[gdal] 03/16: Imported Upstream version 2.1.0~beta1+dfsg

Sebastiaan Couwenberg sebastic at moszumanska.debian.org
Sat Apr 2 16:11:06 UTC 2016


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

sebastic pushed a commit to branch experimental-2.1
in repository gdal.

commit a46ebc9f98dbe3c989275bfe22ee38c663b988d9
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Sat Apr 2 10:43:55 2016 +0200

    Imported Upstream version 2.1.0~beta1+dfsg
---
 COMMITERS                                          |     7 +
 Doxyfile                                           |     6 +-
 GDALmake.opt.in                                    |   152 +-
 GNUmakefile                                        |    38 +-
 HOWTO-RELEASE                                      |    29 +-
 LICENSE.TXT                                        |   116 +
 MIGRATION_GUIDE.TXT                                |    23 +-
 NEWS                                               |  1027 +-
 NEWS.template                                      |   230 +
 PROVENANCE.TXT                                     |    16 +-
 VERSION                                            |     2 +-
 Vagrantfile                                        |     6 +-
 aclocal.m4                                         |     8 +-
 alg/GNUmakefile                                    |    15 +-
 alg/contour.cpp                                    |   327 +-
 alg/delaunay.c                                     |   581 +
 alg/fpolygonize.cpp                                |   820 -
 alg/gdal_alg.h                                     |   301 +-
 alg/gdal_alg_priv.h                                |   100 +-
 alg/gdal_crs.c                                     |   195 +-
 alg/gdal_nrgcrs.c                                  |    56 +-
 alg/gdal_octave.cpp                                |    38 +-
 alg/gdal_rpc.cpp                                   |   983 +-
 alg/gdal_simplesurf.cpp                            |    63 +-
 alg/gdal_simplesurf.h                              |     6 +-
 alg/gdal_tps.cpp                                   |   114 +-
 alg/gdalchecksum.cpp                               |    42 +-
 alg/gdalcutline.cpp                                |    78 +-
 alg/gdaldither.cpp                                 |   136 +-
 alg/gdalgeoloc.cpp                                 |   269 +-
 alg/gdalgrid.cpp                                   |  1139 +-
 alg/gdalgrid.h                                     |    17 +-
 alg/gdalgrid_priv.h                                |    13 +-
 alg/gdalgridavx.cpp                                |    22 +-
 alg/gdalgridsse.cpp                                |     4 +-
 alg/gdalmatching.cpp                               |    79 +-
 alg/gdalmediancut.cpp                              |   285 +-
 alg/gdalpansharpen.cpp                             |  1630 ++
 alg/gdalpansharpen.h                               |   270 +
 alg/gdalproximity.cpp                              |   100 +-
 alg/gdalrasterfpolygonenumerator.cpp               |   250 -
 alg/gdalrasterize.cpp                              |   309 +-
 alg/gdalrasterpolygonenumerator.cpp                |   129 +-
 alg/gdalsievefilter.cpp                            |   208 +-
 alg/gdalsimplewarp.cpp                             |   292 +-
 alg/gdaltransformer.cpp                            |   806 +-
 alg/gdaltransformgeolocs.cpp                       |    10 +-
 alg/gdalwarper.cpp                                 |   360 +-
 alg/gdalwarper.h                                   |   109 +-
 alg/gdalwarpkernel.cpp                             |   934 +-
 alg/gdalwarpkernel_opencl.c                        |   520 +-
 alg/gdalwarpkernel_opencl.h                        |    35 +-
 alg/gdalwarpoperation.cpp                          |   572 +-
 alg/gvgcpfit.h                                     |    10 +-
 alg/internal_qhull_headers.h                       |  1006 +
 alg/libqhull/COPYING.txt                           |    38 +
 alg/libqhull/README.txt                            |   523 +
 alg/libqhull/geom.c                                |  1236 +
 alg/libqhull/geom.h                                |   176 +
 alg/libqhull/geom2.c                               |  2083 ++
 alg/libqhull/global.c                              |  2126 ++
 alg/libqhull/io.c                                  |  4060 +++
 alg/libqhull/io.h                                  |   159 +
 alg/libqhull/libqhull.c                            |  1401 +
 alg/libqhull/libqhull.h                            |  1100 +
 alg/libqhull/mem.c                                 |   545 +
 alg/libqhull/mem.h                                 |   219 +
 alg/libqhull/merge.c                               |  3623 +++
 alg/libqhull/merge.h                               |   178 +
 alg/libqhull/poly.c                                |  1202 +
 alg/libqhull/poly.h                                |   295 +
 alg/libqhull/poly2.c                               |  3156 +++
 alg/libqhull/qhull_a.h                             |   151 +
 alg/libqhull/qset.c                                |  1343 +
 alg/libqhull/qset.h                                |   488 +
 alg/libqhull/random.c                              |   243 +
 alg/libqhull/random.h                              |    34 +
 alg/libqhull/rboxlib.c                             |   793 +
 alg/libqhull/stat.c                                |   714 +
 alg/libqhull/stat.h                                |   541 +
 alg/libqhull/user.c                                |   527 +
 alg/libqhull/user.h                                |   858 +
 alg/libqhull/usermem.c                             |    64 +
 alg/libqhull/userprintf.c                          |    64 +
 alg/libqhull/userprintf_rbox.c                     |    53 +
 alg/llrasterize.cpp                                |    69 +-
 alg/makefile.vc                                    |    35 +-
 alg/polygonize.cpp                                 |   446 +-
 alg/rasterfill.cpp                                 |   228 +-
 alg/thinplatespline.cpp                            |   241 +-
 alg/thinplatespline.h                              |    62 +-
 apps/GNUmakefile                                   |   106 +-
 apps/commonutils.cpp                               |     4 +-
 apps/commonutils.h                                 |    12 +-
 apps/dumpoverviews.cpp                             |    61 +-
 apps/gdal-config.in                                |     9 +-
 apps/gdal_contour.cpp                              |    29 +-
 apps/gdal_grid.cpp                                 |  1149 -
 apps/gdal_grid_bin.cpp                             |   195 +
 apps/gdal_grid_lib.cpp                             |  1320 +
 apps/gdal_rasterize.cpp                            |   995 -
 apps/gdal_rasterize_bin.cpp                        |   180 +
 apps/gdal_rasterize_lib.cpp                        |  1194 +
 apps/gdal_translate.cpp                            |  2015 --
 apps/gdal_translate_bin.cpp                        |   306 +
 apps/gdal_translate_lib.cpp                        |  2207 ++
 apps/gdal_utilities.dox                            |   336 +-
 apps/gdal_utils.h                                  |   214 +
 apps/gdal_utils_priv.h                             |   149 +
 apps/gdaladdo.cpp                                  |    58 +-
 apps/gdalasyncread.cpp                             |    99 +-
 apps/gdalbuildvrt.cpp                              |  1609 --
 apps/gdalbuildvrt_bin.cpp                          |   213 +
 apps/gdalbuildvrt_lib.cpp                          |  1750 ++
 apps/gdaldem.cpp                                   |  2802 --
 apps/gdaldem_bin.cpp                               |   216 +
 apps/gdaldem_lib.cpp                               |  3096 +++
 apps/gdalenhance.cpp                               |    89 +-
 apps/gdalflattenmask.c                             |     2 +-
 apps/gdalinfo.c                                    |  1600 --
 apps/gdalinfo_bin.cpp                              |   241 +
 apps/gdalinfo_lib.cpp                              |  1705 ++
 apps/gdallocationinfo.cpp                          |   162 +-
 apps/gdalmanage.cpp                                |    31 +-
 apps/gdalserver.c                                  |   198 +-
 apps/gdalsrsinfo.cpp                               |   208 +-
 apps/gdaltindex.c                                  |   111 +-
 apps/gdaltorture.cpp                               |    32 +-
 apps/gdaltransform.cpp                             |    88 +-
 apps/gdalwarp.cpp                                  |  2744 --
 apps/gdalwarp_bin.cpp                              |   529 +
 apps/gdalwarp_lib.cpp                              |  2967 +++
 apps/gdalwarpsimple.c                              |    73 +-
 apps/gnm_utilities.dox                             |   140 +
 apps/gnmanalyse.cpp                                |   630 +
 apps/gnmmanage.cpp                                 |   921 +
 apps/makefile.vc                                   |    97 +-
 apps/multireadtest.cpp                             |    32 +-
 apps/nearblack.cpp                                 |   779 -
 apps/nearblack_bin.cpp                             |   164 +
 apps/nearblack_lib.cpp                             |   926 +
 apps/ogr2ogr.cpp                                   |  4121 ---
 apps/ogr2ogr_bin.cpp                               |   403 +
 apps/ogr2ogr_lib.cpp                               |  4599 ++++
 apps/ogr_utilities.dox                             |   156 +-
 apps/ogrdissolve.cpp                               |   321 +-
 apps/ogrinfo.cpp                                   |   210 +-
 apps/ogrlineref.cpp                                |   329 +-
 apps/ogrtindex.cpp                                 |    84 +-
 apps/test_ogrsf.cpp                                |   203 +-
 apps/testepsg.cpp                                  |    53 +-
 apps/testreprojmulti.cpp                           |     8 +-
 bridge/bridge_test.cpp                             |    69 +-
 bridge/gbgetsymbol.cpp                             |    20 +-
 bridge/gdalbridge.cpp                              |   106 +-
 bridge/gdalbridge.h                                |    90 +-
 config.guess                                       |   779 +-
 config.sub                                         |   399 +-
 configure                                          |  3324 ++-
 configure.in                                       |   896 +-
 data/compdcs.csv                                   |     5 +-
 data/coordinate_axis.csv                           |    38 +-
 data/datum_shift.csv                               |  1558 +-
 data/ellipsoid.csv                                 |     2 +-
 data/gcs.csv                                       |    54 +-
 data/gdal_datum.csv                                |    78 +-
 data/gdalvrt.xsd                                   |    59 +-
 data/geoccs.csv                                    |    10 +
 data/netcdf_config.xsd                             |   143 +
 data/nitf_spec.xml                                 |   483 +-
 data/ogrvrt.xsd                                    |    38 +-
 data/osmconf.ini                                   |     2 +-
 data/pcs.csv                                       |   425 +-
 data/projop_wparm.csv                              |   338 +-
 data/ruian_vf_ob_v1.gfs                            |    49 +
 data/ruian_vf_st_v1.gfs                            |    98 +
 data/ruian_vf_v1.gfs                               |    98 +
 data/unit_of_measure.csv                           |   155 +-
 data/vdv452.xml                                    |   367 +
 data/vdv452.xsd                                    |    63 +
 data/vertcs.csv                                    |    10 +-
 dist_docs/README_UNX_BIN.TXT                       |    71 -
 dist_docs/README_WIN_BIN.TXT                       |    86 -
 dist_docs/SETUP_GDAL.BAT                           |    24 -
 dist_docs/burnpath.c                               |   113 -
 dist_docs/install_unx.sh                           |    70 -
 doc/api.dox                                        |     4 +-
 doc/br/gdal_tutorial_br.dox                        |     2 +-
 doc/br/index_br.dox                                |   138 +-
 doc/credits.dox                                    |     6 +-
 doc/download.dox                                   |     4 +-
 doc/gdal_building.dox                              |     4 +-
 doc/gdal_datamodel.dox                             |    24 +-
 doc/gdal_drivertut.dox                             |    20 +-
 doc/gdal_footer.html                               |     2 +-
 doc/gdal_tutorial.dox                              |     8 +-
 doc/index.dox                                      |    66 +-
 doc/ru/Doxyfile                                    |     2 +-
 doc/ru/gdal_datamodel_ru.dox                       |    46 +-
 doc/ru/gdal_tutorial_ru.dox                        |    41 +-
 doc/ru/index_ru.dox                                |   150 +-
 doc/sponsorship.dox                                |    10 +-
 doc/warptut.dox                                    |    12 +-
 doc/wince_port.dox                                 |   340 -
 doxygen_sqlite3.db                                 |   Bin 162816 -> 289792 bytes
 frmts/GNUmakefile                                  |     7 +-
 frmts/aaigrid/aaigriddataset.cpp                   |   626 +-
 frmts/adrg/adrgdataset.cpp                         |   509 +-
 frmts/adrg/srpdataset.cpp                          |   263 +-
 frmts/aigrid/GNUmakefile                           |     2 +-
 frmts/aigrid/aigccitt.c                            |   222 +-
 frmts/aigrid/aigdataset.cpp                        |   300 +-
 frmts/aigrid/aigopen.c                             |   101 +-
 frmts/aigrid/aigrid.h                              |    24 +-
 frmts/aigrid/aigrid_format.html                    |   138 +-
 frmts/aigrid/aitest.c                              |    26 +-
 frmts/aigrid/gridlib.c                             |   350 +-
 frmts/aigrid/makefile.vc                           |     2 +-
 frmts/airsar/airsardataset.cpp                     |   213 +-
 frmts/airsar/frmt_airsar.html                      |    14 +-
 frmts/arg/argdataset.cpp                           |   374 +-
 frmts/blx/blx.c                                    |   523 +-
 frmts/blx/blx.h                                    |    40 +-
 frmts/blx/blxdataset.cpp                           |   227 +-
 frmts/blx/frmt_blx.html                            |     6 +-
 frmts/bmp/bmpdataset.cpp                           |   380 +-
 frmts/bpg/bpgdataset.cpp                           |    42 +-
 frmts/bsb/bsb2raw.c                                |    21 +-
 frmts/bsb/bsb_read.c                               |   248 +-
 frmts/bsb/bsb_read.h                               |    19 +-
 frmts/bsb/bsbdataset.cpp                           |   341 +-
 frmts/cals/GNUmakefile                             |    17 +
 frmts/cals/calsdataset.cpp                         |   616 +
 frmts/cals/frmt_cals.html                          |    70 +
 frmts/cals/makefile.vc                             |    15 +
 frmts/ceos/ceosdataset.cpp                         |    75 +-
 frmts/ceos/ceosopen.c                              |    76 +-
 frmts/ceos/ceosopen.h                              |     8 +-
 frmts/ceos/ceostest.c                              |     8 +-
 frmts/ceos2/ceos.c                                 |    90 +-
 frmts/ceos2/ceos.h                                 |   151 +-
 frmts/ceos2/ceosrecipe.c                           |   485 +-
 frmts/ceos2/ceossar.c                              |    16 +-
 frmts/ceos2/sar_ceosdataset.cpp                    |   865 +-
 frmts/coasp/coasp_dataset.cpp                      |   284 +-
 frmts/cosar/cosar_dataset.cpp                      |   122 +-
 frmts/cosar/frmt_cosar.html                        |     4 +-
 frmts/ctg/ctgdataset.cpp                           |    99 +-
 frmts/dds/ddsdataset.cpp                           |   174 +-
 frmts/dimap/dimapdataset.cpp                       |   376 +-
 frmts/dods/dodsdataset2.cpp                        |   293 +-
 frmts/dods/frmt_dods.html                          |    34 +-
 frmts/dted/dted_api.c                              |   102 +-
 frmts/dted/dted_api.h                              |    26 +-
 frmts/dted/dted_create.c                           |    41 +-
 frmts/dted/dted_ptstream.c                         |    82 +-
 frmts/dted/dted_test.c                             |    12 +-
 frmts/dted/dteddataset.cpp                         |   261 +-
 frmts/dted/frmt_dted.html                          |     6 +-
 frmts/e00grid/e00compr.h                           |    12 +-
 frmts/e00grid/e00griddataset.cpp                   |   189 +-
 frmts/e00grid/e00read.c                            |    52 +-
 frmts/ecw/GNUmakefile                              |     2 +-
 frmts/ecw/ecwcreatecopy.cpp                        |   549 +-
 frmts/ecw/ecwdataset.cpp                           |   789 +-
 frmts/ecw/ecwsdk_headers.h                         |   102 +
 frmts/ecw/frmt_ecw.html                            |    68 +-
 frmts/ecw/frmt_jp2ecw.html                         |    58 +-
 frmts/ecw/gdal_ecw.h                               |   179 +-
 frmts/ecw/jp2userbox.cpp                           |    18 +-
 frmts/elas/elasdataset.cpp                         |   228 +-
 frmts/elas/frmt_elas.html                          |     2 +-
 frmts/envisat/EnvisatFile.c                        |   403 +-
 frmts/envisat/EnvisatFile.h                        |    68 +-
 frmts/envisat/adsrange.cpp                         |   134 +-
 frmts/envisat/adsrange.hpp                         |    53 +-
 frmts/envisat/dumpgeo.c                            |    17 +-
 frmts/envisat/envisat_dump.c                       |    33 +-
 frmts/envisat/envisatdataset.cpp                   |   415 +-
 frmts/envisat/records.c                            |    40 +-
 frmts/envisat/records.h                            |    16 +-
 frmts/envisat/timedelta.hpp                        |    48 +-
 frmts/envisat/unwrapgcps.cpp                       |   214 +-
 frmts/epsilon/epsilondataset.cpp                   |   313 +-
 frmts/epsilon/frmt_epsilon.html                    |    82 +-
 frmts/ers/ersdataset.cpp                           |   338 +-
 frmts/ers/ershdrnode.cpp                           |   131 +-
 frmts/ers/ershdrnode.h                             |     4 +-
 frmts/ers/frmt_ers.html                            |     4 +-
 frmts/fit/fit.cpp                                  |    22 +-
 frmts/fit/fit.h                                    |     8 +-
 frmts/fit/fitdataset.cpp                           |   316 +-
 frmts/fit/gstEndian.h                              |    16 +-
 frmts/fit/gstTypes.h                               |     8 +-
 frmts/fits/fitsdataset.cpp                         |   149 +-
 frmts/formats_list.html                            |    86 +-
 frmts/frmt_various.html                            |   263 +-
 frmts/gdalallregister.cpp                          |   119 +-
 frmts/georaster/frmt_georaster.html                |   562 +-
 frmts/georaster/georaster_dataset.cpp              |   304 +-
 frmts/georaster/georaster_priv.h                   |    45 +-
 frmts/georaster/georaster_rasterband.cpp           |    77 +-
 frmts/georaster/georaster_wrapper.cpp              |   257 +-
 frmts/georaster/oci_wrapper.cpp                    |    42 +-
 frmts/georaster/oci_wrapper.h                      |    12 +-
 frmts/gff/gff_dataset.cpp                          |   113 +-
 frmts/gif/GNUmakefile                              |     2 +-
 frmts/gif/biggifdataset.cpp                        |   129 +-
 frmts/gif/frmt_gif.html                            |     6 +-
 frmts/gif/gifabstractdataset.cpp                   |   140 +-
 frmts/gif/gifabstractdataset.h                     |    13 +-
 frmts/gif/gifdataset.cpp                           |   232 +-
 frmts/gif/giflib/README                            |     5 +-
 frmts/gif/giflib/dgif_lib.c                        |   109 +-
 frmts/gif/giflib/egif_lib.c                        |    70 +-
 frmts/gif/giflib/gif_hash.h                        |     6 +-
 frmts/gif/giflib/gif_lib.h                         |     6 +-
 frmts/gif/giflib/gif_lib_private.h                 |     7 +-
 frmts/gif/giflib/gifalloc.c                        |    33 +-
 frmts/grass/frmt_grass.html                        |     2 +-
 frmts/grass/grass57dataset.cpp                     |   254 +-
 frmts/grass/grassdataset.cpp                       |    93 +-
 frmts/grass/pkg/Makefile.in                        |    10 +-
 frmts/grass/pkg/configure.in                       |     8 +-
 frmts/grib/degrib18/degrib/clock.c                 |   285 +-
 frmts/grib/degrib18/degrib/clock.h                 |     2 +-
 frmts/grib/degrib18/degrib/degrib1.cpp             |    89 +-
 frmts/grib/degrib18/degrib/degrib1.h               |    43 +
 frmts/grib/degrib18/degrib/degrib2.cpp             |    26 +-
 frmts/grib/degrib18/degrib/engribapi.c             |    28 +-
 frmts/grib/degrib18/degrib/filedatasource.cpp      |     6 +-
 frmts/grib/degrib18/degrib/fileendian.cpp          |     2 +-
 frmts/grib/degrib18/degrib/grib1tab.cpp            |    99 +-
 frmts/grib/degrib18/degrib/grib2api.c              |    23 +-
 frmts/grib/degrib18/degrib/inventory.cpp           |    58 +-
 frmts/grib/degrib18/degrib/memendian.c             |     4 +-
 frmts/grib/degrib18/degrib/memorydatasource.cpp    |     2 +-
 frmts/grib/degrib18/degrib/meta.h                  |    10 +-
 frmts/grib/degrib18/degrib/metaname.cpp            |   109 +-
 frmts/grib/degrib18/degrib/metaparse.cpp           |    56 +-
 frmts/grib/degrib18/degrib/metaprint.cpp           |    75 +-
 frmts/grib/degrib18/degrib/myassert.c              |     2 +-
 frmts/grib/degrib18/degrib/myassert.h              |    10 +-
 frmts/grib/degrib18/degrib/myerror.c               |    16 +-
 frmts/grib/degrib18/degrib/myerror.h               |     4 +-
 frmts/grib/degrib18/degrib/myutil.c                |    44 +-
 frmts/grib/degrib18/degrib/scan.c                  |     6 +-
 frmts/grib/degrib18/degrib/tdlpack.cpp             |   271 +-
 frmts/grib/degrib18/degrib/weather.c               |    32 +-
 frmts/grib/degrib18/g2clib-1.0.4/README            |     2 +-
 frmts/grib/degrib18/g2clib-1.0.4/cmplxpack.c       |     2 +-
 frmts/grib/degrib18/g2clib-1.0.4/compack.c         |    12 +-
 frmts/grib/degrib18/g2clib-1.0.4/comunpack.c       |     4 +-
 frmts/grib/degrib18/g2clib-1.0.4/dec_jpeg2000.cpp  |    60 +-
 frmts/grib/degrib18/g2clib-1.0.4/dec_png.c         |     4 +-
 frmts/grib/degrib18/g2clib-1.0.4/drstemplates.c    |    29 +-
 frmts/grib/degrib18/g2clib-1.0.4/drstemplates.h    |    10 +-
 frmts/grib/degrib18/g2clib-1.0.4/g2_addfield.c     |    58 +-
 frmts/grib/degrib18/g2clib-1.0.4/g2_addgrid.c      |    39 +-
 frmts/grib/degrib18/g2clib-1.0.4/g2_addlocal.c     |    30 +-
 frmts/grib/degrib18/g2clib-1.0.4/g2_create.c       |     9 +-
 frmts/grib/degrib18/g2clib-1.0.4/g2_getfld.c       |    10 +-
 frmts/grib/degrib18/g2clib-1.0.4/g2_gribend.c      |    22 +-
 frmts/grib/degrib18/g2clib-1.0.4/g2_info.c         |    29 +-
 frmts/grib/degrib18/g2clib-1.0.4/g2_miss.c         |     2 +-
 frmts/grib/degrib18/g2clib-1.0.4/g2_unpack3.c      |     6 +-
 frmts/grib/degrib18/g2clib-1.0.4/g2_unpack4.c      |     4 +-
 frmts/grib/degrib18/g2clib-1.0.4/g2_unpack7.c      |     5 -
 frmts/grib/degrib18/g2clib-1.0.4/gbits.c           |    40 +-
 frmts/grib/degrib18/g2clib-1.0.4/getdim.c          |     3 -
 frmts/grib/degrib18/g2clib-1.0.4/getpoly.c         |     3 -
 frmts/grib/degrib18/g2clib-1.0.4/grib2.h           |    60 +-
 frmts/grib/degrib18/g2clib-1.0.4/grib2c.doc        |    36 +-
 frmts/grib/degrib18/g2clib-1.0.4/gridtemplates.c   |    31 +-
 frmts/grib/degrib18/g2clib-1.0.4/gridtemplates.h   |    10 +-
 frmts/grib/degrib18/g2clib-1.0.4/jpcpack.c         |     9 +-
 frmts/grib/degrib18/g2clib-1.0.4/jpcunpack.c       |     3 +-
 frmts/grib/degrib18/g2clib-1.0.4/misspack.c        |    12 +-
 frmts/grib/degrib18/g2clib-1.0.4/pack_gp.c         |     9 +-
 frmts/grib/degrib18/g2clib-1.0.4/pdstemplates.c    |    29 +-
 frmts/grib/degrib18/g2clib-1.0.4/pdstemplates.h    |    12 +-
 frmts/grib/degrib18/g2clib-1.0.4/pngpack.c         |     4 +-
 frmts/grib/degrib18/g2clib-1.0.4/pngunpack.c       |     3 +-
 frmts/grib/degrib18/g2clib-1.0.4/reduce.c          |     9 +-
 frmts/grib/degrib18/g2clib-1.0.4/seekgb.c          |     6 +-
 frmts/grib/degrib18/g2clib-1.0.4/simpack.c         |    12 +-
 frmts/grib/degrib18/g2clib-1.0.4/simunpack.c       |     6 +-
 frmts/grib/degrib18/g2clib-1.0.4/specunpack.c      |     2 +-
 frmts/grib/frmt_grib.html                          |    16 +-
 frmts/grib/gribdataset.cpp                         |   484 +-
 frmts/gsg/gs7bgdataset.cpp                         |   161 +-
 frmts/gsg/gsagdataset.cpp                          |   247 +-
 frmts/gsg/gsbgdataset.cpp                          |   118 +-
 frmts/gta/GNUmakefile                              |     2 +-
 frmts/gta/gta_headers.h                            |    40 +
 frmts/gta/gtadataset.cpp                           |   160 +-
 frmts/gtiff/frmt_gtiff.html                        |    71 +-
 frmts/gtiff/geotiff.cpp                            |  6073 +++--
 frmts/gtiff/gt_citation.cpp                        |    90 +-
 frmts/gtiff/gt_citation.h                          |    16 +-
 frmts/gtiff/gt_jpeg_copy.cpp                       |   136 +-
 frmts/gtiff/gt_jpeg_copy.h                         |    11 +-
 frmts/gtiff/gt_overview.cpp                        |   136 +-
 frmts/gtiff/gt_overview.h                          |     8 +-
 frmts/gtiff/gt_wkt_srs.cpp                         |   820 +-
 frmts/gtiff/gt_wkt_srs.h                           |    13 +-
 frmts/gtiff/gt_wkt_srs_for_gdal.h                  |     4 +-
 frmts/gtiff/gtiff.h                                |     5 +-
 frmts/gtiff/libgeotiff/GNUmakefile                 |     4 +-
 frmts/gtiff/libgeotiff/epsg_datum.inc              |     2 +-
 frmts/gtiff/libgeotiff/epsg_units.inc              |     2 +-
 frmts/gtiff/libgeotiff/geo_config.h                |     3 +
 frmts/gtiff/libgeotiff/geo_ctrans.inc              |     6 +-
 frmts/gtiff/libgeotiff/geo_extra.c                 |    29 +-
 frmts/gtiff/libgeotiff/geo_free.c                  |    12 +-
 frmts/gtiff/libgeotiff/geo_get.c                   |    22 +-
 frmts/gtiff/libgeotiff/geo_keyp.h                  |    15 +-
 frmts/gtiff/libgeotiff/geo_names.c                 |    47 +-
 frmts/gtiff/libgeotiff/geo_new.c                   |    62 +-
 frmts/gtiff/libgeotiff/geo_normalize.c             |   500 +-
 frmts/gtiff/libgeotiff/geo_normalize.h             |    20 +-
 frmts/gtiff/libgeotiff/geo_print.c                 |   107 +-
 frmts/gtiff/libgeotiff/geo_set.c                   |    52 +-
 frmts/gtiff/libgeotiff/geo_simpletags.c            |    37 +-
 frmts/gtiff/libgeotiff/geo_simpletags.h            |    16 +-
 frmts/gtiff/libgeotiff/geo_tiffp.c                 |    25 +-
 frmts/gtiff/libgeotiff/geo_tiffp.h                 |    16 +-
 frmts/gtiff/libgeotiff/geo_trans.c                 |    38 +-
 frmts/gtiff/libgeotiff/geo_write.c                 |    63 +-
 frmts/gtiff/libgeotiff/geokeys.h                   |    18 +-
 frmts/gtiff/libgeotiff/geokeys.inc                 |     2 +-
 frmts/gtiff/libgeotiff/geonames.h                  |    71 +-
 frmts/gtiff/libgeotiff/geotiff.h                   |     8 +-
 frmts/gtiff/libgeotiff/geotiff_proj4.c             |   419 +-
 frmts/gtiff/libgeotiff/geotiffio.h                 |    11 +-
 frmts/gtiff/libgeotiff/geovalues.h                 |    13 +-
 frmts/gtiff/libgeotiff/xtiff.c                     |    36 +-
 frmts/gtiff/libgeotiff/xtiffio.h                   |    21 +-
 frmts/gtiff/libtiff/GNUmakefile                    |     2 +-
 frmts/gtiff/libtiff/gdal_libtiff_symbol_rename.h   |     2 +
 frmts/gtiff/libtiff/makefile.vc                    |     6 +-
 frmts/gtiff/libtiff/tif_aux.c                      |    16 +-
 frmts/gtiff/libtiff/tif_close.c                    |    12 +-
 frmts/gtiff/libtiff/tif_codec.c                    |     5 +-
 frmts/gtiff/libtiff/tif_color.c                    |    16 +-
 frmts/gtiff/libtiff/tif_compress.c                 |     6 +-
 frmts/gtiff/libtiff/tif_config.h                   |     2 +-
 frmts/gtiff/libtiff/tif_config.h.wince             |     6 +-
 frmts/gtiff/libtiff/tif_dir.c                      |    95 +-
 frmts/gtiff/libtiff/tif_dirinfo.c                  |    38 +-
 frmts/gtiff/libtiff/tif_dirread.c                  |    77 +-
 frmts/gtiff/libtiff/tif_dirwrite.c                 |    55 +-
 frmts/gtiff/libtiff/tif_dumpmode.c                 |     4 +-
 frmts/gtiff/libtiff/tif_extension.c                |    38 +-
 frmts/gtiff/libtiff/tif_fax3.c                     |    12 +-
 frmts/gtiff/libtiff/tif_fax3.h                     |     6 +-
 frmts/gtiff/libtiff/tif_getimage.c                 |   188 +-
 frmts/gtiff/libtiff/tif_jpeg.c                     |   258 +-
 frmts/gtiff/libtiff/tif_jpeg_12.c                  |     3 +
 frmts/gtiff/libtiff/tif_luv.c                      |    71 +-
 frmts/gtiff/libtiff/tif_lzma.c                     |     6 +-
 frmts/gtiff/libtiff/tif_lzw.c                      |    85 +-
 frmts/gtiff/libtiff/tif_next.c                     |    12 +-
 frmts/gtiff/libtiff/tif_ojpeg.c                    |    52 +-
 frmts/gtiff/libtiff/tif_open.c                     |     8 +-
 frmts/gtiff/libtiff/tif_packbits.c                 |     5 +-
 frmts/gtiff/libtiff/tif_pixarlog.c                 |   106 +-
 frmts/gtiff/libtiff/tif_predict.c                  |   146 +-
 frmts/gtiff/libtiff/tif_print.c                    |    20 +-
 frmts/gtiff/libtiff/tif_read.c                     |    44 +-
 frmts/gtiff/libtiff/tif_strip.c                    |    12 +-
 frmts/gtiff/libtiff/tif_tile.c                     |    29 +-
 frmts/gtiff/libtiff/tif_vsi.c                      |    22 +-
 frmts/gtiff/libtiff/tif_write.c                    |    36 +-
 frmts/gtiff/libtiff/tif_zip.c                      |    14 +-
 frmts/gtiff/libtiff/tiff.h                         |     6 +-
 frmts/gtiff/libtiff/tiffio.h                       |     6 +-
 frmts/gtiff/libtiff/tiffiop.h                      |   105 +-
 frmts/gtiff/libtiff/tiffvers.h                     |     4 +-
 frmts/gtiff/libtiff/uvcode.h                       |     2 +-
 frmts/gtiff/tif_float.c                            |   120 +-
 frmts/gtiff/tifvsi.cpp                             |    37 +-
 frmts/gtiff/tifvsi.h                               |     2 +-
 frmts/gxf/README                                   |     4 +-
 frmts/gxf/gxf_ogcwkt.c                             |   122 +-
 frmts/gxf/gxf_proj4.c                              |   515 +-
 frmts/gxf/gxfdataset.cpp                           |   123 +-
 frmts/gxf/gxfopen.c                                |   164 +-
 frmts/gxf/gxfopen.h                                |    10 +-
 frmts/gxf/makefile.vc                              |     2 -
 frmts/hdf4/frmt_hdf4.html                          |    40 +-
 frmts/hdf4/hdf-eos/EHapi.c                         |   194 +-
 frmts/hdf4/hdf-eos/GDapi.c                         |   342 +-
 frmts/hdf4/hdf-eos/SWapi.c                         |   643 +-
 frmts/hdf4/hdf-eos/ease.h                          |     2 +-
 frmts/hdf4/hdf-eos/gctp_wrap.c                     |    37 +-
 frmts/hdf4/hdf4compat.h                            |     6 +-
 frmts/hdf4/hdf4dataset.cpp                         |   764 +-
 frmts/hdf4/hdf4dataset.h                           |    21 +-
 frmts/hdf4/hdf4imagedataset.cpp                    |  1179 +-
 frmts/hdf5/bagdataset.cpp                          |   378 +-
 frmts/hdf5/frmt_bag.html                           |    10 +-
 frmts/hdf5/frmt_hdf5.html                          |    39 +-
 frmts/hdf5/gh5_convenience.cpp                     |    51 +-
 frmts/hdf5/gh5_convenience.h                       |    17 +-
 frmts/hdf5/hdf5dataset.cpp                         |   605 +-
 frmts/hdf5/hdf5dataset.h                           |    20 +-
 frmts/hdf5/hdf5imagedataset.cpp                    |   495 +-
 frmts/hdf5/iso19115_srs.cpp                        |    29 +-
 frmts/hf2/hf2dataset.cpp                           |   274 +-
 frmts/hfa/frmt_hfa.html                            |    24 +-
 frmts/hfa/hfa.h                                    |   115 +-
 frmts/hfa/hfa_overviews.cpp                        |    35 +-
 frmts/hfa/hfa_p.h                                  |   166 +-
 frmts/hfa/hfaband.cpp                              |   851 +-
 frmts/hfa/hfacompress.cpp                          |   149 +-
 frmts/hfa/hfadataset.cpp                           |  1413 +-
 frmts/hfa/hfadictionary.cpp                        |    76 +-
 frmts/hfa/hfaentry.cpp                             |   303 +-
 frmts/hfa/hfafield.cpp                             |   367 +-
 frmts/hfa/hfaopen.cpp                              |   817 +-
 frmts/hfa/hfatest.cpp                              |    94 +-
 frmts/hfa/hfatype.cpp                              |   164 +-
 frmts/hfa/makefile.vc                              |     2 +-
 frmts/idrisi/IdrisiDataset.cpp                     |   939 +-
 frmts/idrisi/frmt_Idrisi.html                      |    42 +-
 frmts/idrisi/idrisi.h                              |     8 +-
 frmts/idrisi/rdc.txt                               |     6 +-
 frmts/idrisi/rst.txt                               |     2 +-
 frmts/ilwis/frmt_ilwis.html                        |     7 +-
 frmts/ilwis/ilwiscoordinatesystem.cpp              |   439 +-
 frmts/ilwis/ilwisdataset.cpp                       |   614 +-
 frmts/ilwis/ilwisdataset.h                         |    39 +-
 frmts/ilwis/makefile.vc                            |     2 -
 frmts/ingr/IngrTypes.cpp                           |   442 +-
 frmts/ingr/IngrTypes.h                             |   263 +-
 frmts/ingr/IntergraphBand.cpp                      |   572 +-
 frmts/ingr/IntergraphBand.h                        |    20 +-
 frmts/ingr/IntergraphDataset.cpp                   |   371 +-
 frmts/ingr/IntergraphDataset.h                     |     9 +-
 frmts/ingr/JpegHelper.cpp                          |    59 +-
 frmts/ingr/JpegHelper.h                            |     8 +-
 frmts/ingr/frmt_intergraphraster.html              |   463 +-
 frmts/iris/irisdataset.cpp                         |   329 +-
 frmts/iso8211/8211createfromxml.cpp                |    42 +-
 frmts/iso8211/8211dump.cpp                         |    83 +-
 frmts/iso8211/Makefile.in                          |    24 +-
 frmts/iso8211/ddffield.cpp                         |    69 +-
 frmts/iso8211/ddffielddefn.cpp                     |   222 +-
 frmts/iso8211/ddfmodule.cpp                        |   161 +-
 frmts/iso8211/ddfrecord.cpp                        |   475 +-
 frmts/iso8211/ddfsubfielddefn.cpp                  |   191 +-
 frmts/iso8211/ddfutils.cpp                         |     8 +-
 frmts/iso8211/intro.dox                            |     6 +-
 frmts/iso8211/iso8211.h                            |   152 +-
 frmts/iso8211/mkcatalog.cpp                        |    17 +-
 frmts/iso8211/timetest.cpp                         |    17 +-
 frmts/jaxapalsar/frmt_palsar.html                  |     2 +-
 frmts/jaxapalsar/jaxapalsardataset.cpp             |   175 +-
 frmts/jdem/jdemdataset.cpp                         |   145 +-
 frmts/jdem/makefile.vc                             |     2 -
 frmts/jp2kak/GNUmakefile                           |     2 +-
 frmts/jp2kak/frmt_jp2kak.html                      |    34 +-
 frmts/jp2kak/jp2kak.lst                            |     7 +
 frmts/jp2kak/jp2kak_headers.h                      |    68 +
 frmts/jp2kak/jp2kakdataset.cpp                     |  1349 +-
 frmts/jp2kak/makefile.vc                           |     5 +
 frmts/jp2kak/subfile_source.h                      |    49 +-
 frmts/jp2kak/vsil_target.h                         |     7 +-
 frmts/jpeg/GNUmakefile                             |     8 +-
 frmts/jpeg/frmt_jpeg.html                          |    26 +-
 frmts/jpeg/jpgdataset.cpp                          |  1613 +-
 frmts/jpeg/jpgdataset_12.cpp                       |    27 +-
 frmts/jpeg/libjpeg/jccoefct.c                      |     4 +-
 frmts/jpeg/libjpeg/jcmarker.c                      |    20 +-
 frmts/jpeg/libjpeg/jcparam.c                       |     4 +-
 frmts/jpeg/libjpeg/jcsample.c                      |     2 +-
 frmts/jpeg/libjpeg/jdhuff.c                        |     5 +-
 frmts/jpeg/libjpeg/jdinput.c                       |     2 +-
 frmts/jpeg/libjpeg/jdmarker.c                      |    43 +-
 frmts/jpeg/libjpeg/jdmaster.c                      |     2 +-
 frmts/jpeg/libjpeg/jdphuff.c                       |     5 +-
 frmts/jpeg/libjpeg/jdsample.c                      |     2 +-
 frmts/jpeg/libjpeg/jerror.c                        |     3 +
 frmts/jpeg/libjpeg/jmemansi.c                      |     1 +
 frmts/jpeg/libjpeg/jmemmgr.c                       |    11 +-
 frmts/jpeg/libjpeg/jmorecfg.h                      |     2 +-
 frmts/jpeg/libjpeg/jpeglib.h                       |     9 +-
 frmts/jpeg/libjpeg/jquant1.c                       |     2 +-
 frmts/jpeg/libjpeg/jquant2.c                       |     8 +-
 frmts/jpeg/libjpeg12/jmorecfg.h.12                 |    20 +-
 frmts/jpeg/makefile.vc                             |     2 +-
 frmts/jpeg/vsidataio.cpp                           |    27 +-
 frmts/jpeg/vsidataio.h                             |     8 +-
 frmts/jpeg/vsidataio_12.cpp                        |    43 +
 frmts/jpeg2000/frmt_jpeg2000.html                  |    10 +-
 frmts/jpeg2000/jpeg2000_vsil_io.cpp                |    45 +-
 frmts/jpeg2000/jpeg2000_vsil_io.h                  |     2 +-
 frmts/jpeg2000/jpeg2000dataset.cpp                 |   266 +-
 frmts/jpegls/jpeglsdataset.cpp                     |    96 +-
 frmts/jpipkak/GNUmakefile                          |     8 +-
 frmts/jpipkak/frmt_jpipkak.html                    |   505 +-
 frmts/jpipkak/jpipkak_headers.h                    |    42 +
 frmts/jpipkak/jpipkakdataset.cpp                   |   456 +-
 frmts/jpipkak/jpipkakdataset.h                     |    63 +-
 frmts/kea/GNUmakefile                              |     2 +-
 frmts/kea/frmt_kea.html                            |     2 +-
 frmts/kea/keaband.cpp                              |   130 +-
 frmts/kea/keaband.h                                |    34 +-
 frmts/kea/keacopy.cpp                              |    93 +-
 frmts/kea/keacopy.h                                |    34 +-
 frmts/kea/keadataset.cpp                           |   139 +-
 frmts/kea/keadataset.h                             |    44 +-
 frmts/kea/keadriver.cpp                            |   125 +-
 frmts/kea/keamaskband.cpp                          |    36 +-
 frmts/kea/keamaskband.h                            |    34 +-
 frmts/kea/keaoverview.cpp                          |    40 +-
 frmts/kea/keaoverview.h                            |    35 +-
 frmts/kea/kearat.cpp                               |   114 +-
 frmts/kea/kearat.h                                 |    38 +-
 frmts/kea/libkea_headers.h                         |    57 +
 frmts/kmlsuperoverlay/kmlsuperoverlaydataset.cpp   |   321 +-
 frmts/kmlsuperoverlay/kmlsuperoverlaydataset.h     |    11 +-
 frmts/l1b/frmt_l1b.html                            |    11 +-
 frmts/l1b/l1bdataset.cpp                           |   527 +-
 frmts/leveller/frmt_leveller.html                  |    37 +-
 frmts/leveller/levellerdataset.cpp                 |   729 +-
 frmts/makefile.vc                                  |    11 +-
 frmts/map/GNUmakefile                              |     2 -
 frmts/map/mapdataset.cpp                           |   178 +-
 frmts/mbtiles/GNUmakefile                          |     4 +-
 frmts/mbtiles/frmt_mbtiles.html                    |   372 +-
 frmts/mbtiles/makefile.vc                          |     2 +-
 frmts/mbtiles/mbtilesdataset.cpp                   |  1989 +-
 frmts/mem/frmt_mem.html                            |     4 +-
 frmts/mem/memdataset.cpp                           |   626 +-
 frmts/mem/memdataset.h                             |    43 +-
 frmts/mrf/GNUmakefile                              |    67 +
 frmts/mrf/JPEG12_band.cpp                          |    26 +
 frmts/mrf/JPEG_band.cpp                            |   371 +
 frmts/mrf/LERC_band.cpp                            |   301 +
 frmts/mrf/PNG_band.cpp                             |   372 +
 frmts/mrf/README                                   |    94 +
 frmts/mrf/Raw_band.cpp                             |    65 +
 frmts/mrf/Tif_band.cpp                             |   207 +
 frmts/mrf/frmt_marfa.html                          |    49 +
 frmts/mrf/libLERC/BitMask.cpp                      |   158 +
 frmts/mrf/libLERC/BitMask.h                        |    70 +
 frmts/mrf/libLERC/BitMask2.cpp                     |   125 +
 frmts/mrf/libLERC/BitMask2.h                       |    72 +
 frmts/mrf/libLERC/BitStuffer.cpp                   |   313 +
 frmts/mrf/libLERC/BitStuffer.h                     |    59 +
 frmts/mrf/libLERC/BitStuffer2.cpp                  |   360 +
 frmts/mrf/libLERC/BitStuffer2.h                    |   143 +
 frmts/mrf/libLERC/CntZImage.cpp                    |  1251 +
 frmts/mrf/libLERC/CntZImage.h                      |   168 +
 frmts/mrf/libLERC/Defines.h                        |    87 +
 frmts/mrf/libLERC/GNUmakefile                      |    28 +
 frmts/mrf/libLERC/Huffman.cpp                      |   550 +
 frmts/mrf/libLERC/Huffman.h                        |   203 +
 frmts/mrf/libLERC/Image.h                          |    88 +
 frmts/mrf/libLERC/LICENSE.TXT                      |   101 +
 frmts/mrf/libLERC/Lerc2.cpp                        |   309 +
 frmts/mrf/libLERC/Lerc2.h                          |  1472 +
 frmts/mrf/libLERC/NOTICE.TXT                       |    23 +
 frmts/mrf/libLERC/RLE.cpp                          |   326 +
 frmts/mrf/libLERC/RLE.h                            |    72 +
 frmts/mrf/libLERC/TImage.hpp                       |   198 +
 frmts/mrf/libLERC/makefile.vc                      |    27 +
 frmts/mrf/makefile.vc                              |    98 +
 frmts/mrf/marfa.h                                  |   716 +
 frmts/mrf/marfa_dataset.cpp                        |  1983 ++
 frmts/mrf/mrf_band.cpp                             |   989 +
 frmts/mrf/mrf_overview.cpp                         |   454 +
 frmts/mrf/mrf_util.cpp                             |   635 +
 frmts/mrsid/frmt_jp2mrsid.html                     |     4 +-
 frmts/mrsid/frmt_mrsid.html                        |     4 +-
 frmts/mrsid/mrsiddataset.cpp                       |   499 +-
 frmts/mrsid/mrsidstream.cpp                        |    19 +-
 frmts/mrsid/mrsidstream.h                          |    14 +-
 frmts/mrsid_lidar/frmt_mrsid_lidar.html            |     4 +-
 .../frmt_mrsid_lidar_view_point_cloud.html         |   206 +-
 frmts/mrsid_lidar/gdal_MG4Lidar.cpp                |   172 +-
 frmts/mrsid_lidar/mg4lidar_headers.h               |    43 +
 frmts/msg/frmt_msg.html                            |    12 +-
 frmts/msg/msgcommand.cpp                           |    17 +-
 frmts/msg/msgcommand.h                             |     5 +-
 frmts/msg/msgdataset.cpp                           |   117 +-
 frmts/msg/msgdataset.h                             |     6 +-
 frmts/msg/prologue.cpp                             |    20 +-
 frmts/msg/prologue.h                               |     4 +-
 frmts/msg/reflectancecalculator.cpp                |    12 +-
 frmts/msg/reflectancecalculator.h                  |     4 +-
 frmts/msg/xritheaderparser.cpp                     |    12 +-
 frmts/msgn/frmt_msgn.html                          |     2 +-
 frmts/msgn/makefile.vc                             |     2 +-
 frmts/msgn/msg_basic_types.cpp                     |    48 +-
 frmts/msgn/msg_basic_types.h                       |    34 +-
 frmts/msgn/msg_reader_core.cpp                     |   165 +-
 frmts/msgn/msgndataset.cpp                         |   117 +-
 frmts/netcdf/GNUmakefile                           |     2 +-
 frmts/netcdf/frmt_netcdf.html                      |   103 +-
 frmts/netcdf/frmt_netcdf_vector.html               |   293 +
 frmts/netcdf/gmtdataset.cpp                        |   323 +-
 frmts/netcdf/makefile.vc                           |     2 +-
 frmts/netcdf/netcdfdataset.cpp                     |  6804 +++--
 frmts/netcdf/netcdfdataset.h                       |   539 +-
 frmts/netcdf/netcdflayer.cpp                       |  2359 ++
 frmts/netcdf/netcdfwriterconfig.cpp                |   194 +
 frmts/ngsgeoid/ngsgeoiddataset.cpp                 |    96 +-
 frmts/nitf/ecrgtocdataset.cpp                      |   288 +-
 frmts/nitf/frmt_nitf.html                          |    45 +-
 frmts/nitf/frmt_nitf_advanced.html                 |    61 +-
 frmts/nitf/mgrs.c                                  |   234 +-
 frmts/nitf/mgrs.h                                  |    51 +-
 frmts/nitf/nitf_gcprpc.cpp                         |    22 +-
 frmts/nitf/nitfaridpcm.cpp                         |   160 +-
 frmts/nitf/nitfbilevel.cpp                         |    29 +-
 frmts/nitf/nitfdataset.cpp                         |  2114 +-
 frmts/nitf/nitfdataset.h                           |    37 +-
 frmts/nitf/nitfdes.c                               |    90 +-
 frmts/nitf/nitfdump.c                              |   135 +-
 frmts/nitf/nitffile.c                              |   363 +-
 frmts/nitf/nitfimage.c                             |   916 +-
 frmts/nitf/nitflib.h                               |    41 +-
 frmts/nitf/nitfrasterband.cpp                      |   322 +-
 frmts/nitf/nitfwritejpeg.cpp                       |    80 +-
 frmts/nitf/nitfwritejpeg_12.cpp                    |     1 +
 frmts/nitf/rpftocdataset.cpp                       |   515 +-
 frmts/nitf/rpftocfile.cpp                          |   360 +-
 frmts/nitf/rpftoclib.h                             |    17 +-
 frmts/northwood/grcdataset.cpp                     |   141 +-
 frmts/northwood/grddataset.cpp                     |   172 +-
 frmts/northwood/northwood.cpp                      |   237 +-
 frmts/northwood/northwood.h                        |    13 +-
 frmts/ogdi/frmt_ogdi.html                          |    18 +-
 frmts/ogdi/ogdidataset.cpp                         |   236 +-
 frmts/openjpeg/frmt_jp2openjpeg.html               |    16 +-
 frmts/openjpeg/openjpegdataset.cpp                 |   544 +-
 frmts/ozi/ozidataset.cpp                           |   186 +-
 frmts/pcidsk/GNUmakefile                           |     6 +-
 frmts/pcidsk/frmt_pcidsk.html                      |    10 +-
 frmts/pcidsk/gdal_edb.cpp                          |    69 +-
 frmts/pcidsk/gdal_pcidsk.h                         |   221 -
 frmts/pcidsk/ogrpcidsklayer.cpp                    |   245 +-
 frmts/pcidsk/pcidskdataset.cpp                     |  1644 --
 frmts/pcidsk/pcidskdataset2.cpp                    |   948 +-
 frmts/pcidsk/pcidskdataset2.h                      |    28 +-
 frmts/pcidsk/pcidsktiledrasterband.cpp             |   365 -
 frmts/pcidsk/sdk/Doxyfile                          |     4 +-
 .../pcidsk/sdk/channel/cbandinterleavedchannel.cpp |    48 +-
 frmts/pcidsk/sdk/channel/cbandinterleavedchannel.h |     6 +-
 frmts/pcidsk/sdk/channel/cexternalchannel.cpp      |   100 +-
 frmts/pcidsk/sdk/channel/cexternalchannel.h        |     6 +-
 frmts/pcidsk/sdk/channel/cpcidskchannel.cpp        |    47 +-
 frmts/pcidsk/sdk/channel/cpcidskchannel.h          |     6 +-
 .../sdk/channel/cpixelinterleavedchannel.cpp       |    32 +-
 .../pcidsk/sdk/channel/cpixelinterleavedchannel.h  |     6 +-
 frmts/pcidsk/sdk/channel/ctiledchannel.cpp         |    71 +-
 frmts/pcidsk/sdk/channel/ctiledchannel.h           |     6 +-
 frmts/pcidsk/sdk/core/clinksegment.cpp             |    14 +-
 frmts/pcidsk/sdk/core/clinksegment.h               |     6 +-
 frmts/pcidsk/sdk/core/cpcidskfile.cpp              |   119 +-
 frmts/pcidsk/sdk/core/cpcidskfile.h                |     6 +-
 frmts/pcidsk/sdk/core/libjpeg_io.cpp               |    10 +-
 frmts/pcidsk/sdk/core/metadataset.h                |     6 +-
 frmts/pcidsk/sdk/core/metadataset_p.cpp            |    18 +-
 frmts/pcidsk/sdk/core/mutexholder.h                |    10 +-
 frmts/pcidsk/sdk/core/pcidsk_pubutils.cpp          |     8 +-
 frmts/pcidsk/sdk/core/pcidsk_utils.cpp             |    70 +-
 frmts/pcidsk/sdk/core/pcidsk_utils.h               |    16 +-
 frmts/pcidsk/sdk/core/pcidskbuffer.cpp             |    28 +-
 frmts/pcidsk/sdk/core/pcidskcreate.cpp             |    40 +-
 frmts/pcidsk/sdk/core/pcidskexception.cpp          |    28 +-
 frmts/pcidsk/sdk/core/pcidskopen.cpp               |     2 +-
 frmts/pcidsk/sdk/core/protectedfile.h              |     6 +-
 frmts/pcidsk/sdk/core/sysvirtualfile.cpp           |    58 +-
 frmts/pcidsk/sdk/core/sysvirtualfile.h             |     6 +-
 frmts/pcidsk/sdk/pcidsk_ads40.h                    |     6 +-
 frmts/pcidsk/sdk/pcidsk_airphoto.h                 |     6 +-
 frmts/pcidsk/sdk/pcidsk_array.h                    |     6 +-
 frmts/pcidsk/sdk/pcidsk_binary.h                   |     6 +-
 frmts/pcidsk/sdk/pcidsk_buffer.h                   |     6 +-
 frmts/pcidsk/sdk/pcidsk_channel.h                  |     6 +-
 frmts/pcidsk/sdk/pcidsk_config.h                   |    18 +-
 frmts/pcidsk/sdk/pcidsk_edb.h                      |     6 +-
 frmts/pcidsk/sdk/pcidsk_ephemeris.h                |     6 +-
 frmts/pcidsk/sdk/pcidsk_exception.h                |    16 +-
 frmts/pcidsk/sdk/pcidsk_file.h                     |     6 +-
 frmts/pcidsk/sdk/pcidsk_gcp.h                      |     6 +-
 frmts/pcidsk/sdk/pcidsk_gcpsegment.h               |     6 +-
 frmts/pcidsk/sdk/pcidsk_georef.h                   |     8 +-
 frmts/pcidsk/sdk/pcidsk_interfaces.h               |     6 +-
 frmts/pcidsk/sdk/pcidsk_io.h                       |     6 +-
 frmts/pcidsk/sdk/pcidsk_mutex.h                    |     6 +-
 frmts/pcidsk/sdk/pcidsk_pct.h                      |     6 +-
 frmts/pcidsk/sdk/pcidsk_poly.h                     |    10 +-
 frmts/pcidsk/sdk/pcidsk_rpc.h                      |     6 +-
 frmts/pcidsk/sdk/pcidsk_segment.h                  |     6 +-
 frmts/pcidsk/sdk/pcidsk_shape.h                    |    12 +-
 frmts/pcidsk/sdk/pcidsk_tex.h                      |     6 +-
 frmts/pcidsk/sdk/pcidsk_toutin.h                   |     6 +-
 frmts/pcidsk/sdk/pcidsk_types.h                    |     6 +-
 frmts/pcidsk/sdk/pcidsk_vectorsegment.h            |     8 +-
 frmts/pcidsk/sdk/segment/cpcidsk_array.cpp         |    28 +-
 frmts/pcidsk/sdk/segment/cpcidsk_array.h           |     6 +-
 frmts/pcidsk/sdk/segment/cpcidsk_tex.cpp           |     4 +-
 frmts/pcidsk/sdk/segment/cpcidsk_tex.h             |     6 +-
 frmts/pcidsk/sdk/segment/cpcidskads40model.cpp     |    14 +-
 frmts/pcidsk/sdk/segment/cpcidskads40model.h       |     6 +-
 frmts/pcidsk/sdk/segment/cpcidskapmodel.cpp        |    29 +-
 frmts/pcidsk/sdk/segment/cpcidskapmodel.h          |     6 +-
 frmts/pcidsk/sdk/segment/cpcidskbinarysegment.cpp  |    21 +-
 frmts/pcidsk/sdk/segment/cpcidskbinarysegment.h    |     6 +-
 frmts/pcidsk/sdk/segment/cpcidskbitmap.cpp         |    32 +-
 frmts/pcidsk/sdk/segment/cpcidskbitmap.h           |     6 +-
 .../pcidsk/sdk/segment/cpcidskephemerissegment.cpp |   331 +-
 frmts/pcidsk/sdk/segment/cpcidskephemerissegment.h |     6 +-
 frmts/pcidsk/sdk/segment/cpcidskgcp2segment.cpp    |    24 +-
 frmts/pcidsk/sdk/segment/cpcidskgcp2segment.h      |     6 +-
 frmts/pcidsk/sdk/segment/cpcidskgeoref.cpp         |   376 +-
 frmts/pcidsk/sdk/segment/cpcidskgeoref.h           |     6 +-
 frmts/pcidsk/sdk/segment/cpcidskpct.cpp            |     4 +-
 frmts/pcidsk/sdk/segment/cpcidskpct.h              |     4 +-
 frmts/pcidsk/sdk/segment/cpcidskpolymodel.h        |     6 +-
 frmts/pcidsk/sdk/segment/cpcidskrpcmodel.cpp       |    57 +-
 frmts/pcidsk/sdk/segment/cpcidskrpcmodel.h         |     6 +-
 frmts/pcidsk/sdk/segment/cpcidsksegment.cpp        |    14 +-
 frmts/pcidsk/sdk/segment/cpcidsksegment.h          |     6 +-
 frmts/pcidsk/sdk/segment/cpcidsktoutinmodel.cpp    |   264 +-
 frmts/pcidsk/sdk/segment/cpcidsktoutinmodel.h      |     8 +-
 frmts/pcidsk/sdk/segment/cpcidskvectorsegment.cpp  |   113 +-
 frmts/pcidsk/sdk/segment/cpcidskvectorsegment.h    |     4 +-
 .../cpcidskvectorsegment_consistencycheck.cpp      |    17 +-
 frmts/pcidsk/sdk/segment/metadatasegment.h         |     6 +-
 frmts/pcidsk/sdk/segment/metadatasegment_p.cpp     |    16 +-
 frmts/pcidsk/sdk/segment/orbitstructures.h         |   145 +-
 frmts/pcidsk/sdk/segment/pcidsksegmentbuilder.h    |     8 +-
 frmts/pcidsk/sdk/segment/sysblockmap.cpp           |    40 +-
 frmts/pcidsk/sdk/segment/sysblockmap.h             |     6 +-
 frmts/pcidsk/sdk/segment/toutinstructures.h        |    45 +-
 frmts/pcidsk/sdk/segment/vecsegdataindex.cpp       |    25 +-
 frmts/pcidsk/sdk/segment/vecsegdataindex.h         |     6 +-
 frmts/pcidsk/sdk/segment/vecsegheader.cpp          |    23 +-
 frmts/pcidsk/sdk/segment/vecsegheader.h            |     4 +-
 frmts/pcidsk/vsi_pcidsk_io.cpp                     |    53 +-
 frmts/pcraster/libcsf/_gsomece.c                   |     3 +-
 frmts/pcraster/libcsf/attrsize.c                   |     1 +
 frmts/pcraster/libcsf/create2.c                    |     4 +-
 frmts/pcraster/libcsf/csfsup.c                     |    12 +-
 frmts/pcraster/libcsf/csftypes.h                   |     2 +-
 frmts/pcraster/libcsf/delattr.c                    |     2 +-
 frmts/pcraster/libcsf/getattr.c                    |     4 +-
 frmts/pcraster/libcsf/kernlcsf.c                   |     5 +-
 frmts/pcraster/libcsf/legend.c                     |     5 +-
 frmts/pcraster/libcsf/mclose.c                     |    11 +-
 frmts/pcraster/libcsf/mopen.c                      |     7 +-
 frmts/pcraster/libcsf/moreattr.c                   |    24 +-
 frmts/pcraster/libcsf/mperror.c                    |     4 +-
 frmts/pcraster/libcsf/pcrtypes.h                   |    20 +-
 frmts/pcraster/libcsf/putallmv.c                   |     2 +-
 frmts/pcraster/libcsf/putattr.c                    |    30 +-
 frmts/pcraster/libcsf/putsomec.c                   |     3 +-
 frmts/pcraster/libcsf/rattrblk.c                   |     3 +-
 frmts/pcraster/libcsf/rextend.c                    |    16 +-
 frmts/pcraster/libcsf/ruseas.c                     |    18 +-
 frmts/pcraster/libcsf/setangle.c                   |     4 +-
 frmts/pcraster/libcsf/setmv.c                      |     3 +-
 frmts/pcraster/libcsf/strconst.c                   |     6 +-
 frmts/pcraster/libcsf/trackmm.c                    |     2 +-
 frmts/pcraster/pcrasterdataset.cpp                 |   137 +-
 frmts/pcraster/pcrasterdataset.h                   |    34 +-
 frmts/pcraster/pcrastermisc.cpp                    |    60 +-
 frmts/pcraster/pcrasterrasterband.cpp              |   116 +-
 frmts/pcraster/pcrasterrasterband.h                |    49 +-
 frmts/pcraster/pcrasterutil.cpp                    |    43 +-
 frmts/pcraster/pcrasterutil.h                      |    34 +-
 frmts/pdf/GNUmakefile                              |    23 +-
 frmts/pdf/frmt_pdf.html                            |   142 +-
 frmts/pdf/gdal_pdf.h                               |   155 +-
 frmts/pdf/makefile.vc                              |    10 +-
 frmts/pdf/ogrpdflayer.cpp                          |    12 +-
 frmts/pdf/pdfcreatecopy.cpp                        |   118 +-
 frmts/pdf/pdfcreatecopy.h                          |     6 +-
 frmts/pdf/pdfdataset.cpp                           |  2318 +-
 frmts/pdf/pdfio.cpp                                |    20 +-
 frmts/pdf/pdfio.h                                  |    10 +-
 frmts/pdf/pdfobject.cpp                            |   729 +-
 frmts/pdf/pdfobject.h                              |    90 +-
 frmts/pdf/pdfreadvectors.cpp                       |    60 +-
 frmts/pdf/pdfsdk_headers.h                         |   129 +
 frmts/pdf/pdfwritabledataset.cpp                   |     8 +-
 frmts/pds/frmt_isis2.html                          |     4 +-
 frmts/pds/frmt_isis3.html                          |     3 +-
 frmts/pds/frmt_pds.html                            |    10 +-
 frmts/pds/isis2dataset.cpp                         |   534 +-
 frmts/pds/isis3dataset.cpp                         |   482 +-
 frmts/pds/nasakeywordhandler.cpp                   |   137 +-
 frmts/pds/pdsdataset.cpp                           |   549 +-
 frmts/pds/vicardataset.cpp                         |   448 +-
 frmts/pds/vicarkeywordhandler.cpp                  |   174 +-
 frmts/pds/vicarkeywordhandler.h                    |    12 +-
 frmts/pgchip/GNUmakefile                           |    24 -
 frmts/pgchip/INSTALL                               |    37 -
 frmts/pgchip/README                                |    29 -
 frmts/pgchip/makefile.vc                           |    15 -
 frmts/pgchip/pgchip.h                              |   119 -
 frmts/pgchip/pgchipdataset.cpp                     |   995 -
 frmts/pgchip/pgchiprasterband.cpp                  |   191 -
 frmts/pgchip/pgchiputilities.cpp                   |   290 -
 frmts/pgchip/todo                                  |     9 -
 frmts/plmosaic/frmt_plmosaic.html                  |    10 +-
 frmts/plmosaic/plmosaicdataset.cpp                 |   362 +-
 frmts/png/GNUmakefile                              |     6 +-
 frmts/png/libpng/LICENSE                           |    53 +-
 frmts/png/libpng/README                            |     2 +-
 frmts/png/libpng/makefile.vc                       |     4 +-
 frmts/png/libpng/png.c                             |    32 +-
 frmts/png/libpng/png.h                             |   512 +-
 frmts/png/libpng/pngconf.h                         |    20 +-
 frmts/png/libpng/pngerror.c                        |     2 +-
 frmts/png/libpng/pnggccrd.c                        |     2 +-
 frmts/png/libpng/pngget.c                          |    13 +-
 frmts/png/libpng/pngmem.c                          |     6 +-
 frmts/png/libpng/pngpread.c                        |    11 +-
 frmts/png/libpng/pngread.c                         |     8 +-
 frmts/png/libpng/pngrio.c                          |     2 +-
 frmts/png/libpng/pngrtran.c                        |    38 +-
 frmts/png/libpng/pngrutil.c                        |    94 +-
 frmts/png/libpng/pngset.c                          |   165 +-
 frmts/png/libpng/pngtrans.c                        |     2 +-
 frmts/png/libpng/pngvcrd.c                         |     1 +
 frmts/png/libpng/pngwio.c                          |     2 +-
 frmts/png/libpng/pngwrite.c                        |   145 +-
 frmts/png/libpng/pngwtran.c                        |     2 +-
 frmts/png/libpng/pngwutil.c                        |   471 +-
 frmts/png/pngdataset.cpp                           |   910 +-
 frmts/postgisraster/postgisraster.h                |    73 +-
 frmts/postgisraster/postgisrasterdataset.cpp       |  1403 +-
 frmts/postgisraster/postgisrasterdriver.cpp        |    19 +-
 frmts/postgisraster/postgisrasterrasterband.cpp    |   418 +-
 frmts/postgisraster/postgisrastertiledataset.cpp   |    34 +-
 .../postgisraster/postgisrastertilerasterband.cpp  |    87 +-
 frmts/postgisraster/postgisrastertools.cpp         |    56 +-
 frmts/r/frmt_r.html                                |     8 +-
 frmts/r/rcreatecopy.cpp                            |    65 +-
 frmts/r/rdataset.cpp                               |   164 +-
 frmts/rasdaman/frmt_rasdaman.html                  |    18 +-
 frmts/rasdaman/makefile.vc                         |     2 -
 frmts/rasdaman/rasdamandataset.cpp                 |    99 +-
 frmts/rasdaman/rasdamandataset.h                   |    20 +-
 frmts/rasterlite/frmt_rasterlite.html              |   426 +-
 frmts/rasterlite/rasterlitecreatecopy.cpp          |   247 +-
 frmts/rasterlite/rasterlitedataset.cpp             |   691 +-
 frmts/rasterlite/rasterlitedataset.h               |    30 +-
 frmts/rasterlite/rasterliteoverviews.cpp           |   413 +-
 frmts/raw/GNUmakefile                              |     2 +-
 frmts/raw/ace2dataset.cpp                          |    84 +-
 frmts/raw/atlsci_spheroid.cpp                      |    60 +-
 frmts/raw/atlsci_spheroid.h                        |    14 +-
 frmts/raw/btdataset.cpp                            |   236 +-
 frmts/raw/cpgdataset.cpp                           |   689 +-
 frmts/raw/ctable2dataset.cpp                       |   172 +-
 frmts/raw/dipxdataset.cpp                          |   162 +-
 frmts/raw/doq1dataset.cpp                          |   163 +-
 frmts/raw/doq2dataset.cpp                          |   172 +-
 frmts/raw/ehdrdataset.cpp                          |  1140 +-
 frmts/raw/eirdataset.cpp                           |   241 +-
 frmts/raw/envidataset.cpp                          |  1739 +-
 frmts/raw/fastdataset.cpp                          |   294 +-
 frmts/raw/frmt_fast.html                           |     6 +-
 frmts/raw/frmt_lcp.html                            |  1298 +-
 frmts/raw/frmt_mff2.html                           |    54 +-
 frmts/raw/fujibasdataset.cpp                       |   104 +-
 frmts/raw/genbindataset.cpp                        |   281 +-
 frmts/raw/gscdataset.cpp                           |    85 +-
 frmts/raw/gtxdataset.cpp                           |   145 +-
 frmts/raw/hkvdataset.cpp                           |   789 +-
 frmts/raw/idadataset.cpp                           |   315 +-
 frmts/raw/iscedataset.cpp                          |   676 +
 frmts/raw/krodataset.cpp                           |   122 +-
 frmts/raw/landataset.cpp                           |   381 +-
 frmts/raw/lcpdataset.cpp                           |   496 +-
 frmts/raw/loslasdataset.cpp                        |    79 +-
 frmts/raw/makefile.vc                              |     2 +-
 frmts/raw/mffdataset.cpp                           |   800 +-
 frmts/raw/ndfdataset.cpp                           |   192 +-
 frmts/raw/ntv2dataset.cpp                          |   416 +-
 frmts/raw/pauxdataset.cpp                          |   439 +-
 frmts/raw/pnmdataset.cpp                           |   132 +-
 frmts/raw/rawdataset.cpp                           |   674 +-
 frmts/raw/rawdataset.h                             |    23 +-
 frmts/raw/roipacdataset.cpp                        |   272 +-
 frmts/raw/snodasdataset.cpp                        |   141 +-
 frmts/rik/frmt_rik.html                            |     3 +-
 frmts/rik/rikdataset.cpp                           |   251 +-
 frmts/rmf/frmt_rmf.html                            |     4 +-
 frmts/rmf/rmfdataset.cpp                           |   586 +-
 frmts/rmf/rmfdataset.h                             |    10 +-
 frmts/rmf/rmfdem.cpp                               |    56 +-
 frmts/rmf/rmflzw.cpp                               |     8 +-
 frmts/rs2/frmt_rs2.html                            |    10 +-
 frmts/rs2/rs2dataset.cpp                           |   738 +-
 frmts/safe/GNUmakefile                             |    13 +
 frmts/safe/frmt_safe.html                          |    49 +
 frmts/safe/makefile.vc                             |    13 +
 frmts/safe/safedataset.cpp                         |  1096 +
 frmts/saga/sagadataset.cpp                         |   390 +-
 frmts/sde/frmt_sde.html                            |   186 +-
 frmts/sde/gdal_sde.h                               |     6 +-
 frmts/sde/sdedataset.cpp                           |   188 +-
 frmts/sde/sdedataset.h                             |    24 +-
 frmts/sde/sdeerror.cpp                             |    17 +-
 frmts/sde/sdeerror.h                               |     4 +-
 frmts/sde/sderasterband.cpp                        |   239 +-
 frmts/sde/sderasterband.h                          |    25 +-
 frmts/sdts/Makefile.in                             |    52 +-
 frmts/sdts/sdts2shp.cpp                            |   101 +-
 frmts/sdts/sdts_al.h                               |    73 +-
 frmts/sdts/sdts_main.dox                           |     6 +-
 frmts/sdts/sdts_tut.dox                            |     2 +-
 frmts/sdts/sdtsattrreader.cpp                      |    46 +-
 frmts/sdts/sdtscatd.cpp                            |    86 +-
 frmts/sdts/sdtsdataset.cpp                         |   122 +-
 frmts/sdts/sdtsindexedreader.cpp                   |    64 +-
 frmts/sdts/sdtsiref.cpp                            |   101 +-
 frmts/sdts/sdtslib.cpp                             |   100 +-
 frmts/sdts/sdtslinereader.cpp                      |    93 +-
 frmts/sdts/sdtspointreader.cpp                     |    54 +-
 frmts/sdts/sdtspolygonreader.cpp                   |   176 +-
 frmts/sdts/sdtsrasterreader.cpp                    |   131 +-
 frmts/sdts/sdtstransfer.cpp                        |   205 +-
 frmts/sdts/sdtsxref.cpp                            |    28 +-
 frmts/sentinel2/GNUmakefile                        |    11 +
 frmts/sentinel2/frmt_sentinel2.html                |   458 +
 frmts/sentinel2/makefile.vc                        |    13 +
 frmts/sentinel2/sentinel2dataset.cpp               |  3231 +++
 frmts/sgi/sgidataset.cpp                           |   386 +-
 frmts/srtmhgt/srtmhgtdataset.cpp                   |   185 +-
 frmts/terragen/frmt_terragen.html                  |    34 +-
 frmts/terragen/terragendataset.cpp                 |   591 +-
 frmts/til/tildataset.cpp                           |   178 +-
 frmts/tsx/tsxdataset.cpp                           |   223 +-
 frmts/usgsdem/CDED.notes                           |     2 +-
 frmts/usgsdem/frmt_usgsdem.html                    |    28 +-
 frmts/usgsdem/usgsdem_create.cpp                   |   414 +-
 frmts/usgsdem/usgsdemdataset.cpp                   |   411 +-
 frmts/vrt/GNUmakefile                              |     2 +-
 frmts/vrt/gdal_vrt.h                               |     7 +-
 frmts/vrt/makefile.vc                              |     3 +-
 frmts/vrt/vrt_tutorial.dox                         |   289 +-
 frmts/vrt/vrtdataset.cpp                           |   989 +-
 frmts/vrt/vrtdataset.h                             |   473 +-
 frmts/vrt/vrtderivedrasterband.cpp                 |   172 +-
 frmts/vrt/vrtdriver.cpp                            |   192 +-
 frmts/vrt/vrtfilters.cpp                           |   337 +-
 frmts/vrt/vrtpansharpened.cpp                      |  1755 ++
 frmts/vrt/vrtrasterband.cpp                        |   531 +-
 frmts/vrt/vrtrawrasterband.cpp                     |   226 +-
 frmts/vrt/vrtsourcedrasterband.cpp                 |   673 +-
 frmts/vrt/vrtsources.cpp                           |  1102 +-
 frmts/vrt/vrtwarped.cpp                            |   739 +-
 frmts/wcs/frmt_wcs.html                            |    20 +-
 frmts/wcs/httpdriver.cpp                           |    60 +-
 frmts/wcs/wcsdataset.cpp                           |   648 +-
 frmts/webp/frmt_webp.html                          |   102 +-
 frmts/webp/webp_headers.h                          |    41 +
 frmts/webp/webpdataset.cpp                         |   303 +-
 frmts/wms/GNUmakefile                              |     3 +-
 frmts/wms/frmt_wms.html                            |    31 +-
 frmts/wms/frmt_wms_iip.xml                         |    14 +
 frmts/wms/gdalhttp.cpp                             |    75 +-
 frmts/wms/gdalhttp.h                               |     8 +-
 frmts/wms/gdalwmscache.cpp                         |    10 +-
 frmts/wms/gdalwmsdataset.cpp                       |    50 +-
 frmts/wms/gdalwmsrasterband.cpp                    |    70 +-
 frmts/wms/makefile.vc                              |     3 +-
 frmts/wms/md5.cpp                                  |    16 +-
 frmts/wms/minidriver.cpp                           |    22 +-
 frmts/wms/minidriver_arcgis_server.cpp             |   187 +-
 frmts/wms/minidriver_arcgis_server.h               |    11 +-
 frmts/wms/minidriver_iip.cpp                       |    81 +
 frmts/wms/minidriver_iip.h                         |    44 +
 frmts/wms/minidriver_tiled_wms.cpp                 |    27 +-
 frmts/wms/minidriver_tiled_wms.h                   |     3 +-
 frmts/wms/minidriver_wms.cpp                       |     8 +-
 frmts/wms/wmsdriver.cpp                            |   191 +-
 frmts/wms/wmsdriver.h                              |    41 +-
 frmts/wms/wmsmetadataset.cpp                       |    10 +-
 frmts/wms/wmsmetadataset.h                         |     8 +-
 frmts/wms/wmsutils.cpp                             |     6 +-
 frmts/wmts/GNUmakefile                             |    11 +
 frmts/wmts/frmt_wmts.html                          |   284 +
 frmts/wmts/makefile.vc                             |    14 +
 frmts/wmts/wmtsdataset.cpp                         |  2017 ++
 frmts/xpm/xpmdataset.cpp                           |   361 +-
 frmts/xyz/frmt_xyz.html                            |     4 +-
 frmts/xyz/xyzdataset.cpp                           |   427 +-
 frmts/zlib/GNUmakefile                             |     4 +-
 frmts/zlib/README                                  |     6 +-
 frmts/zlib/adler32.c                               |     4 +-
 frmts/zlib/gzio.c                                  |     6 +-
 frmts/zlib/zconf.h                                 |     4 +-
 frmts/zlib/zlib.h                                  |     6 +-
 frmts/zlib/zutil.c                                 |    10 +-
 frmts/zlib/zutil.h                                 |    28 +-
 frmts/zmap/zmapdataset.cpp                         |   201 +-
 gcore/GNUmakefile                                  |    14 +-
 gcore/gdal.h                                       |   317 +-
 gcore/gdal_frmts.h                                 |    14 +-
 gcore/gdal_mdreader.cpp                            |   268 +-
 gcore/gdal_mdreader.h                              |    40 +-
 gcore/gdal_misc.cpp                                |  1013 +-
 gcore/gdal_pam.h                                   |    44 +-
 gcore/gdal_priv.h                                  |   474 +-
 gcore/gdal_priv_templates.hpp                      |   436 +
 gcore/gdal_proxy.h                                 |    32 +-
 gcore/gdal_rat.cpp                                 |   743 +-
 gcore/gdal_rat.h                                   |   113 +-
 gcore/gdal_version.h                               |     8 +-
 gcore/gdalabstractbandblockcache.cpp               |   190 +
 gcore/gdalallvalidmaskband.cpp                     |    19 +-
 gcore/gdalarraybandblockcache.cpp                  |   481 +
 gcore/gdalclientserver.cpp                         |   884 +-
 gcore/gdalcolortable.cpp                           |   114 +-
 gcore/gdaldataset.cpp                              |  1400 +-
 gcore/gdaldefaultasync.cpp                         |   110 +-
 gcore/gdaldefaultoverviews.cpp                     |   249 +-
 gcore/gdaldllmain.cpp                              |    15 +-
 gcore/gdaldriver.cpp                               |   249 +-
 gcore/gdaldrivermanager.cpp                        |   216 +-
 gcore/gdalexif.cpp                                 |   222 +-
 gcore/gdalexif.h                                   |    28 +-
 gcore/gdalgeorefpamdataset.cpp                     |    40 +-
 gcore/gdalgeorefpamdataset.h                       |     8 +-
 gcore/gdalgmlcoverage.cpp                          |    64 +-
 gcore/gdalhashsetbandblockcache.cpp                |   302 +
 gcore/gdaljp2abstractdataset.cpp                   |    55 +-
 gcore/gdaljp2abstractdataset.h                     |     8 +-
 gcore/gdaljp2box.cpp                               |   156 +-
 gcore/gdaljp2metadata.cpp                          |   434 +-
 gcore/gdaljp2metadata.h                            |    20 +-
 gcore/gdaljp2metadatagenerator.cpp                 |    78 +-
 gcore/gdaljp2metadatagenerator.h                   |     4 +-
 gcore/gdaljp2structure.cpp                         |    94 +-
 gcore/gdalmajorobject.cpp                          |    87 +-
 gcore/gdalmultidomainmetadata.cpp                  |    56 +-
 gcore/gdalnodatamaskband.cpp                       |    32 +-
 gcore/gdalnodatavaluesmaskband.cpp                 |    55 +-
 gcore/gdalopeninfo.cpp                             |   202 +-
 gcore/gdaloverviewdataset.cpp                      |   257 +-
 gcore/gdalpamdataset.cpp                           |   382 +-
 gcore/gdalpamproxydb.cpp                           |   175 +-
 gcore/gdalpamrasterband.cpp                        |   239 +-
 gcore/gdalproxydataset.cpp                         |    41 +-
 gcore/gdalproxypool.cpp                            |   132 +-
 gcore/gdalrasterband.cpp                           |  1377 +-
 gcore/gdalrasterblock.cpp                          |   411 +-
 gcore/gdalrescaledalphaband.cpp                    |    15 +-
 gcore/gdalsse_priv.h                               |   368 +-
 gcore/gdalvirtualmem.cpp                           |   187 +-
 gcore/jp2dump.cpp                                  |    57 -
 gcore/makefile.vc                                  |     4 +-
 gcore/mdreader/reader_alos.cpp                     |     6 +-
 gcore/mdreader/reader_alos.h                       |     4 +-
 gcore/mdreader/reader_digital_globe.cpp            |    65 +-
 gcore/mdreader/reader_digital_globe.h              |     8 +-
 gcore/mdreader/reader_eros.cpp                     |     8 +-
 gcore/mdreader/reader_eros.h                       |     4 +-
 gcore/mdreader/reader_geo_eye.cpp                  |    60 +-
 gcore/mdreader/reader_geo_eye.h                    |     8 +-
 gcore/mdreader/reader_kompsat.cpp                  |    12 +-
 gcore/mdreader/reader_kompsat.h                    |     4 +-
 gcore/mdreader/reader_landsat.cpp                  |     8 +-
 gcore/mdreader/reader_landsat.h                    |     6 +-
 gcore/mdreader/reader_orb_view.cpp                 |     6 +-
 gcore/mdreader/reader_orb_view.h                   |     4 +-
 gcore/mdreader/reader_pleiades.cpp                 |    17 +-
 gcore/mdreader/reader_pleiades.h                   |     4 +-
 gcore/mdreader/reader_rapid_eye.cpp                |     2 +-
 gcore/mdreader/reader_rapid_eye.h                  |     2 +-
 gcore/mdreader/reader_rdk1.cpp                     |    10 +-
 gcore/mdreader/reader_rdk1.h                       |     6 +-
 gcore/mdreader/reader_spot.cpp                     |     2 +-
 gcore/overview.cpp                                 |   924 +-
 gcore/rasterio.cpp                                 |  2524 +-
 gdal.pc.in                                         |     2 +-
 gdalnightlysvn.sh                                  |     8 +-
 gnm/GNUmakefile                                    |    31 +
 gnm/gnm.h                                          |   699 +
 gnm/gnm_api.h                                      |   100 +
 gnm/gnm_arch.dox                                   |    56 +
 gnm/gnm_frmts/GNUmakefile                          |    38 +
 gnm/gnm_frmts/db/GNUmakefile                       |    18 +
 gnm/gnm_frmts/db/gnmdb.h                           |    61 +
 gnm/gnm_frmts/db/gnmdbdriver.cpp                   |   136 +
 gnm/gnm_frmts/db/gnmdbnetwork.cpp                  |   462 +
 gnm/gnm_frmts/db/makefile.vc                       |    16 +
 gnm/gnm_frmts/file/GNUmakefile                     |    18 +
 gnm/gnm_frmts/file/gnmfile.h                       |    75 +
 gnm/gnm_frmts/file/gnmfiledriver.cpp               |   157 +
 gnm/gnm_frmts/file/gnmfilenetwork.cpp              |   659 +
 gnm/gnm_frmts/file/makefile.vc                     |    16 +
 gnm/gnm_frmts/gnm_frmts.h                          |    49 +
 gnm/gnm_frmts/gnmregisterall.cpp                   |    55 +
 gnm/gnm_frmts/makefile.vc                          |    32 +
 gnm/gnm_frmts/o/README.TXT                         |     7 +
 gnm/gnm_priv.h                                     |   101 +
 gnm/gnm_tut.dox                                    |   337 +
 gnm/gnmgenericnetwork.cpp                          |  1526 ++
 gnm/gnmgraph.cpp                                   |   622 +
 gnm/gnmgraph.h                                     |   229 +
 gnm/gnmlayer.cpp                                   |   367 +
 gnm/gnmnetwork.cpp                                 |    99 +
 gnm/gnmresultlayer.cpp                             |   213 +
 gnm/gnmrule.cpp                                    |   189 +
 gnm/makefile.vc                                    |    40 +
 ltmain.sh                                          |     6 +-
 m4/acinclude.m4                                    |     6 +-
 m4/ax_cflags_warn_all.m4                           |     2 +-
 m4/ax_check_compile_flag.m4                        |    74 +
 m4/ax_lib_libkml.m4                                |     4 +-
 m4/ax_lib_sqlite3.m4                               |    12 +-
 m4/lib-link.m4                                     |     2 +-
 m4/libtool.m4                                      |    12 +-
 m4/pkg.m4                                          |     2 +-
 makefile.vc                                        |    38 +-
 makegdal_gen.bat                                   |     4 +-
 man/man1/_home_rouault_dist_wrk_gdal_apps_.1       |    54 +-
 man/man1/gdal-config.1                             |     2 +-
 man/man1/gdal2tiles.1                              |    10 +-
 man/man1/gdal_calc.1                               |     2 +-
 man/man1/gdal_contour.1                            |     5 +-
 man/man1/gdal_edit.1                               |     7 +-
 man/man1/gdal_fillnodata.1                         |     2 +-
 man/man1/gdal_grid.1                               |    31 +-
 man/man1/gdal_merge.1                              |    13 +-
 man/man1/gdal_pansharpen.1                         |    99 +
 man/man1/gdal_polygonize.1                         |     2 +-
 man/man1/gdal_proximity.1                          |     4 +-
 man/man1/gdal_rasterize.1                          |    16 +-
 man/man1/gdal_retile.1                             |    12 +-
 man/man1/gdal_sieve.1                              |     2 +-
 man/man1/gdal_translate.1                          |     9 +-
 man/man1/gdal_utilities.1                          |    18 +-
 man/man1/gdaladdo.1                                |    15 +-
 man/man1/gdalbuildvrt.1                            |    16 +-
 man/man1/gdalcompare.1                             |     2 +-
 man/man1/gdaldem.1                                 |     7 +-
 man/man1/gdalinfo.1                                |     5 +-
 man/man1/gdallocationinfo.1                        |     6 +-
 man/man1/gdalmanage.1                              |     2 +-
 man/man1/gdalmove.1                                |     2 +-
 man/man1/gdalsrsinfo.1                             |     2 +-
 man/man1/gdaltindex.1                              |     4 +-
 man/man1/gdaltransform.1                           |     6 +-
 man/man1/gdalwarp.1                                |    19 +-
 man/man1/gnm_utilities.1                           |    14 +
 man/man1/gnmanalyse.1                              |    54 +
 man/man1/gnmmanage.1                               |    85 +
 man/man1/nearblack.1                               |     9 +-
 man/man1/ogr2ogr.1                                 |    29 +-
 man/man1/ogr_utilities.1                           |    28 +-
 man/man1/ogrinfo.1                                 |    18 +-
 man/man1/ogrlineref.1                              |    12 +-
 man/man1/ogrtindex.1                               |     2 +-
 man/man1/pct2rgb.1                                 |     4 +-
 man/man1/rgb2pct.1                                 |     4 +-
 mkbindist.sh                                       |     4 -
 mkgdaldist.sh                                      |    17 +-
 mktestdist.sh                                      |     2 +-
 nmake-wince.opt                                    |   145 -
 nmake.opt                                          |   177 +-
 ogr/Doxyfile                                       |     2 +-
 ogr/GNUmakefile                                    |    25 +-
 ogr/generate_encoding_table.c                      |     6 +-
 ogr/gml2ogrgeometry.cpp                            |   618 +-
 ogr/index.dox                                      |   114 -
 ogr/makefile.vc                                    |     6 -
 ogr/ogr2gmlgeometry.cpp                            |   349 +-
 ogr/ogr_api.cpp                                    |   706 +-
 ogr/ogr_api.h                                      |   190 +-
 ogr/ogr_apitut.dox                                 |     2 +-
 ogr/ogr_arch.dox                                   |    12 +-
 ogr/ogr_capi_test.c                                |    10 +-
 ogr/ogr_core.h                                     |   178 +-
 ogr/ogr_drivertut.dox                              |    11 +-
 ogr/ogr_expat.cpp                                  |     7 +-
 ogr/ogr_feature.h                                  |    91 +-
 ogr/ogr_feature_style.html                         |   182 +-
 ogr/ogr_featurestyle.h                             |    82 +-
 ogr/ogr_fromepsg.cpp                               |  1099 +-
 ogr/ogr_geocoding.cpp                              |   113 +-
 ogr/ogr_geocoding.h                                |    10 +-
 ogr/ogr_geometry.h                                 |   280 +-
 ogr/ogr_geos.h                                     |     6 +-
 ogr/ogr_opt.cpp                                    |   301 +-
 ogr/ogr_p.h                                        |    45 +-
 ogr/ogr_spatialref.h                               |   141 +-
 ogr/ogr_sql.dox                                    |    10 +-
 ogr/ogr_sql_sqlite.dox                             |     2 +-
 ogr/ogr_srs_api.h                                  |   124 +-
 ogr/ogr_srs_dict.cpp                               |    64 +-
 ogr/ogr_srs_erm.cpp                                |    50 +-
 ogr/ogr_srs_esri.cpp                               |  1141 +-
 ogr/ogr_srs_esri_names.h                           |   676 +-
 ogr/ogr_srs_ozi.cpp                                |   113 +-
 ogr/ogr_srs_panorama.cpp                           |    98 +-
 ogr/ogr_srs_pci.cpp                                |   206 +-
 ogr/ogr_srs_proj4.cpp                              |  1096 +-
 ogr/ogr_srs_usgs.cpp                               |    79 +-
 ogr/ogr_srs_validate.cpp                           |   149 +-
 ogr/ogr_srs_xml.cpp                                |   399 +-
 ogr/ogr_srsnode.cpp                                |   267 +-
 ogr/ograpispy.cpp                                  |    87 +-
 ogr/ograpispy.h                                    |    24 +-
 ogr/ograssemblepolygon.cpp                         |    74 +-
 ogr/ogrcircularstring.cpp                          |    62 +-
 ogr/ogrcompoundcurve.cpp                           |    94 +-
 ogr/ogrct.cpp                                      |   473 +-
 ogr/ogrcurve.cpp                                   |    38 +-
 ogr/ogrcurvecollection.cpp                         |   173 +-
 ogr/ogrcurvepolygon.cpp                            |    98 +-
 ogr/ogrfeature.cpp                                 |  1442 +-
 ogr/ogrfeaturedefn.cpp                             |   172 +-
 ogr/ogrfeaturequery.cpp                            |    62 +-
 ogr/ogrfeaturestyle.cpp                            |   479 +-
 ogr/ogrfielddefn.cpp                               |   219 +-
 ogr/ogrgeomediageometry.cpp                        |    30 +-
 ogr/ogrgeomediageometry.h                          |     6 +-
 ogr/ogrgeometry.cpp                                |  1627 +-
 ogr/ogrgeometrycollection.cpp                      |   304 +-
 ogr/ogrgeometryfactory.cpp                         |   615 +-
 ogr/ogrlinearring.cpp                              |   217 +-
 ogr/ogrlinestring.cpp                              |  1068 +-
 ogr/ogrmulticurve.cpp                              |    58 +-
 ogr/ogrmultilinestring.cpp                         |    53 +-
 ogr/ogrmultipoint.cpp                              |   244 +-
 ogr/ogrmultipolygon.cpp                            |    70 +-
 ogr/ogrmultisurface.cpp                            |    87 +-
 ogr/ogrpgeogeometry.cpp                            |   422 +-
 ogr/ogrpgeogeometry.h                              |    10 +-
 ogr/ogrpoint.cpp                                   |   405 +-
 ogr/ogrpolygon.cpp                                 |   266 +-
 ogr/ogrsf_frmts/GNUmakefile                        |     5 +-
 ogr/ogrsf_frmts/aeronavfaa/ogr_aeronavfaa.h        |     8 +-
 .../aeronavfaa/ograeronavfaadatasource.cpp         |    23 +-
 ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadriver.cpp |    29 +-
 ogr/ogrsf_frmts/aeronavfaa/ograeronavfaalayer.cpp  |   115 +-
 ogr/ogrsf_frmts/amigocloud/GNUmakefile             |    14 +
 ogr/ogrsf_frmts/amigocloud/drv_amigocloud.html     |   129 +
 ogr/ogrsf_frmts/amigocloud/makefile.vc             |    33 +
 ogr/ogrsf_frmts/amigocloud/ogr_amigocloud.h        |   296 +
 .../amigocloud/ogramigoclouddatasource.cpp         |   866 +
 ogr/ogrsf_frmts/amigocloud/ogramigoclouddriver.cpp |   138 +
 ogr/ogrsf_frmts/amigocloud/ogramigocloudlayer.cpp  |   465 +
 .../amigocloud/ogramigocloudresultlayer.cpp        |   134 +
 .../amigocloud/ogramigocloudtablelayer.cpp         |  1183 +
 ogr/ogrsf_frmts/amigocloud/pkg/Makefile.in         |    40 +
 ogr/ogrsf_frmts/amigocloud/pkg/configure           |  4351 +++
 ogr/ogrsf_frmts/amigocloud/pkg/configure.in        |   115 +
 ogr/ogrsf_frmts/arcgen/ogr_arcgen.h                |     8 +-
 ogr/ogrsf_frmts/arcgen/ograrcgendatasource.cpp     |    30 +-
 ogr/ogrsf_frmts/arcgen/ograrcgendriver.cpp         |    44 +-
 ogr/ogrsf_frmts/arcgen/ograrcgenlayer.cpp          |    53 +-
 ogr/ogrsf_frmts/arcobjects/aodriver.cpp            |     4 +-
 ogr/ogrsf_frmts/arcobjects/aoutils.cpp             |    18 +-
 ogr/ogrsf_frmts/arcobjects/aoutils.h               |     4 +-
 ogr/ogrsf_frmts/arcobjects/drv_ao.html             |   200 +-
 ogr/ogrsf_frmts/arcobjects/ogr_ao.h                |     8 +-
 ogr/ogrsf_frmts/avc/avc.h                          |    79 +-
 ogr/ogrsf_frmts/avc/avc_bin.c                      |   342 +-
 ogr/ogrsf_frmts/avc/avc_binwr.c                    |   317 +-
 ogr/ogrsf_frmts/avc/avc_e00gen.c                   |   261 +-
 ogr/ogrsf_frmts/avc/avc_e00parse.c                 |   299 +-
 ogr/ogrsf_frmts/avc/avc_e00read.c                  |   297 +-
 ogr/ogrsf_frmts/avc/avc_e00write.c                 |   212 +-
 ogr/ogrsf_frmts/avc/avc_mbyte.c                    |    87 +-
 ogr/ogrsf_frmts/avc/avc_mbyte.h                    |    18 +-
 ogr/ogrsf_frmts/avc/avc_misc.c                     |    53 +-
 ogr/ogrsf_frmts/avc/avc_rawbin.c                   |   112 +-
 ogr/ogrsf_frmts/avc/dbfopen.h                      |   192 -
 ogr/ogrsf_frmts/avc/drv_avcbin.html                |    22 +-
 ogr/ogrsf_frmts/avc/drv_avce00.html                |    20 +-
 ogr/ogrsf_frmts/avc/ogr_avc.h                      |    32 +-
 ogr/ogrsf_frmts/avc/ogravcbindatasource.cpp        |    49 +-
 ogr/ogrsf_frmts/avc/ogravcbindriver.cpp            |    40 +-
 ogr/ogrsf_frmts/avc/ogravcbinlayer.cpp             |   165 +-
 ogr/ogrsf_frmts/avc/ogravcdatasource.cpp           |    18 +-
 ogr/ogrsf_frmts/avc/ogravce00datasource.cpp        |    94 +-
 ogr/ogrsf_frmts/avc/ogravce00driver.cpp            |    29 +-
 ogr/ogrsf_frmts/avc/ogravce00layer.cpp             |   101 +-
 ogr/ogrsf_frmts/avc/ogravclayer.cpp                |   153 +-
 ogr/ogrsf_frmts/bna/GNUmakefile                    |     2 -
 ogr/ogrsf_frmts/bna/drv_bna.html                   |     4 +-
 ogr/ogrsf_frmts/bna/makefile.vc                    |     1 -
 ogr/ogrsf_frmts/bna/ogr_bna.h                      |    30 +-
 ogr/ogrsf_frmts/bna/ogrbnadatasource.cpp           |   130 +-
 ogr/ogrsf_frmts/bna/ogrbnadriver.cpp               |    76 +-
 ogr/ogrsf_frmts/bna/ogrbnalayer.cpp                |   347 +-
 ogr/ogrsf_frmts/bna/ogrbnaparser.cpp               |   189 +-
 ogr/ogrsf_frmts/bna/ogrbnaparser.h                 |     8 +-
 ogr/ogrsf_frmts/cartodb/drv_cartodb.html           |     2 +-
 ogr/ogrsf_frmts/cartodb/ogr_cartodb.h              |    61 +-
 ogr/ogrsf_frmts/cartodb/ogrcartodbdatasource.cpp   |   171 +-
 ogr/ogrsf_frmts/cartodb/ogrcartodbdriver.cpp       |    53 +-
 ogr/ogrsf_frmts/cartodb/ogrcartodblayer.cpp        |    58 +-
 ogr/ogrsf_frmts/cartodb/ogrcartodbresultlayer.cpp  |     6 +-
 ogr/ogrsf_frmts/cartodb/ogrcartodbtablelayer.cpp   |   487 +-
 ogr/ogrsf_frmts/cloudant/drv_cloudant.html         |     6 +-
 ogr/ogrsf_frmts/cloudant/ogr_cloudant.h            |    12 +-
 ogr/ogrsf_frmts/cloudant/ogrcloudantdatasource.cpp |    51 +-
 ogr/ogrsf_frmts/cloudant/ogrcloudantdriver.cpp     |     2 +-
 ogr/ogrsf_frmts/cloudant/ogrcloudanttablelayer.cpp |    43 +-
 ogr/ogrsf_frmts/couchdb/drv_couchdb.html           |     4 +-
 ogr/ogrsf_frmts/couchdb/ogr_couchdb.h              |    24 +-
 ogr/ogrsf_frmts/couchdb/ogrcouchdbdatasource.cpp   |    76 +-
 ogr/ogrsf_frmts/couchdb/ogrcouchdbdriver.cpp       |    10 +-
 ogr/ogrsf_frmts/couchdb/ogrcouchdblayer.cpp        |    44 +-
 ogr/ogrsf_frmts/couchdb/ogrcouchdbrowslayer.cpp    |    19 +-
 ogr/ogrsf_frmts/couchdb/ogrcouchdbtablelayer.cpp   |   129 +-
 ogr/ogrsf_frmts/csv/GNUmakefile                    |     4 +-
 ogr/ogrsf_frmts/csv/drv_csv.html                   |   147 +-
 ogr/ogrsf_frmts/csv/makefile.vc                    |     2 +-
 ogr/ogrsf_frmts/csv/ogr_csv.h                      |    73 +-
 ogr/ogrsf_frmts/csv/ogrcsvdatasource.cpp           |   628 +-
 ogr/ogrsf_frmts/csv/ogrcsvdriver.cpp               |   178 +-
 ogr/ogrsf_frmts/csv/ogrcsvlayer.cpp                |   989 +-
 ogr/ogrsf_frmts/csw/ogrcswdataset.cpp              |   122 +-
 ogr/ogrsf_frmts/db2/GNUmakefile                    |    10 +
 ogr/ogrsf_frmts/db2/drv_db2.html                   |   119 +
 ogr/ogrsf_frmts/db2/drv_db2_raster.html            |   394 +
 ogr/ogrsf_frmts/db2/gdaldb2rasterband.cpp          |  2163 ++
 ogr/ogrsf_frmts/db2/makefile.vc                    |    14 +
 ogr/ogrsf_frmts/db2/makeplugin.vc                  |    34 +
 ogr/ogrsf_frmts/db2/ogr_db2.h                      |   911 +
 ogr/ogrsf_frmts/db2/ogrdb2cli.cpp                  |  1849 ++
 ogr/ogrsf_frmts/db2/ogrdb2datasource.cpp           |  3622 +++
 ogr/ogrsf_frmts/db2/ogrdb2datasourcemd.cpp         |   930 +
 ogr/ogrsf_frmts/db2/ogrdb2driver.cpp               |   252 +
 ogr/ogrsf_frmts/db2/ogrdb2geometryvalidator.cpp    |   505 +
 ogr/ogrsf_frmts/db2/ogrdb2layer.cpp                |   497 +
 ogr/ogrsf_frmts/db2/ogrdb2selectlayer.cpp          |   239 +
 ogr/ogrsf_frmts/db2/ogrdb2tablelayer.cpp           |  1524 ++
 ogr/ogrsf_frmts/dgn/dgndump.c                      |    37 +-
 ogr/ogrsf_frmts/dgn/dgnfloat.cpp                   |    38 +-
 ogr/ogrsf_frmts/dgn/dgnhelp.cpp                    |   305 +-
 ogr/ogrsf_frmts/dgn/dgnlib.h                       |   212 +-
 ogr/ogrsf_frmts/dgn/dgnlibp.h                      |    17 +-
 ogr/ogrsf_frmts/dgn/dgnopen.cpp                    |    65 +-
 ogr/ogrsf_frmts/dgn/dgnread.cpp                    |   373 +-
 ogr/ogrsf_frmts/dgn/dgnstroke.cpp                  |    37 +-
 ogr/ogrsf_frmts/dgn/dgnwrite.cpp                   |   673 +-
 ogr/ogrsf_frmts/dgn/dgnwritetest.c                 |    37 +-
 ogr/ogrsf_frmts/dgn/dist/README                    |    10 +-
 ogr/ogrsf_frmts/dgn/drv_dgn.html                   |    42 +-
 ogr/ogrsf_frmts/dgn/ogr_dgn.h                      |    21 +-
 ogr/ogrsf_frmts/dgn/ogrdgndatasource.cpp           |   134 +-
 ogr/ogrsf_frmts/dgn/ogrdgndriver.cpp               |    60 +-
 ogr/ogrsf_frmts/dgn/ogrdgnlayer.cpp                |   436 +-
 ogr/ogrsf_frmts/dgn/web/index.html                 |    83 +-
 ogr/ogrsf_frmts/dgn/web/representation.html        |    34 +-
 ogr/ogrsf_frmts/dods/drv_dods.html                 |     2 +-
 ogr/ogrsf_frmts/dods/ogr_dods.h                    |    46 +-
 ogr/ogrsf_frmts/dods/ogrdodsdatasource.cpp         |    69 +-
 ogr/ogrsf_frmts/dods/ogrdodsdriver.cpp             |     6 +-
 ogr/ogrsf_frmts/dods/ogrdodsfielddefn.cpp          |    46 +-
 ogr/ogrsf_frmts/dods/ogrdodsgrid.cpp               |    93 +-
 ogr/ogrsf_frmts/dods/ogrdodslayer.cpp              |    54 +-
 ogr/ogrsf_frmts/dods/ogrdodssequencelayer.cpp      |   165 +-
 ogr/ogrsf_frmts/dwg/drv_dwg.html                   |     4 +-
 ogr/ogrsf_frmts/dwg/ogr_dwg.h                      |    22 +-
 ogr/ogrsf_frmts/dwg/ogrdwg_blockmap.cpp            |    12 +-
 ogr/ogrsf_frmts/dwg/ogrdwg_dimension.cpp           |    61 +-
 ogr/ogrsf_frmts/dwg/ogrdwg_hatch.cpp               |    50 +-
 ogr/ogrsf_frmts/dwg/ogrdwgblockslayer.cpp          |    15 +-
 ogr/ogrsf_frmts/dwg/ogrdwgdatasource.cpp           |    49 +-
 ogr/ogrsf_frmts/dwg/ogrdwgdriver.cpp               |     9 +-
 ogr/ogrsf_frmts/dwg/ogrdwglayer.cpp                |   175 +-
 ogr/ogrsf_frmts/dxf/drv_dxf.html                   |    94 +-
 ogr/ogrsf_frmts/dxf/intronurbs.cpp                 |    50 +-
 ogr/ogrsf_frmts/dxf/ogr_autocad_services.cpp       |   565 +-
 ogr/ogrsf_frmts/dxf/ogr_autocad_services.h         |     6 +-
 ogr/ogrsf_frmts/dxf/ogr_dxf.h                      |    64 +-
 ogr/ogrsf_frmts/dxf/ogrdxf_blockmap.cpp            |    39 +-
 ogr/ogrsf_frmts/dxf/ogrdxf_dimension.cpp           |    54 +-
 ogr/ogrsf_frmts/dxf/ogrdxf_hatch.cpp               |   107 +-
 ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.cpp     |    38 +-
 ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.h       |    27 +-
 ogr/ogrsf_frmts/dxf/ogrdxfblockslayer.cpp          |    17 +-
 ogr/ogrsf_frmts/dxf/ogrdxfblockswriterlayer.cpp    |    14 +-
 ogr/ogrsf_frmts/dxf/ogrdxfdatasource.cpp           |   245 +-
 ogr/ogrsf_frmts/dxf/ogrdxfdriver.cpp               |    77 +-
 ogr/ogrsf_frmts/dxf/ogrdxflayer.cpp                |   302 +-
 ogr/ogrsf_frmts/dxf/ogrdxfreader.cpp               |    49 +-
 ogr/ogrsf_frmts/dxf/ogrdxfwriterds.cpp             |   184 +-
 ogr/ogrsf_frmts/dxf/ogrdxfwriterlayer.cpp          |   170 +-
 ogr/ogrsf_frmts/edigeo/drv_edigeo.html             |     6 +-
 ogr/ogrsf_frmts/edigeo/ogr_edigeo.h                |    14 +-
 ogr/ogrsf_frmts/edigeo/ogredigeodatasource.cpp     |   133 +-
 ogr/ogrsf_frmts/edigeo/ogredigeodriver.cpp         |    33 +-
 ogr/ogrsf_frmts/edigeo/ogredigeolayer.cpp          |    14 +-
 ogr/ogrsf_frmts/elastic/drv_elasticsearch.html     |   284 +-
 ogr/ogrsf_frmts/elastic/ogr_elastic.h              |   220 +-
 ogr/ogrsf_frmts/elastic/ogrelasticdatasource.cpp   |   531 +-
 ogr/ogrsf_frmts/elastic/ogrelasticdriver.cpp       |   106 +-
 ogr/ogrsf_frmts/elastic/ogrelasticlayer.cpp        |  2589 +-
 ogr/ogrsf_frmts/filegdb/FGdbDatasource.cpp         |   280 +-
 ogr/ogrsf_frmts/filegdb/FGdbDriver.cpp             |   390 +-
 ogr/ogrsf_frmts/filegdb/FGdbLayer.cpp              |  1119 +-
 ogr/ogrsf_frmts/filegdb/FGdbUtils.cpp              |    79 +-
 ogr/ogrsf_frmts/filegdb/FGdbUtils.h                |    10 +-
 ogr/ogrsf_frmts/filegdb/drv_filegdb.html           |   259 +-
 ogr/ogrsf_frmts/filegdb/filegdbsdk_headers.h       |    41 +
 ogr/ogrsf_frmts/filegdb/makefile.vc                |     6 +
 ogr/ogrsf_frmts/filegdb/ogr_fgdb.h                 |    91 +-
 ogr/ogrsf_frmts/fme/drv_fme.html                   |    34 +-
 ogr/ogrsf_frmts/fme/fme2ogr.h                      |    55 +-
 ogr/ogrsf_frmts/fme/fme2ogr_utils.cpp              |    13 +-
 ogr/ogrsf_frmts/fme/ogrfmecacheindex.cpp           |    66 +-
 ogr/ogrsf_frmts/fme/ogrfmedatasource.cpp           |   277 +-
 ogr/ogrsf_frmts/fme/ogrfmedriver.cpp               |    12 +-
 ogr/ogrsf_frmts/fme/ogrfmelayer.cpp                |    38 +-
 ogr/ogrsf_frmts/fme/ogrfmelayercached.cpp          |    62 +-
 ogr/ogrsf_frmts/fme/ogrfmelayerdb.cpp              |    78 +-
 ogr/ogrsf_frmts/generic/GNUmakefile                |    19 +-
 ogr/ogrsf_frmts/generic/makefile.vc                |    18 +-
 ogr/ogrsf_frmts/generic/ogr_attrind.cpp            |     6 +-
 ogr/ogrsf_frmts/generic/ogr_gensql.cpp             |   246 +-
 ogr/ogrsf_frmts/generic/ogr_gensql.h               |    19 +-
 ogr/ogrsf_frmts/generic/ogr_miattrind.cpp          |   143 +-
 ogr/ogrsf_frmts/generic/ogrdatasource.cpp          |    28 +-
 ogr/ogrsf_frmts/generic/ogreditablelayer.cpp       |   816 +
 ogr/ogrsf_frmts/generic/ogreditablelayer.h         |   129 +
 ogr/ogrsf_frmts/generic/ogremulatedtransaction.cpp |    39 +-
 ogr/ogrsf_frmts/generic/ogremulatedtransaction.h   |     8 +-
 ogr/ogrsf_frmts/generic/ogrlayer.cpp               |   963 +-
 ogr/ogrsf_frmts/generic/ogrlayerdecorator.cpp      |    17 +-
 ogr/ogrsf_frmts/generic/ogrlayerdecorator.h        |    11 +-
 ogr/ogrsf_frmts/generic/ogrlayerpool.cpp           |    50 +-
 ogr/ogrsf_frmts/generic/ogrlayerpool.h             |    10 +-
 ogr/ogrsf_frmts/generic/ogrmutexeddatasource.cpp   |    18 +-
 ogr/ogrsf_frmts/generic/ogrmutexeddatasource.h     |    26 +-
 ogr/ogrsf_frmts/generic/ogrmutexedlayer.cpp        |     8 +-
 ogr/ogrsf_frmts/generic/ogrmutexedlayer.h          |    10 +-
 ogr/ogrsf_frmts/generic/ogrregisterall.cpp         |    26 +-
 ogr/ogrsf_frmts/generic/ogrsfdriver.cpp            |    31 +-
 ogr/ogrsf_frmts/generic/ogrsfdriverregistrar.cpp   |    23 +-
 ogr/ogrsf_frmts/generic/ogrunionlayer.cpp          |    93 +-
 ogr/ogrsf_frmts/generic/ogrunionlayer.h            |     8 +-
 ogr/ogrsf_frmts/generic/ogrwarpedlayer.cpp         |    14 +-
 ogr/ogrsf_frmts/generic/ogrwarpedlayer.h           |     8 +-
 ogr/ogrsf_frmts/geoconcept/drv_geoconcept.html     |    10 +-
 ogr/ogrsf_frmts/geoconcept/geoconcept.c            |   290 +-
 ogr/ogrsf_frmts/geoconcept/geoconcept.h            |     8 +-
 ogr/ogrsf_frmts/geoconcept/geoconcept_syscoord.c   |   105 +-
 ogr/ogrsf_frmts/geoconcept/geoconcept_syscoord.h   |    13 +-
 .../geoconcept/ogrgeoconceptdatasource.cpp         |   170 +-
 .../geoconcept/ogrgeoconceptdatasource.h           |    22 +-
 ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdriver.cpp |    63 +-
 ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdriver.h   |    14 +-
 ogr/ogrsf_frmts/geoconcept/ogrgeoconceptlayer.cpp  |   153 +-
 ogr/ogrsf_frmts/geoconcept/ogrgeoconceptlayer.h    |    16 +-
 ogr/ogrsf_frmts/geojson/drv_geojson.html           |   155 +-
 ogr/ogrsf_frmts/geojson/libjson/ChangeLog          |    14 +-
 ogr/ogrsf_frmts/geojson/libjson/GNUmakefile        |     6 +-
 ogr/ogrsf_frmts/geojson/libjson/README.html        |    68 +-
 ogr/ogrsf_frmts/geojson/libjson/arraylist.c        |     8 +-
 ogr/ogrsf_frmts/geojson/libjson/arraylist.h        |     4 +-
 ogr/ogrsf_frmts/geojson/libjson/bits.h             |     4 +-
 ogr/ogrsf_frmts/geojson/libjson/debug.c            |     2 +-
 ogr/ogrsf_frmts/geojson/libjson/debug.h            |     4 +-
 ogr/ogrsf_frmts/geojson/libjson/json.h             |     4 +-
 ogr/ogrsf_frmts/geojson/libjson/json_c_version.h   |     4 +-
 ogr/ogrsf_frmts/geojson/libjson/json_inttypes.h    |    21 +-
 ogr/ogrsf_frmts/geojson/libjson/json_object.c      |    19 +-
 ogr/ogrsf_frmts/geojson/libjson/json_object.h      |    18 +-
 .../geojson/libjson/json_object_private.h          |     4 +-
 ogr/ogrsf_frmts/geojson/libjson/json_tokener.c     |    27 +-
 ogr/ogrsf_frmts/geojson/libjson/json_tokener.h     |    20 +-
 ogr/ogrsf_frmts/geojson/libjson/json_util.c        |    18 +-
 ogr/ogrsf_frmts/geojson/libjson/json_util.h        |     4 +-
 ogr/ogrsf_frmts/geojson/libjson/linkhash.c         |     2 +-
 ogr/ogrsf_frmts/geojson/libjson/linkhash.h         |    10 +-
 ogr/ogrsf_frmts/geojson/libjson/makefile.vc        |     5 +-
 ogr/ogrsf_frmts/geojson/libjson/printbuf.c         |    10 +-
 ogr/ogrsf_frmts/geojson/libjson/printbuf.h         |     6 +-
 ogr/ogrsf_frmts/geojson/ogr_geojson.h              |    73 +-
 ogr/ogrsf_frmts/geojson/ogresrijsonreader.cpp      |   234 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsondatasource.cpp   |   336 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsondriver.cpp       |   161 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsonlayer.cpp        |   192 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsonreader.cpp       |   456 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsonreader.h         |    23 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsonutils.cpp        |    67 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsonutils.h          |     5 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsonwritelayer.cpp   |    29 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.cpp       |   586 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.h         |    33 +-
 ogr/ogrsf_frmts/geojson/ogrtopojsonreader.cpp      |    63 +-
 ogr/ogrsf_frmts/geomedia/drv_geomedia.html         |    16 +-
 ogr/ogrsf_frmts/geomedia/ogr_geomedia.h            |    22 +-
 ogr/ogrsf_frmts/geomedia/ogrgeomediadatasource.cpp |    39 +-
 ogr/ogrsf_frmts/geomedia/ogrgeomediadriver.cpp     |    20 +-
 ogr/ogrsf_frmts/geomedia/ogrgeomedialayer.cpp      |    51 +-
 ogr/ogrsf_frmts/geomedia/ogrgeomediatablelayer.cpp |    34 +-
 ogr/ogrsf_frmts/georss/drv_georss.html             |    23 +-
 ogr/ogrsf_frmts/georss/ogr_georss.h                |    26 +-
 ogr/ogrsf_frmts/georss/ogrgeorssdatasource.cpp     |    75 +-
 ogr/ogrsf_frmts/georss/ogrgeorssdriver.cpp         |    39 +-
 ogr/ogrsf_frmts/georss/ogrgeorsslayer.cpp          |   303 +-
 ogr/ogrsf_frmts/gft/drv_gft.html                   |    52 +-
 ogr/ogrsf_frmts/gft/ogr_gft.h                      |    13 +-
 ogr/ogrsf_frmts/gft/ogrgftdatasource.cpp           |    58 +-
 ogr/ogrsf_frmts/gft/ogrgftdriver.cpp               |    14 +-
 ogr/ogrsf_frmts/gft/ogrgftlayer.cpp                |    25 +-
 ogr/ogrsf_frmts/gft/ogrgftresultlayer.cpp          |    18 +-
 ogr/ogrsf_frmts/gft/ogrgfttablelayer.cpp           |    55 +-
 ogr/ogrsf_frmts/gme/GNUmakefile                    |    16 -
 ogr/ogrsf_frmts/gme/makefile.vc                    |    15 -
 ogr/ogrsf_frmts/gme/ogr_gme.h                      |   213 -
 ogr/ogrsf_frmts/gme/ogrgmedatasource.cpp           |   598 -
 ogr/ogrsf_frmts/gme/ogrgmedriver.cpp               |   122 -
 ogr/ogrsf_frmts/gme/ogrgmejson.cpp                 |   550 -
 ogr/ogrsf_frmts/gme/ogrgmejson.h                   |    59 -
 ogr/ogrsf_frmts/gme/ogrgmelayer.cpp                |  1074 -
 ogr/ogrsf_frmts/gml/drv_gml.html                   |    54 +-
 ogr/ogrsf_frmts/gml/gfstemplate.cpp                |    43 +-
 ogr/ogrsf_frmts/gml/gmlfeature.cpp                 |    29 +-
 ogr/ogrsf_frmts/gml/gmlfeatureclass.cpp            |   228 +-
 ogr/ogrsf_frmts/gml/gmlhandler.cpp                 |   152 +-
 ogr/ogrsf_frmts/gml/gmlpropertydefn.cpp            |    35 +-
 ogr/ogrsf_frmts/gml/gmlreader.cpp                  |   298 +-
 ogr/ogrsf_frmts/gml/gmlreader.h                    |   110 +-
 ogr/ogrsf_frmts/gml/gmlreaderp.h                   |   200 +-
 ogr/ogrsf_frmts/gml/gmlreadstate.cpp               |     8 +-
 ogr/ogrsf_frmts/gml/gmlregistry.cpp                |    18 +-
 ogr/ogrsf_frmts/gml/gmlregistry.h                  |    16 +-
 ogr/ogrsf_frmts/gml/gmlutils.cpp                   |    70 +-
 ogr/ogrsf_frmts/gml/gmlutils.h                     |    28 +-
 ogr/ogrsf_frmts/gml/hugefileresolver.cpp           |   673 +-
 ogr/ogrsf_frmts/gml/ogr_gml.h                      |   110 +-
 ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp           |   526 +-
 ogr/ogrsf_frmts/gml/ogrgmldriver.cpp               |    61 +-
 ogr/ogrsf_frmts/gml/ogrgmllayer.cpp                |   120 +-
 ogr/ogrsf_frmts/gml/parsexsd.cpp                   |   135 +-
 ogr/ogrsf_frmts/gml/parsexsd.h                     |    12 +-
 ogr/ogrsf_frmts/gml/resolvexlinks.cpp              |    58 +-
 ogr/ogrsf_frmts/gml/trstring.cpp                   |    42 +-
 ogr/ogrsf_frmts/gml/xercesc_headers.h              |    55 +
 ogr/ogrsf_frmts/gmt/drv_gmt.html                   |    10 +-
 ogr/ogrsf_frmts/gmt/ogr_gmt.h                      |    31 +-
 ogr/ogrsf_frmts/gmt/ogrgmtdatasource.cpp           |    65 +-
 ogr/ogrsf_frmts/gmt/ogrgmtdriver.cpp               |    29 +-
 ogr/ogrsf_frmts/gmt/ogrgmtlayer.cpp                |   324 +-
 ogr/ogrsf_frmts/gpkg/GNUmakefile                   |     2 +-
 ogr/ogrsf_frmts/gpkg/drv_geopackage.html           |     6 +-
 ogr/ogrsf_frmts/gpkg/drv_geopackage_raster.html    |     4 +-
 ogr/ogrsf_frmts/gpkg/gdalgeopackagerasterband.cpp  |   921 +-
 ogr/ogrsf_frmts/gpkg/geopackage_aspatial.md        |     3 +-
 ogr/ogrsf_frmts/gpkg/gpkgmbtilescommon.h           |   153 +
 ogr/ogrsf_frmts/gpkg/ogr_geopackage.h              |   221 +-
 ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp   |   718 +-
 ogr/ogrsf_frmts/gpkg/ogrgeopackagedriver.cpp       |   163 +-
 ogr/ogrsf_frmts/gpkg/ogrgeopackagelayer.cpp        |    65 +-
 ogr/ogrsf_frmts/gpkg/ogrgeopackageselectlayer.cpp  |     9 +-
 ogr/ogrsf_frmts/gpkg/ogrgeopackagetablelayer.cpp   |   523 +-
 ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.cpp      |   223 +-
 ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.h        |    23 +-
 ogr/ogrsf_frmts/gpsbabel/ogr_gpsbabel.h            |     9 +-
 ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldatasource.cpp |   163 +-
 ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldriver.cpp     |    89 +-
 .../gpsbabel/ogrgpsbabelwritedatasource.cpp        |    87 +-
 ogr/ogrsf_frmts/gpx/drv_gpx.html                   |    14 +-
 ogr/ogrsf_frmts/gpx/ogr_gpx.h                      |   101 +-
 ogr/ogrsf_frmts/gpx/ogrgpxdatasource.cpp           |   240 +-
 ogr/ogrsf_frmts/gpx/ogrgpxdriver.cpp               |    43 +-
 ogr/ogrsf_frmts/gpx/ogrgpxlayer.cpp                |   783 +-
 ogr/ogrsf_frmts/grass/drv_grass.html               |    16 +-
 ogr/ogrsf_frmts/grass/ogrgrass.h                   |    28 +-
 ogr/ogrsf_frmts/grass/ogrgrassdatasource.cpp       |    57 +-
 ogr/ogrsf_frmts/grass/ogrgrassdriver.cpp           |    38 +-
 ogr/ogrsf_frmts/grass/ogrgrasslayer.cpp            |   313 +-
 ogr/ogrsf_frmts/gtm/drv_gtm.html                   |     2 +-
 ogr/ogrsf_frmts/gtm/gtm.cpp                        |   376 +-
 ogr/ogrsf_frmts/gtm/gtm.h                          |    48 +-
 ogr/ogrsf_frmts/gtm/gtmtracklayer.cpp              |   117 +-
 ogr/ogrsf_frmts/gtm/gtmwaypointlayer.cpp           |    72 +-
 ogr/ogrsf_frmts/gtm/ogr_gtm.h                      |    32 +-
 ogr/ogrsf_frmts/gtm/ogrgtmdatasource.cpp           |   162 +-
 ogr/ogrsf_frmts/gtm/ogrgtmdriver.cpp               |    35 +-
 ogr/ogrsf_frmts/gtm/ogrgtmlayer.cpp                |    43 +-
 ogr/ogrsf_frmts/htf/drv_htf.html                   |    22 +-
 ogr/ogrsf_frmts/htf/ogr_htf.h                      |    24 +-
 ogr/ogrsf_frmts/htf/ogrhtfdatasource.cpp           |    99 +-
 ogr/ogrsf_frmts/htf/ogrhtfdriver.cpp               |    38 +-
 ogr/ogrsf_frmts/htf/ogrhtflayer.cpp                |   199 +-
 ogr/ogrsf_frmts/idb/drv_idb.html                   |     4 +-
 ogr/ogrsf_frmts/idb/ogr_idb.h                      |    16 +-
 ogr/ogrsf_frmts/idb/ogridbdatasource.cpp           |    34 +-
 ogr/ogrsf_frmts/idb/ogridbdriver.cpp               |    13 +-
 ogr/ogrsf_frmts/idb/ogridblayer.cpp                |    24 +-
 ogr/ogrsf_frmts/idb/ogridbtablelayer.cpp           |    20 +-
 ogr/ogrsf_frmts/idrisi/generate_test_files.c       |     4 +-
 ogr/ogrsf_frmts/idrisi/ogr_idrisi.h                |    14 +-
 ogr/ogrsf_frmts/idrisi/ogridrisidatasource.cpp     |    57 +-
 ogr/ogrsf_frmts/idrisi/ogridrisidriver.cpp         |    19 +-
 ogr/ogrsf_frmts/idrisi/ogridrisilayer.cpp          |   134 +-
 ogr/ogrsf_frmts/ili/drv_ili.html                   |    32 +-
 ogr/ogrsf_frmts/ili/ili1reader.cpp                 |   336 +-
 ogr/ogrsf_frmts/ili/ili1reader.h                   |    18 +-
 ogr/ogrsf_frmts/ili/ili1readerp.h                  |     6 +-
 ogr/ogrsf_frmts/ili/ili2handler.cpp                |    58 +-
 ogr/ogrsf_frmts/ili/ili2reader.cpp                 |    89 +-
 ogr/ogrsf_frmts/ili/ili2reader.h                   |    14 +-
 ogr/ogrsf_frmts/ili/ili2readerp.h                  |    57 +-
 ogr/ogrsf_frmts/ili/imdreader.cpp                  |   209 +-
 ogr/ogrsf_frmts/ili/imdreader.h                    |    86 +-
 ogr/ogrsf_frmts/ili/ogr_ili1.h                     |    15 +-
 ogr/ogrsf_frmts/ili/ogr_ili2.h                     |    22 +-
 ogr/ogrsf_frmts/ili/ogrili1datasource.cpp          |    91 +-
 ogr/ogrsf_frmts/ili/ogrili1driver.cpp              |    61 +-
 ogr/ogrsf_frmts/ili/ogrili1layer.cpp               |   364 +-
 ogr/ogrsf_frmts/ili/ogrili2datasource.cpp          |   141 +-
 ogr/ogrsf_frmts/ili/ogrili2driver.cpp              |    77 +-
 ogr/ogrsf_frmts/ili/ogrili2layer.cpp               |    95 +-
 ogr/ogrsf_frmts/ili/xercesc_headers.h              |    58 +
 ogr/ogrsf_frmts/ingres/drv_ingres.html             |    18 +-
 ogr/ogrsf_frmts/ingres/ogr_ingres.h                |    41 +-
 ogr/ogrsf_frmts/ingres/ogringresdatasource.cpp     |   164 +-
 ogr/ogrsf_frmts/ingres/ogringresdriver.cpp         |    15 +-
 ogr/ogrsf_frmts/ingres/ogringreslayer.cpp          |    60 +-
 ogr/ogrsf_frmts/ingres/ogringresresultlayer.cpp    |    10 +-
 ogr/ogrsf_frmts/ingres/ogringresstatement.cpp      |    88 +-
 ogr/ogrsf_frmts/ingres/ogringrestablelayer.cpp     |   173 +-
 ogr/ogrsf_frmts/jml/drv_jml.html                   |     4 +-
 ogr/ogrsf_frmts/jml/ogr_jml.h                      |    51 +-
 ogr/ogrsf_frmts/jml/ogrjmldataset.cpp              |   128 +-
 ogr/ogrsf_frmts/jml/ogrjmllayer.cpp                |   311 +-
 ogr/ogrsf_frmts/jml/ogrjmlwriterlayer.cpp          |    66 +-
 ogr/ogrsf_frmts/kml/drv_kml.html                   |    26 +-
 ogr/ogrsf_frmts/kml/kml.cpp                        |   197 +-
 ogr/ogrsf_frmts/kml/kml.h                          |     4 +-
 ogr/ogrsf_frmts/kml/kmlnode.cpp                    |   195 +-
 ogr/ogrsf_frmts/kml/kmlnode.h                      |    27 +-
 ogr/ogrsf_frmts/kml/kmlutility.h                   |    13 +-
 ogr/ogrsf_frmts/kml/kmlvector.cpp                  |    61 +-
 ogr/ogrsf_frmts/kml/ogr2kmlgeometry.cpp            |   266 +-
 ogr/ogrsf_frmts/kml/ogr_kml.h                      |    37 +-
 ogr/ogrsf_frmts/kml/ogrkmldatasource.cpp           |    84 +-
 ogr/ogrsf_frmts/kml/ogrkmldriver.cpp               |    64 +-
 ogr/ogrsf_frmts/kml/ogrkmllayer.cpp                |   110 +-
 ogr/ogrsf_frmts/libkml/drv_libkml.html             |   344 +-
 ogr/ogrsf_frmts/libkml/libkml_headers.h            |    50 +
 ogr/ogrsf_frmts/libkml/ogr_libkml.h                |    51 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmldatasource.cpp     |   404 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmldriver.cpp         |    74 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmlfeature.cpp        |    41 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmlfeature.h          |    10 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmlfeaturestyle.cpp   |    77 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmlfield.cpp          |   123 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmlfield.h            |     4 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmlgeometry.cpp       |    98 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmlgeometry.h         |    13 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmllayer.cpp          |   132 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmlstyle.cpp          |   162 +-
 ogr/ogrsf_frmts/makefile.vc                        |    37 +-
 ogr/ogrsf_frmts/mdb/drv_mdb.html                   |     2 +-
 ogr/ogrsf_frmts/mdb/ogr_mdb.h                      |    22 +-
 ogr/ogrsf_frmts/mdb/ogrmdbdatasource.cpp           |    20 +-
 ogr/ogrsf_frmts/mdb/ogrmdbdriver.cpp               |    17 +-
 ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp             |    83 +-
 ogr/ogrsf_frmts/mdb/ogrmdblayer.cpp                |    32 +-
 ogr/ogrsf_frmts/mem/drv_memory.html                |    13 +-
 ogr/ogrsf_frmts/mem/ogr_mem.h                      |    66 +-
 ogr/ogrsf_frmts/mem/ogrmemdatasource.cpp           |    44 +-
 ogr/ogrsf_frmts/mem/ogrmemdriver.cpp               |    32 +-
 ogr/ogrsf_frmts/mem/ogrmemlayer.cpp                |   644 +-
 ogr/ogrsf_frmts/mitab/HISTORY.TXT                  |    12 +-
 ogr/ogrsf_frmts/mitab/README.TXT                   |     4 +-
 ogr/ogrsf_frmts/mitab/drv_mitab.html               |    12 +-
 ogr/ogrsf_frmts/mitab/mitab.h                      |   204 +-
 ogr/ogrsf_frmts/mitab/mitab_bounds.cpp             |     6 +-
 ogr/ogrsf_frmts/mitab/mitab_coordsys.cpp           |    35 +-
 ogr/ogrsf_frmts/mitab/mitab_datfile.cpp            |   254 +-
 ogr/ogrsf_frmts/mitab/mitab_feature.cpp            |   815 +-
 ogr/ogrsf_frmts/mitab/mitab_feature_mif.cpp        |   734 +-
 ogr/ogrsf_frmts/mitab/mitab_geometry.cpp           |   137 +-
 ogr/ogrsf_frmts/mitab/mitab_geometry.h             |    12 +-
 ogr/ogrsf_frmts/mitab/mitab_idfile.cpp             |    44 +-
 ogr/ogrsf_frmts/mitab/mitab_imapinfofile.cpp       |    47 +-
 ogr/ogrsf_frmts/mitab/mitab_indfile.cpp            |   210 +-
 ogr/ogrsf_frmts/mitab/mitab_mapcoordblock.cpp      |   199 +-
 ogr/ogrsf_frmts/mitab/mitab_mapfile.cpp            |   415 +-
 ogr/ogrsf_frmts/mitab/mitab_mapheaderblock.cpp     |    91 +-
 ogr/ogrsf_frmts/mitab/mitab_mapindexblock.cpp      |   185 +-
 ogr/ogrsf_frmts/mitab/mitab_mapobjectblock.cpp     |   349 +-
 ogr/ogrsf_frmts/mitab/mitab_maptoolblock.cpp       |    97 +-
 ogr/ogrsf_frmts/mitab/mitab_middatafile.cpp        |    39 +-
 ogr/ogrsf_frmts/mitab/mitab_miffile.cpp            |   307 +-
 ogr/ogrsf_frmts/mitab/mitab_ogr_datasource.cpp     |    95 +-
 ogr/ogrsf_frmts/mitab/mitab_ogr_driver.cpp         |    82 +-
 ogr/ogrsf_frmts/mitab/mitab_ogr_driver.h           |    18 +-
 ogr/ogrsf_frmts/mitab/mitab_priv.h                 |   266 +-
 ogr/ogrsf_frmts/mitab/mitab_rawbinblock.cpp        |   193 +-
 ogr/ogrsf_frmts/mitab/mitab_spatialref.cpp         |   135 +-
 ogr/ogrsf_frmts/mitab/mitab_tabfile.cpp            |   272 +-
 ogr/ogrsf_frmts/mitab/mitab_tabseamless.cpp        |    48 +-
 ogr/ogrsf_frmts/mitab/mitab_tabview.cpp            |   168 +-
 ogr/ogrsf_frmts/mitab/mitab_tooldef.cpp            |    82 +-
 ogr/ogrsf_frmts/mitab/mitab_utils.cpp              |   119 +-
 ogr/ogrsf_frmts/mitab/mitab_utils.h                |    16 +-
 ogr/ogrsf_frmts/mongodb/GNUmakefile                |    14 +
 ogr/ogrsf_frmts/mongodb/drv_mongodb.html           |   220 +
 ogr/ogrsf_frmts/mongodb/makefile.vc                |    32 +
 ogr/ogrsf_frmts/mongodb/mongocxx_headers.h         |    56 +
 ogr/ogrsf_frmts/mongodb/ogrmongodbdriver.cpp       |  2847 ++
 ogr/ogrsf_frmts/mssqlspatial/GNUmakefile           |     2 +-
 ogr/ogrsf_frmts/mssqlspatial/drv_mssqlspatial.html |    81 +-
 ogr/ogrsf_frmts/mssqlspatial/makefile.vc           |    22 +-
 ogr/ogrsf_frmts/mssqlspatial/ogr_mssqlspatial.h    |   924 +-
 .../mssqlspatial/ogrmssqlgeometryparser.cpp        |    54 +-
 .../mssqlspatial/ogrmssqlgeometrywriter.cpp        |   507 +
 .../mssqlspatial/ogrmssqlspatialdatasource.cpp     |   359 +-
 .../mssqlspatial/ogrmssqlspatialdriver.cpp         |    30 +-
 .../mssqlspatial/ogrmssqlspatiallayer.cpp          |    91 +-
 .../mssqlspatial/ogrmssqlspatialtablelayer.cpp     |  1188 +-
 ogr/ogrsf_frmts/mysql/drv_mysql.html               |   108 +-
 ogr/ogrsf_frmts/mysql/ogr_mysql.h                  |    60 +-
 ogr/ogrsf_frmts/mysql/ogrmysqldatasource.cpp       |   219 +-
 ogr/ogrsf_frmts/mysql/ogrmysqldriver.cpp           |    61 +-
 ogr/ogrsf_frmts/mysql/ogrmysqllayer.cpp            |    41 +-
 ogr/ogrsf_frmts/mysql/ogrmysqlresultlayer.cpp      |    47 +-
 ogr/ogrsf_frmts/mysql/ogrmysqltablelayer.cpp       |   243 +-
 ogr/ogrsf_frmts/nas/GNUmakefile                    |     7 +
 ogr/ogrsf_frmts/nas/makefile.vc                    |     9 +-
 ogr/ogrsf_frmts/nas/nashandler.cpp                 |   220 +-
 ogr/ogrsf_frmts/nas/nasreader.cpp                  |   299 +-
 ogr/ogrsf_frmts/nas/nasreaderp.h                   |    62 +-
 ogr/ogrsf_frmts/nas/ogr_nas.h                      |    15 +-
 ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp           |   136 +-
 ogr/ogrsf_frmts/nas/ogrnasdriver.cpp               |    58 +-
 ogr/ogrsf_frmts/nas/ogrnaslayer.cpp                |   103 +-
 ogr/ogrsf_frmts/nas/ogrnasrelationlayer.cpp        |    47 +-
 ogr/ogrsf_frmts/ntf/README.txt                     |    12 +-
 ogr/ogrsf_frmts/ntf/drv_ntf.html                   |    46 +-
 ogr/ogrsf_frmts/ntf/ntf.h                          |    84 +-
 ogr/ogrsf_frmts/ntf/ntf_codelist.cpp               |    22 +-
 ogr/ogrsf_frmts/ntf/ntf_estlayers.cpp              |   464 +-
 ogr/ogrsf_frmts/ntf/ntf_generic.cpp                |   125 +-
 ogr/ogrsf_frmts/ntf/ntf_raster.cpp                 |    47 +-
 ogr/ogrsf_frmts/ntf/ntfdump.cpp                    |    14 +-
 ogr/ogrsf_frmts/ntf/ntffilereader.cpp              |   431 +-
 ogr/ogrsf_frmts/ntf/ntfrecord.cpp                  |    46 +-
 ogr/ogrsf_frmts/ntf/ntfstroke.cpp                  |    44 +-
 ogr/ogrsf_frmts/ntf/ogrntfdatasource.cpp           |   112 +-
 ogr/ogrsf_frmts/ntf/ogrntfdriver.cpp               |    32 +-
 ogr/ogrsf_frmts/ntf/ogrntffeatureclasslayer.cpp    |    16 +-
 ogr/ogrsf_frmts/ntf/ogrntflayer.cpp                |    18 +-
 ogr/ogrsf_frmts/null/ogrnulldriver.cpp             |    12 +-
 ogr/ogrsf_frmts/oci/drv_oci.html                   |    46 +-
 ogr/ogrsf_frmts/oci/fastload.cpp                   |    63 +-
 ogr/ogrsf_frmts/oci/ocitest.cpp                    |    10 +-
 ogr/ogrsf_frmts/oci/ogr_oci.h                      |    74 +-
 ogr/ogrsf_frmts/oci/ogrocidatasource.cpp           |   147 +-
 ogr/ogrsf_frmts/oci/ogrocidriver.cpp               |    54 +-
 ogr/ogrsf_frmts/oci/ogrocilayer.cpp                |   237 +-
 ogr/ogrsf_frmts/oci/ogrociloaderlayer.cpp          |    95 +-
 ogr/ogrsf_frmts/oci/ogrociselectlayer.cpp          |    22 +-
 ogr/ogrsf_frmts/oci/ogrocisession.cpp              |   120 +-
 ogr/ogrsf_frmts/oci/ogrocistatement.cpp            |    95 +-
 ogr/ogrsf_frmts/oci/ogrocistringbuf.cpp            |    12 +-
 ogr/ogrsf_frmts/oci/ogrocistroke.cpp               |    72 +-
 ogr/ogrsf_frmts/oci/ogrocitablelayer.cpp           |   415 +-
 ogr/ogrsf_frmts/oci/ogrociwritablelayer.cpp        |    74 +-
 ogr/ogrsf_frmts/odbc/drv_odbc.html                 |    22 +-
 ogr/ogrsf_frmts/odbc/ogr_odbc.h                    |    46 +-
 ogr/ogrsf_frmts/odbc/ogrodbcdatasource.cpp         |    69 +-
 ogr/ogrsf_frmts/odbc/ogrodbcdriver.cpp             |    11 +-
 ogr/ogrsf_frmts/odbc/ogrodbclayer.cpp              |    40 +-
 ogr/ogrsf_frmts/odbc/ogrodbctablelayer.cpp         |    65 +-
 ogr/ogrsf_frmts/ods/GNUmakefile                    |     9 +-
 ogr/ogrsf_frmts/ods/drv_ods.html                   |     2 +-
 ogr/ogrsf_frmts/ods/makefile.vc                    |     2 +-
 ogr/ogrsf_frmts/ods/ods_formula.cpp                |    48 +-
 ogr/ogrsf_frmts/ods/ods_formula.h                  |    23 +-
 ogr/ogrsf_frmts/ods/ods_formula_node.cpp           |   323 +-
 ogr/ogrsf_frmts/ods/ods_formula_parser.cpp         |  1855 +-
 ogr/ogrsf_frmts/ods/ods_formula_parser.hpp         |    69 +-
 ogr/ogrsf_frmts/ods/ods_formula_parser.y           |    18 +-
 ogr/ogrsf_frmts/ods/ogr_ods.h                      |    43 +-
 ogr/ogrsf_frmts/ods/ogrodsdatasource.cpp           |   660 +-
 ogr/ogrsf_frmts/ods/ogrodsdriver.cpp               |    71 +-
 ogr/ogrsf_frmts/ogdi/drv_ogdi.html                 |    10 +-
 ogr/ogrsf_frmts/ogdi/ogrogdi.h                     |    20 +-
 ogr/ogrsf_frmts/ogdi/ogrogdidatasource.cpp         |    26 +-
 ogr/ogrsf_frmts/ogdi/ogrogdidriver.cpp             |    21 +-
 ogr/ogrsf_frmts/ogdi/ogrogdilayer.cpp              |    44 +-
 ogr/ogrsf_frmts/ogr_attrind.h                      |    10 +-
 ogr/ogrsf_frmts/ogr_formats.html                   |    53 +-
 ogr/ogrsf_frmts/ogrsf_frmts.dox                    |   132 +-
 ogr/ogrsf_frmts/ogrsf_frmts.h                      |   114 +-
 ogr/ogrsf_frmts/openair/drv_openair.html           |    12 +-
 ogr/ogrsf_frmts/openair/ogr_openair.h              |    24 +-
 ogr/ogrsf_frmts/openair/ogropenairdatasource.cpp   |    58 +-
 ogr/ogrsf_frmts/openair/ogropenairdriver.cpp       |    69 +-
 ogr/ogrsf_frmts/openair/ogropenairlabellayer.cpp   |    51 +-
 ogr/ogrsf_frmts/openair/ogropenairlayer.cpp        |   186 +-
 ogr/ogrsf_frmts/openfilegdb/drv_openfilegdb.html   |    10 +-
 ogr/ogrsf_frmts/openfilegdb/filegdbindex.cpp       |   164 +-
 ogr/ogrsf_frmts/openfilegdb/filegdbtable.cpp       |   309 +-
 ogr/ogrsf_frmts/openfilegdb/filegdbtable.h         |    20 +-
 ogr/ogrsf_frmts/openfilegdb/filegdbtable_priv.h    |     8 +-
 ogr/ogrsf_frmts/openfilegdb/ogr_openfilegdb.h      |    23 +-
 .../openfilegdb/ogropenfilegdbdatasource.cpp       |   201 +-
 .../openfilegdb/ogropenfilegdbdriver.cpp           |   123 +-
 .../openfilegdb/ogropenfilegdblayer.cpp            |   318 +-
 ogr/ogrsf_frmts/osm/drv_osm.html                   |    18 +-
 ogr/ogrsf_frmts/osm/gpb.h                          |    44 +-
 ogr/ogrsf_frmts/osm/ogr_osm.h                      |   186 +-
 ogr/ogrsf_frmts/osm/ogrosmdatasource.cpp           |  1451 +-
 ogr/ogrsf_frmts/osm/ogrosmdriver.cpp               |    71 +-
 ogr/ogrsf_frmts/osm/ogrosmlayer.cpp                |   170 +-
 ogr/ogrsf_frmts/osm/osm2osm.c                      |     8 +-
 ogr/ogrsf_frmts/osm/osm_parser.cpp                 |   293 +-
 ogr/ogrsf_frmts/osm/osm_parser.h                   |     8 +-
 ogr/ogrsf_frmts/pds/ogr_pds.h                      |    18 +-
 ogr/ogrsf_frmts/pds/ogrpdsdatasource.cpp           |   119 +-
 ogr/ogrsf_frmts/pds/ogrpdsdriver.cpp               |    38 +-
 ogr/ogrsf_frmts/pds/ogrpdslayer.cpp                |   123 +-
 ogr/ogrsf_frmts/pg/drv_pg.html                     |    64 +-
 ogr/ogrsf_frmts/pg/drv_pg_advanced.html            |    12 +-
 ogr/ogrsf_frmts/pg/ogr_pg.h                        |    66 +-
 ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp             |   497 +-
 ogr/ogrsf_frmts/pg/ogrpgdriver.cpp                 |    68 +-
 ogr/ogrsf_frmts/pg/ogrpglayer.cpp                  |   234 +-
 ogr/ogrsf_frmts/pg/ogrpgresultlayer.cpp            |    30 +-
 ogr/ogrsf_frmts/pg/ogrpgtablelayer.cpp             |   502 +-
 ogr/ogrsf_frmts/pg/ogrpgutility.cpp                |     8 +-
 ogr/ogrsf_frmts/pgdump/drv_pgdump.html             |    22 +-
 ogr/ogrsf_frmts/pgdump/ogr_pgdump.h                |    30 +-
 ogr/ogrsf_frmts/pgdump/ogrpgdumpdatasource.cpp     |   119 +-
 ogr/ogrsf_frmts/pgdump/ogrpgdumpdriver.cpp         |    60 +-
 ogr/ogrsf_frmts/pgdump/ogrpgdumplayer.cpp          |   308 +-
 ogr/ogrsf_frmts/pgeo/drv_pgeo.html                 |    18 +-
 ogr/ogrsf_frmts/pgeo/ogr_pgeo.h                    |    26 +-
 ogr/ogrsf_frmts/pgeo/ogrpgeodatasource.cpp         |    66 +-
 ogr/ogrsf_frmts/pgeo/ogrpgeodriver.cpp             |    53 +-
 ogr/ogrsf_frmts/pgeo/ogrpgeolayer.cpp              |    71 +-
 ogr/ogrsf_frmts/pgeo/ogrpgeoselectlayer.cpp        |    10 +-
 ogr/ogrsf_frmts/pgeo/ogrpgeotablelayer.cpp         |    42 +-
 ogr/ogrsf_frmts/plscenes/GNUmakefile               |     2 +-
 ogr/ogrsf_frmts/plscenes/drv_plscenes.html         |   220 +-
 ogr/ogrsf_frmts/plscenes/makefile.vc               |     2 +-
 ogr/ogrsf_frmts/plscenes/ogr_plscenes.h            |   171 +-
 ogr/ogrsf_frmts/plscenes/ogrplscenesdataset.cpp    |   126 +-
 ogr/ogrsf_frmts/plscenes/ogrplscenesdriver.cpp     |   100 +
 ogr/ogrsf_frmts/plscenes/ogrplsceneslayer.cpp      |    34 +-
 ogr/ogrsf_frmts/plscenes/ogrplscenesv1dataset.cpp  |   669 +
 ogr/ogrsf_frmts/plscenes/ogrplscenesv1layer.cpp    |  1454 +
 ogr/ogrsf_frmts/rec/ll_recio.cpp                   |    36 +-
 ogr/ogrsf_frmts/rec/ogr_rec.h                      |    16 +-
 ogr/ogrsf_frmts/rec/ogrrecdatasource.cpp           |    35 +-
 ogr/ogrsf_frmts/rec/ogrrecdriver.cpp               |    31 +-
 ogr/ogrsf_frmts/rec/ogrreclayer.cpp                |    92 +-
 ogr/ogrsf_frmts/s57/ddfrecordindex.cpp             |    99 +-
 ogr/ogrsf_frmts/s57/drv_s57.html                   |    61 +-
 ogr/ogrsf_frmts/s57/ogr_s57.h                      |    22 +-
 ogr/ogrsf_frmts/s57/ogrs57datasource.cpp           |   314 +-
 ogr/ogrsf_frmts/s57/ogrs57driver.cpp               |   153 +-
 ogr/ogrsf_frmts/s57/ogrs57layer.cpp                |    96 +-
 ogr/ogrsf_frmts/s57/s57.h                          |    38 +-
 ogr/ogrsf_frmts/s57/s57classregistrar.cpp          |   141 +-
 ogr/ogrsf_frmts/s57/s57dump.cpp                    |    88 +-
 ogr/ogrsf_frmts/s57/s57featuredefns.cpp            |   133 +-
 ogr/ogrsf_frmts/s57/s57filecollector.cpp           |    53 +-
 ogr/ogrsf_frmts/s57/s57reader.cpp                  |  1258 +-
 ogr/ogrsf_frmts/s57/s57tables.h                    |     8 +-
 ogr/ogrsf_frmts/s57/s57tables.py                   |    29 +-
 ogr/ogrsf_frmts/s57/s57writer.cpp                  |   217 +-
 ogr/ogrsf_frmts/sde/drv_sde.html                   |    68 +-
 ogr/ogrsf_frmts/sde/ogr_sde.h                      |    50 +-
 ogr/ogrsf_frmts/sde/ogrsdedatasource.cpp           |   376 +-
 ogr/ogrsf_frmts/sde/ogrsdedriver.cpp               |    16 +-
 ogr/ogrsf_frmts/sde/ogrsdelayer.cpp                |   618 +-
 ogr/ogrsf_frmts/sdts/drv_sdts.html                 |     4 +-
 ogr/ogrsf_frmts/sdts/ogr_sdts.h                    |    18 +-
 ogr/ogrsf_frmts/sdts/ogrsdtsdatasource.cpp         |    24 +-
 ogr/ogrsf_frmts/sdts/ogrsdtsdriver.cpp             |    28 +-
 ogr/ogrsf_frmts/sdts/ogrsdtslayer.cpp              |    50 +-
 ogr/ogrsf_frmts/segukooa/ogr_segukooa.h            |     8 +-
 ogr/ogrsf_frmts/segukooa/ogrsegukooadatasource.cpp |     6 +-
 ogr/ogrsf_frmts/segukooa/ogrsegukooadriver.cpp     |    29 +-
 ogr/ogrsf_frmts/segukooa/ogrsegukooalayer.cpp      |    70 +-
 ogr/ogrsf_frmts/segy/ogr_segy.h                    |     8 +-
 ogr/ogrsf_frmts/segy/ogrsegydriver.cpp             |    36 +-
 ogr/ogrsf_frmts/segy/ogrsegylayer.cpp              |    16 +-
 ogr/ogrsf_frmts/selafin/GNUmakefile                |     3 +
 ogr/ogrsf_frmts/selafin/drv_selafin.html           |     8 +-
 ogr/ogrsf_frmts/selafin/io_selafin.cpp             |   256 +-
 ogr/ogrsf_frmts/selafin/io_selafin.h               |    62 +-
 ogr/ogrsf_frmts/selafin/ogr_selafin.h              |    32 +-
 ogr/ogrsf_frmts/selafin/ogrselafindatasource.cpp   |   153 +-
 ogr/ogrsf_frmts/selafin/ogrselafindriver.cpp       |    52 +-
 ogr/ogrsf_frmts/selafin/ogrselafinlayer.cpp        |   167 +-
 ogr/ogrsf_frmts/shape/GNUmakefile                  |     2 +-
 ogr/ogrsf_frmts/shape/dbfopen.c                    |   168 +-
 ogr/ogrsf_frmts/shape/drv_shapefile.html           |    77 +-
 ogr/ogrsf_frmts/shape/ogrshape.h                   |    37 +-
 ogr/ogrsf_frmts/shape/ogrshapedatasource.cpp       |   197 +-
 ogr/ogrsf_frmts/shape/ogrshapedriver.cpp           |   122 +-
 ogr/ogrsf_frmts/shape/ogrshapelayer.cpp            |   393 +-
 ogr/ogrsf_frmts/shape/sbnsearch.c                  |    27 +-
 ogr/ogrsf_frmts/shape/shape2ogr.cpp                |   461 +-
 ogr/ogrsf_frmts/shape/shapefil.h                   |    62 +-
 ogr/ogrsf_frmts/shape/shp_vsi.c                    |     8 +-
 ogr/ogrsf_frmts/shape/shpopen.c                    |   387 +-
 ogr/ogrsf_frmts/shape/shptree.c                    |   176 +-
 ogr/ogrsf_frmts/sosi/fyba_melding.cpp              |     9 +-
 ogr/ogrsf_frmts/sosi/ogr_sosi.h                    |    12 +-
 ogr/ogrsf_frmts/sosi/ogrsosidatasource.cpp         |   122 +-
 ogr/ogrsf_frmts/sosi/ogrsosidriver.cpp             |    29 +-
 ogr/ogrsf_frmts/sosi/ogrsosilayer.cpp              |    38 +-
 ogr/ogrsf_frmts/sqlite/GNUmakefile                 |     4 +
 ogr/ogrsf_frmts/sqlite/drv_sqlite.html             |    52 +-
 ogr/ogrsf_frmts/sqlite/ogr_sqlite.h                |    88 +-
 ogr/ogrsf_frmts/sqlite/ogrsqlite3ext.h             |    14 +-
 ogr/ogrsf_frmts/sqlite/ogrsqliteapiroutines.c      |     6 +-
 ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp     |   358 +-
 ogr/ogrsf_frmts/sqlite/ogrsqlitedriver.cpp         |   110 +-
 ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.cpp     |   124 +-
 ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.h       |     8 +-
 ogr/ogrsf_frmts/sqlite/ogrsqlitelayer.cpp          |   616 +-
 ogr/ogrsf_frmts/sqlite/ogrsqliteregexp.cpp         |    18 +-
 ogr/ogrsf_frmts/sqlite/ogrsqliteregexp.h           |     8 +-
 ogr/ogrsf_frmts/sqlite/ogrsqliteselectlayer.cpp    |    39 +-
 .../sqlite/ogrsqlitesinglefeaturelayer.cpp         |    12 +-
 ogr/ogrsf_frmts/sqlite/ogrsqlitesqlfunctions.cpp   |    42 +-
 ogr/ogrsf_frmts/sqlite/ogrsqlitesqlfunctions.h     |     8 +-
 ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp     |   443 +-
 ogr/ogrsf_frmts/sqlite/ogrsqlitevfs.cpp            |    77 +-
 ogr/ogrsf_frmts/sqlite/ogrsqliteviewlayer.cpp      |    58 +-
 ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.cpp     |   136 +-
 ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.h       |     8 +-
 ogr/ogrsf_frmts/sqlite/test_load_virtual_ogr.c     |     6 +-
 ogr/ogrsf_frmts/sua/drv_sua.html                   |     2 +-
 ogr/ogrsf_frmts/sua/ogr_sua.h                      |     8 +-
 ogr/ogrsf_frmts/sua/ogrsuadriver.cpp               |    31 +-
 ogr/ogrsf_frmts/sua/ogrsualayer.cpp                |    28 +-
 ogr/ogrsf_frmts/svg/ogr_svg.h                      |    19 +-
 ogr/ogrsf_frmts/svg/ogrsvgdatasource.cpp           |    35 +-
 ogr/ogrsf_frmts/svg/ogrsvgdriver.cpp               |    34 +-
 ogr/ogrsf_frmts/svg/ogrsvglayer.cpp                |    75 +-
 ogr/ogrsf_frmts/sxf/ogr_sxf.h                      |    16 +-
 ogr/ogrsf_frmts/sxf/ogrsxfdatasource.cpp           |   134 +-
 ogr/ogrsf_frmts/sxf/ogrsxfdriver.cpp               |    13 +-
 ogr/ogrsf_frmts/sxf/ogrsxflayer.cpp                |    99 +-
 ogr/ogrsf_frmts/sxf/org_sxf_defs.h                 |    84 +-
 ogr/ogrsf_frmts/tiger/drv_tiger.html               |    60 +-
 ogr/ogrsf_frmts/tiger/ogr_tiger.h                  |     8 +-
 ogr/ogrsf_frmts/tiger/ogrtigerdatasource.cpp       |   216 +-
 ogr/ogrsf_frmts/tiger/ogrtigerdriver.cpp           |    37 +-
 ogr/ogrsf_frmts/tiger/ogrtigerlayer.cpp            |    16 +-
 ogr/ogrsf_frmts/tiger/tigeraltname.cpp             |     8 +-
 ogr/ogrsf_frmts/tiger/tigercompletechain.cpp       |    94 +-
 ogr/ogrsf_frmts/tiger/tigerfilebase.cpp            |   148 +-
 ogr/ogrsf_frmts/tiger/tigerinfo.cpp                |    21 +-
 ogr/ogrsf_frmts/tiger/tigerlandmarks.cpp           |     6 +-
 ogr/ogrsf_frmts/tiger/tigeroverunder.cpp           |     6 +-
 ogr/ogrsf_frmts/tiger/tigerpip.cpp                 |     6 +-
 ogr/ogrsf_frmts/tiger/tigerpoint.cpp               |    14 +-
 ogr/ogrsf_frmts/tiger/tigerpolygon.cpp             |    33 +-
 ogr/ogrsf_frmts/tiger/tigerpolygoneconomic.cpp     |     8 +-
 ogr/ogrsf_frmts/vdv/GNUmakefile                    |    14 +
 ogr/ogrsf_frmts/vdv/drv_vdv.html                   |    80 +
 ogr/ogrsf_frmts/vdv/makefile.vc                    |    15 +
 ogr/ogrsf_frmts/vdv/ogr_vdv.h                      |   219 +
 ogr/ogrsf_frmts/vdv/ogrvdvdatasource.cpp           |  1863 ++
 ogr/ogrsf_frmts/vfk/drv_vfk.html                   |    16 +-
 ogr/ogrsf_frmts/vfk/ogr_vfk.h                      |    16 +-
 ogr/ogrsf_frmts/vfk/ogrvfkdatasource.cpp           |    48 +-
 ogr/ogrsf_frmts/vfk/ogrvfkdriver.cpp               |    36 +-
 ogr/ogrsf_frmts/vfk/ogrvfklayer.cpp                |    65 +-
 ogr/ogrsf_frmts/vfk/vfkdatablock.cpp               |   345 +-
 ogr/ogrsf_frmts/vfk/vfkdatablocksqlite.cpp         |   267 +-
 ogr/ogrsf_frmts/vfk/vfkfeature.cpp                 |   127 +-
 ogr/ogrsf_frmts/vfk/vfkfeaturesqlite.cpp           |    30 +-
 ogr/ogrsf_frmts/vfk/vfkproperty.cpp                |    10 +-
 ogr/ogrsf_frmts/vfk/vfkpropertydefn.cpp            |    10 +-
 ogr/ogrsf_frmts/vfk/vfkreader.cpp                  |   171 +-
 ogr/ogrsf_frmts/vfk/vfkreader.h                    |    43 +-
 ogr/ogrsf_frmts/vfk/vfkreaderp.h                   |    14 +-
 ogr/ogrsf_frmts/vfk/vfkreadersqlite.cpp            |   199 +-
 ogr/ogrsf_frmts/vrt/drv_vrt.html                   |    58 +-
 ogr/ogrsf_frmts/vrt/ogr_vrt.h                      |    34 +-
 ogr/ogrsf_frmts/vrt/ogrvrtdatasource.cpp           |   164 +-
 ogr/ogrsf_frmts/vrt/ogrvrtdriver.cpp               |    51 +-
 ogr/ogrsf_frmts/vrt/ogrvrtlayer.cpp                |   418 +-
 ogr/ogrsf_frmts/walk/drv_walk.html                 |     8 +-
 ogr/ogrsf_frmts/walk/ogis_geometry_wkb_struct.h    |    18 +-
 ogr/ogrsf_frmts/walk/ogrwalk.h                     |    27 +-
 ogr/ogrsf_frmts/walk/ogrwalkdatasource.cpp         |    43 +-
 ogr/ogrsf_frmts/walk/ogrwalkdriver.cpp             |    10 +-
 ogr/ogrsf_frmts/walk/ogrwalklayer.cpp              |    38 +-
 ogr/ogrsf_frmts/walk/ogrwalktablelayer.cpp         |    40 +-
 ogr/ogrsf_frmts/walk/ogrwalktool.cpp               |   146 +-
 ogr/ogrsf_frmts/wasp/GNUmakefile                   |     1 -
 ogr/ogrsf_frmts/wasp/drv_wasp.html                 |    10 +-
 ogr/ogrsf_frmts/wasp/ogrwasp.h                     |    48 +-
 ogr/ogrsf_frmts/wasp/ogrwaspdatasource.cpp         |    84 +-
 ogr/ogrsf_frmts/wasp/ogrwaspdriver.cpp             |    16 +-
 ogr/ogrsf_frmts/wasp/ogrwasplayer.cpp              |   122 +-
 ogr/ogrsf_frmts/wfs/drv_wfs.html                   |    23 +-
 ogr/ogrsf_frmts/wfs/ogr_wfs.h                      |    36 +-
 ogr/ogrsf_frmts/wfs/ogrwfsdatasource.cpp           |   219 +-
 ogr/ogrsf_frmts/wfs/ogrwfsdriver.cpp               |    37 +-
 ogr/ogrsf_frmts/wfs/ogrwfsfilter.cpp               |    20 +-
 ogr/ogrsf_frmts/wfs/ogrwfsjoinlayer.cpp            |    43 +-
 ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp                |   175 +-
 ogr/ogrsf_frmts/xls/drv_xls.html                   |     4 +-
 ogr/ogrsf_frmts/xls/ogr_xls.h                      |     8 +-
 ogr/ogrsf_frmts/xls/ogrxlsdatasource.cpp           |     8 +-
 ogr/ogrsf_frmts/xls/ogrxlsdriver.cpp               |    14 +-
 ogr/ogrsf_frmts/xls/ogrxlslayer.cpp                |     6 +-
 ogr/ogrsf_frmts/xlsx/drv_xlsx.html                 |     2 +-
 ogr/ogrsf_frmts/xlsx/ogr_xlsx.h                    |    24 +-
 ogr/ogrsf_frmts/xlsx/ogrxlsxdatasource.cpp         |   161 +-
 ogr/ogrsf_frmts/xlsx/ogrxlsxdriver.cpp             |    19 +-
 ogr/ogrsf_frmts/xplane/drv_xplane.html             |    50 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane.h                |    14 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.cpp   |   896 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.h     |     8 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.cpp   |    47 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.h     |     4 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.cpp   |     4 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.h     |     4 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_geo_utils.cpp    |     7 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_geo_utils.h      |     6 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.cpp   |     6 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.h     |    10 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_reader.cpp       |    19 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_reader.h         |     4 +-
 ogr/ogrsf_frmts/xplane/ogrxplanedatasource.cpp     |    13 +-
 ogr/ogrsf_frmts/xplane/ogrxplanedriver.cpp         |    12 +-
 ogr/ogrsf_frmts/xplane/ogrxplanelayer.cpp          |    26 +-
 ogr/ogrsf_frmts/xplane/test_geo_utils.cpp          |     4 +-
 ogr/ogrspatialreference.cpp                        |  2345 +-
 ogr/ogrsurface.cpp                                 |    12 +-
 ogr/ogrutils.cpp                                   |   735 +-
 ogr/osr_cs_wkt.c                                   |    15 +-
 ogr/osr_cs_wkt.h                                   |     8 +-
 ogr/osr_cs_wkt_parser.c                            |    10 +-
 ogr/osr_tutorial.dox                               |     6 +-
 ogr/swq.cpp                                        |   132 +-
 ogr/swq.h                                          |    53 +-
 ogr/swq_expr_node.cpp                              |   100 +-
 ogr/swq_op_general.cpp                             |   207 +-
 ogr/swq_op_registrar.cpp                           |     4 +-
 ogr/swq_parser.cpp                                 |    48 +-
 ogr/swq_parser.y                                   |    70 +-
 ogr/swq_select.cpp                                 |   253 +-
 port/GNUmakefile                                   |    23 +-
 port/cpl_atomic_ops.cpp                            |    76 +-
 port/cpl_atomic_ops.h                              |    37 +-
 port/cpl_aws.cpp                                   |   643 +
 port/cpl_aws.h                                     |   136 +
 port/cpl_base64.cpp                                |   149 +-
 port/cpl_config.h.in                               |    15 +-
 port/cpl_config.h.vc                               |     4 +-
 port/cpl_config.h.wince                            |   161 -
 port/cpl_conv.cpp                                  |  1102 +-
 port/cpl_conv.h                                    |    89 +-
 port/cpl_csv.cpp                                   |   664 +-
 port/cpl_csv.h                                     |    13 +-
 port/cpl_error.cpp                                 |   466 +-
 port/cpl_error.h                                   |   110 +-
 port/cpl_findfile.cpp                              |    89 +-
 port/cpl_getexecpath.cpp                           |    35 +-
 port/cpl_google_oauth2.cpp                         |    78 +-
 port/cpl_hash_set.cpp                              |   221 +-
 port/cpl_hash_set.h                                |    18 +-
 port/cpl_http.cpp                                  |   157 +-
 port/cpl_http.h                                    |    18 +-
 port/cpl_list.cpp                                  |   153 +-
 port/cpl_list.h                                    |    26 +-
 port/cpl_minixml.cpp                               |   802 +-
 port/cpl_minixml.h                                 |   113 +-
 port/cpl_minizip_ioapi.cpp                         |    64 +-
 port/cpl_minizip_ioapi.h                           |    24 +-
 port/cpl_minizip_unzip.cpp                         |   197 +-
 port/cpl_minizip_unzip.h                           |   104 +-
 port/cpl_minizip_zip.cpp                           |   297 +-
 port/cpl_minizip_zip.h                             |   118 +-
 port/cpl_multiproc.cpp                             |   601 +-
 port/cpl_multiproc.h                               |    74 +-
 port/cpl_odbc.cpp                                  |   293 +-
 port/cpl_odbc.h                                    |    53 +-
 port/cpl_path.cpp                                  |   447 +-
 port/cpl_port.h                                    |   474 +-
 port/cpl_progress.cpp                              |    48 +-
 port/cpl_quad_tree.cpp                             |   240 +-
 port/cpl_quad_tree.h                               |    12 +-
 port/cpl_recode.cpp                                |   100 +-
 port/cpl_recode_iconv.cpp                          |    59 +-
 port/cpl_recode_stub.cpp                           |   228 +-
 port/cpl_sha256.cpp                                |   472 +
 port/cpl_sha256.h                                  |    68 +
 port/cpl_spawn.cpp                                 |   203 +-
 port/cpl_spawn.h                                   |     9 +-
 port/cpl_string.cpp                                |  1362 +-
 port/cpl_string.h                                  |   225 +-
 port/cpl_strtod.cpp                                |   129 +-
 port/cpl_time.cpp                                  |   333 +-
 port/cpl_time.h                                    |    82 +-
 port/cpl_virtualmem.cpp                            |  1178 +-
 port/cpl_virtualmem.h                              |    23 +-
 port/cpl_vsi.h                                     |   123 +-
 port/cpl_vsi_error.cpp                             |   295 +
 port/cpl_vsi_error.h                               |    67 +
 port/cpl_vsi_mem.cpp                               |   323 +-
 port/cpl_vsi_virtual.h                             |    52 +-
 port/cpl_vsil.cpp                                  |   447 +-
 port/cpl_vsil_abstract_archive.cpp                 |    91 +-
 port/cpl_vsil_buffered_reader.cpp                  |    86 +-
 port/cpl_vsil_cache.cpp                            |   141 +-
 port/cpl_vsil_crypt.cpp                            |  1934 ++
 port/cpl_vsil_curl.cpp                             |  2102 +-
 port/cpl_vsil_curl_priv.h                          |     4 +-
 port/cpl_vsil_curl_streaming.cpp                   |   553 +-
 port/cpl_vsil_gzip.cpp                             |   600 +-
 port/cpl_vsil_sparsefile.cpp                       |   111 +-
 port/cpl_vsil_stdin.cpp                            |    34 +-
 port/cpl_vsil_stdout.cpp                           |    68 +-
 port/cpl_vsil_subfile.cpp                          |    85 +-
 port/cpl_vsil_tar.cpp                              |   231 +-
 port/cpl_vsil_unix_stdio_64.cpp                    |   296 +-
 port/cpl_vsil_win32.cpp                            |   417 +-
 port/cpl_vsisimple.cpp                             |   460 +-
 port/cpl_win32ce_api.cpp                           |   130 -
 port/cpl_win32ce_api.h                             |   105 -
 port/cpl_wince.h                                   |    44 -
 port/cpl_worker_thread_pool.cpp                    |   468 +
 port/cpl_worker_thread_pool.h                      |   103 +
 port/cpl_xml_validate.cpp                          |   143 +-
 port/cplgetsymbol.cpp                              |    85 +-
 port/cplkeywordparser.cpp                          |    91 +-
 port/cplkeywordparser.h                            |     6 +-
 port/cplstring.cpp                                 |    78 +-
 port/cplstringlist.cpp                             |  1581 +-
 port/gdal_csv.h                                    |     4 +-
 port/makefile.vc                                   |    15 +-
 port/vsipreload.cpp                                |    90 +-
 port/xmlreformat.cpp                               |    16 +-
 scripts/GNUmakefile                                |    10 +
 scripts/check_broken_links.py                      |    87 +
 scripts/completionFinder.py                        |   287 +
 scripts/fix_typos.sh                               |    66 +
 scripts/gdal-bash-completion.sh                    |   722 +
 scripts/typos_whitelist.txt                        |    39 +
 scripts/vce2008_wine/nmake_vce2008.local           |     4 +-
 swig/GNUmakefile                                   |     2 +-
 swig/SWIGmake.base                                 |     5 +-
 swig/csharp/const/GdalConst.cs                     |     1 +
 swig/csharp/const/GdalConstPINVOKE.cs              |     3 +
 swig/csharp/const/gdalconst_wrap.c                 |    10 +
 swig/csharp/csharp.opt                             |     4 +-
 swig/csharp/gdal/AsyncReader.cs                    |     2 +-
 swig/csharp/gdal/Band.cs                           |    20 +-
 swig/csharp/gdal/ColorEntry.cs                     |     2 +-
 swig/csharp/gdal/ColorTable.cs                     |     2 +-
 swig/csharp/gdal/Dataset.cs                        |    42 +-
 swig/csharp/gdal/GCP.cs                            |     2 +-
 swig/csharp/gdal/GDALBuildVRTOptions.cs            |    77 +
 swig/csharp/gdal/GDALDEMProcessingOptions.cs       |    77 +
 swig/csharp/gdal/GDALGridOptions.cs                |    77 +
 swig/csharp/gdal/GDALInfoOptions.cs                |    77 +
 swig/csharp/gdal/GDALNearblackOptions.cs           |    77 +
 swig/csharp/gdal/GDALRasterizeOptions.cs           |    77 +
 swig/csharp/gdal/GDALTranslateOptions.cs           |    77 +
 swig/csharp/gdal/GDALVectorTranslateOptions.cs     |    77 +
 swig/csharp/gdal/GDALWarpAppOptions.cs             |    77 +
 swig/csharp/gdal/Gdal.cs                           |   203 +-
 swig/csharp/gdal/GdalPINVOKE.cs                    |   123 +-
 swig/csharp/gdal/MajorObject.cs                    |     6 +-
 swig/csharp/gdal/RasterAttributeTable.cs           |     2 +-
 swig/csharp/gdal/SWIGTYPE_p_p_GDALDatasetShadow.cs |    30 +
 swig/csharp/gdal/Transformer.cs                    |     2 +-
 swig/csharp/gdal/XMLNode.cs                        |     2 +-
 swig/csharp/gdal/gdal_wrap.cpp                     |  2220 +-
 swig/csharp/ogr/CoordinateTransformation.cs        |     2 +-
 swig/csharp/ogr/DataSource.cs                      |     2 +-
 swig/csharp/ogr/Driver.cs                          |     2 +-
 swig/csharp/ogr/Envelope.cs                        |     2 +-
 swig/csharp/ogr/Envelope3D.cs                      |     2 +-
 swig/csharp/ogr/Feature.cs                         |    37 +-
 swig/csharp/ogr/FeatureDefn.cs                     |     2 +-
 swig/csharp/ogr/FieldDefn.cs                       |     2 +-
 swig/csharp/ogr/GeomFieldDefn.cs                   |     2 +-
 swig/csharp/ogr/Geometry.cs                        |    82 +-
 swig/csharp/ogr/Layer.cs                           |     2 +-
 swig/csharp/ogr/Ogr.cs                             |    28 +-
 swig/csharp/ogr/OgrPINVOKE.cs                      |    67 +-
 swig/csharp/ogr/Osr.cs                             |    23 +-
 swig/csharp/ogr/SpatialReference.cs                |     2 +-
 swig/csharp/ogr/StyleTable.cs                      |     2 +-
 swig/csharp/ogr/ogr_wrap.cpp                       |   955 +-
 swig/csharp/ogr/osr_wrap.cpp                       |    77 +-
 swig/csharp/ogr/wkbGeometryType.cs                 |    40 +
 swig/csharp/osr/CoordinateTransformation.cs        |     2 +-
 swig/csharp/osr/Osr.cs                             |    23 +-
 swig/csharp/osr/SpatialReference.cs                |     2 +-
 swig/csharp/osr/osr_wrap.cpp                       |    77 +-
 swig/include/Band.i                                |   155 +-
 swig/include/ColorTable.i                          |    22 +-
 swig/include/Dataset.i                             |   194 +-
 swig/include/Driver.i                              |    42 +-
 swig/include/MajorObject.i                         |     6 +-
 swig/include/Operations.i                          |   148 +-
 swig/include/README.typemaps                       |    16 +-
 swig/include/RasterAttributeTable.i                |    32 +-
 swig/include/Transform.i                           |     8 +-
 swig/include/XMLNode.i                             |    70 +-
 swig/include/cpl.i                                 |   102 +-
 swig/include/cpl_exceptions.i                      |    17 +-
 swig/include/cplvirtualmem.i                       |     4 +-
 swig/include/csharp/gdal_csharp.i                  |    44 +-
 swig/include/csharp/gdal_csharp_extend.i           |    34 +-
 swig/include/csharp/ogr_csharp.i                   |    20 +-
 swig/include/csharp/ogr_csharp_extend.i            |     8 +-
 swig/include/csharp/osr_csharp.i                   |     4 +-
 swig/include/csharp/swig_csharp_extensions.i       |    16 +-
 swig/include/csharp/typemaps_csharp.i              |    66 +-
 swig/include/gdal.i                                |   696 +-
 swig/include/gdal_array.i                          |  2617 +-
 swig/include/gdalconst.i                           |     9 +-
 swig/include/gnm.i                                 |   384 +
 swig/include/java/callback.i                       |     2 -
 swig/include/java/gdal_java.i                      |    91 +-
 swig/include/java/gdalconst_java.i                 |    13 +-
 swig/include/java/java_exceptions.i                |     4 +-
 swig/include/java/ogr_java.i                       |    30 +-
 swig/include/java/ogr_java_extend.i                |     6 +-
 swig/include/java/osr_java.i                       |    27 +-
 swig/include/java/typemaps_java.i                  |   121 +-
 swig/include/ogr.i                                 |   892 +-
 swig/include/ogr_error_map.i                       |     6 +-
 swig/include/osr.i                                 |   111 +-
 swig/include/perl/callback.i                       |    19 +-
 swig/include/perl/confess.i                        |    33 +
 swig/include/perl/destroy.i                        |    17 +-
 swig/include/perl/gdal_perl.i                      |  1572 +-
 swig/include/perl/ogr_perl.i                       |   934 +-
 swig/include/perl/osr_perl.i                       |   101 +-
 swig/include/perl/typemaps_perl.i                  |  1258 +-
 swig/include/php/typemaps_php.i                    |     8 +-
 swig/include/python/callback.i                     |    19 +-
 swig/include/python/docs/README                    |     4 +-
 swig/include/python/docs/doxy2swig.py              |    12 +-
 swig/include/python/docs/ogr_datasource_docs.i     |    93 +-
 swig/include/python/docs/ogr_driver_docs.i         |    39 +-
 swig/include/python/docs/ogr_feature_docs.i        |   555 +-
 swig/include/python/docs/ogr_featuredef_docs.i     |   166 +-
 swig/include/python/docs/ogr_fielddef_docs.i       |   234 +-
 swig/include/python/docs/ogr_geometry_docs.i       |   592 +-
 swig/include/python/docs/ogr_layer_docs.i          |   783 +-
 swig/include/python/gdal_python.i                  |  1135 +-
 swig/include/python/ogr_python.i                   |    77 +-
 swig/include/python/osr_python.i                   |    36 +-
 swig/include/python/python_exceptions.i            |    44 +-
 swig/include/python/python_strings.i               |   192 +-
 swig/include/python/typemaps_python.i              |   218 +-
 swig/include/ruby/gdal_ruby.i                      |    20 +-
 swig/include/ruby/ogr_ruby.i                       |    28 +-
 swig/include/ruby/osr_ruby.i                       |    28 +-
 swig/include/ruby/typemaps_ruby.i                  |    77 +-
 swig/java/GNUmakefile                              |     9 +-
 swig/java/add_javadoc.c                            |     4 +-
 swig/java/apps/GDALContour.java                    |     4 +-
 swig/java/apps/GDALOverviews.java                  |    20 +-
 swig/java/apps/GDALProximity.java                  |    14 +-
 swig/java/apps/ReadXML.java                        |     6 +-
 swig/java/apps/WKT2WKB.java                        |     6 +-
 swig/java/apps/gdalinfo.java                       |    31 +-
 swig/java/apps/multireadtest.java                  |     8 +-
 swig/java/apps/ogr2ogr.java                        |   161 +-
 swig/java/apps/ogr2ogr_new.java                    |    84 +
 swig/java/apps/ogrinfo.java                        |    56 +-
 swig/java/gnm/makefile.vc                          |    16 +
 swig/java/java.opt                                 |     1 +
 swig/java/javadoc.java                             |   148 +-
 swig/java/makefile.vc                              |    14 +-
 swig/makefile.vc                                   |     8 +
 swig/perl/Changes                                  |    73 +
 swig/perl/Changes-in-the-API-in-2.0                |     2 +-
 swig/perl/Doxyfile                                 |     8 +-
 swig/perl/GNUmakefile                              |    13 +-
 swig/perl/MANIFEST                                 |     6 +
 swig/perl/Makefile.PL                              |    50 +-
 swig/perl/gdal_wrap.cpp                            | 23512 ----------------
 swig/perl/gdalconst_wrap.c                         |  2603 --
 swig/perl/index.dox                                |   212 +-
 swig/perl/lib/Geo/GDAL.dox                         |  1116 +-
 swig/perl/lib/Geo/GDAL.pm                          |  2071 --
 swig/perl/lib/Geo/GDAL/Const.pm                    |   194 -
 swig/perl/lib/Geo/GNM.dox                          |    14 +
 swig/perl/lib/Geo/OGR.dox                          |   509 +-
 swig/perl/lib/Geo/OGR.pm                           |  2530 --
 swig/perl/lib/Geo/OSR.dox                          |    34 +-
 swig/perl/lib/Geo/OSR.pm                           |   725 -
 swig/perl/ogr_wrap.cpp                             | 26600 -------------------
 swig/perl/osr_wrap.cpp                             | 14358 ----------
 swig/perl/parse-for-doxygen.pl                     |    75 +-
 swig/perl/rr.dox                                   |     2 +-
 swig/perl/rv.dox                                   |     2 +-
 swig/perl/streaming.dox                            |    36 +
 swig/perl/t/00-measures-00.t                       |    44 +
 swig/perl/t/00-measures-01.t                       |   495 +
 swig/perl/t/00-measures-02.t                       |    59 +
 swig/perl/t/00-measures-03.t                       |   261 +
 swig/perl/t/00-measures-04.t                       |    83 +
 swig/perl/t/00.t                                   |   320 +-
 swig/perl/t/01.t                                   |    46 +-
 swig/perl/t/02.t                                   |    84 +-
 swig/perl/t/03.t                                   |    71 +-
 swig/perl/t/alg.t                                  |    82 +
 swig/perl/t/callback.t                             |    42 +
 swig/perl/t/error.t                                |    30 +
 swig/perl/t/feature.t                              |   173 +
 swig/perl/t/gcp.t                                  |    38 +
 swig/perl/t/gdal.t                                 |   369 +-
 swig/perl/t/layer.t                                |    59 +
 swig/perl/t/nodata.t                               |    33 +
 swig/perl/t/ogr.t                                  |    74 +-
 swig/perl/t/open.t                                 |    74 +
 swig/perl/t/osr.t                                  |    26 +-
 swig/perl/t/parenting.t                            |   131 +
 swig/perl/t/utf8.t                                 |    68 +
 swig/perl/t/util.t                                 |    76 +
 swig/php/gdal_wrap.cpp                             |    26 +-
 swig/php/gdalconst_wrap.c                          |    12 +-
 swig/php/gnm.php                                   |   293 +
 swig/php/gnm_wrap.cpp                              |  3705 +++
 swig/php/ogr_wrap.cpp                              |    18 +-
 swig/php/osr_wrap.cpp                              |    18 +-
 swig/php/php_gnm.h                                 |    73 +
 swig/python/GNUmakefile                            |    81 +-
 swig/python/README.txt                             |     6 +-
 swig/python/extensions/gdal_array_wrap.cpp         |  1652 +-
 swig/python/extensions/gdal_wrap.cpp               |  9335 +++++--
 swig/python/extensions/gdalconst_wrap.c            |  1331 +-
 swig/python/extensions/gnm_wrap.cpp                |  7237 +++++
 swig/python/extensions/ogr_wrap.cpp                |  8369 ++++--
 swig/python/extensions/osr_wrap.cpp                |  2974 ++-
 swig/python/fallback_build.bat                     |     2 +-
 swig/python/fallback_build_mingw32_under_unix.sh   |     2 +-
 swig/python/gnm.py                                 |   277 +
 swig/python/osgeo/__init__.py                      |     2 +-
 swig/python/osgeo/gdal.py                          |  1917 +-
 swig/python/osgeo/gdal_array.py                    |    87 +-
 swig/python/osgeo/gdalconst.py                     |    11 +-
 swig/python/osgeo/gnm.py                           |   277 +
 swig/python/osgeo/ogr.py                           |  3304 ++-
 swig/python/osgeo/osr.py                           |   318 +-
 swig/python/samples/README                         |     8 +-
 swig/python/samples/assemblepoly.py                |    13 +-
 swig/python/samples/attachpct.py                   |    23 +-
 swig/python/samples/build_jp2_from_xml.py          |    17 +-
 swig/python/samples/classify.py                    |    12 +-
 swig/python/samples/crs2crs2grid.py                |    66 +-
 swig/python/samples/densify.py                     |    93 +-
 swig/python/samples/dump_jp2.py                    |    12 +-
 swig/python/samples/fft.py                         |    17 +-
 swig/python/samples/gcps2ogr.py                    |    15 +-
 swig/python/samples/gdal2grd.py                    |    15 +-
 swig/python/samples/gdal_cp.py                     |    10 +-
 swig/python/samples/gdal_ls.py                     |     7 +-
 swig/python/samples/gdal_lut.py                    |    34 +-
 swig/python/samples/gdal_vrtmerge.py               |    54 +-
 swig/python/samples/gdalcopyproj.py                |    19 +-
 swig/python/samples/gdalfilter.py                  |    17 +-
 swig/python/samples/gdalinfo.py                    |   199 +-
 swig/python/samples/gdalpythonserver.py            |   109 +-
 swig/python/samples/get_soundg.py                  |    19 +-
 swig/python/samples/histrep.py                     |    17 +-
 swig/python/samples/hsv_merge.py                   |    31 +-
 swig/python/samples/jpeg_in_tiff_extract.py        |     5 +-
 swig/python/samples/load2odbc.py                   |    23 +-
 swig/python/samples/loslas2ntv2.py                 |    41 +-
 swig/python/samples/magphase.py                    |    10 +-
 .../python/samples/make_fuzzer_friendly_archive.py |    40 +
 swig/python/samples/ogr2ogr.py                     |   386 +-
 swig/python/samples/ogr2vrt.py                     |    35 +-
 swig/python/samples/ogr_build_junction_table.py    |    10 +-
 swig/python/samples/ogr_dispatch.py                |     4 +-
 swig/python/samples/ogr_layer_algebra.py           |    19 +-
 swig/python/samples/ogrinfo.py                     |   172 +-
 swig/python/samples/ogrupdate.py                   |    15 +-
 swig/python/samples/rel.py                         |    19 +-
 swig/python/samples/tigerpoly.py                   |    28 +-
 swig/python/samples/tolatlong.py                   |    11 +-
 swig/python/samples/val_at_coord.py                |    13 +-
 swig/python/samples/val_repl.py                    |    11 +-
 swig/python/samples/validate_jp2.py                |    20 +-
 swig/python/samples/vec_tr.py                      |    17 +-
 swig/python/samples/vec_tr_spat.py                 |    15 +-
 swig/python/samples/wcs_virtds_params.py           |    16 +-
 swig/python/scripts/epsg_tr.py                     |    63 +-
 swig/python/scripts/esri2wkt.py                    |    27 +-
 swig/python/scripts/gcps2vec.py                    |    34 +-
 swig/python/scripts/gcps2wld.py                    |    25 +-
 swig/python/scripts/gdal2tiles.py                  |   365 +-
 swig/python/scripts/gdal2xyz.py                    |    29 +-
 swig/python/scripts/gdal_auth.py                   |    26 +-
 swig/python/scripts/gdal_calc.py                   |    28 +-
 swig/python/scripts/gdal_edit.dox                  |     5 +-
 swig/python/scripts/gdal_edit.py                   |    18 +-
 swig/python/scripts/gdal_fillnodata.py             |    48 +-
 swig/python/scripts/gdal_merge.py                  |    79 +-
 swig/python/scripts/gdal_pansharpen.py             |   249 +
 swig/python/scripts/gdal_polygonize.py             |    47 +-
 swig/python/scripts/gdal_proximity.dox             |     2 +-
 swig/python/scripts/gdal_proximity.py              |    36 +-
 swig/python/scripts/gdal_retile.py                 |    28 +-
 swig/python/scripts/gdal_sieve.py                  |    56 +-
 swig/python/scripts/gdalchksum.py                  |    29 +-
 swig/python/scripts/gdalcompare.py                 |    19 +-
 swig/python/scripts/gdalident.py                   |    27 +-
 swig/python/scripts/gdalimport.py                  |    28 +-
 swig/python/scripts/gdalmove.py                    |    51 +-
 swig/python/scripts/mkgraticule.py                 |    38 +-
 swig/python/scripts/pct2rgb.py                     |    30 +-
 swig/python/scripts/rgb2pct.py                     |    24 +-
 swig/python/setup.py                               |    56 +-
 update_copyright.py                                |     8 +-
 vb6/README.TXT                                     |     4 +-
 vb6/vb6_support.cpp                                |    72 +-
 wince/README                                       |   253 -
 wince/TODO                                         |     6 -
 wince/msvc80/gdalce_common.vsprops                 |    41 -
 wince/msvc80/gdalce_dll/gdalce_dll.sln             |    44 -
 wince/msvc80/gdalce_dll/gdalce_dll.vcproj          |  1515 --
 2541 files changed, 342175 insertions(+), 240289 deletions(-)

diff --git a/COMMITERS b/COMMITERS
index 0de6dc2..cbc9a96 100644
--- a/COMMITERS
+++ b/COMMITERS
@@ -179,6 +179,13 @@ vmo           Vincent Mora                 wasp
 jratike80     Jukka Rahkonen               documentation
               jukka.rahkonen at latuviitta.fi
 
+dadler        David Adler                  DB2
+              dadler at adtechgeospatial.com
+			  
+
+lplesea       Lucian Plesea		   mrf, wms
+	      lplesea at esri.com
+
 ===============
 Past developers
 ===============
diff --git a/Doxyfile b/Doxyfile
index 78db20a..fde9392 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -390,7 +390,8 @@ INPUT                  = port \
                          ogr/ogrsf_frmts/generic \
                          ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.cpp \
                          ogr/ogrsf_frmts/kml/ogr2kmlgeometry.cpp \
-			 swig/python/scripts
+			 swig/python/scripts \
+			 gnm 
 
 # If the value of the INPUT tag contains directories, you can use the 
 # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
@@ -939,7 +940,8 @@ PREDEFINED             = HAVE_DLFCN_H \
                          __cplusplus \
                          DOXYGEN_SKIP \
                          HAVE_CURL \
-			 OGR_ENABLED
+                         CPL_UNUSED= \
+                         UNUSED_IF_NO_GEOS=
 
 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
 # this tag can be used to specify a list of macro names that should be expanded. 
diff --git a/GDALmake.opt.in b/GDALmake.opt.in
index 672d73a..81a2105 100644
--- a/GDALmake.opt.in
+++ b/GDALmake.opt.in
@@ -1,3 +1,4 @@
+# -*- Makefile -*- for emacs.
 GDAL_ROOT	=	@abs_top_builddir@
 top_builddir	=	$(GDAL_ROOT)
 
@@ -12,7 +13,7 @@ ifeq ($(HAVE_LIBTOOL),yes)
 LIBTOOL_COMPILE_CC =	$(LIBTOOL) --mode=compile --tag=CC
 LIBTOOL_COMPILE_CXX =	$(LIBTOOL) --mode=compile --tag=CXX
 LIBTOOL_LINK	=	$(LIBTOOL) --mode=link
-LIBTOOL_INSTALL	=	$(LIBTOOL) --mode=install 
+LIBTOOL_INSTALL	=	$(LIBTOOL) --mode=install
 LIBTOOL_FINISH	=	$(LIBTOOL) --mode=finish --silent
 LIBTOOL_CLEAN	=	$(LIBTOOL) --mode=clean
 OBJ_EXT = lo
@@ -35,7 +36,7 @@ INSTALL_DIR	= 	$(GDAL_ROOT)/install-sh -d
 LIBS	=	$(SDE_LIB) @LIBS@ $(KAK_LIBS) $(DWG_LIBS) $(CURL_LIB) \
 		$(MRSID_LIBS) $(MRSID_LIDAR_LIBS) $(ECW_LIBS) $(INGRES_LIB) \
 		$(PCIDSK_LIB) $(RASDAMAN_LIB) $(CHARLS_LIB) $(SOSI_LIB) \
-		$(OPENCL_LIB) $(JVM_LIB) $(LIBICONV) $(FGDB_LIB) $(LIBXML2_LIB)
+		$(OPENCL_LIB) $(JVM_LIB) $(LIBICONV) $(FGDB_LIB) $(LIBXML2_LIB) $(MONGODB_LIB)
 
 SSEFLAGS = @SSEFLAGS@
 HAVE_SSE_AT_COMPILE_TIME = @HAVE_SSE_AT_COMPILE_TIME@
@@ -49,7 +50,8 @@ PY_HAVE_SETUPTOOLS=@PY_HAVE_SETUPTOOLS@
 BINDINGS	=	@BINDINGS@
 
 HAVE_OGDI = @HAVE_OGDI@
-OGR_ENABLED = @OGR_ENABLED@
+OGR_ENABLED = yes
+GNM_ENABLED = @GNM_ENABLED@
 
 OSX_FRAMEWORK_PREFIX = /Library/Frameworks/GDAL.framework
 OSX_VERSION_FRAMEWORK_PREFIX = ${OSX_FRAMEWORK_PREFIX}/Versions/@GDAL_VERSION_MAJOR at .@GDAL_VERSION_MINOR@
@@ -69,7 +71,36 @@ INST_HTML	=	$(HOME)/www/gdal
 CPPFLAGS	= @CPPFLAGS@ -I$(GDAL_ROOT)/port @EXTRA_INCLUDES@ -DGDAL_COMPILATION
 CFLAGS		= @CFLAGS@ @C_WFLAGS@ $(USER_DEFS)
 CXXFLAGS	= @CXXFLAGS@ @CXX_WFLAGS@ $(USER_DEFS)
+CFLAGS_NOFTRAPV          = @CFLAGS_NOFTRAPV@ @C_WFLAGS@ $(USER_DEFS)
+CXXFLAGS_NOFTRAPV        = @CXXFLAGS_NOFTRAPV@ @CXX_WFLAGS@ $(USER_DEFS)
+CFLAGS_NO_LTO_IF_AVX_NONDEFAULT             = @CFLAGS_NO_LTO_IF_AVX_NONDEFAULT@ @C_WFLAGS@ $(USER_DEFS)
+CXXFLAGS_NO_LTO_IF_AVX_NONDEFAULT           = @CXXFLAGS_NO_LTO_IF_AVX_NONDEFAULT@ @CXX_WFLAGS@ $(USER_DEFS)
+
+NO_UNUSED_PARAMETER_FLAG = @NO_UNUSED_PARAMETER_FLAG@
+NO_SIGN_COMPARE = @NO_SIGN_COMPARE@
+NO_NON_VIRTUAL_DTOR_FLAG = @NO_NON_VIRTUAL_DTOR_FLAG@
+NO_LOGICAL_OP_FLAG = @NO_LOGICAL_OP_FLAG@
+
+# Also available -DAFL_FRIENDLY for strcmp(), etc.. variants that will
+# work better with American Fuzzy Lop branch examination logic
+
+# TODO(schwehr): Make these be configure flags.
+# CFLAGS += -Werror
+# CFLAGS += -std=c11
+# CFLAGS += -fsanitize=address
+# CFLAGS += -D_FORTIFY_SOURCE=2
+# CFLAGS += -fPIE -pie
+# CFLAGS += -fstack-protector-all
+
+# CXXFLAGS += -Werror
+# CXXFLAGS += -std=c++11
+# CXXFLAGS += -fsanitize=address
+# CXXFLAGS += -D_FORTIFY_SOURCE=2
+# CXXFLAGS += -fPIE -pie
+# CXXFLAGS += -fstack-protector-all
+
 LDFLAGS     = @LDFLAGS@
+# LDFLAGS += -fsanitize=address
 
 RANLIB		=	@RANLIB@
 SO_EXT		=	@SO_EXT@
@@ -84,13 +115,14 @@ endif
 
 GDAL_INCLUDE	=	-I$(GDAL_ROOT)/port -I$(GDAL_ROOT)/gcore \
 			-I$(GDAL_ROOT)/alg \
-			-I$(GDAL_ROOT)/ogr -I$(GDAL_ROOT)/ogr/ogrsf_frmts
+                        -I$(GDAL_ROOT)/ogr -I$(GDAL_ROOT)/ogr/ogrsf_frmts \
+                        -I$(GDAL_ROOT)/gnm -I$(GDAL_ROOT)/apps
 
 # libtool targets and help variables
 LIBGDAL	:=		libgdal.la
-LIBGDAL_CURRENT	:=	20
-LIBGDAL_REVISION	:=	2
-LIBGDAL_AGE	:=	0
+LIBGDAL_CURRENT	:=	21
+LIBGDAL_REVISION	:=	0
+LIBGDAL_AGE	:=	1
 
 # native build targets and variables
 GDAL_VER	=	@GDAL_VER@
@@ -144,13 +176,13 @@ endif
 # HDF5 Support.
 #
 HAVE_HDF5     = @HAVE_HDF5@
-HDF5_INCLUDE  = @HDF5_INCLUDE@ 
+HDF5_INCLUDE  = @HDF5_INCLUDE@
 
 #
 # KEA Support.
 #
 HAVE_KEA     = @HAVE_KEA@
-KEA_INC      = @KEA_INC@ 
+KEA_INC      = @KEA_INC@
 KEA_LIB      = @KEA_LIB@
 LIBS       +=   $(KEA_LIB)
 
@@ -172,12 +204,13 @@ HAVE_DODS = yes
 endif
 
 #
-# SQLite 
+# SQLite
 #
 SQLITE_INC = @SQLITE_INC@
 SQLITE_HAS_COLUMN_METADATA = @SQLITE_HAS_COLUMN_METADATA@
 HAVE_SQLITE = @HAVE_SQLITE@
 HAVE_SPATIALITE = @HAVE_SPATIALITE@
+SPATIALITE_SONAME = @SPATIALITE_SONAME@
 SPATIALITE_INC = @SPATIALITE_INC@
 SPATIALITE_AMALGAMATION = @SPATIALITE_AMALGAMATION@
 SPATIALITE_412_OR_LATER = @SPATIALITE_412_OR_LATER@
@@ -221,9 +254,9 @@ MRSID_LIBS	= @MRSID_LIBS@
 MRSID_LIDAR_INCLUDE	= @MRSID_LIDAR_INCLUDE@
 MRSID_LIDAR_LIBS	= @MRSID_LIDAR_LIBS@
 
-# 
+#
 # ECW Related
-# 
+#
 ECW_FLAGS	= @ECW_FLAGS@
 ECW_INCLUDE 	= @ECW_INCLUDE@
 ECW_LIBS	= @ECW_LIBS@
@@ -233,7 +266,7 @@ ECW_LIBS	= @ECW_LIBS@
 HAVE_XERCES	= @HAVE_XERCES@
 XERCES_INCLUDE	= @XERCES_INCLUDE@
 
-# 
+#
 # Enable NAS format
 #
 HAVE_NAS	= @HAVE_NAS@
@@ -261,6 +294,10 @@ OCI_INCLUDE	= @OCI_INCLUDE@
 HAVE_GEOS       =       @HAVE_GEOS@
 GEOS_CFLAGS     =       @GEOS_CFLAGS@
 
+# QHull Support
+
+QHULL_SETTING   =       @QHULL_SETTING@
+
 # GRASS Support
 
 GRASS_SETTING	=	@GRASS_SETTING@
@@ -268,21 +305,28 @@ GRASS_INCLUDE	=	@GRASS_INCLUDE@
 GRASS_GISBASE	=	@GRASS_GISBASE@
 HAVE_GRASS	=	@HAVE_GRASS@
 
-# 
+#
 # SDE
 #
 HAVE_SDE = @SDE_ENABLED@
 SDE_LIB	= @SDE_LIB@
 SDE_INC = @SDE_INC@
 
-# 
+#
 # FileGDB
 #
 HAVE_FGDB = @FGDB_ENABLED@
 FGDB_LIB = @FGDB_LIB@
 FGDB_INC = @FGDB_INC@
 
-# 
+#
+# MongoDB
+#
+HAVE_MONGODB = @MONGODB_ENABLED@
+MONGODB_LIB = @MONGODB_LIB@
+MONGODB_INC = @MONGODB_INC@
+
+#
 # ArcObjects
 #
 HAVE_ARCOBJECTS = @ARCOBJECTS_ENABLED@
@@ -302,7 +346,7 @@ CURL_INC	=	@CURL_INC@
 LIBJSONC_SETTING = @LIBJSONC_SETTING@
 JSON_INCLUDE = @JSON_INCLUDE@
 
-# 
+#
 # OpenCL support
 #
 OPENCL_LIB	=	@OPENCL_LIB@
@@ -318,7 +362,7 @@ HAVE_SOSI = @SOSI_ENABLED@
 
 #
 # PCIDSK SDK
-# 
+#
 PCIDSK_SETTING  =       @PCIDSK_SETTING@
 PCIDSK_LIB	=	@PCIDSK_LIB@
 PCIDSK_INCLUDE	=	@PCIDSK_INCLUDE@
@@ -336,7 +380,7 @@ HAVE_LIBXML2 = @HAVE_LIBXML2@
 LIBXML2_INC = @LIBXML2_INC@
 LIBXML2_LIB = @LIBXML2_LIB@
 
-# 
+#
 # DWGdirect Library
 #
 DWGDIRECT =	@DWGDIRECT@
@@ -355,10 +399,10 @@ DWG_LIBS = $(DWG_LIBDIR)/DD_$(DWG_PLT)_ModelerGeometry.a \
 	$(DWG_LIBDIR)/DD_$(DWG_PLT)_Ge.a \
 	$(DWG_LIBDIR)/DD_$(DWG_PLT)_Root.a \
 	$(DWG_LIBDIR)/DD_$(DWG_PLT)_FT.a \
-	$(DWG_LIBDIR)/DD_$(DWG_PLT)_Alloc.a 
+	$(DWG_LIBDIR)/DD_$(DWG_PLT)_Alloc.a
 HAVE_DWGDIRECT = yes
 else
-DWG_LIBS =	
+DWG_LIBS =
 HAVE_DWGDIRECT = no
 endif
 
@@ -377,7 +421,7 @@ endif
 #
 ifeq (@X_FME_HOME@,)
 HAVE_FME        =       no
-FME_INCLUDE	=	
+FME_INCLUDE	=
 else
 HAVE_FME        =       yes
 FME_INCLUDE	=	-I at X_FME_HOME@/fmeobjects/cpp
@@ -423,6 +467,11 @@ RASDAMAN_INC  =   @RASDAMAN_INC@
 RASDAMAN_LIB  =   @RASDAMAN_LIB@
 
 #
+# PDF stuff
+#
+PDF_PLUGIN = @PDF_PLUGIN@
+
+#
 # Poppler stuff
 #
 
@@ -432,6 +481,7 @@ POPPLER_BASE_STREAM_HAS_TWO_ARGS = @POPPLER_BASE_STREAM_HAS_TWO_ARGS@
 POPPLER_0_20_OR_LATER = @POPPLER_0_20_OR_LATER@
 POPPLER_0_23_OR_LATER = @POPPLER_0_23_OR_LATER@
 POPPLER_INC = @POPPLER_INC@
+POPPLER_PLUGIN_LIB = @POPPLER_PLUGIN_LIB@
 
 #
 # Podofo stuff
@@ -439,6 +489,15 @@ POPPLER_INC = @POPPLER_INC@
 
 HAVE_PODOFO = @HAVE_PODOFO@
 PODOFO_INC = @PODOFO_INC@
+PODOFO_PLUGIN_LIB = @PODOFO_PLUGIN_LIB@
+
+#
+# Pdfium stuff
+#
+
+HAVE_PDFIUM = @HAVE_PDFIUM@
+PDFIUM_INC = @PDFIUM_INC@
+PDFIUM_PLUGIN_LIB = @PDFIUM_PLUGIN_LIB@
 
 #
 # CharLs stuff
@@ -459,11 +518,12 @@ PROJ_INCLUDE	=	@PROJ_INCLUDE@
 
 PAM_SETTING     =       @PAM_SETTING@
 
-ifeq ($(OGR_ENABLED),yes)
 GDAL_LIBS	:= $(GDAL_LIB) $(OCI_LIB) $(GDAL_LIBS)
+# TODO: Remove -DOGR_ENABLED.
 CPPFLAGS	:= -DOGR_ENABLED $(CPPFLAGS)
-else
-GDAL_LIBS	=	$(GDAL_LIB)
+
+ifeq ($(GNM_ENABLED),yes)
+CPPFLAGS	:= -DGNM_ENABLED $(CPPFLAGS)
 endif
 
 #
@@ -485,28 +545,42 @@ HAVE_FREEXL = @HAVE_FREEXL@
 FREEXL_INCLUDE = @FREEXL_INCLUDE@
 
 #
-#	Note these codes have to exactly match the format directory names, 
-#	and their uppercase form should be the format portion of the
-#	format registration entry point.  eg. gdb -> GDALRegister_GDB().
+# cryptopp stuff
 #
-GDAL_FORMATS = 	gxf gtiff hfa aigrid aaigrid ceos ceos2 iso8211 xpm \
-		sdts raw dted mem jdem envisat elas fit vrt usgsdem l1b \
-		nitf bmp pcidsk airsar rs2 ilwis rmf leveller sgi srtmhgt \
-		idrisi gsg ingr ers jaxapalsar dimap gff cosar pds adrg \
-		coasp tsx terragen blx msgn til r northwood saga xyz hf2 \
-		kmlsuperoverlay ctg e00grid zmap ngsgeoid iris map\
-		@OPT_GDAL_FORMATS@
+HAVE_CRYPTOPP    =       @HAVE_CRYPTOPP@
+USE_ONLY_CRYPTODLL_ALG        =       @USE_ONLY_CRYPTODLL_ALG@
 
+#
+#	Note these codes have to exactly match the format directory names,
+#	and their uppercase form should be the format portion of the
+#	format registration entry point.  eg. gdb -> GDALRegister_GTiff().
+#
+GDAL_FORMATS :=
+GDAL_FORMATS += gxf gtiff hfa aigrid aaigrid ceos ceos2 iso8211 xpm
+GDAL_FORMATS += sdts raw dted mem jdem envisat elas fit vrt usgsdem l1b
+GDAL_FORMATS += nitf bmp airsar rs2 ilwis rmf leveller sgi srtmhgt
+GDAL_FORMATS += idrisi gsg ingr ers jaxapalsar dimap gff cosar pds adrg
+GDAL_FORMATS += coasp tsx terragen blx msgn til r northwood saga xyz hf2
+GDAL_FORMATS += kmlsuperoverlay ctg e00grid zmap ngsgeoid iris map cals
+GDAL_FORMATS += safe sentinel2
+GDAL_FORMATS += @OPT_GDAL_FORMATS@
+
+ifneq ($(PCIDSK_SETTING),no)
+GDAL_FORMATS += pcidsk
+endif
 
 ifneq ($(LIBZ_SETTING),no)
-GDAL_FORMATS := $(GDAL_FORMATS) rik ozi pdf
+GDAL_FORMATS := $(GDAL_FORMATS) rik ozi
+
+ifneq ($(PDF_PLUGIN),yes)
+GDAL_FORMATS := $(GDAL_FORMATS) pdf
+endif
+
 endif
 
-ifeq ($(OGR_ENABLED),yes)
 ifeq ($(HAVE_SQLITE),yes)
 GDAL_FORMATS := $(GDAL_FORMATS) rasterlite mbtiles
 endif
-endif
 
 ifeq ($(HAVE_POSTGISRASTER),yes)
 GDAL_FORMATS := $(GDAL_FORMATS) postgisraster
@@ -516,9 +590,7 @@ ifeq ($(HAVE_CHARLS),yes)
 GDAL_FORMATS := $(GDAL_FORMATS) jpegls
 endif
 
-ifeq ($(OGR_ENABLED),yes)
 GDAL_FORMATS := $(GDAL_FORMATS) arg
-endif
 
 #
 # CONFIG_LIBS is what local program should link against, and CONFIG_LIBS_INS
diff --git a/GNUmakefile b/GNUmakefile
index 999abd0..ba9f2b9 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -4,10 +4,24 @@ include GDALmake.opt
 GDAL_OBJ	=	$(GDAL_ROOT)/frmts/o/*.o \
 			$(GDAL_ROOT)/gcore/*.o \
 			$(GDAL_ROOT)/port/*.o \
-			$(GDAL_ROOT)/alg/*.o
+			$(GDAL_ROOT)/alg/*.o \
+			$(GDAL_ROOT)/apps/commonutils.o \
+			$(GDAL_ROOT)/apps/gdalinfo_lib.o \
+			$(GDAL_ROOT)/apps/gdal_translate_lib.o \
+			$(GDAL_ROOT)/apps/gdalwarp_lib.o \
+			$(GDAL_ROOT)/apps/ogr2ogr_lib.o \
+			$(GDAL_ROOT)/apps/gdaldem_lib.o \
+			$(GDAL_ROOT)/apps/nearblack_lib.o \
+			$(GDAL_ROOT)/apps/gdal_grid_lib.o \
+			$(GDAL_ROOT)/apps/gdal_rasterize_lib.o \
+			$(GDAL_ROOT)/apps/gdalbuildvrt_lib.o
 
 GDAL_OBJ += $(GDAL_ROOT)/ogr/ogrsf_frmts/o/*.o
 
+ifeq ($(GNM_ENABLED),yes)
+   GDAL_OBJ += $(GDAL_ROOT)/gnm/*.o $(GDAL_ROOT)/gnm/gnm_frmts/o/*.o
+endif
+
 include ./ogr/file.lst
 GDAL_OBJ += $(addprefix ./ogr/,$(OBJ))
 
@@ -17,6 +31,9 @@ LIBGDAL-$(HAVE_LD_SHARED)	+=	$(GDAL_SLIB)
 LIBGDAL-$(HAVE_LIBTOOL)	:= $(LIBGDAL)
 
 default:	lib-target apps-target swig-target gdal.pc
+ifeq ($(PDF_PLUGIN),yes)
+	(cd frmts/pdf; $(MAKE) plugin)
+endif
 
 lib-target:	check-lib;
 
@@ -44,15 +61,25 @@ ifeq ($(MACOSX_FRAMEWORK),yes)
 	install_name_tool -id ${OSX_VERSION_FRAMEWORK_PREFIX}/GDAL .libs/libgdal.dylib
 endif
 
-check-lib:	port-target core-target frmts-target ogr-target
+check-lib:	port-target core-target frmts-target ogr-target gnm-target appslib-target
 	$(MAKE) $(LIBGDAL-yes)
 
+appslib-target:
+	(cd apps; $(MAKE) appslib)
+
 port-target:
 	(cd port; $(MAKE))
 
 ogr-target:
 	(cd ogr; $(MAKE) lib )
 
+ifeq ($(GNM_ENABLED),yes)
+gnm-target:
+	(cd gnm; $(MAKE) lib )
+else
+gnm-target:	;
+endif
+
 core-target:
 	(cd gcore; $(MAKE))
 	(cd alg; $(MAKE))
@@ -79,6 +106,7 @@ swig-modules:	apps-target
 clean:	lclean
 	(cd port; $(MAKE) clean)
 	(cd ogr; $(MAKE) clean)
+	(cd gnm; $(MAKE) clean)
 	(cd gcore; $(MAKE) clean)
 	(cd frmts; $(MAKE) clean)
 	(cd alg; $(MAKE) clean)
@@ -86,7 +114,9 @@ clean:	lclean
 ifneq ($(BINDINGS),)
 	(cd swig; $(MAKE) clean)
 endif
-
+ifeq ($(PDF_PLUGIN),yes)
+	(cd frmts/pdf; $(MAKE) clean)
+endif
 
 
 lclean:
@@ -176,10 +206,12 @@ endif
 	(cd frmts; $(MAKE) install)
 	(cd alg; $(MAKE) install)
 	(cd ogr; $(MAKE) install)
+	(cd gnm; $(MAKE) install)
 	(cd apps; $(MAKE) install)
 ifneq ($(BINDINGS),)
 	(cd swig; $(MAKE) install)
 endif
+	(cd scripts; $(MAKE) install)
 	for f in LICENSE.TXT data/*.* ; do $(INSTALL_DATA) $$f $(DESTDIR)$(INST_DATA) ; done
 	$(LIBTOOL_FINISH) $(DESTDIR)$(INST_LIB)
 	$(INSTALL_DIR) $(DESTDIR)$(INST_LIB)/pkgconfig
diff --git a/HOWTO-RELEASE b/HOWTO-RELEASE
index bcd270b..95f6c8f 100644
--- a/HOWTO-RELEASE
+++ b/HOWTO-RELEASE
@@ -25,15 +25,21 @@ Prerequisites:
     It may also be helpful to check:
       http://upstream-tracker.org/versions/gdal.html
 
+2) Delete existing fix_typos directory and run scripts/fix_typos.sh
+
 Process :
 
 1) a) Regenerate configure using autogen.sh and commit if changed.
    b) Regenerate swig generated files for python bindings and commit if changed.
 
-   There is often a reference system on which this should be done (ie. Frank's
+   There is often a reference system on which this should be done (i.e. Frank's
    dev workstation) to avoid unnecessary churn from different autoconf or swig
    versions.
 
+   c) "cd scripts; make completion" to regenerate scripts/gdal-bash-completion.sh
+      if new command line switches have been added. scripts/completionFinder.py
+      must also be edited before if new utilities/scripts are added/removed.
+
 2) Update the release date, and number information in gcore/gdal_version.h.
 
 3) Update the VERSION file. 
@@ -42,8 +48,9 @@ Process :
      And the version of libgdal in ./swig/python/README.txt
 
 3.2) Update ./swig/include/perl/gdal_perl.i $VERSION and $GDAL_VERSION
-strings to current version. Kick Perl module maintainer to make a CPAN
-release.
+strings to current version. Update also $VERSION in
+./swig/include/perl/ogr_perl.i to the same as the other $VERSION. Kick
+Perl module maintainer to make a CPAN release.
 
 3.3) For major releases update the VERSION macro in nmake.opt (for 1.6, 1.7etc)
 
@@ -75,18 +82,16 @@ release.
             https://svn.osgeo.org/gdal/tags/1.4.1
 
 9) Create the source distributions using the mkgdaldist.sh script.  The
-   argument should be the version number (ie. 1.4.1). 
-
-   eg.
-   % mkgdaldist.sh 1.4.0
+   argument should be the version number (i.e. 1.4.2). As our process involves
+   doing betas or RCs, use the -rc option so that the filenames include this
+   information (after promotion to official release, filename renaming will have
+   to be done)
 
-   or
- 
-   % mkgdaldist.sh 1.4.2 -branch tags/1.4.2
+   % mkgdaldist.sh 1.4.2 -branch tags/1.4.2 -rc RC1
 
 10) Create a snapshot of the documentation.
 
- ie. On www.gdal.org:
+ i.e. On www.gdal.org:
  % cd /osgeo/gdal
  % ./gdal-web-refresh.sh
  % zip -r gdal180doc.zip gdal-web/*.* gdal-web/ogr gdal-web/java 
@@ -182,7 +187,7 @@ c) Build the bindings:
     This will build and sign the artifacts with a single command. Read on for 
     more details.
 
-a)  Build the maven aritfacts:
+a)  Build the maven artifacts:
 
      ant maven
 
diff --git a/LICENSE.TXT b/LICENSE.TXT
index d65fdd2..11fa099 100644
--- a/LICENSE.TXT
+++ b/LICENSE.TXT
@@ -261,3 +261,119 @@ Developed at SunSoft, a Sun Microsystems, Inc. business.
 Permission to use, copy, modify, and distribute this
 software is freely granted, provided that this notice
 is preserved.
+
+
+gdal/alg/libqhull
+-----------------
+
+Only applies when GDAL is compiled with internal qhull support
+
+
+                    Qhull, Copyright (c) 1993-2012
+                    
+                            C.B. Barber
+                           Arlington, MA 
+                          
+                               and
+
+       The National Science and Technology Research Center for
+        Computation and Visualization of Geometric Structures
+                        (The Geometry Center)
+                       University of Minnesota
+
+                       email: qhull at qhull.org
+
+This software includes Qhull from C.B. Barber and The Geometry Center.  
+Qhull is copyrighted as noted above.  Qhull is free software and may 
+be obtained via http from www.qhull.org.  It may be freely copied, modified, 
+and redistributed under the following conditions:
+
+1. All copyright notices must remain intact in all files.
+
+2. A copy of this text file must be distributed along with any copies 
+   of Qhull that you redistribute; this includes copies that you have 
+   modified, or copies of programs or other software products that 
+   include Qhull.
+
+3. If you modify Qhull, you must include a notice giving the
+   name of the person performing the modification, the date of
+   modification, and the reason for such modification.
+
+4. When distributing modified versions of Qhull, or other software 
+   products that include Qhull, you must provide notice that the original 
+   source code may be obtained as noted above.
+
+5. There is no warranty or other guarantee of fitness for Qhull, it is 
+   provided solely "as is".  Bug reports or fixes may be sent to 
+   qhull_bug at qhull.org; the authors may or may not act on them as 
+   they desire.
+
+gdal/frmts/pdf/pdfdataset.cpp (method PDFiumRenderPageBitmap())
+---------------------------------------------------------------
+
+Copyright 2014 PDFium Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+gdal/frmts/mrf/* (apply when MRF driver included in build)
+---------------------------------------------------------------
+
+Copyright (c) 2002-2012, California Institute of Technology.
+All rights reserved.  Based on Government Sponsored Research under contracts NAS7-1407 and/or NAS7-03001.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright notice,
+     this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+  3. Neither the name of the California Institute of Technology (Caltech), its operating division the Jet Propulsion Laboratory (JPL),
+     the National Aeronautics and Space Administration (NASA), nor the names of its contributors may be used to
+     endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE CALIFORNIA INSTITUTE OF TECHNOLOGY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+~~~~~~~~
+
+Copyright 2014-2015 Esri
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+
diff --git a/MIGRATION_GUIDE.TXT b/MIGRATION_GUIDE.TXT
index a6138bb..fd1bc89 100644
--- a/MIGRATION_GUIDE.TXT
+++ b/MIGRATION_GUIDE.TXT
@@ -1,3 +1,20 @@
+MIGRATION GUIDE FROM GDAL 2.0 to GDAL 2.1
+------------------------------------------
+
+A) RFC 61: Support for measured geometries
+
+Link: https://trac.osgeo.org/gdal/wiki/rfc61_support_for_measured_geometries
+
+The OGRwkbGeometryType enumeration has been extended with new values for the
+M and ZM variants of the geometry types. Client code may have to be upgraded
+to take into account those new values. Note that the wkbPolyhedralSurface, wkbTIN
+and wkbTriangle types and their Z, M and ZM variants, have also been introduced
+as a provision for a potential support in a future version (they are unused in
+OGR core and drivers for now).
+
+Previously the ESRI Shapefile driver read XYM data as XYZ. Now it is read
+as XYM.
+
 MIGRATION GUIDE FROM GDAL 1.11 to GDAL 2.0
 ------------------------------------------
 
@@ -209,7 +226,7 @@ C API:
   * GDALGetRasterSampleOverviewEx() is added.
 
 Out-of-tree drivers :
-  * See the virtual method API changes mentionned above in the C++ API paragraph.
+  * See the virtual method API changes mentioned above in the C++ API paragraph.
 
 MIGRATION GUIDE FROM GDAL 1.10 to GDAL 1.11
 -------------------------------------------
@@ -220,7 +237,7 @@ C++ API:
 
   * GDALRasterAttributeTable is now an abstract class.
     See http://trac.osgeo.org/gdal/wiki/rfc40_enhanced_rat_support
-    The functionnality of GDAL 1.X GDALRasterAttributeTable is now in
+    The functionality of GDAL 1.X GDALRasterAttributeTable is now in
     GDALDefaultRasterAttributeTable.
 
 OGR drivers :
@@ -228,7 +245,7 @@ OGR drivers :
   * Due to RFC 41, if a OGR driver calls SetGeomType(wkbNone) on a layer,
     it will be impossible to affect geometries to features of that layer.
     This worked before, although it was inconsistent, but it does no longer now.
-    In the developmenet of RFC 41, the CSV and VRT drivers have been upgraded
+    In the development of RFC 41, the CSV and VRT drivers have been upgraded
     to fix such errors.
 
 Changes that should likely not impact anybody :
diff --git a/NEWS b/NEWS
index 814a00d..3e27666 100644
--- a/NEWS
+++ b/NEWS
@@ -1,310 +1,695 @@
-= GDAL/OGR 2.0.2 Release Notes = 
+= GDAL/OGR 2.1.0 Release Notes (up to r33846) =
 
-The 2.0.2 release is a bug fix release.
+== In a nutshell... ==
+
+ * New GDAL/raster drivers:
+    - CALS: read/write driver for CALS Type I rasters
+    - DB2 driver: read/write support for DB2 database (Windows only)
+    - ISCE: read/write driver (#5991)
+    - MRF: read/write driver (#6342)
+    - SAFE: read driver for ESA SENTINEL-1 SAR products (#6054)
+    - SENTINEL2: read driver for ESA SENTINEL-2 L1B/LC1/L2A products
+    - WMTS: read driver for OGC WMTS services
+ * New OGR/vector drivers:
+    - AmigoCloud: read/write support for AmigoCloud mapping platform
+    - DB2 driver: read/write support for DB2 database (Windows only)
+    - MongoDB: read/write driver
+    - netCDF: read/write driver
+    - VDV: read/write VDV-451/VDV-452 driver, with specialization for the
+           Austrian official open government street graph format
+ * Significantly improved drivers:
+    - CSV: new options, editing capabilities of existing file
+    - ElasticSearch: read support and support writing any geometry type
+    - GeoJSON: editing capabilities of existing file, "native data" (RFC 60) support
+    - MBTiles: add raster write support
+    - PDF: add PDFium library as a possible back-end.
+    - PLScenes: add support for V1 API
+    - VRT: on-the-fly pan-sharpening
+    - GTiff: multi-threaded compression for some compression methods
+ * Port library: add /vsis3/, /vsis3_streaming/, /vsicrypt/ virtual file systems
+ * RFC 26: Add hash-set band block cache implementation for very larger rasters (WMS, WMTS, ...)
+        http://trac.osgeo.org/gdal/wiki/rfc26_blockcache
+ * RFC 48: Geographical networks support (GNM)
+        https://trac.osgeo.org/gdal/wiki/rfc48_geographical_networks_support
+ * RFC 58: Add DeleteNoDataValue():
+        https://trac.osgeo.org/gdal/wiki/rfc58_removing_dataset_nodata_value
+ * RFC 59.1: Make GDAL/OGR utilities available as library functions:
+        https://trac.osgeo.org/gdal/wiki/rfc59.1_utilities_as_a_library
+   For gdalinfo, gdal_translate, gdalwarp, ogr2ogr, gdaldem, nearblack, gdalgrid,
+   gdal_rasterize, gdalbuildvrt
+   Available in C, Python, Perl and Java bindings.
+ * RFC 60: Improved round-tripping in OGR
+        https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
+   Implemented in GeoJSON driver
+ * RFC 61: Support for measured geometries.
+        https://trac.osgeo.org/gdal/wiki/rfc61_support_for_measured_geometries
+   Implemented in Shapefile, PostgreSQL/PostGIS, PGDump, MEM, SQLite, GeoPackage,
+   FileGDB, OpenFileGDB, CSV, VRT
+ * Upgrade to EPSG database v8.8
+ * General sanitization pass to clean-up code, fix a lot of compiler warnings,
+   as well as issues pointed by static code analyzers, such as Coverity Scan
+   (credits to Kurt Schwehr for tackling a large part of them) or CLang Static Analyzer.
+ * Fixes in a number of drivers to be more robust against corrupted files (most found
+   with American Fuzzy Lop): RIK, INGR, Northwood, HF2, CEOS, GTiff, GXF, BMP,
+   NITF, HFA, VRT, FIT, CEOS2, NWT_GRD/NWT_GRC, MITAB, RPFTOC, DBF/Shape, XYZ, VFK, DXF,
+   NAS, GSAG, GS7BG, OpenFileGDB, RMF, AIGRID, OpenAIR, EHDR, ISO8211, FAST,
+   USGSDEM, DGN, SGI, OpenJPEG, PCRaster, BSB, ADRG, SRP, JPEG, Leveller, VICAR, PCIDSK, XPM
+   as well as in portability library (CPL), algorithms and raster core.
+ * Driver removed:
+    - Google Maps Engine (GME)  (#6261)
+
+== New installed files ==
+ * gdal_pansharpen.py
+ * data/vdv452.xml
+ * data/vdv452.xsd
+ * data/netcdf_config.xsd
+ * /path/where/bash-completion/scripts/are/installed/gdal-bash-completion.sh
+
+== Backward compatibility issues ==
+
+See MIGRATION_GUIDE.TXT
 
-== Build(Windows) ==
- * Fix linking error with MSVC_VER=1900 (VS 2015) (#6255)
+== GDAL/OGR 2.1.0 - General Changes ==
+
+Build(Unix):
+ * Allow plugin for HDF4, HDF5, GeoRaster, FileGDB, OCI and PG
+ * Add a --with-gnm option to enable GNM
+ * Add --enable-lto switch to turn on link time optimization (GCC >= 5)
+ * Add --with-spatialite=dlopen --with-spatialite-soname=libspatialite.so[.X] syntax to allow linking against spatialite through dlopen() mechanism (#6386)
+ * Add a lot of warning options when available in the compiler.
+ * Change detection test of podofo to work with podofo 0.9.3
+ * Fix gdalserver compilation with recent GNU libc (such as in Arch Linux) (#6073)
+ * Add pkg-config support for libkml fork (#6077)
+ * Update config.sub and config.guess to their latest upstream versions so as to be able to detect new architectures (android, ppcle64, etc..) (#6101)
+ * Fix python package installation in custom prefixes (#4563)
+ * configure: check that CXX is really a working compiler (#4436)
+ * Build support for Kakadu 7.7
+ * thinplatespline.cpp: avoid using optimized version of VizGeorefSpline2DBase_func4() with ICC versions that fail on it (#6350)
+ * Add bash completion for GDAL/OGR utilities and scripts (#6381)
+ * Add support for ODBC autodetection with mingw64 (#6000)
+ * Remove macos 9 and older support (#6133).
+ * Remove dist_docs, burnpath and pszUpdableINST_DATA in gcore/gdaldrivermanager.cpp as they are have not been used for a while (#6140).
+ * Removed --without-ogr configure flag (#6117).  Always build with OGR.
+
+Build(Windows):
+ * Add support for Visual Studio 2015 (a.k.a MSVC_VER=1900 or VC 13)
+ * Add KAKFLAGS to nmake.opt with KDU_{MAJOR,MINOR,PATCH}_VERSION define-s.
+ * nmake.opt: make it less error prone to define SETARGV when paths include spaces (#6032)
+ * nmake.opt: add CL.EXE compiler option /FC to display full path of source code file in diagnostics
+ * Remove WinCE support (#6133)
+ * nmake.opt: add /I flag to the INSTALL command so that xcopy will be smart enough to create a directory when copying files and avoid prompting for user input (https://github.com/OSGeo/gdal/pull/95)
+ * Enable mssql spatial blugin build, use BCP as the default option for the sqlncli enabled builds
+
+Build(all):
+ * Compatibility with C++11 and C++14
+ * Optional crypto++ dependency for /vsicrypt/ support
+ * Optional mongocxx dependency for MongoDB support
+
+Other:
+ * Disable copy constructor and assignment operators in classes OGRFieldDefn, OGRGeomFieldDefn, OGRFeature, GDALMultiDomainMetadata, GDALDefaultOverviews, GDALOpenInfoGDALDataset, GDALRasterBlock, GDALRasterBand and GDALDriver (#6100)
 
-== Build(Unix) ==
- * Add pkg-config support for libkml fork, in addition to the old detection method. The libkml/libkml fork on GitHub supports pkg-config and no longer includes the third_party libraries. (#6077)
- * gdalserver.c: Add include of signal.h for SIGPIPE and signal() (#6193)
- * fix detection of FreeXL on MinGW/MSYS (#6330)
+== GDAL 2.1.0 - Overview of Changes ==
 
-== Port ==
+Port:
+ * Add /vsicrypt/ virtual file system for reading/creating/update encrypted files on the fly, with random access capabilities
+ * Add /vsis3/ and /vsis3_streaming/ virtual file systems to read/write objects from AWS S3 buckets
+ * /vsizip/: avoid returning the previous file list of an already opened .zip if it has changed afterwards (#6005)
+ * /vsizip/: use CP437 on Windows when ICONV support is available (#6410)
+ * /vsimem/: implement append mode (#6049)
+ * /vsistdin/: fix caching of first 1MB / VRT driver: read XML content from /vsistdin/ in a streaming compatible way (#6061)
+ * /vsistdout/: flush when closing the handle (#6149)
+ * Add VSIReadDirEx() with a limit on the number of files before giving up and corresponding VSIFilesystemHandler::ReadDirEx() virtual function
+ * cpl_vsil_cache: rework to be able to work on very large files on 32bit systems
+ * Add CPLThreadLocaleC class to use thread-specific locale settings (when available)
+ * VSIWin32Handle::Flush(): add VSI_FLUSH config option that can be set to TRUE to force FlushFileBuffers(). (hack related to #5556)
+ * Fix VSIL append mode in Windows (#6065)
+ * Make CPLCreateMutexEx() support CPL_MUTEX_REGULAR; and fix CPL_MUTEX_ADAPTIVE to avoid continuing in code path for creation of recursive mutex
+ * Add CPLWorkerThreadPool API
+ * Add CPLGetThreadLocalConfigOption()
+ * Fix CPL_LSBINT16PTR() and CPL_LSBINT32PTR() to work with non-byte pointer (#6090)
+ * CPLRecodeStub(): add special case for CP437 -> UTF-8 when input is only printable ASCII
+ * CPLHTTPFetch(): add LOW_SPEED_TIME and LOW_SPEED_LIMIT options
  * CPLGetValueType(): improve heuristics to avoid detecting some WKB strings as real numbers (#6128)
+ * Add CPL_SHA256* and CPL_HMAC_SHA256 functions 
+ * Make CPLVirtualMemFileMapNew() work on all systems having mmap(), and thus GeoTIFF GTIFF_VIRTUAL_MEM_IO optimization too
+ * Add VSI_MALLOC_VERBOSE() and similar macros to output an error message in case of failed alloc
+ * CPLParseXMLString(): limit depth of elements to 10000
+ * Win32 file management: handle files whose total file path length is greater than 255 characters in Open() and Stat()
+ * Make CPLFormFilename(absolute_path, "..", NULL) truncate when possible
+ * Add VSIGetDiskFreeSpace()
+ * Implement CPLIsInf() for Solaris 11
+ * Add a CPL_FINAL macro that expands to C++11 final keyword when C++11 is enabled, and use it in a few places
+ * Avoid CPLEscapeString (CPLES_URL) encoding some characters unnecessarily (#5526)
+ * Add CPLTestBool(), CPLTestBoolean(), CPLFetchBool()
  * Fix CPLGetValueType() to recognize D1 as a string and not a real number (#6305)
- * /vsistdout/: flush when closing the handle (#6149)
  * CPLFormFilename(): use '/' directory separator on Windows on /vsicurl_streaming/ files (#6310)
+ * Add hack enabled by -DDEBUG_BOOL to detect implicit int->bool conversions that dislike MSVC (#6325)
+ * Add hack to '#define NULL nullptr' when NULL_AS_NULLPTR is defined. Must be used together with -std=c++11 -Wzero-as-null-pointer-constant with GCC to detect misuses of NULL/nullptr (#6327)
+ * Add VSIError mechanism to store errors related to filesystem calls, and use it for /vsis3/. Add new CPLE_ error numbers. (https://github.com/OSGeo/gdal/pull/98)
 
-== GDAL Core ==
- * Fix memory leaks if GDALAllRegister is not called (#6139)
- * Make private member of GDALDataset really opaque so as to be able to extend it without breaking the C++ ABI (#6163)
+Core:
+ * Change default value of GDAL_CACHEMAX to 5% of usable physical RAM
+ * Allow open options name to be prefixed by @ to be silently ignored when not existing in driver options (RFC 60)
+ * Honour NBITS metadata item when doing RasterIO() with non-nearest resampling (#6024)
+ * GDALClientServer: pass open options to INSTR_Open call
+ * Improve performance of GDALCopyWords() float->byte/int16/uint16 by using SSE2
+ * Decorate prototypes of RasterIO() related operations with CPL_WARN_UNUSED_RESULT
  * Avoid deadlock when writing 2 datasets in 2 threads (#6163)
+ * Remove obsolete symbols __pure_virtual(), GDALCreateProjDef(), GDALReprojectToLongLat(), GDALReprojectFromLongLat() and GDALDestroyProjDef()
+ * Remove obsolete non-template-based implementation of GDALCopyWords(). We don't support anymore such compilers
+ * GDALJP2Box::ReadBoxData(): do not abort if memory allocation fails
+ * Add GDALAdjustValueToDataType() in C API, and use it in GDALTranslate() and GDALWarp()
+ * GDALDefaultOverviews::CreateMaskBand(): fix logic error related to writing per-band mask
  * Block cache: fix excessive memory consumption when dealing with datasets with different block sizes (#6226)
- * Fix leak in GetMetadataItem() on GDALProxyPoolDataset (#6238)
+ * EXIFExtractMetadata(): fix potential 1-byte write buffer stack overflow 
  * MDReader: do no attempt reading side-car files on /vsisubfile/ (#6241)
- * Fix potential buffer overflow in PamHistogramToXMLTree() (#6266)
+ * GDALCheckBandCount(): allow by default a maximum number of bands to 65536
+ * GDALOpenInfo: add StealSiblingFiles() and AreSiblingFilesLoaded() methods
+ * GDALOpenInfo::GetSiblingFiles(): give up after GDAL_READDIR_LIMIT_ON_OPEN (default=1000) files in the directory
+ * GDALDefaultOverviews: add TransferSiblingFiles() method
+ * GDALDriver::DefaultCreateCopy(): fix logic related to propagation of NBITS / PIXELTYPE metadata items as creation options
+ * Reorder driver registration a bit so that formats with efficient identification are probed first
+ * Add GDALIdentifyEnum (GDAL_IDENTIFY_UNKNOWN, GDAL_IDENTIFY_FALSE or GDAL_IDENTIFY_TRUE) for return values of Identify()
+ * GDALLoadRPCFile(): load .rpc files from Ikonos products that have extra end-of-line character (#6341)
+ * Export GDALRegenerateOverviewsMultiBand() symbol, but mostly for plugins (#6342)
+ * Add GDAL_NO_AUTOLOAD to compile out the body of AutoLoadDriver (#6380)
+ * Avoid ComputeStatistics(), GetHistogram() and ComputeRasterMinMax() to use only the first column of blocks in approximation mode for a raster whose shape of blocks is a square (#6378)
+ * Add GDALGetDataTypeSizeBits() and GDALGetDataTypeSizeBytes().
+ * GDALReadOziMapFile(): fix reading Ozi external files from virtual file systems (https://github.com/OSGeo/gdal/pull/114)
+ * Add CPLSetCurrentErrorHandlerCatchDebug() to enable custom error handlers not to intercept debug messages
 
-== GDAL Algorithms ==
- * Warp: avoid really excessive processing time for some warping with target areas completely off the source raster (especially when involving RPC) (#6182)
+Algorithms:
+ * RPC transformer: provide SSE2 accelerated transformer
+ * RPC: fix off-by-half pixel computation of (pixel, line), and in bilinear and bicubic RPC DEM interpolation; fix off-by-one pixel registration for Pleiades RPC (#5993)
+ * RPC: make RPCInverseTransformPoint() check convergence has been reached (#6162)
+ * RPC DEM: optimize when DEM is in NAD83 or any other geodetic CS that transform as a no-op to WGS 84
+ * RPC DEM: take into account vertical datum of the DEM when present to convert DEM elevations to ellipsoidal heights (#6084)
+ * RPC DEM: do fallback cubic -> bilinear and bilinear -> near on DEM edges
+ * RPC DEM: improve inverse transformer to validate error threshold and improve convergence (#6162, #6377)
+ * TPS solver: discard duplicated GCP to avoid avoidable error, warning when 2 GCPs have same (pixel,line) but different (X,Y) or the reverse
+ * Warper: rework multithreaded computations to use a thread pool rather than forking threads each time
+ * Warper: avoid really excessive processing time for some warping with target areas completely off the source raster (especially when involving RPC) (#6182)
+ * gdal_grid: add linear interpolation algorithm
+ * gdal_grid: add invdistnn algorithm, variation on the existing inverse distance weighting algorithm with quadtree to search for points only in the neighborhood (#6038)
+ * gdal_grid: fix crash in optimized mode with GCC 4.4 on 64bit (#5987)
+ * gdal_grid: compile gdalgrid AVX optimization for Windows when supported by compiler
+ * Add GDALTriangulationXXXX() API through libqhull
+ * Sieve filter: fix crash on nodata polygons (#6096)
+ * Sieve filter: improvement to walk through the biggest neighbour chain until we find a polygon larger than the threshold (#6296)
+ * GDALFPolygonize(): factor implementation with integer case
+ * GDALComputeMedianCutPCT(): fix to make it work with rasters with more than 2 billion pixels (#6146)
+ * Overview: Make average and gauss methods aware of transparent color table entries (#6371)
 
-== Utilities ==
- * ogr2ogr: prevent from the gt setting to override transaction group size of 1 set by skipfailures earlier (#2409)
- * ogr2ogr: fix -skip mode to rollback current transaction in case of failed insertion (#6328)
- * gdalmove.py: fix to run with GDAL 2.0 gdal.InvGeoTransform() signature (#6173)
- * gdaladdo: emit error message if passed an invalid dataset name (#6240)
+Utilities:
+ * gdalinfo: workaround bug in proj <= 4.9.1 on datasets with a SRS with a vertical shift grid (#6083)
+ * gdal_translate: detect more reliably if specified bands are not in default order
+ * gdal_rasterize: do on-the-fly reprojection of input vector onto output raster
+ * gdal_rasterize: rasterize: always create output with 1/2 cell buffer of input geometry envelope (#6058)
+ * gdal_rasterize: add the -dialect option
+ * gdalwarp: add -doo option to specify open options of (existing) output dataset
+ * gdalwarp: if RPC_DEM warping option is specified, use exact transformer by default (#5993)
+ * gdalwarp: make it honour nodata value of existing dataset (if -dstNoData isn't explicitly specified)
+ * gdalwarp: do not propagate STATISTICS_ of second or following source datasets
+ * gdalwarp: do not emit warning when using -cutline with a SRS and the source raster has RPC or GEOLOCATION
+ * gdalwarp: check that the cutline is valid after transformation/reprojection
+ * gdalwarp: better deal when dealing with a mix of RGB and RGBA datasets as input
  * gdalwarp: fix -srcnodata to not put garbage values as target dstnodata (#6315)
+ * gdalwarp: densify cutline to avoid invalid geometry after reprojection to source raster, especially in the RPC case (#6375)
+ * gdalserver: add a -nofork mode (Unix only for now), so that multiple clients can connect to the same dataset. Useful for safe 'concurrent' updates
+ * add gdal_pansharpen.py script
+ * gdal2tiles.py: fix error on a raster with less than 3 bands that resulted in a 'IndexError: list index out of range'
+ * gdal2tiles.py: Change EPSG:3785 / EPSG:900913 into EPSG:3857 (#5622)
+ * gdal2tiles.py: add Leaflet template (https://github.com/OSGeo/gdal/pull/71)
+ * gdal2tiles.py: add -q switch for quiet mode
+ * gdaldem: correctly deal with NaN as nodata value (#6066)
+ * gdaldem color-relief: deal with the case of repeated entries with the same value and the input raster has pixels that match that value exactly (#6422)
+ * gdaladdo: emit error message if passed an invalid dataset name (#6240)
+ * gdaladdo: do not silence warnings when opening in update mode, if the open is succesful
+ * gdalbuildvrt: fix potential crash when using -b switch (#6095)
+ * gdalbuildvrt: accept nan as value for -srcnodata and -vrtnodata
+ * gdalbuildvrt: return non zero return code if the flush of the VRT to disk failed
+ * gdal_merge.py: takes again into account -n flag (#6067)
+ * gdalbuildvrt / gdal_translate / VRT: use floating point values for source and destination offsets and sizes (#6127)
+ * gdalmove.py: fix to run with GDAL 2.0 gdal.InvGeoTransform() signature
 
-== GDAL drivers ==
+Python samples:
+ * gdalpythonserver.py: update to protocol 3
+ 
+AAIGRID:
+ * when writing with floating-point values, ensure at least one value has a decimal point to avoid issues with some readers (#6060)
 
-BSB driver:
- * remove broken and useless logic to deal with extension lines in headers (#6307)
+BMP driver:
+ * BMP: avoid too big color table allocation in case of wrong iClrUsed value
+
+BLX driver:
+ * converted to support VirtualIO
 
 ECRG driver:
+ * change subdataset definition to make sure that they only consist of frames of same scale (#6043)
  * fix base34 decoding and Windows filename handling (#6271)
 
+ECW driver:
+ * use wide char Open API on Windows when GDAL_FILENAME_IS_UTF8=YES (https://github.com/OSGeo/gdal/pull/70)
+
+GeoRaster driver:
+ * fix deflate read error depending on endianness (#6252)
+
+GIF driver:
+ * libgif: partial resync with giflib master (but keep ABI of 4.1.6)
+ * fix crash when CreateCopy a source with one color in the color table
+
+GMT driver:
+ * validate raster dimensions on opening, and acquire mutex in dataset destructor
+
+GPKG driver:
+ * write support: fix various issues in update scenarios when interacting with the GDAL block cache that could result in lost/corrupted band data to be written in tiles (#6309)
+ * write support: fix potential use of freed sqlite temporary DB handle when generating overviews with partial tiles (#6335)
+ * write support: fix potential crash in scenarios when block cache is full (#6365)
+ * write support: fix inversion of row/column in one of the SQL request involved in partial tiles management (#6339)
+
 GTiff driver:
- * [2.0 regression] fix problem with implicit overviews of JPEG-compressed files (#6308)
- * fix potential memleak in GTiffDataset::GetJPEGOverviewCount() (#6318)
+ * add NUM_THREADS creation and open options to enable multi-threaded compression
+ * fix GTiffDataset::IsBlockAvailable() wrong behaviour when compiling against internal libtiff, when a BigTIFF file has a TileByteCounts with LONG/4-byte counts and not LONG8 (#6001)
+ * Correctly take into account overridden linear units for a geotiff with a EPSG PCS code (#6210, #4954)
+ * make VirtualMemIO() work with non native endianness
+ * improve VirtualMemIO() performance in tiled Contig read to single band copy
+ * improve single band tiled VirtualMemIO reading
+ * improve DirectIO() to work on tiled uncompressed geotiff, for non-resampling and nearest resampling cases. Also improve performance of resampling cases on un-tiled files
+ * fix DirectIO() mode with complex types and inverted endianness (#6198)
+ * optimize writing of 12-bit values
+ * implement lazy loading of .aux.xml and .tfw/.wld
+ * Internal libtiff: update to CVS HEAD post libtiff 4.0.6
+ * make SetColorInterpretation(GCI_AlphaBand) work on a 5 band or more GeoTIFF (#6102)
+ * automatically set PHOTOMETRIC=RGB if manually assigning color interpretation Red,Green,Blue to band 1,2,3 before directory crystallization (#6272)
+ * add GEOTIFF_KEYS_FLAVOR=ESRI_PE creation option to write EPSG:3857 in a ESRI compatible way (#5924)
  * call XTIFFInitialize() in LibgeotiffOneTimeInit() as the former isn't thread-safe, so better call it from the later which is thread-safe (#6163)
- * fix writing other angular units than degree (namely arc-second, arc-minute, grad, gon and radian) (#6171)
- * fix reading angular unit value for angular units than degree (#6171)
+ * fix reading and writing angular units different from degree (namely arc-second, arc-minute, grad, gon and radian) (#6171)
  * do not use VirtualMemIO optimization on compressed /vsimem/ files (#6195)
- * fix DirectIO() mode with complex types and inverted endianness (#6198)
  * correctly set GTRasterTypeGeoKey=RasterPixelIsPoint if AREA_OR_POINT=Point but there is no SRS set (#6225)
+ * improve a bit error detection when writing
+ * check free space before writing (only for big, non sparse, uncompressed)
  * do not read large 'one row' JBIG compressed files with the scanline API (#6264)
- * fix SetMetadata() to properly clear existing PAM metadata (complement to #5807)
- * prevent potential out of bounds read to TIFFTAG_EXTRASAMPLES (#6282)
+ * Fix SetMetadata() to properly clear existing PAM metadata (complement to #5807)
+ * prevent potential out of bounds read/write to TIFFTAG_EXTRASAMPLES (#6282)
  * do not use first directory as potential mask, to avoid assertion in GTiffDataset::SetDirectory() (#6287)
  * reject files with strips/tiles/scanlines bigger than 2 GB to avoid 32 bit integer overflow.
    Also in case of files with Contig PlanarConfiguration do not make reading one block for band 2 OK when reading for band 1 issued an error (#6288)
+ * GTIFFWriteDirectory(): avoid memory leak of codec related memory (#2055)
+ * Make ALPHA=NO in CreateCopy() cancel alpha color interpretation even if present in source raster
+ * fix problem with implicit overviews of JPEG-compressed files (#6308)
+ * fix compilation problem with internal libtiff if DEFER_STRILE_LOAD isn't defined (which is not the default configuration) (https://github.com/OSGeo/gdal/pull/90)
+ * use more appropriate error message when 4GB threshold is reached with external overviews, and try to make doc of BIGTIFF=IF_NEEDED/IF_SAFER clearer (#6353)
 
-GPKG driver:
- * fix various issues in update scenarios when interacting with the GDAL block cache that could result in lost/corrupted band data to be written in tiles (#6309)
- * fix potential use of freed sqlite temporary DB handle when generating overviews with partial tiles (#6335)
+HDF4 driver:
+ * Skip quotation mark when parsing HDF-EOS metadata.
+
+HDF5 driver:
+ * add Komsat Mission ID to possible value for HDF5 SAR product (https://github.com/OSGeo/gdal/pull/103)
+
+HF2 driver:
+ * fix reading side of the driver to work on architectures where char is unsigned, like PPC or ARM (#6082)
 
 HFA driver:
- * fix crash when nNumRuns = 0 with RLE compression (#6208)
- * avoid potential out-of-bounds buffer write (#6286)
+ * when reading projection, preserve EPSG code if AutoIdentifyEPSG() identified the SRS, even if a PE string is present (#6079)
+ * keep TOWGS84 even when using ESRI PE string (#6158)
+ * fix crashes on corrupted files (#6208, #6286)
+
+INGR driver:
+ * check that RLE decoding produced the expected number of bytes and error out otherwise; test that 'random' line seeking actually works
+
+JPEGLS driver:
+ * fix build error (#6430)
+
+JP2ECW driver:
+ * honour psExtraArg->eResampleAlg when upsampling (#6022)
+
+JP2KAK driver:
+ * honour psExtraArg->eResampleAlg when upsampling (#6022)
+ * try rounded dimensions to decide if the data is being requested exactly at a sub-resolution
+ * support v7.7 on Unix (additional changes potentially needed on Windows)
+
+JP2OpenJPEG driver:
+ * Safer multi-threaded use
+
+JPEG driver:
+ * add USE_INTERNAL_OVERVIEWS open option (default to TRUE as in recent versions, can be set to FALSE to hide internal overviews
+
+KMLSuperOverlay driver:
+ * fix 2.0 regression with some RasterIO() requests involving resampling (#6311)
+ * recognize datasets that have a intermediate <Folder> that forms a <Document><Folder><Region/><GroundOverlay/> structure (#6343)
 
-KMLSuperoverlay driver:
- * [2.0 regression] fix errors happening with some RasterIO() requests involving resampling (#6311)
+LCP driver:
+ * fix wrong use of endianness macros to fix behaviour on big-endian hots
 
-netCDF driver:
+Leveller driver:
+ * update to v9 read support (#5632,)
+
+MBTiles driver:
+ * add raster write support
+
+MEM driver:
+ * avoid 32 bit overflows
+
+NetCDF driver:
+ * add support for reading NC4 unsigned short attributes and variables (#6337) * read correctly nodata values in [128,255] range for (unsigned) Byte data type (#6175)
+ * implement Get/SetUnitType() using the standard units attribute (https://github.com/OSGeo/gdal/pull/96)
+ * optimize IReadBlock() and CheckData() handling of partial blocks in the x axis by re-using the GDAL block buffer instead of allocating a new temporary buffer for each block (#5950)
+ * full read/write support for new NetCDF4 types NC_UBYTE, NC_USHORT, NC_UINT and NC_STRING for variables (except for NC_STRING) and attributes (https://github.com/OSGeo/gdal/pull/99)
+ * add support for the geostationary projection (#6030)
  * fix one byte heap write overflow in NCDFTokenizeArray() (#6231)
  * fix potential buffer overflows with uses of nc_inq_varname(), nc_inq_attname() and nc_get_att_text() (#6227)
  * validate that gridmapping:GeoTransform has 6 values (#6244)
- * NCDFIsGDALVersionGTE(): validate content of NC_GLOBAL#GDAL variable (#6245)
+ * fix wrong use of deallocator when writing a GEOLOCATION array, and other issues
+ * limit number of bands reported to 32768 by default
+ * validate raster dimensions
+ * validate content of NC_GLOBAL#GDAL variable (#6245)
+
+NGSGEOID driver:
+ * make it work on > 2GB file
 
 NITF driver:
- * fix TRE parser to properly deal with variable length items not in first nesting level, such as ENGRDA (not added in nitf_spec.xml in this changeset) (#6285)
+ * data/nitf_spec.xml: Add CSCCGA, MENSRB, SENSRB, STREOB, ENGRDA, EXPLTB and PATCHB TREs (https://github.com/OSGeo/gdal/pull/81, #6285, https://github.com/OSGeo/gdal/pull/86)
+ * fix parser to properly deal with variable length items not in first nesting level
+
+Northwoord driver:
+ * fix computation of intermediate color table values on non-Intel platforms (#6091)
+
+NTv2 driver:
+ * support reading/writing/appending to files with big-endian order (cf https://github.com/OSGeo/proj.4/issues/345)
+
+OpenJPEG driver:
+ * do not expose block dimensions larger than dataset dimensions to avoid wasting memory (#6233)
+
+PCIDSK driver:
+ * Remove the old driver (#6172)
 
 PDF driver:
+ * add PDFium library as a possible back-end. Initial support contributed by Klokan Technologies GmbH  (http://www.maptiler.com/)
+ * workaround a bug of PoDoFo 0.9.0 by avoiding loading of vector content in raster-only mode (doesn't prevent the crash if reading the vector layers) (#6069)
+ * make OGC BP registration work with media box where bottom_y is negative and top_y = 0 (in non rotated case)
+ * make OGC BP registration work with media box where min_x != 0 (in non-rotated case)
  * correctly take into account non-meter linear units with OGC BP encoding, and add support for US FOOT (#6292)
 
 PDS driver:
  * change default values of PDS_SampleProjOffset_Shift and PDS_LineProjOffset_Shift to 0.5 (#5941)
+ * fix nodata value for UInt16 to be 0 (#6064)
+ * accept 'ODL_VERSION_ID = ODL3' in header (#6279)
 
-USGSDEM driver:
- * fix CreateCopy() with VS 2015 (#6257)
+PGChip driver:
+ * driver removed from sources
+
+PNG driver:
+ * Support writing 1, 2 or 4 bit single band
+ * Add NBITS creation option
+ * fix XML of creation option list
+ * Update internal libpng to 1.2.56
+
+PostgisRaster driver:
+ * avoid Identify() to recognize OGR PostgreSQL connection strings with schemas option and cause loud 'QuietDelete' (#6034)
+
+Raw drivers:
+ * better support for direct read of more than 2GB in single gulp (untested though)
+
+RIK driver:
+ * fix Identify() method to recognize again non-RIK3 RIK datasets (#6078)
+
+RMF driver:
+ * implement GetNoDataValue()
+
+ROIPAC driver:
+ * Support offset and scale band (#6189)
 
 VICAR driver:
  * change PDS_SampleProjOffset_Shift and PDS_LineProjOffset_Shift default values to 0.5 (#5941)
- * VICARKeywordHandler::Ingest(): fix potential buffer overflows (#6256)
- * be robust to truncated files (#6321)
+ * fix loss of precision in scale and offset
 
 VRT driver:
+ * expose implicit 'virtual' overviews for VRT whose bands are made of a single SimpleSource/ComplexSource
+ * gdalvrt.xsd: Add capitalized versions of true and false (#6014)
+ * GetSingleSimpleSource(): check there's a single source (#6025)
+ * honour VRTRasterBand NBITS metadata with SimpleSource and ComplexSource
+ * properly take into account nodata value declared at VRT band level when doing resampling with non-nearest
+ * honour relativeToVRT when using AddBand() to add a VRTRawRasterBand (https://github.com/OSGeo/gdal/pull/67)
+ * VRT warp: fix crash with implicit overviews and destination alpha band (#6081)
+ * make GetDefaultHistogram() on a sourced raster band save the result in the VRT (#6088)
  * serialize NODATA and NoDataValue items with %.16g, e.g. so as to be able to hold large int32 nodata values (#6151)
+ * VRTSourcedRasterBand: make ComputeRasterMinMax() and ComputeStatistics() forward bApproxOK to overview band (useful for implicit overviews)
+ * make CreateCopy() preserve NBITS metadata item
+ * avoid loading sibling file list if not available
  * VRT raw: don't truncate last figure of ImageOffset if there are left space padding (#6290)
+ * VRTWarpedDataset::SetMetadataItem(): fix crash when calling with name=SrcOvrLevel and value=NULL (#6397)
+ * Warped VRT: fix deadlock in situation where warped VRT datasets are read in multiple threads and the block cache reaches saturation. Also add a GDAL_ENABLE_READ_WRITE_MUTEX config option that can be set to NO to disable the read/write mutex mechanism in cases where it would deadlock (#6400)
 
 WMS driver:
+ * add a IIP (Internet Imaging Protocol) minidriver
  * limit number of zoom levels for ArcGIS MapServer JSon (#6186)
+ * determine a resolution that will not result in a number that is larger than the maximum size of an integer.  Any value that exceeds the maximum size of an integer will raise an invalid dataset dimensions error. (https://github.com/OSGeo/gdal/pull/89)
 
-XPM driver:
- * fix vulnerabilities in reading (#6253)
+== OGR 2.1.0 - Overview of Changes ==
 
-== OGR core ==
- * OGRSQL: correctly sort NULL values in first positions (#6155)
+Core:
+ * Add OGREditableLayer class to add editing capabilities to drivers with none or limited editing capabilities
+ * OGRGeometry: add DelaunayTriangulation() method (GEOS >= 3.4)
+ * OGRGeometry and derived classes: implement copy constructor and assignment operator (#5990)
+ * OGRGeometry: Fix result of Equals on POINT EMPTY with POINT(0 0)
+ * OGRFeature SetField(): more type conversions allowed, particularly with array types
+ * OGRFeature::SetGeometry()/SetGeometryDirectly(): make it work when passed geometry is the currently installed geometry (#6312)
+ * OGR SQL: do not silently skip NULL values in the first records when evaluating a SELECT DISTINCT (#6020)
+ * OGR SQL: correctly sort NULL values in first positions (#6155)
+ * Add OGRUpdateFieldType()
+ * Decorate a few functions/methods of the OGR layer API with CPL_WARN_UNUSED_RESULT
+ * WKT export: use 15 significant figures, instead of 15 figures after decimal point (#6145)
+ * WKT export: do not append .0 after non-finite values (#6319)
+ * Fix typo in definition of name of OGR_FD_ReorderFieldDefns (final s was missing)
  * OGRLayer::SetIgnoredFields(): properly reset state of non first geometry fields (#6283)
  * Make OGRLayer::SetSpatialFilter(GetSpatialFilter()) work with non empty spatial filter (#6284)
+ * OGRLayerDecorator: add missing CreateGeomField()
  * OGRLayer::Erase(): do not discard input geometries that have no intersection with method layer (#6322)
- * OGRFeature::SetGeometry()/SetGeometryDirectly(): make it work when passed geometry is the currently installed geometry (#6312)
+ * OGRLayer::Erase(): Speedup = ~70%
+ * Add OGRPreparedGeometryContains()
+ * Use prepared geometry intersects as pretest in layer Intersection, Union, and Identity methods if requested.
+   Use prepared geometry containment as pretest in layer Intersection method if requested.
+ * Bail out from layer algebra methods if GEOS calls fail and not SKIP_FAILURES.
+ * OGR_G_SetPoints(): error out if padfX or padfY == NULL, do not change coordinate dimension to 3D when pabyZ == NULL, fix optimization on linestring to call setPoints() only if the strides are the ones of a double, not 0 as incorrectly done before (#6344)
 
-== OGRSpatialReference == 
- * morphFromESRI(): map Mercator_Auxiliary_Sphere to EPSG:3857 (#5924)
+OGRSpatialReference:
+ * Upgrade to EPSG database v8.8
+ * Add support for SCH (Spherical Cross-track Height) projection
+ * Optimize reprojection typically between WGS84 based SRS and WebMercator
+ * Correctly transform Mercator_2SP and _1SP to ESRI Mercator, and back from ESRI Mercator to Mercator_2SP (#4861)
+ * No longer enforce C locale if running against latest proj that is locale safe (4.9.2 or later)
+ * EPSGGetPCSInfo(): use pcs.override.csv in priority over pcs.csv to read projection name, UOM, UOMAngle, GeogCS, etc... (#6026)
+ * morphToESRI(): use GCS_WGS_1972 as GCS name for EPSG:4322 (#6027)
+ * morphToESRI(): use Mercator_Auxiliary_Sphere projection for EPSG:3857. morphFromESRI(): map Mercator_Auxiliary_Sphere to EPSG:3857 (#5924)
+ * Align hard-coded WKT of well known GCS definitions of WGS84, WGS72, NAD27 and NAD83 with the WKT of their EPSG def (#6080)
  * morphFromESRI(): special case with PROJCS name 'WGS_84_Pseudo_Mercator' (#6134)
  * OSR C API: fix declarations of OSRSetAxes() and OSRSetWagner(), and add missing OSRSetHOMAC(), OSRSetMercator2SP() and OSRSetTPED() (#6183)
+ * Recognize EPSG 9835 method (Lambert Cylindrical Equal Area (Ellipsoidal)), needed for EPSG:6933 PCS for example
+ * importFromProj4/exportToProj4(): rework linear unit conversion between WKT name/values and proj4 unit name, and extend its scope in WKT to proj4 conversions
+ * OSR ESRI .prj: add support for reading custom ellipsoid in Parameters line
+ * on import of +proj=geos, if +sweep=x is used then store it as a proj4 extension node (#6030)
 
-== OGR drivers == 
+Utilities:
+ * ogrinfo / ogr2ogr: implement @filename syntax for -sql and -where
+ * ogr2ogr: prevent the -gt setting from overriding transaction group size of 1 set by skipfailures earlier (#2409)
+ * ogr2ogr: warn if -zfield field does not exist in source layer
+ * ogr2ogr -skip: rollback dataset transaction in case of failure (#6328)
+ * ogr2ogr: fix -append with a source dataset with a mix of existing and non existing layers in the target datasource (#6345)
+ * ogr2ogr: imply quiet mode if /vsistdout/ is used as destination filename
+ * ogr2ogr: make -dim and -nlt support measure geometry types
+
+CartoDB:
+ * fix GetNextFeature() on a newly create table (#6109)
+ * defer 'CartoDBfycation' at layer closing
+ * optimize feature insertion with multiple rows INSERT
 
 CSV driver:
- * Make OGRCSVLayer::CreateGeomField() returns OGRERR_NONE in case of success instead of OGRERR_FAILURE (#6280)
+ * add editing capabilities of existing files
+ * add X_POSSIBLE_NAMES, Y_POSSIBLE_NAMES, Z_POSSIBLE_NAMES, GEOM_POSSIBLE_NAMES and KEEP_GEOM_COLUMNS open options
+ * add HEADERS open option to force OGR to handle numeric column names. (PR #63)
+ * add EMPTY_STRING_AS_NULL=YES/NO open option
+ * implement compatibility enhancements for GeoCSV specification (#5989)
+ * fix detection of TAB delimiter in allCountries.csv when the first line has a comma (#6086)
+ * fix issues with leading single quote, and missing first line after ResetReading(), when parsing allCountries.txt (#6087)
+ * speed-up GetFeatureCount() on allCountries.txt
+ * on CreateDataSource() with a .csv name, do not try to open other existing .csv files in the directory
+ * make CreateGeomField() returns OGRERR_NONE in case of success instead of OGRERR_FAILURE (#6280)
+ * avoid adding trailing comma in header line when writing 'WKT,a_single_field'
+
+DGN driver:
+ * add partial 3D transformation support for cell headers
+
+DXF driver:
+ * detect files without .dxf extension (#5994)
+ * fix handling of ELLIPSE with Z extrusion axis = -1 (#5705)
+
+ElasticSearch driver:
+ * use get /_stats instead of /_status for ElasticSearch 2.0 compatibility (#6346)
+
+FileGDB driver:
+ * make CreateFeature() honour user set FID, and implement more fine grained transaction for Linux/Unix
+ * give a hint of using FileGDB SDK 1.4 is FileGDB compression is used
 
 GeoJSON driver:
- * [2.0 regression] fix crash on null / non-json object features (#6166)
- * make sure there's enough space to write the FeatureCollection bbox (#6262)
+ * Add editing capabilities of existing files
+ * Add ARRAY_AS_STRING=YES open option
+ * Use '%.17g' formatting by default for floating-point numbers and add SIGNIFICANT_FIGURES layer creation option (#6291)
+ * add a json_ex_get_object_by_path() function
+ * fix crash on null / non-json object features (#6166)
+ * serialize string values that are valid JSon dictionary or array as it (ie do not quote them)
+ * make sure there's enough space to write the FeatureCollection bbox (#6262). Also avoid duplicating FeatureCollection bbox if source has one (trunk only)
+ * Export POINT EMPTY as having a null geometry, instead as of being POINT(0 0) (#6349)
+ * Do not 'promote' a null field to OFTString type if it had another type before (#6351)
+
+GME driver:
+ * Driver removed.  Maps Engine being shut down at the end of January 2016.
 
 GML driver:
+ * VFR: add new attribute DatumVzniku (v1.6)
+ * VFR: fix ST_UVOH type handling
+ * VFR: fix ZpusobyOchrany attributes (data types and names)
+ * VFR: fix CisloDomovni attributes (Integer->IntegerList)
+ * VFR: fix TEA attributes of StavebniObjekty
+ * add NAMESPACE_DECL=YES option to OGR_G_ExportToGMLEx() to add xmlns:gml=http://www.opengis.net/gml or http://www.opengis.net/gml/3.2 declaration; Also accept GML2 or GML32 as valid valiues for FORMAT option (#6214)
  * serialize in .gfs file the name of the geometry element when it is 'geometry' since this is a particular case (#6247)
  * fix logic error in BuildJointClassFromScannedSchema() (#6302)
- * VFR: fix broken processing VFR ST_UVOH files (#6248)
- * VFR: fix reading ZpusobOchrany attributes (#6258)
+
+GPKG driver:
+ * make it accept files with non standard extension if they still have the correct application_id (#6396); also accept the .gpkx extension that may be used for extended geopackages
+ * emit warning when generating a database without .gpkg/.gpkx extension (#6396)
+ * as GPKG 1.1 uses a different application_id, emit a more specific warning if the application id starts with GPxx (but is not GP10). Add GPKG_WARN_UNRECOGNIZED_APPLICATION_ID config option to avoid the warning
+ * correct scope of gpkg_geom_XXXXX extensions to be read-write, and allow reading geometry types CURVE or SURFACE
+ * avoid trying to insert a gpkg_geom_XXXX extension if already done (#6402)
 
 GPX driver:
- * [2.0 regression] fix crash when parsing a 'time' extension element at route/track level (#6237)
+ * fix crash when parsing a 'time' extension element at route/track level (2.0 regression, #6237)
 
 ILI driver:
- * Support for Surface polygon rings spread over multiple geometry records (#5099)
+ * ILI1: Support for Surface polygon rings spread over multiple geometry records
+ * ILI1: add string TID support (https://github.com/OSGeo/gdal/pull/91)
+ * Fix crash with models using types derived from INTERLIS
+ * Fix memory leaks (#6178)
+
+JML driver:
+ * remove arbitrary limitation preventing from reading geometries with <gml:coordinates> larger than 10 MB (#6338)
+
+KML driver:
+
+LIBKML driver:
+ * for documents without folder, use document name when available as name of layer (#6409)
+
+Memory driver:
+ * add support for sparse feature IDs
+ * add ADVERTIZE_UTF8 layer creation option
 
 MITAB driver:
- * add support for block sizes other than 512 bytes in .map files, for MapInfo 15.2 compatibility (#6298)
+ * Add support for block sizes other than 512 bytes in .map files, for MapInfo 15.2 compatibility (#6298)
+ * write correct datum id for EPSG:3857
  * read MID files with TAB delimiter and empty first field (#5405)
  * use projection code 29 when exporting non-Polar Lambert Azimuthal Equal Area (#5220)
- * fix segfault when parsing a Region 0 (#6273)
- * TABPolyline::ReadGeometryFromMIFFile(): fix segfaults on invalid geometries (#6273)
- * TABRectangle::ReadGeometryFromMIFFile(): fix crash on malformed ROUNDRECT (#6273)
+ * fix crashes when parsing invalid MIF geometries (#6273)
 
 MSSQLSpatial driver:
+ * Implement MSSQL bulk insert (#4792)
  * do not treat a primary key that is not of integer type as the FID (#6235)
 
 NTF driver:
  * fix potential buffer overflows when reading too short lines (#6277)
 
+ODBC driver:
+ * remove limitations to 500 columns
+
+ODS driver:
+ * fix loss of precision in formula computation
+
 OpenFileGDB driver:
+ * do not emit warning if SDC/CDF table detected and that FileGDB driver is present
  * fix min/max on columns without indices (#6150)
- * fix import of MultiLineString Z geometries with several parts (#6332)
+ * build correct geometry for a multi-part wkbMultiLineStringZ (#6332)
+
+OSM driver:
+ * correct fields ids for the (non frequently used) Node message
+ * do not override 'our' osm_id (the node, way or relation id) with a tag named 'osm_id' (#6347)
 
 PG driver:
- * fix memleak in ExecuteSQL() (#6179)
+ * Add PRELUDE_STATEMENTS and CLOSING_STATEMENTS open option to be for example able to specify options, like statement_timeout, with pg_bouncer
+ * Fix 2.0 regression when overwriting several existing PostGIS layers with ogr2ogr (#6018)
+ * Update PG, PGDump and CartoDB drivers to correctly export POINT EMPTY for PostGIS 2.2
  * avoid reseting error potentially emitted by ExecuteSQL() (#6194)
+ * sanitize management of quoting for FID column at layer creation
+ * fix to get SRID on result layer with PostGIS 2.2
+ * in copy mode (the default on layer creation), do not truncate the concatenated string list to the field width (#6356)
+ * make such that GEOMETRY_NAME layer creation option is honoured in ogr2ogr when the source geometry field has a not-null constraint (#6366)
+ * read and set DESCRIPTION metadata item from/into pg_description system table; add DESCRIPTION layer creation option
+ * support int2[] and numeric[] types, better map float4[] type
+ * remove code that was intented to handled binary cursors as it cannot be triggered
+ * fix append of several layers in PG_USE_COPY mode and within transaction (ogr2ogr -append use case) (#6411)
 
 PGDump driver:
- * fix issue with case of ogc_fid field in case the FID layer creation option is not set by user or by ogr2ogr (related to #6232)
+ * fix issue with case of ogc_fid field in case the FID  layer creation option is not set by user or by ogr2ogr (related to #6232)
+ * in copy mode (the default on layer creation), do not truncate the concatenated string list to the field width (#6356)
+ * make such that GEOMETRY_NAME layer creation option is honoured in ogr2ogr when the source geometry field has a not-null constraint (#6366)
+ * set DESCRIPTION metadata item from/into pg_description system table; add DESCRIPTION layer creation option
 
-Shape driver:
+Shapefile driver:
+ * accept opening standalone .dbf files whose header length is not a multiple of 32 bytes (#6035)
  * fix REPACK crash on shapefile without .dbf (#6274)
- * fix crash on MultiLineStringM shapes that have no M component (#6317)
-
-VRT driver:
- * fix editing with 'direct' geometry mode which could cause attribute column to be empty (#6289)
-
-== SWIG Language Bindings ==
-
-Perl bindings:
- * Fix incorrect signature in "shadow" feature of Geo::OGR::Feature new (#6181)
- * Add missing osr.t to MANIFEST. Update Makefile.PL to the one in CPAN version.
-
-Java bindings:
- * GNUmakefile: add support for all hardening buildflags (#5998)
-
-= GDAL/OGR 2.0.1 Release Notes = 
-
-The 2.0.1 release is a bug fix release.
-
-== Build ==
- * Build support for Kakadu 7.5 (note: require KAKOBJDIR and KAKFLAGS to be defined in nmake.opt) (#6052)
-
-== Build(Unix) ==
- * Add plugin option for GeoRaster, HDF4, HDF5, FileGDB, OCI and PG drivers (#6012)
-
-== Port ==
- * Fix CPL_LSBINT16PTR() and CPL_LSBINT32PTR() to work with non-byte pointer (#6090)
- * /vsistdin/: fix caching of first 1MB / VRT driver: read XML content from /vsistdin/ in a streaming compatible way (#6061)
- * /vsimem/: implement append mode (#6049)
- * /vsizip/: avoid returning the previous file list of an already opened .zip if it has changed afterwards (#6005)
- * cpl_config.h.in: set svn:eol-style LF to avoid issues with msys mingw (#6013)
-
-== GDAL Core ==
- * Honour NBITS metadata item when doing RasterIO() with non-nearest resampling (#6024)
-
-== GDAL Algorithms ==
- * Sieve filter: fix crash on nodata polygons (#6096)
- * Fix crash on gdalgrid when compiled with ICC when AVX isn't available at runtime (#6089)
- * RPC: fix off-by-half pixel computation of (pixel, line), and in bilinear and bicubic RPC DEM interpolation; fix off-by-one pixel registration for Pleaiades RPC (#5993)
-
-== Utilities ==
- * gdalinfo: workaround bug in released proj versions on datasets with a SRS with a vertical shift grid (#6083)
- * gdalbuildvrt: fix potential crash when using -b switch (#6095)
- * gdalserver: fix compilation with recent GNU libc (such as in Arch Linux) (#6073)
- * gdaldem: correctly deal with NaN as nodata value (#6066)
- * gdal_merge.py: takes again into account -n flag (#6067)
-
-== GDAL drivers ==
-
-AAIGrid:
- * When writing with floating-point values, ensure at least one value has a decimal point to avoid issues with some readers (#6060)
-
-ECRG driver:
- * change subdataset definition to make sure that they only consist of frames of same scale (#6043)
-
-GTiff driver:
- * Fix GTiffDataset::IsBlockAvailable() wrong behaviour when compiling against internal libtiff, when a BigTIFF file has a TileByteCounts with LONG/4-byte counts and not LONG8 (#6001)
 
-HF2 driver:
- * fix reading side of the driver to work on architectures where char is unsigned, like PPC or ARM (#6082)
-
-HFA driver:
- * when reading projection, preserve EPSG code if AutoIdentifyEPSG() identified the SRS, even if a PE string is present (#6079)
-
-JP2ECW driver:
-* Honour psExtraArg->eResampleAlg when upsampling (#6022)
-
-JP2KAK driver:
- * Honour psExtraArg->eResampleAlg when upsampling (#6022)
-
-Northwood driver:
- * fix computation of intermediate color table values on non-Intel platforms (#6091)
-
-PDF driver:
- * workaround a bug of PoDoFo 0.9.0 by avoiding loading of vector content in raster-only mode (doesn't prevent the crash if reading the vector layers) (#6069)
-
-PDS driver:
- * fix nodata value for UInt16 to be 0 (#6064)
-
-PostgisRaster driver:
- * avoid Identify() to recognize OGR PostgreSQL connection strings with schemas option and cause loud 'QuietDelete' (#6034)
-
-Rasterlite driver:
+SQLite/Spatialite driver:
+ * support file:xxx URI syntax (derived from patch by joker99, #6150)
+ * fix heuristics in OGRSQLiteSelectLayer::GetExtent() to not be used when there's a sub SELECT (#6062)
+ * fix crash on GetLayerByName('non_existing_table(geom_column)') (#6103)
+ * fix OGRSQLiteSelectLayerCommonBehaviour::GetBaseLayer() to no longer 'eat' consecutive characters in layer name (#6107)
+ * Spatialite: turn debug messages warning about update not being supported because of missing or too old spatialite version as errors, and return NULL to the caller (#6199)
+ * fix memleak in OGRSQLiteTableLayer destructor when updating geometry_columns_time
 
-RIK driver:
- * fix Identify() method to recognize again non-RIK3 RIK datasets (#6078)
+SXF driver:
+ * fix wrong use of endianness macros to fix behaviour on big-endian hots
+ * add recoding from CP1251 for TEXT attribute that is now decoded
+ * fix various issues (#6357)
 
 VRT driver:
- * Make GetDefaultHistogram() on a sourced raster band save the result in the VRT (#6088)
- * VRT warp: fix crash with implicit overviews and destination alpha band (#6081)
- * VRTDataset::GetSingleSimpleSource(): check there's a single source (#6025)
- * Fix crash on Windows and Mac that may occur with 2 levels of VRT opened in non-shared mode (#6017)
-
-== OGR core ==
- * OGR SQL: do not silently skip NULL values in the first records when evaluating a SELECT DISTINCT (#6020)
-
-== OGRSpatialReference == 
- * morphToESRI(): use GCS_WGS_1972 as GCS name for EPSG:4322 (#6027)
- * EPSGGetPCSInfo(): use pcs.override.csv in priority over pcs.csv to read projection name, UOM, UOMAngle, GeogCS, etc... (#6026)
- * Correctly transform Mercator_2SP and _1SP to ESRI Mercator, and back from ESRI Mercator to Mercator_2SP (#4861)
-
-== OGR drivers == 
-
-CSV driver:
- * Fix issues with leading single quote, and missing first line after ResetReading(), when parsing allCountries.txt (#6087)
- * fix detection of TAB delimiter in allCountries.csv when the first line has a comma (#6086)
-
-CartoDB driver:
- * fix GetNextFeature() on a newly create table (#6109)
- * fix invalid read of memory in OGRCARTODBTableLayer::GetLayerDefnInternal() (#6007)
-
-DXF driver:
- * make it compatible with C++11/C++14 (#6002)
-
-GeoJSON driver:
- * Internal libjson: fix for C11 compatibility (fix runtime crash, #6008)
-
-PG driver:
- * Fix 2.0 regression when overwriting several existing PostGIS layers with ogr2ogr (#6018)
-
-Shapefile driver:
- * accept opening standalone .dbf files whose header length is not a multiple of 32 bytes (#6035)
+ * implement CloseDependentDatasets()
+ * fix editing with 'direct' geometry mode which could cause attribute column to be empty (#6289)
+ * fix crash with a OGRVRTWarpedLayer using a source layer that would have non geometry column (unlikely to happen currently as this would require explicit disabling it, but more likey with following commit that createe VRT non-spatial layer implictly when the source is non-spatial, linked to #6336)
+ * avoid creating an implicit wkbUnknown geometry field when the source has no geometry column and there's no XML elements related to geometry fields (#6336)
 
-SQLite/Spatialite driver:
- * Fix issue with consecutive identical characters in layer name with ExecuteSQL() (#6107)
- * Fix crash on GetLayerByName('non_existing_table(geom_column)') (#6103)
- * fix heuristics in OGRSQLiteSelectLayer::GetExtent() to not be used when there's a sub SELECT (#6062)
+XLSX driver:
+ * fix reading sheets with more than > 26 columns and 'holes' (#6363)
 
 XPlane driver:
  * extend ICAO identifiers to 5 digits (#6003)
 
 == SWIG Language Bindings ==
 
+All bindings:
+ * add a options parameter to gdal.ReprojectImage() to pass warp options
+ * Change ReadRaster and WriteRaster to use GIntBig and the *IOEx-methods
+ * prevent NULL file pointer from being passed to VSIF*L functions
+ * make gdal.Rename() accept Unicode strings
+
+Java bindings:
+ * GNUmakefile: add -f in rm commands
+ * GNUmakefile: add support for all hardening buildflags
+
 Perl bindings:
- * Add basic POD to GDAL.pm.
+ * Fix #6050: string formatting in croak.
+ * Perl Makefile.PL: add support for all hardening buildflags (#5998)
+ * use strict and warnings in overridden constructors.
+ * add $VERSION to ogr_perl.i (OGR.pm), which is required by pause.perl.org.
  * Add some basic module info for CPAN.
- * Add missing files to MANIFEST
- * Use strict and warnings in overridden constructors.
- * string formatting in croak (#6050)
- * Use standard C comments in swig bindings (#6039)
+ * New Makefile.PL, which can download and build GDAL. This allows automatic testing of the CPAN module.
+ * Wrap VSIStdoutSetRedirection
+ * Removed Geo::OGR::Driver and Geo::OGR::DataSource since they are now merged into respective GDAL classes.
+ * Add to the error stack also errors from the bindings
 
 Python bindings:
- * Fix build with SWIG 3.0.6 (#6045)
+ * make Feature.ExportToJson() output boolean value for a boolean field
+ * support floating point coordinates for the source windows of Band.ReadRaster() and Band.ReadAsArray()
+ * fix build with SWIG 3.0.6 (#6045)
+ * make gdal.OpenEx() throw a Python exception in case of failed open when exceptions are enables with gdal.UseExceptions() (#6075)
+ * Disable opening a NumPy dataset with a filename returned by gdal_array.GetArrayFilename(() unless GDAL_ARRAY_OPEN_BY_FILENAME is set to TRUE
+ * disable the warning about using deprecated wkb25DBit constant as it uses a trick that prevents the bindings from being used by py2exe / pyinstaller (#6364)
 
 = GDAL/OGR 2.0 Release Notes =
 
@@ -465,8 +850,8 @@ Algorithms:
  * Warper: fix GDALSuggestedWarpOutput() wrong extent in some circumstances (e.g. dataset of big dimension with world coordinates) (#5693)
  * Warper: fix integer overflow when reprojecting into an area with (part of) bounds completely outside of the source projection (#5789)
  * Warper: add min,max,med,q1 and q3 resampling algorithms (#5868)
- * Warper: add a SRC_COORD_PRECISION warping option to help getting more reproducable output when -wm parameter changes (#5925)
- * Warper: fix failure in GDALSuggestedWarpOut2() when top-left and bottom-right corners tranform to the same point (#5980)
+ * Warper: add a SRC_COORD_PRECISION warping option to help getting more reproducible output when -wm parameter changes (#5925)
+ * Warper: fix failure in GDALSuggestedWarpOut2() when top-left and bottom-right corners transform to the same point (#5980)
  * GDALReprojectImage(): takes into account nodata values set on destination dataset
  * Median cut and dithering: optimizations and enhancements to deal with 8-bit precision (only if using internal interface for now)
  * rasterfill: add option to specify driver to use for temporary files
@@ -534,7 +919,7 @@ BAG driver:
  * change nodata value for uncertainty band to 1e6 (#5482)
 
 BMP driver:
- * backout r17065 change that infered georeferencing based on the resolution information in the BMP header (#3578)
+ * back out r17065 change that inferred georeferencing based on the resolution information in the BMP header (#3578)
 
 DIMAP driver:
  * DIMAP 2: handle the case where the Raster_Data element is in main file (#5018, #4826)
@@ -584,7 +969,7 @@ New capabilities:
  * add GTIFF_VIRTUAL_MEM_IO=YES/NO/IF_ENOUGH_RAM configuration option so that RasterIO() can rely on memory-mapped file I/O (when possible and supported by the OS)
  * support reading and created streamable files
  * for JPEG-compressed TIFF, avoid quantization tables to be emitted in each strip/tile and use optimized Huffman coding by default
- * avoid SetNoDataValue() to immediately 'cryztalize' the IFD
+ * avoid SetNoDataValue() to immediately 'crystallize' the IFD
  * allow unsetting TIFFTAG_SOFTWARE, TIFFTAG_DOCUMENTNAME, etc... by removing them from metadata list or passing None as a value of SetMetadataItem() (#5619)
  * allow lossless copying of CMYK JPEG into JPEG-in-TIFF
  * set alpha on target by default when translating from Grey+Alpha
@@ -748,7 +1133,7 @@ PCIDSK driver:
  * close dataset in case of exception in PCIDSK2Dataset::LLOpen() (#5729)
 
 PCRaster driver:
- * Allign libcsf code with PCRaster raster format code (#5843)
+ * Align libcsf code with PCRaster raster format code (#5843)
  * Implement Create() (#5844)
  * Improve handling of no-data value (#5953)
 
@@ -785,7 +1170,7 @@ VRT driver:
  * make sure nodata value set on VRT raster band is taken into account in statistics computation (#5463)
  * fix ComputeStatistics() on VRT that are a sub-window of source dataset (#5468)
  * VRT raw: fix corrupted serialization on Windows (#5531)
- * implement heuristics to determine if GetMinimum()/GetMaximum() should use the implementation of their sources of not. Can be overriden by setting VRT_MIN_MAX_FROM_SOURCES = YES/NO (#5444)
+ * implement heuristics to determine if GetMinimum()/GetMaximum() should use the implementation of their sources of not. Can be overridden by setting VRT_MIN_MAX_FROM_SOURCES = YES/NO (#5444)
  * VRT warp: avoid to warp truncated blocks at right/bottom edges, so that scale computation is correct
  * fix RasterIO() to be able to fill buffers larger than 2GB (#5700)
  * fix performance problem when serializing into XML a big number of sources
@@ -929,8 +1314,8 @@ GME driver:
 GML driver:
  * add XSD=filename open option
  * add FORCE_SRS_DETECTION, INVERT_AXIS_ORDER_IF_LAT_LONG, CONSIDER_EPSG_AS_URN, READ_MODE, EXPOSE_GML_ID, EXPOSE_FID, DOWNLOAD_SCHEMA and REGISTRY open options
- * fix bug that prevented multiple instanciation of the reader with Xerces backend (#5571)
- * parse correctly GML geometries whose srsDimension attribue is on top-level geometry element and not on posList (#5606)
+ * Fix bug that prevented multiple instances of the reader with Xerces backend (#5571)
+ * parse correctly GML geometries whose srsDimension attribute is on top-level geometry element and not on posList (#5606)
  * add datasource option SRSDIMENSION_LOC=GEOMETRY to be able to write srsDimension attribute on top level geometry element, default on posList unchanged (#5066)
  * add support for reading layers resulting from a WFS 2.0 join query
  * read/write top <gml:description> and <gml:name> as DESCRIPTION and NAME metadata items. Also add GML_ID, DESCRIPTION and NAME creation options
@@ -938,7 +1323,7 @@ GML driver:
  * Fix incorrect geometry cast when reading GML topogeometries (#5715)
  * VFR: fix ST_Z type (changes) -- list all layers
  * VFR: include also non-spatial (removed) features (ZaniklePrvky) in type ST_Z (changes)
- * VFR: use String when 32-bit integer wasn't wide enough
+ * VFR: use String when 32-bit integer was not wide enough
  * VFR: add support for UVOH file type
  * VFR: add missing support for OriginalniHraniceOmpv geometry
  * VFR: update GFS files to RFC31 (OGR 64bit Integer Fields and FIDs)
@@ -1072,7 +1457,7 @@ OpenAir driver:
 OpenFileGDB driver:
  * add compatibility with .gdbtable files bigger than 4 GB (#5615)
  * support opening files with ConfigurationKeyword=MAX_FILE_SIZE_4GB or MAX_FILE_SIZE_256TB (#5615)
- * fix occasionnal write-after-end-of-buffer (#5464)
+ * fix occasional write-after-end-of-buffer (#5464)
  * avoid error message when failing to import SRS from WKID code (might be an ESRI code for example)
  * fix spatial filter with GeneralPolygon shapes (#5591)
  * fix for reading GDB with string fields with a default value length > 127 (#5636)
@@ -1130,7 +1515,7 @@ Shapefile driver:
  * add check not to cut unicode character while cut the string lengnt for field max length during SetFeature
  * avoid reading whole .shx at open time for /vsicurl/
  * add SHAPE_REWIND_ON_WRITE configuration option that can be set to NO to disable correction of ring winding order on write. Useful when dealing with MultiPolygon that are MultiPatch objects in fact (#5888)
- * Make ENCODING layer creation option prioritary over SHAPE_ENCODING config. option
+ * Make ENCODING layer creation option proprietary over SHAPE_ENCODING config. option
 
 SOSI driver:
  * remove error noise (#5710)
@@ -1140,7 +1525,7 @@ S57 driver:
  * make it possible to set LNAM_REFS=OFF as advertized in the doc
 
 SQLite/Spatialite driver:
- * SQLite/Spatialte: add support for multiple geometry colunn tables, accordingly with RFC 41 (#5494)
+ * SQLite/Spatialite: add support for multiple geometry column tables, accordingly with RFC 41 (#5494)
  * SQLite SQL dialect: Add hstore_get_value(hstore, key) function
  * remove 'T' suffix when formatting the content of a Date field (#5672)
  * optimize CreateFeature() when fields can be null or not null from one feature to another one
@@ -1298,7 +1683,7 @@ Build(Unix):
 
 Build(Windows):
  * add option to generate VC project for x64 on makegdal_gen.bat
- * nmake.opt: add WITH_PDB=1 option to optionaly generate .pdb file on Release builds (#5420)
+ * nmake.opt: add WITH_PDB=1 option to optionally generate .pdb file on Release builds (#5420)
  * add support for building the OGR SOSI driver as a plugin (#3638)
  * add support for building the HDF4 driver as plugin (#5294)
  * add support for MrSID v9
@@ -1379,13 +1764,13 @@ Utilities:
  * gdal_translate: use floor() to compute image coordinates from world coordinates when specifying -projwin (useful when extracting from left or top of upper-left corner, which generate negative image coordinates) (#5367)
  * gdaltindex: remove annoying warning 'Warning 1: Field location of width 255 truncated to 254' (#5121)
  * gdaltindex: add -src_srs_name and -src_srs_format to go with MapServer RFC100; add also a -f and -lyr_name options to be able to create a non-shapefile tileindex
- * gdalwarp: Fix segfault where metadata values weren't being nullchecked properly during conflict resolution (#5069)
+ * gdalwarp: Fix segfault where metadata values were not being nullchecked properly during conflict resolution (#5069)
  * gdalwarp: honor -s_srs when using cutline (#5081)
  * gdalwarp: copy nodata values from source to dest if -dstnodata is not given ; add option to not set dest nodata with -dstnodata None (#5087)
  * gdalwarp: do not return a non-zero exit status for warnings
  * gdalwarp: prevent from copying statistics metadata (#5319)
  * gdal_rasterize: set the progress bar to 100% even when there's nothing to do
- * gdal_grid: add support for diffferent types of geometries (#5341)
+ * gdal_grid: add support for different types of geometries (#5341)
  * gdal_grid: add  -z_increase and -z_multiply options
  * gdaldem: check that value of -z, -s, -az and -alt is numeric
  * gdalbuildvrt: validate values of -srcnodata and -vrtnodata arguments
@@ -1458,7 +1843,7 @@ GTiff driver:
  * make SetColorInterpretation() round-trip with GetColorInterpreation();
    read color interpretation from PAM if it exists (overrides internal tiff color interpretation);
    set TIFFTAG_PHOTOMETRIC=PHOTOMETRIC_RGB if calling SetColorInterpretation() with R,G,B and no explicit PHOTOMETRIC creation option defined
- * gt_wkt_srs.cpp: fix compilation with external libgeotiff. The file is dependant of quite a few CPL stuff, don't try to pretend otherwise
+ * gt_wkt_srs.cpp: fix compilation with external libgeotiff. The file is dependent of quite a few CPL stuff, don't try to pretend otherwise
  * implement GetVirtualMemAuto() for some formulations of TIFF files (RFC 45)
  * fix reading a single-strip TIFF file where the single strip is bigger than 2GB (32bit builds only) (#5403)
  * look for .tab file before .wld/.tfw
@@ -1482,7 +1867,7 @@ HFA driver:
  * add minimally tested support for u2 and u4 data in basedata
  * use direct binning for thematic layers and real instead of integer for values (#5066)
  * add a HFA_COMPRESS_OVR config option to select whether to create compressed overviews (#4866)
- * fix rewriting of statics in existing HFA file where base data value is 8-bit (#5175)
+ * fix rewriting of statistics in existing HFA file where base data value is 8-bit (#5175)
  * implement re-writing existing histogram in HFA file, after raster editing (#5176)
  * avoid segfaults when creating a Imagine dataset with an invalid WKT (#5258)
  * expose color columns in RAT as Integer with values in range [0-255] instead of Real with values [0-1] (#5362)
@@ -1598,7 +1983,7 @@ Rasterlite driver:
 
 Raw drivers:
  * implement GetVirtualMemAuto() (RFC 45)
- * IRasterIO(): add special behaviour to avoid going to block based IO when the dataset has INTERLEAVE=PIXEL and is elligible to direct I/O access pattern
+ * IRasterIO(): add special behaviour to avoid going to block based IO when the dataset has INTERLEAVE=PIXEL and is eligible to direct I/O access pattern
  * allow direct I/O access even if a small proportion of scanlines are loaded (improve QGIS use case where the overview display will load sparse scanlines, which would prevent direct I/O at full resolution afterwards)
  * fix optimized RasterIO() when doing sub-sampling with non standard buffer pixel offset (#5438)
 
@@ -1648,8 +2033,8 @@ Core:
  * OGRGeometryFactory::organizePolygons() in DEFAULT method: fix a case with 2 outer rings that are touching by the first point of the smallest one
  * OGRGeometryFactory::organizePolygons(): optimization in ONLY_CCW case
  * OGRGeometryFactory::organizePolygons(): Add an experimental mode : CCW_INNER_JUST_AFTER_CW_OUTER
- * OGRLineString::segmentize() : don't set 0 as z for interpolated points, but the z from the previous point
- * OGRLineString::setNumPoints() : add an optional argument to avoid zeroizing the arrays
+ * OGRLineString::segmentize() : do not set 0 as z for interpolated points, but the z from the previous point
+ * OGRLineString::setNumPoints(): add an optional argument to avoid zeroing the arrays
  * Add OGRLineString::setZ()
  * Add OGRLineString::Project() and OGRLineString::getSubline()
  * OGRPolygon: add stealExteriorRing() and stealInteriorRing(int iRing)
@@ -1665,7 +2050,7 @@ Core:
  * introduce OGRLayer::FindFieldIndex() / OGR_L_FindFieldIndex() to lookup potentially laundered field names (RFC 42)
  * OGR SQL: upgrade to support RFC 41 (multiple geometry fields)
  * OGR SQL: more stricter checks
- * OGR SQL: make parsing error report a useful hint where the syntax error occured
+ * OGR SQL: make parsing error report a useful hint where the syntax error occurred
  * OGR SQL: fix thread-safety of swq_op_registrar::GetOperator() (#5196)
  * OGR SQL: support not explicitly specifying AS keyword for aliasing a column spec
  * OGR SQL: don't call CONCAT(a_column ...) or SUBSTR(a_column ...) as a_column
@@ -1686,7 +2071,7 @@ OGRSpatialReference:
  * morph central_latitude to latitude_of_origin in morphFromESRI() (#3191)
  * OGRProj4CT: avoid using proj when the 2 projections are actually identical (#5188)
  * add sanity checks in OGR_SRSNode::importFromWkt() (#5193)
- * VERT_CS: when importing from proj.4 put AXIS node after UNIT; COMPD_CS: when importing from EPSG:x+y, set a more meaningfull name for the COMPD_CS node
+ * VERT_CS: when importing from proj.4 put AXIS node after UNIT; COMPD_CS: when importing from EPSG:x+y, set a more meaningful name for the COMPD_CS node
  * OGRSpatialReference::Validate() : in addition to hand-validation, use WKT grammar from OGC 01-009 CT
  * preserve authority when importing +init=auth_name:auth_code (e.g. +init=IGNF:LAMB93)
 
@@ -1750,7 +2135,7 @@ GeoJSON driver:
  * report integer values that are int64 as strings
  * add 3d support to esri geojson reader (#5219)
  * be less strict on looking for esri field type tag (#5219)
- * fix sometimes incorrect result (significant digit losts...) when using -lco COORDINATE_PRECISION=0
+ * fix sometimes incorrect result (significant digit lost...) when using -lco COORDINATE_PRECISION=0
  * fix handling of huge coordinates when writing (#5377)
 
 GeoRSS driver:
@@ -1770,7 +2155,7 @@ GML driver:
  * autodiscover all XML attributes as OGR fields when creating .gfs file if GML_ATTRIBUTES_TO_OGR_FIELDS is set to YES (#5418)
  * allow the <ElementPath> in .gfs to have several components that give the full XML path
  * fix writing of .xsd file to avoid fid/gml_id being written as regular fields (#5142)
- * fix writing of global srsName attribue on the global boundedBy.Envelope when all layers have same SRS (#5143)
+ * fix writing of global srsName attribute on the global boundedBy.Envelope when all layers have same SRS (#5143)
  * support for writing .gml/.xsd with fields of type StringList, RealList, IntegerList and support for parsing such .xsd files
  * when writing .xsd for a datasource that has fields of type StringList, RealList or IntegerList, advertize SF-1 profile in the .XSD schema
  * recognize xsd:boolean in XSD parsing and map it to String (#5384)
@@ -1808,7 +2193,7 @@ LIBKML driver:
  * add support for reading <gx:Track> as a LINESTRING (#5095)
  * add support for writing and reading <snippet>
  * add support for writing atom:author, atom:link, phonenumber, Region,
-   ScreenOverlay, 3D model, StlyeMap
+   ScreenOverlay, 3D model, StyleMap
  * add support for reading and generating Camera object
  * add layer creation options to generate a LookAt element at layer level
  * if UPDATE_TARGETHREF dataset creation option is defined, a NetworkLinkControl/Update document will be created
@@ -1969,14 +2354,14 @@ Python bindings:
  * fix ref-counting of callable passed to gdal.PushErrorHandler() that could cause segfaults (#5186)
  * make gdal_array.NumericTypeCodeToGDALTypeCode accept numpy dtype arguments (#5223)
  * add default xoff,yoff,xsize,ysize values to ReadRaster calls
- * make ogr.CreateGeometryFromWkt() and SpatialReference.ImportFromWkt() propery validate their argument (#5302)
+ * make ogr.CreateGeometryFromWkt() and SpatialReference.ImportFromWkt() properly validate their argument (#5302)
 
 = GDAL/OGR 1.10.0 Release Notes (r23656 to r25905) =
 
 == In a nutshell... ==
 
  * New GDAL drivers:
-   - ARG: read/write suuport for ARG datasets (#4591)
+   - ARG: read/write support for ARG datasets (#4591)
    - CTable2: read/write support for CTable2 datum grid shift format
    - DDS: write-only support for DirectDraw Surface format (#5017)
    - IRIS: read support for products generated by the IRIS weather radar software (#4854)
@@ -2201,18 +2586,18 @@ GTiff driver:
  * Fix writing of RGBA pixel-interleaved JPEG-compressed TIFF (#4732)
  * Set color interpretation to GCI_PaletteIndex after calling SetColorTable() (#4547)
  * Conversion for 8-bit unpacked CMYK (PHOTOMETRIC_SEPARATED) to RGBA.
- * Maximize EPSG compatability where PCS is defined (#4607)
+ * Maximize EPSG compatibility where PCS is defined (#4607)
  * Ensure that unusual units with an authority node are saved nicely (like EPSG:2066)
  * Add CT_HotineObliqueMercatorAzimuthCenter support
  * Fix PolarStereographic / 9829 support
  * Make sure that GetMetadata() initializes the value of GDALMD_AREA_OR_POINT item, if not already done (#4691)
- * When building overviews, if the image has already an internal mask, then build internal overviews for the mask implicitely
+ * When building overviews, if the image has already an internal mask, then build internal overviews for the mask implicitly
  * Better handling of SetMetadata(a_string) (#4816)
  * Use GTIFAllocDefn/GTIFFreeDefn with libgeotiff 1.4.1+
  * Add support for GEO_NORMALIZE_DISABLE_TOWGS84 (#3309)
  * Improve handling of description and offset/scale without reverting to .aux.xml
  * Workaround defects in libtiff 3.X when generating several overview levels at the same time
- * Special case where the EGM96 Vertical Datum code is mis-used as a Vertical CS code (#4922)
+ * Special case where the EGM96 Vertical Datum code is misused as a Vertical CS code (#4922)
  * Support unsetting geotiff tags when calling SetGeoTransform([0,1,0,0,0,1]) and SetProjection('')
  * Rework how CSV files are searched w.r.t libgeotiff (#4994)
 
@@ -2234,7 +2619,7 @@ GTX driver:
 GXF driver:
  * Avoid having big buffer on stack (#4852)
  * Avoid locale floating point parsing problems (similar to r24367).
- * Implement continuued lines mechanism (#4873)
+ * Implement continued lines mechanism (#4873)
  * Fix various vulnerabilities / DoS
 
 HDF4 driver:
@@ -2290,12 +2675,12 @@ JPEG driver:
  * When there are no external overviews built, take advantage of the nature of JPEG compression to expose overviews of level 2, 4 and 8
  * Don't return junk content when requesting xml:XMP but no XMP metadata is present (#4593)
  * add a INTERNAL_MASK creation option to be able to disable appending the ZLib mask if not needed
- * add support for creating a JPEG loss-less file starting with the recentlish IJG libjpeg v9
+ * add support for creating a JPEG loss-less file starting with the recent IJG libjpeg v9
    (with -co ARITHMETIC=yes -co BLOCK=1 -co COLOR_TRANSFORM=RGB1)
 
 JPEG2000 driver:
  * do not accept by default source bands of type different from Byte, Int16 or UInt16 since they seem to cause crashes in libjasper.
-   This can be overriden, at your own risk, by setting JPEG2000_FORCE_CREATION configuration option to YES (#5002)
+   This can be overridden, at your own risk, by setting JPEG2000_FORCE_CREATION configuration option to YES (#5002)
 
 KMLSuperOverlay driver:
  * Add read support
@@ -2363,7 +2748,7 @@ PostgisRaster driver:
  * Implement CreateCopy and Delete (#4530)
  * Supports reading of tiled raster with irregular blocking and irregular pixel size
  * Cache postgres db connection.
- * Use PG enviroment variables as fallback when settings are not provided in the connection string. (#4533).
+ * Use PG environment variables as fallback when settings are not provided in the connection string. (#4533).
  * Do not report nodata value when there is none (#4414)
  * Removed dependency on the 'rid' column.
  * Fix to make SQL queries with un-rounded floating point string representations. (#4736)
@@ -2450,7 +2835,7 @@ Core:
  * OGRDataSource::CopyLayer(): take into account field renaming by output driver (e.g. Shapefile driver that might truncated field names) (#4667)
  * OGRLayer::FilterGeometry() : speed-up improvement in some cases and  use GEOSPreparedIntersects() when available (r23953, r25268)
  * OGRLayer::SetNextByIndex(): return OGRERR_FAILURE if index < 0
- * OGRLineString::setPoint( int iPoint, OGRPoint * poPoint ) : avoid promotting the line to 25D if the point is only 2D (#4688)
+ * OGRLineString::setPoint( int iPoint, OGRPoint * poPoint ) : avoid promoting the line to 25D if the point is only 2D (#4688)
  * OGRGeometry::Centroid(): make it work properly on POINT EMPTY with latest SVN geos version
  * Add reversePoints() method on linestring
 
@@ -2515,7 +2900,7 @@ DXF driver:
  * Write layer geometry extent in file header (#4618)
  * Ignore Spline frame control points for VERTEX of POLYLINE (#4683)
  * Add color to POINT, INSERT and HATCH
- * Take into account extruction vector to transform from OCS to WCS for MTEXT, TEXT, POINT, LINE, CIRCLE, ELLIPSE, ARC, SPLINE and HATCH (#4842)
+ * Take into account extrusion vector to transform from OCS to WCS for MTEXT, TEXT, POINT, LINE, CIRCLE, ELLIPSE, ARC, SPLINE and HATCH (#4842)
 
 FileGDB driver:
  * Add the FGDB_BULK_LOAD configuration option (#4420)
@@ -2608,7 +2993,7 @@ MSSQLSpatial driver:
  * Fix the parser to swap coordinates with geography data type (#4642)
  * Fix to read multipoint geometries correctly (#4781)
  * Fix to read 3D geometries correctly (#4806, #4626)
- * Use MSSQL catalog if geometry_colums doesn't exist (#4967)
+ * Use MSSQL catalog if geometry_columns doesn't exist (#4967)
  * Utilize OGRFieldDefn::IsIgnored() (#4534)
  * Remove requirement for identity fid column in MSSQL tables (#4438)
 
@@ -2669,9 +3054,9 @@ SDE driver:
 
 Shapefile driver:
  * Add support for reading ESRI .sbn spatial index (#4719)
- * Add defered layer loading
+ * Add deferred layer loading
  * Implement auto-growing of string and integer columns
- * Add a special SQL command 'RESIZE table_name' to resize (shrink) fields to their optimium size, also available as a RESIZE=YES layer creation option for conveniency
+ * Add a special SQL command 'RESIZE table_name' to resize (shrink) fields to their optimum size, also available as a RESIZE=YES layer creation option for convenience
  * Recode field name from UTF-8 to DBF encoding in CreateField()
  * In creation, limit fields of type OFTString to a width of 254 characters (#5052)
  * Spatial index optimization (#4472)
@@ -2683,7 +3068,7 @@ Shapefile driver:
  * Make TestCapability(OLCFastFeatureCount) return TRUE when an attribute filter is set only if attribute indices can be used
  * Shapelib: Fix memory leaks in error code path of DBFCreateLL() (#4860)
  * Deal better with shapefile directories with foo.shp and FOO.DBF, particularly for REPACK support, and particularly for Windows OS (on Linux, foo.shp and FOO.DBF will be 2 different layers)
- * Delete temporary _packed.cpg file generated during REPACK of a layer whose .dbf has an accompaying .cpg file
+ * Delete temporary _packed.cpg file generated during REPACK of a layer whose .dbf has an accompanying .cpg file
  * In DeleteDataSource(), delete .cpg file if existing
 
 S57 driver:
@@ -2693,21 +3078,21 @@ S57 driver:
 
 SQLite/Spatialite driver:
  * Add support for tables with multiple geometry columns (#4768)
- * Add (preliminary) support for Spatialite 4.0 database changes (#4784)
+ * Add (preliminary) support for SpatiaLite 4.0 database changes (#4784)
  * Make GDAL loadable as a SQLite3 extension (named VirtualOGR) (#4782)
  * Add support for OFTDateTime/OFTDate/OFTTime field types
  * Add a SRID layer creation option
  * Make REGEXP function available by using libpcre (#4823)
  * Add a COMPRESS_COLUMNS layer creation option to make string columns ZLib compressed
- * Implement minimalistic set of spatial functions if Spatialite isn't available
- * Spatialite: make use of spatial filter on result layers when the SQL expression is simple enough (no join, etc...) (#4508)
- * Spatialite: spatial index can be used even when linking against regular SQLite (#4632)
- * Spatialite: to improve performance, defer spatial index creation at layer closing or when a spatial request is done
- * Spatialite: use Spatialite 'layer_statistics' and 'spatialite_history' to cache the row count and extent of (spatial) layers
+ * Implement minimal set of spatial functions if SpatiaLite isn't available
+ * SpatiaLite: make use of spatial filter on result layers when the SQL expression is simple enough (no join, etc...) (#4508)
+ * SpatiaLite: spatial index can be used even when linking against regular SQLite (#4632)
+ * SpatiaLite: to improve performance, defer spatial index creation at layer closing or when a spatial request is done
+ * SpatiaLite: use SpatiaLite 'layer_statistics' and 'spatialite_history' to cache the row count and extent of (spatial) layers
  * Spatialite: add support for reading Spatialite 4.0 statistics (filling them on the fly still not implemented)
- * Spatialite: for Spatialite 4.0, translate INIT_WITH_EPSG=NO into InitSpatialMetaData('NONE') to avoid filling the spatial_ref_sys table
+ * SpatiaLite: for SpatiaLite 4.0, translate INIT_WITH_EPSG=NO into InitSpatialMetaData('NONE') to avoid filling the spatial_ref_sys table
  * On SQL result layers, report the SRS of the geometry of the first feature as the layer SRS
- * Defered layer definition building for table and view layers
+ * Deferred layer definition building for table and view layers
  * Speed-up opening of a result layer that has an ORDER BY
  * Cache GetExtent() result
  * Allow inserting empty feature
@@ -2798,7 +3183,7 @@ Python bindings:
  * setup.py: Changes to run without setuptools (#4693)
  * setup.py: Automatically run 2to3 for Python3
  * Define __nonzero__ on Layer object to avoid GetFeatureCount() being called behind our back when doing 'if a_layer:' (#4758)
- * Fix performance problem when instanciating Feature, especially with Python 3
+ * Fix performance problem when instantiating Feature, especially with Python 3
  * Add RasterBand.ReadBlock(), mostly for driver testing
  * Reject strings when array of strings are expected
  * make gdal.PushErrorHandler() also accept a Python error handler function as an argument (#4993)
@@ -2814,7 +3199,7 @@ Python bindings:
  * Encoding support for shapefile/dbf (#882)
  * RFC 35: Delete, reorder and alter field definitions of OGR layers
  * RFC 37: Add mechanism to provide user data to CPLErrorHandler (#4295)
- * gdalsrsinfo: new supported utility to report SRS in various form (supercedes testepsg)
+ * gdalsrsinfo: new supported utility to report SRS in various form (supersedes testepsg)
 
 == New installed files ==
 
@@ -2890,7 +3275,7 @@ Port:
  * CPLMiniXML: emit warnings when encountering non-conformant XML that is however accepted by the parser
  * add CPLBase64Encode(); move cpl_base64.h contents to cpl_string.h
  * Use CRITICAL_SECTION instead of Mutex on win32
- * CPLHTTPFetch(): Add a CLOSE_PERSISTENT option to close the persistant sessions
+ * CPLHTTPFetch(): Add a CLOSE_PERSISTENT option to close the persistent sessions
  * CPLHTTPFetch(): Add support for "NEGOTIATE" http auth mechanism
  * CPLHTTPFetch(): Add a CUSTOMREQUEST option
  * VSIBufferedReaderHandle: fix Eof()
@@ -2901,12 +3286,12 @@ Port:
 Core:
  * Provide for ABI specific plugin subdirectories on all platforms
  * Force cleanup of datasets when destroying the dataset manager
- * Add a GDALDataset::CloseDependantDatasets() that can be used by GDALDriverManager::~GDALDriverManager() to safely close remaining opened datasets (#3954)
+ * Add a GDALDataset::CloseDependentDatasets() that can be used by GDALDriverManager::~GDALDriverManager() to safely close remaining opened datasets (#3954)
  * Add GDALRasterBand::ReportError() and GDALDataset::ReportError() to prepend dataset name (and band) before error message (#4242)
  * Fix performance problem when serializing huge color tables, metadata, CategoryNames and GCPs to VRT/PAM (#3961)
  * Be careful about Nan complex values getting histogram, avoid locale issues with statistics metadata
  * GDALRasterBand::IRasterIO() default implementation : don't try to use full-res band if I/O failed on the appropriate overview band (for WMS errors)
- * RasterIO: Return earlier when a write error occured while flushing dirty block
+ * RasterIO: Return earlier when a write error occurred while flushing dirty block
  * GDAL_DISABLE_READDIR_ON_OPEN can be set to EMPTY_DIR to avoid reading the dir, but it set an empty dir to avoid looking for auxiliary files
  * Use sibling file list to look for .aux.xml, .aux, .ovr, world files, tab files
  * Add GDALFindAssociatedFile() (#4008)
@@ -2925,12 +3310,12 @@ Algorithms:
  * gdalrasterize: use double instead of float to avoid precision issues (#4292)
 
 Utilities:
- * gdalsrsinfo: new supported utility to report SRS in various form (supercedes testepsg)
+ * gdalsrsinfo: new supported utility to report SRS in various form (supersedes testepsg)
  * gdalinfo: add '-nofl' option to only display the first file of the file list
  * gdalinfo: add '-sd num' option to report subdataset with the specified number.
  * gdalinfo: add '-proj4' option to gdalinfo, to report a PROJ.4 string for the CRS
  * gdal_translate: propagate INTERLEAVE metadata to intermediate VRT dataset
- * gdal_translate: force quiet mode when outputing to /vsistdout/
+ * gdal_translate: force quiet mode when writing to /vsistdout/
  * gdalwarp: Disable CENTER_LONG rewrapping for cutline (#3932)
  * gdalwarp: add -refine_gcps option to discard outliers GCPs before warping (#4143)
  * gdalwarp: add warning if user specifies several of -order, -tps, -rpc or -geoloc options
@@ -2939,7 +3324,7 @@ Utilities:
  * gdalwarp: detect situations where the user will override the source file
  * gdallocationinfo: do not let one off-db pixel cause all the rest to be suppressed (#4181)
  * gdal_rasterize: fix half pixel shift when rasterizing points; make gdal_rasterize utility increase the computed raster extent by a half-pixel for point layers (#3774)
- * gdal_rasterize: when source datasource has a single layer, use it implicitely if none of -l or -sql is specified
+ * gdal_rasterize: when source datasource has a single layer, use it implicitly if none of -l or -sql is specified
  * nearblack: add -color option (#4085)
  * nearblack: improve detection of collar
  * nearblack: remove useless restrictions on number of bands for -setmask and -setalpha options (#4124)
@@ -2960,7 +3345,7 @@ Multi-driver topics:
  * Port DOQ1, DOQ2, ELAS, Idrisi, L1B, NDF, NWT_GRD, NWT_GRC, USGSDEM to VSI virtual file API
  * PAM-enable BT and BLX drivers
  * Implement Identify() for AAIGrid, ACE2, DTED, NWT_GRD, NWT_GRC, WMS, WCS, JDEM and BSB drivers
- * Make GIF, JPEG and PNG drivers return a non NULL dataset when outputing to /vsistdout/
+ * Make GIF, JPEG and PNG drivers return a non NULL dataset when writing to /vsistdout/
  * HFA and GTiff: add explicit error message when trying to add external overviews when there are already internal overviews (#4044)
  * Initialize overview manager to support external overviews for AAIGRID, DIPX, ELAS, GXF, FIT, FITS, GMT, GRIB, GSAG, GSBG, GS7BG, ILWIS, L1B, LCP, Leveller, NWT_GRD, NWT_GRC, RIK, SDTS and SAGA
 
@@ -3032,7 +3417,7 @@ ENVISAT driver:
  * Report metadata from the ASAR ADS and GADS in the RECORDS metadata domain (#4105)
  * Read MERIS metadata (#4105)
  * Read data from ERS products in ENVISAT format (#4105)
- * Improved MERIS Level 2 bands datection (#4141 and #4142)
+ * Improved MERIS Level 2 bands detection (#4141 and #4142)
 
 EPSILON driver:
  * Now require libepsilon 0.9.1 to build (now dual LGPL/GPL) (#4084)
@@ -3046,7 +3431,7 @@ ERS driver:
 GeoRaster driver:
  * Set nodata causes invalid XML metadata (#3893)
  * Fix SetStatistics() failure (#4072)
- * Fix defaut interleaving (#4071)
+ * Fix default interleaving (#4071)
  * modelCoordinateLocation=CENTER default (#3266)
  * Cache block/level error in update (#4089)
  * Fix sequence.nextval not supported (Oracle 10g) (#4132)
@@ -3056,7 +3441,7 @@ GeoRaster driver:
  * Fix loading of small images, FlushCache issue (#4363)
 
 GIF driver:
- * Make CreateCopy() more friendly with outputing in /vsistdout/
+ * Make CreateCopy() more friendly with writing in /vsistdout/
 
 GRIB driver:
  * Fix grid vs cell-center convention (#2637)
@@ -3084,11 +3469,11 @@ GTiff driver:
  * Overviews: Improve error reporting for >16bit images to JPEG compression
  * Use CPLAtof() for geotiff and epsg .csv file handling (#3886, #3979)
  * Lots of Imagine and ESRI PE string citation handling changes from 1.8-esri. Some citation related changes only compiled in if ESRI_SPECIFIC defined.
- * Give PAM information precidence over metadata from GeoTIFF itself.   Avoid unnecessary (default) writes of scale/offset.  Treat (0,1,0,0,0,-1) as a default geotransform as well as (0,1,0,0,0,1).
+ * Give PAM information precedence over metadata from GeoTIFF itself.   Avoid unnecessary (default) writes of scale/offset.  Treat (0,1,0,0,0,-1) as a default geotransform as well as (0,1,0,0,0,1).
  * Migrate in some ESRI only logic for 1bit color tables, AdjustLinearUnits and default for 1bit data
  * Add a GTIFF_IGNORE_READ_ERRORS configuration option (#3994)
  * Lazy loading of RPC/RPB/IMD files (#3996)
- * Add mutex protection in GTiffOneTimeInit() to avoid occasionnal segfaults
+ * Add mutex protection in GTiffOneTimeInit() to avoid occasional segfaults
  * Stop interpreting 4th band as alpha when not defined
  * Also list nSubType == FILETYPE_PAGE as subdatasets
  * CreateCopy(): copies category names from the source bands
@@ -3193,7 +3578,7 @@ NetCDF driver:
  * Add support for deflate compression
  * Add format support information and CreateOptionList to driver metadata 
  * Add support for valid_range/valid_min/valid_max
- * Proper handling of singed/unsigned byte data
+ * Proper handling of signed/unsigned byte data
  * Add support for Create() function and significantly refactor code for export (#4221)
  * Improvements to CF projection support (see wiki:NetCDF_ProjectionTestingStatus)
  
@@ -3210,7 +3595,7 @@ NITF driver:
  * Add IREPBAND and ISUBCAT creation option (#4343)
  * Make sure scanline access is used only on single block image (#3926)
  * Add a NITF_DISABLE_RPF_LOCATION_TABLE_SANITY_TESTS configuration option that can be set to TRUE to blindly trust the RPF location table (#3930)
- * Correctly assign hemisphere for a ICORDS='U' NITF file with accompagnying .nfw and .hdr files (#3931)
+ * Correctly assign hemisphere for a ICORDS='U' NITF file with accompanying .nfw and .hdr files (#3931)
  * Make PAM available at band level for JPEG/JPEG2000 compressed datasets (#3985)
  * Read IMRFCA TRE for RPC info. Read CSEXRA TRE.
  * Read CSDIDA and PIAIMC TREs as metadata
@@ -3312,7 +3697,7 @@ VRT driver:
 WCS driver:
  * Add time support (#3449)
  * Honour dimensionLimit restrictions on WCS request size.
- * Fetch projection from returned image file chunks if they have them (ie. GeoTIFF).
+ * Fetch projection from returned image file chunks if they have them (i.e. GeoTIFF).
  * Honour Resample option for WCS 1.0.
  * Include service url in GetFileList if ESRI_BUILD defined
  * Check validity of 'OverviewCount' parameter
@@ -3365,7 +3750,7 @@ Core:
  * OGR SQL: Correctly parse big SQL statements (#4262)
  * OGR SQL: fix joining a float column with a string column (#4321)
  * OGR SQL: with DISTINCT, consider null values are such, and not as empty string (#4353)
- * OGR SQL: fix offset convertion for SUBSTR() (#4348)
+ * OGR SQL: fix offset conversion for SUBSTR() (#4348)
  * Add OGR_G_GetPoints()
  * Fix parsing of WKT geometries mixing 2D and 3D parts
  * OGR_Dr_CopyDataSource() and OGRSFDriver::CopyDataSource() : make sure that the driver is attached to the created datasource (#4350)
@@ -3391,7 +3776,7 @@ OGRSpatialReference:
  * Add Germany zone 1-5 in range 31491-31495 in the data/esri_extra.wkt file
  * fix NAD_1983_Oregon_Statewide_Lambert_Feet_Intl code
  * added/updated coordinates systems provided by IGNF (#3868)
- * ERM: add support for EPSG:n based coordinate sysetms (#3955)
+ * ERM: add support for EPSG:n based coordinate systems (#3955)
  * ImportFromEPSG(): Add default support for various degree units without supporting .csv file.
  * ImportFromEPSG(): Add support for spherical LAEA (#3828)
  * ImportFromEPSG(): use CoLatConeAxis parameter to build Krovak azimuth parameter (#4223)
@@ -3551,7 +3936,7 @@ NAS driver:
  * Add support for treating wfs:Delete as a special Delete feature with typeName and FeatureId properties
  * Handle empty files gracefully (#3809)
  * Preliminary support for SRS in NAS files, including 3GKn SRS
- * Implement special treatement for <lage> to be zero passed and string (NAS #9)
+ * Implement special treatment for <lage> to be zero passed and string (NAS #9)
  * Add special handling of punktkennung (NAS #12)
  * Add special handling for artDerFlurstuecksgrenze (#4255)
  * Add support for wfsext:Replace operations (PostNAS #11)
@@ -3593,7 +3978,7 @@ PGDump driver:
  * fix handling of Nan with fields with non-zero width (#2112)
  * Add CREATE_SCHEMA and DROP_TABLE layer creation option (#4033)
  * Fix crash when inserting a feature with a geometry in a layer with a geom type of wkbNone;
- * PG and PGDump: fix insertion of features with first field being a 0-charachter string in a non-spatial table and without FID in COPY mode (#4040)
+ * PG and PGDump: fix insertion of features with first field being a 0-character string in a non-spatial table and without FID in COPY mode (#4040)
  * Add NONE_AS_UNKNOWN, FID, EXTRACT_SCHEMA_FROM_LAYER_NAME layer creation options
  * Better escaping of column and table names
  * Create field of type OFTString and width > 0, as VARCHAR(width) (#4202)
@@ -3670,7 +4055,7 @@ SVG driver:
 S57 driver:
  * Add support for Dutch inland ENCs (#3881)
  * Allow up to 65536 attributes, use GUInt16 for iAttr (#3881)
- * Be cautious of case where end piont of a line segment has an invalid RCID
+ * Be cautious of case where end point of a line segment has an invalid RCID
  * Correct handling of update that need to existing SG2D into an existing feature without it (#4332)
 
 VRT driver:
@@ -3731,7 +4116,7 @@ Perl bindings:
  * Detect context in a typemap which returns a array, this now returns a list in list context; the change affects at least GetExtent and GetEnvelope methods, which retain backward compatibility though new and/or changed methods: FeatureDefn::Name, FeatureDefn::GeometryIgnored, FeatureDefn::StyleIgnored, Feature::ReferenceGeometry, Feature::SetFrom, FieldDefn::Ignored, Geometry::AsJSON
  * Perl typemaps: more correct manipulation of the stack, more cases where a list is returned in a list context, better handling of callback_data @Band::COLORINTERPRETATIONS, Band methods Unit, ScaleAndOffset, GetBandNumber, RasterAttributeTable method LinearBinning
  * Typemaps for VSIF{Write|Read}L, tests and docs for some VSI* functions.
- * Perl bindings: better by name / by index logics, some checks for silent failures, return schema as a hash if wanted, support ->{field} syntax for features, return list attributes as lists or listrefs as wished so that ->{field} works for lists too (API change)
+ * Perl bindings: better by name / by index logic, some checks for silent failures, return schema as a hash if wanted, support ->{field} syntax for features, return list attributes as lists or listrefs as wished so that ->{field} works for lists too (API change)
 
 Python bindings:
  * Improvements for ogr.Feature field get/set
@@ -3750,7 +4135,7 @@ Ruby bindings:
 = GDAL/OGR 1.8.0 release notes =
 
 (Note: Most changes/bugfixes between 1.7.0 and 1.8.0 that have already gone
-to the 1.7.X maintenance releases are not mentionned hereafter.)
+to the 1.7.X maintenance releases are not mentioned hereafter.)
 
 == In a nutshell... ==
 
@@ -3824,7 +4209,7 @@ Core:
  * On Unix, add capability of opening the target of a symlink through GDALOpen()
    even if it not a real filename. Useful for opening resources expressed as
    GDAL virtual filenames in software offering only file explorers (#3902)
- * Assume anything less than 100000 for GDAL_CACHEMAX is measured in metabytes.
+ * Assume anything less than 100000 for GDAL_CACHEMAX is measured in megabytes.
  * Read cartesian coordinates if applicable in GDALLoadOziMapFile().
  * Avoid being overly sensitive to numeric imprecision when comparing pixel
    value and nodata value in GDALRasterBand::ComputeStatistics()/
@@ -3839,7 +4224,7 @@ Core:
  * Add GDALSetCacheMax64(), GDALGetCacheMax64() and GDALGetCacheUsed64() (#3689)
  * Improve formatting of seconds in DecToDMS()
  * Support negative nPixelOffset values for RawRasterBands
- * GDALDatasetCopyWholeRaster(): improve performance in certains cases by better
+ * GDALDatasetCopyWholeRaster(): improve performance in certain cases by better
    fitting to input/output block sizes
  * Add GDALRasterBandCopyWholeRaster()
  * Make sure band descriptions are properly captured and cloned (#3780)
@@ -3866,7 +4251,7 @@ Algorithms:
  * warper : integrate Google Summer of Code OpenCL implementation of warper
  * gdalgrid: Move ParseAlgorithmAndOptions from apps/gdal_grid.cpp to
              alg/gdalgrid.cpp (#3583)
- * RPCTransformer: take into account optionnal DEM file to extract elevation
+ * RPCTransformer: take into account optional DEM file to extract elevation
    offsets (RPC_HEIGHT_SCALE and RPC_DEM transformation options added) (#3634)
  * GDALReprojectImage() : correctly assign nSrcAlphaBand and nDstAlphaBand (#3821)
  * gdalgrid : Properly initialize the first nearest distance in GDALGridNearestNeighbor().
@@ -3931,7 +4316,7 @@ BSB driver:
  * Added UNIVERSAL TRANSVERSE MERCATOR, LCC and POLYCONIC handling (#3409)
  * provide an option (BSB_IGNORE_LINENUMBERS) to ignore line numbers as some
    generators do them wrong but the image is otherwise readable (#3776)
- * Avoid turning missing values to indice 255 (#3777)
+ * Avoid turning missing values to index 255 (#3777)
 
 DODS driver:
  * Compilation fix to support libdap 3.10
@@ -4014,7 +4399,7 @@ GTiff driver :
    overviews when adding them after dataset reopening
  * auto-promote mask band to full 8 bits by default (unless
    GDAL_TIFF_INTERNAL_MASK_TO_8BIT is set TO FALSE).
- * add LZMA compression optionnal support (requires latest libtiff4 CVS HEAD)
+ * add LZMA compression optional support (requires latest libtiff4 CVS HEAD)
  * Supporting writing compound coordinate systems.
 
 GTX driver:
@@ -4030,7 +4415,7 @@ GXF driver:
    is assumed by the geotransform.  (#3816).
 
 HDF4 driver:
- * Prevent reading unexisting subdatasets
+ * Prevent reading nonexistent subdatasets
  * Allow reading 1D subdatasets, in particular for GEOLOC bands
  * Workaround strange test that swaps xsize, ysize and nbands for the particular
    case of the dataset of ticket #3316
@@ -4128,7 +4513,7 @@ NITF driver:
    files written with the IGEOLO corners out of order.
  * Implement readonly support for RSets (#3457)
  * Add capability of writing CGM segment as creation option (or from the source
-   CGM metatada domain if no CGM= creation option); for consistency, also add
+   CGM metadata domain if no CGM= creation option); for consistency, also add
    the capability of writing TEXT segment as creation option, in addition to
    the existing capability of writing it from the source TEXT metadata domain (#3376)
  * Fix read out of buffer for NBPP < 8 and very small block size; fix decoding
@@ -4260,7 +4645,7 @@ Core:
  * Make the GetStyleTable() SetStyleTable() SetStyleTableDirectly() methods on
    datasources and layers virtual (#2978)
  * Add OGRSFDriverRegistrar::DeregisterDriver() and OGRDeregisterDriver()
- * Improve detection of rounding errors when outputing coordinates as text with
+ * Improve detection of rounding errors when writing coordinates as text with
    OGRMakeWktCoordinate()
  * OGR SQL: allow comparing datetime columns in WHERE clause
  * OGR indexing: re-use .ind file in read-write mode when calling CreateIndex()
@@ -4360,7 +4745,7 @@ CSV driver:
  * Port to VSI*L API for read&write; support writing to /vsistdout/
 
 DGN driver:
- * Correct computation of abyLevelsOccuring (#3554).
+ * Correct computation of abyLevelsOccurring (#3554).
 
 DODS driver:
  * Compilation fix to support libdap 3.10
@@ -4402,7 +4787,7 @@ GML driver:
  * Recognize <gml:Solid> and <gml:CompositeSurface>, <gml:OrientableSurface> elements
    (dealt as an approximation as multipolygons, and not as volumes)
  * Add support for "complex structure flattening" of attributes, and OFTStringList,
-   OFTRealList and OFTIntegerList field types in case of multiple occurences of
+   OFTRealList and OFTIntegerList field types in case of multiple occurrences of
    a GML element (such as UK Ordnance Survey Mastermap) (#3680)
  * Add support for CityGML generic attributes <stringAttribute>, <intAttribute> and
    <doubleAttribute>
@@ -4425,7 +4810,7 @@ GML driver:
    be considered as urn:ogc:def:crs:EPSG::XXXX
  * Expose gml:id as a string field when reading <wfs:FeatureCollection>
  * Add dataset creation option FORMAT=GML3 to write GML3 SF-0 compliant data
- * Add dataset creation option SPACE_INDENTATION=YES/NO to optionnaly disable space indentation
+ * Add dataset creation option SPACE_INDENTATION=YES/NO to optionally disable space indentation
    when writing GML.
  * Recognize GML answer of MapServer WMS GetFeatureInfo request
  * Fix datatype detection to fallback to Real when an integer cannot fit into a 32bit int (#3866)
@@ -4508,12 +4893,12 @@ PGDump driver:
 PostgreSQL driver:
  * Add support for PostgreSQL >= 9.0 new binary data format
  * Use canonical (HEXEWKB) form to get geometry to speed-up feature retrieval.
-   WKT-based retrieval can still be used if PG_USE_TEXT configuratino option
+   WKT-based retrieval can still be used if PG_USE_TEXT configuration option
    is set to YES
  * If the PG_USE_BASE64 configuration option is set to YES, geometries will be
    requested as BASE64 encoded EWKB instead of canonical HEX encoded EWKB.
    (useful when bandwidth is the limiting factor)
- * Don't instanciate layer defn at layer creation. This can speed up
+ * Don't instantiate layer defn at layer creation. This can speed up
    significantly database opening when they are many tables and the user just
    needs to fetch one with GetLayerByName().
  * Implement efficient OGRLayer::GetName() and OGRLayer::GetGeomType()
@@ -4555,7 +4940,7 @@ SQLite driver:
    robust to single quote characters in SRS strings
  * Fix to make CopyLayer() work when src layer is a SQL result layer (#3617)
  * Add OGR_SQLITE_SYNCHRONOUS configuration option that, when set to OFF,
-   can speed up considerably write operations (e.g. on EXT4 filesysstems),
+   can speed up considerably write operations (e.g. on EXT4 filesystems),
    at the expense of extra robustness w.r.t system crashes.
  * Spatialite: when creating a spatialiate DB, add a srs_wkt column in the
    spatial_ref_sys table, as introduced in libspatialite 2.4.0
@@ -4643,7 +5028,7 @@ Python bindings:
 
 = GDAL/OGR 1.7.0 =
 
-(Some of the bugfixes mentionned below might also have gone into 1.6.X maintenance releases.)
+(Some of the bug fixes mentioned below might also have gone into 1.6.X maintenance releases.)
 
 == In a nutshell... ==
 
@@ -4678,7 +5063,7 @@ Build (Windows) :
  * Trap failures in subdirectories and stop build
 
 Build (Unix) :
- * Use proper object file names when building prerequsites lists (#1878)
+ * Use proper object file names when building prerequisites lists (#1878)
  * Updated man page generation
  * Add new ./configure test to check that the GCC 4.1 built-in functions for atomic memory access are really available
  * Handle external libz (#2942)
@@ -4852,7 +5237,7 @@ ECW driver:
  * Enable the JP2ECW driver to open JP2 files with the VSILAPI
  * Fix build with MSVC2008  (#2850)
  * Fix memory overwrite while zooming an ECW image (#2934)
- * Speed-up de-registeration of the driver that can take up to 3 seconds (#3134)
+ * Speed-up de-registration of the driver that can take up to 3 seconds (#3134)
 
 EHDR driver:
  * Add color table update.  Add limited support for floating point
@@ -4872,7 +5257,7 @@ EPSILON driver:
  
 ERS driver:
  * Added PIXELTYPE support to report/create SIGNEDBYTE (#2902)
- * Give precidence to PAM SRS, and even check for .aux file.  (ESRI Merge)
+ * Give precedence to PAM SRS, and even check for .aux file.  (ESRI Merge)
 
 FAST driver:
  * Support 7 bands (#3307)
@@ -4902,9 +5287,9 @@ GeoTIFF driver :
  * Add logic for encoding and reading ESRI PE string from citation.
  * Add support for reading and writing vertical datum info from geotiff
  * Changes to units handling.  (#2755)
- * Optimize opening speed by defering fetching the coordinate system till GetProjectionRef (#2957)
+ * Optimize opening speed by deferring fetching the coordinate system till GetProjectionRef (#2957)
  * Optimize GTiffRasterBand::IReadBlock() for multi-band interleaved case.
- * Avoid uncesserary re-writting the TIFF directory (#3021)
+ * Avoid unnecessary re-writing the TIFF directory (#3021)
  * Use official value for inverse flattening of the WGS84 ellipsoid (#2787)
  * Add metadata domain for XML documents (#2786)
  * Make GTiff driver friendly with files with huge number of bands and pixel interleaving (#2838)
@@ -4958,7 +5343,7 @@ HDF5 driver :
 HFA driver:
  * Support reading and evaluating 3rd order xforms (#2716)
  * Various improvements to SRS support, particularly to preserve PE
-   compatability.  (#2755) 
+   compatibility.  (#2755) 
  * Added HFAEntry::RemoveAndDestroy() method to remove nodes from tree (#2421)
  * Added support for deleting color tables (#2421)
  * Add a scaled progress monitor for HFADataset::IBuildOverviews()
@@ -5057,7 +5442,7 @@ OGDI driver:
 
 PCIDSK driver (old driver):
  * Added worldfile reading. Added PAM fallback for geotransform.
- * Added support for default overviews (ie. .ovr or .rrd).  (ESRI Merge)
+ * Added support for default overviews (i.e. .ovr or .rrd).  (ESRI Merge)
  * fail somewhat gracefully on compressed images
  
 PCIDSK driver (new driver):
@@ -5159,12 +5544,12 @@ OGRSpatialReference :
  * Expose more of the axis orientation API to C
  * Add missing Eckert 1, 2, 3 and 5 projections
  * Fix typos in proj4 conversion for Wagner projections
- * hack in EXTENSION nodes for google mercators (#3136)
+ * Hack in EXTENSION nodes for Google Mercator (#3136)
  * Validates PROJCS with AXIS definitions (#2739)
  * Added support for urn:ogc:def:crs:OGC::CRS:84 (and CRS:83, CRS:27) per WMS spec.
  * Wide variety of improvements to preserve PE strings through a morphFromESRI()
    and morphToESRI() process (#2755)
- * Fix inversion of dictionnary filename and GEOGCS/PROJCS name in OGRSpatialReference::exportToERM() (#2819)
+ * Fix inversion of dictionary filename and GEOGCS/PROJCS name in OGRSpatialReference::exportToERM() (#2819)
  * Fix SpatialReference::IsSame() for LOCAL_CS case (#2849)
  * Fix bug in ImportFromXML that prevented from retrieving projection method
  * Accept both href and xlink:href in OGC XML
@@ -5345,7 +5730,7 @@ General:
     - OSR :
         osr.ImportFromMICoordSys(), osr.ExportToMICoordSys(), SpatialReference.Clone()
         osr.EPSGTreatsAsLatLong(), osr.ImportFromEPSGA()
- * Make resampling an optionnal parameter for gdal.RegenerateOverview(),
+ * Make resampling an optional parameter for gdal.RegenerateOverview(),
    to be consistent with gdal.RegenerateOverviews()
  * NONNULL checks have been added to check various arguments of methods
  * add missing constants : DCAP_VIRTUALIO, color interpretations, OGR constants
@@ -5359,7 +5744,7 @@ CSharp bindings :
  * Add typemaps to support custom CPLErrorHandler via C# swig bindings
 
 Perl bindings :
- * in Polygonize make a local copy of the parameters as they are potentionally edited
+ * in Polygonize make a local copy of the parameters as they are potentially edited
 
 Python bindings :
  * Add support for Python 3.X. Compatibility with Python 2.X preserved (#3265)
@@ -5385,7 +5770,7 @@ Java bindings (general changes):
 Build (Unix):
  * Added basic support for LDFLAGS
  * Try prefix/lib before prefix/src for proj.4 linking (#1345)
- * Allow specification of a python binary for --with-ogpython (#2258)
+ * Allow specification of a python binary for --with-python (#2258)
  * Added NAS driver config support
  * Fixed Expat detection problem on MinGW (#2050)
  * Fix INST_DATA setting (/share/gdal instead of /share) (#2382)
@@ -5630,9 +6015,9 @@ GSAG driver:
  * Major update to correct upside problems, removing Create (#2224, #1616, #2191)
 
 GS7BG driver:
- * Fixed geotransormation matrix calculation (#2132)
+ * Fixed geotransformation matrix calculation (#2132)
  * Properly read the header on big-endian system.
- * fix bigendian support (#2172)
+ * Fix bigendian support (#2172)
 
 GTiff driver:
  * Add support for reading and writing embedded nodata masks of a TIFF file (TIFFTAG_SUBFILETYPE=FILETYPE_MASK)
@@ -5655,14 +6040,14 @@ GTiff driver:
  * Fix writing of blocks on TIFF files in non-native endianness (#2398)
  * Push extra bands of pixel interleaved data into block cache (#2435)
  * Improve integration with PAM metadata loading and saving (#2448)
- * Fix potential buffer overflow in GTIFAngleStringToDD (commited in upstream libgeotiff) - #2228
+ * Fix potential buffer overflow in GTIFAngleStringToDD (committed in upstream libgeotiff) - #2228
  * Fix GTiffOddBitsBand::IWriteBlock with GDT_UInt16/32; Error properly with GDT_Float32; Support creating files with NBITS>8; Handle NBITS=1 IReadBlock/IWriteBlock in GTiffOddBitsBand; Prevent subtle IReadBlock/IWriteBlock round-tripping bug for NBITS<8 (#2360)
  * Set the TIFFTAG_COMPRESSION compression before asking the default strip size, so that in the case of JPEG compression, the correct strip height is selected (either 8 or 16). Tested with libtiff-3.8.2 and internal libtiff
  * Prevent crash on tiff_ovr_9 when JPEG-In-TIFF support is not built
  * In GTiffDataset::Create(), set TIFFTAG_JPEGCOLORMODE=JPEGCOLORMODE_RGB when creating a TIFF with COMPRESS=JPEG and PHOTOMETRIC=YCBCR; In Crystalize(), backup the value of TIFFTAG_JPEGCOLORMODE and set it again after writing the directory (#2645)
  * Handle more gracefully the case where we open or create a TIFF file with a compression method not built in libtiff (use of TIFFIsCODECConfigured)
  * Don't fail when TIFFTAG_JPEGCOLORMODE tag cannot be read 
- * IPP libjpeg compatability changes (#2606)
+ * IPP libjpeg compatibility changes (#2606)
  * ensure zip/jpeg quality is preserved in crystalize. (#2642)
  * support handling nodata via pam/aux mechanisms (#2505)
  * ensure TIFFFlush() is called in FlushCache() (#2512)
@@ -5794,7 +6179,7 @@ NITF driver:
  * Fix #2135 by narrowing workaround test made for #1750
  * Prevent crash on NITF file without image segment (#2362)
  * Additionnal fix for handling 1-bit uncompressed NITF images with NITF_IC=NM  (#1854)
- * Set IREP=RGB implicitely when the first 3 channels of an image are R,G,B (#2343)
+ * Set IREP=RGB implicitly when the first 3 channels of an image are R,G,B (#2343)
  * Allocate one extra byte for the NULL terminating character when reading TEXT data in NITF file (#2366)
  * Fix 'adding BLOCKA TRE precludes writing IGEOLO' (#2475)
  * Add GDAL_DMD_CREATIONOPTIONLIST for NITF
@@ -5890,7 +6275,7 @@ WCS driver:
  * Strip namespaces off DescribeCoverage response (early), and add a bug
 workaround for GeoServer WCS 1.1 responses.
  * Correct wcs 1.1 band identification logic
- * URL encode format and coverage name.  Improve error recognision.
+ * URL encode format and coverage name.  Improve error recognition.
  * GridOffset should be top left corner of pixel center oriented bounds
 
 WMS driver:
@@ -6105,14 +6490,14 @@ SHAPE driver:
 
 S57 driver:
  * Ensure SOUNDG in multipoint form is MultiPoint25D not 2D.
- * Print out contents of OGR_S57_OPTIONS evvironment variable if set (for debug
+ * Print out contents of OGR_S57_OPTIONS environment variable if set (for debug
 purposes).
  * Correct control for applying updates, now done in Ingest method.
 
 VRT driver:
  * carry style string through VRT layer
  * Pass the envelope of the geometry as the spatial filter in the sub-query (#2214)
- * Add "shared" attribute on SrcDataSource to control sharing.  Default to OFF for SrcLayer layers, and ON for SrcSQL layers.  This endevours to avoid conflicts of layer state. (#2229)
+ * Add "shared" attribute on SrcDataSource to control sharing.  Default to OFF for SrcLayer layers, and ON for SrcSQL layers.  This endeavors to avoid conflicts of layer state. (#2229)
 
 XPlane/Flightgear driver:
  * New for 1.6.0 
@@ -6184,7 +6569,7 @@ SWIG Perl
  * Add wrappers for field types datetime and lists. Do not use the overloaded (field name) versions of the get/set functions.
  * GetField and SetField methods, which check for goodness of the field (name, index) and support dates, times, datetimes, and lists. In Row and Tuple the field value may be a listref.
  * Support HEXWKB in Geo::OGR::Geometry::create.
- * As* methods for Geometry as aliases for ExportTo; SpatialReference->create constuctor
+ * As* methods for Geometry as aliases for ExportTo; SpatialReference->create constructor
  * made needed links from parameters to typemaps to make Get- and SetDefaultHistogram methods work in Perl
  * support for mingw Windows builds
 
@@ -6233,7 +6618,7 @@ Algorithms / Utilities:
  * gdal_rasterize: added -i flag to rasterize all areas outside geometry.
  * gdalenhance: new utility for applying histogram equalization enhancements.
  * gdalmanage: Utility for managing datasets (identify, delete, copy, rename)
- * nearblack: Utility for fixing lossily compressed nodata collars.
+ * nearblack: Utility for fixing lossy compressed nodata collars.
 
 Intergraph Raster Driver:
  * New for 1.5.0.
@@ -6352,7 +6737,7 @@ Leveller Driver:
 == OGR 1.5.0 - Overview of Changes ==
 
 General:
- * Plugin drivers test for ABI compatability at load time.
+ * Plugin drivers test for ABI compatibility at load time.
  * SFCOM/OLEDB stuff all removed (moved to /spike in subversion).
  * Various thread safety improvements made.
  * Added PointOnSurface implementation for OGRPolygon.
@@ -6668,7 +7053,7 @@ PostGIS Driver:
  - Include proj4text in new spatial_ref_sys entries.
  - Fixed support for very large queries.
  - Fixed DeleteLayer() implementation.
- - Added COPY support for accerated loading.
+ - Added COPY support for accelerated loading.
 
 MySQL Driver:
  - Added read and write support for Spatial types. 
@@ -6784,7 +7169,7 @@ Multithreading:
  - Lots of work done to implement support for multiple threads reading
    from distinct GDALDataset objects at the same time. 
 
-GDALRasterBand / Persistant Auxiliary Metadata (PAM):
+GDALRasterBand / Persistent Auxiliary Metadata (PAM):
  - Support for preserving a variety of metadata in a supporting XML file. 
  - GDALRasterBand now supports "remembering" histograms, and has a concept
    of the default histogram. 
@@ -6846,7 +7231,7 @@ HFA (Imagine) Driver:
  - Support creating compressed files. 
 
 GeoTIFF Driver:
- - Support reading files with odd bit depths (ie. 3, 12, etc). 
+ - Support reading files with odd bit depths (i.e. 3, 12, etc). 
  - Support 16/24bit floating point TIFFs (per Technote 3) (Andrey).
  - Support 12bit jpeg compressed imagery using libjpeg "MK1" library.
 
@@ -6877,7 +7262,7 @@ Shape Driver:
 PostgreSQL/PostGIS Driver:
  - Implemented fast GetExtent() method (Oleg Semykin).
  - Implemented layer type from geometry_columns (Oleg Semykin).
- - Handle PostGIS 1.0 requirements for coordinate dimemsion exactness.
+ - Handle PostGIS 1.0 requirements for coordinate dimension exactness.
  - Handle EWKT type in PostGIS 1.0.
  - Generally PostGIS 0.x and 1.0 should now be supported fairly gracefully.
  - Added PostGIS "binary cursor" mode for faster geometry access.
@@ -6990,7 +7375,7 @@ ogr.py:
    unreference all features before destroying the corresponding 
    layer/datasource.
  - ogr.Feature fields can now be fetched and set directly as attributes. 
- - Geometry contructor can now take various formats (wkt, gml, and wkb). 
+ - Geometry constructor can now take various formats (wkt, gml, and wkb). 
  - Added docstrings. 
  - Added better __str__ methods on several objects. 
  - Various other improvements. 
@@ -7098,10 +7483,10 @@ GeoTIFF Driver:
 
 DODS Driver:
   - Almost completely reimplemented.   Uses chunk-by-chunk access.  Supports
-    reading several bands from seperate objects.  Some new limitations too.
+    reading several bands from separate objects.  Some new limitations too.
 
 NetCDF Driver:
-  - Seperated out a GMT NetCDF driver and a more generic but partially broken
+  - Separated out a GMT NetCDF driver and a more generic but partially broken
     NetCDF driver (Radim).
 
 JP2KAK Driver:
@@ -7240,7 +7625,7 @@ SQLite Driver:
     - New read/write driver implemented for SQLite databases.
 
 CSV Driver:
-    - New read/write driver implemented for comma seperated value files.
+    - New read/write driver implemented for comma separated value files.
 
 S-57 Driver:
     - Substantial performance improvements.
@@ -7468,7 +7853,7 @@ NTF Driver:
 GDAL 1.1.9 - Overview of Changes
 --------------------------------
 
- o MrSID Driver: New for 1.1.9, read-only, includes good coordiante system
+ o MrSID Driver: New for 1.1.9, read-only, includes good coordinate system
    support, and should be high performance. 
 
  o ECW Driver: Now reads coordinate system information (but doesn't write). 
@@ -7578,7 +7963,7 @@ GDAL 1.1.8 - Overview of Changes
 
  o Lots of work on VRT format.  
 
- o ECW: Fixed bug with reading a more than full resultion.
+ o ECW: Fixed bug with reading a more than full resolution.
 
  o Envisat driver now supports AATSR TOA and MERIS data.
 
@@ -7699,7 +8084,7 @@ GDAL 1.1.6 - Overview of Changes
 
  o Support for writing DTED files. 
 
- o Some raw formats (ie. PAux, HKV) support files larger than 2GB.
+ o Some raw formats (i.e. PAux, HKV) support files larger than 2GB.
 
  o Add the AddBand() method on GDALDataset.
 
@@ -7707,7 +8092,7 @@ GDAL 1.1.6 - Overview of Changes
 
  o Various fixes to OGDI driver.
 
- o Stripped out the GDALProjDef related capabilities.  Superceeded by
+ o Stripped out the GDALProjDef related capabilities.  Superseded by
    OGRSpatialReference, and OGRCoordinateTransformation functionality.
 
  o Improved CEOS support, notable for ESA LANDSAT files, D-PAF ERS-1 and
@@ -7734,7 +8119,7 @@ OGR 1.1.6 - Overview of Changes
  o DGN: Threat SHAPE elements as polygons.  Set style information for text.
    Added 3D support for most elements. 
 
- o Fixed bugs in WKT format for some OGR geometry types (ie. multipoint).
+ o Fixed bugs in WKT format for some OGR geometry types (i.e. multipoint).
 
  o Added support for morphing to/from ESRI WKT format for OGRSpatialReference.
 
@@ -7802,7 +8187,7 @@ o ERMapper ECW Driver is new.
 o GDAL Bridge: upgraded to include new entry points, like GCP access and
 nodata api.
 
-o gdal_translate: added the -not_scrict option.
+o gdal_translate: added the -not_strict option.
 
 o GDALGetRandomRasterSample(): Return magnitude for random samples.
 
@@ -7882,7 +8267,7 @@ o TIGER/Line Driver:
 o OLE DB Provider:
 - Added support for spatial queries via ICommand parameters.
 - Added support for attribute queries by parsing out WHERE clause.
-- In general substantial rework and extentions were made to make it
+- In general substantial rework and extensions were made to make it
 work with ESRI and AutoDesk clients.
 
 o Added gdal/data/stateplane.txt - a test file with one line per state plane
diff --git a/NEWS.template b/NEWS.template
new file mode 100644
index 0000000..fb62361
--- /dev/null
+++ b/NEWS.template
@@ -0,0 +1,230 @@
+= GDAL/OGR X.Y.Z Release Notes (r25919 to rXXXXX) =
+
+== In a nutshell... ==
+
+ * New GDAL drivers:
+ * New OGR drivers:
+
+== New installed files ==
+
+== Backward compatibility issues ==
+
+== GDAL/OGR X.Y.Z - General Changes ==
+
+Build(Unix):
+
+Build(Windows):
+
+== GDAL X.Y.Z - Overview of Changes ==
+
+Port:
+
+Core:
+
+Algorithms:
+
+Utilities:
+
+Multi driver changes:
+
+AAIGrid:
+
+ACE2 driver:
+
+ADRG driver:
+
+BAG driver:
+
+BT driver:
+
+CEOS2 driver:
+
+DIMAP driver:
+
+DTED driver:
+
+ECW driver:
+
+ENVI driver:
+
+ENVISAT driver:
+
+GeoRaster driver:
+
+GIF driver:
+
+GMT driver:
+
+GTiff driver:
+
+GRIB driver:
+
+GSAG driver:
+
+GS7BG driver:
+
+GTX driver:
+
+GXF driver:
+
+HDF4 driver:
+
+HDF5 driver:
+
+HFA driver:
+
+INGR driver:
+
+ISIS3 driver:
+
+JP2ECW driver:
+
+JP2KAK driver:
+
+JP2OpenJPEG driver:
+
+JPEG driver:
+
+JPEG2000 driver:
+
+KMLSuperOverlay driver:
+
+L1B driver:
+
+MG4Lidar driver:
+
+NetCDF driver:
+
+NITF driver:
+
+Northwood driver:
+
+PDF driver:
+
+PNG driver:
+
+PostgisRaster driver:
+
+Rasterlite driver:
+
+RMF driver:
+
+RPFTOC driver:
+
+RS2 driver:
+
+SDTS driver:
+
+SRP driver:
+
+TIL driver:
+
+TSX driver:
+
+VRT driver:
+
+WCS driver:
+
+WebP driver:
+
+WMS driver:
+
+XYZ driver:
+
+== OGR X.Y.Z - Overview of Changes ==
+
+Core:
+
+OGRSpatialReference:
+
+Utilities:
+
+Multi driver changes:
+
+AVCE00 driver:
+
+AVCBin driver:
+
+CSV driver:
+
+DGN driver:
+
+DXF driver:
+
+FileGDB driver:
+
+Geoconcept driver:
+
+GeoJSON driver:
+
+Geomedia driver:
+
+GFT driver:
+
+GML driver:
+
+ILI driver:
+
+Ingres driver:
+
+KML driver:
+
+Idrisi driver:
+
+LIBKML driver:
+
+MITAB driver:
+
+MSSQLSpatial driver:
+
+MySQL:
+
+NAS driver:
+
+NULL driver:
+
+OCI driver:
+
+ODBC driver:
+
+NTF driver:
+
+OCI driver:
+
+PGeo driver:
+
+PG driver:
+
+PGDump driver:
+
+REC driver:
+
+SDE driver:
+
+Shapefile driver:
+
+S57 driver:
+
+SQLite/Spatialite driver:
+
+TIGER driver:
+
+VFK driver:
+
+VRT driver:
+
+WFS driver:
+
+XLS driver:
+
+== SWIG Language Bindings ==
+
+All bindings:
+
+CSharp bindings:
+
+Java bindings:
+
+Perl bindings:
+
+Python bindings:
diff --git a/PROVENANCE.TXT b/PROVENANCE.TXT
index 919c5bc..ede380f 100644
--- a/PROVENANCE.TXT
+++ b/PROVENANCE.TXT
@@ -127,7 +127,7 @@ Note: all the following are build options, not required.
 * cubewerx_extra.wkt: derived from definitions distributed by Cubewerx, rights unclear. See http://trac.osgeo.org/gdal/ticket/2165
 * ecw_cs.wkt: Derived via much processing from ERMapper GDT definitions, rights unclear. See http://trac.osgeo.org/gdal/ticket/2162
 * esri_extra.wkt: Derived with some processing from projections definitions in ArcGIS, rights unclear. See http://trac.osgeo.org/gdal/ticket/2163
-* ellipsoid.csv, gcs.csv, gdal_datum.csv, pcs.csv, prime_meridian.csv, projop_wparm.csv, unit_of_measure.csv: Derived from EPSG.  Modifications to EPSG data violate the EPSG use agreement (if we are to still attribute it to EPSG) so I have segregated changes into override files (ie. gcs.override.csv). 
+* ellipsoid.csv, gcs.csv, gdal_datum.csv, pcs.csv, prime_meridian.csv, projop_wparm.csv, unit_of_measure.csv: Derived from EPSG.  Modifications to EPSG data violate the EPSG use agreement (if we are to still attribute it to EPSG) so I have segregated changes into override files (i.e. gcs.override.csv). 
 * seed_2d.dgn, seed_3d.dgn: Exact source of these files is unclear.  The files contain no substantial creative content since all but the header elements were stripped.  Judged to acceptable use. 
 * NTS-50kindex.csv: Provided by Matt Wilkie, derived from NRCan dataset, rights unclear.  See http://trac.osgeo.org/gdal/ticket/2164 (closed - this file isn't actually in the source tree - it is separately distributed as part of FWTools!)
 
@@ -148,10 +148,6 @@ Note: all the following are build options, not required.
 
 * copyright somewhat unclear, not actually part of software. 
 
-=== gdal/dist_docs ===
-
-* All written by me, not used any more.  
-
 === gdal/doc ===
 
 * no copyright messages in .dox files.
@@ -171,10 +167,6 @@ Note: all the following are build options, not required.
 * histrep.py: corrected copyright message (Atlantis to FrankW), change license to MIT/X.
 * various contributors, all under proper and compatible copyright headers.
 
-=== gdal/wince ===
-
-* all written by Mateusz Loskot.
-
 === gdal/vb6 ===
 
 * all written by FrankW, clean. 
@@ -232,7 +224,7 @@ Note: all the following are build options, not required.
 === gdal/ogr/ogrsf_frmts/mitab ===
 
 * Copyright Daniel Morissette, Stepane Villeneuve, Frank Warmerdam (MIT/X). 
-* Some code derived from MapServer with credit in headers, no problem forseen.
+* Some code derived from MapServer with credit in headers, no problem foreseen.
 * All clean.
 
 === gdal/ogr/ogrsf_frmts/mysql ===
@@ -308,7 +300,7 @@ Note: all the following are build options, not required.
 * SpatialReferenceIdl.idl, GeometryIdl.idl, CoverageIdl.idl: From OGC spec package I believe.  (removed)
 * ogr_capi_test.c: no copyright message, written by Daniel Morissette. Added copyright.
 * oledbgis.h: No copyright message, mostly OGC spec constants. 
-* swq.h, swq.c: Has alternate form of MIT/X license.  On review this license is functionally equililent to the general GDAL license.
+* swq.h, swq.c: Has alternate form of MIT/X license.  On review this license is functionally equivalent to the general GDAL license.
 * Copyright holders include Frank Warmerdam, Daniel Morissette, Softmap Inc., Stephane Villeneuve., Andrey Kiselev, Information Interoperability Institute
 
 
@@ -530,7 +522,7 @@ I have added this license to LICENSE.TXT to satisfy the credit requirement.
 === gdal/frmts/pcraster ===
 
 * Kor de Jong holds copyright.
-* Some missing headers (pcrasterdataset.h, pcrastermisc.cpp, pcrasterrasterband.cpp, pcpcrasterutil.cpp, pcrasterutil.h (#1822).
+* Some missing headers (pcrasterdataset.h, pcrastermisc.cpp, pcrasterrasterband.cpp, pcrasterutil.cpp, pcrasterutil.h (#1822).
 * libcsf: license and copyright implicit in AUTHORS and COPYING documents. 
 * libcsf COPYING indicates an MIT-like agreement but with more explicit requirements for notice in binaries.  Added to gdal/LICENSE.TXT
 
diff --git a/VERSION b/VERSION
index e9307ca..7d002b1 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.0.2
+2.1.0beta1
diff --git a/Vagrantfile b/Vagrantfile
index 793257a..54abdd4 100644
--- a/Vagrantfile
+++ b/Vagrantfile
@@ -16,15 +16,17 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
   config.vm.hostname = "gdal-vagrant"
   config.vm.box_url = "http://files.vagrantup.com/precise64.box"
   config.vm.host_name = "gdal-vagrant"
-  
+
   config.vm.network :forwarded_port, guest: 80, host: 8080
 
+  config.vm.synced_folder "../autotest/", "/home/vagrant/autotest/"
+
   config.vm.provider :virtualbox do |vb|
      vb.customize ["modifyvm", :id, "--memory", vm_ram]
      vb.customize ["modifyvm", :id, "--cpus", vm_cpu]
      vb.customize ["modifyvm", :id, "--ioapic", "on"]
      vb.name = "gdal-vagrant"
-   end  
+   end
 
   ppaRepos = [
     "ppa:ubuntugis/ubuntugis-unstable", "ppa:marlam/gta"
diff --git a/aclocal.m4 b/aclocal.m4
index 187c970..d9e879d 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -1,7 +1,7 @@
-# generated automatically by aclocal 1.11 -*- Autoconf -*-
+# generated automatically by aclocal 1.14.1 -*- Autoconf -*-
+
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
 
-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-# 2005, 2006, 2007, 2008, 2009  Free Software Foundation, Inc.
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
@@ -11,8 +11,10 @@
 # even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 # PARTICULAR PURPOSE.
 
+m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
 m4_include([m4/acinclude.m4])
 m4_include([m4/ax_cflags_warn_all.m4])
+m4_include([m4/ax_check_compile_flag.m4])
 m4_include([m4/ax_lib_expat.m4])
 m4_include([m4/ax_lib_libkml.m4])
 m4_include([m4/ax_lib_sqlite3.m4])
diff --git a/alg/GNUmakefile b/alg/GNUmakefile
index 832c6a0..3121032 100644
--- a/alg/GNUmakefile
+++ b/alg/GNUmakefile
@@ -8,9 +8,9 @@ OBJ	=	gdalmediancut.o gdaldither.o gdal_crs.o gdaltransformer.o \
 		gdalgrid.o gdalcutline.o gdalproximity.o rasterfill.o \
 		gdalrasterpolygonenumerator.o \
 		gdalsievefilter.o gdalwarpkernel_opencl.o polygonize.o \
-		gdalrasterfpolygonenumerator.o fpolygonize.o \
 		contour.o gdaltransformgeolocs.o \
-		gdal_octave.o gdal_simplesurf.o gdalmatching.o
+		gdal_octave.o gdal_simplesurf.o gdalmatching.o delaunay.o \
+		gdalpansharpen.o
 
 ifeq ($(HAVE_AVX_AT_COMPILE_TIME),yes)
 CPPFLAGS 	:=	-DHAVE_AVX_AT_COMPILE_TIME $(CPPFLAGS)
@@ -28,12 +28,21 @@ ifeq ($(HAVE_ARMADILLO),yes)
 CPPFLAGS 	:=	-DHAVE_ARMADILLO $(CPPFLAGS)
 endif
 
+ifeq ($(QHULL_SETTING),external)
+CPPFLAGS 	:=	-DEXTERNAL_QHULL $(CPPFLAGS)
+endif
+ifeq ($(QHULL_SETTING),internal)
+CPPFLAGS 	:=	-DINTERNAL_QHULL -Ilibqhull $(CPPFLAGS)
+endif
+
 CPPFLAGS	:=	$(CPPFLAGS) $(OPENCL_FLAGS)
 
 default:	$(OBJ:.o=.$(OBJ_EXT)) gdalgridavx.$(OBJ_EXT) gdalgridsse.$(OBJ_EXT)
 
+# We use CXXFLAGS_NO_LTO_IF_AVX_NONDEFAULT to avoid the whole library to be compiled with -mavx
+# if -mavx is not the default
 gdalgridavx.$(OBJ_EXT):   gdalgridavx.cpp
-	$(CXX) $(GDAL_INCLUDE) $(CXXFLAGS) $(AVXFLAGS) $(CPPFLAGS) -c -o $@ $<
+	$(CXX) $(GDAL_INCLUDE) $(CXXFLAGS_NO_LTO_IF_AVX_NONDEFAULT) $(AVXFLAGS) $(CPPFLAGS) -c -o $@ $<
 
 gdalgridsse.$(OBJ_EXT):   gdalgridsse.cpp
 	$(CXX) $(GDAL_INCLUDE) $(CXXFLAGS) $(SSEFLAGS) $(CPPFLAGS) -c -o $@ $<
diff --git a/alg/contour.cpp b/alg/contour.cpp
index 40a0587..4242e55 100644
--- a/alg/contour.cpp
+++ b/alg/contour.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: contour.cpp 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: contour.cpp 33757 2016-03-20 20:22:33Z goatbar $
  *
  * Project:  Contour Generation
- * Purpose:  Core algorithm implementation for contour line generation. 
+ * Purpose:  Core algorithm implementation for contour line generation.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -33,9 +33,7 @@
 #include "gdal_alg.h"
 #include "ogr_api.h"
 
-CPL_CVSID("$Id: contour.cpp 27044 2014-03-16 23:41:27Z rouault $");
-
-#ifdef OGR_ENABLED
+CPL_CVSID("$Id: contour.cpp 33757 2016-03-20 20:22:33Z goatbar $");
 
 // The amount of a contour interval that pixels should be fudged by if they
 // match a contour level exactly.
@@ -43,7 +41,7 @@ CPL_CVSID("$Id: contour.cpp 27044 2014-03-16 23:41:27Z rouault $");
 #define FUDGE_EXACT 0.001
 
 // The amount of a pixel that line ends need to be within to be considered to
-// match for joining purposes. 
+// match for joining purposes.
 
 #define JOIN_DIST 0.0001
 
@@ -78,14 +76,14 @@ public:
 /************************************************************************/
 /*                           GDALContourLevel                           */
 /************************************************************************/
-class GDALContourLevel 
+class GDALContourLevel
 {
     double dfLevel;
 
     int nEntryMax;
     int nEntryCount;
     GDALContourItem **papoEntries;
-    
+
 public:
     GDALContourLevel( double );
     ~GDALContourLevel();
@@ -122,18 +120,18 @@ class GDALContourGenerator
     double  dfContourInterval;
     double  dfContourOffset;
 
-    CPLErr AddSegment( double dfLevel, 
+    CPLErr AddSegment( double dfLevel,
                        double dfXStart, double dfYStart,
                        double dfXEnd, double dfYEnd, int bLeftHigh );
 
     CPLErr ProcessPixel( int iPixel );
-    CPLErr ProcessRect( double, double, double, 
-                        double, double, double, 
+    CPLErr ProcessRect( double, double, double,
+                        double, double, double,
                         double, double, double,
                         double, double, double );
 
-    void   Intersect( double, double, double, 
-                      double, double, double, 
+    void   Intersect( double, double, double,
+                      double, double, double,
                       double, double, int *, double *, double * );
 
     GDALContourLevel *FindLevel( double dfLevel );
@@ -146,29 +144,31 @@ public:
                           GDALContourWriter pfnWriter, void *pWriterCBData );
     ~GDALContourGenerator();
 
+    bool                Init();
+
     void                SetNoData( double dfNoDataValue );
-    void                SetContourLevels( double dfContourInterval, 
-                                          double dfContourOffset = 0.0 )
-        { this->dfContourInterval = dfContourInterval;
-          this->dfContourOffset = dfContourOffset; }
+    void                SetContourLevels( double dfContourIntervalIn,
+                                          double dfContourOffsetIn = 0.0 )
+        { dfContourInterval = dfContourIntervalIn;
+          dfContourOffset = dfContourOffsetIn; }
 
     void                SetFixedLevels( int, double * );
     CPLErr              FeedLine( double *padfScanline );
     CPLErr              EjectContours( int bOnlyUnused = FALSE );
-    
+
 };
 
 /************************************************************************/
 /*                           GDAL_CG_Create()                           */
 /************************************************************************/
 
-GDALContourGeneratorH 
-GDAL_CG_Create( int nWidth, int nHeight, int bNoDataSet, double dfNoDataValue, 
-                double dfContourInterval, double dfContourBase, 
+GDALContourGeneratorH
+GDAL_CG_Create( int nWidth, int nHeight, int bNoDataSet, double dfNoDataValue,
+                double dfContourInterval, double dfContourBase,
                 GDALContourWriter pfnWriter, void *pCBData )
 
 {
-    GDALContourGenerator *poCG = new GDALContourGenerator( nWidth, nHeight, 
+    GDALContourGenerator *poCG = new GDALContourGenerator( nWidth, nHeight,
                                                            pfnWriter, pCBData );
 
     if( bNoDataSet )
@@ -211,14 +211,14 @@ void GDAL_CG_Destroy( GDALContourGeneratorH hCG )
 /************************************************************************/
 
 GDALContourGenerator::GDALContourGenerator( int nWidthIn, int nHeightIn,
-                                            GDALContourWriter pfnWriterIn, 
+                                            GDALContourWriter pfnWriterIn,
                                             void *pWriterCBDataIn )
 {
     nWidth = nWidthIn;
     nHeight = nHeightIn;
 
-    padfLastLine = (double *) CPLCalloc(sizeof(double),nWidth);
-    padfThisLine = (double *) CPLCalloc(sizeof(double),nWidth);
+    padfLastLine = NULL;
+    padfThisLine = NULL;
 
     pfnWriter = pfnWriterIn;
     pWriterCBData = pWriterCBDataIn;
@@ -254,10 +254,21 @@ GDALContourGenerator::~GDALContourGenerator()
 }
 
 /************************************************************************/
+/*                              Init()                                  */
+/************************************************************************/
+
+bool GDALContourGenerator::Init()
+{
+    padfLastLine = (double *) VSI_CALLOC_VERBOSE(sizeof(double),nWidth);
+    padfThisLine = (double *) VSI_CALLOC_VERBOSE(sizeof(double),nWidth);
+    return padfLastLine != NULL && padfThisLine != NULL;
+}
+
+/************************************************************************/
 /*                           SetFixedLevels()                           */
 /************************************************************************/
 
-void GDALContourGenerator::SetFixedLevels( int nFixedLevelCount, 
+void GDALContourGenerator::SetFixedLevels( int nFixedLevelCount,
                                            double *padfFixedLevels )
 
 {
@@ -294,14 +305,14 @@ CPLErr GDALContourGenerator::ProcessPixel( int iPixel )
 /* -------------------------------------------------------------------- */
     dfUpLeft = padfLastLine[MAX(0,iPixel-1)];
     dfUpRight = padfLastLine[MIN(nWidth-1,iPixel)];
-    
+
     dfLoLeft = padfThisLine[MAX(0,iPixel-1)];
     dfLoRight = padfThisLine[MIN(nWidth-1,iPixel)];
 
 /* -------------------------------------------------------------------- */
 /*      Check if we have any nodata values.                             */
 /* -------------------------------------------------------------------- */
-    if( bNoDataActive 
+    if( bNoDataActive
         && ( dfUpLeft == dfNoDataValue
              || dfLoLeft == dfNoDataValue
              || dfLoRight == dfNoDataValue
@@ -312,22 +323,22 @@ CPLErr GDALContourGenerator::ProcessPixel( int iPixel )
 /*      Check if we have any nodata, if so, go to a special case of     */
 /*      code.                                                           */
 /* -------------------------------------------------------------------- */
-    if( iPixel > 0 && iPixel < nWidth 
+    if( iPixel > 0 && iPixel < nWidth
         && iLine > 0 && iLine < nHeight && !bSubdivide )
     {
-        return ProcessRect( dfUpLeft, iPixel - 0.5, iLine - 0.5, 
-                            dfLoLeft, iPixel - 0.5, iLine + 0.5, 
-                            dfLoRight, iPixel + 0.5, iLine + 0.5, 
+        return ProcessRect( dfUpLeft, iPixel - 0.5, iLine - 0.5,
+                            dfLoLeft, iPixel - 0.5, iLine + 0.5,
+                            dfLoRight, iPixel + 0.5, iLine + 0.5,
                             dfUpRight, iPixel + 0.5, iLine - 0.5 );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Prepare subdivisions.                                           */
 /* -------------------------------------------------------------------- */
-    int nGoodCount = 0; 
+    int nGoodCount = 0;
     double dfASum = 0.0;
-    double dfCenter, dfTop=0.0, dfRight=0.0, dfLeft=0.0, dfBottom=0.0;
-    
+    double dfTop=0.0, dfRight=0.0, dfLeft=0.0, dfBottom=0.0;
+
     if( dfUpLeft != dfNoDataValue )
     {
         dfASum += dfUpLeft;
@@ -352,10 +363,10 @@ CPLErr GDALContourGenerator::ProcessPixel( int iPixel )
         nGoodCount++;
     }
 
-    if( nGoodCount == 0.0 )
+    if( nGoodCount == 0 )
         return CE_None;
 
-    dfCenter = dfASum / nGoodCount;
+    double dfCenter = dfASum / nGoodCount;
 
     if( dfUpLeft != dfNoDataValue )
     {
@@ -400,34 +411,34 @@ CPLErr GDALContourGenerator::ProcessPixel( int iPixel )
 
     if( dfUpLeft != dfNoDataValue && iPixel > 0 && iLine > 0 )
     {
-        eErr = ProcessRect( dfUpLeft, iPixel - 0.5, iLine - 0.5, 
-                            dfLeft, iPixel - 0.5, iLine, 
-                            dfCenter, iPixel, iLine, 
+        eErr = ProcessRect( dfUpLeft, iPixel - 0.5, iLine - 0.5,
+                            dfLeft, iPixel - 0.5, iLine,
+                            dfCenter, iPixel, iLine,
                             dfTop, iPixel, iLine - 0.5 );
     }
 
-    if( dfLoLeft != dfNoDataValue && eErr == CE_None 
+    if( dfLoLeft != dfNoDataValue && eErr == CE_None
         && iPixel > 0 && iLine < nHeight )
     {
-        eErr = ProcessRect( dfLeft, iPixel - 0.5, iLine, 
+        eErr = ProcessRect( dfLeft, iPixel - 0.5, iLine,
                             dfLoLeft, iPixel - 0.5, iLine + 0.5,
-                            dfBottom, iPixel, iLine + 0.5, 
+                            dfBottom, iPixel, iLine + 0.5,
                             dfCenter, iPixel, iLine );
     }
 
     if( dfLoRight != dfNoDataValue && iPixel < nWidth && iLine < nHeight )
     {
-        eErr = ProcessRect( dfCenter, iPixel, iLine, 
+        eErr = ProcessRect( dfCenter, iPixel, iLine,
                             dfBottom, iPixel, iLine + 0.5,
-                            dfLoRight, iPixel + 0.5, iLine + 0.5, 
+                            dfLoRight, iPixel + 0.5, iLine + 0.5,
                             dfRight, iPixel + 0.5, iLine );
     }
 
     if( dfUpRight != dfNoDataValue && iPixel < nWidth && iLine > 0 )
     {
-        eErr = ProcessRect( dfTop, iPixel, iLine - 0.5, 
+        eErr = ProcessRect( dfTop, iPixel, iLine - 0.5,
                             dfCenter, iPixel, iLine,
-                            dfRight, iPixel + 0.5, iLine, 
+                            dfRight, iPixel + 0.5, iLine,
                             dfUpRight, iPixel + 0.5, iLine - 0.5 );
     }
 
@@ -438,12 +449,12 @@ CPLErr GDALContourGenerator::ProcessPixel( int iPixel )
 /*                            ProcessRect()                             */
 /************************************************************************/
 
-CPLErr GDALContourGenerator::ProcessRect( 
-    double dfUpLeft, double dfUpLeftX, double dfUpLeftY, 
-    double dfLoLeft, double dfLoLeftX, double dfLoLeftY, 
-    double dfLoRight, double dfLoRightX, double dfLoRightY, 
+CPLErr GDALContourGenerator::ProcessRect(
+    double dfUpLeft, double dfUpLeftX, double dfUpLeftY,
+    double dfLoLeft, double dfLoLeftX, double dfLoLeftY,
+    double dfLoRight, double dfLoRightX, double dfLoRightY,
     double dfUpRight, double dfUpRightX, double dfUpRightY )
-    
+
 {
 /* -------------------------------------------------------------------- */
 /*      Identify the range of elevations over this rect.                */
@@ -452,13 +463,13 @@ CPLErr GDALContourGenerator::ProcessRect(
 
     double dfMin = MIN(MIN(dfUpLeft,dfUpRight),MIN(dfLoLeft,dfLoRight));
     double dfMax = MAX(MAX(dfUpLeft,dfUpRight),MAX(dfLoLeft,dfLoRight));
-    
+
 
 /* -------------------------------------------------------------------- */
 /*      Compute the set of levels to compute contours for.              */
 /* -------------------------------------------------------------------- */
 
-    /* 
+    /*
     ** If we are using fixed levels, then find the min/max in the levels
     ** table.
     */
@@ -470,9 +481,9 @@ CPLErr GDALContourGenerator::ProcessRect(
         while( nStart <= nEnd )
         {
             nMiddle = (nEnd + nStart) / 2;
-            
+
             double dfMiddleLevel = papoLevels[nMiddle]->GetLevel();
-            
+
             if( dfMiddleLevel < dfMin )
                 nStart = nMiddle + 1;
             else if( dfMiddleLevel > dfMin )
@@ -488,7 +499,7 @@ CPLErr GDALContourGenerator::ProcessRect(
             iStartLevel = nEnd + 1;
 
         iEndLevel = iStartLevel;
-        while( iEndLevel < nLevelCount-1 
+        while( iEndLevel < nLevelCount-1
                && papoLevels[iEndLevel+1]->GetLevel() < dfMax )
             iEndLevel++;
 
@@ -504,9 +515,9 @@ CPLErr GDALContourGenerator::ProcessRect(
     */
     else
     {
-        iStartLevel = (int) 
+        iStartLevel = (int)
             ceil((dfMin - dfContourOffset) / dfContourInterval);
-        iEndLevel = (int)   
+        iEndLevel = (int)
             floor((dfMax - dfContourOffset) / dfContourInterval);
     }
 
@@ -527,7 +538,7 @@ CPLErr GDALContourGenerator::ProcessRect(
         else
             dfLevel = iLevel * dfContourInterval + dfContourOffset;
 
-        int  nPoints = 0; 
+        int  nPoints = 0;
         double adfX[4], adfY[4];
         CPLErr eErr = CE_None;
 
@@ -552,7 +563,7 @@ CPLErr GDALContourGenerator::ProcessRect(
         Intersect( dfUpRight, dfUpRightX, dfUpRightY,
                    dfUpLeft, dfUpLeftX, dfUpLeftY,
                    dfLoLeft, dfLevel, &nPoints, adfX, adfY );
-        
+
         if( nPoints == 1 || nPoints == 3 )
             CPLDebug( "CONTOUR", "Got nPoints = %d", nPoints );
 
@@ -564,13 +575,13 @@ CPLErr GDALContourGenerator::ProcessRect(
                                    adfX[0], adfY[0], adfX[1], adfY[1],
                                    dfUpRight > dfLoLeft );
             }
-            else if ( nPoints1 == 1 && nPoints3 == 2 ) // left + right 
+            else if ( nPoints1 == 1 && nPoints3 == 2 ) // left + right
             {
                 eErr = AddSegment( dfLevel,
                                    adfX[0], adfY[0], adfX[1], adfY[1],
                                    dfUpLeft > dfLoRight );
             }
-            else if ( nPoints1 == 1 && nPoints == 2 ) // left + top 
+            else if ( nPoints1 == 1 && nPoints == 2 ) // left + top
             { // Do not do vertical contours on the left, due to symmetry
               if ( !(dfUpLeft == dfLevel && dfLoLeft == dfLevel) )
                 eErr = AddSegment( dfLevel,
@@ -601,7 +612,7 @@ CPLErr GDALContourGenerator::ProcessRect(
                 // If we get here it is a serious error!
                 CPLDebug( "CONTOUR", "Contour state not implemented!");
             }
- 
+
             if( eErr != CE_None )
                  return eErr;
         }
@@ -634,10 +645,10 @@ CPLErr GDALContourGenerator::ProcessRect(
 /*                             Intersect()                              */
 /************************************************************************/
 
-void GDALContourGenerator::Intersect( double dfVal1, double dfX1, double dfY1, 
+void GDALContourGenerator::Intersect( double dfVal1, double dfX1, double dfY1,
                                       double dfVal2, double dfX2, double dfY2,
-                                      double dfNext, 
-                                      double dfLevel, int *pnPoints, 
+                                      double dfNext,
+                                      double dfLevel, int *pnPoints,
                                       double *padfX, double *padfY )
 
 {
@@ -669,7 +680,7 @@ void GDALContourGenerator::Intersect( double dfVal1, double dfX1, double dfY1,
 /*                             AddSegment()                             */
 /************************************************************************/
 
-CPLErr GDALContourGenerator::AddSegment( double dfLevel, 
+CPLErr GDALContourGenerator::AddSegment( double dfLevel,
                                          double dfX1, double dfY1,
                                          double dfX2, double dfY2,
                                          int bLeftHigh)
@@ -697,7 +708,7 @@ CPLErr GDALContourGenerator::AddSegment( double dfLevel,
         poTarget->AddSegment( dfX1, dfY1, dfX2, dfY2, bLeftHigh );
 
         poLevel->AdjustContour( iTarget );
-        
+
         return CE_None;
     }
 
@@ -751,7 +762,7 @@ CPLErr GDALContourGenerator::FeedLine( double *padfScanline )
         if( bNoDataActive && padfThisLine[iPixel] == dfNoDataValue )
             continue;
 
-        double dfLevel = (padfThisLine[iPixel] - dfContourOffset) 
+        double dfLevel = (padfThisLine[iPixel] - dfContourOffset)
             / dfContourInterval;
 
         if( dfLevel - (int) dfLevel == 0.0 )
@@ -793,7 +804,7 @@ CPLErr GDALContourGenerator::FeedLine( double *padfScanline )
         if( eErr != CE_None )
             return eErr;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      eject any pending contours.                                     */
 /* -------------------------------------------------------------------- */
@@ -825,13 +836,13 @@ CPLErr GDALContourGenerator::EjectContours( int bOnlyUnused )
         GDALContourLevel *poLevel = papoLevels[iLevel];
         int iContour;
 
-        for( iContour = 0; 
-             iContour < poLevel->GetContourCount() && eErr == CE_None; 
+        for( iContour = 0;
+             iContour < poLevel->GetContourCount() && eErr == CE_None;
              /* increment in loop if we don't consume it. */ )
         {
             int  iC2;
             GDALContourItem *poTarget = poLevel->GetContour( iContour );
-            
+
             if( bOnlyUnused && poTarget->bRecentlyAccessed )
             {
                 iContour++;
@@ -841,7 +852,7 @@ CPLErr GDALContourGenerator::EjectContours( int bOnlyUnused )
             poLevel->RemoveContour( iContour );
 
             // Try to find another contour we can merge with in this level.
-            
+
             for( iC2 = 0; iC2 < poLevel->GetContourCount(); iC2++ )
             {
                 GDALContourItem *poOther = poLevel->GetContour( iC2 );
@@ -850,7 +861,7 @@ CPLErr GDALContourGenerator::EjectContours( int bOnlyUnused )
                     break;
             }
 
-            // If we didn't merge it, then eject (write) it out. 
+            // If we didn't merge it, then eject (write) it out.
             if( iC2 == poLevel->GetContourCount() )
             {
                 if( pfnWriter != NULL )
@@ -858,8 +869,8 @@ CPLErr GDALContourGenerator::EjectContours( int bOnlyUnused )
                     // If direction is wrong, then reverse before ejecting.
                     poTarget->PrepareEjection();
 
-                    eErr = pfnWriter( poTarget->dfLevel, poTarget->nPoints, 
-                                      poTarget->padfX, poTarget->padfY, 
+                    eErr = pfnWriter( poTarget->dfLevel, poTarget->nPoints,
+                                      poTarget->padfX, poTarget->padfY,
                                       pWriterCBData );
                 }
             }
@@ -906,12 +917,12 @@ GDALContourLevel *GDALContourGenerator::FindLevel( double dfLevel )
     if( nLevelMax == nLevelCount )
     {
         nLevelMax = nLevelMax * 2 + 10;
-        papoLevels = (GDALContourLevel **) 
+        papoLevels = (GDALContourLevel **)
             CPLRealloc( papoLevels, sizeof(void*) * nLevelMax );
     }
 
     if( nLevelCount - nEnd - 1 > 0 )
-        memmove( papoLevels + nEnd + 2, papoLevels + nEnd + 1, 
+        memmove( papoLevels + nEnd + 2, papoLevels + nEnd + 1,
                  (nLevelCount - nEnd - 1) * sizeof(void*) );
     papoLevels[nEnd+1] = poLevel;
     nLevelCount++;
@@ -960,7 +971,7 @@ GDALContourLevel::~GDALContourLevel()
 void GDALContourLevel::AdjustContour( int iChanged )
 
 {
-    while( iChanged > 0 
+    while( iChanged > 0
          && papoEntries[iChanged]->dfTailX < papoEntries[iChanged-1]->dfTailX )
     {
         GDALContourItem *poTemp = papoEntries[iChanged];
@@ -987,7 +998,7 @@ void GDALContourLevel::RemoveContour( int iTarget )
 
 {
     if( iTarget < nEntryCount )
-        memmove( papoEntries + iTarget, papoEntries + iTarget + 1, 
+        memmove( papoEntries + iTarget, papoEntries + iTarget + 1,
                  (nEntryCount - iTarget - 1) * sizeof(void*) );
     nEntryCount--;
 }
@@ -1018,7 +1029,7 @@ int GDALContourLevel::FindContour( double dfX, double dfY )
             nEnd = nMiddle - 1;
         else
         {
-            while( nMiddle > 0 
+            while( nMiddle > 0
                    && fabs(papoEntries[nMiddle]->dfTailX-dfX) < JOIN_DIST )
                 nMiddle--;
 
@@ -1075,7 +1086,7 @@ int GDALContourLevel::InsertContour( GDALContourItem *poNewContour )
     if( nEntryMax == nEntryCount )
     {
         nEntryMax = nEntryMax * 2 + 10;
-        papoEntries = (GDALContourItem **) 
+        papoEntries = (GDALContourItem **)
             CPLRealloc( papoEntries, sizeof(void*) * nEntryMax );
     }
 
@@ -1083,7 +1094,7 @@ int GDALContourLevel::InsertContour( GDALContourItem *poNewContour )
 /*      Insert the new contour at the appropriate location.             */
 /* -------------------------------------------------------------------- */
     if( nEntryCount - nEnd - 1 > 0 )
-        memmove( papoEntries + nEnd + 2, papoEntries + nEnd + 1, 
+        memmove( papoEntries + nEnd + 2, papoEntries + nEnd + 1,
                  (nEntryCount - nEnd - 1) * sizeof(void*) );
     papoEntries[nEnd+1] = poNewContour;
     nEntryCount++;
@@ -1111,7 +1122,7 @@ GDALContourItem::GDALContourItem( double dfLevelIn )
     nMaxPoints = 0;
     padfX = NULL;
     padfY = NULL;
-    
+
     bLeftIsHigh = FALSE;
 
     dfTailX = 0.0;
@@ -1132,7 +1143,7 @@ GDALContourItem::~GDALContourItem()
 /*                             AddSegment()                             */
 /************************************************************************/
 
-int GDALContourItem::AddSegment( double dfXStart, double dfYStart, 
+int GDALContourItem::AddSegment( double dfXStart, double dfYStart,
                                  double dfXEnd, double dfYEnd,
                                  int bLeftHigh)
 
@@ -1163,7 +1174,7 @@ int GDALContourItem::AddSegment( double dfXStart, double dfYStart,
 /* -------------------------------------------------------------------- */
 /*      Try to matching up with one of the ends, and insert.            */
 /* -------------------------------------------------------------------- */
-    if( fabs(padfX[nPoints-1]-dfXStart) < JOIN_DIST 
+    if( fabs(padfX[nPoints-1]-dfXStart) < JOIN_DIST
              && fabs(padfY[nPoints-1]-dfYStart) < JOIN_DIST )
     {
         padfX[nPoints] = dfXEnd;
@@ -1176,7 +1187,7 @@ int GDALContourItem::AddSegment( double dfXStart, double dfYStart,
 
         return TRUE;
     }
-    else if( fabs(padfX[nPoints-1]-dfXEnd) < JOIN_DIST 
+    else if( fabs(padfX[nPoints-1]-dfXEnd) < JOIN_DIST
              && fabs(padfY[nPoints-1]-dfYEnd) < JOIN_DIST )
     {
         padfX[nPoints] = dfXStart;
@@ -1192,7 +1203,7 @@ int GDALContourItem::AddSegment( double dfXStart, double dfYStart,
     else
         return FALSE;
 }
- 
+
 /************************************************************************/
 /*                               Merge()                                */
 /************************************************************************/
@@ -1206,14 +1217,14 @@ int GDALContourItem::Merge( GDALContourItem *poOther )
 /* -------------------------------------------------------------------- */
 /*      Try to matching up with one of the ends, and insert.            */
 /* -------------------------------------------------------------------- */
-    if( fabs(padfX[nPoints-1]-poOther->padfX[0]) < JOIN_DIST 
+    if( fabs(padfX[nPoints-1]-poOther->padfX[0]) < JOIN_DIST
         && fabs(padfY[nPoints-1]-poOther->padfY[0]) < JOIN_DIST )
     {
         MakeRoomFor( nPoints + poOther->nPoints - 1 );
 
-        memcpy( padfX + nPoints, poOther->padfX + 1, 
+        memcpy( padfX + nPoints, poOther->padfX + 1,
                 sizeof(double) * (poOther->nPoints-1) );
-        memcpy( padfY + nPoints, poOther->padfY + 1, 
+        memcpy( padfY + nPoints, poOther->padfY + 1,
                 sizeof(double) * (poOther->nPoints-1) );
         nPoints += poOther->nPoints - 1;
 
@@ -1223,18 +1234,18 @@ int GDALContourItem::Merge( GDALContourItem *poOther )
 
         return TRUE;
     }
-    else if( fabs(padfX[0]-poOther->padfX[poOther->nPoints-1]) < JOIN_DIST 
+    else if( fabs(padfX[0]-poOther->padfX[poOther->nPoints-1]) < JOIN_DIST
              && fabs(padfY[0]-poOther->padfY[poOther->nPoints-1]) < JOIN_DIST )
     {
         MakeRoomFor( nPoints + poOther->nPoints - 1 );
 
-        memmove( padfX + poOther->nPoints - 1, padfX, 
+        memmove( padfX + poOther->nPoints - 1, padfX,
                 sizeof(double) * nPoints );
-        memmove( padfY + poOther->nPoints - 1, padfY, 
+        memmove( padfY + poOther->nPoints - 1, padfY,
                 sizeof(double) * nPoints );
-        memcpy( padfX, poOther->padfX, 
+        memcpy( padfX, poOther->padfX,
                 sizeof(double) * (poOther->nPoints-1) );
-        memcpy( padfY, poOther->padfY, 
+        memcpy( padfY, poOther->padfY,
                 sizeof(double) * (poOther->nPoints-1) );
         nPoints += poOther->nPoints - 1;
 
@@ -1244,7 +1255,7 @@ int GDALContourItem::Merge( GDALContourItem *poOther )
 
         return TRUE;
     }
-    else if( fabs(padfX[nPoints-1]-poOther->padfX[poOther->nPoints-1]) < JOIN_DIST 
+    else if( fabs(padfX[nPoints-1]-poOther->padfX[poOther->nPoints-1]) < JOIN_DIST
         && fabs(padfY[nPoints-1]-poOther->padfY[poOther->nPoints-1]) < JOIN_DIST )
     {
         int i;
@@ -1265,16 +1276,16 @@ int GDALContourItem::Merge( GDALContourItem *poOther )
 
         return TRUE;
     }
-    else if( fabs(padfX[0]-poOther->padfX[0]) < JOIN_DIST 
+    else if( fabs(padfX[0]-poOther->padfX[0]) < JOIN_DIST
         && fabs(padfY[0]-poOther->padfY[0]) < JOIN_DIST )
     {
         int i;
 
         MakeRoomFor( nPoints + poOther->nPoints - 1 );
 
-        memmove( padfX + poOther->nPoints - 1, padfX, 
+        memmove( padfX + poOther->nPoints - 1, padfX,
                 sizeof(double) * nPoints );
-        memmove( padfY + poOther->nPoints - 1, padfY, 
+        memmove( padfY + poOther->nPoints - 1, padfY,
                 sizeof(double) * nPoints );
 
         for( i = 0; i < poOther->nPoints-1; i++ )
@@ -1331,7 +1342,7 @@ void GDALContourItem::PrepareEjection()
             dfTemp = padfX[i];
             padfX[i] = padfX[ nPoints - i - 1];
             padfX[ nPoints - i - 1] = dfTemp;
-            
+
             dfTemp = padfY[i];
             padfY[i] = padfY[ nPoints - i - 1];
             padfY[ nPoints - i - 1] = dfTemp;
@@ -1350,8 +1361,8 @@ void GDALContourItem::PrepareEjection()
 /*                          OGRContourWriter()                          */
 /************************************************************************/
 
-CPLErr OGRContourWriter( double dfLevel, 
-                         int nPoints, double *padfX, double *padfY, 
+CPLErr OGRContourWriter( double dfLevel,
+                         int nPoints, double *padfX, double *padfY,
                          void *pInfo )
 
 {
@@ -1367,16 +1378,16 @@ CPLErr OGRContourWriter( double dfLevel,
 
     if( poInfo->nElevField != -1 )
         OGR_F_SetFieldDouble( hFeat, poInfo->nElevField, dfLevel );
-    
+
     hGeom = OGR_G_CreateGeometry( wkbLineString );
-    
+
     for( iPoint = nPoints-1; iPoint >= 0; iPoint-- )
     {
         OGR_G_SetPoint( hGeom, iPoint,
-                        poInfo->adfGeoTransform[0] 
+                        poInfo->adfGeoTransform[0]
                         + poInfo->adfGeoTransform[1] * padfX[iPoint]
                         + poInfo->adfGeoTransform[2] * padfY[iPoint],
-                        poInfo->adfGeoTransform[3] 
+                        poInfo->adfGeoTransform[3]
                         + poInfo->adfGeoTransform[4] * padfX[iPoint]
                         + poInfo->adfGeoTransform[5] * padfY[iPoint],
                         dfLevel );
@@ -1384,12 +1395,12 @@ CPLErr OGRContourWriter( double dfLevel,
 
     OGR_F_SetGeometryDirectly( hFeat, hGeom );
 
-    OGR_L_CreateFeature( (OGRLayerH) poInfo->hLayer, hFeat );
+    OGRErr eErr = OGR_L_CreateFeature( (OGRLayerH) poInfo->hLayer, hFeat );
     OGR_F_Destroy( hFeat );
 
-    return CE_None;
+    return (eErr == OGRERR_NONE) ? CE_None : CE_Failure;
 }
-#endif // OGR_ENABLED
+
 
 /************************************************************************/
 /*                        GDALContourGenerate()                         */
@@ -1408,22 +1419,22 @@ CPLErr OGRContourWriter( double dfLevel,
  *
  * ALGORITHM RULES
 
-For contouring purposes raster pixel values are assumed to represent a point 
-value at the center of the corresponding pixel region.  For the purpose of 
+For contouring purposes raster pixel values are assumed to represent a point
+value at the center of the corresponding pixel region.  For the purpose of
 contour generation we virtually connect each pixel center to the values to
 the left, right, top and bottom.  We assume that the pixel value is linearly
 interpolated between the pixel centers along each line, and determine where
-(if any) contour lines will appear along these line segements.  Then the
-contour crossings are connected.  
+(if any) contour lines will appear along these line segments.  Then the
+contour crossings are connected.
 
-This means that contour lines' nodes won't actually be on pixel edges, but 
-rather along vertical and horizontal lines connecting the pixel centers. 
+This means that contour lines' nodes will not actually be on pixel edges, but
+rather along vertical and horizontal lines connecting the pixel centers.
 
 \verbatim
 General Case:
 
       5 |                  | 3
-     -- + ---------------- + -- 
+     -- + ---------------- + --
         |                  |
         |                  |
         |                  |
@@ -1431,116 +1442,112 @@ General Case:
      10 +                  |
         |\                 |
         | \                |
-     -- + -+-------------- + -- 
+     -- + -+-------------- + --
      12 |  10              | 1
 
 
 Saddle Point:
 
       5 |                  | 12
-     -- + -------------+-- + -- 
+     -- + -------------+-- + --
         |               \  |
         |                 \|
-        |                  + 
+        |                  +
         |                  |
         +                  |
         |\                 |
         | \                |
-     -- + -+-------------- + -- 
+     -- + -+-------------- + --
      12 |                  | 1
 
 or:
 
       5 |                  | 12
-     -- + -------------+-- + -- 
+     -- + -------------+-- + --
         |          __/     |
         |      ___/        |
-        |  ___/          __+ 
+        |  ___/          __+
         | /           __/  |
         +'         __/     |
         |       __/        |
         |   ,__/           |
-     -- + -+-------------- + -- 
+     -- + -+-------------- + --
      12 |                  | 1
 \endverbatim
 
 Nodata:
 
-In the "nodata" case we treat the whole nodata pixel as a no-mans land. 
+In the "nodata" case we treat the whole nodata pixel as a no-mans land.
 We extend the corner pixels near the nodata out to half way and then
 construct extra lines from those points to the center which is assigned
-an averaged value from the two nearby points (in this case (12+3+5)/3). 
+an averaged value from the two nearby points (in this case (12+3+5)/3).
 
 \verbatim
       5 |                  | 3
-     -- + ---------------- + -- 
+     -- + ---------------- + --
         |                  |
         |                  |
         |      6.7         |
         |        +---------+ 3
-     10 +___     |          
-        |   \____+ 10       
-        |        |          
-     -- + -------+        +    
+     10 +___     |
+        |   \____+ 10
+        |        |
+     -- + -------+        +
      12 |       12           (nodata)
 
 \endverbatim
 
  *
- * @param hBand The band to read raster data from.  The whole band will be 
+ * @param hBand The band to read raster data from.  The whole band will be
  * processed.
  *
  * @param dfContourInterval The elevation interval between contours generated.
- * 
- * @param dfContourBase The "base" relative to which contour intervals are 
- * applied.  This is normally zero, but could be different.  To generate 10m 
+ *
+ * @param dfContourBase The "base" relative to which contour intervals are
+ * applied.  This is normally zero, but could be different.  To generate 10m
  * contours at 5, 15, 25, ... the ContourBase would be 5.
  *
  * @param  nFixedLevelCount The number of fixed levels. If this is greater than
- * zero, then fixed levels will be used, and ContourInterval and ContourBase 
+ * zero, then fixed levels will be used, and ContourInterval and ContourBase
  * are ignored.
  *
- * @param padfFixedLevels The list of fixed contour levels at which contours 
- * should be generated.  It will contain FixedLevelCount entries, and may be 
- * NULL if fixed levels are disabled (FixedLevelCount = 0). 
+ * @param padfFixedLevels The list of fixed contour levels at which contours
+ * should be generated.  It will contain FixedLevelCount entries, and may be
+ * NULL if fixed levels are disabled (FixedLevelCount = 0).
  *
  * @param bUseNoData If TRUE the dfNoDataValue will be used.
  *
  * @param dfNoDataValue The value to use as a "nodata" value. That is, a
  * pixel value which should be ignored in generating contours as if the value
- * of the pixel were not known. 
+ * of the pixel were not known.
  *
- * @param hLayer The layer to which new contour vectors will be written. 
+ * @param hLayer The layer to which new contour vectors will be written.
  * Each contour will have a LINESTRING geometry attached to it.   This
  * is really of type OGRLayerH, but void * is used to avoid pulling the
- * ogr_api.h file in here. 
+ * ogr_api.h file in here.
  *
  * @param iIDField If not -1 this will be used as a field index to indicate
  * where a unique id should be written for each feature (contour) written.
- * 
+ *
  * @param iElevField If not -1 this will be used as a field index to indicate
  * where the elevation value of the contour should be written.
  *
  * @param pfnProgress A GDALProgressFunc that may be used to report progress
  * to the user, or to interrupt the algorithm.  May be NULL if not required.
- * 
+ *
  * @param pProgressArg The callback data for the pfnProgress function.
  *
  * @return CE_None on success or CE_Failure if an error occurs.
  */
 
-CPLErr GDALContourGenerate( GDALRasterBandH hBand, 
+CPLErr GDALContourGenerate( GDALRasterBandH hBand,
                             double dfContourInterval, double dfContourBase,
                             int nFixedLevelCount, double *padfFixedLevels,
-                            int bUseNoData, double dfNoDataValue, 
+                            int bUseNoData, double dfNoDataValue,
                             void *hLayer, int iIDField, int iElevField,
                             GDALProgressFunc pfnProgress, void *pProgressArg )
 
 {
-#ifndef OGR_ENABLED
-    CPLError(CE_Failure, CPLE_NotSupported, "GDALContourGenerate() unimplemented in a non OGR build");
-    return CE_Failure;
-#else
     VALIDATE_POINTER1( hBand, "GDALContourGenerate", CE_Failure );
 
     OGRContourWriterInfo oCWI;
@@ -1582,6 +1589,10 @@ CPLErr GDALContourGenerate( GDALRasterBandH hBand,
     int nYSize = GDALGetRasterBandYSize( hBand );
 
     GDALContourGenerator oCG( nXSize, nYSize, OGRContourWriter, &oCWI );
+    if( !oCG.Init() )
+    {
+        return CE_Failure;
+    }
 
     if( nFixedLevelCount > 0 )
         oCG.SetFixedLevels( nFixedLevelCount, padfFixedLevels );
@@ -1598,21 +1609,20 @@ CPLErr GDALContourGenerate( GDALRasterBandH hBand,
     double *padfScanline;
     CPLErr eErr = CE_None;
 
-    padfScanline = (double *) VSIMalloc(sizeof(double) * nXSize);
+    padfScanline = (double *) VSI_MALLOC2_VERBOSE(sizeof(double), nXSize);
     if (padfScanline == NULL)
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory,
-                  "VSIMalloc(): Out of memory in GDALContourGenerate" );
         return CE_Failure;
     }
 
     for( iLine = 0; iLine < nYSize && eErr == CE_None; iLine++ )
     {
-        GDALRasterIO( hBand, GF_Read, 0, iLine, nXSize, 1, 
+        eErr = GDALRasterIO( hBand, GF_Read, 0, iLine, nXSize, 1,
                       padfScanline, nXSize, 1, GDT_Float64, 0, 0 );
-        eErr = oCG.FeedLine( padfScanline );
+        if( eErr == CE_None )
+            eErr = oCG.FeedLine( padfScanline );
 
-        if( eErr == CE_None 
+        if( eErr == CE_None
             && !pfnProgress( (iLine+1) / (double) nYSize, "", pProgressArg ) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
@@ -1623,5 +1633,4 @@ CPLErr GDALContourGenerate( GDALRasterBandH hBand,
     CPLFree( padfScanline );
 
     return eErr;
-#endif // OGR_ENABLED
 }
diff --git a/alg/delaunay.c b/alg/delaunay.c
new file mode 100644
index 0000000..1d6ba9e
--- /dev/null
+++ b/alg/delaunay.c
@@ -0,0 +1,581 @@
+/******************************************************************************
+ * $Id: delaunay.c 33715 2016-03-13 08:52:06Z goatbar $
+ *
+ * Project:  GDAL algorithms
+ * Purpose:  Delaunay triangulation
+ * Author:   Even Rouault, even.rouault at spatialys.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#if defined(__MINGW32__) || defined(__MINGW64__)
+/*  This avoids i586-mingw32msvc/include/direct.h from including libqhull/io.h ... */
+#define _DIRECT_H_
+/* For __MINGW64__ */
+#define _INC_DIRECT
+#define _INC_STAT
+#endif
+
+#if defined(INTERNAL_QHULL) && !defined(DONT_DEPRECATE_SPRINTF)
+#define DONT_DEPRECATE_SPRINTF
+#endif
+
+#include "cpl_error.h"
+#include "cpl_conv.h"
+#include "cpl_multiproc.h"
+#include "gdal_alg.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+
+CPL_CVSID("$Id: delaunay.c 33715 2016-03-13 08:52:06Z goatbar $");
+
+#if defined(INTERNAL_QHULL) || defined(EXTERNAL_QHULL)
+#define HAVE_INTERNAL_OR_EXTERNAL_QHULL 1
+#endif
+
+#if HAVE_INTERNAL_OR_EXTERNAL_QHULL
+#ifdef INTERNAL_QHULL
+
+#include "internal_qhull_headers.h"
+
+#else /* INTERNAL_QHULL */
+
+#include "libqhull.h"
+#include "qset.h"
+
+#endif /* INTERNAL_QHULL */
+
+#endif /* HAVE_INTERNAL_OR_EXTERNAL_QHULL*/
+
+
+#if HAVE_INTERNAL_OR_EXTERNAL_QHULL
+static CPLMutex* hMutex = NULL;
+#endif
+
+/************************************************************************/
+/*                       GDALHasTriangulation()                         */
+/************************************************************************/
+
+/** Returns if GDAL is built with Delaunay triangulation support.
+ *
+ * @return TRUE if GDAL is built with Delaunay triangulation support.
+ *
+ * @since GDAL 2.1
+ */
+int GDALHasTriangulation()
+{
+#if HAVE_INTERNAL_OR_EXTERNAL_QHULL
+    return TRUE;
+#else
+    return FALSE;
+#endif
+}
+
+/************************************************************************/
+/*                   GDALTriangulationCreateDelaunay()                  */
+/************************************************************************/
+
+/** Computes a Delaunay triangulation of the passed points
+ *
+ * @param nPoints number of points
+ * @param padfX x coordinates of the points.
+ * @param padfY y coordinates of the points.
+ * @return triangulation that must be freed with GDALTriangulationFree(), or
+ *         NULL in case of error.
+ *
+ * @since GDAL 2.1
+ */
+GDALTriangulation* GDALTriangulationCreateDelaunay(int nPoints,
+                                                   const double* padfX,
+                                                   const double* padfY)
+{
+#if HAVE_INTERNAL_OR_EXTERNAL_QHULL
+    coordT* points;
+    int i, j;
+    GDALTriangulation* psDT = NULL;
+    facetT *facet;
+    GDALTriFacet* pasFacets;
+    int* panMapQHFacetIdToFacetIdx; /* map from QHull facet ID to the index of our GDALTriFacet* array */
+    int curlong, totlong;     /* memory remaining after qh_memfreeshort */
+
+    /* QHull is not thread safe, so we need to protect all operations with a mutex */
+    CPLCreateOrAcquireMutex(&hMutex, 1000);
+
+#if qh_QHpointer  /* see user.h */
+    if (qh_qh)
+    {
+        fprintf (stderr, "QH6238: Qhull link error.  The global variable qh_qh was not initialized\n\
+                 to NULL by global.c.  Please compile this program with -Dqh_QHpointer_dllimport\n\
+                 as well as -Dqh_QHpointer, or use libqhullstatic, or use a different tool chain.\n\n");
+        CPLReleaseMutex(hMutex);
+        return NULL;
+    }
+#endif
+
+    points = (coordT*)VSI_MALLOC2_VERBOSE(sizeof(double)*2, nPoints);
+    if( points == NULL )
+    {
+        CPLReleaseMutex(hMutex);
+        return NULL;
+    }
+    for(i=0;i<nPoints;i++)
+    {
+        points[2*i] = padfX[i];
+        points[2*i+1] = padfY[i];
+    }
+
+    /* d: Delaunay */
+    /* Qbb: scale last coordinate to [0,m] for Delaunay */
+    /* Qc: keep coplanar points with nearest facet */
+    /* Qz: add a point-at-infinity for Delaunay triangulation */
+    /* Qt: triangulated output */
+    if( qh_new_qhull(2, nPoints, points, FALSE /* ismalloc */,
+                      "qhull d Qbb Qc Qz Qt", NULL, stderr) != 0 )
+    {
+        VSIFree(points);
+        CPLError(CE_Failure, CPLE_AppDefined, "Delaunay triangulation failed");
+        goto end;
+    }
+
+    VSIFree(points);
+    points = NULL;
+
+    /* Establish a map from QHull facet id to the index in our array of sequential facets */
+    panMapQHFacetIdToFacetIdx = (int*)VSI_MALLOC2_VERBOSE(sizeof(int), qh facet_id);
+    if( panMapQHFacetIdToFacetIdx == NULL )
+    {
+        goto end;
+    }
+    memset(panMapQHFacetIdToFacetIdx, 0xFF, sizeof(int) * qh facet_id);
+
+    for(j = 0, facet = qh facet_list;
+        facet != NULL && facet->next != NULL;
+        facet = facet->next)
+    {
+        if( facet->upperdelaunay != qh UPPERdelaunay )
+            continue;
+
+        if( qh_setsize(facet->vertices) != 3 ||
+            qh_setsize(facet->neighbors) != 3 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Triangulation resulted in non triangular facet %d: vertices=%d",
+                     facet->id, qh_setsize(facet->vertices));
+            VSIFree(panMapQHFacetIdToFacetIdx);
+            goto end;
+        }
+
+        CPLAssert(facet->id < qh facet_id);
+        panMapQHFacetIdToFacetIdx[facet->id] = j++;
+    }
+
+    pasFacets = (GDALTriFacet*) VSI_MALLOC2_VERBOSE( j, sizeof(GDALTriFacet) );
+    if(pasFacets == NULL )
+    {
+        VSIFree(panMapQHFacetIdToFacetIdx);
+        goto end;
+    }
+
+    psDT = (GDALTriangulation*)CPLCalloc(1, sizeof(GDALTriangulation));
+    psDT->nFacets = j;
+    psDT->pasFacets = pasFacets;
+
+    // Store vertex and neighbor information for each triangle.
+    for(facet = qh facet_list;
+        facet != NULL && facet->next != NULL;
+        facet = facet->next)
+    {
+        int k;
+        if( facet->upperdelaunay != qh UPPERdelaunay )
+            continue;
+        k = panMapQHFacetIdToFacetIdx[facet->id];
+        pasFacets[k].anVertexIdx[0] =
+            qh_pointid(((vertexT*) facet->vertices->e[0].p)->point);
+        pasFacets[k].anVertexIdx[1] =
+            qh_pointid(((vertexT*) facet->vertices->e[1].p)->point);
+        pasFacets[k].anVertexIdx[2] =
+            qh_pointid(((vertexT*) facet->vertices->e[2].p)->point);
+        pasFacets[k].anNeighborIdx[0] =
+            panMapQHFacetIdToFacetIdx[((facetT*) facet->neighbors->e[0].p)->id];
+        pasFacets[k].anNeighborIdx[1] =
+            panMapQHFacetIdToFacetIdx[((facetT*) facet->neighbors->e[1].p)->id];
+        pasFacets[k].anNeighborIdx[2] =
+            panMapQHFacetIdToFacetIdx[((facetT*) facet->neighbors->e[2].p)->id];
+    }
+
+    VSIFree(panMapQHFacetIdToFacetIdx);
+
+end:
+    qh_freeqhull(!qh_ALL);
+    qh_memfreeshort(&curlong, &totlong);
+
+    CPLReleaseMutex(hMutex);
+
+    return psDT;
+#else /* HAVE_INTERNAL_OR_EXTERNAL_QHULL */
+
+    /* Suppress unused argument warnings. */
+    (void)nPoints;
+    (void)padfX;
+    (void)padfY;
+
+    CPLError(CE_Failure, CPLE_NotSupported,
+             "GDALTriangulationCreateDelaunay() unavailable since GDAL built without QHull support");
+    return NULL;
+#endif /* HAVE_INTERNAL_OR_EXTERNAL_QHULL */
+}
+
+/************************************************************************/
+/*                       GDALTriangulationFree()                        */
+/************************************************************************/
+
+/** Free a triangulation.
+ *
+ * @param psDT triangulation.
+ * @since GDAL 2.1
+ */
+void GDALTriangulationFree(GDALTriangulation* psDT)
+{
+    if( psDT )
+    {
+        VSIFree(psDT->pasFacets);
+        VSIFree(psDT->pasFacetCoefficients);
+        VSIFree(psDT);
+    }
+}
+
+/************************************************************************/
+/*               GDALTriangulationComputeBarycentricCoefficients()      */
+/************************************************************************/
+
+/** Computes barycentric coefficients for each triangles of the triangulation.
+ *
+ * @param psDT triangulation.
+ * @param padfX x coordinates of the points. Must be identical to the one passed
+ *              to GDALTriangulationCreateDelaunay().
+ * @param padfY y coordinates of the points. Must be identical to the one passed
+ *              to GDALTriangulationCreateDelaunay().
+ *
+ * @return TRUE in case of success.
+ *
+ * @since GDAL 2.1
+ */
+int  GDALTriangulationComputeBarycentricCoefficients(GDALTriangulation* psDT,
+                                                     const double* padfX,
+                                                     const double* padfY)
+{
+    int i;
+
+    if( psDT->pasFacetCoefficients != NULL )
+    {
+        return TRUE;
+    }
+    psDT->pasFacetCoefficients = (GDALTriBarycentricCoefficients*)VSI_MALLOC2_VERBOSE(
+        sizeof(GDALTriBarycentricCoefficients), psDT->nFacets);
+    if( psDT->pasFacetCoefficients == NULL )
+    {
+        return FALSE;
+    }
+
+    for(i = 0; i < psDT->nFacets; i++)
+    {
+        GDALTriFacet* psFacet = &(psDT->pasFacets[i]);
+        GDALTriBarycentricCoefficients* psCoeffs = &(psDT->pasFacetCoefficients[i]);
+        double dfX1 = padfX[psFacet->anVertexIdx[0]];
+        double dfY1 = padfY[psFacet->anVertexIdx[0]];
+        double dfX2 = padfX[psFacet->anVertexIdx[1]];
+        double dfY2 = padfY[psFacet->anVertexIdx[1]];
+        double dfX3 = padfX[psFacet->anVertexIdx[2]];
+        double dfY3 = padfY[psFacet->anVertexIdx[2]];
+        /* See https://en.wikipedia.org/wiki/Barycentric_coordinate_system */
+        double dfDenom = (dfY2 - dfY3) * (dfX1 - dfX3) + (dfX3 - dfX2) * (dfY1 - dfY3);
+        psCoeffs->dfMul1X = (dfY2  - dfY3) / dfDenom;
+        psCoeffs->dfMul1Y = (dfX3  - dfX2) / dfDenom;
+        psCoeffs->dfMul2X = (dfY3  - dfY1) / dfDenom;
+        psCoeffs->dfMul2Y = (dfX1  - dfX3) / dfDenom;
+        psCoeffs->dfCstX = dfX3;
+        psCoeffs->dfCstY = dfY3;
+    }
+    return TRUE;
+}
+
+/************************************************************************/
+/*               GDALTriangulationComputeBarycentricCoordinates()       */
+/************************************************************************/
+
+/** Computes the barycentric coordinates of a point.
+ *
+ * @param psDT triangulation.
+ * @param nFacetIdx index of the triangle in the triangulation
+ * @param dfX x coordinate of the point.
+ * @param dfY y coordinate of the point.
+ * @param pdfL1 (output) pointer to the 1st barycentric coordinate.
+ * @param pdfL2 (output) pointer to the 2nd barycentric coordinate.
+ * @param pdfL3 (output) pointer to the 2nd barycentric coordinate.
+ *
+ * @return TRUE in case of success.
+ *
+ * @since GDAL 2.1
+ */
+
+#define BARYC_COORD_L1(psCoeffs, dfX, dfY) \
+        (psCoeffs->dfMul1X * ((dfX) - psCoeffs->dfCstX) + psCoeffs->dfMul1Y * ((dfY) - psCoeffs->dfCstY))
+#define BARYC_COORD_L2(psCoeffs, dfX, dfY) \
+        (psCoeffs->dfMul2X * ((dfX) - psCoeffs->dfCstX) + psCoeffs->dfMul2Y * ((dfY) - psCoeffs->dfCstY))
+#define BARYC_COORD_L3(l1, l2)  (1 - (l1) - (l2))
+
+int  GDALTriangulationComputeBarycentricCoordinates(const GDALTriangulation* psDT,
+                                                    int nFacetIdx,
+                                                    double dfX,
+                                                    double dfY,
+                                                    double* pdfL1,
+                                                    double* pdfL2,
+                                                    double* pdfL3)
+{
+    const GDALTriBarycentricCoefficients* psCoeffs;
+    if( psDT->pasFacetCoefficients == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "GDALTriangulationComputeBarycentricCoefficients() should be called before");
+        return FALSE;
+    }
+    CPLAssert(nFacetIdx >= 0 && nFacetIdx < psDT->nFacets);
+    psCoeffs = &(psDT->pasFacetCoefficients[nFacetIdx]);
+    *pdfL1 = BARYC_COORD_L1(psCoeffs, dfX, dfY);
+    *pdfL2 = BARYC_COORD_L2(psCoeffs, dfX, dfY);
+    *pdfL3 = BARYC_COORD_L3(*pdfL1, *pdfL2);
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*               GDALTriangulationFindFacetBruteForce()                 */
+/************************************************************************/
+
+#define EPS     1e-10
+
+/** Returns the index of the triangle that contains the point by iterating
+ * over all triangles.
+ *
+ * If the function returns FALSE and *panOutputFacetIdx >= 0, then it means
+ * the point is outside the hull of the triangulation, and *panOutputFacetIdx
+ * is the closest triangle to the point.
+ *
+ * @param psDT triangulation.
+ * @param dfX x coordinate of the point.
+ * @param dfY y coordinate of the point.
+ * @param panOutputFacetIdx (output) pointer to the index of the triangle.
+ *
+ * @return index >= 0 of the triangle in case of success, -1 otherwise.
+ *
+ * @since GDAL 2.1
+ */
+
+int GDALTriangulationFindFacetBruteForce(const GDALTriangulation* psDT,
+                                         double dfX,
+                                         double dfY,
+                                         int* panOutputFacetIdx)
+{
+    int nFacetIdx;
+    *panOutputFacetIdx = -1;
+    if( psDT->pasFacetCoefficients == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "GDALTriangulationComputeBarycentricCoefficients() should be called before");
+        return FALSE;
+    }
+    for(nFacetIdx=0;nFacetIdx<psDT->nFacets;nFacetIdx++)
+    {
+        double l1, l2, l3;
+        const GDALTriBarycentricCoefficients* psCoeffs =
+                                    &(psDT->pasFacetCoefficients[nFacetIdx]);
+        l1 = BARYC_COORD_L1(psCoeffs, dfX, dfY);
+        if( l1 < -EPS )
+        {
+            int neighbor = psDT->pasFacets[nFacetIdx].anNeighborIdx[0];
+            if( neighbor < 0 )
+            {
+                *panOutputFacetIdx = nFacetIdx;
+                return FALSE;
+            }
+            continue;
+        }
+        if( l1 > 1 + EPS )
+            continue;
+        l2 = BARYC_COORD_L2(psCoeffs, dfX, dfY);
+        if( l2 < -EPS )
+        {
+            int neighbor = psDT->pasFacets[nFacetIdx].anNeighborIdx[1];
+            if( neighbor < 0 )
+            {
+                *panOutputFacetIdx = nFacetIdx;
+                return FALSE;
+            }
+            continue;
+        }
+        if( l2 > 1 + EPS )
+            continue;
+        l3 = BARYC_COORD_L3(l1, l2);
+        if( l3 < -EPS )
+        {
+            int neighbor = psDT->pasFacets[nFacetIdx].anNeighborIdx[2];
+            if( neighbor < 0 )
+            {
+                *panOutputFacetIdx = nFacetIdx;
+                return FALSE;
+            }
+            continue;
+        }
+        if( l3 > 1 + EPS )
+            continue;
+        *panOutputFacetIdx = nFacetIdx;
+        return TRUE;
+    }
+    return FALSE;
+}
+
+/************************************************************************/
+/*               GDALTriangulationFindFacetDirected()                   */
+/************************************************************************/
+
+#define EPS     1e-10
+
+/** Returns the index of the triangle that contains the point by walking in
+ * the triangulation.
+ *
+ * If the function returns FALSE and *panOutputFacetIdx >= 0, then it means
+ * the point is outside the hull of the triangulation, and *panOutputFacetIdx
+ * is the closest triangle to the point.
+ *
+ * @param psDT triangulation.
+ * @param nFacetIdx index of first triangle to start with.
+ * @param dfX x coordinate of the point.
+ * @param dfY y coordinate of the point.
+ * @param panOutputFacetIdx (output) pointer to the index of the triangle.
+ *
+ * @return TRUE in case of success, -1 otherwise.
+ *
+ * @since GDAL 2.1
+ */
+
+int GDALTriangulationFindFacetDirected(const GDALTriangulation* psDT,
+                                       int nFacetIdx,
+                                       double dfX,
+                                       double dfY,
+                                       int* panOutputFacetIdx)
+{
+    int k, nIterMax;
+    *panOutputFacetIdx = -1;
+    if( psDT->pasFacetCoefficients == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "GDALTriangulationComputeBarycentricCoefficients() should be called before");
+        return FALSE;
+    }
+    CPLAssert(nFacetIdx >= 0 && nFacetIdx < psDT->nFacets);
+
+    nIterMax = 2 + psDT->nFacets / 4;
+    for(k=0;k<nIterMax;k++)
+    {
+        double l1, l2, l3;
+        int bMatch = TRUE;
+        const GDALTriFacet* psFacet = &(psDT->pasFacets[nFacetIdx]);
+        const GDALTriBarycentricCoefficients* psCoeffs =
+                                &(psDT->pasFacetCoefficients[nFacetIdx]);
+        l1 = BARYC_COORD_L1(psCoeffs, dfX, dfY);
+        if( l1 < -EPS )
+        {
+            int neighbor = psFacet->anNeighborIdx[0];
+            if( neighbor < 0 )
+            {
+                *panOutputFacetIdx = nFacetIdx;
+                return FALSE;
+            }
+            nFacetIdx = neighbor;
+            continue;
+        }
+        else if( l1 > 1 + EPS )
+            bMatch = FALSE; // outside or degenerate
+
+        l2 = BARYC_COORD_L2(psCoeffs, dfX, dfY);
+        if( l2 < -EPS )
+        {
+            int neighbor = psFacet->anNeighborIdx[1];
+            if( neighbor < 0 )
+            {
+                *panOutputFacetIdx = nFacetIdx;
+                return FALSE;
+            }
+            nFacetIdx = neighbor;
+            continue;
+        }
+        else if( l2 > 1 + EPS )
+            bMatch = FALSE; // outside or degenerate
+
+        l3 = BARYC_COORD_L3(l1, l2);
+        if( l3 < -EPS )
+        {
+            int neighbor = psFacet->anNeighborIdx[2];
+            if( neighbor < 0 )
+            {
+                *panOutputFacetIdx = nFacetIdx;
+                return FALSE;
+            }
+            nFacetIdx = neighbor;
+            continue;
+        }
+        else if( l3 > 1 + EPS )
+            bMatch = FALSE; // outside or degenerate
+
+        if( bMatch )
+        {
+            *panOutputFacetIdx = nFacetIdx;
+            return TRUE;
+        }
+        else
+        {
+            break;
+        }
+    }
+
+    CPLDebug("GDAL", "Using brute force lookup");
+    return GDALTriangulationFindFacetBruteForce(psDT, dfX, dfY, panOutputFacetIdx);
+}
+
+/************************************************************************/
+/*                         GDALTriangulationTerminate()                 */
+/************************************************************************/
+
+void GDALTriangulationTerminate()
+{
+#if HAVE_INTERNAL_OR_EXTERNAL_QHULL
+    if( hMutex != NULL )
+    {
+        CPLDestroyMutex(hMutex);
+        hMutex = NULL;
+    }
+#endif
+}
diff --git a/alg/fpolygonize.cpp b/alg/fpolygonize.cpp
deleted file mode 100644
index 5883fa8..0000000
--- a/alg/fpolygonize.cpp
+++ /dev/null
@@ -1,820 +0,0 @@
-/******************************************************************************
- * $Id: fpolygonize.cpp 22501 2011-06-04 21:28:47Z rouault $
- * 
- * Project:  GDAL
- * Purpose:  Version of Raster to Polygon Converter using float buffers.
- * Author:   Jorge Arevalo, jorge.arevalo at deimos-space.com. Most of the code
- * taken from GDALPolygonize.cpp, by Frank Warmerdam, warmerdam at pobox.com
- *
- ******************************************************************************
- * Copyright (c) 2011, Jorge Arevalo
- * Copyright (c) 2008, Frank Warmerdam
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "gdal_alg_priv.h"
-#include "cpl_conv.h"
-#include "cpl_string.h"
-#include <vector>
-
-CPL_CVSID("$Id: fpolygonize.cpp 22501 2011-06-04 21:28:47Z rouault $");
-
-#define GP_NODATA_MARKER -51502112
-
-#ifdef OGR_ENABLED
-
-/******************************************************************************/
-/*                          GDALFloatEquals()                                 */
-/* Code from:                                                                 */
-/* http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm  */
-/******************************************************************************/
-GBool GDALFloatEquals(float A, float B)
-{
-    /**
-     * This function will allow maxUlps-1 floats between A and B.
-     */
-    int maxUlps = MAX_ULPS;
-    int aInt, bInt;
-
-    /**
-     * Make sure maxUlps is non-negative and small enough that the default NAN
-     * won't compare as equal to anything.
-     */
-    CPLAssert(maxUlps > 0 && maxUlps < 4 * 1024 * 1024);
-
-    /**
-     * This assignation could violate strict aliasing. It causes a warning with
-     * gcc -O2. Use of memcpy preferred. Credits for Even Rouault. Further info
-     * at http://trac.osgeo.org/gdal/ticket/4005#comment:6
-     */
-    //int aInt = *(int*)&A;
-    memcpy(&aInt, &A, 4);
-
-    /**
-     * Make aInt lexicographically ordered as a twos-complement int
-     */
-    if (aInt < 0)
-        aInt = 0x80000000 - aInt;
-    /**
-     * Make bInt lexicographically ordered as a twos-complement int
-     */
-    //int bInt = *(int*)&B;
-    memcpy(&bInt, &B, 4);
-    
-    if (bInt < 0)
-        bInt = 0x80000000 - bInt;
-    int intDiff = abs(aInt - bInt);
-    if (intDiff <= maxUlps)
-        return true;
-    return false;
-}
-
-/************************************************************************/
-/* ==================================================================== */
-/*                               RPolygonF                              */
-/*									*/
-/*      This is a helper class to hold polygons while they are being    */
-/*      formed in memory, and to provide services to coalesce a much    */
-/*      of edge sections into complete rings.                           */
-/* ==================================================================== */
-/************************************************************************/
-
-class RPolygonF {
-public:
-    RPolygonF( float fValue ) { fPolyValue = fValue; nLastLineUpdated = -1; }
-
-    float            fPolyValue;
-    int              nLastLineUpdated;
-
-    std::vector< std::vector<int> > aanXY;
-
-    void             AddSegment( int x1, int y1, int x2, int y2 );
-    void             Dump();
-    void             Coalesce();
-    void             Merge( int iBaseString, int iSrcString, int iDirection );
-};
-
-/************************************************************************/
-/*                                Dump()                                */
-/************************************************************************/
-void RPolygonF::Dump()
-{
-    size_t iString;
-
-    printf( "RPolygonF: Value=%f, LastLineUpdated=%d\n",
-            fPolyValue, nLastLineUpdated );
-    
-    for( iString = 0; iString < aanXY.size(); iString++ )
-    {
-        std::vector<int> &anString = aanXY[iString];
-        size_t iVert;
-     
-        printf( "  String %d:\n", (int) iString );
-        for( iVert = 0; iVert < anString.size(); iVert += 2 )
-        {
-            printf( "    (%d,%d)\n", anString[iVert], anString[iVert+1] );
-        }
-    }
-}
-
-/************************************************************************/
-/*                              Coalesce()                              */
-/************************************************************************/
-
-void RPolygonF::Coalesce()
-
-{
-    size_t iBaseString;
-
-/* -------------------------------------------------------------------- */
-/*      Iterate over loops starting from the first, trying to merge     */
-/*      other segments into them.                                       */
-/* -------------------------------------------------------------------- */
-    for( iBaseString = 0; iBaseString < aanXY.size(); iBaseString++ )
-    {
-        std::vector<int> &anBase = aanXY[iBaseString];
-        int bMergeHappened = TRUE;
-
-/* -------------------------------------------------------------------- */
-/*      Keep trying to merge the following strings into our target      */
-/*      "base" string till we have tried them all once without any      */
-/*      mergers.                                                        */
-/* -------------------------------------------------------------------- */
-        while( bMergeHappened )
-        {
-            size_t iString;
-
-            bMergeHappened = FALSE;
-
-/* -------------------------------------------------------------------- */
-/*      Loop over the following strings, trying to find one we can      */
-/*      merge onto the end of our base string.                          */
-/* -------------------------------------------------------------------- */
-            for( iString = iBaseString+1; 
-                 iString < aanXY.size(); 
-                 iString++ )
-            {
-                std::vector<int> &anString = aanXY[iString];
-
-                if( anBase[anBase.size()-2] == anString[0]
-                    && anBase[anBase.size()-1] == anString[1] )
-                {
-                    Merge( iBaseString, iString, 1 );
-                    bMergeHappened = TRUE;
-                }
-                else if( anBase[anBase.size()-2] == anString[anString.size()-2]
-                         && anBase[anBase.size()-1] == anString[anString.size()-1] )
-                {
-                    Merge( iBaseString, iString, -1 );
-                    bMergeHappened = TRUE;
-                }
-            }
-        }
-
-        /* At this point our loop *should* be closed! */
-
-        CPLAssert( anBase[0] == anBase[anBase.size()-2]
-                   && anBase[1] == anBase[anBase.size()-1] );
-    }
-
-}
-
-/************************************************************************/
-/*                               Merge()                                */
-/************************************************************************/
-
-void RPolygonF::Merge( int iBaseString, int iSrcString, int iDirection )
-
-{
-    std::vector<int> &anBase = aanXY[iBaseString];
-    std::vector<int> &anString = aanXY[iSrcString];
-    int iStart, iEnd, i;
-
-    if( iDirection == 1 )
-    {
-        iStart = 1;
-        iEnd = anString.size() / 2; 
-    }
-    else
-    {
-        iStart = anString.size() / 2 - 2;
-        iEnd = -1; 
-    }
-    
-    for( i = iStart; i != iEnd; i += iDirection )
-    {
-        anBase.push_back( anString[i*2+0] );
-        anBase.push_back( anString[i*2+1] );
-    }
-    
-    if( iSrcString < ((int) aanXY.size())-1 )
-        aanXY[iSrcString] = aanXY[aanXY.size()-1];
-
-    size_t nSize = aanXY.size(); 
-    aanXY.resize(nSize-1);
-}
-
-/************************************************************************/
-/*                             AddSegment()                             */
-/************************************************************************/
-
-void RPolygonF::AddSegment( int x1, int y1, int x2, int y2 )
-
-{
-    nLastLineUpdated = MAX(y1, y2);
-
-/* -------------------------------------------------------------------- */
-/*      Is there an existing string ending with this?                   */
-/* -------------------------------------------------------------------- */
-    size_t iString;
-
-    for( iString = 0; iString < aanXY.size(); iString++ )
-    {
-        std::vector<int> &anString = aanXY[iString];
-        size_t nSSize = anString.size();
-        
-        if( anString[nSSize-2] == x1 
-            && anString[nSSize-1] == y1 )
-        {
-            int nTemp;
-
-            nTemp = x2;
-            x2 = x1;
-            x1 = nTemp;
-
-            nTemp = y2;
-            y2 = y1;
-            y1 = nTemp;
-        }
-
-        if( anString[nSSize-2] == x2 
-            && anString[nSSize-1] == y2 )
-        {
-            // We are going to add a segment, but should we just extend 
-            // an existing segment already going in the right direction?
-
-            int nLastLen = MAX(ABS(anString[nSSize-4]-anString[nSSize-2]),
-                               ABS(anString[nSSize-3]-anString[nSSize-1]));
-            
-            if( nSSize >= 4 
-                && (anString[nSSize-4] - anString[nSSize-2]
-                    == (anString[nSSize-2] - x1)*nLastLen)
-                && (anString[nSSize-3] - anString[nSSize-1]
-                    == (anString[nSSize-1] - y1)*nLastLen) )
-            {
-                anString.pop_back();
-                anString.pop_back();
-            }
-
-            anString.push_back( x1 );
-            anString.push_back( y1 );
-            return;
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Create a new string.                                            */
-/* -------------------------------------------------------------------- */
-    size_t nSize = aanXY.size();
-    aanXY.resize(nSize + 1);
-    std::vector<int> &anString = aanXY[nSize];
-
-    anString.push_back( x1 );
-    anString.push_back( y1 );
-    anString.push_back( x2 );
-    anString.push_back( y2 );
-
-    return;
-}
-
-/************************************************************************/
-/* ==================================================================== */
-/*     End of RPolygonF                                                  */
-/* ==================================================================== */
-/************************************************************************/
-
-/************************************************************************/
-/*                              AddEdges()                              */
-/*                                                                      */
-/*      Examine one pixel and compare to its neighbour above            */
-/*      (previous) and right.  If they are different polygon ids        */
-/*      then add the pixel edge to this polygon and the one on the      */
-/*      other side of the edge.                                         */
-/************************************************************************/
-
-static void AddEdges( GInt32 *panThisLineId, GInt32 *panLastLineId, 
-                      GInt32 *panPolyIdMap, float *pafPolyValue,
-                      RPolygonF **papoPoly, int iX, int iY )
-
-{
-    int nThisId = panThisLineId[iX];
-    int nRightId = panThisLineId[iX+1];
-    int nPreviousId = panLastLineId[iX];
-    int iXReal = iX - 1;
-
-    if( nThisId != -1 )
-        nThisId = panPolyIdMap[nThisId];
-    if( nRightId != -1 )
-        nRightId = panPolyIdMap[nRightId];
-    if( nPreviousId != -1 )
-        nPreviousId = panPolyIdMap[nPreviousId];
-
-    if( nThisId != nPreviousId )
-    {
-        if( nThisId != -1 )
-        {
-            if( papoPoly[nThisId] == NULL )
-                papoPoly[nThisId] = new RPolygonF( pafPolyValue[nThisId] );
-
-            papoPoly[nThisId]->AddSegment( iXReal, iY, iXReal+1, iY );
-        }
-        if( nPreviousId != -1 )
-        {
-            if( papoPoly[nPreviousId] == NULL )
-                papoPoly[nPreviousId] = new RPolygonF(pafPolyValue[nPreviousId]);
-
-            papoPoly[nPreviousId]->AddSegment( iXReal, iY, iXReal+1, iY );
-        }
-    }
-
-    if( nThisId != nRightId )
-    {
-        if( nThisId != -1 )
-        {
-            if( papoPoly[nThisId] == NULL )
-                papoPoly[nThisId] = new RPolygonF(pafPolyValue[nThisId]);
-
-            papoPoly[nThisId]->AddSegment( iXReal+1, iY, iXReal+1, iY+1 );
-        }
-
-        if( nRightId != -1 )
-        {
-            if( papoPoly[nRightId] == NULL )
-                papoPoly[nRightId] = new RPolygonF(pafPolyValue[nRightId]);
-
-            papoPoly[nRightId]->AddSegment( iXReal+1, iY, iXReal+1, iY+1 );
-        }
-    }
-}
-
-/************************************************************************/
-/*                         EmitPolygonToLayer()                         */
-/************************************************************************/
-
-static CPLErr
-EmitPolygonToLayer( OGRLayerH hOutLayer, int iPixValField,
-                    RPolygonF *poRPoly, double *padfGeoTransform )
-
-{
-    OGRFeatureH hFeat;
-    OGRGeometryH hPolygon;
-
-/* -------------------------------------------------------------------- */
-/*      Turn bits of lines into coherent rings.                         */
-/* -------------------------------------------------------------------- */
-    poRPoly->Coalesce();
-
-/* -------------------------------------------------------------------- */
-/*      Create the polygon geometry.                                    */
-/* -------------------------------------------------------------------- */
-    size_t iString;
-
-    hPolygon = OGR_G_CreateGeometry( wkbPolygon );
-    
-    for( iString = 0; iString < poRPoly->aanXY.size(); iString++ )
-    {
-        std::vector<int> &anString = poRPoly->aanXY[iString];
-        OGRGeometryH hRing = OGR_G_CreateGeometry( wkbLinearRing );
-
-        int iVert;
-
-        // we go last to first to ensure the linestring is allocated to 
-        // the proper size on the first try.
-        for( iVert = anString.size()/2 - 1; iVert >= 0; iVert-- )
-        {
-            double dfX, dfY;
-            int    nPixelX, nPixelY;
-            
-            nPixelX = anString[iVert*2];
-            nPixelY = anString[iVert*2+1];
-
-            dfX = padfGeoTransform[0] 
-                + nPixelX * padfGeoTransform[1]
-                + nPixelY * padfGeoTransform[2];
-            dfY = padfGeoTransform[3] 
-                + nPixelX * padfGeoTransform[4]
-                + nPixelY * padfGeoTransform[5];
-
-            OGR_G_SetPoint_2D( hRing, iVert, dfX, dfY );
-        }
-
-        OGR_G_AddGeometryDirectly( hPolygon, hRing );
-    }
-    
-/* -------------------------------------------------------------------- */
-/*      Create the feature object.                                      */
-/* -------------------------------------------------------------------- */
-    hFeat = OGR_F_Create( OGR_L_GetLayerDefn( hOutLayer ) );
-
-    OGR_F_SetGeometryDirectly( hFeat, hPolygon );
-
-    if( iPixValField >= 0 )
-        OGR_F_SetFieldDouble( hFeat, iPixValField, (double)poRPoly->fPolyValue );
-
-/* -------------------------------------------------------------------- */
-/*      Write the to the layer.                                         */
-/* -------------------------------------------------------------------- */
-    CPLErr eErr = CE_None;
-
-    if( OGR_L_CreateFeature( hOutLayer, hFeat ) != OGRERR_NONE )
-        eErr = CE_Failure;
-
-    OGR_F_Destroy( hFeat );
-
-    return eErr;
-}
-
-/************************************************************************/
-/*                          GPMaskImageData()                           */
-/*                                                                      */
-/*      Mask out image pixels to a special nodata value if the mask     */
-/*      band is zero.                                                   */
-/************************************************************************/
-
-static CPLErr 
-GPMaskImageData( GDALRasterBandH hMaskBand, GByte* pabyMaskLine, int iY, int nXSize, 
-                 float *pafImageLine )
-
-{
-    CPLErr eErr;
-
-    eErr = GDALRasterIO( hMaskBand, GF_Read, 0, iY, nXSize, 1, 
-                         pabyMaskLine, nXSize, 1, GDT_Byte, 0, 0 );
-    if( eErr == CE_None )
-    {
-        int i;
-        for( i = 0; i < nXSize; i++ )
-        {
-            if( pabyMaskLine[i] == 0 )
-                pafImageLine[i] = GP_NODATA_MARKER;
-        }
-    }
-
-    return eErr;
-}
-#endif // OGR_ENABLED
-
-/************************************************************************/
-/*                           GDALFPolygonize()                           */
-/************************************************************************/
-
-/**
- * Create polygon coverage from raster data.
- *
- * This function creates vector polygons for all connected regions of pixels in
- * the raster sharing a common pixel value.  Optionally each polygon may be
- * labelled with the pixel value in an attribute.  Optionally a mask band
- * can be provided to determine which pixels are eligible for processing.
- *
- * The source pixel band values are read into a 32bit float buffer. If you want
- * to use a (probably faster) version using signed 32bit integer buffer, see
- * GDALPolygonize() at polygonize.cpp.
- *
- * Polygon features will be created on the output layer, with polygon 
- * geometries representing the polygons.  The polygon geometries will be
- * in the georeferenced coordinate system of the image (based on the
- * geotransform of the source dataset).  It is acceptable for the output
- * layer to already have features.  Note that GDALFPolygonize() does not
- * set the coordinate system on the output layer.  Application code should
- * do this when the layer is created, presumably matching the raster 
- * coordinate system. 
- *
- * The algorithm used attempts to minimize memory use so that very large
- * rasters can be processed.  However, if the raster has many polygons 
- * or very large/complex polygons, the memory use for holding polygon 
- * enumerations and active polygon geometries may grow to be quite large. 
- *
- * The algorithm will generally produce very dense polygon geometries, with
- * edges that follow exactly on pixel boundaries for all non-interior pixels.
- * For non-thematic raster data (such as satellite images) the result will
- * essentially be one small polygon per pixel, and memory and output layer
- * sizes will be substantial.  The algorithm is primarily intended for 
- * relatively simple thematic imagery, masks, and classification results. 
- * 
- * @param hSrcBand the source raster band to be processed.
- * @param hMaskBand an optional mask band.  All pixels in the mask band with a 
- * value other than zero will be considered suitable for collection as 
- * polygons.  
- * @param hOutLayer the vector feature layer to which the polygons should
- * be written. 
- * @param iPixValField the attribute field index indicating the feature
- * attribute into which the pixel value of the polygon should be written.
- * @param papszOptions a name/value list of additional options
- * <dl>
- * <dt>"8CONNECTED":</dt> May be set to "8" to use 8 connectedness.
- * Otherwise 4 connectedness will be applied to the algorithm
- * </dl>
- * @param pfnProgress callback for reporting algorithm progress matching the
- * GDALProgressFunc() semantics.  May be NULL.
- * @param pProgressArg callback argument passed to pfnProgress.
- * 
- * @return CE_None on success or CE_Failure on a failure.
- *
- * @since GDAL 1.9.0
- */
-
-CPLErr CPL_STDCALL
-GDALFPolygonize( GDALRasterBandH hSrcBand,
-                GDALRasterBandH hMaskBand,
-                OGRLayerH hOutLayer, int iPixValField, 
-                char **papszOptions,
-                GDALProgressFunc pfnProgress, 
-                void * pProgressArg )
-
-{
-#ifndef OGR_ENABLED
-    CPLError(CE_Failure, CPLE_NotSupported, "GDALFPolygonize() unimplemented in a non OGR build");
-    return CE_Failure;
-#else
-    VALIDATE_POINTER1( hSrcBand, "GDALFPolygonize", CE_Failure );
-    VALIDATE_POINTER1( hOutLayer, "GDALFPolygonize", CE_Failure );
-
-    if( pfnProgress == NULL )
-        pfnProgress = GDALDummyProgress;
-
-    int nConnectedness = CSLFetchNameValue( papszOptions, "8CONNECTED" ) ? 8 : 4;
-
-/* -------------------------------------------------------------------- */
-/*      Confirm our output layer will support feature creation.         */
-/* -------------------------------------------------------------------- */
-    if( !OGR_L_TestCapability( hOutLayer, OLCSequentialWrite ) )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Output feature layer does not appear to support creation\n"
-                  "of features in GDALFPolygonize()." );
-        return CE_Failure;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Allocate working buffers.                                       */
-/* -------------------------------------------------------------------- */
-    CPLErr eErr = CE_None;
-    int nXSize = GDALGetRasterBandXSize( hSrcBand );
-    int nYSize = GDALGetRasterBandYSize( hSrcBand );
-    float *pafLastLineVal = (float *) VSIMalloc2(sizeof(float),nXSize + 2);
-    float *pafThisLineVal = (float *) VSIMalloc2(sizeof(float),nXSize + 2);
-    GInt32 *panLastLineId =  (GInt32 *) VSIMalloc2(sizeof(GInt32),nXSize + 2);
-    GInt32 *panThisLineId =  (GInt32 *) VSIMalloc2(sizeof(GInt32),nXSize + 2);
-    GByte *pabyMaskLine = (hMaskBand != NULL) ? (GByte *) VSIMalloc(nXSize) : NULL;
-    if (pafLastLineVal == NULL || pafThisLineVal == NULL ||
-        panLastLineId == NULL || panThisLineId == NULL ||
-        (hMaskBand != NULL && pabyMaskLine == NULL))
-    {
-        CPLError(CE_Failure, CPLE_OutOfMemory,
-                 "Could not allocate enough memory for temporary buffers");
-        CPLFree( panThisLineId );
-        CPLFree( panLastLineId );
-        CPLFree( pafThisLineVal );
-        CPLFree( pafLastLineVal );
-        CPLFree( pabyMaskLine );
-        return CE_Failure;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Get the geotransform, if there is one, so we can convert the    */
-/*      vectors into georeferenced coordinates.                         */
-/* -------------------------------------------------------------------- */
-    GDALDatasetH hSrcDS = GDALGetBandDataset( hSrcBand );
-    double adfGeoTransform[6] = { 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 };
-
-    if( hSrcDS )
-        GDALGetGeoTransform( hSrcDS, adfGeoTransform );
-
-/* -------------------------------------------------------------------- */
-/*      The first pass over the raster is only used to build up the     */
-/*      polygon id map so we will know in advance what polygons are     */
-/*      what on the second pass.                                        */
-/* -------------------------------------------------------------------- */
-    int iY;
-    GDALRasterFPolygonEnumerator oFirstEnum(nConnectedness);
-
-    for( iY = 0; eErr == CE_None && iY < nYSize; iY++ )
-    {
-        eErr = GDALRasterIO( 
-            hSrcBand,
-            GF_Read, 0, iY, nXSize, 1, 
-            pafThisLineVal, nXSize, 1, GDT_Float32, 0, 0 );
-        
-        if( eErr == CE_None && hMaskBand != NULL )
-            eErr = GPMaskImageData( hMaskBand, pabyMaskLine, iY, nXSize,
-                    pafThisLineVal );
-
-        if( iY == 0 )
-            oFirstEnum.ProcessLine( 
-                NULL, pafThisLineVal, NULL, panThisLineId, nXSize );
-        else
-            oFirstEnum.ProcessLine(
-                pafLastLineVal, pafThisLineVal,
-                panLastLineId,  panThisLineId, 
-                nXSize );
-
-        // swap lines
-        float * pafTmp = pafLastLineVal;
-        pafLastLineVal = pafThisLineVal;
-        pafThisLineVal = pafTmp;
-
-        GInt32 * panTmp = panThisLineId;
-        panThisLineId = panLastLineId;
-        panLastLineId = panTmp;
-
-/* -------------------------------------------------------------------- */
-/*      Report progress, and support interrupts.                        */
-/* -------------------------------------------------------------------- */
-        if( eErr == CE_None 
-            && !pfnProgress( 0.10 * ((iY+1) / (double) nYSize), 
-                             "", pProgressArg ) )
-        {
-            CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
-            eErr = CE_Failure;
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Make a pass through the maps, ensuring every polygon id         */
-/*      points to the final id it should use, not an intermediate       */
-/*      value.                                                          */
-/* -------------------------------------------------------------------- */
-    oFirstEnum.CompleteMerges();
-
-/* -------------------------------------------------------------------- */
-/*      Initialize ids to -1 to serve as a nodata value for the         */
-/*      previous line, and past the beginning and end of the            */
-/*      scanlines.                                                      */
-/* -------------------------------------------------------------------- */
-    int iX;
-
-    panThisLineId[0] = -1;
-    panThisLineId[nXSize+1] = -1;
-
-    for( iX = 0; iX < nXSize+2; iX++ )
-        panLastLineId[iX] = -1;
-
-/* -------------------------------------------------------------------- */
-/*      We will use a new enumerator for the second pass primariliy     */
-/*      so we can preserve the first pass map.                          */
-/* -------------------------------------------------------------------- */
-    GDALRasterFPolygonEnumerator oSecondEnum(nConnectedness);
-    RPolygonF **papoPoly = (RPolygonF **)
-        CPLCalloc(sizeof(RPolygonF*),oFirstEnum.nNextPolygonId);
-
-/* ==================================================================== */
-/*      Second pass during which we will actually collect polygon       */
-/*      edges as geometries.                                            */
-/* ==================================================================== */
-    for( iY = 0; eErr == CE_None && iY < nYSize+1; iY++ )
-    {
-/* -------------------------------------------------------------------- */
-/*      Read the image data.                                            */
-/* -------------------------------------------------------------------- */
-        if( iY < nYSize )
-        {
-            eErr = GDALRasterIO( hSrcBand, GF_Read, 0, iY, nXSize, 1, 
-                                 pafThisLineVal, nXSize, 1, GDT_Float32, 0, 0 );
-
-            if( eErr == CE_None && hMaskBand != NULL )
-                eErr = GPMaskImageData( hMaskBand, pabyMaskLine, iY, nXSize,
-                        pafThisLineVal );
-        }
-
-        if( eErr != CE_None )
-            continue;
-
-/* -------------------------------------------------------------------- */
-/*      Determine what polygon the various pixels belong to (redoing    */
-/*      the same thing done in the first pass above).                   */
-/* -------------------------------------------------------------------- */
-        if( iY == nYSize )
-        {
-            for( iX = 0; iX < nXSize+2; iX++ )
-                panThisLineId[iX] = -1;
-        }
-        else if( iY == 0 )
-            oSecondEnum.ProcessLine( 
-                NULL, pafThisLineVal, NULL, panThisLineId+1, nXSize );
-        else
-            oSecondEnum.ProcessLine(
-                pafLastLineVal, pafThisLineVal,
-                panLastLineId+1,  panThisLineId+1, 
-                nXSize );
-
-/* -------------------------------------------------------------------- */
-/*      Add polygon edges to our polygon list for the pixel             */
-/*      boundaries within and above this line.                          */
-/* -------------------------------------------------------------------- */
-        for( iX = 0; iX < nXSize+1; iX++ )
-        {
-            AddEdges( panThisLineId, panLastLineId, 
-                      oFirstEnum.panPolyIdMap, oFirstEnum.pafPolyValue,
-                      papoPoly, iX, iY );
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Periodically we scan out polygons and write out those that      */
-/*      haven't been added to on the last line as we can be sure        */
-/*      they are complete.                                              */
-/* -------------------------------------------------------------------- */
-        if( iY % 8 == 7 )
-        {
-            for( iX = 0; 
-                 eErr == CE_None && iX < oSecondEnum.nNextPolygonId; 
-                 iX++ )
-            {
-                if( papoPoly[iX] && papoPoly[iX]->nLastLineUpdated < iY-1 )
-                {
-                    if( hMaskBand == NULL
-                        || !GDALFloatEquals(papoPoly[iX]->fPolyValue, GP_NODATA_MARKER) )
-                    {
-                        eErr = 
-                            EmitPolygonToLayer( hOutLayer, iPixValField, 
-                                                papoPoly[iX], adfGeoTransform );
-                    }
-                    delete papoPoly[iX];
-                    papoPoly[iX] = NULL;
-                }
-            }
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Swap pixel value, and polygon id lines to be ready for the      */
-/*      next line.                                                      */
-/* -------------------------------------------------------------------- */
-        float *pafTmp = pafLastLineVal;
-        pafLastLineVal = pafThisLineVal;
-        pafThisLineVal = pafTmp;
-
-        GInt32 *panTmp = panThisLineId;
-        panThisLineId = panLastLineId;
-        panLastLineId = panTmp;
-
-/* -------------------------------------------------------------------- */
-/*      Report progress, and support interrupts.                        */
-/* -------------------------------------------------------------------- */
-        if( eErr == CE_None 
-            && !pfnProgress( 0.10 + 0.90 * ((iY+1) / (double) nYSize), 
-                             "", pProgressArg ) )
-        {
-            CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
-            eErr = CE_Failure;
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Make a cleanup pass for all unflushed polygons.                 */
-/* -------------------------------------------------------------------- */
-    for( iX = 0; eErr == CE_None && iX < oSecondEnum.nNextPolygonId; iX++ )
-    {
-        if( papoPoly[iX] )
-        {
-            if( hMaskBand == NULL
-                || !GDALFloatEquals(papoPoly[iX]->fPolyValue, GP_NODATA_MARKER) )
-            {
-                eErr = 
-                    EmitPolygonToLayer( hOutLayer, iPixValField, 
-                                        papoPoly[iX], adfGeoTransform );
-            }
-            delete papoPoly[iX];
-            papoPoly[iX] = NULL;
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Cleanup                                                         */
-/* -------------------------------------------------------------------- */
-    CPLFree( panThisLineId );
-    CPLFree( panLastLineId );
-    CPLFree( pafThisLineVal );
-    CPLFree( pafLastLineVal );
-    CPLFree( pabyMaskLine );
-    CPLFree( papoPoly );
-
-    return eErr;
-#endif // OGR_ENABLED
-}
-
diff --git a/alg/gdal_alg.h b/alg/gdal_alg.h
index b4734fb..0235012 100644
--- a/alg/gdal_alg.h
+++ b/alg/gdal_alg.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_alg.h 27850 2014-10-12 16:58:09Z rouault $
+ * $Id: gdal_alg.h 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  GDAL Image Processing Algorithms
  * Purpose:  Prototypes, and definitions for various GDAL based algorithms.
@@ -45,49 +45,49 @@
 
 CPL_C_START
 
-int CPL_DLL CPL_STDCALL GDALComputeMedianCutPCT( GDALRasterBandH hRed, 
-                             GDALRasterBandH hGreen, 
-                             GDALRasterBandH hBlue, 
+int CPL_DLL CPL_STDCALL GDALComputeMedianCutPCT( GDALRasterBandH hRed,
+                             GDALRasterBandH hGreen,
+                             GDALRasterBandH hBlue,
                              int (*pfnIncludePixel)(int,int,void*),
-                             int nColors, 
+                             int nColors,
                              GDALColorTableH hColorTable,
-                             GDALProgressFunc pfnProgress, 
+                             GDALProgressFunc pfnProgress,
                              void * pProgressArg );
 
-int CPL_DLL CPL_STDCALL GDALDitherRGB2PCT( GDALRasterBandH hRed, 
-                       GDALRasterBandH hGreen, 
-                       GDALRasterBandH hBlue, 
-                       GDALRasterBandH hTarget, 
-                       GDALColorTableH hColorTable, 
-                       GDALProgressFunc pfnProgress, 
+int CPL_DLL CPL_STDCALL GDALDitherRGB2PCT( GDALRasterBandH hRed,
+                       GDALRasterBandH hGreen,
+                       GDALRasterBandH hBlue,
+                       GDALRasterBandH hTarget,
+                       GDALColorTableH hColorTable,
+                       GDALProgressFunc pfnProgress,
                        void * pProgressArg );
 
-int CPL_DLL CPL_STDCALL GDALChecksumImage( GDALRasterBandH hBand, 
+int CPL_DLL CPL_STDCALL GDALChecksumImage( GDALRasterBandH hBand,
                                int nXOff, int nYOff, int nXSize, int nYSize );
-                               
-CPLErr CPL_DLL CPL_STDCALL 
-GDALComputeProximity( GDALRasterBandH hSrcBand, 
+
+CPLErr CPL_DLL CPL_STDCALL
+GDALComputeProximity( GDALRasterBandH hSrcBand,
                       GDALRasterBandH hProximityBand,
                       char **papszOptions,
-                      GDALProgressFunc pfnProgress, 
+                      GDALProgressFunc pfnProgress,
                       void * pProgressArg );
 
 CPLErr CPL_DLL CPL_STDCALL
-GDALFillNodata( GDALRasterBandH hTargetBand, 
+GDALFillNodata( GDALRasterBandH hTargetBand,
                 GDALRasterBandH hMaskBand,
-                double dfMaxSearchDist, 
+                double dfMaxSearchDist,
                 int bDeprecatedOption,
                 int nSmoothingIterations,
                 char **papszOptions,
-                GDALProgressFunc pfnProgress, 
+                GDALProgressFunc pfnProgress,
                 void * pProgressArg );
 
 CPLErr CPL_DLL CPL_STDCALL
-GDALPolygonize( GDALRasterBandH hSrcBand, 
+GDALPolygonize( GDALRasterBandH hSrcBand,
                 GDALRasterBandH hMaskBand,
-                OGRLayerH hOutLayer, int iPixValField, 
+                OGRLayerH hOutLayer, int iPixValField,
                 char **papszOptions,
-                GDALProgressFunc pfnProgress, 
+                GDALProgressFunc pfnProgress,
                 void * pProgressArg );
 
 CPLErr CPL_DLL CPL_STDCALL
@@ -103,16 +103,16 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
                  GDALRasterBandH hDstBand,
                  int nSizeThreshold, int nConnectedness,
                  char **papszOptions,
-                 GDALProgressFunc pfnProgress, 
+                 GDALProgressFunc pfnProgress,
                  void * pProgressArg );
 
 /*
  * Warp Related.
  */
 
-typedef int 
-(*GDALTransformerFunc)( void *pTransformerArg, 
-                        int bDstToSrc, int nPointCount, 
+typedef int
+(*GDALTransformerFunc)( void *pTransformerArg,
+                        int bDstToSrc, int nPointCount,
                         double *x, double *y, double *z, int *panSuccess );
 
 #define GDAL_GTI2_SIGNATURE     "GTI2"
@@ -127,15 +127,15 @@ typedef struct {
 } GDALTransformerInfo;
 
 void CPL_DLL GDALDestroyTransformer( void *pTransformerArg );
-int  CPL_DLL GDALUseTransformer( void *pTranformerArg, 
-                                 int bDstToSrc, int nPointCount, 
-                                 double *x, double *y, double *z, 
+int  CPL_DLL GDALUseTransformer( void *pTransformerArg,
+                                 int bDstToSrc, int nPointCount,
+                                 double *x, double *y, double *z,
                                  int *panSuccess );
 void* GDALCreateSimilarTransformer( void* psTransformerArg, double dfSrcRatioX, double dfSrcRatioY );
 
 
 /* High level transformer for going from image coordinates on one file
-   to image coordiantes on another, potentially doing reprojection, 
+   to image coordinates on another, potentially doing reprojection,
    utilizing GCPs or using the geotransform. */
 
 void CPL_DLL *
@@ -144,17 +144,17 @@ GDALCreateGenImgProjTransformer( GDALDatasetH hSrcDS, const char *pszSrcWKT,
                                  int bGCPUseOK, double dfGCPErrorThreshold,
                                  int nOrder );
 void CPL_DLL *
-GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS, 
+GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
                                   char **papszOptions );
 void CPL_DLL *
 GDALCreateGenImgProjTransformer3( const char *pszSrcWKT,
                                   const double *padfSrcGeoTransform,
                                   const char *pszDstWKT,
                                   const double *padfDstGeoTransform );
-void CPL_DLL GDALSetGenImgProjTransformerDstGeoTransform( void *, 
+void CPL_DLL GDALSetGenImgProjTransformerDstGeoTransform( void *,
                                                           const double * );
 void CPL_DLL GDALDestroyGenImgProjTransformer( void * );
-int CPL_DLL GDALGenImgProjTransform( 
+int CPL_DLL GDALGenImgProjTransform(
     void *pTransformArg, int bDstToSrc, int nPointCount,
     double *x, double *y, double *z, int *panSuccess );
 
@@ -162,35 +162,35 @@ void GDALSetTransformerDstGeoTransform( void *, const double * );
 
 /* Geo to geo reprojection transformer. */
 void CPL_DLL *
-GDALCreateReprojectionTransformer( const char *pszSrcWKT, 
+GDALCreateReprojectionTransformer( const char *pszSrcWKT,
                                    const char *pszDstWKT );
 void CPL_DLL GDALDestroyReprojectionTransformer( void * );
-int CPL_DLL GDALReprojectionTransform( 
+int CPL_DLL GDALReprojectionTransform(
     void *pTransformArg, int bDstToSrc, int nPointCount,
     double *x, double *y, double *z, int *panSuccess );
 
 /* GCP based transformer ... forward is to georef coordinates */
 void CPL_DLL *
-GDALCreateGCPTransformer( int nGCPCount, const GDAL_GCP *pasGCPList, 
+GDALCreateGCPTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
                           int nReqOrder, int bReversed );
-			  
+
 /* GCP based transformer with refinement of the GCPs ... forward is to georef coordinates */
 void CPL_DLL *
-GDALCreateGCPRefineTransformer( int nGCPCount, const GDAL_GCP *pasGCPList, 
+GDALCreateGCPRefineTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
                                 int nReqOrder, int bReversed, double tolerance, int minimumGcps);
-			  
+
 void CPL_DLL GDALDestroyGCPTransformer( void *pTransformArg );
-int CPL_DLL GDALGCPTransform( 
+int CPL_DLL GDALGCPTransform(
     void *pTransformArg, int bDstToSrc, int nPointCount,
     double *x, double *y, double *z, int *panSuccess );
 
 /* Thin Plate Spine transformer ... forward is to georef coordinates */
 
 void CPL_DLL *
-GDALCreateTPSTransformer( int nGCPCount, const GDAL_GCP *pasGCPList, 
+GDALCreateTPSTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
                           int bReversed );
 void CPL_DLL GDALDestroyTPSTransformer( void *pTransformArg );
-int CPL_DLL GDALTPSTransform( 
+int CPL_DLL GDALTPSTransform(
     void *pTransformArg, int bDstToSrc, int nPointCount,
     double *x, double *y, double *z, int *panSuccess );
 
@@ -199,77 +199,75 @@ char CPL_DLL ** RPCInfoToMD( GDALRPCInfo *psRPCInfo );
 /* RPC based transformer ... src is pixel/line/elev, dst is long/lat/elev */
 
 void CPL_DLL *
-GDALCreateRPCTransformer( GDALRPCInfo *psRPC, int bReversed, 
+GDALCreateRPCTransformer( GDALRPCInfo *psRPC, int bReversed,
                           double dfPixErrThreshold,
                           char **papszOptions );
 void CPL_DLL GDALDestroyRPCTransformer( void *pTransformArg );
-int CPL_DLL GDALRPCTransform( 
+int CPL_DLL GDALRPCTransform(
     void *pTransformArg, int bDstToSrc, int nPointCount,
     double *x, double *y, double *z, int *panSuccess );
 
 /* Geolocation transformer */
 
 void CPL_DLL *
-GDALCreateGeoLocTransformer( GDALDatasetH hBaseDS, 
+GDALCreateGeoLocTransformer( GDALDatasetH hBaseDS,
                              char **papszGeolocationInfo,
                              int bReversed );
 void CPL_DLL GDALDestroyGeoLocTransformer( void *pTransformArg );
-int CPL_DLL GDALGeoLocTransform( 
+int CPL_DLL GDALGeoLocTransform(
     void *pTransformArg, int bDstToSrc, int nPointCount,
     double *x, double *y, double *z, int *panSuccess );
 
 /* Approximate transformer */
 void CPL_DLL *
-GDALCreateApproxTransformer( GDALTransformerFunc pfnRawTransformer, 
+GDALCreateApproxTransformer( GDALTransformerFunc pfnRawTransformer,
                              void *pRawTransformerArg, double dfMaxError );
-void CPL_DLL GDALApproxTransformerOwnsSubtransformer( void *pCBData, 
+void CPL_DLL GDALApproxTransformerOwnsSubtransformer( void *pCBData,
                                                       int bOwnFlag );
 void CPL_DLL GDALDestroyApproxTransformer( void *pApproxArg );
 int  CPL_DLL GDALApproxTransform(
     void *pTransformArg, int bDstToSrc, int nPointCount,
     double *x, double *y, double *z, int *panSuccess );
 
-                      
-
 
 int CPL_DLL CPL_STDCALL
-GDALSimpleImageWarp( GDALDatasetH hSrcDS, 
-                     GDALDatasetH hDstDS, 
+GDALSimpleImageWarp( GDALDatasetH hSrcDS,
+                     GDALDatasetH hDstDS,
                      int nBandCount, int *panBandList,
                      GDALTransformerFunc pfnTransform,
                      void *pTransformArg,
-                     GDALProgressFunc pfnProgress, 
-                     void *pProgressArg, 
+                     GDALProgressFunc pfnProgress,
+                     void *pProgressArg,
                      char **papszWarpOptions );
 
 CPLErr CPL_DLL CPL_STDCALL
-GDALSuggestedWarpOutput( GDALDatasetH hSrcDS, 
+GDALSuggestedWarpOutput( GDALDatasetH hSrcDS,
                          GDALTransformerFunc pfnTransformer,
                          void *pTransformArg,
-                         double *padfGeoTransformOut, 
+                         double *padfGeoTransformOut,
                          int *pnPixels, int *pnLines );
 CPLErr CPL_DLL CPL_STDCALL
-GDALSuggestedWarpOutput2( GDALDatasetH hSrcDS, 
+GDALSuggestedWarpOutput2( GDALDatasetH hSrcDS,
                           GDALTransformerFunc pfnTransformer,
                           void *pTransformArg,
-                          double *padfGeoTransformOut, 
+                          double *padfGeoTransformOut,
                           int *pnPixels, int *pnLines,
-                          double *padfExtents, 
+                          double *padfExtents,
                           int nOptions );
 
 CPLXMLNode CPL_DLL *
 GDALSerializeTransformer( GDALTransformerFunc pfnFunc, void *pTransformArg );
-CPLErr CPL_DLL GDALDeserializeTransformer( CPLXMLNode *psTree, 
-                                           GDALTransformerFunc *ppfnFunc, 
+CPLErr CPL_DLL GDALDeserializeTransformer( CPLXMLNode *psTree,
+                                           GDALTransformerFunc *ppfnFunc,
                                            void **ppTransformArg );
 
 CPLErr CPL_DLL
-GDALTransformGeolocations( GDALRasterBandH hXBand, 
-                           GDALRasterBandH hYBand, 
+GDALTransformGeolocations( GDALRasterBandH hXBand,
+                           GDALRasterBandH hYBand,
                            GDALRasterBandH hZBand,
-                           GDALTransformerFunc pfnTransformer, 
-                           void *pTransformArg, 
-                           GDALProgressFunc pfnProgress, 
+                           GDALTransformerFunc pfnTransformer,
+                           void *pTransformArg,
+                           GDALProgressFunc pfnProgress,
                            void *pProgressArg,
                            char **papszOptions );
 
@@ -283,33 +281,33 @@ typedef CPLErr (*GDALContourWriter)( double dfLevel, int nPoints,
 typedef void *GDALContourGeneratorH;
 
 GDALContourGeneratorH CPL_DLL
-GDAL_CG_Create( int nWidth, int nHeight, 
+GDAL_CG_Create( int nWidth, int nHeight,
                 int bNoDataSet, double dfNoDataValue,
                 double dfContourInterval, double dfContourBase,
                 GDALContourWriter pfnWriter, void *pCBData );
-CPLErr CPL_DLL GDAL_CG_FeedLine( GDALContourGeneratorH hCG, 
+CPLErr CPL_DLL GDAL_CG_FeedLine( GDALContourGeneratorH hCG,
                                  double *padfScanline );
 void CPL_DLL GDAL_CG_Destroy( GDALContourGeneratorH hCG );
 
-typedef struct 
+typedef struct
 {
     void   *hLayer;
 
     double adfGeoTransform[6];
-    
+
     int    nElevField;
     int    nIDField;
     int    nNextID;
 } OGRContourWriterInfo;
 
-CPLErr CPL_DLL 
+CPLErr CPL_DLL
 OGRContourWriter( double, int, double *, double *, void *pInfo );
 
 CPLErr CPL_DLL
-GDALContourGenerate( GDALRasterBandH hBand, 
+GDALContourGenerate( GDALRasterBandH hBand,
                             double dfContourInterval, double dfContourBase,
                             int nFixedLevelCount, double *padfFixedLevels,
-                            int bUseNoData, double dfNoDataValue, 
+                            int bUseNoData, double dfNoDataValue,
                             void *hLayer, int iIDField, int iElevField,
                             GDALProgressFunc pfnProgress, void *pProgressArg );
 
@@ -317,36 +315,36 @@ GDALContourGenerate( GDALRasterBandH hBand,
 /*      Rasterizer API - geometries burned into GDAL raster.            */
 /************************************************************************/
 
-CPLErr CPL_DLL 
-GDALRasterizeGeometries( GDALDatasetH hDS, 
-                         int nBandCount, int *panBandList, 
+CPLErr CPL_DLL
+GDALRasterizeGeometries( GDALDatasetH hDS,
+                         int nBandCount, int *panBandList,
                          int nGeomCount, OGRGeometryH *pahGeometries,
-                         GDALTransformerFunc pfnTransformer, 
-                         void *pTransformArg, 
+                         GDALTransformerFunc pfnTransformer,
+                         void *pTransformArg,
                          double *padfGeomBurnValue,
                          char **papszOptions,
-                         GDALProgressFunc pfnProgress, 
+                         GDALProgressFunc pfnProgress,
                          void * pProgressArg );
 CPLErr CPL_DLL
-GDALRasterizeLayers( GDALDatasetH hDS, 
+GDALRasterizeLayers( GDALDatasetH hDS,
                      int nBandCount, int *panBandList,
                      int nLayerCount, OGRLayerH *pahLayers,
-                     GDALTransformerFunc pfnTransformer, 
-                     void *pTransformArg, 
+                     GDALTransformerFunc pfnTransformer,
+                     void *pTransformArg,
                      double *padfLayerBurnValues,
                      char **papszOptions,
-                     GDALProgressFunc pfnProgress, 
+                     GDALProgressFunc pfnProgress,
                      void *pProgressArg );
 
-CPLErr CPL_DLL 
+CPLErr CPL_DLL
 GDALRasterizeLayersBuf( void *pData, int nBufXSize, int nBufYSize,
                         GDALDataType eBufType, int nPixelSpace, int nLineSpace,
                         int nLayerCount, OGRLayerH *pahLayers,
                         const char *pszDstProjection,
                         double *padfDstGeoTransform,
-                        GDALTransformerFunc pfnTransformer, 
+                        GDALTransformerFunc pfnTransformer,
                         void *pTransformArg, double dfBurnValue,
-                        char **papszOptions, GDALProgressFunc pfnProgress, 
+                        char **papszOptions, GDALProgressFunc pfnProgress,
                         void *pProgressArg );
 
 
@@ -365,7 +363,11 @@ typedef enum {
   /*! Number of Points (Data Metric) */ GGA_MetricCount = 7,
   /*! Average Distance (Data Metric) */ GGA_MetricAverageDistance = 8,
   /*! Average Distance Between Data Points (Data Metric) */
-                                        GGA_MetricAverageDistancePts = 9
+                                        GGA_MetricAverageDistancePts = 9,
+  /*! Linear interpolation (from Delaunay triangulation. Since GDAL 2.1 */
+                                        GGA_Linear = 10,
+  /*! Inverse distance to a power with nearest neighbor search for max points */
+                                        GGA_InverseDistanceToAPowerNearestNeighbor = 11
 } GDALGridAlgorithm;
 
 /** Inverse distance to a power method control options */
@@ -405,6 +407,30 @@ typedef struct
     double  dfNoDataValue;
 } GDALGridInverseDistanceToAPowerOptions;
 
+typedef struct
+{
+    /*! Weighting power. */
+    double  dfPower;
+    /*! The radius of search circle. */
+    double  dfRadius;
+
+    /*! Maximum number of data points to use.
+     *
+     * Do not search for more points than this number.
+     * If less amount of points found the grid node considered empty and will
+     * be filled with NODATA marker.
+     */
+    GUInt32 nMaxPoints;
+    /*! Minimum number of data points to use.
+     *
+     * If less amount of points found the grid node considered empty and will
+     * be filled with NODATA marker.
+     */
+    GUInt32 nMinPoints;
+    /*! No data marker to fill empty points. */
+    double  dfNoDataValue;
+} GDALGridInverseDistanceToAPowerNearestNeighborOptions;
+
 /** Moving average method control options */
 typedef struct
 {
@@ -465,6 +491,20 @@ typedef struct
     double  dfNoDataValue;
 } GDALGridDataMetricsOptions;
 
+/** Linear method control options */
+typedef struct
+{
+    /*! In case the point to be interpolated does not fit into a triangle of
+     * the Delaunay triangulation, use that maximum distance to search a nearest
+     * neighbour, or use nodata otherwise. If set to -1, the search distance is infinite.
+     * If set to 0, nodata value will be always used.
+     */
+    double  dfRadius;
+    /*! No data marker to fill empty points. */
+    double  dfNoDataValue;
+} GDALGridLinearOptions;
+
+
 CPLErr CPL_DLL
 GDALGridCreate( GDALGridAlgorithm, const void *, GUInt32,
                 const double *, const double *, const double *,
@@ -472,11 +512,92 @@ GDALGridCreate( GDALGridAlgorithm, const void *, GUInt32,
                 GUInt32, GUInt32, GDALDataType, void *,
                 GDALProgressFunc, void *);
 
+typedef struct GDALGridContext GDALGridContext;
+
+GDALGridContext CPL_DLL*
+GDALGridContextCreate( GDALGridAlgorithm eAlgorithm, const void *poOptions,
+                       GUInt32 nPoints,
+                       const double *padfX, const double *padfY, const double *padfZ,
+                       int bCallerWillKeepPointArraysAlive );
+
+void CPL_DLL GDALGridContextFree(GDALGridContext* psContext);
+
+CPLErr CPL_DLL GDALGridContextProcess(GDALGridContext* psContext,
+                              double dfXMin, double dfXMax, double dfYMin, double dfYMax,
+                              GUInt32 nXSize, GUInt32 nYSize, GDALDataType eType, void *pData,
+                              GDALProgressFunc pfnProgress, void *pProgressArg );
+
 GDAL_GCP CPL_DLL *
 GDALComputeMatchingPoints( GDALDatasetH hFirstImage,
                            GDALDatasetH hSecondImage,
                            char **papszOptions,
-                           int *pnGCPCount ); 
+                           int *pnGCPCount );
+
+/************************************************************************/
+/*  Delaunay triangulation interface.                                   */
+/************************************************************************/
+
+typedef struct
+{
+    int anVertexIdx[3];   /* index to the padfX/padfY arrays */
+    int anNeighborIdx[3]; /* index to GDALDelaunayTriangulation.pasFacets, or -1 */
+                          /* anNeighborIdx[k] is the triangle to the opposite side */
+                          /* of the opposite segment of anVertexIdx[k] */
+} GDALTriFacet;
+
+/* Conversion from cartesian (x,y) to barycentric (l1,l2,l3) with :
+   l1 = dfMul1X * (x - dfCxtX) + dfMul1Y * (y - dfCstY)
+   l2 = dfMul2X * (x - dfCxtX) + dfMul2Y * (y - dfCstY)
+   l3 = 1 - l1 - l2
+*/
+typedef struct
+{
+    double      dfMul1X;
+    double      dfMul1Y;
+    double      dfMul2X;
+    double      dfMul2Y;
+    double      dfCstX;
+    double      dfCstY;
+} GDALTriBarycentricCoefficients;
+
+typedef struct
+{
+    int                             nFacets;
+    GDALTriFacet                   *pasFacets;     /* nFacets elements */
+    GDALTriBarycentricCoefficients *pasFacetCoefficients; /* nFacets elements */
+} GDALTriangulation;
+
+int CPL_DLL GDALHasTriangulation(void);
+
+GDALTriangulation CPL_DLL *GDALTriangulationCreateDelaunay(int nPoints,
+                                                           const double* padfX,
+                                                           const double* padfY);
+int  CPL_DLL GDALTriangulationComputeBarycentricCoefficients(
+                                                GDALTriangulation* psDT,
+                                                const double* padfX,
+                                                const double* padfY);
+int  CPL_DLL GDALTriangulationComputeBarycentricCoordinates(
+                                                const GDALTriangulation* psDT,
+                                                int nFacetIdx,
+                                                double dfX,
+                                                double dfY,
+                                                double* pdfL1,
+                                                double* pdfL2,
+                                                double* pdfL3);
+int CPL_DLL GDALTriangulationFindFacetBruteForce( const GDALTriangulation* psDT,
+                                                  double dfX,
+                                                  double dfY,
+                                                  int* panOutputFacetIdx );
+int CPL_DLL GDALTriangulationFindFacetDirected( const GDALTriangulation* psDT,
+                                                int nFacetIdx,
+                                                double dfX,
+                                                double dfY,
+                                                int* panOutputFacetIdx );
+void CPL_DLL GDALTriangulationFree(GDALTriangulation* psDT);
+
+// GDAL internal use only
+void GDALTriangulationTerminate(void);
+
 CPL_C_END
-                            
+
 #endif /* ndef GDAL_ALG_H_INCLUDED */
diff --git a/alg/gdal_alg_priv.h b/alg/gdal_alg_priv.h
index 3015ec0..88b0d11 100644
--- a/alg/gdal_alg_priv.h
+++ b/alg/gdal_alg_priv.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_alg_priv.h 28826 2015-03-30 17:51:14Z rouault $
+ * $Id: gdal_alg_priv.h 33757 2016-03-20 20:22:33Z goatbar $
  *
  * Project:  GDAL Image Processing Algorithms
  * Purpose:  Prototypes and definitions for various GDAL based algorithms:
@@ -71,18 +71,18 @@ void GDALdllImagePoint( int nRasterXSize, int nRasterYSize,
                         double *padfX, double *padfY, double *padfVariant,
                         llPointFunc pfnPointFunc, void *pCBData );
 
-void GDALdllImageLine( int nRasterXSize, int nRasterYSize, 
+void GDALdllImageLine( int nRasterXSize, int nRasterYSize,
                        int nPartCount, int *panPartSize,
                        double *padfX, double *padfY, double *padfVariant,
                        llPointFunc pfnPointFunc, void *pCBData );
 
-void GDALdllImageLineAllTouched(int nRasterXSize, int nRasterYSize, 
+void GDALdllImageLineAllTouched(int nRasterXSize, int nRasterYSize,
                                 int nPartCount, int *panPartSize,
                                 double *padfX, double *padfY,
                                 double *padfVariant,
                                 llPointFunc pfnPointFunc, void *pCBData );
 
-void GDALdllImageFilledPolygon(int nRasterXSize, int nRasterYSize, 
+void GDALdllImageFilledPolygon(int nRasterXSize, int nRasterYSize,
                                int nPartCount, int *panPartSize,
                                double *padfX, double *padfY,
                                double *padfVariant,
@@ -96,17 +96,17 @@ CPL_C_END
 
 #define GP_NODATA_MARKER -51502112
 
-class GDALRasterPolygonEnumerator
+template<class DataType, class EqualityTest> class GDALRasterPolygonEnumeratorT
 
 {
 private:
     void     MergePolygon( int nSrcId, int nDstId );
-    int      NewPolygon( GInt32 nValue );
+    int      NewPolygon( DataType nValue );
 
 public:  // these are intended to be readonly.
 
     GInt32   *panPolyIdMap;
-    GInt32   *panPolyValue;
+    DataType   *panPolyValue;
 
     int      nNextPolygonId;
     int      nPolyAlloc;
@@ -114,11 +114,11 @@ public:  // these are intended to be readonly.
     int      nConnectedness;
 
 public:
-             GDALRasterPolygonEnumerator( int nConnectedness=4 );
-            ~GDALRasterPolygonEnumerator();
+             GDALRasterPolygonEnumeratorT( int nConnectedness=4 );
+            ~GDALRasterPolygonEnumeratorT();
 
-    void     ProcessLine( GInt32 *panLastLineVal, GInt32 *panThisLineVal,
-                          GInt32 *panLastLineId,  GInt32 *panThisLineId, 
+    void     ProcessLine( DataType *panLastLineVal, DataType *panThisLineVal,
+                          GInt32 *panLastLineId,  GInt32 *panThisLineId,
                           int nXSize );
 
     void     CompleteMerges();
@@ -126,42 +126,12 @@ public:
     void     Clear();
 };
 
-#ifdef OGR_ENABLED
-/************************************************************************/
-/*                          Polygon Enumerator                          */
-/*                                                                      */
-/*              Buffers has float values instead og GInt32              */
-/************************************************************************/
-class GDALRasterFPolygonEnumerator
-
+struct IntEqualityTest
 {
-private:
-    void     MergePolygon( int nSrcId, int nDstId );
-    int      NewPolygon( float fValue );
-
-public:  // these are intended to be readonly.
-
-    GInt32   *panPolyIdMap;
-    float    *pafPolyValue;
-
-    int      nNextPolygonId;
-    int      nPolyAlloc;
-
-    int      nConnectedness;
-
-public:
-             GDALRasterFPolygonEnumerator( int nConnectedness=4 );
-            ~GDALRasterFPolygonEnumerator();
-
-    void     ProcessLine( float *pafLastLineVal, float *pafThisLineVal,
-                          GInt32 *panLastLineId,  GInt32 *panThisLineId,
-                          int nXSize );
-
-    void     CompleteMerges();
-
-    void     Clear();
+    bool operator()(GInt32 a, GInt32 b) { return a == b; }
 };
-#endif
+
+typedef GDALRasterPolygonEnumeratorT<GInt32, IntEqualityTest> GDALRasterPolygonEnumerator;
 
 typedef void* (*GDALTransformDeserializeFunc)( CPLXMLNode *psTree );
 
@@ -174,44 +144,49 @@ void GDALCleanupTransformDeserializerMutex();
 
 /* Transformer cloning */
 
-void* GDALCreateTPSTransformerInt( int nGCPCount, const GDAL_GCP *pasGCPList, 
+void* GDALCreateTPSTransformerInt( int nGCPCount, const GDAL_GCP *pasGCPList,
                                    int bReversed, char** papszOptions );
 
-void CPL_DLL * GDALCloneTransformer( void *pTranformerArg );
+void CPL_DLL * GDALCloneTransformer( void *pTransformerArg );
 
 /************************************************************************/
 /*      Color table related                                             */
 /************************************************************************/
 
-int
-GDALComputeMedianCutPCTInternal( GDALRasterBandH hRed, 
-                           GDALRasterBandH hGreen, 
-                           GDALRasterBandH hBlue, 
+/* definitions exists for T = GUInt32 and T = GUIntBig */
+template<class T> int
+GDALComputeMedianCutPCTInternal( GDALRasterBandH hRed,
+                           GDALRasterBandH hGreen,
+                           GDALRasterBandH hBlue,
                            GByte* pabyRedBand,
                            GByte* pabyGreenBand,
                            GByte* pabyBlueBand,
                            int (*pfnIncludePixel)(int,int,void*),
-                           int nColors, 
+                           int nColors,
                            int nBits,
-                           int* panHistogram,
+                           T* panHistogram,
                            GDALColorTableH hColorTable,
-                           GDALProgressFunc pfnProgress, 
+                           GDALProgressFunc pfnProgress,
                            void * pProgressArg );
 
-int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed, 
-                               GDALRasterBandH hGreen, 
-                               GDALRasterBandH hBlue, 
-                               GDALRasterBandH hTarget, 
+int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
+                               GDALRasterBandH hGreen,
+                               GDALRasterBandH hBlue,
+                               GDALRasterBandH hTarget,
                                GDALColorTableH hColorTable,
                                int nBits,
                                GInt16* pasDynamicColorMap,
                                int bDither,
-                               GDALProgressFunc pfnProgress, 
+                               GDALProgressFunc pfnProgress,
                                void * pProgressArg );
 
 #define PRIME_FOR_65536                                 98317
+
+/* See HashHistogram structure in gdalmediancut.cpp and ColorIndex structure in gdaldither.cpp */
+/* 6 * sizeof(int) should be the size of the largest of both structures */
 #define MEDIAN_CUT_AND_DITHER_BUFFER_SIZE_65536         (6 * sizeof(int) * PRIME_FOR_65536)
 
+
 /************************************************************************/
 /*      Float comparison function.                                      */
 /************************************************************************/
@@ -220,10 +195,15 @@ int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
  * Units in the Last Place. This specifies how big an error we are willing to
  * accept in terms of the value of the least significant digit of the floating
  * point number’s representation. MAX_ULPS can also be interpreted in terms of
- * how many representable floats we are willing to accept between A and B. 
+ * how many representable floats we are willing to accept between A and B.
  */
 #define MAX_ULPS 10
 
 GBool GDALFloatEquals(float A, float B);
 
+struct FloatEqualityTest
+{
+    bool operator()(float a, float b) { return GDALFloatEquals(a,b) == TRUE; }
+};
+
 #endif /* ndef GDAL_ALG_PRIV_H_INCLUDED */
diff --git a/alg/gdal_crs.c b/alg/gdal_crs.c
index 8f0e74c..a219adc 100644
--- a/alg/gdal_crs.c
+++ b/alg/gdal_crs.c
@@ -1,9 +1,9 @@
 /******************************************************************************
- * $Id: gdal_crs.c 29207 2015-05-18 17:23:45Z mloskot $
+ * $Id: gdal_crs.c 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  Mapinfo Image Warper
- * Purpose:  Implemention of the GDALTransformer wrapper around CRS.C functions
- *           to build a polynomial transformation based on ground control 
+ * Purpose:  Implementation of the GDALTransformer wrapper around CRS.C functions
+ *           to build a polynomial transformation based on ground control
  *           points.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -28,27 +28,26 @@
       Fixed bug so that only the active control points were used.
     Last Update:  6/29/2011 C. F. Stallmann & R. van den Dool (South African National Space Agency)
       GCP refinement added
-      
 
     Copyright (c) 1992, Michigan State University
  * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
-   
+
     Permission is hereby granted, free of charge, to any person obtaining a
     copy of this software and associated documentation files (the "Software"),
     to deal in the Software without restriction, including without limitation
     the rights to use, copy, modify, merge, publish, distribute, sublicense,
     and/or sell copies of the Software, and to permit persons to whom the
     Software is furnished to do so, subject to the following conditions:
-    
+
     The above copyright notice and this permission notice shall be included
     in all copies or substantial portions of the Software.
-    
+
     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     DEALINGS IN THE SOFTWARE.
 
  ****************************************************************************/
@@ -59,7 +58,7 @@
 #include "cpl_string.h"
 #include "cpl_atomic_ops.h"
 
-CPL_CVSID("$Id: gdal_crs.c 29207 2015-05-18 17:23:45Z mloskot $");
+CPL_CVSID("$Id: gdal_crs.c 33715 2016-03-13 08:52:06Z goatbar $");
 
 /* Hum, we cannot include gdal_priv.h from a .c file... */
 CPL_C_START
@@ -93,7 +92,7 @@ typedef struct
 
     double adfToGeoX[20];
     double adfToGeoY[20];
-    
+
     double adfFromGeoX[20];
     double adfFromGeoY[20];
 
@@ -105,9 +104,9 @@ typedef struct
     int    bRefine;
     int    nMinimumGcps;
     double dfTolerance;
-    
+
     volatile int nRefCount;
-    
+
 } GCPTransformInfo;
 
 CPL_C_START
@@ -116,13 +115,13 @@ void *GDALDeserializeGCPTransformer( CPLXMLNode *psTree );
 CPL_C_END
 
 /* crs.c */
-static int CRS_georef(double, double, double *, double *, 
+static int CRS_georef(double, double, double *, double *,
                               double [], double [], int);
 static int CRS_compute_georef_equations(struct Control_Points *,
     double [], double [], double [], double [], int);
 static int remove_outliers(GCPTransformInfo *);
 
-static char *CRS_error_message[] = {
+static const char * const CRS_error_message[] = {
     "Failed to compute GCP transform: Not enough points available",
     "Failed to compute GCP transform: Transform is not solvable",
     "Failed to compute GCP transform: Not enough memory",
@@ -142,7 +141,7 @@ void* GDALCreateSimilarGCPTransformer( void *hTransformArg, double dfRatioX, dou
     GCPTransformInfo *psInfo = (GCPTransformInfo *) hTransformArg;
 
     VALIDATE_POINTER1( hTransformArg, "GDALCreateSimilarGCPTransformer", NULL );
-    
+
     if( dfRatioX == 1.0 && dfRatioY == 1.0 )
     {
         /* We can just use a ref count, since using the source transformation */
@@ -171,34 +170,8 @@ void* GDALCreateSimilarGCPTransformer( void *hTransformArg, double dfRatioX, dou
 /*                      GDALCreateGCPTransformer()                      */
 /************************************************************************/
 
-/**
- * Create GCP based polynomial transformer.
- *
- * Computes least squares fit polynomials from a provided set of GCPs,
- * and stores the coefficients for later transformation of points between
- * pixel/line and georeferenced coordinates. 
- *
- * The return value should be used as a TransformArg in combination with
- * the transformation function GDALGCPTransform which fits the 
- * GDALTransformerFunc signature.  The returned transform argument should
- * be deallocated with GDALDestroyGCPTransformer when no longer needed.
- *
- * This function may fail (returning NULL) if the provided set of GCPs
- * are inadequate for the requested order, the determinate is zero or they
- * are otherwise "ill conditioned".  
- *
- * Note that 2nd order requires at least 6 GCPs, and 3rd order requires at
- * least 10 gcps.  If nReqOrder is 0 the highest order possible with the
- * provided gcp count will be used.
- *
- * @param nGCPCount the number of GCPs in pasGCPList.
- * @param pasGCPList an array of GCPs to be used as input.
- * @param nReqOrder the requested polynomial order.  It should be 1, 2 or 3.
- * 
- * @return the transform argument or NULL if creation fails. 
- */
-
-void *GDALCreateGCPTransformerEx( int nGCPCount, const GDAL_GCP *pasGCPList, 
+static
+void *GDALCreateGCPTransformerEx( int nGCPCount, const GDAL_GCP *pasGCPList,
                                 int nReqOrder, int bReversed, int bRefine, double dfTolerance, int nMinimumGcps)
 
 {
@@ -217,14 +190,14 @@ void *GDALCreateGCPTransformerEx( int nGCPCount, const GDAL_GCP *pasGCPList,
         else
             nReqOrder = 1;
     }
-    
+
     psInfo = (GCPTransformInfo *) CPLCalloc(sizeof(GCPTransformInfo),1);
     psInfo->bReversed = bReversed;
     psInfo->nOrder = nReqOrder;
     psInfo->bRefine = bRefine;
     psInfo->dfTolerance = dfTolerance;
     psInfo->nMinimumGcps = nMinimumGcps;
-    
+
     psInfo->nRefCount = 1;
 
     psInfo->pasGCPList = GDALDuplicateGCPs( nGCPCount, pasGCPList );
@@ -236,7 +209,7 @@ void *GDALCreateGCPTransformerEx( int nGCPCount, const GDAL_GCP *pasGCPList,
     psInfo->sTI.pfnCleanup = GDALDestroyGCPTransformer;
     psInfo->sTI.pfnSerialize = GDALSerializeGCPTransformer;
     psInfo->sTI.pfnCreateSimilar = GDALCreateSimilarGCPTransformer;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Compute the forward and reverse polynomials.                    */
 /* -------------------------------------------------------------------- */
@@ -255,7 +228,7 @@ void *GDALCreateGCPTransformerEx( int nGCPCount, const GDAL_GCP *pasGCPList,
         padfRasterX = (double *) CPLCalloc(sizeof(double),nGCPCount);
         padfRasterY = (double *) CPLCalloc(sizeof(double),nGCPCount);
         panStatus = (int *) CPLCalloc(sizeof(int),nGCPCount);
-    
+
         for( iGCP = 0; iGCP < nGCPCount; iGCP++ )
         {
             panStatus[iGCP] = 1;
@@ -294,14 +267,40 @@ void *GDALCreateGCPTransformerEx( int nGCPCount, const GDAL_GCP *pasGCPList,
     }
 }
 
-void *GDALCreateGCPTransformer( int nGCPCount, const GDAL_GCP *pasGCPList, 
+/**
+ * Create GCP based polynomial transformer.
+ *
+ * Computes least squares fit polynomials from a provided set of GCPs,
+ * and stores the coefficients for later transformation of points between
+ * pixel/line and georeferenced coordinates.
+ *
+ * The return value should be used as a TransformArg in combination with
+ * the transformation function GDALGCPTransform which fits the
+ * GDALTransformerFunc signature.  The returned transform argument should
+ * be deallocated with GDALDestroyGCPTransformer when no longer needed.
+ *
+ * This function may fail (returning NULL) if the provided set of GCPs
+ * are inadequate for the requested order, the determinate is zero or they
+ * are otherwise "ill conditioned".
+ *
+ * Note that 2nd order requires at least 6 GCPs, and 3rd order requires at
+ * least 10 gcps.  If nReqOrder is 0 the highest order possible with the
+ * provided gcp count will be used.
+ *
+ * @param nGCPCount the number of GCPs in pasGCPList.
+ * @param pasGCPList an array of GCPs to be used as input.
+ * @param nReqOrder the requested polynomial order.  It should be 1, 2 or 3.
+ *
+ * @return the transform argument or NULL if creation fails.
+ */
+void *GDALCreateGCPTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
                                 int nReqOrder, int bReversed )
 
 {
     return GDALCreateGCPTransformerEx(nGCPCount, pasGCPList, nReqOrder, bReversed, FALSE, -1, -1);
 }
 
-void *GDALCreateGCPRefineTransformer( int nGCPCount, const GDAL_GCP *pasGCPList, 
+void *GDALCreateGCPRefineTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
                                 int nReqOrder, int bReversed, double dfTolerance, int nMinimumGcps)
 
 {
@@ -322,10 +321,10 @@ void *GDALCreateGCPRefineTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
  * Destroy GCP transformer.
  *
  * This function is used to destroy information about a GCP based
- * polynomial transformation created with GDALCreateGCPTransformer(). 
+ * polynomial transformation created with GDALCreateGCPTransformer().
  *
- * @param pTransformArg the transform arg previously returned by 
- * GDALCreateGCPTransformer(). 
+ * @param pTransformArg the transform arg previously returned by
+ * GDALCreateGCPTransformer().
  */
 
 void GDALDestroyGCPTransformer( void *pTransformArg )
@@ -356,10 +355,10 @@ void GDALDestroyGCPTransformer( void *pTransformArg )
  *
  * This function matches the GDALTransformerFunc signature, and can be
  * used to transform one or more points from pixel/line coordinates to
- * georeferenced coordinates (SrcToDst) or vice versa (DstToSrc). 
+ * georeferenced coordinates (SrcToDst) or vice versa (DstToSrc).
  *
- * @param pTransformArg return value from GDALCreateGCPTransformer(). 
- * @param bDstToSrc TRUE if transformation is from the destination 
+ * @param pTransformArg return value from GDALCreateGCPTransformer().
+ * @param bDstToSrc TRUE if transformation is from the destination
  * (georeferenced) coordinates to pixel/line or FALSE when transforming
  * from pixel/line to georeferenced coordinates.
  * @param nPointCount the number of values in the x, y and z arrays.
@@ -383,7 +382,7 @@ int GDALGCPTransform( void *pTransformArg, int bDstToSrc,
 
     if( psInfo->bReversed )
         bDstToSrc = !bDstToSrc;
-    
+
     for( i = 0; i < nPointCount; i++ )
     {
         if( x[i] == HUGE_VAL || y[i] == HUGE_VAL )
@@ -394,14 +393,14 @@ int GDALGCPTransform( void *pTransformArg, int bDstToSrc,
 
         if( bDstToSrc )
         {
-            CRS_georef( x[i], y[i], x + i, y + i, 
-                        psInfo->adfFromGeoX, psInfo->adfFromGeoY, 
+            CRS_georef( x[i], y[i], x + i, y + i,
+                        psInfo->adfFromGeoX, psInfo->adfFromGeoY,
                         psInfo->nOrder );
         }
         else
         {
-            CRS_georef( x[i], y[i], x + i, y + i, 
-                        psInfo->adfToGeoX, psInfo->adfToGeoY, 
+            CRS_georef( x[i], y[i], x + i, y + i,
+                        psInfo->adfToGeoX, psInfo->adfToGeoY,
                         psInfo->nOrder );
         }
         panSuccess[i] = TRUE;
@@ -427,12 +426,12 @@ CPLXMLNode *GDALSerializeGCPTransformer( void *pTransformArg )
 /* -------------------------------------------------------------------- */
 /*      Serialize Order and bReversed.                                  */
 /* -------------------------------------------------------------------- */
-    CPLCreateXMLElementAndValue( 
-        psTree, "Order", 
+    CPLCreateXMLElementAndValue(
+        psTree, "Order",
         CPLSPrintf( "%d", psInfo->nOrder ) );
-                         
-    CPLCreateXMLElementAndValue( 
-        psTree, "Reversed", 
+
+    CPLCreateXMLElementAndValue(
+        psTree, "Reversed",
         CPLSPrintf( "%d", psInfo->bReversed ) );
 
     if( psInfo->bRefine )
@@ -449,7 +448,7 @@ CPLXMLNode *GDALSerializeGCPTransformer( void *pTransformArg )
             psTree, "Tolerance",
             CPLSPrintf( "%f", psInfo->dfTolerance ) );
     }
-                                 
+
 /* -------------------------------------------------------------------- */
 /*	Attach GCP List. 						*/
 /* -------------------------------------------------------------------- */
@@ -512,15 +511,15 @@ void *GDALDeserializeGCPTransformer( CPLXMLNode *psTree )
 /* -------------------------------------------------------------------- */
     if(bRefine)
     {
-        pResult = GDALCreateGCPRefineTransformer( nGCPCount, pasGCPList, nReqOrder, 
+        pResult = GDALCreateGCPRefineTransformer( nGCPCount, pasGCPList, nReqOrder,
                                         bReversed, dfTolerance, nMinimumGcps );
     }
     else
     {
-        pResult = GDALCreateGCPTransformer( nGCPCount, pasGCPList, nReqOrder, 
+        pResult = GDALCreateGCPTransformer( nGCPCount, pasGCPList, nReqOrder,
                                         bReversed );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Cleanup GCP copy.                                               */
 /* -------------------------------------------------------------------- */
@@ -578,7 +577,7 @@ static double term(int,double,double);
 */
 /***************************************************************************/
 
-static int 
+static int
 CRS_georef (
     double e1,  /* EASTINGS TO BE TRANSFORMED */
     double n1,  /* NORTHINGS TO BE TRANSFORMED */
@@ -646,10 +645,10 @@ CRS_georef (
 */
 /***************************************************************************/
 
-static int 
-CRS_compute_georef_equations (struct Control_Points *cp, 
-                                      double E12[], double N12[], 
-                                      double E21[], double N21[], 
+static int
+CRS_compute_georef_equations (struct Control_Points *cp,
+                                      double E12[], double N12[],
+                                      double E21[], double N21[],
                                       int order)
 {
     double *tempptr;
@@ -695,7 +694,7 @@ CRS_compute_georef_equations (struct Control_Points *cp,
 */
 /***************************************************************************/
 
-static int 
+static int
 calccoef (struct Control_Points *cp, double E[], double N[], int order)
 {
     struct MATRIX m;
@@ -870,9 +869,9 @@ ORDER\TERM   1    2    3    4    5    6    7    8    9   10
 */
 /***************************************************************************/
 
-static double term (int term, double e, double n)
+static double term (int nTerm, double e, double n)
 {
-    switch(term)
+    switch(nTerm)
     {
       case  1: return((double)1.0);
       case  2: return((double)e);
@@ -940,7 +939,7 @@ static int solvemat (struct MATRIX *m,
             return(MUNSOLVABLE);
 
         /* if row with highest pivot is not the current row, switch them */
- 
+
         if(imark != i)
         {
             for(j2 = 1 ; j2 <= m->n ; j2++)
@@ -991,26 +990,26 @@ static int solvemat (struct MATRIX *m,
 /*
   DETECTS THE WORST OUTLIER IN THE GCP LIST AND RETURNS THE INDEX OF THE
   OUTLIER.
-  
+
   THE WORST OUTLIER IS CALCULATED BASED ON THE CONTROL POINTS, COEFFICIENTS
   AND THE ALLOWED TOLERANCE:
-  
+
   sampleAdj = a0 + a1*sample + a2*line + a3*line*sample
   lineAdj = b0 + b1*sample + b2*line + b3*line*sample
-  
+
   WHERE sampleAdj AND lineAdj ARE CORRELATED GCPS
-  
+
   [residualSample] = [A1][sampleCoefficients] - [b1]
   [residualLine] = [A2][lineCoefficients] - [b2]
-  
+
   sampleResidual^2 = sum( [residualSample]^2 )
   lineResidual^2 = sum( [lineSample]^2 )
-  
+
   residuals(i) = squareRoot( residualSample(i)^2 + residualLine(i)^2 )
-  
+
   THE GCP WITH THE GREATEST DISTANCE residual(i) GREATER THAN THE TOLERANCE WILL
   CONSIDERED THE WORST OUTLIER.
-  
+
   IF NO OUTLIER CAN BE FOUND, -1 WILL BE RETURNED.
 */
 /***************************************************************************/
@@ -1020,11 +1019,11 @@ static int worst_outlier(struct Control_Points *cp, double E[], double N[], doub
     int nI, nIndex;
     double dfDifference, dfSampleResidual, dfLineResidual, dfSampleRes, dfLineRes, dfCurrentDifference;
     double dfE1, dfN1, dfE2, dfN2, dfEn;
-  
+
     padfResiduals = (double *) CPLCalloc(sizeof(double),cp->count);
     dfSampleResidual = 0.0;
     dfLineResidual = 0.0;
-  
+
     for(nI = 0; nI < cp->count; nI++)
     {
         dfE1 = cp->e1[nI];
@@ -1035,13 +1034,13 @@ static int worst_outlier(struct Control_Points *cp, double E[], double N[], doub
 
         dfSampleRes = E[0] + E[1] * dfE1 + E[2] * dfN1 + E[3] * dfE2 + E[4] * dfEn + E[5] * dfN2 - cp->e2[nI];
         dfLineRes = N[0] + N[1] * dfE1 + N[2] * dfN1 + N[3] * dfE2 + N[4] * dfEn + N[5] * dfN2 - cp->n2[nI];
-    
+
         dfSampleResidual += dfSampleRes*dfSampleRes;
         dfLineResidual += dfLineRes*dfLineRes;
-    
+
         padfResiduals[nI] = sqrt(dfSampleRes*dfSampleRes + dfLineRes*dfLineRes);
     }
-  
+
     nIndex = -1;
     dfDifference = -1.0;
     for(nI = 0; nI < cp->count; nI++)
@@ -1065,9 +1064,9 @@ static int worst_outlier(struct Control_Points *cp, double E[], double N[], doub
 /*
   REMOVES THE WORST OUTLIERS ITERATIVELY UNTIL THE MINIMUM NUMBER OF GCPS
   ARE REACHED OR NO OUTLIERS CAN BE DETECTED.
-  
+
   1. WE CALCULATE THE COEFFICIENTS FOR ALL THE GCPS.
-  2. THE GCP LIST WILL BE SCANED TO DETERMINE THE WORST OUTLIER USING
+  2. THE GCP LIST WILL BE SCANNED TO DETERMINE THE WORST OUTLIER USING
      THE CALCULATED COEFFICIENTS.
   3. THE WORST OUTLIER WILL BE REMOVED FROM THE GCP LIST.
   4. THE COEFFICIENTS WILL BE RECALCULATED WITHOUT THE WORST OUTLIER.
@@ -1082,18 +1081,18 @@ static int remove_outliers( GCPTransformInfo *psInfo )
     int nI, nCRSresult, nGCPCount, nMinimumGcps, nReqOrder;
     double dfTolerance;
     struct Control_Points sPoints;
-    
+
     nGCPCount = psInfo->nGCPCount;
     nMinimumGcps = psInfo->nMinimumGcps;
     nReqOrder = psInfo->nOrder;
     dfTolerance = psInfo->dfTolerance;
-    
+
     padfGeoX = (double *) CPLCalloc(sizeof(double),nGCPCount);
     padfGeoY = (double *) CPLCalloc(sizeof(double),nGCPCount);
     padfRasterX = (double *) CPLCalloc(sizeof(double),nGCPCount);
     padfRasterY = (double *) CPLCalloc(sizeof(double),nGCPCount);
     panStatus = (int *) CPLCalloc(sizeof(int),nGCPCount);
-    
+
     for( nI = 0; nI < nGCPCount; nI++ )
     {
         panStatus[nI] = 1;
@@ -1109,7 +1108,7 @@ static int remove_outliers( GCPTransformInfo *psInfo )
     sPoints.e2 = padfGeoX;
     sPoints.n2 = padfGeoY;
     sPoints.status = panStatus;
-  
+
     nCRSresult = CRS_compute_georef_equations( &sPoints,
                                       psInfo->adfToGeoX, psInfo->adfToGeoY,
                                       psInfo->adfFromGeoX, psInfo->adfFromGeoY,
@@ -1156,7 +1155,7 @@ static int remove_outliers( GCPTransformInfo *psInfo )
         psInfo->pasGCPList[nI].dfGCPLine = sPoints.n1[nI];
     }
     psInfo->nGCPCount = sPoints.count;
-    
+
     CPLFree( sPoints.e1 );
     CPLFree( sPoints.n1 );
     CPLFree( sPoints.e2 );
diff --git a/alg/gdal_nrgcrs.c b/alg/gdal_nrgcrs.c
index c5c759e..c6d5af0 100644
--- a/alg/gdal_nrgcrs.c
+++ b/alg/gdal_nrgcrs.c
@@ -1,9 +1,9 @@
 /******************************************************************************
- * $Id: gdal_nrgcrs.c 23156 2011-10-01 15:34:16Z rouault $
+ * $Id: gdal_nrgcrs.c 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  Mapinfo Image Warper
- * Purpose:  Implemention of the GDALTransformer wrapper around CRS.C functions
- *           to build a polynomial transformation based on ground control 
+ * Purpose:  Implementation of the GDALTransformer wrapper around CRS.C functions
+ *           to build a polynomial transformation based on ground control
  *           points.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -40,13 +40,13 @@ typedef struct
 {
     double adfToGeoX[20];
     double adfToGeoY[20];
-    
+
     double adfFromGeoX[20];
     double adfFromGeoY[20];
 
     int    nOrder;
     int    bReversed;
-    
+
 } GCPTransformInfo;
 
 
@@ -59,16 +59,16 @@ typedef struct
  *
  * Computes least squares fit polynomials from a provided set of GCPs,
  * and stores the coefficients for later transformation of points between
- * pixel/line and georeferenced coordinates. 
+ * pixel/line and georeferenced coordinates.
  *
  * The return value should be used as a TransformArg in combination with
- * the transformation function GDALGCPTransform which fits the 
+ * the transformation function GDALGCPTransform which fits the
  * GDALTransformerFunc signature.  The returned transform argument should
  * be deallocated with GDALDestroyGCPTransformer when no longer needed.
  *
  * This function may fail (returning NULL) if the provided set of GCPs
  * are inadequate for the requested order, the determinate is zero or they
- * are otherwise "ill conditioned".  
+ * are otherwise "ill conditioned".
  *
  * Note that 2nd order requires at least 6 GCPs, and 3rd order requires at
  * least 10 gcps.  If nReqOrder is 0 the highest order possible with the
@@ -78,11 +78,11 @@ typedef struct
  * @param pasGCPList an array of GCPs to be used as input.
  * @param nReqOrder the requested polynomial order.  It should be 1, 2 or 3.
  * @param bReversed set it to TRUE to compute the reversed transformation.
- * 
- * @return the transform argument or NULL if creation fails. 
+ *
+ * @return the transform argument or NULL if creation fails.
  */
 
-void *GDALCreateGCPTransformer( int nGCPCount, const GDAL_GCP *pasGCPList, 
+void *GDALCreateGCPTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
                                 int nReqOrder, int bReversed )
 
 {
@@ -100,7 +100,7 @@ void *GDALCreateGCPTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
         else
             nReqOrder = 1;
     }
-    
+
     psInfo = (GCPTransformInfo *) CPLCalloc(sizeof(GCPTransformInfo),1);
     psInfo->bReversed = bReversed;
     psInfo->nOrder = nReqOrder;
@@ -113,7 +113,7 @@ void *GDALCreateGCPTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
     padfRasterX = (double *) CPLCalloc(sizeof(double),nGCPCount);
     padfRasterY = (double *) CPLCalloc(sizeof(double),nGCPCount);
     panStatus = (int *) CPLCalloc(sizeof(int),nGCPCount);
-    
+
     for( iGCP = 0; iGCP < nGCPCount; iGCP++ )
     {
         panStatus[iGCP] = 1;
@@ -165,7 +165,7 @@ void *GDALCreateGCPTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
     CPLDebug( "GDALCreateGCPTransformer",
 	      "Number of GCPs %d, transformation order %d",
 	      nGCPCount, psInfo->nOrder );
-    
+
     for( iGCP = 0; iGCP < nGCPCount; iGCP++ )
     {
 	double x = pasGCPList[iGCP].dfGCPX;
@@ -177,7 +177,7 @@ void *GDALCreateGCPTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
 		  "GCP %d. Residuals: X: %f, Y: %f", iGCP,
 		  pasGCPList[iGCP].dfGCPPixel - x, pasGCPList[iGCP].dfGCPLine - y );
     }
-    
+
     return psInfo;
 
   CleanupAfterError:
@@ -186,7 +186,7 @@ void *GDALCreateGCPTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
     CPLFree( padfRasterX );
     CPLFree( padfRasterX );
     CPLFree( panStatus );
-    
+
     CPLFree( psInfo );
     return NULL;
 }
@@ -199,10 +199,10 @@ void *GDALCreateGCPTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
  * Destroy GCP transformer.
  *
  * This function is used to destroy information about a GCP based
- * polynomial transformation created with GDALCreateGCPTransformer(). 
+ * polynomial transformation created with GDALCreateGCPTransformer().
  *
- * @param pTransformArg the transform arg previously returned by 
- * GDALCreateGCPTransformer(). 
+ * @param pTransformArg the transform arg previously returned by
+ * GDALCreateGCPTransformer().
  */
 
 void GDALDestroyGCPTransformer( void *pTransformArg )
@@ -220,10 +220,10 @@ void GDALDestroyGCPTransformer( void *pTransformArg )
  *
  * This function matches the GDALTransformerFunc signature, and can be
  * used to transform one or more points from pixel/line coordinates to
- * georeferenced coordinates (SrcToDst) or vice versa (DstToSrc). 
+ * georeferenced coordinates (SrcToDst) or vice versa (DstToSrc).
  *
- * @param pTransformArg return value from GDALCreateGCPTransformer(). 
- * @param bDstToSrc TRUE if transformation is from the destination 
+ * @param pTransformArg return value from GDALCreateGCPTransformer().
+ * @param bDstToSrc TRUE if transformation is from the destination
  * (georeferenced) coordinates to pixel/line or FALSE when transforming
  * from pixel/line to georeferenced coordinates.
  * @param nPointCount the number of values in the x, y and z arrays.
@@ -236,9 +236,9 @@ void GDALDestroyGCPTransformer( void *pTransformArg )
  * @return TRUE.
  */
 
-int GDALGCPTransform( void *pTransformArg, int bDstToSrc, 
-                      int nPointCount, 
-                      double *x, double *y, double *z, 
+int GDALGCPTransform( void *pTransformArg, int bDstToSrc,
+                      int nPointCount,
+                      double *x, double *y, double *z,
                       int *panSuccess )
 
 {
@@ -248,7 +248,7 @@ int GDALGCPTransform( void *pTransformArg, int bDstToSrc,
 
     if( psInfo->bReversed )
         bDstToSrc = !bDstToSrc;
-    
+
     for( i = 0; i < nPointCount; i++ )
     {
 	X = x[i];
@@ -273,7 +273,7 @@ int GDALGCPTransform( void *pTransformArg, int bDstToSrc,
 CPLXMLNode *GDALSerializeGCPTransformer( void *pTransformArg )
 
 {
-    CPLError( CE_Failure, CPLE_AppDefined, 
+    CPLError( CE_Failure, CPLE_AppDefined,
               "serialization not supported for this type of gcp transformer.");
     return NULL;
 }
@@ -281,7 +281,7 @@ CPLXMLNode *GDALSerializeGCPTransformer( void *pTransformArg )
 void *GDALDeserializeGCPTransformer( CPLXMLNode *psTree )
 
 {
-    CPLError( CE_Failure, CPLE_AppDefined, 
+    CPLError( CE_Failure, CPLE_AppDefined,
               "deserialization not supported for this type of gcp transformer.");
     return NULL;
 }
diff --git a/alg/gdal_octave.cpp b/alg/gdal_octave.cpp
index 2bbeeb1..46bd1b1 100644
--- a/alg/gdal_octave.cpp
+++ b/alg/gdal_octave.cpp
@@ -37,7 +37,7 @@ CPL_CVSID("$Id");
 
 GDALIntegralImage::GDALIntegralImage()
 {
-    pMatrix = 0;
+    pMatrix = NULL;
     nHeight = 0;
     nWidth = 0;
 }
@@ -46,15 +46,15 @@ int GDALIntegralImage::GetHeight() { return nHeight; }
 
 int GDALIntegralImage::GetWidth() { return nWidth; }
 
-void GDALIntegralImage::Initialize(const double **padfImg, int nHeight, int nWidth)
+void GDALIntegralImage::Initialize(const double **padfImg, int nHeightIn, int nWidthIn)
 {
     //Memory allocation
-    pMatrix = new double*[nHeight];
-    for (int i = 0; i < nHeight; i++)
-        pMatrix[i] = new double[nWidth];
+    pMatrix = new double*[nHeightIn];
+    for (int i = 0; i < nHeightIn; i++)
+        pMatrix[i] = new double[nWidthIn];
 
-    this->nHeight = nHeight;
-    this->nWidth = nWidth;
+    nHeight = nHeightIn;
+    nWidth = nWidthIn;
 
     //Integral image calculation
     for (int i = 0; i < nHeight; i++)
@@ -86,23 +86,23 @@ double GDALIntegralImage::GetValue(int nRow, int nCol)
         return 0;
 }
 
-double GDALIntegralImage::GetRectangleSum(int nRow, int nCol, int nWidth, int nHeight)
+double GDALIntegralImage::GetRectangleSum(int nRow, int nCol, int nWidthIn, int nHeightIn)
 {
     double a = 0, b = 0, c = 0, d = 0;
 
     //Left top point of rectangle is first
-    int w = nWidth - 1;
-    int h = nHeight - 1;
+    int w = nWidthIn - 1;
+    int h = nHeightIn - 1;
 
     int row = nRow;
     int col = nCol;
 
     //Left top point
-    int lt_row = (row <= this->nHeight) ? (row - 1) : -1;
-    int lt_col = (col <= this->nWidth) ? (col - 1) : -1;
+    int lt_row = (row <= nHeight) ? (row - 1) : -1;
+    int lt_col = (col <= nWidth) ? (col - 1) : -1;
     //Right bottom point of the rectangle
-    int rb_row = (row + h < this->nHeight) ? (row + h) : (this->nHeight - 1);
-    int rb_col = (col + w < this->nWidth) ? (col + w) : (this->nWidth - 1);
+    int rb_row = (row + h < nHeight) ? (row + h) : (nHeight - 1);
+    int rb_col = (col + w < nWidth) ? (col + w) : (nWidth - 1);
 
     if (lt_row >= 0 && lt_col >= 0)
         a = this->GetValue(lt_row, lt_col);
@@ -159,8 +159,8 @@ GDALOctaveLayer::GDALOctaveLayer(int nOctave, int nInterval)
     this->width = 0;
     this->height = 0;
 
-    this->detHessians = 0;
-    this->signs = 0;
+    this->detHessians = NULL;
+    this->signs = NULL;
 }
 
 void GDALOctaveLayer::ComputeLayer(GDALIntegralImage *poImg)
@@ -256,18 +256,18 @@ void GDALOctaveMap::ComputeMap(GDALIntegralImage *poImg)
 bool GDALOctaveMap::PointIsExtremum(int row, int col, GDALOctaveLayer *bot,
                                     GDALOctaveLayer *mid, GDALOctaveLayer *top, double threshold)
 {
-    //Check that point in middle layer has all neighbours
+    // Check that point in middle layer has all neighbors.
     if (row <= top->radius || col <= top->radius ||
         row + top->radius >= top->height || col + top->radius >= top->width)
         return false;
 
     double curPoint = mid->detHessians[row][col];
 
-    //Hessian should be higher than threshold
+    // Hessian should be higher than threshold.
     if (curPoint < threshold)
         return false;
 
-    //Hessian should be higher than hessians of all neighbours
+    // Hessian should be higher than Hessians of all neighbors
     for (int i = -1; i <= 1; i++)
         for (int j = -1; j <= 1; j++)
         {
diff --git a/alg/gdal_rpc.cpp b/alg/gdal_rpc.cpp
index 9d84a7e..7c24a0b 100644
--- a/alg/gdal_rpc.cpp
+++ b/alg/gdal_rpc.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: gdal_rpc.cpp 29417 2015-06-22 08:30:54Z rouault $
+ * $Id: gdal_rpc.cpp 33846 2016-04-01 14:53:13Z rouault $
  *
  * Project:  Image Warper
- * Purpose:  Implements a rational polynomail (RPC) based transformer. 
+ * Purpose:  Implements a rational polynomial (RPC) based transformer.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -34,13 +34,20 @@
 #include "cpl_minixml.h"
 #include "gdal_mdreader.h"
 
-CPL_CVSID("$Id: gdal_rpc.cpp 29417 2015-06-22 08:30:54Z rouault $");
+#if (defined(__x86_64) || defined(_M_X64))
+#define USE_SSE2_OPTIM
+#include "gdalsse_priv.h"
+#endif
+
+CPL_CVSID("$Id: gdal_rpc.cpp 33846 2016-04-01 14:53:13Z rouault $");
 
 CPL_C_START
 CPLXMLNode *GDALSerializeRPCTransformer( void *pTransformArg );
 void *GDALDeserializeRPCTransformer( CPLXMLNode *psTree );
 CPL_C_END
 
+static const int MAX_ABS_VALUE_WARNINGS = 20;
+
 /************************************************************************/
 /*                            RPCInfoToMD()                             */
 /*                                                                      */
@@ -175,52 +182,6 @@ static void RPCComputeTerms( double dfLong, double dfLat, double dfHeight,
 }
 
 /************************************************************************/
-/*                            RPCEvaluate()                             */
-/************************************************************************/
-
-static double RPCEvaluate( double *padfTerms, double *padfCoefs )
-
-{
-    double dfSum = 0.0;
-    int i;
-
-    for( i = 0; i < 20; i++ )
-        dfSum += padfTerms[i] * padfCoefs[i];
-
-    return dfSum;
-}
-
-/************************************************************************/
-/*                         RPCTransformPoint()                          */
-/************************************************************************/
-
-static void RPCTransformPoint( GDALRPCInfo *psRPC, 
-                               double dfLong, double dfLat, double dfHeight, 
-                               double *pdfPixel, double *pdfLine )
-
-{
-    double dfResultX, dfResultY;
-    double adfTerms[20];
-   
-    RPCComputeTerms( 
-        (dfLong   - psRPC->dfLONG_OFF) / psRPC->dfLONG_SCALE, 
-        (dfLat    - psRPC->dfLAT_OFF) / psRPC->dfLAT_SCALE, 
-        (dfHeight - psRPC->dfHEIGHT_OFF) / psRPC->dfHEIGHT_SCALE,
-        adfTerms );
-    
-    dfResultX = RPCEvaluate( adfTerms, psRPC->adfSAMP_NUM_COEFF )
-        / RPCEvaluate( adfTerms, psRPC->adfSAMP_DEN_COEFF );
-    
-    dfResultY = RPCEvaluate( adfTerms, psRPC->adfLINE_NUM_COEFF )
-        / RPCEvaluate( adfTerms, psRPC->adfLINE_DEN_COEFF );
-   
-    // RPCs are using the center of upper left pixel = 0,0 convention
-    // convert to top left corner = 0,0 convention used in GDAL
-     *pdfPixel = dfResultX * psRPC->dfSAMP_SCALE + psRPC->dfSAMP_OFF + 0.5;
-    *pdfLine = dfResultY * psRPC->dfLINE_SCALE + psRPC->dfLINE_OFF + 0.5;
-}
-
-/************************************************************************/
 /* ==================================================================== */
 /*			     GDALRPCTransformer                         */
 /* ==================================================================== */
@@ -240,6 +201,7 @@ typedef struct {
     GDALRPCInfo sRPC;
 
     double      adfPLToLatLongGeoTransform[6];
+    double      dfRefZ;
 
     int         bReversed;
 
@@ -252,20 +214,172 @@ typedef struct {
     char        *pszDEMPath;
 
     DEMResampleAlg eResampleAlg;
-    
+
     int         bHasDEMMissingValue;
     double      dfDEMMissingValue;
+    int         bApplyDEMVDatumShift;
 
     int         bHasTriedOpeningDS;
     GDALDataset *poDS;
 
     OGRCoordinateTransformation *poCT;
 
+    int         nMaxIterations;
+
     double      adfDEMGeoTransform[6];
     double      adfDEMReverseGeoTransform[6];
+
+#ifdef USE_SSE2_OPTIM
+    double      adfDoubles[20 * 4 + 1];
+    double     *padfCoeffs; // LINE_NUM_COEFF, LINE_DEN_COEFF, SAMP_NUM_COEFF and then SAMP_DEN_COEFF
+#endif
+
+    bool        bRPCInverseVerbose;
+    char       *pszRPCInverseLog;
 } GDALRPCTransformInfo;
 
 /************************************************************************/
+/*                            RPCEvaluate()                             */
+/************************************************************************/
+#ifdef USE_SSE2_OPTIM
+
+static void RPCEvaluate4( const double *padfTerms,
+                          const double *padfCoefs,
+                          double& dfSum1, double& dfSum2,
+                          double& dfSum3, double& dfSum4 )
+
+{
+    int i;
+    XMMReg2Double terms, coefs1, coefs2, coefs3, coefs4,
+                  sum1 = XMMReg2Double::Zero(),
+                  sum2 = XMMReg2Double::Zero(),
+                  sum3 = XMMReg2Double::Zero(),
+                  sum4 = XMMReg2Double::Zero();
+    for( i = 0; i < 20; i+=2 )
+    {
+        terms = XMMReg2Double::Load2ValAligned(padfTerms + i);
+        coefs1 = XMMReg2Double::Load2ValAligned(padfCoefs + i);       // LINE_NUM_COEFF
+        coefs2 = XMMReg2Double::Load2ValAligned(padfCoefs + i + 20);  // LINE_DEN_COEFF
+        coefs3 = XMMReg2Double::Load2ValAligned(padfCoefs + i + 40);  // SAMP_NUM_COEFF
+        coefs4 = XMMReg2Double::Load2ValAligned(padfCoefs + i + 60);  // SAMP_DEN_COEFF
+        sum1 += terms * coefs1;
+        sum2 += terms * coefs2;
+        sum3 += terms * coefs3;
+        sum4 += terms * coefs4;
+    }
+    sum1.AddLowAndHigh();
+    sum2.AddLowAndHigh();
+    sum3.AddLowAndHigh();
+    sum4.AddLowAndHigh();
+    dfSum1 = (double)sum1;
+    dfSum2 = (double)sum2;
+    dfSum3 = (double)sum3;
+    dfSum4 = (double)sum4;
+}
+
+#else
+
+static double RPCEvaluate( const double *padfTerms, const double *padfCoefs )
+
+{
+    double dfSum1 = 0.0, dfSum2 = 0.0;
+    int i;
+
+    for( i = 0; i < 20; i+=2 )
+    {
+        dfSum1 += padfTerms[i] * padfCoefs[i];
+        dfSum2 += padfTerms[i+1] * padfCoefs[i+1];
+    }
+
+    return dfSum1 + dfSum2;
+}
+
+#endif
+
+/************************************************************************/
+/*                         RPCTransformPoint()                          */
+/************************************************************************/
+
+static void RPCTransformPoint( const GDALRPCTransformInfo *psRPCTransformInfo,
+                               double dfLong, double dfLat, double dfHeight,
+                               double *pdfPixel, double *pdfLine )
+
+{
+    double dfResultX, dfResultY;
+    double adfTermsWithMargin[20+1];
+    // Make sure padfTerms is aligned on a 16-byte boundary for SSE2 aligned loads
+    double* padfTerms = adfTermsWithMargin + (((size_t)adfTermsWithMargin) % 16) / 8;
+
+    const double dfNormalizedLong =
+      (dfLong   - psRPCTransformInfo->sRPC.dfLONG_OFF) / psRPCTransformInfo->sRPC.dfLONG_SCALE;
+    const double dfNormalizedLat =
+      (dfLat    - psRPCTransformInfo->sRPC.dfLAT_OFF) / psRPCTransformInfo->sRPC.dfLAT_SCALE;
+    const double dfNormalizedHeight =
+      (dfHeight - psRPCTransformInfo->sRPC.dfHEIGHT_OFF) / psRPCTransformInfo->sRPC.dfHEIGHT_SCALE;
+
+    // The absolute values of the 3 above normalized values are supposed to be
+    // below 1. Warn (as debug message) if it is not the case. We allow for some
+    // margin above 1 (1.5, somewhat arbitrary chosen) before warning
+    static int nCountWarningsAboutAboveOneNormalizedValues = 0;
+    if( nCountWarningsAboutAboveOneNormalizedValues < MAX_ABS_VALUE_WARNINGS )
+    {
+        bool bWarned = false;
+        if( fabs(dfNormalizedLong) > 1.5 )
+        {
+            bWarned = true;
+            CPLDebug("RPC", "Normalized %s for (lon,lat,height)=(%f,%f,%f) is %f, "
+                    "ie with an absolute value of > 1, which may cause numeric stability problems",
+                    "longitude", dfLong, dfLat, dfHeight, dfNormalizedLong);
+        }
+        if( fabs(dfNormalizedLat) > 1.5 )
+        {
+            bWarned = true;
+            CPLDebug("RPC", "Normalized %s for (lon,lat,height)=(%f,%f,%f) is %f, "
+                    "ie with an absolute value of > 1, which may cause numeric stability problems",
+                    "latitude", dfLong, dfLat, dfHeight, dfNormalizedLat);
+        }
+        if( fabs(dfNormalizedHeight) > 1.5 )
+        {
+            bWarned = true;
+            CPLDebug("RPC", "Normalized %s for (lon,lat,height)=(%f,%f,%f) is %f, "
+                    "ie with an absolute value of > 1, which may cause numeric stability problems",
+                    "height", dfLong, dfLat, dfHeight, dfNormalizedHeight);
+        }
+        if( bWarned )
+        {
+            // Limit the number of warnings
+            nCountWarningsAboutAboveOneNormalizedValues ++;
+            if( nCountWarningsAboutAboveOneNormalizedValues == MAX_ABS_VALUE_WARNINGS )
+            {
+                CPLDebug("RPC", "No more such debug warnings will be emitted");
+            }
+        }
+    }
+
+    RPCComputeTerms( dfNormalizedLong, dfNormalizedLat, dfNormalizedHeight, padfTerms );
+
+#ifdef USE_SSE2_OPTIM
+    double dfSampNum, dfSampDen, dfLineNum, dfLineDen;
+    RPCEvaluate4( padfTerms,
+                  psRPCTransformInfo->padfCoeffs,
+                  dfLineNum, dfLineDen, dfSampNum, dfSampDen );
+    dfResultX = dfSampNum / dfSampDen;
+    dfResultY = dfLineNum / dfLineDen;
+#else
+    dfResultX = RPCEvaluate( padfTerms, psRPCTransformInfo->sRPC.adfSAMP_NUM_COEFF )
+        / RPCEvaluate( padfTerms, psRPCTransformInfo->sRPC.adfSAMP_DEN_COEFF );
+
+    dfResultY = RPCEvaluate( padfTerms, psRPCTransformInfo->sRPC.adfLINE_NUM_COEFF )
+        / RPCEvaluate( padfTerms, psRPCTransformInfo->sRPC.adfLINE_DEN_COEFF );
+#endif
+
+    // RPCs are using the center of upper left pixel = 0,0 convention
+    // convert to top left corner = 0,0 convention used in GDAL
+    *pdfPixel = dfResultX * psRPCTransformInfo->sRPC.dfSAMP_SCALE + psRPCTransformInfo->sRPC.dfSAMP_OFF + 0.5;
+    *pdfLine = dfResultY * psRPCTransformInfo->sRPC.dfLINE_SCALE + psRPCTransformInfo->sRPC.dfLINE_OFF + 0.5;
+}
+
+/************************************************************************/
 /*                     GDALSerializeRPCDEMResample()                    */
 /************************************************************************/
 
@@ -293,10 +407,10 @@ void* GDALCreateSimilarRPCTransformer( void *hTransformArg, double dfRatioX, dou
     VALIDATE_POINTER1( hTransformArg, "GDALCreateSimilarRPCTransformer", NULL );
 
     GDALRPCTransformInfo *psInfo = (GDALRPCTransformInfo *) hTransformArg;
-    
+
     GDALRPCInfo sRPC;
     memcpy(&sRPC, &(psInfo->sRPC), sizeof(GDALRPCInfo));
-    
+
     if( dfRatioX != 1.0 || dfRatioY != 1.0 )
     {
         sRPC.dfLINE_OFF /= dfRatioY;
@@ -318,12 +432,75 @@ void* GDALCreateSimilarRPCTransformer( void *hTransformArg, double dfRatioX, dou
         if( psInfo->bHasDEMMissingValue )
             papszOptions = CSLSetNameValue(papszOptions, "RPC_DEM_MISSING_VALUE",
                                            CPLSPrintf("%.18g", psInfo->dfDEMMissingValue)) ;
+        papszOptions = CSLSetNameValue(papszOptions, "RPC_DEM_APPLY_VDATUM_SHIFT",
+                                           (psInfo->bApplyDEMVDatumShift) ? "TRUE" : "FALSE") ;
     }
-    psInfo = (GDALRPCTransformInfo*) GDALCreateRPCTransformer( &sRPC,
+    papszOptions = CSLSetNameValue(papszOptions, "RPC_MAX_ITERATIONS",
+                                   CPLSPrintf("%d", psInfo->nMaxIterations));
+
+    GDALRPCTransformInfo* psNewInfo = (GDALRPCTransformInfo*) GDALCreateRPCTransformer( &sRPC,
            psInfo->bReversed, psInfo->dfPixErrThreshold, papszOptions );
     CSLDestroy(papszOptions);
 
-    return psInfo;
+    return psNewInfo;
+}
+
+/************************************************************************/
+/*                      GDALRPCGetHeightAtLongLat()                     */
+/************************************************************************/
+
+static
+int GDALRPCGetDEMHeight( const GDALRPCTransformInfo *psTransform,
+                         const double dfXIn, const double dfYIn, double* pdfDEMH );
+
+static bool GDALRPCGetHeightAtLongLat( const GDALRPCTransformInfo *psTransform,
+                                       const double dfXIn, const double dfYIn,
+                                       double* pdfHeight,
+                                       double* pdfDEMPixel = NULL, double* pdfDEMLine = NULL)
+{
+    double dfVDatumShift = 0.0;
+    double dfDEMH = 0;
+    if(psTransform->poDS)
+    {
+        double dfX, dfY;
+        double dfXTemp = dfXIn;
+        double dfYTemp = dfYIn;
+        //check if dem is not in WGS84 and transform points padfX[i], padfY[i]
+        if(psTransform->poCT)
+        {
+            double dfZ = 0;
+            if (!psTransform->poCT->Transform(1, &dfXTemp, &dfYTemp, &dfZ))
+            {
+                return false;
+            }
+
+            // We must take the opposite since poCT transforms from
+            // WGS84 to geoid. And we are going to do the reverse:
+            // take an elevation over the geoid and transforms it to WGS84
+            if( psTransform->bApplyDEMVDatumShift )
+                dfVDatumShift = -dfZ;
+        }
+
+        GDALApplyGeoTransform( (double*)(psTransform->adfDEMReverseGeoTransform),
+                                dfXTemp, dfYTemp, &dfX, &dfY );
+        if( pdfDEMPixel )
+            *pdfDEMPixel = dfX;
+        if( pdfDEMLine )
+            *pdfDEMLine = dfY;
+
+        if( !GDALRPCGetDEMHeight( psTransform, dfX, dfY, &dfDEMH) )
+        {
+            if( psTransform->bHasDEMMissingValue )
+                dfDEMH = psTransform->dfDEMMissingValue;
+            else
+            {
+                return false;
+            }
+        }
+    }
+
+    *pdfHeight = dfVDatumShift + (psTransform->dfHeightOffset + dfDEMH * psTransform->dfHeightScale);
+    return true;
 }
 
 /************************************************************************/
@@ -331,35 +508,35 @@ void* GDALCreateSimilarRPCTransformer( void *hTransformArg, double dfRatioX, dou
 /************************************************************************/
 
 /**
- * Create an RPC based transformer. 
+ * Create an RPC based transformer.
  *
- * The geometric sensor model describing the physical relationship between 
- * image coordinates and ground coordinate is known as a Rigorous Projection 
- * Model. A Rigorous Projection Model expresses the mapping of the image space 
- * coordinates of rows and columns (r,c) onto the object space reference 
+ * The geometric sensor model describing the physical relationship between
+ * image coordinates and ground coordinate is known as a Rigorous Projection
+ * Model. A Rigorous Projection Model expresses the mapping of the image space
+ * coordinates of rows and columns (r,c) onto the object space reference
  * surface geodetic coordinates (long, lat, height).
- * 
- * RPC supports a generic description of the Rigorous Projection Models. The 
- * approximation used by GDAL (RPC00) is a set of rational polynomials exp 
- * ressing the normalized row and column values, (rn , cn), as a function of
- *  normalized geodetic latitude, longitude, and height, (P, L, H), given a 
+ *
+ * RPC supports a generic description of the Rigorous Projection Models. The
+ * approximation used by GDAL (RPC00) is a set of rational polynomials
+ * expressing the normalized row and column values, (rn , cn), as a function of
+ * normalized geodetic latitude, longitude, and height, (P, L, H), given a
  * set of normalized polynomial coefficients (LINE_NUM_COEF_n, LINE_DEN_COEF_n,
- *  SAMP_NUM_COEF_n, SAMP_DEN_COEF_n). Normalized values, rather than actual 
- * values are used in order to minimize introduction of errors during the 
- * calculations. The transformation between row and column values (r,c), and 
- * normalized row and column values (rn, cn), and between the geodetic 
- * latitude, longitude, and height and normalized geodetic latitude, 
- * longitude, and height (P, L, H), is defined by a set of normalizing 
- * translations (offsets) and scales that ensure all values are contained i 
+ * SAMP_NUM_COEF_n, SAMP_DEN_COEF_n). Normalized values, rather than actual
+ * values are used in order to minimize introduction of errors during the
+ * calculations. The transformation between row and column values (r,c), and
+ * normalized row and column values (rn, cn), and between the geodetic
+ * latitude, longitude, and height and normalized geodetic latitude,
+ * longitude, and height (P, L, H), is defined by a set of normalizing
+ * translations (offsets) and scales that ensure all values are contained i
  * the range -1 to +1.
  *
- * This function creates a GDALTransformFunc compatible transformer 
- * for going between image pixel/line and long/lat/height coordinates 
+ * This function creates a GDALTransformFunc compatible transformer
+ * for going between image pixel/line and long/lat/height coordinates
  * using RPCs.  The RPCs are provided in a GDALRPCInfo structure which is
- * normally read from metadata using GDALExtractRPCInfo().  
+ * normally read from metadata using GDALExtractRPCInfo().
  *
  * GDAL RPC Metadata has the following entries (also described in GDAL RFC 22
- * and the GeoTIFF RPC document http://geotiff.maptools.org/rpc_prop.html .  
+ * and the GeoTIFF RPC document http://geotiff.maptools.org/rpc_prop.html .
  *
  * <ul>
  * <li>ERR_BIAS: Error - Bias. The RMS bias error in meters per horizontal axis of all points in the image (-1.0 if unknown)
@@ -384,23 +561,31 @@ void* GDALCreateSimilarRPCTransformer( void *hTransformArg, double dfRatioX, dou
  * as a forward transformation though in RPC terms that would be considered
  * an inverse transformation (and is solved by iterative approximation using
  * long/lat/height to pixel/line transformations).  The default direction can
- * be reversed by passing bReversed=TRUE.  
- * 
+ * be reversed by passing bReversed=TRUE.
+ *
  * The iterative solution of pixel/line
- * to lat/long/height is currently run for up to 10 iterations or until 
+ * to lat/long/height is currently run for up to 10 iterations or until
  * the apparent error is less than dfPixErrThreshold pixels.  Passing zero
  * will not avoid all error, but will cause the operation to run for the maximum
- * number of iterations. 
+ * number of iterations.
+ *
+ * Starting with GDAL 2.1, debugging of the RPC inverse transformer can be done by setting the
+ * RPC_INVERSE_VERBOSE configuration option to YES (in which case extra debug
+ * information will be displayed in the "RPC" debug category, so requiring CPL_DEBUG
+ * to be also set) and/or by setting RPC_INVERSE_LOG to a filename that will
+ * contain the content of iterations (this last option only makes sense when
+ * debugging point by point, since each time RPCInverseTransformPoint() is called,
+ * the file is rewritten)
  *
  * Additional options to the transformer can be supplied in papszOptions.
  *
  * Options:
- * 
+ *
  * <ul>
  * <li> RPC_HEIGHT: a fixed height offset to be applied to all points passed
  * in.  In this situation the Z passed into the transformation function is
  * assumed to be height above ground, and the RPC_HEIGHT is assumed to be
- * an average height above sea level for ground in the target scene. 
+ * an average height above sea level for ground in the target scene.
  *
  * <li> RPC_HEIGHT_SCALE: a factor used to multiply heights above ground.
  * Useful when elevation offsets of the DEM are not expressed in meters. (GDAL >= 1.8.0)
@@ -418,22 +603,40 @@ void* GDALCreateSimilarRPCTransformer( void *hTransformArg, double dfRatioX, dou
  * cover the requested coordinate. When not specified, missing values will cause
  * a failed transform. (GDAL >= 1.11.2)
  *
+ * <li> RPC_DEM_APPLY_VDATUM_SHIFT: whether the vertical component of a compound SRS
+ * for the DEM should be used (when it is present). This is useful so as to be able to transform the
+ * "raw" values from the DEM expressed with respect to a geoid to the heights with
+ * respect to the WGS84 ellipsoid. When this is enabled, the GTIFF_REPORT_COMPD_CS configuration
+ * option will be also set temporarily so as to get the vertical information from GeoTIFF
+ * files. Defaults to TRUE. (GDAL >= 2.1.0)
+ *
+ * <li> RPC_PIXEL_ERROR_THRESHOLD: overrides the dfPixErrThreshold parameter, ie
+  the error (measured in pixels) allowed in the
+ * iterative solution of pixel/line to lat/long computations (the other way
+ * is always exact given the equations).  (GDAL >= 2.1.0)
+ *
+ * <li> RPC_MAX_ITERATIONS: maximum number of iterations allowed in the iterative
+ * solution of pixel/line to lat/long computations. Default value is 10
+ * in the absence of a DEM, or 20 if there is a DEM.  (GDAL >= 2.1.0)
+ *
  * </ul>
  *
  * @param psRPCInfo Definition of the RPC parameters.
  *
- * @param bReversed If true "forward" transformation will be lat/long to pixel/line instead of the normal pixel/line to lat/long.
+ * @param bReversed If true "forward" transformation will be lat/long to
+ * pixel/line instead of the normal pixel/line to lat/long.
  *
- * @param dfPixErrThreshold the error (measured in pixels) allowed in the 
+ * @param dfPixErrThreshold the error (measured in pixels) allowed in the
  * iterative solution of pixel/line to lat/long computations (the other way
- * is always exact given the equations). 
+ * is always exact given the equations). Starting with GDAL 2.1, this may also
+ * be set through the RPC_PIXEL_ERROR_THRESHOLD transformer option.
  *
- * @param papszOptions Other transformer options (ie. RPC_HEIGHT=<z>). 
+ * @param papszOptions Other transformer options (i.e. RPC_HEIGHT=<z>).
  *
  * @return transformer callback data (deallocate with GDALDestroyTransformer()).
  */
 
-void *GDALCreateRPCTransformer( GDALRPCInfo *psRPCInfo, int bReversed, 
+void *GDALCreateRPCTransformer( GDALRPCInfo *psRPCInfo, int bReversed,
                                 double dfPixErrThreshold,
                                 char **papszOptions )
 
@@ -443,12 +646,18 @@ void *GDALCreateRPCTransformer( GDALRPCInfo *psRPCInfo, int bReversed,
 /* -------------------------------------------------------------------- */
 /*      Initialize core info.                                           */
 /* -------------------------------------------------------------------- */
-    psTransform = (GDALRPCTransformInfo *) 
+    psTransform = (GDALRPCTransformInfo *)
         CPLCalloc(sizeof(GDALRPCTransformInfo),1);
 
     memcpy( &(psTransform->sRPC), psRPCInfo, sizeof(GDALRPCInfo) );
     psTransform->bReversed = bReversed;
-    psTransform->dfPixErrThreshold = dfPixErrThreshold;
+    const char* pszPixErrThreshold = CSLFetchNameValue( papszOptions, "RPC_PIXEL_ERROR_THRESHOLD" );
+    if( pszPixErrThreshold != NULL )
+        psTransform->dfPixErrThreshold = CPLAtof(pszPixErrThreshold);
+    else if( dfPixErrThreshold > 0 )
+        psTransform->dfPixErrThreshold = dfPixErrThreshold;
+    else
+        psTransform->dfPixErrThreshold = 0.1;
     psTransform->dfHeightOffset = 0.0;
     psTransform->dfHeightScale = 1.0;
 
@@ -458,7 +667,16 @@ void *GDALCreateRPCTransformer( GDALRPCInfo *psRPCInfo, int bReversed,
     psTransform->sTI.pfnCleanup = GDALDestroyRPCTransformer;
     psTransform->sTI.pfnSerialize = GDALSerializeRPCTransformer;
     psTransform->sTI.pfnCreateSimilar = GDALCreateSimilarRPCTransformer;
-   
+
+#ifdef USE_SSE2_OPTIM
+    // Make sure padfCoeffs is aligned on a 16-byte boundary for SSE2 aligned loads
+    psTransform->padfCoeffs = psTransform->adfDoubles + (((size_t)psTransform->adfDoubles) % 16) / 8;
+    memcpy(psTransform->padfCoeffs, psRPCInfo->adfLINE_NUM_COEFF, 20 * sizeof(double));
+    memcpy(psTransform->padfCoeffs+20, psRPCInfo->adfLINE_DEN_COEFF, 20 * sizeof(double));
+    memcpy(psTransform->padfCoeffs+40, psRPCInfo->adfSAMP_NUM_COEFF, 20 * sizeof(double));
+    memcpy(psTransform->padfCoeffs+60, psRPCInfo->adfSAMP_DEN_COEFF, 20 * sizeof(double));
+#endif
+
 /* -------------------------------------------------------------------- */
 /*      Do we have a "average height" that we want to consider all      */
 /*      elevations to be relative to?                                   */
@@ -493,7 +711,7 @@ void *GDALCreateRPCTransformer( GDALRPCInfo *psRPCInfo, int bReversed,
         psTransform->eResampleAlg = DRA_Cubic;
     else
     {
-        CPLDebug("RPC", "Unknown interpolation %s. Defaulting to bilinear", pszDEMInterpolation); 
+        CPLDebug("RPC", "Unknown interpolation %s. Defaulting to bilinear", pszDEMInterpolation);
         psTransform->eResampleAlg = DRA_Bilinear;
     }
 
@@ -508,6 +726,24 @@ void *GDALCreateRPCTransformer( GDALRPCInfo *psRPCInfo, int bReversed,
     }
 
 /* -------------------------------------------------------------------- */
+/*      Whether to apply vdatum shift                                   */
+/* -------------------------------------------------------------------- */
+    psTransform->bApplyDEMVDatumShift = CSLFetchBoolean(
+        papszOptions, "RPC_DEM_APPLY_VDATUM_SHIFT", TRUE );
+
+
+    psTransform->nMaxIterations = atoi( CSLFetchNameValueDef(
+        papszOptions, "RPC_MAX_ITERATIONS", "0" ) );
+
+/* -------------------------------------------------------------------- */
+/*      Debug                                                           */
+/* -------------------------------------------------------------------- */
+    psTransform->bRPCInverseVerbose = CPLTestBool( CPLGetConfigOption("RPC_INVERSE_VERBOSE", "NO") );
+    const char* pszRPCInverseLog = CPLGetConfigOption("RPC_INVERSE_LOG", NULL);
+    if( pszRPCInverseLog != NULL )
+        psTransform->pszRPCInverseLog = CPLStrdup(pszRPCInverseLog);
+
+/* -------------------------------------------------------------------- */
 /*      Establish a reference point for calcualating an affine          */
 /*      geotransform approximate transformation.                        */
 /* -------------------------------------------------------------------- */
@@ -519,34 +755,65 @@ void *GDALCreateRPCTransformer( GDALRPCInfo *psRPCInfo, int bReversed,
         dfRefLong = (psRPCInfo->dfMIN_LONG + psRPCInfo->dfMAX_LONG) * 0.5;
         dfRefLat  = (psRPCInfo->dfMIN_LAT  + psRPCInfo->dfMAX_LAT ) * 0.5;
 
-        RPCTransformPoint( psRPCInfo, dfRefLong, dfRefLat, 0.0, 
-                           &dfRefPixel, &dfRefLine );
+        double dfX = dfRefLong;
+        double dfY = dfRefLat;
+        double dfZ = 0;
+        int nSuccess;
+        // Try with DEM first
+        if( GDALRPCTransform( psTransform, !(psTransform->bReversed), 1,
+                          &dfX, &dfY, &dfZ, &nSuccess) )
+        {
+            dfRefPixel = dfX;
+            dfRefLine = dfY;
+        }
+        else
+        {
+            RPCTransformPoint( psTransform, dfRefLong, dfRefLat, 0.0,
+                               &dfRefPixel, &dfRefLine );
+        }
     }
 
     // Try with scale and offset if we don't can't use bounds or
-    // the results seem daft. 
+    // the results seem daft.
     if( dfRefPixel < 0.0 || dfRefLine < 0.0
         || dfRefPixel > 100000 || dfRefLine > 100000 )
     {
         dfRefLong = psRPCInfo->dfLONG_OFF;
         dfRefLat  = psRPCInfo->dfLAT_OFF;
 
-        RPCTransformPoint( psRPCInfo, dfRefLong, dfRefLat, 0.0, 
-                           &dfRefPixel, &dfRefLine );
+        double dfX = dfRefLong;
+        double dfY = dfRefLat;
+        double dfZ = 0;
+        int nSuccess;
+        // Try with DEM first
+        if( GDALRPCTransform( psTransform, !(psTransform->bReversed), 1,
+                               &dfX, &dfY, &dfZ, &nSuccess) )
+        {
+            dfRefPixel = dfX;
+            dfRefLine = dfY;
+        }
+        else
+        {
+            RPCTransformPoint( psTransform, dfRefLong, dfRefLat, 0.0,
+                               &dfRefPixel, &dfRefLine );
+        }
     }
 
+    psTransform->dfRefZ = 0.0;
+    GDALRPCGetHeightAtLongLat(psTransform, dfRefLong, dfRefLat, &psTransform->dfRefZ);
+
 /* -------------------------------------------------------------------- */
 /*      Transform nearby locations to establish affine direction        */
 /*      vectors.                                                        */
 /* -------------------------------------------------------------------- */
     double dfRefPixelDelta, dfRefLineDelta, dfLLDelta = 0.0001;
 
-    RPCTransformPoint( psRPCInfo, dfRefLong+dfLLDelta, dfRefLat, 0.0, 
+    RPCTransformPoint( psTransform, dfRefLong+dfLLDelta, dfRefLat, psTransform->dfRefZ,
                        &dfRefPixelDelta, &dfRefLineDelta );
     adfGTFromLL[1] = (dfRefPixelDelta - dfRefPixel) / dfLLDelta;
     adfGTFromLL[4] = (dfRefLineDelta - dfRefLine) / dfLLDelta;
-    
-    RPCTransformPoint( psRPCInfo, dfRefLong, dfRefLat+dfLLDelta, 0.0, 
+
+    RPCTransformPoint( psTransform, dfRefLong, dfRefLat+dfLLDelta, psTransform->dfRefZ,
                        &dfRefPixelDelta, &dfRefLineDelta );
     adfGTFromLL[2] = (dfRefPixelDelta - dfRefPixel) / dfLLDelta;
     adfGTFromLL[5] = (dfRefLineDelta - dfRefLine) / dfLLDelta;
@@ -555,7 +822,7 @@ void *GDALCreateRPCTransformer( GDALRPCInfo *psRPCInfo, int bReversed,
         - adfGTFromLL[1] * dfRefLong - adfGTFromLL[2] * dfRefLat;
     adfGTFromLL[3] = dfRefLine
         - adfGTFromLL[4] * dfRefLong - adfGTFromLL[5] * dfRefLat;
-    
+
     if( !GDALInvGeoTransform( adfGTFromLL, psTransform->adfPLToLatLongGeoTransform) )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Cannot invert geotransform");
@@ -583,6 +850,7 @@ void GDALDestroyRPCTransformer( void *pTransformAlg )
         GDALClose(psTransform->poDS);
     if(psTransform->poCT)
         OCTDestroyCoordinateTransformation((OGRCoordinateTransformationH)psTransform->poCT);
+    CPLFree( psTransform->pszRPCInverseLog );
 
     CPLFree( pTransformAlg );
 }
@@ -591,15 +859,18 @@ void GDALDestroyRPCTransformer( void *pTransformAlg )
 /*                      RPCInverseTransformPoint()                      */
 /************************************************************************/
 
-static void 
-RPCInverseTransformPoint( GDALRPCTransformInfo *psTransform,
-                          double dfPixel, double dfLine, double dfHeight, 
+static bool
+RPCInverseTransformPoint( const GDALRPCTransformInfo *psTransform,
+                          double dfPixel, double dfLine, double dfUserHeight,
                           double *pdfLong, double *pdfLat )
 
 {
+    // Memo:
+    // Known to work with 40 iterations with DEM on all points (int coord and +0.5,+0.5 shift)
+    // of flock1.20160216_041050_0905.tif, especially on (0,0)
+
     double dfResultX, dfResultY;
     int    iIter;
-    GDALRPCInfo *psRPC = &(psTransform->sRPC);
 
 /* -------------------------------------------------------------------- */
 /*      Compute an initial approximation based on linear                */
@@ -613,50 +884,200 @@ RPCInverseTransformPoint( GDALRPCTransformInfo *psTransform,
         + psTransform->adfPLToLatLongGeoTransform[4] * dfPixel
         + psTransform->adfPLToLatLongGeoTransform[5] * dfLine;
 
+    if( psTransform->bRPCInverseVerbose )
+    {
+        CPLDebug("RPC", "Computing inverse transform for (pixel,line)=(%f,%f)",
+                 dfPixel, dfLine);
+    }
+    VSILFILE* fpLog = NULL;
+    if( psTransform->pszRPCInverseLog )
+    {
+        fpLog = VSIFOpenL( CPLResetExtension(psTransform->pszRPCInverseLog, "csvt"), "wb" );
+        if( fpLog != NULL )
+        {
+            VSIFPrintfL( fpLog, "Integer,Real,Real,Real,String,Real,Real\n" );
+            VSIFCloseL( fpLog );
+        }
+        fpLog = VSIFOpenL( psTransform->pszRPCInverseLog, "wb" );
+        if( fpLog != NULL )
+            VSIFPrintfL( fpLog, "iter,long,lat,height,WKT,error_pixel_x,error_pixel_y\n" );
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Now iterate, trying to find a closer LL location that will      */
 /*      back transform to the indicated pixel and line.                 */
 /* -------------------------------------------------------------------- */
     double dfPixelDeltaX=0.0, dfPixelDeltaY=0.0;
-
-    for( iIter = 0; iIter < 10; iIter++ )
+    double dfLastResultX = 0.0, dfLastResultY = 0.0;
+    double dfLastPixelDeltaX = 0.0, dfLastPixelDeltaY = 0.0;
+    double dfDEMH = 0.0;
+    bool bLastPixelDeltaValid = false;
+    const int nMaxIterations = (psTransform->nMaxIterations > 0) ? psTransform->nMaxIterations :
+                               (psTransform->poDS != NULL) ? 20 : 10;
+    int nCountConsecutiveErrorBelow2 = 0;
+
+    for( iIter = 0; iIter < nMaxIterations; iIter++ )
     {
         double dfBackPixel, dfBackLine;
 
-        RPCTransformPoint( psRPC, dfResultX, dfResultY, dfHeight, 
+        // Update DEMH
+        dfDEMH = 0;
+        double dfDEMPixel = 0.0, dfDEMLine = 0.0;
+        if( !GDALRPCGetHeightAtLongLat(psTransform, dfResultX, dfResultY,
+                                        &dfDEMH, &dfDEMPixel, &dfDEMLine) )
+        {
+            if( psTransform->poDS )
+            {
+                CPLDebug("RPC", "DEM (pixel, line) = (%g, %g)", dfDEMPixel, dfDEMLine);
+            }
+
+            // The first time, the guess might be completely out of the
+            // validity of the DEM, so pickup the "reference Z" as the
+            // first guess or the closest point of the DEM by snapping to it
+            if( iIter == 0 )
+            {
+                bool bUseRefZ = true;
+                if( psTransform->poDS )
+                {
+                    if( dfDEMPixel >= psTransform->poDS->GetRasterXSize() )
+                        dfDEMPixel = psTransform->poDS->GetRasterXSize() - 0.5;
+                    else if( dfDEMPixel < 0 )
+                        dfDEMPixel = 0.5;
+                    if( dfDEMLine >= psTransform->poDS->GetRasterYSize() )
+                        dfDEMLine = psTransform->poDS->GetRasterYSize() - 0.5;
+                    else if( dfDEMPixel < 0 )
+                        dfDEMPixel = 0.5;
+                    if( GDALRPCGetDEMHeight( psTransform, dfDEMPixel, dfDEMLine, &dfDEMH) )
+                    {
+                        bUseRefZ = false;
+                        CPLDebug("RPC", "Iteration %d for (pixel, line) = (%g, %g): "
+                                "No elevation value at %.15g %.15g. "
+                                "Using elevation %g at DEM (pixel, line) = (%g, %g) (snapping to boundaries) instead",
+                                iIter, dfPixel, dfLine,
+                                dfResultX, dfResultY,
+                                dfDEMH, dfDEMPixel, dfDEMLine );
+                    }
+                }
+                if( bUseRefZ )
+                {
+                    dfDEMH = psTransform->dfRefZ;
+                    CPLDebug("RPC", "Iteration %d for (pixel, line) = (%g, %g): "
+                            "No elevation value at %.15g %.15g. "
+                            "Using elevation %g of reference point instead",
+                            iIter, dfPixel, dfLine,
+                            dfResultX, dfResultY,
+                            dfDEMH);
+                }
+            }
+            else
+            {
+                CPLDebug("RPC", "Iteration %d for (pixel, line) = (%g, %g): "
+                          "No elevation value at %.15g %.15g. Erroring out",
+                          iIter, dfPixel, dfLine, dfResultX, dfResultY);
+                if( fpLog )
+                    VSIFCloseL(fpLog);
+                return false;
+            }
+        }
+
+        RPCTransformPoint( psTransform, dfResultX, dfResultY,
+                           dfUserHeight + dfDEMH,
                            &dfBackPixel, &dfBackLine );
 
         dfPixelDeltaX = dfBackPixel - dfPixel;
         dfPixelDeltaY = dfBackLine - dfLine;
 
-        dfResultX = dfResultX 
-            - dfPixelDeltaX * psTransform->adfPLToLatLongGeoTransform[1]
-            - dfPixelDeltaY * psTransform->adfPLToLatLongGeoTransform[2];
-        dfResultY = dfResultY 
-            - dfPixelDeltaX * psTransform->adfPLToLatLongGeoTransform[4]
-            - dfPixelDeltaY * psTransform->adfPLToLatLongGeoTransform[5];
+        if( psTransform->bRPCInverseVerbose )
+        {
+            CPLDebug( "RPC", "Iter %d: dfPixelDeltaX=%.02f, dfPixelDeltaY=%.02f, long=%f, lat=%f, height=%f",
+                      iIter, dfPixelDeltaX, dfPixelDeltaY,
+                      dfResultX, dfResultY, dfUserHeight + dfDEMH);
+        }
+        if( fpLog != NULL )
+        {
+            VSIFPrintfL( fpLog, "%d,%.12f,%.12f,%f,\"POINT(%.12f %.12f)\",%f,%f\n",
+                         iIter, dfResultX, dfResultY, dfUserHeight + dfDEMH,
+                         dfResultX, dfResultY, dfPixelDeltaX, dfPixelDeltaY);
+        }
 
-        if( ABS(dfPixelDeltaX) < psTransform->dfPixErrThreshold
-            && ABS(dfPixelDeltaY) < psTransform->dfPixErrThreshold )
+        double dfError = MAX(ABS(dfPixelDeltaX), ABS(dfPixelDeltaY));
+        if( dfError < psTransform->dfPixErrThreshold )
         {
             iIter = -1;
-            //CPLDebug( "RPC", "Converged!" );
+            if( psTransform->bRPCInverseVerbose )
+            {
+                CPLDebug( "RPC", "Converged!" );
+            }
             break;
         }
+        else if( psTransform->poDS != NULL &&
+                 bLastPixelDeltaValid && dfPixelDeltaX * dfLastPixelDeltaX < 0 &&
+                 dfPixelDeltaY * dfLastPixelDeltaY < 0 )
+        {
+            // When there is a DEM, if the error changes sign, we might oscillate
+            // forever, so take a mean position as a new guess
+            if( psTransform->bRPCInverseVerbose )
+            {
+                CPLDebug( "RPC", "Oscillation detected. Taking mean of 2 previous results as new guess" );
+            }
+            dfResultX = ( fabs(dfPixelDeltaX) * dfLastResultX + fabs(dfLastPixelDeltaX) * dfResultX ) /
+                          (fabs(dfPixelDeltaX) + fabs(dfLastPixelDeltaX));
+            dfResultY = ( fabs(dfPixelDeltaY) * dfLastResultY + fabs(dfLastPixelDeltaY) * dfResultY ) /
+                          (fabs(dfPixelDeltaY) + fabs(dfLastPixelDeltaY));
+            bLastPixelDeltaValid = false;
+            nCountConsecutiveErrorBelow2 = 0;
+            continue;
+        }
+
+        double dfBoostFactor = 1.0;
+        if( psTransform->poDS != NULL && nCountConsecutiveErrorBelow2 >= 5 && dfError < 2 )
+        {
+          // When there is a DEM, if we remain below a given threshold (somewhat
+          // arbitrarily set to 2 pixels) for some time, apply a "boost factor"
+          // for the new guessed result, in the hope we will go out of the
+          // somewhat current stuck situation
+          dfBoostFactor = 10;
+          if( psTransform->bRPCInverseVerbose )
+          {
+              CPLDebug("RPC", "Applying boost factor 10");
+          }
+        }
+
+        if ( dfError < 2 )
+            nCountConsecutiveErrorBelow2 ++;
+        else
+            nCountConsecutiveErrorBelow2 = 0;
+
+        double dfNewResultX = dfResultX
+            - dfPixelDeltaX * psTransform->adfPLToLatLongGeoTransform[1] * dfBoostFactor
+            - dfPixelDeltaY * psTransform->adfPLToLatLongGeoTransform[2] * dfBoostFactor;
+        double dfNewResultY = dfResultY
+            - dfPixelDeltaX * psTransform->adfPLToLatLongGeoTransform[4] * dfBoostFactor
+            - dfPixelDeltaY * psTransform->adfPLToLatLongGeoTransform[5] * dfBoostFactor;
+
+        dfLastResultX = dfResultX;
+        dfLastResultY = dfResultY;
+        dfResultX = dfNewResultX;
+        dfResultY = dfNewResultY;
+        dfLastPixelDeltaX = dfPixelDeltaX;
+        dfLastPixelDeltaY = dfPixelDeltaY;
+        bLastPixelDeltaValid = true;
     }
+    if( fpLog != NULL )
+        VSIFCloseL( fpLog );
 
     if( iIter != -1 )
     {
-#ifdef notdef
-        CPLDebug( "RPC", "Failed Iterations %d: Got: %g,%g  Offset=%g,%g", 
-                  iIter, 
+        CPLDebug( "RPC", "Failed Iterations %d: Got: %.16g,%.16g  Offset=%g,%g",
+                  iIter,
                   dfResultX, dfResultY,
                   dfPixelDeltaX, dfPixelDeltaY );
-#endif
+        return false;
     }
-    
+
     *pdfLong = dfResultX;
     *pdfLat = dfResultY;
+    return true;
 }
 
 
@@ -665,17 +1086,17 @@ double BiCubicKernel(double dfVal)
 {
 	if ( dfVal > 2.0 )
 		return 0.0;
-	
+
 	double a, b, c, d;
 	double xm1 = dfVal - 1.0;
 	double xp1 = dfVal + 1.0;
 	double xp2 = dfVal + 2.0;
-	
+
 	a = ( xp2 <= 0.0 ) ? 0.0 : xp2 * xp2 * xp2;
 	b = ( xp1 <= 0.0 ) ? 0.0 : xp1 * xp1 * xp1;
 	c = ( dfVal   <= 0.0 ) ? 0.0 : dfVal * dfVal * dfVal;
 	d = ( xm1 <= 0.0 ) ? 0.0 : xm1 * xm1 * xm1;
-	
+
 	return ( 0.16666666666666666667 * ( a - ( 4.0 * b ) + ( 6.0 * c ) - ( 4.0 * d ) ) );
 }
 
@@ -684,25 +1105,20 @@ double BiCubicKernel(double dfVal)
 /************************************************************************/
 
 static
-int GDALRPCGetDEMHeight( GDALRPCTransformInfo *psTransform,
-                      double dfX, double dfY, double* pdfDEMH )
+int GDALRPCGetDEMHeight( const GDALRPCTransformInfo *psTransform,
+                         const double dfXIn, const double dfYIn, double* pdfDEMH )
 {
-    
-    int bGotNoDataValue = FALSE;
-    double dfNoDataValue = 0;
     int nRasterXSize = psTransform->poDS->GetRasterXSize();
     int nRasterYSize = psTransform->poDS->GetRasterYSize();
-    dfNoDataValue = psTransform->poDS->GetRasterBand(1)->GetNoDataValue( &bGotNoDataValue );
-
+    int bGotNoDataValue = FALSE;
+    double dfNoDataValue = psTransform->poDS->GetRasterBand(1)->GetNoDataValue( &bGotNoDataValue );
     int bands[1] = {1};
 
-    double dfDEMH(0);
-
     if(psTransform->eResampleAlg == DRA_Cubic)
     {
         // convert from upper left corner of pixel coordinates to center of pixel coordinates:
-        dfX -= 0.5;
-        dfY -= 0.5;
+        double dfX = dfXIn - 0.5;
+        double dfY = dfYIn - 0.5;
         int dX = int(dfX);
         int dY = int(dfY);
         double dfDeltaX = dfX - dX;
@@ -712,7 +1128,7 @@ int GDALRPCGetDEMHeight( GDALRPCTransformInfo *psTransform,
         int dYNew = dY - 1;
         if (!(dXNew >= 0 && dYNew >= 0 && dXNew + 4 <= nRasterXSize && dYNew + 4 <= nRasterYSize))
         {
-            return FALSE;
+            goto bilinear_fallback;
         }
         //cubic interpolation
         double adfElevData[16] = {0};
@@ -752,13 +1168,17 @@ int GDALRPCGetDEMHeight( GDALRPCTransformInfo *psTransform,
         {
             return FALSE;
         }
-        dfDEMH = dfSumH / dfSumWeight;
+
+        *pdfDEMH = dfSumH / dfSumWeight;
+
+        return TRUE;
     }
     else if(psTransform->eResampleAlg == DRA_Bilinear)
     {
+bilinear_fallback:
         // convert from upper left corner of pixel coordinates to center of pixel coordinates:
-        dfX -= 0.5;
-        dfY -= 0.5;
+        double dfX = dfXIn - 0.5;
+        double dfY = dfYIn - 0.5;
         int dX = int(dfX);
         int dY = int(dfY);
         double dfDeltaX = dfX - dX;
@@ -766,7 +1186,7 @@ int GDALRPCGetDEMHeight( GDALRPCTransformInfo *psTransform,
 
         if (!(dX >= 0 && dY >= 0 && dX + 2 <= nRasterXSize && dY + 2 <= nRasterYSize))
         {
-            return FALSE;
+            goto near_fallback;
         }
         //bilinear interpolation
         double adfElevData[4] = {0,0,0,0};
@@ -792,53 +1212,57 @@ int GDALRPCGetDEMHeight( GDALRPCTransformInfo *psTransform,
                 return FALSE;
             }
         }
-        double dfDeltaX1 = 1.0 - dfDeltaX;                
+        double dfDeltaX1 = 1.0 - dfDeltaX;
         double dfDeltaY1 = 1.0 - dfDeltaY;
 
         double dfXZ1 = adfElevData[0] * dfDeltaX1 + adfElevData[1] * dfDeltaX;
         double dfXZ2 = adfElevData[2] * dfDeltaX1 + adfElevData[3] * dfDeltaX;
         double dfYZ = dfXZ1 * dfDeltaY1 + dfXZ2 * dfDeltaY;
-        dfDEMH = dfYZ;
+
+        *pdfDEMH = dfYZ;
+
+        return TRUE;
     }
     else
     {
-        int dX = (int) (dfX);
-        int dY = (int) (dfY);
+near_fallback:
+        int dX = (int) (dfXIn);
+        int dY = (int) (dfYIn);
         if (!(dX >= 0 && dY >= 0 && dX < nRasterXSize && dY < nRasterYSize))
         {
             return FALSE;
         }
+        double dfDEMH(0);
         CPLErr eErr = psTransform->poDS->RasterIO(GF_Read, dX, dY, 1, 1,
                                                     &dfDEMH, 1, 1,
                                                     GDT_Float64, 1, bands, 0, 0, 0,
-                                                  NULL);
+                                                    NULL);
         if(eErr != CE_None ||
             (bGotNoDataValue && ARE_REAL_EQUAL(dfNoDataValue, dfDEMH)) )
         {
             return FALSE;
         }
-    }
-    
-    *pdfDEMH = dfDEMH;
 
-    return TRUE;
+        *pdfDEMH = dfDEMH;
+
+        return TRUE;
+    }
 }
 
 /************************************************************************/
 /*                    GDALRPCTransformWholeLineWithDEM()                */
 /************************************************************************/
 
-static int GDALRPCTransformWholeLineWithDEM( GDALRPCTransformInfo *psTransform, 
-                                             int nPointCount, 
+static int GDALRPCTransformWholeLineWithDEM( const GDALRPCTransformInfo *psTransform,
+                                             int nPointCount,
                                              double *padfX, double *padfY, double *padfZ,
                                              int *panSuccess,
                                              int nXLeft, int nXWidth,
                                              int nYTop, int nYHeight )
 {
     int i;
-    GDALRPCInfo *psRPC = &(psTransform->sRPC);
 
-    double* padfDEMBuffer = (double*) VSIMalloc2(sizeof(double), nXWidth * nYHeight);
+    double* padfDEMBuffer = (double*) VSI_MALLOC2_VERBOSE(sizeof(double), nXWidth * nYHeight);
     if( padfDEMBuffer == NULL )
     {
         for( i = 0; i < nPointCount; i++ )
@@ -949,9 +1373,9 @@ static int GDALRPCTransformWholeLineWithDEM( GDALRPCTransformInfo *psTransform,
                     if( k_valid_sample >= 0 )
                     {
                         dfDEMH = adfElevData[k_valid_sample];
-                        RPCTransformPoint( psRPC, padfX[i], padfY[i], 
+                        RPCTransformPoint( psTransform, padfX[i], padfY[i],
                             padfZ[i] + (psTransform->dfHeightOffset + dfDEMH) *
-                                        psTransform->dfHeightScale, 
+                                        psTransform->dfHeightScale,
                             padfX + i, padfY + i );
 
                         panSuccess[i] = TRUE;
@@ -960,9 +1384,9 @@ static int GDALRPCTransformWholeLineWithDEM( GDALRPCTransformInfo *psTransform,
                     else if( psTransform->bHasDEMMissingValue )
                     {
                         dfDEMH = psTransform->dfDEMMissingValue;
-                        RPCTransformPoint( psRPC, padfX[i], padfY[i], 
+                        RPCTransformPoint( psTransform, padfX[i], padfY[i],
                             padfZ[i] + (psTransform->dfHeightOffset + dfDEMH) *
-                                        psTransform->dfHeightScale, 
+                                        psTransform->dfHeightScale,
                             padfX + i, padfY + i );
 
                         panSuccess[i] = TRUE;
@@ -975,7 +1399,7 @@ static int GDALRPCTransformWholeLineWithDEM( GDALRPCTransformInfo *psTransform,
                     }
                 }
             }
-            double dfDeltaX1 = 1.0 - dfDeltaX;                
+            double dfDeltaX1 = 1.0 - dfDeltaX;
             double dfDeltaY1 = 1.0 - dfDeltaY;
 
             double dfXZ1 = adfElevData[0] * dfDeltaX1 + adfElevData[1] * dfDeltaX;
@@ -1002,16 +1426,16 @@ static int GDALRPCTransformWholeLineWithDEM( GDALRPCTransformInfo *psTransform,
             }
         }
 
-        RPCTransformPoint( psRPC, padfX[i], padfY[i], 
+        RPCTransformPoint( psTransform, padfX[i], padfY[i],
                             padfZ[i] + (psTransform->dfHeightOffset + dfDEMH) *
-                                        psTransform->dfHeightScale, 
+                                        psTransform->dfHeightScale,
                             padfX + i, padfY + i );
 
         panSuccess[i] = TRUE;
     }
 
     VSIFree(padfDEMBuffer);
-    
+
     return TRUE;
 }
 
@@ -1019,8 +1443,8 @@ static int GDALRPCTransformWholeLineWithDEM( GDALRPCTransformInfo *psTransform,
 /*                          GDALRPCTransform()                          */
 /************************************************************************/
 
-int GDALRPCTransform( void *pTransformArg, int bDstToSrc, 
-                      int nPointCount, 
+int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
+                      int nPointCount,
                       double *padfX, double *padfY, double *padfZ,
                       int *panSuccess )
 
@@ -1028,20 +1452,26 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
     VALIDATE_POINTER1( pTransformArg, "GDALRPCTransform", 0 );
 
     GDALRPCTransformInfo *psTransform = (GDALRPCTransformInfo *) pTransformArg;
-    GDALRPCInfo *psRPC = &(psTransform->sRPC);
     int i;
 
     if( psTransform->bReversed )
         bDstToSrc = !bDstToSrc;
 
 /* -------------------------------------------------------------------- */
-/*      Lazy opening of the optionnal DEM file.                         */
+/*      Lazy opening of the optional DEM file.                          */
 /* -------------------------------------------------------------------- */
     if(psTransform->pszDEMPath != NULL &&
        psTransform->bHasTriedOpeningDS == FALSE)
     {
         int bIsValid = FALSE;
         psTransform->bHasTriedOpeningDS = TRUE;
+        CPLString osPrevValueConfigOption;
+        if( psTransform->bApplyDEMVDatumShift )
+        {
+            osPrevValueConfigOption
+                = CPLGetThreadLocalConfigOption("GTIFF_REPORT_COMPD_CS", "");
+            CPLSetThreadLocalConfigOption("GTIFF_REPORT_COMPD_CS", "YES");
+        }
         psTransform->poDS = (GDALDataset *)
                                 GDALOpen( psTransform->pszDEMPath, GA_ReadOnly );
         if(psTransform->poDS != NULL && psTransform->poDS->GetRasterCount() >= 1)
@@ -1051,11 +1481,54 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
             {
                 OGRSpatialReference* poWGSSpaRef =
                         new OGRSpatialReference(SRS_WKT_WGS84);
+
                 OGRSpatialReference* poDSSpaRef =
                         new OGRSpatialReference(pszSpatialRef);
+                if( !psTransform->bApplyDEMVDatumShift )
+                    poDSSpaRef->StripVertical();
+
                 if(!poWGSSpaRef->IsSame(poDSSpaRef))
                     psTransform->poCT =OGRCreateCoordinateTransformation(
                                                     poWGSSpaRef, poDSSpaRef );
+
+                if( psTransform->poCT != NULL && !poDSSpaRef->IsCompound() )
+                {
+                    // Empiric attempt to guess if the coordinate transformation
+                    // to WGS84 is a no-op. For example for NED13 datasets in NAD83
+                    double adfX[] = { -179, 179, 179, -179, 0, 0 };
+                    double adfY[] = { 89, 89, -89, -89, 0, 0 };
+                    double adfZ[] = { 0, 0, 0, 0, 0, 0 };
+
+                    // Also test with a "reference point" from the RPC values
+                    double dfRefLong, dfRefLat;
+                    if( psTransform->sRPC.dfMIN_LONG != -180 || psTransform->sRPC.dfMAX_LONG != 180 )
+                    {
+                        dfRefLong = (psTransform->sRPC.dfMIN_LONG + psTransform->sRPC.dfMAX_LONG) * 0.5;
+                        dfRefLat  = (psTransform->sRPC.dfMIN_LAT  + psTransform->sRPC.dfMAX_LAT ) * 0.5;
+                    }
+                    else
+                    {
+                        dfRefLong = psTransform->sRPC.dfLONG_OFF;
+                        dfRefLat  = psTransform->sRPC.dfLAT_OFF;
+                    }
+                    adfX[5] = dfRefLong;
+                    adfY[5] = dfRefLat;
+
+                    if( psTransform->poCT->Transform(
+                                                6, adfX, adfY, adfZ) &&
+                        fabs(adfX[0] - -179) < 1e-12 && fabs(adfY[0] -  89) < 1e-12 &&
+                        fabs(adfX[1] -  179) < 1e-12 && fabs(adfY[1] -  89) < 1e-12 &&
+                        fabs(adfX[2] -  179) < 1e-12 && fabs(adfY[2] - -89) < 1e-12 &&
+                        fabs(adfX[3] - -179) < 1e-12 && fabs(adfY[3] - -89) < 1e-12 &&
+                        fabs(adfX[4] -    0) < 1e-12 && fabs(adfY[4] -   0) < 1e-12 &&
+                        fabs(adfX[5] - dfRefLong) < 1e-12 && fabs(adfY[5] - dfRefLat) < 1e-12 )
+                    {
+                        CPLDebug("RPC", "Short-circuiting coordinate transformation from DEM SRS to WGS 84 due to apparent nop");
+                        delete psTransform->poCT;
+                        psTransform->poCT = NULL;
+                    }
+                }
+
                 delete poWGSSpaRef;
                 delete poDSSpaRef;
             }
@@ -1069,6 +1542,12 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
             }
         }
 
+        if( psTransform->bApplyDEMVDatumShift )
+        {
+            CPLSetThreadLocalConfigOption("GTIFF_REPORT_COMPD_CS",
+                osPrevValueConfigOption.size() ? osPrevValueConfigOption.c_str() : NULL);
+        }
+
         if (!bIsValid && psTransform->poDS != NULL)
         {
             GDALClose(psTransform->poDS);
@@ -1090,11 +1569,11 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
         /* of EPSG:4326 or EPSG:3857 */
         if( nPointCount >= 10 && psTransform->poDS != NULL &&
             psTransform->poCT == NULL && padfY[0] == padfY[nPointCount-1] &&
-            padfY[0] == padfY[nPointCount/ 2] && 
+            padfY[0] == padfY[nPointCount/ 2] &&
             psTransform->adfDEMReverseGeoTransform[1] > 0.0 &&
-            psTransform->adfDEMReverseGeoTransform[2] == 0.0 && 
+            psTransform->adfDEMReverseGeoTransform[2] == 0.0 &&
             psTransform->adfDEMReverseGeoTransform[4] == 0.0 &&
-            CSLTestBoolean(CPLGetConfigOption("GDAL_RPC_DEM_OPTIM", "YES")) )
+            CPLTestBool(CPLGetConfigOption("GDAL_RPC_DEM_OPTIM", "YES")) )
         {
             int bUseOptimized = TRUE;
             double dfMinX = padfX[0], dfMaxX = padfX[0];
@@ -1154,7 +1633,7 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
                         bOnce = TRUE;
                         CPLDebug("RPC", "Using GDALRPCTransformWholeLineWithDEM");
                     }
-                    return GDALRPCTransformWholeLineWithDEM( psTransform, nPointCount, 
+                    return GDALRPCTransformWholeLineWithDEM( psTransform, nPointCount,
                                                              padfX, padfY, padfZ,
                                                              panSuccess,
                                                              nXLeft, nXWidth,
@@ -1162,53 +1641,20 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
                 }
             }
         }
-        
+
         for( i = 0; i < nPointCount; i++ )
         {
-            if(psTransform->poDS)
+            double dfHeight = 0.0;
+            if( !GDALRPCGetHeightAtLongLat( psTransform, padfX[i], padfY[i],
+                                            &dfHeight ) )
             {
-                double dfX, dfY;
-                //check if dem is not in WGS84 and transform points padfX[i], padfY[i]
-                if(psTransform->poCT)
-                {
-                    double dfXOrig = padfX[i];
-                    double dfYOrig = padfY[i];
-                    double dfZOrig = padfZ[i];
-                    if (!psTransform->poCT->Transform(
-                                                1, &dfXOrig, &dfYOrig, &dfZOrig))
-                    {
-                        panSuccess[i] = FALSE;
-                        continue;
-                    }
-                    GDALApplyGeoTransform( psTransform->adfDEMReverseGeoTransform,
-                                           dfXOrig, dfYOrig, &dfX, &dfY );
-                }
-                else
-                    GDALApplyGeoTransform( psTransform->adfDEMReverseGeoTransform,
-                                           padfX[i], padfY[i], &dfX, &dfY );
-
-                double dfDEMH(0);
-                if( !GDALRPCGetDEMHeight( psTransform, dfX, dfY, &dfDEMH) )
-                {
-                    if( psTransform->bHasDEMMissingValue )
-                        dfDEMH = psTransform->dfDEMMissingValue;
-                    else
-                    {
-                        panSuccess[i] = FALSE;
-                        continue;
-                    }
-                }
-
-                RPCTransformPoint( psRPC, padfX[i], padfY[i], 
-                                   padfZ[i] + (psTransform->dfHeightOffset + dfDEMH) *
-                                                psTransform->dfHeightScale, 
-                                   padfX + i, padfY + i );
+                panSuccess[i] = FALSE;
+                continue;
             }
-            else
-                RPCTransformPoint( psRPC, padfX[i], padfY[i], 
-                                   padfZ[i] + psTransform->dfHeightOffset *
-                                              psTransform->dfHeightScale, 
-                                   padfX + i, padfY + i );
+
+            RPCTransformPoint( psTransform, padfX[i], padfY[i],
+                                padfZ[i] + dfHeight,
+                                padfX + i, padfY + i );
             panSuccess[i] = TRUE;
         }
 
@@ -1224,53 +1670,14 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
     {
         double dfResultX, dfResultY;
 
-        if(psTransform->poDS)
+        if( !RPCInverseTransformPoint( psTransform, padfX[i], padfY[i],
+                    padfZ[i],
+                    &dfResultX, &dfResultY ) )
         {
-            RPCInverseTransformPoint( psTransform, padfX[i], padfY[i], 
-                      padfZ[i] + psTransform->dfHeightOffset *
-                                 psTransform->dfHeightScale,
-                      &dfResultX, &dfResultY );
-
-            double dfX, dfY;
-            //check if dem is not in WGS84 and transform points padfX[i], padfY[i]
-            if(psTransform->poCT)
-            {
-                double dfZ = 0;
-                if (!psTransform->poCT->Transform(1, &dfResultX, &dfResultY, &dfZ))
-                {
-                    panSuccess[i] = FALSE;
-                    continue;
-                }
-            }
-
-            GDALApplyGeoTransform( psTransform->adfDEMReverseGeoTransform,
-                                    dfResultX, dfResultY, &dfX, &dfY );
-
-            double dfDEMH(0);
-            if( !GDALRPCGetDEMHeight( psTransform, dfX, dfY, &dfDEMH) )
-            {
-                if( psTransform->bHasDEMMissingValue )
-                    dfDEMH = psTransform->dfDEMMissingValue;
-                else
-                {
-                    panSuccess[i] = FALSE;
-                    continue;
-                }
-            }
-
-            RPCInverseTransformPoint( psTransform, padfX[i], padfY[i], 
-                                      padfZ[i] + (psTransform->dfHeightOffset + dfDEMH) *
-                                                  psTransform->dfHeightScale,
-                                      &dfResultX, &dfResultY );
+            panSuccess[i] = FALSE;
+            continue;
         }
-        else
-        {
-            RPCInverseTransformPoint( psTransform, padfX[i], padfY[i], 
-                                      padfZ[i] + psTransform->dfHeightOffset *
-                                                 psTransform->dfHeightScale,
-                                      &dfResultX, &dfResultY );
 
-        }
         padfX[i] = dfResultX;
         padfY[i] = dfResultY;
 
@@ -1290,7 +1697,7 @@ CPLXMLNode *GDALSerializeRPCTransformer( void *pTransformArg )
     VALIDATE_POINTER1( pTransformArg, "GDALSerializeRPCTransformer", NULL );
 
     CPLXMLNode *psTree;
-    GDALRPCTransformInfo *psInfo = 
+    GDALRPCTransformInfo *psInfo =
         (GDALRPCTransformInfo *)(pTransformArg);
 
     psTree = CPLCreateXMLNode( NULL, CXT_Element, "RPCTransformer" );
@@ -1298,23 +1705,23 @@ CPLXMLNode *GDALSerializeRPCTransformer( void *pTransformArg )
 /* -------------------------------------------------------------------- */
 /*      Serialize bReversed.                                            */
 /* -------------------------------------------------------------------- */
-    CPLCreateXMLElementAndValue( 
-        psTree, "Reversed", 
+    CPLCreateXMLElementAndValue(
+        psTree, "Reversed",
         CPLString().Printf( "%d", psInfo->bReversed ) );
 
 /* -------------------------------------------------------------------- */
 /*      Serialize Height Offset.                                        */
 /* -------------------------------------------------------------------- */
-    CPLCreateXMLElementAndValue( 
-        psTree, "HeightOffset", 
+    CPLCreateXMLElementAndValue(
+        psTree, "HeightOffset",
         CPLString().Printf( "%.15g", psInfo->dfHeightOffset ) );
 
 /* -------------------------------------------------------------------- */
 /*      Serialize Height Scale.                                         */
 /* -------------------------------------------------------------------- */
     if (psInfo->dfHeightScale != 1.0)
-        CPLCreateXMLElementAndValue( 
-            psTree, "HeightScale", 
+        CPLCreateXMLElementAndValue(
+            psTree, "HeightScale",
             CPLString().Printf( "%.15g", psInfo->dfHeightScale ) );
 
 /* -------------------------------------------------------------------- */
@@ -1322,35 +1729,38 @@ CPLXMLNode *GDALSerializeRPCTransformer( void *pTransformArg )
 /* -------------------------------------------------------------------- */
     if (psInfo->pszDEMPath != NULL)
     {
-        CPLCreateXMLElementAndValue( 
-            psTree, "DEMPath", 
+        CPLCreateXMLElementAndValue(
+            psTree, "DEMPath",
             CPLString().Printf( "%s", psInfo->pszDEMPath ) );
 
 /* -------------------------------------------------------------------- */
 /*      Serialize DEM interpolation                                     */
 /* -------------------------------------------------------------------- */
-        CPLCreateXMLElementAndValue( 
+        CPLCreateXMLElementAndValue(
             psTree, "DEMInterpolation", GDALSerializeRPCDEMResample(psInfo->eResampleAlg) );
 
         if( psInfo->bHasDEMMissingValue )
         {
-            CPLCreateXMLElementAndValue( 
+            CPLCreateXMLElementAndValue(
                 psTree, "DEMMissingValue", CPLSPrintf("%.18g", psInfo->dfDEMMissingValue) );
         }
+
+        CPLCreateXMLElementAndValue(
+                psTree, "DEMApplyVDatumShift", ( psInfo->bApplyDEMVDatumShift ) ? "true" : "false" );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Serialize pixel error threshold.                                */
 /* -------------------------------------------------------------------- */
-    CPLCreateXMLElementAndValue( 
-        psTree, "PixErrThreshold", 
+    CPLCreateXMLElementAndValue(
+        psTree, "PixErrThreshold",
         CPLString().Printf( "%.15g", psInfo->dfPixErrThreshold ) );
 
 /* -------------------------------------------------------------------- */
 /*      RPC metadata.                                                   */
 /* -------------------------------------------------------------------- */
     char **papszMD = RPCInfoToMD( &(psInfo->sRPC) );
-    CPLXMLNode *psMD= CPLCreateXMLNode( psTree, CXT_Element, 
+    CPLXMLNode *psMD= CPLCreateXMLNode( psTree, CXT_Element,
                                         "Metadata" );
 
     for( int i = 0; papszMD != NULL && papszMD[i] != NULL; i++ )
@@ -1358,13 +1768,13 @@ CPLXMLNode *GDALSerializeRPCTransformer( void *pTransformArg )
         const char *pszRawValue;
         char *pszKey;
         CPLXMLNode *psMDI;
-                
+
         pszRawValue = CPLParseNameValue( papszMD[i], &pszKey );
-                
+
         psMDI = CPLCreateXMLNode( psMD, CXT_Element, "MDI" );
         CPLSetXMLValue( psMDI, "#key", pszKey );
         CPLCreateXMLNode( psMDI, CXT_Text, pszRawValue );
-                
+
         CPLFree( pszKey );
     }
 
@@ -1396,21 +1806,21 @@ void *GDALDeserializeRPCTransformer( CPLXMLNode *psTree )
         || psMetadata->eType != CXT_Element
         || !EQUAL(psMetadata->pszValue,"Metadata") )
         return NULL;
-    
-    for( psMDI = psMetadata->psChild; psMDI != NULL; 
+
+    for( psMDI = psMetadata->psChild; psMDI != NULL;
          psMDI = psMDI->psNext )
     {
-        if( !EQUAL(psMDI->pszValue,"MDI") 
-            || psMDI->eType != CXT_Element 
-            || psMDI->psChild == NULL 
-            || psMDI->psChild->psNext == NULL 
+        if( !EQUAL(psMDI->pszValue,"MDI")
+            || psMDI->eType != CXT_Element
+            || psMDI->psChild == NULL
+            || psMDI->psChild->psNext == NULL
             || psMDI->psChild->eType != CXT_Attribute
             || psMDI->psChild->psChild == NULL )
             continue;
-        
-        papszMD = 
-            CSLSetNameValue( papszMD, 
-                             psMDI->psChild->psChild->pszValue, 
+
+        papszMD =
+            CSLSetNameValue( papszMD,
+                             psMDI->psChild->psChild->pszValue,
                              psMDI->psChild->psNext->pszValue );
     }
 
@@ -1432,7 +1842,7 @@ void *GDALDeserializeRPCTransformer( CPLXMLNode *psTree )
 
     bReversed = atoi(CPLGetXMLValue(psTree,"Reversed","0"));
 
-    dfPixErrThreshold = 
+    dfPixErrThreshold =
         CPLAtof(CPLGetXMLValue(psTree,"PixErrThreshold","0.25"));
 
     papszOptions = CSLSetNameValue( papszOptions, "RPC_HEIGHT",
@@ -1454,12 +1864,17 @@ void *GDALDeserializeRPCTransformer( CPLXMLNode *psTree )
         papszOptions = CSLSetNameValue( papszOptions, "RPC_DEM_MISSING_VALUE",
                                         pszDEMMissingValue);
 
+    const char* pszDEMApplyVDatumShift = CPLGetXMLValue(psTree,"DEMApplyVDatumShift", NULL);
+    if (pszDEMApplyVDatumShift != NULL)
+        papszOptions = CSLSetNameValue( papszOptions, "RPC_DEM_APPLY_VDATUM_SHIFT",
+                                        pszDEMApplyVDatumShift);
+
 /* -------------------------------------------------------------------- */
 /*      Generate transformation.                                        */
 /* -------------------------------------------------------------------- */
     pResult = GDALCreateRPCTransformer( &sRPC, bReversed, dfPixErrThreshold,
                                         papszOptions );
-    
+
     CSLDestroy( papszOptions );
 
     return pResult;
diff --git a/alg/gdal_simplesurf.cpp b/alg/gdal_simplesurf.cpp
index 754c136..c871b75 100644
--- a/alg/gdal_simplesurf.cpp
+++ b/alg/gdal_simplesurf.cpp
@@ -1,6 +1,6 @@
 /******************************************************************************
  * Project:  GDAL
- * Purpose:  Correlator - GDALSimpleSURF and GDALFeaturePoint classes. 
+ * Purpose:  Correlator - GDALSimpleSURF and GDALFeaturePoint classes.
  * Author:   Andrew Migal, migal.drew at gmail.com
  *
  ******************************************************************************
@@ -59,16 +59,16 @@ GDALFeaturePoint::GDALFeaturePoint(const GDALFeaturePoint& fp)
         padfDescriptor[i] = fp.padfDescriptor[i];
 }
 
-GDALFeaturePoint::GDALFeaturePoint(int nX, int nY,
-                                   int nScale, int nRadius, int nSign)
+GDALFeaturePoint::GDALFeaturePoint(int nXIn, int nYIn,
+                                   int nScaleIn, int nRadiusIn, int nSignIn)
 {
-    this->nX = nX;
-    this->nY = nY;
-    this->nScale = nScale;
-    this->nRadius = nRadius;
-    this->nSign = nSign;
+    nX = nXIn;
+    nY = nYIn;
+    nScale = nScaleIn;
+    nRadius = nRadiusIn;
+    nSign = nSignIn;
 
-    this->padfDescriptor = new double[DESC_SIZE];
+    padfDescriptor = new double[DESC_SIZE];
 }
 
 GDALFeaturePoint& GDALFeaturePoint::operator=(const GDALFeaturePoint& point)
@@ -94,19 +94,19 @@ GDALFeaturePoint& GDALFeaturePoint::operator=(const GDALFeaturePoint& point)
 }
 
 int  GDALFeaturePoint::GetX() { return nX; }
-void GDALFeaturePoint::SetX(int nX) { this->nX = nX; }
+void GDALFeaturePoint::SetX(int nXIn) { nX = nXIn; }
 
 int  GDALFeaturePoint::GetY() { return nY; }
-void GDALFeaturePoint::SetY(int nY) { this->nY = nY; }
+void GDALFeaturePoint::SetY(int nYIn) { nY = nYIn; }
 
 int  GDALFeaturePoint::GetScale() { return nScale; }
-void GDALFeaturePoint::SetScale(int nScale) { this->nScale = nScale; }
+void GDALFeaturePoint::SetScale(int nScaleIn) { nScale = nScaleIn; }
 
 int  GDALFeaturePoint::GetRadius() { return nRadius; }
-void GDALFeaturePoint::SetRadius(int nRadius) { this->nRadius = nRadius; }
+void GDALFeaturePoint::SetRadius(int nRadiusIn) { nRadius = nRadiusIn; }
 
 int  GDALFeaturePoint::GetSign() { return nSign; }
-void GDALFeaturePoint::SetSign(int nSign) { this->nSign = nSign; }
+void GDALFeaturePoint::SetSign(int nSignIn) { nSign = nSignIn; }
 
 double& GDALFeaturePoint::operator [] (int nIndex)
 {
@@ -170,20 +170,23 @@ CPLErr GDALSimpleSURF::ConvertRGBToLuminosity(
     GDALDataType eGreenType = green->GetRasterDataType();
     GDALDataType eBlueType = blue->GetRasterDataType();
 
-    int dataRedSize = GDALGetDataTypeSize(eRedType) / 8;
-    int dataGreenSize = GDALGetDataTypeSize(eGreenType) / 8;
-    int dataBlueSize = GDALGetDataTypeSize(eBlueType) / 8;
+    const int dataRedSize = GDALGetDataTypeSizeBytes(eRedType);
+    const int dataGreenSize = GDALGetDataTypeSizeBytes(eGreenType);
+    const int dataBlueSize = GDALGetDataTypeSizeBytes(eBlueType);
 
     void *paRedLayer = CPLMalloc(dataRedSize * nWidth * nHeight);
     void *paGreenLayer = CPLMalloc(dataGreenSize * nWidth * nHeight);
     void *paBlueLayer = CPLMalloc(dataBlueSize * nWidth * nHeight);
 
-    red->RasterIO(GF_Read, 0, 0, nXSize, nYSize, paRedLayer, nWidth, nHeight, eRedType, 0, 0, NULL);
-    green->RasterIO(GF_Read, 0, 0, nXSize, nYSize, paGreenLayer, nWidth, nHeight, eGreenType, 0, 0, NULL);
-    blue->RasterIO(GF_Read, 0, 0, nXSize, nYSize, paBlueLayer, nWidth, nHeight, eBlueType, 0, 0, NULL);
+    CPLErr eErr;
+    eErr = red->RasterIO(GF_Read, 0, 0, nXSize, nYSize, paRedLayer, nWidth, nHeight, eRedType, 0, 0, NULL);
+    if( eErr == CE_None )
+        eErr = green->RasterIO(GF_Read, 0, 0, nXSize, nYSize, paGreenLayer, nWidth, nHeight, eGreenType, 0, 0, NULL);
+    if( eErr == CE_None )
+        eErr = blue->RasterIO(GF_Read, 0, 0, nXSize, nYSize, paBlueLayer, nWidth, nHeight, eBlueType, 0, 0, NULL);
 
     double maxValue = 255.0;
-    for (int row = 0; row < nHeight; row++)
+    for (int row = 0; row < nHeight && eErr == CE_None; row++)
         for (int col = 0; col < nWidth; col++)
         {
             // Get RGB values
@@ -204,20 +207,20 @@ CPLErr GDALSimpleSURF::ConvertRGBToLuminosity(
     CPLFree(paGreenLayer);
     CPLFree(paBlueLayer);
 
-    return CE_None;
+    return eErr;
 }
 
 std::vector<GDALFeaturePoint>*
 GDALSimpleSURF::ExtractFeaturePoints(GDALIntegralImage *poImg,
                                      double dfThreshold)
 {
-    std::vector<GDALFeaturePoint>* poCollection = 
+    std::vector<GDALFeaturePoint>* poCollection =
         new std::vector<GDALFeaturePoint>();
 
     //Calc Hessian values for layers
     poOctMap->ComputeMap(poImg);
 
-    //Search for exremum points
+    // Search for extremum points.
     for (int oct = octaveStart; oct <= octaveEnd; oct++)
     {
         for (int k = 0; k < GDALOctaveMap::INTERVALS - 2; k++)
@@ -241,7 +244,7 @@ GDALSimpleSURF::ExtractFeaturePoints(GDALIntegralImage *poImg,
             }
         }
     }
-    
+
     return poCollection;
 }
 
@@ -365,8 +368,8 @@ CPLErr GDALSimpleSURF::MatchFeaturePoints(
 /* -------------------------------------------------------------------- */
     if (poMatchPairs == NULL)
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Matched points colection isn't specified");
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Matched points collection isn't specified" );
         return CE_Failure;
     }
 
@@ -383,8 +386,8 @@ CPLErr GDALSimpleSURF::MatchFeaturePoints(
     // Affects to false matching pruning
     const double ratioThreshold = 0.8;
 
-    int len_1 = poFirstCollect->size();
-    int len_2 = poSecondCollect->size();
+    int len_1 = static_cast<int>(poFirstCollect->size());
+    int len_2 = static_cast<int>(poSecondCollect->size());
 
     int minLength = (len_1 < len_2) ? len_1 : len_2;
 
@@ -511,6 +514,7 @@ CPLErr GDALSimpleSURF::MatchFeaturePoints(
 
     // Clean up
     delete[] alreadyMatched;
+    delete poPairInfoList;
 
     return CE_None;
 }
@@ -519,4 +523,3 @@ GDALSimpleSURF::~GDALSimpleSURF()
 {
     delete poOctMap;
 }
-
diff --git a/alg/gdal_simplesurf.h b/alg/gdal_simplesurf.h
index 1428e17..ca262dc 100644
--- a/alg/gdal_simplesurf.h
+++ b/alg/gdal_simplesurf.h
@@ -179,7 +179,7 @@ private:
  * @brief Integral image class (summed area table).
  * @details Integral image is a table for fast computing the sum of
  * values in rectangular subarea. In more detail, for 2-dimensional array
- * of numbers this class provides capabilty to get sum of values in
+ * of numbers this class provides capability to get sum of values in
  * rectangular arbitrary area with any size in constant time.
  * Integral image is constructed from grayscale picture.
  */
@@ -215,7 +215,7 @@ public:
      * @param nRow Row of left top point of rectangle
      * @param nCol Column of left top point of rectangle
      * @param nWidth Width of rectangular area (number of columns)
-     * @param nHeight Heigth of rectangular area (number of rows)
+     * @param nHeight Height of rectangular area (number of rows)
      *
      * @return Sum of values in specified grid.
      */
@@ -288,7 +288,7 @@ public:
     virtual ~GDALOctaveLayer();
 
     /**
-     * Perform calculation of Hessian determinats and their signs
+     * Perform calculation of Hessian determinants and their signs
      * for specified integral image. Result is stored internally.
      *
      * @param poImg Integral image object, which provides all necessary
diff --git a/alg/gdal_tps.cpp b/alg/gdal_tps.cpp
index a7274aa..6bf229c 100644
--- a/alg/gdal_tps.cpp
+++ b/alg/gdal_tps.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_tps.cpp 29207 2015-05-18 17:23:45Z mloskot $
+ * $Id: gdal_tps.cpp 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  High Performance Image Reprojector
  * Purpose:  Thin Plate Spline transformer (GDAL wrapper portion)
@@ -36,8 +36,9 @@
 #include "cpl_string.h"
 #include "cpl_atomic_ops.h"
 #include "cpl_multiproc.h"
+#include <map>
 
-CPL_CVSID("$Id: gdal_tps.cpp 29207 2015-05-18 17:23:45Z mloskot $");
+CPL_CVSID("$Id: gdal_tps.cpp 33715 2016-03-13 08:52:06Z goatbar $");
 
 CPL_C_START
 CPLXMLNode *GDALSerializeTPSTransformer( void *pTransformArg );
@@ -57,9 +58,9 @@ typedef struct
 
     int       nGCPCount;
     GDAL_GCP *pasGCPList;
-    
+
     volatile int nRefCount;
-    
+
 } TPSTransformInfo;
 
 /************************************************************************/
@@ -72,7 +73,7 @@ void* GDALCreateSimilarTPSTransformer( void *hTransformArg, double dfRatioX, dou
     VALIDATE_POINTER1( hTransformArg, "GDALCreateSimilarTPSTransformer", NULL );
 
     TPSTransformInfo *psInfo = (TPSTransformInfo *) hTransformArg;
-    
+
     if( dfRatioX == 1.0 && dfRatioY == 1.0 )
     {
         /* We can just use a ref count, since using the source transformation */
@@ -106,31 +107,31 @@ void* GDALCreateSimilarTPSTransformer( void *hTransformArg, double dfRatioX, dou
  *
  * The thin plate spline transformer produces exact transformation
  * at all control points and smoothly varying transformations between
- * control points with greatest influence from local control points. 
- * It is suitable for for many applications not well modelled by polynomial
- * transformations. 
+ * control points with greatest influence from local control points.
+ * It is suitable for for many applications not well modeled by polynomial
+ * transformations.
  *
  * Creating the TPS transformer involves solving systems of linear equations
  * related to the number of control points involved.  This solution is
  * computed within this function call.  It can be quite an expensive operation
- * for large numbers of GCPs.  For instance, for reference, it takes on the 
- * order of 10s for 400 GCPs on a 2GHz Athlon processor. 
+ * for large numbers of GCPs.  For instance, for reference, it takes on the
+ * order of 10s for 400 GCPs on a 2GHz Athlon processor.
  *
- * TPS Transformers are serializable. 
+ * TPS Transformers are serializable.
  *
  * The GDAL Thin Plate Spline transformer is based on code provided by
- * Gilad Ronnen on behalf of VIZRT Inc (http://www.visrt.com).  Incorporation 
- * of the algorithm into GDAL was supported by the Centro di Ecologia Alpina 
- * (http://www.cealp.it). 
+ * Gilad Ronnen on behalf of VIZRT Inc (http://www.visrt.com).  Incorporation
+ * of the algorithm into GDAL was supported by the Centro di Ecologia Alpina
+ * (http://www.cealp.it).
  *
  * @param nGCPCount the number of GCPs in pasGCPList.
  * @param pasGCPList an array of GCPs to be used as input.
  * @param bReversed set it to TRUE to compute the reversed transformation.
- * 
- * @return the transform argument or NULL if creation fails. 
+ *
+ * @return the transform argument or NULL if creation fails.
  */
 
-void *GDALCreateTPSTransformer( int nGCPCount, const GDAL_GCP *pasGCPList, 
+void *GDALCreateTPSTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
                                 int bReversed )
 {
     return GDALCreateTPSTransformerInt(nGCPCount, pasGCPList, bReversed, NULL);
@@ -142,7 +143,7 @@ static void GDALTPSComputeForwardInThread(void* pData)
     psInfo->bForwardSolved = psInfo->poForward->solve() != 0;
 }
 
-void *GDALCreateTPSTransformerInt( int nGCPCount, const GDAL_GCP *pasGCPList, 
+void *GDALCreateTPSTransformerInt( int nGCPCount, const GDAL_GCP *pasGCPList,
                                    int bReversed, char** papszOptions )
 
 {
@@ -171,6 +172,8 @@ void *GDALCreateTPSTransformerInt( int nGCPCount, const GDAL_GCP *pasGCPList,
 /* -------------------------------------------------------------------- */
 /*      Attach all the points to the transformation.                    */
 /* -------------------------------------------------------------------- */
+    std::map< std::pair<double, double>, int > oMapPixelLineToIdx;
+    std::map< std::pair<double, double>, int > oMapXYToIdx;
     for( iGCP = 0; iGCP < nGCPCount; iGCP++ )
     {
         double    afPL[2], afXY[2];
@@ -180,15 +183,60 @@ void *GDALCreateTPSTransformerInt( int nGCPCount, const GDAL_GCP *pasGCPList,
         afXY[0] = pasGCPList[iGCP].dfGCPX;
         afXY[1] = pasGCPList[iGCP].dfGCPY;
 
+        std::map< std::pair<double, double>, int >::iterator oIter;
+        oIter = oMapPixelLineToIdx.find( std::pair<double,double>(afPL[0], afPL[1]) );
+        if( oIter != oMapPixelLineToIdx.end() )
+        {
+            if( afXY[0] == pasGCPList[oIter->second].dfGCPX &&
+                afXY[1] == pasGCPList[oIter->second].dfGCPY )
+            {
+                continue;
+            }
+            else
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "GCP %d and %d have same (pixel,line)=(%f,%f) but different (X,Y): (%f,%f) vs (%f,%f)",
+                         iGCP + 1, oIter->second,
+                         afPL[0], afPL[1],
+                         afXY[0], afXY[1],
+                         pasGCPList[oIter->second].dfGCPX, pasGCPList[oIter->second].dfGCPY);
+            }
+        }
+        else
+        {
+            oMapPixelLineToIdx[ std::pair<double,double>(afPL[0], afPL[1]) ] = iGCP;
+        }
+
+        oIter = oMapXYToIdx.find( std::pair<double,double>(afXY[0], afXY[1]) );
+        if( oIter != oMapXYToIdx.end() )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                        "GCP %d and %d have same (x,y)=(%f,%f) but different (pixel,line): (%f,%f) vs (%f,%f)",
+                        iGCP + 1, oIter->second,
+                        afXY[0], afXY[1],
+                        afPL[0], afPL[1],
+                        pasGCPList[oIter->second].dfGCPPixel, pasGCPList[oIter->second].dfGCPLine);
+        }
+        else
+        {
+            oMapXYToIdx[ std::pair<double,double>(afXY[0], afXY[1]) ] = iGCP;
+        }
+
+        bool bOK = true;
         if( bReversed )
         {
-            psInfo->poReverse->add_point( afPL[0], afPL[1], afXY );
-            psInfo->poForward->add_point( afXY[0], afXY[1], afPL );
+            bOK &= psInfo->poReverse->add_point( afPL[0], afPL[1], afXY );
+            bOK &= psInfo->poForward->add_point( afXY[0], afXY[1], afPL );
         }
         else
         {
-            psInfo->poForward->add_point( afPL[0], afPL[1], afXY );
-            psInfo->poReverse->add_point( afXY[0], afXY[1], afPL );
+            bOK &= psInfo->poForward->add_point( afPL[0], afPL[1], afXY );
+            bOK &= psInfo->poReverse->add_point( afXY[0], afXY[1], afPL );
+        }
+        if( !bOK )
+        {
+            GDALDestroyTPSTransformer(psInfo);
+            return NULL;
         }
     }
 
@@ -239,10 +287,10 @@ void *GDALCreateTPSTransformerInt( int nGCPCount, const GDAL_GCP *pasGCPList,
  * Destroy TPS transformer.
  *
  * This function is used to destroy information about a GCP based
- * polynomial transformation created with GDALCreateTPSTransformer(). 
+ * polynomial transformation created with GDALCreateTPSTransformer().
  *
- * @param pTransformArg the transform arg previously returned by 
- * GDALCreateTPSTransformer(). 
+ * @param pTransformArg the transform arg previously returned by
+ * GDALCreateTPSTransformer().
  */
 
 void GDALDestroyTPSTransformer( void *pTransformArg )
@@ -260,7 +308,7 @@ void GDALDestroyTPSTransformer( void *pTransformArg )
 
         GDALDeinitGCPs( psInfo->nGCPCount, psInfo->pasGCPList );
         CPLFree( psInfo->pasGCPList );
-        
+
         CPLFree( pTransformArg );
     }
 }
@@ -276,8 +324,8 @@ void GDALDestroyTPSTransformer( void *pTransformArg )
  * used to transform one or more points from pixel/line coordinates to
  * georeferenced coordinates (SrcToDst) or vice versa (DstToSrc).
  *
- * @param pTransformArg return value from GDALCreateTPSTransformer(). 
- * @param bDstToSrc TRUE if transformation is from the destination 
+ * @param pTransformArg return value from GDALCreateTPSTransformer().
+ * @param bDstToSrc TRUE if transformation is from the destination
  * (georeferenced) coordinates to pixel/line or FALSE when transforming
  * from pixel/line to georeferenced coordinates.
  * @param nPointCount the number of values in the x, y and z arrays.
@@ -340,10 +388,10 @@ CPLXMLNode *GDALSerializeTPSTransformer( void *pTransformArg )
 /* -------------------------------------------------------------------- */
 /*      Serialize bReversed.                                            */
 /* -------------------------------------------------------------------- */
-    CPLCreateXMLElementAndValue( 
-        psTree, "Reversed", 
+    CPLCreateXMLElementAndValue(
+        psTree, "Reversed",
         CPLString().Printf( "%d", psInfo->bReversed ) );
-                                 
+
 /* -------------------------------------------------------------------- */
 /*	Attach GCP List. 						*/
 /* -------------------------------------------------------------------- */
@@ -365,7 +413,7 @@ CPLXMLNode *GDALSerializeTPSTransformer( void *pTransformArg )
 void *GDALDeserializeTPSTransformer( CPLXMLNode *psTree )
 
 {
-    GDAL_GCP *pasGCPList = 0;
+    GDAL_GCP *pasGCPList = NULL;
     int nGCPCount = 0;
     void *pResult;
     int bReversed;
@@ -392,7 +440,7 @@ void *GDALDeserializeTPSTransformer( CPLXMLNode *psTree )
 /*      Generate transformation.                                        */
 /* -------------------------------------------------------------------- */
     pResult = GDALCreateTPSTransformer( nGCPCount, pasGCPList, bReversed );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Cleanup GCP copy.                                               */
 /* -------------------------------------------------------------------- */
diff --git a/alg/gdalchecksum.cpp b/alg/gdalchecksum.cpp
index b3fec60..979be30 100644
--- a/alg/gdalchecksum.cpp
+++ b/alg/gdalchecksum.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: gdalchecksum.cpp 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: gdalchecksum.cpp 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  GDAL
- * Purpose:  Compute simple checksum for a region of image data. 
+ * Purpose:  Compute simple checksum for a region of image data.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -31,19 +31,19 @@
 #include "gdal_alg.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: gdalchecksum.cpp 27044 2014-03-16 23:41:27Z rouault $");
+CPL_CVSID("$Id: gdalchecksum.cpp 33715 2016-03-13 08:52:06Z goatbar $");
 
 /************************************************************************/
 /*                         GDALChecksumImage()                          */
 /************************************************************************/
 
 /**
- * Compute checksum for image region. 
+ * Compute checksum for image region.
  *
- * Computes a 16bit (0-65535) checksum from a region of raster data on a GDAL 
- * supported band.   Floating point data is converted to 32bit integer 
+ * Computes a 16bit (0-65535) checksum from a region of raster data on a GDAL
+ * supported band.   Floating point data is converted to 32bit integer
  * so decimal portions of such raster data will not affect the checksum.
- * Real and Imaginary components of complex bands influence the result. 
+ * Real and Imaginary components of complex bands influence the result.
  *
  * @param hBand the raster band to read from.
  * @param nXOff pixel offset of window to read.
@@ -51,41 +51,38 @@ CPL_CVSID("$Id: gdalchecksum.cpp 27044 2014-03-16 23:41:27Z rouault $");
  * @param nXSize pixel size of window to read.
  * @param nYSize line size of window to read.
  *
- * @return Checksum value. 
+ * @return Checksum value.
  */
 
-int CPL_STDCALL 
-GDALChecksumImage( GDALRasterBandH hBand, 
+int CPL_STDCALL
+GDALChecksumImage( GDALRasterBandH hBand,
                    int nXOff, int nYOff, int nXSize, int nYSize )
 
 {
     VALIDATE_POINTER1( hBand, "GDALChecksumImage", 0 );
 
-    const static int anPrimes[11] = 
+    const static int anPrimes[11] =
         { 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43 };
 
     int  iLine, i, nChecksum = 0, iPrime = 0, nCount;
     GDALDataType eDataType = GDALGetRasterDataType( hBand );
     int  bComplex = GDALDataTypeIsComplex( eDataType );
-    
+
     if (eDataType == GDT_Float32 || eDataType == GDT_Float64 ||
         eDataType == GDT_CFloat32 || eDataType == GDT_CFloat64)
     {
         double* padfLineData;
         GDALDataType eDstDataType = (bComplex) ? GDT_CFloat64 : GDT_Float64;
 
-        padfLineData = (double *) VSIMalloc2(nXSize, sizeof(double) * 2);
+        padfLineData = (double *) VSI_MALLOC2_VERBOSE(nXSize, sizeof(double) * 2);
         if (padfLineData == NULL)
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory,
-                    "VSIMalloc2(): Out of memory in GDALChecksumImage. "
-                    "Checksum value couldn't be computed\n");
             return 0;
         }
 
         for( iLine = nYOff; iLine < nYOff + nYSize; iLine++ )
         {
-            if (GDALRasterIO( hBand, GF_Read, nXOff, iLine, nXSize, 1, 
+            if (GDALRasterIO( hBand, GF_Read, nXOff, iLine, nXSize, 1,
                               padfLineData, nXSize, 1, eDstDataType, 0, 0 ) != CE_None)
             {
                 CPLError( CE_Failure, CPLE_FileIO,
@@ -134,22 +131,20 @@ GDALChecksumImage( GDALRasterBandH hBand,
         int  *panLineData;
         GDALDataType eDstDataType = (bComplex) ? GDT_CInt32 : GDT_Int32;
 
-        panLineData = (GInt32 *) VSIMalloc2(nXSize, sizeof(GInt32) * 2);
+        panLineData = (GInt32 *) VSI_MALLOC2_VERBOSE(nXSize, sizeof(GInt32) * 2);
         if (panLineData == NULL)
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory,
-                    "VSIMalloc2(): Out of memory in GDALChecksumImage. "
-                    "Checksum value couldn't be computed\n");
             return 0;
         }
 
         for( iLine = nYOff; iLine < nYOff + nYSize; iLine++ )
         {
-            if (GDALRasterIO( hBand, GF_Read, nXOff, iLine, nXSize, 1, 
+            if (GDALRasterIO( hBand, GF_Read, nXOff, iLine, nXSize, 1,
                             panLineData, nXSize, 1, eDstDataType, 0, 0 ) != CE_None)
             {
                 CPLError( CE_Failure, CPLE_FileIO,
-                        "Checksum value couldn't be computed due to I/O read error.\n");
+                          "Checksum value could not be computed due to I/O "
+                          "read error.\n");
                 break;
             }
             nCount = (bComplex) ? nXSize * 2 : nXSize;
@@ -169,4 +164,3 @@ GDALChecksumImage( GDALRasterBandH hBand,
 
     return nChecksum;
 }
-                       
diff --git a/alg/gdalcutline.cpp b/alg/gdalcutline.cpp
index 36ff99e..8036290 100644
--- a/alg/gdalcutline.cpp
+++ b/alg/gdalcutline.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalcutline.cpp 28223 2014-12-26 11:28:03Z goatbar $
+ * $Id: gdalcutline.cpp 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  High Performance Image Reprojector
  * Purpose:  Implement cutline/blend mask generator.
@@ -35,7 +35,7 @@
 #include "ogr_geometry.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: gdalcutline.cpp 28223 2014-12-26 11:28:03Z goatbar $");
+CPL_CVSID("$Id: gdalcutline.cpp 33715 2016-03-13 08:52:06Z goatbar $");
 
 /************************************************************************/
 /*                         BlendMaskGenerator()                         */
@@ -75,36 +75,35 @@ BlendMaskGenerator(
 /* -------------------------------------------------------------------- */
 /*      Prepare a clipping polygon a bit bigger than the area of        */
 /*      interest in the hopes of simplifying the cutline down to        */
-/*      stuff that will be relavent for this area of interest.          */
+/*      stuff that will be relevant for this area of interest.          */
 /* -------------------------------------------------------------------- */
     CPLString osClipRectWKT;
 
-    osClipRectWKT.Printf( "POLYGON((%g %g,%g %g,%g %g,%g %g,%g %g))", 
-                          nXOff - (dfBlendDist+1), 
-                          nYOff - (dfBlendDist+1), 
-                          nXOff + nXSize + (dfBlendDist+1), 
-                          nYOff - (dfBlendDist+1), 
-                          nXOff + nXSize + (dfBlendDist+1), 
-                          nYOff + nYSize + (dfBlendDist+1), 
-                          nXOff - (dfBlendDist+1), 
-                          nYOff + nYSize + (dfBlendDist+1), 
-                          nXOff - (dfBlendDist+1), 
+    osClipRectWKT.Printf( "POLYGON((%g %g,%g %g,%g %g,%g %g,%g %g))",
+                          nXOff - (dfBlendDist+1),
+                          nYOff - (dfBlendDist+1),
+                          nXOff + nXSize + (dfBlendDist+1),
+                          nYOff - (dfBlendDist+1),
+                          nXOff + nXSize + (dfBlendDist+1),
+                          nYOff + nYSize + (dfBlendDist+1),
+                          nXOff - (dfBlendDist+1),
+                          nYOff + nYSize + (dfBlendDist+1),
+                          nXOff - (dfBlendDist+1),
                           nYOff - (dfBlendDist+1) );
-    
+
     OGRPolygon *poClipRect = NULL;
     char *pszWKT = (char *) osClipRectWKT.c_str();
-    
-    OGRGeometryFactory::createFromWkt( &pszWKT, NULL, 
+
+    OGRGeometryFactory::createFromWkt( &pszWKT, NULL,
                                        (OGRGeometry**) (&poClipRect) );
 
     if( poClipRect )
     {
 
-        /***** if it doesnt intersect the polym zero the mask and return *****/
+        // If it does not intersect the polym zero the mask and return.
 
         if ( ! ((OGRGeometry *) hPolygon)->Intersects( poClipRect ) )
         {
-            
             memset( pafValidityMask, 0, sizeof(float) * nXSize * nYSize );
 
             delete poLines;
@@ -113,8 +112,8 @@ BlendMaskGenerator(
             return CE_None;
         }
 
-        /***** if it doesnt intersect the line at all just return *****/
-         
+        // If it does not intersect the line at all just return.
+
         else if ( ! ((OGRGeometry *) poLines)->Intersects( poClipRect ) )
         {
             delete poLines;
@@ -123,7 +122,7 @@ BlendMaskGenerator(
             return CE_None;
         }
 
-        OGRGeometry *poClippedLines = 
+        OGRGeometry *poClippedLines =
             poLines->Intersection( poClipRect );
         delete poLines;
         poLines = poClippedLines;
@@ -147,8 +146,8 @@ BlendMaskGenerator(
     /***** this check was already done in the calling *****/
     /***** function and should never be true          *****/
 
-    /*if( sEnvelope.MinY - dfBlendDist > nYOff+nYSize 
-        || sEnvelope.MaxY + dfBlendDist < nYOff 
+    /*if( sEnvelope.MinY - dfBlendDist > nYOff+nYSize
+        || sEnvelope.MaxY + dfBlendDist < nYOff
         || sEnvelope.MinX - dfBlendDist > nXOff+nXSize
         || sEnvelope.MaxX + dfBlendDist < nXOff )
         return CE_None;
@@ -166,7 +165,7 @@ BlendMaskGenerator(
 /* -------------------------------------------------------------------- */
     int iY, iX;
     double dfLastDist;
-    
+
     for( iY = 0; iY < nYSize; iY++ )
     {
         dfLastDist = 0.0;
@@ -183,7 +182,7 @@ BlendMaskGenerator(
                 dfLastDist -= 1.0;
                 continue;
             }
-            
+
             double dfDist, dfRatio;
             CPLString osPointWKT;
             GEOSGeom poGEOSPoint;
@@ -209,11 +208,11 @@ BlendMaskGenerator(
                 /* outside */
                 dfRatio = 0.5 - (dfDist / dfBlendDist) * 0.5;
             }
-            else 
+            else
             {
                 /* inside */
                 dfRatio = 0.5 + (dfDist / dfBlendDist) * 0.5;
-            }                
+            }
 
             pafValidityMask[iX + iY * nXSize] *= (float)dfRatio;
         }
@@ -350,12 +349,12 @@ GDALWarpCutlineMasker( void *pMaskFuncArg,
     char *apszOptions[] = { szDataPointer, NULL };
 
     memset( szDataPointer, 0, sizeof(szDataPointer) );
-    sprintf( szDataPointer, "DATAPOINTER=" );
-    CPLPrintPointer( szDataPointer+strlen(szDataPointer), 
-                    pabyPolyMask, 
-                     sizeof(szDataPointer) - strlen(szDataPointer) );
+    snprintf( szDataPointer, sizeof(szDataPointer), "DATAPOINTER=" );
+    CPLPrintPointer( szDataPointer+strlen(szDataPointer),
+                     pabyPolyMask,
+                     static_cast<int>(sizeof(szDataPointer) - strlen(szDataPointer)) );
 
-    hMemDS = GDALCreate( hMemDriver, "warp_temp", 
+    hMemDS = GDALCreate( hMemDriver, "warp_temp",
                          nXSize, nYSize, 0, GDT_Byte, NULL );
     GDALAddBand( hMemDS, GDT_Byte, apszOptions );
     GDALSetGeoTransform( hMemDS, adfGeoTransform );
@@ -367,20 +366,19 @@ GDALWarpCutlineMasker( void *pMaskFuncArg,
     double dfBurnValue = 255.0;
     int    anXYOff[2];
     char   **papszRasterizeOptions = NULL;
-    
 
     if( CSLFetchBoolean( psWO->papszWarpOptions, "CUTLINE_ALL_TOUCHED", FALSE ))
-        papszRasterizeOptions = 
+        papszRasterizeOptions =
             CSLSetNameValue( papszRasterizeOptions, "ALL_TOUCHED", "TRUE" );
 
     anXYOff[0] = nXOff;
     anXYOff[1] = nYOff;
 
-    eErr = 
-        GDALRasterizeGeometries( hMemDS, 1, &nTargetBand, 
-                                 1, &hPolygon, 
-                                 CutlineTransformer, anXYOff, 
-                                 &dfBurnValue, papszRasterizeOptions, 
+    eErr =
+        GDALRasterizeGeometries( hMemDS, 1, &nTargetBand,
+                                 1, &hPolygon,
+                                 CutlineTransformer, anXYOff,
+                                 &dfBurnValue, papszRasterizeOptions,
                                  NULL, NULL );
 
     CSLDestroy( papszRasterizeOptions );
@@ -404,7 +402,7 @@ GDALWarpCutlineMasker( void *pMaskFuncArg,
     }
     else
     {
-        eErr = BlendMaskGenerator( nXOff, nYOff, nXSize, nYSize, 
+        eErr = BlendMaskGenerator( nXOff, nYOff, nXSize, nYSize,
                                    pabyPolyMask, (float *) pValidityMask,
                                    hPolygon, psWO->dfCutlineBlendDist );
     }
diff --git a/alg/gdaldither.cpp b/alg/gdaldither.cpp
index e7ff8d8..b613fd0 100644
--- a/alg/gdaldither.cpp
+++ b/alg/gdaldither.cpp
@@ -1,9 +1,9 @@
 /******************************************************************************
- * $Id: gdaldither.cpp 28085 2014-12-07 14:36:00Z rouault $
+ * $Id: gdaldither.cpp 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  CIETMap Phase 2
  * Purpose:  Convert RGB (24bit) to a pseudo-colored approximation using
- *           Floyd-Steinberg dithering (error diffusion). 
+ *           Floyd-Steinberg dithering (error diffusion).
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -43,7 +43,7 @@
  *  3/8-3/8-1/4 distribution, at the cost of greater processing.  I have
  *  seen the 3/8-3/8-1/4 distribution described as "our" algorithm before,
  *  but I have no idea who the credit really belongs to.
- *  -- 
+ *  --
  *					    Lou Steinberg
  *
  */
@@ -70,7 +70,7 @@
 
 #define MAKE_COLOR_CODE(r,g,b) ((r)|((g)<<8)|((b)<<16))
 
-CPL_CVSID("$Id: gdaldither.cpp 28085 2014-12-07 14:36:00Z rouault $");
+CPL_CVSID("$Id: gdaldither.cpp 33715 2016-03-13 08:52:06Z goatbar $");
 
 static void FindNearestColor( int nColors, int *panPCT, GByte *pabyColorMap,
                               int nCLevels );
@@ -78,7 +78,9 @@ static int FindNearestColor( int nColors, int *panPCT,
                              int nRedValue, int nGreenValue, int nBlueValue );
 
 /* Structure for a hashmap from a color code to a color index of the color table */
-typedef struct  /* NOTE: if changing the size of this structure, edit MEDIAN_CUT_AND_DITHER_BUFFER_SIZE_65536 */
+/* NOTE: if changing the size of this structure, edit */
+/* MEDIAN_CUT_AND_DITHER_BUFFER_SIZE_65536 in gdal_alg_priv.h and take into account HashHistogram in gdalmediancut.cpp */
+typedef struct
 {
     GUInt32 nColorCode;
     GUInt32 nColorCode2;
@@ -96,37 +98,37 @@ typedef struct  /* NOTE: if changing the size of this structure, edit MEDIAN_CUT
 /**
  * 24bit to 8bit conversion with dithering.
  *
- * This functions utilizes Floyd-Steinberg dithering in the process of 
+ * This functions utilizes Floyd-Steinberg dithering in the process of
  * converting a 24bit RGB image into a pseudocolored 8bit image using a
- * provided color table.  
+ * provided color table.
  *
  * The red, green and blue input bands do not necessarily need to come
  * from the same file, but they must be the same width and height.  They will
  * be clipped to 8bit during reading, so non-eight bit bands are generally
  * inappropriate.  Likewise the hTarget band will be written with 8bit values
- * and must match the width and height of the source bands. 
+ * and must match the width and height of the source bands.
  *
  * The color table cannot have more than 256 entries.
  *
- * @param hRed Red input band. 
- * @param hGreen Green input band. 
- * @param hBlue Blue input band. 
- * @param hTarget Output band. 
- * @param hColorTable the color table to use with the output band. 
+ * @param hRed Red input band.
+ * @param hGreen Green input band.
+ * @param hBlue Blue input band.
+ * @param hTarget Output band.
+ * @param hColorTable the color table to use with the output band.
  * @param pfnProgress callback for reporting algorithm progress matching the
  * GDALProgressFunc() semantics.  May be NULL.
  * @param pProgressArg callback argument passed to pfnProgress.
  *
- * @return CE_None on success or CE_Failure if an error occurs. 
+ * @return CE_None on success or CE_Failure if an error occurs.
  */
 
-int CPL_STDCALL 
-GDALDitherRGB2PCT( GDALRasterBandH hRed, 
-                   GDALRasterBandH hGreen, 
-                   GDALRasterBandH hBlue, 
-                   GDALRasterBandH hTarget, 
+int CPL_STDCALL
+GDALDitherRGB2PCT( GDALRasterBandH hRed,
+                   GDALRasterBandH hGreen,
+                   GDALRasterBandH hBlue,
+                   GDALRasterBandH hTarget,
                    GDALColorTableH hColorTable,
-                   GDALProgressFunc pfnProgress, 
+                   GDALProgressFunc pfnProgress,
                    void * pProgressArg )
 
 {
@@ -135,15 +137,15 @@ GDALDitherRGB2PCT( GDALRasterBandH hRed,
                                 pfnProgress, pProgressArg );
 }
 
-int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed, 
-                         GDALRasterBandH hGreen, 
-                         GDALRasterBandH hBlue, 
-                         GDALRasterBandH hTarget, 
+int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
+                         GDALRasterBandH hGreen,
+                         GDALRasterBandH hBlue,
+                         GDALRasterBandH hTarget,
                          GDALColorTableH hColorTable,
                          int nBits,
                          GInt16* pasDynamicColorMap, /* NULL or at least 256 * 256 * 256 * sizeof(GInt16) bytes */
                          int bDither,
-                         GDALProgressFunc pfnProgress, 
+                         GDALProgressFunc pfnProgress,
                          void * pProgressArg )
 {
     VALIDATE_POINTER1( hRed, "GDALDitherRGB2PCT", CE_Failure );
@@ -154,16 +156,16 @@ int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
 
     int		nXSize, nYSize;
     CPLErr err = CE_None;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Validate parameters.                                            */
 /* -------------------------------------------------------------------- */
     nXSize = GDALGetRasterBandXSize( hRed );
     nYSize = GDALGetRasterBandYSize( hRed );
 
-    if( GDALGetRasterBandXSize( hGreen ) != nXSize 
-        || GDALGetRasterBandYSize( hGreen ) != nYSize 
-        || GDALGetRasterBandXSize( hBlue ) != nXSize 
+    if( GDALGetRasterBandXSize( hGreen ) != nXSize
+        || GDALGetRasterBandYSize( hGreen ) != nYSize
+        || GDALGetRasterBandXSize( hBlue ) != nXSize
         || GDALGetRasterBandYSize( hBlue ) != nYSize )
     {
         CPLError( CE_Failure, CPLE_IllegalArg,
@@ -172,7 +174,7 @@ int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
         return CE_Failure;
     }
 
-    if( GDALGetRasterBandXSize( hTarget ) != nXSize 
+    if( GDALGetRasterBandXSize( hTarget ) != nXSize
         || GDALGetRasterBandYSize( hTarget ) != nYSize )
     {
         CPLError( CE_Failure, CPLE_IllegalArg,
@@ -196,7 +198,7 @@ int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
     int anPCT[256*4];
 #endif
     nColors = GDALGetColorEntryCount( hColorTable );
-    
+
     if (nColors == 0 )
     {
         CPLError( CE_Failure, CPLE_IllegalArg,
@@ -213,17 +215,21 @@ int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
 
         return CE_Failure;
     }
-    
-    for( iColor = 0; iColor < nColors; iColor++ )
+
+    iColor = 0;
+    do
     {
         GDALColorEntry	sEntry;
 
         GDALGetColorEntryAsRGB( hColorTable, iColor, &sEntry );
-        CAST_PCT(anPCT)[4*iColor+0] = sEntry.c1;
-        CAST_PCT(anPCT)[4*iColor+1] = sEntry.c2;
-        CAST_PCT(anPCT)[4*iColor+2] = sEntry.c3;
+        CAST_PCT(anPCT)[4*iColor+0] = static_cast<GByte>(sEntry.c1);
+        CAST_PCT(anPCT)[4*iColor+1] = static_cast<GByte>(sEntry.c2);
+        CAST_PCT(anPCT)[4*iColor+2] = static_cast<GByte>(sEntry.c3);
         CAST_PCT(anPCT)[4*iColor+3] = 0;
-    }
+
+        iColor ++;
+    } while( iColor < nColors );
+
 #ifdef USE_SSE2
     /* Pad to multiple of 8 colors */
     int nColorsMod8 = nColors % 8;
@@ -245,22 +251,20 @@ int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
     int nCLevels = 1 << nBits;
     ColorIndex* psColorIndexMap = NULL;
 
-    pabyRed = (GByte *) VSIMalloc(nXSize);
-    pabyGreen = (GByte *) VSIMalloc(nXSize);
-    pabyBlue = (GByte *) VSIMalloc(nXSize);
+    pabyRed = (GByte *) VSI_MALLOC_VERBOSE(nXSize);
+    pabyGreen = (GByte *) VSI_MALLOC_VERBOSE(nXSize);
+    pabyBlue = (GByte *) VSI_MALLOC_VERBOSE(nXSize);
+
+    pabyIndex = (GByte *) VSI_MALLOC_VERBOSE(nXSize);
 
-    pabyIndex = (GByte *) VSIMalloc(nXSize);
+    panError = (int *) VSI_CALLOC_VERBOSE(sizeof(int),(nXSize+2) * 3);
 
-    panError = (int *) VSICalloc(sizeof(int),(nXSize+2) * 3);
-    
     if (pabyRed == NULL ||
         pabyGreen == NULL ||
         pabyBlue == NULL ||
         pabyIndex == NULL ||
         panError == NULL)
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory,
-                  "VSIMalloc(): Out of memory in GDALDitherRGB2PCT" );
         err = CE_Failure;
         goto end_and_cleanup;
     }
@@ -271,12 +275,10 @@ int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
 /*      Build a 24bit to 8 bit color mapping.                           */
 /* -------------------------------------------------------------------- */
 
-        pabyColorMap = (GByte *) VSIMalloc(nCLevels * nCLevels * nCLevels 
+        pabyColorMap = (GByte *) VSI_MALLOC_VERBOSE(nCLevels * nCLevels * nCLevels
                                         * sizeof(GByte));
         if( pabyColorMap == NULL )
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory,
-                  "VSIMalloc(): Out of memory in GDALDitherRGB2PCT" );
             err = CE_Failure;
             goto end_and_cleanup;
         }
@@ -322,12 +324,16 @@ int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
 /* -------------------------------------------------------------------- */
 /*      Read source data.                                               */
 /* -------------------------------------------------------------------- */
-        GDALRasterIO( hRed, GF_Read, 0, iScanline, nXSize, 1, 
+        err = GDALRasterIO( hRed, GF_Read, 0, iScanline, nXSize, 1,
                       pabyRed, nXSize, 1, GDT_Byte, 0, 0 );
-        GDALRasterIO( hGreen, GF_Read, 0, iScanline, nXSize, 1, 
+        if( err == CE_None )
+            err = GDALRasterIO( hGreen, GF_Read, 0, iScanline, nXSize, 1,
                       pabyGreen, nXSize, 1, GDT_Byte, 0, 0 );
-        GDALRasterIO( hBlue, GF_Read, 0, iScanline, nXSize, 1, 
+        if( err == CE_None )
+            err = GDALRasterIO( hBlue, GF_Read, 0, iScanline, nXSize, 1,
                       pabyBlue, nXSize, 1, GDT_Byte, 0, 0 );
+        if( err != CE_None )
+            goto end_and_cleanup;
 
 /* -------------------------------------------------------------------- */
 /*	Apply the error from the previous line to this one.		*/
@@ -369,7 +375,7 @@ int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
                 GUInt32 nIdx = nColorCode % PRIME_FOR_65536;
                 //int nCollisions = 0;
                 //static int nMaxCollisions = 0;
-                while( TRUE )
+                while( true )
                 {
                     if( psColorIndexMap[nIdx].nColorCode == nColorCode )
                     {
@@ -437,8 +443,8 @@ int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
                 int iRed   = nRedValue *   nCLevels   / 256;
                 int iGreen = nGreenValue * nCLevels / 256;
                 int iBlue  = nBlueValue *  nCLevels  / 256;
-                
-                iIndex = pabyColorMap[iRed + iGreen * nCLevels 
+
+                iIndex = pabyColorMap[iRed + iGreen * nCLevels
                                     + iBlue * nCLevels * nCLevels];
             }
             else
@@ -446,10 +452,10 @@ int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
                 GUInt32 nColorCode = MAKE_COLOR_CODE(nRedValue, nGreenValue, nBlueValue);
                 GInt16* psIndex = &pasDynamicColorMap[nColorCode];
                 if( *psIndex < 0 )
-                    iIndex = *psIndex = FindNearestColor( nColors, anPCT,
+                    iIndex = *psIndex = static_cast<GInt16>(FindNearestColor( nColors, anPCT,
                                                           nRedValue,
                                                           nGreenValue,
-                                                          nBlueValue );
+                                                          nBlueValue ));
                 else
                     iIndex = *psIndex;
             }
@@ -463,11 +469,11 @@ int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
 /* -------------------------------------------------------------------- */
             nError = nRedValue - CAST_PCT(anPCT)[4*iIndex+0];
             nSixth = nError / 6;
-            
+
             panError[i*3    ] += nSixth;
             panError[i*3+6  ] = nSixth;
             panError[i*3+3  ] += nError - 5 * nSixth;
-            
+
             nLastRedError = 2 * nSixth;
 
 /* -------------------------------------------------------------------- */
@@ -479,7 +485,7 @@ int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
             panError[i*3  +1] += nSixth;
             panError[i*3+6+1] = nSixth;
             panError[i*3+3+1] += nError - 5 * nSixth;
-            
+
             nLastGreenError = 2 * nSixth;
 
 /* -------------------------------------------------------------------- */
@@ -487,19 +493,21 @@ int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
 /* -------------------------------------------------------------------- */
             nError = nBlueValue - CAST_PCT(anPCT)[4*iIndex+2];
             nSixth = nError / 6;
-            
+
             panError[i*3  +2] += nSixth;
             panError[i*3+6+2] = nSixth;
             panError[i*3+3+2] += nError - 5 * nSixth;
-            
+
             nLastBlueError = 2 * nSixth;
         }
 
 /* -------------------------------------------------------------------- */
 /*      Write results.                                                  */
 /* -------------------------------------------------------------------- */
-        GDALRasterIO( hTarget, GF_Write, 0, iScanline, nXSize, 1, 
+        err = GDALRasterIO( hTarget, GF_Write, 0, iScanline, nXSize, 1,
                       pabyIndex, nXSize, 1, GDT_Byte, 0, 0 );
+        if( err != CE_None )
+            break;
     }
 
     pfnProgress( 1.0, NULL, pProgressArg );
@@ -604,7 +612,7 @@ static int FindNearestColor( int nColors, int *panPCT,
     {
         int     nThisDist;
 
-        nThisDist = ABS(nRedValue   - panPCT[4*iColor+0]) 
+        nThisDist = ABS(nRedValue   - panPCT[4*iColor+0])
                   + ABS(nGreenValue - panPCT[4*iColor+1])
                   + ABS(nBlueValue  - panPCT[4*iColor+2]);
 
@@ -648,7 +656,7 @@ static void FindNearestColor( int nColors, int *panPCT, GByte *pabyColorMap,
 
                 int nBestIndex = FindNearestColor( nColors, panPCT,
                                         nRedValue, nGreenValue, nBlueValue );
-                pabyColorMap[iRed + iGreen*nCLevels 
+                pabyColorMap[iRed + iGreen*nCLevels
                                     + iBlue*nCLevels*nCLevels] = (GByte)nBestIndex;
             }
         }
diff --git a/alg/gdalgeoloc.cpp b/alg/gdalgeoloc.cpp
index b17f526..2945e93 100644
--- a/alg/gdalgeoloc.cpp
+++ b/alg/gdalgeoloc.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalgeoloc.cpp 29207 2015-05-18 17:23:45Z mloskot $
+ * $Id: gdalgeoloc.cpp 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Implements Geolocation array based transformer.
@@ -38,7 +38,7 @@ SHPHandle hSHP = NULL;
 DBFHandle hDBF = NULL;
 #endif
 
-CPL_CVSID("$Id: gdalgeoloc.cpp 29207 2015-05-18 17:23:45Z mloskot $");
+CPL_CVSID("$Id: gdalgeoloc.cpp 33715 2016-03-13 08:52:06Z goatbar $");
 
 CPL_C_START
 CPLXMLNode *GDALSerializeGeoLocTransformer( void *pTransformArg );
@@ -67,13 +67,13 @@ typedef struct {
     float       *pafBackMapY;
 
     // geolocation bands.
-    
+
     GDALDatasetH     hDS_X;
     GDALRasterBandH  hBand_X;
     GDALDatasetH     hDS_Y;
     GDALRasterBandH  hBand_Y;
 
-    // Located geolocation data. 
+    // Located geolocation data.
     int              nGeoLocXSize;
     int              nGeoLocYSize;
     double           *padfGeoLocX;
@@ -118,17 +118,15 @@ static int GeoLocLoadFullData( GDALGeoLocTransformInfo *psTransform )
 
     psTransform->nGeoLocXSize = nXSize;
     psTransform->nGeoLocYSize = nYSize;
-    
-    psTransform->padfGeoLocY = (double *) 
-        VSIMalloc3(sizeof(double), nXSize, nYSize);
-    psTransform->padfGeoLocX = (double *) 
-        VSIMalloc3(sizeof(double), nXSize, nYSize);
-    
+
+    psTransform->padfGeoLocY = (double *)
+        VSI_MALLOC3_VERBOSE(sizeof(double), nXSize, nYSize);
+    psTransform->padfGeoLocX = (double *)
+        VSI_MALLOC3_VERBOSE(sizeof(double), nXSize, nYSize);
+
     if( psTransform->padfGeoLocX == NULL ||
         psTransform->padfGeoLocY == NULL )
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory,
-                 "GeoLocLoadFullData : Out of memory");
         return FALSE;
     }
 
@@ -138,22 +136,20 @@ static int GeoLocLoadFullData( GDALGeoLocTransformInfo *psTransform )
         /* The XBAND contains the x coordinates for all lines */
         /* The YBAND contains the y coordinates for all columns */
 
-        double* padfTempX = (double*)VSIMalloc2(nXSize, sizeof(double));
-        double* padfTempY = (double*)VSIMalloc2(nYSize, sizeof(double));
+        double* padfTempX = (double*)VSI_MALLOC2_VERBOSE(nXSize, sizeof(double));
+        double* padfTempY = (double*)VSI_MALLOC2_VERBOSE(nYSize, sizeof(double));
         if (padfTempX == NULL || padfTempY == NULL)
         {
             CPLFree(padfTempX);
             CPLFree(padfTempY);
-            CPLError(CE_Failure, CPLE_OutOfMemory,
-                 "GeoLocLoadFullData : Out of memory");
             return FALSE;
         }
 
         CPLErr eErr = CE_None;
 
-        eErr = GDALRasterIO( psTransform->hBand_X, GF_Read, 
+        eErr = GDALRasterIO( psTransform->hBand_X, GF_Read,
                              0, 0, nXSize, 1,
-                             padfTempX, nXSize, 1, 
+                             padfTempX, nXSize, 1,
                              GDT_Float64, 0, 0 );
 
         int i,j;
@@ -166,9 +162,9 @@ static int GeoLocLoadFullData( GDALGeoLocTransformInfo *psTransform )
 
         if (eErr == CE_None)
         {
-            eErr = GDALRasterIO( psTransform->hBand_Y, GF_Read, 
+            eErr = GDALRasterIO( psTransform->hBand_Y, GF_Read,
                                 0, 0, nYSize, 1,
-                                padfTempY, nYSize, 1, 
+                                padfTempY, nYSize, 1,
                                 GDT_Float64, 0, 0 );
 
             for(j=0;j<nYSize;j++)
@@ -188,18 +184,18 @@ static int GeoLocLoadFullData( GDALGeoLocTransformInfo *psTransform )
     }
     else
     {
-        if( GDALRasterIO( psTransform->hBand_X, GF_Read, 
+        if( GDALRasterIO( psTransform->hBand_X, GF_Read,
                         0, 0, nXSize, nYSize,
-                        psTransform->padfGeoLocX, nXSize, nYSize, 
-                        GDT_Float64, 0, 0 ) != CE_None 
-            || GDALRasterIO( psTransform->hBand_Y, GF_Read, 
+                        psTransform->padfGeoLocX, nXSize, nYSize,
+                        GDT_Float64, 0, 0 ) != CE_None
+            || GDALRasterIO( psTransform->hBand_Y, GF_Read,
                             0, 0, nXSize, nYSize,
-                            psTransform->padfGeoLocY, nXSize, nYSize, 
+                            psTransform->padfGeoLocY, nXSize, nYSize,
                             GDT_Float64, 0, 0 ) != CE_None )
             return FALSE;
     }
 
-    psTransform->dfNoDataX = GDALGetRasterNoDataValue( psTransform->hBand_X, 
+    psTransform->dfNoDataX = GDALGetRasterNoDataValue( psTransform->hBand_X,
                                                        &(psTransform->bHasNoData) );
 
     return TRUE;
@@ -250,13 +246,13 @@ static int GeoLocGenerateBackMap( GDALGeoLocTransformInfo *psTransform )
 /*      is approximate.                                                 */
 /* -------------------------------------------------------------------- */
     double dfTargetPixels = (nXSize * nYSize * 1.3);
-    double dfPixelSize = sqrt((dfMaxX - dfMinX) * (dfMaxY - dfMinY) 
+    double dfPixelSize = sqrt((dfMaxX - dfMinX) * (dfMaxY - dfMinY)
                               / dfTargetPixels);
     int nBMXSize, nBMYSize;
 
-    nBMYSize = psTransform->nBackMapHeight = 
+    nBMYSize = psTransform->nBackMapHeight =
         (int) ((dfMaxY - dfMinY) / dfPixelSize + 1);
-    nBMXSize= psTransform->nBackMapWidth =  
+    nBMXSize= psTransform->nBackMapWidth =
         (int) ((dfMaxX - dfMinX) / dfPixelSize + 1);
 
     if (nBMXSize > INT_MAX / nBMYSize)
@@ -281,21 +277,18 @@ static int GeoLocGenerateBackMap( GDALGeoLocTransformInfo *psTransform )
 /* -------------------------------------------------------------------- */
     GByte  *pabyValidFlag;
 
-    pabyValidFlag = (GByte *) 
-        VSICalloc(nBMXSize, nBMYSize); 
+    pabyValidFlag = (GByte *)
+        VSI_CALLOC_VERBOSE(nBMXSize, nBMYSize);
 
-    psTransform->pafBackMapX = (float *) 
-        VSIMalloc3(nBMXSize, nBMYSize, sizeof(float)); 
-    psTransform->pafBackMapY = (float *) 
-        VSIMalloc3(nBMXSize, nBMYSize, sizeof(float)); 
+    psTransform->pafBackMapX = (float *)
+        VSI_MALLOC3_VERBOSE(nBMXSize, nBMYSize, sizeof(float));
+    psTransform->pafBackMapY = (float *)
+        VSI_MALLOC3_VERBOSE(nBMXSize, nBMYSize, sizeof(float));
 
     if( pabyValidFlag == NULL ||
         psTransform->pafBackMapX == NULL ||
         psTransform->pafBackMapY == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory, 
-                  "Unable to allocate %dx%d back-map for geolocation array transformer.",
-                  nBMXSize, nBMYSize );
         CPLFree( pabyValidFlag );
         return FALSE;
     }
@@ -309,7 +302,7 @@ static int GeoLocGenerateBackMap( GDALGeoLocTransformInfo *psTransform )
 /* -------------------------------------------------------------------- */
 /*      Run through the whole geoloc array forward projecting and       */
 /*      pushing into the backmap.                                       */
-/*      Initialise to the nMaxIter+1 value so we can spot genuinely     */
+/*      Initialize to the nMaxIter+1 value so we can spot genuinely     */
 /*      valid pixels in the hole-filling loop.                          */
 /* -------------------------------------------------------------------- */
     int iBMX, iBMY;
@@ -320,7 +313,7 @@ static int GeoLocGenerateBackMap( GDALGeoLocTransformInfo *psTransform )
         for( iX = 0; iX < nXSize; iX++ )
         {
             if( psTransform->bHasNoData &&
-                psTransform->padfGeoLocX[iX + iY * nXSize] 
+                psTransform->padfGeoLocX[iX + iY * nXSize]
                 == psTransform->dfNoDataX )
                 continue;
 
@@ -332,9 +325,9 @@ static int GeoLocGenerateBackMap( GDALGeoLocTransformInfo *psTransform )
             if( iBMX < 0 || iBMY < 0 || iBMX >= nBMXSize || iBMY >= nBMYSize )
                 continue;
 
-            psTransform->pafBackMapX[iBMX + iBMY * nBMXSize] = 
+            psTransform->pafBackMapX[iBMX + iBMY * nBMXSize] =
                 (float)(iX * psTransform->dfPIXEL_STEP + psTransform->dfPIXEL_OFFSET);
-            psTransform->pafBackMapY[iBMX + iBMY * nBMXSize] = 
+            psTransform->pafBackMapY[iBMX + iBMY * nBMXSize] =
                 (float)(iY * psTransform->dfLINE_STEP + psTransform->dfLINE_OFFSET);
 
             pabyValidFlag[iBMX + iBMY * nBMXSize] = (GByte) (nMaxIter+1);
@@ -356,7 +349,7 @@ static int GeoLocGenerateBackMap( GDALGeoLocTransformInfo *psTransform )
         {
             for( iBMX = 0; iBMX < nBMXSize; iBMX++ )
             {
-                // if this point is already set, ignore it. 
+                // if this point is already set, ignore it.
                 if( pabyValidFlag[iBMX + iBMY*nBMXSize] )
                 {
                     nNumValid++;
@@ -450,16 +443,16 @@ static int GeoLocGenerateBackMap( GDALGeoLocTransformInfo *psTransform )
 
 #ifdef notdef
     GDALDatasetH hBMDS = GDALCreate( GDALGetDriverByName( "GTiff" ),
-                                     "backmap.tif", nBMXSize, nBMYSize, 2, 
+                                     "backmap.tif", nBMXSize, nBMYSize, 2,
                                      GDT_Float32, NULL );
     GDALSetGeoTransform( hBMDS, psTransform->adfBackMapGeoTransform );
-    GDALRasterIO( GDALGetRasterBand(hBMDS,1), GF_Write, 
-                  0, 0, nBMXSize, nBMYSize, 
-                  psTransform->pafBackMapX, nBMXSize, nBMYSize, 
+    GDALRasterIO( GDALGetRasterBand(hBMDS,1), GF_Write,
+                  0, 0, nBMXSize, nBMYSize,
+                  psTransform->pafBackMapX, nBMXSize, nBMYSize,
                   GDT_Float32, 0, 0 );
-    GDALRasterIO( GDALGetRasterBand(hBMDS,2), GF_Write, 
-                  0, 0, nBMXSize, nBMYSize, 
-                  psTransform->pafBackMapY, nBMXSize, nBMYSize, 
+    GDALRasterIO( GDALGetRasterBand(hBMDS,2), GF_Write,
+                  0, 0, nBMXSize, nBMYSize,
+                  psTransform->pafBackMapY, nBMXSize, nBMYSize,
                   GDT_Float32, 0, 0 );
     GDALClose( hBMDS );
 #endif
@@ -473,17 +466,17 @@ static int GeoLocGenerateBackMap( GDALGeoLocTransformInfo *psTransform )
 /*                         FindGeoLocPosition()                         */
 /************************************************************************/
 
-#ifdef notdef 
+#ifdef notdef
 
 /*
 This searching approach has been abandoned because it is too sensitive
-to discontinuities in the data.  Left in case it might be revived in 
+to discontinuities in the data.  Left in case it might be revived in
 the future.
  */
 
 static int FindGeoLocPosition( GDALGeoLocTransformInfo *psTransform,
                                double dfGeoX, double dfGeoY,
-                               int nStartX, int nStartY, 
+                               int nStartX, int nStartY,
                                double *pdfFoundX, double *pdfFoundY )
 
 {
@@ -497,7 +490,7 @@ static int FindGeoLocPosition( GDALGeoLocTransformInfo *psTransform,
     int nStepCount = 0;
 
     // Start in center if we don't have any provided info.
-    if( nStartX < 0 || nStartY < 0 
+    if( nStartX < 0 || nStartY < 0
         || nStartX >= nXSize || nStartY >= nYSize )
     {
         nStartX = nXSize / 2;
@@ -544,16 +537,16 @@ static int FindGeoLocPosition( GDALGeoLocTransformInfo *psTransform,
             dfDeltaYDown = *(padfThisY+nXSize) - *padfThisY;
         }
 
-        double dfRightProjection = 
-            (dfDeltaXRight * dfDeltaX + dfDeltaYRight * dfDeltaY) 
+        double dfRightProjection =
+            (dfDeltaXRight * dfDeltaX + dfDeltaYRight * dfDeltaY)
             / (dfDeltaXRight*dfDeltaXRight + dfDeltaYRight*dfDeltaYRight);
 
-        double dfDownProjection = 
-            (dfDeltaXDown * dfDeltaX + dfDeltaYDown * dfDeltaY) 
+        double dfDownProjection =
+            (dfDeltaXDown * dfDeltaX + dfDeltaYDown * dfDeltaY)
             / (dfDeltaXDown*dfDeltaXDown + dfDeltaYDown*dfDeltaYDown);
 
         // Are we in our target cell?
-        if( dfRightProjection >= 0.0 && dfRightProjection < 1.0 
+        if( dfRightProjection >= 0.0 && dfRightProjection < 1.0
             && dfDownProjection >= 0.0 && dfDownProjection < 1.0 )
         {
             *pdfFoundX = iX + dfRightProjection;
@@ -561,37 +554,37 @@ static int FindGeoLocPosition( GDALGeoLocTransformInfo *psTransform,
 
             return TRUE;
         }
-            
+
         if( ABS(dfRightProjection) > ABS(dfDownProjection) )
         {
-            // Do we want to move right? 
+            // Do we want to move right?
             if( dfRightProjection > 1.0 && iX < nXSize-1 )
             {
                 iXNext = iX + MAX(1,(int)(dfRightProjection - nStepCount)/2);
                 iYNext = iY;
             }
-            
-            // Do we want to move left? 
+
+            // Do we want to move left?
             else if( dfRightProjection < 0.0 && iX > 0 )
             {
                 iXNext = iX - MAX(1,(int)(ABS(dfRightProjection) - nStepCount)/2);
                 iYNext = iY;
             }
-            
+
             // Do we want to move down.
             else if( dfDownProjection > 1.0 && iY < nYSize-1 )
             {
                 iXNext = iX;
                 iYNext = iY + MAX(1,(int)(dfDownProjection - nStepCount)/2);
             }
-            
-            // Do we want to move up? 
+
+            // Do we want to move up?
             else if( dfDownProjection < 0.0 && iY > 0 )
             {
                 iXNext = iX;
                 iYNext = iY - MAX(1,(int)(ABS(dfDownProjection) - nStepCount)/2);
             }
-            
+
             // We aren't there, and we have no where to go
             else
             {
@@ -606,28 +599,28 @@ static int FindGeoLocPosition( GDALGeoLocTransformInfo *psTransform,
                 iXNext = iX;
                 iYNext = iY + MAX(1,(int)(dfDownProjection - nStepCount)/2);
             }
-            
-            // Do we want to move up? 
+
+            // Do we want to move up?
             else if( dfDownProjection < 0.0 && iY > 0 )
             {
                 iXNext = iX;
                 iYNext = iY - MAX(1,(int)(ABS(dfDownProjection) - nStepCount)/2);
             }
-            
-            // Do we want to move right? 
+
+            // Do we want to move right?
             else if( dfRightProjection > 1.0 && iX < nXSize-1 )
             {
                 iXNext = iX + MAX(1,(int)(dfRightProjection - nStepCount)/2);
                 iYNext = iY;
             }
-            
-            // Do we want to move left? 
+
+            // Do we want to move left?
             else if( dfRightProjection < 0.0 && iX > 0 )
             {
                 iXNext = iX - MAX(1,(int)(ABS(dfRightProjection) - nStepCount)/2);
                 iYNext = iY;
             }
-            
+
             // We aren't there, and we have no where to go
             else
             {
@@ -649,7 +642,7 @@ static int FindGeoLocPosition( GDALGeoLocTransformInfo *psTransform,
             {
                 *pdfFoundX = iX + dfRightProjection;
                 *pdfFoundY = iY + dfDownProjection;
-                
+
                 return TRUE;
             }
 
@@ -657,18 +650,18 @@ static int FindGeoLocPosition( GDALGeoLocTransformInfo *psTransform,
             if( hSHP != NULL )
             {
                 SHPObject *hObj;
-                
+
                 hObj = SHPCreateSimpleObject( SHPT_ARC, nStepCount,
                                               adfPathX, adfPathY, NULL );
                 SHPWriteObject( hSHP, -1, hObj );
                 SHPDestroyObject( hObj );
-                
+
                 int iShape = DBFGetRecordCount( hDBF );
                 DBFWriteDoubleAttribute( hDBF, iShape, 0, dfGeoX );
                 DBFWriteDoubleAttribute( hDBF, iShape, 1, dfGeoY );
             }
-#endif             
-            //CPLDebug( "GeoL", "Looping at step (%d) on search for %g,%g.", 
+#endif
+            //CPLDebug( "GeoL", "Looping at step (%d) on search for %g,%g.",
             //          nStepCount, dfGeoX, dfGeoY );
             return FALSE;
         }
@@ -681,10 +674,10 @@ static int FindGeoLocPosition( GDALGeoLocTransformInfo *psTransform,
 
     }
 
-    //CPLDebug( "GeoL", "Exceeded step count max (%d) on search for %g,%g.", 
-    //          MAX(nXSize,nYSize), 
+    //CPLDebug( "GeoL", "Exceeded step count max (%d) on search for %g,%g.",
+    //          MAX(nXSize,nYSize),
     //          dfGeoX, dfGeoY );
-    
+
 #ifdef SHAPE_DEBUG
     if( hSHP != NULL )
     {
@@ -700,7 +693,7 @@ static int FindGeoLocPosition( GDALGeoLocTransformInfo *psTransform,
         DBFWriteDoubleAttribute( hDBF, iShape, 1, dfGeoY );
     }
 #endif
-              
+
     return FALSE;
 }
 #endif /* def notdef */
@@ -729,7 +722,7 @@ void* GDALCreateSimilarGeoLocTransformer( void *hTransformArg, double dfRatioX,
     VALIDATE_POINTER1( hTransformArg, "GDALCreateSimilarGeoLocTransformer", NULL );
 
     GDALGeoLocTransformInfo *psInfo = (GDALGeoLocTransformInfo *) hTransformArg;
-    
+
     char** papszGeolocationInfo = CSLDuplicate(psInfo->papszGeolocationInfo);
 
     if( dfRatioX != 1.0 || dfRatioY != 1.0 )
@@ -742,7 +735,7 @@ void* GDALCreateSimilarGeoLocTransformer( void *hTransformArg, double dfRatioX,
 
     psInfo = (GDALGeoLocTransformInfo*) GDALCreateGeoLocTransformer(
         NULL, papszGeolocationInfo, psInfo->bReversed );
-    
+
     CSLDestroy(papszGeolocationInfo);
 
     return psInfo;
@@ -752,7 +745,7 @@ void* GDALCreateSimilarGeoLocTransformer( void *hTransformArg, double dfRatioX,
 /*                    GDALCreateGeoLocTransformer()                     */
 /************************************************************************/
 
-void *GDALCreateGeoLocTransformer( GDALDatasetH hBaseDS, 
+void *GDALCreateGeoLocTransformer( GDALDatasetH hBaseDS,
                                    char **papszGeolocationInfo,
                                    int bReversed )
 
@@ -774,7 +767,7 @@ void *GDALCreateGeoLocTransformer( GDALDatasetH hBaseDS,
 /* -------------------------------------------------------------------- */
 /*      Initialize core info.                                           */
 /* -------------------------------------------------------------------- */
-    psTransform = (GDALGeoLocTransformInfo *) 
+    psTransform = (GDALGeoLocTransformInfo *)
         CPLCalloc(sizeof(GDALGeoLocTransformInfo),1);
 
     psTransform->bReversed = bReversed;
@@ -785,7 +778,7 @@ void *GDALCreateGeoLocTransformer( GDALDatasetH hBaseDS,
     psTransform->sTI.pfnCleanup = GDALDestroyGeoLocTransformer;
     psTransform->sTI.pfnSerialize = GDALSerializeGeoLocTransformer;
     psTransform->sTI.pfnCreateSimilar = GDALCreateSimilarGeoLocTransformer;
-    
+
     psTransform->papszGeolocationInfo = CSLDuplicate( papszGeolocationInfo );
 
 /* -------------------------------------------------------------------- */
@@ -803,7 +796,7 @@ void *GDALCreateGeoLocTransformer( GDALDatasetH hBaseDS,
 /* -------------------------------------------------------------------- */
 /*      Establish access to geolocation dataset(s).                     */
 /* -------------------------------------------------------------------- */
-    const char *pszDSName = CSLFetchNameValue( papszGeolocationInfo, 
+    const char *pszDSName = CSLFetchNameValue( papszGeolocationInfo,
                                                "X_DATASET" );
     if( pszDSName != NULL )
     {
@@ -812,11 +805,14 @@ void *GDALCreateGeoLocTransformer( GDALDatasetH hBaseDS,
     else
     {
         psTransform->hDS_X = hBaseDS;
-        GDALReferenceDataset( psTransform->hDS_X );
-        psTransform->papszGeolocationInfo = 
-            CSLSetNameValue( psTransform->papszGeolocationInfo, 
-                             "X_DATASET", 
-                             GDALGetDescription( hBaseDS ) );
+        if( hBaseDS )
+        {
+            GDALReferenceDataset( psTransform->hDS_X );
+            psTransform->papszGeolocationInfo =
+                CSLSetNameValue( psTransform->papszGeolocationInfo,
+                                 "X_DATASET",
+                                 GDALGetDescription( hBaseDS ) );
+        }
     }
 
     pszDSName = CSLFetchNameValue( papszGeolocationInfo, "Y_DATASET" );
@@ -827,11 +823,14 @@ void *GDALCreateGeoLocTransformer( GDALDatasetH hBaseDS,
     else
     {
         psTransform->hDS_Y = hBaseDS;
-        GDALReferenceDataset( psTransform->hDS_Y );
-        psTransform->papszGeolocationInfo = 
-            CSLSetNameValue( psTransform->papszGeolocationInfo, 
-                             "Y_DATASET", 
-                             GDALGetDescription( hBaseDS ) );
+        if( hBaseDS )
+        {
+            GDALReferenceDataset( psTransform->hDS_Y );
+            psTransform->papszGeolocationInfo =
+                CSLSetNameValue( psTransform->papszGeolocationInfo,
+                                 "Y_DATASET",
+                                 GDALGetDescription( hBaseDS ) );
+        }
     }
 
     if (psTransform->hDS_X == NULL ||
@@ -896,7 +895,7 @@ void *GDALCreateGeoLocTransformer( GDALDatasetH hBaseDS,
 /* -------------------------------------------------------------------- */
 /*      Load the geolocation array.                                     */
 /* -------------------------------------------------------------------- */
-    if( !GeoLocLoadFullData( psTransform ) 
+    if( !GeoLocLoadFullData( psTransform )
         || !GeoLocGenerateBackMap( psTransform ) )
     {
         GDALDestroyGeoLocTransformer( psTransform );
@@ -916,7 +915,7 @@ void GDALDestroyGeoLocTransformer( void *pTransformAlg )
     if( pTransformAlg == NULL )
         return;
 
-    GDALGeoLocTransformInfo *psTransform = 
+    GDALGeoLocTransformInfo *psTransform =
         (GDALGeoLocTransformInfo *) pTransformAlg;
 
     CPLFree( psTransform->pafBackMapX );
@@ -924,12 +923,12 @@ void GDALDestroyGeoLocTransformer( void *pTransformAlg )
     CSLDestroy( psTransform->papszGeolocationInfo );
     CPLFree( psTransform->padfGeoLocX );
     CPLFree( psTransform->padfGeoLocY );
-             
-    if( psTransform->hDS_X != NULL 
+
+    if( psTransform->hDS_X != NULL
         && GDALDereferenceDataset( psTransform->hDS_X ) == 0 )
             GDALClose( psTransform->hDS_X );
 
-    if( psTransform->hDS_Y != NULL 
+    if( psTransform->hDS_Y != NULL
         && GDALDereferenceDataset( psTransform->hDS_Y ) == 0 )
             GDALClose( psTransform->hDS_Y );
 
@@ -968,9 +967,9 @@ int GDALGeoLocTransform( void *pTransformArg,
                 continue;
             }
 
-            double dfGeoLocPixel = (padfX[i] - psTransform->dfPIXEL_OFFSET) 
+            double dfGeoLocPixel = (padfX[i] - psTransform->dfPIXEL_OFFSET)
                 / psTransform->dfPIXEL_STEP;
-            double dfGeoLocLine = (padfY[i] - psTransform->dfLINE_OFFSET) 
+            double dfGeoLocLine = (padfY[i] - psTransform->dfLINE_OFFSET)
                 / psTransform->dfLINE_STEP;
 
             int iX, iY;
@@ -1011,18 +1010,18 @@ int GDALGeoLocTransform( void *pTransformArg,
                      (!psTransform->bHasNoData ||
                         padfGLX[1] != psTransform->dfNoDataX) )
             {
-                padfX[i] = padfGLX[0] 
+                padfX[i] = padfGLX[0]
                     + (dfGeoLocPixel-iX) * (padfGLX[1] - padfGLX[0]);
-                padfY[i] = padfGLY[0] 
+                padfY[i] = padfGLY[0]
                     + (dfGeoLocPixel-iX) * (padfGLY[1] - padfGLY[0]);
             }
             else if( iY + 1 < psTransform->nGeoLocYSize &&
                      (!psTransform->bHasNoData ||
                         padfGLX[nXSize] != psTransform->dfNoDataX) )
             {
-                padfX[i] = padfGLX[0] 
+                padfX[i] = padfGLX[0]
                     + (dfGeoLocLine -iY) * (padfGLX[nXSize] - padfGLX[0]);
-                padfY[i] = padfGLY[0] 
+                padfY[i] = padfGLY[0]
                     + (dfGeoLocLine -iY) * (padfGLY[nXSize] - padfGLY[0]);
             }
             else
@@ -1063,9 +1062,9 @@ int GDALGeoLocTransform( void *pTransformArg,
 
             int iBM = iBMX + iBMY * psTransform->nBackMapWidth;
 
-            if( iBMX < 0 || iBMY < 0 
+            if( iBMX < 0 || iBMY < 0
                 || iBMX >= psTransform->nBackMapWidth
-                || iBMY >= psTransform->nBackMapHeight 
+                || iBMY >= psTransform->nBackMapHeight
                 || psTransform->pafBackMapX[iBM] < 0 )
             {
                 panSuccess[i] = FALSE;
@@ -1139,7 +1138,7 @@ int GDALGeoLocTransform( void *pTransformArg,
                 continue;
             }
 
-            if( !FindGeoLocPosition( psTransform, padfX[i], padfY[i], 
+            if( !FindGeoLocPosition( psTransform, padfX[i], padfY[i],
                                      -1, -1, &dfGeoLocX, &dfGeoLocY ) )
             {
                 padfX[i] = HUGE_VAL;
@@ -1151,9 +1150,9 @@ int GDALGeoLocTransform( void *pTransformArg,
             nStartX = (int) dfGeoLocX;
             nStartY = (int) dfGeoLocY;
 
-            padfX[i] = dfGeoLocX * psTransform->dfPIXEL_STEP 
+            padfX[i] = dfGeoLocX * psTransform->dfPIXEL_STEP
                 + psTransform->dfPIXEL_OFFSET;
-            padfY[i] = dfGeoLocY * psTransform->dfLINE_STEP 
+            padfY[i] = dfGeoLocY * psTransform->dfLINE_STEP
                 + psTransform->dfLINE_OFFSET;
 
             panSuccess[i] = TRUE;
@@ -1164,7 +1163,7 @@ int GDALGeoLocTransform( void *pTransformArg,
         {
             DBFClose( hDBF );
             hDBF = NULL;
-            
+
             SHPClose( hSHP );
             hSHP = NULL;
         }
@@ -1185,7 +1184,7 @@ CPLXMLNode *GDALSerializeGeoLocTransformer( void *pTransformArg )
     VALIDATE_POINTER1( pTransformArg, "GDALSerializeGeoLocTransformer", NULL );
 
     CPLXMLNode *psTree;
-    GDALGeoLocTransformInfo *psInfo = 
+    GDALGeoLocTransformInfo *psInfo =
         (GDALGeoLocTransformInfo *)(pTransformArg);
 
     psTree = CPLCreateXMLNode( NULL, CXT_Element, "GeoLocTransformer" );
@@ -1193,15 +1192,15 @@ CPLXMLNode *GDALSerializeGeoLocTransformer( void *pTransformArg )
 /* -------------------------------------------------------------------- */
 /*      Serialize bReversed.                                            */
 /* -------------------------------------------------------------------- */
-    CPLCreateXMLElementAndValue( 
-        psTree, "Reversed", 
+    CPLCreateXMLElementAndValue(
+        psTree, "Reversed",
         CPLString().Printf( "%d", psInfo->bReversed ) );
-                                 
+
 /* -------------------------------------------------------------------- */
 /*      geoloc metadata.                                                */
 /* -------------------------------------------------------------------- */
     char **papszMD = psInfo->papszGeolocationInfo;
-    CPLXMLNode *psMD= CPLCreateXMLNode( psTree, CXT_Element, 
+    CPLXMLNode *psMD= CPLCreateXMLNode( psTree, CXT_Element,
                                         "Metadata" );
 
     for( int i = 0; papszMD != NULL && papszMD[i] != NULL; i++ )
@@ -1209,13 +1208,13 @@ CPLXMLNode *GDALSerializeGeoLocTransformer( void *pTransformArg )
         const char *pszRawValue;
         char *pszKey;
         CPLXMLNode *psMDI;
-                
+
         pszRawValue = CPLParseNameValue( papszMD[i], &pszKey );
-                
+
         psMDI = CPLCreateXMLNode( psMD, CXT_Element, "MDI" );
         CPLSetXMLValue( psMDI, "#key", pszKey );
         CPLCreateXMLNode( psMDI, CXT_Text, pszRawValue );
-                
+
         CPLFree( pszKey );
     }
 
@@ -1243,21 +1242,21 @@ void *GDALDeserializeGeoLocTransformer( CPLXMLNode *psTree )
         psMetadata->eType != CXT_Element
         || !EQUAL(psMetadata->pszValue,"Metadata") )
         return NULL;
-    
-    for( psMDI = psMetadata->psChild; psMDI != NULL; 
+
+    for( psMDI = psMetadata->psChild; psMDI != NULL;
          psMDI = psMDI->psNext )
     {
-        if( !EQUAL(psMDI->pszValue,"MDI") 
-            || psMDI->eType != CXT_Element 
-            || psMDI->psChild == NULL 
-            || psMDI->psChild->psNext == NULL 
+        if( !EQUAL(psMDI->pszValue,"MDI")
+            || psMDI->eType != CXT_Element
+            || psMDI->psChild == NULL
+            || psMDI->psChild->psNext == NULL
             || psMDI->psChild->eType != CXT_Attribute
             || psMDI->psChild->psChild == NULL )
             continue;
-        
-        papszMD = 
-            CSLSetNameValue( papszMD, 
-                             psMDI->psChild->psChild->pszValue, 
+
+        papszMD =
+            CSLSetNameValue( papszMD,
+                             psMDI->psChild->psChild->pszValue,
                              psMDI->psChild->psNext->pszValue );
     }
 
@@ -1270,7 +1269,7 @@ void *GDALDeserializeGeoLocTransformer( CPLXMLNode *psTree )
 /*      Generate transformation.                                        */
 /* -------------------------------------------------------------------- */
     pResult = GDALCreateGeoLocTransformer( NULL, papszMD, bReversed );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Cleanup GCP copy.                                               */
 /* -------------------------------------------------------------------- */
diff --git a/alg/gdalgrid.cpp b/alg/gdalgrid.cpp
index a9a3383..76f1716 100644
--- a/alg/gdalgrid.cpp
+++ b/alg/gdalgrid.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalgrid.cpp 29914 2015-08-29 21:21:33Z rouault $
+ * $Id: gdalgrid.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  GDAL Gridding API.
  * Purpose:  Implementation of GDAL scattered data gridder.
@@ -33,12 +33,14 @@
 #include "gdalgrid.h"
 #include <float.h>
 #include <limits.h>
-#include "cpl_multiproc.h"
+#include <map>
+#include "cpl_worker_thread_pool.h"
 #include "gdalgrid_priv.h"
+#include <cstdlib>
 
-CPL_CVSID("$Id: gdalgrid.cpp 29914 2015-08-29 21:21:33Z rouault $");
+CPL_CVSID("$Id: gdalgrid.cpp 33808 2016-03-29 21:15:28Z goatbar $");
 
-#define TO_RADIANS (3.14159265358979323846 / 180.0)
+#define TO_RADIANS (M_PI / 180.0)
 
 #ifndef DBL_MAX
 # ifdef __DBL_MAX__
@@ -85,7 +87,7 @@ static void GDALGridGetPointBounds(const void* hFeature, CPLRectObj* pBounds)
  *      Z=\frac{\sum_{i=1}^n{\frac{Z_i}{r_i^p}}}{\sum_{i=1}^n{\frac{1}{r_i^p}}}
  * \f]
  *
- *  where 
+ *  where
  *  <ul>
  *      <li> \f$Z_i\f$ is a known value at point \f$i\f$,
  *      <li> \f$r_i\f$ is an Euclidean distance from the grid node
@@ -101,11 +103,11 @@ static void GDALGridGetPointBounds(const void* hFeature, CPLRectObj* pBounds)
  *  \f]
  *
  * @param poOptions Algorithm parameters. This should point to
- * GDALGridInverseDistanceToAPowerOptions object. 
+ * GDALGridInverseDistanceToAPowerOptions object.
  * @param nPoints Number of elements in input arrays.
- * @param padfX Input array of X coordinates. 
- * @param padfY Input array of Y coordinates. 
- * @param padfZ Input array of Z values. 
+ * @param padfX Input array of X coordinates.
+ * @param padfY Input array of Y coordinates.
+ * @param padfZ Input array of Z values.
  * @param dfXPoint X coordinate of the point to compute.
  * @param dfYPoint Y coordinate of the point to compute.
  * @param pdfValue Pointer to variable where the computed grid node value
@@ -152,7 +154,7 @@ GDALGridInverseDistanceToAPower( const void *poOptions, GUInt32 nPoints,
         ((GDALGridInverseDistanceToAPowerOptions *)poOptions)->dfPower / 2;
     const double    dfSmoothing =
         ((GDALGridInverseDistanceToAPowerOptions *)poOptions)->dfSmoothing;
-    const GUInt32   nMaxPoints = 
+    const GUInt32   nMaxPoints =
         ((GDALGridInverseDistanceToAPowerOptions *)poOptions)->nMaxPoints;
     double  dfNominator = 0.0, dfDenominator = 0.0;
     GUInt32 i, n = 0;
@@ -209,6 +211,178 @@ GDALGridInverseDistanceToAPower( const void *poOptions, GUInt32 nPoints,
 }
 
 /************************************************************************/
+/*                   GDALGridInverseDistanceToAPowerNearestNeighbor()   */
+/************************************************************************/
+
+/**
+ * Inverse distance to a power with nearest neighbor search, ideal when
+ * max_points used.
+ *
+ * The Inverse Distance to a Power gridding method is a weighted average
+ * interpolator. You should supply the input arrays with the scattered data
+ * values including coordinates of every data point and output grid geometry.
+ * The function will compute interpolated value for the given position in
+ * output grid.
+ *
+ * For every grid node the resulting value \f$Z\f$ will be calculated using
+ * formula for nearest matches:
+ *
+ * \f[
+ *      Z=\frac{\sum_{i=1}^n{\frac{Z_i}{r_i^p}}}{\sum_{i=1}^n{\frac{1}{r_i^p}}}
+ * \f]
+ *
+ *  where
+ *  <ul>
+ *      <li> \f$Z_i\f$ is a known value at point \f$i\f$,
+ *      <li> \f$r_i\f$ is an Euclidean distance from the grid node
+ *           to point \f$i\f$,
+ *      <li> \f$p\f$ is a weighting power,
+ *      <li> \f$n\f$ is a total number of points in search ellipse.
+ *  </ul>
+ *
+ *  In this method the weighting factor \f$w\f$ is
+ *
+ *  \f[
+ *      w=\frac{1}{r^p}
+ *  \f]
+ *
+ * @param poOptions Algorithm parameters. This should point to
+ * GDALGridInverseDistanceToAPowerNearestNeighborOptions object.
+ * @param nPoints Number of elements in input arrays.
+ * @param padfX Input array of X coordinates.
+ * @param padfY Input array of Y coordinates.
+ * @param padfZ Input array of Z values.
+ * @param dfXPoint X coordinate of the point to compute.
+ * @param dfYPoint Y coordinate of the point to compute.
+ * @param pdfValue Pointer to variable where the computed grid node value
+ * will be returned.
+ * @param hExtraParamsIn extra parameters.
+ *
+ * @return CE_None on success or CE_Failure if something goes wrong.
+ */
+
+CPLErr
+GDALGridInverseDistanceToAPowerNearestNeighbor( const void *poOptions, GUInt32 nPoints,
+                                 const double *padfX, const double *padfY,
+                                 const double *padfZ,
+                                 double dfXPoint, double dfYPoint,
+                                 double *pdfValue,
+                                 void* hExtraParamsIn )
+{
+    double dfRadius =
+        ((GDALGridInverseDistanceToAPowerNearestNeighborOptions *)poOptions)->dfRadius;
+
+    const GUInt32 nMaxPoints =
+        ((GDALGridInverseDistanceToAPowerNearestNeighborOptions *)poOptions)->nMaxPoints;
+    double dfNominator = 0.0, dfDenominator = 0.0;
+    GUInt32 n = 0;
+
+    GDALGridExtraParameters* psExtraParams = (GDALGridExtraParameters*) hExtraParamsIn;
+    CPLQuadTree* phQuadTree = psExtraParams->hQuadTree;
+
+    const double dfRPower2 = psExtraParams->dfRadiusPower2PreComp;
+    const double dfRPower4 = psExtraParams->dfRadiusPower4PreComp;
+
+    const double dfPowerDiv2 = psExtraParams->dfPowerDiv2PreComp;
+
+    std::multimap<double, double> oMapDistanceToZValues;
+    if (phQuadTree != NULL)
+    {
+        CPLRectObj sAoi;
+        double dfSearchRadius = dfRadius;
+        sAoi.minx = dfXPoint - dfSearchRadius;
+        sAoi.miny = dfYPoint - dfSearchRadius;
+        sAoi.maxx = dfXPoint + dfSearchRadius;
+        sAoi.maxy = dfYPoint + dfSearchRadius;
+        int nFeatureCount = 0;
+        GDALGridPoint** papsPoints = (GDALGridPoint**)
+                CPLQuadTreeSearch(phQuadTree, &sAoi, &nFeatureCount);
+        if (nFeatureCount != 0)
+        {
+            for(int k = 0; k < nFeatureCount; k++)
+            {
+                int i = papsPoints[k]->i;
+                double  dfRX = padfX[i] - dfXPoint;
+                double  dfRY = padfY[i] - dfYPoint;
+
+                const double dfR2 = dfRX * dfRX + dfRY * dfRY;
+                if (dfR2 < 0.0000000000001)
+                {
+                    (*pdfValue) = padfZ[i];
+                    CPLFree(papsPoints);
+                    return CE_None;
+                }
+                if(dfR2 <= dfRPower2)
+                {
+                    oMapDistanceToZValues.insert(std::make_pair(dfR2, padfZ[i]));
+                }
+            }
+        }
+        CPLFree(papsPoints);
+    }
+    else
+    {
+        for (GUInt32 i = 0; i < nPoints; i++)
+        {
+            double dfRX = padfX[i] - dfXPoint;
+            double dfRY = padfY[i] - dfYPoint;
+            const double dfR2 =    dfRX * dfRX + dfRY * dfRY;
+
+            // Is this point located inside the search circle?
+            if (dfRPower2 * dfRX * dfRX + dfRPower2 * dfRY * dfRY <= dfRPower4)
+            {
+                // If the test point is close to the grid node, use the point
+                // value directly as a node value to avoid singularity.
+                if (dfR2 < 0.0000000000001)
+                {
+                    (*pdfValue) = padfZ[i];
+                    return CE_None;
+                }
+                else
+                {
+                    oMapDistanceToZValues.insert(std::make_pair(dfR2, padfZ[i]));
+                }
+            }
+        }
+    }
+
+    /**
+     * Examine all "neighbors" within the radius (sorted by distance via the multimap), and use the
+     * closest n points based on distance until the max is reached.
+     */
+    for(std::multimap<double, double>::iterator oMapDistanceToZValuesIter = oMapDistanceToZValues.begin();
+        oMapDistanceToZValuesIter != oMapDistanceToZValues.end();
+        ++oMapDistanceToZValuesIter)
+    {
+        double dfR2 = (*oMapDistanceToZValuesIter).first;
+        double dfZ = (*oMapDistanceToZValuesIter).second;
+
+        const double dfW = pow(dfR2, dfPowerDiv2);
+        double dfInvW = 1.0 / dfW;
+        dfNominator += dfInvW * dfZ;
+        dfDenominator += dfInvW;
+        n++;
+        if (nMaxPoints > 0 && n >= nMaxPoints)
+        {
+            break;
+        }
+    }
+
+    if (n < ((GDALGridInverseDistanceToAPowerNearestNeighborOptions *)poOptions)->nMinPoints
+         || dfDenominator == 0.0 )
+    {
+        (*pdfValue) =
+            ((GDALGridInverseDistanceToAPowerNearestNeighborOptions*)poOptions)->dfNoDataValue;
+    }
+    else
+    {
+        (*pdfValue) = dfNominator / dfDenominator;
+    }
+
+    return CE_None;
+}
+
+/************************************************************************/
 /*              GDALGridInverseDistanceToAPowerNoSearch()               */
 /************************************************************************/
 
@@ -341,7 +515,7 @@ GDALGridInverseDistanceToAPowerNoSearch( const void *poOptions, GUInt32 nPoints,
  *      Z=\frac{\sum_{i=1}^n{Z_i}}{n}
  * \f]
  *
- *  where 
+ *  where
  *  <ul>
  *      <li> \f$Z\f$ is a resulting value at the grid node,
  *      <li> \f$Z_i\f$ is a known value at point \f$i\f$,
@@ -349,11 +523,11 @@ GDALGridInverseDistanceToAPowerNoSearch( const void *poOptions, GUInt32 nPoints,
  *  </ul>
  *
  * @param poOptions Algorithm parameters. This should point to
- * GDALGridMovingAverageOptions object. 
+ * GDALGridMovingAverageOptions object.
  * @param nPoints Number of elements in input arrays.
- * @param padfX Input array of X coordinates. 
- * @param padfY Input array of Y coordinates. 
- * @param padfZ Input array of Z values. 
+ * @param padfX Input array of X coordinates.
+ * @param padfY Input array of Y coordinates.
+ * @param padfZ Input array of Z values.
  * @param dfXPoint X coordinate of the point to compute.
  * @param dfYPoint Y coordinate of the point to compute.
  * @param pdfValue Pointer to variable where the computed grid node value
@@ -444,11 +618,11 @@ GDALGridMovingAverage( const void *poOptions, GUInt32 nPoints,
  * NODATA value will be returned.
  *
  * @param poOptions Algorithm parameters. This should point to
- * GDALGridNearestNeighborOptions object. 
+ * GDALGridNearestNeighborOptions object.
  * @param nPoints Number of elements in input arrays.
- * @param padfX Input array of X coordinates. 
- * @param padfY Input array of Y coordinates. 
- * @param padfZ Input array of Z values. 
+ * @param padfX Input array of X coordinates.
+ * @param padfY Input array of Y coordinates.
+ * @param padfZ Input array of Z values.
  * @param dfXPoint X coordinate of the point to compute.
  * @param dfYPoint Y coordinate of the point to compute.
  * @param pdfValue Pointer to variable where the computed grid node value
@@ -520,15 +694,15 @@ GDALGridNearestNeighbor( const void *poOptions, GUInt32 nPoints,
                     dfNearestR = dfRadius1;
                 for(int k=0; k<nFeatureCount; k++)
                 {
-                    int i = papsPoints[k]->i;
-                    double  dfRX = padfX[i] - dfXPoint;
-                    double  dfRY = padfY[i] - dfYPoint;
+                    int idx = papsPoints[k]->i;
+                    double  dfRX = padfX[idx] - dfXPoint;
+                    double  dfRY = padfY[idx] - dfYPoint;
 
                     const double    dfR2 = dfRX * dfRX + dfRY * dfRY;
                     if( dfR2 <= dfNearestR )
                     {
                         dfNearestR = dfR2;
-                        dfNearestValue = padfZ[i];
+                        dfNearestValue = padfZ[idx];
                     }
                 }
 
@@ -595,7 +769,7 @@ GDALGridNearestNeighbor( const void *poOptions, GUInt32 nPoints,
  *      Z=\min{(Z_1,Z_2,\ldots,Z_n)}
  * \f]
  *
- *  where 
+ *  where
  *  <ul>
  *      <li> \f$Z\f$ is a resulting value at the grid node,
  *      <li> \f$Z_i\f$ is a known value at point \f$i\f$,
@@ -603,11 +777,11 @@ GDALGridNearestNeighbor( const void *poOptions, GUInt32 nPoints,
  *  </ul>
  *
  * @param poOptions Algorithm parameters. This should point to
- * GDALGridDataMetricsOptions object. 
+ * GDALGridDataMetricsOptions object.
  * @param nPoints Number of elements in input arrays.
- * @param padfX Input array of X coordinates. 
- * @param padfY Input array of Y coordinates. 
- * @param padfZ Input array of Z values. 
+ * @param padfX Input array of X coordinates.
+ * @param padfY Input array of Y coordinates.
+ * @param padfZ Input array of Z values.
  * @param dfXPoint X coordinate of the point to compute.
  * @param dfYPoint Y coordinate of the point to compute.
  * @param pdfValue Pointer to variable where the computed grid node value
@@ -707,7 +881,7 @@ GDALGridDataMetricMinimum( const void *poOptions, GUInt32 nPoints,
  *      Z=\max{(Z_1,Z_2,\ldots,Z_n)}
  * \f]
  *
- *  where 
+ *  where
  *  <ul>
  *      <li> \f$Z\f$ is a resulting value at the grid node,
  *      <li> \f$Z_i\f$ is a known value at point \f$i\f$,
@@ -715,11 +889,11 @@ GDALGridDataMetricMinimum( const void *poOptions, GUInt32 nPoints,
  *  </ul>
  *
  * @param poOptions Algorithm parameters. This should point to
- * GDALGridDataMetricsOptions object. 
+ * GDALGridDataMetricsOptions object.
  * @param nPoints Number of elements in input arrays.
- * @param padfX Input array of X coordinates. 
- * @param padfY Input array of Y coordinates. 
- * @param padfZ Input array of Z values. 
+ * @param padfX Input array of X coordinates.
+ * @param padfY Input array of Y coordinates.
+ * @param padfZ Input array of Z values.
  * @param dfXPoint X coordinate of the point to compute.
  * @param dfYPoint Y coordinate of the point to compute.
  * @param pdfValue Pointer to variable where the computed grid node value
@@ -820,7 +994,7 @@ GDALGridDataMetricMaximum( const void *poOptions, GUInt32 nPoints,
  *      Z=\max{(Z_1,Z_2,\ldots,Z_n)}-\min{(Z_1,Z_2,\ldots,Z_n)}
  * \f]
  *
- *  where 
+ *  where
  *  <ul>
  *      <li> \f$Z\f$ is a resulting value at the grid node,
  *      <li> \f$Z_i\f$ is a known value at point \f$i\f$,
@@ -828,11 +1002,11 @@ GDALGridDataMetricMaximum( const void *poOptions, GUInt32 nPoints,
  *  </ul>
  *
  * @param poOptions Algorithm parameters. This should point to
- * GDALGridDataMetricsOptions object. 
+ * GDALGridDataMetricsOptions object.
  * @param nPoints Number of elements in input arrays.
- * @param padfX Input array of X coordinates. 
- * @param padfY Input array of Y coordinates. 
- * @param padfZ Input array of Z values. 
+ * @param padfX Input array of X coordinates.
+ * @param padfY Input array of Y coordinates.
+ * @param padfZ Input array of Z values.
  * @param dfXPoint X coordinate of the point to compute.
  * @param dfYPoint Y coordinate of the point to compute.
  * @param pdfValue Pointer to variable where the computed grid node value
@@ -933,18 +1107,18 @@ GDALGridDataMetricRange( const void *poOptions, GUInt32 nPoints,
  *      Z=n
  * \f]
  *
- *  where 
+ *  where
  *  <ul>
  *      <li> \f$Z\f$ is a resulting value at the grid node,
  *      <li> \f$n\f$ is a total number of points in search ellipse.
  *  </ul>
  *
  * @param poOptions Algorithm parameters. This should point to
- * GDALGridDataMetricsOptions object. 
+ * GDALGridDataMetricsOptions object.
  * @param nPoints Number of elements in input arrays.
- * @param padfX Input array of X coordinates. 
- * @param padfY Input array of Y coordinates. 
- * @param padfZ Input array of Z values. 
+ * @param padfX Input array of X coordinates.
+ * @param padfY Input array of Y coordinates.
+ * @param padfZ Input array of Z values.
  * @param dfXPoint X coordinate of the point to compute.
  * @param dfYPoint Y coordinate of the point to compute.
  * @param pdfValue Pointer to variable where the computed grid node value
@@ -1034,7 +1208,7 @@ GDALGridDataMetricCount( const void *poOptions, GUInt32 nPoints,
  *      Z=\frac{\sum_{i = 1}^n r_i}{n}
  * \f]
  *
- *  where 
+ *  where
  *  <ul>
  *      <li> \f$Z\f$ is a resulting value at the grid node,
  *      <li> \f$r_i\f$ is an Euclidean distance from the grid node
@@ -1043,11 +1217,11 @@ GDALGridDataMetricCount( const void *poOptions, GUInt32 nPoints,
  *  </ul>
  *
  * @param poOptions Algorithm parameters. This should point to
- * GDALGridDataMetricsOptions object. 
+ * GDALGridDataMetricsOptions object.
  * @param nPoints Number of elements in input arrays.
- * @param padfX Input array of X coordinates. 
- * @param padfY Input array of Y coordinates. 
- * @param padfZ Input array of Z values. 
+ * @param padfX Input array of X coordinates.
+ * @param padfY Input array of Y coordinates.
+ * @param padfZ Input array of Z values.
  * @param dfXPoint X coordinate of the point to compute.
  * @param dfYPoint Y coordinate of the point to compute.
  * @param pdfValue Pointer to variable where the computed grid node value
@@ -1145,7 +1319,7 @@ GDALGridDataMetricAverageDistance( const void *poOptions, GUInt32 nPoints,
  *      Z=\frac{\sum_{i = 1}^{n-1}\sum_{j=i+1}^{n} r_{ij}}{\left(n-1\right)\,n-\frac{n+{\left(n-1\right)}^{2}-1}{2}}
  * \f]
  *
- *  where 
+ *  where
  *  <ul>
  *      <li> \f$Z\f$ is a resulting value at the grid node,
  *      <li> \f$r_{ij}\f$ is an Euclidean distance between points
@@ -1154,11 +1328,11 @@ GDALGridDataMetricAverageDistance( const void *poOptions, GUInt32 nPoints,
  *  </ul>
  *
  * @param poOptions Algorithm parameters. This should point to
- * GDALGridDataMetricsOptions object. 
+ * GDALGridDataMetricsOptions object.
  * @param nPoints Number of elements in input arrays.
- * @param padfX Input array of X coordinates. 
- * @param padfY Input array of Y coordinates. 
- * @param padfZ Input array of Z values. 
+ * @param padfX Input array of X coordinates.
+ * @param padfY Input array of Y coordinates.
+ * @param padfZ Input array of Z values.
  * @param dfXPoint X coordinate of the point to compute.
  * @param dfYPoint Y coordinate of the point to compute.
  * @param pdfValue Pointer to variable where the computed grid node value
@@ -1222,14 +1396,14 @@ GDALGridDataMetricAverageDistancePts( const void *poOptions, GUInt32 nPoints,
         if ( dfRadius2 * dfRX1 * dfRX1 + dfRadius1 * dfRY1 * dfRY1 <= dfR12 )
         {
             GUInt32 j;
-            
+
             // Search all the remaining points within the ellipse and compute
             // distances between them and the first point
             for ( j = i + 1; j < nPoints; j++ )
             {
                 double  dfRX2 = padfX[j] - dfXPoint;
                 double  dfRY2 = padfY[j] - dfYPoint;
-                
+
                 if ( bRotated )
                 {
                     double dfRXRotated = dfRX2 * dfCoeff1 + dfRY2 * dfCoeff2;
@@ -1266,6 +1440,110 @@ GDALGridDataMetricAverageDistancePts( const void *poOptions, GUInt32 nPoints,
 }
 
 /************************************************************************/
+/*                        GDALGridLinear()                              */
+/************************************************************************/
+
+/**
+ * Linear interpolation
+ *
+ * The Linear method performs linear interpolation by finding in which triangle
+ * of a Delaunay triangulation the point is, and by doing interpolation from
+ * its barycentric coordinates within the triangle.
+ * If the point is not in any triangle, depending on the radius, the
+ * algorithm will use the value of the nearest point or the nodata value.
+ *
+ * @param poOptions Algorithm parameters. This should point to
+ * GDALGridLinearOptions object.
+ * @param nPoints Number of elements in input arrays.
+ * @param padfX Input array of X coordinates.
+ * @param padfY Input array of Y coordinates.
+ * @param padfZ Input array of Z values.
+ * @param dfXPoint X coordinate of the point to compute.
+ * @param dfYPoint Y coordinate of the point to compute.
+ * @param pdfValue Pointer to variable where the computed grid node value
+ * will be returned.
+ *
+ * @return CE_None on success or CE_Failure if something goes wrong.
+ *
+ * @since GDAL 2.1
+ */
+
+CPLErr
+GDALGridLinear( const void *poOptions, CPL_UNUSED GUInt32 nPoints,
+                const double *padfX, const double *padfY,
+                const double *padfZ,
+                double dfXPoint, double dfYPoint, double *pdfValue,
+                void* hExtraParams )
+{
+    GDALGridExtraParameters* psExtraParams = (GDALGridExtraParameters*) hExtraParams;
+    GDALTriangulation* psTriangulation = psExtraParams->psTriangulation;
+
+    int nOutputFacetIdx = -1;
+    int bRet = GDALTriangulationFindFacetDirected( psTriangulation,
+                                                   psExtraParams->nInitialFacetIdx,
+                                                   dfXPoint, dfYPoint,
+                                                   &nOutputFacetIdx );
+    CPLAssert(nOutputFacetIdx >= 0);
+    // Reuse output facet idx as next initial index since we proceed line by line
+    psExtraParams->nInitialFacetIdx = nOutputFacetIdx;
+
+    if( bRet )
+    {
+        double lambda1, lambda2, lambda3;
+        GDALTriangulationComputeBarycentricCoordinates(
+                                                psTriangulation,
+                                                nOutputFacetIdx,
+                                                dfXPoint, dfYPoint,
+                                                &lambda1, &lambda2, &lambda3);
+        int i1 = psTriangulation->pasFacets[nOutputFacetIdx].anVertexIdx[0];
+        int i2 = psTriangulation->pasFacets[nOutputFacetIdx].anVertexIdx[1];
+        int i3 = psTriangulation->pasFacets[nOutputFacetIdx].anVertexIdx[2];
+        *pdfValue = lambda1 * padfZ[i1] + lambda2 * padfZ[i2] + lambda3 * padfZ[i3];
+    }
+    else
+    {
+        double dfRadius = ((GDALGridLinearOptions*)poOptions)->dfRadius;
+        if( dfRadius == 0 )
+            *pdfValue = ((GDALGridLinearOptions*)poOptions)->dfNoDataValue;
+        else
+        {
+            GDALGridNearestNeighborOptions sNeighbourOptions;
+            sNeighbourOptions.dfRadius1 = dfRadius < 0 ? 0 : dfRadius;
+            sNeighbourOptions.dfRadius2 = dfRadius < 0 ? 0 : dfRadius;
+            sNeighbourOptions.dfAngle = 0;
+            sNeighbourOptions.dfNoDataValue = ((GDALGridLinearOptions*)poOptions)->dfNoDataValue;
+            return GDALGridNearestNeighbor(&sNeighbourOptions, nPoints,
+                                        padfX, padfY, padfZ,
+                                        dfXPoint, dfYPoint, pdfValue,
+                                        hExtraParams);
+#if 0
+            // Disabled since the nearest point is not necessarily the nearest
+            // vertex of the "nearest" triangle
+            int iBestIdx;
+            double dfBestDist;
+            for(int i=0;i<3;i++)
+            {
+                int idx = psTriangulation->pasFacets[nOutputFacetIdx].anVertexIdx[i];
+                double dfDist = (padfX[idx] - dfXPoint) * (padfX[idx] - dfXPoint) +
+                                (padfY[idx] - dfYPoint) * (padfY[idx] - dfYPoint);
+                if( i == 0 || dfDist < dfBestDist )
+                {
+                    iBestIdx = idx;
+                    dfBestDist = dfDist;
+                }
+            }
+            if( dfRadius < 0 || dfBestDist <= dfRadius * dfRadius )
+                *pdfValue = padfZ[iBestIdx];
+            else
+                *pdfValue = ((GDALGridLinearOptions*)poOptions)->dfNoDataValue;
+#endif
+        }
+    }
+
+    return CE_None;
+}
+
+/************************************************************************/
 /*                             GDALGridJob                              */
 /************************************************************************/
 
@@ -1293,7 +1571,6 @@ struct _GDALGridJob
     int               (*pfnProgress)(GDALGridJob* psJob);
     GDALDataType        eType;
 
-    CPLJoinableThread  *hThread;
     volatile int   *pnCounter;
     volatile int   *pbStop;
     CPLCond        *hCond;
@@ -1362,11 +1639,13 @@ static void GDALGridJobProcess(void* user_data)
     const double* padfZ = psJob->padfZ;
     const void *poOptions = psJob->poOptions;
     GDALGridFunction  pfnGDALGridMethod = psJob->pfnGDALGridMethod;
-    GDALGridExtraParameters *psExtraParameters = psJob->psExtraParameters;
+    // Have a local copy of sExtraParameters since we want to modify
+    // nInitialFacetIdx
+    GDALGridExtraParameters sExtraParameters = *(psJob->psExtraParameters);
     GDALDataType eType = psJob->eType;
     int (*pfnProgress)(GDALGridJob* psJob) = psJob->pfnProgress;
 
-    int         nDataTypeSize = GDALGetDataTypeSize(eType) / 8;
+    int         nDataTypeSize = GDALGetDataTypeSizeBytes(eType);
     int         nLineSpace = nXSize * nDataTypeSize;
 
     /* -------------------------------------------------------------------- */
@@ -1374,11 +1653,12 @@ static void GDALGridJobProcess(void* user_data)
     /*  and use GDALCopyWords() to copy values into output data array with  */
     /*  appropriate data type conversion.                                   */
     /* -------------------------------------------------------------------- */
-    double      *padfValues = (double *)VSIMalloc2( sizeof(double), nXSize );
+    double      *padfValues = (double *)VSI_MALLOC2_VERBOSE( sizeof(double), nXSize );
     if( padfValues == NULL )
     {
         *(psJob->pbStop) = TRUE;
-        pfnProgress(psJob); /* to notify the main thread */
+        if( pfnProgress != NULL )
+            pfnProgress(psJob); /* to notify the main thread */
         return;
     }
 
@@ -1392,14 +1672,15 @@ static void GDALGridJobProcess(void* user_data)
 
             if ( (*pfnGDALGridMethod)( poOptions, nPoints, padfX, padfY, padfZ,
                                        dfXPoint, dfYPoint,
-                                       padfValues + nXPoint, psExtraParameters ) != CE_None )
+                                       padfValues + nXPoint, &sExtraParameters ) != CE_None )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
                           "Gridding failed at X position %lu, Y position %lu",
                           (long unsigned int)nXPoint,
                           (long unsigned int)nYPoint );
                 *(psJob->pbStop) = TRUE;
-                pfnProgress(psJob); /* to notify the main thread */
+                if( pfnProgress != NULL )
+                    pfnProgress(psJob); /* to notify the main thread */
                 break;
             }
         }
@@ -1408,7 +1689,7 @@ static void GDALGridJobProcess(void* user_data)
                        pabyData + nYPoint * nLineSpace, eType, nDataTypeSize,
                        nXSize );
 
-        if( *(psJob->pbStop) || pfnProgress(psJob) )
+        if( *(psJob->pbStop) || (pfnProgress != NULL && pfnProgress(psJob)) )
             break;
     }
 
@@ -1416,81 +1697,85 @@ static void GDALGridJobProcess(void* user_data)
 }
 
 /************************************************************************/
-/*                            GDALGridCreate()                          */
+/*                        GDALGridContextCreate()                       */
 /************************************************************************/
 
+struct GDALGridContext
+{
+    GDALGridAlgorithm  eAlgorithm;
+    void               *poOptions;
+    GDALGridFunction    pfnGDALGridMethod;
+
+    GUInt32             nPoints;
+    GDALGridPoint      *pasGridPoints;
+    GDALGridXYArrays    sXYArrays;
+
+    GDALGridExtraParameters sExtraParameters;
+    double*             padfX;
+    double*             padfY;
+    double*             padfZ;
+    int                 bFreePadfXYZArrays;
+
+    void               *pabyX;
+    void               *pabyY;
+    void               *pabyZ;
+
+    CPLWorkerThreadPool *poWorkerThreadPool;
+};
+
+static void GDALGridContextCreateQuadTree(GDALGridContext* psContext);
+
 /**
- * Create regular grid from the scattered data.
+ * Creates a context to do regular gridding from the scattered data.
  *
  * This function takes the arrays of X and Y coordinates and corresponding Z
- * values as input and computes regular grid (or call it a raster) from these
- * scattered data. You should supply geometry and extent of the output grid
- * and allocate array sufficient to hold such a grid.
- *
- * Starting with GDAL 1.10, it is possible to set the GDAL_NUM_THREADS
- * configuration option to parallelize the processing. The value to set is
- * the number of worker threads, or ALL_CPUS to use all the cores/CPUs of the
- * computer (default value).
+ * values as input to prepare computation of regular grid (or call it a raster)
+ * from these scattered data.
  *
- * Starting with GDAL 1.10, on Intel/AMD i386/x86_64 architectures, some
+ * On Intel/AMD i386/x86_64 architectures, some
  * gridding methods will be optimized with SSE instructions (provided GDAL
- * has been compiled with such support, and it is availabable at runtime).
+ * has been compiled with such support, and it is available at runtime).
  * Currently, only 'invdist' algorithm with default parameters has an optimized
  * implementation.
  * This can provide substantial speed-up, but sometimes at the expense of
  * reduced floating point precision. This can be disabled by setting the
  * GDAL_USE_SSE configuration option to NO.
- * Starting with GDAL 1.11, a further optimized version can use the AVX
+ * A further optimized version can use the AVX
  * instruction set. This can be disabled by setting the GDAL_USE_AVX
  * configuration option to NO.
- * 
  *
- * @param eAlgorithm Gridding method. 
- * @param poOptions Options to control choosen gridding method.
+ * It is possible to set the GDAL_NUM_THREADS
+ * configuration option to parallelize the processing. The value to set is
+ * the number of worker threads, or ALL_CPUS to use all the cores/CPUs of the
+ * computer (default value).
+ *
+ * @param eAlgorithm Gridding method.
+ * @param poOptions Options to control chosen gridding method.
  * @param nPoints Number of elements in input arrays.
- * @param padfX Input array of X coordinates. 
- * @param padfY Input array of Y coordinates. 
- * @param padfZ Input array of Z values. 
- * @param dfXMin Lowest X border of output grid.
- * @param dfXMax Highest X border of output grid.
- * @param dfYMin Lowest Y border of output grid.
- * @param dfYMax Highest Y border of output grid.
- * @param nXSize Number of columns in output grid.
- * @param nYSize Number of rows in output grid.
- * @param eType Data type of output array.  
- * @param pData Pointer to array where the computed grid will be stored.
- * @param pfnProgress a GDALProgressFunc() compatible callback function for
- * reporting progress or NULL.
- * @param pProgressArg argument to be passed to pfnProgress.  May be NULL.
+ * @param padfX Input array of X coordinates.
+ * @param padfY Input array of Y coordinates.
+ * @param padfZ Input array of Z values.
+ * @param bCallerWillKeepPointArraysAlive Whether the provided padfX, padfY, padfZ
+ *        arrays will still be "alive" during the calls to GDALGridContextProcess().
+ *        Setting to TRUE prevent them from being duplicated in the context.
+ *        If unsure, set to FALSE.
  *
- * @return CE_None on success or CE_Failure if something goes wrong.
+ * @return the context (to be freed with GDALGridContextFree()) or NULL in case or error
+ *
+ * @since GDAL 2.1
  */
 
-CPLErr
-GDALGridCreate( GDALGridAlgorithm eAlgorithm, const void *poOptions,
-                GUInt32 nPoints,
-                const double *padfX, const double *padfY, const double *padfZ,
-                double dfXMin, double dfXMax, double dfYMin, double dfYMax,
-                GUInt32 nXSize, GUInt32 nYSize, GDALDataType eType, void *pData,
-                GDALProgressFunc pfnProgress, void *pProgressArg )
+GDALGridContext*
+GDALGridContextCreate( GDALGridAlgorithm eAlgorithm, const void *poOptions,
+                       GUInt32 nPoints,
+                       const double *padfX, const double *padfY, const double *padfZ,
+                       int bCallerWillKeepPointArraysAlive )
 {
+    GDALGridFunction    pfnGDALGridMethod = NULL;
     CPLAssert( poOptions );
     CPLAssert( padfX );
     CPLAssert( padfY );
     CPLAssert( padfZ );
-    CPLAssert( pData );
-
-    if ( pfnProgress == NULL )
-        pfnProgress = GDALDummyProgress;
-
-    if ( nXSize == 0 || nYSize == 0 )
-    {
-        CPLError( CE_Failure, CPLE_IllegalArg,
-                  "Output raster dimesions should have non-zero size." );
-        return CE_Failure;
-    }
-
-    GDALGridFunction    pfnGDALGridMethod;
     int bCreateQuadTree = FALSE;
 
     /* Potentially unaligned pointers */
@@ -1503,9 +1788,14 @@ GDALGridCreate( GDALGridAlgorithm eAlgorithm, const void *poOptions,
     float* pafYAligned = NULL;
     float* pafZAligned = NULL;
 
+    void *poOptionsNew = NULL;
+
     switch ( eAlgorithm )
     {
         case GGA_InverseDistanceToAPower:
+            poOptionsNew = CPLMalloc(sizeof(GDALGridInverseDistanceToAPowerOptions));
+            memcpy(poOptionsNew, poOptions, sizeof(GDALGridInverseDistanceToAPowerOptions));
+
             if ( ((GDALGridInverseDistanceToAPowerOptions *)poOptions)->
                  dfRadius1 == 0.0 &&
                  ((GDALGridInverseDistanceToAPowerOptions *)poOptions)->
@@ -1523,12 +1813,12 @@ GDALGridCreate( GDALGridAlgorithm eAlgorithm, const void *poOptions,
 
 #define ALIGN32(x)  (((char*)(x)) + ((32 - (((size_t)(x)) % 32)) % 32))
 
-                    if( CSLTestBoolean(CPLGetConfigOption("GDAL_USE_AVX", "YES")) &&
+                    if( CPLTestBool(CPLGetConfigOption("GDAL_USE_AVX", "YES")) &&
                         CPLHaveRuntimeAVX() )
                     {
-                        pabyX = (float*)VSIMalloc(sizeof(float) * nPoints + 31);
-                        pabyY = (float*)VSIMalloc(sizeof(float) * nPoints + 31);
-                        pabyZ = (float*)VSIMalloc(sizeof(float) * nPoints + 31);
+                        pabyX = (float*)VSI_MALLOC_VERBOSE(sizeof(float) * nPoints + 31);
+                        pabyY = (float*)VSI_MALLOC_VERBOSE(sizeof(float) * nPoints + 31);
+                        pabyZ = (float*)VSI_MALLOC_VERBOSE(sizeof(float) * nPoints + 31);
                         if( pabyX != NULL && pabyY != NULL && pabyZ != NULL)
                         {
                             CPLDebug("GDAL_GRID", "Using AVX optimized version");
@@ -1559,12 +1849,12 @@ GDALGridCreate( GDALGridAlgorithm eAlgorithm, const void *poOptions,
 #define ALIGN16(x)  (((char*)(x)) + ((16 - (((size_t)(x)) % 16)) % 16))
 
                     if( pafXAligned == NULL &&
-                        CSLTestBoolean(CPLGetConfigOption("GDAL_USE_SSE", "YES")) &&
+                        CPLTestBool(CPLGetConfigOption("GDAL_USE_SSE", "YES")) &&
                         CPLHaveRuntimeSSE() )
                     {
-                        pabyX = (float*)VSIMalloc(sizeof(float) * nPoints + 15);
-                        pabyY = (float*)VSIMalloc(sizeof(float) * nPoints + 15);
-                        pabyZ = (float*)VSIMalloc(sizeof(float) * nPoints + 15);
+                        pabyX = (float*)VSI_MALLOC_VERBOSE(sizeof(float) * nPoints + 15);
+                        pabyY = (float*)VSI_MALLOC_VERBOSE(sizeof(float) * nPoints + 15);
+                        pabyZ = (float*)VSI_MALLOC_VERBOSE(sizeof(float) * nPoints + 15);
                         if( pabyX != NULL && pabyY != NULL && pabyZ != NULL)
                         {
                             CPLDebug("GDAL_GRID", "Using SSE optimized version");
@@ -1595,11 +1885,25 @@ GDALGridCreate( GDALGridAlgorithm eAlgorithm, const void *poOptions,
                 pfnGDALGridMethod = GDALGridInverseDistanceToAPower;
             break;
 
+        case GGA_InverseDistanceToAPowerNearestNeighbor:
+            poOptionsNew = CPLMalloc(sizeof(GDALGridInverseDistanceToAPowerNearestNeighborOptions));
+            memcpy(poOptionsNew, poOptions, sizeof(GDALGridInverseDistanceToAPowerNearestNeighborOptions));
+
+            pfnGDALGridMethod = GDALGridInverseDistanceToAPowerNearestNeighbor;
+            bCreateQuadTree = TRUE;
+            break;
+
         case GGA_MovingAverage:
+            poOptionsNew = CPLMalloc(sizeof(GDALGridMovingAverageOptions));
+            memcpy(poOptionsNew, poOptions, sizeof(GDALGridMovingAverageOptions));
+
             pfnGDALGridMethod = GDALGridMovingAverage;
             break;
 
         case GGA_NearestNeighbor:
+            poOptionsNew = CPLMalloc(sizeof(GDALGridNearestNeighborOptions));
+            memcpy(poOptionsNew, poOptions, sizeof(GDALGridNearestNeighborOptions));
+
             pfnGDALGridMethod = GDALGridNearestNeighbor;
             bCreateQuadTree = (nPoints > 100 &&
                 (((GDALGridNearestNeighborOptions *)poOptions)->dfRadius1 ==
@@ -1607,94 +1911,144 @@ GDALGridCreate( GDALGridAlgorithm eAlgorithm, const void *poOptions,
             break;
 
         case GGA_MetricMinimum:
+            poOptionsNew = CPLMalloc(sizeof(GDALGridDataMetricsOptions));
+            memcpy(poOptionsNew, poOptions, sizeof(GDALGridDataMetricsOptions));
+
             pfnGDALGridMethod = GDALGridDataMetricMinimum;
             break;
 
         case GGA_MetricMaximum:
+            poOptionsNew = CPLMalloc(sizeof(GDALGridDataMetricsOptions));
+            memcpy(poOptionsNew, poOptions, sizeof(GDALGridDataMetricsOptions));
+
             pfnGDALGridMethod = GDALGridDataMetricMaximum;
             break;
 
         case GGA_MetricRange:
+            poOptionsNew = CPLMalloc(sizeof(GDALGridDataMetricsOptions));
+            memcpy(poOptionsNew, poOptions, sizeof(GDALGridDataMetricsOptions));
+
             pfnGDALGridMethod = GDALGridDataMetricRange;
             break;
 
         case GGA_MetricCount:
+            poOptionsNew = CPLMalloc(sizeof(GDALGridDataMetricsOptions));
+            memcpy(poOptionsNew, poOptions, sizeof(GDALGridDataMetricsOptions));
+
             pfnGDALGridMethod = GDALGridDataMetricCount;
             break;
 
         case GGA_MetricAverageDistance:
+            poOptionsNew = CPLMalloc(sizeof(GDALGridDataMetricsOptions));
+            memcpy(poOptionsNew, poOptions, sizeof(GDALGridDataMetricsOptions));
+
             pfnGDALGridMethod = GDALGridDataMetricAverageDistance;
             break;
 
         case GGA_MetricAverageDistancePts:
+            poOptionsNew = CPLMalloc(sizeof(GDALGridDataMetricsOptions));
+            memcpy(poOptionsNew, poOptions, sizeof(GDALGridDataMetricsOptions));
+
             pfnGDALGridMethod = GDALGridDataMetricAverageDistancePts;
             break;
 
+        case GGA_Linear:
+            poOptionsNew = CPLMalloc(sizeof(GDALGridLinearOptions));
+            memcpy(poOptionsNew, poOptions, sizeof(GDALGridLinearOptions));
+
+            pfnGDALGridMethod = GDALGridLinear;
+            break;
+
         default:
             CPLError( CE_Failure, CPLE_IllegalArg,
                       "GDAL does not support gridding method %d", eAlgorithm );
-	    return CE_Failure;
+            return NULL;
     }
 
-    const double    dfDeltaX = ( dfXMax - dfXMin ) / nXSize;
-    const double    dfDeltaY = ( dfYMax - dfYMin ) / nYSize;
+    if( pafXAligned != NULL )
+        bCallerWillKeepPointArraysAlive = TRUE;
+    if( !bCallerWillKeepPointArraysAlive )
+    {
+        double* padfXNew = (double*)VSI_MALLOC2_VERBOSE(nPoints, sizeof(double));
+        double* padfYNew = (double*)VSI_MALLOC2_VERBOSE(nPoints, sizeof(double));
+        double* padfZNew = (double*)VSI_MALLOC2_VERBOSE(nPoints, sizeof(double));
+        if( padfXNew == NULL || padfYNew == NULL || padfZNew == NULL )
+        {
+            VSIFree(padfXNew);
+            VSIFree(padfYNew);
+            VSIFree(padfZNew);
+            CPLFree(poOptionsNew);
+            return NULL;
+        }
+        memcpy(padfXNew, padfX, nPoints * sizeof(double));
+        memcpy(padfYNew, padfY, nPoints * sizeof(double));
+        memcpy(padfZNew, padfZ, nPoints * sizeof(double));
+        padfX = padfXNew;
+        padfY = padfYNew;
+        padfZ = padfZNew;
+    }
+    GDALGridContext* psContext = (GDALGridContext*)CPLCalloc(1, sizeof(GDALGridContext));
+    psContext->eAlgorithm = eAlgorithm;
+    psContext->poOptions = poOptionsNew;
+    psContext->pfnGDALGridMethod = pfnGDALGridMethod;
+    psContext->nPoints = nPoints;
+    psContext->pasGridPoints = NULL;
+    psContext->sXYArrays.padfX = padfX;
+    psContext->sXYArrays.padfY = padfY;
+    psContext->sExtraParameters.hQuadTree = NULL;
+    psContext->sExtraParameters.dfInitialSearchRadius = 0;
+    psContext->sExtraParameters.pafX = pafXAligned;
+    psContext->sExtraParameters.pafY = pafYAligned;
+    psContext->sExtraParameters.pafZ = pafZAligned;
+    psContext->sExtraParameters.psTriangulation = NULL;
+    psContext->sExtraParameters.nInitialFacetIdx = 0;
+    psContext->padfX = pafXAligned ? NULL : (double*)padfX;
+    psContext->padfY = pafXAligned ? NULL : (double*)padfY;
+    psContext->padfZ = pafXAligned ? NULL : (double*)padfZ;
+    psContext->bFreePadfXYZArrays = !bCallerWillKeepPointArraysAlive;
+    psContext->pabyX = pabyX;
+    psContext->pabyY = pabyY;
+    psContext->pabyZ = pabyZ;
 
 /* -------------------------------------------------------------------- */
 /*  Create quadtree if requested and possible.                          */
 /* -------------------------------------------------------------------- */
-    CPLQuadTree* hQuadTree = NULL;
-    double       dfInitialSearchRadius = 0;
-    GDALGridPoint* pasGridPoints = NULL;
-    GDALGridXYArrays sXYArrays;
-    sXYArrays.padfX = padfX;
-    sXYArrays.padfY = padfY;
-
     if( bCreateQuadTree )
     {
-        pasGridPoints = (GDALGridPoint*) VSIMalloc2(nPoints, sizeof(GDALGridPoint));
-        if( pasGridPoints != NULL )
-        {
-            CPLRectObj sRect;
-            GUInt32 i;
-
-            /* Determine point extents */
-            sRect.minx = padfX[0];
-            sRect.miny = padfY[0];
-            sRect.maxx = padfX[0];
-            sRect.maxy = padfY[0];
-            for(i = 1; i < nPoints; i++)
-            {
-                if( padfX[i] < sRect.minx ) sRect.minx = padfX[i];
-                if( padfY[i] < sRect.miny ) sRect.miny = padfY[i];
-                if( padfX[i] > sRect.maxx ) sRect.maxx = padfX[i];
-                if( padfY[i] > sRect.maxy ) sRect.maxy = padfY[i];
-            }
-
-            /* Initial value for search radius is the typical dimension of a */
-            /* "pixel" of the point array (assuming rather uniform distribution) */
-            dfInitialSearchRadius = sqrt((sRect.maxx - sRect.minx) *
-                                         (sRect.maxy - sRect.miny) / nPoints);
+        GDALGridContextCreateQuadTree(psContext);
+    }
 
-            hQuadTree = CPLQuadTreeCreate(&sRect, GDALGridGetPointBounds );
+    /* -------------------------------------------------------------------- */
+    /*  Pre-compute extra parameters in GDALGridExtraParameters              */
+    /* -------------------------------------------------------------------- */
+    if( eAlgorithm == GGA_InverseDistanceToAPowerNearestNeighbor )
+    {
+        const double dfPower =
+            ((GDALGridInverseDistanceToAPowerNearestNeighborOptions *)poOptions)->dfPower;
+        psContext->sExtraParameters.dfPowerDiv2PreComp = dfPower / 2;
+
+        const double dfRadius =
+            ((GDALGridInverseDistanceToAPowerNearestNeighborOptions *)poOptions)->dfRadius;
+        psContext->sExtraParameters.dfRadiusPower2PreComp = pow ( dfRadius, 2 );
+        psContext->sExtraParameters.dfRadiusPower4PreComp = pow ( dfRadius, 4 );
+    }
 
-            for(i = 0; i < nPoints; i++)
-            {
-                pasGridPoints[i].psXYArrays = &sXYArrays;
-                pasGridPoints[i].i = i;
-                CPLQuadTreeInsert(hQuadTree, pasGridPoints + i);
-            }
+    if( eAlgorithm == GGA_Linear )
+    {
+        psContext->sExtraParameters.psTriangulation =
+                GDALTriangulationCreateDelaunay(nPoints, padfX, padfY);
+        if( psContext->sExtraParameters.psTriangulation == NULL )
+        {
+            GDALGridContextFree(psContext);
+            return NULL;
         }
+        GDALTriangulationComputeBarycentricCoefficients(
+            psContext->sExtraParameters.psTriangulation, padfX, padfY );
     }
 
-
-    GDALGridExtraParameters sExtraParameters;
-
-    sExtraParameters.hQuadTree = hQuadTree;
-    sExtraParameters.dfInitialSearchRadius = dfInitialSearchRadius;
-    sExtraParameters.pafX = pafXAligned;
-    sExtraParameters.pafY = pafYAligned;
-    sExtraParameters.pafZ = pafZAligned;
-
+/* -------------------------------------------------------------------- */
+/*  Start thread pool.                                                  */
+/* -------------------------------------------------------------------- */
     const char* pszThreads = CPLGetConfigOption("GDAL_NUM_THREADS", "ALL_CPUS");
     int nThreads;
     if (EQUAL(pszThreads, "ALL_CPUS"))
@@ -1703,12 +2057,217 @@ GDALGridCreate( GDALGridAlgorithm eAlgorithm, const void *poOptions,
         nThreads = atoi(pszThreads);
     if (nThreads > 128)
         nThreads = 128;
-    if (nThreads >= (int)nYSize / 2)
-        nThreads = (int)nYSize / 2;
+    if( nThreads > 1 )
+    {
+        psContext->poWorkerThreadPool = new CPLWorkerThreadPool();
+        if( !psContext->poWorkerThreadPool->Setup(nThreads, NULL, NULL) )
+        {
+            delete psContext->poWorkerThreadPool;
+            psContext->poWorkerThreadPool = NULL;
+        }
+        else
+        {
+            CPLDebug("GDAL_GRID", "Using %d threads", nThreads);
+        }
+    }
+    else
+        psContext->poWorkerThreadPool = NULL;
+
+    return psContext;
+}
+
+/************************************************************************/
+/*                      GDALGridContextCreateQuadTree()                 */
+/************************************************************************/
+
+void GDALGridContextCreateQuadTree(GDALGridContext* psContext)
+{
+    GUInt32 nPoints = psContext->nPoints;
+    psContext->pasGridPoints = (GDALGridPoint*)
+            VSI_MALLOC2_VERBOSE(nPoints, sizeof(GDALGridPoint));
+    if( psContext->pasGridPoints != NULL )
+    {
+        const double* padfX = psContext->padfX;
+        const double* padfY = psContext->padfY;
+
+        CPLRectObj sRect;
+        GUInt32 i;
+
+        /* Determine point extents */
+        sRect.minx = padfX[0];
+        sRect.miny = padfY[0];
+        sRect.maxx = padfX[0];
+        sRect.maxy = padfY[0];
+        for(i = 1; i < nPoints; i++)
+        {
+            if( padfX[i] < sRect.minx ) sRect.minx = padfX[i];
+            if( padfY[i] < sRect.miny ) sRect.miny = padfY[i];
+            if( padfX[i] > sRect.maxx ) sRect.maxx = padfX[i];
+            if( padfY[i] > sRect.maxy ) sRect.maxy = padfY[i];
+        }
+
+        /* Initial value for search radius is the typical dimension of a */
+        /* "pixel" of the point array (assuming rather uniform distribution) */
+        psContext->sExtraParameters.dfInitialSearchRadius =
+                                sqrt((sRect.maxx - sRect.minx) *
+                                        (sRect.maxy - sRect.miny) / nPoints);
+
+        psContext->sExtraParameters.hQuadTree =
+                    CPLQuadTreeCreate(&sRect, GDALGridGetPointBounds );
+
+        for(i = 0; i < nPoints; i++)
+        {
+            psContext->pasGridPoints[i].psXYArrays = &(psContext->sXYArrays);
+            psContext->pasGridPoints[i].i = i;
+            CPLQuadTreeInsert(psContext->sExtraParameters.hQuadTree,
+                                psContext->pasGridPoints + i);
+        }
+    }
+}
+
+/************************************************************************/
+/*                        GDALGridContextFree()                         */
+/************************************************************************/
+
+/**
+ * Free a context used created by GDALGridContextCreate()
+ *
+ * @param psContext the context.
+ *
+ * @since GDAL 2.1
+ */
+void GDALGridContextFree(GDALGridContext* psContext)
+{
+    if( psContext )
+    {
+        CPLFree( psContext->poOptions );
+        CPLFree( psContext->pasGridPoints );
+        if( psContext->sExtraParameters.hQuadTree != NULL )
+            CPLQuadTreeDestroy( psContext->sExtraParameters.hQuadTree );
+        if( psContext->bFreePadfXYZArrays )
+        {
+            CPLFree(psContext->padfX);
+            CPLFree(psContext->padfY);
+            CPLFree(psContext->padfZ);
+        }
+        CPLFree(psContext->pabyX);
+        CPLFree(psContext->pabyY);
+        CPLFree(psContext->pabyZ);
+        if( psContext->sExtraParameters.psTriangulation )
+            GDALTriangulationFree( psContext->sExtraParameters.psTriangulation );
+        delete psContext->poWorkerThreadPool;
+        CPLFree(psContext);
+    }
+}
+
+/************************************************************************/
+/*                        GDALGridContextProcess()                      */
+/************************************************************************/
+
+/**
+ * Do the gridding of a window of a raster.
+ *
+ * This function takes the gridding context as input to preprare computation
+ * of regular grid (or call it a raster) from these scattered data.
+ * You should supply the extent of the output grid and allocate array
+ * sufficient to hold such a grid.
+ *
+ * @param psContext Gridding context.
+ * @param dfXMin Lowest X border of output grid.
+ * @param dfXMax Highest X border of output grid.
+ * @param dfYMin Lowest Y border of output grid.
+ * @param dfYMax Highest Y border of output grid.
+ * @param nXSize Number of columns in output grid.
+ * @param nYSize Number of rows in output grid.
+ * @param eType Data type of output array.
+ * @param pData Pointer to array where the computed grid will be stored.
+ * @param pfnProgress a GDALProgressFunc() compatible callback function for
+ * reporting progress or NULL.
+ * @param pProgressArg argument to be passed to pfnProgress.  May be NULL.
+ *
+ * @return CE_None on success or CE_Failure if something goes wrong.
+ *
+ * @since GDAL 2.1
+ */
+
+CPLErr GDALGridContextProcess(GDALGridContext* psContext,
+                              double dfXMin, double dfXMax, double dfYMin, double dfYMax,
+                              GUInt32 nXSize, GUInt32 nYSize, GDALDataType eType, void *pData,
+                              GDALProgressFunc pfnProgress, void *pProgressArg )
+{
+    CPLAssert( psContext );
+    CPLAssert( pData );
+
+    if ( nXSize == 0 || nYSize == 0 )
+    {
+        CPLError( CE_Failure, CPLE_IllegalArg,
+                  "Output raster dimensions should have non-zero size." );
+        return CE_Failure;
+    }
+
+    const double    dfDeltaX = ( dfXMax - dfXMin ) / nXSize;
+    const double    dfDeltaY = ( dfYMax - dfYMin ) / nYSize;
+
+    // For linear, check if we will need to fallback to nearest neighbour
+    // by sampling along the edges (if all points on edges are within triangles,
+    // then interior points will also be!)
+    if( psContext->eAlgorithm == GGA_Linear &&
+        psContext->sExtraParameters.hQuadTree == NULL )
+    {
+        int bNeedNearest = FALSE;
+        int nStartLeft = 0, nStartRight = 0;
+        const double    dfXPointMin = dfXMin + ( 0 + 0.5 ) * dfDeltaX;
+        const double    dfXPointMax = dfXMin + ( nXSize - 1 + 0.5 ) * dfDeltaX;
+        for ( GUInt32 nYPoint = 0; !bNeedNearest && nYPoint < nYSize; nYPoint ++ )
+        {
+            const double    dfYPoint = dfYMin + ( nYPoint + 0.5 ) * dfDeltaY;
+
+            if( !GDALTriangulationFindFacetDirected( psContext->sExtraParameters.psTriangulation,
+                                                     nStartLeft,
+                                                     dfXPointMin, dfYPoint,
+                                                     &nStartLeft) )
+            {
+                bNeedNearest = TRUE;
+            }
+            if( !GDALTriangulationFindFacetDirected( psContext->sExtraParameters.psTriangulation,
+                                                     nStartRight,
+                                                     dfXPointMax, dfYPoint,
+                                                     &nStartRight) )
+            {
+                bNeedNearest = TRUE;
+            }
+        }
+        int nStartTop = 0, nStartBottom = 0;
+        const double    dfYPointMin = dfYMin + ( 0 + 0.5 ) * dfDeltaY;
+        const double    dfYPointMax = dfYMin + ( nYSize - 1 + 0.5 ) * dfDeltaY;
+        for ( GUInt32 nXPoint = 1; !bNeedNearest && nXPoint + 1 < nXSize; nXPoint ++ )
+        {
+            const double    dfXPoint = dfXMin + ( nXPoint + 0.5 ) * dfDeltaX;
+
+            if( !GDALTriangulationFindFacetDirected( psContext->sExtraParameters.psTriangulation,
+                                                     nStartTop,
+                                                     dfXPoint, dfYPointMin,
+                                                     &nStartTop) )
+            {
+                bNeedNearest = TRUE;
+            }
+            if( !GDALTriangulationFindFacetDirected( psContext->sExtraParameters.psTriangulation,
+                                                     nStartBottom,
+                                                     dfXPoint, dfYPointMax,
+                                                     &nStartBottom) )
+            {
+                bNeedNearest = TRUE;
+            }
+        }
+        if( bNeedNearest )
+        {
+            CPLDebug("GDAL_GRID", "Will need nearest neighbour");
+            GDALGridContextCreateQuadTree(psContext);
+        }
+    }
 
     volatile int nCounter = 0;
     volatile int bStop = FALSE;
-
     GDALGridJob sJob;
     sJob.nYStart = 0;
     sJob.pabyData = (GByte*) pData;
@@ -1719,13 +2278,13 @@ GDALGridCreate( GDALGridAlgorithm eAlgorithm, const void *poOptions,
     sJob.dfYMin = dfYMin;
     sJob.dfDeltaX = dfDeltaX;
     sJob.dfDeltaY = dfDeltaY;
-    sJob.nPoints = nPoints;
-    sJob.padfX = padfX;
-    sJob.padfY = padfY;
-    sJob.padfZ = padfZ;
-    sJob.poOptions = poOptions;
-    sJob.pfnGDALGridMethod = pfnGDALGridMethod;
-    sJob.psExtraParameters = &sExtraParameters;
+    sJob.nPoints = psContext->nPoints;
+    sJob.padfX = psContext->padfX;
+    sJob.padfY = psContext->padfY;
+    sJob.padfZ = psContext->padfZ;
+    sJob.poOptions = psContext->poOptions;
+    sJob.pfnGDALGridMethod = psContext->pfnGDALGridMethod;
+    sJob.psExtraParameters = &psContext->sExtraParameters;
     sJob.pfnProgress = NULL;
     sJob.eType = eType;
     sJob.pfnRealProgress = pfnProgress;
@@ -1734,35 +2293,25 @@ GDALGridCreate( GDALGridAlgorithm eAlgorithm, const void *poOptions,
     sJob.pbStop = &bStop;
     sJob.hCond = NULL;
     sJob.hCondMutex = NULL;
-    sJob.hThread = NULL;
-
-    if( nThreads > 1 )
-    {
-        sJob.hCond = CPLCreateCond();
-        if( sJob.hCond == NULL )
-        {
-            CPLError(CE_Warning, CPLE_AppDefined,
-                     "Cannot create condition. Reverting to monothread processing");
-            nThreads = 1;
-        }
-    }
 
-    if( nThreads <= 1 )
+    if( psContext->poWorkerThreadPool == NULL )
     {
-        sJob.pfnProgress = GDALGridProgressMonoThread;
+        if( sJob.pfnRealProgress != NULL && sJob.pfnRealProgress != GDALDummyProgress )
+            sJob.pfnProgress = GDALGridProgressMonoThread;
 
         GDALGridJobProcess(&sJob);
     }
     else
     {
+        int nThreads  = psContext->poWorkerThreadPool->GetThreadCount();
         GDALGridJob* pasJobs = (GDALGridJob*) CPLMalloc(sizeof(GDALGridJob) * nThreads);
         int i;
 
-        CPLDebug("GDAL_GRID", "Using %d threads", nThreads);
-
         sJob.nYStep = nThreads;
-        sJob.hCondMutex = CPLCreateMutex(); /* and take implicitely the mutex */
-        sJob.pfnProgress = GDALGridProgressMultiThread;
+        sJob.hCondMutex = CPLCreateMutex(); /* and  implicitly take the mutex */
+        sJob.hCond = CPLCreateCond();
+        if( sJob.pfnRealProgress != NULL && sJob.pfnRealProgress != GDALDummyProgress )
+            sJob.pfnProgress = GDALGridProgressMultiThread;
 
 /* -------------------------------------------------------------------- */
 /*      Start threads.                                                  */
@@ -1771,8 +2320,8 @@ GDALGridCreate( GDALGridAlgorithm eAlgorithm, const void *poOptions,
         {
             memcpy(&pasJobs[i], &sJob, sizeof(GDALGridJob));
             pasJobs[i].nYStart = i;
-            pasJobs[i].hThread = CPLCreateJoinableThread( GDALGridJobProcess,
-                                                          (void*) &pasJobs[i] );
+            psContext->poWorkerThreadPool->SubmitJob( GDALGridJobProcess,
+                                                      (void*) &pasJobs[i] );
         }
 
 /* -------------------------------------------------------------------- */
@@ -1785,7 +2334,8 @@ GDALGridCreate( GDALGridAlgorithm eAlgorithm, const void *poOptions,
             int nLocalCounter = nCounter;
             CPLReleaseMutex(sJob.hCondMutex);
 
-            if( !pfnProgress( nLocalCounter / (double) nYSize, "", pProgressArg ) )
+            if( pfnProgress != NULL &&
+                !pfnProgress( nLocalCounter / (double) nYSize, "", pProgressArg ) )
             {
                 CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
                 bStop = TRUE;
@@ -1801,29 +2351,97 @@ GDALGridCreate( GDALGridAlgorithm eAlgorithm, const void *poOptions,
 /* -------------------------------------------------------------------- */
 /*      Wait for all threads to complete and finish.                    */
 /* -------------------------------------------------------------------- */
-        for(i=0;i<nThreads;i++)
-        {
-            if( pasJobs[i].hThread )
-                CPLJoinThread(pasJobs[i].hThread);
-        }
+        psContext->poWorkerThreadPool->WaitCompletion();
 
         CPLFree(pasJobs);
         CPLDestroyCond(sJob.hCond);
         CPLDestroyMutex(sJob.hCondMutex);
     }
 
-    CPLFree( pasGridPoints );
-    if( hQuadTree != NULL )
-        CPLQuadTreeDestroy( hQuadTree );
-    
-    CPLFree(pabyX);
-    CPLFree(pabyY);
-    CPLFree(pabyZ);
-
     return bStop ? CE_Failure : CE_None;
 }
 
 /************************************************************************/
+/*                            GDALGridCreate()                          */
+/************************************************************************/
+
+/**
+ * Create regular grid from the scattered data.
+ *
+ * This function takes the arrays of X and Y coordinates and corresponding Z
+ * values as input and computes regular grid (or call it a raster) from these
+ * scattered data. You should supply geometry and extent of the output grid
+ * and allocate array sufficient to hold such a grid.
+ *
+ * Starting with GDAL 1.10, it is possible to set the GDAL_NUM_THREADS
+ * configuration option to parallelize the processing. The value to set is
+ * the number of worker threads, or ALL_CPUS to use all the cores/CPUs of the
+ * computer (default value).
+ *
+ * Starting with GDAL 1.10, on Intel/AMD i386/x86_64 architectures, some
+ * gridding methods will be optimized with SSE instructions (provided GDAL
+ * has been compiled with such support, and it is available at runtime).
+ * Currently, only 'invdist' algorithm with default parameters has an optimized
+ * implementation.
+ * This can provide substantial speed-up, but sometimes at the expense of
+ * reduced floating point precision. This can be disabled by setting the
+ * GDAL_USE_SSE configuration option to NO.
+ * Starting with GDAL 1.11, a further optimized version can use the AVX
+ * instruction set. This can be disabled by setting the GDAL_USE_AVX
+ * configuration option to NO.
+ *
+ * Note: it will be more efficient to use GDALGridContextCreate(),
+ * GDALGridContextProcess() and GDALGridContextFree() when doing repeated
+ * gridding operations with the same algorithm, parameters and points, and
+ * moving the window in the output grid.
+ *
+ * @param eAlgorithm Gridding method.
+ * @param poOptions Options to control chosen gridding method.
+ * @param nPoints Number of elements in input arrays.
+ * @param padfX Input array of X coordinates.
+ * @param padfY Input array of Y coordinates.
+ * @param padfZ Input array of Z values.
+ * @param dfXMin Lowest X border of output grid.
+ * @param dfXMax Highest X border of output grid.
+ * @param dfYMin Lowest Y border of output grid.
+ * @param dfYMax Highest Y border of output grid.
+ * @param nXSize Number of columns in output grid.
+ * @param nYSize Number of rows in output grid.
+ * @param eType Data type of output array.
+ * @param pData Pointer to array where the computed grid will be stored.
+ * @param pfnProgress a GDALProgressFunc() compatible callback function for
+ * reporting progress or NULL.
+ * @param pProgressArg argument to be passed to pfnProgress.  May be NULL.
+ *
+ * @return CE_None on success or CE_Failure if something goes wrong.
+ */
+
+CPLErr
+GDALGridCreate( GDALGridAlgorithm eAlgorithm, const void *poOptions,
+                GUInt32 nPoints,
+                const double *padfX, const double *padfY, const double *padfZ,
+                double dfXMin, double dfXMax, double dfYMin, double dfYMax,
+                GUInt32 nXSize, GUInt32 nYSize, GDALDataType eType, void *pData,
+                GDALProgressFunc pfnProgress, void *pProgressArg )
+{
+    CPLErr eErr = CE_Failure;
+    GDALGridContext* psContext = GDALGridContextCreate( eAlgorithm,poOptions,
+                                                        nPoints,
+                                                        padfX, padfY, padfZ,
+                                                        TRUE );
+    if( psContext )
+    {
+        eErr = GDALGridContextProcess( psContext,
+                                       dfXMin, dfXMax, dfYMin, dfYMax,
+                                       nXSize, nYSize, eType, pData,
+                                       pfnProgress, pProgressArg );
+    }
+
+    GDALGridContextFree(psContext);
+    return eErr;
+}
+
+/************************************************************************/
 /*                      ParseAlgorithmAndOptions()                      */
 /*                                                                      */
 /*      Translates mnemonic gridding algorithm names into               */
@@ -1844,10 +2462,15 @@ CPLErr ParseAlgorithmAndOptions( const char *pszAlgorithm,
     char **papszParms = CSLTokenizeString2( pszAlgorithm, ":", FALSE );
 
     if ( CSLCount(papszParms) < 1 )
+    {
+        CSLDestroy( papszParms );
         return CE_Failure;
+    }
 
     if ( EQUAL(papszParms[0], szAlgNameInvDist) )
         *peAlgorithm = GGA_InverseDistanceToAPower;
+    else if ( EQUAL(papszParms[0], szAlgNameInvDistNearestNeighbor) )
+        *peAlgorithm = GGA_InverseDistanceToAPowerNearestNeighbor;
     else if ( EQUAL(papszParms[0], szAlgNameAverage) )
         *peAlgorithm = GGA_MovingAverage;
     else if ( EQUAL(papszParms[0], szAlgNameNearest) )
@@ -1864,6 +2487,8 @@ CPLErr ParseAlgorithmAndOptions( const char *pszAlgorithm,
         *peAlgorithm = GGA_MetricAverageDistance;
     else if ( EQUAL(papszParms[0], szAlgNameAverageDistancePts) )
         *peAlgorithm = GGA_MetricAverageDistancePts;
+    else if ( EQUAL(papszParms[0], szAlgNameLinear) )
+        *peAlgorithm = GGA_Linear;
     else
     {
         fprintf( stderr, "Unsupported gridding method \"%s\".\n",
@@ -1917,6 +2542,31 @@ CPLErr ParseAlgorithmAndOptions( const char *pszAlgorithm,
                 dfNoDataValue = (pszValue) ? CPLAtofM(pszValue) : 0.0;
             break;
 
+        case GGA_InverseDistanceToAPowerNearestNeighbor:
+            *ppOptions =
+                CPLMalloc( sizeof(GDALGridInverseDistanceToAPowerNearestNeighborOptions) );
+
+            pszValue = CSLFetchNameValue( papszParms, "power" );
+            ((GDALGridInverseDistanceToAPowerNearestNeighborOptions *)*ppOptions)->
+                dfPower = (pszValue) ? CPLAtofM(pszValue) : 2.0;
+
+            pszValue = CSLFetchNameValue( papszParms, "radius" );
+            ((GDALGridInverseDistanceToAPowerNearestNeighborOptions *)*ppOptions)->
+                dfRadius = (pszValue) ? CPLAtofM(pszValue) : 1.0;
+
+            pszValue = CSLFetchNameValue( papszParms, "max_points" );
+            ((GDALGridInverseDistanceToAPowerNearestNeighborOptions *)*ppOptions)->
+                nMaxPoints = (GUInt32) ((pszValue) ? CPLAtofM(pszValue) : 12);
+
+            pszValue = CSLFetchNameValue( papszParms, "min_points" );
+            ((GDALGridInverseDistanceToAPowerNearestNeighborOptions *)*ppOptions)->
+                nMinPoints = (GUInt32) ((pszValue) ? CPLAtofM(pszValue) : 0);
+
+            pszValue = CSLFetchNameValue( papszParms, "nodata" );
+            ((GDALGridInverseDistanceToAPowerNearestNeighborOptions *)*ppOptions)->
+                dfNoDataValue = (pszValue) ? CPLAtofM(pszValue) : 0.0;
+            break;
+
         case GGA_MovingAverage:
             *ppOptions =
                 CPLMalloc( sizeof(GDALGridMovingAverageOptions) );
@@ -1986,13 +2636,25 @@ CPLErr ParseAlgorithmAndOptions( const char *pszAlgorithm,
 
             pszValue = CSLFetchNameValue( papszParms, "min_points" );
             ((GDALGridDataMetricsOptions *)*ppOptions)->
-                nMinPoints = (pszValue) ? atol(pszValue) : 0;
+                nMinPoints = (pszValue) ? atoi(pszValue) : 0;
 
             pszValue = CSLFetchNameValue( papszParms, "nodata" );
             ((GDALGridDataMetricsOptions *)*ppOptions)->
                 dfNoDataValue = (pszValue) ? CPLAtofM(pszValue) : 0.0;
             break;
 
+        case GGA_Linear:
+            *ppOptions =
+                CPLMalloc( sizeof(GDALGridLinearOptions) );
+
+            pszValue = CSLFetchNameValue( papszParms, "radius" );
+            ((GDALGridLinearOptions *)*ppOptions)->
+                dfRadius = (pszValue) ? CPLAtofM(pszValue) : -1.0;
+
+            pszValue = CSLFetchNameValue( papszParms, "nodata" );
+            ((GDALGridLinearOptions *)*ppOptions)->
+                dfNoDataValue = (pszValue) ? CPLAtofM(pszValue) : 0.0;
+            break;
    }
 
     CSLDestroy( papszParms );
@@ -2028,18 +2690,18 @@ int CPLHaveRuntimeSSE()
 #if _MSC_VER <= 1310
 static void inline __cpuid(int cpuinfo[4], int level)
 {
-    __asm 
+    __asm
     {
         push   ebx
         push   esi
 
         mov    esi,cpuinfo
-        mov    eax,level  
-        cpuid  
+        mov    eax,level
+        cpuid
         mov    dword ptr [esi], eax
-        mov    dword ptr [esi+4],ebx  
-        mov    dword ptr [esi+8],ecx  
-        mov    dword ptr [esi+0Ch],edx 
+        mov    dword ptr [esi+4],ebx
+        mov    dword ptr [esi+8],ecx
+        mov    dword ptr [esi+0Ch],edx
 
         pop    esi
         pop    ebx
@@ -2110,6 +2772,39 @@ int CPLHaveRuntimeAVX()
     return TRUE;
 }
 
+#elif defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 160040219) && (defined(_M_IX86) || defined(_M_X64))
+// _xgetbv available only in Visual Studio 2010 SP1 or later
+
+#include <intrin.h>
+
+int CPLHaveRuntimeAVX()
+{
+    int cpuinfo[4] = {0,0,0,0};
+    __cpuid(cpuinfo, 1);
+
+    /* Check OSXSAVE feature */
+    if( (cpuinfo[2] & (1 << CPUID_OSXSAVE_ECX_BIT)) == 0 )
+    {
+        return FALSE;
+    }
+
+    /* Check AVX feature */
+    if( (cpuinfo[2] & (1 << CPUID_AVX_ECX_BIT)) == 0 )
+    {
+        return FALSE;
+    }
+
+    /* Issue XGETBV and check the XMM and YMM state bit */
+    unsigned __int64 xcrFeatureMask = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
+    if( (xcrFeatureMask & ( BIT_XMM_STATE | BIT_YMM_STATE )) !=
+                          ( BIT_XMM_STATE | BIT_YMM_STATE ) )
+    {
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
 #else
 
 int CPLHaveRuntimeAVX()
diff --git a/alg/gdalgrid.h b/alg/gdalgrid.h
index dbd814f..f111130 100644
--- a/alg/gdalgrid.h
+++ b/alg/gdalgrid.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalgrid.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: gdalgrid.h 29541 2015-07-20 14:03:42Z rouault $
  *
  * Project:  GDAL Gridding API.
  * Purpose:  Prototypes, and definitions for of GDAL scattered data gridder.
@@ -44,6 +44,7 @@
  */
 
 static const char szAlgNameInvDist[] = "invdist";
+static const char szAlgNameInvDistNearestNeighbor[] = "invdistnn";
 static const char szAlgNameAverage[] = "average";
 static const char szAlgNameNearest[] = "nearest";
 static const char szAlgNameMinimum[] = "minimum";
@@ -52,6 +53,7 @@ static const char szAlgNameRange[] = "range";
 static const char szAlgNameCount[] = "count";
 static const char szAlgNameAverageDistance[] = "average_distance";
 static const char szAlgNameAverageDistancePts[] = "average_distance_pts";
+static const char szAlgNameLinear[] = "linear";
 
 CPL_C_START
 
@@ -67,6 +69,12 @@ GDALGridInverseDistanceToAPower( const void *, GUInt32,
                                  double, double, double *,
                                  void* );
 CPLErr
+GDALGridInverseDistanceToAPowerNearestNeighbor( const void *, GUInt32,
+                                 const double *, const double *,
+                                 const double *,
+                                 double, double, double *,
+                                 void* );
+CPLErr
 GDALGridInverseDistanceToAPowerNoSearch( const void *, GUInt32,
                                          const double *, const double *,
                                          const double *,
@@ -113,6 +121,13 @@ GDALGridDataMetricAverageDistancePts( const void *, GUInt32,
                                       const double *, double, double,
                                       double *,
                                       void*  );
+CPLErr
+GDALGridLinear( const void *, GUInt32,
+                                 const double *, const double *,
+                                 const double *,
+                                 double, double, double *,
+                                 void* );
+
 CPLErr CPL_DLL
 ParseAlgorithmAndOptions( const char *,
                           GDALGridAlgorithm *,
diff --git a/alg/gdalgrid_priv.h b/alg/gdalgrid_priv.h
index fd61c34..9fe4e13 100644
--- a/alg/gdalgrid_priv.h
+++ b/alg/gdalgrid_priv.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalgrid_priv.h 29314 2015-06-05 20:21:11Z rouault $
+ * $Id: gdalgrid_priv.h 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  GDAL Gridding API.
  * Purpose:  Prototypes, and definitions for of GDAL scattered data gridder.
@@ -49,6 +49,14 @@ typedef struct
     const float *pafX;
     const float *pafY;
     const float *pafZ;
+    GDALTriangulation* psTriangulation;
+    int                nInitialFacetIdx;
+    /*! Weighting power divided by 2 (pre-computation). */
+    double  dfPowerDiv2PreComp;
+    /*! The radius of search circle squared (pre-computation). */
+    double  dfRadiusPower2PreComp;
+    /*! The radius of search circle to power 4 (pre-computation). */
+    double  dfRadiusPower4PreComp;
 } GDALGridExtraParameters;
 
 #ifdef HAVE_SSE_AT_COMPILE_TIME
@@ -79,8 +87,7 @@ CPLErr GDALGridInverseDistanceToAPower2NoSmoothingNoSearchAVX(
                                         double *pdfValue,
                                         void* hExtraParamsIn );
 #endif
-
-#if defined(__GNUC__) 
+#if defined(__GNUC__)
 #if defined(__x86_64)
 #define GCC_CPUID(level, a, b, c, d)            \
   __asm__ ("xchgq %%rbx, %q1\n"                 \
diff --git a/alg/gdalgridavx.cpp b/alg/gdalgridavx.cpp
index 82b8d57..0e50831 100644
--- a/alg/gdalgridavx.cpp
+++ b/alg/gdalgridavx.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalgridavx.cpp 29914 2015-08-29 21:21:33Z rouault $
+ * $Id: gdalgridavx.cpp 31631 2015-11-18 17:55:29Z rouault $
  *
  * Project:  GDAL Gridding API.
  * Purpose:  Implementation of GDAL scattered data gridder.
@@ -33,7 +33,7 @@
 #ifdef HAVE_AVX_AT_COMPILE_TIME
 #include <immintrin.h>
 
-CPL_CVSID("$Id: gdalgridavx.cpp 29914 2015-08-29 21:21:33Z rouault $");
+CPL_CVSID("$Id: gdalgridavx.cpp 31631 2015-11-18 17:55:29Z rouault $");
 
 /************************************************************************/
 /*         GDALGridInverseDistanceToAPower2NoSmoothingNoSearchAVX()     */
@@ -124,6 +124,11 @@ GDALGridInverseDistanceToAPower2NoSmoothingNoSearchAVX(
             if( mask & (1 << j) )
             {
                 (*pdfValue) = (pafZ)[i + j];
+
+                // GCC and MSVC need explicit zeroing
+#if !defined(__clang__)
+                _mm256_zeroupper();
+#endif
                 return CE_None;
             }
         }
@@ -135,6 +140,12 @@ GDALGridInverseDistanceToAPower2NoSmoothingNoSearchAVX(
     _mm256_storeu_ps(afNominator, ymm_nominator);
     _mm256_storeu_ps(afDenominator, ymm_denominator);
 
+    // MSVC doesn't emit AVX afterwards but may use SSE, so clear upper bits
+    // Other compilers will continue using AVX for the below floating points operations
+#if defined(_MSC_FULL_VER)
+    _mm256_zeroupper();
+#endif
+
     float fNominator = afNominator[0] + afNominator[1] +
                        afNominator[2] + afNominator[3] +
                        afNominator[4] + afNominator[5] +
@@ -179,7 +190,12 @@ GDALGridInverseDistanceToAPower2NoSmoothingNoSearchAVX(
     else
         (*pdfValue) = fNominator / fDenominator;
 
+    // GCC needs explicit zeroing
+#if defined(__GNUC__) && !defined(__clang__)
+    _mm256_zeroupper();
+#endif
+
     return CE_None;
 }
 
-#endif
+#endif /* HAVE_AVX_AT_COMPILE_TIME */
diff --git a/alg/gdalgridsse.cpp b/alg/gdalgridsse.cpp
index 8e33337..d6cf9f3 100644
--- a/alg/gdalgridsse.cpp
+++ b/alg/gdalgridsse.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalgridsse.cpp 29914 2015-08-29 21:21:33Z rouault $
+ * $Id: gdalgridsse.cpp 29913 2015-08-29 21:16:44Z rouault $
  *
  * Project:  GDAL Gridding API.
  * Purpose:  Implementation of GDAL scattered data gridder.
@@ -33,7 +33,7 @@
 #ifdef HAVE_SSE_AT_COMPILE_TIME
 #include <xmmintrin.h>
 
-CPL_CVSID("$Id: gdalgridsse.cpp 29914 2015-08-29 21:21:33Z rouault $");
+CPL_CVSID("$Id: gdalgridsse.cpp 29913 2015-08-29 21:16:44Z rouault $");
 
 /************************************************************************/
 /*         GDALGridInverseDistanceToAPower2NoSmoothingNoSearchSSE()     */
diff --git a/alg/gdalmatching.cpp b/alg/gdalmatching.cpp
index b3840e1..41ad625 100644
--- a/alg/gdalmatching.cpp
+++ b/alg/gdalmatching.cpp
@@ -2,7 +2,7 @@
  * $Id$
  *
  * Project:  GDAL
- * Purpose:  GDAL Wrapper for image matching via corellation algorithm.
+ * Purpose:  GDAL Wrapper for image matching via correlation algorithm.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  * Author:   Andrew Migal, migal.drew at gmail.com
  *
@@ -57,7 +57,7 @@ CPL_CVSID("$Id");
  * @param dfThreshold Value from 0 to 1. Threshold for feature point recognition.
  * Number of detected points is larger if threshold is lower
  *
- * @see GDALFeaturePoint, GDALSimpleSURF class for detailes.
+ * @see GDALFeaturePoint, GDALSimpleSURF class for details.
  *
  * @note Every octave finds points in specific size. For small images
  * use small octave numbers, for high resolution - large.
@@ -121,14 +121,27 @@ GatherFeaturePoints(GDALDataset* poDataset, int* panBands,
     GDALRasterBand *poRstGreenBand = poDataset->GetRasterBand(panBands[1]);
     GDALRasterBand *poRstBlueBand = poDataset->GetRasterBand(panBands[2]);
 
-    int nWidth = poRstRedBand->GetXSize();
-    int nHeight = poRstRedBand->GetYSize();
+    const int nWidth = poRstRedBand->GetXSize();
+    const int nHeight = poRstRedBand->GetYSize();
+
+    if (nWidth == 0 || nHeight == 0)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Must have non-zero width and height.");
+        return NULL;
+    }
 
     // Allocate memory for grayscale image
-    double **padfImg = NULL;
-    padfImg = new double*[nHeight];
-    for (int i = 0; i < nHeight; i++)
+    double **padfImg = new double*[nHeight];
+    for (int i = 0; ;)
+    {
         padfImg[i] = new double[nWidth];
+        for (int j = 0; j < nWidth; ++j)
+          padfImg[i][j] = 0.0;
+        ++i;
+        if( i == nHeight )
+            break;
+    }
 
     // Create grayscale image
     GDALSimpleSURF::ConvertRGBToLuminosity(
@@ -141,15 +154,15 @@ GatherFeaturePoints(GDALDataset* poDataset, int* panBands,
 
     // Get feature points
     GDALSimpleSURF *poSurf = new GDALSimpleSURF(nOctaveStart, nOctaveEnd);
-    
-    std::vector<GDALFeaturePoint> *poCollection = 
+
+    std::vector<GDALFeaturePoint> *poCollection =
         poSurf->ExtractFeaturePoints(poImg, dfThreshold);
 
     // Clean up
     delete poImg;
     delete poSurf;
 
-    for (int i = 0; i < nHeight; i++)
+    for (int i = 0; i < nHeight; ++i)
         delete[] padfImg[i];
 
     delete[] padfImg;
@@ -198,7 +211,7 @@ GDALComputeMatchingPoints( GDALDatasetH hFirstImage,
         anBandMap1[2] = 3;
     }
     else
-    { 
+    {
         anBandMap1[0] = anBandMap1[1] = anBandMap1[2] = 1;
     }
 
@@ -209,7 +222,7 @@ GDALComputeMatchingPoints( GDALDatasetH hFirstImage,
         anBandMap2[2] = 3;
     }
     else
-    { 
+    {
         anBandMap2[0] = anBandMap2[1] = anBandMap2[2] = 1;
     }
 
@@ -217,35 +230,37 @@ GDALComputeMatchingPoints( GDALDatasetH hFirstImage,
 /*      Collect reference points on each image.                         */
 /* -------------------------------------------------------------------- */
     std::vector<GDALFeaturePoint> *poFPCollection1 =
-        GatherFeaturePoints((GDALDataset *) hFirstImage, anBandMap1, 
+        GatherFeaturePoints((GDALDataset *) hFirstImage, anBandMap1,
                             nOctaveStart, nOctaveEnd, dfSURFThreshold);
     if( poFPCollection1 == NULL )
         return NULL;
 
-    std::vector<GDALFeaturePoint> *poFPCollection2 = 
-        GatherFeaturePoints((GDALDataset *) hSecondImage, anBandMap2, 
-                            nOctaveStart, nOctaveEnd, 
+    std::vector<GDALFeaturePoint> *poFPCollection2 =
+        GatherFeaturePoints((GDALDataset *) hSecondImage, anBandMap2,
+                            nOctaveStart, nOctaveEnd,
                             dfSURFThreshold);
-    
+
     if( poFPCollection2 == NULL )
+    {
+        delete poFPCollection1;
         return NULL;
+    }
 
-    
 /* -------------------------------------------------------------------- */
 /*      Try to find corresponding locations.                            */
 /* -------------------------------------------------------------------- */
-    CPLErr eErr;
     std::vector<GDALFeaturePoint *> oMatchPairs;
 
-    eErr = GDALSimpleSURF::MatchFeaturePoints(
+    if( CE_None != GDALSimpleSURF::MatchFeaturePoints(
         &oMatchPairs, poFPCollection1, poFPCollection2,
-        dfMatchingThreshold );
-
-    if( eErr != CE_None )
+        dfMatchingThreshold ))
+    {
+        delete poFPCollection1;
+        delete poFPCollection2;
         return NULL;
+    }
 
-    
-    *pnGCPCount = oMatchPairs.size() / 2;
+    *pnGCPCount = static_cast<int>(oMatchPairs.size()) / 2;
 
 /* -------------------------------------------------------------------- */
 /*      Translate these into GCPs - but with the output coordinate      */
@@ -255,14 +270,14 @@ GDALComputeMatchingPoints( GDALDatasetH hFirstImage,
 
     GDALInitGCPs(*pnGCPCount, pasGCPList);
 
-    for (int i=0; i < *pnGCPCount; i++) 
+    for (int i=0; i < *pnGCPCount; i++)
     {
         GDALFeaturePoint *poPoint1 = oMatchPairs[i*2  ];
         GDALFeaturePoint *poPoint2 = oMatchPairs[i*2+1];
 
         pasGCPList[i].dfGCPPixel = poPoint1->GetX() + 0.5;
         pasGCPList[i].dfGCPLine = poPoint1->GetY() + 0.5;
-        
+
         pasGCPList[i].dfGCPX = poPoint2->GetX() + 0.5;
         pasGCPList[i].dfGCPY = poPoint2->GetY() + 0.5;
         pasGCPList[i].dfGCPZ = 0.0;
@@ -271,13 +286,13 @@ GDALComputeMatchingPoints( GDALDatasetH hFirstImage,
     // Cleanup the feature point lists.
     delete poFPCollection1;
     delete poFPCollection2;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Optionally transform into the georef coordinates of the         */
 /*      output image.                                                   */
 /* -------------------------------------------------------------------- */
-    int bGeorefOutput = 
-        CSLTestBoolean(CSLFetchNameValueDef(papszOptions,"OUTPUT_GEOREF","NO"));
+    const bool bGeorefOutput =
+        CPLTestBool(CSLFetchNameValueDef(papszOptions,"OUTPUT_GEOREF","NO"));
 
     if( bGeorefOutput )
     {
@@ -285,9 +300,9 @@ GDALComputeMatchingPoints( GDALDatasetH hFirstImage,
 
         GDALGetGeoTransform( hSecondImage, adfGeoTransform );
 
-        for (int i=0; i < *pnGCPCount; i++) 
+        for (int i=0; i < *pnGCPCount; i++)
         {
-            GDALApplyGeoTransform(adfGeoTransform, 
+            GDALApplyGeoTransform(adfGeoTransform,
                                   pasGCPList[i].dfGCPX,
                                   pasGCPList[i].dfGCPY,
                                   &(pasGCPList[i].dfGCPX),
diff --git a/alg/gdalmediancut.cpp b/alg/gdalmediancut.cpp
index 3e17858..b37a3c2 100644
--- a/alg/gdalmediancut.cpp
+++ b/alg/gdalmediancut.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: gdalmediancut.cpp 28085 2014-12-07 14:36:00Z rouault $
+ * $Id: gdalmediancut.cpp 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  CIETMap Phase 2
- * Purpose:  Use median cut algorithm to generate an near-optimal PCT for a 
+ * Purpose:  Use median cut algorithm to generate an near-optimal PCT for a
  *           given RGB image.  Implemented as function GDALComputeMedianCutPCT.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -34,20 +34,23 @@
  *
  *      "Color  Image Quantization for Frame Buffer Display", Paul
  *      Heckbert, SIGGRAPH proceedings, 1982, pp. 297-307.
- * 
+ *
  */
 
 #include "gdal_priv.h"
 #include "gdal_alg.h"
 #include "gdal_alg_priv.h"
+#include <limits>
 
-CPL_CVSID("$Id: gdalmediancut.cpp 28085 2014-12-07 14:36:00Z rouault $");
+CPL_CVSID("$Id: gdalmediancut.cpp 33715 2016-03-13 08:52:06Z goatbar $");
 
 #define HISTOGRAM(h,n,r,g,b) h[((r)*(n)+(g))*(n)+(b)]
 
 #define MAKE_COLOR_CODE(r,g,b) ((r)+(g)*256+(b)*256*256)
 
-typedef struct /* NOTE: if changing the size of this structure, edit MEDIAN_CUT_AND_DITHER_BUFFER_SIZE_65536 */
+/* NOTE: if changing the size of this structure, edit */
+/* MEDIAN_CUT_AND_DITHER_BUFFER_SIZE_65536 in gdal_alg_priv.h and take into account ColorIndex in gdaldither.cpp */
+typedef struct
 {
     GUInt32 nColorCode;
     int     nCount;
@@ -62,19 +65,23 @@ typedef	struct colorbox {
 	int	rmin, rmax;
 	int	gmin, gmax;
 	int	bmin, bmax;
-	int	total;
+	GUIntBig	total;
 } Colorbox;
 
-static void splitbox(Colorbox* ptr, const int* histogram,
+template<class T>
+static void splitbox(Colorbox* ptr, const T* histogram,
                      const HashHistogram* psHashHistogram,
                      int nCLevels,
                      Colorbox **pfreeboxes, Colorbox **pusedboxes,
                      GByte* pabyRedBand,
                      GByte* pabyGreenBand,
-                     GByte* pabyBlueBand, int nPixels);
+                     GByte* pabyBlueBand, T nPixels);
+
+template<class T>
 static void shrinkbox(Colorbox* box,
-                      const int* histogram,
+                      const T* histogram,
                       int nCLevels);
+
 static Colorbox* largest_box(Colorbox *usedboxes);
 
 /************************************************************************/
@@ -87,7 +94,7 @@ static Colorbox* largest_box(Colorbox *usedboxes);
  * This function implements a median cut algorithm to compute an "optimal"
  * pseudocolor table for representing an input RGB image.  This PCT could
  * then be used with GDALDitherRGB2PCT() to convert a 24bit RGB image into
- * an eightbit pseudo-colored image. 
+ * an eightbit pseudo-colored image.
  *
  * This code was based on the tiffmedian.c code from libtiff (www.libtiff.org)
  * which was based on a paper by Paul Heckbert:
@@ -100,11 +107,11 @@ static Colorbox* largest_box(Colorbox *usedboxes);
  * The red, green and blue input bands do not necessarily need to come
  * from the same file, but they must be the same width and height.  They will
  * be clipped to 8bit during reading, so non-eight bit bands are generally
- * inappropriate. 
+ * inappropriate.
  *
- * @param hRed Red input band. 
- * @param hGreen Green input band. 
- * @param hBlue Blue input band. 
+ * @param hRed Red input band.
+ * @param hGreen Green input band.
+ * @param hBlue Blue input band.
  * @param pfnIncludePixel function used to test which pixels should be included
  * in the analysis.  At this time this argument is ignored and all pixels are
  * utilized.  This should normally be NULL.
@@ -114,27 +121,45 @@ static Colorbox* largest_box(Colorbox *usedboxes);
  * GDALProgressFunc() semantics.  May be NULL.
  * @param pProgressArg callback argument passed to pfnProgress.
  *
- * @return returns CE_None on success or CE_Failure if an error occurs. 
+ * @return returns CE_None on success or CE_Failure if an error occurs.
  */
 
 extern "C" int CPL_STDCALL
-GDALComputeMedianCutPCT( GDALRasterBandH hRed, 
-                         GDALRasterBandH hGreen, 
-                         GDALRasterBandH hBlue, 
+GDALComputeMedianCutPCT( GDALRasterBandH hRed,
+                         GDALRasterBandH hGreen,
+                         GDALRasterBandH hBlue,
                          int (*pfnIncludePixel)(int,int,void*),
-                         int nColors, 
+                         int nColors,
                          GDALColorTableH hColorTable,
-                         GDALProgressFunc pfnProgress, 
+                         GDALProgressFunc pfnProgress,
                          void * pProgressArg )
 
 {
-    return GDALComputeMedianCutPCTInternal(hRed, hGreen, hBlue,
-                                     NULL, NULL, NULL,
-                                     pfnIncludePixel, nColors,
-                                     5,
-                                     NULL,
-                                     hColorTable,
-                                     pfnProgress, pProgressArg);
+    VALIDATE_POINTER1( hRed, "GDALComputeMedianCutPCT", CE_Failure );
+    int nXSize = GDALGetRasterBandXSize( hRed );
+    int nYSize = GDALGetRasterBandYSize( hRed );
+    if( nYSize == 0 )
+        return CE_Failure;
+    if( (GUInt32)nXSize < UINT_MAX / (GUInt32)nYSize )
+    {
+        return GDALComputeMedianCutPCTInternal(hRed, hGreen, hBlue,
+                                        NULL, NULL, NULL,
+                                        pfnIncludePixel, nColors,
+                                        5,
+                                        (GUInt32*)NULL,
+                                        hColorTable,
+                                        pfnProgress, pProgressArg);
+    }
+    else
+    {
+        return GDALComputeMedianCutPCTInternal(hRed, hGreen, hBlue,
+                                        NULL, NULL, NULL,
+                                        pfnIncludePixel, nColors,
+                                        5,
+                                        (GUIntBig*)NULL,
+                                        hColorTable,
+                                        pfnProgress, pProgressArg);
+    }
 }
 
 /*static int nMaxCollisions = 0;*/
@@ -144,7 +169,7 @@ static inline int FindColorCount(const HashHistogram* psHashHistogram,
 {
     GUInt32 nIdx = nColorCode % PRIME_FOR_65536;
     /*int nCollisions = 0; */
-    while( TRUE )
+    while( true )
     {
         if( (int)psHashHistogram[nIdx].nColorCode < 0 )
         {
@@ -198,7 +223,7 @@ static inline int* FindAndInsertColorCount(HashHistogram* psHashHistogram,
 {
     GUInt32 nIdx = nColorCode % PRIME_FOR_65536;
     /*int nCollisions = 0;*/
-    while( TRUE )
+    while( true )
     {
         if( psHashHistogram[nIdx].nColorCode == nColorCode )
         {
@@ -253,19 +278,19 @@ static inline int* FindAndInsertColorCount(HashHistogram* psHashHistogram,
     }
 }
 
-int
-GDALComputeMedianCutPCTInternal( GDALRasterBandH hRed, 
-                           GDALRasterBandH hGreen, 
-                           GDALRasterBandH hBlue, 
+template<class T> int
+GDALComputeMedianCutPCTInternal( GDALRasterBandH hRed,
+                           GDALRasterBandH hGreen,
+                           GDALRasterBandH hBlue,
                            GByte* pabyRedBand,
                            GByte* pabyGreenBand,
                            GByte* pabyBlueBand,
                            int (*pfnIncludePixel)(int,int,void*),
-                           int nColors, 
+                           int nColors,
                            int nBits,
-                           int* panHistogram, /* NULL, or at least of size (1<<nBits)^3 * sizeof(int) bytes */
+                           T* panHistogram, /* NULL, or at least of size (1<<nBits)^3 * sizeof(T) bytes */
                            GDALColorTableH hColorTable,
-                           GDALProgressFunc pfnProgress, 
+                           GDALProgressFunc pfnProgress,
                            void * pProgressArg )
 
 {
@@ -282,9 +307,9 @@ GDALComputeMedianCutPCTInternal( GDALRasterBandH hRed,
     nXSize = GDALGetRasterBandXSize( hRed );
     nYSize = GDALGetRasterBandYSize( hRed );
 
-    if( GDALGetRasterBandXSize( hGreen ) != nXSize 
-        || GDALGetRasterBandYSize( hGreen ) != nYSize 
-        || GDALGetRasterBandXSize( hBlue ) != nXSize 
+    if( GDALGetRasterBandXSize( hGreen ) != nXSize
+        || GDALGetRasterBandYSize( hGreen ) != nYSize
+        || GDALGetRasterBandXSize( hBlue ) != nXSize
         || GDALGetRasterBandYSize( hBlue ) != nYSize )
     {
         CPLError( CE_Failure, CPLE_IllegalArg,
@@ -326,25 +351,31 @@ GDALComputeMedianCutPCTInternal( GDALRasterBandH hRed,
 /* ==================================================================== */
     int	     i;
     Colorbox *box_list, *ptr;
-    int* histogram;
+    T* histogram;
     Colorbox *freeboxes;
     Colorbox *usedboxes;
     int nCLevels = 1 << nBits;
     int nColorShift = 8 - nBits;
     int nColorCounter = 0;
     GByte anRed[256], anGreen[256], anBlue[256];
-    int nPixels = 0;
+    T nPixels = 0;
     HashHistogram* psHashHistogram = NULL;
-    
+
+    if( (GUInt32)nXSize > std::numeric_limits<T>::max() / (GUInt32)nYSize )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "GDALComputeMedianCutPCTInternal() not called with large enough type");
+    }
+
     if( nBits == 8 && pabyRedBand != NULL && pabyGreenBand != NULL &&
-        pabyBlueBand != NULL && nXSize < INT_MAX / nYSize )
+        pabyBlueBand != NULL && (GUInt32)nXSize <= std::numeric_limits<T>::max() / (GUInt32)nYSize )
     {
-        nPixels = nXSize * nYSize;
+        nPixels = (T)nXSize * (T)nYSize;
     }
 
     if( panHistogram )
     {
-        if( nBits == 8 && (GIntBig)nXSize * nYSize <= 65536 )
+        if( nBits == 8 && (GUIntBig)nXSize * nYSize <= 65536 )
         {
             /* If the image is small enough, then the number of colors */
             /* will be limited and using a hashmap, rather than a full table */
@@ -356,16 +387,14 @@ GDALComputeMedianCutPCTInternal( GDALRasterBandH hRed,
         else
         {
             histogram = panHistogram;
-            memset(histogram, 0, nCLevels*nCLevels*nCLevels * sizeof(int));
+            memset(histogram, 0, nCLevels*nCLevels*nCLevels * sizeof(T));
         }
     }
     else
     {
-        histogram = (int*) VSICalloc(nCLevels*nCLevels*nCLevels,sizeof(int));
+        histogram = (T*) VSI_CALLOC_VERBOSE(nCLevels*nCLevels*nCLevels,sizeof(T));
         if( histogram == NULL )
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory,
-                  "VSICalloc(): Out of memory in GDALComputeMedianCutPCT" );
             return CE_Failure;
         }
     }
@@ -400,28 +429,26 @@ GDALComputeMedianCutPCTInternal( GDALRasterBandH hRed,
 
     ptr->rmin = ptr->gmin = ptr->bmin = 999;
     ptr->rmax = ptr->gmax = ptr->bmax = -1;
-    ptr->total = nXSize * nYSize;
+    ptr->total = (GUIntBig)nXSize * (GUIntBig)nYSize;
 
 /* -------------------------------------------------------------------- */
 /*      Collect histogram.                                              */
 /* -------------------------------------------------------------------- */
-    pabyRedLine = (GByte *) VSIMalloc(nXSize);
-    pabyGreenLine = (GByte *) VSIMalloc(nXSize);
-    pabyBlueLine = (GByte *) VSIMalloc(nXSize);
-    
+    pabyRedLine = (GByte *) VSI_MALLOC_VERBOSE(nXSize);
+    pabyGreenLine = (GByte *) VSI_MALLOC_VERBOSE(nXSize);
+    pabyBlueLine = (GByte *) VSI_MALLOC_VERBOSE(nXSize);
+
     if (pabyRedLine == NULL ||
         pabyGreenLine == NULL ||
         pabyBlueLine == NULL)
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory,
-                  "VSIMalloc(): Out of memory in GDALComputeMedianCutPCT" );
         err = CE_Failure;
         goto end_and_cleanup;
     }
 
     for( iLine = 0; iLine < nYSize; iLine++ )
     {
-        if( !pfnProgress( iLine / (double) nYSize, 
+        if( !pfnProgress( iLine / (double) nYSize,
                           "Generating Histogram", pProgressArg ) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User Terminated" );
@@ -429,17 +456,21 @@ GDALComputeMedianCutPCTInternal( GDALRasterBandH hRed,
             goto end_and_cleanup;
         }
 
-        GDALRasterIO( hRed, GF_Read, 0, iLine, nXSize, 1, 
+        err = GDALRasterIO( hRed, GF_Read, 0, iLine, nXSize, 1,
                       pabyRedLine, nXSize, 1, GDT_Byte, 0, 0 );
-        GDALRasterIO( hGreen, GF_Read, 0, iLine, nXSize, 1, 
+        if( err == CE_None )
+            err = GDALRasterIO( hGreen, GF_Read, 0, iLine, nXSize, 1,
                       pabyGreenLine, nXSize, 1, GDT_Byte, 0, 0 );
-        GDALRasterIO( hBlue, GF_Read, 0, iLine, nXSize, 1, 
+        if( err == CE_None )
+            err = GDALRasterIO( hBlue, GF_Read, 0, iLine, nXSize, 1,
                       pabyBlueLine, nXSize, 1, GDT_Byte, 0, 0 );
+        if( err != CE_None )
+            goto end_and_cleanup;
 
         for( iPixel = 0; iPixel < nXSize; iPixel++ )
         {
             int	nRed, nGreen, nBlue;
-            
+
             nRed = pabyRedLine[iPixel] >> nColorShift;
             nGreen = pabyGreenLine[iPixel] >> nColorShift;
             nBlue = pabyBlueLine[iPixel] >> nColorShift;
@@ -451,27 +482,30 @@ GDALComputeMedianCutPCTInternal( GDALRasterBandH hRed,
             ptr->gmax = MAX(ptr->gmax, nGreen);
             ptr->bmax = MAX(ptr->bmax, nBlue);
 
-            int* pnColor;
+            bool bFirstOccurrence;
             if( psHashHistogram )
             {
-                pnColor = FindAndInsertColorCount(psHashHistogram,
+                int* pnColor = FindAndInsertColorCount(psHashHistogram,
                                          MAKE_COLOR_CODE(nRed, nGreen, nBlue));
+                bFirstOccurrence = ( *pnColor == 0 );
+                (*pnColor) ++;
             }
             else
             {
-                pnColor = &HISTOGRAM(histogram, nCLevels, nRed, nGreen, nBlue);
+                T* pnColor = &HISTOGRAM(histogram, nCLevels, nRed, nGreen, nBlue);
+                bFirstOccurrence = ( *pnColor == 0 );
+                (*pnColor) ++;
             }
-            if( *pnColor == 0 )
+            if( bFirstOccurrence)
             {
                 if( nColorShift == 0 && nColorCounter < nColors )
                 {
-                    anRed[nColorCounter] = nRed;
-                    anGreen[nColorCounter] = nGreen;
-                    anBlue[nColorCounter] = nBlue;
+                    anRed[nColorCounter] = static_cast<GByte>(nRed);
+                    anGreen[nColorCounter] = static_cast<GByte>(nGreen);
+                    anBlue[nColorCounter] = static_cast<GByte>(nBlue);
                 }
                 nColorCounter++;
             }
-            (*pnColor) ++;
         }
     }
 
@@ -513,7 +547,7 @@ GDALComputeMedianCutPCTInternal( GDALRasterBandH hRed,
 /* ==================================================================== */
 /*      STEP 4: assign colors to all boxes                              */
 /* ==================================================================== */
-    for (i = 0, ptr = usedboxes; ptr != NULL; ++i, ptr = ptr->next) 
+    for (i = 0, ptr = usedboxes; ptr != NULL; ++i, ptr = ptr->next)
     {
         GDALColorEntry	sEntry;
 
@@ -535,7 +569,7 @@ end_and_cleanup:
 
     if( panHistogram == NULL )
         CPLFree( histogram );
-    
+
     return err;
 }
 
@@ -546,27 +580,28 @@ end_and_cleanup:
 static Colorbox *
 largest_box(Colorbox *usedboxes)
 {
-    Colorbox *p, *b;
-    int size;
+    Colorbox *b = NULL;
 
-    b = NULL;
-    size = -1;
-    for (p = usedboxes; p != NULL; p = p->next)
+    for (Colorbox* p = usedboxes; p != NULL; p = p->next)
+    {
         if ((p->rmax > p->rmin || p->gmax > p->gmin ||
-             p->bmax > p->bmin) &&  p->total > size)
-            size = (b = p)->total;
+             p->bmax > p->bmin) && (b == NULL || p->total > b->total))
+        {
+            b = p;
+        }
+    }
     return (b);
 }
 
 static void shrinkboxFromBand(Colorbox* ptr,
                               const GByte* pabyRedBand,
                               const GByte* pabyGreenBand,
-                              const GByte* pabyBlueBand, int nPixels)
+                              const GByte* pabyBlueBand, GUIntBig nPixels)
 {
     int rmin_new = 255, rmax_new = 0,
         gmin_new = 255, gmax_new = 0,
         bmin_new = 255, bmax_new = 0;
-    for(int i=0;i<nPixels;i++)
+    for(GUIntBig i=0;i<nPixels;i++)
     {
         int iR = pabyRedBand[i];
         int iG = pabyGreenBand[i];
@@ -690,7 +725,7 @@ static void shrinkboxFromHashHistogram(Colorbox* box,
             }
         }
     }
-    
+
     have_bmin:
     if (box->bmax > box->bmin) {
         //count_iter = 0;
@@ -717,23 +752,23 @@ static void shrinkboxFromHashHistogram(Colorbox* box,
 /************************************************************************/
 /*                              splitbox()                              */
 /************************************************************************/
-static void
-splitbox(Colorbox* ptr, const int* histogram,
+template<class T> static void
+splitbox(Colorbox* ptr, const T* histogram,
          const HashHistogram* psHashHistogram,
          int nCLevels,
          Colorbox **pfreeboxes, Colorbox **pusedboxes,
          GByte* pabyRedBand,
          GByte* pabyGreenBand,
-         GByte* pabyBlueBand, int nPixels)
+         GByte* pabyBlueBand, T nPixels)
 {
-    int		hist2[256];
+    T		hist2[256];
     int		first=0, last=0;
     Colorbox	*new_cb;
-    const int	*iptr;
-    int *histp;
+    const T	*iptr;
+    T *histp;
     int	i, j;
     int	ir,ig,ib;
-    int sum, sum1, sum2;
+    T sum, sum1, sum2;
     enum { RED, GREEN, BLUE } axis;
 
     /*
@@ -749,7 +784,7 @@ splitbox(Colorbox* ptr, const int* histogram,
     else
         axis = BLUE;
     /* get histogram along longest axis */
-    int nIters = (ptr->rmax - ptr->rmin + 1) * (ptr->gmax - ptr->gmin + 1) *
+    GUInt32 nIters = (ptr->rmax - ptr->rmin + 1) * (ptr->gmax - ptr->gmin + 1) *
                  (ptr->bmax - ptr->bmin + 1);
     //printf("nIters = %d\n", nIters);
     switch (axis) {
@@ -764,11 +799,11 @@ splitbox(Colorbox* ptr, const int* histogram,
                                 gmax = ptr->gmax,
                                 bmin = ptr->bmin,
                                 bmax = ptr->bmax;
-            for(int i=0;i<nPixels;i++)
+            for(T iPixel=0;iPixel<nPixels;iPixel++)
             {
-                int iR = pabyRedBand[i];
-                int iG = pabyGreenBand[i];
-                int iB = pabyBlueBand[i];
+                int iR = pabyRedBand[iPixel];
+                int iG = pabyGreenBand[iPixel];
+                int iB = pabyBlueBand[iPixel];
                 if( iR >= rmin && iR <= rmax &&
                     iG >= gmin && iG <= gmax &&
                     iB >= bmin && iB <= bmax )
@@ -820,11 +855,11 @@ splitbox(Colorbox* ptr, const int* histogram,
                                 gmax = ptr->gmax,
                                 bmin = ptr->bmin,
                                 bmax = ptr->bmax;
-            for(int i=0;i<nPixels;i++)
+            for(T iPixel=0;iPixel<nPixels;iPixel++)
             {
-                int iR = pabyRedBand[i];
-                int iG = pabyGreenBand[i];
-                int iB = pabyBlueBand[i];
+                int iR = pabyRedBand[iPixel];
+                int iG = pabyGreenBand[iPixel];
+                int iB = pabyBlueBand[iPixel];
                 if( iR >= rmin && iR <= rmax &&
                     iG >= gmin && iG <= gmax &&
                     iB >= bmin && iB <= bmax )
@@ -876,11 +911,11 @@ splitbox(Colorbox* ptr, const int* histogram,
                                 gmax = ptr->gmax,
                                 bmin = ptr->bmin,
                                 bmax = ptr->bmax;
-            for(int i=0;i<nPixels;i++)
+            for(T iPixel=0;iPixel<nPixels;iPixel++)
             {
-                int iR = pabyRedBand[i];
-                int iG = pabyGreenBand[i];
-                int iB = pabyBlueBand[i];
+                int iR = pabyRedBand[iPixel];
+                int iG = pabyGreenBand[iPixel];
+                int iB = pabyBlueBand[iPixel];
                 if( iR >= rmin && iR <= rmax &&
                     iG >= gmin && iG <= gmax &&
                     iB >= bmin && iB <= bmax )
@@ -924,7 +959,7 @@ splitbox(Colorbox* ptr, const int* histogram,
       }
     }
     /* find median point */
-    sum2 = ptr->total / 2;
+    sum2 = static_cast<T>(ptr->total / 2);
     histp = &hist2[first];
     sum = 0;
     for (i = first; i <= last && (sum += *histp++) < sum2; ++i)
@@ -971,8 +1006,8 @@ splitbox(Colorbox* ptr, const int* histogram,
         break;
     }
     if( nPixels != 0 &&
-        (new_cb->rmax - new_cb->rmin + 1) * (new_cb->gmax - new_cb->gmin + 1) *
-        (new_cb->bmax - new_cb->bmin + 1) > nPixels )
+        (T)(new_cb->rmax - new_cb->rmin + 1) * (T)(new_cb->gmax - new_cb->gmin + 1) *
+        (T)(new_cb->bmax - new_cb->bmin + 1) > nPixels )
     {
         shrinkboxFromBand(new_cb, pabyRedBand, pabyGreenBand, pabyBlueBand, nPixels);
     }
@@ -985,8 +1020,8 @@ splitbox(Colorbox* ptr, const int* histogram,
         shrinkbox(new_cb, histogram, nCLevels);
     }
     if( nPixels != 0 &&
-        (ptr->rmax - ptr->rmin + 1) * (ptr->gmax - ptr->gmin + 1) *
-        (ptr->bmax - ptr->bmin + 1) > nPixels )
+        (T)(ptr->rmax - ptr->rmin + 1) * (T)(ptr->gmax - ptr->gmin + 1) *
+        (T)(ptr->bmax - ptr->bmin + 1) > nPixels )
     {
         shrinkboxFromBand(ptr, pabyRedBand, pabyGreenBand, pabyBlueBand, nPixels);
     }
@@ -1003,10 +1038,10 @@ splitbox(Colorbox* ptr, const int* histogram,
 /************************************************************************/
 /*                             shrinkbox()                              */
 /************************************************************************/
-static void
-shrinkbox(Colorbox* box, const int* histogram, int nCLevels)
+template<class T> static void
+shrinkbox(Colorbox* box, const T* histogram, int nCLevels)
 {
-    const int *histp;
+    const T *histp;
     int ir, ig, ib;
     //int count_iter;
 
@@ -1100,7 +1135,7 @@ shrinkbox(Colorbox* box, const int* histogram, int nCLevels)
             }
         }
     }
-    
+
     have_bmin:
     if (box->bmax > box->bmin) {
         //count_iter = 0;
@@ -1124,3 +1159,33 @@ shrinkbox(Colorbox* box, const int* histogram, int nCLevels)
     have_bmax:
     ;
 }
+
+/* Explicitly instantiate template functions */
+template int
+GDALComputeMedianCutPCTInternal<GUInt32>( GDALRasterBandH hRed,
+                           GDALRasterBandH hGreen,
+                           GDALRasterBandH hBlue,
+                           GByte* pabyRedBand,
+                           GByte* pabyGreenBand,
+                           GByte* pabyBlueBand,
+                           int (*pfnIncludePixel)(int,int,void*),
+                           int nColors,
+                           int nBits,
+                           GUInt32* panHistogram,
+                           GDALColorTableH hColorTable,
+                           GDALProgressFunc pfnProgress,
+                           void * pProgressArg );
+template int
+GDALComputeMedianCutPCTInternal<GUIntBig>( GDALRasterBandH hRed,
+                           GDALRasterBandH hGreen,
+                           GDALRasterBandH hBlue,
+                           GByte* pabyRedBand,
+                           GByte* pabyGreenBand,
+                           GByte* pabyBlueBand,
+                           int (*pfnIncludePixel)(int,int,void*),
+                           int nColors,
+                           int nBits,
+                           GUIntBig* panHistogram,
+                           GDALColorTableH hColorTable,
+                           GDALProgressFunc pfnProgress,
+                           void * pProgressArg );
diff --git a/alg/gdalpansharpen.cpp b/alg/gdalpansharpen.cpp
new file mode 100644
index 0000000..2fc6a33
--- /dev/null
+++ b/alg/gdalpansharpen.cpp
@@ -0,0 +1,1630 @@
+/******************************************************************************
+ * $Id: gdalpansharpen.cpp 33808 2016-03-29 21:15:28Z goatbar $
+ *
+ * Project:  GDAL Pansharpening module
+ * Purpose:  Implementation of pansharpening.
+ * Author:   Even Rouault <even.rouault at spatialys.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Even Rouault <even.rouault at spatialys.com>
+ * Copyright (c) 2015, Airbus DS Geo SA (weighted Brovey algorithm)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gdalpansharpen.h"
+#include "gdal_priv.h"
+#include "cpl_conv.h"
+#include "gdal_priv_templates.hpp"
+#include "../frmts/vrt/vrtdataset.h"
+#include "../frmts/mem/memdataset.h"
+#include <new>
+
+// Limit types to practical use cases
+#define LIMIT_TYPES 1
+
+CPL_CVSID("$Id: gdalpansharpen.cpp 33808 2016-03-29 21:15:28Z goatbar $");
+
+/************************************************************************/
+/*                     GDALCreatePansharpenOptions()                    */
+/************************************************************************/
+
+/** Create pansharpening options.
+ *
+ * @return a newly allocated pansharpening option structure that must be freed
+ * with GDALDestroyPansharpenOptions().
+ *
+ * @since GDAL 2.1
+ */
+
+GDALPansharpenOptions * GDALCreatePansharpenOptions()
+{
+    GDALPansharpenOptions* psOptions =
+            (GDALPansharpenOptions*)CPLCalloc(1, sizeof(GDALPansharpenOptions));
+    psOptions->ePansharpenAlg = GDAL_PSH_WEIGHTED_BROVEY;
+    psOptions->eResampleAlg = GRIORA_Cubic;
+    return psOptions;
+}
+
+/************************************************************************/
+/*                     GDALDestroyPansharpenOptions()                   */
+/************************************************************************/
+
+/** Destroy pansharpening options.
+ *
+ * @param psOptions a pansharpening option structure allocated with
+ * GDALCreatePansharpenOptions()
+ *
+ * @since GDAL 2.1
+ */
+
+void GDALDestroyPansharpenOptions( GDALPansharpenOptions* psOptions )
+{
+    if( psOptions == NULL )
+        return;
+    CPLFree(psOptions->padfWeights);
+    CPLFree(psOptions->pahInputSpectralBands);
+    CPLFree(psOptions->panOutPansharpenedBands);
+    CPLFree(psOptions);
+}
+
+/************************************************************************/
+/*                      GDALClonePansharpenOptions()                    */
+/************************************************************************/
+
+/** Clone pansharpening options.
+ *
+ * @param psOptions a pansharpening option structure allocated with
+ * GDALCreatePansharpenOptions()
+ * @return a newly allocated pansharpening option structure that must be freed
+ * with GDALDestroyPansharpenOptions().
+ *
+ * @since GDAL 2.1
+ */
+
+GDALPansharpenOptions* GDALClonePansharpenOptions(
+                                        const GDALPansharpenOptions* psOptions)
+{
+    GDALPansharpenOptions* psNewOptions = GDALCreatePansharpenOptions();
+    psNewOptions->ePansharpenAlg = psOptions->ePansharpenAlg;
+    psNewOptions->eResampleAlg = psOptions->eResampleAlg;
+    psNewOptions->nBitDepth = psOptions->nBitDepth;
+    psNewOptions->nWeightCount = psOptions->nWeightCount;
+    if( psOptions->padfWeights )
+    {
+        psNewOptions->padfWeights =
+            (double*)CPLMalloc(sizeof(double) * psOptions->nWeightCount);
+        memcpy(psNewOptions->padfWeights,
+               psOptions->padfWeights,
+               sizeof(double) * psOptions->nWeightCount);
+    }
+    psNewOptions->hPanchroBand = psOptions->hPanchroBand;
+    psNewOptions->nInputSpectralBands = psOptions->nInputSpectralBands;
+    if( psOptions->pahInputSpectralBands )
+    {
+        psNewOptions->pahInputSpectralBands =
+            (GDALRasterBandH*)CPLMalloc(sizeof(GDALRasterBandH) * psOptions->nInputSpectralBands);
+        memcpy(psNewOptions->pahInputSpectralBands,
+               psOptions->pahInputSpectralBands,
+               sizeof(GDALRasterBandH) * psOptions->nInputSpectralBands);
+    }
+    psNewOptions->nOutPansharpenedBands = psOptions->nOutPansharpenedBands;
+    if( psOptions->panOutPansharpenedBands )
+    {
+        psNewOptions->panOutPansharpenedBands =
+            (int*)CPLMalloc(sizeof(int) * psOptions->nOutPansharpenedBands);
+        memcpy(psNewOptions->panOutPansharpenedBands,
+               psOptions->panOutPansharpenedBands,
+               sizeof(int) * psOptions->nOutPansharpenedBands);
+    }
+    psNewOptions->bHasNoData = psOptions->bHasNoData;
+    psNewOptions->dfNoData = psOptions->dfNoData;
+    psNewOptions->nThreads = psOptions->nThreads;
+    psNewOptions->dfMSShiftX = psOptions->dfMSShiftX;
+    psNewOptions->dfMSShiftY = psOptions->dfMSShiftY;
+    return psNewOptions;
+}
+
+/************************************************************************/
+/*                        GDALPansharpenOperation()                     */
+/************************************************************************/
+
+/** Pansharpening operation constructor.
+ *
+ * The object is ready to be used after Initialize() has been called.
+ */
+GDALPansharpenOperation::GDALPansharpenOperation()
+{
+    psOptions = NULL;
+    bPositiveWeights = TRUE;
+    poThreadPool = NULL;
+    nKernelRadius = 0;
+}
+
+/************************************************************************/
+/*                       ~GDALPansharpenOperation()                     */
+/************************************************************************/
+
+/** Pansharpening operation destructor.
+ */
+
+GDALPansharpenOperation::~GDALPansharpenOperation()
+{
+    GDALDestroyPansharpenOptions(psOptions);
+    for(size_t i=0;i<aVDS.size();i++)
+        delete aVDS[i];
+    delete poThreadPool;
+}
+
+/************************************************************************/
+/*                              Initialize()                            */
+/************************************************************************/
+
+/** Initialize the pansharpening operation.
+ *
+ * @param psOptionsIn pansharpening options. Must not be NULL.
+ *
+ * @return CE_None in case of success, CE_Failure in case of failure.
+ */
+CPLErr GDALPansharpenOperation::Initialize(const GDALPansharpenOptions* psOptionsIn)
+{
+    if( psOptionsIn->hPanchroBand == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "hPanchroBand not set");
+        return CE_Failure;
+    }
+    if( psOptionsIn->nInputSpectralBands <= 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "No input spectral bands defined");
+        return CE_Failure;
+    }
+    if( psOptionsIn->padfWeights == NULL ||
+        psOptionsIn->nWeightCount != psOptionsIn->nInputSpectralBands )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "No weights defined, or not the same number as input spectral bands");
+        return CE_Failure;
+    }
+    GDALRasterBandH hRefBand = psOptionsIn->pahInputSpectralBands[0];
+    int bSameDataset = psOptionsIn->nInputSpectralBands > 1;
+    if( bSameDataset )
+        anInputBands.push_back(GDALGetBandNumber(hRefBand));
+    for(int i=1;i<psOptionsIn->nInputSpectralBands;i++)
+    {
+        GDALRasterBandH hBand = psOptionsIn->pahInputSpectralBands[i];
+        if( GDALGetRasterBandXSize(hBand) != GDALGetRasterBandXSize(hRefBand) ||
+            GDALGetRasterBandYSize(hBand) != GDALGetRasterBandYSize(hRefBand) )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Dimensions of input spectral band %d different from first spectral band",
+                     i);
+            return CE_Failure;
+        }
+        if( bSameDataset )
+        {
+            if( GDALGetBandDataset(hBand) == NULL ||
+                GDALGetBandDataset(hBand) != GDALGetBandDataset(hRefBand) )
+            {
+                anInputBands.resize(0);
+                bSameDataset = FALSE;
+            }
+            else
+            {
+                anInputBands.push_back(GDALGetBandNumber(hBand));
+            }
+        }
+    }
+    if( psOptionsIn->nOutPansharpenedBands == 0 )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined, "No output pansharpened band defined");
+    }
+    for(int i=0;i<psOptionsIn->nOutPansharpenedBands;i++)
+    {
+        if( psOptionsIn->panOutPansharpenedBands[i] < 0 ||
+            psOptionsIn->panOutPansharpenedBands[i] >= psOptionsIn->nInputSpectralBands )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Invalid value panOutPansharpenedBands[%d] = %d",
+                     psOptionsIn->panOutPansharpenedBands[i], i);
+            return CE_Failure;
+        }
+    }
+
+    GDALRasterBand* poPanchroBand = (GDALRasterBand*)psOptionsIn->hPanchroBand;
+    GDALDataType eWorkDataType = poPanchroBand->GetRasterDataType();
+    if( psOptionsIn->nBitDepth )
+    {
+        if( psOptionsIn->nBitDepth < 0 || psOptionsIn->nBitDepth > 31 ||
+            (eWorkDataType == GDT_Byte && psOptionsIn->nBitDepth > 8) ||
+            (eWorkDataType == GDT_UInt16 && psOptionsIn->nBitDepth > 16) ||
+            (eWorkDataType == GDT_UInt32 && psOptionsIn->nBitDepth > 32) )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Invalid value nBitDepth = %d for type %s",
+                     psOptionsIn->nBitDepth, GDALGetDataTypeName(eWorkDataType));
+            return CE_Failure;
+        }
+    }
+
+    psOptions = GDALClonePansharpenOptions(psOptionsIn);
+    if( psOptions->nBitDepth == GDALGetDataTypeSize(eWorkDataType) )
+        psOptions->nBitDepth = 0;
+    if( psOptions->nBitDepth &&
+        !(eWorkDataType == GDT_Byte || eWorkDataType == GDT_UInt16 ||
+          eWorkDataType == GDT_UInt32) )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Ignoring nBitDepth = %d for type %s",
+                 psOptions->nBitDepth, GDALGetDataTypeName(eWorkDataType));
+        psOptions->nBitDepth = 0;
+    }
+
+    // Detect negative weights
+    for(int i=0;i<psOptions->nInputSpectralBands; i++)
+    {
+        if( psOptions->padfWeights[i] < 0.0 )
+        {
+            bPositiveWeights = FALSE;
+            break;
+        }
+    }
+
+    for(int i=0;i<psOptions->nInputSpectralBands; i++)
+    {
+        aMSBands.push_back((GDALRasterBand*)psOptions->pahInputSpectralBands[i]);
+    }
+
+    if( psOptions->bHasNoData )
+    {
+        int bNeedToWrapInVRT = FALSE;
+        for(int i=0;i<psOptions->nInputSpectralBands; i++)
+        {
+            GDALRasterBand* poBand = (GDALRasterBand*)psOptions->pahInputSpectralBands[i];
+            int bHasNoData;
+            double dfNoData = poBand->GetNoDataValue(&bHasNoData);
+            if( !bHasNoData || dfNoData != psOptions->dfNoData )
+                bNeedToWrapInVRT = TRUE;
+        }
+
+        if( bNeedToWrapInVRT )
+        {
+            // Wrap spectral bands in a VRT if they don't have the nodata value
+            VRTDataset* poVDS = NULL;
+            for(int i=0;i<psOptions->nInputSpectralBands; i++)
+            {
+                GDALRasterBand* poSrcBand = aMSBands[i];
+                if( anInputBands.size() == 0 || i == 0 )
+                {
+                    poVDS = new VRTDataset(poSrcBand->GetXSize(), poSrcBand->GetYSize());
+                    aVDS.push_back(poVDS);
+                }
+                if( anInputBands.size() )
+                    anInputBands[i] = i + 1;
+                poVDS->AddBand(poSrcBand->GetRasterDataType(), NULL);
+                VRTSourcedRasterBand* poVRTBand = (VRTSourcedRasterBand*) poVDS->GetRasterBand(i+1);
+                aMSBands[i] = poVRTBand;
+                poVRTBand->SetNoDataValue(psOptions->dfNoData);
+                const char* pszNBITS = poSrcBand->GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
+                if( pszNBITS )
+                    poVRTBand->SetMetadataItem("NBITS", pszNBITS, "IMAGE_STRUCTURE");
+
+                VRTSimpleSource* poSimpleSource = new VRTSimpleSource();
+                poVRTBand->ConfigureSource( poSimpleSource,
+                                            poSrcBand,
+                                            FALSE,
+                                            0, 0,
+                                            poSrcBand->GetXSize(), poSrcBand->GetYSize(),
+                                            0, 0,
+                                            poSrcBand->GetXSize(), poSrcBand->GetYSize() );
+                poVRTBand->AddSource( poSimpleSource );
+            }
+        }
+    }
+
+    // Setup thread pool
+    int nThreads = psOptions->nThreads;
+    if( nThreads == -1 )
+        nThreads = CPLGetNumCPUs();
+    else if( nThreads == 0 )
+    {
+        const char* pszNumThreads = CPLGetConfigOption("GDAL_NUM_THREADS", NULL);
+        if( pszNumThreads )
+        {
+            if( EQUAL(pszNumThreads, "ALL_CPUS") )
+                nThreads = CPLGetNumCPUs();
+            else
+                nThreads = atoi(pszNumThreads);
+        }
+    }
+    if( nThreads > 1 )
+    {
+        CPLDebug("PANSHARPEN", "Using %d threads", nThreads);
+        poThreadPool = new (std::nothrow) CPLWorkerThreadPool();
+        if( poThreadPool == NULL ||
+            !poThreadPool->Setup( nThreads, NULL, NULL ) )
+        {
+            delete poThreadPool;
+            poThreadPool = NULL;
+        }
+    }
+
+    GDALRIOResampleAlg eResampleAlg = psOptions->eResampleAlg;
+    if( eResampleAlg != GRIORA_NearestNeighbour )
+    {
+        const char* pszResampling =
+            (eResampleAlg == GRIORA_Bilinear) ? "BILINEAR" :
+            (eResampleAlg == GRIORA_Cubic) ? "CUBIC" :
+            (eResampleAlg == GRIORA_CubicSpline) ? "CUBICSPLINE" :
+            (eResampleAlg == GRIORA_Lanczos) ? "LANCZOS" :
+            (eResampleAlg == GRIORA_Average) ? "AVERAGE" :
+            (eResampleAlg == GRIORA_Mode) ? "MODE" :
+            (eResampleAlg == GRIORA_Gauss) ? "GAUSS" : "UNKNOWN";
+
+        GDALGetResampleFunction(pszResampling, &nKernelRadius);
+    }
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                    WeightedBroveyWithNoData()                        */
+/************************************************************************/
+
+template<class WorkDataType, class OutDataType>
+                    void GDALPansharpenOperation::WeightedBroveyWithNoData(
+                                                     const WorkDataType* pPanBuffer,
+                                                     const WorkDataType* pUpsampledSpectralBuffer,
+                                                     OutDataType* pDataBuf,
+                                                     int nValues,
+                                                     int nBandValues,
+                                                     WorkDataType nMaxValue) const
+{
+    WorkDataType noData, validValue;
+    GDALCopyWord(psOptions->dfNoData, noData);
+
+    if( !(std::numeric_limits<WorkDataType>::is_integer) )
+        validValue = (WorkDataType)(noData + 1e-5);
+    else if (noData == std::numeric_limits<WorkDataType>::min())
+        validValue = std::numeric_limits<WorkDataType>::min() + 1;
+    else
+        validValue = noData - 1;
+
+    for(int j=0;j<nValues;j++)
+    {
+        double dfFactor;
+        double dfPseudoPanchro = 0;
+        for(int i=0;i<psOptions->nInputSpectralBands;i++)
+        {
+            WorkDataType nSpectralVal = pUpsampledSpectralBuffer[i * nBandValues + j];
+            if( nSpectralVal == noData )
+            {
+                dfPseudoPanchro = 0.0;
+                break;
+            }
+            dfPseudoPanchro += psOptions->padfWeights[i] * nSpectralVal;
+        }
+        if( dfPseudoPanchro && pPanBuffer[j] != noData )
+        {
+            dfFactor = pPanBuffer[j] / dfPseudoPanchro;
+            for(int i=0;i<psOptions->nOutPansharpenedBands;i++)
+            {
+                WorkDataType nRawValue =
+                    pUpsampledSpectralBuffer[psOptions->panOutPansharpenedBands[i] * nBandValues + j];
+                WorkDataType nPansharpenedValue;
+                GDALCopyWord(nRawValue * dfFactor, nPansharpenedValue);
+                if( nMaxValue && nPansharpenedValue > nMaxValue )
+                    nPansharpenedValue = nMaxValue;
+                // We don't want a valid value to be mapped to NoData
+                if( nPansharpenedValue == noData )
+                    nPansharpenedValue = validValue;
+                GDALCopyWord(nPansharpenedValue, pDataBuf[i * nBandValues + j]);
+            }
+        }
+        else
+        {
+            for(int i=0;i<psOptions->nOutPansharpenedBands;i++)
+            {
+                GDALCopyWord(noData, pDataBuf[i * nBandValues + j]);
+            }
+        }
+    }
+}
+
+/************************************************************************/
+/*                         WeightedBrovey()                             */
+/************************************************************************/
+
+template<class WorkDataType, class OutDataType, int bHasBitDepth>
+                    void GDALPansharpenOperation::WeightedBrovey3(
+                                                     const WorkDataType* pPanBuffer,
+                                                     const WorkDataType* pUpsampledSpectralBuffer,
+                                                     OutDataType* pDataBuf,
+                                                     int nValues,
+                                                     int nBandValues,
+                                                     WorkDataType nMaxValue) const
+{
+    if( psOptions->bHasNoData )
+    {
+        WeightedBroveyWithNoData<WorkDataType,OutDataType>
+                                (pPanBuffer, pUpsampledSpectralBuffer,
+                                 pDataBuf, nValues, nBandValues, nMaxValue);
+        return;
+    }
+
+    for(int j=0;j<nValues;j++)
+    {
+        double dfFactor;
+        //if( pPanBuffer[j] == 0 )
+        //    dfFactor = 1.0;
+        //else
+        {
+            double dfPseudoPanchro = 0;
+            for(int i=0;i<psOptions->nInputSpectralBands;i++)
+                dfPseudoPanchro += psOptions->padfWeights[i] *
+                                pUpsampledSpectralBuffer[i * nBandValues + j];
+            if( dfPseudoPanchro )
+                dfFactor = pPanBuffer[j] / dfPseudoPanchro;
+            else
+                dfFactor = 0.0;
+        }
+
+        for(int i=0;i<psOptions->nOutPansharpenedBands;i++)
+        {
+            WorkDataType nRawValue =
+                pUpsampledSpectralBuffer[psOptions->panOutPansharpenedBands[i] * nBandValues + j];
+            WorkDataType nPansharpenedValue;
+            GDALCopyWord(nRawValue * dfFactor, nPansharpenedValue);
+            if( bHasBitDepth && nPansharpenedValue > nMaxValue )
+                nPansharpenedValue = nMaxValue;
+            GDALCopyWord(nPansharpenedValue, pDataBuf[i * nBandValues + j]);
+        }
+    }
+}
+
+/* We restrict to 64bit processors because they are guaranteed to have SSE2 */
+/* Could possibly be used too on 32bit, but we would need to check at runtime */
+#if defined(__x86_64) || defined(_M_X64)
+
+#include <gdalsse_priv.h>
+
+template<int NINPUT, int NOUTPUT>
+int GDALPansharpenOperation::WeightedBroveyPositiveWeightsInternal(
+                                                     const GUInt16* pPanBuffer,
+                                                     const GUInt16* pUpsampledSpectralBuffer,
+                                                     GUInt16* pDataBuf,
+                                                     int nValues,
+                                                     int nBandValues,
+                                                     GUInt16 nMaxValue) const
+{
+    CPLAssert( NINPUT == 3 || NINPUT == 4 );
+    const XMMReg4Double w0 = XMMReg4Double::Load1ValHighAndLow(psOptions->padfWeights + 0);
+    const XMMReg4Double w1 = XMMReg4Double::Load1ValHighAndLow(psOptions->padfWeights + 1);
+    const XMMReg4Double w2 = XMMReg4Double::Load1ValHighAndLow(psOptions->padfWeights + 2);
+    const XMMReg4Double w3 = (NINPUT == 3) ? XMMReg4Double::Zero() :
+                    XMMReg4Double::Load1ValHighAndLow(psOptions->padfWeights + 3);
+
+    const XMMReg4Double zero = XMMReg4Double::Zero();
+    double dfMaxValue = nMaxValue;
+    const XMMReg4Double maxValue = XMMReg4Double::Load1ValHighAndLow(&dfMaxValue);
+
+    int j;
+    for(j=0;j<nValues-3;j+=4)
+    {
+        XMMReg4Double pseudoPanchro = zero;
+
+        pseudoPanchro += w0 * XMMReg4Double::Load4Val(pUpsampledSpectralBuffer + j);
+        pseudoPanchro += w1 * XMMReg4Double::Load4Val(pUpsampledSpectralBuffer + nBandValues + j);
+        pseudoPanchro += w2 * XMMReg4Double::Load4Val(pUpsampledSpectralBuffer + 2 * nBandValues + j);
+        if( NINPUT == 4 )
+            pseudoPanchro += w3 * XMMReg4Double::Load4Val(pUpsampledSpectralBuffer + 3 * nBandValues + j);
+
+        /* Little trick to avoid use of ternary operator due to one of the branch being zero */
+        XMMReg4Double factor = XMMReg4Double::And(
+            XMMReg4Double::NotEquals(pseudoPanchro, zero),
+            XMMReg4Double::Load4Val(pPanBuffer + j) / pseudoPanchro );
+
+        for(int i=0;i<NOUTPUT;i++)
+        {
+            XMMReg4Double rawValue = XMMReg4Double::Load4Val(pUpsampledSpectralBuffer + i * nBandValues + j);
+            XMMReg4Double tmp = XMMReg4Double::Min(rawValue * factor, maxValue);
+            tmp.Store4Val(pDataBuf + i * nBandValues + j);
+        }
+    }
+    return j;
+}
+
+#else
+
+template<int NINPUT, int NOUTPUT>
+int GDALPansharpenOperation::WeightedBroveyPositiveWeightsInternal(
+                                                     const GUInt16* pPanBuffer,
+                                                     const GUInt16* pUpsampledSpectralBuffer,
+                                                     GUInt16* pDataBuf,
+                                                     int nValues,
+                                                     int nBandValues,
+                                                     GUInt16 nMaxValue) const
+{
+    CPLAssert( NINPUT == 3 || NINPUT == 4 );
+    const double dfw0 = psOptions->padfWeights[0];
+    const double dfw1 = psOptions->padfWeights[1];
+    const double dfw2 = psOptions->padfWeights[2];
+    const double dfw3 = (NINPUT == 3) ? 0 : psOptions->padfWeights[3];
+    int j;
+    for(j=0;j<nValues-1;j+=2)
+    {
+        double dfFactor, dfFactor2;
+        double dfPseudoPanchro = 0;
+        double dfPseudoPanchro2 = 0;
+
+        dfPseudoPanchro += dfw0 *
+                        pUpsampledSpectralBuffer[j];
+        dfPseudoPanchro2 += dfw0 *
+                        pUpsampledSpectralBuffer[j + 1];
+
+        dfPseudoPanchro += dfw1 *
+                        pUpsampledSpectralBuffer[nBandValues + j];
+        dfPseudoPanchro2 += dfw1 *
+                        pUpsampledSpectralBuffer[nBandValues + j + 1];
+
+        dfPseudoPanchro += dfw2 *
+                        pUpsampledSpectralBuffer[2 * nBandValues + j];
+        dfPseudoPanchro2 += dfw2 *
+                        pUpsampledSpectralBuffer[2 * nBandValues + j + 1];
+
+        if( NINPUT == 4 )
+        {
+            dfPseudoPanchro += dfw3 *
+                            pUpsampledSpectralBuffer[3 * nBandValues + j];
+            dfPseudoPanchro2 += dfw3 *
+                            pUpsampledSpectralBuffer[3 * nBandValues + j + 1];
+        }
+
+        if( dfPseudoPanchro )
+            dfFactor = pPanBuffer[j] / dfPseudoPanchro;
+        else
+            dfFactor = 0.0;
+        if( dfPseudoPanchro2 )
+            dfFactor2 = pPanBuffer[j+1] / dfPseudoPanchro2;
+        else
+            dfFactor2 = 0.0;
+
+        for(int i=0;i<NOUTPUT;i++)
+        {
+            GUInt16 nRawValue =
+                pUpsampledSpectralBuffer[i * nBandValues + j];
+            double dfTmp = nRawValue * dfFactor;
+            if( dfTmp > nMaxValue )
+                pDataBuf[i * nBandValues + j] = nMaxValue;
+            else
+                pDataBuf[i * nBandValues + j] = (GUInt16)(dfTmp + 0.5);
+
+            GUInt16 nRawValue2 =
+                pUpsampledSpectralBuffer[i * nBandValues + j + 1];
+            double dfTmp2 = nRawValue2 * dfFactor2;
+            if( dfTmp2 > nMaxValue )
+                pDataBuf[i * nBandValues + j + 1] = nMaxValue;
+            else
+                pDataBuf[i * nBandValues + j + 1] = (GUInt16)(dfTmp2 + 0.5);
+        }
+    }
+    return j;
+}
+#endif
+
+void GDALPansharpenOperation::WeightedBroveyPositiveWeights(
+                                                     const GUInt16* pPanBuffer,
+                                                     const GUInt16* pUpsampledSpectralBuffer,
+                                                     GUInt16* pDataBuf,
+                                                     int nValues,
+                                                     int nBandValues,
+                                                     GUInt16 nMaxValue) const
+{
+    if( psOptions->bHasNoData )
+    {
+        WeightedBroveyWithNoData<GUInt16,GUInt16>
+                                (pPanBuffer, pUpsampledSpectralBuffer,
+                                 pDataBuf, nValues, nBandValues, nMaxValue);
+        return;
+    }
+
+    if( nMaxValue == 0 )
+        nMaxValue = std::numeric_limits<GUInt16>::max();
+    int j;
+    if( psOptions->nInputSpectralBands == 3 &&
+        psOptions->nOutPansharpenedBands == 3 &&
+        psOptions->panOutPansharpenedBands[0] == 0 &&
+        psOptions->panOutPansharpenedBands[1] == 1 &&
+        psOptions->panOutPansharpenedBands[2] == 2 )
+    {
+        j = WeightedBroveyPositiveWeightsInternal<3,3>(
+            pPanBuffer, pUpsampledSpectralBuffer, pDataBuf, nValues, nBandValues, nMaxValue);
+    }
+    else if( psOptions->nInputSpectralBands == 4 &&
+        psOptions->nOutPansharpenedBands == 4 &&
+        psOptions->panOutPansharpenedBands[0] == 0 &&
+        psOptions->panOutPansharpenedBands[1] == 1 &&
+        psOptions->panOutPansharpenedBands[2] == 2 &&
+        psOptions->panOutPansharpenedBands[3] == 3 )
+    {
+        j = WeightedBroveyPositiveWeightsInternal<4,4>(
+            pPanBuffer, pUpsampledSpectralBuffer, pDataBuf, nValues, nBandValues, nMaxValue);
+    }
+    else if( psOptions->nInputSpectralBands == 4 &&
+        psOptions->nOutPansharpenedBands == 3 &&
+        psOptions->panOutPansharpenedBands[0] == 0 &&
+        psOptions->panOutPansharpenedBands[1] == 1 &&
+        psOptions->panOutPansharpenedBands[2] == 2 )
+    {
+        j = WeightedBroveyPositiveWeightsInternal<4,3>(
+            pPanBuffer, pUpsampledSpectralBuffer, pDataBuf, nValues, nBandValues, nMaxValue);
+    }
+    else
+    {
+        for(j=0;j<nValues-1;j+=2)
+        {
+            double dfFactor, dfFactor2;
+            double dfPseudoPanchro = 0;
+            double dfPseudoPanchro2 = 0;
+            for(int i=0;i<psOptions->nInputSpectralBands;i++)
+            {
+                dfPseudoPanchro += psOptions->padfWeights[i] *
+                                pUpsampledSpectralBuffer[i * nBandValues + j];
+                dfPseudoPanchro2 += psOptions->padfWeights[i] *
+                                pUpsampledSpectralBuffer[i * nBandValues + j + 1];
+            }
+            if( dfPseudoPanchro )
+                dfFactor = pPanBuffer[j] / dfPseudoPanchro;
+            else
+                dfFactor = 0.0;
+            if( dfPseudoPanchro2 )
+                dfFactor2 = pPanBuffer[j+1] / dfPseudoPanchro2;
+            else
+                dfFactor2 = 0.0;
+
+            for(int i=0;i<psOptions->nOutPansharpenedBands;i++)
+            {
+                GUInt16 nRawValue =
+                    pUpsampledSpectralBuffer[psOptions->panOutPansharpenedBands[i] * nBandValues + j];
+                double dfTmp = nRawValue * dfFactor;
+                if( dfTmp > nMaxValue )
+                    pDataBuf[i * nBandValues + j] = nMaxValue;
+                else
+                    pDataBuf[i * nBandValues + j] = (GUInt16)(dfTmp + 0.5);
+
+                GUInt16 nRawValue2 =
+                    pUpsampledSpectralBuffer[psOptions->panOutPansharpenedBands[i] * nBandValues + j + 1];
+                double dfTmp2 = nRawValue2 * dfFactor2;
+                if( dfTmp2 > nMaxValue )
+                    pDataBuf[i * nBandValues + j + 1] = nMaxValue;
+                else
+                    pDataBuf[i * nBandValues + j + 1] = (GUInt16)(dfTmp2 + 0.5);
+            }
+        }
+    }
+    for( ;j<nValues ;j++)
+    {
+        double dfFactor;
+        double dfPseudoPanchro = 0;
+        for(int i=0;i<psOptions->nInputSpectralBands;i++)
+            dfPseudoPanchro += psOptions->padfWeights[i] *
+                            pUpsampledSpectralBuffer[i * nBandValues + j];
+        if( dfPseudoPanchro )
+            dfFactor = pPanBuffer[j] / dfPseudoPanchro;
+        else
+            dfFactor = 0.0;
+
+        for(int i=0;i<psOptions->nOutPansharpenedBands;i++)
+        {
+            GUInt16 nRawValue =
+                pUpsampledSpectralBuffer[psOptions->panOutPansharpenedBands[i] * nBandValues + j];
+            double dfTmp = nRawValue * dfFactor;
+            if( dfTmp > nMaxValue )
+                pDataBuf[i * nBandValues + j] = nMaxValue;
+            else
+                pDataBuf[i * nBandValues + j] = (GUInt16)(dfTmp + 0.5);
+        }
+    }
+}
+
+template<class WorkDataType, class OutDataType> void GDALPansharpenOperation::WeightedBrovey(
+                                                     const WorkDataType* pPanBuffer,
+                                                     const WorkDataType* pUpsampledSpectralBuffer,
+                                                     OutDataType* pDataBuf,
+                                                     int nValues,
+                                                     int nBandValues,
+                                                     WorkDataType nMaxValue) const
+{
+    if( nMaxValue == 0 )
+        WeightedBrovey3<WorkDataType, OutDataType, FALSE>(
+            pPanBuffer, pUpsampledSpectralBuffer, pDataBuf, nValues, nBandValues, 0);
+    else
+    {
+        WeightedBrovey3<WorkDataType, OutDataType, TRUE>(
+            pPanBuffer, pUpsampledSpectralBuffer, pDataBuf, nValues, nBandValues, nMaxValue);
+    }
+}
+
+template<>
+void GDALPansharpenOperation::WeightedBrovey<GUInt16,GUInt16>(
+                                                     const GUInt16* pPanBuffer,
+                                                     const GUInt16* pUpsampledSpectralBuffer,
+                                                     GUInt16* pDataBuf,
+                                                     int nValues,
+                                                     int nBandValues,
+                                                     GUInt16 nMaxValue) const
+{
+    if( bPositiveWeights )
+    {
+        WeightedBroveyPositiveWeights(
+                pPanBuffer, pUpsampledSpectralBuffer, pDataBuf, nValues, nBandValues, nMaxValue);
+    }
+    else if( nMaxValue == 0 )
+    {
+        WeightedBrovey3<GUInt16, GUInt16, FALSE>(
+                pPanBuffer, pUpsampledSpectralBuffer, pDataBuf, nValues, nBandValues, 0);
+    }
+    else
+    {
+        WeightedBrovey3<GUInt16, GUInt16, TRUE>(
+            pPanBuffer, pUpsampledSpectralBuffer, pDataBuf, nValues, nBandValues, nMaxValue);
+    }
+}
+
+template<class WorkDataType> CPLErr GDALPansharpenOperation::WeightedBrovey(
+                                                     const WorkDataType* pPanBuffer,
+                                                     const WorkDataType* pUpsampledSpectralBuffer,
+                                                     void *pDataBuf,
+                                                     GDALDataType eBufDataType,
+                                                     int nValues,
+                                                     int nBandValues,
+                                                     WorkDataType nMaxValue) const
+{
+    switch( eBufDataType )
+    {
+        case GDT_Byte:
+            WeightedBrovey(pPanBuffer, pUpsampledSpectralBuffer,
+                           (GByte*)pDataBuf, nValues, nBandValues, nMaxValue);
+            break;
+
+        case GDT_UInt16:
+            WeightedBrovey(pPanBuffer, pUpsampledSpectralBuffer,
+                           (GUInt16*)pDataBuf, nValues, nBandValues, nMaxValue);
+            break;
+
+#ifndef LIMIT_TYPES
+        case GDT_Int16:
+            WeightedBrovey(pPanBuffer, pUpsampledSpectralBuffer,
+                           (GInt16*)pDataBuf, nValues, nBandValues, nMaxValue);
+            break;
+
+        case GDT_UInt32:
+            WeightedBrovey(pPanBuffer, pUpsampledSpectralBuffer,
+                           (GUInt32*)pDataBuf, nValues, nBandValues, nMaxValue);
+            break;
+
+        case GDT_Int32:
+            WeightedBrovey(pPanBuffer, pUpsampledSpectralBuffer,
+                           (GInt32*)pDataBuf, nValues, nBandValues, nMaxValue);
+            break;
+
+        case GDT_Float32:
+            WeightedBrovey(pPanBuffer, pUpsampledSpectralBuffer,
+                           (float*)pDataBuf, nValues, nBandValues, nMaxValue);
+            break;
+#endif
+
+        case GDT_Float64:
+            WeightedBrovey(pPanBuffer, pUpsampledSpectralBuffer,
+                           (double*)pDataBuf, nValues, nBandValues, nMaxValue);
+            break;
+
+        default:
+            CPLError(CE_Failure, CPLE_NotSupported, "eBufDataType not supported");
+            return CE_Failure;
+            break;
+    }
+
+    return CE_None;
+}
+
+template<class WorkDataType> CPLErr GDALPansharpenOperation::WeightedBrovey(
+                                                     const WorkDataType* pPanBuffer,
+                                                     const WorkDataType* pUpsampledSpectralBuffer,
+                                                     void *pDataBuf,
+                                                     GDALDataType eBufDataType,
+                                                     int nValues, int nBandValues) const
+{
+    switch( eBufDataType )
+    {
+        case GDT_Byte:
+            WeightedBrovey3<WorkDataType, GByte, FALSE>(pPanBuffer, pUpsampledSpectralBuffer,
+                           (GByte*)pDataBuf, nValues, nBandValues, 0);
+            break;
+
+        case GDT_UInt16:
+            WeightedBrovey3<WorkDataType, GUInt16, FALSE>(pPanBuffer, pUpsampledSpectralBuffer,
+                           (GUInt16*)pDataBuf, nValues, nBandValues, 0);
+            break;
+
+#ifndef LIMIT_TYPES
+        case GDT_Int16:
+            WeightedBrovey3<WorkDataType, GInt16, FALSE>(pPanBuffer, pUpsampledSpectralBuffer,
+                           (GInt16*)pDataBuf, nValues, nBandValues, 0);
+            break;
+
+        case GDT_UInt32:
+            WeightedBrovey3<WorkDataType, GUInt32, FALSE>(pPanBuffer, pUpsampledSpectralBuffer,
+                           (GUInt32*)pDataBuf, nValues, nBandValues, 0);
+            break;
+
+        case GDT_Int32:
+            WeightedBrovey3<WorkDataType, GInt32, FALSE>(pPanBuffer, pUpsampledSpectralBuffer,
+                           (GInt32*)pDataBuf, nValues, nBandValues, 0);
+            break;
+
+        case GDT_Float32:
+            WeightedBrovey3<WorkDataType, float, FALSE>(pPanBuffer, pUpsampledSpectralBuffer,
+                           (float*)pDataBuf, nValues, nBandValues, 0);
+            break;
+#endif
+
+        case GDT_Float64:
+            WeightedBrovey3<WorkDataType, double, FALSE>(pPanBuffer, pUpsampledSpectralBuffer,
+                           (double*)pDataBuf, nValues, nBandValues, 0);
+            break;
+
+        default:
+            CPLError(CE_Failure, CPLE_NotSupported, "eBufDataType not supported");
+            return CE_Failure;
+            break;
+    }
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                           ClampValues()                              */
+/************************************************************************/
+
+template< class T >
+static void ClampValues(T* panBuffer, int nValues, T nMaxVal)
+{
+    for(int i=0;i<nValues;i++)
+    {
+        if( panBuffer[i] > nMaxVal )
+            panBuffer[i] = nMaxVal;
+    }
+}
+
+/************************************************************************/
+/*                         ProcessRegion()                              */
+/************************************************************************/
+
+/** Executes a pansharpening operation on a rectangular region of the
+ * resulting dataset.
+ *
+ * The window is expressed with respect to the dimensions of the panchromatic
+ * band.
+ *
+ * Spectral bands are upsampled and merged with the panchromatic band according
+ * to the select algorithm and options.
+ *
+ * @param nXOff pixel offset.
+ * @param nYOff pixel offset.
+ * @param nXSize width of the pansharpened region to compute.
+ * @param nYSize height of the pansharpened region to compute.
+ * @param pDataBuf output buffer. Must be nXSize * nYSize *
+ *                 GDALGetDataTypeSizeBytes(eBufDataType) *
+ *                 psOptions->nOutPansharpenedBands large.
+ *                 It begins with all values of the first output band, followed
+ *                 by values of the second output band, etc...
+ * @param eBufDataType data type of the output buffer
+ *
+ * @return CE_None in case of success, CE_Failure in case of failure.
+ *
+ * @since GDAL 2.1
+ */
+CPLErr GDALPansharpenOperation::ProcessRegion(int nXOff, int nYOff,
+                                              int nXSize, int nYSize,
+                                              void *pDataBuf,
+                                              GDALDataType eBufDataType)
+{
+    if( psOptions == NULL )
+        return CE_Failure;
+
+    // TODO: avoid allocating buffers each time
+    GDALRasterBand* poPanchroBand = (GDALRasterBand*)psOptions->hPanchroBand;
+    GDALDataType eWorkDataType = poPanchroBand->GetRasterDataType();
+#ifdef LIMIT_TYPES
+    if( eWorkDataType != GDT_Byte && eWorkDataType != GDT_UInt16 )
+        eWorkDataType = GDT_Float64;
+#endif
+    const int nDataTypeSize = GDALGetDataTypeSizeBytes(eWorkDataType);
+    GByte* pUpsampledSpectralBuffer = (GByte*)VSI_MALLOC3_VERBOSE(nXSize, nYSize,
+        psOptions->nInputSpectralBands * nDataTypeSize);
+    GByte* pPanBuffer = (GByte*)VSI_MALLOC3_VERBOSE(nXSize, nYSize, nDataTypeSize);
+    if( pUpsampledSpectralBuffer == NULL || pPanBuffer == NULL )
+    {
+        VSIFree(pUpsampledSpectralBuffer);
+        VSIFree(pPanBuffer);
+        return CE_Failure;
+    }
+
+    CPLErr eErr =
+        poPanchroBand->RasterIO(GF_Read,
+                nXOff, nYOff, nXSize, nYSize, pPanBuffer, nXSize, nYSize,
+                eWorkDataType, 0, 0, NULL);
+    if( eErr != CE_None )
+    {
+        VSIFree(pUpsampledSpectralBuffer);
+        VSIFree(pPanBuffer);
+        return CE_Failure;
+    }
+
+    int nTasks = 0;
+    if( poThreadPool )
+    {
+        nTasks = poThreadPool->GetThreadCount();
+        if( nTasks > nYSize )
+            nTasks = nYSize;
+    }
+
+    GDALRasterIOExtraArg sExtraArg;
+    INIT_RASTERIO_EXTRA_ARG(sExtraArg);
+    const GDALRIOResampleAlg eResampleAlg = psOptions->eResampleAlg;
+    sExtraArg.eResampleAlg = eResampleAlg;
+    sExtraArg.bFloatingPointWindowValidity = TRUE;
+    double dfRatioX = (double)poPanchroBand->GetXSize() / aMSBands[0]->GetXSize();
+    double dfRatioY = (double)poPanchroBand->GetYSize() / aMSBands[0]->GetYSize();
+    sExtraArg.dfXOff = (nXOff + psOptions->dfMSShiftX) / dfRatioX;
+    sExtraArg.dfYOff = (nYOff + psOptions->dfMSShiftY) / dfRatioY;
+    sExtraArg.dfXSize = nXSize / dfRatioX;
+    sExtraArg.dfYSize = nYSize / dfRatioY;
+    if( sExtraArg.dfXOff + sExtraArg.dfXSize > aMSBands[0]->GetXSize() )
+        sExtraArg.dfXOff = aMSBands[0]->GetXSize() - sExtraArg.dfXSize;
+    if( sExtraArg.dfYOff + sExtraArg.dfYSize > aMSBands[0]->GetYSize() )
+        sExtraArg.dfYOff = aMSBands[0]->GetYSize() - sExtraArg.dfYSize;
+    int nSpectralXOff = (int)(sExtraArg.dfXOff);
+    int nSpectralYOff = (int)(sExtraArg.dfYOff);
+    int nSpectralXSize = (int)(0.49999 + sExtraArg.dfXSize);
+    int nSpectralYSize = (int)(0.49999 + sExtraArg.dfYSize);
+    if( nSpectralXSize == 0 )
+        nSpectralXSize = 1;
+    if( nSpectralYSize == 0 )
+        nSpectralYSize = 1;
+
+    // When upsampling, extract the multispectral data at
+    // full resolution in a temp buffer, and then do the upsampling.
+    if( nSpectralXSize < nXSize && nSpectralYSize < nYSize &&
+        eResampleAlg != GRIORA_NearestNeighbour && nYSize > 1 )
+    {
+        // Take some margin to take into account the radius of the resampling kernel
+        int nXOffExtract = nSpectralXOff - nKernelRadius;
+        int nYOffExtract = nSpectralYOff - nKernelRadius;
+        int nXSizeExtract = nSpectralXSize + 1 + 2 * nKernelRadius;
+        int nYSizeExtract = nSpectralYSize + 1 + 2 * nKernelRadius;
+        if( nXOffExtract < 0 )
+        {
+            nXSizeExtract += nXOffExtract;
+            nXOffExtract = 0;
+        }
+        if( nYOffExtract < 0 )
+        {
+            nYSizeExtract += nYOffExtract;
+            nYOffExtract = 0;
+        }
+        if( nXOffExtract + nXSizeExtract > aMSBands[0]->GetXSize() )
+            nXSizeExtract = aMSBands[0]->GetXSize() - nXOffExtract;
+        if( nYOffExtract + nYSizeExtract > aMSBands[0]->GetYSize() )
+            nYSizeExtract = aMSBands[0]->GetYSize() - nYOffExtract;
+
+        GByte* pSpectralBuffer = (GByte*)VSI_MALLOC3_VERBOSE(nXSizeExtract, nYSizeExtract,
+                            psOptions->nInputSpectralBands * nDataTypeSize);
+        if( pSpectralBuffer == NULL )
+        {
+            VSIFree(pUpsampledSpectralBuffer);
+            VSIFree(pPanBuffer);
+            return CE_Failure;
+        }
+
+        if( anInputBands.size() )
+        {
+            // Use dataset RasterIO when possible
+            eErr = aMSBands[0]->GetDataset()->RasterIO(GF_Read,
+                        nXOffExtract, nYOffExtract,
+                        nXSizeExtract, nYSizeExtract,
+                        pSpectralBuffer,
+                        nXSizeExtract, nYSizeExtract,
+                        eWorkDataType,
+                        (int)anInputBands.size(), &anInputBands[0],
+                        0, 0, 0, NULL);
+        }
+        else
+        {
+            for(int i=0; eErr == CE_None && i < psOptions->nInputSpectralBands; i++)
+            {
+                eErr = aMSBands[i]->RasterIO(GF_Read,
+                        nXOffExtract, nYOffExtract,
+                        nXSizeExtract, nYSizeExtract,
+                        pSpectralBuffer + (size_t)i * nXSizeExtract * nYSizeExtract * nDataTypeSize,
+                        nXSizeExtract, nYSizeExtract,
+                        eWorkDataType, 0, 0, NULL);
+            }
+        }
+        if( eErr != CE_None )
+        {
+            VSIFree(pSpectralBuffer);
+            VSIFree(pUpsampledSpectralBuffer);
+            VSIFree(pPanBuffer);
+            return CE_Failure;
+        }
+
+        /* Create a MEM dataset that wraps the input buffer */
+        GDALDataset* poMEMDS = MEMDataset::Create("", nXSizeExtract, nYSizeExtract, 0,
+                                                  eWorkDataType, NULL);
+
+        char* apszOptions[4];
+        char szBuffer0[64], szBuffer1[64], szBuffer2[64];
+
+        snprintf(szBuffer1, sizeof(szBuffer1), "PIXELOFFSET=" CPL_FRMT_GIB, (GIntBig)nDataTypeSize);
+        snprintf(szBuffer2, sizeof(szBuffer2), "LINEOFFSET=" CPL_FRMT_GIB, (GIntBig)nDataTypeSize * nXSizeExtract);
+        apszOptions[0] = szBuffer0;
+        apszOptions[1] = szBuffer1;
+        apszOptions[2] = szBuffer2;
+        apszOptions[3] = NULL;
+
+        for( int i = 0; i < psOptions->nInputSpectralBands; i++ )
+        {
+            char szBuffer[64];
+            int nRet = CPLPrintPointer(szBuffer,
+                       pSpectralBuffer + (size_t)i * nDataTypeSize * nXSizeExtract * nYSizeExtract, sizeof(szBuffer));
+            szBuffer[nRet] = 0;
+
+            snprintf(szBuffer0, sizeof(szBuffer0), "DATAPOINTER=%s", szBuffer);
+
+            poMEMDS->AddBand(eWorkDataType, apszOptions);
+
+            const char* pszNBITS = aMSBands[i]->GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
+            if( pszNBITS )
+                poMEMDS->GetRasterBand(i+1)->SetMetadataItem("NBITS", pszNBITS, "IMAGE_STRUCTURE");
+
+            if( psOptions->bHasNoData )
+                poMEMDS->GetRasterBand(i+1)->SetNoDataValue(psOptions->dfNoData);
+        }
+
+        if( nTasks <= 1 )
+        {
+            nSpectralXOff -= nXOffExtract;
+            nSpectralYOff -= nYOffExtract;
+            sExtraArg.dfXOff -= nXOffExtract;
+            sExtraArg.dfYOff -= nYOffExtract;
+            CPL_IGNORE_RET_VAL(poMEMDS->RasterIO(GF_Read,
+                              nSpectralXOff,
+                              nSpectralYOff,
+                              nSpectralXSize, nSpectralYSize,
+                              pUpsampledSpectralBuffer, nXSize, nYSize,
+                              eWorkDataType,
+                              psOptions->nInputSpectralBands, NULL,
+                              0, 0, 0,
+                              &sExtraArg));
+        }
+        else
+        {
+            // We are abusing the contract of the GDAL API by using the MEMDataset
+            // from several threads. In this case, this is safe. In case that would
+            // no longer be the case we could create as many MEMDataset as threads
+            // pointing to the same buffer.
+
+            // To avoid races in threads, we query now the mask flags
+            // so that implicit mask bands are created now
+            if( eResampleAlg != GRIORA_NearestNeighbour )
+            {
+                for(int i=0;i<poMEMDS->GetRasterCount();i++)
+                {
+                    poMEMDS->GetRasterBand(i+1)->GetMaskFlags();
+                }
+            }
+
+            std::vector<GDALPansharpenResampleJob> asJobs;
+            asJobs.resize( nTasks );
+            GDALPansharpenResampleJob* pasJobs = &(asJobs[0]);
+            {
+                std::vector<void*> ahJobData;
+                ahJobData.resize( nTasks );
+
+#ifdef DEBUG_TIMING
+                struct timeval tv;
+#endif
+                for( int i=0;i<nTasks;i++)
+                {
+                    size_t iStartLine = ((size_t)i * nYSize) / nTasks;
+                    size_t iNextStartLine = ((size_t)(i+1) * nYSize) / nTasks;
+                    pasJobs[i].poMEMDS = poMEMDS;
+                    pasJobs[i].eResampleAlg = eResampleAlg;
+                    pasJobs[i].dfXOff = sExtraArg.dfXOff - nXOffExtract;
+                    pasJobs[i].dfYOff = (nYOff + psOptions->dfMSShiftY + iStartLine) / dfRatioY - nYOffExtract;
+                    pasJobs[i].dfXSize = sExtraArg.dfXSize;
+                    pasJobs[i].dfYSize = (iNextStartLine - iStartLine) / dfRatioY;
+                    if( pasJobs[i].dfXOff + pasJobs[i].dfXSize > aMSBands[0]->GetXSize() )
+                        pasJobs[i].dfXOff = aMSBands[0]->GetXSize() - pasJobs[i].dfXSize;
+                    if( pasJobs[i].dfYOff + pasJobs[i].dfYSize > aMSBands[0]->GetYSize() )
+                        pasJobs[i].dfYOff = aMSBands[0]->GetYSize() - pasJobs[i].dfYSize;
+                    pasJobs[i].nXOff = (int)pasJobs[i].dfXOff;
+                    pasJobs[i].nYOff = (int)pasJobs[i].dfYOff;
+                    pasJobs[i].nXSize = (int)(0.4999 + pasJobs[i].dfXSize);
+                    pasJobs[i].nYSize = (int)(0.4999 + pasJobs[i].dfYSize);
+                    if( pasJobs[i].nXSize == 0 )
+                        pasJobs[i].nXSize = 1;
+                    if( pasJobs[i].nYSize == 0 )
+                        pasJobs[i].nYSize = 1;
+                    pasJobs[i].pBuffer = pUpsampledSpectralBuffer + (size_t)iStartLine * nXSize * nDataTypeSize;
+                    pasJobs[i].eDT = eWorkDataType;
+                    pasJobs[i].nBufXSize = nXSize;
+                    pasJobs[i].nBufYSize = (int)(iNextStartLine - iStartLine);
+                    pasJobs[i].nBandCount = psOptions->nInputSpectralBands;
+                    pasJobs[i].nBandSpace = (GSpacing)nXSize * nYSize * nDataTypeSize;
+#ifdef DEBUG_TIMING
+                    pasJobs[i].ptv = &tv;
+#endif
+                    ahJobData[i] = &(pasJobs[i]);
+                }
+#ifdef DEBUG_TIMING
+                gettimeofday(&tv, NULL);
+#endif
+                poThreadPool->SubmitJobs(PansharpenResampleJobThreadFunc, ahJobData);
+                poThreadPool->WaitCompletion();
+            }
+        }
+
+        GDALClose(poMEMDS);
+
+        VSIFree(pSpectralBuffer);
+    }
+    else
+    {
+        if( anInputBands.size() )
+        {
+            // Use dataset RasterIO when possible
+            eErr = aMSBands[0]->GetDataset()->RasterIO(GF_Read,
+                        nSpectralXOff, nSpectralYOff,
+                        nSpectralXSize, nSpectralYSize,
+                        pUpsampledSpectralBuffer,
+                        nXSize, nYSize,
+                        eWorkDataType,
+                        (int)anInputBands.size(), &anInputBands[0],
+                        0, 0, 0, &sExtraArg);
+        }
+        else
+        {
+            for(int i=0; eErr == CE_None && i < psOptions->nInputSpectralBands; i++)
+            {
+                eErr = aMSBands[i]->RasterIO(GF_Read,
+                        nSpectralXOff, nSpectralYOff,
+                        nSpectralXSize, nSpectralYSize,
+                        pUpsampledSpectralBuffer + (size_t)i * nXSize * nYSize * nDataTypeSize,
+                        nXSize, nYSize,
+                        eWorkDataType, 0, 0, &sExtraArg);
+            }
+        }
+        if( eErr != CE_None )
+        {
+            VSIFree(pUpsampledSpectralBuffer);
+            VSIFree(pPanBuffer);
+            return CE_Failure;
+        }
+    }
+
+    // In case NBITS was not set on the spectral bands, clamp the values
+    // if overshoot might have occurred.
+    int nBitDepth = psOptions->nBitDepth;
+    if( nBitDepth && (eResampleAlg == GRIORA_Cubic ||
+                      eResampleAlg == GRIORA_CubicSpline ||
+                      eResampleAlg == GRIORA_Lanczos) )
+    {
+        for(int i=0;i < psOptions->nInputSpectralBands; i++)
+        {
+            GDALRasterBand* poBand = aMSBands[i];
+            int nBandBitDepth = 0;
+            const char* pszNBITS = poBand->GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
+            if( pszNBITS )
+                nBandBitDepth = atoi(pszNBITS);
+            if( nBandBitDepth < nBitDepth )
+            {
+                if( eWorkDataType == GDT_Byte )
+                {
+                    ClampValues(((GByte*)pUpsampledSpectralBuffer) + i * nXSize * nYSize,
+                               nXSize*nYSize,
+                               (GByte)((1 << nBitDepth)-1));
+                }
+                else if( eWorkDataType == GDT_UInt16 )
+                {
+                    ClampValues(((GUInt16*)pUpsampledSpectralBuffer) + i * nXSize * nYSize,
+                               nXSize*nYSize,
+                               (GUInt16)((1 << nBitDepth)-1));
+                }
+#ifndef LIMIT_TYPES
+                else if( eWorkDataType == GDT_UInt32 )
+                {
+                    ClampValues(((GUInt32*)pUpsampledSpectralBuffer) + i * nXSize * nYSize,
+                               nXSize*nYSize,
+                               (GUInt32)((1 << nBitDepth)-1));
+                }
+#endif
+            }
+        }
+    }
+
+    GUInt32 nMaxValue = (1 << nBitDepth) - 1;
+
+    double* padfTempBuffer = NULL;
+    GDALDataType eBufDataTypeOri = eBufDataType;
+    void* pDataBufOri = pDataBuf;
+    // CFloat64 is the query type used by gdallocationinfo...
+#ifdef LIMIT_TYPES
+    if( eBufDataType != GDT_Byte && eBufDataType != GDT_UInt16 )
+#else
+    if( eBufDataType == GDT_CFloat64 )
+#endif
+    {
+        padfTempBuffer = (double*)VSI_MALLOC3_VERBOSE(nXSize, nYSize,
+                    psOptions->nOutPansharpenedBands * sizeof(double));
+        if( padfTempBuffer == NULL )
+        {
+            VSIFree(pUpsampledSpectralBuffer);
+            VSIFree(pPanBuffer);
+            return CE_Failure;
+        }
+        pDataBuf = padfTempBuffer;
+        eBufDataType = GDT_Float64;
+    }
+
+    if( nTasks > 1 )
+    {
+        std::vector<GDALPansharpenJob> asJobs;
+        asJobs.resize( nTasks );
+        GDALPansharpenJob* pasJobs = &(asJobs[0]);
+        {
+            std::vector<void*> ahJobData;
+            ahJobData.resize( nTasks );
+#ifdef DEBUG_TIMING
+            struct timeval tv;
+#endif
+            for( int i=0;i<nTasks;i++)
+            {
+                size_t iStartLine = ((size_t)i * nYSize) / nTasks;
+                size_t iNextStartLine = ((size_t)(i+1) * nYSize) / nTasks;
+                pasJobs[i].poPansharpenOperation = this;
+                pasJobs[i].eWorkDataType = eWorkDataType;
+                pasJobs[i].eBufDataType = eBufDataType;
+                pasJobs[i].pPanBuffer = pPanBuffer + iStartLine *  nXSize * nDataTypeSize;
+                pasJobs[i].pUpsampledSpectralBuffer = pUpsampledSpectralBuffer + iStartLine * nXSize * nDataTypeSize;
+                pasJobs[i].pDataBuf =
+                    static_cast<GByte*>(pDataBuf) +
+                    iStartLine * nXSize *
+                    GDALGetDataTypeSizeBytes(eBufDataType);
+                pasJobs[i].nValues = (int)(iNextStartLine - iStartLine) * nXSize;
+                pasJobs[i].nBandValues = nXSize * nYSize;
+                pasJobs[i].nMaxValue = nMaxValue;
+#ifdef DEBUG_TIMING
+                pasJobs[i].ptv = &tv;
+#endif
+                ahJobData[i] = &(pasJobs[i]);
+            }
+#ifdef DEBUG_TIMING
+            gettimeofday(&tv, NULL);
+#endif
+            poThreadPool->SubmitJobs(PansharpenJobThreadFunc, ahJobData);
+            poThreadPool->WaitCompletion();
+        }
+
+        eErr = CE_None;
+        for( int i=0;i<nTasks;i++)
+        {
+            if( pasJobs[i].eErr != CE_None )
+                eErr = CE_Failure;
+        }
+    }
+    else
+    {
+        eErr = PansharpenChunk( eWorkDataType, eBufDataType,
+                                pPanBuffer,
+                                pUpsampledSpectralBuffer,
+                                pDataBuf,
+                                nXSize * nYSize,
+                                nXSize * nYSize,
+                                nMaxValue);
+    }
+
+    if( padfTempBuffer )
+    {
+        GDALCopyWords(padfTempBuffer, GDT_Float64, sizeof(double),
+                      pDataBufOri, eBufDataTypeOri,
+                      GDALGetDataTypeSizeBytes(eBufDataTypeOri),
+                      nXSize*nYSize*psOptions->nOutPansharpenedBands);
+        VSIFree(padfTempBuffer);
+    }
+
+    VSIFree(pUpsampledSpectralBuffer);
+    VSIFree(pPanBuffer);
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                   PansharpenResampleJobThreadFunc()                  */
+/************************************************************************/
+
+//static int acc=0;
+
+void GDALPansharpenOperation::PansharpenResampleJobThreadFunc(void* pUserData)
+{
+    GDALPansharpenResampleJob* psJob = (GDALPansharpenResampleJob*) pUserData;
+
+#ifdef DEBUG_TIMING
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+    GIntBig launch_time = (GIntBig)psJob->ptv->tv_sec * 1000000 + (GIntBig)psJob->ptv->tv_usec;
+    GIntBig start_job = (GIntBig)tv.tv_sec * 1000000 + (GIntBig)tv.tv_usec;
+#endif
+
+#if 0
+    for(int i=0;i<1000000;i++)
+        acc += i * i;
+#else
+    GDALRasterIOExtraArg sExtraArg;
+    INIT_RASTERIO_EXTRA_ARG(sExtraArg);
+    sExtraArg.eResampleAlg = psJob->eResampleAlg;
+    sExtraArg.bFloatingPointWindowValidity = TRUE;
+    sExtraArg.dfXOff = psJob->dfXOff;
+    sExtraArg.dfYOff = psJob->dfYOff;
+    sExtraArg.dfXSize = psJob->dfXSize;
+    sExtraArg.dfYSize = psJob->dfYSize;
+
+    CPL_IGNORE_RET_VAL(psJob->poMEMDS->RasterIO(GF_Read,
+                             psJob->nXOff,
+                             psJob->nYOff,
+                             psJob->nXSize,
+                             psJob->nYSize,
+                             psJob->pBuffer,
+                             psJob->nBufXSize,
+                             psJob->nBufYSize,
+                             psJob->eDT,
+                             psJob->nBandCount,
+                             NULL,
+                             0, 0, psJob->nBandSpace,
+                             &sExtraArg));
+#endif
+
+#ifdef DEBUG_TIMING
+    struct timeval tv_end;
+    gettimeofday(&tv_end, NULL);
+    GIntBig end = (GIntBig)tv_end.tv_sec * 1000000 + (GIntBig)tv_end.tv_usec;
+    if( start_job - launch_time > 500 )
+        printf("Resample: Delay before start=" CPL_FRMT_GIB ", completion time=" CPL_FRMT_GIB "\n",
+               start_job - launch_time, end - start_job);
+#endif
+}
+
+/************************************************************************/
+/*                      PansharpenJobThreadFunc()                       */
+/************************************************************************/
+
+void GDALPansharpenOperation::PansharpenJobThreadFunc(void* pUserData)
+{
+    GDALPansharpenJob* psJob = (GDALPansharpenJob*) pUserData;
+
+#ifdef DEBUG_TIMING
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+    GIntBig launch_time = (GIntBig)psJob->ptv->tv_sec * 1000000 + (GIntBig)psJob->ptv->tv_usec;
+    GIntBig start_job = (GIntBig)tv.tv_sec * 1000000 + (GIntBig)tv.tv_usec;
+#endif
+
+#if 0
+    for(int i=0;i<1000000;i++)
+        acc += i * i;
+    psJob->eErr = CE_None;
+#else
+    psJob->eErr = psJob->poPansharpenOperation->PansharpenChunk(psJob->eWorkDataType,
+                                  psJob->eBufDataType,
+                                  psJob->pPanBuffer,
+                                  psJob->pUpsampledSpectralBuffer,
+                                  psJob->pDataBuf,
+                                  psJob->nValues,
+                                  psJob->nBandValues,
+                                  psJob->nMaxValue);
+#endif
+
+#ifdef DEBUG_TIMING
+    struct timeval tv_end;
+    gettimeofday(&tv_end, NULL);
+    GIntBig end = (GIntBig)tv_end.tv_sec * 1000000 + (GIntBig)tv_end.tv_usec;
+    if( start_job - launch_time > 500 )
+        printf("Pansharpen: Delay before start=" CPL_FRMT_GIB ", completion time=" CPL_FRMT_GIB "\n",
+               start_job - launch_time, end - start_job);
+#endif
+}
+
+/************************************************************************/
+/*                           PansharpenChunk()                          */
+/************************************************************************/
+
+CPLErr GDALPansharpenOperation::PansharpenChunk( GDALDataType eWorkDataType,
+                                                 GDALDataType eBufDataType,
+                                                 const void* pPanBuffer,
+                                                 const void* pUpsampledSpectralBuffer,
+                                                 void* pDataBuf,
+                                                 int nValues,
+                                                 int nBandValues,
+                                                 GUInt32 nMaxValue) const
+{
+    CPLErr eErr;
+
+    switch( eWorkDataType )
+    {
+        case GDT_Byte:
+            eErr = WeightedBrovey ((GByte*)pPanBuffer,
+                                   (GByte*)pUpsampledSpectralBuffer,
+                                   pDataBuf, eBufDataType,
+                                   nValues, nBandValues, (GByte)nMaxValue);
+            break;
+
+        case GDT_UInt16:
+            eErr = WeightedBrovey ((GUInt16*)pPanBuffer,
+                                   (GUInt16*)pUpsampledSpectralBuffer,
+                                   pDataBuf, eBufDataType,
+                                   nValues, nBandValues, (GUInt16)nMaxValue);
+            break;
+
+#ifndef LIMIT_TYPES
+        case GDT_Int16:
+            eErr = WeightedBrovey ((GInt16*)pPanBuffer,
+                                   (GInt16*)pUpsampledSpectralBuffer,
+                                   pDataBuf, eBufDataType,
+                                   nValues, nBandValues);
+            break;
+
+        case GDT_UInt32:
+            eErr = WeightedBrovey ((GUInt32*)pPanBuffer,
+                                   (GUInt32*)pUpsampledSpectralBuffer,
+                                   pDataBuf, eBufDataType,
+                                   nValues, nBandValues, nMaxValue);
+            break;
+
+        case GDT_Int32:
+            eErr = WeightedBrovey ((GInt32*)pPanBuffer,
+                                   (GInt32*)pUpsampledSpectralBuffer,
+                                   pDataBuf, eBufDataType,
+                                   nValues, nBandValues);
+            break;
+
+        case GDT_Float32:
+            eErr = WeightedBrovey ((float*)pPanBuffer,
+                                   (float*)pUpsampledSpectralBuffer,
+                                   pDataBuf, eBufDataType,
+                                   nValues, nBandValues);
+            break;
+#endif
+        case GDT_Float64:
+            eErr = WeightedBrovey ((double*)pPanBuffer,
+                                   (double*)pUpsampledSpectralBuffer,
+                                   pDataBuf, eBufDataType,
+                                   nValues, nBandValues);
+            break;
+
+        default:
+            CPLError( CE_Failure, CPLE_NotSupported,
+                      "eWorkDataType not supported");
+            eErr = CE_Failure;
+            break;
+    }
+
+    return eErr;
+}
+
+
+/************************************************************************/
+/*                             GetOptions()                             */
+/************************************************************************/
+
+GDALPansharpenOptions* GDALPansharpenOperation::GetOptions()
+{
+    return psOptions;
+}
+
+/************************************************************************/
+/*                     GDALCreatePansharpenOperation()                  */
+/************************************************************************/
+
+/** Instantiate a pansharpening operation.
+ *
+ * The passed options are validated.
+ *
+ * @param psOptions a pansharpening option structure allocated with
+ * GDALCreatePansharpenOptions(). It is duplicated by this function.
+ * @return a valid pansharpening operation handle, or NULL in case of failure.
+ *
+ * @since GDAL 2.1
+ */
+
+GDALPansharpenOperationH GDALCreatePansharpenOperation(
+                                    const GDALPansharpenOptions* psOptions )
+{
+    GDALPansharpenOperation* psOperation = new GDALPansharpenOperation();
+    if( psOperation->Initialize(psOptions) == CE_None )
+        return (GDALPansharpenOperationH)psOperation;
+    delete psOperation;
+    return NULL;
+}
+
+/************************************************************************/
+/*                     GDALDestroyPansharpenOperation()                 */
+/************************************************************************/
+
+/** Destroy a pansharpening operation.
+ *
+ * @param hOperation a valid pansharpening operation.
+ *
+ * @since GDAL 2.1
+ */
+
+void GDALDestroyPansharpenOperation( GDALPansharpenOperationH hOperation )
+{
+    delete (GDALPansharpenOperation*)hOperation;
+}
+
+/************************************************************************/
+/*                       GDALPansharpenProcessRegion()                  */
+/************************************************************************/
+
+/** Executes a pansharpening operation on a rectangular region of the
+ * resulting dataset.
+ *
+ * The window is expressed with respect to the dimensions of the panchromatic
+ * band.
+ *
+ * Spectral bands are upsampled and merged with the panchromatic band according
+ * to the select algorithm and options.
+ *
+ * @param hOperation a valid pansharpening operation.
+ * @param nXOff pixel offset.
+ * @param nYOff pixel offset.
+ * @param nXSize width of the pansharpened region to compute.
+ * @param nYSize height of the pansharpened region to compute.
+ * @param pDataBuf output buffer. Must be nXSize * nYSize *
+ *                 GDALGetDataTypeSizeBytes(eBufDataType) *
+ *                 psOptions->nOutPansharpenedBands large.
+ *                 It begins with all values of the first output band, followed
+ *                 by values of the second output band, etc...
+ * @param eBufDataType data type of the output buffer
+ *
+ * @return CE_None in case of success, CE_Failure in case of failure.
+ *
+ * @since GDAL 2.1
+ */
+CPLErr GDALPansharpenProcessRegion( GDALPansharpenOperationH hOperation,
+                                    int nXOff, int nYOff,
+                                    int nXSize, int nYSize,
+                                    void *pDataBuf,
+                                    GDALDataType eBufDataType)
+{
+    return ((GDALPansharpenOperation*)hOperation)->ProcessRegion(nXOff, nYOff,
+                                                        nXSize, nYSize,
+                                                        pDataBuf, eBufDataType);
+}
diff --git a/alg/gdalpansharpen.h b/alg/gdalpansharpen.h
new file mode 100644
index 0000000..97f60db
--- /dev/null
+++ b/alg/gdalpansharpen.h
@@ -0,0 +1,270 @@
+/******************************************************************************
+ * $Id: gdalpansharpen.h 33715 2016-03-13 08:52:06Z goatbar $
+ *
+ * Project:  GDAL Pansharpening module
+ * Purpose:  Prototypes, and definitions for pansharpening related work.
+ * Author:   Even Rouault <even.rouault at spatialys.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef GDALPANSHARPEN_H_INCLUDED
+#define GDALPANSHARPEN_H_INCLUDED
+
+#include "gdal.h"
+
+CPL_C_START
+
+/**
+ * \file gdalpansharpen.h
+ *
+ * GDAL pansharpening related entry points and definitions.
+ *
+ * @since GDAL 2.1
+ */
+
+/** Pansharpening algorithms.
+ */
+typedef enum
+{
+    /*! Weighted Brovery. */
+    GDAL_PSH_WEIGHTED_BROVEY
+} GDALPansharpenAlg;
+
+/** Pansharpening options.
+  */
+typedef struct
+{
+    /*! Pan sharpening algorithm/method. Only weighed Brovey for now. */
+    GDALPansharpenAlg    ePansharpenAlg;
+
+    /*! Resampling algorithm to upsample spectral bands to pan band resolution. */
+    GDALRIOResampleAlg   eResampleAlg;
+
+    /*! Bit depth of the spectral bands. Can be let to 0 for default behaviour. */
+    int                  nBitDepth;
+
+    /*! Number of weight coefficients in padfWeights. */
+    int                  nWeightCount;
+
+    /*! Array of nWeightCount weights used by weighted Brovey. */
+    double              *padfWeights;
+
+    /*! Panchromatic band. */
+    GDALRasterBandH      hPanchroBand;
+
+    /*! Number of input spectral bands. */
+    int                  nInputSpectralBands;
+
+    /** Array of nInputSpectralBands input spectral bands. The spectral band have
+     *  generally a coarser resolution than the panchromatic band, but they
+     *  are assumed to have the same spatial extent (and projection) at that point.
+     *  Necessary spatial adjustments must be done beforehand, for example by wrapping
+     *  inside a VRT dataset.
+     */
+    GDALRasterBandH     *pahInputSpectralBands;
+
+    /*! Number of output pansharpened spectral bands. */
+    int                  nOutPansharpenedBands;
+
+    /*! Array of nOutPansharpendBands values such as panOutPansharpenedBands[k] is a value in the range [0,nInputSpectralBands-1] . */
+    int                 *panOutPansharpenedBands;
+
+    /*! Whether the panchromatic and spectral bands have a noData value. */
+    int                  bHasNoData;
+
+    /** NoData value of the panchromatic and spectral bands (only taken into account if bHasNoData = TRUE).
+        This will also be use has the output nodata value. */
+    double               dfNoData;
+
+    /** Number of threads or -1 to mean ALL_CPUS. By default (0), single threaded mode is enabled
+      * unless the GDAL_NUM_THREADS configuration option is set to an integer or ALL_CPUS. */
+    int                  nThreads;
+
+    double               dfMSShiftX;
+    double               dfMSShiftY;
+
+} GDALPansharpenOptions;
+
+
+GDALPansharpenOptions CPL_DLL * GDALCreatePansharpenOptions(void);
+void CPL_DLL GDALDestroyPansharpenOptions( GDALPansharpenOptions * );
+GDALPansharpenOptions CPL_DLL * GDALClonePansharpenOptions(
+                                        const GDALPansharpenOptions* psOptions);
+
+/*! Pansharpening operation handle. */
+typedef void* GDALPansharpenOperationH;
+
+GDALPansharpenOperationH CPL_DLL GDALCreatePansharpenOperation(const GDALPansharpenOptions* );
+void CPL_DLL GDALDestroyPansharpenOperation( GDALPansharpenOperationH );
+CPLErr CPL_DLL GDALPansharpenProcessRegion( GDALPansharpenOperationH hOperation,
+                                            int nXOff, int nYOff,
+                                            int nXSize, int nYSize,
+                                            void *pDataBuf,
+                                            GDALDataType eBufDataType);
+
+CPL_C_END
+
+#ifdef __cplusplus
+
+#include <vector>
+#include "gdal_priv.h"
+#include "cpl_worker_thread_pool.h"
+
+#ifdef DEBUG_TIMING
+#include <sys/time.h>
+#endif
+
+class GDALPansharpenOperation;
+
+typedef struct
+{
+    GDALPansharpenOperation* poPansharpenOperation;
+    GDALDataType eWorkDataType;
+    GDALDataType eBufDataType;
+    const void* pPanBuffer;
+    const void* pUpsampledSpectralBuffer;
+    void* pDataBuf;
+    int nValues;
+    int nBandValues;
+    GUInt32 nMaxValue;
+
+#ifdef DEBUG_TIMING
+    struct timeval* ptv;
+#endif
+
+    CPLErr eErr;
+} GDALPansharpenJob;
+
+typedef struct
+{
+    GDALDataset* poMEMDS;
+    int          nXOff;
+    int          nYOff;
+    int          nXSize;
+    int          nYSize;
+    double       dfXOff;
+    double       dfYOff;
+    double       dfXSize;
+    double       dfYSize;
+    void        *pBuffer;
+    GDALDataType eDT;
+    int          nBufXSize;
+    int          nBufYSize;
+    int          nBandCount;
+    GDALRIOResampleAlg eResampleAlg;
+    GSpacing     nBandSpace;
+
+#ifdef DEBUG_TIMING
+    struct timeval* ptv;
+#endif
+} GDALPansharpenResampleJob;
+
+/** Pansharpening operation class.
+ */
+class GDALPansharpenOperation
+{
+        GDALPansharpenOptions* psOptions;
+        std::vector<int> anInputBands;
+        std::vector<GDALDataset*> aVDS; // to destroy
+        std::vector<GDALRasterBand*> aMSBands; // original multispectral bands potentially warped into a VRT
+        int bPositiveWeights;
+        CPLWorkerThreadPool* poThreadPool;
+        int nKernelRadius;
+
+        static void PansharpenJobThreadFunc(void* pUserData);
+        static void PansharpenResampleJobThreadFunc(void* pUserData);
+
+        template<class WorkDataType, class OutDataType> void WeightedBroveyWithNoData(
+                                                     const WorkDataType* pPanBuffer,
+                                                     const WorkDataType* pUpsampledSpectralBuffer,
+                                                     OutDataType* pDataBuf,
+                                                     int nValues,
+                                                     int nBandValues,
+                                                     WorkDataType nMaxValue) const;
+        template<class WorkDataType, class OutDataType, int bHasBitDepth> void WeightedBrovey3(
+                                                     const WorkDataType* pPanBuffer,
+                                                     const WorkDataType* pUpsampledSpectralBuffer,
+                                                     OutDataType* pDataBuf,
+                                                     int nValues,
+                                                     int nBandValues,
+                                                     WorkDataType nMaxValue) const;
+        template<class WorkDataType, class OutDataType> void WeightedBrovey(
+                                                     const WorkDataType* pPanBuffer,
+                                                     const WorkDataType* pUpsampledSpectralBuffer,
+                                                     OutDataType* pDataBuf,
+                                                     int nValues,
+                                                     int nBandValues,
+                                                     WorkDataType nMaxValue) const;
+        template<class WorkDataType> CPLErr WeightedBrovey(
+                                                     const WorkDataType* pPanBuffer,
+                                                     const WorkDataType* pUpsampledSpectralBuffer,
+                                                     void *pDataBuf,
+                                                     GDALDataType eBufDataType,
+                                                     int nValues,
+                                                     int nBandValues,
+                                                     WorkDataType nMaxValue) const;
+        template<class WorkDataType> CPLErr WeightedBrovey(
+                                                     const WorkDataType* pPanBuffer,
+                                                     const WorkDataType* pUpsampledSpectralBuffer,
+                                                     void *pDataBuf,
+                                                     GDALDataType eBufDataType,
+                                                     int nValues,
+                                                     int nBandValues) const;
+        void WeightedBroveyPositiveWeights(
+                                                     const GUInt16* pPanBuffer,
+                                                     const GUInt16* pUpsampledSpectralBuffer,
+                                                     GUInt16* pDataBuf,
+                                                     int nValues,
+                                                     int nBandValues,
+                                                     GUInt16 nMaxValue) const;
+
+        template<int NINPUT, int NOUTPUT> int WeightedBroveyPositiveWeightsInternal(
+                                                     const GUInt16* pPanBuffer,
+                                                     const GUInt16* pUpsampledSpectralBuffer,
+                                                     GUInt16* pDataBuf,
+                                                     int nValues,
+                                                     int nBandValues,
+                                                     GUInt16 nMaxValue) const;
+
+        CPLErr PansharpenChunk( GDALDataType eWorkDataType, GDALDataType eBufDataType,
+                                                     const void* pPanBuffer,
+                                                     const void* pUpsampledSpectralBuffer,
+                                                     void* pDataBuf,
+                                                     int nValues,
+                                                     int nBandValues,
+                                                     GUInt32 nMaxValue) const;
+    public:
+                             GDALPansharpenOperation();
+                            ~GDALPansharpenOperation();
+
+        CPLErr               Initialize(const GDALPansharpenOptions* psOptions);
+        CPLErr               ProcessRegion(int nXOff, int nYOff,
+                                           int nXSize, int nYSize,
+                                           void *pDataBuf,
+                                           GDALDataType eBufDataType);
+        GDALPansharpenOptions* GetOptions();
+};
+
+#endif /* __cplusplus */
+
+#endif /* GDALPANSHARPEN_H_INCLUDED */
diff --git a/alg/gdalproximity.cpp b/alg/gdalproximity.cpp
index af13815..1fc490e 100644
--- a/alg/gdalproximity.cpp
+++ b/alg/gdalproximity.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalproximity.cpp 28882 2015-04-09 15:59:38Z rouault $
+ * $Id: gdalproximity.cpp 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Compute each pixel's proximity to a set of target pixels.
@@ -32,10 +32,10 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: gdalproximity.cpp 28882 2015-04-09 15:59:38Z rouault $");
+CPL_CVSID("$Id: gdalproximity.cpp 33715 2016-03-13 08:52:06Z goatbar $");
 
 static CPLErr
-ProcessProximityLine( GInt32 *panSrcScanline, int *panNearX, int *panNearY, 
+ProcessProximityLine( GInt32 *panSrcScanline, int *panNearX, int *panNearY,
                       int bForward, int iLine, int nXSize, double nMaxDist,
                       float *pafProximity, double *pdfSrcNoDataValue,
                       int nTargetValues, int *panTargetValues );
@@ -45,7 +45,8 @@ ProcessProximityLine( GInt32 *panSrcScanline, int *panNearX, int *panNearY,
 /************************************************************************/
 
 /**
-Compute the proximity of all pixels in the image to a set of pixels in the source image.
+Compute the proximity of all pixels in the image to a set of pixels in
+the source image.
 
 This function attempts to compute the proximity of all pixels in
 the image to a set of pixels in the source image.  The following
@@ -56,7 +57,7 @@ that target pixels are set to the value corresponding to a distance
 of zero.
 
 The progress function args may be NULL or a valid progress reporting function
-such as GDALTermProgress/NULL. 
+such as GDALTermProgress/NULL.
 
 Options:
 
@@ -70,14 +71,14 @@ integers.
   DISTUNITS=[PIXEL]/GEO
 
 Indicates whether distances will be computed in pixel units or
-in georeferenced units.  The default is pixel units.  This also 
+in georeferenced units.  The default is pixel units.  This also
 determines the interpretation of MAXDIST.
 
   MAXDIST=n
 
 The maximum distance to search.  Proximity distances greater than
 this value will not be computed.  Instead output pixels will be
-set to a nodata value. 
+set to a nodata value.
 
   NODATA=n
 
@@ -94,15 +95,15 @@ the proximity output.
   FIXED_BUF_VAL=n
 
 If this option is set, all pixels within the MAXDIST threadhold are
-set to this fixed value instead of to a proximity distance.  
+set to this fixed value instead of to a proximity distance.
 */
 
 
-CPLErr CPL_STDCALL 
-GDALComputeProximity( GDALRasterBandH hSrcBand, 
+CPLErr CPL_STDCALL
+GDALComputeProximity( GDALRasterBandH hSrcBand,
                       GDALRasterBandH hProximityBand,
                       char **papszOptions,
-                      GDALProgressFunc pfnProgress, 
+                      GDALProgressFunc pfnProgress,
                       void * pProgressArg )
 
 {
@@ -141,7 +142,8 @@ GDALComputeProximity( GDALRasterBandH hSrcBand,
         else if( !EQUAL(pszOpt,"PIXEL") )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "Unrecognised DISTUNITS value '%s', should be GEO or PIXEL.",
+                      "Unrecognized DISTUNITS value '%s', "
+                      "should be GEO or PIXEL.",
                       pszOpt );
             return CE_Failure;
         }
@@ -166,7 +168,7 @@ GDALComputeProximity( GDALRasterBandH hSrcBand,
     if( nXSize != GDALGetRasterBandXSize( hProximityBand )
         || nYSize != GDALGetRasterBandYSize( hProximityBand ))
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Source and proximity bands are not the same size." );
         return CE_Failure;
     }
@@ -199,7 +201,7 @@ GDALComputeProximity( GDALRasterBandH hSrcBand,
         if( !bSuccess )
             fNoDataValue = 65535.0;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Is there a fixed value we wish to force the buffer area to?     */
 /* -------------------------------------------------------------------- */
@@ -215,17 +217,17 @@ GDALComputeProximity( GDALRasterBandH hSrcBand,
 /* -------------------------------------------------------------------- */
     int *panTargetValues = NULL;
     int  nTargetValues = 0;
-    
+
     pszOpt = CSLFetchNameValue( papszOptions, "VALUES" );
     if( pszOpt != NULL )
     {
         char **papszValuesTokens;
 
         papszValuesTokens = CSLTokenizeStringComplex( pszOpt, ",", FALSE,FALSE);
-        
+
         nTargetValues = CSLCount(papszValuesTokens);
         panTargetValues = (int *) CPLCalloc(sizeof(int),nTargetValues);
-        
+
         for( i = 0; i < nTargetValues; i++ )
             panTargetValues[i] = atoi(papszValuesTokens[i]);
         CSLDestroy( papszValuesTokens );
@@ -255,7 +257,7 @@ GDALComputeProximity( GDALRasterBandH hSrcBand,
     int iLine;
     CPLErr eErr = CE_None;
 
-    if( eProxType == GDT_Byte 
+    if( eProxType == GDT_Byte
         || eProxType == GDT_UInt16
         || eProxType == GDT_UInt32 )
     {
@@ -268,7 +270,7 @@ GDALComputeProximity( GDALRasterBandH hSrcBand,
             goto end;
         }
         CPLString osTmpFile = CPLGenerateTempFilename( "proximity" );
-        hWorkProximityDS = 
+        hWorkProximityDS =
             GDALCreate( hDriver, osTmpFile,
                         nXSize, nYSize, 1, GDT_Float32, NULL );
         if (hWorkProximityDS == NULL)
@@ -283,18 +285,16 @@ GDALComputeProximity( GDALRasterBandH hSrcBand,
 /*      Allocate buffer for two scanlines of distances as floats        */
 /*      (the current and last line).                                    */
 /* -------------------------------------------------------------------- */
-    pafProximity = (float *) VSIMalloc2(sizeof(float), nXSize);
-    panNearX = (int *) VSIMalloc2(sizeof(int), nXSize);
-    panNearY = (int *) VSIMalloc2(sizeof(int), nXSize);
-    panSrcScanline = (GInt32 *) VSIMalloc2(sizeof(GInt32), nXSize);
+    pafProximity = (float *) VSI_MALLOC2_VERBOSE(sizeof(float), nXSize);
+    panNearX = (int *) VSI_MALLOC2_VERBOSE(sizeof(int), nXSize);
+    panNearY = (int *) VSI_MALLOC2_VERBOSE(sizeof(int), nXSize);
+    panSrcScanline = (GInt32 *) VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize);
 
-    if( pafProximity== NULL 
-        || panNearX == NULL 
+    if( pafProximity== NULL
+        || panNearX == NULL
         || panNearY == NULL
         || panSrcScanline == NULL)
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory, 
-                  "Out of memory allocating working buffers.");
         eErr = CE_Failure;
         goto end;
     }
@@ -309,7 +309,7 @@ GDALComputeProximity( GDALRasterBandH hSrcBand,
     for( iLine = 0; eErr == CE_None && iLine < nYSize; iLine++ )
     {
         // Read for target values.
-        eErr = GDALRasterIO( hSrcBand, GF_Read, 0, iLine, nXSize, 1, 
+        eErr = GDALRasterIO( hSrcBand, GF_Read, 0, iLine, nXSize, 1,
                              panSrcScanline, nXSize, 1, GDT_Int32, 0, 0 );
         if( eErr != CE_None )
             break;
@@ -318,24 +318,24 @@ GDALComputeProximity( GDALRasterBandH hSrcBand,
             pafProximity[i] = -1.0;
 
         // Left to right
-        ProcessProximityLine( panSrcScanline, panNearX, panNearY, 
+        ProcessProximityLine( panSrcScanline, panNearX, panNearY,
                               TRUE, iLine, nXSize, dfMaxDist, pafProximity,
                               pdfSrcNoData, nTargetValues, panTargetValues );
 
         // Right to Left
-        ProcessProximityLine( panSrcScanline, panNearX, panNearY, 
+        ProcessProximityLine( panSrcScanline, panNearX, panNearY,
                               FALSE, iLine, nXSize, dfMaxDist, pafProximity,
                               pdfSrcNoData, nTargetValues, panTargetValues );
 
         // Write out results.
-        eErr = 
-            GDALRasterIO( hWorkProximityBand, GF_Write, 0, iLine, nXSize, 1, 
+        eErr =
+            GDALRasterIO( hWorkProximityBand, GF_Write, 0, iLine, nXSize, 1,
                           pafProximity, nXSize, 1, GDT_Float32, 0, 0 );
 
         if( eErr != CE_None )
             break;
 
-        if( !pfnProgress( 0.5 * (iLine+1) / (double) nYSize, 
+        if( !pfnProgress( 0.5 * (iLine+1) / (double) nYSize,
                           "", pProgressArg ) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
@@ -352,8 +352,8 @@ GDALComputeProximity( GDALRasterBandH hSrcBand,
     for( iLine = nYSize-1; eErr == CE_None && iLine >= 0; iLine-- )
     {
         // Read first pass proximity
-        eErr = 
-            GDALRasterIO( hWorkProximityBand, GF_Read, 0, iLine, nXSize, 1, 
+        eErr =
+            GDALRasterIO( hWorkProximityBand, GF_Read, 0, iLine, nXSize, 1,
                           pafProximity, nXSize, 1, GDT_Float32, 0, 0 );
 
         if( eErr != CE_None )
@@ -361,22 +361,22 @@ GDALComputeProximity( GDALRasterBandH hSrcBand,
 
         // Read pixel values.
 
-        eErr = GDALRasterIO( hSrcBand, GF_Read, 0, iLine, nXSize, 1, 
+        eErr = GDALRasterIO( hSrcBand, GF_Read, 0, iLine, nXSize, 1,
                              panSrcScanline, nXSize, 1, GDT_Int32, 0, 0 );
         if( eErr != CE_None )
             break;
 
         // Right to left
-        ProcessProximityLine( panSrcScanline, panNearX, panNearY, 
+        ProcessProximityLine( panSrcScanline, panNearX, panNearY,
                               FALSE, iLine, nXSize, dfMaxDist, pafProximity,
                               pdfSrcNoData, nTargetValues, panTargetValues );
 
         // Left to right
-        ProcessProximityLine( panSrcScanline, panNearX, panNearY, 
+        ProcessProximityLine( panSrcScanline, panNearX, panNearY,
                               TRUE, iLine, nXSize, dfMaxDist, pafProximity,
                               pdfSrcNoData, nTargetValues, panTargetValues );
 
-        // Final post processing of distances. 
+        // Final post processing of distances.
         for( i = 0; i < nXSize; i++ )
         {
             if( pafProximity[i] < 0.0 )
@@ -385,20 +385,20 @@ GDALComputeProximity( GDALRasterBandH hSrcBand,
             {
                 if( bFixedBufVal )
                     pafProximity[i] = (float) dfFixedBufVal;
-                else 
+                else
                     pafProximity[i] = (float)(pafProximity[i] * dfDistMult);
             }
         }
-  
+
         // Write out results.
-        eErr = 
-            GDALRasterIO( hProximityBand, GF_Write, 0, iLine, nXSize, 1, 
+        eErr =
+            GDALRasterIO( hProximityBand, GF_Write, 0, iLine, nXSize, 1,
                           pafProximity, nXSize, 1, GDT_Float32, 0, 0 );
 
         if( eErr != CE_None )
             break;
 
-        if( !pfnProgress( 0.5 + 0.5 * (nYSize-iLine) / (double) nYSize, 
+        if( !pfnProgress( 0.5 + 0.5 * (nYSize-iLine) / (double) nYSize,
                           "", pProgressArg ) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
@@ -429,9 +429,9 @@ end:
 /************************************************************************/
 /*                        ProcessProximityLine()                        */
 /************************************************************************/
-                      
+
 static CPLErr
-ProcessProximityLine( GInt32 *panSrcScanline, int *panNearX, int *panNearY, 
+ProcessProximityLine( GInt32 *panSrcScanline, int *panNearX, int *panNearY,
                       int bForward, int iLine, int nXSize, double dfMaxDist,
                       float *pafProximity, double *pdfSrcNoDataValue,
                       int nTargetValues, int *panTargetValues )
@@ -442,13 +442,13 @@ ProcessProximityLine( GInt32 *panSrcScanline, int *panNearX, int *panNearY,
     if( bForward )
     {
         iStart = 0;
-        iEnd = nXSize; 
+        iEnd = nXSize;
         iStep = 1;
     }
     else
     {
         iStart = nXSize-1;
-        iEnd = -1; 
+        iEnd = -1;
         iStep = -1;
     }
 
@@ -547,11 +547,11 @@ ProcessProximityLine( GInt32 *panSrcScanline, int *panNearX, int *panNearY,
 /* -------------------------------------------------------------------- */
 /*      Update our proximity value.                                     */
 /* -------------------------------------------------------------------- */
-        if( panNearX[iPixel] != -1 
+        if( panNearX[iPixel] != -1
             && (pdfSrcNoDataValue == NULL
                 || panSrcScanline[iPixel] != *pdfSrcNoDataValue)
             && fNearDistSq <= dfMaxDist * dfMaxDist
-            && (pafProximity[iPixel] < 0 
+            && (pafProximity[iPixel] < 0
                 || fNearDistSq < pafProximity[iPixel] * pafProximity[iPixel]) )
             pafProximity[iPixel] = sqrt(fNearDistSq);
     }
diff --git a/alg/gdalrasterfpolygonenumerator.cpp b/alg/gdalrasterfpolygonenumerator.cpp
deleted file mode 100644
index ccbfa1f..0000000
--- a/alg/gdalrasterfpolygonenumerator.cpp
+++ /dev/null
@@ -1,250 +0,0 @@
-/******************************************************************************
- * $Id: gdalrasterfpolygonenumerator.cpp 24379 2012-05-04 01:26:19Z warmerdam $
- *
- * Project:  GDAL
- * Purpose:  Version of Raster Polygon Enumerator using float buffers.
- * Author:   Jorge Arevalo, jorge.arevalo at deimos-space.com. Most of the code
- * taken from GDALRasterFPolygonEnumerator, by Frank Warmerdam, warmerdam at pobox.com
- *
- ******************************************************************************
- * Copyright (c) 2011, Jorge Arevalo
- * Copyright (c) 2008, Frank Warmerdam
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "gdal_alg_priv.h"
-#include "cpl_conv.h"
-#include <vector>
-
-CPL_CVSID("$Id: gdalrasterfpolygonenumerator.cpp 24379 2012-05-04 01:26:19Z warmerdam $");
-
-#ifdef OGR_ENABLED
-/************************************************************************/
-/*                    GDALRasterFPolygonEnumerator()                     */
-/************************************************************************/
-
-GDALRasterFPolygonEnumerator::GDALRasterFPolygonEnumerator(
-    int nConnectedness )
-
-{
-    panPolyIdMap = NULL;
-    pafPolyValue = NULL;
-    nNextPolygonId = 0;
-    nPolyAlloc = 0;
-    this->nConnectedness = nConnectedness;
-    CPLAssert( nConnectedness == 4 || nConnectedness == 8 );
-}
-
-/************************************************************************/
-/*                    ~GDALRasterFPolygonEnumerator()                    */
-/************************************************************************/
-
-GDALRasterFPolygonEnumerator::~GDALRasterFPolygonEnumerator()
-
-{
-    Clear();
-}
-
-/************************************************************************/
-/*                               Clear()                                */
-/************************************************************************/
-
-void GDALRasterFPolygonEnumerator::Clear()
-
-{
-    CPLFree( panPolyIdMap );
-    CPLFree( pafPolyValue );
-    
-    panPolyIdMap = NULL;
-    pafPolyValue = NULL;
-    
-    nNextPolygonId = 0;
-    nPolyAlloc = 0;
-}
-
-/************************************************************************/
-/*                            MergePolygon()                            */
-/*                                                                      */
-/*      Update the polygon map to indicate the merger of two polygons.  */
-/************************************************************************/
-
-void GDALRasterFPolygonEnumerator::MergePolygon( int nSrcId, int nDstId )
-
-{
-    while( panPolyIdMap[nDstId] != nDstId )
-        nDstId = panPolyIdMap[nDstId];
-
-    while( panPolyIdMap[nSrcId] != nSrcId )
-        nSrcId = panPolyIdMap[nSrcId];
-
-    if( nSrcId == nDstId )
-        return;
-
-    panPolyIdMap[nSrcId] = nDstId;
-}
-
-/************************************************************************/
-/*                             NewPolygon()                             */
-/*                                                                      */
-/*      Allocate a new polygon id, and reallocate the polygon maps      */
-/*      if needed.                                                      */
-/************************************************************************/
-
-int GDALRasterFPolygonEnumerator::NewPolygon( float fValue )
-
-{
-    int nPolyId = nNextPolygonId;
-
-    if( nNextPolygonId >= nPolyAlloc )
-    {
-        nPolyAlloc = nPolyAlloc * 2 + 20;
-        panPolyIdMap = (GInt32 *) CPLRealloc(panPolyIdMap,nPolyAlloc*4);
-        pafPolyValue = (float *) CPLRealloc(pafPolyValue,nPolyAlloc*4);
-    }
-
-    nNextPolygonId++;
-
-    panPolyIdMap[nPolyId] = nPolyId;
-    pafPolyValue[nPolyId] = fValue;
-
-    return nPolyId;
-}
-
-/************************************************************************/
-/*                           CompleteMerges()                           */
-/*                                                                      */
-/*      Make a pass through the maps, ensuring every polygon id         */
-/*      points to the final id it should use, not an intermediate       */
-/*      value.                                                          */
-/************************************************************************/
-
-void GDALRasterFPolygonEnumerator::CompleteMerges()
-
-{
-    int iPoly;
-    int nFinalPolyCount = 0;
-
-    for( iPoly = 0; iPoly < nNextPolygonId; iPoly++ )
-    {
-        while( panPolyIdMap[iPoly] 
-               != panPolyIdMap[panPolyIdMap[iPoly]] )
-            panPolyIdMap[iPoly] = panPolyIdMap[panPolyIdMap[iPoly]];
-
-        if( panPolyIdMap[iPoly] == iPoly )
-            nFinalPolyCount++;
-    }
-
-    CPLDebug( "GDALRasterFPolygonEnumerator",
-              "Counted %d polygon fragments forming %d final polygons.", 
-              nNextPolygonId, nFinalPolyCount );
-}
-
-/************************************************************************/
-/*                            ProcessLine()                             */
-/*                                                                      */
-/*      Assign ids to polygons, one line at a time.                     */
-/************************************************************************/
-
-void GDALRasterFPolygonEnumerator::ProcessLine(
-    float *pafLastLineVal, float *pafThisLineVal,
-    GInt32 *panLastLineId,  GInt32 *panThisLineId,
-    int nXSize )
-
-{
-    int i;
-
-/* -------------------------------------------------------------------- */
-/*      Special case for the first line.                                */
-/* -------------------------------------------------------------------- */
-    if( pafLastLineVal == NULL )
-    {
-        for( i=0; i < nXSize; i++ )
-        {
-            if( i == 0 || !GDALFloatEquals(pafThisLineVal[i], pafThisLineVal[i-1]) )
-            {
-                panThisLineId[i] = NewPolygon( pafThisLineVal[i] );
-            }
-            else
-                panThisLineId[i] = panThisLineId[i-1];
-        }        
-        
-        return;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Process each pixel comparing to the previous pixel, and to      */
-/*      the last line.                                                  */
-/* -------------------------------------------------------------------- */
-    for( i = 0; i < nXSize; i++ )
-    {
-        if( i > 0 && GDALFloatEquals(pafThisLineVal[i], pafThisLineVal[i-1]) )
-        {
-            panThisLineId[i] = panThisLineId[i-1];        
-
-            if( GDALFloatEquals(pafLastLineVal[i], pafThisLineVal[i])
-                && (panPolyIdMap[panLastLineId[i]]
-                    != panPolyIdMap[panThisLineId[i]]) )
-            {
-                MergePolygon( panLastLineId[i], panThisLineId[i] );
-            }
-
-            if( nConnectedness == 8 
-                && pafLastLineVal[i-1] == pafThisLineVal[i] 
-                && (panPolyIdMap[panLastLineId[i-1]]
-                    != panPolyIdMap[panThisLineId[i]]) )
-            {
-                MergePolygon( panLastLineId[i-1], panThisLineId[i] );
-            }
-
-            if( nConnectedness == 8 && i < nXSize-1 
-                && pafLastLineVal[i+1] == pafThisLineVal[i] 
-                && (panPolyIdMap[panLastLineId[i+1]]
-                    != panPolyIdMap[panThisLineId[i]]) )
-            {
-                MergePolygon( panLastLineId[i+1], panThisLineId[i] );
-            }
-        }
-        else if( GDALFloatEquals(pafLastLineVal[i], pafThisLineVal[i]) )
-        {
-            panThisLineId[i] = panLastLineId[i];
-        }
-        else if( i > 0 && nConnectedness == 8 
-                 && GDALFloatEquals(pafLastLineVal[i-1], pafThisLineVal[i]) )
-        {
-            panThisLineId[i] = panLastLineId[i-1];
-
-            if( i < nXSize-1 && pafLastLineVal[i+1] == pafThisLineVal[i]
-                && (panPolyIdMap[panLastLineId[i+1]]
-                != panPolyIdMap[panThisLineId[i]]) )
-            {
-                MergePolygon( panLastLineId[i+1], panThisLineId[i] );
-            }
-        }
-        else if( i < nXSize-1 && nConnectedness == 8 
-                 && GDALFloatEquals(pafLastLineVal[i+1], pafThisLineVal[i]) )
-        {
-            panThisLineId[i] = panLastLineId[i+1];
-        }
-        else
-            panThisLineId[i] = 
-                NewPolygon( pafThisLineVal[i] );
-    }
-}
-#endif
diff --git a/alg/gdalrasterize.cpp b/alg/gdalrasterize.cpp
index 58c98cd..2ffae51 100644
--- a/alg/gdalrasterize.cpp
+++ b/alg/gdalrasterize.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalrasterize.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: gdalrasterize.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Vector rasterization.
@@ -37,14 +37,12 @@
 #include "ogr_geometry.h"
 #include "ogr_spatialref.h"
 
-#ifdef OGR_ENABLED
 #include "ogrsf_frmts.h"
-#endif
 
 /************************************************************************/
 /*                           gvBurnScanline()                           */
 /************************************************************************/
-
+static
 void gvBurnScanline( void *pCBData, int nY, int nXStart, int nXEnd,
                      double dfVariant )
 
@@ -70,15 +68,15 @@ void gvBurnScanline( void *pCBData, int nY, int nXStart, int nXEnd,
         for( iBand = 0; iBand < psInfo->nBands; iBand++ )
         {
             unsigned char *pabyInsert;
-            unsigned char nBurnValue = (unsigned char) 
+            unsigned char nBurnValue = (unsigned char)
                 ( psInfo->padfBurnValue[iBand] +
                   ( (psInfo->eBurnValueSource == GBV_UserBurnValue)?
                              0 : dfVariant ) );
-            
-            pabyInsert = psInfo->pabyChunkBuf 
+
+            pabyInsert = psInfo->pabyChunkBuf
                 + iBand * psInfo->nXSize * psInfo->nYSize
                 + nY * psInfo->nXSize + nXStart;
-                
+
             if( psInfo->eMergeAlg == GRMA_Add ) {
                 int	nPixels = nXEnd - nXStart + 1;
                 while( nPixels-- > 0 )
@@ -94,11 +92,11 @@ void gvBurnScanline( void *pCBData, int nY, int nXStart, int nXEnd,
         {
             int	nPixels = nXEnd - nXStart + 1;
             double   *padfInsert;
-            double   dfBurnValue = 
+            double   dfBurnValue =
                 ( psInfo->padfBurnValue[iBand] +
                   ( (psInfo->eBurnValueSource == GBV_UserBurnValue)?
                              0 : dfVariant ) );
-            
+
             padfInsert = ((double *) psInfo->pabyChunkBuf)
                 + iBand * psInfo->nXSize * psInfo->nYSize
                 + nY * psInfo->nXSize + nXStart;
@@ -120,7 +118,7 @@ void gvBurnScanline( void *pCBData, int nY, int nXStart, int nXEnd,
 /************************************************************************/
 /*                            gvBurnPoint()                             */
 /************************************************************************/
-
+static
 void gvBurnPoint( void *pCBData, int nY, int nX, double dfVariant )
 
 {
@@ -134,7 +132,7 @@ void gvBurnPoint( void *pCBData, int nY, int nX, double dfVariant )
     {
         for( iBand = 0; iBand < psInfo->nBands; iBand++ )
         {
-            unsigned char *pbyInsert = psInfo->pabyChunkBuf 
+            unsigned char *pbyInsert = psInfo->pabyChunkBuf
                                       + iBand * psInfo->nXSize * psInfo->nYSize
                                       + nY * psInfo->nXSize + nX;
 
@@ -193,7 +191,7 @@ static void GDALCollectRingsFromGeometry(
     if ( eFlatType == wkbPoint )
     {
         OGRPoint    *poPoint = (OGRPoint *) poShape;
-        int nNewCount = aPointX.size() + 1;
+        size_t nNewCount = aPointX.size() + 1;
 
         aPointX.reserve( nNewCount );
         aPointY.reserve( nNewCount );
@@ -218,7 +216,7 @@ static void GDALCollectRingsFromGeometry(
     {
         OGRLineString   *poLine = (OGRLineString *) poShape;
         int nCount = poLine->getNumPoints();
-        int nNewCount = aPointX.size() + nCount;
+        size_t nNewCount = aPointX.size() + static_cast<size_t>(nCount);
 
         aPointX.reserve( nNewCount );
         aPointY.reserve( nNewCount );
@@ -246,7 +244,7 @@ static void GDALCollectRingsFromGeometry(
     {
         OGRLinearRing *poRing = (OGRLinearRing *) poShape;
         int nCount = poRing->getNumPoints();
-        int nNewCount = aPointX.size() + nCount;
+        size_t nNewCount = aPointX.size() + static_cast<size_t>(nCount);
 
         aPointX.reserve( nNewCount );
         aPointY.reserve( nNewCount );
@@ -273,17 +271,17 @@ static void GDALCollectRingsFromGeometry(
     else if( eFlatType == wkbPolygon )
     {
         OGRPolygon *poPolygon = (OGRPolygon *) poShape;
-        
-        GDALCollectRingsFromGeometry( poPolygon->getExteriorRing(), 
-                                      aPointX, aPointY, aPointVariant, 
+
+        GDALCollectRingsFromGeometry( poPolygon->getExteriorRing(),
+                                      aPointX, aPointY, aPointVariant,
                                       aPartSize, eBurnValueSrc );
 
         for( i = 0; i < poPolygon->getNumInteriorRings(); i++ )
-            GDALCollectRingsFromGeometry( poPolygon->getInteriorRing(i), 
-                                          aPointX, aPointY, aPointVariant, 
+            GDALCollectRingsFromGeometry( poPolygon->getInteriorRing(i),
+                                          aPointX, aPointY, aPointVariant,
                                           aPartSize, eBurnValueSrc );
     }
-    
+
     else if( eFlatType == wkbMultiPoint
              || eFlatType == wkbMultiLineString
              || eFlatType == wkbMultiPolygon
@@ -293,7 +291,7 @@ static void GDALCollectRingsFromGeometry(
 
         for( i = 0; i < poGC->getNumGeometries(); i++ )
             GDALCollectRingsFromGeometry( poGC->getGeometryRef(i),
-                                          aPointX, aPointY, aPointVariant, 
+                                          aPointX, aPointY, aPointVariant,
                                           aPartSize, eBurnValueSrc );
     }
     else
@@ -305,14 +303,14 @@ static void GDALCollectRingsFromGeometry(
 /************************************************************************/
 /*                       gv_rasterize_one_shape()                       */
 /************************************************************************/
-static void 
+static void
 gv_rasterize_one_shape( unsigned char *pabyChunkBuf, int nYOff,
                         int nXSize, int nYSize,
                         int nBands, GDALDataType eType, int bAllTouched,
-                        OGRGeometry *poShape, double *padfBurnValue, 
+                        OGRGeometry *poShape, double *padfBurnValue,
                         GDALBurnValueSrc eBurnValueSrc,
                         GDALRasterMergeAlg eMergeAlg,
-                        GDALTransformerFunc pfnTransformer, 
+                        GDALTransformerFunc pfnTransformer,
                         void *pTransformArg )
 
 {
@@ -350,7 +348,7 @@ gv_rasterize_one_shape( unsigned char *pabyChunkBuf, int nYOff,
         int *panSuccess = (int *) CPLCalloc(sizeof(int),aPointX.size());
 
         // TODO: we need to add all appropriate error checking at some point.
-        pfnTransformer( pTransformArg, FALSE, aPointX.size(), 
+        pfnTransformer( pTransformArg, FALSE, static_cast<int>(aPointX.size()),
                         &(aPointX[0]), &(aPointY[0]), NULL, panSuccess );
         CPLFree( panSuccess );
     }
@@ -379,9 +377,9 @@ gv_rasterize_one_shape( unsigned char *pabyChunkBuf, int nYOff,
     {
       case wkbPoint:
       case wkbMultiPoint:
-        GDALdllImagePoint( sInfo.nXSize, nYSize, 
-                           aPartSize.size(), &(aPartSize[0]), 
-                           &(aPointX[0]), &(aPointY[0]), 
+        GDALdllImagePoint( sInfo.nXSize, nYSize,
+                           static_cast<int>(aPartSize.size()), &(aPartSize[0]),
+                           &(aPointX[0]), &(aPointY[0]),
                            (eBurnValueSrc == GBV_UserBurnValue)?
                            NULL : &(aPointVariant[0]),
                            gvBurnPoint, &sInfo );
@@ -390,16 +388,16 @@ gv_rasterize_one_shape( unsigned char *pabyChunkBuf, int nYOff,
       case wkbMultiLineString:
       {
           if( bAllTouched )
-              GDALdllImageLineAllTouched( sInfo.nXSize, nYSize, 
-                                          aPartSize.size(), &(aPartSize[0]), 
-                                          &(aPointX[0]), &(aPointY[0]), 
+              GDALdllImageLineAllTouched( sInfo.nXSize, nYSize,
+                                          static_cast<int>(aPartSize.size()), &(aPartSize[0]),
+                                          &(aPointX[0]), &(aPointY[0]),
                                           (eBurnValueSrc == GBV_UserBurnValue)?
                                           NULL : &(aPointVariant[0]),
                                           gvBurnPoint, &sInfo );
           else
-              GDALdllImageLine( sInfo.nXSize, nYSize, 
-                                aPartSize.size(), &(aPartSize[0]), 
-                                &(aPointX[0]), &(aPointY[0]), 
+              GDALdllImageLine( sInfo.nXSize, nYSize,
+                                static_cast<int>(aPartSize.size()), &(aPartSize[0]),
+                                &(aPointX[0]), &(aPointY[0]),
                                 (eBurnValueSrc == GBV_UserBurnValue)?
                                 NULL : &(aPointVariant[0]),
                                 gvBurnPoint, &sInfo );
@@ -408,9 +406,9 @@ gv_rasterize_one_shape( unsigned char *pabyChunkBuf, int nYOff,
 
       default:
       {
-          GDALdllImageFilledPolygon( sInfo.nXSize, nYSize, 
-                                     aPartSize.size(), &(aPartSize[0]), 
-                                     &(aPointX[0]), &(aPointY[0]), 
+          GDALdllImageFilledPolygon( sInfo.nXSize, nYSize,
+                                     static_cast<int>(aPartSize.size()), &(aPartSize[0]),
+                                     &(aPointX[0]), &(aPointY[0]),
                                      (eBurnValueSrc == GBV_UserBurnValue)?
                                      NULL : &(aPointVariant[0]),
                                      gvBurnScanline, &sInfo );
@@ -422,25 +420,25 @@ gv_rasterize_one_shape( unsigned char *pabyChunkBuf, int nYOff,
                  polygons more appropriately is added. */
               if(eBurnValueSrc == GBV_UserBurnValue)
               {
-                  GDALdllImageLineAllTouched( sInfo.nXSize, nYSize, 
-                                              aPartSize.size(), &(aPartSize[0]), 
-                                              &(aPointX[0]), &(aPointY[0]), 
+                  GDALdllImageLineAllTouched( sInfo.nXSize, nYSize,
+                                              static_cast<int>(aPartSize.size()), &(aPartSize[0]),
+                                              &(aPointX[0]), &(aPointY[0]),
                                               NULL,
                                               gvBurnPoint, &sInfo );
               }
               else
               {
                   unsigned int n;
-                  for ( i = 0, n = 0; i < aPartSize.size(); i++ )
+                  for ( i = 0, n = 0; i < static_cast<unsigned int>(aPartSize.size()); i++ )
                   {
                       int j;
                       for ( j = 0; j < aPartSize[i]; j++ )
                           aPointVariant[n++] = aPointVariant[0];
                   }
 
-                  GDALdllImageLineAllTouched( sInfo.nXSize, nYSize, 
-                                              aPartSize.size(), &(aPartSize[0]), 
-                                              &(aPointX[0]), &(aPointY[0]), 
+                  GDALdllImageLineAllTouched( sInfo.nXSize, nYSize,
+                                              static_cast<int>(aPartSize.size()), &(aPartSize[0]),
+                                              &(aPointX[0]), &(aPointY[0]),
                                               &(aPointVariant[0]),
                                               gvBurnPoint, &sInfo );
               }
@@ -457,10 +455,10 @@ gv_rasterize_one_shape( unsigned char *pabyChunkBuf, int nYOff,
 /*      points.                                                         */
 /************************************************************************/
 
-static CPLErr GDALRasterizeOptions(char **papszOptions, 
+static CPLErr GDALRasterizeOptions(char **papszOptions,
                                    int *pbAllTouched,
-                                   GDALBurnValueSrc *peBurnValueSource, 
-                                   GDALRasterMergeAlg *peMergeAlg) 
+                                   GDALBurnValueSrc *peBurnValueSource,
+                                   GDALRasterMergeAlg *peMergeAlg)
 {
     *pbAllTouched = CSLFetchBoolean( papszOptions, "ALL_TOUCHED", FALSE );
 
@@ -475,7 +473,7 @@ static CPLErr GDALRasterizeOptions(char **papszOptions,
         else
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "Unrecognised value '%s' for BURN_VALUE_FROM.", 
+                      "Unrecognized value '%s' for BURN_VALUE_FROM.",
                       pszOpt );
             return CE_Failure;
         }
@@ -495,12 +493,12 @@ static CPLErr GDALRasterizeOptions(char **papszOptions,
         else
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "Unrecognised value '%s' for MERGE_ALG.", 
+                      "Unrecognized value '%s' for MERGE_ALG.",
                       pszOpt );
             return CE_Failure;
         }
     }
-    
+
     return CE_None;
 }
 
@@ -512,9 +510,9 @@ static CPLErr GDALRasterizeOptions(char **papszOptions,
  * Burn geometries into raster.
  *
  * Rasterize a list of geometric objects into a raster dataset.  The
- * geometries are passed as an array of OGRGeometryH handlers.  
+ * geometries are passed as an array of OGRGeometryH handlers.
  *
- * If the geometries are in the georferenced coordinates of the raster
+ * If the geometries are in the georeferenced coordinates of the raster
  * dataset, then the pfnTransform may be passed in NULL and one will be
  * derived internally from the geotransform of the dataset.  The transform
  * needs to transform the geometry locations into pixel/line coordinates
@@ -523,25 +521,25 @@ static CPLErr GDALRasterizeOptions(char **papszOptions,
  * The output raster may be of any GDAL supported datatype, though currently
  * internally the burning is done either as GDT_Byte or GDT_Float32.  This
  * may be improved in the future.  An explicit list of burn values for
- * each geometry for each band must be passed in. 
+ * each geometry for each band must be passed in.
  *
  * The papszOption list of options currently only supports one option. The
  * "ALL_TOUCHED" option may be enabled by setting it to "TRUE".
  *
  * @param hDS output data, must be opened in update mode.
  * @param nBandCount the number of bands to be updated.
- * @param panBandList the list of bands to be updated. 
+ * @param panBandList the list of bands to be updated.
  * @param nGeomCount the number of geometries being passed in pahGeometries.
- * @param pahGeometries the array of geometries to burn in. 
- * @param pfnTransformer transformation to apply to geometries to put into 
+ * @param pahGeometries the array of geometries to burn in.
+ * @param pfnTransformer transformation to apply to geometries to put into
  * pixel/line coordinates on raster.  If NULL a geotransform based one will
  * be created internally.
  * @param pTransformArg callback data for transformer.
- * @param padfGeomBurnValue the array of values to burn into the raster.  
- * There should be nBandCount values for each geometry. 
+ * @param padfGeomBurnValue the array of values to burn into the raster.
+ * There should be nBandCount values for each geometry.
  * @param papszOptions special options controlling rasterization
  * <dl>
- * <dt>"ALL_TOUCHED":</dt> <dd>May be set to TRUE to set all pixels touched 
+ * <dt>"ALL_TOUCHED":</dt> <dd>May be set to TRUE to set all pixels touched
  * by the line or polygons, not just those whose center is within the polygon
  * or that are selected by brezenhams line algorithm.  Defaults to FALSE.</dd>
  * <dt>"BURN_VALUE_FROM":</dt> <dd>May be set to "Z" to use the Z values of the
@@ -557,14 +555,14 @@ static CPLErr GDALRasterizeOptions(char **papszOptions,
  * @return CE_None on success or CE_Failure on error.
  */
 
-CPLErr GDALRasterizeGeometries( GDALDatasetH hDS, 
+CPLErr GDALRasterizeGeometries( GDALDatasetH hDS,
                                 int nBandCount, int *panBandList,
                                 int nGeomCount, OGRGeometryH *pahGeometries,
-                                GDALTransformerFunc pfnTransformer, 
-                                void *pTransformArg, 
+                                GDALTransformerFunc pfnTransformer,
+                                void *pTransformArg,
                                 double *padfGeomBurnValue,
                                 char **papszOptions,
-                                GDALProgressFunc pfnProgress, 
+                                GDALProgressFunc pfnProgress,
                                 void *pProgressArg )
 
 {
@@ -597,7 +595,7 @@ CPLErr GDALRasterizeGeometries( GDALDatasetH hDS,
     int bAllTouched;
     GDALBurnValueSrc eBurnValueSource;
     GDALRasterMergeAlg eMergeAlg;
-    if( GDALRasterizeOptions(papszOptions, &bAllTouched, 
+    if( GDALRasterizeOptions(papszOptions, &bAllTouched,
                              &eBurnValueSource, &eMergeAlg) == CE_Failure) {
         return CE_Failure;
     }
@@ -616,8 +614,8 @@ CPLErr GDALRasterizeGeometries( GDALDatasetH hDS,
     {
         bNeedToFreeTransformer = TRUE;
 
-        pTransformArg = 
-            GDALCreateGenImgProjTransformer( NULL, NULL, hDS, NULL, 
+        pTransformArg =
+            GDALCreateGenImgProjTransformer( NULL, NULL, hDS, NULL,
                                              FALSE, 0.0, 0);
         pfnTransformer = GDALGenImgProjTransform;
     }
@@ -633,10 +631,10 @@ CPLErr GDALRasterizeGeometries( GDALDatasetH hDS,
         eType = GDT_Float64;
 
     nScanlineBytes = nBandCount * poDS->GetRasterXSize()
-        * (GDALGetDataTypeSize(eType)/8);
+        * GDALGetDataTypeSizeBytes(eType);
 
     const char  *pszYChunkSize = CSLFetchNameValue(papszOptions, "CHUNKYSIZE");
-    if( pszYChunkSize == NULL || ((nYChunkSize = atoi(pszYChunkSize))) == 0) 
+    if( pszYChunkSize == NULL || ((nYChunkSize = atoi(pszYChunkSize))) == 0)
     {
         nYChunkSize = 10000000 / nScanlineBytes;
     }
@@ -648,11 +646,9 @@ CPLErr GDALRasterizeGeometries( GDALDatasetH hDS,
               (poDS->GetRasterYSize()+nYChunkSize-1) / nYChunkSize,
               nYChunkSize );
 
-    pabyChunkBuf = (unsigned char *) VSIMalloc(nYChunkSize * nScanlineBytes);
+    pabyChunkBuf = (unsigned char *) VSI_MALLOC2_VERBOSE(nYChunkSize, nScanlineBytes);
     if( pabyChunkBuf == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory, 
-                  "Unable to allocate rasterization buffer." );
         return CE_Failure;
     }
 
@@ -663,8 +659,8 @@ CPLErr GDALRasterizeGeometries( GDALDatasetH hDS,
 
     pfnProgress( 0.0, NULL, pProgressArg );
 
-    for( iY = 0; 
-         iY < poDS->GetRasterYSize() && eErr == CE_None; 
+    for( iY = 0;
+         iY < poDS->GetRasterYSize() && eErr == CE_None;
          iY += nYChunkSize )
     {
         int	nThisYChunkSize;
@@ -674,9 +670,9 @@ CPLErr GDALRasterizeGeometries( GDALDatasetH hDS,
         if( nThisYChunkSize + iY > poDS->GetRasterYSize() )
             nThisYChunkSize = poDS->GetRasterYSize() - iY;
 
-        eErr = 
-            poDS->RasterIO(GF_Read, 
-                           0, iY, poDS->GetRasterXSize(), nThisYChunkSize, 
+        eErr =
+            poDS->RasterIO(GF_Read,
+                           0, iY, poDS->GetRasterXSize(), nThisYChunkSize,
                            pabyChunkBuf,poDS->GetRasterXSize(),nThisYChunkSize,
                            eType, nBandCount, panBandList,
                            0, 0, 0, NULL );
@@ -694,11 +690,11 @@ CPLErr GDALRasterizeGeometries( GDALDatasetH hDS,
                                     pfnTransformer, pTransformArg );
         }
 
-        eErr = 
+        eErr =
             poDS->RasterIO( GF_Write, 0, iY,
-                            poDS->GetRasterXSize(), nThisYChunkSize, 
+                            poDS->GetRasterXSize(), nThisYChunkSize,
                             pabyChunkBuf,
-                            poDS->GetRasterXSize(), nThisYChunkSize, 
+                            poDS->GetRasterXSize(), nThisYChunkSize,
                             eType, nBandCount, panBandList, 0, 0, 0, NULL);
 
         if( !pfnProgress((iY+nThisYChunkSize)/((double)poDS->GetRasterYSize()),
@@ -708,12 +704,12 @@ CPLErr GDALRasterizeGeometries( GDALDatasetH hDS,
             eErr = CE_Failure;
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      cleanup                                                         */
 /* -------------------------------------------------------------------- */
     VSIFree( pabyChunkBuf );
-    
+
     if( bNeedToFreeTransformer )
         GDALDestroyTransformer( pTransformArg );
 
@@ -730,7 +726,7 @@ CPLErr GDALRasterizeGeometries( GDALDatasetH hDS,
  * Rasterize all the geometric objects from a list of layers into a raster
  * dataset.  The layers are passed as an array of OGRLayerH handlers.
  *
- * If the geometries are in the georferenced coordinates of the raster
+ * If the geometries are in the georeferenced coordinates of the raster
  * dataset, then the pfnTransform may be passed in NULL and one will be
  * derived internally from the geotransform of the dataset.  The transform
  * needs to transform the geometry locations into pixel/line coordinates
@@ -739,19 +735,19 @@ CPLErr GDALRasterizeGeometries( GDALDatasetH hDS,
  * The output raster may be of any GDAL supported datatype, though currently
  * internally the burning is done either as GDT_Byte or GDT_Float32.  This
  * may be improved in the future.  An explicit list of burn values for
- * each layer for each band must be passed in. 
+ * each layer for each band must be passed in.
  *
  * @param hDS output data, must be opened in update mode.
  * @param nBandCount the number of bands to be updated.
- * @param panBandList the list of bands to be updated. 
+ * @param panBandList the list of bands to be updated.
  * @param nLayerCount the number of layers being passed in pahLayers array.
- * @param pahLayers the array of layers to burn in. 
- * @param pfnTransformer transformation to apply to geometries to put into 
+ * @param pahLayers the array of layers to burn in.
+ * @param pfnTransformer transformation to apply to geometries to put into
  * pixel/line coordinates on raster.  If NULL a geotransform based one will
  * be created internally.
  * @param pTransformArg callback data for transformer.
- * @param padfLayerBurnValues the array of values to burn into the raster.  
- * There should be nBandCount values for each layer. 
+ * @param padfLayerBurnValues the array of values to burn into the raster.
+ * There should be nBandCount values for each layer.
  * @param papszOptions special options controlling rasterization:
  * <dl>
  * <dt>"ATTRIBUTE":</dt> <dd>Identifies an attribute field on the features to be
@@ -764,7 +760,7 @@ CPLErr GDALRasterizeGeometries( GDALDatasetH hDS,
  * used. Default size will be estimated based on the GDAL cache buffer size
  * using formula: cache_size_bytes/scanline_size_bytes, so the chunk will
  * not exceed the cache.</dd>
- * <dt>"ALL_TOUCHED":</dt> <dd>May be set to TRUE to set all pixels touched 
+ * <dt>"ALL_TOUCHED":</dt> <dd>May be set to TRUE to set all pixels touched
  * by the line or polygons, not just those whose center is within the polygon
  * or that are selected by brezenhams line algorithm.  Defaults to FALSE.</dd>
  * <dt>"BURN_VALUE_FROM":</dt> <dd>May be set to "Z" to use the Z values of the
@@ -784,18 +780,14 @@ CPLErr GDALRasterizeGeometries( GDALDatasetH hDS,
 CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
                             int nBandCount, int *panBandList,
                             int nLayerCount, OGRLayerH *pahLayers,
-                            GDALTransformerFunc pfnTransformer, 
-                            void *pTransformArg, 
+                            GDALTransformerFunc pfnTransformer,
+                            void *pTransformArg,
                             double *padfLayerBurnValues,
                             char **papszOptions,
-                            GDALProgressFunc pfnProgress, 
+                            GDALProgressFunc pfnProgress,
                             void *pProgressArg )
 
 {
-#ifndef OGR_ENABLED
-    CPLError(CE_Failure, CPLE_NotSupported, "GDALRasterizeLayers() unimplemented in a non OGR build");
-    return CE_Failure;
-#else
     GDALDataType   eType;
     unsigned char *pabyChunkBuf;
     GDALDataset *poDS = (GDALDataset *) hDS;
@@ -820,7 +812,7 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
     int bAllTouched;
     GDALBurnValueSrc eBurnValueSource;
     GDALRasterMergeAlg eMergeAlg;
-    if( GDALRasterizeOptions(papszOptions, &bAllTouched, 
+    if( GDALRasterizeOptions(papszOptions, &bAllTouched,
                              &eBurnValueSource, &eMergeAlg) == CE_Failure) {
         return CE_Failure;
     }
@@ -840,7 +832,7 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
         eType = GDT_Float64;
 
     nScanlineBytes = nBandCount * poDS->GetRasterXSize()
-        * (GDALGetDataTypeSize(eType)/8);
+        * GDALGetDataTypeSizeBytes(eType);
 
     if ( pszYChunkSize && ((nYChunkSize = atoi(pszYChunkSize))) != 0 )
         ;
@@ -861,11 +853,9 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
     CPLDebug( "GDAL", "Rasterizer operating on %d swaths of %d scanlines.",
               (poDS->GetRasterYSize()+nYChunkSize-1) / nYChunkSize,
               nYChunkSize );
-    pabyChunkBuf = (unsigned char *) VSIMalloc(nYChunkSize * nScanlineBytes);
+    pabyChunkBuf = (unsigned char *) VSI_MALLOC2_VERBOSE(nYChunkSize, nScanlineBytes);
     if( pabyChunkBuf == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory, 
-                  "Unable to allocate rasterization buffer." );
         return CE_Failure;
     }
 
@@ -881,15 +871,13 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
                              eType, nBandCount, panBandList, 0, 0, 0, NULL )
              != CE_None )
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory, 
-                      "Unable to read buffer." );
             CPLFree( pabyChunkBuf );
             return CE_Failure;
         }
     }
 
 /* ==================================================================== */
-/*      Read the specified layers transfoming and rasterizing           */
+/*      Read the specified layers transforming and rasterizing          */
 /*      geometries.                                                     */
 /* ==================================================================== */
     CPLErr      eErr = CE_None;
@@ -907,7 +895,7 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
 
         if ( !poLayer )
         {
-            CPLError( CE_Warning, CPLE_AppDefined, 
+            CPLError( CE_Warning, CPLE_AppDefined,
                       "Layer element number %d is NULL, skipping.\n", iLayer );
             continue;
         }
@@ -926,9 +914,9 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
                 poLayer->GetLayerDefn()->GetFieldIndex( pszBurnAttribute );
             if ( iBurnField == -1 )
             {
-                CPLError( CE_Warning, CPLE_AppDefined, 
+                CPLError( CE_Warning, CPLE_AppDefined,
                           "Failed to find field %s on layer %s, skipping.\n",
-                          pszBurnAttribute, 
+                          pszBurnAttribute,
                           poLayer->GetLayerDefn()->GetName() );
                 continue;
             }
@@ -951,7 +939,7 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
             OGRSpatialReference *poSRS = poLayer->GetSpatialRef();
             if ( !poSRS )
             {
-                CPLError( CE_Warning, CPLE_AppDefined, 
+                CPLError( CE_Warning, CPLE_AppDefined,
                           "Failed to fetch spatial reference on layer %s "
                           "to build transformer, assuming matching coordinate systems.\n",
                           poLayer->GetLayerDefn()->GetName() );
@@ -959,7 +947,7 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
             else
                 poSRS->exportToWkt( &pszProjection );
 
-            pTransformArg = 
+            pTransformArg =
                 GDALCreateGenImgProjTransformer( NULL, pszProjection,
                                                  hDS, NULL, FALSE, 0.0, 0 );
             pfnTransformer = GDALGenImgProjTransform;
@@ -974,9 +962,14 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
 /* -------------------------------------------------------------------- */
 /*      Loop over image in designated chunks.                           */
 /* -------------------------------------------------------------------- */
+
+        double *padfAttrValues = (double *) VSI_MALLOC_VERBOSE(sizeof(double) * nBandCount);
+        if( padfAttrValues == NULL )
+            eErr = CE_Failure;
+
         int     iY;
-        for( iY = 0; 
-             iY < poDS->GetRasterYSize() && eErr == CE_None; 
+        for( iY = 0;
+             iY < poDS->GetRasterYSize() && eErr == CE_None;
              iY += nYChunkSize )
         {
             int	nThisYChunkSize;
@@ -988,9 +981,9 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
             // Only re-read image if not a single chunk is being rendered
             if ( nYChunkSize < poDS->GetRasterYSize() )
             {
-                eErr = 
+                eErr =
                     poDS->RasterIO( GF_Read, 0, iY,
-                                    poDS->GetRasterXSize(), nThisYChunkSize, 
+                                    poDS->GetRasterXSize(), nThisYChunkSize,
                                     pabyChunkBuf,
                                     poDS->GetRasterXSize(), nThisYChunkSize,
                                     eType, nBandCount, panBandList, 0, 0, 0, NULL );
@@ -998,7 +991,6 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
                     break;
             }
 
-            double *padfAttrValues = (double *) VSIMalloc(sizeof(double) * nBandCount);
             while( (poFeat = poLayer->GetNextFeature()) != NULL )
             {
                 OGRGeometry *poGeom = poFeat->GetGeometryRef();
@@ -1014,7 +1006,7 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
 
                     padfBurnValues = padfAttrValues;
                 }
-                
+
                 gv_rasterize_one_shape( pabyChunkBuf, iY,
                                         poDS->GetRasterXSize(),
                                         nThisYChunkSize,
@@ -1025,16 +1017,15 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
 
                 delete poFeat;
             }
-            VSIFree( padfAttrValues );
 
             // Only write image if not a single chunk is being rendered
             if ( nYChunkSize < poDS->GetRasterYSize() )
             {
-                eErr = 
+                eErr =
                     poDS->RasterIO( GF_Write, 0, iY,
-                                    poDS->GetRasterXSize(), nThisYChunkSize, 
+                                    poDS->GetRasterXSize(), nThisYChunkSize,
                                     pabyChunkBuf,
-                                    poDS->GetRasterXSize(), nThisYChunkSize, 
+                                    poDS->GetRasterXSize(), nThisYChunkSize,
                                     eType, nBandCount, panBandList, 0, 0, 0, NULL );
             }
 
@@ -1048,6 +1039,8 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
             }
         }
 
+        VSIFree( padfAttrValues );
+
         if ( bNeedToFreeTransformer )
         {
             GDALDestroyTransformer( pTransformArg );
@@ -1055,17 +1048,17 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
             pfnTransformer = NULL;
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Write out the image once for all layers if user requested       */
 /*      to render the whole raster in single chunk.                     */
 /* -------------------------------------------------------------------- */
-    if ( nYChunkSize == poDS->GetRasterYSize() )
+    if ( eErr == CE_None && nYChunkSize == poDS->GetRasterYSize() )
     {
-        poDS->RasterIO( GF_Write, 0, 0,
-                                poDS->GetRasterXSize(), nYChunkSize, 
+        eErr = poDS->RasterIO( GF_Write, 0, 0,
+                                poDS->GetRasterXSize(), nYChunkSize,
                                 pabyChunkBuf,
-                                poDS->GetRasterXSize(), nYChunkSize, 
+                                poDS->GetRasterXSize(), nYChunkSize,
                                 eType, nBandCount, panBandList, 0, 0, 0, NULL );
     }
 
@@ -1073,9 +1066,8 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
 /*      cleanup                                                         */
 /* -------------------------------------------------------------------- */
     VSIFree( pabyChunkBuf );
-    
+
     return eErr;
-#endif /* def OGR_ENABLED */
 }
 
 /************************************************************************/
@@ -1088,7 +1080,7 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
  * Rasterize all the geometric objects from a list of layers into supplied
  * raster buffer.  The layers are passed as an array of OGRLayerH handlers.
  *
- * If the geometries are in the georferenced coordinates of the raster
+ * If the geometries are in the georeferenced coordinates of the raster
  * dataset, then the pfnTransform may be passed in NULL and one will be
  * derived internally from the geotransform of the dataset.  The transform
  * needs to transform the geometry locations into pixel/line coordinates
@@ -1096,13 +1088,13 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
  *
  * The output raster may be of any GDAL supported datatype, though currently
  * internally the burning is done either as GDT_Byte or GDT_Float32.  This
- * may be improved in the future. 
+ * may be improved in the future.
  *
  * @param pData pointer to the output data array.
  *
  * @param nBufXSize width of the output data array in pixels.
  *
- * @param nBufYSize height of the output data array in pixels. 
+ * @param nBufYSize height of the output data array in pixels.
  *
  * @param eBufType data type of the output data array.
  *
@@ -1116,20 +1108,20 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
  *
  * @param nLayerCount the number of layers being passed in pahLayers array.
  *
- * @param pahLayers the array of layers to burn in. 
+ * @param pahLayers the array of layers to burn in.
  *
  * @param pszDstProjection WKT defining the coordinate system of the target
  * raster.
  *
  * @param padfDstGeoTransform geotransformation matrix of the target raster.
  *
- * @param pfnTransformer transformation to apply to geometries to put into 
+ * @param pfnTransformer transformation to apply to geometries to put into
  * pixel/line coordinates on raster.  If NULL a geotransform based one will
  * be created internally.
  *
  * @param pTransformArg callback data for transformer.
  *
- * @param dfBurnValue the value to burn into the raster.  
+ * @param dfBurnValue the value to burn into the raster.
  *
  * @param papszOptions special options controlling rasterization:
  * <dl>
@@ -1137,7 +1129,7 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
  * used for a burn in value. The value will be burned into all output
  * bands. If specified, padfLayerBurnValues will not be used and can be a NULL
  * pointer.</dd>
- * <dt>"ALL_TOUCHED":</dt> <dd>May be set to TRUE to set all pixels touched 
+ * <dt>"ALL_TOUCHED":</dt> <dd>May be set to TRUE to set all pixels touched
  * by the line or polygons, not just those whose center is within the polygon
  * or that are selected by brezenhams line algorithm.  Defaults to FALSE.</dd>
  * </dl>
@@ -1147,7 +1139,9 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
  * is. This is implemented properly only for points and lines for now. Polygons
  * will be burned using the Z value from the first point. The M value may
  * be supported in the future.</dd>
- * <dt>"MERGE_ALG":</dt> <dd>May be REPLACE (the default) or ADD.  REPLACE results in overwriting of value, while ADD adds the new value to the existing raster, suitable for heatmaps for instance.</dd>
+ * <dt>"MERGE_ALG":</dt> <dd>May be REPLACE (the default) or ADD.  REPLACE
+ * results in overwriting of value, while ADD adds the new value to the
+ * existing raster, suitable for heatmaps for instance.</dd>
  * </dl>
  *
  * @param pfnProgress the progress function to report completion.
@@ -1164,26 +1158,38 @@ CPLErr GDALRasterizeLayersBuf( void *pData, int nBufXSize, int nBufYSize,
                                int nLayerCount, OGRLayerH *pahLayers,
                                const char *pszDstProjection,
                                double *padfDstGeoTransform,
-                               GDALTransformerFunc pfnTransformer, 
+                               GDALTransformerFunc pfnTransformer,
                                void *pTransformArg, double dfBurnValue,
                                char **papszOptions,
                                GDALProgressFunc pfnProgress,
                                void *pProgressArg )
 
 {
-#ifndef OGR_ENABLED
-    CPLError(CE_Failure, CPLE_NotSupported, "GDALRasterizeLayersBuf() unimplemented in a non OGR build");
-    return CE_Failure;
-#else
 /* -------------------------------------------------------------------- */
 /*      If pixel and line spaceing are defaulted assign reasonable      */
 /*      value assuming a packed buffer.                                 */
 /* -------------------------------------------------------------------- */
-    if( nPixelSpace == 0 )
-        nPixelSpace = GDALGetDataTypeSize( eBufType ) / 8;
-    
+    if( nPixelSpace != 0 )
+    {
+        nPixelSpace = GDALGetDataTypeSizeBytes( eBufType );
+    }
+    if( nPixelSpace != GDALGetDataTypeSizeBytes( eBufType ) )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                "GDALRasterizeLayersBuf(): unsupported value of nPixelSpace" );
+        return CE_Failure;
+    }
+
     if( nLineSpace == 0 )
+    {
         nLineSpace = nPixelSpace * nBufXSize;
+    }
+    if( nLineSpace != nPixelSpace * nBufXSize )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                "GDALRasterizeLayersBuf(): unsupported value of nLineSpace" );
+        return CE_Failure;
+    }
 
     if( pfnProgress == NULL )
         pfnProgress = GDALDummyProgress;
@@ -1200,13 +1206,13 @@ CPLErr GDALRasterizeLayersBuf( void *pData, int nBufXSize, int nBufYSize,
     int bAllTouched;
     GDALBurnValueSrc eBurnValueSource;
     GDALRasterMergeAlg eMergeAlg;
-    if( GDALRasterizeOptions(papszOptions, &bAllTouched, 
+    if( GDALRasterizeOptions(papszOptions, &bAllTouched,
                              &eBurnValueSource, &eMergeAlg) == CE_Failure) {
         return CE_Failure;
     }
 
 /* ==================================================================== */
-/*      Read thes pecified layers transfoming and rasterizing           */
+/*      Read the specified layers transforming and rasterizing          */
 /*      geometries.                                                     */
 /* ==================================================================== */
     CPLErr      eErr = CE_None;
@@ -1223,7 +1229,7 @@ CPLErr GDALRasterizeLayersBuf( void *pData, int nBufXSize, int nBufYSize,
 
         if ( !poLayer )
         {
-            CPLError( CE_Warning, CPLE_AppDefined, 
+            CPLError( CE_Warning, CPLE_AppDefined,
                       "Layer element number %d is NULL, skipping.\n", iLayer );
             continue;
         }
@@ -1242,9 +1248,9 @@ CPLErr GDALRasterizeLayersBuf( void *pData, int nBufXSize, int nBufYSize,
                 poLayer->GetLayerDefn()->GetFieldIndex( pszBurnAttribute );
             if ( iBurnField == -1 )
             {
-                CPLError( CE_Warning, CPLE_AppDefined, 
+                CPLError( CE_Warning, CPLE_AppDefined,
                           "Failed to find field %s on layer %s, skipping.\n",
-                          pszBurnAttribute, 
+                          pszBurnAttribute,
                           poLayer->GetLayerDefn()->GetName() );
                 continue;
             }
@@ -1265,7 +1271,7 @@ CPLErr GDALRasterizeLayersBuf( void *pData, int nBufXSize, int nBufYSize,
             OGRSpatialReference *poSRS = poLayer->GetSpatialRef();
             if ( !poSRS )
             {
-                CPLError( CE_Warning, CPLE_AppDefined, 
+                CPLError( CE_Warning, CPLE_AppDefined,
                           "Failed to fetch spatial reference on layer %s "
                           "to build transformer, assuming matching coordinate systems.\n",
                           poLayer->GetLayerDefn()->GetName() );
@@ -1292,7 +1298,7 @@ CPLErr GDALRasterizeLayersBuf( void *pData, int nBufXSize, int nBufYSize,
 
             if ( pszBurnAttribute )
                 dfBurnValue = poFeat->GetFieldAsDouble( iBurnField );
-            
+
             gv_rasterize_one_shape( (unsigned char *) pData, 0,
                                     nBufXSize, nBufYSize,
                                     1, eBufType, bAllTouched, poGeom,
@@ -1317,7 +1323,6 @@ CPLErr GDALRasterizeLayersBuf( void *pData, int nBufXSize, int nBufYSize,
             pfnTransformer = NULL;
         }
     }
-    
+
     return eErr;
-#endif /* def OGR_ENABLED */
 }
diff --git a/alg/gdalrasterpolygonenumerator.cpp b/alg/gdalrasterpolygonenumerator.cpp
index d09c8e7..60727fa 100644
--- a/alg/gdalrasterpolygonenumerator.cpp
+++ b/alg/gdalrasterpolygonenumerator.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalrasterpolygonenumerator.cpp 28826 2015-03-30 17:51:14Z rouault $
+ * $Id: gdalrasterpolygonenumerator.cpp 33757 2016-03-20 20:22:33Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Raster Polygon Enumerator
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2008, Frank Warmerdam
+ * Copyright (c) 2015, Even Rouault <even.rouault at spatialys.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,29 +32,31 @@
 #include "cpl_conv.h"
 #include <vector>
 
-CPL_CVSID("$Id: gdalrasterpolygonenumerator.cpp 28826 2015-03-30 17:51:14Z rouault $");
+CPL_CVSID("$Id: gdalrasterpolygonenumerator.cpp 33757 2016-03-20 20:22:33Z goatbar $");
 
 /************************************************************************/
-/*                    GDALRasterPolygonEnumerator()                     */
+/*                    GDALRasterPolygonEnumeratorT()                    */
 /************************************************************************/
 
-GDALRasterPolygonEnumerator::GDALRasterPolygonEnumerator( 
-    int nConnectedness )
+template<class DataType, class EqualityTest>
+GDALRasterPolygonEnumeratorT<DataType,EqualityTest>::GDALRasterPolygonEnumeratorT(
+    int nConnectednessIn )
 
 {
     panPolyIdMap = NULL;
     panPolyValue = NULL;
     nNextPolygonId = 0;
     nPolyAlloc = 0;
-    this->nConnectedness = nConnectedness;
+    nConnectedness = nConnectednessIn;
     CPLAssert( nConnectedness == 4 || nConnectedness == 8 );
 }
 
 /************************************************************************/
-/*                    ~GDALRasterPolygonEnumerator()                    */
+/*                    ~GDALRasterPolygonEnumeratorT()                    */
 /************************************************************************/
 
-GDALRasterPolygonEnumerator::~GDALRasterPolygonEnumerator()
+template<class DataType, class EqualityTest>
+GDALRasterPolygonEnumeratorT<DataType,EqualityTest>::~GDALRasterPolygonEnumeratorT()
 
 {
     Clear();
@@ -63,15 +66,16 @@ GDALRasterPolygonEnumerator::~GDALRasterPolygonEnumerator()
 /*                               Clear()                                */
 /************************************************************************/
 
-void GDALRasterPolygonEnumerator::Clear()
+template<class DataType, class EqualityTest>
+void GDALRasterPolygonEnumeratorT<DataType,EqualityTest>::Clear()
 
 {
     CPLFree( panPolyIdMap );
     CPLFree( panPolyValue );
-    
+
     panPolyIdMap = NULL;
     panPolyValue = NULL;
-    
+
     nNextPolygonId = 0;
     nPolyAlloc = 0;
 }
@@ -82,19 +86,32 @@ void GDALRasterPolygonEnumerator::Clear()
 /*      Update the polygon map to indicate the merger of two polygons.  */
 /************************************************************************/
 
-void GDALRasterPolygonEnumerator::MergePolygon( int nSrcId, int nDstId )
+template<class DataType, class EqualityTest>
+void GDALRasterPolygonEnumeratorT<DataType,EqualityTest>::MergePolygon( int nSrcId, int nDstIdInit )
 
 {
-    while( panPolyIdMap[nDstId] != nDstId )
-        nDstId = panPolyIdMap[nDstId];
+    // Figure out the final dest id
+    int nDstIdFinal = nDstIdInit;
+    while( panPolyIdMap[nDstIdFinal] != nDstIdFinal )
+        nDstIdFinal = panPolyIdMap[nDstIdFinal];
+
+    // Map the whole intermediate chain to it
+    int nDstIdCur = nDstIdInit;
+    while( panPolyIdMap[nDstIdCur] != nDstIdCur )
+    {
+        int nNextDstId = panPolyIdMap[nDstIdCur];
+        panPolyIdMap[nDstIdCur] = nDstIdFinal;
+        nDstIdCur = nNextDstId;
+    }
 
+    // And map the whole source chain to it too (can be done in one pass)
     while( panPolyIdMap[nSrcId] != nSrcId )
-        nSrcId = panPolyIdMap[nSrcId];
-
-    if( nSrcId == nDstId )
-        return;
-
-    panPolyIdMap[nSrcId] = nDstId;
+    {
+        int nNextSrcId = panPolyIdMap[nSrcId];
+        panPolyIdMap[nSrcId] = nDstIdFinal;
+        nSrcId = nNextSrcId;
+    }
+    panPolyIdMap[nSrcId] = nDstIdFinal;
 }
 
 /************************************************************************/
@@ -104,7 +121,8 @@ void GDALRasterPolygonEnumerator::MergePolygon( int nSrcId, int nDstId )
 /*      if needed.                                                      */
 /************************************************************************/
 
-int GDALRasterPolygonEnumerator::NewPolygon( GInt32 nValue )
+template<class DataType, class EqualityTest>
+int GDALRasterPolygonEnumeratorT<DataType,EqualityTest>::NewPolygon( DataType nValue )
 
 {
     int nPolyId = nNextPolygonId;
@@ -112,8 +130,8 @@ int GDALRasterPolygonEnumerator::NewPolygon( GInt32 nValue )
     if( nNextPolygonId >= nPolyAlloc )
     {
         nPolyAlloc = nPolyAlloc * 2 + 20;
-        panPolyIdMap = (GInt32 *) CPLRealloc(panPolyIdMap,nPolyAlloc*4);
-        panPolyValue = (GInt32 *) CPLRealloc(panPolyValue,nPolyAlloc*4);
+        panPolyIdMap = (GInt32 *) CPLRealloc(panPolyIdMap,nPolyAlloc*sizeof(GInt32));
+        panPolyValue = (DataType *) CPLRealloc(panPolyValue,nPolyAlloc*sizeof(DataType));
     }
 
     nNextPolygonId++;
@@ -132,7 +150,8 @@ int GDALRasterPolygonEnumerator::NewPolygon( GInt32 nValue )
 /*      value.                                                          */
 /************************************************************************/
 
-void GDALRasterPolygonEnumerator::CompleteMerges()
+template<class DataType, class EqualityTest>
+void GDALRasterPolygonEnumeratorT<DataType,EqualityTest>::CompleteMerges()
 
 {
     int iPoly;
@@ -140,16 +159,29 @@ void GDALRasterPolygonEnumerator::CompleteMerges()
 
     for( iPoly = 0; iPoly < nNextPolygonId; iPoly++ )
     {
-        while( panPolyIdMap[iPoly] 
-               != panPolyIdMap[panPolyIdMap[iPoly]] )
-            panPolyIdMap[iPoly] = panPolyIdMap[panPolyIdMap[iPoly]];
+        // Figure out the final id
+        int nId = panPolyIdMap[iPoly];
+        while( nId != panPolyIdMap[nId] )
+        {
+            nId = panPolyIdMap[nId];
+        }
+
+        // Then map the whole intermediate chain to it
+        int nIdCur = panPolyIdMap[iPoly];
+        panPolyIdMap[iPoly] = nId;
+        while( nIdCur != panPolyIdMap[nIdCur] )
+        {
+            int nNextId = panPolyIdMap[nIdCur];
+            panPolyIdMap[nIdCur] = nId;
+            nIdCur = nNextId;
+        }
 
         if( panPolyIdMap[iPoly] == iPoly )
             nFinalPolyCount++;
     }
 
-    CPLDebug( "GDALRasterPolygonEnumerator", 
-              "Counted %d polygon fragments forming %d final polygons.", 
+    CPLDebug( "GDALRasterPolygonEnumerator",
+              "Counted %d polygon fragments forming %d final polygons.",
               nNextPolygonId, nFinalPolyCount );
 }
 
@@ -159,13 +191,15 @@ void GDALRasterPolygonEnumerator::CompleteMerges()
 /*      Assign ids to polygons, one line at a time.                     */
 /************************************************************************/
 
-void GDALRasterPolygonEnumerator::ProcessLine( 
-    GInt32 *panLastLineVal, GInt32 *panThisLineVal,
+template<class DataType, class EqualityTest>
+void GDALRasterPolygonEnumeratorT<DataType,EqualityTest>::ProcessLine(
+    DataType *panLastLineVal, DataType *panThisLineVal,
     GInt32 *panLastLineId,  GInt32 *panThisLineId,
     int nXSize )
 
 {
     int i;
+    EqualityTest eq;
 
 /* -------------------------------------------------------------------- */
 /*      Special case for the first line.                                */
@@ -178,7 +212,7 @@ void GDALRasterPolygonEnumerator::ProcessLine(
             {
                 panThisLineId[i] = -1;
             }
-            else if( i == 0 || panThisLineVal[i] != panThisLineVal[i-1] )
+            else if( i == 0 || !(eq.operator()(panThisLineVal[i], panThisLineVal[i-1])) )
             {
                 panThisLineId[i] = NewPolygon( panThisLineVal[i] );
             }
@@ -199,57 +233,60 @@ void GDALRasterPolygonEnumerator::ProcessLine(
         {
             panThisLineId[i] = -1;
         }
-        else if( i > 0 && panThisLineVal[i] == panThisLineVal[i-1] )
+        else if( i > 0 && eq.operator()(panThisLineVal[i], panThisLineVal[i-1]) )
         {
-            panThisLineId[i] = panThisLineId[i-1];        
+            panThisLineId[i] = panThisLineId[i-1];
 
-            if( panLastLineVal[i] == panThisLineVal[i] 
+            if( eq.operator()(panLastLineVal[i], panThisLineVal[i])
                 && (panPolyIdMap[panLastLineId[i]]
                     != panPolyIdMap[panThisLineId[i]]) )
             {
                 MergePolygon( panLastLineId[i], panThisLineId[i] );
             }
 
-            if( nConnectedness == 8 
-                && panLastLineVal[i-1] == panThisLineVal[i] 
+            if( nConnectedness == 8
+                && eq.operator()(panLastLineVal[i-1], panThisLineVal[i])
                 && (panPolyIdMap[panLastLineId[i-1]]
                     != panPolyIdMap[panThisLineId[i]]) )
             {
                 MergePolygon( panLastLineId[i-1], panThisLineId[i] );
             }
 
-            if( nConnectedness == 8 && i < nXSize-1 
-                && panLastLineVal[i+1] == panThisLineVal[i] 
+            if( nConnectedness == 8 && i < nXSize-1
+                && eq.operator()(panLastLineVal[i+1], panThisLineVal[i])
                 && (panPolyIdMap[panLastLineId[i+1]]
                     != panPolyIdMap[panThisLineId[i]]) )
             {
                 MergePolygon( panLastLineId[i+1], panThisLineId[i] );
             }
         }
-        else if( panLastLineVal[i] == panThisLineVal[i] )
+        else if( eq.operator()(panLastLineVal[i], panThisLineVal[i]) )
         {
             panThisLineId[i] = panLastLineId[i];
         }
-        else if( i > 0 && nConnectedness == 8 
-                 && panLastLineVal[i-1] == panThisLineVal[i] )
+        else if( i > 0 && nConnectedness == 8
+                 && eq.operator()(panLastLineVal[i-1], panThisLineVal[i]) )
         {
             panThisLineId[i] = panLastLineId[i-1];
 
-            if( i < nXSize-1 && panLastLineVal[i+1] == panThisLineVal[i]
+            if( i < nXSize-1 && eq.operator()(panLastLineVal[i+1], panThisLineVal[i])
                 && (panPolyIdMap[panLastLineId[i+1]]
                 != panPolyIdMap[panThisLineId[i]]) )
             {
                 MergePolygon( panLastLineId[i+1], panThisLineId[i] );
             }
         }
-        else if( i < nXSize-1 && nConnectedness == 8 
-                 && panLastLineVal[i+1] == panThisLineVal[i] )
+        else if( i < nXSize-1 && nConnectedness == 8
+                 && eq.operator()(panLastLineVal[i+1], panThisLineVal[i]) )
         {
             panThisLineId[i] = panLastLineId[i+1];
         }
         else
-            panThisLineId[i] = 
+            panThisLineId[i] =
                 NewPolygon( panThisLineVal[i] );
     }
 }
 
+template class GDALRasterPolygonEnumeratorT<GInt32, IntEqualityTest>;
+
+template class GDALRasterPolygonEnumeratorT<float, FloatEqualityTest>;
diff --git a/alg/gdalsievefilter.cpp b/alg/gdalsievefilter.cpp
index 9dc9f38..ae1bff1 100644
--- a/alg/gdalsievefilter.cpp
+++ b/alg/gdalsievefilter.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalsievefilter.cpp 30152 2015-09-06 12:29:19Z rouault $
+ * $Id: gdalsievefilter.cpp 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Raster to Polygon Converter
@@ -31,29 +31,29 @@
 #include "gdal_alg_priv.h"
 #include "cpl_conv.h"
 #include <vector>
+#include <set>
 
-CPL_CVSID("$Id: gdalsievefilter.cpp 30152 2015-09-06 12:29:19Z rouault $");
+CPL_CVSID("$Id: gdalsievefilter.cpp 33715 2016-03-13 08:52:06Z goatbar $");
 
 #define MY_MAX_INT 2147483647
 
 /*
  * General Plan
  *
- * 1) make a pass with the polygon enumerator to build up the 
+ * 1) make a pass with the polygon enumerator to build up the
  *    polygon map array.  Also accumulate polygon size information.
  *
  * 2) Identify the polygons that need to be merged.
- * 
- * 3) Make a pass with the polygon enumerator.  For each "to be merged" 
- *    polygon keep track of it's largest neighbour. 
- * 
+ *
+ * 3) Make a pass with the polygon enumerator.  For each "to be merged"
+ *    polygon keep track of its largest neighbour.
+ *
  * 4) Fix up remappings that would go to polygons smaller than the seive
- *    size.  Ensure these in term map to the largest neighbour of the 
- *    "to be seieved" polygons. 
- * 
+ *    size.  Ensure these in term map to the largest neighbour of the
+ *    "to be sieved" polygons.
+ *
  * 5) Make another pass with the polygon enumerator. This time we remap
  *    the actual pixel values of all polygons to be merged.
- * 
  */
 
 /************************************************************************/
@@ -63,14 +63,14 @@ CPL_CVSID("$Id: gdalsievefilter.cpp 30152 2015-09-06 12:29:19Z rouault $");
 /*      band is zero.                                                   */
 /************************************************************************/
 
-static CPLErr 
-GPMaskImageData( GDALRasterBandH hMaskBand, GByte *pabyMaskLine, int iY, int nXSize, 
+static CPLErr
+GPMaskImageData( GDALRasterBandH hMaskBand, GByte *pabyMaskLine, int iY, int nXSize,
                  GInt32 *panImageLine )
 
 {
     CPLErr eErr;
 
-    eErr = GDALRasterIO( hMaskBand, GF_Read, 0, iY, nXSize, 1, 
+    eErr = GDALRasterIO( hMaskBand, GF_Read, 0, iY, nXSize, 1,
                          pabyMaskLine, nXSize, 1, GDT_Byte, 0, 0 );
     if( eErr == CE_None )
     {
@@ -85,6 +85,8 @@ GPMaskImageData( GDALRasterBandH hMaskBand, GByte *pabyMaskLine, int iY, int nXS
     return eErr;
 }
 
+// TODO: What is "eaches" supposed to be?
+
 /************************************************************************/
 /*                          CompareNeighbour()                          */
 /*                                                                      */
@@ -99,19 +101,19 @@ GPMaskImageData( GDALRasterBandH hMaskBand, GByte *pabyMaskLine, int iY, int nXS
 /*      smaller than our sieve threshold.                               */
 /************************************************************************/
 
-static inline void CompareNeighbour( int nPolyId1, int nPolyId2, 
-                                     int *panPolyIdMap, 
-                                     int *panPolyValue,
+static inline void CompareNeighbour( int nPolyId1, int nPolyId2,
+                                     int *panPolyIdMap,
+                                     int * /* panPolyValue */,
                                      std::vector<int> &anPolySizes,
                                      std::vector<int> &anBigNeighbour )
 
 {
     // nodata polygon do not need neighbours, and cannot be neighbours
-    // to valid polygons. 
+    // to valid polygons.
     if( nPolyId1 < 0 || nPolyId2 < 0 )
         return;
 
-    // make sure we are working with the final merged polygon ids. 
+    // make sure we are working with the final merged polygon ids.
     nPolyId1 = panPolyIdMap[nPolyId1];
     nPolyId2 = panPolyIdMap[nPolyId2];
 
@@ -119,8 +121,8 @@ static inline void CompareNeighbour( int nPolyId1, int nPolyId2,
         return;
 
     // nodata polygon do not need neighbours, and cannot be neighbours
-    // to valid polygons. 
-    // should no longer happen with r28826 optim
+    // to valid polygons.
+    // should no longer happen with r28826 optimization
     //if( panPolyValue[nPolyId1] == GP_NODATA_MARKER
     //    || panPolyValue[nPolyId2] == GP_NODATA_MARKER )
     //    return;
@@ -138,43 +140,43 @@ static inline void CompareNeighbour( int nPolyId1, int nPolyId2,
 /*                          GDALSieveFilter()                           */
 /************************************************************************/
 
-/** 
- * Removes small raster polygons. 
+/**
+ * Removes small raster polygons.
  *
  * The function removes raster polygons smaller than a provided
- * threshold size (in pixels) and replaces replaces them with the pixel value 
- * of the largest neighbour polygon.  
+ * threshold size (in pixels) and replaces replaces them with the pixel value
+ * of the largest neighbour polygon.
  *
  * Polygon are determined (per GDALRasterPolygonEnumerator) as regions of
  * the raster where the pixels all have the same value, and that are contiguous
- * (connected).  
+ * (connected).
  *
  * Pixels determined to be "nodata" per hMaskBand will not be treated as part
  * of a polygon regardless of their pixel values.  Nodata areas will never be
- * changed nor affect polygon sizes. 
+ * changed nor affect polygon sizes.
  *
  * Polygons smaller than the threshold with no neighbours that are as large
  * as the threshold will not be altered.  Polygons surrounded by nodata areas
- * will therefore not be altered.  
+ * will therefore not be altered.
  *
  * The algorithm makes three passes over the input file to enumerate the
- * polygons and collect limited information about them.  Memory use is 
+ * polygons and collect limited information about them.  Memory use is
  * proportional to the number of polygons (roughly 24 bytes per polygon), but
  * is not directly related to the size of the raster.  So very large raster
  * files can be processed effectively if there aren't too many polygons.  But
- * extremely noisy rasters with many one pixel polygons will end up being 
+ * extremely noisy rasters with many one pixel polygons will end up being
  * expensive (in memory) to process.
- * 
+ *
  * @param hSrcBand the source raster band to be processed.
- * @param hMaskBand an optional mask band.  All pixels in the mask band with a 
+ * @param hMaskBand an optional mask band.  All pixels in the mask band with a
  * value other than zero will be considered suitable for inclusion in polygons.
  * @param hDstBand the output raster band.  It may be the same as hSrcBand
- * to update the source in place. 
+ * to update the source in place.
  * @param nSizeThreshold raster polygons with sizes smaller than this will
  * be merged into their largest neighbour.
  * @param nConnectedness either 4 indicating that diagonal pixels are not
  * considered directly adjacent for polygon membership purposes or 8
- * indicating they are. 
+ * indicating they are.
  * @param papszOptions algorithm options in name=value list form.  None currently
  * supported.
  * @param pfnProgress callback for reporting algorithm progress matching the
@@ -204,19 +206,17 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
     CPLErr eErr = CE_None;
     int nXSize = GDALGetRasterBandXSize( hSrcBand );
     int nYSize = GDALGetRasterBandYSize( hSrcBand );
-    GInt32 *panLastLineVal = (GInt32 *) VSIMalloc2(sizeof(GInt32), nXSize);
-    GInt32 *panThisLineVal = (GInt32 *) VSIMalloc2(sizeof(GInt32), nXSize);
-    GInt32 *panLastLineId =  (GInt32 *) VSIMalloc2(sizeof(GInt32), nXSize);
-    GInt32 *panThisLineId =  (GInt32 *) VSIMalloc2(sizeof(GInt32), nXSize);
-    GInt32 *panThisLineWriteVal = (GInt32 *) VSIMalloc2(sizeof(GInt32), nXSize);
-    GByte *pabyMaskLine = (hMaskBand != NULL) ? (GByte *) VSIMalloc(nXSize) : NULL;
+    GInt32 *panLastLineVal = (GInt32 *) VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize);
+    GInt32 *panThisLineVal = (GInt32 *) VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize);
+    GInt32 *panLastLineId =  (GInt32 *) VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize);
+    GInt32 *panThisLineId =  (GInt32 *) VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize);
+    GInt32 *panThisLineWriteVal = (GInt32 *) VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize);
+    GByte *pabyMaskLine = (hMaskBand != NULL) ? (GByte *) VSI_MALLOC_VERBOSE(nXSize) : NULL;
     if (panLastLineVal == NULL || panThisLineVal == NULL ||
         panLastLineId == NULL || panThisLineId == NULL ||
         panThisLineWriteVal == NULL ||
         (hMaskBand != NULL && pabyMaskLine == NULL))
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory,
-                 "Could not allocate enough memory for temporary buffers");
         CPLFree( panThisLineId );
         CPLFree( panLastLineId );
         CPLFree( panThisLineVal );
@@ -237,21 +237,21 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
 
     for( iY = 0; eErr == CE_None && iY < nYSize; iY++ )
     {
-        eErr = GDALRasterIO( 
+        eErr = GDALRasterIO(
             hSrcBand,
-            GF_Read, 0, iY, nXSize, 1, 
+            GF_Read, 0, iY, nXSize, 1,
             panThisLineVal, nXSize, 1, GDT_Int32, 0, 0 );
-        
+
         if( eErr == CE_None && hMaskBand != NULL )
             eErr = GPMaskImageData( hMaskBand, pabyMaskLine, iY, nXSize, panThisLineVal );
 
         if( iY == 0 )
-            oFirstEnum.ProcessLine( 
+            oFirstEnum.ProcessLine(
                 NULL, panThisLineVal, NULL, panThisLineId, nXSize );
         else
             oFirstEnum.ProcessLine(
-                panLastLineVal, panThisLineVal, 
-                panLastLineId,  panThisLineId, 
+                panLastLineVal, panThisLineVal,
+                panLastLineId,  panThisLineId,
                 nXSize );
 
 /* -------------------------------------------------------------------- */
@@ -262,7 +262,7 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
 
         for( iX = 0; iX < nXSize; iX++ )
         {
-            iPoly = panThisLineId[iX]; 
+            iPoly = panThisLineId[iX];
 
             if( iPoly >= 0 && anPolySizes[iPoly] < MY_MAX_INT )
                 anPolySizes[iPoly] += 1;
@@ -282,8 +282,8 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
 /* -------------------------------------------------------------------- */
 /*      Report progress, and support interrupts.                        */
 /* -------------------------------------------------------------------- */
-        if( eErr == CE_None 
-            && !pfnProgress( 0.25 * ((iY+1) / (double) nYSize), 
+        if( eErr == CE_None
+            && !pfnProgress( 0.25 * ((iY+1) / (double) nYSize),
                              "", pProgressArg ) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
@@ -299,7 +299,7 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
     oFirstEnum.CompleteMerges();
 
 /* -------------------------------------------------------------------- */
-/*      Push the sizes of merged polygon fragments into the the         */
+/*      Push the sizes of merged polygon fragments into the             */
 /*      merged polygon id's count.                                      */
 /* -------------------------------------------------------------------- */
     for( iPoly = 0; iPoly < oFirstEnum.nNextPolygonId; iPoly++ )
@@ -309,7 +309,7 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
             GIntBig nSize = anPolySizes[oFirstEnum.panPolyIdMap[iPoly]];
 
             nSize += anPolySizes[iPoly];
-            
+
             if( nSize > MY_MAX_INT )
                 nSize = MY_MAX_INT;
 
@@ -319,7 +319,7 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
     }
 
 /* -------------------------------------------------------------------- */
-/*      We will use a new enumerator for the second pass primariliy     */
+/*      We will use a new enumerator for the second pass primarily      */
 /*      so we can preserve the first pass map.                          */
 /* -------------------------------------------------------------------- */
     GDALRasterPolygonEnumerator oSecondEnum( nConnectedness );
@@ -339,7 +339,7 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
 /* -------------------------------------------------------------------- */
 /*      Read the image data.                                            */
 /* -------------------------------------------------------------------- */
-        eErr = GDALRasterIO( hSrcBand, GF_Read, 0, iY, nXSize, 1, 
+        eErr = GDALRasterIO( hSrcBand, GF_Read, 0, iY, nXSize, 1,
                              panThisLineVal, nXSize, 1, GDT_Int32, 0, 0 );
 
         if( eErr == CE_None && hMaskBand != NULL )
@@ -353,12 +353,12 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
 /*      the same thing done in the first pass above).                   */
 /* -------------------------------------------------------------------- */
         if( iY == 0 )
-            oSecondEnum.ProcessLine( 
+            oSecondEnum.ProcessLine(
                 NULL, panThisLineVal, NULL, panThisLineId, nXSize );
         else
             oSecondEnum.ProcessLine(
-                panLastLineVal, panThisLineVal, 
-                panLastLineId,  panThisLineId, 
+                panLastLineVal, panThisLineVal,
+                panLastLineId,  panThisLineId,
                 nXSize );
 
 /* -------------------------------------------------------------------- */
@@ -369,30 +369,29 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
         {
             if( iY > 0 )
             {
-                CompareNeighbour( panThisLineId[iX], 
+                CompareNeighbour( panThisLineId[iX],
                                   panLastLineId[iX],
                                   oFirstEnum.panPolyIdMap,
                                   oFirstEnum.panPolyValue,
                                   anPolySizes, anBigNeighbour );
 
                 if( iX > 0 && nConnectedness == 8 )
-                    CompareNeighbour( panThisLineId[iX], 
+                    CompareNeighbour( panThisLineId[iX],
                                       panLastLineId[iX-1],
                                       oFirstEnum.panPolyIdMap,
                                       oFirstEnum.panPolyValue,
                                       anPolySizes, anBigNeighbour );
-                    
+
                 if( iX < nXSize-1 && nConnectedness == 8 )
-                    CompareNeighbour( panThisLineId[iX], 
+                    CompareNeighbour( panThisLineId[iX],
                                       panLastLineId[iX+1],
                                       oFirstEnum.panPolyIdMap,
                                       oFirstEnum.panPolyValue,
                                       anPolySizes, anBigNeighbour );
-                    
             }
-            
+
             if( iX > 0 )
-                CompareNeighbour( panThisLineId[iX], 
+                CompareNeighbour( panThisLineId[iX],
                                   panThisLineId[iX-1],
                                   oFirstEnum.panPolyIdMap,
                                   oFirstEnum.panPolyValue,
@@ -400,7 +399,7 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
 
             // We don't need to compare to next pixel or next line
             // since they will be compared to us.
-        }                     
+        }
 
 /* -------------------------------------------------------------------- */
 /*      Swap pixel value, and polygon id lines to be ready for the      */
@@ -417,8 +416,8 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
 /* -------------------------------------------------------------------- */
 /*      Report progress, and support interrupts.                        */
 /* -------------------------------------------------------------------- */
-        if( eErr == CE_None 
-            && !pfnProgress( 0.25 + 0.25 * ((iY+1) / (double) nYSize), 
+        if( eErr == CE_None
+            && !pfnProgress( 0.25 + 0.25 * ((iY+1) / (double) nYSize),
                              "", pProgressArg ) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
@@ -440,7 +439,7 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
         if( oFirstEnum.panPolyIdMap[iPoly] != iPoly )
             continue;
 
-        // Ignore nodata polygons. 
+        // Ignore nodata polygons.
         if( oFirstEnum.panPolyValue[iPoly] == GP_NODATA_MARKER )
             continue;
 
@@ -460,28 +459,50 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
             continue;
         }
 
-        // If our biggest neighbour is larger than the threshold
-        // then we are golden. 
-        if( anPolySizes[anBigNeighbour[iPoly]] >= nSizeThreshold )
-            continue;
+        std::set<int> oSetVisitedPoly;
+        oSetVisitedPoly.insert(iPoly);
 
-#ifdef notdef
-        // Will our neighbours biggest neighbour do?  
-        // Eventually we need something sort of recursive here with
-        // loop detection.
-        if( anPolySizes[anBigNeighbour[anBigNeighbour[iPoly]]] 
-            >= nSizeThreshold )
+        // Walk through our neighbours until we find a polygon large enough
+        int iFinalId = iPoly;
+        bool bFoundBigEnoughPoly = false;
+        while(true)
         {
-            anBigNeighbour[iPoly] = anBigNeighbour[anBigNeighbour[iPoly]];
+            iFinalId = anBigNeighbour[iFinalId];
+            if( iFinalId < 0 )
+            {
+                break;
+            }
+            // If the biggest neighbour is larger than the threshold
+            // then we are golden.
+            if( anPolySizes[iFinalId] >= nSizeThreshold )
+            {
+                bFoundBigEnoughPoly = true;
+                break;
+            }
+            // Check that we don't cycle on an already visited polygon
+            if( oSetVisitedPoly.find(iFinalId) != oSetVisitedPoly.end() )
+                break;
+            oSetVisitedPoly.insert(iFinalId);
+        }
+
+        if( !bFoundBigEnoughPoly )
+        {
+            nFailedMerges++;
+            anBigNeighbour[iPoly] = -1;
             continue;
         }
-#endif
 
-        nFailedMerges++;
-        anBigNeighbour[iPoly] = -1;
-    }									
+        // Map the whole intermediate chain to it
+        int iPolyCur = iPoly;
+        while( anBigNeighbour[iPolyCur] != iFinalId )
+        {
+            int iNextPoly = anBigNeighbour[iPolyCur];
+            anBigNeighbour[iPolyCur] = iFinalId;
+            iPolyCur = iNextPoly;
+        }
+    }
 
-    CPLDebug( "GDALSieveFilter", 
+    CPLDebug( "GDALSieveFilter",
               "Small Polygons: %d, Isolated: %d, Unmergable: %d",
               nSieveTargets, nIsolatedSmall, nFailedMerges );
 
@@ -491,14 +512,13 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
 /*      "final maps" from the first.                                    */
 /* ==================================================================== */
     oSecondEnum.Clear();
-    
 
     for( iY = 0; eErr == CE_None && iY < nYSize; iY++ )
     {
 /* -------------------------------------------------------------------- */
 /*      Read the image data.                                            */
 /* -------------------------------------------------------------------- */
-        eErr = GDALRasterIO( hSrcBand, GF_Read, 0, iY, nXSize, 1, 
+        eErr = GDALRasterIO( hSrcBand, GF_Read, 0, iY, nXSize, 1,
                              panThisLineVal, nXSize, 1, GDT_Int32, 0, 0 );
 
         memcpy( panThisLineWriteVal, panThisLineVal, 4 * nXSize );
@@ -514,12 +534,12 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
 /*      the same thing done in the first pass above).                   */
 /* -------------------------------------------------------------------- */
         if( iY == 0 )
-            oSecondEnum.ProcessLine( 
+            oSecondEnum.ProcessLine(
                 NULL, panThisLineVal, NULL, panThisLineId, nXSize );
         else
             oSecondEnum.ProcessLine(
-                panLastLineVal, panThisLineVal, 
-                panLastLineId,  panThisLineId, 
+                panLastLineVal, panThisLineVal,
+                panLastLineId,  panThisLineId,
                 nXSize );
 
 /* -------------------------------------------------------------------- */
@@ -535,7 +555,7 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
 
                 if( anBigNeighbour[iThisPoly] != -1 )
                 {
-                    panThisLineWriteVal[iX] = 
+                    panThisLineWriteVal[iX] =
                         oFirstEnum.panPolyValue[
                             anBigNeighbour[iThisPoly]];
                 }
@@ -545,7 +565,7 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
 /* -------------------------------------------------------------------- */
 /*      Write the update data out.                                      */
 /* -------------------------------------------------------------------- */
-        eErr = GDALRasterIO( hDstBand, GF_Write, 0, iY, nXSize, 1, 
+        eErr = GDALRasterIO( hDstBand, GF_Write, 0, iY, nXSize, 1,
                              panThisLineWriteVal, nXSize, 1, GDT_Int32, 0, 0 );
 
 /* -------------------------------------------------------------------- */
@@ -563,8 +583,8 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
 /* -------------------------------------------------------------------- */
 /*      Report progress, and support interrupts.                        */
 /* -------------------------------------------------------------------- */
-        if( eErr == CE_None 
-            && !pfnProgress( 0.5 + 0.5 * ((iY+1) / (double) nYSize), 
+        if( eErr == CE_None
+            && !pfnProgress( 0.5 + 0.5 * ((iY+1) / (double) nYSize),
                              "", pProgressArg ) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
diff --git a/alg/gdalsimplewarp.cpp b/alg/gdalsimplewarp.cpp
index c5ada70..0d27f95 100644
--- a/alg/gdalsimplewarp.cpp
+++ b/alg/gdalsimplewarp.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalsimplewarp.cpp 15436 2008-09-24 19:26:31Z rouault $
+ * $Id: gdalsimplewarp.cpp 33676 2016-03-07 21:38:34Z goatbar $
  *
  * Project:  Mapinfo Image Warper
  * Purpose:  Simple (source in memory) warp algorithm.
@@ -27,14 +27,14 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_priv.h"
-#include "gdal_alg.h"
 #include "cpl_string.h"
+#include "gdal_alg.h"
+#include "gdal_priv.h"
 
-CPL_CVSID("$Id: gdalsimplewarp.cpp 15436 2008-09-24 19:26:31Z rouault $");
+CPL_CVSID("$Id: gdalsimplewarp.cpp 33676 2016-03-07 21:38:34Z goatbar $");
 
-static void 
-GDALSimpleWarpRemapping( int nBandCount, GByte **papabySrcData, 
+static void
+GDALSimpleWarpRemapping( int nBandCount, GByte **papabySrcData,
                          int nSrcXSize, int nSrcYSize,
                          char **papszWarpOptions );
 
@@ -47,55 +47,53 @@ GDALSimpleWarpRemapping( int nBandCount, GByte **papabySrcData,
  *
  * Copies an image from a source dataset to a destination dataset applying
  * an application defined transformation.   This algorithm is called simple
- * because it lacks many options such as resampling kernels (other than 
+ * because it lacks many options such as resampling kernels (other than
  * nearest neighbour), support for data types other than 8bit, and the
  * ability to warp images without holding the entire source and destination
  * image in memory.
  *
- * The following option(s) may be passed in papszWarpOptions. 
+ * The following option(s) may be passed in papszWarpOptions.
  * <ul>
  * <li> "INIT=v[,v...]": This option indicates that the output dataset should
  * be initialized to the indicated value in any area valid data is not written.
- * Distinct values may be listed for each band separated by columns. 
+ * Distinct values may be listed for each band separated by columns.
  * </ul>
  *
- * @param hSrcDS the source image dataset. 
- * @param hDstDS the destination image dataset. 
+ * @param hSrcDS the source image dataset.
+ * @param hDstDS the destination image dataset.
  * @param nBandCount the number of bands to be warped.  If zero, all bands
  * will be processed.
- * @param panBandList the list of bands to translate. 
- * @param pfnTransform the transformation function to call.  See 
- * GDALTransformerFunc(). 
+ * @param panBandList the list of bands to translate.
+ * @param pfnTransform the transformation function to call.  See
+ * GDALTransformerFunc().
  * @param pTransformArg the callback handle to pass to pfnTransform.
- * @param pfnProgress the function used to report progress.  See 
- * GDALProgressFunc(). 
- * @param pProgressArg the callback handle to pass to pfnProgress. 
- * @param papszWarpOptions additional options controlling the warp. 
- * 
- * @return TRUE if the operation completes, or FALSE if an error occurs. 
+ * @param pfnProgress the function used to report progress.  See
+ * GDALProgressFunc().
+ * @param pProgressArg the callback handle to pass to pfnProgress.
+ * @param papszWarpOptions additional options controlling the warp.
+ *
+ * @return TRUE if the operation completes, or FALSE if an error occurs.
  */
 
 int CPL_STDCALL
-GDALSimpleImageWarp( GDALDatasetH hSrcDS, GDALDatasetH hDstDS, 
-                     int nBandCount, int *panBandList, 
+GDALSimpleImageWarp( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
+                     int nBandCount, int *panBandList,
                      GDALTransformerFunc pfnTransform, void *pTransformArg,
-                     GDALProgressFunc pfnProgress, void *pProgressArg, 
+                     GDALProgressFunc pfnProgress, void *pProgressArg,
                      char **papszWarpOptions )
-    
+
 {
     VALIDATE_POINTER1( hSrcDS, "GDALSimpleImageWarp", 0 );
     VALIDATE_POINTER1( hDstDS, "GDALSimpleImageWarp", 0 );
 
-    int		iBand, bCancelled = FALSE;
+    bool bError = false;
 
 /* -------------------------------------------------------------------- */
 /*      If no bands provided assume we should process all bands.        */
 /* -------------------------------------------------------------------- */
     if( nBandCount == 0 )
     {
-        int nResult;
-
-        nBandCount = GDALGetRasterCount( hSrcDS ); 
+        nBandCount = GDALGetRasterCount( hSrcDS );
         if (nBandCount == 0)
         {
             CPLError(CE_Failure, CPLE_AppDefined,
@@ -105,13 +103,14 @@ GDALSimpleImageWarp( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
 
         panBandList = (int *) CPLCalloc(sizeof(int),nBandCount);
 
-        for( iBand = 0; iBand < nBandCount; iBand++ )
+        for( int iBand = 0; iBand < nBandCount; iBand++ )
             panBandList[iBand] = iBand+1;
 
-        nResult = GDALSimpleImageWarp( hSrcDS, hDstDS, nBandCount, panBandList,
-                                       pfnTransform, pTransformArg, 
-                                       pfnProgress, pProgressArg, 
-                                       papszWarpOptions );
+        const int nResult =
+            GDALSimpleImageWarp( hSrcDS, hDstDS, nBandCount, panBandList,
+                                 pfnTransform, pTransformArg,
+                                 pfnProgress, pProgressArg,
+                                 papszWarpOptions );
         CPLFree( panBandList );
         return nResult;
     }
@@ -128,19 +127,43 @@ GDALSimpleImageWarp( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
 /* -------------------------------------------------------------------- */
 /*      Load the source image band(s).                                  */
 /* -------------------------------------------------------------------- */
-    int   nSrcXSize = GDALGetRasterXSize(hSrcDS);
-    int   nSrcYSize = GDALGetRasterYSize(hSrcDS);
-    GByte **papabySrcData;
+    const int nSrcXSize = GDALGetRasterXSize(hSrcDS);
+    const int nSrcYSize = GDALGetRasterYSize(hSrcDS);
+    GByte **papabySrcData = static_cast<GByte **>(
+        CPLCalloc(nBandCount, sizeof(GByte*)) );
 
-    papabySrcData = (GByte **) CPLCalloc(nBandCount,sizeof(GByte*));
-    for( iBand = 0; iBand < nBandCount; iBand++ )
+    bool ok = true;
+    for( int iBand = 0; iBand < nBandCount; iBand++ )
     {
-        papabySrcData[iBand] = (GByte *) VSIMalloc(nSrcXSize*nSrcYSize);
-        
-        GDALRasterIO( GDALGetRasterBand(hSrcDS,panBandList[iBand]), GF_Read,
-                      0, 0, nSrcXSize, nSrcYSize, 
-                      papabySrcData[iBand], nSrcXSize, nSrcYSize, GDT_Byte, 
-                      0, 0 );
+        papabySrcData[iBand] = static_cast<GByte *>(
+            VSI_MALLOC2_VERBOSE(nSrcXSize, nSrcYSize) );
+        if( papabySrcData[iBand] == NULL )
+        {
+            CPLError( CE_Failure, CPLE_OutOfMemory,
+                      "GDALSimpleImageWarp out of memory.\n" );
+            ok = false;
+            break;
+        }
+
+        if( GDALRasterIO( GDALGetRasterBand(hSrcDS,panBandList[iBand]), GF_Read,
+                      0, 0, nSrcXSize, nSrcYSize,
+                      papabySrcData[iBand], nSrcXSize, nSrcYSize, GDT_Byte,
+                      0, 0 ) != CE_None )
+        {
+            CPLError( CE_Failure, CPLE_FileIO, "GDALSimpleImageWarp "
+                      "GDALRasterIO failure %s ",
+                      CPLGetLastErrorMsg() );
+            ok = false;
+            break;
+        }
+    }
+    if( !ok ) {
+        for( int i=0; i <= nBandCount; i++ )
+        {
+            VSIFree(papabySrcData[i]);
+        }
+        CPLFree(papabySrcData);
+        return FALSE;
     }
 
 /* -------------------------------------------------------------------- */
@@ -152,26 +175,25 @@ GDALSimpleImageWarp( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
 /* -------------------------------------------------------------------- */
 /*      Allocate scanline buffers for output image.                     */
 /* -------------------------------------------------------------------- */
-    int nDstXSize = GDALGetRasterXSize( hDstDS );
-    int nDstYSize = GDALGetRasterYSize( hDstDS );
-    GByte **papabyDstLine;
+    const int nDstXSize = GDALGetRasterXSize( hDstDS );
+    const int nDstYSize = GDALGetRasterYSize( hDstDS );
+    GByte **papabyDstLine = static_cast<GByte **>(
+        CPLCalloc(nBandCount, sizeof(GByte*)) );
 
-    papabyDstLine = (GByte **) CPLCalloc(nBandCount,sizeof(GByte*));
-    
-    for( iBand = 0; iBand < nBandCount; iBand++ )
-        papabyDstLine[iBand] = (GByte *) CPLMalloc( nDstXSize );
+    for( int iBand = 0; iBand < nBandCount; iBand++ )
+        papabyDstLine[iBand] = static_cast<GByte *>(CPLMalloc( nDstXSize ));
 
 /* -------------------------------------------------------------------- */
 /*      Allocate x,y,z coordinate arrays for transformation ... one     */
 /*      scanlines worth of positions.                                   */
 /* -------------------------------------------------------------------- */
-    double *padfX, *padfY, *padfZ;
-    int    *pabSuccess;
-
-    padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
-    padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
-    padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
-    pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
+    double *padfX = static_cast<double *>(
+        CPLMalloc(sizeof(double) * nDstXSize) );
+    double *padfY = static_cast<double *>(
+        CPLMalloc(sizeof(double) * nDstXSize) );
+    double *padfZ = static_cast<double *>(
+        CPLMalloc(sizeof(double) * nDstXSize) );
+    int *pabSuccess = static_cast<int *>( CPLMalloc(sizeof(int) * nDstXSize) );
 
 /* -------------------------------------------------------------------- */
 /*      Establish the value we will use to initialize the bands.  We    */
@@ -180,25 +202,23 @@ GDALSimpleImageWarp( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
 /*      overridden by passed                                            */
 /*      option(s).                                                      */
 /* -------------------------------------------------------------------- */
-    int         *panBandInit;
-
-    panBandInit = (int *) CPLCalloc(sizeof(int),nBandCount);
+    int * const panBandInit =
+        static_cast<int *>( CPLCalloc(sizeof(int), nBandCount) );
     if( CSLFetchNameValue( papszWarpOptions, "INIT" ) )
     {
-        int  iBand, nTokenCount;
-        char **papszTokens = 
-            CSLTokenizeStringComplex( CSLFetchNameValue( papszWarpOptions, 
+        char **papszTokens =
+            CSLTokenizeStringComplex( CSLFetchNameValue( papszWarpOptions,
                                                          "INIT" ),
                                       " ,", FALSE, FALSE );
 
-        nTokenCount = CSLCount(papszTokens);
+        const int nTokenCount = CSLCount(papszTokens);
 
-        for( iBand = 0; iBand < nBandCount; iBand++ )
+        for( int iBand = 0; iBand < nBandCount; iBand++ )
         {
             if( nTokenCount == 0 )
                 panBandInit[iBand] = 0;
             else
-                panBandInit[iBand] = 
+                panBandInit[iBand] =
                     atoi(papszTokens[MIN(iBand,nTokenCount-1)]);
         }
 
@@ -208,27 +228,29 @@ GDALSimpleImageWarp( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
 /* -------------------------------------------------------------------- */
 /*      Loop over all the scanlines in the output image.                */
 /* -------------------------------------------------------------------- */
-    int iDstY;
-
-    for( iDstY = 0; iDstY < nDstYSize; iDstY++ )
+    for( int iDstY = 0; iDstY < nDstYSize; iDstY++ )
     {
-        int iDstX;
-
-        // Clear output buffer to "transparent" value.  Shouldn't we
+        // Clear output buffer to "transparent" value.  Should not we
         // really be reading from the destination file to support overlay?
-        for( iBand = 0; iBand < nBandCount; iBand++ )
+        for( int iBand = 0; iBand < nBandCount; iBand++ )
         {
             if( panBandInit[iBand] == -1 )
-                GDALRasterIO( GDALGetRasterBand(hDstDS,iBand+1), GF_Read,
-                              0, iDstY, nDstXSize, 1, 
-                              papabyDstLine[iBand], nDstXSize, 1, GDT_Byte, 
-                              0, 0 );
+            {
+                if( GDALRasterIO( GDALGetRasterBand(hDstDS,iBand+1), GF_Read,
+                              0, iDstY, nDstXSize, 1,
+                              papabyDstLine[iBand], nDstXSize, 1, GDT_Byte,
+                              0, 0 ) != CE_None )
+                {
+                    bError = TRUE;
+                    break;
+                }
+            }
             else
                 memset( papabyDstLine[iBand], panBandInit[iBand], nDstXSize );
         }
 
         // Set point to transform.
-        for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
+        for( int iDstX = 0; iDstX < nDstXSize; iDstX++ )
         {
             padfX[iDstX] = iDstX + 0.5;
             padfY[iDstX] = iDstY + 0.5;
@@ -237,50 +259,52 @@ GDALSimpleImageWarp( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
 
         // Transform the points from destination pixel/line coordinates
         // to source pixel/line coordinates.
-        pfnTransform( pTransformArg, TRUE, nDstXSize, 
+        pfnTransform( pTransformArg, TRUE, nDstXSize,
                       padfX, padfY, padfZ, pabSuccess );
 
         // Loop over the output scanline.
-        for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
+        for( int iDstX = 0; iDstX < nDstXSize; iDstX++ )
         {
             if( !pabSuccess[iDstX] )
                 continue;
 
             // We test against the value before casting to avoid the
             // problem of asymmetric truncation effects around zero.  That is
-            // -0.5 will be 0 when cast to an int. 
+            // -0.5 will be 0 when cast to an int.
             if( padfX[iDstX] < 0.0 || padfY[iDstX] < 0.0 )
                 continue;
 
-            int iSrcX, iSrcY, iSrcOffset;
-
-            iSrcX = (int) padfX[iDstX];
-            iSrcY = (int) padfY[iDstX];
+            const int iSrcX = static_cast<int>( padfX[iDstX] );
+            const int iSrcY = static_cast<int>( padfY[iDstX] );
 
             if( iSrcX >= nSrcXSize || iSrcY >= nSrcYSize )
                 continue;
 
-            iSrcOffset = iSrcX + iSrcY * nSrcXSize;
-            
-            for( iBand = 0; iBand < nBandCount; iBand++ )
+            const int iSrcOffset = iSrcX + iSrcY * nSrcXSize;
+
+            for( int iBand = 0; iBand < nBandCount; iBand++ )
                 papabyDstLine[iBand][iDstX] = papabySrcData[iBand][iSrcOffset];
         }
 
-        // Write scanline to disk. 
-        for( iBand = 0; iBand < nBandCount; iBand++ )
+        // Write scanline to disk.
+        for( int iBand = 0; iBand < nBandCount; iBand++ )
         {
-            GDALRasterIO( GDALGetRasterBand(hDstDS,iBand+1), GF_Write,
-                          0, iDstY, nDstXSize, 1, 
-                          papabyDstLine[iBand], nDstXSize, 1, GDT_Byte, 0, 0 );
+            if( GDALRasterIO( GDALGetRasterBand(hDstDS,iBand+1), GF_Write,
+                          0, iDstY, nDstXSize, 1,
+                          papabyDstLine[iBand], nDstXSize, 1, GDT_Byte, 0, 0 ) != CE_None )
+            {
+                bError = TRUE;
+                break;
+            }
         }
 
         if( pfnProgress != NULL )
         {
-            if( !pfnProgress( (iDstY+1) / (double) nDstYSize, 
+            if( !pfnProgress( (iDstY+1) / (double) nDstYSize,
                               "", pProgressArg ) )
             {
                 CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
-                bCancelled = TRUE;
+                bError = TRUE;
                 break;
             }
         }
@@ -289,7 +313,7 @@ GDALSimpleImageWarp( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
 /* -------------------------------------------------------------------- */
 /*      Cleanup working buffers.                                        */
 /* -------------------------------------------------------------------- */
-    for( iBand = 0; iBand < nBandCount; iBand++ )
+    for( int iBand = 0; iBand < nBandCount; iBand++ )
     {
         CPLFree( papabyDstLine[iBand] );
         CPLFree( papabySrcData[iBand] );
@@ -302,8 +326,8 @@ GDALSimpleImageWarp( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
     CPLFree( padfY );
     CPLFree( padfZ );
     CPLFree( pabSuccess );
-    
-    return !bCancelled;
+
+    return !bError;
 }
 
 /************************************************************************/
@@ -314,11 +338,11 @@ GDALSimpleImageWarp( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
 /*      data before warping.  Two kinds are support ... REMAP           */
 /*      commands which remap selected pixel values for any band and     */
 /*      REMAP_MULTI which only remap pixels matching the input in       */
-/*      all bands at once (ie. to remap an RGB value to another).       */
+/*      all bands at once (i.e. to remap an RGB value to another).       */
 /************************************************************************/
 
-static void 
-GDALSimpleWarpRemapping( int nBandCount, GByte **papabySrcData, 
+static void
+GDALSimpleWarpRemapping( int nBandCount, GByte **papabySrcData,
                          int nSrcXSize, int nSrcYSize,
                          char **papszWarpOptions )
 
@@ -327,30 +351,29 @@ GDALSimpleWarpRemapping( int nBandCount, GByte **papabySrcData,
 /* ==================================================================== */
 /*      Process any and all single value REMAP commands.                */
 /* ==================================================================== */
-    int  iRemap;
-    char **papszRemaps = CSLFetchNameValueMultiple( papszWarpOptions, 
+    char **papszRemaps = CSLFetchNameValueMultiple( papszWarpOptions,
                                                     "REMAP" );
 
-    for( iRemap = 0; iRemap < CSLCount(papszRemaps); iRemap++ )
+    for( int iRemap = 0; iRemap < CSLCount(papszRemaps); iRemap++ )
     {
 
 /* -------------------------------------------------------------------- */
 /*      What are the pixel values to map from and to?                   */
 /* -------------------------------------------------------------------- */
         char **papszTokens = CSLTokenizeString( papszRemaps[iRemap] );
-        int  nFromValue, nToValue;
-        
+
         if( CSLCount(papszTokens) != 2 )
         {
             CPLError( CE_Warning, CPLE_AppDefined,
-                      "Ill formed REMAP `%s' ignored in GDALSimpleWarpRemapping()", 
+                      "Ill formed REMAP `%s' ignored in GDALSimpleWarpRemapping()",
                       papszRemaps[iRemap] );
+            CSLDestroy( papszTokens );
             continue;
         }
 
-        nFromValue = atoi(papszTokens[0]);
-        nToValue = atoi(papszTokens[1]);
-        
+        const int nFromValue = atoi(papszTokens[0]);
+        const int nToValue = atoi(papszTokens[1]);
+
         CSLDestroy( papszTokens );
 
 /* -------------------------------------------------------------------- */
@@ -359,12 +382,12 @@ GDALSimpleWarpRemapping( int nBandCount, GByte **papabySrcData,
         for( int iBand = 0; iBand < nBandCount; iBand++ )
         {
             GByte *pabyData = papabySrcData[iBand];
-            int   nPixelCount = nSrcXSize * nSrcYSize;
-            
+            int nPixelCount = nSrcXSize * nSrcYSize;
+
             while( nPixelCount != 0 )
             {
                 if( *pabyData == nFromValue )
-                    *pabyData = (GByte) nToValue;
+                    *pabyData = static_cast<GByte>( nToValue );
 
                 pabyData++;
                 nPixelCount--;
@@ -377,34 +400,35 @@ GDALSimpleWarpRemapping( int nBandCount, GByte **papabySrcData,
 /* ==================================================================== */
 /*      Process any and all REMAP_MULTI commands.                       */
 /* ==================================================================== */
-    papszRemaps = CSLFetchNameValueMultiple( papszWarpOptions, 
+    papszRemaps = CSLFetchNameValueMultiple( papszWarpOptions,
                                              "REMAP_MULTI" );
 
-    for( iRemap = 0; iRemap < CSLCount(papszRemaps); iRemap++ )
+    for( int iRemap = 0; iRemap < CSLCount(papszRemaps); iRemap++ )
     {
 /* -------------------------------------------------------------------- */
 /*      What are the pixel values to map from and to?                   */
 /* -------------------------------------------------------------------- */
         char **papszTokens = CSLTokenizeString( papszRemaps[iRemap] );
-        int *panFromValue, *panToValue;
-        int  nMapBandCount, iBand;
 
-        if( CSLCount(papszTokens) % 2 == 1 
-            || CSLCount(papszTokens) == 0 
+        if( CSLCount(papszTokens) % 2 == 1
+            || CSLCount(papszTokens) == 0
             || CSLCount(papszTokens) > nBandCount * 2 )
         {
             CPLError( CE_Warning, CPLE_AppDefined,
-                      "Ill formed REMAP_MULTI `%s' ignored in GDALSimpleWarpRemapping()", 
+                      "Ill formed REMAP_MULTI `%s' ignored in GDALSimpleWarpRemapping()",
                       papszRemaps[iRemap] );
+            CSLDestroy( papszTokens );
             continue;
         }
 
-        nMapBandCount = CSLCount(papszTokens) / 2;
-        
-        panFromValue = (int *) CPLMalloc(sizeof(int) * nMapBandCount );
-        panToValue = (int *) CPLMalloc(sizeof(int) * nMapBandCount );
+        const int nMapBandCount = CSLCount(papszTokens) / 2;
+
+        int *panFromValue = static_cast<int *>(
+            CPLMalloc(sizeof(int) * nMapBandCount ) );
+        int *panToValue = static_cast<int *>(
+            CPLMalloc(sizeof(int) * nMapBandCount ) );
 
-        for( iBand = 0; iBand < nMapBandCount; iBand++ )
+        for( int iBand = 0; iBand < nMapBandCount; iBand++ )
         {
             panFromValue[iBand] = atoi(papszTokens[iBand]);
             panToValue[iBand] = atoi(papszTokens[iBand+nMapBandCount]);
@@ -415,27 +439,27 @@ GDALSimpleWarpRemapping( int nBandCount, GByte **papabySrcData,
 /* -------------------------------------------------------------------- */
 /*      Search for matching values to replace.                          */
 /* -------------------------------------------------------------------- */
-        int   nPixelCount = nSrcXSize * nSrcYSize;
-        int   iPixel;
+        const int nPixelCount = nSrcXSize * nSrcYSize;
 
-        for( iPixel = 0; iPixel < nPixelCount; iPixel++ )
+        for( int iPixel = 0; iPixel < nPixelCount; iPixel++ )
         {
             if( papabySrcData[0][iPixel] != panFromValue[0] )
                 continue;
 
-            int bMatch = TRUE;
+            bool bMatch = true;
 
-            for( iBand = 1; iBand < nMapBandCount; iBand++ )
+            for( int iBand = 1; iBand < nMapBandCount; iBand++ )
             {
                 if( papabySrcData[iBand][iPixel] != panFromValue[iBand] )
-                    bMatch = FALSE;
+                    bMatch = false;
             }
 
             if( !bMatch )
                 continue;
 
-            for( iBand = 0; iBand < nMapBandCount; iBand++ )
-                papabySrcData[iBand][iPixel] = (GByte) panToValue[iBand];
+            for( int iBand = 0; iBand < nMapBandCount; iBand++ )
+                papabySrcData[iBand][iPixel] =
+                    static_cast<GByte>( panToValue[iBand] );
         }
 
         CPLFree( panFromValue );
diff --git a/alg/gdaltransformer.cpp b/alg/gdaltransformer.cpp
index 62a528e..8bd16b6 100644
--- a/alg/gdaltransformer.cpp
+++ b/alg/gdaltransformer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaltransformer.cpp 29309 2015-06-05 18:48:48Z rouault $
+ * $Id: gdaltransformer.cpp 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  Mapinfo Image Warper
  * Purpose:  Implementation of one or more GDALTrasformerFunc types, including
@@ -7,7 +7,7 @@
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
- * Copyright (c) 2002, i3 - information integration and imaging 
+ * Copyright (c) 2002, i3 - information integration and imaging
  *                          Fort Collin, CO
  * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
@@ -38,7 +38,7 @@
 #include "cpl_list.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: gdaltransformer.cpp 29309 2015-06-05 18:48:48Z rouault $");
+CPL_CVSID("$Id: gdaltransformer.cpp 33715 2016-03-13 08:52:06Z goatbar $");
 CPL_C_START
 void *GDALDeserializeGCPTransformer( CPLXMLNode *psTree );
 void *GDALDeserializeTPSTransformer( CPLXMLNode *psTree );
@@ -66,24 +66,24 @@ static void GDALRefreshGenImgProjTransformer(void* hTransformArg);
 
 Generic signature for spatial point transformers.
 
-This function signature is used for a variety of functions that accept 
+This function signature is used for a variety of functions that accept
 passed in functions used to transform point locations between two coordinate
-spaces.  
+spaces.
 
-The GDALCreateGenImgProjTransformer(), GDALCreateReprojectionTransformer(), 
+The GDALCreateGenImgProjTransformer(), GDALCreateReprojectionTransformer(),
 GDALCreateGCPTransformer() and GDALCreateApproxTransformer() functions can
 be used to prepare argument data for some built-in transformers.  As well,
 applications can implement their own transformers to the following signature.
 
 \code
-typedef int 
-(*GDALTransformerFunc)( void *pTransformerArg, 
-                        int bDstToSrc, int nPointCount, 
+typedef int
+(*GDALTransformerFunc)( void *pTransformerArg,
+                        int bDstToSrc, int nPointCount,
                         double *x, double *y, double *z, int *panSuccess );
 \endcode
 
 @param pTransformerArg application supplied callback data used by the
-transformer.  
+transformer.
 
 @param bDstToSrc if TRUE the transformation will be from the destination
 coordinate space to the source coordinate system, otherwise the transformation
@@ -119,40 +119,40 @@ points may have failed) or FALSE if the overall transformation fails.
  *
  * Then a resolution is computed with the intent that the length of the
  * distance from the top left corner of the output imagery to the bottom right
- * corner would represent the same number of pixels as in the source image. 
- * Note that if the image is somewhat rotated the diagonal taken isnt of the
+ * corner would represent the same number of pixels as in the source image.
+ * Note that if the image is somewhat rotated the diagonal taken isn't of the
  * whole output bounding rectangle, but instead of the locations where the
- * top/left and bottom/right corners transform.  The output pixel size is 
+ * top/left and bottom/right corners transform.  The output pixel size is
  * always square.  This is intended to approximately preserve the resolution
- * of the input data in the output file. 
- * 
+ * of the input data in the output file.
+ *
  * The values returned in padfGeoTransformOut, pnPixels and pnLines are
  * the suggested number of pixels and lines for the output file, and the
  * geotransform relating those pixels to the output georeferenced coordinates.
  *
- * The trickiest part of using the function is ensuring that the 
- * transformer created is from source file pixel/line coordinates to 
- * output file georeferenced coordinates.  This can be accomplished with 
- * GDALCreateGenImgProjTransformer() by passing a NULL for the hDstDS.  
+ * The trickiest part of using the function is ensuring that the
+ * transformer created is from source file pixel/line coordinates to
+ * output file georeferenced coordinates.  This can be accomplished with
+ * GDALCreateGenImgProjTransformer() by passing a NULL for the hDstDS.
  *
  * @param hSrcDS the input image (it is assumed the whole input images is
- * being transformed). 
+ * being transformed).
  * @param pfnTransformer the transformer function.
  * @param pTransformArg the callback data for the transformer function.
  * @param padfGeoTransformOut the array of six doubles in which the suggested
- * geotransform is returned. 
+ * geotransform is returned.
  * @param pnPixels int in which the suggest pixel width of output is returned.
  * @param pnLines int in which the suggest pixel height of output is returned.
  *
- * @return CE_None if successful or CE_Failure otherwise. 
+ * @return CE_None if successful or CE_Failure otherwise.
  */
 
 
 CPLErr CPL_STDCALL
-GDALSuggestedWarpOutput( GDALDatasetH hSrcDS, 
-                         GDALTransformerFunc pfnTransformer, 
-                         void *pTransformArg, 
-                         double *padfGeoTransformOut, 
+GDALSuggestedWarpOutput( GDALDatasetH hSrcDS,
+                         GDALTransformerFunc pfnTransformer,
+                         void *pTransformArg,
+                         double *padfGeoTransformOut,
                          int *pnPixels, int *pnLines )
 
 {
@@ -160,8 +160,8 @@ GDALSuggestedWarpOutput( GDALDatasetH hSrcDS,
 
     double adfExtent[4] = { 0 };
 
-    return GDALSuggestedWarpOutput2( hSrcDS, pfnTransformer, pTransformArg, 
-                                     padfGeoTransformOut, pnPixels, pnLines, 
+    return GDALSuggestedWarpOutput2( hSrcDS, pfnTransformer, pTransformArg,
+                                     padfGeoTransformOut, pnPixels, pnLines,
                                      adfExtent, 0 );
 }
 
@@ -181,13 +181,13 @@ static int GDALSuggestedWarpOutput2_MustAdjustForRightBorder(
     double adfX[21] = { 0 };
     double adfY[21] = { 0 };
     double adfZ[21] = { 0 };
-    
+
     //double dfMinXOut = padfExtent[0];
     //double dfMinYOut = padfExtent[1];
     double dfMaxXOut = padfExtent[2];
     double dfMaxYOut = padfExtent[3];
-    
-    // Take 20 steps 
+
+    // Take 20 steps
     nSamplePoints = 0;
     for( dfRatio = 0.0; dfRatio <= 1.01; dfRatio += 0.05 )
     {
@@ -200,20 +200,20 @@ static int GDALSuggestedWarpOutput2_MustAdjustForRightBorder(
         adfY[nSamplePoints]   = dfMaxYOut - dfPixelSizeY * dfRatio * nLines;
         adfZ[nSamplePoints++] = 0.0;
     }
-    
+
     bErr = FALSE;
-    if( !pfnTransformer( pTransformArg, TRUE, nSamplePoints, 
+    if( !pfnTransformer( pTransformArg, TRUE, nSamplePoints,
                              adfX, adfY, adfZ, abSuccess ) )
     {
         bErr = TRUE;
     }
-    
-    if( !bErr && !pfnTransformer( pTransformArg, FALSE, nSamplePoints, 
+
+    if( !bErr && !pfnTransformer( pTransformArg, FALSE, nSamplePoints,
                              adfX, adfY, adfZ, abSuccess ) )
     {
         bErr = TRUE;
     }
-    
+
     nSamplePoints = 0;
     nBadCount = 0;
     for( dfRatio = 0.0; !bErr && dfRatio <= 1.01; dfRatio += 0.05 )
@@ -225,7 +225,7 @@ static int GDALSuggestedWarpOutput2_MustAdjustForRightBorder(
             nBadCount ++;
         nSamplePoints ++;
     }
-    
+
     return (nBadCount == nSamplePoints);
 }
 
@@ -244,13 +244,13 @@ static int GDALSuggestedWarpOutput2_MustAdjustForBottomBorder(
     double adfX[21] = { 0 };
     double adfY[21] = { 0 };
     double adfZ[21] = { 0 };
-    
+
     double dfMinXOut = padfExtent[0];
     double dfMinYOut = padfExtent[1];
     //double dfMaxXOut = padfExtent[2];
     //double dfMaxYOut = padfExtent[3];
-    
-    // Take 20 steps 
+
+    // Take 20 steps
     nSamplePoints = 0;
     for( dfRatio = 0.0; dfRatio <= 1.01; dfRatio += 0.05 )
     {
@@ -263,20 +263,20 @@ static int GDALSuggestedWarpOutput2_MustAdjustForBottomBorder(
         adfY[nSamplePoints]   = dfMinYOut;
         adfZ[nSamplePoints++] = 0.0;
     }
-    
+
     bErr = FALSE;
-    if( !pfnTransformer( pTransformArg, TRUE, nSamplePoints, 
+    if( !pfnTransformer( pTransformArg, TRUE, nSamplePoints,
                              adfX, adfY, adfZ, abSuccess ) )
     {
         bErr = TRUE;
     }
-    
-    if( !bErr && !pfnTransformer( pTransformArg, FALSE, nSamplePoints, 
+
+    if( !bErr && !pfnTransformer( pTransformArg, FALSE, nSamplePoints,
                              adfX, adfY, adfZ, abSuccess ) )
     {
         bErr = TRUE;
     }
-    
+
     nSamplePoints = 0;
     nBadCount = 0;
     for( dfRatio = 0.0; !bErr && dfRatio <= 1.01; dfRatio += 0.05 )
@@ -288,7 +288,7 @@ static int GDALSuggestedWarpOutput2_MustAdjustForBottomBorder(
             nBadCount ++;
         nSamplePoints ++;
     }
-    
+
     return (nBadCount == nSamplePoints);
 }
 
@@ -306,34 +306,34 @@ static int GDALSuggestedWarpOutput2_MustAdjustForBottomBorder(
  *
  * Then a resolution is computed with the intent that the length of the
  * distance from the top left corner of the output imagery to the bottom right
- * corner would represent the same number of pixels as in the source image. 
- * Note that if the image is somewhat rotated the diagonal taken isnt of the
+ * corner would represent the same number of pixels as in the source image.
+ * Note that if the image is somewhat rotated the diagonal taken isn't of the
  * whole output bounding rectangle, but instead of the locations where the
- * top/left and bottom/right corners transform.  The output pixel size is 
+ * top/left and bottom/right corners transform.  The output pixel size is
  * always square.  This is intended to approximately preserve the resolution
- * of the input data in the output file. 
- * 
+ * of the input data in the output file.
+ *
  * The values returned in padfGeoTransformOut, pnPixels and pnLines are
  * the suggested number of pixels and lines for the output file, and the
  * geotransform relating those pixels to the output georeferenced coordinates.
  *
- * The trickiest part of using the function is ensuring that the 
- * transformer created is from source file pixel/line coordinates to 
- * output file georeferenced coordinates.  This can be accomplished with 
- * GDALCreateGenImgProjTransformer() by passing a NULL for the hDstDS.  
+ * The trickiest part of using the function is ensuring that the
+ * transformer created is from source file pixel/line coordinates to
+ * output file georeferenced coordinates.  This can be accomplished with
+ * GDALCreateGenImgProjTransformer() by passing a NULL for the hDstDS.
  *
  * @param hSrcDS the input image (it is assumed the whole input images is
- * being transformed). 
+ * being transformed).
  * @param pfnTransformer the transformer function.
  * @param pTransformArg the callback data for the transformer function.
  * @param padfGeoTransformOut the array of six doubles in which the suggested
- * geotransform is returned. 
+ * geotransform is returned.
  * @param pnPixels int in which the suggest pixel width of output is returned.
  * @param pnLines int in which the suggest pixel height of output is returned.
- * @param padfExtent Four entry array to return extents as (xmin, ymin, xmax, ymax). 
+ * @param padfExtent Four entry array to return extents as (xmin, ymin, xmax, ymax).
  * @param nOptions Options, currently always zero.
  *
- * @return CE_None if successful or CE_Failure otherwise. 
+ * @return CE_None if successful or CE_Failure otherwise.
  */
 
 CPLErr CPL_STDCALL
@@ -375,9 +375,9 @@ retry:
     double dfRatio = 0.0;
     double dfStep = 1. / nSteps;
 
-    pabSuccess = (int *) VSIMalloc3(sizeof(int), nSteps + 1, nSteps + 1);
-    padfX = (double *) VSIMalloc3(sizeof(double) * 3, nSteps + 1, nSteps + 1);
-    padfXRevert = (double *) VSIMalloc3(sizeof(double) * 3, nSteps + 1, nSteps + 1);
+    pabSuccess = (int *) VSI_MALLOC3_VERBOSE(sizeof(int), nSteps + 1, nSteps + 1);
+    padfX = (double *) VSI_MALLOC3_VERBOSE(sizeof(double) * 3, nSteps + 1, nSteps + 1);
+    padfXRevert = (double *) VSI_MALLOC3_VERBOSE(sizeof(double) * 3, nSteps + 1, nSteps + 1);
     if (pabSuccess == NULL || padfX == NULL || padfXRevert == NULL)
     {
         CPLFree( padfX );
@@ -395,19 +395,18 @@ retry:
     padfYRevert = padfXRevert + nSampleMax;
     padfZRevert = padfXRevert + nSampleMax * 2;
 
-
     // Take N_STEPS steps
     int iStep;
     for( iStep = 0; iStep <= nSteps; iStep ++ )
     {
         dfRatio = (iStep == nSteps) ? 1.0 : iStep * dfStep;
 
-        // Along top 
+        // Along top
         padfX[iStep]   = dfRatio * nInXSize;
         padfY[iStep]   = 0.0;
         padfZ[iStep] = 0.0;
 
-        // Along bottom 
+        // Along bottom
         padfX[nSteps + 1 + iStep]   = dfRatio * nInXSize;
         padfY[nSteps + 1 + iStep]   = nInYSize;
         padfZ[nSteps + 1 + iStep] = 0.0;
@@ -432,10 +431,10 @@ retry:
 /* -------------------------------------------------------------------- */
     int    nFailedCount = 0, i;
 
-    if( !pfnTransformer( pTransformArg, FALSE, nSamplePoints, 
+    if( !pfnTransformer( pTransformArg, FALSE, nSamplePoints,
                          padfX, padfY, padfZ, pabSuccess ) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "GDALSuggestedWarpOutput() failed because the passed\n"
                   "transformer failed." );
         CPLFree( padfX );
@@ -449,7 +448,7 @@ retry:
         if( !pabSuccess[i] )
             nFailedCount++;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Check if the computed target coordinates are revertable.        */
 /*      If not, try the detailed grid sampling.                         */
@@ -459,7 +458,7 @@ retry:
         memcpy(padfXRevert, padfX, nSamplePoints * sizeof(double));
         memcpy(padfYRevert, padfY, nSamplePoints * sizeof(double));
         memcpy(padfZRevert, padfZ, nSamplePoints * sizeof(double));
-        if( !pfnTransformer( pTransformArg, TRUE, nSamplePoints, 
+        if( !pfnTransformer( pTransformArg, TRUE, nSamplePoints,
                              padfXRevert, padfYRevert, padfZRevert, pabSuccess ) )
         {
             nFailedCount = 1;
@@ -499,9 +498,9 @@ retry:
                     dfExpectedX   = nInXSize;
                     dfExpectedY   = dfRatio * nInYSize;
                 }
-                
-                if (fabs(padfXRevert[i] - dfExpectedX) > nInXSize / nSteps ||
-                    fabs(padfYRevert[i] - dfExpectedY) > nInYSize / nSteps)
+
+                if (fabs(padfXRevert[i] - dfExpectedX) > nInXSize / static_cast<double>(nSteps) ||
+                    fabs(padfYRevert[i] - dfExpectedY) > nInYSize / static_cast<double>(nSteps))
                     nFailedCount ++;
             }
             if( nFailedCount != 0 )
@@ -522,7 +521,7 @@ retry:
         double dfRatio2;
         nSamplePoints = 0;
 
-        // Take N_STEPS steps 
+        // Take N_STEPS steps
         for( iStep = 0; iStep <= nSteps; iStep ++ )
         {
             dfRatio = (iStep == nSteps) ? 1.0 : iStep * dfStep;
@@ -540,10 +539,10 @@ retry:
 
         CPLAssert( nSamplePoints == nSampleMax );
 
-        if( !pfnTransformer( pTransformArg, FALSE, nSamplePoints, 
+        if( !pfnTransformer( pTransformArg, FALSE, nSamplePoints,
                              padfX, padfY, padfZ, pabSuccess ) )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "GDALSuggestedWarpOutput() failed because the passed\n"
                       "transformer failed." );
 
@@ -554,7 +553,7 @@ retry:
             return CE_Failure;
         }
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Collect the bounds, ignoring any failed points.                 */
 /* -------------------------------------------------------------------- */
@@ -587,24 +586,24 @@ retry:
             double x_out_before = padfX[i-1];
             double x_out_after = padfX[i];
             int nIter = 0;
-            double x_in_before = (x_i - 1) * nInXSize * 1.0 / nSteps;
-            double x_in_after = x_i * nInXSize * 1.0 / nSteps;
+            double x_in_before = (double)(x_i - 1) * nInXSize / nSteps;
+            double x_in_after = (double)x_i * nInXSize / nSteps;
             int valid_before = pabSuccess[i-1];
             int valid_after = pabSuccess[i];
-            
-            /* Detect discontinuity in target coordinates when the target x coordinates */
-            /* change sign. This may be a false positive when the targe tx is around 0 */
-            /* Dichotomic search to reduce the interval to near the discontinuity and */
-            /* get a better out extent */
+
+            // Detect discontinuity in target coordinates when the target x
+            // coordinates change sign. This may be a false positive when the
+            // target tx is around 0 Dichotomic search to reduce the interval
+            // to near the discontinuity and get a better out extent.
             while ( (!valid_before || !valid_after ||
                      x_out_before * x_out_after < 0) && nIter < 16 )
             {
                 double x = (x_in_before + x_in_after) / 2;
-                double y = y_i * nInYSize * 1.0 / nSteps;
+                double y = (double)y_i * nInYSize / nSteps;
                 double z= 0;
                 //fprintf(stderr, "[%d] (%f, %f) -> ", nIter, x, y);
                 int bSuccess = TRUE;
-                if( !pfnTransformer( pTransformArg, FALSE, 1, 
+                if( !pfnTransformer( pTransformArg, FALSE, 1,
                                      &x, &y, &z, &bSuccess ) || !bSuccess )
                 {
                     //fprintf(stderr, "invalid\n");
@@ -622,7 +621,7 @@ retry:
                 else
                 {
                     //fprintf(stderr, "(%f, %f)\n", x, y);
-                    
+
                     if( !bGotInitialPoint )
                     {
                         bGotInitialPoint = TRUE;
@@ -636,7 +635,7 @@ retry:
                         dfMaxXOut = MAX(dfMaxXOut,x);
                         dfMaxYOut = MAX(dfMaxYOut,y);
                     }
-                    
+
                     if (!valid_before || x_out_before * x < 0)
                     {
                         valid_after = TRUE;
@@ -653,7 +652,7 @@ retry:
                 nIter ++;
             }
         }
-        
+
         if( !pabSuccess[i] )
         {
             nFailedCount++;
@@ -677,7 +676,7 @@ retry:
 
     if( nFailedCount > nSamplePoints - 10 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Too many points (%d out of %d) failed to transform,\n"
                   "unable to compute output bounds.",
                   nFailedCount, nSamplePoints );
@@ -690,8 +689,8 @@ retry:
     }
 
     if( nFailedCount > 0 )
-        CPLDebug( "GDAL", 
-                  "GDALSuggestedWarpOutput(): %d out of %d points failed to transform.", 
+        CPLDebug( "GDAL",
+                  "GDALSuggestedWarpOutput(): %d out of %d points failed to transform.",
                   nFailedCount, nSamplePoints );
 
 /* -------------------------------------------------------------------- */
@@ -717,21 +716,21 @@ retry:
     }
 
     dfDiagonalDist = sqrt( dfDeltaX * dfDeltaX + dfDeltaY * dfDeltaY );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Compute a pixel size from this.                                 */
 /* -------------------------------------------------------------------- */
     double dfPixelSize;
 
-    dfPixelSize = dfDiagonalDist 
+    dfPixelSize = dfDiagonalDist
         / sqrt(((double)nInXSize)*nInXSize + ((double)nInYSize)*nInYSize);
 
     double dfPixels = (dfMaxXOut - dfMinXOut) / dfPixelSize;
     double dfLines =  (dfMaxYOut - dfMinYOut) / dfPixelSize;
-    
+
     if( dfPixels > INT_MAX - 1 || dfLines > INT_MAX - 1 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Computed dimensions are too big : %.0f x %.0f",
                   dfPixels + 0.5, dfLines + 0.5 );
 
@@ -744,14 +743,14 @@ retry:
 
     *pnPixels = (int) (dfPixels + 0.5);
     *pnLines = (int) (dfLines + 0.5);
-    
+
     double dfPixelSizeX = dfPixelSize;
     double dfPixelSizeY = dfPixelSize;
-   
+
     double adfExtent[4];
     const double adfRatioArray[] = { 0, 0.001, 0.01, 0.1, 1 };
     size_t nRetry;
-    
+
 #define N_ELEMENTS(x) (sizeof(x) / sizeof(x[0]))
 
 /* -------------------------------------------------------------------- */
@@ -776,7 +775,7 @@ retry:
             break;
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Check that the bottom border is not completely out of source    */
 /*      image. If so, adjust the y pixel size a bit in the hope it will */
@@ -799,14 +798,14 @@ retry:
             break;
         }
     }
-    
-    
+
+
 /* -------------------------------------------------------------------- */
 /*      Recompute some bounds so that all return values are consistent  */
 /* -------------------------------------------------------------------- */
     dfMaxXOut = dfMinXOut + (*pnPixels) * dfPixelSizeX;
     dfMinYOut = dfMaxYOut - (*pnLines) * dfPixelSizeY;
-    
+
     /* -------------------------------------------------------------------- */
     /*      Return raw extents.                                             */
     /* -------------------------------------------------------------------- */
@@ -824,7 +823,7 @@ retry:
     padfGeoTransformOut[3] = dfMaxYOut;
     padfGeoTransformOut[4] = 0.0;
     padfGeoTransformOut[5] = - dfPixelSizeY;
-    
+
     CPLFree( padfX );
     CPLFree( padfXRevert );
     CPLFree( pabSuccess );
@@ -854,7 +853,7 @@ typedef struct {
 
     double   adfDstGeoTransform[6];
     double   adfDstInvGeoTransform[6];
-    
+
     void     *pDstGCPTransformArg;
     void     *pDstRPCTransformArg;
     void     *pDstTPSTransformArg;
@@ -869,14 +868,14 @@ static void* GDALCreateSimilarGenImgProjTransformer( void *hTransformArg, double
 {
     VALIDATE_POINTER1( hTransformArg, "GDALCreateSimilarGenImgProjTransformer", NULL );
 
-    GDALGenImgProjTransformInfo *psInfo = 
+    GDALGenImgProjTransformInfo *psInfo =
         (GDALGenImgProjTransformInfo *) hTransformArg;
 
     GDALGenImgProjTransformInfo *psClonedInfo =  (GDALGenImgProjTransformInfo *)
         CPLMalloc(sizeof(GDALGenImgProjTransformInfo));
 
     memcpy(psClonedInfo, psInfo, sizeof(GDALGenImgProjTransformInfo));
-    
+
     if( psClonedInfo->pSrcGCPTransformArg )
         psClonedInfo->pSrcGCPTransformArg = GDALCreateSimilarTransformer( psInfo->pSrcGCPTransformArg, dfRatioX, dfRatioY );
     else if( psClonedInfo->pSrcRPCTransformArg )
@@ -901,7 +900,7 @@ static void* GDALCreateSimilarGenImgProjTransformer( void *hTransformArg, double
             psClonedInfo->adfSrcGeoTransform[4] *= dfRatioX;
             psClonedInfo->adfSrcGeoTransform[5] *= dfRatioX;
         }
-        if( !GDALInvGeoTransform( psClonedInfo->adfSrcGeoTransform, 
+        if( !GDALInvGeoTransform( psClonedInfo->adfSrcGeoTransform,
                                   psClonedInfo->adfSrcInvGeoTransform ) )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Cannot invert geotransform");
@@ -909,10 +908,10 @@ static void* GDALCreateSimilarGenImgProjTransformer( void *hTransformArg, double
             return NULL;
         }
     }
-    
+
     if( psClonedInfo->pReprojectArg )
         psClonedInfo->pReprojectArg = GDALCloneTransformer( psInfo->pReprojectArg );
-    
+
     if( psClonedInfo->pDstGCPTransformArg )
         psClonedInfo->pDstGCPTransformArg = GDALCloneTransformer( psInfo->pDstGCPTransformArg );
     else if( psClonedInfo->pDstRPCTransformArg )
@@ -920,7 +919,7 @@ static void* GDALCreateSimilarGenImgProjTransformer( void *hTransformArg, double
     else if( psClonedInfo->pDstTPSTransformArg )
         psClonedInfo->pDstTPSTransformArg = GDALCloneTransformer( psInfo->pDstTPSTransformArg );
 
-    
+
     return psClonedInfo;
 }
 
@@ -933,41 +932,41 @@ static void* GDALCreateSimilarGenImgProjTransformer( void *hTransformArg, double
  *
  * This function creates a transformation object that maps from pixel/line
  * coordinates on one image to pixel/line coordinates on another image.  The
- * images may potentially be georeferenced in different coordinate systems, 
- * and may used GCPs to map between their pixel/line coordinates and 
+ * images may potentially be georeferenced in different coordinate systems,
+ * and may used GCPs to map between their pixel/line coordinates and
  * georeferenced coordinates (as opposed to the default assumption that their
- * geotransform should be used). 
+ * geotransform should be used).
  *
  * This transformer potentially performs three concatenated transformations.
  *
  * The first stage is from source image pixel/line coordinates to source
- * image georeferenced coordinates, and may be done using the geotransform, 
+ * image georeferenced coordinates, and may be done using the geotransform,
  * or if not defined using a polynomial model derived from GCPs.  If GCPs
- * are used this stage is accomplished using GDALGCPTransform(). 
+ * are used this stage is accomplished using GDALGCPTransform().
  *
  * The second stage is to change projections from the source coordinate system
- * to the destination coordinate system, assuming they differ.  This is 
+ * to the destination coordinate system, assuming they differ.  This is
  * accomplished internally using GDALReprojectionTransform().
  *
  * The third stage is converting from destination image georeferenced
  * coordinates to destination image coordinates.  This is done using the
- * destination image geotransform, or if not available, using a polynomial 
- * model derived from GCPs. If GCPs are used this stage is accomplished using 
+ * destination image geotransform, or if not available, using a polynomial
+ * model derived from GCPs. If GCPs are used this stage is accomplished using
  * GDALGCPTransform().  This stage is skipped if hDstDS is NULL when the
- * transformation is created. 
- * 
+ * transformation is created.
+ *
  * @param hSrcDS source dataset, or NULL.
- * @param pszSrcWKT the coordinate system for the source dataset.  If NULL, 
- * it will be read from the dataset itself. 
- * @param hDstDS destination dataset (or NULL). 
+ * @param pszSrcWKT the coordinate system for the source dataset.  If NULL,
+ * it will be read from the dataset itself.
+ * @param hDstDS destination dataset (or NULL).
  * @param pszDstWKT the coordinate system for the destination dataset.  If
  * NULL, and hDstDS not NULL, it will be read from the destination dataset.
  * @param bGCPUseOK TRUE if GCPs should be used if the geotransform is not
  * available on the source dataset (not destination).
  * @param dfGCPErrorThreshold ignored/deprecated.
- * @param nOrder the maximum order to use for GCP derived polynomials if 
+ * @param nOrder the maximum order to use for GCP derived polynomials if
  * possible.  Use 0 to autoselect, or -1 for thin plate splines.
- * 
+ *
  * @return handle suitable for use GDALGenImgProjTransform(), and to be
  * deallocated with GDALDestroyGenImgProjTransformer().
  */
@@ -989,7 +988,7 @@ GDALCreateGenImgProjTransformer( GDALDatasetH hSrcDS, const char *pszSrcWKT,
     if( !bGCPUseOK )
         papszOptions = CSLSetNameValue( papszOptions, "GCPS_OK", "FALSE" );
     if( nOrder != 0 )
-        papszOptions = CSLSetNameValue( papszOptions, "MAX_GCP_ORDER", 
+        papszOptions = CSLSetNameValue( papszOptions, "MAX_GCP_ORDER",
                                         CPLString().Printf("%d",nOrder) );
 
     pRet = GDALCreateGenImgProjTransformer2( hSrcDS, hDstDS, papszOptions );
@@ -1009,10 +1008,10 @@ GDALCreateGenImgProjTransformer( GDALDatasetH hSrcDS, const char *pszSrcWKT,
 
 static CPLString InsertCenterLong( GDALDatasetH hDS, CPLString osWKT )
 
-{								        
-    if( !EQUALN(osWKT.c_str(), "GEOGCS[", 7) )
+{
+    if( !STARTS_WITH_CI(osWKT.c_str(), "GEOGCS[") )
         return osWKT;
-    
+
     if( strstr(osWKT,"EXTENSION[\"CENTER_LONG") != NULL )
         return osWKT;
 
@@ -1032,7 +1031,7 @@ static CPLString InsertCenterLong( GDALDatasetH hDS, CPLString osWKT )
     int nXSize = GDALGetRasterXSize( hDS );
     int nYSize = GDALGetRasterYSize( hDS );
 
-    dfMinLong = 
+    dfMinLong =
         MIN(MIN(adfGeoTransform[0] + 0 * adfGeoTransform[1]
                 + 0 * adfGeoTransform[2],
                 adfGeoTransform[0] + nXSize * adfGeoTransform[1]
@@ -1041,7 +1040,7 @@ static CPLString InsertCenterLong( GDALDatasetH hDS, CPLString osWKT )
                 + nYSize * adfGeoTransform[2],
                 adfGeoTransform[0] + nXSize * adfGeoTransform[1]
                 + nYSize * adfGeoTransform[2]));
-    dfMaxLong = 
+    dfMaxLong =
         MAX(MAX(adfGeoTransform[0] + 0 * adfGeoTransform[1]
                 + 0 * adfGeoTransform[2],
                 adfGeoTransform[0] + nXSize * adfGeoTransform[1]
@@ -1064,7 +1063,7 @@ static CPLString InsertCenterLong( GDALDatasetH hDS, CPLString osWKT )
     poExt  = new OGR_SRSNode( "EXTENSION" );
     poExt->AddChild( new OGR_SRSNode( "CENTER_LONG" ) );
     poExt->AddChild( new OGR_SRSNode( CPLString().Printf("%g",dfCenterLong) ));
-    
+
     oSRS.GetRoot()->AddChild( poExt->Clone() );
     delete poExt;
 
@@ -1073,7 +1072,7 @@ static CPLString InsertCenterLong( GDALDatasetH hDS, CPLString osWKT )
 /* -------------------------------------------------------------------- */
     char *pszWKT = NULL;
     oSRS.exportToWkt( &pszWKT );
-    
+
     osWKT = pszWKT;
     CPLFree( pszWKT );
 
@@ -1089,7 +1088,7 @@ static GDALGenImgProjTransformInfo* GDALCreateGenImgProjTransformerInternal()
 /* -------------------------------------------------------------------- */
 /*      Initialize the transform info.                                  */
 /* -------------------------------------------------------------------- */
-    GDALGenImgProjTransformInfo* psInfo = (GDALGenImgProjTransformInfo *) 
+    GDALGenImgProjTransformInfo* psInfo = (GDALGenImgProjTransformInfo *)
         CPLCalloc(sizeof(GDALGenImgProjTransformInfo),1);
 
     memcpy( psInfo->sTI.abySignature, GDAL_GTI2_SIGNATURE, strlen(GDAL_GTI2_SIGNATURE) );
@@ -1098,7 +1097,7 @@ static GDALGenImgProjTransformInfo* GDALCreateGenImgProjTransformerInternal()
     psInfo->sTI.pfnCleanup = GDALDestroyGenImgProjTransformer;
     psInfo->sTI.pfnSerialize = GDALSerializeGenImgProjTransformer;
     psInfo->sTI.pfnCreateSimilar = GDALCreateSimilarGenImgProjTransformer;
-    
+
     return psInfo;
 }
 
@@ -1111,65 +1110,65 @@ static GDALGenImgProjTransformInfo* GDALCreateGenImgProjTransformerInternal()
  *
  * This function creates a transformation object that maps from pixel/line
  * coordinates on one image to pixel/line coordinates on another image.  The
- * images may potentially be georeferenced in different coordinate systems, 
- * and may used GCPs to map between their pixel/line coordinates and 
+ * images may potentially be georeferenced in different coordinate systems,
+ * and may used GCPs to map between their pixel/line coordinates and
  * georeferenced coordinates (as opposed to the default assumption that their
- * geotransform should be used). 
+ * geotransform should be used).
  *
  * This transformer potentially performs three concatenated transformations.
  *
  * The first stage is from source image pixel/line coordinates to source
- * image georeferenced coordinates, and may be done using the geotransform, 
+ * image georeferenced coordinates, and may be done using the geotransform,
  * or if not defined using a polynomial model derived from GCPs.  If GCPs
- * are used this stage is accomplished using GDALGCPTransform(). 
+ * are used this stage is accomplished using GDALGCPTransform().
  *
  * The second stage is to change projections from the source coordinate system
- * to the destination coordinate system, assuming they differ.  This is 
+ * to the destination coordinate system, assuming they differ.  This is
  * accomplished internally using GDALReprojectionTransform().
  *
  * The third stage is converting from destination image georeferenced
  * coordinates to destination image coordinates.  This is done using the
- * destination image geotransform, or if not available, using a polynomial 
- * model derived from GCPs. If GCPs are used this stage is accomplished using 
+ * destination image geotransform, or if not available, using a polynomial
+ * model derived from GCPs. If GCPs are used this stage is accomplished using
  * GDALGCPTransform().  This stage is skipped if hDstDS is NULL when the
- * transformation is created. 
+ * transformation is created.
  *
  * Supported Options:
  * <ul>
  * <li> SRC_SRS: WKT SRS to be used as an override for hSrcDS.
  * <li> DST_SRS: WKT SRS to be used as an override for hDstDS.
- * <li> GCPS_OK: If false, GCPs will not be used, default is TRUE. 
+ * <li> GCPS_OK: If false, GCPs will not be used, default is TRUE.
  * <li> REFINE_MINIMUM_GCPS: The minimum amount of GCPs that should be available after the refinement.
- * <li> REFINE_TOLERANCE: The tolernace that specifies when a GCP will be eliminated.
+ * <li> REFINE_TOLERANCE: The tolerance that specifies when a GCP will be eliminated.
  * <li> MAX_GCP_ORDER: the maximum order to use for GCP derived polynomials if
- * possible.  The default is to autoselect based on the number of GCPs.  
+ * possible.  The default is to autoselect based on the number of GCPs.
  * A value of -1 triggers use of Thin Plate Spline instead of polynomials.
- * <li> SRC_METHOD: may have a value which is one of GEOTRANSFORM, 
- * GCP_POLYNOMIAL, GCP_TPS, GEOLOC_ARRAY, RPC to force only one geolocation 
- * method to be considered on the source dataset. Will be used for pixel/line 
+ * <li> SRC_METHOD: may have a value which is one of GEOTRANSFORM,
+ * GCP_POLYNOMIAL, GCP_TPS, GEOLOC_ARRAY, RPC to force only one geolocation
+ * method to be considered on the source dataset. Will be used for pixel/line
  * to georef transformation on the source dataset.
- * <li> DST_METHOD: may have a value which is one of GEOTRANSFORM, 
- * GCP_POLYNOMIAL, GCP_TPS, GEOLOC_ARRAY, RPC to force only one geolocation 
- * method to be considered on the target dataset.  Will be used for pixel/line 
+ * <li> DST_METHOD: may have a value which is one of GEOTRANSFORM,
+ * GCP_POLYNOMIAL, GCP_TPS, GEOLOC_ARRAY, RPC to force only one geolocation
+ * method to be considered on the target dataset.  Will be used for pixel/line
  * to georef transformation on the destination dataset.
  * <li> RPC_HEIGHT: A fixed height to be used with RPC calculations.
  * <li> RPC_DEM: The name of a DEM file to be used with RPC calculations.
  * <li> Other RPC related options. See GDALCreateRPCTransformer()
- * <li> INSERT_CENTER_LONG: May be set to FALSE to disable setting up a 
+ * <li> INSERT_CENTER_LONG: May be set to FALSE to disable setting up a
  * CENTER_LONG value on the coordinate system to rewrap things around the
- * center of the image.  
+ * center of the image.
  * </ul>
- * 
+ *
  * @param hSrcDS source dataset, or NULL.
  * @param hDstDS destination dataset (or NULL).
  * @param papszOptions NULL-terminated list of string options (or NULL).
- * 
+ *
  * @return handle suitable for use GDALGenImgProjTransform(), and to be
  * deallocated with GDALDestroyGenImgProjTransformer() or NULL on failure.
  */
 
 void *
-GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS, 
+GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
                                   char **papszOptions )
 
 {
@@ -1191,7 +1190,7 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
 
     pszValue = CSLFetchNameValue( papszOptions, "GCPS_OK" );
     if( pszValue )
-        bGCPUseOK = CSLTestBoolean(pszValue);
+        bGCPUseOK = CPLTestBool(pszValue);
 
     pszValue = CSLFetchNameValue( papszOptions, "REFINE_MINIMUM_GCPS" );
     if( pszValue )
@@ -1228,7 +1227,7 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
     }
 
     else if( (pszMethod == NULL || EQUAL(pszMethod,"GEOTRANSFORM"))
-             && GDALGetGeoTransform( hSrcDS, psInfo->adfSrcGeoTransform ) 
+             && GDALGetGeoTransform( hSrcDS, psInfo->adfSrcGeoTransform )
              == CE_None
              && (psInfo->adfSrcGeoTransform[0] != 0.0
                  || psInfo->adfSrcGeoTransform[1] != 1.0
@@ -1237,7 +1236,7 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
                  || psInfo->adfSrcGeoTransform[4] != 0.0
                  || ABS(psInfo->adfSrcGeoTransform[5]) != 1.0) )
     {
-        if( !GDALInvGeoTransform( psInfo->adfSrcGeoTransform, 
+        if( !GDALInvGeoTransform( psInfo->adfSrcGeoTransform,
                                   psInfo->adfSrcInvGeoTransform ) )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Cannot invert geotransform");
@@ -1248,22 +1247,22 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
             pszSrcWKT = GDALGetProjectionRef( hSrcDS );
     }
 
-    else if( bGCPUseOK 
+    else if( bGCPUseOK
              && (pszMethod == NULL || EQUAL(pszMethod,"GCP_POLYNOMIAL") )
              && GDALGetGCPCount( hSrcDS ) > 0 && nOrder >= 0 )
     {
         if(bRefine)
         {
-                psInfo->pSrcGCPTransformArg = 
+                psInfo->pSrcGCPTransformArg =
                     GDALCreateGCPRefineTransformer( GDALGetGCPCount( hSrcDS ),
-                                                    GDALGetGCPs( hSrcDS ), nOrder, 
+                                                    GDALGetGCPs( hSrcDS ), nOrder,
                                                     FALSE, dfTolerance, nMinimumGcps );
         }
         else
         {
-            psInfo->pSrcGCPTransformArg = 
+            psInfo->pSrcGCPTransformArg =
                 GDALCreateGCPTransformer( GDALGetGCPCount( hSrcDS ),
-                                          GDALGetGCPs( hSrcDS ), nOrder, 
+                                          GDALGetGCPs( hSrcDS ), nOrder,
                                           FALSE );
         }
 
@@ -1277,12 +1276,12 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
             pszSrcWKT = GDALGetGCPProjection( hSrcDS );
     }
 
-    else if( bGCPUseOK 
-             && GDALGetGCPCount( hSrcDS ) > 0 
+    else if( bGCPUseOK
+             && GDALGetGCPCount( hSrcDS ) > 0
              && nOrder <= 0
              && (pszMethod == NULL || EQUAL(pszMethod,"GCP_TPS")) )
     {
-        psInfo->pSrcTPSTransformArg = 
+        psInfo->pSrcTPSTransformArg =
             GDALCreateTPSTransformerInt( GDALGetGCPCount( hSrcDS ),
                                          GDALGetGCPs( hSrcDS ), FALSE,
                                          papszOptions);
@@ -1300,8 +1299,8 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
              && (papszMD = GDALGetMetadata( hSrcDS, "RPC" )) != NULL
              && GDALExtractRPCInfo( papszMD, &sRPCInfo ) )
     {
-        psInfo->pSrcRPCTransformArg = 
-            GDALCreateRPCTransformer( &sRPCInfo, FALSE, 0.1, papszOptions );
+        psInfo->pSrcRPCTransformArg =
+            GDALCreateRPCTransformer( &sRPCInfo, FALSE, 0, papszOptions );
         if( psInfo->pSrcRPCTransformArg == NULL )
         {
             GDALDestroyGenImgProjTransformer( psInfo );
@@ -1314,7 +1313,7 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
     else if( (pszMethod == NULL || EQUAL(pszMethod,"GEOLOC_ARRAY"))
              && (papszMD = GDALGetMetadata( hSrcDS, "GEOLOCATION" )) != NULL )
     {
-        psInfo->pSrcGeoLocTransformArg = 
+        psInfo->pSrcGeoLocTransformArg =
             GDALCreateGeoLocTransformer( hSrcDS, papszMD, FALSE );
 
         if( psInfo->pSrcGeoLocTransformArg == NULL )
@@ -1328,9 +1327,9 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
 
     else if( pszMethod != NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to compute a %s based transformation between pixel/line\n"
-                  "and georeferenced coordinates for %s.\n", 
+                  "and georeferenced coordinates for %s.\n",
                   pszMethod, GDALGetDescription( hSrcDS ) );
 
         GDALDestroyGenImgProjTransformer( psInfo );
@@ -1339,11 +1338,12 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
 
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Unable to compute a transformation between pixel/line\n"
-                  "and georeferenced coordinates for %s.\n"
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "The transformation is already \"north up\" or\n"
+                  "a transformation between pixel/line and georeferenced\n"
+                  "coordinates cannot be computed for %s.\n"
                   "There is no affine transformation and no GCPs.\n"
-                  "Specify transformation option SRC_METHOD=NO_GEOTRANSFORM to bypass this check.", 
+                  "Specify transformation option SRC_METHOD=NO_GEOTRANSFORM to bypass this check.",
                   GDALGetDescription( hSrcDS ) );
 
         GDALDestroyGenImgProjTransformer( psInfo );
@@ -1373,7 +1373,7 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
         if( pszDstWKT == NULL )
             pszDstWKT = GDALGetProjectionRef( hDstDS );
 
-        if( !GDALInvGeoTransform( psInfo->adfDstGeoTransform, 
+        if( !GDALInvGeoTransform( psInfo->adfDstGeoTransform,
                                   psInfo->adfDstInvGeoTransform ) )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Cannot invert geotransform");
@@ -1381,23 +1381,23 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
             return NULL;
         }
     }
-    else if( bGCPUseOK 
+    else if( bGCPUseOK
              && (pszDstMethod == NULL || EQUAL(pszDstMethod,"GCP_POLYNOMIAL") )
              && GDALGetGCPCount( hDstDS ) > 0 && nOrder >= 0 )
     {
         if(bRefine)
         {
-            psInfo->pDstGCPTransformArg = 
+            psInfo->pDstGCPTransformArg =
                 GDALCreateGCPRefineTransformer( GDALGetGCPCount( hDstDS ),
-                                                GDALGetGCPs( hDstDS ), nOrder, 
-                                                FALSE, dfTolerance, 
+                                                GDALGetGCPs( hDstDS ), nOrder,
+                                                FALSE, dfTolerance,
                                                 nMinimumGcps );
         }
         else
         {
-            psInfo->pDstGCPTransformArg = 
+            psInfo->pDstGCPTransformArg =
                 GDALCreateGCPTransformer( GDALGetGCPCount( hDstDS ),
-                                          GDALGetGCPs( hDstDS ), nOrder, 
+                                          GDALGetGCPs( hDstDS ), nOrder,
                                           FALSE );
         }
 
@@ -1410,12 +1410,12 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
         if( pszDstWKT == NULL )
             pszDstWKT = GDALGetGCPProjection( hDstDS );
     }
-    else if( bGCPUseOK 
-             && GDALGetGCPCount( hDstDS ) > 0 
+    else if( bGCPUseOK
+             && GDALGetGCPCount( hDstDS ) > 0
              && nOrder <= 0
              && (pszDstMethod == NULL || EQUAL(pszDstMethod,"GCP_TPS")) )
     {
-        psInfo->pDstTPSTransformArg = 
+        psInfo->pDstTPSTransformArg =
             GDALCreateTPSTransformerInt( GDALGetGCPCount( hDstDS ),
                                          GDALGetGCPs( hDstDS ), FALSE,
                                          papszOptions );
@@ -1432,8 +1432,8 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
              && (papszMD = GDALGetMetadata( hDstDS, "RPC" )) != NULL
              && GDALExtractRPCInfo( papszMD, &sRPCInfo ) )
     {
-        psInfo->pDstRPCTransformArg = 
-            GDALCreateRPCTransformer( &sRPCInfo, FALSE, 0.1, papszOptions );
+        psInfo->pDstRPCTransformArg =
+            GDALCreateRPCTransformer( &sRPCInfo, FALSE, 0, papszOptions );
         if( psInfo->pDstRPCTransformArg == NULL )
         {
             GDALDestroyGenImgProjTransformer( psInfo );
@@ -1445,29 +1445,29 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
 
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to compute a transformation between pixel/line\n"
                   "and georeferenced coordinates for %s.\n"
-                  "There is no affine transformation and no GCPs.", 
+                  "There is no affine transformation and no GCPs.",
                   GDALGetDescription( hDstDS ) );
 
         GDALDestroyGenImgProjTransformer( psInfo );
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Setup reprojection.                                             */
 /* -------------------------------------------------------------------- */
-    if( pszSrcWKT != NULL && strlen(pszSrcWKT) > 0 
-        && pszDstWKT != NULL && strlen(pszDstWKT) > 0 
+    if( pszSrcWKT != NULL && strlen(pszSrcWKT) > 0
+        && pszDstWKT != NULL && strlen(pszDstWKT) > 0
         && !EQUAL(pszSrcWKT,pszDstWKT) )
     {
         CPLString osSrcWKT = pszSrcWKT;
-        if (hSrcDS 
+        if (hSrcDS
             && CSLFetchBoolean( papszOptions, "INSERT_CENTER_LONG", TRUE ) )
             osSrcWKT = InsertCenterLong( hSrcDS, osSrcWKT );
-        
-        psInfo->pReprojectArg = 
+
+        psInfo->pReprojectArg =
             GDALCreateReprojectionTransformer( osSrcWKT.c_str(), pszDstWKT );
         if( psInfo->pReprojectArg == NULL )
         {
@@ -1475,7 +1475,7 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
             return NULL;
         }
     }
-        
+
     return psInfo;
 }
 
@@ -1506,34 +1506,34 @@ void GDALRefreshGenImgProjTransformer(void* hTransformArg)
  *
  * This function creates a transformation object that maps from pixel/line
  * coordinates on one image to pixel/line coordinates on another image.  The
- * images may potentially be georeferenced in different coordinate systems, 
- * and may used GCPs to map between their pixel/line coordinates and 
+ * images may potentially be georeferenced in different coordinate systems,
+ * and may used GCPs to map between their pixel/line coordinates and
  * georeferenced coordinates (as opposed to the default assumption that their
- * geotransform should be used). 
+ * geotransform should be used).
  *
  * This transformer potentially performs three concatenated transformations.
  *
  * The first stage is from source image pixel/line coordinates to source
- * image georeferenced coordinates, and may be done using the geotransform, 
+ * image georeferenced coordinates, and may be done using the geotransform,
  * or if not defined using a polynomial model derived from GCPs.  If GCPs
- * are used this stage is accomplished using GDALGCPTransform(). 
+ * are used this stage is accomplished using GDALGCPTransform().
  *
  * The second stage is to change projections from the source coordinate system
- * to the destination coordinate system, assuming they differ.  This is 
+ * to the destination coordinate system, assuming they differ.  This is
  * accomplished internally using GDALReprojectionTransform().
  *
  * The third stage is converting from destination image georeferenced
  * coordinates to destination image coordinates.  This is done using the
- * destination image geotransform, or if not available, using a polynomial 
- * model derived from GCPs. If GCPs are used this stage is accomplished using 
+ * destination image geotransform, or if not available, using a polynomial
+ * model derived from GCPs. If GCPs are used this stage is accomplished using
  * GDALGCPTransform().  This stage is skipped if hDstDS is NULL when the
- * transformation is created. 
+ * transformation is created.
  *
  * @param pszSrcWKT source WKT (or NULL).
  * @param padfSrcGeoTransform source geotransform (or NULL).
  * @param pszDstWKT destination WKT (or NULL).
  * @param padfDstGeoTransform destination geotransform (or NULL).
- * 
+ *
  * @return handle suitable for use GDALGenImgProjTransform(), and to be
  * deallocated with GDALDestroyGenImgProjTransformer() or NULL on failure.
  */
@@ -1551,7 +1551,7 @@ GDALCreateGenImgProjTransformer3( const char *pszSrcWKT,
 /*      Initialize the transform info.                                  */
 /* -------------------------------------------------------------------- */
     psInfo = GDALCreateGenImgProjTransformerInternal();
-    
+
 /* -------------------------------------------------------------------- */
 /*      Get forward and inverse geotransform for the source image.      */
 /* -------------------------------------------------------------------- */
@@ -1559,7 +1559,7 @@ GDALCreateGenImgProjTransformer3( const char *pszSrcWKT,
     {
         memcpy( psInfo->adfSrcGeoTransform, padfSrcGeoTransform,
                 sizeof(psInfo->adfSrcGeoTransform) );
-        if( !GDALInvGeoTransform( psInfo->adfSrcGeoTransform, 
+        if( !GDALInvGeoTransform( psInfo->adfSrcGeoTransform,
                                   psInfo->adfSrcInvGeoTransform ) )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Cannot invert geotransform");
@@ -1582,11 +1582,11 @@ GDALCreateGenImgProjTransformer3( const char *pszSrcWKT,
 /* -------------------------------------------------------------------- */
 /*      Setup reprojection.                                             */
 /* -------------------------------------------------------------------- */
-    if( pszSrcWKT != NULL && strlen(pszSrcWKT) > 0 
-        && pszDstWKT != NULL && strlen(pszDstWKT) > 0 
+    if( pszSrcWKT != NULL && strlen(pszSrcWKT) > 0
+        && pszDstWKT != NULL && strlen(pszDstWKT) > 0
         && !EQUAL(pszSrcWKT, pszDstWKT) )
     {
-        psInfo->pReprojectArg = 
+        psInfo->pReprojectArg =
             GDALCreateReprojectionTransformer( pszSrcWKT, pszDstWKT );
         if( psInfo->pReprojectArg == NULL )
         {
@@ -1594,7 +1594,7 @@ GDALCreateGenImgProjTransformer3( const char *pszSrcWKT,
             return NULL;
         }
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Get forward and inverse geotransform for destination image.     */
 /*      If we have no destination matrix use a unit transform.          */
@@ -1603,7 +1603,7 @@ GDALCreateGenImgProjTransformer3( const char *pszSrcWKT,
     {
         memcpy( psInfo->adfDstGeoTransform, padfDstGeoTransform,
                 sizeof(psInfo->adfDstGeoTransform) );
-        if( !GDALInvGeoTransform( psInfo->adfDstGeoTransform, 
+        if( !GDALInvGeoTransform( psInfo->adfDstGeoTransform,
                                   psInfo->adfDstInvGeoTransform ) )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Cannot invert geotransform");
@@ -1622,7 +1622,7 @@ GDALCreateGenImgProjTransformer3( const char *pszSrcWKT,
         memcpy( psInfo->adfDstInvGeoTransform, psInfo->adfDstGeoTransform,
                 sizeof(double) * 6 );
     }
-    
+
     return psInfo;
 }
 
@@ -1633,30 +1633,30 @@ GDALCreateGenImgProjTransformer3( const char *pszSrcWKT,
 /**
  * Set GenImgProj output geotransform.
  *
- * Normally the "destination geotransform", or transformation between 
+ * Normally the "destination geotransform", or transformation between
  * georeferenced output coordinates and pixel/line coordinates on the
- * destination file is extracted from the destination file by 
+ * destination file is extracted from the destination file by
  * GDALCreateGenImgProjTransformer() and stored in the GenImgProj private
  * info.  However, sometimes it is inconvenient to have an output file
  * handle with appropriate geotransform information when creating the
  * transformation.  For these cases, this function can be used to apply
- * the destination geotransform. 
+ * the destination geotransform.
  *
  * @param hTransformArg the handle to update.
  * @param padfGeoTransform the destination geotransform to apply (six doubles).
  */
 
-void GDALSetGenImgProjTransformerDstGeoTransform( 
+void GDALSetGenImgProjTransformerDstGeoTransform(
     void *hTransformArg, const double *padfGeoTransform )
 
 {
     VALIDATE_POINTER0( hTransformArg, "GDALSetGenImgProjTransformerDstGeoTransform" );
 
-    GDALGenImgProjTransformInfo *psInfo = 
+    GDALGenImgProjTransformInfo *psInfo =
         static_cast<GDALGenImgProjTransformInfo *>( hTransformArg );
 
     memcpy( psInfo->adfDstGeoTransform, padfGeoTransform, sizeof(double) * 6 );
-    if( !GDALInvGeoTransform( psInfo->adfDstGeoTransform, 
+    if( !GDALInvGeoTransform( psInfo->adfDstGeoTransform,
                               psInfo->adfDstInvGeoTransform ) )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Cannot invert geotransform");
@@ -1673,7 +1673,7 @@ void GDALSetGenImgProjTransformerDstGeoTransform(
  * This function is used to deallocate the handle created with
  * GDALCreateGenImgProjTransformer().
  *
- * @param hTransformArg the handle to deallocate. 
+ * @param hTransformArg the handle to deallocate.
  */
 
 void GDALDestroyGenImgProjTransformer( void *hTransformArg )
@@ -1682,7 +1682,7 @@ void GDALDestroyGenImgProjTransformer( void *hTransformArg )
     if( hTransformArg == NULL )
         return;
 
-    GDALGenImgProjTransformInfo *psInfo = 
+    GDALGenImgProjTransformInfo *psInfo =
         (GDALGenImgProjTransformInfo *) hTransformArg;
 
     if( psInfo->pSrcGCPTransformArg != NULL )
@@ -1719,22 +1719,22 @@ void GDALDestroyGenImgProjTransformer( void *hTransformArg )
 /**
  * Perform general image reprojection transformation.
  *
- * Actually performs the transformation setup in 
+ * Actually performs the transformation setup in
  * GDALCreateGenImgProjTransformer().  This function matches the signature
  * required by the GDALTransformerFunc(), and more details on the arguments
- * can be found in that topic. 
+ * can be found in that topic.
  */
 
 #ifdef DEBUG_APPROX_TRANSFORMER
 int countGDALGenImgProjTransform = 0;
 #endif
 
-int GDALGenImgProjTransform( void *pTransformArg, int bDstToSrc, 
-                             int nPointCount, 
+int GDALGenImgProjTransform( void *pTransformArg, int bDstToSrc,
+                             int nPointCount,
                              double *padfX, double *padfY, double *padfZ,
                              int *panSuccess )
 {
-    GDALGenImgProjTransformInfo *psInfo = 
+    GDALGenImgProjTransformInfo *psInfo =
         (GDALGenImgProjTransformInfo *) pTransformArg;
     int   i;
     double *padfGeoTransform;
@@ -1776,38 +1776,38 @@ int GDALGenImgProjTransform( void *pTransformArg, int bDstToSrc,
 
     if( pGCPTransformArg != NULL )
     {
-        if( !GDALGCPTransform( pGCPTransformArg, FALSE, 
+        if( !GDALGCPTransform( pGCPTransformArg, FALSE,
                                nPointCount, padfX, padfY, padfZ,
                                panSuccess ) )
             return FALSE;
     }
     else if( pTPSTransformArg != NULL )
     {
-        if( !GDALTPSTransform( pTPSTransformArg, FALSE, 
+        if( !GDALTPSTransform( pTPSTransformArg, FALSE,
                                nPointCount, padfX, padfY, padfZ,
                                panSuccess ) )
             return FALSE;
     }
     else if( pRPCTransformArg != NULL )
     {
-        if( !GDALRPCTransform( pRPCTransformArg, FALSE, 
+        if( !GDALRPCTransform( pRPCTransformArg, FALSE,
                                nPointCount, padfX, padfY, padfZ,
                                panSuccess ) )
             return FALSE;
     }
     else if( pGeoLocTransformArg != NULL )
     {
-        if( !GDALGeoLocTransform( pGeoLocTransformArg, FALSE, 
+        if( !GDALGeoLocTransform( pGeoLocTransformArg, FALSE,
                                   nPointCount, padfX, padfY, padfZ,
                                   panSuccess ) )
             return FALSE;
     }
-    else 
+    else
     {
         for( i = 0; i < nPointCount; i++ )
         {
             double dfNewX, dfNewY;
-            
+
             if( padfX[i] == HUGE_VAL || padfY[i] == HUGE_VAL )
             {
                 panSuccess[i] = FALSE;
@@ -1820,7 +1820,7 @@ int GDALGenImgProjTransform( void *pTransformArg, int bDstToSrc,
             dfNewY = padfGeoTransform[3]
                 + padfX[i] * padfGeoTransform[4]
                 + padfY[i] * padfGeoTransform[5];
-            
+
             padfX[i] = dfNewX;
             padfY[i] = dfNewY;
         }
@@ -1831,7 +1831,7 @@ int GDALGenImgProjTransform( void *pTransformArg, int bDstToSrc,
 /* -------------------------------------------------------------------- */
     if( psInfo->pReprojectArg )
     {
-        if( !GDALReprojectionTransform( psInfo->pReprojectArg, bDstToSrc, 
+        if( !GDALReprojectionTransform( psInfo->pReprojectArg, bDstToSrc,
                                         nPointCount, padfX, padfY, padfZ,
                                         panSuccess ) )
             return FALSE;
@@ -1856,7 +1856,7 @@ int GDALGenImgProjTransform( void *pTransformArg, int bDstToSrc,
         pTPSTransformArg = psInfo->pDstTPSTransformArg;
         pGeoLocTransformArg = NULL;
     }
-        
+
     if( pGCPTransformArg != NULL )
     {
         if( !GDALGCPTransform( pGCPTransformArg, TRUE,
@@ -1893,19 +1893,19 @@ int GDALGenImgProjTransform( void *pTransformArg, int bDstToSrc,
 
             if( !panSuccess[i] )
                 continue;
-            
+
             dfNewX = padfGeoTransform[0]
                 + padfX[i] * padfGeoTransform[1]
                 + padfY[i] * padfGeoTransform[2];
             dfNewY = padfGeoTransform[3]
                 + padfX[i] * padfGeoTransform[4]
                 + padfY[i] * padfGeoTransform[5];
-            
+
             padfX[i] = dfNewX;
             padfY[i] = dfNewY;
         }
     }
-        
+
     return TRUE;
 }
 
@@ -1919,7 +1919,7 @@ GDALSerializeGenImgProjTransformer( void *pTransformArg )
 {
     char szWork[200];
     CPLXMLNode *psTree;
-    GDALGenImgProjTransformInfo *psInfo = 
+    GDALGenImgProjTransformInfo *psInfo =
         (GDALGenImgProjTransformInfo *) pTransformArg;
 
     psTree = CPLCreateXMLNode( NULL, CXT_Element, "GenImgProjTransformer" );
@@ -1929,14 +1929,13 @@ GDALSerializeGenImgProjTransformer( void *pTransformArg )
 /* -------------------------------------------------------------------- */
     if( psInfo->pSrcGCPTransformArg != NULL )
     {
-        CPLXMLNode *psTransformerContainer;
-        CPLXMLNode *psTransformer;
 
-        psTransformerContainer = 
+        CPLXMLNode *psTransformerContainer =
             CPLCreateXMLNode( psTree, CXT_Element, "SrcGCPTransformer" );
 
-        psTransformer = GDALSerializeTransformer( GDALGCPTransform,
-                                                  psInfo->pSrcGCPTransformArg);
+        CPLXMLNode *psTransformer
+            = GDALSerializeTransformer( GDALGCPTransform,
+                                        psInfo->pSrcGCPTransformArg);
         if( psTransformer != NULL )
             CPLAddXMLChild( psTransformerContainer, psTransformer );
     }
@@ -1946,14 +1945,11 @@ GDALSerializeGenImgProjTransformer( void *pTransformArg )
 /* -------------------------------------------------------------------- */
     else if( psInfo->pSrcTPSTransformArg != NULL )
     {
-        CPLXMLNode *psTransformerContainer;
-        CPLXMLNode *psTransformer;
+        CPLXMLNode *psTransformerContainer
+            = CPLCreateXMLNode( psTree, CXT_Element, "SrcTPSTransformer" );
 
-        psTransformerContainer = 
-            CPLCreateXMLNode( psTree, CXT_Element, "SrcTPSTransformer" );
-
-        psTransformer = 
-            GDALSerializeTransformer( NULL, psInfo->pSrcTPSTransformArg);
+        CPLXMLNode *psTransformer
+            = GDALSerializeTransformer( NULL, psInfo->pSrcTPSTransformArg);
         if( psTransformer != NULL )
             CPLAddXMLChild( psTransformerContainer, psTransformer );
     }
@@ -1963,14 +1959,11 @@ GDALSerializeGenImgProjTransformer( void *pTransformArg )
 /* -------------------------------------------------------------------- */
     else if( psInfo->pSrcGeoLocTransformArg != NULL )
     {
-        CPLXMLNode *psTransformerContainer;
-        CPLXMLNode *psTransformer;
-
-        psTransformerContainer = 
-            CPLCreateXMLNode( psTree, CXT_Element, "SrcGeoLocTransformer" );
+        CPLXMLNode *psTransformerContainer
+            = CPLCreateXMLNode( psTree, CXT_Element, "SrcGeoLocTransformer" );
 
-        psTransformer = 
-            GDALSerializeTransformer( NULL, psInfo->pSrcGeoLocTransformArg);
+        CPLXMLNode *psTransformer
+            = GDALSerializeTransformer( NULL, psInfo->pSrcGeoLocTransformArg);
         if( psTransformer != NULL )
             CPLAddXMLChild( psTransformerContainer, psTransformer );
     }
@@ -1980,14 +1973,11 @@ GDALSerializeGenImgProjTransformer( void *pTransformArg )
 /* -------------------------------------------------------------------- */
     else if( psInfo->pSrcRPCTransformArg != NULL )
     {
-        CPLXMLNode *psTransformerContainer;
-        CPLXMLNode *psTransformer;
-
-        psTransformerContainer = 
-            CPLCreateXMLNode( psTree, CXT_Element, "SrcRPCTransformer" );
+        CPLXMLNode *psTransformerContainer
+            = CPLCreateXMLNode( psTree, CXT_Element, "SrcRPCTransformer" );
 
-        psTransformer = 
-            GDALSerializeTransformer( NULL, psInfo->pSrcRPCTransformArg);
+        CPLXMLNode *psTransformer
+            = GDALSerializeTransformer( NULL, psInfo->pSrcRPCTransformArg);
         if( psTransformer != NULL )
             CPLAddXMLChild( psTransformerContainer, psTransformer );
     }
@@ -1997,7 +1987,7 @@ GDALSerializeGenImgProjTransformer( void *pTransformArg )
 /* -------------------------------------------------------------------- */
     else
     {
-        CPLsprintf( szWork, "%.18g,%.18g,%.18g,%.18g,%.18g,%.18g",
+        CPLsnprintf( szWork, sizeof(szWork), "%.18g,%.18g,%.18g,%.18g,%.18g,%.18g",
                  psInfo->adfSrcGeoTransform[0],
                  psInfo->adfSrcGeoTransform[1],
                  psInfo->adfSrcGeoTransform[2],
@@ -2005,8 +1995,8 @@ GDALSerializeGenImgProjTransformer( void *pTransformArg )
                  psInfo->adfSrcGeoTransform[4],
                  psInfo->adfSrcGeoTransform[5] );
         CPLCreateXMLElementAndValue( psTree, "SrcGeoTransform", szWork );
-        
-        CPLsprintf( szWork, "%.18g,%.18g,%.18g,%.18g,%.18g,%.18g",
+
+        CPLsnprintf( szWork, sizeof(szWork), "%.18g,%.18g,%.18g,%.18g,%.18g,%.18g",
                  psInfo->adfSrcInvGeoTransform[0],
                  psInfo->adfSrcInvGeoTransform[1],
                  psInfo->adfSrcInvGeoTransform[2],
@@ -2015,20 +2005,18 @@ GDALSerializeGenImgProjTransformer( void *pTransformArg )
                  psInfo->adfSrcInvGeoTransform[5] );
         CPLCreateXMLElementAndValue( psTree, "SrcInvGeoTransform", szWork );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Handle Dest GCP transformation.                                 */
 /* -------------------------------------------------------------------- */
     if( psInfo->pDstGCPTransformArg != NULL )
     {
-        CPLXMLNode *psTransformerContainer;
-        CPLXMLNode *psTransformer;
-
-        psTransformerContainer = 
-            CPLCreateXMLNode( psTree, CXT_Element, "DstGCPTransformer" );
+        CPLXMLNode *psTransformerContainer
+            = CPLCreateXMLNode( psTree, CXT_Element, "DstGCPTransformer" );
 
-        psTransformer = GDALSerializeTransformer( GDALGCPTransform,
-                                                  psInfo->pDstGCPTransformArg);
+        CPLXMLNode *psTransformer
+            = GDALSerializeTransformer( GDALGCPTransform,
+                                        psInfo->pDstGCPTransformArg);
         if( psTransformer != NULL )
             CPLAddXMLChild( psTransformerContainer, psTransformer );
     }
@@ -2038,14 +2026,11 @@ GDALSerializeGenImgProjTransformer( void *pTransformArg )
 /* -------------------------------------------------------------------- */
     else if( psInfo->pDstTPSTransformArg != NULL )
     {
-        CPLXMLNode *psTransformerContainer;
-        CPLXMLNode *psTransformer;
+        CPLXMLNode *psTransformerContainer
+            = CPLCreateXMLNode( psTree, CXT_Element, "DstTPSTransformer" );
 
-        psTransformerContainer = 
-            CPLCreateXMLNode( psTree, CXT_Element, "DstTPSTransformer" );
-
-        psTransformer = 
-            GDALSerializeTransformer( NULL, psInfo->pDstTPSTransformArg);
+        CPLXMLNode *psTransformer
+            = GDALSerializeTransformer( NULL, psInfo->pDstTPSTransformArg);
         if( psTransformer != NULL )
             CPLAddXMLChild( psTransformerContainer, psTransformer );
     }
@@ -2055,14 +2040,11 @@ GDALSerializeGenImgProjTransformer( void *pTransformArg )
 /* -------------------------------------------------------------------- */
     else if( psInfo->pDstRPCTransformArg != NULL )
     {
-        CPLXMLNode *psTransformerContainer;
-        CPLXMLNode *psTransformer;
-
-        psTransformerContainer = 
-            CPLCreateXMLNode( psTree, CXT_Element, "DstRPCTransformer" );
+        CPLXMLNode *psTransformerContainer
+            = CPLCreateXMLNode( psTree, CXT_Element, "DstRPCTransformer" );
 
-        psTransformer = 
-            GDALSerializeTransformer( NULL, psInfo->pDstRPCTransformArg);
+        CPLXMLNode *psTransformer
+            = GDALSerializeTransformer( NULL, psInfo->pDstRPCTransformArg);
         if( psTransformer != NULL )
             CPLAddXMLChild( psTransformerContainer, psTransformer );
     }
@@ -2072,7 +2054,7 @@ GDALSerializeGenImgProjTransformer( void *pTransformArg )
 /* -------------------------------------------------------------------- */
     else
     {
-        CPLsprintf( szWork, "%.18g,%.18g,%.18g,%.18g,%.18g,%.18g",
+        CPLsnprintf( szWork, sizeof(szWork), "%.18g,%.18g,%.18g,%.18g,%.18g,%.18g",
                  psInfo->adfDstGeoTransform[0],
                  psInfo->adfDstGeoTransform[1],
                  psInfo->adfDstGeoTransform[2],
@@ -2080,8 +2062,8 @@ GDALSerializeGenImgProjTransformer( void *pTransformArg )
                  psInfo->adfDstGeoTransform[4],
                  psInfo->adfDstGeoTransform[5] );
         CPLCreateXMLElementAndValue( psTree, "DstGeoTransform", szWork );
-        
-        CPLsprintf( szWork, "%.18g,%.18g,%.18g,%.18g,%.18g,%.18g",
+
+        CPLsnprintf( szWork, sizeof(szWork), "%.18g,%.18g,%.18g,%.18g,%.18g,%.18g",
                  psInfo->adfDstInvGeoTransform[0],
                  psInfo->adfDstInvGeoTransform[1],
                  psInfo->adfDstInvGeoTransform[2],
@@ -2096,18 +2078,17 @@ GDALSerializeGenImgProjTransformer( void *pTransformArg )
 /* -------------------------------------------------------------------- */
     if( psInfo->pReprojectArg != NULL )
     {
-        CPLXMLNode *psTransformerContainer;
-        CPLXMLNode *psTransformer;
 
-        psTransformerContainer = 
-            CPLCreateXMLNode( psTree, CXT_Element, "ReprojectTransformer" );
+        CPLXMLNode *psTransformerContainer
+            = CPLCreateXMLNode( psTree, CXT_Element, "ReprojectTransformer" );
 
-        psTransformer = GDALSerializeTransformer( GDALReprojectionTransform,
+        CPLXMLNode *psTransformer
+            = GDALSerializeTransformer( GDALReprojectionTransform,
                                                   psInfo->pReprojectArg );
         if( psTransformer != NULL )
             CPLAddXMLChild( psTransformerContainer, psTransformer );
     }
-    
+
     return psTree;
 }
 
@@ -2118,7 +2099,7 @@ GDALSerializeGenImgProjTransformer( void *pTransformArg )
 static void GDALDeserializeGeoTransform(const char* pszGT,
                                         double adfGeoTransform[6])
 {
-    CPLsscanf( pszGT, "%lf,%lf,%lf,%lf,%lf,%lf", 
+    CPLsscanf( pszGT, "%lf,%lf,%lf,%lf,%lf,%lf",
                adfGeoTransform + 0,
                adfGeoTransform + 1,
                adfGeoTransform + 2,
@@ -2134,25 +2115,25 @@ static void GDALDeserializeGeoTransform(const char* pszGT,
 void *GDALDeserializeGenImgProjTransformer( CPLXMLNode *psTree )
 
 {
-    GDALGenImgProjTransformInfo *psInfo;
     CPLXMLNode *psSubtree;
 
 /* -------------------------------------------------------------------- */
 /*      Initialize the transform info.                                  */
 /* -------------------------------------------------------------------- */
-    psInfo = GDALCreateGenImgProjTransformerInternal();
+    GDALGenImgProjTransformInfo *psInfo
+        = GDALCreateGenImgProjTransformerInternal();
 
 /* -------------------------------------------------------------------- */
 /*      SrcGeotransform                                                 */
 /* -------------------------------------------------------------------- */
     if( CPLGetXMLNode( psTree, "SrcGeoTransform" ) != NULL )
     {
-        GDALDeserializeGeoTransform( CPLGetXMLValue( psTree, "SrcGeoTransform", "" ), 
+        GDALDeserializeGeoTransform( CPLGetXMLValue( psTree, "SrcGeoTransform", "" ),
                                      psInfo->adfSrcGeoTransform );
 
         if( CPLGetXMLNode( psTree, "SrcInvGeoTransform" ) != NULL )
         {
-            GDALDeserializeGeoTransform( CPLGetXMLValue( psTree, "SrcInvGeoTransform", "" ), 
+            GDALDeserializeGeoTransform( CPLGetXMLValue( psTree, "SrcInvGeoTransform", "" ),
                                      psInfo->adfSrcInvGeoTransform );
         }
         else
@@ -2171,7 +2152,7 @@ void *GDALDeserializeGenImgProjTransformer( CPLXMLNode *psTree )
     psSubtree = CPLGetXMLNode( psTree, "SrcGCPTransformer" );
     if( psSubtree != NULL && psSubtree->psChild != NULL )
     {
-        psInfo->pSrcGCPTransformArg = 
+        psInfo->pSrcGCPTransformArg =
             GDALDeserializeGCPTransformer( psSubtree->psChild );
     }
 
@@ -2181,7 +2162,7 @@ void *GDALDeserializeGenImgProjTransformer( CPLXMLNode *psTree )
     psSubtree = CPLGetXMLNode( psTree, "SrcTPSTransformer" );
     if( psSubtree != NULL && psSubtree->psChild != NULL )
     {
-        psInfo->pSrcTPSTransformArg = 
+        psInfo->pSrcTPSTransformArg =
             GDALDeserializeTPSTransformer( psSubtree->psChild );
     }
 
@@ -2191,7 +2172,7 @@ void *GDALDeserializeGenImgProjTransformer( CPLXMLNode *psTree )
     psSubtree = CPLGetXMLNode( psTree, "SrcGeoLocTransformer" );
     if( psSubtree != NULL && psSubtree->psChild != NULL )
     {
-        psInfo->pSrcGeoLocTransformArg = 
+        psInfo->pSrcGeoLocTransformArg =
             GDALDeserializeGeoLocTransformer( psSubtree->psChild );
     }
 
@@ -2201,7 +2182,7 @@ void *GDALDeserializeGenImgProjTransformer( CPLXMLNode *psTree )
     psSubtree = CPLGetXMLNode( psTree, "SrcRPCTransformer" );
     if( psSubtree != NULL && psSubtree->psChild != NULL )
     {
-        psInfo->pSrcRPCTransformArg = 
+        psInfo->pSrcRPCTransformArg =
             GDALDeserializeRPCTransformer( psSubtree->psChild );
     }
 
@@ -2211,7 +2192,7 @@ void *GDALDeserializeGenImgProjTransformer( CPLXMLNode *psTree )
     psSubtree = CPLGetXMLNode( psTree, "DstTPSTransformer" );
     if( psSubtree != NULL && psSubtree->psChild != NULL )
     {
-        psInfo->pDstTPSTransformArg = 
+        psInfo->pDstTPSTransformArg =
             GDALDeserializeTPSTransformer( psSubtree->psChild );
     }
 
@@ -2221,7 +2202,7 @@ void *GDALDeserializeGenImgProjTransformer( CPLXMLNode *psTree )
     psSubtree = CPLGetXMLNode( psTree, "DstRPCTransformer" );
     if( psSubtree != NULL && psSubtree->psChild != NULL )
     {
-        psInfo->pDstRPCTransformArg = 
+        psInfo->pDstRPCTransformArg =
             GDALDeserializeRPCTransformer( psSubtree->psChild );
     }
 
@@ -2230,12 +2211,12 @@ void *GDALDeserializeGenImgProjTransformer( CPLXMLNode *psTree )
 /* -------------------------------------------------------------------- */
     if( CPLGetXMLNode( psTree, "DstGeoTransform" ) != NULL )
     {
-        GDALDeserializeGeoTransform( CPLGetXMLValue( psTree, "DstGeoTransform", "" ), 
+        GDALDeserializeGeoTransform( CPLGetXMLValue( psTree, "DstGeoTransform", "" ),
                                      psInfo->adfDstGeoTransform );
 
         if( CPLGetXMLNode( psTree, "DstInvGeoTransform" ) != NULL )
         {
-            GDALDeserializeGeoTransform( CPLGetXMLValue( psTree, "DstInvGeoTransform", "" ), 
+            GDALDeserializeGeoTransform( CPLGetXMLValue( psTree, "DstInvGeoTransform", "" ),
                                         psInfo->adfDstInvGeoTransform );
         }
         else
@@ -2247,14 +2228,14 @@ void *GDALDeserializeGenImgProjTransformer( CPLXMLNode *psTree )
             }
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Reproject transformer                                           */
 /* -------------------------------------------------------------------- */
     psSubtree = CPLGetXMLNode( psTree, "ReprojectTransformer" );
     if( psSubtree != NULL && psSubtree->psChild != NULL )
     {
-        psInfo->pReprojectArg = 
+        psInfo->pReprojectArg =
             GDALDeserializeReprojectionTransformer( psSubtree->psChild );
     }
 
@@ -2281,23 +2262,23 @@ typedef struct {
 /**
  * Create reprojection transformer.
  *
- * Creates a callback data structure suitable for use with 
+ * Creates a callback data structure suitable for use with
  * GDALReprojectionTransformation() to represent a transformation from
  * one geographic or projected coordinate system to another.  On input
- * the coordinate systems are described in OpenGIS WKT format. 
+ * the coordinate systems are described in OpenGIS WKT format.
  *
  * Internally the OGRCoordinateTransformation object is used to implement
  * the reprojection.
  *
  * @param pszSrcWKT the coordinate system for the source coordinate system.
- * @param pszDstWKT the coordinate system for the destination coordinate 
+ * @param pszDstWKT the coordinate system for the destination coordinate
  * system.
  *
- * @return Handle for use with GDALReprojectionTransform(), or NULL if the 
- * system fails to initialize the reprojection. 
+ * @return Handle for use with GDALReprojectionTransform(), or NULL if the
+ * system fails to initialize the reprojection.
  **/
 
-void *GDALCreateReprojectionTransformer( const char *pszSrcWKT, 
+void *GDALCreateReprojectionTransformer( const char *pszSrcWKT,
                                          const char *pszDstWKT )
 
 {
@@ -2309,15 +2290,15 @@ void *GDALCreateReprojectionTransformer( const char *pszSrcWKT,
 /* -------------------------------------------------------------------- */
     if( oSrcSRS.importFromWkt( (char **) &pszSrcWKT ) != OGRERR_NONE )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Failed to import coordinate system `%s'.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Failed to import coordinate system `%s'.",
                   pszSrcWKT );
         return NULL;
     }
     if( oDstSRS.importFromWkt( (char **) &pszDstWKT ) != OGRERR_NONE )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Failed to import coordinate system `%s'.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Failed to import coordinate system `%s'.",
                   pszSrcWKT );
         return NULL;
     }
@@ -2338,11 +2319,11 @@ void *GDALCreateReprojectionTransformer( const char *pszSrcWKT,
 /* -------------------------------------------------------------------- */
     GDALReprojectionTransformInfo *psInfo;
 
-    psInfo = (GDALReprojectionTransformInfo *) 
+    psInfo = (GDALReprojectionTransformInfo *)
         CPLCalloc(sizeof(GDALReprojectionTransformInfo),1);
 
     psInfo->poForwardTransform = poForwardTransform;
-    psInfo->poReverseTransform = 
+    psInfo->poReverseTransform =
         OGRCreateCoordinateTransformation(&oDstSRS,&oSrcSRS);
 
     memcpy( psInfo->sTI.abySignature, GDAL_GTI2_SIGNATURE, strlen(GDAL_GTI2_SIGNATURE) );
@@ -2371,8 +2352,8 @@ void GDALDestroyReprojectionTransformer( void *pTransformArg )
     if( pTransformArg == NULL )
         return;
 
-    GDALReprojectionTransformInfo *psInfo = 
-        (GDALReprojectionTransformInfo *) pTransformArg;		
+    GDALReprojectionTransformInfo *psInfo =
+        (GDALReprojectionTransformInfo *) pTransformArg;
 
     if( psInfo->poForwardTransform )
         delete psInfo->poForwardTransform;
@@ -2390,27 +2371,27 @@ void GDALDestroyReprojectionTransformer( void *pTransformArg )
 /**
  * Perform reprojection transformation.
  *
- * Actually performs the reprojection transformation described in 
- * GDALCreateReprojectionTransformer().  This function matches the 
+ * Actually performs the reprojection transformation described in
+ * GDALCreateReprojectionTransformer().  This function matches the
  * GDALTransformerFunc() signature.  Details of the arguments are described
- * there. 
+ * there.
  */
 
-int GDALReprojectionTransform( void *pTransformArg, int bDstToSrc, 
-                                int nPointCount, 
+int GDALReprojectionTransform( void *pTransformArg, int bDstToSrc,
+                                int nPointCount,
                                 double *padfX, double *padfY, double *padfZ,
                                 int *panSuccess )
 
 {
-    GDALReprojectionTransformInfo *psInfo = 
-        (GDALReprojectionTransformInfo *) pTransformArg;		
+    GDALReprojectionTransformInfo *psInfo =
+        (GDALReprojectionTransformInfo *) pTransformArg;
     int bSuccess;
 
     if( bDstToSrc )
-        bSuccess = psInfo->poReverseTransform->TransformEx( 
+        bSuccess = psInfo->poReverseTransform->TransformEx(
             nPointCount, padfX, padfY, padfZ, panSuccess );
     else
-        bSuccess = psInfo->poForwardTransform->TransformEx( 
+        bSuccess = psInfo->poForwardTransform->TransformEx(
             nPointCount, padfX, padfY, padfZ, panSuccess );
 
     return bSuccess;
@@ -2425,7 +2406,7 @@ GDALSerializeReprojectionTransformer( void *pTransformArg )
 
 {
     CPLXMLNode *psTree;
-    GDALReprojectionTransformInfo *psInfo = 
+    GDALReprojectionTransformInfo *psInfo =
         (GDALReprojectionTransformInfo *) pTransformArg;
 
     psTree = CPLCreateXMLNode( NULL, CXT_Element, "ReprojectionTransformer" );
@@ -2461,7 +2442,7 @@ GDALDeserializeReprojectionTransformer( CPLXMLNode *psTree )
 
 {
     const char *pszSourceSRS = CPLGetXMLValue( psTree, "SourceSRS", NULL );
-    const char *pszTargetSRS= CPLGetXMLValue( psTree, "TargetSRS", NULL );
+    const char *pszTargetSRS = CPLGetXMLValue( psTree, "TargetSRS", NULL );
     char *pszSourceWKT = NULL, *pszTargetWKT = NULL;
     void *pResult = NULL;
 
@@ -2488,7 +2469,7 @@ GDALDeserializeReprojectionTransformer( CPLXMLNode *psTree )
     }
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "ReprojectionTransformer definition missing either\n"
                   "SourceSRS or TargetSRS definition." );
     }
@@ -2505,7 +2486,7 @@ GDALDeserializeReprojectionTransformer( CPLXMLNode *psTree )
 /* ==================================================================== */
 /************************************************************************/
 
-typedef struct 
+typedef struct
 {
     GDALTransformerInfo sTI;
 
@@ -2525,7 +2506,7 @@ void* GDALCreateSimilarApproxTransformer( void *hTransformArg, double dfSrcRatio
 {
     VALIDATE_POINTER1( hTransformArg, "GDALCreateSimilarApproxTransformer", NULL );
 
-    ApproxTransformInfo *psInfo = 
+    ApproxTransformInfo *psInfo =
         (ApproxTransformInfo *) hTransformArg;
 
     ApproxTransformInfo *psClonedInfo =  (ApproxTransformInfo *)
@@ -2564,7 +2545,7 @@ GDALSerializeApproxTransformer( void *pTransformArg )
 /* -------------------------------------------------------------------- */
 /*      Attach max error.                                               */
 /* -------------------------------------------------------------------- */
-    CPLCreateXMLElementAndValue( psTree, "MaxError", 
+    CPLCreateXMLElementAndValue( psTree, "MaxError",
                                  CPLString().Printf("%g",psInfo->dfMaxError) );
 
 /* -------------------------------------------------------------------- */
@@ -2573,9 +2554,9 @@ GDALSerializeApproxTransformer( void *pTransformArg )
     CPLXMLNode *psTransformerContainer;
     CPLXMLNode *psTransformer;
 
-    psTransformerContainer = 
+    psTransformerContainer =
         CPLCreateXMLNode( psTree, CXT_Element, "BaseTransformer" );
-    
+
     psTransformer = GDALSerializeTransformer( psInfo->pfnBaseTransformer,
                                               psInfo->pBaseCBData );
     if( psTransformer != NULL )
@@ -2594,34 +2575,34 @@ GDALSerializeApproxTransformer( void *pTransformArg )
  * This function creates a context for an approximated transformer.  Basically
  * a high precision transformer is supplied as input and internally linear
  * approximations are computed to generate results to within a defined
- * precision. 
+ * precision.
  *
  * The approximation is actually done at the point where GDALApproxTransform()
  * calls are made, and depend on the assumption that the roughly linear.  The
- * first and last point passed in must be the extreme values and the 
+ * first and last point passed in must be the extreme values and the
  * intermediate values should describe a curve between the end points.  The
  * approximator transforms and center using the approximate transformer, and
  * then compares the true middle transformed value to a linear approximation
  * based on the end points.  If the error is within the supplied threshold
- * then the end points are used to linearly approximate all the values 
+ * then the end points are used to linearly approximate all the values
  * otherwise the inputs points are split into two smaller sets, and the
  * function recursively called till a sufficiently small set of points if found
  * that the linear approximation is OK, or that all the points are exactly
- * computed. 
+ * computed.
  *
  * This function is very suitable for approximating transformation results
  * from output pixel/line space to input coordinates for warpers that operate
  * on one input scanline at a time.  Care should be taken using it in other
  * circumstances as little internal validation is done, in order to keep things
- * fast. 
+ * fast.
  *
  * @param pfnBaseTransformer the high precision transformer which should be
- * approximated. 
- * @param pBaseTransformArg the callback argument for the high precision 
- * transformer. 
+ * approximated.
+ * @param pBaseTransformArg the callback argument for the high precision
+ * transformer.
  * @param dfMaxError the maximum cartesian error in the "output" space that
  * is to be accepted in the linear approximation.
- * 
+ *
  * @return callback pointer suitable for use with GDALApproxTransform().  It
  * should be deallocated with GDALDestroyApproxTransformer().
  */
@@ -2668,8 +2649,8 @@ void GDALApproxTransformerOwnsSubtransformer( void *pCBData, int bOwnFlag )
  * Cleanup approximate transformer.
  *
  * Deallocates the resources allocated by GDALCreateApproxTransformer().
- * 
- * @param pCBData callback data originally returned by 
+ *
+ * @param pCBData callback data originally returned by
  * GDALCreateApproxTransformer().
  */
 
@@ -2681,7 +2662,7 @@ void GDALDestroyApproxTransformer( void * pCBData )
 
     ApproxTransformInfo	*psATInfo = (ApproxTransformInfo *) pCBData;
 
-    if( psATInfo->bOwnSubtransformer ) 
+    if( psATInfo->bOwnSubtransformer )
         GDALDestroyTransformer( psATInfo->pBaseCBData );
 
     CPLFree( pCBData );
@@ -2691,7 +2672,7 @@ void GDALDestroyApproxTransformer( void * pCBData )
 /*                      GDALApproxTransformInternal()                   */
 /************************************************************************/
 
-static int GDALApproxTransformInternal( void *pCBData, int bDstToSrc, int nPoints, 
+static int GDALApproxTransformInternal( void *pCBData, int bDstToSrc, int nPoints,
                                         double *x, double *y, double *z, int *panSuccess,
                                         const double xSMETransformed[3], /* SME = Start, Middle, End */
                                         const double ySMETransformed[3],
@@ -2717,8 +2698,8 @@ static int GDALApproxTransformInternal( void *pCBData, int bDstToSrc, int nPoint
         y2[2] = y[nPoints-1];
         z2[2] = z[nPoints-1];
 
-        bSuccess = 
-            psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, bDstToSrc, 3, 
+        bSuccess =
+            psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, bDstToSrc, 3,
                                         x2, y2, z2, anSuccess2 );
         CPLAssert(bSuccess);
         CPLAssert(anSuccess2[0]);
@@ -2788,20 +2769,20 @@ static int GDALApproxTransformInternal( void *pCBData, int bDstToSrc, int nPoint
                                  x[nMiddle] == x[nMiddle + (nPoints - nMiddle - 1) / 2] );
 
         if( !bUseBaseTransformForHalf1 && !bUseBaseTransformForHalf2 )
-            bSuccess = 
-                psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, bDstToSrc, 3, 
+            bSuccess =
+                psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, bDstToSrc, 3,
                                              xMiddle, yMiddle, zMiddle, anSuccess2 );
         else if( !bUseBaseTransformForHalf1 )
         {
-            bSuccess = 
-                psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, bDstToSrc, 2, 
+            bSuccess =
+                psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, bDstToSrc, 2,
                                              xMiddle, yMiddle, zMiddle, anSuccess2 );
             anSuccess2[2] = TRUE;
         }
         else if( !bUseBaseTransformForHalf2 )
         {
-            bSuccess = 
-                psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, bDstToSrc, 1, 
+            bSuccess =
+                psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, bDstToSrc, 1,
                                               xMiddle + 2, yMiddle + 2, zMiddle + 2,
                                               anSuccess2 + 2 );
             anSuccess2[0] = TRUE;
@@ -2850,11 +2831,11 @@ static int GDALApproxTransformInternal( void *pCBData, int bDstToSrc, int nPoint
             y2[2] = yMiddle[1];
             z2[2] = zMiddle[1];
 
-            bSuccess = 
-                GDALApproxTransformInternal( psATInfo, bDstToSrc, nMiddle, 
+            bSuccess =
+                GDALApproxTransformInternal( psATInfo, bDstToSrc, nMiddle,
                                             x, y, z, panSuccess,
                                             x2, y2, z2);
-    
+
         }
         else
         {
@@ -2882,7 +2863,7 @@ static int GDALApproxTransformInternal( void *pCBData, int bDstToSrc, int nPoint
             y2[2] = ySMETransformed[2];
             z2[2] = zSMETransformed[2];
 
-            bSuccess = 
+            bSuccess =
                 GDALApproxTransformInternal( psATInfo, bDstToSrc, nPoints - nMiddle,
                                             x+nMiddle, y+nMiddle, z+nMiddle,
                                             panSuccess+nMiddle,
@@ -2942,7 +2923,7 @@ static int GDALApproxTransformInternal( void *pCBData, int bDstToSrc, int nPoint
 #endif
         panSuccess[i] = TRUE;
     }
-    
+
     return TRUE;
 }
 
@@ -2953,21 +2934,21 @@ static int GDALApproxTransformInternal( void *pCBData, int bDstToSrc, int nPoint
 /**
  * Perform approximate transformation.
  *
- * Actually performs the approximate transformation described in 
- * GDALCreateApproxTransformer().  This function matches the 
+ * Actually performs the approximate transformation described in
+ * GDALCreateApproxTransformer().  This function matches the
  * GDALTransformerFunc() signature.  Details of the arguments are described
- * there. 
+ * there.
  */
 
-int GDALApproxTransform( void *pCBData, int bDstToSrc, int nPoints, 
+int GDALApproxTransform( void *pCBData, int bDstToSrc, int nPoints,
                          double *x, double *y, double *z, int *panSuccess )
 
 {
     ApproxTransformInfo *psATInfo = (ApproxTransformInfo *) pCBData;
     double x2[3], y2[3], z2[3];
-    int nMiddle, anSuccess2[3], bSuccess;
+    int anSuccess2[3], bSuccess;
 
-    nMiddle = (nPoints-1)/2;
+    int nMiddle = (nPoints-1)/2;
 
 /* -------------------------------------------------------------------- */
 /*      Bail if our preconditions are not met, or if error is not       */
@@ -2996,8 +2977,8 @@ int GDALApproxTransform( void *pCBData, int bDstToSrc, int nPoints,
     y2[2] = y[nPoints-1];
     z2[2] = z[nPoints-1];
 
-    bSuccess = 
-        psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, bDstToSrc, 3, 
+    bSuccess =
+        psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, bDstToSrc, 3,
                                       x2, y2, z2, anSuccess2 );
     if( !bSuccess || !anSuccess2[0] || !anSuccess2[1] || !anSuccess2[2] )
     {
@@ -3006,7 +2987,7 @@ int GDALApproxTransform( void *pCBData, int bDstToSrc, int nPoints,
         goto end;
     }
 
-    bRet = GDALApproxTransformInternal( pCBData, bDstToSrc, nPoints, 
+    bRet = GDALApproxTransformInternal( pCBData, bDstToSrc, nPoints,
                                         x, y, z, panSuccess,
                                         x2,
                                         y2,
@@ -3030,20 +3011,18 @@ GDALDeserializeApproxTransformer( CPLXMLNode *psTree )
 
 {
     double dfMaxError = CPLAtof(CPLGetXMLValue( psTree, "MaxError",  "0.25" ));
-    CPLXMLNode *psContainer;
     GDALTransformerFunc pfnBaseTransform = NULL;
     void *pBaseCBData = NULL;
 
-    psContainer = CPLGetXMLNode( psTree, "BaseTransformer" );
+    CPLXMLNode *psContainer = CPLGetXMLNode( psTree, "BaseTransformer" );
 
     if( psContainer != NULL && psContainer->psChild != NULL )
     {
-        GDALDeserializeTransformer( psContainer->psChild, 
-                                    &pfnBaseTransform, 
+        GDALDeserializeTransformer( psContainer->psChild,
+                                    &pfnBaseTransform,
                                     &pBaseCBData );
-        
     }
-    
+
     if( pfnBaseTransform == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -3053,7 +3032,7 @@ GDALDeserializeApproxTransformer( CPLXMLNode *psTree )
     else
     {
         void *pApproxCBData = GDALCreateApproxTransformer( pfnBaseTransform,
-                                                           pBaseCBData, 
+                                                           pBaseCBData,
                                                            dfMaxError );
         GDALApproxTransformerOwnsSubtransformer( pApproxCBData, TRUE );
 
@@ -3069,7 +3048,7 @@ GDALDeserializeApproxTransformer( CPLXMLNode *psTree )
  * Apply GeoTransform to x/y coordinate.
  *
  * Applies the following computation, converting a (pixel,line) coordinate
- * into a georeferenced (geo_x,geo_y) location. 
+ * into a georeferenced (geo_x,geo_y) location.
  *
  *  *pdfGeoX = padfGeoTransform[0] + dfPixel * padfGeoTransform[1]
  *                                 + dfLine  * padfGeoTransform[2];
@@ -3078,13 +3057,13 @@ GDALDeserializeApproxTransformer( CPLXMLNode *psTree )
  *
  * @param padfGeoTransform Six coefficient GeoTransform to apply.
  * @param dfPixel Input pixel position.
- * @param dfLine Input line position. 
+ * @param dfLine Input line position.
  * @param pdfGeoX output location where geo_x (easting/longitude) location is placed.
  * @param pdfGeoY output location where geo_y (northing/latitude) location is placed.
  */
 
-void CPL_STDCALL GDALApplyGeoTransform( double *padfGeoTransform, 
-                            double dfPixel, double dfLine, 
+void CPL_STDCALL GDALApplyGeoTransform( double *padfGeoTransform,
+                            double dfPixel, double dfLine,
                             double *pdfGeoX, double *pdfGeoY )
 {
     *pdfGeoX = padfGeoTransform[0] + dfPixel * padfGeoTransform[1]
@@ -3101,26 +3080,24 @@ void CPL_STDCALL GDALApplyGeoTransform( double *padfGeoTransform,
  * Invert Geotransform.
  *
  * This function will invert a standard 3x2 set of GeoTransform coefficients.
- * This converts the equation from being pixel to geo to being geo to pixel. 
+ * This converts the equation from being pixel to geo to being geo to pixel.
  *
  * @param gt_in Input geotransform (six doubles - unaltered).
- * @param gt_out Output geotransform (six doubles - updated). 
+ * @param gt_out Output geotransform (six doubles - updated).
  *
- * @return TRUE on success or FALSE if the equation is uninvertable. 
+ * @return TRUE on success or FALSE if the equation is uninvertable.
  */
 
 int CPL_STDCALL GDALInvGeoTransform( double *gt_in, double *gt_out )
 
 {
-    double	det, inv_det;
-
     /* Special case - no rotation - to avoid computing determinate */
     /* and potential precision issues. */
     if( gt_in[2] == 0.0 && gt_in[4] == 0.0 &&
         gt_in[1] != 0.0 && gt_in[5] != 0.0 )
     {
         /*X = gt_in[0] + x * gt_in[1]
-          Y = gt_in[3] + y * gt_in[5] 
+          Y = gt_in[3] + y * gt_in[5]
           -->
           x = -gt_in[0] / gt_in[1] + (1 / gt_in[1]) * X
           y = -gt_in[3] / gt_in[5] + (1 / gt_in[5]) * Y
@@ -3138,14 +3115,14 @@ int CPL_STDCALL GDALInvGeoTransform( double *gt_in, double *gt_out )
 
     /* Compute determinate */
 
-    det = gt_in[1] * gt_in[5] - gt_in[2] * gt_in[4];
+    const double det = gt_in[1] * gt_in[5] - gt_in[2] * gt_in[4];
 
     if( fabs(det) < 0.000000000000001 )
         return 0;
 
-    inv_det = 1.0 / det;
+    const double inv_det = 1.0 / det;
 
-    /* compute adjoint, and devide by determinate */
+    /* compute adjoint, and divide by determinate */
 
     gt_out[1] =  gt_in[5] * inv_det;
     gt_out[4] = -gt_in[4] * inv_det;
@@ -3265,7 +3242,7 @@ void GDALCleanupTransformDeserializerMutex()
 /*                     GDALDeserializeTransformer()                     */
 /************************************************************************/
 
-CPLErr GDALDeserializeTransformer( CPLXMLNode *psTree, 
+CPLErr GDALDeserializeTransformer( CPLXMLNode *psTree,
                                    GDALTransformerFunc *ppfnFunc,
                                    void **ppTransformArg )
 
@@ -3276,7 +3253,7 @@ CPLErr GDALDeserializeTransformer( CPLXMLNode *psTree,
     CPLErrorReset();
 
     if( psTree == NULL || psTree->eType != CXT_Element )
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Malformed element in GDALDeserializeTransformer" );
     else if( EQUAL(psTree->pszValue,"GenImgProjTransformer") )
     {
@@ -3340,7 +3317,7 @@ CPLErr GDALDeserializeTransformer( CPLXMLNode *psTree,
         else
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                    "Unrecognised element '%s' GDALDeserializeTransformer",
+                    "Unrecognized element '%s' GDALDeserializeTransformer",
                     psTree->pszValue );
         }
     }
@@ -3375,8 +3352,8 @@ void GDALDestroyTransformer( void *pTransformArg )
 /************************************************************************/
 
 int GDALUseTransformer( void *pTransformArg,
-                        int bDstToSrc, int nPointCount, 
-                        double *x, double *y, double *z, 
+                        int bDstToSrc, int nPointCount,
+                        double *x, double *y, double *z,
                         int *panSuccess )
 {
     GDALTransformerInfo *psInfo = (GDALTransformerInfo *) pTransformArg;
@@ -3389,7 +3366,7 @@ int GDALUseTransformer( void *pTransformArg,
         return FALSE;
     }
     else
-        return psInfo->pfnTransform( pTransformArg, bDstToSrc, nPointCount, 
+        return psInfo->pfnTransform( pTransformArg, bDstToSrc, nPointCount,
                                      x, y, z, panSuccess );
 }
 
@@ -3433,6 +3410,7 @@ void *GDALCloneTransformer( void *pTransformArg )
             CE_None )
         {
             CPLDestroyXMLNode(pSerialized);
+            CPLFree(pClonedTransformArg);
             return NULL;
         }
         CPLDestroyXMLNode(pSerialized);
@@ -3462,7 +3440,7 @@ void* GDALCreateSimilarTransformer( void* pTransformArg, double dfRatioX, double
     {
         return psInfo->pfnCreateSimilar(psInfo, dfRatioX, dfRatioY);
     }
-    
+
     CPLError( CE_Failure, CPLE_AppDefined,
                   "No CreateSimilar function available for this transformer." );
     return NULL;
@@ -3486,12 +3464,12 @@ void GDALSetTransformerDstGeoTransform(void *pTransformArg,
                   "Attempt to call GDALSetTransformerDstGeoTransform on a non-GTI2 transformer." );
         return;
     }
-    
+
     if( EQUAL(psInfo->pszClassName, "GDALApproxTransformer") )
     {
         ApproxTransformInfo   *psATInfo = (ApproxTransformInfo*)pTransformArg;
         psInfo = (GDALTransformerInfo *)psATInfo->pBaseCBData;
-          
+
         if( psInfo == NULL ||
             memcmp(psInfo->abySignature,GDAL_GTI2_SIGNATURE, strlen(GDAL_GTI2_SIGNATURE)) != 0 )
         {
@@ -3500,7 +3478,7 @@ void GDALSetTransformerDstGeoTransform(void *pTransformArg,
             return;
         }
     }
-    
+
     if( EQUAL(psInfo->pszClassName, "GDALGenImgProjTransformer") )
     {
         GDALSetGenImgProjTransformerDstGeoTransform(psInfo, padfGeoTransform);
diff --git a/alg/gdaltransformgeolocs.cpp b/alg/gdaltransformgeolocs.cpp
index d12b259..9294f81 100644
--- a/alg/gdaltransformgeolocs.cpp
+++ b/alg/gdaltransformgeolocs.cpp
@@ -33,18 +33,16 @@
 
 CPL_CVSID("$Id$");
 
-                                      
-
 /************************************************************************/
 /*                     GDALTransformGeolocations()                      */
 /************************************************************************/
 
-/** 
+/**
  * Transform locations held in bands.
  *
  * The X/Y and possibly Z values in the identified bands are transformed
  * using a spatial transformer.  The changes values are written back to the
- * source bands so they need to updatable.  
+ * source bands so they need to updatable.
  *
  * @param hXBand the band containing the X locations (usually long/easting).
  * @param hYBand the band containing the Y locations (usually lat/northing).
@@ -118,7 +116,7 @@ GDALTransformGeolocations( GDALRasterBandH hXBand,
                                       padfZ, nXSize, 1, GDT_Float64, 0, 0, NULL );
         else
             memset( padfZ, 0, sizeof(double) * nXSize);
-        
+
         if( eErr == CE_None )
         {
             pfnTransformer( pTransformArg, FALSE, nXSize,
@@ -138,7 +136,7 @@ GDALTransformGeolocations( GDALRasterBandH hXBand,
         if( eErr == CE_None )
             pfnProgress( (iLine+1) / (double) nYSize, "", pProgressArg );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Cleanup                                                         */
 /* -------------------------------------------------------------------- */
diff --git a/alg/gdalwarper.cpp b/alg/gdalwarper.cpp
index 09cfec6..6a9206e 100644
--- a/alg/gdalwarper.cpp
+++ b/alg/gdalwarper.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalwarper.cpp 29207 2015-05-18 17:23:45Z mloskot $
+ * $Id: gdalwarper.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  High Performance Image Reprojector
  * Purpose:  Implementation of high level convenience APIs for warper.
@@ -34,7 +34,7 @@
 #include "ogr_api.h"
 #include "gdal_priv.h"
 
-CPL_CVSID("$Id: gdalwarper.cpp 29207 2015-05-18 17:23:45Z mloskot $");
+CPL_CVSID("$Id: gdalwarper.cpp 33808 2016-03-29 21:15:28Z goatbar $");
 
 /************************************************************************/
 /*                         GDALReprojectImage()                         */
@@ -46,22 +46,22 @@ CPL_CVSID("$Id: gdalwarper.cpp 29207 2015-05-18 17:23:45Z mloskot $");
  * This is a convenience function utilizing the GDALWarpOperation class to
  * reproject an image from a source to a destination.  In particular, this
  * function takes care of establishing the transformation function to
- * implement the reprojection, and will default a variety of other 
- * warp options. 
+ * implement the reprojection, and will default a variety of other
+ * warp options.
  *
  * No metadata, projection info, or color tables are transferred
- * to the output file. 
+ * to the output file.
  *
  * Starting with GDAL 2.0, nodata values set on destination dataset are taken
  * into account.
  *
- * @param hSrcDS the source image file. 
+ * @param hSrcDS the source image file.
  * @param pszSrcWKT the source projection.  If NULL the source projection
  * is read from from hSrcDS.
- * @param hDstDS the destination image file. 
+ * @param hDstDS the destination image file.
  * @param pszDstWKT the destination projection.  If NULL the destination
  * projection will be read from hDstDS.
- * @param eResampleAlg the type of resampling to use.  
+ * @param eResampleAlg the type of resampling to use.
  * @param dfWarpMemoryLimit the amount of memory (in bytes) that the warp
  * API is allowed to use for caching.  This is in addition to the memory
  * already allocated to the GDAL caching (as per GDALSetCacheMax()).  May be
@@ -69,7 +69,7 @@ CPL_CVSID("$Id: gdalwarper.cpp 29207 2015-05-18 17:23:45Z mloskot $");
  * @param dfMaxError maximum error measured in input pixels that is allowed
  * in approximating the transformation (0.0 for exact calculations).
  * @param pfnProgress a GDALProgressFunc() compatible callback function for
- * reporting progress or NULL. 
+ * reporting progress or NULL.
  * @param pProgressArg argument to be passed to pfnProgress.  May be NULL.
  * @param psOptions warp options, normally NULL.
  *
@@ -93,8 +93,8 @@ GDALReprojectImage( GDALDatasetH hSrcDS, const char *pszSrcWKT,
 /* -------------------------------------------------------------------- */
     void *hTransformArg;
 
-    hTransformArg = 
-        GDALCreateGenImgProjTransformer( hSrcDS, pszSrcWKT, hDstDS, pszDstWKT, 
+    hTransformArg =
+        GDALCreateGenImgProjTransformer( hSrcDS, pszSrcWKT, hDstDS, pszDstWKT,
                                          TRUE, 1000.0, 0 );
 
     if( hTransformArg == NULL )
@@ -116,8 +116,8 @@ GDALReprojectImage( GDALDatasetH hSrcDS, const char *pszSrcWKT,
 /* -------------------------------------------------------------------- */
     if( dfMaxError > 0.0 )
     {
-        psWOptions->pTransformerArg = 
-            GDALCreateApproxTransformer( GDALGenImgProjTransform, 
+        psWOptions->pTransformerArg =
+            GDALCreateApproxTransformer( GDALGenImgProjTransform,
                                          hTransformArg, dfMaxError );
 
         psWOptions->pfnTransformer = GDALApproxTransform;
@@ -140,10 +140,10 @@ GDALReprojectImage( GDALDatasetH hSrcDS, const char *pszSrcWKT,
     {
         psWOptions->nBandCount = MIN(GDALGetRasterCount(hSrcDS),
                                      GDALGetRasterCount(hDstDS));
-        
-        psWOptions->panSrcBands = (int *) 
+
+        psWOptions->panSrcBands = (int *)
             CPLMalloc(sizeof(int) * psWOptions->nBandCount);
-        psWOptions->panDstBands = (int *) 
+        psWOptions->panDstBands = (int *)
             CPLMalloc(sizeof(int) * psWOptions->nBandCount);
 
         for( iBand = 0; iBand < psWOptions->nBandCount; iBand++ )
@@ -175,9 +175,9 @@ GDALReprojectImage( GDALDatasetH hSrcDS, const char *pszSrcWKT,
             {
                 int  ii;
 
-                psWOptions->padfSrcNoDataReal = (double *) 
+                psWOptions->padfSrcNoDataReal = (double *)
                     CPLMalloc(sizeof(double) * psWOptions->nBandCount);
-                psWOptions->padfSrcNoDataImag = (double *) 
+                psWOptions->padfSrcNoDataImag = (double *)
                     CPLMalloc(sizeof(double) * psWOptions->nBandCount);
 
                 for( ii = 0; ii < psWOptions->nBandCount; ii++ )
@@ -204,9 +204,9 @@ GDALReprojectImage( GDALDatasetH hSrcDS, const char *pszSrcWKT,
             {
                 int  ii;
 
-                psWOptions->padfDstNoDataReal = (double *) 
+                psWOptions->padfDstNoDataReal = (double *)
                     CPLMalloc(sizeof(double) * psWOptions->nBandCount);
-                psWOptions->padfDstNoDataImag = (double *) 
+                psWOptions->padfDstNoDataImag = (double *)
                     CPLMalloc(sizeof(double) * psWOptions->nBandCount);
 
                 for( ii = 0; ii < psWOptions->nBandCount; ii++ )
@@ -238,7 +238,7 @@ GDALReprojectImage( GDALDatasetH hSrcDS, const char *pszSrcWKT,
     eErr = oWarper.Initialize( psWOptions );
 
     if( eErr == CE_None )
-        eErr = oWarper.ChunkAndWarpImage( 0, 0, 
+        eErr = oWarper.ChunkAndWarpImage( 0, 0,
                                           GDALGetRasterXSize(hDstDS),
                                           GDALGetRasterYSize(hDstDS) );
 
@@ -249,7 +249,7 @@ GDALReprojectImage( GDALDatasetH hSrcDS, const char *pszSrcWKT,
 
     if( dfMaxError > 0.0 )
         GDALDestroyApproxTransformer( psWOptions->pTransformerArg );
-        
+
     GDALDestroyWarpOptions( psWOptions );
 
     return eErr;
@@ -261,14 +261,14 @@ GDALReprojectImage( GDALDatasetH hSrcDS, const char *pszSrcWKT,
 /*      This is a "quicky" reprojection API.                            */
 /************************************************************************/
 
-CPLErr CPL_STDCALL GDALCreateAndReprojectImage( 
-    GDALDatasetH hSrcDS, const char *pszSrcWKT, 
+CPLErr CPL_STDCALL GDALCreateAndReprojectImage(
+    GDALDatasetH hSrcDS, const char *pszSrcWKT,
     const char *pszDstFilename, const char *pszDstWKT,
     GDALDriverH hDstDriver, char **papszCreateOptions,
     GDALResampleAlg eResampleAlg, double dfWarpMemoryLimit, double dfMaxError,
-    GDALProgressFunc pfnProgress, void *pProgressArg, 
+    GDALProgressFunc pfnProgress, void *pProgressArg,
     GDALWarpOptions *psOptions )
-    
+
 {
     VALIDATE_POINTER1( hSrcDS, "GDALCreateAndReprojectImage", CE_Failure );
 
@@ -298,8 +298,8 @@ CPLErr CPL_STDCALL GDALCreateAndReprojectImage(
 /* -------------------------------------------------------------------- */
     void *hTransformArg;
 
-    hTransformArg = 
-        GDALCreateGenImgProjTransformer( hSrcDS, pszSrcWKT, NULL, pszDstWKT, 
+    hTransformArg =
+        GDALCreateGenImgProjTransformer( hSrcDS, pszSrcWKT, NULL, pszDstWKT,
                                          TRUE, 1000.0, 0 );
 
     if( hTransformArg == NULL )
@@ -311,8 +311,8 @@ CPLErr CPL_STDCALL GDALCreateAndReprojectImage(
     double adfDstGeoTransform[6];
     int    nPixels, nLines;
 
-    if( GDALSuggestedWarpOutput( hSrcDS, 
-                                 GDALGenImgProjTransform, hTransformArg, 
+    if( GDALSuggestedWarpOutput( hSrcDS,
+                                 GDALGenImgProjTransform, hTransformArg,
                                  adfDstGeoTransform, &nPixels, &nLines )
         != CE_None )
         return CE_Failure;
@@ -324,7 +324,7 @@ CPLErr CPL_STDCALL GDALCreateAndReprojectImage(
 /* -------------------------------------------------------------------- */
     GDALDatasetH hDstDS;
 
-    hDstDS = GDALCreate( hDstDriver, pszDstFilename, nPixels, nLines, 
+    hDstDS = GDALCreate( hDstDriver, pszDstFilename, nPixels, nLines,
                          GDALGetRasterCount(hSrcDS),
                          GDALGetRasterDataType(GDALGetRasterBand(hSrcDS,1)),
                          papszCreateOptions );
@@ -343,8 +343,8 @@ CPLErr CPL_STDCALL GDALCreateAndReprojectImage(
 /* -------------------------------------------------------------------- */
     CPLErr eErr ;
 
-    eErr = 
-        GDALReprojectImage( hSrcDS, pszSrcWKT, hDstDS, pszDstWKT, 
+    eErr =
+        GDALReprojectImage( hSrcDS, pszSrcWKT, hDstDS, pszDstWKT,
                             eResampleAlg, dfWarpMemoryLimit, dfMaxError,
                             pfnProgress, pProgressArg, psOptions );
 
@@ -360,10 +360,10 @@ CPLErr CPL_STDCALL GDALCreateAndReprojectImage(
 /*      band based on a provided NODATA value.                          */
 /************************************************************************/
 
-CPLErr 
-GDALWarpNoDataMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType, 
+CPLErr
+GDALWarpNoDataMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
                       int /* nXOff */, int /* nYOff */, int nXSize, int nYSize,
-                      GByte **ppImageData, 
+                      GByte **ppImageData,
                       int bMaskIsFloat, void *pValidityMask, int* pbOutAllValid )
 
 {
@@ -374,7 +374,7 @@ GDALWarpNoDataMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
 
     if( nBandCount != 1 || bMaskIsFloat )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Invalid nBandCount or bMaskIsFloat argument in SourceNoDataMask" );
         return CE_Failure;
     }
@@ -388,7 +388,7 @@ GDALWarpNoDataMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
           int iOffset;
 
           // nothing to do if value is out of range.
-          if( padfNoData[0] < 0.0 || padfNoData[0] > 255.000001 
+          if( padfNoData[0] < 0.0 || padfNoData[0] > 255.000001
               || padfNoData[1] != 0.0 )
           {
               *pbOutAllValid = TRUE;
@@ -407,7 +407,7 @@ GDALWarpNoDataMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
           *pbOutAllValid = bAllValid;
       }
       break;
-      
+
       case GDT_Int16:
       {
           int nNoData = (int) padfNoData[0];
@@ -434,7 +434,7 @@ GDALWarpNoDataMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
           *pbOutAllValid = bAllValid;
       }
       break;
-      
+
       case GDT_UInt16:
       {
           int nNoData = (int) padfNoData[0];
@@ -461,7 +461,7 @@ GDALWarpNoDataMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
           *pbOutAllValid = bAllValid;
       }
       break;
-      
+
       case GDT_Float32:
       {
           float fNoData = (float) padfNoData[0];
@@ -489,7 +489,7 @@ GDALWarpNoDataMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
           *pbOutAllValid = bAllValid;
       }
       break;
-      
+
       case GDT_Float64:
       {
           double dfNoData = padfNoData[0];
@@ -517,13 +517,13 @@ GDALWarpNoDataMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
           *pbOutAllValid = bAllValid;
       }
       break;
-      
+
       default:
       {
           double  *padfWrk;
           int     iLine, iPixel;
-          int     nWordSize = GDALGetDataTypeSize(eType)/8;
-          
+          const int nWordSize = GDALGetDataTypeSizeBytes(eType);
+
           int bIsNoDataRealNan = CPLIsNan(padfNoData[0]);
           int bIsNoDataImagNan = CPLIsNan(padfNoData[1]);
 
@@ -531,10 +531,10 @@ GDALWarpNoDataMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
           int bAllValid = TRUE;
           for( iLine = 0; iLine < nYSize; iLine++ )
           {
-              GDALCopyWords( ((GByte *) *ppImageData)+nWordSize*iLine*nXSize, 
+              GDALCopyWords( ((GByte *) *ppImageData)+nWordSize*iLine*nXSize,
                              eType, nWordSize,
                              padfWrk, GDT_CFloat64, 16, nXSize );
-              
+
               for( iPixel = 0; iPixel < nXSize; iPixel++ )
               {
                   if( ((bIsNoDataRealNan && CPLIsNan(padfWrk[iPixel*2])) ||
@@ -543,13 +543,13 @@ GDALWarpNoDataMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
                           (!bIsNoDataImagNan && ARE_REAL_EQUAL(padfWrk[iPixel*2+1], padfNoData[1]))) )
                   {
                       int iOffset = iPixel + iLine * nXSize;
-                      
+
                       bAllValid = FALSE;
                       panValidityMask[iOffset>>5] &=
                           ~(0x01 << (iOffset & 0x1f));
                   }
               }
-              
+
           }
           *pbOutAllValid = bAllValid;
 
@@ -569,7 +569,7 @@ GDALWarpNoDataMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
 /*      it.                                                             */
 /************************************************************************/
 
-CPLErr 
+CPLErr
 GDALWarpSrcAlphaMasker( void *pMaskFuncArg,
                         CPL_UNUSED int nBandCount,
                         CPL_UNUSED GDALDataType eType,
@@ -602,12 +602,12 @@ GDALWarpSrcAlphaMasker( void *pMaskFuncArg,
 /*      Read the alpha band.                                            */
 /* -------------------------------------------------------------------- */
     CPLErr eErr;
-    GDALRasterBandH hAlphaBand = GDALGetRasterBand( psWO->hSrcDS, 
+    GDALRasterBandH hAlphaBand = GDALGetRasterBand( psWO->hSrcDS,
                                                     psWO->nSrcAlphaBand );
     if (hAlphaBand == NULL)
         return CE_Failure;
 
-    eErr = GDALRasterIO( hAlphaBand, GF_Read, nXOff, nYOff, nXSize, nYSize, 
+    eErr = GDALRasterIO( hAlphaBand, GF_Read, nXOff, nYOff, nXSize, nYSize,
                          pafMask, nXSize, nYSize, GDT_Float32, 0, 0 );
 
     if( eErr != CE_None )
@@ -669,12 +669,9 @@ GDALWarpSrcMaskMasker( void *pMaskFuncArg,
 /* -------------------------------------------------------------------- */
     GByte *pabySrcMask;
 
-    pabySrcMask = (GByte *) VSIMalloc2(nXSize,nYSize);
+    pabySrcMask = (GByte *) VSI_MALLOC2_VERBOSE(nXSize,nYSize);
     if( pabySrcMask == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory,
-                  "Failed to allocate pabySrcMask (%dx%d) in GDALWarpSrcMaskMasker()", 
-                  nXSize, nYSize );
         return CE_Failure;
     }
 
@@ -698,7 +695,7 @@ GDALWarpSrcMaskMasker( void *pMaskFuncArg,
 /* -------------------------------------------------------------------- */
     CPLErr eErr;
 
-    eErr = GDALRasterIO( hMaskBand, GF_Read, nXOff, nYOff, nXSize, nYSize, 
+    eErr = GDALRasterIO( hMaskBand, GF_Read, nXOff, nYOff, nXSize, nYSize,
                          pabySrcMask, nXSize, nYSize, GDT_Byte, 0, 0 );
 
     if( eErr != CE_None )
@@ -757,7 +754,7 @@ GDALWarpDstAlphaMasker( void *pMaskFuncArg, int nBandCount,
         return CE_Failure;
     }
 
-    GDALRasterBandH hAlphaBand = 
+    GDALRasterBandH hAlphaBand =
         GDALGetRasterBand( psWO->hDstDS, psWO->nDstAlphaBand );
     if (hAlphaBand == NULL)
         return CE_Failure;
@@ -767,7 +764,7 @@ GDALWarpDstAlphaMasker( void *pMaskFuncArg, int nBandCount,
 /* -------------------------------------------------------------------- */
     if( nBandCount >= 0 )
     {
-        const char *pszInitDest = 
+        const char *pszInitDest =
             CSLFetchNameValue( psWO->papszWarpOptions, "INIT_DEST" );
 
         // Special logic for destinations being initialized on the fly.
@@ -781,7 +778,7 @@ GDALWarpDstAlphaMasker( void *pMaskFuncArg, int nBandCount,
         // Read data.
         eErr = GDALRasterIO( hAlphaBand, GF_Read, nXOff, nYOff, nXSize, nYSize,
                              pafMask, nXSize, nYSize, GDT_Float32, 0, 0 );
-        
+
         if( eErr != CE_None )
             return eErr;
 
@@ -802,7 +799,7 @@ GDALWarpDstAlphaMasker( void *pMaskFuncArg, int nBandCount,
     {
         for( iPixel = nXSize * nYSize - 1; iPixel >= 0; iPixel-- )
             pafMask[iPixel] = (float)(int) ( pafMask[iPixel] * 255.1 );
-        
+
         // Write data.
 
         /* The VRT warper will pass destination sizes that may exceed */
@@ -815,10 +812,10 @@ GDALWarpDstAlphaMasker( void *pMaskFuncArg, int nBandCount,
         if (nYOff + nYSize > GDALGetRasterBandYSize(hAlphaBand))
             nDstYSize = GDALGetRasterBandYSize(hAlphaBand) - nYOff;
 
-        eErr = GDALRasterIO( hAlphaBand, GF_Write, 
-                             nXOff, nYOff, nDstXSize, nDstYSize, 
+        eErr = GDALRasterIO( hAlphaBand, GF_Write,
+                             nXOff, nYOff, nDstXSize, nDstYSize,
                              pafMask, nDstXSize, nDstYSize, GDT_Float32,
-                             0, sizeof(float) * nXSize );
+                             0, (int)sizeof(float) * nXSize );
         return eErr;
     }
 }
@@ -833,48 +830,48 @@ GDALWarpDstAlphaMasker( void *pMaskFuncArg, int nBandCount,
  * \var char **GDALWarpOptions::papszWarpOptions;
  *
  * A string list of additional options controlling the warp operation in
- * name=value format.  A suitable string list can be prepared with 
+ * name=value format.  A suitable string list can be prepared with
  * CSLSetNameValue().
  *
  * The following values are currently supported:
- * 
- *  - INIT_DEST=[value] or INIT_DEST=NO_DATA: This option forces the 
+ *
+ *  - INIT_DEST=[value] or INIT_DEST=NO_DATA: This option forces the
  * destination image to be initialized to the indicated value (for all bands)
  * or indicates that it should be initialized to the NO_DATA value in
  * padfDstNoDataReal/padfDstNoDataImag.  If this value isn't set the
- * destination image will be read and overlayed.  
+ * destination image will be read and overlaid.
  *
  * - WRITE_FLUSH=YES/NO: This option forces a flush to disk of data after
- * each chunk is processed.  In some cases this helps ensure a serial 
+ * each chunk is processed.  In some cases this helps ensure a serial
  * writing of the output data otherwise a block of data may be written to disk
- * each time a block of data is read for the input buffer resulting in alot
+ * each time a block of data is read for the input buffer resulting in a lot
  * of extra seeking around the disk, and reduced IO throughput.  The default
  * at this time is NO.
  *
  * - SKIP_NOSOURCE=YES/NO: Skip all processing for chunks for which there
- * is no corresponding input data.  This will disable initializing the 
+ * is no corresponding input data.  This will disable initializing the
  * destination (INIT_DEST) and all other processing, and so should be used
- * careful.  Mostly useful to short circuit a lot of extra work in mosaicing 
+ * careful.  Mostly useful to short circuit a lot of extra work in mosaicing
  * situations.
- * 
+ *
  * - UNIFIED_SRC_NODATA=YES/[NO]: By default nodata masking values considered
  * independently for each band.  However, sometimes it is desired to treat all
  * bands as nodata if and only if, all bands match the corresponding nodata
- * values.  To get this behavior set this option to YES. 
+ * values.  To get this behavior set this option to YES.
  *
- * Normally when computing the source raster data to 
+ * Normally when computing the source raster data to
  * load to generate a particular output area, the warper samples transforms
  * 21 points along each edge of the destination region back onto the source
  * file, and uses this to compute a bounding window on the source image that
- * is sufficient.  Depending on the transformation in effect, the source 
- * window may be a bit too small, or even missing large areas.  Problem 
- * situations are those where the transformation is very non-linear or 
+ * is sufficient.  Depending on the transformation in effect, the source
+ * window may be a bit too small, or even missing large areas.  Problem
+ * situations are those where the transformation is very non-linear or
  * "inside out".  Examples are transforming from WGS84 to Polar Steregraphic
  * for areas around the pole, or transformations where some of the image is
  * untransformable.  The following options provide some additional control
  * to deal with errors in computing the source window:
- * 
- * - SAMPLE_GRID=YES/NO: Setting this option to YES will force the sampling to 
+ *
+ * - SAMPLE_GRID=YES/NO: Setting this option to YES will force the sampling to
  * include internal points as well as edge points which can be important if
  * the transformation is esoteric inside out, or if large sections of the
  * destination image are not transformable into the source coordinate system.
@@ -885,8 +882,8 @@ GDALWarpDstAlphaMasker( void *pMaskFuncArg, int nBandCount,
  *
  * - SOURCE_EXTRA: This is a number of extra pixels added around the source
  * window for a given request, and by default it is 1 to take care of rounding
- * error.  Setting this larger will incease the amount of data that needs to
- * be read, but can avoid missing source data.  
+ * error.  Setting this larger will increase the amount of data that needs to
+ * be read, but can avoid missing source data.
  *
  * - CUTLINE: This may contain the WKT geometry for a cutline.  It will
  * be converted into a geometry by GDALWarpOperation::Initialize() and assigned
@@ -900,38 +897,43 @@ GDALWarpDstAlphaMasker( void *pMaskFuncArg, int nBandCount,
  * - CUTLINE_ALL_TOUCHED: This defaults to FALSE, but may be set to TRUE
  * to enable ALL_TOUCHEd mode when rasterizing cutline polygons.  This is
  * useful to ensure that that all pixels overlapping the cutline polygon
- * will be selected, not just those whose center point falls within the 
+ * will be selected, not just those whose center point falls within the
  * polygon.
  *
- * - OPTIMIZE_SIZE: This defaults to FALSE, but may be set to TRUE when
- * outputing typically to a compressed dataset (GeoTIFF with COMPRESSED creation
- * option set for example) for achieving a smaller file size. This is achieved
- * by writing at once data aligned on full blocks of the target dataset, which
- * avoids partial writes of compressed blocks and lost space when they are rewritten
- * at the end of the file. However sticking to target block size may cause major
+ * - OPTIMIZE_SIZE: This defaults to FALSE, but may be set to TRUE
+ * typically when writing to a compressed dataset (GeoTIFF with
+ * COMPRESSED creation option set for example) for achieving a smaller
+ * file size. This is achieved by writing at once data aligned on full
+ * blocks of the target dataset, which avoids partial writes of
+ * compressed blocks and lost space when they are rewritten at the end
+ * of the file. However sticking to target block size may cause major
  * processing slowdown for some particular reprojections.
  *
  * - NUM_THREADS: (GDAL >= 1.10) Can be set to a numeric value or ALL_CPUS to
  * set the number of threads to use to parallelize the computation part of the
  * warping. If not set, computation will be done in a single thread.
  *
- * - STREAMABLE_OUTPUT: (GDAL >= 2.0) This defaults to FALSE, but may be set to TRUE when
- * outputing typically to a streamed file. The gdalwarp utility automatically
- * sets this option when outputing to /vsistdout/ or a named pipe (on Unix).
- * This option has performance impacts for some reprojections.
- * Note: band interleaved output is not currently supported by the warping algorithm in
- * a streamable compabible way.
+ * - STREAMABLE_OUTPUT: (GDAL >= 2.0) This defaults to FALSE, but may
+ * be set to TRUE typically when writing to a streamed file. The
+ * gdalwarp utility automatically sets this option when writing to
+ * /vsistdout/ or a named pipe (on Unix).  This option has performance
+ * impacts for some reprojections.  Note: band interleaved output is
+ * not currently supported by the warping algorithm in a streamable
+ * compatible way.
  *
- * - SRC_COORD_PRECISION: (GDAL >= 2.0). Advanced setting. This defaults to 0, to indicate that
- * no rounding of computing source image coordinates corresponding to the target
- * image must be done. If greater than 0 (and typically below 1), this value,
- * expressed in pixel, will be used to round computed source image coordinates. The purpose
- * of this option is to make the results of warping with the approximated transformer
- * more reproducible and not sensitive to changes in warping memory size. To achieve
- * that, SRC_COORD_PRECISION must be at least 10 times greater than the error
- * threshold. The higher the SRC_COORD_PRECISION/error_threshold ratio, the higher
- * the performance will be, since exact reprojections must statistically be
- * done with a frequency of 4*error_threshold/SRC_COORD_PRECISION.
+ * - SRC_COORD_PRECISION: (GDAL >= 2.0). Advanced setting. This
+ * defaults to 0, to indicate that no rounding of computing source
+ * image coordinates corresponding to the target image must be
+ * done. If greater than 0 (and typically below 1), this value,
+ * expressed in pixel, will be used to round computed source image
+ * coordinates. The purpose of this option is to make the results of
+ * warping with the approximated transformer more reproducible and not
+ * sensitive to changes in warping memory size. To achieve that,
+ * SRC_COORD_PRECISION must be at least 10 times greater than the
+ * error threshold. The higher the SRC_COORD_PRECISION/error_threshold
+ * ratio, the higher the performance will be, since exact
+ * reprojections must statistically be done with a frequency of
+ * 4*error_threshold/SRC_COORD_PRECISION.
  */
 
 /************************************************************************/
@@ -1003,7 +1005,7 @@ GDALCloneWarpOptions( const GDALWarpOptions *psSrcOptions )
     memcpy( psDstOptions, psSrcOptions, sizeof(GDALWarpOptions) );
 
     if( psSrcOptions->papszWarpOptions != NULL )
-        psDstOptions->papszWarpOptions = 
+        psDstOptions->papszWarpOptions =
             CSLDuplicate( psSrcOptions->papszWarpOptions );
 
     COPY_MEM( panSrcBands, int, psSrcOptions->nBandCount );
@@ -1012,12 +1014,12 @@ GDALCloneWarpOptions( const GDALWarpOptions *psSrcOptions )
     COPY_MEM( padfSrcNoDataImag, double, psSrcOptions->nBandCount );
     COPY_MEM( padfDstNoDataReal, double, psSrcOptions->nBandCount );
     COPY_MEM( padfDstNoDataImag, double, psSrcOptions->nBandCount );
-    COPY_MEM( papfnSrcPerBandValidityMaskFunc, GDALMaskFunc, 
+    COPY_MEM( papfnSrcPerBandValidityMaskFunc, GDALMaskFunc,
               psSrcOptions->nBandCount );
     psDstOptions->papSrcPerBandValidityMaskFuncArg = NULL;
 
     if( psSrcOptions->hCutline != NULL )
-        psDstOptions->hCutline = 
+        psDstOptions->hCutline =
             OGR_G_Clone( (OGRGeometryH) psSrcOptions->hCutline );
     psDstOptions->dfCutlineBlendDist = psSrcOptions->dfCutlineBlendDist;
 
@@ -1028,7 +1030,7 @@ GDALCloneWarpOptions( const GDALWarpOptions *psSrcOptions )
 /*                      GDALSerializeWarpOptions()                      */
 /************************************************************************/
 
-CPLXMLNode * CPL_STDCALL 
+CPLXMLNode * CPL_STDCALL
 GDALSerializeWarpOptions( const GDALWarpOptions *psWO )
 
 {
@@ -1038,12 +1040,12 @@ GDALSerializeWarpOptions( const GDALWarpOptions *psWO )
 /*      Create root.                                                    */
 /* -------------------------------------------------------------------- */
     psTree = CPLCreateXMLNode( NULL, CXT_Element, "GDALWarpOptions" );
-    
+
 /* -------------------------------------------------------------------- */
 /*      WarpMemoryLimit                                                 */
 /* -------------------------------------------------------------------- */
-    CPLCreateXMLElementAndValue( 
-        psTree, "WarpMemoryLimit", 
+    CPLCreateXMLElementAndValue(
+        psTree, "WarpMemoryLimit",
         CPLString().Printf("%g", psWO->dfWarpMemoryLimit ) );
 
 /* -------------------------------------------------------------------- */
@@ -1078,15 +1080,15 @@ GDALSerializeWarpOptions( const GDALWarpOptions *psWO )
     else
         pszAlgName = "Unknown";
 
-    CPLCreateXMLElementAndValue( 
+    CPLCreateXMLElementAndValue(
         psTree, "ResampleAlg", pszAlgName );
 
 /* -------------------------------------------------------------------- */
 /*      Working Data Type                                               */
 /* -------------------------------------------------------------------- */
 
-    CPLCreateXMLElementAndValue( 
-        psTree, "WorkingDataType", 
+    CPLCreateXMLElementAndValue(
+        psTree, "WorkingDataType",
         GDALGetDataTypeName( psWO->eWorkingDataType ) );
 
 /* -------------------------------------------------------------------- */
@@ -1094,22 +1096,22 @@ GDALSerializeWarpOptions( const GDALWarpOptions *psWO )
 /* -------------------------------------------------------------------- */
     int iWO;
 
-    for( iWO = 0; psWO->papszWarpOptions != NULL 
+    for( iWO = 0; psWO->papszWarpOptions != NULL
              && psWO->papszWarpOptions[iWO] != NULL; iWO++ )
     {
         char *pszName = NULL;
-        const char *pszValue = 
+        const char *pszValue =
             CPLParseNameValue( psWO->papszWarpOptions[iWO], &pszName );
-            
+
         /* EXTRA_ELTS is an internal detail that we will recover */
         /* no need to serialize it */
         if( !EQUAL(pszName, "EXTRA_ELTS") )
         {
-            CPLXMLNode *psOption = 
-                CPLCreateXMLElementAndValue( 
+            CPLXMLNode *psOption =
+                CPLCreateXMLElementAndValue(
                     psTree, "Option", pszValue );
 
-            CPLCreateXMLNode( 
+            CPLCreateXMLNode(
                 CPLCreateXMLNode( psOption, CXT_Attribute, "name" ),
                 CXT_Text, pszName );
         }
@@ -1122,21 +1124,21 @@ GDALSerializeWarpOptions( const GDALWarpOptions *psWO )
 /* -------------------------------------------------------------------- */
     if( psWO->hSrcDS != NULL )
     {
-        CPLCreateXMLElementAndValue( 
-            psTree, "SourceDataset", 
+        CPLCreateXMLElementAndValue(
+            psTree, "SourceDataset",
             GDALGetDescription( psWO->hSrcDS ) );
-        
+
         char** papszOpenOptions = ((GDALDataset*)psWO->hSrcDS)->GetOpenOptions();
         GDALSerializeOpenOptionsToXML(psTree, papszOpenOptions);
     }
-    
+
     if( psWO->hDstDS != NULL && strlen(GDALGetDescription(psWO->hDstDS)) != 0 )
     {
-        CPLCreateXMLElementAndValue( 
-            psTree, "DestinationDataset", 
+        CPLCreateXMLElementAndValue(
+            psTree, "DestinationDataset",
             GDALGetDescription( psWO->hDstDS ) );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Serialize transformer.                                          */
 /* -------------------------------------------------------------------- */
@@ -1145,10 +1147,10 @@ GDALSerializeWarpOptions( const GDALWarpOptions *psWO )
         CPLXMLNode *psTransformerContainer;
         CPLXMLNode *psTransformerTree;
 
-        psTransformerContainer = 
+        psTransformerContainer =
             CPLCreateXMLNode( psTree, CXT_Element, "Transformer" );
 
-        psTransformerTree = 
+        psTransformerTree =
             GDALSerializeTransformer( psWO->pfnTransformer,
                                       psWO->pTransformerArg );
 
@@ -1171,21 +1173,21 @@ GDALSerializeWarpOptions( const GDALWarpOptions *psWO )
 
         psBand = CPLCreateXMLNode( psBandList, CXT_Element, "BandMapping" );
         if( psWO->panSrcBands != NULL )
-            CPLCreateXMLNode( 
+            CPLCreateXMLNode(
                 CPLCreateXMLNode( psBand, CXT_Attribute, "src" ),
                 CXT_Text, CPLString().Printf( "%d", psWO->panSrcBands[i] ) );
         if( psWO->panDstBands != NULL )
-            CPLCreateXMLNode( 
+            CPLCreateXMLNode(
                 CPLCreateXMLNode( psBand, CXT_Attribute, "dst" ),
                 CXT_Text, CPLString().Printf( "%d", psWO->panDstBands[i] ) );
-        
+
         if( psWO->padfSrcNoDataReal != NULL )
         {
             if (CPLIsNan(psWO->padfSrcNoDataReal[i]))
                 CPLCreateXMLElementAndValue(psBand, "SrcNoDataReal", "nan");
             else
-                CPLCreateXMLElementAndValue( 
-                    psBand, "SrcNoDataReal", 
+                CPLCreateXMLElementAndValue(
+                    psBand, "SrcNoDataReal",
                     CPLString().Printf( "%.16g", psWO->padfSrcNoDataReal[i] ) );
         }
 
@@ -1194,8 +1196,8 @@ GDALSerializeWarpOptions( const GDALWarpOptions *psWO )
             if (CPLIsNan(psWO->padfSrcNoDataImag[i]))
                 CPLCreateXMLElementAndValue(psBand, "SrcNoDataImag", "nan");
             else
-                CPLCreateXMLElementAndValue( 
-                    psBand, "SrcNoDataImag", 
+                CPLCreateXMLElementAndValue(
+                    psBand, "SrcNoDataImag",
                     CPLString().Printf( "%.16g", psWO->padfSrcNoDataImag[i] ) );
         }
 
@@ -1204,8 +1206,8 @@ GDALSerializeWarpOptions( const GDALWarpOptions *psWO )
             if (CPLIsNan(psWO->padfDstNoDataReal[i]))
                 CPLCreateXMLElementAndValue(psBand, "DstNoDataReal", "nan");
             else
-                CPLCreateXMLElementAndValue( 
-                    psBand, "DstNoDataReal", 
+                CPLCreateXMLElementAndValue(
+                    psBand, "DstNoDataReal",
                     CPLString().Printf( "%.16g", psWO->padfDstNoDataReal[i] ) );
         }
 
@@ -1214,8 +1216,8 @@ GDALSerializeWarpOptions( const GDALWarpOptions *psWO )
             if (CPLIsNan(psWO->padfDstNoDataImag[i]))
                 CPLCreateXMLElementAndValue(psBand, "DstNoDataImag", "nan");
             else
-                CPLCreateXMLElementAndValue( 
-                    psBand, "DstNoDataImag", 
+                CPLCreateXMLElementAndValue(
+                    psBand, "DstNoDataImag",
                     CPLString().Printf( "%.16g", psWO->padfDstNoDataImag[i] ) );
         }
     }
@@ -1224,13 +1226,13 @@ GDALSerializeWarpOptions( const GDALWarpOptions *psWO )
 /*      Alpha bands.                                                    */
 /* -------------------------------------------------------------------- */
     if( psWO->nSrcAlphaBand > 0 )
-        CPLCreateXMLElementAndValue( 
-            psTree, "SrcAlphaBand", 
+        CPLCreateXMLElementAndValue(
+            psTree, "SrcAlphaBand",
             CPLString().Printf( "%d", psWO->nSrcAlphaBand ) );
 
     if( psWO->nDstAlphaBand > 0 )
-        CPLCreateXMLElementAndValue( 
-            psTree, "DstAlphaBand", 
+        CPLCreateXMLElementAndValue(
+            psTree, "DstAlphaBand",
             CPLString().Printf( "%d", psWO->nDstAlphaBand ) );
 
 /* -------------------------------------------------------------------- */
@@ -1248,8 +1250,8 @@ GDALSerializeWarpOptions( const GDALWarpOptions *psWO )
     }
 
     if( psWO->dfCutlineBlendDist != 0.0 )
-        CPLCreateXMLElementAndValue( 
-            psTree, "CutlineBlendDist", 
+        CPLCreateXMLElementAndValue(
+            psTree, "CutlineBlendDist",
             CPLString().Printf( "%.5g", psWO->dfCutlineBlendDist ) );
 
     return psTree;
@@ -1270,7 +1272,7 @@ GDALWarpOptions * CPL_STDCALL GDALDeserializeWarpOptions( CPLXMLNode *psTree )
     if( psTree == NULL || psTree->eType != CXT_Element
         || !EQUAL(psTree->pszValue,"GDALWarpOptions") )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Wrong node, unable to deserialize GDALWarpOptions." );
         return NULL;
     }
@@ -1283,13 +1285,13 @@ GDALWarpOptions * CPL_STDCALL GDALDeserializeWarpOptions( CPLXMLNode *psTree )
 /* -------------------------------------------------------------------- */
 /*      Warp memory limit.                                              */
 /* -------------------------------------------------------------------- */
-    psWO->dfWarpMemoryLimit = 
+    psWO->dfWarpMemoryLimit =
         CPLAtof(CPLGetXMLValue(psTree,"WarpMemoryLimit","0.0"));
 
 /* -------------------------------------------------------------------- */
 /*      resample algorithm                                              */
 /* -------------------------------------------------------------------- */
-    const char *pszValue = 
+    const char *pszValue =
         CPLGetXMLValue(psTree,"ResampleAlg","Default");
 
     if( EQUAL(pszValue,"NearestNeighbour") )
@@ -1320,7 +1322,7 @@ GDALWarpOptions * CPL_STDCALL GDALDeserializeWarpOptions( CPLXMLNode *psTree )
         /* leave as is */;
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unrecognise ResampleAlg value '%s'.",
                   pszValue );
     }
@@ -1328,32 +1330,32 @@ GDALWarpOptions * CPL_STDCALL GDALDeserializeWarpOptions( CPLXMLNode *psTree )
 /* -------------------------------------------------------------------- */
 /*      Working data type.                                              */
 /* -------------------------------------------------------------------- */
-    psWO->eWorkingDataType = 
+    psWO->eWorkingDataType =
         GDALGetDataTypeByName(
             CPLGetXMLValue(psTree,"WorkingDataType","Unknown"));
 
 /* -------------------------------------------------------------------- */
 /*      Name/value warp options.                                        */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psItem; 
+    CPLXMLNode *psItem;
 
     for( psItem = psTree->psChild; psItem != NULL; psItem = psItem->psNext )
     {
-        if( psItem->eType == CXT_Element 
+        if( psItem->eType == CXT_Element
             && EQUAL(psItem->pszValue,"Option") )
         {
             const char *pszName = CPLGetXMLValue(psItem, "Name", NULL );
-            const char *pszValue = CPLGetXMLValue(psItem, "", NULL );
+            pszValue = CPLGetXMLValue(psItem, "", NULL );
 
             if( pszName != NULL && pszValue != NULL )
             {
-                psWO->papszWarpOptions = 
-                    CSLSetNameValue( psWO->papszWarpOptions, 
+                psWO->papszWarpOptions =
+                    CSLSetNameValue( psWO->papszWarpOptions,
                                      pszName, pszValue );
             }
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Source Dataset.                                                 */
 /* -------------------------------------------------------------------- */
@@ -1383,7 +1385,7 @@ GDALWarpOptions * CPL_STDCALL GDALDeserializeWarpOptions( CPLXMLNode *psTree )
     CPLXMLNode *psBand = NULL;
 
     psWO->nBandCount = 0;
-    
+
     if (psBandTree)
         psBand = psBandTree->psChild;
     else
@@ -1391,7 +1393,7 @@ GDALWarpOptions * CPL_STDCALL GDALDeserializeWarpOptions( CPLXMLNode *psTree )
 
     for( ; psBand != NULL; psBand = psBand->psNext )
     {
-        if( psBand->eType != CXT_Element 
+        if( psBand->eType != CXT_Element
             || !EQUAL(psBand->pszValue,"BandMapping") )
             continue;
 
@@ -1410,7 +1412,7 @@ GDALWarpOptions * CPL_STDCALL GDALDeserializeWarpOptions( CPLXMLNode *psTree )
 
     for( ; psBand != NULL; psBand = psBand->psNext )
     {
-        if( psBand->eType != CXT_Element 
+        if( psBand->eType != CXT_Element
             || !EQUAL(psBand->pszValue,"BandMapping") )
             continue;
 
@@ -1419,13 +1421,13 @@ GDALWarpOptions * CPL_STDCALL GDALDeserializeWarpOptions( CPLXMLNode *psTree )
 /* -------------------------------------------------------------------- */
         if( psWO->panSrcBands == NULL )
             psWO->panSrcBands = (int *)CPLMalloc(sizeof(int)*psWO->nBandCount);
-        
+
         pszValue = CPLGetXMLValue(psBand,"src",NULL);
         if( pszValue == NULL )
             psWO->panSrcBands[iBand] = iBand+1;
         else
             psWO->panSrcBands[iBand] = atoi(pszValue);
-        
+
 /* -------------------------------------------------------------------- */
 /*      Destination band.                                               */
 /* -------------------------------------------------------------------- */
@@ -1433,12 +1435,12 @@ GDALWarpOptions * CPL_STDCALL GDALDeserializeWarpOptions( CPLXMLNode *psTree )
         if( pszValue != NULL )
         {
             if( psWO->panDstBands == NULL )
-                psWO->panDstBands = 
+                psWO->panDstBands =
                     (int *) CPLMalloc(sizeof(int)*psWO->nBandCount);
 
             psWO->panDstBands[iBand] = atoi(pszValue);
         }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Source nodata.                                                  */
 /* -------------------------------------------------------------------- */
@@ -1446,22 +1448,22 @@ GDALWarpOptions * CPL_STDCALL GDALDeserializeWarpOptions( CPLXMLNode *psTree )
         if( pszValue != NULL )
         {
             if( psWO->padfSrcNoDataReal == NULL )
-                psWO->padfSrcNoDataReal = 
+                psWO->padfSrcNoDataReal =
                     (double *) CPLCalloc(sizeof(double),psWO->nBandCount);
 
             psWO->padfSrcNoDataReal[iBand] = CPLAtof(pszValue);
         }
-        
+
         pszValue = CPLGetXMLValue(psBand,"SrcNoDataImag",NULL);
         if( pszValue != NULL )
         {
             if( psWO->padfSrcNoDataImag == NULL )
-                psWO->padfSrcNoDataImag = 
+                psWO->padfSrcNoDataImag =
                     (double *) CPLCalloc(sizeof(double),psWO->nBandCount);
 
             psWO->padfSrcNoDataImag[iBand] = CPLAtof(pszValue);
         }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Destination nodata.                                             */
 /* -------------------------------------------------------------------- */
@@ -1469,31 +1471,31 @@ GDALWarpOptions * CPL_STDCALL GDALDeserializeWarpOptions( CPLXMLNode *psTree )
         if( pszValue != NULL )
         {
             if( psWO->padfDstNoDataReal == NULL )
-                psWO->padfDstNoDataReal = 
+                psWO->padfDstNoDataReal =
                     (double *) CPLCalloc(sizeof(double),psWO->nBandCount);
 
             psWO->padfDstNoDataReal[iBand] = CPLAtof(pszValue);
         }
-        
+
         pszValue = CPLGetXMLValue(psBand,"DstNoDataImag",NULL);
         if( pszValue != NULL )
         {
             if( psWO->padfDstNoDataImag == NULL )
-                psWO->padfDstNoDataImag = 
+                psWO->padfDstNoDataImag =
                     (double *) CPLCalloc(sizeof(double),psWO->nBandCount);
 
             psWO->padfDstNoDataImag[iBand] = CPLAtof(pszValue);
         }
-        
+
         iBand++;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Alpha bands.                                                    */
 /* -------------------------------------------------------------------- */
-    psWO->nSrcAlphaBand = 
+    psWO->nSrcAlphaBand =
         atoi( CPLGetXMLValue( psTree, "SrcAlphaBand", "0" ) );
-    psWO->nDstAlphaBand = 
+    psWO->nDstAlphaBand =
         atoi( CPLGetXMLValue( psTree, "DstAlphaBand", "0" ) );
 
 /* -------------------------------------------------------------------- */
@@ -1502,7 +1504,7 @@ GDALWarpOptions * CPL_STDCALL GDALDeserializeWarpOptions( CPLXMLNode *psTree )
     const char *pszWKT = CPLGetXMLValue( psTree, "Cutline", NULL );
     if( pszWKT )
     {
-        OGR_G_CreateFromWkt( (char **) &pszWKT, NULL, 
+        OGR_G_CreateFromWkt( (char **) &pszWKT, NULL,
                              (OGRGeometryH *) (&psWO->hCutline) );
     }
 
@@ -1516,15 +1518,15 @@ GDALWarpOptions * CPL_STDCALL GDALDeserializeWarpOptions( CPLXMLNode *psTree )
 
     if( psTransformer != NULL && psTransformer->psChild != NULL )
     {
-        GDALDeserializeTransformer( psTransformer->psChild, 
+        GDALDeserializeTransformer( psTransformer->psChild,
                                     &(psWO->pfnTransformer),
                                     &(psWO->pTransformerArg) );
     }
 
 /* -------------------------------------------------------------------- */
-/*      If any error has occured, cleanup else return success.          */
+/*      If any error has occurred, cleanup else return success.          */
 /* -------------------------------------------------------------------- */
-    if( CPLGetLastErrorNo() != CE_None )
+    if( CPLGetLastErrorType() != CE_None )
     {
         if ( psWO->pTransformerArg )
         {
diff --git a/alg/gdalwarper.h b/alg/gdalwarper.h
index 4221bf1..9cf35ef 100644
--- a/alg/gdalwarper.h
+++ b/alg/gdalwarper.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalwarper.h 29330 2015-06-14 12:11:11Z rouault $
+ * $Id: gdalwarper.h 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  GDAL High Performance Warper
  * Purpose:  Prototypes, and definitions for warping related work.
@@ -45,7 +45,7 @@
 
 CPL_C_START
 
-/* Note: values are selected to be consistent with GDALRIOResampleAlg of gcore/gdal.h */ 
+/* Note: values are selected to be consistent with GDALRIOResampleAlg of gcore/gdal.h */
 /*! Warp Resampling Algorithm */
 typedef enum {
   /*! Nearest neighbour (select on one input pixel) */ GRA_NearestNeighbour=0,
@@ -53,7 +53,7 @@ typedef enum {
   /*! Cubic Convolution Approximation (4x4 kernel) */  GRA_Cubic=2,
   /*! Cubic B-Spline Approximation (4x4 kernel) */     GRA_CubicSpline=3,
   /*! Lanczos windowed sinc interpolation (6x6 kernel) */ GRA_Lanczos=4,
-  /*! Average (computes the average of all non-NODATA contributing pixels) */ GRA_Average=5, 
+  /*! Average (computes the average of all non-NODATA contributing pixels) */ GRA_Average=5,
   /*! Mode (selects the value which appears most often of all the sampled points) */ GRA_Mode=6,
   // GRA_Gauss=7 reserved.
   /*! Max (selects maximum of all non-NODATA contributing pixels) */ GRA_Max=8,
@@ -73,38 +73,38 @@ typedef enum {
     /*! Quantile */ GWKAOM_Quant=6
 } GWKAverageOrModeAlg;
 
-typedef int 
+typedef int
 (*GDALMaskFunc)( void *pMaskFuncArg,
-                 int nBandCount, GDALDataType eType, 
-                 int nXOff, int nYOff, 
+                 int nBandCount, GDALDataType eType,
+                 int nXOff, int nYOff,
                  int nXSize, int nYSize,
-                 GByte **papabyImageData, 
+                 GByte **papabyImageData,
                  int bMaskIsFloat, void *pMask );
 
-CPLErr CPL_DLL 
+CPLErr CPL_DLL
 GDALWarpNoDataMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
                       int nXOff, int nYOff, int nXSize, int nYSize,
                       GByte **papabyImageData, int bMaskIsFloat,
                       void *pValidityMask, int* pbOutAllValid );
 
-CPLErr CPL_DLL 
+CPLErr CPL_DLL
 GDALWarpDstAlphaMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
                         int nXOff, int nYOff, int nXSize, int nYSize,
                         GByte ** /*ppImageData */,
                         int bMaskIsFloat, void *pValidityMask );
-CPLErr CPL_DLL 
+CPLErr CPL_DLL
 GDALWarpSrcAlphaMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
                         int nXOff, int nYOff, int nXSize, int nYSize,
                         GByte ** /*ppImageData */,
                         int bMaskIsFloat, void *pValidityMask, int* pbOutAllOpaque );
 
-CPLErr CPL_DLL 
+CPLErr CPL_DLL
 GDALWarpSrcMaskMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
                        int nXOff, int nYOff, int nXSize, int nYSize,
                        GByte ** /*ppImageData */,
                        int bMaskIsFloat, void *pValidityMask );
 
-CPLErr CPL_DLL 
+CPLErr CPL_DLL
 GDALWarpCutlineMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
                        int nXOff, int nYOff, int nXSize, int nYSize,
                        GByte ** /* ppImageData */,
@@ -116,11 +116,11 @@ GDALWarpCutlineMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
 
 /** Warp control options for use with GDALWarpOperation::Initialize()  */
 typedef struct {
-    
-    char              **papszWarpOptions;  
+
+    char              **papszWarpOptions;
 
     /*! In bytes, 0.0 for internal default */
-    double              dfWarpMemoryLimit; 
+    double              dfWarpMemoryLimit;
 
     /*! Resampling algorithm to use */
     GDALResampleAlg     eResampleAlg;
@@ -137,7 +137,7 @@ typedef struct {
 
     /*! Number of bands to process, may be 0 to select all bands. */
     int                 nBandCount;
-    
+
     /*! The band numbers for the source bands to process (1 based) */
     int                *panSrcBands;
 
@@ -152,13 +152,13 @@ typedef struct {
 
     /*! The "nodata" value real component for each input band, if NULL there isn't one */
     double             *padfSrcNoDataReal;
-    /*! The "nodata" value imaginary component - may be NULL even if real 
+    /*! The "nodata" value imaginary component - may be NULL even if real
       component is provided. */
     double             *padfSrcNoDataImag;
 
     /*! The "nodata" value real component for each output band, if NULL there isn't one */
     double             *padfDstNoDataReal;
-    /*! The "nodata" value imaginary component - may be NULL even if real 
+    /*! The "nodata" value imaginary component - may be NULL even if real
       component is provided. */
     double             *padfDstNoDataImag;
 
@@ -177,10 +177,10 @@ typedef struct {
 
     GDALMaskFunc       *papfnSrcPerBandValidityMaskFunc;
     void              **papSrcPerBandValidityMaskFuncArg;
-    
+
     GDALMaskFunc        pfnSrcValidityMaskFunc;
     void               *pSrcValidityMaskFuncArg;
-    
+
     GDALMaskFunc        pfnSrcDensityMaskFunc;
     void               *pSrcDensityMaskFuncArg;
 
@@ -192,7 +192,7 @@ typedef struct {
 
     CPLErr              (*pfnPreWarpChunkProcessor)( void *pKern, void *pArg );
     void               *pPreWarpProcessorArg;
-    
+
     CPLErr              (*pfnPostWarpChunkProcessor)( void *pKern, void *pArg);
     void               *pPostWarpProcessorArg;
 
@@ -219,20 +219,20 @@ GDALWarpOptions CPL_DLL * CPL_STDCALL
 /************************************************************************/
 
 CPLErr CPL_DLL CPL_STDCALL
-GDALReprojectImage( GDALDatasetH hSrcDS, const char *pszSrcWKT, 
+GDALReprojectImage( GDALDatasetH hSrcDS, const char *pszSrcWKT,
                     GDALDatasetH hDstDS, const char *pszDstWKT,
                     GDALResampleAlg eResampleAlg, double dfWarpMemoryLimit,
                     double dfMaxError,
-                    GDALProgressFunc pfnProgress, void *pProgressArg, 
+                    GDALProgressFunc pfnProgress, void *pProgressArg,
                     GDALWarpOptions *psOptions );
 
 CPLErr CPL_DLL CPL_STDCALL
-GDALCreateAndReprojectImage( GDALDatasetH hSrcDS, const char *pszSrcWKT, 
+GDALCreateAndReprojectImage( GDALDatasetH hSrcDS, const char *pszSrcWKT,
                     const char *pszDstFilename, const char *pszDstWKT,
                     GDALDriverH hDstDriver, char **papszCreateOptions,
                     GDALResampleAlg eResampleAlg, double dfWarpMemoryLimit,
                     double dfMaxError,
-                    GDALProgressFunc pfnProgress, void *pProgressArg, 
+                    GDALProgressFunc pfnProgress, void *pProgressArg,
                     GDALWarpOptions *psOptions );
 
 /************************************************************************/
@@ -240,23 +240,23 @@ GDALCreateAndReprojectImage( GDALDatasetH hSrcDS, const char *pszSrcWKT,
 /************************************************************************/
 
 GDALDatasetH CPL_DLL CPL_STDCALL
-GDALAutoCreateWarpedVRT( GDALDatasetH hSrcDS, 
-                         const char *pszSrcWKT, const char *pszDstWKT, 
-                         GDALResampleAlg eResampleAlg, 
+GDALAutoCreateWarpedVRT( GDALDatasetH hSrcDS,
+                         const char *pszSrcWKT, const char *pszDstWKT,
+                         GDALResampleAlg eResampleAlg,
                          double dfMaxError, const GDALWarpOptions *psOptions );
 
-GDALDatasetH CPL_DLL CPL_STDCALL 
-GDALCreateWarpedVRT( GDALDatasetH hSrcDS, 
+GDALDatasetH CPL_DLL CPL_STDCALL
+GDALCreateWarpedVRT( GDALDatasetH hSrcDS,
                      int nPixels, int nLines, double *padfGeoTransform,
                      GDALWarpOptions *psOptions );
 
 CPLErr CPL_DLL CPL_STDCALL
-GDALInitializeWarpedVRT( GDALDatasetH hDS, 
+GDALInitializeWarpedVRT( GDALDatasetH hDS,
                          GDALWarpOptions *psWO );
 
 CPL_C_END
 
-#ifdef __cplusplus 
+#ifdef __cplusplus
 
 /************************************************************************/
 /*                            GDALWarpKernel                            */
@@ -308,13 +308,13 @@ public:
     int                 nYRadius;
     int                 nFiltInitX; // Filtering offset
     int                 nFiltInitY;
-    
+
     int                 nSrcXOff;
     int                 nSrcYOff;
 
     int                 nDstXOff;
     int                 nDstYOff;
-        
+
     GDALTransformerFunc pfnTransformer;
     void                *pTransformerArg;
 
@@ -323,9 +323,11 @@ public:
 
     double              dfProgressBase;
     double              dfProgressScale;
-    
+
     double              *padfDstNoDataReal;
 
+    void                *psThreadData;
+
                        GDALWarpKernel();
     virtual           ~GDALWarpKernel();
 
@@ -333,6 +335,11 @@ public:
     CPLErr              PerformWarp();
 };
 
+void* GWKThreadsCreate(char** papszWarpOptions,
+                       GDALTransformerFunc pfnTransformer,
+                       void* pTransformerArg);
+void GWKThreadsEnd(void* psThreadDataIn);
+
 /************************************************************************/
 /*                         GDALWarpOperation()                          */
 /*                                                                      */
@@ -352,14 +359,14 @@ private:
     void            WipeOptions();
     int             ValidateOptions();
 
-    CPLErr          ComputeSourceWindow( int nDstXOff, int nDstYOff, 
+    CPLErr          ComputeSourceWindow( int nDstXOff, int nDstYOff,
                                          int nDstXSize, int nDstYSize,
-                                         int *pnSrcXOff, int *pnSrcYOff, 
+                                         int *pnSrcXOff, int *pnSrcYOff,
                                          int *pnSrcXSize, int *pnSrcYSize,
                                          int *pnSrcXExtraSize, int *pnSrcYExtraSize,
                                          double* pdfSrcFillRatio );
 
-    CPLErr          CreateKernelMask( GDALWarpKernel *, int iBand, 
+    CPLErr          CreateKernelMask( GDALWarpKernel *, int iBand,
                                       const char *pszType );
 
     CPLMutex        *hIOMutex;
@@ -372,11 +379,13 @@ private:
     int             bReportTimings;
     unsigned long   nLastTimeReported;
 
+    void           *psThreadData;
+
     void            WipeChunkList();
-    CPLErr          CollectChunkList( int nDstXOff, int nDstYOff, 
+    CPLErr          CollectChunkList( int nDstXOff, int nDstYOff,
                                       int nDstXSize, int nDstYSize );
     void            ReportTiming( const char * );
-    
+
 public:
                     GDALWarpOperation();
     virtual        ~GDALWarpOperation();
@@ -385,31 +394,31 @@ public:
 
     const GDALWarpOptions         *GetOptions();
 
-    CPLErr          ChunkAndWarpImage( int nDstXOff, int nDstYOff, 
+    CPLErr          ChunkAndWarpImage( int nDstXOff, int nDstYOff,
                                        int nDstXSize, int nDstYSize );
-    CPLErr          ChunkAndWarpMulti( int nDstXOff, int nDstYOff, 
+    CPLErr          ChunkAndWarpMulti( int nDstXOff, int nDstYOff,
                                        int nDstXSize, int nDstYSize );
-    CPLErr          WarpRegion( int nDstXOff, int nDstYOff, 
+    CPLErr          WarpRegion( int nDstXOff, int nDstYOff,
                                 int nDstXSize, int nDstYSize,
                                 int nSrcXOff=0, int nSrcYOff=0,
                                 int nSrcXSize=0, int nSrcYSize=0,
                                 double dfProgressBase=0.0, double dfProgressScale=1.0);
-    CPLErr          WarpRegion( int nDstXOff, int nDstYOff, 
+    CPLErr          WarpRegion( int nDstXOff, int nDstYOff,
                                 int nDstXSize, int nDstYSize,
                                 int nSrcXOff, int nSrcYOff,
                                 int nSrcXSize, int nSrcYSize,
                                 int nSrcXExtraSize, int nSrcYExtraSize,
                                 double dfProgressBase, double dfProgressScale);
-    CPLErr          WarpRegionToBuffer( int nDstXOff, int nDstYOff, 
-                                        int nDstXSize, int nDstYSize, 
-                                        void *pDataBuf, 
+    CPLErr          WarpRegionToBuffer( int nDstXOff, int nDstYOff,
+                                        int nDstXSize, int nDstYSize,
+                                        void *pDataBuf,
                                         GDALDataType eBufDataType,
                                         int nSrcXOff=0, int nSrcYOff=0,
                                         int nSrcXSize=0, int nSrcYSize=0,
                                         double dfProgressBase=0.0, double dfProgressScale=1.0);
-    CPLErr          WarpRegionToBuffer( int nDstXOff, int nDstYOff, 
-                                        int nDstXSize, int nDstYSize, 
-                                        void *pDataBuf, 
+    CPLErr          WarpRegionToBuffer( int nDstXOff, int nDstYOff,
+                                        int nDstXSize, int nDstYSize,
+                                        void *pDataBuf,
                                         GDALDataType eBufDataType,
                                         int nSrcXOff, int nSrcYOff,
                                         int nSrcXSize, int nSrcYSize,
diff --git a/alg/gdalwarpkernel.cpp b/alg/gdalwarpkernel.cpp
index 27b7679..b5f2e4d 100644
--- a/alg/gdalwarpkernel.cpp
+++ b/alg/gdalwarpkernel.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalwarpkernel.cpp 28946 2015-04-18 20:12:47Z rouault $
+ * $Id: gdalwarpkernel.cpp 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  High Performance Image Reprojector
  * Purpose:  Implementation of the GDALWarpKernel class.  Implements the actual
@@ -39,12 +39,13 @@
 #include "cpl_string.h"
 #include "gdalwarpkernel_opencl.h"
 #include "cpl_atomic_ops.h"
-#include "cpl_multiproc.h"
+#include "cpl_worker_thread_pool.h"
 #include <limits>
+#include <new>
 
-CPL_CVSID("$Id: gdalwarpkernel.cpp 28946 2015-04-18 20:12:47Z rouault $");
+CPL_CVSID("$Id: gdalwarpkernel.cpp 33715 2016-03-13 08:52:06Z goatbar $");
 
-//#define INSTANCIATE_FLOAT64_SSE2_IMPL
+//#define INSTANTIATE_FLOAT64_SSE2_IMPL
 
 static const int anGWKFilterRadius[] =
 {
@@ -131,7 +132,7 @@ static CPLErr GWKNearestNoMasksOrDstDensityOnlyByte( GDALWarpKernel *poWK );
 static CPLErr GWKBilinearNoMasksOrDstDensityOnlyByte( GDALWarpKernel *poWK );
 static CPLErr GWKCubicNoMasksOrDstDensityOnlyByte( GDALWarpKernel *poWK );
 static CPLErr GWKCubicNoMasksOrDstDensityOnlyFloat( GDALWarpKernel *poWK );
-#ifdef INSTANCIATE_FLOAT64_SSE2_IMPL
+#ifdef INSTANTIATE_FLOAT64_SSE2_IMPL
 static CPLErr GWKCubicNoMasksOrDstDensityOnlyDouble( GDALWarpKernel *poWK );
 #endif
 static CPLErr GWKCubicSplineNoMasksOrDstDensityOnlyByte( GDALWarpKernel *poWK );
@@ -139,7 +140,7 @@ static CPLErr GWKNearestByte( GDALWarpKernel *poWK );
 static CPLErr GWKNearestNoMasksOrDstDensityOnlyShort( GDALWarpKernel *poWK );
 static CPLErr GWKBilinearNoMasksOrDstDensityOnlyShort( GDALWarpKernel *poWK );
 static CPLErr GWKBilinearNoMasksOrDstDensityOnlyFloat( GDALWarpKernel *poWK );
-#ifdef INSTANCIATE_FLOAT64_SSE2_IMPL
+#ifdef INSTANTIATE_FLOAT64_SSE2_IMPL
 static CPLErr GWKBilinearNoMasksOrDstDensityOnlyDouble( GDALWarpKernel *poWK );
 #endif
 static CPLErr GWKCubicNoMasksOrDstDensityOnlyShort( GDALWarpKernel *poWK );
@@ -160,7 +161,6 @@ typedef struct _GWKJobStruct GWKJobStruct;
 
 struct _GWKJobStruct
 {
-    CPLJoinableThread *hThread;
     GDALWarpKernel *poWK;
     int             iYMin;
     int             iYMax;
@@ -170,6 +170,10 @@ struct _GWKJobStruct
     CPLMutex       *hCondMutex;
     int           (*pfnProgress)(GWKJobStruct* psJob);
     void           *pTransformerArg;
+
+    // Just used during thread initialization phase
+    GDALTransformerFunc pfnTransformerInit;
+    void           *pTransformerArgInit;
 } ;
 
 /************************************************************************/
@@ -226,7 +230,6 @@ static CPLErr GWKGenericMonoThread( GDALWarpKernel *poWK,
     sThreadJob.pbStop = &bStop;
     sThreadJob.hCond = NULL;
     sThreadJob.hCondMutex = NULL;
-    sThreadJob.hThread = NULL;
     sThreadJob.pfnProgress = GWKProgressMonoThread;
     sThreadJob.pTransformerArg = poWK->pTransformerArg;
 
@@ -236,62 +239,114 @@ static CPLErr GWKGenericMonoThread( GDALWarpKernel *poWK,
 }
 
 /************************************************************************/
-/*                                GWKRun()                              */
+/*                     GWKThreadInitTransformer()                       */
 /************************************************************************/
 
-static CPLErr GWKRun( GDALWarpKernel *poWK,
-                      const char* pszFuncName,
-                      void (*pfnFunc) (void *pUserData) )
-
+static void GWKThreadInitTransformer(void* pData)
 {
-    int nDstYSize = poWK->nDstYSize;
-
-    CPLDebug( "GDAL", "GDALWarpKernel()::%s()\n"
-              "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
-              pszFuncName,
-              poWK->nSrcXOff, poWK->nSrcYOff,
-              poWK->nSrcXSize, poWK->nSrcYSize,
-              poWK->nDstXOff, poWK->nDstYOff,
-              poWK->nDstXSize, poWK->nDstYSize );
-
-    if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
+    GWKJobStruct* psJob = (GWKJobStruct*)pData;
+    if( psJob->pTransformerArg == NULL )
+        psJob->pTransformerArg = GDALCloneTransformer(psJob->pTransformerArgInit);
+    if( psJob->pTransformerArg != NULL )
     {
-        CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
-        return CE_Failure;
+        // In case of lazy opening (for example RPCDEM), do a dummy transformation
+        // to be sure that the DEM is really opened with the context of this thread.
+        double dfX = 0.5, dfY = 0.5, dfZ = 0.0;
+        int bSuccess = FALSE;
+        CPLPushErrorHandler(CPLQuietErrorHandler);
+        psJob->pfnTransformerInit(psJob->pTransformerArg, TRUE, 1,
+                                  &dfX, &dfY, &dfZ, &bSuccess );
+        CPLPopErrorHandler();
     }
+}
+
+/************************************************************************/
+/*                          GWKThreadsCreate()                          */
+/************************************************************************/
 
-    const char* pszWarpThreads = CSLFetchNameValue(poWK->papszWarpOptions, "NUM_THREADS");
+typedef struct
+{
+    CPLWorkerThreadPool* poThreadPool;
+    GWKJobStruct* pasThreadJob;
+    CPLCond* hCond;
+    CPLMutex* hCondMutex;
+} GWKThreadData;
+
+void* GWKThreadsCreate(char** papszWarpOptions,
+                       GDALTransformerFunc pfnTransformer, void* pTransformerArg)
+{
     int nThreads;
+    const char* pszWarpThreads = CSLFetchNameValue(papszWarpOptions, "NUM_THREADS");
     if (pszWarpThreads == NULL)
         pszWarpThreads = CPLGetConfigOption("GDAL_NUM_THREADS", "1");
     if (EQUAL(pszWarpThreads, "ALL_CPUS"))
         nThreads = CPLGetNumCPUs();
     else
         nThreads = atoi(pszWarpThreads);
+    if( nThreads <= 1 )
+        nThreads = 0;
     if (nThreads > 128)
         nThreads = 128;
-    if (nThreads >= nDstYSize / 2)
-        nThreads = nDstYSize / 2;
 
-    if (nThreads <= 1)
-    {
-        return GWKGenericMonoThread(poWK, pfnFunc);
-    }
-    else
-    {
-        GWKJobStruct* pasThreadJob =
-            (GWKJobStruct*)CPLCalloc(sizeof(GWKJobStruct), nThreads);
+    GWKThreadData* psThreadData = (GWKThreadData*)VSI_CALLOC_VERBOSE(1,sizeof(GWKThreadData));
+    if( psThreadData == NULL )
+        return NULL;
 
+    CPLCond* hCond = NULL;
+    if( nThreads )
+        hCond = CPLCreateCond();
+    if( nThreads && hCond )
+    {
 /* -------------------------------------------------------------------- */
 /*      Duplicate pTransformerArg per thread.                           */
 /* -------------------------------------------------------------------- */
         int i;
         int bTransformerCloningSuccess = TRUE;
 
+        psThreadData->hCond = hCond;
+        psThreadData->pasThreadJob =
+                (GWKJobStruct*)VSI_CALLOC_VERBOSE(sizeof(GWKJobStruct), nThreads);
+        if( psThreadData->pasThreadJob == NULL )
+        {
+            GWKThreadsEnd(psThreadData);
+            return NULL;
+        }
+
+        psThreadData->hCondMutex = CPLCreateMutex();
+        if( psThreadData->hCondMutex == NULL )
+        {
+            GWKThreadsEnd(psThreadData);
+            return NULL;
+        }
+        CPLReleaseMutex(psThreadData->hCondMutex);
+
+        std::vector<void*> apInitData;
         for(i=0;i<nThreads;i++)
         {
-            pasThreadJob[i].pTransformerArg = GDALCloneTransformer(poWK->pTransformerArg);
-            if( pasThreadJob[i].pTransformerArg == NULL )
+            psThreadData->pasThreadJob[i].hCond = psThreadData->hCond;
+            psThreadData->pasThreadJob[i].hCondMutex = psThreadData->hCondMutex;
+            psThreadData->pasThreadJob[i].pfnTransformerInit = pfnTransformer;
+            psThreadData->pasThreadJob[i].pTransformerArgInit = pTransformerArg;
+            if( i == 0 )
+                psThreadData->pasThreadJob[i].pTransformerArg = pTransformerArg;
+            else
+                psThreadData->pasThreadJob[i].pTransformerArg = NULL;
+            apInitData.push_back(&(psThreadData->pasThreadJob[i]));
+        }
+
+        psThreadData->poThreadPool = new (std::nothrow) CPLWorkerThreadPool();
+        if( psThreadData->poThreadPool == NULL ||
+            !psThreadData->poThreadPool->Setup(nThreads,
+                                          GWKThreadInitTransformer,
+                                          &apInitData[0]) )
+        {
+            GWKThreadsEnd(psThreadData);
+            return NULL;
+        }
+
+        for(i=1;i<nThreads;i++)
+        {
+            if( psThreadData->pasThreadJob[i].pTransformerArg == NULL )
             {
                 CPLDebug("WARP", "Cannot deserialize transformer");
                 bTransformerCloningSuccess = FALSE;
@@ -301,99 +356,141 @@ static CPLErr GWKRun( GDALWarpKernel *poWK,
 
         if (!bTransformerCloningSuccess)
         {
-            for(i=0;i<nThreads;i++)
+            for(i=1;i<nThreads;i++)
             {
-                if( pasThreadJob[i].pTransformerArg )
-                    GDALDestroyTransformer(pasThreadJob[i].pTransformerArg);
+                if( psThreadData->pasThreadJob[i].pTransformerArg )
+                    GDALDestroyTransformer(psThreadData->pasThreadJob[i].pTransformerArg);
             }
-            CPLFree(pasThreadJob);
+            CPLFree(psThreadData->pasThreadJob);
+            psThreadData->pasThreadJob = NULL;
+            delete psThreadData->poThreadPool;
+            psThreadData->poThreadPool = NULL;
 
             CPLDebug("WARP", "Cannot duplicate transformer function. "
                      "Falling back to mono-thread computation");
-            return GWKGenericMonoThread(poWK, pfnFunc);
         }
+    }
 
-        CPLCond* hCond = CPLCreateCond();
-        if (hCond == NULL)
-        {
-            for(i=0;i<nThreads;i++)
-            {
-                if( pasThreadJob[i].pTransformerArg )
-                    GDALDestroyTransformer(pasThreadJob[i].pTransformerArg);
-            }
-            CPLFree(pasThreadJob);
+    return psThreadData;
+}
 
-            CPLDebug("WARP", "Multithreading disabled. "
-                     "Falling back to mono-thread computation");
-            return GWKGenericMonoThread(poWK, pfnFunc);
+/************************************************************************/
+/*                             GWKThreadsEnd()                          */
+/************************************************************************/
+
+void GWKThreadsEnd(void* psThreadDataIn)
+{
+    GWKThreadData* psThreadData = (GWKThreadData*)psThreadDataIn;
+    if( psThreadData == NULL )
+        return;
+    if( psThreadData->poThreadPool )
+    {
+        int nThreads = psThreadData->poThreadPool->GetThreadCount();
+        for(int i=1;i<nThreads;i++)
+        {
+            if( psThreadData->pasThreadJob[i].pTransformerArg )
+                GDALDestroyTransformer(psThreadData->pasThreadJob[i].pTransformerArg);
         }
+        delete psThreadData->poThreadPool;
+    }
+    CPLFree(psThreadData->pasThreadJob);
+    if( psThreadData->hCond )
+        CPLDestroyCond(psThreadData->hCond);
+    if( psThreadData->hCondMutex )
+        CPLDestroyMutex(psThreadData->hCondMutex);
+    CPLFree(psThreadData);
+}
 
-        CPLDebug("WARP", "Using %d threads", nThreads);
+/************************************************************************/
+/*                                GWKRun()                              */
+/************************************************************************/
 
-        CPLMutex* hCondMutex = CPLCreateMutex(); /* and take implicitely the mutex */
+static CPLErr GWKRun( GDALWarpKernel *poWK,
+                      const char* pszFuncName,
+                      void (*pfnFunc) (void *pUserData) )
 
-        volatile int bStop = FALSE;
-        volatile int nCounter = 0;
+{
+    int nDstYSize = poWK->nDstYSize;
+
+    CPLDebug( "GDAL", "GDALWarpKernel()::%s()\n"
+              "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
+              pszFuncName,
+              poWK->nSrcXOff, poWK->nSrcYOff,
+              poWK->nSrcXSize, poWK->nSrcYSize,
+              poWK->nDstXOff, poWK->nDstYOff,
+              poWK->nDstXSize, poWK->nDstYSize );
+
+    if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
+    {
+        CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
+        return CE_Failure;
+    }
+
+    GWKThreadData* psThreadData = (GWKThreadData*)poWK->psThreadData;
+    if( psThreadData == NULL || psThreadData->poThreadPool == NULL )
+    {
+        return GWKGenericMonoThread(poWK, pfnFunc);
+    }
+
+    int nThreads = psThreadData->poThreadPool->GetThreadCount();
+    if (nThreads >= nDstYSize / 2)
+        nThreads = nDstYSize / 2;
+
+    CPLDebug("WARP", "Using %d threads", nThreads);
+
+    volatile int bStop = FALSE;
+    volatile int nCounter = 0;
+
+    CPLAcquireMutex(psThreadData->hCondMutex, 1000);
 
 /* -------------------------------------------------------------------- */
-/*      Lannch worker threads                                           */
+/*      Submit jobs                                                     */
 /* -------------------------------------------------------------------- */
-        for(i=0;i<nThreads;i++)
-        {
-            pasThreadJob[i].poWK = poWK;
-            pasThreadJob[i].pnCounter = &nCounter;
-            pasThreadJob[i].iYMin = (int)(((GIntBig)i) * nDstYSize / nThreads);
-            pasThreadJob[i].iYMax = (int)(((GIntBig)(i + 1)) * nDstYSize / nThreads);
-            pasThreadJob[i].pbStop = &bStop;
-            pasThreadJob[i].hCond = hCond;
-            pasThreadJob[i].hCondMutex = hCondMutex;
-            if( poWK->pfnProgress != GDALDummyProgress )
-                pasThreadJob[i].pfnProgress = GWKProgressThread;
-            else
-                pasThreadJob[i].pfnProgress = NULL;
-            pasThreadJob[i].hThread = CPLCreateJoinableThread( pfnFunc,
-                                                  (void*) &pasThreadJob[i] );
-        }
+    for(int i=0;i<nThreads;i++)
+    {
+        psThreadData->pasThreadJob[i].poWK = poWK;
+        psThreadData->pasThreadJob[i].pnCounter = &nCounter;
+        psThreadData->pasThreadJob[i].iYMin = (int)(((GIntBig)i) * nDstYSize / nThreads);
+        psThreadData->pasThreadJob[i].iYMax = (int)(((GIntBig)(i + 1)) * nDstYSize / nThreads);
+        psThreadData->pasThreadJob[i].pbStop = &bStop;
+        if( poWK->pfnProgress != GDALDummyProgress )
+            psThreadData->pasThreadJob[i].pfnProgress = GWKProgressThread;
+        else
+            psThreadData->pasThreadJob[i].pfnProgress = NULL;
+        psThreadData->poThreadPool->SubmitJob( pfnFunc,
+                                   (void*) &psThreadData->pasThreadJob[i] );
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Report progress.                                                */
 /* -------------------------------------------------------------------- */
-        if( poWK->pfnProgress != GDALDummyProgress )
+    if( poWK->pfnProgress != GDALDummyProgress )
+    {
+        while(nCounter < nDstYSize)
         {
-            while(nCounter < nDstYSize)
-            {
-                CPLCondWait(hCond, hCondMutex);
+            CPLCondWait(psThreadData->hCond, psThreadData->hCondMutex);
 
-                if( !poWK->pfnProgress( poWK->dfProgressBase + poWK->dfProgressScale *
-                                        (nCounter / (double) nDstYSize),
-                                        "", poWK->pProgress ) )
-                {
-                    CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
-                    bStop = TRUE;
-                    break;
-                }
+            if( !poWK->pfnProgress( poWK->dfProgressBase + poWK->dfProgressScale *
+                                    (nCounter / (double) nDstYSize),
+                                    "", poWK->pProgress ) )
+            {
+                CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
+                bStop = TRUE;
+                break;
             }
         }
+    }
 
-        /* Release mutex before joining threads, otherwise they will dead-lock */
-        /* forever in GWKProgressThread() */
-        CPLReleaseMutex(hCondMutex);
+    /* Release mutex before joining threads, otherwise they will dead-lock */
+    /* forever in GWKProgressThread() */
+    CPLReleaseMutex(psThreadData->hCondMutex);
 
 /* -------------------------------------------------------------------- */
-/*      Wait for all threads to complete and finish.                    */
+/*      Wait for all jobs to complete.                                  */
 /* -------------------------------------------------------------------- */
-        for(i=0;i<nThreads;i++)
-        {
-            CPLJoinThread(pasThreadJob[i].hThread);
-            GDALDestroyTransformer(pasThreadJob[i].pTransformerArg);
-        }
+    psThreadData->poThreadPool->WaitCompletion();
 
-        CPLFree(pasThreadJob);
-        CPLDestroyCond(hCond);
-        CPLDestroyMutex(hCondMutex);
-
-        return !bStop ? CE_None : CE_Failure;
-    }
+    return !bStop ? CE_None : CE_Failure;
 }
 
 /************************************************************************/
@@ -409,37 +506,37 @@ static CPLErr GWKRun( GDALWarpKernel *poWK,
  *
  * This class is responsible for low level image warping for one
  * "chunk" of imagery.  The class is essentially a structure with all
- * data members public - primarily so that new special-case functions 
- * can be added without changing the class declaration.  
+ * data members public - primarily so that new special-case functions
+ * can be added without changing the class declaration.
  *
  * Applications are normally intended to interactive with warping facilities
  * through the GDALWarpOperation class, though the GDALWarpKernel can in
- * theory be used directly if great care is taken in setting up the 
- * control data. 
+ * theory be used directly if great care is taken in setting up the
+ * control data.
  *
  * <h3>Design Issues</h3>
  *
- * My intention is that PerformWarp() would analyse the setup in terms
+ * The intention is that PerformWarp() would analyze the setup in terms
  * of the datatype, resampling type, and validity/density mask usage and
  * pick one of many specific implementations of the warping algorithm over
- * a continuim of optimization vs. generality.  At one end there will be a
+ * a continuum of optimization vs. generality.  At one end there will be a
  * reference general purpose implementation of the algorithm that supports
  * any data type (working internally in double precision complex), all three
  * resampling types, and any or all of the validity/density masks.  At the
  * other end would be highly optimized algorithms for common cases like
- * nearest neighbour resampling on GDT_Byte data with no masks.  
+ * nearest neighbour resampling on GDT_Byte data with no masks.
  *
- * The full set of optimized versions have not been decided but we should 
+ * The full set of optimized versions have not been decided but we should
  * expect to have at least:
- *  - One for each resampling algorithm for 8bit data with no masks. 
+ *  - One for each resampling algorithm for 8bit data with no masks.
  *  - One for each resampling algorithm for float data with no masks.
  *  - One for each resampling algorithm for float data with any/all masks
- *    (essentially the generic case for just float data). 
+ *    (essentially the generic case for just float data).
  *  - One for each resampling algorithm for 8bit data with support for
- *    input validity masks (per band or per pixel).  This handles the common 
+ *    input validity masks (per band or per pixel).  This handles the common
  *    case of nodata masking.
  *  - One for each resampling algorithm for float data with support for
- *    input validity masks (per band or per pixel).  This handles the common 
+ *    input validity masks (per band or per pixel).  This handles the common
  *    case of nodata masking.
  *
  * Some of the specializations would operate on all bands in one pass
@@ -447,9 +544,9 @@ static CPLErr GWKRun( GDALWarpKernel *poWK,
  * process each band individually to reduce code complexity.
  *
  * <h3>Masking Semantics</h3>
- * 
+ *
  * A detailed explanation of the semantics of the validity and density masks,
- * and their effects on resampling kernels is needed here. 
+ * and their effects on resampling kernels is needed here.
  */
 
 /************************************************************************/
@@ -458,44 +555,44 @@ static CPLErr GWKRun( GDALWarpKernel *poWK,
 
 /**
  * \var GDALResampleAlg GDALWarpKernel::eResample;
- * 
+ *
  * Resampling algorithm.
  *
- * The resampling algorithm to use.  One of GRA_NearestNeighbour, GRA_Bilinear, 
+ * The resampling algorithm to use.  One of GRA_NearestNeighbour, GRA_Bilinear,
  * GRA_Cubic, GRA_CubicSpline, GRA_Lanczos, GRA_Average, or GRA_Mode.
  *
  * This field is required. GDT_NearestNeighbour may be used as a default
- * value. 
+ * value.
  */
-                                  
+
 /**
  * \var GDALDataType GDALWarpKernel::eWorkingDataType;
- * 
+ *
  * Working pixel data type.
  *
  * The datatype of pixels in the source image (papabySrcimage) and
- * destination image (papabyDstImage) buffers.  Note that operations on 
+ * destination image (papabyDstImage) buffers.  Note that operations on
  * some data types (such as GDT_Byte) may be much better optimized than other
- * less common cases. 
+ * less common cases.
  *
  * This field is required.  It may not be GDT_Unknown.
  */
-                                  
+
 /**
  * \var int GDALWarpKernel::nBands;
- * 
+ *
  * Number of bands.
  *
  * The number of bands (layers) of imagery being warped.  Determines the
- * number of entries in the papabySrcImage, papanBandSrcValid, 
- * and papabyDstImage arrays. 
+ * number of entries in the papabySrcImage, papanBandSrcValid,
+ * and papabyDstImage arrays.
  *
  * This field is required.
  */
 
 /**
  * \var int GDALWarpKernel::nSrcXSize;
- * 
+ *
  * Source image width in pixels.
  *
  * This field is required.
@@ -503,7 +600,7 @@ static CPLErr GWKRun( GDALWarpKernel *poWK,
 
 /**
  * \var int GDALWarpKernel::nSrcYSize;
- * 
+ *
  * Source image height in pixels.
  *
  * This field is required.
@@ -511,7 +608,7 @@ static CPLErr GWKRun( GDALWarpKernel *poWK,
 
 /**
  * \var int GDALWarpKernel::nSrcXExtraSize;
- * 
+ *
  * Number of pixels included in nSrcXSize that are present on the edges of
  * the area of interest to take into account the width of the kernel.
  *
@@ -520,7 +617,7 @@ static CPLErr GWKRun( GDALWarpKernel *poWK,
 
 /**
  * \var int GDALWarpKernel::nSrcYExtraSize;
- * 
+ *
  * Number of pixels included in nSrcYExtraSize that are present on the edges of
  * the area of interest to take into account the height of the kernel.
  *
@@ -529,19 +626,19 @@ static CPLErr GWKRun( GDALWarpKernel *poWK,
 
 /**
  * \var int GDALWarpKernel::papabySrcImage;
- * 
+ *
  * Array of source image band data.
  *
  * This is an array of pointers (of size GDALWarpKernel::nBands) pointers
- * to image data.  Each individual band of image data is organized as a single 
+ * to image data.  Each individual band of image data is organized as a single
  * block of image data in left to right, then bottom to top order.  The actual
  * type of the image data is determined by GDALWarpKernel::eWorkingDataType.
  *
- * To access the the pixel value for the (x=3,y=4) pixel (zero based) of
+ * To access the pixel value for the (x=3,y=4) pixel (zero based) of
  * the second band with eWorkingDataType set to GDT_Float32 use code like
  * this:
  *
- * \code 
+ * \code
  *   float dfPixelValue;
  *   int   nBand = 1;  // band indexes are zero based.
  *   int   nPixel = 3; // zero based
@@ -560,7 +657,7 @@ static CPLErr GWKRun( GDALWarpKernel *poWK,
 /**
  * \var GUInt32 **GDALWarpKernel::papanBandSrcValid;
  *
- * Per band validity mask for source pixels. 
+ * Per band validity mask for source pixels.
  *
  * Array of pixel validity mask layers for each source band.   Each of
  * the mask layers is the same size (in pixels) as the source image with
@@ -570,7 +667,7 @@ static CPLErr GWKRun( GDALWarpKernel *poWK,
  * valid.  The following code can be used to test the validity of a particular
  * pixel.
  *
- * \code 
+ * \code
  *   int   bIsValid = TRUE;
  *   int   nBand = 1;  // band indexes are zero based.
  *   int   nPixel = 3; // zero based
@@ -579,14 +676,14 @@ static CPLErr GWKRun( GDALWarpKernel *poWK,
  *   assert( nPixel >= 0 && nPixel < poKern->nSrcXSize );
  *   assert( nLine >= 0 && nLine < poKern->nSrcYSize );
  *   assert( nBand >= 0 && nBand < poKern->nBands );
- * 
+ *
  *   if( poKern->papanBandSrcValid != NULL
  *       && poKern->papanBandSrcValid[nBand] != NULL )
  *   {
  *       GUInt32 *panBandMask = poKern->papanBandSrcValid[nBand];
  *       int    iPixelOffset = nPixel + nLine * poKern->nSrcXSize;
- * 
- *       bIsValid = panBandMask[iPixelOffset>>5] 
+ *
+ *       bIsValid = panBandMask[iPixelOffset>>5]
  *                  & (0x01 << (iPixelOffset & 0x1f));
  *   }
  * \endcode
@@ -595,33 +692,33 @@ static CPLErr GWKRun( GDALWarpKernel *poWK,
 /**
  * \var GUInt32 *GDALWarpKernel::panUnifiedSrcValid;
  *
- * Per pixel validity mask for source pixels. 
+ * Per pixel validity mask for source pixels.
  *
  * A single validity mask layer that applies to the pixels of all source
  * bands.  It is accessed similarly to papanBandSrcValid, but without the
  * extra level of band indirection.
  *
- * This pointer may be NULL indicating that all pixels are valid. 
- * 
+ * This pointer may be NULL indicating that all pixels are valid.
+ *
  * Note that if both panUnifiedSrcValid, and papanBandSrcValid are available,
  * the pixel isn't considered to be valid unless both arrays indicate it is
- * valid.  
+ * valid.
  */
 
 /**
  * \var float *GDALWarpKernel::pafUnifiedSrcDensity;
  *
- * Per pixel density mask for source pixels. 
+ * Per pixel density mask for source pixels.
  *
  * A single density mask layer that applies to the pixels of all source
- * bands.  It contains values between 0.0 and 1.0 indicating the degree to 
- * which this pixel should be allowed to contribute to the output result. 
+ * bands.  It contains values between 0.0 and 1.0 indicating the degree to
+ * which this pixel should be allowed to contribute to the output result.
  *
  * This pointer may be NULL indicating that all pixels have a density of 1.0.
  *
  * The density for a pixel may be accessed like this:
  *
- * \code 
+ * \code
  *   float fDensity = 1.0;
  *   int   nPixel = 3; // zero based
  *   int   nLine = 4;  // zero based
@@ -652,19 +749,19 @@ static CPLErr GWKRun( GDALWarpKernel *poWK,
 
 /**
  * \var GByte **GDALWarpKernel::papabyDstImage;
- * 
+ *
  * Array of destination image band data.
  *
  * This is an array of pointers (of size GDALWarpKernel::nBands) pointers
- * to image data.  Each individual band of image data is organized as a single 
+ * to image data.  Each individual band of image data is organized as a single
  * block of image data in left to right, then bottom to top order.  The actual
  * type of the image data is determined by GDALWarpKernel::eWorkingDataType.
  *
- * To access the the pixel value for the (x=3,y=4) pixel (zero based) of
+ * To access the pixel value for the (x=3,y=4) pixel (zero based) of
  * the second band with eWorkingDataType set to GDT_Float32 use code like
  * this:
  *
- * \code 
+ * \code
  *   float dfPixelValue;
  *   int   nBand = 1;  // band indexes are zero based.
  *   int   nPixel = 3; // zero based
@@ -683,19 +780,19 @@ static CPLErr GWKRun( GDALWarpKernel *poWK,
 /**
  * \var GUInt32 *GDALWarpKernel::panDstValid;
  *
- * Per pixel validity mask for destination pixels. 
+ * Per pixel validity mask for destination pixels.
  *
  * A single validity mask layer that applies to the pixels of all destination
  * bands.  It is accessed similarly to papanUnitifiedSrcValid, but based
  * on the size of the destination image.
  *
- * This pointer may be NULL indicating that all pixels are valid. 
+ * This pointer may be NULL indicating that all pixels are valid.
  */
 
 /**
  * \var float *GDALWarpKernel::pafDstDensity;
  *
- * Per pixel density mask for destination pixels. 
+ * Per pixel density mask for destination pixels.
  *
  * A single density mask layer that applies to the pixels of all destination
  * bands.  It contains values between 0.0 and 1.0.
@@ -704,7 +801,7 @@ static CPLErr GWKRun( GDALWarpKernel *poWK,
  *
  * The density for a pixel may be accessed like this:
  *
- * \code 
+ * \code
  *   float fDensity = 1.0;
  *   int   nPixel = 3; // zero based
  *   int   nLine = 4;  // zero based
@@ -761,23 +858,23 @@ static CPLErr GWKRun( GDALWarpKernel *poWK,
  *
  * Source/destination location transformer.
  *
- * The function to call to transform coordinates between source image 
- * pixel/line coordinates and destination image pixel/line coordinates.  
- * See GDALTransformerFunc() for details of the semantics of this function. 
+ * The function to call to transform coordinates between source image
+ * pixel/line coordinates and destination image pixel/line coordinates.
+ * See GDALTransformerFunc() for details of the semantics of this function.
  *
- * The GDALWarpKern algorithm will only ever use this transformer in 
- * "destination to source" mode (bDstToSrc=TRUE), and will always pass 
+ * The GDALWarpKern algorithm will only ever use this transformer in
+ * "destination to source" mode (bDstToSrc=TRUE), and will always pass
  * partial or complete scanlines of points in the destination image as
- * input.  This means, amoung other things, that it is safe to the the
- * approximating transform GDALApproxTransform() as the transformation 
- * function. 
+ * input.  This means, among other things, that it is safe to the the
+ * approximating transform GDALApproxTransform() as the transformation
+ * function.
  *
  * Source and destination images may be subsets of a larger overall image.
  * The transformation algorithms will expect and return pixel/line coordinates
  * in terms of this larger image, so coordinates need to be offset by
  * the offsets specified in nSrcXOff, nSrcYOff, nDstXOff, and nDstYOff before
- * passing to pfnTransformer, and after return from it. 
- * 
+ * passing to pfnTransformer, and after return from it.
+ *
  * The GDALWarpKernel::pfnTransformerArg value will be passed as the callback
  * data to this function when it is called.
  *
@@ -797,12 +894,12 @@ static CPLErr GWKRun( GDALWarpKernel *poWK,
  *
  * The function to call to report progress of the algorithm, and to check
  * for a requested termination of the operation.  It operates according to
- * GDALProgressFunc() semantics. 
+ * GDALProgressFunc() semantics.
  *
- * Generally speaking the progress function will be invoked for each 
- * scanline of the destination buffer that has been processed. 
+ * Generally speaking the progress function will be invoked for each
+ * scanline of the destination buffer that has been processed.
  *
- * This field may be NULL (internally set to GDALDummyProgress()). 
+ * This field may be NULL (internally set to GDALDummyProgress()).
  */
 
 /**
@@ -856,6 +953,8 @@ GDALWarpKernel::GDALWarpKernel()
     pfnTransformer = NULL;
     pTransformerArg = NULL;
     papszWarpOptions = NULL;
+    padfDstNoDataReal = NULL;
+    psThreadData = NULL;
 }
 
 /************************************************************************/
@@ -873,7 +972,7 @@ GDALWarpKernel::~GDALWarpKernel()
 
 /**
  * \fn CPLErr GDALWarpKernel::PerformWarp();
- * 
+ *
  * This method performs the warp described in the GDALWarpKernel.
  *
  * @return CE_None on success or CE_Failure if an error occurs.
@@ -924,9 +1023,9 @@ CPLErr GDALWarpKernel::PerformWarp()
             dfYScale = 1.0 / nYReciprocalScale;
     }
     /*CPLDebug("WARP", "dfXScale = %f, dfYScale = %f", dfXScale, dfYScale);*/
-    
+
     int bUse4SamplesFormula = (dfXScale >= 0.95 && dfYScale >= 0.95);
-    
+
     // Safety check for callers that would use GDALWarpKernel without using
     // GDALWarpOperation.
     if( (eResample == GRA_CubicSpline || eResample == GRA_Lanczos ||
@@ -972,7 +1071,7 @@ CPLErr GDALWarpKernel::PerformWarp()
         CSLFetchBoolean( papszWarpOptions, "USE_OPENCL", TRUE ))
     {
         CPLErr eResult = GWKOpenCLCase( this );
-        
+
         // CE_Warning tells us a suitable OpenCL environment was not available
         // so we fall through to other CPU based methods.
         if( eResult != CE_Warning )
@@ -1067,7 +1166,7 @@ CPLErr GDALWarpKernel::PerformWarp()
         && bNoMasksOrDstDensityOnly )
         return GWKCubicNoMasksOrDstDensityOnlyFloat( this );
 
-#ifdef INSTANCIATE_FLOAT64_SSE2_IMPL
+#ifdef INSTANTIATE_FLOAT64_SSE2_IMPL
     if( eWorkingDataType == GDT_Float64
         && eResample == GRA_Bilinear
         && bNoMasksOrDstDensityOnly )
@@ -1102,20 +1201,20 @@ CPLErr GDALWarpKernel::PerformWarp()
 
     return GWKGeneralCase( this );
 }
-                                  
+
 /************************************************************************/
 /*                              Validate()                              */
 /************************************************************************/
 
 /**
  * \fn CPLErr GDALWarpKernel::Validate()
- * 
+ *
  * Check the settings in the GDALWarpKernel, and issue a CPLError()
  * (and return CE_Failure) if the configuration is considered to be
- * invalid for some reason.  
+ * invalid for some reason.
  *
  * This method will also do some standard defaulting such as setting
- * pfnProgress to GDALDummyProgress() if it is NULL. 
+ * pfnProgress to GDALDummyProgress() if it is NULL.
  *
  * @return CE_None on success or CE_Failure if an error is detected.
  */
@@ -1126,7 +1225,7 @@ CPLErr GDALWarpKernel::Validate()
     if ( (size_t)eResample >=
          (sizeof(anGWKFilterRadius) / sizeof(anGWKFilterRadius[0])) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unsupported resampling method %d.", (int) eResample );
         return CE_Failure;
     }
@@ -1142,7 +1241,7 @@ CPLErr GDALWarpKernel::Validate()
 /*      original density.                                               */
 /************************************************************************/
 
-static void GWKOverlayDensity( GDALWarpKernel *poWK, int iDstOffset, 
+static void GWKOverlayDensity( GDALWarpKernel *poWK, int iDstOffset,
                                double dfDensity )
 {
     if( dfDensity < 0.0001 || poWK->pafDstDensity == NULL )
@@ -1153,14 +1252,27 @@ static void GWKOverlayDensity( GDALWarpKernel *poWK, int iDstOffset,
 }
 
 /************************************************************************/
-/*                          GWKRoundValueT()                           */
+/*                          GWKRoundValueT()                            */
 /************************************************************************/
 
-template<class T>
-static CPL_INLINE T GWKRoundValueT(double dfValue)
+template<class T, EMULATED_BOOL is_signed> struct sGWKRoundValueT
+{
+    static T eval(double);
+};
+
+template<class T> struct sGWKRoundValueT<T, true> /* signed */
+{
+    static T eval(double dfValue) { return (T)floor(dfValue + 0.5); }
+};
+
+template<class T> struct sGWKRoundValueT<T, false> /* unsigned */
+{
+    static T eval(double dfValue) { return (T)(dfValue + 0.5); }
+};
+
+template<class T> static T GWKRoundValueT(double dfValue)
 {
-    return (std::numeric_limits<T>::min() < 0) ? (T)floor(dfValue + 0.5) :
-                                                 (T)(dfValue + 0.5);
+    return sGWKRoundValueT<T, std::numeric_limits<T>::is_signed>::eval(dfValue);
 }
 
 template<> float GWKRoundValueT<float>(double dfValue)
@@ -1207,7 +1319,7 @@ template<> double GWKClampValueT<double>(double dfValue)
 /************************************************************************/
 
 template<class T>
-static int GWKSetPixelValueRealT( GDALWarpKernel *poWK, int iBand, 
+static int GWKSetPixelValueRealT( GDALWarpKernel *poWK, int iBand,
                          int iDstOffset, double dfDensity,
                          T value)
 {
@@ -1231,7 +1343,7 @@ static int GWKSetPixelValueRealT( GDALWarpKernel *poWK, int iBand,
 
         if( poWK->pafDstDensity != NULL )
             dfDstDensity = poWK->pafDstDensity[iDstOffset];
-        else if( poWK->panDstValid != NULL 
+        else if( poWK->panDstValid != NULL
                  && !((poWK->panDstValid[iDstOffset>>5]
                        & (0x01 << (iDstOffset & 0x1f))) ) )
             dfDstDensity = 0.0;
@@ -1244,7 +1356,7 @@ static int GWKSetPixelValueRealT( GDALWarpKernel *poWK, int iBand,
         // not occluded by the overlay.
         double dfDstInfluence = (1.0 - dfDensity) * dfDstDensity;
 
-        double dfReal = (value * dfDensity + dfDstReal * dfDstInfluence) 
+        double dfReal = (value * dfDensity + dfDstReal * dfDstInfluence)
                             / (dfDensity + dfDstInfluence);
 
 /* -------------------------------------------------------------------- */
@@ -1274,8 +1386,8 @@ static int GWKSetPixelValueRealT( GDALWarpKernel *poWK, int iBand,
 /*                          GWKSetPixelValue()                          */
 /************************************************************************/
 
-static int GWKSetPixelValue( GDALWarpKernel *poWK, int iBand, 
-                             int iDstOffset, double dfDensity, 
+static int GWKSetPixelValue( GDALWarpKernel *poWK, int iBand,
+                             int iDstOffset, double dfDensity,
                              double dfReal, double dfImag )
 
 {
@@ -1299,7 +1411,7 @@ static int GWKSetPixelValue( GDALWarpKernel *poWK, int iBand,
 
         if( poWK->pafDstDensity != NULL )
             dfDstDensity = poWK->pafDstDensity[iDstOffset];
-        else if( poWK->panDstValid != NULL 
+        else if( poWK->panDstValid != NULL
                  && !((poWK->panDstValid[iDstOffset>>5]
                        & (0x01 << (iDstOffset & 0x1f))) ) )
             dfDstDensity = 0.0;
@@ -1322,42 +1434,42 @@ static int GWKSetPixelValue( GDALWarpKernel *poWK, int iBand,
             dfDstReal = ((GUInt16 *) pabyDst)[iDstOffset];
             dfDstImag = 0.0;
             break;
- 
+
           case GDT_Int32:
             dfDstReal = ((GInt32 *) pabyDst)[iDstOffset];
             dfDstImag = 0.0;
             break;
- 
+
           case GDT_UInt32:
             dfDstReal = ((GUInt32 *) pabyDst)[iDstOffset];
             dfDstImag = 0.0;
             break;
- 
+
           case GDT_Float32:
             dfDstReal = ((float *) pabyDst)[iDstOffset];
             dfDstImag = 0.0;
             break;
- 
+
           case GDT_Float64:
             dfDstReal = ((double *) pabyDst)[iDstOffset];
             dfDstImag = 0.0;
             break;
- 
+
           case GDT_CInt16:
             dfDstReal = ((GInt16 *) pabyDst)[iDstOffset*2];
             dfDstImag = ((GInt16 *) pabyDst)[iDstOffset*2+1];
             break;
- 
+
           case GDT_CInt32:
             dfDstReal = ((GInt32 *) pabyDst)[iDstOffset*2];
             dfDstImag = ((GInt32 *) pabyDst)[iDstOffset*2+1];
             break;
- 
+
           case GDT_CFloat32:
             dfDstReal = ((float *) pabyDst)[iDstOffset*2];
             dfDstImag = ((float *) pabyDst)[iDstOffset*2+1];
             break;
- 
+
           case GDT_CFloat64:
             dfDstReal = ((double *) pabyDst)[iDstOffset*2];
             dfDstImag = ((double *) pabyDst)[iDstOffset*2+1];
@@ -1373,10 +1485,10 @@ static int GWKSetPixelValue( GDALWarpKernel *poWK, int iBand,
         // not occluded by the overlay.
         double dfDstInfluence = (1.0 - dfDensity) * dfDstDensity;
 
-        dfReal = (dfReal * dfDensity + dfDstReal * dfDstInfluence) 
+        dfReal = (dfReal * dfDensity + dfDstReal * dfDstInfluence)
             / (dfDensity + dfDstInfluence);
 
-        dfImag = (dfImag * dfDensity + dfDstImag * dfDstInfluence) 
+        dfImag = (dfImag * dfDensity + dfDstImag * dfDstInfluence)
             / (dfDensity + dfDstInfluence);
     }
 
@@ -1484,8 +1596,8 @@ static int GWKSetPixelValue( GDALWarpKernel *poWK, int iBand,
 
 /* It is assumed that panUnifiedSrcValid has been checked before */
 
-static int GWKGetPixelValue( GDALWarpKernel *poWK, int iBand, 
-                             int iSrcOffset, double *pdfDensity, 
+static int GWKGetPixelValue( GDALWarpKernel *poWK, int iBand,
+                             int iSrcOffset, double *pdfDensity,
                              double *pdfReal, double *pdfImag )
 
 {
@@ -1516,42 +1628,42 @@ static int GWKGetPixelValue( GDALWarpKernel *poWK, int iBand,
         *pdfReal = ((GUInt16 *) pabySrc)[iSrcOffset];
         *pdfImag = 0.0;
         break;
- 
+
       case GDT_Int32:
         *pdfReal = ((GInt32 *) pabySrc)[iSrcOffset];
         *pdfImag = 0.0;
         break;
- 
+
       case GDT_UInt32:
         *pdfReal = ((GUInt32 *) pabySrc)[iSrcOffset];
         *pdfImag = 0.0;
         break;
- 
+
       case GDT_Float32:
         *pdfReal = ((float *) pabySrc)[iSrcOffset];
         *pdfImag = 0.0;
         break;
- 
+
       case GDT_Float64:
         *pdfReal = ((double *) pabySrc)[iSrcOffset];
         *pdfImag = 0.0;
         break;
- 
+
       case GDT_CInt16:
         *pdfReal = ((GInt16 *) pabySrc)[iSrcOffset*2];
         *pdfImag = ((GInt16 *) pabySrc)[iSrcOffset*2+1];
         break;
- 
+
       case GDT_CInt32:
         *pdfReal = ((GInt32 *) pabySrc)[iSrcOffset*2];
         *pdfImag = ((GInt32 *) pabySrc)[iSrcOffset*2+1];
         break;
- 
+
       case GDT_CFloat32:
         *pdfReal = ((float *) pabySrc)[iSrcOffset*2];
         *pdfImag = ((float *) pabySrc)[iSrcOffset*2+1];
         break;
- 
+
       case GDT_CFloat64:
         *pdfReal = ((double *) pabySrc)[iSrcOffset*2];
         *pdfImag = ((double *) pabySrc)[iSrcOffset*2+1];
@@ -1577,7 +1689,7 @@ static int GWKGetPixelValue( GDALWarpKernel *poWK, int iBand,
 /* It is assumed that adfImag[] is set to 0 by caller code for non-complex */
 /* data-types. */
 
-static int GWKGetPixelRow( GDALWarpKernel *poWK, int iBand, 
+static int GWKGetPixelRow( GDALWarpKernel *poWK, int iBand,
                            int iSrcOffset, int nHalfSrcLen,
                            double* padfDensity,
                            double adfReal[],
@@ -1587,7 +1699,7 @@ static int GWKGetPixelRow( GDALWarpKernel *poWK, int iBand,
     int     nSrcLen = nHalfSrcLen * 2;
     int     bHasValid = FALSE;
     int     i;
-    
+
     if( padfDensity != NULL )
     {
         // Init the density
@@ -1596,7 +1708,7 @@ static int GWKGetPixelRow( GDALWarpKernel *poWK, int iBand,
             padfDensity[i] = 1.0;
             padfDensity[i+1] = 1.0;
         }
-        
+
         if ( poWK->panUnifiedSrcValid != NULL )
         {
             for ( i = 0; i < nSrcLen; i += 2 )
@@ -1606,7 +1718,7 @@ static int GWKGetPixelRow( GDALWarpKernel *poWK, int iBand,
                     bHasValid = TRUE;
                 else
                     padfDensity[i] = 0.0;
-                
+
                 if(poWK->panUnifiedSrcValid[(iSrcOffset+i+1)>>5]
                 & (0x01 << ((iSrcOffset+i+1) & 0x1f)))
                     bHasValid = TRUE;
@@ -1620,7 +1732,7 @@ static int GWKGetPixelRow( GDALWarpKernel *poWK, int iBand,
             else
                 return FALSE;
         }
-        
+
         if ( poWK->papanBandSrcValid != NULL
             && poWK->papanBandSrcValid[iBand] != NULL)
         {
@@ -1631,14 +1743,14 @@ static int GWKGetPixelRow( GDALWarpKernel *poWK, int iBand,
                     bHasValid = TRUE;
                 else
                     padfDensity[i] = 0.0;
-                
+
                 if(poWK->papanBandSrcValid[iBand][(iSrcOffset+i+1)>>5]
                 & (0x01 << ((iSrcOffset+i+1) & 0x1f)))
                     bHasValid = TRUE;
                 else
                     padfDensity[i+1] = 0.0;
             }
-            
+
             // Reset or fail as needed
             if ( bHasValid )
                 bHasValid = FALSE;
@@ -1646,7 +1758,7 @@ static int GWKGetPixelRow( GDALWarpKernel *poWK, int iBand,
                 return FALSE;
         }
     }
-    
+
     // Fetch data
     switch( poWK->eWorkingDataType )
     {
@@ -1815,7 +1927,7 @@ static int GWKGetPixelRow( GDALWarpKernel *poWK, int iBand,
                 padfDensity[i] = 1.0;
                 bHasValid = TRUE;
             }
-            
+
             if(padfDensity[i+1] > 0.000000001)
             {
                 padfDensity[i+1] = 1.0;
@@ -1831,14 +1943,14 @@ static int GWKGetPixelRow( GDALWarpKernel *poWK, int iBand,
                 padfDensity[i] = poWK->pafUnifiedSrcDensity[iSrcOffset+i];
             if(padfDensity[i] > 0.000000001)
                 bHasValid = TRUE;
-            
+
             if(padfDensity[i+1] > 0.000000001)
                 padfDensity[i+1] = poWK->pafUnifiedSrcDensity[iSrcOffset+i+1];
             if(padfDensity[i+1] > 0.000000001)
                 bHasValid = TRUE;
         }
     }
-    
+
     return bHasValid;
 }
 
@@ -1847,8 +1959,8 @@ static int GWKGetPixelRow( GDALWarpKernel *poWK, int iBand,
 /************************************************************************/
 
 template<class T>
-static int GWKGetPixelT( GDALWarpKernel *poWK, int iBand, 
-                         int iSrcOffset, double *pdfDensity, 
+static int GWKGetPixelT( GDALWarpKernel *poWK, int iBand,
+                         int iSrcOffset, double *pdfDensity,
                          T *pValue )
 
 {
@@ -1881,16 +1993,16 @@ static int GWKGetPixelT( GDALWarpKernel *poWK, int iBand,
 /*     Set of bilinear interpolators                                    */
 /************************************************************************/
 
-static int GWKBilinearResample4Sample( GDALWarpKernel *poWK, int iBand, 
+static int GWKBilinearResample4Sample( GDALWarpKernel *poWK, int iBand,
                                 double dfSrcX, double dfSrcY,
-                                double *pdfDensity, 
+                                double *pdfDensity,
                                 double *pdfReal, double *pdfImag )
 
 {
     // Save as local variables to avoid following pointers
     int     nSrcXSize = poWK->nSrcXSize;
     int     nSrcYSize = poWK->nSrcYSize;
-    
+
     int     iSrcX = (int) floor(dfSrcX - 0.5);
     int     iSrcY = (int) floor(dfSrcY - 0.5);
     int     iSrcOffset;
@@ -1921,7 +2033,7 @@ static int GWKBilinearResample4Sample( GDALWarpKernel *poWK, int iBand,
         bShifted = TRUE;
         --iSrcOffset;
     }
-    
+
     // Get pixel row
     if ( iSrcY >= 0 && iSrcY < nSrcYSize
          && iSrcOffset >= 0 && iSrcOffset < nSrcXSize * nSrcYSize
@@ -1938,7 +2050,7 @@ static int GWKBilinearResample4Sample( GDALWarpKernel *poWK, int iBand,
             adfImag[0] = adfImag[1];
             adfDensity[0] = adfDensity[1];
         }
-        
+
         // Upper Left Pixel
         if ( iSrcX >= 0 && iSrcX < nSrcXSize
              && adfDensity[0] > 0.000000001 )
@@ -1949,7 +2061,7 @@ static int GWKBilinearResample4Sample( GDALWarpKernel *poWK, int iBand,
             dfAccumulatorImag += adfImag[0] * dfMult1;
             dfAccumulatorDensity += adfDensity[0] * dfMult1;
         }
-            
+
         // Upper Right Pixel
         if ( iSrcX+1 >= 0 && iSrcX+1 < nSrcXSize
              && adfDensity[1] > 0.000000001 )
@@ -1961,7 +2073,7 @@ static int GWKBilinearResample4Sample( GDALWarpKernel *poWK, int iBand,
             dfAccumulatorDensity += adfDensity[1] * dfMult2;
         }
     }
-        
+
     // Get pixel row
     if ( iSrcY+1 >= 0 && iSrcY+1 < nSrcYSize
          && iSrcOffset+nSrcXSize >= 0
@@ -1971,7 +2083,7 @@ static int GWKBilinearResample4Sample( GDALWarpKernel *poWK, int iBand,
     {
         double dfMult1 = dfRatioX * (1.0-dfRatioY);
         double dfMult2 = (1.0-dfRatioX) * (1.0-dfRatioY);
-        
+
         // Shifting corrected
         if ( bShifted )
         {
@@ -1979,7 +2091,7 @@ static int GWKBilinearResample4Sample( GDALWarpKernel *poWK, int iBand,
             adfImag[0] = adfImag[1];
             adfDensity[0] = adfDensity[1];
         }
-        
+
         // Lower Left Pixel
         if ( iSrcX >= 0 && iSrcX < nSrcXSize
              && adfDensity[0] > 0.000000001 )
@@ -2030,7 +2142,7 @@ static int GWKBilinearResample4Sample( GDALWarpKernel *poWK, int iBand,
 }
 
 template<class T>
-static int GWKBilinearResampleNoMasks4SampleT( GDALWarpKernel *poWK, int iBand, 
+static int GWKBilinearResampleNoMasks4SampleT( GDALWarpKernel *poWK, int iBand,
                                         double dfSrcX, double dfSrcY,
                                         T *pValue )
 
@@ -2044,9 +2156,9 @@ static int GWKBilinearResampleNoMasks4SampleT( GDALWarpKernel *poWK, int iBand,
     int     iSrcOffset = iSrcX + iSrcY * poWK->nSrcXSize;
     double  dfRatioX = 1.5 - (dfSrcX - iSrcX);
     double  dfRatioY = 1.5 - (dfSrcY - iSrcY);
-    
+
     T* pSrc = (T *)poWK->papabySrcImage[iBand];
-    
+
     if( iSrcX >= 0 && iSrcX+1 < poWK->nSrcXSize
         && iSrcY >= 0 && iSrcY+1 < poWK->nSrcYSize )
     {
@@ -2070,7 +2182,7 @@ static int GWKBilinearResampleNoMasks4SampleT( GDALWarpKernel *poWK, int iBand,
 
         dfAccumulator += (double)pSrc[iSrcOffset] * dfMult;
     }
-        
+
     // Upper Right Pixel
     if( iSrcX+1 >= 0 && iSrcX+1 < poWK->nSrcXSize
         && iSrcY >= 0 && iSrcY < poWK->nSrcYSize )
@@ -2081,7 +2193,7 @@ static int GWKBilinearResampleNoMasks4SampleT( GDALWarpKernel *poWK, int iBand,
 
         dfAccumulator += (double)pSrc[iSrcOffset+1] * dfMult;
     }
-        
+
     // Lower Right Pixel
     if( iSrcX+1 >= 0 && iSrcX+1 < poWK->nSrcXSize
         && iSrcY+1 >= 0 && iSrcY+1 < poWK->nSrcYSize )
@@ -2092,7 +2204,7 @@ static int GWKBilinearResampleNoMasks4SampleT( GDALWarpKernel *poWK, int iBand,
 
         dfAccumulator += (double)pSrc[iSrcOffset+1+poWK->nSrcXSize] * dfMult;
     }
-        
+
     // Lower Left Pixel
     if( iSrcX >= 0 && iSrcX < poWK->nSrcXSize
         && iSrcY+1 >= 0 && iSrcY+1 < poWK->nSrcYSize )
@@ -2189,7 +2301,6 @@ static int GWKCubicResample4Sample( GDALWarpKernel *poWK, int iBand,
             adfImag[0], adfImag[1], adfImag[2], adfImag[3]);
     }
 
-    
 /* -------------------------------------------------------------------- */
 /*      For now, if we have any pixels missing in the kernel area,      */
 /*      we fallback on using bilinear interpolation.  Ideally we        */
@@ -2205,7 +2316,7 @@ static int GWKCubicResample4Sample( GDALWarpKernel *poWK, int iBand,
     *pdfImag = CubicConvolution(dfDeltaY, dfDeltaY2, dfDeltaY3,
                                    adfValueImag[0], adfValueImag[1],
                                    adfValueImag[2], adfValueImag[3]);
-    
+
     return TRUE;
 }
 
@@ -2269,8 +2380,6 @@ static int GWKCubicResampleNoMasks4SampleT( GDALWarpKernel *poWK, int iBand,
  * where sinc(x) = sin(PI * x) / (PI * x).
  */
 
-#define GWK_PI 3.14159265358979323846
-
 static double GWKLanczosSinc( double dfX )
 {
     /*if( fabs(dfX) > 3.0 )
@@ -2281,7 +2390,7 @@ static double GWKLanczosSinc( double dfX )
     if ( dfX == 0.0 )
         return 1.0;
 
-    const double dfPIX = GWK_PI * dfX;
+    const double dfPIX = M_PI * dfX;
     const double dfPIXoverR = dfPIX / 3;
     const double dfPIX2overR = dfPIX * dfPIXoverR;
     return sin(dfPIX) * sin(dfPIXoverR) / dfPIX2overR;
@@ -2295,7 +2404,7 @@ static double GWKLanczosSinc4Values( double* padfValues )
             padfValues[i] = 1.0;
         else
         {
-            const double dfPIX = GWK_PI * padfValues[i];
+            const double dfPIX = M_PI * padfValues[i];
             const double dfPIXoverR = dfPIX / 3;
             const double dfPIX2overR = dfPIX * dfPIXoverR;
             padfValues[i] = sin(dfPIX) * sin(dfPIXoverR) / dfPIX2overR;
@@ -2304,8 +2413,6 @@ static double GWKLanczosSinc4Values( double* padfValues )
     return padfValues[0] + padfValues[1] + padfValues[2] + padfValues[3];
 }
 
-//#undef GWK_PI
-
 /************************************************************************/
 /*                           GWKBilinear()                              */
 /************************************************************************/
@@ -2425,11 +2532,11 @@ static double GWKBSpline( double x )
     double xp2 = x + 2.0;
     double xp1 = x + 1.0;
     double xm1 = x - 1.0;
-    
+
     // This will most likely be used, so we'll compute it ahead of time to
     // avoid stalling the processor
     double xp2c = xp2 * xp2 * xp2;
-    
+
     // Note that the test is computed only if it is needed
     return (((xp2 > 0.0)?((xp1 > 0.0)?((x > 0.0)?((xm1 > 0.0)?
                                                   -4.0 * xm1*xm1*xm1:0.0) +
@@ -2446,11 +2553,11 @@ static double GWKBSpline4Values( double* padfValues )
         double xp2 = x + 2.0;
         double xp1 = x + 1.0;
         double xm1 = x - 1.0;
-        
+
         // This will most likely be used, so we'll compute it ahead of time to
         // avoid stalling the processor
         double xp2c = xp2 * xp2 * xp2;
-        
+
         // Note that the test is computed only if it is needed
         padfValues[i] = (((xp2 > 0.0)?((xp1 > 0.0)?((x > 0.0)?((xm1 > 0.0)?
                                                     -4.0 * xm1*xm1*xm1:0.0) +
@@ -2466,9 +2573,9 @@ static double GWKBSpline4Values( double* padfValues )
 
 typedef struct _GWKResampleWrkStruct GWKResampleWrkStruct;
 
-typedef int (*pfnGWKResampleType) ( GDALWarpKernel *poWK, int iBand, 
+typedef int (*pfnGWKResampleType) ( GDALWarpKernel *poWK, int iBand,
                                     double dfSrcX, double dfSrcY,
-                                    double *pdfDensity, 
+                                    double *pdfDensity,
                                     double *pdfReal, double *pdfImag,
                                     GWKResampleWrkStruct* psWrkStruct );
 
@@ -2497,15 +2604,15 @@ struct _GWKResampleWrkStruct
 /*                    GWKResampleCreateWrkStruct()                      */
 /************************************************************************/
 
-static int GWKResample( GDALWarpKernel *poWK, int iBand, 
+static int GWKResample( GDALWarpKernel *poWK, int iBand,
                         double dfSrcX, double dfSrcY,
-                        double *pdfDensity, 
+                        double *pdfDensity,
                         double *pdfReal, double *pdfImag,
                         GWKResampleWrkStruct* psWrkStruct );
 
-static int GWKResampleOptimizedLanczos( GDALWarpKernel *poWK, int iBand, 
+static int GWKResampleOptimizedLanczos( GDALWarpKernel *poWK, int iBand,
                                         double dfSrcX, double dfSrcY,
-                                        double *pdfDensity, 
+                                        double *pdfDensity,
                                         double *pdfReal, double *pdfImag,
                                         GWKResampleWrkStruct* psWrkStruct );
 
@@ -2520,7 +2627,7 @@ static GWKResampleWrkStruct* GWKResampleCreateWrkStruct(GDALWarpKernel *poWK)
     // Alloc space for saved X weights
     psWrkStruct->padfWeightsX = (double *)CPLCalloc( nXDist, sizeof(double) );
     psWrkStruct->panCalcX = (char *)CPLMalloc( nXDist * sizeof(char) );
-    
+
     psWrkStruct->padfWeightsY = (double *)CPLCalloc( nYDist, sizeof(double) );
     psWrkStruct->iLastSrcX = -10;
     psWrkStruct->iLastSrcY = -10;
@@ -2602,9 +2709,9 @@ static void GWKResampleDeleteWrkStruct(GWKResampleWrkStruct* psWrkStruct)
 /*                           GWKResample()                              */
 /************************************************************************/
 
-static int GWKResample( GDALWarpKernel *poWK, int iBand, 
+static int GWKResample( GDALWarpKernel *poWK, int iBand,
                         double dfSrcX, double dfSrcY,
-                        double *pdfDensity, 
+                        double *pdfDensity,
                         double *pdfReal, double *pdfImag,
                         GWKResampleWrkStruct* psWrkStruct )
 
@@ -2639,7 +2746,7 @@ static int GWKResample( GDALWarpKernel *poWK, int iBand,
     // Mark as needing calculation (don't calculate the weights yet,
     // because a mask may render it unnecessary)
     memset( panCalcX, FALSE, nXDist * sizeof(char) );
-    
+
     FilterFuncType pfnGetWeight = apfGWKFilter[poWK->eResample];
     CPLAssert(pfnGetWeight);
 
@@ -2650,7 +2757,7 @@ static int GWKResample( GDALWarpKernel *poWK, int iBand,
         j = -iSrcY;
     if( iSrcY + jMax >= nSrcYSize )
         jMax = nSrcYSize - iSrcY - 1;
-        
+
     int iMin = poWK->nFiltInitX, iMax = poWK->nXRadius;
     if( iSrcX + iMin < 0 )
         iMin = -iSrcX;
@@ -2722,7 +2829,7 @@ static int GWKResample( GDALWarpKernel *poWK, int iBand,
                 dfAccumulatorDensityLocal += padfRowDensity[i-iMin] * dfWeight2;
             dfAccumulatorWeightLocal += dfWeight2;
         }
-        
+
         dfAccumulatorReal += dfAccumulatorRealLocal * dfWeight1;
         dfAccumulatorImag += dfAccumulatorImagLocal * dfWeight1;
         dfAccumulatorDensity += dfAccumulatorDensityLocal * dfWeight1;
@@ -2755,7 +2862,7 @@ static int GWKResample( GDALWarpKernel *poWK, int iBand,
         else
             *pdfDensity = 1.0;
     }
-    
+
     return TRUE;
 }
 
@@ -2763,9 +2870,9 @@ static int GWKResample( GDALWarpKernel *poWK, int iBand,
 /*                      GWKResampleOptimizedLanczos()                   */
 /************************************************************************/
 
-static int GWKResampleOptimizedLanczos( GDALWarpKernel *poWK, int iBand, 
+static int GWKResampleOptimizedLanczos( GDALWarpKernel *poWK, int iBand,
                         double dfSrcX, double dfSrcY,
-                        double *pdfDensity, 
+                        double *pdfDensity,
                         double *pdfReal, double *pdfImag,
                         GWKResampleWrkStruct* psWrkStruct )
 
@@ -2828,20 +2935,20 @@ static int GWKResampleOptimizedLanczos( GDALWarpKernel *poWK, int iBand,
             // Optimisation of GWKLanczosSinc(i - dfDeltaX) based on the following
             // trigonometric formulas.
 
-    //sin(GWK_PI * (dfBase + k)) = sin(GWK_PI * dfBase) * cos(GWK_PI * k) + cos(GWK_PI * dfBase) * sin(GWK_PI * k)
-    //sin(GWK_PI * (dfBase + k)) = dfSinPIBase * cos(GWK_PI * k) + dfCosPIBase * sin(GWK_PI * k)
-    //sin(GWK_PI * (dfBase + k)) = dfSinPIBase * cos(GWK_PI * k)
-    //sin(GWK_PI * (dfBase + k)) = dfSinPIBase * (((k % 2) == 0) ? 1 : -1)
+    //sin(M_PI * (dfBase + k)) = sin(M_PI * dfBase) * cos(M_PI * k) + cos(M_PI * dfBase) * sin(M_PI * k)
+    //sin(M_PI * (dfBase + k)) = dfSinPIBase * cos(M_PI * k) + dfCosPIBase * sin(M_PI * k)
+    //sin(M_PI * (dfBase + k)) = dfSinPIBase * cos(M_PI * k)
+    //sin(M_PI * (dfBase + k)) = dfSinPIBase * (((k % 2) == 0) ? 1 : -1)
 
-    //sin(GWK_PI / dfR * (dfBase + k)) = sin(GWK_PI / dfR * dfBase) * cos(GWK_PI / dfR * k) + cos(GWK_PI / dfR * dfBase) * sin(GWK_PI / dfR * k)
-    //sin(GWK_PI / dfR * (dfBase + k)) = dfSinPIBaseOverR * cos(GWK_PI / dfR * k) + dfCosPIBaseOverR * sin(GWK_PI / dfR * k)
+    //sin(M_PI / dfR * (dfBase + k)) = sin(M_PI / dfR * dfBase) * cos(M_PI / dfR * k) + cos(M_PI / dfR * dfBase) * sin(M_PI / dfR * k)
+    //sin(M_PI / dfR * (dfBase + k)) = dfSinPIBaseOverR * cos(M_PI / dfR * k) + dfCosPIBaseOverR * sin(M_PI / dfR * k)
 
-            double dfSinPIDeltaXOver3 = sin((-GWK_PI / 3) * dfDeltaX);
+            double dfSinPIDeltaXOver3 = sin((-M_PI / 3) * dfDeltaX);
             double dfSin2PIDeltaXOver3 = dfSinPIDeltaXOver3 * dfSinPIDeltaXOver3;
-            /* ok to use sqrt(1-sin^2) since GWK_PI / 3 * dfDeltaX < PI/2 */
+            /* ok to use sqrt(1-sin^2) since M_PI / 3 * dfDeltaX < PI/2 */
             double dfCosPIDeltaXOver3 = sqrt(1 - dfSin2PIDeltaXOver3);
             double dfSinPIDeltaX = (3-4*dfSin2PIDeltaXOver3)*dfSinPIDeltaXOver3;
-            const double dfInvPI2Over3 = 3.0 / (GWK_PI * GWK_PI);
+            const double dfInvPI2Over3 = 3.0 / (M_PI * M_PI);
             double dfInvPI2Over3xSinPIDeltaX = dfInvPI2Over3 * dfSinPIDeltaX;
             double dfInvPI2Over3xSinPIDeltaXxm0d5SinPIDeltaXOver3 =
                 -0.5 * dfInvPI2Over3xSinPIDeltaX * dfSinPIDeltaXOver3;
@@ -2889,12 +2996,12 @@ static int GWKResampleOptimizedLanczos( GDALWarpKernel *poWK, int iBand,
         if( iSrcY != psWrkStruct->iLastSrcY ||
             dfDeltaY != psWrkStruct->dfLastDeltaY )
         {
-            double dfSinPIDeltaYOver3 = sin((-GWK_PI / 3) * dfDeltaY);
+            double dfSinPIDeltaYOver3 = sin((-M_PI / 3) * dfDeltaY);
             double dfSin2PIDeltaYOver3 = dfSinPIDeltaYOver3 * dfSinPIDeltaYOver3;
-            /* ok to use sqrt(1-sin^2) since GWK_PI / 3 * dfDeltaY < PI/2 */
+            /* ok to use sqrt(1-sin^2) since M_PI / 3 * dfDeltaY < PI/2 */
             double dfCosPIDeltaYOver3 = sqrt(1 - dfSin2PIDeltaYOver3);
             double dfSinPIDeltaY = (3-4*dfSin2PIDeltaYOver3)*dfSinPIDeltaYOver3;
-            const double dfInvPI2Over3 = 3.0 / (GWK_PI * GWK_PI);
+            const double dfInvPI2Over3 = 3.0 / (M_PI * M_PI);
             double dfInvPI2Over3xSinPIDeltaY = dfInvPI2Over3 * dfSinPIDeltaY;
             double dfInvPI2Over3xSinPIDeltaYxm0d5SinPIDeltaYOver3 =
                 -0.5 * dfInvPI2Over3xSinPIDeltaY * dfSinPIDeltaYOver3;
@@ -2941,11 +3048,10 @@ static int GWKResampleOptimizedLanczos( GDALWarpKernel *poWK, int iBand,
             dfColAccWeight += padfWeightsY[j-poWK->nFiltInitY];
         }
         dfAccumulatorWeight = dfRowAccWeight * dfColAccWeight;
-
-        if( !GDALDataTypeIsComplex(poWK->eWorkingDataType) )
-            padfRowImag = NULL;
     }
 
+    const bool bIsNonComplex = !GDALDataTypeIsComplex(poWK->eWorkingDataType);
+
     // Loop over pixel rows in the kernel
     for ( int j = jMin; j <= jMax; ++j )
     {
@@ -2985,7 +3091,7 @@ static int GWKResampleOptimizedLanczos( GDALWarpKernel *poWK, int iBand,
                 dfAccumulatorWeight += dfWeight2;
             }
         }
-        else if( padfRowImag == NULL )
+        else if( bIsNonComplex )
         {
             double dfRowAccReal = 0.0;
             for (int i = iMin; i <= iMax; ++i )
@@ -3043,7 +3149,7 @@ static int GWKResampleOptimizedLanczos( GDALWarpKernel *poWK, int iBand,
         else
             *pdfDensity = 1.0;
     }
-    
+
     return TRUE;
 }
 
@@ -3060,7 +3166,7 @@ static int GWKResampleNoMasksT( GDALWarpKernel *poWK, int iBand,
     // Commonly used; save locally
     int     nSrcXSize = poWK->nSrcXSize;
     int     nSrcYSize = poWK->nSrcYSize;
-    
+
     double  dfAccumulator = 0.0;
     int     iSrcX = (int) floor( dfSrcX - 0.5 );
     int     iSrcY = (int) floor( dfSrcY - 0.5 );
@@ -3074,7 +3180,7 @@ static int GWKResampleNoMasksT( GDALWarpKernel *poWK, int iBand,
     int     nYRadius = poWK->nYRadius;
 
     T*  pSrcBand = (T*) poWK->papabySrcImage[iBand];
-    
+
     // Politely refusing to process invalid coordinates or obscenely small image
     if ( iSrcX >= nSrcXSize || iSrcY >= nSrcYSize
          || nXRadius > nSrcXSize || nYRadius > nSrcYSize )
@@ -3091,7 +3197,7 @@ static int GWKResampleNoMasksT( GDALWarpKernel *poWK, int iBand,
     // Loop over all rows in the kernel
     double dfAccumulatorWeightHorizontal = 0.0;
     double dfAccumulatorWeightVertical = 0.0;
-    
+
     int iMin = 1 - nXRadius;
     if( iSrcX + iMin < 0 )
         iMin = -iSrcX;
@@ -3156,9 +3262,9 @@ static int GWKResampleNoMasksT( GDALWarpKernel *poWK, int iBand,
         dfAccumulator += dfWeight * dfAccumulatorLocal;
         dfAccumulatorWeightVertical += dfWeight;
     }
-    
+
     double dfAccumulatorWeight = dfAccumulatorWeightHorizontal * dfAccumulatorWeightVertical;
-    
+
     *pValue = GWKClampValueT<T>(dfAccumulator / dfAccumulatorWeight);
 
     return TRUE;
@@ -3182,7 +3288,7 @@ static int GWKResampleNoMasks_SSE2_T( GDALWarpKernel *poWK, int iBand,
     // Commonly used; save locally
     int     nSrcXSize = poWK->nSrcXSize;
     int     nSrcYSize = poWK->nSrcYSize;
-    
+
     double  dfAccumulator = 0.0;
     int     iSrcX = (int) floor( dfSrcX - 0.5 );
     int     iSrcY = (int) floor( dfSrcY - 0.5 );
@@ -3196,7 +3302,7 @@ static int GWKResampleNoMasks_SSE2_T( GDALWarpKernel *poWK, int iBand,
     int     nYRadius = poWK->nYRadius;
 
     const T*  pSrcBand = (const T*) poWK->papabySrcImage[iBand];
-    
+
     // Politely refusing to process invalid coordinates or obscenely small image
     if ( iSrcX >= nSrcXSize || iSrcY >= nSrcYSize
          || nXRadius > nSrcXSize || nYRadius > nSrcYSize )
@@ -3213,7 +3319,7 @@ static int GWKResampleNoMasks_SSE2_T( GDALWarpKernel *poWK, int iBand,
     // Loop over all rows in the kernel
     double dfAccumulatorWeightHorizontal = 0.0;
     double dfAccumulatorWeightVertical = 0.0;
-    
+
     int iMin = 1 - nXRadius;
     if( iSrcX + iMin < 0 )
         iMin = -iSrcX;
@@ -3361,7 +3467,7 @@ static int GWKResampleNoMasks_SSE2_T( GDALWarpKernel *poWK, int iBand,
     }
 
     double dfAccumulatorWeight = dfAccumulatorWeightHorizontal * dfAccumulatorWeightVertical;
-    
+
     *pValue = GWKClampValueT<T>(dfAccumulator / dfAccumulatorWeight);
 
     return TRUE;
@@ -3415,7 +3521,7 @@ int GWKResampleNoMasksT<float>( GDALWarpKernel *poWK, int iBand,
     return GWKResampleNoMasks_SSE2_T(poWK, iBand, dfSrcX, dfSrcY, pValue, padfWeight);
 }
 
-#ifdef INSTANCIATE_FLOAT64_SSE2_IMPL
+#ifdef INSTANTIATE_FLOAT64_SSE2_IMPL
 
 /************************************************************************/
 /*                     GWKResampleNoMasksT<double>()                    */
@@ -3429,7 +3535,7 @@ int GWKResampleNoMasksT<double>( GDALWarpKernel *poWK, int iBand,
     return GWKResampleNoMasks_SSE2_T(poWK, iBand, dfSrcX, dfSrcY, pValue, padfWeight);
 }
 
-#endif /* INSTANCIATE_FLOAT64_SSE2_IMPL */
+#endif /* INSTANTIATE_FLOAT64_SSE2_IMPL */
 
 #endif /* defined(__x86_64) || defined(_M_X64) */
 
@@ -3471,7 +3577,7 @@ static void GWKRoundSourceCoordinates(int nDstXSize,
             padfX[iDstX] = iDstX + dfDstXOff;
             padfY[iDstX] = dfDstY;
             padfZ[iDstX] = 0.0;
-            pfnTransformer( pTransformerArg, TRUE, 1, 
+            pfnTransformer( pTransformerArg, TRUE, 1,
                             padfX + iDstX, padfY + iDstX,
                             padfZ + iDstX, pabSuccess + iDstX );
             padfX[iDstX] = floor(padfX[iDstX] / dfSrcCoordPrecision + 0.5) * dfSrcCoordPrecision;
@@ -3485,7 +3591,7 @@ static void GWKRoundSourceCoordinates(int nDstXSize,
 /*                                                                      */
 /*      This is identical to GWKGeneralCase(), but functions via        */
 /*      OpenCL. This means we have vector optimization (SSE) and/or     */
-/*      GPU optimization depending on our prefs. The code itsef is      */
+/*      GPU optimization depending on our prefs. The code itself is     */
 /*      general and not optimized, but by defining constants we can     */
 /*      make some pretty darn good code on the fly.                     */
 /************************************************************************/
@@ -3504,7 +3610,7 @@ static CPLErr GWKOpenCLCase( GDALWarpKernel *poWK )
     int useImag = FALSE;
     OCLResampAlg resampAlg;
     cl_int err;
-    
+
     switch ( poWK->eWorkingDataType )
     {
       case GDT_Byte:
@@ -3526,11 +3632,11 @@ static CPLErr GWKOpenCLCase( GDALWarpKernel *poWK )
       default:
         // We don't support higher precision formats
         CPLDebug( "OpenCL",
-                  "Unsupported resampling OpenCL data type %d.", 
+                  "Unsupported resampling OpenCL data type %d.",
                   (int) poWK->eWorkingDataType );
         return CE_Warning;
     }
-    
+
     switch (poWK->eResample)
     {
       case GRA_Bilinear:
@@ -3547,14 +3653,16 @@ static CPLErr GWKOpenCLCase( GDALWarpKernel *poWK )
         break;
       default:
         // We don't support higher precision formats
-        CPLDebug( "OpenCL", 
-                  "Unsupported resampling OpenCL resampling alg %d.", 
+        CPLDebug( "OpenCL",
+                  "Unsupported resampling OpenCL resampling alg %d.",
                   (int) poWK->eResample );
         return CE_Warning;
     }
-    
-    // Using a factor of 2 or 4 seems to have much less rounding error than 3 on the GPU.
-    // Then the rounding error can cause strange artifacting under the right conditions.
+
+    // Using a factor of 2 or 4 seems to have much less rounding error
+    // than 3 on the GPU.
+    // Then the rounding error can cause strange artifacts under the
+    // right conditions.
     warper = GDALWarpKernelOpenCL_createEnv(nSrcXSize, nSrcYSize,
                                             nDstXSize, nDstYSize,
                                             imageFormat, poWK->nBands, 4,
@@ -3570,19 +3678,19 @@ static CPLErr GWKOpenCLCase( GDALWarpKernel *poWK )
             goto free_warper;
         return eErr;
     }
-    
+
     CPLDebug( "GDAL", "GDALWarpKernel()::GWKOpenCLCase()\n"
               "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
               nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize,
               nDstXOff, nDstYOff, nDstXSize, nDstYSize );
-    
+
     if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
     {
         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
         eErr = CE_Failure;
         goto free_warper;
     }
-    
+
     /* ==================================================================== */
     /*      Loop over bands.                                                */
     /* ==================================================================== */
@@ -3591,32 +3699,32 @@ static CPLErr GWKOpenCLCase( GDALWarpKernel *poWK )
             GDALWarpKernelOpenCL_setSrcValid(warper, (int *)poWK->papanBandSrcValid[iBand], iBand);
             if(err != CL_SUCCESS)
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "OpenCL routines reported failure (%d) on line %d.", (int) err, __LINE__ );
                 eErr = CE_Failure;
                 goto free_warper;
             }
         }
-        
+
         err = GDALWarpKernelOpenCL_setSrcImg(warper, poWK->papabySrcImage[iBand], iBand);
         if(err != CL_SUCCESS)
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "OpenCL routines reported failure (%d) on line %d.", (int) err, __LINE__ );
             eErr = CE_Failure;
             goto free_warper;
         }
-        
+
         err = GDALWarpKernelOpenCL_setDstImg(warper, poWK->papabyDstImage[iBand], iBand);
         if(err != CL_SUCCESS)
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "OpenCL routines reported failure (%d) on line %d.", (int) err, __LINE__ );
             eErr = CE_Failure;
             goto free_warper;
         }
     }
-    
+
     /* -------------------------------------------------------------------- */
     /*      Allocate x,y,z coordinate arrays for transformation ... one     */
     /*      scanlines worth of positions.                                   */
@@ -3625,7 +3733,7 @@ static CPLErr GWKOpenCLCase( GDALWarpKernel *poWK )
     int    *pabSuccess;
     double dfSrcCoordPrecision;
     double dfErrorThreshold;
-    
+
     padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
     padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
     padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
@@ -3641,7 +3749,7 @@ static CPLErr GWKOpenCLCase( GDALWarpKernel *poWK )
     for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; ++iDstY )
     {
         int iDstX;
-        
+
         /* ---------------------------------------------------------------- */
         /*      Setup points to transform to source image space.            */
         /* ---------------------------------------------------------------- */
@@ -3651,12 +3759,12 @@ static CPLErr GWKOpenCLCase( GDALWarpKernel *poWK )
             padfY[iDstX] = iDstY + 0.5 + nDstYOff;
             padfZ[iDstX] = 0.0;
         }
-        
+
         /* ---------------------------------------------------------------- */
         /*      Transform the points from destination pixel/line coordinates*/
         /*      to source pixel/line coordinates.                           */
         /* ---------------------------------------------------------------- */
-        poWK->pfnTransformer( poWK->pTransformerArg, TRUE, nDstXSize, 
+        poWK->pfnTransformer( poWK->pTransformerArg, TRUE, nDstXSize,
                               padfX, padfY, padfZ, pabSuccess );
         if( dfSrcCoordPrecision > 0.0 )
         {
@@ -3674,49 +3782,49 @@ static CPLErr GWKOpenCLCase( GDALWarpKernel *poWK )
                                                pabSuccess, iDstY);
         if(err != CL_SUCCESS)
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "OpenCL routines reported failure (%d) on line %d.", (int) err, __LINE__ );
             return CE_Failure;
         }
-        
+
         //Update the valid & density masks because we don't do so in the kernel
         for( iDstX = 0; iDstX < nDstXSize && eErr == CE_None; iDstX++ )
         {
             double dfX = padfX[iDstX];
             double dfY = padfY[iDstX];
             int iDstOffset = iDstX + iDstY * nDstXSize;
-            
+
             //See GWKGeneralCase() for appropriate commenting
             if( !pabSuccess[iDstX] || dfX < nSrcXOff || dfY < nSrcYOff )
                 continue;
-            
+
             int iSrcX = ((int) dfX) - nSrcXOff;
             int iSrcY = ((int) dfY) - nSrcYOff;
-            
+
             if( iSrcX < 0 || iSrcX >= nSrcXSize || iSrcY < 0 || iSrcY >= nSrcYSize )
                 continue;
-            
+
             int iSrcOffset = iSrcX + iSrcY * nSrcXSize;
             double  dfDensity = 1.0;
-            
-            if( poWK->pafUnifiedSrcDensity != NULL 
-                && iSrcX >= 0 && iSrcY >= 0 
+
+            if( poWK->pafUnifiedSrcDensity != NULL
+                && iSrcX >= 0 && iSrcY >= 0
                 && iSrcX < nSrcXSize && iSrcY < nSrcYSize )
                 dfDensity = poWK->pafUnifiedSrcDensity[iSrcOffset];
-            
+
             GWKOverlayDensity( poWK, iDstOffset, dfDensity );
-            
+
             //Because this is on the bit-wise level, it can't be done well in OpenCL
             if( poWK->panDstValid != NULL )
                 poWK->panDstValid[iDstOffset>>5] |= 0x01 << (iDstOffset & 0x1f);
         }
     }
-    
+
     CPLFree( padfX );
     CPLFree( padfY );
     CPLFree( padfZ );
     CPLFree( pabSuccess );
-    
+
     err = GDALWarpKernelOpenCL_runResamp(warper,
                                          poWK->pafUnifiedSrcDensity,
                                          poWK->panUnifiedSrcValid,
@@ -3726,15 +3834,15 @@ static CPLErr GWKOpenCLCase( GDALWarpKernel *poWK )
                                          poWK->dfXFilter, poWK->dfYFilter,
                                          poWK->nXRadius, poWK->nYRadius,
                                          poWK->nFiltInitX, poWK->nFiltInitY);
-    
+
     if(err != CL_SUCCESS)
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "OpenCL routines reported failure (%d) on line %d.", (int) err, __LINE__ );
         eErr = CE_Failure;
         goto free_warper;
     }
-    
+
     /* ==================================================================== */
     /*      Loop over output lines.                                         */
     /* ==================================================================== */
@@ -3745,16 +3853,16 @@ static CPLErr GWKOpenCLCase( GDALWarpKernel *poWK )
             int iDstX;
             void *rowReal, *rowImag;
             GByte *pabyDst = poWK->papabyDstImage[iBand];
-            
+
             err = GDALWarpKernelOpenCL_getRow(warper, &rowReal, &rowImag, iDstY, iBand);
             if(err != CL_SUCCESS)
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "OpenCL routines reported failure (%d) on line %d.", (int) err, __LINE__ );
                 eErr = CE_Failure;
                 goto free_warper;
             }
-            
+
             //Copy the data from the warper to GDAL's memory
             switch ( poWK->eWorkingDataType )
             {
@@ -3794,7 +3902,7 @@ static CPLErr GWKOpenCLCase( GDALWarpKernel *poWK )
               break;
               default:
                 // We don't support higher precision formats
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "Unsupported resampling OpenCL data type %d.", (int) poWK->eWorkingDataType );
                 eErr = CE_Failure;
                 goto free_warper;
@@ -3804,11 +3912,11 @@ static CPLErr GWKOpenCLCase( GDALWarpKernel *poWK )
 free_warper:
     if((err = GDALWarpKernelOpenCL_deleteEnv(warper)) != CL_SUCCESS)
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "OpenCL routines reported failure (%d) on line %d.", (int) err, __LINE__ );
         return CE_Failure;
     }
-    
+
     return eErr;
 }
 #endif /* defined(HAVE_OPENCL) */
@@ -3893,7 +4001,7 @@ static void GWKGeneralCaseThread( void* pData)
     padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
     padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
     pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
-    
+
     int bUse4SamplesFormula = (poWK->dfXScale >= 0.95 && poWK->dfYScale >= 0.95);
 
     GWKResampleWrkStruct* psWrkStruct = NULL;
@@ -3976,7 +4084,7 @@ static void GWKGeneralCaseThread( void* pData)
 /* ==================================================================== */
             int iBand;
             int bHasFoundDensity = FALSE;
-            
+
             iDstOffset = iDstX + iDstY * nDstXSize;
             for( iBand = 0; iBand < poWK->nBands; iBand++ )
             {
@@ -3990,33 +4098,38 @@ static void GWKGeneralCaseThread( void* pData)
                 if ( poWK->eResample == GRA_NearestNeighbour ||
                      nSrcXSize == 1 || nSrcYSize == 1)
                 {
-                    GWKGetPixelValue( poWK, iBand, iSrcOffset,
-                                      &dfBandDensity, &dfValueReal, &dfValueImag );
+                    // FALSE is returned if dfBandDensity == 0, which is
+                    // checked below
+                    CPL_IGNORE_RET_VAL(GWKGetPixelValue( poWK, iBand, iSrcOffset,
+                                      &dfBandDensity, &dfValueReal, &dfValueImag ));
                 }
                 else if ( poWK->eResample == GRA_Bilinear &&
                           bUse4SamplesFormula )
                 {
-                    GWKBilinearResample4Sample( poWK, iBand, 
+                    GWKBilinearResample4Sample( poWK, iBand,
                                          padfX[iDstX]-poWK->nSrcXOff,
                                          padfY[iDstX]-poWK->nSrcYOff,
-                                         &dfBandDensity, 
+                                         &dfBandDensity,
                                          &dfValueReal, &dfValueImag );
                 }
                 else if ( poWK->eResample == GRA_Cubic &&
                           bUse4SamplesFormula )
                 {
-                    GWKCubicResample4Sample( poWK, iBand, 
+                    GWKCubicResample4Sample( poWK, iBand,
                                         padfX[iDstX]-poWK->nSrcXOff,
                                         padfY[iDstX]-poWK->nSrcYOff,
-                                        &dfBandDensity, 
+                                        &dfBandDensity,
                                         &dfValueReal, &dfValueImag );
                 }
                 else
+#ifdef DEBUG
+                if( psWrkStruct != NULL ) /* only useful for clang static analyzer */
+#endif
                 {
-                    psWrkStruct->pfnGWKResample( poWK, iBand, 
+                    psWrkStruct->pfnGWKResample( poWK, iBand,
                                  padfX[iDstX]-poWK->nSrcXOff,
                                  padfY[iDstX]-poWK->nSrcYOff,
-                                 &dfBandDensity, 
+                                 &dfBandDensity,
                                  &dfValueReal, &dfValueImag, psWrkStruct );
                 }
 
@@ -4047,7 +4160,7 @@ static void GWKGeneralCaseThread( void* pData)
 
             if( poWK->panDstValid != NULL )
             {
-                poWK->panDstValid[iDstOffset>>5] |= 
+                poWK->panDstValid[iDstOffset>>5] |=
                     0x01 << (iDstOffset & 0x1f);
             }
 
@@ -4215,7 +4328,8 @@ static void GWKResampleNoMasksOrDstDensityOnlyThread( void* pData )
     GWKResampleNoMasksOrDstDensityOnlyThreadInternal<T,eResample,FALSE>(pData);
 }
 
-template<class T,GDALResampleAlg eResample> void GWKResampleNoMasksOrDstDensityOnlyHas4SampleThread( void* pData )
+template<class T,GDALResampleAlg eResample>
+static void GWKResampleNoMasksOrDstDensityOnlyHas4SampleThread( void* pData )
 
 {
     GWKJobStruct* psJob = (GWKJobStruct*) pData;
@@ -4252,7 +4366,7 @@ static CPLErr GWKCubicNoMasksOrDstDensityOnlyFloat( GDALWarpKernel *poWK )
                    GWKResampleNoMasksOrDstDensityOnlyHas4SampleThread<float,GRA_Cubic> );
 }
 
-#ifdef INSTANCIATE_FLOAT64_SSE2_IMPL
+#ifdef INSTANTIATE_FLOAT64_SSE2_IMPL
 
 static CPLErr GWKCubicNoMasksOrDstDensityOnlyDouble( GDALWarpKernel *poWK )
 {
@@ -4349,7 +4463,7 @@ static void GWKNearestThread( void* pData )
             if( !GWKCheckAndComputeSrcOffsets(pabSuccess, iDstX, padfX, padfY,
                                     poWK, nSrcXSize, nSrcYSize, iSrcOffset) )
                 continue;
- 
+
 /* -------------------------------------------------------------------- */
 /*      Do not try to apply invalid source pixels to the dest.          */
 /* -------------------------------------------------------------------- */
@@ -4374,7 +4488,7 @@ static void GWKNearestThread( void* pData )
 /*      Loop processing each band.                                      */
 /* ==================================================================== */
             int iBand;
-            
+
             iDstOffset = iDstX + iDstY * nDstXSize;
 
             for( iBand = 0; iBand < poWK->nBands; iBand++ )
@@ -4394,7 +4508,7 @@ static void GWKNearestThread( void* pData )
                         else
                         {
                             /* let the general code take care of mixing */
-                            GWKSetPixelValueRealT( poWK, iBand, iDstOffset, 
+                            GWKSetPixelValueRealT( poWK, iBand, iDstOffset,
                                           dfBandDensity, value );
                         }
                     }
@@ -4404,7 +4518,7 @@ static void GWKNearestThread( void* pData )
                     }
                 }
             }
- 
+
 /* -------------------------------------------------------------------- */
 /*      Mark this pixel valid/opaque in the output.                     */
 /* -------------------------------------------------------------------- */
@@ -4412,7 +4526,7 @@ static void GWKNearestThread( void* pData )
 
             if( poWK->panDstValid != NULL )
             {
-                poWK->panDstValid[iDstOffset>>5] |= 
+                poWK->panDstValid[iDstOffset>>5] |=
                     0x01 << (iDstOffset & 0x1f);
             }
         } /* Next iDstX */
@@ -4462,7 +4576,7 @@ static CPLErr GWKBilinearNoMasksOrDstDensityOnlyFloat( GDALWarpKernel *poWK )
                    GWKResampleNoMasksOrDstDensityOnlyHas4SampleThread<float,GRA_Bilinear> );
 }
 
-#ifdef INSTANCIATE_FLOAT64_SSE2_IMPL
+#ifdef INSTANTIATE_FLOAT64_SSE2_IMPL
 
 static CPLErr GWKBilinearNoMasksOrDstDensityOnlyDouble( GDALWarpKernel *poWK )
 {
@@ -4551,8 +4665,8 @@ static void GWKAverageOrModeThread( void* pData)
 
     // only used with nAlgo = 6
     float quant = 0.5;
-    
-    if ( poWK->eResample == GRA_Average ) 
+
+    if ( poWK->eResample == GRA_Average )
     {
         nAlgo = GWKAOM_Average;
     }
@@ -4582,7 +4696,7 @@ static void GWKAverageOrModeThread( void* pData)
             {
                 nBins = 65536;
             }
-            panVals = (int*) VSIMalloc(nBins * sizeof(int));
+            panVals = (int*) VSI_MALLOC_VERBOSE(nBins * sizeof(int));
             if( panVals == NULL )
                 return;
         }
@@ -4592,8 +4706,8 @@ static void GWKAverageOrModeThread( void* pData)
 
             if ( nSrcXSize > 0 && nSrcYSize > 0 )
             {
-                pafVals = (float*) VSIMalloc3(nSrcXSize, nSrcYSize, sizeof(float));
-                panSums = (int*) VSIMalloc3(nSrcXSize, nSrcYSize, sizeof(int));
+                pafVals = (float*) VSI_MALLOC3_VERBOSE(nSrcXSize, nSrcYSize, sizeof(float));
+                panSums = (int*) VSI_MALLOC3_VERBOSE(nSrcXSize, nSrcYSize, sizeof(int));
                 if( pafVals == NULL || panSums == NULL )
                 {
                     VSIFree(pafVals);
@@ -4718,7 +4832,7 @@ static void GWKAverageOrModeThread( void* pData)
 /* ==================================================================== */
 /*      Loop processing each band.                                      */
 /* ==================================================================== */
-            
+
             for( int iBand = 0; iBand < poWK->nBands; iBand++ )
             {
                 double dfBandDensity = 0.0;
@@ -4737,11 +4851,11 @@ static void GWKAverageOrModeThread( void* pData)
                 int iSrcXMin, iSrcXMax,iSrcYMin,iSrcYMax;
 
                 // compute corners in source crs
-                iSrcXMin = MAX( ((int) floor((padfX[iDstX] + 1e-10))) - poWK->nSrcXOff, 0 ); 
-                iSrcXMax = MIN( ((int) ceil((padfX2[iDstX] - 1e-10))) - poWK->nSrcXOff, nSrcXSize ); 
-                iSrcYMin = MAX( ((int) floor((padfY[iDstX] + 1e-10))) - poWK->nSrcYOff, 0 ); 
+                iSrcXMin = MAX( ((int) floor((padfX[iDstX] + 1e-10))) - poWK->nSrcXOff, 0 );
+                iSrcXMax = MIN( ((int) ceil((padfX2[iDstX] - 1e-10))) - poWK->nSrcXOff, nSrcXSize );
+                iSrcYMin = MAX( ((int) floor((padfY[iDstX] + 1e-10))) - poWK->nSrcYOff, 0 );
                 iSrcYMax = MIN( ((int) ceil((padfY2[iDstX] - 1e-10))) - poWK->nSrcYOff, nSrcYSize );
-                
+
                 // The transformation might not have preserved ordering of coordinates
                 // so do the necessary swapping (#5433)
                 // NOTE: this is really an approximative fix. To do something more precise
@@ -4750,12 +4864,12 @@ static void GWKAverageOrModeThread( void* pData)
                 // and take the bounding box of the got source coordinates.
                 if( iSrcXMax < iSrcXMin )
                 {
-                    iSrcXMin = MAX( ((int) floor((padfX2[iDstX] + 1e-10))) - poWK->nSrcXOff, 0 ); 
-                    iSrcXMax = MIN( ((int) ceil((padfX[iDstX] - 1e-10))) - poWK->nSrcXOff, nSrcXSize ); 
+                    iSrcXMin = MAX( ((int) floor((padfX2[iDstX] + 1e-10))) - poWK->nSrcXOff, 0 );
+                    iSrcXMax = MIN( ((int) ceil((padfX[iDstX] - 1e-10))) - poWK->nSrcXOff, nSrcXSize );
                 }
                 if( iSrcYMax < iSrcYMin )
                 {
-                    iSrcYMin = MAX( ((int) floor((padfY2[iDstX] + 1e-10))) - poWK->nSrcYOff, 0 ); 
+                    iSrcYMin = MAX( ((int) floor((padfY2[iDstX] + 1e-10))) - poWK->nSrcYOff, 0 );
                     iSrcYMax = MIN( ((int) ceil((padfY[iDstX] - 1e-10))) - poWK->nSrcYOff, nSrcYSize );
                 }
                 if( iSrcXMin == iSrcXMax && iSrcXMax < nSrcXSize )
@@ -4764,7 +4878,7 @@ static void GWKAverageOrModeThread( void* pData)
                     iSrcYMax ++;
 
                 // loop over source lines and pixels - 3 possible algorithms
-                
+
                 if ( nAlgo == GWKAOM_Average ) // poWK->eResample == GRA_Average
                 {
                     // this code adapted from GDALDownsampleChunk32R_AverageT() in gcore/overview.cpp
@@ -4773,64 +4887,64 @@ static void GWKAverageOrModeThread( void* pData)
                         for( iSrcX = iSrcXMin; iSrcX < iSrcXMax; iSrcX++ )
                         {
                             iSrcOffset = iSrcX + iSrcY * nSrcXSize;
-                            
+
                             if( poWK->panUnifiedSrcValid != NULL
                                 && !(poWK->panUnifiedSrcValid[iSrcOffset>>5]
                                      & (0x01 << (iSrcOffset & 0x1f))) )
                             {
                                 continue;
                             }
-                            
+
                             nCount2++;
                             if ( GWKGetPixelValue( poWK, iBand, iSrcOffset,
-                                                   &dfBandDensity, &dfValueRealTmp, &dfValueImagTmp ) && dfBandDensity > 0.0000000001 ) 
+                                                   &dfBandDensity, &dfValueRealTmp, &dfValueImagTmp ) && dfBandDensity > 0.0000000001 )
                             {
                                 nCount++;
                                 dfTotal += dfValueRealTmp;
                             }
                         }
                     }
-                    
+
                     if ( nCount > 0 )
-                    {                
+                    {
                         dfValueReal = dfTotal / nCount;
-                        dfBandDensity = 1;                
+                        dfBandDensity = 1;
                         bHasFoundDensity = TRUE;
                     }
-                                       
+
                 } // GRA_Average
-                
+
                 else if ( nAlgo == GWKAOM_Imode || nAlgo == GWKAOM_Fmode ) // poWK->eResample == GRA_Mode
                 {
                     // this code adapted from GDALDownsampleChunk32R_Mode() in gcore/overview.cpp
 
                     if ( nAlgo == GWKAOM_Fmode ) // int32 or float
                     {
-                        /* I'm not sure how much sense it makes to run a majority
-                           filter on floating point data, but here it is for the sake
-                           of compatability. It won't look right on RGB images by the
-                           nature of the filter. */
-                        int     iMaxInd = 0, iMaxVal = -1, i = 0;
+                        /* I'm not sure how much sense it makes to run a
+                           majority filter on floating point data, but here it
+                           is for the sake of compatibility. It won't look
+                           right on RGB images by the nature of the filter. */
+                        int iMaxInd = 0, iMaxVal = -1, i = 0;
 
                         for( iSrcY = iSrcYMin; iSrcY < iSrcYMax; iSrcY++ )
                         {
                             for( iSrcX = iSrcXMin; iSrcX < iSrcXMax; iSrcX++ )
                             {
                                 iSrcOffset = iSrcX + iSrcY * nSrcXSize;
-                                
+
                                 if( poWK->panUnifiedSrcValid != NULL
                                     && !(poWK->panUnifiedSrcValid[iSrcOffset>>5]
                                          & (0x01 << (iSrcOffset & 0x1f))) )
                                     continue;
-                                
+
                                 nCount2++;
                                 if ( GWKGetPixelValue( poWK, iBand, iSrcOffset,
-                                                       &dfBandDensity, &dfValueRealTmp, &dfValueImagTmp ) && dfBandDensity > 0.0000000001 ) 
+                                                       &dfBandDensity, &dfValueRealTmp, &dfValueImagTmp ) && dfBandDensity > 0.0000000001 )
                                 {
                                     nCount++;
 
                                     float fVal = (float)dfValueRealTmp;
-                                    
+
                                     //Check array for existing entry
                                     for( i = 0; i < iMaxInd; ++i )
                                         if( pafVals[i] == fVal
@@ -4839,16 +4953,16 @@ static void GWKAverageOrModeThread( void* pData)
                                             iMaxVal = i;
                                             break;
                                         }
-                                    
+
                                     //Add to arr if entry not already there
                                     if( i == iMaxInd )
                                     {
                                         pafVals[iMaxInd] = fVal;
                                         panSums[iMaxInd] = 1;
-                                        
+
                                         if( iMaxVal < 0 )
                                             iMaxVal = iMaxInd;
-                                        
+
                                         ++iMaxInd;
                                     }
                                 }
@@ -4858,31 +4972,31 @@ static void GWKAverageOrModeThread( void* pData)
                         if( iMaxVal != -1 )
                         {
                             dfValueReal = pafVals[iMaxVal];
-                            dfBandDensity = 1;                
+                            dfBandDensity = 1;
                             bHasFoundDensity = TRUE;
                         }
                     }
-                    
+
                     else // byte or int16
                     {
                         int nMaxVal = 0, iMaxInd = -1;
 
                         memset(panVals, 0, nBins*sizeof(int));
-                        
+
                         for( iSrcY = iSrcYMin; iSrcY < iSrcYMax; iSrcY++ )
                         {
                             for( iSrcX = iSrcXMin; iSrcX < iSrcXMax; iSrcX++ )
                             {
                                 iSrcOffset = iSrcX + iSrcY * nSrcXSize;
-                                
+
                                 if( poWK->panUnifiedSrcValid != NULL
                                     && !(poWK->panUnifiedSrcValid[iSrcOffset>>5]
                                          & (0x01 << (iSrcOffset & 0x1f))) )
                                     continue;
-                                
+
                                 nCount2++;
                                 if ( GWKGetPixelValue( poWK, iBand, iSrcOffset,
-                                                       &dfBandDensity, &dfValueRealTmp, &dfValueImagTmp ) && dfBandDensity > 0.0000000001 ) 
+                                                       &dfBandDensity, &dfValueRealTmp, &dfValueImagTmp ) && dfBandDensity > 0.0000000001 )
                                 {
                                     nCount++;
 
@@ -4897,15 +5011,15 @@ static void GWKAverageOrModeThread( void* pData)
                                 }
                             }
                         }
-                        
+
                         if( iMaxInd != -1 )
                         {
                             dfValueReal = (float)iMaxInd;
-                            dfBandDensity = 1;                
-                            bHasFoundDensity = TRUE;                  
+                            dfBandDensity = 1;
+                            bHasFoundDensity = TRUE;
                         }
                     }
-                    
+
                 } // GRA_Mode
                 else if ( nAlgo == GWKAOM_Max ) // poWK->eResample == GRA_Max
                 {
@@ -4986,7 +5100,7 @@ static void GWKAverageOrModeThread( void* pData)
                 else if ( nAlgo == GWKAOM_Quant ) // poWK->eResample == GRA_Med | GRA_Q1 | GRA_Q3
                 {
                     std::vector<double> dfValuesTmp;
-                    
+
                     // this code adapted from nAlgo 1 method, GRA_Average
                     for( iSrcY = iSrcYMin; iSrcY < iSrcYMax; iSrcY++ )
                     {
@@ -5014,7 +5128,7 @@ static void GWKAverageOrModeThread( void* pData)
                     if ( nCount > 0 )
                     {
                         std::sort(dfValuesTmp.begin(), dfValuesTmp.end());
-                        int quantIdx = std::ceil(quant * dfValuesTmp.size() - 1);
+                        int quantIdx = static_cast<int>(std::ceil(quant * dfValuesTmp.size() - 1));
                         dfValueReal = dfValuesTmp[quantIdx];
 
                         dfBandDensity = 1;
@@ -5038,9 +5152,9 @@ static void GWKAverageOrModeThread( void* pData)
                     GWKSetPixelValue( poWK, iBand, iDstOffset,
                                       dfBandDensity,
                                       dfValueReal, dfValueImag );
-                }                    
+                }
             }
-            
+
             if (!bHasFoundDensity)
                 continue;
 
@@ -5051,7 +5165,7 @@ static void GWKAverageOrModeThread( void* pData)
 
             if( poWK->panDstValid != NULL )
             {
-                poWK->panDstValid[iDstOffset>>5] |= 
+                poWK->panDstValid[iDstOffset>>5] |=
                     0x01 << (iDstOffset & 0x1f);
             }
 
diff --git a/alg/gdalwarpkernel_opencl.c b/alg/gdalwarpkernel_opencl.c
index 08b9549..4cb9284 100644
--- a/alg/gdalwarpkernel_opencl.c
+++ b/alg/gdalwarpkernel_opencl.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalwarpkernel_opencl.c 28300 2015-01-07 08:30:07Z rouault $
+ * $Id: gdalwarpkernel_opencl.c 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  OpenCL Image Reprojector
  * Purpose:  Implementation of the GDALWarpKernel reprojector in OpenCL.
@@ -41,7 +41,7 @@
 #include "cpl_string.h"
 #include "gdalwarpkernel_opencl.h"
 
-CPL_CVSID("$Id: gdalwarpkernel_opencl.c 28300 2015-01-07 08:30:07Z rouault $");
+CPL_CVSID("$Id: gdalwarpkernel_opencl.c 33715 2016-03-13 08:52:06Z goatbar $");
 
 #define handleErr(err) if((err) != CL_SUCCESS) { \
     CPLError(CE_Failure, CPLE_AppDefined, "Error at file %s line %d: %s", __FILE__, __LINE__, getCLErrorString(err)); \
@@ -247,7 +247,7 @@ static const char* getCLDataTypeString( cl_channel_type dataType )
 }
 
 /*
- Finds an appropirate OpenCL device. If the user specifies a preference, the
+ Finds an appropriate OpenCL device. If the user specifies a preference, the
  code for it should be here (but not currently supported). For debugging, it's
  always easier to use CL_DEVICE_TYPE_CPU because then printf() can be called
  from the kernel. If debugging is on, we can print the name and stats about the
@@ -260,7 +260,7 @@ cl_device_id get_device(OCLVendor *peVendor)
     size_t returned_size = 0;
     cl_char vendor_name[1024] = {0};
     cl_char device_name[1024] = {0};
-    
+
     cl_platform_id platforms[10];
     cl_uint num_platforms;
 
@@ -278,18 +278,18 @@ cl_device_id get_device(OCLVendor *peVendor)
         if( err != CL_SUCCESS || device == 0 )
             return NULL;
     }
-    
+
     // Get some information about the returned device
-    err = clGetDeviceInfo(device, CL_DEVICE_VENDOR, sizeof(vendor_name), 
+    err = clGetDeviceInfo(device, CL_DEVICE_VENDOR, sizeof(vendor_name),
                           vendor_name, &returned_size);
-    err |= clGetDeviceInfo(device, CL_DEVICE_NAME, sizeof(device_name), 
+    err |= clGetDeviceInfo(device, CL_DEVICE_NAME, sizeof(device_name),
                            device_name, &returned_size);
     assert(err == CL_SUCCESS);
     CPLDebug( "OpenCL", "Connected to %s %s.", vendor_name, device_name);
 
-    if (strncmp((const char*)vendor_name, "Advanced Micro Devices", strlen("Advanced Micro Devices")) == 0)
+    if (STARTS_WITH((const char*)vendor_name, "Advanced Micro Devices"))
         *peVendor = VENDOR_AMD;
-    else if (strncmp((const char*)vendor_name, "Intel(R) Corporation", strlen("Intel(R) Corporation")) == 0)
+    else if (STARTS_WITH((const char*)vendor_name, "Intel(R) Corporation"))
         *peVendor = VENDOR_INTEL;
     else
         *peVendor = VENDOR_OTHER;
@@ -314,7 +314,7 @@ cl_int set_supported_formats(struct oclWarper *warper,
     int extraSpace = 9999;
     cl_int err;
     int bFound = FALSE;
-    
+
     //Find what we *can* handle
     handleErr(err = clGetSupportedImageFormats(warper->context,
                                                CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
@@ -340,12 +340,12 @@ cl_int set_supported_formats(struct oclWarper *warper,
             thisOrderSize = 4;
             break;
         }
-        
+
         //Choose an order with the least wasted space
         if (fmtBuf[i].image_channel_data_type == dataType &&
             minOrderSize <= thisOrderSize &&
             extraSpace > thisOrderSize - minOrderSize ) {
-			
+
             //Set the vector size, order, & remember wasted space
             (*chosenSize) = thisOrderSize;
             (*chosenOrder) = fmtBuf[i].image_channel_order;
@@ -353,9 +353,9 @@ cl_int set_supported_formats(struct oclWarper *warper,
             bFound = TRUE;
         }
     }
-    
+
     free(fmtBuf);
-    
+
     if( !bFound )
     {
         CPLDebug("OpenCL",
@@ -374,7 +374,7 @@ cl_int set_supported_formats(struct oclWarper *warper,
  has as much pinned host RAM available as total device RAM because device RAM
  tends to be similarly scarce. However, if the pinned memory fails we fall back
  to using a regular memory allocation.
- 
+
  Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
  */
 cl_int alloc_pinned_mem(struct oclWarper *warper, int imgNum, size_t dataSz,
@@ -396,12 +396,12 @@ cl_int alloc_pinned_mem(struct oclWarper *warper, int imgNum, size_t dataSz,
         CPLDebug("OpenCL", "Using fallback non-pinned memory!");
 #endif
         //Fallback to regular allocation
-        wrkPtr[imgNum] = (void *)VSIMalloc(dataSz);
-        
+        wrkPtr[imgNum] = (void *)VSI_MALLOC_VERBOSE(dataSz);
+
         if (wrkPtr[imgNum] == NULL)
             handleErr(err = CL_OUT_OF_HOST_MEMORY);
     }
-    
+
     return CL_SUCCESS;
 }
 
@@ -412,7 +412,7 @@ cl_int alloc_pinned_mem(struct oclWarper *warper, int imgNum, size_t dataSz,
  Reasons for buffering it like this include reading each row from disk and
  de-interleaving bands and parts of bands. Then they can be copied to the device
  as a single operation fit for use as an OpenCL memory object.
- 
+
  Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
  */
 cl_int alloc_working_arr(struct oclWarper *warper,
@@ -422,7 +422,7 @@ cl_int alloc_working_arr(struct oclWarper *warper,
     int i, b;
     size_t srcDataSz1, dstDataSz1, srcDataSz4, dstDataSz4;
     const int numBands = warper->numBands;
-    
+
     //Find the best channel order for this format
     err = set_supported_formats(warper, 1,
                                 &(warper->imgChOrder1), &(warper->imgChSize1),
@@ -434,37 +434,37 @@ cl_int alloc_working_arr(struct oclWarper *warper,
                                     warper->imageFormat);
         handleErr(err);
     }
-    
+
     //Alloc space for pointers to the main image data
-    warper->realWork.v = (void **)VSICalloc(ptrSz, warper->numImages);
-    warper->dstRealWork.v = (void **)VSICalloc(ptrSz, warper->numImages);
+    warper->realWork.v = (void **)VSI_CALLOC_VERBOSE(ptrSz, warper->numImages);
+    warper->dstRealWork.v = (void **)VSI_CALLOC_VERBOSE(ptrSz, warper->numImages);
     if (warper->realWork.v == NULL || warper->dstRealWork.v == NULL)
         handleErr(err = CL_OUT_OF_HOST_MEMORY);
-    
+
     if (warper->imagWorkCL != NULL) {
         //Alloc space for pointers to the extra channel, if it exists
-        warper->imagWork.v = (void **)VSICalloc(ptrSz, warper->numImages);
-        warper->dstImagWork.v = (void **)VSICalloc(ptrSz, warper->numImages);
+        warper->imagWork.v = (void **)VSI_CALLOC_VERBOSE(ptrSz, warper->numImages);
+        warper->dstImagWork.v = (void **)VSI_CALLOC_VERBOSE(ptrSz, warper->numImages);
         if (warper->imagWork.v == NULL || warper->dstImagWork.v == NULL)
             handleErr(err = CL_OUT_OF_HOST_MEMORY);
     } else {
         warper->imagWork.v = NULL;
         warper->dstImagWork.v = NULL;
     }
-    
+
     //Calc the sizes we need
     srcDataSz1 = dataSz * warper->srcWidth * warper->srcHeight * warper->imgChSize1;
     dstDataSz1 = dataSz * warper->dstWidth * warper->dstHeight;
     srcDataSz4 = dataSz * warper->srcWidth * warper->srcHeight * warper->imgChSize4;
     dstDataSz4 = dataSz * warper->dstWidth * warper->dstHeight * 4;
-    
+
     //Allocate pinned memory for each band's image
     for (b = 0, i = 0; b < numBands && i < warper->numImages; ++i) {
         if(warper->useVec && b < numBands - numBands % 4) {
             handleErr(err = alloc_pinned_mem(warper, i, srcDataSz4,
                                              warper->realWork.v,
                                              warper->realWorkCL));
-            
+
             handleErr(err = alloc_pinned_mem(warper, i, dstDataSz4,
                                              warper->dstRealWork.v,
                                              warper->dstRealWorkCL));
@@ -473,14 +473,14 @@ cl_int alloc_working_arr(struct oclWarper *warper,
             handleErr(err = alloc_pinned_mem(warper, i, srcDataSz1,
                                              warper->realWork.v,
                                              warper->realWorkCL));
-            
+
             handleErr(err = alloc_pinned_mem(warper, i, dstDataSz1,
                                              warper->dstRealWork.v,
                                              warper->dstRealWorkCL));
             ++b;
         }
     }
-    
+
     if (warper->imagWorkCL != NULL) {
         //Allocate pinned memory for each band's extra channel, if exists
         for (b = 0, i = 0; b < numBands && i < warper->numImages; ++i) {
@@ -488,7 +488,7 @@ cl_int alloc_working_arr(struct oclWarper *warper,
                 handleErr(err = alloc_pinned_mem(warper, i, srcDataSz4,
                                                  warper->imagWork.v,
                                                  warper->imagWorkCL));
-                
+
                 handleErr(err = alloc_pinned_mem(warper, i, dstDataSz4,
                                                  warper->dstImagWork.v,
                                                  warper->dstImagWorkCL));
@@ -497,7 +497,7 @@ cl_int alloc_working_arr(struct oclWarper *warper,
                 handleErr(err = alloc_pinned_mem(warper, i, srcDataSz1,
                                                  warper->imagWork.v,
                                                  warper->imagWorkCL));
-                
+
                 handleErr(err = alloc_pinned_mem(warper, i, dstDataSz1,
                                                  warper->dstImagWork.v,
                                                  warper->dstImagWorkCL));
@@ -505,17 +505,17 @@ cl_int alloc_working_arr(struct oclWarper *warper,
             }
         }
     }
-    
+
     return CL_SUCCESS;
 }
 
 /*
- Assemble and create the kernel. For optimization, portabilaty, and
- implimentation limitation reasons, the program is actually assembled from
+ Assemble and create the kernel. For optimization, portability, and
+ implementation limitation reasons, the program is actually assembled from
  several strings, then compiled with as many invariants as possible defined by
  the preprocessor. There is also quite a bit of error-catching code in here
  because the kernel is where many bugs show up.
- 
+
  Returns CL_SUCCESS on success and other CL_* errors in the error buffer when
  something goes wrong.
  */
@@ -528,9 +528,10 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
     cl_kernel kernel;
 	cl_int err = CL_SUCCESS;
     char *buffer = (char *)CPLCalloc(128000, sizeof(char));
-    char *progBuf = (char *)CPLCalloc(128000, sizeof(char));
+#define PROGBUF_SIZE 128000
+    char *progBuf = (char *)CPLCalloc(PROGBUF_SIZE, sizeof(char));
     float dstMinVal, dstMaxVal;
-    
+
     const char *outType;
     const char *dUseVec = "";
     const char *dVecf = "float";
@@ -579,14 +580,14 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
                 "int bandNum)\n"
 "{\n"
 	"fReal *= dstMaxVal;\n"
-    
+
     "if (fReal < dstMinVal)\n"
         "dstPtr[iDstOffset] = (outType)dstMinVal;\n"
     "else if (fReal > dstMaxVal)\n"
         "dstPtr[iDstOffset] = (outType)dstMaxVal;\n"
     "else\n"
         "dstPtr[iDstOffset] = (dstMinVal < 0) ? (outType)floor(fReal + 0.5f) : (outType)(fReal + 0.5f);\n"
-    
+
     "if (useDstNoDataReal && bandNum >= 0 &&\n"
         "fDstNoDataReal[bandNum] == dstPtr[iDstOffset])\n"
     "{\n"
@@ -611,15 +612,15 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
 "#ifdef USE_VEC\n"
     "if (fDensity.x < 0.00001f && fDensity.y < 0.00001f &&\n"
         "fDensity.z < 0.00001f && fDensity.w < 0.00001f ) {\n"
-    
+
         "fReal = 0.0f;\n"
         "fImag = 0.0f;\n"
-    
+
     "} else if (fDensity.x < 0.9999f || fDensity.y < 0.9999f ||\n"
                "fDensity.z < 0.9999f || fDensity.w < 0.9999f ) {\n"
         "vecf fDstReal, fDstImag;\n"
         "float fDstDensity;\n"
-    
+
         "fDstReal.x = dstReal[iDstOffset];\n"
         "fDstReal.y = dstReal[iDstOffset+iDstHeight*iDstWidth];\n"
         "fDstReal.z = dstReal[iDstOffset+iDstHeight*iDstWidth*2];\n"
@@ -632,19 +633,19 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
         "}\n"
 "#else\n"
     "if (fDensity < 0.00001f) {\n"
-    
+
         "fReal = 0.0f;\n"
         "fImag = 0.0f;\n"
-    
+
     "} else if (fDensity < 0.9999f) {\n"
         "vecf fDstReal, fDstImag;\n"
         "float fDstDensity;\n"
-    
+
         "fDstReal = dstReal[iDstOffset];\n"
         "if (useImag)\n"
             "fDstImag = dstImag[iDstOffset];\n"
 "#endif\n"
-    
+
         "if (useDstDensity)\n"
             "fDstDensity = dstDensity[iDstOffset];\n"
         "else if (useDstValid &&\n"
@@ -652,15 +653,15 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
             "fDstDensity = 0.0f;\n"
         "else\n"
             "fDstDensity = 1.0f;\n"
-        
+
         "vecf fDstInfluence = (1.0f - fDensity) * fDstDensity;\n"
-        
+
         // Density should be checked for <= 0.0 & handled by the calling function
         "fReal = (fReal * fDensity + fDstReal * fDstInfluence) / (fDensity + fDstInfluence);\n"
         "if (useImag)\n"
             "fImag = (fImag * fDensity + fDstImag * fDstInfluence) / (fDensity + fDstInfluence);\n"
     "}\n"
-    
+
 "#ifdef USE_VEC\n"
     "clampToDst(fReal.x, dstReal, iDstOffset, fDstNoDataReal, bandNum);\n"
     "clampToDst(fReal.y, dstReal, iDstOffset+iDstHeight*iDstWidth, fDstNoDataReal, bandNum);\n"
@@ -691,45 +692,45 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
 "{\n"
     "int iSrcOffset = 0, iBandValidLen = 0, iSrcOffsetMask = 0;\n"
     "int bHasValid = FALSE;\n"
-    
+
     // Clamp the src offset values if needed
     "if(useUnifiedSrcDensity | useUnifiedSrcValid | useUseBandSrcValid){\n"
         "int iSrcX = iSrc.x;\n"
         "int iSrcY = iSrc.y;\n"
-        
+
         // Needed because the offset isn't clamped in OpenCL hardware
         "if(iSrcX < 0)\n"
             "iSrcX = 0;\n"
         "else if(iSrcX >= iSrcWidth)\n"
             "iSrcX = iSrcWidth - 1;\n"
-            
+
         "if(iSrcY < 0)\n"
             "iSrcY = 0;\n"
         "else if(iSrcY >= iSrcHeight)\n"
             "iSrcY = iSrcHeight - 1;\n"
-            
+
         "iSrcOffset = iSrcY*iSrcWidth + iSrcX;\n"
         "iBandValidLen = 1 + ((iSrcWidth*iSrcHeight)>>5);\n"
         "iSrcOffsetMask = (0x01 << (iSrcOffset & 0x1f));\n"
     "}\n"
-    
+
     "if (useUnifiedSrcValid &&\n"
         "!((nUnifiedSrcValid[iSrcOffset>>5] & iSrcOffsetMask) ) )\n"
         "return FALSE;\n"
-    
+
 "#ifdef USE_VEC\n"
     "if (!useUseBandSrcValid || !useBandSrcValid[bandNum] ||\n"
         "((nBandSrcValid[(iSrcOffset>>5)+iBandValidLen*bandNum    ] & iSrcOffsetMask)) )\n"
         "bHasValid = TRUE;\n"
-    
+
     "if (!useUseBandSrcValid || !useBandSrcValid[bandNum+1] ||\n"
         "((nBandSrcValid[(iSrcOffset>>5)+iBandValidLen*(1+bandNum)] & iSrcOffsetMask)) )\n"
         "bHasValid = TRUE;\n"
-    
+
     "if (!useUseBandSrcValid || !useBandSrcValid[bandNum+2] ||\n"
         "((nBandSrcValid[(iSrcOffset>>5)+iBandValidLen*(2+bandNum)] & iSrcOffsetMask)) )\n"
         "bHasValid = TRUE;\n"
-    
+
     "if (!useUseBandSrcValid || !useBandSrcValid[bandNum+3] ||\n"
         "((nBandSrcValid[(iSrcOffset>>5)+iBandValidLen*(3+bandNum)] & iSrcOffsetMask)) )\n"
         "bHasValid = TRUE;\n"
@@ -738,14 +739,14 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
         "((nBandSrcValid[(iSrcOffset>>5)+iBandValidLen*bandNum    ] & iSrcOffsetMask)) )\n"
         "bHasValid = TRUE;\n"
 "#endif\n"
-    
+
     "if (!bHasValid)\n"
         "return FALSE;\n"
-    
+
     "const sampler_t samp =  CLK_NORMALIZED_COORDS_FALSE |\n"
                             "CLK_ADDRESS_CLAMP_TO_EDGE |\n"
                             "CLK_FILTER_NEAREST;\n"
-    
+
 "#ifdef USE_VEC\n"
     "(*fReal) = read_imagef(srcReal, samp, iSrc);\n"
     "if (useImag)\n"
@@ -755,14 +756,14 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
     "if (useImag)\n"
         "(*fImag) = read_imagef(srcImag, samp, iSrc).x;\n"
 "#endif\n"
-    
+
     "if (useUnifiedSrcDensity) {\n"
         "(*fDensity) = fUnifiedSrcDensity[iSrcOffset];\n"
     "} else {\n"
         "(*fDensity) = 1.0f;\n"
         "return TRUE;\n"
     "}\n"
-    
+
 "#ifdef USE_VEC\n"
     "return  (*fDensity).x > 0.0000001f || (*fDensity).y > 0.0000001f ||\n"
             "(*fDensity).z > 0.0000001f || (*fDensity).w > 0.0000001f;\n"
@@ -777,22 +778,22 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
 "{\n"
     "if (fSrcCoords.x < 0.0f || fSrcCoords.y < 0.0f)\n"
         "return FALSE;\n"
-    
+
     "int iSrcX = (int) (fSrcCoords.x - 0.5f);\n"
     "int iSrcY = (int) (fSrcCoords.y - 0.5f);\n"
-    
+
     "if( iSrcX < 0 || iSrcX >= iSrcWidth || iSrcY < 0 || iSrcY >= iSrcHeight )\n"
         "return FALSE;\n"
-    
+
     "int iSrcOffset = iSrcX + iSrcY * iSrcWidth;\n"
-    
+
     "if (useUnifiedSrcDensity && fUnifiedSrcDensity[iSrcOffset] < 0.00001f)\n"
         "return FALSE;\n"
-    
+
     "if (useUnifiedSrcValid &&\n"
         "!(nUnifiedSrcValid[iSrcOffset>>5] & (0x01 << (iSrcOffset & 0x1f))) )\n"
         "return FALSE;\n"
-    
+
     "return TRUE;\n"
 "}\n"
 
@@ -806,7 +807,7 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
                                 "(float)((ceil((iDstWidth  - 1) / (float)iCoordMult) + 1) * iCoordMult), \n"
                             "(0.5f * (float)iCoordMult + nDstY) /\n"
                                 "(float)((ceil((iDstHeight - 1) / (float)iCoordMult) + 1) * iCoordMult));\n"
-    
+
     // Check & return when the thread group overruns the image size
     "if (nDstX >= iDstWidth || nDstY >= iDstHeight)\n"
         "return (float2)(-99.0f, -99.0f);\n"
@@ -816,10 +817,10 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
                             "CLK_FILTER_LINEAR;\n"
 
     "float4  fSrcCoords = read_imagef(srcCoords,samp,fDst);\n"
-    
+
     "return (float2)(fSrcCoords.x, fSrcCoords.y);\n"
 "}\n";
-    
+
     const char *kernBilinear =
 // ************************ Bilinear ************************
 "__kernel void resamp(__read_only image2d_t srcCoords,\n"
@@ -848,11 +849,11 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
     "vecf    fAccumulatorReal = 0.0f, fAccumulatorImag = 0.0f;\n"
     "vecf    fAccumulatorDensity = 0.0f;\n"
     "float   fAccumulatorDivisor = 0.0f;\n"
-    
+
     "if ( iSrcY >= 0 && iSrcY < iSrcHeight ) {\n"
         "float fMult1 = fRatioX * fRatioY;\n"
         "float fMult2 = (1.0f-fRatioX) * fRatioY;\n"
-    
+
 		// Upper Left Pixel
 		"if ( iSrcX >= 0 && iSrcX < iSrcWidth\n"
 			 "&& getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
@@ -864,7 +865,7 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
 			"fAccumulatorImag += fImag * fMult1;\n"
 			"fAccumulatorDensity += fDens * fMult1;\n"
 		"}\n"
-	
+
 		// Upper Right Pixel
 		"if ( iSrcX+1 >= 0 && iSrcX+1 < iSrcWidth\n"
 			"&& getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
@@ -877,11 +878,11 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
 			"fAccumulatorDensity += fDens * fMult2;\n"
 		"}\n"
     "}\n"
-    
+
     "if ( iSrcY+1 >= 0 && iSrcY+1 < iSrcHeight ) {\n"
         "float fMult1 = fRatioX * (1.0f-fRatioY);\n"
         "float fMult2 = (1.0f-fRatioX) * (1.0f-fRatioY);\n"
-    
+
         // Lower Left Pixel
 		"if ( iSrcX >= 0 && iSrcX < iSrcWidth\n"
 			"&& getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
@@ -893,7 +894,7 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
 			"fAccumulatorImag += fImag * fMult1;\n"
 			"fAccumulatorDensity += fDens * fMult1;\n"
 		"}\n"
-	
+
 		// Lower Right Pixel
 		"if ( iSrcX+1 >= 0 && iSrcX+1 < iSrcWidth\n"
 			"&& getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
@@ -906,7 +907,7 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
 			"fAccumulatorDensity += fDens * fMult2;\n"
 		"}\n"
     "}\n"
-    
+
     // Compute and save final pixel
     "if ( fAccumulatorDivisor < 0.00001f ) {\n"
         "setPixel(dstReal, dstImag, dstDensity, nDstValid, fDstNoDataReal, bandNum,\n"
@@ -925,7 +926,7 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
                 "fAccumulatorDensity, fAccumulatorReal, fAccumulatorImag );\n"
     "}\n"
 "}\n";
-    
+
     const char *kernCubic =
 // ************************ Cubic ************************
 "vecf cubicConvolution(float dist1, float dist2, float dist3,\n"
@@ -957,10 +958,10 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
 "{\n"
     "int i;\n"
     "float2  fSrc = getSrcCoords(srcCoords);\n"
-    
+
     "if (!isValid(fUnifiedSrcDensity, nUnifiedSrcValid, fSrc))\n"
         "return;\n"
-    
+
     "int     iSrcX = (int) floor( fSrc.x - 0.5f );\n"
     "int     iSrcY = (int) floor( fSrc.y - 0.5f );\n"
     "float   fDeltaX = fSrc.x - 0.5f - (float)iSrcX;\n"
@@ -975,7 +976,7 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
 "#else\n"
     "vecf    fImag = 0.0f;\n"
 "#endif\n"
-    
+
     // Loop over rows
     "for (i = -1; i < 3; ++i)\n"
     "{\n"
@@ -984,20 +985,20 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
         "int hasPx;\n"
 "#if useImag != 0\n"
         "vecf    fImag1 = 0.0f, fImag2 = 0.0f, fImag3 = 0.0f, fImag4 = 0.0f;\n"
-        
+
         //Get all the pixels for this row
         "hasPx  = getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
                         "useBandSrcValid, nBandSrcValid, (int2)(iSrcX-1, iSrcY+i),\n"
                         "bandNum, &fDens1, &fReal1, &fImag1);\n"
-        
+
         "hasPx |= getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
                         "useBandSrcValid, nBandSrcValid, (int2)(iSrcX  , iSrcY+i),\n"
                         "bandNum, &fDens2, &fReal2, &fImag2);\n"
-        
+
         "hasPx |= getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
                         "useBandSrcValid, nBandSrcValid, (int2)(iSrcX+1, iSrcY+i),\n"
                         "bandNum, &fDens3, &fReal3, &fImag3);\n"
-        
+
         "hasPx |= getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
                         "useBandSrcValid, nBandSrcValid, (int2)(iSrcX+2, iSrcY+i),\n"
                         "bandNum, &fDens4, &fReal4, &fImag4);\n"
@@ -1006,20 +1007,20 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
         "hasPx  = getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
                 "useBandSrcValid, nBandSrcValid, (int2)(iSrcX-1, iSrcY+i),\n"
                 "bandNum, &fDens1, &fReal1, &fImag);\n"
-        
+
         "hasPx |= getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
                 "useBandSrcValid, nBandSrcValid, (int2)(iSrcX  , iSrcY+i),\n"
                 "bandNum, &fDens2, &fReal2, &fImag);\n"
-        
+
         "hasPx |= getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
                 "useBandSrcValid, nBandSrcValid, (int2)(iSrcX+1, iSrcY+i),\n"
                 "bandNum, &fDens3, &fReal3, &fImag);\n"
-        
+
         "hasPx |= getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
                 "useBandSrcValid, nBandSrcValid, (int2)(iSrcX+2, iSrcY+i),\n"
                 "bandNum, &fDens4, &fReal4, &fImag);\n"
 "#endif\n"
-        
+
         // Shortcut if no px
         "if (!hasPx) {\n"
             "afDens[i+1] = 0.0f;\n"
@@ -1029,7 +1030,7 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
 "#endif\n"
             "continue;\n"
         "}\n"
-        
+
         // Process this row
         "afDens[i+1] = cubicConvolution(fDeltaX, fDeltaX2, fDeltaX3, fDens1, fDens2, fDens3, fDens4);\n"
         "afReal[i+1] = cubicConvolution(fDeltaX, fDeltaX2, fDeltaX3, fReal1, fReal2, fReal3, fReal4);\n"
@@ -1037,7 +1038,7 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
         "afImag[i+1] = cubicConvolution(fDeltaX, fDeltaX2, fDeltaX3, fImag1, fImag2, fImag3, fImag4);\n"
 "#endif\n"
     "}\n"
-    
+
     // Compute and save final pixel
     "setPixel(dstReal, dstImag, dstDensity, nDstValid, fDstNoDataReal, bandNum,\n"
              "cubicConvolution(fDeltaY, fDeltaY2, fDeltaY3, afDens[0], afDens[1], afDens[2], afDens[3]),\n"
@@ -1061,7 +1062,7 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
         "return 0.0f;\n"
     "if ( fX == 0.0f )\n"
         "return 1.0f;\n"
-    
+
     "float fPIX = PI * fX;\n"
     "return ( sin(fPIX) / fPIX ) * ( sin(fPIX / fR) * fR / fPIX );\n"
 "}\n"
@@ -1074,7 +1075,7 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
     "float xp1 = x + 1.0f;\n"
     "float xm1 = x - 1.0f;\n"
     "float xp2c = xp2 * xp2 * xp2;\n"
-    
+
     "return (((xp2 > 0.0f)?((xp1 > 0.0f)?((x > 0.0f)?((xm1 > 0.0f)?\n"
                                                      "-4.0f * xm1*xm1*xm1:0.0f) +\n"
                                          "6.0f * x*x*x:0.0f) +\n"
@@ -1099,15 +1100,15 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
                      "const int bandNum)\n"
 "{\n"
     "float2  fSrc = getSrcCoords(srcCoords);\n"
-    
+
     "if (!isValid(fUnifiedSrcDensity, nUnifiedSrcValid, fSrc))\n"
         "return;\n"
-    
+
     "int     iSrcX = floor( fSrc.x - 0.5f );\n"
     "int     iSrcY = floor( fSrc.y - 0.5f );\n"
     "float   fDeltaX = fSrc.x - 0.5f - (float)iSrcX;\n"
     "float   fDeltaY = fSrc.y - 0.5f - (float)iSrcY;\n"
-    
+
     "vecf  fAccumulatorReal = 0.0f, fAccumulatorImag = 0.0f;\n"
     "vecf  fAccumulatorDensity = 0.0f;\n"
     "float fAccumulatorWeight = 0.0f;\n"
@@ -1118,11 +1119,11 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
     "{\n"
         "float   fWeight1;\n"
         "int2 iSrc = (int2)(0, iSrcY + j);\n"
-        
+
         // Skip sampling over edge of image
         "if ( iSrc.y < 0 || iSrc.y >= iSrcHeight )\n"
             "continue;\n"
-    
+
         // Select the resampling algorithm
         "if ( doCubicSpline )\n"
             // Calculate the Y weight
@@ -1133,14 +1134,14 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
             "fWeight1 = ( fYScale < 1.0f ) ?\n"
                 "lanczosSinc(j * fYScale, fYFilter) * fYScale :\n"
                 "lanczosSinc(j - fDeltaY, fYFilter);\n"
-        
+
         // Iterate over pixels in row
         "for ( i = nFiltInitX; i <= nXRadius; ++i )\n"
         "{\n"
             "float fWeight2;\n"
             "vecf fDensity = 0.0f, fReal, fImag;\n"
             "iSrc.x = iSrcX + i;\n"
-            
+
             // Skip sampling at edge of image
             // Skip sampling when invalid pixel
             "if ( iSrc.x < 0 || iSrc.x >= iSrcWidth || \n"
@@ -1148,7 +1149,7 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
                             "nUnifiedSrcValid, useBandSrcValid, nBandSrcValid,\n"
                             "iSrc, bandNum, &fDensity, &fReal, &fImag) )\n"
                 "continue;\n"
-    
+
             // Choose among possible algorithms
             "if ( doCubicSpline )\n"
                 // Calculate & save the X weight
@@ -1160,7 +1161,7 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
                 "fWeight2 = fWeight1 * ((fXScale < 1.0f ) ?\n"
                     "lanczosSinc(i * fXScale, fXFilter) * fXScale :\n"
                     "lanczosSinc(i - fDeltaX, fXFilter));\n"
-            
+
             // Accumulate!
             "fAccumulatorReal += fReal * fWeight2;\n"
             "fAccumulatorImag += fImag * fWeight2;\n"
@@ -1187,7 +1188,7 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
                  "fAccumulatorDensity, fAccumulatorReal, fAccumulatorImag);\n"
     "}\n"
 "}\n";
-    
+
     //Defines based on image format
     switch (warper->imageFormat) {
         case CL_FLOAT:
@@ -1216,27 +1217,27 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
             outType = "ushort";
             break;
     }
-    
+
     //Use vector format?
     if (useVec) {
         dUseVec = "-D USE_VEC";
         dVecf = "float4";
     }
-    
+
     //Assemble the kernel from parts. The compiler is unable to handle multiple
     //kernels in one string with more than a few __constant modifiers each.
     if (warper->resampAlg == OCL_Bilinear)
-        sprintf(progBuf, "%s\n%s", kernGenFuncs, kernBilinear);
+        snprintf(progBuf, PROGBUF_SIZE, "%s\n%s", kernGenFuncs, kernBilinear);
     else if (warper->resampAlg == OCL_Cubic)
-        sprintf(progBuf, "%s\n%s", kernGenFuncs, kernCubic);
+        snprintf(progBuf, PROGBUF_SIZE, "%s\n%s", kernGenFuncs, kernCubic);
     else
-        sprintf(progBuf, "%s\n%s", kernGenFuncs, kernResampler);
-    
+        snprintf(progBuf, PROGBUF_SIZE, "%s\n%s", kernGenFuncs, kernResampler);
+
     //Actually make the program from assembled source
     program = clCreateProgramWithSource(warper->context, 1, (const char**)&progBuf,
                                         NULL, &err);
     handleErrGoto(err, error_final);
-    
+
     //Assemble the compiler arg string for speed. All invariants should be defined here.
     sprintf(buffer, "-cl-fast-relaxed-math -Werror -D FALSE=0 -D TRUE=1 "
             "%s"
@@ -1260,7 +1261,7 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
             warper->nBandSrcValidCL != NULL, warper->coordMult);
 
     (*clErr) = err = clBuildProgram(program, 1, &(warper->dev), buffer, NULL, NULL);
-    
+
     //Detailed debugging info
     if (err != CL_SUCCESS)
     {
@@ -1268,7 +1269,7 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
         err = clGetProgramBuildInfo(program, warper->dev, CL_PROGRAM_BUILD_LOG,
                                     128000*sizeof(char), buffer, NULL);
         handleErrGoto(err, error_free_program);
-        
+
         CPLError(CE_Failure, CPLE_AppDefined, "Error: Failed to build program executable!\nBuild Log:\n%s", buffer);
 
         err = clGetProgramBuildInfo(program, warper->dev, CL_PROGRAM_BUILD_STATUS,
@@ -1287,13 +1288,13 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
         CPLDebug("OpenCL", "Build Status: %s\nProgram Source:\n%s", pszStatus, progBuf);
         goto error_free_program;
     }
-    
+
     kernel = clCreateKernel(program, "resamp", &err);
     handleErrGoto(err, error_free_program);
-    
+
     err = clReleaseProgram(program);
     handleErrGoto(err, error_final);
-    
+
     CPLFree(buffer);
     CPLFree(progBuf);
     return kernel;
@@ -1312,14 +1313,14 @@ error_final:
  working memory should be a pinned, linear, array of floats. This allows us to
  allocate and copy all data in one step. The pointer to the device memory is
  saved and set as the appropriate argument number.
- 
+
  Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
  */
 cl_int set_coord_data (struct oclWarper *warper, cl_mem *xy)
 {
     cl_int err = CL_SUCCESS;
     cl_image_format imgFmt;
-    
+
     //Copy coord data to the device
     imgFmt.image_channel_order = warper->xyChOrder;
     imgFmt.image_channel_data_type = CL_FLOAT;
@@ -1330,10 +1331,10 @@ cl_int set_coord_data (struct oclWarper *warper, cl_mem *xy)
                             (size_t) sizeof(float) * warper->xyChSize * warper->xyWidth,
                             warper->xyWork, &err);
     handleErr(err);
-    
+
     //Free the source memory, now that it's copied we don't need it
     freeCLMem(warper->xyWorkCL, warper->xyWork);
-    
+
     //Set up argument
     if (warper->kern1 != NULL) {
         handleErr(err = clSetKernelArg(warper->kern1, 0, sizeof(cl_mem), xy));
@@ -1341,7 +1342,7 @@ cl_int set_coord_data (struct oclWarper *warper, cl_mem *xy)
     if (warper->kern4 != NULL) {
         handleErr(err = clSetKernelArg(warper->kern4, 0, sizeof(cl_mem), xy));
     }
-    
+
     return CL_SUCCESS;
 }
 
@@ -1353,7 +1354,7 @@ cl_int set_coord_data (struct oclWarper *warper, cl_mem *xy)
  from the working memory to the device memory. After that, we check if we are
  using the per-band validity mask, and set that as appropriate. At the end, the
  CL mem is passed as the kernel arguments.
- 
+
  Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
  */
 cl_int set_unified_data(struct oclWarper *warper,
@@ -1366,7 +1367,7 @@ cl_int set_unified_data(struct oclWarper *warper,
     int useValid = warper->nBandSrcValidCL != NULL;
     //32 bits in the mask
     int validSz = sizeof(int) * ((31 + sz) >> 5);
-    
+
     //Copy unifiedSrcDensity if it exists
     if (unifiedSrcDensity == NULL) {
         //Alloc dummy device RAM
@@ -1379,7 +1380,7 @@ cl_int set_unified_data(struct oclWarper *warper,
                                                 sizeof(float) * sz, unifiedSrcDensity, &err);
         handleErr(err);
     }
-    
+
     //Copy unifiedSrcValid if it exists
     if (unifiedSrcValid == NULL) {
         //Alloc dummy device RAM
@@ -1392,7 +1393,7 @@ cl_int set_unified_data(struct oclWarper *warper,
                                               validSz, unifiedSrcValid, &err);
         handleErr(err);
     }
-    
+
     // Set the band validity usage
     if(useValid) {
         (*useBandSrcValidCL) = clCreateBuffer(warper->context,
@@ -1405,7 +1406,7 @@ cl_int set_unified_data(struct oclWarper *warper,
         (*useBandSrcValidCL) = clCreateBuffer(warper->context, CL_MEM_READ_ONLY, 1, NULL, &err);
         handleErr(err);
     }
-    
+
     //Do a more thorough check for validity
     if (useValid) {
         int i;
@@ -1414,7 +1415,7 @@ cl_int set_unified_data(struct oclWarper *warper,
             if (warper->useBandSrcValid[i])
                 useValid = TRUE;
     }
-    
+
     //And the validity mask if needed
     if (useValid) {
         (*nBandSrcValidCL) = clCreateBuffer(warper->context,
@@ -1441,7 +1442,7 @@ cl_int set_unified_data(struct oclWarper *warper,
         handleErr(err = clSetKernelArg(warper->kern4, 5, sizeof(cl_mem), useBandSrcValidCL));
         handleErr(err = clSetKernelArg(warper->kern4, 6, sizeof(cl_mem), nBandSrcValidCL));
     }
-    
+
     return CL_SUCCESS;
 }
 
@@ -1450,7 +1451,7 @@ cl_int set_unified_data(struct oclWarper *warper,
  of course. Then, if applicable, we set the additional image channel. Once this
  data is copied to the device, it can be freed on the host, so that is done
  here. Finally the appropriate kernel arguments are set.
- 
+
  Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
  */
 cl_int set_src_rast_data (struct oclWarper *warper, int iNum, size_t sz,
@@ -1459,7 +1460,7 @@ cl_int set_src_rast_data (struct oclWarper *warper, int iNum, size_t sz,
     cl_image_format imgFmt;
     cl_int err = CL_SUCCESS;
     int useImagWork = warper->imagWork.v != NULL && warper->imagWork.v[iNum] != NULL;
-    
+
     //Set up image vars
     imgFmt.image_channel_order = chOrder;
     imgFmt.image_channel_data_type = warper->imageFormat;
@@ -1470,7 +1471,7 @@ cl_int set_src_rast_data (struct oclWarper *warper, int iNum, size_t sz,
                                  (size_t) warper->srcWidth, (size_t) warper->srcHeight,
                                  sz * warper->srcWidth, warper->realWork.v[iNum], &err);
     handleErr(err);
-    
+
     //And the source image parts if needed
     if (useImagWork) {
         (*srcImag) = clCreateImage2D(warper->context,
@@ -1493,7 +1494,7 @@ cl_int set_src_rast_data (struct oclWarper *warper, int iNum, size_t sz,
     if (warper->imagWork.v != NULL) {
         freeCLMem(warper->imagWorkCL[iNum], warper->imagWork.v[iNum]);
     }
-    
+
     //Set up per-band arguments
     if (warper->kern1 != NULL) {
         handleErr(err = clSetKernelArg(warper->kern1, 1, sizeof(cl_mem), srcReal));
@@ -1503,7 +1504,7 @@ cl_int set_src_rast_data (struct oclWarper *warper, int iNum, size_t sz,
         handleErr(err = clSetKernelArg(warper->kern4, 1, sizeof(cl_mem), srcReal));
         handleErr(err = clSetKernelArg(warper->kern4, 2, sizeof(cl_mem), srcImag));
     }
-    
+
     return CL_SUCCESS;
 }
 
@@ -1512,7 +1513,7 @@ cl_int set_src_rast_data (struct oclWarper *warper, int iNum, size_t sz,
  is copied to the device because some blending is done there. First the real
  data is allocated and copied, then the imag data is allocated and copied if
  needed. They are then set as the appropriate arguments to the kernel.
- 
+
  Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
  */
 cl_int set_dst_rast_data(struct oclWarper *warper, int iImg, size_t sz,
@@ -1520,12 +1521,12 @@ cl_int set_dst_rast_data(struct oclWarper *warper, int iImg, size_t sz,
 {
     cl_int err = CL_SUCCESS;
     sz *= warper->dstWidth * warper->dstHeight;
-    
+
     //Copy the dst real data
     (*dstReal) = clCreateBuffer(warper->context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR,
                                 sz, warper->dstRealWork.v[iImg], &err);
     handleErr(err);
-    
+
     //Copy the dst imag data if exists
     if (warper->dstImagWork.v != NULL && warper->dstImagWork.v[iImg] != NULL) {
         (*dstImag) = clCreateBuffer(warper->context,
@@ -1536,7 +1537,7 @@ cl_int set_dst_rast_data(struct oclWarper *warper, int iImg, size_t sz,
         (*dstImag) = clCreateBuffer(warper->context, CL_MEM_READ_WRITE, 1, NULL, &err);
         handleErr(err);
     }
-    
+
     //Set up per-band arguments
     if (warper->kern1 != NULL) {
         handleErr(err = clSetKernelArg(warper->kern1, 7, sizeof(cl_mem), dstReal));
@@ -1546,14 +1547,14 @@ cl_int set_dst_rast_data(struct oclWarper *warper, int iImg, size_t sz,
         handleErr(err = clSetKernelArg(warper->kern4, 7, sizeof(cl_mem), dstReal));
         handleErr(err = clSetKernelArg(warper->kern4, 8, sizeof(cl_mem), dstImag));
     }
-    
+
     return CL_SUCCESS;
 }
 
 /*
  Read the final raster data back from the graphics card to working memory. This
  copies both the real memory and the imag memory if appropriate.
- 
+
  Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
  */
 cl_int get_dst_rast_data(struct oclWarper *warper, int iImg, size_t wordSz,
@@ -1561,22 +1562,22 @@ cl_int get_dst_rast_data(struct oclWarper *warper, int iImg, size_t wordSz,
 {
     cl_int err = CL_SUCCESS;
     size_t sz = warper->dstWidth * warper->dstHeight * wordSz;
-    
+
     //Copy from dev into working memory
     handleErr(err = clEnqueueReadBuffer(warper->queue, dstReal,
                                         CL_FALSE, 0, sz, warper->dstRealWork.v[iImg],
                                         0, NULL, NULL));
-    
+
     //If we are expecting the imag channel, then copy it back also
     if (warper->dstImagWork.v != NULL && warper->dstImagWork.v[iImg] != NULL) {
         handleErr(err = clEnqueueReadBuffer(warper->queue, dstImag,
                                             CL_FALSE, 0, sz, warper->dstImagWork.v[iImg],
                                             0, NULL, NULL));
     }
-    
+
     //The copy requests were non-blocking, so we'll need to make sure they finish.
     handleErr(err = clFinish(warper->queue));
-    
+
     return CL_SUCCESS;
 }
 
@@ -1585,7 +1586,7 @@ cl_int get_dst_rast_data(struct oclWarper *warper, int iImg, size_t wordSz,
  to blend the final output image with the existing buffer. This handles the
  unified structures that apply to all bands. After the buffers are created and
  copied, they are set as kernel arguments.
- 
+
  Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
  */
 cl_int set_dst_data(struct oclWarper *warper,
@@ -1594,7 +1595,7 @@ cl_int set_dst_data(struct oclWarper *warper,
 {
     cl_int err = CL_SUCCESS;
     size_t sz = warper->dstWidth * warper->dstHeight;
-    
+
     //Copy the no-data value(s)
     if (dstNoDataReal == NULL) {
         (*dstNoDataRealCL) = clCreateBuffer(warper->context, CL_MEM_READ_ONLY, 1, NULL, &err);
@@ -1605,7 +1606,7 @@ cl_int set_dst_data(struct oclWarper *warper,
                                          sizeof(float) * warper->numBands, dstNoDataReal, &err);
         handleErr(err);
     }
-    
+
     //Copy unifiedSrcDensity if it exists
     if (dstDensity == NULL) {
         (*dstDensityCL) = clCreateBuffer(warper->context, CL_MEM_READ_ONLY, 1, NULL, &err);
@@ -1616,7 +1617,7 @@ cl_int set_dst_data(struct oclWarper *warper,
                                          sizeof(float) * sz, dstDensity, &err);
         handleErr(err);
     }
-    
+
     //Copy unifiedSrcValid if it exists
     if (dstValid == NULL) {
         (*dstValidCL) = clCreateBuffer(warper->context, CL_MEM_READ_ONLY, 1, NULL, &err);
@@ -1627,7 +1628,7 @@ cl_int set_dst_data(struct oclWarper *warper,
                                        sizeof(int) * ((31 + sz) >> 5), dstValid, &err);
         handleErr(err);
     }
-    
+
     //Set up arguments
     if (warper->kern1 != NULL) {
         handleErr(err = clSetKernelArg(warper->kern1,  9, sizeof(cl_mem), dstNoDataRealCL));
@@ -1639,7 +1640,7 @@ cl_int set_dst_data(struct oclWarper *warper,
         handleErr(err = clSetKernelArg(warper->kern4, 10, sizeof(cl_mem), dstDensityCL));
         handleErr(err = clSetKernelArg(warper->kern4, 11, sizeof(cl_mem), dstValidCL));
     }
-    
+
     return CL_SUCCESS;
 }
 
@@ -1647,7 +1648,7 @@ cl_int set_dst_data(struct oclWarper *warper,
  Go ahead and execute the kernel. This handles some housekeeping stuff like the
  run dimensions. When running in debug mode, it times the kernel call and prints
  the execution time.
- 
+
  Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
  */
 cl_int execute_kern(struct oclWarper *warper, cl_kernel kern, size_t loc_size)
@@ -1661,7 +1662,7 @@ cl_int execute_kern(struct oclWarper *warper, cl_kernel kern, size_t loc_size)
     size_t end_time;
     char *vecTxt = "";
 #endif
-    
+
     // Use a likely X-dimension which is a power of 2
     if (loc_size >= 512)
         group_size[0] = 32;
@@ -1671,33 +1672,33 @@ cl_int execute_kern(struct oclWarper *warper, cl_kernel kern, size_t loc_size)
         group_size[0] = 8;
     else
         group_size[0] = 1;
-    
+
     if (group_size[0] > loc_size)
         group_size[1] = group_size[0]/loc_size;
     else
         group_size[1] = 1;
-    
+
     //Round up num_runs to find the dim of the block of pixels we'll be processing
     if(warper->dstWidth % group_size[0])
         ceil_runs[0] = warper->dstWidth + group_size[0] - warper->dstWidth % group_size[0];
     else
         ceil_runs[0] = warper->dstWidth;
-    
+
     if(warper->dstHeight % group_size[1])
         ceil_runs[1] = warper->dstHeight + group_size[1] - warper->dstHeight % group_size[1];
     else
         ceil_runs[1] = warper->dstHeight;
-    
+
 #ifdef DEBUG_OPENCL
     handleErr(err = clSetCommandQueueProperty(warper->queue, CL_QUEUE_PROFILING_ENABLE, CL_TRUE, NULL));
 #endif
-    
-    // Run the calculation by enqueuing it and forcing the 
+
+    // Run the calculation by enqueuing it and forcing the
     // command queue to complete the task
-    handleErr(err = clEnqueueNDRangeKernel(warper->queue, kern, 2, NULL, 
+    handleErr(err = clEnqueueNDRangeKernel(warper->queue, kern, 2, NULL,
                                            ceil_runs, group_size, 0, NULL, &ev));
     handleErr(err = clFinish(warper->queue));
-    
+
 #ifdef DEBUG_OPENCL
     handleErr(err = clGetEventProfilingInfo(ev, CL_PROFILING_COMMAND_START,
                                             sizeof(size_t), &start_time, NULL));
@@ -1708,7 +1709,7 @@ cl_int execute_kern(struct oclWarper *warper, cl_kernel kern, size_t loc_size)
     handleErr(err = clReleaseEvent(ev));
     if (kern == warper->kern4)
         vecTxt = "(vec)";
-    
+
     CPLDebug("OpenCL", "Kernel Time: %6s %10lu", vecTxt, (long int)((end_time-start_time)/100000));
 #endif
     return CL_SUCCESS;
@@ -1718,7 +1719,7 @@ cl_int execute_kern(struct oclWarper *warper, cl_kernel kern, size_t loc_size)
  Copy data from a raw source to the warper's working memory. If the imag
  channel is expected, then the data will be de-interlaced into component blocks
  of memory.
- 
+
  Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
  */
 cl_int set_img_data(struct oclWarper *warper, void *srcImgData,
@@ -1731,7 +1732,7 @@ cl_int set_img_data(struct oclWarper *warper, void *srcImgData,
     unsigned int imgNum = bandNum;
     void *dstReal = NULL;
     void *dstImag = NULL;
-    
+
     // Handle vector if needed
     if (warper->useVec && bandNum < warper->numBands - warper->numBands % 4) {
         imgChSize = warper->imgChSize4;
@@ -1740,20 +1741,20 @@ cl_int set_img_data(struct oclWarper *warper, void *srcImgData,
     } else if(warper->useVec) {
         imgNum = bandNum / 4 + bandNum % 4;
     }
-    
+
     // Set the images as needed
     dstReal = dstRealImgs[imgNum];
     if(dstImagImgs == NULL)
         dstImag = NULL;
     else
         dstImag = dstImagImgs[imgNum];
-    
+
     // Set stuff for dst imgs
     if (!isSrc) {
         vecOff *= height * width;
         imgChSize = 1;
     }
-    
+
     // Copy values as needed
     if (warper->imagWorkCL == NULL && !(warper->useVec && isSrc)) {
         //Set memory size & location depending on the data type
@@ -1906,7 +1907,7 @@ cl_int set_img_data(struct oclWarper *warper, void *srcImgData,
             }
         }
     }
-    
+
     return CL_SUCCESS;
 }
 
@@ -1916,7 +1917,7 @@ cl_int set_img_data(struct oclWarper *warper, void *srcImgData,
  device, perhaps the user can choose it later? This would also choose the
  appropriate OpenCL image format (R, RG, RGBA, or multiples thereof). Space
  for metadata can be allocated as required, though.
- 
+
  Supported image formats are:
  CL_FLOAT, CL_SNORM_INT8, CL_UNORM_INT8, CL_SNORM_INT16, CL_UNORM_INT16
  32-bit int formats won't keep precision when converted to floats internally
@@ -1939,13 +1940,13 @@ struct oclWarper* GDALWarpKernelOpenCL_createEnv(int srcWidth, int srcHeight,
     cl_device_id device;
     cl_bool bool_flag;
     OCLVendor eCLVendor = VENDOR_OTHER;
-    
-    // Do we have a suitable OpenCL device? 
+
+    // Do we have a suitable OpenCL device?
     device = get_device(&eCLVendor);
     if( device == NULL )
         return NULL;
-        
-    err = clGetDeviceInfo(device, CL_DEVICE_IMAGE_SUPPORT, 
+
+    err = clGetDeviceInfo(device, CL_DEVICE_IMAGE_SUPPORT,
                           sizeof(cl_bool), &bool_flag, &sz);
     if( err != CL_SUCCESS || !bool_flag )
     {
@@ -1957,13 +1958,13 @@ struct oclWarper* GDALWarpKernelOpenCL_createEnv(int srcWidth, int srcHeight,
     warper = (struct oclWarper *)CPLCalloc(1, sizeof(struct oclWarper));
 
     warper->eCLVendor = eCLVendor;
-    
+
     //Init passed vars
     warper->srcWidth = srcWidth;
     warper->srcHeight = srcHeight;
     warper->dstWidth = dstWidth;
     warper->dstHeight = dstHeight;
-    
+
     warper->coordMult = coordMult;
     warper->numBands = numBands;
     warper->imageFormat = imageFormat;
@@ -1973,7 +1974,7 @@ struct oclWarper* GDALWarpKernelOpenCL_createEnv(int srcWidth, int srcHeight,
     warper->useUnifiedSrcValid = FALSE;
     warper->useDstDensity = FALSE;
     warper->useDstValid = FALSE;
-    
+
     warper->imagWorkCL = NULL;
     warper->dstImagWorkCL = NULL;
     warper->useBandSrcValidCL = NULL;
@@ -1986,12 +1987,12 @@ struct oclWarper* GDALWarpKernelOpenCL_createEnv(int srcWidth, int srcHeight,
     warper->kern4 = NULL;
 
     warper->dev = device;
-    
+
     warper->context = clCreateContext(0, 1, &(warper->dev), NULL, NULL, &err);
     handleErrGoto(err, error_label);
     warper->queue = clCreateCommandQueue(warper->context, warper->dev, 0, &err);
     handleErrGoto(err, error_label);
-    
+
     //Ensure that we hand handle imagery of these dimensions
     err = clGetDeviceInfo(warper->dev, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof(size_t), &maxWidth, &sz);
     handleErrGoto(err, error_label);
@@ -2001,7 +2002,7 @@ struct oclWarper* GDALWarpKernelOpenCL_createEnv(int srcWidth, int srcHeight,
         err = CL_INVALID_IMAGE_SIZE;
         handleErrGoto(err, error_label);
     }
-    
+
     // Split bands into sets of four when possible
     // Cubic runs slower as vector, so don't use it (probably register pressure)
     // Feel free to do more testing and come up with more precise case statements
@@ -2012,49 +2013,49 @@ struct oclWarper* GDALWarpKernelOpenCL_createEnv(int srcWidth, int srcHeight,
         warper->numImages = numBands/4 + numBands % 4;
         warper->useVec = TRUE;
     }
-    
+
     //Make the pointer space for the real images
     warper->realWorkCL = (cl_mem *)CPLCalloc(sizeof(cl_mem), warper->numImages);
     warper->dstRealWorkCL = (cl_mem *)CPLCalloc(sizeof(cl_mem), warper->numImages);
-    
+
     //Make space for the per-channel Imag data (if exists)
     if (useImag) {
         warper->imagWorkCL = (cl_mem *)CPLCalloc(sizeof(cl_mem), warper->numImages);
         warper->dstImagWorkCL = (cl_mem *)CPLCalloc(sizeof(cl_mem), warper->numImages);
     }
-    
+
     //Make space for the per-band BandSrcValid data (if exists)
     if (useBandSrcValid) {
         //32 bits in the mask
         size_t sz = warper->numBands * ((31 + warper->srcWidth * warper->srcHeight) >> 5);
-        
+
         //Allocate some space for the validity of the validity mask
         err = alloc_pinned_mem(warper, 0, warper->numBands*sizeof(char),
                                (void **)&(warper->useBandSrcValid),
                                &(warper->useBandSrcValidCL));
         handleErrGoto(err, error_label);
-        
+
         for (i = 0; i < warper->numBands; ++i)
             warper->useBandSrcValid[i] = FALSE;
-        
-        //Allocate one array for all the band validity masks
-        //Remember that the masks don't use much memeory (they're bitwise)
+
+        // Allocate one array for all the band validity masks.
+        // Remember that the masks don't use much memory (they're bitwise).
         err = alloc_pinned_mem(warper, 0, sz * sizeof(int),
                                (void **)&(warper->nBandSrcValid),
                                &(warper->nBandSrcValidCL));
         handleErrGoto(err, error_label);
     }
-    
-    //Make space for the per-band 
+
+    //Make space for the per-band
     if (dfDstNoDataReal != NULL) {
         alloc_pinned_mem(warper, 0, warper->numBands,
                          (void **)&(warper->fDstNoDataReal), &(warper->fDstNoDataRealCL));
-        
+
         //Copy over values
         for (i = 0; i < warper->numBands; ++i)
             warper->fDstNoDataReal[i] = dfDstNoDataReal[i];
     }
-    
+
     //Alloc working host image memory
     //We'll be copying into these buffers soon
     switch (imageFormat) {
@@ -2075,30 +2076,30 @@ struct oclWarper* GDALWarpKernelOpenCL_createEnv(int srcWidth, int srcHeight,
         break;
     }
     handleErrGoto(err, error_label);
-    
-    //Find a good & compable image channel order for the Lat/Long arr
+
+    // Find a good & compatible image channel order for the Lat/Long array.
     err = set_supported_formats(warper, 2,
                                 &(warper->xyChOrder), &(warper->xyChSize),
                                 CL_FLOAT);
     handleErrGoto(err, error_label);
-    
+
     //Set coordinate image dimensions
     warper->xyWidth  = ceil(((float)warper->dstWidth  + (float)warper->coordMult-1)/(float)warper->coordMult);
     warper->xyHeight = ceil(((float)warper->dstHeight + (float)warper->coordMult-1)/(float)warper->coordMult);
-    
+
     //Alloc coord memory
     sz = sizeof(float) * warper->xyChSize * warper->xyWidth * warper->xyHeight;
     err = alloc_pinned_mem(warper, 0, sz, (void **)&(warper->xyWork),
                            &(warper->xyWorkCL));
     handleErrGoto(err, error_label);
-    
+
     //Ensure everything is finished allocating, copying, & mapping
     err = clFinish(warper->queue);
     handleErrGoto(err, error_label);
-    
+
     (*clErr) = CL_SUCCESS;
     return warper;
-    
+
 error_label:
     GDALWarpKernelOpenCL_deleteEnv(warper);
     return NULL;
@@ -2106,7 +2107,7 @@ error_label:
 
 /*
  Copy the validity mask for an image band to the warper.
- 
+
  Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
  */
 cl_int GDALWarpKernelOpenCL_setSrcValid(struct oclWarper *warper,
@@ -2114,29 +2115,29 @@ cl_int GDALWarpKernelOpenCL_setSrcValid(struct oclWarper *warper,
 {
     //32 bits in the mask
     int stride = (31 + warper->srcWidth * warper->srcHeight) >> 5;
-    
+
     //Copy bandSrcValid
     assert(warper->nBandSrcValid != NULL);
     memcpy(&(warper->nBandSrcValid[bandNum*stride]), bandSrcValid, sizeof(int) * stride);
     warper->useBandSrcValid[bandNum] = TRUE;
-    
+
     return CL_SUCCESS;
 }
 
 /*
  Sets the source image real & imag into the host memory so that it is
  permuted (ex. RGBA) for better graphics card access.
- 
+
  Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
  */
 cl_int GDALWarpKernelOpenCL_setSrcImg(struct oclWarper *warper, void *imgData,
                                       int bandNum)
 {
     void **imagWorkPtr = NULL;
-    
+
     if (warper->imagWorkCL != NULL)
         imagWorkPtr = warper->imagWork.v;
-    
+
     return set_img_data(warper, imgData, warper->srcWidth, warper->srcHeight,
                         TRUE, bandNum, warper->realWork.v, imagWorkPtr);
 }
@@ -2144,17 +2145,17 @@ cl_int GDALWarpKernelOpenCL_setSrcImg(struct oclWarper *warper, void *imgData,
 /*
  Sets the destination image real & imag into the host memory so that it is
  permuted (ex. RGBA) for better graphics card access.
- 
+
  Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
  */
 cl_int GDALWarpKernelOpenCL_setDstImg(struct oclWarper *warper, void *imgData,
                                       int bandNum)
 {
     void **dstImagWorkPtr = NULL;
-    
+
     if (warper->dstImagWorkCL != NULL)
         dstImagWorkPtr = warper->dstImagWork.v;
-    
+
     return set_img_data(warper, imgData, warper->dstWidth, warper->dstHeight,
                         FALSE, bandNum, warper->dstRealWork.v, dstImagWorkPtr);
 }
@@ -2165,15 +2166,15 @@ cl_int GDALWarpKernelOpenCL_setDstImg(struct oclWarper *warper, void *imgData,
  the coordinates as ready to be used in OpenCL image memory: interleaved and
  minus the offset. By using image memory, we can use a smaller texture for
  coordinates and use OpenCL's built-in interpolation to save memory.
- 
+
  What it does: generates a smaller matrix of X/Y coordinate transformation
  values from an original matrix. When bilinearly sampled in the GPU hardware,
  the generated values are as close as possible to the original matrix.
- 
- Complication: matricies have arbitrary dimensions and the sub-sampling factor
- is an arbitrary integer greater than zero. Getting the edge cases right is 
+
+ Complication: matrices have arbitrary dimensions and the sub-sampling factor
+ is an arbitrary integer greater than zero. Getting the edge cases right is
  difficult.
- 
+
  Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
  */
 cl_int GDALWarpKernelOpenCL_setCoordRow(struct oclWarper *warper,
@@ -2190,30 +2191,30 @@ cl_int GDALWarpKernelOpenCL_setCoordRow(struct oclWarper *warper,
     float *xyPtr, *xyPrevPtr = NULL;
     int lastRow = rowNum == height - 1;
     double dstHeightMod = 1.0, dstWidthMod = 1.0;
-    
+
     //Return if we're at an off row
     if(!lastRow && rowNum % coordMult != 0)
         return CL_SUCCESS;
-    
+
     //Standard row, adjusted for the skipped rows
     xyPtr = &(warper->xyWork[xyWidth * xyChSize * rowNum / coordMult]);
-    
+
     //Find our row
     if(lastRow){
         //Setup for the final row
         xyPtr     = &(warper->xyWork[xyWidth * xyChSize * (warper->xyHeight - 1)]);
         xyPrevPtr = &(warper->xyWork[xyWidth * xyChSize * (warper->xyHeight - 2)]);
-        
+
         if((height-1) % coordMult)
             dstHeightMod = (double)coordMult / (double)((height-1) % coordMult);
     }
-    
+
     //Copy selected coordinates
     for (i = 0; i < width; i += coordMult) {
         if (success[i]) {
             xyPtr[0] = rowSrcX[i] - srcXOff;
             xyPtr[1] = rowSrcY[i] - srcYOff;
-            
+
             if(lastRow) {
                 //Adjust bottom row so interpolator returns correct value
                 xyPtr[0] = dstHeightMod * (xyPtr[0] - xyPrevPtr[0]) + xyPrevPtr[0];
@@ -2223,11 +2224,11 @@ cl_int GDALWarpKernelOpenCL_setCoordRow(struct oclWarper *warper,
             xyPtr[0] = -99.0f;
             xyPtr[1] = -99.0f;
         }
-        
+
         xyPtr += xyChSize;
         xyPrevPtr += xyChSize;
     }
-    
+
     //Copy remaining coordinate
     if((width-1) % coordMult){
         dstWidthMod = (double)coordMult / (double)((width-1) % coordMult);
@@ -2237,24 +2238,24 @@ cl_int GDALWarpKernelOpenCL_setCoordRow(struct oclWarper *warper,
         xyPtr -= xyChSize*2;
         xyPrevPtr -= xyChSize*2;
     }
-    
+
     if(lastRow) {
         double origX = rowSrcX[width-1] - srcXOff;
         double origY = rowSrcY[width-1] - srcYOff;
         double a = 1.0, b = 1.0;
-        
+
         // Calculate the needed x/y values using an equation from the OpenCL Spec
         // section 8.2, solving for Ti1j1
         if((width -1) % coordMult)
             a = ((width -1) % coordMult)/(double)coordMult;
-        
+
         if((height-1) % coordMult)
             b = ((height-1) % coordMult)/(double)coordMult;
-        
+
         xyPtr[xyChSize  ] = (((1.0 - a) * (1.0 - b) * xyPrevPtr[0]
                               + a * (1.0 - b) * xyPrevPtr[xyChSize]
                               + (1.0 - a) * b * xyPtr[0]) - origX)/(-a * b);
-        
+
         xyPtr[xyChSize+1] = (((1.0 - a) * (1.0 - b) * xyPrevPtr[1]
                               + a * (1.0 - b) * xyPrevPtr[xyChSize+1]
                               + (1.0 - a) * b * xyPtr[1]) - origY)/(-a * b);
@@ -2263,7 +2264,7 @@ cl_int GDALWarpKernelOpenCL_setCoordRow(struct oclWarper *warper,
         xyPtr[xyChSize  ] = dstWidthMod * (rowSrcX[width-1] - srcXOff - xyPtr[0]) + xyPtr[0];
         xyPtr[xyChSize+1] = dstWidthMod * (rowSrcY[width-1] - srcYOff - xyPtr[1]) + xyPtr[1];
     }
-    
+
     return CL_SUCCESS;
 }
 
@@ -2273,7 +2274,7 @@ cl_int GDALWarpKernelOpenCL_setCoordRow(struct oclWarper *warper,
  back from the device RAM for each band. Also check to make sure that
  setRow*() was called the appropriate number of times to init all image
  data.
- 
+
  Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
  */
 cl_int GDALWarpKernelOpenCL_runResamp(struct oclWarper *warper,
@@ -2294,7 +2295,7 @@ cl_int GDALWarpKernelOpenCL_runResamp(struct oclWarper *warper,
 	size_t groupSize, wordSize;
     cl_kernel kern = NULL;
     cl_channel_order chOrder;
-    
+
     warper->useUnifiedSrcDensity = unifiedSrcDensity != NULL;
     warper->useUnifiedSrcValid = unifiedSrcValid != NULL;
 
@@ -2316,7 +2317,7 @@ cl_int GDALWarpKernelOpenCL_runResamp(struct oclWarper *warper,
             wordSize = sizeof(unsigned short);
             break;
     }
-    
+
     //Compile the kernel; the invariants are being compiled into the code
     if (!warper->useVec || warper->numBands % 4) {
         warper->kern1 = get_kernel(warper, FALSE,
@@ -2330,19 +2331,19 @@ cl_int GDALWarpKernelOpenCL_runResamp(struct oclWarper *warper,
                                    nXRadius, nYRadius, nFiltInitX, nFiltInitY, &err);
         handleErr(err);
     }
-    
+
     //Copy coord data to the device
     handleErr(err = set_coord_data(warper, &xy));
-    
+
     //Copy unified density & valid data
     handleErr(err = set_unified_data(warper, &unifiedSrcDensityCL, &unifiedSrcValidCL,
                                      unifiedSrcDensity, unifiedSrcValid,
                                      &useBandSrcValidCL, &nBandSrcValidCL));
-    
+
     //Copy output density & valid data
     handleErr(set_dst_data(warper, &dstDensityCL, &dstValidCL, &dstNoDataRealCL,
                            dstDensity, dstValid, warper->fDstNoDataReal));
-    
+
     //What's the recommended group size?
     if (warper->useVec) {
         // Start with the vector kernel
@@ -2361,14 +2362,14 @@ cl_int GDALWarpKernelOpenCL_runResamp(struct oclWarper *warper,
         chSize = warper->imgChSize1;
         chOrder = warper->imgChOrder1;
     }
-    
+
     //Loop over each image
     for (i = 0; i < warper->numImages; ++i)
     {
         cl_mem srcImag, srcReal;
         cl_mem dstReal, dstImag;
         int bandNum = nextBandNum;
-        
+
         //Switch kernels if needed
         if (warper->useVec && nextBandNum < warper->numBands - warper->numBands % 4) {
             nextBandNum += 4;
@@ -2383,40 +2384,40 @@ cl_int GDALWarpKernelOpenCL_runResamp(struct oclWarper *warper,
             }
             ++nextBandNum;
         }
-        
+
         //Create & copy the source image
         handleErr(err = set_src_rast_data(warper, i, chSize*wordSize, chOrder,
                                           &srcReal, &srcImag));
-        
+
         //Create & copy the output image
         if (kern == warper->kern1) {
             handleErr(err = set_dst_rast_data(warper, i, wordSize, &dstReal, &dstImag));
         } else {
             handleErr(err = set_dst_rast_data(warper, i, wordSize*4, &dstReal, &dstImag));
         }
-        
+
         //Set the bandNum
         handleErr(err = clSetKernelArg(kern, 12, sizeof(int), &bandNum));
-        
+
         //Run the kernel
         handleErr(err = execute_kern(warper, kern, groupSize));
-        
+
         //Free loop CL mem
         handleErr(err = clReleaseMemObject(srcReal));
         handleErr(err = clReleaseMemObject(srcImag));
-        
+
         //Copy the back output results
         if (kern == warper->kern1) {
             handleErr(err = get_dst_rast_data(warper, i, wordSize, dstReal, dstImag));
         } else {
             handleErr(err = get_dst_rast_data(warper, i, wordSize*4, dstReal, dstImag));
         }
-            
+
         //Free remaining CL mem
         handleErr(err = clReleaseMemObject(dstReal));
         handleErr(err = clReleaseMemObject(dstImag));
     }
-    
+
     //Free remaining CL mem
     handleErr(err = clReleaseMemObject(xy));
     handleErr(err = clReleaseMemObject(unifiedSrcDensityCL));
@@ -2436,7 +2437,7 @@ cl_int GDALWarpKernelOpenCL_runResamp(struct oclWarper *warper,
  channel is in use, it will receive a pointer. Otherwise it'll be set to NULL.
  These are pointers to floating point data, so the caller will need to
  manipulate the output as appropriate before saving the data.
- 
+
  Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
  */
 cl_int GDALWarpKernelOpenCL_getRow(struct oclWarper *warper,
@@ -2445,14 +2446,14 @@ cl_int GDALWarpKernelOpenCL_getRow(struct oclWarper *warper,
 {
     int memOff = rowNum * warper->dstWidth;
     int imgNum = bandNum;
-    
+
     if (warper->useVec && bandNum < warper->numBands - warper->numBands % 4) {
         memOff += warper->dstWidth * warper->dstHeight * (bandNum % 4);
         imgNum = bandNum / 4;
     } else if(warper->useVec) {
         imgNum = bandNum / 4 + bandNum % 4;
     }
-    
+
     //Return pointers into the warper's data
     switch (warper->imageFormat) {
         case CL_FLOAT:
@@ -2471,7 +2472,7 @@ cl_int GDALWarpKernelOpenCL_getRow(struct oclWarper *warper,
             (*rowReal) = &(warper->dstRealWork.us[imgNum][memOff]);
             break;
     }
-    
+
     if (warper->dstImagWorkCL == NULL) {
         (*rowImag) = NULL;
     } else {
@@ -2493,21 +2494,21 @@ cl_int GDALWarpKernelOpenCL_getRow(struct oclWarper *warper,
                 break;
         }
     }
-    
+
     return CL_SUCCESS;
 }
 
 /*
  Free the OpenCL warper environment. It should check everything for NULL, so
  be sure to mark free()ed pointers as NULL or it'll be double free()ed.
- 
+
  Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
  */
 cl_int GDALWarpKernelOpenCL_deleteEnv(struct oclWarper *warper)
 {
     int i;
 	cl_int err = CL_SUCCESS;
-    
+
     for (i = 0; i < warper->numImages; ++i) {
         // Run free!!
         void* dummy = NULL;
@@ -2519,7 +2520,7 @@ cl_int GDALWarpKernelOpenCL_deleteEnv(struct oclWarper *warper)
             freeCLMem(warper->dstRealWorkCL[i], warper->dstRealWork.v[i]);
         else
             freeCLMem(warper->dstRealWorkCL[i], dummy);
-        
+
         //(As applicable)
         if(warper->imagWorkCL != NULL && warper->imagWork.v != NULL && warper->imagWork.v[i] != NULL) {
             freeCLMem(warper->imagWorkCL[i], warper->imagWork.v[i]);
@@ -2528,19 +2529,19 @@ cl_int GDALWarpKernelOpenCL_deleteEnv(struct oclWarper *warper)
             freeCLMem(warper->dstImagWorkCL[i], warper->dstImagWork.v[i]);
         }
     }
-    
+
     //Free cl_mem
     freeCLMem(warper->useBandSrcValidCL, warper->useBandSrcValid);
     freeCLMem(warper->nBandSrcValidCL, warper->nBandSrcValid);
     freeCLMem(warper->xyWorkCL, warper->xyWork);
     freeCLMem(warper->fDstNoDataRealCL, warper->fDstNoDataReal);
-    
+
     //Free pointers to cl_mem*
     if (warper->realWorkCL != NULL)
         CPLFree(warper->realWorkCL);
     if (warper->dstRealWorkCL != NULL)
         CPLFree(warper->dstRealWorkCL);
-    
+
     if (warper->imagWorkCL != NULL)
         CPLFree(warper->imagWorkCL);
     if (warper->dstImagWorkCL != NULL)
@@ -2550,12 +2551,12 @@ cl_int GDALWarpKernelOpenCL_deleteEnv(struct oclWarper *warper)
         CPLFree(warper->realWork.v);
     if (warper->dstRealWork.v != NULL)
         CPLFree(warper->dstRealWork.v);
-    
+
     if (warper->imagWork.v != NULL)
         CPLFree(warper->imagWork.v);
     if (warper->dstImagWork.v != NULL)
         CPLFree(warper->dstImagWork.v);
-    
+
     //Free OpenCL structures
     if (warper->kern1 != NULL)
         clReleaseKernel(warper->kern1);
@@ -2565,11 +2566,10 @@ cl_int GDALWarpKernelOpenCL_deleteEnv(struct oclWarper *warper)
         clReleaseCommandQueue(warper->queue);
     if (warper->context != NULL)
         clReleaseContext(warper->context);
-    
+
     CPLFree(warper);
-    
+
     return CL_SUCCESS;
 }
 
 #endif /* defined(HAVE_OPENCL) */
-
diff --git a/alg/gdalwarpkernel_opencl.h b/alg/gdalwarpkernel_opencl.h
index 54f9625..003b0c1 100644
--- a/alg/gdalwarpkernel_opencl.h
+++ b/alg/gdalwarpkernel_opencl.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalwarpkernel_opencl.h 25068 2012-10-07 14:01:47Z rouault $
+ * $Id: gdalwarpkernel_opencl.h 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  OpenCL Image Reprojector
  * Purpose:  Implementation of the GDALWarpKernel reprojector in OpenCL.
@@ -29,9 +29,9 @@
 
 #if defined(HAVE_OPENCL)
 
-/* The following relates to the profiling calls to 
+/* The following relates to the profiling calls to
    clSetCommandQueueProperty() which are not available by default
-   with some OpenCL implementation (ie. ATI) */
+   with some OpenCL implementation (i.e. ATI) */
 
 #if defined(DEBUG_OPENCL) && DEBUG_OPENCL == 1
 #define CL_USE_DEPRECATED_OPENCL_1_0_APIS
@@ -67,21 +67,21 @@ struct oclWarper {
     cl_device_id dev;
     cl_kernel kern1;
     cl_kernel kern4;
-    
+
     int srcWidth;
     int srcHeight;
     int dstWidth;
     int dstHeight;
-    
+
     int useUnifiedSrcDensity;
     int useUnifiedSrcValid;
     int useDstDensity;
     int useDstValid;
-    
+
     int numBands;
     int numImages;
     OCLResampAlg resampAlg;
-    
+
     cl_channel_type imageFormat;
     cl_mem *realWorkCL;
     union {
@@ -92,7 +92,7 @@ struct oclWarper {
         unsigned short **us;
         float **f;
     } realWork;
-    
+
     cl_mem *imagWorkCL;
     union {
         void **v;
@@ -102,7 +102,7 @@ struct oclWarper {
         unsigned short **us;
         float **f;
     } imagWork;
-    
+
     cl_mem *dstRealWorkCL;
     union {
         void **v;
@@ -112,7 +112,7 @@ struct oclWarper {
         unsigned short **us;
         float **f;
     } dstRealWork;
-    
+
     cl_mem *dstImagWorkCL;
     union {
         void **v;
@@ -122,29 +122,29 @@ struct oclWarper {
         unsigned short **us;
         float **f;
     } dstImagWork;
-    
+
     unsigned int imgChSize1;
     cl_channel_order imgChOrder1;
     unsigned int imgChSize4;
     cl_channel_order imgChOrder4;
 	char    useVec;
-    
+
     cl_mem useBandSrcValidCL;
     char *useBandSrcValid;
-    
+
     cl_mem nBandSrcValidCL;
     float *nBandSrcValid;
-    
+
     cl_mem xyWorkCL;
     float *xyWork;
-    
+
     int xyWidth;
     int xyHeight;
     int coordMult;
-    
+
     unsigned int xyChSize;
     cl_channel_order xyChOrder;
-    
+
     cl_mem fDstNoDataRealCL;
     float *fDstNoDataReal;
 
@@ -195,4 +195,3 @@ cl_int GDALWarpKernelOpenCL_deleteEnv(struct oclWarper *warper);
 #endif
 
 #endif /* defined(HAVE_OPENCL) */
-
diff --git a/alg/gdalwarpoperation.cpp b/alg/gdalwarpoperation.cpp
index 3d8a9bd..921b95e 100644
--- a/alg/gdalwarpoperation.cpp
+++ b/alg/gdalwarpoperation.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalwarpoperation.cpp 31177 2015-10-28 12:43:31Z rouault $
+ * $Id: gdalwarpoperation.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  High Performance Image Reprojector
  * Purpose:  Implementation of the GDALWarpOperation class.
@@ -33,13 +33,13 @@
 #include "cpl_multiproc.h"
 #include "ogr_api.h"
 
-CPL_CVSID("$Id: gdalwarpoperation.cpp 31177 2015-10-28 12:43:31Z rouault $");
+CPL_CVSID("$Id: gdalwarpoperation.cpp 33808 2016-03-29 21:15:28Z goatbar $");
 
-struct _GDALWarpChunk { 
-    int dx, dy, dsx, dsy; 
-    int sx, sy, ssx, ssy; 
+struct _GDALWarpChunk {
+    int dx, dy, dsx, dsy;
+    int sx, sy, ssx, ssy;
     int sExtraSx, sExtraSy;
-}; 
+};
 
 /************************************************************************/
 /* ==================================================================== */
@@ -50,7 +50,7 @@ struct _GDALWarpChunk {
 /**
  * \class GDALWarpOperation "gdalwarper.h"
  *
- * High level image warping class. 
+ * High level image warping class.
 
 <h2>Warper Design</h2>
 
@@ -60,32 +60,32 @@ The overall GDAL high performance image warper is split into a few components.
 via GDALTransformerFunc() implementations such as the one returned by
 GDALCreateGenImgProjTransformer().  The transformers are ultimately responsible
 for translating pixel/line locations on the destination image to pixel/line
-locations on the source image. 
+locations on the source image.
 
  - In order to handle images too large to hold in RAM, the warper needs to
 segment large images.  This is the responsibility of the GDALWarpOperation
-class.  The GDALWarpOperation::ChunkAndWarpImage() invokes 
+class.  The GDALWarpOperation::ChunkAndWarpImage() invokes
 GDALWarpOperation::WarpRegion() on chunks of output and input image that
-are small enough to hold in the amount of memory allowed by the application. 
-This process is described in greater detail in the <b>Image Chunking</b> 
-section. 
+are small enough to hold in the amount of memory allowed by the application.
+This process is described in greater detail in the <b>Image Chunking</b>
+section.
 
- - The GDALWarpOperation::WarpRegion() function creates and loads an output 
-image buffer, and then calls WarpRegionToBuffer(). 
+ - The GDALWarpOperation::WarpRegion() function creates and loads an output
+image buffer, and then calls WarpRegionToBuffer().
 
- - GDALWarpOperation::WarpRegionToBuffer() is responsible for loading the 
+ - GDALWarpOperation::WarpRegionToBuffer() is responsible for loading the
 source imagery corresponding to a particular output region, and generating
 masks and density masks from the source and destination imagery using
 the generator functions found in the GDALWarpOptions structure.  Binds this
-all into an instance of GDALWarpKernel on which the 
-GDALWarpKernel::PerformWarp() method is called. 
+all into an instance of GDALWarpKernel on which the
+GDALWarpKernel::PerformWarp() method is called.
 
  - GDALWarpKernel does the actual image warping, but is given an input image
 and an output image to operate on.  The GDALWarpKernel does no IO, and in
-fact knows nothing about GDAL.  It invokes the transformation function to 
+fact knows nothing about GDAL.  It invokes the transformation function to
 get sample locations, builds output values based on the resampling algorithm
 in use.  It also takes any validity and density masks into account during
-this operation.  
+this operation.
 
 <h3>Chunk Size Selection</h3>
 
@@ -93,26 +93,25 @@ The GDALWarpOptions ChunkAndWarpImage() method is responsible for invoking
 the WarpRegion() method on appropriate sized output chunks such that the
 memory required for the output image buffer, input image buffer and any
 required density and validity buffers is less than or equal to the application
-defined maximum memory available for use.  
+defined maximum memory available for use.
 
-It checks the memory requrired by walking the edges of the output region, 
-transforming the locations back into source pixel/line coordinates and 
+It checks the memory required by walking the edges of the output region,
+transforming the locations back into source pixel/line coordinates and
 establishing a bounding rectangle of source imagery that would be required
 for the output area.  This is actually accomplished by the private
-GDALWarpOperation::ComputeSourceWindow() method. 
+GDALWarpOperation::ComputeSourceWindow() method.
 
 Then memory requirements are used by totaling the memory required for all
 output bands, input bands, validity masks and density masks.  If this is
 greater than the GDALWarpOptions::dfWarpMemoryLimit then the destination
-region is divided in two (splitting the longest dimension), and 
-ChunkAndWarpImage() recursively invoked on each destination subregion. 
+region is divided in two (splitting the longest dimension), and
+ChunkAndWarpImage() recursively invoked on each destination subregion.
 
 <h3>Validity and Density Masks Generation</h3>
 
-Fill in ways in which the validity and density masks may be generated here. 
+Fill in ways in which the validity and density masks may be generated here.
 Note that detailed semantics of the masks should be found in
-GDALWarpKernel. 
-
+GDALWarpKernel.
 */
 
 /************************************************************************/
@@ -133,6 +132,7 @@ GDALWarpOperation::GDALWarpOperation()
 
     bReportTimings = FALSE;
     nLastTimeReported = 0;
+    psThreadData = NULL;
 }
 
 /************************************************************************/
@@ -151,6 +151,8 @@ GDALWarpOperation::~GDALWarpOperation()
     }
 
     WipeChunkList();
+    if( psThreadData )
+        GWKThreadsEnd(psThreadData);
 }
 
 /************************************************************************/
@@ -186,7 +188,7 @@ int GDALWarpOperation::ValidateOptions()
 {
     if( psOptions == NULL )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg, 
+        CPLError( CE_Failure, CPLE_IllegalArg,
                   "GDALWarpOptions.Validate()\n"
                   "  no options currently initialized." );
         return FALSE;
@@ -194,27 +196,27 @@ int GDALWarpOperation::ValidateOptions()
 
     if( psOptions->dfWarpMemoryLimit < 100000.0 )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg, 
+        CPLError( CE_Failure, CPLE_IllegalArg,
                   "GDALWarpOptions.Validate()\n"
                   "  dfWarpMemoryLimit=%g is unreasonably small.",
                   psOptions->dfWarpMemoryLimit );
         return FALSE;
     }
 
-    if( psOptions->eResampleAlg != GRA_NearestNeighbour 
+    if( psOptions->eResampleAlg != GRA_NearestNeighbour
         && psOptions->eResampleAlg != GRA_Bilinear
         && psOptions->eResampleAlg != GRA_Cubic
         && psOptions->eResampleAlg != GRA_CubicSpline
         && psOptions->eResampleAlg != GRA_Lanczos
         && psOptions->eResampleAlg != GRA_Average
         && psOptions->eResampleAlg != GRA_Mode
-        && psOptions->eResampleAlg != GRA_Max 
+        && psOptions->eResampleAlg != GRA_Max
         && psOptions->eResampleAlg != GRA_Min
         && psOptions->eResampleAlg != GRA_Med
         && psOptions->eResampleAlg != GRA_Q1
         && psOptions->eResampleAlg != GRA_Q3)
     {
-        CPLError( CE_Failure, CPLE_IllegalArg, 
+        CPLError( CE_Failure, CPLE_IllegalArg,
                   "GDALWarpOptions.Validate()\n"
                   "  eResampleArg=%d is not a supported value.",
                   psOptions->eResampleAlg );
@@ -222,9 +224,9 @@ int GDALWarpOperation::ValidateOptions()
     }
 
     if( (int) psOptions->eWorkingDataType < 1
-        && (int) psOptions->eWorkingDataType >= GDT_TypeCount )
+        || (int) psOptions->eWorkingDataType >= GDT_TypeCount )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg, 
+        CPLError( CE_Failure, CPLE_IllegalArg,
                   "GDALWarpOptions.Validate()\n"
                   "  eWorkingDataType=%d is not a supported value.",
                   psOptions->eWorkingDataType );
@@ -233,7 +235,7 @@ int GDALWarpOperation::ValidateOptions()
 
     if( psOptions->hSrcDS == NULL )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg, 
+        CPLError( CE_Failure, CPLE_IllegalArg,
                   "GDALWarpOptions.Validate()\n"
                   "  hSrcDS is not set." );
         return FALSE;
@@ -241,7 +243,7 @@ int GDALWarpOperation::ValidateOptions()
 
     if( psOptions->nBandCount == 0 )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg, 
+        CPLError( CE_Failure, CPLE_IllegalArg,
                   "GDALWarpOptions.Validate()\n"
                   "  nBandCount=0, no bands configured!" );
         return FALSE;
@@ -249,7 +251,7 @@ int GDALWarpOperation::ValidateOptions()
 
     if( psOptions->panSrcBands == NULL )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg, 
+        CPLError( CE_Failure, CPLE_IllegalArg,
                   "GDALWarpOptions.Validate()\n"
                   "  panSrcBands is NULL." );
         return FALSE;
@@ -257,7 +259,7 @@ int GDALWarpOperation::ValidateOptions()
 
     if( psOptions->hDstDS != NULL && psOptions->panDstBands == NULL )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg, 
+        CPLError( CE_Failure, CPLE_IllegalArg,
                   "GDALWarpOptions.Validate()\n"
                   "  panDstBands is NULL." );
         return FALSE;
@@ -265,8 +267,8 @@ int GDALWarpOperation::ValidateOptions()
 
     for( int iBand = 0; iBand < psOptions->nBandCount; iBand++ )
     {
-        if( psOptions->panSrcBands[iBand] < 1 
-            || psOptions->panSrcBands[iBand] 
+        if( psOptions->panSrcBands[iBand] < 1
+            || psOptions->panSrcBands[iBand]
             > GDALGetRasterCount( psOptions->hSrcDS ) )
         {
             CPLError( CE_Failure, CPLE_IllegalArg,
@@ -275,7 +277,7 @@ int GDALWarpOperation::ValidateOptions()
             return FALSE;
         }
         if( psOptions->hDstDS != NULL
-            && (psOptions->panDstBands[iBand] < 1 
+            && (psOptions->panDstBands[iBand] < 1
                 || psOptions->panDstBands[iBand]
                 > GDALGetRasterCount( psOptions->hDstDS ) ) )
         {
@@ -286,7 +288,7 @@ int GDALWarpOperation::ValidateOptions()
         }
 
         if( psOptions->hDstDS != NULL
-            && GDALGetRasterAccess( 
+            && GDALGetRasterAccess(
                 GDALGetRasterBand(psOptions->hDstDS,
                                   psOptions->panDstBands[iBand]))
             == GA_ReadOnly )
@@ -300,7 +302,7 @@ int GDALWarpOperation::ValidateOptions()
 
     if( psOptions->nBandCount == 0 )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg, 
+        CPLError( CE_Failure, CPLE_IllegalArg,
                   "GDALWarpOptions.Validate()\n"
                   "  nBandCount=0, no bands configured!" );
         return FALSE;
@@ -309,7 +311,7 @@ int GDALWarpOperation::ValidateOptions()
     if( psOptions->padfSrcNoDataReal != NULL
         && psOptions->padfSrcNoDataImag == NULL )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg, 
+        CPLError( CE_Failure, CPLE_IllegalArg,
                   "GDALWarpOptions.Validate()\n"
                   "  padfSrcNoDataReal set, but padfSrcNoDataImag not set." );
         return FALSE;
@@ -317,7 +319,7 @@ int GDALWarpOperation::ValidateOptions()
 
     if( psOptions->pfnProgress == NULL )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg, 
+        CPLError( CE_Failure, CPLE_IllegalArg,
                   "GDALWarpOptions.Validate()\n"
                   "  pfnProgress is NULL." );
         return FALSE;
@@ -325,19 +327,19 @@ int GDALWarpOperation::ValidateOptions()
 
     if( psOptions->pfnTransformer == NULL )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg, 
+        CPLError( CE_Failure, CPLE_IllegalArg,
                   "GDALWarpOptions.Validate()\n"
                   "  pfnTransformer is NULL." );
         return FALSE;
     }
 
-    if( CSLFetchNameValue( psOptions->papszWarpOptions, 
+    if( CSLFetchNameValue( psOptions->papszWarpOptions,
                            "SAMPLE_STEPS" ) != NULL )
     {
-        if( atoi(CSLFetchNameValue( psOptions->papszWarpOptions, 
+        if( atoi(CSLFetchNameValue( psOptions->papszWarpOptions,
                                     "SAMPLE_STEPS" )) < 2 )
         {
-            CPLError( CE_Failure, CPLE_IllegalArg, 
+            CPLError( CE_Failure, CPLE_IllegalArg,
                       "GDALWarpOptions.Validate()\n"
                       "  SAMPLE_STEPS warp option has illegal value." );
             return FALSE;
@@ -368,19 +370,19 @@ int GDALWarpOperation::ValidateOptions()
         }
     }
 
-    if( psOptions->nSrcAlphaBand > 0 
+    if( psOptions->nSrcAlphaBand > 0
         && psOptions->pfnSrcDensityMaskFunc != NULL )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg, 
+        CPLError( CE_Failure, CPLE_IllegalArg,
                "GDALWarpOptions.Validate()\n"
                "  pfnSrcDensityMaskFunc provided as well as a SrcAlphaBand." );
         return FALSE;
     }
 
-    if( psOptions->nDstAlphaBand > 0 
+    if( psOptions->nDstAlphaBand > 0
         && psOptions->pfnDstDensityMaskFunc != NULL )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg, 
+        CPLError( CE_Failure, CPLE_IllegalArg,
                "GDALWarpOptions.Validate()\n"
                "  pfnDstDensityMaskFunc provided as well as a DstAlphaBand." );
         return FALSE;
@@ -404,10 +406,10 @@ int GDALWarpOperation::ValidateOptions()
  * Defaulting operations include:
  *  - If the nBandCount is 0, it will be set to the number of bands in the
  *    source image (which must match the output image) and the panSrcBands
- *    and panDstBands will be populated. 
+ *    and panDstBands will be populated.
  *
  * @param psNewOptions input set of warp options.  These are copied and may
- * be destroyed after this call by the application. 
+ * be destroyed after this call by the application.
  *
  * @return CE_None on success or CE_Failure if an error occurs.
  */
@@ -430,19 +432,19 @@ CPLErr GDALWarpOperation::Initialize( const GDALWarpOptions *psNewOptions )
 /* -------------------------------------------------------------------- */
 /*      Default band mapping if missing.                                */
 /* -------------------------------------------------------------------- */
-    if( psOptions->nBandCount == 0 
+    if( psOptions->nBandCount == 0
         && psOptions->hSrcDS != NULL
-        && psOptions->hDstDS != NULL 
-        && GDALGetRasterCount( psOptions->hSrcDS ) 
+        && psOptions->hDstDS != NULL
+        && GDALGetRasterCount( psOptions->hSrcDS )
         == GDALGetRasterCount( psOptions->hDstDS ) )
     {
         int  i;
 
         psOptions->nBandCount = GDALGetRasterCount( psOptions->hSrcDS );
 
-        psOptions->panSrcBands = (int *) 
+        psOptions->panSrcBands = (int *)
             CPLMalloc(sizeof(int) * psOptions->nBandCount );
-        psOptions->panDstBands = (int *) 
+        psOptions->panDstBands = (int *)
             CPLMalloc(sizeof(int) * psOptions->nBandCount );
 
         for( i = 0; i < psOptions->nBandCount; i++ )
@@ -460,9 +462,9 @@ CPLErr GDALWarpOperation::Initialize( const GDALWarpOptions *psNewOptions )
 /*      of band" with the output type we may need to use the higher     */
 /*      resolution input type to ensure we can identify nodata values.  */
 /* -------------------------------------------------------------------- */
-    if( psOptions->eWorkingDataType == GDT_Unknown 
-        && psOptions->hSrcDS != NULL 
-        && psOptions->hDstDS != NULL 
+    if( psOptions->eWorkingDataType == GDT_Unknown
+        && psOptions->hSrcDS != NULL
+        && psOptions->hDstDS != NULL
         && psOptions->nBandCount >= 1 )
     {
         int iBand;
@@ -470,17 +472,17 @@ CPLErr GDALWarpOperation::Initialize( const GDALWarpOptions *psNewOptions )
 
         for( iBand = 0; iBand < psOptions->nBandCount; iBand++ )
         {
-            GDALRasterBandH hDstBand = GDALGetRasterBand( 
+            GDALRasterBandH hDstBand = GDALGetRasterBand(
                 psOptions->hDstDS, psOptions->panDstBands[iBand] );
-            GDALRasterBandH hSrcBand = GDALGetRasterBand( 
+            GDALRasterBandH hSrcBand = GDALGetRasterBand(
                 psOptions->hSrcDS, psOptions->panSrcBands[iBand] );
-                                                  
+
             if( hDstBand != NULL )
-                psOptions->eWorkingDataType = 
-                    GDALDataTypeUnion( psOptions->eWorkingDataType, 
+                psOptions->eWorkingDataType =
+                    GDALDataTypeUnion( psOptions->eWorkingDataType,
                                        GDALGetRasterDataType( hDstBand ) );
-            
-            if( hSrcBand != NULL 
+
+            if( hSrcBand != NULL
                 && psOptions->padfSrcNoDataReal != NULL )
             {
                 int bMergeSource = FALSE;
@@ -489,18 +491,18 @@ CPLErr GDALWarpOperation::Initialize( const GDALWarpOptions *psNewOptions )
                     && psOptions->padfSrcNoDataImag[iBand] != 0.0
                     && !GDALDataTypeIsComplex( psOptions->eWorkingDataType ) )
                     bMergeSource = TRUE;
-                else if( psOptions->padfSrcNoDataReal[iBand] < 0.0 
+                else if( psOptions->padfSrcNoDataReal[iBand] < 0.0
                          && (psOptions->eWorkingDataType == GDT_Byte
                              || psOptions->eWorkingDataType == GDT_UInt16
                              || psOptions->eWorkingDataType == GDT_UInt32) )
                     bMergeSource = TRUE;
-                else if( psOptions->padfSrcNoDataReal[iBand] < -32768.0 
+                else if( psOptions->padfSrcNoDataReal[iBand] < -32768.0
                          && psOptions->eWorkingDataType == GDT_Int16 )
                     bMergeSource = TRUE;
-                else if( psOptions->padfSrcNoDataReal[iBand] < -2147483648.0 
+                else if( psOptions->padfSrcNoDataReal[iBand] < -2147483648.0
                          && psOptions->eWorkingDataType == GDT_Int32 )
                     bMergeSource = TRUE;
-                else if( psOptions->padfSrcNoDataReal[iBand] > 256 
+                else if( psOptions->padfSrcNoDataReal[iBand] > 256
                          && psOptions->eWorkingDataType == GDT_Byte )
                     bMergeSource = TRUE;
                 else if( psOptions->padfSrcNoDataReal[iBand] > 32767
@@ -509,7 +511,7 @@ CPLErr GDALWarpOperation::Initialize( const GDALWarpOptions *psNewOptions )
                 else if( psOptions->padfSrcNoDataReal[iBand] > 65535
                          && psOptions->eWorkingDataType == GDT_UInt16 )
                     bMergeSource = TRUE;
-                else if( psOptions->padfSrcNoDataReal[iBand] > 2147483648.0 
+                else if( psOptions->padfSrcNoDataReal[iBand] > 2147483648.0
                          && psOptions->eWorkingDataType == GDT_Int32 )
                     bMergeSource = TRUE;
                 else if( psOptions->padfSrcNoDataReal[iBand] > 4294967295.0
@@ -517,8 +519,8 @@ CPLErr GDALWarpOperation::Initialize( const GDALWarpOptions *psNewOptions )
                     bMergeSource = TRUE;
 
                 if( bMergeSource )
-                    psOptions->eWorkingDataType = 
-                        GDALDataTypeUnion( psOptions->eWorkingDataType, 
+                    psOptions->eWorkingDataType =
+                        GDALDataTypeUnion( psOptions->eWorkingDataType,
                                            GDALGetRasterDataType( hSrcBand ) );
             }
         }
@@ -539,18 +541,18 @@ CPLErr GDALWarpOperation::Initialize( const GDALWarpOptions *psNewOptions )
 /* -------------------------------------------------------------------- */
 /*      Are we doing timings?                                           */
 /* -------------------------------------------------------------------- */
-    bReportTimings = CSLFetchBoolean( psOptions->papszWarpOptions, 
+    bReportTimings = CSLFetchBoolean( psOptions->papszWarpOptions,
                                       "REPORT_TIMINGS", FALSE );
 
 /* -------------------------------------------------------------------- */
 /*      Support creating cutline from text warpoption.                  */
 /* -------------------------------------------------------------------- */
-    const char *pszCutlineWKT = 
+    const char *pszCutlineWKT =
         CSLFetchNameValue( psOptions->papszWarpOptions, "CUTLINE" );
-        
+
     if( pszCutlineWKT )
     {
-        if( OGR_G_CreateFromWkt( (char **) &pszCutlineWKT, NULL, 
+        if( OGR_G_CreateFromWkt( (char **) &pszCutlineWKT, NULL,
                                  (OGRGeometryH *) &(psOptions->hCutline) )
             != OGRERR_NONE )
         {
@@ -575,6 +577,14 @@ CPLErr GDALWarpOperation::Initialize( const GDALWarpOptions *psNewOptions )
 
     if( eErr != CE_None )
         WipeOptions();
+    else
+    {
+        psThreadData = GWKThreadsCreate(psOptions->papszWarpOptions,
+                                        psOptions->pfnTransformer,
+                                        psOptions->pTransformerArg);
+        if( psThreadData == NULL )
+            eErr = CE_Failure;
+    }
 
     return eErr;
 }
@@ -621,19 +631,19 @@ void GDALDestroyWarpOperation( GDALWarpOperationH hOperation )
 /************************************************************************/
 
 static int OrderWarpChunk(const void* _a, const void *_b)
-{ 
+{
     const GDALWarpChunk* a = (const GDALWarpChunk* )_a;
     const GDALWarpChunk* b = (const GDALWarpChunk* )_b;
     if (a->dy < b->dy)
-        return -1; 
+        return -1;
     else if (a->dy > b->dy)
-        return 1; 
+        return 1;
     else if (a->dx < b->dx)
-        return -1; 
+        return -1;
     else if (a->dx > b->dx)
-        return 1; 
+        return 1;
     else
-        return 0; 
+        return 0;
 }
 
 /**
@@ -641,15 +651,15 @@ static int OrderWarpChunk(const void* _a, const void *_b)
                 int nDstXOff, int nDstYOff,  int nDstXSize, int nDstYSize );
  *
  * This method does a complete warp of the source image to the destination
- * image for the indicated region with the current warp options in effect.  
- * Progress is reported to the installed progress monitor, if any.  
+ * image for the indicated region with the current warp options in effect.
+ * Progress is reported to the installed progress monitor, if any.
  *
- * This function will subdivide the region and recursively call itself 
+ * This function will subdivide the region and recursively call itself
  * until the total memory required to process a region chunk will all fit
- * in the memory pool defined by GDALWarpOptions::dfWarpMemoryLimit.  
+ * in the memory pool defined by GDALWarpOptions::dfWarpMemoryLimit.
  *
  * Once an appropriate region is selected GDALWarpOperation::WarpRegion()
- * is invoked to do the actual work. 
+ * is invoked to do the actual work.
  *
  * @param nDstXOff X offset to window of destination data to be produced.
  * @param nDstYOff Y offset to window of destination data to be produced.
@@ -659,7 +669,7 @@ static int OrderWarpChunk(const void* _a, const void *_b)
  * @return CE_None on success or CE_Failure if an error occurs.
  */
 
-CPLErr GDALWarpOperation::ChunkAndWarpImage( 
+CPLErr GDALWarpOperation::ChunkAndWarpImage(
     int nDstXOff, int nDstYOff,  int nDstXSize, int nDstYSize )
 
 {
@@ -668,9 +678,10 @@ CPLErr GDALWarpOperation::ChunkAndWarpImage(
 /* -------------------------------------------------------------------- */
     WipeChunkList();
     CollectChunkList( nDstXOff, nDstYOff, nDstXSize, nDstYSize );
-    
+
     /* Sort chucks from top to bottom, and for equal y, from left to right */
-    qsort(pasChunkList, nChunkListCount, sizeof(GDALWarpChunk), OrderWarpChunk); 
+    if( pasChunkList )
+        qsort(pasChunkList, nChunkListCount, sizeof(GDALWarpChunk), OrderWarpChunk);
 
 /* -------------------------------------------------------------------- */
 /*      Total up output pixels to process.                              */
@@ -678,7 +689,7 @@ CPLErr GDALWarpOperation::ChunkAndWarpImage(
     int iChunk;
     double dfTotalPixels = 0;
 
-    for( iChunk = 0; iChunk < nChunkListCount; iChunk++ )
+    for( iChunk = 0; pasChunkList != NULL && iChunk < nChunkListCount; iChunk++ )
     {
         GDALWarpChunk *pasThisChunk = pasChunkList + iChunk;
         double dfChunkPixels = pasThisChunk->dsx * (double) pasThisChunk->dsy;
@@ -692,7 +703,7 @@ CPLErr GDALWarpOperation::ChunkAndWarpImage(
 /* -------------------------------------------------------------------- */
     double dfPixelsProcessed=0.0;
 
-    for( iChunk = 0; iChunk < nChunkListCount; iChunk++ )
+    for( iChunk = 0; pasChunkList != NULL && iChunk < nChunkListCount; iChunk++ )
     {
         GDALWarpChunk *pasThisChunk = pasChunkList + iChunk;
         double dfChunkPixels = pasThisChunk->dsx * (double) pasThisChunk->dsy;
@@ -701,9 +712,9 @@ CPLErr GDALWarpOperation::ChunkAndWarpImage(
         double dfProgressBase = dfPixelsProcessed / dfTotalPixels;
         double dfProgressScale = dfChunkPixels / dfTotalPixels;
 
-        eErr = WarpRegion( pasThisChunk->dx, pasThisChunk->dy, 
+        eErr = WarpRegion( pasThisChunk->dx, pasThisChunk->dy,
                            pasThisChunk->dsx, pasThisChunk->dsy,
-                           pasThisChunk->sx, pasThisChunk->sy, 
+                           pasThisChunk->sx, pasThisChunk->sy,
                            pasThisChunk->ssx, pasThisChunk->ssy,
                            pasThisChunk->sExtraSx, pasThisChunk->sExtraSy,
                            dfProgressBase, dfProgressScale);
@@ -753,7 +764,7 @@ typedef struct
     CPLMutex          *hIOMutex;
 
     CPLMutex          *hCondMutex;
-    int                bIOMutexTaken;
+    volatile int       bIOMutexTaken;
     CPLCond           *hCond;
 } ChunkThreadData;
 
@@ -785,9 +796,9 @@ static void ChunkThreadMain( void *pThreadData )
         }
 
         psData->eErr = psData->poOperation->WarpRegion(
-                                    pasChunkInfo->dx, pasChunkInfo->dy, 
+                                    pasChunkInfo->dx, pasChunkInfo->dy,
                                     pasChunkInfo->dsx, pasChunkInfo->dsy,
-                                    pasChunkInfo->sx, pasChunkInfo->sy, 
+                                    pasChunkInfo->sx, pasChunkInfo->sy,
                                     pasChunkInfo->ssx, pasChunkInfo->ssy,
                                     pasChunkInfo->sExtraSx, pasChunkInfo->sExtraSy,
                                     psData->dfProgressBase,
@@ -809,8 +820,8 @@ static void ChunkThreadMain( void *pThreadData )
                 int nDstXOff, int nDstYOff,  int nDstXSize, int nDstYSize );
  *
  * This method does a complete warp of the source image to the destination
- * image for the indicated region with the current warp options in effect.  
- * Progress is reported to the installed progress monitor, if any.  
+ * image for the indicated region with the current warp options in effect.
+ * Progress is reported to the installed progress monitor, if any.
  *
  * Externally this method operates the same as ChunkAndWarpImage(), but
  * internally this method uses multiple threads to interleave input/output
@@ -824,7 +835,7 @@ static void ChunkThreadMain( void *pThreadData )
  * @return CE_None on success or CE_Failure if an error occurs.
  */
 
-CPLErr GDALWarpOperation::ChunkAndWarpMulti( 
+CPLErr GDALWarpOperation::ChunkAndWarpMulti(
     int nDstXOff, int nDstYOff,  int nDstXSize, int nDstYSize )
 
 {
@@ -845,7 +856,8 @@ CPLErr GDALWarpOperation::ChunkAndWarpMulti(
     CollectChunkList( nDstXOff, nDstYOff, nDstXSize, nDstYSize );
 
     /* Sort chucks from top to bottom, and for equal y, from left to right */
-    qsort(pasChunkList, nChunkListCount, sizeof(GDALWarpChunk), OrderWarpChunk); 
+    if( pasChunkList )
+        qsort(pasChunkList, nChunkListCount, sizeof(GDALWarpChunk), OrderWarpChunk);
 
 /* -------------------------------------------------------------------- */
 /*      Process them one at a time, updating the progress               */
@@ -869,7 +881,7 @@ CPLErr GDALWarpOperation::ChunkAndWarpMulti(
 /* -------------------------------------------------------------------- */
 /*      Launch thread for this chunk.                                   */
 /* -------------------------------------------------------------------- */
-        if( iChunk < nChunkListCount )
+        if( pasChunkList != NULL && iChunk < nChunkListCount )
         {
             GDALWarpChunk *pasThisChunk = pasChunkList + iChunk;
             double dfChunkPixels = pasThisChunk->dsx * (double) pasThisChunk->dsy;
@@ -898,7 +910,7 @@ CPLErr GDALWarpOperation::ChunkAndWarpMulti(
                 CPLCreateJoinableThread( ChunkThreadMain, (void*) &asThreadData[iThread] );
             if( asThreadData[iThread].hThreadHandle == NULL )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "CPLCreateJoinableThread() failed in ChunkAndWarpMulti()" );
                 eErr = CE_Failure;
                 break;
@@ -915,14 +927,13 @@ CPLErr GDALWarpOperation::ChunkAndWarpMulti(
             }
         }
 
-        
 /* -------------------------------------------------------------------- */
 /*      Wait for previous chunks thread to complete.                    */
 /* -------------------------------------------------------------------- */
         if( iChunk > 0 )
         {
             iThread = (iChunk-1) % 2;
-            
+
             /* Wait for thread to finish. */
             CPLJoinThread(asThreadData[iThread].hThreadHandle);
             asThreadData[iThread].hThreadHandle = NULL;
@@ -988,7 +999,7 @@ void GDALWarpOperation::WipeChunkList()
 /*                          CollectChunkList()                          */
 /************************************************************************/
 
-CPLErr GDALWarpOperation::CollectChunkList( 
+CPLErr GDALWarpOperation::CollectChunkList(
     int nDstXOff, int nDstYOff,  int nDstXSize, int nDstYSize )
 
 {
@@ -1004,17 +1015,17 @@ CPLErr GDALWarpOperation::CollectChunkList(
     eErr = ComputeSourceWindow( nDstXOff, nDstYOff, nDstXSize, nDstYSize,
                                 &nSrcXOff, &nSrcYOff, &nSrcXSize, &nSrcYSize,
                                 &nSrcXExtraSize, &nSrcYExtraSize, &dfSrcFillRatio );
-    
+
     if( eErr != CE_None )
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
-                  "Unable to compute source region for output window %d,%d,%d,%d, skipping.", 
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Unable to compute source region for output window %d,%d,%d,%d, skipping.",
                   nDstXOff, nDstYOff, nDstXSize, nDstYSize );
         return eErr;
     }
 
 /* -------------------------------------------------------------------- */
-/*      If we are allowed to drop no-source regons, do so now if       */
+/*      If we are allowed to drop no-source regions, do so now if       */
 /*      appropriate.                                                    */
 /* -------------------------------------------------------------------- */
     if( (nSrcXSize == 0 || nSrcYSize == 0)
@@ -1027,8 +1038,8 @@ CPLErr GDALWarpOperation::CollectChunkList(
 /* -------------------------------------------------------------------- */
     int nSrcPixelCostInBits;
 
-    nSrcPixelCostInBits = 
-        GDALGetDataTypeSize( psOptions->eWorkingDataType ) 
+    nSrcPixelCostInBits =
+        GDALGetDataTypeSize( psOptions->eWorkingDataType )
         * psOptions->nBandCount;
 
     if( psOptions->pfnSrcDensityMaskFunc != NULL )
@@ -1044,7 +1055,7 @@ CPLErr GDALWarpOperation::CollectChunkList(
     else if (hSrcBand != NULL && (GDALGetMaskFlags(hSrcBand) & GMF_PER_DATASET))
         nSrcPixelCostInBits += 1; /* UnifiedSrcValid bit mask */
 
-    if( psOptions->papfnSrcPerBandValidityMaskFunc != NULL 
+    if( psOptions->papfnSrcPerBandValidityMaskFunc != NULL
         || psOptions->padfSrcNoDataReal != NULL )
         nSrcPixelCostInBits += psOptions->nBandCount; /* bit/band mask */
 
@@ -1056,8 +1067,8 @@ CPLErr GDALWarpOperation::CollectChunkList(
 /* -------------------------------------------------------------------- */
     int nDstPixelCostInBits;
 
-    nDstPixelCostInBits = 
-        GDALGetDataTypeSize( psOptions->eWorkingDataType ) 
+    nDstPixelCostInBits =
+        GDALGetDataTypeSize( psOptions->eWorkingDataType )
         * psOptions->nBandCount;
 
     if( psOptions->pfnDstDensityMaskFunc != NULL )
@@ -1080,15 +1091,14 @@ CPLErr GDALWarpOperation::CollectChunkList(
     dfTotalMemoryUse =
         (((double) nSrcPixelCostInBits) * nSrcXSize * nSrcYSize
          + ((double) nDstPixelCostInBits) * nDstXSize * nDstYSize) / 8.0;
-         
-        
+
     int nBlockXSize = 1, nBlockYSize = 1;
     if (psOptions->hDstDS)
     {
         GDALGetBlockSize(GDALGetRasterBand(psOptions->hDstDS, 1),
                          &nBlockXSize, &nBlockYSize);
     }
-    
+
     // If size of working buffers need exceed the allow limit, then divide
     // the target area
     // Do it also if the "fill ratio" of the source is too low (#3120), but
@@ -1103,7 +1113,7 @@ CPLErr GDALWarpOperation::CollectChunkList(
          CSLFetchBoolean( psOptions->papszWarpOptions, "SRC_FILL_RATIO_HEURISTICS", TRUE )) )
     {
         CPLErr eErr2 = CE_None;
-        
+
         int bStreamableOutput =
                 CSLFetchBoolean( psOptions->papszWarpOptions, "STREAMABLE_OUTPUT", FALSE );
         int bOptimizeSize = !bStreamableOutput &&
@@ -1121,17 +1131,17 @@ CPLErr GDALWarpOperation::CollectChunkList(
         {
             bHasDivided = TRUE;
             int nChunk1 = nDstXSize / 2;
-            
+
             /* In the optimize size case, try to stick on target block boundaries */
             if ((bOptimizeSize || bStreamableOutput) && nChunk1 > nBlockXSize)
                 nChunk1 = (nChunk1 / nBlockXSize) * nBlockXSize;
-            
+
             int nChunk2 = nDstXSize - nChunk1;
 
-            eErr = CollectChunkList( nDstXOff, nDstYOff, 
+            eErr = CollectChunkList( nDstXOff, nDstYOff,
                                      nChunk1, nDstYSize );
 
-            eErr2 = CollectChunkList( nDstXOff+nChunk1, nDstYOff, 
+            eErr2 = CollectChunkList( nDstXOff+nChunk1, nDstYOff,
                                       nChunk2, nDstYSize );
         }
         else if( !(bStreamableOutput && nDstYSize / 2 < nBlockYSize) )
@@ -1145,10 +1155,10 @@ CPLErr GDALWarpOperation::CollectChunkList(
 
             int nChunk2 = nDstYSize - nChunk1;
 
-            eErr = CollectChunkList( nDstXOff, nDstYOff, 
+            eErr = CollectChunkList( nDstXOff, nDstYOff,
                                      nDstXSize, nChunk1 );
 
-            eErr2 = CollectChunkList( nDstXOff, nDstYOff+nChunk1, 
+            eErr2 = CollectChunkList( nDstXOff, nDstYOff+nChunk1,
                                       nDstXSize, nChunk2 );
         }
 
@@ -1167,7 +1177,7 @@ CPLErr GDALWarpOperation::CollectChunkList(
     if( nChunkListCount == nChunkListMax )
     {
         nChunkListMax = nChunkListMax * 2 + 1;
-        pasChunkList = (GDALWarpChunk *) 
+        pasChunkList = (GDALWarpChunk *)
             CPLRealloc(pasChunkList,sizeof(GDALWarpChunk)*nChunkListMax );
     }
 
@@ -1193,7 +1203,7 @@ CPLErr GDALWarpOperation::CollectChunkList(
 /************************************************************************/
 
 /**
- * \fn CPLErr GDALWarpOperation::WarpRegion(int nDstXOff, int nDstYOff, 
+ * \fn CPLErr GDALWarpOperation::WarpRegion(int nDstXOff, int nDstYOff,
                                             int nDstXSize, int nDstYSize,
                                             int nSrcXOff=0, int nSrcYOff=0,
                                             int nSrcXSize=0, int nSrcYSize=0,
@@ -1201,14 +1211,14 @@ CPLErr GDALWarpOperation::CollectChunkList(
                                             double dfProgressScale = 1);
  *
  * This method requests the indicated region of the output file be generated.
- * 
+ *
  * Note that WarpRegion() will produce the requested area in one low level warp
  * operation without verifying that this does not exceed the stated memory
  * limits for the warp operation.  Applications should take care not to call
- * WarpRegion() on too large a region!  This function 
- * is normally called by ChunkAndWarpImage(), the normal entry point for 
+ * WarpRegion() on too large a region!  This function
+ * is normally called by ChunkAndWarpImage(), the normal entry point for
  * applications.  Use it instead if staying within memory constraints is
- * desired. 
+ * desired.
  *
  * Progress is reported from dfProgressBase to dfProgressBase + dfProgressScale
  * for the indicated region.
@@ -1228,14 +1238,14 @@ CPLErr GDALWarpOperation::CollectChunkList(
  * @return CE_None on success or CE_Failure if an error occurs.
  */
 
-CPLErr GDALWarpOperation::WarpRegion( int nDstXOff, int nDstYOff, 
+CPLErr GDALWarpOperation::WarpRegion( int nDstXOff, int nDstYOff,
                                       int nDstXSize, int nDstYSize,
                                       int nSrcXOff, int nSrcYOff,
                                       int nSrcXSize, int nSrcYSize,
                                       double dfProgressBase,
                                       double dfProgressScale)
 {
-    return WarpRegion(nDstXOff, nDstYOff, 
+    return WarpRegion(nDstXOff, nDstYOff,
                       nDstXSize, nDstYSize,
                       nSrcXOff, nSrcYOff,
                       nSrcXSize, nSrcYSize,
@@ -1243,7 +1253,7 @@ CPLErr GDALWarpOperation::WarpRegion( int nDstXOff, int nDstYOff,
                       dfProgressBase, dfProgressScale);
 }
 
-CPLErr GDALWarpOperation::WarpRegion( int nDstXOff, int nDstYOff, 
+CPLErr GDALWarpOperation::WarpRegion( int nDstXOff, int nDstYOff,
                                       int nDstXSize, int nDstYSize,
                                       int nSrcXOff, int nSrcYOff,
                                       int nSrcXSize, int nSrcYSize,
@@ -1261,7 +1271,7 @@ CPLErr GDALWarpOperation::WarpRegion( int nDstXOff, int nDstYOff,
 /*      Allocate the output buffer.                                     */
 /* -------------------------------------------------------------------- */
     void *pDstBuffer;
-    int  nWordSize = GDALGetDataTypeSize(psOptions->eWorkingDataType)/8;
+    const int nWordSize = GDALGetDataTypeSizeBytes(psOptions->eWorkingDataType);
     int  nBandSize = nWordSize * nDstXSize * nDstYSize;
 
     if (nDstXSize > INT_MAX / nDstYSize ||
@@ -1273,12 +1283,9 @@ CPLErr GDALWarpOperation::WarpRegion( int nDstXOff, int nDstYOff,
         return CE_Failure;
     }
 
-    pDstBuffer = VSIMalloc( nBandSize * psOptions->nBandCount );
+    pDstBuffer = VSI_MALLOC_VERBOSE( nBandSize * psOptions->nBandCount );
     if( pDstBuffer == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory,
-                  "Out of memory allocating %d byte destination buffer.",
-                  nBandSize * psOptions->nBandCount );
         return CE_Failure;
     }
 
@@ -1296,10 +1303,10 @@ CPLErr GDALWarpOperation::WarpRegion( int nDstXOff, int nDstYOff,
 
     if( pszInitDest != NULL && !EQUAL(pszInitDest, "") )
     {
-        char **papszInitValues = 
+        char **papszInitValues =
             CSLTokenizeStringComplex( pszInitDest, ",", FALSE, FALSE );
         int nInitCount = CSLCount(papszInitValues);
-                                                           
+
         for( iBand = 0; iBand < psOptions->nBandCount; iBand++ )
         {
             double adfInitRealImag[2];
@@ -1319,10 +1326,10 @@ CPLErr GDALWarpOperation::WarpRegion( int nDstXOff, int nDstYOff,
             }
 
             pBandData = ((GByte *) pDstBuffer) + iBand * nBandSize;
-            
+
             if( psOptions->eWorkingDataType == GDT_Byte )
-                memset( pBandData, 
-                        MAX(0,MIN(255,(int)adfInitRealImag[0])), 
+                memset( pBandData,
+                        MAX(0,MIN(255,(int)adfInitRealImag[0])),
                         nBandSize);
             else if( !CPLIsNan(adfInitRealImag[0]) && adfInitRealImag[0] == 0.0 &&
                      !CPLIsNan(adfInitRealImag[1]) && adfInitRealImag[1] == 0.0 )
@@ -1331,13 +1338,13 @@ CPLErr GDALWarpOperation::WarpRegion( int nDstXOff, int nDstYOff,
             }
             else if( !CPLIsNan(adfInitRealImag[1]) && adfInitRealImag[1] == 0.0 )
             {
-                GDALCopyWords( &adfInitRealImag, GDT_Float64, 0, 
+                GDALCopyWords( &adfInitRealImag, GDT_Float64, 0,
                                pBandData,psOptions->eWorkingDataType,nWordSize,
                                nDstXSize * nDstYSize );
             }
             else
             {
-                GDALCopyWords( &adfInitRealImag, GDT_CFloat64, 0, 
+                GDALCopyWords( &adfInitRealImag, GDT_CFloat64, 0,
                                pBandData,psOptions->eWorkingDataType,nWordSize,
                                nDstXSize * nDstYSize );
             }
@@ -1352,11 +1359,11 @@ CPLErr GDALWarpOperation::WarpRegion( int nDstXOff, int nDstYOff,
 /* -------------------------------------------------------------------- */
     if( pszInitDest == NULL )
     {
-        eErr = GDALDatasetRasterIO( psOptions->hDstDS, GF_Read, 
+        eErr = GDALDatasetRasterIO( psOptions->hDstDS, GF_Read,
                                     nDstXOff, nDstYOff, nDstXSize, nDstYSize,
-                                    pDstBuffer, nDstXSize, nDstYSize, 
-                                    psOptions->eWorkingDataType, 
-                                    psOptions->nBandCount, 
+                                    pDstBuffer, nDstXSize, nDstYSize,
+                                    psOptions->eWorkingDataType,
+                                    psOptions->nBandCount,
                                     psOptions->panDstBands,
                                     0, 0, 0 );
 
@@ -1372,8 +1379,8 @@ CPLErr GDALWarpOperation::WarpRegion( int nDstXOff, int nDstYOff,
 /* -------------------------------------------------------------------- */
 /*      Perform the warp.                                               */
 /* -------------------------------------------------------------------- */
-    eErr = WarpRegionToBuffer( nDstXOff, nDstYOff, nDstXSize, nDstYSize, 
-                               pDstBuffer, psOptions->eWorkingDataType, 
+    eErr = WarpRegionToBuffer( nDstXOff, nDstYOff, nDstXSize, nDstYSize,
+                               pDstBuffer, psOptions->eWorkingDataType,
                                nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize,
                                nSrcXExtraSize, nSrcYExtraSize,
                                dfProgressBase, dfProgressScale);
@@ -1383,16 +1390,16 @@ CPLErr GDALWarpOperation::WarpRegion( int nDstXOff, int nDstYOff,
 /* -------------------------------------------------------------------- */
     if( eErr == CE_None )
     {
-        eErr = GDALDatasetRasterIO( psOptions->hDstDS, GF_Write, 
+        eErr = GDALDatasetRasterIO( psOptions->hDstDS, GF_Write,
                                     nDstXOff, nDstYOff, nDstXSize, nDstYSize,
-                                    pDstBuffer, nDstXSize, nDstYSize, 
-                                    psOptions->eWorkingDataType, 
-                                    psOptions->nBandCount, 
+                                    pDstBuffer, nDstXSize, nDstYSize,
+                                    psOptions->eWorkingDataType,
+                                    psOptions->nBandCount,
                                     psOptions->panDstBands,
                                     0, 0, 0 );
         if( eErr == CE_None &&
             CSLFetchBoolean( psOptions->papszWarpOptions, "WRITE_FLUSH",
-                             FALSE ) )					
+                             FALSE ) )
         {
             CPLErr eOldErr = CPLGetLastErrorType();
             CPLString osLastErrMsg = CPLGetLastErrorMsg();
@@ -1408,7 +1415,7 @@ CPLErr GDALWarpOperation::WarpRegion( int nDstXOff, int nDstYOff,
 /*      Cleanup and return.                                             */
 /* -------------------------------------------------------------------- */
     VSIFree( pDstBuffer );
-    
+
     return eErr;
 }
 
@@ -1439,24 +1446,24 @@ CPLErr GDALWarpRegion( GDALWarpOperationH hOperation,
 /************************************************************************/
 
 /**
- * \fn CPLErr GDALWarpOperation::WarpRegionToBuffer( 
-                                  int nDstXOff, int nDstYOff, 
-                                  int nDstXSize, int nDstYSize, 
-                                  void *pDataBuf, 
+ * \fn CPLErr GDALWarpOperation::WarpRegionToBuffer(
+                                  int nDstXOff, int nDstYOff,
+                                  int nDstXSize, int nDstYSize,
+                                  void *pDataBuf,
                                   GDALDataType eBufDataType,
                                   int nSrcXOff=0, int nSrcYOff=0,
                                   int nSrcXSize=0, int nSrcYSize=0,
                                   double dfProgressBase = 0,
                                   double dfProgressScale = 1 );
- * 
+ *
  * This method requests that a particular window of the output dataset
  * be warped and the result put into the provided data buffer.  The output
  * dataset doesn't even really have to exist to use this method as long as
  * the transformation function in the GDALWarpOptions is setup to map to
- * a virtual pixel/line space. 
+ * a virtual pixel/line space.
  *
  * This method will do the whole region in one chunk, so be wary of the
- * amount of memory that might be used. 
+ * amount of memory that might be used.
  *
  * @param nDstXOff X offset to window of destination data to be produced.
  * @param nDstYOff Y offset to window of destination data to be produced.
@@ -1464,7 +1471,7 @@ CPLErr GDALWarpRegion( GDALWarpOperationH hOperation,
  * @param nDstYSize Height of output window on destination file to be produced.
  * @param pDataBuf the data buffer to place result in, of type eBufDataType.
  * @param eBufDataType the type of the output data buffer.  For now this
- * must match GDALWarpOptions::eWorkingDataType. 
+ * must match GDALWarpOptions::eWorkingDataType.
  * @param nSrcXOff source window X offset (computed if window all zero)
  * @param nSrcYOff source window Y offset (computed if window all zero)
  * @param nSrcXSize source window X size (computed if window all zero)
@@ -1476,20 +1483,20 @@ CPLErr GDALWarpRegion( GDALWarpOperationH hOperation,
  * @return CE_None on success or CE_Failure if an error occurs.
  */
 
-CPLErr GDALWarpOperation::WarpRegionToBuffer( 
-    int nDstXOff, int nDstYOff, int nDstXSize, int nDstYSize, 
+CPLErr GDALWarpOperation::WarpRegionToBuffer(
+    int nDstXOff, int nDstYOff, int nDstXSize, int nDstYSize,
     void *pDataBuf, GDALDataType eBufDataType,
     int nSrcXOff, int nSrcYOff, int nSrcXSize, int nSrcYSize,
     double dfProgressBase, double dfProgressScale)
 {
-    return WarpRegionToBuffer(nDstXOff, nDstYOff, nDstXSize, nDstYSize, 
+    return WarpRegionToBuffer(nDstXOff, nDstYOff, nDstXSize, nDstYSize,
                               pDataBuf, eBufDataType,
                               nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize, 0, 0,
                               dfProgressBase, dfProgressScale);
 }
 
-CPLErr GDALWarpOperation::WarpRegionToBuffer( 
-    int nDstXOff, int nDstYOff, int nDstXSize, int nDstYSize, 
+CPLErr GDALWarpOperation::WarpRegionToBuffer(
+    int nDstXOff, int nDstYOff, int nDstXSize, int nDstYSize,
     void *pDataBuf, GDALDataType eBufDataType,
     int nSrcXOff, int nSrcYOff, int nSrcXSize, int nSrcYSize,
     int nSrcXExtraSize, int nSrcYExtraSize,
@@ -1498,7 +1505,7 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
 {
     CPLErr eErr = CE_None;
     int    i;
-    int    nWordSize = GDALGetDataTypeSize(psOptions->eWorkingDataType)/8;
+    const int nWordSize = GDALGetDataTypeSizeBytes(psOptions->eWorkingDataType);
 
     (void) eBufDataType;
     CPLAssert( eBufDataType == psOptions->eWorkingDataType );
@@ -1509,10 +1516,9 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
     if( nSrcXSize == 0 && nSrcYSize == 0 )
     {
         eErr = ComputeSourceWindow( nDstXOff, nDstYOff, nDstXSize, nDstYSize,
-                                    &nSrcXOff, &nSrcYOff, 
+                                    &nSrcXOff, &nSrcYOff,
                                     &nSrcXSize, &nSrcYSize,
                                     &nSrcXExtraSize, &nSrcYExtraSize, NULL );
-    
         if( eErr != CE_None )
             return eErr;
     }
@@ -1528,14 +1534,15 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
 
     oWK.pfnTransformer = psOptions->pfnTransformer;
     oWK.pTransformerArg = psOptions->pTransformerArg;
-    
+
     oWK.pfnProgress = psOptions->pfnProgress;
     oWK.pProgress = psOptions->pProgressArg;
     oWK.dfProgressBase = dfProgressBase;
     oWK.dfProgressScale = dfProgressScale;
 
     oWK.papszWarpOptions = psOptions->papszWarpOptions;
-    
+    oWK.psThreadData = psThreadData;
+
     oWK.padfDstNoDataReal = psOptions->padfDstNoDataReal;
 
 /* -------------------------------------------------------------------- */
@@ -1561,29 +1568,26 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
         return CE_Failure;
     }
 
-    oWK.papabySrcImage = (GByte **) 
+    oWK.papabySrcImage = (GByte **)
         CPLCalloc(sizeof(GByte*),psOptions->nBandCount);
     oWK.papabySrcImage[0] = (GByte *)
-        VSIMalloc( nWordSize * (nSrcXSize * nSrcYSize + WARP_EXTRA_ELTS) * psOptions->nBandCount );
+        VSI_MALLOC_VERBOSE( nWordSize * (nSrcXSize * nSrcYSize + WARP_EXTRA_ELTS) * psOptions->nBandCount );
 
     if( nSrcXSize != 0 && nSrcYSize != 0 && oWK.papabySrcImage[0] == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory, 
-                  "Failed to allocate %d byte source buffer.",
-                  nWordSize * (nSrcXSize * nSrcYSize + WARP_EXTRA_ELTS) * psOptions->nBandCount );
         eErr = CE_Failure;
     }
-        
+
     for( i = 0; i < psOptions->nBandCount && eErr == CE_None; i++ )
         oWK.papabySrcImage[i] = ((GByte *) oWK.papabySrcImage[0])
             + nWordSize * (nSrcXSize * nSrcYSize + WARP_EXTRA_ELTS) * i;
 
     if( eErr == CE_None && nSrcXSize > 0 && nSrcYSize > 0 )
-        eErr = 
-            GDALDatasetRasterIO( psOptions->hSrcDS, GF_Read, 
-                                 nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize, 
+        eErr =
+            GDALDatasetRasterIO( psOptions->hSrcDS, GF_Read,
+                                 nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize,
                                  oWK.papabySrcImage[0], nSrcXSize, nSrcYSize,
-                                 psOptions->eWorkingDataType, 
+                                 psOptions->eWorkingDataType,
                                  psOptions->nBandCount, psOptions->panSrcBands,
                                  0, 0, nWordSize * (nSrcXSize * nSrcYSize + WARP_EXTRA_ELTS) );
 
@@ -1597,7 +1601,7 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
     oWK.nDstXSize = nDstXSize;
     oWK.nDstYSize = nDstYSize;
 
-    oWK.papabyDstImage = (GByte **) 
+    oWK.papabyDstImage = (GByte **)
         CPLCalloc(sizeof(GByte*),psOptions->nBandCount);
 
     for( i = 0; i < psOptions->nBandCount && eErr == CE_None; i++ )
@@ -1610,7 +1614,7 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
 /*      Eventually we need handling for a whole bunch of the            */
 /*      validity and density masks here.                                */
 /* -------------------------------------------------------------------- */
-    
+
     /* TODO */
 
 /* -------------------------------------------------------------------- */
@@ -1622,15 +1626,15 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
         CPLAssert( oWK.pafUnifiedSrcDensity == NULL );
 
         eErr = CreateKernelMask( &oWK, 0, "UnifiedSrcDensity" );
-        
+
         if( eErr == CE_None )
         {
             int bOutAllOpaque = FALSE;
-            eErr = 
-                GDALWarpSrcAlphaMasker( psOptions, 
-                                        psOptions->nBandCount, 
+            eErr =
+                GDALWarpSrcAlphaMasker( psOptions,
+                                        psOptions->nBandCount,
                                         psOptions->eWorkingDataType,
-                                        oWK.nSrcXOff, oWK.nSrcYOff, 
+                                        oWK.nSrcXOff, oWK.nSrcYOff,
                                         oWK.nSrcXSize, oWK.nSrcYSize,
                                         oWK.papabySrcImage,
                                         TRUE, oWK.pafUnifiedSrcDensity,
@@ -1652,28 +1656,26 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
     {
         if( oWK.pafUnifiedSrcDensity == NULL )
         {
-            int j = oWK.nSrcXSize * oWK.nSrcYSize;
-
             eErr = CreateKernelMask( &oWK, 0, "UnifiedSrcDensity" );
 
             if( eErr == CE_None )
             {
-                for( j = oWK.nSrcXSize * oWK.nSrcYSize - 1; j >= 0; j-- )
+                for( int j = oWK.nSrcXSize * oWK.nSrcYSize - 1; j >= 0; j-- )
                     oWK.pafUnifiedSrcDensity[j] = 1.0;
             }
         }
-        
+
         if( eErr == CE_None )
-            eErr = 
-                GDALWarpCutlineMasker( psOptions, 
-                                       psOptions->nBandCount, 
+            eErr =
+                GDALWarpCutlineMasker( psOptions,
+                                       psOptions->nBandCount,
                                        psOptions->eWorkingDataType,
-                                       oWK.nSrcXOff, oWK.nSrcYOff, 
+                                       oWK.nSrcXOff, oWK.nSrcYOff,
                                        oWK.nSrcXSize, oWK.nSrcYSize,
                                        oWK.papabySrcImage,
                                        TRUE, oWK.pafUnifiedSrcDensity );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Generate a destination density mask if we have a destination    */
 /*      alpha band.                                                     */
@@ -1683,18 +1685,18 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
         CPLAssert( oWK.pafDstDensity == NULL );
 
         eErr = CreateKernelMask( &oWK, i, "DstDensity" );
-        
+
         if( eErr == CE_None )
-            eErr = 
-                GDALWarpDstAlphaMasker( psOptions, 
-                                        psOptions->nBandCount, 
+            eErr =
+                GDALWarpDstAlphaMasker( psOptions,
+                                        psOptions->nBandCount,
                                         psOptions->eWorkingDataType,
-                                        oWK.nDstXOff, oWK.nDstYOff, 
+                                        oWK.nDstXOff, oWK.nDstYOff,
                                         oWK.nDstXSize, oWK.nDstYSize,
                                         oWK.papabyDstImage,
                                         TRUE, oWK.pafDstDensity );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      If we have source nodata values create the validity mask.       */
 /* -------------------------------------------------------------------- */
@@ -1715,10 +1717,10 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
                 adfNoData[1] = psOptions->padfSrcNoDataImag[i];
 
                 int bAllValid = FALSE;
-                eErr = 
-                    GDALWarpNoDataMasker( adfNoData, 1, 
+                eErr =
+                    GDALWarpNoDataMasker( adfNoData, 1,
                                           psOptions->eWorkingDataType,
-                                          oWK.nSrcXOff, oWK.nSrcYOff, 
+                                          oWK.nSrcXOff, oWK.nSrcYOff,
                                           oWK.nSrcXSize, oWK.nSrcYSize,
                                           &(oWK.papabySrcImage[i]),
                                           FALSE, oWK.papanBandSrcValid[i],
@@ -1738,7 +1740,7 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
             CPLFree( oWK.papanBandSrcValid );
             oWK.papanBandSrcValid = NULL;
         }
-        
+
 /* -------------------------------------------------------------------- */
 /*      If UNIFIED_SRC_NODATA is set, then compute a unified input      */
 /*      pixel mask if and only if all bands nodata is true.  That       */
@@ -1747,7 +1749,7 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
 /* -------------------------------------------------------------------- */
         if( oWK.papanBandSrcValid != NULL &&
             CSLFetchBoolean( psOptions->papszWarpOptions, "UNIFIED_SRC_NODATA",
-                             FALSE ) 
+                             FALSE )
             && eErr == CE_None )
         {
             int nBytesInMask = (oWK.nSrcXSize * oWK.nSrcYSize + 31) / 8;
@@ -1758,16 +1760,16 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
             if( eErr == CE_None )
             {
                 memset( oWK.panUnifiedSrcValid, 0, nBytesInMask );
-                
+
                 for( i = 0; i < psOptions->nBandCount; i++ )
                 {
                     for( iWord = nBytesInMask/4 - 1; iWord >= 0; iWord-- )
-                        oWK.panUnifiedSrcValid[iWord] |= 
+                        oWK.panUnifiedSrcValid[iWord] |=
                             oWK.papanBandSrcValid[i][iWord];
                     CPLFree( oWK.papanBandSrcValid[i] );
                     oWK.papanBandSrcValid[i] = NULL;
                 }
-                
+
                 CPLFree( oWK.papanBandSrcValid );
                 oWK.papanBandSrcValid = NULL;
             }
@@ -1783,26 +1785,26 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
     if( psOptions->nBandCount > 0 )
         hSrcBand = GDALGetRasterBand(psOptions->hSrcDS,
                                      psOptions->panSrcBands[0]);
-    
-    if( eErr == CE_None 
-        && oWK.pafUnifiedSrcDensity == NULL 
+
+    if( eErr == CE_None
+        && oWK.pafUnifiedSrcDensity == NULL
         && (GDALGetMaskFlags(hSrcBand) & GMF_PER_DATASET) &&
         nSrcXSize > 0 && nSrcYSize > 0 )
 
     {
         eErr = CreateKernelMask( &oWK, 0, "UnifiedSrcValid" );
-        
+
         if( eErr == CE_None )
-            eErr = 
-                GDALWarpSrcMaskMasker( psOptions, 
-                                       psOptions->nBandCount, 
+            eErr =
+                GDALWarpSrcMaskMasker( psOptions,
+                                       psOptions->nBandCount,
                                        psOptions->eWorkingDataType,
-                                       oWK.nSrcXOff, oWK.nSrcYOff, 
+                                       oWK.nSrcXOff, oWK.nSrcYOff,
                                        oWK.nSrcXSize, oWK.nSrcYSize,
                                        oWK.papabySrcImage,
                                        FALSE, oWK.panUnifiedSrcValid );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      If we have destination nodata values create the                 */
 /*      validity mask.  We set the DstValid for any pixel that we       */
@@ -1828,21 +1830,21 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
         if( eErr == CE_None && panBandMask != NULL )
         {
             int iBand, iWord;
-            
+
             for( iBand = 0; iBand < psOptions->nBandCount; iBand++ )
             {
                 double adfNoData[2];
-            
+
                 memset( panBandMask, 0xff, nMaskWords * 4 );
 
                 adfNoData[0] = psOptions->padfDstNoDataReal[iBand];
                 adfNoData[1] = psOptions->padfDstNoDataImag[iBand];
-            
+
                 int bAllValid = FALSE;
-                eErr = 
-                    GDALWarpNoDataMasker( adfNoData, 1, 
+                eErr =
+                    GDALWarpNoDataMasker( adfNoData, 1,
                                           psOptions->eWorkingDataType,
-                                          oWK.nDstXOff, oWK.nDstYOff, 
+                                          oWK.nDstXOff, oWK.nDstYOff,
                                           oWK.nDstXSize, oWK.nDstYSize,
                                           oWK.papabyDstImage + iBand,
                                           FALSE, panBandMask,
@@ -1864,7 +1866,7 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
             CPLFree( panBandMask );
         }
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Release IO Mutex, and acquire warper mutex.                     */
 /* -------------------------------------------------------------------- */
@@ -1873,7 +1875,7 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
         CPLReleaseMutex( hIOMutex );
         if( !CPLAcquireMutex( hWarpMutex, 600.0 ) )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Failed to acquire WarpMutex in WarpRegion()." );
             return CE_Failure;
         }
@@ -1883,7 +1885,7 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
 /*      Optional application provided prewarp chunk processor.          */
 /* -------------------------------------------------------------------- */
     if( eErr == CE_None && psOptions->pfnPreWarpChunkProcessor != NULL )
-        eErr = psOptions->pfnPreWarpChunkProcessor( 
+        eErr = psOptions->pfnPreWarpChunkProcessor(
             (void *) &oWK, psOptions->pPreWarpProcessorArg );
 
 /* -------------------------------------------------------------------- */
@@ -1899,7 +1901,7 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
 /*      Optional application provided postwarp chunk processor.         */
 /* -------------------------------------------------------------------- */
     if( eErr == CE_None && psOptions->pfnPostWarpChunkProcessor != NULL )
-        eErr = psOptions->pfnPostWarpChunkProcessor( 
+        eErr = psOptions->pfnPostWarpChunkProcessor(
             (void *) &oWK, psOptions->pPostWarpProcessorArg );
 
 /* -------------------------------------------------------------------- */
@@ -1910,27 +1912,27 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
         CPLReleaseMutex( hWarpMutex );
         if( !CPLAcquireMutex( hIOMutex, 600.0 ) )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Failed to acquire IOMutex in WarpRegion()." );
             return CE_Failure;
         }
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Write destination alpha if available.                           */
 /* -------------------------------------------------------------------- */
     if( eErr == CE_None && psOptions->nDstAlphaBand > 0 )
     {
-        eErr = 
-            GDALWarpDstAlphaMasker( psOptions, 
-                                    -psOptions->nBandCount, 
+        eErr =
+            GDALWarpDstAlphaMasker( psOptions,
+                                    -psOptions->nBandCount,
                                     psOptions->eWorkingDataType,
-                                    oWK.nDstXOff, oWK.nDstYOff, 
+                                    oWK.nDstXOff, oWK.nDstYOff,
                                     oWK.nDstXSize, oWK.nDstYSize,
                                     oWK.papabyDstImage,
                                     TRUE, oWK.pafDstDensity );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Cleanup.                                                        */
 /* -------------------------------------------------------------------- */
@@ -1948,7 +1950,7 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
     CPLFree( oWK.pafUnifiedSrcDensity );
     CPLFree( oWK.panDstValid );
     CPLFree( oWK.pafDstDensity );
-    
+
     return eErr;
 }
 
@@ -1959,9 +1961,9 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
 /**
  * @see GDALWarpOperation::WarpRegionToBuffer()
  */
-                                 
+
 CPLErr GDALWarpRegionToBuffer( GDALWarpOperationH hOperation,
-    int nDstXOff, int nDstYOff, int nDstXSize, int nDstYSize, 
+    int nDstXOff, int nDstYOff, int nDstXSize, int nDstYSize,
     void *pDataBuf, GDALDataType eBufDataType,
     int nSrcXOff, int nSrcYOff, int nSrcXSize, int nSrcYSize )
 
@@ -1999,7 +2001,7 @@ CPLErr GDALWarpOperation::CreateKernelMask( GDALWarpKernel *poKernel,
         if( poKernel->papanBandSrcValid == NULL )
             poKernel->papanBandSrcValid = (GUInt32 **)
                 CPLCalloc( sizeof(void*),poKernel->nBands);
-                
+
         ppMask = (void **) &(poKernel->papanBandSrcValid[iBand]);
         nExtraElts = WARP_EXTRA_ELTS;
         nXSize = poKernel->nSrcXSize;
@@ -2061,13 +2063,10 @@ CPLErr GDALWarpOperation::CreateKernelMask( GDALWarpKernel *poKernel,
         else
             nBytes = (nXSize * nYSize + nExtraElts + 31) / 8;
 
-        *ppMask = VSIMalloc( nBytes );
+        *ppMask = VSI_MALLOC_VERBOSE( nBytes );
 
         if( *ppMask == NULL )
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory, 
-                      "Out of memory allocating %d bytes for %s mask.", 
-                      nBytes, pszType );
             return CE_Failure;
         }
 
@@ -2083,9 +2082,9 @@ CPLErr GDALWarpOperation::CreateKernelMask( GDALWarpKernel *poKernel,
 /*                        ComputeSourceWindow()                         */
 /************************************************************************/
 
-CPLErr GDALWarpOperation::ComputeSourceWindow(int nDstXOff, int nDstYOff, 
+CPLErr GDALWarpOperation::ComputeSourceWindow(int nDstXOff, int nDstYOff,
                                               int nDstXSize, int nDstYSize,
-                                              int *pnSrcXOff, int *pnSrcYOff, 
+                                              int *pnSrcXOff, int *pnSrcYOff,
                                               int *pnSrcXSize, int *pnSrcYSize,
                                               int *pnSrcXExtraSize, int *pnSrcYExtraSize,
                                               double *pdfSrcFillRatio)
@@ -2105,18 +2104,18 @@ CPLErr GDALWarpOperation::ComputeSourceWindow(int nDstXOff, int nDstYOff,
     int    nSamplePoints;
     double dfRatio;
 
-    if( CSLFetchNameValue( psOptions->papszWarpOptions, 
+    if( CSLFetchNameValue( psOptions->papszWarpOptions,
                            "SAMPLE_STEPS" ) != NULL )
     {
-        nStepCount = 
-            atoi(CSLFetchNameValue( psOptions->papszWarpOptions, 
+        nStepCount =
+            atoi(CSLFetchNameValue( psOptions->papszWarpOptions,
                                     "SAMPLE_STEPS" ));
         nStepCount = MAX(2,nStepCount);
     }
 
     dfStepSize = 1.0 / (nStepCount-1);
 
-    bUseGrid = CSLFetchBoolean( psOptions->papszWarpOptions, 
+    bUseGrid = CSLFetchBoolean( psOptions->papszWarpOptions,
                                 "SAMPLE_GRID", FALSE );
 
   TryAgainWithGrid:
@@ -2142,8 +2141,8 @@ CPLErr GDALWarpOperation::ComputeSourceWindow(int nDstXOff, int nDstYOff,
         nSampleMax = nStepCount * 4;
     }
 
-    pabSuccess = (int *) VSIMalloc2(sizeof(int), nSampleMax);
-    padfX = (double *) VSIMalloc2(sizeof(double) * 3, nSampleMax);
+    pabSuccess = (int *) VSI_MALLOC2_VERBOSE(sizeof(int), nSampleMax);
+    padfX = (double *) VSI_MALLOC2_VERBOSE(sizeof(double) * 3, nSampleMax);
     if (pabSuccess == NULL || padfX == NULL)
     {
         CPLFree( padfX );
@@ -2160,12 +2159,12 @@ CPLErr GDALWarpOperation::ComputeSourceWindow(int nDstXOff, int nDstYOff,
     {
         double dfRatioY;
 
-        for( dfRatioY = 0.0; 
-             dfRatioY <= 1.0 + dfStepSize*0.5; 
+        for( dfRatioY = 0.0;
+             dfRatioY <= 1.0 + dfStepSize*0.5;
              dfRatioY += dfStepSize )
         {
-            for( dfRatio = 0.0; 
-                 dfRatio <= 1.0 + dfStepSize*0.5; 
+            for( dfRatio = 0.0;
+                 dfRatio <= 1.0 + dfStepSize*0.5;
                  dfRatio += dfStepSize )
             {
                 padfX[nSamplePoints]   = dfRatio * nDstXSize + nDstXOff;
@@ -2181,46 +2180,46 @@ CPLErr GDALWarpOperation::ComputeSourceWindow(int nDstXOff, int nDstYOff,
     {
         for( dfRatio = 0.0; dfRatio <= 1.0 + dfStepSize*0.5; dfRatio += dfStepSize )
         {
-            // Along top 
+            // Along top
             padfX[nSamplePoints]   = dfRatio * nDstXSize + nDstXOff;
             padfY[nSamplePoints]   = nDstYOff;
             padfZ[nSamplePoints++] = 0.0;
-            
-            // Along bottom 
+
+            // Along bottom
             padfX[nSamplePoints]   = dfRatio * nDstXSize + nDstXOff;
             padfY[nSamplePoints]   = nDstYOff + nDstYSize;
             padfZ[nSamplePoints++] = 0.0;
-            
+
             // Along left
             padfX[nSamplePoints]   = nDstXOff;
             padfY[nSamplePoints]   = dfRatio * nDstYSize + nDstYOff;
             padfZ[nSamplePoints++] = 0.0;
-            
+
             // Along right
             padfX[nSamplePoints]   = nDstXSize + nDstXOff;
             padfY[nSamplePoints]   = dfRatio * nDstYSize + nDstYOff;
             padfZ[nSamplePoints++] = 0.0;
         }
     }
-        
+
     CPLAssert( nSamplePoints == nSampleMax );
 
 /* -------------------------------------------------------------------- */
 /*      Transform them to the input pixel coordinate space              */
 /* -------------------------------------------------------------------- */
-    if( !psOptions->pfnTransformer( psOptions->pTransformerArg, 
-                                    TRUE, nSamplePoints, 
+    if( !psOptions->pfnTransformer( psOptions->pTransformerArg,
+                                    TRUE, nSamplePoints,
                                     padfX, padfY, padfZ, pabSuccess ) )
     {
         CPLFree( padfX );
         CPLFree( pabSuccess );
 
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "GDALWarperOperation::ComputeSourceWindow() failed because\n"
                   "the pfnTransformer failed." );
         return CE_Failure;
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Collect the bounds, ignoring any failed points.                 */
 /* -------------------------------------------------------------------- */
@@ -2271,7 +2270,7 @@ CPLErr GDALWarpOperation::ComputeSourceWindow(int nDstXOff, int nDstYOff,
 /* -------------------------------------------------------------------- */
     if( nFailedCount > nSamplePoints - 5 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Too many points (%d out of %d) failed to transform,\n"
                   "unable to compute output bounds.",
                   nFailedCount, nSamplePoints );
@@ -2279,8 +2278,8 @@ CPLErr GDALWarpOperation::ComputeSourceWindow(int nDstXOff, int nDstYOff,
     }
 
     if( nFailedCount > 0 )
-        CPLDebug( "GDAL", 
-                  "GDALWarpOperation::ComputeSourceWindow() %d out of %d points failed to transform.", 
+        CPLDebug( "GDAL",
+                  "GDALWarpOperation::ComputeSourceWindow() %d out of %d points failed to transform.",
                   nFailedCount, nSamplePoints );
 
 /* -------------------------------------------------------------------- */
@@ -2331,7 +2330,7 @@ CPLErr GDALWarpOperation::ComputeSourceWindow(int nDstXOff, int nDstYOff,
 /*      fallback to adding a bit to the window if any points failed     */
 /*      to transform.                                                   */
 /* -------------------------------------------------------------------- */
-    if( CSLFetchNameValue( psOptions->papszWarpOptions, 
+    if( CSLFetchNameValue( psOptions->papszWarpOptions,
                            "SOURCE_EXTRA" ) != NULL )
     {
         nResWinSize += atoi(
@@ -2365,7 +2364,7 @@ CPLErr GDALWarpOperation::ComputeSourceWindow(int nDstXOff, int nDstYOff,
                        ((int) dfCeilMaxYOut) - *pnSrcYOff );
     nSrcXSizeRaw = MAX(0,nSrcXSizeRaw);
     nSrcYSizeRaw = MAX(0,nSrcYSizeRaw);
-    
+
     *pnSrcXOff = MAX(0,(int) floor( dfMinXOut ) - nResWinSize );
     *pnSrcYOff = MAX(0,(int) floor( dfMinYOut ) - nResWinSize );
     *pnSrcXOff = MIN(*pnSrcXOff,nRasterXSize);
@@ -2382,12 +2381,12 @@ CPLErr GDALWarpOperation::ComputeSourceWindow(int nDstXOff, int nDstYOff,
         *pnSrcXExtraSize = *pnSrcXSize - nSrcXSizeRaw;
     if( pnSrcYExtraSize )
         *pnSrcYExtraSize = *pnSrcYSize - nSrcYSizeRaw;
-    
+
     // Computed the ratio of the clamped source raster window size over
     // the unclamped source raster window size
     if( pdfSrcFillRatio )
         *pdfSrcFillRatio = *pnSrcXSize * *pnSrcYSize / MAX(1.0,
-        (dfMaxXOut - dfMinXOut + 2 * nResWinSize) * (dfMaxYOut - dfMinYOut + 2 * nResWinSize)); 
+        (dfMaxXOut - dfMinXOut + 2 * nResWinSize) * (dfMaxYOut - dfMinYOut + 2 * nResWinSize));
 
     return CE_None;
 }
@@ -2406,10 +2405,9 @@ void GDALWarpOperation::ReportTiming( const char * pszMessage )
 
     if( pszMessage != NULL )
     {
-        CPLDebug( "WARP_TIMING", "%s: %lds", 
+        CPLDebug( "WARP_TIMING", "%s: %lds",
                   pszMessage, (long)(nNewTime - nLastTimeReported) );
     }
 
     nLastTimeReported = nNewTime;
 }
-
diff --git a/alg/gvgcpfit.h b/alg/gvgcpfit.h
index d289cc2..4496c59 100644
--- a/alg/gvgcpfit.h
+++ b/alg/gvgcpfit.h
@@ -1,5 +1,5 @@
-#ifndef _GVGCPFIT_H_INCLUDED
-#define _GVGCPFIT_H_INCLUDED
+#ifndef GVGCPFIT_H_INCLUDED
+#define GVGCPFIT_H_INCLUDED
 
 #include "cpl_port.h"
 #include "cpl_conv.h"
@@ -51,8 +51,8 @@ EXTERNAL int svdcmp(double **a, int m, int n, double *w, double **v);
 
 
 /*----------------------------- FILE polyfit.h ----------------------------*/
-#ifndef __POLYFIT_H
-#define __POLYFIT_H
+#ifndef POLYFIT_H
+#define POLYFIT_H
 
 EXTERNAL int OneDPolyFit( double *rms_err, double *coeffs_array,
     int fit_order, int no_samples, double *f_array, double *x_array );
@@ -86,7 +86,7 @@ EXTERNAL double ThreeDPolyEval( double *coeff, int order, double x, double y, do
 
 
 
-#endif /* __POLYFIT_H */
+#endif /* POLYFIT_H */
 
 
 /*---------------------- End of FILE polyfit.h ----------------------------*/
diff --git a/alg/internal_qhull_headers.h b/alg/internal_qhull_headers.h
new file mode 100644
index 0000000..61f2bf1
--- /dev/null
+++ b/alg/internal_qhull_headers.h
@@ -0,0 +1,1006 @@
+/******************************************************************************
+ *
+ * Project:  GDAL
+ * Purpose:  Includes internal qhull headers
+ * Author:   Even Rouault <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+#ifndef INTERNAL_QHULL_HEADERS_H
+#define INTERNAL_QHULL_HEADERS_H
+
+#ifdef HAVE_GCC_SYSTEM_HEADER
+#pragma GCC system_header
+#endif
+
+#if defined(__MINGW64__)
+/* See https://github.com/scipy/scipy/issues/3237 */
+/* This ensures that ptr_intT is a long lon on MinGW 64 */
+#define _MSC_VER 1
+#endif
+
+// To avoid issue with icc that defines a template in qhull_a.h
+#if defined(__INTEL_COMPILER)
+#define QHULL_OS_WIN
+#endif
+
+/* Below a lot of renames and static definition of the symbols so as */
+/* to avoid "contaminating" with a potential external qhull */
+typedef struct setT gdal_setT;
+typedef struct facetT gdal_facetT;
+typedef struct vertexT gdal_vertexT;
+typedef struct qhT gdal_qhT;
+typedef struct ridgeT gdal_ridgeT;
+#define gdal_realT double
+#define gdal_pointT double
+#define gdal_realT double
+#define gdal_coordT double
+#define gdal_boolT unsigned int
+
+#define qhmem gdal_qhmem
+#define qh_rand_seed gdal_qh_rand_seed
+#define qh_qh gdal_qh_qh
+#define qh_qhstat gdal_qh_qhstat
+#define qh_version gdal_qh_version
+#define qhull_inuse gdal_qhull_inuse
+
+#define qh_compare_vertexpoint gdal_qh_compare_vertexpoint
+static int qh_compare_vertexpoint();
+
+#define qh_intcompare gdal_qh_intcompare
+
+#ifdef notdef
+
+Generated by the following Python script + manual cleaning of the result
+
+f = open('headers.txt')
+for line in f.readlines():
+    line = line[0:-1].strip()
+    if len(line) > 3 and line[0] != '#' and (line[-2:] == ');' or line[-1:] == ',') and \
+       line.find('(') > 0 and line.find('=') < 0 and line.find('typedef') < 0 and line.find('are used by') < 0 and \
+       line.find('&') < 0 and line.find('"') < 0 and line.find(' ') < line.find('('):
+        line = line[0:line.find('(')].strip()
+        last_star = line.rfind('*')
+        last_space = line.rfind(' ')
+        if last_star > last_space:
+            (type, name) = (line[0:last_star+1], line[last_star+1:])
+        else:
+            (type, name) = (line[0:last_space], line[last_space+1:])
+        type = type.strip()
+        print('#define %s gdal_%s' % (name, name))
+        if type.find('void') != 0 and type.find('int') != 0 and type.find('char') != 0 and type.find('double') != 0 and type.find('unsigned') != 0:
+            type = 'gdal_' + type
+        print("static %s %s();" % (type, name))
+#endif
+
+#define qh_backnormal gdal_qh_backnormal
+static void qh_backnormal();
+#define qh_distplane gdal_qh_distplane
+static void qh_distplane();
+#define qh_findbest gdal_qh_findbest
+static gdal_facetT * qh_findbest();
+#define qh_findbesthorizon gdal_qh_findbesthorizon
+static gdal_facetT * qh_findbesthorizon();
+#define qh_findbestnew gdal_qh_findbestnew
+static gdal_facetT * qh_findbestnew();
+#define qh_gausselim gdal_qh_gausselim
+static void qh_gausselim();
+#define qh_getangle gdal_qh_getangle
+static gdal_realT qh_getangle();
+#define qh_getcenter gdal_qh_getcenter
+static gdal_pointT * qh_getcenter();
+#define qh_getcentrum gdal_qh_getcentrum
+static gdal_pointT * qh_getcentrum();
+#define qh_getdistance gdal_qh_getdistance
+static gdal_realT qh_getdistance();
+#define qh_normalize gdal_qh_normalize
+static void qh_normalize();
+#define qh_normalize2 gdal_qh_normalize2
+static void qh_normalize2();
+#define qh_projectpoint gdal_qh_projectpoint
+static gdal_pointT * qh_projectpoint();
+#define qh_setfacetplane gdal_qh_setfacetplane
+static void qh_setfacetplane();
+#define qh_sethyperplane_det gdal_qh_sethyperplane_det
+static void qh_sethyperplane_det();
+#define qh_sethyperplane_gauss gdal_qh_sethyperplane_gauss
+static void qh_sethyperplane_gauss();
+#define qh_sharpnewfacets gdal_qh_sharpnewfacets
+static gdal_boolT qh_sharpnewfacets();
+#define qh_copypoints gdal_qh_copypoints
+static gdal_coordT * qh_copypoints();
+#define qh_crossproduct gdal_qh_crossproduct
+static void qh_crossproduct();
+#define qh_determinant gdal_qh_determinant
+static gdal_realT qh_determinant();
+#define qh_detjoggle gdal_qh_detjoggle
+static gdal_realT qh_detjoggle();
+#define qh_detroundoff gdal_qh_detroundoff
+static void qh_detroundoff();
+#define qh_detsimplex gdal_qh_detsimplex
+static gdal_realT qh_detsimplex();
+#define qh_distnorm gdal_qh_distnorm
+static gdal_realT qh_distnorm();
+#define qh_distround gdal_qh_distround
+static gdal_realT qh_distround();
+#define qh_divzero gdal_qh_divzero
+static gdal_realT qh_divzero();
+#define qh_facetarea gdal_qh_facetarea
+static gdal_realT qh_facetarea();
+#define qh_facetarea_simplex gdal_qh_facetarea_simplex
+static gdal_realT qh_facetarea_simplex();
+#define qh_facetcenter gdal_qh_facetcenter
+static gdal_pointT * qh_facetcenter();
+#define qh_findgooddist gdal_qh_findgooddist
+static gdal_facetT * qh_findgooddist();
+#define qh_getarea gdal_qh_getarea
+static void qh_getarea();
+#define qh_gram_schmidt gdal_qh_gram_schmidt
+static gdal_boolT qh_gram_schmidt();
+#define qh_inthresholds gdal_qh_inthresholds
+static gdal_boolT qh_inthresholds();
+#define qh_joggleinput gdal_qh_joggleinput
+static void qh_joggleinput();
+#define qh_maxabsval gdal_qh_maxabsval
+static gdal_realT  * qh_maxabsval();
+#define qh_maxmin gdal_qh_maxmin
+static gdal_setT   * qh_maxmin();
+#define qh_maxouter gdal_qh_maxouter
+static gdal_realT qh_maxouter();
+#define qh_maxsimplex gdal_qh_maxsimplex
+static void qh_maxsimplex();
+#define qh_minabsval gdal_qh_minabsval
+static gdal_realT qh_minabsval();
+#define qh_mindiff gdal_qh_mindiff
+static int qh_mindiff();
+#define qh_orientoutside gdal_qh_orientoutside
+static gdal_boolT qh_orientoutside();
+#define qh_outerinner gdal_qh_outerinner
+static void qh_outerinner();
+#define qh_pointdist gdal_qh_pointdist
+static gdal_coordT qh_pointdist();
+#define qh_printmatrix gdal_qh_printmatrix
+static void qh_printmatrix();
+#define qh_printpoints gdal_qh_printpoints
+static void qh_printpoints();
+#define qh_projectinput gdal_qh_projectinput
+static void qh_projectinput();
+#define qh_projectpoints gdal_qh_projectpoints
+static void qh_projectpoints();
+#define qh_rotateinput gdal_qh_rotateinput
+static void qh_rotateinput();
+#define qh_rotatepoints gdal_qh_rotatepoints
+static void qh_rotatepoints();
+#define qh_scaleinput gdal_qh_scaleinput
+static void qh_scaleinput();
+#define qh_scalelast gdal_qh_scalelast
+static void qh_scalelast();
+#define qh_scalepoints gdal_qh_scalepoints
+static void qh_scalepoints();
+#define qh_sethalfspace gdal_qh_sethalfspace
+static gdal_boolT qh_sethalfspace();
+#define qh_sethalfspace_all gdal_qh_sethalfspace_all
+static gdal_coordT * qh_sethalfspace_all();
+#define qh_voronoi_center gdal_qh_voronoi_center
+static gdal_pointT * qh_voronoi_center();
+#define dfacet gdal_dfacet
+static void dfacet();
+#define dvertex gdal_dvertex
+static void dvertex();
+#define qh_compare_facetarea gdal_qh_compare_facetarea
+static int qh_compare_facetarea();
+#define qh_compare_facetmerge gdal_qh_compare_facetmerge
+static int qh_compare_facetmerge();
+#define qh_compare_facetvisit gdal_qh_compare_facetvisit
+static int qh_compare_facetvisit();
+#define qh_copyfilename gdal_qh_copyfilename
+static void qh_copyfilename();
+#define qh_countfacets gdal_qh_countfacets
+static void qh_countfacets();
+#define qh_detvnorm gdal_qh_detvnorm
+static gdal_pointT * qh_detvnorm();
+#define qh_detvridge gdal_qh_detvridge
+static gdal_setT   * qh_detvridge();
+#define qh_detvridge3 gdal_qh_detvridge3
+static gdal_setT   * qh_detvridge3();
+#define qh_eachvoronoi gdal_qh_eachvoronoi
+static int qh_eachvoronoi();
+#define qh_eachvoronoi_all gdal_qh_eachvoronoi_all
+static int qh_eachvoronoi_all();
+#define qh_facet2point gdal_qh_facet2point
+static void qh_facet2point();
+#define qh_facetvertices gdal_qh_facetvertices
+static gdal_setT   * qh_facetvertices();
+#define qh_geomplanes gdal_qh_geomplanes
+static void qh_geomplanes();
+#define qh_markkeep gdal_qh_markkeep
+static void qh_markkeep();
+#define qh_markvoronoi gdal_qh_markvoronoi
+static gdal_setT   * qh_markvoronoi();
+#define qh_order_vertexneighbors gdal_qh_order_vertexneighbors
+static void qh_order_vertexneighbors();
+#define qh_prepare_output gdal_qh_prepare_output
+static void qh_prepare_output();
+#define qh_printafacet gdal_qh_printafacet
+static void qh_printafacet();
+#define qh_printbegin gdal_qh_printbegin
+static void qh_printbegin();
+#define qh_printcenter gdal_qh_printcenter
+static void qh_printcenter();
+#define qh_printcentrum gdal_qh_printcentrum
+static void qh_printcentrum();
+#define qh_printend gdal_qh_printend
+static void qh_printend();
+#define qh_printend4geom gdal_qh_printend4geom
+static void qh_printend4geom();
+#define qh_printextremes gdal_qh_printextremes
+static void qh_printextremes();
+#define qh_printextremes_2d gdal_qh_printextremes_2d
+static void qh_printextremes_2d();
+#define qh_printextremes_d gdal_qh_printextremes_d
+static void qh_printextremes_d();
+#define qh_printfacet gdal_qh_printfacet
+static void qh_printfacet();
+#define qh_printfacet2math gdal_qh_printfacet2math
+static void qh_printfacet2math();
+#define qh_printfacet2geom gdal_qh_printfacet2geom
+static void qh_printfacet2geom();
+#define qh_printfacet2geom_points gdal_qh_printfacet2geom_points
+static void qh_printfacet2geom_points();
+#define qh_printfacet3math gdal_qh_printfacet3math
+static void qh_printfacet3math();
+#define qh_printfacet3geom_nonsimplicial gdal_qh_printfacet3geom_nonsimplicial
+static void qh_printfacet3geom_nonsimplicial();
+#define qh_printfacet3geom_points gdal_qh_printfacet3geom_points
+static void qh_printfacet3geom_points();
+#define qh_printfacet3geom_simplicial gdal_qh_printfacet3geom_simplicial
+static void qh_printfacet3geom_simplicial();
+#define qh_printfacet3vertex gdal_qh_printfacet3vertex
+static void qh_printfacet3vertex();
+#define qh_printfacet4geom_nonsimplicial gdal_qh_printfacet4geom_nonsimplicial
+static void qh_printfacet4geom_nonsimplicial();
+#define qh_printfacet4geom_simplicial gdal_qh_printfacet4geom_simplicial
+static void qh_printfacet4geom_simplicial();
+#define qh_printfacetNvertex_nonsimplicial gdal_qh_printfacetNvertex_nonsimplicial
+static void qh_printfacetNvertex_nonsimplicial();
+#define qh_printfacetNvertex_simplicial gdal_qh_printfacetNvertex_simplicial
+static void qh_printfacetNvertex_simplicial();
+#define qh_printfacetheader gdal_qh_printfacetheader
+static void qh_printfacetheader();
+#define qh_printfacetridges gdal_qh_printfacetridges
+static void qh_printfacetridges();
+#define qh_printfacets gdal_qh_printfacets
+static void qh_printfacets();
+#define qh_printhyperplaneintersection gdal_qh_printhyperplaneintersection
+static void qh_printhyperplaneintersection();
+#define qh_printneighborhood gdal_qh_printneighborhood
+static void qh_printneighborhood();
+#define qh_printline3geom gdal_qh_printline3geom
+static void qh_printline3geom();
+#define qh_printpoint gdal_qh_printpoint
+static void qh_printpoint();
+#define qh_printpointid gdal_qh_printpointid
+static void qh_printpointid();
+#define qh_printpoint3 gdal_qh_printpoint3
+static void qh_printpoint3();
+#define qh_printpoints_out gdal_qh_printpoints_out
+static void qh_printpoints_out();
+#define qh_printpointvect gdal_qh_printpointvect
+static void qh_printpointvect();
+#define qh_printpointvect2 gdal_qh_printpointvect2
+static void qh_printpointvect2();
+#define qh_printridge gdal_qh_printridge
+static void qh_printridge();
+#define qh_printspheres gdal_qh_printspheres
+static void qh_printspheres();
+#define qh_printvdiagram gdal_qh_printvdiagram
+static void qh_printvdiagram();
+#define qh_printvdiagram2 gdal_qh_printvdiagram2
+static int qh_printvdiagram2();
+#define qh_printvertex gdal_qh_printvertex
+static void qh_printvertex();
+#define qh_printvertexlist gdal_qh_printvertexlist
+static void qh_printvertexlist();
+#define qh_printvertices gdal_qh_printvertices
+static void qh_printvertices();
+#define qh_printvneighbors gdal_qh_printvneighbors
+static void qh_printvneighbors();
+#define qh_printvoronoi gdal_qh_printvoronoi
+static void qh_printvoronoi();
+#define qh_printvnorm gdal_qh_printvnorm
+static void qh_printvnorm();
+#define qh_printvridge gdal_qh_printvridge
+static void qh_printvridge();
+#define qh_produce_output gdal_qh_produce_output
+static void qh_produce_output();
+#define qh_produce_output2 gdal_qh_produce_output2
+static void qh_produce_output2();
+#define qh_projectdim3 gdal_qh_projectdim3
+static void qh_projectdim3();
+#define qh_readfeasible gdal_qh_readfeasible
+static int qh_readfeasible();
+#define qh_readpoints gdal_qh_readpoints
+static gdal_coordT * qh_readpoints();
+#define qh_setfeasible gdal_qh_setfeasible
+static void qh_setfeasible();
+#define qh_skipfacet gdal_qh_skipfacet
+static gdal_boolT qh_skipfacet();
+#define qh_skipfilename gdal_qh_skipfilename
+static char   * qh_skipfilename();
+#define qh_qhull gdal_qh_qhull
+static void qh_qhull();
+#define qh_addpoint gdal_qh_addpoint
+static gdal_boolT qh_addpoint();
+#define qh_printsummary gdal_qh_printsummary
+static void qh_printsummary();
+#define qh_errexit gdal_qh_errexit
+static void qh_errexit();
+#define qh_errprint gdal_qh_errprint
+static void qh_errprint();
+#define qh_new_qhull gdal_qh_new_qhull
+static int qh_new_qhull();
+#define qh_printfacetlist gdal_qh_printfacetlist
+static void qh_printfacetlist();
+#define qh_printhelp_degenerate gdal_qh_printhelp_degenerate
+static void qh_printhelp_degenerate();
+#define qh_printhelp_narrowhull gdal_qh_printhelp_narrowhull
+static void qh_printhelp_narrowhull();
+#define qh_printhelp_singular gdal_qh_printhelp_singular
+static void qh_printhelp_singular();
+#define qh_user_memsizes gdal_qh_user_memsizes
+static void qh_user_memsizes();
+#define qh_exit gdal_qh_exit
+static void qh_exit();
+#define qh_free gdal_qh_free
+static void qh_free();
+#define qh_malloc gdal_qh_malloc
+static void   * qh_malloc();
+#define qh_fprintf gdal_qh_fprintf
+static void qh_fprintf(FILE *fp, int msgcode, const char *fmt, ... );
+/*#define qh_fprintf_rbox gdal_qh_fprintf_rbox*/
+/*static void qh_fprintf_rbox(FILE *fp, int msgcode, const char *fmt, ... );*/
+#define qh_findbest gdal_qh_findbest
+static gdal_facetT * qh_findbest();
+#define qh_findbestnew gdal_qh_findbestnew
+static gdal_facetT * qh_findbestnew();
+#define qh_gram_schmidt gdal_qh_gram_schmidt
+static gdal_boolT qh_gram_schmidt();
+#define qh_outerinner gdal_qh_outerinner
+static void qh_outerinner();
+#define qh_printsummary gdal_qh_printsummary
+static void qh_printsummary();
+#define qh_projectinput gdal_qh_projectinput
+static void qh_projectinput();
+#define qh_randommatrix gdal_qh_randommatrix
+static void qh_randommatrix();
+#define qh_rotateinput gdal_qh_rotateinput
+static void qh_rotateinput();
+#define qh_scaleinput gdal_qh_scaleinput
+static void qh_scaleinput();
+#define qh_setdelaunay gdal_qh_setdelaunay
+static void qh_setdelaunay();
+#define qh_sethalfspace_all gdal_qh_sethalfspace_all
+static gdal_coordT  * qh_sethalfspace_all();
+#define qh_clock gdal_qh_clock
+static unsigned long qh_clock();
+#define qh_checkflags gdal_qh_checkflags
+static void qh_checkflags();
+#define qh_clear_outputflags gdal_qh_clear_outputflags
+static void qh_clear_outputflags();
+#define qh_freebuffers gdal_qh_freebuffers
+static void qh_freebuffers();
+#define qh_freeqhull gdal_qh_freeqhull
+static void qh_freeqhull();
+#define qh_freeqhull2 gdal_qh_freeqhull2
+static void qh_freeqhull2();
+#define qh_init_A gdal_qh_init_A
+static void qh_init_A();
+#define qh_init_B gdal_qh_init_B
+static void qh_init_B();
+#define qh_init_qhull_command gdal_qh_init_qhull_command
+static void qh_init_qhull_command();
+/*#define qh_initbuffers gdal_qh_initbuffers*/
+/*static void qh_initbuffers();*/
+#define qh_initflags gdal_qh_initflags
+static void qh_initflags();
+#define qh_initqhull_buffers gdal_qh_initqhull_buffers
+static void qh_initqhull_buffers();
+#define qh_initqhull_globals gdal_qh_initqhull_globals
+static void qh_initqhull_globals();
+#define qh_initqhull_mem gdal_qh_initqhull_mem
+static void qh_initqhull_mem();
+#define qh_initqhull_outputflags gdal_qh_initqhull_outputflags
+static void qh_initqhull_outputflags();
+#define qh_initqhull_start gdal_qh_initqhull_start
+static void qh_initqhull_start();
+#define qh_initqhull_start2 gdal_qh_initqhull_start2
+static void qh_initqhull_start2();
+#define qh_initthresholds gdal_qh_initthresholds
+static void qh_initthresholds();
+#define qh_option gdal_qh_option
+static void qh_option();
+/*#define qh_restore_qhull gdal_qh_restore_qhull*/
+/*static void qh_restore_qhull();*/
+/*#define qh_save_qhull gdal_qh_save_qhull*/
+/*static gdal_qhT    * qh_save_qhull();*/
+#define dfacet gdal_dfacet
+static void dfacet();
+#define dvertex gdal_dvertex
+static void dvertex();
+#define qh_printneighborhood gdal_qh_printneighborhood
+static void qh_printneighborhood();
+#define qh_produce_output gdal_qh_produce_output
+static void qh_produce_output();
+#define qh_readpoints gdal_qh_readpoints
+static gdal_coordT * qh_readpoints();
+#define qh_meminit gdal_qh_meminit
+static void qh_meminit();
+#define qh_memfreeshort gdal_qh_memfreeshort
+static void qh_memfreeshort();
+#define qh_check_output gdal_qh_check_output
+static void qh_check_output();
+#define qh_check_points gdal_qh_check_points
+static void qh_check_points();
+#define qh_facetvertices gdal_qh_facetvertices
+static gdal_setT   * qh_facetvertices();
+#define qh_findbestfacet gdal_qh_findbestfacet
+static gdal_facetT * qh_findbestfacet();
+#define qh_nearvertex gdal_qh_nearvertex
+static gdal_vertexT * qh_nearvertex();
+#define qh_point gdal_qh_point
+static gdal_pointT * qh_point();
+#define qh_pointfacet gdal_qh_pointfacet
+static gdal_setT   * qh_pointfacet();
+#define qh_pointid gdal_qh_pointid
+static int qh_pointid();
+#define qh_pointvertex gdal_qh_pointvertex
+static gdal_setT   * qh_pointvertex();
+#define qh_setvoronoi_all gdal_qh_setvoronoi_all
+static void qh_setvoronoi_all();
+#define qh_triangulate gdal_qh_triangulate
+static void qh_triangulate();
+/*#define qh_rboxpoints gdal_qh_rboxpoints*/
+/*static int qh_rboxpoints();*/
+/*#define qh_errexit_rbox gdal_qh_errexit_rbox*/
+/*static void qh_errexit_rbox();*/
+#define qh_collectstatistics gdal_qh_collectstatistics
+static void qh_collectstatistics();
+#define qh_printallstatistics gdal_qh_printallstatistics
+static void qh_printallstatistics();
+/*#define machines gdal_machines*/
+/*static gdal_of machines();*/
+#define qh_memalloc gdal_qh_memalloc
+static void * qh_memalloc();
+#define qh_memfree gdal_qh_memfree
+static void qh_memfree();
+#define qh_memfreeshort gdal_qh_memfreeshort
+static void qh_memfreeshort();
+#define qh_meminit gdal_qh_meminit
+static void qh_meminit();
+#define qh_meminitbuffers gdal_qh_meminitbuffers
+static void qh_meminitbuffers();
+#define qh_memsetup gdal_qh_memsetup
+static void qh_memsetup();
+#define qh_memsize gdal_qh_memsize
+static void qh_memsize();
+#define qh_memstatistics gdal_qh_memstatistics
+static void qh_memstatistics();
+#define qh_memtotal gdal_qh_memtotal
+static void qh_memtotal();
+/*#define qh_mergefacet gdal_qh_mergefacet*/
+/*static gdal_if qh_mergefacet();*/
+#define qh_premerge gdal_qh_premerge
+static void qh_premerge();
+#define qh_postmerge gdal_qh_postmerge
+static void qh_postmerge();
+#define qh_all_merges gdal_qh_all_merges
+static void qh_all_merges();
+#define qh_appendmergeset gdal_qh_appendmergeset
+static void qh_appendmergeset();
+#define qh_basevertices gdal_qh_basevertices
+static gdal_setT   * qh_basevertices();
+#define qh_checkconnect gdal_qh_checkconnect
+static void qh_checkconnect();
+#define qh_checkzero gdal_qh_checkzero
+static gdal_boolT qh_checkzero();
+#define qh_compareangle gdal_qh_compareangle
+static int qh_compareangle();
+#define qh_comparemerge gdal_qh_comparemerge
+static int qh_comparemerge();
+#define qh_comparevisit gdal_qh_comparevisit
+static int qh_comparevisit();
+#define qh_copynonconvex gdal_qh_copynonconvex
+static void qh_copynonconvex();
+#define qh_degen_redundant_facet gdal_qh_degen_redundant_facet
+static void qh_degen_redundant_facet();
+#define qh_degen_redundant_neighbors gdal_qh_degen_redundant_neighbors
+static void qh_degen_redundant_neighbors();
+#define qh_find_newvertex gdal_qh_find_newvertex
+static gdal_vertexT * qh_find_newvertex();
+#define qh_findbest_test gdal_qh_findbest_test
+static void qh_findbest_test();
+#define qh_findbestneighbor gdal_qh_findbestneighbor
+static gdal_facetT * qh_findbestneighbor();
+#define qh_flippedmerges gdal_qh_flippedmerges
+static void qh_flippedmerges();
+#define qh_forcedmerges gdal_qh_forcedmerges
+static void qh_forcedmerges();
+#define qh_getmergeset gdal_qh_getmergeset
+static void qh_getmergeset();
+#define qh_getmergeset_initial gdal_qh_getmergeset_initial
+static void qh_getmergeset_initial();
+#define qh_hashridge gdal_qh_hashridge
+static void qh_hashridge();
+#define qh_hashridge_find gdal_qh_hashridge_find
+static gdal_ridgeT * qh_hashridge_find();
+#define qh_makeridges gdal_qh_makeridges
+static void qh_makeridges();
+#define qh_mark_dupridges gdal_qh_mark_dupridges
+static void qh_mark_dupridges();
+#define qh_maydropneighbor gdal_qh_maydropneighbor
+static void qh_maydropneighbor();
+#define qh_merge_degenredundant gdal_qh_merge_degenredundant
+static int qh_merge_degenredundant();
+#define qh_merge_nonconvex gdal_qh_merge_nonconvex
+static void qh_merge_nonconvex();
+#define qh_mergecycle gdal_qh_mergecycle
+static void qh_mergecycle();
+#define qh_mergecycle_all gdal_qh_mergecycle_all
+static void qh_mergecycle_all();
+#define qh_mergecycle_facets gdal_qh_mergecycle_facets
+static void qh_mergecycle_facets();
+#define qh_mergecycle_neighbors gdal_qh_mergecycle_neighbors
+static void qh_mergecycle_neighbors();
+#define qh_mergecycle_ridges gdal_qh_mergecycle_ridges
+static void qh_mergecycle_ridges();
+#define qh_mergecycle_vneighbors gdal_qh_mergecycle_vneighbors
+static void qh_mergecycle_vneighbors();
+#define qh_mergefacet gdal_qh_mergefacet
+static void qh_mergefacet();
+#define qh_mergefacet2d gdal_qh_mergefacet2d
+static void qh_mergefacet2d();
+#define qh_mergeneighbors gdal_qh_mergeneighbors
+static void qh_mergeneighbors();
+#define qh_mergeridges gdal_qh_mergeridges
+static void qh_mergeridges();
+#define qh_mergesimplex gdal_qh_mergesimplex
+static void qh_mergesimplex();
+#define qh_mergevertex_del gdal_qh_mergevertex_del
+static void qh_mergevertex_del();
+#define qh_mergevertex_neighbors gdal_qh_mergevertex_neighbors
+static void qh_mergevertex_neighbors();
+#define qh_mergevertices gdal_qh_mergevertices
+static void qh_mergevertices();
+#define qh_neighbor_intersections gdal_qh_neighbor_intersections
+static gdal_setT   * qh_neighbor_intersections();
+#define qh_newvertices gdal_qh_newvertices
+static void qh_newvertices();
+#define qh_reducevertices gdal_qh_reducevertices
+static gdal_boolT qh_reducevertices();
+#define qh_redundant_vertex gdal_qh_redundant_vertex
+static gdal_vertexT * qh_redundant_vertex();
+#define qh_remove_extravertices gdal_qh_remove_extravertices
+static gdal_boolT qh_remove_extravertices();
+#define qh_rename_sharedvertex gdal_qh_rename_sharedvertex
+static gdal_vertexT * qh_rename_sharedvertex();
+#define qh_renameridgevertex gdal_qh_renameridgevertex
+static void qh_renameridgevertex();
+#define qh_renamevertex gdal_qh_renamevertex
+static void qh_renamevertex();
+#define qh_test_appendmerge gdal_qh_test_appendmerge
+static gdal_boolT qh_test_appendmerge();
+#define qh_test_vneighbors gdal_qh_test_vneighbors
+static gdal_boolT qh_test_vneighbors();
+#define qh_tracemerge gdal_qh_tracemerge
+static void qh_tracemerge();
+#define qh_tracemerging gdal_qh_tracemerging
+static void qh_tracemerging();
+#define qh_updatetested gdal_qh_updatetested
+static void qh_updatetested();
+#define qh_vertexridges gdal_qh_vertexridges
+static gdal_setT   * qh_vertexridges();
+#define qh_vertexridges_facet gdal_qh_vertexridges_facet
+static void qh_vertexridges_facet();
+#define qh_willdelete gdal_qh_willdelete
+static void qh_willdelete();
+#define qh_appendfacet gdal_qh_appendfacet
+static void qh_appendfacet();
+#define qh_appendvertex gdal_qh_appendvertex
+static void qh_appendvertex();
+#define qh_attachnewfacets gdal_qh_attachnewfacets
+static void qh_attachnewfacets();
+#define qh_checkflipped gdal_qh_checkflipped
+static gdal_boolT qh_checkflipped();
+#define qh_delfacet gdal_qh_delfacet
+static void qh_delfacet();
+#define qh_deletevisible gdal_qh_deletevisible
+static void qh_deletevisible();
+#define qh_facetintersect gdal_qh_facetintersect
+static gdal_setT   * qh_facetintersect();
+#define qh_gethash gdal_qh_gethash
+static int qh_gethash();
+#define qh_makenewfacet gdal_qh_makenewfacet
+static gdal_facetT * qh_makenewfacet();
+#define qh_makenewplanes gdal_qh_makenewplanes
+static void qh_makenewplanes();
+#define qh_makenew_nonsimplicial gdal_qh_makenew_nonsimplicial
+static gdal_facetT * qh_makenew_nonsimplicial();
+#define qh_makenew_simplicial gdal_qh_makenew_simplicial
+static gdal_facetT * qh_makenew_simplicial();
+#define qh_matchneighbor gdal_qh_matchneighbor
+static void qh_matchneighbor();
+#define qh_matchnewfacets gdal_qh_matchnewfacets
+static void qh_matchnewfacets();
+#define qh_matchvertices gdal_qh_matchvertices
+static gdal_boolT qh_matchvertices();
+#define qh_newfacet gdal_qh_newfacet
+static gdal_facetT * qh_newfacet();
+#define qh_newridge gdal_qh_newridge
+static gdal_ridgeT * qh_newridge();
+#define qh_pointid gdal_qh_pointid
+static int qh_pointid();
+#define qh_removefacet gdal_qh_removefacet
+static void qh_removefacet();
+#define qh_removevertex gdal_qh_removevertex
+static void qh_removevertex();
+#define qh_updatevertices gdal_qh_updatevertices
+static void qh_updatevertices();
+#define qh_addhash gdal_qh_addhash
+static void qh_addhash();
+#define qh_check_bestdist gdal_qh_check_bestdist
+static void qh_check_bestdist();
+#define qh_check_maxout gdal_qh_check_maxout
+static void qh_check_maxout();
+#define qh_check_output gdal_qh_check_output
+static void qh_check_output();
+#define qh_check_point gdal_qh_check_point
+static void qh_check_point();
+#define qh_check_points gdal_qh_check_points
+static void qh_check_points();
+#define qh_checkconvex gdal_qh_checkconvex
+static void qh_checkconvex();
+#define qh_checkfacet gdal_qh_checkfacet
+static void qh_checkfacet();
+#define qh_checkflipped_all gdal_qh_checkflipped_all
+static void qh_checkflipped_all();
+#define qh_checkpolygon gdal_qh_checkpolygon
+static void qh_checkpolygon();
+#define qh_checkvertex gdal_qh_checkvertex
+static void qh_checkvertex();
+#define qh_clearcenters gdal_qh_clearcenters
+static void qh_clearcenters();
+#define qh_createsimplex gdal_qh_createsimplex
+static void qh_createsimplex();
+#define qh_delridge gdal_qh_delridge
+static void qh_delridge();
+#define qh_delvertex gdal_qh_delvertex
+static void qh_delvertex();
+#define qh_facet3vertex gdal_qh_facet3vertex
+static gdal_setT   * qh_facet3vertex();
+#define qh_findbestfacet gdal_qh_findbestfacet
+static gdal_facetT * qh_findbestfacet();
+#define qh_findbestlower gdal_qh_findbestlower
+static gdal_facetT * qh_findbestlower();
+#define qh_findfacet_all gdal_qh_findfacet_all
+static gdal_facetT * qh_findfacet_all();
+#define qh_findgood gdal_qh_findgood
+static int qh_findgood();
+#define qh_findgood_all gdal_qh_findgood_all
+static void qh_findgood_all();
+#define qh_furthestnext gdal_qh_furthestnext
+static void qh_furthestnext();
+#define qh_furthestout gdal_qh_furthestout
+static void qh_furthestout();
+#define qh_infiniteloop gdal_qh_infiniteloop
+static void qh_infiniteloop();
+#define qh_initbuild gdal_qh_initbuild
+static void qh_initbuild();
+#define qh_initialhull gdal_qh_initialhull
+static void qh_initialhull();
+#define qh_initialvertices gdal_qh_initialvertices
+static gdal_setT   * qh_initialvertices();
+#define qh_isvertex gdal_qh_isvertex
+static gdal_vertexT * qh_isvertex();
+#define qh_makenewfacets gdal_qh_makenewfacets
+static gdal_vertexT * qh_makenewfacets();
+#define qh_matchduplicates gdal_qh_matchduplicates
+static void qh_matchduplicates();
+#define qh_nearcoplanar gdal_qh_nearcoplanar
+static void qh_nearcoplanar();
+#define qh_nearvertex gdal_qh_nearvertex
+static gdal_vertexT * qh_nearvertex();
+#define qh_newhashtable gdal_qh_newhashtable
+static int qh_newhashtable();
+#define qh_newvertex gdal_qh_newvertex
+static gdal_vertexT * qh_newvertex();
+#define qh_nextridge3d gdal_qh_nextridge3d
+static gdal_ridgeT * qh_nextridge3d();
+#define qh_outcoplanar gdal_qh_outcoplanar
+static void qh_outcoplanar();
+#define qh_point gdal_qh_point
+static gdal_pointT * qh_point();
+#define qh_point_add gdal_qh_point_add
+static void qh_point_add();
+#define qh_pointfacet gdal_qh_pointfacet
+static gdal_setT   * qh_pointfacet();
+#define qh_pointvertex gdal_qh_pointvertex
+static gdal_setT   * qh_pointvertex();
+#define qh_prependfacet gdal_qh_prependfacet
+static void qh_prependfacet();
+#define qh_printhashtable gdal_qh_printhashtable
+static void qh_printhashtable();
+#define qh_printlists gdal_qh_printlists
+static void qh_printlists();
+#define qh_resetlists gdal_qh_resetlists
+static void qh_resetlists();
+#define qh_setvoronoi_all gdal_qh_setvoronoi_all
+static void qh_setvoronoi_all();
+#define qh_triangulate gdal_qh_triangulate
+static void qh_triangulate();
+#define qh_triangulate_facet gdal_qh_triangulate_facet
+static void qh_triangulate_facet();
+#define qh_triangulate_link gdal_qh_triangulate_link
+static void qh_triangulate_link();
+#define qh_triangulate_mirror gdal_qh_triangulate_mirror
+static void qh_triangulate_mirror();
+#define qh_triangulate_null gdal_qh_triangulate_null
+static void qh_triangulate_null();
+#define qh_vertexintersect gdal_qh_vertexintersect
+static void qh_vertexintersect();
+#define qh_vertexintersect_new gdal_qh_vertexintersect_new
+static gdal_setT   * qh_vertexintersect_new();
+#define qh_vertexneighbors gdal_qh_vertexneighbors
+static void qh_vertexneighbors();
+#define qh_vertexsubset gdal_qh_vertexsubset
+static gdal_boolT qh_vertexsubset();
+#define qh_qhull gdal_qh_qhull
+static void qh_qhull();
+#define qh_addpoint gdal_qh_addpoint
+static gdal_boolT qh_addpoint();
+#define qh_buildhull gdal_qh_buildhull
+static void qh_buildhull();
+#define qh_buildtracing gdal_qh_buildtracing
+static void qh_buildtracing();
+#define qh_build_withrestart gdal_qh_build_withrestart
+static void qh_build_withrestart();
+#define qh_errexit2 gdal_qh_errexit2
+static void qh_errexit2();
+#define qh_findhorizon gdal_qh_findhorizon
+static void qh_findhorizon();
+#define qh_nextfurthest gdal_qh_nextfurthest
+static gdal_pointT * qh_nextfurthest();
+#define qh_partitionall gdal_qh_partitionall
+static void qh_partitionall();
+#define qh_partitioncoplanar gdal_qh_partitioncoplanar
+static void qh_partitioncoplanar();
+#define qh_partitionpoint gdal_qh_partitionpoint
+static void qh_partitionpoint();
+#define qh_partitionvisible gdal_qh_partitionvisible
+static void qh_partitionvisible();
+#define qh_precision gdal_qh_precision
+static void qh_precision();
+#define qh_printsummary gdal_qh_printsummary
+static void qh_printsummary();
+#define qh_appendprint gdal_qh_appendprint
+static void qh_appendprint();
+#define qh_freebuild gdal_qh_freebuild
+static void qh_freebuild();
+#define qh_freebuffers gdal_qh_freebuffers
+static void qh_freebuffers();
+/*#define qh_initbuffers gdal_qh_initbuffers*/
+/*static void qh_initbuffers();*/
+#define qh_allstatA gdal_qh_allstatA
+static void qh_allstatA();
+#define qh_allstatB gdal_qh_allstatB
+static void qh_allstatB();
+#define qh_allstatC gdal_qh_allstatC
+static void qh_allstatC();
+#define qh_allstatD gdal_qh_allstatD
+static void qh_allstatD();
+#define qh_allstatE gdal_qh_allstatE
+static void qh_allstatE();
+#define qh_allstatE2 gdal_qh_allstatE2
+static void qh_allstatE2();
+#define qh_allstatF gdal_qh_allstatF
+static void qh_allstatF();
+#define qh_allstatG gdal_qh_allstatG
+static void qh_allstatG();
+#define qh_allstatH gdal_qh_allstatH
+static void qh_allstatH();
+#define qh_freebuffers gdal_qh_freebuffers
+static void qh_freebuffers();
+/*#define qh_initbuffers gdal_qh_initbuffers*/
+/*static void qh_initbuffers();*/
+#define qh_setaddsorted gdal_qh_setaddsorted
+static void qh_setaddsorted();
+#define qh_setaddnth gdal_qh_setaddnth
+static void qh_setaddnth();
+#define qh_setappend gdal_qh_setappend
+static void qh_setappend();
+#define qh_setappend_set gdal_qh_setappend_set
+static void qh_setappend_set();
+#define qh_setappend2ndlast gdal_qh_setappend2ndlast
+static void qh_setappend2ndlast();
+#define qh_setcheck gdal_qh_setcheck
+static void qh_setcheck();
+#define qh_setcompact gdal_qh_setcompact
+static void qh_setcompact();
+#define qh_setcopy gdal_qh_setcopy
+static gdal_setT * qh_setcopy();
+#define qh_setdel gdal_qh_setdel
+static void * qh_setdel();
+#define qh_setdellast gdal_qh_setdellast
+static void * qh_setdellast();
+#define qh_setdelnth gdal_qh_setdelnth
+static void * qh_setdelnth();
+#define qh_setdelnthsorted gdal_qh_setdelnthsorted
+static void * qh_setdelnthsorted();
+#define qh_setdelsorted gdal_qh_setdelsorted
+static void * qh_setdelsorted();
+#define qh_setduplicate gdal_qh_setduplicate
+static gdal_setT * qh_setduplicate();
+#define qh_setequal gdal_qh_setequal
+static int qh_setequal();
+#define qh_setequal_except gdal_qh_setequal_except
+static int qh_setequal_except();
+#define qh_setequal_skip gdal_qh_setequal_skip
+static int qh_setequal_skip();
+#define qh_setendpointer gdal_qh_setendpointer
+static void ** qh_setendpointer();
+#define qh_setfree gdal_qh_setfree
+static void qh_setfree();
+#define qh_setfree2 gdal_qh_setfree2
+static void qh_setfree2();
+#define qh_setfreelong gdal_qh_setfreelong
+static void qh_setfreelong();
+#define qh_setin gdal_qh_setin
+static int qh_setin();
+#define qh_setindex gdal_qh_setindex
+static int qh_setindex();
+#define qh_setlarger gdal_qh_setlarger
+static void qh_setlarger();
+#define qh_setlast gdal_qh_setlast
+static void * qh_setlast();
+#define qh_setnew gdal_qh_setnew
+static gdal_setT * qh_setnew();
+#define qh_setnew_delnthsorted gdal_qh_setnew_delnthsorted
+static gdal_setT * qh_setnew_delnthsorted();
+#define qh_setprint gdal_qh_setprint
+static void qh_setprint();
+#define qh_setreplace gdal_qh_setreplace
+static void qh_setreplace();
+#define qh_setsize gdal_qh_setsize
+static int qh_setsize();
+#define qh_settemp gdal_qh_settemp
+static gdal_setT * qh_settemp();
+#define qh_settempfree gdal_qh_settempfree
+static void qh_settempfree();
+#define qh_settempfree_all gdal_qh_settempfree_all
+static void qh_settempfree_all();
+#define qh_settemppop gdal_qh_settemppop
+static gdal_setT * qh_settemppop();
+#define qh_settemppush gdal_qh_settemppush
+static void qh_settemppush();
+#define qh_settruncate gdal_qh_settruncate
+static void qh_settruncate();
+#define qh_setunique gdal_qh_setunique
+static int qh_setunique();
+#define qh_setzero gdal_qh_setzero
+static void qh_setzero();
+#define qh_argv_to_command gdal_qh_argv_to_command
+static int qh_argv_to_command();
+#define qh_argv_to_command_size gdal_qh_argv_to_command_size
+static int qh_argv_to_command_size();
+#define qh_rand gdal_qh_rand
+static int qh_rand();
+#define qh_srand gdal_qh_srand
+static void qh_srand();
+#define qh_randomfactor gdal_qh_randomfactor
+static gdal_realT qh_randomfactor();
+#define qh_randommatrix gdal_qh_randommatrix
+static void qh_randommatrix();
+#define qh_strtol gdal_qh_strtol
+static int qh_strtol();
+#define qh_strtod gdal_qh_strtod
+static double qh_strtod();
+#define qh_allstatA gdal_qh_allstatA
+static void qh_allstatA();
+#define qh_allstatB gdal_qh_allstatB
+static void qh_allstatB();
+#define qh_allstatC gdal_qh_allstatC
+static void qh_allstatC();
+#define qh_allstatD gdal_qh_allstatD
+static void qh_allstatD();
+#define qh_allstatE gdal_qh_allstatE
+static void qh_allstatE();
+#define qh_allstatE2 gdal_qh_allstatE2
+static void qh_allstatE2();
+#define qh_allstatF gdal_qh_allstatF
+static void qh_allstatF();
+#define qh_allstatG gdal_qh_allstatG
+static void qh_allstatG();
+#define qh_allstatH gdal_qh_allstatH
+static void qh_allstatH();
+#define qh_allstatI gdal_qh_allstatI
+static void qh_allstatI();
+#define qh_allstatistics gdal_qh_allstatistics
+static void qh_allstatistics();
+#define qh_collectstatistics gdal_qh_collectstatistics
+static void qh_collectstatistics();
+#define qh_freestatistics gdal_qh_freestatistics
+static void qh_freestatistics();
+#define qh_initstatistics gdal_qh_initstatistics
+static void qh_initstatistics();
+#define qh_newstats gdal_qh_newstats
+static gdal_boolT qh_newstats();
+#define qh_nostatistic gdal_qh_nostatistic
+static gdal_boolT qh_nostatistic();
+#define qh_printallstatistics gdal_qh_printallstatistics
+static void qh_printallstatistics();
+#define qh_printstatistics gdal_qh_printstatistics
+static void qh_printstatistics();
+#define qh_printstatlevel gdal_qh_printstatlevel
+static void qh_printstatlevel();
+#define qh_printstats gdal_qh_printstats
+static void qh_printstats();
+#define qh_stddev gdal_qh_stddev
+static gdal_realT qh_stddev();
+
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable : 4324 )
+#pragma warning( disable : 4032 )
+#pragma warning( disable : 4306 )  /* e.g 'type cast' : conversion from 'long' to 'facetT *' of greater size */
+#endif
+
+#include "libqhull.h"
+#include "libqhull.c"
+#include "poly.c"
+#include "poly2.c"
+#include "mem.c"
+#include "user.c"
+#include "global.c"
+/*#include "userprintf.c"*/
+#include "random.c"
+#include "qset.c"
+#include "io.c"
+#include "usermem.c"
+#include "geom.c"
+#include "geom2.c"
+#include "stat.c"
+#include "merge.c"
+
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
+
+/* Replaces userprintf.c implementation */
+static void qh_fprintf(CPL_UNUSED FILE *fp, CPL_UNUSED int msgcode, const char *fmt, ... )
+{
+    va_list args;
+    va_start(args, fmt);
+    CPLErrorV(CE_Warning, CPLE_AppDefined, fmt, args);
+    va_end(args);
+}
+
+#endif
diff --git a/alg/libqhull/COPYING.txt b/alg/libqhull/COPYING.txt
new file mode 100644
index 0000000..7a73d9f
--- /dev/null
+++ b/alg/libqhull/COPYING.txt
@@ -0,0 +1,38 @@
+                    Qhull, Copyright (c) 1993-2012
+                    
+                            C.B. Barber
+                           Arlington, MA 
+                          
+                               and
+
+       The National Science and Technology Research Center for
+        Computation and Visualization of Geometric Structures
+                        (The Geometry Center)
+                       University of Minnesota
+
+                       email: qhull at qhull.org
+
+This software includes Qhull from C.B. Barber and The Geometry Center.  
+Qhull is copyrighted as noted above.  Qhull is free software and may 
+be obtained via http from www.qhull.org.  It may be freely copied, modified, 
+and redistributed under the following conditions:
+
+1. All copyright notices must remain intact in all files.
+
+2. A copy of this text file must be distributed along with any copies 
+   of Qhull that you redistribute; this includes copies that you have 
+   modified, or copies of programs or other software products that 
+   include Qhull.
+
+3. If you modify Qhull, you must include a notice giving the
+   name of the person performing the modification, the date of
+   modification, and the reason for such modification.
+
+4. When distributing modified versions of Qhull, or other software 
+   products that include Qhull, you must provide notice that the original 
+   source code may be obtained as noted above.
+
+5. There is no warranty or other guarantee of fitness for Qhull, it is 
+   provided solely "as is".  Bug reports or fixes may be sent to 
+   qhull_bug at qhull.org; the authors may or may not act on them as 
+   they desire.
diff --git a/alg/libqhull/README.txt b/alg/libqhull/README.txt
new file mode 100644
index 0000000..843ec44
--- /dev/null
+++ b/alg/libqhull/README.txt
@@ -0,0 +1,523 @@
+Name
+
+      qhull, rbox         2012.1     2012/02/18
+  
+Convex hull, Delaunay triangulation, Voronoi diagrams, Halfspace intersection
+ 
+      Documentation:
+        html/index.htm
+        http://www.qhull.org/html
+
+      Available from:
+        <http://www.qhull.org>
+        <git at gitorious.org:qhull/qhull.git>
+        <http://packages.debian.org/sid/libqhull5> [out-of-date]
+ 
+      News and a paper:
+        <http://www.qhull.org/news>
+        <http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.117.405>
+
+     Version 1 (simplicial only):
+        <http://www.qhull.org/download/qhull-1.0.tar.gz>
+       
+
+Purpose
+
+  Qhull is a general dimension convex hull program that reads a set 
+  of points from stdin, and outputs the smallest convex set that contains 
+  the points to stdout.  It also generates Delaunay triangulations, Voronoi 
+  diagrams, furthest-site Voronoi diagrams, and halfspace intersections
+  about a point.
+
+  Rbox is a useful tool in generating input for Qhull; it generates 
+  hypercubes, diamonds, cones, circles, simplices, spirals, 
+  lattices, and random points.
+  
+  Qhull produces graphical output for Geomview.  This helps with
+  understanding the output. <http://www.geomview.org>
+
+Environment requirements
+
+  Qhull and rbox should run on all 32-bit and 64-bit computers.  Use
+  an ANSI C or C++ compiler to compile the program.  The software is 
+  self-contained.  It comes with examples and test scripts.
+  
+  Qhull's C++ interface uses the STL.  The C++ test program uses QTestLib 
+  from Nokia's Qt Framework.  Qhull's C++ interface may change without 
+  notice.  Eventually, it will move into the qhull shared library.
+  
+  Qhull is copyrighted software.  Please read COPYING.txt and REGISTER.txt
+  before using or distributing Qhull.
+
+To cite Qhull, please use
+
+  Barber, C.B., Dobkin, D.P., and Huhdanpaa, H.T., "The Quickhull 
+  algorithm for convex hulls," ACM Trans. on Mathematical Software,
+  22(4):469-483, Dec 1996, http://www.qhull.org.
+
+To contribute to Qhull
+
+  Qhull is on Gitorious (http://gitorious.org:qhull, git at gitorious.org:qhull/qhull.git)
+  
+  For internal documentation, see html/qh-code.htm
+
+To install Qhull
+
+  Qhull is precompiled for Windows, otherwise it needs compilation.
+  
+  Besides makefiles for gcc, qhull includes CMakeLists.txt for CMake, 
+  vcproj/sln files for Microsoft Visual Studio, and .pro files for Qt Creator.
+  It compiles with mingw.
+  
+  Install and build instructions follow.  
+  
+  See the end of this document for a list of distributed files.
+
+-----------------
+Installing Qhull on Windows
+
+  The zip file contains rbox.exe, qhull.exe, qconvex.exe, qdelaunay.exe, 
+  qhalf.exe, qvoronoi.exe, testqset.exe, user_eg*.exe, documentation files, 
+  and source files.
+  
+  To install Qhull:
+  - Unzip the files into a directory.  You may use WinZip32 <www.hotfiles.com>
+  - Click on QHULL-GO or open a command window into Qhull's bin directory.
+    
+  To uninstall Qhull
+  - Delete the qhull directory
+  
+  To learn about Qhull:
+  - Execute 'qconvex' for a synopsis and examples.
+  - Execute 'rbox 10 | qconvex' to compute the convex hull of 10 random points.
+  - Execute 'rbox 10 | qconvex i TO file' to write results to 'file'.
+  - Browse the documentation: qhull\html\index.htm
+  - If an error occurs, Windows sends the error to stdout instead of stderr.
+    Use 'TO xxx' to send normal output to xxx and error output to stdout
+
+  To improve the command window
+  - Double-click the window bar to increase the size of the window
+  - Right-click the window bar
+  - Select Properties
+  - Check QuickEdit Mode
+    Select text with right-click or Enter
+    Paste text with right-click
+  - Change Font to Lucinda Console
+  - Change Layout to Screen Buffer Height 999, Window Size Height 55
+  - Change Colors to Screen Background White, Screen Text Black
+  - Click OK
+  - Select 'Modify shortcut that started this window', then OK
+
+  If you use qhull a lot, install MSYS (www.mingw.org),
+    Road Bash (www.qhull.org/bash), or Cygwin (www.cygwin.com).
+
+-----------------
+Installing Qhull on Unix with gcc
+
+  To build Qhull, static libraries, shared library, and C++ interface
+  - Extract Qhull from qhull...tgz or qhull...zip
+  - make
+  - export LD_LIBRARY_PATH=$PWD/lib:$LD_LIBRARY_PATH
+
+  Or, to build Qhull and libqhullstatic.a
+  - Extract Qhull from qhull...tgz or qhull...zip
+  - cd src/libqhull
+  - make
+
+  The Makefiles may be edited for other compilers.
+  If 'testqset' exits with an error, qhull is broken
+  
+-----------------
+Installing Qhull with CMake 2.6 or later
+
+  To build Qhull, static libraries, shared library, and C++ interface
+  - Extract Qhull from qhull...tgz or qhull...zip
+  - cd build
+  - cmake ..
+  - make
+  - make install
+  
+  On Windows, CMake installs to C:/Program Files/qhull
+  See CMakeLists.txt for further build instructions
+
+-----------------
+Installing Qhull with Qt
+
+  To build Qhull, static libraries, shared library, C++ interface, and C++ test
+  - Extract Qhull from qhull...tgz or qhull...zip
+  - cd src
+  - qmake
+  - make
+  
+-----------------
+Installing Qhull with Autoconf [WARNING out-of-date]
+
+  The tar.gz tarball contains documentation, source files, 
+  and a config directory [R. Laboissiere].
+
+  [Nov 2011] Qhull 2009.1.2 does not include the C++ interface
+  
+  To install Qhull
+  - Extract the files
+  - ./configure
+  - make
+  - make install
+
+-------------------
+Working with Qhull's C++ interface
+
+  Qhull's C++ interface is likely to change.  Stay current with Gitorious.
+
+  To clone Qhull's next branch from http://gitorious.org/qhull
+    git init
+    git clone git://gitorious.org/qhull/qhull.git
+    cd qhull
+    git checkout next
+    ...
+    git pull origin next
+
+------------------
+Compiling Qhull with Microsoft Visual C++ 2005 or later
+
+  To compile Qhull with Microsoft Visual C++
+  - Extract Qhull from Gitorious, qhull...tgz, or qhull...zip
+  - Load solution build/qhull.sln 
+  - Build
+  - Project qhulltest requires Qt for DevStudio (http://qt.nokia.com/downloads)
+    Set the QTDIR environment variable to your Qt directory (e.g., c:/qt/4.7.4)
+    If incorrect, precompile will fail with 'Can not locate the file specified'
+
+-----------------
+Compiling Qhull with Qt Creator
+
+  Qt (http://qt.nokia.com) is a C++ framework for Windows, Linux, and Macintosh
+
+  Qhull uses QTestLib to test qhull's C++ interface (qhulltest)
+  
+  To compile Qhull with Qt Creator
+  - Extract Qhull from Gitorious, qhull...tgz, or qhull...zip
+  - Download the Qt SDK from Nokia (http://qt.nokia.com/downloads)
+  - Start Qt Creator
+  - Load src/qhull-all.pro
+  - Build
+
+-----------------
+Compiling Qhull with mingw on Windows
+
+  To compile Qhull with MINGW
+  - Extract Qhull from Gitorious, qhull...tgz, or qhull...zip
+  - Install Road Bash (http://www.qhull.org/bash)
+    or install MSYS (http://www.mingw.org/wiki/msys)
+  - Install MINGW (http://www.mingw.org/).  Mingw is included with Qt SDK.  
+  - make
+  
+-----------------
+Compiling Qhull with cygwin on Windows
+
+  To compile Qhull with cygwin
+  - Extract Qhull from Gitorious, qhull...tgz, or qhull...zip
+  - Install cygwin (http://www.cygwin.com)
+  - Include packages for gcc, make, ar, and ln
+  - make
+
+-----------------
+Compiling from Makfile without gcc
+
+  The file, qhull-src.tgz, contains documentation and source files for
+  qhull and rbox.  
+  
+  To unpack the gzip file
+  - tar zxf qhull-src.tgz
+  - cd qhull
+  
+  Compiling qhull and rbox with Makefile
+  - in Makefile, check the CC, CCOPTS1, PRINTMAN, and PRINTC defines
+      - the defaults are gcc and enscript
+      - CCOPTS1 should include the ANSI flag.  It defines __STDC__
+  - in user.h, check the definitions of qh_SECticks and qh_CPUclock.
+      - use '#define qh_CLOCKtype 2' for timing runs longer than 1 hour
+  - type: make 
+      - this builds: qhull qconvex qdelaunay qhalf qvoronoi rbox libqhull.a
+  - type: make doc
+      - this prints the man page
+      - See also qhull/html/index.htm
+  - if your compiler reports many errors, it is probably not a ANSI C compiler
+      - you will need to set the -ansi switch or find another compiler
+  - if your compiler warns about missing prototypes for fprintf() etc.
+      - this is ok, your compiler should have these in stdio.h
+  - if your compiler warns about missing prototypes for memset() etc.
+      - include memory.h in qhull_a.h
+  - if your compiler reports "global.c: storage size of 'qh_qh' isn't known"
+      - delete the initializer "={0}" in global.c, stat.c and mem.c
+  - if your compiler warns about "stat.c: improper initializer"
+      - this is ok, the initializer is not used
+  - if you have trouble building libqhull.a with 'ar'
+      - try 'make -f Makefile.txt qhullx' 
+  - if the code compiles, the qhull test case will automatically execute
+  - if an error occurs, there's an incompatibility between machines
+      - If you can, try a different compiler 
+      - You can turn off the Qhull memory manager with qh_NOmem in mem.h
+      - You can turn off compiler optimization (-O2 in Makefile)
+      - If you find the source of the problem, please let us know
+  - to install the programs and their man pages:
+      - define MANDIR and BINDIR
+      - type 'make install'
+
+  - if you have Geomview (www.geomview.org)
+       - try  'rbox 100 | qconvex G >a' and load 'a' into Geomview
+       - run 'q_eg' for Geomview examples of Qhull output (see qh-eg.htm)
+
+------------------
+Compiling on other machines and compilers
+
+  Qhull compiles with Borland C++ 5.0 bcc32.  A Makefile is included.
+  Execute 'make -f Mborland'.  If you use the Borland IDE, set the ANSI
+  option in Options:Project:Compiler:Source:Language-compliance.
+  
+  Qhull compiles with Borland C++ 4.02 for Win32 and DOS Power Pack.  
+  Use 'make -f Mborland -D_DPMI'.  Qhull 1.0 compiles with Borland 
+  C++ 4.02.  For rbox 1.0, use "bcc32 -WX -w- -O2-e -erbox -lc rbox.c".  
+  Use the same options for Qhull 1.0. [D. Zwick]
+  
+  Qhull compiles with Metrowerks C++ 1.7 with the ANSI option.
+  If you turn on full warnings, the compiler will report a number of 
+  unused variables, variables set but not used, and dead code.  These are
+  intentional.  For example, variables may be initialized (unnecessarily)
+  to prevent warnings about possible use of uninitialized variables.  
+
+  Qhull compiles on the Power Macintosh with Metrowerk's C compiler.
+  It uses the SIOUX interface to read point coordinates and return output.
+  There is no graphical output.  For project files, see 'Compiling a
+  custom build'.  Instead of using SIOUX, Qhull may be embedded within an
+  application.  
+
+  Some users have reported problems with compiling Qhull under Irix 5.1.  It
+  compiles under other versions of Irix. 
+  
+  If you have troubles with the memory manager, you can turn it off by
+  defining qh_NOmem in mem.h.
+
+-----------------
+Distributed files
+
+  README.txt           // Instructions for installing Qhull 
+  REGISTER.txt         // Qhull registration 
+  COPYING.txt          // Copyright notice 
+  QHULL-GO.lnk         // Windows icon for eg/qhull-go.bat
+  Announce.txt         // Announcement 
+  CMakeLists.txt       // CMake build file (2.6 or later)
+  File_id.diz          // Package descriptor
+  index.htm            // Home page 
+  Makefile             // Makefile for gcc and other compilers
+  qhull*.md5sum        // md5sum for all files
+
+  bin/*		       // Qhull executables and dll (.zip only)
+  build/qhull.sln      // DevStudio solution and project files (2005 or later)
+  build/*.vcproj
+  config/*             // Autoconf files for creating configure (Unix only)
+  eg/*                 // Test scripts and geomview files from q_eg
+  html/index.htm       // Manual
+  html/qh-faq.htm      // Frequently asked questions
+  html/qh-get.htm      // Download page
+  html/qhull-cpp.xml   // C++ style notes as a Road FAQ (www.qhull.org/road)
+  src/Changes.txt      // Change history for Qhull and rbox 
+  src/qhull-all.pro    // Qt project
+
+eg/ 
+  q_eg                 // shell script for Geomview examples (eg.01.cube)
+  q_egtest             // shell script for Geomview test examples
+  q_test               // shell script to test qhull
+  q_test-ok.txt        // output from q_test
+  qhulltest-ok.txt     // output from qhulltest (Qt only)
+
+rbox consists of (bin, html):
+  rbox.exe             // Win32 executable (.zip only) 
+  rbox.htm             // html manual 
+  rbox.man             // Unix man page 
+  rbox.txt
+
+qhull consists of (bin, html):
+  qhull.exe            // Win32 executables and dlls (.zip only) 
+  qconvex.exe
+  qdelaunay.exe
+  qhalf.exe
+  qvoronoi.exe
+  qhull.dll
+  qhull_p.dll
+  qhull-go.bat         // command window
+  qconvex.htm          // html manual
+  qdelaun.htm
+  qdelau_f.htm        
+  qhalf.htm
+  qvoronoi.htm
+  qvoron_f.htm
+  qh-eg.htm
+  qh-code.htm
+  qh-impre.htm
+  index.htm
+  qh-opt*.htm
+  qh-quick.htm
+  qh--*.gif            // images for manual
+  normal_voronoi_knauss_oesterle.jpg
+  qhull.man            // Unix man page 
+  qhull.txt
+
+bin/
+  msvcr80.dll          // Visual C++ redistributable file (.zip only)
+
+src/
+  qhull/unix.c         // Qhull and rbox applications
+  qconvex/qconvex.c    
+  qhalf/qhalf.c
+  qdelaunay/qdelaunay.c
+  qvoronoi/qvoronoi.c
+  rbox/rbox.c
+
+  user_eg/user_eg.c    // example of using qhull_p.dll (requires -Dqh_QHpointer)
+  user_eg2/user_eg2.c  // example of using qhull.dll from a user program
+  user_eg3/user_eg3.cpp // example of Qhull's C++ interface with libqhullstatic_p.a
+  qhulltest/qhulltest.cpp // Test of Qhull's C++ interface using Qt's QTestLib
+  qhull-*.pri          // Include files for Qt projects
+
+src/libqhull
+  libqhull.pro         // Qt project for shared library (qhull.dll)
+  index.htm            // design documentation for libqhull
+  qh-*.htm
+  qhull-exports.def    // Export Definition file for Visual C++
+  Makefile             // Simple gcc Makefile for qhull and libqhullstatic.a
+  Mborland             // Makefile for Borland C++ 5.0
+
+  libqhull.h           // header file for qhull
+  user.h               // header file of user definable constants 
+  libqhull.c           // Quickhull algorithm with partitioning
+  user.c               // user re-definable functions 
+  usermem.c
+  userprintf.c
+  userprintf_rbox.c
+
+  qhull_a.h            // include files for libqhull/*.c 
+  geom.c               // geometric routines 
+  geom2.c
+  geom.h     
+  global.c             // global variables 
+  io.c                 // input-output routines 
+  io.h   
+  mem.c                // memory routines, this is stand-alone code 
+  mem.h
+  merge.c              // merging of non-convex facets 
+  merge.h
+  poly.c               // polyhedron routines 
+  poly2.c
+  poly.h 
+  qset.c               // set routines, this only depends on mem.c 
+  qset.h
+  random.c             // utilities w/ Park & Miller's random number generator
+  random.h
+  rboxlib.c            // point set generator for rbox
+  stat.c               // statistics 
+  stat.h
+
+src/libqhullp
+  libqhullp.pro        // Qt project for shared library (qhull_p.dll)
+  qhull_p-exports.def  // Export Definition file for Visual C++
+
+src/libqhullstatic/
+  libqhullstatic.pro   // Qt project for static library     
+     
+src/libqhullstaticp/
+  libqhullstaticp.pro  // Qt project for static library with qh_QHpointer
+     
+src/libqhullcpp/
+  libqhullcpp.pro      // Qt project for static C++ library     
+  Qhull.cpp            // Call libqhull.c from C++
+  Qhull.h
+  qt-qhull.cpp         // Supporting methods for Qt
+  qhull_interface.cpp  // Another approach to C++
+    
+  Coordinates.cpp      // input classes
+  Coordinates.h
+  PointCoordinates.cpp
+  PointCoordinates.h
+  RboxPoints.cpp       // call rboxlib.c from C++
+  RboxPoints.h
+
+  QhullFacet.cpp       // data structure classes
+  QhullFacet.h
+  QhullHyperplane.cpp
+  QhullHyperplane.h
+  QhullPoint.cpp
+  QhullPoint.h
+  QhullQh.cpp
+  QhullStat.cpp
+  QhullStat.h
+  QhullVertex.cpp
+  QhullVertex.h
+  
+  QhullFacetList.cpp   // collection classes
+  QhullFacetList.h
+  QhullFacetSet.cpp
+  QhullFacetSet.h
+  QhullIterator.h
+  QhullLinkedList.h
+  QhullPoints.cpp
+  QhullPoints.h
+  QhullPointSet.cpp
+  QhullPointSet.h
+  QhullRidge.cpp
+  QhullRidge.h
+  QhullSet.cpp
+  QhullSet.h
+  QhullSets.h
+  QhullVertexSet.cpp
+  QhullVertexSet.h
+
+  functionObjects.h    // supporting classes
+  QhullError.cpp
+  QhullError.h
+  QhullQh.cpp
+  QhullQh.h
+  UsingLibQhull.cpp
+  UsingLibQhull.h
+
+src/qhulltest/
+  qhulltest.pro        // Qt project for test of C++ interface     
+  Coordinates_test.cpp // Test of each class
+  PointCoordinates_test.cpp
+  Point_test.cpp
+  QhullFacetList_test.cpp
+  QhullFacetSet_test.cpp
+  QhullFacet_test.cpp
+  QhullHyperplane_test.cpp
+  QhullLinkedList_test.cpp
+  QhullPointSet_test.cpp
+  QhullPoints_test.cpp
+  QhullPoint_test.cpp
+  QhullRidge_test.cpp
+  QhullSet_test.cpp
+  QhullVertexSet_test.cpp
+  QhullVertex_test.cpp
+  Qhull_test.cpp
+  RboxPoints_test.cpp
+  UsingLibQhull_test.cpp
+
+src/road/
+  RoadError.cpp        // Supporting base classes
+  RoadError.h
+  RoadLogEvent.cpp
+  RoadLogEvent.h
+  RoadTest.cpp         // Run multiple test files with QTestLib
+  RoadTest.h
+
+src/testqset/
+  testqset.pro		// Qt project for test qset.c with mem.c
+  testqset.c
+  
+-----------------
+Authors:
+
+  C. Bradford Barber                  Hannu Huhdanpaa (Version 1.0)
+  bradb at shore.net                     hannu at qhull.org
+  
+  Qhull 1.0 and 2.0 were developed under NSF grants NSF/DMS-8920161 
+  and NSF-CCR-91-15793 750-7504 at the Geometry Center and Harvard 
+  University.  If you find Qhull useful, please let us know.
diff --git a/alg/libqhull/geom.c b/alg/libqhull/geom.c
new file mode 100644
index 0000000..f9de507
--- /dev/null
+++ b/alg/libqhull/geom.c
@@ -0,0 +1,1236 @@
+/*<html><pre>  -<a                             href="qh-geom.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   geom.c
+   geometric routines of qhull
+
+   see qh-geom.htm and geom.h
+
+   Copyright (c) 1993-2012 The Geometry Center.
+   $Id: //main/2011/qhull/src/libqhull/geom.c#3 $$Change: 1464 $
+   $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+
+   infrequent code goes into geom2.c
+*/
+
+#include "qhull_a.h"
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="distplane">-</a>
+
+  qh_distplane( point, facet, dist )
+    return distance from point to facet
+
+  returns:
+    dist
+    if qh.RANDOMdist, joggles result
+
+  notes:
+    dist > 0 if point is above facet (i.e., outside)
+    does not error (for qh_sortfacets, qh_outerinner)
+
+  see:
+    qh_distnorm in geom2.c
+    qh_distplane [geom.c], QhullFacet::distance, and QhullHyperplane::distance are copies
+*/
+void qh_distplane(pointT *point, facetT *facet, realT *dist) {
+  coordT *normal= facet->normal, *coordp, randr;
+  int k;
+
+  switch (qh hull_dim){
+  case 2:
+    *dist= facet->offset + point[0] * normal[0] + point[1] * normal[1];
+    break;
+  case 3:
+    *dist= facet->offset + point[0] * normal[0] + point[1] * normal[1] + point[2] * normal[2];
+    break;
+  case 4:
+    *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3];
+    break;
+  case 5:
+    *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4];
+    break;
+  case 6:
+    *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5];
+    break;
+  case 7:
+    *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5]+point[6]*normal[6];
+    break;
+  case 8:
+    *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5]+point[6]*normal[6]+point[7]*normal[7];
+    break;
+  default:
+    *dist= facet->offset;
+    coordp= point;
+    for (k=qh hull_dim; k--; )
+      *dist += *coordp++ * *normal++;
+    break;
+  }
+  zinc_(Zdistplane);
+  if (!qh RANDOMdist && qh IStracing < 4)
+    return;
+  if (qh RANDOMdist) {
+    randr= qh_RANDOMint;
+    *dist += (2.0 * randr / qh_RANDOMmax - 1.0) *
+      qh RANDOMfactor * qh MAXabs_coord;
+  }
+  if (qh IStracing >= 4) {
+    qh_fprintf(qh ferr, 8001, "qh_distplane: ");
+    qh_fprintf(qh ferr, 8002, qh_REAL_1, *dist);
+    qh_fprintf(qh ferr, 8003, "from p%d to f%d\n", qh_pointid(point), facet->id);
+  }
+  return;
+} /* distplane */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="findbest">-</a>
+
+  qh_findbest( point, startfacet, bestoutside, qh_ISnewfacets, qh_NOupper, dist, isoutside, numpart )
+    find facet that is furthest below a point
+    for upperDelaunay facets
+      returns facet only if !qh_NOupper and clearly above
+
+  input:
+    starts search at 'startfacet' (can not be flipped)
+    if !bestoutside(qh_ALL), stops at qh.MINoutside
+
+  returns:
+    best facet (reports error if NULL)
+    early out if isoutside defined and bestdist > qh.MINoutside
+    dist is distance to facet
+    isoutside is true if point is outside of facet
+    numpart counts the number of distance tests
+
+  see also:
+    qh_findbestnew()
+
+  notes:
+    If merging (testhorizon), searches horizon facets of coplanar best facets because
+    after qh_distplane, this and qh_partitionpoint are the most expensive in 3-d
+      avoid calls to distplane, function calls, and real number operations.
+    caller traces result
+    Optimized for outside points.   Tried recording a search set for qh_findhorizon.
+    Made code more complicated.
+
+  when called by qh_partitionvisible():
+    indicated by qh_ISnewfacets
+    qh.newfacet_list is list of simplicial, new facets
+    qh_findbestnew set if qh_sharpnewfacets returns True (to use qh_findbestnew)
+    qh.bestfacet_notsharp set if qh_sharpnewfacets returns False
+
+  when called by qh_findfacet(), qh_partitionpoint(), qh_partitioncoplanar(),
+                 qh_check_bestdist(), qh_addpoint()
+    indicated by !qh_ISnewfacets
+    returns best facet in neighborhood of given facet
+      this is best facet overall if dist > -   qh.MAXcoplanar
+        or hull has at least a "spherical" curvature
+
+  design:
+    initialize and test for early exit
+    repeat while there are better facets
+      for each neighbor of facet
+        exit if outside facet found
+        test for better facet
+    if point is inside and partitioning
+      test for new facets with a "sharp" intersection
+      if so, future calls go to qh_findbestnew()
+    test horizon facets
+*/
+facetT *qh_findbest(pointT *point, facetT *startfacet,
+                     boolT bestoutside, boolT isnewfacets, boolT noupper,
+                     realT *dist, boolT *isoutside, int *numpart) {
+  realT bestdist= -REALmax/2 /* avoid underflow */;
+  facetT *facet, *neighbor, **neighborp;
+  facetT *bestfacet= NULL, *lastfacet= NULL;
+  int oldtrace= qh IStracing;
+  unsigned int visitid= ++qh visit_id;
+  int numpartnew=0;
+  boolT testhorizon = True; /* needed if precise, e.g., rbox c D6 | qhull Q0 Tv */
+
+  zinc_(Zfindbest);
+  if (qh IStracing >= 3 || (qh TRACElevel && qh TRACEpoint >= 0 && qh TRACEpoint == qh_pointid(point))) {
+    if (qh TRACElevel > qh IStracing)
+      qh IStracing= qh TRACElevel;
+    qh_fprintf(qh ferr, 8004, "qh_findbest: point p%d starting at f%d isnewfacets? %d, unless %d exit if > %2.2g\n",
+             qh_pointid(point), startfacet->id, isnewfacets, bestoutside, qh MINoutside);
+    qh_fprintf(qh ferr, 8005, "  testhorizon? %d noupper? %d", testhorizon, noupper);
+    qh_fprintf(qh ferr, 8006, "  Last point added was p%d.", qh furthest_id);
+    qh_fprintf(qh ferr, 8007, "  Last merge was #%d.  max_outside %2.2g\n", zzval_(Ztotmerge), qh max_outside);
+  }
+  if (isoutside)
+    *isoutside= True;
+  if (!startfacet->flipped) {  /* test startfacet */
+    *numpart= 1;
+    qh_distplane(point, startfacet, dist);  /* this code is duplicated below */
+    if (!bestoutside && *dist >= qh MINoutside
+    && (!startfacet->upperdelaunay || !noupper)) {
+      bestfacet= startfacet;
+      goto LABELreturn_best;
+    }
+    bestdist= *dist;
+    if (!startfacet->upperdelaunay) {
+      bestfacet= startfacet;
+    }
+  }else
+    *numpart= 0;
+  startfacet->visitid= visitid;
+  facet= startfacet;
+  while (facet) {
+    trace4((qh ferr, 4001, "qh_findbest: neighbors of f%d, bestdist %2.2g f%d\n",
+                facet->id, bestdist, getid_(bestfacet)));
+    lastfacet= facet;
+    FOREACHneighbor_(facet) {
+      if (!neighbor->newfacet && isnewfacets)
+        continue;
+      if (neighbor->visitid == visitid)
+        continue;
+      neighbor->visitid= visitid;
+      if (!neighbor->flipped) {  /* code duplicated above */
+        (*numpart)++;
+        qh_distplane(point, neighbor, dist);
+        if (*dist > bestdist) {
+          if (!bestoutside && *dist >= qh MINoutside
+          && (!neighbor->upperdelaunay || !noupper)) {
+            bestfacet= neighbor;
+            goto LABELreturn_best;
+          }
+          if (!neighbor->upperdelaunay) {
+            bestfacet= neighbor;
+            bestdist= *dist;
+            break; /* switch to neighbor */
+          }else if (!bestfacet) {
+            bestdist= *dist;
+            break; /* switch to neighbor */
+          }
+        } /* end of *dist>bestdist */
+      } /* end of !flipped */
+    } /* end of FOREACHneighbor */
+    facet= neighbor;  /* non-NULL only if *dist>bestdist */
+  } /* end of while facet (directed search) */
+  if (isnewfacets) {
+    if (!bestfacet) {
+      bestdist= -REALmax/2;
+      bestfacet= qh_findbestnew(point, startfacet->next, &bestdist, bestoutside, isoutside, &numpartnew);
+      testhorizon= False; /* qh_findbestnew calls qh_findbesthorizon */
+    }else if (!qh findbest_notsharp && bestdist < - qh DISTround) {
+      if (qh_sharpnewfacets()) {
+        /* seldom used, qh_findbestnew will retest all facets */
+        zinc_(Zfindnewsharp);
+        bestfacet= qh_findbestnew(point, bestfacet, &bestdist, bestoutside, isoutside, &numpartnew);
+        testhorizon= False; /* qh_findbestnew calls qh_findbesthorizon */
+        qh findbestnew= True;
+      }else
+        qh findbest_notsharp= True;
+    }
+  }
+  if (!bestfacet)
+    bestfacet= qh_findbestlower(lastfacet, point, &bestdist, numpart);
+  if (testhorizon)
+    bestfacet= qh_findbesthorizon(!qh_IScheckmax, point, bestfacet, noupper, &bestdist, &numpartnew);
+  *dist= bestdist;
+  if (isoutside && bestdist < qh MINoutside)
+    *isoutside= False;
+LABELreturn_best:
+  zadd_(Zfindbesttot, *numpart);
+  zmax_(Zfindbestmax, *numpart);
+  (*numpart) += numpartnew;
+  qh IStracing= oldtrace;
+  return bestfacet;
+}  /* findbest */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="findbesthorizon">-</a>
+
+  qh_findbesthorizon( qh_IScheckmax, point, startfacet, qh_NOupper, &bestdist, &numpart )
+    search coplanar and better horizon facets from startfacet/bestdist
+    ischeckmax turns off statistics and minsearch update
+    all arguments must be initialized
+  returns(ischeckmax):
+    best facet
+  returns(!ischeckmax):
+    best facet that is not upperdelaunay
+    allows upperdelaunay that is clearly outside
+  returns:
+    bestdist is distance to bestfacet
+    numpart -- updates number of distance tests
+
+  notes:
+    no early out -- use qh_findbest() or qh_findbestnew()
+    Searches coplanar or better horizon facets
+
+  when called by qh_check_maxout() (qh_IScheckmax)
+    startfacet must be closest to the point
+      Otherwise, if point is beyond and below startfacet, startfacet may be a local minimum
+      even though other facets are below the point.
+    updates facet->maxoutside for good, visited facets
+    may return NULL
+
+    searchdist is qh.max_outside + 2 * DISTround
+      + max( MINvisible('Vn'), MAXcoplanar('Un'));
+    This setting is a guess.  It must be at least max_outside + 2*DISTround
+    because a facet may have a geometric neighbor across a vertex
+
+  design:
+    for each horizon facet of coplanar best facets
+      continue if clearly inside
+      unless upperdelaunay or clearly outside
+         update best facet
+*/
+facetT *qh_findbesthorizon(boolT ischeckmax, pointT* point, facetT *startfacet, boolT noupper, realT *bestdist, int *numpart) {
+  facetT *bestfacet= startfacet;
+  realT dist;
+  facetT *neighbor, **neighborp, *facet;
+  facetT *nextfacet= NULL; /* optimize last facet of coplanarfacetset */
+  int numpartinit= *numpart, coplanarfacetset_size;
+  unsigned int visitid= ++qh visit_id;
+  boolT newbest= False; /* for tracing */
+  realT minsearch, searchdist;  /* skip facets that are too far from point */
+
+  if (!ischeckmax) {
+    zinc_(Zfindhorizon);
+  }else {
+#if qh_MAXoutside
+    if ((!qh ONLYgood || startfacet->good) && *bestdist > startfacet->maxoutside)
+      startfacet->maxoutside= *bestdist;
+#endif
+  }
+  searchdist= qh_SEARCHdist; /* multiple of qh.max_outside and precision constants */
+  minsearch= *bestdist - searchdist;
+  if (ischeckmax) {
+    /* Always check coplanar facets.  Needed for RBOX 1000 s Z1 G1e-13 t996564279 | QHULL Tv */
+    minimize_(minsearch, -searchdist);
+  }
+  coplanarfacetset_size= 0;
+  facet= startfacet;
+  while (True) {
+    trace4((qh ferr, 4002, "qh_findbesthorizon: neighbors of f%d bestdist %2.2g f%d ischeckmax? %d noupper? %d minsearch %2.2g searchdist %2.2g\n",
+                facet->id, *bestdist, getid_(bestfacet), ischeckmax, noupper,
+                minsearch, searchdist));
+    FOREACHneighbor_(facet) {
+      if (neighbor->visitid == visitid)
+        continue;
+      neighbor->visitid= visitid;
+      if (!neighbor->flipped) {
+        qh_distplane(point, neighbor, &dist);
+        (*numpart)++;
+        if (dist > *bestdist) {
+          if (!neighbor->upperdelaunay || ischeckmax || (!noupper && dist >= qh MINoutside)) {
+            bestfacet= neighbor;
+            *bestdist= dist;
+            newbest= True;
+            if (!ischeckmax) {
+              minsearch= dist - searchdist;
+              if (dist > *bestdist + searchdist) {
+                zinc_(Zfindjump);  /* everything in qh.coplanarfacetset at least searchdist below */
+                coplanarfacetset_size= 0;
+              }
+            }
+          }
+        }else if (dist < minsearch)
+          continue;  /* if ischeckmax, dist can't be positive */
+#if qh_MAXoutside
+        if (ischeckmax && dist > neighbor->maxoutside)
+          neighbor->maxoutside= dist;
+#endif
+      } /* end of !flipped */
+      if (nextfacet) {
+        if (!coplanarfacetset_size++) {
+          SETfirst_(qh coplanarfacetset)= nextfacet;
+          SETtruncate_(qh coplanarfacetset, 1);
+        }else
+          qh_setappend(&qh coplanarfacetset, nextfacet); /* Was needed for RBOX 1000 s W1e-13 P0 t996547055 | QHULL d Qbb Qc Tv
+                                                 and RBOX 1000 s Z1 G1e-13 t996564279 | qhull Tv  */
+      }
+      nextfacet= neighbor;
+    } /* end of EACHneighbor */
+    facet= nextfacet;
+    if (facet)
+      nextfacet= NULL;
+    else if (!coplanarfacetset_size)
+      break;
+    else if (!--coplanarfacetset_size) {
+      facet= SETfirstt_(qh coplanarfacetset, facetT);
+      SETtruncate_(qh coplanarfacetset, 0);
+    }else
+      facet= (facetT*)qh_setdellast(qh coplanarfacetset);
+  } /* while True, for each facet in qh.coplanarfacetset */
+  if (!ischeckmax) {
+    zadd_(Zfindhorizontot, *numpart - numpartinit);
+    zmax_(Zfindhorizonmax, *numpart - numpartinit);
+    if (newbest)
+      zinc_(Zparthorizon);
+  }
+  trace4((qh ferr, 4003, "qh_findbesthorizon: newbest? %d bestfacet f%d bestdist %2.2g\n", newbest, getid_(bestfacet), *bestdist));
+  return bestfacet;
+}  /* findbesthorizon */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="findbestnew">-</a>
+
+  qh_findbestnew( point, startfacet, dist, isoutside, numpart )
+    find best newfacet for point
+    searches all of qh.newfacet_list starting at startfacet
+    searches horizon facets of coplanar best newfacets
+    searches all facets if startfacet == qh.facet_list
+  returns:
+    best new or horizon facet that is not upperdelaunay
+    early out if isoutside and not 'Qf'
+    dist is distance to facet
+    isoutside is true if point is outside of facet
+    numpart is number of distance tests
+
+  notes:
+    Always used for merged new facets (see qh_USEfindbestnew)
+    Avoids upperdelaunay facet unless (isoutside and outside)
+
+    Uses qh.visit_id, qh.coplanarfacetset.
+    If share visit_id with qh_findbest, coplanarfacetset is incorrect.
+
+    If merging (testhorizon), searches horizon facets of coplanar best facets because
+    a point maybe coplanar to the bestfacet, below its horizon facet,
+    and above a horizon facet of a coplanar newfacet.  For example,
+      rbox 1000 s Z1 G1e-13 | qhull
+      rbox 1000 s W1e-13 P0 t992110337 | QHULL d Qbb Qc
+
+    qh_findbestnew() used if
+       qh_sharpnewfacets -- newfacets contains a sharp angle
+       if many merges, qh_premerge found a merge, or 'Qf' (qh.findbestnew)
+
+  see also:
+    qh_partitionall() and qh_findbest()
+
+  design:
+    for each new facet starting from startfacet
+      test distance from point to facet
+      return facet if clearly outside
+      unless upperdelaunay and a lowerdelaunay exists
+         update best facet
+    test horizon facets
+*/
+facetT *qh_findbestnew(pointT *point, facetT *startfacet,
+           realT *dist, boolT bestoutside, boolT *isoutside, int *numpart) {
+  realT bestdist= -REALmax/2;
+  facetT *bestfacet= NULL, *facet;
+  int oldtrace= qh IStracing, i;
+  unsigned int visitid= ++qh visit_id;
+  realT distoutside= 0.0;
+  boolT isdistoutside; /* True if distoutside is defined */
+  /*boolT testhorizon = True;*/ /* needed if precise, e.g., rbox c D6 | qhull Q0 Tv */
+
+  if (!startfacet) {
+    if (qh MERGING)
+      qh_fprintf(qh ferr, 6001, "qhull precision error (qh_findbestnew): merging has formed and deleted a cone of new facets.  Can not continue.\n");
+    else
+      qh_fprintf(qh ferr, 6002, "qhull internal error (qh_findbestnew): no new facets for point p%d\n",
+              qh furthest_id);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  zinc_(Zfindnew);
+  if (qh BESToutside || bestoutside)
+    isdistoutside= False;
+  else {
+    isdistoutside= True;
+    distoutside= qh_DISToutside; /* multiple of qh.MINoutside & qh.max_outside, see user.h */
+  }
+  if (isoutside)
+    *isoutside= True;
+  *numpart= 0;
+  if (qh IStracing >= 3 || (qh TRACElevel && qh TRACEpoint >= 0 && qh TRACEpoint == qh_pointid(point))) {
+    if (qh TRACElevel > qh IStracing)
+      qh IStracing= qh TRACElevel;
+    qh_fprintf(qh ferr, 8008, "qh_findbestnew: point p%d facet f%d. Stop? %d if dist > %2.2g\n",
+             qh_pointid(point), startfacet->id, isdistoutside, distoutside);
+    qh_fprintf(qh ferr, 8009, "  Last point added p%d visitid %d.",  qh furthest_id, visitid);
+    qh_fprintf(qh ferr, 8010, "  Last merge was #%d.\n", zzval_(Ztotmerge));
+  }
+  /* visit all new facets starting with startfacet, maybe qh facet_list */
+  for (i=0, facet=startfacet; i < 2; i++, facet= qh newfacet_list) {
+    FORALLfacet_(facet) {
+      if (facet == startfacet && i)
+        break;
+      facet->visitid= visitid;
+      if (!facet->flipped) {
+        qh_distplane(point, facet, dist);
+        (*numpart)++;
+        if (*dist > bestdist) {
+          if (!facet->upperdelaunay || *dist >= qh MINoutside) {
+            bestfacet= facet;
+            if (isdistoutside && *dist >= distoutside)
+              goto LABELreturn_bestnew;
+            bestdist= *dist;
+          }
+        }
+      } /* end of !flipped */
+    } /* FORALLfacet from startfacet or qh newfacet_list */
+  }
+  if (/*testhorizon ||*/ !bestfacet)
+    bestfacet= qh_findbesthorizon(!qh_IScheckmax, point, bestfacet ? bestfacet : startfacet,
+                                        !qh_NOupper, &bestdist, numpart);
+  *dist= bestdist;
+  if (isoutside && *dist < qh MINoutside)
+    *isoutside= False;
+LABELreturn_bestnew:
+  zadd_(Zfindnewtot, *numpart);
+  zmax_(Zfindnewmax, *numpart);
+  trace4((qh ferr, 4004, "qh_findbestnew: bestfacet f%d bestdist %2.2g\n", getid_(bestfacet), *dist));
+  qh IStracing= oldtrace;
+  return bestfacet;
+}  /* findbestnew */
+
+/* ============ hyperplane functions -- keep code together [?] ============ */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="backnormal">-</a>
+
+  qh_backnormal( rows, numrow, numcol, sign, normal, nearzero )
+    given an upper-triangular rows array and a sign,
+    solve for normal equation x using back substitution over rows U
+
+  returns:
+     normal= x
+
+     if will not be able to divzero() when normalized(qh.MINdenom_2 and qh.MINdenom_1_2),
+       if fails on last row
+         this means that the hyperplane intersects [0,..,1]
+         sets last coordinate of normal to sign
+       otherwise
+         sets tail of normal to [...,sign,0,...], i.e., solves for b= [0...0]
+         sets nearzero
+
+  notes:
+     assumes numrow == numcol-1
+
+     see Golub & van Loan 4.4-9 for back substitution
+
+     solves Ux=b where Ax=b and PA=LU
+     b= [0,...,0,sign or 0]  (sign is either -1 or +1)
+     last row of A= [0,...,0,1]
+
+     1) Ly=Pb == y=b since P only permutes the 0's of   b
+
+  design:
+    for each row from end
+      perform back substitution
+      if near zero
+        use qh_divzero for division
+        if zero divide and not last row
+          set tail of normal to 0
+*/
+void qh_backnormal(realT **rows, int numrow, int numcol, boolT sign,
+        coordT *normal, boolT *nearzero) {
+  int i, j;
+  coordT *normalp, *normal_tail, *ai, *ak;
+  realT diagonal;
+  boolT waszero;
+  int zerocol= -1;
+
+  normalp= normal + numcol - 1;
+  *normalp--= (sign ? -1.0 : 1.0);
+  for (i=numrow; i--; ) {
+    *normalp= 0.0;
+    ai= rows[i] + i + 1;
+    ak= normalp+1;
+    for (j=i+1; j < numcol; j++)
+      *normalp -= *ai++ * *ak++;
+    diagonal= (rows[i])[i];
+    if (fabs_(diagonal) > qh MINdenom_2)
+      *(normalp--) /= diagonal;
+    else {
+      waszero= False;
+      *normalp= qh_divzero(*normalp, diagonal, qh MINdenom_1_2, &waszero);
+      if (waszero) {
+        zerocol= i;
+        *(normalp--)= (sign ? -1.0 : 1.0);
+        for (normal_tail= normalp+2; normal_tail < normal + numcol; normal_tail++)
+          *normal_tail= 0.0;
+      }else
+        normalp--;
+    }
+  }
+  if (zerocol != -1) {
+    zzinc_(Zback0);
+    *nearzero= True;
+    trace4((qh ferr, 4005, "qh_backnormal: zero diagonal at column %d.\n", i));
+    qh_precision("zero diagonal on back substitution");
+  }
+} /* backnormal */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="gausselim">-</a>
+
+  qh_gausselim( rows, numrow, numcol, sign )
+    Gaussian elimination with partial pivoting
+
+  returns:
+    rows is upper triangular (includes row exchanges)
+    flips sign for each row exchange
+    sets nearzero if pivot[k] < qh.NEARzero[k], else clears it
+
+  notes:
+    if nearzero, the determinant's sign may be incorrect.
+    assumes numrow <= numcol
+
+  design:
+    for each row
+      determine pivot and exchange rows if necessary
+      test for near zero
+      perform gaussian elimination step
+*/
+void qh_gausselim(realT **rows, int numrow, int numcol, boolT *sign, boolT *nearzero) {
+  realT *ai, *ak, *rowp, *pivotrow;
+  realT n, pivot, pivot_abs= 0.0, temp;
+  int i, j, k, pivoti, flip=0;
+
+  *nearzero= False;
+  for (k=0; k < numrow; k++) {
+    pivot_abs= fabs_((rows[k])[k]);
+    pivoti= k;
+    for (i=k+1; i < numrow; i++) {
+      if ((temp= fabs_((rows[i])[k])) > pivot_abs) {
+        pivot_abs= temp;
+        pivoti= i;
+      }
+    }
+    if (pivoti != k) {
+      rowp= rows[pivoti];
+      rows[pivoti]= rows[k];
+      rows[k]= rowp;
+      *sign ^= 1;
+      flip ^= 1;
+    }
+    if (pivot_abs <= qh NEARzero[k]) {
+      *nearzero= True;
+      if (pivot_abs == 0.0) {   /* remainder of column == 0 */
+        if (qh IStracing >= 4) {
+          qh_fprintf(qh ferr, 8011, "qh_gausselim: 0 pivot at column %d. (%2.2g < %2.2g)\n", k, pivot_abs, qh DISTround);
+          qh_printmatrix(qh ferr, "Matrix:", rows, numrow, numcol);
+        }
+        zzinc_(Zgauss0);
+        qh_precision("zero pivot for Gaussian elimination");
+        goto LABELnextcol;
+      }
+    }
+    pivotrow= rows[k] + k;
+    pivot= *pivotrow++;  /* signed value of pivot, and remainder of row */
+    for (i=k+1; i < numrow; i++) {
+      ai= rows[i] + k;
+      ak= pivotrow;
+      n= (*ai++)/pivot;   /* divzero() not needed since |pivot| >= |*ai| */
+      for (j= numcol - (k+1); j--; )
+        *ai++ -= n * *ak++;
+    }
+  LABELnextcol:
+    ;
+  }
+  wmin_(Wmindenom, pivot_abs);  /* last pivot element */
+  if (qh IStracing >= 5)
+    qh_printmatrix(qh ferr, "qh_gausselem: result", rows, numrow, numcol);
+} /* gausselim */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="getangle">-</a>
+
+  qh_getangle( vect1, vect2 )
+    returns the dot product of two vectors
+    if qh.RANDOMdist, joggles result
+
+  notes:
+    the angle may be > 1.0 or < -1.0 because of roundoff errors
+
+*/
+realT qh_getangle(pointT *vect1, pointT *vect2) {
+  realT angle= 0, randr;
+  int k;
+
+  for (k=qh hull_dim; k--; )
+    angle += *vect1++ * *vect2++;
+  if (qh RANDOMdist) {
+    randr= qh_RANDOMint;
+    angle += (2.0 * randr / qh_RANDOMmax - 1.0) *
+      qh RANDOMfactor;
+  }
+  trace4((qh ferr, 4006, "qh_getangle: %2.2g\n", angle));
+  return(angle);
+} /* getangle */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="getcenter">-</a>
+
+  qh_getcenter( vertices )
+    returns arithmetic center of a set of vertices as a new point
+
+  notes:
+    allocates point array for center
+*/
+pointT *qh_getcenter(setT *vertices) {
+  int k;
+  pointT *center, *coord;
+  vertexT *vertex, **vertexp;
+  int count= qh_setsize(vertices);
+
+  if (count < 2) {
+    qh_fprintf(qh ferr, 6003, "qhull internal error (qh_getcenter): not defined for %d points\n", count);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  center= (pointT *)qh_memalloc(qh normal_size);
+  for (k=0; k < qh hull_dim; k++) {
+    coord= center+k;
+    *coord= 0.0;
+    FOREACHvertex_(vertices)
+      *coord += vertex->point[k];
+    /* count cannot be 0 since above qh_errexit didn't return */
+    /* coverity[divide_by_zero] */
+    *coord /= count;
+  }
+  return(center);
+} /* getcenter */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="getcentrum">-</a>
+
+  qh_getcentrum( facet )
+    returns the centrum for a facet as a new point
+
+  notes:
+    allocates the centrum
+*/
+pointT *qh_getcentrum(facetT *facet) {
+  realT dist;
+  pointT *centrum, *point;
+
+  point= qh_getcenter(facet->vertices);
+  zzinc_(Zcentrumtests);
+  qh_distplane(point, facet, &dist);
+  centrum= qh_projectpoint(point, facet, dist);
+  qh_memfree(point, qh normal_size);
+  trace4((qh ferr, 4007, "qh_getcentrum: for f%d, %d vertices dist= %2.2g\n",
+          facet->id, qh_setsize(facet->vertices), dist));
+  return centrum;
+} /* getcentrum */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="getdistance">-</a>
+
+  qh_getdistance( facet, neighbor, mindist, maxdist )
+    returns the maxdist and mindist distance of any vertex from neighbor
+
+  returns:
+    the max absolute value
+
+  design:
+    for each vertex of facet that is not in neighbor
+      test the distance from vertex to neighbor
+*/
+realT qh_getdistance(facetT *facet, facetT *neighbor, realT *mindist, realT *maxdist) {
+  vertexT *vertex, **vertexp;
+  realT dist, maxd, mind;
+
+  FOREACHvertex_(facet->vertices)
+    vertex->seen= False;
+  FOREACHvertex_(neighbor->vertices)
+    vertex->seen= True;
+  mind= 0.0;
+  maxd= 0.0;
+  FOREACHvertex_(facet->vertices) {
+    if (!vertex->seen) {
+      zzinc_(Zbestdist);
+      qh_distplane(vertex->point, neighbor, &dist);
+      if (dist < mind)
+        mind= dist;
+      else if (dist > maxd)
+        maxd= dist;
+    }
+  }
+  *mindist= mind;
+  *maxdist= maxd;
+  mind= -mind;
+  if (maxd > mind)
+    return maxd;
+  else
+    return mind;
+} /* getdistance */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="normalize">-</a>
+
+  qh_normalize( normal, dim, toporient )
+    normalize a vector and report if too small
+    does not use min norm
+
+  see:
+    qh_normalize2
+*/
+void qh_normalize(coordT *normal, int dim, boolT toporient) {
+  qh_normalize2( normal, dim, toporient, NULL, NULL);
+} /* normalize */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="normalize2">-</a>
+
+  qh_normalize2( normal, dim, toporient, minnorm, ismin )
+    normalize a vector and report if too small
+    qh.MINdenom/MINdenom1 are the upper limits for divide overflow
+
+  returns:
+    normalized vector
+    flips sign if !toporient
+    if minnorm non-NULL,
+      sets ismin if normal < minnorm
+
+  notes:
+    if zero norm
+       sets all elements to sqrt(1.0/dim)
+    if divide by zero (divzero())
+       sets largest element to   +/-1
+       bumps Znearlysingular
+
+  design:
+    computes norm
+    test for minnorm
+    if not near zero
+      normalizes normal
+    else if zero norm
+      sets normal to standard value
+    else
+      uses qh_divzero to normalize
+      if nearzero
+        sets norm to direction of maximum value
+*/
+void qh_normalize2 (coordT *normal, int dim, boolT toporient,
+            realT *minnorm, boolT *ismin) {
+  int k;
+  realT *colp, *maxp, norm= 0, temp, *norm1, *norm2, *norm3;
+  boolT zerodiv;
+
+  norm1= normal+1;
+  norm2= normal+2;
+  norm3= normal+3;
+  if (dim == 2)
+    norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1));
+  else if (dim == 3)
+    norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2));
+  else if (dim == 4) {
+    norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2)
+               + (*norm3)*(*norm3));
+  }else if (dim > 4) {
+    norm= (*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2)
+               + (*norm3)*(*norm3);
+    for (k=dim-4, colp=normal+4; k--; colp++)
+      norm += (*colp) * (*colp);
+    norm= sqrt(norm);
+  }
+  if (minnorm) {
+    if (norm < *minnorm)
+      *ismin= True;
+    else
+      *ismin= False;
+  }
+  wmin_(Wmindenom, norm);
+  if (norm > qh MINdenom) {
+    if (!toporient)
+      norm= -norm;
+    *normal /= norm;
+    *norm1 /= norm;
+    if (dim == 2)
+      ; /* all done */
+    else if (dim == 3)
+      *norm2 /= norm;
+    else if (dim == 4) {
+      *norm2 /= norm;
+      *norm3 /= norm;
+    }else if (dim >4) {
+      *norm2 /= norm;
+      *norm3 /= norm;
+      for (k=dim-4, colp=normal+4; k--; )
+        *colp++ /= norm;
+    }
+  }else if (norm == 0.0) {
+    temp= sqrt(1.0/dim);
+    for (k=dim, colp=normal; k--; )
+      *colp++ = temp;
+  }else {
+    if (!toporient)
+      norm= -norm;
+    for (k=dim, colp=normal; k--; colp++) { /* k used below */
+      temp= qh_divzero(*colp, norm, qh MINdenom_1, &zerodiv);
+      if (!zerodiv)
+        *colp= temp;
+      else {
+        maxp= qh_maxabsval(normal, dim);
+        temp= ((*maxp * norm >= 0.0) ? 1.0 : -1.0);
+        for (k=dim, colp=normal; k--; colp++)
+          *colp= 0.0;
+        *maxp= temp;
+        zzinc_(Znearlysingular);
+        trace0((qh ferr, 1, "qh_normalize: norm=%2.2g too small during p%d\n",
+               norm, qh furthest_id));
+        return;
+      }
+    }
+  }
+} /* normalize */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="projectpoint">-</a>
+
+  qh_projectpoint( point, facet, dist )
+    project point onto a facet by dist
+
+  returns:
+    returns a new point
+
+  notes:
+    if dist= distplane(point,facet)
+      this projects point to hyperplane
+    assumes qh_memfree_() is valid for normal_size
+*/
+pointT *qh_projectpoint(pointT *point, facetT *facet, realT dist) {
+  pointT *newpoint, *np, *normal;
+  int normsize= qh normal_size;
+  int k;
+  void **freelistp; /* used !qh_NOmem */
+
+  qh_memalloc_(normsize, freelistp, newpoint, pointT);
+  np= newpoint;
+  normal= facet->normal;
+  for (k=qh hull_dim; k--; )
+    *(np++)= *point++ - dist * *normal++;
+  return(newpoint);
+} /* projectpoint */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="setfacetplane">-</a>
+
+  qh_setfacetplane( facet )
+    sets the hyperplane for a facet
+    if qh.RANDOMdist, joggles hyperplane
+
+  notes:
+    uses global buffers qh.gm_matrix and qh.gm_row
+    overwrites facet->normal if already defined
+    updates Wnewvertex if PRINTstatistics
+    sets facet->upperdelaunay if upper envelope of Delaunay triangulation
+
+  design:
+    copy vertex coordinates to qh.gm_matrix/gm_row
+    compute determinate
+    if nearzero
+      recompute determinate with gaussian elimination
+      if nearzero
+        force outside orientation by testing interior point
+*/
+void qh_setfacetplane(facetT *facet) {
+  pointT *point;
+  vertexT *vertex, **vertexp;
+  int normsize= qh normal_size;
+  int k,i, oldtrace= 0;
+  realT dist;
+  void **freelistp; /* used !qh_NOmem */
+  coordT *coord, *gmcoord;
+  pointT *point0= SETfirstt_(facet->vertices, vertexT)->point;
+  boolT nearzero= False;
+
+  zzinc_(Zsetplane);
+  if (!facet->normal)
+    qh_memalloc_(normsize, freelistp, facet->normal, coordT);
+  if (facet == qh tracefacet) {
+    oldtrace= qh IStracing;
+    qh IStracing= 5;
+    qh_fprintf(qh ferr, 8012, "qh_setfacetplane: facet f%d created.\n", facet->id);
+    qh_fprintf(qh ferr, 8013, "  Last point added to hull was p%d.", qh furthest_id);
+    if (zzval_(Ztotmerge))
+      qh_fprintf(qh ferr, 8014, "  Last merge was #%d.", zzval_(Ztotmerge));
+    qh_fprintf(qh ferr, 8015, "\n\nCurrent summary is:\n");
+      qh_printsummary(qh ferr);
+  }
+  if (qh hull_dim <= 4) {
+    i= 0;
+    if (qh RANDOMdist) {
+      gmcoord= qh gm_matrix;
+      FOREACHvertex_(facet->vertices) {
+        qh gm_row[i++]= gmcoord;
+        coord= vertex->point;
+        for (k=qh hull_dim; k--; )
+          *(gmcoord++)= *coord++ * qh_randomfactor(qh RANDOMa, qh RANDOMb);
+      }
+    }else {
+      FOREACHvertex_(facet->vertices)
+       qh gm_row[i++]= vertex->point;
+    }
+    qh_sethyperplane_det(qh hull_dim, qh gm_row, point0, facet->toporient,
+                facet->normal, &facet->offset, &nearzero);
+  }
+  if (qh hull_dim > 4 || nearzero) {
+    i= 0;
+    gmcoord= qh gm_matrix;
+    FOREACHvertex_(facet->vertices) {
+      if (vertex->point != point0) {
+        qh gm_row[i++]= gmcoord;
+        coord= vertex->point;
+        point= point0;
+        for (k=qh hull_dim; k--; )
+          *(gmcoord++)= *coord++ - *point++;
+      }
+    }
+    qh gm_row[i]= gmcoord;  /* for areasimplex */
+    if (qh RANDOMdist) {
+      gmcoord= qh gm_matrix;
+      for (i=qh hull_dim-1; i--; ) {
+        for (k=qh hull_dim; k--; )
+          *(gmcoord++) *= qh_randomfactor(qh RANDOMa, qh RANDOMb);
+      }
+    }
+    qh_sethyperplane_gauss(qh hull_dim, qh gm_row, point0, facet->toporient,
+                facet->normal, &facet->offset, &nearzero);
+    if (nearzero) {
+      if (qh_orientoutside(facet)) {
+        trace0((qh ferr, 2, "qh_setfacetplane: flipped orientation after testing interior_point during p%d\n", qh furthest_id));
+      /* this is part of using Gaussian Elimination.  For example in 5-d
+           1 1 1 1 0
+           1 1 1 1 1
+           0 0 0 1 0
+           0 1 0 0 0
+           1 0 0 0 0
+           norm= 0.38 0.38 -0.76 0.38 0
+         has a determinate of 1, but g.e. after subtracting pt. 0 has
+         0's in the diagonal, even with full pivoting.  It does work
+         if you subtract pt. 4 instead. */
+      }
+    }
+  }
+  facet->upperdelaunay= False;
+  if (qh DELAUNAY) {
+    if (qh UPPERdelaunay) {     /* matches qh_triangulate_facet and qh.lower_threshold in qh_initbuild */
+      if (facet->normal[qh hull_dim -1] >= qh ANGLEround * qh_ZEROdelaunay)
+        facet->upperdelaunay= True;
+    }else {
+      if (facet->normal[qh hull_dim -1] > -qh ANGLEround * qh_ZEROdelaunay)
+        facet->upperdelaunay= True;
+    }
+  }
+  if (qh PRINTstatistics || qh IStracing || qh TRACElevel || qh JOGGLEmax < REALmax) {
+    qh old_randomdist= qh RANDOMdist;
+    qh RANDOMdist= False;
+    FOREACHvertex_(facet->vertices) {
+      if (vertex->point != point0) {
+        boolT istrace= False;
+        zinc_(Zdiststat);
+        qh_distplane(vertex->point, facet, &dist);
+        dist= fabs_(dist);
+        zinc_(Znewvertex);
+        wadd_(Wnewvertex, dist);
+        if (dist > wwval_(Wnewvertexmax)) {
+          wwval_(Wnewvertexmax)= dist;
+          if (dist > qh max_outside) {
+            qh max_outside= dist;  /* used by qh_maxouter() */
+            if (dist > qh TRACEdist)
+              istrace= True;
+          }
+        }else if (-dist > qh TRACEdist)
+          istrace= True;
+        if (istrace) {
+          qh_fprintf(qh ferr, 8016, "qh_setfacetplane: ====== vertex p%d(v%d) increases max_outside to %2.2g for new facet f%d last p%d\n",
+                qh_pointid(vertex->point), vertex->id, dist, facet->id, qh furthest_id);
+          qh_errprint("DISTANT", facet, NULL, NULL, NULL);
+        }
+      }
+    }
+    qh RANDOMdist= qh old_randomdist;
+  }
+  if (qh IStracing >= 3) {
+    qh_fprintf(qh ferr, 8017, "qh_setfacetplane: f%d offset %2.2g normal: ",
+             facet->id, facet->offset);
+    for (k=0; k < qh hull_dim; k++)
+      qh_fprintf(qh ferr, 8018, "%2.2g ", facet->normal[k]);
+    qh_fprintf(qh ferr, 8019, "\n");
+  }
+  if (facet == qh tracefacet)
+    qh IStracing= oldtrace;
+} /* setfacetplane */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="sethyperplane_det">-</a>
+
+  qh_sethyperplane_det( dim, rows, point0, toporient, normal, offset, nearzero )
+    given dim X dim array indexed by rows[], one row per point,
+        toporient(flips all signs),
+        and point0 (any row)
+    set normalized hyperplane equation from oriented simplex
+
+  returns:
+    normal (normalized)
+    offset (places point0 on the hyperplane)
+    sets nearzero if hyperplane not through points
+
+  notes:
+    only defined for dim == 2..4
+    rows[] is not modified
+    solves det(P-V_0, V_n-V_0, ..., V_1-V_0)=0, i.e. every point is on hyperplane
+    see Bower & Woodworth, A programmer's geometry, Butterworths 1983.
+
+  derivation of 3-d minnorm
+    Goal: all vertices V_i within qh.one_merge of hyperplane
+    Plan: exactly translate the facet so that V_0 is the origin
+          exactly rotate the facet so that V_1 is on the x-axis and y_2=0.
+          exactly rotate the effective perturbation to only effect n_0
+             this introduces a factor of sqrt(3)
+    n_0 = ((y_2-y_0)*(z_1-z_0) - (z_2-z_0)*(y_1-y_0)) / norm
+    Let M_d be the max coordinate difference
+    Let M_a be the greater of M_d and the max abs. coordinate
+    Let u be machine roundoff and distround be max error for distance computation
+    The max error for n_0 is sqrt(3) u M_a M_d / norm.  n_1 is approx. 1 and n_2 is approx. 0
+    The max error for distance of V_1 is sqrt(3) u M_a M_d M_d / norm.  Offset=0 at origin
+    Then minnorm = 1.8 u M_a M_d M_d / qh.ONEmerge
+    Note that qh.one_merge is approx. 45.5 u M_a and norm is usually about M_d M_d
+
+  derivation of 4-d minnorm
+    same as above except rotate the facet so that V_1 on x-axis and w_2, y_3, w_3=0
+     [if two vertices fixed on x-axis, can rotate the other two in yzw.]
+    n_0 = det3_(...) = y_2 det2_(z_1, w_1, z_3, w_3) = - y_2 w_1 z_3
+     [all other terms contain at least two factors nearly zero.]
+    The max error for n_0 is sqrt(4) u M_a M_d M_d / norm
+    Then minnorm = 2 u M_a M_d M_d M_d / qh.ONEmerge
+    Note that qh.one_merge is approx. 82 u M_a and norm is usually about M_d M_d M_d
+*/
+void qh_sethyperplane_det(int dim, coordT **rows, coordT *point0,
+          boolT toporient, coordT *normal, realT *offset, boolT *nearzero) {
+  realT maxround, dist;
+  int i;
+  pointT *point;
+
+
+  if (dim == 2) {
+    normal[0]= dY(1,0);
+    normal[1]= dX(0,1);
+    qh_normalize2 (normal, dim, toporient, NULL, NULL);
+    *offset= -(point0[0]*normal[0]+point0[1]*normal[1]);
+    *nearzero= False;  /* since nearzero norm => incident points */
+  }else if (dim == 3) {
+    normal[0]= det2_(dY(2,0), dZ(2,0),
+                     dY(1,0), dZ(1,0));
+    normal[1]= det2_(dX(1,0), dZ(1,0),
+                     dX(2,0), dZ(2,0));
+    normal[2]= det2_(dX(2,0), dY(2,0),
+                     dX(1,0), dY(1,0));
+    qh_normalize2 (normal, dim, toporient, NULL, NULL);
+    *offset= -(point0[0]*normal[0] + point0[1]*normal[1]
+               + point0[2]*normal[2]);
+    maxround= qh DISTround;
+    for (i=dim; i--; ) {
+      point= rows[i];
+      if (point != point0) {
+        dist= *offset + (point[0]*normal[0] + point[1]*normal[1]
+               + point[2]*normal[2]);
+        if (dist > maxround || dist < -maxround) {
+          *nearzero= True;
+          break;
+        }
+      }
+    }
+  }else if (dim == 4) {
+    normal[0]= - det3_(dY(2,0), dZ(2,0), dW(2,0),
+                        dY(1,0), dZ(1,0), dW(1,0),
+                        dY(3,0), dZ(3,0), dW(3,0));
+    normal[1]=   det3_(dX(2,0), dZ(2,0), dW(2,0),
+                        dX(1,0), dZ(1,0), dW(1,0),
+                        dX(3,0), dZ(3,0), dW(3,0));
+    normal[2]= - det3_(dX(2,0), dY(2,0), dW(2,0),
+                        dX(1,0), dY(1,0), dW(1,0),
+                        dX(3,0), dY(3,0), dW(3,0));
+    normal[3]=   det3_(dX(2,0), dY(2,0), dZ(2,0),
+                        dX(1,0), dY(1,0), dZ(1,0),
+                        dX(3,0), dY(3,0), dZ(3,0));
+    qh_normalize2 (normal, dim, toporient, NULL, NULL);
+    *offset= -(point0[0]*normal[0] + point0[1]*normal[1]
+               + point0[2]*normal[2] + point0[3]*normal[3]);
+    maxround= qh DISTround;
+    for (i=dim; i--; ) {
+      point= rows[i];
+      if (point != point0) {
+        dist= *offset + (point[0]*normal[0] + point[1]*normal[1]
+               + point[2]*normal[2] + point[3]*normal[3]);
+        if (dist > maxround || dist < -maxround) {
+          *nearzero= True;
+          break;
+        }
+      }
+    }
+  }
+  if (*nearzero) {
+    zzinc_(Zminnorm);
+    trace0((qh ferr, 3, "qh_sethyperplane_det: degenerate norm during p%d.\n", qh furthest_id));
+    zzinc_(Znearlysingular);
+  }
+} /* sethyperplane_det */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="sethyperplane_gauss">-</a>
+
+  qh_sethyperplane_gauss( dim, rows, point0, toporient, normal, offset, nearzero )
+    given(dim-1) X dim array of rows[i]= V_{i+1} - V_0 (point0)
+    set normalized hyperplane equation from oriented simplex
+
+  returns:
+    normal (normalized)
+    offset (places point0 on the hyperplane)
+
+  notes:
+    if nearzero
+      orientation may be incorrect because of incorrect sign flips in gausselim
+    solves [V_n-V_0,...,V_1-V_0, 0 .. 0 1] * N == [0 .. 0 1]
+        or [V_n-V_0,...,V_1-V_0, 0 .. 0 1] * N == [0]
+    i.e., N is normal to the hyperplane, and the unnormalized
+        distance to [0 .. 1] is either 1 or   0
+
+  design:
+    perform gaussian elimination
+    flip sign for negative values
+    perform back substitution
+    normalize result
+    compute offset
+*/
+void qh_sethyperplane_gauss(int dim, coordT **rows, pointT *point0,
+                boolT toporient, coordT *normal, coordT *offset, boolT *nearzero) {
+  coordT *pointcoord, *normalcoef;
+  int k;
+  boolT sign= toporient, nearzero2= False;
+
+  qh_gausselim(rows, dim-1, dim, &sign, nearzero);
+  for (k=dim-1; k--; ) {
+    if ((rows[k])[k] < 0)
+      sign ^= 1;
+  }
+  if (*nearzero) {
+    zzinc_(Znearlysingular);
+    trace0((qh ferr, 4, "qh_sethyperplane_gauss: nearly singular or axis parallel hyperplane during p%d.\n", qh furthest_id));
+    qh_backnormal(rows, dim-1, dim, sign, normal, &nearzero2);
+  }else {
+    qh_backnormal(rows, dim-1, dim, sign, normal, &nearzero2);
+    if (nearzero2) {
+      zzinc_(Znearlysingular);
+      trace0((qh ferr, 5, "qh_sethyperplane_gauss: singular or axis parallel hyperplane at normalization during p%d.\n", qh furthest_id));
+    }
+  }
+  if (nearzero2)
+    *nearzero= True;
+  qh_normalize2(normal, dim, True, NULL, NULL);
+  pointcoord= point0;
+  normalcoef= normal;
+  *offset= -(*pointcoord++ * *normalcoef++);
+  for (k=dim-1; k--; )
+    *offset -= *pointcoord++ * *normalcoef++;
+} /* sethyperplane_gauss */
+
+
+
diff --git a/alg/libqhull/geom.h b/alg/libqhull/geom.h
new file mode 100644
index 0000000..c85049b
--- /dev/null
+++ b/alg/libqhull/geom.h
@@ -0,0 +1,176 @@
+/*<html><pre>  -<a                             href="qh-geom.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+  geom.h
+    header file for geometric routines
+
+   see qh-geom.htm and geom.c
+
+   Copyright (c) 1993-2012 The Geometry Center.
+   $Id: //main/2011/qhull/src/libqhull/geom.h#3 $$Change: 1464 $
+   $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+*/
+
+#ifndef qhDEFgeom
+#define qhDEFgeom 1
+
+#include "libqhull.h"
+
+/* ============ -macros- ======================== */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >--------------------------------</a><a name="fabs_">-</a>
+
+  fabs_(a)
+    returns the absolute value of a
+*/
+#define fabs_( a ) ((( a ) < 0 ) ? -( a ):( a ))
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >--------------------------------</a><a name="fmax_">-</a>
+
+  fmax_(a,b)
+    returns the maximum value of a and b
+*/
+#define fmax_( a,b )  ( ( a ) < ( b ) ? ( b ) : ( a ) )
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >--------------------------------</a><a name="fmin_">-</a>
+
+  fmin_(a,b)
+    returns the minimum value of a and b
+*/
+#define fmin_( a,b )  ( ( a ) > ( b ) ? ( b ) : ( a ) )
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >--------------------------------</a><a name="maximize_">-</a>
+
+  maximize_(maxval, val)
+    set maxval to val if val is greater than maxval
+*/
+#define maximize_( maxval, val ) { if (( maxval ) < ( val )) ( maxval )= ( val ); }
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >--------------------------------</a><a name="minimize_">-</a>
+
+  minimize_(minval, val)
+    set minval to val if val is less than minval
+*/
+#define minimize_( minval, val ) { if (( minval ) > ( val )) ( minval )= ( val ); }
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >--------------------------------</a><a name="det2_">-</a>
+
+  det2_(a1, a2,
+        b1, b2)
+
+    compute a 2-d determinate
+*/
+#define det2_( a1,a2,b1,b2 ) (( a1 )*( b2 ) - ( a2 )*( b1 ))
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >--------------------------------</a><a name="det3_">-</a>
+
+  det3_(a1, a2, a3,
+       b1, b2, b3,
+       c1, c2, c3)
+
+    compute a 3-d determinate
+*/
+#define det3_( a1,a2,a3,b1,b2,b3,c1,c2,c3 ) ( ( a1 )*det2_( b2,b3,c2,c3 ) \
+                - ( b1 )*det2_( a2,a3,c2,c3 ) + ( c1 )*det2_( a2,a3,b2,b3 ) )
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >--------------------------------</a><a name="dX">-</a>
+
+  dX( p1, p2 )
+  dY( p1, p2 )
+  dZ( p1, p2 )
+
+    given two indices into rows[],
+
+    compute the difference between X, Y, or Z coordinates
+*/
+#define dX( p1,p2 )  ( *( rows[p1] ) - *( rows[p2] ))
+#define dY( p1,p2 )  ( *( rows[p1]+1 ) - *( rows[p2]+1 ))
+#define dZ( p1,p2 )  ( *( rows[p1]+2 ) - *( rows[p2]+2 ))
+#define dW( p1,p2 )  ( *( rows[p1]+3 ) - *( rows[p2]+3 ))
+
+/*============= prototypes in alphabetical order, infrequent at end ======= */
+
+void    qh_backnormal(realT **rows, int numrow, int numcol, boolT sign, coordT *normal, boolT *nearzero);
+void    qh_distplane(pointT *point, facetT *facet, realT *dist);
+facetT *qh_findbest(pointT *point, facetT *startfacet,
+                     boolT bestoutside, boolT isnewfacets, boolT noupper,
+                     realT *dist, boolT *isoutside, int *numpart);
+facetT *qh_findbesthorizon(boolT ischeckmax, pointT *point,
+                     facetT *startfacet, boolT noupper, realT *bestdist, int *numpart);
+facetT *qh_findbestnew(pointT *point, facetT *startfacet, realT *dist,
+                     boolT bestoutside, boolT *isoutside, int *numpart);
+void    qh_gausselim(realT **rows, int numrow, int numcol, boolT *sign, boolT *nearzero);
+realT   qh_getangle(pointT *vect1, pointT *vect2);
+pointT *qh_getcenter(setT *vertices);
+pointT *qh_getcentrum(facetT *facet);
+realT   qh_getdistance(facetT *facet, facetT *neighbor, realT *mindist, realT *maxdist);
+void    qh_normalize(coordT *normal, int dim, boolT toporient);
+void    qh_normalize2 (coordT *normal, int dim, boolT toporient,
+            realT *minnorm, boolT *ismin);
+pointT *qh_projectpoint(pointT *point, facetT *facet, realT dist);
+
+void    qh_setfacetplane(facetT *newfacets);
+void    qh_sethyperplane_det(int dim, coordT **rows, coordT *point0,
+              boolT toporient, coordT *normal, realT *offset, boolT *nearzero);
+void    qh_sethyperplane_gauss(int dim, coordT **rows, pointT *point0,
+             boolT toporient, coordT *normal, coordT *offset, boolT *nearzero);
+boolT   qh_sharpnewfacets(void);
+
+/*========= infrequently used code in geom2.c =============*/
+
+coordT *qh_copypoints(coordT *points, int numpoints, int dimension);
+void    qh_crossproduct(int dim, realT vecA[3], realT vecB[3], realT vecC[3]);
+realT   qh_determinant(realT **rows, int dim, boolT *nearzero);
+realT   qh_detjoggle(pointT *points, int numpoints, int dimension);
+void    qh_detroundoff(void);
+realT   qh_detsimplex(pointT *apex, setT *points, int dim, boolT *nearzero);
+realT   qh_distnorm(int dim, pointT *point, pointT *normal, realT *offsetp);
+realT   qh_distround(int dimension, realT maxabs, realT maxsumabs);
+realT   qh_divzero(realT numer, realT denom, realT mindenom1, boolT *zerodiv);
+realT   qh_facetarea(facetT *facet);
+realT   qh_facetarea_simplex(int dim, coordT *apex, setT *vertices,
+          vertexT *notvertex,  boolT toporient, coordT *normal, realT *offset);
+pointT *qh_facetcenter(setT *vertices);
+facetT *qh_findgooddist(pointT *point, facetT *facetA, realT *distp, facetT **facetlist);
+void    qh_getarea(facetT *facetlist);
+boolT   qh_gram_schmidt(int dim, realT **rows);
+boolT   qh_inthresholds(coordT *normal, realT *angle);
+void    qh_joggleinput(void);
+realT  *qh_maxabsval(realT *normal, int dim);
+setT   *qh_maxmin(pointT *points, int numpoints, int dimension);
+realT   qh_maxouter(void);
+void    qh_maxsimplex(int dim, setT *maxpoints, pointT *points, int numpoints, setT **simplex);
+realT   qh_minabsval(realT *normal, int dim);
+int     qh_mindiff(realT *vecA, realT *vecB, int dim);
+boolT   qh_orientoutside(facetT *facet);
+void    qh_outerinner(facetT *facet, realT *outerplane, realT *innerplane);
+coordT  qh_pointdist(pointT *point1, pointT *point2, int dim);
+void    qh_printmatrix(FILE *fp, const char *string, realT **rows, int numrow, int numcol);
+void    qh_printpoints(FILE *fp, const char *string, setT *points);
+void    qh_projectinput(void);
+void    qh_projectpoints(signed char *project, int n, realT *points,
+             int numpoints, int dim, realT *newpoints, int newdim);
+void    qh_rotateinput(realT **rows);
+void    qh_rotatepoints(realT *points, int numpoints, int dim, realT **rows);
+void    qh_scaleinput(void);
+void    qh_scalelast(coordT *points, int numpoints, int dim, coordT low,
+                   coordT high, coordT newhigh);
+void    qh_scalepoints(pointT *points, int numpoints, int dim,
+                realT *newlows, realT *newhighs);
+boolT   qh_sethalfspace(int dim, coordT *coords, coordT **nextp,
+              coordT *normal, coordT *offset, coordT *feasible);
+coordT *qh_sethalfspace_all(int dim, int count, coordT *halfspaces, pointT *feasible);
+pointT *qh_voronoi_center(int dim, setT *points);
+
+#endif /* qhDEFgeom */
+
+
+
diff --git a/alg/libqhull/geom2.c b/alg/libqhull/geom2.c
new file mode 100644
index 0000000..e242fb3
--- /dev/null
+++ b/alg/libqhull/geom2.c
@@ -0,0 +1,2083 @@
+/*<html><pre>  -<a                             href="qh-geom.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+
+   geom2.c
+   infrequently used geometric routines of qhull
+
+   see qh-geom.htm and geom.h
+
+   Copyright (c) 1993-2012 The Geometry Center.
+   $Id: //main/2011/qhull/src/libqhull/geom2.c#3 $$Change: 1464 $
+   $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+
+   frequently used code goes into geom.c
+*/
+
+#include "qhull_a.h"
+
+/*================== functions in alphabetic order ============*/
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="copypoints">-</a>
+
+  qh_copypoints( points, numpoints, dimension)
+    return qh_malloc'd copy of points
+*/
+coordT *qh_copypoints(coordT *points, int numpoints, int dimension) {
+  int size;
+  coordT *newpoints;
+
+  size= numpoints * dimension * (int)sizeof(coordT);
+  if (!(newpoints=(coordT*)qh_malloc((size_t)size))) {
+    qh_fprintf(qh ferr, 6004, "qhull error: insufficient memory to copy %d points\n",
+        numpoints);
+    qh_errexit(qh_ERRmem, NULL, NULL);
+  }
+  /* newpoints cannot be NULL since above qh_errexit didn't return */
+  /* coverity[var_deref_model] */
+  memcpy((char *)newpoints, (char *)points, (size_t)size);
+  return newpoints;
+} /* copypoints */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="crossproduct">-</a>
+
+  qh_crossproduct( dim, vecA, vecB, vecC )
+    crossproduct of 2 dim vectors
+    C= A x B
+
+  notes:
+    from Glasner, Graphics Gems I, p. 639
+    only defined for dim==3
+*/
+void qh_crossproduct(int dim, realT vecA[3], realT vecB[3], realT vecC[3]){
+
+  if (dim == 3) {
+    vecC[0]=   det2_(vecA[1], vecA[2],
+                     vecB[1], vecB[2]);
+    vecC[1]= - det2_(vecA[0], vecA[2],
+                     vecB[0], vecB[2]);
+    vecC[2]=   det2_(vecA[0], vecA[1],
+                     vecB[0], vecB[1]);
+  }
+} /* vcross */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="determinant">-</a>
+
+  qh_determinant( rows, dim, nearzero )
+    compute signed determinant of a square matrix
+    uses qh.NEARzero to test for degenerate matrices
+
+  returns:
+    determinant
+    overwrites rows and the matrix
+    if dim == 2 or 3
+      nearzero iff determinant < qh NEARzero[dim-1]
+      (!quite correct, not critical)
+    if dim >= 4
+      nearzero iff diagonal[k] < qh NEARzero[k]
+*/
+realT qh_determinant(realT **rows, int dim, boolT *nearzero) {
+  realT det=0;
+  int i;
+  boolT sign= False;
+
+  *nearzero= False;
+  if (dim < 2) {
+    qh_fprintf(qh ferr, 6005, "qhull internal error (qh_determinate): only implemented for dimension >= 2\n");
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }else if (dim == 2) {
+    det= det2_(rows[0][0], rows[0][1],
+                 rows[1][0], rows[1][1]);
+    if (fabs_(det) < qh NEARzero[1])  /* not really correct, what should this be? */
+      *nearzero= True;
+  }else if (dim == 3) {
+    det= det3_(rows[0][0], rows[0][1], rows[0][2],
+                 rows[1][0], rows[1][1], rows[1][2],
+                 rows[2][0], rows[2][1], rows[2][2]);
+    if (fabs_(det) < qh NEARzero[2])  /* not really correct, what should this be? */
+      *nearzero= True;
+  }else {
+    qh_gausselim(rows, dim, dim, &sign, nearzero);  /* if nearzero, diagonal still ok*/
+    det= 1.0;
+    for (i=dim; i--; )
+      det *= (rows[i])[i];
+    if (sign)
+      det= -det;
+  }
+  return det;
+} /* determinant */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="detjoggle">-</a>
+
+  qh_detjoggle( points, numpoints, dimension )
+    determine default max joggle for point array
+      as qh_distround * qh_JOGGLEdefault
+
+  returns:
+    initial value for JOGGLEmax from points and REALepsilon
+
+  notes:
+    computes DISTround since qh_maxmin not called yet
+    if qh SCALElast, last dimension will be scaled later to MAXwidth
+
+    loop duplicated from qh_maxmin
+*/
+realT qh_detjoggle(pointT *points, int numpoints, int dimension) {
+  realT abscoord, distround, joggle, maxcoord, mincoord;
+  pointT *point, *pointtemp;
+  realT maxabs= -REALmax;
+  realT sumabs= 0;
+  realT maxwidth= 0;
+  int k;
+
+  for (k=0; k < dimension; k++) {
+    if (qh SCALElast && k == dimension-1)
+      abscoord= maxwidth;
+    else if (qh DELAUNAY && k == dimension-1) /* will qh_setdelaunay() */
+      abscoord= 2 * maxabs * maxabs;  /* may be low by qh hull_dim/2 */
+    else {
+      maxcoord= -REALmax;
+      mincoord= REALmax;
+      FORALLpoint_(points, numpoints) {
+        maximize_(maxcoord, point[k]);
+        minimize_(mincoord, point[k]);
+      }
+      maximize_(maxwidth, maxcoord-mincoord);
+      abscoord= fmax_(maxcoord, -mincoord);
+    }
+    sumabs += abscoord;
+    maximize_(maxabs, abscoord);
+  } /* for k */
+  distround= qh_distround(qh hull_dim, maxabs, sumabs);
+  joggle= distround * qh_JOGGLEdefault;
+  maximize_(joggle, REALepsilon * qh_JOGGLEdefault);
+  trace2((qh ferr, 2001, "qh_detjoggle: joggle=%2.2g maxwidth=%2.2g\n", joggle, maxwidth));
+  return joggle;
+} /* detjoggle */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="detroundoff">-</a>
+
+  qh_detroundoff()
+    determine maximum roundoff errors from
+      REALepsilon, REALmax, REALmin, qh.hull_dim, qh.MAXabs_coord,
+      qh.MAXsumcoord, qh.MAXwidth, qh.MINdenom_1
+
+    accounts for qh.SETroundoff, qh.RANDOMdist, qh MERGEexact
+      qh.premerge_cos, qh.postmerge_cos, qh.premerge_centrum,
+      qh.postmerge_centrum, qh.MINoutside,
+      qh_RATIOnearinside, qh_COPLANARratio, qh_WIDEcoplanar
+
+  returns:
+    sets qh.DISTround, etc. (see below)
+    appends precision constants to qh.qhull_options
+
+  see:
+    qh_maxmin() for qh.NEARzero
+
+  design:
+    determine qh.DISTround for distance computations
+    determine minimum denominators for qh_divzero
+    determine qh.ANGLEround for angle computations
+    adjust qh.premerge_cos,... for roundoff error
+    determine qh.ONEmerge for maximum error due to a single merge
+    determine qh.NEARinside, qh.MAXcoplanar, qh.MINvisible,
+      qh.MINoutside, qh.WIDEfacet
+    initialize qh.max_vertex and qh.minvertex
+*/
+void qh_detroundoff(void) {
+
+  qh_option("_max-width", NULL, &qh MAXwidth);
+  if (!qh SETroundoff) {
+    qh DISTround= qh_distround(qh hull_dim, qh MAXabs_coord, qh MAXsumcoord);
+    if (qh RANDOMdist)
+      qh DISTround += qh RANDOMfactor * qh MAXabs_coord;
+    qh_option("Error-roundoff", NULL, &qh DISTround);
+  }
+  qh MINdenom= qh MINdenom_1 * qh MAXabs_coord;
+  qh MINdenom_1_2= sqrt(qh MINdenom_1 * qh hull_dim) ;  /* if will be normalized */
+  qh MINdenom_2= qh MINdenom_1_2 * qh MAXabs_coord;
+                                              /* for inner product */
+  qh ANGLEround= 1.01 * qh hull_dim * REALepsilon;
+  if (qh RANDOMdist)
+    qh ANGLEround += qh RANDOMfactor;
+  if (qh premerge_cos < REALmax/2) {
+    qh premerge_cos -= qh ANGLEround;
+    if (qh RANDOMdist)
+      qh_option("Angle-premerge-with-random", NULL, &qh premerge_cos);
+  }
+  if (qh postmerge_cos < REALmax/2) {
+    qh postmerge_cos -= qh ANGLEround;
+    if (qh RANDOMdist)
+      qh_option("Angle-postmerge-with-random", NULL, &qh postmerge_cos);
+  }
+  qh premerge_centrum += 2 * qh DISTround;    /*2 for centrum and distplane()*/
+  qh postmerge_centrum += 2 * qh DISTround;
+  if (qh RANDOMdist && (qh MERGEexact || qh PREmerge))
+    qh_option("Centrum-premerge-with-random", NULL, &qh premerge_centrum);
+  if (qh RANDOMdist && qh POSTmerge)
+    qh_option("Centrum-postmerge-with-random", NULL, &qh postmerge_centrum);
+  { /* compute ONEmerge, max vertex offset for merging simplicial facets */
+    realT maxangle= 1.0, maxrho;
+
+    minimize_(maxangle, qh premerge_cos);
+    minimize_(maxangle, qh postmerge_cos);
+    /* max diameter * sin theta + DISTround for vertex to its hyperplane */
+    qh ONEmerge= sqrt((realT)qh hull_dim) * qh MAXwidth *
+      sqrt(1.0 - maxangle * maxangle) + qh DISTround;
+    maxrho= qh hull_dim * qh premerge_centrum + qh DISTround;
+    maximize_(qh ONEmerge, maxrho);
+    maxrho= qh hull_dim * qh postmerge_centrum + qh DISTround;
+    maximize_(qh ONEmerge, maxrho);
+    if (qh MERGING)
+      qh_option("_one-merge", NULL, &qh ONEmerge);
+  }
+  qh NEARinside= qh ONEmerge * qh_RATIOnearinside; /* only used if qh KEEPnearinside */
+  if (qh JOGGLEmax < REALmax/2 && (qh KEEPcoplanar || qh KEEPinside)) {
+    realT maxdist;             /* adjust qh.NEARinside for joggle */
+    qh KEEPnearinside= True;
+    maxdist= sqrt((realT)qh hull_dim) * qh JOGGLEmax + qh DISTround;
+    maxdist= 2*maxdist;        /* vertex and coplanar point can joggle in opposite directions */
+    maximize_(qh NEARinside, maxdist);  /* must agree with qh_nearcoplanar() */
+  }
+  if (qh KEEPnearinside)
+    qh_option("_near-inside", NULL, &qh NEARinside);
+  if (qh JOGGLEmax < qh DISTround) {
+    qh_fprintf(qh ferr, 6006, "qhull error: the joggle for 'QJn', %.2g, is below roundoff for distance computations, %.2g\n",
+         qh JOGGLEmax, qh DISTround);
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  if (qh MINvisible > REALmax/2) {
+    if (!qh MERGING)
+      qh MINvisible= qh DISTround;
+    else if (qh hull_dim <= 3)
+      qh MINvisible= qh premerge_centrum;
+    else
+      qh MINvisible= qh_COPLANARratio * qh premerge_centrum;
+    if (qh APPROXhull && qh MINvisible > qh MINoutside)
+      qh MINvisible= qh MINoutside;
+    qh_option("Visible-distance", NULL, &qh MINvisible);
+  }
+  if (qh MAXcoplanar > REALmax/2) {
+    qh MAXcoplanar= qh MINvisible;
+    qh_option("U-coplanar-distance", NULL, &qh MAXcoplanar);
+  }
+  if (!qh APPROXhull) {             /* user may specify qh MINoutside */
+    qh MINoutside= 2 * qh MINvisible;
+    if (qh premerge_cos < REALmax/2)
+      maximize_(qh MINoutside, (1- qh premerge_cos) * qh MAXabs_coord);
+    qh_option("Width-outside", NULL, &qh MINoutside);
+  }
+  qh WIDEfacet= qh MINoutside;
+  maximize_(qh WIDEfacet, qh_WIDEcoplanar * qh MAXcoplanar);
+  maximize_(qh WIDEfacet, qh_WIDEcoplanar * qh MINvisible);
+  qh_option("_wide-facet", NULL, &qh WIDEfacet);
+  if (qh MINvisible > qh MINoutside + 3 * REALepsilon
+  && !qh BESToutside && !qh FORCEoutput)
+    qh_fprintf(qh ferr, 7001, "qhull input warning: minimum visibility V%.2g is greater than \nminimum outside W%.2g.  Flipped facets are likely.\n",
+             qh MINvisible, qh MINoutside);
+  qh max_vertex= qh DISTround;
+  qh min_vertex= -qh DISTround;
+  /* numeric constants reported in printsummary */
+} /* detroundoff */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="detsimplex">-</a>
+
+  qh_detsimplex( apex, points, dim, nearzero )
+    compute determinant of a simplex with point apex and base points
+
+  returns:
+     signed determinant and nearzero from qh_determinant
+
+  notes:
+     uses qh.gm_matrix/qh.gm_row (assumes they're big enough)
+
+  design:
+    construct qm_matrix by subtracting apex from points
+    compute determinate
+*/
+realT qh_detsimplex(pointT *apex, setT *points, int dim, boolT *nearzero) {
+  pointT *coorda, *coordp, *gmcoord, *point, **pointp;
+  coordT **rows;
+  int k,  i=0;
+  realT det;
+
+  zinc_(Zdetsimplex);
+  gmcoord= qh gm_matrix;
+  rows= qh gm_row;
+  FOREACHpoint_(points) {
+    if (i == dim)
+      break;
+    rows[i++]= gmcoord;
+    coordp= point;
+    coorda= apex;
+    for (k=dim; k--; )
+      *(gmcoord++)= *coordp++ - *coorda++;
+  }
+  if (i < dim) {
+    qh_fprintf(qh ferr, 6007, "qhull internal error (qh_detsimplex): #points %d < dimension %d\n",
+               i, dim);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  det= qh_determinant(rows, dim, nearzero);
+  trace2((qh ferr, 2002, "qh_detsimplex: det=%2.2g for point p%d, dim %d, nearzero? %d\n",
+          det, qh_pointid(apex), dim, *nearzero));
+  return det;
+} /* detsimplex */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="distnorm">-</a>
+
+  qh_distnorm( dim, point, normal, offset )
+    return distance from point to hyperplane at normal/offset
+
+  returns:
+    dist
+
+  notes:
+    dist > 0 if point is outside of hyperplane
+
+  see:
+    qh_distplane in geom.c
+*/
+realT qh_distnorm(int dim, pointT *point, pointT *normal, realT *offsetp) {
+  coordT *normalp= normal, *coordp= point;
+  realT dist;
+  int k;
+
+  dist= *offsetp;
+  for (k=dim; k--; )
+    dist += *(coordp++) * *(normalp++);
+  return dist;
+} /* distnorm */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="distround">-</a>
+
+  qh_distround(dimension, maxabs, maxsumabs )
+    compute maximum round-off error for a distance computation
+      to a normalized hyperplane
+    maxabs is the maximum absolute value of a coordinate
+    maxsumabs is the maximum possible sum of absolute coordinate values
+
+  returns:
+    max dist round for REALepsilon
+
+  notes:
+    calculate roundoff error according to
+    Lemma 3.2-1 of Golub and van Loan "Matrix Computation"
+    use sqrt(dim) since one vector is normalized
+      or use maxsumabs since one vector is < 1
+*/
+realT qh_distround(int dimension, realT maxabs, realT maxsumabs) {
+  realT maxdistsum, maxround;
+
+  maxdistsum= sqrt((realT)dimension) * maxabs;
+  minimize_( maxdistsum, maxsumabs);
+  maxround= REALepsilon * (dimension * maxdistsum * 1.01 + maxabs);
+              /* adds maxabs for offset */
+  trace4((qh ferr, 4008, "qh_distround: %2.2g maxabs %2.2g maxsumabs %2.2g maxdistsum %2.2g\n",
+                 maxround, maxabs, maxsumabs, maxdistsum));
+  return maxround;
+} /* distround */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="divzero">-</a>
+
+  qh_divzero( numer, denom, mindenom1, zerodiv )
+    divide by a number that's nearly zero
+    mindenom1= minimum denominator for dividing into 1.0
+
+  returns:
+    quotient
+    sets zerodiv and returns 0.0 if it would overflow
+
+  design:
+    if numer is nearly zero and abs(numer) < abs(denom)
+      return numer/denom
+    else if numer is nearly zero
+      return 0 and zerodiv
+    else if denom/numer non-zero
+      return numer/denom
+    else
+      return 0 and zerodiv
+*/
+realT qh_divzero(realT numer, realT denom, realT mindenom1, boolT *zerodiv) {
+  realT temp, numerx, denomx;
+
+
+  if (numer < mindenom1 && numer > -mindenom1) {
+    numerx= fabs_(numer);
+    denomx= fabs_(denom);
+    if (numerx < denomx) {
+      *zerodiv= False;
+      return numer/denom;
+    }else {
+      *zerodiv= True;
+      return 0.0;
+    }
+  }
+  temp= denom/numer;
+  if (temp > mindenom1 || temp < -mindenom1) {
+    *zerodiv= False;
+    return numer/denom;
+  }else {
+    *zerodiv= True;
+    return 0.0;
+  }
+} /* divzero */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="facetarea">-</a>
+
+  qh_facetarea( facet )
+    return area for a facet
+
+  notes:
+    if non-simplicial,
+      uses centrum to triangulate facet and sums the projected areas.
+    if (qh DELAUNAY),
+      computes projected area instead for last coordinate
+    assumes facet->normal exists
+    projecting tricoplanar facets to the hyperplane does not appear to make a difference
+
+  design:
+    if simplicial
+      compute area
+    else
+      for each ridge
+        compute area from centrum to ridge
+    negate area if upper Delaunay facet
+*/
+realT qh_facetarea(facetT *facet) {
+  vertexT *apex;
+  pointT *centrum;
+  realT area= 0.0;
+  ridgeT *ridge, **ridgep;
+
+  if (facet->simplicial) {
+    apex= SETfirstt_(facet->vertices, vertexT);
+    area= qh_facetarea_simplex(qh hull_dim, apex->point, facet->vertices,
+                    apex, facet->toporient, facet->normal, &facet->offset);
+  }else {
+    if (qh CENTERtype == qh_AScentrum)
+      centrum= facet->center;
+    else
+      centrum= qh_getcentrum(facet);
+    FOREACHridge_(facet->ridges)
+      area += qh_facetarea_simplex(qh hull_dim, centrum, ridge->vertices,
+                 NULL, (boolT)(ridge->top == facet),  facet->normal, &facet->offset);
+    if (qh CENTERtype != qh_AScentrum)
+      qh_memfree(centrum, qh normal_size);
+  }
+  if (facet->upperdelaunay && qh DELAUNAY)
+    area= -area;  /* the normal should be [0,...,1] */
+  trace4((qh ferr, 4009, "qh_facetarea: f%d area %2.2g\n", facet->id, area));
+  return area;
+} /* facetarea */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="facetarea_simplex">-</a>
+
+  qh_facetarea_simplex( dim, apex, vertices, notvertex, toporient, normal, offset )
+    return area for a simplex defined by
+      an apex, a base of vertices, an orientation, and a unit normal
+    if simplicial or tricoplanar facet,
+      notvertex is defined and it is skipped in vertices
+
+  returns:
+    computes area of simplex projected to plane [normal,offset]
+    returns 0 if vertex too far below plane (qh WIDEfacet)
+      vertex can't be apex of tricoplanar facet
+
+  notes:
+    if (qh DELAUNAY),
+      computes projected area instead for last coordinate
+    uses qh gm_matrix/gm_row and qh hull_dim
+    helper function for qh_facetarea
+
+  design:
+    if Notvertex
+      translate simplex to apex
+    else
+      project simplex to normal/offset
+      translate simplex to apex
+    if Delaunay
+      set last row/column to 0 with -1 on diagonal
+    else
+      set last row to Normal
+    compute determinate
+    scale and flip sign for area
+*/
+realT qh_facetarea_simplex(int dim, coordT *apex, setT *vertices,
+        vertexT *notvertex,  boolT toporient, coordT *normal, realT *offset) {
+  pointT *coorda, *coordp, *gmcoord;
+  coordT **rows, *normalp;
+  int k,  i=0;
+  realT area, dist;
+  vertexT *vertex, **vertexp;
+  boolT nearzero;
+
+  gmcoord= qh gm_matrix;
+  rows= qh gm_row;
+  FOREACHvertex_(vertices) {
+    if (vertex == notvertex)
+      continue;
+    rows[i++]= gmcoord;
+    coorda= apex;
+    coordp= vertex->point;
+    normalp= normal;
+    if (notvertex) {
+      for (k=dim; k--; )
+        *(gmcoord++)= *coordp++ - *coorda++;
+    }else {
+      dist= *offset;
+      for (k=dim; k--; )
+        dist += *coordp++ * *normalp++;
+      if (dist < -qh WIDEfacet) {
+        zinc_(Znoarea);
+        return 0.0;
+      }
+      coordp= vertex->point;
+      normalp= normal;
+      for (k=dim; k--; )
+        *(gmcoord++)= (*coordp++ - dist * *normalp++) - *coorda++;
+    }
+  }
+  if (i != dim-1) {
+    qh_fprintf(qh ferr, 6008, "qhull internal error (qh_facetarea_simplex): #points %d != dim %d -1\n",
+               i, dim);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  rows[i]= gmcoord;
+  if (qh DELAUNAY) {
+    for (i=0; i < dim-1; i++)
+      rows[i][dim-1]= 0.0;
+    for (k=dim; k--; )
+      *(gmcoord++)= 0.0;
+    rows[dim-1][dim-1]= -1.0;
+  }else {
+    normalp= normal;
+    for (k=dim; k--; )
+      *(gmcoord++)= *normalp++;
+  }
+  zinc_(Zdetsimplex);
+  area= qh_determinant(rows, dim, &nearzero);
+  if (toporient)
+    area= -area;
+  area *= qh AREAfactor;
+  trace4((qh ferr, 4010, "qh_facetarea_simplex: area=%2.2g for point p%d, toporient %d, nearzero? %d\n",
+          area, qh_pointid(apex), toporient, nearzero));
+  return area;
+} /* facetarea_simplex */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="facetcenter">-</a>
+
+  qh_facetcenter( vertices )
+    return Voronoi center (Voronoi vertex) for a facet's vertices
+
+  returns:
+    return temporary point equal to the center
+
+  see:
+    qh_voronoi_center()
+*/
+pointT *qh_facetcenter(setT *vertices) {
+  setT *points= qh_settemp(qh_setsize(vertices));
+  vertexT *vertex, **vertexp;
+  pointT *center;
+
+  FOREACHvertex_(vertices)
+    qh_setappend(&points, vertex->point);
+  center= qh_voronoi_center(qh hull_dim-1, points);
+  qh_settempfree(&points);
+  return center;
+} /* facetcenter */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="findgooddist">-</a>
+
+  qh_findgooddist( point, facetA, dist, facetlist )
+    find best good facet visible for point from facetA
+    assumes facetA is visible from point
+
+  returns:
+    best facet, i.e., good facet that is furthest from point
+      distance to best facet
+      NULL if none
+
+    moves good, visible facets (and some other visible facets)
+      to end of qh facet_list
+
+  notes:
+    uses qh visit_id
+
+  design:
+    initialize bestfacet if facetA is good
+    move facetA to end of facetlist
+    for each facet on facetlist
+      for each unvisited neighbor of facet
+        move visible neighbors to end of facetlist
+        update best good neighbor
+        if no good neighbors, update best facet
+*/
+facetT *qh_findgooddist(pointT *point, facetT *facetA, realT *distp,
+               facetT **facetlist) {
+  realT bestdist= -REALmax, dist;
+  facetT *neighbor, **neighborp, *bestfacet=NULL, *facet;
+  boolT goodseen= False;
+
+  if (facetA->good) {
+    zzinc_(Zcheckpart);  /* calls from check_bestdist occur after print stats */
+    qh_distplane(point, facetA, &bestdist);
+    bestfacet= facetA;
+    goodseen= True;
+  }
+  qh_removefacet(facetA);
+  qh_appendfacet(facetA);
+  *facetlist= facetA;
+  facetA->visitid= ++qh visit_id;
+  FORALLfacet_(*facetlist) {
+    FOREACHneighbor_(facet) {
+      if (neighbor->visitid == qh visit_id)
+        continue;
+      neighbor->visitid= qh visit_id;
+      if (goodseen && !neighbor->good)
+        continue;
+      zzinc_(Zcheckpart);
+      qh_distplane(point, neighbor, &dist);
+      if (dist > 0) {
+        qh_removefacet(neighbor);
+        qh_appendfacet(neighbor);
+        if (neighbor->good) {
+          goodseen= True;
+          if (dist > bestdist) {
+            bestdist= dist;
+            bestfacet= neighbor;
+          }
+        }
+      }
+    }
+  }
+  if (bestfacet) {
+    *distp= bestdist;
+    trace2((qh ferr, 2003, "qh_findgooddist: p%d is %2.2g above good facet f%d\n",
+      qh_pointid(point), bestdist, bestfacet->id));
+    return bestfacet;
+  }
+  trace4((qh ferr, 4011, "qh_findgooddist: no good facet for p%d above f%d\n",
+      qh_pointid(point), facetA->id));
+  return NULL;
+}  /* findgooddist */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="getarea">-</a>
+
+  qh_getarea( facetlist )
+    set area of all facets in facetlist
+    collect statistics
+    nop if hasAreaVolume
+
+  returns:
+    sets qh totarea/totvol to total area and volume of convex hull
+    for Delaunay triangulation, computes projected area of the lower or upper hull
+      ignores upper hull if qh ATinfinity
+
+  notes:
+    could compute outer volume by expanding facet area by rays from interior
+    the following attempt at perpendicular projection underestimated badly:
+      qh.totoutvol += (-dist + facet->maxoutside + qh DISTround)
+                            * area/ qh hull_dim;
+  design:
+    for each facet on facetlist
+      compute facet->area
+      update qh.totarea and qh.totvol
+*/
+void qh_getarea(facetT *facetlist) {
+  realT area;
+  realT dist;
+  facetT *facet;
+
+  if (qh hasAreaVolume)
+    return;
+  if (qh REPORTfreq)
+    qh_fprintf(qh ferr, 8020, "computing area of each facet and volume of the convex hull\n");
+  else
+    trace1((qh ferr, 1001, "qh_getarea: computing volume and area for each facet\n"));
+  qh totarea= qh totvol= 0.0;
+  FORALLfacet_(facetlist) {
+    if (!facet->normal)
+      continue;
+    if (facet->upperdelaunay && qh ATinfinity)
+      continue;
+    if (!facet->isarea) {
+      facet->f.area= qh_facetarea(facet);
+      facet->isarea= True;
+    }
+    area= facet->f.area;
+    if (qh DELAUNAY) {
+      if (facet->upperdelaunay == qh UPPERdelaunay)
+        qh totarea += area;
+    }else {
+      qh totarea += area;
+      qh_distplane(qh interior_point, facet, &dist);
+      qh totvol += -dist * area/ qh hull_dim;
+    }
+    if (qh PRINTstatistics) {
+      wadd_(Wareatot, area);
+      wmax_(Wareamax, area);
+      wmin_(Wareamin, area);
+    }
+  }
+  qh hasAreaVolume= True;
+} /* getarea */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="gram_schmidt">-</a>
+
+  qh_gram_schmidt( dim, row )
+    implements Gram-Schmidt orthogonalization by rows
+
+  returns:
+    false if zero norm
+    overwrites rows[dim][dim]
+
+  notes:
+    see Golub & van Loan Algorithm 6.2-2
+    overflow due to small divisors not handled
+
+  design:
+    for each row
+      compute norm for row
+      if non-zero, normalize row
+      for each remaining rowA
+        compute inner product of row and rowA
+        reduce rowA by row * inner product
+*/
+boolT qh_gram_schmidt(int dim, realT **row) {
+  realT *rowi, *rowj, norm;
+  int i, j, k;
+
+  for (i=0; i < dim; i++) {
+    rowi= row[i];
+    for (norm= 0.0, k= dim; k--; rowi++)
+      norm += *rowi * *rowi;
+    norm= sqrt(norm);
+    wmin_(Wmindenom, norm);
+    if (norm == 0.0)  /* either 0 or overflow due to sqrt */
+      return False;
+    for (k=dim; k--; )
+      *(--rowi) /= norm;
+    for (j=i+1; j < dim; j++) {
+      rowj= row[j];
+      for (norm= 0.0, k=dim; k--; )
+        norm += *rowi++ * *rowj++;
+      for (k=dim; k--; )
+        *(--rowj) -= *(--rowi) * norm;
+    }
+  }
+  return True;
+} /* gram_schmidt */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="inthresholds">-</a>
+
+  qh_inthresholds( normal, angle )
+    return True if normal within qh.lower_/upper_threshold
+
+  returns:
+    estimate of angle by summing of threshold diffs
+      angle may be NULL
+      smaller "angle" is better
+
+  notes:
+    invalid if qh.SPLITthresholds
+
+  see:
+    qh.lower_threshold in qh_initbuild()
+    qh_initthresholds()
+
+  design:
+    for each dimension
+      test threshold
+*/
+boolT qh_inthresholds(coordT *normal, realT *angle) {
+  boolT within= True;
+  int k;
+  realT threshold;
+
+  if (angle)
+    *angle= 0.0;
+  for (k=0; k < qh hull_dim; k++) {
+    threshold= qh lower_threshold[k];
+    if (threshold > -REALmax/2) {
+      if (normal[k] < threshold)
+        within= False;
+      if (angle) {
+        threshold -= normal[k];
+        *angle += fabs_(threshold);
+      }
+    }
+    if (qh upper_threshold[k] < REALmax/2) {
+      threshold= qh upper_threshold[k];
+      if (normal[k] > threshold)
+        within= False;
+      if (angle) {
+        threshold -= normal[k];
+        *angle += fabs_(threshold);
+      }
+    }
+  }
+  return within;
+} /* inthresholds */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="joggleinput">-</a>
+
+  qh_joggleinput()
+    randomly joggle input to Qhull by qh.JOGGLEmax
+    initial input is qh.first_point/qh.num_points of qh.hull_dim
+      repeated calls use qh.input_points/qh.num_points
+
+  returns:
+    joggles points at qh.first_point/qh.num_points
+    copies data to qh.input_points/qh.input_malloc if first time
+    determines qh.JOGGLEmax if it was zero
+    if qh.DELAUNAY
+      computes the Delaunay projection of the joggled points
+
+  notes:
+    if qh.DELAUNAY, unnecessarily joggles the last coordinate
+    the initial 'QJn' may be set larger than qh_JOGGLEmaxincrease
+
+  design:
+    if qh.DELAUNAY
+      set qh.SCALElast for reduced precision errors
+    if first call
+      initialize qh.input_points to the original input points
+      if qh.JOGGLEmax == 0
+        determine default qh.JOGGLEmax
+    else
+      increase qh.JOGGLEmax according to qh.build_cnt
+    joggle the input by adding a random number in [-qh.JOGGLEmax,qh.JOGGLEmax]
+    if qh.DELAUNAY
+      sets the Delaunay projection
+*/
+void qh_joggleinput(void) {
+  int i, seed, size;
+  coordT *coordp, *inputp;
+  realT randr, randa, randb;
+
+  if (!qh input_points) { /* first call */
+    qh input_points= qh first_point;
+    qh input_malloc= qh POINTSmalloc;
+    size= qh num_points * qh hull_dim * sizeof(coordT);
+    if (!(qh first_point=(coordT*)qh_malloc((size_t)size))) {
+      qh_fprintf(qh ferr, 6009, "qhull error: insufficient memory to joggle %d points\n",
+          qh num_points);
+      qh_errexit(qh_ERRmem, NULL, NULL);
+    }
+    qh POINTSmalloc= True;
+    if (qh JOGGLEmax == 0.0) {
+      qh JOGGLEmax= qh_detjoggle(qh input_points, qh num_points, qh hull_dim);
+      qh_option("QJoggle", NULL, &qh JOGGLEmax);
+    }
+  }else {                 /* repeated call */
+    if (!qh RERUN && qh build_cnt > qh_JOGGLEretry) {
+      if (((qh build_cnt-qh_JOGGLEretry-1) % qh_JOGGLEagain) == 0) {
+        realT maxjoggle= qh MAXwidth * qh_JOGGLEmaxincrease;
+        if (qh JOGGLEmax < maxjoggle) {
+          qh JOGGLEmax *= qh_JOGGLEincrease;
+          minimize_(qh JOGGLEmax, maxjoggle);
+        }
+      }
+    }
+    qh_option("QJoggle", NULL, &qh JOGGLEmax);
+  }
+  if (qh build_cnt > 1 && qh JOGGLEmax > fmax_(qh MAXwidth/4, 0.1)) {
+      qh_fprintf(qh ferr, 6010, "qhull error: the current joggle for 'QJn', %.2g, is too large for the width\nof the input.  If possible, recompile Qhull with higher-precision reals.\n",
+                qh JOGGLEmax);
+      qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  /* for some reason, using qh ROTATErandom and qh_RANDOMseed does not repeat the run. Use 'TRn' instead */
+  seed= qh_RANDOMint;
+  qh_option("_joggle-seed", &seed, NULL);
+  trace0((qh ferr, 6, "qh_joggleinput: joggle input by %2.2g with seed %d\n",
+    qh JOGGLEmax, seed));
+  inputp= qh input_points;
+  coordp= qh first_point;
+  randa= 2.0 * qh JOGGLEmax/qh_RANDOMmax;
+  randb= -qh JOGGLEmax;
+  size= qh num_points * qh hull_dim;
+  for (i=size; i--; ) {
+    randr= qh_RANDOMint;
+    *(coordp++)= *(inputp++) + (randr * randa + randb);
+  }
+  if (qh DELAUNAY) {
+    qh last_low= qh last_high= qh last_newhigh= REALmax;
+    qh_setdelaunay(qh hull_dim, qh num_points, qh first_point);
+  }
+} /* joggleinput */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="maxabsval">-</a>
+
+  qh_maxabsval( normal, dim )
+    return pointer to maximum absolute value of a dim vector
+    returns NULL if dim=0
+*/
+realT *qh_maxabsval(realT *normal, int dim) {
+  realT maxval= -REALmax;
+  realT *maxp= NULL, *colp, absval;
+  int k;
+
+  for (k=dim, colp= normal; k--; colp++) {
+    absval= fabs_(*colp);
+    if (absval > maxval) {
+      maxval= absval;
+      maxp= colp;
+    }
+  }
+  return maxp;
+} /* maxabsval */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="maxmin">-</a>
+
+  qh_maxmin( points, numpoints, dimension )
+    return max/min points for each dimension
+    determine max and min coordinates
+
+  returns:
+    returns a temporary set of max and min points
+      may include duplicate points. Does not include qh.GOODpoint
+    sets qh.NEARzero, qh.MAXabs_coord, qh.MAXsumcoord, qh.MAXwidth
+         qh.MAXlastcoord, qh.MINlastcoord
+    initializes qh.max_outside, qh.min_vertex, qh.WAScoplanar, qh.ZEROall_ok
+
+  notes:
+    loop duplicated in qh_detjoggle()
+
+  design:
+    initialize global precision variables
+    checks definition of REAL...
+    for each dimension
+      for each point
+        collect maximum and minimum point
+      collect maximum of maximums and minimum of minimums
+      determine qh.NEARzero for Gaussian Elimination
+*/
+setT *qh_maxmin(pointT *points, int numpoints, int dimension) {
+  int k;
+  realT maxcoord, temp;
+  pointT *minimum, *maximum, *point, *pointtemp;
+  setT *set;
+
+  qh max_outside= 0.0;
+  qh MAXabs_coord= 0.0;
+  qh MAXwidth= -REALmax;
+  qh MAXsumcoord= 0.0;
+  qh min_vertex= 0.0;
+  qh WAScoplanar= False;
+  if (qh ZEROcentrum)
+    qh ZEROall_ok= True;
+  if (REALmin < REALepsilon && REALmin < REALmax && REALmin > -REALmax
+  && REALmax > 0.0 && -REALmax < 0.0)
+    ; /* all ok */
+  else {
+    qh_fprintf(qh ferr, 6011, "qhull error: floating point constants in user.h are wrong\n\
+REALepsilon %g REALmin %g REALmax %g -REALmax %g\n",
+             REALepsilon, REALmin, REALmax, -REALmax);
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  set= qh_settemp(2*dimension);
+  for (k=0; k < dimension; k++) {
+    if (points == qh GOODpointp)
+      minimum= maximum= points + dimension;
+    else
+      minimum= maximum= points;
+    FORALLpoint_(points, numpoints) {
+      if (point == qh GOODpointp)
+        continue;
+      if (maximum[k] < point[k])
+        maximum= point;
+      else if (minimum[k] > point[k])
+        minimum= point;
+    }
+    if (k == dimension-1) {
+      qh MINlastcoord= minimum[k];
+      qh MAXlastcoord= maximum[k];
+    }
+    if (qh SCALElast && k == dimension-1)
+      maxcoord= qh MAXwidth;
+    else {
+      maxcoord= fmax_(maximum[k], -minimum[k]);
+      if (qh GOODpointp) {
+        temp= fmax_(qh GOODpointp[k], -qh GOODpointp[k]);
+        maximize_(maxcoord, temp);
+      }
+      temp= maximum[k] - minimum[k];
+      maximize_(qh MAXwidth, temp);
+    }
+    maximize_(qh MAXabs_coord, maxcoord);
+    qh MAXsumcoord += maxcoord;
+    qh_setappend(&set, maximum);
+    qh_setappend(&set, minimum);
+    /* calculation of qh NEARzero is based on error formula 4.4-13 of
+       Golub & van Loan, authors say n^3 can be ignored and 10 be used in
+       place of rho */
+    qh NEARzero[k]= 80 * qh MAXsumcoord * REALepsilon;
+  }
+  if (qh IStracing >=1)
+    qh_printpoints(qh ferr, "qh_maxmin: found the max and min points(by dim):", set);
+  return(set);
+} /* maxmin */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="maxouter">-</a>
+
+  qh_maxouter()
+    return maximum distance from facet to outer plane
+    normally this is qh.max_outside+qh.DISTround
+    does not include qh.JOGGLEmax
+
+  see:
+    qh_outerinner()
+
+  notes:
+    need to add another qh.DISTround if testing actual point with computation
+
+  for joggle:
+    qh_setfacetplane() updated qh.max_outer for Wnewvertexmax (max distance to vertex)
+    need to use Wnewvertexmax since could have a coplanar point for a high
+      facet that is replaced by a low facet
+    need to add qh.JOGGLEmax if testing input points
+*/
+realT qh_maxouter(void) {
+  realT dist;
+
+  dist= fmax_(qh max_outside, qh DISTround);
+  dist += qh DISTround;
+  trace4((qh ferr, 4012, "qh_maxouter: max distance from facet to outer plane is %2.2g max_outside is %2.2g\n", dist, qh max_outside));
+  return dist;
+} /* maxouter */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="maxsimplex">-</a>
+
+  qh_maxsimplex( dim, maxpoints, points, numpoints, simplex )
+    determines maximum simplex for a set of points
+    starts from points already in simplex
+    skips qh.GOODpointp (assumes that it isn't in maxpoints)
+
+  returns:
+    simplex with dim+1 points
+
+  notes:
+    assumes at least pointsneeded points in points
+    maximizes determinate for x,y,z,w, etc.
+    uses maxpoints as long as determinate is clearly non-zero
+
+  design:
+    initialize simplex with at least two points
+      (find points with max or min x coordinate)
+    for each remaining dimension
+      add point that maximizes the determinate
+        (use points from maxpoints first)
+*/
+void qh_maxsimplex(int dim, setT *maxpoints, pointT *points, int numpoints, setT **simplex) {
+  pointT *point, **pointp, *pointtemp, *maxpoint, *minx=NULL, *maxx=NULL;
+  boolT nearzero, maxnearzero= False;
+  int k, sizinit;
+  realT maxdet= -REALmax, det, mincoord= REALmax, maxcoord= -REALmax;
+
+  sizinit= qh_setsize(*simplex);
+  if (sizinit < 2) {
+    if (qh_setsize(maxpoints) >= 2) {
+      FOREACHpoint_(maxpoints) {
+        if (maxcoord < point[0]) {
+          maxcoord= point[0];
+          maxx= point;
+        }
+        if (mincoord > point[0]) {
+          mincoord= point[0];
+          minx= point;
+        }
+      }
+    }else {
+      FORALLpoint_(points, numpoints) {
+        if (point == qh GOODpointp)
+          continue;
+        if (maxcoord < point[0]) {
+          maxcoord= point[0];
+          maxx= point;
+        }
+        if (mincoord > point[0]) {
+          mincoord= point[0];
+          minx= point;
+        }
+      }
+    }
+    qh_setunique(simplex, minx);
+    if (qh_setsize(*simplex) < 2)
+      qh_setunique(simplex, maxx);
+    sizinit= qh_setsize(*simplex);
+    if (sizinit < 2) {
+      qh_precision("input has same x coordinate");
+      if (zzval_(Zsetplane) > qh hull_dim+1) {
+        qh_fprintf(qh ferr, 6012, "qhull precision error (qh_maxsimplex for voronoi_center):\n%d points with the same x coordinate.\n",
+                 qh_setsize(maxpoints)+numpoints);
+        qh_errexit(qh_ERRprec, NULL, NULL);
+      }else {
+        qh_fprintf(qh ferr, 6013, "qhull input error: input is less than %d-dimensional since it has the same x coordinate\n", qh hull_dim);
+        qh_errexit(qh_ERRinput, NULL, NULL);
+      }
+    }
+  }
+  for (k=sizinit; k < dim+1; k++) {
+    maxpoint= NULL;
+    maxdet= -REALmax;
+    FOREACHpoint_(maxpoints) {
+      if (!qh_setin(*simplex, point)) {
+        det= qh_detsimplex(point, *simplex, k, &nearzero);
+        if ((det= fabs_(det)) > maxdet) {
+          maxdet= det;
+          maxpoint= point;
+          maxnearzero= nearzero;
+        }
+      }
+    }
+    if (!maxpoint || maxnearzero) {
+      zinc_(Zsearchpoints);
+      if (!maxpoint) {
+        trace0((qh ferr, 7, "qh_maxsimplex: searching all points for %d-th initial vertex.\n", k+1));
+      }else {
+        trace0((qh ferr, 8, "qh_maxsimplex: searching all points for %d-th initial vertex, better than p%d det %2.2g\n",
+                k+1, qh_pointid(maxpoint), maxdet));
+      }
+      FORALLpoint_(points, numpoints) {
+        if (point == qh GOODpointp)
+          continue;
+        if (!qh_setin(*simplex, point)) {
+          det= qh_detsimplex(point, *simplex, k, &nearzero);
+          if ((det= fabs_(det)) > maxdet) {
+            maxdet= det;
+            maxpoint= point;
+            maxnearzero= nearzero;
+          }
+        }
+      }
+    } /* !maxpoint */
+    if (!maxpoint) {
+      qh_fprintf(qh ferr, 6014, "qhull internal error (qh_maxsimplex): not enough points available\n");
+      qh_errexit(qh_ERRqhull, NULL, NULL);
+    }
+    qh_setappend(simplex, maxpoint);
+    trace1((qh ferr, 1002, "qh_maxsimplex: selected point p%d for %d`th initial vertex, det=%2.2g\n",
+            qh_pointid(maxpoint), k+1, maxdet));
+  } /* k */
+} /* maxsimplex */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="minabsval">-</a>
+
+  qh_minabsval( normal, dim )
+    return minimum absolute value of a dim vector
+*/
+realT qh_minabsval(realT *normal, int dim) {
+  realT minval= 0;
+  realT maxval= 0;
+  realT *colp;
+  int k;
+
+  for (k=dim, colp=normal; k--; colp++) {
+    maximize_(maxval, *colp);
+    minimize_(minval, *colp);
+  }
+  return fmax_(maxval, -minval);
+} /* minabsval */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="mindiff">-</a>
+
+  qh_mindif ( vecA, vecB, dim )
+    return index of min abs. difference of two vectors
+*/
+int qh_mindiff(realT *vecA, realT *vecB, int dim) {
+  realT mindiff= REALmax, diff;
+  realT *vecAp= vecA, *vecBp= vecB;
+  int k, mink= 0;
+
+  for (k=0; k < dim; k++) {
+    diff= *vecAp++ - *vecBp++;
+    diff= fabs_(diff);
+    if (diff < mindiff) {
+      mindiff= diff;
+      mink= k;
+    }
+  }
+  return mink;
+} /* mindiff */
+
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="orientoutside">-</a>
+
+  qh_orientoutside( facet  )
+    make facet outside oriented via qh.interior_point
+
+  returns:
+    True if facet reversed orientation.
+*/
+boolT qh_orientoutside(facetT *facet) {
+  int k;
+  realT dist;
+
+  qh_distplane(qh interior_point, facet, &dist);
+  if (dist > 0) {
+    for (k=qh hull_dim; k--; )
+      facet->normal[k]= -facet->normal[k];
+    facet->offset= -facet->offset;
+    return True;
+  }
+  return False;
+} /* orientoutside */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="outerinner">-</a>
+
+  qh_outerinner( facet, outerplane, innerplane  )
+    if facet and qh.maxoutdone (i.e., qh_check_maxout)
+      returns outer and inner plane for facet
+    else
+      returns maximum outer and inner plane
+    accounts for qh.JOGGLEmax
+
+  see:
+    qh_maxouter(), qh_check_bestdist(), qh_check_points()
+
+  notes:
+    outerplaner or innerplane may be NULL
+    facet is const
+    Does not error (QhullFacet)
+
+    includes qh.DISTround for actual points
+    adds another qh.DISTround if testing with floating point arithmetic
+*/
+void qh_outerinner(facetT *facet, realT *outerplane, realT *innerplane) {
+  realT dist, mindist;
+  vertexT *vertex, **vertexp;
+
+  if (outerplane) {
+    if (!qh_MAXoutside || !facet || !qh maxoutdone) {
+      *outerplane= qh_maxouter();       /* includes qh.DISTround */
+    }else { /* qh_MAXoutside ... */
+#if qh_MAXoutside
+      *outerplane= facet->maxoutside + qh DISTround;
+#endif
+
+    }
+    if (qh JOGGLEmax < REALmax/2)
+      *outerplane += qh JOGGLEmax * sqrt((realT)qh hull_dim);
+  }
+  if (innerplane) {
+    if (facet) {
+      mindist= REALmax;
+      FOREACHvertex_(facet->vertices) {
+        zinc_(Zdistio);
+        qh_distplane(vertex->point, facet, &dist);
+        minimize_(mindist, dist);
+      }
+      *innerplane= mindist - qh DISTround;
+    }else
+      *innerplane= qh min_vertex - qh DISTround;
+    if (qh JOGGLEmax < REALmax/2)
+      *innerplane -= qh JOGGLEmax * sqrt((realT)qh hull_dim);
+  }
+} /* outerinner */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="pointdist">-</a>
+
+  qh_pointdist( point1, point2, dim )
+    return distance between two points
+
+  notes:
+    returns distance squared if 'dim' is negative
+*/
+coordT qh_pointdist(pointT *point1, pointT *point2, int dim) {
+  coordT dist, diff;
+  int k;
+
+  dist= 0.0;
+  for (k= (dim > 0 ? dim : -dim); k--; ) {
+    diff= *point1++ - *point2++;
+    dist += diff * diff;
+  }
+  if (dim > 0)
+    return(sqrt(dist));
+  return dist;
+} /* pointdist */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="printmatrix">-</a>
+
+  qh_printmatrix( fp, string, rows, numrow, numcol )
+    print matrix to fp given by row vectors
+    print string as header
+
+  notes:
+    print a vector by qh_printmatrix(fp, "", &vect, 1, len)
+*/
+void qh_printmatrix(FILE *fp, const char *string, realT **rows, int numrow, int numcol) {
+  realT *rowp;
+  realT r; /*bug fix*/
+  int i,k;
+
+  qh_fprintf(fp, 9001, "%s\n", string);
+  for (i=0; i < numrow; i++) {
+    rowp= rows[i];
+    for (k=0; k < numcol; k++) {
+      r= *rowp++;
+      qh_fprintf(fp, 9002, "%6.3g ", r);
+    }
+    qh_fprintf(fp, 9003, "\n");
+  }
+} /* printmatrix */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="printpoints">-</a>
+
+  qh_printpoints( fp, string, points )
+    print pointids to fp for a set of points
+    if string, prints string and 'p' point ids
+*/
+void qh_printpoints(FILE *fp, const char *string, setT *points) {
+  pointT *point, **pointp;
+
+  if (string) {
+    qh_fprintf(fp, 9004, "%s", string);
+    FOREACHpoint_(points)
+      qh_fprintf(fp, 9005, " p%d", qh_pointid(point));
+    qh_fprintf(fp, 9006, "\n");
+  }else {
+    FOREACHpoint_(points)
+      qh_fprintf(fp, 9007, " %d", qh_pointid(point));
+    qh_fprintf(fp, 9008, "\n");
+  }
+} /* printpoints */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="projectinput">-</a>
+
+  qh_projectinput()
+    project input points using qh.lower_bound/upper_bound and qh DELAUNAY
+    if qh.lower_bound[k]=qh.upper_bound[k]= 0,
+      removes dimension k
+    if halfspace intersection
+      removes dimension k from qh.feasible_point
+    input points in qh first_point, num_points, input_dim
+
+  returns:
+    new point array in qh first_point of qh hull_dim coordinates
+    sets qh POINTSmalloc
+    if qh DELAUNAY
+      projects points to paraboloid
+      lowbound/highbound is also projected
+    if qh ATinfinity
+      adds point "at-infinity"
+    if qh POINTSmalloc
+      frees old point array
+
+  notes:
+    checks that qh.hull_dim agrees with qh.input_dim, PROJECTinput, and DELAUNAY
+
+
+  design:
+    sets project[k] to -1 (delete), 0 (keep), 1 (add for Delaunay)
+    determines newdim and newnum for qh hull_dim and qh num_points
+    projects points to newpoints
+    projects qh.lower_bound to itself
+    projects qh.upper_bound to itself
+    if qh DELAUNAY
+      if qh ATINFINITY
+        projects points to paraboloid
+        computes "infinity" point as vertex average and 10% above all points
+      else
+        uses qh_setdelaunay to project points to paraboloid
+*/
+void qh_projectinput(void) {
+  int k,i;
+  int newdim= qh input_dim, newnum= qh num_points;
+  signed char *project;
+  int size= (qh input_dim+1)*sizeof(*project);
+  pointT *newpoints, *coord, *infinity;
+  realT paraboloid, maxboloid= 0;
+
+  project= (signed char*)qh_memalloc(size);
+  memset((char*)project, 0, (size_t)size);
+  for (k=0; k < qh input_dim; k++) {   /* skip Delaunay bound */
+    if (qh lower_bound[k] == 0 && qh upper_bound[k] == 0) {
+      project[k]= -1;
+      newdim--;
+    }
+  }
+  if (qh DELAUNAY) {
+    project[k]= 1;
+    newdim++;
+    if (qh ATinfinity)
+      newnum++;
+  }
+  if (newdim != qh hull_dim) {
+    qh_fprintf(qh ferr, 6015, "qhull internal error (qh_projectinput): dimension after projection %d != hull_dim %d\n", newdim, qh hull_dim);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  if (!(newpoints=(coordT*)qh_malloc(newnum*newdim*sizeof(coordT)))){
+    qh_fprintf(qh ferr, 6016, "qhull error: insufficient memory to project %d points\n",
+           qh num_points);
+    qh_errexit(qh_ERRmem, NULL, NULL);
+  }
+  qh_projectpoints(project, qh input_dim+1, qh first_point,
+                    qh num_points, qh input_dim, newpoints, newdim);
+  trace1((qh ferr, 1003, "qh_projectinput: updating lower and upper_bound\n"));
+  qh_projectpoints(project, qh input_dim+1, qh lower_bound,
+                    1, qh input_dim+1, qh lower_bound, newdim+1);
+  qh_projectpoints(project, qh input_dim+1, qh upper_bound,
+                    1, qh input_dim+1, qh upper_bound, newdim+1);
+  if (qh HALFspace) {
+    if (!qh feasible_point) {
+      qh_fprintf(qh ferr, 6017, "qhull internal error (qh_projectinput): HALFspace defined without qh.feasible_point\n");
+      qh_errexit(qh_ERRqhull, NULL, NULL);
+    }
+    qh_projectpoints(project, qh input_dim, qh feasible_point,
+                      1, qh input_dim, qh feasible_point, newdim);
+  }
+  qh_memfree(project, (qh input_dim+1)*sizeof(*project));
+  if (qh POINTSmalloc)
+    qh_free(qh first_point);
+  qh first_point= newpoints;
+  qh POINTSmalloc= True;
+  if (qh DELAUNAY && qh ATinfinity) {
+    coord= qh first_point;
+    infinity= qh first_point + qh hull_dim * qh num_points;
+    for (k=qh hull_dim-1; k--; )
+      infinity[k]= 0.0;
+    for (i=qh num_points; i--; ) {
+      paraboloid= 0.0;
+      for (k=0; k < qh hull_dim-1; k++) {
+        paraboloid += *coord * *coord;
+        infinity[k] += *coord;
+        coord++;
+      }
+      *(coord++)= paraboloid;
+      maximize_(maxboloid, paraboloid);
+    }
+    /* coord == infinity */
+    for (k=qh hull_dim-1; k--; )
+      *(coord++) /= qh num_points;
+    *(coord++)= maxboloid * 1.1;
+    qh num_points++;
+    trace0((qh ferr, 9, "qh_projectinput: projected points to paraboloid for Delaunay\n"));
+  }else if (qh DELAUNAY)  /* !qh ATinfinity */
+    qh_setdelaunay( qh hull_dim, qh num_points, qh first_point);
+} /* projectinput */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="projectpoints">-</a>
+
+  qh_projectpoints( project, n, points, numpoints, dim, newpoints, newdim )
+    project points/numpoints/dim to newpoints/newdim
+    if project[k] == -1
+      delete dimension k
+    if project[k] == 1
+      add dimension k by duplicating previous column
+    n is size of project
+
+  notes:
+    newpoints may be points if only adding dimension at end
+
+  design:
+    check that 'project' and 'newdim' agree
+    for each dimension
+      if project == -1
+        skip dimension
+      else
+        determine start of column in newpoints
+        determine start of column in points
+          if project == +1, duplicate previous column
+        copy dimension (column) from points to newpoints
+*/
+void qh_projectpoints(signed char *project, int n, realT *points,
+        int numpoints, int dim, realT *newpoints, int newdim) {
+  int testdim= dim, oldk=0, newk=0, i,j=0,k;
+  realT *newp, *oldp;
+
+  for (k=0; k < n; k++)
+    testdim += project[k];
+  if (testdim != newdim) {
+    qh_fprintf(qh ferr, 6018, "qhull internal error (qh_projectpoints): newdim %d should be %d after projection\n",
+      newdim, testdim);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  for (j=0; j<n; j++) {
+    if (project[j] == -1)
+      oldk++;
+    else {
+      newp= newpoints+newk++;
+      if (project[j] == +1) {
+        if (oldk >= dim)
+          continue;
+        oldp= points+oldk;
+      }else
+        oldp= points+oldk++;
+      for (i=numpoints; i--; ) {
+        *newp= *oldp;
+        newp += newdim;
+        oldp += dim;
+      }
+    }
+    if (oldk >= dim)
+      break;
+  }
+  trace1((qh ferr, 1004, "qh_projectpoints: projected %d points from dim %d to dim %d\n",
+    numpoints, dim, newdim));
+} /* projectpoints */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="rotateinput">-</a>
+
+  qh_rotateinput( rows )
+    rotate input using row matrix
+    input points given by qh first_point, num_points, hull_dim
+    assumes rows[dim] is a scratch buffer
+    if qh POINTSmalloc, overwrites input points, else mallocs a new array
+
+  returns:
+    rotated input
+    sets qh POINTSmalloc
+
+  design:
+    see qh_rotatepoints
+*/
+void qh_rotateinput(realT **rows) {
+
+  if (!qh POINTSmalloc) {
+    qh first_point= qh_copypoints(qh first_point, qh num_points, qh hull_dim);
+    qh POINTSmalloc= True;
+  }
+  qh_rotatepoints(qh first_point, qh num_points, qh hull_dim, rows);
+}  /* rotateinput */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="rotatepoints">-</a>
+
+  qh_rotatepoints( points, numpoints, dim, row )
+    rotate numpoints points by a d-dim row matrix
+    assumes rows[dim] is a scratch buffer
+
+  returns:
+    rotated points in place
+
+  design:
+    for each point
+      for each coordinate
+        use row[dim] to compute partial inner product
+      for each coordinate
+        rotate by partial inner product
+*/
+void qh_rotatepoints(realT *points, int numpoints, int dim, realT **row) {
+  realT *point, *rowi, *coord= NULL, sum, *newval;
+  int i,j,k;
+
+  if (qh IStracing >= 1)
+    qh_printmatrix(qh ferr, "qh_rotatepoints: rotate points by", row, dim, dim);
+  for (point= points, j= numpoints; j--; point += dim) {
+    newval= row[dim];
+    for (i=0; i < dim; i++) {
+      rowi= row[i];
+      coord= point;
+      for (sum= 0.0, k= dim; k--; )
+        sum += *rowi++ * *coord++;
+      *(newval++)= sum;
+    }
+    for (k=dim; k--; )
+      *(--coord)= *(--newval);
+  }
+} /* rotatepoints */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="scaleinput">-</a>
+
+  qh_scaleinput()
+    scale input points using qh low_bound/high_bound
+    input points given by qh first_point, num_points, hull_dim
+    if qh POINTSmalloc, overwrites input points, else mallocs a new array
+
+  returns:
+    scales coordinates of points to low_bound[k], high_bound[k]
+    sets qh POINTSmalloc
+
+  design:
+    see qh_scalepoints
+*/
+void qh_scaleinput(void) {
+
+  if (!qh POINTSmalloc) {
+    qh first_point= qh_copypoints(qh first_point, qh num_points, qh hull_dim);
+    qh POINTSmalloc= True;
+  }
+  qh_scalepoints(qh first_point, qh num_points, qh hull_dim,
+       qh lower_bound, qh upper_bound);
+}  /* scaleinput */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="scalelast">-</a>
+
+  qh_scalelast( points, numpoints, dim, low, high, newhigh )
+    scale last coordinate to [0,m] for Delaunay triangulations
+    input points given by points, numpoints, dim
+
+  returns:
+    changes scale of last coordinate from [low, high] to [0, newhigh]
+    overwrites last coordinate of each point
+    saves low/high/newhigh in qh.last_low, etc. for qh_setdelaunay()
+
+  notes:
+    when called by qh_setdelaunay, low/high may not match actual data
+
+  design:
+    compute scale and shift factors
+    apply to last coordinate of each point
+*/
+void qh_scalelast(coordT *points, int numpoints, int dim, coordT low,
+                   coordT high, coordT newhigh) {
+  realT scale, shift;
+  coordT *coord;
+  int i;
+  boolT nearzero= False;
+
+  trace4((qh ferr, 4013, "qh_scalelast: scale last coordinate from [%2.2g, %2.2g] to [0,%2.2g]\n",
+    low, high, newhigh));
+  qh last_low= low;
+  qh last_high= high;
+  qh last_newhigh= newhigh;
+  scale= qh_divzero(newhigh, high - low,
+                  qh MINdenom_1, &nearzero);
+  if (nearzero) {
+    if (qh DELAUNAY)
+      qh_fprintf(qh ferr, 6019, "qhull input error: can not scale last coordinate.  Input is cocircular\n   or cospherical.   Use option 'Qz' to add a point at infinity.\n");
+    else
+      qh_fprintf(qh ferr, 6020, "qhull input error: can not scale last coordinate.  New bounds [0, %2.2g] are too wide for\nexisting bounds [%2.2g, %2.2g] (width %2.2g)\n",
+                newhigh, low, high, high-low);
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  shift= - low * newhigh / (high-low);
+  coord= points + dim - 1;
+  for (i=numpoints; i--; coord += dim)
+    *coord= *coord * scale + shift;
+} /* scalelast */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="scalepoints">-</a>
+
+  qh_scalepoints( points, numpoints, dim, newlows, newhighs )
+    scale points to new lowbound and highbound
+    retains old bound when newlow= -REALmax or newhigh= +REALmax
+
+  returns:
+    scaled points
+    overwrites old points
+
+  design:
+    for each coordinate
+      compute current low and high bound
+      compute scale and shift factors
+      scale all points
+      enforce new low and high bound for all points
+*/
+void qh_scalepoints(pointT *points, int numpoints, int dim,
+        realT *newlows, realT *newhighs) {
+  int i,k;
+  realT shift, scale, *coord, low, high, newlow, newhigh, mincoord, maxcoord;
+  boolT nearzero= False;
+
+  for (k=0; k < dim; k++) {
+    newhigh= newhighs[k];
+    newlow= newlows[k];
+    if (newhigh > REALmax/2 && newlow < -REALmax/2)
+      continue;
+    low= REALmax;
+    high= -REALmax;
+    for (i=numpoints, coord=points+k; i--; coord += dim) {
+      minimize_(low, *coord);
+      maximize_(high, *coord);
+    }
+    if (newhigh > REALmax/2)
+      newhigh= high;
+    if (newlow < -REALmax/2)
+      newlow= low;
+    if (qh DELAUNAY && k == dim-1 && newhigh < newlow) {
+      qh_fprintf(qh ferr, 6021, "qhull input error: 'Qb%d' or 'QB%d' inverts paraboloid since high bound %.2g < low bound %.2g\n",
+               k, k, newhigh, newlow);
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+    scale= qh_divzero(newhigh - newlow, high - low,
+                  qh MINdenom_1, &nearzero);
+    if (nearzero) {
+      qh_fprintf(qh ferr, 6022, "qhull input error: %d'th dimension's new bounds [%2.2g, %2.2g] too wide for\nexisting bounds [%2.2g, %2.2g]\n",
+              k, newlow, newhigh, low, high);
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+    shift= (newlow * high - low * newhigh)/(high-low);
+    coord= points+k;
+    for (i=numpoints; i--; coord += dim)
+      *coord= *coord * scale + shift;
+    coord= points+k;
+    if (newlow < newhigh) {
+      mincoord= newlow;
+      maxcoord= newhigh;
+    }else {
+      mincoord= newhigh;
+      maxcoord= newlow;
+    }
+    for (i=numpoints; i--; coord += dim) {
+      minimize_(*coord, maxcoord);  /* because of roundoff error */
+      maximize_(*coord, mincoord);
+    }
+    trace0((qh ferr, 10, "qh_scalepoints: scaled %d'th coordinate [%2.2g, %2.2g] to [%.2g, %.2g] for %d points by %2.2g and shifted %2.2g\n",
+      k, low, high, newlow, newhigh, numpoints, scale, shift));
+  }
+} /* scalepoints */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="setdelaunay">-</a>
+
+  qh_setdelaunay( dim, count, points )
+    project count points to dim-d paraboloid for Delaunay triangulation
+
+    dim is one more than the dimension of the input set
+    assumes dim is at least 3 (i.e., at least a 2-d Delaunay triangulation)
+
+    points is a dim*count realT array.  The first dim-1 coordinates
+    are the coordinates of the first input point.  array[dim] is
+    the first coordinate of the second input point.  array[2*dim] is
+    the first coordinate of the third input point.
+
+    if qh.last_low defined (i.e., 'Qbb' called qh_scalelast)
+      calls qh_scalelast to scale the last coordinate the same as the other points
+
+  returns:
+    for each point
+      sets point[dim-1] to sum of squares of coordinates
+    scale points to 'Qbb' if needed
+
+  notes:
+    to project one point, use
+      qh_setdelaunay(qh hull_dim, 1, point)
+
+    Do not use options 'Qbk', 'QBk', or 'QbB' since they scale
+    the coordinates after the original projection.
+
+*/
+void qh_setdelaunay(int dim, int count, pointT *points) {
+  int i, k;
+  coordT *coordp, coord;
+  realT paraboloid;
+
+  trace0((qh ferr, 11, "qh_setdelaunay: project %d points to paraboloid for Delaunay triangulation\n", count));
+  coordp= points;
+  for (i=0; i < count; i++) {
+    coord= *coordp++;
+    paraboloid= coord*coord;
+    for (k=dim-2; k--; ) {
+      coord= *coordp++;
+      paraboloid += coord*coord;
+    }
+    *coordp++ = paraboloid;
+  }
+  if (qh last_low < REALmax/2)
+    qh_scalelast(points, count, dim, qh last_low, qh last_high, qh last_newhigh);
+} /* setdelaunay */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="sethalfspace">-</a>
+
+  qh_sethalfspace( dim, coords, nextp, normal, offset, feasible )
+    set point to dual of halfspace relative to feasible point
+    halfspace is normal coefficients and offset.
+
+  returns:
+    false if feasible point is outside of hull (error message already reported)
+    overwrites coordinates for point at dim coords
+    nextp= next point (coords)
+
+  design:
+    compute distance from feasible point to halfspace
+    divide each normal coefficient by -dist
+*/
+boolT qh_sethalfspace(int dim, coordT *coords, coordT **nextp,
+         coordT *normal, coordT *offset, coordT *feasible) {
+  coordT *normp= normal, *feasiblep= feasible, *coordp= coords;
+  realT dist;
+  realT r; /*bug fix*/
+  int k;
+  boolT zerodiv;
+
+  dist= *offset;
+  for (k=dim; k--; )
+    dist += *(normp++) * *(feasiblep++);
+  if (dist > 0)
+    goto LABELerroroutside;
+  normp= normal;
+  if (dist < -qh MINdenom) {
+    for (k=dim; k--; )
+      *(coordp++)= *(normp++) / -dist;
+  }else {
+    for (k=dim; k--; ) {
+      *(coordp++)= qh_divzero(*(normp++), -dist, qh MINdenom_1, &zerodiv);
+      if (zerodiv)
+        goto LABELerroroutside;
+    }
+  }
+  *nextp= coordp;
+  if (qh IStracing >= 4) {
+    qh_fprintf(qh ferr, 8021, "qh_sethalfspace: halfspace at offset %6.2g to point: ", *offset);
+    for (k=dim, coordp=coords; k--; ) {
+      r= *coordp++;
+      qh_fprintf(qh ferr, 8022, " %6.2g", r);
+    }
+    qh_fprintf(qh ferr, 8023, "\n");
+  }
+  return True;
+LABELerroroutside:
+  feasiblep= feasible;
+  normp= normal;
+  qh_fprintf(qh ferr, 6023, "qhull input error: feasible point is not clearly inside halfspace\nfeasible point: ");
+  for (k=dim; k--; )
+    qh_fprintf(qh ferr, 8024, qh_REAL_1, r=*(feasiblep++));
+  qh_fprintf(qh ferr, 8025, "\n     halfspace: ");
+  for (k=dim; k--; )
+    qh_fprintf(qh ferr, 8026, qh_REAL_1, r=*(normp++));
+  qh_fprintf(qh ferr, 8027, "\n     at offset: ");
+  qh_fprintf(qh ferr, 8028, qh_REAL_1, *offset);
+  qh_fprintf(qh ferr, 8029, " and distance: ");
+  qh_fprintf(qh ferr, 8030, qh_REAL_1, dist);
+  qh_fprintf(qh ferr, 8031, "\n");
+  return False;
+} /* sethalfspace */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="sethalfspace_all">-</a>
+
+  qh_sethalfspace_all( dim, count, halfspaces, feasible )
+    generate dual for halfspace intersection with feasible point
+    array of count halfspaces
+      each halfspace is normal coefficients followed by offset
+      the origin is inside the halfspace if the offset is negative
+
+  returns:
+    malloc'd array of count X dim-1 points
+
+  notes:
+    call before qh_init_B or qh_initqhull_globals
+    unused/untested code: please email bradb at shore.net if this works ok for you
+    If using option 'Fp', also set qh feasible_point. It is a malloc'd array
+      that is freed by qh_freebuffers.
+
+  design:
+    see qh_sethalfspace
+*/
+coordT *qh_sethalfspace_all(int dim, int count, coordT *halfspaces, pointT *feasible) {
+  int i, newdim;
+  pointT *newpoints;
+  coordT *coordp, *normalp, *offsetp;
+
+  trace0((qh ferr, 12, "qh_sethalfspace_all: compute dual for halfspace intersection\n"));
+  newdim= dim - 1;
+  if (!(newpoints=(coordT*)qh_malloc(count*newdim*sizeof(coordT)))){
+    qh_fprintf(qh ferr, 6024, "qhull error: insufficient memory to compute dual of %d halfspaces\n",
+          count);
+    qh_errexit(qh_ERRmem, NULL, NULL);
+  }
+  coordp= newpoints;
+  normalp= halfspaces;
+  for (i=0; i < count; i++) {
+    offsetp= normalp + newdim;
+    if (!qh_sethalfspace(newdim, coordp, &coordp, normalp, offsetp, feasible)) {
+      qh_fprintf(qh ferr, 8032, "The halfspace was at index %d\n", i);
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+    normalp= offsetp + 1;
+  }
+  return newpoints;
+} /* sethalfspace_all */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="sharpnewfacets">-</a>
+
+  qh_sharpnewfacets()
+
+  returns:
+    true if could be an acute angle (facets in different quadrants)
+
+  notes:
+    for qh_findbest
+
+  design:
+    for all facets on qh.newfacet_list
+      if two facets are in different quadrants
+        set issharp
+*/
+boolT qh_sharpnewfacets() {
+  facetT *facet;
+  boolT issharp = False;
+  int *quadrant, k;
+
+  quadrant= (int*)qh_memalloc(qh hull_dim * sizeof(int));
+  FORALLfacet_(qh newfacet_list) {
+    if (facet == qh newfacet_list) {
+      for (k=qh hull_dim; k--; )
+        quadrant[ k]= (facet->normal[ k] > 0);
+    }else {
+      for (k=qh hull_dim; k--; ) {
+        if (quadrant[ k] != (facet->normal[ k] > 0)) {
+          issharp= True;
+          break;
+        }
+      }
+    }
+    if (issharp)
+      break;
+  }
+  qh_memfree( quadrant, qh hull_dim * sizeof(int));
+  trace3((qh ferr, 3001, "qh_sharpnewfacets: %d\n", issharp));
+  return issharp;
+} /* sharpnewfacets */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="voronoi_center">-</a>
+
+  qh_voronoi_center( dim, points )
+    return Voronoi center for a set of points
+    dim is the original dimension of the points
+    gh.gm_matrix/qh.gm_row are scratch buffers
+
+  returns:
+    center as a temporary point
+    if non-simplicial,
+      returns center for max simplex of points
+
+  notes:
+    from Bowyer & Woodwark, A Programmer's Geometry, 1983, p. 65
+
+  design:
+    if non-simplicial
+      determine max simplex for points
+    translate point0 of simplex to origin
+    compute sum of squares of diagonal
+    compute determinate
+    compute Voronoi center (see Bowyer & Woodwark)
+*/
+pointT *qh_voronoi_center(int dim, setT *points) {
+  pointT *point, **pointp, *point0;
+  pointT *center= (pointT*)qh_memalloc(qh center_size);
+  setT *simplex;
+  int i, j, k, size= qh_setsize(points);
+  coordT *gmcoord;
+  realT *diffp, sum2, *sum2row, *sum2p, det, factor;
+  boolT nearzero, infinite;
+
+  if (size == dim+1)
+    simplex= points;
+  else if (size < dim+1) {
+    qh_fprintf(qh ferr, 6025, "qhull internal error (qh_voronoi_center):\n  need at least %d points to construct a Voronoi center\n",
+             dim+1);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+    simplex= points;  /* never executed -- avoids warning */
+  }else {
+    simplex= qh_settemp(dim+1);
+    qh_maxsimplex(dim, points, NULL, 0, &simplex);
+  }
+  point0= SETfirstt_(simplex, pointT);
+  gmcoord= qh gm_matrix;
+  for (k=0; k < dim; k++) {
+    qh gm_row[k]= gmcoord;
+    FOREACHpoint_(simplex) {
+      if (point != point0)
+        *(gmcoord++)= point[k] - point0[k];
+    }
+  }
+  sum2row= gmcoord;
+  for (i=0; i < dim; i++) {
+    sum2= 0.0;
+    for (k=0; k < dim; k++) {
+      diffp= qh gm_row[k] + i;
+      sum2 += *diffp * *diffp;
+    }
+    *(gmcoord++)= sum2;
+  }
+  det= qh_determinant(qh gm_row, dim, &nearzero);
+  factor= qh_divzero(0.5, det, qh MINdenom, &infinite);
+  if (infinite) {
+    for (k=dim; k--; )
+      center[k]= qh_INFINITE;
+    if (qh IStracing)
+      qh_printpoints(qh ferr, "qh_voronoi_center: at infinity for ", simplex);
+  }else {
+    for (i=0; i < dim; i++) {
+      gmcoord= qh gm_matrix;
+      sum2p= sum2row;
+      for (k=0; k < dim; k++) {
+        qh gm_row[k]= gmcoord;
+        if (k == i) {
+          for (j=dim; j--; )
+            *(gmcoord++)= *sum2p++;
+        }else {
+          FOREACHpoint_(simplex) {
+            if (point != point0)
+              *(gmcoord++)= point[k] - point0[k];
+          }
+        }
+      }
+      center[i]= qh_determinant(qh gm_row, dim, &nearzero)*factor + point0[i];
+    }
+#ifndef qh_NOtrace
+    if (qh IStracing >= 3) {
+      qh_fprintf(qh ferr, 8033, "qh_voronoi_center: det %2.2g factor %2.2g ", det, factor);
+      qh_printmatrix(qh ferr, "center:", &center, 1, dim);
+      if (qh IStracing >= 5) {
+        qh_printpoints(qh ferr, "points", simplex);
+        FOREACHpoint_(simplex)
+          qh_fprintf(qh ferr, 8034, "p%d dist %.2g, ", qh_pointid(point),
+                   qh_pointdist(point, center, dim));
+        qh_fprintf(qh ferr, 8035, "\n");
+      }
+    }
+#endif
+  }
+  if (simplex != points)
+    qh_settempfree(&simplex);
+  return center;
+} /* voronoi_center */
+
diff --git a/alg/libqhull/global.c b/alg/libqhull/global.c
new file mode 100644
index 0000000..5ef7e02
--- /dev/null
+++ b/alg/libqhull/global.c
@@ -0,0 +1,2126 @@
+
+/*<html><pre>  -<a                             href="qh-globa.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   global.c
+   initializes all the globals of the qhull application
+
+   see README
+
+   see libqhull.h for qh.globals and function prototypes
+
+   see qhull_a.h for internal functions
+
+   Copyright (c) 1993-2012 The Geometry Center.
+   $Id: //main/2011/qhull/src/libqhull/global.c#15 $$Change: 1490 $
+   $DateTime: 2012/02/19 20:27:01 $$Author: bbarber $
+ */
+
+#include "qhull_a.h"
+
+/*========= qh definition -- globals defined in libqhull.h =======================*/
+
+int qhull_inuse= 0; /* not used */
+
+#if qh_QHpointer
+qhT *qh_qh= NULL;       /* pointer to all global variables */
+#else
+qhT qh_qh;              /* all global variables.
+                           Add "= {0}" if this causes a compiler error.
+                           Also qh_qhstat in stat.c and qhmem in mem.c.  */
+#endif
+
+/*-<a                             href  ="qh-globa.htm#TOC"
+  >--------------------------------</a><a name="qh_version">-</a>
+
+  qh_version
+    version string by year and date
+
+    the revision increases on code changes only
+
+  notes:
+    change date:    Changes.txt, Announce.txt, index.htm, README.txt,
+                    qhull-news.html, Eudora signatures, CMakeLists.txt
+    change version: README.txt, qh-get.htm, File_id.diz, Makefile.txt
+    change year:    Copying.txt
+    check download size
+    recompile user_eg.c, rbox.c, libqhull.c, qconvex.c, qdelaun.c qvoronoi.c, qhalf.c, testqset.c
+*/
+
+const char *qh_version = "2012.1 2012/02/18";
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="appendprint">-</a>
+
+  qh_appendprint( printFormat )
+    append printFormat to qh.PRINTout unless already defined
+*/
+void qh_appendprint(qh_PRINT format) {
+  int i;
+
+  for (i=0; i < qh_PRINTEND; i++) {
+    if (qh PRINTout[i] == format && format != qh_PRINTqhull)
+      break;
+    if (!qh PRINTout[i]) {
+      qh PRINTout[i]= format;
+      break;
+    }
+  }
+} /* appendprint */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="checkflags">-</a>
+
+  qh_checkflags( commandStr, hiddenFlags )
+    errors if commandStr contains hiddenFlags
+    hiddenFlags starts and ends with a space and is space deliminated (checked)
+
+  notes:
+    ignores first word (e.g., "qconvex i")
+    use qh_strtol/strtod since strtol/strtod may or may not skip trailing spaces
+
+  see:
+    qh_initflags() initializes Qhull according to commandStr
+*/
+void qh_checkflags(char *command, char *hiddenflags) {
+  char *s= command, *t, *chkerr; /* qh_skipfilename is non-const */
+  char key, opt, prevopt;
+  char chkkey[]= "   ";
+  char chkopt[]=  "    ";
+  char chkopt2[]= "     ";
+  boolT waserr= False;
+
+  if (*hiddenflags != ' ' || hiddenflags[strlen(hiddenflags)-1] != ' ') {
+    qh_fprintf(qh ferr, 6026, "qhull error (qh_checkflags): hiddenflags must start and end with a space: \"%s\"", hiddenflags);
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  if (strpbrk(hiddenflags, ",\n\r\t")) {
+    qh_fprintf(qh ferr, 6027, "qhull error (qh_checkflags): hiddenflags contains commas, newlines, or tabs: \"%s\"", hiddenflags);
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  while (*s && !isspace(*s))  /* skip program name */
+    s++;
+  while (*s) {
+    while (*s && isspace(*s))
+      s++;
+    if (*s == '-')
+      s++;
+    if (!*s)
+      break;
+    key = *s++;
+    chkerr = NULL;
+    if (key == 'T' && (*s == 'I' || *s == 'O')) {  /* TI or TO 'file name' */
+      s= qh_skipfilename(++s);
+      continue;
+    }
+    chkkey[1]= key;
+    if (strstr(hiddenflags, chkkey)) {
+      chkerr= chkkey;
+    }else if (isupper(key)) {
+      opt= ' ';
+      prevopt= ' ';
+      chkopt[1]= key;
+      chkopt2[1]= key;
+      while (!chkerr && *s && !isspace(*s)) {
+        opt= *s++;
+        if (isalpha(opt)) {
+          chkopt[2]= opt;
+          if (strstr(hiddenflags, chkopt))
+            chkerr= chkopt;
+          if (prevopt != ' ') {
+            chkopt2[2]= prevopt;
+            chkopt2[3]= opt;
+            if (strstr(hiddenflags, chkopt2))
+              chkerr= chkopt2;
+          }
+        }else if (key == 'Q' && isdigit(opt) && prevopt != 'b'
+              && (prevopt == ' ' || islower(prevopt))) {
+            chkopt[2]= opt;
+            if (strstr(hiddenflags, chkopt))
+              chkerr= chkopt;
+        }else {
+          qh_strtod(s-1, &t);
+          if (s < t)
+            s= t;
+        }
+        prevopt= opt;
+      }
+    }
+    if (chkerr) {
+      *chkerr= '\'';
+      chkerr[strlen(chkerr)-1]=  '\'';
+      qh_fprintf(qh ferr, 6029, "qhull error: option %s is not used with this program.\n             It may be used with qhull.\n", chkerr);
+      waserr= True;
+    }
+  }
+  if (waserr)
+    qh_errexit(qh_ERRinput, NULL, NULL);
+} /* checkflags */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="qh_clear_outputflags">-</a>
+
+  qh_clear_outputflags()
+    Clear output flags for QhullPoints
+*/
+void qh_clear_outputflags(void) {
+  int i,k;
+
+  qh ANNOTATEoutput= False;
+  qh DOintersections= False;
+  qh DROPdim= -1;
+  qh FORCEoutput= False;
+  qh GETarea= False;
+  qh GOODpoint= 0;
+  qh GOODpointp= NULL;
+  qh GOODthreshold= False;
+  qh GOODvertex= 0;
+  qh GOODvertexp= NULL;
+  qh IStracing= 0;
+  qh KEEParea= False;
+  qh KEEPmerge= False;
+  qh KEEPminArea= REALmax;
+  qh PRINTcentrums= False;
+  qh PRINTcoplanar= False;
+  qh PRINTdots= False;
+  qh PRINTgood= False;
+  qh PRINTinner= False;
+  qh PRINTneighbors= False;
+  qh PRINTnoplanes= False;
+  qh PRINToptions1st= False;
+  qh PRINTouter= False;
+  qh PRINTprecision= True;
+  qh PRINTridges= False;
+  qh PRINTspheres= False;
+  qh PRINTstatistics= False;
+  qh PRINTsummary= False;
+  qh PRINTtransparent= False;
+  qh SPLITthresholds= False;
+  qh TRACElevel= 0;
+  qh TRInormals= False;
+  qh USEstdout= False;
+  qh VERIFYoutput= False;
+  for (k=qh input_dim+1; k--; ) {  /* duplicated in qh_initqhull_buffers and qh_clear_outputflags */
+    qh lower_threshold[k]= -REALmax;
+    qh upper_threshold[k]= REALmax;
+    qh lower_bound[k]= -REALmax;
+    qh upper_bound[k]= REALmax;
+  }
+
+  for (i=0; i < qh_PRINTEND; i++) {
+    qh PRINTout[i]= qh_PRINTnone;
+  }
+
+  if (!qh qhull_commandsiz2)
+      qh qhull_commandsiz2= (int)strlen(qh qhull_command); /* WARN64 */
+  else {
+      qh qhull_command[qh qhull_commandsiz2]= '\0';
+  }
+  if (!qh qhull_optionsiz2)
+    qh qhull_optionsiz2= (int)strlen(qh qhull_options);  /* WARN64 */
+  else {
+    qh qhull_options[qh qhull_optionsiz2]= '\0';
+    qh qhull_optionlen= qh_OPTIONline;  /* start a new line */
+  }
+} /* clear_outputflags */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="clock">-</a>
+
+  qh_clock()
+    return user CPU time in 100ths (qh_SECtick)
+    only defined for qh_CLOCKtype == 2
+
+  notes:
+    use first value to determine time 0
+    from Stevens '92 8.15
+*/
+unsigned long qh_clock(void) {
+
+#if (qh_CLOCKtype == 2)
+  struct tms time;
+  static long clktck;  /* initialized first call */
+  double ratio, cpu;
+  unsigned long ticks;
+
+  if (!clktck) {
+    if ((clktck= sysconf(_SC_CLK_TCK)) < 0) {
+      qh_fprintf(qh ferr, 6030, "qhull internal error (qh_clock): sysconf() failed.  Use qh_CLOCKtype 1 in user.h\n");
+      qh_errexit(qh_ERRqhull, NULL, NULL);
+    }
+  }
+  if (times(&time) == -1) {
+    qh_fprintf(qh ferr, 6031, "qhull internal error (qh_clock): times() failed.  Use qh_CLOCKtype 1 in user.h\n");
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  ratio= qh_SECticks / (double)clktck;
+  ticks= time.tms_utime * ratio;
+  return ticks;
+#else
+  qh_fprintf(qh ferr, 6032, "qhull internal error (qh_clock): use qh_CLOCKtype 2 in user.h\n");
+  qh_errexit(qh_ERRqhull, NULL, NULL); /* never returns */
+  return 0;
+#endif
+} /* clock */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="freebuffers">-</a>
+
+  qh_freebuffers()
+    free up global memory buffers
+
+  notes:
+    must match qh_initbuffers()
+*/
+void qh_freebuffers(void) {
+
+  trace5((qh ferr, 5001, "qh_freebuffers: freeing up global memory buffers\n"));
+  /* allocated by qh_initqhull_buffers */
+  qh_memfree(qh NEARzero, qh hull_dim * sizeof(realT));
+  qh_memfree(qh lower_threshold, (qh input_dim+1) * sizeof(realT));
+  qh_memfree(qh upper_threshold, (qh input_dim+1) * sizeof(realT));
+  qh_memfree(qh lower_bound, (qh input_dim+1) * sizeof(realT));
+  qh_memfree(qh upper_bound, (qh input_dim+1) * sizeof(realT));
+  qh_memfree(qh gm_matrix, (qh hull_dim+1) * qh hull_dim * sizeof(coordT));
+  qh_memfree(qh gm_row, (qh hull_dim+1) * sizeof(coordT *));
+  qh NEARzero= qh lower_threshold= qh upper_threshold= NULL;
+  qh lower_bound= qh upper_bound= NULL;
+  qh gm_matrix= NULL;
+  qh gm_row= NULL;
+  qh_setfree(&qh other_points);
+  qh_setfree(&qh del_vertices);
+  qh_setfree(&qh coplanarfacetset);
+  if (qh line)                /* allocated by qh_readinput, freed if no error */
+    qh_free(qh line);
+  if (qh half_space)
+    qh_free(qh half_space);
+  if (qh temp_malloc)
+    qh_free(qh temp_malloc);
+  if (qh feasible_point)      /* allocated by qh_readfeasible */
+    qh_free(qh feasible_point);
+  if (qh feasible_string)     /* allocated by qh_initflags */
+    qh_free(qh feasible_string);
+  qh line= qh feasible_string= NULL;
+  qh half_space= qh feasible_point= qh temp_malloc= NULL;
+  /* usually allocated by qh_readinput */
+  if (qh first_point && qh POINTSmalloc) {
+    qh_free(qh first_point);
+    qh first_point= NULL;
+  }
+  if (qh input_points && qh input_malloc) { /* set by qh_joggleinput */
+    qh_free(qh input_points);
+    qh input_points= NULL;
+  }
+  trace5((qh ferr, 5002, "qh_freebuffers: finished\n"));
+} /* freebuffers */
+
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="freebuild">-</a>
+
+  qh_freebuild( allmem )
+    free global memory used by qh_initbuild and qh_buildhull
+    if !allmem,
+      does not free short memory (e.g., facetT, freed by qh_memfreeshort)
+
+  design:
+    free centrums
+    free each vertex
+    mark unattached ridges
+    for each facet
+      free ridges
+      free outside set, coplanar set, neighbor set, ridge set, vertex set
+      free facet
+    free hash table
+    free interior point
+    free merge set
+    free temporary sets
+*/
+void qh_freebuild(boolT allmem) {
+  facetT *facet;
+  vertexT *vertex;
+  ridgeT *ridge, **ridgep;
+  mergeT *merge, **mergep;
+
+  trace1((qh ferr, 1005, "qh_freebuild: free memory from qh_inithull and qh_buildhull\n"));
+  if (qh del_vertices)
+    qh_settruncate(qh del_vertices, 0);
+  if (allmem) {
+    while ((vertex= qh vertex_list)) {
+      if (vertex->next)
+        qh_delvertex(vertex);
+      else {
+        qh_memfree(vertex, (int)sizeof(vertexT));
+        qh newvertex_list= qh vertex_list= NULL;
+      }
+    }
+  }else if (qh VERTEXneighbors) {
+    FORALLvertices
+      qh_setfreelong(&(vertex->neighbors));
+  }
+  qh VERTEXneighbors= False;
+  qh GOODclosest= NULL;
+  if (allmem) {
+    FORALLfacets {
+      FOREACHridge_(facet->ridges)
+        ridge->seen= False;
+    }
+    FORALLfacets {
+      if (facet->visible) {
+        FOREACHridge_(facet->ridges) {
+          if (!otherfacet_(ridge, facet)->visible)
+            ridge->seen= True;  /* an unattached ridge */
+        }
+      }
+    }
+    while ((facet= qh facet_list)) {
+      FOREACHridge_(facet->ridges) {
+        if (ridge->seen) {
+          qh_setfree(&(ridge->vertices));
+          qh_memfree(ridge, (int)sizeof(ridgeT));
+        }else
+          ridge->seen= True;
+      }
+      qh_setfree(&(facet->outsideset));
+      qh_setfree(&(facet->coplanarset));
+      qh_setfree(&(facet->neighbors));
+      qh_setfree(&(facet->ridges));
+      qh_setfree(&(facet->vertices));
+      if (facet->next)
+        qh_delfacet(facet);
+      else {
+        qh_memfree(facet, (int)sizeof(facetT));
+        qh visible_list= qh newfacet_list= qh facet_list= NULL;
+      }
+    }
+  }else {
+    FORALLfacets {
+      qh_setfreelong(&(facet->outsideset));
+      qh_setfreelong(&(facet->coplanarset));
+      if (!facet->simplicial) {
+        qh_setfreelong(&(facet->neighbors));
+        qh_setfreelong(&(facet->ridges));
+        qh_setfreelong(&(facet->vertices));
+      }
+    }
+  }
+  qh_setfree(&(qh hash_table));
+  qh_memfree(qh interior_point, qh normal_size);
+  qh interior_point= NULL;
+  FOREACHmerge_(qh facet_mergeset)  /* usually empty */
+    qh_memfree(merge, (int)sizeof(mergeT));
+  qh facet_mergeset= NULL;  /* temp set */
+  qh degen_mergeset= NULL;  /* temp set */
+  qh_settempfree_all();
+} /* freebuild */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="freeqhull">-</a>
+
+  qh_freeqhull( allmem )
+    see qh_freeqhull2
+    if qh_QHpointer, frees qh_qh
+*/
+void qh_freeqhull(boolT allmem) {
+    qh_freeqhull2(allmem);
+#if qh_QHpointer
+    qh_free(qh_qh);
+    qh_qh= NULL;
+#endif
+}
+
+/*-<a                             href="qh-globa.htm#TOC"
+>-------------------------------</a><a name="freeqhull2">-</a>
+
+qh_freeqhull2( allmem )
+  free global memory
+  if !allmem,
+    does not free short memory (freed by qh_memfreeshort)
+
+notes:
+  sets qh.NOerrexit in case caller forgets to
+
+see:
+  see qh_initqhull_start2()
+
+design:
+  free global and temporary memory from qh_initbuild and qh_buildhull
+  free buffers
+  free statistics
+*/
+void qh_freeqhull2(boolT allmem) {
+
+  trace1((qh ferr, 1006, "qh_freeqhull2: free global memory\n"));
+  qh NOerrexit= True;  /* no more setjmp since called at exit and ~QhullQh */
+  qh_freebuild(allmem);
+  qh_freebuffers();
+  qh_freestatistics();
+#if qh_QHpointer
+  memset((char *)qh_qh, 0, sizeof(qhT));
+  /* qh_qh freed by caller, qh_freeqhull() */
+#else
+  memset((char *)&qh_qh, 0, sizeof(qhT));
+#endif
+  qh NOerrexit= True;
+} /* freeqhull2 */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="init_A">-</a>
+
+  qh_init_A( infile, outfile, errfile, argc, argv )
+    initialize memory and stdio files
+    convert input options to option string (qh.qhull_command)
+
+  notes:
+    infile may be NULL if qh_readpoints() is not called
+
+    errfile should always be defined.  It is used for reporting
+    errors.  outfile is used for output and format options.
+
+    argc/argv may be 0/NULL
+
+    called before error handling initialized
+    qh_errexit() may not be used
+*/
+void qh_init_A(FILE *infile, FILE *outfile, FILE *errfile, int argc, char *argv[]) {
+  qh_meminit(errfile);
+  qh_initqhull_start(infile, outfile, errfile);
+  qh_init_qhull_command(argc, argv);
+} /* init_A */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="init_B">-</a>
+
+  qh_init_B( points, numpoints, dim, ismalloc )
+    initialize globals for points array
+
+    points has numpoints dim-dimensional points
+      points[0] is the first coordinate of the first point
+      points[1] is the second coordinate of the first point
+      points[dim] is the first coordinate of the second point
+
+    ismalloc=True
+      Qhull will call qh_free(points) on exit or input transformation
+    ismalloc=False
+      Qhull will allocate a new point array if needed for input transformation
+
+    qh.qhull_command
+      is the option string.
+      It is defined by qh_init_B(), qh_qhull_command(), or qh_initflags
+
+  returns:
+    if qh.PROJECTinput or (qh.DELAUNAY and qh.PROJECTdelaunay)
+      projects the input to a new point array
+
+        if qh.DELAUNAY,
+          qh.hull_dim is increased by one
+        if qh.ATinfinity,
+          qh_projectinput adds point-at-infinity for Delaunay tri.
+
+    if qh.SCALEinput
+      changes the upper and lower bounds of the input, see qh_scaleinput()
+
+    if qh.ROTATEinput
+      rotates the input by a random rotation, see qh_rotateinput()
+      if qh.DELAUNAY
+        rotates about the last coordinate
+
+  notes:
+    called after points are defined
+    qh_errexit() may be used
+*/
+void qh_init_B(coordT *points, int numpoints, int dim, boolT ismalloc) {
+  qh_initqhull_globals(points, numpoints, dim, ismalloc);
+  if (qhmem.LASTsize == 0)
+    qh_initqhull_mem();
+  /* mem.c and qset.c are initialized */
+  qh_initqhull_buffers();
+  qh_initthresholds(qh qhull_command);
+  if (qh PROJECTinput || (qh DELAUNAY && qh PROJECTdelaunay))
+    qh_projectinput();
+  if (qh SCALEinput)
+    qh_scaleinput();
+  if (qh ROTATErandom >= 0) {
+    qh_randommatrix(qh gm_matrix, qh hull_dim, qh gm_row);
+    if (qh DELAUNAY) {
+      int k, lastk= qh hull_dim-1;
+      for (k=0; k < lastk; k++) {
+        qh gm_row[k][lastk]= 0.0;
+        qh gm_row[lastk][k]= 0.0;
+      }
+      qh gm_row[lastk][lastk]= 1.0;
+    }
+    qh_gram_schmidt(qh hull_dim, qh gm_row);
+    qh_rotateinput(qh gm_row);
+  }
+} /* init_B */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="init_qhull_command">-</a>
+
+  qh_init_qhull_command( argc, argv )
+    build qh.qhull_command from argc/argv
+
+  returns:
+    a space-delimited string of options (just as typed)
+
+  notes:
+    makes option string easy to input and output
+
+    argc/argv may be 0/NULL
+*/
+void qh_init_qhull_command(int argc, char *argv[]) {
+
+  if (!qh_argv_to_command(argc, argv, qh qhull_command, (int)sizeof(qh qhull_command))){
+    /* Assumes qh.ferr is defined. */
+    qh_fprintf(qh ferr, 6033, "qhull input error: more than %d characters in command line\n",
+          (int)sizeof(qh qhull_command));
+    qh_exit(qh_ERRinput);  /* error reported, can not use qh_errexit */
+  }
+} /* init_qhull_command */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="initflags">-</a>
+
+  qh_initflags( commandStr )
+    set flags and initialized constants from commandStr
+
+  returns:
+    sets qh.qhull_command to command if needed
+
+  notes:
+    ignores first word (e.g., "qhull d")
+    use qh_strtol/strtod since strtol/strtod may or may not skip trailing spaces
+
+  see:
+    qh_initthresholds() continues processing of 'Pdn' and 'PDn'
+    'prompt' in unix.c for documentation
+
+  design:
+    for each space-delimited option group
+      if top-level option
+        check syntax
+        append appropriate option to option string
+        set appropriate global variable or append printFormat to print options
+      else
+        for each sub-option
+          check syntax
+          append appropriate option to option string
+          set appropriate global variable or append printFormat to print options
+*/
+void qh_initflags(char *command) {
+  int k, i, lastproject;
+  char *s= command, *t, *prev_s, *start, key;
+  boolT isgeom= False, wasproject;
+  realT r;
+
+  if (command <= &qh qhull_command[0] || command > &qh qhull_command[0] + sizeof(qh qhull_command)) {
+    if (command != &qh qhull_command[0]) {
+      *qh qhull_command= '\0';
+      strncat(qh qhull_command, command, sizeof(qh qhull_command)-strlen(qh qhull_command)-1);
+    }
+    while (*s && !isspace(*s))  /* skip program name */
+      s++;
+  }
+  while (*s) {
+    while (*s && isspace(*s))
+      s++;
+    if (*s == '-')
+      s++;
+    if (!*s)
+      break;
+    prev_s= s;
+    switch (*s++) {
+    case 'd':
+      qh_option("delaunay", NULL, NULL);
+      qh DELAUNAY= True;
+      break;
+    case 'f':
+      qh_option("facets", NULL, NULL);
+      qh_appendprint(qh_PRINTfacets);
+      break;
+    case 'i':
+      qh_option("incidence", NULL, NULL);
+      qh_appendprint(qh_PRINTincidences);
+      break;
+    case 'm':
+      qh_option("mathematica", NULL, NULL);
+      qh_appendprint(qh_PRINTmathematica);
+      break;
+    case 'n':
+      qh_option("normals", NULL, NULL);
+      qh_appendprint(qh_PRINTnormals);
+      break;
+    case 'o':
+      qh_option("offFile", NULL, NULL);
+      qh_appendprint(qh_PRINToff);
+      break;
+    case 'p':
+      qh_option("points", NULL, NULL);
+      qh_appendprint(qh_PRINTpoints);
+      break;
+    case 's':
+      qh_option("summary", NULL, NULL);
+      qh PRINTsummary= True;
+      break;
+    case 'v':
+      qh_option("voronoi", NULL, NULL);
+      qh VORONOI= True;
+      qh DELAUNAY= True;
+      break;
+    case 'A':
+      if (!isdigit(*s) && *s != '.' && *s != '-')
+        qh_fprintf(qh ferr, 7002, "qhull warning: no maximum cosine angle given for option 'An'.  Ignored.\n");
+      else {
+        if (*s == '-') {
+          qh premerge_cos= -qh_strtod(s, &s);
+          qh_option("Angle-premerge-", NULL, &qh premerge_cos);
+          qh PREmerge= True;
+        }else {
+          qh postmerge_cos= qh_strtod(s, &s);
+          qh_option("Angle-postmerge", NULL, &qh postmerge_cos);
+          qh POSTmerge= True;
+        }
+        qh MERGING= True;
+      }
+      break;
+    case 'C':
+      if (!isdigit(*s) && *s != '.' && *s != '-')
+        qh_fprintf(qh ferr, 7003, "qhull warning: no centrum radius given for option 'Cn'.  Ignored.\n");
+      else {
+        if (*s == '-') {
+          qh premerge_centrum= -qh_strtod(s, &s);
+          qh_option("Centrum-premerge-", NULL, &qh premerge_centrum);
+          qh PREmerge= True;
+        }else {
+          qh postmerge_centrum= qh_strtod(s, &s);
+          qh_option("Centrum-postmerge", NULL, &qh postmerge_centrum);
+          qh POSTmerge= True;
+        }
+        qh MERGING= True;
+      }
+      break;
+    case 'E':
+      if (*s == '-')
+        qh_fprintf(qh ferr, 7004, "qhull warning: negative maximum roundoff given for option 'An'.  Ignored.\n");
+      else if (!isdigit(*s))
+        qh_fprintf(qh ferr, 7005, "qhull warning: no maximum roundoff given for option 'En'.  Ignored.\n");
+      else {
+        qh DISTround= qh_strtod(s, &s);
+        qh_option("Distance-roundoff", NULL, &qh DISTround);
+        qh SETroundoff= True;
+      }
+      break;
+    case 'H':
+      start= s;
+      qh HALFspace= True;
+      qh_strtod(s, &t);
+      while (t > s)  {
+        if (*t && !isspace(*t)) {
+          if (*t == ',')
+            t++;
+          else
+            qh_fprintf(qh ferr, 7006, "qhull warning: origin for Halfspace intersection should be 'Hn,n,n,...'\n");
+        }
+        s= t;
+        qh_strtod(s, &t);
+      }
+      if (start < t) {
+        if (!(qh feasible_string= (char*)calloc((size_t)(t-start+1), (size_t)1))) {
+          qh_fprintf(qh ferr, 6034, "qhull error: insufficient memory for 'Hn,n,n'\n");
+          qh_errexit(qh_ERRmem, NULL, NULL);
+        }
+        strncpy(qh feasible_string, start, (size_t)(t-start));
+        qh_option("Halfspace-about", NULL, NULL);
+        qh_option(qh feasible_string, NULL, NULL);
+      }else
+        qh_option("Halfspace", NULL, NULL);
+      break;
+    case 'R':
+      if (!isdigit(*s))
+        qh_fprintf(qh ferr, 7007, "qhull warning: missing random perturbation for option 'Rn'.  Ignored\n");
+      else {
+        qh RANDOMfactor= qh_strtod(s, &s);
+        qh_option("Random_perturb", NULL, &qh RANDOMfactor);
+        qh RANDOMdist= True;
+      }
+      break;
+    case 'V':
+      if (!isdigit(*s) && *s != '-')
+        qh_fprintf(qh ferr, 7008, "qhull warning: missing visible distance for option 'Vn'.  Ignored\n");
+      else {
+        qh MINvisible= qh_strtod(s, &s);
+        qh_option("Visible", NULL, &qh MINvisible);
+      }
+      break;
+    case 'U':
+      if (!isdigit(*s) && *s != '-')
+        qh_fprintf(qh ferr, 7009, "qhull warning: missing coplanar distance for option 'Un'.  Ignored\n");
+      else {
+        qh MAXcoplanar= qh_strtod(s, &s);
+        qh_option("U-coplanar", NULL, &qh MAXcoplanar);
+      }
+      break;
+    case 'W':
+      if (*s == '-')
+        qh_fprintf(qh ferr, 7010, "qhull warning: negative outside width for option 'Wn'.  Ignored.\n");
+      else if (!isdigit(*s))
+        qh_fprintf(qh ferr, 7011, "qhull warning: missing outside width for option 'Wn'.  Ignored\n");
+      else {
+        qh MINoutside= qh_strtod(s, &s);
+        qh_option("W-outside", NULL, &qh MINoutside);
+        qh APPROXhull= True;
+      }
+      break;
+    /************  sub menus ***************/
+    case 'F':
+      while (*s && !isspace(*s)) {
+        switch (*s++) {
+        case 'a':
+          qh_option("Farea", NULL, NULL);
+          qh_appendprint(qh_PRINTarea);
+          qh GETarea= True;
+          break;
+        case 'A':
+          qh_option("FArea-total", NULL, NULL);
+          qh GETarea= True;
+          break;
+        case 'c':
+          qh_option("Fcoplanars", NULL, NULL);
+          qh_appendprint(qh_PRINTcoplanars);
+          break;
+        case 'C':
+          qh_option("FCentrums", NULL, NULL);
+          qh_appendprint(qh_PRINTcentrums);
+          break;
+        case 'd':
+          qh_option("Fd-cdd-in", NULL, NULL);
+          qh CDDinput= True;
+          break;
+        case 'D':
+          qh_option("FD-cdd-out", NULL, NULL);
+          qh CDDoutput= True;
+          break;
+        case 'F':
+          qh_option("FFacets-xridge", NULL, NULL);
+          qh_appendprint(qh_PRINTfacets_xridge);
+          break;
+        case 'i':
+          qh_option("Finner", NULL, NULL);
+          qh_appendprint(qh_PRINTinner);
+          break;
+        case 'I':
+          qh_option("FIDs", NULL, NULL);
+          qh_appendprint(qh_PRINTids);
+          break;
+        case 'm':
+          qh_option("Fmerges", NULL, NULL);
+          qh_appendprint(qh_PRINTmerges);
+          break;
+        case 'M':
+          qh_option("FMaple", NULL, NULL);
+          qh_appendprint(qh_PRINTmaple);
+          break;
+        case 'n':
+          qh_option("Fneighbors", NULL, NULL);
+          qh_appendprint(qh_PRINTneighbors);
+          break;
+        case 'N':
+          qh_option("FNeighbors-vertex", NULL, NULL);
+          qh_appendprint(qh_PRINTvneighbors);
+          break;
+        case 'o':
+          qh_option("Fouter", NULL, NULL);
+          qh_appendprint(qh_PRINTouter);
+          break;
+        case 'O':
+          if (qh PRINToptions1st) {
+            qh_option("FOptions", NULL, NULL);
+            qh_appendprint(qh_PRINToptions);
+          }else
+            qh PRINToptions1st= True;
+          break;
+        case 'p':
+          qh_option("Fpoint-intersect", NULL, NULL);
+          qh_appendprint(qh_PRINTpointintersect);
+          break;
+        case 'P':
+          qh_option("FPoint-nearest", NULL, NULL);
+          qh_appendprint(qh_PRINTpointnearest);
+          break;
+        case 'Q':
+          qh_option("FQhull", NULL, NULL);
+          qh_appendprint(qh_PRINTqhull);
+          break;
+        case 's':
+          qh_option("Fsummary", NULL, NULL);
+          qh_appendprint(qh_PRINTsummary);
+          break;
+        case 'S':
+          qh_option("FSize", NULL, NULL);
+          qh_appendprint(qh_PRINTsize);
+          qh GETarea= True;
+          break;
+        case 't':
+          qh_option("Ftriangles", NULL, NULL);
+          qh_appendprint(qh_PRINTtriangles);
+          break;
+        case 'v':
+          /* option set in qh_initqhull_globals */
+          qh_appendprint(qh_PRINTvertices);
+          break;
+        case 'V':
+          qh_option("FVertex-average", NULL, NULL);
+          qh_appendprint(qh_PRINTaverage);
+          break;
+        case 'x':
+          qh_option("Fxtremes", NULL, NULL);
+          qh_appendprint(qh_PRINTextremes);
+          break;
+        default:
+          s--;
+          qh_fprintf(qh ferr, 7012, "qhull warning: unknown 'F' output option %c, rest ignored\n", (int)s[0]);
+          while (*++s && !isspace(*s));
+          break;
+        }
+      }
+      break;
+    case 'G':
+      isgeom= True;
+      qh_appendprint(qh_PRINTgeom);
+      while (*s && !isspace(*s)) {
+        switch (*s++) {
+        case 'a':
+          qh_option("Gall-points", NULL, NULL);
+          qh PRINTdots= True;
+          break;
+        case 'c':
+          qh_option("Gcentrums", NULL, NULL);
+          qh PRINTcentrums= True;
+          break;
+        case 'h':
+          qh_option("Gintersections", NULL, NULL);
+          qh DOintersections= True;
+          break;
+        case 'i':
+          qh_option("Ginner", NULL, NULL);
+          qh PRINTinner= True;
+          break;
+        case 'n':
+          qh_option("Gno-planes", NULL, NULL);
+          qh PRINTnoplanes= True;
+          break;
+        case 'o':
+          qh_option("Gouter", NULL, NULL);
+          qh PRINTouter= True;
+          break;
+        case 'p':
+          qh_option("Gpoints", NULL, NULL);
+          qh PRINTcoplanar= True;
+          break;
+        case 'r':
+          qh_option("Gridges", NULL, NULL);
+          qh PRINTridges= True;
+          break;
+        case 't':
+          qh_option("Gtransparent", NULL, NULL);
+          qh PRINTtransparent= True;
+          break;
+        case 'v':
+          qh_option("Gvertices", NULL, NULL);
+          qh PRINTspheres= True;
+          break;
+        case 'D':
+          if (!isdigit(*s))
+            qh_fprintf(qh ferr, 6035, "qhull input error: missing dimension for option 'GDn'\n");
+          else {
+            if (qh DROPdim >= 0)
+              qh_fprintf(qh ferr, 7013, "qhull warning: can only drop one dimension.  Previous 'GD%d' ignored\n",
+                   qh DROPdim);
+            qh DROPdim= qh_strtol(s, &s);
+            qh_option("GDrop-dim", &qh DROPdim, NULL);
+          }
+          break;
+        default:
+          s--;
+          qh_fprintf(qh ferr, 7014, "qhull warning: unknown 'G' print option %c, rest ignored\n", (int)s[0]);
+          while (*++s && !isspace(*s));
+          break;
+        }
+      }
+      break;
+    case 'P':
+      while (*s && !isspace(*s)) {
+        switch (*s++) {
+        case 'd': case 'D':  /* see qh_initthresholds() */
+          key= s[-1];
+          i= qh_strtol(s, &s);
+          r= 0;
+          if (*s == ':') {
+            s++;
+            r= qh_strtod(s, &s);
+          }
+          if (key == 'd')
+            qh_option("Pdrop-facets-dim-less", &i, &r);
+          else
+            qh_option("PDrop-facets-dim-more", &i, &r);
+          break;
+        case 'g':
+          qh_option("Pgood-facets", NULL, NULL);
+          qh PRINTgood= True;
+          break;
+        case 'G':
+          qh_option("PGood-facet-neighbors", NULL, NULL);
+          qh PRINTneighbors= True;
+          break;
+        case 'o':
+          qh_option("Poutput-forced", NULL, NULL);
+          qh FORCEoutput= True;
+          break;
+        case 'p':
+          qh_option("Pprecision-ignore", NULL, NULL);
+          qh PRINTprecision= False;
+          break;
+        case 'A':
+          if (!isdigit(*s))
+            qh_fprintf(qh ferr, 6036, "qhull input error: missing facet count for keep area option 'PAn'\n");
+          else {
+            qh KEEParea= qh_strtol(s, &s);
+            qh_option("PArea-keep", &qh KEEParea, NULL);
+            qh GETarea= True;
+          }
+          break;
+        case 'F':
+          if (!isdigit(*s))
+            qh_fprintf(qh ferr, 6037, "qhull input error: missing facet area for option 'PFn'\n");
+          else {
+            qh KEEPminArea= qh_strtod(s, &s);
+            qh_option("PFacet-area-keep", NULL, &qh KEEPminArea);
+            qh GETarea= True;
+          }
+          break;
+        case 'M':
+          if (!isdigit(*s))
+            qh_fprintf(qh ferr, 6038, "qhull input error: missing merge count for option 'PMn'\n");
+          else {
+            qh KEEPmerge= qh_strtol(s, &s);
+            qh_option("PMerge-keep", &qh KEEPmerge, NULL);
+          }
+          break;
+        default:
+          s--;
+          qh_fprintf(qh ferr, 7015, "qhull warning: unknown 'P' print option %c, rest ignored\n", (int)s[0]);
+          while (*++s && !isspace(*s));
+          break;
+        }
+      }
+      break;
+    case 'Q':
+      lastproject= -1;
+      while (*s && !isspace(*s)) {
+        switch (*s++) {
+        case 'b': case 'B':  /* handled by qh_initthresholds */
+          key= s[-1];
+          if (key == 'b' && *s == 'B') {
+            s++;
+            r= qh_DEFAULTbox;
+            qh SCALEinput= True;
+            qh_option("QbBound-unit-box", NULL, &r);
+            break;
+          }
+          if (key == 'b' && *s == 'b') {
+            s++;
+            qh SCALElast= True;
+            qh_option("Qbbound-last", NULL, NULL);
+            break;
+          }
+          k= qh_strtol(s, &s);
+          r= 0.0;
+          wasproject= False;
+          if (*s == ':') {
+            s++;
+            if ((r= qh_strtod(s, &s)) == 0.0) {
+              t= s;            /* need true dimension for memory allocation */
+              while (*t && !isspace(*t)) {
+                if (toupper(*t++) == 'B'
+                 && k == qh_strtol(t, &t)
+                 && *t++ == ':'
+                 && qh_strtod(t, &t) == 0.0) {
+                  qh PROJECTinput++;
+                  trace2((qh ferr, 2004, "qh_initflags: project dimension %d\n", k));
+                  qh_option("Qb-project-dim", &k, NULL);
+                  wasproject= True;
+                  lastproject= k;
+                  break;
+                }
+              }
+            }
+          }
+          if (!wasproject) {
+            if (lastproject == k && r == 0.0)
+              lastproject= -1;  /* doesn't catch all possible sequences */
+            else if (key == 'b') {
+              qh SCALEinput= True;
+              if (r == 0.0)
+                r= -qh_DEFAULTbox;
+              qh_option("Qbound-dim-low", &k, &r);
+            }else {
+              qh SCALEinput= True;
+              if (r == 0.0)
+                r= qh_DEFAULTbox;
+              qh_option("QBound-dim-high", &k, &r);
+            }
+          }
+          break;
+        case 'c':
+          qh_option("Qcoplanar-keep", NULL, NULL);
+          qh KEEPcoplanar= True;
+          break;
+        case 'f':
+          qh_option("Qfurthest-outside", NULL, NULL);
+          qh BESToutside= True;
+          break;
+        case 'g':
+          qh_option("Qgood-facets-only", NULL, NULL);
+          qh ONLYgood= True;
+          break;
+        case 'i':
+          qh_option("Qinterior-keep", NULL, NULL);
+          qh KEEPinside= True;
+          break;
+        case 'm':
+          qh_option("Qmax-outside-only", NULL, NULL);
+          qh ONLYmax= True;
+          break;
+        case 'r':
+          qh_option("Qrandom-outside", NULL, NULL);
+          qh RANDOMoutside= True;
+          break;
+        case 's':
+          qh_option("Qsearch-initial-simplex", NULL, NULL);
+          qh ALLpoints= True;
+          break;
+        case 't':
+          qh_option("Qtriangulate", NULL, NULL);
+          qh TRIangulate= True;
+          break;
+        case 'T':
+          qh_option("QTestPoints", NULL, NULL);
+          if (!isdigit(*s))
+            qh_fprintf(qh ferr, 6039, "qhull input error: missing number of test points for option 'QTn'\n");
+          else {
+            qh TESTpoints= qh_strtol(s, &s);
+            qh_option("QTestPoints", &qh TESTpoints, NULL);
+          }
+          break;
+        case 'u':
+          qh_option("QupperDelaunay", NULL, NULL);
+          qh UPPERdelaunay= True;
+          break;
+        case 'v':
+          qh_option("Qvertex-neighbors-convex", NULL, NULL);
+          qh TESTvneighbors= True;
+          break;
+        case 'x':
+          qh_option("Qxact-merge", NULL, NULL);
+          qh MERGEexact= True;
+          break;
+        case 'z':
+          qh_option("Qz-infinity-point", NULL, NULL);
+          qh ATinfinity= True;
+          break;
+        case '0':
+          qh_option("Q0-no-premerge", NULL, NULL);
+          qh NOpremerge= True;
+          break;
+        case '1':
+          if (!isdigit(*s)) {
+            qh_option("Q1-no-angle-sort", NULL, NULL);
+            qh ANGLEmerge= False;
+            break;
+          }
+          switch (*s++) {
+          case '0':
+            qh_option("Q10-no-narrow", NULL, NULL);
+            qh NOnarrow= True;
+            break;
+          case '1':
+            qh_option("Q11-trinormals Qtriangulate", NULL, NULL);
+            qh TRInormals= True;
+            qh TRIangulate= True;
+            break;
+          default:
+            s--;
+            qh_fprintf(qh ferr, 7016, "qhull warning: unknown 'Q' qhull option 1%c, rest ignored\n", (int)s[0]);
+            while (*++s && !isspace(*s));
+            break;
+          }
+          break;
+        case '2':
+          qh_option("Q2-no-merge-independent", NULL, NULL);
+          qh MERGEindependent= False;
+          goto LABELcheckdigit;
+          break; /* no warnings */
+        case '3':
+          qh_option("Q3-no-merge-vertices", NULL, NULL);
+          qh MERGEvertices= False;
+        LABELcheckdigit:
+          if (isdigit(*s))
+            qh_fprintf(qh ferr, 7017, "qhull warning: can not follow '1', '2', or '3' with a digit.  '%c' skipped.\n",
+                     *s++);
+          break;
+        case '4':
+          qh_option("Q4-avoid-old-into-new", NULL, NULL);
+          qh AVOIDold= True;
+          break;
+        case '5':
+          qh_option("Q5-no-check-outer", NULL, NULL);
+          qh SKIPcheckmax= True;
+          break;
+        case '6':
+          qh_option("Q6-no-concave-merge", NULL, NULL);
+          qh SKIPconvex= True;
+          break;
+        case '7':
+          qh_option("Q7-no-breadth-first", NULL, NULL);
+          qh VIRTUALmemory= True;
+          break;
+        case '8':
+          qh_option("Q8-no-near-inside", NULL, NULL);
+          qh NOnearinside= True;
+          break;
+        case '9':
+          qh_option("Q9-pick-furthest", NULL, NULL);
+          qh PICKfurthest= True;
+          break;
+        case 'G':
+          i= qh_strtol(s, &t);
+          if (qh GOODpoint)
+            qh_fprintf(qh ferr, 7018, "qhull warning: good point already defined for option 'QGn'.  Ignored\n");
+          else if (s == t)
+            qh_fprintf(qh ferr, 7019, "qhull warning: missing good point id for option 'QGn'.  Ignored\n");
+          else if (i < 0 || *s == '-') {
+            qh GOODpoint= i-1;
+            qh_option("QGood-if-dont-see-point", &i, NULL);
+          }else {
+            qh GOODpoint= i+1;
+            qh_option("QGood-if-see-point", &i, NULL);
+          }
+          s= t;
+          break;
+        case 'J':
+          if (!isdigit(*s) && *s != '-')
+            qh JOGGLEmax= 0.0;
+          else {
+            qh JOGGLEmax= (realT) qh_strtod(s, &s);
+            qh_option("QJoggle", NULL, &qh JOGGLEmax);
+          }
+          break;
+        case 'R':
+          if (!isdigit(*s) && *s != '-')
+            qh_fprintf(qh ferr, 7020, "qhull warning: missing random seed for option 'QRn'.  Ignored\n");
+          else {
+            qh ROTATErandom= i= qh_strtol(s, &s);
+            if (i > 0)
+              qh_option("QRotate-id", &i, NULL );
+            else if (i < -1)
+              qh_option("QRandom-seed", &i, NULL );
+          }
+          break;
+        case 'V':
+          i= qh_strtol(s, &t);
+          if (qh GOODvertex)
+            qh_fprintf(qh ferr, 7021, "qhull warning: good vertex already defined for option 'QVn'.  Ignored\n");
+          else if (s == t)
+            qh_fprintf(qh ferr, 7022, "qhull warning: no good point id given for option 'QVn'.  Ignored\n");
+          else if (i < 0) {
+            qh GOODvertex= i - 1;
+            qh_option("QV-good-facets-not-point", &i, NULL);
+          }else {
+            qh_option("QV-good-facets-point", &i, NULL);
+            qh GOODvertex= i + 1;
+          }
+          s= t;
+          break;
+        default:
+          s--;
+          qh_fprintf(qh ferr, 7023, "qhull warning: unknown 'Q' qhull option %c, rest ignored\n", (int)s[0]);
+          while (*++s && !isspace(*s));
+          break;
+        }
+      }
+      break;
+    case 'T':
+      while (*s && !isspace(*s)) {
+        if (isdigit(*s) || *s == '-')
+          qh IStracing= qh_strtol(s, &s);
+        else switch (*s++) {
+        case 'a':
+          qh_option("Tannotate-output", NULL, NULL);
+          qh ANNOTATEoutput= True;
+          break;
+        case 'c':
+          qh_option("Tcheck-frequently", NULL, NULL);
+          qh CHECKfrequently= True;
+          break;
+        case 's':
+          qh_option("Tstatistics", NULL, NULL);
+          qh PRINTstatistics= True;
+          break;
+        case 'v':
+          qh_option("Tverify", NULL, NULL);
+          qh VERIFYoutput= True;
+          break;
+        case 'z':
+          if (qh ferr == qh_FILEstderr) {
+            /* The C++ interface captures the output in qh_fprint_qhull() */
+            qh_option("Tz-stdout", NULL, NULL);
+            qh USEstdout= True;
+          }else if (!qh fout)
+            qh_fprintf(qh ferr, 7024, "qhull warning: output file undefined(stdout).  Option 'Tz' ignored.\n");
+          else {
+            qh_option("Tz-stdout", NULL, NULL);
+            qh USEstdout= True;
+            qh ferr= qh fout;
+            qhmem.ferr= qh fout;
+          }
+          break;
+        case 'C':
+          if (!isdigit(*s))
+            qh_fprintf(qh ferr, 7025, "qhull warning: missing point id for cone for trace option 'TCn'.  Ignored\n");
+          else {
+            i= qh_strtol(s, &s);
+            qh_option("TCone-stop", &i, NULL);
+            qh STOPcone= i + 1;
+          }
+          break;
+        case 'F':
+          if (!isdigit(*s))
+            qh_fprintf(qh ferr, 7026, "qhull warning: missing frequency count for trace option 'TFn'.  Ignored\n");
+          else {
+            qh REPORTfreq= qh_strtol(s, &s);
+            qh_option("TFacet-log", &qh REPORTfreq, NULL);
+            qh REPORTfreq2= qh REPORTfreq/2;  /* for tracemerging() */
+          }
+          break;
+        case 'I':
+          if (!isspace(*s))
+            qh_fprintf(qh ferr, 7027, "qhull warning: missing space between 'TI' and filename, %s\n", s);
+          while (isspace(*s))
+            s++;
+          t= qh_skipfilename(s);
+          {
+            char filename[qh_FILENAMElen];
+
+            qh_copyfilename(filename, (int)sizeof(filename), s, (int)(t-s));   /* WARN64 */
+            s= t;
+            if (!freopen(filename, "r", stdin)) {
+              qh_fprintf(qh ferr, 6041, "qhull error: could not open file \"%s\".", filename);
+              qh_errexit(qh_ERRinput, NULL, NULL);
+            }else {
+              qh_option("TInput-file", NULL, NULL);
+              qh_option(filename, NULL, NULL);
+            }
+          }
+          break;
+        case 'O':
+            if (!isspace(*s))
+                qh_fprintf(qh ferr, 7028, "qhull warning: missing space between 'TO' and filename, %s\n", s);
+            while (isspace(*s))
+                s++;
+            t= qh_skipfilename(s);
+            {
+              char filename[qh_FILENAMElen];
+
+              qh_copyfilename(filename, (int)sizeof(filename), s, (int)(t-s));  /* WARN64 */
+              s= t;
+              if (!freopen(filename, "w", stdout)) {
+                qh_fprintf(qh ferr, 6044, "qhull error: could not open file \"%s\".", filename);
+                qh_errexit(qh_ERRinput, NULL, NULL);
+              }else {
+                qh_option("TOutput-file", NULL, NULL);
+              qh_option(filename, NULL, NULL);
+            }
+          }
+          break;
+        case 'P':
+          if (!isdigit(*s))
+            qh_fprintf(qh ferr, 7029, "qhull warning: missing point id for trace option 'TPn'.  Ignored\n");
+          else {
+            qh TRACEpoint= qh_strtol(s, &s);
+            qh_option("Trace-point", &qh TRACEpoint, NULL);
+          }
+          break;
+        case 'M':
+          if (!isdigit(*s))
+            qh_fprintf(qh ferr, 7030, "qhull warning: missing merge id for trace option 'TMn'.  Ignored\n");
+          else {
+            qh TRACEmerge= qh_strtol(s, &s);
+            qh_option("Trace-merge", &qh TRACEmerge, NULL);
+          }
+          break;
+        case 'R':
+          if (!isdigit(*s))
+            qh_fprintf(qh ferr, 7031, "qhull warning: missing rerun count for trace option 'TRn'.  Ignored\n");
+          else {
+            qh RERUN= qh_strtol(s, &s);
+            qh_option("TRerun", &qh RERUN, NULL);
+          }
+          break;
+        case 'V':
+          i= qh_strtol(s, &t);
+          if (s == t)
+            qh_fprintf(qh ferr, 7032, "qhull warning: missing furthest point id for trace option 'TVn'.  Ignored\n");
+          else if (i < 0) {
+            qh STOPpoint= i - 1;
+            qh_option("TV-stop-before-point", &i, NULL);
+          }else {
+            qh STOPpoint= i + 1;
+            qh_option("TV-stop-after-point", &i, NULL);
+          }
+          s= t;
+          break;
+        case 'W':
+          if (!isdigit(*s))
+            qh_fprintf(qh ferr, 7033, "qhull warning: missing max width for trace option 'TWn'.  Ignored\n");
+          else {
+            qh TRACEdist= (realT) qh_strtod(s, &s);
+            qh_option("TWide-trace", NULL, &qh TRACEdist);
+          }
+          break;
+        default:
+          s--;
+          qh_fprintf(qh ferr, 7034, "qhull warning: unknown 'T' trace option %c, rest ignored\n", (int)s[0]);
+          while (*++s && !isspace(*s));
+          break;
+        }
+      }
+      break;
+    default:
+      qh_fprintf(qh ferr, 7035, "qhull warning: unknown flag %c(%x)\n", (int)s[-1],
+               (int)s[-1]);
+      break;
+    }
+    if (s-1 == prev_s && *s && !isspace(*s)) {
+      qh_fprintf(qh ferr, 7036, "qhull warning: missing space after flag %c(%x); reserved for menu. Skipped.\n",
+               (int)*prev_s, (int)*prev_s);
+      while (*s && !isspace(*s))
+        s++;
+    }
+  }
+  if (qh STOPcone && qh JOGGLEmax < REALmax/2)
+    qh_fprintf(qh ferr, 7078, "qhull warning: 'TCn' (stopCone) ignored when used with 'QJn' (joggle)\n");
+  if (isgeom && !qh FORCEoutput && qh PRINTout[1])
+    qh_fprintf(qh ferr, 7037, "qhull warning: additional output formats are not compatible with Geomview\n");
+  /* set derived values in qh_initqhull_globals */
+} /* initflags */
+
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="initqhull_buffers">-</a>
+
+  qh_initqhull_buffers()
+    initialize global memory buffers
+
+  notes:
+    must match qh_freebuffers()
+*/
+void qh_initqhull_buffers(void) {
+  int k;
+
+  qh TEMPsize= (qhmem.LASTsize - sizeof(setT))/SETelemsize;
+  if (qh TEMPsize <= 0 || qh TEMPsize > qhmem.LASTsize)
+    qh TEMPsize= 8;  /* e.g., if qh_NOmem */
+  qh other_points= qh_setnew(qh TEMPsize);
+  qh del_vertices= qh_setnew(qh TEMPsize);
+  qh coplanarfacetset= qh_setnew(qh TEMPsize);
+  qh NEARzero= (realT *)qh_memalloc(qh hull_dim * sizeof(realT));
+  qh lower_threshold= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
+  qh upper_threshold= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
+  qh lower_bound= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
+  qh upper_bound= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
+  for (k=qh input_dim+1; k--; ) {  /* duplicated in qh_initqhull_buffers and qh_clear_outputflags */
+    qh lower_threshold[k]= -REALmax;
+    qh upper_threshold[k]= REALmax;
+    qh lower_bound[k]= -REALmax;
+    qh upper_bound[k]= REALmax;
+  }
+  qh gm_matrix= (coordT *)qh_memalloc((qh hull_dim+1) * qh hull_dim * sizeof(coordT));
+  qh gm_row= (coordT **)qh_memalloc((qh hull_dim+1) * sizeof(coordT *));
+} /* initqhull_buffers */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="initqhull_globals">-</a>
+
+  qh_initqhull_globals( points, numpoints, dim, ismalloc )
+    initialize globals
+    if ismalloc
+      points were malloc'd and qhull should free at end
+
+  returns:
+    sets qh.first_point, num_points, input_dim, hull_dim and others
+    seeds random number generator (seed=1 if tracing)
+    modifies qh.hull_dim if ((qh.DELAUNAY and qh.PROJECTdelaunay) or qh.PROJECTinput)
+    adjust user flags as needed
+    also checks DIM3 dependencies and constants
+
+  notes:
+    do not use qh_point() since an input transformation may move them elsewhere
+
+  see:
+    qh_initqhull_start() sets default values for non-zero globals
+
+  design:
+    initialize points array from input arguments
+    test for qh.ZEROcentrum
+      (i.e., use opposite vertex instead of centrum for convexity testing)
+    initialize qh.CENTERtype, qh.normal_size,
+      qh.center_size, qh.TRACEpoint/level,
+    initialize and test random numbers
+    qh_initqhull_outputflags() -- adjust and test output flags
+*/
+void qh_initqhull_globals(coordT *points, int numpoints, int dim, boolT ismalloc) {
+  int seed, pointsneeded, extra= 0, i, randi, k;
+  realT randr;
+  realT factorial;
+
+  time_t timedata;
+
+  trace0((qh ferr, 13, "qh_initqhull_globals: for %s | %s\n", qh rbox_command,
+      qh qhull_command));
+  qh POINTSmalloc= ismalloc;
+  qh first_point= points;
+  qh num_points= numpoints;
+  qh hull_dim= qh input_dim= dim;
+  if (!qh NOpremerge && !qh MERGEexact && !qh PREmerge && qh JOGGLEmax > REALmax/2) {
+    qh MERGING= True;
+    if (qh hull_dim <= 4) {
+      qh PREmerge= True;
+      qh_option("_pre-merge", NULL, NULL);
+    }else {
+      qh MERGEexact= True;
+      qh_option("Qxact_merge", NULL, NULL);
+    }
+  }else if (qh MERGEexact)
+    qh MERGING= True;
+  if (!qh NOpremerge && qh JOGGLEmax > REALmax/2) {
+#ifdef qh_NOmerge
+    qh JOGGLEmax= 0.0;
+#endif
+  }
+  if (qh TRIangulate && qh JOGGLEmax < REALmax/2 && qh PRINTprecision)
+    qh_fprintf(qh ferr, 7038, "qhull warning: joggle('QJ') always produces simplicial output.  Triangulated output('Qt') does nothing.\n");
+  if (qh JOGGLEmax < REALmax/2 && qh DELAUNAY && !qh SCALEinput && !qh SCALElast) {
+    qh SCALElast= True;
+    qh_option("Qbbound-last-qj", NULL, NULL);
+  }
+  if (qh MERGING && !qh POSTmerge && qh premerge_cos > REALmax/2
+  && qh premerge_centrum == 0) {
+    qh ZEROcentrum= True;
+    qh ZEROall_ok= True;
+    qh_option("_zero-centrum", NULL, NULL);
+  }
+  if (qh JOGGLEmax < REALmax/2 && REALepsilon > 2e-8 && qh PRINTprecision)
+    qh_fprintf(qh ferr, 7039, "qhull warning: real epsilon, %2.2g, is probably too large for joggle('QJn')\nRecompile with double precision reals(see user.h).\n",
+          REALepsilon);
+#ifdef qh_NOmerge
+  if (qh MERGING) {
+    qh_fprintf(qh ferr, 6045, "qhull input error: merging not installed(qh_NOmerge + 'Qx', 'Cn' or 'An')\n");
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+#endif
+  if (qh DELAUNAY && qh KEEPcoplanar && !qh KEEPinside) {
+    qh KEEPinside= True;
+    qh_option("Qinterior-keep", NULL, NULL);
+  }
+  if (qh DELAUNAY && qh HALFspace) {
+    qh_fprintf(qh ferr, 6046, "qhull input error: can not use Delaunay('d') or Voronoi('v') with halfspace intersection('H')\n");
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  if (!qh DELAUNAY && (qh UPPERdelaunay || qh ATinfinity)) {
+    qh_fprintf(qh ferr, 6047, "qhull input error: use upper-Delaunay('Qu') or infinity-point('Qz') with Delaunay('d') or Voronoi('v')\n");
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  if (qh UPPERdelaunay && qh ATinfinity) {
+    qh_fprintf(qh ferr, 6048, "qhull input error: can not use infinity-point('Qz') with upper-Delaunay('Qu')\n");
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  if (qh SCALElast && !qh DELAUNAY && qh PRINTprecision)
+    qh_fprintf(qh ferr, 7040, "qhull input warning: option 'Qbb' (scale-last-coordinate) is normally used with 'd' or 'v'\n");
+  qh DOcheckmax= (!qh SKIPcheckmax && qh MERGING );
+  qh KEEPnearinside= (qh DOcheckmax && !(qh KEEPinside && qh KEEPcoplanar)
+                          && !qh NOnearinside);
+  if (qh MERGING)
+    qh CENTERtype= qh_AScentrum;
+  else if (qh VORONOI)
+    qh CENTERtype= qh_ASvoronoi;
+  if (qh TESTvneighbors && !qh MERGING) {
+    qh_fprintf(qh ferr, 6049, "qhull input error: test vertex neighbors('Qv') needs a merge option\n");
+    qh_errexit(qh_ERRinput, NULL ,NULL);
+  }
+  if (qh PROJECTinput || (qh DELAUNAY && qh PROJECTdelaunay)) {
+    qh hull_dim -= qh PROJECTinput;
+    if (qh DELAUNAY) {
+      qh hull_dim++;
+      if (qh ATinfinity)
+        extra= 1;
+    }
+  }
+  if (qh hull_dim <= 1) {
+    qh_fprintf(qh ferr, 6050, "qhull error: dimension %d must be > 1\n", qh hull_dim);
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  for (k=2, factorial=1.0; k < qh hull_dim; k++)
+    factorial *= k;
+  qh AREAfactor= 1.0 / factorial;
+  trace2((qh ferr, 2005, "qh_initqhull_globals: initialize globals.  dim %d numpoints %d malloc? %d projected %d to hull_dim %d\n",
+        dim, numpoints, ismalloc, qh PROJECTinput, qh hull_dim));
+  qh normal_size= qh hull_dim * sizeof(coordT);
+  qh center_size= qh normal_size - sizeof(coordT);
+  pointsneeded= qh hull_dim+1;
+  if (qh hull_dim > qh_DIMmergeVertex) {
+    qh MERGEvertices= False;
+    qh_option("Q3-no-merge-vertices-dim-high", NULL, NULL);
+  }
+  if (qh GOODpoint)
+    pointsneeded++;
+#ifdef qh_NOtrace
+  if (qh IStracing) {
+    qh_fprintf(qh ferr, 6051, "qhull input error: tracing is not installed(qh_NOtrace in user.h)");
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+#endif
+  if (qh RERUN > 1) {
+    qh TRACElastrun= qh IStracing; /* qh_build_withrestart duplicates next conditional */
+    if (qh IStracing != -1)
+      qh IStracing= 0;
+  }else if (qh TRACEpoint != -1 || qh TRACEdist < REALmax/2 || qh TRACEmerge) {
+    qh TRACElevel= (qh IStracing? qh IStracing : 3);
+    qh IStracing= 0;
+  }
+  if (qh ROTATErandom == 0 || qh ROTATErandom == -1) {
+    seed= (int)time(&timedata);
+    if (qh ROTATErandom  == -1) {
+      seed= -seed;
+      qh_option("QRandom-seed", &seed, NULL );
+    }else
+      qh_option("QRotate-random", &seed, NULL);
+    qh ROTATErandom= seed;
+  }
+  seed= qh ROTATErandom;
+  if (seed == INT_MIN)    /* default value */
+    seed= 1;
+  else if (seed < 0)
+    seed= -seed;
+  qh_RANDOMseed_(seed);
+  randr= 0.0;
+  for (i=1000; i--; ) {
+    randi= qh_RANDOMint;
+    randr += randi;
+    if (randi > qh_RANDOMmax) {
+      qh_fprintf(qh ferr, 8036, "\
+qhull configuration error (qh_RANDOMmax in user.h):\n\
+   random integer %d > qh_RANDOMmax(%.8g)\n",
+               randi, qh_RANDOMmax);
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+  }
+  qh_RANDOMseed_(seed);
+  randr = randr/1000;
+  if (randr < qh_RANDOMmax * 0.1
+  || randr > qh_RANDOMmax * 0.9)
+    qh_fprintf(qh ferr, 8037, "\
+qhull configuration warning (qh_RANDOMmax in user.h):\n\
+   average of 1000 random integers (%.2g) is much different than expected (%.2g).\n\
+   Is qh_RANDOMmax (%.2g) wrong?\n",
+             randr, qh_RANDOMmax * 0.5, qh_RANDOMmax);
+  qh RANDOMa= 2.0 * qh RANDOMfactor/qh_RANDOMmax;
+  qh RANDOMb= 1.0 - qh RANDOMfactor;
+  if (qh_HASHfactor < 1.1) {
+    qh_fprintf(qh ferr, 6052, "qhull internal error (qh_initqhull_globals): qh_HASHfactor %d must be at least 1.1.  Qhull uses linear hash probing\n",
+      qh_HASHfactor);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  if (numpoints+extra < pointsneeded) {
+    qh_fprintf(qh ferr, 6214, "qhull input error: not enough points(%d) to construct initial simplex (need %d)\n",
+            numpoints, pointsneeded);
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  qh_initqhull_outputflags();
+} /* initqhull_globals */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="initqhull_mem">-</a>
+
+  qh_initqhull_mem(  )
+    initialize mem.c for qhull
+    qh.hull_dim and qh.normal_size determine some of the allocation sizes
+    if qh.MERGING,
+      includes ridgeT
+    calls qh_user_memsizes() to add up to 10 additional sizes for quick allocation
+      (see numsizes below)
+
+  returns:
+    mem.c already for qh_memalloc/qh_memfree (errors if called beforehand)
+
+  notes:
+    qh_produceoutput() prints memsizes
+
+*/
+void qh_initqhull_mem(void) {
+  int numsizes;
+  int i;
+
+  numsizes= 8+10;
+  qh_meminitbuffers(qh IStracing, qh_MEMalign, numsizes,
+                     qh_MEMbufsize,qh_MEMinitbuf);
+  qh_memsize((int)sizeof(vertexT));
+  if (qh MERGING) {
+    qh_memsize((int)sizeof(ridgeT));
+    qh_memsize((int)sizeof(mergeT));
+  }
+  qh_memsize((int)sizeof(facetT));
+  i= sizeof(setT) + (qh hull_dim - 1) * SETelemsize;  /* ridge.vertices */
+  qh_memsize(i);
+  qh_memsize(qh normal_size);        /* normal */
+  i += SETelemsize;                 /* facet.vertices, .ridges, .neighbors */
+  qh_memsize(i);
+  qh_user_memsizes();
+  qh_memsetup();
+} /* initqhull_mem */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="initqhull_outputflags">-</a>
+
+  qh_initqhull_outputflags
+    initialize flags concerned with output
+
+  returns:
+    adjust user flags as needed
+
+  see:
+    qh_clear_outputflags() resets the flags
+
+  design:
+    test for qh.PRINTgood (i.e., only print 'good' facets)
+    check for conflicting print output options
+*/
+void qh_initqhull_outputflags(void) {
+  boolT printgeom= False, printmath= False, printcoplanar= False;
+  int i;
+
+  trace3((qh ferr, 3024, "qh_initqhull_outputflags: %s\n", qh qhull_command));
+  if (!(qh PRINTgood || qh PRINTneighbors)) {
+    if (qh KEEParea || qh KEEPminArea < REALmax/2 || qh KEEPmerge || qh DELAUNAY
+        || (!qh ONLYgood && (qh GOODvertex || qh GOODpoint))) {
+      qh PRINTgood= True;
+      qh_option("Pgood", NULL, NULL);
+    }
+  }
+  if (qh PRINTtransparent) {
+    if (qh hull_dim != 4 || !qh DELAUNAY || qh VORONOI || qh DROPdim >= 0) {
+      qh_fprintf(qh ferr, 6215, "qhull input error: transparent Delaunay('Gt') needs 3-d Delaunay('d') w/o 'GDn'\n");
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+    qh DROPdim = 3;
+    qh PRINTridges = True;
+  }
+  for (i=qh_PRINTEND; i--; ) {
+    if (qh PRINTout[i] == qh_PRINTgeom)
+      printgeom= True;
+    else if (qh PRINTout[i] == qh_PRINTmathematica || qh PRINTout[i] == qh_PRINTmaple)
+      printmath= True;
+    else if (qh PRINTout[i] == qh_PRINTcoplanars)
+      printcoplanar= True;
+    else if (qh PRINTout[i] == qh_PRINTpointnearest)
+      printcoplanar= True;
+    else if (qh PRINTout[i] == qh_PRINTpointintersect && !qh HALFspace) {
+      qh_fprintf(qh ferr, 6053, "qhull input error: option 'Fp' is only used for \nhalfspace intersection('Hn,n,n').\n");
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }else if (qh PRINTout[i] == qh_PRINTtriangles && (qh HALFspace || qh VORONOI)) {
+      qh_fprintf(qh ferr, 6054, "qhull input error: option 'Ft' is not available for Voronoi vertices or halfspace intersection\n");
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }else if (qh PRINTout[i] == qh_PRINTcentrums && qh VORONOI) {
+      qh_fprintf(qh ferr, 6055, "qhull input error: option 'FC' is not available for Voronoi vertices('v')\n");
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }else if (qh PRINTout[i] == qh_PRINTvertices) {
+      if (qh VORONOI)
+        qh_option("Fvoronoi", NULL, NULL);
+      else
+        qh_option("Fvertices", NULL, NULL);
+    }
+  }
+  if (printcoplanar && qh DELAUNAY && qh JOGGLEmax < REALmax/2) {
+    if (qh PRINTprecision)
+      qh_fprintf(qh ferr, 7041, "qhull input warning: 'QJ' (joggle) will usually prevent coincident input sites for options 'Fc' and 'FP'\n");
+  }
+  if (printmath && (qh hull_dim > 3 || qh VORONOI)) {
+    qh_fprintf(qh ferr, 6056, "qhull input error: Mathematica and Maple output is only available for 2-d and 3-d convex hulls and 2-d Delaunay triangulations\n");
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  if (printgeom) {
+    if (qh hull_dim > 4) {
+      qh_fprintf(qh ferr, 6057, "qhull input error: Geomview output is only available for 2-d, 3-d and 4-d\n");
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+    if (qh PRINTnoplanes && !(qh PRINTcoplanar + qh PRINTcentrums
+     + qh PRINTdots + qh PRINTspheres + qh DOintersections + qh PRINTridges)) {
+      qh_fprintf(qh ferr, 6058, "qhull input error: no output specified for Geomview\n");
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+    if (qh VORONOI && (qh hull_dim > 3 || qh DROPdim >= 0)) {
+      qh_fprintf(qh ferr, 6059, "qhull input error: Geomview output for Voronoi diagrams only for 2-d\n");
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+    /* can not warn about furthest-site Geomview output: no lower_threshold */
+    if (qh hull_dim == 4 && qh DROPdim == -1 &&
+        (qh PRINTcoplanar || qh PRINTspheres || qh PRINTcentrums)) {
+      qh_fprintf(qh ferr, 7042, "qhull input warning: coplanars, vertices, and centrums output not\n\
+available for 4-d output(ignored).  Could use 'GDn' instead.\n");
+      qh PRINTcoplanar= qh PRINTspheres= qh PRINTcentrums= False;
+    }
+  }
+  if (!qh KEEPcoplanar && !qh KEEPinside && !qh ONLYgood) {
+    if ((qh PRINTcoplanar && qh PRINTspheres) || printcoplanar) {
+      if (qh QHULLfinished) {
+        qh_fprintf(qh ferr, 7072, "qhull output warning: ignoring coplanar points, option 'Qc' was not set for the first run of qhull.\n");
+      }else {
+        qh KEEPcoplanar = True;
+        qh_option("Qcoplanar", NULL, NULL);
+      }
+    }
+  }
+  qh PRINTdim= qh hull_dim;
+  if (qh DROPdim >=0) {    /* after Geomview checks */
+    if (qh DROPdim < qh hull_dim) {
+      qh PRINTdim--;
+      if (!printgeom || qh hull_dim < 3)
+        qh_fprintf(qh ferr, 7043, "qhull input warning: drop dimension 'GD%d' is only available for 3-d/4-d Geomview\n", qh DROPdim);
+    }else
+      qh DROPdim= -1;
+  }else if (qh VORONOI) {
+    qh DROPdim= qh hull_dim-1;
+    qh PRINTdim= qh hull_dim-1;
+  }
+} /* qh_initqhull_outputflags */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="initqhull_start">-</a>
+
+  qh_initqhull_start( infile, outfile, errfile )
+    allocate memory if needed and call qh_initqhull_start2()
+*/
+void qh_initqhull_start(FILE *infile, FILE *outfile, FILE *errfile) {
+
+#if qh_QHpointer
+  if (qh_qh) {
+    qh_fprintf(errfile, 6205, "qhull error (qh_initqhull_start): qh_qh already defined.  Call qh_save_qhull() first\n");
+    qh_exit(qh_ERRqhull);  /* no error handler */
+  }
+  if (!(qh_qh= (qhT *)qh_malloc(sizeof(qhT)))) {
+    qh_fprintf(errfile, 6060, "qhull error (qh_initqhull_start): insufficient memory\n");
+    qh_exit(qh_ERRmem);  /* no error handler */
+  }
+#endif
+  qh_initstatistics();
+  qh_initqhull_start2(infile, outfile, errfile);
+} /* initqhull_start */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="initqhull_start2">-</a>
+
+  qh_initqhull_start2( infile, outfile, errfile )
+    start initialization of qhull
+    initialize statistics, stdio, default values for global variables
+    assumes qh_qh is defined
+  notes:
+    report errors elsewhere, error handling and g_qhull_output [Qhull.cpp, QhullQh()] not in initialized
+  see:
+    qh_maxmin() determines the precision constants
+    qh_freeqhull2()
+*/
+void qh_initqhull_start2(FILE *infile, FILE *outfile, FILE *errfile) {
+  time_t timedata;
+  int seed;
+
+  qh_CPUclock; /* start the clock(for qh_clock).  One-shot. */
+#if qh_QHpointer
+  memset((char *)qh_qh, 0, sizeof(qhT));   /* every field is 0, FALSE, NULL */
+#else
+  memset((char *)&qh_qh, 0, sizeof(qhT));
+#endif
+  qh ANGLEmerge= True;
+  qh DROPdim= -1;
+  qh ferr= errfile;
+  qh fin= infile;
+  qh fout= outfile;
+  qh furthest_id= -1;
+  qh JOGGLEmax= REALmax;
+  qh KEEPminArea = REALmax;
+  qh last_low= REALmax;
+  qh last_high= REALmax;
+  qh last_newhigh= REALmax;
+  qh max_outside= 0.0;
+  qh max_vertex= 0.0;
+  qh MAXabs_coord= 0.0;
+  qh MAXsumcoord= 0.0;
+  qh MAXwidth= -REALmax;
+  qh MERGEindependent= True;
+  qh MINdenom_1= fmax_(1.0/REALmax, REALmin); /* used by qh_scalepoints */
+  qh MINoutside= 0.0;
+  qh MINvisible= REALmax;
+  qh MAXcoplanar= REALmax;
+  qh outside_err= REALmax;
+  qh premerge_centrum= 0.0;
+  qh premerge_cos= REALmax;
+  qh PRINTprecision= True;
+  qh PRINTradius= 0.0;
+  qh postmerge_cos= REALmax;
+  qh postmerge_centrum= 0.0;
+  qh ROTATErandom= INT_MIN;
+  qh MERGEvertices= True;
+  qh totarea= 0.0;
+  qh totvol= 0.0;
+  qh TRACEdist= REALmax;
+  qh TRACEpoint= -1; /* recompile or use 'TPn' */
+  qh tracefacet_id= UINT_MAX;  /* recompile to trace a facet */
+  qh tracevertex_id= UINT_MAX; /* recompile to trace a vertex */
+  seed= (int)time(&timedata);
+  qh_RANDOMseed_(seed);
+  qh run_id= qh_RANDOMint+1; /* disallow 0 [UsingLibQhull::NOqhRunId] */
+  qh_option("run-id", &qh run_id, NULL);
+  strcat(qh qhull, "qhull");
+} /* initqhull_start2 */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="initthresholds">-</a>
+
+  qh_initthresholds( commandString )
+    set thresholds for printing and scaling from commandString
+
+  returns:
+    sets qh.GOODthreshold or qh.SPLITthreshold if 'Pd0D1' used
+
+  see:
+    qh_initflags(), 'Qbk' 'QBk' 'Pdk' and 'PDk'
+    qh_inthresholds()
+
+  design:
+    for each 'Pdn' or 'PDn' option
+      check syntax
+      set qh.lower_threshold or qh.upper_threshold
+    set qh.GOODthreshold if an unbounded threshold is used
+    set qh.SPLITthreshold if a bounded threshold is used
+*/
+void qh_initthresholds(char *command) {
+  realT value;
+  int idx, maxdim, k;
+  char *s= command; /* non-const due to strtol */
+  char key;
+
+  maxdim= qh input_dim;
+  if (qh DELAUNAY && (qh PROJECTdelaunay || qh PROJECTinput))
+    maxdim++;
+  while (*s) {
+    if (*s == '-')
+      s++;
+    if (*s == 'P') {
+      s++;
+      while (*s && !isspace(key= *s++)) {
+        if (key == 'd' || key == 'D') {
+          if (!isdigit(*s)) {
+            qh_fprintf(qh ferr, 7044, "qhull warning: no dimension given for Print option '%c' at: %s.  Ignored\n",
+                    key, s-1);
+            continue;
+          }
+          idx= qh_strtol(s, &s);
+          if (idx >= qh hull_dim) {
+            qh_fprintf(qh ferr, 7045, "qhull warning: dimension %d for Print option '%c' is >= %d.  Ignored\n",
+                idx, key, qh hull_dim);
+            continue;
+          }
+          if (*s == ':') {
+            s++;
+            value= qh_strtod(s, &s);
+            if (fabs((double)value) > 1.0) {
+              qh_fprintf(qh ferr, 7046, "qhull warning: value %2.4g for Print option %c is > +1 or < -1.  Ignored\n",
+                      value, key);
+              continue;
+            }
+          }else
+            value= 0.0;
+          if (key == 'd')
+            qh lower_threshold[idx]= value;
+          else
+            qh upper_threshold[idx]= value;
+        }
+      }
+    }else if (*s == 'Q') {
+      s++;
+      while (*s && !isspace(key= *s++)) {
+        if (key == 'b' && *s == 'B') {
+          s++;
+          for (k=maxdim; k--; ) {
+            qh lower_bound[k]= -qh_DEFAULTbox;
+            qh upper_bound[k]= qh_DEFAULTbox;
+          }
+        }else if (key == 'b' && *s == 'b')
+          s++;
+        else if (key == 'b' || key == 'B') {
+          if (!isdigit(*s)) {
+            qh_fprintf(qh ferr, 7047, "qhull warning: no dimension given for Qhull option %c.  Ignored\n",
+                    key);
+            continue;
+          }
+          idx= qh_strtol(s, &s);
+          if (idx >= maxdim) {
+            qh_fprintf(qh ferr, 7048, "qhull warning: dimension %d for Qhull option %c is >= %d.  Ignored\n",
+                idx, key, maxdim);
+            continue;
+          }
+          if (*s == ':') {
+            s++;
+            value= qh_strtod(s, &s);
+          }else if (key == 'b')
+            value= -qh_DEFAULTbox;
+          else
+            value= qh_DEFAULTbox;
+          if (key == 'b')
+            qh lower_bound[idx]= value;
+          else
+            qh upper_bound[idx]= value;
+        }
+      }
+    }else {
+      while (*s && !isspace(*s))
+        s++;
+    }
+    while (isspace(*s))
+      s++;
+  }
+  for (k=qh hull_dim; k--; ) {
+    if (qh lower_threshold[k] > -REALmax/2) {
+      qh GOODthreshold= True;
+      if (qh upper_threshold[k] < REALmax/2) {
+        qh SPLITthresholds= True;
+        qh GOODthreshold= False;
+        break;
+      }
+    }else if (qh upper_threshold[k] < REALmax/2)
+      qh GOODthreshold= True;
+  }
+} /* initthresholds */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="option">-</a>
+
+  qh_option( option, intVal, realVal )
+    add an option description to qh.qhull_options
+
+  notes:
+    NOerrors -- qh_option can not call qh_errexit() [qh_initqhull_start2]
+    will be printed with statistics ('Ts') and errors
+    strlen(option) < 40
+*/
+void qh_option(const char *option, int *i, realT *r) {
+  char buf[200];
+  int len, maxlen;
+
+  sprintf(buf, "  %s", option);
+  if (i)
+    sprintf(buf+strlen(buf), " %d", *i);
+  if (r)
+    sprintf(buf+strlen(buf), " %2.2g", *r);
+  len= (int)strlen(buf);  /* WARN64 */
+  qh qhull_optionlen += len;
+  maxlen= sizeof(qh qhull_options) - len -1;
+  maximize_(maxlen, 0);
+  if (qh qhull_optionlen >= qh_OPTIONline && maxlen > 0) {
+    qh qhull_optionlen= len;
+    strncat(qh qhull_options, "\n", (size_t)(maxlen--));
+  }
+  strncat(qh qhull_options, buf, (size_t)maxlen);
+} /* option */
+
+#if qh_QHpointer
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="restore_qhull">-</a>
+
+  qh_restore_qhull( oldqh )
+    restores a previously saved qhull
+    also restores qh_qhstat and qhmem.tempstack
+    Sets *oldqh to NULL
+  notes:
+    errors if current qhull hasn't been saved or freed
+    uses qhmem for error reporting
+
+  NOTE 1998/5/11:
+    Freeing memory after qh_save_qhull and qh_restore_qhull
+    is complicated.  The procedures will be redesigned.
+
+  see:
+    qh_save_qhull(), UsingLibQhull
+*/
+void qh_restore_qhull(qhT **oldqh) {
+
+  if (*oldqh && strcmp((*oldqh)->qhull, "qhull")) {
+    qh_fprintf(qhmem.ferr, 6061, "qhull internal error (qh_restore_qhull): %p is not a qhull data structure\n",
+                  *oldqh);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  if (qh_qh) {
+    qh_fprintf(qhmem.ferr, 6062, "qhull internal error (qh_restore_qhull): did not save or free existing qhull\n");
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  if (!*oldqh || !(*oldqh)->old_qhstat) {
+    qh_fprintf(qhmem.ferr, 6063, "qhull internal error (qh_restore_qhull): did not previously save qhull %p\n",
+                  *oldqh);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  qh_qh= *oldqh;
+  *oldqh= NULL;
+  qh_qhstat= qh old_qhstat;
+  qhmem.tempstack= qh old_tempstack;
+  qh old_qhstat= 0;
+  qh old_tempstack= 0;
+  trace1((qh ferr, 1007, "qh_restore_qhull: restored qhull from %p\n", *oldqh));
+} /* restore_qhull */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="save_qhull">-</a>
+
+  qh_save_qhull(  )
+    saves qhull for a later qh_restore_qhull
+    also saves qh_qhstat and qhmem.tempstack
+
+  returns:
+    qh_qh=NULL
+
+  notes:
+    need to initialize qhull or call qh_restore_qhull before continuing
+
+  NOTE 1998/5/11:
+    Freeing memory after qh_save_qhull and qh_restore_qhull
+    is complicated.  The procedures will be redesigned.
+
+  see:
+    qh_restore_qhull()
+*/
+qhT *qh_save_qhull(void) {
+  qhT *oldqh;
+
+  trace1((qhmem.ferr, 1045, "qh_save_qhull: save qhull %p\n", qh_qh));
+  if (!qh_qh) {
+    qh_fprintf(qhmem.ferr, 6064, "qhull internal error (qh_save_qhull): qhull not initialized\n");
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  qh old_qhstat= qh_qhstat;
+  qh_qhstat= NULL;
+  qh old_tempstack= qhmem.tempstack;
+  qhmem.tempstack= NULL;
+  oldqh= qh_qh;
+  qh_qh= NULL;
+  return oldqh;
+} /* save_qhull */
+
+#endif
diff --git a/alg/libqhull/io.c b/alg/libqhull/io.c
new file mode 100644
index 0000000..752ab73
--- /dev/null
+++ b/alg/libqhull/io.c
@@ -0,0 +1,4060 @@
+/*<html><pre>  -<a                             href="qh-io.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   io.c
+   Input/Output routines of qhull application
+
+   see qh-io.htm and io.h
+
+   see user.c for qh_errprint and qh_printfacetlist
+
+   unix.c calls qh_readpoints and qh_produce_output
+
+   unix.c and user.c are the only callers of io.c functions
+   This allows the user to avoid loading io.o from qhull.a
+
+   Copyright (c) 1993-2012 The Geometry Center.
+   $Id: //main/2011/qhull/src/libqhull/io.c#3 $$Change: 1464 $
+   $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+*/
+
+#include "qhull_a.h"
+
+/*========= -functions in alphabetical order after qh_produce_output()  =====*/
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="produce_output">-</a>
+
+  qh_produce_output()
+  qh_produce_output2()
+    prints out the result of qhull in desired format
+    qh_produce_output2() does not call qh_prepare_output()
+    if qh.GETarea
+      computes and prints area and volume
+    qh.PRINTout[] is an array of output formats
+
+  notes:
+    prints output in qh.PRINTout order
+*/
+void qh_produce_output(void) {
+    int tempsize= qh_setsize(qhmem.tempstack);
+
+    qh_prepare_output();
+    qh_produce_output2();
+    if (qh_setsize(qhmem.tempstack) != tempsize) {
+        qh_fprintf(qh ferr, 6206, "qhull internal error (qh_produce_output): temporary sets not empty(%d)\n",
+            qh_setsize(qhmem.tempstack));
+        qh_errexit(qh_ERRqhull, NULL, NULL);
+    }
+} /* produce_output */
+
+
+void qh_produce_output2(void) {
+  int i, tempsize= qh_setsize(qhmem.tempstack), d_1;
+
+  if (qh PRINTsummary)
+    qh_printsummary(qh ferr);
+  else if (qh PRINTout[0] == qh_PRINTnone)
+    qh_printsummary(qh fout);
+  for (i=0; i < qh_PRINTEND; i++)
+    qh_printfacets(qh fout, qh PRINTout[i], qh facet_list, NULL, !qh_ALL);
+  qh_allstatistics();
+  if (qh PRINTprecision && !qh MERGING && (qh JOGGLEmax > REALmax/2 || qh RERUN))
+    qh_printstats(qh ferr, qhstat precision, NULL);
+  if (qh VERIFYoutput && (zzval_(Zridge) > 0 || zzval_(Zridgemid) > 0))
+    qh_printstats(qh ferr, qhstat vridges, NULL);
+  if (qh PRINTstatistics) {
+    qh_printstatistics(qh ferr, "");
+    qh_memstatistics(qh ferr);
+    d_1= sizeof(setT) + (qh hull_dim - 1) * SETelemsize;
+    qh_fprintf(qh ferr, 8040, "\
+    size in bytes: merge %d ridge %d vertex %d facet %d\n\
+         normal %d ridge vertices %d facet vertices or neighbors %d\n",
+            (int)sizeof(mergeT), (int)sizeof(ridgeT),
+            (int)sizeof(vertexT), (int)sizeof(facetT),
+            qh normal_size, d_1, d_1 + SETelemsize);
+  }
+  if (qh_setsize(qhmem.tempstack) != tempsize) {
+    qh_fprintf(qh ferr, 6065, "qhull internal error (qh_produce_output2): temporary sets not empty(%d)\n",
+             qh_setsize(qhmem.tempstack));
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+} /* produce_output2 */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="dfacet">-</a>
+
+  dfacet( id )
+    print facet by id, for debugging
+
+*/
+void dfacet(unsigned id) {
+  facetT *facet;
+
+  FORALLfacets {
+    if (facet->id == id) {
+      qh_printfacet(qh fout, facet);
+      break;
+    }
+  }
+} /* dfacet */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="dvertex">-</a>
+
+  dvertex( id )
+    print vertex by id, for debugging
+*/
+void dvertex(unsigned id) {
+  vertexT *vertex;
+
+  FORALLvertices {
+    if (vertex->id == id) {
+      qh_printvertex(qh fout, vertex);
+      break;
+    }
+  }
+} /* dvertex */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="compare_vertexpoint">-</a>
+
+  qh_compare_vertexpoint( p1, p2 )
+    used by qsort() to order vertices by point id
+*/
+int qh_compare_vertexpoint(const void *p1, const void *p2) {
+  const vertexT *a= *((vertexT *const*)p1), *b= *((vertexT *const*)p2);
+
+  return((qh_pointid(a->point) > qh_pointid(b->point)?1:-1));
+} /* compare_vertexpoint */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="compare_facetarea">-</a>
+
+  qh_compare_facetarea( p1, p2 )
+    used by qsort() to order facets by area
+*/
+int qh_compare_facetarea(const void *p1, const void *p2) {
+  const facetT *a= *((facetT *const*)p1), *b= *((facetT *const*)p2);
+
+  if (!a->isarea)
+    return -1;
+  if (!b->isarea)
+    return 1;
+  if (a->f.area > b->f.area)
+    return 1;
+  else if (a->f.area == b->f.area)
+    return 0;
+  return -1;
+} /* compare_facetarea */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="compare_facetmerge">-</a>
+
+  qh_compare_facetmerge( p1, p2 )
+    used by qsort() to order facets by number of merges
+*/
+int qh_compare_facetmerge(const void *p1, const void *p2) {
+  const facetT *a= *((facetT *const*)p1), *b= *((facetT *const*)p2);
+
+  return(a->nummerge - b->nummerge);
+} /* compare_facetvisit */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="compare_facetvisit">-</a>
+
+  qh_compare_facetvisit( p1, p2 )
+    used by qsort() to order facets by visit id or id
+*/
+int qh_compare_facetvisit(const void *p1, const void *p2) {
+  const facetT *a= *((facetT *const*)p1), *b= *((facetT *const*)p2);
+  int i,j;
+
+  if (!(i= a->visitid))
+    i= 0 - a->id; /* do not convert to int, sign distinguishes id from visitid */
+  if (!(j= b->visitid))
+    j= 0 - b->id;
+  return(i - j);
+} /* compare_facetvisit */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="copyfilename">-</a>
+
+  qh_copyfilename( dest, size, source, length )
+    copy filename identified by qh_skipfilename()
+
+  notes:
+    see qh_skipfilename() for syntax
+*/
+void qh_copyfilename(char *filename, int size, const char* source, int length) {
+  char c= *source;
+
+  if (length > size + 1) {
+      qh_fprintf(qh ferr, 6040, "qhull error: filename is more than %d characters, %s\n",  size-1, source);
+      qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  strncpy(filename, source, length);
+  filename[length]= '\0';
+  if (c == '\'' || c == '"') {
+    char *s= filename + 1;
+    char *t= filename;
+    while (*s) {
+      if (*s == c) {
+          if (s[-1] == '\\')
+              t[-1]= c;
+      }else
+          *t++= *s;
+      s++;
+    }
+    *t= '\0';
+  }
+} /* copyfilename */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="countfacets">-</a>
+
+  qh_countfacets( facetlist, facets, printall,
+          numfacets, numsimplicial, totneighbors, numridges, numcoplanar, numtricoplanars  )
+    count good facets for printing and set visitid
+    if allfacets, ignores qh_skipfacet()
+
+  notes:
+    qh_printsummary and qh_countfacets must match counts
+
+  returns:
+    numfacets, numsimplicial, total neighbors, numridges, coplanars
+    each facet with ->visitid indicating 1-relative position
+      ->visitid==0 indicates not good
+
+  notes
+    numfacets >= numsimplicial
+    if qh.NEWfacets,
+      does not count visible facets (matches qh_printafacet)
+
+  design:
+    for all facets on facetlist and in facets set
+      unless facet is skipped or visible (i.e., will be deleted)
+        mark facet->visitid
+        update counts
+*/
+void qh_countfacets(facetT *facetlist, setT *facets, boolT printall,
+    int *numfacetsp, int *numsimplicialp, int *totneighborsp, int *numridgesp, int *numcoplanarsp, int *numtricoplanarsp) {
+  facetT *facet, **facetp;
+  int numfacets= 0, numsimplicial= 0, numridges= 0, totneighbors= 0, numcoplanars= 0, numtricoplanars= 0;
+
+  FORALLfacet_(facetlist) {
+    if ((facet->visible && qh NEWfacets)
+    || (!printall && qh_skipfacet(facet)))
+      facet->visitid= 0;
+    else {
+      facet->visitid= ++numfacets;
+      totneighbors += qh_setsize(facet->neighbors);
+      if (facet->simplicial) {
+        numsimplicial++;
+        if (facet->keepcentrum && facet->tricoplanar)
+          numtricoplanars++;
+      }else
+        numridges += qh_setsize(facet->ridges);
+      if (facet->coplanarset)
+        numcoplanars += qh_setsize(facet->coplanarset);
+    }
+  }
+
+  FOREACHfacet_(facets) {
+    if ((facet->visible && qh NEWfacets)
+    || (!printall && qh_skipfacet(facet)))
+      facet->visitid= 0;
+    else {
+      facet->visitid= ++numfacets;
+      totneighbors += qh_setsize(facet->neighbors);
+      if (facet->simplicial){
+        numsimplicial++;
+        if (facet->keepcentrum && facet->tricoplanar)
+          numtricoplanars++;
+      }else
+        numridges += qh_setsize(facet->ridges);
+      if (facet->coplanarset)
+        numcoplanars += qh_setsize(facet->coplanarset);
+    }
+  }
+  qh visit_id += numfacets+1;
+  *numfacetsp= numfacets;
+  *numsimplicialp= numsimplicial;
+  *totneighborsp= totneighbors;
+  *numridgesp= numridges;
+  *numcoplanarsp= numcoplanars;
+  *numtricoplanarsp= numtricoplanars;
+} /* countfacets */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="detvnorm">-</a>
+
+  qh_detvnorm( vertex, vertexA, centers, offset )
+    compute separating plane of the Voronoi diagram for a pair of input sites
+    centers= set of facets (i.e., Voronoi vertices)
+      facet->visitid= 0 iff vertex-at-infinity (i.e., unbounded)
+
+  assumes:
+    qh_ASvoronoi and qh_vertexneighbors() already set
+
+  returns:
+    norm
+      a pointer into qh.gm_matrix to qh.hull_dim-1 reals
+      copy the data before reusing qh.gm_matrix
+    offset
+      if 'QVn'
+        sign adjusted so that qh.GOODvertexp is inside
+      else
+        sign adjusted so that vertex is inside
+
+    qh.gm_matrix= simplex of points from centers relative to first center
+
+  notes:
+    in io.c so that code for 'v Tv' can be removed by removing io.c
+    returns pointer into qh.gm_matrix to avoid tracking of temporary memory
+
+  design:
+    determine midpoint of input sites
+    build points as the set of Voronoi vertices
+    select a simplex from points (if necessary)
+      include midpoint if the Voronoi region is unbounded
+    relocate the first vertex of the simplex to the origin
+    compute the normalized hyperplane through the simplex
+    orient the hyperplane toward 'QVn' or 'vertex'
+    if 'Tv' or 'Ts'
+      if bounded
+        test that hyperplane is the perpendicular bisector of the input sites
+      test that Voronoi vertices not in the simplex are still on the hyperplane
+    free up temporary memory
+*/
+pointT *qh_detvnorm(vertexT *vertex, vertexT *vertexA, setT *centers, realT *offsetp) {
+  facetT *facet, **facetp;
+  int  i, k, pointid, pointidA, point_i, point_n;
+  setT *simplex= NULL;
+  pointT *point, **pointp, *point0, *midpoint, *normal, *inpoint;
+  coordT *coord, *gmcoord, *normalp;
+  setT *points= qh_settemp(qh TEMPsize);
+  boolT nearzero= False;
+  boolT unbounded= False;
+  int numcenters= 0;
+  int dim= qh hull_dim - 1;
+  realT dist, offset, angle, zero= 0.0;
+
+  midpoint= qh gm_matrix + qh hull_dim * qh hull_dim;  /* last row */
+  for (k=0; k < dim; k++)
+    midpoint[k]= (vertex->point[k] + vertexA->point[k])/2;
+  FOREACHfacet_(centers) {
+    numcenters++;
+    if (!facet->visitid)
+      unbounded= True;
+    else {
+      if (!facet->center)
+        facet->center= qh_facetcenter(facet->vertices);
+      qh_setappend(&points, facet->center);
+    }
+  }
+  if (numcenters > dim) {
+    simplex= qh_settemp(qh TEMPsize);
+    qh_setappend(&simplex, vertex->point);
+    if (unbounded)
+      qh_setappend(&simplex, midpoint);
+    qh_maxsimplex(dim, points, NULL, 0, &simplex);
+    qh_setdelnth(simplex, 0);
+  }else if (numcenters == dim) {
+    if (unbounded)
+      qh_setappend(&points, midpoint);
+    simplex= points;
+  }else {
+    qh_fprintf(qh ferr, 6216, "qhull internal error (qh_detvnorm): too few points(%d) to compute separating plane\n", numcenters);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  i= 0;
+  gmcoord= qh gm_matrix;
+  point0= SETfirstt_(simplex, pointT);
+  FOREACHpoint_(simplex) {
+    if (qh IStracing >= 4)
+      qh_printmatrix(qh ferr, "qh_detvnorm: Voronoi vertex or midpoint",
+                              &point, 1, dim);
+    if (point != point0) {
+      qh gm_row[i++]= gmcoord;
+      coord= point0;
+      for (k=dim; k--; )
+        *(gmcoord++)= *point++ - *coord++;
+    }
+  }
+  qh gm_row[i]= gmcoord;  /* does not overlap midpoint, may be used later for qh_areasimplex */
+  normal= gmcoord;
+  qh_sethyperplane_gauss(dim, qh gm_row, point0, True,
+                normal, &offset, &nearzero);
+  if (qh GOODvertexp == vertexA->point)
+    inpoint= vertexA->point;
+  else
+    inpoint= vertex->point;
+  zinc_(Zdistio);
+  dist= qh_distnorm(dim, inpoint, normal, &offset);
+  if (dist > 0) {
+    offset= -offset;
+    normalp= normal;
+    for (k=dim; k--; ) {
+      *normalp= -(*normalp);
+      normalp++;
+    }
+  }
+  if (qh VERIFYoutput || qh PRINTstatistics) {
+    pointid= qh_pointid(vertex->point);
+    pointidA= qh_pointid(vertexA->point);
+    if (!unbounded) {
+      zinc_(Zdiststat);
+      dist= qh_distnorm(dim, midpoint, normal, &offset);
+      if (dist < 0)
+        dist= -dist;
+      zzinc_(Zridgemid);
+      wwmax_(Wridgemidmax, dist);
+      wwadd_(Wridgemid, dist);
+      trace4((qh ferr, 4014, "qh_detvnorm: points %d %d midpoint dist %2.2g\n",
+                 pointid, pointidA, dist));
+      for (k=0; k < dim; k++)
+        midpoint[k]= vertexA->point[k] - vertex->point[k];  /* overwrites midpoint! */
+      qh_normalize(midpoint, dim, False);
+      angle= qh_distnorm(dim, midpoint, normal, &zero); /* qh_detangle uses dim+1 */
+      if (angle < 0.0)
+        angle= angle + 1.0;
+      else
+        angle= angle - 1.0;
+      if (angle < 0.0)
+        angle -= angle;
+      trace4((qh ferr, 4015, "qh_detvnorm: points %d %d angle %2.2g nearzero %d\n",
+                 pointid, pointidA, angle, nearzero));
+      if (nearzero) {
+        zzinc_(Zridge0);
+        wwmax_(Wridge0max, angle);
+        wwadd_(Wridge0, angle);
+      }else {
+        zzinc_(Zridgeok)
+        wwmax_(Wridgeokmax, angle);
+        wwadd_(Wridgeok, angle);
+      }
+    }
+    if (simplex != points) {
+      FOREACHpoint_i_(points) {
+        if (!qh_setin(simplex, point)) {
+          facet= SETelemt_(centers, point_i, facetT);
+          zinc_(Zdiststat);
+          dist= qh_distnorm(dim, point, normal, &offset);
+          if (dist < 0)
+            dist= -dist;
+          zzinc_(Zridge);
+          wwmax_(Wridgemax, dist);
+          wwadd_(Wridge, dist);
+          trace4((qh ferr, 4016, "qh_detvnorm: points %d %d Voronoi vertex %d dist %2.2g\n",
+                             pointid, pointidA, facet->visitid, dist));
+        }
+      }
+    }
+  }
+  *offsetp= offset;
+  if (simplex != points)
+    qh_settempfree(&simplex);
+  qh_settempfree(&points);
+  return normal;
+} /* detvnorm */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="detvridge">-</a>
+
+  qh_detvridge( vertexA )
+    determine Voronoi ridge from 'seen' neighbors of vertexA
+    include one vertex-at-infinite if an !neighbor->visitid
+
+  returns:
+    temporary set of centers (facets, i.e., Voronoi vertices)
+    sorted by center id
+*/
+setT *qh_detvridge(vertexT *vertex) {
+  setT *centers= qh_settemp(qh TEMPsize);
+  setT *tricenters= qh_settemp(qh TEMPsize);
+  facetT *neighbor, **neighborp;
+  boolT firstinf= True;
+
+  FOREACHneighbor_(vertex) {
+    if (neighbor->seen) {
+      if (neighbor->visitid) {
+        if (!neighbor->tricoplanar || qh_setunique(&tricenters, neighbor->center))
+          qh_setappend(&centers, neighbor);
+      }else if (firstinf) {
+        firstinf= False;
+        qh_setappend(&centers, neighbor);
+      }
+    }
+  }
+  qsort(SETaddr_(centers, facetT), (size_t)qh_setsize(centers),
+             sizeof(facetT *), qh_compare_facetvisit);
+  qh_settempfree(&tricenters);
+  return centers;
+} /* detvridge */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="detvridge3">-</a>
+
+  qh_detvridge3( atvertex, vertex )
+    determine 3-d Voronoi ridge from 'seen' neighbors of atvertex and vertex
+    include one vertex-at-infinite for !neighbor->visitid
+    assumes all facet->seen2= True
+
+  returns:
+    temporary set of centers (facets, i.e., Voronoi vertices)
+    listed in adjacency order (!oriented)
+    all facet->seen2= True
+
+  design:
+    mark all neighbors of atvertex
+    for each adjacent neighbor of both atvertex and vertex
+      if neighbor selected
+        add neighbor to set of Voronoi vertices
+*/
+setT *qh_detvridge3 (vertexT *atvertex, vertexT *vertex) {
+  setT *centers= qh_settemp(qh TEMPsize);
+  setT *tricenters= qh_settemp(qh TEMPsize);
+  facetT *neighbor, **neighborp, *facet= NULL;
+  boolT firstinf= True;
+
+  FOREACHneighbor_(atvertex)
+    neighbor->seen2= False;
+  FOREACHneighbor_(vertex) {
+    if (!neighbor->seen2) {
+      facet= neighbor;
+      break;
+    }
+  }
+  while (facet) {
+    facet->seen2= True;
+    if (neighbor->seen) {
+      if (facet->visitid) {
+        if (!facet->tricoplanar || qh_setunique(&tricenters, facet->center))
+          qh_setappend(&centers, facet);
+      }else if (firstinf) {
+        firstinf= False;
+        qh_setappend(&centers, facet);
+      }
+    }
+    FOREACHneighbor_(facet) {
+      if (!neighbor->seen2) {
+        if (qh_setin(vertex->neighbors, neighbor))
+          break;
+        else
+          neighbor->seen2= True;
+      }
+    }
+    facet= neighbor;
+  }
+  if (qh CHECKfrequently) {
+    FOREACHneighbor_(vertex) {
+      if (!neighbor->seen2) {
+          qh_fprintf(qh ferr, 6217, "qhull internal error (qh_detvridge3): neighbors of vertex p%d are not connected at facet %d\n",
+                 qh_pointid(vertex->point), neighbor->id);
+        qh_errexit(qh_ERRqhull, neighbor, NULL);
+      }
+    }
+  }
+  FOREACHneighbor_(atvertex)
+    neighbor->seen2= True;
+  qh_settempfree(&tricenters);
+  return centers;
+} /* detvridge3 */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="eachvoronoi">-</a>
+
+  qh_eachvoronoi( fp, printvridge, vertex, visitall, innerouter, inorder )
+    if visitall,
+      visit all Voronoi ridges for vertex (i.e., an input site)
+    else
+      visit all unvisited Voronoi ridges for vertex
+      all vertex->seen= False if unvisited
+    assumes
+      all facet->seen= False
+      all facet->seen2= True (for qh_detvridge3)
+      all facet->visitid == 0 if vertex_at_infinity
+                         == index of Voronoi vertex
+                         >= qh.num_facets if ignored
+    innerouter:
+      qh_RIDGEall--  both inner (bounded) and outer(unbounded) ridges
+      qh_RIDGEinner- only inner
+      qh_RIDGEouter- only outer
+
+    if inorder
+      orders vertices for 3-d Voronoi diagrams
+
+  returns:
+    number of visited ridges (does not include previously visited ridges)
+
+    if printvridge,
+      calls printvridge( fp, vertex, vertexA, centers)
+        fp== any pointer (assumes FILE*)
+        vertex,vertexA= pair of input sites that define a Voronoi ridge
+        centers= set of facets (i.e., Voronoi vertices)
+                 ->visitid == index or 0 if vertex_at_infinity
+                 ordered for 3-d Voronoi diagram
+  notes:
+    uses qh.vertex_visit
+
+  see:
+    qh_eachvoronoi_all()
+
+  design:
+    mark selected neighbors of atvertex
+    for each selected neighbor (either Voronoi vertex or vertex-at-infinity)
+      for each unvisited vertex
+        if atvertex and vertex share more than d-1 neighbors
+          bump totalcount
+          if printvridge defined
+            build the set of shared neighbors (i.e., Voronoi vertices)
+            call printvridge
+*/
+int qh_eachvoronoi(FILE *fp, printvridgeT printvridge, vertexT *atvertex, boolT visitall, qh_RIDGE innerouter, boolT inorder) {
+  boolT unbounded;
+  int count;
+  facetT *neighbor, **neighborp, *neighborA, **neighborAp;
+  setT *centers;
+  setT *tricenters= qh_settemp(qh TEMPsize);
+
+  vertexT *vertex, **vertexp;
+  boolT firstinf;
+  unsigned int numfacets= (unsigned int)qh num_facets;
+  int totridges= 0;
+
+  qh vertex_visit++;
+  atvertex->seen= True;
+  if (visitall) {
+    FORALLvertices
+      vertex->seen= False;
+  }
+  FOREACHneighbor_(atvertex) {
+    if (neighbor->visitid < numfacets)
+      neighbor->seen= True;
+  }
+  FOREACHneighbor_(atvertex) {
+    if (neighbor->seen) {
+      FOREACHvertex_(neighbor->vertices) {
+        if (vertex->visitid != qh vertex_visit && !vertex->seen) {
+          vertex->visitid= qh vertex_visit;
+          count= 0;
+          firstinf= True;
+          qh_settruncate(tricenters, 0);
+          FOREACHneighborA_(vertex) {
+            if (neighborA->seen) {
+              if (neighborA->visitid) {
+                if (!neighborA->tricoplanar || qh_setunique(&tricenters, neighborA->center))
+                  count++;
+              }else if (firstinf) {
+                count++;
+                firstinf= False;
+              }
+            }
+          }
+          if (count >= qh hull_dim - 1) {  /* e.g., 3 for 3-d Voronoi */
+            if (firstinf) {
+              if (innerouter == qh_RIDGEouter)
+                continue;
+              unbounded= False;
+            }else {
+              if (innerouter == qh_RIDGEinner)
+                continue;
+              unbounded= True;
+            }
+            totridges++;
+            trace4((qh ferr, 4017, "qh_eachvoronoi: Voronoi ridge of %d vertices between sites %d and %d\n",
+                  count, qh_pointid(atvertex->point), qh_pointid(vertex->point)));
+            if (printvridge && fp) {
+              if (inorder && qh hull_dim == 3+1) /* 3-d Voronoi diagram */
+                centers= qh_detvridge3 (atvertex, vertex);
+              else
+                centers= qh_detvridge(vertex);
+              (*printvridge) (fp, atvertex, vertex, centers, unbounded);
+              qh_settempfree(&centers);
+            }
+          }
+        }
+      }
+    }
+  }
+  FOREACHneighbor_(atvertex)
+    neighbor->seen= False;
+  qh_settempfree(&tricenters);
+  return totridges;
+} /* eachvoronoi */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="eachvoronoi_all">-</a>
+
+  qh_eachvoronoi_all( fp, printvridge, isUpper, innerouter, inorder )
+    visit all Voronoi ridges
+
+    innerouter:
+      see qh_eachvoronoi()
+
+    if inorder
+      orders vertices for 3-d Voronoi diagrams
+
+  returns
+    total number of ridges
+
+    if isUpper == facet->upperdelaunay  (i.e., a Vornoi vertex)
+      facet->visitid= Voronoi vertex index(same as 'o' format)
+    else
+      facet->visitid= 0
+
+    if printvridge,
+      calls printvridge( fp, vertex, vertexA, centers)
+      [see qh_eachvoronoi]
+
+  notes:
+    Not used for qhull.exe
+    same effect as qh_printvdiagram but ridges not sorted by point id
+*/
+int qh_eachvoronoi_all(FILE *fp, printvridgeT printvridge, boolT isUpper, qh_RIDGE innerouter, boolT inorder) {
+  facetT *facet;
+  vertexT *vertex;
+  int numcenters= 1;  /* vertex 0 is vertex-at-infinity */
+  int totridges= 0;
+
+  qh_clearcenters(qh_ASvoronoi);
+  qh_vertexneighbors();
+  maximize_(qh visit_id, (unsigned) qh num_facets);
+  FORALLfacets {
+    facet->visitid= 0;
+    facet->seen= False;
+    facet->seen2= True;
+  }
+  FORALLfacets {
+    if (facet->upperdelaunay == isUpper)
+      facet->visitid= numcenters++;
+  }
+  FORALLvertices
+    vertex->seen= False;
+  FORALLvertices {
+    if (qh GOODvertex > 0 && qh_pointid(vertex->point)+1 != qh GOODvertex)
+      continue;
+    totridges += qh_eachvoronoi(fp, printvridge, vertex,
+                   !qh_ALL, innerouter, inorder);
+  }
+  return totridges;
+} /* eachvoronoi_all */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="facet2point">-</a>
+
+  qh_facet2point( facet, point0, point1, mindist )
+    return two projected temporary vertices for a 2-d facet
+    may be non-simplicial
+
+  returns:
+    point0 and point1 oriented and projected to the facet
+    returns mindist (maximum distance below plane)
+*/
+void qh_facet2point(facetT *facet, pointT **point0, pointT **point1, realT *mindist) {
+  vertexT *vertex0, *vertex1;
+  realT dist;
+
+  if (facet->toporient ^ qh_ORIENTclock) {
+    vertex0= SETfirstt_(facet->vertices, vertexT);
+    vertex1= SETsecondt_(facet->vertices, vertexT);
+  }else {
+    vertex1= SETfirstt_(facet->vertices, vertexT);
+    vertex0= SETsecondt_(facet->vertices, vertexT);
+  }
+  zadd_(Zdistio, 2);
+  qh_distplane(vertex0->point, facet, &dist);
+  *mindist= dist;
+  *point0= qh_projectpoint(vertex0->point, facet, dist);
+  qh_distplane(vertex1->point, facet, &dist);
+  minimize_(*mindist, dist);
+  *point1= qh_projectpoint(vertex1->point, facet, dist);
+} /* facet2point */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="facetvertices">-</a>
+
+  qh_facetvertices( facetlist, facets, allfacets )
+    returns temporary set of vertices in a set and/or list of facets
+    if allfacets, ignores qh_skipfacet()
+
+  returns:
+    vertices with qh.vertex_visit
+
+  notes:
+    optimized for allfacets of facet_list
+
+  design:
+    if allfacets of facet_list
+      create vertex set from vertex_list
+    else
+      for each selected facet in facets or facetlist
+        append unvisited vertices to vertex set
+*/
+setT *qh_facetvertices(facetT *facetlist, setT *facets, boolT allfacets) {
+  setT *vertices;
+  facetT *facet, **facetp;
+  vertexT *vertex, **vertexp;
+
+  qh vertex_visit++;
+  if (facetlist == qh facet_list && allfacets && !facets) {
+    vertices= qh_settemp(qh num_vertices);
+    FORALLvertices {
+      vertex->visitid= qh vertex_visit;
+      qh_setappend(&vertices, vertex);
+    }
+  }else {
+    vertices= qh_settemp(qh TEMPsize);
+    FORALLfacet_(facetlist) {
+      if (!allfacets && qh_skipfacet(facet))
+        continue;
+      FOREACHvertex_(facet->vertices) {
+        if (vertex->visitid != qh vertex_visit) {
+          vertex->visitid= qh vertex_visit;
+          qh_setappend(&vertices, vertex);
+        }
+      }
+    }
+  }
+  FOREACHfacet_(facets) {
+    if (!allfacets && qh_skipfacet(facet))
+      continue;
+    FOREACHvertex_(facet->vertices) {
+      if (vertex->visitid != qh vertex_visit) {
+        vertex->visitid= qh vertex_visit;
+        qh_setappend(&vertices, vertex);
+      }
+    }
+  }
+  return vertices;
+} /* facetvertices */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="geomplanes">-</a>
+
+  qh_geomplanes( facet, outerplane, innerplane )
+    return outer and inner planes for Geomview
+    qh.PRINTradius is size of vertices and points (includes qh.JOGGLEmax)
+
+  notes:
+    assume precise calculations in io.c with roundoff covered by qh_GEOMepsilon
+*/
+void qh_geomplanes(facetT *facet, realT *outerplane, realT *innerplane) {
+  realT radius;
+
+  if (qh MERGING || qh JOGGLEmax < REALmax/2) {
+    qh_outerinner(facet, outerplane, innerplane);
+    radius= qh PRINTradius;
+    if (qh JOGGLEmax < REALmax/2)
+      radius -= qh JOGGLEmax * sqrt((realT)qh hull_dim);  /* already accounted for in qh_outerinner() */
+    *outerplane += radius;
+    *innerplane -= radius;
+    if (qh PRINTcoplanar || qh PRINTspheres) {
+      *outerplane += qh MAXabs_coord * qh_GEOMepsilon;
+      *innerplane -= qh MAXabs_coord * qh_GEOMepsilon;
+    }
+  }else
+    *innerplane= *outerplane= 0;
+} /* geomplanes */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="markkeep">-</a>
+
+  qh_markkeep( facetlist )
+    mark good facets that meet qh.KEEParea, qh.KEEPmerge, and qh.KEEPminArea
+    ignores visible facets (!part of convex hull)
+
+  returns:
+    may clear facet->good
+    recomputes qh.num_good
+
+  design:
+    get set of good facets
+    if qh.KEEParea
+      sort facets by area
+      clear facet->good for all but n largest facets
+    if qh.KEEPmerge
+      sort facets by merge count
+      clear facet->good for all but n most merged facets
+    if qh.KEEPminarea
+      clear facet->good if area too small
+    update qh.num_good
+*/
+void qh_markkeep(facetT *facetlist) {
+  facetT *facet, **facetp;
+  setT *facets= qh_settemp(qh num_facets);
+  int size, count;
+
+  trace2((qh ferr, 2006, "qh_markkeep: only keep %d largest and/or %d most merged facets and/or min area %.2g\n",
+          qh KEEParea, qh KEEPmerge, qh KEEPminArea));
+  FORALLfacet_(facetlist) {
+    if (!facet->visible && facet->good)
+      qh_setappend(&facets, facet);
+  }
+  size= qh_setsize(facets);
+  if (qh KEEParea) {
+    qsort(SETaddr_(facets, facetT), (size_t)size,
+             sizeof(facetT *), qh_compare_facetarea);
+    if ((count= size - qh KEEParea) > 0) {
+      FOREACHfacet_(facets) {
+        facet->good= False;
+        if (--count == 0)
+          break;
+      }
+    }
+  }
+  if (qh KEEPmerge) {
+    qsort(SETaddr_(facets, facetT), (size_t)size,
+             sizeof(facetT *), qh_compare_facetmerge);
+    if ((count= size - qh KEEPmerge) > 0) {
+      FOREACHfacet_(facets) {
+        facet->good= False;
+        if (--count == 0)
+          break;
+      }
+    }
+  }
+  if (qh KEEPminArea < REALmax/2) {
+    FOREACHfacet_(facets) {
+      if (!facet->isarea || facet->f.area < qh KEEPminArea)
+        facet->good= False;
+    }
+  }
+  qh_settempfree(&facets);
+  count= 0;
+  FORALLfacet_(facetlist) {
+    if (facet->good)
+      count++;
+  }
+  qh num_good= count;
+} /* markkeep */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="markvoronoi">-</a>
+
+  qh_markvoronoi( facetlist, facets, printall, isLower, numcenters )
+    mark voronoi vertices for printing by site pairs
+
+  returns:
+    temporary set of vertices indexed by pointid
+    isLower set if printing lower hull (i.e., at least one facet is lower hull)
+    numcenters= total number of Voronoi vertices
+    bumps qh.printoutnum for vertex-at-infinity
+    clears all facet->seen and sets facet->seen2
+
+    if selected
+      facet->visitid= Voronoi vertex id
+    else if upper hull (or 'Qu' and lower hull)
+      facet->visitid= 0
+    else
+      facet->visitid >= qh num_facets
+
+  notes:
+    ignores qh.ATinfinity, if defined
+*/
+setT *qh_markvoronoi(facetT *facetlist, setT *facets, boolT printall, boolT *isLowerp, int *numcentersp) {
+  int numcenters=0;
+  facetT *facet, **facetp;
+  setT *vertices;
+  boolT isLower= False;
+
+  qh printoutnum++;
+  qh_clearcenters(qh_ASvoronoi);  /* in case, qh_printvdiagram2 called by user */
+  qh_vertexneighbors();
+  vertices= qh_pointvertex();
+  if (qh ATinfinity)
+    SETelem_(vertices, qh num_points-1)= NULL;
+  qh visit_id++;
+  maximize_(qh visit_id, (unsigned) qh num_facets);
+  FORALLfacet_(facetlist) {
+    if (printall || !qh_skipfacet(facet)) {
+      if (!facet->upperdelaunay) {
+        isLower= True;
+        break;
+      }
+    }
+  }
+  FOREACHfacet_(facets) {
+    if (printall || !qh_skipfacet(facet)) {
+      if (!facet->upperdelaunay) {
+        isLower= True;
+        break;
+      }
+    }
+  }
+  FORALLfacets {
+    if (facet->normal && (facet->upperdelaunay == isLower))
+      facet->visitid= 0;  /* facetlist or facets may overwrite */
+    else
+      facet->visitid= qh visit_id;
+    facet->seen= False;
+    facet->seen2= True;
+  }
+  numcenters++;  /* qh_INFINITE */
+  FORALLfacet_(facetlist) {
+    if (printall || !qh_skipfacet(facet))
+      facet->visitid= numcenters++;
+  }
+  FOREACHfacet_(facets) {
+    if (printall || !qh_skipfacet(facet))
+      facet->visitid= numcenters++;
+  }
+  *isLowerp= isLower;
+  *numcentersp= numcenters;
+  trace2((qh ferr, 2007, "qh_markvoronoi: isLower %d numcenters %d\n", isLower, numcenters));
+  return vertices;
+} /* markvoronoi */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="order_vertexneighbors">-</a>
+
+  qh_order_vertexneighbors( vertex )
+    order facet neighbors of a 2-d or 3-d vertex by adjacency
+
+  notes:
+    does not orient the neighbors
+
+  design:
+    initialize a new neighbor set with the first facet in vertex->neighbors
+    while vertex->neighbors non-empty
+      select next neighbor in the previous facet's neighbor set
+    set vertex->neighbors to the new neighbor set
+*/
+void qh_order_vertexneighbors(vertexT *vertex) {
+  setT *newset;
+  facetT *facet, *neighbor, **neighborp;
+
+  trace4((qh ferr, 4018, "qh_order_vertexneighbors: order neighbors of v%d for 3-d\n", vertex->id));
+  newset= qh_settemp(qh_setsize(vertex->neighbors));
+  facet= (facetT*)qh_setdellast(vertex->neighbors);
+  qh_setappend(&newset, facet);
+  while (qh_setsize(vertex->neighbors)) {
+    FOREACHneighbor_(vertex) {
+      if (qh_setin(facet->neighbors, neighbor)) {
+        qh_setdel(vertex->neighbors, neighbor);
+        qh_setappend(&newset, neighbor);
+        facet= neighbor;
+        break;
+      }
+    }
+    if (!neighbor) {
+      qh_fprintf(qh ferr, 6066, "qhull internal error (qh_order_vertexneighbors): no neighbor of v%d for f%d\n",
+        vertex->id, facet->id);
+      qh_errexit(qh_ERRqhull, facet, NULL);
+    }
+  }
+  qh_setfree(&vertex->neighbors);
+  qh_settemppop();
+  vertex->neighbors= newset;
+} /* order_vertexneighbors */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="prepare_output">-</a>
+
+  qh_prepare_output( )
+    prepare for qh_produce_output2() according to
+      qh.KEEPminArea, KEEParea, KEEPmerge, GOODvertex, GOODthreshold, GOODpoint, ONLYgood, SPLITthresholds
+    does not reset facet->good
+
+  notes
+    except for PRINTstatistics, no-op if previously called with same options
+*/
+void qh_prepare_output(void) {
+  if (qh VORONOI) {
+    qh_clearcenters (qh_ASvoronoi);
+    qh_vertexneighbors();
+  }
+  if (qh TRIangulate && !qh hasTriangulation) {
+    qh_triangulate();
+    if (qh VERIFYoutput && !qh CHECKfrequently)
+      qh_checkpolygon (qh facet_list);
+  }
+  qh_findgood_all (qh facet_list);
+  if (qh GETarea)
+    qh_getarea(qh facet_list);
+  if (qh KEEParea || qh KEEPmerge || qh KEEPminArea < REALmax/2)
+    qh_markkeep (qh facet_list);
+  if (qh PRINTstatistics)
+    qh_collectstatistics();
+}
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printafacet">-</a>
+
+  qh_printafacet( fp, format, facet, printall )
+    print facet to fp in given output format (see qh.PRINTout)
+
+  returns:
+    nop if !printall and qh_skipfacet()
+    nop if visible facet and NEWfacets and format != PRINTfacets
+    must match qh_countfacets
+
+  notes
+    preserves qh.visit_id
+    facet->normal may be null if PREmerge/MERGEexact and STOPcone before merge
+
+  see
+    qh_printbegin() and qh_printend()
+
+  design:
+    test for printing facet
+    call appropriate routine for format
+    or output results directly
+*/
+void qh_printafacet(FILE *fp, qh_PRINT format, facetT *facet, boolT printall) {
+  realT color[4], offset, dist, outerplane, innerplane;
+  boolT zerodiv;
+  coordT *point, *normp, *coordp, **pointp, *feasiblep;
+  int k;
+  vertexT *vertex, **vertexp;
+  facetT *neighbor, **neighborp;
+
+  if (!printall && qh_skipfacet(facet))
+    return;
+  if (facet->visible && qh NEWfacets && format != qh_PRINTfacets)
+    return;
+  qh printoutnum++;
+  switch (format) {
+  case qh_PRINTarea:
+    if (facet->isarea) {
+      qh_fprintf(fp, 9009, qh_REAL_1, facet->f.area);
+      qh_fprintf(fp, 9010, "\n");
+    }else
+      qh_fprintf(fp, 9011, "0\n");
+    break;
+  case qh_PRINTcoplanars:
+    qh_fprintf(fp, 9012, "%d", qh_setsize(facet->coplanarset));
+    FOREACHpoint_(facet->coplanarset)
+      qh_fprintf(fp, 9013, " %d", qh_pointid(point));
+    qh_fprintf(fp, 9014, "\n");
+    break;
+  case qh_PRINTcentrums:
+    qh_printcenter(fp, format, NULL, facet);
+    break;
+  case qh_PRINTfacets:
+    qh_printfacet(fp, facet);
+    break;
+  case qh_PRINTfacets_xridge:
+    qh_printfacetheader(fp, facet);
+    break;
+  case qh_PRINTgeom:  /* either 2 , 3, or 4-d by qh_printbegin */
+    if (!facet->normal)
+      break;
+    for (k=qh hull_dim; k--; ) {
+      color[k]= (facet->normal[k]+1.0)/2.0;
+      maximize_(color[k], -1.0);
+      minimize_(color[k], +1.0);
+    }
+    qh_projectdim3 (color, color);
+    if (qh PRINTdim != qh hull_dim)
+      qh_normalize2 (color, 3, True, NULL, NULL);
+    if (qh hull_dim <= 2)
+      qh_printfacet2geom(fp, facet, color);
+    else if (qh hull_dim == 3) {
+      if (facet->simplicial)
+        qh_printfacet3geom_simplicial(fp, facet, color);
+      else
+        qh_printfacet3geom_nonsimplicial(fp, facet, color);
+    }else {
+      if (facet->simplicial)
+        qh_printfacet4geom_simplicial(fp, facet, color);
+      else
+        qh_printfacet4geom_nonsimplicial(fp, facet, color);
+    }
+    break;
+  case qh_PRINTids:
+    qh_fprintf(fp, 9015, "%d\n", facet->id);
+    break;
+  case qh_PRINTincidences:
+  case qh_PRINToff:
+  case qh_PRINTtriangles:
+    if (qh hull_dim == 3 && format != qh_PRINTtriangles)
+      qh_printfacet3vertex(fp, facet, format);
+    else if (facet->simplicial || qh hull_dim == 2 || format == qh_PRINToff)
+      qh_printfacetNvertex_simplicial(fp, facet, format);
+    else
+      qh_printfacetNvertex_nonsimplicial(fp, facet, qh printoutvar++, format);
+    break;
+  case qh_PRINTinner:
+    qh_outerinner(facet, NULL, &innerplane);
+    offset= facet->offset - innerplane;
+    goto LABELprintnorm;
+    break; /* prevent warning */
+  case qh_PRINTmerges:
+    qh_fprintf(fp, 9016, "%d\n", facet->nummerge);
+    break;
+  case qh_PRINTnormals:
+    offset= facet->offset;
+    goto LABELprintnorm;
+    break; /* prevent warning */
+  case qh_PRINTouter:
+    qh_outerinner(facet, &outerplane, NULL);
+    offset= facet->offset - outerplane;
+  LABELprintnorm:
+    if (!facet->normal) {
+      qh_fprintf(fp, 9017, "no normal for facet f%d\n", facet->id);
+      break;
+    }
+    if (qh CDDoutput) {
+      qh_fprintf(fp, 9018, qh_REAL_1, -offset);
+      for (k=0; k < qh hull_dim; k++)
+        qh_fprintf(fp, 9019, qh_REAL_1, -facet->normal[k]);
+    }else {
+      for (k=0; k < qh hull_dim; k++)
+        qh_fprintf(fp, 9020, qh_REAL_1, facet->normal[k]);
+      qh_fprintf(fp, 9021, qh_REAL_1, offset);
+    }
+    qh_fprintf(fp, 9022, "\n");
+    break;
+  case qh_PRINTmathematica:  /* either 2 or 3-d by qh_printbegin */
+  case qh_PRINTmaple:
+    if (qh hull_dim == 2)
+      qh_printfacet2math(fp, facet, format, qh printoutvar++);
+    else
+      qh_printfacet3math(fp, facet, format, qh printoutvar++);
+    break;
+  case qh_PRINTneighbors:
+    qh_fprintf(fp, 9023, "%d", qh_setsize(facet->neighbors));
+    FOREACHneighbor_(facet)
+      qh_fprintf(fp, 9024, " %d",
+               neighbor->visitid ? neighbor->visitid - 1: 0 - neighbor->id);
+    qh_fprintf(fp, 9025, "\n");
+    break;
+  case qh_PRINTpointintersect:
+    if (!qh feasible_point) {
+      qh_fprintf(qh ferr, 6067, "qhull input error (qh_printafacet): option 'Fp' needs qh feasible_point\n");
+      qh_errexit( qh_ERRinput, NULL, NULL);
+    }
+    if (facet->offset > 0)
+      goto LABELprintinfinite;
+    point= coordp= (coordT*)qh_memalloc(qh normal_size);
+    normp= facet->normal;
+    feasiblep= qh feasible_point;
+    if (facet->offset < -qh MINdenom) {
+      for (k=qh hull_dim; k--; )
+        *(coordp++)= (*(normp++) / - facet->offset) + *(feasiblep++);
+    }else {
+      for (k=qh hull_dim; k--; ) {
+        *(coordp++)= qh_divzero(*(normp++), facet->offset, qh MINdenom_1,
+                                 &zerodiv) + *(feasiblep++);
+        if (zerodiv) {
+          qh_memfree(point, qh normal_size);
+          goto LABELprintinfinite;
+        }
+      }
+    }
+    qh_printpoint(fp, NULL, point);
+    qh_memfree(point, qh normal_size);
+    break;
+  LABELprintinfinite:
+    for (k=qh hull_dim; k--; )
+      qh_fprintf(fp, 9026, qh_REAL_1, qh_INFINITE);
+    qh_fprintf(fp, 9027, "\n");
+    break;
+  case qh_PRINTpointnearest:
+    FOREACHpoint_(facet->coplanarset) {
+      int id, id2;
+      vertex= qh_nearvertex(facet, point, &dist);
+      id= qh_pointid(vertex->point);
+      id2= qh_pointid(point);
+      qh_fprintf(fp, 9028, "%d %d %d " qh_REAL_1 "\n", id, id2, facet->id, dist);
+    }
+    break;
+  case qh_PRINTpoints:  /* VORONOI only by qh_printbegin */
+    if (qh CDDoutput)
+      qh_fprintf(fp, 9029, "1 ");
+    qh_printcenter(fp, format, NULL, facet);
+    break;
+  case qh_PRINTvertices:
+    qh_fprintf(fp, 9030, "%d", qh_setsize(facet->vertices));
+    FOREACHvertex_(facet->vertices)
+      qh_fprintf(fp, 9031, " %d", qh_pointid(vertex->point));
+    qh_fprintf(fp, 9032, "\n");
+    break;
+  default:
+    break;
+  }
+} /* printafacet */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printbegin">-</a>
+
+  qh_printbegin(  )
+    prints header for all output formats
+
+  returns:
+    checks for valid format
+
+  notes:
+    uses qh.visit_id for 3/4off
+    changes qh.interior_point if printing centrums
+    qh_countfacets clears facet->visitid for non-good facets
+
+  see
+    qh_printend() and qh_printafacet()
+
+  design:
+    count facets and related statistics
+    print header for format
+*/
+void qh_printbegin(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
+  int numfacets, numsimplicial, numridges, totneighbors, numcoplanars, numtricoplanars;
+  int i, num;
+  facetT *facet, **facetp;
+  vertexT *vertex, **vertexp;
+  setT *vertices;
+  pointT *point, **pointp, *pointtemp;
+
+  qh printoutnum= 0;
+  qh_countfacets(facetlist, facets, printall, &numfacets, &numsimplicial,
+      &totneighbors, &numridges, &numcoplanars, &numtricoplanars);
+  switch (format) {
+  case qh_PRINTnone:
+    break;
+  case qh_PRINTarea:
+    qh_fprintf(fp, 9033, "%d\n", numfacets);
+    break;
+  case qh_PRINTcoplanars:
+    qh_fprintf(fp, 9034, "%d\n", numfacets);
+    break;
+  case qh_PRINTcentrums:
+    if (qh CENTERtype == qh_ASnone)
+      qh_clearcenters(qh_AScentrum);
+    qh_fprintf(fp, 9035, "%d\n%d\n", qh hull_dim, numfacets);
+    break;
+  case qh_PRINTfacets:
+  case qh_PRINTfacets_xridge:
+    if (facetlist)
+      qh_printvertexlist(fp, "Vertices and facets:\n", facetlist, facets, printall);
+    break;
+  case qh_PRINTgeom:
+    if (qh hull_dim > 4)  /* qh_initqhull_globals also checks */
+      goto LABELnoformat;
+    if (qh VORONOI && qh hull_dim > 3)  /* PRINTdim == DROPdim == hull_dim-1 */
+      goto LABELnoformat;
+    if (qh hull_dim == 2 && (qh PRINTridges || qh DOintersections))
+      qh_fprintf(qh ferr, 7049, "qhull warning: output for ridges and intersections not implemented in 2-d\n");
+    if (qh hull_dim == 4 && (qh PRINTinner || qh PRINTouter ||
+                             (qh PRINTdim == 4 && qh PRINTcentrums)))
+      qh_fprintf(qh ferr, 7050, "qhull warning: output for outer/inner planes and centrums not implemented in 4-d\n");
+    if (qh PRINTdim == 4 && (qh PRINTspheres))
+      qh_fprintf(qh ferr, 7051, "qhull warning: output for vertices not implemented in 4-d\n");
+    if (qh PRINTdim == 4 && qh DOintersections && qh PRINTnoplanes)
+      qh_fprintf(qh ferr, 7052, "qhull warning: 'Gnh' generates no output in 4-d\n");
+    if (qh PRINTdim == 2) {
+      qh_fprintf(fp, 9036, "{appearance {linewidth 3} LIST # %s | %s\n",
+              qh rbox_command, qh qhull_command);
+    }else if (qh PRINTdim == 3) {
+      qh_fprintf(fp, 9037, "{appearance {+edge -evert linewidth 2} LIST # %s | %s\n",
+              qh rbox_command, qh qhull_command);
+    }else if (qh PRINTdim == 4) {
+      qh visit_id++;
+      num= 0;
+      FORALLfacet_(facetlist)    /* get number of ridges to be printed */
+        qh_printend4geom(NULL, facet, &num, printall);
+      FOREACHfacet_(facets)
+        qh_printend4geom(NULL, facet, &num, printall);
+      qh ridgeoutnum= num;
+      qh printoutvar= 0;  /* counts number of ridges in output */
+      qh_fprintf(fp, 9038, "LIST # %s | %s\n", qh rbox_command, qh qhull_command);
+    }
+
+    if (qh PRINTdots) {
+      qh printoutnum++;
+      num= qh num_points + qh_setsize(qh other_points);
+      if (qh DELAUNAY && qh ATinfinity)
+        num--;
+      if (qh PRINTdim == 4)
+        qh_fprintf(fp, 9039, "4VECT %d %d 1\n", num, num);
+      else
+        qh_fprintf(fp, 9040, "VECT %d %d 1\n", num, num);
+
+      for (i=num; i--; ) {
+        if (i % 20 == 0)
+          qh_fprintf(fp, 9041, "\n");
+        qh_fprintf(fp, 9042, "1 ");
+      }
+      qh_fprintf(fp, 9043, "# 1 point per line\n1 ");
+      for (i=num-1; i--; ) { /* num at least 3 for D2 */
+        if (i % 20 == 0)
+          qh_fprintf(fp, 9044, "\n");
+        qh_fprintf(fp, 9045, "0 ");
+      }
+      qh_fprintf(fp, 9046, "# 1 color for all\n");
+      FORALLpoints {
+        if (!qh DELAUNAY || !qh ATinfinity || qh_pointid(point) != qh num_points-1) {
+          if (qh PRINTdim == 4)
+            qh_printpoint(fp, NULL, point);
+            else
+              qh_printpoint3 (fp, point);
+        }
+      }
+      FOREACHpoint_(qh other_points) {
+        if (qh PRINTdim == 4)
+          qh_printpoint(fp, NULL, point);
+        else
+          qh_printpoint3 (fp, point);
+      }
+      qh_fprintf(fp, 9047, "0 1 1 1  # color of points\n");
+    }
+
+    if (qh PRINTdim == 4  && !qh PRINTnoplanes)
+      /* 4dview loads up multiple 4OFF objects slowly */
+      qh_fprintf(fp, 9048, "4OFF %d %d 1\n", 3*qh ridgeoutnum, qh ridgeoutnum);
+    qh PRINTcradius= 2 * qh DISTround;  /* include test DISTround */
+    if (qh PREmerge) {
+      maximize_(qh PRINTcradius, qh premerge_centrum + qh DISTround);
+    }else if (qh POSTmerge)
+      maximize_(qh PRINTcradius, qh postmerge_centrum + qh DISTround);
+    qh PRINTradius= qh PRINTcradius;
+    if (qh PRINTspheres + qh PRINTcoplanar)
+      maximize_(qh PRINTradius, qh MAXabs_coord * qh_MINradius);
+    if (qh premerge_cos < REALmax/2) {
+      maximize_(qh PRINTradius, (1- qh premerge_cos) * qh MAXabs_coord);
+    }else if (!qh PREmerge && qh POSTmerge && qh postmerge_cos < REALmax/2) {
+      maximize_(qh PRINTradius, (1- qh postmerge_cos) * qh MAXabs_coord);
+    }
+    maximize_(qh PRINTradius, qh MINvisible);
+    if (qh JOGGLEmax < REALmax/2)
+      qh PRINTradius += qh JOGGLEmax * sqrt((realT)qh hull_dim);
+    if (qh PRINTdim != 4 &&
+        (qh PRINTcoplanar || qh PRINTspheres || qh PRINTcentrums)) {
+      vertices= qh_facetvertices(facetlist, facets, printall);
+      if (qh PRINTspheres && qh PRINTdim <= 3)
+        qh_printspheres(fp, vertices, qh PRINTradius);
+      if (qh PRINTcoplanar || qh PRINTcentrums) {
+        qh firstcentrum= True;
+        if (qh PRINTcoplanar&& !qh PRINTspheres) {
+          FOREACHvertex_(vertices)
+            qh_printpointvect2 (fp, vertex->point, NULL, qh interior_point, qh PRINTradius);
+        }
+        FORALLfacet_(facetlist) {
+          if (!printall && qh_skipfacet(facet))
+            continue;
+          if (!facet->normal)
+            continue;
+          if (qh PRINTcentrums && qh PRINTdim <= 3)
+            qh_printcentrum(fp, facet, qh PRINTcradius);
+          if (!qh PRINTcoplanar)
+            continue;
+          FOREACHpoint_(facet->coplanarset)
+            qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius);
+          FOREACHpoint_(facet->outsideset)
+            qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius);
+        }
+        FOREACHfacet_(facets) {
+          if (!printall && qh_skipfacet(facet))
+            continue;
+          if (!facet->normal)
+            continue;
+          if (qh PRINTcentrums && qh PRINTdim <= 3)
+            qh_printcentrum(fp, facet, qh PRINTcradius);
+          if (!qh PRINTcoplanar)
+            continue;
+          FOREACHpoint_(facet->coplanarset)
+            qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius);
+          FOREACHpoint_(facet->outsideset)
+            qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius);
+        }
+      }
+      qh_settempfree(&vertices);
+    }
+    qh visit_id++; /* for printing hyperplane intersections */
+    break;
+  case qh_PRINTids:
+    qh_fprintf(fp, 9049, "%d\n", numfacets);
+    break;
+  case qh_PRINTincidences:
+    if (qh VORONOI && qh PRINTprecision)
+      qh_fprintf(qh ferr, 7053, "qhull warning: writing Delaunay.  Use 'p' or 'o' for Voronoi centers\n");
+    qh printoutvar= qh vertex_id;  /* centrum id for non-simplicial facets */
+    if (qh hull_dim <= 3)
+      qh_fprintf(fp, 9050, "%d\n", numfacets);
+    else
+      qh_fprintf(fp, 9051, "%d\n", numsimplicial+numridges);
+    break;
+  case qh_PRINTinner:
+  case qh_PRINTnormals:
+  case qh_PRINTouter:
+    if (qh CDDoutput)
+      qh_fprintf(fp, 9052, "%s | %s\nbegin\n    %d %d real\n", qh rbox_command,
+            qh qhull_command, numfacets, qh hull_dim+1);
+    else
+      qh_fprintf(fp, 9053, "%d\n%d\n", qh hull_dim+1, numfacets);
+    break;
+  case qh_PRINTmathematica:
+  case qh_PRINTmaple:
+    if (qh hull_dim > 3)  /* qh_initbuffers also checks */
+      goto LABELnoformat;
+    if (qh VORONOI)
+      qh_fprintf(qh ferr, 7054, "qhull warning: output is the Delaunay triangulation\n");
+    if (format == qh_PRINTmaple) {
+      if (qh hull_dim == 2)
+        qh_fprintf(fp, 9054, "PLOT(CURVES(\n");
+      else
+        qh_fprintf(fp, 9055, "PLOT3D(POLYGONS(\n");
+    }else
+      qh_fprintf(fp, 9056, "{\n");
+    qh printoutvar= 0;   /* counts number of facets for notfirst */
+    break;
+  case qh_PRINTmerges:
+    qh_fprintf(fp, 9057, "%d\n", numfacets);
+    break;
+  case qh_PRINTpointintersect:
+    qh_fprintf(fp, 9058, "%d\n%d\n", qh hull_dim, numfacets);
+    break;
+  case qh_PRINTneighbors:
+    qh_fprintf(fp, 9059, "%d\n", numfacets);
+    break;
+  case qh_PRINToff:
+  case qh_PRINTtriangles:
+    if (qh VORONOI)
+      goto LABELnoformat;
+    num = qh hull_dim;
+    if (format == qh_PRINToff || qh hull_dim == 2)
+      qh_fprintf(fp, 9060, "%d\n%d %d %d\n", num,
+        qh num_points+qh_setsize(qh other_points), numfacets, totneighbors/2);
+    else { /* qh_PRINTtriangles */
+      qh printoutvar= qh num_points+qh_setsize(qh other_points); /* first centrum */
+      if (qh DELAUNAY)
+        num--;  /* drop last dimension */
+      qh_fprintf(fp, 9061, "%d\n%d %d %d\n", num, qh printoutvar
+        + numfacets - numsimplicial, numsimplicial + numridges, totneighbors/2);
+    }
+    FORALLpoints
+      qh_printpointid(qh fout, NULL, num, point, -1);
+    FOREACHpoint_(qh other_points)
+      qh_printpointid(qh fout, NULL, num, point, -1);
+    if (format == qh_PRINTtriangles && qh hull_dim > 2) {
+      FORALLfacets {
+        if (!facet->simplicial && facet->visitid)
+          qh_printcenter(qh fout, format, NULL, facet);
+      }
+    }
+    break;
+  case qh_PRINTpointnearest:
+    qh_fprintf(fp, 9062, "%d\n", numcoplanars);
+    break;
+  case qh_PRINTpoints:
+    if (!qh VORONOI)
+      goto LABELnoformat;
+    if (qh CDDoutput)
+      qh_fprintf(fp, 9063, "%s | %s\nbegin\n%d %d real\n", qh rbox_command,
+           qh qhull_command, numfacets, qh hull_dim);
+    else
+      qh_fprintf(fp, 9064, "%d\n%d\n", qh hull_dim-1, numfacets);
+    break;
+  case qh_PRINTvertices:
+    qh_fprintf(fp, 9065, "%d\n", numfacets);
+    break;
+  case qh_PRINTsummary:
+  default:
+  LABELnoformat:
+    qh_fprintf(qh ferr, 6068, "qhull internal error (qh_printbegin): can not use this format for dimension %d\n",
+         qh hull_dim);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+} /* printbegin */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printcenter">-</a>
+
+  qh_printcenter( fp, string, facet )
+    print facet->center as centrum or Voronoi center
+    string may be NULL.  Don't include '%' codes.
+    nop if qh CENTERtype neither CENTERvoronoi nor CENTERcentrum
+    if upper envelope of Delaunay triangulation and point at-infinity
+      prints qh_INFINITE instead;
+
+  notes:
+    defines facet->center if needed
+    if format=PRINTgeom, adds a 0 if would otherwise be 2-d
+    Same as QhullFacet::printCenter
+*/
+void qh_printcenter(FILE *fp, qh_PRINT format, const char *string, facetT *facet) {
+  int k, num;
+
+  if (qh CENTERtype != qh_ASvoronoi && qh CENTERtype != qh_AScentrum)
+    return;
+  if (string)
+    qh_fprintf(fp, 9066, string);
+  if (qh CENTERtype == qh_ASvoronoi) {
+    num= qh hull_dim-1;
+    if (!facet->normal || !facet->upperdelaunay || !qh ATinfinity) {
+      if (!facet->center)
+        facet->center= qh_facetcenter(facet->vertices);
+      for (k=0; k < num; k++)
+        qh_fprintf(fp, 9067, qh_REAL_1, facet->center[k]);
+    }else {
+      for (k=0; k < num; k++)
+        qh_fprintf(fp, 9068, qh_REAL_1, qh_INFINITE);
+    }
+  }else /* qh CENTERtype == qh_AScentrum */ {
+    num= qh hull_dim;
+    if (format == qh_PRINTtriangles && qh DELAUNAY)
+      num--;
+    if (!facet->center)
+      facet->center= qh_getcentrum(facet);
+    for (k=0; k < num; k++)
+      qh_fprintf(fp, 9069, qh_REAL_1, facet->center[k]);
+  }
+  if (format == qh_PRINTgeom && num == 2)
+    qh_fprintf(fp, 9070, " 0\n");
+  else
+    qh_fprintf(fp, 9071, "\n");
+} /* printcenter */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printcentrum">-</a>
+
+  qh_printcentrum( fp, facet, radius )
+    print centrum for a facet in OOGL format
+    radius defines size of centrum
+    2-d or 3-d only
+
+  returns:
+    defines facet->center if needed
+*/
+void qh_printcentrum(FILE *fp, facetT *facet, realT radius) {
+  pointT *centrum, *projpt;
+  boolT tempcentrum= False;
+  realT xaxis[4], yaxis[4], normal[4], dist;
+  realT green[3]={0, 1, 0};
+  vertexT *apex;
+  int k;
+
+  if (qh CENTERtype == qh_AScentrum) {
+    if (!facet->center)
+      facet->center= qh_getcentrum(facet);
+    centrum= facet->center;
+  }else {
+    centrum= qh_getcentrum(facet);
+    tempcentrum= True;
+  }
+  qh_fprintf(fp, 9072, "{appearance {-normal -edge normscale 0} ");
+  if (qh firstcentrum) {
+    qh firstcentrum= False;
+    qh_fprintf(fp, 9073, "{INST geom { define centrum CQUAD  # f%d\n\
+-0.3 -0.3 0.0001     0 0 1 1\n\
+ 0.3 -0.3 0.0001     0 0 1 1\n\
+ 0.3  0.3 0.0001     0 0 1 1\n\
+-0.3  0.3 0.0001     0 0 1 1 } transform { \n", facet->id);
+  }else
+    qh_fprintf(fp, 9074, "{INST geom { : centrum } transform { # f%d\n", facet->id);
+  apex= SETfirstt_(facet->vertices, vertexT);
+  qh_distplane(apex->point, facet, &dist);
+  projpt= qh_projectpoint(apex->point, facet, dist);
+  for (k=qh hull_dim; k--; ) {
+    xaxis[k]= projpt[k] - centrum[k];
+    normal[k]= facet->normal[k];
+  }
+  if (qh hull_dim == 2) {
+    xaxis[2]= 0;
+    normal[2]= 0;
+  }else if (qh hull_dim == 4) {
+    qh_projectdim3 (xaxis, xaxis);
+    qh_projectdim3 (normal, normal);
+    qh_normalize2 (normal, qh PRINTdim, True, NULL, NULL);
+  }
+  qh_crossproduct(3, xaxis, normal, yaxis);
+  qh_fprintf(fp, 9075, "%8.4g %8.4g %8.4g 0\n", xaxis[0], xaxis[1], xaxis[2]);
+  qh_fprintf(fp, 9076, "%8.4g %8.4g %8.4g 0\n", yaxis[0], yaxis[1], yaxis[2]);
+  qh_fprintf(fp, 9077, "%8.4g %8.4g %8.4g 0\n", normal[0], normal[1], normal[2]);
+  qh_printpoint3 (fp, centrum);
+  qh_fprintf(fp, 9078, "1 }}}\n");
+  qh_memfree(projpt, qh normal_size);
+  qh_printpointvect(fp, centrum, facet->normal, NULL, radius, green);
+  if (tempcentrum)
+    qh_memfree(centrum, qh normal_size);
+} /* printcentrum */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printend">-</a>
+
+  qh_printend( fp, format )
+    prints trailer for all output formats
+
+  see:
+    qh_printbegin() and qh_printafacet()
+
+*/
+void qh_printend(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
+  int num;
+  facetT *facet, **facetp;
+
+  if (!qh printoutnum)
+    qh_fprintf(qh ferr, 7055, "qhull warning: no facets printed\n");
+  switch (format) {
+  case qh_PRINTgeom:
+    if (qh hull_dim == 4 && qh DROPdim < 0  && !qh PRINTnoplanes) {
+      qh visit_id++;
+      num= 0;
+      FORALLfacet_(facetlist)
+        qh_printend4geom(fp, facet,&num, printall);
+      FOREACHfacet_(facets)
+        qh_printend4geom(fp, facet, &num, printall);
+      if (num != qh ridgeoutnum || qh printoutvar != qh ridgeoutnum) {
+        qh_fprintf(qh ferr, 6069, "qhull internal error (qh_printend): number of ridges %d != number printed %d and at end %d\n", qh ridgeoutnum, qh printoutvar, num);
+        qh_errexit(qh_ERRqhull, NULL, NULL);
+      }
+    }else
+      qh_fprintf(fp, 9079, "}\n");
+    break;
+  case qh_PRINTinner:
+  case qh_PRINTnormals:
+  case qh_PRINTouter:
+    if (qh CDDoutput)
+      qh_fprintf(fp, 9080, "end\n");
+    break;
+  case qh_PRINTmaple:
+    qh_fprintf(fp, 9081, "));\n");
+    break;
+  case qh_PRINTmathematica:
+    qh_fprintf(fp, 9082, "}\n");
+    break;
+  case qh_PRINTpoints:
+    if (qh CDDoutput)
+      qh_fprintf(fp, 9083, "end\n");
+    break;
+  default:
+    break;
+  }
+} /* printend */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printend4geom">-</a>
+
+  qh_printend4geom( fp, facet, numridges, printall )
+    helper function for qh_printbegin/printend
+
+  returns:
+    number of printed ridges
+
+  notes:
+    just counts printed ridges if fp=NULL
+    uses facet->visitid
+    must agree with qh_printfacet4geom...
+
+  design:
+    computes color for facet from its normal
+    prints each ridge of facet
+*/
+void qh_printend4geom(FILE *fp, facetT *facet, int *nump, boolT printall) {
+  realT color[3];
+  int i, num= *nump;
+  facetT *neighbor, **neighborp;
+  ridgeT *ridge, **ridgep;
+
+  if (!printall && qh_skipfacet(facet))
+    return;
+  if (qh PRINTnoplanes || (facet->visible && qh NEWfacets))
+    return;
+  if (!facet->normal)
+    return;
+  if (fp) {
+    for (i=0; i < 3; i++) {
+      color[i]= (facet->normal[i]+1.0)/2.0;
+      maximize_(color[i], -1.0);
+      minimize_(color[i], +1.0);
+    }
+  }
+  facet->visitid= qh visit_id;
+  if (facet->simplicial) {
+    FOREACHneighbor_(facet) {
+      if (neighbor->visitid != qh visit_id) {
+        if (fp)
+          qh_fprintf(fp, 9084, "3 %d %d %d %8.4g %8.4g %8.4g 1 # f%d f%d\n",
+                 3*num, 3*num+1, 3*num+2, color[0], color[1], color[2],
+                 facet->id, neighbor->id);
+        num++;
+      }
+    }
+  }else {
+    FOREACHridge_(facet->ridges) {
+      neighbor= otherfacet_(ridge, facet);
+      if (neighbor->visitid != qh visit_id) {
+        if (fp)
+          qh_fprintf(fp, 9085, "3 %d %d %d %8.4g %8.4g %8.4g 1 #r%d f%d f%d\n",
+                 3*num, 3*num+1, 3*num+2, color[0], color[1], color[2],
+                 ridge->id, facet->id, neighbor->id);
+        num++;
+      }
+    }
+  }
+  *nump= num;
+} /* printend4geom */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printextremes">-</a>
+
+  qh_printextremes( fp, facetlist, facets, printall )
+    print extreme points for convex hulls or halfspace intersections
+
+  notes:
+    #points, followed by ids, one per line
+
+    sorted by id
+    same order as qh_printpoints_out if no coplanar/interior points
+*/
+void qh_printextremes(FILE *fp, facetT *facetlist, setT *facets, boolT printall) {
+  setT *vertices, *points;
+  pointT *point;
+  vertexT *vertex, **vertexp;
+  int id;
+  int numpoints=0, point_i, point_n;
+  int allpoints= qh num_points + qh_setsize(qh other_points);
+
+  points= qh_settemp(allpoints);
+  qh_setzero(points, 0, allpoints);
+  vertices= qh_facetvertices(facetlist, facets, printall);
+  FOREACHvertex_(vertices) {
+    id= qh_pointid(vertex->point);
+    if (id >= 0) {
+      SETelem_(points, id)= vertex->point;
+      numpoints++;
+    }
+  }
+  qh_settempfree(&vertices);
+  qh_fprintf(fp, 9086, "%d\n", numpoints);
+  FOREACHpoint_i_(points) {
+    if (point)
+      qh_fprintf(fp, 9087, "%d\n", point_i);
+  }
+  qh_settempfree(&points);
+} /* printextremes */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printextremes_2d">-</a>
+
+  qh_printextremes_2d( fp, facetlist, facets, printall )
+    prints point ids for facets in qh_ORIENTclock order
+
+  notes:
+    #points, followed by ids, one per line
+    if facetlist/facets are disjoint than the output includes skips
+    errors if facets form a loop
+    does not print coplanar points
+*/
+void qh_printextremes_2d(FILE *fp, facetT *facetlist, setT *facets, boolT printall) {
+  int numfacets, numridges, totneighbors, numcoplanars, numsimplicial, numtricoplanars;
+  setT *vertices;
+  facetT *facet, *startfacet, *nextfacet;
+  vertexT *vertexA, *vertexB;
+
+  qh_countfacets(facetlist, facets, printall, &numfacets, &numsimplicial,
+      &totneighbors, &numridges, &numcoplanars, &numtricoplanars); /* marks qh visit_id */
+  vertices= qh_facetvertices(facetlist, facets, printall);
+  qh_fprintf(fp, 9088, "%d\n", qh_setsize(vertices));
+  qh_settempfree(&vertices);
+  if (!numfacets)
+    return;
+  facet= startfacet= facetlist ? facetlist : SETfirstt_(facets, facetT);
+  qh vertex_visit++;
+  qh visit_id++;
+  do {
+    if (facet->toporient ^ qh_ORIENTclock) {
+      vertexA= SETfirstt_(facet->vertices, vertexT);
+      vertexB= SETsecondt_(facet->vertices, vertexT);
+      nextfacet= SETfirstt_(facet->neighbors, facetT);
+    }else {
+      vertexA= SETsecondt_(facet->vertices, vertexT);
+      vertexB= SETfirstt_(facet->vertices, vertexT);
+      nextfacet= SETsecondt_(facet->neighbors, facetT);
+    }
+    if (facet->visitid == qh visit_id) {
+      qh_fprintf(qh ferr, 6218, "Qhull internal error (qh_printextremes_2d): loop in facet list.  facet %d nextfacet %d\n",
+                 facet->id, nextfacet->id);
+      qh_errexit2 (qh_ERRqhull, facet, nextfacet);
+    }
+    if (facet->visitid) {
+      if (vertexA->visitid != qh vertex_visit) {
+        vertexA->visitid= qh vertex_visit;
+        qh_fprintf(fp, 9089, "%d\n", qh_pointid(vertexA->point));
+      }
+      if (vertexB->visitid != qh vertex_visit) {
+        vertexB->visitid= qh vertex_visit;
+        qh_fprintf(fp, 9090, "%d\n", qh_pointid(vertexB->point));
+      }
+    }
+    facet->visitid= qh visit_id;
+    facet= nextfacet;
+  }while (facet && facet != startfacet);
+} /* printextremes_2d */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printextremes_d">-</a>
+
+  qh_printextremes_d( fp, facetlist, facets, printall )
+    print extreme points of input sites for Delaunay triangulations
+
+  notes:
+    #points, followed by ids, one per line
+
+    unordered
+*/
+void qh_printextremes_d(FILE *fp, facetT *facetlist, setT *facets, boolT printall) {
+  setT *vertices;
+  vertexT *vertex, **vertexp;
+  boolT upperseen, lowerseen;
+  facetT *neighbor, **neighborp;
+  int numpoints=0;
+
+  vertices= qh_facetvertices(facetlist, facets, printall);
+  qh_vertexneighbors();
+  FOREACHvertex_(vertices) {
+    upperseen= lowerseen= False;
+    FOREACHneighbor_(vertex) {
+      if (neighbor->upperdelaunay)
+        upperseen= True;
+      else
+        lowerseen= True;
+    }
+    if (upperseen && lowerseen) {
+      vertex->seen= True;
+      numpoints++;
+    }else
+      vertex->seen= False;
+  }
+  qh_fprintf(fp, 9091, "%d\n", numpoints);
+  FOREACHvertex_(vertices) {
+    if (vertex->seen)
+      qh_fprintf(fp, 9092, "%d\n", qh_pointid(vertex->point));
+  }
+  qh_settempfree(&vertices);
+} /* printextremes_d */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacet">-</a>
+
+  qh_printfacet( fp, facet )
+    prints all fields of a facet to fp
+
+  notes:
+    ridges printed in neighbor order
+*/
+void qh_printfacet(FILE *fp, facetT *facet) {
+
+  qh_printfacetheader(fp, facet);
+  if (facet->ridges)
+    qh_printfacetridges(fp, facet);
+} /* printfacet */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacet2geom">-</a>
+
+  qh_printfacet2geom( fp, facet, color )
+    print facet as part of a 2-d VECT for Geomview
+
+    notes:
+      assume precise calculations in io.c with roundoff covered by qh_GEOMepsilon
+      mindist is calculated within io.c.  maxoutside is calculated elsewhere,
+      so a DISTround error may have occurred.
+*/
+void qh_printfacet2geom(FILE *fp, facetT *facet, realT color[3]) {
+  pointT *point0, *point1;
+  realT mindist, innerplane, outerplane;
+  int k;
+
+  qh_facet2point(facet, &point0, &point1, &mindist);
+  qh_geomplanes(facet, &outerplane, &innerplane);
+  if (qh PRINTouter || (!qh PRINTnoplanes && !qh PRINTinner))
+    qh_printfacet2geom_points(fp, point0, point1, facet, outerplane, color);
+  if (qh PRINTinner || (!qh PRINTnoplanes && !qh PRINTouter &&
+                outerplane - innerplane > 2 * qh MAXabs_coord * qh_GEOMepsilon)) {
+    for (k=3; k--; )
+      color[k]= 1.0 - color[k];
+    qh_printfacet2geom_points(fp, point0, point1, facet, innerplane, color);
+  }
+  qh_memfree(point1, qh normal_size);
+  qh_memfree(point0, qh normal_size);
+} /* printfacet2geom */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacet2geom_points">-</a>
+
+  qh_printfacet2geom_points( fp, point1, point2, facet, offset, color )
+    prints a 2-d facet as a VECT with 2 points at some offset.
+    The points are on the facet's plane.
+*/
+void qh_printfacet2geom_points(FILE *fp, pointT *point1, pointT *point2,
+                               facetT *facet, realT offset, realT color[3]) {
+  pointT *p1= point1, *p2= point2;
+
+  qh_fprintf(fp, 9093, "VECT 1 2 1 2 1 # f%d\n", facet->id);
+  if (offset != 0.0) {
+    p1= qh_projectpoint(p1, facet, -offset);
+    p2= qh_projectpoint(p2, facet, -offset);
+  }
+  qh_fprintf(fp, 9094, "%8.4g %8.4g %8.4g\n%8.4g %8.4g %8.4g\n",
+           p1[0], p1[1], 0.0, p2[0], p2[1], 0.0);
+  if (offset != 0.0) {
+    qh_memfree(p1, qh normal_size);
+    qh_memfree(p2, qh normal_size);
+  }
+  qh_fprintf(fp, 9095, "%8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]);
+} /* printfacet2geom_points */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacet2math">-</a>
+
+  qh_printfacet2math( fp, facet, format, notfirst )
+    print 2-d Maple or Mathematica output for a facet
+    may be non-simplicial
+
+  notes:
+    use %16.8f since Mathematica 2.2 does not handle exponential format
+    see qh_printfacet3math
+*/
+void qh_printfacet2math(FILE *fp, facetT *facet, qh_PRINT format, int notfirst) {
+  pointT *point0, *point1;
+  realT mindist;
+  const char *pointfmt;
+
+  qh_facet2point(facet, &point0, &point1, &mindist);
+  if (notfirst)
+    qh_fprintf(fp, 9096, ",");
+  if (format == qh_PRINTmaple)
+    pointfmt= "[[%16.8f, %16.8f], [%16.8f, %16.8f]]\n";
+  else
+    pointfmt= "Line[{{%16.8f, %16.8f}, {%16.8f, %16.8f}}]\n";
+  qh_fprintf(fp, 9097, pointfmt, point0[0], point0[1], point1[0], point1[1]);
+  qh_memfree(point1, qh normal_size);
+  qh_memfree(point0, qh normal_size);
+} /* printfacet2math */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacet3geom_nonsimplicial">-</a>
+
+  qh_printfacet3geom_nonsimplicial( fp, facet, color )
+    print Geomview OFF for a 3-d nonsimplicial facet.
+    if DOintersections, prints ridges to unvisited neighbors(qh visit_id)
+
+  notes
+    uses facet->visitid for intersections and ridges
+*/
+void qh_printfacet3geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]) {
+  ridgeT *ridge, **ridgep;
+  setT *projectedpoints, *vertices;
+  vertexT *vertex, **vertexp, *vertexA, *vertexB;
+  pointT *projpt, *point, **pointp;
+  facetT *neighbor;
+  realT dist, outerplane, innerplane;
+  int cntvertices, k;
+  realT black[3]={0, 0, 0}, green[3]={0, 1, 0};
+
+  qh_geomplanes(facet, &outerplane, &innerplane);
+  vertices= qh_facet3vertex(facet); /* oriented */
+  cntvertices= qh_setsize(vertices);
+  projectedpoints= qh_settemp(cntvertices);
+  FOREACHvertex_(vertices) {
+    zinc_(Zdistio);
+    qh_distplane(vertex->point, facet, &dist);
+    projpt= qh_projectpoint(vertex->point, facet, dist);
+    qh_setappend(&projectedpoints, projpt);
+  }
+  if (qh PRINTouter || (!qh PRINTnoplanes && !qh PRINTinner))
+    qh_printfacet3geom_points(fp, projectedpoints, facet, outerplane, color);
+  if (qh PRINTinner || (!qh PRINTnoplanes && !qh PRINTouter &&
+                outerplane - innerplane > 2 * qh MAXabs_coord * qh_GEOMepsilon)) {
+    for (k=3; k--; )
+      color[k]= 1.0 - color[k];
+    qh_printfacet3geom_points(fp, projectedpoints, facet, innerplane, color);
+  }
+  FOREACHpoint_(projectedpoints)
+    qh_memfree(point, qh normal_size);
+  qh_settempfree(&projectedpoints);
+  qh_settempfree(&vertices);
+  if ((qh DOintersections || qh PRINTridges)
+  && (!facet->visible || !qh NEWfacets)) {
+    facet->visitid= qh visit_id;
+    FOREACHridge_(facet->ridges) {
+      neighbor= otherfacet_(ridge, facet);
+      if (neighbor->visitid != qh visit_id) {
+        if (qh DOintersections)
+          qh_printhyperplaneintersection(fp, facet, neighbor, ridge->vertices, black);
+        if (qh PRINTridges) {
+          vertexA= SETfirstt_(ridge->vertices, vertexT);
+          vertexB= SETsecondt_(ridge->vertices, vertexT);
+          qh_printline3geom(fp, vertexA->point, vertexB->point, green);
+        }
+      }
+    }
+  }
+} /* printfacet3geom_nonsimplicial */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacet3geom_points">-</a>
+
+  qh_printfacet3geom_points( fp, points, facet, offset )
+    prints a 3-d facet as OFF Geomview object.
+    offset is relative to the facet's hyperplane
+    Facet is determined as a list of points
+*/
+void qh_printfacet3geom_points(FILE *fp, setT *points, facetT *facet, realT offset, realT color[3]) {
+  int k, n= qh_setsize(points), i;
+  pointT *point, **pointp;
+  setT *printpoints;
+
+  qh_fprintf(fp, 9098, "{ OFF %d 1 1 # f%d\n", n, facet->id);
+  if (offset != 0.0) {
+    printpoints= qh_settemp(n);
+    FOREACHpoint_(points)
+      qh_setappend(&printpoints, qh_projectpoint(point, facet, -offset));
+  }else
+    printpoints= points;
+  FOREACHpoint_(printpoints) {
+    for (k=0; k < qh hull_dim; k++) {
+      if (k == qh DROPdim)
+        qh_fprintf(fp, 9099, "0 ");
+      else
+        qh_fprintf(fp, 9100, "%8.4g ", point[k]);
+    }
+    if (printpoints != points)
+      qh_memfree(point, qh normal_size);
+    qh_fprintf(fp, 9101, "\n");
+  }
+  if (printpoints != points)
+    qh_settempfree(&printpoints);
+  qh_fprintf(fp, 9102, "%d ", n);
+  for (i=0; i < n; i++)
+    qh_fprintf(fp, 9103, "%d ", i);
+  qh_fprintf(fp, 9104, "%8.4g %8.4g %8.4g 1.0 }\n", color[0], color[1], color[2]);
+} /* printfacet3geom_points */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacet3geom_simplicial">-</a>
+
+  qh_printfacet3geom_simplicial(  )
+    print Geomview OFF for a 3-d simplicial facet.
+
+  notes:
+    may flip color
+    uses facet->visitid for intersections and ridges
+
+    assume precise calculations in io.c with roundoff covered by qh_GEOMepsilon
+    innerplane may be off by qh DISTround.  Maxoutside is calculated elsewhere
+    so a DISTround error may have occurred.
+*/
+void qh_printfacet3geom_simplicial(FILE *fp, facetT *facet, realT color[3]) {
+  setT *points, *vertices;
+  vertexT *vertex, **vertexp, *vertexA, *vertexB;
+  facetT *neighbor, **neighborp;
+  realT outerplane, innerplane;
+  realT black[3]={0, 0, 0}, green[3]={0, 1, 0};
+  int k;
+
+  qh_geomplanes(facet, &outerplane, &innerplane);
+  vertices= qh_facet3vertex(facet);
+  points= qh_settemp(qh TEMPsize);
+  FOREACHvertex_(vertices)
+    qh_setappend(&points, vertex->point);
+  if (qh PRINTouter || (!qh PRINTnoplanes && !qh PRINTinner))
+    qh_printfacet3geom_points(fp, points, facet, outerplane, color);
+  if (qh PRINTinner || (!qh PRINTnoplanes && !qh PRINTouter &&
+              outerplane - innerplane > 2 * qh MAXabs_coord * qh_GEOMepsilon)) {
+    for (k=3; k--; )
+      color[k]= 1.0 - color[k];
+    qh_printfacet3geom_points(fp, points, facet, innerplane, color);
+  }
+  qh_settempfree(&points);
+  qh_settempfree(&vertices);
+  if ((qh DOintersections || qh PRINTridges)
+  && (!facet->visible || !qh NEWfacets)) {
+    facet->visitid= qh visit_id;
+    FOREACHneighbor_(facet) {
+      if (neighbor->visitid != qh visit_id) {
+        vertices= qh_setnew_delnthsorted(facet->vertices, qh hull_dim,
+                          SETindex_(facet->neighbors, neighbor), 0);
+        if (qh DOintersections)
+           qh_printhyperplaneintersection(fp, facet, neighbor, vertices, black);
+        if (qh PRINTridges) {
+          vertexA= SETfirstt_(vertices, vertexT);
+          vertexB= SETsecondt_(vertices, vertexT);
+          qh_printline3geom(fp, vertexA->point, vertexB->point, green);
+        }
+        qh_setfree(&vertices);
+      }
+    }
+  }
+} /* printfacet3geom_simplicial */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacet3math">-</a>
+
+  qh_printfacet3math( fp, facet, notfirst )
+    print 3-d Maple or Mathematica output for a facet
+
+  notes:
+    may be non-simplicial
+    use %16.8f since Mathematica 2.2 does not handle exponential format
+    see qh_printfacet2math
+*/
+void qh_printfacet3math(FILE *fp, facetT *facet, qh_PRINT format, int notfirst) {
+  vertexT *vertex, **vertexp;
+  setT *points, *vertices;
+  pointT *point, **pointp;
+  boolT firstpoint= True;
+  realT dist;
+  const char *pointfmt, *endfmt;
+
+  if (notfirst)
+    qh_fprintf(fp, 9105, ",\n");
+  vertices= qh_facet3vertex(facet);
+  points= qh_settemp(qh_setsize(vertices));
+  FOREACHvertex_(vertices) {
+    zinc_(Zdistio);
+    qh_distplane(vertex->point, facet, &dist);
+    point= qh_projectpoint(vertex->point, facet, dist);
+    qh_setappend(&points, point);
+  }
+  if (format == qh_PRINTmaple) {
+    qh_fprintf(fp, 9106, "[");
+    pointfmt= "[%16.8f, %16.8f, %16.8f]";
+    endfmt= "]";
+  }else {
+    qh_fprintf(fp, 9107, "Polygon[{");
+    pointfmt= "{%16.8f, %16.8f, %16.8f}";
+    endfmt= "}]";
+  }
+  FOREACHpoint_(points) {
+    if (firstpoint)
+      firstpoint= False;
+    else
+      qh_fprintf(fp, 9108, ",\n");
+    qh_fprintf(fp, 9109, pointfmt, point[0], point[1], point[2]);
+  }
+  FOREACHpoint_(points)
+    qh_memfree(point, qh normal_size);
+  qh_settempfree(&points);
+  qh_settempfree(&vertices);
+  qh_fprintf(fp, 9110, endfmt);
+} /* printfacet3math */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacet3vertex">-</a>
+
+  qh_printfacet3vertex( fp, facet, format )
+    print vertices in a 3-d facet as point ids
+
+  notes:
+    prints number of vertices first if format == qh_PRINToff
+    the facet may be non-simplicial
+*/
+void qh_printfacet3vertex(FILE *fp, facetT *facet, qh_PRINT format) {
+  vertexT *vertex, **vertexp;
+  setT *vertices;
+
+  vertices= qh_facet3vertex(facet);
+  if (format == qh_PRINToff)
+    qh_fprintf(fp, 9111, "%d ", qh_setsize(vertices));
+  FOREACHvertex_(vertices)
+    qh_fprintf(fp, 9112, "%d ", qh_pointid(vertex->point));
+  qh_fprintf(fp, 9113, "\n");
+  qh_settempfree(&vertices);
+} /* printfacet3vertex */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacet4geom_nonsimplicial">-</a>
+
+  qh_printfacet4geom_nonsimplicial(  )
+    print Geomview 4OFF file for a 4d nonsimplicial facet
+    prints all ridges to unvisited neighbors (qh.visit_id)
+    if qh.DROPdim
+      prints in OFF format
+
+  notes:
+    must agree with printend4geom()
+*/
+void qh_printfacet4geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]) {
+  facetT *neighbor;
+  ridgeT *ridge, **ridgep;
+  vertexT *vertex, **vertexp;
+  pointT *point;
+  int k;
+  realT dist;
+
+  facet->visitid= qh visit_id;
+  if (qh PRINTnoplanes || (facet->visible && qh NEWfacets))
+    return;
+  FOREACHridge_(facet->ridges) {
+    neighbor= otherfacet_(ridge, facet);
+    if (neighbor->visitid == qh visit_id)
+      continue;
+    if (qh PRINTtransparent && !neighbor->good)
+      continue;
+    if (qh DOintersections)
+      qh_printhyperplaneintersection(fp, facet, neighbor, ridge->vertices, color);
+    else {
+      if (qh DROPdim >= 0)
+        qh_fprintf(fp, 9114, "OFF 3 1 1 # f%d\n", facet->id);
+      else {
+        qh printoutvar++;
+        qh_fprintf(fp, 9115, "# r%d between f%d f%d\n", ridge->id, facet->id, neighbor->id);
+      }
+      FOREACHvertex_(ridge->vertices) {
+        zinc_(Zdistio);
+        qh_distplane(vertex->point,facet, &dist);
+        point=qh_projectpoint(vertex->point,facet, dist);
+        for (k=0; k < qh hull_dim; k++) {
+          if (k != qh DROPdim)
+            qh_fprintf(fp, 9116, "%8.4g ", point[k]);
+        }
+        qh_fprintf(fp, 9117, "\n");
+        qh_memfree(point, qh normal_size);
+      }
+      if (qh DROPdim >= 0)
+        qh_fprintf(fp, 9118, "3 0 1 2 %8.4g %8.4g %8.4g\n", color[0], color[1], color[2]);
+    }
+  }
+} /* printfacet4geom_nonsimplicial */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacet4geom_simplicial">-</a>
+
+  qh_printfacet4geom_simplicial( fp, facet, color )
+    print Geomview 4OFF file for a 4d simplicial facet
+    prints triangles for unvisited neighbors (qh.visit_id)
+
+  notes:
+    must agree with printend4geom()
+*/
+void qh_printfacet4geom_simplicial(FILE *fp, facetT *facet, realT color[3]) {
+  setT *vertices;
+  facetT *neighbor, **neighborp;
+  vertexT *vertex, **vertexp;
+  int k;
+
+  facet->visitid= qh visit_id;
+  if (qh PRINTnoplanes || (facet->visible && qh NEWfacets))
+    return;
+  FOREACHneighbor_(facet) {
+    if (neighbor->visitid == qh visit_id)
+      continue;
+    if (qh PRINTtransparent && !neighbor->good)
+      continue;
+    vertices= qh_setnew_delnthsorted(facet->vertices, qh hull_dim,
+                          SETindex_(facet->neighbors, neighbor), 0);
+    if (qh DOintersections)
+      qh_printhyperplaneintersection(fp, facet, neighbor, vertices, color);
+    else {
+      if (qh DROPdim >= 0)
+        qh_fprintf(fp, 9119, "OFF 3 1 1 # ridge between f%d f%d\n",
+                facet->id, neighbor->id);
+      else {
+        qh printoutvar++;
+        qh_fprintf(fp, 9120, "# ridge between f%d f%d\n", facet->id, neighbor->id);
+      }
+      FOREACHvertex_(vertices) {
+        for (k=0; k < qh hull_dim; k++) {
+          if (k != qh DROPdim)
+            qh_fprintf(fp, 9121, "%8.4g ", vertex->point[k]);
+        }
+        qh_fprintf(fp, 9122, "\n");
+      }
+      if (qh DROPdim >= 0)
+        qh_fprintf(fp, 9123, "3 0 1 2 %8.4g %8.4g %8.4g\n", color[0], color[1], color[2]);
+    }
+    qh_setfree(&vertices);
+  }
+} /* printfacet4geom_simplicial */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacetNvertex_nonsimplicial">-</a>
+
+  qh_printfacetNvertex_nonsimplicial( fp, facet, id, format )
+    print vertices for an N-d non-simplicial facet
+    triangulates each ridge to the id
+*/
+void qh_printfacetNvertex_nonsimplicial(FILE *fp, facetT *facet, int id, qh_PRINT format) {
+  vertexT *vertex, **vertexp;
+  ridgeT *ridge, **ridgep;
+
+  if (facet->visible && qh NEWfacets)
+    return;
+  FOREACHridge_(facet->ridges) {
+    if (format == qh_PRINTtriangles)
+      qh_fprintf(fp, 9124, "%d ", qh hull_dim);
+    qh_fprintf(fp, 9125, "%d ", id);
+    if ((ridge->top == facet) ^ qh_ORIENTclock) {
+      FOREACHvertex_(ridge->vertices)
+        qh_fprintf(fp, 9126, "%d ", qh_pointid(vertex->point));
+    }else {
+      FOREACHvertexreverse12_(ridge->vertices)
+        qh_fprintf(fp, 9127, "%d ", qh_pointid(vertex->point));
+    }
+    qh_fprintf(fp, 9128, "\n");
+  }
+} /* printfacetNvertex_nonsimplicial */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacetNvertex_simplicial">-</a>
+
+  qh_printfacetNvertex_simplicial( fp, facet, format )
+    print vertices for an N-d simplicial facet
+    prints vertices for non-simplicial facets
+      2-d facets (orientation preserved by qh_mergefacet2d)
+      PRINToff ('o') for 4-d and higher
+*/
+void qh_printfacetNvertex_simplicial(FILE *fp, facetT *facet, qh_PRINT format) {
+  vertexT *vertex, **vertexp;
+
+  if (format == qh_PRINToff || format == qh_PRINTtriangles)
+    qh_fprintf(fp, 9129, "%d ", qh_setsize(facet->vertices));
+  if ((facet->toporient ^ qh_ORIENTclock)
+  || (qh hull_dim > 2 && !facet->simplicial)) {
+    FOREACHvertex_(facet->vertices)
+      qh_fprintf(fp, 9130, "%d ", qh_pointid(vertex->point));
+  }else {
+    FOREACHvertexreverse12_(facet->vertices)
+      qh_fprintf(fp, 9131, "%d ", qh_pointid(vertex->point));
+  }
+  qh_fprintf(fp, 9132, "\n");
+} /* printfacetNvertex_simplicial */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacetheader">-</a>
+
+  qh_printfacetheader( fp, facet )
+    prints header fields of a facet to fp
+
+  notes:
+    for 'f' output and debugging
+    Same as QhullFacet::printHeader()
+*/
+void qh_printfacetheader(FILE *fp, facetT *facet) {
+  pointT *point, **pointp, *furthest;
+  facetT *neighbor, **neighborp;
+  realT dist;
+
+  if (facet == qh_MERGEridge) {
+    qh_fprintf(fp, 9133, " MERGEridge\n");
+    return;
+  }else if (facet == qh_DUPLICATEridge) {
+    qh_fprintf(fp, 9134, " DUPLICATEridge\n");
+    return;
+  }else if (!facet) {
+    qh_fprintf(fp, 9135, " NULLfacet\n");
+    return;
+  }
+  qh old_randomdist= qh RANDOMdist;
+  qh RANDOMdist= False;
+  qh_fprintf(fp, 9136, "- f%d\n", facet->id);
+  qh_fprintf(fp, 9137, "    - flags:");
+  if (facet->toporient)
+    qh_fprintf(fp, 9138, " top");
+  else
+    qh_fprintf(fp, 9139, " bottom");
+  if (facet->simplicial)
+    qh_fprintf(fp, 9140, " simplicial");
+  if (facet->tricoplanar)
+    qh_fprintf(fp, 9141, " tricoplanar");
+  if (facet->upperdelaunay)
+    qh_fprintf(fp, 9142, " upperDelaunay");
+  if (facet->visible)
+    qh_fprintf(fp, 9143, " visible");
+  if (facet->newfacet)
+    qh_fprintf(fp, 9144, " new");
+  if (facet->tested)
+    qh_fprintf(fp, 9145, " tested");
+  if (!facet->good)
+    qh_fprintf(fp, 9146, " notG");
+  if (facet->seen)
+    qh_fprintf(fp, 9147, " seen");
+  if (facet->coplanar)
+    qh_fprintf(fp, 9148, " coplanar");
+  if (facet->mergehorizon)
+    qh_fprintf(fp, 9149, " mergehorizon");
+  if (facet->keepcentrum)
+    qh_fprintf(fp, 9150, " keepcentrum");
+  if (facet->dupridge)
+    qh_fprintf(fp, 9151, " dupridge");
+  if (facet->mergeridge && !facet->mergeridge2)
+    qh_fprintf(fp, 9152, " mergeridge1");
+  if (facet->mergeridge2)
+    qh_fprintf(fp, 9153, " mergeridge2");
+  if (facet->newmerge)
+    qh_fprintf(fp, 9154, " newmerge");
+  if (facet->flipped)
+    qh_fprintf(fp, 9155, " flipped");
+  if (facet->notfurthest)
+    qh_fprintf(fp, 9156, " notfurthest");
+  if (facet->degenerate)
+    qh_fprintf(fp, 9157, " degenerate");
+  if (facet->redundant)
+    qh_fprintf(fp, 9158, " redundant");
+  qh_fprintf(fp, 9159, "\n");
+  if (facet->isarea)
+    qh_fprintf(fp, 9160, "    - area: %2.2g\n", facet->f.area);
+  else if (qh NEWfacets && facet->visible && facet->f.replace)
+    qh_fprintf(fp, 9161, "    - replacement: f%d\n", facet->f.replace->id);
+  else if (facet->newfacet) {
+    if (facet->f.samecycle && facet->f.samecycle != facet)
+      qh_fprintf(fp, 9162, "    - shares same visible/horizon as f%d\n", facet->f.samecycle->id);
+  }else if (facet->tricoplanar /* !isarea */) {
+    if (facet->f.triowner)
+      qh_fprintf(fp, 9163, "    - owner of normal & centrum is facet f%d\n", facet->f.triowner->id);
+  }else if (facet->f.newcycle)
+    qh_fprintf(fp, 9164, "    - was horizon to f%d\n", facet->f.newcycle->id);
+  if (facet->nummerge)
+    qh_fprintf(fp, 9165, "    - merges: %d\n", facet->nummerge);
+  qh_printpointid(fp, "    - normal: ", qh hull_dim, facet->normal, -1);
+  qh_fprintf(fp, 9166, "    - offset: %10.7g\n", facet->offset);
+  if (qh CENTERtype == qh_ASvoronoi || facet->center)
+    qh_printcenter(fp, qh_PRINTfacets, "    - center: ", facet);
+#if qh_MAXoutside
+  if (facet->maxoutside > qh DISTround)
+    qh_fprintf(fp, 9167, "    - maxoutside: %10.7g\n", facet->maxoutside);
+#endif
+  if (!SETempty_(facet->outsideset)) {
+    furthest= (pointT*)qh_setlast(facet->outsideset);
+    if (qh_setsize(facet->outsideset) < 6) {
+      qh_fprintf(fp, 9168, "    - outside set(furthest p%d):\n", qh_pointid(furthest));
+      FOREACHpoint_(facet->outsideset)
+        qh_printpoint(fp, "     ", point);
+    }else if (qh_setsize(facet->outsideset) < 21) {
+      qh_printpoints(fp, "    - outside set:", facet->outsideset);
+    }else {
+      qh_fprintf(fp, 9169, "    - outside set:  %d points.", qh_setsize(facet->outsideset));
+      qh_printpoint(fp, "  Furthest", furthest);
+    }
+#if !qh_COMPUTEfurthest
+    qh_fprintf(fp, 9170, "    - furthest distance= %2.2g\n", facet->furthestdist);
+#endif
+  }
+  if (!SETempty_(facet->coplanarset)) {
+    furthest= (pointT*)qh_setlast(facet->coplanarset);
+    if (qh_setsize(facet->coplanarset) < 6) {
+      qh_fprintf(fp, 9171, "    - coplanar set(furthest p%d):\n", qh_pointid(furthest));
+      FOREACHpoint_(facet->coplanarset)
+        qh_printpoint(fp, "     ", point);
+    }else if (qh_setsize(facet->coplanarset) < 21) {
+      qh_printpoints(fp, "    - coplanar set:", facet->coplanarset);
+    }else {
+      qh_fprintf(fp, 9172, "    - coplanar set:  %d points.", qh_setsize(facet->coplanarset));
+      qh_printpoint(fp, "  Furthest", furthest);
+    }
+    zinc_(Zdistio);
+    qh_distplane(furthest, facet, &dist);
+    qh_fprintf(fp, 9173, "      furthest distance= %2.2g\n", dist);
+  }
+  qh_printvertices(fp, "    - vertices:", facet->vertices);
+  qh_fprintf(fp, 9174, "    - neighboring facets:");
+  FOREACHneighbor_(facet) {
+    if (neighbor == qh_MERGEridge)
+      qh_fprintf(fp, 9175, " MERGE");
+    else if (neighbor == qh_DUPLICATEridge)
+      qh_fprintf(fp, 9176, " DUP");
+    else
+      qh_fprintf(fp, 9177, " f%d", neighbor->id);
+  }
+  qh_fprintf(fp, 9178, "\n");
+  qh RANDOMdist= qh old_randomdist;
+} /* printfacetheader */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacetridges">-</a>
+
+  qh_printfacetridges( fp, facet )
+    prints ridges of a facet to fp
+
+  notes:
+    ridges printed in neighbor order
+    assumes the ridges exist
+    for 'f' output
+    same as QhullFacet::printRidges
+*/
+void qh_printfacetridges(FILE *fp, facetT *facet) {
+  facetT *neighbor, **neighborp;
+  ridgeT *ridge, **ridgep;
+  int numridges= 0;
+
+
+  if (facet->visible && qh NEWfacets) {
+    qh_fprintf(fp, 9179, "    - ridges(ids may be garbage):");
+    FOREACHridge_(facet->ridges)
+      qh_fprintf(fp, 9180, " r%d", ridge->id);
+    qh_fprintf(fp, 9181, "\n");
+  }else {
+    qh_fprintf(fp, 9182, "    - ridges:\n");
+    FOREACHridge_(facet->ridges)
+      ridge->seen= False;
+    if (qh hull_dim == 3) {
+      ridge= SETfirstt_(facet->ridges, ridgeT);
+      while (ridge && !ridge->seen) {
+        ridge->seen= True;
+        qh_printridge(fp, ridge);
+        numridges++;
+        ridge= qh_nextridge3d(ridge, facet, NULL);
+        }
+    }else {
+      FOREACHneighbor_(facet) {
+        FOREACHridge_(facet->ridges) {
+          if (otherfacet_(ridge,facet) == neighbor) {
+            ridge->seen= True;
+            qh_printridge(fp, ridge);
+            numridges++;
+          }
+        }
+      }
+    }
+    if (numridges != qh_setsize(facet->ridges)) {
+      qh_fprintf(fp, 9183, "     - all ridges:");
+      FOREACHridge_(facet->ridges)
+        qh_fprintf(fp, 9184, " r%d", ridge->id);
+        qh_fprintf(fp, 9185, "\n");
+    }
+    FOREACHridge_(facet->ridges) {
+      if (!ridge->seen)
+        qh_printridge(fp, ridge);
+    }
+  }
+} /* printfacetridges */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacets">-</a>
+
+  qh_printfacets( fp, format, facetlist, facets, printall )
+    prints facetlist and/or facet set in output format
+
+  notes:
+    also used for specialized formats ('FO' and summary)
+    turns off 'Rn' option since want actual numbers
+*/
+void qh_printfacets(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
+  int numfacets, numsimplicial, numridges, totneighbors, numcoplanars, numtricoplanars;
+  facetT *facet, **facetp;
+  setT *vertices;
+  coordT *center;
+  realT outerplane, innerplane;
+
+  qh old_randomdist= qh RANDOMdist;
+  qh RANDOMdist= False;
+  if (qh CDDoutput && (format == qh_PRINTcentrums || format == qh_PRINTpointintersect || format == qh_PRINToff))
+    qh_fprintf(qh ferr, 7056, "qhull warning: CDD format is not available for centrums, halfspace\nintersections, and OFF file format.\n");
+  if (format == qh_PRINTnone)
+    ; /* print nothing */
+  else if (format == qh_PRINTaverage) {
+    vertices= qh_facetvertices(facetlist, facets, printall);
+    center= qh_getcenter(vertices);
+    qh_fprintf(fp, 9186, "%d 1\n", qh hull_dim);
+    qh_printpointid(fp, NULL, qh hull_dim, center, -1);
+    qh_memfree(center, qh normal_size);
+    qh_settempfree(&vertices);
+  }else if (format == qh_PRINTextremes) {
+    if (qh DELAUNAY)
+      qh_printextremes_d(fp, facetlist, facets, printall);
+    else if (qh hull_dim == 2)
+      qh_printextremes_2d(fp, facetlist, facets, printall);
+    else
+      qh_printextremes(fp, facetlist, facets, printall);
+  }else if (format == qh_PRINToptions)
+    qh_fprintf(fp, 9187, "Options selected for Qhull %s:\n%s\n", qh_version, qh qhull_options);
+  else if (format == qh_PRINTpoints && !qh VORONOI)
+    qh_printpoints_out(fp, facetlist, facets, printall);
+  else if (format == qh_PRINTqhull)
+    qh_fprintf(fp, 9188, "%s | %s\n", qh rbox_command, qh qhull_command);
+  else if (format == qh_PRINTsize) {
+    qh_fprintf(fp, 9189, "0\n2 ");
+    qh_fprintf(fp, 9190, qh_REAL_1, qh totarea);
+    qh_fprintf(fp, 9191, qh_REAL_1, qh totvol);
+    qh_fprintf(fp, 9192, "\n");
+  }else if (format == qh_PRINTsummary) {
+    qh_countfacets(facetlist, facets, printall, &numfacets, &numsimplicial,
+      &totneighbors, &numridges, &numcoplanars, &numtricoplanars);
+    vertices= qh_facetvertices(facetlist, facets, printall);
+    qh_fprintf(fp, 9193, "10 %d %d %d %d %d %d %d %d %d %d\n2 ", qh hull_dim,
+                qh num_points + qh_setsize(qh other_points),
+                qh num_vertices, qh num_facets - qh num_visible,
+                qh_setsize(vertices), numfacets, numcoplanars,
+                numfacets - numsimplicial, zzval_(Zdelvertextot),
+                numtricoplanars);
+    qh_settempfree(&vertices);
+    qh_outerinner(NULL, &outerplane, &innerplane);
+    qh_fprintf(fp, 9194, qh_REAL_2n, outerplane, innerplane);
+  }else if (format == qh_PRINTvneighbors)
+    qh_printvneighbors(fp, facetlist, facets, printall);
+  else if (qh VORONOI && format == qh_PRINToff)
+    qh_printvoronoi(fp, format, facetlist, facets, printall);
+  else if (qh VORONOI && format == qh_PRINTgeom) {
+    qh_printbegin(fp, format, facetlist, facets, printall);
+    qh_printvoronoi(fp, format, facetlist, facets, printall);
+    qh_printend(fp, format, facetlist, facets, printall);
+  }else if (qh VORONOI
+  && (format == qh_PRINTvertices || format == qh_PRINTinner || format == qh_PRINTouter))
+    qh_printvdiagram(fp, format, facetlist, facets, printall);
+  else {
+    qh_printbegin(fp, format, facetlist, facets, printall);
+    FORALLfacet_(facetlist)
+      qh_printafacet(fp, format, facet, printall);
+    FOREACHfacet_(facets)
+      qh_printafacet(fp, format, facet, printall);
+    qh_printend(fp, format, facetlist, facets, printall);
+  }
+  qh RANDOMdist= qh old_randomdist;
+} /* printfacets */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printhyperplaneintersection">-</a>
+
+  qh_printhyperplaneintersection( fp, facet1, facet2, vertices, color )
+    print Geomview OFF or 4OFF for the intersection of two hyperplanes in 3-d or 4-d
+*/
+void qh_printhyperplaneintersection(FILE *fp, facetT *facet1, facetT *facet2,
+                   setT *vertices, realT color[3]) {
+  realT costheta, denominator, dist1, dist2, s, t, mindenom, p[4];
+  vertexT *vertex, **vertexp;
+  int i, k;
+  boolT nearzero1, nearzero2;
+
+  costheta= qh_getangle(facet1->normal, facet2->normal);
+  denominator= 1 - costheta * costheta;
+  i= qh_setsize(vertices);
+  if (qh hull_dim == 3)
+    qh_fprintf(fp, 9195, "VECT 1 %d 1 %d 1 ", i, i);
+  else if (qh hull_dim == 4 && qh DROPdim >= 0)
+    qh_fprintf(fp, 9196, "OFF 3 1 1 ");
+  else
+    qh printoutvar++;
+  qh_fprintf(fp, 9197, "# intersect f%d f%d\n", facet1->id, facet2->id);
+  mindenom= 1 / (10.0 * qh MAXabs_coord);
+  FOREACHvertex_(vertices) {
+    zadd_(Zdistio, 2);
+    qh_distplane(vertex->point, facet1, &dist1);
+    qh_distplane(vertex->point, facet2, &dist2);
+    s= qh_divzero(-dist1 + costheta * dist2, denominator,mindenom,&nearzero1);
+    t= qh_divzero(-dist2 + costheta * dist1, denominator,mindenom,&nearzero2);
+    if (nearzero1 || nearzero2)
+      s= t= 0.0;
+    for (k=qh hull_dim; k--; )
+      p[k]= vertex->point[k] + facet1->normal[k] * s + facet2->normal[k] * t;
+    if (qh PRINTdim <= 3) {
+      qh_projectdim3 (p, p);
+      qh_fprintf(fp, 9198, "%8.4g %8.4g %8.4g # ", p[0], p[1], p[2]);
+    }else
+      qh_fprintf(fp, 9199, "%8.4g %8.4g %8.4g %8.4g # ", p[0], p[1], p[2], p[3]);
+    if (nearzero1+nearzero2)
+      qh_fprintf(fp, 9200, "p%d(coplanar facets)\n", qh_pointid(vertex->point));
+    else
+      qh_fprintf(fp, 9201, "projected p%d\n", qh_pointid(vertex->point));
+  }
+  if (qh hull_dim == 3)
+    qh_fprintf(fp, 9202, "%8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]);
+  else if (qh hull_dim == 4 && qh DROPdim >= 0)
+    qh_fprintf(fp, 9203, "3 0 1 2 %8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]);
+} /* printhyperplaneintersection */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printline3geom">-</a>
+
+  qh_printline3geom( fp, pointA, pointB, color )
+    prints a line as a VECT
+    prints 0's for qh.DROPdim
+
+  notes:
+    if pointA == pointB,
+      it's a 1 point VECT
+*/
+void qh_printline3geom(FILE *fp, pointT *pointA, pointT *pointB, realT color[3]) {
+  int k;
+  realT pA[4], pB[4];
+
+  qh_projectdim3(pointA, pA);
+  qh_projectdim3(pointB, pB);
+  if ((fabs(pA[0] - pB[0]) > 1e-3) ||
+      (fabs(pA[1] - pB[1]) > 1e-3) ||
+      (fabs(pA[2] - pB[2]) > 1e-3)) {
+    qh_fprintf(fp, 9204, "VECT 1 2 1 2 1\n");
+    for (k=0; k < 3; k++)
+       qh_fprintf(fp, 9205, "%8.4g ", pB[k]);
+    qh_fprintf(fp, 9206, " # p%d\n", qh_pointid(pointB));
+  }else
+    qh_fprintf(fp, 9207, "VECT 1 1 1 1 1\n");
+  for (k=0; k < 3; k++)
+    qh_fprintf(fp, 9208, "%8.4g ", pA[k]);
+  qh_fprintf(fp, 9209, " # p%d\n", qh_pointid(pointA));
+  qh_fprintf(fp, 9210, "%8.4g %8.4g %8.4g 1\n", color[0], color[1], color[2]);
+}
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printneighborhood">-</a>
+
+  qh_printneighborhood( fp, format, facetA, facetB, printall )
+    print neighborhood of one or two facets
+
+  notes:
+    calls qh_findgood_all()
+    bumps qh.visit_id
+*/
+void qh_printneighborhood(FILE *fp, qh_PRINT format, facetT *facetA, facetT *facetB, boolT printall) {
+  facetT *neighbor, **neighborp, *facet;
+  setT *facets;
+
+  if (format == qh_PRINTnone)
+    return;
+  qh_findgood_all(qh facet_list);
+  if (facetA == facetB)
+    facetB= NULL;
+  facets= qh_settemp(2*(qh_setsize(facetA->neighbors)+1));
+  qh visit_id++;
+  for (facet= facetA; facet; facet= ((facet == facetA) ? facetB : NULL)) {
+    if (facet->visitid != qh visit_id) {
+      facet->visitid= qh visit_id;
+      qh_setappend(&facets, facet);
+    }
+    FOREACHneighbor_(facet) {
+      if (neighbor->visitid == qh visit_id)
+        continue;
+      neighbor->visitid= qh visit_id;
+      if (printall || !qh_skipfacet(neighbor))
+        qh_setappend(&facets, neighbor);
+    }
+  }
+  qh_printfacets(fp, format, NULL, facets, printall);
+  qh_settempfree(&facets);
+} /* printneighborhood */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printpoint">-</a>
+
+  qh_printpoint( fp, string, point )
+  qh_printpointid( fp, string, dim, point, id )
+    prints the coordinates of a point
+
+  returns:
+    if string is defined
+      prints 'string p%d' (skips p%d if id=-1)
+
+  notes:
+    nop if point is NULL
+    prints id unless it is undefined (-1)
+    Same as QhullPoint's printPoint
+*/
+void qh_printpoint(FILE *fp, const char *string, pointT *point) {
+  int id= qh_pointid( point);
+
+  qh_printpointid( fp, string, qh hull_dim, point, id);
+} /* printpoint */
+
+void qh_printpointid(FILE *fp, const char *string, int dim, pointT *point, int id) {
+  int k;
+  realT r; /*bug fix*/
+
+  if (!point)
+    return;
+  if (string) {
+    qh_fprintf(fp, 9211, "%s", string);
+   if (id != -1)
+      qh_fprintf(fp, 9212, " p%d: ", id);
+  }
+  for (k=dim; k--; ) {
+    r= *point++;
+    if (string)
+      qh_fprintf(fp, 9213, " %8.4g", r);
+    else
+      qh_fprintf(fp, 9214, qh_REAL_1, r);
+  }
+  qh_fprintf(fp, 9215, "\n");
+} /* printpointid */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printpoint3">-</a>
+
+  qh_printpoint3( fp, point )
+    prints 2-d, 3-d, or 4-d point as Geomview 3-d coordinates
+*/
+void qh_printpoint3 (FILE *fp, pointT *point) {
+  int k;
+  realT p[4];
+
+  qh_projectdim3 (point, p);
+  for (k=0; k < 3; k++)
+    qh_fprintf(fp, 9216, "%8.4g ", p[k]);
+  qh_fprintf(fp, 9217, " # p%d\n", qh_pointid(point));
+} /* printpoint3 */
+
+/*----------------------------------------
+-printpoints- print pointids for a set of points starting at index
+   see geom.c
+*/
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printpoints_out">-</a>
+
+  qh_printpoints_out( fp, facetlist, facets, printall )
+    prints vertices, coplanar/inside points, for facets by their point coordinates
+    allows qh.CDDoutput
+
+  notes:
+    same format as qhull input
+    if no coplanar/interior points,
+      same order as qh_printextremes
+*/
+void qh_printpoints_out(FILE *fp, facetT *facetlist, setT *facets, boolT printall) {
+  int allpoints= qh num_points + qh_setsize(qh other_points);
+  int numpoints=0, point_i, point_n;
+  setT *vertices, *points;
+  facetT *facet, **facetp;
+  pointT *point, **pointp;
+  vertexT *vertex, **vertexp;
+  int id;
+
+  points= qh_settemp(allpoints);
+  qh_setzero(points, 0, allpoints);
+  vertices= qh_facetvertices(facetlist, facets, printall);
+  FOREACHvertex_(vertices) {
+    id= qh_pointid(vertex->point);
+    if (id >= 0)
+      SETelem_(points, id)= vertex->point;
+  }
+  if (qh KEEPinside || qh KEEPcoplanar || qh KEEPnearinside) {
+    FORALLfacet_(facetlist) {
+      if (!printall && qh_skipfacet(facet))
+        continue;
+      FOREACHpoint_(facet->coplanarset) {
+        id= qh_pointid(point);
+        if (id >= 0)
+          SETelem_(points, id)= point;
+      }
+    }
+    FOREACHfacet_(facets) {
+      if (!printall && qh_skipfacet(facet))
+        continue;
+      FOREACHpoint_(facet->coplanarset) {
+        id= qh_pointid(point);
+        if (id >= 0)
+          SETelem_(points, id)= point;
+      }
+    }
+  }
+  qh_settempfree(&vertices);
+  FOREACHpoint_i_(points) {
+    if (point)
+      numpoints++;
+  }
+  if (qh CDDoutput)
+    qh_fprintf(fp, 9218, "%s | %s\nbegin\n%d %d real\n", qh rbox_command,
+             qh qhull_command, numpoints, qh hull_dim + 1);
+  else
+    qh_fprintf(fp, 9219, "%d\n%d\n", qh hull_dim, numpoints);
+  FOREACHpoint_i_(points) {
+    if (point) {
+      if (qh CDDoutput)
+        qh_fprintf(fp, 9220, "1 ");
+      qh_printpoint(fp, NULL, point);
+    }
+  }
+  if (qh CDDoutput)
+    qh_fprintf(fp, 9221, "end\n");
+  qh_settempfree(&points);
+} /* printpoints_out */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printpointvect">-</a>
+
+  qh_printpointvect( fp, point, normal, center, radius, color )
+    prints a 2-d, 3-d, or 4-d point as 3-d VECT's relative to normal or to center point
+*/
+void qh_printpointvect(FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius, realT color[3]) {
+  realT diff[4], pointA[4];
+  int k;
+
+  for (k=qh hull_dim; k--; ) {
+    if (center)
+      diff[k]= point[k]-center[k];
+    else if (normal)
+      diff[k]= normal[k];
+    else
+      diff[k]= 0;
+  }
+  if (center)
+    qh_normalize2 (diff, qh hull_dim, True, NULL, NULL);
+  for (k=qh hull_dim; k--; )
+    pointA[k]= point[k]+diff[k] * radius;
+  qh_printline3geom(fp, point, pointA, color);
+} /* printpointvect */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printpointvect2">-</a>
+
+  qh_printpointvect2( fp, point, normal, center, radius )
+    prints a 2-d, 3-d, or 4-d point as 2 3-d VECT's for an imprecise point
+*/
+void qh_printpointvect2 (FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius) {
+  realT red[3]={1, 0, 0}, yellow[3]={1, 1, 0};
+
+  qh_printpointvect(fp, point, normal, center, radius, red);
+  qh_printpointvect(fp, point, normal, center, -radius, yellow);
+} /* printpointvect2 */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printridge">-</a>
+
+  qh_printridge( fp, ridge )
+    prints the information in a ridge
+
+  notes:
+    for qh_printfacetridges()
+    same as operator<< [QhullRidge.cpp]
+*/
+void qh_printridge(FILE *fp, ridgeT *ridge) {
+
+  qh_fprintf(fp, 9222, "     - r%d", ridge->id);
+  if (ridge->tested)
+    qh_fprintf(fp, 9223, " tested");
+  if (ridge->nonconvex)
+    qh_fprintf(fp, 9224, " nonconvex");
+  qh_fprintf(fp, 9225, "\n");
+  qh_printvertices(fp, "           vertices:", ridge->vertices);
+  if (ridge->top && ridge->bottom)
+    qh_fprintf(fp, 9226, "           between f%d and f%d\n",
+            ridge->top->id, ridge->bottom->id);
+} /* printridge */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printspheres">-</a>
+
+  qh_printspheres( fp, vertices, radius )
+    prints 3-d vertices as OFF spheres
+
+  notes:
+    inflated octahedron from Stuart Levy earth/mksphere2
+*/
+void qh_printspheres(FILE *fp, setT *vertices, realT radius) {
+  vertexT *vertex, **vertexp;
+
+  qh printoutnum++;
+  qh_fprintf(fp, 9227, "{appearance {-edge -normal normscale 0} {\n\
+INST geom {define vsphere OFF\n\
+18 32 48\n\
+\n\
+0 0 1\n\
+1 0 0\n\
+0 1 0\n\
+-1 0 0\n\
+0 -1 0\n\
+0 0 -1\n\
+0.707107 0 0.707107\n\
+0 -0.707107 0.707107\n\
+0.707107 -0.707107 0\n\
+-0.707107 0 0.707107\n\
+-0.707107 -0.707107 0\n\
+0 0.707107 0.707107\n\
+-0.707107 0.707107 0\n\
+0.707107 0.707107 0\n\
+0.707107 0 -0.707107\n\
+0 0.707107 -0.707107\n\
+-0.707107 0 -0.707107\n\
+0 -0.707107 -0.707107\n\
+\n\
+3 0 6 11\n\
+3 0 7 6 \n\
+3 0 9 7 \n\
+3 0 11 9\n\
+3 1 6 8 \n\
+3 1 8 14\n\
+3 1 13 6\n\
+3 1 14 13\n\
+3 2 11 13\n\
+3 2 12 11\n\
+3 2 13 15\n\
+3 2 15 12\n\
+3 3 9 12\n\
+3 3 10 9\n\
+3 3 12 16\n\
+3 3 16 10\n\
+3 4 7 10\n\
+3 4 8 7\n\
+3 4 10 17\n\
+3 4 17 8\n\
+3 5 14 17\n\
+3 5 15 14\n\
+3 5 16 15\n\
+3 5 17 16\n\
+3 6 13 11\n\
+3 7 8 6\n\
+3 9 10 7\n\
+3 11 12 9\n\
+3 14 8 17\n\
+3 15 13 14\n\
+3 16 12 15\n\
+3 17 10 16\n} transforms { TLIST\n");
+  FOREACHvertex_(vertices) {
+    qh_fprintf(fp, 9228, "%8.4g 0 0 0 # v%d\n 0 %8.4g 0 0\n0 0 %8.4g 0\n",
+      radius, vertex->id, radius, radius);
+    qh_printpoint3 (fp, vertex->point);
+    qh_fprintf(fp, 9229, "1\n");
+  }
+  qh_fprintf(fp, 9230, "}}}\n");
+} /* printspheres */
+
+
+/*----------------------------------------------
+-printsummary-
+                see libqhull.c
+*/
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printvdiagram">-</a>
+
+  qh_printvdiagram( fp, format, facetlist, facets, printall )
+    print voronoi diagram
+      # of pairs of input sites
+      #indices site1 site2 vertex1 ...
+
+    sites indexed by input point id
+      point 0 is the first input point
+    vertices indexed by 'o' and 'p' order
+      vertex 0 is the 'vertex-at-infinity'
+      vertex 1 is the first Voronoi vertex
+
+  see:
+    qh_printvoronoi()
+    qh_eachvoronoi_all()
+
+  notes:
+    if all facets are upperdelaunay,
+      prints upper hull (furthest-site Voronoi diagram)
+*/
+void qh_printvdiagram(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
+  setT *vertices;
+  int totcount, numcenters;
+  boolT isLower;
+  qh_RIDGE innerouter= qh_RIDGEall;
+  printvridgeT printvridge= NULL;
+
+  if (format == qh_PRINTvertices) {
+    innerouter= qh_RIDGEall;
+    printvridge= qh_printvridge;
+  }else if (format == qh_PRINTinner) {
+    innerouter= qh_RIDGEinner;
+    printvridge= qh_printvnorm;
+  }else if (format == qh_PRINTouter) {
+    innerouter= qh_RIDGEouter;
+    printvridge= qh_printvnorm;
+  }else {
+    qh_fprintf(qh ferr, 6219, "Qhull internal error (qh_printvdiagram): unknown print format %d.\n", format);
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  vertices= qh_markvoronoi(facetlist, facets, printall, &isLower, &numcenters);
+  totcount= qh_printvdiagram2 (NULL, NULL, vertices, innerouter, False);
+  qh_fprintf(fp, 9231, "%d\n", totcount);
+  totcount= qh_printvdiagram2 (fp, printvridge, vertices, innerouter, True /* inorder*/);
+  qh_settempfree(&vertices);
+#if 0  /* for testing qh_eachvoronoi_all */
+  qh_fprintf(fp, 9232, "\n");
+  totcount= qh_eachvoronoi_all(fp, printvridge, qh UPPERdelaunay, innerouter, True /* inorder*/);
+  qh_fprintf(fp, 9233, "%d\n", totcount);
+#endif
+} /* printvdiagram */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printvdiagram2">-</a>
+
+  qh_printvdiagram2( fp, printvridge, vertices, innerouter, inorder )
+    visit all pairs of input sites (vertices) for selected Voronoi vertices
+    vertices may include NULLs
+
+  innerouter:
+    qh_RIDGEall   print inner ridges(bounded) and outer ridges(unbounded)
+    qh_RIDGEinner print only inner ridges
+    qh_RIDGEouter print only outer ridges
+
+  inorder:
+    print 3-d Voronoi vertices in order
+
+  assumes:
+    qh_markvoronoi marked facet->visitid for Voronoi vertices
+    all facet->seen= False
+    all facet->seen2= True
+
+  returns:
+    total number of Voronoi ridges
+    if printvridge,
+      calls printvridge( fp, vertex, vertexA, centers) for each ridge
+      [see qh_eachvoronoi()]
+
+  see:
+    qh_eachvoronoi_all()
+*/
+int qh_printvdiagram2 (FILE *fp, printvridgeT printvridge, setT *vertices, qh_RIDGE innerouter, boolT inorder) {
+  int totcount= 0;
+  int vertex_i, vertex_n;
+  vertexT *vertex;
+
+  FORALLvertices
+    vertex->seen= False;
+  FOREACHvertex_i_(vertices) {
+    if (vertex) {
+      if (qh GOODvertex > 0 && qh_pointid(vertex->point)+1 != qh GOODvertex)
+        continue;
+      totcount += qh_eachvoronoi(fp, printvridge, vertex, !qh_ALL, innerouter, inorder);
+    }
+  }
+  return totcount;
+} /* printvdiagram2 */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printvertex">-</a>
+
+  qh_printvertex( fp, vertex )
+    prints the information in a vertex
+    Duplicated as operator<< [QhullVertex.cpp]
+*/
+void qh_printvertex(FILE *fp, vertexT *vertex) {
+  pointT *point;
+  int k, count= 0;
+  facetT *neighbor, **neighborp;
+  realT r; /*bug fix*/
+
+  if (!vertex) {
+    qh_fprintf(fp, 9234, "  NULLvertex\n");
+    return;
+  }
+  qh_fprintf(fp, 9235, "- p%d(v%d):", qh_pointid(vertex->point), vertex->id);
+  point= vertex->point;
+  if (point) {
+    for (k=qh hull_dim; k--; ) {
+      r= *point++;
+      qh_fprintf(fp, 9236, " %5.2g", r);
+    }
+  }
+  if (vertex->deleted)
+    qh_fprintf(fp, 9237, " deleted");
+  if (vertex->delridge)
+    qh_fprintf(fp, 9238, " ridgedeleted");
+  qh_fprintf(fp, 9239, "\n");
+  if (vertex->neighbors) {
+    qh_fprintf(fp, 9240, "  neighbors:");
+    FOREACHneighbor_(vertex) {
+      if (++count % 100 == 0)
+        qh_fprintf(fp, 9241, "\n     ");
+      qh_fprintf(fp, 9242, " f%d", neighbor->id);
+    }
+    qh_fprintf(fp, 9243, "\n");
+  }
+} /* printvertex */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printvertexlist">-</a>
+
+  qh_printvertexlist( fp, string, facetlist, facets, printall )
+    prints vertices used by a facetlist or facet set
+    tests qh_skipfacet() if !printall
+*/
+void qh_printvertexlist(FILE *fp, const char* string, facetT *facetlist,
+                         setT *facets, boolT printall) {
+  vertexT *vertex, **vertexp;
+  setT *vertices;
+
+  vertices= qh_facetvertices(facetlist, facets, printall);
+  qh_fprintf(fp, 9244, "%s", string);
+  FOREACHvertex_(vertices)
+    qh_printvertex(fp, vertex);
+  qh_settempfree(&vertices);
+} /* printvertexlist */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printvertices">-</a>
+
+  qh_printvertices( fp, string, vertices )
+    prints vertices in a set
+    duplicated as printVertexSet [QhullVertex.cpp]
+*/
+void qh_printvertices(FILE *fp, const char* string, setT *vertices) {
+  vertexT *vertex, **vertexp;
+
+  qh_fprintf(fp, 9245, "%s", string);
+  FOREACHvertex_(vertices)
+    qh_fprintf(fp, 9246, " p%d(v%d)", qh_pointid(vertex->point), vertex->id);
+  qh_fprintf(fp, 9247, "\n");
+} /* printvertices */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printvneighbors">-</a>
+
+  qh_printvneighbors( fp, facetlist, facets, printall )
+    print vertex neighbors of vertices in facetlist and facets ('FN')
+
+  notes:
+    qh_countfacets clears facet->visitid for non-printed facets
+
+  design:
+    collect facet count and related statistics
+    if necessary, build neighbor sets for each vertex
+    collect vertices in facetlist and facets
+    build a point array for point->vertex and point->coplanar facet
+    for each point
+      list vertex neighbors or coplanar facet
+*/
+void qh_printvneighbors(FILE *fp, facetT* facetlist, setT *facets, boolT printall) {
+  int numfacets, numsimplicial, numridges, totneighbors, numneighbors, numcoplanars, numtricoplanars;
+  setT *vertices, *vertex_points, *coplanar_points;
+  int numpoints= qh num_points + qh_setsize(qh other_points);
+  vertexT *vertex, **vertexp;
+  int vertex_i, vertex_n;
+  facetT *facet, **facetp, *neighbor, **neighborp;
+  pointT *point, **pointp;
+
+  qh_countfacets(facetlist, facets, printall, &numfacets, &numsimplicial,
+      &totneighbors, &numridges, &numcoplanars, &numtricoplanars);  /* sets facet->visitid */
+  qh_fprintf(fp, 9248, "%d\n", numpoints);
+  qh_vertexneighbors();
+  vertices= qh_facetvertices(facetlist, facets, printall);
+  vertex_points= qh_settemp(numpoints);
+  coplanar_points= qh_settemp(numpoints);
+  qh_setzero(vertex_points, 0, numpoints);
+  qh_setzero(coplanar_points, 0, numpoints);
+  FOREACHvertex_(vertices)
+    qh_point_add(vertex_points, vertex->point, vertex);
+  FORALLfacet_(facetlist) {
+    FOREACHpoint_(facet->coplanarset)
+      qh_point_add(coplanar_points, point, facet);
+  }
+  FOREACHfacet_(facets) {
+    FOREACHpoint_(facet->coplanarset)
+      qh_point_add(coplanar_points, point, facet);
+  }
+  FOREACHvertex_i_(vertex_points) {
+    if (vertex) {
+      numneighbors= qh_setsize(vertex->neighbors);
+      qh_fprintf(fp, 9249, "%d", numneighbors);
+      if (qh hull_dim == 3)
+        qh_order_vertexneighbors(vertex);
+      else if (qh hull_dim >= 4)
+        qsort(SETaddr_(vertex->neighbors, facetT), (size_t)numneighbors,
+             sizeof(facetT *), qh_compare_facetvisit);
+      FOREACHneighbor_(vertex)
+        qh_fprintf(fp, 9250, " %d",
+                 neighbor->visitid ? neighbor->visitid - 1 : 0 - neighbor->id);
+      qh_fprintf(fp, 9251, "\n");
+    }else if ((facet= SETelemt_(coplanar_points, vertex_i, facetT)))
+      qh_fprintf(fp, 9252, "1 %d\n",
+                  facet->visitid ? facet->visitid - 1 : 0 - facet->id);
+    else
+      qh_fprintf(fp, 9253, "0\n");
+  }
+  qh_settempfree(&coplanar_points);
+  qh_settempfree(&vertex_points);
+  qh_settempfree(&vertices);
+} /* printvneighbors */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printvoronoi">-</a>
+
+  qh_printvoronoi( fp, format, facetlist, facets, printall )
+    print voronoi diagram in 'o' or 'G' format
+    for 'o' format
+      prints voronoi centers for each facet and for infinity
+      for each vertex, lists ids of printed facets or infinity
+      assumes facetlist and facets are disjoint
+    for 'G' format
+      prints an OFF object
+      adds a 0 coordinate to center
+      prints infinity but does not list in vertices
+
+  see:
+    qh_printvdiagram()
+
+  notes:
+    if 'o',
+      prints a line for each point except "at-infinity"
+    if all facets are upperdelaunay,
+      reverses lower and upper hull
+*/
+void qh_printvoronoi(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
+  int k, numcenters, numvertices= 0, numneighbors, numinf, vid=1, vertex_i, vertex_n;
+  facetT *facet, **facetp, *neighbor, **neighborp;
+  setT *vertices;
+  vertexT *vertex;
+  boolT isLower;
+  unsigned int numfacets= (unsigned int) qh num_facets;
+
+  vertices= qh_markvoronoi(facetlist, facets, printall, &isLower, &numcenters);
+  FOREACHvertex_i_(vertices) {
+    if (vertex) {
+      numvertices++;
+      numneighbors = numinf = 0;
+      FOREACHneighbor_(vertex) {
+        if (neighbor->visitid == 0)
+          numinf= 1;
+        else if (neighbor->visitid < numfacets)
+          numneighbors++;
+      }
+      if (numinf && !numneighbors) {
+        SETelem_(vertices, vertex_i)= NULL;
+        numvertices--;
+      }
+    }
+  }
+  if (format == qh_PRINTgeom)
+    qh_fprintf(fp, 9254, "{appearance {+edge -face} OFF %d %d 1 # Voronoi centers and cells\n",
+                numcenters, numvertices);
+  else
+    qh_fprintf(fp, 9255, "%d\n%d %d 1\n", qh hull_dim-1, numcenters, qh_setsize(vertices));
+  if (format == qh_PRINTgeom) {
+    for (k=qh hull_dim-1; k--; )
+      qh_fprintf(fp, 9256, qh_REAL_1, 0.0);
+    qh_fprintf(fp, 9257, " 0 # infinity not used\n");
+  }else {
+    for (k=qh hull_dim-1; k--; )
+      qh_fprintf(fp, 9258, qh_REAL_1, qh_INFINITE);
+    qh_fprintf(fp, 9259, "\n");
+  }
+  FORALLfacet_(facetlist) {
+    if (facet->visitid && facet->visitid < numfacets) {
+      if (format == qh_PRINTgeom)
+        qh_fprintf(fp, 9260, "# %d f%d\n", vid++, facet->id);
+      qh_printcenter(fp, format, NULL, facet);
+    }
+  }
+  FOREACHfacet_(facets) {
+    if (facet->visitid && facet->visitid < numfacets) {
+      if (format == qh_PRINTgeom)
+        qh_fprintf(fp, 9261, "# %d f%d\n", vid++, facet->id);
+      qh_printcenter(fp, format, NULL, facet);
+    }
+  }
+  FOREACHvertex_i_(vertices) {
+    numneighbors= 0;
+    numinf=0;
+    if (vertex) {
+      if (qh hull_dim == 3)
+        qh_order_vertexneighbors(vertex);
+      else if (qh hull_dim >= 4)
+        qsort(SETaddr_(vertex->neighbors, facetT),
+             (size_t)qh_setsize(vertex->neighbors),
+             sizeof(facetT *), qh_compare_facetvisit);
+      FOREACHneighbor_(vertex) {
+        if (neighbor->visitid == 0)
+          numinf= 1;
+        else if (neighbor->visitid < numfacets)
+          numneighbors++;
+      }
+    }
+    if (format == qh_PRINTgeom) {
+      if (vertex) {
+        qh_fprintf(fp, 9262, "%d", numneighbors);
+        FOREACHneighbor_(vertex) {
+          if (neighbor->visitid && neighbor->visitid < numfacets)
+            qh_fprintf(fp, 9263, " %d", neighbor->visitid);
+        }
+        qh_fprintf(fp, 9264, " # p%d(v%d)\n", vertex_i, vertex->id);
+      }else
+        qh_fprintf(fp, 9265, " # p%d is coplanar or isolated\n", vertex_i);
+    }else {
+      if (numinf)
+        numneighbors++;
+      qh_fprintf(fp, 9266, "%d", numneighbors);
+      if (vertex) {
+        FOREACHneighbor_(vertex) {
+          if (neighbor->visitid == 0) {
+            if (numinf) {
+              numinf= 0;
+              qh_fprintf(fp, 9267, " %d", neighbor->visitid);
+            }
+          }else if (neighbor->visitid < numfacets)
+            qh_fprintf(fp, 9268, " %d", neighbor->visitid);
+        }
+      }
+      qh_fprintf(fp, 9269, "\n");
+    }
+  }
+  if (format == qh_PRINTgeom)
+    qh_fprintf(fp, 9270, "}\n");
+  qh_settempfree(&vertices);
+} /* printvoronoi */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printvnorm">-</a>
+
+  qh_printvnorm( fp, vertex, vertexA, centers, unbounded )
+    print one separating plane of the Voronoi diagram for a pair of input sites
+    unbounded==True if centers includes vertex-at-infinity
+
+  assumes:
+    qh_ASvoronoi and qh_vertexneighbors() already set
+
+  note:
+    parameter unbounded is UNUSED by this callback
+
+  see:
+    qh_printvdiagram()
+    qh_eachvoronoi()
+*/
+void qh_printvnorm(FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded) {
+  pointT *normal;
+  realT offset;
+  int k;
+  QHULL_UNUSED(unbounded);
+
+  normal= qh_detvnorm(vertex, vertexA, centers, &offset);
+  qh_fprintf(fp, 9271, "%d %d %d ",
+      2+qh hull_dim, qh_pointid(vertex->point), qh_pointid(vertexA->point));
+  for (k=0; k< qh hull_dim-1; k++)
+    qh_fprintf(fp, 9272, qh_REAL_1, normal[k]);
+  qh_fprintf(fp, 9273, qh_REAL_1, offset);
+  qh_fprintf(fp, 9274, "\n");
+} /* printvnorm */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printvridge">-</a>
+
+  qh_printvridge( fp, vertex, vertexA, centers, unbounded )
+    print one ridge of the Voronoi diagram for a pair of input sites
+    unbounded==True if centers includes vertex-at-infinity
+
+  see:
+    qh_printvdiagram()
+
+  notes:
+    the user may use a different function
+    parameter unbounded is UNUSED
+*/
+void qh_printvridge(FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded) {
+  facetT *facet, **facetp;
+  QHULL_UNUSED(unbounded);
+
+  qh_fprintf(fp, 9275, "%d %d %d", qh_setsize(centers)+2,
+       qh_pointid(vertex->point), qh_pointid(vertexA->point));
+  FOREACHfacet_(centers)
+    qh_fprintf(fp, 9276, " %d", facet->visitid);
+  qh_fprintf(fp, 9277, "\n");
+} /* printvridge */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="projectdim3">-</a>
+
+  qh_projectdim3( source, destination )
+    project 2-d 3-d or 4-d point to a 3-d point
+    uses qh.DROPdim and qh.hull_dim
+    source and destination may be the same
+
+  notes:
+    allocate 4 elements to destination just in case
+*/
+void qh_projectdim3 (pointT *source, pointT *destination) {
+  int i,k;
+
+  for (k=0, i=0; k < qh hull_dim; k++) {
+    if (qh hull_dim == 4) {
+      if (k != qh DROPdim)
+        destination[i++]= source[k];
+    }else if (k == qh DROPdim)
+      destination[i++]= 0;
+    else
+      destination[i++]= source[k];
+  }
+  while (i < 3)
+    destination[i++]= 0.0;
+} /* projectdim3 */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="readfeasible">-</a>
+
+  qh_readfeasible( dim, curline )
+    read feasible point from current line and qh.fin
+
+  returns:
+    number of lines read from qh.fin
+    sets qh.FEASIBLEpoint with malloc'd coordinates
+
+  notes:
+    checks for qh.HALFspace
+    assumes dim > 1
+
+  see:
+    qh_setfeasible
+*/
+int qh_readfeasible(int dim, const char *curline) {
+  boolT isfirst= True;
+  int linecount= 0, tokcount= 0;
+  const char *s;
+  char *t, firstline[qh_MAXfirst+1];
+  coordT *coords, value;
+
+  if (!qh HALFspace) {
+    qh_fprintf(qh ferr, 6070, "qhull input error: feasible point(dim 1 coords) is only valid for halfspace intersection\n");
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  if (qh feasible_string)
+    qh_fprintf(qh ferr, 7057, "qhull input warning: feasible point(dim 1 coords) overrides 'Hn,n,n' feasible point for halfspace intersection\n");
+  if (!(qh feasible_point= (coordT*)qh_malloc(dim* sizeof(coordT)))) {
+    qh_fprintf(qh ferr, 6071, "qhull error: insufficient memory for feasible point\n");
+    qh_errexit(qh_ERRmem, NULL, NULL);
+  }
+  coords= qh feasible_point;
+  while ((s= (isfirst ?  curline : fgets(firstline, qh_MAXfirst, qh fin)))) {
+    if (isfirst)
+      isfirst= False;
+    else
+      linecount++;
+    while (*s) {
+      while (isspace(*s))
+        s++;
+      value= qh_strtod(s, &t);
+      if (s == t)
+        break;
+      s= t;
+      *(coords++)= value;
+      if (++tokcount == dim) {
+        while (isspace(*s))
+          s++;
+        qh_strtod(s, &t);
+        if (s != t) {
+          qh_fprintf(qh ferr, 6072, "qhull input error: coordinates for feasible point do not finish out the line: %s\n",
+               s);
+          qh_errexit(qh_ERRinput, NULL, NULL);
+        }
+        return linecount;
+      }
+    }
+  }
+  qh_fprintf(qh ferr, 6073, "qhull input error: only %d coordinates.  Could not read %d-d feasible point.\n",
+           tokcount, dim);
+  qh_errexit(qh_ERRinput, NULL, NULL);
+  return 0;
+} /* readfeasible */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="readpoints">-</a>
+
+  qh_readpoints( numpoints, dimension, ismalloc )
+    read points from qh.fin into qh.first_point, qh.num_points
+    qh.fin is lines of coordinates, one per vertex, first line number of points
+    if 'rbox D4',
+      gives message
+    if qh.ATinfinity,
+      adds point-at-infinity for Delaunay triangulations
+
+  returns:
+    number of points, array of point coordinates, dimension, ismalloc True
+    if qh.DELAUNAY & !qh.PROJECTinput, projects points to paraboloid
+        and clears qh.PROJECTdelaunay
+    if qh.HALFspace, reads optional feasible point, reads halfspaces,
+        converts to dual.
+
+  for feasible point in "cdd format" in 3-d:
+    3 1
+    coordinates
+    comments
+    begin
+    n 4 real/integer
+    ...
+    end
+
+  notes:
+    dimension will change in qh_initqhull_globals if qh.PROJECTinput
+    uses malloc() since qh_mem not initialized
+    FIXUP QH11012: qh_readpoints needs rewriting, too long
+*/
+coordT *qh_readpoints(int *numpoints, int *dimension, boolT *ismalloc) {
+  coordT *points, *coords, *infinity= NULL;
+  realT paraboloid, maxboloid= -REALmax, value;
+  realT *coordp= NULL, *offsetp= NULL, *normalp= NULL;
+  char *s= 0, *t, firstline[qh_MAXfirst+1];
+  int diminput=0, numinput=0, dimfeasible= 0, newnum, k, tempi;
+  int firsttext=0, firstshort=0, firstlong=0, firstpoint=0;
+  int tokcount= 0, linecount=0, maxcount, coordcount=0;
+  boolT islong, isfirst= True, wasbegin= False;
+  boolT isdelaunay= qh DELAUNAY && !qh PROJECTinput;
+
+  if (qh CDDinput) {
+    while ((s= fgets(firstline, qh_MAXfirst, qh fin))) {
+      linecount++;
+      if (qh HALFspace && linecount == 1 && isdigit(*s)) {
+        dimfeasible= qh_strtol(s, &s);
+        while (isspace(*s))
+          s++;
+        if (qh_strtol(s, &s) == 1)
+          linecount += qh_readfeasible(dimfeasible, s);
+        else
+          dimfeasible= 0;
+      }else if (!memcmp(firstline, "begin", (size_t)5) || !memcmp(firstline, "BEGIN", (size_t)5))
+        break;
+      else if (!*qh rbox_command)
+        strncat(qh rbox_command, s, sizeof(qh rbox_command)-1);
+    }
+    if (!s) {
+      qh_fprintf(qh ferr, 6074, "qhull input error: missing \"begin\" for cdd-formatted input\n");
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+  }
+  while (!numinput && (s= fgets(firstline, qh_MAXfirst, qh fin))) {
+    linecount++;
+    if (!memcmp(s, "begin", (size_t)5) || !memcmp(s, "BEGIN", (size_t)5))
+      wasbegin= True;
+    while (*s) {
+      while (isspace(*s))
+        s++;
+      if (!*s)
+        break;
+      if (!isdigit(*s)) {
+        if (!*qh rbox_command) {
+          strncat(qh rbox_command, s, sizeof(qh rbox_command)-1);
+          firsttext= linecount;
+        }
+        break;
+      }
+      if (!diminput)
+        diminput= qh_strtol(s, &s);
+      else {
+        numinput= qh_strtol(s, &s);
+        if (numinput == 1 && diminput >= 2 && qh HALFspace && !qh CDDinput) {
+          linecount += qh_readfeasible(diminput, s); /* checks if ok */
+          dimfeasible= diminput;
+          diminput= numinput= 0;
+        }else
+          break;
+      }
+    }
+  }
+  if (!s) {
+    qh_fprintf(qh ferr, 6075, "qhull input error: short input file.  Did not find dimension and number of points\n");
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  if (diminput > numinput) {
+    tempi= diminput;    /* exchange dim and n, e.g., for cdd input format */
+    diminput= numinput;
+    numinput= tempi;
+  }
+  if (diminput < 2) {
+    qh_fprintf(qh ferr, 6220,"qhull input error: dimension %d(first number) should be at least 2\n",
+            diminput);
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  if (isdelaunay) {
+    qh PROJECTdelaunay= False;
+    if (qh CDDinput)
+      *dimension= diminput;
+    else
+      *dimension= diminput+1;
+    *numpoints= numinput;
+    if (qh ATinfinity)
+      (*numpoints)++;
+  }else if (qh HALFspace) {
+    *dimension= diminput - 1;
+    *numpoints= numinput;
+    if (diminput < 3) {
+      qh_fprintf(qh ferr, 6221,"qhull input error: dimension %d(first number, includes offset) should be at least 3 for halfspaces\n",
+            diminput);
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+    if (dimfeasible) {
+      if (dimfeasible != *dimension) {
+        qh_fprintf(qh ferr, 6222,"qhull input error: dimension %d of feasible point is not one less than dimension %d for halfspaces\n",
+          dimfeasible, diminput);
+        qh_errexit(qh_ERRinput, NULL, NULL);
+      }
+    }else
+      qh_setfeasible(*dimension);
+  }else {
+    if (qh CDDinput)
+      *dimension= diminput-1;
+    else
+      *dimension= diminput;
+    *numpoints= numinput;
+  }
+  qh normal_size= *dimension * sizeof(coordT); /* for tracing with qh_printpoint */
+  if (qh HALFspace) {
+    qh half_space= coordp= (coordT*)qh_malloc(qh normal_size + sizeof(coordT));
+    if (qh CDDinput) {
+      offsetp= qh half_space;
+      normalp= offsetp + 1;
+    }else {
+      normalp= qh half_space;
+      offsetp= normalp + *dimension;
+    }
+  }
+  qh maxline= diminput * (qh_REALdigits + 5);
+  maximize_(qh maxline, 500);
+  qh line= (char*)qh_malloc((qh maxline+1) * sizeof(char));
+  *ismalloc= True;  /* use malloc since memory not setup */
+  coords= points= qh temp_malloc=
+        (coordT*)qh_malloc((*numpoints)*(*dimension)*sizeof(coordT));
+  if (!coords || !qh line || (qh HALFspace && !qh half_space)) {
+    qh_fprintf(qh ferr, 6076, "qhull error: insufficient memory to read %d points\n",
+            numinput);
+    qh_errexit(qh_ERRmem, NULL, NULL);
+  }
+  if (isdelaunay && qh ATinfinity) {
+    infinity= points + numinput * (*dimension);
+    for (k= (*dimension) - 1; k--; )
+      infinity[k]= 0.0;
+  }
+  maxcount= numinput * diminput;
+  paraboloid= 0.0;
+  while ((s= (isfirst ?  s : fgets(qh line, qh maxline, qh fin)))) {
+    if (!isfirst) {
+      linecount++;
+      if (*s == 'e' || *s == 'E') {
+        if (!memcmp(s, "end", (size_t)3) || !memcmp(s, "END", (size_t)3)) {
+          if (qh CDDinput )
+            break;
+          else if (wasbegin)
+            qh_fprintf(qh ferr, 7058, "qhull input warning: the input appears to be in cdd format.  If so, use 'Fd'\n");
+        }
+      }
+    }
+    islong= False;
+    while (*s) {
+      while (isspace(*s))
+        s++;
+      value= qh_strtod(s, &t);
+      if (s == t) {
+        if (!*qh rbox_command)
+         strncat(qh rbox_command, s, sizeof(qh rbox_command)-1);
+        if (*s && !firsttext)
+          firsttext= linecount;
+        if (!islong && !firstshort && coordcount)
+          firstshort= linecount;
+        break;
+      }
+      if (!firstpoint)
+        firstpoint= linecount;
+      s= t;
+      if (++tokcount > maxcount)
+        continue;
+      if (qh HALFspace) {
+        if (qh CDDinput)
+          *(coordp++)= -value; /* both coefficients and offset */
+        else
+          *(coordp++)= value;
+      }else {
+        *(coords++)= value;
+        if (qh CDDinput && !coordcount) {
+          if (value != 1.0) {
+            qh_fprintf(qh ferr, 6077, "qhull input error: for cdd format, point at line %d does not start with '1'\n",
+                   linecount);
+            qh_errexit(qh_ERRinput, NULL, NULL);
+          }
+          coords--;
+        }else if (isdelaunay) {
+          paraboloid += value * value;
+          if (qh ATinfinity) {
+            if (qh CDDinput)
+              infinity[coordcount-1] += value;
+            else
+              infinity[coordcount] += value;
+          }
+        }
+      }
+      if (++coordcount == diminput) {
+        coordcount= 0;
+        if (isdelaunay) {
+          *(coords++)= paraboloid;
+          maximize_(maxboloid, paraboloid);
+          paraboloid= 0.0;
+        }else if (qh HALFspace) {
+          if (!qh_sethalfspace(*dimension, coords, &coords, normalp, offsetp, qh feasible_point)) {
+            qh_fprintf(qh ferr, 8048, "The halfspace was on line %d\n", linecount);
+            if (wasbegin)
+              qh_fprintf(qh ferr, 8049, "The input appears to be in cdd format.  If so, you should use option 'Fd'\n");
+            qh_errexit(qh_ERRinput, NULL, NULL);
+          }
+          coordp= qh half_space;
+        }
+        while (isspace(*s))
+          s++;
+        if (*s) {
+          islong= True;
+          if (!firstlong)
+            firstlong= linecount;
+        }
+      }
+    }
+    if (!islong && !firstshort && coordcount)
+      firstshort= linecount;
+    if (!isfirst && s - qh line >= qh maxline) {
+      qh_fprintf(qh ferr, 6078, "qhull input error: line %d contained more than %d characters\n",
+              linecount, (int) (s - qh line));   /* WARN64 */
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+    isfirst= False;
+  }
+  if (tokcount != maxcount) {
+    newnum= fmin_(numinput, tokcount/diminput);
+    qh_fprintf(qh ferr, 7073,"\
+qhull warning: instead of %d %d-dimensional points, input contains\n\
+%d points and %d extra coordinates.  Line %d is the first\npoint",
+       numinput, diminput, tokcount/diminput, tokcount % diminput, firstpoint);
+    if (firsttext)
+      qh_fprintf(qh ferr, 8051, ", line %d is the first comment", firsttext);
+    if (firstshort)
+      qh_fprintf(qh ferr, 8052, ", line %d is the first short\nline", firstshort);
+    if (firstlong)
+      qh_fprintf(qh ferr, 8053, ", line %d is the first long line", firstlong);
+    qh_fprintf(qh ferr, 8054, ".  Continue with %d points.\n", newnum);
+    numinput= newnum;
+    if (isdelaunay && qh ATinfinity) {
+      for (k= tokcount % diminput; k--; )
+        infinity[k] -= *(--coords);
+      *numpoints= newnum+1;
+    }else {
+      coords -= tokcount % diminput;
+      *numpoints= newnum;
+    }
+  }
+  if (isdelaunay && qh ATinfinity) {
+    for (k= (*dimension) -1; k--; )
+      infinity[k] /= numinput;
+    if (coords == infinity)
+      coords += (*dimension) -1;
+    else {
+      for (k=0; k < (*dimension) -1; k++)
+        *(coords++)= infinity[k];
+    }
+    *(coords++)= maxboloid * 1.1;
+  }
+  if (qh rbox_command[0]) {
+    qh rbox_command[strlen(qh rbox_command)-1]= '\0';
+    if (!strcmp(qh rbox_command, "./rbox D4"))
+      qh_fprintf(qh ferr, 8055, "\n\
+This is the qhull test case.  If any errors or core dumps occur,\n\
+recompile qhull with 'make new'.  If errors still occur, there is\n\
+an incompatibility.  You should try a different compiler.  You can also\n\
+change the choices in user.h.  If you discover the source of the problem,\n\
+please send mail to qhull_bug at qhull.org.\n\
+\n\
+Type 'qhull' for a short list of options.\n");
+  }
+  qh_free(qh line);
+  qh line= NULL;
+  if (qh half_space) {
+    qh_free(qh half_space);
+    qh half_space= NULL;
+  }
+  qh temp_malloc= NULL;
+  trace1((qh ferr, 1008,"qh_readpoints: read in %d %d-dimensional points\n",
+          numinput, diminput));
+  return(points);
+} /* readpoints */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="setfeasible">-</a>
+
+  qh_setfeasible( dim )
+    set qh.FEASIBLEpoint from qh.feasible_string in "n,n,n" or "n n n" format
+
+  notes:
+    "n,n,n" already checked by qh_initflags()
+    see qh_readfeasible()
+*/
+void qh_setfeasible(int dim) {
+  int tokcount= 0;
+  char *s;
+  coordT *coords, value;
+
+  if (!(s= qh feasible_string)) {
+    qh_fprintf(qh ferr, 6223, "\
+qhull input error: halfspace intersection needs a feasible point.\n\
+Either prepend the input with 1 point or use 'Hn,n,n'.  See manual.\n");
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  if (!(qh feasible_point= (pointT*)qh_malloc(dim * sizeof(coordT)))) {
+    qh_fprintf(qh ferr, 6079, "qhull error: insufficient memory for 'Hn,n,n'\n");
+    qh_errexit(qh_ERRmem, NULL, NULL);
+  }
+  coords= qh feasible_point;
+  while (*s) {
+    value= qh_strtod(s, &s);
+    if (++tokcount > dim) {
+      qh_fprintf(qh ferr, 7059, "qhull input warning: more coordinates for 'H%s' than dimension %d\n",
+          qh feasible_string, dim);
+      break;
+    }
+    *(coords++)= value;
+    if (*s)
+      s++;
+  }
+  while (++tokcount <= dim)
+    *(coords++)= 0.0;
+} /* setfeasible */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="skipfacet">-</a>
+
+  qh_skipfacet( facet )
+    returns 'True' if this facet is not to be printed
+
+  notes:
+    based on the user provided slice thresholds and 'good' specifications
+*/
+boolT qh_skipfacet(facetT *facet) {
+  facetT *neighbor, **neighborp;
+
+  if (qh PRINTneighbors) {
+    if (facet->good)
+      return !qh PRINTgood;
+    FOREACHneighbor_(facet) {
+      if (neighbor->good)
+        return False;
+    }
+    return True;
+  }else if (qh PRINTgood)
+    return !facet->good;
+  else if (!facet->normal)
+    return True;
+  return(!qh_inthresholds(facet->normal, NULL));
+} /* skipfacet */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="skipfilename">-</a>
+
+  qh_skipfilename( string )
+    returns pointer to character after filename
+
+  notes:
+    skips leading spaces
+    ends with spacing or eol
+    if starts with ' or " ends with the same, skipping \' or \"
+    For qhull, qh_argv_to_command() only uses double quotes
+*/
+char *qh_skipfilename(char *filename) {
+  char *s= filename;  /* non-const due to return */
+  char c;
+
+  while (*s && isspace(*s))
+    s++;
+  c= *s++;
+  if (c == '\0') {
+    qh_fprintf(qh ferr, 6204, "qhull input error: filename expected, none found.\n");
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  if (c == '\'' || c == '"') {
+    while (*s !=c || s[-1] == '\\') {
+      if (!*s) {
+        qh_fprintf(qh ferr, 6203, "qhull input error: missing quote after filename -- %s\n", filename);
+        qh_errexit(qh_ERRinput, NULL, NULL);
+      }
+      s++;
+    }
+    s++;
+  }
+  else while (*s && !isspace(*s))
+      s++;
+  return s;
+} /* skipfilename */
+
diff --git a/alg/libqhull/io.h b/alg/libqhull/io.h
new file mode 100644
index 0000000..580d51b
--- /dev/null
+++ b/alg/libqhull/io.h
@@ -0,0 +1,159 @@
+/*<html><pre>  -<a                             href="qh-io.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   io.h
+   declarations of Input/Output functions
+
+   see README, libqhull.h and io.c
+
+   Copyright (c) 1993-2012 The Geometry Center.
+   $Id: //main/2011/qhull/src/libqhull/io.h#3 $$Change: 1464 $
+   $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+*/
+
+#ifndef qhDEFio
+#define qhDEFio 1
+
+#include "libqhull.h"
+
+/*============ constants and flags ==================*/
+
+/*-<a                             href="qh-io.htm#TOC"
+  >--------------------------------</a><a name="qh_MAXfirst">-</a>
+
+  qh_MAXfirst
+    maximum length of first two lines of stdin
+*/
+#define qh_MAXfirst  200
+
+/*-<a                             href="qh-io.htm#TOC"
+  >--------------------------------</a><a name="qh_MINradius">-</a>
+
+  qh_MINradius
+    min radius for Gp and Gv, fraction of maxcoord
+*/
+#define qh_MINradius 0.02
+
+/*-<a                             href="qh-io.htm#TOC"
+  >--------------------------------</a><a name="qh_GEOMepsilon">-</a>
+
+  qh_GEOMepsilon
+    adjust outer planes for 'lines closer' and geomview roundoff.
+    This prevents bleed through.
+*/
+#define qh_GEOMepsilon 2e-3
+
+/*-<a                             href="qh-io.htm#TOC"
+  >--------------------------------</a><a name="qh_WHITESPACE">-</a>
+
+  qh_WHITESPACE
+    possible values of white space
+*/
+#define qh_WHITESPACE " \n\t\v\r\f"
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >--------------------------------</a><a name="RIDGE">-</a>
+
+  qh_RIDGE
+    to select which ridges to print in qh_eachvoronoi
+*/
+typedef enum
+{
+    qh_RIDGEall = 0, qh_RIDGEinner, qh_RIDGEouter
+}
+qh_RIDGE;
+
+/*-<a                             href="qh-io.htm#TOC"
+  >--------------------------------</a><a name="printvridgeT">-</a>
+
+  printvridgeT
+    prints results of qh_printvdiagram
+
+  see:
+    <a href="io.c#printvridge">qh_printvridge</a> for an example
+*/
+typedef void (*printvridgeT)(FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
+
+/*============== -prototypes in alphabetical order =========*/
+
+void    dfacet(unsigned id);
+void    dvertex(unsigned id);
+int     qh_compare_facetarea(const void *p1, const void *p2);
+int     qh_compare_facetmerge(const void *p1, const void *p2);
+int     qh_compare_facetvisit(const void *p1, const void *p2);
+int     qh_compare_vertexpoint(const void *p1, const void *p2); /* not used */
+void    qh_copyfilename(char *filename, int size, const char* source, int length);
+void    qh_countfacets(facetT *facetlist, setT *facets, boolT printall,
+              int *numfacetsp, int *numsimplicialp, int *totneighborsp,
+              int *numridgesp, int *numcoplanarsp, int *numnumtricoplanarsp);
+pointT *qh_detvnorm(vertexT *vertex, vertexT *vertexA, setT *centers, realT *offsetp);
+setT   *qh_detvridge(vertexT *vertex);
+setT   *qh_detvridge3 (vertexT *atvertex, vertexT *vertex);
+int     qh_eachvoronoi(FILE *fp, printvridgeT printvridge, vertexT *atvertex, boolT visitall, qh_RIDGE innerouter, boolT inorder);
+int     qh_eachvoronoi_all(FILE *fp, printvridgeT printvridge, boolT isUpper, qh_RIDGE innerouter, boolT inorder);
+void    qh_facet2point(facetT *facet, pointT **point0, pointT **point1, realT *mindist);
+setT   *qh_facetvertices(facetT *facetlist, setT *facets, boolT allfacets);
+void    qh_geomplanes(facetT *facet, realT *outerplane, realT *innerplane);
+void    qh_markkeep(facetT *facetlist);
+setT   *qh_markvoronoi(facetT *facetlist, setT *facets, boolT printall, boolT *isLowerp, int *numcentersp);
+void    qh_order_vertexneighbors(vertexT *vertex);
+void    qh_prepare_output(void);
+void    qh_printafacet(FILE *fp, qh_PRINT format, facetT *facet, boolT printall);
+void    qh_printbegin(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall);
+void    qh_printcenter(FILE *fp, qh_PRINT format, const char *string, facetT *facet);
+void    qh_printcentrum(FILE *fp, facetT *facet, realT radius);
+void    qh_printend(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall);
+void    qh_printend4geom(FILE *fp, facetT *facet, int *num, boolT printall);
+void    qh_printextremes(FILE *fp, facetT *facetlist, setT *facets, boolT printall);
+void    qh_printextremes_2d(FILE *fp, facetT *facetlist, setT *facets, boolT printall);
+void    qh_printextremes_d(FILE *fp, facetT *facetlist, setT *facets, boolT printall);
+void    qh_printfacet(FILE *fp, facetT *facet);
+void    qh_printfacet2math(FILE *fp, facetT *facet, qh_PRINT format, int notfirst);
+void    qh_printfacet2geom(FILE *fp, facetT *facet, realT color[3]);
+void    qh_printfacet2geom_points(FILE *fp, pointT *point1, pointT *point2,
+                               facetT *facet, realT offset, realT color[3]);
+void    qh_printfacet3math(FILE *fp, facetT *facet, qh_PRINT format, int notfirst);
+void    qh_printfacet3geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]);
+void    qh_printfacet3geom_points(FILE *fp, setT *points, facetT *facet, realT offset, realT color[3]);
+void    qh_printfacet3geom_simplicial(FILE *fp, facetT *facet, realT color[3]);
+void    qh_printfacet3vertex(FILE *fp, facetT *facet, qh_PRINT format);
+void    qh_printfacet4geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]);
+void    qh_printfacet4geom_simplicial(FILE *fp, facetT *facet, realT color[3]);
+void    qh_printfacetNvertex_nonsimplicial(FILE *fp, facetT *facet, int id, qh_PRINT format);
+void    qh_printfacetNvertex_simplicial(FILE *fp, facetT *facet, qh_PRINT format);
+void    qh_printfacetheader(FILE *fp, facetT *facet);
+void    qh_printfacetridges(FILE *fp, facetT *facet);
+void    qh_printfacets(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall);
+void    qh_printhyperplaneintersection(FILE *fp, facetT *facet1, facetT *facet2,
+                   setT *vertices, realT color[3]);
+void    qh_printneighborhood(FILE *fp, qh_PRINT format, facetT *facetA, facetT *facetB, boolT printall);
+void    qh_printline3geom(FILE *fp, pointT *pointA, pointT *pointB, realT color[3]);
+void    qh_printpoint(FILE *fp, const char *string, pointT *point);
+void    qh_printpointid(FILE *fp, const char *string, int dim, pointT *point, int id);
+void    qh_printpoint3 (FILE *fp, pointT *point);
+void    qh_printpoints_out(FILE *fp, facetT *facetlist, setT *facets, boolT printall);
+void    qh_printpointvect(FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius, realT color[3]);
+void    qh_printpointvect2 (FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius);
+void    qh_printridge(FILE *fp, ridgeT *ridge);
+void    qh_printspheres(FILE *fp, setT *vertices, realT radius);
+void    qh_printvdiagram(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall);
+int     qh_printvdiagram2 (FILE *fp, printvridgeT printvridge, setT *vertices, qh_RIDGE innerouter, boolT inorder);
+void    qh_printvertex(FILE *fp, vertexT *vertex);
+void    qh_printvertexlist(FILE *fp, const char* string, facetT *facetlist,
+                         setT *facets, boolT printall);
+void    qh_printvertices(FILE *fp, const char* string, setT *vertices);
+void    qh_printvneighbors(FILE *fp, facetT* facetlist, setT *facets, boolT printall);
+void    qh_printvoronoi(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall);
+void    qh_printvnorm(FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
+void    qh_printvridge(FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
+void    qh_produce_output(void);
+void    qh_produce_output2(void);
+void    qh_projectdim3 (pointT *source, pointT *destination);
+int     qh_readfeasible(int dim, const char *curline);
+coordT *qh_readpoints(int *numpoints, int *dimension, boolT *ismalloc);
+void    qh_setfeasible(int dim);
+boolT   qh_skipfacet(facetT *facet);
+char   *qh_skipfilename(char *filename);
+
+#endif /* qhDEFio */
diff --git a/alg/libqhull/libqhull.c b/alg/libqhull/libqhull.c
new file mode 100644
index 0000000..e9a14dc
--- /dev/null
+++ b/alg/libqhull/libqhull.c
@@ -0,0 +1,1401 @@
+/*<html><pre>  -<a                             href="qh-qhull.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   libqhull.c
+   Quickhull algorithm for convex hulls
+
+   qhull() and top-level routines
+
+   see qh-qhull.htm, libqhull.h, unix.c
+
+   see qhull_a.h for internal functions
+
+   Copyright (c) 1993-2012 The Geometry Center.
+   $Id: //main/2011/qhull/src/libqhull/libqhull.c#4 $$Change: 1464 $
+   $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+*/
+
+#include "qhull_a.h"
+
+/*============= functions in alphabetic order after qhull() =======*/
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >-------------------------------</a><a name="qhull">-</a>
+
+  qh_qhull()
+    compute DIM3 convex hull of qh.num_points starting at qh.first_point
+    qh contains all global options and variables
+
+  returns:
+    returns polyhedron
+      qh.facet_list, qh.num_facets, qh.vertex_list, qh.num_vertices,
+
+    returns global variables
+      qh.hulltime, qh.max_outside, qh.interior_point, qh.max_vertex, qh.min_vertex
+
+    returns precision constants
+      qh.ANGLEround, centrum_radius, cos_max, DISTround, MAXabs_coord, ONEmerge
+
+  notes:
+    unless needed for output
+      qh.max_vertex and qh.min_vertex are max/min due to merges
+
+  see:
+    to add individual points to either qh.num_points
+      use qh_addpoint()
+
+    if qh.GETarea
+      qh_produceoutput() returns qh.totarea and qh.totvol via qh_getarea()
+
+  design:
+    record starting time
+    initialize hull and partition points
+    build convex hull
+    unless early termination
+      update facet->maxoutside for vertices, coplanar, and near-inside points
+    error if temporary sets exist
+    record end time
+*/
+
+void qh_qhull(void) {
+  int numoutside;
+
+  qh hulltime= qh_CPUclock;
+  if (qh RERUN || qh JOGGLEmax < REALmax/2)
+    qh_build_withrestart();
+  else {
+    qh_initbuild();
+    qh_buildhull();
+  }
+  if (!qh STOPpoint && !qh STOPcone) {
+    if (qh ZEROall_ok && !qh TESTvneighbors && qh MERGEexact)
+      qh_checkzero( qh_ALL);
+    if (qh ZEROall_ok && !qh TESTvneighbors && !qh WAScoplanar) {
+      trace2((qh ferr, 2055, "qh_qhull: all facets are clearly convex and no coplanar points.  Post-merging and check of maxout not needed.\n"));
+      qh DOcheckmax= False;
+    }else {
+      if (qh MERGEexact || (qh hull_dim > qh_DIMreduceBuild && qh PREmerge))
+        qh_postmerge("First post-merge", qh premerge_centrum, qh premerge_cos,
+             (qh POSTmerge ? False : qh TESTvneighbors));
+      else if (!qh POSTmerge && qh TESTvneighbors)
+        qh_postmerge("For testing vertex neighbors", qh premerge_centrum,
+             qh premerge_cos, True);
+      if (qh POSTmerge)
+        qh_postmerge("For post-merging", qh postmerge_centrum,
+             qh postmerge_cos, qh TESTvneighbors);
+      if (qh visible_list == qh facet_list) { /* i.e., merging done */
+        qh findbestnew= True;
+        qh_partitionvisible(/*visible_list, newfacet_list*/ !qh_ALL, &numoutside);
+        qh findbestnew= False;
+        qh_deletevisible(/*qh visible_list*/);
+        qh_resetlists(False, qh_RESETvisible /*qh visible_list newvertex_list newfacet_list */);
+      }
+    }
+    if (qh DOcheckmax){
+      if (qh REPORTfreq) {
+        qh_buildtracing(NULL, NULL);
+        qh_fprintf(qh ferr, 8115, "\nTesting all coplanar points.\n");
+      }
+      qh_check_maxout();
+    }
+    if (qh KEEPnearinside && !qh maxoutdone)
+      qh_nearcoplanar();
+  }
+  if (qh_setsize(qhmem.tempstack) != 0) {
+    qh_fprintf(qh ferr, 6164, "qhull internal error (qh_qhull): temporary sets not empty(%d)\n",
+             qh_setsize(qhmem.tempstack));
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  qh hulltime= qh_CPUclock - qh hulltime;
+  qh QHULLfinished= True;
+  trace1((qh ferr, 1036, "Qhull: algorithm completed\n"));
+} /* qhull */
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >-------------------------------</a><a name="addpoint">-</a>
+
+  qh_addpoint( furthest, facet, checkdist )
+    add point (usually furthest point) above facet to hull
+    if checkdist,
+      check that point is above facet.
+      if point is not outside of the hull, uses qh_partitioncoplanar()
+      assumes that facet is defined by qh_findbestfacet()
+    else if facet specified,
+      assumes that point is above facet (major damage if below)
+    for Delaunay triangulations,
+      Use qh_setdelaunay() to lift point to paraboloid and scale by 'Qbb' if needed
+      Do not use options 'Qbk', 'QBk', or 'QbB' since they scale the coordinates.
+
+  returns:
+    returns False if user requested an early termination
+     qh.visible_list, newfacet_list, delvertex_list, NEWfacets may be defined
+    updates qh.facet_list, qh.num_facets, qh.vertex_list, qh.num_vertices
+    clear qh.maxoutdone (will need to call qh_check_maxout() for facet->maxoutside)
+    if unknown point, adds a pointer to qh.other_points
+      do not deallocate the point's coordinates
+
+  notes:
+    assumes point is near its best facet and not at a local minimum of a lens
+      distributions.  Use qh_findbestfacet to avoid this case.
+    uses qh.visible_list, qh.newfacet_list, qh.delvertex_list, qh.NEWfacets
+
+  see also:
+    qh_triangulate() -- triangulate non-simplicial facets
+
+  design:
+    add point to other_points if needed
+    if checkdist
+      if point not above facet
+        partition coplanar point
+        exit
+    exit if pre STOPpoint requested
+    find horizon and visible facets for point
+    make new facets for point to horizon
+    make hyperplanes for point
+    compute balance statistics
+    match neighboring new facets
+    update vertex neighbors and delete interior vertices
+    exit if STOPcone requested
+    merge non-convex new facets
+    if merge found, many merges, or 'Qf'
+       use qh_findbestnew() instead of qh_findbest()
+    partition outside points from visible facets
+    delete visible facets
+    check polyhedron if requested
+    exit if post STOPpoint requested
+    reset working lists of facets and vertices
+*/
+boolT qh_addpoint(pointT *furthest, facetT *facet, boolT checkdist) {
+  int goodvisible, goodhorizon;
+  vertexT *vertex;
+  facetT *newfacet;
+  realT dist, newbalance, pbalance;
+  boolT isoutside= False;
+  int numpart, numpoints, numnew, firstnew;
+
+  qh maxoutdone= False;
+  if (qh_pointid(furthest) == -1)
+    qh_setappend(&qh other_points, furthest);
+  if (!facet) {
+    qh_fprintf(qh ferr, 6213, "qhull internal error (qh_addpoint): NULL facet.  Need to call qh_findbestfacet first\n");
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  if (checkdist) {
+    facet= qh_findbest(furthest, facet, !qh_ALL, !qh_ISnewfacets, !qh_NOupper,
+                        &dist, &isoutside, &numpart);
+    zzadd_(Zpartition, numpart);
+    if (!isoutside) {
+      zinc_(Znotmax);  /* last point of outsideset is no longer furthest. */
+      facet->notfurthest= True;
+      qh_partitioncoplanar(furthest, facet, &dist);
+      return True;
+    }
+  }
+  qh_buildtracing(furthest, facet);
+  if (qh STOPpoint < 0 && qh furthest_id == -qh STOPpoint-1) {
+    facet->notfurthest= True;
+    return False;
+  }
+  qh_findhorizon(furthest, facet, &goodvisible, &goodhorizon);
+  if (qh ONLYgood && !(goodvisible+goodhorizon) && !qh GOODclosest) {
+    zinc_(Znotgood);
+    facet->notfurthest= True;
+    /* last point of outsideset is no longer furthest.  This is ok
+       since all points of the outside are likely to be bad */
+    qh_resetlists(False, qh_RESETvisible /*qh visible_list newvertex_list newfacet_list */);
+    return True;
+  }
+  zzinc_(Zprocessed);
+  firstnew= qh facet_id;
+  vertex= qh_makenewfacets(furthest /*visible_list, attaches if !ONLYgood */);
+  qh_makenewplanes(/* newfacet_list */);
+  numnew= qh facet_id - firstnew;
+  newbalance= numnew - (realT) (qh num_facets-qh num_visible)
+                         * qh hull_dim/qh num_vertices;
+  wadd_(Wnewbalance, newbalance);
+  wadd_(Wnewbalance2, newbalance * newbalance);
+  if (qh ONLYgood
+  && !qh_findgood(qh newfacet_list, goodhorizon) && !qh GOODclosest) {
+    FORALLnew_facets
+      qh_delfacet(newfacet);
+    qh_delvertex(vertex);
+    qh_resetlists(True, qh_RESETvisible /*qh visible_list newvertex_list newfacet_list */);
+    zinc_(Znotgoodnew);
+    facet->notfurthest= True;
+    return True;
+  }
+  if (qh ONLYgood)
+    qh_attachnewfacets(/*visible_list*/);
+  qh_matchnewfacets();
+  qh_updatevertices();
+  if (qh STOPcone && qh furthest_id == qh STOPcone-1) {
+    facet->notfurthest= True;
+    return False;  /* visible_list etc. still defined */
+  }
+  qh findbestnew= False;
+  if (qh PREmerge || qh MERGEexact) {
+    qh_premerge(vertex, qh premerge_centrum, qh premerge_cos);
+    if (qh_USEfindbestnew)
+      qh findbestnew= True;
+    else {
+      FORALLnew_facets {
+        if (!newfacet->simplicial) {
+          qh findbestnew= True;  /* use qh_findbestnew instead of qh_findbest*/
+          break;
+        }
+      }
+    }
+  }else if (qh BESToutside)
+    qh findbestnew= True;
+  qh_partitionvisible(/*visible_list, newfacet_list*/ !qh_ALL, &numpoints);
+  qh findbestnew= False;
+  qh findbest_notsharp= False;
+  zinc_(Zpbalance);
+  pbalance= numpoints - (realT) qh hull_dim /* assumes all points extreme */
+                * (qh num_points - qh num_vertices)/qh num_vertices;
+  wadd_(Wpbalance, pbalance);
+  wadd_(Wpbalance2, pbalance * pbalance);
+  qh_deletevisible(/*qh visible_list*/);
+  zmax_(Zmaxvertex, qh num_vertices);
+  qh NEWfacets= False;
+  if (qh IStracing >= 4) {
+    if (qh num_facets < 2000)
+      qh_printlists();
+    qh_printfacetlist(qh newfacet_list, NULL, True);
+    qh_checkpolygon(qh facet_list);
+  }else if (qh CHECKfrequently) {
+    if (qh num_facets < 50)
+      qh_checkpolygon(qh facet_list);
+    else
+      qh_checkpolygon(qh newfacet_list);
+  }
+  if (qh STOPpoint > 0 && qh furthest_id == qh STOPpoint-1)
+    return False;
+  qh_resetlists(True, qh_RESETvisible /*qh visible_list newvertex_list newfacet_list */);
+  /* qh_triangulate(); to test qh.TRInormals */
+  trace2((qh ferr, 2056, "qh_addpoint: added p%d new facets %d new balance %2.2g point balance %2.2g\n",
+    qh_pointid(furthest), numnew, newbalance, pbalance));
+  return True;
+} /* addpoint */
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >-------------------------------</a><a name="build_withrestart">-</a>
+
+  qh_build_withrestart()
+    allow restarts due to qh.JOGGLEmax while calling qh_buildhull()
+    qh.FIRSTpoint/qh.NUMpoints is point array
+        it may be moved by qh_joggleinput()
+*/
+void qh_build_withrestart(void) {
+  int restart;
+
+  qh ALLOWrestart= True;
+  while (True) {
+    restart= setjmp(qh restartexit); /* simple statement for CRAY J916 */
+    if (restart) {       /* only from qh_precision() */
+      zzinc_(Zretry);
+      wmax_(Wretrymax, qh JOGGLEmax);
+      /* QH7078 warns about using 'TCn' with 'QJn' */
+      qh STOPcone= -1; /* if break from joggle, prevents normal output */
+    }
+    if (!qh RERUN && qh JOGGLEmax < REALmax/2) {
+      if (qh build_cnt > qh_JOGGLEmaxretry) {
+        qh_fprintf(qh ferr, 6229, "qhull precision error: %d attempts to construct a convex hull\n\
+        with joggled input.  Increase joggle above 'QJ%2.2g'\n\
+        or modify qh_JOGGLE... parameters in user.h\n",
+           qh build_cnt, qh JOGGLEmax);
+        qh_errexit(qh_ERRqhull, NULL, NULL);
+      }
+      if (qh build_cnt && !restart)
+        break;
+    }else if (qh build_cnt && qh build_cnt >= qh RERUN)
+      break;
+    qh STOPcone= 0;
+    qh_freebuild(True);  /* first call is a nop */
+    qh build_cnt++;
+    if (!qh qhull_optionsiz)
+      qh qhull_optionsiz= (int)strlen(qh qhull_options);   /* WARN64 */
+    else {
+      qh qhull_options [qh qhull_optionsiz]= '\0';
+      qh qhull_optionlen= qh_OPTIONline;  /* starts a new line */
+    }
+    qh_option("_run", &qh build_cnt, NULL);
+    if (qh build_cnt == qh RERUN) {
+      qh IStracing= qh TRACElastrun;  /* duplicated from qh_initqhull_globals */
+      if (qh TRACEpoint != -1 || qh TRACEdist < REALmax/2 || qh TRACEmerge) {
+        qh TRACElevel= (qh IStracing? qh IStracing : 3);
+        qh IStracing= 0;
+      }
+      qhmem.IStracing= qh IStracing;
+    }
+    if (qh JOGGLEmax < REALmax/2)
+      qh_joggleinput();
+    qh_initbuild();
+    qh_buildhull();
+    if (qh JOGGLEmax < REALmax/2 && !qh MERGING)
+      qh_checkconvex(qh facet_list, qh_ALGORITHMfault);
+  }
+  qh ALLOWrestart= False;
+} /* qh_build_withrestart */
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >-------------------------------</a><a name="buildhull">-</a>
+
+  qh_buildhull()
+    construct a convex hull by adding outside points one at a time
+
+  returns:
+
+  notes:
+    may be called multiple times
+    checks facet and vertex lists for incorrect flags
+    to recover from STOPcone, call qh_deletevisible and qh_resetlists
+
+  design:
+    check visible facet and newfacet flags
+    check newlist vertex flags and qh.STOPcone/STOPpoint
+    for each facet with a furthest outside point
+      add point to facet
+      exit if qh.STOPcone or qh.STOPpoint requested
+    if qh.NARROWhull for initial simplex
+      partition remaining outside points to coplanar sets
+*/
+void qh_buildhull(void) {
+  facetT *facet;
+  pointT *furthest;
+  vertexT *vertex;
+  int id;
+
+  trace1((qh ferr, 1037, "qh_buildhull: start build hull\n"));
+  FORALLfacets {
+    if (facet->visible || facet->newfacet) {
+      qh_fprintf(qh ferr, 6165, "qhull internal error (qh_buildhull): visible or new facet f%d in facet list\n",
+                   facet->id);
+      qh_errexit(qh_ERRqhull, facet, NULL);
+    }
+  }
+  FORALLvertices {
+    if (vertex->newlist) {
+      qh_fprintf(qh ferr, 6166, "qhull internal error (qh_buildhull): new vertex f%d in vertex list\n",
+                   vertex->id);
+      qh_errprint("ERRONEOUS", NULL, NULL, NULL, vertex);
+      qh_errexit(qh_ERRqhull, NULL, NULL);
+    }
+    id= qh_pointid(vertex->point);
+    if ((qh STOPpoint>0 && id == qh STOPpoint-1) ||
+        (qh STOPpoint<0 && id == -qh STOPpoint-1) ||
+        (qh STOPcone>0 && id == qh STOPcone-1)) {
+      trace1((qh ferr, 1038,"qh_buildhull: stop point or cone P%d in initial hull\n", id));
+      return;
+    }
+  }
+  qh facet_next= qh facet_list;      /* advance facet when processed */
+  while ((furthest= qh_nextfurthest(&facet))) {
+    qh num_outside--;  /* if ONLYmax, furthest may not be outside */
+    if (!qh_addpoint(furthest, facet, qh ONLYmax))
+      break;
+  }
+  if (qh NARROWhull) /* move points from outsideset to coplanarset */
+    qh_outcoplanar( /* facet_list */ );
+  if (qh num_outside && !furthest) {
+    qh_fprintf(qh ferr, 6167, "qhull internal error (qh_buildhull): %d outside points were never processed.\n", qh num_outside);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  trace1((qh ferr, 1039, "qh_buildhull: completed the hull construction\n"));
+} /* buildhull */
+
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >-------------------------------</a><a name="buildtracing">-</a>
+
+  qh_buildtracing( furthest, facet )
+    trace an iteration of qh_buildhull() for furthest point and facet
+    if !furthest, prints progress message
+
+  returns:
+    tracks progress with qh.lastreport
+    updates qh.furthest_id (-3 if furthest is NULL)
+    also resets visit_id, vertext_visit on wrap around
+
+  see:
+    qh_tracemerging()
+
+  design:
+    if !furthest
+      print progress message
+      exit
+    if 'TFn' iteration
+      print progress message
+    else if tracing
+      trace furthest point and facet
+    reset qh.visit_id and qh.vertex_visit if overflow may occur
+    set qh.furthest_id for tracing
+*/
+void qh_buildtracing(pointT *furthest, facetT *facet) {
+  realT dist= 0;
+  float cpu;
+  int total, furthestid;
+  time_t timedata;
+  struct tm *tp;
+  vertexT *vertex;
+
+  qh old_randomdist= qh RANDOMdist;
+  qh RANDOMdist= False;
+  if (!furthest) {
+    time(&timedata);
+    tp= localtime(&timedata);
+    cpu= (float)qh_CPUclock - (float)qh hulltime;
+    cpu /= (float)qh_SECticks;
+    total= zzval_(Ztotmerge) - zzval_(Zcyclehorizon) + zzval_(Zcyclefacettot);
+    qh_fprintf(qh ferr, 8118, "\n\
+At %02d:%02d:%02d & %2.5g CPU secs, qhull has created %d facets and merged %d.\n\
+ The current hull contains %d facets and %d vertices.  Last point was p%d\n",
+      tp->tm_hour, tp->tm_min, tp->tm_sec, cpu, qh facet_id -1,
+      total, qh num_facets, qh num_vertices, qh furthest_id);
+    return;
+  }
+  furthestid= qh_pointid(furthest);
+  if (qh TRACEpoint == furthestid) {
+    qh IStracing= qh TRACElevel;
+    qhmem.IStracing= qh TRACElevel;
+  }else if (qh TRACEpoint != -1 && qh TRACEdist < REALmax/2) {
+    qh IStracing= 0;
+    qhmem.IStracing= 0;
+  }
+  if (qh REPORTfreq && (qh facet_id-1 > qh lastreport+qh REPORTfreq)) {
+    qh lastreport= qh facet_id-1;
+    time(&timedata);
+    tp= localtime(&timedata);
+    cpu= (float)qh_CPUclock - (float)qh hulltime;
+    cpu /= (float)qh_SECticks;
+    total= zzval_(Ztotmerge) - zzval_(Zcyclehorizon) + zzval_(Zcyclefacettot);
+    zinc_(Zdistio);
+    qh_distplane(furthest, facet, &dist);
+    qh_fprintf(qh ferr, 8119, "\n\
+At %02d:%02d:%02d & %2.5g CPU secs, qhull has created %d facets and merged %d.\n\
+ The current hull contains %d facets and %d vertices.  There are %d\n\
+ outside points.  Next is point p%d(v%d), %2.2g above f%d.\n",
+      tp->tm_hour, tp->tm_min, tp->tm_sec, cpu, qh facet_id -1,
+      total, qh num_facets, qh num_vertices, qh num_outside+1,
+      furthestid, qh vertex_id, dist, getid_(facet));
+  }else if (qh IStracing >=1) {
+    cpu= (float)qh_CPUclock - (float)qh hulltime;
+    cpu /= (float)qh_SECticks;
+    qh_distplane(furthest, facet, &dist);
+    qh_fprintf(qh ferr, 8120, "qh_addpoint: add p%d(v%d) to hull of %d facets(%2.2g above f%d) and %d outside at %4.4g CPU secs.  Previous was p%d.\n",
+      furthestid, qh vertex_id, qh num_facets, dist,
+      getid_(facet), qh num_outside+1, cpu, qh furthest_id);
+  }
+  zmax_(Zvisit2max, (int)qh visit_id/2);
+  if (qh visit_id > (unsigned) INT_MAX) {
+    zinc_(Zvisit);
+    qh visit_id= 0;
+    FORALLfacets
+      facet->visitid= 0;
+  }
+  zmax_(Zvvisit2max, (int)qh vertex_visit/2);
+  if (qh vertex_visit > (unsigned) INT_MAX/2) { /* 31 bits */
+    zinc_(Zvvisit);
+    qh vertex_visit= 0;
+    FORALLvertices
+      vertex->visitid= 0;
+  }
+  qh furthest_id= furthestid;
+  qh RANDOMdist= qh old_randomdist;
+} /* buildtracing */
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >-------------------------------</a><a name="errexit2">-</a>
+
+  qh_errexit2( exitcode, facet, otherfacet )
+    return exitcode to system after an error
+    report two facets
+
+  returns:
+    assumes exitcode non-zero
+
+  see:
+    normally use qh_errexit() in user.c(reports a facet and a ridge)
+*/
+void qh_errexit2(int exitcode, facetT *facet, facetT *otherfacet) {
+
+  qh_errprint("ERRONEOUS", facet, otherfacet, NULL, NULL);
+  qh_errexit(exitcode, NULL, NULL);
+} /* errexit2 */
+
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >-------------------------------</a><a name="findhorizon">-</a>
+
+  qh_findhorizon( point, facet, goodvisible, goodhorizon )
+    given a visible facet, find the point's horizon and visible facets
+    for all facets, !facet-visible
+
+  returns:
+    returns qh.visible_list/num_visible with all visible facets
+      marks visible facets with ->visible
+    updates count of good visible and good horizon facets
+    updates qh.max_outside, qh.max_vertex, facet->maxoutside
+
+  see:
+    similar to qh_delpoint()
+
+  design:
+    move facet to qh.visible_list at end of qh.facet_list
+    for all visible facets
+     for each unvisited neighbor of a visible facet
+       compute distance of point to neighbor
+       if point above neighbor
+         move neighbor to end of qh.visible_list
+       else if point is coplanar with neighbor
+         update qh.max_outside, qh.max_vertex, neighbor->maxoutside
+         mark neighbor coplanar (will create a samecycle later)
+         update horizon statistics
+*/
+void qh_findhorizon(pointT *point, facetT *facet, int *goodvisible, int *goodhorizon) {
+  facetT *neighbor, **neighborp, *visible;
+  int numhorizon= 0, coplanar= 0;
+  realT dist;
+
+  trace1((qh ferr, 1040,"qh_findhorizon: find horizon for point p%d facet f%d\n",qh_pointid(point),facet->id));
+  *goodvisible= *goodhorizon= 0;
+  zinc_(Ztotvisible);
+  qh_removefacet(facet);  /* visible_list at end of qh facet_list */
+  qh_appendfacet(facet);
+  qh num_visible= 1;
+  if (facet->good)
+    (*goodvisible)++;
+  qh visible_list= facet;
+  facet->visible= True;
+  facet->f.replace= NULL;
+  if (qh IStracing >=4)
+    qh_errprint("visible", facet, NULL, NULL, NULL);
+  qh visit_id++;
+  FORALLvisible_facets {
+    if (visible->tricoplanar && !qh TRInormals) {
+      qh_fprintf(qh ferr, 6230, "Qhull internal error (qh_findhorizon): does not work for tricoplanar facets.  Use option 'Q11'\n");
+      qh_errexit(qh_ERRqhull, visible, NULL);
+    }
+    visible->visitid= qh visit_id;
+    FOREACHneighbor_(visible) {
+      if (neighbor->visitid == qh visit_id)
+        continue;
+      neighbor->visitid= qh visit_id;
+      zzinc_(Znumvisibility);
+      qh_distplane(point, neighbor, &dist);
+      if (dist > qh MINvisible) {
+        zinc_(Ztotvisible);
+        qh_removefacet(neighbor);  /* append to end of qh visible_list */
+        qh_appendfacet(neighbor);
+        neighbor->visible= True;
+        neighbor->f.replace= NULL;
+        qh num_visible++;
+        if (neighbor->good)
+          (*goodvisible)++;
+        if (qh IStracing >=4)
+          qh_errprint("visible", neighbor, NULL, NULL, NULL);
+      }else {
+        if (dist > - qh MAXcoplanar) {
+          neighbor->coplanar= True;
+          zzinc_(Zcoplanarhorizon);
+          qh_precision("coplanar horizon");
+          coplanar++;
+          if (qh MERGING) {
+            if (dist > 0) {
+              maximize_(qh max_outside, dist);
+              maximize_(qh max_vertex, dist);
+#if qh_MAXoutside
+              maximize_(neighbor->maxoutside, dist);
+#endif
+            }else
+              minimize_(qh min_vertex, dist);  /* due to merge later */
+          }
+          trace2((qh ferr, 2057, "qh_findhorizon: point p%d is coplanar to horizon f%d, dist=%2.7g < qh MINvisible(%2.7g)\n",
+              qh_pointid(point), neighbor->id, dist, qh MINvisible));
+        }else
+          neighbor->coplanar= False;
+        zinc_(Ztothorizon);
+        numhorizon++;
+        if (neighbor->good)
+          (*goodhorizon)++;
+        if (qh IStracing >=4)
+          qh_errprint("horizon", neighbor, NULL, NULL, NULL);
+      }
+    }
+  }
+  if (!numhorizon) {
+    qh_precision("empty horizon");
+    qh_fprintf(qh ferr, 6168, "qhull precision error (qh_findhorizon): empty horizon\n\
+QhullPoint p%d was above all facets.\n", qh_pointid(point));
+    qh_printfacetlist(qh facet_list, NULL, True);
+    qh_errexit(qh_ERRprec, NULL, NULL);
+  }
+  trace1((qh ferr, 1041, "qh_findhorizon: %d horizon facets(good %d), %d visible(good %d), %d coplanar\n",
+       numhorizon, *goodhorizon, qh num_visible, *goodvisible, coplanar));
+  if (qh IStracing >= 4 && qh num_facets < 50)
+    qh_printlists();
+} /* findhorizon */
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >-------------------------------</a><a name="nextfurthest">-</a>
+
+  qh_nextfurthest( visible )
+    returns next furthest point and visible facet for qh_addpoint()
+    starts search at qh.facet_next
+
+  returns:
+    removes furthest point from outside set
+    NULL if none available
+    advances qh.facet_next over facets with empty outside sets
+
+  design:
+    for each facet from qh.facet_next
+      if empty outside set
+        advance qh.facet_next
+      else if qh.NARROWhull
+        determine furthest outside point
+        if furthest point is not outside
+          advance qh.facet_next(point will be coplanar)
+    remove furthest point from outside set
+*/
+pointT *qh_nextfurthest(facetT **visible) {
+  facetT *facet;
+  int size, idx;
+  realT randr, dist;
+  pointT *furthest;
+
+  while ((facet= qh facet_next) != qh facet_tail) {
+    if (!facet->outsideset) {
+      qh facet_next= facet->next;
+      continue;
+    }
+    SETreturnsize_(facet->outsideset, size);
+    if (!size) {
+      qh_setfree(&facet->outsideset);
+      qh facet_next= facet->next;
+      continue;
+    }
+    if (qh NARROWhull) {
+      if (facet->notfurthest)
+        qh_furthestout(facet);
+      furthest= (pointT*)qh_setlast(facet->outsideset);
+#if qh_COMPUTEfurthest
+      qh_distplane(furthest, facet, &dist);
+      zinc_(Zcomputefurthest);
+#else
+      dist= facet->furthestdist;
+#endif
+      if (dist < qh MINoutside) { /* remainder of outside set is coplanar for qh_outcoplanar */
+        qh facet_next= facet->next;
+        continue;
+      }
+    }
+    if (!qh RANDOMoutside && !qh VIRTUALmemory) {
+      if (qh PICKfurthest) {
+        qh_furthestnext(/* qh facet_list */);
+        facet= qh facet_next;
+      }
+      *visible= facet;
+      return((pointT*)qh_setdellast(facet->outsideset));
+    }
+    if (qh RANDOMoutside) {
+      int outcoplanar = 0;
+      if (qh NARROWhull) {
+        FORALLfacets {
+          if (facet == qh facet_next)
+            break;
+          if (facet->outsideset)
+            outcoplanar += qh_setsize( facet->outsideset);
+        }
+      }
+      randr= qh_RANDOMint;
+      randr= randr/(qh_RANDOMmax+1);
+      idx= (int)floor((qh num_outside - outcoplanar) * randr);
+      FORALLfacet_(qh facet_next) {
+        if (facet->outsideset) {
+          SETreturnsize_(facet->outsideset, size);
+          if (!size)
+            qh_setfree(&facet->outsideset);
+          else if (size > idx) {
+            *visible= facet;
+            return((pointT*)qh_setdelnth(facet->outsideset, idx));
+          }else
+            idx -= size;
+        }
+      }
+      qh_fprintf(qh ferr, 6169, "qhull internal error (qh_nextfurthest): num_outside %d is too low\nby at least %d, or a random real %g >= 1.0\n",
+              qh num_outside, idx+1, randr);
+      qh_errexit(qh_ERRqhull, NULL, NULL);
+    }else { /* VIRTUALmemory */
+      facet= qh facet_tail->previous;
+      if (!(furthest= (pointT*)qh_setdellast(facet->outsideset))) {
+        if (facet->outsideset)
+          qh_setfree(&facet->outsideset);
+        qh_removefacet(facet);
+        qh_prependfacet(facet, &qh facet_list);
+        continue;
+      }
+      *visible= facet;
+      return furthest;
+    }
+  }
+  return NULL;
+} /* nextfurthest */
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >-------------------------------</a><a name="partitionall">-</a>
+
+  qh_partitionall( vertices, points, numpoints )
+    partitions all points in points/numpoints to the outsidesets of facets
+    vertices= vertices in qh.facet_list(!partitioned)
+
+  returns:
+    builds facet->outsideset
+    does not partition qh.GOODpoint
+    if qh.ONLYgood && !qh.MERGING,
+      does not partition qh.GOODvertex
+
+  notes:
+    faster if qh.facet_list sorted by anticipated size of outside set
+
+  design:
+    initialize pointset with all points
+    remove vertices from pointset
+    remove qh.GOODpointp from pointset (unless it's qh.STOPcone or qh.STOPpoint)
+    for all facets
+      for all remaining points in pointset
+        compute distance from point to facet
+        if point is outside facet
+          remove point from pointset (by not reappending)
+          update bestpoint
+          append point or old bestpoint to facet's outside set
+      append bestpoint to facet's outside set (furthest)
+    for all points remaining in pointset
+      partition point into facets' outside sets and coplanar sets
+*/
+void qh_partitionall(setT *vertices, pointT *points, int numpoints){
+  setT *pointset;
+  vertexT *vertex, **vertexp;
+  pointT *point, **pointp, *bestpoint;
+  int size, point_i, point_n, point_end, remaining, i, id;
+  facetT *facet;
+  realT bestdist= -REALmax, dist, distoutside;
+
+  trace1((qh ferr, 1042, "qh_partitionall: partition all points into outside sets\n"));
+  pointset= qh_settemp(numpoints);
+  qh num_outside= 0;
+  pointp= SETaddr_(pointset, pointT);
+  for (i=numpoints, point= points; i--; point += qh hull_dim)
+    *(pointp++)= point;
+  qh_settruncate(pointset, numpoints);
+  FOREACHvertex_(vertices) {
+    if ((id= qh_pointid(vertex->point)) >= 0)
+      SETelem_(pointset, id)= NULL;
+  }
+  id= qh_pointid(qh GOODpointp);
+  if (id >=0 && qh STOPcone-1 != id && -qh STOPpoint-1 != id)
+    SETelem_(pointset, id)= NULL;
+  if (qh GOODvertexp && qh ONLYgood && !qh MERGING) { /* matches qhull()*/
+    if ((id= qh_pointid(qh GOODvertexp)) >= 0)
+      SETelem_(pointset, id)= NULL;
+  }
+  if (!qh BESToutside) {  /* matches conditional for qh_partitionpoint below */
+    distoutside= qh_DISToutside; /* multiple of qh.MINoutside & qh.max_outside, see user.h */
+    zval_(Ztotpartition)= qh num_points - qh hull_dim - 1; /*misses GOOD... */
+    remaining= qh num_facets;
+    point_end= numpoints;
+    FORALLfacets {
+      size= point_end/(remaining--) + 100;
+      facet->outsideset= qh_setnew(size);
+      bestpoint= NULL;
+      point_end= 0;
+      FOREACHpoint_i_(pointset) {
+        if (point) {
+          zzinc_(Zpartitionall);
+          qh_distplane(point, facet, &dist);
+          if (dist < distoutside)
+            SETelem_(pointset, point_end++)= point;
+          else {
+            qh num_outside++;
+            if (!bestpoint) {
+              bestpoint= point;
+              bestdist= dist;
+            }else if (dist > bestdist) {
+              qh_setappend(&facet->outsideset, bestpoint);
+              bestpoint= point;
+              bestdist= dist;
+            }else
+              qh_setappend(&facet->outsideset, point);
+          }
+        }
+      }
+      if (bestpoint) {
+        qh_setappend(&facet->outsideset, bestpoint);
+#if !qh_COMPUTEfurthest
+        facet->furthestdist= bestdist;
+#endif
+      }else
+        qh_setfree(&facet->outsideset);
+      qh_settruncate(pointset, point_end);
+    }
+  }
+  /* if !qh BESToutside, pointset contains points not assigned to outsideset */
+  if (qh BESToutside || qh MERGING || qh KEEPcoplanar || qh KEEPinside) {
+    qh findbestnew= True;
+    FOREACHpoint_i_(pointset) {
+      if (point)
+        qh_partitionpoint(point, qh facet_list);
+    }
+    qh findbestnew= False;
+  }
+  zzadd_(Zpartitionall, zzval_(Zpartition));
+  zzval_(Zpartition)= 0;
+  qh_settempfree(&pointset);
+  if (qh IStracing >= 4)
+    qh_printfacetlist(qh facet_list, NULL, True);
+} /* partitionall */
+
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >-------------------------------</a><a name="partitioncoplanar">-</a>
+
+  qh_partitioncoplanar( point, facet, dist )
+    partition coplanar point to a facet
+    dist is distance from point to facet
+    if dist NULL,
+      searches for bestfacet and does nothing if inside
+    if qh.findbestnew set,
+      searches new facets instead of using qh_findbest()
+
+  returns:
+    qh.max_outside updated
+    if qh.KEEPcoplanar or qh.KEEPinside
+      point assigned to best coplanarset
+
+  notes:
+    facet->maxoutside is updated at end by qh_check_maxout
+
+  design:
+    if dist undefined
+      find best facet for point
+      if point sufficiently below facet (depends on qh.NEARinside and qh.KEEPinside)
+        exit
+    if keeping coplanar/nearinside/inside points
+      if point is above furthest coplanar point
+        append point to coplanar set (it is the new furthest)
+        update qh.max_outside
+      else
+        append point one before end of coplanar set
+    else if point is clearly outside of qh.max_outside and bestfacet->coplanarset
+    and bestfacet is more than perpendicular to facet
+      repartition the point using qh_findbest() -- it may be put on an outsideset
+    else
+      update qh.max_outside
+*/
+void qh_partitioncoplanar(pointT *point, facetT *facet, realT *dist) {
+  facetT *bestfacet;
+  pointT *oldfurthest;
+  realT bestdist, dist2= 0, angle;
+  int numpart= 0, oldfindbest;
+  boolT isoutside;
+
+  qh WAScoplanar= True;
+  if (!dist) {
+    if (qh findbestnew)
+      bestfacet= qh_findbestnew(point, facet, &bestdist, qh_ALL, &isoutside, &numpart);
+    else
+      bestfacet= qh_findbest(point, facet, qh_ALL, !qh_ISnewfacets, qh DELAUNAY,
+                          &bestdist, &isoutside, &numpart);
+    zinc_(Ztotpartcoplanar);
+    zzadd_(Zpartcoplanar, numpart);
+    if (!qh DELAUNAY && !qh KEEPinside) { /*  for 'd', bestdist skips upperDelaunay facets */
+      if (qh KEEPnearinside) {
+        if (bestdist < -qh NEARinside) {
+          zinc_(Zcoplanarinside);
+          trace4((qh ferr, 4062, "qh_partitioncoplanar: point p%d is more than near-inside facet f%d dist %2.2g findbestnew %d\n",
+                  qh_pointid(point), bestfacet->id, bestdist, qh findbestnew));
+          return;
+        }
+      }else if (bestdist < -qh MAXcoplanar) {
+          trace4((qh ferr, 4063, "qh_partitioncoplanar: point p%d is inside facet f%d dist %2.2g findbestnew %d\n",
+                  qh_pointid(point), bestfacet->id, bestdist, qh findbestnew));
+        zinc_(Zcoplanarinside);
+        return;
+      }
+    }
+  }else {
+    bestfacet= facet;
+    bestdist= *dist;
+  }
+  if (bestdist > qh max_outside) {
+    if (!dist && facet != bestfacet) {
+      zinc_(Zpartangle);
+      angle= qh_getangle(facet->normal, bestfacet->normal);
+      if (angle < 0) {
+        /* typically due to deleted vertex and coplanar facets, e.g.,
+             RBOX 1000 s Z1 G1e-13 t1001185205 | QHULL Tv */
+        zinc_(Zpartflip);
+        trace2((qh ferr, 2058, "qh_partitioncoplanar: repartition point p%d from f%d.  It is above flipped facet f%d dist %2.2g\n",
+                qh_pointid(point), facet->id, bestfacet->id, bestdist));
+        oldfindbest= qh findbestnew;
+        qh findbestnew= False;
+        qh_partitionpoint(point, bestfacet);
+        qh findbestnew= oldfindbest;
+        return;
+      }
+    }
+    qh max_outside= bestdist;
+    if (bestdist > qh TRACEdist) {
+      qh_fprintf(qh ferr, 8122, "qh_partitioncoplanar: ====== p%d from f%d increases max_outside to %2.2g of f%d last p%d\n",
+                     qh_pointid(point), facet->id, bestdist, bestfacet->id, qh furthest_id);
+      qh_errprint("DISTANT", facet, bestfacet, NULL, NULL);
+    }
+  }
+  if (qh KEEPcoplanar + qh KEEPinside + qh KEEPnearinside) {
+    oldfurthest= (pointT*)qh_setlast(bestfacet->coplanarset);
+    if (oldfurthest) {
+      zinc_(Zcomputefurthest);
+      qh_distplane(oldfurthest, bestfacet, &dist2);
+    }
+    if (!oldfurthest || dist2 < bestdist)
+      qh_setappend(&bestfacet->coplanarset, point);
+    else
+      qh_setappend2ndlast(&bestfacet->coplanarset, point);
+  }
+  trace4((qh ferr, 4064, "qh_partitioncoplanar: point p%d is coplanar with facet f%d(or inside) dist %2.2g\n",
+          qh_pointid(point), bestfacet->id, bestdist));
+} /* partitioncoplanar */
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >-------------------------------</a><a name="partitionpoint">-</a>
+
+  qh_partitionpoint( point, facet )
+    assigns point to an outside set, coplanar set, or inside set (i.e., dropt)
+    if qh.findbestnew
+      uses qh_findbestnew() to search all new facets
+    else
+      uses qh_findbest()
+
+  notes:
+    after qh_distplane(), this and qh_findbest() are most expensive in 3-d
+
+  design:
+    find best facet for point
+      (either exhaustive search of new facets or directed search from facet)
+    if qh.NARROWhull
+      retain coplanar and nearinside points as outside points
+    if point is outside bestfacet
+      if point above furthest point for bestfacet
+        append point to outside set (it becomes the new furthest)
+        if outside set was empty
+          move bestfacet to end of qh.facet_list (i.e., after qh.facet_next)
+        update bestfacet->furthestdist
+      else
+        append point one before end of outside set
+    else if point is coplanar to bestfacet
+      if keeping coplanar points or need to update qh.max_outside
+        partition coplanar point into bestfacet
+    else if near-inside point
+      partition as coplanar point into bestfacet
+    else is an inside point
+      if keeping inside points
+        partition as coplanar point into bestfacet
+*/
+void qh_partitionpoint(pointT *point, facetT *facet) {
+  realT bestdist;
+  boolT isoutside;
+  facetT *bestfacet;
+  int numpart;
+#if qh_COMPUTEfurthest
+  realT dist;
+#endif
+
+  if (qh findbestnew)
+    bestfacet= qh_findbestnew(point, facet, &bestdist, qh BESToutside, &isoutside, &numpart);
+  else
+    bestfacet= qh_findbest(point, facet, qh BESToutside, qh_ISnewfacets, !qh_NOupper,
+                          &bestdist, &isoutside, &numpart);
+  zinc_(Ztotpartition);
+  zzadd_(Zpartition, numpart);
+  if (qh NARROWhull) {
+    if (qh DELAUNAY && !isoutside && bestdist >= -qh MAXcoplanar)
+      qh_precision("nearly incident point(narrow hull)");
+    if (qh KEEPnearinside) {
+      if (bestdist >= -qh NEARinside)
+        isoutside= True;
+    }else if (bestdist >= -qh MAXcoplanar)
+      isoutside= True;
+  }
+
+  if (isoutside) {
+    if (!bestfacet->outsideset
+    || !qh_setlast(bestfacet->outsideset)) {
+      qh_setappend(&(bestfacet->outsideset), point);
+      if (!bestfacet->newfacet) {
+        qh_removefacet(bestfacet);  /* make sure it's after qh facet_next */
+        qh_appendfacet(bestfacet);
+      }
+#if !qh_COMPUTEfurthest
+      bestfacet->furthestdist= bestdist;
+#endif
+    }else {
+#if qh_COMPUTEfurthest
+      zinc_(Zcomputefurthest);
+      qh_distplane(oldfurthest, bestfacet, &dist);
+      if (dist < bestdist)
+        qh_setappend(&(bestfacet->outsideset), point);
+      else
+        qh_setappend2ndlast(&(bestfacet->outsideset), point);
+#else
+      if (bestfacet->furthestdist < bestdist) {
+        qh_setappend(&(bestfacet->outsideset), point);
+        bestfacet->furthestdist= bestdist;
+      }else
+        qh_setappend2ndlast(&(bestfacet->outsideset), point);
+#endif
+    }
+    qh num_outside++;
+    trace4((qh ferr, 4065, "qh_partitionpoint: point p%d is outside facet f%d new? %d (or narrowhull)\n",
+          qh_pointid(point), bestfacet->id, bestfacet->newfacet));
+  }else if (qh DELAUNAY || bestdist >= -qh MAXcoplanar) { /* for 'd', bestdist skips upperDelaunay facets */
+    zzinc_(Zcoplanarpart);
+    if (qh DELAUNAY)
+      qh_precision("nearly incident point");
+    if ((qh KEEPcoplanar + qh KEEPnearinside) || bestdist > qh max_outside)
+      qh_partitioncoplanar(point, bestfacet, &bestdist);
+    else {
+      trace4((qh ferr, 4066, "qh_partitionpoint: point p%d is coplanar to facet f%d (dropped)\n",
+          qh_pointid(point), bestfacet->id));
+    }
+  }else if (qh KEEPnearinside && bestdist > -qh NEARinside) {
+    zinc_(Zpartnear);
+    qh_partitioncoplanar(point, bestfacet, &bestdist);
+  }else {
+    zinc_(Zpartinside);
+    trace4((qh ferr, 4067, "qh_partitionpoint: point p%d is inside all facets, closest to f%d dist %2.2g\n",
+          qh_pointid(point), bestfacet->id, bestdist));
+    if (qh KEEPinside)
+      qh_partitioncoplanar(point, bestfacet, &bestdist);
+  }
+} /* partitionpoint */
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >-------------------------------</a><a name="partitionvisible">-</a>
+
+  qh_partitionvisible( allpoints, numoutside )
+    partitions points in visible facets to qh.newfacet_list
+    qh.visible_list= visible facets
+    for visible facets
+      1st neighbor (if any) points to a horizon facet or a new facet
+    if allpoints(!used),
+      repartitions coplanar points
+
+  returns:
+    updates outside sets and coplanar sets of qh.newfacet_list
+    updates qh.num_outside (count of outside points)
+
+  notes:
+    qh.findbest_notsharp should be clear (extra work if set)
+
+  design:
+    for all visible facets with outside set or coplanar set
+      select a newfacet for visible facet
+      if outside set
+        partition outside set into new facets
+      if coplanar set and keeping coplanar/near-inside/inside points
+        if allpoints
+          partition coplanar set into new facets, may be assigned outside
+        else
+          partition coplanar set into coplanar sets of new facets
+    for each deleted vertex
+      if allpoints
+        partition vertex into new facets, may be assigned outside
+      else
+        partition vertex into coplanar sets of new facets
+*/
+void qh_partitionvisible(/*visible_list*/ boolT allpoints, int *numoutside) {
+  facetT *visible, *newfacet;
+  pointT *point, **pointp;
+  int coplanar=0, size;
+  unsigned count;
+  vertexT *vertex, **vertexp;
+
+  if (qh ONLYmax)
+    maximize_(qh MINoutside, qh max_vertex);
+  *numoutside= 0;
+  FORALLvisible_facets {
+    if (!visible->outsideset && !visible->coplanarset)
+      continue;
+    newfacet= visible->f.replace;
+    count= 0;
+    while (newfacet && newfacet->visible) {
+      newfacet= newfacet->f.replace;
+      if (count++ > qh facet_id)
+        qh_infiniteloop(visible);
+    }
+    if (!newfacet)
+      newfacet= qh newfacet_list;
+    if (newfacet == qh facet_tail) {
+      qh_fprintf(qh ferr, 6170, "qhull precision error (qh_partitionvisible): all new facets deleted as\n        degenerate facets. Can not continue.\n");
+      qh_errexit(qh_ERRprec, NULL, NULL);
+    }
+    if (visible->outsideset) {
+      size= qh_setsize(visible->outsideset);
+      *numoutside += size;
+      qh num_outside -= size;
+      FOREACHpoint_(visible->outsideset)
+        qh_partitionpoint(point, newfacet);
+    }
+    if (visible->coplanarset && (qh KEEPcoplanar + qh KEEPinside + qh KEEPnearinside)) {
+      size= qh_setsize(visible->coplanarset);
+      coplanar += size;
+      FOREACHpoint_(visible->coplanarset) {
+        if (allpoints) /* not used */
+          qh_partitionpoint(point, newfacet);
+        else
+          qh_partitioncoplanar(point, newfacet, NULL);
+      }
+    }
+  }
+  FOREACHvertex_(qh del_vertices) {
+    if (vertex->point) {
+      if (allpoints) /* not used */
+        qh_partitionpoint(vertex->point, qh newfacet_list);
+      else
+        qh_partitioncoplanar(vertex->point, qh newfacet_list, NULL);
+    }
+  }
+  trace1((qh ferr, 1043,"qh_partitionvisible: partitioned %d points from outsidesets and %d points from coplanarsets\n", *numoutside, coplanar));
+} /* partitionvisible */
+
+
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >-------------------------------</a><a name="precision">-</a>
+
+  qh_precision( reason )
+    restart on precision errors if not merging and if 'QJn'
+*/
+void qh_precision(const char *reason) {
+
+  if (qh ALLOWrestart && !qh PREmerge && !qh MERGEexact) {
+    if (qh JOGGLEmax < REALmax/2) {
+      trace0((qh ferr, 26, "qh_precision: qhull restart because of %s\n", reason));
+      longjmp(qh restartexit, qh_ERRprec);
+    }
+  }
+} /* qh_precision */
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >-------------------------------</a><a name="printsummary">-</a>
+
+  qh_printsummary( fp )
+    prints summary to fp
+
+  notes:
+    not in io.c so that user_eg.c can prevent io.c from loading
+    qh_printsummary and qh_countfacets must match counts
+
+  design:
+    determine number of points, vertices, and coplanar points
+    print summary
+*/
+void qh_printsummary(FILE *fp) {
+  realT ratio, outerplane, innerplane;
+  float cpu;
+  int size, id, nummerged, numvertices, numcoplanars= 0, nonsimplicial=0;
+  int goodused;
+  facetT *facet;
+  const char *s;
+  int numdel= zzval_(Zdelvertextot);
+  int numtricoplanars= 0;
+
+  size= qh num_points + qh_setsize(qh other_points);
+  numvertices= qh num_vertices - qh_setsize(qh del_vertices);
+  id= qh_pointid(qh GOODpointp);
+  FORALLfacets {
+    if (facet->coplanarset)
+      numcoplanars += qh_setsize( facet->coplanarset);
+    if (facet->good) {
+      if (facet->simplicial) {
+        if (facet->keepcentrum && facet->tricoplanar)
+          numtricoplanars++;
+      }else if (qh_setsize(facet->vertices) != qh hull_dim)
+        nonsimplicial++;
+    }
+  }
+  if (id >=0 && qh STOPcone-1 != id && -qh STOPpoint-1 != id)
+    size--;
+  if (qh STOPcone || qh STOPpoint)
+      qh_fprintf(fp, 9288, "\nAt a premature exit due to 'TVn', 'TCn', 'TRn', or precision error with 'QJn'.");
+  if (qh UPPERdelaunay)
+    goodused= qh GOODvertex + qh GOODpoint + qh SPLITthresholds;
+  else if (qh DELAUNAY)
+    goodused= qh GOODvertex + qh GOODpoint + qh GOODthreshold;
+  else
+    goodused= qh num_good;
+  nummerged= zzval_(Ztotmerge) - zzval_(Zcyclehorizon) + zzval_(Zcyclefacettot);
+  if (qh VORONOI) {
+    if (qh UPPERdelaunay)
+      qh_fprintf(fp, 9289, "\n\
+Furthest-site Voronoi vertices by the convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
+    else
+      qh_fprintf(fp, 9290, "\n\
+Voronoi diagram by the convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
+    qh_fprintf(fp, 9291, "  Number of Voronoi regions%s: %d\n",
+              qh ATinfinity ? " and at-infinity" : "", numvertices);
+    if (numdel)
+      qh_fprintf(fp, 9292, "  Total number of deleted points due to merging: %d\n", numdel);
+    if (numcoplanars - numdel > 0)
+      qh_fprintf(fp, 9293, "  Number of nearly incident points: %d\n", numcoplanars - numdel);
+    else if (size - numvertices - numdel > 0)
+      qh_fprintf(fp, 9294, "  Total number of nearly incident points: %d\n", size - numvertices - numdel);
+    qh_fprintf(fp, 9295, "  Number of%s Voronoi vertices: %d\n",
+              goodused ? " 'good'" : "", qh num_good);
+    if (nonsimplicial)
+      qh_fprintf(fp, 9296, "  Number of%s non-simplicial Voronoi vertices: %d\n",
+              goodused ? " 'good'" : "", nonsimplicial);
+  }else if (qh DELAUNAY) {
+    if (qh UPPERdelaunay)
+      qh_fprintf(fp, 9297, "\n\
+Furthest-site Delaunay triangulation by the convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
+    else
+      qh_fprintf(fp, 9298, "\n\
+Delaunay triangulation by the convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
+    qh_fprintf(fp, 9299, "  Number of input sites%s: %d\n",
+              qh ATinfinity ? " and at-infinity" : "", numvertices);
+    if (numdel)
+      qh_fprintf(fp, 9300, "  Total number of deleted points due to merging: %d\n", numdel);
+    if (numcoplanars - numdel > 0)
+      qh_fprintf(fp, 9301, "  Number of nearly incident points: %d\n", numcoplanars - numdel);
+    else if (size - numvertices - numdel > 0)
+      qh_fprintf(fp, 9302, "  Total number of nearly incident points: %d\n", size - numvertices - numdel);
+    qh_fprintf(fp, 9303, "  Number of%s Delaunay regions: %d\n",
+              goodused ? " 'good'" : "", qh num_good);
+    if (nonsimplicial)
+      qh_fprintf(fp, 9304, "  Number of%s non-simplicial Delaunay regions: %d\n",
+              goodused ? " 'good'" : "", nonsimplicial);
+  }else if (qh HALFspace) {
+    qh_fprintf(fp, 9305, "\n\
+Halfspace intersection by the convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
+    qh_fprintf(fp, 9306, "  Number of halfspaces: %d\n", size);
+    qh_fprintf(fp, 9307, "  Number of non-redundant halfspaces: %d\n", numvertices);
+    if (numcoplanars) {
+      if (qh KEEPinside && qh KEEPcoplanar)
+        s= "similar and redundant";
+      else if (qh KEEPinside)
+        s= "redundant";
+      else
+        s= "similar";
+      qh_fprintf(fp, 9308, "  Number of %s halfspaces: %d\n", s, numcoplanars);
+    }
+    qh_fprintf(fp, 9309, "  Number of intersection points: %d\n", qh num_facets - qh num_visible);
+    if (goodused)
+      qh_fprintf(fp, 9310, "  Number of 'good' intersection points: %d\n", qh num_good);
+    if (nonsimplicial)
+      qh_fprintf(fp, 9311, "  Number of%s non-simplicial intersection points: %d\n",
+              goodused ? " 'good'" : "", nonsimplicial);
+  }else {
+    qh_fprintf(fp, 9312, "\n\
+Convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
+    qh_fprintf(fp, 9313, "  Number of vertices: %d\n", numvertices);
+    if (numcoplanars) {
+      if (qh KEEPinside && qh KEEPcoplanar)
+        s= "coplanar and interior";
+      else if (qh KEEPinside)
+        s= "interior";
+      else
+        s= "coplanar";
+      qh_fprintf(fp, 9314, "  Number of %s points: %d\n", s, numcoplanars);
+    }
+    qh_fprintf(fp, 9315, "  Number of facets: %d\n", qh num_facets - qh num_visible);
+    if (goodused)
+      qh_fprintf(fp, 9316, "  Number of 'good' facets: %d\n", qh num_good);
+    if (nonsimplicial)
+      qh_fprintf(fp, 9317, "  Number of%s non-simplicial facets: %d\n",
+              goodused ? " 'good'" : "", nonsimplicial);
+  }
+  if (numtricoplanars)
+      qh_fprintf(fp, 9318, "  Number of triangulated facets: %d\n", numtricoplanars);
+  qh_fprintf(fp, 9319, "\nStatistics for: %s | %s",
+                      qh rbox_command, qh qhull_command);
+  if (qh ROTATErandom != INT_MIN)
+    qh_fprintf(fp, 9320, " QR%d\n\n", qh ROTATErandom);
+  else
+    qh_fprintf(fp, 9321, "\n\n");
+  qh_fprintf(fp, 9322, "  Number of points processed: %d\n", zzval_(Zprocessed));
+  qh_fprintf(fp, 9323, "  Number of hyperplanes created: %d\n", zzval_(Zsetplane));
+  if (qh DELAUNAY)
+    qh_fprintf(fp, 9324, "  Number of facets in hull: %d\n", qh num_facets - qh num_visible);
+  qh_fprintf(fp, 9325, "  Number of distance tests for qhull: %d\n", zzval_(Zpartition)+
+      zzval_(Zpartitionall)+zzval_(Znumvisibility)+zzval_(Zpartcoplanar));
+#if 0  /* NOTE: must print before printstatistics() */
+  {realT stddev, ave;
+  qh_fprintf(fp, 9326, "  average new facet balance: %2.2g\n",
+          wval_(Wnewbalance)/zval_(Zprocessed));
+  stddev= qh_stddev(zval_(Zprocessed), wval_(Wnewbalance),
+                                 wval_(Wnewbalance2), &ave);
+  qh_fprintf(fp, 9327, "  new facet standard deviation: %2.2g\n", stddev);
+  qh_fprintf(fp, 9328, "  average partition balance: %2.2g\n",
+          wval_(Wpbalance)/zval_(Zpbalance));
+  stddev= qh_stddev(zval_(Zpbalance), wval_(Wpbalance),
+                                 wval_(Wpbalance2), &ave);
+  qh_fprintf(fp, 9329, "  partition standard deviation: %2.2g\n", stddev);
+  }
+#endif
+  if (nummerged) {
+    qh_fprintf(fp, 9330,"  Number of distance tests for merging: %d\n",zzval_(Zbestdist)+
+          zzval_(Zcentrumtests)+zzval_(Zdistconvex)+zzval_(Zdistcheck)+
+          zzval_(Zdistzero));
+    qh_fprintf(fp, 9331,"  Number of distance tests for checking: %d\n",zzval_(Zcheckpart));
+    qh_fprintf(fp, 9332,"  Number of merged facets: %d\n", nummerged);
+  }
+  if (!qh RANDOMoutside && qh QHULLfinished) {
+    cpu= (float)qh hulltime;
+    cpu /= (float)qh_SECticks;
+    wval_(Wcpu)= cpu;
+    qh_fprintf(fp, 9333, "  CPU seconds to compute hull (after input): %2.4g\n", cpu);
+  }
+  if (qh RERUN) {
+    if (!qh PREmerge && !qh MERGEexact)
+      qh_fprintf(fp, 9334, "  Percentage of runs with precision errors: %4.1f\n",
+           zzval_(Zretry)*100.0/qh build_cnt);  /* careful of order */
+  }else if (qh JOGGLEmax < REALmax/2) {
+    if (zzval_(Zretry))
+      qh_fprintf(fp, 9335, "  After %d retries, input joggled by: %2.2g\n",
+         zzval_(Zretry), qh JOGGLEmax);
+    else
+      qh_fprintf(fp, 9336, "  Input joggled by: %2.2g\n", qh JOGGLEmax);
+  }
+  if (qh totarea != 0.0)
+    qh_fprintf(fp, 9337, "  %s facet area:   %2.8g\n",
+            zzval_(Ztotmerge) ? "Approximate" : "Total", qh totarea);
+  if (qh totvol != 0.0)
+    qh_fprintf(fp, 9338, "  %s volume:       %2.8g\n",
+            zzval_(Ztotmerge) ? "Approximate" : "Total", qh totvol);
+  if (qh MERGING) {
+    qh_outerinner(NULL, &outerplane, &innerplane);
+    if (outerplane > 2 * qh DISTround) {
+      qh_fprintf(fp, 9339, "  Maximum distance of %spoint above facet: %2.2g",
+            (qh QHULLfinished ? "" : "merged "), outerplane);
+      ratio= outerplane/(qh ONEmerge + qh DISTround);
+      /* don't report ratio if MINoutside is large */
+      if (ratio > 0.05 && 2* qh ONEmerge > qh MINoutside && qh JOGGLEmax > REALmax/2)
+        qh_fprintf(fp, 9340, " (%.1fx)\n", ratio);
+      else
+        qh_fprintf(fp, 9341, "\n");
+    }
+    if (innerplane < -2 * qh DISTround) {
+      qh_fprintf(fp, 9342, "  Maximum distance of %svertex below facet: %2.2g",
+            (qh QHULLfinished ? "" : "merged "), innerplane);
+      ratio= -innerplane/(qh ONEmerge+qh DISTround);
+      if (ratio > 0.05 && qh JOGGLEmax > REALmax/2)
+        qh_fprintf(fp, 9343, " (%.1fx)\n", ratio);
+      else
+        qh_fprintf(fp, 9344, "\n");
+    }
+  }
+  qh_fprintf(fp, 9345, "\n");
+} /* printsummary */
+
+
diff --git a/alg/libqhull/libqhull.h b/alg/libqhull/libqhull.h
new file mode 100644
index 0000000..53bbdf1
--- /dev/null
+++ b/alg/libqhull/libqhull.h
@@ -0,0 +1,1100 @@
+/*<html><pre>  -<a                             href="qh-qhull.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   libqhull.h
+   user-level header file for using qhull.a library
+
+   see qh-qhull.htm, qhull_a.h
+
+   Copyright (c) 1993-2012 The Geometry Center.
+   $Id: //main/2011/qhull/src/libqhull/libqhull.h#7 $$Change: 1464 $
+   $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+
+   NOTE: access to qh_qh is via the 'qh' macro.  This allows
+   qh_qh to be either a pointer or a structure.  An example
+   of using qh is "qh DROPdim" which accesses the DROPdim
+   field of qh_qh.  Similarly, access to qh_qhstat is via
+   the 'qhstat' macro.
+
+   includes function prototypes for libqhull.c, geom.c, global.c, io.c, user.c
+
+   use mem.h for mem.c
+   use qset.h for qset.c
+
+   see unix.c for an example of using libqhull.h
+
+   recompile qhull if you change this file
+*/
+
+#ifndef qhDEFlibqhull
+#define qhDEFlibqhull 1
+
+/*=========================== -included files ==============*/
+
+#include "user.h"      /* user definable constants (e.g., qh_QHpointer) */
+
+#include <setjmp.h>
+#include <float.h>
+#include <time.h>
+#include <stdio.h>
+
+#if __MWERKS__ && __POWERPC__
+#include  <SIOUX.h>
+#include  <Files.h>
+#include        <Desk.h>
+#endif
+
+#ifndef __STDC__
+#ifndef __cplusplus
+#if     !_MSC_VER
+#error  Neither __STDC__ nor __cplusplus is defined.  Please use strict ANSI C or C++ to compile
+#error  Qhull.  You may need to turn off compiler extensions in your project configuration.  If
+#error  your compiler is a standard C compiler, you can delete this warning from libqhull.h
+#endif
+#endif
+#endif
+
+/*============ constants and basic types ====================*/
+
+extern const char *qh_version; /* defined in global.c */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >--------------------------------</a><a name="coordT">-</a>
+
+  coordT
+    coordinates and coefficients are stored as realT (i.e., double)
+
+  notes:
+    Qhull works well if realT is 'float'.  If so joggle (QJ) is not effective.
+
+    Could use 'float' for data and 'double' for calculations (realT vs. coordT)
+      This requires many type casts, and adjusted error bounds.
+      Also C compilers may do expressions in double anyway.
+*/
+#define coordT realT
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >--------------------------------</a><a name="pointT">-</a>
+
+  pointT
+    a point is an array of coordinates, usually qh.hull_dim
+*/
+#define pointT coordT
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >--------------------------------</a><a name="flagT">-</a>
+
+  flagT
+    Boolean flag as a bit
+*/
+#define flagT unsigned int
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >--------------------------------</a><a name="boolT">-</a>
+
+  boolT
+    boolean value, either True or False
+
+  notes:
+    needed for portability
+    Use qh_False/qh_True as synonyms
+*/
+#define boolT unsigned int
+#ifdef False
+#undef False
+#endif
+#ifdef True
+#undef True
+#endif
+#define False 0
+#define True 1
+#define qh_False 0
+#define qh_True 1
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >--------------------------------</a><a name="CENTERtype">-</a>
+
+  qh_CENTER
+    to distinguish facet->center
+*/
+typedef enum
+{
+    qh_ASnone = 0, qh_ASvoronoi, qh_AScentrum
+}
+qh_CENTER;
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >--------------------------------</a><a name="qh_PRINT">-</a>
+
+  qh_PRINT
+    output formats for printing (qh.PRINTout).
+    'Fa' 'FV' 'Fc' 'FC'
+
+
+   notes:
+   some of these names are similar to qh names.  The similar names are only
+   used in switch statements in qh_printbegin() etc.
+*/
+typedef enum {qh_PRINTnone= 0,
+  qh_PRINTarea, qh_PRINTaverage,           /* 'Fa' 'FV' 'Fc' 'FC' */
+  qh_PRINTcoplanars, qh_PRINTcentrums,
+  qh_PRINTfacets, qh_PRINTfacets_xridge,   /* 'f' 'FF' 'G' 'FI' 'Fi' 'Fn' */
+  qh_PRINTgeom, qh_PRINTids, qh_PRINTinner, qh_PRINTneighbors,
+  qh_PRINTnormals, qh_PRINTouter, qh_PRINTmaple, /* 'n' 'Fo' 'i' 'm' 'Fm' 'FM', 'o' */
+  qh_PRINTincidences, qh_PRINTmathematica, qh_PRINTmerges, qh_PRINToff,
+  qh_PRINToptions, qh_PRINTpointintersect, /* 'FO' 'Fp' 'FP' 'p' 'FQ' 'FS' */
+  qh_PRINTpointnearest, qh_PRINTpoints, qh_PRINTqhull, qh_PRINTsize,
+  qh_PRINTsummary, qh_PRINTtriangles,      /* 'Fs' 'Ft' 'Fv' 'FN' 'Fx' */
+  qh_PRINTvertices, qh_PRINTvneighbors, qh_PRINTextremes,
+  qh_PRINTEND} qh_PRINT;
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >--------------------------------</a><a name="qh_ALL">-</a>
+
+  qh_ALL
+    argument flag for selecting everything
+*/
+#define qh_ALL      True
+#define qh_NOupper  True     /* argument for qh_findbest */
+#define qh_IScheckmax  True     /* argument for qh_findbesthorizon */
+#define qh_ISnewfacets  True     /* argument for qh_findbest */
+#define qh_RESETvisible  True     /* argument for qh_resetlists */
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >--------------------------------</a><a name="qh_ERR">-</a>
+
+  qh_ERR
+    Qhull exit codes, for indicating errors
+    See: MSG_ERROR and MSG_WARNING [user.h]
+*/
+#define qh_ERRnone  0    /* no error occurred during qhull */
+#define qh_ERRinput 1    /* input inconsistency */
+#define qh_ERRsingular 2 /* singular input data */
+#define qh_ERRprec  3    /* precision error */
+#define qh_ERRmem   4    /* insufficient memory, matches mem.h */
+#define qh_ERRqhull 5    /* internal error detected, matches mem.h */
+
+/*-<a                             href="qh-qhull.htm#TOC"
+>--------------------------------</a><a name="qh_FILEstderr">-</a>
+
+qh_FILEstderr
+Fake stderr to distinguish error output from normal output
+For C++ interface.  Must redefine qh_fprintf_qhull
+*/
+#define qh_FILEstderr (FILE*)1
+
+/* ============ -structures- ====================
+   each of the following structures is defined by a typedef
+   all realT and coordT fields occur at the beginning of a structure
+        (otherwise space may be wasted due to alignment)
+   define all flags together and pack into 32-bit number
+*/
+
+typedef struct vertexT vertexT;
+typedef struct ridgeT ridgeT;
+typedef struct facetT facetT;
+#ifndef DEFsetT
+#define DEFsetT 1
+typedef struct setT setT;          /* defined in qset.h */
+#endif
+
+#ifndef DEFqhstatT
+#define DEFqhstatT 1
+typedef struct qhstatT qhstatT;    /* defined in stat.h */
+#endif
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="facetT">-</a>
+
+  facetT
+    defines a facet
+
+  notes:
+   qhull() generates the hull as a list of facets.
+
+  topological information:
+    f.previous,next     doubly-linked list of facets
+    f.vertices          set of vertices
+    f.ridges            set of ridges
+    f.neighbors         set of neighbors
+    f.toporient         True if facet has top-orientation (else bottom)
+
+  geometric information:
+    f.offset,normal     hyperplane equation
+    f.maxoutside        offset to outer plane -- all points inside
+    f.center            centrum for testing convexity
+    f.simplicial        True if facet is simplicial
+    f.flipped           True if facet does not include qh.interior_point
+
+  for constructing hull:
+    f.visible           True if facet on list of visible facets (will be deleted)
+    f.newfacet          True if facet on list of newly created facets
+    f.coplanarset       set of points coplanar with this facet
+                        (includes near-inside points for later testing)
+    f.outsideset        set of points outside of this facet
+    f.furthestdist      distance to furthest point of outside set
+    f.visitid           marks visited facets during a loop
+    f.replace           replacement facet for to-be-deleted, visible facets
+    f.samecycle,newcycle cycle of facets for merging into horizon facet
+
+  see below for other flags and fields
+*/
+struct facetT {
+#if !qh_COMPUTEfurthest
+  coordT   furthestdist;/* distance to furthest point of outsideset */
+#endif
+#if qh_MAXoutside
+  coordT   maxoutside;  /* max computed distance of point to facet
+                        Before QHULLfinished this is an approximation
+                        since maxdist not always set for mergefacet
+                        Actual outer plane is +DISTround and
+                        computed outer plane is +2*DISTround */
+#endif
+  coordT   offset;      /* exact offset of hyperplane from origin */
+  coordT  *normal;      /* normal of hyperplane, hull_dim coefficients */
+                        /*   if tricoplanar, shared with a neighbor */
+  union {               /* in order of testing */
+   realT   area;        /* area of facet, only in io.c if  ->isarea */
+   facetT *replace;     /*  replacement facet if ->visible and NEWfacets
+                             is NULL only if qh_mergedegen_redundant or interior */
+   facetT *samecycle;   /*  cycle of facets from the same visible/horizon intersection,
+                             if ->newfacet */
+   facetT *newcycle;    /*  in horizon facet, current samecycle of new facets */
+   facetT *trivisible;  /* visible facet for ->tricoplanar facets during qh_triangulate() */
+   facetT *triowner;    /* owner facet for ->tricoplanar, !isarea facets w/ ->keepcentrum */
+  }f;
+  coordT  *center;      /*  centrum for convexity, qh CENTERtype == qh_AScentrum */
+                        /*  Voronoi center, qh CENTERtype == qh_ASvoronoi */
+                        /*   if tricoplanar, shared with a neighbor */
+  facetT  *previous;    /* previous facet in the facet_list */
+  facetT  *next;        /* next facet in the facet_list */
+  setT    *vertices;    /* vertices for this facet, inverse sorted by ID
+                           if simplicial, 1st vertex was apex/furthest */
+  setT    *ridges;      /* explicit ridges for nonsimplicial facets.
+                           for simplicial facets, neighbors define the ridges */
+  setT    *neighbors;   /* neighbors of the facet.  If simplicial, the kth
+                           neighbor is opposite the kth vertex, and the first
+                           neighbor is the horizon facet for the first vertex*/
+  setT    *outsideset;  /* set of points outside this facet
+                           if non-empty, last point is furthest
+                           if NARROWhull, includes coplanars for partitioning*/
+  setT    *coplanarset; /* set of points coplanar with this facet
+                           > qh.min_vertex and <= facet->max_outside
+                           a point is assigned to the furthest facet
+                           if non-empty, last point is furthest away */
+  unsigned visitid;     /* visit_id, for visiting all neighbors,
+                           all uses are independent */
+  unsigned id;          /* unique identifier from qh facet_id */
+  unsigned nummerge:9;  /* number of merges */
+#define qh_MAXnummerge 511 /*     2^9-1, 32 flags total, see "flags:" in io.c */
+  flagT    tricoplanar:1; /* True if TRIangulate and simplicial and coplanar with a neighbor */
+                          /*   all tricoplanars share the same ->center, ->normal, ->offset, ->maxoutside */
+                          /*   all tricoplanars share the same apex */
+                          /*   if ->degenerate, does not span facet (one logical ridge) */
+                          /*   one tricoplanar has ->keepcentrum and ->coplanarset */
+                          /*   during qh_triangulate, f.trivisible points to original facet */
+  flagT    newfacet:1;  /* True if facet on qh newfacet_list (new or merged) */
+  flagT    visible:1;   /* True if visible facet (will be deleted) */
+  flagT    toporient:1; /* True if created with top orientation
+                           after merging, use ridge orientation */
+  flagT    simplicial:1;/* True if simplicial facet, ->ridges may be implicit */
+  flagT    seen:1;      /* used to perform operations only once, like visitid */
+  flagT    seen2:1;     /* used to perform operations only once, like visitid */
+  flagT    flipped:1;   /* True if facet is flipped */
+  flagT    upperdelaunay:1; /* True if facet is upper envelope of Delaunay triangulation */
+  flagT    notfurthest:1; /* True if last point of outsideset is not furthest*/
+
+/*-------- flags primarily for output ---------*/
+  flagT    good:1;      /* True if a facet marked good for output */
+  flagT    isarea:1;    /* True if facet->f.area is defined */
+
+/*-------- flags for merging ------------------*/
+  flagT    dupridge:1;  /* True if duplicate ridge in facet */
+  flagT    mergeridge:1; /* True if facet or neighbor contains a qh_MERGEridge
+                            ->normal defined (also defined for mergeridge2) */
+  flagT    mergeridge2:1; /* True if neighbor contains a qh_MERGEridge (mark_dupridges */
+  flagT    coplanar:1;  /* True if horizon facet is coplanar at last use */
+  flagT     mergehorizon:1; /* True if will merge into horizon (->coplanar) */
+  flagT     cycledone:1;/* True if mergecycle_all already done */
+  flagT    tested:1;    /* True if facet convexity has been tested (false after merge */
+  flagT    keepcentrum:1; /* True if keep old centrum after a merge, or marks owner for ->tricoplanar */
+  flagT    newmerge:1;  /* True if facet is newly merged for reducevertices */
+  flagT    degenerate:1; /* True if facet is degenerate (degen_mergeset or ->tricoplanar) */
+  flagT    redundant:1;  /* True if facet is redundant (degen_mergeset) */
+};
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="ridgeT">-</a>
+
+  ridgeT
+    defines a ridge
+
+  notes:
+  a ridge is hull_dim-1 simplex between two neighboring facets.  If the
+  facets are non-simplicial, there may be more than one ridge between
+  two facets.  E.G. a 4-d hypercube has two triangles between each pair
+  of neighboring facets.
+
+  topological information:
+    vertices            a set of vertices
+    top,bottom          neighboring facets with orientation
+
+  geometric information:
+    tested              True if ridge is clearly convex
+    nonconvex           True if ridge is non-convex
+*/
+struct ridgeT {
+  setT    *vertices;    /* vertices belonging to this ridge, inverse sorted by ID
+                           NULL if a degen ridge (matchsame) */
+  facetT  *top;         /* top facet this ridge is part of */
+  facetT  *bottom;      /* bottom facet this ridge is part of */
+  unsigned id:24;       /* unique identifier, =>room for 8 flags, bit field matches qh.ridge_id */
+  flagT    seen:1;      /* used to perform operations only once */
+  flagT    tested:1;    /* True when ridge is tested for convexity */
+  flagT    nonconvex:1; /* True if getmergeset detected a non-convex neighbor
+                           only one ridge between neighbors may have nonconvex */
+};
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="vertexT">-</a>
+
+  vertexT
+     defines a vertex
+
+  topological information:
+    next,previous       doubly-linked list of all vertices
+    neighbors           set of adjacent facets (only if qh.VERTEXneighbors)
+
+  geometric information:
+    point               array of DIM3 coordinates
+*/
+struct vertexT {
+  vertexT *next;        /* next vertex in vertex_list */
+  vertexT *previous;    /* previous vertex in vertex_list */
+  pointT  *point;       /* hull_dim coordinates (coordT) */
+  setT    *neighbors;   /* neighboring facets of vertex, qh_vertexneighbors()
+                           inits in io.c or after first merge */
+  unsigned visitid:31;  /* for use with qh vertex_visit, size must match */
+  flagT    seen2:1;     /* another seen flag */
+  unsigned id:24;       /* unique identifier, bit field matches qh.vertex_id */
+  unsigned dim:4;       /* dimension of point if non-zero, used by cpp */
+                        /* =>room for 4 flags */
+  flagT    seen:1;      /* used to perform operations only once */
+  flagT    delridge:1;  /* vertex was part of a deleted ridge */
+  flagT    deleted:1;   /* true if vertex on qh del_vertices */
+  flagT    newlist:1;   /* true if vertex on qh newvertex_list */
+};
+
+#define MAX_vdim 15  /* Maximum size of vertex->dim */
+
+/*======= -global variables -qh ============================*/
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >--------------------------------</a><a name="qh">-</a>
+
+  qh
+   all global variables for qhull are in qh, qhmem, and qhstat
+
+  notes:
+   qhmem is defined in mem.h, qhstat is defined in stat.h, qhrbox is defined in rboxpoints.h
+   Access to qh_qh is via the "qh" macro.  See qh_QHpointer in user.h
+
+   All global variables for qhull are in qh, qhmem, and qhstat
+   qh must be unique for each instance of qhull
+   qhstat may be shared between qhull instances.
+   qhmem may be shared across multiple instances of Qhull.
+   Rbox uses global variables rbox_inuse and rbox, but does not persist data across calls.
+
+   Qhull is not multithreaded.  Global state could be stored in thread-local storage.
+*/
+
+extern int qhull_inuse;
+
+typedef struct qhT qhT;
+#if qh_QHpointer_dllimport
+#define qh qh_qh->
+__declspec(dllimport) extern qhT *qh_qh;     /* allocated in global.c */
+#elif qh_QHpointer
+#define qh qh_qh->
+extern qhT *qh_qh;     /* allocated in global.c */
+#elif qh_dllimport
+#define qh qh_qh.
+__declspec(dllimport) extern qhT qh_qh;      /* allocated in global.c */
+#else
+#define qh qh_qh.
+extern qhT qh_qh;
+#endif
+
+struct qhT {
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >--------------------------------</a><a name="qh-const">-</a>
+
+  qh constants
+    configuration flags and constants for Qhull
+
+  notes:
+    The user configures Qhull by defining flags.  They are
+    copied into qh by qh_setflags().  qh-quick.htm#options defines the flags.
+*/
+  boolT ALLpoints;        /* true 'Qs' if search all points for initial simplex */
+  boolT ANGLEmerge;       /* true 'Qa' if sort potential merges by angle */
+  boolT APPROXhull;       /* true 'Wn' if MINoutside set */
+  realT   MINoutside;     /*   'Wn' min. distance for an outside point */
+  boolT ANNOTATEoutput;   /* true 'Ta' if annotate output with message codes */
+  boolT ATinfinity;       /* true 'Qz' if point num_points-1 is "at-infinity"
+                             for improving precision in Delaunay triangulations */
+  boolT AVOIDold;         /* true 'Q4' if avoid old->new merges */
+  boolT BESToutside;      /* true 'Qf' if partition points into best outsideset */
+  boolT CDDinput;         /* true 'Pc' if input uses CDD format (1.0/offset first) */
+  boolT CDDoutput;        /* true 'PC' if print normals in CDD format (offset first) */
+  boolT CHECKfrequently;  /* true 'Tc' if checking frequently */
+  realT premerge_cos;     /*   'A-n'   cos_max when pre merging */
+  realT postmerge_cos;    /*   'An'    cos_max when post merging */
+  boolT DELAUNAY;         /* true 'd' if computing DELAUNAY triangulation */
+  boolT DOintersections;  /* true 'Gh' if print hyperplane intersections */
+  int   DROPdim;          /* drops dim 'GDn' for 4-d -> 3-d output */
+  boolT FORCEoutput;      /* true 'Po' if forcing output despite degeneracies */
+  int   GOODpoint;        /* 1+n for 'QGn', good facet if visible/not(-) from point n*/
+  pointT *GOODpointp;     /*   the actual point */
+  boolT GOODthreshold;    /* true if qh lower_threshold/upper_threshold defined
+                             false if qh SPLITthreshold */
+  int   GOODvertex;       /* 1+n, good facet if vertex for point n */
+  pointT *GOODvertexp;     /*   the actual point */
+  boolT HALFspace;        /* true 'Hn,n,n' if halfspace intersection */
+  int   IStracing;        /* trace execution, 0=none, 1=least, 4=most, -1=events */
+  int   KEEParea;         /* 'PAn' number of largest facets to keep */
+  boolT KEEPcoplanar;     /* true 'Qc' if keeping nearest facet for coplanar points */
+  boolT KEEPinside;       /* true 'Qi' if keeping nearest facet for inside points
+                              set automatically if 'd Qc' */
+  int   KEEPmerge;        /* 'PMn' number of facets to keep with most merges */
+  realT KEEPminArea;      /* 'PFn' minimum facet area to keep */
+  realT MAXcoplanar;      /* 'Un' max distance below a facet to be coplanar*/
+  boolT MERGEexact;       /* true 'Qx' if exact merges (coplanar, degen, dupridge, flipped) */
+  boolT MERGEindependent; /* true 'Q2' if merging independent sets */
+  boolT MERGING;          /* true if exact-, pre- or post-merging, with angle and centrum tests */
+  realT   premerge_centrum;  /*   'C-n' centrum_radius when pre merging.  Default is round-off */
+  realT   postmerge_centrum; /*   'Cn' centrum_radius when post merging.  Default is round-off */
+  boolT MERGEvertices;    /* true 'Q3' if merging redundant vertices */
+  realT MINvisible;       /* 'Vn' min. distance for a facet to be visible */
+  boolT NOnarrow;         /* true 'Q10' if no special processing for narrow distributions */
+  boolT NOnearinside;     /* true 'Q8' if ignore near-inside points when partitioning */
+  boolT NOpremerge;       /* true 'Q0' if no defaults for C-0 or Qx */
+  boolT ONLYgood;         /* true 'Qg' if process points with good visible or horizon facets */
+  boolT ONLYmax;          /* true 'Qm' if only process points that increase max_outside */
+  boolT PICKfurthest;     /* true 'Q9' if process furthest of furthest points*/
+  boolT POSTmerge;        /* true if merging after buildhull (Cn or An) */
+  boolT PREmerge;         /* true if merging during buildhull (C-n or A-n) */
+                        /* NOTE: some of these names are similar to qh_PRINT names */
+  boolT PRINTcentrums;    /* true 'Gc' if printing centrums */
+  boolT PRINTcoplanar;    /* true 'Gp' if printing coplanar points */
+  int   PRINTdim;         /* print dimension for Geomview output */
+  boolT PRINTdots;        /* true 'Ga' if printing all points as dots */
+  boolT PRINTgood;        /* true 'Pg' if printing good facets */
+  boolT PRINTinner;       /* true 'Gi' if printing inner planes */
+  boolT PRINTneighbors;   /* true 'PG' if printing neighbors of good facets */
+  boolT PRINTnoplanes;    /* true 'Gn' if printing no planes */
+  boolT PRINToptions1st;  /* true 'FO' if printing options to stderr */
+  boolT PRINTouter;       /* true 'Go' if printing outer planes */
+  boolT PRINTprecision;   /* false 'Pp' if not reporting precision problems */
+  qh_PRINT PRINTout[qh_PRINTEND]; /* list of output formats to print */
+  boolT PRINTridges;      /* true 'Gr' if print ridges */
+  boolT PRINTspheres;     /* true 'Gv' if print vertices as spheres */
+  boolT PRINTstatistics;  /* true 'Ts' if printing statistics to stderr */
+  boolT PRINTsummary;     /* true 's' if printing summary to stderr */
+  boolT PRINTtransparent; /* true 'Gt' if print transparent outer ridges */
+  boolT PROJECTdelaunay;  /* true if DELAUNAY, no readpoints() and
+                             need projectinput() for Delaunay in qh_init_B */
+  int   PROJECTinput;     /* number of projected dimensions 'bn:0Bn:0' */
+  boolT QUICKhelp;        /* true if quick help message for degen input */
+  boolT RANDOMdist;       /* true if randomly change distplane and setfacetplane */
+  realT RANDOMfactor;     /*    maximum random perturbation */
+  realT RANDOMa;          /*    qh_randomfactor is randr * RANDOMa + RANDOMb */
+  realT RANDOMb;
+  boolT RANDOMoutside;    /* true if select a random outside point */
+  int   REPORTfreq;       /* buildtracing reports every n facets */
+  int   REPORTfreq2;      /* tracemerging reports every REPORTfreq/2 facets */
+  int   RERUN;            /* 'TRn' rerun qhull n times (qh.build_cnt) */
+  int   ROTATErandom;     /* 'QRn' seed, 0 time, >= rotate input */
+  boolT SCALEinput;       /* true 'Qbk' if scaling input */
+  boolT SCALElast;        /* true 'Qbb' if scale last coord to max prev coord */
+  boolT SETroundoff;      /* true 'E' if qh DISTround is predefined */
+  boolT SKIPcheckmax;     /* true 'Q5' if skip qh_check_maxout */
+  boolT SKIPconvex;       /* true 'Q6' if skip convexity testing during pre-merge */
+  boolT SPLITthresholds;  /* true if upper_/lower_threshold defines a region
+                               used only for printing (!for qh ONLYgood) */
+  int   STOPcone;         /* 'TCn' 1+n for stopping after cone for point n */
+                          /*       also used by qh_build_withresart for err exit*/
+  int   STOPpoint;        /* 'TVn' 'TV-n' 1+n for stopping after/before(-)
+                                        adding point n */
+  int   TESTpoints;       /* 'QTn' num of test points after qh.num_points.  Test points always coplanar. */
+  boolT TESTvneighbors;   /*  true 'Qv' if test vertex neighbors at end */
+  int   TRACElevel;       /* 'Tn' conditional IStracing level */
+  int   TRACElastrun;     /*  qh.TRACElevel applies to last qh.RERUN */
+  int   TRACEpoint;       /* 'TPn' start tracing when point n is a vertex */
+  realT TRACEdist;        /* 'TWn' start tracing when merge distance too big */
+  int   TRACEmerge;       /* 'TMn' start tracing before this merge */
+  boolT TRIangulate;      /* true 'Qt' if triangulate non-simplicial facets */
+  boolT TRInormals;       /* true 'Q11' if triangulate duplicates normals (sets Qt) */
+  boolT UPPERdelaunay;    /* true 'Qu' if computing furthest-site Delaunay */
+  boolT USEstdout;        /* true 'Tz' if using stdout instead of stderr */
+  boolT VERIFYoutput;     /* true 'Tv' if verify output at end of qhull */
+  boolT VIRTUALmemory;    /* true 'Q7' if depth-first processing in buildhull */
+  boolT VORONOI;          /* true 'v' if computing Voronoi diagram */
+
+  /*--------input constants ---------*/
+  realT AREAfactor;       /* 1/(hull_dim-1)! for converting det's to area */
+  boolT DOcheckmax;       /* true if calling qh_check_maxout (qh_initqhull_globals) */
+  char  *feasible_string;  /* feasible point 'Hn,n,n' for halfspace intersection */
+  coordT *feasible_point;  /*    as coordinates, both malloc'd */
+  boolT GETarea;          /* true 'Fa', 'FA', 'FS', 'PAn', 'PFn' if compute facet area/Voronoi volume in io.c */
+  boolT KEEPnearinside;   /* true if near-inside points in coplanarset */
+  int   hull_dim;         /* dimension of hull, set by initbuffers */
+  int   input_dim;        /* dimension of input, set by initbuffers */
+  int   num_points;       /* number of input points */
+  pointT *first_point;    /* array of input points, see POINTSmalloc */
+  boolT POINTSmalloc;     /*   true if qh first_point/num_points allocated */
+  pointT *input_points;   /* copy of original qh.first_point for input points for qh_joggleinput */
+  boolT input_malloc;     /* true if qh input_points malloc'd */
+  char  qhull_command[256];/* command line that invoked this program */
+  int   qhull_commandsiz2; /*    size of qhull_command at qh_clear_outputflags */
+  char  rbox_command[256]; /* command line that produced the input points */
+  char  qhull_options[512];/* descriptive list of options */
+  int   qhull_optionlen;  /*    length of last line */
+  int   qhull_optionsiz;  /*    size of qhull_options at qh_build_withrestart */
+  int   qhull_optionsiz2; /*    size of qhull_options at qh_clear_outputflags */
+  int   run_id;           /* non-zero, random identifier for this instance of qhull */
+  boolT VERTEXneighbors;  /* true if maintaining vertex neighbors */
+  boolT ZEROcentrum;      /* true if 'C-0' or 'C-0 Qx'.  sets ZEROall_ok */
+  realT *upper_threshold; /* don't print if facet->normal[k]>=upper_threshold[k]
+                             must set either GOODthreshold or SPLITthreshold
+                             if Delaunay, default is 0.0 for upper envelope */
+  realT *lower_threshold; /* don't print if facet->normal[k] <=lower_threshold[k] */
+  realT *upper_bound;     /* scale point[k] to new upper bound */
+  realT *lower_bound;     /* scale point[k] to new lower bound
+                             project if both upper_ and lower_bound == 0 */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >--------------------------------</a><a name="qh-prec">-</a>
+
+  qh precision constants
+    precision constants for Qhull
+
+  notes:
+    qh_detroundoff() computes the maximum roundoff error for distance
+    and other computations.  It also sets default values for the
+    qh constants above.
+*/
+  realT ANGLEround;       /* max round off error for angles */
+  realT centrum_radius;   /* max centrum radius for convexity (roundoff added) */
+  realT cos_max;          /* max cosine for convexity (roundoff added) */
+  realT DISTround;        /* max round off error for distances, 'E' overrides */
+  realT MAXabs_coord;     /* max absolute coordinate */
+  realT MAXlastcoord;     /* max last coordinate for qh_scalelast */
+  realT MAXsumcoord;      /* max sum of coordinates */
+  realT MAXwidth;         /* max rectilinear width of point coordinates */
+  realT MINdenom_1;       /* min. abs. value for 1/x */
+  realT MINdenom;         /*    use divzero if denominator < MINdenom */
+  realT MINdenom_1_2;     /* min. abs. val for 1/x that allows normalization */
+  realT MINdenom_2;       /*    use divzero if denominator < MINdenom_2 */
+  realT MINlastcoord;     /* min. last coordinate for qh_scalelast */
+  boolT NARROWhull;       /* set in qh_initialhull if angle < qh_MAXnarrow */
+  realT *NEARzero;        /* hull_dim array for near zero in gausselim */
+  realT NEARinside;       /* keep points for qh_check_maxout if close to facet */
+  realT ONEmerge;         /* max distance for merging simplicial facets */
+  realT outside_err;      /* application's epsilon for coplanar points
+                             qh_check_bestdist() qh_check_points() reports error if point outside */
+  realT WIDEfacet;        /* size of wide facet for skipping ridge in
+                             area computation and locking centrum */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >--------------------------------</a><a name="qh-codetern">-</a>
+
+  qh internal constants
+    internal constants for Qhull
+*/
+  char qhull[sizeof("qhull")]; /* "qhull" for checking ownership while debugging */
+  jmp_buf errexit;        /* exit label for qh_errexit, defined by setjmp() */
+  char jmpXtra[40];       /* extra bytes in case jmp_buf is defined wrong by compiler */
+  jmp_buf restartexit;    /* restart label for qh_errexit, defined by setjmp() */
+  char jmpXtra2[40];      /* extra bytes in case jmp_buf is defined wrong by compiler*/
+  FILE *fin;              /* pointer to input file, init by qh_meminit */
+  FILE *fout;             /* pointer to output file */
+  FILE *ferr;             /* pointer to error file */
+  pointT *interior_point; /* center point of the initial simplex*/
+  int normal_size;     /* size in bytes for facet normals and point coords*/
+  int center_size;     /* size in bytes for Voronoi centers */
+  int   TEMPsize;         /* size for small, temporary sets (in quick mem) */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >--------------------------------</a><a name="qh-lists">-</a>
+
+  qh facet and vertex lists
+    defines lists of facets, new facets, visible facets, vertices, and
+    new vertices.  Includes counts, next ids, and trace ids.
+  see:
+    qh_resetlists()
+*/
+  facetT *facet_list;     /* first facet */
+  facetT  *facet_tail;     /* end of facet_list (dummy facet) */
+  facetT *facet_next;     /* next facet for buildhull()
+                             previous facets do not have outside sets
+                             NARROWhull: previous facets may have coplanar outside sets for qh_outcoplanar */
+  facetT *newfacet_list;  /* list of new facets to end of facet_list */
+  facetT *visible_list;   /* list of visible facets preceding newfacet_list,
+                             facet->visible set */
+  int       num_visible;  /* current number of visible facets */
+  unsigned tracefacet_id;  /* set at init, then can print whenever */
+  facetT *tracefacet;     /*   set in newfacet/mergefacet, undone in delfacet*/
+  unsigned tracevertex_id;  /* set at buildtracing, can print whenever */
+  vertexT *tracevertex;     /*   set in newvertex, undone in delvertex*/
+  vertexT *vertex_list;     /* list of all vertices, to vertex_tail */
+  vertexT  *vertex_tail;    /*      end of vertex_list (dummy vertex) */
+  vertexT *newvertex_list; /* list of vertices in newfacet_list, to vertex_tail
+                             all vertices have 'newlist' set */
+  int   num_facets;       /* number of facets in facet_list
+                             includes visible faces (num_visible) */
+  int   num_vertices;     /* number of vertices in facet_list */
+  int   num_outside;      /* number of points in outsidesets (for tracing and RANDOMoutside)
+                               includes coplanar outsideset points for NARROWhull/qh_outcoplanar() */
+  int   num_good;         /* number of good facets (after findgood_all) */
+  unsigned facet_id;      /* ID of next, new facet from newfacet() */
+  unsigned ridge_id:24;   /* ID of next, new ridge from newridge() */
+  unsigned vertex_id:24;  /* ID of next, new vertex from newvertex() */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >--------------------------------</a><a name="qh-var">-</a>
+
+  qh global variables
+    defines minimum and maximum distances, next visit ids, several flags,
+    and other global variables.
+    initialize in qh_initbuild or qh_maxmin if used in qh_buildhull
+*/
+  unsigned long hulltime; /* ignore time to set up input and randomize */
+                          /*   use unsigned to avoid wrap-around errors */
+  boolT ALLOWrestart;     /* true if qh_precision can use qh.restartexit */
+  int   build_cnt;        /* number of calls to qh_initbuild */
+  qh_CENTER CENTERtype;   /* current type of facet->center, qh_CENTER */
+  int   furthest_id;      /* pointid of furthest point, for tracing */
+  facetT *GOODclosest;    /* closest facet to GOODthreshold in qh_findgood */
+  boolT hasAreaVolume;    /* true if totarea, totvol was defined by qh_getarea */
+  boolT hasTriangulation; /* true if triangulation created by qh_triangulate */
+  realT JOGGLEmax;        /* set 'QJn' if randomly joggle input */
+  boolT maxoutdone;       /* set qh_check_maxout(), cleared by qh_addpoint() */
+  realT max_outside;      /* maximum distance from a point to a facet,
+                               before roundoff, not simplicial vertices
+                               actual outer plane is +DISTround and
+                               computed outer plane is +2*DISTround */
+  realT max_vertex;       /* maximum distance (>0) from vertex to a facet,
+                               before roundoff, due to a merge */
+  realT min_vertex;       /* minimum distance (<0) from vertex to a facet,
+                               before roundoff, due to a merge
+                               if qh.JOGGLEmax, qh_makenewplanes sets it
+                               recomputed if qh.DOcheckmax, default -qh.DISTround */
+  boolT NEWfacets;        /* true while visible facets invalid due to new or merge
+                              from makecone/attachnewfacets to deletevisible */
+  boolT findbestnew;      /* true if partitioning calls qh_findbestnew */
+  boolT findbest_notsharp; /* true if new facets are at least 90 degrees */
+  boolT NOerrexit;        /* true if qh.errexit is not available */
+  realT PRINTcradius;     /* radius for printing centrums */
+  realT PRINTradius;      /* radius for printing vertex spheres and points */
+  boolT POSTmerging;      /* true when post merging */
+  int   printoutvar;      /* temporary variable for qh_printbegin, etc. */
+  int   printoutnum;      /* number of facets printed */
+  boolT QHULLfinished;    /* True after qhull() is finished */
+  realT totarea;          /* 'FA': total facet area computed by qh_getarea, hasAreaVolume */
+  realT totvol;           /* 'FA': total volume computed by qh_getarea, hasAreaVolume */
+  unsigned int visit_id;  /* unique ID for searching neighborhoods, */
+  unsigned int vertex_visit:31; /* unique ID for searching vertices, reset with qh_buildtracing */
+  boolT ZEROall_ok;       /* True if qh_checkzero always succeeds */
+  boolT WAScoplanar;      /* True if qh_partitioncoplanar (qh_check_maxout) */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >--------------------------------</a><a name="qh-set">-</a>
+
+  qh global sets
+    defines sets for merging, initial simplex, hashing, extra input points,
+    and deleted vertices
+*/
+  setT *facet_mergeset;   /* temporary set of merges to be done */
+  setT *degen_mergeset;   /* temporary set of degenerate and redundant merges */
+  setT *hash_table;       /* hash table for matching ridges in qh_matchfacets
+                             size is setsize() */
+  setT *other_points;     /* additional points */
+  setT *del_vertices;     /* vertices to partition and delete with visible
+                             facets.  Have deleted set for checkfacet */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >--------------------------------</a><a name="qh-buf">-</a>
+
+  qh global buffers
+    defines buffers for matrix operations, input, and error messages
+*/
+  coordT *gm_matrix;      /* (dim+1)Xdim matrix for geom.c */
+  coordT **gm_row;        /* array of gm_matrix rows */
+  char* line;             /* malloc'd input line of maxline+1 chars */
+  int maxline;
+  coordT *half_space;     /* malloc'd input array for halfspace (qh normal_size+coordT) */
+  coordT *temp_malloc;    /* malloc'd input array for points */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >--------------------------------</a><a name="qh-static">-</a>
+
+  qh static variables
+    defines static variables for individual functions
+
+  notes:
+    do not use 'static' within a function.  Multiple instances of qhull
+    may exist.
+
+    do not assume zero initialization, 'QPn' may cause a restart
+*/
+  boolT ERREXITcalled;    /* true during qh_errexit (prevents duplicate calls */
+  boolT firstcentrum;     /* for qh_printcentrum */
+  boolT old_randomdist;   /* save RANDOMdist flag during io, tracing, or statistics */
+  setT *coplanarfacetset;  /* set of coplanar facets for searching qh_findbesthorizon() */
+  realT last_low;         /* qh_scalelast parameters for qh_setdelaunay */
+  realT last_high;
+  realT last_newhigh;
+  unsigned lastreport;    /* for qh_buildtracing */
+  int mergereport;        /* for qh_tracemerging */
+  qhstatT *old_qhstat;    /* for saving qh_qhstat in save_qhull() and UsingLibQhull.  Free with qh_free() */
+  setT *old_tempstack;    /* for saving qhmem.tempstack in save_qhull */
+  int   ridgeoutnum;      /* number of ridges for 4OFF output (qh_printbegin,etc) */
+};
+
+/*=========== -macros- =========================*/
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="otherfacet_">-</a>
+
+  otherfacet_(ridge, facet)
+    return neighboring facet for a ridge in facet
+*/
+#define otherfacet_(ridge, facet) \
+                        (((ridge)->top == (facet)) ? (ridge)->bottom : (ridge)->top)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="getid_">-</a>
+
+  getid_(p)
+    return int ID for facet, ridge, or vertex
+    return -1 if NULL
+*/
+#define getid_(p)       ((p) ? (int)((p)->id) : -1)
+
+/*============== FORALL macros ===================*/
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FORALLfacets">-</a>
+
+  FORALLfacets { ... }
+    assign 'facet' to each facet in qh.facet_list
+
+  notes:
+    uses 'facetT *facet;'
+    assumes last facet is a sentinel
+
+  see:
+    FORALLfacet_( facetlist )
+*/
+#define FORALLfacets for (facet=qh facet_list;facet && facet->next;facet=facet->next)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FORALLpoints">-</a>
+
+  FORALLpoints { ... }
+    assign 'point' to each point in qh.first_point, qh.num_points
+
+  declare:
+    coordT *point, *pointtemp;
+*/
+#define FORALLpoints FORALLpoint_(qh first_point, qh num_points)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FORALLpoint_">-</a>
+
+  FORALLpoint_( points, num) { ... }
+    assign 'point' to each point in points array of num points
+
+  declare:
+    coordT *point, *pointtemp;
+*/
+#define FORALLpoint_(points, num) for (point= (points), \
+      pointtemp= (points)+qh hull_dim*(num); point < pointtemp; point += qh hull_dim)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FORALLvertices">-</a>
+
+  FORALLvertices { ... }
+    assign 'vertex' to each vertex in qh.vertex_list
+
+  declare:
+    vertexT *vertex;
+
+  notes:
+    assumes qh.vertex_list terminated with a sentinel
+*/
+#define FORALLvertices for (vertex=qh vertex_list;vertex && vertex->next;vertex= vertex->next)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FOREACHfacet_">-</a>
+
+  FOREACHfacet_( facets ) { ... }
+    assign 'facet' to each facet in facets
+
+  declare:
+    facetT *facet, **facetp;
+
+  see:
+    <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHfacet_(facets)    FOREACHsetelement_(facetT, facets, facet)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FOREACHneighbor_">-</a>
+
+  FOREACHneighbor_( facet ) { ... }
+    assign 'neighbor' to each neighbor in facet->neighbors
+
+  FOREACHneighbor_( vertex ) { ... }
+    assign 'neighbor' to each neighbor in vertex->neighbors
+
+  declare:
+    facetT *neighbor, **neighborp;
+
+  see:
+    <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHneighbor_(facet)  FOREACHsetelement_(facetT, facet->neighbors, neighbor)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FOREACHpoint_">-</a>
+
+  FOREACHpoint_( points ) { ... }
+    assign 'point' to each point in points set
+
+  declare:
+    pointT *point, **pointp;
+
+  see:
+    <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHpoint_(points)    FOREACHsetelement_(pointT, points, point)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FOREACHridge_">-</a>
+
+  FOREACHridge_( ridges ) { ... }
+    assign 'ridge' to each ridge in ridges set
+
+  declare:
+    ridgeT *ridge, **ridgep;
+
+  see:
+    <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHridge_(ridges)    FOREACHsetelement_(ridgeT, ridges, ridge)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FOREACHvertex_">-</a>
+
+  FOREACHvertex_( vertices ) { ... }
+    assign 'vertex' to each vertex in vertices set
+
+  declare:
+    vertexT *vertex, **vertexp;
+
+  see:
+    <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHvertex_(vertices) FOREACHsetelement_(vertexT, vertices,vertex)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FOREACHfacet_i_">-</a>
+
+  FOREACHfacet_i_( facets ) { ... }
+    assign 'facet' and 'facet_i' for each facet in facets set
+
+  declare:
+    facetT *facet;
+    int     facet_n, facet_i;
+
+  see:
+    <a href="qset.h#FOREACHsetelement_i_">FOREACHsetelement_i_</a>
+*/
+#define FOREACHfacet_i_(facets)    FOREACHsetelement_i_(facetT, facets, facet)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FOREACHneighbor_i_">-</a>
+
+  FOREACHneighbor_i_( facet ) { ... }
+    assign 'neighbor' and 'neighbor_i' for each neighbor in facet->neighbors
+
+  FOREACHneighbor_i_( vertex ) { ... }
+    assign 'neighbor' and 'neighbor_i' for each neighbor in vertex->neighbors
+
+  declare:
+    facetT *neighbor;
+    int     neighbor_n, neighbor_i;
+
+  see:
+    <a href="qset.h#FOREACHsetelement_i_">FOREACHsetelement_i_</a>
+*/
+#define FOREACHneighbor_i_(facet)  FOREACHsetelement_i_(facetT, facet->neighbors, neighbor)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FOREACHpoint_i_">-</a>
+
+  FOREACHpoint_i_( points ) { ... }
+    assign 'point' and 'point_i' for each point in points set
+
+  declare:
+    pointT *point;
+    int     point_n, point_i;
+
+  see:
+    <a href="qset.h#FOREACHsetelement_i_">FOREACHsetelement_i_</a>
+*/
+#define FOREACHpoint_i_(points)    FOREACHsetelement_i_(pointT, points, point)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FOREACHridge_i_">-</a>
+
+  FOREACHridge_i_( ridges ) { ... }
+    assign 'ridge' and 'ridge_i' for each ridge in ridges set
+
+  declare:
+    ridgeT *ridge;
+    int     ridge_n, ridge_i;
+
+  see:
+    <a href="qset.h#FOREACHsetelement_i_">FOREACHsetelement_i_</a>
+*/
+#define FOREACHridge_i_(ridges)    FOREACHsetelement_i_(ridgeT, ridges, ridge)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FOREACHvertex_i_">-</a>
+
+  FOREACHvertex_i_( vertices ) { ... }
+    assign 'vertex' and 'vertex_i' for each vertex in vertices set
+
+  declare:
+    vertexT *vertex;
+    int     vertex_n, vertex_i;
+
+  see:
+    <a href="qset.h#FOREACHsetelement_i_">FOREACHsetelement_i_</a>
+*/
+#define FOREACHvertex_i_(vertices) FOREACHsetelement_i_(vertexT, vertices,vertex)
+
+/********* -libqhull.c prototypes (duplicated from qhull_a.h) **********************/
+
+void    qh_qhull(void);
+boolT   qh_addpoint(pointT *furthest, facetT *facet, boolT checkdist);
+void    qh_printsummary(FILE *fp);
+
+/********* -user.c prototypes (alphabetical) **********************/
+
+void    qh_errexit(int exitcode, facetT *facet, ridgeT *ridge);
+void    qh_errprint(const char* string, facetT *atfacet, facetT *otherfacet, ridgeT *atridge, vertexT *atvertex);
+int     qh_new_qhull(int dim, int numpoints, coordT *points, boolT ismalloc,
+                char *qhull_cmd, FILE *outfile, FILE *errfile);
+void    qh_printfacetlist(facetT *facetlist, setT *facets, boolT printall);
+void    qh_printhelp_degenerate(FILE *fp);
+void    qh_printhelp_narrowhull(FILE *fp, realT minangle);
+void    qh_printhelp_singular(FILE *fp);
+void    qh_user_memsizes(void);
+
+/********* -usermem.c prototypes (alphabetical) **********************/
+void    qh_exit(int exitcode);
+void    qh_free(void *mem);
+void   *qh_malloc(size_t size);
+
+/********* -userprintf.c and userprintf_rbox.c prototypes **********************/
+void    qh_fprintf(FILE *fp, int msgcode, const char *fmt, ... );
+void    qh_fprintf_rbox(FILE *fp, int msgcode, const char *fmt, ... );
+
+/***** -geom.c/geom2.c/random.c prototypes (duplicated from geom.h, random.h) ****************/
+
+facetT *qh_findbest(pointT *point, facetT *startfacet,
+                     boolT bestoutside, boolT newfacets, boolT noupper,
+                     realT *dist, boolT *isoutside, int *numpart);
+facetT *qh_findbestnew(pointT *point, facetT *startfacet,
+                     realT *dist, boolT bestoutside, boolT *isoutside, int *numpart);
+boolT   qh_gram_schmidt(int dim, realT **rows);
+void    qh_outerinner(facetT *facet, realT *outerplane, realT *innerplane);
+void    qh_printsummary(FILE *fp);
+void    qh_projectinput(void);
+void    qh_randommatrix(realT *buffer, int dim, realT **row);
+void    qh_rotateinput(realT **rows);
+void    qh_scaleinput(void);
+void    qh_setdelaunay(int dim, int count, pointT *points);
+coordT  *qh_sethalfspace_all(int dim, int count, coordT *halfspaces, pointT *feasible);
+
+/***** -global.c prototypes (alphabetical) ***********************/
+
+unsigned long qh_clock(void);
+void    qh_checkflags(char *command, char *hiddenflags);
+void    qh_clear_outputflags(void);
+void    qh_freebuffers(void);
+void    qh_freeqhull(boolT allmem);
+void    qh_freeqhull2(boolT allmem);
+void    qh_init_A(FILE *infile, FILE *outfile, FILE *errfile, int argc, char *argv[]);
+void    qh_init_B(coordT *points, int numpoints, int dim, boolT ismalloc);
+void    qh_init_qhull_command(int argc, char *argv[]);
+void    qh_initbuffers(coordT *points, int numpoints, int dim, boolT ismalloc);
+void    qh_initflags(char *command);
+void    qh_initqhull_buffers(void);
+void    qh_initqhull_globals(coordT *points, int numpoints, int dim, boolT ismalloc);
+void    qh_initqhull_mem(void);
+void    qh_initqhull_outputflags(void);
+void    qh_initqhull_start(FILE *infile, FILE *outfile, FILE *errfile);
+void    qh_initqhull_start2(FILE *infile, FILE *outfile, FILE *errfile);
+void    qh_initthresholds(char *command);
+void    qh_option(const char *option, int *i, realT *r);
+#if qh_QHpointer
+void    qh_restore_qhull(qhT **oldqh);
+qhT    *qh_save_qhull(void);
+#endif
+
+/***** -io.c prototypes (duplicated from io.h) ***********************/
+
+void    dfacet( unsigned id);
+void    dvertex( unsigned id);
+void    qh_printneighborhood(FILE *fp, qh_PRINT format, facetT *facetA, facetT *facetB, boolT printall);
+void    qh_produce_output(void);
+coordT *qh_readpoints(int *numpoints, int *dimension, boolT *ismalloc);
+
+
+/********* -mem.c prototypes (duplicated from mem.h) **********************/
+
+void qh_meminit(FILE *ferr);
+void qh_memfreeshort(int *curlong, int *totlong);
+
+/********* -poly.c/poly2.c prototypes (duplicated from poly.h) **********************/
+
+void    qh_check_output(void);
+void    qh_check_points(void);
+setT   *qh_facetvertices(facetT *facetlist, setT *facets, boolT allfacets);
+facetT *qh_findbestfacet(pointT *point, boolT bestoutside,
+           realT *bestdist, boolT *isoutside);
+vertexT *qh_nearvertex(facetT *facet, pointT *point, realT *bestdistp);
+pointT *qh_point(int id);
+setT   *qh_pointfacet(void /*qh.facet_list*/);
+int     qh_pointid(pointT *point);
+setT   *qh_pointvertex(void /*qh.facet_list*/);
+void    qh_setvoronoi_all(void);
+void    qh_triangulate(void /*qh facet_list*/);
+
+/********* -rboxpoints.c prototypes **********************/
+int     qh_rboxpoints(FILE* fout, FILE* ferr, char* rbox_command);
+void    qh_errexit_rbox(int exitcode);
+
+/********* -stat.c prototypes (duplicated from stat.h) **********************/
+
+void    qh_collectstatistics(void);
+void    qh_printallstatistics(FILE *fp, const char *string);
+
+#endif /* qhDEFlibqhull */
diff --git a/alg/libqhull/mem.c b/alg/libqhull/mem.c
new file mode 100644
index 0000000..aa8272e
--- /dev/null
+++ b/alg/libqhull/mem.c
@@ -0,0 +1,545 @@
+/*<html><pre>  -<a                             href="qh-mem.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+  mem.c
+    memory management routines for qhull
+
+  This is a standalone program.
+
+  To initialize memory:
+
+    qh_meminit(stderr);
+    qh_meminitbuffers(qh IStracing, qh_MEMalign, 7, qh_MEMbufsize,qh_MEMinitbuf);
+    qh_memsize((int)sizeof(facetT));
+    qh_memsize((int)sizeof(facetT));
+    ...
+    qh_memsetup();
+
+  To free up all memory buffers:
+    qh_memfreeshort(&curlong, &totlong);
+
+  if qh_NOmem,
+    malloc/free is used instead of mem.c
+
+  notes:
+    uses Quickfit algorithm (freelists for commonly allocated sizes)
+    assumes small sizes for freelists (it discards the tail of memory buffers)
+
+  see:
+    qh-mem.htm and mem.h
+    global.c (qh_initbuffers) for an example of using mem.c
+
+  Copyright (c) 1993-2012 The Geometry Center.
+  $Id: //main/2011/qhull/src/libqhull/mem.c#4 $$Change: 1464 $
+  $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+*/
+
+#include "mem.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef qhDEFlibqhull
+typedef struct ridgeT ridgeT;
+typedef struct facetT facetT;
+#ifdef _MSC_VER  /* Microsoft Visual C++ -- warning level 4 */
+#pragma warning( disable : 4127)  /* conditional expression is constant */
+#pragma warning( disable : 4706)  /* assignment within conditional function */
+#endif
+void    qh_errexit(int exitcode, facetT *, ridgeT *);
+void    qh_exit(int exitcode);
+void    qh_fprintf(FILE *fp, int msgcode, const char *fmt, ... );
+void    qh_free(void *mem);
+void   *qh_malloc(size_t size);
+#endif
+
+/*============ -global data structure ==============
+    see mem.h for definition
+*/
+
+qhmemT qhmem= {0,0,0,0,0,0,0,0,0,0,0,
+               0,0,0,0,0,0,0,0,0,0,0,
+               0,0,0,0,0,0,0};     /* remove "= {0}" if this causes a compiler error */
+
+#ifndef qh_NOmem
+
+/*============= internal functions ==============*/
+
+static int qh_intcompare(const void *i, const void *j);
+
+/*========== functions in alphabetical order ======== */
+
+/*-<a                             href="qh-mem.htm#TOC"
+  >-------------------------------</a><a name="intcompare">-</a>
+
+  qh_intcompare( i, j )
+    used by qsort and bsearch to compare two integers
+*/
+static int qh_intcompare(const void *i, const void *j) {
+  return(*((const int *)i) - *((const int *)j));
+} /* intcompare */
+
+
+/*-<a                             href="qh-mem.htm#TOC"
+  >--------------------------------</a><a name="memalloc">-</a>
+
+  qh_memalloc( insize )
+    returns object of insize bytes
+    qhmem is the global memory structure
+
+  returns:
+    pointer to allocated memory
+    errors if insufficient memory
+
+  notes:
+    use explicit type conversion to avoid type warnings on some compilers
+    actual object may be larger than insize
+    use qh_memalloc_() for inline code for quick allocations
+    logs allocations if 'T5'
+
+  design:
+    if size < qhmem.LASTsize
+      if qhmem.freelists[size] non-empty
+        return first object on freelist
+      else
+        round up request to size of qhmem.freelists[size]
+        allocate new allocation buffer if necessary
+        allocate object from allocation buffer
+    else
+      allocate object with qh_malloc() in user.c
+*/
+void *qh_memalloc(int insize) {
+  void **freelistp, *newbuffer;
+  int idx, size, n;
+  int outsize, bufsize;
+  void *object;
+
+  if (insize<0) {
+      qh_fprintf(qhmem.ferr, 6235, "qhull error (qh_memalloc): negative request size (%d).  Did int overflow due to high-D?\n", insize); /* WARN64 */
+      qh_errexit(qhmem_ERRmem, NULL, NULL);
+  }
+  if (insize>=0 && insize <= qhmem.LASTsize) {
+    idx= qhmem.indextable[insize];
+    outsize= qhmem.sizetable[idx];
+    qhmem.totshort += outsize;
+    freelistp= qhmem.freelists+idx;
+    if ((object= *freelistp)) {
+      qhmem.cntquick++;
+      qhmem.totfree -= outsize;
+      *freelistp= *((void **)*freelistp);  /* replace freelist with next object */
+#ifdef qh_TRACEshort
+      n= qhmem.cntshort+qhmem.cntquick+qhmem.freeshort;
+      if (qhmem.IStracing >= 5)
+          qh_fprintf(qhmem.ferr, 8141, "qh_mem %p n %8d alloc quick: %d bytes (tot %d cnt %d)\n", object, n, outsize, qhmem.totshort, qhmem.cntshort+qhmem.cntquick-qhmem.freeshort);
+#endif
+      return(object);
+    }else {
+      qhmem.cntshort++;
+      if (outsize > qhmem .freesize) {
+        qhmem .totdropped += qhmem .freesize;
+        if (!qhmem.curbuffer)
+          bufsize= qhmem.BUFinit;
+        else
+          bufsize= qhmem.BUFsize;
+        if (!(newbuffer= qh_malloc((size_t)bufsize))) {
+          qh_fprintf(qhmem.ferr, 6080, "qhull error (qh_memalloc): insufficient memory to allocate short memory buffer (%d bytes)\n", bufsize);
+          qh_errexit(qhmem_ERRmem, NULL, NULL);
+        }
+        /* newbuffer cannot be NULL since above qh_errexit didn't return */
+        /* coverity[var_deref_op] */
+        *((void **)newbuffer)= qhmem.curbuffer;  /* prepend newbuffer to curbuffer
+                                                    list */
+        qhmem.curbuffer= newbuffer;
+        size= (sizeof(void **) + qhmem.ALIGNmask) & ~qhmem.ALIGNmask;
+        qhmem.freemem= (void *)((char *)newbuffer+size);
+        qhmem.freesize= bufsize - size;
+        qhmem.totbuffer += bufsize - size; /* easier to check */
+        /* Periodically test totbuffer.  It matches at beginning and exit of every call */
+        n = qhmem.totshort + qhmem.totfree + qhmem.totdropped + qhmem.freesize - outsize;
+        if (qhmem.totbuffer != n) {
+            qh_fprintf(qhmem.ferr, 6212, "qh_memalloc internal error: short totbuffer %d != totshort+totfree... %d\n", qhmem.totbuffer, n);
+            qh_errexit(qhmem_ERRmem, NULL, NULL);
+        }
+      }
+      object= qhmem.freemem;
+      qhmem.freemem= (void *)((char *)qhmem.freemem + outsize);
+      qhmem.freesize -= outsize;
+      qhmem.totunused += outsize - insize;
+#ifdef qh_TRACEshort
+      n= qhmem.cntshort+qhmem.cntquick+qhmem.freeshort;
+      if (qhmem.IStracing >= 5)
+          qh_fprintf(qhmem.ferr, 8140, "qh_mem %p n %8d alloc short: %d bytes (tot %d cnt %d)\n", object, n, outsize, qhmem.totshort, qhmem.cntshort+qhmem.cntquick-qhmem.freeshort);
+#endif
+      return object;
+    }
+  }else {                     /* long allocation */
+    if (!qhmem.indextable) {
+      qh_fprintf(qhmem.ferr, 6081, "qhull internal error (qh_memalloc): qhmem has not been initialized.\n");
+      qh_errexit(qhmem_ERRqhull, NULL, NULL);
+    }
+    outsize= insize;
+    qhmem .cntlong++;
+    qhmem .totlong += outsize;
+    if (qhmem.maxlong < qhmem.totlong)
+      qhmem.maxlong= qhmem.totlong;
+    if (!(object= qh_malloc((size_t)outsize))) {
+      qh_fprintf(qhmem.ferr, 6082, "qhull error (qh_memalloc): insufficient memory to allocate %d bytes\n", outsize);
+      qh_errexit(qhmem_ERRmem, NULL, NULL);
+    }
+    if (qhmem.IStracing >= 5)
+      qh_fprintf(qhmem.ferr, 8057, "qh_mem %p n %8d alloc long: %d bytes (tot %d cnt %d)\n", object, qhmem.cntlong+qhmem.freelong, outsize, qhmem.totlong, qhmem.cntlong-qhmem.freelong);
+  }
+  return(object);
+} /* memalloc */
+
+
+/*-<a                             href="qh-mem.htm#TOC"
+  >--------------------------------</a><a name="memfree">-</a>
+
+  qh_memfree( object, insize )
+    free up an object of size bytes
+    size is insize from qh_memalloc
+
+  notes:
+    object may be NULL
+    type checking warns if using (void **)object
+    use qh_memfree_() for quick free's of small objects
+
+  design:
+    if size <= qhmem.LASTsize
+      append object to corresponding freelist
+    else
+      call qh_free(object)
+*/
+void qh_memfree(void *object, int insize) {
+  void **freelistp;
+  int idx, outsize;
+
+  if (!object)
+    return;
+  if (insize <= qhmem.LASTsize) {
+    qhmem .freeshort++;
+    idx= qhmem.indextable[insize];
+    outsize= qhmem.sizetable[idx];
+    qhmem .totfree += outsize;
+    qhmem .totshort -= outsize;
+    freelistp= qhmem.freelists + idx;
+    *((void **)object)= *freelistp;
+    *freelistp= object;
+#ifdef qh_TRACEshort
+    idx= qhmem.cntshort+qhmem.cntquick+qhmem.freeshort;
+    if (qhmem.IStracing >= 5)
+        qh_fprintf(qhmem.ferr, 8142, "qh_mem %p n %8d free short: %d bytes (tot %d cnt %d)\n", object, idx, outsize, qhmem.totshort, qhmem.cntshort+qhmem.cntquick-qhmem.freeshort);
+#endif
+  }else {
+    qhmem .freelong++;
+    qhmem .totlong -= insize;
+    if (qhmem.IStracing >= 5)
+      qh_fprintf(qhmem.ferr, 8058, "qh_mem %p n %8d free long: %d bytes (tot %d cnt %d)\n", object, qhmem.cntlong+qhmem.freelong, insize, qhmem.totlong, qhmem.cntlong-qhmem.freelong);
+    qh_free(object);
+  }
+} /* memfree */
+
+
+/*-<a                             href="qh-mem.htm#TOC"
+  >-------------------------------</a><a name="memfreeshort">-</a>
+
+  qh_memfreeshort( curlong, totlong )
+    frees up all short and qhmem memory allocations
+
+  returns:
+    number and size of current long allocations
+
+  see:
+    qh_freeqhull(allMem)
+    qh_memtotal(curlong, totlong, curshort, totshort, maxlong, totbuffer);
+*/
+void qh_memfreeshort(int *curlong, int *totlong) {
+  void *buffer, *nextbuffer;
+  FILE *ferr;
+
+  *curlong= qhmem .cntlong - qhmem .freelong;
+  *totlong= qhmem .totlong;
+  for (buffer= qhmem.curbuffer; buffer; buffer= nextbuffer) {
+    nextbuffer= *((void **) buffer);
+    qh_free(buffer);
+  }
+  qhmem.curbuffer= NULL;
+  if (qhmem .LASTsize) {
+    qh_free(qhmem .indextable);
+    qh_free(qhmem .freelists);
+    qh_free(qhmem .sizetable);
+  }
+  ferr= qhmem.ferr;
+  memset((char *)&qhmem, 0, sizeof(qhmem));  /* every field is 0, FALSE, NULL */
+  qhmem.ferr= ferr;
+} /* memfreeshort */
+
+
+/*-<a                             href="qh-mem.htm#TOC"
+  >--------------------------------</a><a name="meminit">-</a>
+
+  qh_meminit( ferr )
+    initialize qhmem and test sizeof( void*)
+*/
+void qh_meminit(FILE *ferr) {
+
+  memset((char *)&qhmem, 0, sizeof(qhmem));  /* every field is 0, FALSE, NULL */
+  qhmem.ferr= ferr;
+  if (sizeof(void*) < sizeof(int)) {
+    qh_fprintf(ferr, 6083, "qhull internal error (qh_meminit): sizeof(void*) %d < sizeof(int) %d.  qset.c will not work\n", (int)sizeof(void*), (int)sizeof(int));
+    qh_exit(qhmem_ERRqhull);  /* can not use qh_errexit() */
+  }
+  if (sizeof(void*) > sizeof(ptr_intT)) {
+      qh_fprintf(ferr, 6084, "qhull internal error (qh_meminit): sizeof(void*) %d > sizeof(ptr_intT) %d. Change ptr_intT in mem.h to 'long long'\n", (int)sizeof(void*), (int)sizeof(ptr_intT));
+      qh_exit(qhmem_ERRqhull);  /* can not use qh_errexit() */
+  }
+} /* meminit */
+
+/*-<a                             href="qh-mem.htm#TOC"
+  >-------------------------------</a><a name="meminitbuffers">-</a>
+
+  qh_meminitbuffers( tracelevel, alignment, numsizes, bufsize, bufinit )
+    initialize qhmem
+    if tracelevel >= 5, trace memory allocations
+    alignment= desired address alignment for memory allocations
+    numsizes= number of freelists
+    bufsize=  size of additional memory buffers for short allocations
+    bufinit=  size of initial memory buffer for short allocations
+*/
+void qh_meminitbuffers(int tracelevel, int alignment, int numsizes, int bufsize, int bufinit) {
+
+  qhmem.IStracing= tracelevel;
+  qhmem.NUMsizes= numsizes;
+  qhmem.BUFsize= bufsize;
+  qhmem.BUFinit= bufinit;
+  qhmem.ALIGNmask= alignment-1;
+  if (qhmem.ALIGNmask & ~qhmem.ALIGNmask) {
+    qh_fprintf(qhmem.ferr, 6085, "qhull internal error (qh_meminit): memory alignment %d is not a power of 2\n", alignment);
+    qh_errexit(qhmem_ERRqhull, NULL, NULL);
+  }
+  qhmem.sizetable= (int *) calloc((size_t)numsizes, sizeof(int));
+  qhmem.freelists= (void **) calloc((size_t)numsizes, sizeof(void *));
+  if (!qhmem.sizetable || !qhmem.freelists) {
+    qh_fprintf(qhmem.ferr, 6086, "qhull error (qh_meminit): insufficient memory\n");
+    qh_errexit(qhmem_ERRmem, NULL, NULL);
+  }
+  if (qhmem.IStracing >= 1)
+    qh_fprintf(qhmem.ferr, 8059, "qh_meminitbuffers: memory initialized with alignment %d\n", alignment);
+} /* meminitbuffers */
+
+/*-<a                             href="qh-mem.htm#TOC"
+  >-------------------------------</a><a name="memsetup">-</a>
+
+  qh_memsetup()
+    set up memory after running memsize()
+*/
+void qh_memsetup(void) {
+  int k,i;
+
+  qsort(qhmem.sizetable, (size_t)qhmem.TABLEsize, sizeof(int), qh_intcompare);
+  qhmem.LASTsize= qhmem.sizetable[qhmem.TABLEsize-1];
+  if (qhmem .LASTsize >= qhmem .BUFsize || qhmem.LASTsize >= qhmem .BUFinit) {
+    qh_fprintf(qhmem.ferr, 6087, "qhull error (qh_memsetup): largest mem size %d is >= buffer size %d or initial buffer size %d\n",
+            qhmem .LASTsize, qhmem .BUFsize, qhmem .BUFinit);
+    qh_errexit(qhmem_ERRmem, NULL, NULL);
+  }
+  if (!(qhmem.indextable= (int *)qh_malloc((qhmem.LASTsize+1) * sizeof(int)))) {
+    qh_fprintf(qhmem.ferr, 6088, "qhull error (qh_memsetup): insufficient memory\n");
+    qh_errexit(qhmem_ERRmem, NULL, NULL);
+  }
+  for (k=qhmem.LASTsize+1; k--; )
+    qhmem.indextable[k]= k;
+  i= 0;
+  for (k=0; k <= qhmem.LASTsize; k++) {
+    if (qhmem.indextable[k] <= qhmem.sizetable[i])
+      qhmem.indextable[k]= i;
+    else
+      qhmem.indextable[k]= ++i;
+  }
+} /* memsetup */
+
+/*-<a                             href="qh-mem.htm#TOC"
+  >-------------------------------</a><a name="memsize">-</a>
+
+  qh_memsize( size )
+    define a free list for this size
+*/
+void qh_memsize(int size) {
+  int k;
+
+  if (qhmem .LASTsize) {
+    qh_fprintf(qhmem.ferr, 6089, "qhull error (qh_memsize): called after qhmem_setup\n");
+    qh_errexit(qhmem_ERRqhull, NULL, NULL);
+  }
+  size= (size + qhmem.ALIGNmask) & ~qhmem.ALIGNmask;
+  for (k=qhmem.TABLEsize; k--; ) {
+    if (qhmem.sizetable[k] == size)
+      return;
+  }
+  if (qhmem.TABLEsize < qhmem.NUMsizes)
+    qhmem.sizetable[qhmem.TABLEsize++]= size;
+  else
+    qh_fprintf(qhmem.ferr, 7060, "qhull warning (memsize): free list table has room for only %d sizes\n", qhmem.NUMsizes);
+} /* memsize */
+
+
+/*-<a                             href="qh-mem.htm#TOC"
+  >-------------------------------</a><a name="memstatistics">-</a>
+
+  qh_memstatistics( fp )
+    print out memory statistics
+
+    Verifies that qhmem.totfree == sum of freelists
+*/
+void qh_memstatistics(FILE *fp) {
+  int i, count, totfree= 0;
+  void *object;
+
+  for (i=0; i < qhmem.TABLEsize; i++) {
+    count=0;
+    for (object= qhmem .freelists[i]; object; object= *((void **)object))
+      count++;
+    totfree += qhmem.sizetable[i] * count;
+  }
+  if (totfree != qhmem .totfree) {
+      qh_fprintf(qhmem.ferr, 6211, "qh_memstatistics internal error: totfree %d not equal to freelist total %d\n", qhmem.totfree, totfree);
+      qh_errexit(qhmem_ERRqhull, NULL, NULL);
+  }
+  qh_fprintf(fp, 9278, "\nmemory statistics:\n\
+%7d quick allocations\n\
+%7d short allocations\n\
+%7d long allocations\n\
+%7d short frees\n\
+%7d long frees\n\
+%7d bytes of short memory in use\n\
+%7d bytes of short memory in freelists\n\
+%7d bytes of dropped short memory\n\
+%7d bytes of unused short memory (estimated)\n\
+%7d bytes of long memory allocated (max, except for input)\n\
+%7d bytes of long memory in use (in %d pieces)\n\
+%7d bytes of short memory buffers (minus links)\n\
+%7d bytes per short memory buffer (initially %d bytes)\n",
+           qhmem .cntquick, qhmem .cntshort, qhmem .cntlong,
+           qhmem .freeshort, qhmem .freelong,
+           qhmem .totshort, qhmem .totfree,
+           qhmem .totdropped + qhmem .freesize, qhmem .totunused,
+           qhmem .maxlong, qhmem .totlong, qhmem .cntlong - qhmem .freelong,
+           qhmem .totbuffer, qhmem .BUFsize, qhmem .BUFinit);
+  if (qhmem.cntlarger) {
+    qh_fprintf(fp, 9279, "%7d calls to qh_setlarger\n%7.2g     average copy size\n",
+           qhmem.cntlarger, ((float)qhmem.totlarger)/(float)qhmem.cntlarger);
+    qh_fprintf(fp, 9280, "  freelists(bytes->count):");
+  }
+  for (i=0; i < qhmem.TABLEsize; i++) {
+    count=0;
+    for (object= qhmem .freelists[i]; object; object= *((void **)object))
+      count++;
+    qh_fprintf(fp, 9281, " %d->%d", qhmem.sizetable[i], count);
+  }
+  qh_fprintf(fp, 9282, "\n\n");
+} /* memstatistics */
+
+
+/*-<a                             href="qh-mem.htm#TOC"
+  >-------------------------------</a><a name="NOmem">-</a>
+
+  qh_NOmem
+    turn off quick-fit memory allocation
+
+  notes:
+    uses qh_malloc() and qh_free() instead
+*/
+#else /* qh_NOmem */
+
+void *qh_memalloc(int insize) {
+  void *object;
+
+  if (!(object= qh_malloc((size_t)insize))) {
+    qh_fprintf(qhmem.ferr, 6090, "qhull error (qh_memalloc): insufficient memory\n");
+    qh_errexit(qhmem_ERRmem, NULL, NULL);
+  }
+  qhmem .cntlong++;
+  qhmem .totlong += insize;
+  if (qhmem.maxlong < qhmem.totlong)
+      qhmem.maxlong= qhmem.totlong;
+  if (qhmem.IStracing >= 5)
+    qh_fprintf(qhmem.ferr, 8060, "qh_mem %p n %8d alloc long: %d bytes (tot %d cnt %d)\n", object, qhmem.cntlong+qhmem.freelong, insize, qhmem.totlong, qhmem.cntlong-qhmem.freelong);
+  return object;
+}
+
+void qh_memfree(void *object, int insize) {
+
+  if (!object)
+    return;
+  qh_free(object);
+  qhmem .freelong++;
+  qhmem .totlong -= insize;
+  if (qhmem.IStracing >= 5)
+    qh_fprintf(qhmem.ferr, 8061, "qh_mem %p n %8d free long: %d bytes (tot %d cnt %d)\n", object, qhmem.cntlong+qhmem.freelong, insize, qhmem.totlong, qhmem.cntlong-qhmem.freelong);
+}
+
+void qh_memfreeshort(int *curlong, int *totlong) {
+  *totlong= qhmem .totlong;
+  *curlong= qhmem .cntlong - qhmem .freelong;
+  memset((char *)&qhmem, 0, sizeof(qhmem));  /* every field is 0, FALSE, NULL */
+}
+
+void qh_meminit(FILE *ferr) {
+
+  memset((char *)&qhmem, 0, sizeof(qhmem));  /* every field is 0, FALSE, NULL */
+  qhmem.ferr= ferr;
+  if (sizeof(void*) < sizeof(int)) {
+    qh_fprintf(ferr, 6091, "qhull internal error (qh_meminit): sizeof(void*) %d < sizeof(int) %d.  qset.c will not work\n", (int)sizeof(void*), (int)sizeof(int));
+    qh_errexit(qhmem_ERRqhull, NULL, NULL);
+  }
+}
+
+void qh_meminitbuffers(int tracelevel, int alignment, int numsizes, int bufsize, int bufinit) {
+
+  qhmem.IStracing= tracelevel;
+}
+
+void qh_memsetup(void) {
+
+}
+
+void qh_memsize(int size) {
+
+}
+
+void qh_memstatistics(FILE *fp) {
+
+  qh_fprintf(fp, 9409, "\nmemory statistics:\n\
+%7d long allocations\n\
+%7d long frees\n\
+%7d bytes of long memory allocated (max, except for input)\n\
+%7d bytes of long memory in use (in %d pieces)\n",
+           qhmem .cntlong,
+           qhmem .freelong,
+           qhmem .maxlong, qhmem .totlong, qhmem .cntlong - qhmem .freelong);
+}
+
+#endif /* qh_NOmem */
+
+/*-<a                             href="qh-mem.htm#TOC"
+>-------------------------------</a><a name="memtotlong">-</a>
+
+  qh_memtotal( totlong, curlong, totshort, curshort, maxlong, totbuffer )
+    Return the total, allocated long and short memory
+
+  returns:
+    Returns the total current bytes of long and short allocations
+    Returns the current count of long and short allocations
+    Returns the maximum long memory and total short buffer (minus one link per buffer)
+    Does not error (UsingLibQhull.cpp)
+*/
+void qh_memtotal(int *totlong, int *curlong, int *totshort, int *curshort, int *maxlong, int *totbuffer) {
+    *totlong= qhmem .totlong;
+    *curlong= qhmem .cntlong - qhmem .freelong;
+    *totshort= qhmem .totshort;
+    *curshort= qhmem .cntshort + qhmem .cntquick - qhmem .freeshort;
+    *maxlong= qhmem .maxlong;
+    *totbuffer= qhmem .totbuffer;
+} /* memtotlong */
+
diff --git a/alg/libqhull/mem.h b/alg/libqhull/mem.h
new file mode 100644
index 0000000..ee29458
--- /dev/null
+++ b/alg/libqhull/mem.h
@@ -0,0 +1,219 @@
+/*<html><pre>  -<a                             href="qh-mem.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   mem.h
+     prototypes for memory management functions
+
+   see qh-mem.htm, mem.c and qset.h
+
+   for error handling, writes message and calls
+     qh_errexit(qhmem_ERRmem, NULL, NULL) if insufficient memory
+       and
+     qh_errexit(qhmem_ERRqhull, NULL, NULL) otherwise
+
+   Copyright (c) 1993-2012 The Geometry Center.
+   $Id: //main/2011/qhull/src/libqhull/mem.h#4 $$Change: 1464 $
+   $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+*/
+
+#ifndef qhDEFmem
+#define qhDEFmem 1
+
+#include <stdio.h>
+
+/*-<a                             href="qh-mem.htm#TOC"
+  >-------------------------------</a><a name="NOmem">-</a>
+
+  qh_NOmem
+    turn off quick-fit memory allocation
+
+  notes:
+    mem.c implements Quickfit memory allocation for about 20% time
+    savings.  If it fails on your machine, try to locate the
+    problem, and send the answer to qhull at qhull.org.  If this can
+    not be done, define qh_NOmem to use malloc/free instead.
+
+   #define qh_NOmem
+*/
+
+/*-<a                             href="qh-mem.htm#TOC"
+>-------------------------------</a><a name="TRACEshort">-</a>
+
+qh_TRACEshort
+Trace short and quick memory allocations at T5
+
+*/
+#define qh_TRACEshort
+
+/*-------------------------------------------
+    to avoid bus errors, memory allocation must consider alignment requirements.
+    malloc() automatically takes care of alignment.   Since mem.c manages
+    its own memory, we need to explicitly specify alignment in
+    qh_meminitbuffers().
+
+    A safe choice is sizeof(double).  sizeof(float) may be used if doubles
+    do not occur in data structures and pointers are the same size.  Be careful
+    of machines (e.g., DEC Alpha) with large pointers.  If gcc is available,
+    use __alignof__(double) or fmax_(__alignof__(float), __alignof__(void *)).
+
+   see <a href="user.h#MEMalign">qh_MEMalign</a> in user.h for qhull's alignment
+*/
+
+#define qhmem_ERRmem 4    /* matches qh_ERRmem in libqhull.h */
+#define qhmem_ERRqhull 5  /* matches qh_ERRqhull in libqhull.h */
+
+/*-<a                             href="qh-mem.htm#TOC"
+  >--------------------------------</a><a name="ptr_intT">-</a>
+
+  ptr_intT
+    for casting a void * to an integer-type that holds a pointer
+    Used for integer expressions (e.g., computing qh_gethash() in poly.c)
+
+  notes:
+    WARN64 -- these notes indicate 64-bit issues
+    On 64-bit machines, a pointer may be larger than an 'int'.
+    qh_meminit()/mem.c checks that 'ptr_intT' holds a 'void*'
+    ptr_intT is typically a signed value, but not necessarily so
+    size_t is typically unsigned, but should match the parameter type
+    Qhull uses int instead of size_t except for system calls such as malloc, qsort, qh_malloc, etc.
+    This matches Qt convention and is easier to work with.
+*/
+#if _MSC_VER && defined(_WIN64)
+typedef long long ptr_intT;
+#else
+typedef long ptr_intT;
+#endif
+
+/*-<a                             href="qh-mem.htm#TOC"
+  >--------------------------------</a><a name="qhmemT">-</a>
+
+  qhmemT
+    global memory structure for mem.c
+
+ notes:
+   users should ignore qhmem except for writing extensions
+   qhmem is allocated in mem.c
+
+   qhmem could be swapable like qh and qhstat, but then
+   multiple qh's and qhmem's would need to keep in sync.
+   A swapable qhmem would also waste memory buffers.  As long
+   as memory operations are atomic, there is no problem with
+   multiple qh structures being active at the same time.
+   If you need separate address spaces, you can swap the
+   contents of qhmem.
+*/
+typedef struct qhmemT qhmemT;
+extern qhmemT qhmem;
+
+#ifndef DEFsetT
+#define DEFsetT 1
+typedef struct setT setT;          /* defined in qset.h */
+#endif
+
+/* Update qhmem in mem.c if add or remove fields */
+struct qhmemT {               /* global memory management variables */
+  int      BUFsize;           /* size of memory allocation buffer */
+  int      BUFinit;           /* initial size of memory allocation buffer */
+  int      TABLEsize;         /* actual number of sizes in free list table */
+  int      NUMsizes;          /* maximum number of sizes in free list table */
+  int      LASTsize;          /* last size in free list table */
+  int      ALIGNmask;         /* worst-case alignment, must be 2^n-1 */
+  void   **freelists;          /* free list table, linked by offset 0 */
+  int     *sizetable;         /* size of each freelist */
+  int     *indextable;        /* size->index table */
+  void    *curbuffer;         /* current buffer, linked by offset 0 */
+  void    *freemem;           /*   free memory in curbuffer */
+  int      freesize;          /*   size of freemem in bytes */
+  setT    *tempstack;         /* stack of temporary memory, managed by users */
+  FILE    *ferr;              /* file for reporting errors, only user is qh_fprintf() */
+  int      IStracing;         /* =5 if tracing memory allocations */
+  int      cntquick;          /* count of quick allocations */
+                              /* Note: removing statistics doesn't effect speed */
+  int      cntshort;          /* count of short allocations */
+  int      cntlong;           /* count of long allocations */
+  int      freeshort;         /* count of short memfrees */
+  int      freelong;          /* count of long memfrees */
+  int      totbuffer;         /* total short memory buffers minus buffer links */
+  int      totdropped;        /* total dropped memory at end of short memory buffers (e.g., freesize) */
+  int      totfree;           /* total size of free, short memory on freelists */
+  int      totlong;           /* total size of long memory in use */
+  int      maxlong;           /*   maximum totlong */
+  int      totshort;          /* total size of short memory in use */
+  int      totunused;         /* total unused short memory (estimated, short size - request size of first allocations) */
+  int      cntlarger;         /* count of setlarger's */
+  int      totlarger;         /* total copied by setlarger */
+};
+
+
+/*==================== -macros ====================*/
+
+/*-<a                             href="qh-mem.htm#TOC"
+  >--------------------------------</a><a name="memalloc_">-</a>
+
+  qh_memalloc_(insize, object, type)
+    returns object of size bytes
+        assumes size<=qhmem.LASTsize and void **freelistp is a temp
+*/
+
+#if defined qh_NOmem
+#define qh_memalloc_(insize, freelistp, object, type) {\
+  object= (type*)qh_memalloc(insize); }
+#elif defined qh_TRACEshort
+#define qh_memalloc_(insize, freelistp, object, type) {\
+    freelistp= NULL; /* Avoid warnings */ \
+    object= (type*)qh_memalloc(insize); }
+#else /* !qh_NOmem */
+
+#define qh_memalloc_(insize, freelistp, object, type) {\
+  freelistp= qhmem.freelists + qhmem.indextable[insize];\
+  if ((object= (type*)*freelistp)) {\
+    qhmem.totshort += qhmem.sizetable[qhmem.indextable[insize]]; \
+    qhmem.totfree -= qhmem.sizetable[qhmem.indextable[insize]]; \
+    qhmem.cntquick++;  \
+    *freelistp= *((void **)*freelistp);\
+  }else object= (type*)qh_memalloc(insize);}
+#endif
+
+/*-<a                             href="qh-mem.htm#TOC"
+  >--------------------------------</a><a name="memfree_">-</a>
+
+  qh_memfree_(object, insize)
+    free up an object
+
+  notes:
+    object may be NULL
+    assumes size<=qhmem.LASTsize and void **freelistp is a temp
+*/
+#if defined qh_NOmem
+#define qh_memfree_(object, insize, freelistp) {\
+  qh_memfree(object, insize); }
+#elif defined qh_TRACEshort
+#define qh_memfree_(object, insize, freelistp) {\
+    freelistp= NULL; /* Avoid warnings */ \
+    qh_memfree(object, insize); }
+#else /* !qh_NOmem */
+
+#define qh_memfree_(object, insize, freelistp) {\
+  if (object) { \
+    qhmem .freeshort++;\
+    freelistp= qhmem.freelists + qhmem.indextable[insize];\
+    qhmem.totshort -= qhmem.sizetable[qhmem.indextable[insize]]; \
+    qhmem.totfree += qhmem.sizetable[qhmem.indextable[insize]]; \
+    *((void **)object)= *freelistp;\
+    *freelistp= object;}}
+#endif
+
+/*=============== prototypes in alphabetical order ============*/
+
+void *qh_memalloc(int insize);
+void qh_memfree(void *object, int insize);
+void qh_memfreeshort(int *curlong, int *totlong);
+void qh_meminit(FILE *ferr);
+void qh_meminitbuffers(int tracelevel, int alignment, int numsizes,
+                        int bufsize, int bufinit);
+void qh_memsetup(void);
+void qh_memsize(int size);
+void qh_memstatistics(FILE *fp);
+void qh_memtotal(int *totlong, int *curlong, int *totshort, int *curshort, int *maxlong, int *totbuffer);
+
+#endif /* qhDEFmem */
diff --git a/alg/libqhull/merge.c b/alg/libqhull/merge.c
new file mode 100644
index 0000000..1ad6842
--- /dev/null
+++ b/alg/libqhull/merge.c
@@ -0,0 +1,3623 @@
+/*<html><pre>  -<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   merge.c
+   merges non-convex facets
+
+   see qh-merge.htm and merge.h
+
+   other modules call qh_premerge() and qh_postmerge()
+
+   the user may call qh_postmerge() to perform additional merges.
+
+   To remove deleted facets and vertices (qhull() in libqhull.c):
+     qh_partitionvisible(!qh_ALL, &numoutside);  // visible_list, newfacet_list
+     qh_deletevisible();         // qh.visible_list
+     qh_resetlists(False, qh_RESETvisible);       // qh.visible_list newvertex_list newfacet_list
+
+   assumes qh.CENTERtype= centrum
+
+   merges occur in qh_mergefacet and in qh_mergecycle
+   vertex->neighbors not set until the first merge occurs
+
+   Copyright (c) 1993-2012 C.B. Barber.
+   $Id: //main/2011/qhull/src/libqhull/merge.c#4 $$Change: 1490 $
+   $DateTime: 2012/02/19 20:27:01 $$Author: bbarber $
+*/
+
+#include "qhull_a.h"
+
+#ifndef qh_NOmerge
+
+/*===== functions(alphabetical after premerge and postmerge) ======*/
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="premerge">-</a>
+
+  qh_premerge( apex, maxcentrum )
+    pre-merge nonconvex facets in qh.newfacet_list for apex
+    maxcentrum defines coplanar and concave (qh_test_appendmerge)
+
+  returns:
+    deleted facets added to qh.visible_list with facet->visible set
+
+  notes:
+    uses globals, qh.MERGEexact, qh.PREmerge
+
+  design:
+    mark duplicate ridges in qh.newfacet_list
+    merge facet cycles in qh.newfacet_list
+    merge duplicate ridges and concave facets in qh.newfacet_list
+    check merged facet cycles for degenerate and redundant facets
+    merge degenerate and redundant facets
+    collect coplanar and concave facets
+    merge concave, coplanar, degenerate, and redundant facets
+*/
+void qh_premerge(vertexT *apex, realT maxcentrum, realT maxangle) {
+  boolT othermerge= False;
+  facetT *newfacet;
+
+  if (qh ZEROcentrum && qh_checkzero(!qh_ALL))
+    return;
+  trace2((qh ferr, 2008, "qh_premerge: premerge centrum %2.2g angle %2.2g for apex v%d facetlist f%d\n",
+            maxcentrum, maxangle, apex->id, getid_(qh newfacet_list)));
+  if (qh IStracing >= 4 && qh num_facets < 50)
+    qh_printlists();
+  qh centrum_radius= maxcentrum;
+  qh cos_max= maxangle;
+  qh degen_mergeset= qh_settemp(qh TEMPsize);
+  qh facet_mergeset= qh_settemp(qh TEMPsize);
+  if (qh hull_dim >=3) {
+    qh_mark_dupridges(qh newfacet_list); /* facet_mergeset */
+    qh_mergecycle_all(qh newfacet_list, &othermerge);
+    qh_forcedmerges(&othermerge /* qh facet_mergeset */);
+    FORALLnew_facets {  /* test samecycle merges */
+      if (!newfacet->simplicial && !newfacet->mergeridge)
+        qh_degen_redundant_neighbors(newfacet, NULL);
+    }
+    if (qh_merge_degenredundant())
+      othermerge= True;
+  }else /* qh hull_dim == 2 */
+    qh_mergecycle_all(qh newfacet_list, &othermerge);
+  qh_flippedmerges(qh newfacet_list, &othermerge);
+  if (!qh MERGEexact || zzval_(Ztotmerge)) {
+    zinc_(Zpremergetot);
+    qh POSTmerging= False;
+    qh_getmergeset_initial(qh newfacet_list);
+    qh_all_merges(othermerge, False);
+  }
+  qh_settempfree(&qh facet_mergeset);
+  qh_settempfree(&qh degen_mergeset);
+} /* premerge */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="postmerge">-</a>
+
+  qh_postmerge( reason, maxcentrum, maxangle, vneighbors )
+    post-merge nonconvex facets as defined by maxcentrum and maxangle
+    'reason' is for reporting progress
+    if vneighbors,
+      calls qh_test_vneighbors at end of qh_all_merge
+    if firstmerge,
+      calls qh_reducevertices before qh_getmergeset
+
+  returns:
+    if first call (qh.visible_list != qh.facet_list),
+      builds qh.facet_newlist, qh.newvertex_list
+    deleted facets added to qh.visible_list with facet->visible
+    qh.visible_list == qh.facet_list
+
+  notes:
+
+
+  design:
+    if first call
+      set qh.visible_list and qh.newfacet_list to qh.facet_list
+      add all facets to qh.newfacet_list
+      mark non-simplicial facets, facet->newmerge
+      set qh.newvertex_list to qh.vertex_list
+      add all vertices to qh.newvertex_list
+      if a pre-merge occurred
+        set vertex->delridge {will retest the ridge}
+        if qh.MERGEexact
+          call qh_reducevertices()
+      if no pre-merging
+        merge flipped facets
+    determine non-convex facets
+    merge all non-convex facets
+*/
+void qh_postmerge(const char *reason, realT maxcentrum, realT maxangle,
+                      boolT vneighbors) {
+  facetT *newfacet;
+  boolT othermerges= False;
+  vertexT *vertex;
+
+  if (qh REPORTfreq || qh IStracing) {
+    qh_buildtracing(NULL, NULL);
+    qh_printsummary(qh ferr);
+    if (qh PRINTstatistics)
+      qh_printallstatistics(qh ferr, "reason");
+    qh_fprintf(qh ferr, 8062, "\n%s with 'C%.2g' and 'A%.2g'\n",
+        reason, maxcentrum, maxangle);
+  }
+  trace2((qh ferr, 2009, "qh_postmerge: postmerge.  test vneighbors? %d\n",
+            vneighbors));
+  qh centrum_radius= maxcentrum;
+  qh cos_max= maxangle;
+  qh POSTmerging= True;
+  qh degen_mergeset= qh_settemp(qh TEMPsize);
+  qh facet_mergeset= qh_settemp(qh TEMPsize);
+  if (qh visible_list != qh facet_list) {  /* first call */
+    qh NEWfacets= True;
+    qh visible_list= qh newfacet_list= qh facet_list;
+    FORALLnew_facets {
+      newfacet->newfacet= True;
+       if (!newfacet->simplicial)
+        newfacet->newmerge= True;
+     zinc_(Zpostfacets);
+    }
+    qh newvertex_list= qh vertex_list;
+    FORALLvertices
+      vertex->newlist= True;
+    if (qh VERTEXneighbors) { /* a merge has occurred */
+      FORALLvertices
+        vertex->delridge= True; /* test for redundant, needed? */
+      if (qh MERGEexact) {
+        if (qh hull_dim <= qh_DIMreduceBuild)
+          qh_reducevertices(); /* was skipped during pre-merging */
+      }
+    }
+    if (!qh PREmerge && !qh MERGEexact)
+      qh_flippedmerges(qh newfacet_list, &othermerges);
+  }
+  qh_getmergeset_initial(qh newfacet_list);
+  qh_all_merges(False, vneighbors);
+  qh_settempfree(&qh facet_mergeset);
+  qh_settempfree(&qh degen_mergeset);
+} /* post_merge */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="all_merges">-</a>
+
+  qh_all_merges( othermerge, vneighbors )
+    merge all non-convex facets
+
+    set othermerge if already merged facets (for qh_reducevertices)
+    if vneighbors
+      tests vertex neighbors for convexity at end
+    qh.facet_mergeset lists the non-convex ridges in qh_newfacet_list
+    qh.degen_mergeset is defined
+    if qh.MERGEexact && !qh.POSTmerging,
+      does not merge coplanar facets
+
+  returns:
+    deleted facets added to qh.visible_list with facet->visible
+    deleted vertices added qh.delvertex_list with vertex->delvertex
+
+  notes:
+    unless !qh.MERGEindependent,
+      merges facets in independent sets
+    uses qh.newfacet_list as argument since merges call qh_removefacet()
+
+  design:
+    while merges occur
+      for each merge in qh.facet_mergeset
+        unless one of the facets was already merged in this pass
+          merge the facets
+        test merged facets for additional merges
+        add merges to qh.facet_mergeset
+      if vertices record neighboring facets
+        rename redundant vertices
+          update qh.facet_mergeset
+    if vneighbors ??
+      tests vertex neighbors for convexity at end
+*/
+void qh_all_merges(boolT othermerge, boolT vneighbors) {
+  facetT *facet1, *facet2;
+  mergeT *merge;
+  boolT wasmerge= True, isreduce;
+  void **freelistp;  /* used !qh_NOmem */
+  vertexT *vertex;
+  mergeType mergetype;
+  int numcoplanar=0, numconcave=0, numdegenredun= 0, numnewmerges= 0;
+
+  trace2((qh ferr, 2010, "qh_all_merges: starting to merge facets beginning from f%d\n",
+            getid_(qh newfacet_list)));
+  while (True) {
+    wasmerge= False;
+    while (qh_setsize(qh facet_mergeset)) {
+      while ((merge= (mergeT*)qh_setdellast(qh facet_mergeset))) {
+        facet1= merge->facet1;
+        facet2= merge->facet2;
+        mergetype= merge->type;
+        qh_memfree_(merge, (int)sizeof(mergeT), freelistp);
+        if (facet1->visible || facet2->visible) /*deleted facet*/
+          continue;
+        if ((facet1->newfacet && !facet1->tested)
+                || (facet2->newfacet && !facet2->tested)) {
+          if (qh MERGEindependent && mergetype <= MRGanglecoplanar)
+            continue;      /* perform independent sets of merges */
+        }
+        qh_merge_nonconvex(facet1, facet2, mergetype);
+        numdegenredun += qh_merge_degenredundant();
+        numnewmerges++;
+        wasmerge= True;
+        if (mergetype == MRGconcave)
+          numconcave++;
+        else /* MRGcoplanar or MRGanglecoplanar */
+          numcoplanar++;
+      } /* while setdellast */
+      if (qh POSTmerging && qh hull_dim <= qh_DIMreduceBuild
+      && numnewmerges > qh_MAXnewmerges) {
+        numnewmerges= 0;
+        qh_reducevertices();  /* otherwise large post merges too slow */
+      }
+      qh_getmergeset(qh newfacet_list); /* facet_mergeset */
+    } /* while mergeset */
+    if (qh VERTEXneighbors) {
+      isreduce= False;
+      if (qh hull_dim >=4 && qh POSTmerging) {
+        FORALLvertices
+          vertex->delridge= True;
+        isreduce= True;
+      }
+      if ((wasmerge || othermerge) && (!qh MERGEexact || qh POSTmerging)
+          && qh hull_dim <= qh_DIMreduceBuild) {
+        othermerge= False;
+        isreduce= True;
+      }
+      if (isreduce) {
+        if (qh_reducevertices()) {
+          qh_getmergeset(qh newfacet_list); /* facet_mergeset */
+          continue;
+        }
+      }
+    }
+    if (vneighbors && qh_test_vneighbors(/* qh newfacet_list */))
+      continue;
+    break;
+  } /* while (True) */
+  if (qh CHECKfrequently && !qh MERGEexact) {
+    qh old_randomdist= qh RANDOMdist;
+    qh RANDOMdist= False;
+    qh_checkconvex(qh newfacet_list, qh_ALGORITHMfault);
+    /* qh_checkconnect(); [this is slow and it changes the facet order] */
+    qh RANDOMdist= qh old_randomdist;
+  }
+  trace1((qh ferr, 1009, "qh_all_merges: merged %d coplanar facets %d concave facets and %d degen or redundant facets.\n",
+    numcoplanar, numconcave, numdegenredun));
+  if (qh IStracing >= 4 && qh num_facets < 50)
+    qh_printlists();
+} /* all_merges */
+
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="appendmergeset">-</a>
+
+  qh_appendmergeset( facet, neighbor, mergetype, angle )
+    appends an entry to qh.facet_mergeset or qh.degen_mergeset
+
+    angle ignored if NULL or !qh.ANGLEmerge
+
+  returns:
+    merge appended to facet_mergeset or degen_mergeset
+      sets ->degenerate or ->redundant if degen_mergeset
+
+  see:
+    qh_test_appendmerge()
+
+  design:
+    allocate merge entry
+    if regular merge
+      append to qh.facet_mergeset
+    else if degenerate merge and qh.facet_mergeset is all degenerate
+      append to qh.degen_mergeset
+    else if degenerate merge
+      prepend to qh.degen_mergeset
+    else if redundant merge
+      append to qh.degen_mergeset
+*/
+void qh_appendmergeset(facetT *facet, facetT *neighbor, mergeType mergetype, realT *angle) {
+  mergeT *merge, *lastmerge;
+  void **freelistp; /* used !qh_NOmem */
+
+  if (facet->redundant)
+    return;
+  if (facet->degenerate && mergetype == MRGdegen)
+    return;
+  qh_memalloc_((int)sizeof(mergeT), freelistp, merge, mergeT);
+  merge->facet1= facet;
+  merge->facet2= neighbor;
+  merge->type= mergetype;
+  if (angle && qh ANGLEmerge)
+    merge->angle= *angle;
+  if (mergetype < MRGdegen)
+    qh_setappend(&(qh facet_mergeset), merge);
+  else if (mergetype == MRGdegen) {
+    facet->degenerate= True;
+    if (!(lastmerge= (mergeT*)qh_setlast(qh degen_mergeset))
+    || lastmerge->type == MRGdegen)
+      qh_setappend(&(qh degen_mergeset), merge);
+    else
+      qh_setaddnth(&(qh degen_mergeset), 0, merge);
+  }else if (mergetype == MRGredundant) {
+    facet->redundant= True;
+    qh_setappend(&(qh degen_mergeset), merge);
+  }else /* mergetype == MRGmirror */ {
+    if (facet->redundant || neighbor->redundant) {
+      qh_fprintf(qh ferr, 6092, "qhull error (qh_appendmergeset): facet f%d or f%d is already a mirrored facet\n",
+           facet->id, neighbor->id);
+      qh_errexit2 (qh_ERRqhull, facet, neighbor);
+    }
+    if (!qh_setequal(facet->vertices, neighbor->vertices)) {
+      qh_fprintf(qh ferr, 6093, "qhull error (qh_appendmergeset): mirrored facets f%d and f%d do not have the same vertices\n",
+           facet->id, neighbor->id);
+      qh_errexit2 (qh_ERRqhull, facet, neighbor);
+    }
+    facet->redundant= True;
+    neighbor->redundant= True;
+    qh_setappend(&(qh degen_mergeset), merge);
+  }
+} /* appendmergeset */
+
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="basevertices">-</a>
+
+  qh_basevertices( samecycle )
+    return temporary set of base vertices for samecycle
+    samecycle is first facet in the cycle
+    assumes apex is SETfirst_( samecycle->vertices )
+
+  returns:
+    vertices(settemp)
+    all ->seen are cleared
+
+  notes:
+    uses qh_vertex_visit;
+
+  design:
+    for each facet in samecycle
+      for each unseen vertex in facet->vertices
+        append to result
+*/
+setT *qh_basevertices(facetT *samecycle) {
+  facetT *same;
+  vertexT *apex, *vertex, **vertexp;
+  setT *vertices= qh_settemp(qh TEMPsize);
+
+  apex= SETfirstt_(samecycle->vertices, vertexT);
+  apex->visitid= ++qh vertex_visit;
+  FORALLsame_cycle_(samecycle) {
+    if (same->mergeridge)
+      continue;
+    FOREACHvertex_(same->vertices) {
+      if (vertex->visitid != qh vertex_visit) {
+        qh_setappend(&vertices, vertex);
+        vertex->visitid= qh vertex_visit;
+        vertex->seen= False;
+      }
+    }
+  }
+  trace4((qh ferr, 4019, "qh_basevertices: found %d vertices\n",
+         qh_setsize(vertices)));
+  return vertices;
+} /* basevertices */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="checkconnect">-</a>
+
+  qh_checkconnect()
+    check that new facets are connected
+    new facets are on qh.newfacet_list
+
+  notes:
+    this is slow and it changes the order of the facets
+    uses qh.visit_id
+
+  design:
+    move first new facet to end of qh.facet_list
+    for all newly appended facets
+      append unvisited neighbors to end of qh.facet_list
+    for all new facets
+      report error if unvisited
+*/
+void qh_checkconnect(void /* qh newfacet_list */) {
+  facetT *facet, *newfacet, *errfacet= NULL, *neighbor, **neighborp;
+
+  facet= qh newfacet_list;
+  qh_removefacet(facet);
+  qh_appendfacet(facet);
+  facet->visitid= ++qh visit_id;
+  FORALLfacet_(facet) {
+    FOREACHneighbor_(facet) {
+      if (neighbor->visitid != qh visit_id) {
+        qh_removefacet(neighbor);
+        qh_appendfacet(neighbor);
+        neighbor->visitid= qh visit_id;
+      }
+    }
+  }
+  FORALLnew_facets {
+    if (newfacet->visitid == qh visit_id)
+      break;
+    qh_fprintf(qh ferr, 6094, "qhull error: f%d is not attached to the new facets\n",
+         newfacet->id);
+    errfacet= newfacet;
+  }
+  if (errfacet)
+    qh_errexit(qh_ERRqhull, errfacet, NULL);
+} /* checkconnect */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="checkzero">-</a>
+
+  qh_checkzero( testall )
+    check that facets are clearly convex for qh.DISTround with qh.MERGEexact
+
+    if testall,
+      test all facets for qh.MERGEexact post-merging
+    else
+      test qh.newfacet_list
+
+    if qh.MERGEexact,
+      allows coplanar ridges
+      skips convexity test while qh.ZEROall_ok
+
+  returns:
+    True if all facets !flipped, !dupridge, normal
+         if all horizon facets are simplicial
+         if all vertices are clearly below neighbor
+         if all opposite vertices of horizon are below
+    clears qh.ZEROall_ok if any problems or coplanar facets
+
+  notes:
+    uses qh.vertex_visit
+    horizon facets may define multiple new facets
+
+  design:
+    for all facets in qh.newfacet_list or qh.facet_list
+      check for flagged faults (flipped, etc.)
+    for all facets in qh.newfacet_list or qh.facet_list
+      for each neighbor of facet
+        skip horizon facets for qh.newfacet_list
+        test the opposite vertex
+      if qh.newfacet_list
+        test the other vertices in the facet's horizon facet
+*/
+boolT qh_checkzero(boolT testall) {
+  facetT *facet, *neighbor, **neighborp;
+  facetT *horizon, *facetlist;
+  int neighbor_i;
+  vertexT *vertex, **vertexp;
+  realT dist;
+
+  if (testall)
+    facetlist= qh facet_list;
+  else {
+    facetlist= qh newfacet_list;
+    FORALLfacet_(facetlist) {
+      horizon= SETfirstt_(facet->neighbors, facetT);
+      if (!horizon->simplicial)
+        goto LABELproblem;
+      if (facet->flipped || facet->dupridge || !facet->normal)
+        goto LABELproblem;
+    }
+    if (qh MERGEexact && qh ZEROall_ok) {
+      trace2((qh ferr, 2011, "qh_checkzero: skip convexity check until first pre-merge\n"));
+      return True;
+    }
+  }
+  FORALLfacet_(facetlist) {
+    qh vertex_visit++;
+    neighbor_i= 0;
+    horizon= NULL;
+    FOREACHneighbor_(facet) {
+      if (!neighbor_i && !testall) {
+        horizon= neighbor;
+        neighbor_i++;
+        continue; /* horizon facet tested in qh_findhorizon */
+      }
+      vertex= SETelemt_(facet->vertices, neighbor_i++, vertexT);
+      vertex->visitid= qh vertex_visit;
+      zzinc_(Zdistzero);
+      qh_distplane(vertex->point, neighbor, &dist);
+      if (dist >= -qh DISTround) {
+        qh ZEROall_ok= False;
+        if (!qh MERGEexact || testall || dist > qh DISTround)
+          goto LABELnonconvex;
+      }
+    }
+    if (horizon != NULL && !testall) {
+      FOREACHvertex_(horizon->vertices) {
+        if (vertex->visitid != qh vertex_visit) {
+          zzinc_(Zdistzero);
+          qh_distplane(vertex->point, facet, &dist);
+          if (dist >= -qh DISTround) {
+            qh ZEROall_ok= False;
+            if (!qh MERGEexact || dist > qh DISTround)
+              goto LABELnonconvex;
+          }
+          break;
+        }
+      }
+    }
+  }
+  trace2((qh ferr, 2012, "qh_checkzero: testall %d, facets are %s\n", testall,
+        (qh MERGEexact && !testall) ?
+           "not concave, flipped, or duplicate ridged" : "clearly convex"));
+  return True;
+
+ LABELproblem:
+  qh ZEROall_ok= False;
+  trace2((qh ferr, 2013, "qh_checkzero: facet f%d needs pre-merging\n",
+       facet->id));
+  return False;
+
+ LABELnonconvex:
+  trace2((qh ferr, 2014, "qh_checkzero: facet f%d and f%d are not clearly convex.  v%d dist %.2g\n",
+         facet->id, neighbor->id, vertex->id, dist));
+  return False;
+} /* checkzero */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="compareangle">-</a>
+
+  qh_compareangle( angle1, angle2 )
+    used by qsort() to order merges by angle
+*/
+int qh_compareangle(const void *p1, const void *p2) {
+  const mergeT *a= *((mergeT *const*)p1), *b= *((mergeT *const*)p2);
+
+  return((a->angle > b->angle) ? 1 : -1);
+} /* compareangle */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="comparemerge">-</a>
+
+  qh_comparemerge( merge1, merge2 )
+    used by qsort() to order merges
+*/
+int qh_comparemerge(const void *p1, const void *p2) {
+  const mergeT *a= *((mergeT *const*)p1), *b= *((mergeT *const*)p2);
+
+  return(a->type - b->type);
+} /* comparemerge */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="comparevisit">-</a>
+
+  qh_comparevisit( vertex1, vertex2 )
+    used by qsort() to order vertices by their visitid
+*/
+int qh_comparevisit(const void *p1, const void *p2) {
+  const vertexT *a= *((vertexT *const*)p1), *b= *((vertexT *const*)p2);
+
+  return(a->visitid - b->visitid);
+} /* comparevisit */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="copynonconvex">-</a>
+
+  qh_copynonconvex( atridge )
+    set non-convex flag on other ridges (if any) between same neighbors
+
+  notes:
+    may be faster if use smaller ridge set
+
+  design:
+    for each ridge of atridge's top facet
+      if ridge shares the same neighbor
+        set nonconvex flag
+*/
+void qh_copynonconvex(ridgeT *atridge) {
+  facetT *facet, *otherfacet;
+  ridgeT *ridge, **ridgep;
+
+  facet= atridge->top;
+  otherfacet= atridge->bottom;
+  FOREACHridge_(facet->ridges) {
+    if (otherfacet == otherfacet_(ridge, facet) && ridge != atridge) {
+      ridge->nonconvex= True;
+      trace4((qh ferr, 4020, "qh_copynonconvex: moved nonconvex flag from r%d to r%d\n",
+              atridge->id, ridge->id));
+      break;
+    }
+  }
+} /* copynonconvex */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="degen_redundant_facet">-</a>
+
+  qh_degen_redundant_facet( facet )
+    check facet for degen. or redundancy
+
+  notes:
+    bumps vertex_visit
+    called if a facet was redundant but no longer is (qh_merge_degenredundant)
+    qh_appendmergeset() only appends first reference to facet (i.e., redundant)
+
+  see:
+    qh_degen_redundant_neighbors()
+
+  design:
+    test for redundant neighbor
+    test for degenerate facet
+*/
+void qh_degen_redundant_facet(facetT *facet) {
+  vertexT *vertex, **vertexp;
+  facetT *neighbor, **neighborp;
+
+  trace4((qh ferr, 4021, "qh_degen_redundant_facet: test facet f%d for degen/redundant\n",
+          facet->id));
+  FOREACHneighbor_(facet) {
+    qh vertex_visit++;
+    FOREACHvertex_(neighbor->vertices)
+      vertex->visitid= qh vertex_visit;
+    FOREACHvertex_(facet->vertices) {
+      if (vertex->visitid != qh vertex_visit)
+        break;
+    }
+    if (!vertex) {
+      qh_appendmergeset(facet, neighbor, MRGredundant, NULL);
+      trace2((qh ferr, 2015, "qh_degen_redundant_facet: f%d is contained in f%d.  merge\n", facet->id, neighbor->id));
+      return;
+    }
+  }
+  if (qh_setsize(facet->neighbors) < qh hull_dim) {
+    qh_appendmergeset(facet, facet, MRGdegen, NULL);
+    trace2((qh ferr, 2016, "qh_degen_redundant_neighbors: f%d is degenerate.\n", facet->id));
+  }
+} /* degen_redundant_facet */
+
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="degen_redundant_neighbors">-</a>
+
+  qh_degen_redundant_neighbors( facet, delfacet,  )
+    append degenerate and redundant neighbors to facet_mergeset
+    if delfacet,
+      only checks neighbors of both delfacet and facet
+    also checks current facet for degeneracy
+
+  notes:
+    bumps vertex_visit
+    called for each qh_mergefacet() and qh_mergecycle()
+    merge and statistics occur in merge_nonconvex
+    qh_appendmergeset() only appends first reference to facet (i.e., redundant)
+      it appends redundant facets after degenerate ones
+
+    a degenerate facet has fewer than hull_dim neighbors
+    a redundant facet's vertices is a subset of its neighbor's vertices
+    tests for redundant merges first (appendmergeset is nop for others)
+    in a merge, only needs to test neighbors of merged facet
+
+  see:
+    qh_merge_degenredundant() and qh_degen_redundant_facet()
+
+  design:
+    test for degenerate facet
+    test for redundant neighbor
+    test for degenerate neighbor
+*/
+void qh_degen_redundant_neighbors(facetT *facet, facetT *delfacet) {
+  vertexT *vertex, **vertexp;
+  facetT *neighbor, **neighborp;
+  int size;
+
+  trace4((qh ferr, 4022, "qh_degen_redundant_neighbors: test neighbors of f%d with delfacet f%d\n",
+          facet->id, getid_(delfacet)));
+  if ((size= qh_setsize(facet->neighbors)) < qh hull_dim) {
+    qh_appendmergeset(facet, facet, MRGdegen, NULL);
+    trace2((qh ferr, 2017, "qh_degen_redundant_neighbors: f%d is degenerate with %d neighbors.\n", facet->id, size));
+  }
+  if (!delfacet)
+    delfacet= facet;
+  qh vertex_visit++;
+  FOREACHvertex_(facet->vertices)
+    vertex->visitid= qh vertex_visit;
+  FOREACHneighbor_(delfacet) {
+    /* uses early out instead of checking vertex count */
+    if (neighbor == facet)
+      continue;
+    FOREACHvertex_(neighbor->vertices) {
+      if (vertex->visitid != qh vertex_visit)
+        break;
+    }
+    if (!vertex) {
+      qh_appendmergeset(neighbor, facet, MRGredundant, NULL);
+      trace2((qh ferr, 2018, "qh_degen_redundant_neighbors: f%d is contained in f%d.  merge\n", neighbor->id, facet->id));
+    }
+  }
+  FOREACHneighbor_(delfacet) {   /* redundant merges occur first */
+    if (neighbor == facet)
+      continue;
+    if ((size= qh_setsize(neighbor->neighbors)) < qh hull_dim) {
+      qh_appendmergeset(neighbor, neighbor, MRGdegen, NULL);
+      trace2((qh ferr, 2019, "qh_degen_redundant_neighbors: f%d is degenerate with %d neighbors.  Neighbor of f%d.\n", neighbor->id, size, facet->id));
+    }
+  }
+} /* degen_redundant_neighbors */
+
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="find_newvertex">-</a>
+
+  qh_find_newvertex( oldvertex, vertices, ridges )
+    locate new vertex for renaming old vertex
+    vertices is a set of possible new vertices
+      vertices sorted by number of deleted ridges
+
+  returns:
+    newvertex or NULL
+      each ridge includes both vertex and oldvertex
+    vertices sorted by number of deleted ridges
+
+  notes:
+    modifies vertex->visitid
+    new vertex is in one of the ridges
+    renaming will not cause a duplicate ridge
+    renaming will minimize the number of deleted ridges
+    newvertex may not be adjacent in the dual (though unlikely)
+
+  design:
+    for each vertex in vertices
+      set vertex->visitid to number of references in ridges
+    remove unvisited vertices
+    set qh.vertex_visit above all possible values
+    sort vertices by number of references in ridges
+    add each ridge to qh.hash_table
+    for each vertex in vertices
+      look for a vertex that would not cause a duplicate ridge after a rename
+*/
+vertexT *qh_find_newvertex(vertexT *oldvertex, setT *vertices, setT *ridges) {
+  vertexT *vertex, **vertexp;
+  setT *newridges;
+  ridgeT *ridge, **ridgep;
+  int size, hashsize;
+  int hash;
+
+#ifndef qh_NOtrace
+  if (qh IStracing >= 4) {
+    qh_fprintf(qh ferr, 8063, "qh_find_newvertex: find new vertex for v%d from ",
+             oldvertex->id);
+    FOREACHvertex_(vertices)
+      qh_fprintf(qh ferr, 8064, "v%d ", vertex->id);
+    FOREACHridge_(ridges)
+      qh_fprintf(qh ferr, 8065, "r%d ", ridge->id);
+    qh_fprintf(qh ferr, 8066, "\n");
+  }
+#endif
+  FOREACHvertex_(vertices)
+    vertex->visitid= 0;
+  FOREACHridge_(ridges) {
+    FOREACHvertex_(ridge->vertices)
+      vertex->visitid++;
+  }
+  FOREACHvertex_(vertices) {
+    if (!vertex->visitid) {
+      qh_setdelnth(vertices, SETindex_(vertices,vertex));
+      vertexp--; /* repeat since deleted this vertex */
+    }
+  }
+  qh vertex_visit += (unsigned int)qh_setsize(ridges);
+  if (!qh_setsize(vertices)) {
+    trace4((qh ferr, 4023, "qh_find_newvertex: vertices not in ridges for v%d\n",
+            oldvertex->id));
+    return NULL;
+  }
+  qsort(SETaddr_(vertices, vertexT), (size_t)qh_setsize(vertices),
+                sizeof(vertexT *), qh_comparevisit);
+  /* can now use qh vertex_visit */
+  if (qh PRINTstatistics) {
+    size= qh_setsize(vertices);
+    zinc_(Zintersect);
+    zadd_(Zintersecttot, size);
+    zmax_(Zintersectmax, size);
+  }
+  hashsize= qh_newhashtable(qh_setsize(ridges));
+  FOREACHridge_(ridges)
+    qh_hashridge(qh hash_table, hashsize, ridge, oldvertex);
+  FOREACHvertex_(vertices) {
+    newridges= qh_vertexridges(vertex);
+    FOREACHridge_(newridges) {
+      if (qh_hashridge_find(qh hash_table, hashsize, ridge, vertex, oldvertex, &hash)) {
+        zinc_(Zdupridge);
+        break;
+      }
+    }
+    qh_settempfree(&newridges);
+    if (!ridge)
+      break;  /* found a rename */
+  }
+  if (vertex) {
+    /* counted in qh_renamevertex */
+    trace2((qh ferr, 2020, "qh_find_newvertex: found v%d for old v%d from %d vertices and %d ridges.\n",
+      vertex->id, oldvertex->id, qh_setsize(vertices), qh_setsize(ridges)));
+  }else {
+    zinc_(Zfindfail);
+    trace0((qh ferr, 14, "qh_find_newvertex: no vertex for renaming v%d(all duplicated ridges) during p%d\n",
+      oldvertex->id, qh furthest_id));
+  }
+  qh_setfree(&qh hash_table);
+  return vertex;
+} /* find_newvertex */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="findbest_test">-</a>
+
+  qh_findbest_test( testcentrum, facet, neighbor, bestfacet, dist, mindist, maxdist )
+    test neighbor of facet for qh_findbestneighbor()
+    if testcentrum,
+      tests centrum (assumes it is defined)
+    else
+      tests vertices
+
+  returns:
+    if a better facet (i.e., vertices/centrum of facet closer to neighbor)
+      updates bestfacet, dist, mindist, and maxdist
+*/
+void qh_findbest_test(boolT testcentrum, facetT *facet, facetT *neighbor,
+      facetT **bestfacet, realT *distp, realT *mindistp, realT *maxdistp) {
+  realT dist, mindist, maxdist;
+
+  if (testcentrum) {
+    zzinc_(Zbestdist);
+    qh_distplane(facet->center, neighbor, &dist);
+    dist *= qh hull_dim; /* estimate furthest vertex */
+    if (dist < 0) {
+      maxdist= 0;
+      mindist= dist;
+      dist= -dist;
+    }else {
+      mindist= 0;
+      maxdist= dist;
+    }
+  }else
+    dist= qh_getdistance(facet, neighbor, &mindist, &maxdist);
+  if (dist < *distp) {
+    *bestfacet= neighbor;
+    *mindistp= mindist;
+    *maxdistp= maxdist;
+    *distp= dist;
+  }
+} /* findbest_test */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="findbestneighbor">-</a>
+
+  qh_findbestneighbor( facet, dist, mindist, maxdist )
+    finds best neighbor (least dist) of a facet for merging
+
+  returns:
+    returns min and max distances and their max absolute value
+
+  notes:
+    avoids merging old into new
+    assumes ridge->nonconvex only set on one ridge between a pair of facets
+    could use an early out predicate but not worth it
+
+  design:
+    if a large facet
+      will test centrum
+    else
+      will test vertices
+    if a large facet
+      test nonconvex neighbors for best merge
+    else
+      test all neighbors for the best merge
+    if testing centrum
+      get distance information
+*/
+facetT *qh_findbestneighbor(facetT *facet, realT *distp, realT *mindistp, realT *maxdistp) {
+  facetT *neighbor, **neighborp, *bestfacet= NULL;
+  ridgeT *ridge, **ridgep;
+  boolT nonconvex= True, testcentrum= False;
+  int size= qh_setsize(facet->vertices);
+
+  *distp= REALmax;
+  if (size > qh_BESTcentrum2 * qh hull_dim + qh_BESTcentrum) {
+    testcentrum= True;
+    zinc_(Zbestcentrum);
+    if (!facet->center)
+       facet->center= qh_getcentrum(facet);
+  }
+  if (size > qh hull_dim + qh_BESTnonconvex) {
+    FOREACHridge_(facet->ridges) {
+      if (ridge->nonconvex) {
+        neighbor= otherfacet_(ridge, facet);
+        qh_findbest_test(testcentrum, facet, neighbor,
+                          &bestfacet, distp, mindistp, maxdistp);
+      }
+    }
+  }
+  if (!bestfacet) {
+    nonconvex= False;
+    FOREACHneighbor_(facet)
+      qh_findbest_test(testcentrum, facet, neighbor,
+                        &bestfacet, distp, mindistp, maxdistp);
+  }
+  if (!bestfacet) {
+    qh_fprintf(qh ferr, 6095, "qhull internal error (qh_findbestneighbor): no neighbors for f%d\n", facet->id);
+
+    qh_errexit(qh_ERRqhull, facet, NULL);
+  }
+  if (testcentrum)
+    qh_getdistance(facet, bestfacet, mindistp, maxdistp);
+  trace3((qh ferr, 3002, "qh_findbestneighbor: f%d is best neighbor for f%d testcentrum? %d nonconvex? %d dist %2.2g min %2.2g max %2.2g\n",
+     bestfacet->id, facet->id, testcentrum, nonconvex, *distp, *mindistp, *maxdistp));
+  return(bestfacet);
+} /* findbestneighbor */
+
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="flippedmerges">-</a>
+
+  qh_flippedmerges( facetlist, wasmerge )
+    merge flipped facets into best neighbor
+    assumes qh.facet_mergeset at top of temporary stack
+
+  returns:
+    no flipped facets on facetlist
+    sets wasmerge if merge occurred
+    degen/redundant merges passed through
+
+  notes:
+    othermerges not needed since qh.facet_mergeset is empty before & after
+      keep it in case of change
+
+  design:
+    append flipped facets to qh.facetmergeset
+    for each flipped merge
+      find best neighbor
+      merge facet into neighbor
+      merge degenerate and redundant facets
+    remove flipped merges from qh.facet_mergeset
+*/
+void qh_flippedmerges(facetT *facetlist, boolT *wasmerge) {
+  facetT *facet, *neighbor, *facet1;
+  realT dist, mindist, maxdist;
+  mergeT *merge, **mergep;
+  setT *othermerges;
+  int nummerge=0;
+
+  trace4((qh ferr, 4024, "qh_flippedmerges: begin\n"));
+  FORALLfacet_(facetlist) {
+    if (facet->flipped && !facet->visible)
+      qh_appendmergeset(facet, facet, MRGflip, NULL);
+  }
+  othermerges= qh_settemppop(); /* was facet_mergeset */
+  qh facet_mergeset= qh_settemp(qh TEMPsize);
+  qh_settemppush(othermerges);
+  FOREACHmerge_(othermerges) {
+    facet1= merge->facet1;
+    if (merge->type != MRGflip || facet1->visible)
+      continue;
+    if (qh TRACEmerge-1 == zzval_(Ztotmerge))
+      qhmem.IStracing= qh IStracing= qh TRACElevel;
+    neighbor= qh_findbestneighbor(facet1, &dist, &mindist, &maxdist);
+    trace0((qh ferr, 15, "qh_flippedmerges: merge flipped f%d into f%d dist %2.2g during p%d\n",
+      facet1->id, neighbor->id, dist, qh furthest_id));
+    qh_mergefacet(facet1, neighbor, &mindist, &maxdist, !qh_MERGEapex);
+    nummerge++;
+    if (qh PRINTstatistics) {
+      zinc_(Zflipped);
+      wadd_(Wflippedtot, dist);
+      wmax_(Wflippedmax, dist);
+    }
+    qh_merge_degenredundant();
+  }
+  FOREACHmerge_(othermerges) {
+    if (merge->facet1->visible || merge->facet2->visible)
+      qh_memfree(merge, (int)sizeof(mergeT));
+    else
+      qh_setappend(&qh facet_mergeset, merge);
+  }
+  qh_settempfree(&othermerges);
+  if (nummerge)
+    *wasmerge= True;
+  trace1((qh ferr, 1010, "qh_flippedmerges: merged %d flipped facets into a good neighbor\n", nummerge));
+} /* flippedmerges */
+
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="forcedmerges">-</a>
+
+  qh_forcedmerges( wasmerge )
+    merge duplicated ridges
+
+  returns:
+    removes all duplicate ridges on facet_mergeset
+    wasmerge set if merge
+    qh.facet_mergeset may include non-forced merges(none for now)
+    qh.degen_mergeset includes degen/redun merges
+
+  notes:
+    duplicate ridges occur when the horizon is pinched,
+        i.e. a subridge occurs in more than two horizon ridges.
+     could rename vertices that pinch the horizon
+    assumes qh_merge_degenredundant() has not be called
+    othermerges isn't needed since facet_mergeset is empty afterwards
+      keep it in case of change
+
+  design:
+    for each duplicate ridge
+      find current facets by chasing f.replace links
+      determine best direction for facet
+      merge one facet into the other
+      remove duplicate ridges from qh.facet_mergeset
+*/
+void qh_forcedmerges(boolT *wasmerge) {
+  facetT *facet1, *facet2;
+  mergeT *merge, **mergep;
+  realT dist1, dist2, mindist1, mindist2, maxdist1, maxdist2;
+  setT *othermerges;
+  int nummerge=0, numflip=0;
+
+  if (qh TRACEmerge-1 == zzval_(Ztotmerge))
+    qhmem.IStracing= qh IStracing= qh TRACElevel;
+  trace4((qh ferr, 4025, "qh_forcedmerges: begin\n"));
+  othermerges= qh_settemppop(); /* was facet_mergeset */
+  qh facet_mergeset= qh_settemp(qh TEMPsize);
+  qh_settemppush(othermerges);
+  FOREACHmerge_(othermerges) {
+    if (merge->type != MRGridge)
+        continue;
+    facet1= merge->facet1;
+    facet2= merge->facet2;
+    while (facet1->visible)      /* must exist, no qh_merge_degenredunant */
+      facet1= facet1->f.replace; /* previously merged facet */
+    while (facet2->visible)
+      facet2= facet2->f.replace; /* previously merged facet */
+    if (facet1 == facet2)
+      continue;
+    if (!qh_setin(facet2->neighbors, facet1)) {
+      qh_fprintf(qh ferr, 6096, "qhull internal error (qh_forcedmerges): f%d and f%d had a duplicate ridge but as f%d and f%d they are no longer neighbors\n",
+               merge->facet1->id, merge->facet2->id, facet1->id, facet2->id);
+      qh_errexit2 (qh_ERRqhull, facet1, facet2);
+    }
+    if (qh TRACEmerge-1 == zzval_(Ztotmerge))
+      qhmem.IStracing= qh IStracing= qh TRACElevel;
+    dist1= qh_getdistance(facet1, facet2, &mindist1, &maxdist1);
+    dist2= qh_getdistance(facet2, facet1, &mindist2, &maxdist2);
+    trace0((qh ferr, 16, "qh_forcedmerges: duplicate ridge between f%d and f%d, dist %2.2g and reverse dist %2.2g during p%d\n",
+            facet1->id, facet2->id, dist1, dist2, qh furthest_id));
+    if (dist1 < dist2)
+      qh_mergefacet(facet1, facet2, &mindist1, &maxdist1, !qh_MERGEapex);
+    else {
+      qh_mergefacet(facet2, facet1, &mindist2, &maxdist2, !qh_MERGEapex);
+      dist1= dist2;
+      facet1= facet2;
+    }
+    if (facet1->flipped) {
+      zinc_(Zmergeflipdup);
+      numflip++;
+    }else
+      nummerge++;
+    if (qh PRINTstatistics) {
+      zinc_(Zduplicate);
+      wadd_(Wduplicatetot, dist1);
+      wmax_(Wduplicatemax, dist1);
+    }
+  }
+  FOREACHmerge_(othermerges) {
+    if (merge->type == MRGridge)
+      qh_memfree(merge, (int)sizeof(mergeT));
+    else
+      qh_setappend(&qh facet_mergeset, merge);
+  }
+  qh_settempfree(&othermerges);
+  if (nummerge)
+    *wasmerge= True;
+  trace1((qh ferr, 1011, "qh_forcedmerges: merged %d facets and %d flipped facets across duplicated ridges\n",
+                nummerge, numflip));
+} /* forcedmerges */
+
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="getmergeset">-</a>
+
+  qh_getmergeset( facetlist )
+    determines nonconvex facets on facetlist
+    tests !tested ridges and nonconvex ridges of !tested facets
+
+  returns:
+    returns sorted qh.facet_mergeset of facet-neighbor pairs to be merged
+    all ridges tested
+
+  notes:
+    assumes no nonconvex ridges with both facets tested
+    uses facet->tested/ridge->tested to prevent duplicate tests
+    can not limit tests to modified ridges since the centrum changed
+    uses qh.visit_id
+
+  see:
+    qh_getmergeset_initial()
+
+  design:
+    for each facet on facetlist
+      for each ridge of facet
+        if untested ridge
+          test ridge for convexity
+          if non-convex
+            append ridge to qh.facet_mergeset
+    sort qh.facet_mergeset by angle
+*/
+void qh_getmergeset(facetT *facetlist) {
+  facetT *facet, *neighbor, **neighborp;
+  ridgeT *ridge, **ridgep;
+  int nummerges;
+
+  nummerges= qh_setsize(qh facet_mergeset);
+  trace4((qh ferr, 4026, "qh_getmergeset: started.\n"));
+  qh visit_id++;
+  FORALLfacet_(facetlist) {
+    if (facet->tested)
+      continue;
+    facet->visitid= qh visit_id;
+    facet->tested= True;  /* must be non-simplicial due to merge */
+    FOREACHneighbor_(facet)
+      neighbor->seen= False;
+    FOREACHridge_(facet->ridges) {
+      if (ridge->tested && !ridge->nonconvex)
+        continue;
+      /* if tested & nonconvex, need to append merge */
+      neighbor= otherfacet_(ridge, facet);
+      if (neighbor->seen) {
+        ridge->tested= True;
+        ridge->nonconvex= False;
+      }else if (neighbor->visitid != qh visit_id) {
+        ridge->tested= True;
+        ridge->nonconvex= False;
+        neighbor->seen= True;      /* only one ridge is marked nonconvex */
+        if (qh_test_appendmerge(facet, neighbor))
+          ridge->nonconvex= True;
+      }
+    }
+  }
+  nummerges= qh_setsize(qh facet_mergeset);
+  if (qh ANGLEmerge)
+    qsort(SETaddr_(qh facet_mergeset, mergeT), (size_t)nummerges, sizeof(mergeT *), qh_compareangle);
+  else
+    qsort(SETaddr_(qh facet_mergeset, mergeT), (size_t)nummerges, sizeof(mergeT *), qh_comparemerge);
+  if (qh POSTmerging) {
+    zadd_(Zmergesettot2, nummerges);
+  }else {
+    zadd_(Zmergesettot, nummerges);
+    zmax_(Zmergesetmax, nummerges);
+  }
+  trace2((qh ferr, 2021, "qh_getmergeset: %d merges found\n", nummerges));
+} /* getmergeset */
+
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="getmergeset_initial">-</a>
+
+  qh_getmergeset_initial( facetlist )
+    determine initial qh.facet_mergeset for facets
+    tests all facet/neighbor pairs on facetlist
+
+  returns:
+    sorted qh.facet_mergeset with nonconvex ridges
+    sets facet->tested, ridge->tested, and ridge->nonconvex
+
+  notes:
+    uses visit_id, assumes ridge->nonconvex is False
+
+  see:
+    qh_getmergeset()
+
+  design:
+    for each facet on facetlist
+      for each untested neighbor of facet
+        test facet and neighbor for convexity
+        if non-convex
+          append merge to qh.facet_mergeset
+          mark one of the ridges as nonconvex
+    sort qh.facet_mergeset by angle
+*/
+void qh_getmergeset_initial(facetT *facetlist) {
+  facetT *facet, *neighbor, **neighborp;
+  ridgeT *ridge, **ridgep;
+  int nummerges;
+
+  qh visit_id++;
+  FORALLfacet_(facetlist) {
+    facet->visitid= qh visit_id;
+    facet->tested= True;
+    FOREACHneighbor_(facet) {
+      if (neighbor->visitid != qh visit_id) {
+        if (qh_test_appendmerge(facet, neighbor)) {
+          FOREACHridge_(neighbor->ridges) {
+            if (facet == otherfacet_(ridge, neighbor)) {
+              ridge->nonconvex= True;
+              break;    /* only one ridge is marked nonconvex */
+            }
+          }
+        }
+      }
+    }
+    FOREACHridge_(facet->ridges)
+      ridge->tested= True;
+  }
+  nummerges= qh_setsize(qh facet_mergeset);
+  if (qh ANGLEmerge)
+    qsort(SETaddr_(qh facet_mergeset, mergeT), (size_t)nummerges, sizeof(mergeT *), qh_compareangle);
+  else
+    qsort(SETaddr_(qh facet_mergeset, mergeT), (size_t)nummerges, sizeof(mergeT *), qh_comparemerge);
+  if (qh POSTmerging) {
+    zadd_(Zmergeinittot2, nummerges);
+  }else {
+    zadd_(Zmergeinittot, nummerges);
+    zmax_(Zmergeinitmax, nummerges);
+  }
+  trace2((qh ferr, 2022, "qh_getmergeset_initial: %d merges found\n", nummerges));
+} /* getmergeset_initial */
+
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="hashridge">-</a>
+
+  qh_hashridge( hashtable, hashsize, ridge, oldvertex )
+    add ridge to hashtable without oldvertex
+
+  notes:
+    assumes hashtable is large enough
+
+  design:
+    determine hash value for ridge without oldvertex
+    find next empty slot for ridge
+*/
+void qh_hashridge(setT *hashtable, int hashsize, ridgeT *ridge, vertexT *oldvertex) {
+  int hash;
+  ridgeT *ridgeA;
+
+  hash= qh_gethash(hashsize, ridge->vertices, qh hull_dim-1, 0, oldvertex);
+  while (True) {
+    if (!(ridgeA= SETelemt_(hashtable, hash, ridgeT))) {
+      SETelem_(hashtable, hash)= ridge;
+      break;
+    }else if (ridgeA == ridge)
+      break;
+    if (++hash == hashsize)
+      hash= 0;
+  }
+} /* hashridge */
+
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="hashridge_find">-</a>
+
+  qh_hashridge_find( hashtable, hashsize, ridge, vertex, oldvertex, hashslot )
+    returns matching ridge without oldvertex in hashtable
+      for ridge without vertex
+    if oldvertex is NULL
+      matches with any one skip
+
+  returns:
+    matching ridge or NULL
+    if no match,
+      if ridge already in   table
+        hashslot= -1
+      else
+        hashslot= next NULL index
+
+  notes:
+    assumes hashtable is large enough
+    can't match ridge to itself
+
+  design:
+    get hash value for ridge without vertex
+    for each hashslot
+      return match if ridge matches ridgeA without oldvertex
+*/
+ridgeT *qh_hashridge_find(setT *hashtable, int hashsize, ridgeT *ridge,
+              vertexT *vertex, vertexT *oldvertex, int *hashslot) {
+  int hash;
+  ridgeT *ridgeA;
+
+  *hashslot= 0;
+  zinc_(Zhashridge);
+  hash= qh_gethash(hashsize, ridge->vertices, qh hull_dim-1, 0, vertex);
+  while ((ridgeA= SETelemt_(hashtable, hash, ridgeT))) {
+    if (ridgeA == ridge)
+      *hashslot= -1;
+    else {
+      zinc_(Zhashridgetest);
+      if (qh_setequal_except(ridge->vertices, vertex, ridgeA->vertices, oldvertex))
+        return ridgeA;
+    }
+    if (++hash == hashsize)
+      hash= 0;
+  }
+  if (!*hashslot)
+    *hashslot= hash;
+  return NULL;
+} /* hashridge_find */
+
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="makeridges">-</a>
+
+  qh_makeridges( facet )
+    creates explicit ridges between simplicial facets
+
+  returns:
+    facet with ridges and without qh_MERGEridge
+    ->simplicial is False
+
+  notes:
+    allows qh_MERGEridge flag
+    uses existing ridges
+    duplicate neighbors ok if ridges already exist (qh_mergecycle_ridges)
+
+  see:
+    qh_mergecycle_ridges()
+
+  design:
+    look for qh_MERGEridge neighbors
+    mark neighbors that already have ridges
+    for each unprocessed neighbor of facet
+      create a ridge for neighbor and facet
+    if any qh_MERGEridge neighbors
+      delete qh_MERGEridge flags (already handled by qh_mark_dupridges)
+*/
+void qh_makeridges(facetT *facet) {
+  facetT *neighbor, **neighborp;
+  ridgeT *ridge, **ridgep;
+  int neighbor_i, neighbor_n;
+  boolT toporient, mergeridge= False;
+
+  if (!facet->simplicial)
+    return;
+  trace4((qh ferr, 4027, "qh_makeridges: make ridges for f%d\n", facet->id));
+  facet->simplicial= False;
+  FOREACHneighbor_(facet) {
+    if (neighbor == qh_MERGEridge)
+      mergeridge= True;
+    else
+      neighbor->seen= False;
+  }
+  FOREACHridge_(facet->ridges)
+    otherfacet_(ridge, facet)->seen= True;
+  FOREACHneighbor_i_(facet) {
+    if (neighbor == qh_MERGEridge)
+      continue;  /* fixed by qh_mark_dupridges */
+    else if (!neighbor->seen) {  /* no current ridges */
+      ridge= qh_newridge();
+      ridge->vertices= qh_setnew_delnthsorted(facet->vertices, qh hull_dim,
+                                                          neighbor_i, 0);
+      toporient= facet->toporient ^ (neighbor_i & 0x1);
+      if (toporient) {
+        ridge->top= facet;
+        ridge->bottom= neighbor;
+      }else {
+        ridge->top= neighbor;
+        ridge->bottom= facet;
+      }
+#if 0 /* this also works */
+      flip= (facet->toporient ^ neighbor->toporient)^(skip1 & 0x1) ^ (skip2 & 0x1);
+      if (facet->toporient ^ (skip1 & 0x1) ^ flip) {
+        ridge->top= neighbor;
+        ridge->bottom= facet;
+      }else {
+        ridge->top= facet;
+        ridge->bottom= neighbor;
+      }
+#endif
+      qh_setappend(&(facet->ridges), ridge);
+      qh_setappend(&(neighbor->ridges), ridge);
+    }
+  }
+  if (mergeridge) {
+    while (qh_setdel(facet->neighbors, qh_MERGEridge))
+      ; /* delete each one */
+  }
+} /* makeridges */
+
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="mark_dupridges">-</a>
+
+  qh_mark_dupridges( facetlist )
+    add duplicated ridges to qh.facet_mergeset
+    facet->dupridge is true
+
+  returns:
+    duplicate ridges on qh.facet_mergeset
+    ->mergeridge/->mergeridge2 set
+    duplicate ridges marked by qh_MERGEridge and both sides facet->dupridge
+    no MERGEridges in neighbor sets
+
+  notes:
+    duplicate ridges occur when the horizon is pinched,
+        i.e. a subridge occurs in more than two horizon ridges.
+    could rename vertices that pinch the horizon
+    uses qh.visit_id
+
+  design:
+    for all facets on facetlist
+      if facet contains a duplicate ridge
+        for each neighbor of facet
+          if neighbor marked qh_MERGEridge (one side of the merge)
+            set facet->mergeridge
+          else
+            if neighbor contains a duplicate ridge
+            and the back link is qh_MERGEridge
+              append duplicate ridge to qh.facet_mergeset
+   for each duplicate ridge
+     make ridge sets in preparation for merging
+     remove qh_MERGEridge from neighbor set
+   for each duplicate ridge
+     restore the missing neighbor from the neighbor set that was qh_MERGEridge
+     add the missing ridge for this neighbor
+*/
+void qh_mark_dupridges(facetT *facetlist) {
+  facetT *facet, *neighbor, **neighborp;
+  int nummerge=0;
+  mergeT *merge, **mergep;
+
+
+  trace4((qh ferr, 4028, "qh_mark_dupridges: identify duplicate ridges\n"));
+  FORALLfacet_(facetlist) {
+    if (facet->dupridge) {
+      FOREACHneighbor_(facet) {
+        if (neighbor == qh_MERGEridge) {
+          facet->mergeridge= True;
+          continue;
+        }
+        if (neighbor->dupridge
+        && !qh_setin(neighbor->neighbors, facet)) { /* qh_MERGEridge */
+          qh_appendmergeset(facet, neighbor, MRGridge, NULL);
+          facet->mergeridge2= True;
+          facet->mergeridge= True;
+          nummerge++;
+        }
+      }
+    }
+  }
+  if (!nummerge)
+    return;
+  FORALLfacet_(facetlist) {            /* gets rid of qh_MERGEridge */
+    if (facet->mergeridge && !facet->mergeridge2)
+      qh_makeridges(facet);
+  }
+  FOREACHmerge_(qh facet_mergeset) {   /* restore the missing neighbors */
+    if (merge->type == MRGridge) {
+      qh_setappend(&merge->facet2->neighbors, merge->facet1);
+      qh_makeridges(merge->facet1);   /* and the missing ridges */
+    }
+  }
+  trace1((qh ferr, 1012, "qh_mark_dupridges: found %d duplicated ridges\n",
+                nummerge));
+} /* mark_dupridges */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="maydropneighbor">-</a>
+
+  qh_maydropneighbor( facet )
+    drop neighbor relationship if no ridge between facet and neighbor
+
+  returns:
+    neighbor sets updated
+    appends degenerate facets to qh.facet_mergeset
+
+  notes:
+    won't cause redundant facets since vertex inclusion is the same
+    may drop vertex and neighbor if no ridge
+    uses qh.visit_id
+
+  design:
+    visit all neighbors with ridges
+    for each unvisited neighbor of facet
+      delete neighbor and facet from the neighbor sets
+      if neighbor becomes degenerate
+        append neighbor to qh.degen_mergeset
+    if facet is degenerate
+      append facet to qh.degen_mergeset
+*/
+void qh_maydropneighbor(facetT *facet) {
+  ridgeT *ridge, **ridgep;
+  realT angledegen= qh_ANGLEdegen;
+  facetT *neighbor, **neighborp;
+
+  qh visit_id++;
+  trace4((qh ferr, 4029, "qh_maydropneighbor: test f%d for no ridges to a neighbor\n",
+          facet->id));
+  FOREACHridge_(facet->ridges) {
+    ridge->top->visitid= qh visit_id;
+    ridge->bottom->visitid= qh visit_id;
+  }
+  FOREACHneighbor_(facet) {
+    if (neighbor->visitid != qh visit_id) {
+      trace0((qh ferr, 17, "qh_maydropneighbor: facets f%d and f%d are no longer neighbors during p%d\n",
+            facet->id, neighbor->id, qh furthest_id));
+      zinc_(Zdropneighbor);
+      qh_setdel(facet->neighbors, neighbor);
+      neighborp--;  /* repeat, deleted a neighbor */
+      qh_setdel(neighbor->neighbors, facet);
+      if (qh_setsize(neighbor->neighbors) < qh hull_dim) {
+        zinc_(Zdropdegen);
+        qh_appendmergeset(neighbor, neighbor, MRGdegen, &angledegen);
+        trace2((qh ferr, 2023, "qh_maydropneighbors: f%d is degenerate.\n", neighbor->id));
+      }
+    }
+  }
+  if (qh_setsize(facet->neighbors) < qh hull_dim) {
+    zinc_(Zdropdegen);
+    qh_appendmergeset(facet, facet, MRGdegen, &angledegen);
+    trace2((qh ferr, 2024, "qh_maydropneighbors: f%d is degenerate.\n", facet->id));
+  }
+} /* maydropneighbor */
+
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="merge_degenredundant">-</a>
+
+  qh_merge_degenredundant()
+    merge all degenerate and redundant facets
+    qh.degen_mergeset contains merges from qh_degen_redundant_neighbors()
+
+  returns:
+    number of merges performed
+    resets facet->degenerate/redundant
+    if deleted (visible) facet has no neighbors
+      sets ->f.replace to NULL
+
+  notes:
+    redundant merges happen before degenerate ones
+    merging and renaming vertices can result in degen/redundant facets
+
+  design:
+    for each merge on qh.degen_mergeset
+      if redundant merge
+        if non-redundant facet merged into redundant facet
+          recheck facet for redundancy
+        else
+          merge redundant facet into other facet
+*/
+int qh_merge_degenredundant(void) {
+  int size;
+  mergeT *merge;
+  facetT *bestneighbor, *facet1, *facet2;
+  realT dist, mindist, maxdist;
+  vertexT *vertex, **vertexp;
+  int nummerges= 0;
+  mergeType mergetype;
+
+  while ((merge= (mergeT*)qh_setdellast(qh degen_mergeset))) {
+    facet1= merge->facet1;
+    facet2= merge->facet2;
+    mergetype= merge->type;
+    qh_memfree(merge, (int)sizeof(mergeT));
+    if (facet1->visible)
+      continue;
+    facet1->degenerate= False;
+    facet1->redundant= False;
+    if (qh TRACEmerge-1 == zzval_(Ztotmerge))
+      qhmem.IStracing= qh IStracing= qh TRACElevel;
+    if (mergetype == MRGredundant) {
+      zinc_(Zneighbor);
+      while (facet2->visible) {
+        if (!facet2->f.replace) {
+          qh_fprintf(qh ferr, 6097, "qhull internal error (qh_merge_degenredunant): f%d redundant but f%d has no replacement\n",
+               facet1->id, facet2->id);
+          qh_errexit2 (qh_ERRqhull, facet1, facet2);
+        }
+        facet2= facet2->f.replace;
+      }
+      if (facet1 == facet2) {
+        qh_degen_redundant_facet(facet1); /* in case of others */
+        continue;
+      }
+      trace2((qh ferr, 2025, "qh_merge_degenredundant: facet f%d is contained in f%d, will merge\n",
+            facet1->id, facet2->id));
+      qh_mergefacet(facet1, facet2, NULL, NULL, !qh_MERGEapex);
+      /* merge distance is already accounted for */
+      nummerges++;
+    }else {  /* mergetype == MRGdegen, other merges may have fixed */
+      if (!(size= qh_setsize(facet1->neighbors))) {
+        zinc_(Zdelfacetdup);
+        trace2((qh ferr, 2026, "qh_merge_degenredundant: facet f%d has no neighbors.  Deleted\n", facet1->id));
+        qh_willdelete(facet1, NULL);
+        FOREACHvertex_(facet1->vertices) {
+          qh_setdel(vertex->neighbors, facet1);
+          if (!SETfirst_(vertex->neighbors)) {
+            zinc_(Zdegenvertex);
+            trace2((qh ferr, 2027, "qh_merge_degenredundant: deleted v%d because f%d has no neighbors\n",
+                 vertex->id, facet1->id));
+            vertex->deleted= True;
+            qh_setappend(&qh del_vertices, vertex);
+          }
+        }
+        nummerges++;
+      }else if (size < qh hull_dim) {
+        bestneighbor= qh_findbestneighbor(facet1, &dist, &mindist, &maxdist);
+        trace2((qh ferr, 2028, "qh_merge_degenredundant: facet f%d has %d neighbors, merge into f%d dist %2.2g\n",
+              facet1->id, size, bestneighbor->id, dist));
+        qh_mergefacet(facet1, bestneighbor, &mindist, &maxdist, !qh_MERGEapex);
+        nummerges++;
+        if (qh PRINTstatistics) {
+          zinc_(Zdegen);
+          wadd_(Wdegentot, dist);
+          wmax_(Wdegenmax, dist);
+        }
+      } /* else, another merge fixed the degeneracy and redundancy tested */
+    }
+  }
+  return nummerges;
+} /* merge_degenredundant */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="merge_nonconvex">-</a>
+
+  qh_merge_nonconvex( facet1, facet2, mergetype )
+    remove non-convex ridge between facet1 into facet2
+    mergetype gives why the facet's are non-convex
+
+  returns:
+    merges one of the facets into the best neighbor
+
+  design:
+    if one of the facets is a new facet
+      prefer merging new facet into old facet
+    find best neighbors for both facets
+    merge the nearest facet into its best neighbor
+    update the statistics
+*/
+void qh_merge_nonconvex(facetT *facet1, facetT *facet2, mergeType mergetype) {
+  facetT *bestfacet, *bestneighbor, *neighbor;
+  realT dist, dist2, mindist, mindist2, maxdist, maxdist2;
+
+  if (qh TRACEmerge-1 == zzval_(Ztotmerge))
+    qhmem.IStracing= qh IStracing= qh TRACElevel;
+  trace3((qh ferr, 3003, "qh_merge_nonconvex: merge #%d for f%d and f%d type %d\n",
+      zzval_(Ztotmerge) + 1, facet1->id, facet2->id, mergetype));
+  /* concave or coplanar */
+  if (!facet1->newfacet) {
+    bestfacet= facet2;   /* avoid merging old facet if new is ok */
+    facet2= facet1;
+    facet1= bestfacet;
+  }else
+    bestfacet= facet1;
+  bestneighbor= qh_findbestneighbor(bestfacet, &dist, &mindist, &maxdist);
+  neighbor= qh_findbestneighbor(facet2, &dist2, &mindist2, &maxdist2);
+  if (dist < dist2) {
+    qh_mergefacet(bestfacet, bestneighbor, &mindist, &maxdist, !qh_MERGEapex);
+  }else if (qh AVOIDold && !facet2->newfacet
+  && ((mindist >= -qh MAXcoplanar && maxdist <= qh max_outside)
+       || dist * 1.5 < dist2)) {
+    zinc_(Zavoidold);
+    wadd_(Wavoidoldtot, dist);
+    wmax_(Wavoidoldmax, dist);
+    trace2((qh ferr, 2029, "qh_merge_nonconvex: avoid merging old facet f%d dist %2.2g.  Use f%d dist %2.2g instead\n",
+           facet2->id, dist2, facet1->id, dist2));
+    qh_mergefacet(bestfacet, bestneighbor, &mindist, &maxdist, !qh_MERGEapex);
+  }else {
+    qh_mergefacet(facet2, neighbor, &mindist2, &maxdist2, !qh_MERGEapex);
+    dist= dist2;
+  }
+  if (qh PRINTstatistics) {
+    if (mergetype == MRGanglecoplanar) {
+      zinc_(Zacoplanar);
+      wadd_(Wacoplanartot, dist);
+      wmax_(Wacoplanarmax, dist);
+    }else if (mergetype == MRGconcave) {
+      zinc_(Zconcave);
+      wadd_(Wconcavetot, dist);
+      wmax_(Wconcavemax, dist);
+    }else { /* MRGcoplanar */
+      zinc_(Zcoplanar);
+      wadd_(Wcoplanartot, dist);
+      wmax_(Wcoplanarmax, dist);
+    }
+  }
+} /* merge_nonconvex */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="mergecycle">-</a>
+
+  qh_mergecycle( samecycle, newfacet )
+    merge a cycle of facets starting at samecycle into a newfacet
+    newfacet is a horizon facet with ->normal
+    samecycle facets are simplicial from an apex
+
+  returns:
+    initializes vertex neighbors on first merge
+    samecycle deleted (placed on qh.visible_list)
+    newfacet at end of qh.facet_list
+    deleted vertices on qh.del_vertices
+
+  see:
+    qh_mergefacet()
+    called by qh_mergecycle_all() for multiple, same cycle facets
+
+  design:
+    make vertex neighbors if necessary
+    make ridges for newfacet
+    merge neighbor sets of samecycle into newfacet
+    merge ridges of samecycle into newfacet
+    merge vertex neighbors of samecycle into newfacet
+    make apex of samecycle the apex of newfacet
+    if newfacet wasn't a new facet
+      add its vertices to qh.newvertex_list
+    delete samecycle facets a make newfacet a newfacet
+*/
+void qh_mergecycle(facetT *samecycle, facetT *newfacet) {
+  int traceonce= False, tracerestore= 0;
+  vertexT *apex;
+#ifndef qh_NOtrace
+  facetT *same;
+#endif
+
+  if (newfacet->tricoplanar) {
+    if (!qh TRInormals) {
+      qh_fprintf(qh ferr, 6224, "Qhull internal error (qh_mergecycle): does not work for tricoplanar facets.  Use option 'Q11'\n");
+      qh_errexit(qh_ERRqhull, newfacet, NULL);
+    }
+    newfacet->tricoplanar= False;
+    newfacet->keepcentrum= False;
+  }
+  if (!qh VERTEXneighbors)
+    qh_vertexneighbors();
+  zzinc_(Ztotmerge);
+  if (qh REPORTfreq2 && qh POSTmerging) {
+    if (zzval_(Ztotmerge) > qh mergereport + qh REPORTfreq2)
+      qh_tracemerging();
+  }
+#ifndef qh_NOtrace
+  if (qh TRACEmerge == zzval_(Ztotmerge))
+    qhmem.IStracing= qh IStracing= qh TRACElevel;
+  trace2((qh ferr, 2030, "qh_mergecycle: merge #%d for facets from cycle f%d into coplanar horizon f%d\n",
+        zzval_(Ztotmerge), samecycle->id, newfacet->id));
+  if (newfacet == qh tracefacet) {
+    tracerestore= qh IStracing;
+    qh IStracing= 4;
+    qh_fprintf(qh ferr, 8068, "qh_mergecycle: ========= trace merge %d of samecycle %d into trace f%d, furthest is p%d\n",
+               zzval_(Ztotmerge), samecycle->id, newfacet->id,  qh furthest_id);
+    traceonce= True;
+  }
+  if (qh IStracing >=4) {
+    qh_fprintf(qh ferr, 8069, "  same cycle:");
+    FORALLsame_cycle_(samecycle)
+      qh_fprintf(qh ferr, 8070, " f%d", same->id);
+    qh_fprintf(qh ferr, 8071, "\n");
+  }
+  if (qh IStracing >=4)
+    qh_errprint("MERGING CYCLE", samecycle, newfacet, NULL, NULL);
+#endif /* !qh_NOtrace */
+  apex= SETfirstt_(samecycle->vertices, vertexT);
+  qh_makeridges(newfacet);
+  qh_mergecycle_neighbors(samecycle, newfacet);
+  qh_mergecycle_ridges(samecycle, newfacet);
+  qh_mergecycle_vneighbors(samecycle, newfacet);
+  if (SETfirstt_(newfacet->vertices, vertexT) != apex)
+    qh_setaddnth(&newfacet->vertices, 0, apex);  /* apex has last id */
+  if (!newfacet->newfacet)
+    qh_newvertices(newfacet->vertices);
+  qh_mergecycle_facets(samecycle, newfacet);
+  qh_tracemerge(samecycle, newfacet);
+  /* check for degen_redundant_neighbors after qh_forcedmerges() */
+  if (traceonce) {
+    qh_fprintf(qh ferr, 8072, "qh_mergecycle: end of trace facet\n");
+    qh IStracing= tracerestore;
+  }
+} /* mergecycle */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="mergecycle_all">-</a>
+
+  qh_mergecycle_all( facetlist, wasmerge )
+    merge all samecycles of coplanar facets into horizon
+    don't merge facets with ->mergeridge (these already have ->normal)
+    all facets are simplicial from apex
+    all facet->cycledone == False
+
+  returns:
+    all newfacets merged into coplanar horizon facets
+    deleted vertices on  qh.del_vertices
+    sets wasmerge if any merge
+
+  see:
+    calls qh_mergecycle for multiple, same cycle facets
+
+  design:
+    for each facet on facetlist
+      skip facets with duplicate ridges and normals
+      check that facet is in a samecycle (->mergehorizon)
+      if facet only member of samecycle
+        sets vertex->delridge for all vertices except apex
+        merge facet into horizon
+      else
+        mark all facets in samecycle
+        remove facets with duplicate ridges from samecycle
+        merge samecycle into horizon (deletes facets from facetlist)
+*/
+void qh_mergecycle_all(facetT *facetlist, boolT *wasmerge) {
+  facetT *facet, *same, *prev, *horizon;
+  facetT *samecycle= NULL, *nextfacet, *nextsame;
+  vertexT *apex, *vertex, **vertexp;
+  int cycles=0, total=0, facets, nummerge;
+
+  trace2((qh ferr, 2031, "qh_mergecycle_all: begin\n"));
+  for (facet= facetlist; facet && (nextfacet= facet->next); facet= nextfacet) {
+    if (facet->normal)
+      continue;
+    if (!facet->mergehorizon) {
+      qh_fprintf(qh ferr, 6225, "Qhull internal error (qh_mergecycle_all): f%d without normal\n", facet->id);
+      qh_errexit(qh_ERRqhull, facet, NULL);
+    }
+    horizon= SETfirstt_(facet->neighbors, facetT);
+    if (facet->f.samecycle == facet) {
+      zinc_(Zonehorizon);
+      /* merge distance done in qh_findhorizon */
+      apex= SETfirstt_(facet->vertices, vertexT);
+      FOREACHvertex_(facet->vertices) {
+        if (vertex != apex)
+          vertex->delridge= True;
+      }
+      horizon->f.newcycle= NULL;
+      qh_mergefacet(facet, horizon, NULL, NULL, qh_MERGEapex);
+    }else {
+      samecycle= facet;
+      facets= 0;
+      prev= facet;
+      for (same= facet->f.samecycle; same;  /* FORALLsame_cycle_(facet) */
+           same= (same == facet ? NULL :nextsame)) { /* ends at facet */
+        nextsame= same->f.samecycle;
+        if (same->cycledone || same->visible)
+          qh_infiniteloop(same);
+        same->cycledone= True;
+        if (same->normal) {
+          prev->f.samecycle= same->f.samecycle; /* unlink ->mergeridge */
+          same->f.samecycle= NULL;
+        }else {
+          prev= same;
+          facets++;
+        }
+      }
+      while (nextfacet && nextfacet->cycledone)  /* will delete samecycle */
+        nextfacet= nextfacet->next;
+      horizon->f.newcycle= NULL;
+      qh_mergecycle(samecycle, horizon);
+      nummerge= horizon->nummerge + facets;
+      if (nummerge > qh_MAXnummerge)
+        horizon->nummerge= qh_MAXnummerge;
+      else
+        horizon->nummerge= (short unsigned int)nummerge;
+      zzinc_(Zcyclehorizon);
+      total += facets;
+      zzadd_(Zcyclefacettot, facets);
+      zmax_(Zcyclefacetmax, facets);
+    }
+    cycles++;
+  }
+  if (cycles)
+    *wasmerge= True;
+  trace1((qh ferr, 1013, "qh_mergecycle_all: merged %d same cycles or facets into coplanar horizons\n", cycles));
+} /* mergecycle_all */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="mergecycle_facets">-</a>
+
+  qh_mergecycle_facets( samecycle, newfacet )
+    finish merge of samecycle into newfacet
+
+  returns:
+    samecycle prepended to visible_list for later deletion and partitioning
+      each facet->f.replace == newfacet
+
+    newfacet moved to end of qh.facet_list
+      makes newfacet a newfacet (get's facet1->id if it was old)
+      sets newfacet->newmerge
+      clears newfacet->center (unless merging into a large facet)
+      clears newfacet->tested and ridge->tested for facet1
+
+    adds neighboring facets to facet_mergeset if redundant or degenerate
+
+  design:
+    make newfacet a new facet and set its flags
+    move samecycle facets to qh.visible_list for later deletion
+    unless newfacet is large
+      remove its centrum
+*/
+void qh_mergecycle_facets(facetT *samecycle, facetT *newfacet) {
+  facetT *same, *next;
+
+  trace4((qh ferr, 4030, "qh_mergecycle_facets: make newfacet new and samecycle deleted\n"));
+  qh_removefacet(newfacet);  /* append as a newfacet to end of qh facet_list */
+  qh_appendfacet(newfacet);
+  newfacet->newfacet= True;
+  newfacet->simplicial= False;
+  newfacet->newmerge= True;
+
+  for (same= samecycle->f.samecycle; same; same= (same == samecycle ?  NULL : next)) {
+    next= same->f.samecycle;  /* reused by willdelete */
+    qh_willdelete(same, newfacet);
+  }
+  if (newfacet->center
+      && qh_setsize(newfacet->vertices) <= qh hull_dim + qh_MAXnewcentrum) {
+    qh_memfree(newfacet->center, qh normal_size);
+    newfacet->center= NULL;
+  }
+  trace3((qh ferr, 3004, "qh_mergecycle_facets: merged facets from cycle f%d into f%d\n",
+             samecycle->id, newfacet->id));
+} /* mergecycle_facets */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="mergecycle_neighbors">-</a>
+
+  qh_mergecycle_neighbors( samecycle, newfacet )
+    add neighbors for samecycle facets to newfacet
+
+  returns:
+    newfacet with updated neighbors and vice-versa
+    newfacet has ridges
+    all neighbors of newfacet marked with qh.visit_id
+    samecycle facets marked with qh.visit_id-1
+    ridges updated for simplicial neighbors of samecycle with a ridge
+
+  notes:
+    assumes newfacet not in samecycle
+    usually, samecycle facets are new, simplicial facets without internal ridges
+      not so if horizon facet is coplanar to two different samecycles
+
+  see:
+    qh_mergeneighbors()
+
+  design:
+    check samecycle
+    delete neighbors from newfacet that are also in samecycle
+    for each neighbor of a facet in samecycle
+      if neighbor is simplicial
+        if first visit
+          move the neighbor relation to newfacet
+          update facet links for its ridges
+        else
+          make ridges for neighbor
+          remove samecycle reference
+      else
+        update neighbor sets
+*/
+void qh_mergecycle_neighbors(facetT *samecycle, facetT *newfacet) {
+  facetT *same, *neighbor, **neighborp;
+  int delneighbors= 0, newneighbors= 0;
+  unsigned int samevisitid;
+  ridgeT *ridge, **ridgep;
+
+  samevisitid= ++qh visit_id;
+  FORALLsame_cycle_(samecycle) {
+    if (same->visitid == samevisitid || same->visible)
+      qh_infiniteloop(samecycle);
+    same->visitid= samevisitid;
+  }
+  newfacet->visitid= ++qh visit_id;
+  trace4((qh ferr, 4031, "qh_mergecycle_neighbors: delete shared neighbors from newfacet\n"));
+  FOREACHneighbor_(newfacet) {
+    if (neighbor->visitid == samevisitid) {
+      SETref_(neighbor)= NULL;  /* samecycle neighbors deleted */
+      delneighbors++;
+    }else
+      neighbor->visitid= qh visit_id;
+  }
+  qh_setcompact(newfacet->neighbors);
+
+  trace4((qh ferr, 4032, "qh_mergecycle_neighbors: update neighbors\n"));
+  FORALLsame_cycle_(samecycle) {
+    FOREACHneighbor_(same) {
+      if (neighbor->visitid == samevisitid)
+        continue;
+      if (neighbor->simplicial) {
+        if (neighbor->visitid != qh visit_id) {
+          qh_setappend(&newfacet->neighbors, neighbor);
+          qh_setreplace(neighbor->neighbors, same, newfacet);
+          newneighbors++;
+          neighbor->visitid= qh visit_id;
+          FOREACHridge_(neighbor->ridges) { /* update ridge in case of qh_makeridges */
+            if (ridge->top == same) {
+              ridge->top= newfacet;
+              break;
+            }else if (ridge->bottom == same) {
+              ridge->bottom= newfacet;
+              break;
+            }
+          }
+        }else {
+          qh_makeridges(neighbor);
+          qh_setdel(neighbor->neighbors, same);
+          /* same can't be horizon facet for neighbor */
+        }
+      }else { /* non-simplicial neighbor */
+        qh_setdel(neighbor->neighbors, same);
+        if (neighbor->visitid != qh visit_id) {
+          qh_setappend(&neighbor->neighbors, newfacet);
+          qh_setappend(&newfacet->neighbors, neighbor);
+          neighbor->visitid= qh visit_id;
+          newneighbors++;
+        }
+      }
+    }
+  }
+  trace2((qh ferr, 2032, "qh_mergecycle_neighbors: deleted %d neighbors and added %d\n",
+             delneighbors, newneighbors));
+} /* mergecycle_neighbors */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="mergecycle_ridges">-</a>
+
+  qh_mergecycle_ridges( samecycle, newfacet )
+    add ridges/neighbors for facets in samecycle to newfacet
+    all new/old neighbors of newfacet marked with qh.visit_id
+    facets in samecycle marked with qh.visit_id-1
+    newfacet marked with qh.visit_id
+
+  returns:
+    newfacet has merged ridges
+
+  notes:
+    ridge already updated for simplicial neighbors of samecycle with a ridge
+
+  see:
+    qh_mergeridges()
+    qh_makeridges()
+
+  design:
+    remove ridges between newfacet and samecycle
+    for each facet in samecycle
+      for each ridge in facet
+        update facet pointers in ridge
+        skip ridges processed in qh_mergecycle_neighors
+        free ridges between newfacet and samecycle
+        free ridges between facets of samecycle (on 2nd visit)
+        append remaining ridges to newfacet
+      if simpilicial facet
+        for each neighbor of facet
+          if simplicial facet
+          and not samecycle facet or newfacet
+            make ridge between neighbor and newfacet
+*/
+void qh_mergecycle_ridges(facetT *samecycle, facetT *newfacet) {
+  facetT *same, *neighbor= NULL;
+  int numold=0, numnew=0;
+  int neighbor_i, neighbor_n;
+  unsigned int samevisitid;
+  ridgeT *ridge, **ridgep;
+  boolT toporient;
+  void **freelistp; /* used !qh_NOmem */
+
+  trace4((qh ferr, 4033, "qh_mergecycle_ridges: delete shared ridges from newfacet\n"));
+  samevisitid= qh visit_id -1;
+  FOREACHridge_(newfacet->ridges) {
+    neighbor= otherfacet_(ridge, newfacet);
+    if (neighbor->visitid == samevisitid)
+      SETref_(ridge)= NULL; /* ridge free'd below */
+  }
+  qh_setcompact(newfacet->ridges);
+
+  trace4((qh ferr, 4034, "qh_mergecycle_ridges: add ridges to newfacet\n"));
+  FORALLsame_cycle_(samecycle) {
+    FOREACHridge_(same->ridges) {
+      if (ridge->top == same) {
+        ridge->top= newfacet;
+        neighbor= ridge->bottom;
+      }else if (ridge->bottom == same) {
+        ridge->bottom= newfacet;
+        neighbor= ridge->top;
+      }else if (ridge->top == newfacet || ridge->bottom == newfacet) {
+        qh_setappend(&newfacet->ridges, ridge);
+        numold++;  /* already set by qh_mergecycle_neighbors */
+        continue;
+      }else {
+        qh_fprintf(qh ferr, 6098, "qhull internal error (qh_mergecycle_ridges): bad ridge r%d\n", ridge->id);
+        qh_errexit(qh_ERRqhull, NULL, ridge);
+      }
+      if (neighbor == newfacet) {
+        qh_setfree(&(ridge->vertices));
+        qh_memfree_(ridge, (int)sizeof(ridgeT), freelistp);
+        numold++;
+      }else if (neighbor->visitid == samevisitid) {
+        qh_setdel(neighbor->ridges, ridge);
+        qh_setfree(&(ridge->vertices));
+        qh_memfree_(ridge, (int)sizeof(ridgeT), freelistp);
+        numold++;
+      }else {
+        qh_setappend(&newfacet->ridges, ridge);
+        numold++;
+      }
+    }
+    if (same->ridges)
+      qh_settruncate(same->ridges, 0);
+    if (!same->simplicial)
+      continue;
+    FOREACHneighbor_i_(same) {       /* note: !newfact->simplicial */
+      if (neighbor->visitid != samevisitid && neighbor->simplicial) {
+        ridge= qh_newridge();
+        ridge->vertices= qh_setnew_delnthsorted(same->vertices, qh hull_dim,
+                                                          neighbor_i, 0);
+        toporient= same->toporient ^ (neighbor_i & 0x1);
+        if (toporient) {
+          ridge->top= newfacet;
+          ridge->bottom= neighbor;
+        }else {
+          ridge->top= neighbor;
+          ridge->bottom= newfacet;
+        }
+        qh_setappend(&(newfacet->ridges), ridge);
+        qh_setappend(&(neighbor->ridges), ridge);
+        numnew++;
+      }
+    }
+  }
+
+  trace2((qh ferr, 2033, "qh_mergecycle_ridges: found %d old ridges and %d new ones\n",
+             numold, numnew));
+} /* mergecycle_ridges */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="mergecycle_vneighbors">-</a>
+
+  qh_mergecycle_vneighbors( samecycle, newfacet )
+    create vertex neighbors for newfacet from vertices of facets in samecycle
+    samecycle marked with visitid == qh.visit_id - 1
+
+  returns:
+    newfacet vertices with updated neighbors
+    marks newfacet with qh.visit_id-1
+    deletes vertices that are merged away
+    sets delridge on all vertices (faster here than in mergecycle_ridges)
+
+  see:
+    qh_mergevertex_neighbors()
+
+  design:
+    for each vertex of samecycle facet
+      set vertex->delridge
+      delete samecycle facets from vertex neighbors
+      append newfacet to vertex neighbors
+      if vertex only in newfacet
+        delete it from newfacet
+        add it to qh.del_vertices for later deletion
+*/
+void qh_mergecycle_vneighbors(facetT *samecycle, facetT *newfacet) {
+  facetT *neighbor, **neighborp;
+  unsigned int mergeid;
+  vertexT *vertex, **vertexp, *apex;
+  setT *vertices;
+
+  trace4((qh ferr, 4035, "qh_mergecycle_vneighbors: update vertex neighbors for newfacet\n"));
+  mergeid= qh visit_id - 1;
+  newfacet->visitid= mergeid;
+  vertices= qh_basevertices(samecycle); /* temp */
+  apex= SETfirstt_(samecycle->vertices, vertexT);
+  qh_setappend(&vertices, apex);
+  FOREACHvertex_(vertices) {
+    vertex->delridge= True;
+    FOREACHneighbor_(vertex) {
+      if (neighbor->visitid == mergeid)
+        SETref_(neighbor)= NULL;
+    }
+    qh_setcompact(vertex->neighbors);
+    qh_setappend(&vertex->neighbors, newfacet);
+    if (!SETsecond_(vertex->neighbors)) {
+      zinc_(Zcyclevertex);
+      trace2((qh ferr, 2034, "qh_mergecycle_vneighbors: deleted v%d when merging cycle f%d into f%d\n",
+        vertex->id, samecycle->id, newfacet->id));
+      qh_setdelsorted(newfacet->vertices, vertex);
+      vertex->deleted= True;
+      qh_setappend(&qh del_vertices, vertex);
+    }
+  }
+  qh_settempfree(&vertices);
+  trace3((qh ferr, 3005, "qh_mergecycle_vneighbors: merged vertices from cycle f%d into f%d\n",
+             samecycle->id, newfacet->id));
+} /* mergecycle_vneighbors */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="mergefacet">-</a>
+
+  qh_mergefacet( facet1, facet2, mindist, maxdist, mergeapex )
+    merges facet1 into facet2
+    mergeapex==qh_MERGEapex if merging new facet into coplanar horizon
+
+  returns:
+    qh.max_outside and qh.min_vertex updated
+    initializes vertex neighbors on first merge
+
+  returns:
+    facet2 contains facet1's vertices, neighbors, and ridges
+      facet2 moved to end of qh.facet_list
+      makes facet2 a newfacet
+      sets facet2->newmerge set
+      clears facet2->center (unless merging into a large facet)
+      clears facet2->tested and ridge->tested for facet1
+
+    facet1 prepended to visible_list for later deletion and partitioning
+      facet1->f.replace == facet2
+
+    adds neighboring facets to facet_mergeset if redundant or degenerate
+
+  notes:
+    mindist/maxdist may be NULL (only if both NULL)
+    traces merge if fmax_(maxdist,-mindist) > TRACEdist
+
+  see:
+    qh_mergecycle()
+
+  design:
+    trace merge and check for degenerate simplex
+    make ridges for both facets
+    update qh.max_outside, qh.max_vertex, qh.min_vertex
+    update facet2->maxoutside and keepcentrum
+    update facet2->nummerge
+    update tested flags for facet2
+    if facet1 is simplicial
+      merge facet1 into facet2
+    else
+      merge facet1's neighbors into facet2
+      merge facet1's ridges into facet2
+      merge facet1's vertices into facet2
+      merge facet1's vertex neighbors into facet2
+      add facet2's vertices to qh.new_vertexlist
+      unless qh_MERGEapex
+        test facet2 for degenerate or redundant neighbors
+      move facet1 to qh.visible_list for later deletion
+      move facet2 to end of qh.newfacet_list
+*/
+void qh_mergefacet(facetT *facet1, facetT *facet2, realT *mindist, realT *maxdist, boolT mergeapex) {
+  boolT traceonce= False;
+  vertexT *vertex, **vertexp;
+  int tracerestore=0, nummerge;
+
+  if (facet1->tricoplanar || facet2->tricoplanar) {
+    if (!qh TRInormals) {
+      qh_fprintf(qh ferr, 6226, "Qhull internal error (qh_mergefacet): does not work for tricoplanar facets.  Use option 'Q11'\n");
+      qh_errexit2 (qh_ERRqhull, facet1, facet2);
+    }
+    if (facet2->tricoplanar) {
+      facet2->tricoplanar= False;
+      facet2->keepcentrum= False;
+    }
+  }
+  zzinc_(Ztotmerge);
+  if (qh REPORTfreq2 && qh POSTmerging) {
+    if (zzval_(Ztotmerge) > qh mergereport + qh REPORTfreq2)
+      qh_tracemerging();
+  }
+#ifndef qh_NOtrace
+  if (qh build_cnt >= qh RERUN) {
+    if (mindist && (-*mindist > qh TRACEdist || *maxdist > qh TRACEdist)) {
+      tracerestore= 0;
+      qh IStracing= qh TRACElevel;
+      traceonce= True;
+      qh_fprintf(qh ferr, 8075, "qh_mergefacet: ========= trace wide merge #%d(%2.2g) for f%d into f%d, last point was p%d\n", zzval_(Ztotmerge),
+             fmax_(-*mindist, *maxdist), facet1->id, facet2->id, qh furthest_id);
+    }else if (facet1 == qh tracefacet || facet2 == qh tracefacet) {
+      tracerestore= qh IStracing;
+      qh IStracing= 4;
+      traceonce= True;
+      qh_fprintf(qh ferr, 8076, "qh_mergefacet: ========= trace merge #%d involving f%d, furthest is p%d\n",
+                 zzval_(Ztotmerge), qh tracefacet_id,  qh furthest_id);
+    }
+  }
+  if (qh IStracing >= 2) {
+    realT mergemin= -2;
+    realT mergemax= -2;
+
+    if (mindist) {
+      mergemin= *mindist;
+      mergemax= *maxdist;
+    }
+    qh_fprintf(qh ferr, 8077, "qh_mergefacet: #%d merge f%d into f%d, mindist= %2.2g, maxdist= %2.2g\n",
+    zzval_(Ztotmerge), facet1->id, facet2->id, mergemin, mergemax);
+  }
+#endif /* !qh_NOtrace */
+  if (facet1 == facet2 || facet1->visible || facet2->visible) {
+    qh_fprintf(qh ferr, 6099, "qhull internal error (qh_mergefacet): either f%d and f%d are the same or one is a visible facet\n",
+             facet1->id, facet2->id);
+    qh_errexit2 (qh_ERRqhull, facet1, facet2);
+  }
+  if (qh num_facets - qh num_visible <= qh hull_dim + 1) {
+    qh_fprintf(qh ferr, 6227, "\n\
+qhull precision error: Only %d facets remain.  Can not merge another\n\
+pair.  The input is too degenerate or the convexity constraints are\n\
+too strong.\n", qh hull_dim+1);
+    if (qh hull_dim >= 5 && !qh MERGEexact)
+      qh_fprintf(qh ferr, 8079, "Option 'Qx' may avoid this problem.\n");
+    qh_errexit(qh_ERRprec, NULL, NULL);
+  }
+  if (!qh VERTEXneighbors)
+    qh_vertexneighbors();
+  qh_makeridges(facet1);
+  qh_makeridges(facet2);
+  if (qh IStracing >=4)
+    qh_errprint("MERGING", facet1, facet2, NULL, NULL);
+  if (mindist) {
+    maximize_(qh max_outside, *maxdist);
+    maximize_(qh max_vertex, *maxdist);
+#if qh_MAXoutside
+    maximize_(facet2->maxoutside, *maxdist);
+#endif
+    minimize_(qh min_vertex, *mindist);
+    if (!facet2->keepcentrum
+    && (*maxdist > qh WIDEfacet || *mindist < -qh WIDEfacet)) {
+      facet2->keepcentrum= True;
+      zinc_(Zwidefacet);
+    }
+  }
+  nummerge= facet1->nummerge + facet2->nummerge + 1;
+  if (nummerge >= qh_MAXnummerge)
+    facet2->nummerge= qh_MAXnummerge;
+  else
+    facet2->nummerge= (short unsigned int)nummerge;
+  facet2->newmerge= True;
+  facet2->dupridge= False;
+  qh_updatetested  (facet1, facet2);
+  if (qh hull_dim > 2 && qh_setsize(facet1->vertices) == qh hull_dim)
+    qh_mergesimplex(facet1, facet2, mergeapex);
+  else {
+    qh vertex_visit++;
+    FOREACHvertex_(facet2->vertices)
+      vertex->visitid= qh vertex_visit;
+    if (qh hull_dim == 2)
+      qh_mergefacet2d(facet1, facet2);
+    else {
+      qh_mergeneighbors(facet1, facet2);
+      qh_mergevertices(facet1->vertices, &facet2->vertices);
+    }
+    qh_mergeridges(facet1, facet2);
+    qh_mergevertex_neighbors(facet1, facet2);
+    if (!facet2->newfacet)
+      qh_newvertices(facet2->vertices);
+  }
+  if (!mergeapex)
+    qh_degen_redundant_neighbors(facet2, facet1);
+  if (facet2->coplanar || !facet2->newfacet) {
+    zinc_(Zmergeintohorizon);
+  }else if (!facet1->newfacet && facet2->newfacet) {
+    zinc_(Zmergehorizon);
+  }else {
+    zinc_(Zmergenew);
+  }
+  qh_willdelete(facet1, facet2);
+  qh_removefacet(facet2);  /* append as a newfacet to end of qh facet_list */
+  qh_appendfacet(facet2);
+  facet2->newfacet= True;
+  facet2->tested= False;
+  qh_tracemerge(facet1, facet2);
+  if (traceonce) {
+    qh_fprintf(qh ferr, 8080, "qh_mergefacet: end of wide tracing\n");
+    qh IStracing= tracerestore;
+  }
+} /* mergefacet */
+
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="mergefacet2d">-</a>
+
+  qh_mergefacet2d( facet1, facet2 )
+    in 2d, merges neighbors and vertices of facet1 into facet2
+
+  returns:
+    build ridges for neighbors if necessary
+    facet2 looks like a simplicial facet except for centrum, ridges
+      neighbors are opposite the corresponding vertex
+      maintains orientation of facet2
+
+  notes:
+    qh_mergefacet() retains non-simplicial structures
+      they are not needed in 2d, but later routines may use them
+    preserves qh.vertex_visit for qh_mergevertex_neighbors()
+
+  design:
+    get vertices and neighbors
+    determine new vertices and neighbors
+    set new vertices and neighbors and adjust orientation
+    make ridges for new neighbor if needed
+*/
+void qh_mergefacet2d(facetT *facet1, facetT *facet2) {
+  vertexT *vertex1A, *vertex1B, *vertex2A, *vertex2B, *vertexA, *vertexB;
+  facetT *neighbor1A, *neighbor1B, *neighbor2A, *neighbor2B, *neighborA, *neighborB;
+
+  vertex1A= SETfirstt_(facet1->vertices, vertexT);
+  vertex1B= SETsecondt_(facet1->vertices, vertexT);
+  vertex2A= SETfirstt_(facet2->vertices, vertexT);
+  vertex2B= SETsecondt_(facet2->vertices, vertexT);
+  neighbor1A= SETfirstt_(facet1->neighbors, facetT);
+  neighbor1B= SETsecondt_(facet1->neighbors, facetT);
+  neighbor2A= SETfirstt_(facet2->neighbors, facetT);
+  neighbor2B= SETsecondt_(facet2->neighbors, facetT);
+  if (vertex1A == vertex2A) {
+    vertexA= vertex1B;
+    vertexB= vertex2B;
+    neighborA= neighbor2A;
+    neighborB= neighbor1A;
+  }else if (vertex1A == vertex2B) {
+    vertexA= vertex1B;
+    vertexB= vertex2A;
+    neighborA= neighbor2B;
+    neighborB= neighbor1A;
+  }else if (vertex1B == vertex2A) {
+    vertexA= vertex1A;
+    vertexB= vertex2B;
+    neighborA= neighbor2A;
+    neighborB= neighbor1B;
+  }else { /* 1B == 2B */
+    vertexA= vertex1A;
+    vertexB= vertex2A;
+    neighborA= neighbor2B;
+    neighborB= neighbor1B;
+  }
+  /* vertexB always from facet2, neighborB always from facet1 */
+  if (vertexA->id > vertexB->id) {
+    SETfirst_(facet2->vertices)= vertexA;
+    SETsecond_(facet2->vertices)= vertexB;
+    if (vertexB == vertex2A)
+      facet2->toporient= !facet2->toporient;
+    SETfirst_(facet2->neighbors)= neighborA;
+    SETsecond_(facet2->neighbors)= neighborB;
+  }else {
+    SETfirst_(facet2->vertices)= vertexB;
+    SETsecond_(facet2->vertices)= vertexA;
+    if (vertexB == vertex2B)
+      facet2->toporient= !facet2->toporient;
+    SETfirst_(facet2->neighbors)= neighborB;
+    SETsecond_(facet2->neighbors)= neighborA;
+  }
+  qh_makeridges(neighborB);
+  qh_setreplace(neighborB->neighbors, facet1, facet2);
+  trace4((qh ferr, 4036, "qh_mergefacet2d: merged v%d and neighbor f%d of f%d into f%d\n",
+       vertexA->id, neighborB->id, facet1->id, facet2->id));
+} /* mergefacet2d */
+
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="mergeneighbors">-</a>
+
+  qh_mergeneighbors( facet1, facet2 )
+    merges the neighbors of facet1 into facet2
+
+  see:
+    qh_mergecycle_neighbors()
+
+  design:
+    for each neighbor of facet1
+      if neighbor is also a neighbor of facet2
+        if neighbor is simpilicial
+          make ridges for later deletion as a degenerate facet
+        update its neighbor set
+      else
+        move the neighbor relation to facet2
+    remove the neighbor relation for facet1 and facet2
+*/
+void qh_mergeneighbors(facetT *facet1, facetT *facet2) {
+  facetT *neighbor, **neighborp;
+
+  trace4((qh ferr, 4037, "qh_mergeneighbors: merge neighbors of f%d and f%d\n",
+          facet1->id, facet2->id));
+  qh visit_id++;
+  FOREACHneighbor_(facet2) {
+    neighbor->visitid= qh visit_id;
+  }
+  FOREACHneighbor_(facet1) {
+    if (neighbor->visitid == qh visit_id) {
+      if (neighbor->simplicial)    /* is degen, needs ridges */
+        qh_makeridges(neighbor);
+      if (SETfirstt_(neighbor->neighbors, facetT) != facet1) /*keep newfacet->horizon*/
+        qh_setdel(neighbor->neighbors, facet1);
+      else {
+        qh_setdel(neighbor->neighbors, facet2);
+        qh_setreplace(neighbor->neighbors, facet1, facet2);
+      }
+    }else if (neighbor != facet2) {
+      qh_setappend(&(facet2->neighbors), neighbor);
+      qh_setreplace(neighbor->neighbors, facet1, facet2);
+    }
+  }
+  qh_setdel(facet1->neighbors, facet2);  /* here for makeridges */
+  qh_setdel(facet2->neighbors, facet1);
+} /* mergeneighbors */
+
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="mergeridges">-</a>
+
+  qh_mergeridges( facet1, facet2 )
+    merges the ridge set of facet1 into facet2
+
+  returns:
+    may delete all ridges for a vertex
+    sets vertex->delridge on deleted ridges
+
+  see:
+    qh_mergecycle_ridges()
+
+  design:
+    delete ridges between facet1 and facet2
+      mark (delridge) vertices on these ridges for later testing
+    for each remaining ridge
+      rename facet1 to facet2
+*/
+void qh_mergeridges(facetT *facet1, facetT *facet2) {
+  ridgeT *ridge, **ridgep;
+  vertexT *vertex, **vertexp;
+
+  trace4((qh ferr, 4038, "qh_mergeridges: merge ridges of f%d and f%d\n",
+          facet1->id, facet2->id));
+  FOREACHridge_(facet2->ridges) {
+    if ((ridge->top == facet1) || (ridge->bottom == facet1)) {
+      FOREACHvertex_(ridge->vertices)
+        vertex->delridge= True;
+      qh_delridge(ridge);  /* expensive in high-d, could rebuild */
+      ridgep--; /*repeat*/
+    }
+  }
+  FOREACHridge_(facet1->ridges) {
+    if (ridge->top == facet1)
+      ridge->top= facet2;
+    else
+      ridge->bottom= facet2;
+    qh_setappend(&(facet2->ridges), ridge);
+  }
+} /* mergeridges */
+
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="mergesimplex">-</a>
+
+  qh_mergesimplex( facet1, facet2, mergeapex )
+    merge simplicial facet1 into facet2
+    mergeapex==qh_MERGEapex if merging samecycle into horizon facet
+      vertex id is latest (most recently created)
+    facet1 may be contained in facet2
+    ridges exist for both facets
+
+  returns:
+    facet2 with updated vertices, ridges, neighbors
+    updated neighbors for facet1's vertices
+    facet1 not deleted
+    sets vertex->delridge on deleted ridges
+
+  notes:
+    special case code since this is the most common merge
+    called from qh_mergefacet()
+
+  design:
+    if qh_MERGEapex
+      add vertices of facet2 to qh.new_vertexlist if necessary
+      add apex to facet2
+    else
+      for each ridge between facet1 and facet2
+        set vertex->delridge
+      determine the apex for facet1 (i.e., vertex to be merged)
+      unless apex already in facet2
+        insert apex into vertices for facet2
+      add vertices of facet2 to qh.new_vertexlist if necessary
+      add apex to qh.new_vertexlist if necessary
+      for each vertex of facet1
+        if apex
+          rename facet1 to facet2 in its vertex neighbors
+        else
+          delete facet1 from vertex neighors
+          if only in facet2
+            add vertex to qh.del_vertices for later deletion
+      for each ridge of facet1
+        delete ridges between facet1 and facet2
+        append other ridges to facet2 after renaming facet to facet2
+*/
+void qh_mergesimplex(facetT *facet1, facetT *facet2, boolT mergeapex) {
+  vertexT *vertex, **vertexp, *apex;
+  ridgeT *ridge, **ridgep;
+  boolT issubset= False;
+  int vertex_i= -1, vertex_n;
+  facetT *neighbor, **neighborp, *otherfacet;
+
+  if (mergeapex) {
+    if (!facet2->newfacet)
+      qh_newvertices(facet2->vertices);  /* apex is new */
+    apex= SETfirstt_(facet1->vertices, vertexT);
+    if (SETfirstt_(facet2->vertices, vertexT) != apex)
+      qh_setaddnth(&facet2->vertices, 0, apex);  /* apex has last id */
+    else
+      issubset= True;
+  }else {
+    zinc_(Zmergesimplex);
+    FOREACHvertex_(facet1->vertices)
+      vertex->seen= False;
+    FOREACHridge_(facet1->ridges) {
+      if (otherfacet_(ridge, facet1) == facet2) {
+        FOREACHvertex_(ridge->vertices) {
+          vertex->seen= True;
+          vertex->delridge= True;
+        }
+        break;
+      }
+    }
+    FOREACHvertex_(facet1->vertices) {
+      if (!vertex->seen)
+        break;  /* must occur */
+    }
+    apex= vertex;
+    trace4((qh ferr, 4039, "qh_mergesimplex: merge apex v%d of f%d into facet f%d\n",
+          apex->id, facet1->id, facet2->id));
+    FOREACHvertex_i_(facet2->vertices) {
+      if (vertex->id < apex->id) {
+        break;
+      }else if (vertex->id == apex->id) {
+        issubset= True;
+        break;
+      }
+    }
+    if (!issubset)
+      qh_setaddnth(&facet2->vertices, vertex_i, apex);
+    if (!facet2->newfacet)
+      qh_newvertices(facet2->vertices);
+    else if (!apex->newlist) {
+      qh_removevertex(apex);
+      qh_appendvertex(apex);
+    }
+  }
+  trace4((qh ferr, 4040, "qh_mergesimplex: update vertex neighbors of f%d\n",
+          facet1->id));
+  FOREACHvertex_(facet1->vertices) {
+    if (vertex == apex && !issubset)
+      qh_setreplace(vertex->neighbors, facet1, facet2);
+    else {
+      qh_setdel(vertex->neighbors, facet1);
+      if (!SETsecond_(vertex->neighbors))
+        qh_mergevertex_del(vertex, facet1, facet2);
+    }
+  }
+  trace4((qh ferr, 4041, "qh_mergesimplex: merge ridges and neighbors of f%d into f%d\n",
+          facet1->id, facet2->id));
+  qh visit_id++;
+  FOREACHneighbor_(facet2)
+    neighbor->visitid= qh visit_id;
+  FOREACHridge_(facet1->ridges) {
+    otherfacet= otherfacet_(ridge, facet1);
+    if (otherfacet == facet2) {
+      qh_setdel(facet2->ridges, ridge);
+      qh_setfree(&(ridge->vertices));
+      qh_memfree(ridge, (int)sizeof(ridgeT));
+      qh_setdel(facet2->neighbors, facet1);
+    }else {
+      qh_setappend(&facet2->ridges, ridge);
+      if (otherfacet->visitid != qh visit_id) {
+        qh_setappend(&facet2->neighbors, otherfacet);
+        qh_setreplace(otherfacet->neighbors, facet1, facet2);
+        otherfacet->visitid= qh visit_id;
+      }else {
+        if (otherfacet->simplicial)    /* is degen, needs ridges */
+          qh_makeridges(otherfacet);
+        if (SETfirstt_(otherfacet->neighbors, facetT) != facet1)
+          qh_setdel(otherfacet->neighbors, facet1);
+        else {   /*keep newfacet->neighbors->horizon*/
+          qh_setdel(otherfacet->neighbors, facet2);
+          qh_setreplace(otherfacet->neighbors, facet1, facet2);
+        }
+      }
+      if (ridge->top == facet1) /* wait until after qh_makeridges */
+        ridge->top= facet2;
+      else
+        ridge->bottom= facet2;
+    }
+  }
+  SETfirst_(facet1->ridges)= NULL; /* it will be deleted */
+  trace3((qh ferr, 3006, "qh_mergesimplex: merged simplex f%d apex v%d into facet f%d\n",
+          facet1->id, getid_(apex), facet2->id));
+} /* mergesimplex */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="mergevertex_del">-</a>
+
+  qh_mergevertex_del( vertex, facet1, facet2 )
+    delete a vertex because of merging facet1 into facet2
+
+  returns:
+    deletes vertex from facet2
+    adds vertex to qh.del_vertices for later deletion
+*/
+void qh_mergevertex_del(vertexT *vertex, facetT *facet1, facetT *facet2) {
+
+  zinc_(Zmergevertex);
+  trace2((qh ferr, 2035, "qh_mergevertex_del: deleted v%d when merging f%d into f%d\n",
+          vertex->id, facet1->id, facet2->id));
+  qh_setdelsorted(facet2->vertices, vertex);
+  vertex->deleted= True;
+  qh_setappend(&qh del_vertices, vertex);
+} /* mergevertex_del */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="mergevertex_neighbors">-</a>
+
+  qh_mergevertex_neighbors( facet1, facet2 )
+    merge the vertex neighbors of facet1 to facet2
+
+  returns:
+    if vertex is current qh.vertex_visit
+      deletes facet1 from vertex->neighbors
+    else
+      renames facet1 to facet2 in vertex->neighbors
+    deletes vertices if only one neighbor
+
+  notes:
+    assumes vertex neighbor sets are good
+*/
+void qh_mergevertex_neighbors(facetT *facet1, facetT *facet2) {
+  vertexT *vertex, **vertexp;
+
+  trace4((qh ferr, 4042, "qh_mergevertex_neighbors: merge vertex neighbors of f%d and f%d\n",
+          facet1->id, facet2->id));
+  if (qh tracevertex) {
+    qh_fprintf(qh ferr, 8081, "qh_mergevertex_neighbors: of f%d and f%d at furthest p%d f0= %p\n",
+             facet1->id, facet2->id, qh furthest_id, qh tracevertex->neighbors->e[0].p);
+    qh_errprint("TRACE", NULL, NULL, NULL, qh tracevertex);
+  }
+  FOREACHvertex_(facet1->vertices) {
+    if (vertex->visitid != qh vertex_visit)
+      qh_setreplace(vertex->neighbors, facet1, facet2);
+    else {
+      qh_setdel(vertex->neighbors, facet1);
+      if (!SETsecond_(vertex->neighbors))
+        qh_mergevertex_del(vertex, facet1, facet2);
+    }
+  }
+  if (qh tracevertex)
+    qh_errprint("TRACE", NULL, NULL, NULL, qh tracevertex);
+} /* mergevertex_neighbors */
+
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="mergevertices">-</a>
+
+  qh_mergevertices( vertices1, vertices2 )
+    merges the vertex set of facet1 into facet2
+
+  returns:
+    replaces vertices2 with merged set
+    preserves vertex_visit for qh_mergevertex_neighbors
+    updates qh.newvertex_list
+
+  design:
+    create a merged set of both vertices (in inverse id order)
+*/
+void qh_mergevertices(setT *vertices1, setT **vertices2) {
+  int newsize= qh_setsize(vertices1)+qh_setsize(*vertices2) - qh hull_dim + 1;
+  setT *mergedvertices;
+  vertexT *vertex, **vertexp, **vertex2= SETaddr_(*vertices2, vertexT);
+
+  mergedvertices= qh_settemp(newsize);
+  FOREACHvertex_(vertices1) {
+    if (!*vertex2 || vertex->id > (*vertex2)->id)
+      qh_setappend(&mergedvertices, vertex);
+    else {
+      while (*vertex2 && (*vertex2)->id > vertex->id)
+        qh_setappend(&mergedvertices, *vertex2++);
+      if (!*vertex2 || (*vertex2)->id < vertex->id)
+        qh_setappend(&mergedvertices, vertex);
+      else
+        qh_setappend(&mergedvertices, *vertex2++);
+    }
+  }
+  while (*vertex2)
+    qh_setappend(&mergedvertices, *vertex2++);
+  if (newsize < qh_setsize(mergedvertices)) {
+    qh_fprintf(qh ferr, 6100, "qhull internal error (qh_mergevertices): facets did not share a ridge\n");
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  qh_setfree(vertices2);
+  *vertices2= mergedvertices;
+  qh_settemppop();
+} /* mergevertices */
+
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="neighbor_intersections">-</a>
+
+  qh_neighbor_intersections( vertex )
+    return intersection of all vertices in vertex->neighbors except for vertex
+
+  returns:
+    returns temporary set of vertices
+    does not include vertex
+    NULL if a neighbor is simplicial
+    NULL if empty set
+
+  notes:
+    used for renaming vertices
+
+  design:
+    initialize the intersection set with vertices of the first two neighbors
+    delete vertex from the intersection
+    for each remaining neighbor
+      intersect its vertex set with the intersection set
+      return NULL if empty
+    return the intersection set
+*/
+setT *qh_neighbor_intersections(vertexT *vertex) {
+  facetT *neighbor, **neighborp, *neighborA, *neighborB;
+  setT *intersect;
+  int neighbor_i, neighbor_n;
+
+  FOREACHneighbor_(vertex) {
+    if (neighbor->simplicial)
+      return NULL;
+  }
+  neighborA= SETfirstt_(vertex->neighbors, facetT);
+  neighborB= SETsecondt_(vertex->neighbors, facetT);
+  zinc_(Zintersectnum);
+  if (!neighborA)
+    return NULL;
+  if (!neighborB)
+    intersect= qh_setcopy(neighborA->vertices, 0);
+  else
+    intersect= qh_vertexintersect_new(neighborA->vertices, neighborB->vertices);
+  qh_settemppush(intersect);
+  qh_setdelsorted(intersect, vertex);
+  FOREACHneighbor_i_(vertex) {
+    if (neighbor_i >= 2) {
+      zinc_(Zintersectnum);
+      qh_vertexintersect(&intersect, neighbor->vertices);
+      if (!SETfirst_(intersect)) {
+        zinc_(Zintersectfail);
+        qh_settempfree(&intersect);
+        return NULL;
+      }
+    }
+  }
+  trace3((qh ferr, 3007, "qh_neighbor_intersections: %d vertices in neighbor intersection of v%d\n",
+          qh_setsize(intersect), vertex->id));
+  return intersect;
+} /* neighbor_intersections */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="newvertices">-</a>
+
+  qh_newvertices( vertices )
+    add vertices to end of qh.vertex_list (marks as new vertices)
+
+  returns:
+    vertices on qh.newvertex_list
+    vertex->newlist set
+*/
+void qh_newvertices(setT *vertices) {
+  vertexT *vertex, **vertexp;
+
+  FOREACHvertex_(vertices) {
+    if (!vertex->newlist) {
+      qh_removevertex(vertex);
+      qh_appendvertex(vertex);
+    }
+  }
+} /* newvertices */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="reducevertices">-</a>
+
+  qh_reducevertices()
+    reduce extra vertices, shared vertices, and redundant vertices
+    facet->newmerge is set if merged since last call
+    if !qh.MERGEvertices, only removes extra vertices
+
+  returns:
+    True if also merged degen_redundant facets
+    vertices are renamed if possible
+    clears facet->newmerge and vertex->delridge
+
+  notes:
+    ignored if 2-d
+
+  design:
+    merge any degenerate or redundant facets
+    for each newly merged facet
+      remove extra vertices
+    if qh.MERGEvertices
+      for each newly merged facet
+        for each vertex
+          if vertex was on a deleted ridge
+            rename vertex if it is shared
+      remove delridge flag from new vertices
+*/
+boolT qh_reducevertices(void) {
+  int numshare=0, numrename= 0;
+  boolT degenredun= False;
+  facetT *newfacet;
+  vertexT *vertex, **vertexp;
+
+  if (qh hull_dim == 2)
+    return False;
+  if (qh_merge_degenredundant())
+    degenredun= True;
+ LABELrestart:
+  FORALLnew_facets {
+    if (newfacet->newmerge) {
+      if (!qh MERGEvertices)
+        newfacet->newmerge= False;
+      qh_remove_extravertices(newfacet);
+    }
+  }
+  if (!qh MERGEvertices)
+    return False;
+  FORALLnew_facets {
+    if (newfacet->newmerge) {
+      newfacet->newmerge= False;
+      FOREACHvertex_(newfacet->vertices) {
+        if (vertex->delridge) {
+          if (qh_rename_sharedvertex(vertex, newfacet)) {
+            numshare++;
+            vertexp--; /* repeat since deleted vertex */
+          }
+        }
+      }
+    }
+  }
+  FORALLvertex_(qh newvertex_list) {
+    if (vertex->delridge && !vertex->deleted) {
+      vertex->delridge= False;
+      if (qh hull_dim >= 4 && qh_redundant_vertex(vertex)) {
+        numrename++;
+        if (qh_merge_degenredundant()) {
+          degenredun= True;
+          goto LABELrestart;
+        }
+      }
+    }
+  }
+  trace1((qh ferr, 1014, "qh_reducevertices: renamed %d shared vertices and %d redundant vertices. Degen? %d\n",
+          numshare, numrename, degenredun));
+  return degenredun;
+} /* reducevertices */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="redundant_vertex">-</a>
+
+  qh_redundant_vertex( vertex )
+    detect and rename a redundant vertex
+    vertices have full vertex->neighbors
+
+  returns:
+    returns true if find a redundant vertex
+      deletes vertex(vertex->deleted)
+
+  notes:
+    only needed if vertex->delridge and hull_dim >= 4
+    may add degenerate facets to qh.facet_mergeset
+    doesn't change vertex->neighbors or create redundant facets
+
+  design:
+    intersect vertices of all facet neighbors of vertex
+    determine ridges for these vertices
+    if find a new vertex for vertex among these ridges and vertices
+      rename vertex to the new vertex
+*/
+vertexT *qh_redundant_vertex(vertexT *vertex) {
+  vertexT *newvertex= NULL;
+  setT *vertices, *ridges;
+
+  trace3((qh ferr, 3008, "qh_redundant_vertex: check if v%d can be renamed\n", vertex->id));
+  if ((vertices= qh_neighbor_intersections(vertex))) {
+    ridges= qh_vertexridges(vertex);
+    if ((newvertex= qh_find_newvertex(vertex, vertices, ridges)))
+      qh_renamevertex(vertex, newvertex, ridges, NULL, NULL);
+    qh_settempfree(&ridges);
+    qh_settempfree(&vertices);
+  }
+  return newvertex;
+} /* redundant_vertex */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="remove_extravertices">-</a>
+
+  qh_remove_extravertices( facet )
+    remove extra vertices from non-simplicial facets
+
+  returns:
+    returns True if it finds them
+
+  design:
+    for each vertex in facet
+      if vertex not in a ridge (i.e., no longer used)
+        delete vertex from facet
+        delete facet from vertex's neighbors
+        unless vertex in another facet
+          add vertex to qh.del_vertices for later deletion
+*/
+boolT qh_remove_extravertices(facetT *facet) {
+  ridgeT *ridge, **ridgep;
+  vertexT *vertex, **vertexp;
+  boolT foundrem= False;
+
+  trace4((qh ferr, 4043, "qh_remove_extravertices: test f%d for extra vertices\n",
+          facet->id));
+  FOREACHvertex_(facet->vertices)
+    vertex->seen= False;
+  FOREACHridge_(facet->ridges) {
+    FOREACHvertex_(ridge->vertices)
+      vertex->seen= True;
+  }
+  FOREACHvertex_(facet->vertices) {
+    if (!vertex->seen) {
+      foundrem= True;
+      zinc_(Zremvertex);
+      qh_setdelsorted(facet->vertices, vertex);
+      qh_setdel(vertex->neighbors, facet);
+      if (!qh_setsize(vertex->neighbors)) {
+        vertex->deleted= True;
+        qh_setappend(&qh del_vertices, vertex);
+        zinc_(Zremvertexdel);
+        trace2((qh ferr, 2036, "qh_remove_extravertices: v%d deleted because it's lost all ridges\n", vertex->id));
+      }else
+        trace3((qh ferr, 3009, "qh_remove_extravertices: v%d removed from f%d because it's lost all ridges\n", vertex->id, facet->id));
+      vertexp--; /*repeat*/
+    }
+  }
+  return foundrem;
+} /* remove_extravertices */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="rename_sharedvertex">-</a>
+
+  qh_rename_sharedvertex( vertex, facet )
+    detect and rename if shared vertex in facet
+    vertices have full ->neighbors
+
+  returns:
+    newvertex or NULL
+    the vertex may still exist in other facets (i.e., a neighbor was pinched)
+    does not change facet->neighbors
+    updates vertex->neighbors
+
+  notes:
+    a shared vertex for a facet is only in ridges to one neighbor
+    this may undo a pinched facet
+
+    it does not catch pinches involving multiple facets.  These appear
+      to be difficult to detect, since an exhaustive search is too expensive.
+
+  design:
+    if vertex only has two neighbors
+      determine the ridges that contain the vertex
+      determine the vertices shared by both neighbors
+      if can find a new vertex in this set
+        rename the vertex to the new vertex
+*/
+vertexT *qh_rename_sharedvertex(vertexT *vertex, facetT *facet) {
+  facetT *neighbor, **neighborp, *neighborA= NULL;
+  setT *vertices, *ridges;
+  vertexT *newvertex;
+
+  if (qh_setsize(vertex->neighbors) == 2) {
+    neighborA= SETfirstt_(vertex->neighbors, facetT);
+    if (neighborA == facet)
+      neighborA= SETsecondt_(vertex->neighbors, facetT);
+  }else if (qh hull_dim == 3)
+    return NULL;
+  else {
+    qh visit_id++;
+    FOREACHneighbor_(facet)
+      neighbor->visitid= qh visit_id;
+    FOREACHneighbor_(vertex) {
+      if (neighbor->visitid == qh visit_id) {
+        if (neighborA)
+          return NULL;
+        neighborA= neighbor;
+      }
+    }
+    if (!neighborA) {
+      qh_fprintf(qh ferr, 6101, "qhull internal error (qh_rename_sharedvertex): v%d's neighbors not in f%d\n",
+        vertex->id, facet->id);
+      qh_errprint("ERRONEOUS", facet, NULL, NULL, vertex);
+      qh_errexit(qh_ERRqhull, NULL, NULL);
+    }
+  }
+  /* the vertex is shared by facet and neighborA */
+  ridges= qh_settemp(qh TEMPsize);
+  neighborA->visitid= ++qh visit_id;
+  qh_vertexridges_facet(vertex, facet, &ridges);
+  trace2((qh ferr, 2037, "qh_rename_sharedvertex: p%d(v%d) is shared by f%d(%d ridges) and f%d\n",
+    qh_pointid(vertex->point), vertex->id, facet->id, qh_setsize(ridges), neighborA->id));
+  zinc_(Zintersectnum);
+  vertices= qh_vertexintersect_new(facet->vertices, neighborA->vertices);
+  qh_setdel(vertices, vertex);
+  qh_settemppush(vertices);
+  if ((newvertex= qh_find_newvertex(vertex, vertices, ridges)))
+    qh_renamevertex(vertex, newvertex, ridges, facet, neighborA);
+  qh_settempfree(&vertices);
+  qh_settempfree(&ridges);
+  return newvertex;
+} /* rename_sharedvertex */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="renameridgevertex">-</a>
+
+  qh_renameridgevertex( ridge, oldvertex, newvertex )
+    renames oldvertex as newvertex in ridge
+
+  returns:
+
+  design:
+    delete oldvertex from ridge
+    if newvertex already in ridge
+      copy ridge->noconvex to another ridge if possible
+      delete the ridge
+    else
+      insert newvertex into the ridge
+      adjust the ridge's orientation
+*/
+void qh_renameridgevertex(ridgeT *ridge, vertexT *oldvertex, vertexT *newvertex) {
+  int nth= 0, oldnth;
+  facetT *temp;
+  vertexT *vertex, **vertexp;
+
+  oldnth= qh_setindex(ridge->vertices, oldvertex);
+  qh_setdelnthsorted(ridge->vertices, oldnth);
+  FOREACHvertex_(ridge->vertices) {
+    if (vertex == newvertex) {
+      zinc_(Zdelridge);
+      if (ridge->nonconvex) /* only one ridge has nonconvex set */
+        qh_copynonconvex(ridge);
+      trace2((qh ferr, 2038, "qh_renameridgevertex: ridge r%d deleted.  It contained both v%d and v%d\n",
+        ridge->id, oldvertex->id, newvertex->id));
+      qh_delridge(ridge);
+      return;
+    }
+    if (vertex->id < newvertex->id)
+      break;
+    nth++;
+  }
+  qh_setaddnth(&ridge->vertices, nth, newvertex);
+  if (abs(oldnth - nth)%2) {
+    trace3((qh ferr, 3010, "qh_renameridgevertex: swapped the top and bottom of ridge r%d\n",
+            ridge->id));
+    temp= ridge->top;
+    ridge->top= ridge->bottom;
+    ridge->bottom= temp;
+  }
+} /* renameridgevertex */
+
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="renamevertex">-</a>
+
+  qh_renamevertex( oldvertex, newvertex, ridges, oldfacet, neighborA )
+    renames oldvertex as newvertex in ridges
+    gives oldfacet/neighborA if oldvertex is shared between two facets
+
+  returns:
+    oldvertex may still exist afterwards
+
+
+  notes:
+    can not change neighbors of newvertex (since it's a subset)
+
+  design:
+    for each ridge in ridges
+      rename oldvertex to newvertex and delete degenerate ridges
+    if oldfacet not defined
+      for each neighbor of oldvertex
+        delete oldvertex from neighbor's vertices
+        remove extra vertices from neighbor
+      add oldvertex to qh.del_vertices
+    else if oldvertex only between oldfacet and neighborA
+      delete oldvertex from oldfacet and neighborA
+      add oldvertex to qh.del_vertices
+    else oldvertex is in oldfacet and neighborA and other facets (i.e., pinched)
+      delete oldvertex from oldfacet
+      delete oldfacet from oldvertice's neighbors
+      remove extra vertices (e.g., oldvertex) from neighborA
+*/
+void qh_renamevertex(vertexT *oldvertex, vertexT *newvertex, setT *ridges, facetT *oldfacet, facetT *neighborA) {
+  facetT *neighbor, **neighborp;
+  ridgeT *ridge, **ridgep;
+  boolT istrace= False;
+
+  if (qh IStracing >= 2 || oldvertex->id == qh tracevertex_id ||
+        newvertex->id == qh tracevertex_id)
+    istrace= True;
+  FOREACHridge_(ridges)
+    qh_renameridgevertex(ridge, oldvertex, newvertex);
+  if (!oldfacet) {
+    zinc_(Zrenameall);
+    if (istrace)
+      qh_fprintf(qh ferr, 8082, "qh_renamevertex: renamed v%d to v%d in several facets\n",
+               oldvertex->id, newvertex->id);
+    FOREACHneighbor_(oldvertex) {
+      qh_maydropneighbor(neighbor);
+      qh_setdelsorted(neighbor->vertices, oldvertex);
+      if (qh_remove_extravertices(neighbor))
+        neighborp--; /* neighbor may be deleted */
+    }
+    if (!oldvertex->deleted) {
+      oldvertex->deleted= True;
+      qh_setappend(&qh del_vertices, oldvertex);
+    }
+  }else if (qh_setsize(oldvertex->neighbors) == 2) {
+    zinc_(Zrenameshare);
+    if (istrace)
+      qh_fprintf(qh ferr, 8083, "qh_renamevertex: renamed v%d to v%d in oldfacet f%d\n",
+               oldvertex->id, newvertex->id, oldfacet->id);
+    FOREACHneighbor_(oldvertex)
+      qh_setdelsorted(neighbor->vertices, oldvertex);
+    oldvertex->deleted= True;
+    qh_setappend(&qh del_vertices, oldvertex);
+  }else {
+    zinc_(Zrenamepinch);
+    if (istrace || qh IStracing)
+      qh_fprintf(qh ferr, 8084, "qh_renamevertex: renamed pinched v%d to v%d between f%d and f%d\n",
+               oldvertex->id, newvertex->id, oldfacet->id, neighborA->id);
+    qh_setdelsorted(oldfacet->vertices, oldvertex);
+    qh_setdel(oldvertex->neighbors, oldfacet);
+    qh_remove_extravertices(neighborA);
+  }
+} /* renamevertex */
+
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="test_appendmerge">-</a>
+
+  qh_test_appendmerge( facet, neighbor )
+    tests facet/neighbor for convexity
+    appends to mergeset if non-convex
+    if pre-merging,
+      nop if qh.SKIPconvex, or qh.MERGEexact and coplanar
+
+  returns:
+    true if appends facet/neighbor to mergeset
+    sets facet->center as needed
+    does not change facet->seen
+
+  design:
+    if qh.cos_max is defined
+      if the angle between facet normals is too shallow
+        append an angle-coplanar merge to qh.mergeset
+        return True
+    make facet's centrum if needed
+    if facet's centrum is above the neighbor
+      set isconcave
+    else
+      if facet's centrum is not below the neighbor
+        set iscoplanar
+      make neighbor's centrum if needed
+      if neighbor's centrum is above the facet
+        set isconcave
+      else if neighbor's centrum is not below the facet
+        set iscoplanar
+   if isconcave or iscoplanar
+     get angle if needed
+     append concave or coplanar merge to qh.mergeset
+*/
+boolT qh_test_appendmerge(facetT *facet, facetT *neighbor) {
+  realT dist, dist2= -REALmax, angle= -REALmax;
+  boolT isconcave= False, iscoplanar= False, okangle= False;
+
+  if (qh SKIPconvex && !qh POSTmerging)
+    return False;
+  if ((!qh MERGEexact || qh POSTmerging) && qh cos_max < REALmax/2) {
+    angle= qh_getangle(facet->normal, neighbor->normal);
+    zinc_(Zangletests);
+    if (angle > qh cos_max) {
+      zinc_(Zcoplanarangle);
+      qh_appendmergeset(facet, neighbor, MRGanglecoplanar, &angle);
+      trace2((qh ferr, 2039, "qh_test_appendmerge: coplanar angle %4.4g between f%d and f%d\n",
+         angle, facet->id, neighbor->id));
+      return True;
+    }else
+      okangle= True;
+  }
+  if (!facet->center)
+    facet->center= qh_getcentrum(facet);
+  zzinc_(Zcentrumtests);
+  qh_distplane(facet->center, neighbor, &dist);
+  if (dist > qh centrum_radius)
+    isconcave= True;
+  else {
+    if (dist > -qh centrum_radius)
+      iscoplanar= True;
+    if (!neighbor->center)
+      neighbor->center= qh_getcentrum(neighbor);
+    zzinc_(Zcentrumtests);
+    qh_distplane(neighbor->center, facet, &dist2);
+    if (dist2 > qh centrum_radius)
+      isconcave= True;
+    else if (!iscoplanar && dist2 > -qh centrum_radius)
+      iscoplanar= True;
+  }
+  if (!isconcave && (!iscoplanar || (qh MERGEexact && !qh POSTmerging)))
+    return False;
+  if (!okangle && qh ANGLEmerge) {
+    angle= qh_getangle(facet->normal, neighbor->normal);
+    zinc_(Zangletests);
+  }
+  if (isconcave) {
+    zinc_(Zconcaveridge);
+    if (qh ANGLEmerge)
+      angle += qh_ANGLEconcave + 0.5;
+    qh_appendmergeset(facet, neighbor, MRGconcave, &angle);
+    trace0((qh ferr, 18, "qh_test_appendmerge: concave f%d to f%d dist %4.4g and reverse dist %4.4g angle %4.4g during p%d\n",
+           facet->id, neighbor->id, dist, dist2, angle, qh furthest_id));
+  }else /* iscoplanar */ {
+    zinc_(Zcoplanarcentrum);
+    qh_appendmergeset(facet, neighbor, MRGcoplanar, &angle);
+    trace2((qh ferr, 2040, "qh_test_appendmerge: coplanar f%d to f%d dist %4.4g, reverse dist %4.4g angle %4.4g\n",
+              facet->id, neighbor->id, dist, dist2, angle));
+  }
+  return True;
+} /* test_appendmerge */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="test_vneighbors">-</a>
+
+  qh_test_vneighbors()
+    test vertex neighbors for convexity
+    tests all facets on qh.newfacet_list
+
+  returns:
+    true if non-convex vneighbors appended to qh.facet_mergeset
+    initializes vertex neighbors if needed
+
+  notes:
+    assumes all facet neighbors have been tested
+    this can be expensive
+    this does not guarantee that a centrum is below all facets
+      but it is unlikely
+    uses qh.visit_id
+
+  design:
+    build vertex neighbors if necessary
+    for all new facets
+      for all vertices
+        for each unvisited facet neighbor of the vertex
+          test new facet and neighbor for convexity
+*/
+boolT qh_test_vneighbors(void /* qh newfacet_list */) {
+  facetT *newfacet, *neighbor, **neighborp;
+  vertexT *vertex, **vertexp;
+  int nummerges= 0;
+
+  trace1((qh ferr, 1015, "qh_test_vneighbors: testing vertex neighbors for convexity\n"));
+  if (!qh VERTEXneighbors)
+    qh_vertexneighbors();
+  FORALLnew_facets
+    newfacet->seen= False;
+  FORALLnew_facets {
+    newfacet->seen= True;
+    newfacet->visitid= qh visit_id++;
+    FOREACHneighbor_(newfacet)
+      newfacet->visitid= qh visit_id;
+    FOREACHvertex_(newfacet->vertices) {
+      FOREACHneighbor_(vertex) {
+        if (neighbor->seen || neighbor->visitid == qh visit_id)
+          continue;
+        if (qh_test_appendmerge(newfacet, neighbor))
+          nummerges++;
+      }
+    }
+  }
+  zadd_(Ztestvneighbor, nummerges);
+  trace1((qh ferr, 1016, "qh_test_vneighbors: found %d non-convex, vertex neighbors\n",
+           nummerges));
+  return (nummerges > 0);
+} /* test_vneighbors */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="tracemerge">-</a>
+
+  qh_tracemerge( facet1, facet2 )
+    print trace message after merge
+*/
+void qh_tracemerge(facetT *facet1, facetT *facet2) {
+  boolT waserror= False;
+
+#ifndef qh_NOtrace
+  if (qh IStracing >= 4)
+    qh_errprint("MERGED", facet2, NULL, NULL, NULL);
+  if (facet2 == qh tracefacet || (qh tracevertex && qh tracevertex->newlist)) {
+    qh_fprintf(qh ferr, 8085, "qh_tracemerge: trace facet and vertex after merge of f%d and f%d, furthest p%d\n", facet1->id, facet2->id, qh furthest_id);
+    if (facet2 != qh tracefacet)
+      qh_errprint("TRACE", qh tracefacet,
+        (qh tracevertex && qh tracevertex->neighbors) ?
+           SETfirstt_(qh tracevertex->neighbors, facetT) : NULL,
+        NULL, qh tracevertex);
+  }
+  if (qh tracevertex) {
+    if (qh tracevertex->deleted)
+      qh_fprintf(qh ferr, 8086, "qh_tracemerge: trace vertex deleted at furthest p%d\n",
+            qh furthest_id);
+    else
+      qh_checkvertex(qh tracevertex);
+  }
+  if (qh tracefacet) {
+    qh_checkfacet(qh tracefacet, True, &waserror);
+    if (waserror)
+      qh_errexit(qh_ERRqhull, qh tracefacet, NULL);
+  }
+#endif /* !qh_NOtrace */
+  if (qh CHECKfrequently || qh IStracing >= 4) { /* can't check polygon here */
+    qh_checkfacet(facet2, True, &waserror);
+    if (waserror)
+      qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+} /* tracemerge */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="tracemerging">-</a>
+
+  qh_tracemerging()
+    print trace message during POSTmerging
+
+  returns:
+    updates qh.mergereport
+
+  notes:
+    called from qh_mergecycle() and qh_mergefacet()
+
+  see:
+    qh_buildtracing()
+*/
+void qh_tracemerging(void) {
+  realT cpu;
+  int total;
+  time_t timedata;
+  struct tm *tp;
+
+  qh mergereport= zzval_(Ztotmerge);
+  time(&timedata);
+  tp= localtime(&timedata);
+  cpu= qh_CPUclock;
+  cpu /= qh_SECticks;
+  total= zzval_(Ztotmerge) - zzval_(Zcyclehorizon) + zzval_(Zcyclefacettot);
+  qh_fprintf(qh ferr, 8087, "\n\
+At %d:%d:%d & %2.5g CPU secs, qhull has merged %d facets.  The hull\n\
+  contains %d facets and %d vertices.\n",
+      tp->tm_hour, tp->tm_min, tp->tm_sec, cpu,
+      total, qh num_facets - qh num_visible,
+      qh num_vertices-qh_setsize(qh del_vertices));
+} /* tracemerging */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="updatetested">-</a>
+
+  qh_updatetested( facet1, facet2 )
+    clear facet2->tested and facet1->ridge->tested for merge
+
+  returns:
+    deletes facet2->center unless it's already large
+      if so, clears facet2->ridge->tested
+
+  design:
+    clear facet2->tested
+    clear ridge->tested for facet1's ridges
+    if facet2 has a centrum
+      if facet2 is large
+        set facet2->keepcentrum
+      else if facet2 has 3 vertices due to many merges, or not large and post merging
+        clear facet2->keepcentrum
+      unless facet2->keepcentrum
+        clear facet2->center to recompute centrum later
+        clear ridge->tested for facet2's ridges
+*/
+void qh_updatetested(facetT *facet1, facetT *facet2) {
+  ridgeT *ridge, **ridgep;
+  int size;
+
+  facet2->tested= False;
+  FOREACHridge_(facet1->ridges)
+    ridge->tested= False;
+  if (!facet2->center)
+    return;
+  size= qh_setsize(facet2->vertices);
+  if (!facet2->keepcentrum) {
+    if (size > qh hull_dim + qh_MAXnewcentrum) {
+      facet2->keepcentrum= True;
+      zinc_(Zwidevertices);
+    }
+  }else if (size <= qh hull_dim + qh_MAXnewcentrum) {
+    /* center and keepcentrum was set */
+    if (size == qh hull_dim || qh POSTmerging)
+      facet2->keepcentrum= False; /* if many merges need to recompute centrum */
+  }
+  if (!facet2->keepcentrum) {
+    qh_memfree(facet2->center, qh normal_size);
+    facet2->center= NULL;
+    FOREACHridge_(facet2->ridges)
+      ridge->tested= False;
+  }
+} /* updatetested */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="vertexridges">-</a>
+
+  qh_vertexridges( vertex )
+    return temporary set of ridges adjacent to a vertex
+    vertex->neighbors defined
+
+  notes:
+    uses qh.visit_id
+    does not include implicit ridges for simplicial facets
+
+  design:
+    for each neighbor of vertex
+      add ridges that include the vertex to ridges
+*/
+setT *qh_vertexridges(vertexT *vertex) {
+  facetT *neighbor, **neighborp;
+  setT *ridges= qh_settemp(qh TEMPsize);
+  int size;
+
+  qh visit_id++;
+  FOREACHneighbor_(vertex)
+    neighbor->visitid= qh visit_id;
+  FOREACHneighbor_(vertex) {
+    if (*neighborp)   /* no new ridges in last neighbor */
+      qh_vertexridges_facet(vertex, neighbor, &ridges);
+  }
+  if (qh PRINTstatistics || qh IStracing) {
+    size= qh_setsize(ridges);
+    zinc_(Zvertexridge);
+    zadd_(Zvertexridgetot, size);
+    zmax_(Zvertexridgemax, size);
+    trace3((qh ferr, 3011, "qh_vertexridges: found %d ridges for v%d\n",
+             size, vertex->id));
+  }
+  return ridges;
+} /* vertexridges */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="vertexridges_facet">-</a>
+
+  qh_vertexridges_facet( vertex, facet, ridges )
+    add adjacent ridges for vertex in facet
+    neighbor->visitid==qh.visit_id if it hasn't been visited
+
+  returns:
+    ridges updated
+    sets facet->visitid to qh.visit_id-1
+
+  design:
+    for each ridge of facet
+      if ridge of visited neighbor (i.e., unprocessed)
+        if vertex in ridge
+          append ridge to vertex
+    mark facet processed
+*/
+void qh_vertexridges_facet(vertexT *vertex, facetT *facet, setT **ridges) {
+  ridgeT *ridge, **ridgep;
+  facetT *neighbor;
+
+  FOREACHridge_(facet->ridges) {
+    neighbor= otherfacet_(ridge, facet);
+    if (neighbor->visitid == qh visit_id
+    && qh_setin(ridge->vertices, vertex))
+      qh_setappend(ridges, ridge);
+  }
+  facet->visitid= qh visit_id-1;
+} /* vertexridges_facet */
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >-------------------------------</a><a name="willdelete">-</a>
+
+  qh_willdelete( facet, replace )
+    moves facet to visible list
+    sets facet->f.replace to replace (may be NULL)
+
+  returns:
+    bumps qh.num_visible
+*/
+void qh_willdelete(facetT *facet, facetT *replace) {
+
+  qh_removefacet(facet);
+  qh_prependfacet(facet, &qh visible_list);
+  qh num_visible++;
+  facet->visible= True;
+  facet->f.replace= replace;
+} /* willdelete */
+
+#else /* qh_NOmerge */
+void qh_premerge(vertexT *apex, realT maxcentrum, realT maxangle) {
+}
+void qh_postmerge(const char *reason, realT maxcentrum, realT maxangle,
+                      boolT vneighbors) {
+}
+boolT qh_checkzero(boolT testall) {
+   }
+#endif /* qh_NOmerge */
+
diff --git a/alg/libqhull/merge.h b/alg/libqhull/merge.h
new file mode 100644
index 0000000..da0fb53
--- /dev/null
+++ b/alg/libqhull/merge.h
@@ -0,0 +1,178 @@
+/*<html><pre>  -<a                             href="qh-merge.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   merge.h
+   header file for merge.c
+
+   see qh-merge.htm and merge.c
+
+   Copyright (c) 1993-2012 C.B. Barber.
+   $Id: //main/2011/qhull/src/libqhull/merge.h#3 $$Change: 1464 $
+   $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+*/
+
+#ifndef qhDEFmerge
+#define qhDEFmerge 1
+
+#include "libqhull.h"
+
+
+/*============ -constants- ==============*/
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >--------------------------------</a><a name="qh_ANGLEredundant">-</a>
+
+  qh_ANGLEredundant
+    indicates redundant merge in mergeT->angle
+*/
+#define qh_ANGLEredundant 6.0
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >--------------------------------</a><a name="qh_ANGLEdegen">-</a>
+
+  qh_ANGLEdegen
+    indicates degenerate facet in mergeT->angle
+*/
+#define qh_ANGLEdegen     5.0
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >--------------------------------</a><a name="qh_ANGLEconcave">-</a>
+
+  qh_ANGLEconcave
+    offset to indicate concave facets in mergeT->angle
+
+  notes:
+    concave facets are assigned the range of [2,4] in mergeT->angle
+    roundoff error may make the angle less than 2
+*/
+#define qh_ANGLEconcave  1.5
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >--------------------------------</a><a name="MRG">-</a>
+
+  MRG... (mergeType)
+    indicates the type of a merge (mergeT->type)
+*/
+typedef enum {  /* in sort order for facet_mergeset */
+  MRGnone= 0,
+  MRGcoplanar,          /* centrum coplanar */
+  MRGanglecoplanar,     /* angle coplanar */
+                        /* could detect half concave ridges */
+  MRGconcave,           /* concave ridge */
+  MRGflip,              /* flipped facet. facet1 == facet2 */
+  MRGridge,             /* duplicate ridge (qh_MERGEridge) */
+                        /* degen and redundant go onto degen_mergeset */
+  MRGdegen,             /* degenerate facet (!enough neighbors) facet1 == facet2 */
+  MRGredundant,         /* redundant facet (vertex subset) */
+                        /* merge_degenredundant assumes degen < redundant */
+  MRGmirror,            /* mirror facet from qh_triangulate */
+  ENDmrg
+} mergeType;
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >--------------------------------</a><a name="qh_MERGEapex">-</a>
+
+  qh_MERGEapex
+    flag for qh_mergefacet() to indicate an apex merge
+*/
+#define qh_MERGEapex     True
+
+/*============ -structures- ====================*/
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >--------------------------------</a><a name="mergeT">-</a>
+
+  mergeT
+    structure used to merge facets
+*/
+
+typedef struct mergeT mergeT;
+struct mergeT {         /* initialize in qh_appendmergeset */
+  realT   angle;        /* angle between normals of facet1 and facet2 */
+  facetT *facet1;       /* will merge facet1 into facet2 */
+  facetT *facet2;
+  mergeType type;
+};
+
+
+/*=========== -macros- =========================*/
+
+/*-<a                             href="qh-merge.htm#TOC"
+  >--------------------------------</a><a name="FOREACHmerge_">-</a>
+
+  FOREACHmerge_( merges ) {...}
+    assign 'merge' to each merge in merges
+
+  notes:
+    uses 'mergeT *merge, **mergep;'
+    if qh_mergefacet(),
+      restart since qh.facet_mergeset may change
+    see <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHmerge_( merges ) FOREACHsetelement_(mergeT, merges, merge)
+
+/*============ prototypes in alphabetical order after pre/postmerge =======*/
+
+void    qh_premerge(vertexT *apex, realT maxcentrum, realT maxangle);
+void    qh_postmerge(const char *reason, realT maxcentrum, realT maxangle,
+             boolT vneighbors);
+void    qh_all_merges(boolT othermerge, boolT vneighbors);
+void    qh_appendmergeset(facetT *facet, facetT *neighbor, mergeType mergetype, realT *angle);
+setT   *qh_basevertices( facetT *samecycle);
+void    qh_checkconnect(void /* qh new_facets */);
+boolT   qh_checkzero(boolT testall);
+int     qh_compareangle(const void *p1, const void *p2);
+int     qh_comparemerge(const void *p1, const void *p2);
+int     qh_comparevisit(const void *p1, const void *p2);
+void    qh_copynonconvex(ridgeT *atridge);
+void    qh_degen_redundant_facet(facetT *facet);
+void    qh_degen_redundant_neighbors(facetT *facet, facetT *delfacet);
+vertexT *qh_find_newvertex(vertexT *oldvertex, setT *vertices, setT *ridges);
+void    qh_findbest_test(boolT testcentrum, facetT *facet, facetT *neighbor,
+           facetT **bestfacet, realT *distp, realT *mindistp, realT *maxdistp);
+facetT *qh_findbestneighbor(facetT *facet, realT *distp, realT *mindistp, realT *maxdistp);
+void    qh_flippedmerges(facetT *facetlist, boolT *wasmerge);
+void    qh_forcedmerges( boolT *wasmerge);
+void    qh_getmergeset(facetT *facetlist);
+void    qh_getmergeset_initial(facetT *facetlist);
+void    qh_hashridge(setT *hashtable, int hashsize, ridgeT *ridge, vertexT *oldvertex);
+ridgeT *qh_hashridge_find(setT *hashtable, int hashsize, ridgeT *ridge,
+              vertexT *vertex, vertexT *oldvertex, int *hashslot);
+void    qh_makeridges(facetT *facet);
+void    qh_mark_dupridges(facetT *facetlist);
+void    qh_maydropneighbor(facetT *facet);
+int     qh_merge_degenredundant(void);
+void    qh_merge_nonconvex( facetT *facet1, facetT *facet2, mergeType mergetype);
+void    qh_mergecycle(facetT *samecycle, facetT *newfacet);
+void    qh_mergecycle_all(facetT *facetlist, boolT *wasmerge);
+void    qh_mergecycle_facets( facetT *samecycle, facetT *newfacet);
+void    qh_mergecycle_neighbors(facetT *samecycle, facetT *newfacet);
+void    qh_mergecycle_ridges(facetT *samecycle, facetT *newfacet);
+void    qh_mergecycle_vneighbors( facetT *samecycle, facetT *newfacet);
+void    qh_mergefacet(facetT *facet1, facetT *facet2, realT *mindist, realT *maxdist, boolT mergeapex);
+void    qh_mergefacet2d(facetT *facet1, facetT *facet2);
+void    qh_mergeneighbors(facetT *facet1, facetT *facet2);
+void    qh_mergeridges(facetT *facet1, facetT *facet2);
+void    qh_mergesimplex(facetT *facet1, facetT *facet2, boolT mergeapex);
+void    qh_mergevertex_del(vertexT *vertex, facetT *facet1, facetT *facet2);
+void    qh_mergevertex_neighbors(facetT *facet1, facetT *facet2);
+void    qh_mergevertices(setT *vertices1, setT **vertices);
+setT   *qh_neighbor_intersections(vertexT *vertex);
+void    qh_newvertices(setT *vertices);
+boolT   qh_reducevertices(void);
+vertexT *qh_redundant_vertex(vertexT *vertex);
+boolT   qh_remove_extravertices(facetT *facet);
+vertexT *qh_rename_sharedvertex(vertexT *vertex, facetT *facet);
+void    qh_renameridgevertex(ridgeT *ridge, vertexT *oldvertex, vertexT *newvertex);
+void    qh_renamevertex(vertexT *oldvertex, vertexT *newvertex, setT *ridges,
+                        facetT *oldfacet, facetT *neighborA);
+boolT   qh_test_appendmerge(facetT *facet, facetT *neighbor);
+boolT   qh_test_vneighbors(void /* qh newfacet_list */);
+void    qh_tracemerge(facetT *facet1, facetT *facet2);
+void    qh_tracemerging(void);
+void    qh_updatetested( facetT *facet1, facetT *facet2);
+setT   *qh_vertexridges(vertexT *vertex);
+void    qh_vertexridges_facet(vertexT *vertex, facetT *facet, setT **ridges);
+void    qh_willdelete(facetT *facet, facetT *replace);
+
+#endif /* qhDEFmerge */
diff --git a/alg/libqhull/poly.c b/alg/libqhull/poly.c
new file mode 100644
index 0000000..93f09a5
--- /dev/null
+++ b/alg/libqhull/poly.c
@@ -0,0 +1,1202 @@
+/*<html><pre>  -<a                             href="qh-poly.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   poly.c
+   implements polygons and simplices
+
+   see qh-poly.htm, poly.h and libqhull.h
+
+   infrequent code is in poly2.c
+   (all but top 50 and their callers 12/3/95)
+
+   Copyright (c) 1993-2012 The Geometry Center.
+   $Id: //main/2011/qhull/src/libqhull/poly.c#5 $$Change: 1464 $
+   $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+*/
+
+#include "qhull_a.h"
+
+/*======== functions in alphabetical order ==========*/
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="appendfacet">-</a>
+
+  qh_appendfacet( facet )
+    appends facet to end of qh.facet_list,
+
+  returns:
+    updates qh.newfacet_list, facet_next, facet_list
+    increments qh.numfacets
+
+  notes:
+    assumes qh.facet_list/facet_tail is defined (createsimplex)
+
+  see:
+    qh_removefacet()
+
+*/
+void qh_appendfacet(facetT *facet) {
+  facetT *tail= qh facet_tail;
+
+  if (tail == qh newfacet_list)
+    qh newfacet_list= facet;
+  if (tail == qh facet_next)
+    qh facet_next= facet;
+  facet->previous= tail->previous;
+  facet->next= tail;
+  if (tail->previous)
+    tail->previous->next= facet;
+  else
+    qh facet_list= facet;
+  tail->previous= facet;
+  qh num_facets++;
+  trace4((qh ferr, 4044, "qh_appendfacet: append f%d to facet_list\n", facet->id));
+} /* appendfacet */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="appendvertex">-</a>
+
+  qh_appendvertex( vertex )
+    appends vertex to end of qh.vertex_list,
+
+  returns:
+    sets vertex->newlist
+    updates qh.vertex_list, newvertex_list
+    increments qh.num_vertices
+
+  notes:
+    assumes qh.vertex_list/vertex_tail is defined (createsimplex)
+
+*/
+void qh_appendvertex(vertexT *vertex) {
+  vertexT *tail= qh vertex_tail;
+
+  if (tail == qh newvertex_list)
+    qh newvertex_list= vertex;
+  vertex->newlist= True;
+  vertex->previous= tail->previous;
+  vertex->next= tail;
+  if (tail->previous)
+    tail->previous->next= vertex;
+  else
+    qh vertex_list= vertex;
+  tail->previous= vertex;
+  qh num_vertices++;
+  trace4((qh ferr, 4045, "qh_appendvertex: append v%d to vertex_list\n", vertex->id));
+} /* appendvertex */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="attachnewfacets">-</a>
+
+  qh_attachnewfacets( )
+    attach horizon facets to new facets in qh.newfacet_list
+    newfacets have neighbor and ridge links to horizon but not vice versa
+    only needed for qh.ONLYgood
+
+  returns:
+    set qh.NEWfacets
+    horizon facets linked to new facets
+      ridges changed from visible facets to new facets
+      simplicial ridges deleted
+    qh.visible_list, no ridges valid
+    facet->f.replace is a newfacet (if any)
+
+  design:
+    delete interior ridges and neighbor sets by
+      for each visible, non-simplicial facet
+        for each ridge
+          if last visit or if neighbor is simplicial
+            if horizon neighbor
+              delete ridge for horizon's ridge set
+            delete ridge
+        erase neighbor set
+    attach horizon facets and new facets by
+      for all new facets
+        if corresponding horizon facet is simplicial
+          locate corresponding visible facet {may be more than one}
+          link visible facet to new facet
+          replace visible facet with new facet in horizon
+        else it's non-simplicial
+          for all visible neighbors of the horizon facet
+            link visible neighbor to new facet
+            delete visible neighbor from horizon facet
+          append new facet to horizon's neighbors
+          the first ridge of the new facet is the horizon ridge
+          link the new facet into the horizon ridge
+*/
+void qh_attachnewfacets(void ) {
+  facetT *newfacet= NULL, *neighbor, **neighborp, *horizon, *visible;
+  ridgeT *ridge, **ridgep;
+
+  qh NEWfacets= True;
+  trace3((qh ferr, 3012, "qh_attachnewfacets: delete interior ridges\n"));
+  qh visit_id++;
+  FORALLvisible_facets {
+    visible->visitid= qh visit_id;
+    if (visible->ridges) {
+      FOREACHridge_(visible->ridges) {
+        neighbor= otherfacet_(ridge, visible);
+        if (neighbor->visitid == qh visit_id
+            || (!neighbor->visible && neighbor->simplicial)) {
+          if (!neighbor->visible)  /* delete ridge for simplicial horizon */
+            qh_setdel(neighbor->ridges, ridge);
+          qh_setfree(&(ridge->vertices)); /* delete on 2nd visit */
+          qh_memfree(ridge, (int)sizeof(ridgeT));
+        }
+      }
+      SETfirst_(visible->ridges)= NULL;
+    }
+    SETfirst_(visible->neighbors)= NULL;
+  }
+  trace1((qh ferr, 1017, "qh_attachnewfacets: attach horizon facets to new facets\n"));
+  FORALLnew_facets {
+    horizon= SETfirstt_(newfacet->neighbors, facetT);
+    if (horizon->simplicial) {
+      visible= NULL;
+      FOREACHneighbor_(horizon) {   /* may have more than one horizon ridge */
+        if (neighbor->visible) {
+          if (visible) {
+            if (qh_setequal_skip(newfacet->vertices, 0, horizon->vertices,
+                                  SETindex_(horizon->neighbors, neighbor))) {
+              visible= neighbor;
+              break;
+            }
+          }else
+            visible= neighbor;
+        }
+      }
+      if (visible) {
+        visible->f.replace= newfacet;
+        qh_setreplace(horizon->neighbors, visible, newfacet);
+      }else {
+        qh_fprintf(qh ferr, 6102, "qhull internal error (qh_attachnewfacets): couldn't find visible facet for horizon f%d of newfacet f%d\n",
+                 horizon->id, newfacet->id);
+        qh_errexit2 (qh_ERRqhull, horizon, newfacet);
+      }
+    }else { /* non-simplicial, with a ridge for newfacet */
+      FOREACHneighbor_(horizon) {    /* may hold for many new facets */
+        if (neighbor->visible) {
+          neighbor->f.replace= newfacet;
+          qh_setdelnth(horizon->neighbors,
+                        SETindex_(horizon->neighbors, neighbor));
+          neighborp--; /* repeat */
+        }
+      }
+      qh_setappend(&horizon->neighbors, newfacet);
+      ridge= SETfirstt_(newfacet->ridges, ridgeT);
+      if (ridge->top == horizon)
+        ridge->bottom= newfacet;
+      else
+        ridge->top= newfacet;
+      }
+  } /* newfacets */
+  if (qh PRINTstatistics) {
+    FORALLvisible_facets {
+      if (!visible->f.replace)
+        zinc_(Zinsidevisible);
+    }
+  }
+} /* attachnewfacets */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="checkflipped">-</a>
+
+  qh_checkflipped( facet, dist, allerror )
+    checks facet orientation to interior point
+
+    if allerror set,
+      tests against qh.DISTround
+    else
+      tests against 0 since tested against DISTround before
+
+  returns:
+    False if it flipped orientation (sets facet->flipped)
+    distance if non-NULL
+*/
+boolT qh_checkflipped(facetT *facet, realT *distp, boolT allerror) {
+  realT dist;
+
+  if (facet->flipped && !distp)
+    return False;
+  zzinc_(Zdistcheck);
+  qh_distplane(qh interior_point, facet, &dist);
+  if (distp)
+    *distp= dist;
+  if ((allerror && dist > -qh DISTround)|| (!allerror && dist >= 0.0)) {
+    facet->flipped= True;
+    zzinc_(Zflippedfacets);
+    trace0((qh ferr, 19, "qh_checkflipped: facet f%d is flipped, distance= %6.12g during p%d\n",
+              facet->id, dist, qh furthest_id));
+    qh_precision("flipped facet");
+    return False;
+  }
+  return True;
+} /* checkflipped */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="delfacet">-</a>
+
+  qh_delfacet( facet )
+    removes facet from facet_list and frees up its memory
+
+  notes:
+    assumes vertices and ridges already freed
+*/
+void qh_delfacet(facetT *facet) {
+  void **freelistp; /* used !qh_NOmem */
+
+  trace4((qh ferr, 4046, "qh_delfacet: delete f%d\n", facet->id));
+  if (facet == qh tracefacet)
+    qh tracefacet= NULL;
+  if (facet == qh GOODclosest)
+    qh GOODclosest= NULL;
+  qh_removefacet(facet);
+  if (!facet->tricoplanar || facet->keepcentrum) {
+    qh_memfree_(facet->normal, qh normal_size, freelistp);
+    if (qh CENTERtype == qh_ASvoronoi) {   /* uses macro calls */
+      qh_memfree_(facet->center, qh center_size, freelistp);
+    }else /* AScentrum */ {
+      qh_memfree_(facet->center, qh normal_size, freelistp);
+    }
+  }
+  qh_setfree(&(facet->neighbors));
+  if (facet->ridges)
+    qh_setfree(&(facet->ridges));
+  qh_setfree(&(facet->vertices));
+  if (facet->outsideset)
+    qh_setfree(&(facet->outsideset));
+  if (facet->coplanarset)
+    qh_setfree(&(facet->coplanarset));
+  qh_memfree_(facet, (int)sizeof(facetT), freelistp);
+} /* delfacet */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="deletevisible">-</a>
+
+  qh_deletevisible()
+    delete visible facets and vertices
+
+  returns:
+    deletes each facet and removes from facetlist
+    at exit, qh.visible_list empty (== qh.newfacet_list)
+
+  notes:
+    ridges already deleted
+    horizon facets do not reference facets on qh.visible_list
+    new facets in qh.newfacet_list
+    uses   qh.visit_id;
+*/
+void qh_deletevisible(void /*qh visible_list*/) {
+  facetT *visible, *nextfacet;
+  vertexT *vertex, **vertexp;
+  int numvisible= 0, numdel= qh_setsize(qh del_vertices);
+
+  trace1((qh ferr, 1018, "qh_deletevisible: delete %d visible facets and %d vertices\n",
+         qh num_visible, numdel));
+  for (visible= qh visible_list; visible && visible->visible;
+                visible= nextfacet) { /* deleting current */
+    nextfacet= visible->next;
+    numvisible++;
+    qh_delfacet(visible);
+  }
+  if (numvisible != qh num_visible) {
+    qh_fprintf(qh ferr, 6103, "qhull internal error (qh_deletevisible): qh num_visible %d is not number of visible facets %d\n",
+             qh num_visible, numvisible);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  qh num_visible= 0;
+  zadd_(Zvisfacettot, numvisible);
+  zmax_(Zvisfacetmax, numvisible);
+  zzadd_(Zdelvertextot, numdel);
+  zmax_(Zdelvertexmax, numdel);
+  FOREACHvertex_(qh del_vertices)
+    qh_delvertex(vertex);
+  qh_settruncate(qh del_vertices, 0);
+} /* deletevisible */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="facetintersect">-</a>
+
+  qh_facetintersect( facetA, facetB, skipa, skipB, prepend )
+    return vertices for intersection of two simplicial facets
+    may include 1 prepended entry (if more, need to settemppush)
+
+  returns:
+    returns set of qh.hull_dim-1 + prepend vertices
+    returns skipped index for each test and checks for exactly one
+
+  notes:
+    does not need settemp since set in quick memory
+
+  see also:
+    qh_vertexintersect and qh_vertexintersect_new
+    use qh_setnew_delnthsorted to get nth ridge (no skip information)
+
+  design:
+    locate skipped vertex by scanning facet A's neighbors
+    locate skipped vertex by scanning facet B's neighbors
+    intersect the vertex sets
+*/
+setT *qh_facetintersect(facetT *facetA, facetT *facetB,
+                         int *skipA,int *skipB, int prepend) {
+  setT *intersect;
+  int dim= qh hull_dim, i, j;
+  facetT **neighborsA, **neighborsB;
+
+  neighborsA= SETaddr_(facetA->neighbors, facetT);
+  neighborsB= SETaddr_(facetB->neighbors, facetT);
+  i= j= 0;
+  if (facetB == *neighborsA++)
+    *skipA= 0;
+  else if (facetB == *neighborsA++)
+    *skipA= 1;
+  else if (facetB == *neighborsA++)
+    *skipA= 2;
+  else {
+    for (i=3; i < dim; i++) {
+      if (facetB == *neighborsA++) {
+        *skipA= i;
+        break;
+      }
+    }
+  }
+  if (facetA == *neighborsB++)
+    *skipB= 0;
+  else if (facetA == *neighborsB++)
+    *skipB= 1;
+  else if (facetA == *neighborsB++)
+    *skipB= 2;
+  else {
+    for (j=3; j < dim; j++) {
+      if (facetA == *neighborsB++) {
+        *skipB= j;
+        break;
+      }
+    }
+  }
+  if (i >= dim || j >= dim) {
+    qh_fprintf(qh ferr, 6104, "qhull internal error (qh_facetintersect): f%d or f%d not in others neighbors\n",
+            facetA->id, facetB->id);
+    qh_errexit2 (qh_ERRqhull, facetA, facetB);
+  }
+  intersect= qh_setnew_delnthsorted(facetA->vertices, qh hull_dim, *skipA, prepend);
+  trace4((qh ferr, 4047, "qh_facetintersect: f%d skip %d matches f%d skip %d\n",
+          facetA->id, *skipA, facetB->id, *skipB));
+  return(intersect);
+} /* facetintersect */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="gethash">-</a>
+
+  qh_gethash( hashsize, set, size, firstindex, skipelem )
+    return hashvalue for a set with firstindex and skipelem
+
+  notes:
+    returned hash is in [0,hashsize)
+    assumes at least firstindex+1 elements
+    assumes skipelem is NULL, in set, or part of hash
+
+    hashes memory addresses which may change over different runs of the same data
+    using sum for hash does badly in high d
+*/
+int qh_gethash(int hashsize, setT *set, int size, int firstindex, void *skipelem) {
+  void **elemp= SETelemaddr_(set, firstindex, void);
+  ptr_intT hash = 0, elem;
+  unsigned result;
+  int i;
+#ifdef _MSC_VER                   /* Microsoft Visual C++ -- warn about 64-bit issues */
+#pragma warning( push)            /* WARN64 -- ptr_intT holds a 64-bit pointer */
+#pragma warning( disable : 4311)  /* 'type cast': pointer truncation from 'void*' to 'ptr_intT' */
+#endif
+
+  switch (size-firstindex) {
+  case 1:
+    hash= (ptr_intT)(*elemp) - (ptr_intT) skipelem;
+    break;
+  case 2:
+    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] - (ptr_intT) skipelem;
+    break;
+  case 3:
+    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
+      - (ptr_intT) skipelem;
+    break;
+  case 4:
+    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
+      + (ptr_intT)elemp[3] - (ptr_intT) skipelem;
+    break;
+  case 5:
+    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
+      + (ptr_intT)elemp[3] + (ptr_intT)elemp[4] - (ptr_intT) skipelem;
+    break;
+  case 6:
+    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
+      + (ptr_intT)elemp[3] + (ptr_intT)elemp[4]+ (ptr_intT)elemp[5]
+      - (ptr_intT) skipelem;
+    break;
+  default:
+    hash= 0;
+    i= 3;
+    do {     /* this is about 10% in 10-d */
+      if ((elem= (ptr_intT)*elemp++) != (ptr_intT)skipelem) {
+        hash ^= (elem << i) + (elem >> (32-i));
+        i += 3;
+        if (i >= 32)
+          i -= 32;
+      }
+    }while (*elemp);
+    break;
+  }
+  if (hashsize<0) {
+    qh_fprintf(qh ferr, 6202, "qhull internal error: negative hashsize %d passed to qh_gethash [poly.c]\n", hashsize);
+    qh_errexit2 (qh_ERRqhull, NULL, NULL);
+  }
+  result= (unsigned)(hash & 0xFFFFFFFFU);
+  result %= (unsigned)hashsize;
+  /* result= 0; for debugging */
+  return result;
+#ifdef _MSC_VER
+#pragma warning( pop)
+#endif
+} /* gethash */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="makenewfacet">-</a>
+
+  qh_makenewfacet( vertices, toporient, horizon )
+    creates a toporient? facet from vertices
+
+  returns:
+    returns newfacet
+      adds newfacet to qh.facet_list
+      newfacet->vertices= vertices
+      if horizon
+        newfacet->neighbor= horizon, but not vice versa
+    newvertex_list updated with vertices
+*/
+facetT *qh_makenewfacet(setT *vertices, boolT toporient,facetT *horizon) {
+  facetT *newfacet;
+  vertexT *vertex, **vertexp;
+
+  FOREACHvertex_(vertices) {
+    if (!vertex->newlist) {
+      qh_removevertex(vertex);
+      qh_appendvertex(vertex);
+    }
+  }
+  newfacet= qh_newfacet();
+  newfacet->vertices= vertices;
+  newfacet->toporient= (unsigned char)toporient;
+  if (horizon)
+    qh_setappend(&(newfacet->neighbors), horizon);
+  qh_appendfacet(newfacet);
+  return(newfacet);
+} /* makenewfacet */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="makenewplanes">-</a>
+
+  qh_makenewplanes()
+    make new hyperplanes for facets on qh.newfacet_list
+
+  returns:
+    all facets have hyperplanes or are marked for   merging
+    doesn't create hyperplane if horizon is coplanar (will merge)
+    updates qh.min_vertex if qh.JOGGLEmax
+
+  notes:
+    facet->f.samecycle is defined for facet->mergehorizon facets
+*/
+void qh_makenewplanes(void /* newfacet_list */) {
+  facetT *newfacet;
+
+  FORALLnew_facets {
+    if (!newfacet->mergehorizon)
+      qh_setfacetplane(newfacet);
+  }
+  if (qh JOGGLEmax < REALmax/2)
+    minimize_(qh min_vertex, -wwval_(Wnewvertexmax));
+} /* makenewplanes */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="makenew_nonsimplicial">-</a>
+
+  qh_makenew_nonsimplicial( visible, apex, numnew )
+    make new facets for ridges of a visible facet
+
+  returns:
+    first newfacet, bumps numnew as needed
+    attaches new facets if !qh.ONLYgood
+    marks ridge neighbors for simplicial visible
+    if (qh.ONLYgood)
+      ridges on newfacet, horizon, and visible
+    else
+      ridge and neighbors between newfacet and   horizon
+      visible facet's ridges are deleted
+
+  notes:
+    qh.visit_id if visible has already been processed
+    sets neighbor->seen for building f.samecycle
+      assumes all 'seen' flags initially false
+
+  design:
+    for each ridge of visible facet
+      get neighbor of visible facet
+      if neighbor was already processed
+        delete the ridge (will delete all visible facets later)
+      if neighbor is a horizon facet
+        create a new facet
+        if neighbor coplanar
+          adds newfacet to f.samecycle for later merging
+        else
+          updates neighbor's neighbor set
+          (checks for non-simplicial facet with multiple ridges to visible facet)
+        updates neighbor's ridge set
+        (checks for simplicial neighbor to non-simplicial visible facet)
+        (deletes ridge if neighbor is simplicial)
+
+*/
+#ifndef qh_NOmerge
+facetT *qh_makenew_nonsimplicial(facetT *visible, vertexT *apex, int *numnew) {
+  void **freelistp; /* used !qh_NOmem */
+  ridgeT *ridge, **ridgep;
+  facetT *neighbor, *newfacet= NULL, *samecycle;
+  setT *vertices;
+  boolT toporient;
+  int ridgeid;
+
+  FOREACHridge_(visible->ridges) {
+    ridgeid= ridge->id;
+    neighbor= otherfacet_(ridge, visible);
+    if (neighbor->visible) {
+      if (!qh ONLYgood) {
+        if (neighbor->visitid == qh visit_id) {
+          qh_setfree(&(ridge->vertices));  /* delete on 2nd visit */
+          qh_memfree_(ridge, (int)sizeof(ridgeT), freelistp);
+        }
+      }
+    }else {  /* neighbor is an horizon facet */
+      toporient= (ridge->top == visible);
+      vertices= qh_setnew(qh hull_dim); /* makes sure this is quick */
+      qh_setappend(&vertices, apex);
+      qh_setappend_set(&vertices, ridge->vertices);
+      newfacet= qh_makenewfacet(vertices, toporient, neighbor);
+      (*numnew)++;
+      if (neighbor->coplanar) {
+        newfacet->mergehorizon= True;
+        if (!neighbor->seen) {
+          newfacet->f.samecycle= newfacet;
+          neighbor->f.newcycle= newfacet;
+        }else {
+          samecycle= neighbor->f.newcycle;
+          newfacet->f.samecycle= samecycle->f.samecycle;
+          samecycle->f.samecycle= newfacet;
+        }
+      }
+      if (qh ONLYgood) {
+        if (!neighbor->simplicial)
+          qh_setappend(&(newfacet->ridges), ridge);
+      }else {  /* qh_attachnewfacets */
+        if (neighbor->seen) {
+          if (neighbor->simplicial) {
+            qh_fprintf(qh ferr, 6105, "qhull internal error (qh_makenew_nonsimplicial): simplicial f%d sharing two ridges with f%d\n",
+                   neighbor->id, visible->id);
+            qh_errexit2 (qh_ERRqhull, neighbor, visible);
+          }
+          qh_setappend(&(neighbor->neighbors), newfacet);
+        }else
+          qh_setreplace(neighbor->neighbors, visible, newfacet);
+        if (neighbor->simplicial) {
+          qh_setdel(neighbor->ridges, ridge);
+          qh_setfree(&(ridge->vertices));
+          qh_memfree(ridge, (int)sizeof(ridgeT));
+        }else {
+          qh_setappend(&(newfacet->ridges), ridge);
+          if (toporient)
+            ridge->top= newfacet;
+          else
+            ridge->bottom= newfacet;
+        }
+      trace4((qh ferr, 4048, "qh_makenew_nonsimplicial: created facet f%d from v%d and r%d of horizon f%d\n",
+            newfacet->id, apex->id, ridgeid, neighbor->id));
+      }
+    }
+    neighbor->seen= True;
+  } /* for each ridge */
+  if (!qh ONLYgood)
+    SETfirst_(visible->ridges)= NULL;
+  return newfacet;
+} /* makenew_nonsimplicial */
+#else /* qh_NOmerge */
+facetT *qh_makenew_nonsimplicial(facetT *visible, vertexT *apex, int *numnew) {
+  return NULL;
+}
+#endif /* qh_NOmerge */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="makenew_simplicial">-</a>
+
+  qh_makenew_simplicial( visible, apex, numnew )
+    make new facets for simplicial visible facet and apex
+
+  returns:
+    attaches new facets if (!qh.ONLYgood)
+      neighbors between newfacet and horizon
+
+  notes:
+    nop if neighbor->seen or neighbor->visible(see qh_makenew_nonsimplicial)
+
+  design:
+    locate neighboring horizon facet for visible facet
+    determine vertices and orientation
+    create new facet
+    if coplanar,
+      add new facet to f.samecycle
+    update horizon facet's neighbor list
+*/
+facetT *qh_makenew_simplicial(facetT *visible, vertexT *apex, int *numnew) {
+  facetT *neighbor, **neighborp, *newfacet= NULL;
+  setT *vertices;
+  boolT flip, toporient;
+  int horizonskip=0, visibleskip;
+
+  FOREACHneighbor_(visible) {
+    if (!neighbor->seen && !neighbor->visible) {
+      vertices= qh_facetintersect(neighbor,visible, &horizonskip, &visibleskip, 1);
+      SETfirst_(vertices)= apex;
+      flip= ((horizonskip & 0x1) ^ (visibleskip & 0x1));
+      if (neighbor->toporient)
+        toporient= horizonskip & 0x1;
+      else
+        toporient= (horizonskip & 0x1) ^ 0x1;
+      newfacet= qh_makenewfacet(vertices, toporient, neighbor);
+      (*numnew)++;
+      if (neighbor->coplanar && (qh PREmerge || qh MERGEexact)) {
+#ifndef qh_NOmerge
+        newfacet->f.samecycle= newfacet;
+        newfacet->mergehorizon= True;
+#endif
+      }
+      if (!qh ONLYgood)
+        SETelem_(neighbor->neighbors, horizonskip)= newfacet;
+      trace4((qh ferr, 4049, "qh_makenew_simplicial: create facet f%d top %d from v%d and horizon f%d skip %d top %d and visible f%d skip %d, flip? %d\n",
+            newfacet->id, toporient, apex->id, neighbor->id, horizonskip,
+              neighbor->toporient, visible->id, visibleskip, flip));
+    }
+  }
+  return newfacet;
+} /* makenew_simplicial */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="matchneighbor">-</a>
+
+  qh_matchneighbor( newfacet, newskip, hashsize, hashcount )
+    either match subridge of newfacet with neighbor or add to hash_table
+
+  returns:
+    duplicate ridges are unmatched and marked by qh_DUPLICATEridge
+
+  notes:
+    ridge is newfacet->vertices w/o newskip vertex
+    do not allocate memory (need to free hash_table cleanly)
+    uses linear hash chains
+
+  see also:
+    qh_matchduplicates
+
+  design:
+    for each possible matching facet in qh.hash_table
+      if vertices match
+        set ismatch, if facets have opposite orientation
+        if ismatch and matching facet doesn't have a match
+          match the facets by updating their neighbor sets
+        else
+          indicate a duplicate ridge
+          set facet hyperplane for later testing
+          add facet to hashtable
+          unless the other facet was already a duplicate ridge
+            mark both facets with a duplicate ridge
+            add other facet (if defined) to hash table
+*/
+void qh_matchneighbor(facetT *newfacet, int newskip, int hashsize, int *hashcount) {
+  boolT newfound= False;   /* True, if new facet is already in hash chain */
+  boolT same, ismatch;
+  int hash, scan;
+  facetT *facet, *matchfacet;
+  int skip, matchskip;
+
+  hash= qh_gethash(hashsize, newfacet->vertices, qh hull_dim, 1,
+                     SETelem_(newfacet->vertices, newskip));
+  trace4((qh ferr, 4050, "qh_matchneighbor: newfacet f%d skip %d hash %d hashcount %d\n",
+          newfacet->id, newskip, hash, *hashcount));
+  zinc_(Zhashlookup);
+  for (scan= hash; (facet= SETelemt_(qh hash_table, scan, facetT));
+       scan= (++scan >= hashsize ? 0 : scan)) {
+    if (facet == newfacet) {
+      newfound= True;
+      continue;
+    }
+    zinc_(Zhashtests);
+    if (qh_matchvertices(1, newfacet->vertices, newskip, facet->vertices, &skip, &same)) {
+      if (SETelem_(newfacet->vertices, newskip) ==
+          SETelem_(facet->vertices, skip)) {
+        qh_precision("two facets with the same vertices");
+        qh_fprintf(qh ferr, 6106, "qhull precision error: Vertex sets are the same for f%d and f%d.  Can not force output.\n",
+          facet->id, newfacet->id);
+        qh_errexit2 (qh_ERRprec, facet, newfacet);
+      }
+      ismatch= (same == (boolT)((newfacet->toporient ^ facet->toporient)));
+      matchfacet= SETelemt_(facet->neighbors, skip, facetT);
+      if (ismatch && !matchfacet) {
+        SETelem_(facet->neighbors, skip)= newfacet;
+        SETelem_(newfacet->neighbors, newskip)= facet;
+        (*hashcount)--;
+        trace4((qh ferr, 4051, "qh_matchneighbor: f%d skip %d matched with new f%d skip %d\n",
+           facet->id, skip, newfacet->id, newskip));
+        return;
+      }
+      if (!qh PREmerge && !qh MERGEexact) {
+        qh_precision("a ridge with more than two neighbors");
+        qh_fprintf(qh ferr, 6107, "qhull precision error: facets f%d, f%d and f%d meet at a ridge with more than 2 neighbors.  Can not continue.\n",
+                 facet->id, newfacet->id, getid_(matchfacet));
+        qh_errexit2 (qh_ERRprec, facet, newfacet);
+      }
+      SETelem_(newfacet->neighbors, newskip)= qh_DUPLICATEridge;
+      newfacet->dupridge= True;
+      if (!newfacet->normal)
+        qh_setfacetplane(newfacet);
+      qh_addhash(newfacet, qh hash_table, hashsize, hash);
+      (*hashcount)++;
+      if (!facet->normal)
+        qh_setfacetplane(facet);
+      if (matchfacet != qh_DUPLICATEridge) {
+        SETelem_(facet->neighbors, skip)= qh_DUPLICATEridge;
+        facet->dupridge= True;
+        if (!facet->normal)
+          qh_setfacetplane(facet);
+        if (matchfacet) {
+          matchskip= qh_setindex(matchfacet->neighbors, facet);
+          if( matchskip >= 0 )
+          {
+            SETelem_(matchfacet->neighbors, matchskip)= qh_DUPLICATEridge;
+          }
+          matchfacet->dupridge= True;
+          if (!matchfacet->normal)
+            qh_setfacetplane(matchfacet);
+          qh_addhash(matchfacet, qh hash_table, hashsize, hash);
+          *hashcount += 2;
+        }
+      }
+      trace4((qh ferr, 4052, "qh_matchneighbor: new f%d skip %d duplicates ridge for f%d skip %d matching f%d ismatch %d at hash %d\n",
+           newfacet->id, newskip, facet->id, skip,
+           (matchfacet == qh_DUPLICATEridge ? -2 : getid_(matchfacet)),
+           ismatch, hash));
+      return; /* end of duplicate ridge */
+    }
+  }
+  if (!newfound)
+    SETelem_(qh hash_table, scan)= newfacet;  /* same as qh_addhash */
+  (*hashcount)++;
+  trace4((qh ferr, 4053, "qh_matchneighbor: no match for f%d skip %d at hash %d\n",
+           newfacet->id, newskip, hash));
+} /* matchneighbor */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="matchnewfacets">-</a>
+
+  qh_matchnewfacets()
+    match newfacets in qh.newfacet_list to their newfacet neighbors
+
+  returns:
+    qh.newfacet_list with full neighbor sets
+      get vertices with nth neighbor by deleting nth vertex
+    if qh.PREmerge/MERGEexact or qh.FORCEoutput
+      sets facet->flippped if flipped normal (also prevents point partitioning)
+    if duplicate ridges and qh.PREmerge/MERGEexact
+      sets facet->dupridge
+      missing neighbor links identifies extra ridges to be merging (qh_MERGEridge)
+
+  notes:
+    newfacets already have neighbor[0] (horizon facet)
+    assumes qh.hash_table is NULL
+    vertex->neighbors has not been updated yet
+    do not allocate memory after qh.hash_table (need to free it cleanly)
+
+  design:
+    delete neighbor sets for all new facets
+    initialize a hash table
+    for all new facets
+      match facet with neighbors
+    if unmatched facets (due to duplicate ridges)
+      for each new facet with a duplicate ridge
+        match it with a facet
+    check for flipped facets
+*/
+void qh_matchnewfacets(void /* qh newfacet_list */) {
+  int numnew=0, hashcount=0, newskip;
+  facetT *newfacet, *neighbor;
+  int dim= qh hull_dim, hashsize, neighbor_i, neighbor_n;
+  setT *neighbors;
+#ifndef qh_NOtrace
+  int facet_i, facet_n, numfree= 0;
+  facetT *facet;
+#endif
+
+  trace1((qh ferr, 1019, "qh_matchnewfacets: match neighbors for new facets.\n"));
+  FORALLnew_facets {
+    numnew++;
+    {  /* inline qh_setzero(newfacet->neighbors, 1, qh hull_dim); */
+      neighbors= newfacet->neighbors;
+      neighbors->e[neighbors->maxsize].i= dim+1; /*may be overwritten*/
+      memset((char *)SETelemaddr_(neighbors, 1, void), 0, dim * SETelemsize);
+    }
+  }
+
+  qh_newhashtable(numnew*(qh hull_dim-1)); /* twice what is normally needed,
+                                     but every ridge could be DUPLICATEridge */
+  hashsize= qh_setsize(qh hash_table);
+  FORALLnew_facets {
+    for (newskip=1; newskip<qh hull_dim; newskip++) /* furthest/horizon already matched */
+    {
+      if( hashsize )
+        qh_matchneighbor(newfacet, newskip, hashsize, &hashcount);
+    }
+#if 0   /* use the following to trap hashcount errors */
+    {
+      int count= 0, k;
+      facetT *facet, *neighbor;
+
+      count= 0;
+      FORALLfacet_(qh newfacet_list) {  /* newfacet already in use */
+        for (k=1; k < qh hull_dim; k++) {
+          neighbor= SETelemt_(facet->neighbors, k, facetT);
+          if (!neighbor || neighbor == qh_DUPLICATEridge)
+            count++;
+        }
+        if (facet == newfacet)
+          break;
+      }
+      if (count != hashcount) {
+        qh_fprintf(qh ferr, 8088, "qh_matchnewfacets: after adding facet %d, hashcount %d != count %d\n",
+                 newfacet->id, hashcount, count);
+        qh_errexit(qh_ERRqhull, newfacet, NULL);
+      }
+    }
+#endif  /* end of trap code */
+  }
+  if (hashcount) {
+    FORALLnew_facets {
+      if (newfacet->dupridge) {
+        FOREACHneighbor_i_(newfacet) {
+          if (neighbor == qh_DUPLICATEridge) {
+            qh_matchduplicates(newfacet, neighbor_i, hashsize, &hashcount);
+                    /* this may report MERGEfacet */
+          }
+        }
+      }
+    }
+  }
+  if (hashcount) {
+    qh_fprintf(qh ferr, 6108, "qhull internal error (qh_matchnewfacets): %d neighbors did not match up\n",
+        hashcount);
+    qh_printhashtable(qh ferr);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+#ifndef qh_NOtrace
+  if (qh IStracing >= 2) {
+    FOREACHfacet_i_(qh hash_table) {
+      if (!facet)
+        numfree++;
+    }
+    qh_fprintf(qh ferr, 8089, "qh_matchnewfacets: %d new facets, %d unused hash entries .  hashsize %d\n",
+             numnew, numfree, qh_setsize(qh hash_table));
+  }
+#endif /* !qh_NOtrace */
+  qh_setfree(&qh hash_table);
+  if (qh PREmerge || qh MERGEexact) {
+    if (qh IStracing >= 4)
+      qh_printfacetlist(qh newfacet_list, NULL, qh_ALL);
+    FORALLnew_facets {
+      if (newfacet->normal)
+        qh_checkflipped(newfacet, NULL, qh_ALL);
+    }
+  }else if (qh FORCEoutput)
+    qh_checkflipped_all(qh newfacet_list);  /* prints warnings for flipped */
+} /* matchnewfacets */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="matchvertices">-</a>
+
+  qh_matchvertices( firstindex, verticesA, skipA, verticesB, skipB, same )
+    tests whether vertices match with a single skip
+    starts match at firstindex since all new facets have a common vertex
+
+  returns:
+    true if matched vertices
+    skip index for each set
+    sets same iff vertices have the same orientation
+
+  notes:
+    assumes skipA is in A and both sets are the same size
+
+  design:
+    set up pointers
+    scan both sets checking for a match
+    test orientation
+*/
+boolT qh_matchvertices(int firstindex, setT *verticesA, int skipA,
+       setT *verticesB, int *skipB, boolT *same) {
+  vertexT **elemAp, **elemBp, **skipBp=NULL, **skipAp;
+
+  elemAp= SETelemaddr_(verticesA, firstindex, vertexT);
+  elemBp= SETelemaddr_(verticesB, firstindex, vertexT);
+  skipAp= SETelemaddr_(verticesA, skipA, vertexT);
+  do if (elemAp != skipAp) {
+    while (*elemAp != *elemBp++) {
+      if (skipBp)
+        return False;
+      skipBp= elemBp;  /* one extra like FOREACH */
+    }
+  }while (*(++elemAp));
+  if (!skipBp)
+    skipBp= ++elemBp;
+  *skipB= SETindex_(verticesB, skipB); /* i.e., skipBp - verticesB */
+  *same= !((skipA & 0x1) ^ (*skipB & 0x1)); /* result is 0 or 1 */
+  trace4((qh ferr, 4054, "qh_matchvertices: matched by skip %d(v%d) and skip %d(v%d) same? %d\n",
+          skipA, (*skipAp)->id, *skipB, (*(skipBp-1))->id, *same));
+  return(True);
+} /* matchvertices */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="newfacet">-</a>
+
+  qh_newfacet()
+    return a new facet
+
+  returns:
+    all fields initialized or cleared   (NULL)
+    preallocates neighbors set
+*/
+facetT *qh_newfacet(void) {
+  facetT *facet;
+  void **freelistp; /* used !qh_NOmem */
+
+  qh_memalloc_((int)sizeof(facetT), freelistp, facet, facetT);
+  memset((char *)facet, (size_t)0, sizeof(facetT));
+  if (qh facet_id == qh tracefacet_id)
+    qh tracefacet= facet;
+  facet->id= qh facet_id++;
+  facet->neighbors= qh_setnew(qh hull_dim);
+#if !qh_COMPUTEfurthest
+  facet->furthestdist= 0.0;
+#endif
+#if qh_MAXoutside
+  if (qh FORCEoutput && qh APPROXhull)
+    facet->maxoutside= qh MINoutside;
+  else
+    facet->maxoutside= qh DISTround;
+#endif
+  facet->simplicial= True;
+  facet->good= True;
+  facet->newfacet= True;
+  trace4((qh ferr, 4055, "qh_newfacet: created facet f%d\n", facet->id));
+  return(facet);
+} /* newfacet */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="newridge">-</a>
+
+  qh_newridge()
+    return a new ridge
+*/
+ridgeT *qh_newridge(void) {
+  ridgeT *ridge;
+  void **freelistp;   /* used !qh_NOmem */
+
+  qh_memalloc_((int)sizeof(ridgeT), freelistp, ridge, ridgeT);
+  memset((char *)ridge, (size_t)0, sizeof(ridgeT));
+  zinc_(Ztotridges);
+  if (qh ridge_id == 0xFFFFFF) {
+    qh_fprintf(qh ferr, 7074, "\
+qhull warning: more than %d ridges.  ID field overflows and two ridges\n\
+may have the same identifier.  Otherwise output ok.\n", 0xFFFFFF);
+  }
+  ridge->id= qh ridge_id++;
+  trace4((qh ferr, 4056, "qh_newridge: created ridge r%d\n", ridge->id));
+  return(ridge);
+} /* newridge */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="pointid">-</a>
+
+  qh_pointid(  )
+    return id for a point,
+    returns -3 if null, -2 if interior, or -1 if not known
+
+  alternative code:
+    unsigned long id;
+    id= ((unsigned long)point - (unsigned long)qh.first_point)/qh.normal_size;
+
+  notes:
+    WARN64 -- id truncated to 32-bits, at most 2G points
+    NOerrors returned (QhullPoint::id)
+    if point not in point array
+      the code does a comparison of unrelated pointers.
+*/
+int qh_pointid(pointT *point) {
+  ptr_intT offset, id;
+
+  if (!point)
+    return -3;
+  else if (point == qh interior_point)
+    return -2;
+  else if (point >= qh first_point
+  && point < qh first_point + qh num_points * qh hull_dim) {
+    offset= (ptr_intT)(point - qh first_point);
+    id= offset / qh hull_dim;
+  }else if ((id= qh_setindex(qh other_points, point)) != -1)
+    id += qh num_points;
+  else
+    return -1;
+  return (int)id;
+} /* pointid */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="removefacet">-</a>
+
+  qh_removefacet( facet )
+    unlinks facet from qh.facet_list,
+
+  returns:
+    updates qh.facet_list .newfacet_list .facet_next visible_list
+    decrements qh.num_facets
+
+  see:
+    qh_appendfacet
+*/
+void qh_removefacet(facetT *facet) {
+  facetT *next= facet->next, *previous= facet->previous;
+
+  if (facet == qh newfacet_list)
+    qh newfacet_list= next;
+  if (facet == qh facet_next)
+    qh facet_next= next;
+  if (facet == qh visible_list)
+    qh visible_list= next;
+  if (previous) {
+    previous->next= next;
+    next->previous= previous;
+  }else {  /* 1st facet in qh facet_list */
+    qh facet_list= next;
+    qh facet_list->previous= NULL;
+  }
+  qh num_facets--;
+  trace4((qh ferr, 4057, "qh_removefacet: remove f%d from facet_list\n", facet->id));
+} /* removefacet */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="removevertex">-</a>
+
+  qh_removevertex( vertex )
+    unlinks vertex from qh.vertex_list,
+
+  returns:
+    updates qh.vertex_list .newvertex_list
+    decrements qh.num_vertices
+*/
+void qh_removevertex(vertexT *vertex) {
+  vertexT *next= vertex->next, *previous= vertex->previous;
+
+  if (vertex == qh newvertex_list)
+    qh newvertex_list= next;
+  if (previous) {
+    previous->next= next;
+    next->previous= previous;
+  }else {  /* 1st vertex in qh vertex_list */
+    qh vertex_list= vertex->next;
+    qh vertex_list->previous= NULL;
+  }
+  qh num_vertices--;
+  trace4((qh ferr, 4058, "qh_removevertex: remove v%d from vertex_list\n", vertex->id));
+} /* removevertex */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="updatevertices">-</a>
+
+  qh_updatevertices()
+    update vertex neighbors and delete interior vertices
+
+  returns:
+    if qh.VERTEXneighbors, updates neighbors for each vertex
+      if qh.newvertex_list,
+         removes visible neighbors  from vertex neighbors
+      if qh.newfacet_list
+         adds new facets to vertex neighbors
+    if qh.visible_list
+       interior vertices added to qh.del_vertices for later partitioning
+
+  design:
+    if qh.VERTEXneighbors
+      deletes references to visible facets from vertex neighbors
+      appends new facets to the neighbor list for each vertex
+      checks all vertices of visible facets
+        removes visible facets from neighbor lists
+        marks unused vertices for deletion
+*/
+void qh_updatevertices(void /*qh newvertex_list, newfacet_list, visible_list*/) {
+  facetT *newfacet= NULL, *neighbor, **neighborp, *visible;
+  vertexT *vertex, **vertexp;
+
+  trace3((qh ferr, 3013, "qh_updatevertices: delete interior vertices and update vertex->neighbors\n"));
+  if (qh VERTEXneighbors) {
+    FORALLvertex_(qh newvertex_list) {
+      FOREACHneighbor_(vertex) {
+        if (neighbor->visible)
+          SETref_(neighbor)= NULL;
+      }
+      qh_setcompact(vertex->neighbors);
+    }
+    FORALLnew_facets {
+      FOREACHvertex_(newfacet->vertices)
+        qh_setappend(&vertex->neighbors, newfacet);
+    }
+    FORALLvisible_facets {
+      FOREACHvertex_(visible->vertices) {
+        if (!vertex->newlist && !vertex->deleted) {
+          FOREACHneighbor_(vertex) { /* this can happen under merging */
+            if (!neighbor->visible)
+              break;
+          }
+          if (neighbor)
+            qh_setdel(vertex->neighbors, visible);
+          else {
+            vertex->deleted= True;
+            qh_setappend(&qh del_vertices, vertex);
+            trace2((qh ferr, 2041, "qh_updatevertices: delete vertex p%d(v%d) in f%d\n",
+                  qh_pointid(vertex->point), vertex->id, visible->id));
+          }
+        }
+      }
+    }
+  }else {  /* !VERTEXneighbors */
+    FORALLvisible_facets {
+      FOREACHvertex_(visible->vertices) {
+        if (!vertex->newlist && !vertex->deleted) {
+          vertex->deleted= True;
+          qh_setappend(&qh del_vertices, vertex);
+          trace2((qh ferr, 2042, "qh_updatevertices: delete vertex p%d(v%d) in f%d\n",
+                  qh_pointid(vertex->point), vertex->id, visible->id));
+        }
+      }
+    }
+  }
+} /* updatevertices */
diff --git a/alg/libqhull/poly.h b/alg/libqhull/poly.h
new file mode 100644
index 0000000..9cf04cf
--- /dev/null
+++ b/alg/libqhull/poly.h
@@ -0,0 +1,295 @@
+/*<html><pre>  -<a                             href="qh-poly.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   poly.h
+   header file for poly.c and poly2.c
+
+   see qh-poly.htm, libqhull.h and poly.c
+
+   Copyright (c) 1993-2012 The Geometry Center.
+   $Id: //main/2011/qhull/src/libqhull/poly.h#3 $$Change: 1464 $
+   $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+*/
+
+#ifndef qhDEFpoly
+#define qhDEFpoly 1
+
+#include "libqhull.h"
+
+/*===============   constants ========================== */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >--------------------------------</a><a name="ALGORITHMfault">-</a>
+
+  ALGORITHMfault
+    use as argument to checkconvex() to report errors during buildhull
+*/
+#define qh_ALGORITHMfault 0
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="DATAfault">-</a>
+
+  DATAfault
+    use as argument to checkconvex() to report errors during initialhull
+*/
+#define qh_DATAfault 1
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="DUPLICATEridge">-</a>
+
+  DUPLICATEridge
+    special value for facet->neighbor to indicate a duplicate ridge
+
+  notes:
+    set by matchneighbor, used by matchmatch and mark_dupridge
+*/
+#define qh_DUPLICATEridge (facetT *)1L
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="MERGEridge">-</a>
+
+  MERGEridge       flag in facet
+    special value for facet->neighbor to indicate a merged ridge
+
+  notes:
+    set by matchneighbor, used by matchmatch and mark_dupridge
+*/
+#define qh_MERGEridge (facetT *)2L
+
+
+/*============ -structures- ====================*/
+
+/*=========== -macros- =========================*/
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FORALLfacet_">-</a>
+
+  FORALLfacet_( facetlist ) { ... }
+    assign 'facet' to each facet in facetlist
+
+  notes:
+    uses 'facetT *facet;'
+    assumes last facet is a sentinel
+
+  see:
+    FORALLfacets
+*/
+#define FORALLfacet_( facetlist ) if (facetlist ) for ( facet=( facetlist ); facet && facet->next; facet= facet->next )
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FORALLnew_facets">-</a>
+
+  FORALLnew_facets { ... }
+    assign 'newfacet' to each facet in qh.newfacet_list
+
+  notes:
+    uses 'facetT *newfacet;'
+    at exit, newfacet==NULL
+*/
+#define FORALLnew_facets for ( newfacet=qh newfacet_list;newfacet && newfacet->next;newfacet=newfacet->next )
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FORALLvertex_">-</a>
+
+  FORALLvertex_( vertexlist ) { ... }
+    assign 'vertex' to each vertex in vertexlist
+
+  notes:
+    uses 'vertexT *vertex;'
+    at exit, vertex==NULL
+*/
+#define FORALLvertex_( vertexlist ) for (vertex=( vertexlist );vertex && vertex->next;vertex= vertex->next )
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FORALLvisible_facets">-</a>
+
+  FORALLvisible_facets { ... }
+    assign 'visible' to each visible facet in qh.visible_list
+
+  notes:
+    uses 'vacetT *visible;'
+    at exit, visible==NULL
+*/
+#define FORALLvisible_facets for (visible=qh visible_list; visible && visible->visible; visible= visible->next)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FORALLsame_">-</a>
+
+  FORALLsame_( newfacet ) { ... }
+    assign 'same' to each facet in newfacet->f.samecycle
+
+  notes:
+    uses 'facetT *same;'
+    stops when it returns to newfacet
+*/
+#define FORALLsame_(newfacet) for (same= newfacet->f.samecycle; same != newfacet; same= same->f.samecycle)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FORALLsame_cycle_">-</a>
+
+  FORALLsame_cycle_( newfacet ) { ... }
+    assign 'same' to each facet in newfacet->f.samecycle
+
+  notes:
+    uses 'facetT *same;'
+    at exit, same == NULL
+*/
+#define FORALLsame_cycle_(newfacet) \
+     for (same= newfacet->f.samecycle; \
+         same; same= (same == newfacet ?  NULL : same->f.samecycle))
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FOREACHneighborA_">-</a>
+
+  FOREACHneighborA_( facet ) { ... }
+    assign 'neighborA' to each neighbor in facet->neighbors
+
+  FOREACHneighborA_( vertex ) { ... }
+    assign 'neighborA' to each neighbor in vertex->neighbors
+
+  declare:
+    facetT *neighborA, **neighborAp;
+
+  see:
+    <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHneighborA_(facet)  FOREACHsetelement_(facetT, facet->neighbors, neighborA)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FOREACHvisible_">-</a>
+
+  FOREACHvisible_( facets ) { ... }
+    assign 'visible' to each facet in facets
+
+  notes:
+    uses 'facetT *facet, *facetp;'
+    see <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHvisible_(facets) FOREACHsetelement_(facetT, facets, visible)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FOREACHnewfacet_">-</a>
+
+  FOREACHnewfacet_( facets ) { ... }
+    assign 'newfacet' to each facet in facets
+
+  notes:
+    uses 'facetT *newfacet, *newfacetp;'
+    see <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHnewfacet_(facets) FOREACHsetelement_(facetT, facets, newfacet)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FOREACHvertexA_">-</a>
+
+  FOREACHvertexA_( vertices ) { ... }
+    assign 'vertexA' to each vertex in vertices
+
+  notes:
+    uses 'vertexT *vertexA, *vertexAp;'
+    see <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHvertexA_(vertices) FOREACHsetelement_(vertexT, vertices, vertexA)
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >--------------------------------</a><a name="FOREACHvertexreverse12_">-</a>
+
+  FOREACHvertexreverse12_( vertices ) { ... }
+    assign 'vertex' to each vertex in vertices
+    reverse order of first two vertices
+
+  notes:
+    uses 'vertexT *vertex, *vertexp;'
+    see <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
+*/
+#define FOREACHvertexreverse12_(vertices) FOREACHsetelementreverse12_(vertexT, vertices, vertex)
+
+
+/*=============== prototypes poly.c in alphabetical order ================*/
+
+void    qh_appendfacet(facetT *facet);
+void    qh_appendvertex(vertexT *vertex);
+void    qh_attachnewfacets(void);
+boolT   qh_checkflipped(facetT *facet, realT *dist, boolT allerror);
+void    qh_delfacet(facetT *facet);
+void    qh_deletevisible(void /*qh visible_list, qh horizon_list*/);
+setT   *qh_facetintersect(facetT *facetA, facetT *facetB, int *skipAp,int *skipBp, int extra);
+int     qh_gethash(int hashsize, setT *set, int size, int firstindex, void *skipelem);
+facetT *qh_makenewfacet(setT *vertices, boolT toporient, facetT *facet);
+void    qh_makenewplanes(void /* newfacet_list */);
+facetT *qh_makenew_nonsimplicial(facetT *visible, vertexT *apex, int *numnew);
+facetT *qh_makenew_simplicial(facetT *visible, vertexT *apex, int *numnew);
+void    qh_matchneighbor(facetT *newfacet, int newskip, int hashsize,
+                          int *hashcount);
+void    qh_matchnewfacets(void);
+boolT   qh_matchvertices(int firstindex, setT *verticesA, int skipA,
+                          setT *verticesB, int *skipB, boolT *same);
+facetT *qh_newfacet(void);
+ridgeT *qh_newridge(void);
+int     qh_pointid(pointT *point);
+void    qh_removefacet(facetT *facet);
+void    qh_removevertex(vertexT *vertex);
+void    qh_updatevertices(void);
+
+
+/*========== -prototypes poly2.c in alphabetical order ===========*/
+
+void    qh_addhash(void* newelem, setT *hashtable, int hashsize, int hash);
+void    qh_check_bestdist(void);
+void    qh_check_maxout(void);
+void    qh_check_output(void);
+void    qh_check_point(pointT *point, facetT *facet, realT *maxoutside, realT *maxdist, facetT **errfacet1, facetT **errfacet2);
+void    qh_check_points(void);
+void    qh_checkconvex(facetT *facetlist, int fault);
+void    qh_checkfacet(facetT *facet, boolT newmerge, boolT *waserrorp);
+void    qh_checkflipped_all(facetT *facetlist);
+void    qh_checkpolygon(facetT *facetlist);
+void    qh_checkvertex(vertexT *vertex);
+void    qh_clearcenters(qh_CENTER type);
+void    qh_createsimplex(setT *vertices);
+void    qh_delridge(ridgeT *ridge);
+void    qh_delvertex(vertexT *vertex);
+setT   *qh_facet3vertex(facetT *facet);
+facetT *qh_findbestfacet(pointT *point, boolT bestoutside,
+           realT *bestdist, boolT *isoutside);
+facetT *qh_findbestlower(facetT *upperfacet, pointT *point, realT *bestdistp, int *numpart);
+facetT *qh_findfacet_all(pointT *point, realT *bestdist, boolT *isoutside,
+                          int *numpart);
+int     qh_findgood(facetT *facetlist, int goodhorizon);
+void    qh_findgood_all(facetT *facetlist);
+void    qh_furthestnext(void /* qh facet_list */);
+void    qh_furthestout(facetT *facet);
+void    qh_infiniteloop(facetT *facet);
+void    qh_initbuild(void);
+void    qh_initialhull(setT *vertices);
+setT   *qh_initialvertices(int dim, setT *maxpoints, pointT *points, int numpoints);
+vertexT *qh_isvertex(pointT *point, setT *vertices);
+vertexT *qh_makenewfacets(pointT *point /*horizon_list, visible_list*/);
+void    qh_matchduplicates(facetT *atfacet, int atskip, int hashsize, int *hashcount);
+void    qh_nearcoplanar(void /* qh.facet_list */);
+vertexT *qh_nearvertex(facetT *facet, pointT *point, realT *bestdistp);
+int     qh_newhashtable(int newsize);
+vertexT *qh_newvertex(pointT *point);
+ridgeT *qh_nextridge3d(ridgeT *atridge, facetT *facet, vertexT **vertexp);
+void    qh_outcoplanar(void /* facet_list */);
+pointT *qh_point(int id);
+void    qh_point_add(setT *set, pointT *point, void *elem);
+setT   *qh_pointfacet(void /*qh facet_list*/);
+setT   *qh_pointvertex(void /*qh facet_list*/);
+void    qh_prependfacet(facetT *facet, facetT **facetlist);
+void    qh_printhashtable(FILE *fp);
+void    qh_printlists(void);
+void    qh_resetlists(boolT stats, boolT resetVisible /*qh newvertex_list newfacet_list visible_list*/);
+void    qh_setvoronoi_all(void);
+void    qh_triangulate(void /*qh facet_list*/);
+void    qh_triangulate_facet(facetT *facetA, vertexT **first_vertex);
+void    qh_triangulate_link(facetT *oldfacetA, facetT *facetA, facetT *oldfacetB, facetT *facetB);
+void    qh_triangulate_mirror(facetT *facetA, facetT *facetB);
+void    qh_triangulate_null(facetT *facetA);
+void    qh_vertexintersect(setT **vertexsetA,setT *vertexsetB);
+setT   *qh_vertexintersect_new(setT *vertexsetA,setT *vertexsetB);
+void    qh_vertexneighbors(void /*qh facet_list*/);
+boolT   qh_vertexsubset(setT *vertexsetA, setT *vertexsetB);
+
+
+#endif /* qhDEFpoly */
diff --git a/alg/libqhull/poly2.c b/alg/libqhull/poly2.c
new file mode 100644
index 0000000..ff9c3bc
--- /dev/null
+++ b/alg/libqhull/poly2.c
@@ -0,0 +1,3156 @@
+/*<html><pre>  -<a                             href="qh-poly.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   poly2.c
+   implements polygons and simplices
+
+   see qh-poly.htm, poly.h and libqhull.h
+
+   frequently used code is in poly.c
+
+   Copyright (c) 1993-2012 The Geometry Center.
+   $Id: //main/2011/qhull/src/libqhull/poly2.c#5 $$Change: 1490 $
+   $DateTime: 2012/02/19 20:27:01 $$Author: bbarber $
+*/
+
+#include "qhull_a.h"
+
+/*======== functions in alphabetical order ==========*/
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="addhash">-</a>
+
+  qh_addhash( newelem, hashtable, hashsize, hash )
+    add newelem to linear hash table at hash if not already there
+*/
+void qh_addhash(void* newelem, setT *hashtable, int hashsize, int hash) {
+  int scan;
+  void *elem;
+
+  for (scan= (int)hash; (elem= SETelem_(hashtable, scan));
+       scan= (++scan >= hashsize ? 0 : scan)) {
+    if (elem == newelem)
+      break;
+  }
+  /* loop terminates because qh_HASHfactor >= 1.1 by qh_initbuffers */
+  if (!elem)
+    SETelem_(hashtable, scan)= newelem;
+} /* addhash */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="check_bestdist">-</a>
+
+  qh_check_bestdist()
+    check that all points are within max_outside of the nearest facet
+    if qh.ONLYgood,
+      ignores !good facets
+
+  see:
+    qh_check_maxout(), qh_outerinner()
+
+  notes:
+    only called from qh_check_points()
+      seldom used since qh.MERGING is almost always set
+    if notverified>0 at end of routine
+      some points were well inside the hull.  If the hull contains
+      a lens-shaped component, these points were not verified.  Use
+      options 'Qi Tv' to verify all points.  (Exhaustive check also verifies)
+
+  design:
+    determine facet for each point (if any)
+    for each point
+      start with the assigned facet or with the first facet
+      find the best facet for the point and check all coplanar facets
+      error if point is outside of facet
+*/
+void qh_check_bestdist(void) {
+  boolT waserror= False, unassigned;
+  facetT *facet, *bestfacet, *errfacet1= NULL, *errfacet2= NULL;
+  facetT *facetlist;
+  realT dist, maxoutside, maxdist= -REALmax;
+  pointT *point;
+  int numpart= 0, facet_i, facet_n, notgood= 0, notverified= 0;
+  setT *facets;
+
+  trace1((qh ferr, 1020, "qh_check_bestdist: check points below nearest facet.  Facet_list f%d\n",
+      qh facet_list->id));
+  maxoutside= qh_maxouter();
+  maxoutside += qh DISTround;
+  /* one more qh.DISTround for check computation */
+  trace1((qh ferr, 1021, "qh_check_bestdist: check that all points are within %2.2g of best facet\n", maxoutside));
+  facets= qh_pointfacet(/*qh facet_list*/);
+  if (!qh_QUICKhelp && qh PRINTprecision)
+    qh_fprintf(qh ferr, 8091, "\n\
+qhull output completed.  Verifying that %d points are\n\
+below %2.2g of the nearest %sfacet.\n",
+             qh_setsize(facets), maxoutside, (qh ONLYgood ?  "good " : ""));
+  FOREACHfacet_i_(facets) {  /* for each point with facet assignment */
+    if (facet)
+      unassigned= False;
+    else {
+      unassigned= True;
+      facet= qh facet_list;
+    }
+    point= qh_point(facet_i);
+    if (point == qh GOODpointp)
+      continue;
+    qh_distplane(point, facet, &dist);
+    numpart++;
+    bestfacet= qh_findbesthorizon(!qh_IScheckmax, point, facet, qh_NOupper, &dist, &numpart);
+    /* occurs after statistics reported */
+    maximize_(maxdist, dist);
+    if (dist > maxoutside) {
+      if (qh ONLYgood && !bestfacet->good
+          && !((bestfacet= qh_findgooddist(point, bestfacet, &dist, &facetlist))
+               && dist > maxoutside))
+        notgood++;
+      else {
+        waserror= True;
+        qh_fprintf(qh ferr, 6109, "qhull precision error: point p%d is outside facet f%d, distance= %6.8g maxoutside= %6.8g\n",
+                facet_i, bestfacet->id, dist, maxoutside);
+        if (errfacet1 != bestfacet) {
+          errfacet2= errfacet1;
+          errfacet1= bestfacet;
+        }
+      }
+    }else if (unassigned && dist < -qh MAXcoplanar)
+      notverified++;
+  }
+  qh_settempfree(&facets);
+  if (notverified && !qh DELAUNAY && !qh_QUICKhelp && qh PRINTprecision)
+    qh_fprintf(qh ferr, 8092, "\n%d points were well inside the hull.  If the hull contains\n\
+a lens-shaped component, these points were not verified.  Use\n\
+options 'Qci Tv' to verify all points.\n", notverified);
+  if (maxdist > qh outside_err) {
+    qh_fprintf(qh ferr, 6110, "qhull precision error (qh_check_bestdist): a coplanar point is %6.2g from convex hull.  The maximum value(qh.outside_err) is %6.2g\n",
+              maxdist, qh outside_err);
+    qh_errexit2 (qh_ERRprec, errfacet1, errfacet2);
+  }else if (waserror && qh outside_err > REALmax/2)
+    qh_errexit2 (qh_ERRprec, errfacet1, errfacet2);
+  /* else if waserror, the error was logged to qh.ferr but does not effect the output */
+  trace0((qh ferr, 20, "qh_check_bestdist: max distance outside %2.2g\n", maxdist));
+} /* check_bestdist */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="check_maxout">-</a>
+
+  qh_check_maxout()
+    updates qh.max_outside by checking all points against bestfacet
+    if qh.ONLYgood, ignores !good facets
+
+  returns:
+    updates facet->maxoutside via qh_findbesthorizon()
+    sets qh.maxoutdone
+    if printing qh.min_vertex (qh_outerinner),
+      it is updated to the current vertices
+    removes inside/coplanar points from coplanarset as needed
+
+  notes:
+    defines coplanar as min_vertex instead of MAXcoplanar
+    may not need to check near-inside points because of qh.MAXcoplanar
+      and qh.KEEPnearinside (before it was -DISTround)
+
+  see also:
+    qh_check_bestdist()
+
+  design:
+    if qh.min_vertex is needed
+      for all neighbors of all vertices
+        test distance from vertex to neighbor
+    determine facet for each point (if any)
+    for each point with an assigned facet
+      find the best facet for the point and check all coplanar facets
+        (updates outer planes)
+    remove near-inside points from coplanar sets
+*/
+#ifndef qh_NOmerge
+void qh_check_maxout(void) {
+  facetT *facet, *bestfacet, *neighbor, **neighborp, *facetlist;
+  realT dist, maxoutside, minvertex, old_maxoutside;
+  pointT *point;
+  int numpart= 0, facet_i, facet_n, notgood= 0;
+  setT *facets, *vertices;
+  vertexT *vertex;
+
+  trace1((qh ferr, 1022, "qh_check_maxout: check and update maxoutside for each facet.\n"));
+  maxoutside= minvertex= 0;
+  if (qh VERTEXneighbors
+  && (qh PRINTsummary || qh KEEPinside || qh KEEPcoplanar
+        || qh TRACElevel || qh PRINTstatistics
+        || qh PRINTout[0] == qh_PRINTsummary || qh PRINTout[0] == qh_PRINTnone)) {
+    trace1((qh ferr, 1023, "qh_check_maxout: determine actual maxoutside and minvertex\n"));
+    vertices= qh_pointvertex(/*qh facet_list*/);
+    FORALLvertices {
+      FOREACHneighbor_(vertex) {
+        zinc_(Zdistvertex);  /* distance also computed by main loop below */
+        qh_distplane(vertex->point, neighbor, &dist);
+        minimize_(minvertex, dist);
+        if (-dist > qh TRACEdist || dist > qh TRACEdist
+        || neighbor == qh tracefacet || vertex == qh tracevertex)
+          qh_fprintf(qh ferr, 8093, "qh_check_maxout: p%d(v%d) is %.2g from f%d\n",
+                    qh_pointid(vertex->point), vertex->id, dist, neighbor->id);
+      }
+    }
+    if (qh MERGING) {
+      wmin_(Wminvertex, qh min_vertex);
+    }
+    qh min_vertex= minvertex;
+    qh_settempfree(&vertices);
+  }
+  facets= qh_pointfacet(/*qh facet_list*/);
+  do {
+    old_maxoutside= fmax_(qh max_outside, maxoutside);
+    FOREACHfacet_i_(facets) {     /* for each point with facet assignment */
+      if (facet) {
+        point= qh_point(facet_i);
+        if (point == qh GOODpointp)
+          continue;
+        zzinc_(Ztotcheck);
+        qh_distplane(point, facet, &dist);
+        numpart++;
+        bestfacet= qh_findbesthorizon(qh_IScheckmax, point, facet, !qh_NOupper, &dist, &numpart);
+        if (bestfacet && dist > maxoutside) {
+          if (qh ONLYgood && !bestfacet->good
+          && !((bestfacet= qh_findgooddist(point, bestfacet, &dist, &facetlist))
+               && dist > maxoutside))
+            notgood++;
+          else
+            maxoutside= dist;
+        }
+        if (dist > qh TRACEdist || (bestfacet && bestfacet == qh tracefacet))
+          qh_fprintf(qh ferr, 8094, "qh_check_maxout: p%d is %.2g above f%d\n",
+                     qh_pointid(point), dist, bestfacet ? bestfacet->id : -1);
+      }
+    }
+  }while
+    (maxoutside > 2*old_maxoutside);
+    /* if qh.maxoutside increases substantially, qh_SEARCHdist is not valid
+          e.g., RBOX 5000 s Z1 G1e-13 t1001200614 | qhull */
+  zzadd_(Zcheckpart, numpart);
+  qh_settempfree(&facets);
+  wval_(Wmaxout)= maxoutside - qh max_outside;
+  wmax_(Wmaxoutside, qh max_outside);
+  qh max_outside= maxoutside;
+  qh_nearcoplanar(/*qh.facet_list*/);
+  qh maxoutdone= True;
+  trace1((qh ferr, 1024, "qh_check_maxout: maxoutside %2.2g, min_vertex %2.2g, outside of not good %d\n",
+       maxoutside, qh min_vertex, notgood));
+} /* check_maxout */
+#else /* qh_NOmerge */
+void qh_check_maxout(void) {
+}
+#endif
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="check_output">-</a>
+
+  qh_check_output()
+    performs the checks at the end of qhull algorithm
+    Maybe called after voronoi output.  Will recompute otherwise centrums are Voronoi centers instead
+*/
+void qh_check_output(void) {
+  int i;
+
+  if (qh STOPcone)
+    return;
+  if (qh VERIFYoutput | qh IStracing | qh CHECKfrequently) {
+    qh_checkpolygon(qh facet_list);
+    qh_checkflipped_all(qh facet_list);
+    qh_checkconvex(qh facet_list, qh_ALGORITHMfault);
+  }else if (!qh MERGING && qh_newstats(qhstat precision, &i)) {
+    qh_checkflipped_all(qh facet_list);
+    qh_checkconvex(qh facet_list, qh_ALGORITHMfault);
+  }
+} /* check_output */
+
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="check_point">-</a>
+
+  qh_check_point( point, facet, maxoutside, maxdist, errfacet1, errfacet2 )
+    check that point is less than maxoutside from facet
+*/
+void qh_check_point(pointT *point, facetT *facet, realT *maxoutside, realT *maxdist, facetT **errfacet1, facetT **errfacet2) {
+  realT dist;
+
+  /* occurs after statistics reported */
+  qh_distplane(point, facet, &dist);
+  if (dist > *maxoutside) {
+    if (*errfacet1 != facet) {
+      *errfacet2= *errfacet1;
+      *errfacet1= facet;
+    }
+    qh_fprintf(qh ferr, 6111, "qhull precision error: point p%d is outside facet f%d, distance= %6.8g maxoutside= %6.8g\n",
+              qh_pointid(point), facet->id, dist, *maxoutside);
+  }
+  maximize_(*maxdist, dist);
+} /* qh_check_point */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="check_points">-</a>
+
+  qh_check_points()
+    checks that all points are inside all facets
+
+  notes:
+    if many points and qh_check_maxout not called (i.e., !qh.MERGING),
+       calls qh_findbesthorizon (seldom done).
+    ignores flipped facets
+    maxoutside includes 2 qh.DISTrounds
+      one qh.DISTround for the computed distances in qh_check_points
+    qh_printafacet and qh_printsummary needs only one qh.DISTround
+    the computation for qh.VERIFYdirect does not account for qh.other_points
+
+  design:
+    if many points
+      use qh_check_bestdist()
+    else
+      for all facets
+        for all points
+          check that point is inside facet
+*/
+void qh_check_points(void) {
+  facetT *facet, *errfacet1= NULL, *errfacet2= NULL;
+  realT total, maxoutside, maxdist= -REALmax;
+  pointT *point, **pointp, *pointtemp;
+  boolT testouter;
+
+  maxoutside= qh_maxouter();
+  maxoutside += qh DISTround;
+  /* one more qh.DISTround for check computation */
+  trace1((qh ferr, 1025, "qh_check_points: check all points below %2.2g of all facet planes\n",
+          maxoutside));
+  if (qh num_good)   /* miss counts other_points and !good facets */
+     total= (float)qh num_good * (float)qh num_points;
+  else
+     total= (float)qh num_facets * (float)qh num_points;
+  if (total >= qh_VERIFYdirect && !qh maxoutdone) {
+    if (!qh_QUICKhelp && qh SKIPcheckmax && qh MERGING)
+      qh_fprintf(qh ferr, 7075, "qhull input warning: merging without checking outer planes('Q5' or 'Po').\n\
+Verify may report that a point is outside of a facet.\n");
+    qh_check_bestdist();
+  }else {
+    if (qh_MAXoutside && qh maxoutdone)
+      testouter= True;
+    else
+      testouter= False;
+    if (!qh_QUICKhelp) {
+      if (qh MERGEexact)
+        qh_fprintf(qh ferr, 7076, "qhull input warning: exact merge ('Qx').  Verify may report that a point\n\
+is outside of a facet.  See qh-optq.htm#Qx\n");
+      else if (qh SKIPcheckmax || qh NOnearinside)
+        qh_fprintf(qh ferr, 7077, "qhull input warning: no outer plane check ('Q5') or no processing of\n\
+near-inside points ('Q8').  Verify may report that a point is outside\n\
+of a facet.\n");
+    }
+    if (qh PRINTprecision) {
+      if (testouter)
+        qh_fprintf(qh ferr, 8098, "\n\
+Output completed.  Verifying that all points are below outer planes of\n\
+all %sfacets.  Will make %2.0f distance computations.\n",
+              (qh ONLYgood ?  "good " : ""), total);
+      else
+        qh_fprintf(qh ferr, 8099, "\n\
+Output completed.  Verifying that all points are below %2.2g of\n\
+all %sfacets.  Will make %2.0f distance computations.\n",
+              maxoutside, (qh ONLYgood ?  "good " : ""), total);
+    }
+    FORALLfacets {
+      if (!facet->good && qh ONLYgood)
+        continue;
+      if (facet->flipped)
+        continue;
+      if (!facet->normal) {
+        qh_fprintf(qh ferr, 7061, "qhull warning (qh_check_points): missing normal for facet f%d\n", facet->id);
+        continue;
+      }
+      if (testouter) {
+#if qh_MAXoutside
+        maxoutside= facet->maxoutside + 2* qh DISTround;
+        /* one DISTround to actual point and another to computed point */
+#endif
+      }
+      FORALLpoints {
+        if (point != qh GOODpointp)
+          qh_check_point(point, facet, &maxoutside, &maxdist, &errfacet1, &errfacet2);
+      }
+      FOREACHpoint_(qh other_points) {
+        if (point != qh GOODpointp)
+          qh_check_point(point, facet, &maxoutside, &maxdist, &errfacet1, &errfacet2);
+      }
+    }
+    if (maxdist > qh outside_err) {
+      qh_fprintf(qh ferr, 6112, "qhull precision error (qh_check_points): a coplanar point is %6.2g from convex hull.  The maximum value(qh.outside_err) is %6.2g\n",
+                maxdist, qh outside_err );
+      qh_errexit2( qh_ERRprec, errfacet1, errfacet2 );
+    }else if (errfacet1 && qh outside_err > REALmax/2)
+        qh_errexit2( qh_ERRprec, errfacet1, errfacet2 );
+    /* else if errfacet1, the error was logged to qh.ferr but does not effect the output */
+    trace0((qh ferr, 21, "qh_check_points: max distance outside %2.2g\n", maxdist));
+  }
+} /* check_points */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="checkconvex">-</a>
+
+  qh_checkconvex( facetlist, fault )
+    check that each ridge in facetlist is convex
+    fault = qh_DATAfault if reporting errors
+          = qh_ALGORITHMfault otherwise
+
+  returns:
+    counts Zconcaveridges and Zcoplanarridges
+    errors if concaveridge or if merging an coplanar ridge
+
+  note:
+    if not merging,
+      tests vertices for neighboring simplicial facets
+    else if ZEROcentrum,
+      tests vertices for neighboring simplicial   facets
+    else
+      tests centrums of neighboring facets
+
+  design:
+    for all facets
+      report flipped facets
+      if ZEROcentrum and simplicial neighbors
+        test vertices for neighboring simplicial facets
+      else
+        test centrum against all neighbors
+*/
+void qh_checkconvex(facetT *facetlist, int fault) {
+  facetT *facet, *neighbor, **neighborp, *errfacet1=NULL, *errfacet2=NULL;
+  vertexT *vertex;
+  realT dist;
+  pointT *centrum;
+  boolT waserror= False, centrum_warning= False, tempcentrum= False, allsimplicial;
+  int neighbor_i;
+
+  trace1((qh ferr, 1026, "qh_checkconvex: check all ridges are convex\n"));
+  if (!qh RERUN) {
+    zzval_(Zconcaveridges)= 0;
+    zzval_(Zcoplanarridges)= 0;
+  }
+  FORALLfacet_(facetlist) {
+    if (facet->flipped) {
+      qh_precision("flipped facet");
+      qh_fprintf(qh ferr, 6113, "qhull precision error: f%d is flipped(interior point is outside)\n",
+               facet->id);
+      errfacet1= facet;
+      waserror= True;
+      continue;
+    }
+    if (qh MERGING && (!qh ZEROcentrum || !facet->simplicial || facet->tricoplanar))
+      allsimplicial= False;
+    else {
+      allsimplicial= True;
+      neighbor_i= 0;
+      FOREACHneighbor_(facet) {
+        vertex= SETelemt_(facet->vertices, neighbor_i++, vertexT);
+        if (!neighbor->simplicial || neighbor->tricoplanar) {
+          allsimplicial= False;
+          continue;
+        }
+        qh_distplane(vertex->point, neighbor, &dist);
+        if (dist > -qh DISTround) {
+          if (fault == qh_DATAfault) {
+            qh_precision("coplanar or concave ridge");
+            qh_fprintf(qh ferr, 6114, "qhull precision error: initial simplex is not convex. Distance=%.2g\n", dist);
+            qh_errexit(qh_ERRsingular, NULL, NULL);
+          }
+          if (dist > qh DISTround) {
+            zzinc_(Zconcaveridges);
+            qh_precision("concave ridge");
+            qh_fprintf(qh ferr, 6115, "qhull precision error: f%d is concave to f%d, since p%d(v%d) is %6.4g above\n",
+              facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist);
+            errfacet1= facet;
+            errfacet2= neighbor;
+            waserror= True;
+          }else if (qh ZEROcentrum) {
+            if (dist > 0) {     /* qh_checkzero checks that dist < - qh DISTround */
+              zzinc_(Zcoplanarridges);
+              qh_precision("coplanar ridge");
+              qh_fprintf(qh ferr, 6116, "qhull precision error: f%d is clearly not convex to f%d, since p%d(v%d) is %6.4g above\n",
+                facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist);
+              errfacet1= facet;
+              errfacet2= neighbor;
+              waserror= True;
+            }
+          }else {
+            zzinc_(Zcoplanarridges);
+            qh_precision("coplanar ridge");
+            trace0((qh ferr, 22, "qhull precision error: f%d may be coplanar to f%d, since p%d(v%d) is within %6.4g during p%d\n",
+              facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist, qh furthest_id));
+          }
+        }
+      }
+    }
+    if (!allsimplicial) {
+      if (qh CENTERtype == qh_AScentrum) {
+        if (!facet->center)
+          facet->center= qh_getcentrum(facet);
+        centrum= facet->center;
+      }else {
+        if (!centrum_warning && (!facet->simplicial || facet->tricoplanar)) {
+           centrum_warning= True;
+           qh_fprintf(qh ferr, 7062, "qhull warning: recomputing centrums for convexity test.  This may lead to false, precision errors.\n");
+        }
+        centrum= qh_getcentrum(facet);
+        tempcentrum= True;
+      }
+      FOREACHneighbor_(facet) {
+        if (qh ZEROcentrum && facet->simplicial && neighbor->simplicial)
+          continue;
+        if (facet->tricoplanar || neighbor->tricoplanar)
+          continue;
+        zzinc_(Zdistconvex);
+        qh_distplane(centrum, neighbor, &dist);
+        if (dist > qh DISTround) {
+          zzinc_(Zconcaveridges);
+          qh_precision("concave ridge");
+          qh_fprintf(qh ferr, 6117, "qhull precision error: f%d is concave to f%d.  Centrum of f%d is %6.4g above f%d\n",
+            facet->id, neighbor->id, facet->id, dist, neighbor->id);
+          errfacet1= facet;
+          errfacet2= neighbor;
+          waserror= True;
+        }else if (dist >= 0.0) {   /* if arithmetic always rounds the same,
+                                     can test against centrum radius instead */
+          zzinc_(Zcoplanarridges);
+          qh_precision("coplanar ridge");
+          qh_fprintf(qh ferr, 6118, "qhull precision error: f%d is coplanar or concave to f%d.  Centrum of f%d is %6.4g above f%d\n",
+            facet->id, neighbor->id, facet->id, dist, neighbor->id);
+          errfacet1= facet;
+          errfacet2= neighbor;
+          waserror= True;
+        }
+      }
+      if (tempcentrum)
+        qh_memfree(centrum, qh normal_size);
+    }
+  }
+  if (waserror && !qh FORCEoutput)
+    qh_errexit2 (qh_ERRprec, errfacet1, errfacet2);
+} /* checkconvex */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="checkfacet">-</a>
+
+  qh_checkfacet( facet, newmerge, waserror )
+    checks for consistency errors in facet
+    newmerge set if from merge.c
+
+  returns:
+    sets waserror if any error occurs
+
+  checks:
+    vertex ids are inverse sorted
+    unless newmerge, at least hull_dim neighbors and vertices (exactly if simplicial)
+    if non-simplicial, at least as many ridges as neighbors
+    neighbors are not duplicated
+    ridges are not duplicated
+    in 3-d, ridges=verticies
+    (qh.hull_dim-1) ridge vertices
+    neighbors are reciprocated
+    ridge neighbors are facet neighbors and a ridge for every neighbor
+    simplicial neighbors match facetintersect
+    vertex intersection matches vertices of common ridges
+    vertex neighbors and facet vertices agree
+    all ridges have distinct vertex sets
+
+  notes:
+    uses neighbor->seen
+
+  design:
+    check sets
+    check vertices
+    check sizes of neighbors and vertices
+    check for qh_MERGEridge and qh_DUPLICATEridge flags
+    check neighbor set
+    check ridge set
+    check ridges, neighbors, and vertices
+*/
+void qh_checkfacet(facetT *facet, boolT newmerge, boolT *waserrorp) {
+  facetT *neighbor, **neighborp, *errother=NULL;
+  ridgeT *ridge, **ridgep, *errridge= NULL, *ridge2;
+  vertexT *vertex, **vertexp;
+  unsigned previousid= INT_MAX;
+  int numneighbors, numvertices, numridges=0, numRvertices=0;
+  boolT waserror= False;
+  int skipA, skipB, ridge_i, ridge_n, i;
+  setT *intersection;
+
+  if (facet->visible) {
+    qh_fprintf(qh ferr, 6119, "qhull internal error (qh_checkfacet): facet f%d is on the visible_list\n",
+      facet->id);
+    qh_errexit(qh_ERRqhull, facet, NULL);
+  }
+  if (!facet->normal) {
+    qh_fprintf(qh ferr, 6120, "qhull internal error (qh_checkfacet): facet f%d does not have  a normal\n",
+      facet->id);
+    waserror= True;
+  }
+  qh_setcheck(facet->vertices, "vertices for f", facet->id);
+  qh_setcheck(facet->ridges, "ridges for f", facet->id);
+  qh_setcheck(facet->outsideset, "outsideset for f", facet->id);
+  qh_setcheck(facet->coplanarset, "coplanarset for f", facet->id);
+  qh_setcheck(facet->neighbors, "neighbors for f", facet->id);
+  FOREACHvertex_(facet->vertices) {
+    if (vertex->deleted) {
+      qh_fprintf(qh ferr, 6121, "qhull internal error (qh_checkfacet): deleted vertex v%d in f%d\n", vertex->id, facet->id);
+      qh_errprint("ERRONEOUS", NULL, NULL, NULL, vertex);
+      waserror= True;
+    }
+    if (vertex->id >= previousid) {
+      qh_fprintf(qh ferr, 6122, "qhull internal error (qh_checkfacet): vertices of f%d are not in descending id order at v%d\n", facet->id, vertex->id);
+      waserror= True;
+      break;
+    }
+    previousid= vertex->id;
+  }
+  numneighbors= qh_setsize(facet->neighbors);
+  numvertices= qh_setsize(facet->vertices);
+  numridges= qh_setsize(facet->ridges);
+  if (facet->simplicial) {
+    if (numvertices+numneighbors != 2*qh hull_dim
+    && !facet->degenerate && !facet->redundant) {
+      qh_fprintf(qh ferr, 6123, "qhull internal error (qh_checkfacet): for simplicial facet f%d, #vertices %d + #neighbors %d != 2*qh hull_dim\n",
+                facet->id, numvertices, numneighbors);
+      qh_setprint(qh ferr, "", facet->neighbors);
+      waserror= True;
+    }
+  }else { /* non-simplicial */
+    if (!newmerge
+    &&(numvertices < qh hull_dim || numneighbors < qh hull_dim)
+    && !facet->degenerate && !facet->redundant) {
+      qh_fprintf(qh ferr, 6124, "qhull internal error (qh_checkfacet): for facet f%d, #vertices %d or #neighbors %d < qh hull_dim\n",
+         facet->id, numvertices, numneighbors);
+       waserror= True;
+    }
+    /* in 3-d, can get a vertex twice in an edge list, e.g., RBOX 1000 s W1e-13 t995849315 D2 | QHULL d Tc Tv TP624 TW1e-13 T4 */
+    if (numridges < numneighbors
+    ||(qh hull_dim == 3 && numvertices > numridges && !qh NEWfacets)
+    ||(qh hull_dim == 2 && numridges + numvertices + numneighbors != 6)) {
+      if (!facet->degenerate && !facet->redundant) {
+        qh_fprintf(qh ferr, 6125, "qhull internal error (qh_checkfacet): for facet f%d, #ridges %d < #neighbors %d or(3-d) > #vertices %d or(2-d) not all 2\n",
+            facet->id, numridges, numneighbors, numvertices);
+        waserror= True;
+      }
+    }
+  }
+  FOREACHneighbor_(facet) {
+    if (neighbor == qh_MERGEridge || neighbor == qh_DUPLICATEridge) {
+      qh_fprintf(qh ferr, 6126, "qhull internal error (qh_checkfacet): facet f%d still has a MERGE or DUP neighbor\n", facet->id);
+      qh_errexit(qh_ERRqhull, facet, NULL);
+    }
+    neighbor->seen= True;
+  }
+  FOREACHneighbor_(facet) {
+    if (!qh_setin(neighbor->neighbors, facet)) {
+      qh_fprintf(qh ferr, 6127, "qhull internal error (qh_checkfacet): facet f%d has neighbor f%d, but f%d does not have neighbor f%d\n",
+              facet->id, neighbor->id, neighbor->id, facet->id);
+      errother= neighbor;
+      waserror= True;
+    }
+    if (!neighbor->seen) {
+      qh_fprintf(qh ferr, 6128, "qhull internal error (qh_checkfacet): facet f%d has a duplicate neighbor f%d\n",
+              facet->id, neighbor->id);
+      errother= neighbor;
+      waserror= True;
+    }
+    neighbor->seen= False;
+  }
+  FOREACHridge_(facet->ridges) {
+    qh_setcheck(ridge->vertices, "vertices for r", ridge->id);
+    ridge->seen= False;
+  }
+  FOREACHridge_(facet->ridges) {
+    if (ridge->seen) {
+      qh_fprintf(qh ferr, 6129, "qhull internal error (qh_checkfacet): facet f%d has a duplicate ridge r%d\n",
+              facet->id, ridge->id);
+      errridge= ridge;
+      waserror= True;
+    }
+    ridge->seen= True;
+    numRvertices= qh_setsize(ridge->vertices);
+    if (numRvertices != qh hull_dim - 1) {
+      qh_fprintf(qh ferr, 6130, "qhull internal error (qh_checkfacet): ridge between f%d and f%d has %d vertices\n",
+                ridge->top->id, ridge->bottom->id, numRvertices);
+      errridge= ridge;
+      waserror= True;
+    }
+    neighbor= otherfacet_(ridge, facet);
+    neighbor->seen= True;
+    if (!qh_setin(facet->neighbors, neighbor)) {
+      qh_fprintf(qh ferr, 6131, "qhull internal error (qh_checkfacet): for facet f%d, neighbor f%d of ridge r%d not in facet\n",
+           facet->id, neighbor->id, ridge->id);
+      errridge= ridge;
+      waserror= True;
+    }
+  }
+  if (!facet->simplicial) {
+    FOREACHneighbor_(facet) {
+      if (!neighbor->seen) {
+        qh_fprintf(qh ferr, 6132, "qhull internal error (qh_checkfacet): facet f%d does not have a ridge for neighbor f%d\n",
+              facet->id, neighbor->id);
+        errother= neighbor;
+        waserror= True;
+      }
+      intersection= qh_vertexintersect_new(facet->vertices, neighbor->vertices);
+      qh_settemppush(intersection);
+      FOREACHvertex_(facet->vertices) {
+        vertex->seen= False;
+        vertex->seen2= False;
+      }
+      FOREACHvertex_(intersection)
+        vertex->seen= True;
+      FOREACHridge_(facet->ridges) {
+        if (neighbor != otherfacet_(ridge, facet))
+            continue;
+        FOREACHvertex_(ridge->vertices) {
+          if (!vertex->seen) {
+            qh_fprintf(qh ferr, 6133, "qhull internal error (qh_checkfacet): vertex v%d in r%d not in f%d intersect f%d\n",
+                  vertex->id, ridge->id, facet->id, neighbor->id);
+            qh_errexit(qh_ERRqhull, facet, ridge);
+          }
+          vertex->seen2= True;
+        }
+      }
+      if (!newmerge) {
+        FOREACHvertex_(intersection) {
+          if (!vertex->seen2) {
+            if (qh IStracing >=3 || !qh MERGING) {
+              qh_fprintf(qh ferr, 6134, "qhull precision error (qh_checkfacet): vertex v%d in f%d intersect f%d but\n\
+ not in a ridge.  This is ok under merging.  Last point was p%d\n",
+                     vertex->id, facet->id, neighbor->id, qh furthest_id);
+              if (!qh FORCEoutput && !qh MERGING) {
+                qh_errprint("ERRONEOUS", facet, neighbor, NULL, vertex);
+                if (!qh MERGING)
+                  qh_errexit(qh_ERRqhull, NULL, NULL);
+              }
+            }
+          }
+        }
+      }
+      qh_settempfree(&intersection);
+    }
+  }else { /* simplicial */
+    FOREACHneighbor_(facet) {
+      if (neighbor->simplicial) {
+        skipA= SETindex_(facet->neighbors, neighbor);
+        skipB= qh_setindex(neighbor->neighbors, facet);
+        if (skipB >= 0 && !qh_setequal_skip(facet->vertices, skipA, neighbor->vertices, skipB)) {
+          qh_fprintf(qh ferr, 6135, "qhull internal error (qh_checkfacet): facet f%d skip %d and neighbor f%d skip %d do not match \n",
+                   facet->id, skipA, neighbor->id, skipB);
+          errother= neighbor;
+          waserror= True;
+        }
+      }
+    }
+  }
+  if (qh hull_dim < 5 && (qh IStracing > 2 || qh CHECKfrequently)) {
+    FOREACHridge_i_(facet->ridges) {           /* expensive */
+      for (i=ridge_i+1; i < ridge_n; i++) {
+        ridge2= SETelemt_(facet->ridges, i, ridgeT);
+        if (qh_setequal(ridge->vertices, ridge2->vertices)) {
+          qh_fprintf(qh ferr, 6227, "Qhull internal error (qh_checkfacet): ridges r%d and r%d have the same vertices\n",
+                  ridge->id, ridge2->id);
+          errridge= ridge;
+          waserror= True;
+        }
+      }
+    }
+  }
+  if (waserror) {
+    qh_errprint("ERRONEOUS", facet, errother, errridge, NULL);
+    *waserrorp= True;
+  }
+} /* checkfacet */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="checkflipped_all">-</a>
+
+  qh_checkflipped_all( facetlist )
+    checks orientation of facets in list against interior point
+*/
+void qh_checkflipped_all(facetT *facetlist) {
+  facetT *facet;
+  boolT waserror= False;
+  realT dist;
+
+  if (facetlist == qh facet_list)
+    zzval_(Zflippedfacets)= 0;
+  FORALLfacet_(facetlist) {
+    if (facet->normal && !qh_checkflipped(facet, &dist, !qh_ALL)) {
+      qh_fprintf(qh ferr, 6136, "qhull precision error: facet f%d is flipped, distance= %6.12g\n",
+              facet->id, dist);
+      if (!qh FORCEoutput) {
+        qh_errprint("ERRONEOUS", facet, NULL, NULL, NULL);
+        waserror= True;
+      }
+    }
+  }
+  if (waserror) {
+    qh_fprintf(qh ferr, 8101, "\n\
+A flipped facet occurs when its distance to the interior point is\n\
+greater than %2.2g, the maximum roundoff error.\n", -qh DISTround);
+    qh_errexit(qh_ERRprec, NULL, NULL);
+  }
+} /* checkflipped_all */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="checkpolygon">-</a>
+
+  qh_checkpolygon( facetlist )
+    checks the correctness of the structure
+
+  notes:
+    call with either qh.facet_list or qh.newfacet_list
+    checks num_facets and num_vertices if qh.facet_list
+
+  design:
+    for each facet
+      checks facet and outside set
+    initializes vertexlist
+    for each facet
+      checks vertex set
+    if checking all facets(qh.facetlist)
+      check facet count
+      if qh.VERTEXneighbors
+        check vertex neighbors and count
+      check vertex count
+*/
+void qh_checkpolygon(facetT *facetlist) {
+  facetT *facet;
+  vertexT *vertex, **vertexp, *vertexlist;
+  int numfacets= 0, numvertices= 0, numridges= 0;
+  int totvneighbors= 0, totvertices= 0;
+  boolT waserror= False, nextseen= False, visibleseen= False;
+
+  trace1((qh ferr, 1027, "qh_checkpolygon: check all facets from f%d\n", facetlist->id));
+  if (facetlist != qh facet_list || qh ONLYgood)
+    nextseen= True;
+  FORALLfacet_(facetlist) {
+    if (facet == qh visible_list)
+      visibleseen= True;
+    if (!facet->visible) {
+      if (!nextseen) {
+        if (facet == qh facet_next)
+          nextseen= True;
+        else if (qh_setsize(facet->outsideset)) {
+          if (!qh NARROWhull
+#if !qh_COMPUTEfurthest
+               || facet->furthestdist >= qh MINoutside
+#endif
+                        ) {
+            qh_fprintf(qh ferr, 6137, "qhull internal error (qh_checkpolygon): f%d has outside points before qh facet_next\n",
+                     facet->id);
+            qh_errexit(qh_ERRqhull, facet, NULL);
+          }
+        }
+      }
+      numfacets++;
+      qh_checkfacet(facet, False, &waserror);
+    }
+  }
+  if (qh visible_list && !visibleseen && facetlist == qh facet_list) {
+    qh_fprintf(qh ferr, 6138, "qhull internal error (qh_checkpolygon): visible list f%d no longer on facet list\n", qh visible_list->id);
+    qh_printlists();
+    qh_errexit(qh_ERRqhull, qh visible_list, NULL);
+  }
+  if (facetlist == qh facet_list)
+    vertexlist= qh vertex_list;
+  else if (facetlist == qh newfacet_list)
+    vertexlist= qh newvertex_list;
+  else
+    vertexlist= NULL;
+  FORALLvertex_(vertexlist) {
+    vertex->seen= False;
+    vertex->visitid= 0;
+  }
+  FORALLfacet_(facetlist) {
+    if (facet->visible)
+      continue;
+    if (facet->simplicial)
+      numridges += qh hull_dim;
+    else
+      numridges += qh_setsize(facet->ridges);
+    FOREACHvertex_(facet->vertices) {
+      vertex->visitid++;
+      if (!vertex->seen) {
+        vertex->seen= True;
+        numvertices++;
+        if (qh_pointid(vertex->point) == -1) {
+          qh_fprintf(qh ferr, 6139, "qhull internal error (qh_checkpolygon): unknown point %p for vertex v%d first_point %p\n",
+                   vertex->point, vertex->id, qh first_point);
+          waserror= True;
+        }
+      }
+    }
+  }
+  qh vertex_visit += (unsigned int)numfacets;
+  if (facetlist == qh facet_list) {
+    if (numfacets != qh num_facets - qh num_visible) {
+      qh_fprintf(qh ferr, 6140, "qhull internal error (qh_checkpolygon): actual number of facets is %d, cumulative facet count is %d - %d visible facets\n",
+              numfacets, qh num_facets, qh num_visible);
+      waserror= True;
+    }
+    qh vertex_visit++;
+    if (qh VERTEXneighbors) {
+      FORALLvertices {
+        qh_setcheck(vertex->neighbors, "neighbors for v", vertex->id);
+        if (vertex->deleted)
+          continue;
+        totvneighbors += qh_setsize(vertex->neighbors);
+      }
+      FORALLfacet_(facetlist)
+        totvertices += qh_setsize(facet->vertices);
+      if (totvneighbors != totvertices) {
+        qh_fprintf(qh ferr, 6141, "qhull internal error (qh_checkpolygon): vertex neighbors inconsistent.  Totvneighbors %d, totvertices %d\n",
+                totvneighbors, totvertices);
+        waserror= True;
+      }
+    }
+    if (numvertices != qh num_vertices - qh_setsize(qh del_vertices)) {
+      qh_fprintf(qh ferr, 6142, "qhull internal error (qh_checkpolygon): actual number of vertices is %d, cumulative vertex count is %d\n",
+              numvertices, qh num_vertices - qh_setsize(qh del_vertices));
+      waserror= True;
+    }
+    if (qh hull_dim == 2 && numvertices != numfacets) {
+      qh_fprintf(qh ferr, 6143, "qhull internal error (qh_checkpolygon): #vertices %d != #facets %d\n",
+        numvertices, numfacets);
+      waserror= True;
+    }
+    if (qh hull_dim == 3 && numvertices + numfacets - numridges/2 != 2) {
+      qh_fprintf(qh ferr, 7063, "qhull warning: #vertices %d + #facets %d - #edges %d != 2\n\
+        A vertex appears twice in a edge list.  May occur during merging.",
+        numvertices, numfacets, numridges/2);
+      /* occurs if lots of merging and a vertex ends up twice in an edge list.  e.g., RBOX 1000 s W1e-13 t995849315 D2 | QHULL d Tc Tv */
+    }
+  }
+  if (waserror)
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+} /* checkpolygon */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="checkvertex">-</a>
+
+  qh_checkvertex( vertex )
+    check vertex for consistency
+    checks vertex->neighbors
+
+  notes:
+    neighbors checked efficiently in checkpolygon
+*/
+void qh_checkvertex(vertexT *vertex) {
+  boolT waserror= False;
+  facetT *neighbor, **neighborp, *errfacet=NULL;
+
+  if (qh_pointid(vertex->point) == -1) {
+    qh_fprintf(qh ferr, 6144, "qhull internal error (qh_checkvertex): unknown point id %p\n", vertex->point);
+    waserror= True;
+  }
+  if (vertex->id >= qh vertex_id) {
+    qh_fprintf(qh ferr, 6145, "qhull internal error (qh_checkvertex): unknown vertex id %d\n", vertex->id);
+    waserror= True;
+  }
+  if (!waserror && !vertex->deleted) {
+    if (qh_setsize(vertex->neighbors)) {
+      FOREACHneighbor_(vertex) {
+        if (!qh_setin(neighbor->vertices, vertex)) {
+          qh_fprintf(qh ferr, 6146, "qhull internal error (qh_checkvertex): neighbor f%d does not contain v%d\n", neighbor->id, vertex->id);
+          errfacet= neighbor;
+          waserror= True;
+        }
+      }
+    }
+  }
+  if (waserror) {
+    qh_errprint("ERRONEOUS", NULL, NULL, NULL, vertex);
+    qh_errexit(qh_ERRqhull, errfacet, NULL);
+  }
+} /* checkvertex */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="clearcenters">-</a>
+
+  qh_clearcenters( type )
+    clear old data from facet->center
+
+  notes:
+    sets new centertype
+    nop if CENTERtype is the same
+*/
+void qh_clearcenters(qh_CENTER type) {
+  facetT *facet;
+
+  if (qh CENTERtype != type) {
+    FORALLfacets {
+      if (facet->tricoplanar && !facet->keepcentrum)
+          facet->center= NULL;
+      else if (qh CENTERtype == qh_ASvoronoi){
+        if (facet->center) {
+          qh_memfree(facet->center, qh center_size);
+          facet->center= NULL;
+        }
+      }else /* qh CENTERtype == qh_AScentrum */ {
+        if (facet->center) {
+          qh_memfree(facet->center, qh normal_size);
+          facet->center= NULL;
+        }
+      }
+    }
+    qh CENTERtype= type;
+  }
+  trace2((qh ferr, 2043, "qh_clearcenters: switched to center type %d\n", type));
+} /* clearcenters */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="createsimplex">-</a>
+
+  qh_createsimplex( vertices )
+    creates a simplex from a set of vertices
+
+  returns:
+    initializes qh.facet_list to the simplex
+    initializes qh.newfacet_list, .facet_tail
+    initializes qh.vertex_list, .newvertex_list, .vertex_tail
+
+  design:
+    initializes lists
+    for each vertex
+      create a new facet
+    for each new facet
+      create its neighbor set
+*/
+void qh_createsimplex(setT *vertices) {
+  facetT *facet= NULL, *newfacet;
+  boolT toporient= True;
+  int vertex_i, vertex_n, nth;
+  setT *newfacets= qh_settemp(qh hull_dim+1);
+  vertexT *vertex;
+
+  qh facet_list= qh newfacet_list= qh facet_tail= qh_newfacet();
+  qh num_facets= qh num_vertices= qh num_visible= 0;
+  qh vertex_list= qh newvertex_list= qh vertex_tail= qh_newvertex(NULL);
+  FOREACHvertex_i_(vertices) {
+    newfacet= qh_newfacet();
+    newfacet->vertices= qh_setnew_delnthsorted(vertices, vertex_n,
+                                                vertex_i, 0);
+    newfacet->toporient= (unsigned char)toporient;
+    qh_appendfacet(newfacet);
+    newfacet->newfacet= True;
+    qh_appendvertex(vertex);
+    qh_setappend(&newfacets, newfacet);
+    toporient ^= True;
+  }
+  FORALLnew_facets {
+    nth= 0;
+    FORALLfacet_(qh newfacet_list) {
+      if (facet != newfacet)
+        SETelem_(newfacet->neighbors, nth++)= facet;
+    }
+    qh_settruncate(newfacet->neighbors, qh hull_dim);
+  }
+  qh_settempfree(&newfacets);
+  trace1((qh ferr, 1028, "qh_createsimplex: created simplex\n"));
+} /* createsimplex */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="delridge">-</a>
+
+  qh_delridge( ridge )
+    deletes ridge from data structures it belongs to
+    frees up its memory
+
+  notes:
+    in merge.c, caller sets vertex->delridge for each vertex
+    ridges also freed in qh_freeqhull
+*/
+void qh_delridge(ridgeT *ridge) {
+  void **freelistp; /* used !qh_NOmem */
+
+  qh_setdel(ridge->top->ridges, ridge);
+  qh_setdel(ridge->bottom->ridges, ridge);
+  qh_setfree(&(ridge->vertices));
+  qh_memfree_(ridge, (int)sizeof(ridgeT), freelistp);
+} /* delridge */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="delvertex">-</a>
+
+  qh_delvertex( vertex )
+    deletes a vertex and frees its memory
+
+  notes:
+    assumes vertex->adjacencies have been updated if needed
+    unlinks from vertex_list
+*/
+void qh_delvertex(vertexT *vertex) {
+
+  if (vertex == qh tracevertex)
+    qh tracevertex= NULL;
+  qh_removevertex(vertex);
+  qh_setfree(&vertex->neighbors);
+  qh_memfree(vertex, (int)sizeof(vertexT));
+} /* delvertex */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="facet3vertex">-</a>
+
+  qh_facet3vertex(  )
+    return temporary set of 3-d vertices in qh_ORIENTclock order
+
+  design:
+    if simplicial facet
+      build set from facet->vertices with facet->toporient
+    else
+      for each ridge in order
+        build set from ridge's vertices
+*/
+setT *qh_facet3vertex(facetT *facet) {
+  ridgeT *ridge, *firstridge;
+  vertexT *vertex;
+  int cntvertices, cntprojected=0;
+  setT *vertices;
+
+  cntvertices= qh_setsize(facet->vertices);
+  vertices= qh_settemp(cntvertices);
+  if (facet->simplicial) {
+    if (cntvertices != 3) {
+      qh_fprintf(qh ferr, 6147, "qhull internal error (qh_facet3vertex): only %d vertices for simplicial facet f%d\n",
+                  cntvertices, facet->id);
+      qh_errexit(qh_ERRqhull, facet, NULL);
+    }
+    qh_setappend(&vertices, SETfirst_(facet->vertices));
+    if (facet->toporient ^ qh_ORIENTclock)
+      qh_setappend(&vertices, SETsecond_(facet->vertices));
+    else
+      qh_setaddnth(&vertices, 0, SETsecond_(facet->vertices));
+    qh_setappend(&vertices, SETelem_(facet->vertices, 2));
+  }else {
+    ridge= firstridge= SETfirstt_(facet->ridges, ridgeT);   /* no infinite */
+    while ((ridge= qh_nextridge3d(ridge, facet, &vertex))) {
+      qh_setappend(&vertices, vertex);
+      if (++cntprojected > cntvertices || ridge == firstridge)
+        break;
+    }
+    if (!ridge || cntprojected != cntvertices) {
+      qh_fprintf(qh ferr, 6148, "qhull internal error (qh_facet3vertex): ridges for facet %d don't match up.  got at least %d\n",
+                  facet->id, cntprojected);
+      qh_errexit(qh_ERRqhull, facet, ridge);
+    }
+  }
+  return vertices;
+} /* facet3vertex */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="findbestfacet">-</a>
+
+  qh_findbestfacet( point, bestoutside, bestdist, isoutside )
+    find facet that is furthest below a point
+
+    for Delaunay triangulations,
+      Use qh_setdelaunay() to lift point to paraboloid and scale by 'Qbb' if needed
+      Do not use options 'Qbk', 'QBk', or 'QbB' since they scale the coordinates.
+
+  returns:
+    if bestoutside is set (e.g., qh_ALL)
+      returns best facet that is not upperdelaunay
+      if Delaunay and inside, point is outside circumsphere of bestfacet
+    else
+      returns first facet below point
+      if point is inside, returns nearest, !upperdelaunay facet
+    distance to facet
+    isoutside set if outside of facet
+
+  notes:
+    For tricoplanar facets, this finds one of the tricoplanar facets closest
+    to the point.  For Delaunay triangulations, the point may be inside a
+    different tricoplanar facet. See <a href="../html/qh-code.htm#findfacet">locate a facet with qh_findbestfacet()</a>
+
+    If inside, qh_findbestfacet performs an exhaustive search
+       this may be too conservative.  Sometimes it is clearly required.
+
+    qh_findbestfacet is not used by qhull.
+    uses qh.visit_id and qh.coplanarset
+
+  see:
+    <a href="geom.c#findbest">qh_findbest</a>
+*/
+facetT *qh_findbestfacet(pointT *point, boolT bestoutside,
+           realT *bestdist, boolT *isoutside) {
+  facetT *bestfacet= NULL;
+  int numpart, totpart= 0;
+
+  bestfacet= qh_findbest(point, qh facet_list,
+                            bestoutside, !qh_ISnewfacets, bestoutside /* qh_NOupper */,
+                            bestdist, isoutside, &totpart);
+  if (*bestdist < -qh DISTround) {
+    bestfacet= qh_findfacet_all(point, bestdist, isoutside, &numpart);
+    totpart += numpart;
+    if ((isoutside && bestoutside)
+    || (!isoutside && bestfacet->upperdelaunay)) {
+      bestfacet= qh_findbest(point, bestfacet,
+                            bestoutside, False, bestoutside,
+                            bestdist, isoutside, &totpart);
+      totpart += numpart;
+    }
+  }
+  trace3((qh ferr, 3014, "qh_findbestfacet: f%d dist %2.2g isoutside %d totpart %d\n",
+          bestfacet->id, *bestdist, *isoutside, totpart));
+  return bestfacet;
+} /* findbestfacet */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="findbestlower">-</a>
+
+  qh_findbestlower( facet, point, bestdist, numpart )
+    returns best non-upper, non-flipped neighbor of facet for point
+    if needed, searches vertex neighbors
+
+  returns:
+    returns bestdist and updates numpart
+
+  notes:
+    if Delaunay and inside, point is outside of circumsphere of bestfacet
+    called by qh_findbest() for points above an upperdelaunay facet
+
+*/
+facetT *qh_findbestlower(facetT *upperfacet, pointT *point, realT *bestdistp, int *numpart) {
+  facetT *neighbor, **neighborp, *bestfacet= NULL;
+  realT bestdist= -REALmax/2 /* avoid underflow */;
+  realT dist;
+  vertexT *vertex;
+
+  zinc_(Zbestlower);
+  FOREACHneighbor_(upperfacet) {
+    if (neighbor->upperdelaunay || neighbor->flipped)
+      continue;
+    (*numpart)++;
+    qh_distplane(point, neighbor, &dist);
+    if (dist > bestdist) {
+      bestfacet= neighbor;
+      bestdist= dist;
+    }
+  }
+  if (!bestfacet) {
+    zinc_(Zbestlowerv);
+    /* rarely called, numpart does not count nearvertex computations */
+    vertex= qh_nearvertex(upperfacet, point, &dist);
+    qh_vertexneighbors();
+    FOREACHneighbor_(vertex) {
+      if (neighbor->upperdelaunay || neighbor->flipped)
+        continue;
+      (*numpart)++;
+      qh_distplane(point, neighbor, &dist);
+      if (dist > bestdist) {
+        bestfacet= neighbor;
+        bestdist= dist;
+      }
+    }
+  }
+  if (!bestfacet) {
+    qh_fprintf(qh ferr, 6228, "\n\
+Qhull internal error (qh_findbestlower): all neighbors of facet %d are flipped or upper Delaunay.\n\
+Please report this error to qhull_bug at qhull.org with the input and all of the output.\n",
+       upperfacet->id);
+    qh_errexit(qh_ERRqhull, upperfacet, NULL);
+  }
+  *bestdistp= bestdist;
+  trace3((qh ferr, 3015, "qh_findbestlower: f%d dist %2.2g for f%d p%d\n",
+          bestfacet->id, bestdist, upperfacet->id, qh_pointid(point)));
+  return bestfacet;
+} /* findbestlower */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="findfacet_all">-</a>
+
+  qh_findfacet_all( point, bestdist, isoutside, numpart )
+    exhaustive search for facet below a point
+
+    for Delaunay triangulations,
+      Use qh_setdelaunay() to lift point to paraboloid and scale by 'Qbb' if needed
+      Do not use options 'Qbk', 'QBk', or 'QbB' since they scale the coordinates.
+
+  returns:
+    returns first facet below point
+    if point is inside,
+      returns nearest facet
+    distance to facet
+    isoutside if point is outside of the hull
+    number of distance tests
+
+  notes:
+    for library users, not used by Qhull
+*/
+facetT *qh_findfacet_all(pointT *point, realT *bestdist, boolT *isoutside,
+                          int *numpart) {
+  facetT *bestfacet= NULL, *facet;
+  realT dist;
+  int totpart= 0;
+
+  *bestdist= -REALmax;
+  *isoutside= False;
+  FORALLfacets {
+    if (facet->flipped || !facet->normal)
+      continue;
+    totpart++;
+    qh_distplane(point, facet, &dist);
+    if (dist > *bestdist) {
+      *bestdist= dist;
+      bestfacet= facet;
+      if (dist > qh MINoutside) {
+        *isoutside= True;
+        break;
+      }
+    }
+  }
+  *numpart= totpart;
+  trace3((qh ferr, 3016, "qh_findfacet_all: f%d dist %2.2g isoutside %d totpart %d\n",
+          getid_(bestfacet), *bestdist, *isoutside, totpart));
+  return bestfacet;
+} /* findfacet_all */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="findgood">-</a>
+
+  qh_findgood( facetlist, goodhorizon )
+    identify good facets for qh.PRINTgood
+    if qh.GOODvertex>0
+      facet includes point as vertex
+      if !match, returns goodhorizon
+      inactive if qh.MERGING
+    if qh.GOODpoint
+      facet is visible or coplanar (>0) or not visible (<0)
+    if qh.GOODthreshold
+      facet->normal matches threshold
+    if !goodhorizon and !match,
+      selects facet with closest angle
+      sets GOODclosest
+
+  returns:
+    number of new, good facets found
+    determines facet->good
+    may update qh.GOODclosest
+
+  notes:
+    qh_findgood_all further reduces the good region
+
+  design:
+    count good facets
+    mark good facets for qh.GOODpoint
+    mark good facets for qh.GOODthreshold
+    if necessary
+      update qh.GOODclosest
+*/
+int qh_findgood(facetT *facetlist, int goodhorizon) {
+  facetT *facet, *bestfacet= NULL;
+  realT angle, bestangle= REALmax, dist;
+  int  numgood=0;
+
+  FORALLfacet_(facetlist) {
+    if (facet->good)
+      numgood++;
+  }
+  if (qh GOODvertex>0 && !qh MERGING) {
+    FORALLfacet_(facetlist) {
+      if (!qh_isvertex(qh GOODvertexp, facet->vertices)) {
+        facet->good= False;
+        numgood--;
+      }
+    }
+  }
+  if (qh GOODpoint && numgood) {
+    FORALLfacet_(facetlist) {
+      if (facet->good && facet->normal) {
+        zinc_(Zdistgood);
+        qh_distplane(qh GOODpointp, facet, &dist);
+        if ((qh GOODpoint > 0) ^ (dist > 0.0)) {
+          facet->good= False;
+          numgood--;
+        }
+      }
+    }
+  }
+  if (qh GOODthreshold && (numgood || goodhorizon || qh GOODclosest)) {
+    FORALLfacet_(facetlist) {
+      if (facet->good && facet->normal) {
+        if (!qh_inthresholds(facet->normal, &angle)) {
+          facet->good= False;
+          numgood--;
+          if (angle < bestangle) {
+            bestangle= angle;
+            bestfacet= facet;
+          }
+        }
+      }
+    }
+    if (!numgood && (!goodhorizon || qh GOODclosest)) {
+      if (qh GOODclosest) {
+        if (qh GOODclosest->visible)
+          qh GOODclosest= NULL;
+        else {
+          qh_inthresholds(qh GOODclosest->normal, &angle);
+          if (angle < bestangle)
+            bestfacet= qh GOODclosest;
+        }
+      }
+      if (bestfacet && bestfacet != qh GOODclosest) {
+        if (qh GOODclosest)
+          qh GOODclosest->good= False;
+        qh GOODclosest= bestfacet;
+        bestfacet->good= True;
+        numgood++;
+        trace2((qh ferr, 2044, "qh_findgood: f%d is closest(%2.2g) to thresholds\n",
+           bestfacet->id, bestangle));
+        return numgood;
+      }
+    }else if (qh GOODclosest) { /* numgood > 0 */
+      qh GOODclosest->good= False;
+      qh GOODclosest= NULL;
+    }
+  }
+  zadd_(Zgoodfacet, numgood);
+  trace2((qh ferr, 2045, "qh_findgood: found %d good facets with %d good horizon\n",
+               numgood, goodhorizon));
+  if (!numgood && qh GOODvertex>0 && !qh MERGING)
+    return goodhorizon;
+  return numgood;
+} /* findgood */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="findgood_all">-</a>
+
+  qh_findgood_all( facetlist )
+    apply other constraints for good facets (used by qh.PRINTgood)
+    if qh.GOODvertex
+      facet includes (>0) or doesn't include (<0) point as vertex
+      if last good facet and ONLYgood, prints warning and continues
+    if qh.SPLITthresholds
+      facet->normal matches threshold, or if none, the closest one
+    calls qh_findgood
+    nop if good not used
+
+  returns:
+    clears facet->good if not good
+    sets qh.num_good
+
+  notes:
+    this is like qh_findgood but more restrictive
+
+  design:
+    uses qh_findgood to mark good facets
+    marks facets for qh.GOODvertex
+    marks facets for qh.SPLITthreholds
+*/
+void qh_findgood_all(facetT *facetlist) {
+  facetT *facet, *bestfacet=NULL;
+  realT angle, bestangle= REALmax;
+  int  numgood=0, startgood;
+
+  if (!qh GOODvertex && !qh GOODthreshold && !qh GOODpoint
+  && !qh SPLITthresholds)
+    return;
+  if (!qh ONLYgood)
+    qh_findgood(qh facet_list, 0);
+  FORALLfacet_(facetlist) {
+    if (facet->good)
+      numgood++;
+  }
+  if (qh GOODvertex <0 || (qh GOODvertex > 0 && qh MERGING)) {
+    FORALLfacet_(facetlist) {
+      if (facet->good && ((qh GOODvertex > 0) ^ !!qh_isvertex(qh GOODvertexp, facet->vertices))) {
+        if (!--numgood) {
+          if (qh ONLYgood) {
+            qh_fprintf(qh ferr, 7064, "qhull warning: good vertex p%d does not match last good facet f%d.  Ignored.\n",
+               qh_pointid(qh GOODvertexp), facet->id);
+            return;
+          }else if (qh GOODvertex > 0)
+            qh_fprintf(qh ferr, 7065, "qhull warning: point p%d is not a vertex('QV%d').\n",
+                qh GOODvertex-1, qh GOODvertex-1);
+          else
+            qh_fprintf(qh ferr, 7066, "qhull warning: point p%d is a vertex for every facet('QV-%d').\n",
+                -qh GOODvertex - 1, -qh GOODvertex - 1);
+        }
+        facet->good= False;
+      }
+    }
+  }
+  startgood= numgood;
+  if (qh SPLITthresholds) {
+    FORALLfacet_(facetlist) {
+      if (facet->good) {
+        if (!qh_inthresholds(facet->normal, &angle)) {
+          facet->good= False;
+          numgood--;
+          if (angle < bestangle) {
+            bestangle= angle;
+            bestfacet= facet;
+          }
+        }
+      }
+    }
+    if (!numgood && bestfacet) {
+      bestfacet->good= True;
+      numgood++;
+      trace0((qh ferr, 23, "qh_findgood_all: f%d is closest(%2.2g) to thresholds\n",
+           bestfacet->id, bestangle));
+      return;
+    }
+  }
+  qh num_good= numgood;
+  trace0((qh ferr, 24, "qh_findgood_all: %d good facets remain out of %d facets\n",
+        numgood, startgood));
+} /* findgood_all */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="furthestnext">-</a>
+
+  qh_furthestnext()
+    set qh.facet_next to facet with furthest of all furthest points
+    searches all facets on qh.facet_list
+
+  notes:
+    this may help avoid precision problems
+*/
+void qh_furthestnext(void /* qh facet_list */) {
+  facetT *facet, *bestfacet= NULL;
+  realT dist, bestdist= -REALmax;
+
+  FORALLfacets {
+    if (facet->outsideset) {
+#if qh_COMPUTEfurthest
+      pointT *furthest;
+      furthest= (pointT*)qh_setlast(facet->outsideset);
+      zinc_(Zcomputefurthest);
+      qh_distplane(furthest, facet, &dist);
+#else
+      dist= facet->furthestdist;
+#endif
+      if (dist > bestdist) {
+        bestfacet= facet;
+        bestdist= dist;
+      }
+    }
+  }
+  if (bestfacet) {
+    qh_removefacet(bestfacet);
+    qh_prependfacet(bestfacet, &qh facet_next);
+    trace1((qh ferr, 1029, "qh_furthestnext: made f%d next facet(dist %.2g)\n",
+            bestfacet->id, bestdist));
+  }
+} /* furthestnext */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="furthestout">-</a>
+
+  qh_furthestout( facet )
+    make furthest outside point the last point of outsideset
+
+  returns:
+    updates facet->outsideset
+    clears facet->notfurthest
+    sets facet->furthestdist
+
+  design:
+    determine best point of outsideset
+    make it the last point of outsideset
+*/
+void qh_furthestout(facetT *facet) {
+  pointT *point, **pointp, *bestpoint= NULL;
+  realT dist, bestdist= -REALmax;
+
+  FOREACHpoint_(facet->outsideset) {
+    qh_distplane(point, facet, &dist);
+    zinc_(Zcomputefurthest);
+    if (dist > bestdist) {
+      bestpoint= point;
+      bestdist= dist;
+    }
+  }
+  if (bestpoint) {
+    qh_setdel(facet->outsideset, point);
+    qh_setappend(&facet->outsideset, point);
+#if !qh_COMPUTEfurthest
+    facet->furthestdist= bestdist;
+#endif
+  }
+  facet->notfurthest= False;
+  trace3((qh ferr, 3017, "qh_furthestout: p%d is furthest outside point of f%d\n",
+          qh_pointid(point), facet->id));
+} /* furthestout */
+
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >-------------------------------</a><a name="infiniteloop">-</a>
+
+  qh_infiniteloop( facet )
+    report infinite loop error due to facet
+*/
+void qh_infiniteloop(facetT *facet) {
+
+  qh_fprintf(qh ferr, 6149, "qhull internal error (qh_infiniteloop): potential infinite loop detected\n");
+  qh_errexit(qh_ERRqhull, facet, NULL);
+} /* qh_infiniteloop */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="initbuild">-</a>
+
+  qh_initbuild()
+    initialize hull and outside sets with point array
+    qh.FIRSTpoint/qh.NUMpoints is point array
+    if qh.GOODpoint
+      adds qh.GOODpoint to initial hull
+
+  returns:
+    qh_facetlist with initial hull
+    points partioned into outside sets, coplanar sets, or inside
+    initializes qh.GOODpointp, qh.GOODvertexp,
+
+  design:
+    initialize global variables used during qh_buildhull
+    determine precision constants and points with max/min coordinate values
+      if qh.SCALElast, scale last coordinate(for 'd')
+    build initial simplex
+    partition input points into facets of initial simplex
+    set up lists
+    if qh.ONLYgood
+      check consistency
+      add qh.GOODvertex if defined
+*/
+void qh_initbuild( void) {
+  setT *maxpoints, *vertices;
+  facetT *facet;
+  int i, numpart;
+  realT dist;
+  boolT isoutside;
+
+  qh furthest_id= -1;
+  qh lastreport= 0;
+  qh facet_id= qh vertex_id= qh ridge_id= 0;
+  qh visit_id= qh vertex_visit= 0;
+  qh maxoutdone= False;
+
+  if (qh GOODpoint > 0)
+    qh GOODpointp= qh_point(qh GOODpoint-1);
+  else if (qh GOODpoint < 0)
+    qh GOODpointp= qh_point(-qh GOODpoint-1);
+  if (qh GOODvertex > 0)
+    qh GOODvertexp= qh_point(qh GOODvertex-1);
+  else if (qh GOODvertex < 0)
+    qh GOODvertexp= qh_point(-qh GOODvertex-1);
+  if ((qh GOODpoint
+       && (qh GOODpointp < qh first_point  /* also catches !GOODpointp */
+           || qh GOODpointp > qh_point(qh num_points-1)))
+    || (qh GOODvertex
+        && (qh GOODvertexp < qh first_point  /* also catches !GOODvertexp */
+            || qh GOODvertexp > qh_point(qh num_points-1)))) {
+    qh_fprintf(qh ferr, 6150, "qhull input error: either QGn or QVn point is > p%d\n",
+             qh num_points-1);
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  maxpoints= qh_maxmin(qh first_point, qh num_points, qh hull_dim);
+  if (qh SCALElast)
+    qh_scalelast(qh first_point, qh num_points, qh hull_dim,
+               qh MINlastcoord, qh MAXlastcoord, qh MAXwidth);
+  qh_detroundoff();
+  if (qh DELAUNAY && qh upper_threshold[qh hull_dim-1] > REALmax/2
+                  && qh lower_threshold[qh hull_dim-1] < -REALmax/2) {
+    for (i=qh_PRINTEND; i--; ) {
+      if (qh PRINTout[i] == qh_PRINTgeom && qh DROPdim < 0
+          && !qh GOODthreshold && !qh SPLITthresholds)
+        break;  /* in this case, don't set upper_threshold */
+    }
+    if (i < 0) {
+      if (qh UPPERdelaunay) { /* matches qh.upperdelaunay in qh_setfacetplane */
+        qh lower_threshold[qh hull_dim-1]= qh ANGLEround * qh_ZEROdelaunay;
+        qh GOODthreshold= True;
+      }else {
+        qh upper_threshold[qh hull_dim-1]= -qh ANGLEround * qh_ZEROdelaunay;
+        if (!qh GOODthreshold)
+          qh SPLITthresholds= True; /* build upper-convex hull even if Qg */
+          /* qh_initqhull_globals errors if Qg without Pdk/etc. */
+      }
+    }
+  }
+  vertices= qh_initialvertices(qh hull_dim, maxpoints, qh first_point, qh num_points);
+  qh_initialhull(vertices);  /* initial qh facet_list */
+  qh_partitionall(vertices, qh first_point, qh num_points);
+  if (qh PRINToptions1st || qh TRACElevel || qh IStracing) {
+    if (qh TRACElevel || qh IStracing)
+      qh_fprintf(qh ferr, 8103, "\nTrace level %d for %s | %s\n",
+         qh IStracing ? qh IStracing : qh TRACElevel, qh rbox_command, qh qhull_command);
+    qh_fprintf(qh ferr, 8104, "Options selected for Qhull %s:\n%s\n", qh_version, qh qhull_options);
+  }
+  qh_resetlists(False, qh_RESETvisible /*qh visible_list newvertex_list newfacet_list */);
+  qh facet_next= qh facet_list;
+  qh_furthestnext(/* qh facet_list */);
+  if (qh PREmerge) {
+    qh cos_max= qh premerge_cos;
+    qh centrum_radius= qh premerge_centrum;
+  }
+  if (qh ONLYgood) {
+    if (qh GOODvertex > 0 && qh MERGING) {
+      qh_fprintf(qh ferr, 6151, "qhull input error: 'Qg QVn' (only good vertex) does not work with merging.\nUse 'QJ' to joggle the input or 'Q0' to turn off merging.\n");
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+    if (!(qh GOODthreshold || qh GOODpoint
+         || (!qh MERGEexact && !qh PREmerge && qh GOODvertexp))) {
+      qh_fprintf(qh ferr, 6152, "qhull input error: 'Qg' (ONLYgood) needs a good threshold('Pd0D0'), a\n\
+good point(QGn or QG-n), or a good vertex with 'QJ' or 'Q0' (QVn).\n");
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+    if (qh GOODvertex > 0  && !qh MERGING  /* matches qh_partitionall */
+        && !qh_isvertex(qh GOODvertexp, vertices)) {
+      facet= qh_findbestnew(qh GOODvertexp, qh facet_list,
+                          &dist, !qh_ALL, &isoutside, &numpart);
+      zadd_(Zdistgood, numpart);
+      if (!isoutside) {
+        qh_fprintf(qh ferr, 6153, "qhull input error: point for QV%d is inside initial simplex.  It can not be made a vertex.\n",
+               qh_pointid(qh GOODvertexp));
+        qh_errexit(qh_ERRinput, NULL, NULL);
+      }
+      if (!qh_addpoint(qh GOODvertexp, facet, False)) {
+        qh_settempfree(&vertices);
+        qh_settempfree(&maxpoints);
+        return;
+      }
+    }
+    qh_findgood(qh facet_list, 0);
+  }
+  qh_settempfree(&vertices);
+  qh_settempfree(&maxpoints);
+  trace1((qh ferr, 1030, "qh_initbuild: initial hull created and points partitioned\n"));
+} /* initbuild */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="initialhull">-</a>
+
+  qh_initialhull( vertices )
+    constructs the initial hull as a DIM3 simplex of vertices
+
+  design:
+    creates a simplex (initializes lists)
+    determines orientation of simplex
+    sets hyperplanes for facets
+    doubles checks orientation (in case of axis-parallel facets with Gaussian elimination)
+    checks for flipped facets and qh.NARROWhull
+    checks the result
+*/
+void qh_initialhull(setT *vertices) {
+  facetT *facet, *firstfacet, *neighbor, **neighborp;
+  realT dist, angle, minangle= REALmax;
+#ifndef qh_NOtrace
+  int k;
+#endif
+
+  qh_createsimplex(vertices);  /* qh facet_list */
+  qh_resetlists(False, qh_RESETvisible);
+  qh facet_next= qh facet_list;      /* advance facet when processed */
+  qh interior_point= qh_getcenter(vertices);
+  firstfacet= qh facet_list;
+  qh_setfacetplane(firstfacet);
+  zinc_(Znumvisibility); /* needs to be in printsummary */
+  qh_distplane(qh interior_point, firstfacet, &dist);
+  if (dist > 0) {
+    FORALLfacets
+      facet->toporient ^= (unsigned char)True;
+  }
+  FORALLfacets
+    qh_setfacetplane(facet);
+  FORALLfacets {
+    if (!qh_checkflipped(facet, NULL, qh_ALL)) {/* due to axis-parallel facet */
+      trace1((qh ferr, 1031, "qh_initialhull: initial orientation incorrect.  Correct all facets\n"));
+      facet->flipped= False;
+      FORALLfacets {
+        facet->toporient ^= (unsigned char)True;
+        qh_orientoutside(facet);
+      }
+      break;
+    }
+  }
+  FORALLfacets {
+    if (!qh_checkflipped(facet, NULL, !qh_ALL)) {  /* can happen with 'R0.1' */
+      if (qh DELAUNAY && ! qh ATinfinity) {
+        if (qh UPPERdelaunay)
+          qh_fprintf(qh ferr, 6240, "Qhull input error: Can not compute the upper Delaunay triangulation or upper Voronoi diagram of cocircular/cospherical points.\n");
+        else
+          qh_fprintf(qh ferr, 6239, "Qhull input error: Use option 'Qz' for the Delaunay triangulation or Voronoi diagram of cocircular/cospherical points.  Option 'Qz' adds a point \"at infinity\" (above the corresponding paraboloid).\n");
+        qh_errexit(qh_ERRinput, NULL, NULL);
+      }
+      qh_precision("initial facet is coplanar with interior point");
+      qh_fprintf(qh ferr, 6154, "qhull precision error: initial facet %d is coplanar with the interior point\n",
+                   facet->id);
+      qh_errexit(qh_ERRsingular, facet, NULL);
+    }
+    FOREACHneighbor_(facet) {
+      angle= qh_getangle(facet->normal, neighbor->normal);
+      minimize_( minangle, angle);
+    }
+  }
+  if (minangle < qh_MAXnarrow && !qh NOnarrow) {
+    realT diff= 1.0 + minangle;
+
+    qh NARROWhull= True;
+    qh_option("_narrow-hull", NULL, &diff);
+    if (minangle < qh_WARNnarrow && !qh RERUN && qh PRINTprecision)
+      qh_printhelp_narrowhull(qh ferr, minangle);
+  }
+  zzval_(Zprocessed)= qh hull_dim+1;
+  qh_checkpolygon(qh facet_list);
+  qh_checkconvex(qh facet_list,   qh_DATAfault);
+#ifndef qh_NOtrace
+  if (qh IStracing >= 1) {
+    qh_fprintf(qh ferr, 8105, "qh_initialhull: simplex constructed, interior point:");
+    for (k=0; k < qh hull_dim; k++)
+      qh_fprintf(qh ferr, 8106, " %6.4g", qh interior_point[k]);
+    qh_fprintf(qh ferr, 8107, "\n");
+  }
+#endif
+} /* initialhull */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="initialvertices">-</a>
+
+  qh_initialvertices( dim, maxpoints, points, numpoints )
+    determines a non-singular set of initial vertices
+    maxpoints may include duplicate points
+
+  returns:
+    temporary set of dim+1 vertices in descending order by vertex id
+    if qh.RANDOMoutside && !qh.ALLpoints
+      picks random points
+    if dim >= qh_INITIALmax,
+      uses min/max x and max points with non-zero determinants
+
+  notes:
+    unless qh.ALLpoints,
+      uses maxpoints as long as determinate is non-zero
+*/
+setT *qh_initialvertices(int dim, setT *maxpoints, pointT *points, int numpoints) {
+  pointT *point, **pointp;
+  setT *vertices, *simplex, *tested;
+  realT randr;
+  int idx, point_i, point_n, k;
+  boolT nearzero= False;
+
+  vertices= qh_settemp(dim + 1);
+  simplex= qh_settemp(dim+1);
+  if (qh ALLpoints)
+    qh_maxsimplex(dim, NULL, points, numpoints, &simplex);
+  else if (qh RANDOMoutside) {
+    while (qh_setsize(simplex) != dim+1) {
+      randr= qh_RANDOMint;
+      randr= randr/(qh_RANDOMmax+1);
+      idx= (int)floor(qh num_points * randr);
+      while (qh_setin(simplex, qh_point(idx))) {
+            idx++; /* in case qh_RANDOMint always returns the same value */
+        idx= idx < qh num_points ? idx : 0;
+      }
+      qh_setappend(&simplex, qh_point(idx));
+    }
+  }else if (qh hull_dim >= qh_INITIALmax) {
+    tested= qh_settemp(dim+1);
+    qh_setappend(&simplex, SETfirst_(maxpoints));   /* max and min X coord */
+    qh_setappend(&simplex, SETsecond_(maxpoints));
+    qh_maxsimplex(fmin_(qh_INITIALsearch, dim), maxpoints, points, numpoints, &simplex);
+    k= qh_setsize(simplex);
+    FOREACHpoint_i_(maxpoints) {
+      if (point_i & 0x1) {     /* first pick up max. coord. points */
+        if (!qh_setin(simplex, point) && !qh_setin(tested, point)){
+          qh_detsimplex(point, simplex, k, &nearzero);
+          if (nearzero)
+            qh_setappend(&tested, point);
+          else {
+            qh_setappend(&simplex, point);
+            if (++k == dim)  /* use search for last point */
+              break;
+          }
+        }
+      }
+    }
+    while (k != dim && (point= (pointT*)qh_setdellast(maxpoints))) {
+      if (!qh_setin(simplex, point) && !qh_setin(tested, point)){
+        qh_detsimplex(point, simplex, k, &nearzero);
+        if (nearzero)
+          qh_setappend(&tested, point);
+        else {
+          qh_setappend(&simplex, point);
+          k++;
+        }
+      }
+    }
+    idx= 0;
+    while (k != dim && (point= qh_point(idx++))) {
+      if (!qh_setin(simplex, point) && !qh_setin(tested, point)){
+        qh_detsimplex(point, simplex, k, &nearzero);
+        if (!nearzero){
+          qh_setappend(&simplex, point);
+          k++;
+        }
+      }
+    }
+    qh_settempfree(&tested);
+    qh_maxsimplex(dim, maxpoints, points, numpoints, &simplex);
+  }else
+    qh_maxsimplex(dim, maxpoints, points, numpoints, &simplex);
+  FOREACHpoint_(simplex)
+    qh_setaddnth(&vertices, 0, qh_newvertex(point)); /* descending order */
+  qh_settempfree(&simplex);
+  return vertices;
+} /* initialvertices */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="isvertex">-</a>
+
+  qh_isvertex(  )
+    returns vertex if point is in vertex set, else returns NULL
+
+  notes:
+    for qh.GOODvertex
+*/
+vertexT *qh_isvertex(pointT *point, setT *vertices) {
+  vertexT *vertex, **vertexp;
+
+  FOREACHvertex_(vertices) {
+    if (vertex->point == point)
+      return vertex;
+  }
+  return NULL;
+} /* isvertex */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="makenewfacets">-</a>
+
+  qh_makenewfacets( point )
+    make new facets from point and qh.visible_list
+
+  returns:
+    qh.newfacet_list= list of new facets with hyperplanes and ->newfacet
+    qh.newvertex_list= list of vertices in new facets with ->newlist set
+
+    if (qh.ONLYgood)
+      newfacets reference horizon facets, but not vice versa
+      ridges reference non-simplicial horizon ridges, but not vice versa
+      does not change existing facets
+    else
+      sets qh.NEWfacets
+      new facets attached to horizon facets and ridges
+      for visible facets,
+        visible->r.replace is corresponding new facet
+
+  see also:
+    qh_makenewplanes() -- make hyperplanes for facets
+    qh_attachnewfacets() -- attachnewfacets if not done here(qh ONLYgood)
+    qh_matchnewfacets() -- match up neighbors
+    qh_updatevertices() -- update vertex neighbors and delvertices
+    qh_deletevisible() -- delete visible facets
+    qh_checkpolygon() --check the result
+    qh_triangulate() -- triangulate a non-simplicial facet
+
+  design:
+    for each visible facet
+      make new facets to its horizon facets
+      update its f.replace
+      clear its neighbor set
+*/
+vertexT *qh_makenewfacets(pointT *point /*visible_list*/) {
+  facetT *visible, *newfacet= NULL, *newfacet2= NULL, *neighbor, **neighborp;
+  vertexT *apex;
+  int numnew=0;
+
+  qh newfacet_list= qh facet_tail;
+  qh newvertex_list= qh vertex_tail;
+  apex= qh_newvertex(point);
+  qh_appendvertex(apex);
+  qh visit_id++;
+  if (!qh ONLYgood)
+    qh NEWfacets= True;
+  FORALLvisible_facets {
+    FOREACHneighbor_(visible)
+      neighbor->seen= False;
+    if (visible->ridges) {
+      visible->visitid= qh visit_id;
+      newfacet2= qh_makenew_nonsimplicial(visible, apex, &numnew);
+    }
+    if (visible->simplicial)
+      newfacet= qh_makenew_simplicial(visible, apex, &numnew);
+    if (!qh ONLYgood) {
+      if (newfacet2)  /* newfacet is null if all ridges defined */
+        newfacet= newfacet2;
+      if (newfacet)
+        visible->f.replace= newfacet;
+      else
+        zinc_(Zinsidevisible);
+      SETfirst_(visible->neighbors)= NULL;
+    }
+  }
+  trace1((qh ferr, 1032, "qh_makenewfacets: created %d new facets from point p%d to horizon\n",
+          numnew, qh_pointid(point)));
+  if (qh IStracing >= 4)
+    qh_printfacetlist(qh newfacet_list, NULL, qh_ALL);
+  return apex;
+} /* makenewfacets */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="matchduplicates">-</a>
+
+  qh_matchduplicates( atfacet, atskip, hashsize, hashcount )
+    match duplicate ridges in qh.hash_table for atfacet/atskip
+    duplicates marked with ->dupridge and qh_DUPLICATEridge
+
+  returns:
+    picks match with worst merge (min distance apart)
+    updates hashcount
+
+  see also:
+    qh_matchneighbor
+
+  notes:
+
+  design:
+    compute hash value for atfacet and atskip
+    repeat twice -- once to make best matches, once to match the rest
+      for each possible facet in qh.hash_table
+        if it is a matching facet and pass 2
+          make match
+          unless tricoplanar, mark match for merging (qh_MERGEridge)
+          [e.g., tricoplanar RBOX s 1000 t993602376 | QHULL C-1e-3 d Qbb FA Qt]
+        if it is a matching facet and pass 1
+          test if this is a better match
+      if pass 1,
+        make best match (it will not be merged)
+*/
+#ifndef qh_NOmerge
+void qh_matchduplicates(facetT *atfacet, int atskip, int hashsize, int *hashcount) {
+  boolT same, ismatch;
+  int hash, scan;
+  facetT *facet, *newfacet, *maxmatch= NULL, *maxmatch2= NULL, *nextfacet;
+  int skip, newskip, nextskip= 0, maxskip= 0, maxskip2= 0, makematch;
+  realT maxdist= -REALmax, mindist, dist2, low, high;
+
+  hash= qh_gethash(hashsize, atfacet->vertices, qh hull_dim, 1,
+                     SETelem_(atfacet->vertices, atskip));
+  trace2((qh ferr, 2046, "qh_matchduplicates: find duplicate matches for f%d skip %d hash %d hashcount %d\n",
+          atfacet->id, atskip, hash, *hashcount));
+  for (makematch= 0; makematch < 2; makematch++) {
+    qh visit_id++;
+    for (newfacet= atfacet, newskip= atskip; newfacet; newfacet= nextfacet, newskip= nextskip) {
+      zinc_(Zhashlookup);
+      nextfacet= NULL;
+      newfacet->visitid= qh visit_id;
+      for (scan= hash; (facet= SETelemt_(qh hash_table, scan, facetT));
+           scan= (++scan >= hashsize ? 0 : scan)) {
+        if (!facet->dupridge || facet->visitid == qh visit_id)
+          continue;
+        zinc_(Zhashtests);
+        if (qh_matchvertices(1, newfacet->vertices, newskip, facet->vertices, &skip, &same)) {
+          ismatch= (same == (boolT)(newfacet->toporient ^ facet->toporient));
+          if (SETelemt_(facet->neighbors, skip, facetT) != qh_DUPLICATEridge) {
+            if (!makematch) {
+              qh_fprintf(qh ferr, 6155, "qhull internal error (qh_matchduplicates): missing dupridge at f%d skip %d for new f%d skip %d hash %d\n",
+                     facet->id, skip, newfacet->id, newskip, hash);
+              qh_errexit2 (qh_ERRqhull, facet, newfacet);
+            }
+          }else if (ismatch && makematch) {
+            if (SETelemt_(newfacet->neighbors, newskip, facetT) == qh_DUPLICATEridge) {
+              SETelem_(facet->neighbors, skip)= newfacet;
+              if (newfacet->tricoplanar)
+                SETelem_(newfacet->neighbors, newskip)= facet;
+              else
+                SETelem_(newfacet->neighbors, newskip)= qh_MERGEridge;
+              *hashcount -= 2; /* removed two unmatched facets */
+              trace4((qh ferr, 4059, "qh_matchduplicates: duplicate f%d skip %d matched with new f%d skip %d merge\n",
+                    facet->id, skip, newfacet->id, newskip));
+            }
+          }else if (ismatch) {
+            mindist= qh_getdistance(facet, newfacet, &low, &high);
+            dist2= qh_getdistance(newfacet, facet, &low, &high);
+            minimize_(mindist, dist2);
+            if (mindist > maxdist) {
+              maxdist= mindist;
+              maxmatch= facet;
+              maxskip= skip;
+              maxmatch2= newfacet;
+              maxskip2= newskip;
+            }
+            trace3((qh ferr, 3018, "qh_matchduplicates: duplicate f%d skip %d new f%d skip %d at dist %2.2g, max is now f%d f%d\n",
+                    facet->id, skip, newfacet->id, newskip, mindist,
+                    maxmatch->id, maxmatch2->id));
+          }else { /* !ismatch */
+            nextfacet= facet;
+            nextskip= skip;
+          }
+        }
+        if (makematch && !facet
+        && SETelemt_(facet->neighbors, skip, facetT) == qh_DUPLICATEridge) {
+          qh_fprintf(qh ferr, 6156, "qhull internal error (qh_matchduplicates): no MERGEridge match for duplicate f%d skip %d at hash %d\n",
+                     newfacet->id, newskip, hash);
+          qh_errexit(qh_ERRqhull, newfacet, NULL);
+        }
+      }
+    } /* end of for each new facet at hash */
+    if (!makematch) {
+      if (!maxmatch) {
+        qh_fprintf(qh ferr, 6157, "qhull internal error (qh_matchduplicates): no maximum match at duplicate f%d skip %d at hash %d\n",
+                     atfacet->id, atskip, hash);
+        qh_errexit(qh_ERRqhull, atfacet, NULL);
+      }
+      /* maxmatch cannot be NULL since above qh_errexit didn't return */
+      /* coverity[var_deref_op] */
+      SETelem_(maxmatch->neighbors, maxskip)= maxmatch2;
+      SETelem_(maxmatch2->neighbors, maxskip2)= maxmatch;
+      *hashcount -= 2; /* removed two unmatched facets */
+      zzinc_(Zmultiridge);
+      trace0((qh ferr, 25, "qh_matchduplicates: duplicate f%d skip %d matched with new f%d skip %d keep\n",
+              maxmatch->id, maxskip, maxmatch2->id, maxskip2));
+      qh_precision("ridge with multiple neighbors");
+      if (qh IStracing >= 4)
+        qh_errprint("DUPLICATED/MATCH", maxmatch, maxmatch2, NULL, NULL);
+    }
+  }
+} /* matchduplicates */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="nearcoplanar">-</a>
+
+  qh_nearcoplanar()
+    for all facets, remove near-inside points from facet->coplanarset</li>
+    coplanar points defined by innerplane from qh_outerinner()
+
+  returns:
+    if qh KEEPcoplanar && !qh KEEPinside
+      facet->coplanarset only contains coplanar points
+    if qh.JOGGLEmax
+      drops inner plane by another qh.JOGGLEmax diagonal since a
+        vertex could shift out while a coplanar point shifts in
+
+  notes:
+    used for qh.PREmerge and qh.JOGGLEmax
+    must agree with computation of qh.NEARcoplanar in qh_detroundoff()
+  design:
+    if not keeping coplanar or inside points
+      free all coplanar sets
+    else if not keeping both coplanar and inside points
+      remove !coplanar or !inside points from coplanar sets
+*/
+void qh_nearcoplanar(void /* qh.facet_list */) {
+  facetT *facet;
+  pointT *point, **pointp;
+  int numpart;
+  realT dist, innerplane;
+
+  if (!qh KEEPcoplanar && !qh KEEPinside) {
+    FORALLfacets {
+      if (facet->coplanarset)
+        qh_setfree( &facet->coplanarset);
+    }
+  }else if (!qh KEEPcoplanar || !qh KEEPinside) {
+    qh_outerinner(NULL, NULL, &innerplane);
+    if (qh JOGGLEmax < REALmax/2)
+      innerplane -= qh JOGGLEmax * sqrt((realT)qh hull_dim);
+    numpart= 0;
+    FORALLfacets {
+      if (facet->coplanarset) {
+        FOREACHpoint_(facet->coplanarset) {
+          numpart++;
+          qh_distplane(point, facet, &dist);
+          if (dist < innerplane) {
+            if (!qh KEEPinside)
+              SETref_(point)= NULL;
+          }else if (!qh KEEPcoplanar)
+            SETref_(point)= NULL;
+        }
+        qh_setcompact(facet->coplanarset);
+      }
+    }
+    zzadd_(Zcheckpart, numpart);
+  }
+} /* nearcoplanar */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="nearvertex">-</a>
+
+  qh_nearvertex( facet, point, bestdist )
+    return nearest vertex in facet to point
+
+  returns:
+    vertex and its distance
+
+  notes:
+    if qh.DELAUNAY
+      distance is measured in the input set
+    searches neighboring tricoplanar facets (requires vertexneighbors)
+      Slow implementation.  Recomputes vertex set for each point.
+    The vertex set could be stored in the qh.keepcentrum facet.
+*/
+vertexT *qh_nearvertex(facetT *facet, pointT *point, realT *bestdistp) {
+  realT bestdist= REALmax, dist;
+  vertexT *bestvertex= NULL, *vertex, **vertexp, *apex;
+  coordT *center;
+  facetT *neighbor, **neighborp;
+  setT *vertices;
+  int dim= qh hull_dim;
+
+  if (qh DELAUNAY)
+    dim--;
+  if (facet->tricoplanar) {
+    if (!qh VERTEXneighbors || !facet->center) {
+      qh_fprintf(qh ferr, 6158, "qhull internal error (qh_nearvertex): qh.VERTEXneighbors and facet->center required for tricoplanar facets\n");
+      qh_errexit(qh_ERRqhull, facet, NULL);
+    }
+    vertices= qh_settemp(qh TEMPsize);
+    apex= SETfirstt_(facet->vertices, vertexT);
+    center= facet->center;
+    FOREACHneighbor_(apex) {
+      if (neighbor->center == center) {
+        FOREACHvertex_(neighbor->vertices)
+          qh_setappend(&vertices, vertex);
+      }
+    }
+  }else
+    vertices= facet->vertices;
+  FOREACHvertex_(vertices) {
+    dist= qh_pointdist(vertex->point, point, -dim);
+    if (dist < bestdist) {
+      bestdist= dist;
+      bestvertex= vertex;
+    }
+  }
+  if (facet->tricoplanar)
+    qh_settempfree(&vertices);
+  *bestdistp= sqrt(bestdist);
+  trace3((qh ferr, 3019, "qh_nearvertex: v%d dist %2.2g for f%d p%d\n",
+        bestvertex ? bestvertex->id : -1, *bestdistp, facet->id, qh_pointid(point)));
+  return bestvertex;
+} /* nearvertex */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="newhashtable">-</a>
+
+  qh_newhashtable( newsize )
+    returns size of qh.hash_table of at least newsize slots
+
+  notes:
+    assumes qh.hash_table is NULL
+    qh_HASHfactor determines the number of extra slots
+    size is not divisible by 2, 3, or 5
+*/
+int qh_newhashtable(int newsize) {
+  int size;
+
+  size= ((newsize+1)*qh_HASHfactor) | 0x1;  /* odd number */
+  while (True) {
+    if (newsize<0 || size<0) {
+        qh_fprintf(qhmem.ferr, 6236, "qhull error (qh_newhashtable): negative request (%d) or size (%d).  Did int overflow due to high-D?\n", newsize, size); /* WARN64 */
+        qh_errexit(qhmem_ERRmem, NULL, NULL);
+    }
+    if ((size%3) && (size%5))
+      break;
+    size += 2;
+    /* loop terminates because there is an infinite number of primes */
+  }
+  qh hash_table= qh_setnew(size);
+  qh_setzero(qh hash_table, 0, size);
+  return size;
+} /* newhashtable */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="newvertex">-</a>
+
+  qh_newvertex( point )
+    returns a new vertex for point
+*/
+vertexT *qh_newvertex(pointT *point) {
+  vertexT *vertex;
+
+  zinc_(Ztotvertices);
+  vertex= (vertexT *)qh_memalloc((int)sizeof(vertexT));
+  memset((char *) vertex, (size_t)0, sizeof(vertexT));
+  if (qh vertex_id == 0xFFFFFF) {
+    qh_fprintf(qh ferr, 6159, "qhull error: more than %d vertices.  ID field overflows and two vertices\n\
+may have the same identifier.  Vertices will not be sorted correctly.\n", 0xFFFFFF);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  if (qh vertex_id == qh tracevertex_id)
+    qh tracevertex= vertex;
+  vertex->id= qh vertex_id++;
+  vertex->point= point;
+  vertex->dim= (unsigned char)(qh hull_dim <= MAX_vdim ? qh hull_dim : 0);
+  trace4((qh ferr, 4060, "qh_newvertex: vertex p%d(v%d) created\n", qh_pointid(vertex->point),
+          vertex->id));
+  return(vertex);
+} /* newvertex */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="nextridge3d">-</a>
+
+  qh_nextridge3d( atridge, facet, vertex )
+    return next ridge and vertex for a 3d facet
+    returns NULL on error
+    [for QhullFacet::nextRidge3d] Does not call qh_errexit nor access qh_qh.
+
+  notes:
+    in qh_ORIENTclock order
+    this is a O(n^2) implementation to trace all ridges
+    be sure to stop on any 2nd visit
+    same as QhullRidge::nextRidge3d
+    does not use qh_qh or qh_errexit [QhullFacet.cpp]
+
+  design:
+    for each ridge
+      exit if it is the ridge after atridge
+*/
+ridgeT *qh_nextridge3d(ridgeT *atridge, facetT *facet, vertexT **vertexp) {
+  vertexT *atvertex, *vertex, *othervertex;
+  ridgeT *ridge, **ridgep;
+
+  if ((atridge->top == facet) ^ qh_ORIENTclock)
+    atvertex= SETsecondt_(atridge->vertices, vertexT);
+  else
+    atvertex= SETfirstt_(atridge->vertices, vertexT);
+  FOREACHridge_(facet->ridges) {
+    if (ridge == atridge)
+      continue;
+    if ((ridge->top == facet) ^ qh_ORIENTclock) {
+      othervertex= SETsecondt_(ridge->vertices, vertexT);
+      vertex= SETfirstt_(ridge->vertices, vertexT);
+    }else {
+      vertex= SETsecondt_(ridge->vertices, vertexT);
+      othervertex= SETfirstt_(ridge->vertices, vertexT);
+    }
+    if (vertex == atvertex) {
+      if (vertexp)
+        *vertexp= othervertex;
+      return ridge;
+    }
+  }
+  return NULL;
+} /* nextridge3d */
+#else /* qh_NOmerge */
+void qh_matchduplicates(facetT *atfacet, int atskip, int hashsize, int *hashcount) {
+}
+ridgeT *qh_nextridge3d(ridgeT *atridge, facetT *facet, vertexT **vertexp) {
+
+  return NULL;
+}
+#endif /* qh_NOmerge */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="outcoplanar">-</a>
+
+  qh_outcoplanar()
+    move points from all facets' outsidesets to their coplanarsets
+
+  notes:
+    for post-processing under qh.NARROWhull
+
+  design:
+    for each facet
+      for each outside point for facet
+        partition point into coplanar set
+*/
+void qh_outcoplanar(void /* facet_list */) {
+  pointT *point, **pointp;
+  facetT *facet;
+  realT dist;
+
+  trace1((qh ferr, 1033, "qh_outcoplanar: move outsideset to coplanarset for qh NARROWhull\n"));
+  FORALLfacets {
+    FOREACHpoint_(facet->outsideset) {
+      qh num_outside--;
+      if (qh KEEPcoplanar || qh KEEPnearinside) {
+        qh_distplane(point, facet, &dist);
+        zinc_(Zpartition);
+        qh_partitioncoplanar(point, facet, &dist);
+      }
+    }
+    qh_setfree(&facet->outsideset);
+  }
+} /* outcoplanar */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="point">-</a>
+
+  qh_point( id )
+    return point for a point id, or NULL if unknown
+
+  alternative code:
+    return((pointT *)((unsigned   long)qh.first_point
+           + (unsigned long)((id)*qh.normal_size)));
+*/
+pointT *qh_point(int id) {
+
+  if (id < 0)
+    return NULL;
+  if (id < qh num_points)
+    return qh first_point + id * qh hull_dim;
+  id -= qh num_points;
+  if (id < qh_setsize(qh other_points))
+    return SETelemt_(qh other_points, id, pointT);
+  return NULL;
+} /* point */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="point_add">-</a>
+
+  qh_point_add( set, point, elem )
+    stores elem at set[point.id]
+
+  returns:
+    access function for qh_pointfacet and qh_pointvertex
+
+  notes:
+    checks point.id
+*/
+void qh_point_add(setT *set, pointT *point, void *elem) {
+  int id, size;
+
+  SETreturnsize_(set, size);
+  if ((id= qh_pointid(point)) < 0)
+    qh_fprintf(qh ferr, 7067, "qhull internal warning (point_add): unknown point %p id %d\n",
+      point, id);
+  else if (id >= size) {
+    qh_fprintf(qh ferr, 6160, "qhull internal error(point_add): point p%d is out of bounds(%d)\n",
+             id, size);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }else
+    SETelem_(set, id)= elem;
+} /* point_add */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="pointfacet">-</a>
+
+  qh_pointfacet()
+    return temporary set of facet for each point
+    the set is indexed by point id
+
+  notes:
+    vertices assigned to one of the facets
+    coplanarset assigned to the facet
+    outside set assigned to the facet
+    NULL if no facet for point (inside)
+      includes qh.GOODpointp
+
+  access:
+    FOREACHfacet_i_(facets) { ... }
+    SETelem_(facets, i)
+
+  design:
+    for each facet
+      add each vertex
+      add each coplanar point
+      add each outside point
+*/
+setT *qh_pointfacet(void /*qh facet_list*/) {
+  int numpoints= qh num_points + qh_setsize(qh other_points);
+  setT *facets;
+  facetT *facet;
+  vertexT *vertex, **vertexp;
+  pointT *point, **pointp;
+
+  facets= qh_settemp(numpoints);
+  qh_setzero(facets, 0, numpoints);
+  qh vertex_visit++;
+  FORALLfacets {
+    FOREACHvertex_(facet->vertices) {
+      if (vertex->visitid != qh vertex_visit) {
+        vertex->visitid= qh vertex_visit;
+        qh_point_add(facets, vertex->point, facet);
+      }
+    }
+    FOREACHpoint_(facet->coplanarset)
+      qh_point_add(facets, point, facet);
+    FOREACHpoint_(facet->outsideset)
+      qh_point_add(facets, point, facet);
+  }
+  return facets;
+} /* pointfacet */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="pointvertex">-</a>
+
+  qh_pointvertex(  )
+    return temporary set of vertices indexed by point id
+    entry is NULL if no vertex for a point
+      this will include qh.GOODpointp
+
+  access:
+    FOREACHvertex_i_(vertices) { ... }
+    SETelem_(vertices, i)
+*/
+setT *qh_pointvertex(void /*qh facet_list*/) {
+  int numpoints= qh num_points + qh_setsize(qh other_points);
+  setT *vertices;
+  vertexT *vertex;
+
+  vertices= qh_settemp(numpoints);
+  qh_setzero(vertices, 0, numpoints);
+  FORALLvertices
+    qh_point_add(vertices, vertex->point, vertex);
+  return vertices;
+} /* pointvertex */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="prependfacet">-</a>
+
+  qh_prependfacet( facet, facetlist )
+    prepend facet to the start of a facetlist
+
+  returns:
+    increments qh.numfacets
+    updates facetlist, qh.facet_list, facet_next
+
+  notes:
+    be careful of prepending since it can lose a pointer.
+      e.g., can lose _next by deleting and then prepending before _next
+*/
+void qh_prependfacet(facetT *facet, facetT **facetlist) {
+  facetT *prevfacet, *list;
+
+
+  trace4((qh ferr, 4061, "qh_prependfacet: prepend f%d before f%d\n",
+          facet->id, getid_(*facetlist)));
+  if (!*facetlist)
+    (*facetlist)= qh facet_tail;
+  list= *facetlist;
+  prevfacet= list->previous;
+  facet->previous= prevfacet;
+  if (prevfacet)
+    prevfacet->next= facet;
+  list->previous= facet;
+  facet->next= *facetlist;
+  if (qh facet_list == list)  /* this may change *facetlist */
+    qh facet_list= facet;
+  if (qh facet_next == list)
+    qh facet_next= facet;
+  *facetlist= facet;
+  qh num_facets++;
+} /* prependfacet */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="printhashtable">-</a>
+
+  qh_printhashtable( fp )
+    print hash table to fp
+
+  notes:
+    not in I/O to avoid bringing io.c in
+
+  design:
+    for each hash entry
+      if defined
+        if unmatched or will merge (NULL, qh_MERGEridge, qh_DUPLICATEridge)
+          print entry and neighbors
+*/
+void qh_printhashtable(FILE *fp) {
+  facetT *facet, *neighbor;
+  int id, facet_i, facet_n, neighbor_i= 0, neighbor_n= 0;
+  vertexT *vertex, **vertexp;
+
+  FOREACHfacet_i_(qh hash_table) {
+    if (facet) {
+      FOREACHneighbor_i_(facet) {
+        if (!neighbor || neighbor == qh_MERGEridge || neighbor == qh_DUPLICATEridge)
+          break;
+      }
+      if (neighbor_i == neighbor_n)
+        continue;
+      qh_fprintf(fp, 9283, "hash %d f%d ", facet_i, facet->id);
+      FOREACHvertex_(facet->vertices)
+        qh_fprintf(fp, 9284, "v%d ", vertex->id);
+      qh_fprintf(fp, 9285, "\n neighbors:");
+      FOREACHneighbor_i_(facet) {
+        if (neighbor == qh_MERGEridge)
+          id= -3;
+        else if (neighbor == qh_DUPLICATEridge)
+          id= -2;
+        else
+          id= getid_(neighbor);
+        qh_fprintf(fp, 9286, " %d", id);
+      }
+      qh_fprintf(fp, 9287, "\n");
+    }
+  }
+} /* printhashtable */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="printlists">-</a>
+
+  qh_printlists( fp )
+    print out facet and vertex list for debugging (without 'f/v' tags)
+*/
+void qh_printlists(void) {
+  facetT *facet;
+  vertexT *vertex;
+  int count= 0;
+
+  qh_fprintf(qh ferr, 8108, "qh_printlists: facets:");
+  FORALLfacets {
+    if (++count % 100 == 0)
+      qh_fprintf(qh ferr, 8109, "\n     ");
+    qh_fprintf(qh ferr, 8110, " %d", facet->id);
+  }
+  qh_fprintf(qh ferr, 8111, "\n  new facets %d visible facets %d next facet for qh_addpoint %d\n  vertices(new %d):",
+     getid_(qh newfacet_list), getid_(qh visible_list), getid_(qh facet_next),
+     getid_(qh newvertex_list));
+  count = 0;
+  FORALLvertices {
+    if (++count % 100 == 0)
+      qh_fprintf(qh ferr, 8112, "\n     ");
+    qh_fprintf(qh ferr, 8113, " %d", vertex->id);
+  }
+  qh_fprintf(qh ferr, 8114, "\n");
+} /* printlists */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="resetlists">-</a>
+
+  qh_resetlists( stats, qh_RESETvisible )
+    reset newvertex_list, newfacet_list, visible_list
+    if stats,
+      maintains statistics
+
+  returns:
+    visible_list is empty if qh_deletevisible was called
+*/
+void qh_resetlists(boolT stats, boolT resetVisible /*qh newvertex_list newfacet_list visible_list*/) {
+  vertexT *vertex;
+  facetT *newfacet, *visible;
+  int totnew=0, totver=0;
+
+  if (stats) {
+    FORALLvertex_(qh newvertex_list)
+      totver++;
+    FORALLnew_facets
+      totnew++;
+    zadd_(Zvisvertextot, totver);
+    zmax_(Zvisvertexmax, totver);
+    zadd_(Znewfacettot, totnew);
+    zmax_(Znewfacetmax, totnew);
+  }
+  FORALLvertex_(qh newvertex_list)
+    vertex->newlist= False;
+  qh newvertex_list= NULL;
+  FORALLnew_facets
+    newfacet->newfacet= False;
+  qh newfacet_list= NULL;
+  if (resetVisible) {
+    FORALLvisible_facets {
+      visible->f.replace= NULL;
+      visible->visible= False;
+    }
+    qh num_visible= 0;
+  }
+  qh visible_list= NULL; /* may still have visible facets via qh_triangulate */
+  qh NEWfacets= False;
+} /* resetlists */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="setvoronoi_all">-</a>
+
+  qh_setvoronoi_all()
+    compute Voronoi centers for all facets
+    includes upperDelaunay facets if qh.UPPERdelaunay ('Qu')
+
+  returns:
+    facet->center is the Voronoi center
+
+  notes:
+    this is unused/untested code
+      please email bradb at shore.net if this works ok for you
+
+  use:
+    FORALLvertices {...} to locate the vertex for a point.
+    FOREACHneighbor_(vertex) {...} to visit the Voronoi centers for a Voronoi cell.
+*/
+void qh_setvoronoi_all(void) {
+  facetT *facet;
+
+  qh_clearcenters(qh_ASvoronoi);
+  qh_vertexneighbors();
+
+  FORALLfacets {
+    if (!facet->normal || !facet->upperdelaunay || qh UPPERdelaunay) {
+      if (!facet->center)
+        facet->center= qh_facetcenter(facet->vertices);
+    }
+  }
+} /* setvoronoi_all */
+
+#ifndef qh_NOmerge
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="triangulate">-</a>
+
+  qh_triangulate()
+    triangulate non-simplicial facets on qh.facet_list,
+    if qh VORONOI, sets Voronoi centers of non-simplicial facets
+    nop if hasTriangulation
+
+  returns:
+    all facets simplicial
+    each tricoplanar facet has ->f.triowner == owner of ->center,normal,etc.
+
+  notes:
+    call after qh_check_output since may switch to Voronoi centers
+    Output may overwrite ->f.triowner with ->f.area
+*/
+void qh_triangulate(void /*qh facet_list*/) {
+  facetT *facet, *nextfacet, *owner;
+  int onlygood= qh ONLYgood;
+  facetT *neighbor, *visible= NULL, *facet1, *facet2, *new_facet_list= NULL;
+  facetT *orig_neighbor= NULL, *otherfacet;
+  vertexT *new_vertex_list= NULL;
+  mergeT *merge;
+  mergeType mergetype;
+  int neighbor_i, neighbor_n;
+
+  if (qh hasTriangulation)
+      return;
+  trace1((qh ferr, 1034, "qh_triangulate: triangulate non-simplicial facets\n"));
+  if (qh hull_dim == 2)
+    return;
+  if (qh VORONOI) {  /* otherwise lose Voronoi centers [could rebuild vertex set from tricoplanar] */
+    qh_clearcenters(qh_ASvoronoi);
+    qh_vertexneighbors();
+  }
+  qh ONLYgood= False; /* for makenew_nonsimplicial */
+  qh visit_id++;
+  qh NEWfacets= True;
+  qh degen_mergeset= qh_settemp(qh TEMPsize);
+  qh newvertex_list= qh vertex_tail;
+  for (facet= qh facet_list; facet && facet->next; facet= nextfacet) { /* non-simplicial facets moved to end */
+    nextfacet= facet->next;
+    if (facet->visible || facet->simplicial)
+      continue;
+    /* triangulate all non-simplicial facets, otherwise merging does not work, e.g., RBOX c P-0.1 P+0.1 P+0.1 D3 | QHULL d Qt Tv */
+    if (!new_facet_list)
+      new_facet_list= facet;  /* will be moved to end */
+    qh_triangulate_facet(facet, &new_vertex_list);
+  }
+  trace2((qh ferr, 2047, "qh_triangulate: delete null facets from f%d -- apex same as second vertex\n", getid_(new_facet_list)));
+  for (facet= new_facet_list; facet && facet->next; facet= nextfacet) { /* null facets moved to end */
+    nextfacet= facet->next;
+    if (facet->visible)
+      continue;
+    if (facet->ridges) {
+      if (qh_setsize(facet->ridges) > 0) {
+        qh_fprintf(qh ferr, 6161, "qhull error (qh_triangulate): ridges still defined for f%d\n", facet->id);
+        qh_errexit(qh_ERRqhull, facet, NULL);
+      }
+      qh_setfree(&facet->ridges);
+    }
+    if (SETfirst_(facet->vertices) == SETsecond_(facet->vertices)) {
+      zinc_(Ztrinull);
+      qh_triangulate_null(facet);
+    }
+  }
+  trace2((qh ferr, 2048, "qh_triangulate: delete %d or more mirror facets -- same vertices and neighbors\n", qh_setsize(qh degen_mergeset)));
+  qh visible_list= qh facet_tail;
+  while ((merge= (mergeT*)qh_setdellast(qh degen_mergeset))) {
+    facet1= merge->facet1;
+    facet2= merge->facet2;
+    mergetype= merge->type;
+    qh_memfree(merge, (int)sizeof(mergeT));
+    if (mergetype == MRGmirror) {
+      zinc_(Ztrimirror);
+      qh_triangulate_mirror(facet1, facet2);
+    }
+  }
+  qh_settempfree(&qh degen_mergeset);
+  trace2((qh ferr, 2049, "qh_triangulate: update neighbor lists for vertices from v%d\n", getid_(new_vertex_list)));
+  qh newvertex_list= new_vertex_list;  /* all vertices of new facets */
+  qh visible_list= NULL;
+  qh_updatevertices(/*qh newvertex_list, empty newfacet_list and visible_list*/);
+  qh_resetlists(False, !qh_RESETvisible /*qh newvertex_list, empty newfacet_list and visible_list*/);
+
+  trace2((qh ferr, 2050, "qh_triangulate: identify degenerate tricoplanar facets from f%d\n", getid_(new_facet_list)));
+  trace2((qh ferr, 2051, "qh_triangulate: and replace facet->f.triowner with tricoplanar facets that own center, normal, etc.\n"));
+  FORALLfacet_(new_facet_list) {
+    if (facet->tricoplanar && !facet->visible) {
+      FOREACHneighbor_i_(facet) {
+        if (neighbor_i == 0) {  /* first iteration */
+          if (neighbor->tricoplanar)
+            orig_neighbor= neighbor->f.triowner;
+          else
+            orig_neighbor= neighbor;
+        }else {
+          if (neighbor->tricoplanar)
+            otherfacet= neighbor->f.triowner;
+          else
+            otherfacet= neighbor;
+          if (orig_neighbor == otherfacet) {
+            zinc_(Ztridegen);
+            facet->degenerate= True;
+            break;
+          }
+        }
+      }
+    }
+  }
+
+  trace2((qh ferr, 2052, "qh_triangulate: delete visible facets -- non-simplicial, null, and mirrored facets\n"));
+  owner= NULL;
+  visible= NULL;
+  for (facet= new_facet_list; facet && facet->next; facet= nextfacet) { /* may delete facet */
+    nextfacet= facet->next;
+    if (facet->visible) {
+      if (facet->tricoplanar) { /* a null or mirrored facet */
+        qh_delfacet(facet);
+        qh num_visible--;
+      }else {  /* a non-simplicial facet followed by its tricoplanars */
+        if (visible && !owner) {
+          /*  RBOX 200 s D5 t1001471447 | QHULL Qt C-0.01 Qx Qc Tv Qt -- f4483 had 6 vertices/neighbors and 8 ridges */
+          trace2((qh ferr, 2053, "qh_triangulate: all tricoplanar facets degenerate for non-simplicial facet f%d\n",
+                       visible->id));
+          qh_delfacet(visible);
+          qh num_visible--;
+        }
+        visible= facet;
+        owner= NULL;
+      }
+    }else if (facet->tricoplanar) {
+      if (facet->f.triowner != visible) {
+        qh_fprintf(qh ferr, 6162, "qhull error (qh_triangulate): tricoplanar facet f%d not owned by its visible, non-simplicial facet f%d\n", facet->id, getid_(visible));
+        qh_errexit2 (qh_ERRqhull, facet, visible);
+      }
+      if (owner)
+        facet->f.triowner= owner;
+      else if (visible != NULL && !facet->degenerate) {
+        owner= facet;
+        nextfacet= visible->next; /* rescan tricoplanar facets with owner */
+        facet->keepcentrum= True;  /* one facet owns ->normal, etc. */
+        facet->coplanarset= visible->coplanarset;
+        facet->outsideset= visible->outsideset;
+        visible->coplanarset= NULL;
+        visible->outsideset= NULL;
+        if (!qh TRInormals) { /* center and normal copied to tricoplanar facets */
+          visible->center= NULL;
+          visible->normal= NULL;
+        }
+        qh_delfacet(visible);
+        qh num_visible--;
+      }
+    }
+  }
+  if (visible && !owner) {
+    trace2((qh ferr, 2054, "qh_triangulate: all tricoplanar facets degenerate for last non-simplicial facet f%d\n",
+                 visible->id));
+    qh_delfacet(visible);
+    qh num_visible--;
+  }
+  qh NEWfacets= False;
+  qh ONLYgood= onlygood; /* restore value */
+  if (qh CHECKfrequently)
+    qh_checkpolygon(qh facet_list);
+  qh hasTriangulation= True;
+} /* triangulate */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="triangulate_facet">-</a>
+
+  qh_triangulate_facet(facetA)
+    triangulate a non-simplicial facet
+      if qh.CENTERtype=qh_ASvoronoi, sets its Voronoi center
+  returns:
+    qh.newfacet_list == simplicial facets
+      facet->tricoplanar set and ->keepcentrum false
+      facet->degenerate set if duplicated apex
+      facet->f.trivisible set to facetA
+      facet->center copied from facetA (created if qh_ASvoronoi)
+        qh_eachvoronoi, qh_detvridge, qh_detvridge3 assume centers copied
+      facet->normal,offset,maxoutside copied from facetA
+
+  notes:
+      qh_makenew_nonsimplicial uses neighbor->seen for the same
+
+  see also:
+      qh_addpoint() -- add a point
+      qh_makenewfacets() -- construct a cone of facets for a new vertex
+
+  design:
+      if qh_ASvoronoi,
+         compute Voronoi center (facet->center)
+      select first vertex (highest ID to preserve ID ordering of ->vertices)
+      triangulate from vertex to ridges
+      copy facet->center, normal, offset
+      update vertex neighbors
+*/
+void qh_triangulate_facet(facetT *facetA, vertexT **first_vertex) {
+  facetT *newfacet;
+  facetT *neighbor, **neighborp;
+  vertexT *apex;
+  int numnew=0;
+
+  trace3((qh ferr, 3020, "qh_triangulate_facet: triangulate facet f%d\n", facetA->id));
+
+  if (qh IStracing >= 4)
+    qh_printfacet(qh ferr, facetA);
+  FOREACHneighbor_(facetA) {
+    neighbor->seen= False;
+    neighbor->coplanar= False;
+  }
+  if (qh CENTERtype == qh_ASvoronoi && !facetA->center  /* matches upperdelaunay in qh_setfacetplane() */
+        && fabs_(facetA->normal[qh hull_dim -1]) >= qh ANGLEround * qh_ZEROdelaunay) {
+    facetA->center= qh_facetcenter(facetA->vertices);
+  }
+  qh_willdelete(facetA, NULL);
+  qh newfacet_list= qh facet_tail;
+  facetA->visitid= qh visit_id;
+  apex= SETfirstt_(facetA->vertices, vertexT);
+  qh_makenew_nonsimplicial(facetA, apex, &numnew);
+  SETfirst_(facetA->neighbors)= NULL;
+  FORALLnew_facets {
+    newfacet->tricoplanar= True;
+    newfacet->f.trivisible= facetA;
+    newfacet->degenerate= False;
+    newfacet->upperdelaunay= facetA->upperdelaunay;
+    newfacet->good= facetA->good;
+    if (qh TRInormals) {
+      newfacet->keepcentrum= True;
+      newfacet->normal= qh_copypoints(facetA->normal, 1, qh hull_dim);
+      if (qh CENTERtype == qh_AScentrum)
+        newfacet->center= qh_getcentrum(newfacet);
+      else
+        newfacet->center= qh_copypoints(facetA->center, 1, qh hull_dim);
+    }else {
+      newfacet->keepcentrum= False;
+      newfacet->normal= facetA->normal;
+      newfacet->center= facetA->center;
+    }
+    newfacet->offset= facetA->offset;
+#if qh_MAXoutside
+    newfacet->maxoutside= facetA->maxoutside;
+#endif
+  }
+  qh_matchnewfacets(/*qh newfacet_list*/);
+  zinc_(Ztricoplanar);
+  zadd_(Ztricoplanartot, numnew);
+  zmax_(Ztricoplanarmax, numnew);
+  qh visible_list= NULL;
+  if (!(*first_vertex))
+    (*first_vertex)= qh newvertex_list;
+  qh newvertex_list= NULL;
+  qh_updatevertices(/*qh newfacet_list, empty visible_list and newvertex_list*/);
+  qh_resetlists(False, !qh_RESETvisible /*qh newfacet_list, empty visible_list and newvertex_list*/);
+} /* triangulate_facet */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="triangulate_link">-</a>
+
+  qh_triangulate_link(oldfacetA, facetA, oldfacetB, facetB)
+    relink facetA to facetB via oldfacets
+  returns:
+    adds mirror facets to qh degen_mergeset (4-d and up only)
+  design:
+    if they are already neighbors, the opposing neighbors become MRGmirror facets
+*/
+void qh_triangulate_link(facetT *oldfacetA, facetT *facetA, facetT *oldfacetB, facetT *facetB) {
+  int errmirror= False;
+
+  trace3((qh ferr, 3021, "qh_triangulate_link: relink old facets f%d and f%d between neighbors f%d and f%d\n",
+         oldfacetA->id, oldfacetB->id, facetA->id, facetB->id));
+  if (qh_setin(facetA->neighbors, facetB)) {
+    if (!qh_setin(facetB->neighbors, facetA))
+      errmirror= True;
+    else
+      qh_appendmergeset(facetA, facetB, MRGmirror, NULL);
+  }else if (qh_setin(facetB->neighbors, facetA))
+    errmirror= True;
+  if (errmirror) {
+    qh_fprintf(qh ferr, 6163, "qhull error (qh_triangulate_link): mirror facets f%d and f%d do not match for old facets f%d and f%d\n",
+       facetA->id, facetB->id, oldfacetA->id, oldfacetB->id);
+    qh_errexit2 (qh_ERRqhull, facetA, facetB);
+  }
+  qh_setreplace(facetB->neighbors, oldfacetB, facetA);
+  qh_setreplace(facetA->neighbors, oldfacetA, facetB);
+} /* triangulate_link */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="triangulate_mirror">-</a>
+
+  qh_triangulate_mirror(facetA, facetB)
+    delete mirrored facets from qh_triangulate_null() and qh_triangulate_mirror
+      a mirrored facet shares the same vertices of a logical ridge
+  design:
+    since a null facet duplicates the first two vertices, the opposing neighbors absorb the null facet
+    if they are already neighbors, the opposing neighbors become MRGmirror facets
+*/
+void qh_triangulate_mirror(facetT *facetA, facetT *facetB) {
+  facetT *neighbor, *neighborB;
+  int neighbor_i, neighbor_n;
+
+  trace3((qh ferr, 3022, "qh_triangulate_mirror: delete mirrored facets f%d and f%d\n",
+         facetA->id, facetB->id));
+  FOREACHneighbor_i_(facetA) {
+    neighborB= SETelemt_(facetB->neighbors, neighbor_i, facetT);
+    if (neighbor == neighborB)
+      continue; /* occurs twice */
+    qh_triangulate_link(facetA, neighbor, facetB, neighborB);
+  }
+  qh_willdelete(facetA, NULL);
+  qh_willdelete(facetB, NULL);
+} /* triangulate_mirror */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="triangulate_null">-</a>
+
+  qh_triangulate_null(facetA)
+    remove null facetA from qh_triangulate_facet()
+      a null facet has vertex #1 (apex) == vertex #2
+  returns:
+    adds facetA to ->visible for deletion after qh_updatevertices
+    qh degen_mergeset contains mirror facets (4-d and up only)
+  design:
+    since a null facet duplicates the first two vertices, the opposing neighbors absorb the null facet
+    if they are already neighbors, the opposing neighbors become MRGmirror facets
+*/
+void qh_triangulate_null(facetT *facetA) {
+  facetT *neighbor, *otherfacet;
+
+  trace3((qh ferr, 3023, "qh_triangulate_null: delete null facet f%d\n", facetA->id));
+  neighbor= SETfirstt_(facetA->neighbors, facetT);
+  otherfacet= SETsecondt_(facetA->neighbors, facetT);
+  qh_triangulate_link(facetA, neighbor, facetA, otherfacet);
+  qh_willdelete(facetA, NULL);
+} /* triangulate_null */
+
+#else /* qh_NOmerge */
+void qh_triangulate(void) {
+}
+#endif /* qh_NOmerge */
+
+   /*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="vertexintersect">-</a>
+
+  qh_vertexintersect( vertexsetA, vertexsetB )
+    intersects two vertex sets (inverse id ordered)
+    vertexsetA is a temporary set at the top of qhmem.tempstack
+
+  returns:
+    replaces vertexsetA with the intersection
+
+  notes:
+    could overwrite vertexsetA if currently too slow
+*/
+void qh_vertexintersect(setT **vertexsetA,setT *vertexsetB) {
+  setT *intersection;
+
+  intersection= qh_vertexintersect_new(*vertexsetA, vertexsetB);
+  qh_settempfree(vertexsetA);
+  *vertexsetA= intersection;
+  qh_settemppush(intersection);
+} /* vertexintersect */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="vertexintersect_new">-</a>
+
+  qh_vertexintersect_new(  )
+    intersects two vertex sets (inverse id ordered)
+
+  returns:
+    a new set
+*/
+setT *qh_vertexintersect_new(setT *vertexsetA,setT *vertexsetB) {
+  setT *intersection= qh_setnew(qh hull_dim - 1);
+  vertexT **vertexA= SETaddr_(vertexsetA, vertexT);
+  vertexT **vertexB= SETaddr_(vertexsetB, vertexT);
+
+  while (*vertexA && *vertexB) {
+    if (*vertexA  == *vertexB) {
+      qh_setappend(&intersection, *vertexA);
+      vertexA++; vertexB++;
+    }else {
+      if ((*vertexA)->id > (*vertexB)->id)
+        vertexA++;
+      else
+        vertexB++;
+    }
+  }
+  return intersection;
+} /* vertexintersect_new */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="vertexneighbors">-</a>
+
+  qh_vertexneighbors()
+    for each vertex in qh.facet_list,
+      determine its neighboring facets
+
+  returns:
+    sets qh.VERTEXneighbors
+      nop if qh.VERTEXneighbors already set
+      qh_addpoint() will maintain them
+
+  notes:
+    assumes all vertex->neighbors are NULL
+
+  design:
+    for each facet
+      for each vertex
+        append facet to vertex->neighbors
+*/
+void qh_vertexneighbors(void /*qh facet_list*/) {
+  facetT *facet;
+  vertexT *vertex, **vertexp;
+
+  if (qh VERTEXneighbors)
+    return;
+  trace1((qh ferr, 1035, "qh_vertexneighbors: determine neighboring facets for each vertex\n"));
+  qh vertex_visit++;
+  FORALLfacets {
+    if (facet->visible)
+      continue;
+    FOREACHvertex_(facet->vertices) {
+      if (vertex->visitid != qh vertex_visit) {
+        vertex->visitid= qh vertex_visit;
+        vertex->neighbors= qh_setnew(qh hull_dim);
+      }
+      qh_setappend(&vertex->neighbors, facet);
+    }
+  }
+  qh VERTEXneighbors= True;
+} /* vertexneighbors */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="vertexsubset">-</a>
+
+  qh_vertexsubset( vertexsetA, vertexsetB )
+    returns True if vertexsetA is a subset of vertexsetB
+    assumes vertexsets are sorted
+
+  note:
+    empty set is a subset of any other set
+*/
+boolT qh_vertexsubset(setT *vertexsetA, setT *vertexsetB) {
+  vertexT **vertexA= (vertexT **) SETaddr_(vertexsetA, vertexT);
+  vertexT **vertexB= (vertexT **) SETaddr_(vertexsetB, vertexT);
+
+  while (True) {
+    if (!*vertexA)
+      return True;
+    if (!*vertexB)
+      return False;
+    if ((*vertexA)->id > (*vertexB)->id)
+      return False;
+    if (*vertexA  == *vertexB)
+      vertexA++;
+    vertexB++;
+  }
+  return False; /* avoid warnings */
+} /* vertexsubset */
diff --git a/alg/libqhull/qhull_a.h b/alg/libqhull/qhull_a.h
new file mode 100644
index 0000000..e21175f
--- /dev/null
+++ b/alg/libqhull/qhull_a.h
@@ -0,0 +1,151 @@
+/*<html><pre>  -<a                             href="qh-qhull.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   qhull_a.h
+   all header files for compiling qhull
+
+   see qh-qhull.htm
+
+   see libqhull.h for user-level definitions
+
+   see user.h for user-definable constants
+
+   defines internal functions for libqhull.c global.c
+
+   Copyright (c) 1993-2012 The Geometry Center.
+   $Id: //main/2011/qhull/src/libqhull/qhull_a.h#3 $$Change: 1464 $
+   $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+
+   Notes:  grep for ((" and (" to catch fprintf("lkasdjf");
+           full parens around (x?y:z)
+           use '#include qhull/qhull_a.h' to avoid name clashes
+*/
+
+#ifndef qhDEFqhulla
+#define qhDEFqhulla 1
+
+#include "libqhull.h"  /* Defines data types */
+
+#include "stat.h"
+#include "random.h"
+#include "mem.h"
+#include "qset.h"
+#include "geom.h"
+#include "merge.h"
+#include "poly.h"
+#include "io.h"
+
+#include <setjmp.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>    /* some compilers will not need float.h */
+#include <limits.h>
+#include <time.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+/*** uncomment here and qset.c
+     if string.h does not define memcpy()
+#include <memory.h>
+*/
+
+#if qh_CLOCKtype == 2  /* defined in user.h from libqhull.h */
+#include <sys/types.h>
+#include <sys/times.h>
+#include <unistd.h>
+#endif
+
+#ifdef _MSC_VER  /* Microsoft Visual C++ -- warning level 4 */
+#pragma warning( disable : 4100)  /* unreferenced formal parameter */
+#pragma warning( disable : 4127)  /* conditional expression is constant */
+#pragma warning( disable : 4706)  /* assignment within conditional function */
+#pragma warning( disable : 4996)  /* function was declared deprecated(strcpy, localtime, etc.) */
+#endif
+
+/* ======= -macros- =========== */
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >--------------------------------</a><a name="traceN">-</a>
+
+  traceN((qh ferr, 0Nnnn, "format\n", vars));
+    calls qh_fprintf if qh.IStracing >= N
+
+    Add debugging traps to the end of qh_fprintf
+
+  notes:
+    removing tracing reduces code size but doesn't change execution speed
+*/
+#ifndef qh_NOtrace
+#define trace0(args) {if (qh IStracing) qh_fprintf args;}
+#define trace1(args) {if (qh IStracing >= 1) qh_fprintf args;}
+#define trace2(args) {if (qh IStracing >= 2) qh_fprintf args;}
+#define trace3(args) {if (qh IStracing >= 3) qh_fprintf args;}
+#define trace4(args) {if (qh IStracing >= 4) qh_fprintf args;}
+#define trace5(args) {if (qh IStracing >= 5) qh_fprintf args;}
+#else /* qh_NOtrace */
+#define trace0(args) {}
+#define trace1(args) {}
+#define trace2(args) {}
+#define trace3(args) {}
+#define trace4(args) {}
+#define trace5(args) {}
+#endif /* qh_NOtrace */
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >--------------------------------</a><a name="QHULL_UNUSED">-</a>
+
+*/
+
+/* See Qt's qglobal.h */
+#if !defined(SAG_COM) && (defined(WIN64) || defined(_WIN64) || defined(__WIN64__) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__))
+#   define QHULL_OS_WIN
+#elif defined(__MWERKS__) && defined(__INTEL__)
+#   define QHULL_OS_WIN
+#endif
+#if defined(__INTEL_COMPILER) && !defined(QHULL_OS_WIN)
+template <typename T>
+inline void qhullUnused(T &x) { (void)x; }
+#  define QHULL_UNUSED(x) qhullUnused(x);
+#else
+#  define QHULL_UNUSED(x) (void)x;
+#endif
+
+/***** -libqhull.c prototypes (alphabetical after qhull) ********************/
+
+void    qh_qhull(void);
+boolT   qh_addpoint(pointT *furthest, facetT *facet, boolT checkdist);
+void    qh_buildhull(void);
+void    qh_buildtracing(pointT *furthest, facetT *facet);
+void    qh_build_withrestart(void);
+void    qh_errexit2(int exitcode, facetT *facet, facetT *otherfacet);
+void    qh_findhorizon(pointT *point, facetT *facet, int *goodvisible,int *goodhorizon);
+pointT *qh_nextfurthest(facetT **visible);
+void    qh_partitionall(setT *vertices, pointT *points,int npoints);
+void    qh_partitioncoplanar(pointT *point, facetT *facet, realT *dist);
+void    qh_partitionpoint(pointT *point, facetT *facet);
+void    qh_partitionvisible(boolT allpoints, int *numpoints);
+void    qh_precision(const char *reason);
+void    qh_printsummary(FILE *fp);
+
+/***** -global.c internal prototypes (alphabetical) ***********************/
+
+void    qh_appendprint(qh_PRINT format);
+void    qh_freebuild(boolT allmem);
+void    qh_freebuffers(void);
+void    qh_initbuffers(coordT *points, int numpoints, int dim, boolT ismalloc);
+
+/***** -stat.c internal prototypes (alphabetical) ***********************/
+
+void    qh_allstatA(void);
+void    qh_allstatB(void);
+void    qh_allstatC(void);
+void    qh_allstatD(void);
+void    qh_allstatE(void);
+void    qh_allstatE2 (void);
+void    qh_allstatF(void);
+void    qh_allstatG(void);
+void    qh_allstatH(void);
+void    qh_freebuffers(void);
+void    qh_initbuffers(coordT *points, int numpoints, int dim, boolT ismalloc);
+
+#endif /* qhDEFqhulla */
diff --git a/alg/libqhull/qset.c b/alg/libqhull/qset.c
new file mode 100644
index 0000000..532c3ba
--- /dev/null
+++ b/alg/libqhull/qset.c
@@ -0,0 +1,1343 @@
+/*<html><pre>  -<a                             href="qh-set.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   qset.c
+   implements set manipulations needed for quickhull
+
+   see qh-set.htm and qset.h
+
+   Be careful of strict aliasing (two pointers of different types
+   that reference the same location).  The last slot of a set is
+   either the actual size of the set plus 1, or the NULL terminator
+   of the set (i.e., setelemT).
+
+   Copyright (c) 1993-2012 The Geometry Center.
+   $Id: //main/2011/qhull/src/libqhull/qset.c#6 $$Change: 1475 $
+   $DateTime: 2012/01/27 22:32:16 $$Author: bbarber $
+*/
+
+#include "qset.h"
+#include "mem.h"
+#include <stdio.h>
+#include <string.h>
+/*** uncomment here and qhull_a.h
+     if string.h does not define memcpy()
+#include <memory.h>
+*/
+
+#ifndef qhDEFlibqhull
+typedef struct ridgeT ridgeT;
+typedef struct facetT facetT;
+void    qh_errexit(int exitcode, facetT *, ridgeT *);
+void    qh_fprintf(FILE *fp, int msgcode, const char *fmt, ... );
+#  ifdef _MSC_VER  /* Microsoft Visual C++ -- warning level 4 */
+#  pragma warning( disable : 4127)  /* conditional expression is constant */
+#  pragma warning( disable : 4706)  /* assignment within conditional function */
+#  endif
+#endif
+
+/*=============== internal macros ===========================*/
+
+/*============ functions in alphabetical order ===================*/
+
+/*-<a                             href="qh-set.htm#TOC"
+  >--------------------------------<a name="setaddnth">-</a>
+
+  qh_setaddnth( setp, nth, newelem)
+    adds newelem as n'th element of sorted or unsorted *setp
+
+  notes:
+    *setp and newelem must be defined
+    *setp may be a temp set
+    nth=0 is first element
+    errors if nth is out of bounds
+
+  design:
+    expand *setp if empty or full
+    move tail of *setp up one
+    insert newelem
+*/
+void qh_setaddnth(setT **setp, int nth, void *newelem) {
+  int oldsize, i;
+  setelemT *sizep;          /* avoid strict aliasing */
+  setelemT *oldp, *newp;
+
+  if (!*setp || (sizep= SETsizeaddr_(*setp))->i==0) {
+    qh_setlarger(setp);
+    sizep= SETsizeaddr_(*setp);
+  }
+  oldsize= sizep->i - 1;
+  if (nth < 0 || nth > oldsize) {
+    qh_fprintf(qhmem.ferr, 6171, "qhull internal error (qh_setaddnth): nth %d is out-of-bounds for set:\n", nth);
+    qh_setprint(qhmem.ferr, "", *setp);
+    qh_errexit(qhmem_ERRqhull, NULL, NULL);
+  }
+  sizep->i++;
+  oldp= (setelemT *)SETelemaddr_(*setp, oldsize, void);   /* NULL */
+  newp= oldp+1;
+  for (i=oldsize-nth+1; i--; )  /* move at least NULL  */
+    (newp--)->p= (oldp--)->p;       /* may overwrite *sizep */
+  newp->p= newelem;
+} /* setaddnth */
+
+
+/*-<a                              href="qh-set.htm#TOC"
+  >--------------------------------<a name="setaddsorted">-</a>
+
+  setaddsorted( setp, newelem )
+    adds an newelem into sorted *setp
+
+  notes:
+    *setp and newelem must be defined
+    *setp may be a temp set
+    nop if newelem already in set
+
+  design:
+    find newelem's position in *setp
+    insert newelem
+*/
+void qh_setaddsorted(setT **setp, void *newelem) {
+  int newindex=0;
+  void *elem, **elemp;
+
+  FOREACHelem_(*setp) {          /* could use binary search instead */
+    if (elem < newelem)
+      newindex++;
+    else if (elem == newelem)
+      return;
+    else
+      break;
+  }
+  qh_setaddnth(setp, newindex, newelem);
+} /* setaddsorted */
+
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="setappend">-</a>
+
+  qh_setappend( setp, newelem)
+    append newelem to *setp
+
+  notes:
+    *setp may be a temp set
+    *setp and newelem may be NULL
+
+  design:
+    expand *setp if empty or full
+    append newelem to *setp
+
+*/
+void qh_setappend(setT **setp, void *newelem) {
+  setelemT *sizep;  /* Avoid strict aliasing.  Writing to *endp may overwrite *sizep */
+  setelemT *endp;
+  int count;
+
+  if (!newelem)
+    return;
+  if (!*setp || (sizep= SETsizeaddr_(*setp))->i==0) {
+    qh_setlarger(setp);
+    sizep= SETsizeaddr_(*setp);
+  }
+  count= (sizep->i)++ - 1;
+  endp= (setelemT *)SETelemaddr_(*setp, count, void);
+  (endp++)->p= newelem;
+  endp->p= NULL;
+} /* setappend */
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="setappend_set">-</a>
+
+  qh_setappend_set( setp, setA)
+    appends setA to *setp
+
+  notes:
+    *setp can not be a temp set
+    *setp and setA may be NULL
+
+  design:
+    setup for copy
+    expand *setp if it is too small
+    append all elements of setA to *setp
+*/
+void qh_setappend_set(setT **setp, setT *setA) {
+  int sizeA, size;
+  setT *oldset;
+  setelemT *sizep;
+
+  if (!setA)
+    return;
+  SETreturnsize_(setA, sizeA);
+  if (!*setp)
+    *setp= qh_setnew(sizeA);
+  sizep= SETsizeaddr_(*setp);
+  if (!(size= sizep->i))
+    size= (*setp)->maxsize;
+  else
+    size--;
+  if (size + sizeA > (*setp)->maxsize) {
+    oldset= *setp;
+    *setp= qh_setcopy(oldset, sizeA);
+    qh_setfree(&oldset);
+    sizep= SETsizeaddr_(*setp);
+  }
+  if (sizeA > 0) {
+    sizep->i= size+sizeA+1;   /* memcpy may overwrite */
+    memcpy((char *)&((*setp)->e[size].p), (char *)&(setA->e[0].p), (size_t)(sizeA+1) * SETelemsize);
+  }
+} /* setappend_set */
+
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="setappend2ndlast">-</a>
+
+  qh_setappend2ndlast( setp, newelem )
+    makes newelem the next to the last element in *setp
+
+  notes:
+    *setp must have at least one element
+    newelem must be defined
+    *setp may be a temp set
+
+  design:
+    expand *setp if empty or full
+    move last element of *setp up one
+    insert newelem
+*/
+void qh_setappend2ndlast(setT **setp, void *newelem) {
+    setelemT *sizep;  /* Avoid strict aliasing.  Writing to *endp may overwrite *sizep */
+    setelemT *endp, *lastp;
+    int count;
+
+    if (!*setp || (sizep= SETsizeaddr_(*setp))->i==0) {
+        qh_setlarger(setp);
+        sizep= SETsizeaddr_(*setp);
+    }
+    count= (sizep->i)++ - 1;
+    endp= (setelemT *)SETelemaddr_(*setp, count, void); /* NULL */
+    lastp= endp-1;
+    *(endp++)= *lastp;
+    endp->p= NULL;    /* may overwrite *sizep */
+    lastp->p= newelem;
+} /* setappend2ndlast */
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="setcheck">-</a>
+
+  qh_setcheck( set, typename, id )
+    check set for validity
+    report errors with typename and id
+
+  design:
+    checks that maxsize, actual size, and NULL terminator agree
+*/
+void qh_setcheck(setT *set, const char *tname, unsigned id) {
+  int maxsize, size;
+  int waserr= 0;
+
+  if (!set)
+    return;
+  SETreturnsize_(set, size);
+  maxsize= set->maxsize;
+  if (size > maxsize || !maxsize) {
+    qh_fprintf(qhmem.ferr, 6172, "qhull internal error (qh_setcheck): actual size %d of %s%d is greater than max size %d\n",
+             size, tname, id, maxsize);
+    waserr= 1;
+  }else if (set->e[size].p) {
+    qh_fprintf(qhmem.ferr, 6173, "qhull internal error (qh_setcheck): %s%d(size %d max %d) is not null terminated.\n",
+             tname, id, size-1, maxsize);
+    waserr= 1;
+  }
+  if (waserr) {
+    qh_setprint(qhmem.ferr, "ERRONEOUS", set);
+    qh_errexit(qhmem_ERRqhull, NULL, NULL);
+  }
+} /* setcheck */
+
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="setcompact">-</a>
+
+  qh_setcompact( set )
+    remove internal NULLs from an unsorted set
+
+  returns:
+    updated set
+
+  notes:
+    set may be NULL
+    it would be faster to swap tail of set into holes, like qh_setdel
+
+  design:
+    setup pointers into set
+    skip NULLs while copying elements to start of set
+    update the actual size
+*/
+void qh_setcompact(setT *set) {
+  int size;
+  void **destp, **elemp, **endp, **firstp;
+
+  if (!set)
+    return;
+  SETreturnsize_(set, size);
+  destp= elemp= firstp= SETaddr_(set, void);
+  endp= destp + size;
+  while (1) {
+    if (!(*destp++ = *elemp++)) {
+      destp--;
+      if (elemp > endp)
+        break;
+    }
+  }
+  qh_settruncate(set, (int)(destp-firstp));   /* WARN64 */
+} /* setcompact */
+
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="setcopy">-</a>
+
+  qh_setcopy( set, extra )
+    make a copy of a sorted or unsorted set with extra slots
+
+  returns:
+    new set
+
+  design:
+    create a newset with extra slots
+    copy the elements to the newset
+
+*/
+setT *qh_setcopy(setT *set, int extra) {
+  setT *newset;
+  int size;
+
+  if (extra < 0)
+    extra= 0;
+  SETreturnsize_(set, size);
+  newset= qh_setnew(size+extra);
+  SETsizeaddr_(newset)->i= size+1;    /* memcpy may overwrite */
+  memcpy((char *)&(newset->e[0].p), (char *)&(set->e[0].p), (size_t)(size+1) * SETelemsize);
+  return(newset);
+} /* setcopy */
+
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="setdel">-</a>
+
+  qh_setdel( set, oldelem )
+    delete oldelem from an unsorted set
+
+  returns:
+    returns oldelem if found
+    returns NULL otherwise
+
+  notes:
+    set may be NULL
+    oldelem must not be NULL;
+    only deletes one copy of oldelem in set
+
+  design:
+    locate oldelem
+    update actual size if it was full
+    move the last element to the oldelem's location
+*/
+void *qh_setdel(setT *set, void *oldelem) {
+  setelemT *sizep;
+  setelemT *elemp;
+  setelemT *lastp;
+
+  if (!set)
+    return NULL;
+  elemp= (setelemT *)SETaddr_(set, void);
+  while (elemp->p != oldelem && elemp->p)
+    elemp++;
+  if (elemp->p) {
+    sizep= SETsizeaddr_(set);
+    if (!(sizep->i)--)         /*  if was a full set */
+      sizep->i= set->maxsize;  /*     *sizep= (maxsize-1)+ 1 */
+    lastp= (setelemT *)SETelemaddr_(set, sizep->i-1, void);
+    elemp->p= lastp->p;      /* may overwrite itself */
+    lastp->p= NULL;
+    return oldelem;
+  }
+  return NULL;
+} /* setdel */
+
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="setdellast">-</a>
+
+  qh_setdellast( set)
+    return last element of set or NULL
+
+  notes:
+    deletes element from set
+    set may be NULL
+
+  design:
+    return NULL if empty
+    if full set
+      delete last element and set actual size
+    else
+      delete last element and update actual size
+*/
+void *qh_setdellast(setT *set) {
+  int setsize;  /* actually, actual_size + 1 */
+  int maxsize;
+  setelemT *sizep;
+  void *returnvalue;
+
+  if (!set || !(set->e[0].p))
+    return NULL;
+  sizep= SETsizeaddr_(set);
+  if ((setsize= sizep->i)) {
+    returnvalue= set->e[setsize - 2].p;
+    set->e[setsize - 2].p= NULL;
+    sizep->i--;
+  }else {
+    maxsize= set->maxsize;
+    returnvalue= set->e[maxsize - 1].p;
+    set->e[maxsize - 1].p= NULL;
+    sizep->i= maxsize;
+  }
+  return returnvalue;
+} /* setdellast */
+
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="setdelnth">-</a>
+
+  qh_setdelnth( set, nth )
+    deletes nth element from unsorted set
+    0 is first element
+
+  returns:
+    returns the element (needs type conversion)
+
+  notes:
+    errors if nth invalid
+
+  design:
+    setup points and check nth
+    delete nth element and overwrite with last element
+*/
+void *qh_setdelnth(setT *set, int nth) {
+  void *elem;
+  setelemT *sizep;
+  setelemT *elemp, *lastp;
+
+  if (nth < 0) {
+    qh_fprintf(qhmem.ferr, 6174, "qhull internal error (qh_setdelnth): nth %d is out-of-bounds for set:\n", nth);
+    qh_setprint(qhmem.ferr, "", set);
+    qh_errexit(qhmem_ERRqhull, NULL, NULL);
+    nth = 0;
+  }
+  elemp= (setelemT *)SETelemaddr_(set, nth, void);
+  sizep= SETsizeaddr_(set);
+  if ((sizep->i--)==0)         /*  if was a full set */
+    sizep->i= set->maxsize;  /*     *sizep= (maxsize-1)+ 1 */
+  if (nth >= sizep->i) {
+    qh_fprintf(qhmem.ferr, 6174, "qhull internal error (qh_setdelnth): nth %d is out-of-bounds for set:\n", nth);
+    qh_setprint(qhmem.ferr, "", set);
+    qh_errexit(qhmem_ERRqhull, NULL, NULL);
+  }
+  lastp= (setelemT *)SETelemaddr_(set, sizep->i-1, void);
+  elem= elemp->p;
+  elemp->p= lastp->p;      /* may overwrite itself */
+  lastp->p= NULL;
+  return elem;
+} /* setdelnth */
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="setdelnthsorted">-</a>
+
+  qh_setdelnthsorted( set, nth )
+    deletes nth element from sorted set
+
+  returns:
+    returns the element (use type conversion)
+
+  notes:
+    errors if nth invalid
+
+  see also:
+    setnew_delnthsorted
+
+  design:
+    setup points and check nth
+    copy remaining elements down one
+    update actual size
+*/
+void *qh_setdelnthsorted(setT *set, int nth) {
+  void *elem;
+  setelemT *sizep;
+  setelemT *newp, *oldp;
+
+  sizep= SETsizeaddr_(set);
+  if (nth < 0 || (sizep->i && nth >= sizep->i-1) || nth >= set->maxsize) {
+    qh_fprintf(qhmem.ferr, 6175, "qhull internal error (qh_setdelnthsorted): nth %d is out-of-bounds for set:\n", nth);
+    qh_setprint(qhmem.ferr, "", set);
+    qh_errexit(qhmem_ERRqhull, NULL, NULL);
+  }
+  newp= (setelemT *)SETelemaddr_(set, nth, void);
+  elem= newp->p;
+  oldp= newp+1;
+  while (((newp++)->p= (oldp++)->p))
+    ; /* copy remaining elements and NULL */
+  if ((sizep->i--)==0)         /*  if was a full set */
+    sizep->i= set->maxsize;  /*     *sizep= (max size-1)+ 1 */
+  return elem;
+} /* setdelnthsorted */
+
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="setdelsorted">-</a>
+
+  qh_setdelsorted( set, oldelem )
+    deletes oldelem from sorted set
+
+  returns:
+    returns oldelem if it was deleted
+
+  notes:
+    set may be NULL
+
+  design:
+    locate oldelem in set
+    copy remaining elements down one
+    update actual size
+*/
+void *qh_setdelsorted(setT *set, void *oldelem) {
+  setelemT *sizep;
+  setelemT *newp, *oldp;
+
+  if (!set)
+    return NULL;
+  newp= (setelemT *)SETaddr_(set, void);
+  while(newp->p != oldelem && newp->p)
+    newp++;
+  if (newp->p) {
+    oldp= newp+1;
+    while (((newp++)->p= (oldp++)->p))
+      ; /* copy remaining elements */
+    sizep= SETsizeaddr_(set);
+    if ((sizep->i--)==0)    /*  if was a full set */
+      sizep->i= set->maxsize;  /*     *sizep= (max size-1)+ 1 */
+    return oldelem;
+  }
+  return NULL;
+} /* setdelsorted */
+
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="setduplicate">-</a>
+
+  qh_setduplicate( set, elemsize )
+    duplicate a set of elemsize elements
+
+  notes:
+    use setcopy if retaining old elements
+
+  design:
+    create a new set
+    for each elem of the old set
+      create a newelem
+      append newelem to newset
+*/
+setT *qh_setduplicate(setT *set, int elemsize) {
+  void          *elem, **elemp, *newElem;
+  setT          *newSet;
+  int           size;
+
+  if (!(size= qh_setsize(set)))
+    return NULL;
+  newSet= qh_setnew(size);
+  FOREACHelem_(set) {
+    newElem= qh_memalloc(elemsize);
+    memcpy(newElem, elem, (size_t)elemsize);
+    qh_setappend(&newSet, newElem);
+  }
+  return newSet;
+} /* setduplicate */
+
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="setendpointer">-</a>
+
+  qh_setendpointer( set )
+    Returns pointer to NULL terminator of a set's elements
+    set can not be NULL
+
+*/
+void **qh_setendpointer(setT *set) {
+
+  setelemT *sizep= SETsizeaddr_(set);
+  int n= sizep->i;
+  return (n ? &set->e[n-1].p : &sizep->p);
+} /* qh_setendpointer */
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="setequal">-</a>
+
+  qh_setequal(  )
+    returns 1 if two sorted sets are equal, otherwise returns 0
+
+  notes:
+    either set may be NULL
+
+  design:
+    check size of each set
+    setup pointers
+    compare elements of each set
+*/
+int qh_setequal(setT *setA, setT *setB) {
+  void **elemAp, **elemBp;
+  int sizeA= 0, sizeB= 0;
+
+  if (setA) {
+    SETreturnsize_(setA, sizeA);
+  }
+  if (setB) {
+    SETreturnsize_(setB, sizeB);
+  }
+  if (sizeA != sizeB)
+    return 0;
+  if (!sizeA)
+    return 1;
+  elemAp= SETaddr_(setA, void);
+  elemBp= SETaddr_(setB, void);
+  if (!memcmp((char *)elemAp, (char *)elemBp, sizeA*SETelemsize))
+    return 1;
+  return 0;
+} /* setequal */
+
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="setequal_except">-</a>
+
+  qh_setequal_except( setA, skipelemA, setB, skipelemB )
+    returns 1 if sorted setA and setB are equal except for skipelemA & B
+
+  returns:
+    false if either skipelemA or skipelemB are missing
+
+  notes:
+    neither set may be NULL
+
+    if skipelemB is NULL,
+      can skip any one element of setB
+
+  design:
+    setup pointers
+    search for skipelemA, skipelemB, and mismatches
+    check results
+*/
+int qh_setequal_except(setT *setA, void *skipelemA, setT *setB, void *skipelemB) {
+  void **elemA, **elemB;
+  int skip=0;
+
+  elemA= SETaddr_(setA, void);
+  elemB= SETaddr_(setB, void);
+  while (1) {
+    if (*elemA == skipelemA) {
+      skip++;
+      elemA++;
+    }
+    if (skipelemB) {
+      if (*elemB == skipelemB) {
+        skip++;
+        elemB++;
+      }
+    }else if (*elemA != *elemB) {
+      skip++;
+      if (!(skipelemB= *elemB++))
+        return 0;
+    }
+    if (!*elemA)
+      break;
+    if (*elemA++ != *elemB++)
+      return 0;
+  }
+  if (skip != 2 || *elemB)
+    return 0;
+  return 1;
+} /* setequal_except */
+
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="setequal_skip">-</a>
+
+  qh_setequal_skip( setA, skipA, setB, skipB )
+    returns 1 if sorted setA and setB are equal except for elements skipA & B
+
+  returns:
+    false if different size
+
+  notes:
+    neither set may be NULL
+
+  design:
+    setup pointers
+    search for mismatches while skipping skipA and skipB
+*/
+int qh_setequal_skip(setT *setA, int skipA, setT *setB, int skipB) {
+  void **elemA, **elemB, **skipAp, **skipBp;
+
+  elemA= SETaddr_(setA, void);
+  elemB= SETaddr_(setB, void);
+  skipAp= SETelemaddr_(setA, skipA, void);
+  skipBp= SETelemaddr_(setB, skipB, void);
+  while (1) {
+    if (elemA == skipAp)
+      elemA++;
+    if (elemB == skipBp)
+      elemB++;
+    if (!*elemA)
+      break;
+    if (*elemA++ != *elemB++)
+      return 0;
+  }
+  if (*elemB)
+    return 0;
+  return 1;
+} /* setequal_skip */
+
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="setfree">-</a>
+
+  qh_setfree( setp )
+    frees the space occupied by a sorted or unsorted set
+
+  returns:
+    sets setp to NULL
+
+  notes:
+    set may be NULL
+
+  design:
+    free array
+    free set
+*/
+void qh_setfree(setT **setp) {
+  int size;
+  void **freelistp;  /* used !qh_NOmem */
+
+  if (*setp) {
+    size= sizeof(setT) + ((*setp)->maxsize)*SETelemsize;
+    if (size <= qhmem.LASTsize) {
+      qh_memfree_(*setp, size, freelistp);
+    }else
+      qh_memfree(*setp, size);
+    *setp= NULL;
+  }
+} /* setfree */
+
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="setfree2">-</a>
+
+  qh_setfree2( setp, elemsize )
+    frees the space occupied by a set and its elements
+
+  notes:
+    set may be NULL
+
+  design:
+    free each element
+    free set
+*/
+void qh_setfree2 (setT **setp, int elemsize) {
+  void          *elem, **elemp;
+
+  FOREACHelem_(*setp)
+    qh_memfree(elem, elemsize);
+  qh_setfree(setp);
+} /* setfree2 */
+
+
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="setfreelong">-</a>
+
+  qh_setfreelong( setp )
+    frees a set only if it's in long memory
+
+  returns:
+    sets setp to NULL if it is freed
+
+  notes:
+    set may be NULL
+
+  design:
+    if set is large
+      free it
+*/
+void qh_setfreelong(setT **setp) {
+  int size;
+
+  if (*setp) {
+    size= sizeof(setT) + ((*setp)->maxsize)*SETelemsize;
+    if (size > qhmem.LASTsize) {
+      qh_memfree(*setp, size);
+      *setp= NULL;
+    }
+  }
+} /* setfreelong */
+
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="setin">-</a>
+
+  qh_setin( set, setelem )
+    returns 1 if setelem is in a set, 0 otherwise
+
+  notes:
+    set may be NULL or unsorted
+
+  design:
+    scans set for setelem
+*/
+int qh_setin(setT *set, void *setelem) {
+  void *elem, **elemp;
+
+  FOREACHelem_(set) {
+    if (elem == setelem)
+      return 1;
+  }
+  return 0;
+} /* setin */
+
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="setindex">-</a>
+
+  qh_setindex( set, atelem )
+    returns the index of atelem in set.
+    returns -1, if not in set or maxsize wrong
+
+  notes:
+    set may be NULL and may contain nulls.
+    NOerrors returned (qh_pointid, QhullPoint::id)
+
+  design:
+    checks maxsize
+    scans set for atelem
+*/
+int qh_setindex(setT *set, void *atelem) {
+  void **elem;
+  int size, i;
+
+  if (!set)
+    return -1;
+  SETreturnsize_(set, size);
+  if (size > set->maxsize)
+    return -1;
+  elem= SETaddr_(set, void);
+  for (i=0; i < size; i++) {
+    if (*elem++ == atelem)
+      return i;
+  }
+  return -1;
+} /* setindex */
+
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="setlarger">-</a>
+
+  qh_setlarger( oldsetp )
+    returns a larger set that contains all elements of *oldsetp
+
+  notes:
+    the set is at least twice as large
+    if temp set, updates qhmem.tempstack
+
+  design:
+    creates a new set
+    copies the old set to the new set
+    updates pointers in tempstack
+    deletes the old set
+*/
+void qh_setlarger(setT **oldsetp) {
+  int size= 1;
+  setT *newset, *set, **setp, *oldset;
+  setelemT *sizep;
+  setelemT *newp, *oldp;
+
+  if (*oldsetp) {
+    oldset= *oldsetp;
+    SETreturnsize_(oldset, size);
+    qhmem.cntlarger++;
+    qhmem.totlarger += size+1;
+    newset= qh_setnew(2 * size);
+    oldp= (setelemT *)SETaddr_(oldset, void);
+    newp= (setelemT *)SETaddr_(newset, void);
+    memcpy((char *)newp, (char *)oldp, (size_t)(size+1) * SETelemsize);
+    sizep= SETsizeaddr_(newset);
+    sizep->i= size+1;
+    FOREACHset_((setT *)qhmem.tempstack) {
+      if (set == oldset)
+        *(setp-1)= newset;
+    }
+    qh_setfree(oldsetp);
+  }else
+    newset= qh_setnew(3);
+  *oldsetp= newset;
+} /* setlarger */
+
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="setlast">-</a>
+
+  qh_setlast(  )
+    return last element of set or NULL (use type conversion)
+
+  notes:
+    set may be NULL
+
+  design:
+    return last element
+*/
+void *qh_setlast(setT *set) {
+  int size;
+
+  if (set) {
+    size= SETsizeaddr_(set)->i;
+    if (!size)
+      return SETelem_(set, set->maxsize - 1);
+    else if (size > 1)
+      return SETelem_(set, size - 2);
+  }
+  return NULL;
+} /* setlast */
+
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="setnew">-</a>
+
+  qh_setnew( setsize )
+    creates and allocates space for a set
+
+  notes:
+    setsize means the number of elements (!including the NULL terminator)
+    use qh_settemp/qh_setfreetemp if set is temporary
+
+  design:
+    allocate memory for set
+    roundup memory if small set
+    initialize as empty set
+*/
+setT *qh_setnew(int setsize) {
+  setT *set;
+  int sizereceived; /* used !qh_NOmem */
+  int size;
+  void **freelistp; /* used !qh_NOmem */
+
+  if (!setsize)
+    setsize++;
+  size= sizeof(setT) + setsize * SETelemsize;
+  if (size>0 && size <= qhmem.LASTsize) {
+    qh_memalloc_(size, freelistp, set, setT);
+#ifndef qh_NOmem
+    sizereceived= qhmem.sizetable[ qhmem.indextable[size]];
+    if (sizereceived > size)
+      setsize += (sizereceived - size)/SETelemsize;
+#endif
+  }else
+    set= (setT*)qh_memalloc(size);
+  set->maxsize= setsize;
+  set->e[setsize].i= 1;
+  set->e[0].p= NULL;
+  return(set);
+} /* setnew */
+
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="setnew_delnthsorted">-</a>
+
+  qh_setnew_delnthsorted( set, size, nth, prepend )
+    creates a sorted set not containing nth element
+    if prepend, the first prepend elements are undefined
+
+  notes:
+    set must be defined
+    checks nth
+    see also: setdelnthsorted
+
+  design:
+    create new set
+    setup pointers and allocate room for prepend'ed entries
+    append head of old set to new set
+    append tail of old set to new set
+*/
+setT *qh_setnew_delnthsorted(setT *set, int size, int nth, int prepend) {
+  setT *newset;
+  void **oldp, **newp;
+  int tailsize= size - nth -1, newsize;
+
+  if (tailsize < 0) {
+    qh_fprintf(qhmem.ferr, 6176, "qhull internal error (qh_setnew_delnthsorted): nth %d is out-of-bounds for set:\n", nth);
+    qh_setprint(qhmem.ferr, "", set);
+    qh_errexit(qhmem_ERRqhull, NULL, NULL);
+  }
+  newsize= size-1 + prepend;
+  newset= qh_setnew(newsize);
+  newset->e[newset->maxsize].i= newsize+1;  /* may be overwritten */
+  oldp= SETaddr_(set, void);
+  newp= SETaddr_(newset, void) + prepend;
+  switch (nth) {
+  case 0:
+    break;
+  case 1:
+    *(newp++)= *oldp++;
+    break;
+  case 2:
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    break;
+  case 3:
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    break;
+  case 4:
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    break;
+  default:
+    memcpy((char *)newp, (char *)oldp, (size_t)nth * SETelemsize);
+    newp += nth;
+    oldp += nth;
+    break;
+  }
+  oldp++;
+  switch (tailsize) {
+  case 0:
+    break;
+  case 1:
+    *(newp++)= *oldp++;
+    break;
+  case 2:
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    break;
+  case 3:
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    break;
+  case 4:
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    *(newp++)= *oldp++;
+    break;
+  default:
+    memcpy((char *)newp, (char *)oldp, (size_t)tailsize * SETelemsize);
+    newp += tailsize;
+  }
+  *newp= NULL;
+  return(newset);
+} /* setnew_delnthsorted */
+
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="setprint">-</a>
+
+  qh_setprint( fp, string, set )
+    print set elements to fp with identifying string
+
+  notes:
+    never errors
+*/
+void qh_setprint(FILE *fp, const char* string, setT *set) {
+  int size, k;
+
+  if (!set)
+    qh_fprintf(fp, 9346, "%s set is null\n", string);
+  else {
+    SETreturnsize_(set, size);
+    qh_fprintf(fp, 9347, "%s set=%p maxsize=%d size=%d elems=",
+             string, set, set->maxsize, size);
+    if (size > set->maxsize)
+      size= set->maxsize+1;
+    for (k=0; k < size; k++)
+      qh_fprintf(fp, 9348, " %p", set->e[k].p);
+    qh_fprintf(fp, 9349, "\n");
+  }
+} /* setprint */
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="setreplace">-</a>
+
+  qh_setreplace( set, oldelem, newelem )
+    replaces oldelem in set with newelem
+
+  notes:
+    errors if oldelem not in the set
+    newelem may be NULL, but it turns the set into an indexed set (no FOREACH)
+
+  design:
+    find oldelem
+    replace with newelem
+*/
+void qh_setreplace(setT *set, void *oldelem, void *newelem) {
+  void **elemp;
+
+  elemp= SETaddr_(set, void);
+  while (*elemp != oldelem && *elemp)
+    elemp++;
+  if (*elemp)
+    *elemp= newelem;
+  else {
+    qh_fprintf(qhmem.ferr, 6177, "qhull internal error (qh_setreplace): elem %p not found in set\n",
+       oldelem);
+    qh_setprint(qhmem.ferr, "", set);
+    qh_errexit(qhmem_ERRqhull, NULL, NULL);
+  }
+} /* setreplace */
+
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="setsize">-</a>
+
+  qh_setsize( set )
+    returns the size of a set
+
+  notes:
+    errors if set's maxsize is incorrect
+    same as SETreturnsize_(set)
+    same code for qh_setsize [qset.c] and QhullSetBase::count
+
+  design:
+    determine actual size of set from maxsize
+*/
+int qh_setsize(setT *set) {
+  int size;
+  setelemT *sizep;
+
+  if (!set)
+    return(0);
+  sizep= SETsizeaddr_(set);
+  if ((size= sizep->i)) {
+    size--;
+    if (size > set->maxsize) {
+      qh_fprintf(qhmem.ferr, 6178, "qhull internal error (qh_setsize): current set size %d is greater than maximum size %d\n",
+               size, set->maxsize);
+      qh_setprint(qhmem.ferr, "set: ", set);
+      qh_errexit(qhmem_ERRqhull, NULL, NULL);
+    }
+  }else
+    size= set->maxsize;
+  return size;
+} /* setsize */
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="settemp">-</a>
+
+  qh_settemp( setsize )
+    return a stacked, temporary set of up to setsize elements
+
+  notes:
+    use settempfree or settempfree_all to release from qhmem.tempstack
+    see also qh_setnew
+
+  design:
+    allocate set
+    append to qhmem.tempstack
+
+*/
+setT *qh_settemp(int setsize) {
+  setT *newset;
+
+  newset= qh_setnew(setsize);
+  qh_setappend(&qhmem.tempstack, newset);
+  if (qhmem.IStracing >= 5)
+    qh_fprintf(qhmem.ferr, 8123, "qh_settemp: temp set %p of %d elements, depth %d\n",
+       newset, newset->maxsize, qh_setsize(qhmem.tempstack));
+  return newset;
+} /* settemp */
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="settempfree">-</a>
+
+  qh_settempfree( set )
+    free temporary set at top of qhmem.tempstack
+
+  notes:
+    nop if set is NULL
+    errors if set not from previous   qh_settemp
+
+  to locate errors:
+    use 'T2' to find source and then find mismatching qh_settemp
+
+  design:
+    check top of qhmem.tempstack
+    free it
+*/
+void qh_settempfree(setT **set) {
+  setT *stackedset;
+
+  if (!*set)
+    return;
+  stackedset= qh_settemppop();
+  if (stackedset != *set) {
+    qh_settemppush(stackedset);
+    qh_fprintf(qhmem.ferr, 6179, "qhull internal error (qh_settempfree): set %p(size %d) was not last temporary allocated(depth %d, set %p, size %d)\n",
+             *set, qh_setsize(*set), qh_setsize(qhmem.tempstack)+1,
+             stackedset, qh_setsize(stackedset));
+    qh_errexit(qhmem_ERRqhull, NULL, NULL);
+  }
+  qh_setfree(set);
+} /* settempfree */
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="settempfree_all">-</a>
+
+  qh_settempfree_all(  )
+    free all temporary sets in qhmem.tempstack
+
+  design:
+    for each set in tempstack
+      free set
+    free qhmem.tempstack
+*/
+void qh_settempfree_all(void) {
+  setT *set, **setp;
+
+  FOREACHset_(qhmem.tempstack)
+    qh_setfree(&set);
+  qh_setfree(&qhmem.tempstack);
+} /* settempfree_all */
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="settemppop">-</a>
+
+  qh_settemppop(  )
+    pop and return temporary set from qhmem.tempstack
+
+  notes:
+    the returned set is permanent
+
+  design:
+    pop and check top of qhmem.tempstack
+*/
+setT *qh_settemppop(void) {
+  setT *stackedset;
+
+  stackedset= (setT*)qh_setdellast(qhmem.tempstack);
+  if (!stackedset) {
+    qh_fprintf(qhmem.ferr, 6180, "qhull internal error (qh_settemppop): pop from empty temporary stack\n");
+    qh_errexit(qhmem_ERRqhull, NULL, NULL);
+  }
+  if (qhmem.IStracing >= 5)
+    qh_fprintf(qhmem.ferr, 8124, "qh_settemppop: depth %d temp set %p of %d elements\n",
+       qh_setsize(qhmem.tempstack)+1, stackedset, qh_setsize(stackedset));
+  return stackedset;
+} /* settemppop */
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="settemppush">-</a>
+
+  qh_settemppush( set )
+    push temporary set unto qhmem.tempstack (makes it temporary)
+
+  notes:
+    duplicates settemp() for tracing
+
+  design:
+    append set to tempstack
+*/
+void qh_settemppush(setT *set) {
+    if (!set) {
+        fprintf (qhmem.ferr, "qhull error (qh_settemppush): can not push a NULL temp\n");
+        qh_errexit (qhmem_ERRqhull, NULL, NULL);
+    }
+  qh_setappend(&qhmem.tempstack, set);
+  if (qhmem.IStracing >= 5)
+    qh_fprintf(qhmem.ferr, 8125, "qh_settemppush: depth %d temp set %p of %d elements\n",
+      qh_setsize(qhmem.tempstack), set, qh_setsize(set));
+} /* settemppush */
+
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="settruncate">-</a>
+
+  qh_settruncate( set, size )
+    truncate set to size elements
+
+  notes:
+    set must be defined
+
+  see:
+    SETtruncate_
+
+  design:
+    check size
+    update actual size of set
+*/
+void qh_settruncate(setT *set, int size) {
+
+  if (size < 0 || size > set->maxsize) {
+    qh_fprintf(qhmem.ferr, 6181, "qhull internal error (qh_settruncate): size %d out of bounds for set:\n", size);
+    qh_setprint(qhmem.ferr, "", set);
+    qh_errexit(qhmem_ERRqhull, NULL, NULL);
+  }
+  set->e[set->maxsize].i= size+1;   /* maybe overwritten */
+  set->e[size].p= NULL;
+} /* settruncate */
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="setunique">-</a>
+
+  qh_setunique( set, elem )
+    add elem to unsorted set unless it is already in set
+
+  notes:
+    returns 1 if it is appended
+
+  design:
+    if elem not in set
+      append elem to set
+*/
+int qh_setunique(setT **set, void *elem) {
+
+  if (!qh_setin(*set, elem)) {
+    qh_setappend(set, elem);
+    return 1;
+  }
+  return 0;
+} /* setunique */
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="setzero">-</a>
+
+  qh_setzero( set, index, size )
+    zero elements from index on
+    set actual size of set to size
+
+  notes:
+    set must be defined
+    the set becomes an indexed set (can not use FOREACH...)
+
+  see also:
+    qh_settruncate
+
+  design:
+    check index and size
+    update actual size
+    zero elements starting at e[index]
+*/
+void qh_setzero(setT *set, int idx, int size) {
+  int count;
+
+  if (idx < 0 || idx >= size || size > set->maxsize) {
+    qh_fprintf(qhmem.ferr, 6182, "qhull internal error (qh_setzero): index %d or size %d out of bounds for set:\n", idx, size);
+    qh_setprint(qhmem.ferr, "", set);
+    qh_errexit(qhmem_ERRqhull, NULL, NULL);
+  }
+  set->e[set->maxsize].i=  size+1;  /* may be overwritten */
+  count= size - idx + 1;   /* +1 for NULL terminator */
+  memset((char *)SETelemaddr_(set, idx, void), 0, (size_t)count * SETelemsize);
+} /* setzero */
diff --git a/alg/libqhull/qset.h b/alg/libqhull/qset.h
new file mode 100644
index 0000000..759b501
--- /dev/null
+++ b/alg/libqhull/qset.h
@@ -0,0 +1,488 @@
+/*<html><pre>  -<a                             href="qh-set.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   qset.h
+     header file for qset.c that implements set
+
+   see qh-set.htm and qset.c
+
+   only uses mem.c, malloc/free
+
+   for error handling, writes message and calls
+      qh_errexit(qhmem_ERRqhull, NULL, NULL);
+
+   set operations satisfy the following properties:
+    - sets have a max size, the actual size (if different) is stored at the end
+    - every set is NULL terminated
+    - sets may be sorted or unsorted, the caller must distinguish this
+
+   Copyright (c) 1993-2012 The Geometry Center.
+   $Id: //main/2011/qhull/src/libqhull/qset.h#4 $$Change: 1464 $
+   $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+*/
+
+#ifndef qhDEFset
+#define qhDEFset 1
+
+#include <stdio.h>
+
+/*================= -structures- ===============*/
+
+#ifndef DEFsetT
+#define DEFsetT 1
+typedef struct setT setT;   /* a set is a sorted or unsorted array of pointers */
+#endif
+
+/*-<a                                      href="qh-set.htm#TOC"
+>----------------------------------------</a><a name="setT">-</a>
+
+setT
+  a set or list of pointers with maximum size and actual size.
+
+variations:
+  unsorted, unique   -- a list of unique pointers with NULL terminator
+                           user guarantees uniqueness
+  sorted             -- a sorted list of unique pointers with NULL terminator
+                           qset.c guarantees uniqueness
+  unsorted           -- a list of pointers terminated with NULL
+  indexed            -- an array of pointers with NULL elements
+
+structure for set of n elements:
+
+        --------------
+        |  maxsize
+        --------------
+        |  e[0] - a pointer, may be NULL for indexed sets
+        --------------
+        |  e[1]
+
+        --------------
+        |  ...
+        --------------
+        |  e[n-1]
+        --------------
+        |  e[n] = NULL
+        --------------
+        |  ...
+        --------------
+        |  e[maxsize] - n+1 or NULL (determines actual size of set)
+        --------------
+
+*/
+
+/*-- setelemT -- internal type to allow both pointers and indices
+*/
+typedef union setelemT setelemT;
+union setelemT {
+  void    *p;
+  int      i;         /* integer used for e[maxSize] */
+};
+
+struct setT {
+  int maxsize;          /* maximum number of elements (except NULL) */
+  setelemT e[1];        /* array of pointers, tail is NULL */
+                        /* last slot (unless NULL) is actual size+1
+                           e[maxsize]==NULL or e[e[maxsize]-1]==NULL */
+                        /* this may generate a warning since e[] contains
+                           maxsize elements */
+};
+
+/*=========== -constants- =========================*/
+
+/*-<a                                 href="qh-set.htm#TOC"
+  >-----------------------------------</a><a name="SETelemsize">-</a>
+
+  SETelemsize
+    size of a set element in bytes
+*/
+#define SETelemsize ((int)sizeof(setelemT))
+
+
+/*=========== -macros- =========================*/
+
+/*-<a                                 href="qh-set.htm#TOC"
+  >-----------------------------------</a><a name="FOREACHsetelement_">-</a>
+
+   FOREACHsetelement_(type, set, variable)
+     define FOREACH iterator
+
+   declare:
+     assumes *variable and **variablep are declared
+     no space in "variable)" [DEC Alpha cc compiler]
+
+   each iteration:
+     variable is set element
+     variablep is one beyond variable.
+
+   to repeat an element:
+     variablep--; / *repeat* /
+
+   at exit:
+     variable is NULL at end of loop
+
+   example:
+     #define FOREACHfacet_( facets ) FOREACHsetelement_( facetT, facets, facet )
+
+   notes:
+     use FOREACHsetelement_i_() if need index or include NULLs
+
+   WARNING:
+     nested loops can't use the same variable (define another FOREACH)
+
+     needs braces if nested inside another FOREACH
+     this includes intervening blocks, e.g. FOREACH...{ if () FOREACH...} )
+*/
+#define FOREACHsetelement_(type, set, variable) \
+        if (((variable= NULL), set)) for (\
+          variable##p= (type **)&((set)->e[0].p); \
+          (variable= *variable##p++);)
+
+/*-<a                                      href="qh-set.htm#TOC"
+  >----------------------------------------</a><a name="FOREACHsetelement_i_">-</a>
+
+   FOREACHsetelement_i_(type, set, variable)
+     define indexed FOREACH iterator
+
+   declare:
+     type *variable, variable_n, variable_i;
+
+   each iteration:
+     variable is set element, may be NULL
+     variable_i is index, variable_n is qh_setsize()
+
+   to repeat an element:
+     variable_i--; variable_n-- repeats for deleted element
+
+   at exit:
+     variable==NULL and variable_i==variable_n
+
+   example:
+     #define FOREACHfacet_i_( facets ) FOREACHsetelement_i_( facetT, facets, facet )
+
+   WARNING:
+     nested loops can't use the same variable (define another FOREACH)
+
+     needs braces if nested inside another FOREACH
+     this includes intervening blocks, e.g. FOREACH...{ if () FOREACH...} )
+*/
+#define FOREACHsetelement_i_(type, set, variable) \
+        if (((variable= NULL), set)) for (\
+          variable##_i= 0, variable= (type *)((set)->e[0].p), \
+                   variable##_n= qh_setsize(set);\
+          variable##_i < variable##_n;\
+          variable= (type *)((set)->e[++variable##_i].p) )
+
+/*-<a                                    href="qh-set.htm#TOC"
+  >--------------------------------------</a><a name="FOREACHsetelementreverse_">-</a>
+
+   FOREACHsetelementreverse_(type, set, variable)-
+     define FOREACH iterator in reverse order
+
+   declare:
+     assumes *variable and **variablep are declared
+     also declare 'int variabletemp'
+
+   each iteration:
+     variable is set element
+
+   to repeat an element:
+     variabletemp++; / *repeat* /
+
+   at exit:
+     variable is NULL
+
+   example:
+     #define FOREACHvertexreverse_( vertices ) FOREACHsetelementreverse_( vertexT, vertices, vertex )
+
+   notes:
+     use FOREACHsetelementreverse12_() to reverse first two elements
+     WARNING: needs braces if nested inside another FOREACH
+*/
+#define FOREACHsetelementreverse_(type, set, variable) \
+        if (((variable= NULL), set)) for (\
+           variable##temp= qh_setsize(set)-1, variable= qh_setlast(set);\
+           variable; variable= \
+           ((--variable##temp >= 0) ? SETelemt_(set, variable##temp, type) : NULL))
+
+/*-<a                                 href="qh-set.htm#TOC"
+  >-----------------------------------</a><a name="FOREACHsetelementreverse12_">-</a>
+
+   FOREACHsetelementreverse12_(type, set, variable)-
+     define FOREACH iterator with e[1] and e[0] reversed
+
+   declare:
+     assumes *variable and **variablep are declared
+
+   each iteration:
+     variable is set element
+     variablep is one after variable.
+
+   to repeat an element:
+     variablep--; / *repeat* /
+
+   at exit:
+     variable is NULL at end of loop
+
+   example
+     #define FOREACHvertexreverse12_( vertices ) FOREACHsetelementreverse12_( vertexT, vertices, vertex )
+
+   notes:
+     WARNING: needs braces if nested inside another FOREACH
+*/
+#define FOREACHsetelementreverse12_(type, set, variable) \
+        if (((variable= NULL), set)) for (\
+          variable##p= (type **)&((set)->e[1].p); \
+          (variable= *variable##p); \
+          variable##p == ((type **)&((set)->e[0].p))?variable##p += 2: \
+              (variable##p == ((type **)&((set)->e[1].p))?variable##p--:variable##p++))
+
+/*-<a                                 href="qh-set.htm#TOC"
+  >-----------------------------------</a><a name="FOREACHelem_">-</a>
+
+   FOREACHelem_( set )-
+     iterate elements in a set
+
+   declare:
+     void *elem, *elemp;
+
+   each iteration:
+     elem is set element
+     elemp is one beyond
+
+   to repeat an element:
+     elemp--; / *repeat* /
+
+   at exit:
+     elem == NULL at end of loop
+
+   example:
+     FOREACHelem_(set) {
+
+   notes:
+     WARNING: needs braces if nested inside another FOREACH
+*/
+#define FOREACHelem_(set) FOREACHsetelement_(void, set, elem)
+
+/*-<a                                 href="qh-set.htm#TOC"
+  >-----------------------------------</a><a name="FOREACHset_">-</a>
+
+   FOREACHset_( set )-
+     iterate a set of sets
+
+   declare:
+     setT *set, **setp;
+
+   each iteration:
+     set is set element
+     setp is one beyond
+
+   to repeat an element:
+     setp--; / *repeat* /
+
+   at exit:
+     set == NULL at end of loop
+
+   example
+     FOREACHset_(sets) {
+
+   notes:
+     WARNING: needs braces if nested inside another FOREACH
+*/
+#define FOREACHset_(sets) FOREACHsetelement_(setT, sets, set)
+
+/*-<a                                       href="qh-set.htm#TOC"
+  >-----------------------------------------</a><a name="SETindex_">-</a>
+
+   SETindex_( set, elem )
+     return index of elem in set
+
+   notes:
+     for use with FOREACH iteration
+     WARN64 -- Maximum set size is 2G
+
+   example:
+     i= SETindex_(ridges, ridge)
+*/
+#define SETindex_(set, elem) ((int)((void **)elem##p - (void **)&(set)->e[1].p))
+
+/*-<a                                     href="qh-set.htm#TOC"
+  >---------------------------------------</a><a name="SETref_">-</a>
+
+   SETref_( elem )
+     l.h.s. for modifying the current element in a FOREACH iteration
+
+   example:
+     SETref_(ridge)= anotherridge;
+*/
+#define SETref_(elem) (elem##p[-1])
+
+/*-<a                                     href="qh-set.htm#TOC"
+  >---------------------------------------</a><a name="SETelem_">-</a>
+
+   SETelem_(set, n)
+     return the n'th element of set
+
+   notes:
+      assumes that n is valid [0..size] and that set is defined
+      use SETelemt_() for type cast
+*/
+#define SETelem_(set, n)           ((set)->e[n].p)
+
+/*-<a                                     href="qh-set.htm#TOC"
+  >---------------------------------------</a><a name="SETelemt_">-</a>
+
+   SETelemt_(set, n, type)
+     return the n'th element of set as a type
+
+   notes:
+      assumes that n is valid [0..size] and that set is defined
+*/
+#define SETelemt_(set, n, type)    ((type*)((set)->e[n].p))
+
+/*-<a                                     href="qh-set.htm#TOC"
+  >---------------------------------------</a><a name="SETelemaddr_">-</a>
+
+   SETelemaddr_(set, n, type)
+     return address of the n'th element of a set
+
+   notes:
+      assumes that n is valid [0..size] and set is defined
+*/
+#define SETelemaddr_(set, n, type) ((type **)(&((set)->e[n].p)))
+
+/*-<a                                     href="qh-set.htm#TOC"
+  >---------------------------------------</a><a name="SETfirst_">-</a>
+
+   SETfirst_(set)
+     return first element of set
+
+*/
+#define SETfirst_(set)             ((set)->e[0].p)
+
+/*-<a                                     href="qh-set.htm#TOC"
+  >---------------------------------------</a><a name="SETfirstt_">-</a>
+
+   SETfirstt_(set, type)
+     return first element of set as a type
+
+*/
+#define SETfirstt_(set, type)      ((type*)((set)->e[0].p))
+
+/*-<a                                     href="qh-set.htm#TOC"
+  >---------------------------------------</a><a name="SETsecond_">-</a>
+
+   SETsecond_(set)
+     return second element of set
+
+*/
+#define SETsecond_(set)            ((set)->e[1].p)
+
+/*-<a                                     href="qh-set.htm#TOC"
+  >---------------------------------------</a><a name="SETsecondt_">-</a>
+
+   SETsecondt_(set, type)
+     return second element of set as a type
+*/
+#define SETsecondt_(set, type)     ((type*)((set)->e[1].p))
+
+/*-<a                                     href="qh-set.htm#TOC"
+  >---------------------------------------</a><a name="SETaddr_">-</a>
+
+   SETaddr_(set, type)
+       return address of set's elements
+*/
+#define SETaddr_(set,type)         ((type **)(&((set)->e[0].p)))
+
+/*-<a                                     href="qh-set.htm#TOC"
+  >---------------------------------------</a><a name="SETreturnsize_">-</a>
+
+   SETreturnsize_(set, size)
+     return size of a set
+
+   notes:
+      set must be defined
+      use qh_setsize(set) unless speed is critical
+*/
+#define SETreturnsize_(set, size) (((size)= ((set)->e[(set)->maxsize].i))?(--(size)):((size)= (set)->maxsize))
+
+/*-<a                                     href="qh-set.htm#TOC"
+  >---------------------------------------</a><a name="SETempty_">-</a>
+
+   SETempty_(set)
+     return true(1) if set is empty
+
+   notes:
+      set may be NULL
+*/
+#define SETempty_(set)            (!set || (SETfirst_(set) ? 0 : 1))
+
+/*-<a                             href="qh-set.htm#TOC"
+  >-------------------------------<a name="SETsizeaddr_">-</a>
+
+  SETsizeaddr_(set)
+    return pointer to 'actual size+1' of set (set CANNOT be NULL!!)
+    Its type is setelemT* for strict aliasing
+    All SETelemaddr_ must be cast to setelemT
+
+
+  notes:
+    *SETsizeaddr==NULL or e[*SETsizeaddr-1].p==NULL
+*/
+#define SETsizeaddr_(set) (&((set)->e[(set)->maxsize]))
+
+/*-<a                                     href="qh-set.htm#TOC"
+  >---------------------------------------</a><a name="SETtruncate_">-</a>
+
+   SETtruncate_(set, size)
+     truncate set to size
+
+   see:
+     qh_settruncate()
+
+*/
+#define SETtruncate_(set, size) {set->e[set->maxsize].i= size+1; /* maybe overwritten */ \
+      set->e[size].p= NULL;}
+
+/*======= prototypes in alphabetical order ============*/
+
+void  qh_setaddsorted(setT **setp, void *elem);
+void  qh_setaddnth(setT **setp, int nth, void *newelem);
+void  qh_setappend(setT **setp, void *elem);
+void  qh_setappend_set(setT **setp, setT *setA);
+void  qh_setappend2ndlast(setT **setp, void *elem);
+void  qh_setcheck(setT *set, const char *tname, unsigned id);
+void  qh_setcompact(setT *set);
+setT *qh_setcopy(setT *set, int extra);
+void *qh_setdel(setT *set, void *elem);
+void *qh_setdellast(setT *set);
+void *qh_setdelnth(setT *set, int nth);
+void *qh_setdelnthsorted(setT *set, int nth);
+void *qh_setdelsorted(setT *set, void *newelem);
+setT *qh_setduplicate( setT *set, int elemsize);
+int   qh_setequal(setT *setA, setT *setB);
+int   qh_setequal_except(setT *setA, void *skipelemA, setT *setB, void *skipelemB);
+int   qh_setequal_skip(setT *setA, int skipA, setT *setB, int skipB);
+void **qh_setendpointer(setT *set);
+void  qh_setfree(setT **set);
+void  qh_setfree2( setT **setp, int elemsize);
+void  qh_setfreelong(setT **set);
+int   qh_setin(setT *set, void *setelem);
+int   qh_setindex(setT *set, void *setelem);
+void  qh_setlarger(setT **setp);
+void *qh_setlast(setT *set);
+setT *qh_setnew(int size);
+setT *qh_setnew_delnthsorted(setT *set, int size, int nth, int prepend);
+void  qh_setprint(FILE *fp, const char* string, setT *set);
+void  qh_setreplace(setT *set, void *oldelem, void *newelem);
+int   qh_setsize(setT *set);
+setT *qh_settemp(int setsize);
+void  qh_settempfree(setT **set);
+void  qh_settempfree_all(void);
+setT *qh_settemppop(void);
+void  qh_settemppush(setT *set);
+void  qh_settruncate(setT *set, int size);
+int   qh_setunique(setT **set, void *elem);
+void  qh_setzero(setT *set, int idx, int size);
+
+
+#endif /* qhDEFset */
diff --git a/alg/libqhull/random.c b/alg/libqhull/random.c
new file mode 100644
index 0000000..99b0e04
--- /dev/null
+++ b/alg/libqhull/random.c
@@ -0,0 +1,243 @@
+/*<html><pre>  -<a                             href="index.htm#TOC"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   random.c -- utilities
+     Park & Miller's minimal standard random number generator
+     argc/argv conversion
+
+     Used by rbox.  Do not use 'qh'
+*/
+
+#include "libqhull.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef _MSC_VER  /* Microsoft Visual C++ -- warning level 4 */
+#pragma warning( disable : 4706)  /* assignment within conditional function */
+#pragma warning( disable : 4996)  /* function was declared deprecated(strcpy, localtime, etc.) */
+#endif
+
+/*-<a                             href="qh-globa.htm#TOC"
+ >-------------------------------</a><a name="argv_to_command">-</a>
+
+ qh_argv_to_command( argc, argv, command, max_size )
+
+    build command from argc/argv
+    max_size is at least
+
+ returns:
+    a space-delimited string of options (just as typed)
+    returns false if max_size is too short
+
+ notes:
+    silently removes
+    makes option string easy to input and output
+    matches qh_argv_to_command_size()
+
+    argc may be 0
+*/
+int qh_argv_to_command(int argc, char *argv[], char* command, int max_size) {
+  int i, remaining;
+  char *s;
+  *command= '\0';  /* max_size > 0 */
+
+  if (argc) {
+    if ((s= strrchr( argv[0], '\\')) /* get filename w/o .exe extension */
+    || (s= strrchr( argv[0], '/')))
+        s++;
+    else
+        s= argv[0];
+    if ((int)strlen(s) < max_size)   /* WARN64 */
+        strcpy(command, s);
+    else
+        goto error_argv;
+    if ((s= strstr(command, ".EXE"))
+    ||  (s= strstr(command, ".exe")))
+        *s= '\0';
+  }
+  for (i=1; i < argc; i++) {
+    s= argv[i];
+    remaining= max_size - (int)strlen(command) - (int)strlen(s) - 2;   /* WARN64 */
+    if (!*s || strchr(s, ' ')) {
+      char *t= command + strlen(command);
+      remaining -= 2;
+      if (remaining < 0) {
+        goto error_argv;
+      }
+      *t++= ' ';
+      *t++= '"';
+      while (*s) {
+        if (*s == '"') {
+          if (--remaining < 0)
+            goto error_argv;
+          *t++= '\\';
+        }
+        *t++= *s++;
+      }
+      *t++= '"';
+      *t= '\0';
+    }else if (remaining < 0) {
+      goto error_argv;
+    }else
+      strcat(command, " ");
+      strcat(command, s);
+  }
+  return 1;
+
+error_argv:
+  return 0;
+} /* argv_to_command */
+
+/*-<a                             href="qh-globa.htm#TOC"
+>-------------------------------</a><a name="argv_to_command_size">-</a>
+
+qh_argv_to_command_size( argc, argv )
+
+    return size to allocate for qh_argv_to_command()
+
+notes:
+    argc may be 0
+    actual size is usually shorter
+*/
+int qh_argv_to_command_size(int argc, char *argv[]) {
+    unsigned int count= 1; /* null-terminator if argc==0 */
+    int i;
+    char *s;
+
+    for (i=0; i<argc; i++){
+      count += (int)strlen(argv[i]) + 1;   /* WARN64 */
+      if (i>0 && strchr(argv[i], ' ')) {
+        count += 2;  /* quote delimiters */
+        for (s=argv[i]; *s; s++) {
+          if (*s == '"') {
+            count++;
+          }
+        }
+      }
+    }
+    return count;
+} /* argv_to_command_size */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="rand">-</a>
+
+  qh_rand()
+  qh_srand( seed )
+    generate pseudo-random number between 1 and 2^31 -2
+
+  notes:
+    For qhull and rbox, called from qh_RANDOMint(),etc. [user.h]
+
+    From Park & Miller's minimal standard random number generator
+      Communications of the ACM, 31:1192-1201, 1988.
+    Does not use 0 or 2^31 -1
+      this is silently enforced by qh_srand()
+    Can make 'Rn' much faster by moving qh_rand to qh_distplane
+*/
+
+/* Global variables and constants */
+
+int qh_rand_seed= 1;  /* define as global variable instead of using qh */
+
+#define qh_rand_a 16807
+#define qh_rand_m 2147483647
+#define qh_rand_q 127773  /* m div a */
+#define qh_rand_r 2836    /* m mod a */
+
+int qh_rand( void) {
+    int lo, hi, test;
+    int seed = qh_rand_seed;
+
+    hi = seed / qh_rand_q;  /* seed div q */
+    lo = seed % qh_rand_q;  /* seed mod q */
+    test = qh_rand_a * lo - qh_rand_r * hi;
+    if (test > 0)
+        seed= test;
+    else
+        seed= test + qh_rand_m;
+    qh_rand_seed= seed;
+    /* seed = seed < qh_RANDOMmax/2 ? 0 : qh_RANDOMmax;  for testing */
+    /* seed = qh_RANDOMmax;  for testing */
+    return seed;
+} /* rand */
+
+void qh_srand( int seed) {
+    if (seed < 1)
+        qh_rand_seed= 1;
+    else if (seed >= qh_rand_m)
+        qh_rand_seed= qh_rand_m - 1;
+    else
+        qh_rand_seed= seed;
+} /* qh_srand */
+
+/*-<a                             href="qh-geom.htm#TOC"
+>-------------------------------</a><a name="randomfactor">-</a>
+
+qh_randomfactor( scale, offset )
+return a random factor r * scale + offset
+
+notes:
+qh.RANDOMa/b are defined in global.c
+*/
+realT qh_randomfactor(realT scale, realT offset) {
+    realT randr;
+
+    randr= qh_RANDOMint;
+    return randr * scale + offset;
+} /* randomfactor */
+
+/*-<a                             href="qh-geom.htm#TOC"
+>-------------------------------</a><a name="randommatrix">-</a>
+
+qh_randommatrix( buffer, dim, rows )
+generate a random dim X dim matrix in range [-1,1]
+assumes buffer is [dim+1, dim]
+
+returns:
+sets buffer to random numbers
+sets rows to rows of buffer
+sets row[dim] as scratch row
+*/
+void qh_randommatrix(realT *buffer, int dim, realT **rows) {
+    int i, k;
+    realT **rowi, *coord, realr;
+
+    coord= buffer;
+    rowi= rows;
+    for (i=0; i < dim; i++) {
+        *(rowi++)= coord;
+        for (k=0; k < dim; k++) {
+            realr= qh_RANDOMint;
+            *(coord++)= 2.0 * realr/(qh_RANDOMmax+1) - 1.0;
+        }
+    }
+    *rowi= coord;
+} /* randommatrix */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="strtol">-</a>
+
+  qh_strtol( s, endp) qh_strtod( s, endp)
+    internal versions of strtol() and strtod()
+    does not skip trailing spaces
+  notes:
+    some implementations of strtol()/strtod() skip trailing spaces
+*/
+double qh_strtod(const char *s, char **endp) {
+  double result;
+
+  result= strtod(s, endp);
+  if (s < (*endp) && (*endp)[-1] == ' ')
+    (*endp)--;
+  return result;
+} /* strtod */
+
+int qh_strtol(const char *s, char **endp) {
+  int result;
+
+  result= (int) strtol(s, endp, 10);     /* WARN64 */
+  if (s< (*endp) && (*endp)[-1] == ' ')
+    (*endp)--;
+  return result;
+} /* strtol */
diff --git a/alg/libqhull/random.h b/alg/libqhull/random.h
new file mode 100644
index 0000000..87371db
--- /dev/null
+++ b/alg/libqhull/random.h
@@ -0,0 +1,34 @@
+/*<html><pre>  -<a                             href="qh-geom.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+  random.h
+    header file for random routines
+
+   see qh-geom.htm and random.c
+
+   Copyright (c) 1993-2012 The Geometry Center.
+   $Id: //main/2011/qhull/src/libqhull/random.h#3 $$Change: 1464 $
+   $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+*/
+
+#ifndef qhDEFrandom
+#define qhDEFrandom 1
+
+#include "libqhull.h"
+
+/*============= prototypes in alphabetical order ======= */
+
+
+int     qh_argv_to_command(int argc, char *argv[], char* command, int max_size);
+int     qh_argv_to_command_size(int argc, char *argv[]);
+int     qh_rand( void);
+void    qh_srand( int seed);
+realT   qh_randomfactor(realT scale, realT offset);
+void    qh_randommatrix(realT *buffer, int dim, realT **row);
+int     qh_strtol(const char *s, char **endp);
+double  qh_strtod(const char *s, char **endp);
+
+#endif /* qhDEFrandom */
+
+
+
diff --git a/alg/libqhull/rboxlib.c b/alg/libqhull/rboxlib.c
new file mode 100644
index 0000000..d877eba
--- /dev/null
+++ b/alg/libqhull/rboxlib.c
@@ -0,0 +1,793 @@
+/*<html><pre>  -<a                             href="index.htm#TOC"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   rboxlib.c
+     Generate input points
+
+   notes:
+     For documentation, see prompt[] of rbox.c
+     50 points generated for 'rbox D4'
+
+   WARNING:
+     incorrect range if qh_RANDOMmax is defined wrong (user.h)
+*/
+
+#include "random.h"
+#include "libqhull.h"
+
+#include <ctype.h>
+#include <limits.h>
+#include <math.h>
+#include <setjmp.h>
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef _MSC_VER  /* Microsoft Visual C++ */
+#pragma warning( disable : 4706)  /* assignment within conditional expression. */
+#pragma warning( disable : 4996)  /* this function (strncat,sprintf,strcpy) or variable may be unsafe. */
+#endif
+
+#define MAXdim 200
+
+/* ------------------------------ prototypes ----------------*/
+int roundi( double a);
+void out1( double a);
+void out2n( double a, double b);
+void out3n( double a, double b, double c);
+
+void    qh_fprintf_rbox(FILE *fp, int msgcode, const char *fmt, ... );
+void    qh_free(void *mem);
+void   *qh_malloc(size_t size);
+int     qh_rand( void);
+void    qh_srand( int seed);
+
+
+/* ------------------------------ globals -------------------*/
+
+/* No state is carried between rbox requests */
+typedef struct rboxT rboxT;
+struct rboxT {
+  FILE *fout;
+  FILE *ferr;
+  int isinteger;
+  double out_offset;
+  jmp_buf errexit;        /* exit label for rboxpoints, defined by setjmp(), called by qh_errexit_rbox() */
+};
+
+
+int rbox_inuse= 0;
+rboxT rbox;
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >-------------------------------</a><a name="rboxpoints">-</a>
+
+  qh_rboxpoints( fout, ferr, rbox_command )
+    Generate points to fout according to rbox options
+    Report errors on ferr
+
+  returns:
+    0 (qh_ERRnone) on success
+    1 (qh_ERRinput) on input error
+    4 (qh_ERRmem) on memory error
+    5 (qh_ERRqhull) on internal error
+
+  notes:
+    To avoid stdio, redefine qh_malloc, qh_free, and qh_fprintf_rbox (user.c)
+    Rbox is not multithreaded.
+
+  design:
+    Straight line code (consider defining a struct and functions):
+
+    Parse arguments into variables
+    Determine the number of points
+    Generate the points
+*/
+int qh_rboxpoints(FILE* fout, FILE* ferr, char* rbox_command) {
+  int i,j,k;
+  int gendim;
+  int cubesize, diamondsize, seed=0, count, apex;
+  int dim=3 , numpoints= 0, totpoints, addpoints=0;
+  int issphere=0, isaxis=0,  iscdd= 0, islens= 0, isregular=0, iswidth=0, addcube=0;
+  int isgap=0, isspiral=0, NOcommand= 0, adddiamond=0;
+  int israndom=0, istime=0;
+  int isbox=0, issimplex=0, issimplex2=0, ismesh=0;
+  double width=0.0, gap=0.0, radius= 0.0;
+  double coord[MAXdim], offset, meshm=3.0, meshn=4.0, meshr=5.0;
+  double *simplex= NULL, *simplexp;
+  int nthroot, mult[MAXdim];
+  double norm, factor, randr, rangap, lensangle= 0, lensbase= 1;
+  double anglediff, angle, x, y, cube= 0.0, diamond= 0.0;
+  double box= qh_DEFAULTbox; /* scale all numbers before output */
+  double randmax= qh_RANDOMmax;
+  char command[200], seedbuf[200];
+  char *s= command, *t, *first_point= NULL;
+  time_t timedata;
+  int exitcode;
+
+  if (rbox_inuse) {
+    qh_fprintf_rbox(rbox.ferr, 6188, "rbox error: rbox in use by another process.  Please lock calls to rbox.\n");
+    return qh_ERRqhull;
+  }
+  rbox_inuse= True;
+  rbox.ferr= ferr;
+  rbox.fout= fout;
+
+  exitcode= setjmp(rbox.errexit);
+  if (exitcode) {
+    /* same code for error exit and normal return */
+    if (simplex)
+        qh_free(simplex);
+    rbox_inuse= False;
+    return exitcode;
+  }
+
+  *command= '\0';
+  strncat(command, rbox_command, sizeof(command)-strlen(command)-1);
+
+  while (*s && !isspace(*s))  /* skip program name */
+    s++;
+  while (*s) {
+    while (*s && isspace(*s))
+      s++;
+    if (*s == '-')
+      s++;
+    if (!*s)
+      break;
+    if (isdigit(*s)) {
+      numpoints= qh_strtol(s, &s);
+      continue;
+    }
+    /* ============= read flags =============== */
+    switch (*s++) {
+    case 'c':
+      addcube= 1;
+      t= s;
+      while (isspace(*t))
+        t++;
+      if (*t == 'G')
+        cube= qh_strtod(++t, &s);
+      break;
+    case 'd':
+      adddiamond= 1;
+      t= s;
+      while (isspace(*t))
+        t++;
+      if (*t == 'G')
+        diamond= qh_strtod(++t, &s);
+      break;
+    case 'h':
+      iscdd= 1;
+      break;
+    case 'l':
+      isspiral= 1;
+      break;
+    case 'n':
+      NOcommand= 1;
+      break;
+    case 'r':
+      isregular= 1;
+      break;
+    case 's':
+      issphere= 1;
+      break;
+    case 't':
+      istime= 1;
+      if (isdigit(*s)) {
+        seed= qh_strtol(s, &s);
+        israndom= 0;
+      }else
+        israndom= 1;
+      break;
+    case 'x':
+      issimplex= 1;
+      break;
+    case 'y':
+      issimplex2= 1;
+      break;
+    case 'z':
+      rbox.isinteger= 1;
+      break;
+    case 'B':
+      box= qh_strtod(s, &s);
+      isbox= 1;
+      break;
+    case 'D':
+      dim= qh_strtol(s, &s);
+      if (dim < 1
+      || dim > MAXdim) {
+        qh_fprintf_rbox(rbox.ferr, 6189, "rbox error: dimension, D%d, out of bounds (>=%d or <=0)", dim, MAXdim);
+        qh_errexit_rbox(qh_ERRinput);
+      }
+      break;
+    case 'G':
+      if (isdigit(*s))
+        gap= qh_strtod(s, &s);
+      else
+        gap= 0.5;
+      isgap= 1;
+      break;
+    case 'L':
+      if (isdigit(*s))
+        radius= qh_strtod(s, &s);
+      else
+        radius= 10;
+      islens= 1;
+      break;
+    case 'M':
+      ismesh= 1;
+      if (*s)
+        meshn= qh_strtod(s, &s);
+      if (*s == ',') {
+        ++s;
+        meshm= qh_strtod(s, &s);
+      }else
+        meshm= 0.0;
+      if (*s == ',') {
+        ++s;
+        meshr= qh_strtod(s, &s);
+      }else
+        meshr= sqrt(meshn*meshn + meshm*meshm);
+      if (*s && !isspace(*s)) {
+        qh_fprintf_rbox(rbox.ferr, 7069, "rbox warning: assuming 'M3,4,5' since mesh args are not integers or reals\n");
+        meshn= 3.0, meshm=4.0, meshr=5.0;
+      }
+      break;
+    case 'O':
+      rbox.out_offset= qh_strtod(s, &s);
+      break;
+    case 'P':
+      if (!first_point)
+        first_point= s-1;
+      addpoints++;
+      while (*s && !isspace(*s))   /* read points later */
+        s++;
+      break;
+    case 'W':
+      width= qh_strtod(s, &s);
+      iswidth= 1;
+      break;
+    case 'Z':
+      if (isdigit(*s))
+        radius= qh_strtod(s, &s);
+      else
+        radius= 1.0;
+      isaxis= 1;
+      break;
+    default:
+      qh_fprintf_rbox(rbox.ferr, 7070, "rbox error: unknown flag at %s.\nExecute 'rbox' without arguments for documentation.\n", s);
+      qh_errexit_rbox(qh_ERRinput);
+    }
+    if (*s && !isspace(*s)) {
+      qh_fprintf_rbox(rbox.ferr, 7071, "rbox error: missing space between flags at %s.\n", s);
+      qh_errexit_rbox(qh_ERRinput);
+    }
+  }
+
+  /* ============= defaults, constants, and sizes =============== */
+  if (rbox.isinteger && !isbox)
+    box= qh_DEFAULTzbox;
+  if (addcube) {
+    cubesize= (int)floor(ldexp(1.0,dim)+0.5);
+    if (cube == 0.0)
+      cube= box;
+  }else
+    cubesize= 0;
+  if (adddiamond) {
+    diamondsize= 2*dim;
+    if (diamond == 0.0)
+      diamond= box;
+  }else
+    diamondsize= 0;
+  if (islens) {
+    if (isaxis) {
+        qh_fprintf_rbox(rbox.ferr, 6190, "rbox error: can not combine 'Ln' with 'Zn'\n");
+        qh_errexit_rbox(qh_ERRinput);
+    }
+    if (radius <= 1.0) {
+        qh_fprintf_rbox(rbox.ferr, 6191, "rbox error: lens radius %.2g should be greater than 1.0\n",
+               radius);
+        qh_errexit_rbox(qh_ERRinput);
+    }
+    lensangle= asin(1.0/radius);
+    lensbase= radius * cos(lensangle);
+  }
+
+  if (!numpoints) {
+    if (issimplex2)
+        ; /* ok */
+    else if (isregular + issimplex + islens + issphere + isaxis + isspiral + iswidth + ismesh) {
+        qh_fprintf_rbox(rbox.ferr, 6192, "rbox error: missing count\n");
+        qh_errexit_rbox(qh_ERRinput);
+    }else if (adddiamond + addcube + addpoints)
+        ; /* ok */
+    else {
+        numpoints= 50;  /* ./rbox D4 is the test case */
+        issphere= 1;
+    }
+  }
+  if ((issimplex + islens + isspiral + ismesh > 1)
+  || (issimplex + issphere + isspiral + ismesh > 1)) {
+    qh_fprintf_rbox(rbox.ferr, 6193, "rbox error: can only specify one of 'l', 's', 'x', 'Ln', or 'Mn,m,r' ('Ln s' is ok).\n");
+    qh_errexit_rbox(qh_ERRinput);
+  }
+
+  /* ============= print header with total points =============== */
+  if (issimplex || ismesh)
+    totpoints= numpoints;
+  else if (issimplex2)
+    totpoints= numpoints+dim+1;
+  else if (isregular) {
+    totpoints= numpoints;
+    if (dim == 2) {
+        if (islens)
+          totpoints += numpoints - 2;
+    }else if (dim == 3) {
+        if (islens)
+          totpoints += 2 * numpoints;
+      else if (isgap)
+        totpoints += 1 + numpoints;
+      else
+        totpoints += 2;
+    }
+  }else
+    totpoints= numpoints + isaxis;
+  totpoints += cubesize + diamondsize + addpoints;
+
+  /* ============= seed randoms =============== */
+  if (istime == 0) {
+    for (s=command; *s; s++) {
+      if (issimplex2 && *s == 'y') /* make 'y' same seed as 'x' */
+        i= 'x';
+      else
+        i= *s;
+      seed= 11*seed + i;
+    }
+  }else if (israndom) {
+    seed= (int)time(&timedata);
+    sprintf(seedbuf, " t%d", seed);  /* appends an extra t, not worth removing */
+    strncat(command, seedbuf, sizeof(command)-strlen(command)-1);
+    t= strstr(command, " t ");
+    if (t)
+      strcpy(t+1, t+3); /* remove " t " */
+  } /* else, seed explicitly set to n */
+  qh_RANDOMseed_(seed);
+
+  /* ============= print header =============== */
+
+  if (iscdd)
+      qh_fprintf_rbox(rbox.fout, 9391, "%s\nbegin\n        %d %d %s\n",
+      NOcommand ? "" : command,
+      totpoints, dim+1,
+      rbox.isinteger ? "integer" : "real");
+  else if (NOcommand)
+      qh_fprintf_rbox(rbox.fout, 9392, "%d\n%d\n", dim, totpoints);
+  else
+      qh_fprintf_rbox(rbox.fout, 9393, "%d %s\n%d\n", dim, command, totpoints);
+
+  /* ============= explicit points =============== */
+  if ((s= first_point)) {
+    while (s && *s) { /* 'P' */
+      count= 0;
+      if (iscdd)
+        out1( 1.0);
+      while (*++s) {
+        out1( qh_strtod(s, &s));
+        count++;
+        if (isspace(*s) || !*s)
+          break;
+        if (*s != ',') {
+          qh_fprintf_rbox(rbox.ferr, 6194, "rbox error: missing comma after coordinate in %s\n\n", s);
+          qh_errexit_rbox(qh_ERRinput);
+        }
+      }
+      if (count < dim) {
+        for (k=dim-count; k--; )
+          out1( 0.0);
+      }else if (count > dim) {
+        qh_fprintf_rbox(rbox.ferr, 6195, "rbox error: %d coordinates instead of %d coordinates in %s\n\n",
+                  count, dim, s);
+        qh_errexit_rbox(qh_ERRinput);
+      }
+      qh_fprintf_rbox(rbox.fout, 9394, "\n");
+      while ((s= strchr(s, 'P'))) {
+        if (isspace(s[-1]))
+          break;
+      }
+    }
+  }
+
+  /* ============= simplex distribution =============== */
+  if (issimplex+issimplex2) {
+    if (!(simplex= (double*)qh_malloc( dim * (dim+1) * sizeof(double)))) {
+      qh_fprintf_rbox(rbox.ferr, 6196, "rbox error: insufficient memory for simplex\n");
+      qh_errexit_rbox(qh_ERRmem); /* qh_ERRmem */
+    }
+    simplexp= simplex;
+    if (isregular) {
+      for (i=0; i<dim; i++) {
+        for (k=0; k<dim; k++)
+          *(simplexp++)= i==k ? 1.0 : 0.0;
+      }
+      for (k=0; k<dim; k++)
+        *(simplexp++)= -1.0;
+    }else {
+      for (i=0; i<dim+1; i++) {
+        for (k=0; k<dim; k++) {
+          randr= qh_RANDOMint;
+          *(simplexp++)= 2.0 * randr/randmax - 1.0;
+        }
+      }
+    }
+    if (issimplex2) {
+        simplexp= simplex;
+      for (i=0; i<dim+1; i++) {
+        if (iscdd)
+          out1( 1.0);
+        for (k=0; k<dim; k++)
+          out1( *(simplexp++) * box);
+        qh_fprintf_rbox(rbox.fout, 9395, "\n");
+      }
+    }
+    for (j=0; j<numpoints; j++) {
+      if (iswidth)
+        apex= qh_RANDOMint % (dim+1);
+      else
+        apex= -1;
+      for (k=0; k<dim; k++)
+        coord[k]= 0.0;
+      norm= 0.0;
+      for (i=0; i<dim+1; i++) {
+        randr= qh_RANDOMint;
+        factor= randr/randmax;
+        if (i == apex)
+          factor *= width;
+        norm += factor;
+        for (k=0; k<dim; k++) {
+          simplexp= simplex + i*dim + k;
+          coord[k] += factor * (*simplexp);
+        }
+      }
+      for (k=0; k<dim; k++)
+        coord[k] /= norm;
+      if (iscdd)
+        out1( 1.0);
+      for (k=0; k < dim; k++)
+        out1( coord[k] * box);
+      qh_fprintf_rbox(rbox.fout, 9396, "\n");
+    }
+    isregular= 0; /* continue with isbox */
+    numpoints= 0;
+  }
+
+  /* ============= mesh distribution =============== */
+  if (ismesh) {
+    nthroot= (int)(pow((double)numpoints, 1.0/dim) + 0.99999);
+    for (k=dim; k--; )
+      mult[k]= 0;
+    for (i=0; i < numpoints; i++) {
+      for (k=0; k < dim; k++) {
+        if (k == 0)
+          out1( mult[0] * meshn + mult[1] * (-meshm));
+        else if (k == 1)
+          out1( mult[0] * meshm + mult[1] * meshn);
+        else
+          out1( mult[k] * meshr );
+      }
+      qh_fprintf_rbox(rbox.fout, 9397, "\n");
+      for (k=0; k < dim; k++) {
+        if (++mult[k] < nthroot)
+          break;
+        mult[k]= 0;
+      }
+    }
+  }
+  /* ============= regular points for 's' =============== */
+  else if (isregular && !islens) {
+    if (dim != 2 && dim != 3) {
+      qh_fprintf_rbox(rbox.ferr, 6197, "rbox error: regular points can be used only in 2-d and 3-d\n\n");
+      qh_errexit_rbox(qh_ERRinput);
+    }
+    if (!isaxis || radius == 0.0) {
+      isaxis= 1;
+      radius= 1.0;
+    }
+    if (dim == 3) {
+      if (iscdd)
+        out1( 1.0);
+      out3n( 0.0, 0.0, -box);
+      if (!isgap) {
+        if (iscdd)
+          out1( 1.0);
+        out3n( 0.0, 0.0, box);
+      }
+    }
+    angle= 0.0;
+    anglediff= 2.0 * M_PI/numpoints;
+    for (i=0; i < numpoints; i++) {
+      angle += anglediff;
+      x= radius * cos(angle);
+      y= radius * sin(angle);
+      if (dim == 2) {
+        if (iscdd)
+          out1( 1.0);
+        out2n( x*box, y*box);
+      }else {
+        norm= sqrt(1.0 + x*x + y*y);
+        if (iscdd)
+          out1( 1.0);
+        out3n( box*x/norm, box*y/norm, box/norm);
+        if (isgap) {
+          x *= 1-gap;
+          y *= 1-gap;
+          norm= sqrt(1.0 + x*x + y*y);
+          if (iscdd)
+            out1( 1.0);
+          out3n( box*x/norm, box*y/norm, box/norm);
+        }
+      }
+    }
+  }
+  /* ============= regular points for 'r Ln D2' =============== */
+  else if (isregular && islens && dim == 2) {
+    double cos_0;
+
+    angle= lensangle;
+    anglediff= 2 * lensangle/(numpoints - 1);
+    cos_0= cos(lensangle);
+    for (i=0; i < numpoints; i++, angle -= anglediff) {
+      x= radius * sin(angle);
+      y= radius * (cos(angle) - cos_0);
+      if (iscdd)
+        out1( 1.0);
+      out2n( x*box, y*box);
+      if (i != 0 && i != numpoints - 1) {
+        if (iscdd)
+          out1( 1.0);
+        out2n( x*box, -y*box);
+      }
+    }
+  }
+  /* ============= regular points for 'r Ln D3' =============== */
+  else if (isregular && islens && dim != 2) {
+    if (dim != 3) {
+      qh_fprintf_rbox(rbox.ferr, 6198, "rbox error: regular points can be used only in 2-d and 3-d\n\n");
+      qh_errexit_rbox(qh_ERRinput);
+    }
+    angle= 0.0;
+    anglediff= 2* M_PI/numpoints;
+    if (!isgap) {
+      isgap= 1;
+      gap= 0.5;
+    }
+    offset= sqrt(radius * radius - (1-gap)*(1-gap)) - lensbase;
+    for (i=0; i < numpoints; i++, angle += anglediff) {
+      x= cos(angle);
+      y= sin(angle);
+      if (iscdd)
+        out1( 1.0);
+      out3n( box*x, box*y, 0.0);
+      x *= 1-gap;
+      y *= 1-gap;
+      if (iscdd)
+        out1( 1.0);
+      out3n( box*x, box*y, box * offset);
+      if (iscdd)
+        out1( 1.0);
+      out3n( box*x, box*y, -box * offset);
+    }
+  }
+  /* ============= apex of 'Zn' distribution + gendim =============== */
+  else {
+    if (isaxis) {
+      gendim= dim-1;
+      if (iscdd)
+        out1( 1.0);
+      for (j=0; j < gendim; j++)
+        out1( 0.0);
+      out1( -box);
+      qh_fprintf_rbox(rbox.fout, 9398, "\n");
+    }else if (islens)
+      gendim= dim-1;
+    else
+      gendim= dim;
+    /* ============= generate random point in unit cube =============== */
+    for (i=0; i < numpoints; i++) {
+      norm= 0.0;
+      for (j=0; j < gendim; j++) {
+        randr= qh_RANDOMint;
+        coord[j]= 2.0 * randr/randmax - 1.0;
+        norm += coord[j] * coord[j];
+      }
+      norm= sqrt(norm);
+      /* ============= dim-1 point of 'Zn' distribution ========== */
+      if (isaxis) {
+        if (!isgap) {
+          isgap= 1;
+          gap= 1.0;
+        }
+        randr= qh_RANDOMint;
+        rangap= 1.0 - gap * randr/randmax;
+        factor= radius * rangap / norm;
+        for (j=0; j<gendim; j++)
+          coord[j]= factor * coord[j];
+      /* ============= dim-1 point of 'Ln s' distribution =========== */
+      }else if (islens && issphere) {
+        if (!isgap) {
+          isgap= 1;
+          gap= 1.0;
+        }
+        randr= qh_RANDOMint;
+        rangap= 1.0 - gap * randr/randmax;
+        factor= rangap / norm;
+        for (j=0; j<gendim; j++)
+          coord[j]= factor * coord[j];
+      /* ============= dim-1 point of 'Ln' distribution ========== */
+      }else if (islens && !issphere) {
+        if (!isgap) {
+          isgap= 1;
+          gap= 1.0;
+        }
+        j= qh_RANDOMint % gendim;
+        if (coord[j] < 0)
+          coord[j]= -1.0 - coord[j] * gap;
+        else
+          coord[j]= 1.0 - coord[j] * gap;
+      /* ============= point of 'l' distribution =============== */
+      }else if (isspiral) {
+        if (dim != 3) {
+          qh_fprintf_rbox(rbox.ferr, 6199, "rbox error: spiral distribution is available only in 3d\n\n");
+          longjmp(rbox.errexit,qh_ERRinput);
+        }
+        coord[0]= cos(2*M_PI*i/(numpoints - 1));
+        coord[1]= sin(2*M_PI*i/(numpoints - 1));
+        coord[2]= 2.0*(double)i/(double)(numpoints-1) - 1.0;
+      /* ============= point of 's' distribution =============== */
+      }else if (issphere) {
+        factor= 1.0/norm;
+        if (iswidth) {
+          randr= qh_RANDOMint;
+          factor *= 1.0 - width * randr/randmax;
+        }
+        for (j=0; j<dim; j++)
+          coord[j]= factor * coord[j];
+      }
+      /* ============= project 'Zn s' point in to sphere =============== */
+      if (isaxis && issphere) {
+        coord[dim-1]= 1.0;
+        norm= 1.0;
+        for (j=0; j<gendim; j++)
+          norm += coord[j] * coord[j];
+        norm= sqrt(norm);
+        for (j=0; j<dim; j++)
+          coord[j]= coord[j] / norm;
+        if (iswidth) {
+          randr= qh_RANDOMint;
+          coord[dim-1] *= 1 - width * randr/randmax;
+        }
+      /* ============= project 'Zn' point onto cube =============== */
+      }else if (isaxis && !issphere) {  /* not very interesting */
+        randr= qh_RANDOMint;
+        coord[dim-1]= 2.0 * randr/randmax - 1.0;
+      /* ============= project 'Ln' point out to sphere =============== */
+      }else if (islens) {
+        coord[dim-1]= lensbase;
+        for (j=0, norm= 0; j<dim; j++)
+          norm += coord[j] * coord[j];
+        norm= sqrt(norm);
+        for (j=0; j<dim; j++)
+          coord[j]= coord[j] * radius/ norm;
+        coord[dim-1] -= lensbase;
+        if (iswidth) {
+          randr= qh_RANDOMint;
+          coord[dim-1] *= 1 - width * randr/randmax;
+        }
+        if (qh_RANDOMint > randmax/2)
+          coord[dim-1]= -coord[dim-1];
+      /* ============= project 'Wn' point toward boundary =============== */
+      }else if (iswidth && !issphere) {
+        j= qh_RANDOMint % gendim;
+        if (coord[j] < 0)
+          coord[j]= -1.0 - coord[j] * width;
+        else
+          coord[j]= 1.0 - coord[j] * width;
+      }
+      /* ============= write point =============== */
+      if (iscdd)
+        out1( 1.0);
+      for (k=0; k < dim; k++)
+        out1( coord[k] * box);
+      qh_fprintf_rbox(rbox.fout, 9399, "\n");
+    }
+  }
+
+  /* ============= write cube vertices =============== */
+  if (addcube) {
+    for (j=0; j<cubesize; j++) {
+      if (iscdd)
+        out1( 1.0);
+      for (k=dim-1; k>=0; k--) {
+        if (j & ( 1 << k))
+          out1( cube);
+        else
+          out1( -cube);
+      }
+      qh_fprintf_rbox(rbox.fout, 9400, "\n");
+    }
+  }
+
+  /* ============= write diamond vertices =============== */
+  if (adddiamond) {
+    for (j=0; j<diamondsize; j++) {
+      if (iscdd)
+        out1( 1.0);
+      for (k=dim-1; k>=0; k--) {
+        if (j/2 != k)
+          out1( 0.0);
+        else if (j & 0x1)
+          out1( diamond);
+        else
+          out1( -diamond);
+      }
+      qh_fprintf_rbox(rbox.fout, 9401, "\n");
+    }
+  }
+
+  if (iscdd)
+    qh_fprintf_rbox(rbox.fout, 9402, "end\nhull\n");
+
+  /* same code for error exit and normal return */
+  if (simplex)
+    qh_free(simplex);
+  rbox_inuse= False;
+  return qh_ERRnone;
+} /* rboxpoints */
+
+/*------------------------------------------------
+outxxx - output functions
+*/
+int roundi( double a) {
+  if (a < 0.0) {
+    if (a - 0.5 < INT_MIN) {
+      qh_fprintf_rbox(rbox.ferr, 6200, "rbox input error: negative coordinate %2.2g is too large.  Reduce 'Bn'\n", a);
+      qh_errexit_rbox(qh_ERRinput);
+    }
+    return (int)(a - 0.5);
+  }else {
+    if (a + 0.5 > INT_MAX) {
+      qh_fprintf_rbox(rbox.ferr, 6201, "rbox input error: coordinate %2.2g is too large.  Reduce 'Bn'\n", a);
+      qh_errexit_rbox(qh_ERRinput);
+    }
+    return (int)(a + 0.5);
+  }
+} /* roundi */
+
+void out1(double a) {
+
+  if (rbox.isinteger)
+    qh_fprintf_rbox(rbox.fout, 9403, "%d ", roundi( a+rbox.out_offset));
+  else
+    qh_fprintf_rbox(rbox.fout, 9404, qh_REAL_1, a+rbox.out_offset);
+} /* out1 */
+
+void out2n( double a, double b) {
+
+  if (rbox.isinteger)
+    qh_fprintf_rbox(rbox.fout, 9405, "%d %d\n", roundi(a+rbox.out_offset), roundi(b+rbox.out_offset));
+  else
+    qh_fprintf_rbox(rbox.fout, 9406, qh_REAL_2n, a+rbox.out_offset, b+rbox.out_offset);
+} /* out2n */
+
+void out3n( double a, double b, double c) {
+
+  if (rbox.isinteger)
+    qh_fprintf_rbox(rbox.fout, 9407, "%d %d %d\n", roundi(a+rbox.out_offset), roundi(b+rbox.out_offset), roundi(c+rbox.out_offset));
+  else
+    qh_fprintf_rbox(rbox.fout, 9408, qh_REAL_3n, a+rbox.out_offset, b+rbox.out_offset, c+rbox.out_offset);
+} /* out3n */
+
+void qh_errexit_rbox(int exitcode)
+{
+    longjmp(rbox.errexit, exitcode);
+} /* rbox_errexit */
diff --git a/alg/libqhull/stat.c b/alg/libqhull/stat.c
new file mode 100644
index 0000000..183deb3
--- /dev/null
+++ b/alg/libqhull/stat.c
@@ -0,0 +1,714 @@
+/*<html><pre>  -<a                             href="qh-stat.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   stat.c
+   contains all statistics that are collected for qhull
+
+   see qh-stat.htm and stat.h
+
+   Copyright (c) 1993-2012 The Geometry Center.
+   $Id: //main/2011/qhull/src/libqhull/stat.c#3 $$Change: 1464 $
+   $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+*/
+
+#include "qhull_a.h"
+
+/*============ global data structure ==========*/
+
+#if qh_QHpointer
+qhstatT *qh_qhstat=NULL;  /* global data structure */
+#else
+qhstatT qh_qhstat;   /* add "={0}" if this causes a compiler error */
+#endif
+
+/*========== functions in alphabetic order ================*/
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >-------------------------------</a><a name="allstatA">-</a>
+
+  qh_allstatA()
+    define statistics in groups of 20
+
+  notes:
+    (otherwise, 'gcc -O2' uses too much memory)
+    uses qhstat.next
+*/
+void qh_allstatA(void) {
+
+   /* zdef_(type,name,doc,average) */
+  zzdef_(zdoc, Zdoc2, "precision statistics", -1);
+  zdef_(zinc, Znewvertex, NULL, -1);
+  zdef_(wadd, Wnewvertex, "ave. distance of a new vertex to a facet(!0s)", Znewvertex);
+  zzdef_(wmax, Wnewvertexmax, "max. distance of a new vertex to a facet", -1);
+  zdef_(wmax, Wvertexmax, "max. distance of an output vertex to a facet", -1);
+  zdef_(wmin, Wvertexmin, "min. distance of an output vertex to a facet", -1);
+  zdef_(wmin, Wmindenom, "min. denominator in hyperplane computation", -1);
+
+  qhstat precision= qhstat next;  /* call qh_precision for each of these */
+  zzdef_(zdoc, Zdoc3, "precision problems (corrected unless 'Q0' or an error)", -1);
+  zzdef_(zinc, Zcoplanarridges, "coplanar half ridges in output", -1);
+  zzdef_(zinc, Zconcaveridges, "concave half ridges in output", -1);
+  zzdef_(zinc, Zflippedfacets, "flipped facets", -1);
+  zzdef_(zinc, Zcoplanarhorizon, "coplanar horizon facets for new vertices", -1);
+  zzdef_(zinc, Zcoplanarpart, "coplanar points during partitioning", -1);
+  zzdef_(zinc, Zminnorm, "degenerate hyperplanes recomputed with gaussian elimination", -1);
+  zzdef_(zinc, Znearlysingular, "nearly singular or axis-parallel hyperplanes", -1);
+  zzdef_(zinc, Zback0, "zero divisors during back substitute", -1);
+  zzdef_(zinc, Zgauss0, "zero divisors during gaussian elimination", -1);
+  zzdef_(zinc, Zmultiridge, "ridges with multiple neighbors", -1);
+}
+void qh_allstatB(void) {
+  zzdef_(zdoc, Zdoc1, "summary information", -1);
+  zdef_(zinc, Zvertices, "number of vertices in output", -1);
+  zdef_(zinc, Znumfacets, "number of facets in output", -1);
+  zdef_(zinc, Znonsimplicial, "number of non-simplicial facets in output", -1);
+  zdef_(zinc, Znowsimplicial, "number of simplicial facets that were merged", -1);
+  zdef_(zinc, Znumridges, "number of ridges in output", -1);
+  zdef_(zadd, Znumridges, "average number of ridges per facet", Znumfacets);
+  zdef_(zmax, Zmaxridges, "maximum number of ridges", -1);
+  zdef_(zadd, Znumneighbors, "average number of neighbors per facet", Znumfacets);
+  zdef_(zmax, Zmaxneighbors, "maximum number of neighbors", -1);
+  zdef_(zadd, Znumvertices, "average number of vertices per facet", Znumfacets);
+  zdef_(zmax, Zmaxvertices, "maximum number of vertices", -1);
+  zdef_(zadd, Znumvneighbors, "average number of neighbors per vertex", Zvertices);
+  zdef_(zmax, Zmaxvneighbors, "maximum number of neighbors", -1);
+  zdef_(wadd, Wcpu, "cpu seconds for qhull after input", -1);
+  zdef_(zinc, Ztotvertices, "vertices created altogether", -1);
+  zzdef_(zinc, Zsetplane, "facets created altogether", -1);
+  zdef_(zinc, Ztotridges, "ridges created altogether", -1);
+  zdef_(zinc, Zpostfacets, "facets before post merge", -1);
+  zdef_(zadd, Znummergetot, "average merges per facet(at most 511)", Znumfacets);
+  zdef_(zmax, Znummergemax, "  maximum merges for a facet(at most 511)", -1);
+  zdef_(zinc, Zangle, NULL, -1);
+  zdef_(wadd, Wangle, "average angle(cosine) of facet normals for all ridges", Zangle);
+  zdef_(wmax, Wanglemax, "  maximum angle(cosine) of facet normals across a ridge", -1);
+  zdef_(wmin, Wanglemin, "  minimum angle(cosine) of facet normals across a ridge", -1);
+  zdef_(wadd, Wareatot, "total area of facets", -1);
+  zdef_(wmax, Wareamax, "  maximum facet area", -1);
+  zdef_(wmin, Wareamin, "  minimum facet area", -1);
+}
+void qh_allstatC(void) {
+  zdef_(zdoc, Zdoc9, "build hull statistics", -1);
+  zzdef_(zinc, Zprocessed, "points processed", -1);
+  zzdef_(zinc, Zretry, "retries due to precision problems", -1);
+  zdef_(wmax, Wretrymax, "  max. random joggle", -1);
+  zdef_(zmax, Zmaxvertex, "max. vertices at any one time", -1);
+  zdef_(zinc, Ztotvisible, "ave. visible facets per iteration", Zprocessed);
+  zdef_(zinc, Zinsidevisible, "  ave. visible facets without an horizon neighbor", Zprocessed);
+  zdef_(zadd, Zvisfacettot,  "  ave. facets deleted per iteration", Zprocessed);
+  zdef_(zmax, Zvisfacetmax,  "    maximum", -1);
+  zdef_(zadd, Zvisvertextot, "ave. visible vertices per iteration", Zprocessed);
+  zdef_(zmax, Zvisvertexmax, "    maximum", -1);
+  zdef_(zinc, Ztothorizon, "ave. horizon facets per iteration", Zprocessed);
+  zdef_(zadd, Znewfacettot,  "ave. new or merged facets per iteration", Zprocessed);
+  zdef_(zmax, Znewfacetmax,  "    maximum(includes initial simplex)", -1);
+  zdef_(wadd, Wnewbalance, "average new facet balance", Zprocessed);
+  zdef_(wadd, Wnewbalance2, "  standard deviation", -1);
+  zdef_(wadd, Wpbalance, "average partition balance", Zpbalance);
+  zdef_(wadd, Wpbalance2, "  standard deviation", -1);
+  zdef_(zinc, Zpbalance, "  number of trials", -1);
+  zdef_(zinc, Zsearchpoints, "searches of all points for initial simplex", -1);
+  zdef_(zinc, Zdetsimplex, "determinants computed(area & initial hull)", -1);
+  zdef_(zinc, Znoarea, "determinants not computed because vertex too low", -1);
+  zdef_(zinc, Znotmax, "points ignored(!above max_outside)", -1);
+  zdef_(zinc, Znotgood, "points ignored(!above a good facet)", -1);
+  zdef_(zinc, Znotgoodnew, "points ignored(didn't create a good new facet)", -1);
+  zdef_(zinc, Zgoodfacet, "good facets found", -1);
+  zzdef_(zinc, Znumvisibility, "distance tests for facet visibility", -1);
+  zdef_(zinc, Zdistvertex, "distance tests to report minimum vertex", -1);
+  zzdef_(zinc, Ztotcheck, "points checked for facets' outer planes", -1);
+  zzdef_(zinc, Zcheckpart, "  ave. distance tests per check", Ztotcheck);
+}
+void qh_allstatD(void) {
+  zdef_(zinc, Zvisit, "resets of visit_id", -1);
+  zdef_(zinc, Zvvisit, "  resets of vertex_visit", -1);
+  zdef_(zmax, Zvisit2max, "  max visit_id/2", -1);
+  zdef_(zmax, Zvvisit2max, "  max vertex_visit/2", -1);
+
+  zdef_(zdoc, Zdoc4, "partitioning statistics(see previous for outer planes)", -1);
+  zzdef_(zadd, Zdelvertextot, "total vertices deleted", -1);
+  zdef_(zmax, Zdelvertexmax, "    maximum vertices deleted per iteration", -1);
+  zdef_(zinc, Zfindbest, "calls to findbest", -1);
+  zdef_(zadd, Zfindbesttot, " ave. facets tested", Zfindbest);
+  zdef_(zmax, Zfindbestmax, " max. facets tested", -1);
+  zdef_(zadd, Zfindcoplanar, " ave. coplanar search", Zfindbest);
+  zdef_(zinc, Zfindnew, "calls to findbestnew", -1);
+  zdef_(zadd, Zfindnewtot, " ave. facets tested", Zfindnew);
+  zdef_(zmax, Zfindnewmax, " max. facets tested", -1);
+  zdef_(zinc, Zfindnewjump, " ave. clearly better", Zfindnew);
+  zdef_(zinc, Zfindnewsharp, " calls due to qh_sharpnewfacets", -1);
+  zdef_(zinc, Zfindhorizon, "calls to findhorizon", -1);
+  zdef_(zadd, Zfindhorizontot, " ave. facets tested", Zfindhorizon);
+  zdef_(zmax, Zfindhorizonmax, " max. facets tested", -1);
+  zdef_(zinc, Zfindjump,       " ave. clearly better", Zfindhorizon);
+  zdef_(zinc, Zparthorizon, " horizon facets better than bestfacet", -1);
+  zdef_(zinc, Zpartangle, "angle tests for repartitioned coplanar points", -1);
+  zdef_(zinc, Zpartflip, "  repartitioned coplanar points for flipped orientation", -1);
+}
+void qh_allstatE(void) {
+  zdef_(zinc, Zpartinside, "inside points", -1);
+  zdef_(zinc, Zpartnear, "  inside points kept with a facet", -1);
+  zdef_(zinc, Zcoplanarinside, "  inside points that were coplanar with a facet", -1);
+  zdef_(zinc, Zbestlower, "calls to findbestlower", -1);
+  zdef_(zinc, Zbestlowerv, "  with search of vertex neighbors", -1);
+  zdef_(wadd, Wmaxout, "difference in max_outside at final check", -1);
+  zzdef_(zinc, Zpartitionall, "distance tests for initial partition", -1);
+  zdef_(zinc, Ztotpartition, "partitions of a point", -1);
+  zzdef_(zinc, Zpartition, "distance tests for partitioning", -1);
+  zzdef_(zinc, Zdistcheck, "distance tests for checking flipped facets", -1);
+  zzdef_(zinc, Zdistconvex, "distance tests for checking convexity", -1);
+  zdef_(zinc, Zdistgood, "distance tests for checking good point", -1);
+  zdef_(zinc, Zdistio, "distance tests for output", -1);
+  zdef_(zinc, Zdiststat, "distance tests for statistics", -1);
+  zdef_(zinc, Zdistplane, "total number of distance tests", -1);
+  zdef_(zinc, Ztotpartcoplanar, "partitions of coplanar points or deleted vertices", -1);
+  zzdef_(zinc, Zpartcoplanar, "   distance tests for these partitions", -1);
+  zdef_(zinc, Zcomputefurthest, "distance tests for computing furthest", -1);
+}
+void qh_allstatE2(void) {
+  zdef_(zdoc, Zdoc5, "statistics for matching ridges", -1);
+  zdef_(zinc, Zhashlookup, "total lookups for matching ridges of new facets", -1);
+  zdef_(zinc, Zhashtests, "average number of tests to match a ridge", Zhashlookup);
+  zdef_(zinc, Zhashridge, "total lookups of subridges(duplicates and boundary)", -1);
+  zdef_(zinc, Zhashridgetest, "average number of tests per subridge", Zhashridge);
+  zdef_(zinc, Zdupsame, "duplicated ridges in same merge cycle", -1);
+  zdef_(zinc, Zdupflip, "duplicated ridges with flipped facets", -1);
+
+  zdef_(zdoc, Zdoc6, "statistics for determining merges", -1);
+  zdef_(zinc, Zangletests, "angles computed for ridge convexity", -1);
+  zdef_(zinc, Zbestcentrum, "best merges used centrum instead of vertices",-1);
+  zzdef_(zinc, Zbestdist, "distance tests for best merge", -1);
+  zzdef_(zinc, Zcentrumtests, "distance tests for centrum convexity", -1);
+  zzdef_(zinc, Zdistzero, "distance tests for checking simplicial convexity", -1);
+  zdef_(zinc, Zcoplanarangle, "coplanar angles in getmergeset", -1);
+  zdef_(zinc, Zcoplanarcentrum, "coplanar centrums in getmergeset", -1);
+  zdef_(zinc, Zconcaveridge, "concave ridges in getmergeset", -1);
+}
+void qh_allstatF(void) {
+  zdef_(zdoc, Zdoc7, "statistics for merging", -1);
+  zdef_(zinc, Zpremergetot, "merge iterations", -1);
+  zdef_(zadd, Zmergeinittot, "ave. initial non-convex ridges per iteration", Zpremergetot);
+  zdef_(zadd, Zmergeinitmax, "  maximum", -1);
+  zdef_(zadd, Zmergesettot, "  ave. additional non-convex ridges per iteration", Zpremergetot);
+  zdef_(zadd, Zmergesetmax, "  maximum additional in one pass", -1);
+  zdef_(zadd, Zmergeinittot2, "initial non-convex ridges for post merging", -1);
+  zdef_(zadd, Zmergesettot2, "  additional non-convex ridges", -1);
+  zdef_(wmax, Wmaxoutside, "max distance of vertex or coplanar point above facet(w/roundoff)", -1);
+  zdef_(wmin, Wminvertex, "max distance of merged vertex below facet(or roundoff)", -1);
+  zdef_(zinc, Zwidefacet, "centrums frozen due to a wide merge", -1);
+  zdef_(zinc, Zwidevertices, "centrums frozen due to extra vertices", -1);
+  zzdef_(zinc, Ztotmerge, "total number of facets or cycles of facets merged", -1);
+  zdef_(zinc, Zmergesimplex, "merged a simplex", -1);
+  zdef_(zinc, Zonehorizon, "simplices merged into coplanar horizon", -1);
+  zzdef_(zinc, Zcyclehorizon, "cycles of facets merged into coplanar horizon", -1);
+  zzdef_(zadd, Zcyclefacettot, "  ave. facets per cycle", Zcyclehorizon);
+  zdef_(zmax, Zcyclefacetmax, "  max. facets", -1);
+  zdef_(zinc, Zmergeintohorizon, "new facets merged into horizon", -1);
+  zdef_(zinc, Zmergenew, "new facets merged", -1);
+  zdef_(zinc, Zmergehorizon, "horizon facets merged into new facets", -1);
+  zdef_(zinc, Zmergevertex, "vertices deleted by merging", -1);
+  zdef_(zinc, Zcyclevertex, "vertices deleted by merging into coplanar horizon", -1);
+  zdef_(zinc, Zdegenvertex, "vertices deleted by degenerate facet", -1);
+  zdef_(zinc, Zmergeflipdup, "merges due to flipped facets in duplicated ridge", -1);
+  zdef_(zinc, Zneighbor, "merges due to redundant neighbors", -1);
+  zdef_(zadd, Ztestvneighbor, "non-convex vertex neighbors", -1);
+}
+void qh_allstatG(void) {
+  zdef_(zinc, Zacoplanar, "merges due to angle coplanar facets", -1);
+  zdef_(wadd, Wacoplanartot, "  average merge distance", Zacoplanar);
+  zdef_(wmax, Wacoplanarmax, "  maximum merge distance", -1);
+  zdef_(zinc, Zcoplanar, "merges due to coplanar facets", -1);
+  zdef_(wadd, Wcoplanartot, "  average merge distance", Zcoplanar);
+  zdef_(wmax, Wcoplanarmax, "  maximum merge distance", -1);
+  zdef_(zinc, Zconcave, "merges due to concave facets", -1);
+  zdef_(wadd, Wconcavetot, "  average merge distance", Zconcave);
+  zdef_(wmax, Wconcavemax, "  maximum merge distance", -1);
+  zdef_(zinc, Zavoidold, "coplanar/concave merges due to avoiding old merge", -1);
+  zdef_(wadd, Wavoidoldtot, "  average merge distance", Zavoidold);
+  zdef_(wmax, Wavoidoldmax, "  maximum merge distance", -1);
+  zdef_(zinc, Zdegen, "merges due to degenerate facets", -1);
+  zdef_(wadd, Wdegentot, "  average merge distance", Zdegen);
+  zdef_(wmax, Wdegenmax, "  maximum merge distance", -1);
+  zdef_(zinc, Zflipped, "merges due to removing flipped facets", -1);
+  zdef_(wadd, Wflippedtot, "  average merge distance", Zflipped);
+  zdef_(wmax, Wflippedmax, "  maximum merge distance", -1);
+  zdef_(zinc, Zduplicate, "merges due to duplicated ridges", -1);
+  zdef_(wadd, Wduplicatetot, "  average merge distance", Zduplicate);
+  zdef_(wmax, Wduplicatemax, "  maximum merge distance", -1);
+}
+void qh_allstatH(void) {
+  zdef_(zdoc, Zdoc8, "renamed vertex statistics", -1);
+  zdef_(zinc, Zrenameshare, "renamed vertices shared by two facets", -1);
+  zdef_(zinc, Zrenamepinch, "renamed vertices in a pinched facet", -1);
+  zdef_(zinc, Zrenameall, "renamed vertices shared by multiple facets", -1);
+  zdef_(zinc, Zfindfail, "rename failures due to duplicated ridges", -1);
+  zdef_(zinc, Zdupridge, "  duplicate ridges detected", -1);
+  zdef_(zinc, Zdelridge, "deleted ridges due to renamed vertices", -1);
+  zdef_(zinc, Zdropneighbor, "dropped neighbors due to renamed vertices", -1);
+  zdef_(zinc, Zdropdegen, "degenerate facets due to dropped neighbors", -1);
+  zdef_(zinc, Zdelfacetdup, "  facets deleted because of no neighbors", -1);
+  zdef_(zinc, Zremvertex, "vertices removed from facets due to no ridges", -1);
+  zdef_(zinc, Zremvertexdel, "  deleted", -1);
+  zdef_(zinc, Zintersectnum, "vertex intersections for locating redundant vertices", -1);
+  zdef_(zinc, Zintersectfail, "intersections failed to find a redundant vertex", -1);
+  zdef_(zinc, Zintersect, "intersections found redundant vertices", -1);
+  zdef_(zadd, Zintersecttot, "   ave. number found per vertex", Zintersect);
+  zdef_(zmax, Zintersectmax, "   max. found for a vertex", -1);
+  zdef_(zinc, Zvertexridge, NULL, -1);
+  zdef_(zadd, Zvertexridgetot, "  ave. number of ridges per tested vertex", Zvertexridge);
+  zdef_(zmax, Zvertexridgemax, "  max. number of ridges per tested vertex", -1);
+
+  zdef_(zdoc, Zdoc10, "memory usage statistics(in bytes)", -1);
+  zdef_(zadd, Zmemfacets, "for facets and their normals, neighbor and vertex sets", -1);
+  zdef_(zadd, Zmemvertices, "for vertices and their neighbor sets", -1);
+  zdef_(zadd, Zmempoints, "for input points and outside and coplanar sets",-1);
+  zdef_(zadd, Zmemridges, "for ridges and their vertex sets", -1);
+} /* allstat */
+
+void qh_allstatI(void) {
+  qhstat vridges= qhstat next;
+  zzdef_(zdoc, Zdoc11, "Voronoi ridge statistics", -1);
+  zzdef_(zinc, Zridge, "non-simplicial Voronoi vertices for all ridges", -1);
+  zzdef_(wadd, Wridge, "  ave. distance to ridge", Zridge);
+  zzdef_(wmax, Wridgemax, "  max. distance to ridge", -1);
+  zzdef_(zinc, Zridgemid, "bounded ridges", -1);
+  zzdef_(wadd, Wridgemid, "  ave. distance of midpoint to ridge", Zridgemid);
+  zzdef_(wmax, Wridgemidmax, "  max. distance of midpoint to ridge", -1);
+  zzdef_(zinc, Zridgeok, "bounded ridges with ok normal", -1);
+  zzdef_(wadd, Wridgeok, "  ave. angle to ridge", Zridgeok);
+  zzdef_(wmax, Wridgeokmax, "  max. angle to ridge", -1);
+  zzdef_(zinc, Zridge0, "bounded ridges with near-zero normal", -1);
+  zzdef_(wadd, Wridge0, "  ave. angle to ridge", Zridge0);
+  zzdef_(wmax, Wridge0max, "  max. angle to ridge", -1);
+
+  zdef_(zdoc, Zdoc12, "Triangulation statistics(Qt)", -1);
+  zdef_(zinc, Ztricoplanar, "non-simplicial facets triangulated", -1);
+  zdef_(zadd, Ztricoplanartot, "  ave. new facets created(may be deleted)", Ztricoplanar);
+  zdef_(zmax, Ztricoplanarmax, "  max. new facets created", -1);
+  zdef_(zinc, Ztrinull, "null new facets deleted(duplicated vertex)", -1);
+  zdef_(zinc, Ztrimirror, "mirrored pairs of new facets deleted(same vertices)", -1);
+  zdef_(zinc, Ztridegen, "degenerate new facets in output(same ridge)", -1);
+} /* allstat */
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >-------------------------------</a><a name="allstatistics">-</a>
+
+  qh_allstatistics()
+    reset printed flag for all statistics
+*/
+void qh_allstatistics(void) {
+  int i;
+
+  for(i=ZEND; i--; )
+    qhstat printed[i]= False;
+} /* allstatistics */
+
+#if qh_KEEPstatistics
+/*-<a                             href="qh-stat.htm#TOC"
+  >-------------------------------</a><a name="collectstatistics">-</a>
+
+  qh_collectstatistics()
+    collect statistics for qh.facet_list
+
+*/
+void qh_collectstatistics(void) {
+  facetT *facet, *neighbor, **neighborp;
+  vertexT *vertex, **vertexp;
+  realT dotproduct, dist;
+  int sizneighbors, sizridges, sizvertices, i;
+
+  qh old_randomdist= qh RANDOMdist;
+  qh RANDOMdist= False;
+  zval_(Zmempoints)= qh num_points * qh normal_size +
+                             sizeof(qhT) + sizeof(qhstatT);
+  zval_(Zmemfacets)= 0;
+  zval_(Zmemridges)= 0;
+  zval_(Zmemvertices)= 0;
+  zval_(Zangle)= 0;
+  wval_(Wangle)= 0.0;
+  zval_(Znumridges)= 0;
+  zval_(Znumfacets)= 0;
+  zval_(Znumneighbors)= 0;
+  zval_(Znumvertices)= 0;
+  zval_(Znumvneighbors)= 0;
+  zval_(Znummergetot)= 0;
+  zval_(Znummergemax)= 0;
+  zval_(Zvertices)= qh num_vertices - qh_setsize(qh del_vertices);
+  if (qh MERGING || qh APPROXhull || qh JOGGLEmax < REALmax/2)
+    wmax_(Wmaxoutside, qh max_outside);
+  if (qh MERGING)
+    wmin_(Wminvertex, qh min_vertex);
+  FORALLfacets
+    facet->seen= False;
+  if (qh DELAUNAY) {
+    FORALLfacets {
+      if (facet->upperdelaunay != qh UPPERdelaunay)
+        facet->seen= True; /* remove from angle statistics */
+    }
+  }
+  FORALLfacets {
+    if (facet->visible && qh NEWfacets)
+      continue;
+    sizvertices= qh_setsize(facet->vertices);
+    sizneighbors= qh_setsize(facet->neighbors);
+    sizridges= qh_setsize(facet->ridges);
+    zinc_(Znumfacets);
+    zadd_(Znumvertices, sizvertices);
+    zmax_(Zmaxvertices, sizvertices);
+    zadd_(Znumneighbors, sizneighbors);
+    zmax_(Zmaxneighbors, sizneighbors);
+    zadd_(Znummergetot, facet->nummerge);
+    i= facet->nummerge; /* avoid warnings */
+    zmax_(Znummergemax, i);
+    if (!facet->simplicial) {
+      if (sizvertices == qh hull_dim) {
+        zinc_(Znowsimplicial);
+      }else {
+        zinc_(Znonsimplicial);
+      }
+    }
+    if (sizridges) {
+      zadd_(Znumridges, sizridges);
+      zmax_(Zmaxridges, sizridges);
+    }
+    zadd_(Zmemfacets, sizeof(facetT) + qh normal_size + 2*sizeof(setT)
+       + SETelemsize * (sizneighbors + sizvertices));
+    if (facet->ridges) {
+      zadd_(Zmemridges,
+         sizeof(setT) + SETelemsize * sizridges + sizridges *
+         (sizeof(ridgeT) + sizeof(setT) + SETelemsize * (qh hull_dim-1))/2);
+    }
+    if (facet->outsideset)
+      zadd_(Zmempoints, sizeof(setT) + SETelemsize * qh_setsize(facet->outsideset));
+    if (facet->coplanarset)
+      zadd_(Zmempoints, sizeof(setT) + SETelemsize * qh_setsize(facet->coplanarset));
+    if (facet->seen) /* Delaunay upper envelope */
+      continue;
+    facet->seen= True;
+    FOREACHneighbor_(facet) {
+      if (neighbor == qh_DUPLICATEridge || neighbor == qh_MERGEridge
+          || neighbor->seen || !facet->normal || !neighbor->normal)
+        continue;
+      dotproduct= qh_getangle(facet->normal, neighbor->normal);
+      zinc_(Zangle);
+      wadd_(Wangle, dotproduct);
+      wmax_(Wanglemax, dotproduct)
+      wmin_(Wanglemin, dotproduct)
+    }
+    if (facet->normal) {
+      FOREACHvertex_(facet->vertices) {
+        zinc_(Zdiststat);
+        qh_distplane(vertex->point, facet, &dist);
+        wmax_(Wvertexmax, dist);
+        wmin_(Wvertexmin, dist);
+      }
+    }
+  }
+  FORALLvertices {
+    if (vertex->deleted)
+      continue;
+    zadd_(Zmemvertices, sizeof(vertexT));
+    if (vertex->neighbors) {
+      sizneighbors= qh_setsize(vertex->neighbors);
+      zadd_(Znumvneighbors, sizneighbors);
+      zmax_(Zmaxvneighbors, sizneighbors);
+      zadd_(Zmemvertices, sizeof(vertexT) + SETelemsize * sizneighbors);
+    }
+  }
+  qh RANDOMdist= qh old_randomdist;
+} /* collectstatistics */
+#endif /* qh_KEEPstatistics */
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >-------------------------------</a><a name="freestatistics">-</a>
+
+  qh_freestatistics(  )
+    free memory used for statistics
+*/
+void qh_freestatistics(void) {
+
+#if qh_QHpointer
+  qh_free(qh_qhstat);
+  qh_qhstat= NULL;
+#endif
+} /* freestatistics */
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >-------------------------------</a><a name="initstatistics">-</a>
+
+  qh_initstatistics(  )
+    allocate and initialize statistics
+
+  notes:
+    uses qh_malloc() instead of qh_memalloc() since mem.c not set up yet
+    NOerrors -- qh_initstatistics can not use qh_errexit().  One first call, qh_memalloc is not initialized.  Also invoked by QhullQh().
+*/
+void qh_initstatistics(void) {
+  int i;
+  realT realx;
+  int intx;
+
+#if qh_QHpointer
+  if(qh_qhstat){  /* qh_initstatistics may be called from Qhull::resetStatistics() */
+      qh_free(qh_qhstat);
+      qh_qhstat= 0;
+  }
+  if (!(qh_qhstat= (qhstatT *)qh_malloc(sizeof(qhstatT)))) {
+    qh_fprintf(qhmem.ferr, 6183, "qhull error (qh_initstatistics): insufficient memory\n");
+    qh_exit(qh_ERRmem);  /* can not use qh_errexit() */
+  }
+#endif
+
+  qhstat next= 0;
+  qh_allstatA();
+  qh_allstatB();
+  qh_allstatC();
+  qh_allstatD();
+  qh_allstatE();
+  qh_allstatE2();
+  qh_allstatF();
+  qh_allstatG();
+  qh_allstatH();
+  qh_allstatI();
+  if (qhstat next > (int)sizeof(qhstat id)) {
+    qh_fprintf(qhmem.ferr, 6184, "qhull error (qh_initstatistics): increase size of qhstat.id[].\n\
+      qhstat.next %d should be <= sizeof(qhstat id) %d\n", qhstat next, (int)sizeof(qhstat id));
+#if 0 /* for locating error, Znumridges should be duplicated */
+    for(i=0; i < ZEND; i++) {
+      int j;
+      for(j=i+1; j < ZEND; j++) {
+        if (qhstat id[i] == qhstat id[j]) {
+          qh_fprintf(qhmem.ferr, 6185, "qhull error (qh_initstatistics): duplicated statistic %d at indices %d and %d\n",
+              qhstat id[i], i, j);
+        }
+      }
+    }
+#endif
+    qh_exit(qh_ERRqhull);  /* can not use qh_errexit() */
+  }
+  qhstat init[zinc].i= 0;
+  qhstat init[zadd].i= 0;
+  qhstat init[zmin].i= INT_MAX;
+  qhstat init[zmax].i= INT_MIN;
+  qhstat init[wadd].r= 0;
+  qhstat init[wmin].r= REALmax;
+  qhstat init[wmax].r= -REALmax;
+  for(i=0; i < ZEND; i++) {
+    if (qhstat type[i] > ZTYPEreal) {
+      realx= qhstat init[(unsigned char)(qhstat type[i])].r;
+      qhstat stats[i].r= realx;
+    }else if (qhstat type[i] != zdoc) {
+      intx= qhstat init[(unsigned char)(qhstat type[i])].i;
+      qhstat stats[i].i= intx;
+    }
+  }
+} /* initstatistics */
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >-------------------------------</a><a name="newstats">-</a>
+
+  qh_newstats(  )
+    returns True if statistics for zdoc
+
+  returns:
+    next zdoc
+*/
+boolT qh_newstats(int idx, int *nextindex) {
+  boolT isnew= False;
+  int start, i;
+
+  if (qhstat type[qhstat id[idx]] == zdoc)
+    start= idx+1;
+  else
+    start= idx;
+  for(i= start; i < qhstat next && qhstat type[qhstat id[i]] != zdoc; i++) {
+    if (!qh_nostatistic(qhstat id[i]) && !qhstat printed[qhstat id[i]])
+        isnew= True;
+  }
+  *nextindex= i;
+  return isnew;
+} /* newstats */
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >-------------------------------</a><a name="nostatistic">-</a>
+
+  qh_nostatistic( index )
+    true if no statistic to print
+*/
+boolT qh_nostatistic(int i) {
+
+  if ((qhstat type[i] > ZTYPEreal
+       &&qhstat stats[i].r == qhstat init[(unsigned char)(qhstat type[i])].r)
+      || (qhstat type[i] < ZTYPEreal
+          &&qhstat stats[i].i == qhstat init[(unsigned char)(qhstat type[i])].i))
+    return True;
+  return False;
+} /* nostatistic */
+
+#if qh_KEEPstatistics
+/*-<a                             href="qh-stat.htm#TOC"
+  >-------------------------------</a><a name="printallstatistics">-</a>
+
+  qh_printallstatistics( fp, string )
+    print all statistics with header 'string'
+*/
+void qh_printallstatistics(FILE *fp, const char *string) {
+
+  qh_allstatistics();
+  qh_collectstatistics();
+  qh_printstatistics(fp, string);
+  qh_memstatistics(fp);
+}
+
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >-------------------------------</a><a name="printstatistics">-</a>
+
+  qh_printstatistics( fp, string )
+    print statistics to a file with header 'string'
+    skips statistics with qhstat.printed[] (reset with qh_allstatistics)
+
+  see:
+    qh_printallstatistics()
+*/
+void qh_printstatistics(FILE *fp, const char *string) {
+  int i, k;
+  realT ave;
+
+  if (qh num_points != qh num_vertices) {
+    wval_(Wpbalance)= 0;
+    wval_(Wpbalance2)= 0;
+  }else
+    wval_(Wpbalance2)= qh_stddev(zval_(Zpbalance), wval_(Wpbalance),
+                                 wval_(Wpbalance2), &ave);
+  wval_(Wnewbalance2)= qh_stddev(zval_(Zprocessed), wval_(Wnewbalance),
+                                 wval_(Wnewbalance2), &ave);
+  qh_fprintf(fp, 9350, "\n\
+%s\n\
+ qhull invoked by: %s | %s\n%s with options:\n%s\n", string, qh rbox_command,
+     qh qhull_command, qh_version, qh qhull_options);
+  qh_fprintf(fp, 9351, "\nprecision constants:\n\
+ %6.2g max. abs. coordinate in the (transformed) input('Qbd:n')\n\
+ %6.2g max. roundoff error for distance computation('En')\n\
+ %6.2g max. roundoff error for angle computations\n\
+ %6.2g min. distance for outside points ('Wn')\n\
+ %6.2g min. distance for visible facets ('Vn')\n\
+ %6.2g max. distance for coplanar facets ('Un')\n\
+ %6.2g max. facet width for recomputing centrum and area\n\
+",
+  qh MAXabs_coord, qh DISTround, qh ANGLEround, qh MINoutside,
+        qh MINvisible, qh MAXcoplanar, qh WIDEfacet);
+  if (qh KEEPnearinside)
+    qh_fprintf(fp, 9352, "\
+ %6.2g max. distance for near-inside points\n", qh NEARinside);
+  if (qh premerge_cos < REALmax/2) qh_fprintf(fp, 9353, "\
+ %6.2g max. cosine for pre-merge angle\n", qh premerge_cos);
+  if (qh PREmerge) qh_fprintf(fp, 9354, "\
+ %6.2g radius of pre-merge centrum\n", qh premerge_centrum);
+  if (qh postmerge_cos < REALmax/2) qh_fprintf(fp, 9355, "\
+ %6.2g max. cosine for post-merge angle\n", qh postmerge_cos);
+  if (qh POSTmerge) qh_fprintf(fp, 9356, "\
+ %6.2g radius of post-merge centrum\n", qh postmerge_centrum);
+  qh_fprintf(fp, 9357, "\
+ %6.2g max. distance for merging two simplicial facets\n\
+ %6.2g max. roundoff error for arithmetic operations\n\
+ %6.2g min. denominator for divisions\n\
+  zero diagonal for Gauss: ", qh ONEmerge, REALepsilon, qh MINdenom);
+  for(k=0; k < qh hull_dim; k++)
+    qh_fprintf(fp, 9358, "%6.2e ", qh NEARzero[k]);
+  qh_fprintf(fp, 9359, "\n\n");
+  for(i=0 ; i < qhstat next; )
+    qh_printstats(fp, i, &i);
+} /* printstatistics */
+#endif /* qh_KEEPstatistics */
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >-------------------------------</a><a name="printstatlevel">-</a>
+
+  qh_printstatlevel( fp, id )
+    print level information for a statistic
+
+  notes:
+    nop if id >= ZEND, printed, or same as initial value
+*/
+void qh_printstatlevel(FILE *fp, int id, int start) {
+#define NULLfield "       "
+
+  if (id >= ZEND || qhstat printed[id])
+    return;
+  if (qhstat type[id] == zdoc) {
+    qh_fprintf(fp, 9360, "%s\n", qhstat doc[id]);
+    return;
+  }
+  (void) start; /* not used */
+  if (qh_nostatistic(id) || !qhstat doc[id])
+    return;
+  qhstat printed[id]= True;
+  if (qhstat count[id] != -1
+      && qhstat stats[(unsigned char)(qhstat count[id])].i == 0)
+    qh_fprintf(fp, 9361, " *0 cnt*");
+  else if (qhstat type[id] >= ZTYPEreal && qhstat count[id] == -1)
+    qh_fprintf(fp, 9362, "%7.2g", qhstat stats[id].r);
+  else if (qhstat type[id] >= ZTYPEreal && qhstat count[id] != -1)
+    qh_fprintf(fp, 9363, "%7.2g", qhstat stats[id].r/ qhstat stats[(unsigned char)(qhstat count[id])].i);
+  else if (qhstat type[id] < ZTYPEreal && qhstat count[id] == -1)
+    qh_fprintf(fp, 9364, "%7d", qhstat stats[id].i);
+  else if (qhstat type[id] < ZTYPEreal && qhstat count[id] != -1)
+    qh_fprintf(fp, 9365, "%7.3g", (realT) qhstat stats[id].i / qhstat stats[(unsigned char)(qhstat count[id])].i);
+  qh_fprintf(fp, 9366, " %s\n", qhstat doc[id]);
+} /* printstatlevel */
+
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >-------------------------------</a><a name="printstats">-</a>
+
+  qh_printstats( fp, index, nextindex )
+    print statistics for a zdoc group
+
+  returns:
+    next zdoc if non-null
+*/
+void qh_printstats(FILE *fp, int idx, int *nextindex) {
+  int j, nexti;
+
+  if (qh_newstats(idx, &nexti)) {
+    qh_fprintf(fp, 9367, "\n");
+    for (j=idx; j<nexti; j++)
+      qh_printstatlevel(fp, qhstat id[j], 0);
+  }
+  if (nextindex)
+    *nextindex= nexti;
+} /* printstats */
+
+#if qh_KEEPstatistics
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >-------------------------------</a><a name="stddev">-</a>
+
+  qh_stddev( num, tot, tot2, ave )
+    compute the standard deviation and average from statistics
+
+    tot2 is the sum of the squares
+  notes:
+    computes r.m.s.:
+      (x-ave)^2
+      == x^2 - 2x tot/num +   (tot/num)^2
+      == tot2 - 2 tot tot/num + tot tot/num
+      == tot2 - tot ave
+*/
+realT qh_stddev(int num, realT tot, realT tot2, realT *ave) {
+  realT stddev;
+
+  *ave= tot/num;
+  stddev= sqrt(tot2/num - *ave * *ave);
+  return stddev;
+} /* stddev */
+
+#endif /* qh_KEEPstatistics */
+
+#if !qh_KEEPstatistics
+void    qh_collectstatistics(void) {}
+void    qh_printallstatistics(FILE *fp, char *string) {};
+void    qh_printstatistics(FILE *fp, char *string) {}
+#endif
+
diff --git a/alg/libqhull/stat.h b/alg/libqhull/stat.h
new file mode 100644
index 0000000..97d8efa
--- /dev/null
+++ b/alg/libqhull/stat.h
@@ -0,0 +1,541 @@
+/*<html><pre>  -<a                             href="qh-stat.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   stat.h
+     contains all statistics that are collected for qhull
+
+   see qh-stat.htm and stat.c
+
+   Copyright (c) 1993-2012 The Geometry Center.
+   $Id: //main/2011/qhull/src/libqhull/stat.h#5 $$Change: 1464 $
+   $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+
+   recompile qhull if you change this file
+
+   Integer statistics are Z* while real statistics are W*.
+
+   define maydebugx to call a routine at every statistic event
+
+*/
+
+#ifndef qhDEFstat
+#define qhDEFstat 1
+
+#include "libqhull.h"
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >-------------------------------</a><a name="KEEPstatistics">-</a>
+
+  qh_KEEPstatistics
+    0 turns off statistic gathering (except zzdef/zzinc/zzadd/zzval/wwval)
+*/
+#ifndef qh_KEEPstatistics
+#define qh_KEEPstatistics 1
+#endif
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >-------------------------------</a><a name="statistics">-</a>
+
+  Zxxx for integers, Wxxx for reals
+
+  notes:
+    be sure that all statistics are defined in stat.c
+      otherwise initialization may core dump
+    can pick up all statistics by:
+      grep '[zw].*_[(][ZW]' *.c >z.x
+    remove trailers with query">-</a>
+    remove leaders with  query-replace-regexp [ ^I]+  (
+*/
+#if qh_KEEPstatistics
+enum statistics {     /* alphabetical after Z/W */
+    Zacoplanar,
+    Wacoplanarmax,
+    Wacoplanartot,
+    Zangle,
+    Wangle,
+    Wanglemax,
+    Wanglemin,
+    Zangletests,
+    Wareatot,
+    Wareamax,
+    Wareamin,
+    Zavoidold,
+    Wavoidoldmax,
+    Wavoidoldtot,
+    Zback0,
+    Zbestcentrum,
+    Zbestdist,
+    Zbestlower,
+    Zbestlowerv,
+    Zcentrumtests,
+    Zcheckpart,
+    Zcomputefurthest,
+    Zconcave,
+    Wconcavemax,
+    Wconcavetot,
+    Zconcaveridges,
+    Zconcaveridge,
+    Zcoplanar,
+    Wcoplanarmax,
+    Wcoplanartot,
+    Zcoplanarangle,
+    Zcoplanarcentrum,
+    Zcoplanarhorizon,
+    Zcoplanarinside,
+    Zcoplanarpart,
+    Zcoplanarridges,
+    Wcpu,
+    Zcyclefacetmax,
+    Zcyclefacettot,
+    Zcyclehorizon,
+    Zcyclevertex,
+    Zdegen,
+    Wdegenmax,
+    Wdegentot,
+    Zdegenvertex,
+    Zdelfacetdup,
+    Zdelridge,
+    Zdelvertextot,
+    Zdelvertexmax,
+    Zdetsimplex,
+    Zdistcheck,
+    Zdistconvex,
+    Zdistgood,
+    Zdistio,
+    Zdistplane,
+    Zdiststat,
+    Zdistvertex,
+    Zdistzero,
+    Zdoc1,
+    Zdoc2,
+    Zdoc3,
+    Zdoc4,
+    Zdoc5,
+    Zdoc6,
+    Zdoc7,
+    Zdoc8,
+    Zdoc9,
+    Zdoc10,
+    Zdoc11,
+    Zdoc12,
+    Zdropdegen,
+    Zdropneighbor,
+    Zdupflip,
+    Zduplicate,
+    Wduplicatemax,
+    Wduplicatetot,
+    Zdupridge,
+    Zdupsame,
+    Zflipped,
+    Wflippedmax,
+    Wflippedtot,
+    Zflippedfacets,
+    Zfindbest,
+    Zfindbestmax,
+    Zfindbesttot,
+    Zfindcoplanar,
+    Zfindfail,
+    Zfindhorizon,
+    Zfindhorizonmax,
+    Zfindhorizontot,
+    Zfindjump,
+    Zfindnew,
+    Zfindnewmax,
+    Zfindnewtot,
+    Zfindnewjump,
+    Zfindnewsharp,
+    Zgauss0,
+    Zgoodfacet,
+    Zhashlookup,
+    Zhashridge,
+    Zhashridgetest,
+    Zhashtests,
+    Zinsidevisible,
+    Zintersect,
+    Zintersectfail,
+    Zintersectmax,
+    Zintersectnum,
+    Zintersecttot,
+    Zmaxneighbors,
+    Wmaxout,
+    Wmaxoutside,
+    Zmaxridges,
+    Zmaxvertex,
+    Zmaxvertices,
+    Zmaxvneighbors,
+    Zmemfacets,
+    Zmempoints,
+    Zmemridges,
+    Zmemvertices,
+    Zmergeflipdup,
+    Zmergehorizon,
+    Zmergeinittot,
+    Zmergeinitmax,
+    Zmergeinittot2,
+    Zmergeintohorizon,
+    Zmergenew,
+    Zmergesettot,
+    Zmergesetmax,
+    Zmergesettot2,
+    Zmergesimplex,
+    Zmergevertex,
+    Wmindenom,
+    Wminvertex,
+    Zminnorm,
+    Zmultiridge,
+    Znearlysingular,
+    Zneighbor,
+    Wnewbalance,
+    Wnewbalance2,
+    Znewfacettot,
+    Znewfacetmax,
+    Znewvertex,
+    Wnewvertex,
+    Wnewvertexmax,
+    Znoarea,
+    Znonsimplicial,
+    Znowsimplicial,
+    Znotgood,
+    Znotgoodnew,
+    Znotmax,
+    Znumfacets,
+    Znummergemax,
+    Znummergetot,
+    Znumneighbors,
+    Znumridges,
+    Znumvertices,
+    Znumvisibility,
+    Znumvneighbors,
+    Zonehorizon,
+    Zpartangle,
+    Zpartcoplanar,
+    Zpartflip,
+    Zparthorizon,
+    Zpartinside,
+    Zpartition,
+    Zpartitionall,
+    Zpartnear,
+    Zpbalance,
+    Wpbalance,
+    Wpbalance2,
+    Zpostfacets,
+    Zpremergetot,
+    Zprocessed,
+    Zremvertex,
+    Zremvertexdel,
+    Zrenameall,
+    Zrenamepinch,
+    Zrenameshare,
+    Zretry,
+    Wretrymax,
+    Zridge,
+    Wridge,
+    Wridgemax,
+    Zridge0,
+    Wridge0,
+    Wridge0max,
+    Zridgemid,
+    Wridgemid,
+    Wridgemidmax,
+    Zridgeok,
+    Wridgeok,
+    Wridgeokmax,
+    Zsearchpoints,
+    Zsetplane,
+    Ztestvneighbor,
+    Ztotcheck,
+    Ztothorizon,
+    Ztotmerge,
+    Ztotpartcoplanar,
+    Ztotpartition,
+    Ztotridges,
+    Ztotvertices,
+    Ztotvisible,
+    Ztricoplanar,
+    Ztricoplanarmax,
+    Ztricoplanartot,
+    Ztridegen,
+    Ztrimirror,
+    Ztrinull,
+    Wvertexmax,
+    Wvertexmin,
+    Zvertexridge,
+    Zvertexridgetot,
+    Zvertexridgemax,
+    Zvertices,
+    Zvisfacettot,
+    Zvisfacetmax,
+    Zvisit,
+    Zvisit2max,
+    Zvisvertextot,
+    Zvisvertexmax,
+    Zvvisit,
+    Zvvisit2max,
+    Zwidefacet,
+    Zwidevertices,
+    ZEND};
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >-------------------------------</a><a name="ZZstat">-</a>
+
+  Zxxx/Wxxx statistics that remain defined if qh_KEEPstatistics=0
+
+  notes:
+    be sure to use zzdef, zzinc, etc. with these statistics (no double checking!)
+*/
+#else
+enum statistics {     /* for zzdef etc. macros */
+  Zback0,
+  Zbestdist,
+  Zcentrumtests,
+  Zcheckpart,
+  Zconcaveridges,
+  Zcoplanarhorizon,
+  Zcoplanarpart,
+  Zcoplanarridges,
+  Zcyclefacettot,
+  Zcyclehorizon,
+  Zdelvertextot,
+  Zdistcheck,
+  Zdistconvex,
+  Zdistzero,
+  Zdoc1,
+  Zdoc2,
+  Zdoc3,
+  Zdoc11,
+  Zflippedfacets,
+  Zgauss0,
+  Zminnorm,
+  Zmultiridge,
+  Znearlysingular,
+  Wnewvertexmax,
+  Znumvisibility,
+  Zpartcoplanar,
+  Zpartition,
+  Zpartitionall,
+  Zprocessed,
+  Zretry,
+  Zridge,
+  Wridge,
+  Wridgemax,
+  Zridge0,
+  Wridge0,
+  Wridge0max,
+  Zridgemid,
+  Wridgemid,
+  Wridgemidmax,
+  Zridgeok,
+  Wridgeok,
+  Wridgeokmax,
+  Zsetplane,
+  Ztotcheck,
+  Ztotmerge,
+    ZEND};
+#endif
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >-------------------------------</a><a name="ztype">-</a>
+
+  ztype
+    the type of a statistic sets its initial value.
+
+  notes:
+    The type should be the same as the macro for collecting the statistic
+*/
+enum ztypes {zdoc,zinc,zadd,zmax,zmin,ZTYPEreal,wadd,wmax,wmin,ZTYPEend};
+
+/*========== macros and constants =============*/
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >--------------------------------</a><a name="MAYdebugx">-</a>
+
+  MAYdebugx
+    define as maydebug() to be called frequently for error trapping
+*/
+#define MAYdebugx
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >--------------------------------</a><a name="zdef_">-</a>
+
+  zzdef_, zdef_( type, name, doc, -1)
+    define a statistic (assumes 'qhstat.next= 0;')
+
+  zdef_( type, name, doc, count)
+    define an averaged statistic
+    printed as name/count
+*/
+#define zzdef_(stype,name,string,cnt) qhstat id[qhstat next++]=name; \
+   qhstat doc[name]= string; qhstat count[name]= cnt; qhstat type[name]= stype
+#if qh_KEEPstatistics
+#define zdef_(stype,name,string,cnt) qhstat id[qhstat next++]=name; \
+   qhstat doc[name]= string; qhstat count[name]= cnt; qhstat type[name]= stype
+#else
+#define zdef_(type,name,doc,count)
+#endif
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >--------------------------------</a><a name="zinc_">-</a>
+
+  zzinc_( name ), zinc_( name)
+    increment an integer statistic
+*/
+#define zzinc_(id) {MAYdebugx; qhstat stats[id].i++;}
+#if qh_KEEPstatistics
+#define zinc_(id) {MAYdebugx; qhstat stats[id].i++;}
+#else
+#define zinc_(id) {}
+#endif
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >--------------------------------</a><a name="zadd_">-</a>
+
+  zzadd_( name, value ), zadd_( name, value ), wadd_( name, value )
+    add value to an integer or real statistic
+*/
+#define zzadd_(id, val) {MAYdebugx; qhstat stats[id].i += (val);}
+#define wwadd_(id, val) {MAYdebugx; qhstat stats[id].r += (val);}
+#if qh_KEEPstatistics
+#define zadd_(id, val) {MAYdebugx; qhstat stats[id].i += (val);}
+#define wadd_(id, val) {MAYdebugx; qhstat stats[id].r += (val);}
+#else
+#define zadd_(id, val) {}
+#define wadd_(id, val) {}
+#endif
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >--------------------------------</a><a name="zval_">-</a>
+
+  zzval_( name ), zval_( name ), wwval_( name )
+    set or return value of a statistic
+*/
+#define zzval_(id) ((qhstat stats[id]).i)
+#define wwval_(id) ((qhstat stats[id]).r)
+#if qh_KEEPstatistics
+#define zval_(id) ((qhstat stats[id]).i)
+#define wval_(id) ((qhstat stats[id]).r)
+#else
+#define zval_(id) qhstat tempi
+#define wval_(id) qhstat tempr
+#endif
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >--------------------------------</a><a name="zmax_">-</a>
+
+  zmax_( id, val ), wmax_( id, value )
+    maximize id with val
+*/
+#define wwmax_(id, val) {MAYdebugx; maximize_(qhstat stats[id].r,(val));}
+#if qh_KEEPstatistics
+#define zmax_(id, val) {MAYdebugx; maximize_(qhstat stats[id].i,(val));}
+#define wmax_(id, val) {MAYdebugx; maximize_(qhstat stats[id].r,(val));}
+#else
+#define zmax_(id, val) {}
+#define wmax_(id, val) {}
+#endif
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >--------------------------------</a><a name="zmin_">-</a>
+
+  zmin_( id, val ), wmin_( id, value )
+    minimize id with val
+*/
+#if qh_KEEPstatistics
+#define zmin_(id, val) {MAYdebugx; minimize_(qhstat stats[id].i,(val));}
+#define wmin_(id, val) {MAYdebugx; minimize_(qhstat stats[id].r,(val));}
+#else
+#define zmin_(id, val) {}
+#define wmin_(id, val) {}
+#endif
+
+/*================== stat.h types ==============*/
+
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >--------------------------------</a><a name="intrealT">-</a>
+
+  intrealT
+    union of integer and real, used for statistics
+*/
+typedef union intrealT intrealT;    /* union of int and realT */
+union intrealT {
+    int i;
+    realT r;
+};
+
+/*-<a                             href="qh-stat.htm#TOC"
+  >--------------------------------</a><a name="qhstat">-</a>
+
+  qhstat
+    global data structure for statistics, similar to qh and qhrbox
+
+  notes:
+   access to qh_qhstat is via the "qhstat" macro.  There are two choices
+   qh_QHpointer = 1     access globals via a pointer
+                        enables qh_saveqhull() and qh_restoreqhull()
+                = 0     qh_qhstat is a static data structure
+                        only one instance of qhull() can be active at a time
+                        default value
+   qh_QHpointer is defined in libqhull.h
+   qh_QHpointer_dllimport and qh_dllimport define qh_qh as __declspec(dllimport) [libqhull.h]
+
+   allocated in stat.c using qh_malloc()
+*/
+#ifndef DEFqhstatT
+#define DEFqhstatT 1
+typedef struct qhstatT qhstatT;
+#endif
+
+#if qh_QHpointer_dllimport
+#define qhstat qh_qhstat->
+__declspec(dllimport) extern qhstatT *qh_qhstat;
+#elif qh_QHpointer
+#define qhstat qh_qhstat->
+extern qhstatT *qh_qhstat;
+#elif qh_dllimport
+#define qhstat qh_qhstat.
+__declspec(dllimport) extern qhstatT qh_qhstat;
+#else
+#define qhstat qh_qhstat.
+extern qhstatT qh_qhstat;
+#endif
+struct qhstatT {
+  intrealT   stats[ZEND];     /* integer and real statistics */
+  unsigned   char id[ZEND+10]; /* id's in print order */
+  const char *doc[ZEND];       /* array of documentation strings */
+  short int  count[ZEND];     /* -1 if none, else index of count to use */
+  char       type[ZEND];      /* type, see ztypes above */
+  char       printed[ZEND];   /* true, if statistic has been printed */
+  intrealT   init[ZTYPEend];  /* initial values by types, set initstatistics */
+
+  int        next;            /* next index for zdef_ */
+  int        precision;       /* index for precision problems */
+  int        vridges;         /* index for Voronoi ridges */
+  int        tempi;
+  realT      tempr;
+};
+
+/*========== function prototypes ===========*/
+
+void    qh_allstatA(void);
+void    qh_allstatB(void);
+void    qh_allstatC(void);
+void    qh_allstatD(void);
+void    qh_allstatE(void);
+void    qh_allstatE2(void);
+void    qh_allstatF(void);
+void    qh_allstatG(void);
+void    qh_allstatH(void);
+void    qh_allstatI(void);
+void    qh_allstatistics(void);
+void    qh_collectstatistics(void);
+void    qh_freestatistics(void);
+void    qh_initstatistics(void);
+boolT   qh_newstats(int idx, int *nextindex);
+boolT   qh_nostatistic(int i);
+void    qh_printallstatistics(FILE *fp, const char *string);
+void    qh_printstatistics(FILE *fp, const char *string);
+void    qh_printstatlevel(FILE *fp, int id, int start);
+void    qh_printstats(FILE *fp, int idx, int *nextindex);
+realT   qh_stddev(int num, realT tot, realT tot2, realT *ave);
+
+#endif   /* qhDEFstat */
diff --git a/alg/libqhull/user.c b/alg/libqhull/user.c
new file mode 100644
index 0000000..653c5a4
--- /dev/null
+++ b/alg/libqhull/user.c
@@ -0,0 +1,527 @@
+/*<html><pre>  -<a                             href="qh-user.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   user.c
+   user redefinable functions
+
+   see user2.c for qh_fprintf, qh_malloc, qh_free
+
+   see README.txt  see COPYING.txt for copyright information.
+
+   see libqhull.h for data structures, macros, and user-callable functions.
+
+   see user_eg.c, unix.c, and qhull_interface.cpp for examples.
+
+   see user.h for user-definable constants
+
+      use qh_NOmem in mem.h to turn off memory management
+      use qh_NOmerge in user.h to turn off facet merging
+      set qh_KEEPstatistics in user.h to 0 to turn off statistics
+
+   This is unsupported software.  You're welcome to make changes,
+   but you're on your own if something goes wrong.  Use 'Tc' to
+   check frequently.  Usually qhull will report an error if
+   a data structure becomes inconsistent.  If so, it also reports
+   the last point added to the hull, e.g., 102.  You can then trace
+   the execution of qhull with "T4P102".
+
+   Please report any errors that you fix to qhull at qhull.org
+
+   call_qhull is a template for calling qhull from within your application
+
+   if you recompile and load this module, then user.o will not be loaded
+   from qhull.a
+
+   you can add additional quick allocation sizes in qh_user_memsizes
+
+   if the other functions here are redefined to not use qh_print...,
+   then io.o will not be loaded from qhull.a.  See user_eg.c for an
+   example.  We recommend keeping io.o for the extra debugging
+   information it supplies.
+*/
+
+#include "qhull_a.h"
+
+#include <stdarg.h>
+
+/*-<a                             href="qh-user.htm#TOC"
+  >-------------------------------</a><a name="call_qhull">-</a>
+
+  qh_call_qhull( void )
+    template for calling qhull from inside your program
+    remove #if 0, #endif to compile
+
+  returns:
+    exit code(see qh_ERR... in libqhull.h)
+    all memory freed
+
+  notes:
+    This can be called any number of times.
+
+  see:
+    qh_call_qhull_once()
+
+*/
+#if 0
+{
+  int dim;                  /* dimension of points */
+  int numpoints;            /* number of points */
+  coordT *points;           /* array of coordinates for each point */
+  boolT ismalloc;           /* True if qhull should free points in qh_freeqhull() or reallocation */
+  char flags[]= "qhull Tv"; /* option flags for qhull, see qh_opt.htm */
+  FILE *outfile= stdout;    /* output from qh_produce_output()
+                               use NULL to skip qh_produce_output() */
+  FILE *errfile= stderr;    /* error messages from qhull code */
+  int exitcode;             /* 0 if no error from qhull */
+  facetT *facet;            /* set by FORALLfacets */
+  int curlong, totlong;     /* memory remaining after qh_memfreeshort */
+
+#if qh_QHpointer  /* see user.h */
+  if (qh_qh){
+      printf ("QH6238: Qhull link error.  The global variable qh_qh was not initialized\n\
+              to NULL by global.c.  Please compile this program with -Dqh_QHpointer_dllimport\n\
+              as well as -Dqh_QHpointer, or use libqhullstatic, or use a different tool chain.\n\n");
+      exit -1;
+  }
+#endif
+
+  /* initialize dim, numpoints, points[], ismalloc here */
+  exitcode= qh_new_qhull(dim, numpoints, points, ismalloc,
+                      flags, outfile, errfile);
+  if (!exitcode) {                  /* if no error */
+    /* 'qh facet_list' contains the convex hull */
+    FORALLfacets {
+       /* ... your code ... */
+    }
+  }
+  qh_freeqhull(!qh_ALL);
+  qh_memfreeshort(&curlong, &totlong);
+  if (curlong || totlong)
+    qh_fprintf(errfile, 7068, "qhull internal warning (main): did not free %d bytes of long memory(%d pieces)\n", totlong, curlong);
+}
+#endif
+
+/*-<a                             href="qh-user.htm#TOC"
+  >-------------------------------</a><a name="new_qhull">-</a>
+
+  qh_new_qhull( dim, numpoints, points, ismalloc, qhull_cmd, outfile, errfile )
+    build new qhull data structure and return exitcode (0 if no errors)
+
+  notes:
+    do not modify points until finished with results.
+      The qhull data structure contains pointers into the points array.
+    do not call qhull functions before qh_new_qhull().
+      The qhull data structure is not initialized until qh_new_qhull().
+
+    outfile may be null
+    qhull_cmd must start with "qhull "
+    projects points to a new point array for Delaunay triangulations ('d' and 'v')
+    transforms points into a new point array for halfspace intersection ('H')
+
+
+  To allow multiple, concurrent calls to qhull()
+    - set qh_QHpointer in user.h
+    - use qh_save_qhull and qh_restore_qhull to swap the global data structure between calls.
+    - use qh_freeqhull(qh_ALL) to free intermediate convex hulls
+
+  see:
+    user_eg.c for an example
+*/
+int qh_new_qhull(int dim, int numpoints, coordT *points, boolT ismalloc,
+                char *qhull_cmd, FILE *outfile, FILE *errfile) {
+  int exitcode, hulldim;
+  boolT new_ismalloc;
+  static boolT firstcall = True;
+  coordT *new_points;
+
+  if (firstcall) {
+    qh_meminit(errfile);
+    firstcall= False;
+  }
+  if (strncmp(qhull_cmd,"qhull ", (size_t)6)) {
+    qh_fprintf(errfile, 6186, "qhull error (qh_new_qhull): start qhull_cmd argument with \"qhull \"\n");
+    qh_exit(qh_ERRinput);
+  }
+  qh_initqhull_start(NULL, outfile, errfile);
+  trace1((qh ferr, 1044, "qh_new_qhull: build new Qhull for %d %d-d points with %s\n", numpoints, dim, qhull_cmd));
+  exitcode = setjmp(qh errexit);
+  if (!exitcode)
+  {
+    qh NOerrexit = False;
+    qh_initflags(qhull_cmd);
+    if (qh DELAUNAY)
+      qh PROJECTdelaunay= True;
+    if (qh HALFspace) {
+      /* points is an array of halfspaces,
+         the last coordinate of each halfspace is its offset */
+      hulldim= dim-1;
+      qh_setfeasible(hulldim);
+      new_points= qh_sethalfspace_all(dim, numpoints, points, qh feasible_point);
+      new_ismalloc= True;
+      if (ismalloc)
+        qh_free(points);
+    }else {
+      hulldim= dim;
+      new_points= points;
+      new_ismalloc= ismalloc;
+    }
+    qh_init_B(new_points, numpoints, hulldim, new_ismalloc);
+    qh_qhull();
+    qh_check_output();
+    if (outfile) {
+      qh_produce_output();
+    }else {
+      qh_prepare_output();
+    }
+    if (qh VERIFYoutput && !qh STOPpoint && !qh STOPcone)
+      qh_check_points();
+  }
+  qh NOerrexit = True;
+  return exitcode;
+} /* new_qhull */
+
+/*-<a                             href="qh-user.htm#TOC"
+  >-------------------------------</a><a name="errexit">-</a>
+
+  qh_errexit( exitcode, facet, ridge )
+    report and exit from an error
+    report facet and ridge if non-NULL
+    reports useful information such as last point processed
+    set qh.FORCEoutput to print neighborhood of facet
+
+  see:
+    qh_errexit2() in libqhull.c for printing 2 facets
+
+  design:
+    check for error within error processing
+    compute qh.hulltime
+    print facet and ridge (if any)
+    report commandString, options, qh.furthest_id
+    print summary and statistics (including precision statistics)
+    if qh_ERRsingular
+      print help text for singular data set
+    exit program via long jump (if defined) or exit()
+*/
+void qh_errexit(int exitcode, facetT *facet, ridgeT *ridge) {
+
+  if (qh ERREXITcalled) {
+    qh_fprintf(qh ferr, 8126, "\nqhull error while processing previous error.  Exit program\n");
+    qh_exit(qh_ERRqhull);
+  }
+  qh ERREXITcalled= True;
+  if (!qh QHULLfinished)
+    qh hulltime= qh_CPUclock - qh hulltime;
+  qh_errprint("ERRONEOUS", facet, NULL, ridge, NULL);
+  qh_fprintf(qh ferr, 8127, "\nWhile executing: %s | %s\n", qh rbox_command, qh qhull_command);
+  qh_fprintf(qh ferr, 8128, "Options selected for Qhull %s:\n%s\n", qh_version, qh qhull_options);
+  if (qh furthest_id >= 0) {
+    qh_fprintf(qh ferr, 8129, "Last point added to hull was p%d.", qh furthest_id);
+    if (zzval_(Ztotmerge))
+      qh_fprintf(qh ferr, 8130, "  Last merge was #%d.", zzval_(Ztotmerge));
+    if (qh QHULLfinished)
+      qh_fprintf(qh ferr, 8131, "\nQhull has finished constructing the hull.");
+    else if (qh POSTmerging)
+      qh_fprintf(qh ferr, 8132, "\nQhull has started post-merging.");
+    qh_fprintf(qh ferr, 8133, "\n");
+  }
+  if (qh FORCEoutput && (qh QHULLfinished || (!facet && !ridge)))
+    qh_produce_output();
+  else if (exitcode != qh_ERRinput) {
+    if (exitcode != qh_ERRsingular && zzval_(Zsetplane) > qh hull_dim+1) {
+      qh_fprintf(qh ferr, 8134, "\nAt error exit:\n");
+      qh_printsummary(qh ferr);
+      if (qh PRINTstatistics) {
+        qh_collectstatistics();
+        qh_printstatistics(qh ferr, "at error exit");
+        qh_memstatistics(qh ferr);
+      }
+    }
+    if (qh PRINTprecision)
+      qh_printstats(qh ferr, qhstat precision, NULL);
+  }
+  if (!exitcode)
+    exitcode= qh_ERRqhull;
+  else if (exitcode == qh_ERRsingular)
+    qh_printhelp_singular(qh ferr);
+  else if (exitcode == qh_ERRprec && !qh PREmerge)
+    qh_printhelp_degenerate(qh ferr);
+  if (qh NOerrexit) {
+    qh_fprintf(qh ferr, 6187, "qhull error while ending program.  Exit program\n");
+    qh_exit(qh_ERRqhull);
+  }
+  qh ERREXITcalled= False;
+  qh NOerrexit= True;
+  longjmp(qh errexit, exitcode);
+} /* errexit */
+
+
+/*-<a                             href="qh-user.htm#TOC"
+  >-------------------------------</a><a name="errprint">-</a>
+
+  qh_errprint( fp, string, atfacet, otherfacet, atridge, atvertex )
+    prints out the information of facets and ridges to fp
+    also prints neighbors and geomview output
+
+  notes:
+    except for string, any parameter may be NULL
+*/
+void qh_errprint(const char *string, facetT *atfacet, facetT *otherfacet, ridgeT *atridge, vertexT *atvertex) {
+  int i;
+
+  if (atfacet) {
+    qh_fprintf(qh ferr, 8135, "%s FACET:\n", string);
+    qh_printfacet(qh ferr, atfacet);
+  }
+  if (otherfacet) {
+    qh_fprintf(qh ferr, 8136, "%s OTHER FACET:\n", string);
+    qh_printfacet(qh ferr, otherfacet);
+  }
+  if (atridge) {
+    qh_fprintf(qh ferr, 8137, "%s RIDGE:\n", string);
+    qh_printridge(qh ferr, atridge);
+    if (atridge->top && atridge->top != atfacet && atridge->top != otherfacet)
+      qh_printfacet(qh ferr, atridge->top);
+    if (atridge->bottom
+        && atridge->bottom != atfacet && atridge->bottom != otherfacet)
+      qh_printfacet(qh ferr, atridge->bottom);
+    if (!atfacet)
+      atfacet= atridge->top;
+    if (!otherfacet)
+      otherfacet= otherfacet_(atridge, atfacet);
+  }
+  if (atvertex) {
+    qh_fprintf(qh ferr, 8138, "%s VERTEX:\n", string);
+    qh_printvertex(qh ferr, atvertex);
+  }
+  if (qh fout && qh FORCEoutput && atfacet && !qh QHULLfinished && !qh IStracing) {
+    qh_fprintf(qh ferr, 8139, "ERRONEOUS and NEIGHBORING FACETS to output\n");
+    for (i=0; i < qh_PRINTEND; i++)  /* use fout for geomview output */
+      qh_printneighborhood(qh fout, qh PRINTout[i], atfacet, otherfacet,
+                            !qh_ALL);
+  }
+} /* errprint */
+
+
+/*-<a                             href="qh-user.htm#TOC"
+  >-------------------------------</a><a name="printfacetlist">-</a>
+
+  qh_printfacetlist( fp, facetlist, facets, printall )
+    print all fields for a facet list and/or set of facets to fp
+    if !printall,
+      only prints good facets
+
+  notes:
+    also prints all vertices
+*/
+void qh_printfacetlist(facetT *facetlist, setT *facets, boolT printall) {
+  facetT *facet, **facetp;
+
+  qh_printbegin(qh ferr, qh_PRINTfacets, facetlist, facets, printall);
+  FORALLfacet_(facetlist)
+    qh_printafacet(qh ferr, qh_PRINTfacets, facet, printall);
+  FOREACHfacet_(facets)
+    qh_printafacet(qh ferr, qh_PRINTfacets, facet, printall);
+  qh_printend(qh ferr, qh_PRINTfacets, facetlist, facets, printall);
+} /* printfacetlist */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printhelp_degenerate">-</a>
+
+  qh_printhelp_degenerate( fp )
+    prints descriptive message for precision error
+
+  notes:
+    no message if qh_QUICKhelp
+*/
+void qh_printhelp_degenerate(FILE *fp) {
+
+  if (qh MERGEexact || qh PREmerge || qh JOGGLEmax < REALmax/2)
+    qh_fprintf(fp, 9368, "\n\
+A Qhull error has occurred.  Qhull should have corrected the above\n\
+precision error.  Please send the input and all of the output to\n\
+qhull_bug at qhull.org\n");
+  else if (!qh_QUICKhelp) {
+    qh_fprintf(fp, 9369, "\n\
+Precision problems were detected during construction of the convex hull.\n\
+This occurs because convex hull algorithms assume that calculations are\n\
+exact, but floating-point arithmetic has roundoff errors.\n\
+\n\
+To correct for precision problems, do not use 'Q0'.  By default, Qhull\n\
+selects 'C-0' or 'Qx' and merges non-convex facets.  With option 'QJ',\n\
+Qhull joggles the input to prevent precision problems.  See \"Imprecision\n\
+in Qhull\" (qh-impre.htm).\n\
+\n\
+If you use 'Q0', the output may include\n\
+coplanar ridges, concave ridges, and flipped facets.  In 4-d and higher,\n\
+Qhull may produce a ridge with four neighbors or two facets with the same \n\
+vertices.  Qhull reports these events when they occur.  It stops when a\n\
+concave ridge, flipped facet, or duplicate facet occurs.\n");
+#if REALfloat
+    qh_fprintf(fp, 9370, "\
+\n\
+Qhull is currently using single precision arithmetic.  The following\n\
+will probably remove the precision problems:\n\
+  - recompile qhull for realT precision(#define REALfloat 0 in user.h).\n");
+#endif
+    if (qh DELAUNAY && !qh SCALElast && qh MAXabs_coord > 1e4)
+      qh_fprintf(fp, 9371, "\
+\n\
+When computing the Delaunay triangulation of coordinates > 1.0,\n\
+  - use 'Qbb' to scale the last coordinate to [0,m] (max previous coordinate)\n");
+    if (qh DELAUNAY && !qh ATinfinity)
+      qh_fprintf(fp, 9372, "\
+When computing the Delaunay triangulation:\n\
+  - use 'Qz' to add a point at-infinity.  This reduces precision problems.\n");
+
+    qh_fprintf(fp, 9373, "\
+\n\
+If you need triangular output:\n\
+  - use option 'Qt' to triangulate the output\n\
+  - use option 'QJ' to joggle the input points and remove precision errors\n\
+  - use option 'Ft'.  It triangulates non-simplicial facets with added points.\n\
+\n\
+If you must use 'Q0',\n\
+try one or more of the following options.  They can not guarantee an output.\n\
+  - use 'QbB' to scale the input to a cube.\n\
+  - use 'Po' to produce output and prevent partitioning for flipped facets\n\
+  - use 'V0' to set min. distance to visible facet as 0 instead of roundoff\n\
+  - use 'En' to specify a maximum roundoff error less than %2.2g.\n\
+  - options 'Qf', 'Qbb', and 'QR0' may also help\n",
+               qh DISTround);
+    qh_fprintf(fp, 9374, "\
+\n\
+To guarantee simplicial output:\n\
+  - use option 'Qt' to triangulate the output\n\
+  - use option 'QJ' to joggle the input points and remove precision errors\n\
+  - use option 'Ft' to triangulate the output by adding points\n\
+  - use exact arithmetic (see \"Imprecision in Qhull\", qh-impre.htm)\n\
+");
+  }
+} /* printhelp_degenerate */
+
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="printhelp_narrowhull">-</a>
+
+  qh_printhelp_narrowhull( minangle )
+    Warn about a narrow hull
+
+  notes:
+    Alternatively, reduce qh_WARNnarrow in user.h
+
+*/
+void qh_printhelp_narrowhull(FILE *fp, realT minangle) {
+
+    qh_fprintf(fp, 9375, "qhull precision warning: \n\
+The initial hull is narrow (cosine of min. angle is %.16f).\n\
+Is the input lower dimensional (e.g., on a plane in 3-d)?  Qhull may\n\
+produce a wide facet.  Options 'QbB' (scale to unit box) or 'Qbb' (scale\n\
+last coordinate) may remove this warning.  Use 'Pp' to skip this warning.\n\
+See 'Limitations' in qh-impre.htm.\n",
+          -minangle);   /* convert from angle between normals to angle between facets */
+} /* printhelp_narrowhull */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printhelp_singular">-</a>
+
+  qh_printhelp_singular( fp )
+    prints descriptive message for singular input
+*/
+void qh_printhelp_singular(FILE *fp) {
+  facetT *facet;
+  vertexT *vertex, **vertexp;
+  realT min, max, *coord, dist;
+  int i,k;
+
+  qh_fprintf(fp, 9376, "\n\
+The input to qhull appears to be less than %d dimensional, or a\n\
+computation has overflowed.\n\n\
+Qhull could not construct a clearly convex simplex from points:\n",
+           qh hull_dim);
+  qh_printvertexlist(fp, "", qh facet_list, NULL, qh_ALL);
+  if (!qh_QUICKhelp)
+    qh_fprintf(fp, 9377, "\n\
+The center point is coplanar with a facet, or a vertex is coplanar\n\
+with a neighboring facet.  The maximum round off error for\n\
+computing distances is %2.2g.  The center point, facets and distances\n\
+to the center point are as follows:\n\n", qh DISTround);
+  qh_printpointid(fp, "center point", qh hull_dim, qh interior_point, -1);
+  qh_fprintf(fp, 9378, "\n");
+  FORALLfacets {
+    qh_fprintf(fp, 9379, "facet");
+    FOREACHvertex_(facet->vertices)
+      qh_fprintf(fp, 9380, " p%d", qh_pointid(vertex->point));
+    zinc_(Zdistio);
+    qh_distplane(qh interior_point, facet, &dist);
+    qh_fprintf(fp, 9381, " distance= %4.2g\n", dist);
+  }
+  if (!qh_QUICKhelp) {
+    if (qh HALFspace)
+      qh_fprintf(fp, 9382, "\n\
+These points are the dual of the given halfspaces.  They indicate that\n\
+the intersection is degenerate.\n");
+    qh_fprintf(fp, 9383,"\n\
+These points either have a maximum or minimum x-coordinate, or\n\
+they maximize the determinant for k coordinates.  Trial points\n\
+are first selected from points that maximize a coordinate.\n");
+    if (qh hull_dim >= qh_INITIALmax)
+      qh_fprintf(fp, 9384, "\n\
+Because of the high dimension, the min x-coordinate and max-coordinate\n\
+points are used if the determinant is non-zero.  Option 'Qs' will\n\
+do a better, though much slower, job.  Instead of 'Qs', you can change\n\
+the points by randomly rotating the input with 'QR0'.\n");
+  }
+  qh_fprintf(fp, 9385, "\nThe min and max coordinates for each dimension are:\n");
+  for (k=0; k < qh hull_dim; k++) {
+    min= REALmax;
+    max= -REALmin;
+    for (i=qh num_points, coord= qh first_point+k; i--; coord += qh hull_dim) {
+      maximize_(max, *coord);
+      minimize_(min, *coord);
+    }
+    qh_fprintf(fp, 9386, "  %d:  %8.4g  %8.4g  difference= %4.4g\n", k, min, max, max-min);
+  }
+  if (!qh_QUICKhelp) {
+    qh_fprintf(fp, 9387, "\n\
+If the input should be full dimensional, you have several options that\n\
+may determine an initial simplex:\n\
+  - use 'QJ'  to joggle the input and make it full dimensional\n\
+  - use 'QbB' to scale the points to the unit cube\n\
+  - use 'QR0' to randomly rotate the input for different maximum points\n\
+  - use 'Qs'  to search all points for the initial simplex\n\
+  - use 'En'  to specify a maximum roundoff error less than %2.2g.\n\
+  - trace execution with 'T3' to see the determinant for each point.\n",
+                     qh DISTround);
+#if REALfloat
+    qh_fprintf(fp, 9388, "\
+  - recompile qhull for realT precision(#define REALfloat 0 in libqhull.h).\n");
+#endif
+    qh_fprintf(fp, 9389, "\n\
+If the input is lower dimensional:\n\
+  - use 'QJ' to joggle the input and make it full dimensional\n\
+  - use 'Qbk:0Bk:0' to delete coordinate k from the input.  You should\n\
+    pick the coordinate with the least range.  The hull will have the\n\
+    correct topology.\n\
+  - determine the flat containing the points, rotate the points\n\
+    into a coordinate plane, and delete the other coordinates.\n\
+  - add one or more points to make the input full dimensional.\n\
+");
+  }
+} /* printhelp_singular */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="user_memsizes">-</a>
+
+  qh_user_memsizes()
+    allocate up to 10 additional, quick allocation sizes
+
+  notes:
+    increase maximum number of allocations in qh_initqhull_mem()
+*/
+void qh_user_memsizes(void) {
+
+  /* qh_memsize(size); */
+} /* user_memsizes */
+
+
diff --git a/alg/libqhull/user.h b/alg/libqhull/user.h
new file mode 100644
index 0000000..50025b3
--- /dev/null
+++ b/alg/libqhull/user.h
@@ -0,0 +1,858 @@
+/*<html><pre>  -<a                             href="qh-user.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   user.h
+   user redefinable constants
+
+   see qh-user.htm.  see COPYING for copyright information.
+
+   before reading any code, review libqhull.h for data structure definitions and
+   the "qh" macro.
+
+Sections:
+   ============= qhull library constants ======================
+   ============= data types and configuration macros ==========
+   ============= performance related constants ================
+   ============= memory constants =============================
+   ============= joggle constants =============================
+   ============= conditional compilation ======================
+   ============= -merge constants- ============================
+
+Code flags --
+  NOerrors -- the code does not call qh_errexit()
+  WARN64 -- the code may be incompatible with 64-bit pointers
+
+*/
+
+#include <time.h>
+
+#ifndef qhDEFuser
+#define qhDEFuser 1
+
+/*============================================================*/
+/*============= qhull library constants ======================*/
+/*============================================================*/
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="filenamelen">-</a>
+
+  FILENAMElen -- max length for TI and TO filenames
+
+*/
+
+#define qh_FILENAMElen 500
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="msgcode">-</a>
+
+  msgcode -- Unique message codes for qh_fprintf
+
+  If add new messages, assign these values and increment.
+
+  def counters =  [27, 1047, 2059, 3025, 4068, 5003,
+     6241, 7079, 8143, 9410, 10000, 11026]
+
+  See: qh_ERR* [libqhull.h]
+*/
+
+#define MSG_TRACE0 0
+#define MSG_TRACE1 1000
+#define MSG_TRACE2 2000
+#define MSG_TRACE3 3000
+#define MSG_TRACE4 4000
+#define MSG_TRACE5 5000
+#define MSG_ERROR  6000   /* errors written to qh.ferr */
+#define MSG_WARNING 7000
+#define MSG_STDERR  8000  /* log messages Written to qh.ferr */
+#define MSG_OUTPUT  9000
+#define MSG_QHULL_ERROR 10000 /* errors thrown by QhullError [QhullError.h] */
+#define MSG_FIXUP  11000  /* FIXUP QH11... */
+#define MSG_MAXLEN  3000 /* qh_printhelp_degenerate() in user.c */
+
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="qh_OPTIONline">-</a>
+
+  qh_OPTIONline -- max length of an option line 'FO'
+*/
+#define qh_OPTIONline 80
+
+/*============================================================*/
+/*============= data types and configuration macros ==========*/
+/*============================================================*/
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="realT">-</a>
+
+  realT
+    set the size of floating point numbers
+
+  qh_REALdigits
+    maximum number of significant digits
+
+  qh_REAL_1, qh_REAL_2n, qh_REAL_3n
+    format strings for printf
+
+  qh_REALmax, qh_REALmin
+    maximum and minimum (near zero) values
+
+  qh_REALepsilon
+    machine roundoff.  Maximum roundoff error for addition and multiplication.
+
+  notes:
+   Select whether to store floating point numbers in single precision (float)
+   or double precision (double).
+
+   Use 'float' to save about 8% in time and 25% in space.  This is particularly
+   helpful if high-d where convex hulls are space limited.  Using 'float' also
+   reduces the printed size of Qhull's output since numbers have 8 digits of
+   precision.
+
+   Use 'double' when greater arithmetic precision is needed.  This is needed
+   for Delaunay triangulations and Voronoi diagrams when you are not merging
+   facets.
+
+   If 'double' gives insufficient precision, your data probably includes
+   degeneracies.  If so you should use facet merging (done by default)
+   or exact arithmetic (see imprecision section of manual, qh-impre.htm).
+   You may also use option 'Po' to force output despite precision errors.
+
+   You may use 'long double', but many format statements need to be changed
+   and you may need a 'long double' square root routine.  S. Grundmann
+   (sg at eeiwzb.et.tu-dresden.de) has done this.  He reports that the code runs
+   much slower with little gain in precision.
+
+   WARNING: on some machines,    int f(){realT a= REALmax;return (a == REALmax);}
+      returns False.  Use (a > REALmax/2) instead of (a == REALmax).
+
+   REALfloat =   1      all numbers are 'float' type
+             =   0      all numbers are 'double' type
+*/
+#define REALfloat 0
+
+#if (REALfloat == 1)
+#define realT float
+#define REALmax FLT_MAX
+#define REALmin FLT_MIN
+#define REALepsilon FLT_EPSILON
+#define qh_REALdigits 8   /* maximum number of significant digits */
+#define qh_REAL_1 "%6.8g "
+#define qh_REAL_2n "%6.8g %6.8g\n"
+#define qh_REAL_3n "%6.8g %6.8g %6.8g\n"
+
+#elif (REALfloat == 0)
+#define realT double
+#define REALmax DBL_MAX
+#define REALmin DBL_MIN
+#define REALepsilon DBL_EPSILON
+#define qh_REALdigits 16    /* maximum number of significant digits */
+#define qh_REAL_1 "%6.16g "
+#define qh_REAL_2n "%6.16g %6.16g\n"
+#define qh_REAL_3n "%6.16g %6.16g %6.16g\n"
+
+#else
+#error unknown float option
+#endif
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="CPUclock">-</a>
+
+  qh_CPUclock
+    define the clock() function for reporting the total time spent by Qhull
+    returns CPU ticks as a 'long int'
+    qh_CPUclock is only used for reporting the total time spent by Qhull
+
+  qh_SECticks
+    the number of clock ticks per second
+
+  notes:
+    looks for CLOCKS_PER_SEC, CLOCKS_PER_SECOND, or assumes microseconds
+    to define a custom clock, set qh_CLOCKtype to 0
+
+    if your system does not use clock() to return CPU ticks, replace
+    qh_CPUclock with the corresponding function.  It is converted
+    to 'unsigned long' to prevent wrap-around during long runs.  By default,
+    <time.h> defines clock_t as 'long'
+
+   Set qh_CLOCKtype to
+
+     1          for CLOCKS_PER_SEC, CLOCKS_PER_SECOND, or microsecond
+                Note:  may fail if more than 1 hour elapsed time
+
+     2          use qh_clock() with POSIX times() (see global.c)
+*/
+#define qh_CLOCKtype 1  /* change to the desired number */
+
+#if (qh_CLOCKtype == 1)
+
+#if defined(CLOCKS_PER_SECOND)
+#define qh_CPUclock    ((unsigned long)clock())  /* return CPU clock */
+#define qh_SECticks CLOCKS_PER_SECOND
+
+#elif defined(CLOCKS_PER_SEC)
+#define qh_CPUclock    ((unsigned long)clock())  /* return CPU clock */
+#define qh_SECticks CLOCKS_PER_SEC
+
+#elif defined(CLK_TCK)
+#define qh_CPUclock    ((unsigned long)clock())  /* return CPU clock */
+#define qh_SECticks CLK_TCK
+
+#else
+#define qh_CPUclock    ((unsigned long)clock())  /* return CPU clock */
+#define qh_SECticks 1E6
+#endif
+
+#elif (qh_CLOCKtype == 2)
+#define qh_CPUclock    qh_clock()  /* return CPU clock */
+#define qh_SECticks 100
+
+#else /* qh_CLOCKtype == ? */
+#error unknown clock option
+#endif
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="RANDOM">-</a>
+
+  qh_RANDOMtype, qh_RANDOMmax, qh_RANDOMseed
+    define random number generator
+
+    qh_RANDOMint generates a random integer between 0 and qh_RANDOMmax.
+    qh_RANDOMseed sets the random number seed for qh_RANDOMint
+
+  Set qh_RANDOMtype (default 5) to:
+    1       for random() with 31 bits (UCB)
+    2       for rand() with RAND_MAX or 15 bits (system 5)
+    3       for rand() with 31 bits (Sun)
+    4       for lrand48() with 31 bits (Solaris)
+    5       for qh_rand() with 31 bits (included with Qhull)
+
+  notes:
+    Random numbers are used by rbox to generate point sets.  Random
+    numbers are used by Qhull to rotate the input ('QRn' option),
+    simulate a randomized algorithm ('Qr' option), and to simulate
+    roundoff errors ('Rn' option).
+
+    Random number generators differ between systems.  Most systems provide
+    rand() but the period varies.  The period of rand() is not critical
+    since qhull does not normally use random numbers.
+
+    The default generator is Park & Miller's minimal standard random
+    number generator [CACM 31:1195 '88].  It is included with Qhull.
+
+    If qh_RANDOMmax is wrong, qhull will report a warning and Geomview
+    output will likely be invisible.
+*/
+#define qh_RANDOMtype 5   /* *** change to the desired number *** */
+
+#if (qh_RANDOMtype == 1)
+#define qh_RANDOMmax ((realT)0x7fffffffUL)  /* 31 bits, random()/MAX */
+#define qh_RANDOMint random()
+#define qh_RANDOMseed_(seed) srandom(seed);
+
+#elif (qh_RANDOMtype == 2)
+#ifdef RAND_MAX
+#define qh_RANDOMmax ((realT)RAND_MAX)
+#else
+#define qh_RANDOMmax ((realT)32767)   /* 15 bits (System 5) */
+#endif
+#define qh_RANDOMint  rand()
+#define qh_RANDOMseed_(seed) srand((unsigned)seed);
+
+#elif (qh_RANDOMtype == 3)
+#define qh_RANDOMmax ((realT)0x7fffffffUL)  /* 31 bits, Sun */
+#define qh_RANDOMint  rand()
+#define qh_RANDOMseed_(seed) srand((unsigned)seed);
+
+#elif (qh_RANDOMtype == 4)
+#define qh_RANDOMmax ((realT)0x7fffffffUL)  /* 31 bits, lrand38()/MAX */
+#define qh_RANDOMint lrand48()
+#define qh_RANDOMseed_(seed) srand48(seed);
+
+#elif (qh_RANDOMtype == 5)
+#define qh_RANDOMmax ((realT)2147483646UL)  /* 31 bits, qh_rand/MAX */
+#define qh_RANDOMint qh_rand()
+#define qh_RANDOMseed_(seed) qh_srand(seed);
+/* unlike rand(), never returns 0 */
+
+#else
+#error: unknown random option
+#endif
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="ORIENTclock">-</a>
+
+  qh_ORIENTclock
+    0 for inward pointing normals by Geomview convention
+*/
+#define qh_ORIENTclock 0
+
+
+/*============================================================*/
+/*============= joggle constants =============================*/
+/*============================================================*/
+
+/*-<a                             href="qh-user.htm#TOC"
+>--------------------------------</a><a name="JOGGLEdefault">-</a>
+
+qh_JOGGLEdefault
+default qh.JOGGLEmax is qh.DISTround * qh_JOGGLEdefault
+
+notes:
+rbox s r 100 | qhull QJ1e-15 QR0 generates 90% faults at distround 7e-16
+rbox s r 100 | qhull QJ1e-14 QR0 generates 70% faults
+rbox s r 100 | qhull QJ1e-13 QR0 generates 35% faults
+rbox s r 100 | qhull QJ1e-12 QR0 generates 8% faults
+rbox s r 100 | qhull QJ1e-11 QR0 generates 1% faults
+rbox s r 100 | qhull QJ1e-10 QR0 generates 0% faults
+rbox 1000 W0 | qhull QJ1e-12 QR0 generates 86% faults
+rbox 1000 W0 | qhull QJ1e-11 QR0 generates 20% faults
+rbox 1000 W0 | qhull QJ1e-10 QR0 generates 2% faults
+the later have about 20 points per facet, each of which may interfere
+
+pick a value large enough to avoid retries on most inputs
+*/
+#define qh_JOGGLEdefault 30000.0
+
+/*-<a                             href="qh-user.htm#TOC"
+>--------------------------------</a><a name="JOGGLEincrease">-</a>
+
+qh_JOGGLEincrease
+factor to increase qh.JOGGLEmax on qh_JOGGLEretry or qh_JOGGLEagain
+*/
+#define qh_JOGGLEincrease 10.0
+
+/*-<a                             href="qh-user.htm#TOC"
+>--------------------------------</a><a name="JOGGLEretry">-</a>
+
+qh_JOGGLEretry
+if ZZretry = qh_JOGGLEretry, increase qh.JOGGLEmax
+
+notes:
+try twice at the original value in case of bad luck the first time
+*/
+#define qh_JOGGLEretry 2
+
+/*-<a                             href="qh-user.htm#TOC"
+>--------------------------------</a><a name="JOGGLEagain">-</a>
+
+qh_JOGGLEagain
+every following qh_JOGGLEagain, increase qh.JOGGLEmax
+
+notes:
+1 is OK since it's already failed qh_JOGGLEretry times
+*/
+#define qh_JOGGLEagain 1
+
+/*-<a                             href="qh-user.htm#TOC"
+>--------------------------------</a><a name="JOGGLEmaxincrease">-</a>
+
+qh_JOGGLEmaxincrease
+maximum qh.JOGGLEmax due to qh_JOGGLEincrease
+relative to qh.MAXwidth
+
+notes:
+qh.joggleinput will retry at this value until qh_JOGGLEmaxretry
+*/
+#define qh_JOGGLEmaxincrease 1e-2
+
+/*-<a                             href="qh-user.htm#TOC"
+>--------------------------------</a><a name="JOGGLEmaxretry">-</a>
+
+qh_JOGGLEmaxretry
+stop after qh_JOGGLEmaxretry attempts
+*/
+#define qh_JOGGLEmaxretry 100
+
+/*============================================================*/
+/*============= performance related constants ================*/
+/*============================================================*/
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="HASHfactor">-</a>
+
+  qh_HASHfactor
+    total hash slots / used hash slots.  Must be at least 1.1.
+
+  notes:
+    =2 for at worst 50% occupancy for qh hash_table and normally 25% occupancy
+*/
+#define qh_HASHfactor 2
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="VERIFYdirect">-</a>
+
+  qh_VERIFYdirect
+    with 'Tv' verify all points against all facets if op count is smaller
+
+  notes:
+    if greater, calls qh_check_bestdist() instead
+*/
+#define qh_VERIFYdirect 1000000
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="INITIALsearch">-</a>
+
+  qh_INITIALsearch
+     if qh_INITIALmax, search points up to this dimension
+*/
+#define qh_INITIALsearch 6
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="INITIALmax">-</a>
+
+  qh_INITIALmax
+    if dim >= qh_INITIALmax, use min/max coordinate points for initial simplex
+
+  notes:
+    from points with non-zero determinants
+    use option 'Qs' to override (much slower)
+*/
+#define qh_INITIALmax 8
+
+/*============================================================*/
+/*============= memory constants =============================*/
+/*============================================================*/
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="MEMalign">-</a>
+
+  qh_MEMalign
+    memory alignment for qh_meminitbuffers() in global.c
+
+  notes:
+    to avoid bus errors, memory allocation must consider alignment requirements.
+    malloc() automatically takes care of alignment.   Since mem.c manages
+    its own memory, we need to explicitly specify alignment in
+    qh_meminitbuffers().
+
+    A safe choice is sizeof(double).  sizeof(float) may be used if doubles
+    do not occur in data structures and pointers are the same size.  Be careful
+    of machines (e.g., DEC Alpha) with large pointers.
+
+    If using gcc, best alignment is
+              #define qh_MEMalign fmax_(__alignof__(realT),__alignof__(void *))
+*/
+#define qh_MEMalign ((int)(fmax_(sizeof(realT), sizeof(void *))))
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="MEMbufsize">-</a>
+
+  qh_MEMbufsize
+    size of additional memory buffers
+
+  notes:
+    used for qh_meminitbuffers() in global.c
+*/
+#define qh_MEMbufsize 0x10000       /* allocate 64K memory buffers */
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="MEMinitbuf">-</a>
+
+  qh_MEMinitbuf
+    size of initial memory buffer
+
+  notes:
+    use for qh_meminitbuffers() in global.c
+*/
+#define qh_MEMinitbuf 0x20000      /* initially allocate 128K buffer */
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="INFINITE">-</a>
+
+  qh_INFINITE
+    on output, indicates Voronoi center at infinity
+*/
+#define qh_INFINITE  -10.101
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="DEFAULTbox">-</a>
+
+  qh_DEFAULTbox
+    default box size (Geomview expects 0.5)
+
+  qh_DEFAULTbox
+    default box size for integer coordinate (rbox only)
+*/
+#define qh_DEFAULTbox 0.5
+#define qh_DEFAULTzbox 1e6
+
+/*============================================================*/
+/*============= conditional compilation ======================*/
+/*============================================================*/
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="compiler">-</a>
+
+  __cplusplus
+    defined by C++ compilers
+
+  __MSC_VER
+    defined by Microsoft Visual C++
+
+  __MWERKS__ && __POWERPC__
+    defined by Metrowerks when compiling for the Power Macintosh
+
+  __STDC__
+    defined for strict ANSI C
+*/
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="COMPUTEfurthest">-</a>
+
+  qh_COMPUTEfurthest
+    compute furthest distance to an outside point instead of storing it with the facet
+    =1 to compute furthest
+
+  notes:
+    computing furthest saves memory but costs time
+      about 40% more distance tests for partitioning
+      removes facet->furthestdist
+*/
+#define qh_COMPUTEfurthest 0
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="KEEPstatistics">-</a>
+
+  qh_KEEPstatistics
+    =0 removes most of statistic gathering and reporting
+
+  notes:
+    if 0, code size is reduced by about 4%.
+*/
+#define qh_KEEPstatistics 1
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="MAXoutside">-</a>
+
+  qh_MAXoutside
+    record outer plane for each facet
+    =1 to record facet->maxoutside
+
+  notes:
+    this takes a realT per facet and slightly slows down qhull
+    it produces better outer planes for geomview output
+*/
+#define qh_MAXoutside 1
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="NOmerge">-</a>
+
+  qh_NOmerge
+    disables facet merging if defined
+
+  notes:
+    This saves about 10% space.
+
+    Unless 'Q0'
+      qh_NOmerge sets 'QJ' to avoid precision errors
+
+    #define qh_NOmerge
+
+  see:
+    <a href="mem.h#NOmem">qh_NOmem</a> in mem.c
+
+    see user.c/user_eg.c for removing io.o
+*/
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="NOtrace">-</a>
+
+  qh_NOtrace
+    no tracing if defined
+
+  notes:
+    This saves about 5% space.
+
+    #define qh_NOtrace
+*/
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="QHpointer">-</a>
+
+  qh_QHpointer
+    access global data with pointer or static structure
+
+  qh_QHpointer  = 1     access globals via a pointer to allocated memory
+                        enables qh_saveqhull() and qh_restoreqhull()
+                        [2010, gcc] costs about 4% in time and 4% in space
+                        [2003, msvc] costs about 8% in time and 2% in space
+
+                = 0     qh_qh and qh_qhstat are static data structures
+                        only one instance of qhull() can be active at a time
+                        default value
+
+  qh_QHpointer_dllimport and qh_dllimport define qh_qh as __declspec(dllimport) [libqhull.h]
+  It is required for msvc-2005.  It is not needed for gcc.
+
+  notes:
+    all global variables for qhull are in qh, qhmem, and qhstat
+    qh is defined in libqhull.h
+    qhmem is defined in mem.h
+    qhstat is defined in stat.h
+    C++ build defines qh_QHpointer [libqhullp.pro, libqhullcpp.pro]
+
+  see:
+    user_eg.c for an example
+*/
+#ifdef qh_QHpointer
+#if qh_dllimport
+#error QH6207 Qhull error: Use qh_QHpointer_dllimport instead of qh_dllimport with qh_QHpointer
+#endif
+#else
+#define qh_QHpointer 0
+#if qh_QHpointer_dllimport
+#error QH6234 Qhull error: Use qh_dllimport instead of qh_QHpointer_dllimport when qh_QHpointer is not defined
+#endif
+#endif
+#if 0  /* sample code */
+    qhT *oldqhA, *oldqhB;
+
+    exitcode= qh_new_qhull(dim, numpoints, points, ismalloc,
+                      flags, outfile, errfile);
+    /* use results from first call to qh_new_qhull */
+    oldqhA= qh_save_qhull();
+    exitcode= qh_new_qhull(dimB, numpointsB, pointsB, ismalloc,
+                      flags, outfile, errfile);
+    /* use results from second call to qh_new_qhull */
+    oldqhB= qh_save_qhull();
+    qh_restore_qhull(&oldqhA);
+    /* use results from first call to qh_new_qhull */
+    qh_freeqhull(qh_ALL);  /* frees all memory used by first call */
+    qh_restore_qhull(&oldqhB);
+    /* use results from second call to qh_new_qhull */
+    qh_freeqhull(!qh_ALL); /* frees long memory used by second call */
+    qh_memfreeshort(&curlong, &totlong);  /* frees short memory and memory allocator */
+#endif
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="QUICKhelp">-</a>
+
+  qh_QUICKhelp
+    =1 to use abbreviated help messages, e.g., for degenerate inputs
+*/
+#define qh_QUICKhelp    0
+
+/*============================================================*/
+/*============= -merge constants- ============================*/
+/*============================================================*/
+/*
+   These constants effect facet merging.  You probably will not need
+   to modify them.  They effect the performance of facet merging.
+*/
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="DIMmergeVertex">-</a>
+
+  qh_DIMmergeVertex
+    max dimension for vertex merging (it is not effective in high-d)
+*/
+#define qh_DIMmergeVertex 6
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="DIMreduceBuild">-</a>
+
+  qh_DIMreduceBuild
+     max dimension for vertex reduction during build (slow in high-d)
+*/
+#define qh_DIMreduceBuild 5
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="BESTcentrum">-</a>
+
+  qh_BESTcentrum
+     if > 2*dim+n vertices, qh_findbestneighbor() tests centrums (faster)
+     else, qh_findbestneighbor() tests all vertices (much better merges)
+
+  qh_BESTcentrum2
+     if qh_BESTcentrum2 * DIM3 + BESTcentrum < #vertices tests centrums
+*/
+#define qh_BESTcentrum 20
+#define qh_BESTcentrum2 2
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="BESTnonconvex">-</a>
+
+  qh_BESTnonconvex
+    if > dim+n neighbors, qh_findbestneighbor() tests nonconvex ridges.
+
+  notes:
+    It is needed because qh_findbestneighbor is slow for large facets
+*/
+#define qh_BESTnonconvex 15
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="MAXnewmerges">-</a>
+
+  qh_MAXnewmerges
+    if >n newmerges, qh_merge_nonconvex() calls qh_reducevertices_centrums.
+
+  notes:
+    It is needed because postmerge can merge many facets at once
+*/
+#define qh_MAXnewmerges 2
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="MAXnewcentrum">-</a>
+
+  qh_MAXnewcentrum
+    if <= dim+n vertices (n approximates the number of merges),
+      reset the centrum in qh_updatetested() and qh_mergecycle_facets()
+
+  notes:
+    needed to reduce cost and because centrums may move too much if
+    many vertices in high-d
+*/
+#define qh_MAXnewcentrum 5
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="COPLANARratio">-</a>
+
+  qh_COPLANARratio
+    for 3-d+ merging, qh.MINvisible is n*premerge_centrum
+
+  notes:
+    for non-merging, it's DISTround
+*/
+#define qh_COPLANARratio 3
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="DISToutside">-</a>
+
+  qh_DISToutside
+    When is a point clearly outside of a facet?
+    Stops search in qh_findbestnew or qh_partitionall
+    qh_findbest uses qh.MINoutside since since it is only called if no merges.
+
+  notes:
+    'Qf' always searches for best facet
+    if !qh.MERGING, same as qh.MINoutside.
+    if qh_USEfindbestnew, increase value since neighboring facets may be ill-behaved
+      [Note: Zdelvertextot occurs normally with interior points]
+            RBOX 1000 s Z1 G1e-13 t1001188774 | QHULL Tv
+    When there is a sharp edge, need to move points to a
+    clearly good facet; otherwise may be lost in another partitioning.
+    if too big then O(n^2) behavior for partitioning in cone
+    if very small then important points not processed
+    Needed in qh_partitionall for
+      RBOX 1000 s Z1 G1e-13 t1001032651 | QHULL Tv
+    Needed in qh_findbestnew for many instances of
+      RBOX 1000 s Z1 G1e-13 t | QHULL Tv
+
+  See:
+    qh_DISToutside -- when is a point clearly outside of a facet
+    qh_SEARCHdist -- when is facet coplanar with the best facet?
+    qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
+*/
+#define qh_DISToutside ((qh_USEfindbestnew ? 2 : 1) * \
+     fmax_((qh MERGING ? 2 : 1)*qh MINoutside, qh max_outside))
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="RATIOnearinside">-</a>
+
+  qh_RATIOnearinside
+    ratio of qh.NEARinside to qh.ONEmerge for retaining inside points for
+    qh_check_maxout().
+
+  notes:
+    This is overkill since do not know the correct value.
+    It effects whether 'Qc' reports all coplanar points
+    Not used for 'd' since non-extreme points are coplanar
+*/
+#define qh_RATIOnearinside 5
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="SEARCHdist">-</a>
+
+  qh_SEARCHdist
+    When is a facet coplanar with the best facet?
+    qh_findbesthorizon: all coplanar facets of the best facet need to be searched.
+
+  See:
+    qh_DISToutside -- when is a point clearly outside of a facet
+    qh_SEARCHdist -- when is facet coplanar with the best facet?
+    qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
+*/
+#define qh_SEARCHdist ((qh_USEfindbestnew ? 2 : 1) * \
+      (qh max_outside + 2 * qh DISTround + fmax_( qh MINvisible, qh MAXcoplanar)));
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="USEfindbestnew">-</a>
+
+  qh_USEfindbestnew
+     Always use qh_findbestnew for qh_partitionpoint, otherwise use
+     qh_findbestnew if merged new facet or sharpnewfacets.
+
+  See:
+    qh_DISToutside -- when is a point clearly outside of a facet
+    qh_SEARCHdist -- when is facet coplanar with the best facet?
+    qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
+*/
+#define qh_USEfindbestnew (zzval_(Ztotmerge) > 50)
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="WIDEcoplanar">-</a>
+
+  qh_WIDEcoplanar
+    n*MAXcoplanar or n*MINvisible for a WIDEfacet
+
+    if vertex is further than qh.WIDEfacet from the hyperplane
+    then its ridges are not counted in computing the area, and
+    the facet's centrum is frozen.
+
+  notes:
+   qh.WIDEfacet= max(qh.MAXoutside,qh_WIDEcoplanar*qh.MAXcoplanar,
+      qh_WIDEcoplanar * qh.MINvisible);
+*/
+#define qh_WIDEcoplanar 6
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="MAXnarrow">-</a>
+
+  qh_MAXnarrow
+    max. cosine in initial hull that sets qh.NARROWhull
+
+  notes:
+    If qh.NARROWhull, the initial partition does not make
+    coplanar points.  If narrow, a coplanar point can be
+    coplanar to two facets of opposite orientations and
+    distant from the exact convex hull.
+
+    Conservative estimate.  Don't actually see problems until it is -1.0
+*/
+#define qh_MAXnarrow -0.99999999
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="WARNnarrow">-</a>
+
+  qh_WARNnarrow
+    max. cosine in initial hull to warn about qh.NARROWhull
+
+  notes:
+    this is a conservative estimate.
+    Don't actually see problems until it is -1.0.  See qh-impre.htm
+*/
+#define qh_WARNnarrow -0.999999999999999
+
+/*-<a                             href="qh-user.htm#TOC"
+  >--------------------------------</a><a name="ZEROdelaunay">-</a>
+
+  qh_ZEROdelaunay
+    a zero Delaunay facet occurs for input sites coplanar with their convex hull
+    the last normal coefficient of a zero Delaunay facet is within
+        qh_ZEROdelaunay * qh.ANGLEround of 0
+
+  notes:
+    qh_ZEROdelaunay does not allow for joggled input ('QJ').
+
+    You can avoid zero Delaunay facets by surrounding the input with a box.
+
+    Use option 'PDk:-n' to explicitly define zero Delaunay facets
+      k= dimension of input sites (e.g., 3 for 3-d Delaunay triangulation)
+      n= the cutoff for zero Delaunay facets (e.g., 'PD3:-1e-12')
+*/
+#define qh_ZEROdelaunay 2
+
+#endif /* qh_DEFuser */
+
+
+
diff --git a/alg/libqhull/usermem.c b/alg/libqhull/usermem.c
new file mode 100644
index 0000000..8cb6ba4
--- /dev/null
+++ b/alg/libqhull/usermem.c
@@ -0,0 +1,64 @@
+/*<html><pre>  -<a                             href="qh-user.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   usermem.c
+   qh_exit(), qh_free(), and qh_malloc()
+
+   See README.txt.
+
+   If you redefine one of these functions you must redefine all of them.
+   If you recompile and load this file, then usermem.o will not be loaded
+   from qhull.a or qhull.lib
+
+   See libqhull.h for data structures, macros, and user-callable functions.
+   See user.c for qhull-related, redefinable functions
+   see user.h for user-definable constants
+   See userprintf.c for qh_fprintf and userprintf_rbox,c for qh_fprintf_rbox
+
+   Please report any errors that you fix to qhull at qhull.org
+*/
+
+#include "libqhull.h"
+
+#include <stdlib.h>
+
+/*-<a                             href="qh-user.htm#TOC"
+  >-------------------------------</a><a name="qh_exit">-</a>
+
+  qh_exit( exitcode )
+    exit program
+
+  notes:
+    same as exit()
+*/
+void qh_exit(int exitcode) {
+    exit(exitcode);
+} /* exit */
+
+/*-<a                             href="qh-user.htm#TOC"
+>-------------------------------</a><a name="qh_free">-</a>
+
+qh_free( mem )
+free memory
+
+notes:
+same as free()
+*/
+void qh_free(void *mem) {
+    free(mem);
+} /* free */
+
+/*-<a                             href="qh-user.htm#TOC"
+    >-------------------------------</a><a name="qh_malloc">-</a>
+
+    qh_malloc( mem )
+      allocate memory
+
+    notes:
+      same as malloc()
+*/
+void *qh_malloc(size_t size) {
+    return malloc(size);
+} /* malloc */
+
+
diff --git a/alg/libqhull/userprintf.c b/alg/libqhull/userprintf.c
new file mode 100644
index 0000000..6df4e4c
--- /dev/null
+++ b/alg/libqhull/userprintf.c
@@ -0,0 +1,64 @@
+/*<html><pre>  -<a                             href="qh-user.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   userprintf.c
+   qh_fprintf()
+
+   see README.txt  see COPYING.txt for copyright information.
+
+   If you recompile and load this file, then userprintf.o will not be loaded
+   from qhull.a or qhull.lib
+
+   See libqhull.h for data structures, macros, and user-callable functions.
+   See user.c for qhull-related, redefinable functions
+   see user.h for user-definable constants
+   See usermem.c for qh_exit(), qh_free(), and qh_malloc()
+   see Qhull.cpp and RboxPoints.cpp for examples.
+
+   Please report any errors that you fix to qhull at qhull.org
+*/
+
+#include "libqhull.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/*-<a                             href="qh-user.htm#TOC"
+   >-------------------------------</a><a name="qh_fprintf">-</a>
+
+   qh_fprintf(fp, msgcode, format, list of args )
+     print arguments to *fp according to format
+     Use qh_fprintf_rbox() for rboxlib.c
+
+   notes:
+     same as fprintf()
+     fgets() is not trapped like fprintf()
+     exit qh_fprintf via qh_errexit()
+*/
+
+void qh_fprintf(FILE *fp, int msgcode, const char *fmt, ... ) {
+    va_list args;
+
+    if (!fp) {
+        fprintf(stderr, "QH6232 Qhull internal error (userprintf.c): fp is 0.  Wrong qh_fprintf called.\n");
+        qh_errexit(6232, NULL, NULL);
+    }
+    va_start(args, fmt);
+#if qh_QHpointer
+    if (qh_qh && qh ANNOTATEoutput)
+#else
+    if (qh ANNOTATEoutput)
+#endif
+    {
+      fprintf(fp, "[QH%.4d]", msgcode);
+    }else if (msgcode >= MSG_ERROR && msgcode < MSG_STDERR ) {
+      fprintf(fp, "QH%.4d ", msgcode);
+    }
+    vfprintf(fp, fmt, args);
+    va_end(args);
+
+    /* Place debugging traps here. Use with option 'Tn' */
+
+} /* qh_fprintf */
+
diff --git a/alg/libqhull/userprintf_rbox.c b/alg/libqhull/userprintf_rbox.c
new file mode 100644
index 0000000..92c3572
--- /dev/null
+++ b/alg/libqhull/userprintf_rbox.c
@@ -0,0 +1,53 @@
+/*<html><pre>  -<a                             href="qh-user.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   userprintf_rbox.c
+   qh_fprintf_rbox()
+
+   see README.txt  see COPYING.txt for copyright information.
+
+   If you recompile and load this file, then userprintf_rbox.o will not be loaded
+   from qhull.a or qhull.lib
+
+   See libqhull.h for data structures, macros, and user-callable functions.
+   See user.c for qhull-related, redefinable functions
+   see user.h for user-definable constants
+   See usermem.c for qh_exit(), qh_free(), and qh_malloc()
+   see Qhull.cpp and RboxPoints.cpp for examples.
+
+   Please report any errors that you fix to qhull at qhull.org
+*/
+
+#include "libqhull.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/*-<a                             href="qh-user.htm#TOC"
+   >-------------------------------</a><a name="qh_fprintf_rbox">-</a>
+
+   qh_fprintf_rbox(fp, msgcode, format, list of args )
+     print arguments to *fp according to format
+     Use qh_fprintf_rbox() for rboxlib.c
+
+   notes:
+     same as fprintf()
+     fgets() is not trapped like fprintf()
+     exit qh_fprintf_rbox via qh_errexit_rbox()
+*/
+
+void qh_fprintf_rbox(FILE *fp, int msgcode, const char *fmt, ... ) {
+    va_list args;
+
+    if (!fp) {
+        fprintf(stderr, "QH6231 Qhull internal error (userprintf.c): fp is 0.  Wrong qh_fprintf_rbox called.\n");
+        qh_errexit_rbox(6231);
+    }
+    if (msgcode >= MSG_ERROR && msgcode < MSG_STDERR)
+      fprintf(fp, "QH%.4d ", msgcode);
+    va_start(args, fmt);
+    vfprintf(fp, fmt, args);
+    va_end(args);
+} /* qh_fprintf_rbox */
+
diff --git a/alg/llrasterize.cpp b/alg/llrasterize.cpp
index 8150264..6109a49 100644
--- a/alg/llrasterize.cpp
+++ b/alg/llrasterize.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: llrasterize.cpp 29117 2015-05-02 20:50:05Z rouault $
+ * $Id: llrasterize.cpp 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Vector polygon rasterization code.
@@ -76,16 +76,16 @@ static void llSwapDouble(double *a, double *b)
 /************************************************************************/
 
 /*
- * NOTE: This code was originally adapted from the gdImageFilledPolygon() 
- * function in libgd.  
- * 
+ * NOTE: This code was originally adapted from the gdImageFilledPolygon()
+ * function in libgd.
+ *
  * http://www.boutell.com/gd/
  *
  * It was later adapted for direct inclusion in GDAL and relicensed under
- * the GDAL MIT/X license (pulled from the OpenEV distribution). 
+ * the GDAL MIT/X license (pulled from the OpenEV distribution).
  */
 
-void GDALdllImageFilledPolygon(int nRasterXSize, int nRasterYSize, 
+void GDALdllImageFilledPolygon(int nRasterXSize, int nRasterYSize,
                                int nPartCount, int *panPartSize,
                                double *padfX, double *padfY,
                                double *dfVariant,
@@ -120,7 +120,8 @@ No known bug
     for( part = 0; part < nPartCount; part++ )
         n += panPartSize[part];
 
-    polyInts = (int *) malloc(sizeof(int) * n);
+    // +1 to make clang static analyzer not warn about potential malloc(0)
+    polyInts = (int *) malloc(sizeof(int) * (n+1));
 
     dminy = padfY[0];
     dmaxy = padfY[0];
@@ -135,14 +136,12 @@ No known bug
     }
     miny = (int) dminy;
     maxy = (int) dmaxy;
-    
-    
+
     if( miny < 0 )
         miny = 0;
     if( maxy >= nRasterYSize )
         maxy = nRasterYSize-1;
-   
-    
+
     minx = 0;
     maxx = nRasterXSize - 1;
 
@@ -151,7 +150,6 @@ No known bug
         int	partoffset = 0;
 
         dy = y +0.5; /* center height of line*/
-         
 
         part = 0;
         ints = 0;
@@ -160,8 +158,7 @@ No known bug
         memset(polyInts, -1, sizeof(int) * n);
 
         for (i=0; (i < n); i++) {
-        
-            
+
             if( i == partoffset + panPartSize[part] ) {
                 partoffset += panPartSize[part];
                 part++;
@@ -174,11 +171,9 @@ No known bug
                 ind1 = i-1;
                 ind2 = i;
             }
-	    
 
             dy1 = padfY[ind1];
             dy2 = padfY[ind2];
-            
 
             if( (dy1 < dy && dy2 < dy) || (dy1 > dy && dy2 > dy) )
                 continue;
@@ -193,15 +188,15 @@ No known bug
                 dx1 = padfX[ind2];
             } else /* if (fabs(dy1-dy2)< 1.e-6) */
             {
-                
-                /*AE: DO NOT skip bottom horizontal segments 
-                  -Fill them separately- 
+
+                /*AE: DO NOT skip bottom horizontal segments
+                  -Fill them separately-
                   They are not taken into account twice.*/
                 if (padfX[ind1] > padfX[ind2])
                 {
                     horizontal_x1 = (int) floor(padfX[ind2]+0.5);
                     horizontal_x2 = (int) floor(padfX[ind1]+0.5);
-		
+
                     if  ( (horizontal_x1 >  maxx) ||  (horizontal_x2 <= minx) )
                         continue;
 
@@ -216,15 +211,15 @@ No known bug
 
             if(( dy < dy2 ) && (dy >= dy1))
             {
-                
+
                 intersect = (dy-dy1) * (dx2-dx1) / (dy2-dy1) + dx1;
 
                 polyInts[ints++] = (int) floor(intersect+0.5);
             }
         }
 
-        /* 
-         * It would be more efficient to do this inline, to avoid 
+        /*
+         * It would be more efficient to do this inline, to avoid
          * a function call for each comparison.
          * NOTE - mloskot: make llCompareInt a functor and use std
          * algorithm and it will be optimized and expanded
@@ -274,7 +269,7 @@ void GDALdllImagePoint( int nRasterXSize, int nRasterYSize,
 /*                         GDALdllImageLine()                           */
 /************************************************************************/
 
-void GDALdllImageLine( int nRasterXSize, int nRasterYSize, 
+void GDALdllImageLine( int nRasterXSize, int nRasterYSize,
                        int nPartCount, int *panPartSize,
                        double *padfX, double *padfY, double *padfVariant,
                        llPointFunc pfnPointFunc, void *pCBData )
@@ -297,7 +292,7 @@ void GDALdllImageLine( int nRasterXSize, int nRasterYSize,
             const int iY1 = (int)floor( padfY[n + j] );
 
             double dfVariant = 0, dfVariant1 = 0;
-            if( padfVariant != NULL && 
+            if( padfVariant != NULL &&
                 ((GDALRasterizeInfo *)pCBData)->eBurnValueSource !=
                     GBV_UserBurnValue )
             {
@@ -314,7 +309,7 @@ void GDALdllImageLine( int nRasterXSize, int nRasterYSize,
 
             // Determine the line slope.
             if ( nDeltaX >= nDeltaY )
-            {           
+            {
                 const int nXError = nDeltaY << 1;
                 const int nYError = nXError - (nDeltaX << 1);
                 int nError = nXError - nDeltaX;
@@ -332,13 +327,13 @@ void GDALdllImageLine( int nRasterXSize, int nRasterYSize,
                     dfVariant += dfDeltaVariant;
                     iX += nXStep;
                     if ( nError > 0 )
-                    { 
+                    {
                         iY += nYStep;
                         nError += nYError;
                     }
                     else
                         nError += nXError;
-                }		
+                }
             }
             else
             {
@@ -359,7 +354,7 @@ void GDALdllImageLine( int nRasterXSize, int nRasterYSize,
                     dfVariant += dfDeltaVariant;
                     iY += nYStep;
                     if ( nError > 0 )
-                    { 
+                    {
                         iX += nXStep;
                         nError += nYError;
                     }
@@ -384,8 +379,8 @@ void GDALdllImageLine( int nRasterXSize, int nRasterYSize,
 /*      will be drawn with the burn value.                              */
 /************************************************************************/
 
-void 
-GDALdllImageLineAllTouched(int nRasterXSize, int nRasterYSize, 
+void
+GDALdllImageLineAllTouched(int nRasterXSize, int nRasterYSize,
                            int nPartCount, int *panPartSize,
                            double *padfX, double *padfY, double *padfVariant,
                            llPointFunc pfnPointFunc, void *pCBData )
@@ -431,7 +426,7 @@ GDALdllImageLineAllTouched(int nRasterXSize, int nRasterYSize,
                 llSwapDouble( &dfY, &dfYEnd );
                 llSwapDouble( &dfVariant, &dfVariantEnd );
             }
-            
+
             // Special case for vertical lines.
             if( floor(dfX) == floor(dfXEnd) )
             {
@@ -485,7 +480,7 @@ GDALdllImageLineAllTouched(int nRasterXSize, int nRasterYSize,
                 int iX = (int) floor(dfX);
                 int iY = (int) floor(dfY);
                 int iXEnd = (int) floor(dfXEnd);
-                
+
                 if( iY >= nRasterYSize )
                     continue;
 
@@ -561,9 +556,9 @@ GDALdllImageLineAllTouched(int nRasterXSize, int nRasterYSize,
                 int iX = (int) floor(dfX);
                 int iY = (int) floor(dfY);
 
-                // burn in the current point.
-                // We should be able to drop the Y check because we cliped in Y,
-                // but there may be some error with all the small steps.
+                // Burn in the current point.
+                // We should be able to drop the Y check because we clipped
+                // in Y, but there may be some error with all the small steps.
                 if( iY >= 0 && iY < nRasterYSize )
                     pfnPointFunc( pCBData, iY, iX, dfVariant );
 
@@ -599,7 +594,7 @@ GDALdllImageLineAllTouched(int nRasterXSize, int nRasterYSize,
                     dfY += dfStepY;
                     dfVariant += dfDeltaVariant * dfStepX;
                 }
-            } // next step along sement.
+            } // next step along segment.
 
         } // next segment
     } // next part
diff --git a/alg/makefile.vc b/alg/makefile.vc
index f1072db..1a240f8 100644
--- a/alg/makefile.vc
+++ b/alg/makefile.vc
@@ -5,7 +5,7 @@
 
 GDAL_ROOT	=	..
 
-EXTRAFLAGS =	-I../ogr/ogrsf_frmts $(GEOS_CFLAGS) 
+EXTRAFLAGS =	-I../ogr/ogrsf_frmts $(GEOS_CFLAGS)
 
 !INCLUDE ..\nmake.opt
 
@@ -13,18 +13,41 @@ EXTRAFLAGS =	-I../ogr/ogrsf_frmts $(GEOS_CFLAGS)
 EXTRAFLAGS = $(EXTRAFLAGS) -DOGR_ENABLED
 !ENDIF
 
+!IFDEF QHULL_SETTING
+!IF "$(QHULL_SETTING)" == "INTERNAL"
+EXTRAFLAGS = $(EXTRAFLAGS) -DINTERNAL_QHULL -Ilibqhull
+!ELSE
+!IF "$(QHULL_SETTING)" == "EXTERNAL"
+EXTRAFLAGS = $(EXTRAFLAGS) -DEXTERNAL_QHULL $(QHULL_INC)
+!ENDIF
+!ENDIF
+!ENDIF
+
 OBJ =	gdaldither.obj gdalmediancut.obj gdal_crs.obj gdaltransformer.obj \
 	gdalsimplewarp.obj gdalwarper.obj gdalwarpkernel.obj \
 	thinplatespline.obj gdal_tps.obj gdalrasterize.obj llrasterize.obj \
 	gdalwarpoperation.obj gdalchecksum.obj gdal_rpc.obj gdalgeoloc.obj \
-	gdalgrid.obj gdalgridsse.obj gdalcutline.obj gdalproximity.obj rasterfill.obj \
+	gdalgrid.obj gdalcutline.obj gdalproximity.obj rasterfill.obj \
 	gdalsievefilter.obj gdalrasterpolygonenumerator.obj polygonize.obj \
-	gdalrasterfpolygonenumerator.obj fpolygonize.obj contour.obj \
+	contour.obj \
 	gdal_octave.obj gdal_simplesurf.obj gdalmatching.obj \
-	gdaltransformgeolocs.obj
-	
+	gdaltransformgeolocs.obj delaunay.obj gdalpansharpen.obj
+
+!IF "$(SSEFLAGS)" == "/DHAVE_SSE_AT_COMPILE_TIME"
+SSE_OBJ = gdalgridsse.obj
+!ENDIF
+
+!IF "$(AVXFLAGS)" == "/DHAVE_AVX_AT_COMPILE_TIME"
+AVX_OBJ = gdalgridavx.obj
+!ENDIF
+
+default:	$(OBJ) $(SSE_OBJ) $(AVX_OBJ)
+
+gdalgridsse.obj:  $*.cpp
+	$(CC) $(CPPFLAGS) $(SSE_ARCH_FLAGS) /c $*.cpp
 
-default:	$(OBJ) 
+gdalgridavx.obj:  $*.cpp
+	$(CC) $(CPPFLAGS) $(AVX_ARCH_FLAGS) /c $*.cpp
 
 clean:
 	-del *.obj
diff --git a/alg/polygonize.cpp b/alg/polygonize.cpp
index 74646f8..500f40b 100644
--- a/alg/polygonize.cpp
+++ b/alg/polygonize.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: polygonize.cpp 28826 2015-03-30 17:51:14Z rouault $
+ * $Id: polygonize.cpp 33757 2016-03-20 20:22:33Z goatbar $
  * Project:  GDAL
  * Purpose:  Raster to Polygon Converter
  * Author:   Frank Warmerdam, warmerdam at pobox.com
@@ -32,9 +32,7 @@
 #include "cpl_string.h"
 #include <vector>
 
-CPL_CVSID("$Id: polygonize.cpp 28826 2015-03-30 17:51:14Z rouault $");
-
-#ifdef OGR_ENABLED
+CPL_CVSID("$Id: polygonize.cpp 33757 2016-03-20 20:22:33Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -48,9 +46,9 @@ CPL_CVSID("$Id: polygonize.cpp 28826 2015-03-30 17:51:14Z rouault $");
 
 class RPolygon {
 public:
-    RPolygon( int nValue ) { nPolyValue = nValue; nLastLineUpdated = -1; }
+    RPolygon(  double dfValue ) { dfPolyValue = dfValue; nLastLineUpdated = -1; }
 
-    int              nPolyValue;
+    double              dfPolyValue;
     int              nLastLineUpdated;
 
     std::vector< std::vector<int> > aanXY;
@@ -68,14 +66,14 @@ void RPolygon::Dump()
 {
     size_t iString;
 
-    printf( "RPolygon: Value=%d, LastLineUpdated=%d\n",
-            nPolyValue, nLastLineUpdated );
-    
+    printf( "RPolygon: Value=%g, LastLineUpdated=%d\n",
+            dfPolyValue, nLastLineUpdated );
+
     for( iString = 0; iString < aanXY.size(); iString++ )
     {
         std::vector<int> &anString = aanXY[iString];
         size_t iVert;
-     
+
         printf( "  String %d:\n", (int) iString );
         for( iVert = 0; iVert < anString.size(); iVert += 2 )
         {
@@ -117,8 +115,8 @@ void RPolygon::Coalesce()
 /*      Loop over the following strings, trying to find one we can      */
 /*      merge onto the end of our base string.                          */
 /* -------------------------------------------------------------------- */
-            for( iString = iBaseString+1; 
-                 iString < aanXY.size(); 
+            for( iString = iBaseString+1;
+                 iString < aanXY.size();
                  iString++ )
             {
                 std::vector<int> &anString = aanXY[iString];
@@ -126,13 +124,13 @@ void RPolygon::Coalesce()
                 if( anBase[anBase.size()-2] == anString[0]
                     && anBase[anBase.size()-1] == anString[1] )
                 {
-                    Merge( iBaseString, iString, 1 );
+                    Merge( static_cast<int>(iBaseString), static_cast<int>(iString), 1 );
                     bMergeHappened = TRUE;
                 }
                 else if( anBase[anBase.size()-2] == anString[anString.size()-2]
                          && anBase[anBase.size()-1] == anString[anString.size()-1] )
                 {
-                    Merge( iBaseString, iString, -1 );
+                    Merge( static_cast<int>(iBaseString), static_cast<int>(iString), -1 );
                     bMergeHappened = TRUE;
                 }
             }
@@ -160,24 +158,24 @@ void RPolygon::Merge( int iBaseString, int iSrcString, int iDirection )
     if( iDirection == 1 )
     {
         iStart = 1;
-        iEnd = anString.size() / 2; 
+        iEnd = static_cast<int>(anString.size()) / 2;
     }
     else
     {
-        iStart = anString.size() / 2 - 2;
-        iEnd = -1; 
+        iStart = static_cast<int>(anString.size()) / 2 - 2;
+        iEnd = -1;
     }
-    
+
     for( i = iStart; i != iEnd; i += iDirection )
     {
         anBase.push_back( anString[i*2+0] );
         anBase.push_back( anString[i*2+1] );
     }
-    
+
     if( iSrcString < ((int) aanXY.size())-1 )
         aanXY[iSrcString] = aanXY[aanXY.size()-1];
 
-    size_t nSize = aanXY.size(); 
+    size_t nSize = aanXY.size();
     aanXY.resize(nSize-1);
 }
 
@@ -199,8 +197,8 @@ void RPolygon::AddSegment( int x1, int y1, int x2, int y2 )
     {
         std::vector<int> &anString = aanXY[iString];
         size_t nSSize = anString.size();
-        
-        if( anString[nSSize-2] == x1 
+
+        if( anString[nSSize-2] == x1
             && anString[nSSize-1] == y1 )
         {
             int nTemp;
@@ -214,16 +212,16 @@ void RPolygon::AddSegment( int x1, int y1, int x2, int y2 )
             y1 = nTemp;
         }
 
-        if( anString[nSSize-2] == x2 
+        if( anString[nSSize-2] == x2
             && anString[nSSize-1] == y2 )
         {
-            // We are going to add a segment, but should we just extend 
+            // We are going to add a segment, but should we just extend
             // an existing segment already going in the right direction?
 
             int nLastLen = MAX(ABS(anString[nSSize-4]-anString[nSSize-2]),
                                ABS(anString[nSSize-3]-anString[nSSize-1]));
-            
-            if( nSSize >= 4 
+
+            if( nSSize >= 4
                 && (anString[nSSize-4] - anString[nSSize-2]
                     == (anString[nSSize-2] - x1)*nLastLen)
                 && (anString[nSSize-3] - anString[nSSize-1]
@@ -269,8 +267,9 @@ void RPolygon::AddSegment( int x1, int y1, int x2, int y2 )
 /*      other side of the edge.                                         */
 /************************************************************************/
 
-static void AddEdges( GInt32 *panThisLineId, GInt32 *panLastLineId, 
-                      GInt32 *panPolyIdMap, GInt32 *panPolyValue,
+template<class DataType>
+static void AddEdges( GInt32 *panThisLineId, GInt32 *panLastLineId,
+                      GInt32 *panPolyIdMap, DataType *panPolyValue,
                       RPolygon **papoPoly, int iX, int iY )
 
 {
@@ -347,7 +346,7 @@ EmitPolygonToLayer( OGRLayerH hOutLayer, int iPixValField,
     size_t iString;
 
     hPolygon = OGR_G_CreateGeometry( wkbPolygon );
-    
+
     for( iString = 0; iString < poRPoly->aanXY.size(); iString++ )
     {
         std::vector<int> &anString = poRPoly->aanXY[iString];
@@ -355,20 +354,20 @@ EmitPolygonToLayer( OGRLayerH hOutLayer, int iPixValField,
 
         int iVert;
 
-        // we go last to first to ensure the linestring is allocated to 
+        // we go last to first to ensure the linestring is allocated to
         // the proper size on the first try.
-        for( iVert = anString.size()/2 - 1; iVert >= 0; iVert-- )
+        for( iVert = static_cast<int>(anString.size())/2 - 1; iVert >= 0; iVert-- )
         {
             double dfX, dfY;
             int    nPixelX, nPixelY;
-            
+
             nPixelX = anString[iVert*2];
             nPixelY = anString[iVert*2+1];
 
-            dfX = padfGeoTransform[0] 
+            dfX = padfGeoTransform[0]
                 + nPixelX * padfGeoTransform[1]
                 + nPixelY * padfGeoTransform[2];
-            dfY = padfGeoTransform[3] 
+            dfY = padfGeoTransform[3]
                 + nPixelX * padfGeoTransform[4]
                 + nPixelY * padfGeoTransform[5];
 
@@ -377,7 +376,7 @@ EmitPolygonToLayer( OGRLayerH hOutLayer, int iPixValField,
 
         OGR_G_AddGeometryDirectly( hPolygon, hRing );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create the feature object.                                      */
 /* -------------------------------------------------------------------- */
@@ -386,7 +385,7 @@ EmitPolygonToLayer( OGRLayerH hOutLayer, int iPixValField,
     OGR_F_SetGeometryDirectly( hFeat, hPolygon );
 
     if( iPixValField >= 0 )
-        OGR_F_SetFieldInteger( hFeat, iPixValField, poRPoly->nPolyValue );
+        OGR_F_SetFieldDouble( hFeat, iPixValField, poRPoly->dfPolyValue );
 
 /* -------------------------------------------------------------------- */
 /*      Write the to the layer.                                         */
@@ -408,14 +407,15 @@ EmitPolygonToLayer( OGRLayerH hOutLayer, int iPixValField,
 /*      band is zero.                                                   */
 /************************************************************************/
 
-static CPLErr 
-GPMaskImageData( GDALRasterBandH hMaskBand, GByte* pabyMaskLine, int iY, int nXSize, 
-                 GInt32 *panImageLine )
+template<class DataType>
+static CPLErr
+GPMaskImageData( GDALRasterBandH hMaskBand, GByte* pabyMaskLine, int iY, int nXSize,
+                 DataType *panImageLine )
 
 {
     CPLErr eErr;
 
-    eErr = GDALRasterIO( hMaskBand, GF_Read, 0, iY, nXSize, 1, 
+    eErr = GDALRasterIO( hMaskBand, GF_Read, 0, iY, nXSize, 1,
                          pabyMaskLine, nXSize, 1, GDT_Byte, 0, 0 );
     if( eErr == CE_None )
     {
@@ -429,79 +429,22 @@ GPMaskImageData( GDALRasterBandH hMaskBand, GByte* pabyMaskLine, int iY, int nXS
 
     return eErr;
 }
-#endif // OGR_ENABLED
 
 /************************************************************************/
-/*                           GDALPolygonize()                           */
+/*                           GDALPolygonizeT()                          */
 /************************************************************************/
 
-/**
- * Create polygon coverage from raster data.
- *
- * This function creates vector polygons for all connected regions of pixels in
- * the raster sharing a common pixel value.  Optionally each polygon may be
- * labelled with the pixel value in an attribute.  Optionally a mask band
- * can be provided to determine which pixels are eligible for processing.
- *
- * Note that currently the source pixel band values are read into a
- * signed 32bit integer buffer (Int32), so floating point or complex 
- * bands will be implicitly truncated before processing. If you want to use a
- * version using 32bit float buffers, see GDALFPolygonize() at fpolygonize.cpp.
- *
- * Polygon features will be created on the output layer, with polygon 
- * geometries representing the polygons.  The polygon geometries will be
- * in the georeferenced coordinate system of the image (based on the
- * geotransform of the source dataset).  It is acceptable for the output
- * layer to already have features.  Note that GDALPolygonize() does not
- * set the coordinate system on the output layer.  Application code should
- * do this when the layer is created, presumably matching the raster 
- * coordinate system. 
- *
- * The algorithm used attempts to minimize memory use so that very large
- * rasters can be processed.  However, if the raster has many polygons 
- * or very large/complex polygons, the memory use for holding polygon 
- * enumerations and active polygon geometries may grow to be quite large. 
- *
- * The algorithm will generally produce very dense polygon geometries, with
- * edges that follow exactly on pixel boundaries for all non-interior pixels.
- * For non-thematic raster data (such as satellite images) the result will
- * essentially be one small polygon per pixel, and memory and output layer
- * sizes will be substantial.  The algorithm is primarily intended for 
- * relatively simple thematic imagery, masks, and classification results. 
- * 
- * @param hSrcBand the source raster band to be processed.
- * @param hMaskBand an optional mask band.  All pixels in the mask band with a 
- * value other than zero will be considered suitable for collection as 
- * polygons.  
- * @param hOutLayer the vector feature layer to which the polygons should
- * be written. 
- * @param iPixValField the attribute field index indicating the feature
- * attribute into which the pixel value of the polygon should be written.
- * @param papszOptions a name/value list of additional options
- * <dl>
- * <dt>"8CONNECTED":</dt> May be set to "8" to use 8 connectedness.
- * Otherwise 4 connectedness will be applied to the algorithm
- * </dl>
- * @param pfnProgress callback for reporting algorithm progress matching the
- * GDALProgressFunc() semantics.  May be NULL.
- * @param pProgressArg callback argument passed to pfnProgress.
- * 
- * @return CE_None on success or CE_Failure on a failure.
- */
-
-CPLErr CPL_STDCALL
-GDALPolygonize( GDALRasterBandH hSrcBand, 
-                GDALRasterBandH hMaskBand,
-                OGRLayerH hOutLayer, int iPixValField, 
-                char **papszOptions,
-                GDALProgressFunc pfnProgress, 
-                void * pProgressArg )
+template<class DataType, class EqualityTest>
+static CPLErr
+GDALPolygonizeT( GDALRasterBandH hSrcBand,
+                 GDALRasterBandH hMaskBand,
+                 OGRLayerH hOutLayer, int iPixValField,
+                 char **papszOptions,
+                 GDALProgressFunc pfnProgress,
+                 void * pProgressArg,
+                 GDALDataType eDT)
 
 {
-#ifndef OGR_ENABLED
-    CPLError(CE_Failure, CPLE_NotSupported, "GDALPolygonize() unimplemented in a non OGR build");
-    return CE_Failure;
-#else
     VALIDATE_POINTER1( hSrcBand, "GDALPolygonize", CE_Failure );
     VALIDATE_POINTER1( hOutLayer, "GDALPolygonize", CE_Failure );
 
@@ -527,17 +470,15 @@ GDALPolygonize( GDALRasterBandH hSrcBand,
     CPLErr eErr = CE_None;
     int nXSize = GDALGetRasterBandXSize( hSrcBand );
     int nYSize = GDALGetRasterBandYSize( hSrcBand );
-    GInt32 *panLastLineVal = (GInt32 *) VSIMalloc2(sizeof(GInt32),nXSize + 2);
-    GInt32 *panThisLineVal = (GInt32 *) VSIMalloc2(sizeof(GInt32),nXSize + 2);
-    GInt32 *panLastLineId =  (GInt32 *) VSIMalloc2(sizeof(GInt32),nXSize + 2);
-    GInt32 *panThisLineId =  (GInt32 *) VSIMalloc2(sizeof(GInt32),nXSize + 2);
-    GByte *pabyMaskLine = (hMaskBand != NULL) ? (GByte *) VSIMalloc(nXSize) : NULL;
+    DataType *panLastLineVal = (DataType *) VSI_MALLOC2_VERBOSE(sizeof(DataType),nXSize + 2);
+    DataType *panThisLineVal = (DataType *) VSI_MALLOC2_VERBOSE(sizeof(DataType),nXSize + 2);
+    GInt32 *panLastLineId =  (GInt32 *) VSI_MALLOC2_VERBOSE(sizeof(GInt32),nXSize + 2);
+    GInt32 *panThisLineId =  (GInt32 *) VSI_MALLOC2_VERBOSE(sizeof(GInt32),nXSize + 2);
+    GByte *pabyMaskLine = (hMaskBand != NULL) ? (GByte *) VSI_MALLOC_VERBOSE(nXSize) : NULL;
     if (panLastLineVal == NULL || panThisLineVal == NULL ||
         panLastLineId == NULL || panThisLineId == NULL ||
         (hMaskBand != NULL && pabyMaskLine == NULL))
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory,
-                 "Could not allocate enough memory for temporary buffers");
         CPLFree( panThisLineId );
         CPLFree( panLastLineId );
         CPLFree( panThisLineVal );
@@ -562,41 +503,41 @@ GDALPolygonize( GDALRasterBandH hSrcBand,
 /*      what on the second pass.                                        */
 /* -------------------------------------------------------------------- */
     int iY;
-    GDALRasterPolygonEnumerator oFirstEnum(nConnectedness);
+    GDALRasterPolygonEnumeratorT<DataType, EqualityTest> oFirstEnum(nConnectedness);
 
     for( iY = 0; eErr == CE_None && iY < nYSize; iY++ )
     {
-        eErr = GDALRasterIO( 
+        eErr = GDALRasterIO(
             hSrcBand,
-            GF_Read, 0, iY, nXSize, 1, 
-            panThisLineVal, nXSize, 1, GDT_Int32, 0, 0 );
-        
+            GF_Read, 0, iY, nXSize, 1,
+            panThisLineVal, nXSize, 1, eDT, 0, 0 );
+
         if( eErr == CE_None && hMaskBand != NULL )
             eErr = GPMaskImageData( hMaskBand, pabyMaskLine, iY, nXSize, panThisLineVal );
 
         if( iY == 0 )
-            oFirstEnum.ProcessLine( 
+            oFirstEnum.ProcessLine(
                 NULL, panThisLineVal, NULL, panThisLineId, nXSize );
         else
             oFirstEnum.ProcessLine(
-                panLastLineVal, panThisLineVal, 
-                panLastLineId,  panThisLineId, 
+                panLastLineVal, panThisLineVal,
+                panLastLineId,  panThisLineId,
                 nXSize );
 
         // swap lines
-        GInt32 *panTmp = panLastLineVal;
+        DataType *panTmpVal = panLastLineVal;
         panLastLineVal = panThisLineVal;
-        panThisLineVal = panTmp;
+        panThisLineVal = panTmpVal;
 
-        panTmp = panThisLineId;
+        GInt32* panTmp = panThisLineId;
         panThisLineId = panLastLineId;
         panLastLineId = panTmp;
 
 /* -------------------------------------------------------------------- */
 /*      Report progress, and support interrupts.                        */
 /* -------------------------------------------------------------------- */
-        if( eErr == CE_None 
-            && !pfnProgress( 0.10 * ((iY+1) / (double) nYSize), 
+        if( eErr == CE_None
+            && !pfnProgress( 0.10 * ((iY+1) / (double) nYSize),
                              "", pProgressArg ) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
@@ -625,11 +566,11 @@ GDALPolygonize( GDALRasterBandH hSrcBand,
         panLastLineId[iX] = -1;
 
 /* -------------------------------------------------------------------- */
-/*      We will use a new enumerator for the second pass primariliy     */
+/*      We will use a new enumerator for the second pass primarily      */
 /*      so we can preserve the first pass map.                          */
 /* -------------------------------------------------------------------- */
-    GDALRasterPolygonEnumerator oSecondEnum(nConnectedness);
-    RPolygon **papoPoly = (RPolygon **) 
+    GDALRasterPolygonEnumeratorT<DataType, EqualityTest> oSecondEnum(nConnectedness);
+    RPolygon **papoPoly = (RPolygon **)
         CPLCalloc(sizeof(RPolygon*),oFirstEnum.nNextPolygonId);
 
 /* ==================================================================== */
@@ -643,8 +584,8 @@ GDALPolygonize( GDALRasterBandH hSrcBand,
 /* -------------------------------------------------------------------- */
         if( iY < nYSize )
         {
-            eErr = GDALRasterIO( hSrcBand, GF_Read, 0, iY, nXSize, 1, 
-                                 panThisLineVal, nXSize, 1, GDT_Int32, 0, 0 );
+            eErr = GDALRasterIO( hSrcBand, GF_Read, 0, iY, nXSize, 1,
+                                 panThisLineVal, nXSize, 1, eDT, 0, 0 );
 
             if( eErr == CE_None && hMaskBand != NULL )
                 eErr = GPMaskImageData( hMaskBand, pabyMaskLine, iY, nXSize, panThisLineVal );
@@ -663,12 +604,12 @@ GDALPolygonize( GDALRasterBandH hSrcBand,
                 panThisLineId[iX] = -1;
         }
         else if( iY == 0 )
-            oSecondEnum.ProcessLine( 
+            oSecondEnum.ProcessLine(
                 NULL, panThisLineVal, NULL, panThisLineId+1, nXSize );
         else
             oSecondEnum.ProcessLine(
-                panLastLineVal, panThisLineVal, 
-                panLastLineId+1,  panThisLineId+1, 
+                panLastLineVal, panThisLineVal,
+                panLastLineId+1,  panThisLineId+1,
                 nXSize );
 
 /* -------------------------------------------------------------------- */
@@ -677,7 +618,7 @@ GDALPolygonize( GDALRasterBandH hSrcBand,
 /* -------------------------------------------------------------------- */
         for( iX = 0; iX < nXSize+1; iX++ )
         {
-            AddEdges( panThisLineId, panLastLineId, 
+            AddEdges( panThisLineId, panLastLineId,
                       oFirstEnum.panPolyIdMap, oFirstEnum.panPolyValue,
                       papoPoly, iX, iY );
         }
@@ -689,14 +630,14 @@ GDALPolygonize( GDALRasterBandH hSrcBand,
 /* -------------------------------------------------------------------- */
         if( iY % 8 == 7 )
         {
-            for( iX = 0; 
-                 eErr == CE_None && iX < oSecondEnum.nNextPolygonId; 
+            for( iX = 0;
+                 eErr == CE_None && iX < oSecondEnum.nNextPolygonId;
                  iX++ )
             {
                 if( papoPoly[iX] && papoPoly[iX]->nLastLineUpdated < iY-1 )
                 {
-                    eErr = 
-                        EmitPolygonToLayer( hOutLayer, iPixValField, 
+                    eErr =
+                        EmitPolygonToLayer( hOutLayer, iPixValField,
                                             papoPoly[iX], adfGeoTransform );
 
                     delete papoPoly[iX];
@@ -709,19 +650,19 @@ GDALPolygonize( GDALRasterBandH hSrcBand,
 /*      Swap pixel value, and polygon id lines to be ready for the      */
 /*      next line.                                                      */
 /* -------------------------------------------------------------------- */
-        GInt32 *panTmp = panLastLineVal;
+        DataType *panTmpVal = panLastLineVal;
         panLastLineVal = panThisLineVal;
-        panThisLineVal = panTmp;
+        panThisLineVal = panTmpVal;
 
-        panTmp = panThisLineId;
+        GInt32* panTmp = panThisLineId;
         panThisLineId = panLastLineId;
         panLastLineId = panTmp;
 
 /* -------------------------------------------------------------------- */
 /*      Report progress, and support interrupts.                        */
 /* -------------------------------------------------------------------- */
-        if( eErr == CE_None 
-            && !pfnProgress( 0.10 + 0.90 * ((iY+1) / (double) nYSize), 
+        if( eErr == CE_None
+            && !pfnProgress( 0.10 + 0.90 * ((iY+1) / (double) nYSize),
                              "", pProgressArg ) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
@@ -736,8 +677,8 @@ GDALPolygonize( GDALRasterBandH hSrcBand,
     {
         if( papoPoly[iX] )
         {
-            eErr = 
-                EmitPolygonToLayer( hOutLayer, iPixValField, 
+            eErr =
+                EmitPolygonToLayer( hOutLayer, iPixValField,
                                     papoPoly[iX], adfGeoTransform );
 
             delete papoPoly[iX];
@@ -756,6 +697,215 @@ GDALPolygonize( GDALRasterBandH hSrcBand,
     CPLFree( papoPoly );
 
     return eErr;
-#endif // OGR_ENABLED
 }
 
+
+/******************************************************************************/
+/*                          GDALFloatEquals()                                 */
+/* Code from:                                                                 */
+/* http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm  */
+/******************************************************************************/
+GBool GDALFloatEquals(float A, float B)
+{
+    /**
+     * This function will allow maxUlps-1 floats between A and B.
+     */
+    const int maxUlps = MAX_ULPS;
+    int aInt, bInt;
+
+    /**
+     * Make sure maxUlps is non-negative and small enough that the default NAN
+     * won't compare as equal to anything.
+     */
+#if MAX_ULPS <= 0 || MAX_ULPS >= 4 * 1024 * 1024
+#error "Invalid MAX_ULPS"
+#endif
+
+    /**
+     * This assignation could violate strict aliasing. It causes a warning with
+     * gcc -O2. Use of memcpy preferred. Credits for Even Rouault. Further info
+     * at http://trac.osgeo.org/gdal/ticket/4005#comment:6
+     */
+    //int aInt = *(int*)&A;
+    memcpy(&aInt, &A, 4);
+
+    /**
+     * Make aInt lexicographically ordered as a twos-complement int
+     */
+    if (aInt < 0)
+        aInt = 0x80000000 - aInt;
+    /**
+     * Make bInt lexicographically ordered as a twos-complement int
+     */
+    //int bInt = *(int*)&B;
+    memcpy(&bInt, &B, 4);
+
+    if (bInt < 0)
+        bInt = 0x80000000 - bInt;
+#ifdef COMPAT_WITH_ICC_CONVERSION_CHECK
+    int intDiff = abs((int) (((GUIntBig)((GIntBig)aInt - (GIntBig)bInt)) & 0xFFFFFFFFU) );
+#else
+    /* to make -ftrapv happy we compute the diff on larger type and cast down later */
+    int intDiff = abs((int)((GIntBig)aInt - (GIntBig)bInt));
+#endif
+    if (intDiff <= maxUlps)
+        return true;
+    return false;
+}
+
+
+/************************************************************************/
+/*                           GDALPolygonize()                           */
+/************************************************************************/
+
+/**
+ * Create polygon coverage from raster data.
+ *
+ * This function creates vector polygons for all connected regions of pixels in
+ * the raster sharing a common pixel value.  Optionally each polygon may be
+ * labeled with the pixel value in an attribute.  Optionally a mask band
+ * can be provided to determine which pixels are eligible for processing.
+ *
+ * Note that currently the source pixel band values are read into a
+ * signed 32bit integer buffer (Int32), so floating point or complex
+ * bands will be implicitly truncated before processing. If you want to use a
+ * version using 32bit float buffers, see GDALFPolygonize().
+  *
+ * Polygon features will be created on the output layer, with polygon
+ * geometries representing the polygons.  The polygon geometries will be
+ * in the georeferenced coordinate system of the image (based on the
+ * geotransform of the source dataset).  It is acceptable for the output
+ * layer to already have features.  Note that GDALPolygonize() does not
+ * set the coordinate system on the output layer.  Application code should
+ * do this when the layer is created, presumably matching the raster
+ * coordinate system.
+ *
+ * The algorithm used attempts to minimize memory use so that very large
+ * rasters can be processed.  However, if the raster has many polygons
+ * or very large/complex polygons, the memory use for holding polygon
+ * enumerations and active polygon geometries may grow to be quite large.
+ *
+ * The algorithm will generally produce very dense polygon geometries, with
+ * edges that follow exactly on pixel boundaries for all non-interior pixels.
+ * For non-thematic raster data (such as satellite images) the result will
+ * essentially be one small polygon per pixel, and memory and output layer
+ * sizes will be substantial.  The algorithm is primarily intended for
+ * relatively simple thematic imagery, masks, and classification results.
+ *
+ * @param hSrcBand the source raster band to be processed.
+ * @param hMaskBand an optional mask band.  All pixels in the mask band with a
+ * value other than zero will be considered suitable for collection as
+ * polygons.
+ * @param hOutLayer the vector feature layer to which the polygons should
+ * be written.
+ * @param iPixValField the attribute field index indicating the feature
+ * attribute into which the pixel value of the polygon should be written.
+ * @param papszOptions a name/value list of additional options
+ * <dl>
+ * <dt>"8CONNECTED":</dt> May be set to "8" to use 8 connectedness.
+ * Otherwise 4 connectedness will be applied to the algorithm
+ * </dl>
+ * @param pfnProgress callback for reporting algorithm progress matching the
+ * GDALProgressFunc() semantics.  May be NULL.
+ * @param pProgressArg callback argument passed to pfnProgress.
+ *
+ * @return CE_None on success or CE_Failure on a failure.
+ */
+
+CPLErr CPL_STDCALL
+GDALPolygonize( GDALRasterBandH hSrcBand,
+                GDALRasterBandH hMaskBand,
+                OGRLayerH hOutLayer, int iPixValField,
+                char **papszOptions,
+                GDALProgressFunc pfnProgress,
+                void * pProgressArg )
+
+{
+    return GDALPolygonizeT<GInt32, IntEqualityTest>(hSrcBand,
+                                                    hMaskBand,
+                                                    hOutLayer,
+                                                    iPixValField,
+                                                    papszOptions,
+                                                    pfnProgress,
+                                                    pProgressArg,
+                                                    GDT_Int32);
+}
+
+
+/************************************************************************/
+/*                           GDALFPolygonize()                           */
+/************************************************************************/
+
+/**
+ * Create polygon coverage from raster data.
+ *
+ * This function creates vector polygons for all connected regions of pixels in
+ * the raster sharing a common pixel value.  Optionally each polygon may be
+ * labeled with the pixel value in an attribute.  Optionally a mask band
+ * can be provided to determine which pixels are eligible for processing.
+ *
+ * The source pixel band values are read into a 32bit float buffer. If you want
+ * to use a (probably faster) version using signed 32bit integer buffer, see
+ * GDALPolygonize().
+ *
+ * Polygon features will be created on the output layer, with polygon
+ * geometries representing the polygons.  The polygon geometries will be
+ * in the georeferenced coordinate system of the image (based on the
+ * geotransform of the source dataset).  It is acceptable for the output
+ * layer to already have features.  Note that GDALFPolygonize() does not
+ * set the coordinate system on the output layer.  Application code should
+ * do this when the layer is created, presumably matching the raster
+ * coordinate system.
+ *
+ * The algorithm used attempts to minimize memory use so that very large
+ * rasters can be processed.  However, if the raster has many polygons
+ * or very large/complex polygons, the memory use for holding polygon
+ * enumerations and active polygon geometries may grow to be quite large.
+ *
+ * The algorithm will generally produce very dense polygon geometries, with
+ * edges that follow exactly on pixel boundaries for all non-interior pixels.
+ * For non-thematic raster data (such as satellite images) the result will
+ * essentially be one small polygon per pixel, and memory and output layer
+ * sizes will be substantial.  The algorithm is primarily intended for
+ * relatively simple thematic imagery, masks, and classification results.
+ *
+ * @param hSrcBand the source raster band to be processed.
+ * @param hMaskBand an optional mask band.  All pixels in the mask band with a
+ * value other than zero will be considered suitable for collection as
+ * polygons.
+ * @param hOutLayer the vector feature layer to which the polygons should
+ * be written.
+ * @param iPixValField the attribute field index indicating the feature
+ * attribute into which the pixel value of the polygon should be written.
+ * @param papszOptions a name/value list of additional options
+ * <dl>
+ * <dt>"8CONNECTED":</dt> May be set to "8" to use 8 connectedness.
+ * Otherwise 4 connectedness will be applied to the algorithm
+ * </dl>
+ * @param pfnProgress callback for reporting algorithm progress matching the
+ * GDALProgressFunc() semantics.  May be NULL.
+ * @param pProgressArg callback argument passed to pfnProgress.
+ *
+ * @return CE_None on success or CE_Failure on a failure.
+ *
+ * @since GDAL 1.9.0
+ */
+
+CPLErr CPL_STDCALL
+GDALFPolygonize( GDALRasterBandH hSrcBand,
+                GDALRasterBandH hMaskBand,
+                OGRLayerH hOutLayer, int iPixValField,
+                char **papszOptions,
+                GDALProgressFunc pfnProgress,
+                void * pProgressArg )
+
+{
+    return GDALPolygonizeT<float, FloatEqualityTest>(hSrcBand,
+                                                    hMaskBand,
+                                                    hOutLayer,
+                                                    iPixValField,
+                                                    papszOptions,
+                                                    pfnProgress,
+                                                    pProgressArg,
+                                                    GDT_Float32);
+}
diff --git a/alg/rasterfill.cpp b/alg/rasterfill.cpp
index e76f103..c657103 100644
--- a/alg/rasterfill.cpp
+++ b/alg/rasterfill.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rasterfill.cpp 28342 2015-01-22 12:31:07Z rouault $
+ * $Id: rasterfill.cpp 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Interpolate in nodata areas.
@@ -7,6 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2008, Frank Warmerdam
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  * Copyright (c) 2015, Sean Gillies <sean at mapbox.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -32,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: rasterfill.cpp 28342 2015-01-22 12:31:07Z rouault $");
+CPL_CVSID("$Id: rasterfill.cpp 33715 2016-03-13 08:52:06Z goatbar $");
 
 /************************************************************************/
 /*                           GDALFilterLine()                           */
@@ -142,11 +143,11 @@ GDALFilterLine( float *pafLastLine, float *pafThisLine, float *pafNextLine,
 /************************************************************************/
 
 static CPLErr
-GDALMultiFilter( GDALRasterBandH hTargetBand, 
-                 GDALRasterBandH hTargetMaskBand, 
+GDALMultiFilter( GDALRasterBandH hTargetBand,
+                 GDALRasterBandH hTargetMaskBand,
                  GDALRasterBandH hFiltMaskBand,
                  int nIterations,
-                 GDALProgressFunc pfnProgress, 
+                 GDALProgressFunc pfnProgress,
                  void * pProgressArg )
 
 {
@@ -174,14 +175,12 @@ GDALMultiFilter( GDALRasterBandH hTargetBand,
 /* -------------------------------------------------------------------- */
 /*      Allocate rotating buffers.                                      */
 /* -------------------------------------------------------------------- */
-    pabyTMaskBuf = (GByte *) VSIMalloc2(nXSize, nBufLines);
-    pabyFMaskBuf = (GByte *) VSIMalloc2(nXSize, nBufLines);
+    pabyTMaskBuf = (GByte *) VSI_MALLOC2_VERBOSE(nXSize, nBufLines);
+    pabyFMaskBuf = (GByte *) VSI_MALLOC2_VERBOSE(nXSize, nBufLines);
 
-    paf3PassLineBuf = (float *) VSIMalloc3(nXSize, nBufLines, 3 * sizeof(float));
+    paf3PassLineBuf = (float *) VSI_MALLOC3_VERBOSE(nXSize, nBufLines, 3 * sizeof(float));
     if (pabyTMaskBuf == NULL || pabyFMaskBuf == NULL || paf3PassLineBuf == NULL)
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory,
-                 "Could not allocate enough memory for temporary buffers");
         eErr = CE_Failure;
         goto end;
     }
@@ -189,8 +188,8 @@ GDALMultiFilter( GDALRasterBandH hTargetBand,
 /* -------------------------------------------------------------------- */
 /*      Process rotating buffers.                                       */
 /* -------------------------------------------------------------------- */
-    for( nNewLine = 0; 
-         eErr == CE_None && nNewLine < nYSize+nIterations; 
+    for( nNewLine = 0;
+         eErr == CE_None && nNewLine < nYSize+nIterations;
          nNewLine++ )
     {
 /* -------------------------------------------------------------------- */
@@ -198,11 +197,11 @@ GDALMultiFilter( GDALRasterBandH hTargetBand,
 /* -------------------------------------------------------------------- */
         iPassCounter = (iPassCounter + 1) % 3;
 
-        pafSLastPass = paf3PassLineBuf 
+        pafSLastPass = paf3PassLineBuf
             + ((iPassCounter+0)%3) * nXSize*nBufLines;
-        pafLastPass = paf3PassLineBuf 
+        pafLastPass = paf3PassLineBuf
             + ((iPassCounter+1)%3) * nXSize*nBufLines;
-        pafThisPass = paf3PassLineBuf 
+        pafThisPass = paf3PassLineBuf
             + ((iPassCounter+2)%3) * nXSize*nBufLines;
 
 /* -------------------------------------------------------------------- */
@@ -216,30 +215,30 @@ GDALMultiFilter( GDALRasterBandH hTargetBand,
 /* -------------------------------------------------------------------- */
         if( nNewLine < nYSize )
         {
-            eErr = 
-                GDALRasterIO( hTargetMaskBand, GF_Read, 
-                              0, nNewLine, nXSize, 1, 
-                              pabyTMaskBuf + nXSize * iBufOffset, nXSize, 1, 
+            eErr =
+                GDALRasterIO( hTargetMaskBand, GF_Read,
+                              0, nNewLine, nXSize, 1,
+                              pabyTMaskBuf + nXSize * iBufOffset, nXSize, 1,
                               GDT_Byte, 0, 0 );
-            
+
             if( eErr != CE_None )
                 break;
 
-            eErr = 
-                GDALRasterIO( hFiltMaskBand, GF_Read, 
-                              0, nNewLine, nXSize, 1, 
-                              pabyFMaskBuf + nXSize * iBufOffset, nXSize, 1, 
+            eErr =
+                GDALRasterIO( hFiltMaskBand, GF_Read,
+                              0, nNewLine, nXSize, 1,
+                              pabyFMaskBuf + nXSize * iBufOffset, nXSize, 1,
                               GDT_Byte, 0, 0 );
-            
+
             if( eErr != CE_None )
                 break;
 
-            eErr = 
-                GDALRasterIO( hTargetBand, GF_Read, 
-                              0, nNewLine, nXSize, 1, 
-                              pafThisPass + nXSize * iBufOffset, nXSize, 1, 
+            eErr =
+                GDALRasterIO( hTargetBand, GF_Read,
+                              0, nNewLine, nXSize, 1,
+                              pafThisPass + nXSize * iBufOffset, nXSize, 1,
                               GDT_Float32, 0, 0 );
-            
+
             if( eErr != CE_None )
                 break;
         }
@@ -256,32 +255,32 @@ GDALMultiFilter( GDALRasterBandH hTargetBand,
         {
             int iLastOffset, iThisOffset, iNextOffset;
 
-            iLastOffset = (iFLine-1) % nBufLines; 
+            iLastOffset = (iFLine-1) % nBufLines;
             iThisOffset = (iFLine  ) % nBufLines;
             iNextOffset = (iFLine+1) % nBufLines;
 
             // default to preserving the old value.
             if( iFLine >= 0 )
-                memcpy( pafThisPass + iThisOffset * nXSize, 
-                        pafLastPass + iThisOffset * nXSize, 
+                memcpy( pafThisPass + iThisOffset * nXSize,
+                        pafLastPass + iThisOffset * nXSize,
                         sizeof(float) * nXSize );
 
-            // currently this skips the first and last line.  Eventually 
+            // currently this skips the first and last line.  Eventually
             // we will enable these too.  TODO
             if( iFLine < 1 || iFLine >= nYSize-1 )
             {
                 continue;
             }
 
-            GDALFilterLine( 
+            GDALFilterLine(
                 pafSLastPass + iLastOffset * nXSize,
-                pafLastPass  + iThisOffset * nXSize, 
-                pafThisPass  + iNextOffset * nXSize, 
+                pafLastPass  + iThisOffset * nXSize,
+                pafThisPass  + iNextOffset * nXSize,
                 pafThisPass  + iThisOffset * nXSize,
                 pabyTMaskBuf + iLastOffset * nXSize,
                 pabyTMaskBuf + iThisOffset * nXSize,
                 pabyTMaskBuf + iNextOffset * nXSize,
-                pabyFMaskBuf + iThisOffset * nXSize, 
+                pabyFMaskBuf + iThisOffset * nXSize,
                 nXSize );
         }
 
@@ -295,10 +294,10 @@ GDALMultiFilter( GDALRasterBandH hTargetBand,
         {
             iBufOffset = iLineToSave % nBufLines;
 
-            eErr = 
-                GDALRasterIO( hTargetBand, GF_Write, 
-                              0, iLineToSave, nXSize, 1, 
-                              pafThisPass + nXSize * iBufOffset, nXSize, 1, 
+            eErr =
+                GDALRasterIO( hTargetBand, GF_Write,
+                              0, iLineToSave, nXSize, 1,
+                              pafThisPass + nXSize * iBufOffset, nXSize, 1,
                               GDT_Float32, 0, 0 );
         }
 
@@ -306,7 +305,7 @@ GDALMultiFilter( GDALRasterBandH hTargetBand,
 /*      Report progress.                                                */
 /* -------------------------------------------------------------------- */
         if( eErr == CE_None
-            && !pfnProgress( (nNewLine+1) / (double) (nYSize+nIterations), 
+            && !pfnProgress( (nNewLine+1) / (double) (nYSize+nIterations),
                              "Smoothing Filter...", pProgressArg ) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
@@ -324,7 +323,7 @@ end:
 
     return eErr;
 }
- 
+
 /************************************************************************/
 /*                             QUAD_CHECK()                             */
 /*                                                                      */
@@ -355,41 +354,41 @@ if( quad_value != nNoDataVal ) 						\
 /**
  * Fill selected raster regions by interpolation from the edges.
  *
- * This algorithm will interpolate values for all designated 
+ * This algorithm will interpolate values for all designated
  * nodata pixels (marked by zeros in hMaskBand).  For each pixel
  * a four direction conic search is done to find values to interpolate
  * from (using inverse distance weighting).  Once all values are
  * interpolated, zero or more smoothing iterations (3x3 average
- * filters on interpolated pixels) are applied to smooth out 
- * artifacts. 
+ * filters on interpolated pixels) are applied to smooth out
+ * artifacts.
  *
  * This algorithm is generally suitable for interpolating missing
  * regions of fairly continuously varying rasters (such as elevation
  * models for instance).  It is also suitable for filling small holes
  * and cracks in more irregularly varying images (like airphotos).  It
- * is generally not so great for interpolating a raster from sparse 
+ * is generally not so great for interpolating a raster from sparse
  * point data - see the algorithms defined in gdal_grid.h for that case.
  *
- * @param hTargetBand the raster band to be modified in place. 
+ * @param hTargetBand the raster band to be modified in place.
  * @param hMaskBand a mask band indicating pixels to be interpolated (zero valued
- * @param dfMaxSearchDist the maximum number of pixels to search in all 
+ * @param dfMaxSearchDist the maximum number of pixels to search in all
  * directions to find values to interpolate from.
  * @param bDeprecatedOption unused argument, should be zero.
- * @param nSmoothingIterations the number of 3x3 smoothing filter passes to 
+ * @param nSmoothingIterations the number of 3x3 smoothing filter passes to
  * run (0 or more).
  * @param papszOptions additional name=value options in a string list (the
  * temporary file driver can be specified like TEMP_FILE_DRIVER=MEM).
  * @param pfnProgress the progress function to report completion.
  * @param pProgressArg callback data for progress function.
- * 
- * @return CE_None on success or CE_Failure if something goes wrong. 
+ *
+ * @return CE_None on success or CE_Failure if something goes wrong.
  */
 
 CPLErr CPL_STDCALL
 GDALFillNodata( GDALRasterBandH hTargetBand,
                 GDALRasterBandH hMaskBand,
                 double dfMaxSearchDist,
-                int bDeprecatedOption,
+                CPL_UNUSED int bDeprecatedOption,
                 int nSmoothingIterations,
                 char **papszOptions,
                 GDALProgressFunc pfnProgress,
@@ -499,7 +498,7 @@ GDALFillNodata( GDALRasterBandH hTargetBand,
     CPLString osValTmpFile = osTmpFile + "fill_val_work.tif";
 
     hValDS = GDALCreate( hDriver, osValTmpFile, nXSize, nYSize, 1,
-                         GDALGetRasterDataType( hTargetBand ), 
+                         GDALGetRasterDataType( hTargetBand ),
                          (char **) papszWorkFileOptions );
 
     if ( hValDS == NULL )
@@ -519,7 +518,7 @@ GDALFillNodata( GDALRasterBandH hTargetBand,
     GDALRasterBandH hFiltMaskBand;
     CPLString osFiltMaskTmpFile = osTmpFile + "fill_filtmask_work.tif";
 
-    hFiltMaskDS = 
+    hFiltMaskDS =
         GDALCreate( hDriver, osFiltMaskTmpFile, nXSize, nYSize, 1,
                     GDT_Byte, (char **) papszWorkFileOptions );
 
@@ -541,22 +540,19 @@ GDALFillNodata( GDALRasterBandH hTargetBand,
     int     iX;
     int     iY;
 
-    panLastY = (GUInt32 *) VSICalloc(nXSize,sizeof(GUInt32));
-    panThisY = (GUInt32 *) VSICalloc(nXSize,sizeof(GUInt32));
-    panTopDownY = (GUInt32 *) VSICalloc(nXSize,sizeof(GUInt32));
-    pafLastValue = (float *) VSICalloc(nXSize,sizeof(float));
-    pafThisValue = (float *) VSICalloc(nXSize,sizeof(float));
-    pafTopDownValue = (float *) VSICalloc(nXSize,sizeof(float));
-    pafScanline = (float *) VSICalloc(nXSize,sizeof(float));
-    pabyMask = (GByte *) VSICalloc(nXSize,1);
-    pabyFiltMask = (GByte *) VSICalloc(nXSize,1);
+    panLastY = (GUInt32 *) VSI_CALLOC_VERBOSE(nXSize,sizeof(GUInt32));
+    panThisY = (GUInt32 *) VSI_CALLOC_VERBOSE(nXSize,sizeof(GUInt32));
+    panTopDownY = (GUInt32 *) VSI_CALLOC_VERBOSE(nXSize,sizeof(GUInt32));
+    pafLastValue = (float *) VSI_CALLOC_VERBOSE(nXSize,sizeof(float));
+    pafThisValue = (float *) VSI_CALLOC_VERBOSE(nXSize,sizeof(float));
+    pafTopDownValue = (float *) VSI_CALLOC_VERBOSE(nXSize,sizeof(float));
+    pafScanline = (float *) VSI_CALLOC_VERBOSE(nXSize,sizeof(float));
+    pabyMask = (GByte *) VSI_CALLOC_VERBOSE(nXSize,1);
+    pabyFiltMask = (GByte *) VSI_CALLOC_VERBOSE(nXSize,1);
     if (panLastY == NULL || panThisY == NULL || panTopDownY == NULL ||
         pafLastValue == NULL || pafThisValue == NULL || pafTopDownValue == NULL ||
         pafScanline == NULL || pabyMask == NULL || pabyFiltMask == NULL)
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory,
-                 "Could not allocate enough memory for temporary buffers");
-
         eErr = CE_Failure;
         goto end;
     }
@@ -571,30 +567,30 @@ GDALFillNodata( GDALRasterBandH hTargetBand,
 /*      known value" for each column and writing it out to the work     */
 /*      files.                                                          */
 /* ==================================================================== */
-    
+
     for( iY = 0; iY < nYSize && eErr == CE_None; iY++ )
     {
 /* -------------------------------------------------------------------- */
 /*      Read data and mask for this line.                               */
 /* -------------------------------------------------------------------- */
-        eErr = 
-            GDALRasterIO( hMaskBand, GF_Read, 0, iY, nXSize, 1, 
+        eErr =
+            GDALRasterIO( hMaskBand, GF_Read, 0, iY, nXSize, 1,
                           pabyMask, nXSize, 1, GDT_Byte, 0, 0 );
 
         if( eErr != CE_None )
             break;
 
-        eErr = 
-            GDALRasterIO( hTargetBand, GF_Read, 0, iY, nXSize, 1, 
+        eErr =
+            GDALRasterIO( hTargetBand, GF_Read, 0, iY, nXSize, 1,
                           pafScanline, nXSize, 1, GDT_Float32, 0, 0 );
-        
+
         if( eErr != CE_None )
             break;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Figure out the most recent pixel for each column.               */
 /* -------------------------------------------------------------------- */
-        
+
         for( iX = 0; iX < nXSize; iX++ )
         {
             if( pabyMask[iX] )
@@ -612,16 +608,16 @@ GDALFillNodata( GDALRasterBandH hTargetBand,
                 panThisY[iX] = nNoDataVal;
             }
         }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Write out best index/value to working files.                    */
 /* -------------------------------------------------------------------- */
-        eErr = GDALRasterIO( hYBand, GF_Write, 0, iY, nXSize, 1, 
+        eErr = GDALRasterIO( hYBand, GF_Write, 0, iY, nXSize, 1,
                              panThisY, nXSize, 1, GDT_UInt32, 0, 0 );
         if( eErr != CE_None )
             break;
 
-        eErr = GDALRasterIO( hValBand, GF_Write, 0, iY, nXSize, 1, 
+        eErr = GDALRasterIO( hValBand, GF_Write, 0, iY, nXSize, 1,
                              pafThisValue, nXSize, 1, GDT_Float32, 0, 0 );
         if( eErr != CE_None )
             break;
@@ -643,7 +639,7 @@ GDALFillNodata( GDALRasterBandH hTargetBand,
 /*      report progress.                                                */
 /* -------------------------------------------------------------------- */
         if( eErr == CE_None
-            && !pfnProgress( dfProgressRatio * (0.5*(iY+1) / (double)nYSize), 
+            && !pfnProgress( dfProgressRatio * (0.5*(iY+1) / (double)nYSize),
                              "Filling...", pProgressArg ) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
@@ -658,24 +654,24 @@ GDALFillNodata( GDALRasterBandH hTargetBand,
 /* ==================================================================== */
     for( iY = nYSize-1; iY >= 0 && eErr == CE_None; iY-- )
     {
-        eErr = 
-            GDALRasterIO( hMaskBand, GF_Read, 0, iY, nXSize, 1, 
+        eErr =
+            GDALRasterIO( hMaskBand, GF_Read, 0, iY, nXSize, 1,
                           pabyMask, nXSize, 1, GDT_Byte, 0, 0 );
 
         if( eErr != CE_None )
             break;
 
-        eErr = 
-            GDALRasterIO( hTargetBand, GF_Read, 0, iY, nXSize, 1, 
+        eErr =
+            GDALRasterIO( hTargetBand, GF_Read, 0, iY, nXSize, 1,
                           pafScanline, nXSize, 1, GDT_Float32, 0, 0 );
-        
+
         if( eErr != CE_None )
             break;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Figure out the most recent pixel for each column.               */
 /* -------------------------------------------------------------------- */
-        
+
         for( iX = 0; iX < nXSize; iX++ )
         {
             if( pabyMask[iX] )
@@ -693,19 +689,19 @@ GDALFillNodata( GDALRasterBandH hTargetBand,
                 panThisY[iX] = nNoDataVal;
             }
         }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Load the last y and corresponding value from the top down pass. */
 /* -------------------------------------------------------------------- */
-        eErr = 
-            GDALRasterIO( hYBand, GF_Read, 0, iY, nXSize, 1, 
+        eErr =
+            GDALRasterIO( hYBand, GF_Read, 0, iY, nXSize, 1,
                           panTopDownY, nXSize, 1, GDT_UInt32, 0, 0 );
 
         if( eErr != CE_None )
             break;
 
-        eErr = 
-            GDALRasterIO( hValBand, GF_Read, 0, iY, nXSize, 1, 
+        eErr =
+            GDALRasterIO( hValBand, GF_Read, 0, iY, nXSize, 1,
                           pafTopDownValue, nXSize, 1, GDT_Float32, 0, 0 );
 
         if( eErr != CE_None )
@@ -733,35 +729,35 @@ GDALFillNodata( GDALRasterBandH hTargetBand,
                 adfQuadDist[iQuad] = dfMaxSearchDist + 1.0;
                 adfQuadValue[iQuad] = 0.0;
             }
-            
-            // Step left and right by one pixel searching for the closest 
-            // target value for each quadrant. 
+
+            // Step left and right by one pixel searching for the closest
+            // target value for each quadrant.
             for( iStep = 0; iStep < nThisMaxSearchDist; iStep++ )
             {
                 int iLeftX = MAX(0,iX - iStep);
                 int iRightX = MIN(nXSize-1,iX + iStep);
-                
-                // top left includes current line 
-                QUAD_CHECK(adfQuadDist[0],adfQuadValue[0], 
+
+                // top left includes current line
+                QUAD_CHECK(adfQuadDist[0],adfQuadValue[0],
                            iLeftX, panTopDownY[iLeftX], iX, iY,
                            pafTopDownValue[iLeftX] );
 
-                // bottom left 
-                QUAD_CHECK(adfQuadDist[1],adfQuadValue[1], 
-                           iLeftX, panLastY[iLeftX], iX, iY, 
+                // bottom left
+                QUAD_CHECK(adfQuadDist[1],adfQuadValue[1],
+                           iLeftX, panLastY[iLeftX], iX, iY,
                            pafLastValue[iLeftX] );
 
                 // top right and bottom right do no include center pixel.
                 if( iStep == 0 )
                      continue;
-                    
-                // top right includes current line 
-                QUAD_CHECK(adfQuadDist[2],adfQuadValue[2], 
+
+                // top right includes current line
+                QUAD_CHECK(adfQuadDist[2],adfQuadValue[2],
                            iRightX, panTopDownY[iRightX], iX, iY,
                            pafTopDownValue[iRightX] );
 
                 // bottom right
-                QUAD_CHECK(adfQuadDist[3],adfQuadValue[3], 
+                QUAD_CHECK(adfQuadDist[3],adfQuadValue[3],
                            iRightX, panLastY[iRightX], iX, iY,
                            pafLastValue[iRightX] );
 
@@ -774,7 +770,7 @@ GDALFillNodata( GDALRasterBandH hTargetBand,
 
             double dfWeightSum = 0.0;
             double dfValueSum = 0.0;
-            
+
             for( iQuad = 0; iQuad < 4; iQuad++ )
             {
                 if( adfQuadDist[iQuad] <= dfMaxSearchDist )
@@ -798,17 +794,17 @@ GDALFillNodata( GDALRasterBandH hTargetBand,
 /* -------------------------------------------------------------------- */
 /*      Write out the updated data and mask information.                */
 /* -------------------------------------------------------------------- */
-        eErr = 
-            GDALRasterIO( hTargetBand, GF_Write, 0, iY, nXSize, 1, 
+        eErr =
+            GDALRasterIO( hTargetBand, GF_Write, 0, iY, nXSize, 1,
                           pafScanline, nXSize, 1, GDT_Float32, 0, 0 );
-        
+
         if( eErr != CE_None )
             break;
 
-        eErr = 
-            GDALRasterIO( hFiltMaskBand, GF_Write, 0, iY, nXSize, 1, 
+        eErr =
+            GDALRasterIO( hFiltMaskBand, GF_Write, 0, iY, nXSize, 1,
                           pabyFiltMask, nXSize, 1, GDT_Byte, 0, 0 );
-        
+
         if( eErr != CE_None )
             break;
 
@@ -819,7 +815,7 @@ GDALFillNodata( GDALRasterBandH hTargetBand,
             float *pafTmp = pafThisValue;
             pafThisValue = pafLastValue;
             pafLastValue = pafTmp;
-            
+
             GUInt32 *panTmp = panThisY;
             panThisY = panLastY;
             panLastY = panTmp;
@@ -829,13 +825,13 @@ GDALFillNodata( GDALRasterBandH hTargetBand,
 /*      report progress.                                                */
 /* -------------------------------------------------------------------- */
         if( eErr == CE_None
-            && !pfnProgress( dfProgressRatio*(0.5+0.5*(nYSize-iY) / (double)nYSize), 
+            && !pfnProgress( dfProgressRatio*(0.5+0.5*(nYSize-iY) / (double)nYSize),
                              "Filling...", pProgressArg ) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
             eErr = CE_Failure;
         }
-    }        
+    }
 
 /* ==================================================================== */
 /*      Now we will do iterative average filters over the               */
@@ -851,7 +847,7 @@ GDALFillNodata( GDALRasterBandH hTargetBand,
         pScaledProgress =
             GDALCreateScaledProgress( dfProgressRatio, 1.0, pfnProgress, NULL );
 
-        eErr = GDALMultiFilter( hTargetBand, hMaskBand, hFiltMaskBand, 
+        eErr = GDALMultiFilter( hTargetBand, hMaskBand, hFiltMaskBand,
                                 nSmoothingIterations,
                                 GDALScaledProgress, pScaledProgress );
 
diff --git a/alg/thinplatespline.cpp b/alg/thinplatespline.cpp
index 5bbb5ab..eeedfe3 100644
--- a/alg/thinplatespline.cpp
+++ b/alg/thinplatespline.cpp
@@ -1,13 +1,13 @@
 /******************************************************************************
- * $Id: thinplatespline.cpp 27546 2014-07-22 22:40:02Z rouault $
+ * $Id: thinplatespline.cpp 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  GDAL Warp API
- * Purpose:  Implemenentation of 2D Thin Plate Spline transformer. 
+ * Purpose:  Implemenentation of 2D Thin Plate Spline transformer.
  * Author:   VIZRT Development Team.
  *
  * This code was provided by Gilad Ronnen (gro at visrt dot com) with
  * permission to reuse under the following license.
- * 
+ *
  ******************************************************************************
  * Copyright (c) 2004, VIZRT Inc.
  * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
@@ -38,9 +38,9 @@
 
 #include "thinplatespline.h"
 
-/////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
 //// vizGeorefSpline2D
-/////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
 
 #define A(r,c) _AA[ _nof_eqs * (r) + (c) ]
 #define Ainv(r,c) _Ainv[ _nof_eqs * (r) + (c) ]
@@ -52,23 +52,37 @@
 static int matrixInvert( int N, double input[], double output[] );
 #endif
 
-void VizGeorefSpline2D::grow_points()
+bool VizGeorefSpline2D::grow_points()
 
 {
     int new_max = _max_nof_points*2 + 2 + 3;
     int i;
 
-    x = (double *) VSIRealloc( x, sizeof(double) * new_max );
-    y = (double *) VSIRealloc( y, sizeof(double) * new_max );
-    u = (double *) VSIRealloc( u, sizeof(double) * new_max );
-    unused = (int *) VSIRealloc( unused, sizeof(int) * new_max );
-    index = (int *) VSIRealloc( index, sizeof(int) * new_max );
-    for( i = 0; i < VIZGEOREF_MAX_VARS; i++ )
+    double *new_x = (double *) VSI_REALLOC_VERBOSE( x, sizeof(double) * new_max );
+    if( !new_x ) return false;
+    x = new_x;
+    double *new_y = (double *) VSI_REALLOC_VERBOSE( y, sizeof(double) * new_max );
+    if( !new_y ) return false;
+    y = new_y;
+    double *new_u = (double *) VSI_REALLOC_VERBOSE( u, sizeof(double) * new_max );
+    if( !new_u ) return false;
+    u = new_u;
+    int *new_unused = (int *) VSI_REALLOC_VERBOSE( unused, sizeof(int) * new_max );
+    if( !new_unused ) return false;
+    unused = new_unused;
+    int *new_index = (int *) VSI_REALLOC_VERBOSE( index, sizeof(int) * new_max );
+    if( !new_index ) return false;
+    index = new_index;
+    for( i = 0; i < _nof_vars; i++ )
     {
-        rhs[i] = (double *) 
-            VSIRealloc( rhs[i], sizeof(double) * new_max );
-        coef[i] = (double *) 
-            VSIRealloc( coef[i], sizeof(double) * new_max );
+        double* rhs_i_new = (double *)
+            VSI_REALLOC_VERBOSE( rhs[i], sizeof(double) * new_max );
+        if( !rhs_i_new ) return false;
+        rhs[i] = rhs_i_new;
+        double* coef_i_new = (double *)
+            VSI_REALLOC_VERBOSE( coef[i], sizeof(double) * new_max );
+        if( !coef_i_new ) return false;
+        coef[i] = coef_i_new;
         if( _max_nof_points == 0 )
         {
             memset(rhs[i], 0, 3 * sizeof(double));
@@ -77,15 +91,19 @@ void VizGeorefSpline2D::grow_points()
     }
 
     _max_nof_points = new_max - 3;
+    return true;
 }
 
-int VizGeorefSpline2D::add_point( const double Px, const double Py, const double *Pvars )
+bool VizGeorefSpline2D::add_point( const double Px, const double Py, const double *Pvars )
 {
     type = VIZ_GEOREF_SPLINE_POINT_WAS_ADDED;
     int i;
 
     if( _nof_points == _max_nof_points )
-        grow_points();
+    {
+        if( !grow_points() )
+            return false;
+    }
 
     i = _nof_points;
     //A new point is added
@@ -94,7 +112,7 @@ int VizGeorefSpline2D::add_point( const double Px, const double Py, const double
     for ( int j = 0; j < _nof_vars; j++ )
         rhs[j][i+3] = Pvars[j];
     _nof_points++;
-    return 1;
+    return true;
 }
 
 #if 0
@@ -163,6 +181,23 @@ static CPL_INLINE double VizGeorefSpline2DBase_func( const double x1, const doub
 }
 
 #if defined(__GNUC__) && defined(__x86_64__)
+/* Some versions of ICC fail to compile VizGeorefSpline2DBase_func4 (#6350) */
+#if defined(__INTEL_COMPILER)
+#if __INTEL_COMPILER >=1500
+#define USE_OPTIMIZED_VizGeorefSpline2DBase_func4
+#else
+#if (__INTEL_COMPILER == 1200) || (__INTEL_COMPILER == 1210)
+#define USE_OPTIMIZED_VizGeorefSpline2DBase_func4
+#else
+#undef USE_OPTIMIZED_VizGeorefSpline2DBase_func4
+#endif
+#endif
+#else // defined(__INTEL_COMPILER)
+#define USE_OPTIMIZED_VizGeorefSpline2DBase_func4
+#endif // defined(__INTEL_COMPILER)
+#endif
+
+#if defined(USE_OPTIMIZED_VizGeorefSpline2DBase_func4)
 
 /* Derived and adapted from code originating from: */
 
@@ -179,9 +214,9 @@ static CPL_INLINE double VizGeorefSpline2DBase_func( const double x1, const doub
  */
 
 /* __ieee754_log(x)
- * Return the logrithm of x
+ * Return the logarithm of x
  *
- * Method :                  
+ * Method:
  *   1. Argument Reduction: find k and f such that
  *                      x = 2^k * (1+f),
  *         where  sqrt(2)/2 < 1+f < sqrt(2) .
@@ -206,8 +241,8 @@ static CPL_INLINE double VizGeorefSpline2DBase_func( const double x1, const doub
  *      by
  *              log(1+f) = f - s*(f - R)        (if f is not too large)
  *              log(1+f) = f - (hfsq - s*(hfsq+R)).     (better accuracy)
- *      
- *      3. Finally,  log(x) = k*ln2 + log(1+f).  
+ *
+ *      3. Finally,  log(x) = k*ln2 + log(1+f).
  *                          = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
  *         Here ln2 is split into two floating point number:
  *                      ln2_hi + ln2_lo,
@@ -245,7 +280,7 @@ typedef union
 static const V2DF
 v2_ln2_div_2pow20 = {6.93147180559945286e-01 / 1048576, 6.93147180559945286e-01 / 1048576},
 v2_Lg1 = {6.666666666666735130e-01, 6.666666666666735130e-01},
-v2_Lg2 = {3.999999999940941908e-01, 3.999999999940941908e-01}, 
+v2_Lg2 = {3.999999999940941908e-01, 3.999999999940941908e-01},
 v2_Lg3 = {2.857142874366239149e-01, 2.857142874366239149e-01},
 v2_Lg4 = {2.222219843214978396e-01, 2.222219843214978396e-01},
 v2_Lg5 = {1.818357216161805012e-01, 1.818357216161805012e-01},
@@ -264,7 +299,7 @@ static const long long cst_0x100000 = MAKE_WIDE_CST(0x00100000);
 static const long long cst_0x3ff00000 = MAKE_WIDE_CST(0x3ff00000);
 
 /* Modified version of __ieee754_log(), less precise than log() but a bit */
-/* faste, and computing 4 log() at a time. Assumes that the values are > 0 */
+/* faster, and computing 4 log() at a time. Assumes that the values are > 0 */
 static void FastApproxLog4Val(v2dfunion* x)
 {
     V2DF f[2],s[2],z[2],R[2],w[2],t1[2],t2[2];
@@ -273,6 +308,7 @@ static void FastApproxLog4Val(v2dfunion* x)
 
     GET_HIGH_WORD(hx[0].i[0],x[0].d[0]);
     GET_HIGH_WORD(hx[0].i[1],x[0].d[1]);
+    /* coverity[uninit_use] */
     k[0].li = hx[0].li & cst_expmask;
     hx[0].li &= ~cst_expmask;
     i[0].li = (hx[0].li + cst_0x95f64) & cst_0x100000;
@@ -299,7 +335,9 @@ static void FastApproxLog4Val(v2dfunion* x)
     s[0] = f[0]/(x[0].v2+v2_one);
     z[0] = s[0]*s[0];
     w[0] = z[0]*z[0];
+    /* coverity[ptr_arith] */
     t1[0]= w[0]*(v2_Lg2+w[0]*(v2_Lg4+w[0]*v2_Lg6));
+    /* coverity[ptr_arith] */
     t2[0]= z[0]*(v2_Lg1+w[0]*(v2_Lg3+w[0]*(v2_Lg5/*+w[0]*v2_Lg7*/)));
     R[0] = t2[0]+t1[0];
     x[0].v2 = ((dk[0].v2 - v2_const1023_mul_2pow20)*v2_ln2_div_2pow20-(s[0]*(f[0]-R[0])-f[0]));
@@ -308,7 +346,9 @@ static void FastApproxLog4Val(v2dfunion* x)
     s[1] = f[1]/(x[1].v2+v2_one);
     z[1] = s[1]*s[1];
     w[1] = z[1]*z[1];
+    /* coverity[ptr_arith] */
     t1[1]= w[1]*(v2_Lg2+w[1]*(v2_Lg4+w[1]*v2_Lg6));
+    /* coverity[ptr_arith] */
     t2[1]= z[1]*(v2_Lg1+w[1]*(v2_Lg3+w[1]*(v2_Lg5/*+w[1]*v2_Lg7*/)));
     R[1] = t2[1]+t1[1];
     x[1].v2 = ((dk[1].v2- v2_const1023_mul_2pow20)*v2_ln2_div_2pow20-(s[1]*(f[1]-R[1])-f[1]));
@@ -343,7 +383,7 @@ static CPL_INLINE void VizGeorefSpline2DBase_func4( double* res,
     res[2] = resv[1].d[0];
     res[3] = resv[1].d[1];
 }
-#else
+#else // defined(USE_OPTIMIZED_VizGeorefSpline2DBase_func4)
 static void VizGeorefSpline2DBase_func4( double* res,
                                          const double* pxy,
                                          const double* xr, const double* yr )
@@ -357,20 +397,20 @@ static void VizGeorefSpline2DBase_func4( double* res,
     double dist3  = SQ( xr[3] - pxy[0] ) + SQ( yr[3] - pxy[1] );
     res[3] = dist3 ? dist3 * log(dist3) : 0.0;
 }
-#endif
+#endif // defined(USE_OPTIMIZED_VizGeorefSpline2DBase_func4)
 
 int VizGeorefSpline2D::solve(void)
 {
     int r, c;
     int p;
-	
+
     //	No points at all
     if ( _nof_points < 1 )
     {
         type = VIZ_GEOREF_SPLINE_ZERO_POINTS;
         return(0);
     }
-	
+
     // Only one point
     if ( _nof_points == 1 )
     {
@@ -381,33 +421,33 @@ int VizGeorefSpline2D::solve(void)
     if ( _nof_points == 2 )
     {
         _dx = x[1] - x[0];
-        _dy = y[1] - y[0];	 
+        _dy = y[1] - y[0];
         double fact = 1.0 / ( _dx * _dx + _dy * _dy );
         _dx *= fact;
         _dy *= fact;
-		
+
         type = VIZ_GEOREF_SPLINE_TWO_POINTS;
         return(2);
     }
-	
+
     // More than 2 points - first we have to check if it is 1D or 2D case
-		
+
     double xmax = x[0], xmin = x[0], ymax = y[0], ymin = y[0];
     double delx, dely;
     double xx, yy;
     double sumx = 0.0f, sumy= 0.0f, sumx2 = 0.0f, sumy2 = 0.0f, sumxy = 0.0f;
     double SSxx, SSyy, SSxy;
-	
+
     for ( p = 0; p < _nof_points; p++ )
     {
         xx = x[p];
         yy = y[p];
-		
+
         xmax = MAX( xmax, xx );
         xmin = MIN( xmin, xx );
         ymax = MAX( ymax, yy );
         ymin = MIN( ymin, yy );
-		
+
         sumx  += xx;
         sumx2 += xx * xx;
         sumy  += yy;
@@ -416,24 +456,24 @@ int VizGeorefSpline2D::solve(void)
     }
     delx = xmax - xmin;
     dely = ymax - ymin;
-	
+
     SSxx = sumx2 - sumx * sumx / _nof_points;
     SSyy = sumy2 - sumy * sumy / _nof_points;
     SSxy = sumxy - sumx * sumy / _nof_points;
-	
-    if ( delx < 0.001 * dely || dely < 0.001 * delx || 
+
+    if ( delx < 0.001 * dely || dely < 0.001 * delx ||
          fabs ( SSxy * SSxy / ( SSxx * SSyy ) ) > 0.99 )
     {
         int p1;
-		
+
         type = VIZ_GEOREF_SPLINE_ONE_DIMENSIONAL;
-		
+
         _dx = _nof_points * sumx2 - sumx * sumx;
         _dy = _nof_points * sumy2 - sumy * sumy;
         double fact = 1.0 / sqrt( _dx * _dx + _dy * _dy );
         _dx *= fact;
         _dy *= fact;
-		
+
         for ( p = 0; p < _nof_points; p++ )
         {
             double dxp = x[p] - x[0];
@@ -441,7 +481,7 @@ int VizGeorefSpline2D::solve(void)
             u[p] = _dx * dxp + _dy * dyp;
             unused[p] = 1;
         }
-		
+
         for ( p = 0; p < _nof_points; p++ )
         {
             int min_index = -1;
@@ -460,48 +500,47 @@ int VizGeorefSpline2D::solve(void)
             index[p] = min_index;
             unused[min_index] = 0;
         }
-		
+
         return(3);
     }
-	
+
     type = VIZ_GEOREF_SPLINE_FULL;
     // Make the necessary memory allocations
 
     _nof_eqs = _nof_points + 3;
-    
+
     if( _nof_eqs > INT_MAX / _nof_eqs )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Too many coefficients. Computation aborted.");
         return 0;
     }
-	
-    double* _AA = ( double * )VSICalloc( _nof_eqs * _nof_eqs, sizeof( double ) );
-    double* _Ainv = ( double * )VSICalloc( _nof_eqs * _nof_eqs, sizeof( double ) );
-    
+
+    double* _AA = ( double * )VSI_CALLOC_VERBOSE( _nof_eqs * _nof_eqs, sizeof( double ) );
+    double* _Ainv = ( double * )VSI_CALLOC_VERBOSE( _nof_eqs * _nof_eqs, sizeof( double ) );
+
     if( _AA == NULL || _Ainv == NULL )
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "Out-of-memory while allocating temporary arrays. Computation aborted.");
         VSIFree(_AA);
         VSIFree(_Ainv);
         return 0;
     }
-	
+
     // Calc the values of the matrix A
     for ( r = 0; r < 3; r++ )
         for ( c = 0; c < 3; c++ )
             A(r,c) = 0.0;
-		
+
     for ( c = 0; c < _nof_points; c++ )
     {
         A(0,c+3) = 1.0;
         A(1,c+3) = x[c];
         A(2,c+3) = y[c];
-			
+
         A(c+3,0) = 1.0;
         A(c+3,1) = x[c];
         A(c+3,2) = y[c];
     }
-		
+
     for ( r = 0; r < _nof_points; r++ )
         for ( c = r; c < _nof_points; c++ )
         {
@@ -509,16 +548,16 @@ int VizGeorefSpline2D::solve(void)
             if ( r != c )
                 A(c+3,r+3 ) = A(r+3,c+3);
         }
-			
+
 #if VIZ_GEOREF_SPLINE_DEBUG
-			
+
     for ( r = 0; r < _nof_eqs; r++ )
     {
         for ( c = 0; c < _nof_eqs; c++ )
             fprintf(stderr, "%f", A(r,c));
         fprintf(stderr, "\n");
     }
-			
+
 #endif
 
     int ret  = 4;
@@ -532,9 +571,16 @@ int VizGeorefSpline2D::solve(void)
             for(col = 0; col < _nof_vars; col++)
                 matRHS.at(row, col) = rhs[col][row];
         arma::mat matCoefs(_nof_vars, _nof_eqs);
+#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
+#endif
         if( !arma::solve(matCoefs, matA, matRHS) )
+#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
+#pragma GCC diagnostic pop
+#endif
         {
-            CPLError(CE_Failure, CPLE_AppDefined, "There is a problem to invert the interpolation matrix.");
+            CPLError(CE_Failure, CPLE_AppDefined, "There is a problem inverting the interpolation matrix.");
             ret = 0;
         }
         else
@@ -546,16 +592,15 @@ int VizGeorefSpline2D::solve(void)
     }
     catch(...)
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "There is a problem to invert the interpolation matrix.");
+        CPLError(CE_Failure, CPLE_AppDefined, "There is a problem inverting the interpolation matrix.");
         ret = 0;
     }
 #else
-    // Invert the matrix
     int status = matrixInvert( _nof_eqs, _AA, _Ainv );
-			
+
     if ( !status )
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "There is a problem to invert the interpolation matrix.");
+        CPLError(CE_Failure, CPLE_AppDefined, "There is a problem inverting the interpolation matrix.");
         ret = 0;
     }
     else
@@ -583,7 +628,7 @@ int VizGeorefSpline2D::get_point( const double Px, const double Py, double *vars
 	double tmp, Pu;
 	double fact;
 	int leftP=0, rightP=0, found = 0;
-	
+
 	switch ( type )
 	{
 	case VIZ_GEOREF_SPLINE_ZERO_POINTS :
@@ -616,12 +661,12 @@ int VizGeorefSpline2D::get_point( const double Px, const double Py, double *vars
 			for ( r = 1; !found && r < _nof_points; r++ )
 			{
 				leftP = index[r-1];
-				rightP = index[r];					
+				rightP = index[r];
 				if ( Pu >= u[leftP] && Pu <= u[rightP] )
 					found = 1;
 			}
 		}
-		
+
 		fact = ( Pu - u[leftP] ) / ( u[rightP] - u[leftP] );
 		for ( v = 0; v < _nof_vars; v++ )
 			vars[v] = ( 1.0 - fact ) * rhs[v][leftP+3] +
@@ -632,16 +677,16 @@ int VizGeorefSpline2D::get_point( const double Px, const double Py, double *vars
         double Pxy[2] = { Px, Py };
         for ( v = 0; v < _nof_vars; v++ )
             vars[v] = coef[v][0] + coef[v][1] * Px + coef[v][2] * Py;
-        
+
         for ( r = 0; r < (_nof_points & (~3)); r+=4 )
         {
-            double tmp[4];
-            VizGeorefSpline2DBase_func4( tmp, Pxy, &x[r], &y[r] );
+            double dfTmp[4];
+            VizGeorefSpline2DBase_func4( dfTmp, Pxy, &x[r], &y[r] );
             for ( v= 0; v < _nof_vars; v++ )
-                vars[v] += coef[v][r+3] * tmp[0] +
-                        coef[v][r+3+1] * tmp[1] +
-                        coef[v][r+3+2] * tmp[2] +
-                        coef[v][r+3+3] * tmp[3];
+                vars[v] += coef[v][r+3] * dfTmp[0] +
+                        coef[v][r+3+1] * dfTmp[1] +
+                        coef[v][r+3+2] * dfTmp[2] +
+                        coef[v][r+3+3] * dfTmp[3];
         }
         for ( ; r < _nof_points; r++ )
         {
@@ -680,15 +725,15 @@ static int matrixInvert( int N, double input[], double output[] )
     // input matrix, returned as output, also of size N-squared.  The Gauss-
     // Jordan Elimination method is used.  (Adapted from a BASIC routine in
     // "Basic Scientific Subroutines Vol. 1", courtesy of Scott Edwards.)
-	
+
     // Array elements 0...N-1 are for the first row, N...2N-1 are for the
     // second row, etc.
-	
+
     // We need to have a temporary array of size N x 2N.  We'll refer to the
     // "left" and "right" halves of this array.
-	
+
     int row, col;
-	
+
 #if 0
     fprintf(stderr, "Matrix Inversion input matrix (N=%d)\n", N);
     for ( row=0; row<N; row++ )
@@ -700,54 +745,54 @@ static int matrixInvert( int N, double input[], double output[] )
         fprintf(stderr, "\n");
     }
 #endif
-	
+
     int tempSize = 2 * N * N;
     double* temp = (double*) new double[ tempSize ];
     double ftemp;
-	
-    if (temp == 0) {
-		
+
+    if (temp == NULL) {
+
         CPLError(CE_Failure, CPLE_AppDefined, "matrixInvert(): ERROR - memory allocation failed.");
         return false;
     }
-	
+
     // First create a double-width matrix with the input array on the left
     // and the identity matrix on the right.
-	
+
     for ( row=0; row<N; row++ )
     {
         for ( col=0; col<N; col++ )
         {
             // Our index into the temp array is X2 because it's twice as wide
             // as the input matrix.
-			
+
             temp[ 2*row*N + col ] = input[ row*N+col ];	// left = input matrix
             temp[ 2*row*N + col + N ] = 0.0f;			// right = 0
         }
         temp[ 2*row*N + row + N ] = 1.0f;		// 1 on the diagonal of RHS
     }
-	
+
     // Now perform row-oriented operations to convert the left hand side
     // of temp to the identity matrix.  The inverse of input will then be
     // on the right.
-	
+
     int max;
     int k=0;
     for (k = 0; k < N; k++)
     {
         if (k+1 < N)	// if not on the last row
-        {              
+        {
             max = k;
             for (row = k+1; row < N; row++) // find the maximum element
-            {  
+            {
                 if (fabs( temp[row*2*N + k] ) > fabs( temp[max*2*N + k] ))
                 {
                     max = row;
                 }
             }
-			
+
             if (max != k)	// swap all the elements in the two rows
-            {        
+            {
                 for (col=k; col<2*N; col++)
                 {
                     ftemp = temp[k*2*N + col];
@@ -756,19 +801,19 @@ static int matrixInvert( int N, double input[], double output[] )
                 }
             }
         }
-		
+
         ftemp = temp[ k*2*N + k ];
         if ( ftemp == 0.0f ) // matrix cannot be inverted
         {
             delete[] temp;
             return false;
         }
-		
+
         for ( col=k; col<2*N; col++ )
         {
             temp[ k*2*N + col ] /= ftemp;
         }
-		
+
         int i2 = k*2*N ;
         for ( row=0; row<N; row++ )
         {
@@ -776,16 +821,16 @@ static int matrixInvert( int N, double input[], double output[] )
             {
                 int i1 = row*2*N;
                 ftemp = temp[ i1 + k ];
-                for ( col=k; col<2*N; col++ ) 
+                for ( col=k; col<2*N; col++ )
                 {
                     temp[ i1 + col ] -= ftemp * temp[ i2 + col ];
                 }
             }
         }
     }
-	
+
     // Retrieve inverse from the right side of temp
-	
+
     for (row = 0; row < N; row++)
     {
         for (col = 0; col < N; col++)
@@ -793,7 +838,7 @@ static int matrixInvert( int N, double input[], double output[] )
             output[row*N + col] = temp[row*2*N + col + N ];
         }
     }
-	
+
 #if 0
     fprintf(stderr, "Matrix Inversion result matrix:\n");
     for ( row=0; row<N; row++ )
@@ -805,7 +850,7 @@ static int matrixInvert( int N, double input[], double output[] )
         fprintf(stderr, "\n");
     }
 #endif
-	
+
     delete [] temp;       // free memory
     return true;
 }
diff --git a/alg/thinplatespline.h b/alg/thinplatespline.h
index 15da846..91ab052 100644
--- a/alg/thinplatespline.h
+++ b/alg/thinplatespline.h
@@ -1,13 +1,13 @@
 /******************************************************************************
- * $Id: thinplatespline.h 26650 2013-11-24 14:05:58Z rouault $
+ * $Id: thinplatespline.h 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  GDAL Warp API
- * Purpose:  Declarations for 2D Thin Plate Spline transformer. 
+ * Purpose:  Declarations for 2D Thin Plate Spline transformer.
  * Author:   VIZRT Development Team.
  *
- * This code was provided by Gilad Ronnen (gro at visrt dot com) with 
+ * This code was provided by Gilad Ronnen (gro at visrt dot com) with
  * permission to reuse under the following license.
- * 
+ *
  ******************************************************************************
  * Copyright (c) 2004, VIZRT Inc.
  *
@@ -40,7 +40,7 @@ typedef enum
 	VIZ_GEOREF_SPLINE_TWO_POINTS,
 	VIZ_GEOREF_SPLINE_ONE_DIMENSIONAL,
 	VIZ_GEOREF_SPLINE_FULL,
-	
+
 	VIZ_GEOREF_SPLINE_POINT_WAS_ADDED,
 	VIZ_GEOREF_SPLINE_POINT_WAS_DELETED
 
@@ -51,27 +51,39 @@ typedef enum
 
 class VizGeorefSpline2D
 {
+    bool grow_points();
+
   public:
 
-    VizGeorefSpline2D(int nof_vars = 1){
-        x = y = u = NULL;
-        unused = index = NULL;
-        for( int i = 0; i < nof_vars; i++ )
+    VizGeorefSpline2D(int nof_vars = 1) :
+        type(VIZ_GEOREF_SPLINE_ZERO_POINTS),
+        _nof_vars(nof_vars),
+        _nof_points(0),
+        _max_nof_points(0),
+        _nof_eqs(0),
+#if 0
+        _tx(0.0),
+        _ty(0.0),
+        _ta(10.0),
+#endif
+        _dx(0.0),
+        _dy(0.0),
+        x(NULL),
+        y(NULL),
+        u(NULL),
+        unused(NULL),
+        index(NULL)
+    {
+        for( int i = 0; i < VIZGEOREF_MAX_VARS; i++ )
         {
             rhs[i] = NULL;
             coef[i] = NULL;
         }
-          
-        _tx = _ty = 0.0;		
-        _ta = 10.0;
-        _nof_points = 0;
-        _nof_vars = nof_vars;
-        _max_nof_points = 0;
+
         grow_points();
-        type = VIZ_GEOREF_SPLINE_ZERO_POINTS;
     }
 
-    ~VizGeorefSpline2D(){
+    ~VizGeorefSpline2D() {
         CPLFree( x );
         CPLFree( y );
         CPLFree( u );
@@ -113,7 +125,7 @@ class VizGeorefSpline2D
                 fprintf(stderr, "\n");
             }
 	}
-	
+
     int delete_list()
 	{
             _nof_points = 0;
@@ -132,8 +144,7 @@ class VizGeorefSpline2D
 	}
 #endif
 
-    void grow_points();
-    int add_point( const double Px, const double Py, const double *Pvars );
+    bool add_point( const double Px, const double Py, const double *Pvars );
     int get_point( const double Px, const double Py, double *Pvars );
 #if 0
     int delete_point(const double Px, const double Py );
@@ -143,17 +154,21 @@ class VizGeorefSpline2D
 #endif
     int solve(void);
 
-  private:	
+  private:
 
     vizGeorefInterType type;
 
-    int _nof_vars;
+    const int _nof_vars;
     int _nof_points;
     int _max_nof_points;
     int _nof_eqs;
 
+#if 0
+    // Disabled because the methods that use there is disabled.
     double _tx, _ty;
     double _ta;
+#endif
+
     double _dx, _dy;
 
     double *x; // [VIZ_GEOREF_SPLINE_MAX_POINTS+3];
@@ -167,4 +182,7 @@ class VizGeorefSpline2D
     double *u; // [VIZ_GEOREF_SPLINE_MAX_POINTS];
     int *unused; // [VIZ_GEOREF_SPLINE_MAX_POINTS];
     int *index; // [VIZ_GEOREF_SPLINE_MAX_POINTS];
+
+  private:
+    CPL_DISALLOW_COPY_ASSIGN(VizGeorefSpline2D);
 };
diff --git a/apps/GNUmakefile b/apps/GNUmakefile
index 2f6b749..a87cd0f 100644
--- a/apps/GNUmakefile
+++ b/apps/GNUmakefile
@@ -13,7 +13,9 @@ BIN_LIST =	gdalinfo$(EXE) gdalserver$(EXE) gdal_translate$(EXE) \
 		gdalenhance$(EXE) gdaltransform$(EXE) gdaldem$(EXE) \
 		gdallocationinfo$(EXE) gdalsrsinfo$(EXE) 
 
-ifeq ($(OGR_ENABLED),yes)
+OBJ = commonutils.o gdalinfo_lib.o gdal_translate_lib.o gdalwarp_lib.o ogr2ogr_lib.o \
+	gdaldem_lib.o nearblack_lib.o gdal_grid_lib.o gdal_rasterize_lib.o gdalbuildvrt_lib.o
+
 BIN_LIST += 	gdal_contour$(EXE) \
 		gdaltindex$(EXE) \
 		gdal_rasterize$(EXE) \
@@ -24,6 +26,10 @@ BIN_LIST += 	gdal_contour$(EXE) \
 		ogrlineref$(EXE) \
 		testepsg$(EXE) \
 		gdalbuildvrt$(EXE)
+
+ifeq ($(GNM_ENABLED),yes)
+BIN_LIST += 	gnmmanage$(EXE) gnmanalyse$(EXE)
+CPPFLAGS +=	-I$(GDAL_ROOT)/gnm
 endif
 
 ifeq ($(HAVE_GEOS),yes)
@@ -43,37 +49,66 @@ lib-depend:
 	(cd ../gcore ; $(MAKE) )
 	(cd ../port ; $(MAKE) )
 
-gdalinfo$(EXE):	gdalinfo.$(OBJ_EXT) commonutils.$(OBJ_EXT) $(DEP_LIBS)
-	$(LD) $(LNK_FLAGS) $< commonutils.$(OBJ_EXT) $(XTRAOBJ) $(CONFIG_LIBS) -o $@
+appslib: $(OBJ:.o=.$(OBJ_EXT))
+
+gdalinfo_lib.$(OBJ_EXT): gdalinfo_lib.cpp
+	$(CXX) -c $(GDAL_INCLUDE) $(CPPFLAGS) $(CXXFLAGS) $< -o $@
+
+gdal_translate_lib.$(OBJ_EXT): gdal_translate_lib.cpp
+	$(CXX) -c $(GDAL_INCLUDE) $(CPPFLAGS) $(CXXFLAGS) $< -o $@
+
+gdalwarp_lib.$(OBJ_EXT): gdalwarp_lib.cpp
+	$(CXX) -c $(GDAL_INCLUDE) $(CPPFLAGS) $(CXXFLAGS) $< -o $@
+
+ogr2ogr_lib.$(OBJ_EXT): ogr2ogr_lib.cpp
+	$(CXX) -c $(GDAL_INCLUDE) $(CPPFLAGS) $(CXXFLAGS) $< -o $@
+
+gdaldem_lib.$(OBJ_EXT): gdaldem_lib.cpp
+	$(CXX) -c $(GDAL_INCLUDE) $(CPPFLAGS) $(CXXFLAGS) $< -o $@
+
+nearblack_lib.$(OBJ_EXT): nearblack_lib.cpp
+	$(CXX) -c $(GDAL_INCLUDE) $(CPPFLAGS) $(CXXFLAGS) $< -o $@
+
+gdal_grid_lib.$(OBJ_EXT): gdal_grid_lib.cpp
+	$(CXX) -c $(GDAL_INCLUDE) $(CPPFLAGS) $(CXXFLAGS) $< -o $@
+
+gdal_rasterize_lib.$(OBJ_EXT): gdal_rasterize_lib.cpp
+	$(CXX) -c $(GDAL_INCLUDE) $(CPPFLAGS) $(CXXFLAGS) $< -o $@
+
+gdalbuildvrt_lib.$(OBJ_EXT): gdalbuildvrt_lib.cpp
+	$(CXX) -c $(GDAL_INCLUDE) $(CPPFLAGS) $(CXXFLAGS) $< -o $@
+
+gdalinfo$(EXE):	gdalinfo_bin.$(OBJ_EXT) $(DEP_LIBS)
+	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) $(CONFIG_LIB_UTILS) -o $@
 
 gdalserver$(EXE):	gdalserver.$(OBJ_EXT) $(DEP_LIBS)
 	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
-gdal_translate$(EXE):	gdal_translate.$(OBJ_EXT) commonutils.$(OBJ_EXT) $(DEP_LIBS)
-	$(LD) $(LNK_FLAGS) $< commonutils.$(OBJ_EXT) $(XTRAOBJ) $(CONFIG_LIBS) -o $@
+gdal_translate$(EXE):	gdal_translate_bin.$(OBJ_EXT) $(DEP_LIBS)
+	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
 gdaladdo$(EXE):	gdaladdo.$(OBJ_EXT)  $(DEP_LIBS)
 	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
-gdalwarp$(EXE): gdalwarp.$(OBJ_EXT) commonutils.$(OBJ_EXT) $(DEP_LIBS)
-	$(LD) $(LNK_FLAGS) $< commonutils.$(OBJ_EXT) $(XTRAOBJ) $(CONFIG_LIBS) -o $@
+gdalwarp$(EXE): gdalwarp_bin.$(OBJ_EXT) $(DEP_LIBS)
+	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
 gdal_contour$(EXE):	gdal_contour.$(OBJ_EXT) $(DEP_LIBS)
 	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
-nearblack$(EXE):	nearblack.$(OBJ_EXT) commonutils.$(OBJ_EXT) $(DEP_LIBS)
-	$(LD) $(LNK_FLAGS) $< commonutils.$(OBJ_EXT) $(XTRAOBJ) $(CONFIG_LIBS) -o $@
+nearblack$(EXE):	nearblack_bin.$(OBJ_EXT) $(DEP_LIBS)
+	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
 gdalmanage$(EXE):	gdalmanage.$(OBJ_EXT) $(DEP_LIBS)
 	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
-gdal_rasterize$(EXE):	gdal_rasterize.$(OBJ_EXT) commonutils.$(OBJ_EXT) $(DEP_LIBS)
-	$(LD) $(LNK_FLAGS) $< commonutils.$(OBJ_EXT) $(XTRAOBJ) $(CONFIG_LIBS) -o $@
+gdal_rasterize$(EXE):	gdal_rasterize_bin.$(OBJ_EXT) $(DEP_LIBS)
+	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
 gdaltindex$(EXE):	gdaltindex.$(OBJ_EXT) $(DEP_LIBS)
 	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
-gdalbuildvrt$(EXE):	gdalbuildvrt.$(OBJ_EXT) $(DEP_LIBS)
+gdalbuildvrt$(EXE):	gdalbuildvrt_bin.$(OBJ_EXT) $(DEP_LIBS)
 	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
 multireadtest$(EXE):	multireadtest.$(OBJ_EXT) $(DEP_LIBS)
@@ -82,14 +117,14 @@ multireadtest$(EXE):	multireadtest.$(OBJ_EXT) $(DEP_LIBS)
 dumpoverviews$(EXE):	dumpoverviews.$(OBJ_EXT) $(DEP_LIBS)
 	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
-gdalenhance$(EXE):	gdalenhance.$(OBJ_EXT) commonutils.$(OBJ_EXT) $(DEP_LIBS)
-	$(LD) $(LNK_FLAGS) $< commonutils.$(OBJ_EXT) $(XTRAOBJ) $(CONFIG_LIBS) -o $@
+gdalenhance$(EXE):	gdalenhance.$(OBJ_EXT) $(DEP_LIBS)
+	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
-gdaldem$(EXE): gdaldem.$(OBJ_EXT) commonutils.$(OBJ_EXT) $(DEP_LIBS)
-	$(LD) $(LNK_FLAGS) $< commonutils.$(OBJ_EXT) $(XTRAOBJ) $(CONFIG_LIBS) -o $@
+gdaldem$(EXE): gdaldem_bin.$(OBJ_EXT) $(DEP_LIBS)
+	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
-gdal_grid$(EXE):	gdal_grid.$(OBJ_EXT) commonutils.$(OBJ_EXT) $(DEP_LIBS)
-	$(LD) $(LNK_FLAGS) $< commonutils.$(OBJ_EXT) $(XTRAOBJ) $(CONFIG_LIBS) -o $@
+gdal_grid$(EXE):	gdal_grid_bin.$(OBJ_EXT) $(DEP_LIBS)
+	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
 gdalwarpsimple$(EXE): gdalwarpsimple.$(OBJ_EXT) $(DEP_LIBS)
 	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
@@ -100,8 +135,8 @@ gdaltransform$(EXE): gdaltransform.$(OBJ_EXT) $(DEP_LIBS)
 gdallocationinfo$(EXE): gdallocationinfo.$(OBJ_EXT) $(DEP_LIBS)
 	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
-gdalsrsinfo$(EXE):	gdalsrsinfo.$(OBJ_EXT) commonutils.$(OBJ_EXT)  $(DEP_LIBS)
-	$(LD) $(LNK_FLAGS) $< commonutils.$(OBJ_EXT) $(XTRAOBJ) $(CONFIG_LIBS) -o $@
+gdalsrsinfo$(EXE):	gdalsrsinfo.$(OBJ_EXT)  $(DEP_LIBS)
+	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
 gdalflattenmask$(EXE): gdalflattenmask.$(OBJ_EXT) $(DEP_LIBS)
 	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
@@ -112,14 +147,14 @@ gdaltorture$(EXE): gdaltorture.$(OBJ_EXT) $(DEP_LIBS)
 gdal2ogr$(EXE):	gdal2ogr.$(OBJ_EXT) $(DEP_LIBS)
 	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
-ogrinfo$(EXE):	ogrinfo.$(OBJ_EXT) commonutils.$(OBJ_EXT)  $(DEP_LIBS)
-	$(LD) $(LNK_FLAGS) $< commonutils.$(OBJ_EXT)  $(XTRAOBJ) $(CONFIG_LIBS) -o $@
+ogrinfo$(EXE):	ogrinfo.$(OBJ_EXT)  $(DEP_LIBS)
+	$(LD) $(LNK_FLAGS) $<  $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
-ogrlineref$(EXE):	ogrlineref.$(OBJ_EXT) commonutils.$(OBJ_EXT)  $(DEP_LIBS)
-	$(LD) $(LNK_FLAGS) $< commonutils.$(OBJ_EXT)  $(XTRAOBJ) $(CONFIG_LIBS) -o $@
+ogrlineref$(EXE):	ogrlineref.$(OBJ_EXT)  $(DEP_LIBS)
+	$(LD) $(LNK_FLAGS) $<  $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
-ogr2ogr$(EXE):	ogr2ogr.$(OBJ_EXT) commonutils.$(OBJ_EXT)  $(DEP_LIBS)
-	$(LD) $(LNK_FLAGS) $< commonutils.$(OBJ_EXT) $(XTRAOBJ) $(CONFIG_LIBS) -o $@
+ogr2ogr$(EXE):	ogr2ogr_bin.$(OBJ_EXT)  $(DEP_LIBS)
+	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
 testepsg$(EXE):	testepsg.$(OBJ_EXT) $(DEP_LIBS)
 	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
@@ -127,8 +162,8 @@ testepsg$(EXE):	testepsg.$(OBJ_EXT) $(DEP_LIBS)
 ogrtindex$(EXE):	ogrtindex.$(OBJ_EXT) $(DEP_LIBS)
 	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
-test_ogrsf$(EXE):	test_ogrsf.$(OBJ_EXT) commonutils.$(OBJ_EXT)  $(DEP_LIBS)
-	$(LD) $(LNK_FLAGS) $< commonutils.$(OBJ_EXT) $(XTRAOBJ) $(CONFIG_LIBS) -o $@
+test_ogrsf$(EXE):	test_ogrsf.$(OBJ_EXT)  $(DEP_LIBS)
+	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
 gdalasyncread$(EXE):	gdalasyncread.$(OBJ_EXT) $(DEP_LIBS)
 	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
@@ -136,6 +171,12 @@ gdalasyncread$(EXE):	gdalasyncread.$(OBJ_EXT) $(DEP_LIBS)
 testreprojmulti$(EXE):	testreprojmulti.$(OBJ_EXT) $(DEP_LIBS)
 	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
+gnmmanage$(EXE):	gnmmanage.$(OBJ_EXT) $(DEP_LIBS)
+	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
+
+gnmanalyse$(EXE):	gnmanalyse.$(OBJ_EXT) $(DEP_LIBS)
+	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
+
 clean:
 	$(RM) *.o $(BIN_LIST) core gdal-config gdal-config-inst
 
@@ -148,10 +189,11 @@ gdal-config:	gdal-config.in ../GDALmake.opt ./GNUmakefile ../VERSION
 	echo 'CONFIG_LIBS="$(CONFIG_LIBS)"' >> gdal-config
 	echo 'CONFIG_DEP_LIBS="$(LIBS)"' >> gdal-config
 	echo 'CONFIG_PREFIX="$(GDAL_ROOT)"' >> gdal-config
-	echo 'CONFIG_CFLAGS="-I$(GDAL_ROOT)/port -I$(GDAL_ROOT)/gcore -I$(GDAL_ROOT)/alg -I$(GDAL_ROOT)/ogr -I$(GDAL_ROOT)/ogr/ogrsf_frmts -I$(GDAL_ROOT)/frmts/vrt"' >> gdal-config
+	echo 'CONFIG_CFLAGS="-I$(GDAL_ROOT)/port -I$(GDAL_ROOT)/gcore -I$(GDAL_ROOT)/alg -I$(GDAL_ROOT)/ogr -I$(GDAL_ROOT)/ogr/ogrsf_frmts -I$(GDAL_ROOT)/frmts/vrt -I$(GDAL_ROOT)/apps"' >> gdal-config
 	echo 'CONFIG_DATA="$(GDAL_ROOT)/data"' >> gdal-config
 	echo 'CONFIG_VERSION="'`cat ../VERSION`'"' >> gdal-config
-	echo 'CONFIG_OGR_ENABLED=$(OGR_ENABLED)' >> gdal-config
+	echo 'CONFIG_OGR_ENABLED=yes' >> gdal-config
+	echo 'CONFIG_GNM_ENABLED=$(GNM_ENABLED)' >> gdal-config
 	echo 'CONFIG_FORMATS="$(GDAL_FORMATS)"' >> gdal-config
 	cat gdal-config.in >> gdal-config
 	chmod a+x gdal-config
@@ -165,7 +207,8 @@ gdal-config-inst:	gdal-config.in ../GDALmake.opt ./GNUmakefile ../VERSION
 	echo 'CONFIG_CFLAGS="-I$(INST_INCLUDE)"' >> gdal-config-inst
 	echo 'CONFIG_DATA="$(INST_DATA)"' >> gdal-config-inst
 	echo 'CONFIG_VERSION="'`cat ../VERSION`'"' >> gdal-config-inst
-	echo 'CONFIG_OGR_ENABLED=$(OGR_ENABLED)' >> gdal-config-inst
+	echo 'CONFIG_OGR_ENABLED=yes' >> gdal-config-inst
+	echo 'CONFIG_GNM_ENABLED=$(GNM_ENABLED)' >> gdal-config-inst
 	echo 'CONFIG_FORMATS="$(GDAL_FORMATS)"' >> gdal-config-inst
 	cat gdal-config.in >> gdal-config-inst
 	chmod a+x gdal-config-inst
@@ -173,5 +216,6 @@ gdal-config-inst:	gdal-config.in ../GDALmake.opt ./GNUmakefile ../VERSION
 
 install: default
 	for f in $(BIN_LIST) ; do $(INSTALL) $$f $(DESTDIR)$(INST_BIN) ; done
+	$(INSTALL) gdal_utils.h $(DESTDIR)$(INST_INCLUDE)
 	$(INSTALL) gdal-config-inst $(DESTDIR)$(INST_BIN)/gdal-config
 
diff --git a/apps/commonutils.cpp b/apps/commonutils.cpp
index 2248546..2d7a2e2 100644
--- a/apps/commonutils.cpp
+++ b/apps/commonutils.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: commonutils.cpp 29330 2015-06-14 12:11:11Z rouault $
+ * $Id: commonutils.cpp 29329 2015-06-14 11:20:13Z rouault $
  *
  * Project:  GDAL Utilities
  * Purpose:  Common utility routines
@@ -31,7 +31,7 @@
 #include "cpl_string.h"
 #include "gdal.h"
 
-CPL_CVSID("$Id: commonutils.cpp 29330 2015-06-14 12:11:11Z rouault $");
+CPL_CVSID("$Id: commonutils.cpp 29329 2015-06-14 11:20:13Z rouault $");
 
 /* -------------------------------------------------------------------- */
 /*                      CheckExtensionConsistency()                     */
diff --git a/apps/commonutils.h b/apps/commonutils.h
index bf62d18..846a1da 100644
--- a/apps/commonutils.h
+++ b/apps/commonutils.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: commonutils.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: commonutils.h 31778 2015-11-26 14:15:36Z rouault $
  *
  * Project:  GDAL Utilities
  * Purpose:  Common utility routines
@@ -27,18 +27,18 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _COMMONUTILS_H_
-#define _COMMONUTILS_H_
+#ifndef COMMONUTILS_H_INCLUDED
+#define COMMONUTILS_H_INCLUDED
 
 #include "cpl_port.h"
 
 CPL_C_START
 
-void CheckExtensionConsistency(const char* pszDestFilename,
+void CPL_DLL CheckExtensionConsistency(const char* pszDestFilename,
                                const char* pszDriverName);
 
-void EarlySetConfigOptions( int argc, char ** argv );
+void CPL_DLL EarlySetConfigOptions( int argc, char ** argv );
 
 CPL_C_END
 
-#endif
+#endif /* COMMONUTILS_H_INCLUDED */
diff --git a/apps/dumpoverviews.cpp b/apps/dumpoverviews.cpp
index 0cd97dc..c6e77fb 100644
--- a/apps/dumpoverviews.cpp
+++ b/apps/dumpoverviews.cpp
@@ -1,5 +1,5 @@
 /* ****************************************************************************
- * $Id: dumpoverviews.cpp 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: dumpoverviews.cpp 33615 2016-03-02 20:19:22Z goatbar $
  *
  * Project:  GDAL Utilities
  * Purpose:  Dump overviews to external files.
@@ -33,7 +33,7 @@
 #include "gdal_priv.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: dumpoverviews.cpp 27044 2014-03-16 23:41:27Z rouault $");
+CPL_CVSID("$Id: dumpoverviews.cpp 33615 2016-03-02 20:19:22Z goatbar $");
 
 static void DumpBand( GDALDatasetH hBaseDS, GDALRasterBandH hBand,
                       const char *pszName );
@@ -41,7 +41,7 @@ static void DumpBand( GDALDatasetH hBaseDS, GDALRasterBandH hBand,
 /************************************************************************/
 /*                               Usage()                                */
 /************************************************************************/
-static void Usage() 
+static void Usage()
 
 {
     printf( "Usage: dumpoverviews [-masks] <filename> [overview]*\n" );
@@ -56,10 +56,9 @@ int main( int argc, char ** argv )
 
 {
     const char *pszSrcFilename = NULL;
-    int iArg;
     int anReqOverviews[1000];
     int nReqOverviewCount = 0;
-    int bMasks = FALSE;
+    bool bMasks = false;
 
     GDALAllRegister();
 
@@ -70,11 +69,11 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
 /*      Process arguments.                                              */
 /* -------------------------------------------------------------------- */
-    for( iArg = 1; iArg < argc; iArg++ )
+    for( int iArg = 1; iArg < argc; iArg++ )
     {
         if( EQUAL(argv[iArg],"-masks") )
         {
-            bMasks = TRUE;
+            bMasks = true;
         }
         else if( pszSrcFilename == NULL )
         {
@@ -110,17 +109,17 @@ int main( int argc, char ** argv )
     for( iBand = 0; iBand < nBandCount; iBand++ )
     {
         GDALRasterBandH hBaseBand = GDALGetRasterBand( hSrcDS, iBand+1 );
-        
+
 /* -------------------------------------------------------------------- */
 /*      Process all overviews.                                          */
 /* -------------------------------------------------------------------- */
         int iOverview;
         int nOverviewCount = GDALGetOverviewCount( hBaseBand );
-        
+
         for( iOverview = 0; iOverview < nOverviewCount; iOverview++ )
         {
             GDALRasterBandH hSrcOver = GDALGetOverview( hBaseBand, iOverview );
-            
+
             if (hSrcOver == NULL)
             {
                 fprintf(stderr, "skipping overview %d as being null\n", iOverview);
@@ -132,14 +131,14 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
             if( nReqOverviewCount > 0 )
             {
-                int i; 
+                int i;
 
                 for( i = 0; i < nReqOverviewCount; i++ )
                 {
                     if( anReqOverviews[i] == iOverview )
                         break;
                 }
-                
+
                 if( i == nReqOverviewCount )
                     continue;
             }
@@ -180,7 +179,7 @@ int main( int argc, char ** argv )
 
     CSLDestroy( argv );
     GDALDestroyDriverManager();
-    
+
     return 0;
 }
 
@@ -192,28 +191,25 @@ static void DumpBand( GDALDatasetH hBaseDS, GDALRasterBandH hSrcOver,
                       const char *pszName )
 
 {
-    int nOrigXSize, nOrigYSize;
-    double adfGeoTransform[6];
-    int    bHaveGT;
-
 /* -------------------------------------------------------------------- */
 /*      Get base ds info.                                               */
 /* -------------------------------------------------------------------- */
-    bHaveGT = GDALGetGeoTransform( hBaseDS, adfGeoTransform ) == CE_None;
-    nOrigXSize = GDALGetRasterXSize( hBaseDS );
-    nOrigYSize = GDALGetRasterYSize( hBaseDS );
+    double adfGeoTransform[6];
+    bool bHaveGT = GDALGetGeoTransform( hBaseDS, adfGeoTransform ) == CE_None;
+
+    int nOrigXSize = GDALGetRasterXSize( hBaseDS );
+    int nOrigYSize = GDALGetRasterYSize( hBaseDS );
 
 /* -------------------------------------------------------------------- */
 /*      Create matching output file.                                    */
 /* -------------------------------------------------------------------- */
-    GDALDatasetH hDstDS;
     int nXSize = GDALGetRasterBandXSize( hSrcOver );
     int nYSize = GDALGetRasterBandYSize( hSrcOver );
     GDALDataType eDT = GDALGetRasterDataType( hSrcOver );
     GDALDriverH hDriver = GDALGetDriverByName( "GTiff" );
 
-    hDstDS = GDALCreate( hDriver, pszName, nXSize, nYSize,
-                         1, eDT, NULL );
+    GDALDatasetH hDstDS = GDALCreate( hDriver, pszName, nXSize, nYSize,
+                                      1, eDT, NULL );
 
     if( hDstDS == NULL )
         exit( 1 );
@@ -224,17 +220,17 @@ static void DumpBand( GDALDatasetH hBaseDS, GDALRasterBandH hSrcOver,
     if( bHaveGT )
     {
         double adfOvGeoTransform[6];
-        
-        memcpy( adfOvGeoTransform, adfGeoTransform, 
+
+        memcpy( adfOvGeoTransform, adfGeoTransform,
                 sizeof(double) * 6 );
-        
+
         adfOvGeoTransform[1] *= (nOrigXSize / (double) nXSize);
         adfOvGeoTransform[2] *= (nOrigXSize / (double) nXSize);
         adfOvGeoTransform[4] *= (nOrigYSize / (double) nYSize);
         adfOvGeoTransform[5] *= (nOrigYSize / (double) nYSize);
-            
+
         GDALSetGeoTransform( hDstDS, adfOvGeoTransform );
-            
+
         GDALSetProjection( hDstDS, GDALGetProjectionRef( hBaseDS ) );
     }
 
@@ -242,14 +238,13 @@ static void DumpBand( GDALDatasetH hBaseDS, GDALRasterBandH hSrcOver,
 /*      Copy over all the image data.                                   */
 /* -------------------------------------------------------------------- */
     void *pData = CPLMalloc(64 * nXSize);
-    int iLine;
 
-    for( iLine = 0; iLine < nYSize; iLine++ )
+    for( int iLine = 0; iLine < nYSize; iLine++ )
     {
-        GDALRasterIO( hSrcOver, GF_Read, 0, iLine, nXSize, 1, 
+        GDALRasterIO( hSrcOver, GF_Read, 0, iLine, nXSize, 1,
                       pData, nXSize, 1, eDT, 0, 0 );
-        GDALRasterIO( GDALGetRasterBand( hDstDS, 1 ), GF_Write, 
-                      0, iLine, nXSize, 1, 
+        GDALRasterIO( GDALGetRasterBand( hDstDS, 1 ), GF_Write,
+                      0, iLine, nXSize, 1,
                       pData, nXSize, 1, eDT, 0, 0 );
     }
     CPLFree( pData );
diff --git a/apps/gdal-config.in b/apps/gdal-config.in
index 4403622..024dcd1 100644
--- a/apps/gdal-config.in
+++ b/apps/gdal-config.in
@@ -10,6 +10,7 @@ Options:
 	[--datadir]
 	[--version]
 	[--ogr-enabled]
+	[--gnm-enabled]
 	[--formats]
 EOF
 	exit $1
@@ -19,7 +20,7 @@ if test $# -eq 0; then
 	usage 1 1>&2
 fi
 
-case $1 in 
+case $1 in
   --libs)
     echo $CONFIG_LIBS
     ;;
@@ -45,7 +46,11 @@ case $1 in
     ;;
 
   --ogr-enabled)
-    echo $CONFIG_OGR_ENABLED
+    echo yes
+    ;;
+
+  --gnm-enabled)
+    echo $CONFIG_GNM_ENABLED
     ;;
 
   --formats)
diff --git a/apps/gdal_contour.cpp b/apps/gdal_contour.cpp
index cb47694..65e3532 100644
--- a/apps/gdal_contour.cpp
+++ b/apps/gdal_contour.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: gdal_contour.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: gdal_contour.cpp 33615 2016-03-02 20:19:22Z goatbar $
  *
  * Project:  Contour Generator
  * Purpose:  Contour Generator mainline.
  * Author:   Frank Warmerdam <warmerdam at pobox.com>
  *
  ******************************************************************************
- * Copyright (c) 2003, Applied Coherent Technology (www.actgate.com). 
+ * Copyright (c) 2003, Applied Coherent Technology (www.actgate.com).
  * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -35,7 +35,7 @@
 #include "ogr_api.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: gdal_contour.cpp 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: gdal_contour.cpp 33615 2016-03-02 20:19:22Z goatbar $");
 
 /************************************************************************/
 /*                            ArgIsNumeric()                            */
@@ -54,11 +54,11 @@ static int ArgIsNumeric( const char *pszArg )
 static void Usage(const char* pszErrorMsg = NULL)
 
 {
-    printf( 
+    printf(
         "Usage: gdal_contour [-b <band>] [-a <attribute_name>] [-3d] [-inodata]\n"
         "                    [-snodata n] [-f <formatname>] [-i <interval>]\n"
-        "                    [-f <formatname>] [[-dsco NAME=VALUE] ...] [[-lco NAME=VALUE] ...]\n"   
-        "                    [-off <offset>] [-fl <level> <level>...]\n" 
+        "                    [-f <formatname>] [[-dsco NAME=VALUE] ...] [[-lco NAME=VALUE] ...]\n"
+        "                    [-off <offset>] [-fl <level> <level>...]\n"
         "                    [-nln <outlayername>] [-q]\n"
         "                    <src_filename> <dst_filename>\n" );
 
@@ -117,6 +117,7 @@ int main( int argc, char ** argv )
         {
             printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
                    argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
+            CSLDestroy( argv );
             return 0;
         }
         else if( EQUAL(argv[i], "--help") )
@@ -140,8 +141,8 @@ int main( int argc, char ** argv )
         {
             if( i >= argc-1 )
                 Usage(CPLSPrintf("%s option requires at least 1 argument", argv[i]));
-            while( i < argc-1 
-                   && nFixedLevelCount 
+            while( i < argc-1
+                   && nFixedLevelCount
                              < (int)(sizeof(adfFixedLevels)/sizeof(double))
                    && ArgIsNumeric(argv[i+1]) )
                 adfFixedLevels[nFixedLevelCount++] = CPLAtof(argv[++i]);
@@ -215,7 +216,7 @@ int main( int argc, char ** argv )
     {
         Usage("Missing destination filename.");
     }
-    
+
     if (!bQuiet)
         pfnProgress = GDALTermProgress;
 
@@ -231,8 +232,8 @@ int main( int argc, char ** argv )
     hBand = GDALGetRasterBand( hSrcDS, nBandIn );
     if( hBand == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Band %d does not exist on dataset.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Band %d does not exist on dataset.",
                   nBandIn );
         exit(2);
     }
@@ -251,7 +252,7 @@ int main( int argc, char ** argv )
         hSRS = OSRNewSpatialReference( pszWKT );
 
 /* -------------------------------------------------------------------- */
-/*      Create the outputfile.                                          */
+/*      Create the output file.                                          */
 /* -------------------------------------------------------------------- */
     OGRDataSourceH hDS;
     OGRSFDriverH hDriver = OGRGetDriverByName( pszFormat );
@@ -260,7 +261,7 @@ int main( int argc, char ** argv )
 
     if( hDriver == NULL )
     {
-        fprintf( stderr, "Unable to find format driver named %s.\n", 
+        fprintf( stderr, "Unable to find format driver named %s.\n",
                  pszFormat );
         exit( 10 );
     }
@@ -269,7 +270,7 @@ int main( int argc, char ** argv )
     if( hDS == NULL )
         exit( 1 );
 
-    hLayer = OGR_DS_CreateLayer( hDS, pszNewLayerName, hSRS, 
+    hLayer = OGR_DS_CreateLayer( hDS, pszNewLayerName, hSRS,
                                  b3D ? wkbLineString25D : wkbLineString,
                                  papszLCO );
     if( hLayer == NULL )
diff --git a/apps/gdal_grid.cpp b/apps/gdal_grid.cpp
deleted file mode 100644
index d47e141..0000000
--- a/apps/gdal_grid.cpp
+++ /dev/null
@@ -1,1149 +0,0 @@
-/* ****************************************************************************
- * $Id: gdal_grid.cpp 29330 2015-06-14 12:11:11Z rouault $
- *
- * Project:  GDAL Utilities
- * Purpose:  GDAL scattered data gridding (interpolation) tool
- * Author:   Andrey Kiselev, dron at ak4719.spb.edu
- *
- * ****************************************************************************
- * Copyright (c) 2007, Andrey Kiselev <dron at ak4719.spb.edu>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include <cstdlib>
-#include <vector>
-#include <algorithm>
-
-#include "cpl_string.h"
-#include "gdal.h"
-#include "gdal_alg.h"
-#include "ogr_spatialref.h"
-#include "ogr_api.h"
-#include "ogrsf_frmts.h"
-#include "gdalgrid.h"
-#include "commonutils.h"
-
-CPL_CVSID("$Id: gdal_grid.cpp 29330 2015-06-14 12:11:11Z rouault $");
-
-/************************************************************************/
-/*                               Usage()                                */
-/************************************************************************/
-
-static void Usage(const char* pszErrorMsg = NULL)
-
-{
-    printf( 
-        "Usage: gdal_grid [--help-general] [--formats]\n"
-        "    [-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/\n"
-        "          CInt16/CInt32/CFloat32/CFloat64}]\n"
-        "    [-of format] [-co \"NAME=VALUE\"]\n"
-        "    [-zfield field_name] [-z_increase increase_value] [-z_multiply multiply_value]\n"
-        "    [-a_srs srs_def] [-spat xmin ymin xmax ymax]\n"
-        "    [-clipsrc <xmin ymin xmax ymax>|WKT|datasource|spat_extent]\n"
-        "    [-clipsrcsql sql_statement] [-clipsrclayer layer]\n"
-        "    [-clipsrcwhere expression]\n"
-        "    [-l layername]* [-where expression] [-sql select_statement]\n"
-        "    [-txe xmin xmax] [-tye ymin ymax] [-outsize xsize ysize]\n"
-        "    [-a algorithm[:parameter1=value1]*]"
-        "    [-q]\n"
-        "    <src_datasource> <dst_filename>\n"
-        "\n"
-        "Available algorithms and parameters with their's defaults:\n"
-        "    Inverse distance to a power (default)\n"
-        "        invdist:power=2.0:smoothing=0.0:radius1=0.0:radius2=0.0:angle=0.0:max_points=0:min_points=0:nodata=0.0\n"
-        "    Moving average\n"
-        "        average:radius1=0.0:radius2=0.0:angle=0.0:min_points=0:nodata=0.0\n"
-        "    Nearest neighbor\n"
-        "        nearest:radius1=0.0:radius2=0.0:angle=0.0:nodata=0.0\n"
-        "    Various data metrics\n"
-        "        <metric name>:radius1=0.0:radius2=0.0:angle=0.0:min_points=0:nodata=0.0\n"
-        "        possible metrics are:\n"
-        "            minimum\n"
-        "            maximum\n"
-        "            range\n"
-        "            count\n"
-        "            average_distance\n"
-        "            average_distance_pts\n"
-        "\n");
-
-    if( pszErrorMsg != NULL )
-        fprintf(stderr, "\nFAILURE: %s\n", pszErrorMsg);
-
-    GDALDestroyDriverManager();
-    exit( 1 );
-}
-
-/************************************************************************/
-/*                          GetAlgorithmName()                          */
-/*                                                                      */
-/*      Translates algortihm code into mnemonic name.                   */
-/************************************************************************/
-
-static void PrintAlgorithmAndOptions( GDALGridAlgorithm eAlgorithm,
-                                      void *pOptions )
-{
-    switch ( eAlgorithm )
-    {
-        case GGA_InverseDistanceToAPower:
-            printf( "Algorithm name: \"%s\".\n", szAlgNameInvDist );
-            CPLprintf( "Options are "
-                    "\"power=%f:smoothing=%f:radius1=%f:radius2=%f:angle=%f"
-                    ":max_points=%lu:min_points=%lu:nodata=%f\"\n",
-                ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfPower,
-                ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfSmoothing,
-                ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfRadius1,
-                ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfRadius2,
-                ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfAngle,
-                (unsigned long)((GDALGridInverseDistanceToAPowerOptions *)pOptions)->nMaxPoints,
-                (unsigned long)((GDALGridInverseDistanceToAPowerOptions *)pOptions)->nMinPoints,
-                ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfNoDataValue);
-            break;
-        case GGA_MovingAverage:
-            printf( "Algorithm name: \"%s\".\n", szAlgNameAverage );
-            CPLprintf( "Options are "
-                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
-                    ":nodata=%f\"\n",
-                ((GDALGridMovingAverageOptions *)pOptions)->dfRadius1,
-                ((GDALGridMovingAverageOptions *)pOptions)->dfRadius2,
-                ((GDALGridMovingAverageOptions *)pOptions)->dfAngle,
-                (unsigned long)((GDALGridMovingAverageOptions *)pOptions)->nMinPoints,
-                ((GDALGridMovingAverageOptions *)pOptions)->dfNoDataValue);
-            break;
-        case GGA_NearestNeighbor:
-            printf( "Algorithm name: \"%s\".\n", szAlgNameNearest );
-            CPLprintf( "Options are "
-                    "\"radius1=%f:radius2=%f:angle=%f:nodata=%f\"\n",
-                ((GDALGridNearestNeighborOptions *)pOptions)->dfRadius1,
-                ((GDALGridNearestNeighborOptions *)pOptions)->dfRadius2,
-                ((GDALGridNearestNeighborOptions *)pOptions)->dfAngle,
-                ((GDALGridNearestNeighborOptions *)pOptions)->dfNoDataValue);
-            break;
-        case GGA_MetricMinimum:
-            printf( "Algorithm name: \"%s\".\n", szAlgNameMinimum );
-            CPLprintf( "Options are "
-                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
-                    ":nodata=%f\"\n",
-                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
-                (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
-            break;
-        case GGA_MetricMaximum:
-            printf( "Algorithm name: \"%s\".\n", szAlgNameMaximum );
-            CPLprintf( "Options are "
-                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
-                    ":nodata=%f\"\n",
-                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
-                (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
-            break;
-        case GGA_MetricRange:
-            printf( "Algorithm name: \"%s\".\n", szAlgNameRange );
-            CPLprintf( "Options are "
-                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
-                    ":nodata=%f\"\n",
-                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
-                (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
-            break;
-        case GGA_MetricCount:
-            printf( "Algorithm name: \"%s\".\n", szAlgNameCount );
-            CPLprintf( "Options are "
-                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
-                    ":nodata=%f\"\n",
-                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
-                (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
-            break;
-        case GGA_MetricAverageDistance:
-            printf( "Algorithm name: \"%s\".\n", szAlgNameAverageDistance );
-            CPLprintf( "Options are "
-                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
-                    ":nodata=%f\"\n",
-                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
-                (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
-            break;
-        case GGA_MetricAverageDistancePts:
-            printf( "Algorithm name: \"%s\".\n", szAlgNameAverageDistancePts );
-            CPLprintf( "Options are "
-                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
-                    ":nodata=%f\"\n",
-                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
-                (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
-                ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
-            break;
-        default:
-            printf( "Algorithm is unknown.\n" );
-            break;
-    }
-}
-
-/************************************************************************/
-/*                          ProcessGeometry()                           */
-/*                                                                      */
-/*  Extract point coordinates from the geometry reference and set the   */
-/*  Z value as requested. Test whther we are in the clipped region      */
-/*  before processing.                                                  */
-/************************************************************************/
-
-static void ProcessGeometry( OGRPoint *poGeom, OGRGeometry *poClipSrc,
-                             int iBurnField, double dfBurnValue,
-                             const double dfIncreaseBurnValue,
-                             const double dfMultiplyBurnValue,
-                             std::vector<double> &adfX,
-                             std::vector<double> &adfY,
-                             std::vector<double> &adfZ )
-
-{
-    if ( poClipSrc && !poGeom->Within(poClipSrc) )
-        return;
-
-    adfX.push_back( poGeom->getX() );
-    adfY.push_back( poGeom->getY() );
-    if ( iBurnField < 0 )
-        adfZ.push_back(  (poGeom->getZ() + dfIncreaseBurnValue) * dfMultiplyBurnValue  );
-    else
-        adfZ.push_back( (dfBurnValue + dfIncreaseBurnValue) * dfMultiplyBurnValue );
-}
-
-/************************************************************************/
-/*                       ProcessCommonGeometry()                        */
-/*                                                                      */
-/*  Process recursivelly geometry and extract points                    */
-/************************************************************************/
-
-static void ProcessCommonGeometry(OGRGeometry* poGeom, OGRGeometry *poClipSrc,
-                                int iBurnField, double dfBurnValue,
-                                const double dfIncreaseBurnValue,
-                                const double dfMultiplyBurnValue,
-                                std::vector<double> &adfX,
-                                std::vector<double> &adfY,
-                                std::vector<double> &adfZ)
-{
-    if (NULL == poGeom)
-        return;
-
-    OGRwkbGeometryType eType = wkbFlatten(poGeom->getGeometryType());
-    switch (eType)
-    {
-    case wkbPoint:
-        return ProcessGeometry((OGRPoint *)poGeom, poClipSrc,
-            iBurnField, dfBurnValue, dfIncreaseBurnValue, dfMultiplyBurnValue, adfX, adfY, adfZ);
-    case wkbLinearRing:
-    case wkbLineString:
-        {
-            OGRLineString *poLS = (OGRLineString*)poGeom;
-            OGRPoint point;
-            for (int pointIndex = 0; pointIndex < poLS->getNumPoints(); pointIndex++)
-            {
-                poLS->getPoint(pointIndex, &point);
-                ProcessCommonGeometry((OGRGeometry*)&point, poClipSrc,
-                    iBurnField, dfBurnValue, dfIncreaseBurnValue, dfMultiplyBurnValue, adfX, adfY, adfZ);
-            }
-        }
-        break;
-    case wkbPolygon:
-        {
-            int nRings(0);
-            OGRPolygon* poPoly = (OGRPolygon*)poGeom;
-            OGRLinearRing* poRing = poPoly->getExteriorRing();
-            ProcessCommonGeometry((OGRGeometry*)poRing, poClipSrc,
-                iBurnField, dfBurnValue, dfIncreaseBurnValue, dfMultiplyBurnValue, adfX, adfY, adfZ);
-
-            nRings = poPoly->getNumInteriorRings();
-            if (nRings > 0)
-            {
-                for (int ir = 0; ir < nRings; ++ir)
-                {
-                    OGRLinearRing* poRing = poPoly->getInteriorRing(ir);
-                    ProcessCommonGeometry((OGRGeometry*)poRing, poClipSrc,
-                        iBurnField, dfBurnValue, dfIncreaseBurnValue, dfMultiplyBurnValue, adfX, adfY, adfZ);
-                }
-            }
-        }
-        break;
-    case wkbMultiPoint:
-    case wkbMultiPolygon:
-    case wkbMultiLineString:
-    case wkbGeometryCollection:
-        {
-            OGRGeometryCollection* pOGRGeometryCollection = (OGRGeometryCollection*)poGeom;
-            for (int i = 0; i < pOGRGeometryCollection->getNumGeometries(); ++i)
-            {
-                ProcessCommonGeometry(pOGRGeometryCollection->getGeometryRef(i), poClipSrc,
-                    iBurnField, dfBurnValue, dfIncreaseBurnValue, dfMultiplyBurnValue, adfX, adfY, adfZ);
-            }
-        }
-        break;
-    case wkbUnknown:
-    case wkbNone:
-    default:
-        break;
-    }
-}
-
-/************************************************************************/
-/*                            ProcessLayer()                            */
-/*                                                                      */
-/*      Process all the features in a layer selection, collecting       */
-/*      geometries and burn values.                                     */
-/************************************************************************/
-
-static CPLErr ProcessLayer( OGRLayerH hSrcLayer, GDALDatasetH hDstDS,
-                          OGRGeometry *poClipSrc,
-                          GUInt32 nXSize, GUInt32 nYSize, int nBand,
-                          int& bIsXExtentSet, int& bIsYExtentSet,
-                          double& dfXMin, double& dfXMax,
-                          double& dfYMin, double& dfYMax,
-                          const char *pszBurnAttribute,
-                          const double dfIncreaseBurnValue,
-                          const double dfMultiplyBurnValue,
-                          GDALDataType eType,
-                          GDALGridAlgorithm eAlgorithm, void *pOptions,
-                          int bQuiet, GDALProgressFunc pfnProgress )
-
-{
-/* -------------------------------------------------------------------- */
-/*      Get field index, and check.                                     */
-/* -------------------------------------------------------------------- */
-    int iBurnField = -1;
-
-    if ( pszBurnAttribute )
-    {
-        iBurnField = OGR_FD_GetFieldIndex( OGR_L_GetLayerDefn( hSrcLayer ),
-                                           pszBurnAttribute );
-        if( iBurnField == -1 )
-        {
-            printf( "Failed to find field %s on layer %s, skipping.\n",
-                    pszBurnAttribute, 
-                    OGR_FD_GetName( OGR_L_GetLayerDefn( hSrcLayer ) ) );
-            return CE_Failure;
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Collect the geometries from this layer, and build list of       */
-/*      values to be interpolated.                                      */
-/* -------------------------------------------------------------------- */
-    OGRFeature *poFeat;
-    std::vector<double> adfX, adfY, adfZ;
-
-    OGR_L_ResetReading( hSrcLayer );
-
-    while( (poFeat = (OGRFeature *)OGR_L_GetNextFeature( hSrcLayer )) != NULL )
-    {
-        OGRGeometry *poGeom = poFeat->GetGeometryRef();
-        double  dfBurnValue = 0.0;
-
-        if ( iBurnField >= 0 )
-            dfBurnValue = poFeat->GetFieldAsDouble( iBurnField );
-
-        ProcessCommonGeometry(poGeom, poClipSrc, iBurnField, dfBurnValue,
-            dfIncreaseBurnValue, dfMultiplyBurnValue, adfX, adfY, adfZ);
-
-        OGRFeature::DestroyFeature( poFeat );
-    }
-
-    if ( adfX.size() == 0 )
-    {
-        printf( "No point geometry found on layer %s, skipping.\n",
-                OGR_FD_GetName( OGR_L_GetLayerDefn( hSrcLayer ) ) );
-        return CE_None;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Compute grid geometry.                                          */
-/* -------------------------------------------------------------------- */
-    if ( !bIsXExtentSet || !bIsYExtentSet )
-    {
-        OGREnvelope sEnvelope;
-        OGR_L_GetExtent( hSrcLayer, &sEnvelope, TRUE );
-
-        if ( !bIsXExtentSet )
-        {
-            dfXMin = sEnvelope.MinX;
-            dfXMax = sEnvelope.MaxX;
-            bIsXExtentSet = TRUE;
-        }
-
-        if ( !bIsYExtentSet )
-        {
-            dfYMin = sEnvelope.MinY;
-            dfYMax = sEnvelope.MaxY;
-            bIsYExtentSet = TRUE;
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Perform gridding.                                               */
-/* -------------------------------------------------------------------- */
-
-    const double    dfDeltaX = ( dfXMax - dfXMin ) / nXSize;
-    const double    dfDeltaY = ( dfYMax - dfYMin ) / nYSize;
-
-    if ( !bQuiet )
-    {
-        printf( "Grid data type is \"%s\"\n", GDALGetDataTypeName(eType) );
-        printf( "Grid size = (%lu %lu).\n",
-                (unsigned long)nXSize, (unsigned long)nYSize );
-        CPLprintf( "Corner coordinates = (%f %f)-(%f %f).\n",
-                dfXMin - dfDeltaX / 2, dfYMax + dfDeltaY / 2,
-                dfXMax + dfDeltaX / 2, dfYMin - dfDeltaY / 2 );
-        CPLprintf( "Grid cell size = (%f %f).\n", dfDeltaX, dfDeltaY );
-        printf( "Source point count = %lu.\n", (unsigned long)adfX.size() );
-        PrintAlgorithmAndOptions( eAlgorithm, pOptions );
-        printf("\n");
-    }
-
-    GDALRasterBandH hBand = GDALGetRasterBand( hDstDS, nBand );
-
-    if (adfX.size() == 0)
-    {
-        // FIXME: Shoulda' set to nodata value instead
-        GDALFillRaster( hBand, 0.0 , 0.0 );
-        return CE_None;
-    }
-
-    GUInt32 nXOffset, nYOffset;
-    int     nBlockXSize, nBlockYSize;
-    int     nDataTypeSize = GDALGetDataTypeSize(eType) / 8;
-
-    // Try to grow the work buffer up to 16 MB if it is smaller
-    GDALGetBlockSize( hBand, &nBlockXSize, &nBlockYSize );
-    const GUInt32 nDesiredBufferSize = 16*1024*1024;
-    if( (GUInt32)nBlockXSize < nXSize && (GUInt32)nBlockYSize < nYSize &&
-        (GUInt32)nBlockXSize < nDesiredBufferSize / (nBlockYSize * nDataTypeSize) )
-    {
-        int nNewBlockXSize  = nDesiredBufferSize / (nBlockYSize * nDataTypeSize);
-        nBlockXSize = (nNewBlockXSize / nBlockXSize) * nBlockXSize;
-        if( (GUInt32)nBlockXSize > nXSize )
-            nBlockXSize = nXSize;
-    }
-    else if( (GUInt32)nBlockXSize == nXSize && (GUInt32)nBlockYSize < nYSize &&
-             (GUInt32)nBlockYSize < nDesiredBufferSize / (nXSize * nDataTypeSize) )
-    {
-        int nNewBlockYSize = nDesiredBufferSize / (nXSize * nDataTypeSize);
-        nBlockYSize = (nNewBlockYSize / nBlockYSize) * nBlockYSize;
-        if( (GUInt32)nBlockYSize > nYSize )
-            nBlockYSize = nYSize;
-    }
-    CPLDebug("GDAL_GRID", "Work buffer: %d * %d", nBlockXSize, nBlockYSize);
-
-    void    *pData =
-        VSIMalloc3( nBlockXSize, nBlockYSize, nDataTypeSize );
-    if( pData == NULL )
-    {
-        CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate work buffer");
-        return CE_Failure;
-    }
-
-    GUInt32 nBlock = 0;
-    GUInt32 nBlockCount = ((nXSize + nBlockXSize - 1) / nBlockXSize)
-        * ((nYSize + nBlockYSize - 1) / nBlockYSize);
-
-    CPLErr eErr = CE_None;
-    for ( nYOffset = 0; nYOffset < nYSize && eErr == CE_None; nYOffset += nBlockYSize )
-    {
-        for ( nXOffset = 0; nXOffset < nXSize && eErr == CE_None; nXOffset += nBlockXSize )
-        {
-            void *pScaledProgress;
-            pScaledProgress =
-                GDALCreateScaledProgress( (double)nBlock / nBlockCount,
-                                          (double)(nBlock + 1) / nBlockCount,
-                                          pfnProgress, NULL );
-            nBlock ++;
-
-            int nXRequest = nBlockXSize;
-            if (nXOffset + nXRequest > nXSize)
-                nXRequest = nXSize - nXOffset;
-
-            int nYRequest = nBlockYSize;
-            if (nYOffset + nYRequest > nYSize)
-                nYRequest = nYSize - nYOffset;
-
-            eErr = GDALGridCreate( eAlgorithm, pOptions,
-                            adfX.size(), &(adfX[0]), &(adfY[0]), &(adfZ[0]),
-                            dfXMin + dfDeltaX * nXOffset,
-                            dfXMin + dfDeltaX * (nXOffset + nXRequest),
-                            dfYMin + dfDeltaY * nYOffset,
-                            dfYMin + dfDeltaY * (nYOffset + nYRequest),
-                            nXRequest, nYRequest, eType, pData,
-                            GDALScaledProgress, pScaledProgress );
-
-            if( eErr == CE_None )
-                eErr = GDALRasterIO( hBand, GF_Write, nXOffset, nYOffset,
-                          nXRequest, nYRequest, pData,
-                          nXRequest, nYRequest, eType, 0, 0 );
-
-            GDALDestroyScaledProgress( pScaledProgress );
-        }
-    }
-
-    CPLFree( pData );
-    return eErr;
-}
-
-/************************************************************************/
-/*                            LoadGeometry()                            */
-/*                                                                      */
-/*  Read geometries from the given dataset using specified filters and  */
-/*  returns a collection of read geometries.                            */
-/************************************************************************/
-
-static OGRGeometryCollection* LoadGeometry( const char* pszDS,
-                                            const char* pszSQL,
-                                            const char* pszLyr,
-                                            const char* pszWhere )
-{
-    GDALDataset         *poDS;
-    OGRLayer            *poLyr;
-    OGRFeature          *poFeat;
-    OGRGeometryCollection *poGeom = NULL;
-        
-    poDS = (GDALDataset*) GDALOpen( pszDS, GA_ReadOnly );
-    if ( poDS == NULL )
-        return NULL;
-
-    if ( pszSQL != NULL )
-        poLyr = poDS->ExecuteSQL( pszSQL, NULL, NULL ); 
-    else if ( pszLyr != NULL )
-        poLyr = poDS->GetLayerByName( pszLyr );
-    else
-        poLyr = poDS->GetLayer(0);
-        
-    if ( poLyr == NULL )
-    {
-        fprintf( stderr,
-            "FAILURE: Failed to identify source layer from datasource.\n" );
-        GDALClose( (GDALDatasetH) poDS );
-        return NULL;
-    }
-    
-    if ( pszWhere )
-        poLyr->SetAttributeFilter( pszWhere );
-        
-    while ( (poFeat = poLyr->GetNextFeature()) != NULL )
-    {
-        OGRGeometry* poSrcGeom = poFeat->GetGeometryRef();
-        if ( poSrcGeom )
-        {
-            OGRwkbGeometryType eType =
-                wkbFlatten( poSrcGeom->getGeometryType() );
-            
-            if ( poGeom == NULL )
-                poGeom = new OGRMultiPolygon();
-
-            if ( eType == wkbPolygon )
-                poGeom->addGeometry( poSrcGeom );
-            else if ( eType == wkbMultiPolygon )
-            {
-                int iGeom;
-                int nGeomCount =
-                    ((OGRMultiPolygon *)poSrcGeom)->getNumGeometries();
-
-                for ( iGeom = 0; iGeom < nGeomCount; iGeom++ )
-                {
-                    poGeom->addGeometry(
-                        ((OGRMultiPolygon *)poSrcGeom)->getGeometryRef(iGeom) );
-                }
-            }
-            else
-            {
-                fprintf( stderr, "FAILURE: Geometry not of polygon type.\n" );
-                OGRGeometryFactory::destroyGeometry( poGeom );
-                OGRFeature::DestroyFeature( poFeat );
-                if ( pszSQL != NULL )
-                    poDS->ReleaseResultSet( poLyr );
-                GDALClose( (GDALDatasetH) poDS );
-                return NULL;
-            }
-        }
-    
-        OGRFeature::DestroyFeature( poFeat );
-    }
-    
-    if( pszSQL != NULL )
-        poDS->ReleaseResultSet( poLyr );
-    GDALClose( (GDALDatasetH) poDS );
-    
-    return poGeom;
-}
-
-/************************************************************************/
-/*                                main()                                */
-/************************************************************************/
-
-#define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg) \
-    do { if (i + nExtraArg >= argc) \
-        Usage(CPLSPrintf("%s option requires %d argument(s)", argv[i], nExtraArg)); } while(0)
-
-int main( int argc, char ** argv )
-{
-    GDALDriverH     hDriver;
-    const char      *pszSource=NULL, *pszDest=NULL, *pszFormat = "GTiff";
-    int             bFormatExplicitlySet = FALSE;
-    char            **papszLayers = NULL;
-    const char      *pszBurnAttribute = NULL;
-    double          dfIncreaseBurnValue = 0.0;
-    double          dfMultiplyBurnValue = 1.0;
-    const char      *pszWHERE = NULL, *pszSQL = NULL;
-    GDALDataType    eOutputType = GDT_Float64;
-    char            **papszCreateOptions = NULL;
-    GUInt32         nXSize = 0, nYSize = 0;
-    double          dfXMin = 0.0, dfXMax = 0.0, dfYMin = 0.0, dfYMax = 0.0;
-    int             bIsXExtentSet = FALSE, bIsYExtentSet = FALSE;
-    GDALGridAlgorithm eAlgorithm = GGA_InverseDistanceToAPower;
-    void            *pOptions = NULL;
-    char            *pszOutputSRS = NULL;
-    int             bQuiet = FALSE;
-    GDALProgressFunc pfnProgress = GDALTermProgress;
-    int             i;
-    OGRGeometry     *poSpatialFilter = NULL;
-    int             bClipSrc = FALSE;
-    OGRGeometry     *poClipSrc = NULL;
-    const char      *pszClipSrcDS = NULL;
-    const char      *pszClipSrcSQL = NULL;
-    const char      *pszClipSrcLayer = NULL;
-    const char      *pszClipSrcWhere = NULL;
-    int              bNoDataSet = FALSE;
-    double           dfNoDataValue = 0;
-
-    /* Check strict compilation and runtime library version as we use C++ API */
-    if (! GDAL_CHECK_VERSION(argv[0]))
-        exit(1);
-
-    GDALAllRegister();
-    OGRRegisterAll();
-
-    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
-    if( argc < 1 )
-        exit( -argc );
-
-/* -------------------------------------------------------------------- */
-/*      Parse arguments.                                                */
-/* -------------------------------------------------------------------- */
-    for( i = 1; i < argc; i++ )
-    {
-        if( EQUAL(argv[i], "--utility_version") )
-        {
-            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
-                   argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
-            return 0;
-        }
-        else if( EQUAL(argv[i],"--help") )
-            Usage();
-        else if( EQUAL(argv[i],"-of") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszFormat = argv[++i];
-            bFormatExplicitlySet = TRUE;
-        }
-
-        else if( EQUAL(argv[i],"-q") || EQUAL(argv[i],"-quiet") )
-        {
-            bQuiet = TRUE;
-            pfnProgress = GDALDummyProgress;
-        }
-
-        else if( EQUAL(argv[i],"-ot") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            int	iType;
-            
-            for( iType = 1; iType < GDT_TypeCount; iType++ )
-            {
-                if( GDALGetDataTypeName((GDALDataType)iType) != NULL
-                    && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
-                             argv[i+1]) )
-                {
-                    eOutputType = (GDALDataType) iType;
-                }
-            }
-
-            if( eOutputType == GDT_Unknown )
-            {
-                Usage(CPLSPrintf("Unknown output pixel type: %s.",
-                                 argv[i + 1] ));
-            }
-            i++;
-        }
-
-        else if( EQUAL(argv[i],"-txe") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2);
-            dfXMin = CPLAtof(argv[++i]);
-            dfXMax = CPLAtof(argv[++i]);
-            bIsXExtentSet = TRUE;
-        }   
-
-        else if( EQUAL(argv[i],"-tye") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2);
-            dfYMin = CPLAtof(argv[++i]);
-            dfYMax = CPLAtof(argv[++i]);
-            bIsYExtentSet = TRUE;
-        }   
-
-        else if( EQUAL(argv[i],"-outsize") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2);
-            nXSize = atoi(argv[++i]);
-            nYSize = atoi(argv[++i]);
-        }   
-
-        else if( EQUAL(argv[i],"-co") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            papszCreateOptions = CSLAddString( papszCreateOptions, argv[++i] );
-        }   
-
-        else if( EQUAL(argv[i],"-zfield") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszBurnAttribute = argv[++i];
-        }
-
-        else if( EQUAL(argv[i],"-z_increase") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            dfIncreaseBurnValue = CPLAtof(argv[++i]);
-        }
-
-        else if( EQUAL(argv[i],"-z_multiply") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            dfMultiplyBurnValue = CPLAtof(argv[++i]);
-        }
-
-        else if( EQUAL(argv[i],"-where") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszWHERE = argv[++i];
-        }
-
-        else if( EQUAL(argv[i],"-l") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            papszLayers = CSLAddString( papszLayers, argv[++i] );
-        }
-
-        else if( EQUAL(argv[i],"-sql") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszSQL = argv[++i];
-        }
-
-        else if( EQUAL(argv[i],"-spat") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(4);
-            OGRLinearRing  oRing;
-
-            oRing.addPoint( CPLAtof(argv[i+1]), CPLAtof(argv[i+2]) );
-            oRing.addPoint( CPLAtof(argv[i+1]), CPLAtof(argv[i+4]) );
-            oRing.addPoint( CPLAtof(argv[i+3]), CPLAtof(argv[i+4]) );
-            oRing.addPoint( CPLAtof(argv[i+3]), CPLAtof(argv[i+2]) );
-            oRing.addPoint( CPLAtof(argv[i+1]), CPLAtof(argv[i+2]) );
-
-            poSpatialFilter = new OGRPolygon();
-            ((OGRPolygon *) poSpatialFilter)->addRing( &oRing );
-            i += 4;
-        }
-
-        else if ( EQUAL(argv[i],"-clipsrc") )
-        {
-            if (i + 1 >= argc)
-                Usage(CPLSPrintf("%s option requires 1 or 4 arguments", argv[i]));
-
-            bClipSrc = TRUE;
-            errno = 0;
-            const double unused = strtod( argv[i + 1], NULL );    // XXX: is it a number or not?
-            if ( errno != 0
-                 && argv[i + 2] != NULL
-                 && argv[i + 3] != NULL
-                 && argv[i + 4] != NULL)
-            {
-                OGRLinearRing  oRing;
-
-                oRing.addPoint( CPLAtof(argv[i + 1]), CPLAtof(argv[i + 2]) );
-                oRing.addPoint( CPLAtof(argv[i + 1]), CPLAtof(argv[i + 4]) );
-                oRing.addPoint( CPLAtof(argv[i + 3]), CPLAtof(argv[i + 4]) );
-                oRing.addPoint( CPLAtof(argv[i + 3]), CPLAtof(argv[i + 2]) );
-                oRing.addPoint( CPLAtof(argv[i + 1]), CPLAtof(argv[i + 2]) );
-
-                poClipSrc = new OGRPolygon();
-                ((OGRPolygon *) poClipSrc)->addRing( &oRing );
-                i += 4;
-
-                (void)unused;
-            }
-            else if (EQUALN(argv[i + 1], "POLYGON", 7)
-                     || EQUALN(argv[i + 1], "MULTIPOLYGON", 12))
-            {
-                OGRGeometryFactory::createFromWkt(&argv[i + 1], NULL, &poClipSrc);
-                if ( poClipSrc == NULL )
-                {
-                    Usage("Invalid geometry. "
-                             "Must be a valid POLYGON or MULTIPOLYGON WKT.");
-                }
-                i++;
-            }
-            else if (EQUAL(argv[i + 1], "spat_extent") )
-            {
-                i++;
-            }
-            else
-            {
-                pszClipSrcDS = argv[i + 1];
-                i++;
-            }
-        }
-
-        else if ( EQUAL(argv[i], "-clipsrcsql") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszClipSrcSQL = argv[i + 1];
-            i++;
-        }
-
-        else if ( EQUAL(argv[i], "-clipsrclayer") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszClipSrcLayer = argv[i + 1];
-            i++;
-        }
-
-        else if ( EQUAL(argv[i], "-clipsrcwhere") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszClipSrcWhere = argv[i + 1];
-            i++;
-        }
-
-        else if( EQUAL(argv[i],"-a_srs") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            OGRSpatialReference oOutputSRS;
-
-            if( oOutputSRS.SetFromUserInput( argv[i+1] ) != OGRERR_NONE )
-            {
-                fprintf( stderr, "Failed to process SRS definition: %s\n", 
-                         argv[i+1] );
-                GDALDestroyDriverManager();
-                exit( 1 );
-            }
-
-            oOutputSRS.exportToWkt( &pszOutputSRS );
-            i++;
-        }   
-
-        else if( EQUAL(argv[i],"-a") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            const char* pszAlgorithm = argv[++i];
-            if ( ParseAlgorithmAndOptions( pszAlgorithm, &eAlgorithm, &pOptions )
-                 != CE_None )
-            {
-                fprintf( stderr,
-                         "Failed to process algorithm name and parameters.\n" );
-                exit( 1 );
-            }
-            
-            char **papszParms = CSLTokenizeString2( pszAlgorithm, ":", FALSE );
-            const char* pszNoDataValue = CSLFetchNameValue( papszParms, "nodata" );
-            if( pszNoDataValue != NULL )
-            {
-                bNoDataSet = TRUE;
-                dfNoDataValue = CPLAtofM(pszNoDataValue);
-            }
-            CSLDestroy(papszParms);
-        }
-
-        else if( argv[i][0] == '-' )
-        {
-            Usage(CPLSPrintf("Unknown option name '%s'", argv[i]));
-        }
-
-        else if( pszSource == NULL )
-        {
-            pszSource = argv[i];
-        }
-
-        else if( pszDest == NULL )
-        {
-            pszDest = argv[i];
-        }
-
-        else
-        {
-            Usage("Too many command options.");
-        }
-    }
-
-    if( pszSource == NULL )
-    {
-        Usage("Source datasource is not specified.");
-    }
-    if( pszDest == NULL )
-    {
-        Usage("Target dataset is not specified.");
-    }
-    if( pszSQL == NULL && papszLayers == NULL )
-    {
-        Usage("Neither -sql nor -l are specified.");
-    }
-    
-    if ( bClipSrc && pszClipSrcDS != NULL )
-    {
-        poClipSrc = LoadGeometry( pszClipSrcDS, pszClipSrcSQL,
-                                  pszClipSrcLayer, pszClipSrcWhere );
-        if ( poClipSrc == NULL )
-        {
-            Usage("Cannot load source clip geometry.");
-        }
-    }
-    else if ( bClipSrc && poClipSrc == NULL && !poSpatialFilter )
-    {
-        Usage("-clipsrc must be used with -spat option or \n"
-                 "a bounding box, WKT string or datasource must be "
-                 "specified.");
-    }
-
-    if ( poSpatialFilter )
-    {
-        if ( poClipSrc )
-        {
-            OGRGeometry *poTemp = poSpatialFilter->Intersection( poClipSrc );
-
-            if ( poTemp )
-            {
-                OGRGeometryFactory::destroyGeometry( poSpatialFilter );
-                poSpatialFilter = poTemp;
-            }
-
-            OGRGeometryFactory::destroyGeometry( poClipSrc );
-            poClipSrc = NULL;
-        }
-    }
-    else
-    {
-        if ( poClipSrc )
-        {
-            poSpatialFilter = poClipSrc;
-            poClipSrc = NULL;
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Find the output driver.                                         */
-/* -------------------------------------------------------------------- */
-    hDriver = GDALGetDriverByName( pszFormat );
-    if( hDriver == NULL )
-    {
-        int	iDr;
-        
-        fprintf( stderr,
-                 "FAILURE: Output driver `%s' not recognised.\n", pszFormat );
-        fprintf( stderr,
-        "The following format drivers are configured and support output:\n" );
-        for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
-        {
-            GDALDriverH hDriver = GDALGetDriver(iDr);
-
-            if( GDALGetMetadataItem( hDriver, GDAL_DCAP_RASTER, NULL) != NULL &&
-                ( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) != NULL
-                || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY, NULL ) != NULL) )
-            {
-                fprintf( stderr, "  %s: %s\n",
-                         GDALGetDriverShortName( hDriver  ),
-                         GDALGetDriverLongName( hDriver ) );
-            }
-        }
-        printf( "\n" );
-        Usage();
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Open input datasource.                                          */
-/* -------------------------------------------------------------------- */
-    OGRDataSourceH hSrcDS;
-
-    hSrcDS = OGROpen( pszSource, FALSE, NULL );
-    if( hSrcDS == NULL )
-    {
-        fprintf( stderr, "Unable to open input datasource \"%s\".\n",
-                 pszSource );
-        fprintf( stderr, "%s\n", CPLGetLastErrorMsg() );
-        exit( 3 );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Create target raster file.                                      */
-/* -------------------------------------------------------------------- */
-    GDALDatasetH    hDstDS;
-    int             nLayerCount = CSLCount(papszLayers);
-    int             nBands = nLayerCount;
-
-    if ( pszSQL )
-        nBands++;
-
-    // FIXME
-    if ( nXSize == 0 )
-        nXSize = 256;
-    if ( nYSize == 0 )
-        nYSize = 256;
-
-    if (!bQuiet && !bFormatExplicitlySet)
-        CheckExtensionConsistency(pszDest, pszFormat);
-
-    hDstDS = GDALCreate( hDriver, pszDest, nXSize, nYSize, nBands,
-                         eOutputType, papszCreateOptions );
-    if ( hDstDS == NULL )
-    {
-        fprintf( stderr, "Unable to create target dataset \"%s\".\n",
-                 pszDest );
-        fprintf( stderr, "%s\n", CPLGetLastErrorMsg() );
-        exit( 3 );
-    }
-    
-    if( bNoDataSet )
-    {
-        for( i = 1; i <= nBands; i++ )
-        {
-            GDALRasterBandH hBand = GDALGetRasterBand( hDstDS, i );
-            GDALSetRasterNoDataValue( hBand, dfNoDataValue );
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      If algorithm was not specified assigh default one.              */
-/* -------------------------------------------------------------------- */
-    if ( !pOptions )
-        ParseAlgorithmAndOptions( szAlgNameInvDist, &eAlgorithm, &pOptions );
-
-/* -------------------------------------------------------------------- */
-/*      Process SQL request.                                            */
-/* -------------------------------------------------------------------- */
-    if( pszSQL != NULL )
-    {
-        OGRLayerH hLayer;
-
-        hLayer = OGR_DS_ExecuteSQL( hSrcDS, pszSQL,
-                                    (OGRGeometryH)poSpatialFilter, NULL ); 
-        if( hLayer != NULL )
-        {
-            // Custom layer will be rasterized in the first band.
-            ProcessLayer( hLayer, hDstDS, poSpatialFilter, nXSize, nYSize, 1,
-                          bIsXExtentSet, bIsYExtentSet,
-                          dfXMin, dfXMax, dfYMin, dfYMax, pszBurnAttribute,
-                          dfIncreaseBurnValue, dfMultiplyBurnValue, eOutputType, eAlgorithm, pOptions,
-                          bQuiet, pfnProgress );
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Process each layer.                                             */
-/* -------------------------------------------------------------------- */
-    for( i = 0; i < nLayerCount; i++ )
-    {
-        OGRLayerH hLayer = OGR_DS_GetLayerByName( hSrcDS, papszLayers[i]);
-        if( hLayer == NULL )
-        {
-            fprintf( stderr, "Unable to find layer \"%s\", skipping.\n", 
-                     papszLayers[i] );
-            continue;
-        }
-
-        if( pszWHERE )
-        {
-            if( OGR_L_SetAttributeFilter( hLayer, pszWHERE ) != OGRERR_NONE )
-                break;
-        }
-
-        if ( poSpatialFilter != NULL )
-            OGR_L_SetSpatialFilter( hLayer, (OGRGeometryH)poSpatialFilter );
-
-        // Fetch the first meaningful SRS definition
-        if ( !pszOutputSRS )
-        {
-            OGRSpatialReferenceH hSRS = OGR_L_GetSpatialRef( hLayer );
-            if ( hSRS )
-                OSRExportToWkt( hSRS, &pszOutputSRS );
-        }
-
-        ProcessLayer( hLayer, hDstDS, poSpatialFilter, nXSize, nYSize,
-                      i + 1 + nBands - nLayerCount,
-                      bIsXExtentSet, bIsYExtentSet,
-                      dfXMin, dfXMax, dfYMin, dfYMax, pszBurnAttribute,
-                      dfIncreaseBurnValue, dfMultiplyBurnValue, eOutputType, eAlgorithm, pOptions,
-                      bQuiet, pfnProgress );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Apply geotransformation matrix.                                 */
-/* -------------------------------------------------------------------- */
-    double  adfGeoTransform[6];
-    adfGeoTransform[0] = dfXMin;
-    adfGeoTransform[1] = (dfXMax - dfXMin) / nXSize;
-    adfGeoTransform[2] = 0.0;
-    adfGeoTransform[3] = dfYMin;
-    adfGeoTransform[4] = 0.0;
-    adfGeoTransform[5] = (dfYMax - dfYMin) / nYSize;
-    GDALSetGeoTransform( hDstDS, adfGeoTransform );
-
-/* -------------------------------------------------------------------- */
-/*      Apply SRS definition if set.                                    */
-/* -------------------------------------------------------------------- */
-    if ( pszOutputSRS )
-    {
-        GDALSetProjection( hDstDS, pszOutputSRS );
-        CPLFree( pszOutputSRS );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Cleanup                                                         */
-/* -------------------------------------------------------------------- */
-    OGR_DS_Destroy( hSrcDS );
-    GDALClose( hDstDS );
-    OGRGeometryFactory::destroyGeometry( poSpatialFilter );
-
-    CPLFree( pOptions );
-    CSLDestroy( papszCreateOptions );
-    CSLDestroy( argv );
-    CSLDestroy( papszLayers );
-
-    OGRCleanupAll();
-
-    GDALDestroyDriverManager();
- 
-    return 0;
-}
-
diff --git a/apps/gdal_grid_bin.cpp b/apps/gdal_grid_bin.cpp
new file mode 100644
index 0000000..5501f4c
--- /dev/null
+++ b/apps/gdal_grid_bin.cpp
@@ -0,0 +1,195 @@
+/******************************************************************************
+ * $Id: gdal_grid_bin.cpp 33615 2016-03-02 20:19:22Z goatbar $
+ *
+ * Project:  GDAL Utilities
+ * Purpose:  GDAL scattered data gridding (interpolation) tool
+ * Authors:  Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_string.h"
+#include "commonutils.h"
+#include "gdal_utils_priv.h"
+
+CPL_CVSID("$Id: gdal_grid_bin.cpp 33615 2016-03-02 20:19:22Z goatbar $");
+
+/************************************************************************/
+/*                               Usage()                                */
+/************************************************************************/
+
+static void Usage(const char* pszErrorMsg = NULL)
+
+{
+    printf(
+        "Usage: gdal_grid [--help-general] [--formats]\n"
+        "    [-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/\n"
+        "          CInt16/CInt32/CFloat32/CFloat64}]\n"
+        "    [-of format] [-co \"NAME=VALUE\"]\n"
+        "    [-zfield field_name] [-z_increase increase_value] [-z_multiply multiply_value]\n"
+        "    [-a_srs srs_def] [-spat xmin ymin xmax ymax]\n"
+        "    [-clipsrc <xmin ymin xmax ymax>|WKT|datasource|spat_extent]\n"
+        "    [-clipsrcsql sql_statement] [-clipsrclayer layer]\n"
+        "    [-clipsrcwhere expression]\n"
+        "    [-l layername]* [-where expression] [-sql select_statement]\n"
+        "    [-txe xmin xmax] [-tye ymin ymax] [-outsize xsize ysize]\n"
+        "    [-a algorithm[:parameter1=value1]*]"
+        "    [-q]\n"
+        "    <src_datasource> <dst_filename>\n"
+        "\n"
+        "Available algorithms and parameters with their defaults:\n"
+        "    Inverse distance to a power (default)\n"
+        "        invdist:power=2.0:smoothing=0.0:radius1=0.0:radius2=0.0:angle=0.0:max_points=0:min_points=0:nodata=0.0\n"
+        "    Inverse distance to a power with nearest neighbor search\n"
+        "        invdistnn:power=2.0:radius=1.0:max_points=12:min_points=0:nodata=0\n"
+        "    Moving average\n"
+        "        average:radius1=0.0:radius2=0.0:angle=0.0:min_points=0:nodata=0.0\n"
+        "    Nearest neighbor\n"
+        "        nearest:radius1=0.0:radius2=0.0:angle=0.0:nodata=0.0\n"
+        "    Various data metrics\n"
+        "        <metric name>:radius1=0.0:radius2=0.0:angle=0.0:min_points=0:nodata=0.0\n"
+        "        possible metrics are:\n"
+        "            minimum\n"
+        "            maximum\n"
+        "            range\n"
+        "            count\n"
+        "            average_distance\n"
+        "            average_distance_pts\n"
+        "    Linear\n"
+        "        linear:radius=-1.0:nodata=0.0\n"
+        "\n");
+
+    if( pszErrorMsg != NULL )
+        fprintf(stderr, "\nFAILURE: %s\n", pszErrorMsg);
+
+    GDALDestroyDriverManager();
+    exit( 1 );
+}
+/************************************************************************/
+/*                         GDALGridOptionsForBinaryNew()                */
+/************************************************************************/
+
+static GDALGridOptionsForBinary *GDALGridOptionsForBinaryNew(void)
+{
+    return (GDALGridOptionsForBinary*) CPLCalloc(  1, sizeof(GDALGridOptionsForBinary) );
+}
+
+/************************************************************************/
+/*                         GDALGridOptionsForBinaryFree()               */
+/************************************************************************/
+
+static void GDALGridOptionsForBinaryFree( GDALGridOptionsForBinary* psOptionsForBinary )
+{
+    if( psOptionsForBinary )
+    {
+        CPLFree(psOptionsForBinary->pszSource);
+        CPLFree(psOptionsForBinary->pszDest);
+        CPLFree(psOptionsForBinary->pszFormat);
+        CPLFree(psOptionsForBinary);
+    }
+}
+/************************************************************************/
+/*                                main()                                */
+/************************************************************************/
+
+int main(int argc, char** argv)
+{
+    /* Check strict compilation and runtime library version as we use C++ API */
+    if (! GDAL_CHECK_VERSION(argv[0]))
+        exit(1);
+
+    EarlySetConfigOptions(argc, argv);
+
+/* -------------------------------------------------------------------- */
+/*      Generic arg processing.                                         */
+/* -------------------------------------------------------------------- */
+    GDALAllRegister();
+    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
+    if( argc < 1 )
+        exit( -argc );
+
+    for( int i = 0; i < argc; i++ )
+    {
+        if( EQUAL(argv[i], "--utility_version") )
+        {
+            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
+                   argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
+            CSLDestroy( argv );
+            return 0;
+        }
+        else if( EQUAL(argv[i],"--help") )
+        {
+            Usage();
+        }
+    }
+
+    GDALGridOptionsForBinary* psOptionsForBinary = GDALGridOptionsForBinaryNew();
+    /* coverity[tainted_data] */
+    GDALGridOptions *psOptions = GDALGridOptionsNew(argv + 1, psOptionsForBinary);
+    CSLDestroy( argv );
+
+    if( psOptions == NULL )
+    {
+        Usage();
+    }
+
+    if( !(psOptionsForBinary->bQuiet) )
+    {
+        GDALGridOptionsSetProgress(psOptions, GDALTermProgress, NULL);
+    }
+
+    if( psOptionsForBinary->pszSource == NULL )
+        Usage("No input file specified.");
+    if( psOptionsForBinary->pszDest== NULL )
+        Usage("No output file specified.");
+
+    if( psOptionsForBinary->pszDest == NULL )
+        psOptionsForBinary->pszDest = CPLStrdup(psOptionsForBinary->pszSource);
+    else if (!psOptionsForBinary->bQuiet && !psOptionsForBinary->bFormatExplicitlySet)
+        CheckExtensionConsistency(psOptionsForBinary->pszDest, psOptionsForBinary->pszFormat);
+
+/* -------------------------------------------------------------------- */
+/*      Open input file.                                                */
+/* -------------------------------------------------------------------- */
+    GDALDatasetH hInDS = GDALOpenEx( psOptionsForBinary->pszSource, GDAL_OF_VECTOR | GDAL_OF_VERBOSE_ERROR,
+                                     NULL, NULL, NULL );
+    if( hInDS == NULL )
+        exit( 1 );
+
+    int bUsageError = FALSE;
+    GDALDatasetH hOutDS = GDALGrid(psOptionsForBinary->pszDest,
+                                   hInDS,
+                                   psOptions, &bUsageError);
+    if(bUsageError == TRUE)
+        Usage();
+    int nRetCode = (hOutDS) ? 0 : 1;
+
+    GDALClose(hInDS);
+    GDALClose(hOutDS);
+    GDALGridOptionsFree(psOptions);
+    GDALGridOptionsForBinaryFree(psOptionsForBinary);
+
+    OGRCleanupAll();
+    GDALDestroyDriverManager();
+
+    return nRetCode;
+}
diff --git a/apps/gdal_grid_lib.cpp b/apps/gdal_grid_lib.cpp
new file mode 100644
index 0000000..72d98fc
--- /dev/null
+++ b/apps/gdal_grid_lib.cpp
@@ -0,0 +1,1320 @@
+/* ****************************************************************************
+ * $Id: gdal_grid_lib.cpp 33808 2016-03-29 21:15:28Z goatbar $
+ *
+ * Project:  GDAL Utilities
+ * Purpose:  GDAL scattered data gridding (interpolation) tool
+ * Author:   Andrey Kiselev, dron at ak4719.spb.edu
+ *
+ * ****************************************************************************
+ * Copyright (c) 2007, Andrey Kiselev <dron at ak4719.spb.edu>
+ * Copyright (c) 2015, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_string.h"
+#include "gdal.h"
+#include "gdal_alg.h"
+#include "ogr_spatialref.h"
+#include "ogr_api.h"
+#include "ogrsf_frmts.h"
+#include "gdalgrid.h"
+#include "gdal_utils_priv.h"
+
+#include <cstdlib>
+#include <vector>
+#include <algorithm>
+
+CPL_CVSID("$Id: gdal_grid_lib.cpp 33808 2016-03-29 21:15:28Z goatbar $");
+
+/************************************************************************/
+/*                          GDALGridOptions                             */
+/************************************************************************/
+
+/** Options for use with GDALGrid(). GDALGridOptions* must be allocated
+ * and freed with GDALGridOptionsNew() and GDALGridOptionsFree() respectively.
+ */
+struct GDALGridOptions
+{
+
+    /*! output format. The default is GeoTIFF(GTiff). Use the short format name. */
+    char *pszFormat;
+
+    /*! allow or suppress progress monitor and other non-error output */
+    int bQuiet;
+
+    /*! the progress function to use */
+    GDALProgressFunc pfnProgress;
+
+    /*! pointer to the progress data variable */
+    void *pProgressData;
+
+    char            **papszLayers;
+    char            *pszBurnAttribute;
+    double          dfIncreaseBurnValue;
+    double          dfMultiplyBurnValue;
+    char            *pszWHERE;
+    char            *pszSQL;
+    GDALDataType    eOutputType;
+    char            **papszCreateOptions;
+    int             nXSize;
+    int             nYSize;
+    double          dfXMin;
+    double          dfXMax;
+    double          dfYMin;
+    double          dfYMax;
+    int             bIsXExtentSet;
+    int             bIsYExtentSet;
+    GDALGridAlgorithm eAlgorithm;
+    void            *pOptions;
+    char            *pszOutputSRS;
+    OGRGeometry     *poSpatialFilter;
+    int             bClipSrc;
+    OGRGeometry     *poClipSrc;
+    char            *pszClipSrcDS;
+    char            *pszClipSrcSQL;
+    char            *pszClipSrcLayer;
+    char            *pszClipSrcWhere;
+    int              bNoDataSet;
+    double           dfNoDataValue;
+};
+
+/************************************************************************/
+/*                          GetAlgorithmName()                          */
+/*                                                                      */
+/*      Grids algorithm code into mnemonic name.                        */
+/************************************************************************/
+
+static void PrintAlgorithmAndOptions( GDALGridAlgorithm eAlgorithm,
+                                      void *pOptions )
+{
+    switch ( eAlgorithm )
+    {
+        case GGA_InverseDistanceToAPower:
+            printf( "Algorithm name: \"%s\".\n", szAlgNameInvDist );
+            CPLprintf( "Options are "
+                    "\"power=%f:smoothing=%f:radius1=%f:radius2=%f:angle=%f"
+                    ":max_points=%lu:min_points=%lu:nodata=%f\"\n",
+                ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfPower,
+                ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfSmoothing,
+                ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfRadius1,
+                ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfRadius2,
+                ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfAngle,
+                (unsigned long)((GDALGridInverseDistanceToAPowerOptions *)pOptions)->nMaxPoints,
+                (unsigned long)((GDALGridInverseDistanceToAPowerOptions *)pOptions)->nMinPoints,
+                ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfNoDataValue);
+            break;
+        case GGA_InverseDistanceToAPowerNearestNeighbor:
+            printf( "Algorithm name: \"%s\".\n", szAlgNameInvDistNearestNeighbor );
+            CPLprintf( "Options are "
+                        "\"power=%f:radius=%f"
+                    ":max_points=%lu:min_points=%lu:nodata=%f\"\n",
+                ((GDALGridInverseDistanceToAPowerNearestNeighborOptions *)pOptions)->dfPower,
+                ((GDALGridInverseDistanceToAPowerNearestNeighborOptions *)pOptions)->dfRadius,
+                (unsigned long)((GDALGridInverseDistanceToAPowerNearestNeighborOptions *)pOptions)->nMaxPoints,
+                (unsigned long)((GDALGridInverseDistanceToAPowerNearestNeighborOptions *)pOptions)->nMinPoints,
+                ((GDALGridInverseDistanceToAPowerNearestNeighborOptions *)pOptions)->dfNoDataValue);
+            break;
+        case GGA_MovingAverage:
+            printf( "Algorithm name: \"%s\".\n", szAlgNameAverage );
+            CPLprintf( "Options are "
+                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
+                    ":nodata=%f\"\n",
+                ((GDALGridMovingAverageOptions *)pOptions)->dfRadius1,
+                ((GDALGridMovingAverageOptions *)pOptions)->dfRadius2,
+                ((GDALGridMovingAverageOptions *)pOptions)->dfAngle,
+                (unsigned long)((GDALGridMovingAverageOptions *)pOptions)->nMinPoints,
+                ((GDALGridMovingAverageOptions *)pOptions)->dfNoDataValue);
+            break;
+        case GGA_NearestNeighbor:
+            printf( "Algorithm name: \"%s\".\n", szAlgNameNearest );
+            CPLprintf( "Options are "
+                    "\"radius1=%f:radius2=%f:angle=%f:nodata=%f\"\n",
+                ((GDALGridNearestNeighborOptions *)pOptions)->dfRadius1,
+                ((GDALGridNearestNeighborOptions *)pOptions)->dfRadius2,
+                ((GDALGridNearestNeighborOptions *)pOptions)->dfAngle,
+                ((GDALGridNearestNeighborOptions *)pOptions)->dfNoDataValue);
+            break;
+        case GGA_MetricMinimum:
+            printf( "Algorithm name: \"%s\".\n", szAlgNameMinimum );
+            CPLprintf( "Options are "
+                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
+                    ":nodata=%f\"\n",
+                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
+                (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
+            break;
+        case GGA_MetricMaximum:
+            printf( "Algorithm name: \"%s\".\n", szAlgNameMaximum );
+            CPLprintf( "Options are "
+                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
+                    ":nodata=%f\"\n",
+                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
+                (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
+            break;
+        case GGA_MetricRange:
+            printf( "Algorithm name: \"%s\".\n", szAlgNameRange );
+            CPLprintf( "Options are "
+                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
+                    ":nodata=%f\"\n",
+                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
+                (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
+            break;
+        case GGA_MetricCount:
+            printf( "Algorithm name: \"%s\".\n", szAlgNameCount );
+            CPLprintf( "Options are "
+                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
+                    ":nodata=%f\"\n",
+                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
+                (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
+            break;
+        case GGA_MetricAverageDistance:
+            printf( "Algorithm name: \"%s\".\n", szAlgNameAverageDistance );
+            CPLprintf( "Options are "
+                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
+                    ":nodata=%f\"\n",
+                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
+                (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
+            break;
+        case GGA_MetricAverageDistancePts:
+            printf( "Algorithm name: \"%s\".\n", szAlgNameAverageDistancePts );
+            CPLprintf( "Options are "
+                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
+                    ":nodata=%f\"\n",
+                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
+                (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
+            break;
+        case GGA_Linear:
+            printf( "Algorithm name: \"%s\".\n", szAlgNameLinear );
+            CPLprintf( "Options are "
+                    "\"radius=%f:nodata=%f\"\n",
+                ((GDALGridLinearOptions *)pOptions)->dfRadius,
+                ((GDALGridLinearOptions *)pOptions)->dfNoDataValue);
+            break;
+        default:
+            printf( "Algorithm is unknown.\n" );
+            break;
+    }
+}
+
+/************************************************************************/
+/*                          ProcessGeometry()                           */
+/*                                                                      */
+/*  Extract point coordinates from the geometry reference and set the   */
+/*  Z value as requested. Test whether we are in the clipped region     */
+/*  before processing.                                                  */
+/************************************************************************/
+
+static void ProcessGeometry( OGRPoint *poGeom, OGRGeometry *poClipSrc,
+                             int iBurnField, double dfBurnValue,
+                             const double dfIncreaseBurnValue,
+                             const double dfMultiplyBurnValue,
+                             std::vector<double> &adfX,
+                             std::vector<double> &adfY,
+                             std::vector<double> &adfZ )
+
+{
+    if ( poClipSrc && !poGeom->Within(poClipSrc) )
+        return;
+
+    adfX.push_back( poGeom->getX() );
+    adfY.push_back( poGeom->getY() );
+    if ( iBurnField < 0 )
+        adfZ.push_back(  (poGeom->getZ() + dfIncreaseBurnValue) * dfMultiplyBurnValue  );
+    else
+        adfZ.push_back( (dfBurnValue + dfIncreaseBurnValue) * dfMultiplyBurnValue );
+}
+
+/************************************************************************/
+/*                       ProcessCommonGeometry()                        */
+/*                                                                      */
+/*  Process recursively geometry and extract points.                    */
+/************************************************************************/
+
+static void ProcessCommonGeometry(OGRGeometry* poGeom, OGRGeometry *poClipSrc,
+                                int iBurnField, double dfBurnValue,
+                                const double dfIncreaseBurnValue,
+                                const double dfMultiplyBurnValue,
+                                std::vector<double> &adfX,
+                                std::vector<double> &adfY,
+                                std::vector<double> &adfZ)
+{
+    if (NULL == poGeom)
+        return;
+
+    OGRwkbGeometryType eType = wkbFlatten(poGeom->getGeometryType());
+    switch (eType)
+    {
+    case wkbPoint:
+        return ProcessGeometry((OGRPoint *)poGeom, poClipSrc,
+            iBurnField, dfBurnValue, dfIncreaseBurnValue, dfMultiplyBurnValue, adfX, adfY, adfZ);
+    case wkbLinearRing:
+    case wkbLineString:
+        {
+            OGRLineString *poLS = (OGRLineString*)poGeom;
+            OGRPoint point;
+            for (int pointIndex = 0; pointIndex < poLS->getNumPoints(); pointIndex++)
+            {
+                poLS->getPoint(pointIndex, &point);
+                ProcessCommonGeometry((OGRGeometry*)&point, poClipSrc,
+                    iBurnField, dfBurnValue, dfIncreaseBurnValue, dfMultiplyBurnValue, adfX, adfY, adfZ);
+            }
+        }
+        break;
+    case wkbPolygon:
+        {
+            int nRings(0);
+            OGRPolygon* poPoly = (OGRPolygon*)poGeom;
+            OGRLinearRing* poRing = poPoly->getExteriorRing();
+            ProcessCommonGeometry((OGRGeometry*)poRing, poClipSrc,
+                iBurnField, dfBurnValue, dfIncreaseBurnValue, dfMultiplyBurnValue, adfX, adfY, adfZ);
+
+            nRings = poPoly->getNumInteriorRings();
+            if (nRings > 0)
+            {
+                for (int ir = 0; ir < nRings; ++ir)
+                {
+                    poRing = poPoly->getInteriorRing(ir);
+                    ProcessCommonGeometry((OGRGeometry*)poRing, poClipSrc,
+                        iBurnField, dfBurnValue, dfIncreaseBurnValue, dfMultiplyBurnValue, adfX, adfY, adfZ);
+                }
+            }
+        }
+        break;
+    case wkbMultiPoint:
+    case wkbMultiPolygon:
+    case wkbMultiLineString:
+    case wkbGeometryCollection:
+        {
+            OGRGeometryCollection* pOGRGeometryCollection = (OGRGeometryCollection*)poGeom;
+            for (int i = 0; i < pOGRGeometryCollection->getNumGeometries(); ++i)
+            {
+                ProcessCommonGeometry(pOGRGeometryCollection->getGeometryRef(i), poClipSrc,
+                    iBurnField, dfBurnValue, dfIncreaseBurnValue, dfMultiplyBurnValue, adfX, adfY, adfZ);
+            }
+        }
+        break;
+    case wkbUnknown:
+    case wkbNone:
+    default:
+        break;
+    }
+}
+
+/************************************************************************/
+/*                            ProcessLayer()                            */
+/*                                                                      */
+/*      Process all the features in a layer selection, collecting       */
+/*      geometries and burn values.                                     */
+/************************************************************************/
+
+static CPLErr ProcessLayer( OGRLayerH hSrcLayer, GDALDatasetH hDstDS,
+                          OGRGeometry *poClipSrc,
+                          int nXSize, int nYSize, int nBand,
+                          int& bIsXExtentSet, int& bIsYExtentSet,
+                          double& dfXMin, double& dfXMax,
+                          double& dfYMin, double& dfYMax,
+                          const char *pszBurnAttribute,
+                          const double dfIncreaseBurnValue,
+                          const double dfMultiplyBurnValue,
+                          GDALDataType eType,
+                          GDALGridAlgorithm eAlgorithm, void *pOptions,
+                          int bQuiet, GDALProgressFunc pfnProgress, void* pProgressData )
+
+{
+/* -------------------------------------------------------------------- */
+/*      Get field index, and check.                                     */
+/* -------------------------------------------------------------------- */
+    int iBurnField = -1;
+
+    if ( pszBurnAttribute )
+    {
+        iBurnField = OGR_FD_GetFieldIndex( OGR_L_GetLayerDefn( hSrcLayer ),
+                                           pszBurnAttribute );
+        if( iBurnField == -1 )
+        {
+            printf( "Failed to find field %s on layer %s, skipping.\n",
+                    pszBurnAttribute,
+                    OGR_FD_GetName( OGR_L_GetLayerDefn( hSrcLayer ) ) );
+            return CE_Failure;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Collect the geometries from this layer, and build list of       */
+/*      values to be interpolated.                                      */
+/* -------------------------------------------------------------------- */
+    OGRFeature *poFeat;
+    std::vector<double> adfX, adfY, adfZ;
+
+    OGR_L_ResetReading( hSrcLayer );
+
+    while( (poFeat = (OGRFeature *)OGR_L_GetNextFeature( hSrcLayer )) != NULL )
+    {
+        OGRGeometry *poGeom = poFeat->GetGeometryRef();
+        double  dfBurnValue = 0.0;
+
+        if ( iBurnField >= 0 )
+            dfBurnValue = poFeat->GetFieldAsDouble( iBurnField );
+
+        ProcessCommonGeometry(poGeom, poClipSrc, iBurnField, dfBurnValue,
+            dfIncreaseBurnValue, dfMultiplyBurnValue, adfX, adfY, adfZ);
+
+        OGRFeature::DestroyFeature( poFeat );
+    }
+
+    if ( adfX.size() == 0 )
+    {
+        printf( "No point geometry found on layer %s, skipping.\n",
+                OGR_FD_GetName( OGR_L_GetLayerDefn( hSrcLayer ) ) );
+        return CE_None;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Compute grid geometry.                                          */
+/* -------------------------------------------------------------------- */
+    if ( !bIsXExtentSet || !bIsYExtentSet )
+    {
+        OGREnvelope sEnvelope;
+        OGR_L_GetExtent( hSrcLayer, &sEnvelope, TRUE );
+
+        if ( !bIsXExtentSet )
+        {
+            dfXMin = sEnvelope.MinX;
+            dfXMax = sEnvelope.MaxX;
+            bIsXExtentSet = TRUE;
+        }
+
+        if ( !bIsYExtentSet )
+        {
+            dfYMin = sEnvelope.MinY;
+            dfYMax = sEnvelope.MaxY;
+            bIsYExtentSet = TRUE;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Perform gridding.                                               */
+/* -------------------------------------------------------------------- */
+
+    const double    dfDeltaX = ( dfXMax - dfXMin ) / nXSize;
+    const double    dfDeltaY = ( dfYMax - dfYMin ) / nYSize;
+
+    if ( !bQuiet )
+    {
+        printf( "Grid data type is \"%s\"\n", GDALGetDataTypeName(eType) );
+        printf( "Grid size = (%lu %lu).\n",
+                (unsigned long)nXSize, (unsigned long)nYSize );
+        CPLprintf( "Corner coordinates = (%f %f)-(%f %f).\n",
+                dfXMin - dfDeltaX / 2, dfYMax + dfDeltaY / 2,
+                dfXMax + dfDeltaX / 2, dfYMin - dfDeltaY / 2 );
+        CPLprintf( "Grid cell size = (%f %f).\n", dfDeltaX, dfDeltaY );
+        printf( "Source point count = %lu.\n", (unsigned long)adfX.size() );
+        PrintAlgorithmAndOptions( eAlgorithm, pOptions );
+        printf("\n");
+    }
+
+    GDALRasterBandH hBand = GDALGetRasterBand( hDstDS, nBand );
+
+    if (adfX.size() == 0)
+    {
+        // FIXME: Should have set to nodata value instead
+        GDALFillRaster( hBand, 0.0 , 0.0 );
+        return CE_None;
+    }
+
+    int     nXOffset, nYOffset;
+    int     nBlockXSize, nBlockYSize;
+    const int nDataTypeSize = GDALGetDataTypeSizeBytes(eType);
+
+    // Try to grow the work buffer up to 16 MB if it is smaller
+    GDALGetBlockSize( hBand, &nBlockXSize, &nBlockYSize );
+    const int nDesiredBufferSize = 16*1024*1024;
+    if( nBlockXSize < nXSize && nBlockYSize < nYSize &&
+        nBlockXSize < nDesiredBufferSize / (nBlockYSize * nDataTypeSize) )
+    {
+        int nNewBlockXSize  = nDesiredBufferSize / (nBlockYSize * nDataTypeSize);
+        nBlockXSize = (nNewBlockXSize / nBlockXSize) * nBlockXSize;
+        if( nBlockXSize > nXSize )
+            nBlockXSize = nXSize;
+    }
+    else if( nBlockXSize == nXSize && nBlockYSize < nYSize &&
+             nBlockYSize < nDesiredBufferSize / (nXSize * nDataTypeSize) )
+    {
+        int nNewBlockYSize = nDesiredBufferSize / (nXSize * nDataTypeSize);
+        nBlockYSize = (nNewBlockYSize / nBlockYSize) * nBlockYSize;
+        if( nBlockYSize > nYSize )
+            nBlockYSize = nYSize;
+    }
+    CPLDebug("GDAL_GRID", "Work buffer: %d * %d", nBlockXSize, nBlockYSize);
+
+    void    *pData =
+        VSIMalloc3( nBlockXSize, nBlockYSize, nDataTypeSize );
+    if( pData == NULL )
+    {
+        CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate work buffer");
+        return CE_Failure;
+    }
+
+    int nBlock = 0;
+    int nBlockCount = ((nXSize + nBlockXSize - 1) / nBlockXSize)
+        * ((nYSize + nBlockYSize - 1) / nBlockYSize);
+
+    GDALGridContext* psContext = GDALGridContextCreate( eAlgorithm, pOptions,
+                                                        static_cast<int>(adfX.size()),
+                                                        &(adfX[0]), &(adfY[0]), &(adfZ[0]),
+                                                        TRUE );
+    if( psContext == NULL )
+    {
+        CPLFree( pData );
+        return CE_Failure;
+    }
+
+    CPLErr eErr = CE_None;
+    for ( nYOffset = 0; nYOffset < nYSize && eErr == CE_None; nYOffset += nBlockYSize )
+    {
+        for ( nXOffset = 0; nXOffset < nXSize && eErr == CE_None; nXOffset += nBlockXSize )
+        {
+            void *pScaledProgress;
+            pScaledProgress =
+                GDALCreateScaledProgress( (double)nBlock / nBlockCount,
+                                          (double)(nBlock + 1) / nBlockCount,
+                                          pfnProgress, pProgressData );
+            nBlock ++;
+
+            int nXRequest = nBlockXSize;
+            if (nXOffset + nXRequest > nXSize)
+                nXRequest = nXSize - nXOffset;
+
+            int nYRequest = nBlockYSize;
+            if (nYOffset + nYRequest > nYSize)
+                nYRequest = nYSize - nYOffset;
+
+            eErr = GDALGridContextProcess( psContext,
+                            dfXMin + dfDeltaX * nXOffset,
+                            dfXMin + dfDeltaX * (nXOffset + nXRequest),
+                            dfYMin + dfDeltaY * nYOffset,
+                            dfYMin + dfDeltaY * (nYOffset + nYRequest),
+                            nXRequest, nYRequest, eType, pData,
+                            GDALScaledProgress, pScaledProgress );
+
+            if( eErr == CE_None )
+                eErr = GDALRasterIO( hBand, GF_Write, nXOffset, nYOffset,
+                          nXRequest, nYRequest, pData,
+                          nXRequest, nYRequest, eType, 0, 0 );
+
+            GDALDestroyScaledProgress( pScaledProgress );
+        }
+    }
+
+    GDALGridContextFree(psContext);
+
+    CPLFree( pData );
+    return eErr;
+}
+
+/************************************************************************/
+/*                            LoadGeometry()                            */
+/*                                                                      */
+/*  Read geometries from the given dataset using specified filters and  */
+/*  returns a collection of read geometries.                            */
+/************************************************************************/
+
+static OGRGeometryCollection* LoadGeometry( const char* pszDS,
+                                            const char* pszSQL,
+                                            const char* pszLyr,
+                                            const char* pszWhere )
+{
+    GDALDataset         *poDS;
+    OGRLayer            *poLyr;
+    OGRFeature          *poFeat;
+    OGRGeometryCollection *poGeom = NULL;
+
+    poDS = (GDALDataset*) GDALOpen( pszDS, GA_ReadOnly );
+    if ( poDS == NULL )
+        return NULL;
+
+    if ( pszSQL != NULL )
+        poLyr = poDS->ExecuteSQL( pszSQL, NULL, NULL );
+    else if ( pszLyr != NULL )
+        poLyr = poDS->GetLayerByName( pszLyr );
+    else
+        poLyr = poDS->GetLayer(0);
+
+    if ( poLyr == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Failed to identify source layer from datasource." );
+        GDALClose( (GDALDatasetH) poDS );
+        return NULL;
+    }
+
+    if ( pszWhere )
+        poLyr->SetAttributeFilter( pszWhere );
+
+    while ( (poFeat = poLyr->GetNextFeature()) != NULL )
+    {
+        OGRGeometry* poSrcGeom = poFeat->GetGeometryRef();
+        if ( poSrcGeom )
+        {
+            OGRwkbGeometryType eType =
+                wkbFlatten( poSrcGeom->getGeometryType() );
+
+            if ( poGeom == NULL )
+                poGeom = new OGRMultiPolygon();
+
+            if ( eType == wkbPolygon )
+                poGeom->addGeometry( poSrcGeom );
+            else if ( eType == wkbMultiPolygon )
+            {
+                int iGeom;
+                int nGeomCount =
+                    ((OGRMultiPolygon *)poSrcGeom)->getNumGeometries();
+
+                for ( iGeom = 0; iGeom < nGeomCount; iGeom++ )
+                {
+                    poGeom->addGeometry(
+                        ((OGRMultiPolygon *)poSrcGeom)->getGeometryRef(iGeom) );
+                }
+            }
+            else
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "Geometry not of polygon type." );
+                OGRGeometryFactory::destroyGeometry( poGeom );
+                OGRFeature::DestroyFeature( poFeat );
+                if ( pszSQL != NULL )
+                    poDS->ReleaseResultSet( poLyr );
+                GDALClose( (GDALDatasetH) poDS );
+                return NULL;
+            }
+        }
+
+        OGRFeature::DestroyFeature( poFeat );
+    }
+
+    if( pszSQL != NULL )
+        poDS->ReleaseResultSet( poLyr );
+    GDALClose( (GDALDatasetH) poDS );
+
+    return poGeom;
+}
+
+/************************************************************************/
+/*                               GDALGrid()                             */
+/************************************************************************/
+
+/**
+ * Create raster from the scattered data.
+ *
+ * This is the equivalent of the <a href="gdal_grid.html">gdal_grid</a> utility.
+ *
+ * GDALGridOptions* must be allocated and freed with GDALGridOptionsNew()
+ * and GDALGridOptionsFree() respectively.
+ *
+ * @param pszDest the destination dataset path.
+ * @param hSrcDataset the source dataset handle.
+ * @param psOptionsIn the options struct returned by GDALGridOptionsNew() or NULL.
+ * @param pbUsageError the pointer to int variable to determine any usage error has occurred or NULL.
+ * @return the output dataset (new dataset that must be closed using GDALClose()) or NULL in case of error.
+ *
+ * @since GDAL 2.1
+ */
+
+GDALDatasetH GDALGrid( const char *pszDest, GDALDatasetH hSrcDataset,
+                       const GDALGridOptions *psOptionsIn, int *pbUsageError )
+
+{
+    if( hSrcDataset == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "No source dataset specified.");
+
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        return NULL;
+    }
+    if( pszDest == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "No target dataset specified.");
+
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        return NULL;
+    }
+
+    GDALGridOptions* psOptionsToFree = NULL;
+    const GDALGridOptions* psOptions;
+    if( psOptionsIn )
+        psOptions = psOptionsIn;
+    else
+    {
+        psOptionsToFree = GDALGridOptionsNew(NULL, NULL);
+        psOptions = psOptionsToFree;
+    }
+
+    GDALDataset* poSrcDS = (GDALDataset*) hSrcDataset;
+
+    if( psOptions->pszSQL == NULL && psOptions->papszLayers == NULL &&
+        poSrcDS->GetLayerCount() != 1 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Neither -sql nor -l are specified, but the source dataset has not one single layer.");
+        if( pbUsageError )
+            *pbUsageError = TRUE;
+        GDALGridOptionsFree(psOptionsToFree);
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Find the output driver.                                         */
+/* -------------------------------------------------------------------- */
+    GDALDriverH hDriver = GDALGetDriverByName( psOptions->pszFormat );
+    if( hDriver == NULL )
+    {
+        int iDr;
+
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Output driver `%s' not recognised.", psOptions->pszFormat );
+        fprintf( stderr,
+        "The following format drivers are configured and support output:\n" );
+        for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
+        {
+            hDriver = GDALGetDriver(iDr);
+
+            if( GDALGetMetadataItem( hDriver, GDAL_DCAP_RASTER, NULL) != NULL &&
+                ( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) != NULL
+                || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY, NULL ) != NULL) )
+            {
+                fprintf( stderr, "  %s: %s\n",
+                         GDALGetDriverShortName( hDriver  ),
+                         GDALGetDriverLongName( hDriver ) );
+            }
+        }
+        printf( "\n" );
+        GDALGridOptionsFree(psOptionsToFree);
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create target raster file.                                      */
+/* -------------------------------------------------------------------- */
+    GDALDatasetH    hDstDS;
+    int             nLayerCount = CSLCount(psOptions->papszLayers);
+    if( nLayerCount == 0 && psOptions->pszSQL == NULL )
+        nLayerCount = 1; /* due to above check */
+    int             nBands = nLayerCount;
+
+    if ( psOptions->pszSQL )
+        nBands++;
+
+    // FIXME
+    int nXSize = psOptions->nXSize;
+    if ( nXSize == 0 )
+        nXSize = 256;
+    int nYSize = psOptions->nYSize;
+    if ( nYSize == 0 )
+        nYSize = 256;
+
+    hDstDS = GDALCreate( hDriver, pszDest, nXSize, nYSize, nBands,
+                         psOptions->eOutputType, psOptions->papszCreateOptions );
+    if ( hDstDS == NULL )
+    {
+        GDALGridOptionsFree(psOptionsToFree);
+        return NULL;
+    }
+
+    if( psOptions->bNoDataSet )
+    {
+        for( int i = 1; i <= nBands; i++ )
+        {
+            GDALRasterBandH hBand = GDALGetRasterBand( hDstDS, i );
+            GDALSetRasterNoDataValue( hBand, psOptions->dfNoDataValue );
+        }
+    }
+
+    double dfXMin = psOptions->dfXMin;
+    double dfYMin = psOptions->dfYMin;
+    double dfXMax = psOptions->dfXMax;
+    double dfYMax = psOptions->dfYMax;
+    int bIsXExtentSet = psOptions->bIsXExtentSet;
+    int bIsYExtentSet = psOptions->bIsYExtentSet;
+    CPLErr eErr = CE_None;
+
+/* -------------------------------------------------------------------- */
+/*      Process SQL request.                                            */
+/* -------------------------------------------------------------------- */
+
+    if( psOptions->pszSQL != NULL )
+    {
+        OGRLayer* poLayer = poSrcDS->ExecuteSQL(psOptions->pszSQL,
+                                                psOptions->poSpatialFilter, NULL );
+        if( poLayer != NULL )
+        {
+            // Custom layer will be rasterized in the first band.
+            eErr = ProcessLayer( (OGRLayerH)poLayer, hDstDS, psOptions->poSpatialFilter,
+                          nXSize, nYSize, 1,
+                          bIsXExtentSet, bIsYExtentSet,
+                          dfXMin, dfXMax, dfYMin, dfYMax, psOptions->pszBurnAttribute,
+                          psOptions->dfIncreaseBurnValue, psOptions->dfMultiplyBurnValue,
+                          psOptions->eOutputType, psOptions->eAlgorithm, psOptions->pOptions,
+                          psOptions->bQuiet, psOptions->pfnProgress, psOptions->pProgressData );
+
+            poSrcDS->ReleaseResultSet(poLayer);
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Process each layer.                                             */
+/* -------------------------------------------------------------------- */
+    char* pszOutputSRS = ( psOptions->pszOutputSRS ) ? CPLStrdup(psOptions->pszOutputSRS) : NULL;
+    for( int i = 0; i < nLayerCount; i++ )
+    {
+        OGRLayerH hLayer = ( psOptions->papszLayers == NULL ) ?
+            GDALDatasetGetLayer(hSrcDataset, 0) :
+            GDALDatasetGetLayerByName( hSrcDataset, psOptions->papszLayers[i]);
+        if( hLayer == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Unable to find layer \"%s\", skipping.",
+                     psOptions->papszLayers[i] ? psOptions->papszLayers[i] : "null" );
+            continue;
+        }
+
+        if( psOptions->pszWHERE )
+        {
+            if( OGR_L_SetAttributeFilter( hLayer, psOptions->pszWHERE ) != OGRERR_NONE )
+                break;
+        }
+
+        if ( psOptions->poSpatialFilter != NULL )
+            OGR_L_SetSpatialFilter( hLayer, (OGRGeometryH)psOptions->poSpatialFilter );
+
+        // Fetch the first meaningful SRS definition
+        if ( !pszOutputSRS )
+        {
+            OGRSpatialReferenceH hSRS = OGR_L_GetSpatialRef( hLayer );
+            if ( hSRS )
+                OSRExportToWkt( hSRS, &pszOutputSRS );
+        }
+
+        eErr = ProcessLayer( hLayer, hDstDS, psOptions->poSpatialFilter, nXSize, nYSize,
+                      i + 1 + nBands - nLayerCount,
+                      bIsXExtentSet, bIsYExtentSet,
+                      dfXMin, dfXMax, dfYMin, dfYMax, psOptions->pszBurnAttribute,
+                      psOptions->dfIncreaseBurnValue, psOptions->dfMultiplyBurnValue,
+                      psOptions->eOutputType, psOptions->eAlgorithm, psOptions->pOptions,
+                      psOptions->bQuiet, psOptions->pfnProgress, psOptions->pProgressData );
+        if( eErr != CE_None )
+            break;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Apply geotransformation matrix.                                 */
+/* -------------------------------------------------------------------- */
+    double  adfGeoTransform[6];
+    adfGeoTransform[0] = dfXMin;
+    adfGeoTransform[1] = (dfXMax - dfXMin) / nXSize;
+    adfGeoTransform[2] = 0.0;
+    adfGeoTransform[3] = dfYMin;
+    adfGeoTransform[4] = 0.0;
+    adfGeoTransform[5] = (dfYMax - dfYMin) / nYSize;
+    GDALSetGeoTransform( hDstDS, adfGeoTransform );
+
+/* -------------------------------------------------------------------- */
+/*      Apply SRS definition if set.                                    */
+/* -------------------------------------------------------------------- */
+    if ( pszOutputSRS )
+    {
+        GDALSetProjection( hDstDS, pszOutputSRS );
+        CPLFree(pszOutputSRS);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      End                                                             */
+/* -------------------------------------------------------------------- */
+    GDALGridOptionsFree(psOptionsToFree);
+
+    if( eErr == CE_None )
+        return hDstDS;
+    else
+    {
+        GDALClose(hDstDS);
+        return NULL;
+    }
+}
+
+/************************************************************************/
+/*                            IsNumber()                               */
+/************************************************************************/
+
+static int IsNumber(const char* pszStr)
+{
+    if (*pszStr == '-' || *pszStr == '+')
+        pszStr ++;
+    if (*pszStr == '.')
+        pszStr ++;
+    return (*pszStr >= '0' && *pszStr <= '9');
+}
+
+/************************************************************************/
+/*                             GDALGridOptionsNew()                     */
+/************************************************************************/
+
+/**
+ * Allocates a GDALGridOptions struct.
+ *
+ * @param papszArgv NULL terminated list of options (potentially including filename and open options too), or NULL.
+ *                  The accepted options are the ones of the <a href="gdal_translate.html">gdal_translate</a> utility.
+ * @param psOptionsForBinary (output) may be NULL (and should generally be NULL),
+ *                           otherwise (gdal_translate_bin.cpp use case) must be allocated with
+ *                           GDALGridOptionsForBinaryNew() prior to this function. Will be
+ *                           filled with potentially present filename, open options,...
+ * @return pointer to the allocated GDALGridOptions struct. Must be freed with GDALGridOptionsFree().
+ *
+ * @since GDAL 2.1
+ */
+
+GDALGridOptions *GDALGridOptionsNew(char** papszArgv, GDALGridOptionsForBinary* psOptionsForBinary)
+{
+    GDALGridOptions *psOptions = (GDALGridOptions *) CPLCalloc( 1, sizeof(GDALGridOptions) );
+
+    psOptions->pszFormat = CPLStrdup("GTiff");
+    psOptions->bQuiet = TRUE;
+    psOptions->pfnProgress = GDALDummyProgress;
+    psOptions->pProgressData = NULL;
+    psOptions->papszLayers = NULL;
+    psOptions->pszBurnAttribute = NULL;
+    psOptions->dfIncreaseBurnValue = 0.0;
+    psOptions->dfMultiplyBurnValue = 1.0;
+    psOptions->pszWHERE = NULL;
+    psOptions->pszSQL = NULL;
+    psOptions->eOutputType = GDT_Float64;
+    psOptions->papszCreateOptions = NULL;
+    psOptions->nXSize = 0;
+    psOptions->nYSize = 0;
+    psOptions->dfXMin = 0.0;
+    psOptions->dfXMax = 0.0;
+    psOptions->dfYMin = 0.0;
+    psOptions->dfYMax = 0.0;
+    psOptions->bIsXExtentSet = FALSE;
+    psOptions->bIsYExtentSet = FALSE;
+    psOptions->eAlgorithm = GGA_InverseDistanceToAPower;
+    psOptions->pOptions = NULL;
+    psOptions->pszOutputSRS = NULL;
+    psOptions->poSpatialFilter = NULL;
+    psOptions->poClipSrc = NULL;
+    psOptions->bClipSrc = FALSE;
+    psOptions->pszClipSrcDS = NULL;
+    psOptions->pszClipSrcSQL = NULL;
+    psOptions->pszClipSrcLayer = NULL;
+    psOptions->pszClipSrcWhere = NULL;
+    psOptions->bNoDataSet = FALSE;
+    psOptions->dfNoDataValue = 0;
+
+    ParseAlgorithmAndOptions( szAlgNameInvDist, &psOptions->eAlgorithm, &psOptions->pOptions );
+
+    bool bGotSourceFilename = false;
+    bool bGotDestFilename = false;
+/* -------------------------------------------------------------------- */
+/*      Handle command line arguments.                                  */
+/* -------------------------------------------------------------------- */
+    int argc = CSLCount(papszArgv);
+    for( int i = 0; i < argc; i++ )
+    {
+        if( EQUAL(papszArgv[i],"-of") && i < argc-1 )
+        {
+            ++i;
+            CPLFree(psOptions->pszFormat);
+            psOptions->pszFormat = CPLStrdup(papszArgv[i]);
+            if( psOptionsForBinary )
+            {
+                psOptionsForBinary->bFormatExplicitlySet = TRUE;
+            }
+        }
+
+        else if( EQUAL(papszArgv[i],"-q") || EQUAL(papszArgv[i],"-quiet") )
+        {
+            if( psOptionsForBinary )
+                psOptionsForBinary->bQuiet = TRUE;
+        }
+
+        else if( EQUAL(papszArgv[i],"-ot") && papszArgv[i+1] )
+        {
+            int iType;
+
+            for( iType = 1; iType < GDT_TypeCount; iType++ )
+            {
+                if( GDALGetDataTypeName((GDALDataType)iType) != NULL
+                    && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
+                             papszArgv[i+1]) )
+                {
+                    psOptions->eOutputType = (GDALDataType) iType;
+                }
+            }
+
+            if( psOptions->eOutputType == GDT_Unknown )
+            {
+                CPLError(CE_Failure, CPLE_NotSupported,
+                         "Unknown output pixel type: %s.", papszArgv[i+1] );
+                GDALGridOptionsFree(psOptions);
+                return NULL;
+            }
+            i++;
+        }
+
+        else if( EQUAL(papszArgv[i],"-txe") && i+2 < argc )
+        {
+            psOptions->dfXMin = CPLAtof(papszArgv[++i]);
+            psOptions->dfXMax = CPLAtof(papszArgv[++i]);
+            psOptions->bIsXExtentSet = TRUE;
+        }
+
+        else if( EQUAL(papszArgv[i],"-tye") && i+2 < argc )
+        {
+            psOptions->dfYMin = CPLAtof(papszArgv[++i]);
+            psOptions->dfYMax = CPLAtof(papszArgv[++i]);
+            psOptions->bIsYExtentSet = TRUE;
+        }
+
+        else if( EQUAL(papszArgv[i],"-outsize") && i+2 < argc )
+        {
+            psOptions->nXSize = atoi(papszArgv[++i]);
+            psOptions->nYSize = atoi(papszArgv[++i]);
+        }
+
+        else if( EQUAL(papszArgv[i],"-co") && i+1 < argc )
+        {
+            psOptions->papszCreateOptions = CSLAddString( psOptions->papszCreateOptions, papszArgv[++i] );
+        }
+
+        else if( EQUAL(papszArgv[i],"-zfield") && i+1 < argc )
+        {
+            CPLFree(psOptions->pszBurnAttribute);
+            psOptions->pszBurnAttribute = CPLStrdup(papszArgv[++i]);
+        }
+
+        else if( EQUAL(papszArgv[i],"-z_increase") && i+1 < argc )
+        {
+            psOptions->dfIncreaseBurnValue = CPLAtof(papszArgv[++i]);
+        }
+
+        else if( EQUAL(papszArgv[i],"-z_multiply") && i+1 < argc )
+        {
+            psOptions->dfMultiplyBurnValue = CPLAtof(papszArgv[++i]);
+        }
+
+        else if( EQUAL(papszArgv[i],"-where") && i+1 < argc )
+        {
+            CPLFree(psOptions->pszWHERE);
+            psOptions->pszWHERE = CPLStrdup(papszArgv[++i]);
+        }
+
+        else if( EQUAL(papszArgv[i],"-l") && i+1 < argc )
+        {
+            psOptions->papszLayers = CSLAddString( psOptions->papszLayers, papszArgv[++i] );
+        }
+
+        else if( EQUAL(papszArgv[i],"-sql") && i+1 < argc )
+        {
+            CPLFree(psOptions->pszSQL);
+            psOptions->pszSQL = CPLStrdup(papszArgv[++i]);
+        }
+
+        else if( EQUAL(papszArgv[i],"-spat") && i+4 < argc )
+        {
+            OGRLinearRing  oRing;
+
+            oRing.addPoint( CPLAtof(papszArgv[i+1]), CPLAtof(papszArgv[i+2]) );
+            oRing.addPoint( CPLAtof(papszArgv[i+1]), CPLAtof(papszArgv[i+4]) );
+            oRing.addPoint( CPLAtof(papszArgv[i+3]), CPLAtof(papszArgv[i+4]) );
+            oRing.addPoint( CPLAtof(papszArgv[i+3]), CPLAtof(papszArgv[i+2]) );
+            oRing.addPoint( CPLAtof(papszArgv[i+1]), CPLAtof(papszArgv[i+2]) );
+
+            delete psOptions->poSpatialFilter;
+            psOptions->poSpatialFilter = new OGRPolygon();
+            ((OGRPolygon *) psOptions->poSpatialFilter)->addRing( &oRing );
+            i += 4;
+        }
+
+        else if( EQUAL(papszArgv[i],"-clipsrc") )
+        {
+            if (i + 1 >= argc)
+            {
+                CPLError(CE_Failure, CPLE_IllegalArg, "%s option requires 1 or 4 arguments", papszArgv[i]);
+                GDALGridOptionsFree(psOptions);
+                return NULL;
+            }
+
+            VSIStatBufL  sStat;
+            psOptions->bClipSrc = TRUE;
+            if ( IsNumber(papszArgv[i+1])
+                 && papszArgv[i+2] != NULL
+                 && papszArgv[i+3] != NULL
+                 && papszArgv[i+4] != NULL)
+            {
+                OGRLinearRing  oRing;
+
+                oRing.addPoint( CPLAtof(papszArgv[i+1]), CPLAtof(papszArgv[i+2]) );
+                oRing.addPoint( CPLAtof(papszArgv[i+1]), CPLAtof(papszArgv[i+4]) );
+                oRing.addPoint( CPLAtof(papszArgv[i+3]), CPLAtof(papszArgv[i+4]) );
+                oRing.addPoint( CPLAtof(papszArgv[i+3]), CPLAtof(papszArgv[i+2]) );
+                oRing.addPoint( CPLAtof(papszArgv[i+1]), CPLAtof(papszArgv[i+2]) );
+
+                delete psOptions->poClipSrc;
+                psOptions->poClipSrc = OGRGeometryFactory::createGeometry(wkbPolygon);
+                ((OGRPolygon *) psOptions->poClipSrc)->addRing( &oRing );
+                i += 4;
+            }
+            else if ((STARTS_WITH_CI(papszArgv[i+1], "POLYGON") ||
+                      STARTS_WITH_CI(papszArgv[i+1], "MULTIPOLYGON")) &&
+                      VSIStatL(papszArgv[i+1], &sStat) != 0)
+            {
+                char* pszTmp = (char*) papszArgv[i+1];
+                delete psOptions->poClipSrc;
+                OGRGeometryFactory::createFromWkt(&pszTmp, NULL, &psOptions->poClipSrc);
+                if (psOptions->poClipSrc == NULL)
+                {
+                    CPLError(CE_Failure, CPLE_IllegalArg,
+                             "Invalid geometry. Must be a valid POLYGON or MULTIPOLYGON WKT");
+                    GDALGridOptionsFree(psOptions);
+                    return NULL;
+                }
+                i ++;
+            }
+            else if (EQUAL(papszArgv[i+1], "spat_extent") )
+            {
+                i ++;
+            }
+            else
+            {
+                CPLFree(psOptions->pszClipSrcDS);
+                psOptions->pszClipSrcDS = CPLStrdup(papszArgv[i+1]);
+                i ++;
+            }
+        }
+        else if( EQUAL(papszArgv[i],"-clipsrcsql") && i+1 < argc )
+        {
+            CPLFree(psOptions->pszClipSrcSQL);
+            psOptions->pszClipSrcSQL = CPLStrdup(papszArgv[i+1]);
+            i ++;
+        }
+        else if( EQUAL(papszArgv[i],"-clipsrclayer") && i+1 < argc )
+        {
+            CPLFree(psOptions->pszClipSrcLayer);
+            psOptions->pszClipSrcLayer = CPLStrdup(papszArgv[i+1]);
+            i ++;
+        }
+        else if( EQUAL(papszArgv[i],"-clipsrcwhere") && i+1 < argc )
+        {
+            CPLFree(psOptions->pszClipSrcWhere);
+            psOptions->pszClipSrcWhere = CPLStrdup(papszArgv[i+1]);
+            i ++;
+        }
+
+        else if( EQUAL(papszArgv[i],"-a_srs") && i+1 < argc )
+        {
+            OGRSpatialReference oOutputSRS;
+
+            if( oOutputSRS.SetFromUserInput( papszArgv[i+1] ) != OGRERR_NONE )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Failed to process SRS definition: %s",
+                         papszArgv[i+1] );
+                GDALGridOptionsFree(psOptions);
+                return NULL;
+            }
+
+            CPLFree(psOptions->pszOutputSRS);
+            oOutputSRS.exportToWkt( &(psOptions->pszOutputSRS) );
+            i++;
+        }
+
+        else if( EQUAL(papszArgv[i],"-a") && i+1 < argc )
+        {
+            const char* pszAlgorithm = papszArgv[++i];
+            CPLFree(psOptions->pOptions);
+            if ( ParseAlgorithmAndOptions( pszAlgorithm, &psOptions->eAlgorithm, &psOptions->pOptions )
+                 != CE_None )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Failed to process algorithm name and parameters" );
+                GDALGridOptionsFree(psOptions);
+                return NULL;
+            }
+
+            char **papszParms = CSLTokenizeString2( pszAlgorithm, ":", FALSE );
+            const char* pszNoDataValue = CSLFetchNameValue( papszParms, "nodata" );
+            if( pszNoDataValue != NULL )
+            {
+                psOptions->bNoDataSet = TRUE;
+                psOptions->dfNoDataValue = CPLAtofM(pszNoDataValue);
+            }
+            CSLDestroy(papszParms);
+        }
+        else if( papszArgv[i][0] == '-' )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unknown option name '%s'", papszArgv[i]);
+            GDALGridOptionsFree(psOptions);
+            return NULL;
+        }
+        else if( !bGotSourceFilename )
+        {
+            bGotSourceFilename = true;
+            if( psOptionsForBinary )
+                psOptionsForBinary->pszSource = CPLStrdup(papszArgv[i]);
+        }
+        else if( !bGotDestFilename )
+        {
+            bGotDestFilename = true;
+            if( psOptionsForBinary )
+                psOptionsForBinary->pszDest = CPLStrdup(papszArgv[i]);
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Too many command options '%s'", papszArgv[i]);
+            GDALGridOptionsFree(psOptions);
+            return NULL;
+        }
+    }
+
+    if ( psOptions->bClipSrc && psOptions->pszClipSrcDS != NULL )
+    {
+        psOptions->poClipSrc = LoadGeometry( psOptions->pszClipSrcDS, psOptions->pszClipSrcSQL,
+                                  psOptions->pszClipSrcLayer, psOptions->pszClipSrcWhere );
+        if ( psOptions->poClipSrc == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Cannot load source clip geometry.");
+            GDALGridOptionsFree(psOptions);
+            return NULL;
+        }
+    }
+    else if ( psOptions->bClipSrc && psOptions->poClipSrc == NULL && !psOptions->poSpatialFilter )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "-clipsrc must be used with -spat option or \n"
+                 "a bounding box, WKT string or datasource must be "
+                 "specified.");
+        GDALGridOptionsFree(psOptions);
+        return NULL;
+    }
+
+    if ( psOptions->poSpatialFilter )
+    {
+        if ( psOptions->poClipSrc )
+        {
+            OGRGeometry *poTemp = psOptions->poSpatialFilter->Intersection( psOptions->poClipSrc );
+            if ( poTemp )
+            {
+                delete psOptions->poSpatialFilter;
+                psOptions->poSpatialFilter = poTemp;
+            }
+
+            delete psOptions->poClipSrc;
+            psOptions->poClipSrc = NULL;
+        }
+    }
+    else
+    {
+        if ( psOptions->poClipSrc )
+        {
+            psOptions->poSpatialFilter = psOptions->poClipSrc;
+            psOptions->poClipSrc = NULL;
+        }
+    }
+
+    if( psOptionsForBinary )
+    {
+        psOptionsForBinary->pszFormat = CPLStrdup(psOptions->pszFormat);
+    }
+
+    return psOptions;
+}
+
+/************************************************************************/
+/*                          GDALGridOptionsFree()                       */
+/************************************************************************/
+
+/**
+ * Frees the GDALGridOptions struct.
+ *
+ * @param psOptions the options struct for GDALGrid().
+ *
+ * @since GDAL 2.1
+ */
+
+void GDALGridOptionsFree(GDALGridOptions *psOptions)
+{
+    if( psOptions )
+    {
+        CPLFree(psOptions->pszFormat);
+        CSLDestroy(psOptions->papszLayers);
+        CPLFree(psOptions->pszBurnAttribute);
+        CPLFree(psOptions->pszWHERE);
+        CPLFree(psOptions->pszSQL);
+        CSLDestroy(psOptions->papszCreateOptions);
+        CPLFree(psOptions->pOptions);
+        CPLFree(psOptions->pszOutputSRS);
+        delete psOptions->poSpatialFilter;
+        delete psOptions->poClipSrc;
+        CPLFree(psOptions->pszClipSrcDS);
+        CPLFree(psOptions->pszClipSrcSQL);
+        CPLFree(psOptions->pszClipSrcLayer);
+        CPLFree(psOptions->pszClipSrcWhere);
+        CPLFree(psOptions);
+    }
+}
+
+/************************************************************************/
+/*                     GDALGridOptionsSetProgress()                     */
+/************************************************************************/
+
+/**
+ * Set a progress function.
+ *
+ * @param psOptions the options struct for GDALGrid().
+ * @param pfnProgress the progress callback.
+ * @param pProgressData the user data for the progress callback.
+ *
+ * @since GDAL 2.1
+ */
+
+void GDALGridOptionsSetProgress( GDALGridOptions *psOptions,
+                                      GDALProgressFunc pfnProgress, void *pProgressData )
+{
+    psOptions->pfnProgress = pfnProgress;
+    psOptions->pProgressData = pProgressData;
+    if( pfnProgress == GDALTermProgress )
+        psOptions->bQuiet = FALSE;
+}
diff --git a/apps/gdal_rasterize.cpp b/apps/gdal_rasterize.cpp
deleted file mode 100644
index b9c6515..0000000
--- a/apps/gdal_rasterize.cpp
+++ /dev/null
@@ -1,995 +0,0 @@
-/******************************************************************************
- * $Id: gdal_rasterize.cpp 28039 2014-11-30 18:24:59Z rouault $
- *
- * Project:  GDAL Utilities
- * Purpose:  Rasterize OGR shapes into a GDAL raster.
- * Author:   Frank Warmerdam <warmerdam at pobox.com>
- *
- ******************************************************************************
- * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
- * Copyright (c) 2008-2012, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "gdal.h"
-#include "gdal_alg.h"
-#include "cpl_conv.h"
-#include "ogr_api.h"
-#include "ogr_srs_api.h"
-#include "cpl_string.h"
-#include "commonutils.h"
-#include <vector>
-
-CPL_CVSID("$Id: gdal_rasterize.cpp 28039 2014-11-30 18:24:59Z rouault $");
-
-/************************************************************************/
-/*                            ArgIsNumeric()                            */
-/************************************************************************/
-
-static int ArgIsNumeric( const char *pszArg )
-
-{
-    return CPLGetValueType(pszArg) != CPL_VALUE_STRING;
-}
-
-/************************************************************************/
-/*                               Usage()                                */
-/************************************************************************/
-
-static void Usage()
-
-{
-    printf( 
-        "Usage: gdal_rasterize [-b band]* [-i] [-at]\n"
-        "       [-burn value]* | [-a attribute_name] [-3d] [-add]\n"
-        "       [-l layername]* [-where expression] [-sql select_statement]\n"
-        "       [-of format] [-a_srs srs_def] [-co \"NAME=VALUE\"]*\n"
-        "       [-a_nodata value] [-init value]*\n"
-        "       [-te xmin ymin xmax ymax] [-tr xres yres] [-tap] [-ts width height]\n"
-        "       [-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/\n"
-        "             CInt16/CInt32/CFloat32/CFloat64}] [-q]\n"
-        "       <src_datasource> <dst_filename>\n" );
-    exit( 1 );
-}
-
-/************************************************************************/
-/*                          InvertGeometries()                          */
-/************************************************************************/
-
-static void InvertGeometries( GDALDatasetH hDstDS, 
-                              std::vector<OGRGeometryH> &ahGeometries )
-
-{
-    OGRGeometryH hCollection = 
-        OGR_G_CreateGeometry( wkbGeometryCollection );
-
-/* -------------------------------------------------------------------- */
-/*      Create a ring that is a bit outside the raster dataset.         */
-/* -------------------------------------------------------------------- */
-    OGRGeometryH hUniversePoly, hUniverseRing;
-    double adfGeoTransform[6];
-    int brx = GDALGetRasterXSize( hDstDS ) + 2;
-    int bry = GDALGetRasterYSize( hDstDS ) + 2;
-
-    GDALGetGeoTransform( hDstDS, adfGeoTransform );
-
-    hUniverseRing = OGR_G_CreateGeometry( wkbLinearRing );
-    
-    OGR_G_AddPoint_2D( 
-        hUniverseRing, 
-        adfGeoTransform[0] + -2*adfGeoTransform[1] + -2*adfGeoTransform[2],
-        adfGeoTransform[3] + -2*adfGeoTransform[4] + -2*adfGeoTransform[5] );
-                       
-    OGR_G_AddPoint_2D( 
-        hUniverseRing, 
-        adfGeoTransform[0] + brx*adfGeoTransform[1] + -2*adfGeoTransform[2],
-        adfGeoTransform[3] + brx*adfGeoTransform[4] + -2*adfGeoTransform[5] );
-                       
-    OGR_G_AddPoint_2D( 
-        hUniverseRing, 
-        adfGeoTransform[0] + brx*adfGeoTransform[1] + bry*adfGeoTransform[2],
-        adfGeoTransform[3] + brx*adfGeoTransform[4] + bry*adfGeoTransform[5] );
-                       
-    OGR_G_AddPoint_2D( 
-        hUniverseRing, 
-        adfGeoTransform[0] + -2*adfGeoTransform[1] + bry*adfGeoTransform[2],
-        adfGeoTransform[3] + -2*adfGeoTransform[4] + bry*adfGeoTransform[5] );
-                       
-    OGR_G_AddPoint_2D( 
-        hUniverseRing, 
-        adfGeoTransform[0] + -2*adfGeoTransform[1] + -2*adfGeoTransform[2],
-        adfGeoTransform[3] + -2*adfGeoTransform[4] + -2*adfGeoTransform[5] );
-                       
-    hUniversePoly = OGR_G_CreateGeometry( wkbPolygon );
-    OGR_G_AddGeometryDirectly( hUniversePoly, hUniverseRing );
-
-    OGR_G_AddGeometryDirectly( hCollection, hUniversePoly );
-    
-/* -------------------------------------------------------------------- */
-/*      Add the rest of the geometries into our collection.             */
-/* -------------------------------------------------------------------- */
-    unsigned int iGeom;
-
-    for( iGeom = 0; iGeom < ahGeometries.size(); iGeom++ )
-        OGR_G_AddGeometryDirectly( hCollection, ahGeometries[iGeom] );
-
-    ahGeometries.resize(1);
-    ahGeometries[0] = hCollection;
-}
-
-/************************************************************************/
-/*                            ProcessLayer()                            */
-/*                                                                      */
-/*      Process all the features in a layer selection, collecting       */
-/*      geometries and burn values.                                     */
-/************************************************************************/
-
-static void ProcessLayer( 
-    OGRLayerH hSrcLayer, int bSRSIsSet, 
-    GDALDatasetH hDstDS, std::vector<int> anBandList,
-    std::vector<double> &adfBurnValues, int b3D, int bInverse,
-    const char *pszBurnAttribute, char **papszRasterizeOptions,
-    GDALProgressFunc pfnProgress, void* pProgressData )
-
-{
-/* -------------------------------------------------------------------- */
-/*      Checkout that SRS are the same.                                 */
-/*      If -a_srs is specified, skip the test                           */
-/* -------------------------------------------------------------------- */
-    if (!bSRSIsSet)
-    {
-        OGRSpatialReferenceH  hDstSRS = NULL;
-        if( GDALGetProjectionRef( hDstDS ) != NULL )
-        {
-            char *pszProjection;
-    
-            pszProjection = (char *) GDALGetProjectionRef( hDstDS );
-    
-            hDstSRS = OSRNewSpatialReference(NULL);
-            if( OSRImportFromWkt( hDstSRS, &pszProjection ) != CE_None )
-            {
-                OSRDestroySpatialReference(hDstSRS);
-                hDstSRS = NULL;
-            }
-        }
-    
-        OGRSpatialReferenceH hSrcSRS = OGR_L_GetSpatialRef(hSrcLayer);
-        if( hDstSRS != NULL && hSrcSRS != NULL )
-        {
-            if( OSRIsSame(hSrcSRS, hDstSRS) == FALSE )
-            {
-                fprintf(stderr,
-                        "Warning : the output raster dataset and the input vector layer do not have the same SRS.\n"
-                        "Results might be incorrect (no on-the-fly reprojection of input data).\n");
-            }
-        }
-        else if( hDstSRS != NULL && hSrcSRS == NULL )
-        {
-            fprintf(stderr,
-                    "Warning : the output raster dataset has a SRS, but the input vector layer SRS is unknown.\n"
-                    "Ensure input vector has the same SRS, otherwise results might be incorrect.\n");
-        }
-        else if( hDstSRS == NULL && hSrcSRS != NULL )
-        {
-            fprintf(stderr,
-                    "Warning : the input vector layer has a SRS, but the output raster dataset SRS is unknown.\n"
-                    "Ensure output raster dataset has the same SRS, otherwise results might be incorrect.\n");
-        }
-    
-        if( hDstSRS != NULL )
-        {
-            OSRDestroySpatialReference(hDstSRS);
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Get field index, and check.                                     */
-/* -------------------------------------------------------------------- */
-    int iBurnField = -1;
-
-    if( pszBurnAttribute )
-    {
-        iBurnField = OGR_FD_GetFieldIndex( OGR_L_GetLayerDefn( hSrcLayer ),
-                                           pszBurnAttribute );
-        if( iBurnField == -1 )
-        {
-            printf( "Failed to find field %s on layer %s, skipping.\n",
-                    pszBurnAttribute, 
-                    OGR_FD_GetName( OGR_L_GetLayerDefn( hSrcLayer ) ) );
-            return;
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Collect the geometries from this layer, and build list of       */
-/*      burn values.                                                    */
-/* -------------------------------------------------------------------- */
-    OGRFeatureH hFeat;
-    std::vector<OGRGeometryH> ahGeometries;
-    std::vector<double> adfFullBurnValues;
-
-    OGR_L_ResetReading( hSrcLayer );
-    
-    while( (hFeat = OGR_L_GetNextFeature( hSrcLayer )) != NULL )
-    {
-        OGRGeometryH hGeom;
-
-        if( OGR_F_GetGeometryRef( hFeat ) == NULL )
-        {
-            OGR_F_Destroy( hFeat );
-            continue;
-        }
-
-        hGeom = OGR_G_Clone( OGR_F_GetGeometryRef( hFeat ) );
-        ahGeometries.push_back( hGeom );
-
-        for( unsigned int iBand = 0; iBand < anBandList.size(); iBand++ )
-        {
-            if( adfBurnValues.size() > 0 )
-                adfFullBurnValues.push_back( 
-                    adfBurnValues[MIN(iBand,adfBurnValues.size()-1)] );
-            else if( pszBurnAttribute )
-            {
-                adfFullBurnValues.push_back( OGR_F_GetFieldAsDouble( hFeat, iBurnField ) );
-            }
-            /* I have made the 3D option exclusive to other options since it
-               can be used to modify the value from "-burn value" or
-               "-a attribute_name" */
-            if( b3D )
-            {
-                // TODO: get geometry "z" value
-                /* Points and Lines will have their "z" values collected at the
-                   point and line levels respectively. However filled polygons
-                   (GDALdllImageFilledPolygon) can use some help by getting
-                   their "z" values here. */
-                adfFullBurnValues.push_back( 0.0 );
-            }
-        }
-        
-        OGR_F_Destroy( hFeat );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      If we are in inverse mode, we add one extra ring around the     */
-/*      whole dataset to invert the concept of insideness and then      */
-/*      merge everything into one geometry collection.                  */
-/* -------------------------------------------------------------------- */
-    if( bInverse )
-    {
-        if( ahGeometries.size() == 0 )
-        {
-            for( unsigned int iBand = 0; iBand < anBandList.size(); iBand++ )
-            {
-                if( adfBurnValues.size() > 0 )
-                    adfFullBurnValues.push_back(
-                        adfBurnValues[MIN(iBand,adfBurnValues.size()-1)] );
-                else /* FIXME? Not sure what to do exactly in the else case, but we must insert a value */
-                    adfFullBurnValues.push_back( 0.0 );
-            }
-        }
-
-        InvertGeometries( hDstDS, ahGeometries );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Perform the burn.                                               */
-/* -------------------------------------------------------------------- */
-    GDALRasterizeGeometries( hDstDS, anBandList.size(), &(anBandList[0]), 
-                             ahGeometries.size(), &(ahGeometries[0]), 
-                             NULL, NULL, &(adfFullBurnValues[0]), 
-                             papszRasterizeOptions,
-                             pfnProgress, pProgressData );
-
-/* -------------------------------------------------------------------- */
-/*      Cleanup geometries.                                             */
-/* -------------------------------------------------------------------- */
-    int iGeom;
-
-    for( iGeom = ahGeometries.size()-1; iGeom >= 0; iGeom-- )
-        OGR_G_DestroyGeometry( ahGeometries[iGeom] );
-}
-
-/************************************************************************/
-/*                  CreateOutputDataset()                               */
-/************************************************************************/
-
-static
-GDALDatasetH CreateOutputDataset(std::vector<OGRLayerH> ahLayers,
-                                 OGRSpatialReferenceH hSRS,
-                                 int bGotBounds, OGREnvelope sEnvelop,
-                                 GDALDriverH hDriver, const char* pszDstFilename,
-                                 int nXSize, int nYSize, double dfXRes, double dfYRes,
-                                 int bTargetAlignedPixels,
-                                 int nBandCount, GDALDataType eOutputType,
-                                 char** papszCreateOptions, std::vector<double> adfInitVals,
-                                 int bNoDataSet, double dfNoData)
-{
-    int bFirstLayer = TRUE;
-    char* pszWKT = NULL;
-    GDALDatasetH hDstDS = NULL;
-    unsigned int i;
-
-    for( i = 0; i < ahLayers.size(); i++ )
-    {
-        OGRLayerH hLayer = ahLayers[i];
-
-        if (!bGotBounds)
-        {
-            OGREnvelope sLayerEnvelop;
-
-            if (OGR_L_GetExtent(hLayer, &sLayerEnvelop, TRUE) != OGRERR_NONE)
-            {
-                fprintf(stderr, "Cannot get layer extent\n");
-                exit(2);
-            }
-
-            /* When rasterizing point layers and that the bounds have */
-            /* not been explicitly set, voluntary increase the extent by */
-            /* a half-pixel size to avoid missing points on the border */
-            if (wkbFlatten(OGR_L_GetGeomType(hLayer)) == wkbPoint &&
-                !bTargetAlignedPixels && dfXRes != 0 && dfYRes != 0)
-            {
-                sLayerEnvelop.MinX -= dfXRes / 2;
-                sLayerEnvelop.MaxX += dfXRes / 2;
-                sLayerEnvelop.MinY -= dfYRes / 2;
-                sLayerEnvelop.MaxY += dfYRes / 2;
-            }
-
-            if (bFirstLayer)
-            {
-                sEnvelop.MinX = sLayerEnvelop.MinX;
-                sEnvelop.MinY = sLayerEnvelop.MinY;
-                sEnvelop.MaxX = sLayerEnvelop.MaxX;
-                sEnvelop.MaxY = sLayerEnvelop.MaxY;
-
-                if (hSRS == NULL)
-                    hSRS = OGR_L_GetSpatialRef(hLayer);
-
-                bFirstLayer = FALSE;
-            }
-            else
-            {
-                sEnvelop.MinX = MIN(sEnvelop.MinX, sLayerEnvelop.MinX);
-                sEnvelop.MinY = MIN(sEnvelop.MinY, sLayerEnvelop.MinY);
-                sEnvelop.MaxX = MAX(sEnvelop.MaxX, sLayerEnvelop.MaxX);
-                sEnvelop.MaxY = MAX(sEnvelop.MaxY, sLayerEnvelop.MaxY);
-            }
-        }
-        else
-        {
-            if (bFirstLayer)
-            {
-                if (hSRS == NULL)
-                    hSRS = OGR_L_GetSpatialRef(hLayer);
-
-                bFirstLayer = FALSE;
-            }
-        }
-    }
-
-    if (dfXRes == 0 && dfYRes == 0)
-    {
-        dfXRes = (sEnvelop.MaxX - sEnvelop.MinX) / nXSize;
-        dfYRes = (sEnvelop.MaxY - sEnvelop.MinY) / nYSize;
-    }
-    else if (bTargetAlignedPixels && dfXRes != 0 && dfYRes != 0)
-    {
-        sEnvelop.MinX = floor(sEnvelop.MinX / dfXRes) * dfXRes;
-        sEnvelop.MaxX = ceil(sEnvelop.MaxX / dfXRes) * dfXRes;
-        sEnvelop.MinY = floor(sEnvelop.MinY / dfYRes) * dfYRes;
-        sEnvelop.MaxY = ceil(sEnvelop.MaxY / dfYRes) * dfYRes;
-    }
-
-    double adfProjection[6];
-    adfProjection[0] = sEnvelop.MinX;
-    adfProjection[1] = dfXRes;
-    adfProjection[2] = 0;
-    adfProjection[3] = sEnvelop.MaxY;
-    adfProjection[4] = 0;
-    adfProjection[5] = -dfYRes;
-
-    if (nXSize == 0 && nYSize == 0)
-    {
-        nXSize = (int)(0.5 + (sEnvelop.MaxX - sEnvelop.MinX) / dfXRes);
-        nYSize = (int)(0.5 + (sEnvelop.MaxY - sEnvelop.MinY) / dfYRes);
-    }
-
-    hDstDS = GDALCreate(hDriver, pszDstFilename, nXSize, nYSize,
-                        nBandCount, eOutputType, papszCreateOptions);
-    if (hDstDS == NULL)
-    {
-        fprintf(stderr, "Cannot create %s\n", pszDstFilename);
-        exit(2);
-    }
-
-    GDALSetGeoTransform(hDstDS, adfProjection);
-
-    if (hSRS)
-        OSRExportToWkt(hSRS, &pszWKT);
-    if (pszWKT)
-        GDALSetProjection(hDstDS, pszWKT);
-    CPLFree(pszWKT);
-
-    int iBand;
-    /*if( nBandCount == 3 || nBandCount == 4 )
-    {
-        for(iBand = 0; iBand < nBandCount; iBand++)
-        {
-            GDALRasterBandH hBand = GDALGetRasterBand(hDstDS, iBand + 1);
-            GDALSetRasterColorInterpretation(hBand, (GDALColorInterp)(GCI_RedBand + iBand));
-        }
-    }*/
-
-    if (bNoDataSet)
-    {
-        for(iBand = 0; iBand < nBandCount; iBand++)
-        {
-            GDALRasterBandH hBand = GDALGetRasterBand(hDstDS, iBand + 1);
-            GDALSetRasterNoDataValue(hBand, dfNoData);
-        }
-    }
-
-    if (adfInitVals.size() != 0)
-    {
-        for(iBand = 0; iBand < MIN(nBandCount,(int)adfInitVals.size()); iBand++)
-        {
-            GDALRasterBandH hBand = GDALGetRasterBand(hDstDS, iBand + 1);
-            GDALFillRaster(hBand, adfInitVals[iBand], 0);
-        }
-    }
-
-    return hDstDS;
-}
-
-/************************************************************************/
-/*                                main()                                */
-/************************************************************************/
-
-int main( int argc, char ** argv )
-
-{
-    int i, b3D = FALSE;
-    int bInverse = FALSE;
-    const char *pszSrcFilename = NULL;
-    const char *pszDstFilename = NULL;
-    char **papszLayers = NULL;
-    const char *pszSQL = NULL;
-    const char *pszBurnAttribute = NULL;
-    const char *pszWHERE = NULL;
-    std::vector<int> anBandList;
-    std::vector<double> adfBurnValues;
-    char **papszRasterizeOptions = NULL;
-    double dfXRes = 0, dfYRes = 0;
-    int bCreateOutput = FALSE;
-    const char* pszFormat = "GTiff";
-    int bFormatExplicitlySet = FALSE;
-    char **papszCreateOptions = NULL;
-    GDALDriverH hDriver = NULL;
-    GDALDataType eOutputType = GDT_Float64;
-    std::vector<double> adfInitVals;
-    int bNoDataSet = FALSE;
-    double dfNoData = 0;
-    OGREnvelope sEnvelop;
-    int bGotBounds = FALSE;
-    int nXSize = 0, nYSize = 0;
-    int bQuiet = FALSE;
-    GDALProgressFunc pfnProgress = GDALTermProgress;
-    OGRSpatialReferenceH hSRS = NULL;
-    int bTargetAlignedPixels = FALSE;
-    
-
-    /* Check that we are running against at least GDAL 1.4 */
-    /* Note to developers : if we use newer API, please change the requirement */
-    if (atoi(GDALVersionInfo("VERSION_NUM")) < 1400)
-    {
-        fprintf(stderr, "At least, GDAL >= 1.4.0 is required for this version of %s, "
-                "which was compiled against GDAL %s\n", argv[0], GDAL_RELEASE_NAME);
-        exit(1);
-    }
-
-    GDALAllRegister();
-    OGRRegisterAll();
-
-    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
-    if( argc < 1 )
-        exit( -argc );
-
-/* -------------------------------------------------------------------- */
-/*      Parse arguments.                                                */
-/* -------------------------------------------------------------------- */
-    for( i = 1; i < argc; i++ )
-    {
-        if( EQUAL(argv[i], "--utility_version") )
-        {
-            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
-                   argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
-            return 0;
-        }
-        else if( EQUAL(argv[i],"-q") || EQUAL(argv[i],"-quiet") )
-        {
-            bQuiet = TRUE;
-            pfnProgress = GDALDummyProgress;
-        }
-        else if( EQUAL(argv[i],"-a") && i < argc-1 )
-        {
-            pszBurnAttribute = argv[++i];
-        }
-        else if( EQUAL(argv[i],"-b") && i < argc-1 )
-        {
-            if (strchr(argv[i+1], ' '))
-            {
-                char** papszTokens = CSLTokenizeString( argv[i+1] );
-                char** papszIter = papszTokens;
-                while(papszIter && *papszIter)
-                {
-                    anBandList.push_back(atoi(*papszIter));
-                    papszIter ++;
-                }
-                CSLDestroy(papszTokens);
-                i += 1;
-            }
-            else
-            {
-                while(i < argc-1 && ArgIsNumeric(argv[i+1]))
-                {
-                    anBandList.push_back(atoi(argv[i+1]));
-                    i += 1;
-                }
-            }
-        }
-        else if( EQUAL(argv[i],"-3d")  )
-        {
-            b3D = TRUE;
-            papszRasterizeOptions = 
-                CSLSetNameValue( papszRasterizeOptions, "BURN_VALUE_FROM", "Z");
-        }
-        else if( EQUAL(argv[i],"-add")  )
-        {
-            papszRasterizeOptions = 
-                CSLSetNameValue( papszRasterizeOptions, "MERGE_ALG", "ADD");
-        }
-        else if( EQUAL(argv[i],"-chunkysize") && i < argc-1 )
-        {
-            papszRasterizeOptions = 
-                CSLSetNameValue( papszRasterizeOptions, "CHUNKYSIZE", 
-                                 argv[++i] );
-        }
-        else if( EQUAL(argv[i],"-i")  )
-        {
-            bInverse = TRUE;
-        }
-        else if( EQUAL(argv[i],"-at")  )
-        {
-            papszRasterizeOptions = 
-                CSLSetNameValue( papszRasterizeOptions, "ALL_TOUCHED", "TRUE" );
-        }
-        else if( EQUAL(argv[i],"-burn") && i < argc-1 )
-        {
-            if (strchr(argv[i+1], ' '))
-            {
-                char** papszTokens = CSLTokenizeString( argv[i+1] );
-                char** papszIter = papszTokens;
-                while(papszIter && *papszIter)
-                {
-                    adfBurnValues.push_back(CPLAtof(*papszIter));
-                    papszIter ++;
-                }
-                CSLDestroy(papszTokens);
-                i += 1;
-            }
-            else
-            {
-                while(i < argc-1 && ArgIsNumeric(argv[i+1]))
-                {
-                    adfBurnValues.push_back(CPLAtof(argv[i+1]));
-                    i += 1;
-                }
-            }
-        }
-        else if( EQUAL(argv[i],"-where") && i < argc-1 )
-        {
-            pszWHERE = argv[++i];
-        }
-        else if( EQUAL(argv[i],"-l") && i < argc-1 )
-        {
-            papszLayers = CSLAddString( papszLayers, argv[++i] );
-        }
-        else if( EQUAL(argv[i],"-sql") && i < argc-1 )
-        {
-            pszSQL = argv[++i];
-        }
-        else if( EQUAL(argv[i],"-of") && i < argc-1 )
-        {
-            pszFormat = argv[++i];
-            bFormatExplicitlySet = TRUE;
-            bCreateOutput = TRUE;
-        }
-        else if( EQUAL(argv[i],"-init") && i < argc - 1 )
-        {
-            if (strchr(argv[i+1], ' '))
-            {
-                char** papszTokens = CSLTokenizeString( argv[i+1] );
-                char** papszIter = papszTokens;
-                while(papszIter && *papszIter)
-                {
-                    adfInitVals.push_back(CPLAtof(*papszIter));
-                    papszIter ++;
-                }
-                CSLDestroy(papszTokens);
-                i += 1;
-            }
-            else
-            {
-                while(i < argc-1 && ArgIsNumeric(argv[i+1]))
-                {
-                    adfInitVals.push_back(CPLAtof(argv[i+1]));
-                    i += 1;
-                }
-            }
-            bCreateOutput = TRUE;
-        }
-        else if( EQUAL(argv[i],"-a_nodata") && i < argc - 1 )
-        {
-            dfNoData = CPLAtof(argv[i+1]);
-            bNoDataSet = TRUE;
-            i += 1;
-            bCreateOutput = TRUE;
-        }
-        else if( EQUAL(argv[i],"-a_srs") && i < argc-1 )
-        {
-            hSRS = OSRNewSpatialReference( NULL );
-
-            if( OSRSetFromUserInput(hSRS, argv[i+1]) != OGRERR_NONE )
-            {
-                fprintf( stderr, "Failed to process SRS definition: %s\n", 
-                         argv[i+1] );
-                exit( 1 );
-            }
-
-            i++;
-            bCreateOutput = TRUE;
-        }   
-
-        else if( EQUAL(argv[i],"-te") && i < argc - 4 )
-        {
-            sEnvelop.MinX = CPLAtof(argv[++i]);
-            sEnvelop.MinY = CPLAtof(argv[++i]);
-            sEnvelop.MaxX = CPLAtof(argv[++i]);
-            sEnvelop.MaxY = CPLAtof(argv[++i]);
-            bGotBounds = TRUE;
-            bCreateOutput = TRUE;
-        }
-        else if( EQUAL(argv[i],"-a_ullr") && i < argc - 4 )
-        {
-            sEnvelop.MinX = CPLAtof(argv[++i]);
-            sEnvelop.MaxY = CPLAtof(argv[++i]);
-            sEnvelop.MaxX = CPLAtof(argv[++i]);
-            sEnvelop.MinY = CPLAtof(argv[++i]);
-            bGotBounds = TRUE;
-            bCreateOutput = TRUE;
-        }
-        else if( EQUAL(argv[i],"-co") && i < argc-1 )
-        {
-            papszCreateOptions = CSLAddString( papszCreateOptions, argv[++i] );
-            bCreateOutput = TRUE;
-        }
-        else if( EQUAL(argv[i],"-ot") && i < argc-1 )
-        {
-            int	iType;
-            
-            for( iType = 1; iType < GDT_TypeCount; iType++ )
-            {
-                if( GDALGetDataTypeName((GDALDataType)iType) != NULL
-                    && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
-                             argv[i+1]) )
-                {
-                    eOutputType = (GDALDataType) iType;
-                }
-            }
-
-            if( eOutputType == GDT_Unknown )
-            {
-                printf( "Unknown output pixel type: %s\n", argv[i+1] );
-                Usage();
-            }
-            i++;
-            bCreateOutput = TRUE;
-        }
-        else if( (EQUAL(argv[i],"-ts") || EQUAL(argv[i],"-outsize")) && i < argc-2 )
-        {
-            nXSize = atoi(argv[++i]);
-            nYSize = atoi(argv[++i]);
-            if (nXSize <= 0 || nYSize <= 0)
-            {
-                printf( "Wrong value for -outsize parameters\n");
-                Usage();
-            }
-            bCreateOutput = TRUE;
-        }
-        else if( EQUAL(argv[i],"-tr") && i < argc-2 )
-        {
-            dfXRes = CPLAtof(argv[++i]);
-            dfYRes = fabs(CPLAtof(argv[++i]));
-            if( dfXRes == 0 || dfYRes == 0 )
-            {
-                printf( "Wrong value for -tr parameters\n");
-                Usage();
-            }
-            bCreateOutput = TRUE;
-        }
-        else if( EQUAL(argv[i],"-tap") )
-        {
-            bTargetAlignedPixels = TRUE;
-            bCreateOutput = TRUE;
-        }
-        else if( pszSrcFilename == NULL )
-        {
-            pszSrcFilename = argv[i];
-        }
-        else if( pszDstFilename == NULL )
-        {
-            pszDstFilename = argv[i];
-        }
-        else
-            Usage();
-    }
-
-    if( pszSrcFilename == NULL || pszDstFilename == NULL )
-    {
-        fprintf( stderr, "Missing source or destination.\n\n" );
-        Usage();
-    }
-
-    if( adfBurnValues.size() == 0 && pszBurnAttribute == NULL && !b3D )
-    {
-        fprintf( stderr, "At least one of -3d, -burn or -a required.\n\n" );
-        Usage();
-    }
-
-    if( bCreateOutput )
-    {
-        if( dfXRes == 0 && dfYRes == 0 && nXSize == 0 && nYSize == 0 )
-        {
-            fprintf( stderr, "'-tr xres yres' or '-ts xsize ysize' is required.\n\n" );
-            Usage();
-        }
-    
-        if (bTargetAlignedPixels && dfXRes == 0 && dfYRes == 0)
-        {
-            fprintf( stderr, "-tap option cannot be used without using -tr\n");
-            Usage();
-        }
-
-        if( anBandList.size() != 0 )
-        {
-            fprintf( stderr, "-b option cannot be used when creating a GDAL dataset.\n\n" );
-            Usage();
-        }
-
-        int nBandCount = 1;
-
-        if (adfBurnValues.size() != 0)
-            nBandCount = adfBurnValues.size();
-
-        if ((int)adfInitVals.size() > nBandCount)
-            nBandCount = adfInitVals.size();
-
-        if (adfInitVals.size() == 1)
-        {
-            for(i=1;i<=nBandCount - 1;i++)
-                adfInitVals.push_back( adfInitVals[0] );
-        }
-
-        int i;
-        for(i=1;i<=nBandCount;i++)
-            anBandList.push_back( i );
-    }
-    else
-    {
-        if( anBandList.size() == 0 )
-            anBandList.push_back( 1 );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Open source vector dataset.                                     */
-/* -------------------------------------------------------------------- */
-    OGRDataSourceH hSrcDS;
-
-    hSrcDS = OGROpen( pszSrcFilename, FALSE, NULL );
-    if( hSrcDS == NULL )
-    {
-        fprintf( stderr, "Failed to open feature source: %s\n", 
-                 pszSrcFilename);
-        exit( 1 );
-    }
-
-    if( pszSQL == NULL && papszLayers == NULL )
-    {
-        if( OGR_DS_GetLayerCount(hSrcDS) == 1 )
-        {
-            papszLayers = CSLAddString(NULL, OGR_L_GetName(OGR_DS_GetLayer(hSrcDS, 0)));
-        }
-        else
-        {
-            fprintf( stderr, "At least one of -l or -sql required.\n\n" );
-            Usage();
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Open target raster file.  Eventually we will add optional       */
-/*      creation.                                                       */
-/* -------------------------------------------------------------------- */
-    GDALDatasetH hDstDS = NULL;
-
-    if (bCreateOutput)
-    {
-/* -------------------------------------------------------------------- */
-/*      Find the output driver.                                         */
-/* -------------------------------------------------------------------- */
-        hDriver = GDALGetDriverByName( pszFormat );
-        if( hDriver == NULL 
-            || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) == NULL )
-        {
-            int	iDr;
-
-            printf( "Output driver `%s' not recognised or does not support\n", 
-                    pszFormat );
-            printf( "direct output file creation.  The following format drivers are configured\n"
-                    "and support direct output:\n" );
-
-            for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
-            {
-                GDALDriverH hDriver = GDALGetDriver(iDr);
-
-                if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL) != NULL )
-                {
-                    printf( "  %s: %s\n",
-                            GDALGetDriverShortName( hDriver  ),
-                            GDALGetDriverLongName( hDriver ) );
-                }
-            }
-            printf( "\n" );
-            exit( 1 );
-        }
-
-        if (!bQuiet && !bFormatExplicitlySet)
-            CheckExtensionConsistency(pszDstFilename, pszFormat);
-    }
-    else
-    {
-        hDstDS = GDALOpen( pszDstFilename, GA_Update );
-        if( hDstDS == NULL )
-            exit( 2 );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Process SQL request.                                            */
-/* -------------------------------------------------------------------- */
-    if( pszSQL != NULL )
-    {
-        OGRLayerH hLayer;
-
-        hLayer = OGR_DS_ExecuteSQL( hSrcDS, pszSQL, NULL, NULL ); 
-        if( hLayer != NULL )
-        {
-            if (bCreateOutput)
-            {
-                std::vector<OGRLayerH> ahLayers;
-                ahLayers.push_back(hLayer);
-
-                hDstDS = CreateOutputDataset(ahLayers, hSRS,
-                                 bGotBounds, sEnvelop,
-                                 hDriver, pszDstFilename,
-                                 nXSize, nYSize, dfXRes, dfYRes,
-                                 bTargetAlignedPixels,
-                                 anBandList.size(), eOutputType,
-                                 papszCreateOptions, adfInitVals,
-                                 bNoDataSet, dfNoData);
-            }
-
-            ProcessLayer( hLayer, hSRS != NULL, hDstDS, anBandList, 
-                          adfBurnValues, b3D, bInverse, pszBurnAttribute,
-                          papszRasterizeOptions, pfnProgress, NULL );
-
-            OGR_DS_ReleaseResultSet( hSrcDS, hLayer );
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Create output file if necessary.                                */
-/* -------------------------------------------------------------------- */
-    int nLayerCount = CSLCount(papszLayers);
-
-    if (bCreateOutput && hDstDS == NULL)
-    {
-        std::vector<OGRLayerH> ahLayers;
-
-        for( i = 0; i < nLayerCount; i++ )
-        {
-            OGRLayerH hLayer = OGR_DS_GetLayerByName( hSrcDS, papszLayers[i] );
-            if( hLayer == NULL )
-            {
-                continue;
-            }
-            ahLayers.push_back(hLayer);
-        }
-
-        hDstDS = CreateOutputDataset(ahLayers, hSRS,
-                                bGotBounds, sEnvelop,
-                                hDriver, pszDstFilename,
-                                nXSize, nYSize, dfXRes, dfYRes,
-                                bTargetAlignedPixels,
-                                anBandList.size(), eOutputType,
-                                papszCreateOptions, adfInitVals,
-                                bNoDataSet, dfNoData);
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Process each layer.                                             */
-/* -------------------------------------------------------------------- */
-
-    for( i = 0; i < nLayerCount; i++ )
-    {
-        OGRLayerH hLayer = OGR_DS_GetLayerByName( hSrcDS, papszLayers[i] );
-        if( hLayer == NULL )
-        {
-            fprintf( stderr, "Unable to find layer %s, skipping.\n", 
-                      papszLayers[i] );
-            continue;
-        }
-
-        if( pszWHERE )
-        {
-            if( OGR_L_SetAttributeFilter( hLayer, pszWHERE ) != OGRERR_NONE )
-                break;
-        }
-
-        void *pScaledProgress;
-        pScaledProgress =
-            GDALCreateScaledProgress( 0.0, 1.0 * (i + 1) / nLayerCount,
-                                      pfnProgress, NULL );
-
-        ProcessLayer( hLayer, hSRS != NULL, hDstDS, anBandList, 
-                      adfBurnValues, b3D, bInverse, pszBurnAttribute,
-                      papszRasterizeOptions, GDALScaledProgress, pScaledProgress );
-
-        GDALDestroyScaledProgress( pScaledProgress );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Cleanup                                                         */
-/* -------------------------------------------------------------------- */
-
-    OGR_DS_Destroy( hSrcDS );
-    GDALClose( hDstDS );
-
-    OSRDestroySpatialReference(hSRS);
-
-    CSLDestroy( argv );
-    CSLDestroy( papszRasterizeOptions );
-    CSLDestroy( papszLayers );
-    CSLDestroy( papszCreateOptions );
-    
-    GDALDestroyDriverManager();
-    OGRCleanupAll();
-
-    return 0;
-}
diff --git a/apps/gdal_rasterize_bin.cpp b/apps/gdal_rasterize_bin.cpp
new file mode 100644
index 0000000..1512d07
--- /dev/null
+++ b/apps/gdal_rasterize_bin.cpp
@@ -0,0 +1,180 @@
+/******************************************************************************
+ * $Id: gdal_rasterize_bin.cpp 33615 2016-03-02 20:19:22Z goatbar $
+ *
+ * Project:  GDAL Utilities
+ * Purpose:  Rasterize OGR shapes into a GDAL raster.
+ * Authors:  Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_string.h"
+#include "commonutils.h"
+#include "gdal_utils_priv.h"
+
+CPL_CVSID("$Id: gdal_rasterize_bin.cpp 33615 2016-03-02 20:19:22Z goatbar $");
+
+/************************************************************************/
+/*                               Usage()                                */
+/************************************************************************/
+
+static void Usage(const char* pszErrorMsg = NULL)
+
+{
+    printf(
+        "Usage: gdal_rasterize [-b band]* [-i] [-at]\n"
+        "       [-burn value]* | [-a attribute_name] [-3d] [-add]\n"
+        "       [-l layername]* [-where expression] [-sql select_statement]\n"
+        "       [-dialect dialect] [-of format] [-a_srs srs_def]\n"
+        "       [-co \"NAME=VALUE\"]* [-a_nodata value] [-init value]*\n"
+        "       [-te xmin ymin xmax ymax] [-tr xres yres] [-tap] [-ts width height]\n"
+        "       [-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/\n"
+        "             CInt16/CInt32/CFloat32/CFloat64}] [-q]\n"
+        "       <src_datasource> <dst_filename>\n" );
+
+    if( pszErrorMsg != NULL )
+        fprintf(stderr, "\nFAILURE: %s\n", pszErrorMsg);
+    exit( 1 );
+}
+
+/************************************************************************/
+/*                       GDALRasterizeOptionsForBinaryNew()             */
+/************************************************************************/
+
+static GDALRasterizeOptionsForBinary *GDALRasterizeOptionsForBinaryNew(void)
+{
+    return (GDALRasterizeOptionsForBinary*) CPLCalloc(  1, sizeof(GDALRasterizeOptionsForBinary) );
+}
+
+/************************************************************************/
+/*                       GDALRasterizeOptionsForBinaryFree()            */
+/************************************************************************/
+
+static void GDALRasterizeOptionsForBinaryFree( GDALRasterizeOptionsForBinary* psOptionsForBinary )
+{
+    if( psOptionsForBinary )
+    {
+        CPLFree(psOptionsForBinary->pszSource);
+        CPLFree(psOptionsForBinary->pszDest);
+        CPLFree(psOptionsForBinary->pszFormat);
+        CPLFree(psOptionsForBinary);
+    }
+}
+/************************************************************************/
+/*                                main()                                */
+/************************************************************************/
+
+int main(int argc, char** argv)
+{
+    /* Check strict compilation and runtime library version as we use C++ API */
+    if (! GDAL_CHECK_VERSION(argv[0]))
+        exit(1);
+
+    EarlySetConfigOptions(argc, argv);
+
+/* -------------------------------------------------------------------- */
+/*      Generic arg processing.                                         */
+/* -------------------------------------------------------------------- */
+    GDALAllRegister();
+    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
+    if( argc < 1 )
+        exit( -argc );
+
+    for( int i = 0; i < argc; i++ )
+    {
+        if( EQUAL(argv[i], "--utility_version") )
+        {
+            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
+                   argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
+            CSLDestroy( argv );
+            return 0;
+        }
+        else if( EQUAL(argv[i],"--help") )
+        {
+            Usage();
+        }
+    }
+
+    GDALRasterizeOptionsForBinary* psOptionsForBinary = GDALRasterizeOptionsForBinaryNew();
+    /* coverity[tainted_data] */
+    GDALRasterizeOptions *psOptions = GDALRasterizeOptionsNew(argv + 1, psOptionsForBinary);
+    CSLDestroy( argv );
+
+    if( psOptions == NULL )
+    {
+        Usage();
+    }
+
+    if( !(psOptionsForBinary->bQuiet) )
+    {
+        GDALRasterizeOptionsSetProgress(psOptions, GDALTermProgress, NULL);
+    }
+
+    if( psOptionsForBinary->pszSource == NULL )
+        Usage("No input file specified.");
+
+    if( psOptionsForBinary->pszDest == NULL )
+        Usage("No output file specified.");
+
+/* -------------------------------------------------------------------- */
+/*      Open input file.                                                */
+/* -------------------------------------------------------------------- */
+    GDALDatasetH hInDS = GDALOpenEx( psOptionsForBinary->pszSource, GDAL_OF_VECTOR | GDAL_OF_VERBOSE_ERROR,
+                                     NULL, NULL, NULL );
+
+    if( hInDS == NULL )
+        exit( 1 );
+
+/* -------------------------------------------------------------------- */
+/*      Open output file if it exists.                                  */
+/* -------------------------------------------------------------------- */
+    GDALDatasetH hDstDS = NULL;
+    if( !(psOptionsForBinary->bCreateOutput) )
+    {
+        CPLPushErrorHandler( CPLQuietErrorHandler );
+        hDstDS = GDALOpenEx( psOptionsForBinary->pszDest, GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR | GDAL_OF_UPDATE,
+                                        NULL, NULL, NULL );
+        CPLPopErrorHandler();
+    }
+
+    if (hDstDS == NULL && !psOptionsForBinary->bQuiet && !psOptionsForBinary->bFormatExplicitlySet)
+        CheckExtensionConsistency(psOptionsForBinary->pszDest, psOptionsForBinary->pszFormat);
+
+
+    int bUsageError = FALSE;
+    GDALDatasetH hRetDS = GDALRasterize(psOptionsForBinary->pszDest,
+                                        hDstDS,
+                                        hInDS,
+                                        psOptions, &bUsageError);
+    if(bUsageError == TRUE)
+        Usage();
+    int nRetCode = (hRetDS) ? 0 : 1;
+
+    GDALClose(hInDS);
+    GDALClose(hRetDS);
+    GDALRasterizeOptionsFree(psOptions);
+    GDALRasterizeOptionsForBinaryFree(psOptionsForBinary);
+
+    GDALDestroyDriverManager();
+
+    return nRetCode;
+}
diff --git a/apps/gdal_rasterize_lib.cpp b/apps/gdal_rasterize_lib.cpp
new file mode 100644
index 0000000..74fef47
--- /dev/null
+++ b/apps/gdal_rasterize_lib.cpp
@@ -0,0 +1,1194 @@
+/******************************************************************************
+ * $Id: gdal_rasterize_lib.cpp 33615 2016-03-02 20:19:22Z goatbar $
+ *
+ * Project:  GDAL Utilities
+ * Purpose:  Rasterize OGR shapes into a GDAL raster.
+ * Author:   Frank Warmerdam <warmerdam at pobox.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2015, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gdal.h"
+#include "gdal_alg.h"
+#include "cpl_conv.h"
+#include "ogr_api.h"
+#include "ogr_srs_api.h"
+#include "cpl_string.h"
+#include "commonutils.h"
+#include "gdal_utils_priv.h"
+#include <vector>
+
+CPL_CVSID("$Id: gdal_rasterize_lib.cpp 33615 2016-03-02 20:19:22Z goatbar $");
+
+/************************************************************************/
+/*                            ArgIsNumeric()                            */
+/************************************************************************/
+
+static int ArgIsNumeric( const char *pszArg )
+
+{
+    return CPLGetValueType(pszArg) != CPL_VALUE_STRING;
+}
+
+
+/************************************************************************/
+/*                          InvertGeometries()                          */
+/************************************************************************/
+
+static void InvertGeometries( GDALDatasetH hDstDS,
+                              std::vector<OGRGeometryH> &ahGeometries )
+
+{
+    OGRGeometryH hCollection =
+        OGR_G_CreateGeometry( wkbGeometryCollection );
+
+/* -------------------------------------------------------------------- */
+/*      Create a ring that is a bit outside the raster dataset.         */
+/* -------------------------------------------------------------------- */
+    OGRGeometryH hUniversePoly, hUniverseRing;
+    double adfGeoTransform[6];
+    int brx = GDALGetRasterXSize( hDstDS ) + 2;
+    int bry = GDALGetRasterYSize( hDstDS ) + 2;
+
+    GDALGetGeoTransform( hDstDS, adfGeoTransform );
+
+    hUniverseRing = OGR_G_CreateGeometry( wkbLinearRing );
+
+    OGR_G_AddPoint_2D(
+        hUniverseRing,
+        adfGeoTransform[0] + -2*adfGeoTransform[1] + -2*adfGeoTransform[2],
+        adfGeoTransform[3] + -2*adfGeoTransform[4] + -2*adfGeoTransform[5] );
+
+    OGR_G_AddPoint_2D(
+        hUniverseRing,
+        adfGeoTransform[0] + brx*adfGeoTransform[1] + -2*adfGeoTransform[2],
+        adfGeoTransform[3] + brx*adfGeoTransform[4] + -2*adfGeoTransform[5] );
+
+    OGR_G_AddPoint_2D(
+        hUniverseRing,
+        adfGeoTransform[0] + brx*adfGeoTransform[1] + bry*adfGeoTransform[2],
+        adfGeoTransform[3] + brx*adfGeoTransform[4] + bry*adfGeoTransform[5] );
+
+    OGR_G_AddPoint_2D(
+        hUniverseRing,
+        adfGeoTransform[0] + -2*adfGeoTransform[1] + bry*adfGeoTransform[2],
+        adfGeoTransform[3] + -2*adfGeoTransform[4] + bry*adfGeoTransform[5] );
+
+    OGR_G_AddPoint_2D(
+        hUniverseRing,
+        adfGeoTransform[0] + -2*adfGeoTransform[1] + -2*adfGeoTransform[2],
+        adfGeoTransform[3] + -2*adfGeoTransform[4] + -2*adfGeoTransform[5] );
+
+    hUniversePoly = OGR_G_CreateGeometry( wkbPolygon );
+    OGR_G_AddGeometryDirectly( hUniversePoly, hUniverseRing );
+
+    OGR_G_AddGeometryDirectly( hCollection, hUniversePoly );
+
+/* -------------------------------------------------------------------- */
+/*      Add the rest of the geometries into our collection.             */
+/* -------------------------------------------------------------------- */
+    unsigned int iGeom;
+
+    for( iGeom = 0; iGeom < ahGeometries.size(); iGeom++ )
+        OGR_G_AddGeometryDirectly( hCollection, ahGeometries[iGeom] );
+
+    ahGeometries.resize(1);
+    ahGeometries[0] = hCollection;
+}
+
+/************************************************************************/
+/*                            ProcessLayer()                            */
+/*                                                                      */
+/*      Process all the features in a layer selection, collecting       */
+/*      geometries and burn values.                                     */
+/************************************************************************/
+
+static CPLErr ProcessLayer(
+    OGRLayerH hSrcLayer, int bSRSIsSet,
+    GDALDatasetH hDstDS, std::vector<int> anBandList,
+    const std::vector<double> &adfBurnValues, int b3D, int bInverse,
+    const char *pszBurnAttribute, char **papszRasterizeOptions,
+    GDALProgressFunc pfnProgress, void* pProgressData )
+
+{
+/* -------------------------------------------------------------------- */
+/*      Checkout that SRS are the same.                                 */
+/*      If -a_srs is specified, skip the test                           */
+/* -------------------------------------------------------------------- */
+    OGRCoordinateTransformationH hCT = NULL;
+    if (!bSRSIsSet)
+    {
+        OGRSpatialReferenceH  hDstSRS = NULL;
+        if( GDALGetProjectionRef( hDstDS ) != NULL )
+        {
+            char *pszProjection;
+
+            pszProjection = (char *) GDALGetProjectionRef( hDstDS );
+
+            hDstSRS = OSRNewSpatialReference(NULL);
+            if( OSRImportFromWkt( hDstSRS, &pszProjection ) != OGRERR_NONE )
+            {
+                OSRDestroySpatialReference(hDstSRS);
+                hDstSRS = NULL;
+            }
+        }
+
+        OGRSpatialReferenceH hSrcSRS = OGR_L_GetSpatialRef(hSrcLayer);
+        if( hDstSRS != NULL && hSrcSRS != NULL )
+        {
+            if( OSRIsSame(hSrcSRS, hDstSRS) == FALSE )
+            {
+                hCT = OCTNewCoordinateTransformation(hSrcSRS, hDstSRS);
+                if( hCT == NULL )
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                        "The output raster dataset and the input vector layer do not have the same SRS.\n"
+                        "And reprojection of input data did not work. Results might be incorrect.");
+                }
+            }
+        }
+        else if( hDstSRS != NULL && hSrcSRS == NULL )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                    "The output raster dataset has a SRS, but the input vector layer SRS is unknown.\n"
+                    "Ensure input vector has the same SRS, otherwise results might be incorrect.");
+        }
+        else if( hDstSRS == NULL && hSrcSRS != NULL )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                    "The input vector layer has a SRS, but the output raster dataset SRS is unknown.\n"
+                    "Ensure output raster dataset has the same SRS, otherwise results might be incorrect.");
+        }
+
+        if( hDstSRS != NULL )
+        {
+            OSRDestroySpatialReference(hDstSRS);
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Get field index, and check.                                     */
+/* -------------------------------------------------------------------- */
+    int iBurnField = -1;
+
+    if( pszBurnAttribute )
+    {
+        iBurnField = OGR_FD_GetFieldIndex( OGR_L_GetLayerDefn( hSrcLayer ),
+                                           pszBurnAttribute );
+        if( iBurnField == -1 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Failed to find field %s on layer %s, skipping.",
+                    pszBurnAttribute,
+                    OGR_FD_GetName( OGR_L_GetLayerDefn( hSrcLayer ) ) );
+            if( hCT != NULL )
+                OCTDestroyCoordinateTransformation(hCT);
+            return CE_Failure;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Collect the geometries from this layer, and build list of       */
+/*      burn values.                                                    */
+/* -------------------------------------------------------------------- */
+    OGRFeatureH hFeat;
+    std::vector<OGRGeometryH> ahGeometries;
+    std::vector<double> adfFullBurnValues;
+
+    OGR_L_ResetReading( hSrcLayer );
+
+    while( (hFeat = OGR_L_GetNextFeature( hSrcLayer )) != NULL )
+    {
+        OGRGeometryH hGeom;
+
+        if( OGR_F_GetGeometryRef( hFeat ) == NULL )
+        {
+            OGR_F_Destroy( hFeat );
+            continue;
+        }
+
+        hGeom = OGR_G_Clone( OGR_F_GetGeometryRef( hFeat ) );
+        if( hCT != NULL )
+        {
+            if( OGR_G_Transform(hGeom, hCT) != OGRERR_NONE )
+            {
+                OGR_F_Destroy( hFeat );
+                OGR_G_DestroyGeometry(hGeom);
+                continue;
+            }
+        }
+        ahGeometries.push_back( hGeom );
+
+        for( unsigned int iBand = 0; iBand < anBandList.size(); iBand++ )
+        {
+            if( adfBurnValues.size() > 0 )
+                adfFullBurnValues.push_back(
+                    adfBurnValues[MIN(iBand,adfBurnValues.size()-1)] );
+            else if( pszBurnAttribute )
+            {
+                adfFullBurnValues.push_back( OGR_F_GetFieldAsDouble( hFeat, iBurnField ) );
+            }
+            /* I have made the 3D option exclusive to other options since it
+               can be used to modify the value from "-burn value" or
+               "-a attribute_name" */
+            if( b3D )
+            {
+                // TODO: get geometry "z" value
+                /* Points and Lines will have their "z" values collected at the
+                   point and line levels respectively. However filled polygons
+                   (GDALdllImageFilledPolygon) can use some help by getting
+                   their "z" values here. */
+                adfFullBurnValues.push_back( 0.0 );
+            }
+        }
+
+        OGR_F_Destroy( hFeat );
+    }
+
+    if( hCT != NULL )
+        OCTDestroyCoordinateTransformation(hCT);
+
+/* -------------------------------------------------------------------- */
+/*      If we are in inverse mode, we add one extra ring around the     */
+/*      whole dataset to invert the concept of insideness and then      */
+/*      merge everything into one geometry collection.                  */
+/* -------------------------------------------------------------------- */
+    if( bInverse )
+    {
+        if( ahGeometries.size() == 0 )
+        {
+            for( unsigned int iBand = 0; iBand < anBandList.size(); iBand++ )
+            {
+                if( adfBurnValues.size() > 0 )
+                    adfFullBurnValues.push_back(
+                        adfBurnValues[MIN(iBand,adfBurnValues.size()-1)] );
+                else /* FIXME? Not sure what to do exactly in the else case, but we must insert a value */
+                    adfFullBurnValues.push_back( 0.0 );
+            }
+        }
+
+        InvertGeometries( hDstDS, ahGeometries );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Perform the burn.                                               */
+/* -------------------------------------------------------------------- */
+    CPLErr eErr = GDALRasterizeGeometries( hDstDS, static_cast<int>(anBandList.size()), &(anBandList[0]),
+                             static_cast<int>(ahGeometries.size()), &(ahGeometries[0]),
+                             NULL, NULL, &(adfFullBurnValues[0]),
+                             papszRasterizeOptions,
+                             pfnProgress, pProgressData );
+
+/* -------------------------------------------------------------------- */
+/*      Cleanup geometries.                                             */
+/* -------------------------------------------------------------------- */
+    int iGeom;
+
+    for( iGeom = static_cast<int>(ahGeometries.size())-1; iGeom >= 0; iGeom-- )
+        OGR_G_DestroyGeometry( ahGeometries[iGeom] );
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                  CreateOutputDataset()                               */
+/************************************************************************/
+
+static
+GDALDatasetH CreateOutputDataset(std::vector<OGRLayerH> ahLayers,
+                                 OGRSpatialReferenceH hSRS,
+                                 int bGotBounds, OGREnvelope sEnvelop,
+                                 GDALDriverH hDriver, const char* pszDest,
+                                 int nXSize, int nYSize, double dfXRes, double dfYRes,
+                                 int bTargetAlignedPixels,
+                                 int nBandCount, GDALDataType eOutputType,
+                                 char** papszCreationOptions, std::vector<double> adfInitVals,
+                                 int bNoDataSet, double dfNoData)
+{
+    int bFirstLayer = TRUE;
+    char* pszWKT = NULL;
+    GDALDatasetH hDstDS = NULL;
+    unsigned int i;
+
+    for( i = 0; i < ahLayers.size(); i++ )
+    {
+        OGRLayerH hLayer = ahLayers[i];
+
+        if (!bGotBounds)
+        {
+            OGREnvelope sLayerEnvelop;
+
+            if (OGR_L_GetExtent(hLayer, &sLayerEnvelop, TRUE) != OGRERR_NONE)
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "Cannot get layer extent");
+                return NULL;
+            }
+
+            /* Voluntarily increase the extent by a half-pixel size to avoid */
+            /* missing points on the border */
+            if (!bTargetAlignedPixels && dfXRes != 0 && dfYRes != 0)
+            {
+                sLayerEnvelop.MinX -= dfXRes / 2;
+                sLayerEnvelop.MaxX += dfXRes / 2;
+                sLayerEnvelop.MinY -= dfYRes / 2;
+                sLayerEnvelop.MaxY += dfYRes / 2;
+            }
+
+            if (bFirstLayer)
+            {
+                sEnvelop.MinX = sLayerEnvelop.MinX;
+                sEnvelop.MinY = sLayerEnvelop.MinY;
+                sEnvelop.MaxX = sLayerEnvelop.MaxX;
+                sEnvelop.MaxY = sLayerEnvelop.MaxY;
+
+                if (hSRS == NULL)
+                    hSRS = OGR_L_GetSpatialRef(hLayer);
+
+                bFirstLayer = FALSE;
+            }
+            else
+            {
+                sEnvelop.MinX = MIN(sEnvelop.MinX, sLayerEnvelop.MinX);
+                sEnvelop.MinY = MIN(sEnvelop.MinY, sLayerEnvelop.MinY);
+                sEnvelop.MaxX = MAX(sEnvelop.MaxX, sLayerEnvelop.MaxX);
+                sEnvelop.MaxY = MAX(sEnvelop.MaxY, sLayerEnvelop.MaxY);
+            }
+        }
+        else
+        {
+            if (bFirstLayer)
+            {
+                if (hSRS == NULL)
+                    hSRS = OGR_L_GetSpatialRef(hLayer);
+
+                bFirstLayer = FALSE;
+            }
+        }
+    }
+
+    if (dfXRes == 0 && dfYRes == 0)
+    {
+        dfXRes = (sEnvelop.MaxX - sEnvelop.MinX) / nXSize;
+        dfYRes = (sEnvelop.MaxY - sEnvelop.MinY) / nYSize;
+    }
+    else if (bTargetAlignedPixels && dfXRes != 0 && dfYRes != 0)
+    {
+        sEnvelop.MinX = floor(sEnvelop.MinX / dfXRes) * dfXRes;
+        sEnvelop.MaxX = ceil(sEnvelop.MaxX / dfXRes) * dfXRes;
+        sEnvelop.MinY = floor(sEnvelop.MinY / dfYRes) * dfYRes;
+        sEnvelop.MaxY = ceil(sEnvelop.MaxY / dfYRes) * dfYRes;
+    }
+
+    double adfProjection[6];
+    adfProjection[0] = sEnvelop.MinX;
+    adfProjection[1] = dfXRes;
+    adfProjection[2] = 0;
+    adfProjection[3] = sEnvelop.MaxY;
+    adfProjection[4] = 0;
+    adfProjection[5] = -dfYRes;
+
+    if (nXSize == 0 && nYSize == 0)
+    {
+        nXSize = (int)(0.5 + (sEnvelop.MaxX - sEnvelop.MinX) / dfXRes);
+        nYSize = (int)(0.5 + (sEnvelop.MaxY - sEnvelop.MinY) / dfYRes);
+    }
+
+    hDstDS = GDALCreate(hDriver, pszDest, nXSize, nYSize,
+                        nBandCount, eOutputType, papszCreationOptions);
+    if (hDstDS == NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot create %s", pszDest);
+        return NULL;
+    }
+
+    GDALSetGeoTransform(hDstDS, adfProjection);
+
+    if (hSRS)
+        OSRExportToWkt(hSRS, &pszWKT);
+    if (pszWKT)
+        GDALSetProjection(hDstDS, pszWKT);
+    CPLFree(pszWKT);
+
+    int iBand;
+    /*if( nBandCount == 3 || nBandCount == 4 )
+    {
+        for(iBand = 0; iBand < nBandCount; iBand++)
+        {
+            GDALRasterBandH hBand = GDALGetRasterBand(hDstDS, iBand + 1);
+            GDALSetRasterColorInterpretation(hBand, (GDALColorInterp)(GCI_RedBand + iBand));
+        }
+    }*/
+
+    if (bNoDataSet)
+    {
+        for(iBand = 0; iBand < nBandCount; iBand++)
+        {
+            GDALRasterBandH hBand = GDALGetRasterBand(hDstDS, iBand + 1);
+            GDALSetRasterNoDataValue(hBand, dfNoData);
+        }
+    }
+
+    if (adfInitVals.size() != 0)
+    {
+        for(iBand = 0; iBand < MIN(nBandCount,(int)adfInitVals.size()); iBand++)
+        {
+            GDALRasterBandH hBand = GDALGetRasterBand(hDstDS, iBand + 1);
+            GDALFillRaster(hBand, adfInitVals[iBand], 0);
+        }
+    }
+
+    return hDstDS;
+}
+
+
+struct GDALRasterizeOptions
+{
+    /*! output format. The default is GeoTIFF(GTiff). Use the short format name. */
+    char *pszFormat;
+
+    /*! the progress function to use */
+    GDALProgressFunc pfnProgress;
+
+    /*! pointer to the progress data variable */
+    void *pProgressData;
+
+    int bCreateOutput;
+    int b3D ;
+    int bInverse;
+    char **papszLayers;
+    char *pszSQL;
+    char *pszDialect;
+    char *pszBurnAttribute;
+    char *pszWHERE;
+    std::vector<int> anBandList;
+    std::vector<double> adfBurnValues;
+    char **papszRasterizeOptions;
+    double dfXRes;
+    double dfYRes;
+    char **papszCreationOptions;
+    GDALDataType eOutputType;
+    std::vector<double> adfInitVals;
+    int bNoDataSet;
+    double dfNoData;
+    OGREnvelope sEnvelop;
+    int bGotBounds;
+    int nXSize, nYSize;
+    OGRSpatialReferenceH hSRS;
+    int bTargetAlignedPixels;
+};
+
+
+/************************************************************************/
+/*                             GDALRasterize()                          */
+/************************************************************************/
+
+/**
+ * Burns vector geometries into a raster
+ *
+ * This is the equivalent of the <a href="gdal_rasterize.html">gdal_rasterize</a> utility.
+ *
+ * GDALRasterizeOptions* must be allocated and freed with GDALRasterizeOptionsNew()
+ * and GDALRasterizeOptionsFree() respectively.
+ * pszDest and hDstDS cannot be used at the same time.
+ *
+ * @param pszDest the destination dataset path or NULL.
+ * @param hDstDS the destination dataset or NULL.
+ * @param hSrcDataset the source dataset handle.
+ * @param psOptionsIn the options struct returned by GDALRasterizeOptionsNew() or NULL.
+ * @param pbUsageError the pointer to int variable to determine any usage error has occurred or NULL.
+ * @return the output dataset (new dataset that must be closed using GDALClose(), or hDstDS is not NULL) or NULL in case of error.
+ *
+ * @since GDAL 2.1
+ */
+
+GDALDatasetH GDALRasterize( const char *pszDest, GDALDatasetH hDstDS,
+                            GDALDatasetH hSrcDataset,
+                            const GDALRasterizeOptions *psOptionsIn, int *pbUsageError )
+{
+    if( pszDest == NULL && hDstDS == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "pszDest == NULL && hDstDS == NULL");
+
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        return NULL;
+    }
+    if( hSrcDataset == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "hSrcDataset== NULL");
+
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        return NULL;
+    }
+    if( hDstDS != NULL && psOptionsIn && psOptionsIn->bCreateOutput )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "hDstDS != NULL but options that imply creating a new dataset have been set.");
+
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        return NULL;
+    }
+
+    GDALRasterizeOptions* psOptionsToFree = NULL;
+    const GDALRasterizeOptions* psOptions;
+    if( psOptionsIn )
+        psOptions = psOptionsIn;
+    else
+    {
+        psOptionsToFree = GDALRasterizeOptionsNew(NULL, NULL);
+        psOptions = psOptionsToFree;
+    }
+
+    int bCloseOutDSOnError = (hDstDS == NULL);
+    if( pszDest == NULL )
+        pszDest = GDALGetDescription(hDstDS);
+
+    if( psOptions->pszSQL == NULL && psOptions->papszLayers == NULL &&
+        GDALDatasetGetLayerCount(hSrcDataset) != 1 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Neither -sql nor -l are specified, but the source dataset has not one single layer.");
+        if( pbUsageError )
+            *pbUsageError = TRUE;
+        GDALRasterizeOptionsFree(psOptionsToFree);
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Open target raster file.  Eventually we will add optional       */
+/*      creation.                                                       */
+/* -------------------------------------------------------------------- */
+    int bCreateOutput = psOptions->bCreateOutput;
+    if( hDstDS == NULL )
+        bCreateOutput = TRUE;
+
+    GDALDriverH hDriver = NULL;
+    if (psOptions->bCreateOutput)
+    {
+/* -------------------------------------------------------------------- */
+/*      Find the output driver.                                         */
+/* -------------------------------------------------------------------- */
+        hDriver = GDALGetDriverByName( psOptions->pszFormat );
+        if( hDriver == NULL
+            || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) == NULL )
+        {
+            int	iDr;
+
+            CPLError( CE_Failure, CPLE_NotSupported,
+                      "Output driver `%s' not recognised or does not support "
+                      " direct output file creation.", psOptions->pszFormat);
+            fprintf(stderr, "The following format drivers are configured\n"
+                    "and support direct output:\n" );
+
+            for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
+            {
+                hDriver = GDALGetDriver(iDr);
+
+                if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL) != NULL )
+                {
+                    fprintf(stderr, "  %s: %s\n",
+                            GDALGetDriverShortName( hDriver  ),
+                            GDALGetDriverLongName( hDriver ) );
+                }
+            }
+            fprintf(stderr, "\n" );
+            GDALRasterizeOptionsFree(psOptionsToFree);
+            return NULL;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Process SQL request.                                            */
+/* -------------------------------------------------------------------- */
+    CPLErr eErr = CE_Failure;
+
+    if( psOptions->pszSQL != NULL )
+    {
+        OGRLayerH hLayer;
+
+        hLayer = GDALDatasetExecuteSQL( hSrcDataset, psOptions->pszSQL, NULL, psOptions->pszDialect );
+        if( hLayer != NULL )
+        {
+            if (bCreateOutput)
+            {
+                std::vector<OGRLayerH> ahLayers;
+                ahLayers.push_back(hLayer);
+
+                hDstDS = CreateOutputDataset(ahLayers, psOptions->hSRS,
+                                 psOptions->bGotBounds, psOptions->sEnvelop,
+                                 hDriver, pszDest,
+                                 psOptions->nXSize, psOptions->nYSize, psOptions->dfXRes, psOptions->dfYRes,
+                                 psOptions->bTargetAlignedPixels,
+                                 static_cast<int>(psOptions->anBandList.size()), psOptions->eOutputType,
+                                 psOptions->papszCreationOptions, psOptions->adfInitVals,
+                                 psOptions->bNoDataSet, psOptions->dfNoData);
+                if( hDstDS == NULL )
+                {
+                    GDALDatasetReleaseResultSet( hSrcDataset, hLayer );
+                    GDALRasterizeOptionsFree(psOptionsToFree);
+                    return NULL;
+                }
+            }
+
+            eErr = ProcessLayer( hLayer, psOptions->hSRS != NULL, hDstDS, psOptions->anBandList,
+                          psOptions->adfBurnValues, psOptions->b3D, psOptions->bInverse, psOptions->pszBurnAttribute,
+                          psOptions->papszRasterizeOptions, psOptions->pfnProgress, psOptions->pProgressData );
+
+            GDALDatasetReleaseResultSet( hSrcDataset, hLayer );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create output file if necessary.                                */
+/* -------------------------------------------------------------------- */
+    int nLayerCount = (psOptions->pszSQL == NULL && psOptions->papszLayers == NULL) ? 1 : CSLCount(psOptions->papszLayers);
+
+    if (psOptions->bCreateOutput && hDstDS == NULL)
+    {
+        std::vector<OGRLayerH> ahLayers;
+
+        for( int i = 0; i < nLayerCount; i++ )
+        {
+            OGRLayerH hLayer;
+            if( psOptions->papszLayers )
+                hLayer = GDALDatasetGetLayerByName( hSrcDataset, psOptions->papszLayers[i] );
+            else
+                hLayer = GDALDatasetGetLayer(hSrcDataset, 0);
+            if( hLayer == NULL )
+            {
+                continue;
+            }
+            ahLayers.push_back(hLayer);
+        }
+
+        hDstDS = CreateOutputDataset(ahLayers, psOptions->hSRS,
+                                psOptions->bGotBounds, psOptions->sEnvelop,
+                                hDriver, pszDest,
+                                psOptions->nXSize, psOptions->nYSize, psOptions->dfXRes, psOptions->dfYRes,
+                                psOptions->bTargetAlignedPixels,
+                                static_cast<int>(psOptions->anBandList.size()), psOptions->eOutputType,
+                                psOptions->papszCreationOptions, psOptions->adfInitVals,
+                                psOptions->bNoDataSet, psOptions->dfNoData);
+        if( hDstDS == NULL )
+        {
+            GDALRasterizeOptionsFree(psOptionsToFree);
+            return NULL;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Process each layer.                                             */
+/* -------------------------------------------------------------------- */
+
+    for( int i = 0; i < nLayerCount; i++ )
+    {
+        OGRLayerH hLayer;
+        if( psOptions->papszLayers )
+            hLayer = GDALDatasetGetLayerByName( hSrcDataset, psOptions->papszLayers[i] );
+        else
+            hLayer = GDALDatasetGetLayer(hSrcDataset, 0);
+        if( hLayer == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Unable to find layer \"%s\", skipping.",
+                     psOptions->papszLayers ? psOptions->papszLayers[i] : "0" );
+            continue;
+        }
+
+        if( psOptions->pszWHERE )
+        {
+            if( OGR_L_SetAttributeFilter( hLayer, psOptions->pszWHERE ) != OGRERR_NONE )
+                break;
+        }
+
+        void *pScaledProgress;
+        pScaledProgress =
+            GDALCreateScaledProgress( 0.0, 1.0 * (i + 1) / nLayerCount,
+                                      psOptions->pfnProgress, psOptions->pProgressData );
+
+        eErr = ProcessLayer( hLayer, psOptions->hSRS != NULL, hDstDS, psOptions->anBandList,
+                      psOptions->adfBurnValues, psOptions->b3D, psOptions->bInverse, psOptions->pszBurnAttribute,
+                      psOptions->papszRasterizeOptions, GDALScaledProgress, pScaledProgress );
+
+        GDALDestroyScaledProgress( pScaledProgress );
+        if( eErr != CE_None )
+            break;
+    }
+
+    GDALRasterizeOptionsFree(psOptionsToFree);
+
+    if( eErr != CE_None )
+    {
+        if( bCloseOutDSOnError )
+            GDALClose(hDstDS);
+        return NULL;
+    }
+
+    return hDstDS;
+}
+
+/************************************************************************/
+/*                           GDALRasterizeOptionsNew()                  */
+/************************************************************************/
+
+/**
+ * Allocates a GDALRasterizeOptions struct.
+ *
+ * @param papszArgv NULL terminated list of options (potentially including filename and open options too), or NULL.
+ *                  The accepted options are the ones of the <a href="gdal_rasterize.html">gdal_rasterize</a> utility.
+ * @param psOptionsForBinary (output) may be NULL (and should generally be NULL),
+ *                           otherwise (gdal_translate_bin.cpp use case) must be allocated with
+ *                           GDALRasterizeOptionsForBinaryNew() prior to this function. Will be
+ *                           filled with potentially present filename, open options,...
+ * @return pointer to the allocated GDALRasterizeOptions struct. Must be freed with GDALRasterizeOptionsFree().
+ *
+ * @since GDAL 2.1
+ */
+
+GDALRasterizeOptions *GDALRasterizeOptionsNew(char** papszArgv,
+                                                      GDALRasterizeOptionsForBinary* psOptionsForBinary)
+{
+    GDALRasterizeOptions *psOptions = new GDALRasterizeOptions;
+
+    psOptions->pszFormat = CPLStrdup("GTiff");
+    psOptions->pfnProgress = GDALDummyProgress;
+    psOptions->pProgressData = NULL;
+    psOptions->bCreateOutput = FALSE;
+    psOptions->b3D = FALSE;
+    psOptions->bInverse = FALSE;
+    memset(&(psOptions->sEnvelop), 0, sizeof(psOptions->sEnvelop));
+    psOptions->papszCreationOptions = NULL;
+    psOptions->papszLayers = NULL;
+    psOptions->pszSQL = NULL;
+    psOptions->pszDialect = NULL;
+    psOptions->pszBurnAttribute = NULL;
+    psOptions->pszWHERE = NULL;
+    psOptions->papszRasterizeOptions = NULL;
+    psOptions->dfXRes = 0;
+    psOptions->dfYRes = 0;
+    psOptions->bCreateOutput = FALSE;
+    psOptions->eOutputType = GDT_Float64;
+    psOptions->bNoDataSet = FALSE;
+    psOptions->dfNoData = 0;
+    psOptions->bGotBounds = FALSE;
+    psOptions->nXSize = 0;
+    psOptions->nYSize = 0;
+    psOptions->hSRS = NULL;
+    psOptions->bTargetAlignedPixels = FALSE;
+
+/* -------------------------------------------------------------------- */
+/*      Handle command line arguments.                                  */
+/* -------------------------------------------------------------------- */
+    int argc = CSLCount(papszArgv);
+    for( int i = 0; i < argc; i++ )
+    {
+        if( EQUAL(papszArgv[i],"-of") && i < argc-1 )
+        {
+            ++i;
+            CPLFree(psOptions->pszFormat);
+            psOptions->pszFormat = CPLStrdup(papszArgv[i]);
+            psOptions->bCreateOutput = TRUE;
+            if( psOptionsForBinary )
+            {
+                psOptionsForBinary->bFormatExplicitlySet = TRUE;
+            }
+        }
+
+        else if( EQUAL(papszArgv[i],"-q") || EQUAL(papszArgv[i],"-quiet") )
+        {
+            if( psOptionsForBinary )
+                psOptionsForBinary->bQuiet = TRUE;
+        }
+
+        else if( EQUAL(papszArgv[i],"-a") && i < argc-1 )
+        {
+            CPLFree(psOptions->pszBurnAttribute);
+            psOptions->pszBurnAttribute = CPLStrdup(papszArgv[++i]);
+        }
+        else if( EQUAL(papszArgv[i],"-b") && i < argc-1 )
+        {
+            if (strchr(papszArgv[i+1], ' '))
+            {
+                char** papszTokens = CSLTokenizeString( papszArgv[i+1] );
+                char** papszIter = papszTokens;
+                while(papszIter && *papszIter)
+                {
+                    psOptions->anBandList.push_back(atoi(*papszIter));
+                    papszIter ++;
+                }
+                CSLDestroy(papszTokens);
+                i += 1;
+            }
+            else
+            {
+                while(i < argc-1 && ArgIsNumeric(papszArgv[i+1]))
+                {
+                    psOptions->anBandList.push_back(atoi(papszArgv[i+1]));
+                    i += 1;
+                }
+            }
+        }
+        else if( EQUAL(papszArgv[i],"-3d")  )
+        {
+            psOptions->b3D = TRUE;
+            psOptions->papszRasterizeOptions =
+                CSLSetNameValue( psOptions->papszRasterizeOptions, "BURN_VALUE_FROM", "Z");
+        }
+        else if( EQUAL(papszArgv[i],"-add")  )
+        {
+            psOptions->papszRasterizeOptions =
+                CSLSetNameValue( psOptions->papszRasterizeOptions, "MERGE_ALG", "ADD");
+        }
+        else if( EQUAL(papszArgv[i],"-chunkysize") && i < argc-1 )
+        {
+            psOptions->papszRasterizeOptions =
+                CSLSetNameValue( psOptions->papszRasterizeOptions, "CHUNKYSIZE",
+                                 papszArgv[++i] );
+        }
+        else if( EQUAL(papszArgv[i],"-i")  )
+        {
+            psOptions->bInverse = TRUE;
+        }
+        else if( EQUAL(papszArgv[i],"-at")  )
+        {
+            psOptions->papszRasterizeOptions =
+                CSLSetNameValue( psOptions->papszRasterizeOptions, "ALL_TOUCHED", "TRUE" );
+        }
+        else if( EQUAL(papszArgv[i],"-burn") && i < argc-1 )
+        {
+            if (strchr(papszArgv[i+1], ' '))
+            {
+                char** papszTokens = CSLTokenizeString( papszArgv[i+1] );
+                char** papszIter = papszTokens;
+                while(papszIter && *papszIter)
+                {
+                    psOptions->adfBurnValues.push_back(CPLAtof(*papszIter));
+                    papszIter ++;
+                }
+                CSLDestroy(papszTokens);
+                i += 1;
+            }
+            else
+            {
+                while(i < argc-1 && ArgIsNumeric(papszArgv[i+1]))
+                {
+                    psOptions->adfBurnValues.push_back(CPLAtof(papszArgv[i+1]));
+                    i += 1;
+                }
+            }
+        }
+        else if( EQUAL(papszArgv[i],"-where") && i < argc-1 )
+        {
+            CPLFree(psOptions->pszWHERE);
+            psOptions->pszWHERE = CPLStrdup(papszArgv[++i]);
+        }
+        else if( EQUAL(papszArgv[i],"-l") && i < argc-1 )
+        {
+            psOptions->papszLayers = CSLAddString( psOptions->papszLayers, papszArgv[++i] );
+        }
+        else if( EQUAL(papszArgv[i],"-sql") && i < argc-1 )
+        {
+            CPLFree(psOptions->pszSQL);
+            psOptions->pszSQL = CPLStrdup(papszArgv[++i]);
+        }
+        else if( EQUAL(papszArgv[i],"-dialect") && i < argc-1 )
+        {
+            CPLFree(psOptions->pszDialect);
+            psOptions->pszDialect = CPLStrdup(papszArgv[++i]);
+        }
+        else if( EQUAL(papszArgv[i],"-init") && i < argc - 1 )
+        {
+            if (strchr(papszArgv[i+1], ' '))
+            {
+                char** papszTokens = CSLTokenizeString( papszArgv[i+1] );
+                char** papszIter = papszTokens;
+                while(papszIter && *papszIter)
+                {
+                    psOptions->adfInitVals.push_back(CPLAtof(*papszIter));
+                    papszIter ++;
+                }
+                CSLDestroy(papszTokens);
+                i += 1;
+            }
+            else
+            {
+                while(i < argc-1 && ArgIsNumeric(papszArgv[i+1]))
+                {
+                    psOptions->adfInitVals.push_back(CPLAtof(papszArgv[i+1]));
+                    i += 1;
+                }
+            }
+            psOptions->bCreateOutput = TRUE;
+        }
+        else if( EQUAL(papszArgv[i],"-a_nodata") && i < argc - 1 )
+        {
+            psOptions->dfNoData = CPLAtof(papszArgv[i+1]);
+            psOptions->bNoDataSet = TRUE;
+            i += 1;
+            psOptions->bCreateOutput = TRUE;
+        }
+        else if( EQUAL(papszArgv[i],"-a_srs") && i < argc-1 )
+        {
+            OSRDestroySpatialReference(psOptions->hSRS);
+            psOptions->hSRS = OSRNewSpatialReference( NULL );
+
+            if( OSRSetFromUserInput(psOptions->hSRS, papszArgv[i+1]) != OGRERR_NONE )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Failed to process SRS definition: %s",
+                         papszArgv[i+1] );
+                GDALRasterizeOptionsFree(psOptions);
+                return NULL;
+            }
+
+            i++;
+            psOptions->bCreateOutput = TRUE;
+        }
+
+        else if( EQUAL(papszArgv[i],"-te") && i < argc - 4 )
+        {
+            psOptions->sEnvelop.MinX = CPLAtof(papszArgv[++i]);
+            psOptions->sEnvelop.MinY = CPLAtof(papszArgv[++i]);
+            psOptions->sEnvelop.MaxX = CPLAtof(papszArgv[++i]);
+            psOptions->sEnvelop.MaxY = CPLAtof(papszArgv[++i]);
+            psOptions->bGotBounds = TRUE;
+            psOptions->bCreateOutput = TRUE;
+        }
+        else if( EQUAL(papszArgv[i],"-a_ullr") && i < argc - 4 )
+        {
+            psOptions->sEnvelop.MinX = CPLAtof(papszArgv[++i]);
+            psOptions->sEnvelop.MaxY = CPLAtof(papszArgv[++i]);
+            psOptions->sEnvelop.MaxX = CPLAtof(papszArgv[++i]);
+            psOptions->sEnvelop.MinY = CPLAtof(papszArgv[++i]);
+            psOptions->bGotBounds = TRUE;
+            psOptions->bCreateOutput = TRUE;
+        }
+        else if( EQUAL(papszArgv[i],"-co") && i < argc-1 )
+        {
+            psOptions->papszCreationOptions = CSLAddString( psOptions->papszCreationOptions, papszArgv[++i] );
+            psOptions->bCreateOutput = TRUE;
+        }
+        else if( EQUAL(papszArgv[i],"-ot") && i < argc-1 )
+        {
+            int iType;
+
+            for( iType = 1; iType < GDT_TypeCount; iType++ )
+            {
+                if( GDALGetDataTypeName((GDALDataType)iType) != NULL
+                    && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
+                             papszArgv[i+1]) )
+                {
+                    psOptions->eOutputType = (GDALDataType) iType;
+                }
+            }
+
+            if( psOptions->eOutputType == GDT_Unknown )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Unknown output pixel type: %s", papszArgv[i+1] );
+                GDALRasterizeOptionsFree(psOptions);
+                return NULL;
+            }
+            i++;
+            psOptions->bCreateOutput = TRUE;
+        }
+        else if( (EQUAL(papszArgv[i],"-ts") || EQUAL(papszArgv[i],"-outsize")) && i < argc-2 )
+        {
+            psOptions->nXSize = atoi(papszArgv[++i]);
+            psOptions->nYSize = atoi(papszArgv[++i]);
+            if (psOptions->nXSize <= 0 || psOptions->nYSize <= 0)
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Wrong value for -outsize parameter.");
+                GDALRasterizeOptionsFree(psOptions);
+                return NULL;
+            }
+            psOptions->bCreateOutput = TRUE;
+        }
+        else if( EQUAL(papszArgv[i],"-tr") && i < argc-2 )
+        {
+            psOptions->dfXRes = CPLAtof(papszArgv[++i]);
+            psOptions->dfYRes = fabs(CPLAtof(papszArgv[++i]));
+            if( psOptions->dfXRes == 0 || psOptions->dfYRes == 0 )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Wrong value for -tr parameter.");
+                GDALRasterizeOptionsFree(psOptions);
+                return NULL;
+            }
+            psOptions->bCreateOutput = TRUE;
+        }
+        else if( EQUAL(papszArgv[i],"-tap") )
+        {
+            psOptions->bTargetAlignedPixels = TRUE;
+            psOptions->bCreateOutput = TRUE;
+        }
+
+        else if( papszArgv[i][0] == '-' )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unknown option name '%s'", papszArgv[i]);
+            GDALRasterizeOptionsFree(psOptions);
+            return NULL;
+        }
+        else if( psOptionsForBinary && psOptionsForBinary->pszSource == NULL )
+        {
+            psOptionsForBinary->pszSource = CPLStrdup(papszArgv[i]);
+        }
+        else if( psOptionsForBinary && psOptionsForBinary->pszDest == NULL )
+        {
+            psOptionsForBinary->pszDest = CPLStrdup(papszArgv[i]);
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Too many command options '%s'", papszArgv[i]);
+            GDALRasterizeOptionsFree(psOptions);
+            return NULL;
+        }
+    }
+
+    if( psOptions->adfBurnValues.size() == 0 &&
+        psOptions->pszBurnAttribute == NULL && !(psOptions->b3D) )
+    {
+        if( psOptionsForBinary == NULL )
+            psOptions->adfBurnValues.push_back(255);
+        else
+        {
+            CPLError(CE_Failure, CPLE_NotSupported, "At least one of -3d, -burn or -a required." );
+            GDALRasterizeOptionsFree(psOptions);
+            return NULL;
+        }
+    }
+
+    if( psOptions->bCreateOutput )
+    {
+        if( psOptions->dfXRes == 0 && psOptions->dfYRes == 0 && psOptions->nXSize == 0 && psOptions->nYSize == 0 )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported, "'-tr xres yres' or '-ts xsize ysize' is required." );
+            GDALRasterizeOptionsFree(psOptions);
+            return NULL;
+        }
+
+        if (psOptions->bTargetAlignedPixels && psOptions->dfXRes == 0 && psOptions->dfYRes == 0)
+        {
+            CPLError(CE_Failure, CPLE_NotSupported, "-tap option cannot be used without using -tr.");
+            GDALRasterizeOptionsFree(psOptions);
+            return NULL;;
+        }
+
+        if( psOptions->anBandList.size() != 0 )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported, "-b option cannot be used when creating a GDAL dataset." );
+            GDALRasterizeOptionsFree(psOptions);
+            return NULL;
+        }
+
+        int nBandCount = 1;
+
+        if (psOptions->adfBurnValues.size() != 0)
+            nBandCount = static_cast<int>(psOptions->adfBurnValues.size());
+
+        if ((int)psOptions->adfInitVals.size() > nBandCount)
+            nBandCount = static_cast<int>(psOptions->adfInitVals.size());
+
+        if (psOptions->adfInitVals.size() == 1)
+        {
+            for(int i=1;i<=nBandCount - 1;i++)
+                psOptions->adfInitVals.push_back( psOptions->adfInitVals[0] );
+        }
+
+        int i;
+        for(i=1;i<=nBandCount;i++)
+            psOptions->anBandList.push_back( i );
+    }
+    else
+    {
+        if( psOptions->anBandList.size() == 0 )
+            psOptions->anBandList.push_back( 1 );
+    }
+
+    if( psOptions->pszDialect != NULL && psOptions->pszWHERE != NULL && psOptions->pszSQL == NULL )
+    {
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "-dialect is ignored with -where. Use -sql instead" );
+    }
+
+    if( psOptionsForBinary )
+    {
+        psOptionsForBinary->bCreateOutput = psOptions->bCreateOutput;
+        psOptionsForBinary->pszFormat = CPLStrdup(psOptions->pszFormat);
+    }
+
+    return psOptions;
+}
+
+/************************************************************************/
+/*                       GDALRasterizeOptionsFree()                     */
+/************************************************************************/
+
+/**
+ * Frees the GDALRasterizeOptions struct.
+ *
+ * @param psOptions the options struct for GDALRasterize().
+ *
+ * @since GDAL 2.1
+ */
+
+void GDALRasterizeOptionsFree(GDALRasterizeOptions *psOptions)
+{
+    if( psOptions )
+    {
+        CPLFree(psOptions->pszFormat);
+        CSLDestroy(psOptions->papszCreationOptions);
+        CSLDestroy(psOptions->papszLayers);
+        CSLDestroy(psOptions->papszRasterizeOptions);
+        CPLFree(psOptions->pszSQL);
+        CPLFree(psOptions->pszDialect);
+        CPLFree(psOptions->pszBurnAttribute);
+        CPLFree(psOptions->pszWHERE);
+        OSRDestroySpatialReference(psOptions->hSRS);
+
+        delete psOptions;
+    }
+}
+
+/************************************************************************/
+/*                  GDALRasterizeOptionsSetProgress()                   */
+/************************************************************************/
+
+/**
+ * Set a progress function.
+ *
+ * @param psOptions the options struct for GDALRasterize().
+ * @param pfnProgress the progress callback.
+ * @param pProgressData the user data for the progress callback.
+ *
+ * @since GDAL 2.1
+ */
+
+void GDALRasterizeOptionsSetProgress( GDALRasterizeOptions *psOptions,
+                                      GDALProgressFunc pfnProgress, void *pProgressData )
+{
+    psOptions->pfnProgress = pfnProgress ? pfnProgress : GDALDummyProgress;
+    psOptions->pProgressData = pProgressData;
+}
diff --git a/apps/gdal_translate.cpp b/apps/gdal_translate.cpp
deleted file mode 100644
index d4f61c7..0000000
--- a/apps/gdal_translate.cpp
+++ /dev/null
@@ -1,2015 +0,0 @@
-/******************************************************************************
- * $Id: gdal_translate.cpp 29259 2015-05-28 22:21:55Z rouault $
- *
- * Project:  GDAL Utilities
- * Purpose:  GDAL Image Translator Program
- * Author:   Frank Warmerdam, warmerdam at pobox.com
- *
- ******************************************************************************
- * Copyright (c) 1998, 2002, Frank Warmerdam
- * Copyright (c) 2007-2014, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "cpl_vsi.h"
-#include "cpl_conv.h"
-#include "cpl_string.h"
-#include "gdal_priv.h"
-#include "ogr_spatialref.h"
-#include "vrtdataset.h"
-#include "commonutils.h"
-
-CPL_CVSID("$Id: gdal_translate.cpp 29259 2015-05-28 22:21:55Z rouault $");
-
-static int ArgIsNumeric( const char * );
-static void AttachMetadata( GDALDatasetH, char ** );
-static void CopyBandInfo( GDALRasterBand * poSrcBand, GDALRasterBand * poDstBand,
-                            int bCanCopyStatsMetadata, int bCopyScale, int bCopyNoData );
-static int bSubCall = FALSE;
-
-/*  ******************************************************************* */
-/*                               Usage()                                */
-/* ******************************************************************** */
-
-static void Usage(const char* pszErrorMsg = NULL, int bShort = TRUE)
-
-{
-    int	iDr;
-        
-    printf( "Usage: gdal_translate [--help-general] [--long-usage]\n"
-            "       [-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/\n"
-            "             CInt16/CInt32/CFloat32/CFloat64}] [-strict]\n"
-            "       [-of format] [-b band] [-mask band] [-expand {gray|rgb|rgba}]\n"
-            "       [-outsize xsize[%%]|0 ysize[%%]|0] [-tr xres yres]\n"
-            "       [-r {nearest,bilinear,cubic,cubicspline,lanczos,average,mode}]\n"
-            "       [-unscale] [-scale[_bn] [src_min src_max [dst_min dst_max]]]* [-exponent[_bn] exp_val]*\n"
-            "       [-srcwin xoff yoff xsize ysize] [-epo] [-eco]\n"
-            "       [-projwin ulx uly lrx lry] [-projwin_srs srs_def]\n"
-            "       [-a_srs srs_def] [-a_ullr ulx uly lrx lry] [-a_nodata value]\n"
-            "       [-gcp pixel line easting northing [elevation]]*\n" 
-            "       [-mo \"META-TAG=VALUE\"]* [-q] [-sds]\n"
-            "       [-co \"NAME=VALUE\"]* [-stats] [-norat]\n"
-            "       [-oo NAME=VALUE]*\n"
-            "       src_dataset dst_dataset\n" );
-
-    if( !bShort )
-    {
-        printf( "\n%s\n\n", GDALVersionInfo( "--version" ) );
-        printf( "The following format drivers are configured and support output:\n" );
-        for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
-        {
-            GDALDriverH hDriver = GDALGetDriver(iDr);
-            
-            if( GDALGetMetadataItem( hDriver, GDAL_DCAP_RASTER, NULL) != NULL &&
-                (GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) != NULL
-                || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY, NULL ) != NULL) )
-            {
-                printf( "  %s: %s\n",
-                        GDALGetDriverShortName( hDriver ),
-                        GDALGetDriverLongName( hDriver ) );
-            }
-        }
-    }
-
-    if( pszErrorMsg != NULL )
-        fprintf(stderr, "\nFAILURE: %s\n", pszErrorMsg);
-
-    exit(1);
-}
-
-/************************************************************************/
-/*                              SrcToDst()                              */
-/************************************************************************/
-
-static void SrcToDst( double dfX, double dfY,
-                      int nSrcXOff, int nSrcYOff,
-                      int nSrcXSize, int nSrcYSize,
-                      int nDstXOff, int nDstYOff,
-                      int nDstXSize, int nDstYSize,
-                      double &dfXOut, double &dfYOut )
-
-{
-    dfXOut = ((dfX - nSrcXOff) / nSrcXSize) * nDstXSize + nDstXOff;
-    dfYOut = ((dfY - nSrcYOff) / nSrcYSize) * nDstYSize + nDstYOff;
-}
-
-/************************************************************************/
-/*                          GetSrcDstWindow()                           */
-/************************************************************************/
-
-static int FixSrcDstWindow( int* panSrcWin, int* panDstWin,
-                            int nSrcRasterXSize,
-                            int nSrcRasterYSize )
-
-{
-    const int nSrcXOff = panSrcWin[0];
-    const int nSrcYOff = panSrcWin[1];
-    const int nSrcXSize = panSrcWin[2];
-    const int nSrcYSize = panSrcWin[3];
-
-    const int nDstXOff = panDstWin[0];
-    const int nDstYOff = panDstWin[1];
-    const int nDstXSize = panDstWin[2];
-    const int nDstYSize = panDstWin[3];
-
-    int bModifiedX = FALSE, bModifiedY = FALSE;
-
-    int nModifiedSrcXOff = nSrcXOff;
-    int nModifiedSrcYOff = nSrcYOff;
-
-    int nModifiedSrcXSize = nSrcXSize;
-    int nModifiedSrcYSize = nSrcYSize;
-
-/* -------------------------------------------------------------------- */
-/*      Clamp within the bounds of the available source data.           */
-/* -------------------------------------------------------------------- */
-    if( nModifiedSrcXOff < 0 )
-    {
-        nModifiedSrcXSize += nModifiedSrcXOff;
-        nModifiedSrcXOff = 0;
-
-        bModifiedX = TRUE;
-    }
-
-    if( nModifiedSrcYOff < 0 )
-    {
-        nModifiedSrcYSize += nModifiedSrcYOff;
-        nModifiedSrcYOff = 0;
-        bModifiedY = TRUE;
-    }
-
-    if( nModifiedSrcXOff + nModifiedSrcXSize > nSrcRasterXSize )
-    {
-        nModifiedSrcXSize = nSrcRasterXSize - nModifiedSrcXOff;
-        bModifiedX = TRUE;
-    }
-
-    if( nModifiedSrcYOff + nModifiedSrcYSize > nSrcRasterYSize )
-    {
-        nModifiedSrcYSize = nSrcRasterYSize - nModifiedSrcYOff;
-        bModifiedY = TRUE;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Don't do anything if the requesting region is completely off    */
-/*      the source image.                                               */
-/* -------------------------------------------------------------------- */
-    if( nModifiedSrcXOff >= nSrcRasterXSize
-        || nModifiedSrcYOff >= nSrcRasterYSize
-        || nModifiedSrcXSize <= 0 || nModifiedSrcYSize <= 0 )
-    {
-        return FALSE;
-    }
-
-    panSrcWin[0] = nModifiedSrcXOff;
-    panSrcWin[1] = nModifiedSrcYOff;
-    panSrcWin[2] = nModifiedSrcXSize;
-    panSrcWin[3] = nModifiedSrcYSize;
-
-/* -------------------------------------------------------------------- */
-/*      If we haven't had to modify the source rectangle, then the      */
-/*      destination rectangle must be the whole region.                 */
-/* -------------------------------------------------------------------- */
-    if( !bModifiedX && !bModifiedY )
-        return TRUE;
-
-/* -------------------------------------------------------------------- */
-/*      Now transform this possibly reduced request back into the       */
-/*      destination buffer coordinates in case the output region is     */
-/*      less than the whole buffer.                                     */
-/* -------------------------------------------------------------------- */
-    double dfDstULX, dfDstULY, dfDstLRX, dfDstLRY;
-
-    SrcToDst( nModifiedSrcXOff, nModifiedSrcYOff,
-              nSrcXOff, nSrcYOff,
-              nSrcXSize, nSrcYSize,
-              nDstXOff, nDstYOff,
-              nDstXSize, nDstYSize,
-              dfDstULX, dfDstULY );
-    SrcToDst( nModifiedSrcXOff + nModifiedSrcXSize, nModifiedSrcYOff + nModifiedSrcYSize,
-              nSrcXOff, nSrcYOff,
-              nSrcXSize, nSrcYSize,
-              nDstXOff, nDstYOff,
-              nDstXSize, nDstYSize,
-              dfDstLRX, dfDstLRY );
-
-    int nModifiedDstXOff = nDstXOff;
-    int nModifiedDstYOff = nDstYOff;
-    int nModifiedDstXSize = nDstXSize;
-    int nModifiedDstYSize = nDstYSize;
-
-    if( bModifiedX )
-    {
-        nModifiedDstXOff = (int) ((dfDstULX - nDstXOff)+0.001);
-        nModifiedDstXSize = (int) ((dfDstLRX - nDstXOff)+0.001)
-            - nModifiedDstXOff;
-
-        nModifiedDstXOff = MAX(0,nModifiedDstXOff);
-        if( nModifiedDstXOff + nModifiedDstXSize > nDstXSize )
-            nModifiedDstXSize = nDstXSize - nModifiedDstXOff;
-    }
-
-    if( bModifiedY )
-    {
-        nModifiedDstYOff = (int) ((dfDstULY - nDstYOff)+0.001);
-        nModifiedDstYSize = (int) ((dfDstLRY - nDstYOff)+0.001)
-            - nModifiedDstYOff;
-
-        nModifiedDstYOff = MAX(0,nModifiedDstYOff);
-        if( nModifiedDstYOff + nModifiedDstYSize > nDstYSize )
-            nModifiedDstYSize = nDstYSize - nModifiedDstYOff;
-    }
-
-    if( nModifiedDstXSize < 1 || nModifiedDstYSize < 1 )
-        return FALSE;
-    else
-    {
-        panDstWin[0] = nModifiedDstXOff;
-        panDstWin[1] = nModifiedDstYOff;
-        panDstWin[2] = nModifiedDstXSize;
-        panDstWin[3] = nModifiedDstYSize;
-
-        return TRUE;
-    }
-}
-
-/************************************************************************/
-/*                             ProxyMain()                              */
-/************************************************************************/
-
-enum
-{
-    MASK_DISABLED,
-    MASK_AUTO,
-    MASK_USER
-};
-
-#define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg) \
-    do { if (i + nExtraArg >= argc) \
-        Usage(CPLSPrintf("%s option requires %d argument(s)", argv[i], nExtraArg)); } while(0)
-
-
-typedef struct
-{
-    int     bScale;
-    int     bHaveScaleSrc;
-    double  dfScaleSrcMin, dfScaleSrcMax;
-    double  dfScaleDstMin, dfScaleDstMax;
-} ScaleParams;
-
-static int ProxyMain( int argc, char ** argv )
-
-{
-    GDALDatasetH	hDataset, hOutDS;
-    int			i;
-    int			nRasterXSize, nRasterYSize;
-    const char		*pszSource=NULL, *pszDest=NULL, *pszFormat = "GTiff";
-    int bFormatExplicitlySet = FALSE;
-    GDALDriverH		hDriver;
-    int			*panBandList = NULL; /* negative value of panBandList[i] means mask band of ABS(panBandList[i]) */
-    int         nBandCount = 0, bDefBands = TRUE;
-    double		adfGeoTransform[6];
-    GDALDataType	eOutputType = GDT_Unknown;
-    int			nOXSize = 0, nOYSize = 0;
-    char		*pszOXSize=NULL, *pszOYSize=NULL;
-    char                **papszCreateOptions = NULL;
-    int                 anSrcWin[4], bStrict = FALSE;
-    const char          *pszProjection;
-
-    int                 bUnscale=FALSE;
-    int                 nScaleRepeat = 0;
-    ScaleParams        *pasScaleParams = NULL;
-    int                 bHasUsedExplictScaleBand = FALSE;
-    int                 nExponentRepeat = 0;
-    double             *padfExponent = NULL;
-    int                 bHasUsedExplictExponentBand = FALSE;
-
-    double              dfULX, dfULY, dfLRX, dfLRY;
-    char                **papszMetadataOptions = NULL;
-    char                *pszOutputSRS = NULL;
-    int                 bQuiet = FALSE, bGotBounds = FALSE;
-    GDALProgressFunc    pfnProgress = GDALTermProgress;
-    int                 nGCPCount = 0;
-    GDAL_GCP            *pasGCPs = NULL;
-    int                 iSrcFileArg = -1, iDstFileArg = -1;
-    int                 bCopySubDatasets = FALSE;
-    double              adfULLR[4] = { 0,0,0,0 };
-    int                 bSetNoData = FALSE;
-    int                 bUnsetNoData = FALSE;
-    double		dfNoDataReal = 0.0;
-    int                 nRGBExpand = 0;
-    int                 bParsedMaskArgument = FALSE;
-    int                 eMaskMode = MASK_AUTO;
-    int                 nMaskBand = 0; /* negative value means mask band of ABS(nMaskBand) */
-    int                 bStats = FALSE, bApproxStats = FALSE;
-    int                 bErrorOnPartiallyOutside = FALSE;
-    int                 bErrorOnCompletelyOutside = FALSE;
-    int                 bNoRAT = FALSE;
-    char              **papszOpenOptions = NULL;
-    const char         *pszResampling = NULL;
-    double              dfXRes = 0.0, dfYRes = 0.0;
-    CPLString           osProjSRS;
-
-    anSrcWin[0] = 0;
-    anSrcWin[1] = 0;
-    anSrcWin[2] = 0;
-    anSrcWin[3] = 0;
-
-    dfULX = dfULY = dfLRX = dfLRY = 0.0;
-    
-    /* Check strict compilation and runtime library version as we use C++ API */
-    if (! GDAL_CHECK_VERSION(argv[0]))
-        exit(1);
-
-    EarlySetConfigOptions(argc, argv);
-
-/* -------------------------------------------------------------------- */
-/*      Register standard GDAL drivers, and process generic GDAL        */
-/*      command options.                                                */
-/* -------------------------------------------------------------------- */
-    GDALAllRegister();
-    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
-    if( argc < 1 )
-        exit( -argc );
-
-/* -------------------------------------------------------------------- */
-/*      Set optimal setting for best performance with huge input VRT.   */
-/*      The rationale for 450 is that typical Linux process allow       */
-/*      only 1024 file descriptors per process and we need to keep some */
-/*      spare for shared libraries, etc. so let's go down to 900.       */
-/*      And some datasets may need 2 file descriptors, so divide by 2   */
-/*      for security.                                                   */
-/* -------------------------------------------------------------------- */
-    if( CPLGetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", NULL) == NULL )
-    {
-        CPLSetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", "450");
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Handle command line arguments.                                  */
-/* -------------------------------------------------------------------- */
-    for( i = 1; i < argc; i++ )
-    {
-        if( EQUAL(argv[i], "--utility_version") )
-        {
-            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
-                   argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
-            return 0;
-        }
-        else if( EQUAL(argv[i],"--help") )
-            Usage();
-        else if ( EQUAL(argv[i], "--long-usage") )
-        {
-            Usage(NULL, FALSE);
-        }
-        else if( EQUAL(argv[i],"-of") && i < argc-1 )
-        {
-            pszFormat = argv[++i];
-            bFormatExplicitlySet = TRUE;
-        }
-
-        else if( EQUAL(argv[i],"-q") || EQUAL(argv[i],"-quiet") )
-        {
-            bQuiet = TRUE;
-            pfnProgress = GDALDummyProgress;
-        }
-
-        else if( EQUAL(argv[i],"-ot") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            int	iType;
-            
-            for( iType = 1; iType < GDT_TypeCount; iType++ )
-            {
-                if( GDALGetDataTypeName((GDALDataType)iType) != NULL
-                    && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
-                             argv[i+1]) )
-                {
-                    eOutputType = (GDALDataType) iType;
-                }
-            }
-
-            if( eOutputType == GDT_Unknown )
-            {
-                Usage(CPLSPrintf("Unknown output pixel type: %s.", argv[i+1] ));
-            }
-            i++;
-        }
-        else if( EQUAL(argv[i],"-b") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            const char* pszBand = argv[i+1];
-            int bMask = FALSE;
-            if (EQUAL(pszBand, "mask"))
-                pszBand = "mask,1";
-            if (EQUALN(pszBand, "mask,", 5))
-            {
-                bMask = TRUE;
-                pszBand += 5;
-                /* If we use tha source mask band as a regular band */
-                /* don't create a target mask band by default */
-                if( !bParsedMaskArgument )
-                    eMaskMode = MASK_DISABLED;
-            }
-            int nBand = atoi(pszBand);
-            if( nBand < 1 )
-            {
-                Usage(CPLSPrintf( "Unrecognizable band number (%s).", argv[i+1] ));
-            }
-            i++;
-
-            nBandCount++;
-            panBandList = (int *) 
-                CPLRealloc(panBandList, sizeof(int) * nBandCount);
-            panBandList[nBandCount-1] = nBand;
-            if (bMask)
-                panBandList[nBandCount-1] *= -1;
-
-            if( panBandList[nBandCount-1] != nBandCount )
-                bDefBands = FALSE;
-        }
-        else if( EQUAL(argv[i],"-mask") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            bParsedMaskArgument = TRUE;
-            const char* pszBand = argv[i+1];
-            if (EQUAL(pszBand, "none"))
-            {
-                eMaskMode = MASK_DISABLED;
-            }
-            else if (EQUAL(pszBand, "auto"))
-            {
-                eMaskMode = MASK_AUTO;
-            }
-            else
-            {
-                int bMask = FALSE;
-                if (EQUAL(pszBand, "mask"))
-                    pszBand = "mask,1";
-                if (EQUALN(pszBand, "mask,", 5))
-                {
-                    bMask = TRUE;
-                    pszBand += 5;
-                }
-                int nBand = atoi(pszBand);
-                if( nBand < 1 )
-                {
-                    Usage(CPLSPrintf( "Unrecognizable band number (%s).", argv[i+1] ));
-                }
-                
-                eMaskMode = MASK_USER;
-                nMaskBand = nBand;
-                if (bMask)
-                    nMaskBand *= -1;
-            }
-            i ++;
-        }
-        else if( EQUAL(argv[i],"-not_strict")  )
-            bStrict = FALSE;
-            
-        else if( EQUAL(argv[i],"-strict")  )
-            bStrict = TRUE;
-            
-        else if( EQUAL(argv[i],"-sds")  )
-            bCopySubDatasets = TRUE;
-            
-        else if( EQUAL(argv[i],"-gcp") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(4);
-            char* endptr = NULL;
-            /* -gcp pixel line easting northing [elev] */
-
-            nGCPCount++;
-            pasGCPs = (GDAL_GCP *) 
-                CPLRealloc( pasGCPs, sizeof(GDAL_GCP) * nGCPCount );
-            GDALInitGCPs( 1, pasGCPs + nGCPCount - 1 );
-
-            pasGCPs[nGCPCount-1].dfGCPPixel = CPLAtofM(argv[++i]);
-            pasGCPs[nGCPCount-1].dfGCPLine = CPLAtofM(argv[++i]);
-            pasGCPs[nGCPCount-1].dfGCPX = CPLAtofM(argv[++i]);
-            pasGCPs[nGCPCount-1].dfGCPY = CPLAtofM(argv[++i]);
-            if( argv[i+1] != NULL 
-                && (CPLStrtod(argv[i+1], &endptr) != 0.0 || argv[i+1][0] == '0') )
-            {
-                /* Check that last argument is really a number and not a filename */
-                /* looking like a number (see ticket #863) */
-                if (endptr && *endptr == 0)
-                    pasGCPs[nGCPCount-1].dfGCPZ = CPLAtofM(argv[++i]);
-            }
-
-            /* should set id and info? */
-        }   
-
-        else if( EQUAL(argv[i],"-a_nodata") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            if (EQUAL(argv[i+1], "none"))
-            {
-                bUnsetNoData = TRUE;
-            }
-            else
-            {
-                bSetNoData = TRUE;
-                dfNoDataReal = CPLAtofM(argv[i+1]);
-            }
-            i += 1;
-        }   
-
-        else if( EQUAL(argv[i],"-a_ullr") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(4);
-            adfULLR[0] = CPLAtofM(argv[i+1]);
-            adfULLR[1] = CPLAtofM(argv[i+2]);
-            adfULLR[2] = CPLAtofM(argv[i+3]);
-            adfULLR[3] = CPLAtofM(argv[i+4]);
-
-            bGotBounds = TRUE;
-            
-            i += 4;
-        }   
-
-        else if( EQUAL(argv[i],"-co") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            papszCreateOptions = CSLAddString( papszCreateOptions, argv[++i] );
-        }   
-
-        else if( EQUAL(argv[i],"-scale") || EQUALN(argv[i],"-scale_", 7) )
-        {
-            int nIndex = 0;
-            if( EQUALN(argv[i],"-scale_", 7) )
-            {
-                if( !bHasUsedExplictScaleBand && nScaleRepeat != 0 )
-                    Usage("Cannot mix -scale and -scale_XX syntax");
-                bHasUsedExplictScaleBand = TRUE;
-                nIndex = atoi(argv[i] + 7);
-                if( nIndex <= 0 || nIndex > 65535 )
-                    Usage(CPLSPrintf( "Invalid parameter name: %s", argv[i] ));
-                nIndex --;
-            }
-            else
-            {
-                if( bHasUsedExplictScaleBand )
-                    Usage("Cannot mix -scale and -scale_XX syntax");
-                nIndex = nScaleRepeat;
-            }
-
-            if( nIndex >= nScaleRepeat )
-            {
-                pasScaleParams = (ScaleParams*)CPLRealloc(pasScaleParams,
-                    (nIndex + 1) * sizeof(ScaleParams));
-                if( nIndex > nScaleRepeat )
-                    memset(pasScaleParams + nScaleRepeat, 0,
-                        sizeof(ScaleParams) * (nIndex - nScaleRepeat));
-                nScaleRepeat = nIndex + 1;
-            }
-            pasScaleParams[nIndex].bScale = TRUE;
-            if( i < argc-2 && ArgIsNumeric(argv[i+1]) )
-            {
-                pasScaleParams[nIndex].bHaveScaleSrc = TRUE;
-                pasScaleParams[nIndex].dfScaleSrcMin = CPLAtofM(argv[i+1]);
-                pasScaleParams[nIndex].dfScaleSrcMax = CPLAtofM(argv[i+2]);
-                i += 2;
-            }
-            if( i < argc-2 && pasScaleParams[nIndex].bHaveScaleSrc && ArgIsNumeric(argv[i+1]) )
-            {
-                pasScaleParams[nIndex].dfScaleDstMin = CPLAtofM(argv[i+1]);
-                pasScaleParams[nIndex].dfScaleDstMax = CPLAtofM(argv[i+2]);
-                i += 2;
-            }
-            else
-            {
-                pasScaleParams[nIndex].dfScaleDstMin = 0.0;
-                pasScaleParams[nIndex].dfScaleDstMax = 255.999;
-            }
-        }
-
-        else if( EQUAL(argv[i],"-exponent") || EQUALN(argv[i],"-exponent_",10) )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-
-            int nIndex = 0;
-            if( EQUALN(argv[i],"-exponent_", 10) )
-            {
-                if( !bHasUsedExplictExponentBand && nExponentRepeat != 0 )
-                    Usage("Cannot mix -exponent and -exponent_XX syntax");
-                bHasUsedExplictExponentBand = TRUE;
-                nIndex = atoi(argv[i] + 10);
-                if( nIndex <= 0 || nIndex > 65535 )
-                    Usage(CPLSPrintf( "Invalid parameter name: %s", argv[i] ));
-                nIndex --;
-            }
-            else
-            {
-                if( bHasUsedExplictExponentBand )
-                    Usage("Cannot mix -exponent and -exponent_XX syntax");
-                nIndex = nExponentRepeat;
-            }
-
-            if( nIndex >= nExponentRepeat )
-            {
-                padfExponent = (double*)CPLRealloc(padfExponent,
-                    (nIndex + 1) * sizeof(double));
-                if( nIndex > nExponentRepeat )
-                    memset(padfExponent + nExponentRepeat, 0,
-                        sizeof(double) * (nIndex - nExponentRepeat));
-                nExponentRepeat = nIndex + 1;
-            }
-            double dfExponent = CPLAtofM(argv[++i]);
-            padfExponent[nIndex] = dfExponent;
-        }
-
-        else if( EQUAL(argv[i], "-unscale") )
-        {
-            bUnscale = TRUE;
-        }
-
-        else if( EQUAL(argv[i],"-mo") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            papszMetadataOptions = CSLAddString( papszMetadataOptions,
-                                                 argv[++i] );
-        }
-
-        else if( EQUAL(argv[i],"-outsize") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2);
-            pszOXSize = argv[++i];
-            pszOYSize = argv[++i];
-        }
-        
-        else if( EQUAL(argv[i],"-tr") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2);
-            dfXRes = CPLAtofM(argv[++i]);
-            dfYRes = fabs(CPLAtofM(argv[++i]));
-            if( dfXRes == 0 || dfYRes == 0 )
-            {
-                Usage("Wrong value for -tr parameters.");
-            }
-        }
-
-        else if( EQUAL(argv[i],"-srcwin") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(4);
-            anSrcWin[0] = atoi(argv[++i]);
-            anSrcWin[1] = atoi(argv[++i]);
-            anSrcWin[2] = atoi(argv[++i]);
-            anSrcWin[3] = atoi(argv[++i]);
-        }   
-
-        else if( EQUAL(argv[i],"-projwin") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(4);
-            dfULX = CPLAtofM(argv[++i]);
-            dfULY = CPLAtofM(argv[++i]);
-            dfLRX = CPLAtofM(argv[++i]);
-            dfLRY = CPLAtofM(argv[++i]);
-        }   
-        
-        else if( EQUAL(argv[i],"-projwin_srs") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            OGRSpatialReference oSRS;
-
-            if( oSRS.SetFromUserInput( argv[i+1] ) != OGRERR_NONE )
-            {
-                fprintf( stderr, "Failed to process SRS definition: %s\n", 
-                         argv[i+1] );
-                GDALDestroyDriverManager();
-                exit( 1 );
-            }
-
-            char* pszSRS = NULL;
-            oSRS.exportToWkt( &pszSRS );
-            if( pszSRS )
-                osProjSRS = pszSRS;
-            i++;
-        }
-
-        else if( EQUAL(argv[i],"-epo") )
-        {
-            bErrorOnPartiallyOutside = TRUE;
-            bErrorOnCompletelyOutside = TRUE;
-        }
-
-        else  if( EQUAL(argv[i],"-eco") )
-        {
-            bErrorOnCompletelyOutside = TRUE;
-        }
-    
-        else if( EQUAL(argv[i],"-a_srs") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            OGRSpatialReference oOutputSRS;
-
-            if( oOutputSRS.SetFromUserInput( argv[i+1] ) != OGRERR_NONE )
-            {
-                fprintf( stderr, "Failed to process SRS definition: %s\n", 
-                         argv[i+1] );
-                GDALDestroyDriverManager();
-                exit( 1 );
-            }
-
-            oOutputSRS.exportToWkt( &pszOutputSRS );
-            i++;
-        }   
-
-        else if( EQUAL(argv[i],"-expand") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            if (EQUAL(argv[i+1], "gray"))
-                nRGBExpand = 1;
-            else if (EQUAL(argv[i+1], "rgb"))
-                nRGBExpand = 3;
-            else if (EQUAL(argv[i+1], "rgba"))
-                nRGBExpand = 4;
-            else
-            {
-                Usage(CPLSPrintf( "Value %s unsupported. Only gray, rgb or rgba are supported.", 
-                    argv[i] ));
-            }
-            i++;
-        }
-
-        else if( EQUAL(argv[i], "-stats") )
-        {
-            bStats = TRUE;
-            bApproxStats = FALSE;
-        }
-        else if( EQUAL(argv[i], "-approx_stats") )
-        {
-            bStats = TRUE;
-            bApproxStats = TRUE;
-        }
-        else if( EQUAL(argv[i], "-norat") )
-        {
-            bNoRAT = TRUE;
-        }
-        else if( EQUAL(argv[i], "-oo") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            papszOpenOptions = CSLAddString( papszOpenOptions,
-                                                argv[++i] );
-        }
-        else if( EQUAL(argv[i],"-r") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszResampling = argv[++i];
-        }  
-        else if( argv[i][0] == '-' )
-        {
-            Usage(CPLSPrintf("Unknown option name '%s'", argv[i]));
-        }
-        else if( pszSource == NULL )
-        {
-            iSrcFileArg = i;
-            pszSource = argv[i];
-        }
-        else if( pszDest == NULL )
-        {
-            pszDest = argv[i];
-            iDstFileArg = i;
-        }
-
-        else
-        {
-            Usage("Too many command options.");
-        }
-    }
-
-    if( pszDest == NULL )
-    {
-        if( pszSource == NULL )
-            Usage("No source dataset specified.");
-        else
-            Usage("No target dataset specified.");
-    }
-
-    if ( strcmp(pszSource, pszDest) == 0)
-    {
-        Usage("Source and destination datasets must be different.");
-    }
-
-    if( strcmp(pszDest, "/vsistdout/") == 0)
-    {
-        bQuiet = TRUE;
-        pfnProgress = GDALDummyProgress;
-    }
-
-    if (!bQuiet && !bFormatExplicitlySet)
-        CheckExtensionConsistency(pszDest, pszFormat);
-/* -------------------------------------------------------------------- */
-/*      Check that incompatible options are not used                    */
-/* -------------------------------------------------------------------- */
-
-    if( pszOXSize != NULL && (dfXRes != 0 && dfYRes != 0) )
-    {
-        Usage("-outsize and -tr options cannot be used at the same time.");
-    }
-    if( bGotBounds &&  (dfXRes != 0 && dfYRes != 0) )
-    {
-        Usage("-a_ullr and -tr options cannot be used at the same time.");
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Attempt to open source file.                                    */
-/* -------------------------------------------------------------------- */
-
-    hDataset = GDALOpenEx( pszSource, GDAL_OF_RASTER, NULL,
-                           (const char* const* )papszOpenOptions, NULL );
-    
-    if( hDataset == NULL )
-    {
-        fprintf( stderr,
-                 "GDALOpen failed - %d\n%s\n",
-                 CPLGetLastErrorNo(), CPLGetLastErrorMsg() );
-        GDALDestroyDriverManager();
-        exit( 1 );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Handle subdatasets.                                             */
-/* -------------------------------------------------------------------- */
-    if( !bCopySubDatasets 
-        && CSLCount(GDALGetMetadata( hDataset, "SUBDATASETS" )) > 0 
-        && GDALGetRasterCount(hDataset) == 0 )
-    {
-        fprintf( stderr,
-                 "Input file contains subdatasets. Please, select one of them for reading.\n" );
-        GDALClose( hDataset );
-        GDALDestroyDriverManager();
-        exit( 1 );
-    }
-
-    if( CSLCount(GDALGetMetadata( hDataset, "SUBDATASETS" )) > 0 
-        && bCopySubDatasets )
-    {
-        char **papszSubdatasets = GDALGetMetadata(hDataset,"SUBDATASETS");
-        char *pszSubDest = (char *) CPLMalloc(strlen(pszDest)+32);
-        int i;
-        int bOldSubCall = bSubCall;
-        char** papszDupArgv = CSLDuplicate(argv);
-        int nRet = 0;
-
-        CPLString osPath = CPLGetPath(pszDest);
-        CPLString osBasename = CPLGetBasename(pszDest);
-        CPLString osExtension = CPLGetExtension(pszDest);
-        CPLString osTemp;
-
-        const char* pszFormat = NULL;
-        if ( CSLCount(papszSubdatasets)/2 < 10 )
-        {
-            pszFormat = "%s_%d";
-        }
-        else if ( CSLCount(papszSubdatasets)/2 < 100 )
-        {
-            pszFormat = "%s_%002d";
-        }
-        else
-        {
-            pszFormat = "%s_%003d";
-        }
-
-        CPLFree(papszDupArgv[iDstFileArg]);
-        papszDupArgv[iDstFileArg] = pszSubDest;
-        bSubCall = TRUE;
-        for( i = 0; papszSubdatasets[i] != NULL; i += 2 )
-        {
-            CPLFree(papszDupArgv[iSrcFileArg]);
-            papszDupArgv[iSrcFileArg] = CPLStrdup(strstr(papszSubdatasets[i],"=")+1);
-            osTemp = CPLSPrintf( pszFormat, osBasename.c_str(), i/2 + 1 );
-            osTemp = CPLFormFilename( osPath, osTemp, osExtension ); 
-            strcpy( pszSubDest, osTemp.c_str() );
-            nRet = ProxyMain( argc, papszDupArgv );
-            if (nRet != 0)
-                break;
-        }
-        CSLDestroy(papszDupArgv);
-
-        bSubCall = bOldSubCall;
-        CSLDestroy(argv);
-
-        GDALClose( hDataset );
-
-        if( !bSubCall )
-        {
-            GDALDumpOpenDatasets( stderr );
-            GDALDestroyDriverManager();
-        }
-        return nRet;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Collect some information from the source file.                  */
-/* -------------------------------------------------------------------- */
-    nRasterXSize = GDALGetRasterXSize( hDataset );
-    nRasterYSize = GDALGetRasterYSize( hDataset );
-
-    if( !bQuiet )
-        printf( "Input file size is %d, %d\n", nRasterXSize, nRasterYSize );
-
-    if( anSrcWin[2] == 0 && anSrcWin[3] == 0 )
-    {
-        anSrcWin[2] = nRasterXSize;
-        anSrcWin[3] = nRasterYSize;
-    }
-
-/* -------------------------------------------------------------------- */
-/*	Build band list to translate					*/
-/* -------------------------------------------------------------------- */
-    if( nBandCount == 0 )
-    {
-        nBandCount = GDALGetRasterCount( hDataset );
-        if( nBandCount == 0 )
-        {
-            fprintf( stderr, "Input file has no bands, and so cannot be translated.\n" );
-            GDALDestroyDriverManager();
-            exit(1 );
-        }
-
-        panBandList = (int *) CPLMalloc(sizeof(int)*nBandCount);
-        for( i = 0; i < nBandCount; i++ )
-            panBandList[i] = i+1;
-    }
-    else
-    {
-        for( i = 0; i < nBandCount; i++ )
-        {
-            if( ABS(panBandList[i]) > GDALGetRasterCount(hDataset) )
-            {
-                fprintf( stderr, 
-                         "Band %d requested, but only bands 1 to %d available.\n",
-                         ABS(panBandList[i]), GDALGetRasterCount(hDataset) );
-                GDALDestroyDriverManager();
-                exit( 2 );
-            }
-        }
-
-        if( nBandCount != GDALGetRasterCount( hDataset ) )
-            bDefBands = FALSE;
-    }
-
-    if( nScaleRepeat > nBandCount )
-    {
-        if( !bHasUsedExplictScaleBand )
-            Usage("-scale has been specified more times than the number of output bands");
-        else
-            Usage("-scale_XX has been specified with XX greater than the number of output bands");
-    }
-
-    if( nExponentRepeat > nBandCount )
-    {
-        if( !bHasUsedExplictExponentBand )
-            Usage("-exponent has been specified more times than the number of output bands");
-        else
-            Usage("-exponent_XX has been specified with XX greater than the number of output bands");
-    }
-/* -------------------------------------------------------------------- */
-/*      Compute the source window from the projected source window      */
-/*      if the projected coordinates were provided.  Note that the      */
-/*      projected coordinates are in ulx, uly, lrx, lry format,         */
-/*      while the anSrcWin is xoff, yoff, xsize, ysize with the         */
-/*      xoff,yoff being the ulx, uly in pixel/line.                     */
-/* -------------------------------------------------------------------- */
-    if( dfULX != 0.0 || dfULY != 0.0 
-        || dfLRX != 0.0 || dfLRY != 0.0 )
-    {
-        double	adfGeoTransform[6];
-
-        GDALGetGeoTransform( hDataset, adfGeoTransform );
-
-        if( adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0 )
-        {
-            fprintf( stderr, 
-                     "The -projwin option was used, but the geotransform is\n"
-                     "rotated.  This configuration is not supported.\n" );
-            GDALClose( hDataset );
-            CPLFree( panBandList );
-            GDALDestroyDriverManager();
-            exit( 1 );
-        }
-
-        if( osProjSRS.size() )
-        {
-            pszProjection = GDALGetProjectionRef( hDataset );
-            if( pszProjection != NULL && strlen(pszProjection) > 0 )
-            {
-                OGRSpatialReference oSRSIn;
-                OGRSpatialReference oSRSDS;
-                oSRSIn.SetFromUserInput(osProjSRS);
-                oSRSDS.SetFromUserInput(pszProjection);
-                if( !oSRSIn.IsSame(&oSRSDS) )
-                {
-                    OGRCoordinateTransformation* poCT = OGRCreateCoordinateTransformation(&oSRSIn, &oSRSDS);
-                    if( !(poCT &&
-                        poCT->Transform(1, &dfULX, &dfULY) &&
-                        poCT->Transform(1, &dfLRX, &dfLRY)) )
-                    {
-                        OGRCoordinateTransformation::DestroyCT(poCT);
-
-                        fprintf( stderr, "-projwin_srs ignored since coordinate transformation failed.\n");
-                        GDALClose( hDataset );
-                        CPLFree( panBandList );
-                        GDALDestroyDriverManager();
-                        exit( 1 );
-                    }
-                    delete poCT;
-                }
-            }
-            else
-            {
-                fprintf( stderr, "-projwin_srs ignored since the dataset has no projection.\n");
-            }
-        }
-
-        anSrcWin[0] = (int) 
-            floor((dfULX - adfGeoTransform[0]) / adfGeoTransform[1] + 0.001);
-        anSrcWin[1] = (int) 
-            floor((dfULY - adfGeoTransform[3]) / adfGeoTransform[5] + 0.001);
-
-        anSrcWin[2] = (int) ((dfLRX - dfULX) / adfGeoTransform[1] + 0.5);
-        anSrcWin[3] = (int) ((dfLRY - dfULY) / adfGeoTransform[5] + 0.5);
-
-        if( !bQuiet )
-            fprintf( stdout, 
-                     "Computed -srcwin %d %d %d %d from projected window.\n",
-                     anSrcWin[0], 
-                     anSrcWin[1], 
-                     anSrcWin[2], 
-                     anSrcWin[3] );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Verify source window dimensions.                                */
-/* -------------------------------------------------------------------- */
-    if( anSrcWin[2] <= 0 || anSrcWin[3] <= 0 )
-    {
-        fprintf( stderr,
-                 "Error: %s-srcwin %d %d %d %d has negative width and/or height.\n",
-                 ( dfULX != 0.0 || dfULY != 0.0 || dfLRX != 0.0 || dfLRY != 0.0 ) ? "Computed " : "",
-                 anSrcWin[0],
-                 anSrcWin[1],
-                 anSrcWin[2],
-                 anSrcWin[3] );
-        exit( 1 );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Verify source window dimensions.                                */
-/* -------------------------------------------------------------------- */
-    else if( anSrcWin[0] < 0 || anSrcWin[1] < 0 
-        || anSrcWin[0] + anSrcWin[2] > GDALGetRasterXSize(hDataset)
-        || anSrcWin[1] + anSrcWin[3] > GDALGetRasterYSize(hDataset) )
-    {
-        int bCompletelyOutside = anSrcWin[0] + anSrcWin[2] <= 0 ||
-                                    anSrcWin[1] + anSrcWin[3] <= 0 ||
-                                    anSrcWin[0] >= GDALGetRasterXSize(hDataset) ||
-                                    anSrcWin[1] >= GDALGetRasterYSize(hDataset);
-        int bIsError = bErrorOnPartiallyOutside || (bCompletelyOutside && bErrorOnCompletelyOutside);
-        if( !bQuiet || bIsError )
-        {
-            fprintf( stderr,
-                 "%s: %s-srcwin %d %d %d %d falls %s outside raster extent.%s\n",
-                 (bIsError) ? "Error" : "Warning",
-                 ( dfULX != 0.0 || dfULY != 0.0 || dfLRX != 0.0 || dfLRY != 0.0 ) ? "Computed " : "",
-                 anSrcWin[0],
-                 anSrcWin[1],
-                 anSrcWin[2],
-                 anSrcWin[3],
-                 (bCompletelyOutside) ? "completely" : "partially",
-                 (bIsError) ? "" : " Going on however." );
-        }
-        if( bIsError )
-            exit(1);
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Find the output driver.                                         */
-/* -------------------------------------------------------------------- */
-    hDriver = GDALGetDriverByName( pszFormat );
-    if( hDriver == NULL )
-    {
-        int	iDr;
-        
-        printf( "Output driver `%s' not recognised.\n", pszFormat );
-        printf( "The following format drivers are configured and support output:\n" );
-        for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
-        {
-            GDALDriverH hDriver = GDALGetDriver(iDr);
-
-            if( GDALGetMetadataItem( hDriver, GDAL_DCAP_RASTER, NULL) != NULL &&
-                (GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) != NULL
-                 || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY, NULL ) != NULL) )
-            {
-                printf( "  %s: %s\n",
-                        GDALGetDriverShortName( hDriver  ),
-                        GDALGetDriverLongName( hDriver ) );
-            }
-        }
-        printf( "\n" );
-        Usage();
-        
-        GDALClose( hDataset );
-        CPLFree( panBandList );
-        GDALDestroyDriverManager();
-        CSLDestroy( argv );
-        CSLDestroy( papszCreateOptions );
-        CSLDestroy( papszOpenOptions );
-        exit( 1 );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      The short form is to CreateCopy().  We use this if the input    */
-/*      matches the whole dataset.  Eventually we should rewrite        */
-/*      this entire program to use virtual datasets to construct a      */
-/*      virtual input source to copy from.                              */
-/* -------------------------------------------------------------------- */
-
-
-    int bSpatialArrangementPreserved = (
-           anSrcWin[0] == 0 && anSrcWin[1] == 0
-        && anSrcWin[2] == GDALGetRasterXSize(hDataset)
-        && anSrcWin[3] == GDALGetRasterYSize(hDataset)
-        && pszOXSize == NULL && pszOYSize == NULL && dfXRes == 0.0 );
-
-    if( eOutputType == GDT_Unknown 
-        && nScaleRepeat == 0 && nExponentRepeat == 0 && !bUnscale
-        && CSLCount(papszMetadataOptions) == 0 && bDefBands 
-        && eMaskMode == MASK_AUTO
-        && bSpatialArrangementPreserved
-        && nGCPCount == 0 && !bGotBounds
-        && pszOutputSRS == NULL && !bSetNoData && !bUnsetNoData
-        && nRGBExpand == 0 && !bStats && !bNoRAT )
-    {
-        
-        hOutDS = GDALCreateCopy( hDriver, pszDest, hDataset, 
-                                 bStrict, papszCreateOptions, 
-                                 pfnProgress, NULL );
-
-        if( hOutDS != NULL )
-            GDALClose( hOutDS );
-        
-        GDALClose( hDataset );
-
-        CPLFree( panBandList );
-
-        if( !bSubCall )
-        {
-            GDALDumpOpenDatasets( stderr );
-            GDALDestroyDriverManager();
-        }
-
-        CSLDestroy( argv );
-        CSLDestroy( papszCreateOptions );
-        CSLDestroy( papszOpenOptions );
-
-        return hOutDS == NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Establish some parameters.                                      */
-/* -------------------------------------------------------------------- */
-    if( dfXRes != 0.0 )
-    {
-        if( !(GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None &&
-              nGCPCount == 0 &&
-              adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0) )
-        {
-            fprintf( stderr, 
-                     "The -tr option was used, but there's no geotransform or it is\n"
-                     "rotated.  This configuration is not supported.\n" );
-            GDALClose( hDataset );
-            CPLFree( panBandList );
-            GDALDestroyDriverManager();
-            exit( 1 );
-        }
-        nOXSize = int(anSrcWin[2] / dfXRes * adfGeoTransform[1] + 0.5);
-        nOYSize = int(anSrcWin[3] / dfYRes * fabs(adfGeoTransform[5]) + 0.5);
-    }
-    else if( pszOXSize == NULL )
-    {
-        nOXSize = anSrcWin[2];
-        nOYSize = anSrcWin[3];
-    }
-    else
-    {
-        int bXAuto = EQUAL(pszOXSize, "auto") || EQUAL(pszOXSize, "0");
-        int bYAuto = EQUAL(pszOYSize, "auto") || EQUAL(pszOYSize, "0");
-        if( bXAuto && bYAuto )
-        {
-            fprintf(stderr, "-outsize %s %s invalid.\n", pszOXSize, pszOYSize);
-            GDALClose( hDataset );
-            CPLFree( panBandList );
-            GDALDestroyDriverManager();
-            exit( 1 );
-        }
-        if( !bXAuto )
-            nOXSize = (int) ((pszOXSize[strlen(pszOXSize)-1]=='%' 
-                            ? CPLAtofM(pszOXSize)/100*anSrcWin[2] : atoi(pszOXSize)));
-        if( !bYAuto )
-            nOYSize = (int) ((pszOYSize[strlen(pszOYSize)-1]=='%' 
-                            ? CPLAtofM(pszOYSize)/100*anSrcWin[3] : atoi(pszOYSize)));
-        if( bXAuto )
-            nOXSize = (int)((double)nOYSize * anSrcWin[2] / anSrcWin[3] + 0.5);
-        else if( bYAuto )
-            nOYSize = (int)((double)nOXSize * anSrcWin[3] / anSrcWin[2] + 0.5);
-    }
-
-    if( nOXSize == 0 || nOYSize == 0 )
-    {
-        fprintf(stderr, "Attempt to create %dx%d dataset is illegal.\n", nOXSize, nOYSize);
-        GDALClose( hDataset );
-        CPLFree( panBandList );
-        GDALDestroyDriverManager();
-        exit( 1 );
-    }
-
-/* ==================================================================== */
-/*      Create a virtual dataset.                                       */
-/* ==================================================================== */
-    VRTDataset *poVDS;
-        
-/* -------------------------------------------------------------------- */
-/*      Make a virtual clone.                                           */
-/* -------------------------------------------------------------------- */
-    poVDS = (VRTDataset *) VRTCreate( nOXSize, nOYSize );
-
-    if( nGCPCount == 0 )
-    {
-        if( pszOutputSRS != NULL )
-        {
-            poVDS->SetProjection( pszOutputSRS );
-        }
-        else
-        {
-            pszProjection = GDALGetProjectionRef( hDataset );
-            if( pszProjection != NULL && strlen(pszProjection) > 0 )
-                poVDS->SetProjection( pszProjection );
-        }
-    }
-
-    if( bGotBounds )
-    {
-        adfGeoTransform[0] = adfULLR[0];
-        adfGeoTransform[1] = (adfULLR[2] - adfULLR[0]) / nOXSize;
-        adfGeoTransform[2] = 0.0;
-        adfGeoTransform[3] = adfULLR[1];
-        adfGeoTransform[4] = 0.0;
-        adfGeoTransform[5] = (adfULLR[3] - adfULLR[1]) / nOYSize;
-
-        poVDS->SetGeoTransform( adfGeoTransform );
-    }
-
-    else if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None 
-        && nGCPCount == 0 )
-    {
-        adfGeoTransform[0] += anSrcWin[0] * adfGeoTransform[1]
-            + anSrcWin[1] * adfGeoTransform[2];
-        adfGeoTransform[3] += anSrcWin[0] * adfGeoTransform[4]
-            + anSrcWin[1] * adfGeoTransform[5];
-        
-        adfGeoTransform[1] *= anSrcWin[2] / (double) nOXSize;
-        adfGeoTransform[2] *= anSrcWin[3] / (double) nOYSize;
-        adfGeoTransform[4] *= anSrcWin[2] / (double) nOXSize;
-        adfGeoTransform[5] *= anSrcWin[3] / (double) nOYSize;
-        
-        if( dfXRes != 0.0 )
-        {
-            adfGeoTransform[1] = dfXRes;
-            adfGeoTransform[5] = (adfGeoTransform[5] > 0) ? dfYRes : -dfYRes;
-        }
-
-        poVDS->SetGeoTransform( adfGeoTransform );
-    }
-
-    if( nGCPCount != 0 )
-    {
-        const char *pszGCPProjection = pszOutputSRS;
-
-        if( pszGCPProjection == NULL )
-            pszGCPProjection = GDALGetGCPProjection( hDataset );
-        if( pszGCPProjection == NULL )
-            pszGCPProjection = "";
-
-        poVDS->SetGCPs( nGCPCount, pasGCPs, pszGCPProjection );
-
-        GDALDeinitGCPs( nGCPCount, pasGCPs );
-        CPLFree( pasGCPs );
-    }
-
-    else if( GDALGetGCPCount( hDataset ) > 0 )
-    {
-        GDAL_GCP *pasGCPs;
-        int       nGCPs = GDALGetGCPCount( hDataset );
-
-        pasGCPs = GDALDuplicateGCPs( nGCPs, GDALGetGCPs( hDataset ) );
-
-        for( i = 0; i < nGCPs; i++ )
-        {
-            pasGCPs[i].dfGCPPixel -= anSrcWin[0];
-            pasGCPs[i].dfGCPLine  -= anSrcWin[1];
-            pasGCPs[i].dfGCPPixel *= (nOXSize / (double) anSrcWin[2] );
-            pasGCPs[i].dfGCPLine  *= (nOYSize / (double) anSrcWin[3] );
-        }
-            
-        poVDS->SetGCPs( nGCPs, pasGCPs,
-                        GDALGetGCPProjection( hDataset ) );
-
-        GDALDeinitGCPs( nGCPs, pasGCPs );
-        CPLFree( pasGCPs );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      To make the VRT to look less awkward (but this is optional      */
-/*      in fact), avoid negative values.                                */
-/* -------------------------------------------------------------------- */
-    int anDstWin[4];
-    anDstWin[0] = 0;
-    anDstWin[1] = 0;
-    anDstWin[2] = nOXSize;
-    anDstWin[3] = nOYSize;
-
-    FixSrcDstWindow( anSrcWin, anDstWin,
-                     GDALGetRasterXSize(hDataset),
-                     GDALGetRasterYSize(hDataset) );
-
-/* -------------------------------------------------------------------- */
-/*      Transfer generally applicable metadata.                         */
-/* -------------------------------------------------------------------- */
-    char** papszMetadata = CSLDuplicate(((GDALDataset*)hDataset)->GetMetadata());
-    if ( nScaleRepeat > 0 || bUnscale || eOutputType != GDT_Unknown )
-    {
-        /* Remove TIFFTAG_MINSAMPLEVALUE and TIFFTAG_MAXSAMPLEVALUE */
-        /* if the data range may change because of options */
-        char** papszIter = papszMetadata;
-        while(papszIter && *papszIter)
-        {
-            if (EQUALN(*papszIter, "TIFFTAG_MINSAMPLEVALUE=", 23) ||
-                EQUALN(*papszIter, "TIFFTAG_MAXSAMPLEVALUE=", 23))
-            {
-                CPLFree(*papszIter);
-                memmove(papszIter, papszIter+1, sizeof(char*) * (CSLCount(papszIter+1)+1));
-            }
-            else
-                papszIter++;
-        }
-    }
-    poVDS->SetMetadata( papszMetadata );
-    CSLDestroy( papszMetadata );
-    AttachMetadata( (GDALDatasetH) poVDS, papszMetadataOptions );
-
-    const char* pszInterleave = GDALGetMetadataItem(hDataset, "INTERLEAVE", "IMAGE_STRUCTURE");
-    if (pszInterleave)
-        poVDS->SetMetadataItem("INTERLEAVE", pszInterleave, "IMAGE_STRUCTURE");
-
-/* -------------------------------------------------------------------- */
-/*      Transfer metadata that remains valid if the spatial             */
-/*      arrangement of the data is unaltered.                           */
-/* -------------------------------------------------------------------- */
-    if( bSpatialArrangementPreserved )
-    {
-        char **papszMD;
-
-        papszMD = ((GDALDataset*)hDataset)->GetMetadata("RPC");
-        if( papszMD != NULL )
-            poVDS->SetMetadata( papszMD, "RPC" );
-
-        papszMD = ((GDALDataset*)hDataset)->GetMetadata("GEOLOCATION");
-        if( papszMD != NULL )
-            poVDS->SetMetadata( papszMD, "GEOLOCATION" );
-    }
-    else
-    {
-        char **papszMD;
-
-        papszMD = ((GDALDataset*)hDataset)->GetMetadata("RPC");
-        if( papszMD != NULL )
-        {
-            papszMD = CSLDuplicate(papszMD);
- 
-            double dfSAMP_OFF = CPLAtof(CSLFetchNameValueDef(papszMD, "SAMP_OFF", "0"));
-            double dfLINE_OFF = CPLAtof(CSLFetchNameValueDef(papszMD, "LINE_OFF", "0"));
-            double dfSAMP_SCALE = CPLAtof(CSLFetchNameValueDef(papszMD, "SAMP_SCALE", "1"));
-            double dfLINE_SCALE = CPLAtof(CSLFetchNameValueDef(papszMD, "LINE_SCALE", "1"));
-
-            dfSAMP_OFF -= anSrcWin[0];
-            dfLINE_OFF -= anSrcWin[1];
-            dfSAMP_OFF *= (nOXSize / (double) anSrcWin[2] );
-            dfLINE_OFF *= (nOYSize / (double) anSrcWin[3] );
-            dfSAMP_SCALE *= (nOXSize / (double) anSrcWin[2] );
-            dfLINE_SCALE *= (nOYSize / (double) anSrcWin[3] );
-
-            CPLString osField;
-            osField.Printf( "%.15g", dfLINE_OFF );
-            papszMD = CSLSetNameValue( papszMD, "LINE_OFF", osField );
-
-            osField.Printf( "%.15g", dfSAMP_OFF );
-            papszMD = CSLSetNameValue( papszMD, "SAMP_OFF", osField );
-
-            osField.Printf( "%.15g", dfLINE_SCALE );
-            papszMD = CSLSetNameValue( papszMD, "LINE_SCALE", osField );
-
-            osField.Printf( "%.15g", dfSAMP_SCALE );
-            papszMD = CSLSetNameValue( papszMD, "SAMP_SCALE", osField );
-
-            poVDS->SetMetadata( papszMD, "RPC" );
-            CSLDestroy(papszMD);
-        }
-    }
-
-    int nSrcBandCount = nBandCount;
-
-    if (nRGBExpand != 0)
-    {
-        GDALRasterBand  *poSrcBand;
-        poSrcBand = ((GDALDataset *) 
-                     hDataset)->GetRasterBand(ABS(panBandList[0]));
-        if (panBandList[0] < 0)
-            poSrcBand = poSrcBand->GetMaskBand();
-        GDALColorTable* poColorTable = poSrcBand->GetColorTable();
-        if (poColorTable == NULL)
-        {
-            fprintf(stderr, "Error : band %d has no color table\n", ABS(panBandList[0]));
-            GDALClose( hDataset );
-            CPLFree( panBandList );
-            GDALDestroyDriverManager();
-            CSLDestroy( argv );
-            CSLDestroy( papszCreateOptions );
-            CSLDestroy( papszOpenOptions );
-            exit( 1 );
-        }
-        
-        /* Check that the color table only contains gray levels */
-        /* when using -expand gray */
-        if (nRGBExpand == 1)
-        {
-            int nColorCount = poColorTable->GetColorEntryCount();
-            int nColor;
-            for( nColor = 0; nColor < nColorCount; nColor++ )
-            {
-                const GDALColorEntry* poEntry = poColorTable->GetColorEntry(nColor);
-                if (poEntry->c1 != poEntry->c2 || poEntry->c1 != poEntry->c3)
-                {
-                    fprintf(stderr, "Warning : color table contains non gray levels colors\n");
-                    break;
-                }
-            }
-        }
-
-        if (nBandCount == 1)
-            nBandCount = nRGBExpand;
-        else if (nBandCount == 2 && (nRGBExpand == 3 || nRGBExpand == 4))
-            nBandCount = nRGBExpand;
-        else
-        {
-            fprintf(stderr, "Error : invalid use of -expand option.\n");
-            exit( 1 );
-        }
-    }
-
-    // Can be set to TRUE in the band loop too
-    int bFilterOutStatsMetadata =
-        (nScaleRepeat > 0 || bUnscale || !bSpatialArrangementPreserved || nRGBExpand != 0);
-
-/* ==================================================================== */
-/*      Process all bands.                                              */
-/* ==================================================================== */
-    for( i = 0; i < nBandCount; i++ )
-    {
-        VRTSourcedRasterBand   *poVRTBand;
-        GDALRasterBand  *poSrcBand;
-        GDALDataType    eBandType;
-        int             nComponent = 0;
-
-        int nSrcBand;
-        if (nRGBExpand != 0)
-        {
-            if (nSrcBandCount == 2 && nRGBExpand == 4 && i == 3)
-                nSrcBand = panBandList[1];
-            else
-            {
-                nSrcBand = panBandList[0];
-                nComponent = i + 1;
-            }
-        }
-        else
-            nSrcBand = panBandList[i];
-
-        poSrcBand = ((GDALDataset *) hDataset)->GetRasterBand(ABS(nSrcBand));
-
-/* -------------------------------------------------------------------- */
-/*      Select output data type to match source.                        */
-/* -------------------------------------------------------------------- */
-        if( eOutputType == GDT_Unknown )
-            eBandType = poSrcBand->GetRasterDataType();
-        else
-        {
-            eBandType = eOutputType;
-            
-            // Check that we can copy existing statistics
-            GDALDataType eSrcBandType = poSrcBand->GetRasterDataType();
-            const char* pszMin = poSrcBand->GetMetadataItem("STATISTICS_MINIMUM");
-            const char* pszMax = poSrcBand->GetMetadataItem("STATISTICS_MAXIMUM");
-            if( !bFilterOutStatsMetadata && eBandType != eSrcBandType &&
-                pszMin != NULL && pszMax != NULL )
-            {
-                int bSrcIsInteger = ( eSrcBandType == GDT_Byte ||
-                                      eSrcBandType == GDT_Int16 ||
-                                      eSrcBandType == GDT_UInt16 ||
-                                      eSrcBandType == GDT_Int32 ||
-                                      eSrcBandType == GDT_UInt32 );
-                int bDstIsInteger = ( eBandType == GDT_Byte ||
-                                      eBandType == GDT_Int16 ||
-                                      eBandType == GDT_UInt16 ||
-                                      eBandType == GDT_Int32 ||
-                                      eBandType == GDT_UInt32 );
-                if( bSrcIsInteger && bDstIsInteger )
-                {
-                    GInt32 nDstMin = 0;
-                    GUInt32 nDstMax = 0;
-                    switch( eBandType )
-                    {
-                        case GDT_Byte:
-                            nDstMin = 0;
-                            nDstMax = 255;
-                            break;
-                        case GDT_UInt16:
-                            nDstMin = 0;
-                            nDstMax = 65535;
-                            break;
-                        case GDT_Int16:
-                            nDstMin = -32768;
-                            nDstMax = 32767;
-                            break;
-                        case GDT_UInt32:
-                            nDstMin = 0;
-                            nDstMax = 0xFFFFFFFFU;
-                            break;
-                        case GDT_Int32:
-                            nDstMin = 0x80000000;
-                            nDstMax = 0x7FFFFFFF;
-                            break;
-                        default:
-                            CPLAssert(FALSE);
-                            break;
-                    }
-
-                    GInt32 nMin = atoi(pszMin);
-                    GUInt32 nMax = (GUInt32)strtoul(pszMax, NULL, 10);
-                    if( nMin < nDstMin || nMax > nDstMax )
-                        bFilterOutStatsMetadata = TRUE;
-                }
-                // Float64 is large enough to hold all integer <= 32 bit or float32 values
-                // there might be other OK cases, but ere on safe side for now
-                else if( !((bSrcIsInteger || eSrcBandType == GDT_Float32) && eBandType == GDT_Float64) )
-                {
-                    bFilterOutStatsMetadata = TRUE;
-                }
-            }
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Create this band.                                               */
-/* -------------------------------------------------------------------- */
-        poVDS->AddBand( eBandType, NULL );
-        poVRTBand = (VRTSourcedRasterBand *) poVDS->GetRasterBand( i+1 );
-        if (nSrcBand < 0)
-        {
-            poVRTBand->AddMaskBandSource(poSrcBand,
-                                         anSrcWin[0], anSrcWin[1],
-                                         anSrcWin[2], anSrcWin[3],
-                                         anDstWin[0], anDstWin[1],
-                                         anDstWin[2], anDstWin[3]);
-            continue;
-        }
-
-        // Preserve nbits if no option change values
-        const char* pszNBits = poSrcBand->GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
-        if( pszNBits && nRGBExpand == 0 && nScaleRepeat == 0 &&
-            !bUnscale && eOutputType == GDT_Unknown && pszResampling == NULL )
-        {
-            poVRTBand->SetMetadataItem("NBITS", pszNBits, "IMAGE_STRUCTURE");
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Do we need to collect scaling information?                      */
-/* -------------------------------------------------------------------- */
-        double dfScale=1.0, dfOffset=0.0;
-        int    bScale = FALSE, bHaveScaleSrc = FALSE;
-        double dfScaleSrcMin = 0.0, dfScaleSrcMax = 0.0;
-        double dfScaleDstMin = 0.0, dfScaleDstMax = 0.0;
-        int    bExponentScaling = FALSE;
-        double dfExponent = 0.0;
-
-        if( i < nScaleRepeat && pasScaleParams[i].bScale )
-        {
-            bScale = pasScaleParams[i].bScale;
-            bHaveScaleSrc = pasScaleParams[i].bHaveScaleSrc;
-            dfScaleSrcMin = pasScaleParams[i].dfScaleSrcMin;
-            dfScaleSrcMax = pasScaleParams[i].dfScaleSrcMax;
-            dfScaleDstMin = pasScaleParams[i].dfScaleDstMin;
-            dfScaleDstMax = pasScaleParams[i].dfScaleDstMax;
-        }
-        else if( nScaleRepeat == 1 && !bHasUsedExplictScaleBand )
-        {
-            bScale = pasScaleParams[0].bScale;
-            bHaveScaleSrc = pasScaleParams[0].bHaveScaleSrc;
-            dfScaleSrcMin = pasScaleParams[0].dfScaleSrcMin;
-            dfScaleSrcMax = pasScaleParams[0].dfScaleSrcMax;
-            dfScaleDstMin = pasScaleParams[0].dfScaleDstMin;
-            dfScaleDstMax = pasScaleParams[0].dfScaleDstMax;
-        }
-
-        if( i < nExponentRepeat && padfExponent[i] != 0.0 )
-        {
-            bExponentScaling = TRUE;
-            dfExponent = padfExponent[i];
-        }
-        else if( nExponentRepeat == 1 && !bHasUsedExplictExponentBand )
-        {
-            bExponentScaling = TRUE;
-            dfExponent = padfExponent[0];
-        }
-
-        if( bExponentScaling && !bScale )
-        {
-            Usage(CPLSPrintf("For band %d, -scale should be specified when -exponent is specified.", i + 1));
-        }
-
-        if( bScale && !bHaveScaleSrc )
-        {
-            double	adfCMinMax[2];
-            GDALComputeRasterMinMax( poSrcBand, TRUE, adfCMinMax );
-            dfScaleSrcMin = adfCMinMax[0];
-            dfScaleSrcMax = adfCMinMax[1];
-        }
-
-        if( bScale )
-        {
-            /* To avoid a divide by zero */
-            if( dfScaleSrcMax == dfScaleSrcMin )
-                dfScaleSrcMax += 0.1;
-
-            if( !bExponentScaling )
-            {
-                dfScale = (dfScaleDstMax - dfScaleDstMin) 
-                    / (dfScaleSrcMax - dfScaleSrcMin);
-                dfOffset = -1 * dfScaleSrcMin * dfScale + dfScaleDstMin;
-            }
-        }
-
-        if( bUnscale )
-        {
-            dfScale = poSrcBand->GetScale();
-            dfOffset = poSrcBand->GetOffset();
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Create a simple or complex data source depending on the         */
-/*      translation type required.                                      */
-/* -------------------------------------------------------------------- */
-        VRTSimpleSource* poSimpleSource;
-        if( bUnscale || bScale || (nRGBExpand != 0 && i < nRGBExpand) )
-        {
-            VRTComplexSource* poSource = new VRTComplexSource();
-
-        /* -------------------------------------------------------------------- */
-        /*      Set complex parameters.                                         */
-        /* -------------------------------------------------------------------- */
-
-            if( dfOffset != 0.0 || dfScale != 1.0 )
-            {
-                poSource->SetLinearScaling(dfOffset, dfScale);
-            }
-            else if( bExponentScaling )
-            {
-                poSource->SetPowerScaling(dfExponent,
-                                          dfScaleSrcMin,
-                                          dfScaleSrcMax,
-                                          dfScaleDstMin,
-                                          dfScaleDstMax);
-            }
-
-            poSource->SetColorTableComponent(nComponent);
-
-            poSimpleSource = poSource;
-        }
-        else
-            poSimpleSource = new VRTSimpleSource();
-
-        poSimpleSource->SetResampling(pszResampling);
-        poVRTBand->ConfigureSource( poSimpleSource,
-                                    poSrcBand,
-                                    FALSE,
-                                    anSrcWin[0], anSrcWin[1],
-                                    anSrcWin[2], anSrcWin[3],
-                                    anDstWin[0], anDstWin[1],
-                                    anDstWin[2], anDstWin[3] );
-
-        poVRTBand->AddSource( poSimpleSource );
-
-/* -------------------------------------------------------------------- */
-/*      In case of color table translate, we only set the color         */
-/*      interpretation other info copied by CopyBandInfo are            */
-/*      not relevant in RGB expansion.                                  */
-/* -------------------------------------------------------------------- */
-        if (nRGBExpand == 1)
-        {
-            poVRTBand->SetColorInterpretation( GCI_GrayIndex );
-        }
-        else if (nRGBExpand != 0 && i < nRGBExpand)
-        {
-            poVRTBand->SetColorInterpretation( (GDALColorInterp) (GCI_RedBand + i) );
-        }
-
-/* -------------------------------------------------------------------- */
-/*      copy over some other information of interest.                   */
-/* -------------------------------------------------------------------- */
-        else
-        {
-            CopyBandInfo( poSrcBand, poVRTBand,
-                          !bStats && !bFilterOutStatsMetadata,
-                          !bUnscale,
-                          !bSetNoData && !bUnsetNoData );
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Set a forcable nodata value?                                    */
-/* -------------------------------------------------------------------- */
-        if( bSetNoData )
-        {
-            double dfVal = dfNoDataReal;
-            int bClamped = FALSE, bRounded = FALSE;
-
-#define CLAMP(val,type,minval,maxval) \
-    do { if (val < minval) { bClamped = TRUE; val = minval; } \
-    else if (val > maxval) { bClamped = TRUE; val = maxval; } \
-    else if (val != (type)val) { bRounded = TRUE; val = (type)(val + 0.5); } } \
-    while(0)
-
-            switch(eBandType)
-            {
-                case GDT_Byte:
-                    CLAMP(dfVal, GByte, 0.0, 255.0);
-                    break;
-                case GDT_Int16:
-                    CLAMP(dfVal, GInt16, -32768.0, 32767.0);
-                    break;
-                case GDT_UInt16:
-                    CLAMP(dfVal, GUInt16, 0.0, 65535.0);
-                    break;
-                case GDT_Int32:
-                    CLAMP(dfVal, GInt32, -2147483648.0, 2147483647.0);
-                    break;
-                case GDT_UInt32:
-                    CLAMP(dfVal, GUInt32, 0.0, 4294967295.0);
-                    break;
-                default:
-                    break;
-            }
-                
-            if (bClamped)
-            {
-                printf( "for band %d, nodata value has been clamped "
-                       "to %.0f, the original value being out of range.\n",
-                       i + 1, dfVal);
-            }
-            else if(bRounded)
-            {
-                printf("for band %d, nodata value has been rounded "
-                       "to %.0f, %s being an integer datatype.\n",
-                       i + 1, dfVal,
-                       GDALGetDataTypeName(eBandType));
-            }
-            
-            poVRTBand->SetNoDataValue( dfVal );
-        }
-
-        if (eMaskMode == MASK_AUTO &&
-            (GDALGetMaskFlags(GDALGetRasterBand(hDataset, 1)) & GMF_PER_DATASET) == 0 &&
-            (poSrcBand->GetMaskFlags() & (GMF_ALL_VALID | GMF_NODATA)) == 0)
-        {
-            if (poVRTBand->CreateMaskBand(poSrcBand->GetMaskFlags()) == CE_None)
-            {
-                VRTSourcedRasterBand* hMaskVRTBand =
-                    (VRTSourcedRasterBand*)poVRTBand->GetMaskBand();
-                hMaskVRTBand->AddMaskBandSource(poSrcBand,
-                                        anSrcWin[0], anSrcWin[1],
-                                        anSrcWin[2], anSrcWin[3],
-                                        anDstWin[0], anDstWin[1],
-                                        anDstWin[2], anDstWin[3] );
-            }
-        }
-    }
-
-    if (eMaskMode == MASK_USER)
-    {
-        GDALRasterBand *poSrcBand =
-            (GDALRasterBand*)GDALGetRasterBand(hDataset, ABS(nMaskBand));
-        if (poSrcBand && poVDS->CreateMaskBand(GMF_PER_DATASET) == CE_None)
-        {
-            VRTSourcedRasterBand* hMaskVRTBand = (VRTSourcedRasterBand*)
-                GDALGetMaskBand(GDALGetRasterBand((GDALDatasetH)poVDS, 1));
-            if (nMaskBand > 0)
-                hMaskVRTBand->AddSimpleSource(poSrcBand,
-                                        anSrcWin[0], anSrcWin[1],
-                                        anSrcWin[2], anSrcWin[3],
-                                        anDstWin[0], anDstWin[1],
-                                        anDstWin[2], anDstWin[3] );
-            else
-                hMaskVRTBand->AddMaskBandSource(poSrcBand,
-                                        anSrcWin[0], anSrcWin[1],
-                                        anSrcWin[2], anSrcWin[3],
-                                        anDstWin[0], anDstWin[1],
-                                        anDstWin[2], anDstWin[3] );
-        }
-    }
-    else
-    if (eMaskMode == MASK_AUTO && nSrcBandCount > 0 &&
-        GDALGetMaskFlags(GDALGetRasterBand(hDataset, 1)) == GMF_PER_DATASET)
-    {
-        if (poVDS->CreateMaskBand(GMF_PER_DATASET) == CE_None)
-        {
-            VRTSourcedRasterBand* hMaskVRTBand = (VRTSourcedRasterBand*)
-                GDALGetMaskBand(GDALGetRasterBand((GDALDatasetH)poVDS, 1));
-            hMaskVRTBand->AddMaskBandSource((GDALRasterBand*)GDALGetRasterBand(hDataset, 1),
-                                        anSrcWin[0], anSrcWin[1],
-                                        anSrcWin[2], anSrcWin[3],
-                                        anDstWin[0], anDstWin[1],
-                                        anDstWin[2], anDstWin[3] );
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Compute stats if required.                                      */
-/* -------------------------------------------------------------------- */
-    if (bStats)
-    {
-        for( i = 0; i < poVDS->GetRasterCount(); i++ )
-        {
-            double dfMin, dfMax, dfMean, dfStdDev;
-            poVDS->GetRasterBand(i+1)->ComputeStatistics( bApproxStats,
-                    &dfMin, &dfMax, &dfMean, &dfStdDev, GDALDummyProgress, NULL );
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Write to the output file using CopyCreate().                    */
-/* -------------------------------------------------------------------- */
-    hOutDS = GDALCreateCopy( hDriver, pszDest, (GDALDatasetH) poVDS,
-                             bStrict, papszCreateOptions, 
-                             pfnProgress, NULL );
-    if( hOutDS != NULL )
-    {
-        int bHasGotErr = FALSE;
-        CPLErrorReset();
-        GDALFlushCache( hOutDS );
-        if (CPLGetLastErrorType() != CE_None)
-            bHasGotErr = TRUE;
-        GDALClose( hOutDS );
-        if (bHasGotErr)
-            hOutDS = NULL;
-    }
-    
-    GDALClose( (GDALDatasetH) poVDS );
-        
-    GDALClose( hDataset );
-
-    CPLFree( panBandList );
-    CPLFree( pasScaleParams );
-    CPLFree( padfExponent );
-    
-    CPLFree( pszOutputSRS );
-
-    if( !bSubCall )
-    {
-        GDALDumpOpenDatasets( stderr );
-        GDALDestroyDriverManager();
-    }
-
-    CSLDestroy( argv );
-    CSLDestroy( papszCreateOptions );
-    CSLDestroy( papszOpenOptions );
-    
-    return hOutDS == NULL;
-}
-
-
-/************************************************************************/
-/*                            ArgIsNumeric()                            */
-/************************************************************************/
-
-int ArgIsNumeric( const char *pszArg )
-
-{
-    return CPLGetValueType(pszArg) != CPL_VALUE_STRING;
-}
-
-/************************************************************************/
-/*                           AttachMetadata()                           */
-/************************************************************************/
-
-static void AttachMetadata( GDALDatasetH hDS, char **papszMetadataOptions )
-
-{
-    int nCount = CSLCount(papszMetadataOptions);
-    int i;
-
-    for( i = 0; i < nCount; i++ )
-    {
-        char    *pszKey = NULL;
-        const char *pszValue;
-        
-        pszValue = CPLParseNameValue( papszMetadataOptions[i], &pszKey );
-        GDALSetMetadataItem(hDS,pszKey,pszValue,NULL);
-        CPLFree( pszKey );
-    }
-
-    CSLDestroy( papszMetadataOptions );
-}
-
-/************************************************************************/
-/*                           CopyBandInfo()                            */
-/************************************************************************/
-
-/* A bit of a clone of VRTRasterBand::CopyCommonInfoFrom(), but we need */
-/* more and more custom behaviour in the context of gdal_translate ... */
-
-static void CopyBandInfo( GDALRasterBand * poSrcBand, GDALRasterBand * poDstBand,
-                          int bCanCopyStatsMetadata, int bCopyScale, int bCopyNoData )
-
-{
-    int bSuccess;
-    double dfNoData;
-
-    if (bCanCopyStatsMetadata)
-    {
-        poDstBand->SetMetadata( poSrcBand->GetMetadata() );
-    }
-    else
-    {
-        char** papszMetadata = poSrcBand->GetMetadata();
-        char** papszMetadataNew = NULL;
-        for( int i = 0; papszMetadata != NULL && papszMetadata[i] != NULL; i++ )
-        {
-            if (strncmp(papszMetadata[i], "STATISTICS_", 11) != 0)
-                papszMetadataNew = CSLAddString(papszMetadataNew, papszMetadata[i]);
-        }
-        poDstBand->SetMetadata( papszMetadataNew );
-        CSLDestroy(papszMetadataNew);
-    }
-
-    poDstBand->SetColorTable( poSrcBand->GetColorTable() );
-    poDstBand->SetColorInterpretation(poSrcBand->GetColorInterpretation());
-    if( strlen(poSrcBand->GetDescription()) > 0 )
-        poDstBand->SetDescription( poSrcBand->GetDescription() );
-
-    if (bCopyNoData)
-    {
-        dfNoData = poSrcBand->GetNoDataValue( &bSuccess );
-        if( bSuccess )
-            poDstBand->SetNoDataValue( dfNoData );
-    }
-
-    if (bCopyScale)
-    {
-        poDstBand->SetOffset( poSrcBand->GetOffset() );
-        poDstBand->SetScale( poSrcBand->GetScale() );
-    }
-
-    poDstBand->SetCategoryNames( poSrcBand->GetCategoryNames() );
-
-    // Copy unit only if the range of pixel values is not modified
-    if( bCanCopyStatsMetadata && bCopyScale && !EQUAL(poSrcBand->GetUnitType(),"") )
-        poDstBand->SetUnitType( poSrcBand->GetUnitType() );
-}
-
-/************************************************************************/
-/*                                main()                                */
-/************************************************************************/
-
-int main( int argc, char ** argv )
-
-{
-    return ProxyMain( argc, argv );
-}
-
-
diff --git a/apps/gdal_translate_bin.cpp b/apps/gdal_translate_bin.cpp
new file mode 100644
index 0000000..95abfc1
--- /dev/null
+++ b/apps/gdal_translate_bin.cpp
@@ -0,0 +1,306 @@
+/******************************************************************************
+ * $Id: gdal_translate_bin.cpp 33615 2016-03-02 20:19:22Z goatbar $
+ *
+ * Project:  GDAL Utilities
+ * Purpose:  GDAL Image Translator Program
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1998, 2002, Frank Warmerdam
+ * Copyright (c) 2007-2014, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_string.h"
+#include "gdal_priv.h"
+#include "ogr_spatialref.h"
+#include "commonutils.h"
+#include "gdal_utils_priv.h"
+
+CPL_CVSID("$Id: gdal_translate_bin.cpp 33615 2016-03-02 20:19:22Z goatbar $");
+
+/*  ******************************************************************* */
+/*                               Usage()                                */
+/* ******************************************************************** */
+
+static void Usage(const char* pszErrorMsg = NULL, int bShort = TRUE) CPL_NO_RETURN;
+
+static void Usage(const char* pszErrorMsg, int bShort)
+
+{
+    int iDr;
+
+    printf( "Usage: gdal_translate [--help-general] [--long-usage]\n"
+            "       [-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/\n"
+            "             CInt16/CInt32/CFloat32/CFloat64}] [-strict]\n"
+            "       [-of format] [-b band] [-mask band] [-expand {gray|rgb|rgba}]\n"
+            "       [-outsize xsize[%%]|0 ysize[%%]|0] [-tr xres yres]\n"
+            "       [-r {nearest,bilinear,cubic,cubicspline,lanczos,average,mode}]\n"
+            "       [-unscale] [-scale[_bn] [src_min src_max [dst_min dst_max]]]* [-exponent[_bn] exp_val]*\n"
+            "       [-srcwin xoff yoff xsize ysize] [-epo] [-eco]\n"
+            "       [-projwin ulx uly lrx lry] [-projwin_srs srs_def]\n"
+            "       [-a_srs srs_def] [-a_ullr ulx uly lrx lry] [-a_nodata value]\n"
+            "       [-gcp pixel line easting northing [elevation]]*\n"
+            "       [-mo \"META-TAG=VALUE\"]* [-q] [-sds]\n"
+            "       [-co \"NAME=VALUE\"]* [-stats] [-norat]\n"
+            "       [-oo NAME=VALUE]*\n"
+            "       src_dataset dst_dataset\n" );
+
+    if( !bShort )
+    {
+        printf( "\n%s\n\n", GDALVersionInfo( "--version" ) );
+        printf( "The following format drivers are configured and support output:\n" );
+        for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
+        {
+            GDALDriverH hDriver = GDALGetDriver(iDr);
+
+            if( GDALGetMetadataItem( hDriver, GDAL_DCAP_RASTER, NULL) != NULL &&
+                (GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) != NULL
+                || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY, NULL ) != NULL) )
+            {
+                printf( "  %s: %s\n",
+                        GDALGetDriverShortName( hDriver ),
+                        GDALGetDriverLongName( hDriver ) );
+            }
+        }
+    }
+
+    if( pszErrorMsg != NULL )
+        fprintf(stderr, "\nFAILURE: %s\n", pszErrorMsg);
+
+    exit(1);
+}
+
+/************************************************************************/
+/*                       GDALTranslateOptionsForBinaryNew()             */
+/************************************************************************/
+
+static GDALTranslateOptionsForBinary *GDALTranslateOptionsForBinaryNew(void)
+{
+    return (GDALTranslateOptionsForBinary*) CPLCalloc(  1, sizeof(GDALTranslateOptionsForBinary) );
+}
+
+/************************************************************************/
+/*                       GDALTranslateOptionsForBinaryFree()            */
+/************************************************************************/
+
+static void GDALTranslateOptionsForBinaryFree( GDALTranslateOptionsForBinary* psOptionsForBinary )
+{
+    if( psOptionsForBinary )
+    {
+        CPLFree(psOptionsForBinary->pszSource);
+        CPLFree(psOptionsForBinary->pszDest);
+        CSLDestroy(psOptionsForBinary->papszOpenOptions);
+        CPLFree(psOptionsForBinary->pszFormat);
+        CPLFree(psOptionsForBinary);
+    }
+}
+
+/************************************************************************/
+/*                                main()                                */
+/************************************************************************/
+
+int main( int argc, char ** argv )
+
+{
+    GDALDatasetH    hDataset, hOutDS;
+    int bUsageError;
+
+    /* Check strict compilation and runtime library version as we use C++ API */
+    if (! GDAL_CHECK_VERSION(argv[0]))
+        exit(1);
+
+    EarlySetConfigOptions(argc, argv);
+
+/* -------------------------------------------------------------------- */
+/*      Register standard GDAL drivers, and process generic GDAL        */
+/*      command options.                                                */
+/* -------------------------------------------------------------------- */
+    GDALAllRegister();
+    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
+    if( argc < 1 )
+        exit( -argc );
+
+    for( int i = 0; argv != NULL && argv[i] != NULL; i++ )
+    {
+        if( EQUAL(argv[i], "--utility_version") )
+        {
+            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
+                   argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
+            CSLDestroy( argv );
+            return 0;
+        }
+        else if( EQUAL(argv[i],"--help") )
+        {
+            Usage(NULL);
+        }
+        else if ( EQUAL(argv[i], "--long-usage") )
+        {
+            Usage(NULL, FALSE);
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Set optimal setting for best performance with huge input VRT.   */
+/*      The rationale for 450 is that typical Linux process allow       */
+/*      only 1024 file descriptors per process and we need to keep some */
+/*      spare for shared libraries, etc. so let's go down to 900.       */
+/*      And some datasets may need 2 file descriptors, so divide by 2   */
+/*      for security.                                                   */
+/* -------------------------------------------------------------------- */
+    if( CPLGetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", NULL) == NULL )
+    {
+        CPLSetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", "450");
+    }
+
+    GDALTranslateOptionsForBinary* psOptionsForBinary = GDALTranslateOptionsForBinaryNew();
+    GDALTranslateOptions *psOptions = GDALTranslateOptionsNew(argv + 1, psOptionsForBinary);
+    CSLDestroy( argv );
+
+    if( psOptions == NULL )
+    {
+        Usage(NULL);
+    }
+
+    if( psOptionsForBinary->pszSource == NULL )
+    {
+        Usage("No source dataset specified.");
+    }
+
+    if( psOptionsForBinary->pszDest == NULL )
+    {
+        Usage("No target dataset specified.");
+    }
+
+    if( strcmp(psOptionsForBinary->pszDest, "/vsistdout/") == 0 )
+    {
+        psOptionsForBinary->bQuiet = TRUE;
+    }
+
+    if( !(psOptionsForBinary->bQuiet) )
+    {
+        GDALTranslateOptionsSetProgress(psOptions, GDALTermProgress, NULL);
+    }
+
+    if (!psOptionsForBinary->bQuiet && !psOptionsForBinary->bFormatExplicitlySet)
+        CheckExtensionConsistency(psOptionsForBinary->pszDest, psOptionsForBinary->pszFormat);
+
+/* -------------------------------------------------------------------- */
+/*      Attempt to open source file.                                    */
+/* -------------------------------------------------------------------- */
+
+    hDataset = GDALOpenEx( psOptionsForBinary->pszSource, GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR, NULL,
+                           (const char* const* )psOptionsForBinary->papszOpenOptions, NULL );
+
+    if( hDataset == NULL )
+    {
+        GDALDestroyDriverManager();
+        exit( 1 );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Handle subdatasets.                                             */
+/* -------------------------------------------------------------------- */
+    if( !psOptionsForBinary->bCopySubDatasets
+        && CSLCount(GDALGetMetadata( hDataset, "SUBDATASETS" )) > 0
+        && GDALGetRasterCount(hDataset) == 0 )
+    {
+        fprintf( stderr,
+                 "Input file contains subdatasets. Please, select one of them for reading.\n" );
+        GDALClose( hDataset );
+        GDALDestroyDriverManager();
+        exit( 1 );
+    }
+
+    if( CSLCount(GDALGetMetadata( hDataset, "SUBDATASETS" )) > 0
+        && psOptionsForBinary->bCopySubDatasets )
+    {
+        char **papszSubdatasets = GDALGetMetadata(hDataset,"SUBDATASETS");
+        char *pszSubDest = (char *) CPLMalloc(strlen(psOptionsForBinary->pszDest)+32);
+        int i;
+
+        CPLString osPath = CPLGetPath(psOptionsForBinary->pszDest);
+        CPLString osBasename = CPLGetBasename(psOptionsForBinary->pszDest);
+        CPLString osExtension = CPLGetExtension(psOptionsForBinary->pszDest);
+        CPLString osTemp;
+
+        const char* pszFormat = NULL;
+        if ( CSLCount(papszSubdatasets)/2 < 10 )
+        {
+            pszFormat = "%s_%d";
+        }
+        else if ( CSLCount(papszSubdatasets)/2 < 100 )
+        {
+            pszFormat = "%s_%002d";
+        }
+        else
+        {
+            pszFormat = "%s_%003d";
+        }
+
+        const char* pszDest = pszSubDest;
+
+        for( i = 0; papszSubdatasets[i] != NULL; i += 2 )
+        {
+            char* pszSource = CPLStrdup(strstr(papszSubdatasets[i],"=")+1);
+            osTemp = CPLSPrintf( pszFormat, osBasename.c_str(), i/2 + 1 );
+            osTemp = CPLFormFilename( osPath, osTemp, osExtension );
+            strcpy( pszSubDest, osTemp.c_str() );
+            hDataset = GDALOpenEx( pszSource, GDAL_OF_RASTER, NULL,
+                           (const char* const* )psOptionsForBinary->papszOpenOptions, NULL );
+            CPLFree(pszSource);
+            if( !psOptionsForBinary->bQuiet )
+                printf("Input file size is %d, %d\n", GDALGetRasterXSize(hDataset), GDALGetRasterYSize(hDataset));
+            hOutDS = GDALTranslate(pszDest, hDataset, psOptions, &bUsageError);
+            if(bUsageError == TRUE)
+                Usage();
+            if (hOutDS == NULL)
+                break;
+            GDALClose(hOutDS);
+        }
+
+        GDALClose(hDataset);
+        GDALTranslateOptionsFree(psOptions);
+        GDALTranslateOptionsForBinaryFree(psOptionsForBinary);
+        CPLFree(pszSubDest);
+
+        GDALDestroyDriverManager();
+        return 0;
+
+    }
+
+    if( !psOptionsForBinary->bQuiet )
+        printf("Input file size is %d, %d\n", GDALGetRasterXSize(hDataset), GDALGetRasterYSize(hDataset));
+
+    hOutDS = GDALTranslate(psOptionsForBinary->pszDest, hDataset, psOptions, &bUsageError);
+    if(bUsageError == TRUE)
+        Usage();
+    int nRetCode = (hOutDS) ? 0 : 1;
+
+    /* Close hOutDS before hDataset for the -f VRT case */
+    GDALClose(hOutDS);
+    GDALClose(hDataset);
+    GDALTranslateOptionsFree(psOptions);
+    GDALTranslateOptionsForBinaryFree(psOptionsForBinary);
+
+    GDALDestroyDriverManager();
+
+    return nRetCode;
+}
diff --git a/apps/gdal_translate_lib.cpp b/apps/gdal_translate_lib.cpp
new file mode 100644
index 0000000..f8765f4
--- /dev/null
+++ b/apps/gdal_translate_lib.cpp
@@ -0,0 +1,2207 @@
+/******************************************************************************
+ * $Id: gdal_translate_lib.cpp 33615 2016-03-02 20:19:22Z goatbar $
+ *
+ * Project:  GDAL Utilities
+ * Purpose:  GDAL Image Translator Program
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1998, 2002, Frank Warmerdam
+ * Copyright (c) 2007-2015, Even Rouault <even dot rouault at mines-paris dot org>
+ * Copyright (c) 2015, Faza Mahamood
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_vsi.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "gdal_priv.h"
+#include "ogr_spatialref.h"
+#include "vrtdataset.h"
+#include "commonutils.h"
+#include "gdal_utils_priv.h"
+
+CPL_CVSID("$Id: gdal_translate_lib.cpp 33615 2016-03-02 20:19:22Z goatbar $");
+
+static int ArgIsNumeric( const char * );
+static void AttachMetadata( GDALDatasetH, char ** );
+static void CopyBandInfo( GDALRasterBand * poSrcBand, GDALRasterBand * poDstBand,
+                            int bCanCopyStatsMetadata, int bCopyScale, int bCopyNoData );
+
+typedef enum
+{
+    MASK_DISABLED,
+    MASK_AUTO,
+    MASK_USER
+} MaskMode;
+
+/************************************************************************/
+/*                         GDALTranslateScaleParams                     */
+/************************************************************************/
+
+/** scaling parameters for use in GDALTranslateOptions.
+ */
+typedef struct
+{
+    /*! scaling is done only if it is set to TRUE. This is helpful when there is a need to
+        scale only certain bands. */
+    int     bScale;
+
+    /*! set it to TRUE if dfScaleSrcMin and dfScaleSrcMax is set. When it is FALSE, the
+        input range is automatically computed from the source data. */
+    int     bHaveScaleSrc;
+
+    /*! the range of input pixel values which need to be scaled */
+    double  dfScaleSrcMin, dfScaleSrcMax;
+
+    /*! the range of output pixel values. If GDALTranslateScaleParams::dfScaleDstMin
+        and GDALTranslateScaleParams::dfScaleDstMax are not set, then the output
+        range is 0 to 255. */
+    double  dfScaleDstMin, dfScaleDstMax;
+} GDALTranslateScaleParams;
+
+/************************************************************************/
+/*                         GDALTranslateOptions                         */
+/************************************************************************/
+
+/** Options for use with GDALTranslate(). GDALTranslateOptions* must be allocated
+ * and freed with GDALTranslateOptionsNew() and GDALTranslateOptionsFree() respectively.
+ */
+struct GDALTranslateOptions
+{
+
+    /*! output format. The default is GeoTIFF(GTiff). Use the short format name. */
+    char *pszFormat;
+
+    /*! allow or suppress progress monitor and other non-error output */
+    int bQuiet;
+
+    /*! the progress function to use */
+    GDALProgressFunc pfnProgress;
+
+    /*! pointer to the progress data variable */
+    void *pProgressData;
+
+    /*! for the output bands to be of the indicated data type */
+    GDALDataType eOutputType;
+
+    MaskMode eMaskMode;
+
+    /*! number of input bands to write to the output file, or to reorder bands */
+    int nBandCount;
+
+    /*! list of input bands to write to the output file, or to reorder bands. The
+        value 1 corresponds to the 1st band. */
+    int *panBandList; /* negative value of panBandList[i] means mask band of ABS(panBandList[i]) */
+
+    /*! size of the output file. GDALTranslateOptions::nOXSizePixel is in pixels and
+        GDALTranslateOptions::nOYSizePixel is in lines. If one of the two values is
+        set to 0, its value will be determined from the other one, while maintaining
+        the aspect ratio of the source dataset */
+    int nOXSizePixel;
+    int nOYSizePixel;
+
+    /*! size of the output file. GDALTranslateOptions::dfOXSizePct and GDALTranslateOptions::dfOYSizePct
+        are fraction of the input image size. The value 100 means 100%. If one of the two values is set
+        to 0, its value will be determined from the other one, while maintaining the aspect ratio of the
+        source dataset */
+    double dfOXSizePct;
+    double dfOYSizePct;
+
+    /*! list of creation options to the output format driver */
+    char **papszCreateOptions;
+
+    /*! subwindow from the source image for copying based on pixel/line location */
+    double adfSrcWin[4];
+
+    /*! don't be forgiving of mismatches and lost data when translating to the output format */
+    int bStrict;
+
+    /*! apply the scale/offset metadata for the bands to convert scaled values to unscaled values.
+     *  It is also often necessary to reset the output datatype with GDALTranslateOptions::eOutputType */
+    int bUnscale;
+
+    /*! the size of pasScaleParams */
+    int nScaleRepeat;
+
+    /*! the list of scale parameters for each band. */
+    GDALTranslateScaleParams *pasScaleParams;
+
+    /*! It is set to TRUE, when scale parameters are specific to each band */
+    int bHasUsedExplicitScaleBand;
+
+    /*! the size of the list padfExponent */
+    int nExponentRepeat;
+
+    /*! to apply non-linear scaling with a power function. It is the list of exponents of the power
+        function (must be positive). This option must be used with GDALTranslateOptions::pasScaleParams. If
+        GDALTranslateOptions::nExponentRepeat is 1, it is applied to all bands of the output image. */
+    double *padfExponent;
+
+    int bHasUsedExplicitExponentBand;
+
+    /*! list of metadata key and value to set on the output dataset if possible.
+     *  GDALTranslateOptionsSetMetadataOptions() and GDALTranslateOptionsAddMetadataOptions()
+     *  should be used */
+    char **papszMetadataOptions;
+
+    /*! override the projection for the output file. The SRS may be any of the usual
+        GDAL/OGR forms, complete WKT, PROJ.4, EPSG:n or a file containing the WKT. */
+    char *pszOutputSRS;
+
+    /*! number of GCPS to be added to the output dataset */
+    int nGCPCount;
+
+    /*! list of GCPs to be added to the output dataset */
+    GDAL_GCP *pasGCPs;
+
+    /*! assign/override the georeferenced bounds of the output file. This assigns
+        georeferenced bounds to the output file, ignoring what would have been
+        derived from the source file. So this does not cause reprojection to the
+        specified SRS. */
+    double adfULLR[4];
+
+    /*! set a nodata value specified in GDALTranslateOptions::dfNoDataReal to the output bands */
+    int bSetNoData;
+
+    /*! avoid setting a nodata value to the output file if one exists for the source file */
+    int bUnsetNoData;
+
+    /*! Assign a specified nodata value to output bands ( GDALTranslateOptions::bSetNoData option
+        should be set). Note that if the input dataset has a nodata value, this does not cause
+        pixel values that are equal to that nodata value to be changed to the value specified. */
+    double dfNoDataReal;
+
+    /*! to expose a dataset with 1 band with a color table as a dataset with
+        3 (RGB) or 4 (RGBA) bands. Useful for output drivers such as JPEG,
+        JPEG2000, MrSID, ECW that don't support color indexed datasets.
+        The 1 value enables to expand a dataset with a color table that only
+        contains gray levels to a gray indexed dataset. */
+    int nRGBExpand;
+
+    int nMaskBand; /* negative value means mask band of ABS(nMaskBand) */
+
+    /*! force recomputation of statistics */
+    int bStats;
+
+    int bApproxStats;
+
+    /*! If this option is set, GDALTranslateOptions::adfSrcWin or (GDALTranslateOptions::dfULX,
+        GDALTranslateOptions::dfULY, GDALTranslateOptions::dfLRX, GDALTranslateOptions::dfLRY)
+        values that falls partially outside the source raster extent will be considered
+        as an error. The default behaviour is to accept such requests. */
+    int bErrorOnPartiallyOutside;
+
+    /*! Same as bErrorOnPartiallyOutside, except that the criterion for
+        erroring out is when the request falls completely outside the
+        source raster extent. */
+    int bErrorOnCompletelyOutside;
+
+    /*! does not copy source RAT into destination dataset (when TRUE) */
+    int bNoRAT;
+
+    /*! resampling algorithm
+        nearest (default), bilinear, cubic, cubicspline, lanczos, average, mode */
+    char *pszResampling;
+
+    /*! target resolution. The values must be expressed in georeferenced units.
+        Both must be positive values. This is exclusive with GDALTranslateOptions::nOXSizePixel
+        (or GDALTranslateOptions::dfOXSizePct), GDALTranslateOptions::nOYSizePixel
+        (or GDALTranslateOptions::dfOYSizePct) and GDALTranslateOptions::adfULLR */
+    double dfXRes;
+    double dfYRes;
+
+    /*! subwindow from the source image for copying (like GDALTranslateOptions::adfSrcWin)
+        but with the corners given in georeferenced coordinates (by default
+        expressed in the SRS of the dataset. Can be changed with
+        pszProjSRS) */
+    double dfULX;
+    double dfULY;
+    double dfLRX;
+    double dfLRY;
+
+    /*! SRS in which to interpret the coordinates given with GDALTranslateOptions::dfULX,
+        GDALTranslateOptions::dfULY, GDALTranslateOptions::dfLRX, GDALTranslateOptions::dfLRY.
+        The SRS may be any of the usual GDAL/OGR forms, complete WKT, PROJ.4, EPSG:n or
+        a file containing the WKT. Note that this does not cause reprojection of the
+        dataset to the specified SRS. */
+    char *pszProjSRS;
+
+};
+
+/************************************************************************/
+/*                              SrcToDst()                              */
+/************************************************************************/
+
+static void SrcToDst( double dfX, double dfY,
+                      double dfSrcXOff, double dfSrcYOff,
+                      double dfSrcXSize, double dfSrcYSize,
+                      double dfDstXOff, double dfDstYOff,
+                      double dfDstXSize, double dfDstYSize,
+                      double &dfXOut, double &dfYOut )
+
+{
+    dfXOut = ((dfX - dfSrcXOff) / dfSrcXSize) * dfDstXSize + dfDstXOff;
+    dfYOut = ((dfY - dfSrcYOff) / dfSrcYSize) * dfDstYSize + dfDstYOff;
+}
+
+/************************************************************************/
+/*                          GetSrcDstWindow()                           */
+/************************************************************************/
+
+static int FixSrcDstWindow( double* padfSrcWin, double* padfDstWin,
+                            int nSrcRasterXSize,
+                            int nSrcRasterYSize )
+
+{
+    const double dfSrcXOff = padfSrcWin[0];
+    const double dfSrcYOff = padfSrcWin[1];
+    const double dfSrcXSize = padfSrcWin[2];
+    const double dfSrcYSize = padfSrcWin[3];
+
+    const double dfDstXOff = padfDstWin[0];
+    const double dfDstYOff = padfDstWin[1];
+    const double dfDstXSize = padfDstWin[2];
+    const double dfDstYSize = padfDstWin[3];
+
+    int bModifiedX = FALSE, bModifiedY = FALSE;
+
+    double dfModifiedSrcXOff = dfSrcXOff;
+    double dfModifiedSrcYOff = dfSrcYOff;
+
+    double dfModifiedSrcXSize = dfSrcXSize;
+    double dfModifiedSrcYSize = dfSrcYSize;
+
+/* -------------------------------------------------------------------- */
+/*      Clamp within the bounds of the available source data.           */
+/* -------------------------------------------------------------------- */
+    if( dfModifiedSrcXOff < 0 )
+    {
+        dfModifiedSrcXSize += dfModifiedSrcXOff;
+        dfModifiedSrcXOff = 0;
+
+        bModifiedX = TRUE;
+    }
+
+    if( dfModifiedSrcYOff < 0 )
+    {
+        dfModifiedSrcYSize += dfModifiedSrcYOff;
+        dfModifiedSrcYOff = 0;
+        bModifiedY = TRUE;
+    }
+
+    if( dfModifiedSrcXOff + dfModifiedSrcXSize > nSrcRasterXSize )
+    {
+        dfModifiedSrcXSize = nSrcRasterXSize - dfModifiedSrcXOff;
+        bModifiedX = TRUE;
+    }
+
+    if( dfModifiedSrcYOff + dfModifiedSrcYSize > nSrcRasterYSize )
+    {
+        dfModifiedSrcYSize = nSrcRasterYSize - dfModifiedSrcYOff;
+        bModifiedY = TRUE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Don't do anything if the requesting region is completely off    */
+/*      the source image.                                               */
+/* -------------------------------------------------------------------- */
+    if( dfModifiedSrcXOff >= nSrcRasterXSize
+        || dfModifiedSrcYOff >= nSrcRasterYSize
+        || dfModifiedSrcXSize <= 0 || dfModifiedSrcYSize <= 0 )
+    {
+        return FALSE;
+    }
+
+    padfSrcWin[0] = dfModifiedSrcXOff;
+    padfSrcWin[1] = dfModifiedSrcYOff;
+    padfSrcWin[2] = dfModifiedSrcXSize;
+    padfSrcWin[3] = dfModifiedSrcYSize;
+
+/* -------------------------------------------------------------------- */
+/*      If we haven't had to modify the source rectangle, then the      */
+/*      destination rectangle must be the whole region.                 */
+/* -------------------------------------------------------------------- */
+    if( !bModifiedX && !bModifiedY )
+        return TRUE;
+
+/* -------------------------------------------------------------------- */
+/*      Now transform this possibly reduced request back into the       */
+/*      destination buffer coordinates in case the output region is     */
+/*      less than the whole buffer.                                     */
+/* -------------------------------------------------------------------- */
+    double dfDstULX, dfDstULY, dfDstLRX, dfDstLRY;
+
+    SrcToDst( dfModifiedSrcXOff, dfModifiedSrcYOff,
+              dfSrcXOff, dfSrcYOff,
+              dfSrcXSize, dfSrcYSize,
+              dfDstXOff, dfDstYOff,
+              dfDstXSize, dfDstYSize,
+              dfDstULX, dfDstULY );
+    SrcToDst( dfModifiedSrcXOff + dfModifiedSrcXSize, dfModifiedSrcYOff + dfModifiedSrcYSize,
+              dfSrcXOff, dfSrcYOff,
+              dfSrcXSize, dfSrcYSize,
+              dfDstXOff, dfDstYOff,
+              dfDstXSize, dfDstYSize,
+              dfDstLRX, dfDstLRY );
+
+    double dfModifiedDstXOff = dfDstXOff;
+    double dfModifiedDstYOff = dfDstYOff;
+    double dfModifiedDstXSize = dfDstXSize;
+    double dfModifiedDstYSize = dfDstYSize;
+
+    if( bModifiedX )
+    {
+        dfModifiedDstXOff = dfDstULX - dfDstXOff;
+        dfModifiedDstXSize = (dfDstLRX - dfDstXOff) - dfModifiedDstXOff;
+
+        dfModifiedDstXOff = MAX(0,dfModifiedDstXOff);
+        if( dfModifiedDstXOff + dfModifiedDstXSize > dfDstXSize )
+            dfModifiedDstXSize = dfDstXSize - dfModifiedDstXOff;
+    }
+
+    if( bModifiedY )
+    {
+        dfModifiedDstYOff = dfDstULY - dfDstYOff;
+        dfModifiedDstYSize = (dfDstLRY - dfDstYOff) - dfModifiedDstYOff;
+
+        dfModifiedDstYOff = MAX(0,dfModifiedDstYOff);
+        if( dfModifiedDstYOff + dfModifiedDstYSize > dfDstYSize )
+            dfModifiedDstYSize = dfDstYSize - dfModifiedDstYOff;
+    }
+
+    if( dfModifiedDstXSize <= 0.0 || dfModifiedDstYSize <= 0.0 )
+        return FALSE;
+    else
+    {
+        padfDstWin[0] = dfModifiedDstXOff;
+        padfDstWin[1] = dfModifiedDstYOff;
+        padfDstWin[2] = dfModifiedDstXSize;
+        padfDstWin[3] = dfModifiedDstYSize;
+
+        return TRUE;
+    }
+}
+
+/************************************************************************/
+/*                          GDALTranslateOptionsClone()                 */
+/************************************************************************/
+
+static
+GDALTranslateOptions* GDALTranslateOptionsClone(const GDALTranslateOptions *psOptionsIn)
+{
+    GDALTranslateOptions* psOptions = (GDALTranslateOptions*) CPLMalloc(sizeof(GDALTranslateOptions));
+    memcpy(psOptions, psOptionsIn, sizeof(GDALTranslateOptions));
+    psOptions->pszFormat = CPLStrdup(psOptionsIn->pszFormat);
+    if( psOptionsIn->panBandList )
+    {
+        psOptions->panBandList = (int*)CPLMalloc(sizeof(int) * psOptions->nBandCount);
+        memcpy(psOptions->panBandList, psOptionsIn->panBandList,
+               sizeof(int) * psOptions->nBandCount);
+    }
+    psOptions->papszCreateOptions = CSLDuplicate(psOptionsIn->papszCreateOptions);
+    if( psOptionsIn->pasScaleParams )
+    {
+        psOptions->pasScaleParams = (GDALTranslateScaleParams*)CPLMalloc(sizeof(GDALTranslateScaleParams) * psOptions->nScaleRepeat);
+        memcpy(psOptions->pasScaleParams, psOptionsIn->pasScaleParams,
+               sizeof(GDALTranslateScaleParams) * psOptions->nScaleRepeat);
+    }
+    if( psOptionsIn->padfExponent )
+    {
+        psOptions->padfExponent = (double*)CPLMalloc(sizeof(double) * psOptions->nExponentRepeat);
+        memcpy(psOptions->padfExponent, psOptionsIn->padfExponent,
+               sizeof(double) * psOptions->nExponentRepeat);
+    }
+    psOptions->papszMetadataOptions = CSLDuplicate(psOptionsIn->papszMetadataOptions);
+    if( psOptionsIn->pszOutputSRS ) psOptions->pszOutputSRS = CPLStrdup(psOptionsIn->pszOutputSRS);
+    if( psOptionsIn->nGCPCount )
+        psOptions->pasGCPs = GDALDuplicateGCPs( psOptionsIn->nGCPCount, psOptionsIn->pasGCPs );
+    if( psOptionsIn->pszResampling ) psOptions->pszResampling = CPLStrdup(psOptionsIn->pszResampling);
+    if( psOptionsIn->pszProjSRS ) psOptions->pszProjSRS = CPLStrdup(psOptionsIn->pszProjSRS);
+    return psOptions;
+}
+
+/************************************************************************/
+/*                        GDALTranslateFlush()                          */
+/************************************************************************/
+
+static GDALDatasetH GDALTranslateFlush(GDALDatasetH hOutDS)
+{
+    if( hOutDS != NULL )
+    {
+        CPLErr eErrBefore = CPLGetLastErrorType();
+        GDALFlushCache( hOutDS );
+        if (eErrBefore == CE_None &&
+            CPLGetLastErrorType() != CE_None)
+        {
+            GDALClose(hOutDS);
+            hOutDS = NULL;
+        }
+    }
+    return hOutDS;
+}
+
+/************************************************************************/
+/*                             GDALTranslate()                          */
+/************************************************************************/
+
+/**
+ * Converts raster data between different formats.
+ *
+ * This is the equivalent of the <a href="gdal_translate.html">gdal_translate</a> utility.
+ *
+ * GDALTranslateOptions* must be allocated and freed with GDALTranslateOptionsNew()
+ * and GDALTranslateOptionsFree() respectively.
+ *
+ * @param pszDest the destination dataset path.
+ * @param hSrcDataset the source dataset handle.
+ * @param psOptionsIn the options struct returned by GDALTranslateOptionsNew() or NULL.
+ * @param pbUsageError the pointer to int variable to determine any usage error has occurred or NULL.
+ * @return the output dataset (new dataset that must be closed using GDALClose()) or NULL in case of error.
+ *
+ * @since GDAL 2.1
+ */
+
+GDALDatasetH GDALTranslate( const char *pszDest, GDALDatasetH hSrcDataset,
+                            const GDALTranslateOptions *psOptionsIn, int *pbUsageError )
+
+{
+    CPLErrorReset();
+    if( hSrcDataset == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "No source dataset specified.");
+
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        return NULL;
+    }
+    if( pszDest == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "No target dataset specified.");
+
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        return NULL;
+    }
+
+    GDALTranslateOptions* psOptions =
+        (psOptionsIn) ? GDALTranslateOptionsClone(psOptionsIn) :
+                        GDALTranslateOptionsNew(NULL, NULL);
+
+    GDALDatasetH hOutDS;
+    int			i;
+    int			nRasterXSize, nRasterYSize;
+    GDALDriverH		hDriver;
+    int			nOXSize = 0, nOYSize = 0;
+    const char          *pszProjection;
+    const char *pszSource = NULL;
+    int bGotBounds = FALSE;
+    int bAllBandsInOrder = TRUE;
+    CPLString osProjSRS;
+
+    if(pbUsageError)
+        *pbUsageError = FALSE;
+
+    if(psOptions->adfULLR[0] != 0.0 || psOptions->adfULLR[1] != 0.0 || psOptions->adfULLR[2] != 0.0 || psOptions->adfULLR[3] != 0.0)
+        bGotBounds = TRUE;
+
+    pszSource = GDALGetDescription(hSrcDataset);
+
+    if( strcmp(pszSource, pszDest) == 0 && pszSource[0] != '\0' &&
+        GDALGetDatasetDriver(hSrcDataset) != GDALGetDriverByName("MEM") )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Source and destination datasets must be different.");
+
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        GDALTranslateOptionsFree(psOptions);
+        return NULL;
+    }
+
+    if(psOptions->pszProjSRS != NULL)
+    {
+        OGRSpatialReference oSRS;
+
+        if( oSRS.SetFromUserInput( psOptions->pszProjSRS ) != OGRERR_NONE )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "Failed to process SRS definition: %s",
+                      psOptions->pszProjSRS );
+            GDALTranslateOptionsFree(psOptions);
+            return NULL;
+        }
+
+        char* pszSRS = NULL;
+        oSRS.exportToWkt( &pszSRS );
+        if( pszSRS )
+            osProjSRS = pszSRS;
+        CPLFree( pszSRS );
+    }
+
+    if(psOptions->pszOutputSRS != NULL)
+    {
+        OGRSpatialReference oOutputSRS;
+
+        if( oOutputSRS.SetFromUserInput( psOptions->pszOutputSRS ) != OGRERR_NONE )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "Failed to process SRS definition: %s",
+                      psOptions->pszOutputSRS );
+            GDALTranslateOptionsFree(psOptions);
+            return NULL;
+        }
+
+        char* pszSRS = NULL;
+        oOutputSRS.exportToWkt( &pszSRS );
+        CPLFree( psOptions->pszOutputSRS );
+        psOptions->pszOutputSRS = CPLStrdup( pszSRS );
+        CPLFree( pszSRS );
+
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Check that incompatible options are not used                    */
+/* -------------------------------------------------------------------- */
+
+    if( (psOptions->nOXSizePixel != 0 || psOptions->dfOXSizePct != 0.0 || psOptions->nOYSizePixel != 0 ||
+         psOptions->dfOYSizePct) && (psOptions->dfXRes != 0 && psOptions->dfYRes != 0) )
+    {
+        CPLError( CE_Failure, CPLE_IllegalArg, "-outsize and -tr options cannot be used at the same time.");
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        GDALTranslateOptionsFree(psOptions);
+        return NULL;
+    }
+    if( bGotBounds &&  (psOptions->dfXRes != 0 && psOptions->dfYRes != 0) )
+    {
+        CPLError( CE_Failure, CPLE_IllegalArg, "-a_ullr and -tr options cannot be used at the same time.");
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        GDALTranslateOptionsFree(psOptions);
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Collect some information from the source file.                  */
+/* -------------------------------------------------------------------- */
+    nRasterXSize = GDALGetRasterXSize( hSrcDataset );
+    nRasterYSize = GDALGetRasterYSize( hSrcDataset );
+
+    if( psOptions->adfSrcWin[2] == 0 && psOptions->adfSrcWin[3] == 0 )
+    {
+        psOptions->adfSrcWin[2] = nRasterXSize;
+        psOptions->adfSrcWin[3] = nRasterYSize;
+    }
+
+/* -------------------------------------------------------------------- */
+/*	Build band list to translate					*/
+/* -------------------------------------------------------------------- */
+    if( psOptions->panBandList == NULL )
+    {
+        psOptions->nBandCount = GDALGetRasterCount( hSrcDataset );
+        if( psOptions->nBandCount == 0 )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "Input file has no bands, and so cannot be translated." );
+            GDALTranslateOptionsFree(psOptions);
+            return NULL;
+        }
+
+        psOptions->panBandList = (int *) CPLMalloc(sizeof(int)*psOptions->nBandCount);
+        for( i = 0; i < psOptions->nBandCount; i++ )
+            psOptions->panBandList[i] = i+1;
+    }
+    else
+    {
+        for( i = 0; i < psOptions->nBandCount; i++ )
+        {
+            if( ABS(psOptions->panBandList[i]) > GDALGetRasterCount(hSrcDataset) )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                         "Band %d requested, but only bands 1 to %d available.",
+                         ABS(psOptions->panBandList[i]), GDALGetRasterCount(hSrcDataset) );
+                GDALTranslateOptionsFree(psOptions);
+                return NULL;
+            }
+
+            if( psOptions->panBandList[i] != i+1 )
+                bAllBandsInOrder = FALSE;
+        }
+
+        if( psOptions->nBandCount != GDALGetRasterCount( hSrcDataset ) )
+            bAllBandsInOrder = FALSE;
+    }
+
+    if( psOptions->nScaleRepeat > psOptions->nBandCount )
+    {
+        if( !psOptions->bHasUsedExplicitScaleBand )
+            CPLError( CE_Failure, CPLE_IllegalArg, "-scale has been specified more times than the number of output bands");
+        else
+            CPLError( CE_Failure, CPLE_IllegalArg, "-scale_XX has been specified with XX greater than the number of output bands");
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        GDALTranslateOptionsFree(psOptions);
+        return NULL;
+    }
+
+    if( psOptions->nExponentRepeat > psOptions->nBandCount )
+    {
+        if( !psOptions->bHasUsedExplicitExponentBand )
+            CPLError( CE_Failure, CPLE_IllegalArg, "-exponent has been specified more times than the number of output bands");
+        else
+            CPLError( CE_Failure, CPLE_IllegalArg, "-exponent_XX has been specified with XX greater than the number of output bands");
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        GDALTranslateOptionsFree(psOptions);
+        return NULL;
+    }
+/* -------------------------------------------------------------------- */
+/*      Compute the source window from the projected source window      */
+/*      if the projected coordinates were provided.  Note that the      */
+/*      projected coordinates are in ulx, uly, lrx, lry format,         */
+/*      while the adfSrcWin is xoff, yoff, xsize, ysize with the        */
+/*      xoff,yoff being the ulx, uly in pixel/line.                     */
+/* -------------------------------------------------------------------- */
+    if( psOptions->dfULX != 0.0 || psOptions->dfULY != 0.0
+        || psOptions->dfLRX != 0.0 || psOptions->dfLRY != 0.0 )
+    {
+        double	adfGeoTransform[6];
+
+        GDALGetGeoTransform( hSrcDataset, adfGeoTransform );
+
+        if( adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0 )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                     "The -projwin option was used, but the geotransform is\n"
+                     "rotated.  This configuration is not supported." );
+            GDALTranslateOptionsFree(psOptions);
+            return NULL;
+        }
+
+        if( osProjSRS.size() )
+        {
+            pszProjection = GDALGetProjectionRef( hSrcDataset );
+            if( pszProjection != NULL && strlen(pszProjection) > 0 )
+            {
+                OGRSpatialReference oSRSIn;
+                OGRSpatialReference oSRSDS;
+                oSRSIn.SetFromUserInput(osProjSRS);
+                oSRSDS.SetFromUserInput(pszProjection);
+                if( !oSRSIn.IsSame(&oSRSDS) )
+                {
+                    OGRCoordinateTransformation* poCT = OGRCreateCoordinateTransformation(&oSRSIn, &oSRSDS);
+                    if( !(poCT &&
+                        poCT->Transform(1, &psOptions->dfULX, &psOptions->dfULY) &&
+                        poCT->Transform(1, &psOptions->dfLRX, &psOptions->dfLRY)) )
+                    {
+                        OGRCoordinateTransformation::DestroyCT(poCT);
+
+                        CPLError( CE_Failure, CPLE_AppDefined, "-projwin_srs ignored since coordinate transformation failed.");
+                        GDALTranslateOptionsFree(psOptions);
+                        return NULL;
+                    }
+                    delete poCT;
+                }
+            }
+            else
+            {
+                CPLError( CE_None, CPLE_None, "-projwin_srs ignored since the dataset has no projection.");
+            }
+        }
+
+        psOptions->adfSrcWin[0] = (psOptions->dfULX - adfGeoTransform[0]) / adfGeoTransform[1];
+        psOptions->adfSrcWin[1] = (psOptions->dfULY - adfGeoTransform[3]) / adfGeoTransform[5];
+
+        psOptions->adfSrcWin[2] = (psOptions->dfLRX - psOptions->dfULX) / adfGeoTransform[1];
+        psOptions->adfSrcWin[3] = (psOptions->dfLRY - psOptions->dfULY) / adfGeoTransform[5];
+
+        /*if( !bQuiet )
+            fprintf( stdout,
+                     "Computed -srcwin %g %g %g %g from projected window.\n",
+                     adfSrcWin[0],
+                     adfSrcWin[1],
+                     adfSrcWin[2],
+                     adfSrcWin[3] ); */
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Verify source window dimensions.                                */
+/* -------------------------------------------------------------------- */
+    if( psOptions->adfSrcWin[2] <= 0 || psOptions->adfSrcWin[3] <= 0 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                 "Error: %s-srcwin %g %g %g %g has negative width and/or height.",
+                 ( psOptions->dfULX != 0.0 || psOptions->dfULY != 0.0 || psOptions->dfLRX != 0.0 || psOptions->dfLRY != 0.0 ) ? "Computed " : "",
+                 psOptions->adfSrcWin[0],
+                 psOptions->adfSrcWin[1],
+                 psOptions->adfSrcWin[2],
+                 psOptions->adfSrcWin[3] );
+        GDALTranslateOptionsFree(psOptions);
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Verify source window dimensions.                                */
+/* -------------------------------------------------------------------- */
+    else if( psOptions->adfSrcWin[0] <= -1 || psOptions->adfSrcWin[1] <= -1
+        || psOptions->adfSrcWin[0] + psOptions->adfSrcWin[2] >= GDALGetRasterXSize(hSrcDataset) + 1
+        || psOptions->adfSrcWin[1] + psOptions->adfSrcWin[3] >= GDALGetRasterYSize(hSrcDataset) + 1 )
+    {
+        int bCompletelyOutside = psOptions->adfSrcWin[0] + psOptions->adfSrcWin[2] <= 0 ||
+                                    psOptions->adfSrcWin[1] + psOptions->adfSrcWin[3] <= 0 ||
+                                    psOptions->adfSrcWin[0] >= GDALGetRasterXSize(hSrcDataset) ||
+                                    psOptions->adfSrcWin[1] >= GDALGetRasterYSize(hSrcDataset);
+        int bIsError = psOptions->bErrorOnPartiallyOutside || (bCompletelyOutside && psOptions->bErrorOnCompletelyOutside);
+        if( !psOptions->bQuiet || bIsError )
+        {
+            CPLErr eErr = CE_Warning;
+
+            if(bIsError)
+                eErr = CE_Failure;
+
+            CPLError( eErr, CPLE_AppDefined,
+                 "%s-srcwin %g %g %g %g falls %s outside raster extent.%s",
+                 ( psOptions->dfULX != 0.0 || psOptions->dfULY != 0.0 || psOptions->dfLRX != 0.0 || psOptions->dfLRY != 0.0 ) ? "Computed " : "",
+                 psOptions->adfSrcWin[0],
+                 psOptions->adfSrcWin[1],
+                 psOptions->adfSrcWin[2],
+                 psOptions->adfSrcWin[3],
+                 (bCompletelyOutside) ? "completely" : "partially",
+                 (bIsError) ? "" : " Going on however." );
+        }
+        if( bIsError )
+        {
+            GDALTranslateOptionsFree(psOptions);
+            return NULL;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Find the output driver.                                         */
+/* -------------------------------------------------------------------- */
+    hDriver = GDALGetDriverByName( psOptions->pszFormat );
+    if( hDriver == NULL )
+    {
+        int iDr;
+
+        CPLError( CE_Failure, CPLE_IllegalArg, "Output driver `%s' not recognised.", psOptions->pszFormat);
+        CPLError( CE_Failure, CPLE_IllegalArg, "The following format drivers are configured and support output:" );
+        for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
+        {
+            hDriver = GDALGetDriver(iDr);
+
+            if( GDALGetMetadataItem( hDriver, GDAL_DCAP_RASTER, NULL) != NULL &&
+                (GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) != NULL
+                 || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY, NULL ) != NULL) )
+            {
+                CPLError( CE_Failure, CPLE_IllegalArg, "  %s: %s",
+                        GDALGetDriverShortName( hDriver  ),
+                        GDALGetDriverLongName( hDriver ) );
+            }
+        }
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        GDALTranslateOptionsFree(psOptions);
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      The short form is to CreateCopy().  We use this if the input    */
+/*      matches the whole dataset.  Eventually we should rewrite        */
+/*      this entire program to use virtual datasets to construct a      */
+/*      virtual input source to copy from.                              */
+/* -------------------------------------------------------------------- */
+
+
+    int bSpatialArrangementPreserved = (
+           psOptions->adfSrcWin[0] == 0 && psOptions->adfSrcWin[1] == 0
+        && psOptions->adfSrcWin[2] == GDALGetRasterXSize(hSrcDataset)
+        && psOptions->adfSrcWin[3] == GDALGetRasterYSize(hSrcDataset)
+        && psOptions->nOXSizePixel == 0 && psOptions->dfOXSizePct == 0.0
+        && psOptions->nOYSizePixel == 0 && psOptions->dfOYSizePct == 0.0 && psOptions->dfXRes == 0.0 );
+
+    if( psOptions->eOutputType == GDT_Unknown
+        && psOptions->nScaleRepeat == 0 && psOptions->nExponentRepeat == 0 && !psOptions->bUnscale
+        && CSLCount(psOptions->papszMetadataOptions) == 0 && bAllBandsInOrder
+        && psOptions->eMaskMode == MASK_AUTO
+        && bSpatialArrangementPreserved
+        && psOptions->nGCPCount == 0 && !bGotBounds
+        && psOptions->pszOutputSRS == NULL && !psOptions->bSetNoData && !psOptions->bUnsetNoData
+        && psOptions->nRGBExpand == 0 && !psOptions->bStats && !psOptions->bNoRAT )
+    {
+
+        hOutDS = GDALCreateCopy( hDriver, pszDest, hSrcDataset,
+                                 psOptions->bStrict, psOptions->papszCreateOptions,
+                                 psOptions->pfnProgress, psOptions->pProgressData );
+        hOutDS = GDALTranslateFlush(hOutDS);
+
+        GDALTranslateOptionsFree(psOptions);
+        return hOutDS;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Establish some parameters.                                      */
+/* -------------------------------------------------------------------- */
+    double              adfGeoTransform[6];
+    if( psOptions->dfXRes != 0.0 )
+    {
+        if( !(GDALGetGeoTransform( hSrcDataset, adfGeoTransform ) == CE_None &&
+              psOptions->nGCPCount == 0 &&
+              adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0) )
+        {
+            CPLError( CE_Failure, CPLE_IllegalArg,
+                     "The -tr option was used, but there's no geotransform or it is\n"
+                     "rotated.  This configuration is not supported." );
+            GDALTranslateOptionsFree(psOptions);
+            return NULL;
+        }
+        nOXSize = int(psOptions->adfSrcWin[2] / psOptions->dfXRes * adfGeoTransform[1] + 0.5);
+        nOYSize = int(psOptions->adfSrcWin[3] / psOptions->dfYRes * fabs(adfGeoTransform[5]) + 0.5);
+    }
+    else if( psOptions->nOXSizePixel == 0 && psOptions->dfOXSizePct == 0.0 && psOptions->nOYSizePixel == 0 && psOptions->dfOYSizePct == 0.0)
+    {
+        nOXSize = int(ceil(psOptions->adfSrcWin[2]-0.001));
+        nOYSize = int(ceil(psOptions->adfSrcWin[3]-0.001));
+    }
+    else
+    {
+        if( !(psOptions->nOXSizePixel == 0 && psOptions->dfOXSizePct == 0.0) )
+        {
+            if(psOptions->nOXSizePixel != 0)
+                nOXSize = psOptions->nOXSizePixel;
+            else
+                nOXSize = (int) (psOptions->dfOXSizePct/100*psOptions->adfSrcWin[2]);
+        }
+
+        if( !(psOptions->nOYSizePixel == 0 && psOptions->dfOYSizePct == 0.0) )
+        {
+            if(psOptions->nOYSizePixel != 0)
+                nOYSize = psOptions->nOYSizePixel;
+            else
+                nOYSize = (int) (psOptions->dfOYSizePct/100*psOptions->adfSrcWin[3]);
+        }
+
+        if( psOptions->nOXSizePixel == 0 && psOptions->dfOXSizePct == 0.0 )
+            nOXSize = (int)((double)nOYSize * psOptions->adfSrcWin[2] / psOptions->adfSrcWin[3] + 0.5);
+        else if( psOptions->nOYSizePixel == 0 && psOptions->dfOYSizePct == 0.0 )
+            nOYSize = (int)((double)nOXSize * psOptions->adfSrcWin[3] / psOptions->adfSrcWin[2] + 0.5);
+    }
+
+    if( nOXSize == 0 || nOYSize == 0 )
+    {
+        CPLError( CE_Failure, CPLE_IllegalArg, "Attempt to create %dx%d dataset is illegal.", nOXSize, nOYSize);
+        GDALTranslateOptionsFree(psOptions);
+        return NULL;
+    }
+
+/* ==================================================================== */
+/*      Create a virtual dataset.                                       */
+/* ==================================================================== */
+    VRTDataset *poVDS;
+
+/* -------------------------------------------------------------------- */
+/*      Make a virtual clone.                                           */
+/* -------------------------------------------------------------------- */
+    poVDS = (VRTDataset *) VRTCreate( nOXSize, nOYSize );
+
+    if( psOptions->nGCPCount == 0 )
+    {
+        if( psOptions->pszOutputSRS != NULL )
+        {
+            poVDS->SetProjection( psOptions->pszOutputSRS );
+        }
+        else
+        {
+            pszProjection = GDALGetProjectionRef( hSrcDataset );
+            if( pszProjection != NULL && strlen(pszProjection) > 0 )
+                poVDS->SetProjection( pszProjection );
+        }
+    }
+
+    if( bGotBounds )
+    {
+        adfGeoTransform[0] = psOptions->adfULLR[0];
+        adfGeoTransform[1] = (psOptions->adfULLR[2] - psOptions->adfULLR[0]) / nOXSize;
+        adfGeoTransform[2] = 0.0;
+        adfGeoTransform[3] = psOptions->adfULLR[1];
+        adfGeoTransform[4] = 0.0;
+        adfGeoTransform[5] = (psOptions->adfULLR[3] - psOptions->adfULLR[1]) / nOYSize;
+
+        poVDS->SetGeoTransform( adfGeoTransform );
+    }
+
+    else if( GDALGetGeoTransform( hSrcDataset, adfGeoTransform ) == CE_None
+        && psOptions->nGCPCount == 0 )
+    {
+        adfGeoTransform[0] += psOptions->adfSrcWin[0] * adfGeoTransform[1]
+            + psOptions->adfSrcWin[1] * adfGeoTransform[2];
+        adfGeoTransform[3] += psOptions->adfSrcWin[0] * adfGeoTransform[4]
+            + psOptions->adfSrcWin[1] * adfGeoTransform[5];
+
+        adfGeoTransform[1] *= psOptions->adfSrcWin[2] / (double) nOXSize;
+        adfGeoTransform[2] *= psOptions->adfSrcWin[3] / (double) nOYSize;
+        adfGeoTransform[4] *= psOptions->adfSrcWin[2] / (double) nOXSize;
+        adfGeoTransform[5] *= psOptions->adfSrcWin[3] / (double) nOYSize;
+
+        if( psOptions->dfXRes != 0.0 )
+        {
+            adfGeoTransform[1] = psOptions->dfXRes;
+            adfGeoTransform[5] = (adfGeoTransform[5] > 0) ? psOptions->dfYRes : -psOptions->dfYRes;
+        }
+
+        poVDS->SetGeoTransform( adfGeoTransform );
+    }
+
+    if( psOptions->nGCPCount != 0 )
+    {
+        const char *pszGCPProjection = psOptions->pszOutputSRS;
+
+        if( pszGCPProjection == NULL )
+            pszGCPProjection = GDALGetGCPProjection( hSrcDataset );
+        if( pszGCPProjection == NULL )
+            pszGCPProjection = "";
+
+        poVDS->SetGCPs( psOptions->nGCPCount, psOptions->pasGCPs, pszGCPProjection );
+    }
+
+    else if( GDALGetGCPCount( hSrcDataset ) > 0 )
+    {
+        GDAL_GCP *pasGCPs;
+        int       nGCPs = GDALGetGCPCount( hSrcDataset );
+
+        pasGCPs = GDALDuplicateGCPs( nGCPs, GDALGetGCPs( hSrcDataset ) );
+
+        for( i = 0; i < nGCPs; i++ )
+        {
+            pasGCPs[i].dfGCPPixel -= psOptions->adfSrcWin[0];
+            pasGCPs[i].dfGCPLine  -= psOptions->adfSrcWin[1];
+            pasGCPs[i].dfGCPPixel *= (nOXSize / (double) psOptions->adfSrcWin[2] );
+            pasGCPs[i].dfGCPLine  *= (nOYSize / (double) psOptions->adfSrcWin[3] );
+        }
+
+        poVDS->SetGCPs( nGCPs, pasGCPs,
+                        GDALGetGCPProjection( hSrcDataset ) );
+
+        GDALDeinitGCPs( nGCPs, pasGCPs );
+        CPLFree( pasGCPs );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      To make the VRT to look less awkward (but this is optional      */
+/*      in fact), avoid negative values.                                */
+/* -------------------------------------------------------------------- */
+    double adfDstWin[4];
+    adfDstWin[0] = 0;
+    adfDstWin[1] = 0;
+    adfDstWin[2] = nOXSize;
+    adfDstWin[3] = nOYSize;
+
+    FixSrcDstWindow( psOptions->adfSrcWin, adfDstWin,
+                     GDALGetRasterXSize(hSrcDataset),
+                     GDALGetRasterYSize(hSrcDataset) );
+
+/* -------------------------------------------------------------------- */
+/*      Transfer generally applicable metadata.                         */
+/* -------------------------------------------------------------------- */
+    char** papszMetadata = CSLDuplicate(((GDALDataset*)hSrcDataset)->GetMetadata());
+    if ( psOptions->nScaleRepeat > 0 || psOptions->bUnscale || psOptions->eOutputType != GDT_Unknown )
+    {
+        /* Remove TIFFTAG_MINSAMPLEVALUE and TIFFTAG_MAXSAMPLEVALUE */
+        /* if the data range may change because of options */
+        char** papszIter = papszMetadata;
+        while(papszIter && *papszIter)
+        {
+            if (STARTS_WITH_CI(*papszIter, "TIFFTAG_MINSAMPLEVALUE=") ||
+                STARTS_WITH_CI(*papszIter, "TIFFTAG_MAXSAMPLEVALUE="))
+            {
+                CPLFree(*papszIter);
+                memmove(papszIter, papszIter+1, sizeof(char*) * (CSLCount(papszIter+1)+1));
+            }
+            else
+                papszIter++;
+        }
+    }
+    poVDS->SetMetadata( papszMetadata );
+    CSLDestroy( papszMetadata );
+    AttachMetadata( (GDALDatasetH) poVDS, psOptions->papszMetadataOptions );
+
+    const char* pszInterleave = GDALGetMetadataItem(hSrcDataset, "INTERLEAVE", "IMAGE_STRUCTURE");
+    if (pszInterleave)
+        poVDS->SetMetadataItem("INTERLEAVE", pszInterleave, "IMAGE_STRUCTURE");
+
+/* -------------------------------------------------------------------- */
+/*      Transfer metadata that remains valid if the spatial             */
+/*      arrangement of the data is unaltered.                           */
+/* -------------------------------------------------------------------- */
+    if( bSpatialArrangementPreserved )
+    {
+        char **papszMD;
+
+        papszMD = ((GDALDataset*)hSrcDataset)->GetMetadata("RPC");
+        if( papszMD != NULL )
+            poVDS->SetMetadata( papszMD, "RPC" );
+
+        papszMD = ((GDALDataset*)hSrcDataset)->GetMetadata("GEOLOCATION");
+        if( papszMD != NULL )
+            poVDS->SetMetadata( papszMD, "GEOLOCATION" );
+    }
+    else
+    {
+        char **papszMD;
+
+        papszMD = ((GDALDataset*)hSrcDataset)->GetMetadata("RPC");
+        if( papszMD != NULL )
+        {
+            papszMD = CSLDuplicate(papszMD);
+
+            double dfSAMP_OFF = CPLAtof(CSLFetchNameValueDef(papszMD, "SAMP_OFF", "0"));
+            double dfLINE_OFF = CPLAtof(CSLFetchNameValueDef(papszMD, "LINE_OFF", "0"));
+            double dfSAMP_SCALE = CPLAtof(CSLFetchNameValueDef(papszMD, "SAMP_SCALE", "1"));
+            double dfLINE_SCALE = CPLAtof(CSLFetchNameValueDef(papszMD, "LINE_SCALE", "1"));
+
+            dfSAMP_OFF -= psOptions->adfSrcWin[0];
+            dfLINE_OFF -= psOptions->adfSrcWin[1];
+            dfSAMP_OFF *= (nOXSize / (double) psOptions->adfSrcWin[2] );
+            dfLINE_OFF *= (nOYSize / (double) psOptions->adfSrcWin[3] );
+            dfSAMP_SCALE *= (nOXSize / (double) psOptions->adfSrcWin[2] );
+            dfLINE_SCALE *= (nOYSize / (double) psOptions->adfSrcWin[3] );
+
+            CPLString osField;
+            osField.Printf( "%.15g", dfLINE_OFF );
+            papszMD = CSLSetNameValue( papszMD, "LINE_OFF", osField );
+
+            osField.Printf( "%.15g", dfSAMP_OFF );
+            papszMD = CSLSetNameValue( papszMD, "SAMP_OFF", osField );
+
+            osField.Printf( "%.15g", dfLINE_SCALE );
+            papszMD = CSLSetNameValue( papszMD, "LINE_SCALE", osField );
+
+            osField.Printf( "%.15g", dfSAMP_SCALE );
+            papszMD = CSLSetNameValue( papszMD, "SAMP_SCALE", osField );
+
+            poVDS->SetMetadata( papszMD, "RPC" );
+            CSLDestroy(papszMD);
+        }
+    }
+
+    int nSrcBandCount = psOptions->nBandCount;
+
+    if (psOptions->nRGBExpand != 0)
+    {
+        GDALRasterBand  *poSrcBand;
+        poSrcBand = ((GDALDataset *)
+                     hSrcDataset)->GetRasterBand(ABS(psOptions->panBandList[0]));
+        if (psOptions->panBandList[0] < 0)
+            poSrcBand = poSrcBand->GetMaskBand();
+        GDALColorTable* poColorTable = poSrcBand->GetColorTable();
+        if (poColorTable == NULL)
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "Error : band %d has no color table", ABS(psOptions->panBandList[0]));
+            GDALClose((GDALDatasetH) poVDS);
+            GDALTranslateOptionsFree(psOptions);
+            return NULL;
+        }
+
+        /* Check that the color table only contains gray levels */
+        /* when using -expand gray */
+        if (psOptions->nRGBExpand == 1)
+        {
+            int nColorCount = poColorTable->GetColorEntryCount();
+            int nColor;
+            for( nColor = 0; nColor < nColorCount; nColor++ )
+            {
+                const GDALColorEntry* poEntry = poColorTable->GetColorEntry(nColor);
+                if (poEntry->c1 != poEntry->c2 || poEntry->c1 != poEntry->c3)
+                {
+                    CPLError( CE_Warning, CPLE_AppDefined, "Warning : color table contains non gray levels colors");
+                    break;
+                }
+            }
+        }
+
+        if (psOptions->nBandCount == 1)
+            psOptions->nBandCount = psOptions->nRGBExpand;
+        else if (psOptions->nBandCount == 2 && (psOptions->nRGBExpand == 3 || psOptions->nRGBExpand == 4))
+            psOptions->nBandCount = psOptions->nRGBExpand;
+        else
+        {
+            CPLError( CE_Failure, CPLE_IllegalArg, "Error : invalid use of -expand option.");
+            GDALClose((GDALDatasetH) poVDS);
+            GDALTranslateOptionsFree(psOptions);
+            return NULL;
+        }
+    }
+
+    // Can be set to TRUE in the band loop too
+    int bFilterOutStatsMetadata =
+        (psOptions->nScaleRepeat > 0 || psOptions->bUnscale || !bSpatialArrangementPreserved || psOptions->nRGBExpand != 0);
+
+/* ==================================================================== */
+/*      Process all bands.                                              */
+/* ==================================================================== */
+    for( i = 0; i < psOptions->nBandCount; i++ )
+    {
+        VRTSourcedRasterBand   *poVRTBand;
+        GDALRasterBand  *poSrcBand;
+        GDALDataType    eBandType;
+        int             nComponent = 0;
+
+        int nSrcBand;
+        if (psOptions->nRGBExpand != 0)
+        {
+            if (nSrcBandCount == 2 && psOptions->nRGBExpand == 4 && i == 3)
+                nSrcBand = psOptions->panBandList[1];
+            else
+            {
+                nSrcBand = psOptions->panBandList[0];
+                nComponent = i + 1;
+            }
+        }
+        else
+            nSrcBand = psOptions->panBandList[i];
+
+        poSrcBand = ((GDALDataset *) hSrcDataset)->GetRasterBand(ABS(nSrcBand));
+
+/* -------------------------------------------------------------------- */
+/*      Select output data type to match source.                        */
+/* -------------------------------------------------------------------- */
+        if( psOptions->eOutputType == GDT_Unknown )
+            eBandType = poSrcBand->GetRasterDataType();
+        else
+        {
+            eBandType = psOptions->eOutputType;
+
+            // Check that we can copy existing statistics
+            GDALDataType eSrcBandType = poSrcBand->GetRasterDataType();
+            const char* pszMin = poSrcBand->GetMetadataItem("STATISTICS_MINIMUM");
+            const char* pszMax = poSrcBand->GetMetadataItem("STATISTICS_MAXIMUM");
+            if( !bFilterOutStatsMetadata && eBandType != eSrcBandType &&
+                pszMin != NULL && pszMax != NULL )
+            {
+                int bSrcIsInteger = ( eSrcBandType == GDT_Byte ||
+                                      eSrcBandType == GDT_Int16 ||
+                                      eSrcBandType == GDT_UInt16 ||
+                                      eSrcBandType == GDT_Int32 ||
+                                      eSrcBandType == GDT_UInt32 );
+                int bDstIsInteger = ( eBandType == GDT_Byte ||
+                                      eBandType == GDT_Int16 ||
+                                      eBandType == GDT_UInt16 ||
+                                      eBandType == GDT_Int32 ||
+                                      eBandType == GDT_UInt32 );
+                if( bSrcIsInteger && bDstIsInteger )
+                {
+                    GInt32 nDstMin = 0;
+                    GUInt32 nDstMax = 0;
+                    switch( eBandType )
+                    {
+                        case GDT_Byte:
+                            nDstMin = 0;
+                            nDstMax = 255;
+                            break;
+                        case GDT_UInt16:
+                            nDstMin = 0;
+                            nDstMax = 65535;
+                            break;
+                        case GDT_Int16:
+                            nDstMin = -32768;
+                            nDstMax = 32767;
+                            break;
+                        case GDT_UInt32:
+                            nDstMin = 0;
+                            nDstMax = 0xFFFFFFFFU;
+                            break;
+                        case GDT_Int32:
+                            nDstMin = 0x80000000;
+                            nDstMax = 0x7FFFFFFF;
+                            break;
+                        default:
+                            CPLAssert(FALSE);
+                            break;
+                    }
+
+                    GInt32 nMin = atoi(pszMin);
+                    GUInt32 nMax = (GUInt32)strtoul(pszMax, NULL, 10);
+                    if( nMin < nDstMin || nMax > nDstMax )
+                        bFilterOutStatsMetadata = TRUE;
+                }
+                // Float64 is large enough to hold all integer <= 32 bit or float32 values
+                // there might be other OK cases, but ere on safe side for now
+                else if( !((bSrcIsInteger || eSrcBandType == GDT_Float32) && eBandType == GDT_Float64) )
+                {
+                    bFilterOutStatsMetadata = TRUE;
+                }
+            }
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Create this band.                                               */
+/* -------------------------------------------------------------------- */
+        poVDS->AddBand( eBandType, NULL );
+        poVRTBand = (VRTSourcedRasterBand *) poVDS->GetRasterBand( i+1 );
+        if (nSrcBand < 0)
+        {
+            poVRTBand->AddMaskBandSource(poSrcBand,
+                                         psOptions->adfSrcWin[0], psOptions->adfSrcWin[1],
+                                         psOptions->adfSrcWin[2], psOptions->adfSrcWin[3],
+                                         adfDstWin[0], adfDstWin[1],
+                                         adfDstWin[2], adfDstWin[3]);
+            continue;
+        }
+
+        // Preserve nbits if no option change values
+        const char* pszNBits = poSrcBand->GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
+        if( pszNBits && psOptions->nRGBExpand == 0 && psOptions->nScaleRepeat == 0 &&
+            !psOptions->bUnscale && psOptions->eOutputType == GDT_Unknown && psOptions->pszResampling == NULL )
+        {
+            poVRTBand->SetMetadataItem("NBITS", pszNBits, "IMAGE_STRUCTURE");
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Do we need to collect scaling information?                      */
+/* -------------------------------------------------------------------- */
+        double dfScale=1.0, dfOffset=0.0;
+        int    bScale = FALSE, bHaveScaleSrc = FALSE;
+        double dfScaleSrcMin = 0.0, dfScaleSrcMax = 0.0;
+        double dfScaleDstMin = 0.0, dfScaleDstMax = 0.0;
+        int    bExponentScaling = FALSE;
+        double dfExponent = 0.0;
+
+        if( i < psOptions->nScaleRepeat && psOptions->pasScaleParams[i].bScale )
+        {
+            bScale = psOptions->pasScaleParams[i].bScale;
+            bHaveScaleSrc = psOptions->pasScaleParams[i].bHaveScaleSrc;
+            dfScaleSrcMin = psOptions->pasScaleParams[i].dfScaleSrcMin;
+            dfScaleSrcMax = psOptions->pasScaleParams[i].dfScaleSrcMax;
+            dfScaleDstMin = psOptions->pasScaleParams[i].dfScaleDstMin;
+            dfScaleDstMax = psOptions->pasScaleParams[i].dfScaleDstMax;
+        }
+        else if( psOptions->nScaleRepeat == 1 && !psOptions->bHasUsedExplicitScaleBand )
+        {
+            bScale = psOptions->pasScaleParams[0].bScale;
+            bHaveScaleSrc = psOptions->pasScaleParams[0].bHaveScaleSrc;
+            dfScaleSrcMin = psOptions->pasScaleParams[0].dfScaleSrcMin;
+            dfScaleSrcMax = psOptions->pasScaleParams[0].dfScaleSrcMax;
+            dfScaleDstMin = psOptions->pasScaleParams[0].dfScaleDstMin;
+            dfScaleDstMax = psOptions->pasScaleParams[0].dfScaleDstMax;
+        }
+
+        if( i < psOptions->nExponentRepeat && psOptions->padfExponent[i] != 0.0 )
+        {
+            bExponentScaling = TRUE;
+            dfExponent = psOptions->padfExponent[i];
+        }
+        else if( psOptions->nExponentRepeat == 1 && !psOptions->bHasUsedExplicitExponentBand )
+        {
+            bExponentScaling = TRUE;
+            dfExponent = psOptions->padfExponent[0];
+        }
+
+        if( bExponentScaling && !bScale )
+        {
+            CPLError( CE_Failure, CPLE_IllegalArg, "For band %d, -scale should be specified when -exponent is specified.", i + 1);
+            if(pbUsageError)
+                *pbUsageError = TRUE;
+            GDALTranslateOptionsFree(psOptions);
+            return NULL;
+        }
+
+        if( bScale && !bHaveScaleSrc )
+        {
+            double	adfCMinMax[2];
+            GDALComputeRasterMinMax( poSrcBand, TRUE, adfCMinMax );
+            dfScaleSrcMin = adfCMinMax[0];
+            dfScaleSrcMax = adfCMinMax[1];
+        }
+
+        if( bScale )
+        {
+            /* To avoid a divide by zero */
+            if( dfScaleSrcMax == dfScaleSrcMin )
+                dfScaleSrcMax += 0.1;
+
+            if( !bExponentScaling )
+            {
+                dfScale = (dfScaleDstMax - dfScaleDstMin)
+                    / (dfScaleSrcMax - dfScaleSrcMin);
+                dfOffset = -1 * dfScaleSrcMin * dfScale + dfScaleDstMin;
+            }
+        }
+
+        if( psOptions->bUnscale )
+        {
+            dfScale = poSrcBand->GetScale();
+            dfOffset = poSrcBand->GetOffset();
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Create a simple or complex data source depending on the         */
+/*      translation type required.                                      */
+/* -------------------------------------------------------------------- */
+        VRTSimpleSource* poSimpleSource;
+        if( psOptions->bUnscale || bScale || (psOptions->nRGBExpand != 0 && i < psOptions->nRGBExpand) )
+        {
+            VRTComplexSource* poSource = new VRTComplexSource();
+
+        /* -------------------------------------------------------------------- */
+        /*      Set complex parameters.                                         */
+        /* -------------------------------------------------------------------- */
+
+            if( dfOffset != 0.0 || dfScale != 1.0 )
+            {
+                poSource->SetLinearScaling(dfOffset, dfScale);
+            }
+            else if( bExponentScaling )
+            {
+                poSource->SetPowerScaling(dfExponent,
+                                          dfScaleSrcMin,
+                                          dfScaleSrcMax,
+                                          dfScaleDstMin,
+                                          dfScaleDstMax);
+            }
+
+            poSource->SetColorTableComponent(nComponent);
+
+            poSimpleSource = poSource;
+        }
+        else
+            poSimpleSource = new VRTSimpleSource();
+
+        poSimpleSource->SetResampling(psOptions->pszResampling);
+        poVRTBand->ConfigureSource( poSimpleSource,
+                                    poSrcBand,
+                                    FALSE,
+                                    psOptions->adfSrcWin[0], psOptions->adfSrcWin[1],
+                                    psOptions->adfSrcWin[2], psOptions->adfSrcWin[3],
+                                    adfDstWin[0], adfDstWin[1],
+                                    adfDstWin[2], adfDstWin[3] );
+
+        poVRTBand->AddSource( poSimpleSource );
+
+/* -------------------------------------------------------------------- */
+/*      In case of color table translate, we only set the color         */
+/*      interpretation other info copied by CopyBandInfo are            */
+/*      not relevant in RGB expansion.                                  */
+/* -------------------------------------------------------------------- */
+        if (psOptions->nRGBExpand == 1)
+        {
+            poVRTBand->SetColorInterpretation( GCI_GrayIndex );
+        }
+        else if (psOptions->nRGBExpand != 0 && i < psOptions->nRGBExpand)
+        {
+            poVRTBand->SetColorInterpretation( (GDALColorInterp) (GCI_RedBand + i) );
+        }
+
+/* -------------------------------------------------------------------- */
+/*      copy over some other information of interest.                   */
+/* -------------------------------------------------------------------- */
+        else
+        {
+            CopyBandInfo( poSrcBand, poVRTBand,
+                          !psOptions->bStats && !bFilterOutStatsMetadata,
+                          !psOptions->bUnscale,
+                          !psOptions->bSetNoData && !psOptions->bUnsetNoData );
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Set a forcible nodata value?                                    */
+/* -------------------------------------------------------------------- */
+        if( psOptions->bSetNoData )
+        {
+            int bClamped = FALSE, bRounded = FALSE;
+            double dfVal = GDALAdjustValueToDataType(eBandType,
+                                                     psOptions->dfNoDataReal,
+                                                     &bClamped, &bRounded );
+
+            if (bClamped)
+            {
+                CPLError( CE_Warning, CPLE_AppDefined, "for band %d, nodata value has been clamped "
+                       "to %.0f, the original value being out of range.",
+                       i + 1, dfVal);
+            }
+            else if(bRounded)
+            {
+                CPLError( CE_Warning, CPLE_AppDefined, "for band %d, nodata value has been rounded "
+                       "to %.0f, %s being an integer datatype.",
+                       i + 1, dfVal,
+                       GDALGetDataTypeName(eBandType));
+            }
+
+            poVRTBand->SetNoDataValue( dfVal );
+        }
+
+        if (psOptions->eMaskMode == MASK_AUTO &&
+            (GDALGetMaskFlags(GDALGetRasterBand(hSrcDataset, 1)) & GMF_PER_DATASET) == 0 &&
+            (poSrcBand->GetMaskFlags() & (GMF_ALL_VALID | GMF_NODATA)) == 0)
+        {
+            if (poVRTBand->CreateMaskBand(poSrcBand->GetMaskFlags()) == CE_None)
+            {
+                VRTSourcedRasterBand* hMaskVRTBand =
+                    (VRTSourcedRasterBand*)poVRTBand->GetMaskBand();
+                hMaskVRTBand->AddMaskBandSource(poSrcBand,
+                                        psOptions->adfSrcWin[0], psOptions->adfSrcWin[1],
+                                        psOptions->adfSrcWin[2], psOptions->adfSrcWin[3],
+                                        adfDstWin[0], adfDstWin[1],
+                                        adfDstWin[2], adfDstWin[3] );
+            }
+        }
+    }
+
+    if (psOptions->eMaskMode == MASK_USER)
+    {
+        GDALRasterBand *poSrcBand =
+            (GDALRasterBand*)GDALGetRasterBand(hSrcDataset, ABS(psOptions->nMaskBand));
+        if (poSrcBand && poVDS->CreateMaskBand(GMF_PER_DATASET) == CE_None)
+        {
+            VRTSourcedRasterBand* hMaskVRTBand = (VRTSourcedRasterBand*)
+                GDALGetMaskBand(GDALGetRasterBand((GDALDatasetH)poVDS, 1));
+            if (psOptions->nMaskBand > 0)
+                hMaskVRTBand->AddSimpleSource(poSrcBand,
+                                        psOptions->adfSrcWin[0], psOptions->adfSrcWin[1],
+                                        psOptions->adfSrcWin[2], psOptions->adfSrcWin[3],
+                                        adfDstWin[0], adfDstWin[1],
+                                        adfDstWin[2], adfDstWin[3] );
+            else
+                hMaskVRTBand->AddMaskBandSource(poSrcBand,
+                                        psOptions->adfSrcWin[0], psOptions->adfSrcWin[1],
+                                        psOptions->adfSrcWin[2], psOptions->adfSrcWin[3],
+                                        adfDstWin[0], adfDstWin[1],
+                                        adfDstWin[2], adfDstWin[3] );
+        }
+    }
+    else
+    if (psOptions->eMaskMode == MASK_AUTO && nSrcBandCount > 0 &&
+        GDALGetMaskFlags(GDALGetRasterBand(hSrcDataset, 1)) == GMF_PER_DATASET)
+    {
+        if (poVDS->CreateMaskBand(GMF_PER_DATASET) == CE_None)
+        {
+            VRTSourcedRasterBand* hMaskVRTBand = (VRTSourcedRasterBand*)
+                GDALGetMaskBand(GDALGetRasterBand((GDALDatasetH)poVDS, 1));
+            hMaskVRTBand->AddMaskBandSource((GDALRasterBand*)GDALGetRasterBand(hSrcDataset, 1),
+                                        psOptions->adfSrcWin[0], psOptions->adfSrcWin[1],
+                                        psOptions->adfSrcWin[2], psOptions->adfSrcWin[3],
+                                        adfDstWin[0], adfDstWin[1],
+                                        adfDstWin[2], adfDstWin[3] );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Compute stats if required.                                      */
+/* -------------------------------------------------------------------- */
+    if (psOptions->bStats)
+    {
+        for( i = 0; i < poVDS->GetRasterCount(); i++ )
+        {
+            double dfMin, dfMax, dfMean, dfStdDev;
+            poVDS->GetRasterBand(i+1)->ComputeStatistics( psOptions->bApproxStats,
+                    &dfMin, &dfMax, &dfMean, &dfStdDev, GDALDummyProgress, NULL );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Write to the output file using CopyCreate().                    */
+/* -------------------------------------------------------------------- */
+    hOutDS = GDALCreateCopy( hDriver, pszDest, (GDALDatasetH) poVDS,
+                             psOptions->bStrict, psOptions->papszCreateOptions,
+                             psOptions->pfnProgress, psOptions->pProgressData );
+    hOutDS = GDALTranslateFlush(hOutDS);
+
+    GDALClose( (GDALDatasetH) poVDS );
+
+    GDALTranslateOptionsFree(psOptions);
+    return hOutDS;
+}
+
+
+/************************************************************************/
+/*                           AttachMetadata()                           */
+/************************************************************************/
+
+static void AttachMetadata( GDALDatasetH hDS, char **papszMetadataOptions )
+
+{
+    int nCount = CSLCount(papszMetadataOptions);
+    int i;
+
+    for( i = 0; i < nCount; i++ )
+    {
+        char    *pszKey = NULL;
+        const char *pszValue;
+
+        pszValue = CPLParseNameValue( papszMetadataOptions[i], &pszKey );
+        GDALSetMetadataItem(hDS,pszKey,pszValue,NULL);
+        CPLFree( pszKey );
+    }
+
+}
+
+/************************************************************************/
+/*                           CopyBandInfo()                            */
+/************************************************************************/
+
+/* A bit of a clone of VRTRasterBand::CopyCommonInfoFrom(), but we need */
+/* more and more custom behaviour in the context of gdal_translate ... */
+
+static void CopyBandInfo( GDALRasterBand * poSrcBand, GDALRasterBand * poDstBand,
+                          int bCanCopyStatsMetadata, int bCopyScale, int bCopyNoData )
+
+{
+    int bSuccess;
+    double dfNoData;
+
+    if (bCanCopyStatsMetadata)
+    {
+        poDstBand->SetMetadata( poSrcBand->GetMetadata() );
+    }
+    else
+    {
+        char** papszMetadata = poSrcBand->GetMetadata();
+        char** papszMetadataNew = NULL;
+        for( int i = 0; papszMetadata != NULL && papszMetadata[i] != NULL; i++ )
+        {
+            if (!STARTS_WITH(papszMetadata[i], "STATISTICS_"))
+                papszMetadataNew = CSLAddString(papszMetadataNew, papszMetadata[i]);
+        }
+        poDstBand->SetMetadata( papszMetadataNew );
+        CSLDestroy(papszMetadataNew);
+    }
+
+    poDstBand->SetColorTable( poSrcBand->GetColorTable() );
+    poDstBand->SetColorInterpretation(poSrcBand->GetColorInterpretation());
+    if( strlen(poSrcBand->GetDescription()) > 0 )
+        poDstBand->SetDescription( poSrcBand->GetDescription() );
+
+    if (bCopyNoData)
+    {
+        dfNoData = poSrcBand->GetNoDataValue( &bSuccess );
+        if( bSuccess )
+            poDstBand->SetNoDataValue( dfNoData );
+    }
+
+    if (bCopyScale)
+    {
+        poDstBand->SetOffset( poSrcBand->GetOffset() );
+        poDstBand->SetScale( poSrcBand->GetScale() );
+    }
+
+    poDstBand->SetCategoryNames( poSrcBand->GetCategoryNames() );
+
+    // Copy unit only if the range of pixel values is not modified
+    if( bCanCopyStatsMetadata && bCopyScale && !EQUAL(poSrcBand->GetUnitType(),"") )
+        poDstBand->SetUnitType( poSrcBand->GetUnitType() );
+}
+
+/************************************************************************/
+/*                            ArgIsNumeric()                            */
+/************************************************************************/
+
+int ArgIsNumeric( const char *pszArg )
+
+{
+    return CPLGetValueType(pszArg) != CPL_VALUE_STRING;
+}
+
+/************************************************************************/
+/*                             GDALTranslateOptionsNew()                */
+/************************************************************************/
+
+/**
+ * Allocates a GDALTranslateOptions struct.
+ *
+ * @param papszArgv NULL terminated list of options (potentially including filename and open options too), or NULL.
+ *                  The accepted options are the ones of the <a href="gdal_translate.html">gdal_translate</a> utility.
+ * @param psOptionsForBinary (output) may be NULL (and should generally be NULL),
+ *                           otherwise (gdal_translate_bin.cpp use case) must be allocated with
+ *                           GDALTranslateOptionsForBinaryNew() prior to this function. Will be
+ *                           filled with potentially present filename, open options,...
+ * @return pointer to the allocated GDALTranslateOptions struct. Must be freed with GDALTranslateOptionsFree().
+ *
+ * @since GDAL 2.1
+ */
+
+GDALTranslateOptions *GDALTranslateOptionsNew(char** papszArgv, GDALTranslateOptionsForBinary* psOptionsForBinary)
+{
+    GDALTranslateOptions *psOptions = (GDALTranslateOptions *) CPLCalloc( 1, sizeof(GDALTranslateOptions) );
+
+    psOptions->pszFormat = CPLStrdup("GTiff");
+    psOptions->bQuiet = TRUE;
+    psOptions->pfnProgress = GDALDummyProgress;
+    psOptions->pProgressData = NULL;
+    psOptions->eOutputType = GDT_Unknown;
+    psOptions->eMaskMode = MASK_AUTO;
+    psOptions->nBandCount = 0;
+    psOptions->panBandList = NULL;
+    psOptions->nOXSizePixel = 0;
+    psOptions->nOYSizePixel = 0;
+    psOptions->dfOXSizePct = 0.0;
+    psOptions->dfOYSizePct = 0.0;
+    psOptions->adfSrcWin[0] = 0;
+    psOptions->adfSrcWin[1] = 0;
+    psOptions->adfSrcWin[2] = 0;
+    psOptions->adfSrcWin[3] = 0;
+    psOptions->bStrict = FALSE;
+    psOptions->bUnscale = FALSE;
+    psOptions->nScaleRepeat = 0;
+    psOptions->pasScaleParams = NULL;
+    psOptions->bHasUsedExplicitScaleBand = FALSE;
+    psOptions->nExponentRepeat = 0;
+    psOptions->padfExponent = NULL;
+    psOptions->bHasUsedExplicitExponentBand = FALSE;
+    psOptions->dfULX = 0.0;
+    psOptions->dfULY = 0.0;
+    psOptions->dfLRX = 0.0;
+    psOptions->dfLRY = 0.0;
+    psOptions->pszOutputSRS = NULL;
+    psOptions->nGCPCount = 0;
+    psOptions->pasGCPs = NULL;
+    psOptions->adfULLR[0] = 0;
+    psOptions->adfULLR[1] = 0;
+    psOptions->adfULLR[2] = 0;
+    psOptions->adfULLR[3] = 0;
+    psOptions->bSetNoData = FALSE;
+    psOptions->bUnsetNoData = FALSE;
+    psOptions->dfNoDataReal = 0.0;
+    psOptions->nRGBExpand = 0;
+    psOptions->nMaskBand = 0;
+    psOptions->bStats = FALSE;
+    psOptions->bApproxStats = FALSE;
+    psOptions->bErrorOnPartiallyOutside = FALSE;
+    psOptions->bErrorOnCompletelyOutside = FALSE;
+    psOptions->bNoRAT = FALSE;
+    psOptions->pszResampling = NULL;
+    psOptions->dfXRes = 0.0;
+    psOptions->dfYRes = 0.0;
+    psOptions->pszProjSRS = NULL;
+
+    bool bParsedMaskArgument = false;
+    bool bOutsideExplicitlySet = false;
+    bool bGotSourceFilename = false;
+    bool bGotDestFilename = false;
+
+/* -------------------------------------------------------------------- */
+/*      Handle command line arguments.                                  */
+/* -------------------------------------------------------------------- */
+    int argc = CSLCount(papszArgv);
+    for( int i = 0; i < argc; i++ )
+    {
+        if( EQUAL(papszArgv[i],"-of") && i < argc-1 )
+        {
+            ++i;
+            CPLFree(psOptions->pszFormat);
+            psOptions->pszFormat = CPLStrdup(papszArgv[i]);
+            if( psOptionsForBinary )
+            {
+                psOptionsForBinary->bFormatExplicitlySet = TRUE;
+            }
+        }
+
+        else if( EQUAL(papszArgv[i],"-q") || EQUAL(papszArgv[i],"-quiet") )
+        {
+            if( psOptionsForBinary )
+                psOptionsForBinary->bQuiet = TRUE;
+        }
+
+        else if( EQUAL(papszArgv[i],"-ot") && papszArgv[i+1] )
+        {
+            int iType;
+
+            for( iType = 1; iType < GDT_TypeCount; iType++ )
+            {
+                if( GDALGetDataTypeName((GDALDataType)iType) != NULL
+                    && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
+                             papszArgv[i+1]) )
+                {
+                    psOptions->eOutputType = (GDALDataType) iType;
+                }
+            }
+
+            if( psOptions->eOutputType == GDT_Unknown )
+            {
+                CPLError(CE_Failure, CPLE_NotSupported,
+                         "Unknown output pixel type: %s.", papszArgv[i+1] );
+                GDALTranslateOptionsFree(psOptions);
+                return NULL;
+            }
+            i++;
+        }
+        else if( EQUAL(papszArgv[i],"-b") && papszArgv[i+1] )
+        {
+            const char* pszBand = papszArgv[i+1];
+            int bMask = FALSE;
+            if (EQUAL(pszBand, "mask"))
+                pszBand = "mask,1";
+            if (STARTS_WITH_CI(pszBand, "mask,"))
+            {
+                bMask = TRUE;
+                pszBand += 5;
+                /* If we use the source mask band as a regular band */
+                /* don't create a target mask band by default */
+                if( !bParsedMaskArgument )
+                    psOptions->eMaskMode = MASK_DISABLED;
+            }
+            int nBand = atoi(pszBand);
+            if( nBand < 1 )
+            {
+                CPLError(CE_Failure, CPLE_NotSupported,"Unrecognizable band number (%s).", papszArgv[i+1] );
+                GDALTranslateOptionsFree(psOptions);
+                return NULL;
+            }
+            i++;
+
+            psOptions->nBandCount++;
+            psOptions->panBandList = (int *)
+                CPLRealloc(psOptions->panBandList, sizeof(int) * psOptions->nBandCount);
+            psOptions->panBandList[psOptions->nBandCount-1] = nBand;
+            if (bMask)
+                psOptions->panBandList[psOptions->nBandCount-1] *= -1;
+
+        }
+        else if( EQUAL(papszArgv[i],"-mask") &&  papszArgv[i+1] )
+        {
+            bParsedMaskArgument = true;
+            const char* pszBand = papszArgv[i+1];
+            if (EQUAL(pszBand, "none"))
+            {
+                psOptions->eMaskMode = MASK_DISABLED;
+            }
+            else if (EQUAL(pszBand, "auto"))
+            {
+                psOptions->eMaskMode = MASK_AUTO;
+            }
+            else
+            {
+                int bMask = FALSE;
+                if (EQUAL(pszBand, "mask"))
+                    pszBand = "mask,1";
+                if (STARTS_WITH_CI(pszBand, "mask,"))
+                {
+                    bMask = TRUE;
+                    pszBand += 5;
+                }
+                int nBand = atoi(pszBand);
+                if( nBand < 1 )
+                {
+                    CPLError(CE_Failure, CPLE_NotSupported,"Unrecognizable band number (%s).", papszArgv[i+1] );
+                    GDALTranslateOptionsFree(psOptions);
+                    return NULL;
+                }
+
+                psOptions->eMaskMode = MASK_USER;
+                psOptions->nMaskBand = nBand;
+                if (bMask)
+                    psOptions->nMaskBand *= -1;
+            }
+            i ++;
+        }
+        else if( EQUAL(papszArgv[i],"-not_strict")  )
+            psOptions->bStrict = FALSE;
+
+        else if( EQUAL(papszArgv[i],"-strict")  )
+            psOptions->bStrict = TRUE;
+
+        else if( EQUAL(papszArgv[i],"-sds")  )
+        {
+            if( psOptionsForBinary )
+                psOptionsForBinary->bCopySubDatasets = TRUE;
+        }
+        else if( EQUAL(papszArgv[i],"-gcp") && i + 4 < argc )
+        {
+            char* endptr = NULL;
+            /* -gcp pixel line easting northing [elev] */
+
+            psOptions->nGCPCount++;
+            psOptions->pasGCPs = (GDAL_GCP *)
+                CPLRealloc( psOptions->pasGCPs, sizeof(GDAL_GCP) * psOptions->nGCPCount );
+            GDALInitGCPs( 1, psOptions->pasGCPs + psOptions->nGCPCount - 1 );
+
+            psOptions->pasGCPs[psOptions->nGCPCount-1].dfGCPPixel = CPLAtofM(papszArgv[++i]);
+            psOptions->pasGCPs[psOptions->nGCPCount-1].dfGCPLine = CPLAtofM(papszArgv[++i]);
+            psOptions->pasGCPs[psOptions->nGCPCount-1].dfGCPX = CPLAtofM(papszArgv[++i]);
+            psOptions->pasGCPs[psOptions->nGCPCount-1].dfGCPY = CPLAtofM(papszArgv[++i]);
+            if( papszArgv[i+1] != NULL
+                && (CPLStrtod(papszArgv[i+1], &endptr) != 0.0 || papszArgv[i+1][0] == '0') )
+            {
+                /* Check that last argument is really a number and not a filename */
+                /* looking like a number (see ticket #863) */
+                if (endptr && *endptr == 0)
+                    psOptions->pasGCPs[psOptions->nGCPCount-1].dfGCPZ = CPLAtofM(papszArgv[++i]);
+            }
+
+            /* should set id and info? */
+        }
+
+        else if( EQUAL(papszArgv[i],"-a_nodata") && papszArgv[i+1] )
+        {
+            if (EQUAL(papszArgv[i+1], "none"))
+            {
+                psOptions->bUnsetNoData = TRUE;
+            }
+            else
+            {
+                psOptions->bSetNoData = TRUE;
+                psOptions->dfNoDataReal = CPLAtofM(papszArgv[i+1]);
+            }
+            i += 1;
+        }
+
+        else if( EQUAL(papszArgv[i],"-a_ullr") && i + 4 < argc )
+        {
+            psOptions->adfULLR[0] = CPLAtofM(papszArgv[i+1]);
+            psOptions->adfULLR[1] = CPLAtofM(papszArgv[i+2]);
+            psOptions->adfULLR[2] = CPLAtofM(papszArgv[i+3]);
+            psOptions->adfULLR[3] = CPLAtofM(papszArgv[i+4]);
+
+            i += 4;
+        }
+
+        else if( EQUAL(papszArgv[i],"-co") && papszArgv[i+1] )
+        {
+            psOptions->papszCreateOptions = CSLAddString( psOptions->papszCreateOptions, papszArgv[++i] );
+        }
+
+        else if( EQUAL(papszArgv[i],"-scale") || STARTS_WITH_CI(papszArgv[i], "-scale_") )
+        {
+            int nIndex = 0;
+            if( STARTS_WITH_CI(papszArgv[i], "-scale_") )
+            {
+                if( !psOptions->bHasUsedExplicitScaleBand && psOptions->nScaleRepeat != 0 )
+                {
+                    CPLError(CE_Failure, CPLE_NotSupported, "Cannot mix -scale and -scale_XX syntax");
+                    GDALTranslateOptionsFree(psOptions);
+                    return NULL;
+                }
+                psOptions->bHasUsedExplicitScaleBand = TRUE;
+                nIndex = atoi(papszArgv[i] + 7);
+                if( nIndex <= 0 || nIndex > 65535 )
+                {
+                    CPLError(CE_Failure, CPLE_NotSupported, "Invalid parameter name: %s", papszArgv[i]);
+                    GDALTranslateOptionsFree(psOptions);
+                    return NULL;
+                }
+                nIndex --;
+            }
+            else
+            {
+                if( psOptions->bHasUsedExplicitScaleBand )
+                {
+                    CPLError(CE_Failure, CPLE_NotSupported, "Cannot mix -scale and -scale_XX syntax");
+                    GDALTranslateOptionsFree(psOptions);
+                    return NULL;
+                }
+                nIndex = psOptions->nScaleRepeat;
+            }
+
+            if( nIndex >= psOptions->nScaleRepeat )
+            {
+                psOptions->pasScaleParams = (GDALTranslateScaleParams*)CPLRealloc(psOptions->pasScaleParams,
+                    (nIndex + 1) * sizeof(GDALTranslateScaleParams));
+                if( nIndex > psOptions->nScaleRepeat )
+                    memset(psOptions->pasScaleParams + psOptions->nScaleRepeat, 0,
+                        sizeof(GDALTranslateScaleParams) * (nIndex - psOptions->nScaleRepeat));
+                psOptions->nScaleRepeat = nIndex + 1;
+            }
+            psOptions->pasScaleParams[nIndex].bScale = TRUE;
+            if( i < argc-2 && ArgIsNumeric(papszArgv[i+1]) )
+            {
+                psOptions->pasScaleParams[nIndex].bHaveScaleSrc = TRUE;
+                psOptions->pasScaleParams[nIndex].dfScaleSrcMin = CPLAtofM(papszArgv[i+1]);
+                psOptions->pasScaleParams[nIndex].dfScaleSrcMax = CPLAtofM(papszArgv[i+2]);
+                i += 2;
+            }
+            if( i < argc-2 && psOptions->pasScaleParams[nIndex].bHaveScaleSrc && ArgIsNumeric(papszArgv[i+1]) )
+            {
+                psOptions->pasScaleParams[nIndex].dfScaleDstMin = CPLAtofM(papszArgv[i+1]);
+                psOptions->pasScaleParams[nIndex].dfScaleDstMax = CPLAtofM(papszArgv[i+2]);
+                i += 2;
+            }
+            else
+            {
+                psOptions->pasScaleParams[nIndex].dfScaleDstMin = 0.0;
+                psOptions->pasScaleParams[nIndex].dfScaleDstMax = 255.999;
+            }
+        }
+
+        else if( (EQUAL(papszArgv[i],"-exponent") || STARTS_WITH_CI(papszArgv[i], "-exponent_")) &&
+                 papszArgv[i+1] )
+        {
+            int nIndex = 0;
+            if( STARTS_WITH_CI(papszArgv[i], "-exponent_") )
+            {
+                if( !psOptions->bHasUsedExplicitExponentBand && psOptions->nExponentRepeat != 0 )
+                {
+                    CPLError(CE_Failure, CPLE_NotSupported, "Cannot mix -exponent and -exponent_XX syntax");
+                    GDALTranslateOptionsFree(psOptions);
+                    return NULL;
+                }
+                psOptions->bHasUsedExplicitExponentBand = TRUE;
+                nIndex = atoi(papszArgv[i] + 10);
+                if( nIndex <= 0 || nIndex > 65535 )
+                {
+                    CPLError(CE_Failure, CPLE_NotSupported, "Invalid parameter name: %s", papszArgv[i]);
+                    GDALTranslateOptionsFree(psOptions);
+                    return NULL;
+                }
+                nIndex --;
+            }
+            else
+            {
+                if( psOptions->bHasUsedExplicitExponentBand )
+                {
+                    CPLError(CE_Failure, CPLE_NotSupported, "Cannot mix -exponent and -exponent_XX syntax");
+                    GDALTranslateOptionsFree(psOptions);
+                    return NULL;
+                }
+                nIndex = psOptions->nExponentRepeat;
+            }
+
+            if( nIndex >= psOptions->nExponentRepeat )
+            {
+                psOptions->padfExponent = (double*)CPLRealloc(psOptions->padfExponent,
+                    (nIndex + 1) * sizeof(double));
+                if( nIndex > psOptions->nExponentRepeat )
+                    memset(psOptions->padfExponent + psOptions->nExponentRepeat, 0,
+                        sizeof(double) * (nIndex - psOptions->nExponentRepeat));
+                psOptions->nExponentRepeat = nIndex + 1;
+            }
+            double dfExponent = CPLAtofM(papszArgv[++i]);
+            psOptions->padfExponent[nIndex] = dfExponent;
+        }
+
+        else if( EQUAL(papszArgv[i], "-unscale") )
+        {
+            psOptions->bUnscale = TRUE;
+        }
+
+        else if( EQUAL(papszArgv[i],"-mo") && papszArgv[i+1] )
+        {
+            psOptions->papszMetadataOptions = CSLAddString( psOptions->papszMetadataOptions,
+                                                 papszArgv[++i] );
+        }
+
+        else if( EQUAL(papszArgv[i],"-outsize") && i+2 < argc && papszArgv[i+1] != NULL )
+        {
+            ++i;
+            if( papszArgv[i][strlen(papszArgv[i])-1] == '%' )
+                psOptions->dfOXSizePct = CPLAtofM(papszArgv[i]);
+            else
+                psOptions->nOXSizePixel = atoi(papszArgv[i]);
+            ++i;
+            if( papszArgv[i][strlen(papszArgv[i])-1] == '%' )
+                psOptions->dfOYSizePct = CPLAtofM(papszArgv[i]);
+            else
+                psOptions->nOYSizePixel = atoi(papszArgv[i]);
+            bOutsideExplicitlySet = true;
+        }
+
+        else if( EQUAL(papszArgv[i],"-tr") && i+2 < argc )
+        {
+            psOptions->dfXRes = CPLAtofM(papszArgv[++i]);
+            psOptions->dfYRes = fabs(CPLAtofM(papszArgv[++i]));
+            if( psOptions->dfXRes == 0 || psOptions->dfYRes == 0 )
+            {
+                CPLError(CE_Failure, CPLE_IllegalArg, "Wrong value for -tr parameters.");
+                GDALTranslateOptionsFree(psOptions);
+                return NULL;
+            }
+        }
+
+        else if( EQUAL(papszArgv[i],"-srcwin") && i+4 < argc )
+        {
+            psOptions->adfSrcWin[0] = CPLAtof(papszArgv[++i]);
+            psOptions->adfSrcWin[1] = CPLAtof(papszArgv[++i]);
+            psOptions->adfSrcWin[2] = CPLAtof(papszArgv[++i]);
+            psOptions->adfSrcWin[3] = CPLAtof(papszArgv[++i]);
+        }
+
+        else if( EQUAL(papszArgv[i],"-projwin") && i+4 < argc )
+        {
+            psOptions->dfULX = CPLAtofM(papszArgv[++i]);
+            psOptions->dfULY = CPLAtofM(papszArgv[++i]);
+            psOptions->dfLRX = CPLAtofM(papszArgv[++i]);
+            psOptions->dfLRY = CPLAtofM(papszArgv[++i]);
+        }
+
+        else if( EQUAL(papszArgv[i],"-projwin_srs") && i+1 < argc )
+        {
+            psOptions->pszProjSRS = CPLStrdup(papszArgv[i+1]);
+            i++;
+        }
+
+        else if( EQUAL(papszArgv[i],"-epo") )
+        {
+            psOptions->bErrorOnPartiallyOutside = TRUE;
+            psOptions->bErrorOnCompletelyOutside = TRUE;
+        }
+
+        else  if( EQUAL(papszArgv[i],"-eco") )
+        {
+            psOptions->bErrorOnCompletelyOutside = TRUE;
+        }
+
+        else if( EQUAL(papszArgv[i],"-a_srs") && i+1 < argc )
+        {
+            psOptions->pszOutputSRS = CPLStrdup(papszArgv[i+1]);
+            i++;
+        }
+
+        else if( EQUAL(papszArgv[i],"-expand") && i+1 < argc && papszArgv[i+1] != NULL )
+        {
+            i++;
+            if (EQUAL(papszArgv[i], "gray"))
+                psOptions->nRGBExpand = 1;
+            else if (EQUAL(papszArgv[i], "rgb"))
+                psOptions->nRGBExpand = 3;
+            else if (EQUAL(papszArgv[i], "rgba"))
+                psOptions->nRGBExpand = 4;
+            else
+            {
+                CPLError(CE_Failure, CPLE_IllegalArg,
+                         "Value %s unsupported. Only gray, rgb or rgba are supported.",
+                          papszArgv[i] );
+                GDALTranslateOptionsFree(psOptions);
+                return NULL;
+            }
+        }
+
+        else if( EQUAL(papszArgv[i], "-stats") )
+        {
+            psOptions->bStats = TRUE;
+            psOptions->bApproxStats = FALSE;
+        }
+        else if( EQUAL(papszArgv[i], "-approx_stats") )
+        {
+            psOptions->bStats = TRUE;
+            psOptions->bApproxStats = TRUE;
+        }
+        else if( EQUAL(papszArgv[i], "-norat") )
+        {
+            psOptions->bNoRAT = TRUE;
+        }
+        else if( EQUAL(papszArgv[i], "-oo") && i+1 < argc )
+        {
+            i++;
+            if( psOptionsForBinary )
+            {
+                psOptionsForBinary->papszOpenOptions =
+                    CSLAddString( psOptionsForBinary->papszOpenOptions,
+                                                papszArgv[i] );
+            }
+        }
+        else if( EQUAL(papszArgv[i],"-r") && i+1 < argc )
+        {
+            psOptions->pszResampling = CPLStrdup(papszArgv[++i]);
+        }
+        else if( papszArgv[i][0] == '-' )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unknown option name '%s'", papszArgv[i]);
+            GDALTranslateOptionsFree(psOptions);
+            return NULL;
+        }
+        else if( !bGotSourceFilename )
+        {
+            bGotSourceFilename = true;
+            if( psOptionsForBinary )
+                psOptionsForBinary->pszSource = CPLStrdup(papszArgv[i]);
+        }
+        else if( !bGotDestFilename )
+        {
+            bGotDestFilename = true;
+            if( psOptionsForBinary )
+                psOptionsForBinary->pszDest = CPLStrdup(papszArgv[i]);
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Too many command options '%s'", papszArgv[i]);
+            GDALTranslateOptionsFree(psOptions);
+            return NULL;
+        }
+    }
+
+    if( bOutsideExplicitlySet &&
+        psOptions->nOXSizePixel == 0 && psOptions->dfOXSizePct == 0.0 &&
+        psOptions->nOYSizePixel == 0 && psOptions->dfOYSizePct == 0.0 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "-outsize %d %d invalid.", psOptions->nOXSizePixel, psOptions->nOYSizePixel);
+        GDALTranslateOptionsFree(psOptions);
+        return NULL;
+    }
+
+    if( psOptionsForBinary )
+    {
+        psOptionsForBinary->pszFormat = CPLStrdup(psOptions->pszFormat);
+    }
+
+    return psOptions;
+}
+
+/************************************************************************/
+/*                        GDALTranslateOptionsFree()                    */
+/************************************************************************/
+
+/**
+ * Frees the GDALTranslateOptions struct.
+ *
+ * @param psOptions the options struct for GDALTranslate().
+ *
+ * @since GDAL 2.1
+ */
+
+void GDALTranslateOptionsFree(GDALTranslateOptions *psOptions)
+{
+    if( psOptions )
+    {
+        CPLFree(psOptions->pszFormat);
+        CPLFree(psOptions->panBandList);
+        CSLDestroy(psOptions->papszCreateOptions);
+        CPLFree(psOptions->pasScaleParams);
+        CPLFree(psOptions->padfExponent);
+        CSLDestroy(psOptions->papszMetadataOptions);
+        CPLFree(psOptions->pszOutputSRS);
+        if( psOptions->nGCPCount )
+            GDALDeinitGCPs(psOptions->nGCPCount, psOptions->pasGCPs);
+        CPLFree(psOptions->pasGCPs);
+        CPLFree(psOptions->pszResampling);
+        CPLFree(psOptions->pszProjSRS);
+
+        CPLFree(psOptions);
+    }
+}
+
+/************************************************************************/
+/*                 GDALTranslateOptionsSetProgress()                    */
+/************************************************************************/
+
+/**
+ * Set a progress function.
+ *
+ * @param psOptions the options struct for GDALTranslate().
+ * @param pfnProgress the progress callback.
+ * @param pProgressData the user data for the progress callback.
+ *
+ * @since GDAL 2.1
+ */
+
+void GDALTranslateOptionsSetProgress( GDALTranslateOptions *psOptions,
+                                      GDALProgressFunc pfnProgress, void *pProgressData )
+{
+    psOptions->pfnProgress = pfnProgress;
+    psOptions->pProgressData = pProgressData;
+    if( pfnProgress == GDALTermProgress )
+        psOptions->bQuiet = FALSE;
+}
diff --git a/apps/gdal_utilities.dox b/apps/gdal_utilities.dox
index b4f24b4..eb398f2 100644
--- a/apps/gdal_utilities.dox
+++ b/apps/gdal_utilities.dox
@@ -1,5 +1,5 @@
 #ifndef DOXYGEN_SKIP
-/* $Id: gdal_utilities.dox 29338 2015-06-14 17:53:28Z rouault $ */
+/* $Id: gdal_utilities.dox 33514 2016-02-20 15:02:29Z rouault $ */
 #endif /* DOXYGEN_SKIP */
 
 /*! 
@@ -35,6 +35,7 @@ The following utility programs are distributed with GDAL.
 <li> \ref gdalmove - Transform the coordinate system of a file (GDAL >= 1.10)
 <li> \ref gdal_edit - Edit in place various information of an existing GDAL dataset (projection, geotransform, nodata, metadata)
 <li> \ref gdal_calc - Command line raster calculator with numpy syntax
+<li> \ref gdal_pansharpen - Perform a pansharpen operation.
 <li> \ref gdal-config - Get options required to build software using GDAL.
 <li> \ref gdalmanage - Identify, copy, rename and delete raster.
 <li> \ref gdalcompare - Compare two images and report on differences.
@@ -43,7 +44,7 @@ The following utility programs are distributed with GDAL.
 \section gdal_utilities_creating Creating New Files
 
 Access an existing file to read it is generally quite simple.  Just
-indicate the name of the file or dataset on the commandline.  However, 
+indicate the name of the file or dataset on the command line.  However, 
 creating a file is more complicated.  It may be necessary to indicate the
 the format to create, various creation options affecting how it will
 be created and perhaps a coordinate system to be assigned.  Many of 
@@ -54,7 +55,7 @@ introduced here. <p>
 <dt> <b>-of</b> <i>format</i></dt><dd> 
 Select the format to create the new file as.  The formats are assigned short 
 names such as GTiff (for GeoTIFF) or HFA (for Erdas Imagine).  The list of 
-all format codes can be listed with the <b>--formats</b> switch.  Only
+all format codes can be listed with the <b>\-\-formats</b> switch.  Only
 formats list as "(rw)" (read-write) can be written.<p>
 Many utilities default
 to creating GeoTIFF files if a format is not specified.  File extensions
@@ -69,14 +70,14 @@ driver supports creation options to control compression, and whether the file
 should be tiled.<p>
 The creation options available vary by format driver, and some simple 
 formats have no creation options at all.  A list of options supported
-for a format can be listed with the "--format <format>" commandline
+for a format can be listed with the "--format <format>" command line
 option but the web page for the format is the definitive source of 
 information on driver creation options.<p>
 </dd>
 
 <dt> <b>-a_srs</b> <i>SRS</i></dt><dd> 
 Several utilities, (gdal_translate and gdalwarp) include the ability
-to specify coordinate systems with commandline options like
+to specify coordinate systems with command line options like
 <b>-a_srs</b> (assign SRS to output), <b>-s_srs</b> (source SRS) and
 <b>-t_srs</b> (target SRS).<p>
 These utilities allow the coordinate system (SRS = spatial reference system)
@@ -102,7 +103,7 @@ a textual format for describing coordinate systems as part of the Simple
 Features specifications.  This format is the internal working format
 for coordinate systems used in GDAL.  The name of a file containing a 
 WKT coordinate system definition may be used a coordinate system argument,
-or the entire coordinate system itself may be used as a commandline
+or the entire coordinate system itself may be used as a command line
 option (though escaping all the quotes in WKT is quite challenging). <p>
 
 <li> <i>ESRI Well Known Text</i>: ESRI uses a slight variation on OGC WKT
@@ -125,31 +126,31 @@ All GDAL command line utility programs support the following
 "general" options.<p>
 
 <dl>
-<dt> <b>--version</b></dt><dd> Report the version of GDAL and exit.</dd>
+<dt> <b>\-\-version</b></dt><dd> Report the version of GDAL and exit.</dd>
 
-<dt> <b>--formats</b></dt><dd> List all raster formats supported by this
+<dt> <b>\-\-formats</b></dt><dd> List all raster formats supported by this
 GDAL build (read-only and read-write) and exit. The format support is indicated
  as follows: 'ro' is read-only driver; 
-'rw' is read or write (ie. supports CreateCopy);
-'rw+' is read, write and update (ie. supports Create).
+'rw' is read or write (i.e. supports CreateCopy);
+'rw+' is read, write and update (i.e. supports Create).
 A 'v' is appended for formats supporting virtual IO (/vsimem, /vsigzip, /vsizip, etc).
 A 's' is appended for formats supporting subdatasets.
 Note: The valid formats for the output of gdalwarp are formats that support the
 Create() method (marked as rw+), not just the CreateCopy() method.
 </dd>
 
-<dt> <b>--format</b> <i>format</i></dt><dd>
+<dt> <b>\-\-format</b> <i>format</i></dt><dd>
 List detailed information about a single format driver.  The <i>format</i> 
-should be the short name reported in the <b>--formats</b> list, such as 
+should be the short name reported in the <b>\-\-formats</b> list, such as 
 GTiff.</dd>
 
-<dt> <b>--optfile</b> <i>file</i></dt><dd>
-Read the named file and substitute the contents into the commandline
+<dt> <b>\-\-optfile</b> <i>file</i></dt><dd>
+Read the named file and substitute the contents into the command line
 options list.  Lines beginning with # will be ignored.  Multi-word arguments
 may be kept together with double quotes. 
 </dd>
 
-<dt> <b>--config</b> <i>key value</i></dt><dd>
+<dt> <b>\-\-config</b> <i>key value</i></dt><dd>
 Sets the named <a href="http://trac.osgeo.org/gdal/wiki/ConfigOptions">
 configuration keyword</a> to the given value, as opposed to 
 setting them as environment variables.  Some common configuration keywords
@@ -158,15 +159,15 @@ and GDAL_DATA (path of the GDAL "data" directory).  Individual drivers may
 be influenced by other configuration options.  
 </dd>
 
-<dt> <b>--debug</b> <i>value</i></dt><dd>
+<dt> <b>\-\-debug</b> <i>value</i></dt><dd>
 Control what debugging messages are emitted.  A value of <i>ON</i> will
 enable all debug messages.  A value of <i>OFF</i> will disable all debug
 messages.  Another value will select only debug messages containing that
 string in the debug prefix code.  
 </dd>
 
-<dt> <b>--help-general</b></dt><dd>
-Gives a brief usage message for the generic GDAL commandline options 
+<dt> <b>\-\-help-general</b></dt><dd>
+Gives a brief usage message for the generic GDAL command line options 
 and exit.
 </dd>
 
@@ -174,7 +175,7 @@ and exit.
 
 \htmlonly
 <p>
-$Id: gdal_utilities.dox 29338 2015-06-14 17:53:28Z rouault $
+$Id: gdal_utilities.dox 33514 2016-02-20 15:02:29Z rouault $
 </p>
 \endhtmlonly
 */
@@ -252,6 +253,10 @@ the full geotransform (but not GCPs).
 <li> Band pseudo-color tables. 
 </ul>
 
+\section gdalinfo_api C API
+
+Starting with GDAL 2.1, this utility is also callable from C with GDALInfo().
+
 \section gdalinfo_example EXAMPLE
 
 \verbatim
@@ -300,7 +305,7 @@ converts raster data between different formats
 gdal_translate [--help-general]
        [-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/
              CInt16/CInt32/CFloat32/CFloat64}] [-strict]
-       [-of format] [-b band] [-mask band] [-expand {gray|rgb|rgba}]
+       [-of format] [-b band]* [-mask band] [-expand {gray|rgb|rgba}]
        [-outsize xsize[%]|0 ysize[%]|0] [-tr xres yres]
        [-r {nearest,bilinear,cubic,cubicspline,lanczos,average,mode}]
        [-unscale] [-scale[_bn] [src_min src_max [dst_min dst_max]]]* [-exponent[_bn] exp_val]*
@@ -371,7 +376,7 @@ It is also possible to use the "-scale_bn" syntax where bn is a band number
 one or several specific bands.
 </dd>
 <dt> <b>-exponent</b> <i> exp_val</i>:</dt><dd> (From GDAL 1.11) To apply non-linear scaling
-with a power function. exp_val is the exponent of the power function (must be postive). This option
+with a power function. exp_val is the exponent of the power function (must be positive). This option
 must be used with the -scale option.
 If specified only once, -exponent applies to all bands of the output image.
 It can be repeated several times so as to specify per band parameters.
@@ -435,6 +440,10 @@ file name, URL of data source or subdataset name for multi-dataset files.</dd>
 <dt> <i>dst_dataset</i>:</dt><dd> The destination file name.</dd>
 </dl>
 
+\section gdal_translate_api C API
+
+Starting with GDAL 2.1, this utility is also callable from C with GDALTranslate().
+
 \section gdal_translate_example EXAMPLE
 
 \verbatim
@@ -466,7 +475,7 @@ builds or rebuilds overview images
 
 \verbatim
 gdaladdo [-r {nearest,average,gauss,cubic,cubicspline,lanczos,average_mp,average_magphase,mode}]
-         [-b band]
+         [-b band]*
          [-ro] [-clean] [-oo NAME=VALUE]* [--help-general] filename levels
 \endverbatim
 
@@ -522,18 +531,18 @@ already has overviews computed, you don't need to clean the existing overviews.
 Some format drivers do not support overviews at all.  Many format drivers
 store overviews in a secondary file with the extension .ovr that is actually
 in TIFF format.  By default, the GeoTIFF driver stores overviews internally to the file 
-operated on (if it is writeable), unless the -ro flag is specified.
+operated on (if it is writable), unless the -ro flag is specified.
 
 Most drivers also support an alternate overview format using Erdas Imagine 
 format.  To trigger this use the USE_RRD=YES configuration option.  This will 
 place the overviews in an associated .aux file suitable for direct use with 
-Imagine or ArcGIS as well as GDAL applications.  (eg --config USE_RRD YES)
+Imagine or ArcGIS as well as GDAL applications.  (e.g. --config USE_RRD YES)
 
 \section gdaladdo_externalgtiffoverviews External overviews in GeoTIFF format
 
 External overviews created in TIFF format may be compressed using the COMPRESS_OVERVIEW 
 configuration option.  All compression methods, supported by the GeoTIFF 
-driver, are available here. (eg --config COMPRESS_OVERVIEW DEFLATE).
+driver, are available here. (e.g. --config COMPRESS_OVERVIEW DEFLATE).
 The photometric interpretation can be set with --config PHOTOMETRIC_OVERVIEW {RGB,YCBCR,...},
 and the interleaving with --config INTERLEAVE_OVERVIEW {PIXEL|BAND}.
 
@@ -562,6 +571,10 @@ documented in the GeoTIFF driver documentation.
 
 See the documentation of the GeoTIFF driver for further explanations on all those options.
 
+\section gdaladdo_api C API
+
+Functionality of this utility can be done from C with GDALBuildOverviews().
+
 \section gdaladdo_example EXAMPLE
 
 \htmlonly
@@ -581,7 +594,7 @@ gdaladdo -ro --config COMPRESS_OVERVIEW DEFLATE erdas.img 2 4 8 16
 \endverbatim
 
 Create an external JPEG-compressed GeoTIFF overview file from a 3-band RGB dataset
-(if the dataset is a writeable GeoTIFF, you also need to add the -ro option to
+(if the dataset is a writable GeoTIFF, you also need to add the -ro option to
 force the generation of external overview):
 
 \verbatim
@@ -624,7 +637,7 @@ tileindex.
 
 <dl>
 <dt><b>-f</b> format:</dt><dd> (GDAL >= 1.11)
-<p>The OGR format of the output tile index file. Default is Esri Shapefile.</p>
+<p>The OGR format of the output tile index file. Default is ESRI Shapefile.</p>
 </dd>
 <dt><b>-tileindex</b> field_name:</dt>
 <dd><p>The output field name to hold the file path/location to the indexed rasters. The default tile index field name is <code>location</code>.</p>
@@ -695,13 +708,13 @@ Builds a VRT from a list of datasets. (compiled by default since GDAL 1.6.1)
 gdalbuildvrt [-tileindex field_name]
              [-resolution {highest|lowest|average|user}]
              [-te xmin ymin xmax ymax] [-tr xres yres] [-tap]
-             [-separate] [-b band] [-sd subdataset]
+             [-separate] [-b band]* [-sd subdataset]
              [-allow_projection_difference] [-q]
              [-addalpha] [-hidenodata]
              [-srcnodata "value [value...]"] [-vrtnodata "value [value...]"] 
              [-a_srs srs_def]
              [-r {nearest,bilinear,cubic,cubicspline,lanczos,average,mode}]
-             [-input_file_list my_liste.txt] [-overwrite] output.vrt [gdalfile]*
+             [-input_file_list my_list.txt] [-overwrite] output.vrt [gdalfile]*
 \endverbatim
 
 \section gdalbuildvrt_description DESCRIPTION
@@ -712,7 +725,7 @@ of the command line, or put in a text file (one filename per line) for very long
 or it can be a MapServer tileindex (see \ref gdaltindex utility). In the later case, all
 entries in the tile index will be added to the VRT.
 
-With -separate, each files goes into a separate <i>stacked</i> band in the VRT band. Otherwise,
+With -separate, each files goes into a separate band in the VRT band. Otherwise,
 the files are considered as tiles of a larger mosaic and the VRT file has as many bands as one
 of the input files.
 
@@ -724,8 +737,13 @@ in the resulting VRT have similar characteristics : number of bands, projection,
 interpretation... If not, files that do not match the common characteristics will be skipped.
 (This is only true in the default mode, and not when using the -separate option)
 
-If there is some amount of spatial overlapping between files, the order may depend on the order they
-are inserted in the VRT file, but this behaviour should not be relied on.
+If there is some amount of spatial overlapping between files, the order of files
+appearing in the list of source matter: files that are listed at the end are the ones
+from which the content will be fetched. Note that nodata will be taken into account
+to potentially fetch data from less prioritary datasets, but currently, alpha channel
+is not taken into account to do alpha compositing (so a source with alpha=0
+appearing on top of another source will override is content). This might be
+changed in later versions.
 
 This utility is somehow equivalent to the gdal_vrtmerge.py utility and is build by default
 in GDAL 1.6.1.
@@ -784,7 +802,8 @@ is written in the NODATA element of each ComplexSource element. Use a value of
 
 <dt> <b>-b</b> <i>band</i>:</dt><dd>(GDAL >= 1.10.0) 
 Select an input <i>band</i> to be processed. Bands are numbered from 1.
-If input bands not set all bands will be added to vrt</dd>
+If input bands not set all bands will be added to vrt.
+Multiple <b>-b</b> switches may be used to select a set of input bands.</dd>
 
 <dt> <b>-sd</b> <i>subdataset</i></dt><dd> (GDAL >= 1.10.0) If the input
 dataset contains several subdatasets use a subdataset with the specified
@@ -800,7 +819,7 @@ is written in the NoDataValue element of each VRTRasterBand element. Use a value
 <tt>None</tt> to ignore intrinsic nodata settings on the source datasets.</dd>
 
 <dt> <b>-separate</b>:</dt><dd> (starting with GDAL 1.7.0)
-Place each input file into a separate <i>stacked</i> band. In that case, only the first
+Place each input file into a separate band. In that case, only the first
 band of each dataset will be placed into a new band. Contrary to the default mode, it is not
 required that all bands have the same datatype.
 </dd>
@@ -844,7 +863,7 @@ gdalbuildvrt doq_index.vrt doq/*.tif
 
 Make a virtual mosaic from files whose name is specified in a text file :
 \verbatim
-gdalbuildvrt -input_file_list my_liste.txt doq_index.vrt
+gdalbuildvrt -input_file_list my_list.txt doq_index.vrt
 \endverbatim
 
 Make a RGB virtual mosaic from 3 single-band input files :
@@ -920,6 +939,10 @@ create output in a particular format, default is shapefiles.</dd>
 <dd> Provide a name for the output vector layer.  Defaults to "contour".</dd>
 </dl>
 
+\section gdal_contour_api C API
+
+Functionality of this utility can be done from C with GDALContourGenerate().
+
 \section gdal_contour_example EXAMPLE
 
 This would create 10meter contours from the DEM data in dem.tif and produce
@@ -947,8 +970,8 @@ burns vector geometries into a raster
 Usage: gdal_rasterize [-b band]* [-i] [-at]
        [-burn value]* | [-a attribute_name] [-3d]
        [-l layername]* [-where expression] [-sql select_statement]
-       [-of format] [-a_srs srs_def] [-co "NAME=VALUE"]*
-       [-a_nodata value] [-init value]*
+       [-dialect dialect] [-of format] [-a_srs srs_def]
+       [-co "NAME=VALUE"]* [-a_nodata value] [-init value]*
        [-te xmin ymin xmax ymax] [-tr xres yres] [-tap] [-ts width height]
        [-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/
              CInt16/CInt32/CFloat32/CFloat64}] [-q]
@@ -961,8 +984,8 @@ This program burns vector geometries (points, lines, and polygons) into the
 raster band(s) of a raster image.  Vectors are read from OGR supported vector 
 formats. 
 
-Note that the vector data must be in the same coordinate system as the
-raster data; on the fly reprojection is not provided.
+Note that on the fly reprojection of vector data to the coordinate system of the
+raster data is only supported since GDAL 2.1.0.
 
 Since GDAL 1.8.0, the target GDAL file can be created by gdal_rasterize. Either
 the -tr or -ts option must be used in that case.
@@ -993,7 +1016,7 @@ The value will be burned into all output bands.</dd>
 
 <dt> <b>-3d</b>: </dt><dd> 
 Indicates that a burn value should be extracted from the "Z" values of the 
-feature. These values are adjusted by the burn value given by "-burn value" or
+feature. These values are added to the burn value given by "-burn value" or
 "-a attribute_name" if provided. As of now, only points and lines are drawn in
 3D.</dd>
 
@@ -1010,6 +1033,11 @@ to burn in from the input layer(s). </dd>
 An SQL statement to be evaluated against the datasource to produce a
 virtual layer of features to be burned in.</dd>
 
+<dt> <b>-dialect</b> <em>dialect</em>: </dt><dd> (GDAL >= 2.1.0)
+SQL dialect. In some cases can be used to use (unoptimized) OGR SQL instead of
+the native SQL of an RDBMS by passing OGRSQL. Starting with GDAL 1.10, the
+"SQLITE" dialect can also be used with any datasource.</dd>
+
 <dt> <b>-of</b> <i>format</i>:</dt><dd> (GDAL >= 1.8.0)
 Select the output format.  The default is GeoTIFF (GTiff).  Use the short format
 name.</dd>
@@ -1067,6 +1095,10 @@ Before GDAL 1.8.0, gdal_rasterize could not create new output files.</dd>
 
 </dl>
 
+\section gdal_rasterize_api C API
+
+Starting with GDAL 2.1, this utility is also callable from C with GDALRasterize().
+
 \section gdal_rasterize_example EXAMPLE
 
 The following would burn all polygons from mask.shp into the RGB TIFF
@@ -1117,7 +1149,7 @@ color table for multiple files.  The <i>palette_file</i> must be a raster file
 in a GDAL supported format with a palette.</dd>
 <dt> <b>-of</b> <i>format</i>:</dt><dd> Format to generated (defaults to GeoTIFF).  Same
 semantics as the <b>-of</b> flag for gdal_translate.  Only output formats
-supporting pseudocolor tables should be used. </dd>
+supporting pseudo-color tables should be used. </dd>
 <dt> <i>source_file</i>:</dt><dd> The input RGB file. </dd>
 <dt> <i>dest_file</i>:</dt><dd> The output pseudo-colored file that will be
 created.</dd>
@@ -1172,7 +1204,7 @@ pct2rgb.py [-of format] [-b band] [-rgba] source_file dest_file
 
 \section pct2rgb_description DESCRIPTION
 
-This utility will convert a pseudocolor band on the input file into an output
+This utility will convert a pseudo-color band on the input file into an output
 RGB file of the desired format. 
 
 <dl>
@@ -1220,12 +1252,12 @@ projection,including  GCP-based transformations.
 <dt> <b>-s_srs</b> <em>srs def</em>:</dt><dd> source spatial reference set.
 The coordinate systems that can be passed are anything supported by the
 OGRSpatialReference.SetFromUserInput() call, which includes EPSG PCS and GCSes
-(ie. EPSG:4296), PROJ.4 declarations (as above), or the name of a .prf file
+(i.e. EPSG:4296), PROJ.4 declarations (as above), or the name of a .prj file
 containing well known text.</dd>
 <dt> <b>-t_srs</b> <em>srs_def</em>:</dt><dd> target spatial reference set.
 The coordinate systems that can be passed are anything supported by the
 OGRSpatialReference.SetFromUserInput() call, which includes EPSG PCS and GCSes
-(ie. EPSG:4296), PROJ.4 declarations (as above), or the name of a .prf file
+(i.e. EPSG:4296), PROJ.4 declarations (as above), or the name of a .prj file
 containing well known text.</dd>
 <dt> <b>-to</b> <em>NAME=VALUE</em>:</dt><dd> set a transformer option suitable
 to pass to GDALCreateGenImgProjTransformer2(). </dd>
@@ -1310,15 +1342,15 @@ nearblack [-of format] [-white | [-color c1,c2,c3...cn]*] [-near dist] [-nb non_
 
 This utility will scan an image and try to set all pixels that are nearly or exactly
 black, white or one or more custom colors around the collar to black or white.  This
-is often used to "fix up" lossy compressed airphotos so that color pixels
-can be treated as transparent when mosaicking. 
+is often used to "fix up" lossy compressed air photos so that color pixels
+can be treated as transparent when mosaicing.
 
 <dl>
 <dt> <b>-o</b> <i>outfile</i>:</dt><dd> The name of the output file to be
 created.  Newly created files are created with the HFA driver by default
 (Erdas Imagine - .img)</dd>
 <dt> <b>-of</b> <i>format</i>:</dt><dd> (GDAL 1.8.0 or later) Select the output format.
-Use the short format name (GTiff for GeoTIFF for examle).</dd>
+Use the short format name (GTiff for GeoTIFF for example).</dd>
 <dt> <b>-co</b> <i>"NAME=VALUE"</i>:</dt><dd> (GDAL 1.8.0 or later) Passes a creation option to the
 output format driver.  Multiple <b>-co</b> options may be listed.  See format 
 specific documentation for legal creation options for each format. Only valid when creating a new file</dd>
@@ -1366,6 +1398,10 @@ The processing is all done in 8bit (Bytes).
 If the output file is omitted, the processed results will be written back
 to the input file - which must support update. 
 
+\section nearblack_api C API
+
+Starting with GDAL 2.1, this utility is also callable from C with GDALNearblack().
+
 \if man
 \section nearblack_author AUTHORS
 Frank Warmerdam <warmerdam at pobox.com>
@@ -1381,8 +1417,9 @@ mosaics a set of images
 
 \verbatim
 gdal_merge.py [-o out_filename] [-of out_format] [-co NAME=VALUE]*
-              [-ps pixelsize_x pixelsize_y] [-tap] [-separate] [-v] [-pct]
-              [-ul_lr ulx uly lrx lry] [-n nodata_value] [-init "value [value...]"]
+              [-ps pixelsize_x pixelsize_y] [-tap] [-separate] [-q] [-v] [-pct]
+              [-ul_lr ulx uly lrx lry] [-init "value [value...]"]
+              [-n nodata_value] [-a_nodata output_nodata_value]
               [-ot datatype] [-createonly] input_files
 \endverbatim
 
@@ -1403,7 +1440,7 @@ Output format, defaults to GeoTIFF (GTiff).
 Creation option for output file.  Multiple options can be specified.
 </dd>
 <dt> <b>-ot</b> <i>datatype</i>:</dt><dd> 
-Force the output image bands to have a specific type. Use type names (ie. Byte, Int16,...)
+Force the output image bands to have a specific type. Use type names (i.e. Byte, Int16,...)
 </dd>
 <dt> <b>-ps</b> <i>pixelsize_x pixelsize_y</i>:</dt><dd> Pixel size to be used for the
 output file.  If not specified the resolution of the first input file will
@@ -1419,11 +1456,11 @@ used.</dd>
 <dt>
 <dt> <b>-v</b>:</dt><dd> Generate verbose output of mosaicing operations as they are done.</dd>
 <dt> <b>-separate</b>:</dt><dd> 
-Place each input file into a separate <i>stacked</i> band. 
+Place each input file into a separate band. 
 </dd>
 <dt> <b>-pct</b>:</dt><dd> 
-Grab a pseudocolor table from the first input image, and use it for the output.
-Merging pseudocolored images this way assumes that all input files use the same
+Grab a pseudo-color table from the first input image, and use it for the output.
+Merging pseudo-colored images this way assumes that all input files use the same
 color table.
 </dd>
 <dt> <b>-n</b> <i>nodata_value</i>:</dt><dd> 
@@ -1475,7 +1512,7 @@ generates directory with TMS tiles, KMLs and simple web viewers
 
 \verbatim
 gdal2tiles.py [-p profile] [-r resampling] [-s srs] [-z zoom]
-              [-e] [-a nodata] [-v] [-h] [-k] [-n] [-u url]
+              [-e] [-a nodata] [-v] [-q] [-h] [-k] [-n] [-u url]
               [-w webviewer] [-t title] [-c copyright]
               [-g googlekey] [-b bingkey] input_file [output_dir]
 \endverbatim
@@ -1484,7 +1521,7 @@ gdal2tiles.py [-p profile] [-r resampling] [-s srs] [-z zoom]
 
 This utility generates a directory with small tiles and metadata, following
 the OSGeo Tile Map Service Specification. Simple web pages with viewers based on
-Google Maps and OpenLayers are generated as well - so anybody can comfortably
+Google Maps, OpenLayers and Leaflet are generated as well - so anybody can comfortably
 explore your maps on-line and you do not need to install or configure any
 special software (like MapServer) and the map displays very fast in the
 web browser. You only need to upload the generated directory onto a web server.
@@ -1510,9 +1547,11 @@ can publish a picture without proper georeferencing too.
   <dd>NODATA transparency value to assign to the input data.</dd>
 <dt> <b>-v, --verbose</b></dt>
   <dd>Generate verbose output of tile generation.</dd>
+<dt> <b>-q, --quiet</b></dt>
+  <dd>Disable messages and status to stdout (GDAL >= 2.1).</dd>
 <dt> <b>-h, --help</b></dt>
   <dd>Show help message and exit.</dd>
-<dt> <b>--version</b></dt>
+<dt> <b>\-\-version</b></dt>
   <dd>Show program's version number and exit.</dd>
 </dl>
 
@@ -1533,7 +1572,7 @@ Options for generated Google Earth SuperOverlay metadata
 Options for generated HTML viewers a la Google Maps
 <dl>
 <dt> <b>-w</b> <i>WEBVIEWER</i>, --webviewer=<i>WEBVIEWER</i>:</dt>
-  <dd>Web viewer to generate (all,google,openlayers,none) - default 'all'.</dd>
+  <dd>Web viewer to generate (all,google,openlayers,leaflet,none) - default 'all'.</dd>
 <dt> <b>-t</b> <i>TITLE</i>, --title=<i>TITLE</i>:</dt>
   <dd>Title of the map.</dd>
 <dt> <b>-c</b> <i>COPYRIGHT</i>, --copyright=<i>COPYRIGHT</i>:</dt>
@@ -1580,16 +1619,16 @@ by configure scripts for applications using GDAL but can be queried by an
 end user. 
 
 <dl>
-<dt> <b>--prefix</b>:</dt><dd> the top level directory for the GDAL
+<dt> <b>\-\-prefix</b>:</dt><dd> the top level directory for the GDAL
 installation.</dd>
-<dt> <b>--libs</b>:</dt><dd> The libraries and link directives required to
+<dt> <b>\-\-libs</b>:</dt><dd> The libraries and link directives required to
 use GDAL.</dd>
-<dt> <b>--cflags</b>:</dt><dd> The include and macro definition required to compiled
+<dt> <b>\-\-cflags</b>:</dt><dd> The include and macro definition required to compiled
 modules using GDAL.</dd>
-<dt> <b>--version</b>:</dt><dd> Reports the GDAL version.</dd>
-<dt> <b>--ogr-enabled</b>:</dt><dd> Reports "yes" or "no" to standard output depending
+<dt> <b>\-\-version</b>:</dt><dd> Reports the GDAL version.</dd>
+<dt> <b>\-\-ogr-enabled</b>:</dt><dd> Reports "yes" or "no" to standard output depending
 on whether OGR is built into GDAL.</dd>
-<dt> <b>--formats</b>:</dt><dd> Reports which formats are configured into GDAL 
+<dt> <b>\-\-formats</b>:</dt><dd> Reports which formats are configured into GDAL 
 to stdout.  
 </dd>
 </dl>
@@ -1637,7 +1676,7 @@ If your number of input tiles exhausts the command line buffer, use the general
 <dl>
 <dt> <b>-targetDir</b> <i>directory</i>:</dt><dd>
 The directory where the tile result is created. Pyramids are stored
-in  subdirectories  numbered  from  1. Created tile names have a numbering
+in  sub-directories  numbered  from  1. Created tile names have a numbering
 schema and contain the name of the source tiles(s)
 </dd>
 <dt> <b>-of</b> <i>format</i>:</dt><dd>
@@ -1647,7 +1686,7 @@ Output format, defaults to GeoTIFF (GTiff).
 Creation option for output file.  Multiple options can be specified.
 </dd>
 <dt> <b>-ot</b> <i>datatype</i>:</dt><dd>
-Force the output image bands to have a specific type. Use type names (ie. Byte, Int16,...)
+Force the output image bands to have a specific type. Use type names (i.e. Byte, Int16,...)
 </dd>
 <dt> <b>-ps</b> <i>pixelsize_x pixelsize_y</i>:</dt><dd> Pixel size to be used for the
 output file.  If not specified, 256 x 256 is the default
@@ -1666,9 +1705,9 @@ Resampling algorithm, default is near
 </dd>
 <dt> <b>-s_srs</b> <i>srs_def</i>:</dt><dd>
 Source spatial reference to use. The coordinate systems  that  can  be
-passed  are  anything  supported by the OGRSpatialReference.SetFro‐mUserInput()  call,
-which  includes  EPSG  PCS  and   GCSes   (ie.EPSG:4296),  PROJ.4  declarations (as above),
-or the name of a .prf file containing well known text.
+passed  are  anything  supported by the OGRSpatialReference.SetFromUserInput()  call,
+which  includes  EPSG, PCS, and GCSes (i.e. EPSG:4296), PROJ.4 declarations (as above),
+or the name of a .prj file containing well known text.
 If  no  srs_def  is  given,  the srs_def  of the source tiles is used (if there is any).
 The srs_def will be propagated to created tiles (if possible) and  to  the  optional
 shape file(s)
@@ -1684,17 +1723,17 @@ The name of the csv file containing the tile(s) georeferencing information.
 The file contains 5 columns: tilename,minx,maxx,miny,maxy
 </dd>
 <dt> <b>-csvDelim</b> <i>column delimiter</i>:</dt><dd>
-The column delimter used in the csv file, default value is a semicolon ";"
+The column delimiter used in the CSV file, default value is a semicolon ";"
 </dd>
 <dt> <b>-useDirForEachRow</b>:</dt><dd>
 Normally the tiles of the base image are stored as described in <b>-targetDir</b>.
 For large images, some file systems have performance problems if the number of files 
 in a directory is to big, causing gdal_retile not to finish in reasonable time. 
 Using this parameter creates a different output structure. The tiles of the base image
-are stored in a subdirectory called 0, the pyramids in subdirectories numbered 1,2,....
-Within each of these directories another level of subdirectories is created, numbered from
+are stored in a sub-directory called 0, the pyramids in sub-directories numbered 1,2,....
+Within each of these directories another level of sub-directories is created, numbered from
 0...n, depending of how many tile rows are needed for each level. Finally, a directory contains
-only the the tiles for one row for a specific level. For large images a performance improvement
+only the tiles for one row for a specific level. For large images a performance improvement
 of a factor N could be achieved.
 </dd>
 </dl>
@@ -1864,6 +1903,25 @@ non-zero). Default is 0.</dd>
 0.0).</dd>
 </dl>
 
+\subsection gdal_grid_algorithms_invdist_nearest_neighbor invdistnn
+
+(Since GDAL 2.1) Inverse distance to a power with nearest neighbor searching, ideal when 
+max_points is used. It has following parameters:
+
+<dl>
+<dt><i>power</i>:</dt> <dd>Weighting power (default 2.0).</dd>
+<dt><i>radius</i>:</dt> <dd>The radius of the search circle, which should be 
+non-zero. Default is 1.0.</dd>
+<dt><i>max_points</i>:</dt> <dd>Maximum number of data points to use. Do not
+search for more points than this number. Found points will be ranked from 
+nearest to furthest distance when weighting. Default is 12.</dd>
+<dt><i>min_points</i>:</dt> <dd>Minimum number of data points to use. If less
+amount of points found the grid node is considered empty and will be filled 
+with NODATA marker. Default is 0.</dd>
+<dt><i>nodata</i>:</dt> <dd>NODATA marker to fill empty points (default
+0.0).</dd>
+</dl>
+
 \subsection gdal_grid_algorithms_average average
 
 Moving average algorithm. It has following parameters:
@@ -1904,6 +1962,28 @@ Default is 0.0.</dd>
 0.0).</dd>
 </dl>
 
+\subsection gdal_grid_algorithms_linear linear
+
+(Since GDAL 2.1) Linear interpolation algorithm.
+
+The Linear method performs linear interpolation by computing a Delaunay
+triangulation of the point cloud, finding in which triangle of the triangulation
+the point is, and by doing linear interpolation from its barycentric coordinates
+within the triangle.
+If the point is not in any triangle, depending on the radius, the
+algorithm will use the value of the nearest point or the nodata value.
+
+It has following parameters:
+
+<dl>
+<dt><i>radius</i>:</dt> <dd>In case the point to be interpolated does not fit
+into a triangle of the Delaunay triangulation, use that maximum distance to search a nearest
+neighbour, or use nodata otherwise. If set to -1, the search distance is infinite.
+If set to 0, nodata value will be always used. Default is -1.</dd>
+<dt><i>nodata</i>:</dt> <dd>NODATA marker to fill empty points (default
+0.0).</dd>
+</dl>
+
 \section gdal_grid_metrics DATA METRICS
 
 Besides the interpolation functionality \ref gdal_grid can be used to compute
@@ -2007,6 +2087,10 @@ following way:
 <a href="ogr/drv_csv.html">Comma Separated Value</a> description page contains
 details on CSV format supported by GDAL/OGR.
 
+\section gdal_grid_api C API
+
+Starting with GDAL 2.1, this utility is also callable from C with GDALGrid().
+
 \section gdal_grid_example EXAMPLE
 
 The following would create raster TIFF file from VRT datasource described in
@@ -2118,7 +2202,7 @@ The following general options are available :
 <dt> <b>-of</b> <i>format</i>:</dt><dd> Select the output format.  The default
 is GeoTIFF (GTiff).  Use the short format name.</dd>
 <dt> <b>-compute_edges</b>:</dt><dd> (GDAL >= 1.8.0) Do the computation at raster edges and near nodata values</dd>
-<dt> <b>-alg</b> <i>ZevenbergenThorne</i>:</dt><dd> (GDAL >= 1.8.0) Use Zevenbergen & Thorne formula, instead of Horn's formula, to compute slope & aspect. The litterature suggests Zevenbergen & Thorne to be more suited to smooth landscapes, whereas Horn's formula to perform better on rougher terrain.</dd>
+<dt> <b>-alg</b> <i>ZevenbergenThorne</i>:</dt><dd> (GDAL >= 1.8.0) Use Zevenbergen & Thorne formula, instead of Horn's formula, to compute slope & aspect. The literature suggests Zevenbergen & Thorne to be more suited to smooth landscapes, whereas Horn's formula to perform better on rougher terrain.</dd>
 <dt> <b>-b</b> <i>band</i>:</dt><dd> Select an input <i>band</i> to be processed. Bands are numbered from 1.</dd>
 <dt> <b>-co</b> <i>"NAME=VALUE"</i>:</dt><dd> Passes a creation option to the
 output format driver.  Multiple <b>-co</b> options may be listed.  See format 
@@ -2258,6 +2342,10 @@ The value -9999 is used as the output nodata value.
 
 There are no specific options.
 
+\section gdaldem_api C API
+
+Starting with GDAL 2.1, this utility is also callable from C with GDALDEMProcessing().
+
 
 \section gdaldem_author AUTHORS
 Matthew Perry <perrygeo at gmail.com>, Even Rouault <even.rouault at mines-paris.org>, Howard Butler <hobu.inc at gmail.com>, Chris Yesson <chris.yesson at ioz.ac.uk>
@@ -2464,7 +2552,7 @@ The gdalmanage program can perform various operations on raster data files, depe
 <dt> <i>newdatasetname</i>:</dt><dd>For copy and rename modes, you provide a <i>source</i> filename and a <i>target</i> filename, just like copy and move commands in an operating system.</dd>
 </dl>
 
-\section gdalmanage_exampes EXAMPLES
+\section gdalmanage_examples EXAMPLES
 
 \subsection gdalmanage_example_identify Using identify mode
 
@@ -2520,3 +2608,103 @@ gdalmanage delete NE1_50M_SR_W.tif
 Tyler Mitchell <spatialguru at shaw.ca>
 \endif
 */
+
+*******************************************************************************
+/*! \page gdal_pansharpen gdal_pansharpen.py
+
+Perform a pansharpen operation.
+
+(Since GDAL 2.1)
+
+\section gdal_pansharpen_synopsis SYNOPSIS
+
+\verbatim
+gdal_pansharpen [--help-general] pan_dataset {spectral_dataset[,band=num]}+ out_dataset
+                [-of format] [-b band]* [-w weight_val]*
+                [-r {nearest,bilinear,cubic,cubicspline,lanczos,average}]
+                [-threads {ALL_CPUS|number}] [-bitdepth val] [-nodata val]
+                [-spat_adjust {union,intersection,none,nonewithoutwarning}]
+                [-co NAME=VALUE]* [-q]
+\endverbatim
+
+\section gdal_pansharpen_description DESCRIPTION
+
+The gdal_pansharpen.py script performs a pan-sharpening operation. It can create
+a "classic" output dataset (such as GeoTIFF), or a VRT dataset describing the
+pan-sharpening operation.
+
+More details can be found in the <a href="gdal_vrttut.html#gdal_vrttut_pansharpen">VRT tutorial</a>.
+
+<dl>
+<dt> <b>-of</b> <i>format</i>:</dt><dd> Select the output format.  The default
+is GeoTIFF (GTiff). "VRT" can also be used. Use the short format name.</dd>
+<dt> <b>-b</b> <i>band</i>:</dt><dd> Select band <i>band</i> from the input spectral
+bands for output. Bands are numbered from 1 in the order spectral bands are specified.
+Multiple <b>-b</b> switches may be used.
+When no -b switch is used, all input spectral bands are set for output.</dd>
+<dt> <b>-w</b> <i>weight_val</i>:</dt><dd>Specify a weight for the computation of the
+pseudo panchromatic value. There must be as many -w switches as input spectral bands.</dd>
+<dt> <b>-r</b>
+<i>{nearest,bilinear,cubic (default),cubicspline,lanczos,average}</i>:</dt><dd>
+Select a resampling algorithm.</dd>
+<dt> <b>-threads</b> <i>{ALL_CPUS,number}</i>:</dt><dd>
+Specify number of threads to use to do the resampling and pan-sharpening itself.
+Can be an integer number or ALL_CPUS.</dd>
+<dt> <b>-bitdepth</b> <i>val</i>:</dt><dd>
+Specify the bit depth of the panchromatic and
+spectral bands (e.g. 12). If not specified, the NBITS metadata item from the
+panchromatic band will be used if it exists.</dd>
+<dt> <b>-nodata</b> <i>val</i>:</dt><dd>
+Specify nodata value for bands. Used for the resampling and pan-sharpening computation
+itself. If not set, deduced from the input bands, provided they have a consistent
+setting.</dd>
+<dt> <b>-spat_adjust</b>
+<i>{union (default),intersection,none,nonewithoutwarning}</i>:</dt><dd>
+Select behaviour when bands have not the same extent. See <i>SpatialExtentAdjustment</i>
+documentation in  <a href="gdal_vrttut.html#gdal_vrttut_pansharpen">VRT tutorial</a></dd>
+<dt> <b>-co</b> <i>"NAME=VALUE"</i>:</dt><dd> Passes a creation option to the
+output format driver.  Multiple <b>-co</b> options may be listed.  See format 
+specific documentation for legal creation options for each format.</dd>
+<dt> <b>-q</b>:</dt><dd> Suppress progress monitor and other non-error
+output.</dd>
+<dt> <i>pan_dataset</i></dt><dd> Dataset with panchromatic band (first band will be used).</dd>
+<dt> <i>spectral_dataset[,band=num]</i></dt><dd> Dataset with one or several spectral bands. If
+the band option is not specified, all bands of the datasets are taken into account. Otherwise,
+only the specified (num)th band. The same dataset can be repeated several times.</dd>
+<dt> <i>out_dataset</i></dt><dd> Output dataset</dd>
+</dl>
+
+Bands should be in the same projection.
+
+\section gdal_pansharpen_example EXAMPLE
+
+With spectral bands in a single dataset :
+\verbatim
+gdal_pansharpen.py panchro.tif multispectral.tif pansharpened_out.tif
+\endverbatim
+
+With a few spectral bands from a single dataset, reordered :
+\verbatim
+gdal_pansharpen.py panchro.tif multispectral.tif,band=3 multispectral.tif,band=2 multispectral.tif,band=1 pansharpened_out.tif
+\endverbatim
+
+With spectral bands in several datasets :
+\verbatim
+gdal_pansharpen.py panchro.tif band1.tif band2.tif band3.tif pansharpened_out.tif
+\endverbatim
+
+Specify weights:
+\verbatim
+gdal_pansharpen.py -w 0.7 -w 0.2 -w 0.1 panchro.tif multispectral.tif pansharpened_out.tif
+\endverbatim
+
+Specify RGB bands from a RGBNir multispectral dataset while computing the pseudo panchromatic intensity on the 4 RGBNir bands:
+\verbatim
+gdal_pansharpen.py -b 1 -b 2 -b 3 panchro.tif rgbnir.tif pansharpened_out.tif
+\endverbatim
+
+\if man
+\section gdal_pansharpen_author AUTHORS
+Even Rouault <even.rouault at spatialys.com>
+\endif
+*/
diff --git a/apps/gdal_utils.h b/apps/gdal_utils.h
new file mode 100644
index 0000000..1777131
--- /dev/null
+++ b/apps/gdal_utils.h
@@ -0,0 +1,214 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL Utilities
+ * Purpose:  GDAL Utilities Public Declarations.
+ * Author:   Faza Mahamood, fazamhd at gmail dot com
+ *
+ * ****************************************************************************
+ * Copyright (c) 1998, Frank Warmerdam
+ * Copyright (c) 2007-2015, Even Rouault <even.rouault at spatialys.com>
+ * Copyright (c) 2015, Faza Mahamood
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef GDAL_UTILS_H_INCLUDED
+#define GDAL_UTILS_H_INCLUDED
+
+/**
+ * \file gdal_utils.h
+ *
+ * Public (C callable) GDAL Utilities entry points.
+ *
+ * @since GDAL 2.1
+ */
+
+#include "cpl_port.h"
+#include "gdal.h"
+
+CPL_C_START
+
+/*! Options for GDALInfo(). Opaque type */
+typedef struct GDALInfoOptions GDALInfoOptions;
+
+typedef struct GDALInfoOptionsForBinary GDALInfoOptionsForBinary;
+
+GDALInfoOptions CPL_DLL *GDALInfoOptionsNew(char** papszArgv, GDALInfoOptionsForBinary* psOptionsForBinary);
+
+void CPL_DLL GDALInfoOptionsFree( GDALInfoOptions *psOptions );
+
+char CPL_DLL *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions );
+
+
+/*! Options for GDALTranslate(). Opaque type */
+typedef struct GDALTranslateOptions GDALTranslateOptions;
+
+typedef struct GDALTranslateOptionsForBinary GDALTranslateOptionsForBinary;
+
+GDALTranslateOptions CPL_DLL *GDALTranslateOptionsNew(char** papszArgv,
+                                                      GDALTranslateOptionsForBinary* psOptionsForBinary);
+
+void CPL_DLL GDALTranslateOptionsFree( GDALTranslateOptions *psOptions );
+
+void CPL_DLL GDALTranslateOptionsSetProgress( GDALTranslateOptions *psOptions,
+                                              GDALProgressFunc pfnProgress,
+                                              void *pProgressData );
+
+GDALDatasetH CPL_DLL GDALTranslate(const char *pszDestFilename,
+                                   GDALDatasetH hSrcDataset,
+                                   const GDALTranslateOptions *psOptions,
+                                   int *pbUsageError);
+
+/*! Options for GDALWarp(). Opaque type */
+typedef struct GDALWarpAppOptions GDALWarpAppOptions;
+
+typedef struct GDALWarpAppOptionsForBinary GDALWarpAppOptionsForBinary;
+
+GDALWarpAppOptions CPL_DLL *GDALWarpAppOptionsNew(char** papszArgv,
+                                                      GDALWarpAppOptionsForBinary* psOptionsForBinary);
+
+void CPL_DLL GDALWarpAppOptionsFree( GDALWarpAppOptions *psOptions );
+
+void CPL_DLL GDALWarpAppOptionsSetProgress( GDALWarpAppOptions *psOptions,
+                                              GDALProgressFunc pfnProgress,
+                                              void *pProgressData );
+void CPL_DLL GDALWarpAppOptionsSetWarpOption( GDALWarpAppOptions *psOptions,
+                                              const char* pszKey,
+                                              const char* pszValue );
+
+GDALDatasetH CPL_DLL GDALWarp( const char *pszDest, GDALDatasetH hDstDS,
+                               int nSrcCount, GDALDatasetH *pahSrcDS,
+                               const GDALWarpAppOptions *psOptions, int *pbUsageError );
+
+/*! Options for GDALVectorTranslate(). Opaque type */
+typedef struct GDALVectorTranslateOptions GDALVectorTranslateOptions;
+
+typedef struct GDALVectorTranslateOptionsForBinary GDALVectorTranslateOptionsForBinary;
+
+GDALVectorTranslateOptions CPL_DLL *GDALVectorTranslateOptionsNew(char** papszArgv,
+                                                      GDALVectorTranslateOptionsForBinary* psOptionsForBinary);
+
+void CPL_DLL GDALVectorTranslateOptionsFree( GDALVectorTranslateOptions *psOptions );
+
+void CPL_DLL GDALVectorTranslateOptionsSetProgress( GDALVectorTranslateOptions *psOptions,
+                                              GDALProgressFunc pfnProgress,
+                                              void *pProgressData );
+
+GDALDatasetH CPL_DLL GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int nSrcCount,
+                               GDALDatasetH *pahSrcDS,
+                               const GDALVectorTranslateOptions *psOptions, int *pbUsageError );
+
+
+/*! Options for GDALDEMProcessing(). Opaque type */
+typedef struct GDALDEMProcessingOptions GDALDEMProcessingOptions;
+
+typedef struct GDALDEMProcessingOptionsForBinary GDALDEMProcessingOptionsForBinary;
+
+GDALDEMProcessingOptions CPL_DLL *GDALDEMProcessingOptionsNew(char** papszArgv,
+                                                      GDALDEMProcessingOptionsForBinary* psOptionsForBinary);
+
+void CPL_DLL GDALDEMProcessingOptionsFree( GDALDEMProcessingOptions *psOptions );
+
+void CPL_DLL GDALDEMProcessingOptionsSetProgress( GDALDEMProcessingOptions *psOptions,
+                                              GDALProgressFunc pfnProgress,
+                                              void *pProgressData );
+
+GDALDatasetH CPL_DLL GDALDEMProcessing(const char *pszDestFilename,
+                                       GDALDatasetH hSrcDataset,
+                                       const char* pszProcessing,
+                                       const char* pszColorFilename,
+                                       const GDALDEMProcessingOptions *psOptions,
+                                       int *pbUsageError);
+
+/*! Options for GDALNearblack(). Opaque type */
+typedef struct GDALNearblackOptions GDALNearblackOptions;
+
+typedef struct GDALNearblackOptionsForBinary GDALNearblackOptionsForBinary;
+
+GDALNearblackOptions CPL_DLL *GDALNearblackOptionsNew(char** papszArgv,
+                                                      GDALNearblackOptionsForBinary* psOptionsForBinary);
+
+void CPL_DLL GDALNearblackOptionsFree( GDALNearblackOptions *psOptions );
+
+void CPL_DLL GDALNearblackOptionsSetProgress( GDALNearblackOptions *psOptions,
+                                              GDALProgressFunc pfnProgress,
+                                              void *pProgressData );
+
+GDALDatasetH CPL_DLL GDALNearblack( const char *pszDest, GDALDatasetH hDstDS,
+                                    GDALDatasetH hSrcDS,
+                                    const GDALNearblackOptions *psOptions, int *pbUsageError );
+
+/*! Options for GDALGrid(). Opaque type */
+typedef struct GDALGridOptions GDALGridOptions;
+
+typedef struct GDALGridOptionsForBinary GDALGridOptionsForBinary;
+
+GDALGridOptions CPL_DLL *GDALGridOptionsNew(char** papszArgv,
+                                                      GDALGridOptionsForBinary* psOptionsForBinary);
+
+void CPL_DLL GDALGridOptionsFree( GDALGridOptions *psOptions );
+
+void CPL_DLL GDALGridOptionsSetProgress( GDALGridOptions *psOptions,
+                                              GDALProgressFunc pfnProgress,
+                                              void *pProgressData );
+
+GDALDatasetH CPL_DLL GDALGrid( const char *pszDest,
+                               GDALDatasetH hSrcDS,
+                               const GDALGridOptions *psOptions, int *pbUsageError );
+
+/*! Options for GDALRasterize(). Opaque type */
+typedef struct GDALRasterizeOptions GDALRasterizeOptions;
+
+typedef struct GDALRasterizeOptionsForBinary GDALRasterizeOptionsForBinary;
+
+GDALRasterizeOptions CPL_DLL *GDALRasterizeOptionsNew(char** papszArgv,
+                                                      GDALRasterizeOptionsForBinary* psOptionsForBinary);
+
+void CPL_DLL GDALRasterizeOptionsFree( GDALRasterizeOptions *psOptions );
+
+void CPL_DLL GDALRasterizeOptionsSetProgress( GDALRasterizeOptions *psOptions,
+                                              GDALProgressFunc pfnProgress,
+                                              void *pProgressData );
+
+GDALDatasetH CPL_DLL GDALRasterize( const char *pszDest, GDALDatasetH hDstDS,
+                                    GDALDatasetH hSrcDS,
+                                    const GDALRasterizeOptions *psOptions, int *pbUsageError );
+
+/*! Options for GDALBuildVRT(). Opaque type */
+typedef struct GDALBuildVRTOptions GDALBuildVRTOptions;
+
+typedef struct GDALBuildVRTOptionsForBinary GDALBuildVRTOptionsForBinary;
+
+GDALBuildVRTOptions CPL_DLL *GDALBuildVRTOptionsNew(char** papszArgv,
+                                                      GDALBuildVRTOptionsForBinary* psOptionsForBinary);
+
+void CPL_DLL GDALBuildVRTOptionsFree( GDALBuildVRTOptions *psOptions );
+
+void CPL_DLL GDALBuildVRTOptionsSetProgress( GDALBuildVRTOptions *psOptions,
+                                              GDALProgressFunc pfnProgress,
+                                              void *pProgressData );
+
+GDALDatasetH CPL_DLL GDALBuildVRT( const char *pszDest,
+                                   int nSrcCount, GDALDatasetH *pahSrcDS, const char* const* papszSrcDSNames,
+                                   const GDALBuildVRTOptions *psOptions, int *pbUsageError );
+
+CPL_C_END
+
+#endif /* GDAL_UTILS_H_INCLUDED */
diff --git a/apps/gdal_utils_priv.h b/apps/gdal_utils_priv.h
new file mode 100644
index 0000000..6cc13c2
--- /dev/null
+++ b/apps/gdal_utils_priv.h
@@ -0,0 +1,149 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL Utilities
+ * Purpose:  GDAL Utilities Private Declarations.
+ * Author:   Even Rouault <even.rouault at spatialys.com>
+ *
+ * ****************************************************************************
+ * Copyright (c) 2015, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef GDAL_UTILS_PRIV_H_INCLUDED
+#define GDAL_UTILS_PRIV_H_INCLUDED
+
+#include "cpl_port.h"
+#include "gdal_utils.h"
+
+/* This file is only meant at being used by the XXXX_bin.cpp and XXXX_lib.cpp files */
+
+CPL_C_START
+
+struct GDALInfoOptionsForBinary
+{
+    /* Filename to open. */
+    char* pszFilename;
+
+    /* Open options. */
+    char** papszOpenOptions;
+
+    /* > for reporting on a particular subdataset */
+    int nSubdataset;
+};
+
+struct GDALTranslateOptionsForBinary
+{
+    char* pszSource;
+    char* pszDest;
+    int bQuiet;
+    int bCopySubDatasets;
+    char** papszOpenOptions;
+    int bFormatExplicitlySet;
+    char* pszFormat;
+};
+
+struct GDALWarpAppOptionsForBinary
+{
+    char** papszSrcFiles;
+    char* pszDstFilename;
+    int bQuiet;
+    char** papszOpenOptions;
+
+    /*! output dataset open option (format specific) */
+    char **papszDestOpenOptions;
+
+    int bOverwrite;
+    int bCreateOutput;
+    int bFormatExplicitlySet;
+    char* pszFormat;
+};
+
+/* Access modes */
+typedef enum
+{
+    ACCESS_CREATION,
+    ACCESS_UPDATE, /* open existing output datasource in update mode rather than trying to create a new one */
+    ACCESS_APPEND, /* append to existing layer instead of creating new */
+    ACCESS_OVERWRITE /*  delete the output layer and recreate it empty */
+} GDALVectorTranslateAccessMode;
+
+struct GDALVectorTranslateOptionsForBinary
+{
+    char* pszDataSource;
+    char* pszDestDataSource;
+    int bQuiet;
+    char** papszOpenOptions;
+    int bFormatExplicitlySet;
+    char* pszFormat;
+    GDALVectorTranslateAccessMode eAccessMode;
+};
+
+struct GDALDEMProcessingOptionsForBinary
+{
+    char* pszProcessing;
+    char* pszSrcFilename;
+    char* pszColorFilename;
+    char* pszDstFilename;
+    int bQuiet;
+    int bFormatExplicitlySet;
+    char* pszFormat;
+};
+
+struct GDALNearblackOptionsForBinary
+{
+    char* pszInFile;
+    char* pszOutFile;
+    int bQuiet;
+    int bFormatExplicitlySet;
+    char* pszFormat;
+};
+
+struct GDALGridOptionsForBinary
+{
+    char* pszSource;
+    char* pszDest;
+    int bQuiet;
+    int bFormatExplicitlySet;
+    char* pszFormat;
+};
+
+struct GDALRasterizeOptionsForBinary
+{
+    char* pszSource;
+    char* pszDest;
+    int bQuiet;
+    int bFormatExplicitlySet;
+    char* pszFormat;
+    int bCreateOutput;
+};
+
+struct GDALBuildVRTOptionsForBinary
+{
+    int nSrcFiles;
+    char** papszSrcFiles;
+    char* pszDstFilename;
+    int bQuiet;
+    int bOverwrite;
+};
+
+CPL_C_END
+
+#endif /* GDAL_UTILS_PRIV_H_INCLUDED */
diff --git a/apps/gdaladdo.cpp b/apps/gdaladdo.cpp
index 0397785..54c0851 100644
--- a/apps/gdaladdo.cpp
+++ b/apps/gdaladdo.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: gdaladdo.cpp 31759 2015-11-25 15:40:59Z rouault $
+ * $Id: gdaladdo.cpp 33843 2016-04-01 08:37:57Z rouault $
  *
  * Project:  GDAL Utilities
- * Purpose:  Commandline application to build overviews. 
+ * Purpose:  Command line application to build overviews.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -31,7 +31,7 @@
 #include "gdal_priv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: gdaladdo.cpp 31759 2015-11-25 15:40:59Z rouault $");
+CPL_CVSID("$Id: gdaladdo.cpp 33843 2016-04-01 08:37:57Z rouault $");
 
 /************************************************************************/
 /*                               Usage()                                */
@@ -47,7 +47,7 @@ static void Usage(const char* pszErrorMsg = NULL)
             "  -ro : open the dataset in read-only mode, in order to generate\n"
             "        external overview (for GeoTIFF datasets especially)\n"
             "  -clean : remove all overviews\n"
-            "  -q : turn off progress display\n" 
+            "  -q : turn off progress display\n"
             "  -b : band to create overview (if not set overviews will be created for all bands)\n"
             "  filename: The file to build overviews for (or whose overviews must be removed).\n"
             "  levels: A list of integral overview levels to build. Ignored with -clean option.\n"
@@ -73,6 +73,30 @@ static void Usage(const char* pszErrorMsg = NULL)
 }
 
 /************************************************************************/
+/*                        GDALAddoErrorHandler()                        */
+/************************************************************************/
+
+class GDALError
+{
+  public:
+      CPLErr            m_eErr;
+      CPLErrorNum       m_errNum;
+      CPLString         m_osMsg;
+
+      GDALError( CPLErr eErr = CE_None, CPLErrorNum errNum= CPLE_None, const char * pszMsg = "") :
+          m_eErr(eErr), m_errNum(errNum), m_osMsg(pszMsg ? pszMsg : "")
+      {
+      }
+};
+
+std::vector<GDALError> aoErrors;
+
+static void CPL_STDCALL GDALAddoErrorHandler( CPLErr eErr, CPLErrorNum errNum, const char * pszMsg )
+{
+    aoErrors.push_back(GDALError(eErr, errNum, pszMsg));
+}
+
+/************************************************************************/
 /*                                main()                                */
 /************************************************************************/
 
@@ -91,7 +115,7 @@ int main( int nArgc, char ** papszArgv )
     int              nResultStatus = 0;
     int              bReadOnly = FALSE;
     int              bClean = FALSE;
-    GDALProgressFunc pfnProgress = GDALTermProgress; 
+    GDALProgressFunc pfnProgress = GDALTermProgress;
     int             *panBandList = NULL;
     int              nBandCount = 0;
     char           **papszOpenOptions = NULL;
@@ -112,7 +136,7 @@ int main( int nArgc, char ** papszArgv )
         exit( -nArgc );
 
 /* -------------------------------------------------------------------- */
-/*      Parse commandline.                                              */
+/*      Parse command line.                                              */
 /* -------------------------------------------------------------------- */
     for( int iArg = 1; iArg < nArgc; iArg++ )
     {
@@ -120,6 +144,7 @@ int main( int nArgc, char ** papszArgv )
         {
             printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
                    papszArgv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
+            CSLDestroy( papszArgv );
             return 0;
         }
         else if( EQUAL(papszArgv[iArg],"--help") )
@@ -133,8 +158,8 @@ int main( int nArgc, char ** papszArgv )
             bReadOnly = TRUE;
         else if( EQUAL(papszArgv[iArg],"-clean"))
             bClean = TRUE;
-        else if( EQUAL(papszArgv[iArg],"-q") || EQUAL(papszArgv[iArg],"-quiet") ) 
-            pfnProgress = GDALDummyProgress; 
+        else if( EQUAL(papszArgv[iArg],"-q") || EQUAL(papszArgv[iArg],"-quiet") )
+            pfnProgress = GDALDummyProgress;
         else if( EQUAL(papszArgv[iArg],"-b"))
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
@@ -144,13 +169,11 @@ int main( int nArgc, char ** papszArgv )
             {
                 printf( "Unrecognizable band number (%s).\n", papszArgv[iArg+1] );
                 Usage();
-                GDALDestroyDriverManager();
-                exit( 2 );
             }
             iArg++;
 
             nBandCount++;
-            panBandList = (int *) 
+            panBandList = (int *)
                 CPLRealloc(panBandList, sizeof(int) * nBandCount);
             panBandList[nBandCount-1] = nBand;
         }
@@ -189,9 +212,18 @@ int main( int nArgc, char ** papszArgv )
         hDataset = NULL;
     else
     {
-        CPLPushErrorHandler( CPLQuietErrorHandler );
+        CPLPushErrorHandler( GDALAddoErrorHandler );
+        CPLSetCurrentErrorHandlerCatchDebug( FALSE );
         hDataset = GDALOpenEx( pszFilename, GDAL_OF_RASTER | GDAL_OF_UPDATE, NULL, papszOpenOptions, NULL );
         CPLPopErrorHandler();
+        if( hDataset != NULL )
+        {
+            for(size_t i=0;i<aoErrors.size();i++)
+            {
+                CPLError( aoErrors[i].m_eErr, aoErrors[i].m_errNum, "%s",
+                          aoErrors[i].m_osMsg.c_str() );
+            }
+        }
     }
 
     if( hDataset == NULL )
@@ -207,7 +239,7 @@ int main( int nArgc, char ** papszArgv )
 /*      Clean overviews.                                                */
 /* -------------------------------------------------------------------- */
     if ( bClean &&
-        GDALBuildOverviews( hDataset,pszResampling, 0, 0, 
+        GDALBuildOverviews( hDataset,pszResampling, 0, NULL,
                              0, NULL, pfnProgress, NULL ) != CE_None )
     {
         printf( "Cleaning overviews failed.\n" );
diff --git a/apps/gdalasyncread.cpp b/apps/gdalasyncread.cpp
index 4f91bd3..1f0069e 100644
--- a/apps/gdalasyncread.cpp
+++ b/apps/gdalasyncread.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalasyncread.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: gdalasyncread.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  GDAL Utilities
  * Purpose:  GDAL Async Image Reader, primarily for testing async api.
@@ -33,7 +33,7 @@
 #include "gdal_priv.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: gdalasyncread.cpp 28053 2014-12-04 09:31:07Z rouault $");
+CPL_CVSID("$Id: gdalasyncread.cpp 33808 2016-03-29 21:15:28Z goatbar $");
 
 /* ******************************************************************** */
 /*                               Usage()                                */
@@ -42,8 +42,6 @@ CPL_CVSID("$Id: gdalasyncread.cpp 28053 2014-12-04 09:31:07Z rouault $");
 static void Usage()
 
 {
-    int	iDr;
-        
     printf( "Usage: gdalasyncread [--help-general]\n"
             "       [-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/\n"
             "             CInt16/CInt32/CFloat32/CFloat64}]\n"
@@ -56,10 +54,10 @@ static void Usage()
 
     printf( "%s\n\n", GDALVersionInfo( "--version" ) );
     printf( "The following format drivers are configured and support output:\n" );
-    for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
+    for( int iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
     {
         GDALDriverH hDriver = GDALGetDriver(iDr);
-        
+
         if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) != NULL
             || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY,
                                     NULL ) != NULL )
@@ -137,9 +135,7 @@ int main( int argc, char ** argv )
 
         else if( EQUAL(argv[i],"-ot") && i < argc-1 )
         {
-            int	iType;
-            
-            for( iType = 1; iType < GDT_TypeCount; iType++ )
+            for( int iType = 1; iType < GDT_TypeCount; iType++ )
             {
                 if( GDALGetDataTypeName((GDALDataType)iType) != NULL
                     && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
@@ -170,7 +166,7 @@ int main( int argc, char ** argv )
             }
 
             nBandCount++;
-            panBandList = (int *) 
+            panBandList = (int *)
                 CPLRealloc(panBandList, sizeof(int) * nBandCount);
             panBandList[nBandCount-1] = atoi(argv[++i]);
 
@@ -180,23 +176,23 @@ int main( int argc, char ** argv )
         else if( EQUAL(argv[i],"-co") && i < argc-1 )
         {
             papszCreateOptions = CSLAddString( papszCreateOptions, argv[++i] );
-        }   
+        }
 
         else if( EQUAL(argv[i],"-ao") && i < argc-1 )
         {
             papszAsyncOptions = CSLAddString( papszAsyncOptions, argv[++i] );
-        }   
+        }
 
         else if( EQUAL(argv[i],"-to") && i < argc-1 )
         {
             dfTimeout = CPLAtof(argv[++i] );
-        }   
+        }
 
         else if( EQUAL(argv[i],"-outsize") && i < argc-2 )
         {
             pszOXSize = argv[++i];
             pszOYSize = argv[++i];
-        }   
+        }
 
         else if( EQUAL(argv[i],"-srcwin") && i < argc-4 )
         {
@@ -204,15 +200,15 @@ int main( int argc, char ** argv )
             anSrcWin[1] = atoi(argv[++i]);
             anSrcWin[2] = atoi(argv[++i]);
             anSrcWin[3] = atoi(argv[++i]);
-        }   
+        }
 
         else if( EQUAL(argv[i],"-multi") )
         {
             bMulti = TRUE;
-        }   
+        }
         else if( argv[i][0] == '-' )
         {
-            printf( "Option %s incomplete, or not recognised.\n\n", 
+            printf( "Option %s incomplete, or not recognised.\n\n",
                     argv[i] );
             Usage();
             GDALDestroyDriverManager();
@@ -258,7 +254,7 @@ int main( int argc, char ** argv )
 
     hSrcDS = GDALOpenShared( pszSource, GA_ReadOnly );
     poSrcDS = (GDALDataset *) hSrcDS;
-    
+
     if( hSrcDS == NULL )
     {
         fprintf( stderr,
@@ -293,9 +289,9 @@ int main( int argc, char ** argv )
     }
     else
     {
-        nOXSize = (int) ((pszOXSize[strlen(pszOXSize)-1]=='%' 
+        nOXSize = (int) ((pszOXSize[strlen(pszOXSize)-1]=='%'
                           ? CPLAtof(pszOXSize)/100*anSrcWin[2] : atoi(pszOXSize)));
-        nOYSize = (int) ((pszOYSize[strlen(pszOYSize)-1]=='%' 
+        nOYSize = (int) ((pszOYSize[strlen(pszOYSize)-1]=='%'
                           ? CPLAtof(pszOYSize)/100*anSrcWin[3] : atoi(pszOYSize)));
     }
 
@@ -322,7 +318,7 @@ int main( int argc, char ** argv )
         {
             if( panBandList[i] < 1 || panBandList[i] > GDALGetRasterCount(hSrcDS) )
             {
-                fprintf( stderr, 
+                fprintf( stderr,
                          "Band %d requested, but only bands 1 to %d available.\n",
                          panBandList[i], GDALGetRasterCount(hSrcDS) );
                 GDALDestroyDriverManager();
@@ -337,19 +333,19 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
 /*      Verify source window.                                           */
 /* -------------------------------------------------------------------- */
-    if( anSrcWin[0] < 0 || anSrcWin[1] < 0 
+    if( anSrcWin[0] < 0 || anSrcWin[1] < 0
         || anSrcWin[2] <= 0 || anSrcWin[3] <= 0
-        || anSrcWin[0] + anSrcWin[2] > GDALGetRasterXSize(hSrcDS) 
+        || anSrcWin[0] + anSrcWin[2] > GDALGetRasterXSize(hSrcDS)
         || anSrcWin[1] + anSrcWin[3] > GDALGetRasterYSize(hSrcDS) )
     {
-        fprintf( stderr, 
+        fprintf( stderr,
                  "-srcwin %d %d %d %d falls outside raster size of %dx%d\n"
                  "or is otherwise illegal.\n",
                  anSrcWin[0],
                  anSrcWin[1],
                  anSrcWin[2],
                  anSrcWin[3],
-                 GDALGetRasterXSize(hSrcDS), 
+                 GDALGetRasterXSize(hSrcDS),
                  GDALGetRasterYSize(hSrcDS) );
         exit( 1 );
     }
@@ -372,10 +368,8 @@ int main( int argc, char ** argv )
 
     if( hDriver == NULL )
     {
-        int	iDr;
-        
         printf( "The following format drivers are configured and support output:\n" );
-        for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
+        for( int iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
         {
             GDALDriverH hDriver = GDALGetDriver(iDr);
 
@@ -388,7 +382,7 @@ int main( int argc, char ** argv )
         }
         printf( "\n" );
         Usage();
-        
+
         GDALClose( hSrcDS );
         CPLFree( panBandList );
         GDALDestroyDriverManager();
@@ -407,7 +401,8 @@ int main( int argc, char ** argv )
 /*      Allocate one big buffer for the whole imagery area to           */
 /*      transfer.                                                       */
 /* -------------------------------------------------------------------- */
-    int nBytesPerPixel = nBandCount * (GDALGetDataTypeSize(eOutputType) / 8);
+    const int nBytesPerPixel =
+        nBandCount * GDALGetDataTypeSizeBytes(eOutputType);
     void *pImage = VSIMalloc3( nOXSize, nOYSize, nBytesPerPixel );
 
     if( pImage == NULL )
@@ -420,15 +415,15 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
 /*      Establish view window                                           */
 /* -------------------------------------------------------------------- */
-    GDALAsyncReader *poAsyncReq;
     int nPixelSpace = nBytesPerPixel;
     int nLineSpace = nBytesPerPixel * nOXSize;
     int nBandSpace = nBytesPerPixel / nBandCount;
 
-    poAsyncReq = poSrcDS->BeginAsyncReader( 
+    GDALAsyncReader *poAsyncReq
+        = poSrcDS->BeginAsyncReader(
         anSrcWin[0], anSrcWin[1], anSrcWin[2], anSrcWin[3],
-        pImage, nOXSize, nOYSize, eOutputType, 
-        nBandCount, panBandList, 
+        pImage, nOXSize, nOYSize, eOutputType,
+        nBandCount, panBandList,
         nPixelSpace, nLineSpace, nBandSpace, papszAsyncOptions );
 
     if( poAsyncReq == NULL )
@@ -444,7 +439,7 @@ int main( int argc, char ** argv )
     hDstDS = NULL;
 
     do
-    {  
+    {
 /* ==================================================================== */
 /*      Create the output file, and initialize if needed.               */
 /* ==================================================================== */
@@ -455,38 +450,38 @@ int main( int argc, char ** argv )
             if( bMulti )
                 osOutFilename.Printf( "%s_%d", pszDest, iMultiCounter++ );
 
-            hDstDS = GDALCreate( hDriver, osOutFilename, nOXSize, nOYSize, 
-                                 nBandCount, eOutputType, 
+            hDstDS = GDALCreate( hDriver, osOutFilename, nOXSize, nOYSize,
+                                 nBandCount, eOutputType,
                                  papszCreateOptions );
             if (hDstDS == NULL)
             {
                 exit(1);
             }
-            
+
             poDstDS = (GDALDataset *) hDstDS;
-                                      
+
 /* -------------------------------------------------------------------- */
 /*      Copy georeferencing.                                            */
 /* -------------------------------------------------------------------- */
             double adfGeoTransform[6];
-    
+
             if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None )
             {
                 adfGeoTransform[0] += anSrcWin[0] * adfGeoTransform[1]
                     + anSrcWin[1] * adfGeoTransform[2];
                 adfGeoTransform[3] += anSrcWin[0] * adfGeoTransform[4]
                     + anSrcWin[1] * adfGeoTransform[5];
-                
+
                 adfGeoTransform[1] *= anSrcWin[2] / (double) nOXSize;
                 adfGeoTransform[2] *= anSrcWin[3] / (double) nOYSize;
                 adfGeoTransform[4] *= anSrcWin[2] / (double) nOXSize;
                 adfGeoTransform[5] *= anSrcWin[3] / (double) nOYSize;
-                
+
                 poDstDS->SetGeoTransform( adfGeoTransform );
             }
 
             poDstDS->SetProjection( poSrcDS->GetProjectionRef() );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Transfer generally applicable metadata.                         */
 /* -------------------------------------------------------------------- */
@@ -501,7 +496,7 @@ int main( int argc, char ** argv )
         int nUpXOff, nUpYOff, nUpXSize, nUpYSize;
 
         eAStatus = poAsyncReq->GetNextUpdatedRegion( dfTimeout,
-                                                     &nUpXOff, &nUpYOff, 
+                                                     &nUpXOff, &nUpYOff,
                                                      &nUpXSize, &nUpYSize );
 
         if( eAStatus != GARIO_UPDATE && eAStatus != GARIO_COMPLETE )
@@ -509,18 +504,18 @@ int main( int argc, char ** argv )
 
         if( !bQuiet )
         {
-            printf( "Got %dx%d @ (%d,%d)\n", 
+            printf( "Got %dx%d @ (%d,%d)\n",
                     nUpXSize, nUpYSize, nUpXOff, nUpYOff );
         }
 
         poAsyncReq->LockBuffer();
-        eErr = 
+        eErr =
             poDstDS->RasterIO( GF_Write, nUpXOff, nUpYOff, nUpXSize, nUpYSize,
-                               ((GByte *) pImage) 
-                               + nUpXOff * nPixelSpace 
-                               + nUpYOff * nLineSpace, 
+                               ((GByte *) pImage)
+                               + nUpXOff * nPixelSpace
+                               + nUpYOff * nLineSpace,
                                nUpXSize, nUpYSize, eOutputType,
-                               nBandCount, NULL, 
+                               nBandCount, NULL,
                                nPixelSpace, nLineSpace, nBandSpace, NULL );
         poAsyncReq->UnlockBuffer();
 
@@ -538,7 +533,7 @@ int main( int argc, char ** argv )
 
     } while( eAStatus != GARIO_ERROR && eAStatus != GARIO_COMPLETE
              && eErr == CE_None );
-                                             
+
     poSrcDS->EndAsyncReader( poAsyncReq );
 
 /* -------------------------------------------------------------------- */
@@ -552,7 +547,7 @@ int main( int argc, char ** argv )
     GDALClose( hSrcDS );
 
     CPLFree( panBandList );
-    
+
     CSLDestroy( argv );
     CSLDestroy( papszCreateOptions );
     CSLDestroy( papszAsyncOptions );
diff --git a/apps/gdalbuildvrt.cpp b/apps/gdalbuildvrt.cpp
deleted file mode 100644
index f29ae92..0000000
--- a/apps/gdalbuildvrt.cpp
+++ /dev/null
@@ -1,1609 +0,0 @@
-/******************************************************************************
- * $Id: gdalbuildvrt.cpp 30126 2015-09-05 09:15:38Z rouault $
- *
- * Project:  GDAL Utilities
- * Purpose:  Commandline application to build VRT datasets from raster products or content of SHP tile index
- * Author:   Even Rouault, even.rouault at mines-paris.org
- *
- ******************************************************************************
- * Copyright (c) 2007-2014, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "gdal_proxy.h"
-#include "cpl_string.h"
-#include "gdal_vrt.h"
-#include "vrtdataset.h"
-
-#ifdef OGR_ENABLED
-#include "ogr_api.h"
-#endif
-#include "ogr_srs_api.h"
-
-CPL_CVSID("$Id: gdalbuildvrt.cpp 30126 2015-09-05 09:15:38Z rouault $");
-
-#define GEOTRSFRM_TOPLEFT_X            0
-#define GEOTRSFRM_WE_RES               1
-#define GEOTRSFRM_ROTATION_PARAM1      2
-#define GEOTRSFRM_TOPLEFT_Y            3
-#define GEOTRSFRM_ROTATION_PARAM2      4
-#define GEOTRSFRM_NS_RES               5
-
-typedef enum
-{
-    LOWEST_RESOLUTION,
-    HIGHEST_RESOLUTION,
-    AVERAGE_RESOLUTION,
-    USER_RESOLUTION
-} ResolutionStrategy;
-
-typedef struct
-{
-    int    isFileOK;
-    int    nRasterXSize;
-    int    nRasterYSize;
-    double adfGeoTransform[6];
-    int    nBlockXSize;
-    int    nBlockYSize;
-    GDALDataType firstBandType;
-    int*         panHasNoData;
-    double*      padfNoDataValues;
-    int    bHasDatasetMask;
-    int    nMaskBlockXSize;
-    int    nMaskBlockYSize;
-} DatasetProperty;
-
-typedef struct
-{
-    GDALColorInterp        colorInterpretation;
-    GDALDataType           dataType;
-    GDALColorTableH        colorTable;
-    int                    bHasNoData;
-    double                 noDataValue;
-} BandProperty;
-
-/************************************************************************/
-/*                            ArgIsNumeric()                            */
-/************************************************************************/
-
-static int ArgIsNumeric( const char *pszArg )
-
-{
-    return CPLGetValueType(pszArg) != CPL_VALUE_STRING;
-}
-
-/************************************************************************/
-/*                               Usage()                                */
-/************************************************************************/
-
-static void Usage(const char* pszErrorMsg = NULL)
-
-{
-    fprintf(stdout, "%s", 
-            "Usage: gdalbuildvrt [-tileindex field_name]\n"
-            "                    [-resolution {highest|lowest|average|user}]\n"
-            "                    [-te xmin ymin xmax ymax] [-tr xres yres] [-tap]\n"
-            "                    [-separate] [-b band] [-sd subdataset]\n"
-            "                    [-allow_projection_difference] [-q]\n"
-            "                    [-addalpha] [-hidenodata]\n"
-            "                    [-srcnodata \"value [value...]\"] [-vrtnodata \"value [value...]\"] \n"
-            "                    [-a_srs srs_def]\n"
-            "                    [-r {nearest,bilinear,cubic,cubicspline,lanczos,average,mode}]\n"
-            "                    [-input_file_list my_liste.txt] [-overwrite] output.vrt [gdalfile]*\n"
-            "\n"
-            "eg.\n"
-            "  % gdalbuildvrt doq_index.vrt doq/*.tif\n"
-            "  % gdalbuildvrt -input_file_list my_liste.txt doq_index.vrt\n"
-            "\n"
-            "NOTES:\n"
-            "  o With -separate, each files goes into a separate band in the VRT band.\n"
-            "    Otherwise, the files are considered as tiles of a larger mosaic.\n"
-            "  o -b option selects a band to add into vrt.  Multiple bands can be listed.\n"
-            "    By default all bands are queried.\n"
-            "  o The default tile index field is 'location' unless otherwise specified by\n"
-            "    -tileindex.\n"
-            "  o In case the resolution of all input files is not the same, the -resolution\n"
-            "    flag enable the user to control the way the output resolution is computed.\n"
-            "    Average is the default.\n"
-            "  o Input files may be any valid GDAL dataset or a GDAL raster tile index.\n"
-            "  o For a GDAL raster tile index, all entries will be added to the VRT.\n"
-            "  o If one GDAL dataset is made of several subdatasets and has 0 raster bands,\n"
-            "    its datasets will be added to the VRT rather than the dataset itself.\n"
-            "    Single subdataset could be selected by its number using the -sd option.\n"
-            "  o By default, only datasets of same projection and band characteristics\n"
-            "    may be added to the VRT.\n"
-            );
-
-    if( pszErrorMsg != NULL )
-        fprintf(stderr, "\nFAILURE: %s\n", pszErrorMsg);
-
-    exit( 1 );
-}
-
-
-/************************************************************************/
-/*                         GetSrcDstWin()                               */
-/************************************************************************/
-
-int  GetSrcDstWin(DatasetProperty* psDP,
-                  double we_res, double ns_res,
-                  double minX, double minY, double maxX, double maxY,
-                  int* pnSrcXOff, int* pnSrcYOff, int* pnSrcXSize, int* pnSrcYSize,
-                  int* pnDstXOff, int* pnDstYOff, int* pnDstXSize, int* pnDstYSize)
-{
-    /* Check that the destination bounding box intersects the source bounding box */
-    if ( psDP->adfGeoTransform[GEOTRSFRM_TOPLEFT_X] +
-         psDP->nRasterXSize *
-         psDP->adfGeoTransform[GEOTRSFRM_WE_RES] < minX )
-         return FALSE;
-    if ( psDP->adfGeoTransform[GEOTRSFRM_TOPLEFT_X] > maxX )
-         return FALSE;
-    if ( psDP->adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] +
-         psDP->nRasterYSize *
-         psDP->adfGeoTransform[GEOTRSFRM_NS_RES] > maxY )
-         return FALSE;
-    if ( psDP->adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] < minY )
-         return FALSE;
-
-    *pnSrcXSize = psDP->nRasterXSize;
-    *pnSrcYSize = psDP->nRasterYSize;
-    if ( psDP->adfGeoTransform[GEOTRSFRM_TOPLEFT_X] < minX )
-    {
-        *pnSrcXOff = (int)((minX - psDP->adfGeoTransform[GEOTRSFRM_TOPLEFT_X]) /
-            psDP->adfGeoTransform[GEOTRSFRM_WE_RES] + 0.5);
-        *pnDstXOff = 0;
-    }
-    else
-    {
-        *pnSrcXOff = 0;
-        *pnDstXOff = (int)
-            (0.5 + (psDP->adfGeoTransform[GEOTRSFRM_TOPLEFT_X] - minX) / we_res);
-    }
-    if ( maxY < psDP->adfGeoTransform[GEOTRSFRM_TOPLEFT_Y])
-    {
-        *pnSrcYOff = (int)((psDP->adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] - maxY) /
-            -psDP->adfGeoTransform[GEOTRSFRM_NS_RES] + 0.5);
-        *pnDstYOff = 0;
-    }
-    else
-    {
-        *pnSrcYOff = 0;
-        *pnDstYOff = (int)
-            (0.5 + (maxY - psDP->adfGeoTransform[GEOTRSFRM_TOPLEFT_Y]) / -ns_res);
-    }
-    *pnDstXSize = (int)
-        (0.5 + psDP->nRasterXSize *
-         psDP->adfGeoTransform[GEOTRSFRM_WE_RES] / we_res);
-    *pnDstYSize = (int)
-        (0.5 + psDP->nRasterYSize *
-         psDP->adfGeoTransform[GEOTRSFRM_NS_RES] / ns_res);
-         
-    return TRUE;
-}
-
-/************************************************************************/
-/*                            VRTBuilder                                */
-/************************************************************************/
-
-class VRTBuilder
-{
-    /* Input parameters */
-    char               *pszOutputFilename;
-    int                 nInputFiles;
-    char              **ppszInputFilenames;
-    int                 nBands;
-    int                *panBandList;   
-    int                 nMaxBandNo;
-    ResolutionStrategy  resolutionStrategy;
-    double              we_res;
-    double              ns_res;
-    int                 bTargetAlignedPixels;
-    double              minX;
-    double              minY;
-    double              maxX;
-    double              maxY;
-    int                 bSeparate;
-    int                 bAllowProjectionDifference;
-    int                 bAddAlpha;
-    int                 bHideNoData;
-    int                 nSubdataset;
-    char               *pszSrcNoData;
-    char               *pszVRTNoData;
-    char               *pszOutputSRS;
-    char               *pszResampling;
-
-    /* Internal variables */
-    char               *pszProjectionRef;
-    BandProperty       *pasBandProperties;
-    int                 bFirst;
-    int                 bHasGeoTransform;
-    int                 nRasterXSize;
-    int                 nRasterYSize;
-    DatasetProperty    *pasDatasetProperties;
-    int                 bUserExtent;
-    int                 bAllowSrcNoData;
-    double             *padfSrcNoData;
-    int                 nSrcNoDataCount;
-    int                 bAllowVRTNoData;
-    double             *padfVRTNoData;
-    int                 nVRTNoDataCount;
-    int                 bHasRunBuild;
-    int                 bHasDatasetMask;
-
-    int         AnalyseRaster(GDALDatasetH hDS, const char* dsFileName,
-                              DatasetProperty* psDatasetProperties);
-
-    void        CreateVRTSeparate(VRTDatasetH hVRTDS);
-    void        CreateVRTNonSeparate(VRTDatasetH hVRTDS);
-
-    public:
-                VRTBuilder(const char* pszOutputFilename,
-                           int nInputFiles, const char* const * ppszInputFilenames,
-                           const int *panBandListIn, int nBandCount, int nMaxBandNo,
-                           ResolutionStrategy resolutionStrategy,
-                           double we_res, double ns_res,
-                           int bTargetAlignedPixels,
-                           double minX, double minY, double maxX, double maxY,
-                           int bSeparate, int bAllowProjectionDifference,
-                           int bAddAlpha, int bHideNoData, int nSubdataset,
-                           const char* pszSrcNoData, const char* pszVRTNoData,
-                           const char* pszOutputSRS,
-                           const char* pszResampling);
-
-               ~VRTBuilder();
-
-        int     Build(GDALProgressFunc pfnProgress, void * pProgressData);
-};
-
-
-/************************************************************************/
-/*                          VRTBuilder()                                */
-/************************************************************************/
-
-VRTBuilder::VRTBuilder(const char* pszOutputFilename,
-                       int nInputFiles, const char* const * ppszInputFilenames,
-                       const int *panBandListIn, int nBandCount, int nMaxBandNo,
-                       ResolutionStrategy resolutionStrategy,
-                       double we_res, double ns_res,
-                       int bTargetAlignedPixels,
-                       double minX, double minY, double maxX, double maxY,
-                       int bSeparate, int bAllowProjectionDifference,
-                       int bAddAlpha, int bHideNoData, int nSubdataset,
-                       const char* pszSrcNoData, const char* pszVRTNoData,
-                       const char* pszOutputSRS,
-                       const char* pszResampling)
-{
-    this->pszOutputFilename = CPLStrdup(pszOutputFilename);
-    this->nInputFiles = nInputFiles;
-
-    this->ppszInputFilenames = (char**) CPLMalloc(nInputFiles * sizeof(char*));
-    for(int i=0;i<nInputFiles;i++)
-    {
-        this->ppszInputFilenames[i] = CPLStrdup(ppszInputFilenames[i]);
-    }
-
-    this->nBands = nBandCount;
-    panBandList = NULL;
-    if( nBandCount )
-    {
-        panBandList = (int*) CPLMalloc(nBands * sizeof(int));
-        memcpy(panBandList, panBandListIn, nBands * sizeof(int));
-    }
-    this->nMaxBandNo = nMaxBandNo;    
-
-    this->resolutionStrategy = resolutionStrategy;
-    this->we_res = we_res;
-    this->ns_res = ns_res;
-    this->bTargetAlignedPixels = bTargetAlignedPixels;
-    this->minX = minX;
-    this->minY = minY;
-    this->maxX = maxX;
-    this->maxY = maxY;
-    this->bSeparate = bSeparate;
-    this->bAllowProjectionDifference = bAllowProjectionDifference;
-    this->bAddAlpha = bAddAlpha;
-    this->bHideNoData = bHideNoData;
-    this->nSubdataset = nSubdataset;
-    this->pszSrcNoData = (pszSrcNoData) ? CPLStrdup(pszSrcNoData) : NULL;
-    this->pszVRTNoData = (pszVRTNoData) ? CPLStrdup(pszVRTNoData) : NULL;
-    this->pszOutputSRS = (pszOutputSRS) ? CPLStrdup(pszOutputSRS) : NULL;
-    this->pszResampling = (pszResampling) ? CPLStrdup(pszResampling) : NULL;
-
-    bUserExtent = FALSE;
-    pszProjectionRef = NULL;
-    pasBandProperties = NULL;
-    bFirst = TRUE;
-    bHasGeoTransform = FALSE;
-    nRasterXSize = 0;
-    nRasterYSize = 0;
-    pasDatasetProperties = NULL;
-    bAllowSrcNoData = TRUE;
-    padfSrcNoData = NULL;
-    nSrcNoDataCount = 0;
-    bAllowVRTNoData = TRUE;
-    padfVRTNoData = NULL;
-    nVRTNoDataCount = 0;
-    bHasRunBuild = FALSE;
-    bHasDatasetMask = FALSE;
-}
-
-/************************************************************************/
-/*                         ~VRTBuilder()                                */
-/************************************************************************/
-
-VRTBuilder::~VRTBuilder()
-{
-    CPLFree(pszOutputFilename);
-    CPLFree(pszSrcNoData);
-    CPLFree(pszVRTNoData);
-    CPLFree(panBandList);
-
-    int i;
-    for(i=0;i<nInputFiles;i++)
-    {
-        CPLFree(ppszInputFilenames[i]);
-    }
-    CPLFree(ppszInputFilenames);
-
-    if (pasDatasetProperties != NULL)
-    {
-        for(i=0;i<nInputFiles;i++)
-        {
-            CPLFree(pasDatasetProperties[i].padfNoDataValues);
-            CPLFree(pasDatasetProperties[i].panHasNoData);
-        }
-    }
-    CPLFree(pasDatasetProperties);
-
-    if (!bSeparate && pasBandProperties != NULL)
-    {
-        int j;
-        for(j=0;j<nBands;j++)
-        {
-            GDALDestroyColorTable(pasBandProperties[j].colorTable);
-        }
-    }
-    CPLFree(pasBandProperties);
-
-    CPLFree(pszProjectionRef);
-    CPLFree(padfSrcNoData);
-    CPLFree(padfVRTNoData);
-    CPLFree(pszOutputSRS);
-    CPLFree(pszResampling);
-}
-
-/************************************************************************/
-/*                           ProjAreEqual()                             */
-/************************************************************************/
-
-static int ProjAreEqual(const char* pszWKT1, const char* pszWKT2)
-{
-    int bRet;
-    OGRSpatialReferenceH hSRS1, hSRS2;
-
-    if (EQUAL(pszWKT1, pszWKT2))
-        return TRUE;
-
-    hSRS1 = OSRNewSpatialReference(pszWKT1);
-    hSRS2 = OSRNewSpatialReference(pszWKT2);
-    bRet = hSRS1 != NULL && hSRS2 != NULL && OSRIsSame(hSRS1,hSRS2);
-    if (hSRS1)
-        OSRDestroySpatialReference(hSRS1);
-    if (hSRS2)
-        OSRDestroySpatialReference(hSRS2);
-    return bRet;
-}
-
-/************************************************************************/
-/*                           AnalyseRaster()                            */
-/************************************************************************/
-
-int VRTBuilder::AnalyseRaster( GDALDatasetH hDS, const char* dsFileName,
-                                  DatasetProperty* psDatasetProperties)
-{
-    char** papszMetadata = GDALGetMetadata( hDS, "SUBDATASETS" );
-    if( CSLCount(papszMetadata) > 0 && GDALGetRasterCount(hDS) == 0 )
-    {
-        pasDatasetProperties =
-            (DatasetProperty*) CPLRealloc(pasDatasetProperties,
-                            (nInputFiles+CSLCount(papszMetadata))*sizeof(DatasetProperty));
-
-        ppszInputFilenames = (char**)CPLRealloc(ppszInputFilenames,
-                                sizeof(char*) * (nInputFiles+CSLCount(papszMetadata)));
-        if ( nSubdataset < 0 )
-        {
-            int count = 1;
-            char subdatasetNameKey[256];
-            sprintf(subdatasetNameKey, "SUBDATASET_%d_NAME", count);
-            while(*papszMetadata != NULL)
-            {
-                if (EQUALN(*papszMetadata, subdatasetNameKey, strlen(subdatasetNameKey)))
-                {
-                    memset(&pasDatasetProperties[nInputFiles], 0, sizeof(DatasetProperty));
-                    ppszInputFilenames[nInputFiles++] =
-                            CPLStrdup(*papszMetadata+strlen(subdatasetNameKey)+1);
-                    count++;
-                    sprintf(subdatasetNameKey, "SUBDATASET_%d_NAME", count);
-                }
-                papszMetadata++;
-            }
-        }
-        else
-        {
-            char        subdatasetNameKey[256];
-            const char  *pszSubdatasetName;
-
-            snprintf( subdatasetNameKey, sizeof(subdatasetNameKey),
-                      "SUBDATASET_%d_NAME", nSubdataset );
-            pszSubdatasetName = CSLFetchNameValue( papszMetadata, subdatasetNameKey );
-            if ( pszSubdatasetName )
-            {
-                memset( &pasDatasetProperties[nInputFiles], 0, sizeof(DatasetProperty) );
-                ppszInputFilenames[nInputFiles++] = CPLStrdup( pszSubdatasetName );
-            }
-        }
-        return FALSE;
-    }
-
-    const char* proj = GDALGetProjectionRef(hDS);
-    double* padfGeoTransform = psDatasetProperties->adfGeoTransform;
-    int bGotGeoTransform = GDALGetGeoTransform(hDS, padfGeoTransform) == CE_None;
-    if (bSeparate)
-    {
-        if (bFirst)
-        {
-            bHasGeoTransform = bGotGeoTransform;
-            if (!bHasGeoTransform)
-            {
-                if (bUserExtent)
-                {
-                    CPLError(CE_Warning, CPLE_NotSupported,
-                        "User extent ignored by gdalbuildvrt -separate with ungeoreferenced images.");
-                }
-                if (resolutionStrategy == USER_RESOLUTION)
-                {
-                    CPLError(CE_Warning, CPLE_NotSupported,
-                        "User resolution ignored by gdalbuildvrt -separate with ungeoreferenced images.");
-                }
-            }
-        }
-        else if (bHasGeoTransform != bGotGeoTransform)
-        {
-            CPLError(CE_Warning, CPLE_NotSupported,
-                    "gdalbuildvrt -separate cannot stack ungeoreferenced and georeferenced images. Skipping %s",
-                    dsFileName);
-            return FALSE;
-        }
-        else if (!bHasGeoTransform &&
-                    (nRasterXSize != GDALGetRasterXSize(hDS) ||
-                    nRasterYSize != GDALGetRasterYSize(hDS)))
-        {
-            CPLError(CE_Warning, CPLE_NotSupported,
-                    "gdalbuildvrt -separate cannot stack ungeoreferenced images that have not the same dimensions. Skipping %s",
-                    dsFileName);
-            return FALSE;
-        }
-    }
-    else
-    {
-        if (!bGotGeoTransform)
-        {
-            CPLError(CE_Warning, CPLE_NotSupported,
-                    "gdalbuildvrt does not support ungeoreferenced image. Skipping %s",
-                    dsFileName);
-            return FALSE;
-        }
-        bHasGeoTransform = TRUE;
-    }
-
-    if (bGotGeoTransform)
-    {
-        if (padfGeoTransform[GEOTRSFRM_ROTATION_PARAM1] != 0 ||
-            padfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] != 0)
-        {
-            CPLError(CE_Warning, CPLE_NotSupported,
-                    "gdalbuildvrt does not support rotated geo transforms. Skipping %s",
-                    dsFileName);
-            return FALSE;
-        }
-        if (padfGeoTransform[GEOTRSFRM_NS_RES] >= 0)
-        {
-            CPLError(CE_Warning, CPLE_NotSupported,
-                    "gdalbuildvrt does not support positive NS resolution. Skipping %s",
-                    dsFileName);
-            return FALSE;
-        }
-    }
-
-    psDatasetProperties->nRasterXSize = GDALGetRasterXSize(hDS);
-    psDatasetProperties->nRasterYSize = GDALGetRasterYSize(hDS);
-    if (bFirst && bSeparate && !bGotGeoTransform)
-    {
-        nRasterXSize = GDALGetRasterXSize(hDS);
-        nRasterYSize = GDALGetRasterYSize(hDS);
-    }
-
-    double ds_minX = padfGeoTransform[GEOTRSFRM_TOPLEFT_X];
-    double ds_maxY = padfGeoTransform[GEOTRSFRM_TOPLEFT_Y];
-    double ds_maxX = ds_minX +
-                GDALGetRasterXSize(hDS) *
-                padfGeoTransform[GEOTRSFRM_WE_RES];
-    double ds_minY = ds_maxY +
-                GDALGetRasterYSize(hDS) *
-                padfGeoTransform[GEOTRSFRM_NS_RES];
-
-    GDALGetBlockSize(GDALGetRasterBand( hDS, 1 ),
-                        &psDatasetProperties->nBlockXSize,
-                        &psDatasetProperties->nBlockYSize);
-
-    int _nBands = GDALGetRasterCount(hDS);
-
-    //if provided band list 
-    if(nBands != 0 && _nBands != 0 && nMaxBandNo != 0 && _nBands >= nMaxBandNo)
-    {
-        if(_nBands < nMaxBandNo)
-        {
-            CPLError(CE_Warning, CPLE_AppDefined,
-                        "Skipping %s as it has no sush bands", dsFileName);
-            return FALSE;
-        }
-        else
-        {
-            _nBands = nMaxBandNo;
-        }
-    }
-
-    if (_nBands == 0)
-    {
-        CPLError(CE_Warning, CPLE_AppDefined,
-                    "Skipping %s as it has no bands", dsFileName);
-        return FALSE;
-    }
-    else if (_nBands > 1 && bSeparate)
-    {
-        CPLError(CE_Warning, CPLE_AppDefined, "%s has %d bands. Only the first one will "
-                    "be taken into account in the -separate case",
-                    dsFileName, _nBands);
-        _nBands = 1;
-    }
-
-    /* For the -separate case */
-    psDatasetProperties->firstBandType = GDALGetRasterDataType(GDALGetRasterBand(hDS, 1));
-
-    psDatasetProperties->padfNoDataValues = (double*)CPLCalloc(sizeof(double), _nBands);
-    psDatasetProperties->panHasNoData = (int*)CPLCalloc(sizeof(int), _nBands);
-
-    psDatasetProperties->bHasDatasetMask = GDALGetMaskFlags(GDALGetRasterBand(hDS, 1)) == GMF_PER_DATASET;
-    if (psDatasetProperties->bHasDatasetMask)
-        bHasDatasetMask = TRUE;
-    GDALGetBlockSize(GDALGetMaskBand(GDALGetRasterBand( hDS, 1 )),
-                        &psDatasetProperties->nMaskBlockXSize,
-                        &psDatasetProperties->nMaskBlockYSize);
-
-    int j;
-    for(j=0;j<_nBands;j++)
-    {
-        if (nSrcNoDataCount > 0)
-        {
-            psDatasetProperties->panHasNoData[j] = TRUE;
-            if (j < nSrcNoDataCount)
-                psDatasetProperties->padfNoDataValues[j] = padfSrcNoData[j];
-            else
-                psDatasetProperties->padfNoDataValues[j] = padfSrcNoData[nSrcNoDataCount - 1];
-        }
-        else
-        {
-            psDatasetProperties->padfNoDataValues[j]  =
-                GDALGetRasterNoDataValue(GDALGetRasterBand(hDS, j+1),
-                                        &psDatasetProperties->panHasNoData[j]);
-        }
-    }
-
-    if (bFirst)
-    {
-        if (proj)
-            pszProjectionRef = CPLStrdup(proj);
-        if (!bUserExtent)
-        {
-            minX = ds_minX;
-            minY = ds_minY;
-            maxX = ds_maxX;
-            maxY = ds_maxY;
-        }
-
-        //if not provided an explicit band list, take the one of the first dataset
-        if(nBands == 0)
-        {
-            nBands = _nBands;
-            CPLFree(panBandList);
-            panBandList = (int*) CPLMalloc(nBands * sizeof(int));
-            for(j=0;j<nBands;j++)
-            {
-                panBandList[j] = j + 1;
-                if(nMaxBandNo < j + 1)
-                    nMaxBandNo = j + 1;
-            }
-        }
-        if (!bSeparate)
-        {
-            pasBandProperties = (BandProperty*)CPLMalloc(nMaxBandNo*sizeof(BandProperty));
-            for(j=0;j<nMaxBandNo;j++)
-            {
-                GDALRasterBandH hRasterBand = GDALGetRasterBand( hDS, j+1 );
-                pasBandProperties[j].colorInterpretation =
-                        GDALGetRasterColorInterpretation(hRasterBand);
-                pasBandProperties[j].dataType = GDALGetRasterDataType(hRasterBand);
-                if (pasBandProperties[j].colorInterpretation == GCI_PaletteIndex)
-                {
-                    pasBandProperties[j].colorTable =
-                            GDALGetRasterColorTable( hRasterBand );
-                    if (pasBandProperties[j].colorTable)
-                    {
-                        pasBandProperties[j].colorTable =
-                                GDALCloneColorTable(pasBandProperties[j].colorTable);
-                    }
-                }
-                else
-                    pasBandProperties[j].colorTable = 0;
-
-                if (nVRTNoDataCount > 0)
-                {
-                    pasBandProperties[j].bHasNoData = TRUE;
-                    if (j < nVRTNoDataCount)
-                        pasBandProperties[j].noDataValue = padfVRTNoData[j];
-                    else
-                        pasBandProperties[j].noDataValue = padfVRTNoData[nVRTNoDataCount - 1];
-                }
-                else
-                {
-                    pasBandProperties[j].noDataValue =
-                            GDALGetRasterNoDataValue(hRasterBand, &pasBandProperties[j].bHasNoData);
-                }
-            }
-        }
-    }
-    else
-    {
-        if ((proj != NULL && pszProjectionRef == NULL) ||
-            (proj == NULL && pszProjectionRef != NULL) ||
-            (proj != NULL && pszProjectionRef != NULL && ProjAreEqual(proj, pszProjectionRef) == FALSE))
-        {
-            if (!bAllowProjectionDifference)
-            {
-                CPLError(CE_Warning, CPLE_NotSupported,
-                            "gdalbuildvrt does not support heterogenous projection. Skipping %s",
-                            dsFileName);
-                return FALSE;
-            }
-        }
-        if (!bSeparate)
-        {
-            if (nMaxBandNo > _nBands)
-            {
-                CPLError(CE_Warning, CPLE_NotSupported,
-                            "gdalbuildvrt does not support heterogenous band numbers. Skipping %s",
-                        dsFileName);
-                return FALSE;
-            }
-            for(j=0;j<nMaxBandNo;j++)
-            {
-                GDALRasterBandH hRasterBand = GDALGetRasterBand( hDS, j+1 );
-                if (pasBandProperties[j].colorInterpretation != GDALGetRasterColorInterpretation(hRasterBand) ||
-                    pasBandProperties[j].dataType != GDALGetRasterDataType(hRasterBand))
-                {
-                    CPLError(CE_Warning, CPLE_NotSupported,
-                                "gdalbuildvrt does not support heterogenous band characteristics. Skipping %s",
-                                dsFileName);
-                    return FALSE;
-                }
-                if (pasBandProperties[j].colorTable)
-                {
-                    GDALColorTableH colorTable = GDALGetRasterColorTable( hRasterBand );
-                    int nRefColorEntryCount = GDALGetColorEntryCount(pasBandProperties[j].colorTable);
-                    int i;
-                    if (colorTable == NULL ||
-                        GDALGetColorEntryCount(colorTable) != nRefColorEntryCount)
-                    {
-                        CPLError(CE_Warning, CPLE_NotSupported,
-                                    "gdalbuildvrt does not support rasters with different color tables (different number of color table entries). Skipping %s",
-                                dsFileName);
-                        return FALSE;
-                    }
-
-                    /* Check that the palette are the same too */
-                    /* We just warn and still process the file. It is not a technical no-go, but the user */
-                    /* should check that the end result is OK for him. */
-                    for(i=0;i<nRefColorEntryCount;i++)
-                    {
-                        const GDALColorEntry* psEntry = GDALGetColorEntry(colorTable, i);
-                        const GDALColorEntry* psEntryRef = GDALGetColorEntry(pasBandProperties[j].colorTable, i);
-                        if (psEntry->c1 != psEntryRef->c1 || psEntry->c2 != psEntryRef->c2 ||
-                            psEntry->c3 != psEntryRef->c3 || psEntry->c4 != psEntryRef->c4)
-                        {
-                            static int bFirstWarningPCT = TRUE;
-                            if (bFirstWarningPCT)
-                                CPLError(CE_Warning, CPLE_NotSupported,
-                                        "%s has different values than the first raster for some entries in the color table.\n"
-                                        "The end result might produce weird colors.\n"
-                                        "You're advised to preprocess your rasters with other tools, such as pct2rgb.py or gdal_translate -expand RGB\n"
-                                        "to operate gdalbuildvrt on RGB rasters instead", dsFileName);
-                            else
-                                CPLError(CE_Warning, CPLE_NotSupported,
-                                            "%s has different values than the first raster for some entries in the color table.",
-                                            dsFileName);
-                            bFirstWarningPCT = FALSE;
-                            break;
-                        }
-                    }
-                }
-            }
-
-        }
-        if (!bUserExtent)
-        {
-            if (ds_minX < minX) minX = ds_minX;
-            if (ds_minY < minY) minY = ds_minY;
-            if (ds_maxX > maxX) maxX = ds_maxX;
-            if (ds_maxY > maxY) maxY = ds_maxY;
-        }
-    }
-
-    if (resolutionStrategy == AVERAGE_RESOLUTION)
-    {
-        we_res += padfGeoTransform[GEOTRSFRM_WE_RES];
-        ns_res += padfGeoTransform[GEOTRSFRM_NS_RES];
-    }
-    else if (resolutionStrategy != USER_RESOLUTION)
-    {
-        if (bFirst)
-        {
-            we_res = padfGeoTransform[GEOTRSFRM_WE_RES];
-            ns_res = padfGeoTransform[GEOTRSFRM_NS_RES];
-        }
-        else if (resolutionStrategy == HIGHEST_RESOLUTION)
-        {
-            we_res = MIN(we_res, padfGeoTransform[GEOTRSFRM_WE_RES]);
-            /* Yes : as ns_res is negative, the highest resolution is the max value */
-            ns_res = MAX(ns_res, padfGeoTransform[GEOTRSFRM_NS_RES]);
-        }
-        else
-        {
-            we_res = MAX(we_res, padfGeoTransform[GEOTRSFRM_WE_RES]);
-            /* Yes : as ns_res is negative, the lowest resolution is the min value */
-            ns_res = MIN(ns_res, padfGeoTransform[GEOTRSFRM_NS_RES]);
-        }
-    }
-
-    return TRUE;
-}
-
-/************************************************************************/
-/*                         CreateVRTSeparate()                          */
-/************************************************************************/
-
-void VRTBuilder::CreateVRTSeparate(VRTDatasetH hVRTDS)
-{
-    int i;
-    int iBand = 1;
-    for(i=0;i<nInputFiles;i++)
-    {
-        DatasetProperty* psDatasetProperties = &pasDatasetProperties[i];
-
-        if (psDatasetProperties->isFileOK == FALSE)
-            continue;
-
-        int nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize,
-            nDstXOff, nDstYOff, nDstXSize, nDstYSize;
-        if (bHasGeoTransform)
-        {
-            if ( ! GetSrcDstWin(psDatasetProperties,
-                        we_res, ns_res, minX, minY, maxX, maxY,
-                        &nSrcXOff, &nSrcYOff, &nSrcXSize, &nSrcYSize,
-                        &nDstXOff, &nDstYOff, &nDstXSize, &nDstYSize) )
-                continue;
-        }
-        else
-        {
-            nSrcXOff = nSrcYOff = nDstXOff = nDstYOff = 0;
-            nSrcXSize = nDstXSize = nRasterXSize;
-            nSrcYSize = nDstYSize = nRasterYSize;
-        }
-
-        const char* dsFileName = ppszInputFilenames[i];
-
-        GDALAddBand(hVRTDS, psDatasetProperties->firstBandType, NULL);
-
-        GDALProxyPoolDatasetH hProxyDS =
-            GDALProxyPoolDatasetCreate(dsFileName,
-                                        psDatasetProperties->nRasterXSize,
-                                        psDatasetProperties->nRasterYSize,
-                                        GA_ReadOnly, TRUE, pszProjectionRef,
-                                        psDatasetProperties->adfGeoTransform);
-        GDALProxyPoolDatasetAddSrcBandDescription(hProxyDS,
-                                            psDatasetProperties->firstBandType,
-                                            psDatasetProperties->nBlockXSize,
-                                            psDatasetProperties->nBlockYSize);
-
-        VRTSourcedRasterBandH hVRTBand =
-                (VRTSourcedRasterBandH)GDALGetRasterBand(hVRTDS, iBand);
-
-        if (bHideNoData)
-            GDALSetMetadataItem(hVRTBand,"HideNoDataValue","1",NULL);
-
-        VRTSourcedRasterBand* poVRTBand = (VRTSourcedRasterBand*)hVRTBand;
-
-        VRTSimpleSource* poSimpleSource;
-        if (bAllowSrcNoData && psDatasetProperties->panHasNoData[0])
-        {
-            GDALSetRasterNoDataValue(hVRTBand, psDatasetProperties->padfNoDataValues[0]);
-            poSimpleSource = new VRTComplexSource();
-            poSimpleSource->SetNoDataValue( psDatasetProperties->padfNoDataValues[0] );
-        }
-        else
-            poSimpleSource = new VRTSimpleSource();
-        if( pszResampling )
-            poSimpleSource->SetResampling(pszResampling);
-        poVRTBand->ConfigureSource( poSimpleSource,
-                                    (GDALRasterBand*)GDALGetRasterBand((GDALDatasetH)hProxyDS, 1),
-                                    FALSE,
-                                    nSrcXOff, nSrcYOff,
-                                    nSrcXSize, nSrcYSize,
-                                    nDstXOff, nDstYOff,
-                                    nDstXSize, nDstYSize );
-
-        poVRTBand->AddSource( poSimpleSource );
-
-        GDALDereferenceDataset(hProxyDS);
-
-        iBand ++;
-    }
-}
-
-/************************************************************************/
-/*                       CreateVRTNonSeparate()                         */
-/************************************************************************/
-
-void VRTBuilder::CreateVRTNonSeparate(VRTDatasetH hVRTDS)
-{
-    int i, j;
-
-    for(j=0;j<nBands;j++)
-    {
-        GDALRasterBandH hBand;
-        int nSelBand = panBandList[j]-1;
-        GDALAddBand(hVRTDS, pasBandProperties[nSelBand].dataType, NULL);
-        hBand = GDALGetRasterBand(hVRTDS, j+1);
-        GDALSetRasterColorInterpretation(hBand, pasBandProperties[nSelBand].colorInterpretation);
-        if (pasBandProperties[nSelBand].colorInterpretation == GCI_PaletteIndex)
-        {
-            GDALSetRasterColorTable(hBand, pasBandProperties[nSelBand].colorTable);
-        }
-        if (bAllowVRTNoData && pasBandProperties[nSelBand].bHasNoData)
-            GDALSetRasterNoDataValue(hBand, pasBandProperties[nSelBand].noDataValue);
-        if ( bHideNoData )
-            GDALSetMetadataItem(hBand,"HideNoDataValue","1",NULL);
-    }
-
-    VRTSourcedRasterBand* poMaskVRTBand = NULL;
-    if (bAddAlpha)
-    {
-        GDALRasterBandH hBand;
-        GDALAddBand(hVRTDS, GDT_Byte, NULL);
-        hBand = GDALGetRasterBand(hVRTDS, nBands + 1);
-        GDALSetRasterColorInterpretation(hBand, GCI_AlphaBand);
-    }
-    else if (bHasDatasetMask)
-    {
-        GDALCreateDatasetMaskBand(hVRTDS, GMF_PER_DATASET);
-        poMaskVRTBand = (VRTSourcedRasterBand*)GDALGetMaskBand(GDALGetRasterBand(hVRTDS, 1));
-    }
-
-
-    for(i=0;i<nInputFiles;i++)
-    {
-        DatasetProperty* psDatasetProperties = &pasDatasetProperties[i];
-
-        if (psDatasetProperties->isFileOK == FALSE)
-            continue;
-
-        int nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize,
-            nDstXOff, nDstYOff, nDstXSize, nDstYSize;
-        if ( ! GetSrcDstWin(psDatasetProperties,
-                        we_res, ns_res, minX, minY, maxX, maxY,
-                        &nSrcXOff, &nSrcYOff, &nSrcXSize, &nSrcYSize,
-                        &nDstXOff, &nDstYOff, &nDstXSize, &nDstYSize) )
-            continue;
-
-        const char* dsFileName = ppszInputFilenames[i];
-
-        GDALProxyPoolDatasetH hProxyDS =
-            GDALProxyPoolDatasetCreate(dsFileName,
-                                        psDatasetProperties->nRasterXSize,
-                                        psDatasetProperties->nRasterYSize,
-                                        GA_ReadOnly, TRUE, pszProjectionRef,
-                                        psDatasetProperties->adfGeoTransform);
-
-        for(j=0;j<nMaxBandNo;j++)
-        {
-            GDALProxyPoolDatasetAddSrcBandDescription(hProxyDS,
-                                            pasBandProperties[j].dataType,
-                                            psDatasetProperties->nBlockXSize,
-                                            psDatasetProperties->nBlockYSize);
-        }
-        if (bHasDatasetMask && !bAddAlpha)
-        {
-            ((GDALProxyPoolRasterBand*)((GDALProxyPoolDataset*)hProxyDS)->GetRasterBand(1))->
-                    AddSrcMaskBandDescription  (GDT_Byte,
-                                                psDatasetProperties->nMaskBlockXSize,
-                                                psDatasetProperties->nMaskBlockYSize);
-        }
-
-        for(j=0;j<nBands;j++)
-        {
-            VRTSourcedRasterBandH hVRTBand =
-                    (VRTSourcedRasterBandH)GDALGetRasterBand(hVRTDS, j + 1);
-
-            /* Place the raster band at the right position in the VRT */
-            int nSelBand = panBandList[j] - 1;
-            VRTSourcedRasterBand* poVRTBand = (VRTSourcedRasterBand*)hVRTBand;
-
-            VRTSimpleSource* poSimpleSource;
-            if (bAllowSrcNoData && psDatasetProperties->panHasNoData[nSelBand])
-            {
-                poSimpleSource = new VRTComplexSource();
-                poSimpleSource->SetNoDataValue( psDatasetProperties->padfNoDataValues[nSelBand] );
-            }
-            else
-                poSimpleSource = new VRTSimpleSource();
-            if( pszResampling )
-                poSimpleSource->SetResampling(pszResampling);
-            poVRTBand->ConfigureSource( poSimpleSource,
-                                        (GDALRasterBand*)GDALGetRasterBand((GDALDatasetH)hProxyDS, nSelBand + 1),
-                                        FALSE,
-                                        nSrcXOff, nSrcYOff,
-                                        nSrcXSize, nSrcYSize,
-                                        nDstXOff, nDstYOff,
-                                        nDstXSize, nDstYSize );
-
-            poVRTBand->AddSource( poSimpleSource );
-        }
-
-        if (bAddAlpha)
-        {
-            VRTSourcedRasterBandH hVRTBand =
-                    (VRTSourcedRasterBandH)GDALGetRasterBand(hVRTDS, nBands + 1);
-            /* Little trick : we use an offset of 255 and a scaling of 0, so that in areas covered */
-            /* by the source, the value of the alpha band will be 255, otherwise it will be 0 */
-            VRTAddComplexSource(hVRTBand, GDALGetRasterBand((GDALDatasetH)hProxyDS, 1),
-                                nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize,
-                                nDstXOff, nDstYOff, nDstXSize, nDstYSize,
-                                255, 0, VRT_NODATA_UNSET);
-        }
-        else if (bHasDatasetMask)
-        {
-            VRTSimpleSource* poSimpleSource = new VRTSimpleSource();
-            if( pszResampling )
-                poSimpleSource->SetResampling(pszResampling);
-            poMaskVRTBand->ConfigureSource( poSimpleSource,
-                                            (GDALRasterBand*)GDALGetRasterBand((GDALDatasetH)hProxyDS, 1),
-                                            TRUE,
-                                            nSrcXOff, nSrcYOff,
-                                            nSrcXSize, nSrcYSize,
-                                            nDstXOff, nDstYOff,
-                                            nDstXSize, nDstYSize );
-
-            poMaskVRTBand->AddSource( poSimpleSource );
-        }
-
-        GDALDereferenceDataset(hProxyDS);
-    }
-}
-
-/************************************************************************/
-/*                             Build()                                  */
-/************************************************************************/
-
-int VRTBuilder::Build(GDALProgressFunc pfnProgress, void * pProgressData)
-{
-    int i;
-
-    if (bHasRunBuild)
-        return CE_Failure;
-    bHasRunBuild = TRUE;
-
-    if( pfnProgress == NULL )
-        pfnProgress = GDALDummyProgress;
-
-    bUserExtent = (minX != 0 || minY != 0 || maxX != 0 || maxY != 0);
-    if (bUserExtent)
-    {
-        if (minX >= maxX || minY >= maxY )
-        {
-            CPLError(CE_Failure, CPLE_IllegalArg, "Invalid user extent");
-            return CE_Failure;
-        }
-    }
-
-    if (resolutionStrategy == USER_RESOLUTION)
-    {
-        if (we_res <= 0 || ns_res <= 0)
-        {
-            CPLError(CE_Failure, CPLE_IllegalArg, "Invalid user resolution");
-            return CE_Failure;
-        }
-
-        /* We work with negative north-south resolution in all the following code */
-        ns_res = -ns_res;
-    }
-    else
-    {
-        we_res = ns_res = 0;
-    }
-
-    pasDatasetProperties =
-            (DatasetProperty*) CPLCalloc(nInputFiles, sizeof(DatasetProperty));
-
-    if (pszSrcNoData != NULL)
-    {
-        if (EQUAL(pszSrcNoData, "none"))
-        {
-            bAllowSrcNoData = FALSE;
-        }
-        else
-        {
-            char **papszTokens = CSLTokenizeString( pszSrcNoData );
-            nSrcNoDataCount = CSLCount(papszTokens);
-            padfSrcNoData = (double *) CPLMalloc(sizeof(double) * nSrcNoDataCount);
-            for(i=0;i<nSrcNoDataCount;i++)
-            {
-                if( !ArgIsNumeric(papszTokens[i]) )
-                {
-                    CPLError(CE_Failure, CPLE_IllegalArg, "Invalid -srcnodata value");
-                    CSLDestroy(papszTokens);
-                    return CE_Failure;
-                }
-                padfSrcNoData[i] = CPLAtofM(papszTokens[i]);
-            }
-            CSLDestroy(papszTokens);
-        }
-    }
-
-    if (pszVRTNoData != NULL)
-    {
-        if (EQUAL(pszVRTNoData, "none"))
-        {
-            bAllowVRTNoData = FALSE;
-        }
-        else
-        {
-            char **papszTokens = CSLTokenizeString( pszVRTNoData );
-            nVRTNoDataCount = CSLCount(papszTokens);
-            padfVRTNoData = (double *) CPLMalloc(sizeof(double) * nVRTNoDataCount);
-            for(i=0;i<nVRTNoDataCount;i++)
-            {
-                if( !ArgIsNumeric(papszTokens[i]) )
-                {
-                    CPLError(CE_Failure, CPLE_IllegalArg, "Invalid -vrtnodata value");
-                    CSLDestroy(papszTokens);
-                    return CE_Failure;
-                }
-                padfVRTNoData[i] = CPLAtofM(papszTokens[i]);
-            }
-            CSLDestroy(papszTokens);
-        }
-    }
-
-    int nCountValid = 0;
-    for(i=0;i<nInputFiles;i++)
-    {
-        const char* dsFileName = ppszInputFilenames[i];
-
-        if (!pfnProgress( 1.0 * (i+1) / nInputFiles, NULL, pProgressData))
-        {
-            return CE_Failure;
-        }
-
-        GDALDatasetH hDS = GDALOpen(ppszInputFilenames[i], GA_ReadOnly );
-        pasDatasetProperties[i].isFileOK = FALSE;
-
-        if (hDS)
-        {
-            if (AnalyseRaster( hDS, dsFileName, &pasDatasetProperties[i] ))
-            {
-                pasDatasetProperties[i].isFileOK = TRUE;
-                nCountValid ++;
-                bFirst = FALSE;
-            }
-            GDALClose(hDS);
-        }
-        else
-        {
-            CPLError(CE_Warning, CPLE_AppDefined, 
-                     "Can't open %s. Skipping it", dsFileName);
-        }
-    }
-
-    if (nCountValid == 0)
-        return CE_None;
-
-    if (bHasGeoTransform)
-    {
-        if (resolutionStrategy == AVERAGE_RESOLUTION)
-        {
-            we_res /= nCountValid;
-            ns_res /= nCountValid;
-        }
-        
-        if ( bTargetAlignedPixels )
-        {
-            minX = floor(minX / we_res) * we_res;
-            maxX = ceil(maxX / we_res) * we_res;
-            minY = floor(minY / -ns_res) * -ns_res;
-            maxY = ceil(maxY / -ns_res) * -ns_res;
-        }
-
-        nRasterXSize = (int)(0.5 + (maxX - minX) / we_res);
-        nRasterYSize = (int)(0.5 + (maxY - minY) / -ns_res);
-    }
-
-    if (nRasterXSize == 0 || nRasterYSize == 0)
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, 
-                  "Computed VRT dimension is invalid. You've probably specified unappropriate resolution.");
-        return CE_Failure;
-    }
-
-    VRTDatasetH hVRTDS = VRTCreate(nRasterXSize, nRasterYSize);
-    GDALSetDescription(hVRTDS, pszOutputFilename);
-
-    if( pszOutputSRS )
-    {
-        GDALSetProjection(hVRTDS, pszOutputSRS);
-    }
-    else if (pszProjectionRef)
-    {
-        GDALSetProjection(hVRTDS, pszProjectionRef);
-    }
-
-    if (bHasGeoTransform)
-    {
-        double adfGeoTransform[6];
-        adfGeoTransform[GEOTRSFRM_TOPLEFT_X] = minX;
-        adfGeoTransform[GEOTRSFRM_WE_RES] = we_res;
-        adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1] = 0;
-        adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] = maxY;
-        adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] = 0;
-        adfGeoTransform[GEOTRSFRM_NS_RES] = ns_res;
-        GDALSetGeoTransform(hVRTDS, adfGeoTransform);
-    }
-
-    if (bSeparate)
-    {
-        CreateVRTSeparate(hVRTDS);
-    }
-    else
-    {
-        CreateVRTNonSeparate(hVRTDS);
-    }
-
-    GDALClose(hVRTDS);
-
-    return CE_None;
-}
-
-/************************************************************************/
-/*                        add_file_to_list()                            */
-/************************************************************************/
-
-static void add_file_to_list(const char* filename, const char* tile_index,
-                             int* pnInputFiles, char*** pppszInputFilenames)
-{
-   
-    int nInputFiles = *pnInputFiles;
-    char** ppszInputFilenames = *pppszInputFilenames;
-    
-    if (EQUAL(CPLGetExtension(filename), "SHP"))
-    {
-#ifndef OGR_ENABLED
-        CPLError(CE_Failure, CPLE_AppDefined, "OGR support needed to read tileindex");
-        *pnInputFiles = 0;
-        *pppszInputFilenames = NULL;
-#else
-        OGRDataSourceH hDS;
-        OGRLayerH      hLayer;
-        OGRFeatureDefnH hFDefn;
-        int j, ti_field;
-
-        OGRRegisterAll();
-        
-        /* Handle GDALTIndex Shapefile as a special case */
-        hDS = OGROpen( filename, FALSE, NULL );
-        if( hDS  == NULL )
-        {
-            fprintf( stderr, "Unable to open shapefile `%s'.\n", 
-                    filename );
-            exit(2);
-        }
-        
-        hLayer = OGR_DS_GetLayer(hDS, 0);
-
-        hFDefn = OGR_L_GetLayerDefn(hLayer);
-
-        for( ti_field = 0; ti_field < OGR_FD_GetFieldCount(hFDefn); ti_field++ )
-        {
-            OGRFieldDefnH hFieldDefn = OGR_FD_GetFieldDefn( hFDefn, ti_field );
-            const char* pszName = OGR_Fld_GetNameRef(hFieldDefn);
-
-            if (strcmp(pszName, "LOCATION") == 0 && strcmp("LOCATION", tile_index) != 0 )
-            {
-                fprintf( stderr, "This shapefile seems to be a tile index of "
-                                "OGR features and not GDAL products.\n");
-            }
-            if( strcmp(pszName, tile_index) == 0 )
-                break;
-        }
-    
-        if( ti_field == OGR_FD_GetFieldCount(hFDefn) )
-        {
-            fprintf( stderr, "Unable to find field `%s' in DBF file `%s'.\n", 
-                    tile_index, filename );
-            return;
-        }
-    
-        /* Load in memory existing file names in SHP */
-        int nTileIndexFiles = (int)OGR_L_GetFeatureCount(hLayer, TRUE);
-        if (nTileIndexFiles == 0)
-        {
-            fprintf( stderr, "Tile index %s is empty. Skipping it.\n", filename);
-            return;
-        }
-        
-        ppszInputFilenames = (char**)CPLRealloc(ppszInputFilenames,
-                              sizeof(char*) * (nInputFiles+nTileIndexFiles));
-        for(j=0;j<nTileIndexFiles;j++)
-        {
-            OGRFeatureH hFeat = OGR_L_GetNextFeature(hLayer);
-            ppszInputFilenames[nInputFiles++] =
-                    CPLStrdup(OGR_F_GetFieldAsString(hFeat, ti_field ));
-            OGR_F_Destroy(hFeat);
-        }
-
-        OGR_DS_Destroy( hDS );
-#endif
-    }
-    else
-    {
-        ppszInputFilenames = (char**)CPLRealloc(ppszInputFilenames,
-                                                 sizeof(char*) * (nInputFiles+1));
-        ppszInputFilenames[nInputFiles++] = CPLStrdup(filename);
-    }
-
-    *pnInputFiles = nInputFiles;
-    *pppszInputFilenames = ppszInputFilenames;
-}
-
-/************************************************************************/
-/*                                main()                                */
-/************************************************************************/
-
-#define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg) \
-    do { if (iArg + nExtraArg >= nArgc) \
-        Usage(CPLSPrintf("%s option requires %d argument(s)", papszArgv[iArg], nExtraArg)); } while(0)
-
-int main( int nArgc, char ** papszArgv )
-
-{
-    const char *tile_index = "location";
-    const char *resolution = NULL;
-    int nInputFiles = 0;
-    char ** ppszInputFilenames = NULL;
-    const char * pszOutputFilename = NULL;
-    int i, iArg;
-    int bSeparate = FALSE;
-    int bAllowProjectionDifference = FALSE;
-    int bQuiet = FALSE;
-    GDALProgressFunc pfnProgress = NULL;
-    double we_res = 0, ns_res = 0;
-    int bTargetAlignedPixels = FALSE;
-    double xmin = 0, ymin = 0, xmax = 0, ymax = 0;
-    int bAddAlpha = FALSE;
-    int bForceOverwrite = FALSE;
-    int bHideNoData = FALSE;
-    int nSubdataset = -1;
-    const char* pszSrcNoData = NULL;
-    const char* pszVRTNoData = NULL;
-    char* pszOutputSRS = NULL;
-    int *panBandList = NULL;
-    int nBandCount = 0;
-    int nMaxBandNo = 0;
-    int nRet;
-    const char* pszResampling = NULL;
-
-    /* Check strict compilation and runtime library version as we use C++ API */
-    if (! GDAL_CHECK_VERSION(papszArgv[0]))
-        exit(1);
-
-    GDALAllRegister();
-
-    nArgc = GDALGeneralCmdLineProcessor( nArgc, &papszArgv, 0 );
-    if( nArgc < 1 )
-        exit( -nArgc );
-
-/* -------------------------------------------------------------------- */
-/*      Parse commandline.                                              */
-/* -------------------------------------------------------------------- */
-    for( iArg = 1; iArg < nArgc; iArg++ )
-    {
-        if( EQUAL(papszArgv[iArg], "--utility_version") )
-        {
-            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
-                   papszArgv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
-            return 0;
-        }
-        else if( EQUAL(papszArgv[iArg],"--help") )
-            Usage();
-        else if( EQUAL(papszArgv[iArg],"-tileindex") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            tile_index = papszArgv[++iArg];
-        }
-        else if( EQUAL(papszArgv[iArg],"-resolution") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            resolution = papszArgv[++iArg];
-        }
-        else if( EQUAL(papszArgv[iArg],"-input_file_list") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            const char* input_file_list = papszArgv[++iArg];
-            FILE* f = VSIFOpen(input_file_list, "r");
-            if (f)
-            {
-                while(1)
-                {
-                    const char* filename = CPLReadLine(f);
-                    if (filename == NULL)
-                        break;
-                    add_file_to_list(filename, tile_index,
-                                     &nInputFiles, &ppszInputFilenames);
-                }
-                VSIFClose(f);
-            }
-        }
-        else if ( EQUAL(papszArgv[iArg],"-separate") )
-        {
-            bSeparate = TRUE;
-        }
-        else if ( EQUAL(papszArgv[iArg],"-allow_projection_difference") )
-        {
-            bAllowProjectionDifference = TRUE;
-        }
-        else if( EQUAL(papszArgv[iArg], "-sd") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            nSubdataset = atoi(papszArgv[++iArg]);
-        }
-        /* Alternate syntax for output file */
-        else if( EQUAL(papszArgv[iArg],"-o") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszOutputFilename = papszArgv[++iArg];
-        }
-        else if ( EQUAL(papszArgv[iArg],"-q") || EQUAL(papszArgv[iArg],"-quiet") )
-        {
-            bQuiet = TRUE;
-        }
-        else if ( EQUAL(papszArgv[iArg],"-tr") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2);
-            we_res = CPLAtofM(papszArgv[++iArg]);
-            ns_res = CPLAtofM(papszArgv[++iArg]);
-        }
-        else if( EQUAL(papszArgv[iArg],"-tap") )
-        {
-            bTargetAlignedPixels = TRUE;
-        }
-        else if ( EQUAL(papszArgv[iArg],"-te") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(4);
-            xmin = CPLAtofM(papszArgv[++iArg]);
-            ymin = CPLAtofM(papszArgv[++iArg]);
-            xmax = CPLAtofM(papszArgv[++iArg]);
-            ymax = CPLAtofM(papszArgv[++iArg]);
-        }
-        else if ( EQUAL(papszArgv[iArg],"-addalpha") )
-        {
-            bAddAlpha = TRUE;
-        }
-        else if( EQUAL(papszArgv[iArg],"-b"))
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            const char* pszBand = papszArgv[++iArg];
-            int nBand = atoi(pszBand);
-            if( nBand < 1 )
-            {
-                printf( "Unrecognizable band number (%s).\n", papszArgv[iArg+1] );
-                Usage();
-                GDALDestroyDriverManager();
-                exit( 1 );
-            }
-            
-            if(nBand > nMaxBandNo)
-            {
-                nMaxBandNo = nBand;
-            }
-
-            nBandCount++;
-            panBandList = (int *) 
-                CPLRealloc(panBandList, sizeof(int) * nBandCount);
-            panBandList[nBandCount-1] = nBand;
-        }
-        else if ( EQUAL(papszArgv[iArg],"-hidenodata") )
-        {
-            bHideNoData = TRUE;
-        }
-        else if ( EQUAL(papszArgv[iArg],"-overwrite") )
-        {
-            bForceOverwrite = TRUE;
-        }
-        else if ( EQUAL(papszArgv[iArg],"-srcnodata") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszSrcNoData = papszArgv[++iArg];
-        }
-        else if ( EQUAL(papszArgv[iArg],"-vrtnodata") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszVRTNoData = papszArgv[++iArg];
-        }
-        else if( EQUAL(papszArgv[iArg],"-a_srs") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            OGRSpatialReferenceH hOutputSRS = OSRNewSpatialReference(NULL);
-
-            if( OSRSetFromUserInput( hOutputSRS, papszArgv[iArg+1] ) != OGRERR_NONE )
-            {
-                fprintf( stderr, "Failed to process SRS definition: %s\n", 
-                         papszArgv[iArg+1] );
-                GDALDestroyDriverManager();
-                exit( 1 );
-            }
-
-            OSRExportToWkt( hOutputSRS, &pszOutputSRS );
-            OSRDestroySpatialReference( hOutputSRS );
-            iArg++;
-        }
-        else if( EQUAL(papszArgv[iArg],"-r") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszResampling = papszArgv[++iArg];
-        }  
-        else if ( papszArgv[iArg][0] == '-' )
-        {
-            Usage(CPLSPrintf("Unknown option name '%s'", papszArgv[iArg]));
-        }
-        else if( pszOutputFilename == NULL )
-        {
-            pszOutputFilename = papszArgv[iArg];
-        }
-        else
-        {
-            add_file_to_list(papszArgv[iArg], tile_index,
-                             &nInputFiles, &ppszInputFilenames);
-        }
-    }
-
-    if( pszOutputFilename == NULL )
-        Usage("No output filename specified.");
-    if( nInputFiles == 0 )
-        Usage("No input filenames specified.");
-
-    if (!bQuiet)
-        pfnProgress = GDALTermProgress;
-       
-    /* Avoid overwriting a non VRT dataset if the user did not put the */
-    /* filenames in the right order */
-    VSIStatBuf sBuf;
-    if (!bForceOverwrite)
-    {
-        int bExists = (VSIStat(pszOutputFilename, &sBuf) == 0);
-        if (bExists)
-        {
-            GDALDriverH hDriver = GDALIdentifyDriver( pszOutputFilename, NULL );
-            if (hDriver && !(EQUAL(GDALGetDriverShortName(hDriver), "VRT") ||
-                   (EQUAL(GDALGetDriverShortName(hDriver), "API_PROXY") &&
-                    EQUAL(CPLGetExtension(pszOutputFilename), "VRT"))) )
-            {
-                fprintf(stderr,
-                        "'%s' is an existing GDAL dataset managed by %s driver.\n"
-                        "There is an high chance you did not put filenames in the right order.\n"
-                        "If you want to overwrite %s, add -overwrite option to the command line.\n\n",
-                        pszOutputFilename, GDALGetDriverShortName(hDriver), pszOutputFilename);
-                Usage();
-            }
-        }
-    }
-    
-    if (we_res != 0 && ns_res != 0 &&
-        resolution != NULL && !EQUAL(resolution, "user"))
-    {
-        Usage(CPLSPrintf("-tr option is not compatible with -resolution %s", resolution));
-    }
-    
-    if (bTargetAlignedPixels && we_res == 0 && ns_res == 0)
-    {
-        Usage("-tap option cannot be used without using -tr");
-    }
-    
-    if (bAddAlpha && bSeparate)
-    {
-        Usage("-addalpha option is not compatible with -separate.");
-    }
-        
-    ResolutionStrategy eStrategy = AVERAGE_RESOLUTION;
-    if ( resolution == NULL || EQUAL(resolution, "user") )
-    {
-        if ( we_res != 0 || ns_res != 0)
-            eStrategy = USER_RESOLUTION;
-        else if ( resolution != NULL && EQUAL(resolution, "user") )
-        {
-            Usage("-tr option must be used with -resolution user.");
-        }
-    }
-    else if ( EQUAL(resolution, "average") )
-        eStrategy = AVERAGE_RESOLUTION;
-    else if ( EQUAL(resolution, "highest") )
-        eStrategy = HIGHEST_RESOLUTION;
-    else if ( EQUAL(resolution, "lowest") )
-        eStrategy = LOWEST_RESOLUTION;
-    else
-    {
-        Usage(CPLSPrintf("invalid value (%s) for -resolution", resolution));
-    }
-    
-    /* If -srcnodata is specified, use it as the -vrtnodata if the latter is not */
-    /* specified */
-    if (pszSrcNoData != NULL && pszVRTNoData == NULL)
-        pszVRTNoData = pszSrcNoData;
-
-    VRTBuilder oBuilder(pszOutputFilename, nInputFiles, ppszInputFilenames,
-                        panBandList, nBandCount, nMaxBandNo,
-                        eStrategy, we_res, ns_res, bTargetAlignedPixels, xmin, ymin, xmax, ymax,
-                        bSeparate, bAllowProjectionDifference, bAddAlpha, bHideNoData, nSubdataset,
-                        pszSrcNoData, pszVRTNoData, pszOutputSRS, pszResampling);
-
-    nRet = (oBuilder.Build(pfnProgress, NULL) == CE_None) ? 0 : 1;
-    
-    for(i=0;i<nInputFiles;i++)
-    {
-        CPLFree(ppszInputFilenames[i]);
-    }
-    CPLFree(ppszInputFilenames);
-    CPLFree(pszOutputSRS);
-    CPLFree( panBandList );
-    CSLDestroy( papszArgv );
-    GDALDumpOpenDatasets( stderr );
-    GDALDestroyDriverManager();
-#ifdef OGR_ENABLED
-    OGRCleanupAll();
-#endif
-
-    return nRet;
-}
diff --git a/apps/gdalbuildvrt_bin.cpp b/apps/gdalbuildvrt_bin.cpp
new file mode 100644
index 0000000..b96ac28
--- /dev/null
+++ b/apps/gdalbuildvrt_bin.cpp
@@ -0,0 +1,213 @@
+/******************************************************************************
+ * $Id: gdalbuildvrt_bin.cpp 33757 2016-03-20 20:22:33Z goatbar $
+ *
+ * Project:  GDAL Utilities
+ * Purpose:  Command line application to build VRT datasets from raster products or content of SHP tile index
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2007-2016, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_string.h"
+#include "cpl_error.h"
+#include "commonutils.h"
+#include "gdal_utils_priv.h"
+
+CPL_CVSID("$Id: gdalbuildvrt_bin.cpp 33757 2016-03-20 20:22:33Z goatbar $");
+
+/************************************************************************/
+/*                               Usage()                                */
+/************************************************************************/
+
+static void Usage(const char* pszErrorMsg = NULL) CPL_NO_RETURN;
+
+static void Usage(const char* pszErrorMsg)
+
+{
+    fprintf(stdout, "%s",
+            "Usage: gdalbuildvrt [-tileindex field_name]\n"
+            "                    [-resolution {highest|lowest|average|user}]\n"
+            "                    [-te xmin ymin xmax ymax] [-tr xres yres] [-tap]\n"
+            "                    [-separate] [-b band] [-sd subdataset]\n"
+            "                    [-allow_projection_difference] [-q]\n"
+            "                    [-addalpha] [-hidenodata]\n"
+            "                    [-srcnodata \"value [value...]\"] [-vrtnodata \"value [value...]\"] \n"
+            "                    [-a_srs srs_def]\n"
+            "                    [-r {nearest,bilinear,cubic,cubicspline,lanczos,average,mode}]\n"
+            "                    [-input_file_list my_list.txt] [-overwrite] output.vrt [gdalfile]*\n"
+            "\n"
+            "e.g.\n"
+            "  % gdalbuildvrt doq_index.vrt doq/*.tif\n"
+            "  % gdalbuildvrt -input_file_list my_list.txt doq_index.vrt\n"
+            "\n"
+            "NOTES:\n"
+            "  o With -separate, each files goes into a separate band in the VRT band.\n"
+            "    Otherwise, the files are considered as tiles of a larger mosaic.\n"
+            "  o -b option selects a band to add into vrt.  Multiple bands can be listed.\n"
+            "    By default all bands are queried.\n"
+            "  o The default tile index field is 'location' unless otherwise specified by\n"
+            "    -tileindex.\n"
+            "  o In case the resolution of all input files is not the same, the -resolution\n"
+            "    flag enable the user to control the way the output resolution is computed.\n"
+            "    Average is the default.\n"
+            "  o Input files may be any valid GDAL dataset or a GDAL raster tile index.\n"
+            "  o For a GDAL raster tile index, all entries will be added to the VRT.\n"
+            "  o If one GDAL dataset is made of several subdatasets and has 0 raster bands,\n"
+            "    its datasets will be added to the VRT rather than the dataset itself.\n"
+            "    Single subdataset could be selected by its number using the -sd option.\n"
+            "  o By default, only datasets of same projection and band characteristics\n"
+            "    may be added to the VRT.\n"
+            );
+
+    if( pszErrorMsg != NULL )
+        fprintf(stderr, "\nFAILURE: %s\n", pszErrorMsg);
+
+    exit( 1 );
+}
+
+/************************************************************************/
+/*                       GDALBuildVRTOptionsForBinaryNew()              */
+/************************************************************************/
+
+static GDALBuildVRTOptionsForBinary *GDALBuildVRTOptionsForBinaryNew(void)
+{
+    return (GDALBuildVRTOptionsForBinary*) CPLCalloc(  1, sizeof(GDALBuildVRTOptionsForBinary) );
+}
+
+/************************************************************************/
+/*                       GDALBuildVRTOptionsForBinaryFree()            */
+/************************************************************************/
+
+static void GDALBuildVRTOptionsForBinaryFree( GDALBuildVRTOptionsForBinary* psOptionsForBinary )
+{
+    if( psOptionsForBinary )
+    {
+        CSLDestroy(psOptionsForBinary->papszSrcFiles);
+        CPLFree(psOptionsForBinary->pszDstFilename);
+        CPLFree(psOptionsForBinary);
+    }
+}
+
+/************************************************************************/
+/*                                main()                                */
+/************************************************************************/
+
+int main( int argc, char ** argv )
+
+{
+    EarlySetConfigOptions(argc, argv);
+
+/* -------------------------------------------------------------------- */
+/*      Register standard GDAL drivers, and process generic GDAL        */
+/*      command options.                                                */
+/* -------------------------------------------------------------------- */
+    GDALAllRegister();
+    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
+    if( argc < 1 )
+        exit( -argc );
+
+    for( int i = 0; argv != NULL && argv[i] != NULL; i++ )
+    {
+        if( EQUAL(argv[i], "--utility_version") )
+        {
+            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
+                   argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
+            CSLDestroy( argv );
+            return 0;
+        }
+        else if( EQUAL(argv[i],"--help") )
+        {
+            Usage(NULL);
+        }
+    }
+
+    GDALBuildVRTOptionsForBinary* psOptionsForBinary = GDALBuildVRTOptionsForBinaryNew();
+    /* coverity[tainted_data] */
+    GDALBuildVRTOptions *psOptions = GDALBuildVRTOptionsNew(argv + 1, psOptionsForBinary);
+    CSLDestroy( argv );
+
+    if( psOptions == NULL )
+    {
+        Usage(NULL);
+    }
+
+    if( psOptionsForBinary->pszDstFilename == NULL )
+    {
+        Usage("No target filename specified.");
+    }
+
+    if( !(psOptionsForBinary->bQuiet) )
+    {
+        GDALBuildVRTOptionsSetProgress(psOptions, GDALTermProgress, NULL);
+    }
+
+    /* Avoid overwriting a non VRT dataset if the user did not put the */
+    /* filenames in the right order */
+    VSIStatBuf sBuf;
+    if (!psOptionsForBinary->bOverwrite)
+    {
+        int bExists = (VSIStat(psOptionsForBinary->pszDstFilename, &sBuf) == 0);
+        if (bExists)
+        {
+            GDALDriverH hDriver = GDALIdentifyDriver( psOptionsForBinary->pszDstFilename, NULL );
+            if (hDriver && !(EQUAL(GDALGetDriverShortName(hDriver), "VRT") ||
+                   (EQUAL(GDALGetDriverShortName(hDriver), "API_PROXY") &&
+                    EQUAL(CPLGetExtension(psOptionsForBinary->pszDstFilename), "VRT"))) )
+            {
+                fprintf(stderr,
+                        "'%s' is an existing GDAL dataset managed by %s driver.\n"
+                        "There is an high chance you did not put filenames in the right order.\n"
+                        "If you want to overwrite %s, add -overwrite option to the command line.\n\n",
+                        psOptionsForBinary->pszDstFilename, GDALGetDriverShortName(hDriver), psOptionsForBinary->pszDstFilename);
+                Usage();
+            }
+        }
+    }
+
+    int bUsageError = FALSE;
+    GDALDatasetH hOutDS = GDALBuildVRT(psOptionsForBinary->pszDstFilename,
+                                       psOptionsForBinary->nSrcFiles,
+                                       NULL,
+                                       (const char* const*)psOptionsForBinary->papszSrcFiles,
+                                       psOptions, &bUsageError);
+    if( bUsageError )
+        Usage();
+    int nRetCode = (hOutDS) ? 0 : 1;
+
+    GDALBuildVRTOptionsFree(psOptions);
+    GDALBuildVRTOptionsForBinaryFree(psOptionsForBinary);
+
+    CPLErrorReset();
+    // The flush to disk is only done at that stage, so check if any error has
+    // happened
+    GDALClose( hOutDS );
+    if( CPLGetLastErrorType() != CE_None )
+        nRetCode = 1;
+
+    GDALDumpOpenDatasets( stderr );
+
+    GDALDestroyDriverManager();
+
+    OGRCleanupAll();
+
+    return nRetCode;
+}
diff --git a/apps/gdalbuildvrt_lib.cpp b/apps/gdalbuildvrt_lib.cpp
new file mode 100644
index 0000000..6f8172d
--- /dev/null
+++ b/apps/gdalbuildvrt_lib.cpp
@@ -0,0 +1,1750 @@
+/******************************************************************************
+ * $Id: gdalbuildvrt_lib.cpp 33757 2016-03-20 20:22:33Z goatbar $
+ *
+ * Project:  GDAL Utilities
+ * Purpose:  Command line application to build VRT datasets from raster products
+ *           or content of SHP tile index
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2007-2016, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_string.h"
+#include "gdal_proxy.h"
+#include "gdal_utils.h"
+#include "gdal_utils_priv.h"
+#include "gdal_vrt.h"
+#include "vrtdataset.h"
+
+#include "ogr_api.h"
+#include "ogr_srs_api.h"
+
+CPL_CVSID("$Id: gdalbuildvrt_lib.cpp 33757 2016-03-20 20:22:33Z goatbar $");
+
+#define GEOTRSFRM_TOPLEFT_X            0
+#define GEOTRSFRM_WE_RES               1
+#define GEOTRSFRM_ROTATION_PARAM1      2
+#define GEOTRSFRM_TOPLEFT_Y            3
+#define GEOTRSFRM_ROTATION_PARAM2      4
+#define GEOTRSFRM_NS_RES               5
+
+typedef enum
+{
+    LOWEST_RESOLUTION,
+    HIGHEST_RESOLUTION,
+    AVERAGE_RESOLUTION,
+    USER_RESOLUTION
+} ResolutionStrategy;
+
+typedef struct
+{
+    int    isFileOK;
+    int    nRasterXSize;
+    int    nRasterYSize;
+    double adfGeoTransform[6];
+    int    nBlockXSize;
+    int    nBlockYSize;
+    GDALDataType firstBandType;
+    int*         panHasNoData;
+    double*      padfNoDataValues;
+    int    bHasDatasetMask;
+    int    nMaskBlockXSize;
+    int    nMaskBlockYSize;
+} DatasetProperty;
+
+typedef struct
+{
+    GDALColorInterp        colorInterpretation;
+    GDALDataType           dataType;
+    GDALColorTableH        colorTable;
+    int                    bHasNoData;
+    double                 noDataValue;
+} BandProperty;
+
+/************************************************************************/
+/*                            ArgIsNumeric()                            */
+/************************************************************************/
+
+static int ArgIsNumeric( const char *pszArg )
+
+{
+    return CPLGetValueType(pszArg) != CPL_VALUE_STRING;
+}
+
+
+/************************************************************************/
+/*                         GetSrcDstWin()                               */
+/************************************************************************/
+
+static int  GetSrcDstWin(DatasetProperty* psDP,
+                  double we_res, double ns_res,
+                  double minX, double minY, double maxX, double maxY,
+                  double* pdfSrcXOff, double* pdfSrcYOff, double* pdfSrcXSize, double* pdfSrcYSize,
+                  double* pdfDstXOff, double* pdfDstYOff, double* pdfDstXSize, double* pdfDstYSize)
+{
+    /* Check that the destination bounding box intersects the source bounding box */
+    if ( psDP->adfGeoTransform[GEOTRSFRM_TOPLEFT_X] +
+         psDP->nRasterXSize *
+         psDP->adfGeoTransform[GEOTRSFRM_WE_RES] < minX )
+         return FALSE;
+    if ( psDP->adfGeoTransform[GEOTRSFRM_TOPLEFT_X] > maxX )
+         return FALSE;
+    if ( psDP->adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] +
+         psDP->nRasterYSize *
+         psDP->adfGeoTransform[GEOTRSFRM_NS_RES] > maxY )
+         return FALSE;
+    if ( psDP->adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] < minY )
+         return FALSE;
+
+    *pdfSrcXSize = psDP->nRasterXSize;
+    *pdfSrcYSize = psDP->nRasterYSize;
+    if ( psDP->adfGeoTransform[GEOTRSFRM_TOPLEFT_X] < minX )
+    {
+        *pdfSrcXOff = (minX - psDP->adfGeoTransform[GEOTRSFRM_TOPLEFT_X]) /
+            psDP->adfGeoTransform[GEOTRSFRM_WE_RES];
+        *pdfDstXOff = 0.0;
+    }
+    else
+    {
+        *pdfSrcXOff = 0.0;
+        *pdfDstXOff =
+            ((psDP->adfGeoTransform[GEOTRSFRM_TOPLEFT_X] - minX) / we_res);
+    }
+    if ( maxY < psDP->adfGeoTransform[GEOTRSFRM_TOPLEFT_Y])
+    {
+        *pdfSrcYOff = (psDP->adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] - maxY) /
+            -psDP->adfGeoTransform[GEOTRSFRM_NS_RES];
+        *pdfDstYOff = 0.0;
+    }
+    else
+    {
+        *pdfSrcYOff = 0.0;
+        *pdfDstYOff =
+            ((maxY - psDP->adfGeoTransform[GEOTRSFRM_TOPLEFT_Y]) / -ns_res);
+    }
+    *pdfDstXSize = (psDP->nRasterXSize *
+         psDP->adfGeoTransform[GEOTRSFRM_WE_RES] / we_res);
+    *pdfDstYSize = (psDP->nRasterYSize *
+         psDP->adfGeoTransform[GEOTRSFRM_NS_RES] / ns_res);
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                            VRTBuilder                                */
+/************************************************************************/
+
+class VRTBuilder
+{
+    /* Input parameters */
+    char               *pszOutputFilename;
+    int                 nInputFiles;
+    char              **ppszInputFilenames;
+    GDALDatasetH       *pahSrcDS;
+    int                 nBands;
+    int                *panBandList;
+    int                 nMaxBandNo;
+    ResolutionStrategy  resolutionStrategy;
+    double              we_res;
+    double              ns_res;
+    int                 bTargetAlignedPixels;
+    double              minX;
+    double              minY;
+    double              maxX;
+    double              maxY;
+    int                 bSeparate;
+    int                 bAllowProjectionDifference;
+    int                 bAddAlpha;
+    int                 bHideNoData;
+    int                 nSubdataset;
+    char               *pszSrcNoData;
+    char               *pszVRTNoData;
+    char               *pszOutputSRS;
+    char               *pszResampling;
+
+    /* Internal variables */
+    char               *pszProjectionRef;
+    BandProperty       *pasBandProperties;
+    int                 bFirst;
+    int                 bHasGeoTransform;
+    int                 nRasterXSize;
+    int                 nRasterYSize;
+    DatasetProperty    *pasDatasetProperties;
+    int                 bUserExtent;
+    int                 bAllowSrcNoData;
+    double             *padfSrcNoData;
+    int                 nSrcNoDataCount;
+    int                 bAllowVRTNoData;
+    double             *padfVRTNoData;
+    int                 nVRTNoDataCount;
+    int                 bHasRunBuild;
+    int                 bHasDatasetMask;
+
+    int         AnalyseRaster(GDALDatasetH hDS,
+                              DatasetProperty* psDatasetProperties);
+
+    void        CreateVRTSeparate(VRTDatasetH hVRTDS);
+    void        CreateVRTNonSeparate(VRTDatasetH hVRTDS);
+
+    public:
+                VRTBuilder(const char* pszOutputFilename,
+                           int nInputFiles,
+                           const char* const * ppszInputFilenames,
+                           GDALDatasetH *pahSrcDSIn,
+                           const int *panBandListIn, int nBandCount, int nMaxBandNo,
+                           ResolutionStrategy resolutionStrategy,
+                           double we_res, double ns_res,
+                           int bTargetAlignedPixels,
+                           double minX, double minY, double maxX, double maxY,
+                           int bSeparate, int bAllowProjectionDifference,
+                           int bAddAlpha, int bHideNoData, int nSubdataset,
+                           const char* pszSrcNoData, const char* pszVRTNoData,
+                           const char* pszOutputSRS,
+                           const char* pszResampling);
+
+               ~VRTBuilder();
+
+        GDALDataset*     Build(GDALProgressFunc pfnProgress, void * pProgressData);
+};
+
+
+/************************************************************************/
+/*                          VRTBuilder()                                */
+/************************************************************************/
+
+VRTBuilder::VRTBuilder(const char* pszOutputFilenameIn,
+                       int nInputFilesIn,
+                       const char* const * ppszInputFilenamesIn,
+                       GDALDatasetH *pahSrcDSIn,
+                       const int *panBandListIn, int nBandCount, int nMaxBandNoIn,
+                       ResolutionStrategy resolutionStrategyIn,
+                       double we_resIn, double ns_resIn,
+                       int bTargetAlignedPixelsIn,
+                       double minXIn, double minYIn, double maxXIn, double maxYIn,
+                       int bSeparateIn, int bAllowProjectionDifferenceIn,
+                       int bAddAlphaIn, int bHideNoDataIn, int nSubdatasetIn,
+                       const char* pszSrcNoDataIn, const char* pszVRTNoDataIn,
+                       const char* pszOutputSRSIn,
+                       const char* pszResamplingIn)
+{
+    pszOutputFilename = CPLStrdup(pszOutputFilenameIn);
+    nInputFiles = nInputFilesIn;
+    pahSrcDS = NULL;
+    ppszInputFilenames = NULL;
+
+    if( ppszInputFilenamesIn )
+    {
+        ppszInputFilenames = (char**) CPLMalloc(nInputFiles * sizeof(char*));
+        for(int i=0;i<nInputFiles;i++)
+        {
+            ppszInputFilenames[i] = CPLStrdup(ppszInputFilenamesIn[i]);
+        }
+    }
+    else if( pahSrcDSIn )
+    {
+        pahSrcDS = (GDALDatasetH*) CPLMalloc(nInputFiles * sizeof(GDALDatasetH));
+        memcpy(pahSrcDS, pahSrcDSIn, nInputFiles * sizeof(GDALDatasetH));
+        ppszInputFilenames = (char**) CPLMalloc(nInputFiles * sizeof(char*));
+        for(int i=0;i<nInputFiles;i++)
+        {
+            ppszInputFilenames[i] = CPLStrdup(GDALGetDescription(pahSrcDSIn[i]));
+        }
+    }
+
+    nBands = nBandCount;
+    panBandList = NULL;
+    if( nBandCount )
+    {
+        panBandList = (int*) CPLMalloc(nBands * sizeof(int));
+        memcpy(panBandList, panBandListIn, nBands * sizeof(int));
+    }
+    nMaxBandNo = nMaxBandNoIn;
+
+    resolutionStrategy = resolutionStrategyIn;
+    we_res = we_resIn;
+    ns_res = ns_resIn;
+    bTargetAlignedPixels = bTargetAlignedPixelsIn;
+    minX = minXIn;
+    minY = minYIn;
+    maxX = maxXIn;
+    maxY = maxYIn;
+    bSeparate = bSeparateIn;
+    bAllowProjectionDifference = bAllowProjectionDifferenceIn;
+    bAddAlpha = bAddAlphaIn;
+    bHideNoData = bHideNoDataIn;
+    nSubdataset = nSubdatasetIn;
+    pszSrcNoData = (pszSrcNoDataIn) ? CPLStrdup(pszSrcNoDataIn) : NULL;
+    pszVRTNoData = (pszVRTNoDataIn) ? CPLStrdup(pszVRTNoDataIn) : NULL;
+    pszOutputSRS = (pszOutputSRSIn) ? CPLStrdup(pszOutputSRSIn) : NULL;
+    pszResampling = (pszResamplingIn) ? CPLStrdup(pszResamplingIn) : NULL;
+
+    bUserExtent = FALSE;
+    pszProjectionRef = NULL;
+    pasBandProperties = NULL;
+    bFirst = TRUE;
+    bHasGeoTransform = FALSE;
+    nRasterXSize = 0;
+    nRasterYSize = 0;
+    pasDatasetProperties = NULL;
+    bAllowSrcNoData = TRUE;
+    padfSrcNoData = NULL;
+    nSrcNoDataCount = 0;
+    bAllowVRTNoData = TRUE;
+    padfVRTNoData = NULL;
+    nVRTNoDataCount = 0;
+    bHasRunBuild = FALSE;
+    bHasDatasetMask = FALSE;
+}
+
+/************************************************************************/
+/*                         ~VRTBuilder()                                */
+/************************************************************************/
+
+VRTBuilder::~VRTBuilder()
+{
+    CPLFree(pszOutputFilename);
+    CPLFree(pszSrcNoData);
+    CPLFree(pszVRTNoData);
+    CPLFree(panBandList);
+
+    for(int i=0;i<nInputFiles;i++)
+    {
+        CPLFree(ppszInputFilenames[i]);
+    }
+    CPLFree(ppszInputFilenames);
+    CPLFree(pahSrcDS);
+
+    if (pasDatasetProperties != NULL)
+    {
+        for(int i=0;i<nInputFiles;i++)
+        {
+            CPLFree(pasDatasetProperties[i].padfNoDataValues);
+            CPLFree(pasDatasetProperties[i].panHasNoData);
+        }
+    }
+    CPLFree(pasDatasetProperties);
+
+    if (!bSeparate && pasBandProperties != NULL)
+    {
+        for(int j=0;j<nBands;j++)
+        {
+            GDALDestroyColorTable(pasBandProperties[j].colorTable);
+        }
+    }
+    CPLFree(pasBandProperties);
+
+    CPLFree(pszProjectionRef);
+    CPLFree(padfSrcNoData);
+    CPLFree(padfVRTNoData);
+    CPLFree(pszOutputSRS);
+    CPLFree(pszResampling);
+}
+
+/************************************************************************/
+/*                           ProjAreEqual()                             */
+/************************************************************************/
+
+static int ProjAreEqual(const char* pszWKT1, const char* pszWKT2)
+{
+    if (EQUAL(pszWKT1, pszWKT2))
+        return TRUE;
+
+    OGRSpatialReferenceH hSRS1 = OSRNewSpatialReference(pszWKT1);
+    OGRSpatialReferenceH hSRS2 = OSRNewSpatialReference(pszWKT2);
+    int bRet = hSRS1 != NULL && hSRS2 != NULL && OSRIsSame(hSRS1,hSRS2);
+    if (hSRS1)
+        OSRDestroySpatialReference(hSRS1);
+    if (hSRS2)
+        OSRDestroySpatialReference(hSRS2);
+    return bRet;
+}
+
+/************************************************************************/
+/*                           AnalyseRaster()                            */
+/************************************************************************/
+
+int VRTBuilder::AnalyseRaster( GDALDatasetH hDS, DatasetProperty* psDatasetProperties)
+{
+    const char* dsFileName = GDALGetDescription(hDS);
+    char** papszMetadata = GDALGetMetadata( hDS, "SUBDATASETS" );
+    if( CSLCount(papszMetadata) > 0 && GDALGetRasterCount(hDS) == 0 )
+    {
+        pasDatasetProperties =
+            (DatasetProperty*) CPLRealloc(pasDatasetProperties,
+                            (nInputFiles+CSLCount(papszMetadata))*sizeof(DatasetProperty));
+
+        ppszInputFilenames = (char**)CPLRealloc(ppszInputFilenames,
+                                sizeof(char*) * (nInputFiles+CSLCount(papszMetadata)));
+        if ( nSubdataset < 0 )
+        {
+            int count = 1;
+            char subdatasetNameKey[80];
+            snprintf(subdatasetNameKey, sizeof(subdatasetNameKey), "SUBDATASET_%d_NAME", count);
+            while(*papszMetadata != NULL)
+            {
+                if (EQUALN(*papszMetadata, subdatasetNameKey, strlen(subdatasetNameKey)))
+                {
+                    memset(&pasDatasetProperties[nInputFiles], 0, sizeof(DatasetProperty));
+                    ppszInputFilenames[nInputFiles++] =
+                            CPLStrdup(*papszMetadata+strlen(subdatasetNameKey)+1);
+                    count++;
+                    snprintf(subdatasetNameKey, sizeof(subdatasetNameKey), "SUBDATASET_%d_NAME", count);
+                }
+                papszMetadata++;
+            }
+        }
+        else
+        {
+            char        subdatasetNameKey[80];
+            const char  *pszSubdatasetName;
+
+            snprintf( subdatasetNameKey, sizeof(subdatasetNameKey),
+                      "SUBDATASET_%d_NAME", nSubdataset );
+            pszSubdatasetName = CSLFetchNameValue( papszMetadata, subdatasetNameKey );
+            if ( pszSubdatasetName )
+            {
+                memset( &pasDatasetProperties[nInputFiles], 0, sizeof(DatasetProperty) );
+                ppszInputFilenames[nInputFiles++] = CPLStrdup( pszSubdatasetName );
+            }
+        }
+        return FALSE;
+    }
+
+    const char* proj = GDALGetProjectionRef(hDS);
+    double* padfGeoTransform = psDatasetProperties->adfGeoTransform;
+    int bGotGeoTransform = GDALGetGeoTransform(hDS, padfGeoTransform) == CE_None;
+    if (bSeparate)
+    {
+        if (bFirst)
+        {
+            bHasGeoTransform = bGotGeoTransform;
+            if (!bHasGeoTransform)
+            {
+                if (bUserExtent)
+                {
+                    CPLError(CE_Warning, CPLE_NotSupported,
+                        "User extent ignored by gdalbuildvrt -separate with ungeoreferenced images.");
+                }
+                if (resolutionStrategy == USER_RESOLUTION)
+                {
+                    CPLError(CE_Warning, CPLE_NotSupported,
+                        "User resolution ignored by gdalbuildvrt -separate with ungeoreferenced images.");
+                }
+            }
+        }
+        else if (bHasGeoTransform != bGotGeoTransform)
+        {
+            CPLError(CE_Warning, CPLE_NotSupported,
+                    "gdalbuildvrt -separate cannot stack ungeoreferenced and georeferenced images. Skipping %s",
+                    dsFileName);
+            return FALSE;
+        }
+        else if (!bHasGeoTransform &&
+                    (nRasterXSize != GDALGetRasterXSize(hDS) ||
+                    nRasterYSize != GDALGetRasterYSize(hDS)))
+        {
+            CPLError(CE_Warning, CPLE_NotSupported,
+                    "gdalbuildvrt -separate cannot stack ungeoreferenced images that have not the same dimensions. Skipping %s",
+                    dsFileName);
+            return FALSE;
+        }
+    }
+    else
+    {
+        if (!bGotGeoTransform)
+        {
+            CPLError(CE_Warning, CPLE_NotSupported,
+                    "gdalbuildvrt does not support ungeoreferenced image. Skipping %s",
+                    dsFileName);
+            return FALSE;
+        }
+        bHasGeoTransform = TRUE;
+    }
+
+    if (bGotGeoTransform)
+    {
+        if (padfGeoTransform[GEOTRSFRM_ROTATION_PARAM1] != 0 ||
+            padfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] != 0)
+        {
+            CPLError(CE_Warning, CPLE_NotSupported,
+                    "gdalbuildvrt does not support rotated geo transforms. Skipping %s",
+                    dsFileName);
+            return FALSE;
+        }
+        if (padfGeoTransform[GEOTRSFRM_NS_RES] >= 0)
+        {
+            CPLError(CE_Warning, CPLE_NotSupported,
+                    "gdalbuildvrt does not support positive NS resolution. Skipping %s",
+                    dsFileName);
+            return FALSE;
+        }
+    }
+
+    psDatasetProperties->nRasterXSize = GDALGetRasterXSize(hDS);
+    psDatasetProperties->nRasterYSize = GDALGetRasterYSize(hDS);
+    if (bFirst && bSeparate && !bGotGeoTransform)
+    {
+        nRasterXSize = GDALGetRasterXSize(hDS);
+        nRasterYSize = GDALGetRasterYSize(hDS);
+    }
+
+    double ds_minX = padfGeoTransform[GEOTRSFRM_TOPLEFT_X];
+    double ds_maxY = padfGeoTransform[GEOTRSFRM_TOPLEFT_Y];
+    double ds_maxX = ds_minX +
+                GDALGetRasterXSize(hDS) *
+                padfGeoTransform[GEOTRSFRM_WE_RES];
+    double ds_minY = ds_maxY +
+                GDALGetRasterYSize(hDS) *
+                padfGeoTransform[GEOTRSFRM_NS_RES];
+
+    GDALGetBlockSize(GDALGetRasterBand( hDS, 1 ),
+                        &psDatasetProperties->nBlockXSize,
+                        &psDatasetProperties->nBlockYSize);
+
+    int _nBands = GDALGetRasterCount(hDS);
+
+    //if provided band list
+    if(nBands != 0 && _nBands != 0 && nMaxBandNo != 0 && _nBands >= nMaxBandNo)
+    {
+        if(_nBands < nMaxBandNo)
+        {
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Skipping %s as it has no such bands", dsFileName);
+            return FALSE;
+        }
+        else
+        {
+            _nBands = nMaxBandNo;
+        }
+    }
+
+    if (_nBands == 0)
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                    "Skipping %s as it has no bands", dsFileName);
+        return FALSE;
+    }
+    else if (_nBands > 1 && bSeparate)
+    {
+        CPLError(CE_Warning, CPLE_AppDefined, "%s has %d bands. Only the first one will "
+                    "be taken into account in the -separate case",
+                    dsFileName, _nBands);
+        _nBands = 1;
+    }
+
+    /* For the -separate case */
+    psDatasetProperties->firstBandType = GDALGetRasterDataType(GDALGetRasterBand(hDS, 1));
+
+    psDatasetProperties->padfNoDataValues = (double*)CPLCalloc(sizeof(double), _nBands);
+    psDatasetProperties->panHasNoData = (int*)CPLCalloc(sizeof(int), _nBands);
+
+    psDatasetProperties->bHasDatasetMask = GDALGetMaskFlags(GDALGetRasterBand(hDS, 1)) == GMF_PER_DATASET;
+    if (psDatasetProperties->bHasDatasetMask)
+        bHasDatasetMask = TRUE;
+    GDALGetBlockSize(GDALGetMaskBand(GDALGetRasterBand( hDS, 1 )),
+                        &psDatasetProperties->nMaskBlockXSize,
+                        &psDatasetProperties->nMaskBlockYSize);
+
+    int j;
+    for(j=0;j<_nBands;j++)
+    {
+        if (nSrcNoDataCount > 0)
+        {
+            psDatasetProperties->panHasNoData[j] = TRUE;
+            if (j < nSrcNoDataCount)
+                psDatasetProperties->padfNoDataValues[j] = padfSrcNoData[j];
+            else
+                psDatasetProperties->padfNoDataValues[j] = padfSrcNoData[nSrcNoDataCount - 1];
+        }
+        else
+        {
+            psDatasetProperties->padfNoDataValues[j]  =
+                GDALGetRasterNoDataValue(GDALGetRasterBand(hDS, j+1),
+                                        &psDatasetProperties->panHasNoData[j]);
+        }
+    }
+
+    if (bFirst)
+    {
+        if (proj)
+            pszProjectionRef = CPLStrdup(proj);
+        if (!bUserExtent)
+        {
+            minX = ds_minX;
+            minY = ds_minY;
+            maxX = ds_maxX;
+            maxY = ds_maxY;
+        }
+
+        //if not provided an explicit band list, take the one of the first dataset
+        if(nBands == 0)
+        {
+            nBands = _nBands;
+            CPLFree(panBandList);
+            panBandList = (int*) CPLMalloc(nBands * sizeof(int));
+            for(j=0;j<nBands;j++)
+            {
+                panBandList[j] = j + 1;
+                if(nMaxBandNo < j + 1)
+                    nMaxBandNo = j + 1;
+            }
+        }
+        if (!bSeparate)
+        {
+            pasBandProperties = (BandProperty*)CPLMalloc(nMaxBandNo*sizeof(BandProperty));
+            for(j=0;j<nMaxBandNo;j++)
+            {
+                GDALRasterBandH hRasterBand = GDALGetRasterBand( hDS, j+1 );
+                pasBandProperties[j].colorInterpretation =
+                        GDALGetRasterColorInterpretation(hRasterBand);
+                pasBandProperties[j].dataType = GDALGetRasterDataType(hRasterBand);
+                if (pasBandProperties[j].colorInterpretation == GCI_PaletteIndex)
+                {
+                    pasBandProperties[j].colorTable =
+                            GDALGetRasterColorTable( hRasterBand );
+                    if (pasBandProperties[j].colorTable)
+                    {
+                        pasBandProperties[j].colorTable =
+                                GDALCloneColorTable(pasBandProperties[j].colorTable);
+                    }
+                }
+                else
+                    pasBandProperties[j].colorTable = NULL;
+
+                if (nVRTNoDataCount > 0)
+                {
+                    pasBandProperties[j].bHasNoData = TRUE;
+                    if (j < nVRTNoDataCount)
+                        pasBandProperties[j].noDataValue = padfVRTNoData[j];
+                    else
+                        pasBandProperties[j].noDataValue = padfVRTNoData[nVRTNoDataCount - 1];
+                }
+                else
+                {
+                    pasBandProperties[j].noDataValue =
+                            GDALGetRasterNoDataValue(hRasterBand, &pasBandProperties[j].bHasNoData);
+                }
+            }
+        }
+    }
+    else
+    {
+        if ((proj != NULL && pszProjectionRef == NULL) ||
+            (proj == NULL && pszProjectionRef != NULL) ||
+            (proj != NULL && pszProjectionRef != NULL && ProjAreEqual(proj, pszProjectionRef) == FALSE))
+        {
+            if (!bAllowProjectionDifference)
+            {
+                CPLError(CE_Warning, CPLE_NotSupported,
+                            "gdalbuildvrt does not support heterogeneous projection. Skipping %s",
+                            dsFileName);
+                return FALSE;
+            }
+        }
+        if (!bSeparate)
+        {
+            if (nMaxBandNo > _nBands)
+            {
+                CPLError(CE_Warning, CPLE_NotSupported,
+                            "gdalbuildvrt does not support heterogeneous band numbers. Skipping %s",
+                        dsFileName);
+                return FALSE;
+            }
+            for(j=0;j<nMaxBandNo;j++)
+            {
+                GDALRasterBandH hRasterBand = GDALGetRasterBand( hDS, j+1 );
+                if (pasBandProperties[j].colorInterpretation != GDALGetRasterColorInterpretation(hRasterBand) ||
+                    pasBandProperties[j].dataType != GDALGetRasterDataType(hRasterBand))
+                {
+                    CPLError(CE_Warning, CPLE_NotSupported,
+                                "gdalbuildvrt does not support heterogeneous band characteristics. Skipping %s",
+                                dsFileName);
+                    return FALSE;
+                }
+                if (pasBandProperties[j].colorTable)
+                {
+                    GDALColorTableH colorTable = GDALGetRasterColorTable( hRasterBand );
+                    int nRefColorEntryCount = GDALGetColorEntryCount(pasBandProperties[j].colorTable);
+                    if (colorTable == NULL ||
+                        GDALGetColorEntryCount(colorTable) != nRefColorEntryCount)
+                    {
+                        CPLError(CE_Warning, CPLE_NotSupported,
+                                    "gdalbuildvrt does not support rasters with different color tables (different number of color table entries). Skipping %s",
+                                dsFileName);
+                        return FALSE;
+                    }
+
+                    /* Check that the palette are the same too */
+                    /* We just warn and still process the file. It is not a technical no-go, but the user */
+                    /* should check that the end result is OK for him. */
+                    for(int i=0;i<nRefColorEntryCount;i++)
+                    {
+                        const GDALColorEntry* psEntry = GDALGetColorEntry(colorTable, i);
+                        const GDALColorEntry* psEntryRef = GDALGetColorEntry(pasBandProperties[j].colorTable, i);
+                        if (psEntry->c1 != psEntryRef->c1 || psEntry->c2 != psEntryRef->c2 ||
+                            psEntry->c3 != psEntryRef->c3 || psEntry->c4 != psEntryRef->c4)
+                        {
+                            static int bFirstWarningPCT = TRUE;
+                            if (bFirstWarningPCT)
+                                CPLError(CE_Warning, CPLE_NotSupported,
+                                        "%s has different values than the first raster for some entries in the color table.\n"
+                                        "The end result might produce weird colors.\n"
+                                        "You're advised to pre-process your rasters with other tools, such as pct2rgb.py or gdal_translate -expand RGB\n"
+                                        "to operate gdalbuildvrt on RGB rasters instead", dsFileName);
+                            else
+                                CPLError(CE_Warning, CPLE_NotSupported,
+                                            "%s has different values than the first raster for some entries in the color table.",
+                                            dsFileName);
+                            bFirstWarningPCT = FALSE;
+                            break;
+                        }
+                    }
+                }
+            }
+
+        }
+        if (!bUserExtent)
+        {
+            if (ds_minX < minX) minX = ds_minX;
+            if (ds_minY < minY) minY = ds_minY;
+            if (ds_maxX > maxX) maxX = ds_maxX;
+            if (ds_maxY > maxY) maxY = ds_maxY;
+        }
+    }
+
+    if (resolutionStrategy == AVERAGE_RESOLUTION)
+    {
+        we_res += padfGeoTransform[GEOTRSFRM_WE_RES];
+        ns_res += padfGeoTransform[GEOTRSFRM_NS_RES];
+    }
+    else if (resolutionStrategy != USER_RESOLUTION)
+    {
+        if (bFirst)
+        {
+            we_res = padfGeoTransform[GEOTRSFRM_WE_RES];
+            ns_res = padfGeoTransform[GEOTRSFRM_NS_RES];
+        }
+        else if (resolutionStrategy == HIGHEST_RESOLUTION)
+        {
+            we_res = MIN(we_res, padfGeoTransform[GEOTRSFRM_WE_RES]);
+            /* Yes : as ns_res is negative, the highest resolution is the max value */
+            ns_res = MAX(ns_res, padfGeoTransform[GEOTRSFRM_NS_RES]);
+        }
+        else
+        {
+            we_res = MAX(we_res, padfGeoTransform[GEOTRSFRM_WE_RES]);
+            /* Yes : as ns_res is negative, the lowest resolution is the min value */
+            ns_res = MIN(ns_res, padfGeoTransform[GEOTRSFRM_NS_RES]);
+        }
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                         CreateVRTSeparate()                          */
+/************************************************************************/
+
+void VRTBuilder::CreateVRTSeparate(VRTDatasetH hVRTDS)
+{
+    int iBand = 1;
+    for(int i=0;i<nInputFiles;i++)
+    {
+        DatasetProperty* psDatasetProperties = &pasDatasetProperties[i];
+
+        if (psDatasetProperties->isFileOK == FALSE)
+            continue;
+
+        double dfSrcXOff, dfSrcYOff, dfSrcXSize, dfSrcYSize,
+               dfDstXOff, dfDstYOff, dfDstXSize, dfDstYSize;
+        if (bHasGeoTransform)
+        {
+            if ( ! GetSrcDstWin(psDatasetProperties,
+                        we_res, ns_res, minX, minY, maxX, maxY,
+                        &dfSrcXOff, &dfSrcYOff, &dfSrcXSize, &dfSrcYSize,
+                        &dfDstXOff, &dfDstYOff, &dfDstXSize, &dfDstYSize) )
+                continue;
+        }
+        else
+        {
+            dfSrcXOff = dfSrcYOff = dfDstXOff = dfDstYOff = 0;
+            dfSrcXSize = dfDstXSize = nRasterXSize;
+            dfSrcYSize = dfDstYSize = nRasterYSize;
+        }
+
+        const char* dsFileName = ppszInputFilenames[i];
+
+        GDALAddBand(hVRTDS, psDatasetProperties->firstBandType, NULL);
+
+        GDALProxyPoolDatasetH hProxyDS =
+            GDALProxyPoolDatasetCreate(dsFileName,
+                                        psDatasetProperties->nRasterXSize,
+                                        psDatasetProperties->nRasterYSize,
+                                        GA_ReadOnly, TRUE, pszProjectionRef,
+                                        psDatasetProperties->adfGeoTransform);
+        GDALProxyPoolDatasetAddSrcBandDescription(hProxyDS,
+                                            psDatasetProperties->firstBandType,
+                                            psDatasetProperties->nBlockXSize,
+                                            psDatasetProperties->nBlockYSize);
+
+        VRTSourcedRasterBandH hVRTBand =
+                (VRTSourcedRasterBandH)GDALGetRasterBand(hVRTDS, iBand);
+
+        if (bHideNoData)
+            GDALSetMetadataItem(hVRTBand,"HideNoDataValue","1",NULL);
+
+        VRTSourcedRasterBand* poVRTBand = (VRTSourcedRasterBand*)hVRTBand;
+
+        VRTSimpleSource* poSimpleSource;
+        if (bAllowSrcNoData && psDatasetProperties->panHasNoData[0])
+        {
+            GDALSetRasterNoDataValue(hVRTBand, psDatasetProperties->padfNoDataValues[0]);
+            poSimpleSource = new VRTComplexSource();
+            poSimpleSource->SetNoDataValue( psDatasetProperties->padfNoDataValues[0] );
+        }
+        else
+            poSimpleSource = new VRTSimpleSource();
+        if( pszResampling )
+            poSimpleSource->SetResampling(pszResampling);
+        poVRTBand->ConfigureSource( poSimpleSource,
+                                    (GDALRasterBand*)GDALGetRasterBand((GDALDatasetH)hProxyDS, 1),
+                                    FALSE,
+                                    dfSrcXOff, dfSrcYOff,
+                                    dfSrcXSize, dfSrcYSize,
+                                    dfDstXOff, dfDstYOff,
+                                    dfDstXSize, dfDstYSize );
+
+        poVRTBand->AddSource( poSimpleSource );
+
+        GDALDereferenceDataset(hProxyDS);
+
+        iBand ++;
+    }
+}
+
+/************************************************************************/
+/*                       CreateVRTNonSeparate()                         */
+/************************************************************************/
+
+void VRTBuilder::CreateVRTNonSeparate(VRTDatasetH hVRTDS)
+{
+    for(int j=0;j<nBands;j++)
+    {
+        GDALRasterBandH hBand;
+        int nSelBand = panBandList[j]-1;
+        GDALAddBand(hVRTDS, pasBandProperties[nSelBand].dataType, NULL);
+        hBand = GDALGetRasterBand(hVRTDS, j+1);
+        GDALSetRasterColorInterpretation(hBand, pasBandProperties[nSelBand].colorInterpretation);
+        if (pasBandProperties[nSelBand].colorInterpretation == GCI_PaletteIndex)
+        {
+            GDALSetRasterColorTable(hBand, pasBandProperties[nSelBand].colorTable);
+        }
+        if (bAllowVRTNoData && pasBandProperties[nSelBand].bHasNoData)
+            GDALSetRasterNoDataValue(hBand, pasBandProperties[nSelBand].noDataValue);
+        if ( bHideNoData )
+            GDALSetMetadataItem(hBand,"HideNoDataValue","1",NULL);
+    }
+
+    VRTSourcedRasterBand* poMaskVRTBand = NULL;
+    if (bAddAlpha)
+    {
+        GDALRasterBandH hBand;
+        GDALAddBand(hVRTDS, GDT_Byte, NULL);
+        hBand = GDALGetRasterBand(hVRTDS, nBands + 1);
+        GDALSetRasterColorInterpretation(hBand, GCI_AlphaBand);
+    }
+    else if (bHasDatasetMask)
+    {
+        GDALCreateDatasetMaskBand(hVRTDS, GMF_PER_DATASET);
+        poMaskVRTBand = (VRTSourcedRasterBand*)GDALGetMaskBand(GDALGetRasterBand(hVRTDS, 1));
+    }
+
+
+    for(int i=0;i<nInputFiles;i++)
+    {
+        DatasetProperty* psDatasetProperties = &pasDatasetProperties[i];
+
+        if (psDatasetProperties->isFileOK == FALSE)
+            continue;
+
+        double dfSrcXOff, dfSrcYOff, dfSrcXSize, dfSrcYSize,
+            dfDstXOff, dfDstYOff, dfDstXSize, dfDstYSize;
+        if ( ! GetSrcDstWin(psDatasetProperties,
+                        we_res, ns_res, minX, minY, maxX, maxY,
+                        &dfSrcXOff, &dfSrcYOff, &dfSrcXSize, &dfSrcYSize,
+                        &dfDstXOff, &dfDstYOff, &dfDstXSize, &dfDstYSize) )
+            continue;
+
+        const char* dsFileName = ppszInputFilenames[i];
+
+        GDALProxyPoolDatasetH hProxyDS =
+            GDALProxyPoolDatasetCreate(dsFileName,
+                                        psDatasetProperties->nRasterXSize,
+                                        psDatasetProperties->nRasterYSize,
+                                        GA_ReadOnly, TRUE, pszProjectionRef,
+                                        psDatasetProperties->adfGeoTransform);
+
+        for(int j=0;j<nMaxBandNo;j++)
+        {
+            GDALProxyPoolDatasetAddSrcBandDescription(hProxyDS,
+                                            pasBandProperties[j].dataType,
+                                            psDatasetProperties->nBlockXSize,
+                                            psDatasetProperties->nBlockYSize);
+        }
+        if (bHasDatasetMask && !bAddAlpha)
+        {
+            ((GDALProxyPoolRasterBand*)((GDALProxyPoolDataset*)hProxyDS)->GetRasterBand(1))->
+                    AddSrcMaskBandDescription  (GDT_Byte,
+                                                psDatasetProperties->nMaskBlockXSize,
+                                                psDatasetProperties->nMaskBlockYSize);
+        }
+
+        for(int j=0;j<nBands;j++)
+        {
+            VRTSourcedRasterBandH hVRTBand =
+                    (VRTSourcedRasterBandH)GDALGetRasterBand(hVRTDS, j + 1);
+
+            /* Place the raster band at the right position in the VRT */
+            int nSelBand = panBandList[j] - 1;
+            VRTSourcedRasterBand* poVRTBand = (VRTSourcedRasterBand*)hVRTBand;
+
+            VRTSimpleSource* poSimpleSource;
+            if (bAllowSrcNoData && psDatasetProperties->panHasNoData[nSelBand])
+            {
+                poSimpleSource = new VRTComplexSource();
+                poSimpleSource->SetNoDataValue( psDatasetProperties->padfNoDataValues[nSelBand] );
+            }
+            else
+                poSimpleSource = new VRTSimpleSource();
+            if( pszResampling )
+                poSimpleSource->SetResampling(pszResampling);
+            poVRTBand->ConfigureSource( poSimpleSource,
+                                        (GDALRasterBand*)GDALGetRasterBand((GDALDatasetH)hProxyDS, nSelBand + 1),
+                                        FALSE,
+                                        dfSrcXOff, dfSrcYOff,
+                                        dfSrcXSize, dfSrcYSize,
+                                        dfDstXOff, dfDstYOff,
+                                        dfDstXSize, dfDstYSize );
+
+            poVRTBand->AddSource( poSimpleSource );
+        }
+
+        if (bAddAlpha)
+        {
+            VRTSourcedRasterBandH hVRTBand =
+                    (VRTSourcedRasterBandH)GDALGetRasterBand(hVRTDS, nBands + 1);
+            /* Little trick : we use an offset of 255 and a scaling of 0, so that in areas covered */
+            /* by the source, the value of the alpha band will be 255, otherwise it will be 0 */
+            ((VRTSourcedRasterBand *) hVRTBand)->AddComplexSource(
+                                            (GDALRasterBand*)GDALGetRasterBand((GDALDatasetH)hProxyDS, 1),
+                                            dfSrcXOff, dfSrcYOff,
+                                            dfSrcXSize, dfSrcYSize,
+                                            dfDstXOff, dfDstYOff,
+                                            dfDstXSize, dfDstYSize,
+                                            255, 0, VRT_NODATA_UNSET);
+        }
+        else if (bHasDatasetMask)
+        {
+            VRTSimpleSource* poSimpleSource = new VRTSimpleSource();
+            if( pszResampling )
+                poSimpleSource->SetResampling(pszResampling);
+            poMaskVRTBand->ConfigureSource( poSimpleSource,
+                                            (GDALRasterBand*)GDALGetRasterBand((GDALDatasetH)hProxyDS, 1),
+                                            TRUE,
+                                            dfSrcXOff, dfSrcYOff,
+                                            dfSrcXSize, dfSrcYSize,
+                                            dfDstXOff, dfDstYOff,
+                                            dfDstXSize, dfDstYSize );
+
+            poMaskVRTBand->AddSource( poSimpleSource );
+        }
+
+        GDALDereferenceDataset(hProxyDS);
+    }
+}
+
+/************************************************************************/
+/*                             Build()                                  */
+/************************************************************************/
+
+GDALDataset* VRTBuilder::Build(GDALProgressFunc pfnProgress, void * pProgressData)
+{
+    if (bHasRunBuild)
+        return NULL;
+    bHasRunBuild = TRUE;
+
+    if( pfnProgress == NULL )
+        pfnProgress = GDALDummyProgress;
+
+    bUserExtent = (minX != 0 || minY != 0 || maxX != 0 || maxY != 0);
+    if (bUserExtent)
+    {
+        if (minX >= maxX || minY >= maxY )
+        {
+            CPLError(CE_Failure, CPLE_IllegalArg, "Invalid user extent");
+            return NULL;
+        }
+    }
+
+    if (resolutionStrategy == USER_RESOLUTION)
+    {
+        if (we_res <= 0 || ns_res <= 0)
+        {
+            CPLError(CE_Failure, CPLE_IllegalArg, "Invalid user resolution");
+            return NULL;
+        }
+
+        /* We work with negative north-south resolution in all the following code */
+        ns_res = -ns_res;
+    }
+    else
+    {
+        we_res = ns_res = 0;
+    }
+
+    pasDatasetProperties =
+            (DatasetProperty*) CPLCalloc(nInputFiles, sizeof(DatasetProperty));
+
+    if (pszSrcNoData != NULL)
+    {
+        if (EQUAL(pszSrcNoData, "none"))
+        {
+            bAllowSrcNoData = FALSE;
+        }
+        else
+        {
+            char **papszTokens = CSLTokenizeString( pszSrcNoData );
+            nSrcNoDataCount = CSLCount(papszTokens);
+            padfSrcNoData = (double *) CPLMalloc(sizeof(double) * nSrcNoDataCount);
+            for(int i=0;i<nSrcNoDataCount;i++)
+            {
+                if( !ArgIsNumeric(papszTokens[i]) && !EQUAL(papszTokens[i], "nan") )
+                {
+                    CPLError(CE_Failure, CPLE_IllegalArg, "Invalid -srcnodata value");
+                    CSLDestroy(papszTokens);
+                    return NULL;
+                }
+                padfSrcNoData[i] = CPLAtofM(papszTokens[i]);
+            }
+            CSLDestroy(papszTokens);
+        }
+    }
+
+    if (pszVRTNoData != NULL)
+    {
+        if (EQUAL(pszVRTNoData, "none"))
+        {
+            bAllowVRTNoData = FALSE;
+        }
+        else
+        {
+            char **papszTokens = CSLTokenizeString( pszVRTNoData );
+            nVRTNoDataCount = CSLCount(papszTokens);
+            padfVRTNoData = (double *) CPLMalloc(sizeof(double) * nVRTNoDataCount);
+            for(int i=0;i<nVRTNoDataCount;i++)
+            {
+                if( !ArgIsNumeric(papszTokens[i]) && !EQUAL(papszTokens[i], "nan") )
+                {
+                    CPLError(CE_Failure, CPLE_IllegalArg, "Invalid -vrtnodata value");
+                    CSLDestroy(papszTokens);
+                    return NULL;
+                }
+                padfVRTNoData[i] = CPLAtofM(papszTokens[i]);
+            }
+            CSLDestroy(papszTokens);
+        }
+    }
+
+    int nCountValid = 0;
+    for(int i=0;i<nInputFiles;i++)
+    {
+        const char* dsFileName = ppszInputFilenames[i];
+
+        if (!pfnProgress( 1.0 * (i+1) / nInputFiles, NULL, pProgressData))
+        {
+            return NULL;
+        }
+
+        GDALDatasetH hDS =
+            (pahSrcDS) ? pahSrcDS[i] :
+                         GDALOpen(ppszInputFilenames[i], GA_ReadOnly );
+        pasDatasetProperties[i].isFileOK = FALSE;
+
+        if (hDS)
+        {
+            if (AnalyseRaster( hDS, &pasDatasetProperties[i] ))
+            {
+                pasDatasetProperties[i].isFileOK = TRUE;
+                nCountValid ++;
+                bFirst = FALSE;
+            }
+            if( pahSrcDS == NULL )
+                GDALClose(hDS);
+        }
+        else
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Can't open %s. Skipping it", dsFileName);
+        }
+    }
+
+    if (nCountValid == 0)
+        return NULL;
+
+    if (bHasGeoTransform)
+    {
+        if (resolutionStrategy == AVERAGE_RESOLUTION)
+        {
+            we_res /= nCountValid;
+            ns_res /= nCountValid;
+        }
+
+        if ( bTargetAlignedPixels )
+        {
+            minX = floor(minX / we_res) * we_res;
+            maxX = ceil(maxX / we_res) * we_res;
+            minY = floor(minY / -ns_res) * -ns_res;
+            maxY = ceil(maxY / -ns_res) * -ns_res;
+        }
+
+        nRasterXSize = (int)(0.5 + (maxX - minX) / we_res);
+        nRasterYSize = (int)(0.5 + (maxY - minY) / -ns_res);
+    }
+
+    if (nRasterXSize == 0 || nRasterYSize == 0)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Computed VRT dimension is invalid. You've probably "
+                  "specified inappropriate resolution.");
+        return NULL;
+    }
+
+    VRTDatasetH hVRTDS = VRTCreate(nRasterXSize, nRasterYSize);
+    GDALSetDescription(hVRTDS, pszOutputFilename);
+
+    if( pszOutputSRS )
+    {
+        GDALSetProjection(hVRTDS, pszOutputSRS);
+    }
+    else if (pszProjectionRef)
+    {
+        GDALSetProjection(hVRTDS, pszProjectionRef);
+    }
+
+    if (bHasGeoTransform)
+    {
+        double adfGeoTransform[6];
+        adfGeoTransform[GEOTRSFRM_TOPLEFT_X] = minX;
+        adfGeoTransform[GEOTRSFRM_WE_RES] = we_res;
+        adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1] = 0;
+        adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] = maxY;
+        adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] = 0;
+        adfGeoTransform[GEOTRSFRM_NS_RES] = ns_res;
+        GDALSetGeoTransform(hVRTDS, adfGeoTransform);
+    }
+
+    if (bSeparate)
+    {
+        CreateVRTSeparate(hVRTDS);
+    }
+    else
+    {
+        CreateVRTNonSeparate(hVRTDS);
+    }
+
+    return (GDALDataset*)hVRTDS;
+}
+
+/************************************************************************/
+/*                        add_file_to_list()                            */
+/************************************************************************/
+
+static bool add_file_to_list(const char* filename, const char* tile_index,
+                             int* pnInputFiles, char*** pppszInputFilenames)
+{
+
+    int nInputFiles = *pnInputFiles;
+    char** ppszInputFilenames = *pppszInputFilenames;
+
+    if (EQUAL(CPLGetExtension(filename), "SHP"))
+    {
+        OGRRegisterAll();
+
+        /* Handle gdaltindex Shapefile as a special case */
+        OGRDataSourceH hDS = OGROpen( filename, FALSE, NULL );
+        if( hDS  == NULL )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Unable to open shapefile `%s'.",
+                      filename );
+            return false;
+        }
+
+        OGRLayerH hLayer = OGR_DS_GetLayer(hDS, 0);
+
+        OGRFeatureDefnH hFDefn = OGR_L_GetLayerDefn(hLayer);
+
+        int ti_field;
+        for( ti_field = 0; ti_field < OGR_FD_GetFieldCount(hFDefn); ti_field++ )
+        {
+            OGRFieldDefnH hFieldDefn = OGR_FD_GetFieldDefn( hFDefn, ti_field );
+            const char* pszName = OGR_Fld_GetNameRef(hFieldDefn);
+
+            if (strcmp(pszName, "LOCATION") == 0 && strcmp("LOCATION", tile_index) != 0 )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "This shapefile seems to be a tile index of "
+                        "OGR features and not GDAL products.");
+            }
+            if( strcmp(pszName, tile_index) == 0 )
+                break;
+        }
+
+        if( ti_field == OGR_FD_GetFieldCount(hFDefn) )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Unable to find field `%s' in DBF file `%s'.",
+                     tile_index, filename );
+            return false;
+        }
+
+        /* Load in memory existing file names in SHP */
+        int nTileIndexFiles = (int)OGR_L_GetFeatureCount(hLayer, TRUE);
+        if (nTileIndexFiles == 0)
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Tile index %s is empty. Skipping it.\n", filename);
+            return true;
+        }
+
+        ppszInputFilenames = (char**)CPLRealloc(ppszInputFilenames,
+                              sizeof(char*) * (nInputFiles+nTileIndexFiles+1));
+        for(int j=0;j<nTileIndexFiles;j++)
+        {
+            OGRFeatureH hFeat = OGR_L_GetNextFeature(hLayer);
+            ppszInputFilenames[nInputFiles++] =
+                    CPLStrdup(OGR_F_GetFieldAsString(hFeat, ti_field ));
+            OGR_F_Destroy(hFeat);
+        }
+        ppszInputFilenames[nInputFiles] = NULL;
+
+        OGR_DS_Destroy( hDS );
+    }
+    else
+    {
+        ppszInputFilenames = (char**)CPLRealloc(ppszInputFilenames,
+                                                 sizeof(char*) * (nInputFiles+1+1));
+        ppszInputFilenames[nInputFiles++] = CPLStrdup(filename);
+        ppszInputFilenames[nInputFiles] = NULL;
+    }
+
+    *pnInputFiles = nInputFiles;
+    *pppszInputFilenames = ppszInputFilenames;
+    return true;
+}
+
+/************************************************************************/
+/*                        GDALBuildVRTOptions                           */
+/************************************************************************/
+
+/** Options for use with GDALBuildVRT(). GDALBuildVRTOptions* must be allocated and
+ * freed with GDALBuildVRTOptionsNew() and GDALBuildVRTOptionsFree() respectively.
+ */
+struct GDALBuildVRTOptions
+{
+    char *pszResolution;
+    int bSeparate;
+    int bAllowProjectionDifference;
+    double we_res;
+    double ns_res;
+    int bTargetAlignedPixels;
+    double xmin;
+    double ymin;
+    double xmax;
+    double ymax;
+    int bAddAlpha;
+    int bHideNoData;
+    int nSubdataset;
+    char* pszSrcNoData;
+    char* pszVRTNoData;
+    char* pszOutputSRS;
+    int *panBandList;
+    int nBandCount;
+    int nMaxBandNo;
+    char* pszResampling;
+
+    /*! allow or suppress progress monitor and other non-error output */
+    int bQuiet;
+
+    /*! the progress function to use */
+    GDALProgressFunc pfnProgress;
+
+    /*! pointer to the progress data variable */
+    void *pProgressData;
+};
+
+/************************************************************************/
+/*                        GDALBuildVRTOptionsClone()                   */
+/************************************************************************/
+
+static
+GDALBuildVRTOptions* GDALBuildVRTOptionsClone(const GDALBuildVRTOptions *psOptionsIn)
+{
+    GDALBuildVRTOptions* psOptions = static_cast<GDALBuildVRTOptions*>(
+        CPLMalloc(sizeof(GDALBuildVRTOptions)) );
+    memcpy(psOptions, psOptionsIn, sizeof(GDALBuildVRTOptions));
+    if( psOptionsIn->pszResolution ) psOptions->pszResolution = CPLStrdup(psOptionsIn->pszResolution);
+    if( psOptionsIn->pszSrcNoData ) psOptions->pszSrcNoData = CPLStrdup(psOptionsIn->pszSrcNoData);
+    if( psOptionsIn->pszVRTNoData ) psOptions->pszVRTNoData = CPLStrdup(psOptionsIn->pszVRTNoData);
+    if( psOptionsIn->pszOutputSRS ) psOptions->pszOutputSRS = CPLStrdup(psOptionsIn->pszOutputSRS);
+    if( psOptionsIn->pszResampling ) psOptions->pszResampling = CPLStrdup(psOptionsIn->pszResampling);
+    if( psOptionsIn->panBandList )
+    {
+        psOptions->panBandList = static_cast<int*>(CPLMalloc(sizeof(int) * psOptionsIn->nBandCount));
+        memcpy(psOptions->panBandList, psOptionsIn->panBandList, sizeof(int) * psOptionsIn->nBandCount);
+    }
+    return psOptions;
+}
+
+/************************************************************************/
+/*                           GDALBuildVRT()                             */
+/************************************************************************/
+
+/**
+ * Build a VRT from a list of datasets.
+ *
+ * This is the equivalent of the <a href="gdalbuildvrt.html">gdalbuildvrt</a> utility.
+ *
+ * GDALBuildVRTOptions* must be allocated and freed with GDALBuildVRTOptionsNew()
+ * and GDALBuildVRTOptionsFree() respectively.
+ * pahSrcDS and papszSrcDSNames cannot be used at the same time.
+ *
+ * @param pszDest the destination dataset path.
+ * @param nSrcCount the number of input datasets.
+ * @param pahSrcDS the list of input datasets (or NULL, exclusive with papszSrcDSNames)
+ * @param papszSrcDSNames the list of input dataset names (or NULL, exclusive with pahSrcDS)
+ * @param psOptionsIn the options struct returned by GDALBuildVRTOptionsNew() or NULL.
+ * @param pbUsageError the pointer to int variable to determine any usage error has occurred.
+ * @return the output dataset (new dataset that must be closed using GDALClose()) or NULL in case of error.
+ *
+ * @since GDAL 2.1
+ */
+
+GDALDatasetH GDALBuildVRT( const char *pszDest,
+                           int nSrcCount, GDALDatasetH *pahSrcDS, const char* const* papszSrcDSNames,
+                           const GDALBuildVRTOptions *psOptionsIn, int *pbUsageError )
+{
+    if( pszDest == NULL )
+        pszDest = "";
+
+    if( nSrcCount == 0 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "No input dataset specified.");
+
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        return NULL;
+    }
+
+    GDALBuildVRTOptions* psOptions =
+        (psOptionsIn) ? GDALBuildVRTOptionsClone(psOptionsIn) :
+                        GDALBuildVRTOptionsNew(NULL, NULL);
+
+    if (psOptions->we_res != 0 && psOptions->ns_res != 0 &&
+        psOptions->pszResolution != NULL && !EQUAL(psOptions->pszResolution, "user"))
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "-tr option is not compatible with -resolution %s", psOptions->pszResolution);
+        if( pbUsageError )
+            *pbUsageError = TRUE;
+        GDALBuildVRTOptionsFree(psOptions);
+        return NULL;
+    }
+
+    if (psOptions->bTargetAlignedPixels && psOptions->we_res == 0 && psOptions->ns_res == 0)
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "-tap option cannot be used without using -tr");
+        if( pbUsageError )
+            *pbUsageError = TRUE;
+        GDALBuildVRTOptionsFree(psOptions);
+        return NULL;
+    }
+
+    if (psOptions->bAddAlpha && psOptions->bSeparate)
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "-addalpha option is not compatible with -separate.");
+        if( pbUsageError )
+            *pbUsageError = TRUE;
+        GDALBuildVRTOptionsFree(psOptions);
+        return NULL;
+    }
+
+    ResolutionStrategy eStrategy = AVERAGE_RESOLUTION;
+    if ( psOptions->pszResolution == NULL || EQUAL(psOptions->pszResolution, "user") )
+    {
+        if ( psOptions->we_res != 0 || psOptions->ns_res != 0)
+            eStrategy = USER_RESOLUTION;
+        else if ( psOptions->pszResolution != NULL && EQUAL(psOptions->pszResolution, "user") )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                      "-tr option must be used with -resolution user.");
+            if( pbUsageError )
+                *pbUsageError = TRUE;
+            GDALBuildVRTOptionsFree(psOptions);
+            return NULL;
+        }
+    }
+    else if ( EQUAL(psOptions->pszResolution, "average") )
+        eStrategy = AVERAGE_RESOLUTION;
+    else if ( EQUAL(psOptions->pszResolution, "highest") )
+        eStrategy = HIGHEST_RESOLUTION;
+    else if ( EQUAL(psOptions->pszResolution, "lowest") )
+        eStrategy = LOWEST_RESOLUTION;
+
+    /* If -srcnodata is specified, use it as the -vrtnodata if the latter is not */
+    /* specified */
+    if (psOptions->pszSrcNoData != NULL && psOptions->pszVRTNoData == NULL)
+        psOptions->pszVRTNoData = CPLStrdup(psOptions->pszSrcNoData);
+
+    VRTBuilder oBuilder(pszDest, nSrcCount, papszSrcDSNames, pahSrcDS,
+                        psOptions->panBandList, psOptions->nBandCount, psOptions->nMaxBandNo,
+                        eStrategy, psOptions->we_res, psOptions->ns_res, psOptions->bTargetAlignedPixels,
+                        psOptions->xmin, psOptions->ymin, psOptions->xmax, psOptions->ymax,
+                        psOptions->bSeparate, psOptions->bAllowProjectionDifference,
+                        psOptions->bAddAlpha, psOptions->bHideNoData, psOptions->nSubdataset,
+                        psOptions->pszSrcNoData, psOptions->pszVRTNoData,
+                        psOptions->pszOutputSRS, psOptions->pszResampling);
+
+    GDALDatasetH hDstDS =
+        (GDALDatasetH)oBuilder.Build(psOptions->pfnProgress, psOptions->pProgressData);
+
+    GDALBuildVRTOptionsFree(psOptions);
+
+    return hDstDS;
+}
+
+/************************************************************************/
+/*                             SanitizeSRS                              */
+/************************************************************************/
+
+static char *SanitizeSRS( const char *pszUserInput )
+
+{
+    OGRSpatialReferenceH hSRS;
+    char *pszResult = NULL;
+
+    CPLErrorReset();
+
+    hSRS = OSRNewSpatialReference( NULL );
+    if( OSRSetFromUserInput( hSRS, pszUserInput ) == OGRERR_NONE )
+        OSRExportToWkt( hSRS, &pszResult );
+    else
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Translating SRS failed:\n%s",
+                  pszUserInput );
+    }
+
+    OSRDestroySpatialReference( hSRS );
+
+    return pszResult;
+}
+
+/************************************************************************/
+/*                             GDALBuildVRTOptionsNew()                  */
+/************************************************************************/
+
+/**
+ * Allocates a GDALBuildVRTOptions struct.
+ *
+ * @param papszArgv NULL terminated list of options (potentially including filename and open options too), or NULL.
+ *                  The accepted options are the ones of the <a href="gdalbuildvrt.html">gdalbuildvrt</a> utility.
+ * @param psOptionsForBinary (output) may be NULL (and should generally be NULL),
+ *                           otherwise (gdal_translate_bin.cpp use case) must be allocated with
+ *                           GDALBuildVRTOptionsForBinaryNew() prior to this function. Will be
+ *                           filled with potentially present filename, open options,...
+ * @return pointer to the allocated GDALBuildVRTOptions struct. Must be freed with GDALBuildVRTOptionsFree().
+ *
+ * @since GDAL 2.1
+ */
+
+GDALBuildVRTOptions *GDALBuildVRTOptionsNew(char** papszArgv,
+                                            GDALBuildVRTOptionsForBinary* psOptionsForBinary)
+{
+    GDALBuildVRTOptions *psOptions = static_cast<GDALBuildVRTOptions *>(
+        CPLCalloc(1, sizeof(GDALBuildVRTOptions)) );
+
+    const char *tile_index = "location";
+
+    psOptions->nSubdataset = -1;
+    psOptions->bQuiet = TRUE;
+    psOptions->pfnProgress = GDALDummyProgress;
+    psOptions->pProgressData = NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Parse arguments.                                                */
+/* -------------------------------------------------------------------- */
+    int argc = CSLCount(papszArgv);
+    for( int iArg = 0; iArg < argc; iArg++ )
+    {
+        if( EQUAL(papszArgv[iArg],"-tileindex") && iArg + 1 < argc )
+        {
+            tile_index = papszArgv[++iArg];
+        }
+        else if( EQUAL(papszArgv[iArg],"-resolution") && iArg + 1 < argc )
+        {
+            CPLFree(psOptions->pszResolution);
+            psOptions->pszResolution = CPLStrdup(papszArgv[++iArg]);
+            if( !EQUAL(psOptions->pszResolution, "user") &&
+                !EQUAL(psOptions->pszResolution, "average") &&
+                !EQUAL(psOptions->pszResolution, "highest") &&
+                !EQUAL(psOptions->pszResolution, "lowest") )
+            {
+                CPLError(CE_Failure, CPLE_IllegalArg,
+                         "Illegal resolution value (%s).", psOptions->pszResolution );
+                GDALBuildVRTOptionsFree(psOptions);
+                return NULL;
+            }
+        }
+        else if( EQUAL(papszArgv[iArg],"-input_file_list") && iArg + 1 < argc )
+        {
+            ++iArg;
+            if( psOptionsForBinary )
+            {
+                const char* input_file_list = papszArgv[iArg];
+                VSILFILE* f = VSIFOpenL(input_file_list, "r");
+                if (f)
+                {
+                    while(1)
+                    {
+                        const char* filename = CPLReadLineL(f);
+                        if (filename == NULL)
+                            break;
+                        if( !add_file_to_list(filename, tile_index,
+                                         &psOptionsForBinary->nSrcFiles,
+                                         &psOptionsForBinary->papszSrcFiles) )
+                        {
+                            VSIFCloseL(f);
+                            GDALBuildVRTOptionsFree(psOptions);
+                            return NULL;
+                        }
+                    }
+                    VSIFCloseL(f);
+                }
+            }
+            else
+            {
+                CPLError(CE_Failure, CPLE_NotSupported,
+                         "-input_file_list not supported in non binary mode");
+            }
+        }
+        else if ( EQUAL(papszArgv[iArg],"-separate") )
+        {
+            psOptions->bSeparate = TRUE;
+        }
+        else if ( EQUAL(papszArgv[iArg],"-allow_projection_difference") )
+        {
+            psOptions->bAllowProjectionDifference = TRUE;
+        }
+        else if( EQUAL(papszArgv[iArg], "-sd") && iArg + 1 < argc )
+        {
+            psOptions->nSubdataset = atoi(papszArgv[++iArg]);
+        }
+        /* Alternate syntax for output file */
+        else if( EQUAL(papszArgv[iArg],"-o") && iArg + 1 < argc )
+        {
+            ++iArg;
+            if( psOptionsForBinary )
+            {
+                CPLFree(psOptionsForBinary->pszDstFilename);
+                psOptionsForBinary->pszDstFilename = CPLStrdup(papszArgv[iArg]);
+            }
+            else
+            {
+                CPLError(CE_Failure, CPLE_NotSupported,
+                         "-o not supported in non binary mode");
+            }
+        }
+        else if ( EQUAL(papszArgv[iArg],"-q") || EQUAL(papszArgv[iArg],"-quiet") )
+        {
+            if( psOptionsForBinary )
+            {
+                psOptionsForBinary->bQuiet = TRUE;
+            }
+        }
+        else if ( EQUAL(papszArgv[iArg],"-tr") && iArg + 2 < argc )
+        {
+            psOptions->we_res = CPLAtofM(papszArgv[++iArg]);
+            psOptions->ns_res = CPLAtofM(papszArgv[++iArg]);
+        }
+        else if( EQUAL(papszArgv[iArg],"-tap") )
+        {
+            psOptions->bTargetAlignedPixels = TRUE;
+        }
+        else if ( EQUAL(papszArgv[iArg],"-te") && iArg + 4 < argc )
+        {
+            psOptions->xmin = CPLAtofM(papszArgv[++iArg]);
+            psOptions->ymin = CPLAtofM(papszArgv[++iArg]);
+            psOptions->xmax = CPLAtofM(papszArgv[++iArg]);
+            psOptions->ymax = CPLAtofM(papszArgv[++iArg]);
+        }
+        else if ( EQUAL(papszArgv[iArg],"-addalpha") )
+        {
+            psOptions->bAddAlpha = TRUE;
+        }
+        else if( EQUAL(papszArgv[iArg],"-b") && iArg + 1 < argc )
+        {
+            const char* pszBand = papszArgv[++iArg];
+            int nBand = atoi(pszBand);
+            if( nBand < 1 )
+            {
+                CPLError(CE_Failure, CPLE_IllegalArg,
+                         "Illegal band number (%s).", papszArgv[iArg] );
+                GDALBuildVRTOptionsFree(psOptions);
+                return NULL;
+            }
+
+            if(nBand > psOptions->nMaxBandNo)
+            {
+                psOptions->nMaxBandNo = nBand;
+            }
+
+            psOptions->nBandCount++;
+            psOptions->panBandList = (int *)
+                CPLRealloc(psOptions->panBandList, sizeof(int) * psOptions->nBandCount);
+            psOptions->panBandList[psOptions->nBandCount-1] = nBand;
+        }
+        else if ( EQUAL(papszArgv[iArg],"-hidenodata") )
+        {
+            psOptions->bHideNoData = TRUE;
+        }
+        else if ( EQUAL(papszArgv[iArg],"-overwrite") )
+        {
+            if( psOptionsForBinary )
+                psOptionsForBinary->bOverwrite = TRUE;
+        }
+        else if ( EQUAL(papszArgv[iArg],"-srcnodata") && iArg + 1 < argc )
+        {
+            CPLFree(psOptions->pszSrcNoData);
+            psOptions->pszSrcNoData = CPLStrdup(papszArgv[++iArg]);
+        }
+        else if ( EQUAL(papszArgv[iArg],"-vrtnodata") && iArg + 1 < argc )
+        {
+            CPLFree(psOptions->pszVRTNoData);
+            psOptions->pszVRTNoData = CPLStrdup(papszArgv[++iArg]);
+        }
+        else if( EQUAL(papszArgv[iArg],"-a_srs") && iArg + 1 < argc )
+        {
+            char *pszSRS = SanitizeSRS(papszArgv[++iArg]);
+            if(pszSRS == NULL)
+            {
+                GDALBuildVRTOptionsFree(psOptions);
+                return NULL;
+            }
+            CPLFree(psOptions->pszOutputSRS);
+            psOptions->pszOutputSRS = pszSRS;
+        }
+        else if( EQUAL(papszArgv[iArg],"-r") && iArg + 1 < argc )
+        {
+            CPLFree(psOptions->pszResampling);
+            psOptions->pszResampling = CPLStrdup(papszArgv[++iArg]);
+        }
+        else if( papszArgv[iArg][0] == '-' )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unknown option name '%s'", papszArgv[iArg]);
+            GDALBuildVRTOptionsFree(psOptions);
+            return NULL;
+        }
+        else
+        {
+            if( psOptionsForBinary )
+            {
+                if( psOptionsForBinary->pszDstFilename == NULL )
+                    psOptionsForBinary->pszDstFilename = CPLStrdup(papszArgv[iArg]);
+                else
+                {
+                    if( !add_file_to_list(papszArgv[iArg], tile_index,
+                                          &psOptionsForBinary->nSrcFiles,
+                                          &psOptionsForBinary->papszSrcFiles) )
+                    {
+                        GDALBuildVRTOptionsFree(psOptions);
+                        return NULL;
+                    }
+                }
+            }
+        }
+    }
+
+    return psOptions;
+}
+
+/************************************************************************/
+/*                        GDALBuildVRTOptionsFree()                     */
+/************************************************************************/
+
+/**
+ * Frees the GDALBuildVRTOptions struct.
+ *
+ * @param psOptions the options struct for GDALBuildVRT().
+ *
+ * @since GDAL 2.1
+ */
+
+void GDALBuildVRTOptionsFree( GDALBuildVRTOptions *psOptions )
+{
+    if( psOptions )
+    {
+        CPLFree( psOptions->pszResolution );
+        CPLFree( psOptions->pszSrcNoData );
+        CPLFree( psOptions->pszVRTNoData );
+        CPLFree( psOptions->pszOutputSRS );
+        CPLFree( psOptions->panBandList );
+        CPLFree( psOptions->pszResampling );
+    }
+
+    CPLFree(psOptions);
+}
+
+/************************************************************************/
+/*                 GDALBuildVRTOptionsSetProgress()                    */
+/************************************************************************/
+
+/**
+ * Set a progress function.
+ *
+ * @param psOptions the options struct for GDALBuildVRT().
+ * @param pfnProgress the progress callback.
+ * @param pProgressData the user data for the progress callback.
+ *
+ * @since GDAL 2.1
+ */
+
+void GDALBuildVRTOptionsSetProgress( GDALBuildVRTOptions *psOptions,
+                                      GDALProgressFunc pfnProgress, void *pProgressData )
+{
+    psOptions->pfnProgress = pfnProgress ? pfnProgress : GDALDummyProgress;
+    psOptions->pProgressData = pProgressData;
+    if( pfnProgress == GDALTermProgress )
+        psOptions->bQuiet = FALSE;
+}
diff --git a/apps/gdaldem.cpp b/apps/gdaldem.cpp
deleted file mode 100644
index 8c06acc..0000000
--- a/apps/gdaldem.cpp
+++ /dev/null
@@ -1,2802 +0,0 @@
-/******************************************************************************
- * $Id: gdaldem.cpp 30887 2015-10-07 15:52:20Z rouault $
- *
- * Project:  GDAL DEM Utilities
- * Purpose:  
- * Authors:  Matthew Perry, perrygeo at gmail.com
- *           Even Rouault, even dot rouault at mines dash paris dot org
- *           Howard Butler, hobu.inc at gmail.com
- *           Chris Yesson, chris dot yesson at ioz dot ac dot uk
- *
- ******************************************************************************
- * Copyright (c) 2006, 2009 Matthew Perry 
- * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
- * Portions derived from GRASS 4.1 (public domain) See 
- * http://trac.osgeo.org/gdal/ticket/2975 for more information regarding 
- * history of this code
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************
- *
- * Slope and aspect calculations based on original method for GRASS GIS 4.1
- * by Michael Shapiro, U.S.Army Construction Engineering Research Laboratory
- *    Olga Waupotitsch, U.S.Army Construction Engineering Research Laboratory
- *    Marjorie Larson, U.S.Army Construction Engineering Research Laboratory
- * as found in GRASS's r.slope.aspect module.
- *
- * Horn's formula is used to find the first order derivatives in x and y directions
- * for slope and aspect calculations: Horn, B. K. P. (1981).
- * "Hill Shading and the Reflectance Map", Proceedings of the IEEE, 69(1):14-47. 
- *
- * Other reference :
- * Burrough, P.A. and McDonell, R.A., 1998. Principles of Geographical Information
- * Systems. p. 190.
- *
- * Shaded relief based on original method for GRASS GIS 4.1 by Jim Westervelt,
- * U.S. Army Construction Engineering Research Laboratory
- * as found in GRASS's r.shaded.relief (formerly shade.rel.sh) module.
- * ref: "r.mapcalc: An Algebra for GIS and Image Processing",
- * by Michael Shapiro and Jim Westervelt, U.S. Army Construction Engineering
- * Research Laboratory (March/1991)
- *
- * Color table of named colors and lookup code derived from src/libes/gis/named_colr.c
- * of GRASS 4.1
- *
- * TRI - Terrain Ruggedness Index is as descibed in Wilson et al (2007)
- * this is based on the method of Valentine et al. (2004)  
- * 
- * TPI - Topographic Position Index follows the description in Wilson et al (2007), following Weiss (2001)
- * The radius is fixed at 1 cell width/height
- * 
- * Roughness - follows the definition in Wilson et al. (2007), which follows Dartnell (2000)
- *
- * References for TRI/TPI/Roughness:
- * Dartnell, P. 2000. Applying Remote Sensing Techniques to map Seafloor 
- *  Geology/Habitat Relationships. Masters Thesis, San Francisco State 
- *  University, pp. 108.
- * Valentine, P. C., S. J. Fuller, L. A. Scully. 2004. Terrain Ruggedness 
- *  Analysis and Distribution of Boulder Ridges in the Stellwagen Bank National
- *  Marine Sanctuary Region (poster). Galway, Ireland: 5th International 
- *  Symposium on Marine Geological and Biological Habitat Mapping (GeoHAB), 
- *  May 2004.
- * Weiss, A. D. 2001. Topographic Positions and Landforms Analysis (poster), 
- *  ESRI International User Conference, July 2001. San Diego, CA: ESRI.
- * Wilson, M. F. J.; O'Connell, B.; Brown, C.; Guinan, J. C. & Grehan, A. J. 
- *  Multiscale terrain analysis of multibeam bathymetry data for habitat mapping
- *  on the continental slope Marine Geodesy, 2007, 30, 3-35
- ****************************************************************************/
-
-#include "cpl_vsi.h"
-#include <stdlib.h>
-#include <math.h>
-
-#include "cpl_conv.h"
-#include "cpl_string.h"
-#include "gdal.h"
-#include "gdal_priv.h"
-#include "commonutils.h"
-
-CPL_CVSID("$Id: gdaldem.cpp 30887 2015-10-07 15:52:20Z rouault $");
-
-#ifndef M_PI
-# define M_PI  3.1415926535897932384626433832795
-#endif
-
-#define INTERPOL(a,b) ((bSrcHasNoData && (ARE_REAL_EQUAL(a, fSrcNoDataValue) || ARE_REAL_EQUAL(b, fSrcNoDataValue))) ? fSrcNoDataValue : 2 * (a) - (b))
-
-/************************************************************************/
-/*                               Usage()                                */
-/************************************************************************/
-
-static void Usage(const char* pszErrorMsg = NULL)
-
-{
-    printf( " Usage: \n"
-            " - To generate a shaded relief map from any GDAL-supported elevation raster : \n\n"
-            "     gdaldem hillshade input_dem output_hillshade \n"
-            "                 [-z ZFactor (default=1)] [-s scale* (default=1)] \n"
-            "                 [-az Azimuth (default=315)] [-alt Altitude (default=45)]\n"
-            "                 [-alg ZevenbergenThorne] [-combined]\n"
-            "                 [-compute_edges] [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
-            "\n"
-            " - To generates a slope map from any GDAL-supported elevation raster :\n\n"
-            "     gdaldem slope input_dem output_slope_map \n"
-            "                 [-p use percent slope (default=degrees)] [-s scale* (default=1)]\n"
-            "                 [-alg ZevenbergenThorne]\n"
-            "                 [-compute_edges] [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
-            "\n"
-            " - To generate an aspect map from any GDAL-supported elevation raster\n"
-            "   Outputs a 32-bit float tiff with pixel values from 0-360 indicating azimuth :\n\n"
-            "     gdaldem aspect input_dem output_aspect_map \n"
-            "                 [-trigonometric] [-zero_for_flat]\n"
-            "                 [-alg ZevenbergenThorne]\n"
-            "                 [-compute_edges] [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
-            "\n"
-            " - To generate a color relief map from any GDAL-supported elevation raster\n"
-            "     gdaldem color-relief input_dem color_text_file output_color_relief_map\n"
-            "                 [-alpha] [-exact_color_entry | -nearest_color_entry]\n"
-            "                 [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
-            "     where color_text_file contains lines of the format \"elevation_value red green blue\"\n"
-            "\n"
-            " - To generate a Terrain Ruggedness Index (TRI) map from any GDAL-supported elevation raster\n"
-            "     gdaldem TRI input_dem output_TRI_map\n"
-            "                 [-compute_edges] [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
-            "\n"
-            " - To generate a Topographic Position Index (TPI) map from any GDAL-supported elevation raster\n"
-            "     gdaldem TPI input_dem output_TPI_map\n"
-            "                 [-compute_edges] [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
-            "\n"
-            " - To generate a roughness map from any GDAL-supported elevation raster\n"
-            "     gdaldem roughness input_dem output_roughness_map\n"
-            "                 [-compute_edges] [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
-            "\n"
-            " Notes : \n"
-            "   Scale is the ratio of vertical units to horizontal\n"
-            "    for Feet:Latlong use scale=370400, for Meters:LatLong use scale=111120 \n\n");
-
-    if( pszErrorMsg != NULL )
-        fprintf(stderr, "\nFAILURE: %s\n", pszErrorMsg);
-
-    exit( 1 );
-}
-
-/************************************************************************/
-/*                          ComputeVal()                                */
-/************************************************************************/
-
-typedef float (*GDALGeneric3x3ProcessingAlg) (float* pafWindow, float fDstNoDataValue, void* pData);
-
-static float ComputeVal(int bSrcHasNoData, float fSrcNoDataValue,
-                        int bIsSrcNoDataNan,
-                        float* afWin, float fDstNoDataValue,
-                        GDALGeneric3x3ProcessingAlg pfnAlg,
-                        void* pData,
-                        int bComputeAtEdges)
-{
-    if (bSrcHasNoData &&
-            ((!bIsSrcNoDataNan && ARE_REAL_EQUAL(afWin[4], fSrcNoDataValue)) ||
-             (bIsSrcNoDataNan && CPLIsNan(afWin[4]))))
-    {
-        return fDstNoDataValue;
-    }
-    else if (bSrcHasNoData)
-    {
-        int k;
-        for(k=0;k<9;k++)
-        {
-            if ((!bIsSrcNoDataNan && ARE_REAL_EQUAL(afWin[k], fSrcNoDataValue)) ||
-                (bIsSrcNoDataNan && CPLIsNan(afWin[k])))
-            {
-                if (bComputeAtEdges)
-                    afWin[k] = afWin[4];
-                else
-                    return fDstNoDataValue;
-            }
-        }
-    }
-
-    return pfnAlg(afWin, fDstNoDataValue, pData);
-}
-
-/************************************************************************/
-/*                  GDALGeneric3x3Processing()                          */
-/************************************************************************/
-
-CPLErr GDALGeneric3x3Processing  ( GDALRasterBandH hSrcBand,
-                                   GDALRasterBandH hDstBand,
-                                   GDALGeneric3x3ProcessingAlg pfnAlg,
-                                   void* pData,
-                                   int bComputeAtEdges,
-                                   GDALProgressFunc pfnProgress,
-                                   void * pProgressData)
-{
-    CPLErr eErr;
-    float *pafThreeLineWin; /* 3 line rotating source buffer */
-    float *pafOutputBuf;     /* 1 line destination buffer */
-    int i, j;
-
-    int bSrcHasNoData, bDstHasNoData;
-    float fSrcNoDataValue = 0.0, fDstNoDataValue = 0.0;
-
-    int nXSize = GDALGetRasterBandXSize(hSrcBand);
-    int nYSize = GDALGetRasterBandYSize(hSrcBand);
-
-    if (pfnProgress == NULL)
-        pfnProgress = GDALDummyProgress;
-
-/* -------------------------------------------------------------------- */
-/*      Initialize progress counter.                                    */
-/* -------------------------------------------------------------------- */
-    if( !pfnProgress( 0.0, NULL, pProgressData ) )
-    {
-        CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
-        return CE_Failure;
-    }
-
-    pafOutputBuf = (float *) CPLMalloc(sizeof(float)*nXSize);
-    pafThreeLineWin  = (float *) CPLMalloc(3*sizeof(float)*(nXSize+1));
-
-    fSrcNoDataValue = (float) GDALGetRasterNoDataValue(hSrcBand, &bSrcHasNoData);
-    fDstNoDataValue = (float) GDALGetRasterNoDataValue(hDstBand, &bDstHasNoData);
-    if (!bDstHasNoData)
-        fDstNoDataValue = 0.0;
-    int bIsSrcNoDataNan = bSrcHasNoData && CPLIsNan(fSrcNoDataValue);
-
-    // Move a 3x3 pafWindow over each cell 
-    // (where the cell in question is #4)
-    // 
-    //      0 1 2
-    //      3 4 5
-    //      6 7 8
-
-    /* Preload the first 2 lines */
-    for ( i = 0; i < 2 && i < nYSize; i++)
-    {
-        GDALRasterIO(   hSrcBand,
-                        GF_Read,
-                        0, i,
-                        nXSize, 1,
-                        pafThreeLineWin + i * nXSize,
-                        nXSize, 1,
-                        GDT_Float32,
-                        0, 0);
-    }
-    
-    if (bComputeAtEdges && nXSize >= 2 && nYSize >= 2)
-    {
-        for (j = 0; j < nXSize; j++)
-        {
-            float afWin[9];
-            int jmin = (j == 0) ? j : j - 1;
-            int jmax = (j == nXSize - 1) ? j : j + 1;
-
-            afWin[0] = INTERPOL(pafThreeLineWin[jmin], pafThreeLineWin[nXSize + jmin]);
-            afWin[1] = INTERPOL(pafThreeLineWin[j],    pafThreeLineWin[nXSize + j]);
-            afWin[2] = INTERPOL(pafThreeLineWin[jmax], pafThreeLineWin[nXSize + jmax]);
-            afWin[3] = pafThreeLineWin[jmin];
-            afWin[4] = pafThreeLineWin[j];
-            afWin[5] = pafThreeLineWin[jmax];
-            afWin[6] = pafThreeLineWin[nXSize + jmin];
-            afWin[7] = pafThreeLineWin[nXSize + j];
-            afWin[8] = pafThreeLineWin[nXSize + jmax];
-
-            pafOutputBuf[j] = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
-                                         bIsSrcNoDataNan,
-                                         afWin, fDstNoDataValue,
-                                         pfnAlg, pData, bComputeAtEdges);
-        }
-        GDALRasterIO(hDstBand, GF_Write,
-                    0, 0, nXSize, 1,
-                    pafOutputBuf, nXSize, 1, GDT_Float32, 0, 0);
-    }
-    else
-    {
-        // Exclude the edges
-        for (j = 0; j < nXSize; j++)
-        {
-            pafOutputBuf[j] = fDstNoDataValue;
-        }
-        GDALRasterIO(hDstBand, GF_Write,
-                    0, 0, nXSize, 1,
-                    pafOutputBuf, nXSize, 1, GDT_Float32, 0, 0);
-    
-        if (nYSize > 1)
-        {
-            GDALRasterIO(hDstBand, GF_Write,
-                        0, nYSize - 1, nXSize, 1,
-                        pafOutputBuf, nXSize, 1, GDT_Float32, 0, 0);
-        }
-    }
-    
-    int nLine1Off = 0*nXSize;
-    int nLine2Off = 1*nXSize;
-    int nLine3Off = 2*nXSize;
-
-    for ( i = 1; i < nYSize-1; i++)
-    {
-        /* Read third line of the line buffer */
-        eErr = GDALRasterIO(   hSrcBand,
-                        GF_Read,
-                        0, i+1,
-                        nXSize, 1,
-                        pafThreeLineWin + nLine3Off,
-                        nXSize, 1,
-                        GDT_Float32,
-                        0, 0);
-        if (eErr != CE_None)
-            goto end;
-
-        if (bComputeAtEdges && nXSize >= 2)
-        {
-            float afWin[9];
-
-            j = 0;
-            afWin[0] = INTERPOL(pafThreeLineWin[nLine1Off + j], pafThreeLineWin[nLine1Off + j+1]);
-            afWin[1] = pafThreeLineWin[nLine1Off + j];
-            afWin[2] = pafThreeLineWin[nLine1Off + j+1];
-            afWin[3] = INTERPOL(pafThreeLineWin[nLine2Off + j], pafThreeLineWin[nLine2Off + j+1]);
-            afWin[4] = pafThreeLineWin[nLine2Off + j];
-            afWin[5] = pafThreeLineWin[nLine2Off + j+1];
-            afWin[6] = INTERPOL(pafThreeLineWin[nLine3Off + j], pafThreeLineWin[nLine3Off + j+1]);
-            afWin[7] = pafThreeLineWin[nLine3Off + j];
-            afWin[8] = pafThreeLineWin[nLine3Off + j+1];
-
-            pafOutputBuf[j] = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
-                                         bIsSrcNoDataNan,
-                                         afWin, fDstNoDataValue,
-                                         pfnAlg, pData, bComputeAtEdges);
-            j = nXSize - 1;
-
-            afWin[0] = pafThreeLineWin[nLine1Off + j-1];
-            afWin[1] = pafThreeLineWin[nLine1Off + j];
-            afWin[2] = INTERPOL(pafThreeLineWin[nLine1Off + j], pafThreeLineWin[nLine1Off + j-1]);
-            afWin[3] = pafThreeLineWin[nLine2Off + j-1];
-            afWin[4] = pafThreeLineWin[nLine2Off + j];
-            afWin[5] = INTERPOL(pafThreeLineWin[nLine2Off + j], pafThreeLineWin[nLine2Off + j-1]);
-            afWin[6] = pafThreeLineWin[nLine3Off + j-1];
-            afWin[7] = pafThreeLineWin[nLine3Off + j];
-            afWin[8] = INTERPOL(pafThreeLineWin[nLine3Off + j], pafThreeLineWin[nLine3Off + j-1]);
-
-            pafOutputBuf[j] = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
-                                         bIsSrcNoDataNan,
-                                         afWin, fDstNoDataValue,
-                                         pfnAlg, pData, bComputeAtEdges);
-        }
-        else
-        {
-            // Exclude the edges
-            pafOutputBuf[0] = fDstNoDataValue;
-            if (nXSize > 1)
-                pafOutputBuf[nXSize - 1] = fDstNoDataValue;
-        }
-
-        for (j = 1; j < nXSize - 1; j++)
-        {
-            float afWin[9];
-            afWin[0] = pafThreeLineWin[nLine1Off + j-1];
-            afWin[1] = pafThreeLineWin[nLine1Off + j];
-            afWin[2] = pafThreeLineWin[nLine1Off + j+1];
-            afWin[3] = pafThreeLineWin[nLine2Off + j-1];
-            afWin[4] = pafThreeLineWin[nLine2Off + j];
-            afWin[5] = pafThreeLineWin[nLine2Off + j+1];
-            afWin[6] = pafThreeLineWin[nLine3Off + j-1];
-            afWin[7] = pafThreeLineWin[nLine3Off + j];
-            afWin[8] = pafThreeLineWin[nLine3Off + j+1];
-
-            pafOutputBuf[j] = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
-                                         bIsSrcNoDataNan,
-                                         afWin, fDstNoDataValue,
-                                         pfnAlg, pData, bComputeAtEdges);
-        }
-
-        /* -----------------------------------------
-         * Write Line to Raster
-         */
-        eErr = GDALRasterIO(hDstBand, GF_Write, 0, i, nXSize, 1,
-                     pafOutputBuf, nXSize, 1, GDT_Float32, 0, 0);
-        if (eErr != CE_None)
-            goto end;
-
-        if( !pfnProgress( 1.0 * (i+1) / nYSize, NULL, pProgressData ) )
-        {
-            CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
-            eErr = CE_Failure;
-            goto end;
-        }
-        
-        int nTemp = nLine1Off;
-        nLine1Off = nLine2Off;
-        nLine2Off = nLine3Off;
-        nLine3Off = nTemp;
-    }
-
-    if (bComputeAtEdges && nXSize >= 2 && nYSize >= 2)
-    {
-        for (j = 0; j < nXSize; j++)
-        {
-            float afWin[9];
-            int jmin = (j == 0) ? j : j - 1;
-            int jmax = (j == nXSize - 1) ? j : j + 1;
-
-            afWin[0] = pafThreeLineWin[nLine1Off + jmin];
-            afWin[1] = pafThreeLineWin[nLine1Off + j];
-            afWin[2] = pafThreeLineWin[nLine1Off + jmax];
-            afWin[3] = pafThreeLineWin[nLine2Off + jmin];
-            afWin[4] = pafThreeLineWin[nLine2Off + j];
-            afWin[5] = pafThreeLineWin[nLine2Off + jmax];
-            afWin[6] = INTERPOL(pafThreeLineWin[nLine2Off + jmin], pafThreeLineWin[nLine1Off + jmin]);
-            afWin[7] = INTERPOL(pafThreeLineWin[nLine2Off + j],    pafThreeLineWin[nLine1Off + j]);
-            afWin[8] = INTERPOL(pafThreeLineWin[nLine2Off + jmax], pafThreeLineWin[nLine1Off + jmax]);
-
-            pafOutputBuf[j] = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
-                                         bIsSrcNoDataNan,
-                                         afWin, fDstNoDataValue,
-                                         pfnAlg, pData, bComputeAtEdges);
-        }
-        GDALRasterIO(hDstBand, GF_Write,
-                     0, i, nXSize, 1,
-                     pafOutputBuf, nXSize, 1, GDT_Float32, 0, 0);
-    }
-
-    pfnProgress( 1.0, NULL, pProgressData );
-    eErr = CE_None;
-
-end:
-    CPLFree(pafOutputBuf);
-    CPLFree(pafThreeLineWin);
-
-    return eErr;
-}
-
-
-/************************************************************************/
-/*                         GDALHillshade()                              */
-/************************************************************************/
-
-typedef struct
-{
-    double nsres;
-    double ewres;
-    double sin_altRadians;
-    double cos_altRadians_mul_z_scale_factor;
-    double azRadians;
-    double square_z_scale_factor;
-    double square_M_PI_2;
-} GDALHillshadeAlgData;
-
-/* Unoptimized formulas are :
-    x = psData->z*((afWin[0] + afWin[3] + afWin[3] + afWin[6]) -
-        (afWin[2] + afWin[5] + afWin[5] + afWin[8])) /
-        (8.0 * psData->ewres * psData->scale);
-
-    y = psData->z*((afWin[6] + afWin[7] + afWin[7] + afWin[8]) -
-        (afWin[0] + afWin[1] + afWin[1] + afWin[2])) /
-        (8.0 * psData->nsres * psData->scale);
-
-    slope = M_PI / 2 - atan(sqrt(x*x + y*y));
-
-    aspect = atan2(y,x);
-
-    cang = sin(alt * degreesToRadians) * sin(slope) +
-           cos(alt * degreesToRadians) * cos(slope) *
-           cos(az * degreesToRadians - M_PI/2 - aspect);
-*/
-
-float GDALHillshadeAlg (float* afWin, CPL_UNUSED float fDstNoDataValue, void* pData)
-{
-    GDALHillshadeAlgData* psData = (GDALHillshadeAlgData*)pData;
-    double x, y, aspect, xx_plus_yy, cang;
-
-    // First Slope ...
-    x = ((afWin[0] + afWin[3] + afWin[3] + afWin[6]) -
-        (afWin[2] + afWin[5] + afWin[5] + afWin[8])) / psData->ewres;
-
-    y = ((afWin[6] + afWin[7] + afWin[7] + afWin[8]) -
-        (afWin[0] + afWin[1] + afWin[1] + afWin[2])) / psData->nsres;
-
-    xx_plus_yy = x * x + y * y;
-
-    // ... then aspect...
-    aspect = atan2(y,x);
-
-    // ... then the shade value
-    cang = (psData->sin_altRadians -
-           psData->cos_altRadians_mul_z_scale_factor * sqrt(xx_plus_yy) *
-           sin(aspect - psData->azRadians)) /
-           sqrt(1 + psData->square_z_scale_factor * xx_plus_yy);
-
-    if (cang <= 0.0)
-        cang = 1.0;
-    else
-        cang = 1.0 + (254.0 * cang);
-
-    return (float) cang;
-}
-
-float GDALHillshadeCombinedAlg (float* afWin, CPL_UNUSED float fDstNoDataValue, void* pData)
-{
-    GDALHillshadeAlgData* psData = (GDALHillshadeAlgData*)pData;
-    double x, y, aspect, xx_plus_yy, cang;
-
-    // First Slope ...
-    x = ((afWin[0] + afWin[3] + afWin[3] + afWin[6]) -
-        (afWin[2] + afWin[5] + afWin[5] + afWin[8])) / psData->ewres;
-
-    y = ((afWin[6] + afWin[7] + afWin[7] + afWin[8]) -
-        (afWin[0] + afWin[1] + afWin[1] + afWin[2])) / psData->nsres;
-
-    xx_plus_yy = x * x + y * y;
-
-    // ... then aspect...
-    aspect = atan2(y,x);
-    double slope = xx_plus_yy * psData->square_z_scale_factor;
-
-    // ... then the shade value
-    cang = acos((psData->sin_altRadians -
-           psData->cos_altRadians_mul_z_scale_factor * sqrt(xx_plus_yy) *
-           sin(aspect - psData->azRadians)) /
-           sqrt(1 + slope));
-
-    // combined shading
-    cang = 1 - cang * atan(sqrt(slope)) / psData->square_M_PI_2;
-
-    if (cang <= 0.0)
-        cang = 1.0;
-    else
-        cang = 1.0 + (254.0 * cang);
-
-    return (float) cang;
-}
-
-float GDALHillshadeZevenbergenThorneAlg (float* afWin, CPL_UNUSED float fDstNoDataValue, void* pData)
-{
-    GDALHillshadeAlgData* psData = (GDALHillshadeAlgData*)pData;
-    double x, y, aspect, xx_plus_yy, cang;
-
-    // First Slope ...
-    x = (afWin[3] - afWin[5]) / psData->ewres;
-
-    y = (afWin[7] - afWin[1]) / psData->nsres;
-
-    xx_plus_yy = x * x + y * y;
-
-    // ... then aspect...
-    aspect = atan2(y,x);
-
-    // ... then the shade value
-    cang = (psData->sin_altRadians -
-           psData->cos_altRadians_mul_z_scale_factor * sqrt(xx_plus_yy) *
-           sin(aspect - psData->azRadians)) /
-           sqrt(1 + psData->square_z_scale_factor * xx_plus_yy);
-
-    if (cang <= 0.0)
-        cang = 1.0;
-    else
-        cang = 1.0 + (254.0 * cang);
-
-    return (float) cang;
-}
-
-float GDALHillshadeZevenbergenThorneCombinedAlg (float* afWin, CPL_UNUSED float fDstNoDataValue, void* pData)
-{
-    GDALHillshadeAlgData* psData = (GDALHillshadeAlgData*)pData;
-    double x, y, aspect, xx_plus_yy, cang;
-
-    // First Slope ...
-    x = (afWin[3] - afWin[5]) / psData->ewres;
-
-    y = (afWin[7] - afWin[1]) / psData->nsres;
-
-    xx_plus_yy = x * x + y * y;
-
-    // ... then aspect...
-    aspect = atan2(y,x);
-    double slope = xx_plus_yy * psData->square_z_scale_factor;
-
-    // ... then the shade value
-    cang = acos((psData->sin_altRadians -
-           psData->cos_altRadians_mul_z_scale_factor * sqrt(xx_plus_yy) *
-           sin(aspect - psData->azRadians)) /
-           sqrt(1 + slope));
-
-    // combined shading
-    cang = 1 - cang * atan(sqrt(slope)) / psData->square_M_PI_2;
-
-    if (cang <= 0.0) 
-        cang = 1.0;
-    else
-        cang = 1.0 + (254.0 * cang);
-        
-    return (float) cang;
-}
-
-void*  GDALCreateHillshadeData(double* adfGeoTransform,
-                               double z,
-                               double scale,
-                               double alt,
-                               double az,
-                               int bZevenbergenThorne)
-{
-    GDALHillshadeAlgData* pData =
-        (GDALHillshadeAlgData*)CPLMalloc(sizeof(GDALHillshadeAlgData));
-        
-    const double degreesToRadians = M_PI / 180.0;
-    pData->nsres = adfGeoTransform[5];
-    pData->ewres = adfGeoTransform[1];
-    pData->sin_altRadians = sin(alt * degreesToRadians);
-    pData->azRadians = az * degreesToRadians;
-    double z_scale_factor = z / (((bZevenbergenThorne) ? 2 : 8) * scale);
-    pData->cos_altRadians_mul_z_scale_factor =
-        cos(alt * degreesToRadians) * z_scale_factor;
-    pData->square_z_scale_factor = z_scale_factor * z_scale_factor;
-    pData->square_M_PI_2 = (M_PI*M_PI)/4;
-    return pData;
-}
-
-/************************************************************************/
-/*                         GDALSlope()                                  */
-/************************************************************************/
-
-typedef struct
-{
-    double nsres;
-    double ewres;
-    double scale;
-    int    slopeFormat;
-} GDALSlopeAlgData;
-
-float GDALSlopeHornAlg (float* afWin, CPL_UNUSED float fDstNoDataValue, void* pData)
-{
-    const double radiansToDegrees = 180.0 / M_PI;
-    GDALSlopeAlgData* psData = (GDALSlopeAlgData*)pData;
-    double dx, dy, key;
-
-    dx = ((afWin[0] + afWin[3] + afWin[3] + afWin[6]) -
-          (afWin[2] + afWin[5] + afWin[5] + afWin[8]))/psData->ewres;
-
-    dy = ((afWin[6] + afWin[7] + afWin[7] + afWin[8]) -
-          (afWin[0] + afWin[1] + afWin[1] + afWin[2]))/psData->nsres;
-
-    key = (dx * dx + dy * dy);
-
-    if (psData->slopeFormat == 1)
-        return (float) (atan(sqrt(key) / (8*psData->scale)) * radiansToDegrees);
-    else
-        return (float) (100*(sqrt(key) / (8*psData->scale)));
-}
-
-float GDALSlopeZevenbergenThorneAlg (float* afWin, CPL_UNUSED float fDstNoDataValue, void* pData)
-{
-    const double radiansToDegrees = 180.0 / M_PI;
-    GDALSlopeAlgData* psData = (GDALSlopeAlgData*)pData;
-    double dx, dy, key;
-
-    dx = (afWin[3] - afWin[5])/psData->ewres;
-
-    dy = (afWin[7] - afWin[1])/psData->nsres;
-
-    key = (dx * dx + dy * dy);
-
-    if (psData->slopeFormat == 1)
-        return (float) (atan(sqrt(key) / (2*psData->scale)) * radiansToDegrees);
-    else
-        return (float) (100*(sqrt(key) / (2*psData->scale)));
-}
-
-void*  GDALCreateSlopeData(double* adfGeoTransform,
-                           double scale,
-                           int slopeFormat)
-{
-    GDALSlopeAlgData* pData =
-        (GDALSlopeAlgData*)CPLMalloc(sizeof(GDALSlopeAlgData));
-        
-    pData->nsres = adfGeoTransform[5];
-    pData->ewres = adfGeoTransform[1];
-    pData->scale = scale;
-    pData->slopeFormat = slopeFormat;
-    return pData;
-}
-
-/************************************************************************/
-/*                         GDALAspect()                                 */
-/************************************************************************/
-
-typedef struct
-{
-    int bAngleAsAzimuth;
-} GDALAspectAlgData;
-
-float GDALAspectAlg (float* afWin, float fDstNoDataValue, void* pData)
-{
-    const double degreesToRadians = M_PI / 180.0;
-    GDALAspectAlgData* psData = (GDALAspectAlgData*)pData;
-    double dx, dy;
-    float aspect;
-    
-    dx = ((afWin[2] + afWin[5] + afWin[5] + afWin[8]) -
-          (afWin[0] + afWin[3] + afWin[3] + afWin[6]));
-
-    dy = ((afWin[6] + afWin[7] + afWin[7] + afWin[8]) - 
-          (afWin[0] + afWin[1] + afWin[1] + afWin[2]));
-
-    aspect = (float) (atan2(dy,-dx) / degreesToRadians);
-
-    if (dx == 0 && dy == 0)
-    {
-        /* Flat area */
-        aspect = fDstNoDataValue;
-    } 
-    else if ( psData->bAngleAsAzimuth )
-    {
-        if (aspect > 90.0) 
-            aspect = 450.0f - aspect;
-        else
-            aspect = 90.0f - aspect;
-    }
-    else
-    {
-        if (aspect < 0)
-            aspect += 360.0;
-    }
-
-    if (aspect == 360.0) 
-        aspect = 0.0;
-
-    return aspect;
-}
-
-float GDALAspectZevenbergenThorneAlg (float* afWin, float fDstNoDataValue, void* pData)
-{
-    const double degreesToRadians = M_PI / 180.0;
-    GDALAspectAlgData* psData = (GDALAspectAlgData*)pData;
-    double dx, dy;
-    float aspect;
-    
-    dx = (afWin[5] - afWin[3]);
-
-    dy = (afWin[7] - afWin[1]);
-
-    aspect = (float) (atan2(dy,-dx) / degreesToRadians);
-
-    if (dx == 0 && dy == 0)
-    {
-        /* Flat area */
-        aspect = fDstNoDataValue;
-    } 
-    else if ( psData->bAngleAsAzimuth )
-    {
-        if (aspect > 90.0) 
-            aspect = 450.0f - aspect;
-        else
-            aspect = 90.0f - aspect;
-    }
-    else
-    {
-        if (aspect < 0)
-            aspect += 360.0;
-    }
-
-    if (aspect == 360.0) 
-        aspect = 0.0;
-
-    return aspect;
-}
-void*  GDALCreateAspectData(int bAngleAsAzimuth)
-{
-    GDALAspectAlgData* pData =
-        (GDALAspectAlgData*)CPLMalloc(sizeof(GDALAspectAlgData));
-        
-    pData->bAngleAsAzimuth = bAngleAsAzimuth;
-    return pData;
-}
-
-/************************************************************************/
-/*                      GDALColorRelief()                               */
-/************************************************************************/
-
-typedef struct
-{
-    double dfVal;
-    int nR;
-    int nG;
-    int nB;
-    int nA;
-} ColorAssociation;
-
-static int GDALColorReliefSortColors(const void* pA, const void* pB)
-{
-    ColorAssociation* pC1 = (ColorAssociation*)pA;
-    ColorAssociation* pC2 = (ColorAssociation*)pB;
-    /* Sort NaN in first position */
-    if( CPLIsNan(pC1->dfVal) )
-        return -1;
-    return (pC1->dfVal < pC2->dfVal) ? -1 :
-           (pC1->dfVal == pC2->dfVal) ? 0 : 1;
-}
-
-typedef enum
-{
-    COLOR_SELECTION_INTERPOLATE,
-    COLOR_SELECTION_NEAREST_ENTRY,
-    COLOR_SELECTION_EXACT_ENTRY
-} ColorSelectionMode;
-
-static int GDALColorReliefGetRGBA (ColorAssociation* pasColorAssociation,
-                                   int nColorAssociation,
-                                   double dfVal,
-                                   ColorSelectionMode eColorSelectionMode,
-                                   int* pnR,
-                                   int* pnG,
-                                   int* pnB,
-                                   int* pnA)
-{
-    int i;
-    int lower = 0;
-    int upper = nColorAssociation - 1;
-    int mid;
-
-    // Special case for NaN
-    if( CPLIsNan(pasColorAssociation[0].dfVal) )
-    {
-        if( CPLIsNan(dfVal) )
-        {
-            *pnR = pasColorAssociation[0].nR;
-            *pnG = pasColorAssociation[0].nG;
-            *pnB = pasColorAssociation[0].nB;
-            *pnA = pasColorAssociation[0].nA;
-            return TRUE;
-        }
-        else
-            lower = 1;
-    }
-
-    /* Find the index of the first element in the LUT input array that */
-    /* is not smaller than the dfVal value. */
-    while(TRUE)
-    {
-        mid = (lower + upper) / 2;
-        if (upper - lower <= 1)
-        {
-            if (dfVal < pasColorAssociation[lower].dfVal)
-                i = lower;
-            else if (dfVal < pasColorAssociation[upper].dfVal)
-                i = upper;
-            else
-                i = upper + 1;
-            break;
-        }
-        else if (pasColorAssociation[mid].dfVal >= dfVal)
-        {
-            upper = mid;
-        }
-        else
-        {
-            lower = mid;
-        }
-    }
-
-    if (i == 0)
-    {
-        if (eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY &&
-            pasColorAssociation[0].dfVal != dfVal)
-        {
-            *pnR = 0;
-            *pnG = 0;
-            *pnB = 0;
-            *pnA = 0;
-            return FALSE;
-        }
-        else
-        {
-            *pnR = pasColorAssociation[0].nR;
-            *pnG = pasColorAssociation[0].nG;
-            *pnB = pasColorAssociation[0].nB;
-            *pnA = pasColorAssociation[0].nA;
-            return TRUE;
-        }
-    }
-    else if (i == nColorAssociation)
-    {
-        if (eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY &&
-            pasColorAssociation[i-1].dfVal != dfVal)
-        {
-            *pnR = 0;
-            *pnG = 0;
-            *pnB = 0;
-            *pnA = 0;
-            return FALSE;
-        }
-        else
-        {
-            *pnR = pasColorAssociation[i-1].nR;
-            *pnG = pasColorAssociation[i-1].nG;
-            *pnB = pasColorAssociation[i-1].nB;
-            *pnA = pasColorAssociation[i-1].nA;
-            return TRUE;
-        }
-    }
-    else
-    {
-        if (eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY &&
-            pasColorAssociation[i-1].dfVal != dfVal)
-        {
-            *pnR = 0;
-            *pnG = 0;
-            *pnB = 0;
-            *pnA = 0;
-            return FALSE;
-        }
-        
-        if (eColorSelectionMode == COLOR_SELECTION_NEAREST_ENTRY &&
-            pasColorAssociation[i-1].dfVal != dfVal)
-        {
-            int index;
-            if (dfVal - pasColorAssociation[i-1].dfVal <
-                pasColorAssociation[i].dfVal - dfVal)
-                index = i -1;
-            else
-                index = i;
-
-            *pnR = pasColorAssociation[index].nR;
-            *pnG = pasColorAssociation[index].nG;
-            *pnB = pasColorAssociation[index].nB;
-            *pnA = pasColorAssociation[index].nA;
-            return TRUE;
-        }
-        
-        double dfRatio = (dfVal - pasColorAssociation[i-1].dfVal) /
-            (pasColorAssociation[i].dfVal - pasColorAssociation[i-1].dfVal);
-        *pnR = (int)(0.45 + pasColorAssociation[i-1].nR + dfRatio *
-                (pasColorAssociation[i].nR - pasColorAssociation[i-1].nR));
-        if (*pnR < 0) *pnR = 0;
-        else if (*pnR > 255) *pnR = 255;
-        *pnG = (int)(0.45 + pasColorAssociation[i-1].nG + dfRatio *
-                (pasColorAssociation[i].nG - pasColorAssociation[i-1].nG));
-        if (*pnG < 0) *pnG = 0;
-        else if (*pnG > 255) *pnG = 255;
-        *pnB = (int)(0.45 + pasColorAssociation[i-1].nB + dfRatio *
-                (pasColorAssociation[i].nB - pasColorAssociation[i-1].nB));
-        if (*pnB < 0) *pnB = 0;
-        else if (*pnB > 255) *pnB = 255;
-        *pnA = (int)(0.45 + pasColorAssociation[i-1].nA + dfRatio *
-                (pasColorAssociation[i].nA - pasColorAssociation[i-1].nA));
-        if (*pnA < 0) *pnA = 0;
-        else if (*pnA > 255) *pnA = 255;
-        
-        return TRUE;
-    }
-}
-
-/* dfPct : percentage between 0 and 1 */
-static double GDALColorReliefGetAbsoluteValFromPct(GDALRasterBandH hSrcBand,
-                                                   double dfPct)
-{
-    double dfMin, dfMax;
-    int bSuccessMin, bSuccessMax;
-    dfMin = GDALGetRasterMinimum(hSrcBand, &bSuccessMin);
-    dfMax = GDALGetRasterMaximum(hSrcBand, &bSuccessMax);
-    if (!bSuccessMin || !bSuccessMax)
-    {
-        double dfMean, dfStdDev;
-        fprintf(stderr, "Computing source raster statistics...\n");
-        GDALComputeRasterStatistics(hSrcBand, FALSE, &dfMin, &dfMax,
-                                    &dfMean, &dfStdDev, NULL, NULL);
-    }
-    return dfMin + dfPct * (dfMax - dfMin);
-}
-
-typedef struct
-{
-    const char *name;
-    float r, g, b;
-} NamedColor;
-
-static const NamedColor namedColors[] = {
-    { "white",  1.00, 1.00, 1.00 },
-    { "black",  0.00, 0.00, 0.00 },
-    { "red",    1.00, 0.00, 0.00 },
-    { "green",  0.00, 1.00, 0.00 },
-    { "blue",   0.00, 0.00, 1.00 },
-    { "yellow", 1.00, 1.00, 0.00 },
-    { "magenta",1.00, 0.00, 1.00 },
-    { "cyan",   0.00, 1.00, 1.00 },
-    { "aqua",   0.00, 0.75, 0.75 },
-    { "grey",   0.75, 0.75, 0.75 },
-    { "gray",   0.75, 0.75, 0.75 },
-    { "orange", 1.00, 0.50, 0.00 },
-    { "brown",  0.75, 0.50, 0.25 },
-    { "purple", 0.50, 0.00, 1.00 },
-    { "violet", 0.50, 0.00, 1.00 },
-    { "indigo", 0.00, 0.50, 1.00 },
-};
-
-static
-int GDALColorReliefFindNamedColor(const char *pszColorName, int *pnR, int *pnG, int *pnB)
-{
-    unsigned int i;
-
-    *pnR = *pnG = *pnB = 0;
-    for (i = 0; i < sizeof(namedColors) / sizeof(namedColors[0]); i++)
-    {
-        if (EQUAL(pszColorName, namedColors[i].name))
-        {
-            *pnR = (int)(255. * namedColors[i].r);
-            *pnG = (int)(255. * namedColors[i].g);
-            *pnB = (int)(255. * namedColors[i].b);
-            return TRUE;
-        }
-    }
-    return FALSE;
-}
-
-static
-ColorAssociation* GDALColorReliefParseColorFile(GDALRasterBandH hSrcBand,
-                                                const char* pszColorFilename,
-                                                int* pnColors)
-{
-    VSILFILE* fpColorFile = VSIFOpenL(pszColorFilename, "rt");
-    if (fpColorFile == NULL)
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s", pszColorFilename);
-        *pnColors = 0;
-        return NULL;
-    }
-
-    ColorAssociation* pasColorAssociation = NULL;
-    int nColorAssociation = 0;
-
-    int bSrcHasNoData = FALSE;
-    double dfSrcNoDataValue = GDALGetRasterNoDataValue(hSrcBand, &bSrcHasNoData);
-
-    const char* pszLine;
-    int bIsGMT_CPT = FALSE;
-    while ((pszLine = CPLReadLineL(fpColorFile)) != NULL)
-    {
-        if (pszLine[0] == '#' && strstr(pszLine, "COLOR_MODEL"))
-        {
-            if (strstr(pszLine, "COLOR_MODEL = RGB") == NULL)
-            {
-                CPLError(CE_Failure, CPLE_AppDefined, "Only COLOR_MODEL = RGB is supported");
-                CPLFree(pasColorAssociation);
-                *pnColors = 0;
-                return NULL;
-            }
-            bIsGMT_CPT = TRUE;
-        }
-
-        char** papszFields = CSLTokenizeStringComplex(pszLine, " ,\t:", 
-                                                      FALSE, FALSE );
-        /* Skip comment lines */
-        int nTokens = CSLCount(papszFields);
-        if (nTokens >= 1 && (papszFields[0][0] == '#' ||
-                             papszFields[0][0] == '/'))
-        {
-            CSLDestroy(papszFields);
-            continue;
-        }
-
-        if (bIsGMT_CPT && nTokens == 8)
-        {
-            pasColorAssociation =
-                    (ColorAssociation*)CPLRealloc(pasColorAssociation,
-                           (nColorAssociation + 2) * sizeof(ColorAssociation));
-
-            pasColorAssociation[nColorAssociation].dfVal = CPLAtof(papszFields[0]);
-            pasColorAssociation[nColorAssociation].nR = atoi(papszFields[1]);
-            pasColorAssociation[nColorAssociation].nG = atoi(papszFields[2]);
-            pasColorAssociation[nColorAssociation].nB = atoi(papszFields[3]);
-            pasColorAssociation[nColorAssociation].nA = 255;
-            nColorAssociation++;
-
-            pasColorAssociation[nColorAssociation].dfVal = CPLAtof(papszFields[4]);
-            pasColorAssociation[nColorAssociation].nR = atoi(papszFields[5]);
-            pasColorAssociation[nColorAssociation].nG = atoi(papszFields[6]);
-            pasColorAssociation[nColorAssociation].nB = atoi(papszFields[7]);
-            pasColorAssociation[nColorAssociation].nA = 255;
-            nColorAssociation++;
-        }
-        else if (bIsGMT_CPT && nTokens == 4)
-        {
-            /* The first token might be B (background), F (foreground) or N (nodata) */
-            /* Just interested in N */
-            if (EQUAL(papszFields[0], "N") && bSrcHasNoData)
-            {
-                 pasColorAssociation =
-                    (ColorAssociation*)CPLRealloc(pasColorAssociation,
-                           (nColorAssociation + 1) * sizeof(ColorAssociation));
-
-                pasColorAssociation[nColorAssociation].dfVal = dfSrcNoDataValue;
-                pasColorAssociation[nColorAssociation].nR = atoi(papszFields[1]);
-                pasColorAssociation[nColorAssociation].nG = atoi(papszFields[2]);
-                pasColorAssociation[nColorAssociation].nB = atoi(papszFields[3]);
-                pasColorAssociation[nColorAssociation].nA = 255;
-                nColorAssociation++;
-            }
-        }
-        else if (!bIsGMT_CPT && nTokens >= 2)
-        {
-            pasColorAssociation =
-                    (ColorAssociation*)CPLRealloc(pasColorAssociation,
-                           (nColorAssociation + 1) * sizeof(ColorAssociation));
-            if (EQUAL(papszFields[0], "nv") && bSrcHasNoData)
-                pasColorAssociation[nColorAssociation].dfVal = dfSrcNoDataValue;
-            else if (strlen(papszFields[0]) > 1 && papszFields[0][strlen(papszFields[0])-1] == '%')
-            {
-                double dfPct = CPLAtof(papszFields[0]) / 100.;
-                if (dfPct < 0.0 || dfPct > 1.0)
-                {
-                    CPLError(CE_Failure, CPLE_AppDefined,
-                             "Wrong value for a percentage : %s", papszFields[0]);
-                    CSLDestroy(papszFields);
-                    VSIFCloseL(fpColorFile);
-                    CPLFree(pasColorAssociation);
-                    *pnColors = 0;
-                    return NULL;
-                }
-                pasColorAssociation[nColorAssociation].dfVal =
-                        GDALColorReliefGetAbsoluteValFromPct(hSrcBand, dfPct);
-            }
-            else
-                pasColorAssociation[nColorAssociation].dfVal = CPLAtof(papszFields[0]);
-
-            if (nTokens >= 4)
-            {
-                pasColorAssociation[nColorAssociation].nR = atoi(papszFields[1]);
-                pasColorAssociation[nColorAssociation].nG = atoi(papszFields[2]);
-                pasColorAssociation[nColorAssociation].nB = atoi(papszFields[3]);
-                pasColorAssociation[nColorAssociation].nA =
-                        (CSLCount(papszFields) >= 5 ) ? atoi(papszFields[4]) : 255;
-            }
-            else
-            {
-                int nR, nG, nB;
-                if (!GDALColorReliefFindNamedColor(papszFields[1], &nR, &nG, &nB))
-                {
-                    CPLError(CE_Failure, CPLE_AppDefined,
-                             "Unknown color : %s", papszFields[1]);
-                    CSLDestroy(papszFields);
-                    VSIFCloseL(fpColorFile);
-                    CPLFree(pasColorAssociation);
-                    *pnColors = 0;
-                    return NULL;
-                }
-                pasColorAssociation[nColorAssociation].nR = nR;
-                pasColorAssociation[nColorAssociation].nG = nG;
-                pasColorAssociation[nColorAssociation].nB = nB;
-                            pasColorAssociation[nColorAssociation].nA =
-                    (CSLCount(papszFields) >= 3 ) ? atoi(papszFields[2]) : 255;
-            }
-
-            nColorAssociation ++;
-        }
-        CSLDestroy(papszFields);
-    }
-    VSIFCloseL(fpColorFile);
-
-    if (nColorAssociation == 0)
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "No color association found in %s", pszColorFilename);
-        *pnColors = 0;
-        return NULL;
-    }
-
-    qsort(pasColorAssociation, nColorAssociation,
-          sizeof(ColorAssociation), GDALColorReliefSortColors);
-
-    *pnColors = nColorAssociation;
-    return pasColorAssociation;
-}
-
-static
-GByte* GDALColorReliefPrecompute(GDALRasterBandH hSrcBand,
-                                 ColorAssociation* pasColorAssociation,
-                                 int nColorAssociation,
-                                 ColorSelectionMode eColorSelectionMode,
-                                 int* pnIndexOffset)
-{
-    GDALDataType eDT = GDALGetRasterDataType(hSrcBand);
-    GByte* pabyPrecomputed = NULL;
-    int nIndexOffset = (eDT == GDT_Int16) ? 32768 : 0;
-    *pnIndexOffset = nIndexOffset;
-    int nXSize = GDALGetRasterBandXSize(hSrcBand);
-    int nYSize = GDALGetRasterBandXSize(hSrcBand);
-    if (eDT == GDT_Byte ||
-        ((eDT == GDT_Int16 || eDT == GDT_UInt16) && nXSize * nYSize > 65536))
-    {
-        int iMax = (eDT == GDT_Byte) ? 256: 65536;
-        pabyPrecomputed = (GByte*) VSIMalloc(4 * iMax);
-        if (pabyPrecomputed)
-        {
-            int i;
-            for(i=0;i<iMax;i++)
-            {
-                int nR, nG, nB, nA;
-                GDALColorReliefGetRGBA  (pasColorAssociation,
-                                         nColorAssociation,
-                                         i - nIndexOffset,
-                                         eColorSelectionMode,
-                                         &nR, &nG, &nB, &nA);
-                pabyPrecomputed[4 * i] = (GByte) nR;
-                pabyPrecomputed[4 * i + 1] = (GByte) nG;
-                pabyPrecomputed[4 * i + 2] = (GByte) nB;
-                pabyPrecomputed[4 * i + 3] = (GByte) nA;
-            }
-        }
-    }
-    return pabyPrecomputed;
-}
-
-/************************************************************************/
-/* ==================================================================== */
-/*                       GDALColorReliefDataset                        */
-/* ==================================================================== */
-/************************************************************************/
-
-class GDALColorReliefRasterBand;
-
-class GDALColorReliefDataset : public GDALDataset
-{
-    friend class GDALColorReliefRasterBand;
-
-    GDALDatasetH       hSrcDS;
-    GDALRasterBandH    hSrcBand;
-    int                nColorAssociation;
-    ColorAssociation*  pasColorAssociation;
-    ColorSelectionMode eColorSelectionMode;
-    GByte*             pabyPrecomputed;
-    int                nIndexOffset;
-    float*             pafSourceBuf;
-    int*               panSourceBuf;
-    int                nCurBlockXOff;
-    int                nCurBlockYOff;
-
-  public:
-                        GDALColorReliefDataset(GDALDatasetH hSrcDS,
-                                            GDALRasterBandH hSrcBand,
-                                            const char* pszColorFilename,
-                                            ColorSelectionMode eColorSelectionMode,
-                                            int bAlpha);
-                       ~GDALColorReliefDataset();
-
-    CPLErr      GetGeoTransform( double * padfGeoTransform );
-    const char *GetProjectionRef();
-};
-
-/************************************************************************/
-/* ==================================================================== */
-/*                    GDALColorReliefRasterBand                       */
-/* ==================================================================== */
-/************************************************************************/
-
-class GDALColorReliefRasterBand : public GDALRasterBand
-{
-    friend class GDALColorReliefDataset;
-
-    
-  public:
-                 GDALColorReliefRasterBand( GDALColorReliefDataset *, int );
-    
-    virtual CPLErr          IReadBlock( int, int, void * );
-    virtual GDALColorInterp GetColorInterpretation();
-};
-
-GDALColorReliefDataset::GDALColorReliefDataset(
-                                     GDALDatasetH hSrcDS,
-                                     GDALRasterBandH hSrcBand,
-                                     const char* pszColorFilename,
-                                     ColorSelectionMode eColorSelectionMode,
-                                     int bAlpha)
-{
-    this->hSrcDS = hSrcDS;
-    this->hSrcBand = hSrcBand;
-    nColorAssociation = 0;
-    pasColorAssociation =
-            GDALColorReliefParseColorFile(hSrcBand, pszColorFilename,
-                                          &nColorAssociation);
-    this->eColorSelectionMode = eColorSelectionMode;
-    
-    nRasterXSize = GDALGetRasterXSize(hSrcDS);
-    nRasterYSize = GDALGetRasterYSize(hSrcDS);
-    
-    int nBlockXSize, nBlockYSize;
-    GDALGetBlockSize( hSrcBand, &nBlockXSize, &nBlockYSize);
-    
-    nIndexOffset = 0;
-    pabyPrecomputed =
-        GDALColorReliefPrecompute(hSrcBand,
-                                  pasColorAssociation,
-                                  nColorAssociation,
-                                  eColorSelectionMode,
-                                  &nIndexOffset);
-    
-    int i;
-    for(i=0;i<((bAlpha) ? 4 : 3);i++)
-    {
-        SetBand(i + 1, new GDALColorReliefRasterBand(this, i+1));
-    }
-    
-    pafSourceBuf = NULL;
-    panSourceBuf = NULL;
-    if (pabyPrecomputed)
-        panSourceBuf = (int *) CPLMalloc(sizeof(int)*nBlockXSize*nBlockYSize);
-    else
-        pafSourceBuf = (float *) CPLMalloc(sizeof(float)*nBlockXSize*nBlockYSize);
-    nCurBlockXOff = -1;
-    nCurBlockYOff = -1;
-}
-
-GDALColorReliefDataset::~GDALColorReliefDataset()
-{
-    CPLFree(pasColorAssociation);
-    CPLFree(pabyPrecomputed);
-    CPLFree(panSourceBuf);
-    CPLFree(pafSourceBuf);
-}
-
-CPLErr GDALColorReliefDataset::GetGeoTransform( double * padfGeoTransform )
-{
-    return GDALGetGeoTransform(hSrcDS, padfGeoTransform);
-}
-
-const char *GDALColorReliefDataset::GetProjectionRef()
-{
-    return GDALGetProjectionRef(hSrcDS);
-}
-
-GDALColorReliefRasterBand::GDALColorReliefRasterBand(
-                                    GDALColorReliefDataset * poDS, int nBand)
-{
-    this->poDS = poDS;
-    this->nBand = nBand;
-    eDataType = GDT_Byte;
-    GDALGetBlockSize( poDS->hSrcBand, &nBlockXSize, &nBlockYSize);
-}
-
-CPLErr GDALColorReliefRasterBand::IReadBlock( int nBlockXOff,
-                                              int nBlockYOff,
-                                              void *pImage )
-{
-    GDALColorReliefDataset * poGDS = (GDALColorReliefDataset *) poDS;
-    int nReqXSize, nReqYSize;
-
-    if ((nBlockXOff + 1) * nBlockXSize >= nRasterXSize)
-        nReqXSize = nRasterXSize - nBlockXOff * nBlockXSize;
-    else
-        nReqXSize = nBlockXSize;
-        
-    if ((nBlockYOff + 1) * nBlockYSize >= nRasterYSize)
-        nReqYSize = nRasterYSize - nBlockYOff * nBlockYSize;
-    else
-        nReqYSize = nBlockYSize;
-
-    if ( poGDS->nCurBlockXOff != nBlockXOff ||
-         poGDS->nCurBlockYOff != nBlockYOff )
-    {
-        poGDS->nCurBlockXOff = nBlockXOff;
-        poGDS->nCurBlockYOff = nBlockYOff;
-        
-        CPLErr eErr = GDALRasterIO( poGDS->hSrcBand,
-                            GF_Read,
-                            nBlockXOff * nBlockXSize,
-                            nBlockYOff * nBlockYSize,
-                            nReqXSize, nReqYSize,
-                            (poGDS->panSourceBuf) ?
-                                (void*) poGDS->panSourceBuf :
-                                (void* )poGDS->pafSourceBuf,
-                            nReqXSize, nReqYSize,
-                            (poGDS->panSourceBuf) ? GDT_Int32 : GDT_Float32,
-                            0, 0);
-        if (eErr != CE_None)
-        {
-            memset(pImage, 0, nBlockXSize * nBlockYSize);
-            return eErr;
-        }
-    }
-
-    int x, y, j = 0;
-    if (poGDS->panSourceBuf)
-    {
-        for( y = 0; y < nReqYSize; y++ )
-        {
-            for( x = 0; x < nReqXSize; x++ )
-            {
-                int nIndex = poGDS->panSourceBuf[j] + poGDS->nIndexOffset;
-                ((GByte*)pImage)[y * nBlockXSize + x] = poGDS->pabyPrecomputed[4*nIndex + nBand-1];
-                j++;
-            }
-        }
-    }
-    else
-    {
-        int anComponents[4];
-        for( y = 0; y < nReqYSize; y++ )
-        {
-            for( x = 0; x < nReqXSize; x++ )
-            {
-                GDALColorReliefGetRGBA  (poGDS->pasColorAssociation,
-                                        poGDS->nColorAssociation,
-                                        poGDS->pafSourceBuf[j],
-                                        poGDS->eColorSelectionMode,
-                                        &anComponents[0],
-                                        &anComponents[1],
-                                        &anComponents[2],
-                                        &anComponents[3]);
-                ((GByte*)pImage)[y * nBlockXSize + x] = (GByte) anComponents[nBand-1];
-                j++;
-            }
-        }
-    }
-    
-    return CE_None;
-}
-
-GDALColorInterp GDALColorReliefRasterBand::GetColorInterpretation()
-{
-    return (GDALColorInterp)(GCI_RedBand + nBand - 1);
-}
-
-
-CPLErr GDALColorRelief (GDALRasterBandH hSrcBand,
-                        GDALRasterBandH hDstBand1,
-                        GDALRasterBandH hDstBand2,
-                        GDALRasterBandH hDstBand3,
-                        GDALRasterBandH hDstBand4,
-                        const char* pszColorFilename,
-                        ColorSelectionMode eColorSelectionMode,
-                        GDALProgressFunc pfnProgress,
-                        void * pProgressData)
-{
-    CPLErr eErr;
-    
-    if (hSrcBand == NULL || hDstBand1 == NULL || hDstBand2 == NULL ||
-        hDstBand3 == NULL)
-        return CE_Failure;
-
-    int nColorAssociation = 0;
-    ColorAssociation* pasColorAssociation =
-            GDALColorReliefParseColorFile(hSrcBand, pszColorFilename,
-                                          &nColorAssociation);
-    if (pasColorAssociation == NULL)
-        return CE_Failure;
-
-    int nXSize = GDALGetRasterBandXSize(hSrcBand);
-    int nYSize = GDALGetRasterBandYSize(hSrcBand);
-
-    if (pfnProgress == NULL)
-        pfnProgress = GDALDummyProgress;
-        
-    int nR = 0, nG = 0, nB = 0, nA = 0;
-    
-/* -------------------------------------------------------------------- */
-/*      Precompute the map from values to RGBA quadruplets              */
-/*      for GDT_Byte, GDT_Int16 or GDT_UInt16                           */
-/* -------------------------------------------------------------------- */
-    int nIndexOffset = 0;
-    GByte* pabyPrecomputed =
-        GDALColorReliefPrecompute(hSrcBand,
-                                  pasColorAssociation,
-                                  nColorAssociation,
-                                  eColorSelectionMode,
-                                  &nIndexOffset);
-
-/* -------------------------------------------------------------------- */
-/*      Initialize progress counter.                                    */
-/* -------------------------------------------------------------------- */
-
-    float* pafSourceBuf = NULL;
-    int* panSourceBuf = NULL;
-    if (pabyPrecomputed)
-        panSourceBuf = (int *) CPLMalloc(sizeof(int)*nXSize);
-    else
-        pafSourceBuf = (float *) CPLMalloc(sizeof(float)*nXSize);
-    GByte* pabyDestBuf1  = (GByte*) CPLMalloc( 4 * nXSize );
-    GByte* pabyDestBuf2  =  pabyDestBuf1 + nXSize;
-    GByte* pabyDestBuf3  =  pabyDestBuf2 + nXSize;
-    GByte* pabyDestBuf4  =  pabyDestBuf3 + nXSize;
-    int i, j;
-
-    if( !pfnProgress( 0.0, NULL, pProgressData ) )
-    {
-        CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
-        eErr = CE_Failure;
-        goto end;
-    }
-
-    for ( i = 0; i < nYSize; i++)
-    {
-        /* Read source buffer */
-        eErr = GDALRasterIO(   hSrcBand,
-                        GF_Read,
-                        0, i,
-                        nXSize, 1,
-                        (panSourceBuf) ? (void*) panSourceBuf : (void* )pafSourceBuf,
-                        nXSize, 1,
-                        (panSourceBuf) ? GDT_Int32 : GDT_Float32,
-                        0, 0);
-        if (eErr != CE_None)
-            goto end;
-
-        if (panSourceBuf)
-        {
-            for ( j = 0; j < nXSize; j++)
-            {
-                int nIndex = panSourceBuf[j] + nIndexOffset;
-                pabyDestBuf1[j] = pabyPrecomputed[4 * nIndex];
-                pabyDestBuf2[j] = pabyPrecomputed[4 * nIndex + 1];
-                pabyDestBuf3[j] = pabyPrecomputed[4 * nIndex + 2];
-                pabyDestBuf4[j] = pabyPrecomputed[4 * nIndex + 3];
-            }
-        }
-        else
-        {
-            for ( j = 0; j < nXSize; j++)
-            {
-                GDALColorReliefGetRGBA  (pasColorAssociation,
-                                         nColorAssociation,
-                                         pafSourceBuf[j],
-                                         eColorSelectionMode,
-                                         &nR,
-                                         &nG,
-                                         &nB,
-                                         &nA);
-                pabyDestBuf1[j] = (GByte) nR;
-                pabyDestBuf2[j] = (GByte) nG;
-                pabyDestBuf3[j] = (GByte) nB;
-                pabyDestBuf4[j] = (GByte) nA;
-            }
-        }
-        
-        /* -----------------------------------------
-         * Write Line to Raster
-         */
-        eErr = GDALRasterIO(hDstBand1,
-                      GF_Write,
-                      0, i, nXSize,
-                      1, pabyDestBuf1, nXSize, 1, GDT_Byte, 0, 0);
-        if (eErr != CE_None)
-            goto end;
-
-        eErr = GDALRasterIO(hDstBand2,
-                      GF_Write,
-                      0, i, nXSize,
-                      1, pabyDestBuf2, nXSize, 1, GDT_Byte, 0, 0);
-        if (eErr != CE_None)
-            goto end;
-            
-        eErr = GDALRasterIO(hDstBand3,
-                      GF_Write,
-                      0, i, nXSize,
-                      1, pabyDestBuf3, nXSize, 1, GDT_Byte, 0, 0);
-        if (eErr != CE_None)
-            goto end;
-            
-        if (hDstBand4)
-        {
-            eErr = GDALRasterIO(hDstBand4,
-                        GF_Write,
-                        0, i, nXSize,
-                        1, pabyDestBuf4, nXSize, 1, GDT_Byte, 0, 0);
-            if (eErr != CE_None)
-                goto end;
-        }
-
-        if( !pfnProgress( 1.0 * (i+1) / nYSize, NULL, pProgressData ) )
-        {
-            CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
-            eErr = CE_Failure;
-            goto end;
-        }
-    }
-    pfnProgress( 1.0, NULL, pProgressData );
-    eErr = CE_None;
-
-end:
-    VSIFree(pabyPrecomputed);
-    CPLFree(pafSourceBuf);
-    CPLFree(panSourceBuf);
-    CPLFree(pabyDestBuf1);
-    CPLFree(pasColorAssociation);
-
-    return eErr;
-}
-
-/************************************************************************/
-/*                     GDALGenerateVRTColorRelief()                     */
-/************************************************************************/
-
-CPLErr GDALGenerateVRTColorRelief(const char* pszDstFilename,
-                               GDALDatasetH hSrcDataset,
-                               GDALRasterBandH hSrcBand,
-                               const char* pszColorFilename,
-                               ColorSelectionMode eColorSelectionMode,
-                               int bAddAlpha)
-{
-
-    int nColorAssociation = 0;
-    ColorAssociation* pasColorAssociation =
-            GDALColorReliefParseColorFile(hSrcBand, pszColorFilename,
-                                          &nColorAssociation);
-    if (pasColorAssociation == NULL)
-        return CE_Failure;
-
-    int nXSize = GDALGetRasterBandXSize(hSrcBand);
-    int nYSize = GDALGetRasterBandYSize(hSrcBand);
-
-    VSILFILE* fp = VSIFOpenL(pszDstFilename, "wt");
-    if (fp == NULL)
-    {
-        CPLFree(pasColorAssociation);
-        return CE_Failure;
-    }
-
-    VSIFPrintfL(fp, "<VRTDataset rasterXSize=\"%d\" rasterYSize=\"%d\">\n", nXSize, nYSize);
-    const char* pszProjectionRef = GDALGetProjectionRef(hSrcDataset);
-    if (pszProjectionRef && pszProjectionRef[0] != '\0')
-    {
-        char* pszEscapedString = CPLEscapeString(pszProjectionRef, -1, CPLES_XML);
-        VSIFPrintfL(fp, "  <SRS>%s</SRS>\n", pszEscapedString);
-        VSIFree(pszEscapedString);
-    }
-    double adfGT[6];
-    if (GDALGetGeoTransform(hSrcDataset, adfGT) == CE_None)
-    {
-        VSIFPrintfL(fp, "  <GeoTransform> %.16g, %.16g, %.16g, "
-                        "%.16g, %.16g, %.16g</GeoTransform>\n",
-                        adfGT[0], adfGT[1], adfGT[2], adfGT[3], adfGT[4], adfGT[5]);
-    }
-    int nBands = 3 + (bAddAlpha ? 1 : 0);
-    int iBand;
-
-    int nBlockXSize, nBlockYSize;
-    GDALGetBlockSize(hSrcBand, &nBlockXSize, &nBlockYSize);
-    
-    int bRelativeToVRT;
-    CPLString osPath = CPLGetPath(pszDstFilename);
-    char* pszSourceFilename = CPLStrdup(
-        CPLExtractRelativePath( osPath.c_str(), GDALGetDescription(hSrcDataset), 
-                                &bRelativeToVRT ));
-
-    for(iBand = 0; iBand < nBands; iBand++)
-    {
-        VSIFPrintfL(fp, "  <VRTRasterBand dataType=\"Byte\" band=\"%d\">\n", iBand + 1);
-        VSIFPrintfL(fp, "    <ColorInterp>%s</ColorInterp>\n",
-                    GDALGetColorInterpretationName((GDALColorInterp)(GCI_RedBand + iBand)));
-        VSIFPrintfL(fp, "    <ComplexSource>\n");
-        VSIFPrintfL(fp, "      <SourceFilename relativeToVRT=\"%d\">%s</SourceFilename>\n",
-                        bRelativeToVRT, pszSourceFilename);
-        VSIFPrintfL(fp, "      <SourceBand>%d</SourceBand>\n", GDALGetBandNumber(hSrcBand));
-        VSIFPrintfL(fp, "      <SourceProperties RasterXSize=\"%d\" "
-                        "RasterYSize=\"%d\" DataType=\"%s\" "
-                        "BlockXSize=\"%d\" BlockYSize=\"%d\"/>\n",
-                        nXSize, nYSize,
-                        GDALGetDataTypeName(GDALGetRasterDataType(hSrcBand)),
-                        nBlockXSize, nBlockYSize);
-        VSIFPrintfL(fp, "      <SrcRect xOff=\"0\" yOff=\"0\" xSize=\"%d\" ySize=\"%d\"/>\n",
-                        nXSize, nYSize);
-        VSIFPrintfL(fp, "      <DstRect xOff=\"0\" yOff=\"0\" xSize=\"%d\" ySize=\"%d\"/>\n",
-                        nXSize, nYSize);
-
-        VSIFPrintfL(fp, "      <LUT>");
-        int iColor;
-#define EPSILON 1e-8
-        for(iColor=0;iColor<nColorAssociation;iColor++)
-        {
-            if (eColorSelectionMode == COLOR_SELECTION_NEAREST_ENTRY)
-            {
-                if (iColor > 1)
-                    VSIFPrintfL(fp, ",");
-            }
-            else if (iColor > 0)
-                VSIFPrintfL(fp, ",");
-
-            double dfVal = pasColorAssociation[iColor].dfVal;
-
-            if (eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY)
-            {
-                VSIFPrintfL(fp, "%.12g:0,", dfVal - EPSILON);
-            }
-            else if (iColor > 0 &&
-                     eColorSelectionMode == COLOR_SELECTION_NEAREST_ENTRY)
-            {
-                double dfMidVal = (dfVal + pasColorAssociation[iColor-1].dfVal) / 2;
-                VSIFPrintfL(fp, "%.12g:%d", dfMidVal - EPSILON,
-                        (iBand == 0) ? pasColorAssociation[iColor-1].nR :
-                        (iBand == 1) ? pasColorAssociation[iColor-1].nG :
-                        (iBand == 2) ? pasColorAssociation[iColor-1].nB :
-                                       pasColorAssociation[iColor-1].nA);
-                VSIFPrintfL(fp, ",%.12g:%d", dfMidVal ,
-                        (iBand == 0) ? pasColorAssociation[iColor].nR :
-                        (iBand == 1) ? pasColorAssociation[iColor].nG :
-                        (iBand == 2) ? pasColorAssociation[iColor].nB :
-                                       pasColorAssociation[iColor].nA);
-
-            }
-
-            if (eColorSelectionMode != COLOR_SELECTION_NEAREST_ENTRY)
-            {
-                if (dfVal != (double)(int)dfVal)
-                    VSIFPrintfL(fp, "%.12g", dfVal);
-                else
-                    VSIFPrintfL(fp, "%d", (int)dfVal);
-                VSIFPrintfL(fp, ":%d",
-                            (iBand == 0) ? pasColorAssociation[iColor].nR :
-                            (iBand == 1) ? pasColorAssociation[iColor].nG :
-                            (iBand == 2) ? pasColorAssociation[iColor].nB :
-                                           pasColorAssociation[iColor].nA);
-            }
-
-            if (eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY)
-            {
-                VSIFPrintfL(fp, ",%.12g:0", dfVal + EPSILON);
-            }
-
-        }
-        VSIFPrintfL(fp, "</LUT>\n");
-
-        VSIFPrintfL(fp, "    </ComplexSource>\n");
-        VSIFPrintfL(fp, "  </VRTRasterBand>\n");
-    }
-
-    CPLFree(pszSourceFilename);
-
-    VSIFPrintfL(fp, "</VRTDataset>\n");
-
-    VSIFCloseL(fp);
-
-    CPLFree(pasColorAssociation);
-
-    return CE_None;
-}
-
-
-/************************************************************************/
-/*                         GDALTRIAlg()                                 */
-/************************************************************************/
-
-float GDALTRIAlg (float* afWin,
-                  CPL_UNUSED float fDstNoDataValue,
-                  CPL_UNUSED void* pData)
-{
-    // Terrain Ruggedness is average difference in height
-    return (fabs(afWin[0]-afWin[4]) +
-            fabs(afWin[1]-afWin[4]) +
-            fabs(afWin[2]-afWin[4]) +
-            fabs(afWin[3]-afWin[4]) +
-            fabs(afWin[5]-afWin[4]) +
-            fabs(afWin[6]-afWin[4]) +
-            fabs(afWin[7]-afWin[4]) +
-            fabs(afWin[8]-afWin[4]))/8;
-}
-
-
-/************************************************************************/
-/*                         GDALTPIAlg()                                 */
-/************************************************************************/
-
-float GDALTPIAlg (float* afWin,
-                  CPL_UNUSED float fDstNoDataValue,
-                  CPL_UNUSED void* pData)
-{
-    // Terrain Position is the difference between
-    // The central cell and the mean of the surrounding cells
-    return afWin[4] -
-            ((afWin[0]+
-              afWin[1]+
-              afWin[2]+
-              afWin[3]+
-              afWin[5]+
-              afWin[6]+
-              afWin[7]+
-              afWin[8])/8);
-}
-
-/************************************************************************/
-/*                     GDALRoughnessAlg()                               */
-/************************************************************************/
-
-float GDALRoughnessAlg (float* afWin, CPL_UNUSED float fDstNoDataValue, CPL_UNUSED void* pData)
-{
-    // Roughness is the largest difference
-    //  between any two cells
-
-    float pafRoughnessMin = afWin[0];
-    float pafRoughnessMax = afWin[0];
-
-    for ( int k = 1; k < 9; k++)
-    {
-        if (afWin[k] > pafRoughnessMax)
-        {
-            pafRoughnessMax=afWin[k];
-        }
-        if (afWin[k] < pafRoughnessMin)
-        {
-            pafRoughnessMin=afWin[k];
-        }
-    }
-    return pafRoughnessMax - pafRoughnessMin;
-}
-
-/************************************************************************/
-/* ==================================================================== */
-/*                       GDALGeneric3x3Dataset                        */
-/* ==================================================================== */
-/************************************************************************/
-
-class GDALGeneric3x3RasterBand;
-
-class GDALGeneric3x3Dataset : public GDALDataset
-{
-    friend class GDALGeneric3x3RasterBand;
-
-    GDALGeneric3x3ProcessingAlg pfnAlg;
-    void*              pAlgData;
-    GDALDatasetH       hSrcDS;
-    GDALRasterBandH    hSrcBand;
-    float*             apafSourceBuf[3];
-    int                bDstHasNoData;
-    double             dfDstNoDataValue;
-    int                nCurLine;
-    int                bComputeAtEdges;
-
-  public:
-                        GDALGeneric3x3Dataset(GDALDatasetH hSrcDS,
-                                              GDALRasterBandH hSrcBand,
-                                              GDALDataType eDstDataType,
-                                              int bDstHasNoData,
-                                              double dfDstNoDataValue,
-                                              GDALGeneric3x3ProcessingAlg pfnAlg,
-                                              void* pAlgData,
-                                              int bComputeAtEdges);
-                       ~GDALGeneric3x3Dataset();
-
-    CPLErr      GetGeoTransform( double * padfGeoTransform );
-    const char *GetProjectionRef();
-};
-
-/************************************************************************/
-/* ==================================================================== */
-/*                    GDALGeneric3x3RasterBand                       */
-/* ==================================================================== */
-/************************************************************************/
-
-class GDALGeneric3x3RasterBand : public GDALRasterBand
-{
-    friend class GDALGeneric3x3Dataset;
-    int bSrcHasNoData;
-    float fSrcNoDataValue;
-    int bIsSrcNoDataNan;
-    
-    void                    InitWidthNoData(void* pImage);
-    
-  public:
-                 GDALGeneric3x3RasterBand( GDALGeneric3x3Dataset *poDS,
-                                           GDALDataType eDstDataType );
-    
-    virtual CPLErr          IReadBlock( int, int, void * );
-    virtual double          GetNoDataValue( int* pbHasNoData );
-};
-
-GDALGeneric3x3Dataset::GDALGeneric3x3Dataset(
-                                     GDALDatasetH hSrcDS,
-                                     GDALRasterBandH hSrcBand,
-                                     GDALDataType eDstDataType,
-                                     int bDstHasNoData,
-                                     double dfDstNoDataValue,
-                                     GDALGeneric3x3ProcessingAlg pfnAlg,
-                                     void* pAlgData,
-                                     int bComputeAtEdges)
-{
-    this->hSrcDS = hSrcDS;
-    this->hSrcBand = hSrcBand;
-    this->pfnAlg = pfnAlg;
-    this->pAlgData = pAlgData;
-    this->bDstHasNoData = bDstHasNoData;
-    this->dfDstNoDataValue = dfDstNoDataValue;
-    this->bComputeAtEdges = bComputeAtEdges;
-    
-    CPLAssert(eDstDataType == GDT_Byte || eDstDataType == GDT_Float32);
-
-    nRasterXSize = GDALGetRasterXSize(hSrcDS);
-    nRasterYSize = GDALGetRasterYSize(hSrcDS);
-    
-    SetBand(1, new GDALGeneric3x3RasterBand(this, eDstDataType));
-    
-    apafSourceBuf[0] = (float *) CPLMalloc(sizeof(float)*nRasterXSize);
-    apafSourceBuf[1] = (float *) CPLMalloc(sizeof(float)*nRasterXSize);
-    apafSourceBuf[2] = (float *) CPLMalloc(sizeof(float)*nRasterXSize);
-
-    nCurLine = -1;
-}
-
-GDALGeneric3x3Dataset::~GDALGeneric3x3Dataset()
-{
-    CPLFree(apafSourceBuf[0]);
-    CPLFree(apafSourceBuf[1]);
-    CPLFree(apafSourceBuf[2]);
-}
-
-CPLErr GDALGeneric3x3Dataset::GetGeoTransform( double * padfGeoTransform )
-{
-    return GDALGetGeoTransform(hSrcDS, padfGeoTransform);
-}
-
-const char *GDALGeneric3x3Dataset::GetProjectionRef()
-{
-    return GDALGetProjectionRef(hSrcDS);
-}
-
-GDALGeneric3x3RasterBand::GDALGeneric3x3RasterBand(GDALGeneric3x3Dataset *poDS,
-                                                   GDALDataType eDstDataType)
-{
-    this->poDS = poDS;
-    this->nBand = 1;
-    eDataType = eDstDataType;
-    nBlockXSize = poDS->GetRasterXSize();
-    nBlockYSize = 1;
-
-    bSrcHasNoData = FALSE;
-    fSrcNoDataValue = (float)GDALGetRasterNoDataValue(poDS->hSrcBand,
-                                                      &bSrcHasNoData);
-    bIsSrcNoDataNan = bSrcHasNoData && CPLIsNan(fSrcNoDataValue);
-}
-
-void   GDALGeneric3x3RasterBand::InitWidthNoData(void* pImage)
-{
-    int j;
-    GDALGeneric3x3Dataset * poGDS = (GDALGeneric3x3Dataset *) poDS;
-    if (eDataType == GDT_Byte)
-    {
-        for(j=0;j<nBlockXSize;j++)
-            ((GByte*)pImage)[j] = (GByte) poGDS->dfDstNoDataValue;
-    }
-    else
-    {
-        for(j=0;j<nBlockXSize;j++)
-            ((float*)pImage)[j] = (float) poGDS->dfDstNoDataValue;
-    }
-}
-
-CPLErr GDALGeneric3x3RasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
-                                             int nBlockYOff,
-                                             void *pImage )
-{
-    int i, j;
-    float fVal;
-    GDALGeneric3x3Dataset * poGDS = (GDALGeneric3x3Dataset *) poDS;
-
-    if (poGDS->bComputeAtEdges && nRasterXSize >= 2 && nRasterYSize >= 2)
-    {
-        if (nBlockYOff == 0)
-        {
-            for(i=0;i<2;i++)
-            {
-                CPLErr eErr = GDALRasterIO( poGDS->hSrcBand,
-                                    GF_Read,
-                                    0, i, nBlockXSize, 1,
-                                    poGDS->apafSourceBuf[i+1],
-                                    nBlockXSize, 1,
-                                    GDT_Float32,
-                                    0, 0);
-                if (eErr != CE_None)
-                {
-                    InitWidthNoData(pImage);
-                    return eErr;
-                }
-            }
-            poGDS->nCurLine = 0;
-
-            for (j = 0; j < nRasterXSize; j++)
-            {
-                float afWin[9];
-                int jmin = (j == 0) ? j : j - 1;
-                int jmax = (j == nRasterXSize - 1) ? j : j + 1;
-
-                afWin[0] = INTERPOL(poGDS->apafSourceBuf[1][jmin], poGDS->apafSourceBuf[2][jmin]);
-                afWin[1] = INTERPOL(poGDS->apafSourceBuf[1][j],    poGDS->apafSourceBuf[2][j]);
-                afWin[2] = INTERPOL(poGDS->apafSourceBuf[1][jmax], poGDS->apafSourceBuf[2][jmax]);
-                afWin[3] = poGDS->apafSourceBuf[1][jmin];
-                afWin[4] = poGDS->apafSourceBuf[1][j];
-                afWin[5] = poGDS->apafSourceBuf[1][jmax];
-                afWin[6] = poGDS->apafSourceBuf[2][jmin];
-                afWin[7] = poGDS->apafSourceBuf[2][j];
-                afWin[8] = poGDS->apafSourceBuf[2][jmax];
-
-                fVal = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
-                                  bIsSrcNoDataNan,
-                                    afWin, (float) poGDS->dfDstNoDataValue,
-                                    poGDS->pfnAlg,
-                                    poGDS->pAlgData,
-                                    poGDS->bComputeAtEdges);
-
-                if (eDataType == GDT_Byte)
-                    ((GByte*)pImage)[j] = (GByte) (fVal + 0.5);
-                else
-                    ((float*)pImage)[j] = fVal;
-            }
-
-            return CE_None;
-        }
-        else if (nBlockYOff == nRasterYSize - 1)
-        {
-            if (poGDS->nCurLine != nRasterYSize - 2)
-            {
-                for(i=0;i<2;i++)
-                {
-                    CPLErr eErr = GDALRasterIO( poGDS->hSrcBand,
-                                        GF_Read,
-                                        0, nRasterYSize - 2 + i, nBlockXSize, 1,
-                                        poGDS->apafSourceBuf[i+1],
-                                        nBlockXSize, 1,
-                                        GDT_Float32,
-                                        0, 0);
-                    if (eErr != CE_None)
-                    {
-                        InitWidthNoData(pImage);
-                        return eErr;
-                    }
-                }
-            }
-
-            for (j = 0; j < nRasterXSize; j++)
-            {
-                float afWin[9];
-                int jmin = (j == 0) ? j : j - 1;
-                int jmax = (j == nRasterXSize - 1) ? j : j + 1;
-
-                afWin[0] = poGDS->apafSourceBuf[1][jmin];
-                afWin[1] = poGDS->apafSourceBuf[1][j];
-                afWin[2] = poGDS->apafSourceBuf[1][jmax];
-                afWin[3] = poGDS->apafSourceBuf[2][jmin];
-                afWin[4] = poGDS->apafSourceBuf[2][j];
-                afWin[5] = poGDS->apafSourceBuf[2][jmax];
-                afWin[6] = INTERPOL(poGDS->apafSourceBuf[2][jmin], poGDS->apafSourceBuf[1][jmin]);
-                afWin[7] = INTERPOL(poGDS->apafSourceBuf[2][j],    poGDS->apafSourceBuf[1][j]);
-                afWin[8] = INTERPOL(poGDS->apafSourceBuf[2][jmax], poGDS->apafSourceBuf[1][jmax]);
-
-                fVal = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
-                                  bIsSrcNoDataNan,
-                                    afWin, (float) poGDS->dfDstNoDataValue,
-                                    poGDS->pfnAlg,
-                                    poGDS->pAlgData,
-                                    poGDS->bComputeAtEdges);
-
-                if (eDataType == GDT_Byte)
-                    ((GByte*)pImage)[j] = (GByte) (fVal + 0.5);
-                else
-                    ((float*)pImage)[j] = fVal;
-            }
-
-            return CE_None;
-        }
-    }
-    else if ( nBlockYOff == 0 || nBlockYOff == nRasterYSize - 1)
-    {
-        InitWidthNoData(pImage);
-        return CE_None;
-    }
-
-    if ( poGDS->nCurLine != nBlockYOff )
-    {
-        if (poGDS->nCurLine + 1 == nBlockYOff)
-        {
-            float* pafTmp =  poGDS->apafSourceBuf[0];
-            poGDS->apafSourceBuf[0] = poGDS->apafSourceBuf[1];
-            poGDS->apafSourceBuf[1] = poGDS->apafSourceBuf[2];
-            poGDS->apafSourceBuf[2] = pafTmp;
-
-            CPLErr eErr = GDALRasterIO( poGDS->hSrcBand,
-                                    GF_Read,
-                                    0, nBlockYOff + 1, nBlockXSize, 1,
-                                    poGDS->apafSourceBuf[2],
-                                    nBlockXSize, 1,
-                                    GDT_Float32,
-                                    0, 0);
-
-            if (eErr != CE_None)
-            {
-                InitWidthNoData(pImage);
-                return eErr;
-            }
-        }
-        else
-        {
-            for(i=0;i<3;i++)
-            {
-                CPLErr eErr = GDALRasterIO( poGDS->hSrcBand,
-                                    GF_Read,
-                                    0, nBlockYOff + i - 1, nBlockXSize, 1,
-                                    poGDS->apafSourceBuf[i],
-                                    nBlockXSize, 1,
-                                    GDT_Float32,
-                                    0, 0);
-                if (eErr != CE_None)
-                {
-                    InitWidthNoData(pImage);
-                    return eErr;
-                }
-            }
-        }
-
-        poGDS->nCurLine = nBlockYOff;
-    }
-
-    if (poGDS->bComputeAtEdges && nRasterXSize >= 2)
-    {
-        float afWin[9];
-
-        j = 0;
-        afWin[0] = INTERPOL(poGDS->apafSourceBuf[0][j], poGDS->apafSourceBuf[0][j+1]);
-        afWin[1] = poGDS->apafSourceBuf[0][j];
-        afWin[2] = poGDS->apafSourceBuf[0][j+1];
-        afWin[3] = INTERPOL(poGDS->apafSourceBuf[1][j], poGDS->apafSourceBuf[1][j+1]);
-        afWin[4] = poGDS->apafSourceBuf[1][j];
-        afWin[5] = poGDS->apafSourceBuf[1][j+1];
-        afWin[6] = INTERPOL(poGDS->apafSourceBuf[2][j], poGDS->apafSourceBuf[2][j+1]);
-        afWin[7] = poGDS->apafSourceBuf[2][j];
-        afWin[8] = poGDS->apafSourceBuf[2][j+1];
-
-        fVal = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
-                          bIsSrcNoDataNan,
-                                    afWin, (float) poGDS->dfDstNoDataValue,
-                                    poGDS->pfnAlg,
-                                    poGDS->pAlgData,
-                                    poGDS->bComputeAtEdges);
-
-        if (eDataType == GDT_Byte)
-            ((GByte*)pImage)[j] = (GByte) (fVal + 0.5);
-        else
-            ((float*)pImage)[j] = fVal;
-
-        j = nRasterXSize - 1;
-
-        afWin[0] = poGDS->apafSourceBuf[0][j-1];
-        afWin[1] = poGDS->apafSourceBuf[0][j];
-        afWin[2] = INTERPOL(poGDS->apafSourceBuf[0][j], poGDS->apafSourceBuf[0][j-1]);
-        afWin[3] = poGDS->apafSourceBuf[1][j-1];
-        afWin[4] = poGDS->apafSourceBuf[1][j];
-        afWin[5] = INTERPOL(poGDS->apafSourceBuf[1][j], poGDS->apafSourceBuf[1][j-1]);
-        afWin[6] = poGDS->apafSourceBuf[2][j-1];
-        afWin[7] = poGDS->apafSourceBuf[2][j];
-        afWin[8] = INTERPOL(poGDS->apafSourceBuf[2][j], poGDS->apafSourceBuf[2][j-1]);
-
-        fVal = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
-                          bIsSrcNoDataNan,
-                                    afWin, (float) poGDS->dfDstNoDataValue,
-                                    poGDS->pfnAlg,
-                                    poGDS->pAlgData,
-                                    poGDS->bComputeAtEdges);
-
-        if (eDataType == GDT_Byte)
-            ((GByte*)pImage)[j] = (GByte) (fVal + 0.5);
-        else
-            ((float*)pImage)[j] = fVal;
-    }
-    else
-    {
-        if (eDataType == GDT_Byte)
-        {
-            ((GByte*)pImage)[0] = (GByte) poGDS->dfDstNoDataValue;
-            if (nBlockXSize > 1)
-                ((GByte*)pImage)[nBlockXSize - 1] = (GByte) poGDS->dfDstNoDataValue;
-        }
-        else
-        {
-            ((float*)pImage)[0] = (float) poGDS->dfDstNoDataValue;
-            if (nBlockXSize > 1)
-                ((float*)pImage)[nBlockXSize - 1] = (float) poGDS->dfDstNoDataValue;
-        }
-    }
-
-
-    for(j=1;j<nBlockXSize - 1;j++)
-    {
-        float afWin[9];
-        afWin[0] = poGDS->apafSourceBuf[0][j-1];
-        afWin[1] = poGDS->apafSourceBuf[0][j];
-        afWin[2] = poGDS->apafSourceBuf[0][j+1];
-        afWin[3] = poGDS->apafSourceBuf[1][j-1];
-        afWin[4] = poGDS->apafSourceBuf[1][j];
-        afWin[5] = poGDS->apafSourceBuf[1][j+1];
-        afWin[6] = poGDS->apafSourceBuf[2][j-1];
-        afWin[7] = poGDS->apafSourceBuf[2][j];
-        afWin[8] = poGDS->apafSourceBuf[2][j+1];
-
-        fVal = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
-                          bIsSrcNoDataNan,
-                                afWin, (float) poGDS->dfDstNoDataValue,
-                                poGDS->pfnAlg,
-                                poGDS->pAlgData,
-                                poGDS->bComputeAtEdges);
-
-        if (eDataType == GDT_Byte)
-            ((GByte*)pImage)[j] = (GByte) (fVal + 0.5);
-        else
-            ((float*)pImage)[j] = fVal;
-
-    }
-
-    return CE_None;
-}
-
-double GDALGeneric3x3RasterBand::GetNoDataValue( int* pbHasNoData )
-{
-    GDALGeneric3x3Dataset * poGDS = (GDALGeneric3x3Dataset *) poDS;
-    if (pbHasNoData)
-        *pbHasNoData = poGDS->bDstHasNoData;
-    return poGDS->dfDstNoDataValue;
-}
-
-/************************************************************************/
-/*                            ArgIsNumeric()                            */
-/************************************************************************/
-
-static int ArgIsNumeric( const char *pszArg )
-
-{
-    return CPLGetValueType(pszArg) != CPL_VALUE_STRING;
-}
-/************************************************************************/
-/*                                main()                                */
-/************************************************************************/
-
-typedef enum
-{
-    HILL_SHADE,
-    SLOPE,
-    ASPECT,
-    COLOR_RELIEF,
-    TRI,
-    TPI,
-    ROUGHNESS
-} Algorithm;
-
-#define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg) \
-    do { if (i + nExtraArg >= argc) \
-        Usage(CPLSPrintf("%s option requires %d argument(s)", argv[i], nExtraArg)); } while(0)
-
-int main( int argc, char ** argv )
-
-{
-    Algorithm eUtilityMode = HILL_SHADE;
-    double z = 1.0;
-    double scale = 1.0;
-    double az = 315.0;
-    double alt = 45.0;
-    // 0 = 'percent' or 1 = 'degrees'
-    int slopeFormat = 1; 
-    int bAddAlpha = FALSE;
-    int bZeroForFlat = FALSE;
-    int bAngleAsAzimuth = TRUE;
-    ColorSelectionMode eColorSelectionMode = COLOR_SELECTION_INTERPOLATE;
-    
-    int nBand = 1;
-    double  adfGeoTransform[6];
-
-    const char *pszSrcFilename = NULL;
-    const char *pszDstFilename = NULL;
-    const char *pszColorFilename = NULL;
-    const char *pszFormat = "GTiff";
-    int bFormatExplicitlySet = FALSE;
-    char **papszCreateOptions = NULL;
-    
-    GDALDatasetH hSrcDataset = NULL;
-    GDALDatasetH hDstDataset = NULL;
-    GDALRasterBandH hSrcBand = NULL;
-    GDALRasterBandH hDstBand = NULL;
-    GDALDriverH hDriver = NULL;
-
-    GDALProgressFunc pfnProgress = GDALTermProgress;
-    
-    int nXSize = 0;
-    int nYSize = 0;
-    
-    int bComputeAtEdges = FALSE;
-    int bZevenbergenThorne = FALSE;
-    int bCombined = FALSE;
-    int bQuiet = FALSE;
-    
-    /* Check strict compilation and runtime library version as we use C++ API */
-    if (! GDAL_CHECK_VERSION(argv[0]))
-        exit(1);
-
-    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
-    if( argc < 2 )
-    {
-        Usage("Not enough arguments.");
-    }
-
-    if( EQUAL(argv[1], "--utility_version") || EQUAL(argv[1], "--utility-version") )
-    {
-        printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
-                argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
-        return 0;
-    }
-    else if( EQUAL(argv[1],"--help") )
-        Usage();
-    else if ( EQUAL(argv[1], "shade") || EQUAL(argv[1], "hillshade") )
-    {
-        eUtilityMode = HILL_SHADE;
-    }
-    else if ( EQUAL(argv[1], "slope") )
-    {
-        eUtilityMode = SLOPE;
-    }
-    else if ( EQUAL(argv[1], "aspect") )
-    {
-        eUtilityMode = ASPECT;
-    }
-    else if ( EQUAL(argv[1], "color-relief") )
-    {
-        eUtilityMode = COLOR_RELIEF;
-    }
-    else if ( EQUAL(argv[1], "TRI") )
-    {
-        eUtilityMode = TRI;
-    }
-    else if ( EQUAL(argv[1], "TPI") )
-    {
-        eUtilityMode = TPI;
-    }
-    else if ( EQUAL(argv[1], "roughness") )
-    {
-        eUtilityMode = ROUGHNESS;
-    }
-    else
-    {
-        Usage("Missing valid sub-utility mention.");
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Parse arguments.                                                */
-/* -------------------------------------------------------------------- */
-    for(int i = 2; i < argc; i++ )
-    {
-        if( eUtilityMode == HILL_SHADE &&
-            (EQUAL(argv[i], "--z") || EQUAL(argv[i], "-z")))
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            ++i;
-            if( !ArgIsNumeric(argv[i]) )
-                Usage();
-            z = CPLAtof(argv[i]);
-        }
-        else if ( eUtilityMode == SLOPE && EQUAL(argv[i], "-p"))
-        {
-            slopeFormat = 0;
-        }
-        else if ( (eUtilityMode == HILL_SHADE || eUtilityMode == SLOPE ||
-                   eUtilityMode == ASPECT) && EQUAL(argv[i], "-alg") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            i ++;
-            if (EQUAL(argv[i], "ZevenbergenThorne"))
-                bZevenbergenThorne = TRUE;
-            else if (!EQUAL(argv[i], "Horn"))
-            {
-                Usage(CPLSPrintf("Wrong value for alg : %s.", argv[i]));
-            }
-        }
-        else if ( eUtilityMode == ASPECT && EQUAL(argv[i], "-trigonometric"))
-        {
-            bAngleAsAzimuth = FALSE;
-        }
-        else if ( eUtilityMode == ASPECT && EQUAL(argv[i], "-zero_for_flat"))
-        {
-            bZeroForFlat = TRUE;
-        }
-        else if ( eUtilityMode == COLOR_RELIEF && EQUAL(argv[i], "-exact_color_entry"))
-        {
-            eColorSelectionMode = COLOR_SELECTION_EXACT_ENTRY;
-        }
-        else if ( eUtilityMode == COLOR_RELIEF && EQUAL(argv[i], "-nearest_color_entry"))
-        {
-            eColorSelectionMode = COLOR_SELECTION_NEAREST_ENTRY;
-        }
-        else if( 
-            (EQUAL(argv[i], "--s") || 
-             EQUAL(argv[i], "-s") ||
-             EQUAL(argv[i], "--scale") ||
-             EQUAL(argv[i], "-scale"))
-          )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            ++i;
-            if( !ArgIsNumeric(argv[i]) )
-                Usage();
-            scale = CPLAtof(argv[i]);
-        }
-        else if( eUtilityMode == HILL_SHADE &&
-            (EQUAL(argv[i], "--az") || 
-             EQUAL(argv[i], "-az") ||
-             EQUAL(argv[i], "--azimuth") ||
-             EQUAL(argv[i], "-azimuth"))
-          )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            ++i;
-            if( !ArgIsNumeric(argv[i]) )
-                Usage();
-            az = CPLAtof(argv[i]);
-        }
-        else if( eUtilityMode == HILL_SHADE &&
-            (EQUAL(argv[i], "--alt") || 
-             EQUAL(argv[i], "-alt") ||
-             EQUAL(argv[i], "--alt") ||
-             EQUAL(argv[i], "-alt"))
-          )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            ++i;
-            if( !ArgIsNumeric(argv[i]) )
-                Usage();
-            alt = CPLAtof(argv[i]);
-        }
-        else if( eUtilityMode == HILL_SHADE &&
-            (EQUAL(argv[i], "-combined") || 
-             EQUAL(argv[i], "--combined"))
-          )
-        {
-            bCombined = TRUE;
-        }
-        else if( eUtilityMode == COLOR_RELIEF &&
-                 EQUAL(argv[i], "-alpha"))
-        {
-            bAddAlpha = TRUE;
-        }
-        else if( eUtilityMode != COLOR_RELIEF &&
-                 EQUAL(argv[i], "-compute_edges"))
-        {
-            bComputeAtEdges = TRUE;
-        }
-        else if( i + 1 < argc &&
-            (EQUAL(argv[i], "--b") || 
-             EQUAL(argv[i], "-b"))
-          )
-        {
-            nBand = atoi(argv[++i]);
-        }
-        else if ( EQUAL(argv[i], "-q") || EQUAL(argv[i], "-quiet") )
-        {
-            pfnProgress = GDALDummyProgress;
-            bQuiet = TRUE;
-        }
-        else if( EQUAL(argv[i],"-co") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            papszCreateOptions = CSLAddString( papszCreateOptions, argv[++i] );
-        }
-        else if( EQUAL(argv[i],"-of") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszFormat = argv[++i];
-            bFormatExplicitlySet = TRUE;
-        }
-        else if( argv[i][0] == '-' )
-        {
-            Usage(CPLSPrintf("Unknown option name '%s'", argv[i]));
-        }
-        else if( pszSrcFilename == NULL )
-        {
-            pszSrcFilename = argv[i];
-        }
-        else if( eUtilityMode == COLOR_RELIEF && pszColorFilename == NULL )
-        {
-            pszColorFilename = argv[i];
-        }
-        else if( pszDstFilename == NULL )
-        {
-            pszDstFilename = argv[i];
-        }
-        else
-            Usage("Too many command options.");
-    }
-
-    if( pszSrcFilename == NULL )
-    {
-        Usage("Missing source.");
-    }
-    if ( eUtilityMode == COLOR_RELIEF && pszColorFilename == NULL )
-    {
-        Usage("Missing color file.");
-    }
-    if( pszDstFilename == NULL )
-    {
-        Usage("Missing destination.");
-    }
-
-    GDALAllRegister();
-
-    // Open Dataset and get raster band
-    hSrcDataset = GDALOpen( pszSrcFilename, GA_ReadOnly );
-    
-    if( hSrcDataset == NULL )
-    {
-        fprintf( stderr,
-                 "GDALOpen failed - %d\n%s\n",
-                 CPLGetLastErrorNo(), CPLGetLastErrorMsg() );
-        GDALDestroyDriverManager();
-        exit( 1 );
-    }
-
-    nXSize = GDALGetRasterXSize(hSrcDataset);
-    nYSize = GDALGetRasterYSize(hSrcDataset);
-
-    if( nBand <= 0 || nBand > GDALGetRasterCount(hSrcDataset) )
-    {
-        fprintf( stderr,
-                 "Unable to fetch band #%d\n", nBand );
-        GDALDestroyDriverManager();
-        exit( 1 );
-    }
-    hSrcBand = GDALGetRasterBand( hSrcDataset, nBand );
-
-    GDALGetGeoTransform(hSrcDataset, adfGeoTransform);
-
-    hDriver = GDALGetDriverByName(pszFormat);
-    if( hDriver == NULL 
-        || (GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) == NULL &&
-            GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY, NULL ) == NULL))
-    {
-        int	iDr;
-
-        fprintf( stderr, "Output driver `%s' not recognised to have\n", 
-                 pszFormat );
-        fprintf( stderr, "output support.  The following format drivers are configured\n"
-                "and support output:\n" );
-
-        for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
-        {
-            GDALDriverH hDriver = GDALGetDriver(iDr);
-
-            if( GDALGetMetadataItem( hDriver, GDAL_DCAP_RASTER, NULL) != NULL &&
-                (GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) != NULL ||
-                 GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY, NULL ) != NULL) )
-            {
-                printf( "  %s: %s\n",
-                        GDALGetDriverShortName( hDriver  ),
-                        GDALGetDriverLongName( hDriver ) );
-            }
-        }
-        GDALDestroyDriverManager();
-        exit( 1 );
-    }
-
-    if (!bQuiet && !bFormatExplicitlySet)
-        CheckExtensionConsistency(pszDstFilename, pszFormat);
-
-    double dfDstNoDataValue = 0;
-    int bDstHasNoData = FALSE;
-    void* pData = NULL;
-    GDALGeneric3x3ProcessingAlg pfnAlg = NULL;
-
-    if (eUtilityMode == HILL_SHADE)
-    {
-        dfDstNoDataValue = 0;
-        bDstHasNoData = TRUE;
-        pData = GDALCreateHillshadeData   (adfGeoTransform,
-                                           z,
-                                           scale,
-                                           alt,
-                                           az,
-                                           bZevenbergenThorne);
-        if (bZevenbergenThorne)
-        {
-            if(!bCombined)
-                pfnAlg = GDALHillshadeZevenbergenThorneAlg;
-            else
-                pfnAlg = GDALHillshadeZevenbergenThorneCombinedAlg;
-        }
-        else
-        {
-            if(!bCombined)
-                pfnAlg = GDALHillshadeAlg;
-            else
-                pfnAlg = GDALHillshadeCombinedAlg;
-        }
-    }
-    else if (eUtilityMode == SLOPE)
-    {
-        dfDstNoDataValue = -9999;
-        bDstHasNoData = TRUE;
-
-        pData = GDALCreateSlopeData(adfGeoTransform, scale, slopeFormat);
-        if (bZevenbergenThorne)
-            pfnAlg = GDALSlopeZevenbergenThorneAlg;
-        else
-            pfnAlg = GDALSlopeHornAlg;
-    }
-
-    else if (eUtilityMode == ASPECT)
-    {
-        if (!bZeroForFlat)
-        {
-            dfDstNoDataValue = -9999;
-            bDstHasNoData = TRUE;
-        }
-
-        pData = GDALCreateAspectData(bAngleAsAzimuth);
-        if (bZevenbergenThorne)
-            pfnAlg = GDALAspectZevenbergenThorneAlg;
-        else
-            pfnAlg = GDALAspectAlg;
-    }
-    else if (eUtilityMode == TRI)
-    {
-        dfDstNoDataValue = -9999;
-        bDstHasNoData = TRUE;
-        pfnAlg = GDALTRIAlg;
-    }
-    else if (eUtilityMode == TPI)
-    {
-        dfDstNoDataValue = -9999;
-        bDstHasNoData = TRUE;
-        pfnAlg = GDALTPIAlg;
-    }
-    else if (eUtilityMode == ROUGHNESS)
-    {
-        dfDstNoDataValue = -9999;
-        bDstHasNoData = TRUE;
-        pfnAlg = GDALRoughnessAlg;
-    }
-    
-    GDALDataType eDstDataType = (eUtilityMode == HILL_SHADE ||
-                                 eUtilityMode == COLOR_RELIEF) ? GDT_Byte :
-                                                               GDT_Float32;
-
-    if( EQUAL(pszFormat, "VRT") )
-    {
-        if (eUtilityMode == COLOR_RELIEF)
-        {
-            GDALGenerateVRTColorRelief(pszDstFilename,
-                                       hSrcDataset,
-                                       hSrcBand,
-                                       pszColorFilename,
-                                       eColorSelectionMode,
-                                       bAddAlpha);
-            GDALClose(hSrcDataset);
-        
-            CPLFree(pData);
-
-            GDALDestroyDriverManager();
-            CSLDestroy( argv );
-            CSLDestroy( papszCreateOptions );
-        
-            return 0;
-        }
-        else
-        {
-            fprintf(stderr, "VRT driver can only be used with color-relief utility\n");
-            GDALDestroyDriverManager();
-
-            exit(1);
-        }
-    }
-    
-    // We might actually want to always go through the intermediate dataset
-    int bForceUseIntermediateDataset = FALSE;
-    if( EQUAL(pszFormat, "GTiff") )
-    {
-        if( !EQUAL(CSLFetchNameValueDef(papszCreateOptions, "COMPRESS", "NONE"), "NONE") &&
-            CSLTestBoolean(CSLFetchNameValueDef(papszCreateOptions, "TILED", "NO")) )
-        {
-            bForceUseIntermediateDataset = TRUE;
-        }
-        else if( strcmp(pszDstFilename, "/vsistdout/") == 0 )
-        {
-            bForceUseIntermediateDataset = TRUE;
-            pfnProgress = GDALDummyProgress;
-            bQuiet = TRUE;
-        }
-#ifdef S_ISFIFO
-        else
-        {
-            VSIStatBufL sStat;
-            if( VSIStatExL(pszDstFilename, &sStat, VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG) == 0 &&
-                S_ISFIFO(sStat.st_mode) )
-            {
-                bForceUseIntermediateDataset = TRUE;
-            }
-        }
-#endif
-    }
-
-    if( GDALGetMetadataItem( hDriver, GDAL_DCAP_RASTER, NULL) != NULL &&
-        ((bForceUseIntermediateDataset || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) == NULL) &&
-         GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY, NULL ) != NULL) )
-    {
-        GDALDatasetH hIntermediateDataset;
-        
-        if (eUtilityMode == COLOR_RELIEF)
-            hIntermediateDataset = (GDALDatasetH)
-                new GDALColorReliefDataset (hSrcDataset,
-                                            hSrcBand,
-                                            pszColorFilename,
-                                            eColorSelectionMode,
-                                            bAddAlpha);
-        else
-            hIntermediateDataset = (GDALDatasetH)
-                new GDALGeneric3x3Dataset(hSrcDataset, hSrcBand,
-                                          eDstDataType,
-                                          bDstHasNoData,
-                                          dfDstNoDataValue,
-                                          pfnAlg,
-                                          pData,
-                                          bComputeAtEdges);
-
-        GDALDatasetH hOutDS = GDALCreateCopy(
-                                 hDriver, pszDstFilename, hIntermediateDataset, 
-                                 TRUE, papszCreateOptions, 
-                                 pfnProgress, NULL );
-
-        if( hOutDS != NULL )
-            GDALClose( hOutDS );
-        GDALClose(hIntermediateDataset);
-        GDALClose(hSrcDataset);
-        
-        CPLFree(pData);
-
-        GDALDestroyDriverManager();
-        CSLDestroy( argv );
-        CSLDestroy( papszCreateOptions );
-        
-        return 0;
-    }
-
-    int nDstBands;
-    if (eUtilityMode == COLOR_RELIEF)
-        nDstBands = (bAddAlpha) ? 4 : 3;
-    else
-        nDstBands = 1;
-
-    hDstDataset = GDALCreate(   hDriver,
-                                pszDstFilename,
-                                nXSize,
-                                nYSize,
-                                nDstBands,
-                                eDstDataType,
-                                papszCreateOptions);
-
-    if( hDstDataset == NULL )
-    {
-        fprintf( stderr,
-                 "Unable to create dataset %s %d\n%s\n", pszDstFilename,
-                 CPLGetLastErrorNo(), CPLGetLastErrorMsg() );
-        GDALDestroyDriverManager();
-        exit( 1 );
-    }
-    
-    hDstBand = GDALGetRasterBand( hDstDataset, 1 );
-
-    GDALSetGeoTransform(hDstDataset, adfGeoTransform);
-    GDALSetProjection(hDstDataset, GDALGetProjectionRef(hSrcDataset));
-    
-    if (eUtilityMode == COLOR_RELIEF)
-    {
-        GDALColorRelief (hSrcBand, 
-                         GDALGetRasterBand(hDstDataset, 1),
-                         GDALGetRasterBand(hDstDataset, 2),
-                         GDALGetRasterBand(hDstDataset, 3),
-                         (bAddAlpha) ? GDALGetRasterBand(hDstDataset, 4) : NULL,
-                         pszColorFilename,
-                         eColorSelectionMode,
-                         pfnProgress, NULL);
-    }
-    else
-    {
-        if (bDstHasNoData)
-            GDALSetRasterNoDataValue(hDstBand, dfDstNoDataValue);
-        
-        GDALGeneric3x3Processing(hSrcBand, hDstBand,
-                                 pfnAlg, pData,
-                                 bComputeAtEdges,
-                                 pfnProgress, NULL);
-                                    
-    }
-
-    GDALClose(hSrcDataset);
-    GDALClose(hDstDataset);
-    CPLFree(pData);
-
-    GDALDestroyDriverManager();
-    CSLDestroy( argv );
-    CSLDestroy( papszCreateOptions );
-
-    return 0;
-}
diff --git a/apps/gdaldem_bin.cpp b/apps/gdaldem_bin.cpp
new file mode 100644
index 0000000..b9fcf70
--- /dev/null
+++ b/apps/gdaldem_bin.cpp
@@ -0,0 +1,216 @@
+/******************************************************************************
+ * $Id: gdaldem_bin.cpp 33615 2016-03-02 20:19:22Z goatbar $
+ *
+ * Project:  GDAL DEM Utilities
+ * Purpose:
+ * Authors:  Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_vsi.h"
+#include <stdlib.h>
+#include <math.h>
+
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "gdal_utils_priv.h"
+#include "gdal_priv.h"
+#include "commonutils.h"
+
+CPL_CVSID("$Id: gdaldem_bin.cpp 33615 2016-03-02 20:19:22Z goatbar $");
+
+/************************************************************************/
+/*                               Usage()                                */
+/************************************************************************/
+
+static void Usage(const char* pszErrorMsg = NULL)
+
+{
+    printf( " Usage: \n"
+            " - To generate a shaded relief map from any GDAL-supported elevation raster : \n\n"
+            "     gdaldem hillshade input_dem output_hillshade \n"
+            "                 [-z ZFactor (default=1)] [-s scale* (default=1)] \n"
+            "                 [-az Azimuth (default=315)] [-alt Altitude (default=45)]\n"
+            "                 [-alg ZevenbergenThorne] [-combined]\n"
+            "                 [-compute_edges] [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
+            "\n"
+            " - To generates a slope map from any GDAL-supported elevation raster :\n\n"
+            "     gdaldem slope input_dem output_slope_map \n"
+            "                 [-p use percent slope (default=degrees)] [-s scale* (default=1)]\n"
+            "                 [-alg ZevenbergenThorne]\n"
+            "                 [-compute_edges] [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
+            "\n"
+            " - To generate an aspect map from any GDAL-supported elevation raster\n"
+            "   Outputs a 32-bit float tiff with pixel values from 0-360 indicating azimuth :\n\n"
+            "     gdaldem aspect input_dem output_aspect_map \n"
+            "                 [-trigonometric] [-zero_for_flat]\n"
+            "                 [-alg ZevenbergenThorne]\n"
+            "                 [-compute_edges] [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
+            "\n"
+            " - To generate a color relief map from any GDAL-supported elevation raster\n"
+            "     gdaldem color-relief input_dem color_text_file output_color_relief_map\n"
+            "                 [-alpha] [-exact_color_entry | -nearest_color_entry]\n"
+            "                 [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
+            "     where color_text_file contains lines of the format \"elevation_value red green blue\"\n"
+            "\n"
+            " - To generate a Terrain Ruggedness Index (TRI) map from any GDAL-supported elevation raster\n"
+            "     gdaldem TRI input_dem output_TRI_map\n"
+            "                 [-compute_edges] [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
+            "\n"
+            " - To generate a Topographic Position Index (TPI) map from any GDAL-supported elevation raster\n"
+            "     gdaldem TPI input_dem output_TPI_map\n"
+            "                 [-compute_edges] [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
+            "\n"
+            " - To generate a roughness map from any GDAL-supported elevation raster\n"
+            "     gdaldem roughness input_dem output_roughness_map\n"
+            "                 [-compute_edges] [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
+            "\n"
+            " Notes : \n"
+            "   Scale is the ratio of vertical units to horizontal\n"
+            "    for Feet:Latlong use scale=370400, for Meters:LatLong use scale=111120 \n\n");
+
+    if( pszErrorMsg != NULL )
+        fprintf(stderr, "\nFAILURE: %s\n", pszErrorMsg);
+
+    exit( 1 );
+}
+
+/************************************************************************/
+/*                       GDALDEMProcessingOptionsForBinaryNew()             */
+/************************************************************************/
+
+static GDALDEMProcessingOptionsForBinary *GDALDEMProcessingOptionsForBinaryNew(void)
+{
+    return (GDALDEMProcessingOptionsForBinary*) CPLCalloc(  1, sizeof(GDALDEMProcessingOptionsForBinary) );
+}
+
+/************************************************************************/
+/*                       GDALDEMProcessingOptionsForBinaryFree()            */
+/************************************************************************/
+
+static void GDALDEMProcessingOptionsForBinaryFree( GDALDEMProcessingOptionsForBinary* psOptionsForBinary )
+{
+    if( psOptionsForBinary )
+    {
+        CPLFree(psOptionsForBinary->pszProcessing);
+        CPLFree(psOptionsForBinary->pszSrcFilename);
+        CPLFree(psOptionsForBinary->pszColorFilename);
+        CPLFree(psOptionsForBinary->pszDstFilename);
+        CPLFree(psOptionsForBinary->pszFormat);
+        CPLFree(psOptionsForBinary);
+    }
+}
+/************************************************************************/
+/*                                main()                                */
+/************************************************************************/
+
+int main( int argc, char ** argv )
+
+{
+    /* Check strict compilation and runtime library version as we use C++ API */
+    if (! GDAL_CHECK_VERSION(argv[0]))
+        exit(1);
+
+    EarlySetConfigOptions(argc, argv);
+
+/* -------------------------------------------------------------------- */
+/*      Register standard GDAL drivers, and process generic GDAL        */
+/*      command options.                                                */
+/* -------------------------------------------------------------------- */
+    GDALAllRegister();
+    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
+    if( argc < 2 )
+    {
+        Usage("Not enough arguments.");
+    }
+
+    if( EQUAL(argv[1], "--utility_version") || EQUAL(argv[1], "--utility-version") )
+    {
+        printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
+                argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
+        CSLDestroy( argv );
+        return 0;
+    }
+    else if( EQUAL(argv[1],"--help") )
+        Usage();
+
+    GDALDEMProcessingOptionsForBinary* psOptionsForBinary = GDALDEMProcessingOptionsForBinaryNew();
+    GDALDEMProcessingOptions *psOptions = GDALDEMProcessingOptionsNew(argv + 1, psOptionsForBinary);
+    CSLDestroy( argv );
+
+    if( psOptions == NULL )
+    {
+        Usage();
+    }
+
+    if( !(psOptionsForBinary->bQuiet) )
+    {
+        GDALDEMProcessingOptionsSetProgress(psOptions, GDALTermProgress, NULL);
+    }
+
+    if( psOptionsForBinary->pszSrcFilename == NULL )
+    {
+        Usage("Missing source.");
+    }
+    if ( EQUAL(psOptionsForBinary->pszProcessing, "color-relief") && psOptionsForBinary->pszColorFilename == NULL )
+    {
+        Usage("Missing color file.");
+    }
+    if( psOptionsForBinary->pszDstFilename == NULL )
+    {
+        Usage("Missing destination.");
+    }
+
+    if (!psOptionsForBinary->bQuiet && !psOptionsForBinary->bFormatExplicitlySet)
+        CheckExtensionConsistency(psOptionsForBinary->pszDstFilename, psOptionsForBinary->pszFormat);
+
+    // Open Dataset and get raster band
+    GDALDatasetH hSrcDataset = GDALOpen( psOptionsForBinary->pszSrcFilename, GA_ReadOnly );
+
+    if( hSrcDataset == NULL )
+    {
+        fprintf( stderr,
+                 "GDALOpen failed - %d\n%s\n",
+                 CPLGetLastErrorNo(), CPLGetLastErrorMsg() );
+        GDALDestroyDriverManager();
+        exit( 1 );
+    }
+
+    int bUsageError = FALSE;
+    GDALDatasetH hOutDS = GDALDEMProcessing(psOptionsForBinary->pszDstFilename, hSrcDataset,
+                               psOptionsForBinary->pszProcessing,
+                               psOptionsForBinary->pszColorFilename,
+                               psOptions, &bUsageError);
+    if(bUsageError == TRUE)
+        Usage();
+    int nRetCode = (hOutDS) ? 0 : 1;
+
+    GDALClose(hSrcDataset);
+    GDALClose(hOutDS);
+    GDALDEMProcessingOptionsFree(psOptions);
+    GDALDEMProcessingOptionsForBinaryFree(psOptionsForBinary);
+
+    GDALDestroyDriverManager();
+
+    return nRetCode;
+}
diff --git a/apps/gdaldem_lib.cpp b/apps/gdaldem_lib.cpp
new file mode 100644
index 0000000..204b8d5
--- /dev/null
+++ b/apps/gdaldem_lib.cpp
@@ -0,0 +1,3096 @@
+/******************************************************************************
+ * $Id: gdaldem_lib.cpp 33782 2016-03-24 10:41:09Z rouault $
+ *
+ * Project:  GDAL DEM Utilities
+ * Purpose:
+ * Authors:  Matthew Perry, perrygeo at gmail.com
+ *           Even Rouault, even dot rouault at mines dash paris dot org
+ *           Howard Butler, hobu.inc at gmail.com
+ *           Chris Yesson, chris dot yesson at ioz dot ac dot uk
+ *
+ ******************************************************************************
+ * Copyright (c) 2006, 2009 Matthew Perry
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ * Portions derived from GRASS 4.1 (public domain) See
+ * http://trac.osgeo.org/gdal/ticket/2975 for more information regarding
+ * history of this code
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************
+ *
+ * Slope and aspect calculations based on original method for GRASS GIS 4.1
+ * by Michael Shapiro, U.S.Army Construction Engineering Research Laboratory
+ *    Olga Waupotitsch, U.S.Army Construction Engineering Research Laboratory
+ *    Marjorie Larson, U.S.Army Construction Engineering Research Laboratory
+ * as found in GRASS's r.slope.aspect module.
+ *
+ * Horn's formula is used to find the first order derivatives in x and y directions
+ * for slope and aspect calculations: Horn, B. K. P. (1981).
+ * "Hill Shading and the Reflectance Map", Proceedings of the IEEE, 69(1):14-47.
+ *
+ * Other reference :
+ * Burrough, P.A. and McDonell, R.A., 1998. Principles of Geographical Information
+ * Systems. p. 190.
+ *
+ * Shaded relief based on original method for GRASS GIS 4.1 by Jim Westervelt,
+ * U.S. Army Construction Engineering Research Laboratory
+ * as found in GRASS's r.shaded.relief (formerly shade.rel.sh) module.
+ * ref: "r.mapcalc: An Algebra for GIS and Image Processing",
+ * by Michael Shapiro and Jim Westervelt, U.S. Army Construction Engineering
+ * Research Laboratory (March/1991)
+ *
+ * Color table of named colors and lookup code derived from src/libes/gis/named_colr.c
+ * of GRASS 4.1
+ *
+ * TRI - Terrain Ruggedness Index is as described in Wilson et al. (2007)
+ * this is based on the method of Valentine et al. (2004)
+ *
+ * TPI - Topographic Position Index follows the description in
+ * Wilson et al. (2007), following Weiss (2001).  The radius is fixed
+ * at 1 cell width/height
+ *
+ * Roughness - follows the definition in Wilson et al. (2007), which follows
+ * Dartnell (2000).
+ *
+ * References for TRI/TPI/Roughness:
+ * Dartnell, P. 2000. Applying Remote Sensing Techniques to map Seafloor
+ *  Geology/Habitat Relationships. Masters Thesis, San Francisco State
+ *  University, pp. 108.
+ * Valentine, P. C., S. J. Fuller, L. A. Scully. 2004. Terrain Ruggedness
+ *  Analysis and Distribution of Boulder Ridges in the Stellwagen Bank National
+ *  Marine Sanctuary Region (poster). Galway, Ireland: 5th International
+ *  Symposium on Marine Geological and Biological Habitat Mapping (GeoHAB),
+ *  May 2004.
+ * Weiss, A. D. 2001. Topographic Positions and Landforms Analysis (poster),
+ *  ESRI International User Conference, July 2001. San Diego, CA: ESRI.
+ * Wilson, M. F. J.; O'Connell, B.; Brown, C.; Guinan, J. C. & Grehan, A. J.
+ *  Multiscale terrain analysis of multibeam bathymetry data for habitat mapping
+ *  on the continental slope Marine Geodesy, 2007, 30, 3-35
+ ****************************************************************************/
+
+#include "cpl_vsi.h"
+#include <algorithm>
+#include <float.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "gdal.h"
+#include "gdal_priv.h"
+#include "gdal_utils_priv.h"
+
+CPL_CVSID("$Id: gdaldem_lib.cpp 33782 2016-03-24 10:41:09Z rouault $");
+
+#define INTERPOL(a,b) ((bSrcHasNoData && (ARE_REAL_EQUAL(a, fSrcNoDataValue) || ARE_REAL_EQUAL(b, fSrcNoDataValue))) ? fSrcNoDataValue : 2 * (a) - (b))
+
+typedef enum
+{
+    COLOR_SELECTION_INTERPOLATE,
+    COLOR_SELECTION_NEAREST_ENTRY,
+    COLOR_SELECTION_EXACT_ENTRY
+} ColorSelectionMode;
+
+struct GDALDEMProcessingOptions
+{
+    /*! output format. The default is GeoTIFF(GTiff). Use the short format name. */
+    char *pszFormat;
+
+    /*! the progress function to use */
+    GDALProgressFunc pfnProgress;
+
+    /*! pointer to the progress data variable */
+    void *pProgressData;
+
+    double z;
+    double scale;
+    double az;
+    double alt;
+    int slopeFormat;
+    int bAddAlpha;
+    int bZeroForFlat;
+    int bAngleAsAzimuth ;
+    ColorSelectionMode eColorSelectionMode;
+    int bComputeAtEdges;
+    int bZevenbergenThorne;
+    int bCombined;
+    char** papszCreateOptions;
+    int nBand;
+};
+
+/************************************************************************/
+/*                          ComputeVal()                                */
+/************************************************************************/
+
+typedef float (*GDALGeneric3x3ProcessingAlg) (float* pafWindow, float fDstNoDataValue, void* pData);
+
+static float ComputeVal(int bSrcHasNoData, float fSrcNoDataValue,
+                        int bIsSrcNoDataNan,
+                        float* afWin, float fDstNoDataValue,
+                        GDALGeneric3x3ProcessingAlg pfnAlg,
+                        void* pData,
+                        int bComputeAtEdges)
+{
+    if (bSrcHasNoData &&
+            ((!bIsSrcNoDataNan && ARE_REAL_EQUAL(afWin[4], fSrcNoDataValue)) ||
+             (bIsSrcNoDataNan && CPLIsNan(afWin[4]))))
+    {
+        return fDstNoDataValue;
+    }
+    else if (bSrcHasNoData)
+    {
+        int k;
+        for(k=0;k<9;k++)
+        {
+            if ((!bIsSrcNoDataNan && ARE_REAL_EQUAL(afWin[k], fSrcNoDataValue)) ||
+                (bIsSrcNoDataNan && CPLIsNan(afWin[k])))
+            {
+                if (bComputeAtEdges)
+                    afWin[k] = afWin[4];
+                else
+                    return fDstNoDataValue;
+            }
+        }
+    }
+
+    return pfnAlg(afWin, fDstNoDataValue, pData);
+}
+
+/************************************************************************/
+/*                  GDALGeneric3x3Processing()                          */
+/************************************************************************/
+
+static
+CPLErr GDALGeneric3x3Processing  ( GDALRasterBandH hSrcBand,
+                                   GDALRasterBandH hDstBand,
+                                   GDALGeneric3x3ProcessingAlg pfnAlg,
+                                   void* pData,
+                                   int bComputeAtEdges,
+                                   GDALProgressFunc pfnProgress,
+                                   void * pProgressData)
+{
+    CPLErr eErr;
+    float *pafThreeLineWin; /* 3 line rotating source buffer */
+    float *pafOutputBuf;     /* 1 line destination buffer */
+    int i, j;
+
+    int bSrcHasNoData, bDstHasNoData;
+    float fSrcNoDataValue = 0.0, fDstNoDataValue = 0.0;
+
+    int nXSize = GDALGetRasterBandXSize(hSrcBand);
+    int nYSize = GDALGetRasterBandYSize(hSrcBand);
+
+    if (pfnProgress == NULL)
+        pfnProgress = GDALDummyProgress;
+
+/* -------------------------------------------------------------------- */
+/*      Initialize progress counter.                                    */
+/* -------------------------------------------------------------------- */
+    if( !pfnProgress( 0.0, NULL, pProgressData ) )
+    {
+        CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
+        return CE_Failure;
+    }
+
+    pafOutputBuf = (float *) VSI_MALLOC2_VERBOSE(sizeof(float),nXSize);
+    pafThreeLineWin  = (float *) VSI_MALLOC2_VERBOSE(3*sizeof(float),(nXSize+1));
+    if( pafOutputBuf == NULL || pafThreeLineWin == NULL )
+    {
+        VSIFree(pafOutputBuf);
+        VSIFree(pafThreeLineWin);
+        return CE_Failure;
+    }
+
+    fSrcNoDataValue = (float) GDALGetRasterNoDataValue(hSrcBand, &bSrcHasNoData);
+    fDstNoDataValue = (float) GDALGetRasterNoDataValue(hDstBand, &bDstHasNoData);
+    if (!bDstHasNoData)
+        fDstNoDataValue = 0.0;
+    int bIsSrcNoDataNan = bSrcHasNoData && CPLIsNan(fSrcNoDataValue);
+
+    int nLine1Off = 0*nXSize;
+    int nLine2Off = 1*nXSize;
+    int nLine3Off = 2*nXSize;
+
+    // Move a 3x3 pafWindow over each cell
+    // (where the cell in question is #4)
+    //
+    //      0 1 2
+    //      3 4 5
+    //      6 7 8
+
+    /* Preload the first 2 lines */
+    for ( i = 0; i < 2 && i < nYSize; i++)
+    {
+        if( GDALRasterIO(   hSrcBand,
+                        GF_Read,
+                        0, i,
+                        nXSize, 1,
+                        pafThreeLineWin + i * nXSize,
+                        nXSize, 1,
+                        GDT_Float32,
+                        0, 0) != CE_None )
+        {
+            eErr = CE_Failure;
+            goto end;
+        }
+    }
+
+    if (bComputeAtEdges && nXSize >= 2 && nYSize >= 2)
+    {
+        for (j = 0; j < nXSize; j++)
+        {
+            float afWin[9];
+            int jmin = (j == 0) ? j : j - 1;
+            int jmax = (j == nXSize - 1) ? j : j + 1;
+
+            afWin[0] = INTERPOL(pafThreeLineWin[jmin], pafThreeLineWin[nXSize + jmin]);
+            afWin[1] = INTERPOL(pafThreeLineWin[j],    pafThreeLineWin[nXSize + j]);
+            afWin[2] = INTERPOL(pafThreeLineWin[jmax], pafThreeLineWin[nXSize + jmax]);
+            afWin[3] = pafThreeLineWin[jmin];
+            afWin[4] = pafThreeLineWin[j];
+            afWin[5] = pafThreeLineWin[jmax];
+            afWin[6] = pafThreeLineWin[nXSize + jmin];
+            afWin[7] = pafThreeLineWin[nXSize + j];
+            afWin[8] = pafThreeLineWin[nXSize + jmax];
+
+            pafOutputBuf[j] = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
+                                         bIsSrcNoDataNan,
+                                         afWin, fDstNoDataValue,
+                                         pfnAlg, pData, bComputeAtEdges);
+        }
+        eErr = GDALRasterIO(hDstBand, GF_Write,
+                    0, 0, nXSize, 1,
+                    pafOutputBuf, nXSize, 1, GDT_Float32, 0, 0);
+    }
+    else
+    {
+        // Exclude the edges
+        for (j = 0; j < nXSize; j++)
+        {
+            pafOutputBuf[j] = fDstNoDataValue;
+        }
+        eErr = GDALRasterIO(hDstBand, GF_Write,
+                    0, 0, nXSize, 1,
+                    pafOutputBuf, nXSize, 1, GDT_Float32, 0, 0);
+
+        if (eErr == CE_None && nYSize > 1)
+        {
+            eErr = GDALRasterIO(hDstBand, GF_Write,
+                        0, nYSize - 1, nXSize, 1,
+                        pafOutputBuf, nXSize, 1, GDT_Float32, 0, 0);
+        }
+    }
+    if( eErr != CE_None )
+        goto end;
+
+
+    for ( i = 1; i < nYSize-1; i++)
+    {
+        /* Read third line of the line buffer */
+        eErr = GDALRasterIO(   hSrcBand,
+                        GF_Read,
+                        0, i+1,
+                        nXSize, 1,
+                        pafThreeLineWin + nLine3Off,
+                        nXSize, 1,
+                        GDT_Float32,
+                        0, 0);
+        if (eErr != CE_None)
+            goto end;
+
+        if (bComputeAtEdges && nXSize >= 2)
+        {
+            float afWin[9];
+
+            j = 0;
+            afWin[0] = INTERPOL(pafThreeLineWin[nLine1Off + j], pafThreeLineWin[nLine1Off + j+1]);
+            afWin[1] = pafThreeLineWin[nLine1Off + j];
+            afWin[2] = pafThreeLineWin[nLine1Off + j+1];
+            afWin[3] = INTERPOL(pafThreeLineWin[nLine2Off + j], pafThreeLineWin[nLine2Off + j+1]);
+            afWin[4] = pafThreeLineWin[nLine2Off + j];
+            afWin[5] = pafThreeLineWin[nLine2Off + j+1];
+            afWin[6] = INTERPOL(pafThreeLineWin[nLine3Off + j], pafThreeLineWin[nLine3Off + j+1]);
+            afWin[7] = pafThreeLineWin[nLine3Off + j];
+            afWin[8] = pafThreeLineWin[nLine3Off + j+1];
+
+            pafOutputBuf[j] = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
+                                         bIsSrcNoDataNan,
+                                         afWin, fDstNoDataValue,
+                                         pfnAlg, pData, bComputeAtEdges);
+            j = nXSize - 1;
+
+            afWin[0] = pafThreeLineWin[nLine1Off + j-1];
+            afWin[1] = pafThreeLineWin[nLine1Off + j];
+            afWin[2] = INTERPOL(pafThreeLineWin[nLine1Off + j], pafThreeLineWin[nLine1Off + j-1]);
+            afWin[3] = pafThreeLineWin[nLine2Off + j-1];
+            afWin[4] = pafThreeLineWin[nLine2Off + j];
+            afWin[5] = INTERPOL(pafThreeLineWin[nLine2Off + j], pafThreeLineWin[nLine2Off + j-1]);
+            afWin[6] = pafThreeLineWin[nLine3Off + j-1];
+            afWin[7] = pafThreeLineWin[nLine3Off + j];
+            afWin[8] = INTERPOL(pafThreeLineWin[nLine3Off + j], pafThreeLineWin[nLine3Off + j-1]);
+
+            pafOutputBuf[j] = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
+                                         bIsSrcNoDataNan,
+                                         afWin, fDstNoDataValue,
+                                         pfnAlg, pData, bComputeAtEdges);
+        }
+        else
+        {
+            // Exclude the edges
+            pafOutputBuf[0] = fDstNoDataValue;
+            if (nXSize > 1)
+                pafOutputBuf[nXSize - 1] = fDstNoDataValue;
+        }
+
+        for (j = 1; j < nXSize - 1; j++)
+        {
+            float afWin[9];
+            afWin[0] = pafThreeLineWin[nLine1Off + j-1];
+            afWin[1] = pafThreeLineWin[nLine1Off + j];
+            afWin[2] = pafThreeLineWin[nLine1Off + j+1];
+            afWin[3] = pafThreeLineWin[nLine2Off + j-1];
+            afWin[4] = pafThreeLineWin[nLine2Off + j];
+            afWin[5] = pafThreeLineWin[nLine2Off + j+1];
+            afWin[6] = pafThreeLineWin[nLine3Off + j-1];
+            afWin[7] = pafThreeLineWin[nLine3Off + j];
+            afWin[8] = pafThreeLineWin[nLine3Off + j+1];
+
+            pafOutputBuf[j] = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
+                                         bIsSrcNoDataNan,
+                                         afWin, fDstNoDataValue,
+                                         pfnAlg, pData, bComputeAtEdges);
+        }
+
+        /* -----------------------------------------
+         * Write Line to Raster
+         */
+        eErr = GDALRasterIO(hDstBand, GF_Write, 0, i, nXSize, 1,
+                     pafOutputBuf, nXSize, 1, GDT_Float32, 0, 0);
+        if (eErr != CE_None)
+            goto end;
+
+        if( !pfnProgress( 1.0 * (i+1) / nYSize, NULL, pProgressData ) )
+        {
+            CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
+            eErr = CE_Failure;
+            goto end;
+        }
+
+        int nTemp = nLine1Off;
+        nLine1Off = nLine2Off;
+        nLine2Off = nLine3Off;
+        nLine3Off = nTemp;
+    }
+
+    if (bComputeAtEdges && nXSize >= 2 && nYSize >= 2)
+    {
+        for (j = 0; j < nXSize; j++)
+        {
+            float afWin[9];
+            int jmin = (j == 0) ? j : j - 1;
+            int jmax = (j == nXSize - 1) ? j : j + 1;
+
+            afWin[0] = pafThreeLineWin[nLine1Off + jmin];
+            afWin[1] = pafThreeLineWin[nLine1Off + j];
+            afWin[2] = pafThreeLineWin[nLine1Off + jmax];
+            afWin[3] = pafThreeLineWin[nLine2Off + jmin];
+            afWin[4] = pafThreeLineWin[nLine2Off + j];
+            afWin[5] = pafThreeLineWin[nLine2Off + jmax];
+            afWin[6] = INTERPOL(pafThreeLineWin[nLine2Off + jmin], pafThreeLineWin[nLine1Off + jmin]);
+            afWin[7] = INTERPOL(pafThreeLineWin[nLine2Off + j],    pafThreeLineWin[nLine1Off + j]);
+            afWin[8] = INTERPOL(pafThreeLineWin[nLine2Off + jmax], pafThreeLineWin[nLine1Off + jmax]);
+
+            pafOutputBuf[j] = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
+                                         bIsSrcNoDataNan,
+                                         afWin, fDstNoDataValue,
+                                         pfnAlg, pData, bComputeAtEdges);
+        }
+        eErr = GDALRasterIO(hDstBand, GF_Write,
+                     0, i, nXSize, 1,
+                     pafOutputBuf, nXSize, 1, GDT_Float32, 0, 0);
+        if( eErr != CE_None )
+            goto end;
+    }
+
+    pfnProgress( 1.0, NULL, pProgressData );
+    eErr = CE_None;
+
+end:
+    CPLFree(pafOutputBuf);
+    CPLFree(pafThreeLineWin);
+
+    return eErr;
+}
+
+
+/************************************************************************/
+/*                         GDALHillshade()                              */
+/************************************************************************/
+
+typedef struct
+{
+    double nsres;
+    double ewres;
+    double sin_altRadians;
+    double cos_altRadians_mul_z_scale_factor;
+    double azRadians;
+    double square_z_scale_factor;
+    double square_M_PI_2;
+} GDALHillshadeAlgData;
+
+/* Unoptimized formulas are :
+    x = psData->z*((afWin[0] + afWin[3] + afWin[3] + afWin[6]) -
+        (afWin[2] + afWin[5] + afWin[5] + afWin[8])) /
+        (8.0 * psData->ewres * psData->scale);
+
+    y = psData->z*((afWin[6] + afWin[7] + afWin[7] + afWin[8]) -
+        (afWin[0] + afWin[1] + afWin[1] + afWin[2])) /
+        (8.0 * psData->nsres * psData->scale);
+
+    slope = M_PI / 2 - atan(sqrt(x*x + y*y));
+
+    aspect = atan2(y,x);
+
+    cang = sin(alt * degreesToRadians) * sin(slope) +
+           cos(alt * degreesToRadians) * cos(slope) *
+           cos(az * degreesToRadians - M_PI/2 - aspect);
+*/
+
+static
+float GDALHillshadeAlg (float* afWin, CPL_UNUSED float fDstNoDataValue, void* pData)
+{
+    GDALHillshadeAlgData* psData = (GDALHillshadeAlgData*)pData;
+    double x, y, aspect, xx_plus_yy, cang;
+
+    // First Slope ...
+    x = ((afWin[0] + afWin[3] + afWin[3] + afWin[6]) -
+        (afWin[2] + afWin[5] + afWin[5] + afWin[8])) / psData->ewres;
+
+    y = ((afWin[6] + afWin[7] + afWin[7] + afWin[8]) -
+        (afWin[0] + afWin[1] + afWin[1] + afWin[2])) / psData->nsres;
+
+    xx_plus_yy = x * x + y * y;
+
+    // ... then aspect...
+    aspect = atan2(y,x);
+
+    // ... then the shade value
+    cang = (psData->sin_altRadians -
+           psData->cos_altRadians_mul_z_scale_factor * sqrt(xx_plus_yy) *
+           sin(aspect - psData->azRadians)) /
+           sqrt(1 + psData->square_z_scale_factor * xx_plus_yy);
+
+    if (cang <= 0.0)
+        cang = 1.0;
+    else
+        cang = 1.0 + (254.0 * cang);
+
+    return (float) cang;
+}
+
+static
+float GDALHillshadeCombinedAlg (float* afWin, CPL_UNUSED float fDstNoDataValue, void* pData)
+{
+    GDALHillshadeAlgData* psData = (GDALHillshadeAlgData*)pData;
+    double x, y, aspect, xx_plus_yy, cang;
+
+    // First Slope ...
+    x = ((afWin[0] + afWin[3] + afWin[3] + afWin[6]) -
+        (afWin[2] + afWin[5] + afWin[5] + afWin[8])) / psData->ewres;
+
+    y = ((afWin[6] + afWin[7] + afWin[7] + afWin[8]) -
+        (afWin[0] + afWin[1] + afWin[1] + afWin[2])) / psData->nsres;
+
+    xx_plus_yy = x * x + y * y;
+
+    // ... then aspect...
+    aspect = atan2(y,x);
+    double slope = xx_plus_yy * psData->square_z_scale_factor;
+
+    // ... then the shade value
+    cang = acos((psData->sin_altRadians -
+           psData->cos_altRadians_mul_z_scale_factor * sqrt(xx_plus_yy) *
+           sin(aspect - psData->azRadians)) /
+           sqrt(1 + slope));
+
+    // combined shading
+    cang = 1 - cang * atan(sqrt(slope)) / psData->square_M_PI_2;
+
+    if (cang <= 0.0)
+        cang = 1.0;
+    else
+        cang = 1.0 + (254.0 * cang);
+
+    return (float) cang;
+}
+
+static
+float GDALHillshadeZevenbergenThorneAlg (float* afWin, CPL_UNUSED float fDstNoDataValue, void* pData)
+{
+    GDALHillshadeAlgData* psData = (GDALHillshadeAlgData*)pData;
+    double x, y, aspect, xx_plus_yy, cang;
+
+    // First Slope ...
+    x = (afWin[3] - afWin[5]) / psData->ewres;
+
+    y = (afWin[7] - afWin[1]) / psData->nsres;
+
+    xx_plus_yy = x * x + y * y;
+
+    // ... then aspect...
+    aspect = atan2(y,x);
+
+    // ... then the shade value
+    cang = (psData->sin_altRadians -
+           psData->cos_altRadians_mul_z_scale_factor * sqrt(xx_plus_yy) *
+           sin(aspect - psData->azRadians)) /
+           sqrt(1 + psData->square_z_scale_factor * xx_plus_yy);
+
+    if (cang <= 0.0)
+        cang = 1.0;
+    else
+        cang = 1.0 + (254.0 * cang);
+
+    return (float) cang;
+}
+
+static
+float GDALHillshadeZevenbergenThorneCombinedAlg (float* afWin, CPL_UNUSED float fDstNoDataValue, void* pData)
+{
+    GDALHillshadeAlgData* psData = (GDALHillshadeAlgData*)pData;
+    double x, y, aspect, xx_plus_yy, cang;
+
+    // First Slope ...
+    x = (afWin[3] - afWin[5]) / psData->ewres;
+
+    y = (afWin[7] - afWin[1]) / psData->nsres;
+
+    xx_plus_yy = x * x + y * y;
+
+    // ... then aspect...
+    aspect = atan2(y,x);
+    double slope = xx_plus_yy * psData->square_z_scale_factor;
+
+    // ... then the shade value
+    cang = acos((psData->sin_altRadians -
+           psData->cos_altRadians_mul_z_scale_factor * sqrt(xx_plus_yy) *
+           sin(aspect - psData->azRadians)) /
+           sqrt(1 + slope));
+
+    // combined shading
+    cang = 1 - cang * atan(sqrt(slope)) / psData->square_M_PI_2;
+
+    if (cang <= 0.0)
+        cang = 1.0;
+    else
+        cang = 1.0 + (254.0 * cang);
+
+    return (float) cang;
+}
+
+static
+void*  GDALCreateHillshadeData(double* adfGeoTransform,
+                               double z,
+                               double scale,
+                               double alt,
+                               double az,
+                               int bZevenbergenThorne)
+{
+    GDALHillshadeAlgData* pData =
+        (GDALHillshadeAlgData*)CPLMalloc(sizeof(GDALHillshadeAlgData));
+
+    const double degreesToRadians = M_PI / 180.0;
+    pData->nsres = adfGeoTransform[5];
+    pData->ewres = adfGeoTransform[1];
+    pData->sin_altRadians = sin(alt * degreesToRadians);
+    pData->azRadians = az * degreesToRadians;
+    double z_scale_factor = z / (((bZevenbergenThorne) ? 2 : 8) * scale);
+    pData->cos_altRadians_mul_z_scale_factor =
+        cos(alt * degreesToRadians) * z_scale_factor;
+    pData->square_z_scale_factor = z_scale_factor * z_scale_factor;
+    pData->square_M_PI_2 = (M_PI*M_PI)/4;
+    return pData;
+}
+
+/************************************************************************/
+/*                         GDALSlope()                                  */
+/************************************************************************/
+
+typedef struct
+{
+    double nsres;
+    double ewres;
+    double scale;
+    int    slopeFormat;
+} GDALSlopeAlgData;
+
+static
+float GDALSlopeHornAlg (float* afWin, CPL_UNUSED float fDstNoDataValue, void* pData)
+{
+    const double radiansToDegrees = 180.0 / M_PI;
+    GDALSlopeAlgData* psData = (GDALSlopeAlgData*)pData;
+    double dx, dy, key;
+
+    dx = ((afWin[0] + afWin[3] + afWin[3] + afWin[6]) -
+          (afWin[2] + afWin[5] + afWin[5] + afWin[8]))/psData->ewres;
+
+    dy = ((afWin[6] + afWin[7] + afWin[7] + afWin[8]) -
+          (afWin[0] + afWin[1] + afWin[1] + afWin[2]))/psData->nsres;
+
+    key = (dx * dx + dy * dy);
+
+    if (psData->slopeFormat == 1)
+        return (float) (atan(sqrt(key) / (8*psData->scale)) * radiansToDegrees);
+    else
+        return (float) (100*(sqrt(key) / (8*psData->scale)));
+}
+
+static
+float GDALSlopeZevenbergenThorneAlg (float* afWin, CPL_UNUSED float fDstNoDataValue, void* pData)
+{
+    const double radiansToDegrees = 180.0 / M_PI;
+    GDALSlopeAlgData* psData = (GDALSlopeAlgData*)pData;
+    double dx, dy, key;
+
+    dx = (afWin[3] - afWin[5])/psData->ewres;
+
+    dy = (afWin[7] - afWin[1])/psData->nsres;
+
+    key = (dx * dx + dy * dy);
+
+    if (psData->slopeFormat == 1)
+        return (float) (atan(sqrt(key) / (2*psData->scale)) * radiansToDegrees);
+    else
+        return (float) (100*(sqrt(key) / (2*psData->scale)));
+}
+
+static
+void*  GDALCreateSlopeData(double* adfGeoTransform,
+                           double scale,
+                           int slopeFormat)
+{
+    GDALSlopeAlgData* pData =
+        (GDALSlopeAlgData*)CPLMalloc(sizeof(GDALSlopeAlgData));
+
+    pData->nsres = adfGeoTransform[5];
+    pData->ewres = adfGeoTransform[1];
+    pData->scale = scale;
+    pData->slopeFormat = slopeFormat;
+    return pData;
+}
+
+/************************************************************************/
+/*                         GDALAspect()                                 */
+/************************************************************************/
+
+typedef struct
+{
+    int bAngleAsAzimuth;
+} GDALAspectAlgData;
+
+static
+float GDALAspectAlg (float* afWin, float fDstNoDataValue, void* pData)
+{
+    const double degreesToRadians = M_PI / 180.0;
+    GDALAspectAlgData* psData = (GDALAspectAlgData*)pData;
+    double dx, dy;
+    float aspect;
+
+    dx = ((afWin[2] + afWin[5] + afWin[5] + afWin[8]) -
+          (afWin[0] + afWin[3] + afWin[3] + afWin[6]));
+
+    dy = ((afWin[6] + afWin[7] + afWin[7] + afWin[8]) -
+          (afWin[0] + afWin[1] + afWin[1] + afWin[2]));
+
+    aspect = (float) (atan2(dy,-dx) / degreesToRadians);
+
+    if (dx == 0 && dy == 0)
+    {
+        /* Flat area */
+        aspect = fDstNoDataValue;
+    }
+    else if ( psData->bAngleAsAzimuth )
+    {
+        if (aspect > 90.0)
+            aspect = 450.0f - aspect;
+        else
+            aspect = 90.0f - aspect;
+    }
+    else
+    {
+        if (aspect < 0)
+            aspect += 360.0;
+    }
+
+    if (aspect == 360.0)
+        aspect = 0.0;
+
+    return aspect;
+}
+
+static
+float GDALAspectZevenbergenThorneAlg (float* afWin, float fDstNoDataValue, void* pData)
+{
+    const double degreesToRadians = M_PI / 180.0;
+    GDALAspectAlgData* psData = (GDALAspectAlgData*)pData;
+    double dx, dy;
+    float aspect;
+
+    dx = (afWin[5] - afWin[3]);
+
+    dy = (afWin[7] - afWin[1]);
+
+    aspect = (float) (atan2(dy,-dx) / degreesToRadians);
+
+    if (dx == 0 && dy == 0)
+    {
+        /* Flat area */
+        aspect = fDstNoDataValue;
+    }
+    else if ( psData->bAngleAsAzimuth )
+    {
+        if (aspect > 90.0)
+            aspect = 450.0f - aspect;
+        else
+            aspect = 90.0f - aspect;
+    }
+    else
+    {
+        if (aspect < 0)
+            aspect += 360.0;
+    }
+
+    if (aspect == 360.0)
+        aspect = 0.0;
+
+    return aspect;
+}
+
+static
+void*  GDALCreateAspectData(int bAngleAsAzimuth)
+{
+    GDALAspectAlgData* pData =
+        (GDALAspectAlgData*)CPLMalloc(sizeof(GDALAspectAlgData));
+
+    pData->bAngleAsAzimuth = bAngleAsAzimuth;
+    return pData;
+}
+
+/************************************************************************/
+/*                      GDALColorRelief()                               */
+/************************************************************************/
+
+typedef struct
+{
+    double dfVal;
+    int nR;
+    int nG;
+    int nB;
+    int nA;
+} ColorAssociation;
+
+static int GDALColorReliefSortColors(const ColorAssociation &pA,
+                                     const ColorAssociation &pB)
+{
+    /* Sort NaN in first position */
+    return (CPLIsNan(pA.dfVal) && !CPLIsNan(pB.dfVal)) || pA.dfVal < pB.dfVal;
+}
+
+static void GDALColorReliefProcessColors(ColorAssociation **ppasColorAssociation,
+                                         int *pnColorAssociation, int bSrcHasNoData,
+                                         double dfSrcNoDataValue)
+{
+    ColorAssociation *pasColorAssociation = *ppasColorAssociation;
+    int nColorAssociation = *pnColorAssociation;
+
+    std::stable_sort(pasColorAssociation, pasColorAssociation + nColorAssociation,
+                     GDALColorReliefSortColors);
+
+    ColorAssociation *pPrevious =
+            (nColorAssociation > 0) ? &pasColorAssociation[0] : NULL;
+    int nAdded = 0;
+    int nRepeatedEntryIndex = 0;
+    for (int i = 1; i < nColorAssociation; ++i)
+    {
+        ColorAssociation *pCurrent = &pasColorAssociation[i];
+
+        // NaN comparison is always false, so it handles itself
+        if (bSrcHasNoData && pCurrent->dfVal == dfSrcNoDataValue)
+        {
+            // check if there is enough distance between the nodata value and its
+            // predecessor
+            double dfNewValue =
+                    pCurrent->dfVal - ABS(pCurrent->dfVal) * DBL_EPSILON;
+            if (dfNewValue > pPrevious->dfVal)
+            {
+                // add one just below the nodata value
+                ++nAdded;
+                ColorAssociation sPrevious = *pPrevious;
+                pasColorAssociation = (ColorAssociation *)CPLRealloc(pasColorAssociation,
+                        (nColorAssociation + nAdded) * sizeof(ColorAssociation));
+                pCurrent = &pasColorAssociation[i];
+                pPrevious = NULL;
+                pasColorAssociation[nColorAssociation + nAdded - 1] = sPrevious;
+                pasColorAssociation[nColorAssociation + nAdded - 1].dfVal = dfNewValue;
+            }
+        }
+        else if (bSrcHasNoData && pPrevious->dfVal == dfSrcNoDataValue)
+        {
+            // check if there is enough distance between the nodata value and its
+            // successor
+            double dfNewValue = pPrevious->dfVal + ABS(pPrevious->dfVal) * DBL_EPSILON;
+            if (dfNewValue < pCurrent->dfVal)
+            {
+                // add one just above the nodata value
+                ++nAdded;
+                ColorAssociation sCurrent = *pCurrent;
+                pasColorAssociation = (ColorAssociation *)CPLRealloc(pasColorAssociation,
+                        (nColorAssociation + nAdded) * sizeof(ColorAssociation));
+                pCurrent = &pasColorAssociation[i];
+                pPrevious = NULL;
+                pasColorAssociation[nColorAssociation + nAdded - 1] = sCurrent;
+                pasColorAssociation[nColorAssociation + nAdded - 1].dfVal = dfNewValue;
+            }
+        }
+        else if (nRepeatedEntryIndex == 0 && pCurrent->dfVal == pPrevious->dfVal)
+        {
+            // second of a series of equivalent entries
+            nRepeatedEntryIndex = i;
+        }
+        else if (nRepeatedEntryIndex != 0 && pCurrent->dfVal != pPrevious->dfVal)
+        {
+            // get the distance between the predecessor and successor of the equivalent
+            // entries
+            double dfTotalDist, dfLeftDist;
+            if (nRepeatedEntryIndex >= 2)
+            {
+                ColorAssociation *pLower = &pasColorAssociation[nRepeatedEntryIndex - 2];
+                dfTotalDist = pCurrent->dfVal - pLower->dfVal;
+                dfLeftDist = pPrevious->dfVal - pLower->dfVal;
+            }
+            else
+            {
+                dfTotalDist = pCurrent->dfVal - pPrevious->dfVal;
+                dfLeftDist = 0;
+            }
+
+            // check if this distance is enough
+            int nEquivalentCount = i - nRepeatedEntryIndex + 1;
+            if (dfTotalDist > ABS(pPrevious->dfVal) * nEquivalentCount * DBL_EPSILON)
+            {
+                // balance the alterations
+                double dfMultiplier = 0.5 - nEquivalentCount * dfLeftDist / dfTotalDist;
+                for (int j = nRepeatedEntryIndex - 1; j < i; ++j)
+                {
+                    pasColorAssociation[j].dfVal +=
+                            (ABS(pPrevious->dfVal) * dfMultiplier) * DBL_EPSILON;
+                    dfMultiplier += 1.0;
+                }
+            }
+            else
+            {
+                // fallback to the old behaviour: keep equivalent entries as they are
+            }
+
+            nRepeatedEntryIndex = 0;
+        }
+        pPrevious = pCurrent;
+    }
+
+    if (nAdded)
+    {
+        std::stable_sort(pasColorAssociation,
+                         pasColorAssociation + nColorAssociation + nAdded,
+                         GDALColorReliefSortColors);
+        *ppasColorAssociation = pasColorAssociation;
+        *pnColorAssociation = nColorAssociation + nAdded;
+    }
+}
+
+static int GDALColorReliefGetRGBA (ColorAssociation* pasColorAssociation,
+                                   int nColorAssociation,
+                                   double dfVal,
+                                   ColorSelectionMode eColorSelectionMode,
+                                   int* pnR,
+                                   int* pnG,
+                                   int* pnB,
+                                   int* pnA)
+{
+    int i;
+    int lower = 0;
+    int upper = nColorAssociation - 1;
+    int mid;
+
+    // Special case for NaN
+    if( CPLIsNan(pasColorAssociation[0].dfVal) )
+    {
+        if( CPLIsNan(dfVal) )
+        {
+            *pnR = pasColorAssociation[0].nR;
+            *pnG = pasColorAssociation[0].nG;
+            *pnB = pasColorAssociation[0].nB;
+            *pnA = pasColorAssociation[0].nA;
+            return TRUE;
+        }
+        else
+            lower = 1;
+    }
+
+    /* Find the index of the first element in the LUT input array that */
+    /* is not smaller than the dfVal value. */
+    while( true )
+    {
+        mid = (lower + upper) / 2;
+        if (upper - lower <= 1)
+        {
+            if (dfVal <= pasColorAssociation[lower].dfVal)
+                i = lower;
+            else if (dfVal <= pasColorAssociation[upper].dfVal)
+                i = upper;
+            else
+                i = upper + 1;
+            break;
+        }
+        else if (pasColorAssociation[mid].dfVal >= dfVal)
+        {
+            upper = mid;
+        }
+        else
+        {
+            lower = mid;
+        }
+    }
+
+    if (i == 0)
+    {
+        if (eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY &&
+            pasColorAssociation[0].dfVal != dfVal)
+        {
+            *pnR = 0;
+            *pnG = 0;
+            *pnB = 0;
+            *pnA = 0;
+            return FALSE;
+        }
+        else
+        {
+            *pnR = pasColorAssociation[0].nR;
+            *pnG = pasColorAssociation[0].nG;
+            *pnB = pasColorAssociation[0].nB;
+            *pnA = pasColorAssociation[0].nA;
+            return TRUE;
+        }
+    }
+    else if (i == nColorAssociation)
+    {
+        if (eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY &&
+            pasColorAssociation[i-1].dfVal != dfVal)
+        {
+            *pnR = 0;
+            *pnG = 0;
+            *pnB = 0;
+            *pnA = 0;
+            return FALSE;
+        }
+        else
+        {
+            *pnR = pasColorAssociation[i-1].nR;
+            *pnG = pasColorAssociation[i-1].nG;
+            *pnB = pasColorAssociation[i-1].nB;
+            *pnA = pasColorAssociation[i-1].nA;
+            return TRUE;
+        }
+    }
+    else
+    {
+        if (eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY &&
+            pasColorAssociation[i-1].dfVal != dfVal)
+        {
+            *pnR = 0;
+            *pnG = 0;
+            *pnB = 0;
+            *pnA = 0;
+            return FALSE;
+        }
+
+        if (eColorSelectionMode == COLOR_SELECTION_NEAREST_ENTRY &&
+            pasColorAssociation[i-1].dfVal != dfVal)
+        {
+            int index;
+            if (dfVal - pasColorAssociation[i-1].dfVal <
+                pasColorAssociation[i].dfVal - dfVal)
+                index = i -1;
+            else
+                index = i;
+
+            *pnR = pasColorAssociation[index].nR;
+            *pnG = pasColorAssociation[index].nG;
+            *pnB = pasColorAssociation[index].nB;
+            *pnA = pasColorAssociation[index].nA;
+            return TRUE;
+        }
+
+        if (pasColorAssociation[i-1].dfVal == dfVal)
+        {
+            *pnR = pasColorAssociation[i-1].nR;
+            *pnG = pasColorAssociation[i-1].nG;
+            *pnB = pasColorAssociation[i-1].nB;
+            *pnA = pasColorAssociation[i-1].nA;
+            return TRUE;
+        }
+
+        double dfRatio = (dfVal - pasColorAssociation[i-1].dfVal) /
+            (pasColorAssociation[i].dfVal - pasColorAssociation[i-1].dfVal);
+        *pnR = (int)(0.45 + pasColorAssociation[i-1].nR + dfRatio *
+                (pasColorAssociation[i].nR - pasColorAssociation[i-1].nR));
+        if (*pnR < 0) *pnR = 0;
+        else if (*pnR > 255) *pnR = 255;
+        *pnG = (int)(0.45 + pasColorAssociation[i-1].nG + dfRatio *
+                (pasColorAssociation[i].nG - pasColorAssociation[i-1].nG));
+        if (*pnG < 0) *pnG = 0;
+        else if (*pnG > 255) *pnG = 255;
+        *pnB = (int)(0.45 + pasColorAssociation[i-1].nB + dfRatio *
+                (pasColorAssociation[i].nB - pasColorAssociation[i-1].nB));
+        if (*pnB < 0) *pnB = 0;
+        else if (*pnB > 255) *pnB = 255;
+        *pnA = (int)(0.45 + pasColorAssociation[i-1].nA + dfRatio *
+                (pasColorAssociation[i].nA - pasColorAssociation[i-1].nA));
+        if (*pnA < 0) *pnA = 0;
+        else if (*pnA > 255) *pnA = 255;
+
+        return TRUE;
+    }
+}
+
+/* dfPct : percentage between 0 and 1 */
+static double GDALColorReliefGetAbsoluteValFromPct(GDALRasterBandH hSrcBand,
+                                                   double dfPct)
+{
+    double dfMin, dfMax;
+    int bSuccessMin, bSuccessMax;
+    dfMin = GDALGetRasterMinimum(hSrcBand, &bSuccessMin);
+    dfMax = GDALGetRasterMaximum(hSrcBand, &bSuccessMax);
+    if (!bSuccessMin || !bSuccessMax)
+    {
+        double dfMean, dfStdDev;
+        fprintf(stderr, "Computing source raster statistics...\n");
+        GDALComputeRasterStatistics(hSrcBand, FALSE, &dfMin, &dfMax,
+                                    &dfMean, &dfStdDev, NULL, NULL);
+    }
+    return dfMin + dfPct * (dfMax - dfMin);
+}
+
+typedef struct
+{
+    const char *name;
+    float r, g, b;
+} NamedColor;
+
+static const NamedColor namedColors[] = {
+    { "white",  1.00, 1.00, 1.00 },
+    { "black",  0.00, 0.00, 0.00 },
+    { "red",    1.00, 0.00, 0.00 },
+    { "green",  0.00, 1.00, 0.00 },
+    { "blue",   0.00, 0.00, 1.00 },
+    { "yellow", 1.00, 1.00, 0.00 },
+    { "magenta",1.00, 0.00, 1.00 },
+    { "cyan",   0.00, 1.00, 1.00 },
+    { "aqua",   0.00, 0.75, 0.75 },
+    { "grey",   0.75, 0.75, 0.75 },
+    { "gray",   0.75, 0.75, 0.75 },
+    { "orange", 1.00, 0.50, 0.00 },
+    { "brown",  0.75, 0.50, 0.25 },
+    { "purple", 0.50, 0.00, 1.00 },
+    { "violet", 0.50, 0.00, 1.00 },
+    { "indigo", 0.00, 0.50, 1.00 },
+};
+
+static
+int GDALColorReliefFindNamedColor(const char *pszColorName, int *pnR, int *pnG, int *pnB)
+{
+    unsigned int i;
+
+    *pnR = *pnG = *pnB = 0;
+    for (i = 0; i < sizeof(namedColors) / sizeof(namedColors[0]); i++)
+    {
+        if (EQUAL(pszColorName, namedColors[i].name))
+        {
+            *pnR = (int)(255. * namedColors[i].r);
+            *pnG = (int)(255. * namedColors[i].g);
+            *pnB = (int)(255. * namedColors[i].b);
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+static
+ColorAssociation* GDALColorReliefParseColorFile(GDALRasterBandH hSrcBand,
+                                                const char* pszColorFilename,
+                                                int* pnColors)
+{
+    VSILFILE* fpColorFile = VSIFOpenL(pszColorFilename, "rt");
+    if (fpColorFile == NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s", pszColorFilename);
+        *pnColors = 0;
+        return NULL;
+    }
+
+    ColorAssociation* pasColorAssociation = NULL;
+    int nColorAssociation = 0;
+
+    int bSrcHasNoData = FALSE;
+    double dfSrcNoDataValue = GDALGetRasterNoDataValue(hSrcBand, &bSrcHasNoData);
+
+    const char* pszLine;
+    int bIsGMT_CPT = FALSE;
+    while ((pszLine = CPLReadLineL(fpColorFile)) != NULL)
+    {
+        if (pszLine[0] == '#' && strstr(pszLine, "COLOR_MODEL"))
+        {
+            if (strstr(pszLine, "COLOR_MODEL = RGB") == NULL)
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "Only COLOR_MODEL = RGB is supported");
+                CPLFree(pasColorAssociation);
+                *pnColors = 0;
+                return NULL;
+            }
+            bIsGMT_CPT = TRUE;
+        }
+
+        char** papszFields = CSLTokenizeStringComplex(pszLine, " ,\t:",
+                                                      FALSE, FALSE );
+        /* Skip comment lines */
+        int nTokens = CSLCount(papszFields);
+        if (nTokens >= 1 && (papszFields[0][0] == '#' ||
+                             papszFields[0][0] == '/'))
+        {
+            CSLDestroy(papszFields);
+            continue;
+        }
+
+        if (bIsGMT_CPT && nTokens == 8)
+        {
+            pasColorAssociation =
+                    (ColorAssociation*)CPLRealloc(pasColorAssociation,
+                           (nColorAssociation + 2) * sizeof(ColorAssociation));
+
+            pasColorAssociation[nColorAssociation].dfVal = CPLAtof(papszFields[0]);
+            pasColorAssociation[nColorAssociation].nR = atoi(papszFields[1]);
+            pasColorAssociation[nColorAssociation].nG = atoi(papszFields[2]);
+            pasColorAssociation[nColorAssociation].nB = atoi(papszFields[3]);
+            pasColorAssociation[nColorAssociation].nA = 255;
+            nColorAssociation++;
+
+            pasColorAssociation[nColorAssociation].dfVal = CPLAtof(papszFields[4]);
+            pasColorAssociation[nColorAssociation].nR = atoi(papszFields[5]);
+            pasColorAssociation[nColorAssociation].nG = atoi(papszFields[6]);
+            pasColorAssociation[nColorAssociation].nB = atoi(papszFields[7]);
+            pasColorAssociation[nColorAssociation].nA = 255;
+            nColorAssociation++;
+        }
+        else if (bIsGMT_CPT && nTokens == 4)
+        {
+            /* The first token might be B (background), F (foreground) or N (nodata) */
+            /* Just interested in N */
+            if (EQUAL(papszFields[0], "N") && bSrcHasNoData)
+            {
+                 pasColorAssociation =
+                    (ColorAssociation*)CPLRealloc(pasColorAssociation,
+                           (nColorAssociation + 1) * sizeof(ColorAssociation));
+
+                pasColorAssociation[nColorAssociation].dfVal = dfSrcNoDataValue;
+                pasColorAssociation[nColorAssociation].nR = atoi(papszFields[1]);
+                pasColorAssociation[nColorAssociation].nG = atoi(papszFields[2]);
+                pasColorAssociation[nColorAssociation].nB = atoi(papszFields[3]);
+                pasColorAssociation[nColorAssociation].nA = 255;
+                nColorAssociation++;
+            }
+        }
+        else if (!bIsGMT_CPT && nTokens >= 2)
+        {
+            pasColorAssociation =
+                    (ColorAssociation*)CPLRealloc(pasColorAssociation,
+                           (nColorAssociation + 1) * sizeof(ColorAssociation));
+            if (EQUAL(papszFields[0], "nv") && bSrcHasNoData)
+                pasColorAssociation[nColorAssociation].dfVal = dfSrcNoDataValue;
+            else if (strlen(papszFields[0]) > 1 && papszFields[0][strlen(papszFields[0])-1] == '%')
+            {
+                double dfPct = CPLAtof(papszFields[0]) / 100.;
+                if (dfPct < 0.0 || dfPct > 1.0)
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Wrong value for a percentage : %s", papszFields[0]);
+                    CSLDestroy(papszFields);
+                    VSIFCloseL(fpColorFile);
+                    CPLFree(pasColorAssociation);
+                    *pnColors = 0;
+                    return NULL;
+                }
+                pasColorAssociation[nColorAssociation].dfVal =
+                        GDALColorReliefGetAbsoluteValFromPct(hSrcBand, dfPct);
+            }
+            else
+                pasColorAssociation[nColorAssociation].dfVal = CPLAtof(papszFields[0]);
+
+            if (nTokens >= 4)
+            {
+                pasColorAssociation[nColorAssociation].nR = atoi(papszFields[1]);
+                pasColorAssociation[nColorAssociation].nG = atoi(papszFields[2]);
+                pasColorAssociation[nColorAssociation].nB = atoi(papszFields[3]);
+                pasColorAssociation[nColorAssociation].nA =
+                        (CSLCount(papszFields) >= 5 ) ? atoi(papszFields[4]) : 255;
+            }
+            else
+            {
+                int nR, nG, nB;
+                if (!GDALColorReliefFindNamedColor(papszFields[1], &nR, &nG, &nB))
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Unknown color : %s", papszFields[1]);
+                    CSLDestroy(papszFields);
+                    VSIFCloseL(fpColorFile);
+                    CPLFree(pasColorAssociation);
+                    *pnColors = 0;
+                    return NULL;
+                }
+                pasColorAssociation[nColorAssociation].nR = nR;
+                pasColorAssociation[nColorAssociation].nG = nG;
+                pasColorAssociation[nColorAssociation].nB = nB;
+                            pasColorAssociation[nColorAssociation].nA =
+                    (CSLCount(papszFields) >= 3 ) ? atoi(papszFields[2]) : 255;
+            }
+
+            nColorAssociation ++;
+        }
+        CSLDestroy(papszFields);
+    }
+    VSIFCloseL(fpColorFile);
+
+    if (nColorAssociation == 0)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "No color association found in %s", pszColorFilename);
+        *pnColors = 0;
+        return NULL;
+    }
+
+    GDALColorReliefProcessColors(&pasColorAssociation, &nColorAssociation,
+                                 bSrcHasNoData, dfSrcNoDataValue);
+
+    *pnColors = nColorAssociation;
+    return pasColorAssociation;
+}
+
+static
+GByte* GDALColorReliefPrecompute(GDALRasterBandH hSrcBand,
+                                 ColorAssociation* pasColorAssociation,
+                                 int nColorAssociation,
+                                 ColorSelectionMode eColorSelectionMode,
+                                 int* pnIndexOffset)
+{
+    GDALDataType eDT = GDALGetRasterDataType(hSrcBand);
+    GByte* pabyPrecomputed = NULL;
+    int nIndexOffset = (eDT == GDT_Int16) ? 32768 : 0;
+    *pnIndexOffset = nIndexOffset;
+    int nXSize = GDALGetRasterBandXSize(hSrcBand);
+    int nYSize = GDALGetRasterBandXSize(hSrcBand);
+    if (eDT == GDT_Byte ||
+        ((eDT == GDT_Int16 || eDT == GDT_UInt16) && nXSize * nYSize > 65536))
+    {
+        int iMax = (eDT == GDT_Byte) ? 256: 65536;
+        pabyPrecomputed = (GByte*) VSI_MALLOC2_VERBOSE(4, iMax);
+        if (pabyPrecomputed)
+        {
+            int i;
+            for(i=0;i<iMax;i++)
+            {
+                int nR, nG, nB, nA;
+                GDALColorReliefGetRGBA  (pasColorAssociation,
+                                         nColorAssociation,
+                                         i - nIndexOffset,
+                                         eColorSelectionMode,
+                                         &nR, &nG, &nB, &nA);
+                pabyPrecomputed[4 * i] = (GByte) nR;
+                pabyPrecomputed[4 * i + 1] = (GByte) nG;
+                pabyPrecomputed[4 * i + 2] = (GByte) nB;
+                pabyPrecomputed[4 * i + 3] = (GByte) nA;
+            }
+        }
+    }
+    return pabyPrecomputed;
+}
+
+/************************************************************************/
+/* ==================================================================== */
+/*                       GDALColorReliefDataset                        */
+/* ==================================================================== */
+/************************************************************************/
+
+class GDALColorReliefRasterBand;
+
+class GDALColorReliefDataset : public GDALDataset
+{
+    friend class GDALColorReliefRasterBand;
+
+    GDALDatasetH       hSrcDS;
+    GDALRasterBandH    hSrcBand;
+    int                nColorAssociation;
+    ColorAssociation*  pasColorAssociation;
+    ColorSelectionMode eColorSelectionMode;
+    GByte*             pabyPrecomputed;
+    int                nIndexOffset;
+    float*             pafSourceBuf;
+    int*               panSourceBuf;
+    int                nCurBlockXOff;
+    int                nCurBlockYOff;
+
+  public:
+                        GDALColorReliefDataset(GDALDatasetH hSrcDS,
+                                            GDALRasterBandH hSrcBand,
+                                            const char* pszColorFilename,
+                                            ColorSelectionMode eColorSelectionMode,
+                                            int bAlpha);
+                       ~GDALColorReliefDataset();
+
+    bool                InitOK() const { return pafSourceBuf != NULL || panSourceBuf != NULL; }
+
+    CPLErr      GetGeoTransform( double * padfGeoTransform );
+    const char *GetProjectionRef();
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                    GDALColorReliefRasterBand                       */
+/* ==================================================================== */
+/************************************************************************/
+
+class GDALColorReliefRasterBand : public GDALRasterBand
+{
+    friend class GDALColorReliefDataset;
+
+
+  public:
+                 GDALColorReliefRasterBand( GDALColorReliefDataset *, int );
+
+    virtual CPLErr          IReadBlock( int, int, void * );
+    virtual GDALColorInterp GetColorInterpretation();
+};
+
+GDALColorReliefDataset::GDALColorReliefDataset(
+                                     GDALDatasetH hSrcDSIn,
+                                     GDALRasterBandH hSrcBandIn,
+                                     const char* pszColorFilename,
+                                     ColorSelectionMode eColorSelectionModeIn,
+                                     int bAlpha)
+{
+    hSrcDS = hSrcDSIn;
+    hSrcBand = hSrcBandIn;
+    nColorAssociation = 0;
+    pasColorAssociation =
+            GDALColorReliefParseColorFile(hSrcBand, pszColorFilename,
+                                          &nColorAssociation);
+    eColorSelectionMode = eColorSelectionModeIn;
+
+    nRasterXSize = GDALGetRasterXSize(hSrcDS);
+    nRasterYSize = GDALGetRasterYSize(hSrcDS);
+
+    int nBlockXSize, nBlockYSize;
+    GDALGetBlockSize( hSrcBand, &nBlockXSize, &nBlockYSize);
+
+    nIndexOffset = 0;
+    pabyPrecomputed =
+        GDALColorReliefPrecompute(hSrcBand,
+                                  pasColorAssociation,
+                                  nColorAssociation,
+                                  eColorSelectionMode,
+                                  &nIndexOffset);
+
+    int i;
+    for(i=0;i<((bAlpha) ? 4 : 3);i++)
+    {
+        SetBand(i + 1, new GDALColorReliefRasterBand(this, i+1));
+    }
+
+    pafSourceBuf = NULL;
+    panSourceBuf = NULL;
+    if (pabyPrecomputed)
+        panSourceBuf = (int *) VSI_MALLOC3_VERBOSE(sizeof(int),nBlockXSize,nBlockYSize);
+    else
+        pafSourceBuf = (float *) VSI_MALLOC3_VERBOSE(sizeof(float),nBlockXSize,nBlockYSize);
+    nCurBlockXOff = -1;
+    nCurBlockYOff = -1;
+}
+
+GDALColorReliefDataset::~GDALColorReliefDataset()
+{
+    CPLFree(pasColorAssociation);
+    CPLFree(pabyPrecomputed);
+    CPLFree(panSourceBuf);
+    CPLFree(pafSourceBuf);
+}
+
+CPLErr GDALColorReliefDataset::GetGeoTransform( double * padfGeoTransform )
+{
+    return GDALGetGeoTransform(hSrcDS, padfGeoTransform);
+}
+
+const char *GDALColorReliefDataset::GetProjectionRef()
+{
+    return GDALGetProjectionRef(hSrcDS);
+}
+
+GDALColorReliefRasterBand::GDALColorReliefRasterBand(
+                                    GDALColorReliefDataset * poDSIn, int nBandIn)
+{
+    poDS = poDSIn;
+    nBand = nBandIn;
+    eDataType = GDT_Byte;
+    GDALGetBlockSize( poDSIn->hSrcBand, &nBlockXSize, &nBlockYSize);
+}
+
+CPLErr GDALColorReliefRasterBand::IReadBlock( int nBlockXOff,
+                                              int nBlockYOff,
+                                              void *pImage )
+{
+    GDALColorReliefDataset * poGDS = (GDALColorReliefDataset *) poDS;
+    int nReqXSize, nReqYSize;
+
+    if ((nBlockXOff + 1) * nBlockXSize >= nRasterXSize)
+        nReqXSize = nRasterXSize - nBlockXOff * nBlockXSize;
+    else
+        nReqXSize = nBlockXSize;
+
+    if ((nBlockYOff + 1) * nBlockYSize >= nRasterYSize)
+        nReqYSize = nRasterYSize - nBlockYOff * nBlockYSize;
+    else
+        nReqYSize = nBlockYSize;
+
+    if ( poGDS->nCurBlockXOff != nBlockXOff ||
+         poGDS->nCurBlockYOff != nBlockYOff )
+    {
+        poGDS->nCurBlockXOff = nBlockXOff;
+        poGDS->nCurBlockYOff = nBlockYOff;
+
+        CPLErr eErr = GDALRasterIO( poGDS->hSrcBand,
+                            GF_Read,
+                            nBlockXOff * nBlockXSize,
+                            nBlockYOff * nBlockYSize,
+                            nReqXSize, nReqYSize,
+                            (poGDS->panSourceBuf) ?
+                                (void*) poGDS->panSourceBuf :
+                                (void* )poGDS->pafSourceBuf,
+                            nReqXSize, nReqYSize,
+                            (poGDS->panSourceBuf) ? GDT_Int32 : GDT_Float32,
+                            0, 0);
+        if (eErr != CE_None)
+        {
+            memset(pImage, 0, nBlockXSize * nBlockYSize);
+            return eErr;
+        }
+    }
+
+    int x, y, j = 0;
+    if (poGDS->panSourceBuf)
+    {
+        for( y = 0; y < nReqYSize; y++ )
+        {
+            for( x = 0; x < nReqXSize; x++ )
+            {
+                int nIndex = poGDS->panSourceBuf[j] + poGDS->nIndexOffset;
+                ((GByte*)pImage)[y * nBlockXSize + x] = poGDS->pabyPrecomputed[4*nIndex + nBand-1];
+                j++;
+            }
+        }
+    }
+    else
+    {
+        int anComponents[4];
+        for( y = 0; y < nReqYSize; y++ )
+        {
+            for( x = 0; x < nReqXSize; x++ )
+            {
+                GDALColorReliefGetRGBA  (poGDS->pasColorAssociation,
+                                        poGDS->nColorAssociation,
+                                        poGDS->pafSourceBuf[j],
+                                        poGDS->eColorSelectionMode,
+                                        &anComponents[0],
+                                        &anComponents[1],
+                                        &anComponents[2],
+                                        &anComponents[3]);
+                ((GByte*)pImage)[y * nBlockXSize + x] = (GByte) anComponents[nBand-1];
+                j++;
+            }
+        }
+    }
+
+    return CE_None;
+}
+
+GDALColorInterp GDALColorReliefRasterBand::GetColorInterpretation()
+{
+    return (GDALColorInterp)(GCI_RedBand + nBand - 1);
+}
+
+
+static
+CPLErr GDALColorRelief (GDALRasterBandH hSrcBand,
+                        GDALRasterBandH hDstBand1,
+                        GDALRasterBandH hDstBand2,
+                        GDALRasterBandH hDstBand3,
+                        GDALRasterBandH hDstBand4,
+                        const char* pszColorFilename,
+                        ColorSelectionMode eColorSelectionMode,
+                        GDALProgressFunc pfnProgress,
+                        void * pProgressData)
+{
+    CPLErr eErr;
+
+    if (hSrcBand == NULL || hDstBand1 == NULL || hDstBand2 == NULL ||
+        hDstBand3 == NULL)
+        return CE_Failure;
+
+    int nColorAssociation = 0;
+    ColorAssociation* pasColorAssociation =
+            GDALColorReliefParseColorFile(hSrcBand, pszColorFilename,
+                                          &nColorAssociation);
+    if (pasColorAssociation == NULL)
+        return CE_Failure;
+
+    int nXSize = GDALGetRasterBandXSize(hSrcBand);
+    int nYSize = GDALGetRasterBandYSize(hSrcBand);
+
+    if (pfnProgress == NULL)
+        pfnProgress = GDALDummyProgress;
+
+    int nR = 0, nG = 0, nB = 0, nA = 0;
+
+/* -------------------------------------------------------------------- */
+/*      Precompute the map from values to RGBA quadruplets              */
+/*      for GDT_Byte, GDT_Int16 or GDT_UInt16                           */
+/* -------------------------------------------------------------------- */
+    int nIndexOffset = 0;
+    GByte* pabyPrecomputed =
+        GDALColorReliefPrecompute(hSrcBand,
+                                  pasColorAssociation,
+                                  nColorAssociation,
+                                  eColorSelectionMode,
+                                  &nIndexOffset);
+
+/* -------------------------------------------------------------------- */
+/*      Initialize progress counter.                                    */
+/* -------------------------------------------------------------------- */
+
+    float* pafSourceBuf = NULL;
+    int* panSourceBuf = NULL;
+    if (pabyPrecomputed)
+        panSourceBuf = (int *) VSI_MALLOC2_VERBOSE(sizeof(int),nXSize);
+    else
+        pafSourceBuf = (float *) VSI_MALLOC2_VERBOSE(sizeof(float),nXSize);
+    GByte* pabyDestBuf1  = (GByte*) VSI_MALLOC2_VERBOSE(4, nXSize );
+    GByte* pabyDestBuf2  =  pabyDestBuf1 + nXSize;
+    GByte* pabyDestBuf3  =  pabyDestBuf2 + nXSize;
+    GByte* pabyDestBuf4  =  pabyDestBuf3 + nXSize;
+    int i, j;
+
+    if( (pabyPrecomputed != NULL && panSourceBuf == NULL) ||
+        (pabyPrecomputed == NULL && pafSourceBuf == NULL) ||
+        pabyDestBuf1 == NULL )
+    {
+        eErr = CE_Failure;
+        goto end;
+    }
+
+    if( !pfnProgress( 0.0, NULL, pProgressData ) )
+    {
+        CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
+        eErr = CE_Failure;
+        goto end;
+    }
+
+    for ( i = 0; i < nYSize; i++)
+    {
+        /* Read source buffer */
+        eErr = GDALRasterIO(   hSrcBand,
+                        GF_Read,
+                        0, i,
+                        nXSize, 1,
+                        (panSourceBuf) ? (void*) panSourceBuf : (void* )pafSourceBuf,
+                        nXSize, 1,
+                        (panSourceBuf) ? GDT_Int32 : GDT_Float32,
+                        0, 0);
+        if (eErr != CE_None)
+            goto end;
+
+        if (pabyPrecomputed)
+        {
+            for ( j = 0; j < nXSize; j++)
+            {
+                int nIndex = panSourceBuf[j] + nIndexOffset;
+                pabyDestBuf1[j] = pabyPrecomputed[4 * nIndex];
+                pabyDestBuf2[j] = pabyPrecomputed[4 * nIndex + 1];
+                pabyDestBuf3[j] = pabyPrecomputed[4 * nIndex + 2];
+                pabyDestBuf4[j] = pabyPrecomputed[4 * nIndex + 3];
+            }
+        }
+        else
+        {
+            for ( j = 0; j < nXSize; j++)
+            {
+                GDALColorReliefGetRGBA  (pasColorAssociation,
+                                         nColorAssociation,
+                                         pafSourceBuf[j],
+                                         eColorSelectionMode,
+                                         &nR,
+                                         &nG,
+                                         &nB,
+                                         &nA);
+                pabyDestBuf1[j] = (GByte) nR;
+                pabyDestBuf2[j] = (GByte) nG;
+                pabyDestBuf3[j] = (GByte) nB;
+                pabyDestBuf4[j] = (GByte) nA;
+            }
+        }
+
+        /* -----------------------------------------
+         * Write Line to Raster
+         */
+        eErr = GDALRasterIO(hDstBand1,
+                      GF_Write,
+                      0, i, nXSize,
+                      1, pabyDestBuf1, nXSize, 1, GDT_Byte, 0, 0);
+        if (eErr != CE_None)
+            goto end;
+
+        eErr = GDALRasterIO(hDstBand2,
+                      GF_Write,
+                      0, i, nXSize,
+                      1, pabyDestBuf2, nXSize, 1, GDT_Byte, 0, 0);
+        if (eErr != CE_None)
+            goto end;
+
+        eErr = GDALRasterIO(hDstBand3,
+                      GF_Write,
+                      0, i, nXSize,
+                      1, pabyDestBuf3, nXSize, 1, GDT_Byte, 0, 0);
+        if (eErr != CE_None)
+            goto end;
+
+        if (hDstBand4)
+        {
+            eErr = GDALRasterIO(hDstBand4,
+                        GF_Write,
+                        0, i, nXSize,
+                        1, pabyDestBuf4, nXSize, 1, GDT_Byte, 0, 0);
+            if (eErr != CE_None)
+                goto end;
+        }
+
+        if( !pfnProgress( 1.0 * (i+1) / nYSize, NULL, pProgressData ) )
+        {
+            CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
+            eErr = CE_Failure;
+            goto end;
+        }
+    }
+    pfnProgress( 1.0, NULL, pProgressData );
+    eErr = CE_None;
+
+end:
+    VSIFree(pabyPrecomputed);
+    CPLFree(pafSourceBuf);
+    CPLFree(panSourceBuf);
+    CPLFree(pabyDestBuf1);
+    CPLFree(pasColorAssociation);
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                     GDALGenerateVRTColorRelief()                     */
+/************************************************************************/
+
+static
+CPLErr GDALGenerateVRTColorRelief(const char* pszDstFilename,
+                               GDALDatasetH hSrcDataset,
+                               GDALRasterBandH hSrcBand,
+                               const char* pszColorFilename,
+                               ColorSelectionMode eColorSelectionMode,
+                               int bAddAlpha)
+{
+
+    int nColorAssociation = 0;
+    ColorAssociation* pasColorAssociation =
+            GDALColorReliefParseColorFile(hSrcBand, pszColorFilename,
+                                          &nColorAssociation);
+    if (pasColorAssociation == NULL)
+        return CE_Failure;
+
+    int nXSize = GDALGetRasterBandXSize(hSrcBand);
+    int nYSize = GDALGetRasterBandYSize(hSrcBand);
+
+    VSILFILE* fp = VSIFOpenL(pszDstFilename, "wt");
+    if (fp == NULL)
+    {
+        CPLFree(pasColorAssociation);
+        return CE_Failure;
+    }
+
+    bool bOK = VSIFPrintfL(fp, "<VRTDataset rasterXSize=\"%d\" rasterYSize=\"%d\">\n", nXSize, nYSize) > 0;
+    const char* pszProjectionRef = GDALGetProjectionRef(hSrcDataset);
+    if (pszProjectionRef && pszProjectionRef[0] != '\0')
+    {
+        char* pszEscapedString = CPLEscapeString(pszProjectionRef, -1, CPLES_XML);
+        bOK &= VSIFPrintfL(fp, "  <SRS>%s</SRS>\n", pszEscapedString) > 0;
+        VSIFree(pszEscapedString);
+    }
+    double adfGT[6];
+    if (GDALGetGeoTransform(hSrcDataset, adfGT) == CE_None)
+    {
+        bOK &= VSIFPrintfL(fp, "  <GeoTransform> %.16g, %.16g, %.16g, "
+                        "%.16g, %.16g, %.16g</GeoTransform>\n",
+                        adfGT[0], adfGT[1], adfGT[2], adfGT[3], adfGT[4], adfGT[5]) > 0;
+    }
+    int nBands = 3 + (bAddAlpha ? 1 : 0);
+    int iBand;
+
+    int nBlockXSize, nBlockYSize;
+    GDALGetBlockSize(hSrcBand, &nBlockXSize, &nBlockYSize);
+
+    int bRelativeToVRT;
+    CPLString osPath = CPLGetPath(pszDstFilename);
+    char* pszSourceFilename = CPLStrdup(
+        CPLExtractRelativePath( osPath.c_str(), GDALGetDescription(hSrcDataset),
+                                &bRelativeToVRT ));
+
+    for(iBand = 0; iBand < nBands; iBand++)
+    {
+        bOK &= VSIFPrintfL(fp, "  <VRTRasterBand dataType=\"Byte\" band=\"%d\">\n", iBand + 1) > 0;
+        bOK &= VSIFPrintfL(fp, "    <ColorInterp>%s</ColorInterp>\n",
+                    GDALGetColorInterpretationName((GDALColorInterp)(GCI_RedBand + iBand))) > 0;
+        bOK &= VSIFPrintfL(fp, "    <ComplexSource>\n") > 0;
+        bOK &= VSIFPrintfL(fp, "      <SourceFilename relativeToVRT=\"%d\">%s</SourceFilename>\n",
+                        bRelativeToVRT, pszSourceFilename) > 0;
+        bOK &= VSIFPrintfL(fp, "      <SourceBand>%d</SourceBand>\n", GDALGetBandNumber(hSrcBand)) > 0;
+        bOK &= VSIFPrintfL(fp, "      <SourceProperties RasterXSize=\"%d\" "
+                        "RasterYSize=\"%d\" DataType=\"%s\" "
+                        "BlockXSize=\"%d\" BlockYSize=\"%d\"/>\n",
+                        nXSize, nYSize,
+                        GDALGetDataTypeName(GDALGetRasterDataType(hSrcBand)),
+                        nBlockXSize, nBlockYSize) > 0;
+        bOK &= VSIFPrintfL(fp, "      <SrcRect xOff=\"0\" yOff=\"0\" xSize=\"%d\" ySize=\"%d\"/>\n",
+                        nXSize, nYSize) > 0;
+        bOK &= VSIFPrintfL(fp, "      <DstRect xOff=\"0\" yOff=\"0\" xSize=\"%d\" ySize=\"%d\"/>\n",
+                        nXSize, nYSize) > 0;
+
+        bOK &= VSIFPrintfL(fp, "      <LUT>") > 0;
+        int iColor;
+#define EPSILON 1e-8
+        for(iColor=0;iColor<nColorAssociation;iColor++)
+        {
+            if (eColorSelectionMode == COLOR_SELECTION_NEAREST_ENTRY)
+            {
+                if (iColor > 1)
+                    bOK &= VSIFPrintfL(fp, ",") > 0;
+            }
+            else if (iColor > 0)
+                bOK &= VSIFPrintfL(fp, ",") > 0;
+
+            double dfVal = pasColorAssociation[iColor].dfVal;
+
+            if (eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY)
+            {
+                bOK &= VSIFPrintfL(fp, "%.18g:0,", dfVal - fabs(dfVal) * DBL_EPSILON) > 0;
+            }
+            else if (iColor > 0 &&
+                     eColorSelectionMode == COLOR_SELECTION_NEAREST_ENTRY)
+            {
+                double dfMidVal = (dfVal + pasColorAssociation[iColor-1].dfVal) / 2;
+                bOK &= VSIFPrintfL(fp, "%.18g:%d", dfMidVal - fabs(dfMidVal) * DBL_EPSILON,
+                        (iBand == 0) ? pasColorAssociation[iColor-1].nR :
+                        (iBand == 1) ? pasColorAssociation[iColor-1].nG :
+                        (iBand == 2) ? pasColorAssociation[iColor-1].nB :
+                                       pasColorAssociation[iColor-1].nA) > 0;
+                bOK &= VSIFPrintfL(fp, ",%.18g:%d", dfMidVal ,
+                        (iBand == 0) ? pasColorAssociation[iColor].nR :
+                        (iBand == 1) ? pasColorAssociation[iColor].nG :
+                        (iBand == 2) ? pasColorAssociation[iColor].nB :
+                                       pasColorAssociation[iColor].nA) > 0;
+
+            }
+
+            if (eColorSelectionMode != COLOR_SELECTION_NEAREST_ENTRY)
+            {
+                if (dfVal != (double)(int)dfVal)
+                    bOK &= VSIFPrintfL(fp, "%.18g", dfVal) > 0;
+                else
+                    bOK &= VSIFPrintfL(fp, "%d", (int)dfVal) > 0;
+                bOK &= VSIFPrintfL(fp, ":%d",
+                            (iBand == 0) ? pasColorAssociation[iColor].nR :
+                            (iBand == 1) ? pasColorAssociation[iColor].nG :
+                            (iBand == 2) ? pasColorAssociation[iColor].nB :
+                                           pasColorAssociation[iColor].nA) > 0;
+            }
+
+            if (eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY)
+            {
+                bOK &= VSIFPrintfL(fp, ",%.18g:0", dfVal + fabs(dfVal) * DBL_EPSILON) > 0;
+            }
+
+        }
+        bOK &= VSIFPrintfL(fp, "</LUT>\n") > 0;
+
+        bOK &= VSIFPrintfL(fp, "    </ComplexSource>\n") > 0;
+        bOK &= VSIFPrintfL(fp, "  </VRTRasterBand>\n") > 0;
+    }
+
+    CPLFree(pszSourceFilename);
+
+    bOK &= VSIFPrintfL(fp, "</VRTDataset>\n") > 0;
+
+    VSIFCloseL(fp);
+
+    CPLFree(pasColorAssociation);
+
+    return (bOK) ? CE_None : CE_Failure;
+}
+
+
+/************************************************************************/
+/*                         GDALTRIAlg()                                 */
+/************************************************************************/
+
+static
+float GDALTRIAlg (float* afWin,
+                  CPL_UNUSED float fDstNoDataValue,
+                  CPL_UNUSED void* pData)
+{
+    // Terrain Ruggedness is average difference in height
+    return (fabs(afWin[0]-afWin[4]) +
+            fabs(afWin[1]-afWin[4]) +
+            fabs(afWin[2]-afWin[4]) +
+            fabs(afWin[3]-afWin[4]) +
+            fabs(afWin[5]-afWin[4]) +
+            fabs(afWin[6]-afWin[4]) +
+            fabs(afWin[7]-afWin[4]) +
+            fabs(afWin[8]-afWin[4]))/8;
+}
+
+
+/************************************************************************/
+/*                         GDALTPIAlg()                                 */
+/************************************************************************/
+
+static
+float GDALTPIAlg (float* afWin,
+                  CPL_UNUSED float fDstNoDataValue,
+                  CPL_UNUSED void* pData)
+{
+    // Terrain Position is the difference between
+    // The central cell and the mean of the surrounding cells
+    return afWin[4] -
+            ((afWin[0]+
+              afWin[1]+
+              afWin[2]+
+              afWin[3]+
+              afWin[5]+
+              afWin[6]+
+              afWin[7]+
+              afWin[8])/8);
+}
+
+/************************************************************************/
+/*                     GDALRoughnessAlg()                               */
+/************************************************************************/
+
+static
+float GDALRoughnessAlg (float* afWin, CPL_UNUSED float fDstNoDataValue, CPL_UNUSED void* pData)
+{
+    // Roughness is the largest difference
+    //  between any two cells
+
+    float pafRoughnessMin = afWin[0];
+    float pafRoughnessMax = afWin[0];
+
+    for ( int k = 1; k < 9; k++)
+    {
+        if (afWin[k] > pafRoughnessMax)
+        {
+            pafRoughnessMax=afWin[k];
+        }
+        if (afWin[k] < pafRoughnessMin)
+        {
+            pafRoughnessMin=afWin[k];
+        }
+    }
+    return pafRoughnessMax - pafRoughnessMin;
+}
+
+/************************************************************************/
+/* ==================================================================== */
+/*                       GDALGeneric3x3Dataset                        */
+/* ==================================================================== */
+/************************************************************************/
+
+class GDALGeneric3x3RasterBand;
+
+class GDALGeneric3x3Dataset : public GDALDataset
+{
+    friend class GDALGeneric3x3RasterBand;
+
+    GDALGeneric3x3ProcessingAlg pfnAlg;
+    void*              pAlgData;
+    GDALDatasetH       hSrcDS;
+    GDALRasterBandH    hSrcBand;
+    float*             apafSourceBuf[3];
+    int                bDstHasNoData;
+    double             dfDstNoDataValue;
+    int                nCurLine;
+    int                bComputeAtEdges;
+
+  public:
+                        GDALGeneric3x3Dataset(GDALDatasetH hSrcDS,
+                                              GDALRasterBandH hSrcBand,
+                                              GDALDataType eDstDataType,
+                                              int bDstHasNoData,
+                                              double dfDstNoDataValue,
+                                              GDALGeneric3x3ProcessingAlg pfnAlg,
+                                              void* pAlgData,
+                                              int bComputeAtEdges);
+                       ~GDALGeneric3x3Dataset();
+
+    bool                InitOK() const { return apafSourceBuf[0] != NULL &&
+                                                apafSourceBuf[1] != NULL &&
+                                                apafSourceBuf[2] != NULL; }
+
+    CPLErr      GetGeoTransform( double * padfGeoTransform );
+    const char *GetProjectionRef();
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                    GDALGeneric3x3RasterBand                       */
+/* ==================================================================== */
+/************************************************************************/
+
+class GDALGeneric3x3RasterBand : public GDALRasterBand
+{
+    friend class GDALGeneric3x3Dataset;
+    int bSrcHasNoData;
+    float fSrcNoDataValue;
+    int bIsSrcNoDataNan;
+
+    void                    InitWidthNoData(void* pImage);
+
+  public:
+                 GDALGeneric3x3RasterBand( GDALGeneric3x3Dataset *poDS,
+                                           GDALDataType eDstDataType );
+
+    virtual CPLErr          IReadBlock( int, int, void * );
+    virtual double          GetNoDataValue( int* pbHasNoData );
+};
+
+GDALGeneric3x3Dataset::GDALGeneric3x3Dataset(
+                                     GDALDatasetH hSrcDSIn,
+                                     GDALRasterBandH hSrcBandIn,
+                                     GDALDataType eDstDataType,
+                                     int bDstHasNoDataIn,
+                                     double dfDstNoDataValueIn,
+                                     GDALGeneric3x3ProcessingAlg pfnAlgIn,
+                                     void* pAlgDataIn,
+                                     int bComputeAtEdgesIn)
+{
+    hSrcDS = hSrcDSIn;
+    hSrcBand = hSrcBandIn;
+    pfnAlg = pfnAlgIn;
+    pAlgData = pAlgDataIn;
+    bDstHasNoData = bDstHasNoDataIn;
+    dfDstNoDataValue = dfDstNoDataValueIn;
+    bComputeAtEdges = bComputeAtEdgesIn;
+
+    CPLAssert(eDstDataType == GDT_Byte || eDstDataType == GDT_Float32);
+
+    nRasterXSize = GDALGetRasterXSize(hSrcDS);
+    nRasterYSize = GDALGetRasterYSize(hSrcDS);
+
+    SetBand(1, new GDALGeneric3x3RasterBand(this, eDstDataType));
+
+    apafSourceBuf[0] = (float *) VSI_MALLOC2_VERBOSE(sizeof(float),nRasterXSize);
+    apafSourceBuf[1] = (float *) VSI_MALLOC2_VERBOSE(sizeof(float),nRasterXSize);
+    apafSourceBuf[2] = (float *) VSI_MALLOC2_VERBOSE(sizeof(float),nRasterXSize);
+
+    nCurLine = -1;
+}
+
+GDALGeneric3x3Dataset::~GDALGeneric3x3Dataset()
+{
+    CPLFree(apafSourceBuf[0]);
+    CPLFree(apafSourceBuf[1]);
+    CPLFree(apafSourceBuf[2]);
+}
+
+CPLErr GDALGeneric3x3Dataset::GetGeoTransform( double * padfGeoTransform )
+{
+    return GDALGetGeoTransform(hSrcDS, padfGeoTransform);
+}
+
+const char *GDALGeneric3x3Dataset::GetProjectionRef()
+{
+    return GDALGetProjectionRef(hSrcDS);
+}
+
+GDALGeneric3x3RasterBand::GDALGeneric3x3RasterBand(GDALGeneric3x3Dataset *poDSIn,
+                                                   GDALDataType eDstDataType)
+{
+    poDS = poDSIn;
+    this->nBand = 1;
+    eDataType = eDstDataType;
+    nBlockXSize = poDS->GetRasterXSize();
+    nBlockYSize = 1;
+
+    bSrcHasNoData = FALSE;
+    fSrcNoDataValue = (float)GDALGetRasterNoDataValue(poDSIn->hSrcBand,
+                                                      &bSrcHasNoData);
+    bIsSrcNoDataNan = bSrcHasNoData && CPLIsNan(fSrcNoDataValue);
+}
+
+void   GDALGeneric3x3RasterBand::InitWidthNoData(void* pImage)
+{
+    int j;
+    GDALGeneric3x3Dataset * poGDS = (GDALGeneric3x3Dataset *) poDS;
+    if (eDataType == GDT_Byte)
+    {
+        for(j=0;j<nBlockXSize;j++)
+            ((GByte*)pImage)[j] = (GByte) poGDS->dfDstNoDataValue;
+    }
+    else
+    {
+        for(j=0;j<nBlockXSize;j++)
+            ((float*)pImage)[j] = (float) poGDS->dfDstNoDataValue;
+    }
+}
+
+CPLErr GDALGeneric3x3RasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
+                                             int nBlockYOff,
+                                             void *pImage )
+{
+    int i, j;
+    float fVal;
+    GDALGeneric3x3Dataset * poGDS = (GDALGeneric3x3Dataset *) poDS;
+
+    if (poGDS->bComputeAtEdges && nRasterXSize >= 2 && nRasterYSize >= 2)
+    {
+        if (nBlockYOff == 0)
+        {
+            for(i=0;i<2;i++)
+            {
+                CPLErr eErr = GDALRasterIO( poGDS->hSrcBand,
+                                    GF_Read,
+                                    0, i, nBlockXSize, 1,
+                                    poGDS->apafSourceBuf[i+1],
+                                    nBlockXSize, 1,
+                                    GDT_Float32,
+                                    0, 0);
+                if (eErr != CE_None)
+                {
+                    InitWidthNoData(pImage);
+                    return eErr;
+                }
+            }
+            poGDS->nCurLine = 0;
+
+            for (j = 0; j < nRasterXSize; j++)
+            {
+                float afWin[9];
+                int jmin = (j == 0) ? j : j - 1;
+                int jmax = (j == nRasterXSize - 1) ? j : j + 1;
+
+                afWin[0] = INTERPOL(poGDS->apafSourceBuf[1][jmin], poGDS->apafSourceBuf[2][jmin]);
+                afWin[1] = INTERPOL(poGDS->apafSourceBuf[1][j],    poGDS->apafSourceBuf[2][j]);
+                afWin[2] = INTERPOL(poGDS->apafSourceBuf[1][jmax], poGDS->apafSourceBuf[2][jmax]);
+                afWin[3] = poGDS->apafSourceBuf[1][jmin];
+                afWin[4] = poGDS->apafSourceBuf[1][j];
+                afWin[5] = poGDS->apafSourceBuf[1][jmax];
+                afWin[6] = poGDS->apafSourceBuf[2][jmin];
+                afWin[7] = poGDS->apafSourceBuf[2][j];
+                afWin[8] = poGDS->apafSourceBuf[2][jmax];
+
+                fVal = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
+                                  bIsSrcNoDataNan,
+                                    afWin, (float) poGDS->dfDstNoDataValue,
+                                    poGDS->pfnAlg,
+                                    poGDS->pAlgData,
+                                    poGDS->bComputeAtEdges);
+
+                if (eDataType == GDT_Byte)
+                    ((GByte*)pImage)[j] = (GByte) (fVal + 0.5);
+                else
+                    ((float*)pImage)[j] = fVal;
+            }
+
+            return CE_None;
+        }
+        else if (nBlockYOff == nRasterYSize - 1)
+        {
+            if (poGDS->nCurLine != nRasterYSize - 2)
+            {
+                for(i=0;i<2;i++)
+                {
+                    CPLErr eErr = GDALRasterIO( poGDS->hSrcBand,
+                                        GF_Read,
+                                        0, nRasterYSize - 2 + i, nBlockXSize, 1,
+                                        poGDS->apafSourceBuf[i+1],
+                                        nBlockXSize, 1,
+                                        GDT_Float32,
+                                        0, 0);
+                    if (eErr != CE_None)
+                    {
+                        InitWidthNoData(pImage);
+                        return eErr;
+                    }
+                }
+            }
+
+            for (j = 0; j < nRasterXSize; j++)
+            {
+                float afWin[9];
+                int jmin = (j == 0) ? j : j - 1;
+                int jmax = (j == nRasterXSize - 1) ? j : j + 1;
+
+                afWin[0] = poGDS->apafSourceBuf[1][jmin];
+                afWin[1] = poGDS->apafSourceBuf[1][j];
+                afWin[2] = poGDS->apafSourceBuf[1][jmax];
+                afWin[3] = poGDS->apafSourceBuf[2][jmin];
+                afWin[4] = poGDS->apafSourceBuf[2][j];
+                afWin[5] = poGDS->apafSourceBuf[2][jmax];
+                afWin[6] = INTERPOL(poGDS->apafSourceBuf[2][jmin], poGDS->apafSourceBuf[1][jmin]);
+                afWin[7] = INTERPOL(poGDS->apafSourceBuf[2][j],    poGDS->apafSourceBuf[1][j]);
+                afWin[8] = INTERPOL(poGDS->apafSourceBuf[2][jmax], poGDS->apafSourceBuf[1][jmax]);
+
+                fVal = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
+                                  bIsSrcNoDataNan,
+                                    afWin, (float) poGDS->dfDstNoDataValue,
+                                    poGDS->pfnAlg,
+                                    poGDS->pAlgData,
+                                    poGDS->bComputeAtEdges);
+
+                if (eDataType == GDT_Byte)
+                    ((GByte*)pImage)[j] = (GByte) (fVal + 0.5);
+                else
+                    ((float*)pImage)[j] = fVal;
+            }
+
+            return CE_None;
+        }
+    }
+    else if ( nBlockYOff == 0 || nBlockYOff == nRasterYSize - 1)
+    {
+        InitWidthNoData(pImage);
+        return CE_None;
+    }
+
+    if ( poGDS->nCurLine != nBlockYOff )
+    {
+        if (poGDS->nCurLine + 1 == nBlockYOff)
+        {
+            float* pafTmp =  poGDS->apafSourceBuf[0];
+            poGDS->apafSourceBuf[0] = poGDS->apafSourceBuf[1];
+            poGDS->apafSourceBuf[1] = poGDS->apafSourceBuf[2];
+            poGDS->apafSourceBuf[2] = pafTmp;
+
+            CPLErr eErr = GDALRasterIO( poGDS->hSrcBand,
+                                    GF_Read,
+                                    0, nBlockYOff + 1, nBlockXSize, 1,
+                                    poGDS->apafSourceBuf[2],
+                                    nBlockXSize, 1,
+                                    GDT_Float32,
+                                    0, 0);
+
+            if (eErr != CE_None)
+            {
+                InitWidthNoData(pImage);
+                return eErr;
+            }
+        }
+        else
+        {
+            for(i=0;i<3;i++)
+            {
+                CPLErr eErr = GDALRasterIO( poGDS->hSrcBand,
+                                    GF_Read,
+                                    0, nBlockYOff + i - 1, nBlockXSize, 1,
+                                    poGDS->apafSourceBuf[i],
+                                    nBlockXSize, 1,
+                                    GDT_Float32,
+                                    0, 0);
+                if (eErr != CE_None)
+                {
+                    InitWidthNoData(pImage);
+                    return eErr;
+                }
+            }
+        }
+
+        poGDS->nCurLine = nBlockYOff;
+    }
+
+    if (poGDS->bComputeAtEdges && nRasterXSize >= 2)
+    {
+        float afWin[9];
+
+        j = 0;
+        afWin[0] = INTERPOL(poGDS->apafSourceBuf[0][j], poGDS->apafSourceBuf[0][j+1]);
+        afWin[1] = poGDS->apafSourceBuf[0][j];
+        afWin[2] = poGDS->apafSourceBuf[0][j+1];
+        afWin[3] = INTERPOL(poGDS->apafSourceBuf[1][j], poGDS->apafSourceBuf[1][j+1]);
+        afWin[4] = poGDS->apafSourceBuf[1][j];
+        afWin[5] = poGDS->apafSourceBuf[1][j+1];
+        afWin[6] = INTERPOL(poGDS->apafSourceBuf[2][j], poGDS->apafSourceBuf[2][j+1]);
+        afWin[7] = poGDS->apafSourceBuf[2][j];
+        afWin[8] = poGDS->apafSourceBuf[2][j+1];
+
+        fVal = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
+                          bIsSrcNoDataNan,
+                                    afWin, (float) poGDS->dfDstNoDataValue,
+                                    poGDS->pfnAlg,
+                                    poGDS->pAlgData,
+                                    poGDS->bComputeAtEdges);
+
+        if (eDataType == GDT_Byte)
+            ((GByte*)pImage)[j] = (GByte) (fVal + 0.5);
+        else
+            ((float*)pImage)[j] = fVal;
+
+        j = nRasterXSize - 1;
+
+        afWin[0] = poGDS->apafSourceBuf[0][j-1];
+        afWin[1] = poGDS->apafSourceBuf[0][j];
+        afWin[2] = INTERPOL(poGDS->apafSourceBuf[0][j], poGDS->apafSourceBuf[0][j-1]);
+        afWin[3] = poGDS->apafSourceBuf[1][j-1];
+        afWin[4] = poGDS->apafSourceBuf[1][j];
+        afWin[5] = INTERPOL(poGDS->apafSourceBuf[1][j], poGDS->apafSourceBuf[1][j-1]);
+        afWin[6] = poGDS->apafSourceBuf[2][j-1];
+        afWin[7] = poGDS->apafSourceBuf[2][j];
+        afWin[8] = INTERPOL(poGDS->apafSourceBuf[2][j], poGDS->apafSourceBuf[2][j-1]);
+
+        fVal = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
+                          bIsSrcNoDataNan,
+                                    afWin, (float) poGDS->dfDstNoDataValue,
+                                    poGDS->pfnAlg,
+                                    poGDS->pAlgData,
+                                    poGDS->bComputeAtEdges);
+
+        if (eDataType == GDT_Byte)
+            ((GByte*)pImage)[j] = (GByte) (fVal + 0.5);
+        else
+            ((float*)pImage)[j] = fVal;
+    }
+    else
+    {
+        if (eDataType == GDT_Byte)
+        {
+            ((GByte*)pImage)[0] = (GByte) poGDS->dfDstNoDataValue;
+            if (nBlockXSize > 1)
+                ((GByte*)pImage)[nBlockXSize - 1] = (GByte) poGDS->dfDstNoDataValue;
+        }
+        else
+        {
+            ((float*)pImage)[0] = (float) poGDS->dfDstNoDataValue;
+            if (nBlockXSize > 1)
+                ((float*)pImage)[nBlockXSize - 1] = (float) poGDS->dfDstNoDataValue;
+        }
+    }
+
+
+    for(j=1;j<nBlockXSize - 1;j++)
+    {
+        float afWin[9];
+        afWin[0] = poGDS->apafSourceBuf[0][j-1];
+        afWin[1] = poGDS->apafSourceBuf[0][j];
+        afWin[2] = poGDS->apafSourceBuf[0][j+1];
+        afWin[3] = poGDS->apafSourceBuf[1][j-1];
+        afWin[4] = poGDS->apafSourceBuf[1][j];
+        afWin[5] = poGDS->apafSourceBuf[1][j+1];
+        afWin[6] = poGDS->apafSourceBuf[2][j-1];
+        afWin[7] = poGDS->apafSourceBuf[2][j];
+        afWin[8] = poGDS->apafSourceBuf[2][j+1];
+
+        fVal = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
+                          bIsSrcNoDataNan,
+                                afWin, (float) poGDS->dfDstNoDataValue,
+                                poGDS->pfnAlg,
+                                poGDS->pAlgData,
+                                poGDS->bComputeAtEdges);
+
+        if (eDataType == GDT_Byte)
+            ((GByte*)pImage)[j] = (GByte) (fVal + 0.5);
+        else
+            ((float*)pImage)[j] = fVal;
+
+    }
+
+    return CE_None;
+}
+
+double GDALGeneric3x3RasterBand::GetNoDataValue( int* pbHasNoData )
+{
+    GDALGeneric3x3Dataset * poGDS = (GDALGeneric3x3Dataset *) poDS;
+    if (pbHasNoData)
+        *pbHasNoData = poGDS->bDstHasNoData;
+    return poGDS->dfDstNoDataValue;
+}
+
+/************************************************************************/
+/*                            ArgIsNumeric()                            */
+/************************************************************************/
+
+static int ArgIsNumeric( const char *pszArg )
+
+{
+    return CPLGetValueType(pszArg) != CPL_VALUE_STRING;
+}
+
+/************************************************************************/
+/*                            GetAlgorithm()                            */
+/************************************************************************/
+
+typedef enum
+{
+    INVALID,
+    HILL_SHADE,
+    SLOPE,
+    ASPECT,
+    COLOR_RELIEF,
+    TRI,
+    TPI,
+    ROUGHNESS
+} Algorithm;
+
+static Algorithm GetAlgorithm(const char* pszProcessing)
+{
+    if ( EQUAL(pszProcessing, "shade") || EQUAL(pszProcessing, "hillshade") )
+    {
+        return HILL_SHADE;
+    }
+    else if ( EQUAL(pszProcessing, "slope") )
+    {
+        return SLOPE;
+    }
+    else if ( EQUAL(pszProcessing, "aspect") )
+    {
+        return ASPECT;
+    }
+    else if ( EQUAL(pszProcessing, "color-relief") )
+    {
+        return COLOR_RELIEF;
+    }
+    else if ( EQUAL(pszProcessing, "TRI") )
+    {
+        return TRI;
+    }
+    else if ( EQUAL(pszProcessing, "TPI") )
+    {
+        return TPI;
+    }
+    else if ( EQUAL(pszProcessing, "roughness") )
+    {
+        return ROUGHNESS;
+    }
+    else
+    {
+        return INVALID;
+    }
+}
+
+/************************************************************************/
+/*                            GDALDEMProcessing()                       */
+/************************************************************************/
+
+/**
+ * Apply a DEM processing.
+ *
+ * This is the equivalent of the <a href="gdaldem.html">gdaldem</a> utility.
+ *
+ * GDALDEMProcessingOptions* must be allocated and freed with
+ * GDALDEMProcessingOptionsNew() and GDALDEMProcessingOptionsFree()
+ * respectively.
+ *
+ * @param pszDest the destination dataset path.
+ * @param hSrcDataset the source dataset handle.
+ * @param pszProcessing the processing to apply (one of "hillshade", "slope",
+ * "aspect", "color-relief", "TRI", "TPI", "Roughness")
+ * @param pszColorFilename color file (mandatory for "color-relief" processing,
+ * should be NULL otherwise)
+ * @param psOptionsIn the options struct returned by
+ * GDALDEMProcessingOptionsNew() or NULL.
+ * @param pbUsageError the pointer to int variable to determine any usage
+ * error has occurred or NULL.
+ * @return the output dataset (new dataset that must be closed using
+ * GDALClose()) or NULL in case of error.
+ *
+ * @since GDAL 2.1
+ */
+
+GDALDatasetH GDALDEMProcessing(const char *pszDest,
+                               GDALDatasetH hSrcDataset,
+                               const char* pszProcessing,
+                               const char* pszColorFilename,
+                               const GDALDEMProcessingOptions *psOptionsIn,
+                               int *pbUsageError)
+{
+    if( hSrcDataset == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "No source dataset specified.");
+
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        return NULL;
+    }
+    if( pszDest == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "No target dataset specified.");
+
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        return NULL;
+    }
+    if( pszProcessing == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "No target dataset specified.");
+
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        return NULL;
+    }
+
+    Algorithm eUtilityMode = GetAlgorithm(pszProcessing);
+    if( eUtilityMode == INVALID )
+    {
+        CPLError(CE_Failure, CPLE_IllegalArg, "Invalid processing");
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        return NULL;
+    }
+
+    if( eUtilityMode == COLOR_RELIEF && pszColorFilename == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "pszColorFilename == NULL.");
+
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        return NULL;
+    }
+    else if( eUtilityMode != COLOR_RELIEF && pszColorFilename != NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "pszColorFilename != NULL.");
+
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        return NULL;
+    }
+
+
+    GDALDEMProcessingOptions* psOptionsToFree = NULL;
+    const GDALDEMProcessingOptions* psOptions;
+    if( psOptionsIn )
+        psOptions = psOptionsIn;
+    else
+    {
+        psOptionsToFree = GDALDEMProcessingOptionsNew(NULL, NULL);
+        psOptions = psOptionsToFree;
+    }
+
+    double  adfGeoTransform[6];
+
+    GDALDatasetH hDstDataset = NULL;
+    GDALRasterBandH hSrcBand = NULL;
+    GDALRasterBandH hDstBand = NULL;
+    GDALDriverH hDriver = NULL;
+
+    int nXSize = GDALGetRasterXSize(hSrcDataset);
+    int nYSize = GDALGetRasterYSize(hSrcDataset);
+
+    if( psOptions->nBand <= 0 || psOptions->nBand > GDALGetRasterCount(hSrcDataset) )
+    {
+        CPLError(CE_Failure, CPLE_IllegalArg,
+                 "Unable to fetch band #%d", psOptions->nBand );
+        GDALDEMProcessingOptionsFree(psOptionsToFree);
+        return NULL;
+    }
+    hSrcBand = GDALGetRasterBand( hSrcDataset, psOptions->nBand );
+
+    GDALGetGeoTransform(hSrcDataset, adfGeoTransform);
+
+    hDriver = GDALGetDriverByName(psOptions->pszFormat);
+    if( hDriver == NULL
+        || (GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) == NULL &&
+            GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY, NULL ) == NULL))
+    {
+        int	iDr;
+
+        CPLError(CE_Failure, CPLE_AppDefined, "Output driver `%s' not recognised to have output support.",
+                 psOptions->pszFormat );
+        fprintf( stderr, "The following format drivers are configured\n"
+                "and support output:\n" );
+
+        for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
+        {
+            hDriver = GDALGetDriver(iDr);
+
+            if( GDALGetMetadataItem( hDriver, GDAL_DCAP_RASTER, NULL) != NULL &&
+                (GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) != NULL ||
+                 GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY, NULL ) != NULL) )
+            {
+                fprintf( stderr, "  %s: %s\n",
+                        GDALGetDriverShortName( hDriver  ),
+                        GDALGetDriverLongName( hDriver ) );
+            }
+        }
+        GDALDEMProcessingOptionsFree(psOptionsToFree);
+        return NULL;
+    }
+
+    double dfDstNoDataValue = 0;
+    int bDstHasNoData = FALSE;
+    void* pData = NULL;
+    GDALGeneric3x3ProcessingAlg pfnAlg = NULL;
+
+    if (eUtilityMode == HILL_SHADE)
+    {
+        dfDstNoDataValue = 0;
+        bDstHasNoData = TRUE;
+        pData = GDALCreateHillshadeData   (adfGeoTransform,
+                                           psOptions->z,
+                                           psOptions->scale,
+                                           psOptions->alt,
+                                           psOptions->az,
+                                           psOptions->bZevenbergenThorne);
+        if (psOptions->bZevenbergenThorne)
+        {
+            if(!psOptions->bCombined)
+                pfnAlg = GDALHillshadeZevenbergenThorneAlg;
+            else
+                pfnAlg = GDALHillshadeZevenbergenThorneCombinedAlg;
+        }
+        else
+        {
+            if(!psOptions->bCombined)
+                pfnAlg = GDALHillshadeAlg;
+            else
+                pfnAlg = GDALHillshadeCombinedAlg;
+        }
+    }
+    else if (eUtilityMode == SLOPE)
+    {
+        dfDstNoDataValue = -9999;
+        bDstHasNoData = TRUE;
+
+        pData = GDALCreateSlopeData(adfGeoTransform, psOptions->scale, psOptions->slopeFormat);
+        if (psOptions->bZevenbergenThorne)
+            pfnAlg = GDALSlopeZevenbergenThorneAlg;
+        else
+            pfnAlg = GDALSlopeHornAlg;
+    }
+
+    else if (eUtilityMode == ASPECT)
+    {
+        if (!psOptions->bZeroForFlat)
+        {
+            dfDstNoDataValue = -9999;
+            bDstHasNoData = TRUE;
+        }
+
+        pData = GDALCreateAspectData(psOptions->bAngleAsAzimuth);
+        if (psOptions->bZevenbergenThorne)
+            pfnAlg = GDALAspectZevenbergenThorneAlg;
+        else
+            pfnAlg = GDALAspectAlg;
+    }
+    else if (eUtilityMode == TRI)
+    {
+        dfDstNoDataValue = -9999;
+        bDstHasNoData = TRUE;
+        pfnAlg = GDALTRIAlg;
+    }
+    else if (eUtilityMode == TPI)
+    {
+        dfDstNoDataValue = -9999;
+        bDstHasNoData = TRUE;
+        pfnAlg = GDALTPIAlg;
+    }
+    else if (eUtilityMode == ROUGHNESS)
+    {
+        dfDstNoDataValue = -9999;
+        bDstHasNoData = TRUE;
+        pfnAlg = GDALRoughnessAlg;
+    }
+
+    GDALDataType eDstDataType = (eUtilityMode == HILL_SHADE ||
+                                 eUtilityMode == COLOR_RELIEF) ? GDT_Byte :
+                                                               GDT_Float32;
+
+    if( EQUAL(psOptions->pszFormat, "VRT") )
+    {
+        if (eUtilityMode == COLOR_RELIEF)
+        {
+            GDALGenerateVRTColorRelief(pszDest,
+                                       hSrcDataset,
+                                       hSrcBand,
+                                       pszColorFilename,
+                                       psOptions->eColorSelectionMode,
+                                       psOptions->bAddAlpha);
+
+            CPLFree(pData);
+
+            GDALDEMProcessingOptionsFree(psOptionsToFree);
+            return GDALOpen(pszDest, GA_Update);
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "VRT driver can only be used with color-relief utility.");
+            GDALDEMProcessingOptionsFree(psOptionsToFree);
+            CPLFree(pData);
+            return NULL;
+        }
+    }
+
+    // We might actually want to always go through the intermediate dataset
+    bool bForceUseIntermediateDataset = false;
+
+    GDALProgressFunc pfnProgress = psOptions->pfnProgress;
+    void* pProgressData = psOptions->pProgressData;
+
+    if( EQUAL(psOptions->pszFormat, "GTiff") )
+    {
+        if( !EQUAL(CSLFetchNameValueDef(psOptions->papszCreateOptions, "COMPRESS", "NONE"), "NONE") &&
+            CPLTestBool(CSLFetchNameValueDef(psOptions->papszCreateOptions, "TILED", "NO")) )
+        {
+            bForceUseIntermediateDataset = true;
+        }
+        else if( strcmp(pszDest, "/vsistdout/") == 0 )
+        {
+            bForceUseIntermediateDataset = true;
+            pfnProgress = GDALDummyProgress;
+            pProgressData = NULL;
+        }
+#ifdef S_ISFIFO
+        else
+        {
+            VSIStatBufL sStat;
+            if( VSIStatExL(pszDest, &sStat, VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG) == 0 &&
+                S_ISFIFO(sStat.st_mode) )
+            {
+                bForceUseIntermediateDataset = true;
+            }
+        }
+#endif
+    }
+
+    if( GDALGetMetadataItem( hDriver, GDAL_DCAP_RASTER, NULL) != NULL &&
+        ((bForceUseIntermediateDataset || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) == NULL) &&
+         GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY, NULL ) != NULL) )
+    {
+        GDALDatasetH hIntermediateDataset;
+
+        if (eUtilityMode == COLOR_RELIEF)
+        {
+            GDALColorReliefDataset* poDS =
+                new GDALColorReliefDataset (hSrcDataset,
+                                            hSrcBand,
+                                            pszColorFilename,
+                                            psOptions->eColorSelectionMode,
+                                            psOptions->bAddAlpha);
+            if( !(poDS->InitOK()) )
+            {
+                delete poDS;
+                CPLFree(pData);
+                GDALDEMProcessingOptionsFree(psOptionsToFree);
+                return NULL;
+            }
+            hIntermediateDataset = (GDALDatasetH)poDS;
+        }
+        else
+        {
+            GDALGeneric3x3Dataset* poDS =
+                new GDALGeneric3x3Dataset(hSrcDataset, hSrcBand,
+                                          eDstDataType,
+                                          bDstHasNoData,
+                                          dfDstNoDataValue,
+                                          pfnAlg,
+                                          pData,
+                                          psOptions->bComputeAtEdges);
+            if( !(poDS->InitOK()) )
+            {
+                delete poDS;
+                CPLFree(pData);
+                GDALDEMProcessingOptionsFree(psOptionsToFree);
+                return NULL;
+            }
+            hIntermediateDataset = (GDALDatasetH)poDS;
+        }
+
+        GDALDatasetH hOutDS = GDALCreateCopy(
+                                 hDriver, pszDest, hIntermediateDataset,
+                                 TRUE, psOptions->papszCreateOptions,
+                                 pfnProgress, pProgressData );
+
+        GDALClose(hIntermediateDataset);
+
+        CPLFree(pData);
+
+        GDALDEMProcessingOptionsFree(psOptionsToFree);
+        return hOutDS;
+    }
+
+    int nDstBands;
+    if (eUtilityMode == COLOR_RELIEF)
+        nDstBands = (psOptions->bAddAlpha) ? 4 : 3;
+    else
+        nDstBands = 1;
+
+    hDstDataset = GDALCreate(   hDriver,
+                                pszDest,
+                                nXSize,
+                                nYSize,
+                                nDstBands,
+                                eDstDataType,
+                                psOptions->papszCreateOptions);
+
+    if( hDstDataset == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unable to create dataset %s", pszDest );
+        GDALDEMProcessingOptionsFree(psOptionsToFree);
+        CPLFree(pData);
+        return NULL;
+    }
+
+    hDstBand = GDALGetRasterBand( hDstDataset, 1 );
+
+    GDALSetGeoTransform(hDstDataset, adfGeoTransform);
+    GDALSetProjection(hDstDataset, GDALGetProjectionRef(hSrcDataset));
+
+    if (eUtilityMode == COLOR_RELIEF)
+    {
+        GDALColorRelief (hSrcBand,
+                         GDALGetRasterBand(hDstDataset, 1),
+                         GDALGetRasterBand(hDstDataset, 2),
+                         GDALGetRasterBand(hDstDataset, 3),
+                         (psOptions->bAddAlpha) ? GDALGetRasterBand(hDstDataset, 4) : NULL,
+                         pszColorFilename,
+                         psOptions->eColorSelectionMode,
+                         pfnProgress, pProgressData);
+    }
+    else
+    {
+        if (bDstHasNoData)
+            GDALSetRasterNoDataValue(hDstBand, dfDstNoDataValue);
+
+        GDALGeneric3x3Processing(hSrcBand, hDstBand,
+                                 pfnAlg, pData,
+                                 psOptions->bComputeAtEdges,
+                                 pfnProgress, pProgressData);
+
+    }
+
+    CPLFree(pData);
+
+    GDALDEMProcessingOptionsFree(psOptionsToFree);
+    return hDstDataset;
+}
+
+/************************************************************************/
+/*                           GDALDEMProcessingOptionsNew()              */
+/************************************************************************/
+
+/**
+ * Allocates a GDALDEMProcessingOptions struct.
+ *
+ * @param papszArgv NULL terminated list of options (potentially including filename and open options too), or NULL.
+ *                  The accepted options are the ones of the <a href="gdal_translate.html">gdal_translate</a> utility.
+ * @param psOptionsForBinary (output) may be NULL (and should generally be NULL),
+ *                           otherwise (gdal_translate_bin.cpp use case) must be allocated with
+ *                           GDALDEMProcessingOptionsForBinaryNew() prior to this function. Will be
+ *                           filled with potentially present filename, open options,...
+ * @return pointer to the allocated GDALDEMProcessingOptions struct. Must be freed with GDALDEMProcessingOptionsFree().
+ *
+ * @since GDAL 2.1
+ */
+
+GDALDEMProcessingOptions *GDALDEMProcessingOptionsNew(char** papszArgv,
+                                                      GDALDEMProcessingOptionsForBinary* psOptionsForBinary)
+{
+    GDALDEMProcessingOptions *psOptions = (GDALDEMProcessingOptions *) CPLCalloc( 1, sizeof(GDALDEMProcessingOptions) );
+    Algorithm eUtilityMode = INVALID;
+
+    psOptions->pszFormat = CPLStrdup("GTiff");
+    psOptions->pfnProgress = GDALDummyProgress;
+    psOptions->pProgressData = NULL;
+    psOptions->z = 1.0;
+    psOptions->scale = 1.0;
+    psOptions->az = 315.0;
+    psOptions->alt = 45.0;
+    // 0 = 'percent' or 1 = 'degrees'
+    psOptions->slopeFormat = 1;
+    psOptions->bAddAlpha = FALSE;
+    psOptions->bZeroForFlat = FALSE;
+    psOptions->bAngleAsAzimuth = TRUE;
+    psOptions->eColorSelectionMode = COLOR_SELECTION_INTERPOLATE;
+    psOptions->bComputeAtEdges = FALSE;
+    psOptions->bZevenbergenThorne = FALSE;
+    psOptions->bCombined = FALSE;
+    psOptions->nBand = 1;
+    psOptions->papszCreateOptions = NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Handle command line arguments.                                  */
+/* -------------------------------------------------------------------- */
+    int argc = CSLCount(papszArgv);
+    for( int i = 0; i < argc; i++ )
+    {
+        if( i == 0 && psOptionsForBinary )
+        {
+            eUtilityMode = GetAlgorithm(papszArgv[0]);
+            if(eUtilityMode == INVALID )
+            {
+                CPLError(CE_Failure, CPLE_IllegalArg, "Invalid utility mode");
+                GDALDEMProcessingOptionsFree(psOptions);
+                return NULL;
+            }
+            psOptionsForBinary->pszProcessing = CPLStrdup(papszArgv[0]);
+            continue;
+        }
+
+        if( EQUAL(papszArgv[i],"-of") && i < argc-1 )
+        {
+            ++i;
+            CPLFree(psOptions->pszFormat);
+            psOptions->pszFormat = CPLStrdup(papszArgv[i]);
+            if( psOptionsForBinary )
+            {
+                psOptionsForBinary->bFormatExplicitlySet = TRUE;
+            }
+        }
+
+        else if( EQUAL(papszArgv[i],"-q") || EQUAL(papszArgv[i],"-quiet") )
+        {
+            if( psOptionsForBinary )
+                psOptionsForBinary->bQuiet = TRUE;
+        }
+
+        else if( (EQUAL(papszArgv[i], "--z") || EQUAL(papszArgv[i], "-z")) && i+1<argc)
+        {
+            ++i;
+            if( !ArgIsNumeric(papszArgv[i]) )
+            {
+                CPLError(CE_Failure, CPLE_IllegalArg, "Numeric value expected for -z");
+                GDALDEMProcessingOptionsFree(psOptions);
+                return NULL;
+            }
+            psOptions->z = CPLAtof(papszArgv[i]);
+        }
+        else if ( EQUAL(papszArgv[i], "-p") )
+        {
+            psOptions->slopeFormat = 0;
+        }
+        else if ( EQUAL(papszArgv[i], "-alg") && i+1<argc)
+        {
+            i ++;
+            if (EQUAL(papszArgv[i], "ZevenbergenThorne"))
+                psOptions->bZevenbergenThorne = TRUE;
+            else if (!EQUAL(papszArgv[i], "Horn"))
+            {
+                CPLError(CE_Failure, CPLE_IllegalArg, "Numeric value expected for %s", papszArgv[i-1]);
+                GDALDEMProcessingOptionsFree(psOptions);
+                return NULL;
+            }
+        }
+        else if ( EQUAL(papszArgv[i], "-trigonometric"))
+        {
+            psOptions->bAngleAsAzimuth = FALSE;
+        }
+        else if ( EQUAL(papszArgv[i], "-zero_for_flat"))
+        {
+            psOptions->bZeroForFlat = TRUE;
+        }
+        else if ( EQUAL(papszArgv[i], "-exact_color_entry"))
+        {
+            psOptions->eColorSelectionMode = COLOR_SELECTION_EXACT_ENTRY;
+        }
+        else if ( EQUAL(papszArgv[i], "-nearest_color_entry"))
+        {
+            psOptions->eColorSelectionMode = COLOR_SELECTION_NEAREST_ENTRY;
+        }
+        else if(
+            (EQUAL(papszArgv[i], "--s") ||
+             EQUAL(papszArgv[i], "-s") ||
+             EQUAL(papszArgv[i], "--scale") ||
+             EQUAL(papszArgv[i], "-scale")) && i+1<argc
+          )
+        {
+            ++i;
+            if( !ArgIsNumeric(papszArgv[i]) )
+            {
+                CPLError(CE_Failure, CPLE_IllegalArg, "Numeric value expected for %s", papszArgv[i-1]);
+                GDALDEMProcessingOptionsFree(psOptions);
+                return NULL;
+            }
+            psOptions->scale = CPLAtof(papszArgv[i]);
+        }
+        else if(
+            (EQUAL(papszArgv[i], "--az") ||
+             EQUAL(papszArgv[i], "-az") ||
+             EQUAL(papszArgv[i], "--azimuth") ||
+             EQUAL(papszArgv[i], "-azimuth")) && i+1<argc
+          )
+        {
+            ++i;
+            if( !ArgIsNumeric(papszArgv[i]) )
+            {
+                CPLError(CE_Failure, CPLE_IllegalArg, "Numeric value expected for %s", papszArgv[i-1]);
+                GDALDEMProcessingOptionsFree(psOptions);
+                return NULL;
+            }
+            psOptions->az = CPLAtof(papszArgv[i]);
+        }
+        else if( eUtilityMode == HILL_SHADE &&
+            (EQUAL(papszArgv[i], "--alt") ||
+             EQUAL(papszArgv[i], "-alt") ||
+             EQUAL(papszArgv[i], "--alt") ||
+             EQUAL(papszArgv[i], "-alt")) && i+1<argc
+          )
+        {
+            ++i;
+            if( !ArgIsNumeric(papszArgv[i]) )
+            {
+                CPLError(CE_Failure, CPLE_IllegalArg, "Numeric value expected for %s", papszArgv[i-1]);
+                GDALDEMProcessingOptionsFree(psOptions);
+                return NULL;
+            }
+            psOptions->alt = CPLAtof(papszArgv[i]);
+        }
+        else if(
+            (EQUAL(papszArgv[i], "-combined") ||
+             EQUAL(papszArgv[i], "--combined"))
+          )
+        {
+            psOptions->bCombined = TRUE;
+        }
+        else if(
+                 EQUAL(papszArgv[i], "-alpha"))
+        {
+            psOptions->bAddAlpha = TRUE;
+        }
+        else if(
+                 EQUAL(papszArgv[i], "-compute_edges"))
+        {
+            psOptions->bComputeAtEdges = TRUE;
+        }
+        else if( i + 1 < argc &&
+            (EQUAL(papszArgv[i], "--b") ||
+             EQUAL(papszArgv[i], "-b"))
+          )
+        {
+            psOptions->nBand = atoi(papszArgv[++i]);
+        }
+        else if( EQUAL(papszArgv[i],"-co") && i+1<argc )
+        {
+            psOptions->papszCreateOptions = CSLAddString( psOptions->papszCreateOptions, papszArgv[++i] );
+        }
+        else if( papszArgv[i][0] == '-' )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unknown option name '%s'", papszArgv[i]);
+            GDALDEMProcessingOptionsFree(psOptions);
+            return NULL;
+        }
+        else if( psOptionsForBinary && psOptionsForBinary->pszSrcFilename == NULL )
+        {
+            psOptionsForBinary->pszSrcFilename = CPLStrdup(papszArgv[i]);
+        }
+        else if( psOptionsForBinary && eUtilityMode == COLOR_RELIEF && psOptionsForBinary->pszColorFilename == NULL )
+        {
+            psOptionsForBinary->pszColorFilename = CPLStrdup(papszArgv[i]);
+        }
+        else if( psOptionsForBinary && psOptionsForBinary->pszDstFilename == NULL )
+        {
+            psOptionsForBinary->pszDstFilename = CPLStrdup(papszArgv[i]);
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Too many command options '%s'", papszArgv[i]);
+            GDALDEMProcessingOptionsFree(psOptions);
+            return NULL;
+        }
+    }
+
+    if( psOptionsForBinary )
+    {
+        psOptionsForBinary->pszFormat = CPLStrdup(psOptions->pszFormat);
+    }
+
+    return psOptions;
+}
+
+/************************************************************************/
+/*                       GDALDEMProcessingOptionsFree()                 */
+/************************************************************************/
+
+/**
+ * Frees the GDALDEMProcessingOptions struct.
+ *
+ * @param psOptions the options struct for GDALDEMProcessing().
+ *
+ * @since GDAL 2.1
+ */
+
+void GDALDEMProcessingOptionsFree(GDALDEMProcessingOptions *psOptions)
+{
+    if( psOptions )
+    {
+        CPLFree(psOptions->pszFormat);
+        CSLDestroy(psOptions->papszCreateOptions);
+
+        CPLFree(psOptions);
+    }
+}
+
+/************************************************************************/
+/*                 GDALDEMProcessingOptionsSetProgress()                */
+/************************************************************************/
+
+/**
+ * Set a progress function.
+ *
+ * @param psOptions the options struct for GDALDEMProcessing().
+ * @param pfnProgress the progress callback.
+ * @param pProgressData the user data for the progress callback.
+ *
+ * @since GDAL 2.1
+ */
+
+void GDALDEMProcessingOptionsSetProgress( GDALDEMProcessingOptions *psOptions,
+                                      GDALProgressFunc pfnProgress, void *pProgressData )
+{
+    psOptions->pfnProgress = pfnProgress;
+    psOptions->pProgressData = pProgressData;
+}
diff --git a/apps/gdalenhance.cpp b/apps/gdalenhance.cpp
index 2c357d3..ad1701e 100644
--- a/apps/gdalenhance.cpp
+++ b/apps/gdalenhance.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: gdalenhance.cpp 28899 2015-04-14 09:27:00Z rouault $
+ * $Id: gdalenhance.cpp 33615 2016-03-02 20:19:22Z goatbar $
  *
  * Project:  GDAL Utilities
- * Purpose:  Commandline application to do image enhancement. 
+ * Purpose:  Command line application to do image enhancement.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  * ****************************************************************************
@@ -35,17 +35,16 @@
 #include "vrtdataset.h"
 #include "commonutils.h"
 
-CPL_CVSID("$Id: gdalenhance.cpp 28899 2015-04-14 09:27:00Z rouault $");
+CPL_CVSID("$Id: gdalenhance.cpp 33615 2016-03-02 20:19:22Z goatbar $");
 
 static int
 ComputeEqualizationLUTs( GDALDatasetH hDataset,  int nLUTBins,
-                         double **ppadfScaleMin, double **padfScaleMax, 
+                         double **ppadfScaleMin, double **padfScaleMax,
                          int ***ppapanLUTs, GDALProgressFunc pfnProgress );
 
-static CPLErr EnhancerCallback( void *hCBData, 
+static CPLErr EnhancerCallback( void *hCBData,
                                 int nXOff, int nYOff, int nXSize, int nYSize,
                                 void *pData );
-                                
 
 typedef struct {
     GDALRasterBand *poSrcBand;
@@ -69,7 +68,7 @@ static void Usage()
             "             CInt16/CInt32/CFloat32/CFloat64}]\n"
             "       [-src_scale[_n] src_min src_max]\n"
             "       [-dst_scale[_n] dst_min dst_max]\n"
-            "       [-lutbins count]\n" 
+            "       [-lutbins count]\n"
             "       [-s_nodata[_n] value]\n"
             "       [-stddev multiplier]\n"
             "       [-equalize]\n"
@@ -135,8 +134,8 @@ int main( int argc, char ** argv )
 
         else if( EQUAL(argv[i],"-ot") && i < argc-1 )
         {
-            int	iType;
-            
+            int iType;
+
             for( iType = 1; iType < GDT_TypeCount; iType++ )
             {
                 if( GDALGetDataTypeName((GDALDataType)iType) != NULL
@@ -155,24 +154,24 @@ int main( int argc, char ** argv )
             i++;
         }
 
-        else if( EQUALN(argv[i],"-s_nodata",9) )
+        else if( STARTS_WITH_CI(argv[i], "-s_nodata") )
         {
             // TODO
             i += 1;
-        }   
+        }
 
         else if( EQUAL(argv[i],"-co") && i < argc-1 )
         {
             papszCreateOptions = CSLAddString( papszCreateOptions, argv[++i] );
-        }   
+        }
 
-        else if( EQUALN(argv[i],"-src_scale",10) && i < argc-2)
+        else if( STARTS_WITH_CI(argv[i], "-src_scale") && i < argc-2)
         {
             // TODO
             i += 2;
         }
 
-        else if( EQUALN(argv[i],"-dst_scale",10) && i < argc-2 )
+        else if( STARTS_WITH_CI(argv[i], "-dst_scale") && i < argc-2 )
         {
             // TODO
             i += 2;
@@ -196,7 +195,7 @@ int main( int argc, char ** argv )
 
         else if( argv[i][0] == '-' )
         {
-            printf( "Option %s incomplete, or not recognised.\n\n", 
+            printf( "Option %s incomplete, or not recognised.\n\n",
                     argv[i] );
             Usage();
         }
@@ -226,7 +225,7 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
 
     hDataset = GDALOpenShared( pszSource, GA_ReadOnly );
-    
+
     if( hDataset == NULL )
     {
         fprintf( stderr,
@@ -244,13 +243,13 @@ int main( int argc, char ** argv )
     hDriver = GDALGetDriverByName( pszFormat );
     if( hDriver == NULL )
     {
-        int	iDr;
-        
+        int iDr;
+
         printf( "Output driver `%s' not recognised.\n", pszFormat );
         printf( "The following format drivers are configured and support output:\n" );
         for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
         {
-            GDALDriverH hDriver = GDALGetDriver(iDr);
+            hDriver = GDALGetDriver(iDr);
 
             if( GDALGetMetadataItem( hDriver, GDAL_DCAP_RASTER, NULL) != NULL &&
                 (GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) != NULL
@@ -273,8 +272,8 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
     if( EQUAL(pszMethod,"equalize") )
     {
-        ComputeEqualizationLUTs( hDataset, nLUTBins, 
-                                 &padfScaleMin, &padfScaleMax, 
+        ComputeEqualizationLUTs( hDataset, nLUTBins,
+                                 &padfScaleMin, &padfScaleMax,
                                  &papanLUTs, pfnProgress );
     }
 
@@ -302,7 +301,7 @@ int main( int argc, char ** argv )
             int iLUT;
             char **papszTokens = CSLTokenizeString( papszLines[iBand] );
 
-            if( CSLCount(papszTokens) < 3 
+            if( CSLCount(papszTokens) < 3
                 || atoi(papszTokens[0]) != iBand+1 )
             {
                 fprintf( stderr, "Line %d seems to be corrupt.\n", iBand+1 );
@@ -318,7 +317,7 @@ int main( int argc, char ** argv )
                 continue;
 
             // process lut
-            if( iBand == 0 )
+            if( papanLUTs == NULL )
             {
                 nLUTBins = CSLCount(papszTokens) - 3;
                 papanLUTs = (int **) CPLCalloc(sizeof(int*),nBandCount);
@@ -342,12 +341,12 @@ int main( int argc, char ** argv )
         FILE *fpConfig = stdout;
         if( pszConfigFile )
             fpConfig = fopen( pszConfigFile, "w" );
-        
+
         for( iBand = 0; iBand < nBandCount; iBand++ )
         {
             fprintf( fpConfig, "%d:Band ", iBand+1 );
             if( padfScaleMin != NULL )
-                fprintf( fpConfig, "%g:ScaleMin %g:ScaleMax ", 
+                fprintf( fpConfig, "%g:ScaleMin %g:ScaleMax ",
                          padfScaleMin[iBand], padfScaleMax[iBand] );
 
             if( papanLUTs )
@@ -376,9 +375,9 @@ int main( int argc, char ** argv )
 /*      Create a virtual dataset.                                       */
 /* ==================================================================== */
     VRTDataset *poVDS;
-    EnhanceCBInfo *pasEInfo = (EnhanceCBInfo *) 
+    EnhanceCBInfo *pasEInfo = (EnhanceCBInfo *)
         CPLCalloc(nBandCount, sizeof(EnhanceCBInfo));
-        
+
 /* -------------------------------------------------------------------- */
 /*      Make a virtual clone.                                           */
 /* -------------------------------------------------------------------- */
@@ -399,11 +398,11 @@ int main( int argc, char ** argv )
     }
     else
     {
-        poVDS->SetGCPs( GDALGetGCPCount(hDataset), 
+        poVDS->SetGCPs( GDALGetGCPCount(hDataset),
                         GDALGetGCPs(hDataset),
                         GDALGetGCPProjection( hDataset ) );
     }
-    
+
     poVDS->SetMetadata( ((GDALDataset*)hDataset)->GetMetadata() );
 
     for( iBand = 0; iBand < nBandCount; iBand++ )
@@ -427,7 +426,7 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
         poVDS->AddBand( eBandType, NULL );
         poVRTBand = (VRTSourcedRasterBand *) poVDS->GetRasterBand( iBand+1 );
-            
+
 /* -------------------------------------------------------------------- */
 /*      Create a function based source with info on how to apply the    */
 /*      enhancement.                                                    */
@@ -440,7 +439,7 @@ int main( int argc, char ** argv )
 
         if( papanLUTs )
             pasEInfo[iBand].panLUT = papanLUTs[iBand];
-        
+
         poVRTBand->AddFuncSource( EnhancerCallback, pasEInfo + iBand );
 
 /* -------------------------------------------------------------------- */
@@ -453,15 +452,15 @@ int main( int argc, char ** argv )
 /*      Write to the output file using CopyCreate().                    */
 /* -------------------------------------------------------------------- */
     hOutDS = GDALCreateCopy( hDriver, pszDest, (GDALDatasetH) poVDS,
-                             FALSE, papszCreateOptions, 
+                             FALSE, papszCreateOptions,
                              pfnProgress, NULL );
     if( hOutDS != NULL )
         GDALClose( hOutDS );
 
     GDALClose( (GDALDatasetH) poVDS );
-        
+
     GDALClose( hDataset );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Cleanup and exit.                                               */
 /* -------------------------------------------------------------------- */
@@ -482,8 +481,8 @@ int main( int argc, char ** argv )
 
 static int
 ComputeEqualizationLUTs( GDALDatasetH hDataset, int nLUTBins,
-                         double **ppadfScaleMin, double **ppadfScaleMax, 
-                         int ***ppapanLUTs, 
+                         double **ppadfScaleMin, double **ppadfScaleMax,
+                         int ***ppapanLUTs,
                          GDALProgressFunc pfnProgress )
 
 {
@@ -510,10 +509,10 @@ ComputeEqualizationLUTs( GDALDatasetH hDataset, int nLUTBins,
 /*      Get a reasonable histogram.                                     */
 /* -------------------------------------------------------------------- */
         eErr =
-            GDALGetDefaultHistogramEx( hBand, 
+            GDALGetDefaultHistogramEx( hBand,
                                      *ppadfScaleMin + iBand,
                                      *ppadfScaleMax + iBand,
-                                     &nHistSize, &panHistogram, 
+                                     &nHistSize, &panHistogram,
                                      TRUE, pfnProgress, NULL );
 
         if( eErr != CE_None )
@@ -541,7 +540,7 @@ ComputeEqualizationLUTs( GDALDatasetH hDataset, int nLUTBins,
 
         if( nTotal == 0 )
         {
-            CPLError( CE_Warning, CPLE_AppDefined, 
+            CPLError( CE_Warning, CPLE_AppDefined,
                       "Zero value entries in histogram, results will not be meaningful." );
             nTotal = 1;
         }
@@ -559,7 +558,7 @@ ComputeEqualizationLUTs( GDALDatasetH hDataset, int nLUTBins,
 
             panLUT[iLUT] = MAX(0,MIN(nLUTBins-1,nValue));
 
-        } 
+        }
 
         (*ppapanLUTs)[iBand] = panLUT;
     }
@@ -573,7 +572,7 @@ ComputeEqualizationLUTs( GDALDatasetH hDataset, int nLUTBins,
 /*      This is the VRT callback that actually does the image rescaling.*/
 /************************************************************************/
 
-static CPLErr EnhancerCallback( void *hCBData, 
+static CPLErr EnhancerCallback( void *hCBData,
                                 int nXOff, int nYOff, int nXSize, int nYSize,
                                 void *pData )
 
@@ -586,7 +585,7 @@ static CPLErr EnhancerCallback( void *hCBData,
                   "Currently gdalenhance only supports Byte output." );
         exit( 2 );
     }
-    
+
     GByte *pabyOutImage = (GByte *) pData;
     CPLErr eErr;
     float *pafSrcImage = (float *) CPLCalloc(sizeof(float),nXSize*nYSize);
@@ -605,9 +604,9 @@ static CPLErr EnhancerCallback( void *hCBData,
     int iPixel;
     int bHaveNoData;
     float fNoData = (float)psEInfo->poSrcBand->GetNoDataValue( &bHaveNoData );
-    double dfScale = 
+    double dfScale =
         psEInfo->nLUTBins / (psEInfo->dfScaleMax - psEInfo->dfScaleMin);
-    
+
     for( iPixel = 0; iPixel < nPixelCount; iPixel++ )
     {
         if( bHaveNoData && pafSrcImage[iPixel] == fNoData )
@@ -629,5 +628,3 @@ static CPLErr EnhancerCallback( void *hCBData,
 
     return CE_None;
 }
-
-
diff --git a/apps/gdalflattenmask.c b/apps/gdalflattenmask.c
index 3323633..0b93575 100644
--- a/apps/gdalflattenmask.c
+++ b/apps/gdalflattenmask.c
@@ -181,7 +181,7 @@ int main(int argc, char* argv[])
 /* -------------------------------------------------------------------- */
 /*      Write geotransform, projection, color interpretations, no data  */
 /*      values, color tables, metadata, etc. before the file is         */
-/*       crystalized                                                    */
+/*      crystallized.                                                   */
 /* -------------------------------------------------------------------- */
     if( GDALGetGeoTransform( hSrcDS, adfGeoTransform ) == CE_None )
     {
diff --git a/apps/gdalinfo.c b/apps/gdalinfo.c
deleted file mode 100644
index 482ddea..0000000
--- a/apps/gdalinfo.c
+++ /dev/null
@@ -1,1600 +0,0 @@
-/******************************************************************************
- * $Id: gdalinfo.c 29781 2015-08-25 16:20:28Z rouault $
- *
- * Project:  GDAL Utilities
- * Purpose:  Commandline application to list info about a file.
- * Author:   Frank Warmerdam, warmerdam at pobox.com
- *
- * ****************************************************************************
- * Copyright (c) 1998, Frank Warmerdam
- * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "gdal.h"
-#include "gdal_alg.h"
-#include "ogr_srs_api.h"
-#include "cpl_string.h"
-#include "cpl_conv.h"
-#include "cpl_multiproc.h"
-#include "commonutils.h"
-#include "json.h"
-#include "ogrgeojsonwriter.h"
-
-CPL_CVSID("$Id: gdalinfo.c 29781 2015-08-25 16:20:28Z rouault $");
-
-static int 
-GDALInfoReportCorner( GDALDatasetH hDataset, 
-                      OGRCoordinateTransformationH hTransform, OGRCoordinateTransformationH hTransformWGS84,
-                      const char * corner_name,
-                      double x, double y,
-                      int bJson, json_object *poCornerCoordinates,
-                      json_object *poWGS84ExtentCoordinates );
-
-static void
-GDALInfoReportMetadata( GDALMajorObjectH hObject,
-                        int bListMDD,
-                        int bShowMetadata,
-                        char **papszExtraMDDomains,
-                        int bIsBand,
-                        int bJson,
-                        json_object *poMetadata );
-
-
-
-/************************************************************************/
-/*                               Usage()                                */
-/************************************************************************/
-
-void Usage(const char* pszErrorMsg)
-
-{
-    printf( "Usage: gdalinfo [--help-general] [-json] [-mm] [-stats] [-hist] [-nogcp] [-nomd]\n"
-            "                [-norat] [-noct] [-nofl] [-checksum] [-proj4]\n"
-            "                [-listmdd] [-mdd domain|`all`]*\n"
-            "                [-sd subdataset] [-oo NAME=VALUE]* datasetname\n" );
-
-    if( pszErrorMsg != NULL )
-        fprintf(stderr, "\nFAILURE: %s\n", pszErrorMsg);
-
-    exit( 1 );
-}
-
-/************************************************************************/
-/*                                main()                                */
-/************************************************************************/
-
-#define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg) \
-    do { if (i + nExtraArg >= argc) \
-        Usage(CPLSPrintf("%s option requires %d argument(s)", argv[i], nExtraArg)); } while(0)
-
-int main( int argc, char ** argv ) 
-
-{
-    GDALDatasetH    hDataset = NULL;
-    GDALRasterBandH hBand = NULL;
-    int         i, iBand;
-    double      adfGeoTransform[6];
-    GDALDriverH     hDriver;
-    int                 bComputeMinMax = FALSE, bSample = FALSE;
-    int                 bShowGCPs = TRUE, bShowMetadata = TRUE, bShowRAT=TRUE;
-    int                 bStats = FALSE, bApproxStats = TRUE;
-    int                 bShowColorTable = TRUE, bComputeChecksum = FALSE;
-    int                 bReportHistograms = FALSE;
-    int                 bReportProj4 = FALSE;
-    int                 nSubdataset = -1;
-    const char          *pszFilename = NULL;
-    char              **papszExtraMDDomains = NULL, **papszFileList;
-    int                 bListMDD = FALSE;
-    const char  *pszProjection = NULL;
-    OGRCoordinateTransformationH hTransform = NULL, hTransformWGS84 = NULL;
-    int             bShowFileList = TRUE;
-    char              **papszOpenOptions = NULL;
-
-    int bJson = FALSE;
-    json_object *poJsonObject = NULL, *poBands = NULL, *poMetadata = NULL;
-
-    /* Check that we are running against at least GDAL 1.5 */
-    /* Note to developers : if we use newer API, please change the requirement */
-    if (atoi(GDALVersionInfo("VERSION_NUM")) < 1500)
-    {
-        fprintf(stderr, "At least, GDAL >= 1.5.0 is required for this version of %s, "
-                "which was compiled against GDAL %s\n", argv[0], GDAL_RELEASE_NAME);
-        exit(1);
-    }
-
-    EarlySetConfigOptions(argc, argv);
-
-    GDALAllRegister();
-
-    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
-    if( argc < 1 )
-        exit( -argc );
-
-/* -------------------------------------------------------------------- */
-/*      Parse arguments.                                                */
-/* -------------------------------------------------------------------- */
-    for( i = 1; i < argc; i++ )
-    {
-        if( EQUAL(argv[i], "--utility_version") )
-        {
-            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
-                   argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
-            return 0;
-        }
-        else if( EQUAL(argv[i],"--help") )
-            Usage(NULL);
-        else if( EQUAL(argv[i],"-json") )
-            bJson = TRUE;
-        else if( EQUAL(argv[i], "-mm") )
-            bComputeMinMax = TRUE;
-        else if( EQUAL(argv[i], "-hist") )
-            bReportHistograms = TRUE;
-        else if( EQUAL(argv[i], "-proj4") )
-            bReportProj4 = TRUE;
-        else if( EQUAL(argv[i], "-stats") )
-        {
-            bStats = TRUE;
-            bApproxStats = FALSE;
-        }
-        else if( EQUAL(argv[i], "-approx_stats") )
-        {
-            bStats = TRUE;
-            bApproxStats = TRUE;
-        }
-        else if( EQUAL(argv[i], "-sample") )
-            bSample = TRUE;
-        else if( EQUAL(argv[i], "-checksum") )
-            bComputeChecksum = TRUE;
-        else if( EQUAL(argv[i], "-nogcp") )
-            bShowGCPs = FALSE;
-        else if( EQUAL(argv[i], "-nomd") )
-            bShowMetadata = FALSE;
-        else if( EQUAL(argv[i], "-norat") )
-            bShowRAT = FALSE;
-        else if( EQUAL(argv[i], "-noct") )
-            bShowColorTable = FALSE;
-        else if( EQUAL(argv[i], "-listmdd") )
-            bListMDD = TRUE;
-        else if( EQUAL(argv[i], "-mdd") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            papszExtraMDDomains = CSLAddString( papszExtraMDDomains,
-                                                argv[++i] );
-        }
-        else if( EQUAL(argv[i], "-oo") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            papszOpenOptions = CSLAddString( papszOpenOptions,
-                                                argv[++i] );
-        }
-        else if( EQUAL(argv[i], "-nofl") )
-            bShowFileList = FALSE;
-        else if( EQUAL(argv[i], "-sd") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            nSubdataset = atoi(argv[++i]);
-        }
-        else if( argv[i][0] == '-' )
-            Usage(CPLSPrintf("Unknown option name '%s'", argv[i]));
-        else if( pszFilename == NULL )
-            pszFilename = argv[i];
-        else
-            Usage("Too many command options.");
-    }
-
-    if( pszFilename == NULL )
-        Usage("No datasource specified.");
-
-/* -------------------------------------------------------------------- */
-/*      Open dataset.                                                   */
-/* -------------------------------------------------------------------- */
-    hDataset = GDALOpenEx( pszFilename, GDAL_OF_READONLY | GDAL_OF_RASTER, NULL,
-                           (const char* const* )papszOpenOptions, NULL );
-
-    if( hDataset == NULL )
-    {
-        fprintf( stderr,
-                 "gdalinfo failed - unable to open '%s'.\n",
-                 pszFilename );
-
-/* -------------------------------------------------------------------- */
-/*      If argument is a VSIFILE, then print its contents               */
-/* -------------------------------------------------------------------- */
-        if ( strncmp( pszFilename, "/vsizip/", 8 ) == 0 || 
-             strncmp( pszFilename, "/vsitar/", 8 ) == 0 ) 
-        {
-            papszFileList = VSIReadDirRecursive( pszFilename );
-            if ( papszFileList )
-            {
-                int nCount = CSLCount( papszFileList );
-                fprintf( stdout, 
-                         "Unable to open source `%s' directly.\n"
-                         "The archive contains %d files:\n", 
-                         pszFilename, nCount );
-                for ( i = 0; i < nCount; i++ )
-                {
-                    fprintf( stdout, "       %s/%s\n", pszFilename, papszFileList[i] );
-                }
-                CSLDestroy( papszFileList );
-                papszFileList = NULL;
-            }
-        }
-
-        CSLDestroy( argv );
-        CSLDestroy( papszExtraMDDomains );
-        CSLDestroy( papszOpenOptions );
-    
-        GDALDumpOpenDatasets( stderr );
-
-        GDALDestroyDriverManager();
-
-        CPLDumpSharedList( NULL );
-
-        exit( 1 );
-    }
-    
-/* -------------------------------------------------------------------- */
-/*      Read specified subdataset if requested.                         */
-/* -------------------------------------------------------------------- */
-    if ( nSubdataset > 0 )
-    {
-        char **papszSubdatasets = GDALGetMetadata( hDataset, "SUBDATASETS" );
-        int nSubdatasets = CSLCount( papszSubdatasets );
-
-        if ( nSubdatasets > 0 && nSubdataset <= nSubdatasets )
-        {
-            char szKeyName[1024];
-            char *pszSubdatasetName;
-
-            snprintf( szKeyName, sizeof(szKeyName),
-                      "SUBDATASET_%d_NAME", nSubdataset );
-            szKeyName[sizeof(szKeyName) - 1] = '\0';
-            pszSubdatasetName =
-                CPLStrdup( CSLFetchNameValue( papszSubdatasets, szKeyName ) );
-            GDALClose( hDataset );
-            hDataset = GDALOpen( pszSubdatasetName, GA_ReadOnly );
-            CPLFree( pszSubdatasetName );
-        }
-        else
-        {
-            fprintf( stderr,
-                     "gdalinfo warning: subdataset %d of %d requested. "
-                     "Reading the main dataset.\n",
-                     nSubdataset, nSubdatasets );
-
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Report general info.                                            */
-/* -------------------------------------------------------------------- */
-    hDriver = GDALGetDatasetDriver( hDataset );
-    if(bJson)
-    {
-        json_object *poDescription = json_object_new_string(GDALGetDescription(hDataset));
-        json_object *poDriverShortName = json_object_new_string(GDALGetDriverShortName(hDriver));
-        json_object *poDriverLongName = json_object_new_string(GDALGetDriverLongName(hDriver));
-        poJsonObject = json_object_new_object();
-        poBands = json_object_new_array();
-        poMetadata = json_object_new_object();
-
-        json_object_object_add(poJsonObject, "description", poDescription);
-        json_object_object_add(poJsonObject, "driverShortName", poDriverShortName);
-        json_object_object_add(poJsonObject, "driverLongName", poDriverLongName);
-    }
-    else
-    {
-        printf( "Driver: %s/%s\n",
-                GDALGetDriverShortName( hDriver ),
-                GDALGetDriverLongName( hDriver ) );
-
-    }
-
-    papszFileList = GDALGetFileList( hDataset );
-
-    if( CSLCount(papszFileList) == 0 )
-    {   
-        if(bJson)
-        {
-            json_object *poFiles = json_object_new_array();   
-            json_object_object_add(poJsonObject, "files", poFiles);
-        }
-        else
-            printf( "Files: none associated\n" );
-    }
-    else
-    {
-        if(bJson)
-        {
-            json_object *poFiles = json_object_new_array();
-
-            for(i = 0; papszFileList[i] != NULL; i++)
-            {
-                json_object *poFile = json_object_new_string(papszFileList[i]);
-                
-                json_object_array_add(poFiles, poFile);
-            }
-            
-            json_object_object_add(poJsonObject, "files", poFiles);
-        }
-        else
-        {
-            printf( "Files: %s\n", papszFileList[0] );
-            if( bShowFileList )
-            {
-                for( i = 1; papszFileList[i] != NULL; i++ )
-                    printf( "       %s\n", papszFileList[i] );
-            }
-        }
-
-    }
-    CSLDestroy( papszFileList );
-
-    if(bJson)
-    {
-        json_object *poSize = json_object_new_array();
-        json_object *poSizeX = json_object_new_int(GDALGetRasterXSize(hDataset));
-        json_object *poSizeY = json_object_new_int(GDALGetRasterYSize(hDataset));
-        
-        json_object_array_add(poSize, poSizeX);
-        json_object_array_add(poSize, poSizeY);
-        json_object_object_add(poJsonObject, "size", poSize);
-    }
-    else
-        printf( "Size is %d, %d\n",
-            GDALGetRasterXSize( hDataset ),
-            GDALGetRasterYSize( hDataset ) );
-
-/* -------------------------------------------------------------------- */
-/*      Report projection.                                              */
-/* -------------------------------------------------------------------- */
-    if( GDALGetProjectionRef( hDataset ) != NULL )
-    {
-        OGRSpatialReferenceH  hSRS;
-        char              *pszProjection;
-        json_object *poCoordinateSystem = NULL;
-
-        if(bJson)
-            poCoordinateSystem = json_object_new_object();
-
-        pszProjection = (char *) GDALGetProjectionRef( hDataset );
-
-        hSRS = OSRNewSpatialReference(NULL);
-        if( OSRImportFromWkt( hSRS, &pszProjection ) == CE_None )
-        {
-            char    *pszPrettyWkt = NULL;
-
-            OSRExportToPrettyWkt( hSRS, &pszPrettyWkt, FALSE );
-            
-            if(bJson)
-            {
-                json_object *poWkt = json_object_new_string(pszPrettyWkt);
-                json_object_object_add(poCoordinateSystem, "wkt", poWkt);
-            }
-            else
-                printf( "Coordinate System is:\n%s\n", pszPrettyWkt );
-            CPLFree( pszPrettyWkt );
-        }
-        else
-        {
-            if(bJson)
-            {
-                json_object *poWkt = json_object_new_string(GDALGetProjectionRef(hDataset));
-                json_object_object_add(poCoordinateSystem, "wkt", poWkt);
-            }
-            else
-                printf( "Coordinate System is `%s'\n",
-                    GDALGetProjectionRef( hDataset ) );
-
-        }
-
-        if ( bReportProj4 )
-        {
-            char *pszProj4 = NULL;
-            OSRExportToProj4( hSRS, &pszProj4 );
-            
-            if(bJson)
-            {
-                json_object *proj4 = json_object_new_string(pszProj4);
-                json_object_object_add(poCoordinateSystem, "proj4", proj4);
-            }
-            else
-                printf("PROJ.4 string is:\n\'%s\'\n",pszProj4);
-            CPLFree( pszProj4 );
-        }
-
-        if(bJson)
-            json_object_object_add(poJsonObject, "coordinateSystem", poCoordinateSystem);
-
-        OSRDestroySpatialReference( hSRS );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Report Geotransform.                                            */
-/* -------------------------------------------------------------------- */
-    if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None )
-    {
-        if(bJson)
-        {
-            json_object *poGeoTransform = json_object_new_array();
-            
-            for(i = 0; i < 6; i++)
-            {
-                json_object *poGeoTransformCoefficient = json_object_new_double_with_precision(adfGeoTransform[i], 16);
-                json_object_array_add(poGeoTransform, poGeoTransformCoefficient);
-            }
-
-            json_object_object_add(poJsonObject, "geoTransform", poGeoTransform);
-        }
-        else
-        {
-            if( adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0 )
-            {
-                CPLprintf( "Origin = (%.15f,%.15f)\n",
-                        adfGeoTransform[0], adfGeoTransform[3] );
-
-                CPLprintf( "Pixel Size = (%.15f,%.15f)\n",
-                        adfGeoTransform[1], adfGeoTransform[5] );
-            }
-            else
-                CPLprintf( "GeoTransform =\n"
-                        "  %.16g, %.16g, %.16g\n"
-                        "  %.16g, %.16g, %.16g\n",
-                        adfGeoTransform[0],
-                        adfGeoTransform[1],
-                        adfGeoTransform[2],
-                        adfGeoTransform[3],
-                        adfGeoTransform[4],
-                        adfGeoTransform[5] );
-        }
-
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Report GCPs.                                                    */
-/* -------------------------------------------------------------------- */
-    if( bShowGCPs && GDALGetGCPCount( hDataset ) > 0 )
-    {
-        json_object *poGCPs = NULL, *poGCPList = NULL;
-
-        if(bJson)
-            poGCPs = json_object_new_object();
-        
-        if (GDALGetGCPProjection(hDataset) != NULL)
-        {
-            json_object *poGCPCoordinateSystem = NULL;
-            OGRSpatialReferenceH  hSRS;
-            char              *pszProjection;
-
-            pszProjection = (char *) GDALGetGCPProjection( hDataset );
-
-            hSRS = OSRNewSpatialReference(NULL);
-            if( OSRImportFromWkt( hSRS, &pszProjection ) == CE_None )
-            {
-                char    *pszPrettyWkt = NULL;
-
-                OSRExportToPrettyWkt( hSRS, &pszPrettyWkt, FALSE );
-                if(bJson)
-                {
-                    json_object *poWkt = json_object_new_string(pszPrettyWkt);
-                    poGCPCoordinateSystem = json_object_new_object();
-                    
-                    json_object_object_add(poGCPCoordinateSystem, "wkt", poWkt);
-                }
-                else
-                    printf( "GCP Projection = \n%s\n", pszPrettyWkt );
-                CPLFree( pszPrettyWkt );
-            }
-            else
-            {
-                if(bJson)
-                {
-                    json_object *poWkt = json_object_new_string(GDALGetGCPProjection(hDataset));
-                    poGCPCoordinateSystem = json_object_new_object();
-                    
-                    json_object_object_add(poGCPCoordinateSystem, "wkt", poWkt);
-                }
-                else
-                    printf( "GCP Projection = %s\n",
-                        GDALGetGCPProjection( hDataset ) );
-
-            }
-
-            if(bJson)
-                json_object_object_add(poGCPs, "coordinateSystem", poGCPCoordinateSystem);
-            OSRDestroySpatialReference( hSRS );
-        }
-
-        if(bJson)
-            poGCPList = json_object_new_array();
-
-        for( i = 0; i < GDALGetGCPCount(hDataset); i++ )
-        {
-            const GDAL_GCP  *psGCP;
-
-            psGCP = GDALGetGCPs( hDataset ) + i;
-            if(bJson)
-            {
-                json_object *poGCP = json_object_new_object();
-                json_object *poId = json_object_new_string(psGCP->pszId);
-                json_object *poInfo = json_object_new_string(psGCP->pszInfo);
-                json_object *poPixel = json_object_new_double_with_precision(psGCP->dfGCPPixel, 15);
-                json_object *poLine = json_object_new_double_with_precision(psGCP->dfGCPLine, 15);
-                json_object *poX = json_object_new_double_with_precision(psGCP->dfGCPX, 15);
-                json_object *poY = json_object_new_double_with_precision(psGCP->dfGCPY, 15);
-                json_object *poZ = json_object_new_double_with_precision(psGCP->dfGCPZ, 15);
-                
-                json_object_object_add(poGCP, "id", poId);
-                json_object_object_add(poGCP, "info", poInfo);
-                json_object_object_add(poGCP, "pixel", poPixel);
-                json_object_object_add(poGCP, "line", poLine);
-                json_object_object_add(poGCP, "x", poX);
-                json_object_object_add(poGCP, "y", poY);
-                json_object_object_add(poGCP, "z", poZ);
-                json_object_array_add(poGCPList, poGCP);
-            }
-            else
-                CPLprintf( "GCP[%3d]: Id=%s, Info=%s\n"
-                    "          (%.15g,%.15g) -> (%.15g,%.15g,%.15g)\n",
-                    i, psGCP->pszId, psGCP->pszInfo,
-                    psGCP->dfGCPPixel, psGCP->dfGCPLine,
-                    psGCP->dfGCPX, psGCP->dfGCPY, psGCP->dfGCPZ );
-        }
-        if(bJson)
-        {
-            json_object_object_add(poGCPs, "gcpList", poGCPList);
-            json_object_object_add(poJsonObject, "gcps", poGCPs);
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Report metadata.                                                */
-/* -------------------------------------------------------------------- */
-
-    GDALInfoReportMetadata( hDataset, bListMDD, bShowMetadata, papszExtraMDDomains, FALSE, bJson, poMetadata );
-    if(bJson && bShowMetadata)
-        json_object_object_add( poJsonObject, "metadata", poMetadata );
-
-/* -------------------------------------------------------------------- */
-/*      Setup projected to lat/long transform if appropriate.           */
-/* -------------------------------------------------------------------- */
-    if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None )
-        pszProjection = GDALGetProjectionRef(hDataset);
-
-    if( pszProjection != NULL && strlen(pszProjection) > 0 )
-    {
-        OGRSpatialReferenceH hProj, hLatLong = NULL, hLatLongWGS84 = NULL;
-
-        hProj = OSRNewSpatialReference( pszProjection );
-        if( hProj != NULL )
-        {
-            hLatLong = OSRCloneGeogCS( hProj );
-
-            if(bJson)
-            {
-                hLatLongWGS84 = OSRNewSpatialReference( NULL );
-                OSRSetWellKnownGeogCS( hLatLongWGS84, "WGS84" );
-            }
-        }
-
-        if( hLatLong != NULL )
-        {
-            CPLPushErrorHandler( CPLQuietErrorHandler );
-            hTransform = OCTNewCoordinateTransformation( hProj, hLatLong );
-            CPLPopErrorHandler();
-            
-            OSRDestroySpatialReference( hLatLong );
-        }
-
-        if( hLatLongWGS84 != NULL )
-        {
-            CPLPushErrorHandler( CPLQuietErrorHandler );
-            hTransformWGS84 = OCTNewCoordinateTransformation( hProj, hLatLongWGS84 );
-            CPLPopErrorHandler();
-            
-            OSRDestroySpatialReference( hLatLongWGS84 );
-        }
-
-        if( hProj != NULL )
-            OSRDestroySpatialReference( hProj );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Report corners.                                                 */
-/* -------------------------------------------------------------------- */
-    if(bJson)
-    {
-        json_object *poLinearRing = json_object_new_array();
-        json_object *poCornerCoordinates = json_object_new_object();
-        json_object *poWGS84Extent = json_object_new_object();
-        json_object *poWGS84ExtentType = json_object_new_string("Polygon");
-        json_object *poWGS84ExtentCoordinates = json_object_new_array();
-
-        GDALInfoReportCorner( hDataset, hTransform, hTransformWGS84, "upperLeft",
-                              0.0, 0.0, bJson, poCornerCoordinates, poWGS84ExtentCoordinates );
-        GDALInfoReportCorner( hDataset, hTransform, hTransformWGS84, "lowerLeft",
-                              0.0, GDALGetRasterYSize(hDataset), bJson, poCornerCoordinates, poWGS84ExtentCoordinates );
-        GDALInfoReportCorner( hDataset, hTransform, hTransformWGS84, "upperRight",
-                              GDALGetRasterXSize(hDataset), 0.0, bJson, poCornerCoordinates, poWGS84ExtentCoordinates );
-        GDALInfoReportCorner( hDataset, hTransform, hTransformWGS84, "lowerRight",
-                              GDALGetRasterXSize(hDataset), GDALGetRasterYSize(hDataset),
-                              bJson, poCornerCoordinates, poWGS84ExtentCoordinates );
-        GDALInfoReportCorner( hDataset, hTransform, hTransformWGS84, "center",
-                              GDALGetRasterXSize(hDataset)/2.0, GDALGetRasterYSize(hDataset)/2.0,
-                              bJson, poCornerCoordinates, poWGS84ExtentCoordinates );
-        GDALInfoReportCorner( hDataset, hTransform, hTransformWGS84, "upperLeft",
-                              0.0, 0.0, bJson, poCornerCoordinates, poWGS84ExtentCoordinates );
-        
-        json_object_object_add( poJsonObject, "cornerCoordinates", poCornerCoordinates );
-        json_object_object_add( poWGS84Extent, "type", poWGS84ExtentType );
-        json_object_array_add( poLinearRing, poWGS84ExtentCoordinates );
-        json_object_object_add( poWGS84Extent, "coordinates", poLinearRing );
-        json_object_object_add( poJsonObject, "wgs84Extent", poWGS84Extent );
-    }
-    else
-    {
-        printf( "Corner Coordinates:\n" );
-        GDALInfoReportCorner( hDataset, hTransform, hTransformWGS84, "Upper Left",
-                              0.0, 0.0, bJson, NULL, NULL );
-        GDALInfoReportCorner( hDataset, hTransform, hTransformWGS84, "Lower Left",
-                              0.0, GDALGetRasterYSize(hDataset), bJson, NULL, NULL );
-        GDALInfoReportCorner( hDataset, hTransform, hTransformWGS84, "Upper Right",
-                              GDALGetRasterXSize(hDataset), 0.0, bJson, NULL, NULL );
-        GDALInfoReportCorner( hDataset, hTransform, hTransformWGS84, "Lower Right",
-                              GDALGetRasterXSize(hDataset),
-                              GDALGetRasterYSize(hDataset), bJson, NULL, NULL );
-        GDALInfoReportCorner( hDataset, hTransform, hTransformWGS84, "Center",
-                              GDALGetRasterXSize(hDataset)/2.0,
-                              GDALGetRasterYSize(hDataset)/2.0, bJson, NULL, NULL );
-
-    }
-
-    if( hTransform != NULL )
-    {
-        OCTDestroyCoordinateTransformation( hTransform );
-        hTransform = NULL;
-    }
-
-    if( hTransformWGS84 != NULL )
-    {
-        OCTDestroyCoordinateTransformation( hTransformWGS84 );
-        hTransformWGS84 = NULL;
-    }
-
-/* ==================================================================== */
-/*      Loop over bands.                                                */
-/* ==================================================================== */
-    for( iBand = 0; iBand < GDALGetRasterCount( hDataset ); iBand++ )
-    {
-        double      dfMin, dfMax, adfCMinMax[2], dfNoData;
-        int         bGotMin, bGotMax, bGotNodata, bSuccess;
-        int         nBlockXSize, nBlockYSize, nMaskFlags;
-        double      dfMean, dfStdDev;
-        GDALColorTableH hTable;
-        CPLErr      eErr;
-        json_object *poBand = NULL, *poBandMetadata = NULL;
-
-        if(bJson)
-        {
-            poBand = json_object_new_object();
-            poBandMetadata = json_object_new_object();
-        }
-
-        hBand = GDALGetRasterBand( hDataset, iBand+1 );
-
-        if( bSample )
-        {
-            float afSample[10000];
-            int   nCount;
-
-            nCount = GDALGetRandomRasterSample( hBand, 10000, afSample );
-            if(!bJson)
-                printf( "Got %d samples.\n", nCount );
-        }
-        
-        GDALGetBlockSize( hBand, &nBlockXSize, &nBlockYSize );
-        if(bJson)
-        {
-            json_object *poBandNumber = json_object_new_int(iBand+1);
-            json_object *poBlock = json_object_new_array();
-            json_object *poType = json_object_new_string(GDALGetDataTypeName(GDALGetRasterDataType(hBand)));
-            json_object *poColorInterp = json_object_new_string(GDALGetColorInterpretationName(
-                GDALGetRasterColorInterpretation(hBand)));
-
-            json_object_array_add(poBlock, json_object_new_int(nBlockXSize));
-            json_object_array_add(poBlock, json_object_new_int(nBlockYSize));
-            json_object_object_add(poBand, "band", poBandNumber);
-            json_object_object_add(poBand, "block", poBlock);
-            json_object_object_add(poBand, "type", poType);
-            json_object_object_add(poBand, "colorInterpretation", poColorInterp);
-        }
-        else
-            printf( "Band %d Block=%dx%d Type=%s, ColorInterp=%s\n", iBand+1,
-                nBlockXSize, nBlockYSize,
-                GDALGetDataTypeName(
-                    GDALGetRasterDataType(hBand)),
-                GDALGetColorInterpretationName(
-                    GDALGetRasterColorInterpretation(hBand)) );
-
-        if( GDALGetDescription( hBand ) != NULL 
-            && strlen(GDALGetDescription( hBand )) > 0 )
-        {
-            if(bJson)
-            {
-                json_object *poBandDescription = json_object_new_string(GDALGetDescription(hBand));
-                json_object_object_add(poBand, "description", poBandDescription);
-            }
-            else
-                printf( "  Description = %s\n", GDALGetDescription(hBand) );
-        }
-
-        dfMin = GDALGetRasterMinimum( hBand, &bGotMin );
-        dfMax = GDALGetRasterMaximum( hBand, &bGotMax );
-        if( bGotMin || bGotMax || bComputeMinMax )
-        {
-            if(!bJson)
-                printf( "  " );
-            if( bGotMin )
-            {
-                if(bJson)
-                {
-                    json_object *poMin = json_object_new_double_with_precision(dfMin, 3);
-                    json_object_object_add(poBand, "min", poMin);
-                }
-                else
-                    CPLprintf( "Min=%.3f ", dfMin );
-            }
-            if( bGotMax )
-            {
-                if(bJson)
-                {
-                    json_object *poMax = json_object_new_double_with_precision(dfMax, 3);
-                    json_object_object_add(poBand, "max", poMax);
-                }
-                else
-                    CPLprintf( "Max=%.3f ", dfMax );
-            }
-
-            if( bComputeMinMax )
-            {
-                CPLErrorReset();
-                GDALComputeRasterMinMax( hBand, FALSE, adfCMinMax );
-                if (CPLGetLastErrorType() == CE_None)
-                {
-                    if(bJson)
-                    {
-                        json_object *poComputedMin = json_object_new_double_with_precision(adfCMinMax[0], 3);
-                        json_object *poComputedMax = json_object_new_double_with_precision(adfCMinMax[1], 3);
-                        json_object_object_add(poBand, "computedMin", poComputedMin);
-                        json_object_object_add(poBand, "computedMax", poComputedMax);
-                    }
-                    else
-                        CPLprintf( "  Computed Min/Max=%.3f,%.3f",
-                          adfCMinMax[0], adfCMinMax[1] );
-                }
-            }
-            if(!bJson)
-                printf( "\n" );
-        }
-
-        eErr = GDALGetRasterStatistics( hBand, bApproxStats, bStats, 
-                                        &dfMin, &dfMax, &dfMean, &dfStdDev );
-        if( eErr == CE_None )
-        {
-            if(bJson)
-            {
-                json_object *poMinimum = json_object_new_double_with_precision(dfMin, 3);
-                json_object *poMaximum = json_object_new_double_with_precision(dfMax, 3);
-                json_object *poMean = json_object_new_double_with_precision(dfMean, 3);
-                json_object *poStdDev = json_object_new_double_with_precision(dfStdDev, 3);
-                
-                json_object_object_add(poBand, "minimum", poMinimum);
-                json_object_object_add(poBand, "maximum", poMaximum);
-                json_object_object_add(poBand, "mean", poMean);
-                json_object_object_add(poBand, "stdDev", poStdDev);
-            }
-            else
-                CPLprintf( "  Minimum=%.3f, Maximum=%.3f, Mean=%.3f, StdDev=%.3f\n",
-                    dfMin, dfMax, dfMean, dfStdDev );
-        }
-
-        if( bReportHistograms )
-        {
-            int nBucketCount;
-            GUIntBig *panHistogram = NULL;
-
-            if(bJson)
-                eErr = GDALGetDefaultHistogramEx( hBand, &dfMin, &dfMax, 
-                                            &nBucketCount, &panHistogram, 
-                                            TRUE, GDALDummyProgress, NULL );
-            else
-                eErr = GDALGetDefaultHistogramEx( hBand, &dfMin, &dfMax, 
-                                            &nBucketCount, &panHistogram, 
-                                            TRUE, GDALTermProgress, NULL );
-            if( eErr == CE_None )
-            {
-                int iBucket;
-                json_object *poHistogram = NULL, *poBuckets = NULL;
-
-                if(bJson)
-                {
-                    json_object *poCount = json_object_new_int(nBucketCount);
-                    json_object *poMin = json_object_new_double(dfMin);
-                    json_object *poMax = json_object_new_double(dfMax);
-                    
-                    poBuckets = json_object_new_array();
-                    poHistogram = json_object_new_object();
-                    json_object_object_add(poHistogram, "count", poCount);
-                    json_object_object_add(poHistogram, "min", poMin);
-                    json_object_object_add(poHistogram, "max", poMax);
-                }
-                else
-                    printf( "  %d buckets from %g to %g:\n  ",
-                        nBucketCount, dfMin, dfMax );
-
-                for( iBucket = 0; iBucket < nBucketCount; iBucket++ )
-                {
-                    if(bJson)
-                    {
-                        json_object *poBucket = json_object_new_int64(panHistogram[iBucket]);
-                        json_object_array_add(poBuckets, poBucket);
-                    }
-                    else
-                        printf( CPL_FRMT_GUIB " ", panHistogram[iBucket] );
-                }
-                if(bJson)
-                {
-                    json_object_object_add(poHistogram, "buckets", poBuckets);
-                    json_object_object_add(poBand, "histogram", poHistogram);
-                }
-                else
-                    printf( "\n" );
-                CPLFree( panHistogram );
-            }
-        }
-
-        if ( bComputeChecksum)
-        {
-            int nBandChecksum = GDALChecksumImage(hBand, 0, 0,
-                                      GDALGetRasterXSize(hDataset),
-                                      GDALGetRasterYSize(hDataset));
-            if(bJson)
-            {
-                json_object *poChecksum = json_object_new_int(nBandChecksum);
-                json_object_object_add(poBand, "checksum", poChecksum);
-            }
-            else
-                printf( "  Checksum=%d\n", nBandChecksum );
-        }
-
-        dfNoData = GDALGetRasterNoDataValue( hBand, &bGotNodata );
-        if( bGotNodata )
-        {
-            if (CPLIsNan(dfNoData))
-            {
-                if(bJson)
-                {
-                    json_object *poNoDataValue = json_object_new_string("nan");
-                    json_object_object_add(poBand, "noDataValue", poNoDataValue);
-                }
-                else
-                    printf( "  NoData Value=nan\n" );
-            }
-            else
-            {
-                if(bJson)
-                {
-                    json_object *poNoDataValue = json_object_new_double_with_precision(dfNoData, 18);
-                    json_object_object_add(poBand, "noDataValue", poNoDataValue);
-                }
-                else
-                    CPLprintf( "  NoData Value=%.18g\n", dfNoData );
-            }
-        }
-
-        if( GDALGetOverviewCount(hBand) > 0 )
-        {
-            int     iOverview;
-            json_object *poOverviews = NULL;
-            
-            if(bJson)
-                poOverviews = json_object_new_array();
-            else
-                printf( "  Overviews: " );
-
-            for( iOverview = 0; 
-                 iOverview < GDALGetOverviewCount(hBand);
-                 iOverview++ )
-            {
-                GDALRasterBandH hOverview;
-                const char *pszResampling = NULL;
-                json_object *poOverview;
-
-                if(!bJson)
-                    if( iOverview != 0 )
-                        printf( ", " );
-
-                hOverview = GDALGetOverview( hBand, iOverview );
-                if (hOverview != NULL)
-                {
-                    if(bJson)
-                    {
-                        json_object *poOverviewSize = json_object_new_array();
-                        json_object *poOverviewSizeX = json_object_new_int( GDALGetRasterBandXSize( hOverview) );
-                        json_object *poOverviewSizeY = json_object_new_int( GDALGetRasterBandYSize( hOverview) );
-                        
-                        poOverview = json_object_new_object();
-                        json_object_array_add( poOverviewSize, poOverviewSizeX );
-                        json_object_array_add( poOverviewSize, poOverviewSizeY );
-                        json_object_object_add( poOverview, "size", poOverviewSize );
-
-                        if(bComputeChecksum)
-                        {
-                            int nOverviewChecksum = GDALChecksumImage(hOverview, 0, 0,
-                                        GDALGetRasterBandXSize(hOverview),
-                                        GDALGetRasterBandYSize(hOverview));
-                            json_object *poOverviewChecksum = json_object_new_int(nOverviewChecksum);
-                            json_object_object_add(poOverview, "checksum", poOverviewChecksum);
-                        }
-                        json_object_array_add(poOverviews, poOverview);
-                    }
-                    else
-                        printf( "%dx%d", 
-                            GDALGetRasterBandXSize( hOverview ),
-                            GDALGetRasterBandYSize( hOverview ) );
-
-                    pszResampling = 
-                        GDALGetMetadataItem( hOverview, "RESAMPLING", "" );
-
-                    if( pszResampling != NULL && !bJson 
-                        && EQUALN(pszResampling,"AVERAGE_BIT2",12) )
-                        printf( "*" );
-                }
-                else
-                    if(!bJson)
-                        printf( "(null)" );
-            }
-            if(bJson)
-                json_object_object_add(poBand, "overviews", poOverviews);
-            else
-                printf( "\n" );
-
-            if ( bComputeChecksum && !bJson )
-            {
-                printf( "  Overviews checksum: " );
-                
-                for( iOverview = 0; 
-                    iOverview < GDALGetOverviewCount(hBand);
-                    iOverview++ )
-                {
-                    GDALRasterBandH hOverview;
-
-                    if( iOverview != 0 )
-                        printf( ", " );
-
-                    hOverview = GDALGetOverview( hBand, iOverview );
-                    if (hOverview)
-                    {
-                        printf( "%d",
-                                GDALChecksumImage(hOverview, 0, 0,
-                                        GDALGetRasterBandXSize(hOverview),
-                                        GDALGetRasterBandYSize(hOverview)));
-                    }
-                    else
-                    {
-                        printf( "(null)" );
-                    }
-                }
-                printf( "\n" );
-            }
-        }
-
-        if( GDALHasArbitraryOverviews( hBand ) && !bJson )
-        {
-            printf( "  Overviews: arbitrary\n" );
-        }
-        
-        nMaskFlags = GDALGetMaskFlags( hBand );
-        if( (nMaskFlags & (GMF_NODATA|GMF_ALL_VALID)) == 0 )
-        {
-            GDALRasterBandH hMaskBand = GDALGetMaskBand(hBand) ;
-            json_object *poMask = NULL, *poFlags = NULL, *poMaskOverviews = NULL;
-
-            if(bJson)
-            {
-                poMask = json_object_new_object();
-                poFlags = json_object_new_array(); 
-            }
-            else
-                printf( "  Mask Flags: " );
-            if( nMaskFlags & GMF_PER_DATASET )
-            {
-                if(bJson)
-                {
-                    json_object *poFlag = json_object_new_string( "PER_DATASET" );
-                    json_object_array_add( poFlags, poFlag );
-                }
-                else
-                    printf( "PER_DATASET " );
-            }
-            if( nMaskFlags & GMF_ALPHA )
-            {
-                if(bJson)
-                {
-                    json_object *poFlag = json_object_new_string( "ALPHA" );
-                    json_object_array_add( poFlags, poFlag );
-                }
-                else
-                    printf( "ALPHA " );
-            }
-            if( nMaskFlags & GMF_NODATA )
-            {
-                if(bJson)
-                {
-                    json_object *poFlag = json_object_new_string( "NODATA" );
-                    json_object_array_add( poFlags, poFlag );
-                }
-                else
-                    printf( "NODATA " );
-            }
-            if( nMaskFlags & GMF_ALL_VALID )
-            {
-                if(bJson)
-                {
-                    json_object *poFlag = json_object_new_string( "ALL_VALID" );
-                    json_object_array_add( poFlags, poFlag );
-                }
-                else
-                    printf( "ALL_VALID " );
-            }
-            if(bJson)
-                json_object_object_add( poMask, "flags", poFlags );
-            else
-                printf( "\n" );
-
-            if(bJson)
-                poMaskOverviews = json_object_new_array();
-
-            if( hMaskBand != NULL &&
-                GDALGetOverviewCount(hMaskBand) > 0 )
-            {
-                int     iOverview;
-                
-                if(!bJson)
-                    printf( "  Overviews of mask band: " );
-                
-                for( iOverview = 0; 
-                     iOverview < GDALGetOverviewCount(hMaskBand);
-                     iOverview++ )
-                {
-                    GDALRasterBandH hOverview;
-                    json_object *poMaskOverviewSizeX, *poMaskOverviewSizeY,
-                                *poMaskOverview = NULL, *poMaskOverviewSize = NULL;
-
-                    if(bJson)
-                    {
-                        poMaskOverview = json_object_new_object();
-                        poMaskOverviewSize = json_object_new_array();
-                    }
-                    else
-                    {
-                        if( iOverview != 0 )
-                            printf( ", " );
-                    }
-
-                    hOverview = GDALGetOverview( hMaskBand, iOverview );
-                    if(bJson)
-                    {
-                        poMaskOverviewSizeX = json_object_new_int(GDALGetRasterBandXSize(hOverview));
-                        poMaskOverviewSizeY = json_object_new_int(GDALGetRasterBandYSize(hOverview));
-
-                        json_object_array_add(poMaskOverviewSize, poMaskOverviewSizeX);
-                        json_object_array_add(poMaskOverviewSize, poMaskOverviewSizeY);
-                        json_object_object_add(poMaskOverview, "size", poMaskOverviewSize);
-                        json_object_array_add(poMaskOverviews, poMaskOverview);
-                    }
-                    else
-                        printf( "%dx%d", 
-                            GDALGetRasterBandXSize( hOverview ),
-                            GDALGetRasterBandYSize( hOverview ) );
-                }
-                if(!bJson)
-                    printf( "\n" );
-            }
-            if(bJson)
-            {
-                json_object_object_add(poMask, "overviews", poMaskOverviews);
-                json_object_object_add(poBand, "mask", poMask);
-            }    
-        }
-
-        if( strlen(GDALGetRasterUnitType(hBand)) > 0 )
-        {
-            if(bJson)
-            {
-                json_object *poUnit = json_object_new_string(GDALGetRasterUnitType(hBand));
-                json_object_object_add(poBand, "unit", poUnit);
-            }
-            else
-                printf( "  Unit Type: %s\n", GDALGetRasterUnitType(hBand) );
-        }
-
-        if( GDALGetRasterCategoryNames(hBand) != NULL )
-        {
-            char **papszCategories = GDALGetRasterCategoryNames(hBand);
-            int i;
-            json_object *poCategories = NULL;
-
-            if(bJson)
-                poCategories = json_object_new_array();           
-            else
-                printf( "  Categories:\n" );
-                
-            for( i = 0; papszCategories[i] != NULL; i++ )
-            {
-                if(bJson)
-                {
-                    json_object *poCategoryName = json_object_new_string(papszCategories[i]);
-                    json_object_array_add(poCategories, poCategoryName);
-                }
-                else
-                    printf( "    %3d: %s\n", i, papszCategories[i] );
-            }
-            if(bJson)
-                json_object_object_add(poBand, "categories", poCategories);
-        }
-
-        if( GDALGetRasterScale( hBand, &bSuccess ) != 1.0 
-            || GDALGetRasterOffset( hBand, &bSuccess ) != 0.0 )
-        {
-            if(bJson)
-            {
-                json_object *poOffset = json_object_new_double_with_precision(GDALGetRasterOffset(hBand, &bSuccess), 15);
-                json_object *poScale = json_object_new_double_with_precision(GDALGetRasterScale(hBand, &bSuccess), 15);
-                json_object_object_add(poBand, "offset", poOffset);
-                json_object_object_add(poBand, "scale", poScale);
-            }
-            else
-                CPLprintf( "  Offset: %.15g,   Scale:%.15g\n",
-                    GDALGetRasterOffset( hBand, &bSuccess ),
-                    GDALGetRasterScale( hBand, &bSuccess ) );
-        }
-        
-        GDALInfoReportMetadata( hBand, bListMDD, bShowMetadata, papszExtraMDDomains, TRUE, bJson, poBandMetadata );
-        if(bJson && bShowMetadata)  
-            json_object_object_add( poBand, "metadata", poBandMetadata );
-
-        if( GDALGetRasterColorInterpretation(hBand) == GCI_PaletteIndex 
-            && (hTable = GDALGetRasterColorTable( hBand )) != NULL )
-        {
-            int         i;
-            json_object *poColorTable = NULL;
-            
-            if(bJson)
-            {
-                json_object *poPalette = json_object_new_string(GDALGetPaletteInterpretationName(
-                    GDALGetPaletteInterpretation(hTable)));
-                json_object *poCount = json_object_new_int(GDALGetColorEntryCount(hTable));
-                poColorTable = json_object_new_object();
-
-                json_object_object_add(poColorTable, "palette", poPalette);
-                json_object_object_add(poColorTable, "count", poCount);
-            }
-            else
-                printf( "  Color Table (%s with %d entries)\n",
-                    GDALGetPaletteInterpretationName(
-                        GDALGetPaletteInterpretation( hTable )), 
-                    GDALGetColorEntryCount( hTable ) );
-
-            if (bShowColorTable)
-            {
-                json_object *poEntries = NULL;
-                
-                if(bJson)
-                    poEntries = json_object_new_array();
-
-                for( i = 0; i < GDALGetColorEntryCount( hTable ); i++ )
-                {
-                    GDALColorEntry  sEntry;
-    
-                    GDALGetColorEntryAsRGB( hTable, i, &sEntry );
-
-                    if(bJson)
-                    {
-                        json_object *poEntry = json_object_new_array();
-                        json_object *poC1 = json_object_new_int(sEntry.c1);
-                        json_object *poC2 = json_object_new_int(sEntry.c2);
-                        json_object *poC3 = json_object_new_int(sEntry.c3);
-                        json_object *poC4 = json_object_new_int(sEntry.c4);
-                        
-                        json_object_array_add(poEntry, poC1);
-                        json_object_array_add(poEntry, poC2);
-                        json_object_array_add(poEntry, poC3);
-                        json_object_array_add(poEntry, poC4);
-                        json_object_array_add(poEntries, poEntry);
-                    }
-                    else
-                        printf( "  %3d: %d,%d,%d,%d\n",
-                            i,
-                            sEntry.c1,
-                            sEntry.c2,
-                            sEntry.c3,
-                            sEntry.c4 );
-                }
-                if(bJson)
-                {
-                    json_object_object_add(poColorTable, "entries", poEntries);
-                    json_object_object_add(poBand, "colorTable", poColorTable);
-                }
-            }   
-        }
-
-        if( bShowRAT && GDALGetDefaultRAT( hBand ) != NULL )
-        {
-            GDALRasterAttributeTableH hRAT = GDALGetDefaultRAT( hBand );
-            
-            if(bJson)
-            {
-                json_object *poRAT = (json_object*) GDALRATSerializeJSON( hRAT );
-                json_object_object_add( poJsonObject, "rat", poRAT );
-            }
-            else
-            {
-                GDALRATDumpReadable( hRAT, NULL );
-            }
-        }
-        if(bJson)
-            json_object_array_add(poBands, poBand);
-    }
-
-    if(bJson)
-    {
-        json_object_object_add(poJsonObject, "bands", poBands);
-        printf("%s\n", json_object_to_json_string_ext(poJsonObject, JSON_C_TO_STRING_PRETTY));
-        json_object_put(poJsonObject);
-    }
-    
-    GDALClose( hDataset );
-    
-    CSLDestroy( papszExtraMDDomains );
-    CSLDestroy( papszOpenOptions );
-    CSLDestroy( argv );
-    
-    GDALDumpOpenDatasets( stderr );
-
-    GDALDestroyDriverManager();
-
-    CPLDumpSharedList( NULL );
-    CPLCleanupTLS();
-
-    exit( 0 );
-}
-
-/************************************************************************/
-/*                        GDALInfoReportCorner()                        */
-/************************************************************************/
-
-static int 
-GDALInfoReportCorner( GDALDatasetH hDataset, 
-                      OGRCoordinateTransformationH hTransform, OGRCoordinateTransformationH hTransformWGS84,
-                      const char * corner_name,
-                      double x, double y,
-                      int bJson, json_object *poCornerCoordinates, json_object *poWGS84ExtentCoordinates )
-
-{
-    double  dfGeoX, dfGeoY;
-    double  adfGeoTransform[6];
-    json_object *poCorner, *poX, *poY;
-
-    if(!bJson)
-        printf( "%-11s ", corner_name );
-
-/* -------------------------------------------------------------------- */
-/*      Transform the point into georeferenced coordinates.             */
-/* -------------------------------------------------------------------- */
-    if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None )
-    {
-        dfGeoX = adfGeoTransform[0] + adfGeoTransform[1] * x
-            + adfGeoTransform[2] * y;
-        dfGeoY = adfGeoTransform[3] + adfGeoTransform[4] * x
-            + adfGeoTransform[5] * y;
-    }
-
-    else
-    {
-        if( bJson )
-        {
-            poCorner = json_object_new_array();
-            poX = json_object_new_double_with_precision( x, 1 );
-            poY = json_object_new_double_with_precision( y, 1 );
-            json_object_array_add( poCorner, poX );
-            json_object_array_add( poCorner, poY );
-            json_object_object_add( poCornerCoordinates, corner_name, poCorner );
-        }
-        else
-            CPLprintf( "(%7.1f,%7.1f)\n", x, y );
-        return FALSE;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Report the georeferenced coordinates.                           */
-/* -------------------------------------------------------------------- */
-    if( ABS(dfGeoX) < 181 && ABS(dfGeoY) < 91 )
-    {
-        if(bJson)
-        {
-            poCorner = json_object_new_array();
-            poX = json_object_new_double_with_precision( dfGeoX, 7 );
-            poY = json_object_new_double_with_precision( dfGeoY, 7 );
-            json_object_array_add( poCorner, poX );
-            json_object_array_add( poCorner, poY );
-            json_object_object_add( poCornerCoordinates, corner_name, poCorner );
-        }
-        else
-            CPLprintf( "(%12.7f,%12.7f) ", dfGeoX, dfGeoY );
-    }
-    else
-    {
-        if(bJson)
-        {
-            poCorner = json_object_new_array();
-            poX = json_object_new_double_with_precision( dfGeoX, 3 );
-            poY = json_object_new_double_with_precision( dfGeoY, 3 );
-            json_object_array_add( poCorner, poX );
-            json_object_array_add( poCorner, poY );
-            json_object_object_add( poCornerCoordinates, corner_name, poCorner );
-        }
-        else
-            CPLprintf( "(%12.3f,%12.3f) ", dfGeoX, dfGeoY );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Transform to latlong and report.                                */
-/* -------------------------------------------------------------------- */
-    if(bJson)
-    {
-        double dfZ = 0.0;
-        if( hTransformWGS84 != NULL && !EQUAL( corner_name, "center" ) 
-        && OCTTransform(hTransformWGS84,1,&dfGeoX,&dfGeoY,&dfZ) )
-        {
-            poCorner = json_object_new_array();
-            poX = json_object_new_double_with_precision( dfGeoX, 7 );
-            poY = json_object_new_double_with_precision( dfGeoY, 7 );
-            json_object_array_add( poCorner, poX );
-            json_object_array_add( poCorner, poY );
-            json_object_array_add( poWGS84ExtentCoordinates , poCorner );
-        }
-    }
-    else
-    {
-        double dfZ = 0.0;
-        if( hTransform != NULL 
-        && OCTTransform(hTransform,1,&dfGeoX,&dfGeoY,&dfZ) )
-        {
-            printf( "(%s,", GDALDecToDMS( dfGeoX, "Long", 2 ) );
-            printf( "%s)", GDALDecToDMS( dfGeoY, "Lat", 2 ) );
-        }
-        printf( "\n" );
-    }
-    
-    return TRUE;
-}
-
-
-/************************************************************************/
-/*                       GDALInfoPrintMetadata()                        */
-/************************************************************************/
-static void GDALInfoPrintMetadata( GDALMajorObjectH hObject,
-                                   const char *pszDomain,
-                                   const char *pszDisplayedname,
-                                   const char *pszIndent,
-                                   int bJson,
-                                   json_object *poMetadata )
-{
-    int i;
-    char **papszMetadata;
-    int bIsxml = FALSE;
-    char *pszKey = NULL;
-    const char *pszValue;
-    json_object *poDomain = NULL, *poValue = NULL;
-
-    if (pszDomain != NULL && EQUALN(pszDomain, "xml:", 4))
-        bIsxml = TRUE;
-
-    papszMetadata = GDALGetMetadata( hObject, pszDomain );
-    if( CSLCount(papszMetadata) > 0 )
-    {
-        if(bJson && !bIsxml)
-            poDomain = json_object_new_object();
-        
-        if(!bJson)
-            printf( "%s%s:\n", pszIndent, pszDisplayedname );
-        
-        for( i = 0; papszMetadata[i] != NULL; i++ )
-        {
-            if(bJson)
-            {
-                if(bIsxml)
-                {
-                    poValue = json_object_new_string( papszMetadata[i] );
-                    break;
-                }
-                else
-                {
-                    pszKey = NULL;
-                    pszValue = CPLParseNameValue( papszMetadata[i], &pszKey );
-                    if( pszKey )
-                    {
-                        poValue = json_object_new_string( pszValue );
-                        json_object_object_add( poDomain, pszKey, poValue );
-                        CPLFree( pszKey );
-                    }
-                }
-            }
-            else
-            {
-                if (bIsxml)
-                    printf( "%s%s\n", pszIndent, papszMetadata[i] );
-                else
-                    printf( "%s  %s\n", pszIndent, papszMetadata[i] );
-            
-            }
-        }
-        if(bJson)
-        {
-            if(bIsxml)
-                json_object_object_add( poMetadata, pszDomain, poValue );
-            else
-            {
-                if(pszDomain == NULL)
-                    json_object_object_add( poMetadata, "", poDomain );
-                else
-                    json_object_object_add( poMetadata, pszDomain, poDomain );
-            }
-        }
-    }
-    
-}
-
-/************************************************************************/
-/*                       GDALInfoReportMetadata()                       */
-/************************************************************************/
-static void GDALInfoReportMetadata( GDALMajorObjectH hObject,
-                                    int bListMDD,
-                                    int bShowMetadata,
-                                    char **papszExtraMDDomains,
-                                    int bIsBand,
-                                    int bJson,
-                                    json_object *poMetadata )
-{
-    const char* pszIndent = "";
-    if( bIsBand )
-        pszIndent = "  ";
-
-    /* -------------------------------------------------------------------- */
-    /*      Report list of Metadata domains                                 */
-    /* -------------------------------------------------------------------- */
-    if( bListMDD )
-    {
-        char** papszMDDList = GDALGetMetadataDomainList( hObject );
-        char** papszIter = papszMDDList;
-        json_object *poMDD = NULL;
-        json_object *poListMDD = NULL;
-        if( bJson )
-            poListMDD = json_object_new_array();
-
-        if( papszMDDList != NULL )
-        {
-            if(!bJson)
-                printf( "%sMetadata domains:\n", pszIndent );
-        }
-        
-        while( papszIter != NULL && *papszIter != NULL )
-        {
-            if( EQUAL(*papszIter, "") )
-            {
-                if(bJson)
-                    poMDD = json_object_new_string( *papszIter );
-                else
-                    printf( "%s  (default)\n", pszIndent);
-            }
-            else
-            {
-                if(bJson)
-                    poMDD = json_object_new_string( *papszIter );
-                else
-                    printf( "%s  %s\n", pszIndent, *papszIter );
-            }
-            if(bJson)
-                json_object_array_add( poListMDD, poMDD );
-            papszIter ++;
-        }
-        if(bJson)
-            json_object_object_add( poMetadata, "metadataDomains", poListMDD );
-        CSLDestroy(papszMDDList);
-    }
-
-    if (!bShowMetadata)
-        return;
-
-    /* -------------------------------------------------------------------- */
-    /*      Report default Metadata domain.                                 */
-    /* -------------------------------------------------------------------- */
-    GDALInfoPrintMetadata( hObject, NULL, "Metadata", pszIndent, bJson, poMetadata );
-
-    /* -------------------------------------------------------------------- */
-    /*      Report extra Metadata domains                                   */
-    /* -------------------------------------------------------------------- */
-    if (papszExtraMDDomains != NULL) {
-        char **papszExtraMDDomainsExpanded = NULL;
-        int iMDD;
-
-        if( EQUAL(papszExtraMDDomains[0], "all") &&
-            papszExtraMDDomains[1] == NULL )
-        {
-            char** papszMDDList = GDALGetMetadataDomainList( hObject );
-            char** papszIter = papszMDDList;
-
-            while( papszIter != NULL && *papszIter != NULL )
-            {
-                if( !EQUAL(*papszIter, "") &&
-                    !EQUAL(*papszIter, "IMAGE_STRUCTURE") &&
-                    !EQUAL(*papszIter, "SUBDATASETS") &&
-                    !EQUAL(*papszIter, "GEOLOCATION") &&
-                    !EQUAL(*papszIter, "RPC") )
-                {
-                    papszExtraMDDomainsExpanded = CSLAddString(papszExtraMDDomainsExpanded, *papszIter);
-                }
-                papszIter ++;
-            }
-            CSLDestroy(papszMDDList);
-        }
-        else
-        {
-            papszExtraMDDomainsExpanded = CSLDuplicate(papszExtraMDDomains);
-        }
-
-        for( iMDD = 0; iMDD < CSLCount(papszExtraMDDomainsExpanded); iMDD++ )
-        {
-            char pszDisplayedname[256];
-            snprintf(pszDisplayedname, 256, "Metadata (%s)", papszExtraMDDomainsExpanded[iMDD]);
-            if(bJson)
-                GDALInfoPrintMetadata( hObject, papszExtraMDDomainsExpanded[iMDD], papszExtraMDDomainsExpanded[iMDD], pszIndent, bJson, poMetadata );
-            else
-                GDALInfoPrintMetadata( hObject, papszExtraMDDomainsExpanded[iMDD], pszDisplayedname, pszIndent, bJson, poMetadata );
-        }
-
-        CSLDestroy(papszExtraMDDomainsExpanded);
-    }
-
-    /* -------------------------------------------------------------------- */
-    /*      Report various named metadata domains.                          */
-    /* -------------------------------------------------------------------- */
-    GDALInfoPrintMetadata( hObject, "IMAGE_STRUCTURE", "Image Structure Metadata", pszIndent, bJson, poMetadata );
-
-    if (!bIsBand)
-    {
-        GDALInfoPrintMetadata( hObject, "SUBDATASETS", "Subdatasets", pszIndent, bJson, poMetadata );
-        GDALInfoPrintMetadata( hObject, "GEOLOCATION", "Geolocation", pszIndent, bJson, poMetadata );
-        GDALInfoPrintMetadata( hObject, "RPC", "RPC Metadata", pszIndent, bJson, poMetadata );
-    }
-
-}
diff --git a/apps/gdalinfo_bin.cpp b/apps/gdalinfo_bin.cpp
new file mode 100644
index 0000000..66e06ab
--- /dev/null
+++ b/apps/gdalinfo_bin.cpp
@@ -0,0 +1,241 @@
+/******************************************************************************
+ * $Id: gdalinfo_bin.cpp 33758 2016-03-21 09:06:22Z rouault $
+ *
+ * Project:  GDAL Utilities
+ * Purpose:  Command line application to list info about a file.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ * ****************************************************************************
+ * Copyright (c) 1998, Frank Warmerdam
+ * Copyright (c) 2007-2015, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gdal.h"
+#include "cpl_string.h"
+#include "cpl_multiproc.h"
+#include "commonutils.h"
+#include "gdal_utils_priv.h"
+
+CPL_CVSID("$Id: gdalinfo_bin.cpp 33758 2016-03-21 09:06:22Z rouault $");
+
+/************************************************************************/
+/*                               Usage()                                */
+/************************************************************************/
+
+static void Usage(const char* pszErrorMsg = NULL)
+
+{
+    printf( "Usage: gdalinfo [--help-general] [-json] [-mm] [-stats] [-hist] [-nogcp] [-nomd]\n"
+            "                [-norat] [-noct] [-nofl] [-checksum] [-proj4]\n"
+            "                [-listmdd] [-mdd domain|`all`]*\n"
+            "                [-sd subdataset] [-oo NAME=VALUE]* datasetname\n" );
+
+    if( pszErrorMsg != NULL )
+        fprintf(stderr, "\nFAILURE: %s\n", pszErrorMsg);
+
+    exit( 1 );
+}
+
+
+/************************************************************************/
+/*                         GDALInfoOptionsForBinary()                   */
+/************************************************************************/
+
+static GDALInfoOptionsForBinary *GDALInfoOptionsForBinaryNew(void)
+{
+    return (GDALInfoOptionsForBinary*) CPLCalloc(  1, sizeof(GDALInfoOptionsForBinary) );
+}
+
+/************************************************************************/
+/*                       GDALInfoOptionsForBinaryFree()                 */
+/************************************************************************/
+
+static void GDALInfoOptionsForBinaryFree( GDALInfoOptionsForBinary* psOptionsForBinary )
+{
+    if( psOptionsForBinary )
+    {
+        CPLFree(psOptionsForBinary->pszFilename);
+        CSLDestroy(psOptionsForBinary->papszOpenOptions);
+        CPLFree(psOptionsForBinary);
+    }
+}
+
+/************************************************************************/
+/*                                main()                                */
+/************************************************************************/
+
+int main( int argc, char ** argv )
+
+{
+    EarlySetConfigOptions(argc, argv);
+
+    GDALAllRegister();
+
+    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
+    if( argc < 1 )
+        exit( -argc );
+
+    for( int i = 0; argv != NULL && argv[i] != NULL; i++ )
+    {
+        if( EQUAL(argv[i], "--utility_version") )
+        {
+            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
+                   argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
+            CSLDestroy( argv );
+            return 0;
+        }
+        else if( EQUAL(argv[i],"--help") )
+        {
+            Usage();
+        }
+    }
+    argv = CSLAddString(argv, "-stdout");
+
+    GDALInfoOptionsForBinary* psOptionsForBinary = GDALInfoOptionsForBinaryNew();
+
+    GDALInfoOptions *psOptions
+        = GDALInfoOptionsNew(argv + 1, psOptionsForBinary);
+    if( psOptions == NULL )
+        Usage();
+
+    if( psOptionsForBinary->pszFilename == NULL )
+        Usage("No datasource specified.");
+
+/* -------------------------------------------------------------------- */
+/*      Open dataset.                                                   */
+/* -------------------------------------------------------------------- */
+#ifdef __AFL_HAVE_MANUAL_CONTROL
+    int iIter = 0;
+    while (__AFL_LOOP(1000)) {
+        iIter ++;
+#endif
+
+    GDALDatasetH hDataset
+        = GDALOpenEx( psOptionsForBinary->pszFilename, GDAL_OF_READONLY | GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR, NULL,
+                      (const char* const* )psOptionsForBinary->papszOpenOptions, NULL );
+
+    if( hDataset == NULL )
+    {
+#ifdef __AFL_HAVE_MANUAL_CONTROL
+        continue;
+#else
+        fprintf( stderr,
+                 "gdalinfo failed - unable to open '%s'.\n",
+                 psOptionsForBinary->pszFilename );
+
+/* -------------------------------------------------------------------- */
+/*      If argument is a VSIFILE, then print its contents               */
+/* -------------------------------------------------------------------- */
+        if ( STARTS_WITH(psOptionsForBinary->pszFilename, "/vsizip/") ||
+             STARTS_WITH(psOptionsForBinary->pszFilename, "/vsitar/") )
+        {
+            char** papszFileList = VSIReadDirRecursive( psOptionsForBinary->pszFilename );
+            if ( papszFileList )
+            {
+                int nCount = CSLCount( papszFileList );
+                fprintf( stdout,
+                         "Unable to open source `%s' directly.\n"
+                         "The archive contains %d files:\n",
+                         psOptionsForBinary->pszFilename, nCount );
+                for ( int i = 0; i < nCount; i++ )
+                {
+                    fprintf( stdout, "       %s/%s\n", psOptionsForBinary->pszFilename, papszFileList[i] );
+                }
+                CSLDestroy( papszFileList );
+            }
+        }
+
+        CSLDestroy( argv );
+
+        GDALInfoOptionsForBinaryFree(psOptionsForBinary);
+
+        GDALInfoOptionsFree( psOptions );
+
+        GDALDumpOpenDatasets( stderr );
+
+        GDALDestroyDriverManager();
+
+        CPLDumpSharedList( NULL );
+
+        exit( 1 );
+#endif
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Read specified subdataset if requested.                         */
+/* -------------------------------------------------------------------- */
+    if ( psOptionsForBinary->nSubdataset > 0 )
+    {
+        char **papszSubdatasets = GDALGetMetadata( hDataset, "SUBDATASETS" );
+        int nSubdatasets = CSLCount( papszSubdatasets );
+
+        if ( nSubdatasets > 0 && psOptionsForBinary->nSubdataset <= nSubdatasets )
+        {
+            char szKeyName[1024];
+            char *pszSubdatasetName;
+
+            snprintf( szKeyName, sizeof(szKeyName),
+                      "SUBDATASET_%d_NAME", psOptionsForBinary->nSubdataset );
+            szKeyName[sizeof(szKeyName) - 1] = '\0';
+            pszSubdatasetName =
+                CPLStrdup( CSLFetchNameValue( papszSubdatasets, szKeyName ) );
+            GDALClose( hDataset );
+            hDataset = GDALOpen( pszSubdatasetName, GA_ReadOnly );
+            CPLFree( pszSubdatasetName );
+        }
+        else
+        {
+            fprintf( stderr,
+                     "gdalinfo warning: subdataset %d of %d requested. "
+                     "Reading the main dataset.\n",
+                     psOptionsForBinary->nSubdataset, nSubdatasets );
+
+        }
+    }
+
+    char* pszGDALInfoOutput = GDALInfo( hDataset, psOptions );
+
+    if( pszGDALInfoOutput )
+        printf( "%s", pszGDALInfoOutput );
+
+    CPLFree( pszGDALInfoOutput );
+
+    GDALClose( hDataset );
+#ifdef __AFL_HAVE_MANUAL_CONTROL
+    }
+#endif
+
+    GDALInfoOptionsForBinaryFree(psOptionsForBinary);
+
+    GDALInfoOptionsFree( psOptions );
+
+    CSLDestroy( argv );
+
+    GDALDumpOpenDatasets( stderr );
+
+    GDALDestroyDriverManager();
+
+    CPLDumpSharedList( NULL );
+    CPLCleanupTLS();
+
+    exit( 0 );
+
+}
diff --git a/apps/gdalinfo_lib.cpp b/apps/gdalinfo_lib.cpp
new file mode 100644
index 0000000..19c5866
--- /dev/null
+++ b/apps/gdalinfo_lib.cpp
@@ -0,0 +1,1705 @@
+/******************************************************************************
+ * $Id: gdalinfo_lib.cpp 33615 2016-03-02 20:19:22Z goatbar $
+ *
+ * Project:  GDAL Utilities
+ * Purpose:  Command line application to list info about a file.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ * ****************************************************************************
+ * Copyright (c) 1998, Frank Warmerdam
+ * Copyright (c) 2007-2015, Even Rouault <even.rouault at spatialys.com>
+ * Copyright (c) 2015, Faza Mahamood
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include <vector>
+
+#include "gdal.h"
+#include "gdal_alg.h"
+#include "ogr_srs_api.h"
+#include "cpl_string.h"
+#include "cpl_conv.h"
+#include "commonutils.h"
+#include "json.h"
+#include "ogrgeojsonwriter.h"
+#include "gdal_utils_priv.h"
+#include "gdal_priv.h"
+#include "gdal_rat.h"
+
+using std::vector;
+
+CPL_CVSID("$Id: gdalinfo_lib.cpp 33615 2016-03-02 20:19:22Z goatbar $");
+
+/*! output format */
+typedef enum {
+    /*! output in text format */ GDALINFO_FORMAT_TEXT = 0,
+    /*! output in json format */ GDALINFO_FORMAT_JSON = 1
+} GDALInfoFormat;
+
+/************************************************************************/
+/*                           GDALInfoOptions                            */
+/************************************************************************/
+
+/** Options for use with GDALInfo(). GDALInfoOptions* must be allocated and freed with GDALInfoOptionsNew() and
+ * GDALInfoOptionsFree() respectively.
+ */
+struct GDALInfoOptions
+{
+    /*! output format */
+    GDALInfoFormat eFormat;
+
+    int bComputeMinMax;
+
+    /*! report histogram information for all bands */
+    int bReportHistograms;
+
+    /*! report a PROJ.4 string corresponding to the file's coordinate system */
+    int bReportProj4;
+
+    /*! read and display image statistics. Force computation if no statistics are stored in an image */
+    int bStats;
+
+    /*! read and display image statistics. Force computation if no statistics are stored in an image.
+        However, they may be computed based on overviews or a subset of all tiles. Useful if you are
+        in a hurry and don't want precise stats. */
+    int bApproxStats;
+
+    int bSample;
+
+    /*! force computation of the checksum for each band in the dataset */
+    int bComputeChecksum;
+
+    /*! allow or suppress ground control points list printing. It may be useful for datasets with huge amount
+        of GCPs, such as L1B AVHRR or HDF4 MODIS which contain thousands of them. */
+    int bShowGCPs;
+
+    /*! allow or suppress metadata printing. Some datasets may contain a lot of metadata strings. */
+    int bShowMetadata;
+
+    /*! allow or suppress printing of raster attribute table */
+    int bShowRAT;
+
+    /*! allow or suppress printing of color table */
+    int bShowColorTable;
+
+    /*! list all metadata domains available for the dataset */
+    int bListMDD;
+
+    /*! display the file list or the first file of the file list */
+    int bShowFileList;
+
+    /*! report metadata for the specified domains. "all" can be used to report metadata
+        in all domains.
+        */
+    char **papszExtraMDDomains;
+
+    bool bStdoutOutput;
+};
+
+
+static int
+GDALInfoReportCorner( const GDALInfoOptions* psOptions,
+                      GDALDatasetH hDataset,
+                      OGRCoordinateTransformationH hTransform,
+                      OGRCoordinateTransformationH hTransformWGS84,
+                      const char * corner_name,
+                      double x,
+                      double y,
+                      bool bJson,
+                      json_object *poCornerCoordinates,
+                      json_object *poWGS84ExtentCoordinates,
+                      CPLString& osStr );
+
+static void
+GDALInfoReportMetadata( const GDALInfoOptions* psOptions,
+                        GDALMajorObjectH hObject,
+                        bool bIsBand,
+                        bool bJson,
+                        json_object *poMetadata,
+                        CPLString& osStr );
+
+
+static void Concat(CPLString& osRet, bool bStdoutOutput,
+                   const char* pszFormat, ...) CPL_PRINT_FUNC_FORMAT (3, 4);
+
+static void Concat(CPLString& osRet, bool bStdoutOutput,
+                   const char* pszFormat, ... )
+{
+    va_list args;
+    va_start( args, pszFormat );
+
+    if( bStdoutOutput )
+    {
+        vfprintf(stdout, pszFormat, args );
+    }
+    else
+    {
+        try
+        {
+            CPLString osTarget;
+            osTarget.vPrintf( pszFormat, args );
+
+            osRet += osTarget;
+        }
+        catch( const std::bad_alloc& )
+        {
+            CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
+        }
+    }
+
+    va_end( args );
+}
+
+/************************************************************************/
+/*                             GDALInfo()                               */
+/************************************************************************/
+
+/**
+ * Lists various information about a GDAL supported raster dataset.
+ *
+ * This is the equivalent of the <a href="gdalinfo.html">gdalinfo</a> utility.
+ *
+ * GDALInfoOptions* must be allocated and freed with GDALInfoOptionsNew()
+ * and GDALInfoOptionsFree() respectively.
+ *
+ * @param hDataset the dataset handle.
+ * @param psOptions the options structure returned by GDALInfoOptionsNew() or NULL.
+ * @return string corresponding to the information about the raster dataset (must be freed with CPLFree()), or NULL in case of error.
+ *
+ * @since GDAL 2.1
+ */
+
+char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
+{
+    if( hDataset == NULL )
+        return NULL;
+
+    GDALInfoOptions* psOptionsToFree = NULL;
+    if( psOptions == NULL )
+    {
+        psOptionsToFree = GDALInfoOptionsNew(NULL, NULL);
+        psOptions = psOptionsToFree;
+    }
+
+    CPLString osStr;
+    json_object *poJsonObject = NULL, *poBands = NULL, *poMetadata = NULL;
+
+    const bool bJson = psOptions->eFormat == GDALINFO_FORMAT_JSON;
+
+/* -------------------------------------------------------------------- */
+/*      Report general info.                                            */
+/* -------------------------------------------------------------------- */
+    GDALDriverH hDriver = GDALGetDatasetDriver( hDataset );
+    if(bJson)
+    {
+        json_object *poDescription = json_object_new_string(GDALGetDescription(hDataset));
+        json_object *poDriverShortName = json_object_new_string(GDALGetDriverShortName(hDriver));
+        json_object *poDriverLongName = json_object_new_string(GDALGetDriverLongName(hDriver));
+        poJsonObject = json_object_new_object();
+        poBands = json_object_new_array();
+        poMetadata = json_object_new_object();
+
+        json_object_object_add(poJsonObject, "description", poDescription);
+        json_object_object_add(poJsonObject, "driverShortName", poDriverShortName);
+        json_object_object_add(poJsonObject, "driverLongName", poDriverLongName);
+    }
+    else
+    {
+        Concat( osStr, psOptions->bStdoutOutput, "Driver: %s/%s\n",
+                GDALGetDriverShortName( hDriver ),
+                GDALGetDriverLongName( hDriver ) );
+    }
+
+    char **papszFileList = GDALGetFileList( hDataset );
+
+    if( papszFileList == NULL || *papszFileList == NULL )
+    {
+        if(bJson)
+        {
+            json_object *poFiles = json_object_new_array();
+            json_object_object_add(poJsonObject, "files", poFiles);
+        }
+        else
+            Concat( osStr, psOptions->bStdoutOutput,
+                    "Files: none associated\n" );
+    }
+    else
+    {
+        if(bJson)
+        {
+            if( psOptions->bShowFileList )
+            {
+                json_object *poFiles = json_object_new_array();
+
+                for(int i = 0; papszFileList[i] != NULL; i++)
+                {
+                    json_object *poFile = json_object_new_string(papszFileList[i]);
+
+                    json_object_array_add(poFiles, poFile);
+                }
+
+                json_object_object_add(poJsonObject, "files", poFiles);
+            }
+        }
+        else
+        {
+            Concat(osStr, psOptions->bStdoutOutput, "Files: %s\n", papszFileList[0] );
+            if( psOptions->bShowFileList )
+            {
+                for( int i = 1; papszFileList[i] != NULL; i++ )
+                    Concat(osStr, psOptions->bStdoutOutput, "       %s\n", papszFileList[i] );
+            }
+        }
+
+    }
+    CSLDestroy( papszFileList );
+
+    if(bJson)
+    {
+        json_object *poSize = json_object_new_array();
+        json_object *poSizeX = json_object_new_int(GDALGetRasterXSize(hDataset));
+        json_object *poSizeY = json_object_new_int(GDALGetRasterYSize(hDataset));
+
+        json_object_array_add(poSize, poSizeX);
+        json_object_array_add(poSize, poSizeY);
+        json_object_object_add(poJsonObject, "size", poSize);
+    }
+    else
+        Concat(osStr, psOptions->bStdoutOutput, "Size is %d, %d\n", GDALGetRasterXSize( hDataset ),
+            GDALGetRasterYSize( hDataset ) );
+
+/* -------------------------------------------------------------------- */
+/*      Report projection.                                              */
+/* -------------------------------------------------------------------- */
+    if( GDALGetProjectionRef( hDataset ) != NULL )
+    {
+        json_object *poCoordinateSystem = NULL;
+
+        if(bJson)
+            poCoordinateSystem = json_object_new_object();
+
+        char *pszProjection
+            = const_cast<char *>( GDALGetProjectionRef( hDataset ) );
+
+        OGRSpatialReferenceH hSRS
+            = OSRNewSpatialReference(NULL);
+        if( OSRImportFromWkt( hSRS, &pszProjection ) == CE_None )
+        {
+            char    *pszPrettyWkt = NULL;
+
+            OSRExportToPrettyWkt( hSRS, &pszPrettyWkt, FALSE );
+
+            if(bJson)
+            {
+                json_object *poWkt = json_object_new_string(pszPrettyWkt);
+                json_object_object_add(poCoordinateSystem, "wkt", poWkt);
+            }
+            else
+                Concat( osStr, psOptions->bStdoutOutput,
+                        "Coordinate System is:\n%s\n",
+                        pszPrettyWkt );
+            CPLFree( pszPrettyWkt );
+        }
+        else
+        {
+            if(bJson)
+            {
+                json_object *poWkt = json_object_new_string(GDALGetProjectionRef(hDataset));
+                json_object_object_add(poCoordinateSystem, "wkt", poWkt);
+            }
+            else
+                Concat( osStr, psOptions->bStdoutOutput,
+                        "Coordinate System is `%s'\n",
+                        GDALGetProjectionRef( hDataset ) );
+
+        }
+
+        if ( psOptions->bReportProj4 )
+        {
+            char *pszProj4 = NULL;
+            OSRExportToProj4( hSRS, &pszProj4 );
+
+            if(bJson)
+            {
+                json_object *proj4 = json_object_new_string(pszProj4);
+                json_object_object_add(poCoordinateSystem, "proj4", proj4);
+            }
+            else
+                Concat(osStr, psOptions->bStdoutOutput, "PROJ.4 string is:\n\'%s\'\n",pszProj4);
+            CPLFree( pszProj4 );
+        }
+
+        if(bJson)
+            json_object_object_add(poJsonObject, "coordinateSystem", poCoordinateSystem);
+
+        OSRDestroySpatialReference( hSRS );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Report Geotransform.                                            */
+/* -------------------------------------------------------------------- */
+    double adfGeoTransform[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
+    if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None )
+    {
+        if(bJson)
+        {
+            json_object *poGeoTransform = json_object_new_array();
+
+            for( int i = 0; i < 6; i++ )
+            {
+                json_object *poGeoTransformCoefficient = json_object_new_double_with_precision(adfGeoTransform[i], 16);
+                json_object_array_add(poGeoTransform, poGeoTransformCoefficient);
+            }
+
+            json_object_object_add(poJsonObject, "geoTransform", poGeoTransform);
+        }
+        else
+        {
+            if( adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0 )
+            {
+                Concat( osStr, psOptions->bStdoutOutput,
+                        "Origin = (%.15f,%.15f)\n",
+                        adfGeoTransform[0], adfGeoTransform[3] );
+
+                Concat( osStr, psOptions->bStdoutOutput,
+                        "Pixel Size = (%.15f,%.15f)\n",
+                        adfGeoTransform[1], adfGeoTransform[5] );
+            }
+            else
+                Concat( osStr, psOptions->bStdoutOutput, "GeoTransform =\n"
+                        "  %.16g, %.16g, %.16g\n"
+                        "  %.16g, %.16g, %.16g\n",
+                        adfGeoTransform[0],
+                        adfGeoTransform[1],
+                        adfGeoTransform[2],
+                        adfGeoTransform[3],
+                        adfGeoTransform[4],
+                        adfGeoTransform[5] );
+        }
+
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Report GCPs.                                                    */
+/* -------------------------------------------------------------------- */
+    if( psOptions->bShowGCPs && GDALGetGCPCount( hDataset ) > 0 )
+    {
+        json_object * const poGCPs = bJson ? json_object_new_object() : NULL;
+
+        if (GDALGetGCPProjection(hDataset) != NULL)
+        {
+            json_object *poGCPCoordinateSystem = NULL;
+
+            char *pszProjection
+                = const_cast<char *>( GDALGetGCPProjection( hDataset ) );
+
+            OGRSpatialReferenceH hSRS
+                = OSRNewSpatialReference(NULL);
+            if( OSRImportFromWkt( hSRS, &pszProjection ) == CE_None )
+            {
+                char    *pszPrettyWkt = NULL;
+
+                OSRExportToPrettyWkt( hSRS, &pszPrettyWkt, FALSE );
+                if(bJson)
+                {
+                    json_object *poWkt = json_object_new_string(pszPrettyWkt);
+                    poGCPCoordinateSystem = json_object_new_object();
+
+                    json_object_object_add(poGCPCoordinateSystem, "wkt", poWkt);
+                }
+                else
+                    Concat(osStr, psOptions->bStdoutOutput, "GCP Projection = \n%s\n", pszPrettyWkt );
+                CPLFree( pszPrettyWkt );
+            }
+            else
+            {
+                if(bJson)
+                {
+                    json_object *poWkt = json_object_new_string(GDALGetGCPProjection(hDataset));
+                    poGCPCoordinateSystem = json_object_new_object();
+
+                    json_object_object_add(poGCPCoordinateSystem, "wkt", poWkt);
+                }
+                else
+                    Concat(osStr, psOptions->bStdoutOutput, "GCP Projection = %s\n",
+                        GDALGetGCPProjection( hDataset ) );
+
+            }
+
+            if(bJson)
+                json_object_object_add(poGCPs, "coordinateSystem", poGCPCoordinateSystem);
+            OSRDestroySpatialReference( hSRS );
+        }
+
+        json_object * const poGCPList = bJson ? json_object_new_array() : NULL;
+
+        for( int i = 0; i < GDALGetGCPCount(hDataset); i++ )
+        {
+            const GDAL_GCP *psGCP = GDALGetGCPs( hDataset ) + i;
+            if(bJson)
+            {
+                json_object *poGCP = json_object_new_object();
+                json_object *poId = json_object_new_string(psGCP->pszId);
+                json_object *poInfo = json_object_new_string(psGCP->pszInfo);
+                json_object *poPixel = json_object_new_double_with_precision(psGCP->dfGCPPixel, 15);
+                json_object *poLine = json_object_new_double_with_precision(psGCP->dfGCPLine, 15);
+                json_object *poX = json_object_new_double_with_precision(psGCP->dfGCPX, 15);
+                json_object *poY = json_object_new_double_with_precision(psGCP->dfGCPY, 15);
+                json_object *poZ = json_object_new_double_with_precision(psGCP->dfGCPZ, 15);
+
+                json_object_object_add(poGCP, "id", poId);
+                json_object_object_add(poGCP, "info", poInfo);
+                json_object_object_add(poGCP, "pixel", poPixel);
+                json_object_object_add(poGCP, "line", poLine);
+                json_object_object_add(poGCP, "x", poX);
+                json_object_object_add(poGCP, "y", poY);
+                json_object_object_add(poGCP, "z", poZ);
+                json_object_array_add(poGCPList, poGCP);
+            }
+            else
+                Concat(osStr, psOptions->bStdoutOutput, "GCP[%3d]: Id=%s, Info=%s\n"
+                    "          (%.15g,%.15g) -> (%.15g,%.15g,%.15g)\n",
+                    i, psGCP->pszId, psGCP->pszInfo,
+                    psGCP->dfGCPPixel, psGCP->dfGCPLine,
+                    psGCP->dfGCPX, psGCP->dfGCPY, psGCP->dfGCPZ );
+        }
+        if(bJson)
+        {
+            json_object_object_add(poGCPs, "gcpList", poGCPList);
+            json_object_object_add(poJsonObject, "gcps", poGCPs);
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Report metadata.                                                */
+/* -------------------------------------------------------------------- */
+
+    GDALInfoReportMetadata( psOptions, hDataset, false, bJson, poMetadata, osStr );
+    if(bJson)
+    {
+        if( psOptions->bShowMetadata )
+            json_object_object_add( poJsonObject, "metadata", poMetadata );
+        else
+            json_object_put(poMetadata);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Setup projected to lat/long transform if appropriate.           */
+/* -------------------------------------------------------------------- */
+    const char  *pszProjection = NULL;
+    if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None )
+        pszProjection = GDALGetProjectionRef(hDataset);
+
+    OGRCoordinateTransformationH hTransform = NULL;
+    OGRCoordinateTransformationH hTransformWGS84 = NULL;
+
+    if( pszProjection != NULL && strlen(pszProjection) > 0 )
+    {
+        OGRSpatialReferenceH hProj, hLatLong = NULL, hLatLongWGS84 = NULL;
+
+        hProj = OSRNewSpatialReference( pszProjection );
+        if( hProj != NULL )
+        {
+            hLatLong = OSRCloneGeogCS( hProj );
+
+            if(bJson)
+            {
+                hLatLongWGS84 = OSRNewSpatialReference( NULL );
+                OSRSetWellKnownGeogCS( hLatLongWGS84, "WGS84" );
+            }
+        }
+
+        if( hLatLong != NULL )
+        {
+            CPLPushErrorHandler( CPLQuietErrorHandler );
+            hTransform = OCTNewCoordinateTransformation( hProj, hLatLong );
+            CPLPopErrorHandler();
+
+            OSRDestroySpatialReference( hLatLong );
+        }
+
+        if( hLatLongWGS84 != NULL )
+        {
+            CPLPushErrorHandler( CPLQuietErrorHandler );
+            hTransformWGS84 = OCTNewCoordinateTransformation( hProj, hLatLongWGS84 );
+            CPLPopErrorHandler();
+
+            OSRDestroySpatialReference( hLatLongWGS84 );
+        }
+
+        if( hProj != NULL )
+            OSRDestroySpatialReference( hProj );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Report corners.                                                 */
+/* -------------------------------------------------------------------- */
+    if(bJson)
+    {
+        json_object *poLinearRing = json_object_new_array();
+        json_object *poCornerCoordinates = json_object_new_object();
+        json_object *poWGS84Extent = json_object_new_object();
+        json_object *poWGS84ExtentType = json_object_new_string("Polygon");
+        json_object *poWGS84ExtentCoordinates = json_object_new_array();
+
+        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "upperLeft",
+                              0.0, 0.0, bJson, poCornerCoordinates, poWGS84ExtentCoordinates, osStr );
+        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "lowerLeft",
+                              0.0, GDALGetRasterYSize(hDataset), bJson, poCornerCoordinates, poWGS84ExtentCoordinates, osStr );
+        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "upperRight",
+                              GDALGetRasterXSize(hDataset), 0.0, bJson, poCornerCoordinates, poWGS84ExtentCoordinates, osStr );
+        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "lowerRight",
+                              GDALGetRasterXSize(hDataset), GDALGetRasterYSize(hDataset),
+                              bJson, poCornerCoordinates, poWGS84ExtentCoordinates, osStr );
+        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "center",
+                              GDALGetRasterXSize(hDataset)/2.0, GDALGetRasterYSize(hDataset)/2.0,
+                              bJson, poCornerCoordinates, poWGS84ExtentCoordinates, osStr );
+        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "upperLeft",
+                              0.0, 0.0, bJson, poCornerCoordinates, poWGS84ExtentCoordinates, osStr );
+
+        json_object_object_add( poJsonObject, "cornerCoordinates", poCornerCoordinates );
+        json_object_object_add( poWGS84Extent, "type", poWGS84ExtentType );
+        json_object_array_add( poLinearRing, poWGS84ExtentCoordinates );
+        json_object_object_add( poWGS84Extent, "coordinates", poLinearRing );
+        json_object_object_add( poJsonObject, "wgs84Extent", poWGS84Extent );
+    }
+    else
+    {
+        Concat(osStr, psOptions->bStdoutOutput, "Corner Coordinates:\n" );
+        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "Upper Left",
+                              0.0, 0.0, bJson, NULL, NULL, osStr );
+        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "Lower Left",
+                              0.0, GDALGetRasterYSize(hDataset), bJson, NULL, NULL, osStr );
+        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "Upper Right",
+                              GDALGetRasterXSize(hDataset), 0.0, bJson, NULL, NULL, osStr );
+        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "Lower Right",
+                              GDALGetRasterXSize(hDataset),
+                              GDALGetRasterYSize(hDataset), bJson, NULL, NULL, osStr );
+        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "Center",
+                              GDALGetRasterXSize(hDataset)/2.0,
+                              GDALGetRasterYSize(hDataset)/2.0, bJson, NULL, NULL, osStr );
+
+    }
+
+    if( hTransform != NULL )
+    {
+        OCTDestroyCoordinateTransformation( hTransform );
+        hTransform = NULL;
+    }
+
+    if( hTransformWGS84 != NULL )
+    {
+        OCTDestroyCoordinateTransformation( hTransformWGS84 );
+        hTransformWGS84 = NULL;
+    }
+
+/* ==================================================================== */
+/*      Loop over bands.                                                */
+/* ==================================================================== */
+    for( int iBand = 0; iBand < GDALGetRasterCount( hDataset ); iBand++ )
+    {
+        json_object *poBand = NULL;
+        json_object *poBandMetadata = NULL;
+
+        if(bJson)
+        {
+            poBand = json_object_new_object();
+            poBandMetadata = json_object_new_object();
+        }
+
+        GDALRasterBandH const hBand = GDALGetRasterBand( hDataset, iBand+1 );
+
+        if( psOptions->bSample )
+        {
+            vector<float> ofSample(10000, 0);
+            float * const pafSample = &ofSample[0];
+            const int nCount =
+                GDALGetRandomRasterSample( hBand, 10000, pafSample );
+            if(!bJson)
+                Concat( osStr, psOptions->bStdoutOutput,
+                        "Got %d samples.\n", nCount );
+        }
+
+        int nBlockXSize = 0;
+        int nBlockYSize = 0;
+        GDALGetBlockSize( hBand, &nBlockXSize, &nBlockYSize );
+        if(bJson)
+        {
+            json_object *poBandNumber = json_object_new_int(iBand+1);
+            json_object *poBlock = json_object_new_array();
+            json_object *poType = json_object_new_string(GDALGetDataTypeName(GDALGetRasterDataType(hBand)));
+            json_object *poColorInterp = json_object_new_string(GDALGetColorInterpretationName(
+                GDALGetRasterColorInterpretation(hBand)));
+
+            json_object_array_add(poBlock, json_object_new_int(nBlockXSize));
+            json_object_array_add(poBlock, json_object_new_int(nBlockYSize));
+            json_object_object_add(poBand, "band", poBandNumber);
+            json_object_object_add(poBand, "block", poBlock);
+            json_object_object_add(poBand, "type", poType);
+            json_object_object_add(poBand, "colorInterpretation", poColorInterp);
+        }
+        else
+            Concat( osStr, psOptions->bStdoutOutput,
+                    "Band %d Block=%dx%d Type=%s, ColorInterp=%s\n",
+                    iBand+1,
+                    nBlockXSize, nBlockYSize,
+                    GDALGetDataTypeName(
+                        GDALGetRasterDataType(hBand)),
+                    GDALGetColorInterpretationName(
+                        GDALGetRasterColorInterpretation(hBand)) );
+
+        if( GDALGetDescription( hBand ) != NULL
+            && strlen(GDALGetDescription( hBand )) > 0 )
+        {
+            if(bJson)
+            {
+                json_object *poBandDescription = json_object_new_string(GDALGetDescription(hBand));
+                json_object_object_add(poBand, "description", poBandDescription);
+            }
+            else
+                Concat( osStr, psOptions->bStdoutOutput, "  Description = %s\n",
+                        GDALGetDescription(hBand) );
+        }
+
+        {
+            int bGotMin = FALSE;
+            int bGotMax = FALSE;
+            const double dfMin = GDALGetRasterMinimum( hBand, &bGotMin );
+            const double dfMax = GDALGetRasterMaximum( hBand, &bGotMax );
+            if( bGotMin || bGotMax || psOptions->bComputeMinMax )
+            {
+                if(!bJson)
+                    Concat(osStr, psOptions->bStdoutOutput, "  " );
+                if( bGotMin )
+                {
+                    if(bJson)
+                    {
+                        json_object *poMin = json_object_new_double_with_precision(dfMin, 3);
+                        json_object_object_add(poBand, "min", poMin);
+                    }
+                    else
+                        Concat(osStr, psOptions->bStdoutOutput, "Min=%.3f ", dfMin );
+                }
+                if( bGotMax )
+                {
+                    if(bJson)
+                    {
+                        json_object *poMax = json_object_new_double_with_precision(dfMax, 3);
+                        json_object_object_add(poBand, "max", poMax);
+                    }
+                    else
+                        Concat(osStr, psOptions->bStdoutOutput, "Max=%.3f ", dfMax );
+                }
+
+                if( psOptions->bComputeMinMax )
+                {
+                    CPLErrorReset();
+                    double adfCMinMax[2] = {0.0, 0.0};
+                    GDALComputeRasterMinMax( hBand, FALSE, adfCMinMax );
+                    if (CPLGetLastErrorType() == CE_None)
+                    {
+                        if(bJson)
+                        {
+                            json_object *poComputedMin = json_object_new_double_with_precision(adfCMinMax[0], 3);
+                            json_object *poComputedMax = json_object_new_double_with_precision(adfCMinMax[1], 3);
+                            json_object_object_add(poBand, "computedMin", poComputedMin);
+                            json_object_object_add(poBand, "computedMax", poComputedMax);
+                        }
+                        else
+                            Concat(osStr, psOptions->bStdoutOutput, "  Computed Min/Max=%.3f,%.3f",
+                              adfCMinMax[0], adfCMinMax[1] );
+                    }
+                }
+                if(!bJson)
+                    Concat(osStr, psOptions->bStdoutOutput, "\n" );
+            }
+        }
+
+        double dfMinStat = 0.0;
+        double dfMaxStat = 0.0;
+        double dfMean = 0.0;
+        double dfStdDev = 0.0;
+        CPLErr eErr = GDALGetRasterStatistics( hBand, psOptions->bApproxStats,
+                                               psOptions->bStats,
+                                               &dfMinStat, &dfMaxStat,
+                                               &dfMean, &dfStdDev );
+        if( eErr == CE_None )
+        {
+            if(bJson)
+            {
+                json_object *poMinimum = json_object_new_double_with_precision(dfMinStat, 3);
+                json_object *poMaximum = json_object_new_double_with_precision(dfMaxStat, 3);
+                json_object *poMean = json_object_new_double_with_precision(dfMean, 3);
+                json_object *poStdDev = json_object_new_double_with_precision(dfStdDev, 3);
+
+                json_object_object_add(poBand, "minimum", poMinimum);
+                json_object_object_add(poBand, "maximum", poMaximum);
+                json_object_object_add(poBand, "mean", poMean);
+                json_object_object_add(poBand, "stdDev", poStdDev);
+            }
+            else
+                Concat(osStr, psOptions->bStdoutOutput, "  Minimum=%.3f, Maximum=%.3f, Mean=%.3f, StdDev=%.3f\n",
+                    dfMinStat, dfMaxStat, dfMean, dfStdDev );
+        }
+
+        if( psOptions->bReportHistograms )
+        {
+            int nBucketCount;
+            GUIntBig *panHistogram = NULL;
+
+            if(bJson)
+                eErr = GDALGetDefaultHistogramEx( hBand, &dfMinStat, &dfMaxStat,
+                                                  &nBucketCount, &panHistogram,
+                                                  TRUE, GDALDummyProgress,
+                                                  NULL );
+            else
+                eErr = GDALGetDefaultHistogramEx( hBand, &dfMinStat, &dfMaxStat,
+                                                  &nBucketCount, &panHistogram,
+                                                  TRUE, GDALTermProgress,
+                                                  NULL );
+            if( eErr == CE_None )
+            {
+                json_object *poHistogram = NULL, *poBuckets = NULL;
+
+                if(bJson)
+                {
+                    json_object *poCount = json_object_new_int(nBucketCount);
+                    json_object *poMin = json_object_new_double(dfMinStat);
+                    json_object *poMax = json_object_new_double(dfMaxStat);
+
+                    poBuckets = json_object_new_array();
+                    poHistogram = json_object_new_object();
+                    json_object_object_add(poHistogram, "count", poCount);
+                    json_object_object_add(poHistogram, "min", poMin);
+                    json_object_object_add(poHistogram, "max", poMax);
+                }
+                else
+                    Concat(osStr, psOptions->bStdoutOutput, "  %d buckets from %g to %g:\n  ",
+                        nBucketCount, dfMinStat, dfMaxStat );
+
+                for( int iBucket = 0; iBucket < nBucketCount; iBucket++ )
+                {
+                    if(bJson)
+                    {
+                        json_object *poBucket = json_object_new_int64(panHistogram[iBucket]);
+                        json_object_array_add(poBuckets, poBucket);
+                    }
+                    else
+                        Concat(osStr, psOptions->bStdoutOutput, CPL_FRMT_GUIB " ", panHistogram[iBucket] );
+                }
+                if(bJson)
+                {
+                    json_object_object_add(poHistogram, "buckets", poBuckets);
+                    json_object_object_add(poBand, "histogram", poHistogram);
+                }
+                else
+                    Concat(osStr, psOptions->bStdoutOutput, "\n" );
+                CPLFree( panHistogram );
+            }
+        }
+
+        if ( psOptions->bComputeChecksum)
+        {
+            int nBandChecksum = GDALChecksumImage(hBand, 0, 0,
+                                      GDALGetRasterXSize(hDataset),
+                                      GDALGetRasterYSize(hDataset));
+            if(bJson)
+            {
+                json_object *poChecksum = json_object_new_int(nBandChecksum);
+                json_object_object_add(poBand, "checksum", poChecksum);
+            }
+            else
+                Concat(osStr, psOptions->bStdoutOutput, "  Checksum=%d\n", nBandChecksum );
+        }
+
+        int bGotNodata = FALSE;
+        const double dfNoData = GDALGetRasterNoDataValue( hBand, &bGotNodata );
+        if( bGotNodata )
+        {
+            if (CPLIsNan(dfNoData))
+            {
+                if(bJson)
+                {
+                    json_object *poNoDataValue = json_object_new_string("nan");
+                    json_object_object_add(poBand, "noDataValue", poNoDataValue);
+                }
+                else
+                    Concat(osStr, psOptions->bStdoutOutput, "  NoData Value=nan\n" );
+            }
+            else
+            {
+                if(bJson)
+                {
+                    json_object *poNoDataValue = json_object_new_double_with_precision(dfNoData, 18);
+                    json_object_object_add(poBand, "noDataValue", poNoDataValue);
+                }
+                else
+                    Concat(osStr, psOptions->bStdoutOutput, "  NoData Value=%.18g\n", dfNoData );
+            }
+        }
+
+        if( GDALGetOverviewCount(hBand) > 0 )
+        {
+            json_object *poOverviews = NULL;
+
+            if(bJson)
+                poOverviews = json_object_new_array();
+            else
+                Concat(osStr, psOptions->bStdoutOutput, "  Overviews: " );
+
+            for( int iOverview = 0;
+                 iOverview < GDALGetOverviewCount(hBand);
+                 iOverview++ )
+            {
+                if(!bJson)
+                    if( iOverview != 0 )
+                        Concat(osStr, psOptions->bStdoutOutput, ", " );
+
+                GDALRasterBandH hOverview = GDALGetOverview( hBand, iOverview );
+                if (hOverview != NULL)
+                {
+                    if(bJson)
+                    {
+                        json_object *poOverviewSize = json_object_new_array();
+                        json_object *poOverviewSizeX = json_object_new_int( GDALGetRasterBandXSize( hOverview) );
+                        json_object *poOverviewSizeY = json_object_new_int( GDALGetRasterBandYSize( hOverview) );
+
+                        json_object *poOverview = json_object_new_object();
+                        json_object_array_add( poOverviewSize, poOverviewSizeX );
+                        json_object_array_add( poOverviewSize, poOverviewSizeY );
+                        json_object_object_add( poOverview, "size", poOverviewSize );
+
+                        if(psOptions->bComputeChecksum)
+                        {
+                            int nOverviewChecksum = GDALChecksumImage(hOverview, 0, 0,
+                                        GDALGetRasterBandXSize(hOverview),
+                                        GDALGetRasterBandYSize(hOverview));
+                            json_object *poOverviewChecksum = json_object_new_int(nOverviewChecksum);
+                            json_object_object_add(poOverview, "checksum", poOverviewChecksum);
+                        }
+                        json_object_array_add(poOverviews, poOverview);
+                    }
+                    else
+                        Concat(osStr, psOptions->bStdoutOutput, "%dx%d",
+                            GDALGetRasterBandXSize( hOverview ),
+                            GDALGetRasterBandYSize( hOverview ) );
+
+                    const char *pszResampling
+                        = GDALGetMetadataItem( hOverview, "RESAMPLING", "" );
+
+                    if( pszResampling != NULL && !bJson
+                        && STARTS_WITH_CI(pszResampling, "AVERAGE_BIT2") )
+                        Concat(osStr, psOptions->bStdoutOutput, "*" );
+                }
+                else
+                    if(!bJson)
+                        Concat(osStr, psOptions->bStdoutOutput, "(null)" );
+            }
+            if(bJson)
+                json_object_object_add(poBand, "overviews", poOverviews);
+            else
+                Concat(osStr, psOptions->bStdoutOutput, "\n" );
+
+            if ( psOptions->bComputeChecksum && !bJson )
+            {
+                Concat(osStr, psOptions->bStdoutOutput, "  Overviews checksum: " );
+
+                for( int iOverview = 0;
+                     iOverview < GDALGetOverviewCount(hBand);
+                     iOverview++ )
+                {
+                    GDALRasterBandH hOverview;
+
+                    if( iOverview != 0 )
+                        Concat(osStr, psOptions->bStdoutOutput, ", " );
+
+                    hOverview = GDALGetOverview( hBand, iOverview );
+                    if (hOverview)
+                    {
+                        Concat(osStr, psOptions->bStdoutOutput, "%d",
+                                GDALChecksumImage(hOverview, 0, 0,
+                                        GDALGetRasterBandXSize(hOverview),
+                                        GDALGetRasterBandYSize(hOverview)));
+                    }
+                    else
+                    {
+                        Concat(osStr, psOptions->bStdoutOutput, "(null)" );
+                    }
+                }
+                Concat(osStr, psOptions->bStdoutOutput, "\n" );
+            }
+        }
+
+        if( GDALHasArbitraryOverviews( hBand ) && !bJson )
+        {
+            Concat(osStr, psOptions->bStdoutOutput, "  Overviews: arbitrary\n" );
+        }
+
+        const int nMaskFlags = GDALGetMaskFlags( hBand );
+        if( (nMaskFlags & (GMF_NODATA|GMF_ALL_VALID)) == 0 )
+        {
+            GDALRasterBandH hMaskBand = GDALGetMaskBand(hBand) ;
+            json_object *poMask = NULL, *poFlags = NULL, *poMaskOverviews = NULL;
+
+            if(bJson)
+            {
+                poMask = json_object_new_object();
+                poFlags = json_object_new_array();
+            }
+            else
+                Concat(osStr, psOptions->bStdoutOutput, "  Mask Flags: " );
+            if( nMaskFlags & GMF_PER_DATASET )
+            {
+                if(bJson)
+                {
+                    json_object *poFlag = json_object_new_string( "PER_DATASET" );
+                    json_object_array_add( poFlags, poFlag );
+                }
+                else
+                    Concat(osStr, psOptions->bStdoutOutput, "PER_DATASET " );
+            }
+            if( nMaskFlags & GMF_ALPHA )
+            {
+                if(bJson)
+                {
+                    json_object *poFlag = json_object_new_string( "ALPHA" );
+                    json_object_array_add( poFlags, poFlag );
+                }
+                else
+                    Concat(osStr, psOptions->bStdoutOutput, "ALPHA " );
+            }
+            if( nMaskFlags & GMF_NODATA )
+            {
+                if(bJson)
+                {
+                    json_object *poFlag = json_object_new_string( "NODATA" );
+                    json_object_array_add( poFlags, poFlag );
+                }
+                else
+                    Concat(osStr, psOptions->bStdoutOutput, "NODATA " );
+            }
+            if( nMaskFlags & GMF_ALL_VALID )
+            {
+                if(bJson)
+                {
+                    json_object *poFlag = json_object_new_string( "ALL_VALID" );
+                    json_object_array_add( poFlags, poFlag );
+                }
+                else
+                    Concat(osStr, psOptions->bStdoutOutput, "ALL_VALID " );
+            }
+            if(bJson)
+                json_object_object_add( poMask, "flags", poFlags );
+            else
+                Concat(osStr, psOptions->bStdoutOutput, "\n" );
+
+            if(bJson)
+                poMaskOverviews = json_object_new_array();
+
+            if( hMaskBand != NULL &&
+                GDALGetOverviewCount(hMaskBand) > 0 )
+            {
+                if(!bJson)
+                    Concat(osStr, psOptions->bStdoutOutput, "  Overviews of mask band: " );
+
+                for( int iOverview = 0;
+                     iOverview < GDALGetOverviewCount(hMaskBand);
+                     iOverview++ )
+                {
+                    GDALRasterBandH hOverview;
+                    json_object *poMaskOverview = NULL;
+                    json_object *poMaskOverviewSize = NULL;
+
+                    if(bJson)
+                    {
+                        poMaskOverview = json_object_new_object();
+                        poMaskOverviewSize = json_object_new_array();
+                    }
+                    else
+                    {
+                        if( iOverview != 0 )
+                            Concat(osStr, psOptions->bStdoutOutput, ", " );
+                    }
+
+                    hOverview = GDALGetOverview( hMaskBand, iOverview );
+                    if(bJson)
+                    {
+                        json_object *poMaskOverviewSizeX =
+                            json_object_new_int(GDALGetRasterBandXSize(hOverview));
+                        json_object *poMaskOverviewSizeY =
+                            json_object_new_int(GDALGetRasterBandYSize(hOverview));
+
+                        json_object_array_add(poMaskOverviewSize, poMaskOverviewSizeX);
+                        json_object_array_add(poMaskOverviewSize, poMaskOverviewSizeY);
+                        json_object_object_add(poMaskOverview, "size", poMaskOverviewSize);
+                        json_object_array_add(poMaskOverviews, poMaskOverview);
+                    }
+                    else
+                        Concat( osStr, psOptions->bStdoutOutput, "%dx%d",
+                                GDALGetRasterBandXSize( hOverview ),
+                                GDALGetRasterBandYSize( hOverview ) );
+                }
+                if(!bJson)
+                    Concat(osStr, psOptions->bStdoutOutput, "\n" );
+            }
+            if(bJson)
+            {
+                json_object_object_add(poMask, "overviews", poMaskOverviews);
+                json_object_object_add(poBand, "mask", poMask);
+            }
+        }
+
+        if( strlen(GDALGetRasterUnitType(hBand)) > 0 )
+        {
+            if(bJson)
+            {
+                json_object *poUnit = json_object_new_string(GDALGetRasterUnitType(hBand));
+                json_object_object_add(poBand, "unit", poUnit);
+            }
+            else
+                Concat(osStr, psOptions->bStdoutOutput, "  Unit Type: %s\n", GDALGetRasterUnitType(hBand) );
+        }
+
+        if( GDALGetRasterCategoryNames(hBand) != NULL )
+        {
+            char **papszCategories = GDALGetRasterCategoryNames(hBand);
+            json_object *poCategories = NULL;
+
+            if(bJson)
+                poCategories = json_object_new_array();
+            else
+                Concat(osStr, psOptions->bStdoutOutput, "  Categories:\n" );
+
+            for( int i = 0; papszCategories[i] != NULL; i++ )
+            {
+                if(bJson)
+                {
+                    json_object *poCategoryName = json_object_new_string(papszCategories[i]);
+                    json_object_array_add(poCategories, poCategoryName);
+                }
+                else
+                    Concat(osStr, psOptions->bStdoutOutput, "    %3d: %s\n", i, papszCategories[i] );
+            }
+            if(bJson)
+                json_object_object_add(poBand, "categories", poCategories);
+        }
+
+        int bSuccess = FALSE;
+        if( GDALGetRasterScale( hBand, &bSuccess ) != 1.0
+            || GDALGetRasterOffset( hBand, &bSuccess ) != 0.0 )
+        {
+            if(bJson)
+            {
+                json_object *poOffset = json_object_new_double_with_precision(
+                    GDALGetRasterOffset(hBand, &bSuccess), 15);
+                json_object *poScale = json_object_new_double_with_precision(
+                    GDALGetRasterScale(hBand, &bSuccess), 15);
+                json_object_object_add(poBand, "offset", poOffset);
+                json_object_object_add(poBand, "scale", poScale);
+            }
+            else
+                Concat(osStr, psOptions->bStdoutOutput, "  Offset: %.15g,   Scale:%.15g\n",
+                    GDALGetRasterOffset( hBand, &bSuccess ),
+                    GDALGetRasterScale( hBand, &bSuccess ) );
+        }
+
+        GDALInfoReportMetadata( psOptions, hBand, true, bJson, poBandMetadata, osStr );
+        if(bJson)
+        {
+            if (psOptions->bShowMetadata)
+                json_object_object_add( poBand, "metadata", poBandMetadata );
+            else
+                json_object_put(poBandMetadata);
+        }
+
+        GDALColorTableH hTable;
+        if( GDALGetRasterColorInterpretation(hBand) == GCI_PaletteIndex
+            && (hTable = GDALGetRasterColorTable( hBand )) != NULL )
+        {
+            if(!bJson)
+                Concat( osStr, psOptions->bStdoutOutput,
+                        "  Color Table (%s with %d entries)\n",
+                        GDALGetPaletteInterpretationName(
+                            GDALGetPaletteInterpretation( hTable )),
+                        GDALGetColorEntryCount( hTable ) );
+
+            if (psOptions->bShowColorTable)
+            {
+                json_object *poEntries = NULL;
+
+                if(bJson)
+                {
+                    json_object *poPalette = json_object_new_string(GDALGetPaletteInterpretationName(
+                        GDALGetPaletteInterpretation(hTable)));
+                    json_object *poCount = json_object_new_int(GDALGetColorEntryCount(hTable));
+
+                    json_object *poColorTable = json_object_new_object();
+
+                    json_object_object_add(poColorTable, "palette", poPalette);
+                    json_object_object_add(poColorTable, "count", poCount);
+
+                    poEntries = json_object_new_array();
+                    json_object_object_add(poColorTable, "entries", poEntries);
+                    json_object_object_add(poBand, "colorTable", poColorTable);
+                }
+
+                for( int i = 0; i < GDALGetColorEntryCount( hTable ); i++ )
+                {
+                    GDALColorEntry  sEntry;
+
+                    GDALGetColorEntryAsRGB( hTable, i, &sEntry );
+
+                    if(bJson)
+                    {
+                        json_object *poEntry = json_object_new_array();
+                        json_object *poC1 = json_object_new_int(sEntry.c1);
+                        json_object *poC2 = json_object_new_int(sEntry.c2);
+                        json_object *poC3 = json_object_new_int(sEntry.c3);
+                        json_object *poC4 = json_object_new_int(sEntry.c4);
+
+                        json_object_array_add(poEntry, poC1);
+                        json_object_array_add(poEntry, poC2);
+                        json_object_array_add(poEntry, poC3);
+                        json_object_array_add(poEntry, poC4);
+                        json_object_array_add(poEntries, poEntry);
+                    }
+                    else
+                        Concat(osStr, psOptions->bStdoutOutput, "  %3d: %d,%d,%d,%d\n",
+                            i,
+                            sEntry.c1,
+                            sEntry.c2,
+                            sEntry.c3,
+                            sEntry.c4 );
+                }
+            }
+        }
+
+        if( psOptions->bShowRAT && GDALGetDefaultRAT( hBand ) != NULL )
+        {
+            GDALRasterAttributeTableH hRAT = GDALGetDefaultRAT( hBand );
+
+            if(bJson)
+            {
+                json_object *poRAT = (json_object*) GDALRATSerializeJSON( hRAT );
+                json_object_object_add( poJsonObject, "rat", poRAT );
+            }
+            else
+            {
+                CPLXMLNode *psTree = ((GDALRasterAttributeTable *) hRAT)->Serialize();
+                char *pszXMLText = CPLSerializeXMLTree( psTree );
+                CPLDestroyXMLNode( psTree );
+                Concat(osStr, psOptions->bStdoutOutput, "%s\n", pszXMLText );
+                CPLFree( pszXMLText );
+            }
+        }
+        if(bJson)
+            json_object_array_add(poBands, poBand);
+    }
+
+    if(bJson)
+    {
+        json_object_object_add(poJsonObject, "bands", poBands);
+        Concat(osStr, psOptions->bStdoutOutput, "%s", json_object_to_json_string_ext(poJsonObject, JSON_C_TO_STRING_PRETTY));
+        json_object_put(poJsonObject);
+    }
+
+    if( psOptionsToFree != NULL )
+        GDALInfoOptionsFree(psOptionsToFree);
+
+    return VSI_STRDUP_VERBOSE(osStr);
+}
+
+/************************************************************************/
+/*                        GDALInfoReportCorner()                        */
+/************************************************************************/
+
+static int
+GDALInfoReportCorner( const GDALInfoOptions* psOptions,
+                      GDALDatasetH hDataset,
+                      OGRCoordinateTransformationH hTransform,
+                      OGRCoordinateTransformationH hTransformWGS84,
+                      const char * corner_name,
+                      double x,
+                      double y,
+                      bool bJson,
+                      json_object *poCornerCoordinates,
+                      json_object *poWGS84ExtentCoordinates,
+                      CPLString& osStr )
+
+{
+    if(!bJson)
+        Concat(osStr, psOptions->bStdoutOutput, "%-11s ", corner_name );
+
+/* -------------------------------------------------------------------- */
+/*      Transform the point into georeferenced coordinates.             */
+/* -------------------------------------------------------------------- */
+    double adfGeoTransform[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
+    double dfGeoX = 0.0;
+    double dfGeoY = 0.0;
+
+    if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None )
+    {
+        dfGeoX = adfGeoTransform[0] + adfGeoTransform[1] * x
+            + adfGeoTransform[2] * y;
+        dfGeoY = adfGeoTransform[3] + adfGeoTransform[4] * x
+            + adfGeoTransform[5] * y;
+    }
+    else
+    {
+        if( bJson )
+        {
+            json_object * const poCorner = json_object_new_array();
+            json_object * const poX = json_object_new_double_with_precision( x, 1 );
+            json_object * const poY = json_object_new_double_with_precision( y, 1 );
+            json_object_array_add( poCorner, poX );
+            json_object_array_add( poCorner, poY );
+            json_object_object_add( poCornerCoordinates, corner_name, poCorner );
+        }
+        else
+            Concat(osStr, psOptions->bStdoutOutput, "(%7.1f,%7.1f)\n", x, y );
+        return FALSE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Report the georeferenced coordinates.                           */
+/* -------------------------------------------------------------------- */
+    if( ABS(dfGeoX) < 181 && ABS(dfGeoY) < 91 )
+    {
+        if(bJson)
+        {
+            json_object * const poCorner = json_object_new_array();
+            json_object * const poX = json_object_new_double_with_precision( dfGeoX, 7 );
+            json_object * const poY = json_object_new_double_with_precision( dfGeoY, 7 );
+            json_object_array_add( poCorner, poX );
+            json_object_array_add( poCorner, poY );
+            json_object_object_add( poCornerCoordinates, corner_name, poCorner );
+        }
+        else
+            Concat(osStr, psOptions->bStdoutOutput, "(%12.7f,%12.7f) ", dfGeoX, dfGeoY );
+    }
+    else
+    {
+        if(bJson)
+        {
+            json_object * const poCorner = json_object_new_array();
+            json_object * const poX = json_object_new_double_with_precision( dfGeoX, 3 );
+            json_object * const poY = json_object_new_double_with_precision( dfGeoY, 3 );
+            json_object_array_add( poCorner, poX );
+            json_object_array_add( poCorner, poY );
+            json_object_object_add( poCornerCoordinates, corner_name, poCorner );
+        }
+        else
+            Concat(osStr, psOptions->bStdoutOutput, "(%12.3f,%12.3f) ", dfGeoX, dfGeoY );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Transform to latlong and report.                                */
+/* -------------------------------------------------------------------- */
+    if(bJson)
+    {
+        double dfZ = 0.0;
+        if( hTransformWGS84 != NULL && !EQUAL( corner_name, "center" )
+        && OCTTransform(hTransformWGS84,1,&dfGeoX,&dfGeoY,&dfZ) )
+        {
+            json_object * const poCorner = json_object_new_array();
+            json_object * const poX = json_object_new_double_with_precision( dfGeoX, 7 );
+            json_object * const poY = json_object_new_double_with_precision( dfGeoY, 7 );
+            json_object_array_add( poCorner, poX );
+            json_object_array_add( poCorner, poY );
+            json_object_array_add( poWGS84ExtentCoordinates , poCorner );
+        }
+    }
+    else
+    {
+        double dfZ = 0.0;
+        if( hTransform != NULL
+        && OCTTransform(hTransform,1,&dfGeoX,&dfGeoY,&dfZ) )
+        {
+            Concat(osStr, psOptions->bStdoutOutput, "(%s,", GDALDecToDMS( dfGeoX, "Long", 2 ) );
+            Concat(osStr, psOptions->bStdoutOutput, "%s)", GDALDecToDMS( dfGeoY, "Lat", 2 ) );
+        }
+        Concat(osStr, psOptions->bStdoutOutput, "\n" );
+    }
+
+    return TRUE;
+}
+
+
+/************************************************************************/
+/*                       GDALInfoPrintMetadata()                        */
+/************************************************************************/
+static void GDALInfoPrintMetadata( const GDALInfoOptions* psOptions,
+                                   GDALMajorObjectH hObject,
+                                   const char *pszDomain,
+                                   const char *pszDisplayedname,
+                                   const char *pszIndent,
+                                   int bJson,
+                                   json_object *poMetadata,
+                                   CPLString& osStr )
+{
+    bool bIsxml = false;
+
+    if (pszDomain != NULL && STARTS_WITH_CI(pszDomain, "xml:"))
+        bIsxml = true;
+
+    char **papszMetadata = GDALGetMetadata( hObject, pszDomain );
+    if( papszMetadata != NULL && *papszMetadata != NULL )
+    {
+        json_object *poDomain =
+            (bJson && !bIsxml) ? json_object_new_object() : NULL;
+
+        if(!bJson)
+            Concat( osStr, psOptions->bStdoutOutput, "%s%s:\n", pszIndent,
+                    pszDisplayedname );
+
+        json_object *poValue = NULL;
+
+        for( int i = 0; papszMetadata[i] != NULL; i++ )
+        {
+            if(bJson)
+            {
+                if(bIsxml)
+                {
+                    poValue = json_object_new_string( papszMetadata[i] );
+                    break;
+                }
+                else
+                {
+                    char *pszKey = NULL;
+                    const char *pszValue =
+                        CPLParseNameValue( papszMetadata[i], &pszKey );
+                    if( pszKey )
+                    {
+                        poValue = json_object_new_string( pszValue );
+                        json_object_object_add( poDomain, pszKey, poValue );
+                        CPLFree( pszKey );
+                    }
+                }
+            }
+            else
+            {
+                if (bIsxml)
+                    Concat(osStr, psOptions->bStdoutOutput, "%s%s\n", pszIndent, papszMetadata[i] );
+                else
+                    Concat(osStr, psOptions->bStdoutOutput, "%s  %s\n", pszIndent, papszMetadata[i] );
+
+            }
+        }
+        if(bJson)
+        {
+            if(bIsxml)
+                json_object_object_add( poMetadata, pszDomain, poValue );
+            else
+            {
+                if(pszDomain == NULL)
+                    json_object_object_add( poMetadata, "", poDomain );
+                else
+                    json_object_object_add( poMetadata, pszDomain, poDomain );
+            }
+        }
+    }
+
+}
+
+/************************************************************************/
+/*                       GDALInfoReportMetadata()                       */
+/************************************************************************/
+static void GDALInfoReportMetadata( const GDALInfoOptions* psOptions,
+                                    GDALMajorObjectH hObject,
+                                    bool bIsBand,
+                                    bool bJson,
+                                    json_object *poMetadata,
+                                    CPLString& osStr )
+{
+    const char* const pszIndent = bIsBand ? "  " : "";
+
+    /* -------------------------------------------------------------------- */
+    /*      Report list of Metadata domains                                 */
+    /* -------------------------------------------------------------------- */
+    if( psOptions->bListMDD )
+    {
+        char** papszMDDList = GDALGetMetadataDomainList( hObject );
+        char** papszIter = papszMDDList;
+        json_object *poMDD = NULL;
+        json_object * const poListMDD = bJson ? json_object_new_array() : NULL;
+
+        if( papszMDDList != NULL )
+        {
+            if(!bJson)
+                Concat(osStr, psOptions->bStdoutOutput, "%sMetadata domains:\n", pszIndent );
+        }
+
+        while( papszIter != NULL && *papszIter != NULL )
+        {
+            if( EQUAL(*papszIter, "") )
+            {
+                if(bJson)
+                    poMDD = json_object_new_string( *papszIter );
+                else
+                    Concat(osStr, psOptions->bStdoutOutput, "%s  (default)\n", pszIndent);
+            }
+            else
+            {
+                if(bJson)
+                    poMDD = json_object_new_string( *papszIter );
+                else
+                    Concat(osStr, psOptions->bStdoutOutput, "%s  %s\n", pszIndent, *papszIter );
+            }
+            if(bJson)
+                json_object_array_add( poListMDD, poMDD );
+            papszIter ++;
+        }
+        if(bJson)
+            json_object_object_add( poMetadata, "metadataDomains", poListMDD );
+        CSLDestroy(papszMDDList);
+    }
+
+    if (!psOptions->bShowMetadata)
+        return;
+
+    /* -------------------------------------------------------------------- */
+    /*      Report default Metadata domain.                                 */
+    /* -------------------------------------------------------------------- */
+    GDALInfoPrintMetadata( psOptions, hObject, NULL, "Metadata", pszIndent, bJson, poMetadata, osStr );
+
+    /* -------------------------------------------------------------------- */
+    /*      Report extra Metadata domains                                   */
+    /* -------------------------------------------------------------------- */
+    if (psOptions->papszExtraMDDomains != NULL) {
+        char **papszExtraMDDomainsExpanded = NULL;
+
+        if( EQUAL(psOptions->papszExtraMDDomains[0], "all") &&
+            psOptions->papszExtraMDDomains[1] == NULL )
+        {
+            char ** papszMDDList = GDALGetMetadataDomainList( hObject );
+            char * const * papszIter = papszMDDList;
+
+            while( papszIter != NULL && *papszIter != NULL )
+            {
+                if( !EQUAL(*papszIter, "") &&
+                    !EQUAL(*papszIter, "IMAGE_STRUCTURE") &&
+                    !EQUAL(*papszIter, "SUBDATASETS") &&
+                    !EQUAL(*papszIter, "GEOLOCATION") &&
+                    !EQUAL(*papszIter, "RPC") )
+                {
+                    papszExtraMDDomainsExpanded =
+                        CSLAddString(papszExtraMDDomainsExpanded, *papszIter);
+                }
+                papszIter ++;
+            }
+            CSLDestroy(papszMDDList);
+        }
+        else
+        {
+            papszExtraMDDomainsExpanded = CSLDuplicate(psOptions->papszExtraMDDomains);
+        }
+
+        for( int iMDD = 0; papszExtraMDDomainsExpanded != NULL &&
+                           papszExtraMDDomainsExpanded[iMDD] != NULL; iMDD++ )
+        {
+            if(bJson)
+            {
+                GDALInfoPrintMetadata(
+                    psOptions, hObject, papszExtraMDDomainsExpanded[iMDD],
+                    papszExtraMDDomainsExpanded[iMDD], pszIndent, bJson,
+                    poMetadata, osStr );
+            }
+            else
+            {
+                CPLString osDisplayedname =
+                    "Metadata (" +
+                    CPLString(papszExtraMDDomainsExpanded[iMDD]) + ")";
+
+                GDALInfoPrintMetadata(
+                    psOptions, hObject, papszExtraMDDomainsExpanded[iMDD],
+                    osDisplayedname.c_str(), pszIndent, bJson, poMetadata,
+                    osStr );
+            }
+        }
+
+        CSLDestroy(papszExtraMDDomainsExpanded);
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Report various named metadata domains.                          */
+    /* -------------------------------------------------------------------- */
+    GDALInfoPrintMetadata( psOptions, hObject, "IMAGE_STRUCTURE",
+                           "Image Structure Metadata", pszIndent, bJson,
+                           poMetadata, osStr );
+
+    if (!bIsBand)
+    {
+        GDALInfoPrintMetadata( psOptions, hObject, "SUBDATASETS", "Subdatasets", pszIndent, bJson, poMetadata, osStr );
+        GDALInfoPrintMetadata( psOptions, hObject, "GEOLOCATION", "Geolocation", pszIndent, bJson, poMetadata, osStr );
+        GDALInfoPrintMetadata( psOptions, hObject, "RPC", "RPC Metadata", pszIndent, bJson, poMetadata, osStr );
+    }
+
+}
+
+/************************************************************************/
+/*                             GDALInfoOptionsNew()                     */
+/************************************************************************/
+
+/**
+ * Allocates a GDALInfoOptions struct.
+ *
+ * @param papszArgv NULL terminated list of options (potentially including filename and open options too), or NULL.
+ *                  The accepted options are the ones of the <a href="gdalinfo.html">gdalinfo</a> utility.
+ * @param psOptionsForBinary (output) may be NULL (and should generally be NULL),
+ *                           otherwise (gdalinfo_bin.cpp use case) must be allocated with
+ *                           GDALInfoOptionsForBinaryNew() prior to this function. Will be
+ *                           filled with potentially present filename, open options, subdataset number...
+ * @return pointer to the allocated GDALInfoOptions struct. Must be freed with GDALInfoOptionsFree().
+ *
+ * @since GDAL 2.1
+ */
+
+GDALInfoOptions *GDALInfoOptionsNew(char** papszArgv,
+                                    GDALInfoOptionsForBinary* psOptionsForBinary)
+{
+    bool bGotFilename = false;
+    GDALInfoOptions *psOptions = static_cast<GDALInfoOptions *>(
+        CPLCalloc( 1, sizeof(GDALInfoOptions) ) );
+
+    psOptions->eFormat = GDALINFO_FORMAT_TEXT;
+    psOptions->bComputeMinMax = FALSE;
+    psOptions->bReportHistograms = FALSE;
+    psOptions->bReportProj4 = FALSE;
+    psOptions->bStats = FALSE;
+    psOptions->bApproxStats = TRUE;
+    psOptions->bSample = FALSE;
+    psOptions->bComputeChecksum = FALSE;
+    psOptions->bShowGCPs = TRUE;
+    psOptions->bShowMetadata = TRUE;
+    psOptions->bShowRAT = TRUE;
+    psOptions->bShowColorTable = TRUE;
+    psOptions->bListMDD = FALSE;
+    psOptions->bShowFileList = TRUE;
+
+/* -------------------------------------------------------------------- */
+/*      Parse arguments.                                                */
+/* -------------------------------------------------------------------- */
+    for( int i = 0; papszArgv != NULL && papszArgv[i] != NULL; i++ )
+    {
+        if( EQUAL(papszArgv[i],"-json") )
+            psOptions->eFormat = GDALINFO_FORMAT_JSON;
+        else if( EQUAL(papszArgv[i], "-mm") )
+            psOptions->bComputeMinMax = TRUE;
+        else if( EQUAL(papszArgv[i], "-hist") )
+            psOptions->bReportHistograms = TRUE;
+        else if( EQUAL(papszArgv[i], "-proj4") )
+            psOptions->bReportProj4 = TRUE;
+        else if( EQUAL(papszArgv[i], "-stats") )
+        {
+            psOptions->bStats = TRUE;
+            psOptions->bApproxStats = FALSE;
+        }
+        else if( EQUAL(papszArgv[i], "-approx_stats") )
+        {
+            psOptions->bStats = TRUE;
+            psOptions->bApproxStats = TRUE;
+        }
+        else if( EQUAL(papszArgv[i], "-sample") )
+            psOptions->bSample = TRUE;
+        else if( EQUAL(papszArgv[i], "-checksum") )
+            psOptions->bComputeChecksum = TRUE;
+        else if( EQUAL(papszArgv[i], "-nogcp") )
+            psOptions->bShowGCPs = FALSE;
+        else if( EQUAL(papszArgv[i], "-nomd") )
+            psOptions->bShowMetadata = FALSE;
+        else if( EQUAL(papszArgv[i], "-norat") )
+            psOptions->bShowRAT = FALSE;
+        else if( EQUAL(papszArgv[i], "-noct") )
+            psOptions->bShowColorTable = FALSE;
+        else if( EQUAL(papszArgv[i], "-listmdd") )
+            psOptions->bListMDD = TRUE;
+        /* Not documented: used by gdalinfo_bin.cpp only */
+        else if( EQUAL(papszArgv[i], "-stdout") )
+            psOptions->bStdoutOutput = true;
+        else if( EQUAL(papszArgv[i], "-mdd") && papszArgv[i+1] != NULL )
+        {
+            psOptions->papszExtraMDDomains = CSLAddString(
+                psOptions->papszExtraMDDomains, papszArgv[++i] );
+        }
+        else if( EQUAL(papszArgv[i], "-oo") && papszArgv[i+1] != NULL )
+        {
+            i++;
+            if( psOptionsForBinary )
+            {
+                psOptionsForBinary->papszOpenOptions = CSLAddString(
+                     psOptionsForBinary->papszOpenOptions, papszArgv[i] );
+            }
+        }
+        else if( EQUAL(papszArgv[i], "-nofl") )
+            psOptions->bShowFileList = FALSE;
+        else if( EQUAL(papszArgv[i], "-sd") && papszArgv[i+1] != NULL )
+        {
+            i++;
+            if( psOptionsForBinary )
+            {
+                psOptionsForBinary->nSubdataset = atoi(papszArgv[i]);
+            }
+        }
+        else if( papszArgv[i][0] == '-' )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unknown option name '%s'", papszArgv[i]);
+            GDALInfoOptionsFree(psOptions);
+            return NULL;
+        }
+        else if( !bGotFilename )
+        {
+            bGotFilename = true;
+            if( psOptionsForBinary )
+                psOptionsForBinary->pszFilename = CPLStrdup(papszArgv[i]);
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Too many command options '%s'", papszArgv[i]);
+            GDALInfoOptionsFree(psOptions);
+            return NULL;
+        }
+    }
+
+    return psOptions;
+}
+
+/************************************************************************/
+/*                             GDALInfoOptionsFree()                    */
+/************************************************************************/
+
+/**
+ * Frees the GDALInfoOptions struct.
+ *
+ * @param psOptions the options struct for GDALInfo().
+ *
+ * @since GDAL 2.1
+ */
+
+void GDALInfoOptionsFree( GDALInfoOptions *psOptions )
+{
+    if( psOptions != NULL )
+    {
+        CSLDestroy( psOptions->papszExtraMDDomains );
+
+        CPLFree(psOptions);
+    }
+}
diff --git a/apps/gdallocationinfo.cpp b/apps/gdallocationinfo.cpp
index 61ad025..d62c904 100644
--- a/apps/gdallocationinfo.cpp
+++ b/apps/gdallocationinfo.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: gdallocationinfo.cpp 28800 2015-03-27 21:03:41Z rouault $
+ * $Id: gdallocationinfo.cpp 33615 2016-03-02 20:19:22Z goatbar $
  *
  * Project:  GDAL
- * Purpose:  Commandline raster query tool.
+ * Purpose:  Command line raster query tool.
  * Author:   Frank Warmerdam <warmerdam at pobox.com>
  *
  ******************************************************************************
@@ -34,7 +34,7 @@
 #include "cpl_minixml.h"
 #include <vector>
 
-CPL_CVSID("$Id: gdallocationinfo.cpp 28800 2015-03-27 21:03:41Z rouault $");
+CPL_CVSID("$Id: gdallocationinfo.cpp 33615 2016-03-02 20:19:22Z goatbar $");
 
 /******************************************************************************/
 /*! \page gdallocationinfo gdallocationinfo
@@ -44,7 +44,7 @@ raster query tool
 \section gdallocationinfo_synopsis SYNOPSIS
 
 \htmlonly
-Usage: 
+Usage:
 \endhtmlonly
 
 \verbatim
@@ -66,15 +66,15 @@ reporting options are provided.
 <dt> <b>-xml</b>:</dt>
 <dd> The output report will be XML formatted for convenient post processing.</dd>
 
-<dt> <b>-lifonly</b>:</dt> 
+<dt> <b>-lifonly</b>:</dt>
 <dd>The only output is filenames production from the LocationInfo request
-against the database (ie. for identifying impacted file from VRT).</dd>
+against the database (i.e. for identifying impacted file from VRT).</dd>
 
-<dt> <b>-valonly</b>:</dt> 
+<dt> <b>-valonly</b>:</dt>
 <dd>The only output is the pixel values of the selected pixel on each of
 the selected bands.</dd>
 
-<dt> <b>-b</b> <em>band</em>:</dt> 
+<dt> <b>-b</b> <em>band</em>:</dt>
 <dd>Selects a band to query.  Multiple bands can be listed.  By default all
 bands are queried.</dd>
 
@@ -97,41 +97,41 @@ pixel/line) must still be given with respect to the base band.</dd>
 
 <dt> <em>srcfile</em>:</dt><dd> The source GDAL raster datasource name.</dd>
 
-<dt> <em>x</em>:</dt><dd> X location of target pixel.  By default the 
+<dt> <em>x</em>:</dt><dd> X location of target pixel.  By default the
 coordinate system is pixel/line unless -l_srs, -wgs84 or -geoloc supplied. </dd>
 
-<dt> <em>y</em>:</dt><dd> Y location of target pixel.  By default the 
+<dt> <em>y</em>:</dt><dd> Y location of target pixel.  By default the
 coordinate system is pixel/line unless -l_srs, -wgs84 or -geoloc supplied. </dd>
 
 </dl>
 
-This utility is intended to provide a variety of information about a 
+This utility is intended to provide a variety of information about a
 pixel.  Currently it reports three things:
 
 <ul>
 <li> The location of the pixel in pixel/line space.
-<li> The result of a LocationInfo metadata query against the datasource - 
+<li> The result of a LocationInfo metadata query against the datasource -
 currently this is only implemented for VRT files which will report the
 file(s) used to satisfy requests for that pixel.
 <li> The raster pixel value of that pixel for all or a subset of the bands.
 <li> The unscaled pixel value if a Scale and/or Offset apply to the band.
 </ul>
 
-The pixel selected is requested by x/y coordinate on the commandline, or read
+The pixel selected is requested by x/y coordinate on the command line, or read
 from stdin. More than one coordinate pair can be supplied when reading
-coordinatesis from stdin. By default pixel/line coordinates are expected.
+coordinates from stdin. By default pixel/line coordinates are expected.
 However with use of the -geoloc, -wgs84, or -l_srs switches it is possible
 to specify the location in other coordinate systems.
 
-The default report is in a human readable text format.  It is possible to 
+The default report is in a human readable text format.  It is possible to
 instead request xml output with the -xml switch.
 
 For scripting purposes, the -valonly and -lifonly switches are provided to
-restrict output to the actual pixel values, or the LocationInfo files 
+restrict output to the actual pixel values, or the LocationInfo files
 identified for the pixel.
 
-It is anticipated that additional reporting capabilities will be added to 
-gdallocationinfo in the future. 
+It is anticipated that additional reporting capabilities will be added to
+gdallocationinfo in the future.
 
 <p>
 \section gdallocationinfo_example EXAMPLE
@@ -176,7 +176,7 @@ static void Usage()
     printf( "Usage: gdallocationinfo [--help-general] [-xml] [-lifonly] [-valonly]\n"
             "                        [-b band]* [-overview overview_level]\n"
             "                        [-l_srs srs_def] [-geoloc] [-wgs84]\n"
-            "                        [-oo NAME=VALUE]* srcfile x y\n" 
+            "                        [-oo NAME=VALUE]* srcfile x y\n"
             "\n" );
     exit( 1 );
 }
@@ -185,15 +185,14 @@ static void Usage()
 /*                             SanitizeSRS                              */
 /************************************************************************/
 
-char *SanitizeSRS( const char *pszUserInput )
+static char *SanitizeSRS( const char *pszUserInput )
 
 {
-    OGRSpatialReferenceH hSRS;
-    char *pszResult = NULL;
-
     CPLErrorReset();
-    
-    hSRS = OSRNewSpatialReference( NULL );
+
+    OGRSpatialReferenceH hSRS = OSRNewSpatialReference( NULL );
+
+    char *pszResult = NULL;
     if( OSRSetFromUserInput( hSRS, pszUserInput ) == OGRERR_NONE )
         OSRExportToWkt( hSRS, &pszResult );
     else
@@ -203,7 +202,7 @@ char *SanitizeSRS( const char *pszUserInput )
                   pszUserInput );
         exit( 1 );
     }
-    
+
     OSRDestroySpatialReference( hSRS );
 
     return pszResult;
@@ -233,14 +232,14 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
 /*      Parse arguments.                                                */
 /* -------------------------------------------------------------------- */
-    int i;
-
-    for( i = 1; i < argc; i++ )
+    for( int i = 1; i < argc; i++ )
     {
         if( EQUAL(argv[i], "--utility_version") )
         {
             printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
                    argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
+            GDALDestroyDriverManager();
+            CSLDestroy(argv);
             return 0;
         }
         else if( EQUAL(argv[i],"-b") && i < argc-1 )
@@ -307,10 +306,9 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
 /*      Open source file.                                               */
 /* -------------------------------------------------------------------- */
-    GDALDatasetH hSrcDS = NULL;
-
-    hSrcDS = GDALOpenEx( pszSrcFilename, GDAL_OF_RASTER, NULL,
-                           (const char* const* )papszOpenOptions, NULL );
+    GDALDatasetH hSrcDS
+        = GDALOpenEx( pszSrcFilename, GDAL_OF_RASTER, NULL,
+                      (const char* const* )papszOpenOptions, NULL );
     if( hSrcDS == NULL )
         exit( 1 );
 
@@ -335,10 +333,10 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
     if( anBandList.size() == 0 )
     {
-        for( i = 0; i < GDALGetRasterCount( hSrcDS ); i++ )
+        for( int i = 0; i < GDALGetRasterCount( hSrcDS ); i++ )
             anBandList.push_back( i+1 );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Turn the location into a pixel and line location.               */
 /* -------------------------------------------------------------------- */
@@ -369,29 +367,29 @@ int main( int argc, char ** argv )
             if( !OCTTransform( hCT, 1, &dfGeoX, &dfGeoY, NULL ) )
                 exit( 1 );
         }
-    
+
         if( pszSourceSRS != NULL )
         {
             double adfGeoTransform[6], adfInvGeoTransform[6];
-    
+
             if( GDALGetGeoTransform( hSrcDS, adfGeoTransform ) != CE_None )
             {
                 CPLError(CE_Failure, CPLE_AppDefined, "Cannot get geotransform");
                 exit( 1 );
             }
-    
+
             if( !GDALInvGeoTransform( adfGeoTransform, adfInvGeoTransform ) )
             {
                 CPLError(CE_Failure, CPLE_AppDefined, "Cannot invert geotransform");
                 exit( 1 );
             }
-    
+
             iPixel = (int) floor(
-                adfInvGeoTransform[0] 
+                adfInvGeoTransform[0]
                 + adfInvGeoTransform[1] * dfGeoX
                 + adfInvGeoTransform[2] * dfGeoY );
             iLine = (int) floor(
-                adfInvGeoTransform[3] 
+                adfInvGeoTransform[3]
                 + adfInvGeoTransform[4] * dfGeoX
                 + adfInvGeoTransform[5] * dfGeoY );
         }
@@ -405,10 +403,10 @@ int main( int argc, char ** argv )
     /*      Prepare report.                                                 */
     /* -------------------------------------------------------------------- */
         CPLString osLine;
-    
+
         if( bAsXML )
         {
-            osLine.Printf( "<Report pixel=\"%d\" line=\"%d\">", 
+            osLine.Printf( "<Report pixel=\"%d\" line=\"%d\">",
                           iPixel, iLine );
             osXML += osLine;
         }
@@ -418,9 +416,9 @@ int main( int argc, char ** argv )
             printf( "  Location: (%dP,%dL)\n", iPixel, iLine );
         }
 
-        int bPixelReport = TRUE;
+        bool bPixelReport = true;
 
-        if( iPixel < 0 || iLine < 0 
+        if( iPixel < 0 || iLine < 0
             || iPixel >= GDALGetRasterXSize( hSrcDS )
             || iLine  >= GDALGetRasterYSize( hSrcDS ) )
         {
@@ -430,13 +428,13 @@ int main( int argc, char ** argv )
                 printf("\n");
             else if( !bQuiet )
                 printf( "\nLocation is off this file! No further details to report.\n");
-            bPixelReport = FALSE;
+            bPixelReport = false;
         }
 
     /* -------------------------------------------------------------------- */
     /*      Process each band.                                              */
     /* -------------------------------------------------------------------- */
-        for( i = 0; bPixelReport && i < (int) anBandList.size(); i++ )
+        for( int i = 0; bPixelReport && i < (int) anBandList.size(); i++ )
         {
             GDALRasterBandH hBand = GDALGetRasterBand( hSrcDS, anBandList[i] );
 
@@ -478,17 +476,17 @@ int main( int argc, char ** argv )
             {
                 printf( "  Band %d:\n", anBandList[i] );
             }
-    
+
     /* -------------------------------------------------------------------- */
     /*      Request location info for this location.  It is possible        */
     /*      only the VRT driver actually supports this.                     */
     /* -------------------------------------------------------------------- */
             CPLString osItem;
-            
+
             osItem.Printf( "Pixel_%d_%d", iPixelToQuery, iLineToQuery );
-            
+
             const char *pszLI = GDALGetMetadataItem( hBand, osItem, "LocationInfo");
-    
+
             if( pszLI != NULL )
             {
                 if( bAsXML )
@@ -498,22 +496,20 @@ int main( int argc, char ** argv )
                 else if( bLIFOnly )
                 {
                     /* Extract all files, if any. */
-                 
+
                     CPLXMLNode *psRoot = CPLParseXMLString( pszLI );
-                    
-                    if( psRoot != NULL 
+
+                    if( psRoot != NULL
                         && psRoot->psChild != NULL
                         && psRoot->eType == CXT_Element
                         && EQUAL(psRoot->pszValue,"LocationInfo") )
                     {
-                        CPLXMLNode *psNode;
-    
-                        for( psNode = psRoot->psChild;
+                        for( CPLXMLNode *psNode = psRoot->psChild;
                              psNode != NULL;
                              psNode = psNode->psNext )
                         {
                             if( psNode->eType == CXT_Element
-                                && EQUAL(psNode->pszValue,"File") 
+                                && EQUAL(psNode->pszValue,"File")
                                 && psNode->psChild != NULL )
                             {
                                 char* pszUnescaped = CPLUnescapeString(
@@ -526,22 +522,22 @@ int main( int argc, char ** argv )
                     CPLDestroyXMLNode( psRoot );
                 }
             }
-    
+
     /* -------------------------------------------------------------------- */
     /*      Report the pixel value of this band.                            */
     /* -------------------------------------------------------------------- */
             double adfPixel[2];
-    
-            if( GDALRasterIO( hBand, GF_Read, iPixelToQuery, iLineToQuery, 1, 1, 
+
+            if( GDALRasterIO( hBand, GF_Read, iPixelToQuery, iLineToQuery, 1, 1,
                               adfPixel, 1, 1, GDT_CFloat64, 0, 0) == CE_None )
             {
                 CPLString osValue;
-    
+
                 if( GDALDataTypeIsComplex( GDALGetRasterDataType( hBand ) ) )
                     osValue.Printf( "%.15g+%.15gi", adfPixel[0], adfPixel[1] );
                 else
                     osValue.Printf( "%.15g", adfPixel[0] );
-    
+
                 if( bAsXML )
                 {
                     osXML += "<Value>";
@@ -552,23 +548,39 @@ int main( int argc, char ** argv )
                     printf( "    Value: %s\n", osValue.c_str() );
                 else if( bValOnly )
                     printf( "%s\n", osValue.c_str() );
-    
+
                 // Report unscaled if we have scale/offset values.
                 int bSuccess;
-                
+
                 double dfOffset = GDALGetRasterOffset( hBand, &bSuccess );
+                // TODO: Should we turn on checking of bSuccess?
+                // Alternatively, delete these checks and put a comment as to
+                // why checking bSuccess does not matter.
+#if 0
+                if (bSuccess == FALSE)
+                {
+                    CPLError( CE_Debug, CPLE_AppDefined,
+                              "Unable to get raster offset." );
+                }
+#endif
                 double dfScale  = GDALGetRasterScale( hBand, &bSuccess );
-    
+#if 0
+                if (bSuccess == FALSE)
+                {
+                    CPLError( CE_Debug, CPLE_AppDefined,
+                              "Unable to get raster scale." );
+                }
+#endif
                 if( dfOffset != 0.0 || dfScale != 1.0 )
                 {
                     adfPixel[0] = adfPixel[0] * dfScale + dfOffset;
                     adfPixel[1] = adfPixel[1] * dfScale + dfOffset;
-    
+
                     if( GDALDataTypeIsComplex( GDALGetRasterDataType( hBand ) ) )
                         osValue.Printf( "%.15g+%.15gi", adfPixel[0], adfPixel[1] );
                     else
                         osValue.Printf( "%.15g", adfPixel[0] );
-    
+
                     if( bAsXML )
                     {
                         osXML += "<DescaledValue>";
@@ -579,19 +591,19 @@ int main( int argc, char ** argv )
                         printf( "    Descaled Value: %s\n", osValue.c_str() );
                 }
             }
-    
+
             if( bAsXML )
                 osXML += "</BandReport>";
         }
 
         osXML += "</Report>";
-    
+
         if( (pszLocX != NULL && pszLocY != NULL)  ||
             (fscanf(stdin, "%lf %lf", &dfGeoX, &dfGeoY) != 2) )
         {
             inputAvailable = 0;
         }
-            
+
     }
 
 /* -------------------------------------------------------------------- */
@@ -599,12 +611,8 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
     if( bAsXML )
     {
-        CPLXMLNode *psRoot;
-        char *pszFormattedXML;
-
-
-        psRoot = CPLParseXMLString( osXML );
-        pszFormattedXML = CPLSerializeXMLTree( psRoot );
+        CPLXMLNode *psRoot = CPLParseXMLString( osXML );
+        char *pszFormattedXML = CPLSerializeXMLTree( psRoot );
         CPLDestroyXMLNode( psRoot );
 
         printf( "%s", pszFormattedXML );
diff --git a/apps/gdalmanage.cpp b/apps/gdalmanage.cpp
index aa0b0af..8ab462c 100644
--- a/apps/gdalmanage.cpp
+++ b/apps/gdalmanage.cpp
@@ -1,9 +1,9 @@
 /******************************************************************************
- * $Id: gdalmanage.cpp 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: gdalmanage.cpp 33615 2016-03-02 20:19:22Z goatbar $
  *
  * Project:  GDAL Utilities
- * Purpose:  Commandline utility for GDAL identify, delete, rename and copy 
- *           (by file) operations. 
+ * Purpose:  Command line utility for GDAL identify, delete, rename and copy
+ *           (by file) operations.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  * ****************************************************************************
@@ -33,7 +33,7 @@
 #include "cpl_string.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: gdalmanage.cpp 27044 2014-03-16 23:41:27Z rouault $");
+CPL_CVSID("$Id: gdalmanage.cpp 33615 2016-03-02 20:19:22Z goatbar $");
 
 /************************************************************************/
 /*                               Usage()                                */
@@ -53,8 +53,8 @@ static void Usage()
 /*                       ProcessIdentifyTarget()                        */
 /************************************************************************/
 
-static void ProcessIdentifyTarget( const char *pszTarget, 
-                                   char **papszSiblingList, 
+static void ProcessIdentifyTarget( const char *pszTarget,
+                                   char **papszSiblingList,
                                    int bRecursive, int bReportFailures )
 
 {
@@ -67,26 +67,26 @@ static void ProcessIdentifyTarget( const char *pszTarget,
     if( hDriver != NULL )
         printf( "%s: %s\n", pszTarget, GDALGetDriverShortName( hDriver ) );
     else if( bReportFailures )
-        printf( "%s: unrecognised\n", pszTarget );
+        printf( "%s: unrecognized\n", pszTarget );
 
     if( !bRecursive || hDriver != NULL )
         return;
 
-    if( VSIStatL( pszTarget, &sStatBuf ) != 0 
+    if( VSIStatL( pszTarget, &sStatBuf ) != 0
         || !VSI_ISDIR( sStatBuf.st_mode ) )
         return;
 
     papszSiblingList = VSIReadDir( pszTarget );
     for( i = 0; papszSiblingList && papszSiblingList[i]; i++ )
     {
-        if( EQUAL(papszSiblingList[i],"..") 
+        if( EQUAL(papszSiblingList[i],"..")
             || EQUAL(papszSiblingList[i],".") )
             continue;
 
-        CPLString osSubTarget = 
+        CPLString osSubTarget =
             CPLFormFilename( pszTarget, papszSiblingList[i], NULL );
 
-        ProcessIdentifyTarget( osSubTarget, papszSiblingList, 
+        ProcessIdentifyTarget( osSubTarget, papszSiblingList,
                                bRecursive, bReportFailures );
     }
     CSLDestroy(papszSiblingList);
@@ -100,7 +100,7 @@ static void Identify( int nArgc, char **papszArgv )
 
 {
 /* -------------------------------------------------------------------- */
-/*      Scan for commandline switches                                   */
+/*      Scan for command line switches                                   */
 /* -------------------------------------------------------------------- */
     int bRecursive = FALSE, bReportFailures = FALSE;
 
@@ -122,7 +122,7 @@ static void Identify( int nArgc, char **papszArgv )
 /* -------------------------------------------------------------------- */
     while( nArgc > 0 )
     {
-        ProcessIdentifyTarget( papszArgv[0], NULL, 
+        ProcessIdentifyTarget( papszArgv[0], NULL,
                                bRecursive, bReportFailures );
         nArgc--;
         papszArgv++;
@@ -221,7 +221,7 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
 /*      Split out based on operation.                                   */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(argv[1],"identify",5) )
+    if( STARTS_WITH_CI(argv[1],"ident" /* identify" */ ) )
         Identify( nRemainingArgc, papszRemainingArgv );
 
     else if( EQUAL(argv[1],"copy") )
@@ -229,7 +229,7 @@ int main( int argc, char ** argv )
 
     else if( EQUAL(argv[1],"rename") )
         Copy( hDriver, nRemainingArgc, papszRemainingArgv, "rename" );
-    
+
     else if( EQUAL(argv[1],"delete") )
         Delete( hDriver, nRemainingArgc, papszRemainingArgv );
 
@@ -244,4 +244,3 @@ int main( int argc, char ** argv )
 
     exit( 0 );
 }
-
diff --git a/apps/gdalserver.c b/apps/gdalserver.c
index 20aabb5..326f122 100644
--- a/apps/gdalserver.c
+++ b/apps/gdalserver.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalserver.c 31326 2015-11-02 20:26:23Z rouault $
+ * $Id: gdalserver.c 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Server application that is forked by libgdal
@@ -28,11 +28,17 @@
  ****************************************************************************/
 
 // So that __USE_XOPEN2K is defined to have getaddrinfo
+#ifndef __sun__
 #define _XOPEN_SOURCE 600
+#endif
 
 #include "cpl_port.h"
 
 #ifdef WIN32
+
+  /* To disable 'warning C4996: 'WSADuplicateSocketA': Use WSADuplicateSocketW()' and 'WSASocketA': Use WSASocketW() instead */
+  #define _WINSOCK_DEPRECATED_NO_WARNINGS
+
   #ifdef _WIN32_WINNT
     #undef _WIN32_WINNT
   #endif
@@ -44,6 +50,7 @@
     #define HAVE_GETADDRINFO 1
   #endif
 #else
+  #include <sys/select.h>
   #include <sys/time.h>
   #include <sys/types.h>
   #include <sys/wait.h>
@@ -64,7 +71,7 @@
   #define closesocket(s) close(s)
   #ifndef SOMAXCONN
   #define SOMAXCONN 128
-  #endif 
+  #endif
 #endif
 
 
@@ -75,21 +82,30 @@
 CPL_C_START
 int CPL_DLL GDALServerLoop(CPL_FILE_HANDLE fin, CPL_FILE_HANDLE fout);
 int CPL_DLL GDALServerLoopSocket(CPL_SOCKET nSocket);
+void CPL_DLL* GDALServerLoopInstanceCreateFromSocket(CPL_SOCKET nSocket);
+int  CPL_DLL  GDALServerLoopInstanceRunIteration(void* pInstance);
+void CPL_DLL  GDALServerLoopInstanceDestroy(void* pInstance);
 CPL_C_END
 
-CPL_CVSID("$Id: gdalserver.c 31326 2015-11-02 20:26:23Z rouault $");
+CPL_CVSID("$Id: gdalserver.c 33720 2016-03-15 00:39:53Z goatbar $");
+
+static int bVerbose = FALSE;
 
 /************************************************************************/
 /*                               Usage()                                */
 /************************************************************************/
 
-void Usage(const char* pszErrorMsg)
+static void Usage(const char* pszErrorMsg)
 
 {
 #ifdef WIN32
-    printf( "Usage: gdalserver [--help-general] [--help] [-tcpserver port | -stdinout]\n");
+    printf( "Usage: gdalserver [--help-general] [--help] [-v]\n");
+    printf( "                  [-tcpserver port | -stdinout]\n");
 #else
-    printf( "Usage: gdalserver [--help-general] [--help] [-tcpserver port | -unixserver filename | -stdinout | [-pipe_in fdin,fdtoclose -pipe_out fdout,fdtoclose]]\n");
+    printf( "Usage: gdalserver [--help-general] [--help] [-v]\n");
+    printf( "                  [-tcpserver port | -unixserver filename | -stdinout | \n");
+    printf( "                  [-pipe_in fdin,fdtoclose -pipe_out fdout,fdtoclose]]\n");
+    printf( "                  [-nofork]\n");
 #endif
     printf( "\n" );
     printf( "-tcpserver : Launch a TCP server on the specified port that can accept.\n");
@@ -99,7 +115,11 @@ void Usage(const char* pszErrorMsg)
 #ifndef WIN32
     printf( "-pipe_in/out:This mode is not meant at being directly used by a user.\n");
     printf( "             It is a helper utility for the client/server working of GDAL.\n");
+    printf( "-nofork     :This mode enables sharing of datasets among several clients,\n");
+    printf( "             for example in concurrent write scenarios. But in that mode,\n");
+    printf( "             only one thread is used, reducing scalability and client isolation.\n");
 #endif
+    printf("\n");
 
     if( pszErrorMsg != NULL )
         fprintf(stderr, "\nFAILURE: %s\n", pszErrorMsg);
@@ -112,7 +132,7 @@ void Usage(const char* pszErrorMsg)
 /*                CreateSocketAndBindAndListen()                        */
 /************************************************************************/
 
-int CreateSocketAndBindAndListen(const char* pszService,
+static CPL_SOCKET CreateSocketAndBindAndListen(const char* pszService,
                                  int *pnFamily,
                                  int *pnSockType,
                                  int *pnProtocol)
@@ -147,7 +167,7 @@ int CreateSocketAndBindAndListen(const char* pszService,
             continue;
 
         if (bind(nListenSocket, psResultsIter->ai_addr,
-                 psResultsIter->ai_addrlen) != SOCKET_ERROR)
+                 (int)psResultsIter->ai_addrlen) != (int)SOCKET_ERROR)
         {
             if( pnFamily )   *pnFamily =   psResultsIter->ai_family;
             if( pnSockType ) *pnSockType = psResultsIter->ai_socktype;
@@ -211,9 +231,11 @@ int CreateSocketAndBindAndListen(const char* pszService,
 /*                             RunServer()                              */
 /************************************************************************/
 
+static
 int RunServer(const char* pszApplication,
               const char* pszService,
-              const char* unused_pszUnixSocketFilename)
+              CPL_UNUSED const char* unused_pszUnixSocketFilename,
+              CPL_UNUSED int bFork)
 {
     int nRet;
     WSADATA wsaData;
@@ -242,14 +264,14 @@ int RunServer(const char* pszApplication,
         CPLSpawnedProcess* psProcess;
         CPL_FILE_HANDLE fin, fout;
         CPL_PID nPid;
-        SOCKET nConnSocket;
+        CPL_SOCKET nConnSocket;
         char szReady[5];
         int bOK = TRUE;
         const char* apszArgs[] = { NULL, "-newconnection", NULL };
 
         apszArgs[0] = pszApplication;
         nConnSocket = accept(nListenSocket, &sockAddr, &nLen);
-        if( nConnSocket == SOCKET_ERROR )
+        if( nConnSocket == (CPL_SOCKET)SOCKET_ERROR )
         {
             fprintf(stderr, "accept() function failed with error: %d\n", WSAGetLastError());
             closesocket(nListenSocket);
@@ -323,6 +345,7 @@ int RunServer(const char* pszApplication,
 /*                          RunNewConnection()                          */
 /************************************************************************/
 
+static
 int RunNewConnection()
 {
     int nRet;
@@ -372,7 +395,7 @@ int RunNewConnection()
 #endif
     nRet = GDALServerLoopSocket(nConnSocket);
 #ifdef _MSC_VER
-    } __except(1) 
+    } __except(1)
     {
         fprintf(stderr, "gdalserver exited with a fatal error.\n");
         nRet = 1;
@@ -391,11 +414,28 @@ int RunNewConnection()
 /*                             RunServer()                              */
 /************************************************************************/
 
-int RunServer(CPL_UNUSED const char* pszApplication,
+typedef struct
+{
+    int nSocket;
+    void* hSrvLoopInstance;
+} ClientInfo;
+
+#define MAX_CLIENTS 100
+
+static int RunServer(CPL_UNUSED const char* pszApplication,
               const char* pszService,
-              const char* pszUnixSocketFilename)
+              const char* pszUnixSocketFilename,
+              int bFork)
 {
     int nListenSocket;
+    int i;
+    int nClients = 0;
+    ClientInfo asClientInfos[MAX_CLIENTS];
+
+    memset( asClientInfos, 0, sizeof(asClientInfos) );
+
+    if( !bFork )
+        signal(SIGPIPE, SIG_IGN);
 
     if( pszUnixSocketFilename != NULL )
     {
@@ -412,7 +452,7 @@ int RunServer(CPL_UNUSED const char* pszApplication,
         sockAddrUnix.sun_family = AF_UNIX;
         CPLStrlcpy(sockAddrUnix.sun_path, pszUnixSocketFilename, sizeof(sockAddrUnix.sun_path));
         unlink(sockAddrUnix.sun_path);
-        len = strlen(sockAddrUnix.sun_path) + sizeof(sockAddrUnix.sun_family);
+        len = (int)(strlen(sockAddrUnix.sun_path) + sizeof(sockAddrUnix.sun_family));
         if (bind(nListenSocket, (struct sockaddr *)&sockAddrUnix, len) == -1)
         {
             perror("bind");
@@ -439,50 +479,111 @@ int RunServer(CPL_UNUSED const char* pszApplication,
     {
         struct sockaddr sockAddr;
         socklen_t nLen = sizeof(sockAddr);
-        int nConnSocket;
         pid_t pid;
         int nStatus;
         struct timeval tv;
         fd_set read_fds;
+        int nMaxSocket;
 
         /* Select on the listen socket, and rip zombie children every second */
         do
         {
+            nMaxSocket = nListenSocket;
             FD_ZERO(&read_fds);
             FD_SET(nListenSocket, &read_fds);
+            for(i=0;i<nClients;i++)
+            {
+                FD_SET(asClientInfos[i].nSocket, &read_fds);
+                if(asClientInfos[i].nSocket > nMaxSocket )
+                    nMaxSocket = asClientInfos[i].nSocket;
+            }
             tv.tv_sec = 1;
             tv.tv_usec = 0;
             waitpid(-1, &nStatus, WNOHANG);
         }
-        while( select(nListenSocket + 1, &read_fds, NULL, NULL, &tv) != 1 );
+        while( select(nMaxSocket + 1, &read_fds, NULL, NULL, &tv) < 1 );
 
-        nConnSocket = accept(nListenSocket, &sockAddr, &nLen);
-        if( nConnSocket < 0 )
+        if( bFork )
         {
-            fprintf(stderr, "accept() function failed with error: %d\n", errno);
-            close(nListenSocket);
-            return 1;
-        }
-
-        pid = fork();
-        if( pid < 0 )
-        {
-            fprintf(stderr, "fork() failed: %d\n", errno);
-            close(nListenSocket);
-            close(nConnSocket);
-            return 1;
-        }
-        else if( pid == 0 )
-        {
-            int nRet;
-            close(nListenSocket);
-            nRet = GDALServerLoopSocket(nConnSocket);
-            close(nConnSocket);
-            return nRet;
+            int nConnSocket = accept(nListenSocket, &sockAddr, &nLen);
+            if( nConnSocket < 0 )
+            {
+                fprintf(stderr, "accept() function failed with error: %d\n", errno);
+                close(nListenSocket);
+                return 1;
+            }
+
+            pid = fork();
+            if( pid < 0 )
+            {
+                fprintf(stderr, "fork() failed: %d\n", errno);
+                close(nListenSocket);
+                close(nConnSocket);
+                return 1;
+            }
+            else if( pid == 0 )
+            {
+                int nRet;
+                close(nListenSocket);
+                nRet = GDALServerLoopSocket(nConnSocket);
+                close(nConnSocket);
+                return nRet;
+            }
+            else
+            {
+                close(nConnSocket);
+            }
         }
         else
         {
-            close(nConnSocket);
+            if( FD_ISSET(nListenSocket, &read_fds) )
+            {
+                int nConnSocket;
+                nConnSocket = accept(nListenSocket, &sockAddr, &nLen);
+                if( nConnSocket < 0 )
+                {
+                    fprintf(stderr, "accept() function failed with error: %d\n", errno);
+                }
+                else
+                {
+                    if( nClients == MAX_CLIENTS  )
+                    {
+                        fprintf(stderr, "Refusing new connection: too many clients (%d)\n",
+                                MAX_CLIENTS);
+                        close(nConnSocket);
+                    }
+                    else
+                    {
+                        void* hSrvLoopInstance = GDALServerLoopInstanceCreateFromSocket(nConnSocket);
+                        asClientInfos[nClients].nSocket = nConnSocket;
+                        asClientInfos[nClients].hSrvLoopInstance = hSrvLoopInstance;
+                        if( bVerbose )
+                            fprintf(stderr, "Accepting new client %d\n", nClients);
+                        nClients ++;
+                    }
+                }
+            }
+            for(i=0;i<nClients;)
+            {
+                if( FD_ISSET(asClientInfos[i].nSocket, &read_fds) )
+                {
+                    //fprintf(stderr, "receiving info from client %d\n", i);
+                    if( !GDALServerLoopInstanceRunIteration(asClientInfos[i].hSrvLoopInstance) )
+                    {
+                        if( bVerbose )
+                            fprintf(stderr, "Removing client %d\n", i);
+                        GDALServerLoopInstanceDestroy(asClientInfos[i].hSrvLoopInstance);
+                        close(asClientInfos[i].nSocket);
+                        memmove(asClientInfos + i, asClientInfos + i + 1,
+                                (nClients - 1 - i) * sizeof(ClientInfo));
+                        nClients --;
+                        if( nClients == 0 && bVerbose )
+                            fprintf(stderr, "No more clients. Server can be safely shut down\n");
+                        continue;
+                    }
+                }
+                i++;
+            }
         }
     }
 }
@@ -505,6 +606,7 @@ int main(int argc, char* argv[])
     int pipe_in = fileno(stdin);
     int pipe_out = fileno(stdout);
 #endif
+    int bFork = TRUE;
     /*for( i = 1; i < argc; i++ )
     {
         if( EQUAL(argv[i], "-daemonize") )
@@ -575,9 +677,15 @@ int main(int argc, char* argv[])
             if( pszComma )
                 close(atoi(pszComma + 1));
         }
+        else if( EQUAL(argv[i],"-nofork") )
+        {
+            bFork = FALSE;
+        }
 #endif
         else if( EQUAL(argv[i], "-daemonize") )
             ;
+        else if( EQUAL(argv[i], "-v") )
+            bVerbose = TRUE;
         else if( argv[i][0] == '-' )
             Usage(CPLSPrintf("Unknown option name '%s'", argv[i]));
         else
@@ -588,7 +696,7 @@ int main(int argc, char* argv[])
         Usage(NULL);
 
     if( pszService != NULL || pszUnixSocketFilename != NULL )
-        nRet = RunServer(argv[0], pszService, pszUnixSocketFilename);
+        nRet = RunServer(argv[0], pszService, pszUnixSocketFilename, bFork);
 #ifdef WIN32
     else if( bNewConnection )
         nRet = RunNewConnection();
@@ -598,20 +706,22 @@ int main(int argc, char* argv[])
     {
 #ifdef WIN32
 #ifdef _MSC_VER
-    __try 
+    __try
 #endif
-    { 
+    {
         nRet = GDALServerLoop(GetStdHandle(STD_INPUT_HANDLE),
                               GetStdHandle(STD_OUTPUT_HANDLE));
     }
 #ifdef _MSC_VER
-    __except(1) 
+    __except(1)
     {
         fprintf(stderr, "gdalserver exited with a fatal error.\n");
         nRet = 1;
     }
 #endif
 #else
+    if( !bFork )
+        fprintf(stderr, "-nofork option incompatible with direct pipe specification.\n");
     nRet = GDALServerLoop(pipe_in, pipe_out);
 #endif
     }
diff --git a/apps/gdalsrsinfo.cpp b/apps/gdalsrsinfo.cpp
index 0a2fc08..db094be 100644
--- a/apps/gdalsrsinfo.cpp
+++ b/apps/gdalsrsinfo.cpp
@@ -2,10 +2,10 @@
  * $Id$
  *
  * Project:  GDAL Utilities
- * Purpose:  Commandline application to list info about a given CRS.
+ * Purpose:  Command line application to list info about a given CRS.
  *           Outputs a number of formats (WKT, PROJ.4, etc.).
  * Author:   Frank Warmerdam, warmerdam at pobox.com
- *           Etienne Tourigny, etourigny.dev-at-gmail-dot-com       
+ *           Etienne Tourigny, etourigny.dev-at-gmail-dot-com
  *
  * ****************************************************************************
  * Copyright (c) 1998, Frank Warmerdam
@@ -39,11 +39,11 @@
 
 CPL_CVSID("$Id$");
 
-int FindSRS( const char *pszInput, OGRSpatialReference &oSRS );
-CPLErr PrintSRS( const OGRSpatialReference &oSRS, 
-                 const char * pszOutputType, 
-                 int bPretty, int bPrintSep );
-void PrintSRSOutputTypes( const OGRSpatialReference &oSRS, 
+bool FindSRS( const char *pszInput, OGRSpatialReference &oSRS );
+CPLErr PrintSRS( const OGRSpatialReference &oSRS,
+                 const char * pszOutputType,
+                 bool bPretty, bool bPrintSep );
+void PrintSRSOutputTypes( const OGRSpatialReference &oSRS,
                           const char ** papszOutputTypes );
 int FindEPSG( const OGRSpatialReference &oSRS );
 int SearchCSVForWKT( const char *pszFileCSV, const char *pszTarget );
@@ -52,7 +52,7 @@ int SearchCSVForWKT( const char *pszFileCSV, const char *pszTarget );
 /*                               Usage()                                */
 /************************************************************************/
 
-void Usage(const char* pszErrorMsg = NULL)
+static void Usage(const char* pszErrorMsg = NULL)
 
 {
     printf( "\nUsage: gdalsrsinfo [options] srs_def\n"
@@ -61,7 +61,7 @@ void Usage(const char* pszErrorMsg = NULL)
             "from which to extract SRS information\n"
             "OR any of the usual GDAL/OGR forms "
             "(complete WKT, PROJ.4, EPSG:n or a file containing the SRS)\n"
-            "\n"          
+            "\n"
             "Options: \n"
             "   [--help-general] [-h]  Show help and exit\n"
             "   [-p]                   Pretty-print where applicable (e.g. WKT)\n"
@@ -70,7 +70,7 @@ void Usage(const char* pszErrorMsg = NULL)
             "   [-o out_type]          Output type { default, all, wkt_all,\n"
             "                                        proj4, epsg,\n"
             "                                        wkt, wkt_simple, wkt_noct, wkt_esri,\n"
-            "                                        mapinfo, xml }\n\n" ); 
+            "                                        mapinfo, xml }\n\n" );
 
     if( pszErrorMsg != NULL )
         fprintf(stderr, "\nFAILURE: %s\n", pszErrorMsg);
@@ -87,14 +87,13 @@ void Usage(const char* pszErrorMsg = NULL)
     do { if (i + nExtraArg >= argc) \
         Usage(CPLSPrintf("%s option requires %d argument(s)", argv[i], nExtraArg)); } while(0)
 
-int main( int argc, char ** argv ) 
+int main( int argc, char ** argv )
 
 {
-    int            i;
-    int            bGotSRS = FALSE;
-    int            bPretty = FALSE;
-    int            bValidate = FALSE;
-    int            bFindEPSG = FALSE;
+    bool bGotSRS = false;
+    bool bPretty = false;
+    bool bValidate = false;
+    bool bFindEPSG = false;
     int            nEPSGCode = -1;
     const char     *pszInput = NULL;
     const char     *pszOutputType = "default";
@@ -110,9 +109,6 @@ int main( int argc, char ** argv )
 /*      Register standard GDAL and OGR drivers.                         */
 /* -------------------------------------------------------------------- */
     GDALAllRegister();
-#ifdef OGR_ENABLED
-    OGRRegisterAll();
-#endif
 
 /* -------------------------------------------------------------------- */
 /*      Register standard GDAL drivers, and process generic GDAL        */
@@ -125,7 +121,7 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
 /*      Parse arguments.                                                */
 /* -------------------------------------------------------------------- */
-    for( i = 1; i < argc; i++ )
+    for( int i = 1; i < argc; i++ )
     {
         CPLDebug( "gdalsrsinfo", "got arg #%d : [%s]", i, argv[i] );
 
@@ -133,26 +129,27 @@ int main( int argc, char ** argv )
         {
             printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
                    argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
+            CSLDestroy( argv );
             return 0;
         }
         else if( EQUAL(argv[i], "-h") || EQUAL(argv[i], "--help") )
             Usage();
         else if( EQUAL(argv[i], "-e") )
-            bFindEPSG = TRUE;
+            bFindEPSG = true;
         else if( EQUAL(argv[i], "-o") )
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
             pszOutputType = argv[++i];
         }
         else if( EQUAL(argv[i], "-p") )
-            bPretty = TRUE;
+            bPretty = true;
         else if( EQUAL(argv[i], "-V") )
-            bValidate = TRUE;
+            bValidate = true;
         else if( argv[i][0] == '-' )
         {
             Usage(CPLSPrintf("Unknown option name '%s'", argv[i]));
         }
-        else  
+        else
             pszInput = argv[i];
     }
 
@@ -162,12 +159,15 @@ int main( int argc, char ** argv )
     }
 
     /* Search for SRS */
-    bGotSRS = FindSRS( pszInput, oSRS );
+    /* coverity[tainted_data] */
+    bGotSRS = FindSRS( pszInput, oSRS ) == TRUE;
 
-    CPLDebug( "gdalsrsinfo", 
+    CPLDebug( "gdalsrsinfo",
               "bGotSRS: %d bValidate: %d pszOutputType: %s bPretty: %d",
-              bGotSRS, bValidate, pszOutputType, bPretty  );
-      
+              static_cast<int>(bGotSRS),
+              static_cast<int>(bValidate),
+              pszOutputType,
+              static_cast<int>(bPretty) );
 
     /* Make sure we got a SRS */
     if ( ! bGotSRS ) {
@@ -180,14 +180,14 @@ int main( int argc, char ** argv )
 
         /* Find EPSG code - experimental */
         if ( EQUAL(pszOutputType,"epsg") )
-            bFindEPSG = TRUE;
+            bFindEPSG = true;
         if ( bFindEPSG ) {
             CPLError( CE_Warning, CPLE_AppDefined,
                       "EPSG detection is experimental and requires new data files (see bug #4345)" );
             nEPSGCode = FindEPSG( oSRS );
             /* If found, replace oSRS based on EPSG code */
             if(nEPSGCode != -1) {
-                CPLDebug( "gdalsrsinfo", 
+                CPLDebug( "gdalsrsinfo",
                           "Found EPSG code %d", nEPSGCode );
                 OGRSpatialReference oSRS2;
                 if ( oSRS2.importFromEPSG( nEPSGCode ) == OGRERR_NONE )
@@ -208,25 +208,25 @@ int main( int argc, char ** argv )
             else
                 printf( "\nValidate Succeeds\n" );
         }
-        
+
         /* Output */
         if ( EQUAL("default", pszOutputType ) ) {
             /* does this work in MSVC? */
-            const char* papszOutputTypes[] = 
-                { "proj4", "wkt", NULL };      
-            if ( bFindEPSG ) 
+            const char* papszOutputTypes[] =
+                { "proj4", "wkt", NULL };
+            if ( bFindEPSG )
                 printf("\nEPSG:%d\n",nEPSGCode);
             PrintSRSOutputTypes( oSRS, papszOutputTypes );
         }
         else if ( EQUAL("all", pszOutputType ) ) {
-            if ( bFindEPSG ) 
+            if ( bFindEPSG )
                 printf("\nEPSG:%d\n\n",nEPSGCode);
-            const char* papszOutputTypes[] = 
+            const char* papszOutputTypes[] =
                 {"proj4","wkt","wkt_simple","wkt_noct","wkt_esri","mapinfo","xml",NULL};
             PrintSRSOutputTypes( oSRS, papszOutputTypes );
         }
         else if ( EQUAL("wkt_all", pszOutputType ) ) {
-            const char* papszOutputTypes[] = 
+            const char* papszOutputTypes[] =
                 { "wkt", "wkt_simple", "wkt_noct", "wkt_esri", NULL };
             PrintSRSOutputTypes( oSRS, papszOutputTypes );
         }
@@ -238,16 +238,13 @@ int main( int argc, char ** argv )
             else
                 PrintSRS( oSRS, pszOutputType, bPretty, FALSE );
             if ( bPretty )
-                printf( "\n" );        
+                printf( "\n" );
         }
-
     }
 
     /* cleanup anything left */
     GDALDestroyDriverManager();
-#ifdef OGR_ENABLED
     OGRCleanupAll();
-#endif
     CSLDestroy( argv );
 
     return 0;
@@ -258,36 +255,32 @@ int main( int argc, char ** argv )
 /*                                                                      */
 /*      Search for SRS from pszInput, update oSRS.                      */
 /************************************************************************/
-int FindSRS( const char *pszInput, OGRSpatialReference &oSRS )
+bool FindSRS( const char *pszInput, OGRSpatialReference &oSRS )
 
 {
-    int            bGotSRS = FALSE;
-    VSILFILE      *fp = NULL;
-    GDALDataset	  *poGDALDS = NULL; 
+    bool bGotSRS = false;
+    GDALDataset *poGDALDS = NULL;
     OGRLayer      *poLayer = NULL;
     const char    *pszProjection = NULL;
     CPLErrorHandler oErrorHandler = NULL;
-    int bIsFile = FALSE;
-    OGRErr eErr = CE_None;
-    int bDebug  = FALSE;
+    bool bIsFile = false;
+    OGRErr eErr = OGRERR_NONE;
 
     /* temporarily suppress error messages we may get from xOpen() */
-    bDebug = CSLTestBoolean(CPLGetConfigOption("CPL_DEBUG", "OFF"));
-    if ( ! bDebug )
+    bool bDebug = CPLTestBool(CPLGetConfigOption("CPL_DEBUG", "OFF"));
+    if( !bDebug )
         oErrorHandler = CPLSetErrorHandler ( CPLQuietErrorHandler );
 
     /* Test if argument is a file */
-    fp = VSIFOpenL( pszInput, "r" );
+    VSILFILE *fp = VSIFOpenL( pszInput, "r" );
     if ( fp )  {
-        bIsFile = TRUE;
+        bIsFile = true;
         VSIFCloseL( fp );
         CPLDebug( "gdalsrsinfo", "argument is a file" );
-    } 
-       
+    }
+
     /* try to open with GDAL */
-    if( strncmp(pszInput, "http://spatialreference.org/",
-                strlen("http://spatialreference.org/")) != 0 )
-    {
+    if( !STARTS_WITH(pszInput, "http://spatialreference.org/") )    {
         CPLDebug( "gdalsrsinfo", "trying to open with GDAL" );
         poGDALDS = (GDALDataset *) GDALOpenEx( pszInput, 0, NULL, NULL, NULL );
     }
@@ -296,9 +289,9 @@ int FindSRS( const char *pszInput, OGRSpatialReference &oSRS )
         if( pszProjection != NULL && pszProjection[0] != '\0' )
         {
             char* pszProjectionTmp = (char*) pszProjection;
-            if( oSRS.importFromWkt( &pszProjectionTmp ) == CE_None ) {
+            if( oSRS.importFromWkt( &pszProjectionTmp ) == OGRERR_NONE ) {
                 CPLDebug( "gdalsrsinfo", "got SRS from GDAL" );
-                bGotSRS = TRUE;
+                bGotSRS = true;
             }
         }
         else if( poGDALDS->GetLayerCount() > 0 )
@@ -308,7 +301,7 @@ int FindSRS( const char *pszInput, OGRSpatialReference &oSRS )
                 OGRSpatialReference *poSRS = poLayer->GetSpatialRef( );
                 if ( poSRS != NULL ) {
                     CPLDebug( "gdalsrsinfo", "got SRS from OGR" );
-                    bGotSRS = TRUE;
+                    bGotSRS = true;
                     OGRSpatialReference* poSRSClone = poSRS->Clone();
                     oSRS = *poSRSClone;
                     OGRSpatialReference::DestroySpatialReference( poSRSClone );
@@ -316,26 +309,26 @@ int FindSRS( const char *pszInput, OGRSpatialReference &oSRS )
             }
         }
         GDALClose( (GDALDatasetH) poGDALDS );
-        if ( ! bGotSRS ) 
+        if ( ! bGotSRS )
             CPLDebug( "gdalsrsinfo", "did not open with GDAL" );
-    }    
-    
+    }
+
     /* Try ESRI file */
     if ( ! bGotSRS && bIsFile && (strstr(pszInput,".prj") != NULL) ) {
-        CPLDebug( "gdalsrsinfo", 
+        CPLDebug( "gdalsrsinfo",
                   "trying to get SRS from ESRI .prj file [%s]", pszInput );
 
         char **pszTemp;
         if ( strstr(pszInput,"ESRI::") != NULL )
             pszTemp = CSLLoad( pszInput+6 );
-        else 
+        else
             pszTemp = CSLLoad( pszInput );
 
         if( pszTemp ) {
             eErr = oSRS.importFromESRI( pszTemp );
             CSLDestroy( pszTemp );
         }
-        else 
+        else
             eErr = OGRERR_UNSUPPORTED_SRS;
 
         if( eErr != OGRERR_NONE ) {
@@ -343,29 +336,29 @@ int FindSRS( const char *pszInput, OGRSpatialReference &oSRS )
         }
         else {
             CPLDebug( "gdalsrsinfo", "got SRS from ESRI .prj file" );
-            bGotSRS = TRUE;
+            bGotSRS = true;
         }
     }
 
     /* Last resort, try OSRSetFromUserInput() */
     if ( ! bGotSRS ) {
-        CPLDebug( "gdalsrsinfo", 
+        CPLDebug( "gdalsrsinfo",
                   "trying to get SRS from user input [%s]", pszInput );
 
         eErr = oSRS.SetFromUserInput( pszInput );
- 
+
        if(  eErr != OGRERR_NONE ) {
             CPLDebug( "gdalsrsinfo", "did not get SRS from user input" );
         }
         else {
             CPLDebug( "gdalsrsinfo", "got SRS from user input" );
-            bGotSRS = TRUE;
+            bGotSRS = true;
         }
     }
-    
+
     /* restore error messages */
-    if ( ! bDebug )
-        CPLSetErrorHandler ( oErrorHandler );	
+    if( !bDebug )
+        CPLSetErrorHandler ( oErrorHandler );
 
 
     return bGotSRS;
@@ -377,17 +370,18 @@ int FindSRS( const char *pszInput, OGRSpatialReference &oSRS )
 /*                                                                      */
 /*      Print spatial reference in specified format.                    */
 /************************************************************************/
-CPLErr PrintSRS( const OGRSpatialReference &oSRS, 
-                 const char * pszOutputType, 
-                 int bPretty, int bPrintSep )
+CPLErr PrintSRS( const OGRSpatialReference &oSRS,
+                 const char * pszOutputType,
+                 bool bPretty, bool bPrintSep )
 
 {
     if ( ! pszOutputType || EQUAL(pszOutputType,""))
         return CE_None;
 
     CPLDebug( "gdalsrsinfo", "PrintSRS( oSRS, %s, %d, %d )\n",
-              pszOutputType, bPretty, bPrintSep );
-    
+              pszOutputType, static_cast<int>(bPretty),
+              static_cast<int>(bPrintSep) );
+
     char *pszOutput = NULL;
 
     if ( EQUAL("proj4", pszOutputType ) ) {
@@ -398,49 +392,49 @@ CPLErr PrintSRS( const OGRSpatialReference &oSRS,
 
     else if ( EQUAL("wkt", pszOutputType ) ) {
         if ( bPrintSep ) printf("OGC WKT :\n");
-        if ( bPretty ) 
+        if ( bPretty )
             oSRS.exportToPrettyWkt( &pszOutput, FALSE );
         else
             oSRS.exportToWkt( &pszOutput );
         printf("%s\n",pszOutput);
     }
-        
+
     else if (  EQUAL("wkt_simple", pszOutputType ) ) {
         if ( bPrintSep ) printf("OGC WKT (simple) :\n");
         oSRS.exportToPrettyWkt( &pszOutput, TRUE );
         printf("%s\n",pszOutput);
     }
-        
+
     else if ( EQUAL("wkt_noct", pszOutputType ) ) {
         if (  bPrintSep ) printf("OGC WKT (no CT) :\n");
         OGRSpatialReference *poSRS = oSRS.Clone();
         poSRS->StripCTParms( );
-        if ( bPretty ) 
+        if ( bPretty )
             poSRS->exportToPrettyWkt( &pszOutput, FALSE );
         else
             poSRS->exportToWkt( &pszOutput );
         OGRSpatialReference::DestroySpatialReference( poSRS );
         printf("%s\n",pszOutput);
     }
-        
+
     else if ( EQUAL("wkt_esri", pszOutputType ) ) {
         if ( bPrintSep ) printf("ESRI WKT :\n");
         OGRSpatialReference *poSRS = oSRS.Clone();
         poSRS->morphToESRI( );
-        if ( bPretty ) 
+        if ( bPretty )
             poSRS->exportToPrettyWkt( &pszOutput, FALSE );
         else
             poSRS->exportToWkt( &pszOutput );
         OGRSpatialReference::DestroySpatialReference( poSRS );
         printf("%s\n",pszOutput);
     }
-        
+
     else if ( EQUAL("mapinfo", pszOutputType ) ) {
         if ( bPrintSep ) printf("MAPINFO : ");
         oSRS.exportToMICoordSys( &pszOutput );
         printf("\'%s\'\n",pszOutput);
     }
-        
+
     else if ( EQUAL("xml", pszOutputType ) ) {
         if ( bPrintSep ) printf("XML :\n");
         oSRS.exportToXML( &pszOutput, NULL );
@@ -455,7 +449,7 @@ CPLErr PrintSRS( const OGRSpatialReference &oSRS,
     }
 
     CPLFree( pszOutput );
-    
+
     return CE_None;
 }
 
@@ -464,15 +458,15 @@ CPLErr PrintSRS( const OGRSpatialReference &oSRS,
 /*                                                                      */
 /*      Print spatial reference in specified formats.                   */
 /************************************************************************/
-void PrintSRSOutputTypes( const OGRSpatialReference &oSRS, 
+void PrintSRSOutputTypes( const OGRSpatialReference &oSRS,
                           const char ** papszOutputTypes )
-    
+
 {
     int nOutputTypes = CSLCount((char**)papszOutputTypes);
     printf( "\n" );
     for ( int i=0; i<nOutputTypes; i++ ) {
-        PrintSRS( oSRS, papszOutputTypes[i], TRUE, TRUE );
-        printf( "\n" );        
+        PrintSRS( oSRS, papszOutputTypes[i], true, true );
+        printf( "\n" );
     }
 }
 
@@ -496,7 +490,7 @@ int SearchCSVForWKT( const char *pszFileCSV, const char *pszTarget )
     int nCode = 0;
     int nFound = -1;
 
-    CPLDebug( "gdalsrsinfo", 
+    CPLDebug( "gdalsrsinfo",
               "SearchCSVForWKT()\nfile=%s\nWKT=%s\n",
               pszFileCSV, pszTarget);
 
@@ -515,15 +509,15 @@ int SearchCSVForWKT( const char *pszFileCSV, const char *pszTarget )
 
     /* support gzipped file */
     if ( strstr( pszFileCSV,".gz") != NULL )
-        sprintf( szTemp, "/vsigzip/%s", pszFilename);
+        snprintf( szTemp, sizeof(szTemp), "/vsigzip/%s", pszFilename);
     else
-        sprintf( szTemp, "%s", pszFilename);
+        snprintf( szTemp, sizeof(szTemp), "%s", pszFilename);
 
     CPLDebug( "gdalsrsinfo", "SearchCSVForWKT() using file %s",
               szTemp );
 
     fp = VSIFOpenL( szTemp, "r" );
-    if( fp == NULL ) 
+    if( fp == NULL )
     {
         CPLDebug( "gdalsrsinfo", "could not open support file %s",
                   pszFilename );
@@ -546,7 +540,7 @@ int SearchCSVForWKT( const char *pszFileCSV, const char *pszTarget )
             continue;
             /* do nothing */;
 
-        // else if( EQUALN(pszLine,"include ",8) )
+        // else if( STARTS_WITH_CI(pszLine, "include ") )
         // {
         //     eErr = importFromDict( pszLine + 8, pszCode );
         //     if( eErr != OGRERR_UNSUPPORTED_SRS )
@@ -559,18 +553,18 @@ int SearchCSVForWKT( const char *pszFileCSV, const char *pszTarget )
         pszTemp = strstr(pszLine,",");
         if (pszTemp)
         {
-            nPos = pszTemp - pszLine;
+            nPos = static_cast<int>(pszTemp - pszLine);
 
             if ( nPos == 0 )
                 continue;
-            
+
             strncpy( szTemp, pszLine, nPos );
             szTemp[nPos] = '\0';
             nCode = atoi(szTemp);
 
             pszWKT = (char *) pszLine + nPos +1;
 
-            // CPLDebug( "gdalsrsinfo", 
+            // CPLDebug( "gdalsrsinfo",
             //           "code=%d\nWKT=\n[%s]\ntarget=\n[%s]\n",
             //           nCode,pszWKT, pszTarget );
 
@@ -584,15 +578,15 @@ int SearchCSVForWKT( const char *pszFileCSV, const char *pszTarget )
             }
         }
     }
-    
+
     VSIFCloseL( fp );
 
     return nFound;
 
 }
 
-/* TODO 
-   - search for well-known values (AutoIdentifyEPSG()) 
+/* TODO
+   - search for well-known values (AutoIdentifyEPSG())
 
    - should we search .override.csv files?
 
@@ -615,9 +609,8 @@ int FindEPSG( const OGRSpatialReference &oSRS )
 {
     char *pszWKT = NULL;
     char *pszESRI = NULL;
-    int nFound = -1;
     OGRSpatialReference *poSRS = NULL;
- 
+
     poSRS = oSRS.Clone();
     poSRS->StripCTParms();
     poSRS->exportToWkt( &pszWKT );
@@ -633,15 +626,14 @@ int FindEPSG( const OGRSpatialReference &oSRS )
 
     /* search for EPSG code in epsg_*.wkt.gz files */
     /* using ESRI WKT for now, as it seems to work best */
-    nFound = SearchCSVForWKT( "epsg_esri.wkt.gz", pszESRI );
+    int nFound = SearchCSVForWKT( "epsg_esri.wkt.gz", pszESRI );
     if ( nFound == -1 )
         nFound = SearchCSVForWKT( "epsg_ogc_simple.wkt.gz", pszESRI );
     if ( nFound == -1 )
         nFound = SearchCSVForWKT( "epsg_ogc.wkt.gz", pszESRI );
 
-    
     CPLFree( pszWKT );
-    CPLFree( pszESRI );    
-    
+    CPLFree( pszESRI );
+
     return nFound;
 }
diff --git a/apps/gdaltindex.c b/apps/gdaltindex.c
index 1810d59..ecac776 100644
--- a/apps/gdaltindex.c
+++ b/apps/gdaltindex.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaltindex.c 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: gdaltindex.c 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  MapServer
  * Purpose:  Commandline App to build tile index for raster files.
@@ -35,7 +35,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: gdaltindex.c 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: gdaltindex.c 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /*                               Usage()                                */
@@ -44,18 +44,18 @@ CPL_CVSID("$Id: gdaltindex.c 28375 2015-01-30 12:06:11Z rouault $");
 static void Usage(const char* pszErrorMsg)
 
 {
-    fprintf(stdout, "%s", 
+    fprintf(stdout, "%s",
             "\n"
             "Usage: gdaltindex [-f format] [-tileindex field_name] [-write_absolute_path] \n"
             "                  [-skip_different_projection] [-t_srs target_srs]\n"
             "                  [-src_srs_name field_name] [-src_srs_format [AUTO|WKT|EPSG|PROJ]\n"
             "                  [-lyr_name name] index_file [gdal_file]*\n"
             "\n"
-            "eg.\n"
-            "  % gdaltindex doq_index.shp doq/*.tif\n" 
+            "e.g.\n"
+            "  % gdaltindex doq_index.shp doq/*.tif\n"
             "\n"
             "NOTES:\n"
-            "  o The shapefile (index_file) will be created if it doesn't already exist.\n" 
+            "  o The shapefile (index_file) will be created if it doesn't already exist.\n"
             "  o The default tile index field is 'location'.\n"
             "  o Raster filenames will be put in the file exactly as they are specified\n"
             "    on the commandline unless the option -write_absolute_path is used.\n"
@@ -141,6 +141,7 @@ int main(int argc, char *argv[])
         {
             printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
                    argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
+            CSLDestroy( argv );
             return 0;
         }
         else if( EQUAL(argv[i_arg],"--help") )
@@ -205,7 +206,7 @@ int main(int argc, char *argv[])
             break;
         }
     }
- 
+
     if( index_filename == NULL )
         Usage("No index filename specified.");
     if( i_arg == argc )
@@ -217,18 +218,19 @@ int main(int argc, char *argv[])
 /*      Create and validate target SRS if given.                        */
 /* -------------------------------------------------------------------- */
    if( bSetTargetSRS )
-   {  
+   {
        if ( skip_different_projection )
        {
-           fprintf( stderr, 
+           fprintf( stderr,
                     "Warning : -skip_different_projection does not apply "
                     "when -t_srs is requested.\n" );
        }
        hTargetSRS = OSRNewSpatialReference("");
+       /* coverity[tainted_data] */
        if( OSRSetFromUserInput( hTargetSRS, pszTargetSRS ) != CE_None )
        {
            OSRDestroySpatialReference( hTargetSRS );
-           fprintf( stderr, "Invalid target SRS `%s'.\n", 
+           fprintf( stderr, "Invalid target SRS `%s'.\n",
                     pszTargetSRS );
            exit(1);
        }
@@ -317,14 +319,14 @@ int main(int argc, char *argv[])
         {
             OGRFieldDefnH hFieldDefn = OGR_Fld_Create( tile_index, OFTString );
             if( nMaxFieldSize )
-                OGR_Fld_SetWidth( hFieldDefn, nMaxFieldSize);
+                OGR_Fld_SetWidth( hFieldDefn, (int)nMaxFieldSize);
             OGR_L_CreateField( hLayer, hFieldDefn, TRUE );
             OGR_Fld_Destroy(hFieldDefn);
             if( pszSrcSRSName != NULL )
             {
                 hFieldDefn = OGR_Fld_Create( pszSrcSRSName, OFTString );
                 if( nMaxFieldSize )
-                    OGR_Fld_SetWidth( hFieldDefn, nMaxFieldSize);
+                    OGR_Fld_SetWidth( hFieldDefn, (int)nMaxFieldSize);
                 OGR_L_CreateField( hLayer, hFieldDefn, TRUE );
                 OGR_Fld_Destroy(hFieldDefn);
             }
@@ -333,7 +335,7 @@ int main(int argc, char *argv[])
 
     if( hTileIndexDS == NULL || hLayer == NULL )
     {
-        fprintf( stderr, "Unable to open/create shapefile `%s'.\n", 
+        fprintf( stderr, "Unable to open/create shapefile `%s'.\n",
                  index_filename );
         exit(2);
     }
@@ -343,11 +345,11 @@ int main(int argc, char *argv[])
     ti_field = OGR_FD_GetFieldIndex( hFDefn, tile_index );
     if( ti_field < 0 )
     {
-        fprintf( stderr, "Unable to find field `%s' in file `%s'.\n", 
+        fprintf( stderr, "Unable to find field `%s' in file `%s'.\n",
                  tile_index, index_filename );
         exit(2);
     }
-    
+
     if( pszSrcSRSName != NULL )
         i_SrcSRSName = OGR_FD_GetFieldIndex( hFDefn, pszSrcSRSName );
 
@@ -435,21 +437,21 @@ int main(int argc, char *argv[])
         hDS = GDALOpen( argv[i_arg], GA_ReadOnly );
         if( hDS == NULL )
         {
-            fprintf( stderr, "Unable to open %s, skipping.\n", 
+            fprintf( stderr, "Unable to open %s, skipping.\n",
                      argv[i_arg] );
             CPLFree(fileNameToWrite);
             continue;
         }
 
         GDALGetGeoTransform( hDS, adfGeoTransform );
-        if( adfGeoTransform[0] == 0.0 
+        if( adfGeoTransform[0] == 0.0
             && adfGeoTransform[1] == 1.0
             && adfGeoTransform[3] == 0.0
             && ABS(adfGeoTransform[5]) == 1.0 )
         {
-            fprintf( stderr, 
+            fprintf( stderr,
                      "It appears no georeferencing is available for\n"
-                     "`%s', skipping.\n", 
+                     "`%s', skipping.\n",
                      argv[i_arg] );
             GDALClose( hDS );
             CPLFree(fileNameToWrite);
@@ -460,7 +462,7 @@ int main(int argc, char *argv[])
 
         /* if not set target srs, test that the current file uses same projection as others */
         if( !bSetTargetSRS )
-        { 
+        {
             if (alreadyExistingProjectionRefValid)
             {
                 int projectionRefNotNull, alreadyExistingProjectionRefNotNull;
@@ -494,40 +496,40 @@ int main(int argc, char *argv[])
 
         nXSize = GDALGetRasterXSize( hDS );
         nYSize = GDALGetRasterYSize( hDS );
-        
-        adfX[0] = adfGeoTransform[0] 
-            + 0 * adfGeoTransform[1] 
+
+        adfX[0] = adfGeoTransform[0]
+            + 0 * adfGeoTransform[1]
             + 0 * adfGeoTransform[2];
-        adfY[0] = adfGeoTransform[3] 
-            + 0 * adfGeoTransform[4] 
+        adfY[0] = adfGeoTransform[3]
+            + 0 * adfGeoTransform[4]
             + 0 * adfGeoTransform[5];
-        
-        adfX[1] = adfGeoTransform[0] 
-            + nXSize * adfGeoTransform[1] 
+
+        adfX[1] = adfGeoTransform[0]
+            + nXSize * adfGeoTransform[1]
             + 0 * adfGeoTransform[2];
-        adfY[1] = adfGeoTransform[3] 
-            + nXSize * adfGeoTransform[4] 
+        adfY[1] = adfGeoTransform[3]
+            + nXSize * adfGeoTransform[4]
             + 0 * adfGeoTransform[5];
-        
-        adfX[2] = adfGeoTransform[0] 
-            + nXSize * adfGeoTransform[1] 
+
+        adfX[2] = adfGeoTransform[0]
+            + nXSize * adfGeoTransform[1]
             + nYSize * adfGeoTransform[2];
-        adfY[2] = adfGeoTransform[3] 
-            + nXSize * adfGeoTransform[4] 
+        adfY[2] = adfGeoTransform[3]
+            + nXSize * adfGeoTransform[4]
             + nYSize * adfGeoTransform[5];
-        
-        adfX[3] = adfGeoTransform[0] 
-            + 0 * adfGeoTransform[1] 
+
+        adfX[3] = adfGeoTransform[0]
+            + 0 * adfGeoTransform[1]
             + nYSize * adfGeoTransform[2];
-        adfY[3] = adfGeoTransform[3] 
-            + 0 * adfGeoTransform[4] 
+        adfY[3] = adfGeoTransform[3]
+            + 0 * adfGeoTransform[4]
             + nYSize * adfGeoTransform[5];
-        
-        adfX[4] = adfGeoTransform[0] 
-            + 0 * adfGeoTransform[1] 
+
+        adfX[4] = adfGeoTransform[0]
+            + 0 * adfGeoTransform[1]
             + 0 * adfGeoTransform[2];
-        adfY[4] = adfGeoTransform[3] 
-            + 0 * adfGeoTransform[4] 
+        adfY[4] = adfGeoTransform[3]
+            + 0 * adfGeoTransform[4]
             + 0 * adfGeoTransform[5];
 
         if( (bSetTargetSRS || i_SrcSRSName >= 0) && projectionRef != NULL && projectionRef[0] != '\0' )
@@ -542,17 +544,17 @@ int main(int argc, char *argv[])
                 hCT = OCTNewCoordinateTransformation( hSourceSRS, hTargetSRS );
                 if( hCT == NULL || !OCTTransform( hCT, 5, adfX, adfY, NULL ) )
                 {
-                    fprintf( stderr, 
+                    fprintf( stderr,
                              "Warning : unable to transform points from source SRS `%s' to target SRS `%s'\n"
-                             "for file `%s' - file skipped\n", 
+                             "for file `%s' - file skipped\n",
                              projectionRef, pszTargetSRS, fileNameToWrite );
-                    if ( hCT ) 
+                    if ( hCT )
                         OCTDestroyCoordinateTransformation( hCT );
                     if ( hSourceSRS )
                         OSRDestroySpatialReference( hSourceSRS );
                     continue;
                 }
-                if ( hCT ) 
+                if ( hCT )
                     OCTDestroyCoordinateTransformation( hCT );
             }
         }
@@ -622,14 +624,13 @@ int main(int argc, char *argv[])
 
         OGR_F_Destroy( hFeature );
 
-        
         CPLFree(fileNameToWrite);
 
         GDALClose( hDS );
     }
-    
+
     CPLFree(current_path);
-    
+
     if (nExistingFiles)
     {
         for(i=0;i<nExistingFiles;i++)
@@ -644,10 +645,10 @@ int main(int argc, char *argv[])
         OSRDestroySpatialReference( hTargetSRS );
 
     OGR_DS_Destroy( hTileIndexDS );
-    
+
     GDALDestroyDriverManager();
     OGRCleanupAll();
     CSLDestroy(argv);
-    
+
     exit( 0 );
-} 
+}
diff --git a/apps/gdaltorture.cpp b/apps/gdaltorture.cpp
index b2ca20c..ae11b80 100644
--- a/apps/gdaltorture.cpp
+++ b/apps/gdaltorture.cpp
@@ -2,7 +2,7 @@
  * $Id: gdaltorture.cpp  $
  *
  * Project:  GDAL Utilities
- * Purpose:  Commandline utility to torture GDAL API on datasets
+ * Purpose:  Command line utility to torture GDAL API on datasets
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
@@ -67,7 +67,7 @@ static void TortureBand(GDALRasterBandH hBand, int bReadWriteOperations, int nRe
     GDALGetBlockSize(hBand, &nBlockXSize, &nBlockYSize);
     //GDALRasterAdviseRead
     //GDALRasterIO
-    //GDALReadBlock 
+    //GDALReadBlock
     //GDALWriteBlock
     nRasterXSize = GDALGetRasterBandXSize(hBand);
     nRasterYSize = GDALGetRasterBandYSize(hBand);
@@ -89,14 +89,14 @@ static void TortureBand(GDALRasterBandH hBand, int bReadWriteOperations, int nRe
     }
 
     GDALGetRasterNoDataValue(hBand, &bHasNoData);
-    //GDALSetRasterNoDataValue 
+    //GDALSetRasterNoDataValue
     GDALGetRasterCategoryNames(hBand);
     //GDALSetRasterCategoryNames
     GDALGetRasterMinimum(hBand, &bSuccess);
     GDALGetRasterMaximum(hBand, &bSuccess);
     GDALGetRasterStatistics(hBand, TRUE, FALSE, &dfMin, &dfMax, &dfMean, &dfStdDev);
     //GDALComputeRasterStatistics
-    //GDALSetRasterStatistics 
+    //GDALSetRasterStatistics
     GDALGetRasterUnitType(hBand);
     GDALGetRasterOffset(hBand, &bSuccess);
     //GDALSetRasterOffset
@@ -110,7 +110,7 @@ static void TortureBand(GDALRasterBandH hBand, int bReadWriteOperations, int nRe
     GDALGetRasterSampleOverview(hBand, 0); // returns a hBand
     //GDALFillRaster
     //GDALComputeBandStats
-    //GDALOverviewMagnitudeCorrection 
+    //GDALOverviewMagnitudeCorrection
     GDALGetDefaultRAT(hBand);
     //GDALSetDefaultRAT
     //GDALAddDerivedBandPixelFunc
@@ -119,7 +119,6 @@ static void TortureBand(GDALRasterBandH hBand, int bReadWriteOperations, int nRe
         TortureBand(hMaskBand, FALSE, nRecurse + 1);
     GDALGetMaskFlags(hBand);
     //GDALCreateMaskBand
-    
 }
 
 /************************************************************************/
@@ -172,7 +171,7 @@ static void TortureDS(const char *pszTarget, int bReadWriteOperations)
     // GDALFlushCache
     // GDALCreateDatasetMaskBand
     // GDALDatasetCopyWholeRaster
-    
+
     for(iBand=0;iBand<nBands;iBand++)
     {
         hBand = GDALGetRasterBand(hDS, iBand + 1);
@@ -190,8 +189,8 @@ static void TortureDS(const char *pszTarget, int bReadWriteOperations)
 /*                       ProcessTortureTarget()                         */
 /************************************************************************/
 
-static void ProcessTortureTarget( const char *pszTarget, 
-                                  char **papszSiblingList, 
+static void ProcessTortureTarget( const char *pszTarget,
+                                  char **papszSiblingList,
                                   int bRecursive, int bReportFailures,
                                   int bReadWriteOperations)
 
@@ -208,26 +207,26 @@ static void ProcessTortureTarget( const char *pszTarget,
         TortureDS(pszTarget, bReadWriteOperations);
     }
     else if( bReportFailures )
-        printf( "%s: unrecognised\n", pszTarget );
+        printf( "%s: unrecognized\n", pszTarget );
 
     if( !bRecursive || hDriver != NULL )
         return;
 
-    if( VSIStatL( pszTarget, &sStatBuf ) != 0 
+    if( VSIStatL( pszTarget, &sStatBuf ) != 0
         || !VSI_ISDIR( sStatBuf.st_mode ) )
         return;
 
     papszSiblingList = VSIReadDir( pszTarget );
     for( i = 0; papszSiblingList && papszSiblingList[i]; i++ )
     {
-        if( EQUAL(papszSiblingList[i],"..") 
+        if( EQUAL(papszSiblingList[i],"..")
             || EQUAL(papszSiblingList[i],".") )
             continue;
 
-        CPLString osSubTarget = 
+        CPLString osSubTarget =
             CPLFormFilename( pszTarget, papszSiblingList[i], NULL );
 
-        ProcessTortureTarget( osSubTarget, papszSiblingList, 
+        ProcessTortureTarget( osSubTarget, papszSiblingList,
                                bRecursive, bReportFailures, bReadWriteOperations );
     }
     CSLDestroy(papszSiblingList);
@@ -253,7 +252,7 @@ int main( int argc, char ** argv )
         Usage();
 
 /* -------------------------------------------------------------------- */
-/*      Scan for commandline switches                                   */
+/*      Scan for command line switches                                   */
 /* -------------------------------------------------------------------- */
     papszArgv = argv + 1;
     argc --;
@@ -278,7 +277,7 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
     while( argc > 0 )
     {
-        ProcessTortureTarget( papszArgv[0], NULL, 
+        ProcessTortureTarget( papszArgv[0], NULL,
                               bRecursive, bReportFailures, bReadWriteOperations );
         argc--;
         papszArgv++;
@@ -292,4 +291,3 @@ int main( int argc, char ** argv )
 
     return 0;
 }
-
diff --git a/apps/gdaltransform.cpp b/apps/gdaltransform.cpp
index b2dfb0a..c134f89 100644
--- a/apps/gdaltransform.cpp
+++ b/apps/gdaltransform.cpp
@@ -2,7 +2,7 @@
  * $Id: gdalwarp.cpp 12380 2007-10-12 17:35:00Z rouault $
  *
  * Project:  GDAL
- * Purpose:  Commandline point transformer.
+ * Purpose:  Command line point transformer.
  * Author:   Frank Warmerdam <warmerdam at pobox.com>
  *
  ******************************************************************************
@@ -41,12 +41,12 @@ CPL_CVSID("$Id: gdaltransform.cpp 12380 2007-10-12 17:35:00Z rouault $");
 static void Usage(const char* pszErrorMsg = NULL)
 
 {
-    printf( 
+    printf(
         "Usage: gdaltransform [--help-general]\n"
         "    [-i] [-s_srs srs_def] [-t_srs srs_def] [-to \"NAME=VALUE\"]\n"
         "    [-order n] [-tps] [-rpc] [-geoloc] \n"
-        "    [-gcp pixel line easting northing [elevation]]* [-output_xy]\n" 
-        "    [srcfile [dstfile]]\n" 
+        "    [-gcp pixel line easting northing [elevation]]* [-output_xy]\n"
+        "    [srcfile [dstfile]]\n"
         "\n" );
 
     if( pszErrorMsg != NULL )
@@ -59,14 +59,14 @@ static void Usage(const char* pszErrorMsg = NULL)
 /*                             SanitizeSRS                              */
 /************************************************************************/
 
-char *SanitizeSRS( const char *pszUserInput )
+static char *SanitizeSRS( const char *pszUserInput )
 
 {
     OGRSpatialReferenceH hSRS;
     char *pszResult = NULL;
 
     CPLErrorReset();
-    
+
     hSRS = OSRNewSpatialReference( NULL );
     if( OSRSetFromUserInput( hSRS, pszUserInput ) == OGRERR_NONE )
         OSRExportToWkt( hSRS, &pszResult );
@@ -77,7 +77,7 @@ char *SanitizeSRS( const char *pszUserInput )
                   pszUserInput );
         exit( 1 );
     }
-    
+
     OSRDestroySpatialReference( hSRS );
 
     return pszResult;
@@ -104,6 +104,10 @@ int main( int argc, char ** argv )
     int                 bInverse = FALSE;
     char              **papszTO = NULL;
     int                 bOutputXY = FALSE;
+    double              dfX = 0.0;
+    double              dfY = 0.0;
+    double              dfZ = 0.0;
+    bool                bCoordOnCommandLine = false;
 
     /* Check that we are running against at least GDAL 1.5 */
     /* Note to developers : if we use newer API, please change the requirement */
@@ -124,12 +128,13 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
     int i;
 
-    for( i = 1; i < argc; i++ )
+    for( i = 1; i < argc && argv[i] != NULL; i++ )
     {
         if( EQUAL(argv[i], "--utility_version") )
         {
             printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
                    argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
+            CSLDestroy(argv);
             return 0;
         }
         else if( EQUAL(argv[i],"--help") )
@@ -183,7 +188,7 @@ int main( int argc, char ** argv )
             /* -gcp pixel line easting northing [elev] */
 
             nGCPCount++;
-            pasGCPs = (GDAL_GCP *) 
+            pasGCPs = (GDAL_GCP *)
                 CPLRealloc( pasGCPs, sizeof(GDAL_GCP) * nGCPCount );
             GDALInitGCPs( 1, pasGCPs + nGCPCount - 1 );
 
@@ -191,7 +196,7 @@ int main( int argc, char ** argv )
             pasGCPs[nGCPCount-1].dfGCPLine = CPLAtof(argv[++i]);
             pasGCPs[nGCPCount-1].dfGCPX = CPLAtof(argv[++i]);
             pasGCPs[nGCPCount-1].dfGCPY = CPLAtof(argv[++i]);
-            if( argv[i+1] != NULL 
+            if( argv[i+1] != NULL
                 && (CPLStrtod(argv[i+1], &endptr) != 0.0 || argv[i+1][0] == '0') )
             {
                 /* Check that last argument is really a number and not a filename */
@@ -201,13 +206,22 @@ int main( int argc, char ** argv )
             }
 
             /* should set id and info? */
-        }   
-        
+        }
+
         else if( EQUAL(argv[i],"-output_xy") )
         {
             bOutputXY = TRUE;
         }
 
+        else if( EQUAL(argv[i],"-coord")  && i + 2 < argc)
+        {
+            bCoordOnCommandLine = true;
+            dfX = CPLAtof(argv[++i]);
+            dfY = CPLAtof(argv[++i]);
+            if( i + 1 < argc && CPLGetValueType(argv[i+1]) != CPL_VALUE_STRING )
+                dfZ = CPLAtof(argv[++i]);
+            bOutputXY = TRUE;
+        }
         else if( argv[i][0] == '-' )
             Usage(CPLSPrintf("Unknown option name '%s'", argv[i]));
 
@@ -242,10 +256,10 @@ int main( int argc, char ** argv )
 
     if( hSrcDS != NULL && nGCPCount > 0 )
     {
-        fprintf( stderr, "Commandline GCPs and input file specified, specify one or the other.\n" );
+        fprintf( stderr, "Command line GCPs and input file specified, specify one or the other.\n" );
         exit( 1 );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create a transformation object from the source to               */
 /*      destination coordinate system.                                  */
@@ -253,19 +267,19 @@ int main( int argc, char ** argv )
     if( nGCPCount != 0 && nOrder == -1 )
     {
         pfnTransformer = GDALTPSTransform;
-        hTransformArg = 
+        hTransformArg =
             GDALCreateTPSTransformer( nGCPCount, pasGCPs, FALSE );
     }
     else if( nGCPCount != 0 )
     {
         pfnTransformer = GDALGCPTransform;
-        hTransformArg = 
+        hTransformArg =
             GDALCreateGCPTransformer( nGCPCount, pasGCPs, nOrder, FALSE );
     }
     else
     {
         pfnTransformer = GDALGenImgProjTransform;
-        hTransformArg = 
+        hTransformArg =
             GDALCreateGenImgProjTransformer2( hSrcDS, hDstDS, papszTO );
     }
 
@@ -279,29 +293,34 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
 /*      Read points from stdin, transform and write to stdout.          */
 /* -------------------------------------------------------------------- */
-    while( !feof(stdin) )
+    while( bCoordOnCommandLine || !feof(stdin) )
     {
-        char szLine[1024];
+        if( !bCoordOnCommandLine )
+        {
+            char szLine[1024];
 
-        if( fgets( szLine, sizeof(szLine)-1, stdin ) == NULL )
-            break;
+            if( fgets( szLine, sizeof(szLine)-1, stdin ) == NULL )
+                break;
 
-        char **papszTokens = CSLTokenizeString(szLine);
-        double dfX, dfY, dfZ = 0.0;
-        int bSuccess = TRUE;
+            char **papszTokens = CSLTokenizeString(szLine);
 
-        if( CSLCount(papszTokens) < 2 )
-        {
+            if( CSLCount(papszTokens) < 2 )
+            {
+                CSLDestroy(papszTokens);
+                continue;
+            }
+
+            dfX = CPLAtof(papszTokens[0]);
+            dfY = CPLAtof(papszTokens[1]);
+            if( CSLCount(papszTokens) >= 3 )
+                dfZ = CPLAtof(papszTokens[2]);
+            else
+                dfZ = 0.0;
             CSLDestroy(papszTokens);
-            continue;
         }
 
-        dfX = CPLAtof(papszTokens[0]);
-        dfY = CPLAtof(papszTokens[1]);
-        if( CSLCount(papszTokens) >= 3 )
-            dfZ = CPLAtof(papszTokens[2]);
-
-        if( pfnTransformer( hTransformArg, bInverse, 1, 
+        int bSuccess = TRUE;
+        if( pfnTransformer( hTransformArg, bInverse, 1,
                             &dfX, &dfY, &dfZ, &bSuccess )
             && bSuccess )
         {
@@ -315,7 +334,8 @@ int main( int argc, char ** argv )
             printf( "transformation failed.\n" );
         }
 
-        CSLDestroy(papszTokens);
+        if( bCoordOnCommandLine )
+            break;
     }
 
     if( nGCPCount != 0 && nOrder == -1 )
diff --git a/apps/gdalwarp.cpp b/apps/gdalwarp.cpp
deleted file mode 100644
index 867152f..0000000
--- a/apps/gdalwarp.cpp
+++ /dev/null
@@ -1,2744 +0,0 @@
-/******************************************************************************
- * $Id: gdalwarp.cpp 33043 2016-01-19 10:00:20Z rouault $
- *
- * Project:  High Performance Image Reprojector
- * Purpose:  Test program for high performance warper API.
- * Author:   Frank Warmerdam <warmerdam at pobox.com>
- *
- ******************************************************************************
- * Copyright (c) 2002, i3 - information integration and imaging 
- *                          Fort Collin, CO
- * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "gdalwarper.h"
-#include "cpl_string.h"
-#include "ogr_spatialref.h"
-#include "ogr_api.h"
-#include "commonutils.h"
-#include "gdal_priv.h"
-#include <vector>
-
-CPL_CVSID("$Id: gdalwarp.cpp 33043 2016-01-19 10:00:20Z rouault $");
-
-static void
-LoadCutline( const char *pszCutlineDSName, const char *pszCLayer, 
-             const char *pszCWHERE, const char *pszCSQL, 
-             void **phCutlineRet );
-static void
-TransformCutlineToSource( GDALDatasetH hSrcDS, void *hCutline,
-                          char ***ppapszWarpOptions, char **papszTO );
-
-static GDALDatasetH 
-GDALWarpCreateOutput( char **papszSrcFiles, const char *pszFilename, 
-                      const char *pszFormat, char **papszTO,
-                      char ***ppapszCreateOptions, GDALDataType eDT,
-                      void ** phTransformArg,
-                      GDALDatasetH* phSrcDS,
-                      int bSetColorInterpretation,
-                      char** papszOpenOptions );
-
-static void 
-RemoveConflictingMetadata( GDALMajorObjectH hObj, char **papszMetadata,
-                           const char *pszValueConflict );
-
-static double	       dfMinX=0.0, dfMinY=0.0, dfMaxX=0.0, dfMaxY=0.0;
-static double	       dfXRes=0.0, dfYRes=0.0;
-static int             bTargetAlignedPixels = FALSE;
-static int             nForcePixels=0, nForceLines=0, bQuiet = FALSE;
-static int             bEnableDstAlpha = FALSE, bEnableSrcAlpha = FALSE;
-
-static int             bVRT = FALSE;
-
-/******************************************************************************/
-/*! \page gdalwarp gdalwarp
-
-image reprojection and warping utility
-
-\section gdalwarp_synopsis SYNOPSIS
-
-\htmlonly
-Usage: 
-\endhtmlonly
-
-\verbatim
-gdalwarp [--help-general] [--formats]
-    [-s_srs srs_def] [-t_srs srs_def] [-to "NAME=VALUE"]
-    [-order n | -tps | -rpc | -geoloc] [-et err_threshold]
-    [-refine_gcps tolerance [minimum_gcps]]
-    [-te xmin ymin xmax ymax] [-te_srs srs_def]
-    [-tr xres yres] [-tap] [-ts width height]
-    [-ovr level|AUTO|AUTO-n|NONE] [-wo "NAME=VALUE"] [-ot Byte/Int16/...] [-wt Byte/Int16]
-    [-srcnodata "value [value...]"] [-dstnodata "value [value...]"] -dstalpha
-    [-r resampling_method] [-wm memory_in_mb] [-multi] [-q]
-    [-cutline datasource] [-cl layer] [-cwhere expression]
-    [-csql statement] [-cblend dist_in_pixels] [-crop_to_cutline]
-    [-of format] [-co "NAME=VALUE"]* [-overwrite]
-    [-nomd] [-cvmd meta_conflict_value] [-setci] [-oo NAME=VALUE]*
-    srcfile* dstfile
-\endverbatim
-
-\section gdalwarp_description DESCRIPTION
-
-<p>
-The gdalwarp utility is an image mosaicing, reprojection and warping
-utility. The program can reproject to any supported projection,
-and can also apply GCPs stored with the image if the image is "raw"
-with control information.
-
-<p>
-<dl>
-<dt> <b>-s_srs</b> <em>srs def</em>:</dt><dd> source spatial reference set.
-The coordinate systems that can be passed are anything supported by the
-OGRSpatialReference.SetFromUserInput() call, which includes EPSG PCS and GCSes
-(ie. EPSG:4296), PROJ.4 declarations (as above), or the name of a .prf file
-containing well known text.</dd>
-<dt> <b>-t_srs</b> <em>srs_def</em>:</dt><dd> target spatial reference set.
-The coordinate systems that can be passed are anything supported by the
-OGRSpatialReference.SetFromUserInput() call, which includes EPSG PCS and GCSes
-(ie. EPSG:4296), PROJ.4 declarations (as above), or the name of a .prf file
-containing well known text.</dd>
-<dt> <b>-to</b> <em>NAME=VALUE</em>:</dt><dd> set a transformer option suitable
-to pass to GDALCreateGenImgProjTransformer2(). </dd>
-<dt> <b>-order</b> <em>n</em>:</dt><dd> order of polynomial used for warping
-(1 to 3). The default is to select a polynomial order based on the number of
-GCPs.</dd>
-<dt> <b>-tps</b>:</dt><dd>Force use of thin plate spline transformer based on
-available GCPs.</dd>
-<dt> <b>-rpc</b>:</dt> <dd>Force use of RPCs.</dd>
-<dt> <b>-geoloc</b>:</dt><dd>Force use of Geolocation Arrays.</dd>
-<dt> <b>-et</b> <em>err_threshold</em>:</dt><dd> error threshold for
-transformation approximation (in pixel units - defaults to 0.125).</dd>
-<dt> <b>-refine_gcps</b> <em>tolerance minimum_gcps</em>:</dt><dd>  (GDAL >= 1.9.0) refines the GCPs by automatically eliminating outliers.
-Outliers will be eliminated until minimum_gcps are left or when no outliers can be detected.
-The tolerance is passed to adjust when a GCP will be eliminated.
-Not that GCP refinement only works with polynomial interpolation.
-The tolerance is in pixel units if no projection is available, otherwise it is in SRS units.
-If minimum_gcps is not provided, the minimum GCPs according to the polynomial model is used.</dd>
-<dt> <b>-te</b> <em>xmin ymin xmax ymax</em>:</dt><dd> set georeferenced
-extents of output file to be created (in target SRS by default, or in the SRS
-specified with -te_srs)
-</dd>
-<dt> <b>-te_srs</b> <i>srs_def</i>:</dt><dd> (GDAL >= 2.0) Specifies the SRS in
-which to interpret the coordinates given with -te. The <i>srs_def</i> may
-be any of the usual GDAL/OGR forms, complete WKT, PROJ.4, EPSG:n or a file
-containing the WKT.
-This must not be confused with -t_srs which is the target SRS of the output
-dataset. -te_srs is a conveniency e.g. when knowing the output coordinates in a
-geodetic long/lat SRS, but still wanting a result in a projected coordinate system.
-</dd>
-<dt> <b>-tr</b> <em>xres yres</em>:</dt><dd> set output file resolution (in
-target georeferenced units)</dd>
-<dt> <b>-tap</b>:</dt><dd> (GDAL >= 1.8.0) (target aligned pixels) align
-the coordinates of the extent of the output file to the values of the -tr,
-such that the aligned extent includes the minimum extent.</dd>
-<dt> <b>-ts</b> <em>width height</em>:</dt><dd> set output file size in
-pixels and lines. If width or height is set to 0, the other dimension will be
-guessed from the computed resolution. Note that -ts cannot be used with -tr</dd>
-<dt> <b>-ovr</b> <em>level|AUTO|AUTO-n|NONE></em>:</dt><dd>(GDAL >= 2.0) To
-specify which overview level of source files must be used. The default choice,
-AUTO, will select the overview level whose resolution is the closest to the
-target resolution. Specify an integer value (0-based, i.e. 0=1st overview level) 
-to select a particular level. Specify AUTO-n where n is an integer greater or
-equal to 1, to select an overview level below the AUTO one. Or specify NONE to
-force the base resolution to be used.</dd>
-<dt> <b>-wo</b> <em>"NAME=VALUE"</em>:</dt><dd> Set a warp option.  The 
-GDALWarpOptions::papszWarpOptions docs show all options.  Multiple
- <b>-wo</b> options may be listed.</dd>
-<dt> <b>-ot</b> <em>type</em>:</dt><dd> For the output bands to be of the
-indicated data type.</dd>
-<dt> <b>-wt</b> <em>type</em>:</dt><dd> Working pixel data type. The data type
-of pixels in the source image and destination image buffers.</dd>
-<dt> <b>-r</b> <em>resampling_method</em>:</dt><dd> Resampling method to use. Available methods are:
-<dl>
-<dt><b>near</b></dt>: <dd>nearest neighbour resampling (default, fastest
-algorithm, worst interpolation quality).</dd>
-<dt><b>bilinear</b></dt>: <dd>bilinear resampling.</dd>
-<dt><b>cubic</b></dt>: <dd>cubic resampling.</dd>
-<dt><b>cubicspline</b></dt>: <dd>cubic spline resampling.</dd>
-<dt><b>lanczos</b></dt>: <dd>Lanczos windowed sinc resampling.</dd>
-<dt><b>average</b></dt>: <dd>average resampling, computes the average of all non-NODATA contributing pixels. (GDAL >= 1.10.0)</dd>
-<dt><b>mode</b></dt>: <dd>mode resampling, selects the value which appears most often of all the sampled points. (GDAL >= 1.10.0)</dd>
-<dt><b>max</b></dt>: <dd>maximum resampling, selects the maximum value from all non-NODATA contributing pixels. (GDAL >= 2.0.0)</dd>
-<dt><b>min</b></dt>: <dd>minimum resampling, selects the minimum value from all non-NODATA contributing pixels. (GDAL >= 2.0.0)</dd>
-<dt><b>med</b></dt>: <dd>median resampling, selects the median value of all non-NODATA contributing pixels. (GDAL >= 2.0.0)</dd>
-<dt><b>q1</b></dt>: <dd>first quartile resampling, selects the first quartile value of all non-NODATA contributing pixels. (GDAL >= 2.0.0)</dd>
-<dt><b>q3</b></dt>: <dd>third quartile resampling, selects the third quartile value of all non-NODATA contributing pixels. (GDAL >= 2.0.0)</dd>
-</dl>
-<dt> <b>-srcnodata</b> <em>value [value...]</em>:</dt><dd> Set nodata masking
-values for input bands (different values can be supplied for each band).  If 
-more than one value is supplied all values should be quoted to keep them 
-together as a single operating system argument.  Masked values will not be 
-used in interpolation.  Use a value of <tt>None</tt> to ignore intrinsic nodata settings on the source dataset.</dd>
-<dt> <b>-dstnodata</b> <em>value [value...]</em>:</dt><dd> Set nodata values
-for output bands (different values can be supplied for each band).  If more
-than one value is supplied all values should be quoted to keep them together
-as a single operating system argument.  New files will be initialized to this
-value and if possible the nodata value will be recorded in the output
-file. Use a value of <tt>None</tt> to ensure that nodata is not defined (GDAL>=1.11).
-If this argument is not used then nodata values will be copied from the source dataset (GDAL>=1.11).</dd>
-<dt> <b>-dstalpha</b>:</dt><dd> Create an output alpha band to identify 
-nodata (unset/transparent) pixels. </dd>
-<dt> <b>-wm</b> <em>memory_in_mb</em>:</dt><dd> Set the amount of memory (in
-megabytes) that the warp API is allowed to use for caching.</dd>
-<dt> <b>-multi</b>:</dt><dd> Use multithreaded warping implementation.
-Multiple threads will be used to process chunks of image and perform
-input/output operation simultaneously.</dd>
-<dt> <b>-q</b>:</dt><dd> Be quiet.</dd>
-<dt> <b>-of</b> <em>format</em>:</dt><dd> Select the output format. The default is GeoTIFF (GTiff). Use the short format name. </dd>
-<dt> <b>-co</b> <em>"NAME=VALUE"</em>:</dt><dd> passes a creation option to
-the output format driver. Multiple <b>-co</b> options may be listed. See
-format specific documentation for legal creation options for each format.
-</dd>
-
-<dt> <b>-cutline</b> <em>datasource</em>:</dt><dd>Enable use of a blend cutline from the name OGR support datasource.</dd>
-<dt> <b>-cl</b> <em>layername</em>:</dt><dd>Select the named layer from the 
-cutline datasource.</dd>
-<dt> <b>-cwhere</b> <em>expression</em>:</dt><dd>Restrict desired cutline features based on attribute query.</dd>
-<dt> <b>-csql</b> <em>query</em>:</dt><dd>Select cutline features using an SQL query instead of from a layer with -cl.</dd>
-<dt> <b>-cblend</b> <em>distance</em>:</dt><dd>Set a blend distance to use to blend over cutlines (in pixels).</dd>
-<dt> <b>-crop_to_cutline</b>:</dt><dd>(GDAL >= 1.8.0) Crop the extent of the target dataset to the extent of the cutline.</dd>
-<dt> <b>-overwrite</b>:</dt><dd>(GDAL >= 1.8.0) Overwrite the target dataset if it already exists.</dd>
-<dt> <b>-nomd</b>:</dt><dd>(GDAL >= 1.10.0) Do not copy metadata. Without this option, dataset and band metadata 
-(as well as some band information) will be copied from the first source dataset. 
-Items that differ between source datasets will be set to * (see -cvmd option).</dd>
-<dt> <b>-cvmd</b> <em>meta_conflict_value</em>:</dt><dd>(GDAL >= 1.10.0) 
-Value to set metadata items that conflict between source datasets (default is "*"). Use "" to remove conflicting items. </dd>
-<dt> <b>-setci</b>:</dt><dd>(GDAL >= 1.10.0) 
-Set the color interpretation of the bands of the target dataset from the source dataset.</dd>
-<dt> <b>-oo</b> <em>NAME=VALUE</em>:</dt><dd>(starting with GDAL 2.0) Dataset open option (format specific)</dd>
-
-<dt> <em>srcfile</em>:</dt><dd> The source file name(s). </dd>
-<dt> <em>dstfile</em>:</dt><dd> The destination file name. </dd>
-</dl>
-
-Mosaicing into an existing output file is supported if the output file 
-already exists. The spatial extent of the existing file will not
-be modified to accommodate new data, so you may have to remove it in that case, or
-use the -overwrite option.
-
-Polygon cutlines may be used as a mask to restrict the area of the destination file
-that may be updated, including blending.  If the OGR layer containing the cutline
-features has no explicit SRS, the cutline features must be in the SRS of the
-destination file. When outputing to a not yet existing target dataset,
-its extent will be the one of the original raster unless -te or -crop_to_cutline are
-specified.
-
-<p>
-\section gdalwarp_example EXAMPLE
-
-For instance, an eight bit spot scene stored in GeoTIFF with
-control points mapping the corners to lat/long could be warped to a UTM
-projection with a command like this:<p>
-
-\verbatim
-gdalwarp -t_srs '+proj=utm +zone=11 +datum=WGS84' raw_spot.tif utm11.tif
-\endverbatim
-
-For instance, the second channel of an ASTER image stored in HDF with
-control points mapping the corners to lat/long could be warped to a UTM
-projection with a command like this:<p>
-
-\verbatim
-gdalwarp HDF4_SDS:ASTER_L1B:"pg-PR1B0000-2002031402_100_001":2 pg-PR1B0000-2002031402_100_001_2.tif
-\endverbatim
-
-<p>
-\section gdalwarp_seealso SEE ALSO
-
-\if man
-http://trac.osgeo.org/gdal/wiki/UserDocs/GdalWarp :
-\else
-<a href="http://trac.osgeo.org/gdal/wiki/UserDocs/GdalWarp">
-\endif
-Wiki page discussing options and behaviours of gdalwarp
-\if man
-\else
-</a>
-\endif
-
-\if man
-\section gdalwarp_author AUTHORS
-Frank Warmerdam <warmerdam at pobox.com>, Silke Reimer <silke at intevation.de>
-\endif
-*/
-
-/************************************************************************/
-/*                               GDALExit()                             */
-/*  This function exits and cleans up GDAL and OGR resources            */
-/*  Perhaps it should be added to C api and used in all apps?           */
-/************************************************************************/
-
-static int GDALExit( int nCode )
-{
-  const char  *pszDebug = CPLGetConfigOption("CPL_DEBUG",NULL);
-  if( pszDebug && (EQUAL(pszDebug,"ON") || EQUAL(pszDebug,"") ) )
-  {  
-    GDALDumpOpenDatasets( stderr );
-    CPLDumpSharedList( NULL );
-  }
-
-  GDALDestroyDriverManager();
-
-#ifdef OGR_ENABLED
-  OGRCleanupAll();
-#endif
-
-  exit( nCode );
-}
-
-/************************************************************************/
-/*                               Usage()                                */
-/************************************************************************/
-
-static void Usage(const char* pszErrorMsg = NULL)
-
-{
-    printf( 
-        "Usage: gdalwarp [--help-general] [--formats]\n"
-        "    [-s_srs srs_def] [-t_srs srs_def] [-to \"NAME=VALUE\"]\n"
-        "    [-order n | -tps | -rpc | -geoloc] [-et err_threshold]\n"
-        "    [-refine_gcps tolerance [minimum_gcps]]\n"
-        "    [-te xmin ymin xmax ymax] [-tr xres yres] [-tap] [-ts width height]\n"
-        "    [-ovr level|AUTO|AUTO-n|NONE] [-wo \"NAME=VALUE\"] [-ot Byte/Int16/...] [-wt Byte/Int16]\n"
-        "    [-srcnodata \"value [value...]\"] [-dstnodata \"value [value...]\"] -dstalpha\n" 
-        "    [-r resampling_method] [-wm memory_in_mb] [-multi] [-q]\n"
-        "    [-cutline datasource] [-cl layer] [-cwhere expression]\n"
-        "    [-csql statement] [-cblend dist_in_pixels] [-crop_to_cutline]\n"
-        "    [-of format] [-co \"NAME=VALUE\"]* [-overwrite]\n"
-        "    [-nomd] [-cvmd meta_conflict_value] [-setci] [-oo NAME=VALUE]*\n"
-        "    srcfile* dstfile\n"
-        "\n"
-        "Available resampling methods:\n"
-        "    near (default), bilinear, cubic, cubicspline, lanczos, average, mode,  max, min, med, Q1, Q3.\n" );
-
-    if( pszErrorMsg != NULL )
-        fprintf(stderr, "\nFAILURE: %s\n", pszErrorMsg);
-
-    GDALExit( 1 );
-}
-
-/************************************************************************/
-/*                             SanitizeSRS                              */
-/************************************************************************/
-
-char *SanitizeSRS( const char *pszUserInput )
-
-{
-    OGRSpatialReferenceH hSRS;
-    char *pszResult = NULL;
-
-    CPLErrorReset();
-    
-    hSRS = OSRNewSpatialReference( NULL );
-    if( OSRSetFromUserInput( hSRS, pszUserInput ) == OGRERR_NONE )
-        OSRExportToWkt( hSRS, &pszResult );
-    else
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Translating source or target SRS failed:\n%s",
-                  pszUserInput );
-        GDALExit( 1 );
-    }
-    
-    OSRDestroySpatialReference( hSRS );
-
-    return pszResult;
-}
-
-#ifdef OGR_ENABLED
-
-static double GetAverageSegmentLength(OGRGeometryH hGeom)
-{
-    if( hGeom == NULL )
-        return 0;
-    switch(wkbFlatten(OGR_G_GetGeometryType(hGeom)))
-    {
-        case wkbLineString:
-        {
-            if( OGR_G_GetPointCount(hGeom) == 0 )
-                return 0;
-            double dfSum = 0;
-            for(int i=0;i<OGR_G_GetPointCount(hGeom)-1;i++)
-            {
-                double dfX1 = OGR_G_GetX(hGeom, i);
-                double dfY1 = OGR_G_GetY(hGeom, i);
-                double dfX2 = OGR_G_GetX(hGeom, i+1);
-                double dfY2 = OGR_G_GetY(hGeom, i+1);
-                double dfDX = dfX2 - dfX1;
-                double dfDY = dfY2 - dfY1;
-                dfSum += sqrt(dfDX * dfDX + dfDY * dfDY);
-            }
-            return dfSum / OGR_G_GetPointCount(hGeom);
-        }
-
-        case wkbPolygon:
-        case wkbMultiPolygon:
-        case wkbMultiLineString:
-        case wkbGeometryCollection:
-        {
-            if( OGR_G_GetGeometryCount(hGeom) == 0 )
-                return 0;
-            double dfSum = 0;
-            for(int i=0; i< OGR_G_GetGeometryCount(hGeom); i++)
-            {
-                dfSum += GetAverageSegmentLength(OGR_G_GetGeometryRef(hGeom, i));
-            }
-            return dfSum / OGR_G_GetGeometryCount(hGeom);
-        }
-        
-        default:
-            return 0;
-    }
-}
-
-/************************************************************************/
-/*                           CropToCutline()                            */
-/************************************************************************/
-
-static void CropToCutline( void* hCutline, char** papszTO, char** papszSrcFiles,
-                           char** papszOpenOptions,
-                           double& dfMinX, double& dfMinY, double& dfMaxX, double &dfMaxY )
-{
-    OGRGeometryH hCutlineGeom = OGR_G_Clone( (OGRGeometryH) hCutline );
-    OGRSpatialReferenceH hCutlineSRS = OGR_G_GetSpatialReference( hCutlineGeom );
-    const char *pszThisTargetSRS = CSLFetchNameValue( papszTO, "DST_SRS" );
-    const char *pszThisSourceSRS = CSLFetchNameValue(papszTO, "SRC_SRS");
-    OGRCoordinateTransformationH hCTCutlineToSrc = NULL;
-    OGRCoordinateTransformationH hCTSrcToDst = NULL;
-    OGRSpatialReferenceH hSrcSRS = NULL, hDstSRS = NULL;
-
-    if( pszThisSourceSRS != NULL )
-    {
-        hSrcSRS = OSRNewSpatialReference(NULL);
-        if( OSRImportFromWkt( hSrcSRS, (char **)&pszThisSourceSRS ) != CE_None )
-        {
-            fprintf(stderr, "Cannot compute bounding box of cutline.\n");
-            GDALExit(1);
-        }
-    }
-    else if( papszSrcFiles[0] != NULL )
-    {
-        GDALDatasetH hSrcDS = GDALOpenEx( papszSrcFiles[0], GDAL_OF_RASTER, NULL,
-                    (const char* const* )papszOpenOptions, NULL );
-        if (hSrcDS == NULL)
-        {
-            fprintf(stderr, "Cannot compute bounding box of cutline.\n");
-            GDALExit(1);
-        }
-
-        const char *pszProjection = NULL;
-
-        if( GDALGetProjectionRef( hSrcDS ) != NULL
-            && strlen(GDALGetProjectionRef( hSrcDS )) > 0 )
-            pszProjection = GDALGetProjectionRef( hSrcDS );
-        else if( GDALGetGCPProjection( hSrcDS ) != NULL )
-            pszProjection = GDALGetGCPProjection( hSrcDS );
-
-        if( pszProjection == NULL )
-        {
-            fprintf(stderr, "Cannot compute bounding box of cutline.\n");
-            GDALExit(1);
-        }
-
-        hSrcSRS = OSRNewSpatialReference(NULL);
-        if( OSRImportFromWkt( hSrcSRS, (char **)&pszProjection ) != CE_None )
-        {
-            fprintf(stderr, "Cannot compute bounding box of cutline.\n");
-            GDALExit(1);
-        }
-
-        GDALClose(hSrcDS);
-    }
-    else
-    {
-        fprintf(stderr, "Cannot compute bounding box of cutline.\n");
-        GDALExit(1);
-    }
-
-    if ( pszThisTargetSRS != NULL )
-    {
-        hDstSRS = OSRNewSpatialReference(NULL);
-        if( OSRImportFromWkt( hDstSRS, (char **)&pszThisTargetSRS ) != CE_None )
-        {
-            fprintf(stderr, "Cannot compute bounding box of cutline.\n");
-            GDALExit(1);
-        }
-    }
-    else
-        hDstSRS = OSRClone(hSrcSRS);
-
-    OGRSpatialReferenceH hCutlineOrTargetSRS = hCutlineSRS ? hCutlineSRS : hDstSRS;
-
-    if( !OSRIsSame(hCutlineOrTargetSRS, hSrcSRS) )
-        hCTCutlineToSrc = OCTNewCoordinateTransformation(hCutlineOrTargetSRS, hSrcSRS);
-    if( !OSRIsSame(hSrcSRS, hDstSRS) )
-        hCTSrcToDst = OCTNewCoordinateTransformation(hSrcSRS, hDstSRS);
-
-    OSRDestroySpatialReference(hSrcSRS);
-    hSrcSRS = NULL;
-
-    OSRDestroySpatialReference(hDstSRS);
-    hDstSRS = NULL;
-
-    // Reproject cutline to target SRS, by doing intermediate vertex densifications
-    // in source SRS.
-    if( hCTSrcToDst != NULL || hCTCutlineToSrc != NULL )
-    {
-        OGREnvelope sLastEnvelope, sCurEnvelope;
-        OGRGeometryH hTransformedGeom = NULL;
-        OGRGeometryH hGeomInSrcSRS = OGR_G_Clone(hCutlineGeom);
-        if( hCTCutlineToSrc != NULL )
-            OGR_G_Transform( hGeomInSrcSRS, hCTCutlineToSrc );
-
-        for(int nIter=0;nIter<10;nIter++)
-        {
-            if( hTransformedGeom != NULL )
-                OGR_G_DestroyGeometry(hTransformedGeom);
-            hTransformedGeom = OGR_G_Clone(hGeomInSrcSRS);
-            if( hCTSrcToDst != NULL )
-                OGR_G_Transform( hTransformedGeom, hCTSrcToDst );
-            OGR_G_GetEnvelope(hTransformedGeom, &sCurEnvelope);
-            if( nIter > 0 || hCTSrcToDst == NULL )
-            {
-                if( sCurEnvelope.MinX == sLastEnvelope.MinX &&
-                    sCurEnvelope.MinY == sLastEnvelope.MinY &&
-                    sCurEnvelope.MaxX == sLastEnvelope.MaxX &&
-                    sCurEnvelope.MaxY == sLastEnvelope.MaxY )
-                {
-                    break;
-                }
-            }
-            double dfAverageSegmentLength = GetAverageSegmentLength(hGeomInSrcSRS);
-            OGR_G_Segmentize(hGeomInSrcSRS, dfAverageSegmentLength/4);
-
-            memcpy(&sLastEnvelope, &sCurEnvelope, sizeof(OGREnvelope));
-        }
-        
-        OGR_G_DestroyGeometry(hGeomInSrcSRS);
-
-        OGR_G_DestroyGeometry(hCutlineGeom);
-        hCutlineGeom = hTransformedGeom;
-    }
-
-    if( hCTCutlineToSrc) 
-        OCTDestroyCoordinateTransformation(hCTCutlineToSrc);
-    if( hCTSrcToDst )
-        OCTDestroyCoordinateTransformation(hCTSrcToDst);
-
-    OGREnvelope sEnvelope;
-    OGR_G_GetEnvelope(hCutlineGeom, &sEnvelope);
-
-    dfMinX = sEnvelope.MinX;
-    dfMinY = sEnvelope.MinY;
-    dfMaxX = sEnvelope.MaxX;
-    dfMaxY = sEnvelope.MaxY;
-    
-    OGR_G_DestroyGeometry(hCutlineGeom);
-}
-#endif /* OGR_ENABLED */
-
-/************************************************************************/
-/*                                main()                                */
-/************************************************************************/
-
-#define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg) \
-    do { if (i + nExtraArg >= argc) \
-        Usage(CPLSPrintf("%s option requires %d argument(s)", argv[i], nExtraArg)); } while(0)
-
-int main( int argc, char ** argv )
-
-{
-    GDALDatasetH	hDstDS;
-    const char         *pszFormat = "GTiff";
-    int bFormatExplicitlySet = FALSE;
-    char              **papszSrcFiles = NULL;
-    char               *pszDstFilename = NULL;
-    int                 bCreateOutput = FALSE, i;
-    void               *hTransformArg = NULL;
-    char               **papszWarpOptions = NULL;
-    double             dfErrorThreshold = 0.125;
-    double             dfWarpMemoryLimit = 0.0;
-    GDALTransformerFunc pfnTransformer = NULL;
-    char                **papszCreateOptions = NULL;
-    GDALDataType        eOutputType = GDT_Unknown, eWorkingType = GDT_Unknown; 
-    GDALResampleAlg     eResampleAlg = GRA_NearestNeighbour;
-    const char          *pszSrcNodata = NULL;
-    const char          *pszDstNodata = NULL;
-    int                 bMulti = FALSE;
-    char                **papszTO = NULL;
-    char                *pszCutlineDSName = NULL;
-    char                *pszCLayer = NULL, *pszCWHERE = NULL, *pszCSQL = NULL;
-    void                *hCutline = NULL;
-    int                  bHasGotErr = FALSE;
-    int                  bCropToCutline = FALSE;
-    int                  bOverwrite = FALSE;
-    int                  bCopyMetadata = TRUE;
-    int                  bCopyBandInfo = TRUE;
-    const char           *pszMDConflictValue = "*";
-    int                  bSetColorInterpretation = FALSE;
-    char               **papszOpenOptions = NULL;
-    int                  nOvLevel = -2;
-    CPLString            osTE_SRS;
-
-    /* Check that we are running against at least GDAL 1.6 */
-    /* Note to developers : if we use newer API, please change the requirement */
-    if (atoi(GDALVersionInfo("VERSION_NUM")) < 1600)
-    {
-        fprintf(stderr, "At least, GDAL >= 1.6.0 is required for this version of %s, "
-                "which was compiled against GDAL %s\n", argv[0], GDAL_RELEASE_NAME);
-        GDALExit(1);
-    }
-
-    EarlySetConfigOptions(argc, argv);
-
-/* -------------------------------------------------------------------- */
-/*      Register standard GDAL drivers, and process generic GDAL        */
-/*      command options.                                                */
-/* -------------------------------------------------------------------- */
-    GDALAllRegister();
-    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
-    if( argc < 1 )
-        GDALExit( -argc );
-
-/* -------------------------------------------------------------------- */
-/*      Set optimal setting for best performance with huge input VRT.   */
-/*      The rationale for 450 is that typical Linux process allow       */
-/*      only 1024 file descriptors per process and we need to keep some */
-/*      spare for shared libraries, etc. so let's go down to 900.       */
-/*      And some datasets may need 2 file descriptors, so divide by 2   */
-/*      for security.                                                   */
-/* -------------------------------------------------------------------- */
-    if( CPLGetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", NULL) == NULL )
-    {
-        CPLSetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", "450");
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Parse arguments.                                                */
-/* -------------------------------------------------------------------- */
-    for( i = 1; i < argc; i++ )
-    {
-        if( EQUAL(argv[i],"-tps") || EQUAL(argv[i],"-rpc") || EQUAL(argv[i],"-geoloc")  )
-        {
-            const char* pszMethod = CSLFetchNameValue(papszTO, "METHOD");
-            if (pszMethod)
-                fprintf(stderr, "Warning: only one METHOD can be used. Method %s is already defined.\n",
-                        pszMethod);
-            const char* pszMAX_GCP_ORDER = CSLFetchNameValue(papszTO, "MAX_GCP_ORDER");
-            if (pszMAX_GCP_ORDER)
-                fprintf(stderr, "Warning: only one METHOD can be used. -order %s option was specified, so it is likely that GCP_POLYNOMIAL was implied.\n",
-                        pszMAX_GCP_ORDER);
-        }
-
-        if( EQUAL(argv[i], "--utility_version") )
-        {
-            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
-                   argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
-            return 0;
-        }
-        else if( EQUAL(argv[i],"--help") )
-            Usage();
-        else if( EQUAL(argv[i],"-co") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            papszCreateOptions = CSLAddString( papszCreateOptions, argv[++i] );
-            bCreateOutput = TRUE;
-        }   
-        else if( EQUAL(argv[i],"-wo") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            papszWarpOptions = CSLAddString( papszWarpOptions, argv[++i] );
-        }   
-        else if( EQUAL(argv[i],"-multi") )
-        {
-            bMulti = TRUE;
-        }   
-        else if( EQUAL(argv[i],"-q") || EQUAL(argv[i],"-quiet"))
-        {
-            bQuiet = TRUE;
-        }   
-        else if( EQUAL(argv[i],"-dstalpha") )
-        {
-            bEnableDstAlpha = TRUE;
-        }
-        else if( EQUAL(argv[i],"-srcalpha") )
-        {
-            bEnableSrcAlpha = TRUE;
-        }
-        else if( EQUAL(argv[i],"-of") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszFormat = argv[++i];
-            bFormatExplicitlySet = TRUE;
-            bCreateOutput = TRUE;
-            if( EQUAL(pszFormat,"VRT") )
-                bVRT = TRUE;
-        }
-        else if( EQUAL(argv[i],"-t_srs") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            char *pszSRS = SanitizeSRS(argv[++i]);
-            papszTO = CSLSetNameValue( papszTO, "DST_SRS", pszSRS );
-            CPLFree( pszSRS );
-        }
-        else if( EQUAL(argv[i],"-s_srs") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            char *pszSRS = SanitizeSRS(argv[++i]);
-            papszTO = CSLSetNameValue( papszTO, "SRC_SRS", pszSRS );
-            CPLFree( pszSRS );
-        }
-        else if( EQUAL(argv[i],"-order") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            const char* pszMethod = CSLFetchNameValue(papszTO, "METHOD");
-            if (pszMethod)
-                fprintf(stderr, "Warning: only one METHOD can be used. Method %s is already defined\n",
-                        pszMethod);
-            papszTO = CSLSetNameValue( papszTO, "MAX_GCP_ORDER", argv[++i] );
-        }
-        else if( EQUAL(argv[i],"-refine_gcps") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            papszTO = CSLSetNameValue( papszTO, "REFINE_TOLERANCE", argv[++i] );
-            if(CPLAtof(argv[i]) < 0)
-            {
-                Usage("The tolerance for -refine_gcps may not be negative.");
-            }
-            if (i < argc-1 && atoi(argv[i+1]) >= 0 && isdigit(argv[i+1][0]))
-            {
-                papszTO = CSLSetNameValue( papszTO, "REFINE_MINIMUM_GCPS", argv[++i] );
-            }
-            else
-            {
-                papszTO = CSLSetNameValue( papszTO, "REFINE_MINIMUM_GCPS", "-1" );
-            }
-        }
-        else if( EQUAL(argv[i],"-tps") )
-        {
-            papszTO = CSLSetNameValue( papszTO, "METHOD", "GCP_TPS" );
-        }
-        else if( EQUAL(argv[i],"-rpc") )
-        {
-            papszTO = CSLSetNameValue( papszTO, "METHOD", "RPC" );
-        }
-        else if( EQUAL(argv[i],"-geoloc") )
-        {
-            papszTO = CSLSetNameValue( papszTO, "METHOD", "GEOLOC_ARRAY" );
-        }
-        else if( EQUAL(argv[i],"-to") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            papszTO = CSLAddString( papszTO, argv[++i] );
-        }
-        else if( EQUAL(argv[i],"-et") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            dfErrorThreshold = CPLAtofM(argv[++i]);
-            papszWarpOptions = CSLAddString( papszWarpOptions, CPLSPrintf("ERROR_THRESHOLD=%.16g", dfErrorThreshold) );
-        }
-        else if( EQUAL(argv[i],"-wm") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            if( CPLAtofM(argv[i+1]) < 10000 )
-                dfWarpMemoryLimit = CPLAtofM(argv[i+1]) * 1024 * 1024;
-            else
-                dfWarpMemoryLimit = CPLAtofM(argv[i+1]);
-            i++;
-        }
-        else if( EQUAL(argv[i],"-srcnodata") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszSrcNodata = argv[++i];
-        }
-        else if( EQUAL(argv[i],"-dstnodata") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszDstNodata = argv[++i];
-        }
-        else if( EQUAL(argv[i],"-tr") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2);
-            dfXRes = CPLAtofM(argv[++i]);
-            dfYRes = fabs(CPLAtofM(argv[++i]));
-            if( dfXRes == 0 || dfYRes == 0 )
-            {
-                Usage("Wrong value for -tr parameters.");
-            }
-            bCreateOutput = TRUE;
-        }
-        else if( EQUAL(argv[i],"-tap") )
-        {
-            bTargetAlignedPixels = TRUE;
-        }
-        else if( EQUAL(argv[i],"-ot") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            int	iType;
-            
-            for( iType = 1; iType < GDT_TypeCount; iType++ )
-            {
-                if( GDALGetDataTypeName((GDALDataType)iType) != NULL
-                    && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
-                             argv[i+1]) )
-                {
-                    eOutputType = (GDALDataType) iType;
-                }
-            }
-
-            if( eOutputType == GDT_Unknown )
-            {
-                Usage(CPLSPrintf( "Unknown output pixel type: %s.", argv[i+1] ));
-            }
-            i++;
-            bCreateOutput = TRUE;
-        }
-        else if( EQUAL(argv[i],"-wt") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            int	iType;
-            
-            for( iType = 1; iType < GDT_TypeCount; iType++ )
-            {
-                if( GDALGetDataTypeName((GDALDataType)iType) != NULL
-                    && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
-                             argv[i+1]) )
-                {
-                    eWorkingType = (GDALDataType) iType;
-                }
-            }
-
-            if( eWorkingType == GDT_Unknown )
-            {
-                Usage(CPLSPrintf( "Unknown working pixel type: %s.", argv[i+1] ));
-            }
-            i++;
-        }
-        else if( EQUAL(argv[i],"-ts") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2);
-            nForcePixels = atoi(argv[++i]);
-            nForceLines = atoi(argv[++i]);
-            bCreateOutput = TRUE;
-        }
-        else if( EQUAL(argv[i],"-te") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(4);
-            dfMinX = CPLAtofM(argv[++i]);
-            dfMinY = CPLAtofM(argv[++i]);
-            dfMaxX = CPLAtofM(argv[++i]);
-            dfMaxY = CPLAtofM(argv[++i]);
-            bCreateOutput = TRUE;
-        }
-        else if( EQUAL(argv[i],"-te_srs") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            char *pszSRS = SanitizeSRS(argv[++i]);
-            osTE_SRS = pszSRS;
-            CPLFree(pszSRS);
-            bCreateOutput = TRUE;
-        }
-        else if( EQUAL(argv[i],"-rn") )
-            eResampleAlg = GRA_NearestNeighbour;
-
-        else if( EQUAL(argv[i],"-rb") )
-            eResampleAlg = GRA_Bilinear;
-
-        else if( EQUAL(argv[i],"-rc") )
-            eResampleAlg = GRA_Cubic;
-
-        else if( EQUAL(argv[i],"-rcs") )
-            eResampleAlg = GRA_CubicSpline;
-
-        else if( EQUAL(argv[i],"-rl") )
-            eResampleAlg = GRA_Lanczos;
-
-        else if( EQUAL(argv[i],"-ra") )
-            eResampleAlg = GRA_Average;
-
-        else if( EQUAL(argv[i],"-rm") )
-            eResampleAlg = GRA_Mode;
-
-        else if( EQUAL(argv[i],"-r") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            if ( EQUAL(argv[++i], "near") )
-                eResampleAlg = GRA_NearestNeighbour;
-            else if ( EQUAL(argv[i], "bilinear") )
-                eResampleAlg = GRA_Bilinear;
-            else if ( EQUAL(argv[i], "cubic") )
-                eResampleAlg = GRA_Cubic;
-            else if ( EQUAL(argv[i], "cubicspline") )
-                eResampleAlg = GRA_CubicSpline;
-            else if ( EQUAL(argv[i], "lanczos") )
-                eResampleAlg = GRA_Lanczos;
-            else if ( EQUAL(argv[i], "average") )
-                eResampleAlg = GRA_Average;
-            else if ( EQUAL(argv[i], "mode") )
-                eResampleAlg = GRA_Mode;
-            else if ( EQUAL(argv[i], "max") )
-                eResampleAlg = GRA_Max;
-            else if ( EQUAL(argv[i], "min") )
-                eResampleAlg = GRA_Min;
-            else if ( EQUAL(argv[i], "med") )
-                eResampleAlg = GRA_Med;
-            else if ( EQUAL(argv[i], "q1") )
-                eResampleAlg = GRA_Q1;
-            else if ( EQUAL(argv[i], "q3") )
-                eResampleAlg = GRA_Q3;
-            else
-            {
-                Usage(CPLSPrintf( "Unknown resampling method: \"%s\".", argv[i] ));
-            }
-        }
-
-        else if( EQUAL(argv[i],"-cutline") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszCutlineDSName = argv[++i];
-        }
-        else if( EQUAL(argv[i],"-cwhere") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszCWHERE = argv[++i];
-        }
-        else if( EQUAL(argv[i],"-cl") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszCLayer = argv[++i];
-        }
-        else if( EQUAL(argv[i],"-csql") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszCSQL = argv[++i];
-        }
-        else if( EQUAL(argv[i],"-cblend") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            papszWarpOptions = 
-                CSLSetNameValue( papszWarpOptions, 
-                                 "CUTLINE_BLEND_DIST", argv[++i] );
-        }
-        else if( EQUAL(argv[i],"-crop_to_cutline")  )
-        {
-            bCropToCutline = TRUE;
-            bCreateOutput = TRUE;
-        }
-        else if( EQUAL(argv[i],"-overwrite") )
-            bOverwrite = TRUE;
-        else if( EQUAL(argv[i],"-nomd") )
-        {
-            bCopyMetadata = FALSE;
-            bCopyBandInfo = FALSE;
-        }   
-        else if( EQUAL(argv[i],"-cvmd") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszMDConflictValue = argv[++i];
-        }
-        else if( EQUAL(argv[i],"-setci") )
-            bSetColorInterpretation = TRUE;
-        else if( EQUAL(argv[i], "-oo") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            papszOpenOptions = CSLAddString( papszOpenOptions,
-                                                argv[++i] );
-        }
-        else if( EQUAL(argv[i], "-ovr") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            const char* pszOvLevel = argv[++i];
-            if( EQUAL(pszOvLevel, "AUTO") )
-                nOvLevel = -2;
-            else if( EQUALN(pszOvLevel,"AUTO-",5) )
-                nOvLevel = -2-atoi(pszOvLevel + 5);
-            else if( EQUAL(pszOvLevel, "NONE") )
-                nOvLevel = -1;
-            else if( CPLGetValueType(pszOvLevel) == CPL_VALUE_INTEGER )
-                nOvLevel = atoi(pszOvLevel); 
-            else
-                Usage(CPLSPrintf("Invalid value '%s' for -ov option", pszOvLevel));
-        }
-        else if( argv[i][0] == '-' )
-            Usage(CPLSPrintf("Unknown option name '%s'", argv[i]));
-
-        else 
-            papszSrcFiles = CSLAddString( papszSrcFiles, argv[i] );
-    }
-/* -------------------------------------------------------------------- */
-/*      Check that incompatible options are not used                    */
-/* -------------------------------------------------------------------- */
-
-    if ((nForcePixels != 0 || nForceLines != 0) && 
-        (dfXRes != 0 && dfYRes != 0))
-    {
-        Usage("-tr and -ts options cannot be used at the same time.");
-    }
-    
-    if (bTargetAlignedPixels && dfXRes == 0 && dfYRes == 0)
-    {
-        Usage("-tap option cannot be used without using -tr.");
-    }
-    
-    if( !bQuiet && !(dfMinX == 0.0 && dfMinY == 0.0 && dfMaxX == 0.0 && dfMaxY == 0.0)  )
-    {
-        if( dfMinX >= dfMaxX )
-            printf("-ts values have minx >= maxx. This will result in a horizontally flipped image.\n");
-        if( dfMinY >= dfMaxY )
-            printf("-ts values have miny >= maxy. This will result in a vertically flipped image.\n");
-    }
-
-/* -------------------------------------------------------------------- */
-/*      The last filename in the file list is really our destination    */
-/*      file.                                                           */
-/* -------------------------------------------------------------------- */
-    if( CSLCount(papszSrcFiles) > 1 )
-    {
-        pszDstFilename = papszSrcFiles[CSLCount(papszSrcFiles)-1];
-        papszSrcFiles[CSLCount(papszSrcFiles)-1] = NULL;
-    }
-
-    if( pszDstFilename == NULL )
-        Usage("No target filename specified.");
-        
-    if( bVRT && CSLCount(papszSrcFiles) > 1 )
-    {
-        fprintf(stderr, "Warning: gdalwarp -of VRT just takes into account "
-                        "the first source dataset.\nIf all source datasets "
-                        "are in the same projection, try making a mosaic of\n"
-                        "them with gdalbuildvrt, and use the resulting "
-                        "VRT file as the input of\ngdalwarp -of VRT.\n");
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Does the output dataset already exist?                          */
-/* -------------------------------------------------------------------- */
-
-    /* FIXME ? source filename=target filename and -overwrite is definitely */
-    /* an error. But I can't imagine of a valid case (without -overwrite), */
-    /* where it would make sense. In doubt, let's keep that dubious possibility... */
-    if ( CSLCount(papszSrcFiles) == 1 &&
-         strcmp(papszSrcFiles[0], pszDstFilename) == 0 && bOverwrite)
-    {
-        fprintf(stderr, "Source and destination datasets must be different.\n");
-        GDALExit( 1 );
-    }
-    
-    int bOutStreaming = FALSE;
-    if( strcmp(pszDstFilename, "/vsistdout/") == 0 )
-    {
-        bQuiet = TRUE;
-        bOutStreaming = TRUE;
-    }
-#ifdef S_ISFIFO
-    else
-    {
-        VSIStatBufL sStat;
-        if( VSIStatExL(pszDstFilename, &sStat, VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG) == 0 &&
-            S_ISFIFO(sStat.st_mode) )
-        {
-            bOutStreaming = TRUE;
-        }
-    }
-#endif
-
-    if( bOutStreaming )
-    {
-        papszWarpOptions = CSLSetNameValue(papszWarpOptions, "STREAMABLE_OUTPUT", "YES");
-        hDstDS = NULL;
-    }
-    else
-    {
-        CPLPushErrorHandler( CPLQuietErrorHandler );
-        hDstDS = GDALOpen( pszDstFilename, GA_Update );
-        CPLPopErrorHandler();
-    }
-
-    if( hDstDS != NULL && bOverwrite )
-    {
-        GDALClose(hDstDS);
-        hDstDS = NULL;
-    }
-
-    if( hDstDS != NULL && bCreateOutput )
-    {
-        fprintf( stderr, 
-                 "Output dataset %s exists,\n"
-                 "but some commandline options were provided indicating a new dataset\n"
-                 "should be created.  Please delete existing dataset and run again.\n",
-                 pszDstFilename );
-        GDALExit( 1 );
-    }
-
-    /* Avoid overwriting an existing destination file that cannot be opened in */
-    /* update mode with a new GTiff file */
-    if ( !bOutStreaming && hDstDS == NULL && !bOverwrite )
-    {
-        CPLPushErrorHandler( CPLQuietErrorHandler );
-        hDstDS = GDALOpen( pszDstFilename, GA_ReadOnly );
-        CPLPopErrorHandler();
-        
-        if (hDstDS)
-        {
-            fprintf( stderr, 
-                     "Output dataset %s exists, but cannot be opened in update mode\n",
-                     pszDstFilename );
-            GDALClose(hDstDS);
-            GDALExit( 1 );
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      -te_srs option                                                  */
-/* -------------------------------------------------------------------- */
-    if( osTE_SRS.size() )
-    {
-        if( dfMinX == 0.0 && dfMinY == 0.0 && dfMaxX == 0.0 && dfMaxY == 0.0 )
-        {
-            fprintf( stderr, "-te_srs ignored since -te is not specified.\n");
-        }
-        else
-        {
-            OGRSpatialReference oSRSIn;
-            oSRSIn.SetFromUserInput(osTE_SRS);
-            OGRSpatialReference oSRSDS;
-            int bOK = FALSE;
-            if( CSLFetchNameValue( papszTO, "DST_SRS" ) != NULL )
-            {
-                oSRSDS.SetFromUserInput( CSLFetchNameValue( papszTO, "DST_SRS" ) );
-                bOK = TRUE;
-            }
-            else if( CSLFetchNameValue( papszTO, "SRC_SRS" ) != NULL )
-            {
-                oSRSDS.SetFromUserInput( CSLFetchNameValue( papszTO, "SRC_SRS" ) );
-                bOK = TRUE;
-            }
-            else
-            {
-                if( papszSrcFiles[0] != NULL )
-                {
-                    GDALDatasetH hSrcDS = GDALOpen( papszSrcFiles[0], GA_ReadOnly );
-                    if( hSrcDS && GDALGetProjectionRef(hSrcDS) && GDALGetProjectionRef(hSrcDS)[0] )
-                    {
-                        oSRSDS.SetFromUserInput( GDALGetProjectionRef(hSrcDS) );
-                        bOK = TRUE;
-                    }
-                    GDALClose(hSrcDS);
-                }
-            }
-            if( !bOK )
-            {
-                fprintf( stderr, "-te_srs ignored since none of -t_srs, -s_srs is specified or the input dataset has no projection.\n");
-                GDALClose(hDstDS);
-                GDALExit( 1 );
-            }
-            if( !oSRSIn.IsSame(&oSRSDS) )
-            {
-                OGRCoordinateTransformation* poCT = OGRCreateCoordinateTransformation(&oSRSIn, &oSRSDS);
-                if( !(poCT &&
-                    poCT->Transform(1, &dfMinX, &dfMinY) &&
-                    poCT->Transform(1, &dfMaxX, &dfMaxY)) )
-                {
-                    OGRCoordinateTransformation::DestroyCT(poCT);
-
-                    fprintf( stderr, "-te_srs ignored since coordinate transformation failed.\n");
-                    GDALClose(hDstDS);
-                    GDALExit( 1 );
-                }
-                delete poCT;
-            }
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      If we have a cutline datasource read it and attach it in the    */
-/*      warp options.                                                   */
-/* -------------------------------------------------------------------- */
-    if( pszCutlineDSName != NULL )
-    {
-        LoadCutline( pszCutlineDSName, pszCLayer, pszCWHERE, pszCSQL,
-                     &hCutline );
-    }
-
-#ifdef OGR_ENABLED
-    if ( bCropToCutline && hCutline != NULL )
-    {
-        CropToCutline( hCutline, papszTO, papszSrcFiles, papszOpenOptions,
-                       dfMinX, dfMinY, dfMaxX, dfMaxY );
-    }
-#endif
-    
-/* -------------------------------------------------------------------- */
-/*      If not, we need to create it.                                   */
-/* -------------------------------------------------------------------- */
-    void* hUniqueTransformArg = NULL;
-    GDALDatasetH hUniqueSrcDS = NULL;
-    int bInitDestSetByUser = ( CSLFetchNameValue( papszWarpOptions, "INIT_DEST" ) != NULL );
-
-    const char* pszWarpThreads = CSLFetchNameValue(papszWarpOptions, "NUM_THREADS");
-    if( pszWarpThreads != NULL )
-    {
-        /* Used by TPS transformer to parallelize direct and inverse matrix computation */
-        papszTO = CSLSetNameValue(papszTO, "NUM_THREADS", pszWarpThreads);
-    }
-
-    if( hDstDS == NULL )
-    {
-        if (!bQuiet && !bFormatExplicitlySet)
-            CheckExtensionConsistency(pszDstFilename, pszFormat);
-
-        hDstDS = GDALWarpCreateOutput( papszSrcFiles, pszDstFilename,pszFormat,
-                                       papszTO, &papszCreateOptions, 
-                                       eOutputType, &hUniqueTransformArg,
-                                       &hUniqueSrcDS, bSetColorInterpretation,
-                                       papszOpenOptions);
-        bCreateOutput = TRUE;
-
-        if( !bInitDestSetByUser )
-        {
-            if ( pszDstNodata == NULL )
-            {
-                papszWarpOptions = CSLSetNameValue(papszWarpOptions,
-                                                "INIT_DEST", "0");
-            }
-            else
-            {
-                papszWarpOptions = CSLSetNameValue(papszWarpOptions,
-                                                "INIT_DEST", "NO_DATA" );
-            }
-        }
-
-        CSLDestroy( papszCreateOptions );
-        papszCreateOptions = NULL;
-    }
- 
-    if( hDstDS == NULL )
-        GDALExit( 1 );
-
-/* -------------------------------------------------------------------- */
-/*      Loop over all source files, processing each in turn.            */
-/* -------------------------------------------------------------------- */
-    int iSrc;
-
-    for( iSrc = 0; papszSrcFiles[iSrc] != NULL; iSrc++ )
-    {
-        GDALDatasetH hSrcDS;
-       
-/* -------------------------------------------------------------------- */
-/*      Open this file.                                                 */
-/* -------------------------------------------------------------------- */
-        if (hUniqueSrcDS)
-            hSrcDS = hUniqueSrcDS;
-        else
-            hSrcDS = GDALOpenEx( papszSrcFiles[iSrc], GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR, NULL,
-                           (const char* const* )papszOpenOptions, NULL );
-    
-        if( hSrcDS == NULL )
-            GDALExit( 2 );
-
-/* -------------------------------------------------------------------- */
-/*      Check that there's at least one raster band                     */
-/* -------------------------------------------------------------------- */
-        if ( GDALGetRasterCount(hSrcDS) == 0 )
-        {     
-            fprintf(stderr, "Input file %s has no raster bands.\n", papszSrcFiles[iSrc] );
-            GDALExit( 1 );
-        }
-
-        if( !bQuiet )
-            printf( "Processing input file %s.\n", papszSrcFiles[iSrc] );
-
-/* -------------------------------------------------------------------- */
-/*      Get the metadata of the first source DS and copy it to the      */
-/*      destination DS. Copy Band-level metadata and other info, only   */
-/*      if source and destination band count are equal. Any values that */
-/*      conflict between source datasets are set to pszMDConflictValue. */
-/* -------------------------------------------------------------------- */
-        if ( bCopyMetadata )
-        {
-            char **papszMetadata = NULL;
-            const char *pszSrcInfo = NULL;
-            const char *pszDstInfo = NULL;
-            GDALRasterBandH hSrcBand = NULL;
-            GDALRasterBandH hDstBand = NULL;
-
-            /* copy metadata from first dataset */
-            if ( iSrc == 0 )
-            {
-                CPLDebug("WARP", "Copying metadata from first source to destination dataset");
-                /* copy dataset-level metadata */
-                papszMetadata = GDALGetMetadata( hSrcDS, NULL );
-
-                char** papszMetadataNew = NULL;
-                for( int i = 0; papszMetadata != NULL && papszMetadata[i] != NULL; i++ )
-                {
-                    // Do not preserve NODATA_VALUES when the output includes an alpha band
-                    if( bEnableDstAlpha &&
-                        EQUALN(papszMetadata[i], "NODATA_VALUES=", strlen("NODATA_VALUES=")) )
-                    {
-                        continue;
-                    }
-
-                    papszMetadataNew = CSLAddString(papszMetadataNew, papszMetadata[i]);
-                }
-
-                if ( CSLCount(papszMetadataNew) > 0 ) {
-                    if ( GDALSetMetadata( hDstDS, papszMetadataNew, NULL ) != CE_None )
-                         fprintf( stderr, 
-                                  "Warning: error copying metadata to destination dataset.\n" );
-                }
-
-                CSLDestroy(papszMetadataNew);
-
-                /* copy band-level metadata and other info */
-                if ( GDALGetRasterCount( hSrcDS ) == GDALGetRasterCount( hDstDS ) )              
-                {
-                    for ( int iBand = 0; iBand < GDALGetRasterCount( hSrcDS ); iBand++ )
-                    {
-                        hSrcBand = GDALGetRasterBand( hSrcDS, iBand + 1 );
-                        hDstBand = GDALGetRasterBand( hDstDS, iBand + 1 );
-                        /* copy metadata, except stats (#5319) */
-                        papszMetadata = GDALGetMetadata( hSrcBand, NULL);              
-                        if ( CSLCount(papszMetadata) > 0 )
-                        {
-                            //GDALSetMetadata( hDstBand, papszMetadata, NULL );       
-                            char** papszMetadataNew = NULL;
-                            for( int i = 0; papszMetadata != NULL && papszMetadata[i] != NULL; i++ )
-                            {
-                                if (strncmp(papszMetadata[i], "STATISTICS_", 11) != 0)
-                                    papszMetadataNew = CSLAddString(papszMetadataNew, papszMetadata[i]);
-                            }
-                            GDALSetMetadata( hDstBand, papszMetadataNew, NULL );
-                            CSLDestroy(papszMetadataNew);
-                        }
-                        /* copy other info (Description, Unit Type) - what else? */
-                        if ( bCopyBandInfo ) {
-                            pszSrcInfo = GDALGetDescription( hSrcBand );
-                            if(  pszSrcInfo != NULL && strlen(pszSrcInfo) > 0 )
-                                GDALSetDescription( hDstBand, pszSrcInfo );  
-                            pszSrcInfo = GDALGetRasterUnitType( hSrcBand );
-                            if(  pszSrcInfo != NULL && strlen(pszSrcInfo) > 0 )
-                                GDALSetRasterUnitType( hDstBand, pszSrcInfo );  
-                        }
-                    }
-                }
-            }
-            /* remove metadata that conflicts between datasets */
-            else 
-            {
-                CPLDebug("WARP", 
-                         "Removing conflicting metadata from destination dataset (source #%d)", iSrc );
-                /* remove conflicting dataset-level metadata */
-                RemoveConflictingMetadata( hDstDS, GDALGetMetadata( hSrcDS, NULL ), pszMDConflictValue );
-                
-                /* remove conflicting copy band-level metadata and other info */
-                if ( GDALGetRasterCount( hSrcDS ) == GDALGetRasterCount( hDstDS ) )              
-                {
-                    for ( int iBand = 0; iBand < GDALGetRasterCount( hSrcDS ); iBand++ )
-                    {
-                        hSrcBand = GDALGetRasterBand( hSrcDS, iBand + 1 );
-                        hDstBand = GDALGetRasterBand( hDstDS, iBand + 1 );
-                        /* remove conflicting metadata */
-                        RemoveConflictingMetadata( hDstBand, GDALGetMetadata( hSrcBand, NULL ), pszMDConflictValue );
-                        /* remove conflicting info */
-                        if ( bCopyBandInfo ) {
-                            pszSrcInfo = GDALGetDescription( hSrcBand );
-                            pszDstInfo = GDALGetDescription( hDstBand );
-                            if( ! ( pszSrcInfo != NULL && strlen(pszSrcInfo) > 0  &&
-                                    pszDstInfo != NULL && strlen(pszDstInfo) > 0  &&
-                                    EQUAL( pszSrcInfo, pszDstInfo ) ) )
-                                GDALSetDescription( hDstBand, "" );  
-                            pszSrcInfo = GDALGetRasterUnitType( hSrcBand );
-                            pszDstInfo = GDALGetRasterUnitType( hDstBand );
-                            if( ! ( pszSrcInfo != NULL && strlen(pszSrcInfo) > 0  &&
-                                    pszDstInfo != NULL && strlen(pszDstInfo) > 0  &&
-                                    EQUAL( pszSrcInfo, pszDstInfo ) ) )
-                                GDALSetRasterUnitType( hDstBand, "" );  
-                        }
-                    }
-                }
-            }          
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Warns if the file has a color table and something more          */
-/*      complicated than nearest neighbour resampling is asked          */
-/* -------------------------------------------------------------------- */
- 
-        if ( eResampleAlg != GRA_NearestNeighbour &&
-             eResampleAlg != GRA_Mode &&
-             GDALGetRasterColorTable(GDALGetRasterBand(hSrcDS, 1)) != NULL)
-        {
-            if( !bQuiet )
-                fprintf( stderr, "Warning: Input file %s has a color table, which will likely lead to "
-                        "bad results when using a resampling method other than "
-                        "nearest neighbour or mode. Converting the dataset prior to 24/32 bit "
-                        "is advised.\n", papszSrcFiles[iSrc] );
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Do we have a source alpha band?                                 */
-/* -------------------------------------------------------------------- */
-        if( GDALGetRasterColorInterpretation( 
-                GDALGetRasterBand(hSrcDS,GDALGetRasterCount(hSrcDS)) ) 
-            == GCI_AlphaBand 
-            && !bEnableSrcAlpha )
-        {
-            bEnableSrcAlpha = TRUE;
-            if( !bQuiet )
-                printf( "Using band %d of source image as alpha.\n", 
-                        GDALGetRasterCount(hSrcDS) );
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Create a transformation object from the source to               */
-/*      destination coordinate system.                                  */
-/* -------------------------------------------------------------------- */
-        if (hUniqueTransformArg)
-            hTransformArg = hUniqueTransformArg;
-        else
-            hTransformArg =
-                GDALCreateGenImgProjTransformer2( hSrcDS, hDstDS, papszTO );
-        
-        if( hTransformArg == NULL )
-            GDALExit( 1 );
-
-        pfnTransformer = GDALGenImgProjTransform;
-
-/* -------------------------------------------------------------------- */
-/*      Determine if we must work with the full-resolution source       */
-/*      dataset, or one of its overview level.                          */
-/* -------------------------------------------------------------------- */
-        GDALDataset* poSrcDS = (GDALDataset*) hSrcDS;
-        GDALDataset* poSrcOvrDS = NULL;
-        int nOvCount = poSrcDS->GetRasterBand(1)->GetOverviewCount();
-        if( nOvLevel <= -2 && nOvCount > 0 )
-        {
-            double adfSuggestedGeoTransform[6];
-            double adfExtent[4];
-            int    nPixels, nLines;
-            /* Compute what the "natural" output resolution (in pixels) would be for this */
-            /* input dataset */
-            if( GDALSuggestedWarpOutput2(hSrcDS, pfnTransformer, hTransformArg,
-                                         adfSuggestedGeoTransform, &nPixels, &nLines,
-                                         adfExtent, 0) == CE_None)
-            {
-                double dfTargetRatio = 1.0 / adfSuggestedGeoTransform[1];
-                if( dfTargetRatio > 1.0 )
-                {
-                    int iOvr;
-                    for( iOvr = -1; iOvr < nOvCount-1; iOvr++ )
-                    {
-                        double dfOvrRatio = (iOvr < 0) ? 1.0 : (double)poSrcDS->GetRasterXSize() /
-                            poSrcDS->GetRasterBand(1)->GetOverview(iOvr)->GetXSize();
-                        double dfNextOvrRatio = (double)poSrcDS->GetRasterXSize() /
-                            poSrcDS->GetRasterBand(1)->GetOverview(iOvr+1)->GetXSize();
-                        if( dfOvrRatio < dfTargetRatio && dfNextOvrRatio > dfTargetRatio )
-                            break;
-                        if( fabs(dfOvrRatio - dfTargetRatio) < 1e-1 )
-                            break;
-                    }
-                    iOvr += (nOvLevel+2);
-                    if( iOvr >= 0 )
-                    {
-                        CPLDebug("WARP", "Selecting overview level %d for %s",
-                                 iOvr, papszSrcFiles[iSrc]);
-                        poSrcOvrDS = GDALCreateOverviewDataset( poSrcDS, iOvr, FALSE, FALSE );
-                    }
-                }
-            }
-        }
-        else if( nOvLevel >= 0 )
-        {
-            poSrcOvrDS = GDALCreateOverviewDataset( poSrcDS, nOvLevel, TRUE, FALSE );
-            if( poSrcOvrDS == NULL )
-            {
-                if( !bQuiet )
-                {
-                    fprintf(stderr, "Warning: cannot get overview level %d for "
-                            "dataset %s. Defaulting to level %d\n",
-                            nOvLevel, papszSrcFiles[iSrc], nOvCount - 1);
-                }
-                if( nOvCount > 0 )
-                    poSrcOvrDS = GDALCreateOverviewDataset( poSrcDS, nOvCount - 1, FALSE, FALSE );
-            }
-            else
-            {
-                CPLDebug("WARP", "Selecting overview level %d for %s",
-                         nOvLevel, papszSrcFiles[iSrc]);
-            }
-        }
-
-        GDALDatasetH hWrkSrcDS = (poSrcOvrDS) ? (GDALDatasetH)poSrcOvrDS : hSrcDS;
-
-        /* We need to recreate the transform when operating on an overview */
-        if( poSrcOvrDS != NULL )
-        {
-            GDALDestroyGenImgProjTransformer( hTransformArg );
-            hTransformArg =
-                GDALCreateGenImgProjTransformer2( hWrkSrcDS, hDstDS, papszTO );
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Warp the transformer with a linear approximator unless the      */
-/*      acceptable error is zero.                                       */
-/* -------------------------------------------------------------------- */
-        if( dfErrorThreshold != 0.0 )
-        {
-            hTransformArg =
-                GDALCreateApproxTransformer( GDALGenImgProjTransform, 
-                                             hTransformArg, dfErrorThreshold);
-            pfnTransformer = GDALApproxTransform;
-            GDALApproxTransformerOwnsSubtransformer(hTransformArg, TRUE);
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Clear temporary INIT_DEST settings after the first image.       */
-/* -------------------------------------------------------------------- */
-        if( bCreateOutput && iSrc == 1 )
-            papszWarpOptions = CSLSetNameValue( papszWarpOptions, 
-                                                "INIT_DEST", NULL );
-
-/* -------------------------------------------------------------------- */
-/*      Setup warp options.                                             */
-/* -------------------------------------------------------------------- */
-        GDALWarpOptions *psWO = GDALCreateWarpOptions();
-
-        psWO->papszWarpOptions = CSLDuplicate(papszWarpOptions);
-        psWO->eWorkingDataType = eWorkingType;
-        psWO->eResampleAlg = eResampleAlg;
-
-        psWO->hSrcDS = hWrkSrcDS;
-        psWO->hDstDS = hDstDS;
-
-        psWO->pfnTransformer = pfnTransformer;
-        psWO->pTransformerArg = hTransformArg;
-
-        if( !bQuiet )
-            psWO->pfnProgress = GDALTermProgress;
-
-        if( dfWarpMemoryLimit != 0.0 )
-            psWO->dfWarpMemoryLimit = dfWarpMemoryLimit;
-
-/* -------------------------------------------------------------------- */
-/*      Setup band mapping.                                             */
-/* -------------------------------------------------------------------- */
-        if( bEnableSrcAlpha )
-            psWO->nBandCount = GDALGetRasterCount(hWrkSrcDS) - 1;
-        else
-            psWO->nBandCount = GDALGetRasterCount(hWrkSrcDS);
-
-        psWO->panSrcBands = (int *) CPLMalloc(psWO->nBandCount*sizeof(int));
-        psWO->panDstBands = (int *) CPLMalloc(psWO->nBandCount*sizeof(int));
-
-        for( i = 0; i < psWO->nBandCount; i++ )
-        {
-            psWO->panSrcBands[i] = i+1;
-            psWO->panDstBands[i] = i+1;
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Setup alpha bands used if any.                                  */
-/* -------------------------------------------------------------------- */
-        if( bEnableSrcAlpha )
-            psWO->nSrcAlphaBand = GDALGetRasterCount(hWrkSrcDS);
-
-        if( !bEnableDstAlpha 
-            && GDALGetRasterCount(hDstDS) == psWO->nBandCount+1 
-            && GDALGetRasterColorInterpretation( 
-                GDALGetRasterBand(hDstDS,GDALGetRasterCount(hDstDS))) 
-            == GCI_AlphaBand )
-        {
-            if( !bQuiet )
-                printf( "Using band %d of destination image as alpha.\n", 
-                        GDALGetRasterCount(hDstDS) );
-                
-            bEnableDstAlpha = TRUE;
-        }
-
-        if( bEnableDstAlpha )
-            psWO->nDstAlphaBand = GDALGetRasterCount(hDstDS);
-
-/* -------------------------------------------------------------------- */
-/*      Setup NODATA options.                                           */
-/* -------------------------------------------------------------------- */
-        if( pszSrcNodata != NULL && !EQUAL(pszSrcNodata,"none") )
-        {
-            char **papszTokens = CSLTokenizeString( pszSrcNodata );
-            int  nTokenCount = CSLCount(papszTokens);
-
-            psWO->padfSrcNoDataReal = (double *) 
-                CPLMalloc(psWO->nBandCount*sizeof(double));
-            psWO->padfSrcNoDataImag = (double *) 
-                CPLMalloc(psWO->nBandCount*sizeof(double));
-
-            for( i = 0; i < psWO->nBandCount; i++ )
-            {
-                if( i < nTokenCount )
-                {
-                    CPLStringToComplex( papszTokens[i], 
-                                        psWO->padfSrcNoDataReal + i,
-                                        psWO->padfSrcNoDataImag + i );
-                }
-                else
-                {
-                    psWO->padfSrcNoDataReal[i] = psWO->padfSrcNoDataReal[i-1];
-                    psWO->padfSrcNoDataImag[i] = psWO->padfSrcNoDataImag[i-1];
-                }
-            }
-
-            CSLDestroy( papszTokens );
-
-            psWO->papszWarpOptions = CSLSetNameValue(psWO->papszWarpOptions,
-                                               "UNIFIED_SRC_NODATA", "YES" );
-        }
-
-/* -------------------------------------------------------------------- */
-/*      If -srcnodata was not specified, but the data has nodata        */
-/*      values, use them.                                               */
-/* -------------------------------------------------------------------- */
-        if( pszSrcNodata == NULL )
-        {
-            int bHaveNodata = FALSE;
-            double dfReal = 0.0;
-
-            for( i = 0; !bHaveNodata && i < psWO->nBandCount; i++ )
-            {
-                GDALRasterBandH hBand = GDALGetRasterBand( hWrkSrcDS, i+1 );
-                dfReal = GDALGetRasterNoDataValue( hBand, &bHaveNodata );
-            }
-
-            if( bHaveNodata )
-            {
-                if( !bQuiet )
-                {
-                    if (CPLIsNan(dfReal))
-                        printf( "Using internal nodata values (e.g. nan) for image %s.\n",
-                                papszSrcFiles[iSrc] );
-                    else
-                        printf( "Using internal nodata values (e.g. %g) for image %s.\n",
-                                dfReal, papszSrcFiles[iSrc] );
-                }
-                psWO->padfSrcNoDataReal = (double *) 
-                    CPLMalloc(psWO->nBandCount*sizeof(double));
-                psWO->padfSrcNoDataImag = (double *) 
-                    CPLMalloc(psWO->nBandCount*sizeof(double));
-                
-                for( i = 0; i < psWO->nBandCount; i++ )
-                {
-                    GDALRasterBandH hBand = GDALGetRasterBand( hWrkSrcDS, i+1 );
-
-                    dfReal = GDALGetRasterNoDataValue( hBand, &bHaveNodata );
-
-                    if( bHaveNodata )
-                    {
-                        psWO->padfSrcNoDataReal[i] = dfReal;
-                        psWO->padfSrcNoDataImag[i] = 0.0;
-                    }
-                    else
-                    {
-                        psWO->padfSrcNoDataReal[i] = -123456.789;
-                        psWO->padfSrcNoDataImag[i] = 0.0;
-                    }
-                }
-            }
-        }
-
-/* -------------------------------------------------------------------- */
-/*      If the output dataset was created, and we have a destination    */
-/*      nodata value, go through marking the bands with the information.*/
-/* -------------------------------------------------------------------- */
-        if( pszDstNodata != NULL && !EQUAL(pszDstNodata,"none") )
-        {
-            char **papszTokens = CSLTokenizeString( pszDstNodata );
-            int  nTokenCount = CSLCount(papszTokens);
-            int bDstNoDataNone = TRUE;
-
-            psWO->padfDstNoDataReal = (double *) 
-                CPLMalloc(psWO->nBandCount*sizeof(double));
-            psWO->padfDstNoDataImag = (double *) 
-                CPLMalloc(psWO->nBandCount*sizeof(double));
-
-            for( i = 0; i < psWO->nBandCount; i++ )
-            {
-                psWO->padfDstNoDataReal[i] = -1.1e20;
-                psWO->padfDstNoDataImag[i] = 0.0;
-
-                if( i < nTokenCount )
-                {
-                    if ( papszTokens[i] != NULL && EQUAL(papszTokens[i],"none") )
-                    {
-                        CPLDebug( "WARP", "dstnodata of band %d not set", i );
-                        bDstNoDataNone = TRUE;
-                        continue;
-                    }
-                    else if ( papszTokens[i] == NULL ) // this shouldn't happen, but just in case
-                    {
-                        fprintf( stderr, "Error parsing dstnodata arg #%d\n", i );
-                        bDstNoDataNone = TRUE;
-                        continue;
-                    }
-                    CPLStringToComplex( papszTokens[i], 
-                                        psWO->padfDstNoDataReal + i,
-                                        psWO->padfDstNoDataImag + i );
-                    bDstNoDataNone = FALSE;
-                    CPLDebug( "WARP", "dstnodata of band %d set to %f", i, psWO->padfDstNoDataReal[i] );
-                }
-                else
-                {
-                    if ( ! bDstNoDataNone )
-                    {                    
-                        psWO->padfDstNoDataReal[i] = psWO->padfDstNoDataReal[i-1];
-                        psWO->padfDstNoDataImag[i] = psWO->padfDstNoDataImag[i-1];
-                        CPLDebug( "WARP", "dstnodata of band %d set from previous band", i );
-                    }
-                    else
-                    {
-                        CPLDebug( "WARP", "dstnodata value of band %d not set", i );
-                        continue;
-                    }
-                }
-                
-                GDALRasterBandH hBand = GDALGetRasterBand( hDstDS, i+1 );
-                int bClamped = FALSE, bRounded = FALSE;
-
-#define CLAMP(val,type,minval,maxval) \
-    do { if (val < minval) { bClamped = TRUE; val = minval; } \
-    else if (val > maxval) { bClamped = TRUE; val = maxval; } \
-    else if (val != (type)val) { bRounded = TRUE; val = (type)(val + 0.5); } } \
-    while(0)
-
-                switch(GDALGetRasterDataType(hBand))
-                {
-                    case GDT_Byte:
-                        CLAMP(psWO->padfDstNoDataReal[i], GByte,
-                              0.0, 255.0);
-                        break;
-                    case GDT_Int16:
-                        CLAMP(psWO->padfDstNoDataReal[i], GInt16,
-                              -32768.0, 32767.0);
-                        break;
-                    case GDT_UInt16:
-                        CLAMP(psWO->padfDstNoDataReal[i], GUInt16,
-                              0.0, 65535.0);
-                        break;
-                    case GDT_Int32:
-                        CLAMP(psWO->padfDstNoDataReal[i], GInt32,
-                              -2147483648.0, 2147483647.0);
-                        break;
-                    case GDT_UInt32:
-                        CLAMP(psWO->padfDstNoDataReal[i], GUInt32,
-                              0.0, 4294967295.0);
-                        break;
-                    default:
-                        break;
-                }
-                    
-                if (bClamped)
-                {
-                    printf( "for band %d, destination nodata value has been clamped "
-                           "to %.0f, the original value being out of range.\n",
-                           i + 1, psWO->padfDstNoDataReal[i]);
-                }
-                else if(bRounded)
-                {
-                    printf("for band %d, destination nodata value has been rounded "
-                           "to %.0f, %s being an integer datatype.\n",
-                           i + 1, psWO->padfDstNoDataReal[i],
-                           GDALGetDataTypeName(GDALGetRasterDataType(hBand)));
-                }
-
-                if( bCreateOutput )
-                {
-                    GDALSetRasterNoDataValue( 
-                        GDALGetRasterBand( hDstDS, psWO->panDstBands[i] ), 
-                        psWO->padfDstNoDataReal[i] );
-                }
-            }
-
-            CSLDestroy( papszTokens );
-        }
-
-        /* else try to fill dstNoData from source bands */
-        if ( pszDstNodata == NULL && psWO->padfSrcNoDataReal != NULL )
-        {
-            psWO->padfDstNoDataReal = (double *) 
-                CPLMalloc(psWO->nBandCount*sizeof(double));
-            psWO->padfDstNoDataImag = (double *) 
-                CPLMalloc(psWO->nBandCount*sizeof(double));
-
-            if( !bQuiet )
-                printf( "Copying nodata values from source %s to destination %s.\n",
-                        papszSrcFiles[iSrc], pszDstFilename );
-
-            for( i = 0; i < psWO->nBandCount; i++ )
-            {
-                psWO->padfDstNoDataReal[i] = psWO->padfSrcNoDataReal[i];
-                psWO->padfDstNoDataImag[i] = psWO->padfSrcNoDataImag[i];
-                CPLDebug("WARP", "srcNoData=%f dstNoData=%f", 
-                            psWO->padfSrcNoDataReal[i], psWO->padfDstNoDataReal[i] );
-
-                if( bCreateOutput )
-                {
-                    CPLDebug("WARP", "calling GDALSetRasterNoDataValue() for band#%d", i );
-                    GDALSetRasterNoDataValue( 
-                        GDALGetRasterBand( hDstDS, psWO->panDstBands[i] ), 
-                        psWO->padfDstNoDataReal[i] );
-                }
-            }
-
-            if( bCreateOutput && !bInitDestSetByUser && iSrc == 0 )
-            {
-                /* As we didn't know at the beginning if there was source nodata */
-                /* we have initialized INIT_DEST=0. Override this with NO_DATA now */
-                psWO->papszWarpOptions = CSLSetNameValue(psWO->papszWarpOptions,
-                                                   "INIT_DEST", "NO_DATA" );
-            }
-        }
-
-/* -------------------------------------------------------------------- */
-/*      If we have a cutline, transform it into the source              */
-/*      pixel/line coordinate system and insert into warp options.      */
-/* -------------------------------------------------------------------- */
-        if( hCutline != NULL )
-        {
-            TransformCutlineToSource( hWrkSrcDS, hCutline, 
-                                      &(psWO->papszWarpOptions), 
-                                      papszTO );
-        }
-
-/* -------------------------------------------------------------------- */
-/*      If we are producing VRT output, then just initialize it with    */
-/*      the warp options and write out now rather than proceeding       */
-/*      with the operations.                                            */
-/* -------------------------------------------------------------------- */
-        if( bVRT )
-        {
-            GDALSetMetadataItem(hDstDS, "SrcOvrLevel", CPLSPrintf("%d", nOvLevel), NULL);
-            if( GDALInitializeWarpedVRT( hDstDS, psWO ) != CE_None )
-                GDALExit( 1 );
-
-            GDALClose( hDstDS );
-            if( poSrcOvrDS )
-                delete poSrcOvrDS;
-            GDALClose( hSrcDS );
-
-            GDALDestroyWarpOptions( psWO );
-
-            CPLFree( pszDstFilename );
-            CSLDestroy( argv );
-            CSLDestroy( papszSrcFiles );
-            CSLDestroy( papszWarpOptions );
-            CSLDestroy( papszTO );
-            CSLDestroy( papszOpenOptions );
-    
-            GDALDumpOpenDatasets( stderr );
-        
-            GDALDestroyDriverManager();
-        
-            return 0;
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Initialize and execute the warp.                                */
-/* -------------------------------------------------------------------- */
-        GDALWarpOperation oWO;
-
-        if( oWO.Initialize( psWO ) == CE_None )
-        {
-            CPLErr eErr;
-            if( bMulti )
-                eErr = oWO.ChunkAndWarpMulti( 0, 0, 
-                                       GDALGetRasterXSize( hDstDS ),
-                                       GDALGetRasterYSize( hDstDS ) );
-            else
-                eErr = oWO.ChunkAndWarpImage( 0, 0, 
-                                       GDALGetRasterXSize( hDstDS ),
-                                       GDALGetRasterYSize( hDstDS ) );
-            if (eErr != CE_None)
-                bHasGotErr = TRUE;
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Cleanup                                                         */
-/* -------------------------------------------------------------------- */
-        if( hTransformArg != NULL )
-            GDALDestroyTransformer( hTransformArg );
-        
-        GDALDestroyWarpOptions( psWO );
-
-        if( poSrcOvrDS )
-            delete poSrcOvrDS;
-        GDALClose( hSrcDS );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Final Cleanup.                                                  */
-/* -------------------------------------------------------------------- */
-    CPLErrorReset();
-    GDALFlushCache( hDstDS );
-    if( CPLGetLastErrorType() == CE_Failure )
-        bHasGotErr = TRUE;
-    GDALClose( hDstDS );
-    
-    CPLFree( pszDstFilename );
-    CSLDestroy( argv );
-    CSLDestroy( papszSrcFiles );
-    CSLDestroy( papszWarpOptions );
-    CSLDestroy( papszTO );
-    CSLDestroy( papszOpenOptions );
-
-    GDALDumpOpenDatasets( stderr );
-
-    GDALDestroyDriverManager();
-    
-#ifdef OGR_ENABLED
-    if( hCutline != NULL )
-        OGR_G_DestroyGeometry( (OGRGeometryH) hCutline );
-    OGRCleanupAll();
-#endif
-
-    return (bHasGotErr) ? 1 : 0;
-}
-
-/************************************************************************/
-/*                        GDALWarpCreateOutput()                        */
-/*                                                                      */
-/*      Create the output file based on various commandline options,    */
-/*      and the input file.                                             */
-/*      If there's just one source file, then *phTransformArg and       */
-/*      *phSrcDS will be set, in order them to be reused by main        */
-/*      function. This saves dataset re-opening, and above all transform*/
-/*      recomputation, which can be expensive in the -tps case          */
-/************************************************************************/
-
-static GDALDatasetH 
-GDALWarpCreateOutput( char **papszSrcFiles, const char *pszFilename, 
-                      const char *pszFormat, char **papszTO, 
-                      char ***ppapszCreateOptions, GDALDataType eDT,
-                      void ** phTransformArg,
-                      GDALDatasetH* phSrcDS,
-                      int bSetColorInterpretation,
-                      char** papszOpenOptions)
-
-
-{
-    GDALDriverH hDriver;
-    GDALDatasetH hDstDS;
-    void *hTransformArg;
-    GDALColorTableH hCT = NULL;
-    double dfWrkMinX=0, dfWrkMaxX=0, dfWrkMinY=0, dfWrkMaxY=0;
-    double dfWrkResX=0, dfWrkResY=0;
-    int nDstBandCount = 0;
-    std::vector<GDALColorInterp> apeColorInterpretations;
-
-    /* If (-ts and -te) or (-tr and -te) are specified, we don't need to compute the suggested output extent */
-    int    bNeedsSuggestedWarpOutput = 
-                  !( ((nForcePixels != 0 && nForceLines != 0) || (dfXRes != 0 && dfYRes != 0)) &&
-                     !(dfMinX == 0.0 && dfMinY == 0.0 && dfMaxX == 0.0 && dfMaxY == 0.0) );
-
-    *phTransformArg = NULL;
-    *phSrcDS = NULL;
-
-/* -------------------------------------------------------------------- */
-/*      Find the output driver.                                         */
-/* -------------------------------------------------------------------- */
-    hDriver = GDALGetDriverByName( pszFormat );
-    if( hDriver == NULL 
-        || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) == NULL )
-    {
-        int	iDr;
-        
-        printf( "Output driver `%s' not recognised or does not support\n", 
-                pszFormat );
-        printf( "direct output file creation.  The following format drivers are configured\n"
-                "and support direct output:\n" );
-
-        for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
-        {
-            GDALDriverH hDriver = GDALGetDriver(iDr);
-
-            if( GDALGetMetadataItem( hDriver, GDAL_DCAP_RASTER, NULL) != NULL &&
-                GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL) != NULL )
-            {
-                printf( "  %s: %s\n",
-                        GDALGetDriverShortName( hDriver  ),
-                        GDALGetDriverLongName( hDriver ) );
-            }
-        }
-        printf( "\n" );
-        GDALExit( 1 );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      For virtual output files, we have to set a special subclass     */
-/*      of dataset to create.                                           */
-/* -------------------------------------------------------------------- */
-    if( bVRT )
-        *ppapszCreateOptions = 
-            CSLSetNameValue( *ppapszCreateOptions, "SUBCLASS", 
-                             "VRTWarpedDataset" );
-
-/* -------------------------------------------------------------------- */
-/*      Loop over all input files to collect extents.                   */
-/* -------------------------------------------------------------------- */
-    int     iSrc;
-    char    *pszThisTargetSRS = (char*)CSLFetchNameValue( papszTO, "DST_SRS" );
-    if( pszThisTargetSRS != NULL )
-        pszThisTargetSRS = CPLStrdup( pszThisTargetSRS );
-
-    for( iSrc = 0; papszSrcFiles[iSrc] != NULL; iSrc++ )
-    {
-        GDALDatasetH hSrcDS;
-        const char *pszThisSourceSRS = CSLFetchNameValue(papszTO,"SRC_SRS");
-
-        hSrcDS = GDALOpenEx( papszSrcFiles[iSrc], GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR, NULL,
-                                (const char* const* )papszOpenOptions, NULL );
-        if( hSrcDS == NULL )
-            GDALExit( 1 );
-
-/* -------------------------------------------------------------------- */
-/*      Check that there's at least one raster band                     */
-/* -------------------------------------------------------------------- */
-        if ( GDALGetRasterCount(hSrcDS) == 0 )
-        {
-            fprintf(stderr, "Input file %s has no raster bands.\n", papszSrcFiles[iSrc] );
-            GDALExit( 1 );
-        }
-
-        if( eDT == GDT_Unknown )
-            eDT = GDALGetRasterDataType(GDALGetRasterBand(hSrcDS,1));
-
-/* -------------------------------------------------------------------- */
-/*      If we are processing the first file, and it has a color         */
-/*      table, then we will copy it to the destination file.            */
-/* -------------------------------------------------------------------- */
-        if( iSrc == 0 )
-        {
-            nDstBandCount = GDALGetRasterCount(hSrcDS);
-            hCT = GDALGetRasterColorTable( GDALGetRasterBand(hSrcDS,1) );
-            if( hCT != NULL )
-            {
-                hCT = GDALCloneColorTable( hCT );
-                if( !bQuiet )
-                    printf( "Copying color table from %s to new file.\n", 
-                            papszSrcFiles[iSrc] );
-            }
-
-            for(int iBand = 0; iBand < nDstBandCount; iBand++)
-            {
-                apeColorInterpretations.push_back(
-                    GDALGetRasterColorInterpretation(GDALGetRasterBand(hSrcDS,iBand+1)) );
-            }
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Get the sourcesrs from the dataset, if not set already.         */
-/* -------------------------------------------------------------------- */
-        if( pszThisSourceSRS == NULL )
-        {
-            const char *pszMethod = CSLFetchNameValue( papszTO, "METHOD" );
-
-            if( GDALGetProjectionRef( hSrcDS ) != NULL 
-                && strlen(GDALGetProjectionRef( hSrcDS )) > 0
-                && (pszMethod == NULL || EQUAL(pszMethod,"GEOTRANSFORM")) )
-                pszThisSourceSRS = GDALGetProjectionRef( hSrcDS );
-            
-            else if( GDALGetGCPProjection( hSrcDS ) != NULL
-                     && strlen(GDALGetGCPProjection(hSrcDS)) > 0 
-                     && GDALGetGCPCount( hSrcDS ) > 1 
-                     && (pszMethod == NULL || EQUALN(pszMethod,"GCP_",4)) )
-                pszThisSourceSRS = GDALGetGCPProjection( hSrcDS );
-            else if( pszMethod != NULL && EQUAL(pszMethod,"RPC") )
-                pszThisSourceSRS = SRS_WKT_WGS84;
-            else
-                pszThisSourceSRS = "";
-        }
-
-        if( pszThisTargetSRS == NULL )
-            pszThisTargetSRS = CPLStrdup( pszThisSourceSRS );
-        
-/* -------------------------------------------------------------------- */
-/*      Create a transformation object from the source to               */
-/*      destination coordinate system.                                  */
-/* -------------------------------------------------------------------- */
-        hTransformArg = 
-            GDALCreateGenImgProjTransformer2( hSrcDS, NULL, papszTO );
-        
-        if( hTransformArg == NULL )
-        {
-            CPLFree( pszThisTargetSRS );
-            GDALClose( hSrcDS );
-            return NULL;
-        }
-        
-        GDALTransformerInfo* psInfo = (GDALTransformerInfo*)hTransformArg;
-
-/* -------------------------------------------------------------------- */
-/*      Get approximate output definition.                              */
-/* -------------------------------------------------------------------- */
-        if( bNeedsSuggestedWarpOutput )
-        {
-            double adfThisGeoTransform[6];
-            double adfExtent[4];
-            int    nThisPixels, nThisLines;
-
-            if ( GDALSuggestedWarpOutput2( hSrcDS, 
-                                        psInfo->pfnTransform, hTransformArg, 
-                                        adfThisGeoTransform, 
-                                        &nThisPixels, &nThisLines, 
-                                        adfExtent, 0 ) != CE_None )
-            {
-                CPLFree( pszThisTargetSRS );
-                GDALClose( hSrcDS );
-                return NULL;
-            }
-            
-            if ( CPLGetConfigOption( "CHECK_WITH_INVERT_PROJ", NULL ) == NULL )
-            {
-                double MinX = adfExtent[0];
-                double MaxX = adfExtent[2];
-                double MaxY = adfExtent[3];
-                double MinY = adfExtent[1];
-                int bSuccess = TRUE;
-                
-                /* Check that the the edges of the target image are in the validity area */
-                /* of the target projection */
-    #define N_STEPS 20
-                int i,j;
-                for(i=0;i<=N_STEPS && bSuccess;i++)
-                {
-                    for(j=0;j<=N_STEPS && bSuccess;j++)
-                    {
-                        double dfRatioI = i * 1.0 / N_STEPS;
-                        double dfRatioJ = j * 1.0 / N_STEPS;
-                        double expected_x = (1 - dfRatioI) * MinX + dfRatioI * MaxX;
-                        double expected_y = (1 - dfRatioJ) * MinY + dfRatioJ * MaxY;
-                        double x = expected_x;
-                        double y = expected_y;
-                        double z = 0;
-                        /* Target SRS coordinates to source image pixel coordinates */
-                        if (!psInfo->pfnTransform(hTransformArg, TRUE, 1, &x, &y, &z, &bSuccess) || !bSuccess)
-                            bSuccess = FALSE;
-                        /* Source image pixel coordinates to target SRS coordinates */
-                        if (!psInfo->pfnTransform(hTransformArg, FALSE, 1, &x, &y, &z, &bSuccess) || !bSuccess)
-                            bSuccess = FALSE;
-                        if (fabs(x - expected_x) > (MaxX - MinX) / nThisPixels ||
-                            fabs(y - expected_y) > (MaxY - MinY) / nThisLines)
-                            bSuccess = FALSE;
-                    }
-                }
-                
-                /* If not, retry with CHECK_WITH_INVERT_PROJ=TRUE that forces ogrct.cpp */
-                /* to check the consistency of each requested projection result with the */
-                /* invert projection */
-                if (!bSuccess)
-                {
-                    CPLSetConfigOption( "CHECK_WITH_INVERT_PROJ", "TRUE" );
-                    CPLDebug("WARP", "Recompute out extent with CHECK_WITH_INVERT_PROJ=TRUE");
-
-                    if( GDALSuggestedWarpOutput2( hSrcDS, 
-                                        psInfo->pfnTransform, hTransformArg, 
-                                        adfThisGeoTransform, 
-                                        &nThisPixels, &nThisLines, 
-                                        adfExtent, 0 ) != CE_None )
-                    {
-                        CPLFree( pszThisTargetSRS );
-                        GDALClose( hSrcDS );
-                        return NULL;
-                    }
-                }
-            }
-
-    /* -------------------------------------------------------------------- */
-    /*      Expand the working bounds to include this region, ensure the    */
-    /*      working resolution is no more than this resolution.             */
-    /* -------------------------------------------------------------------- */
-            if( dfWrkMaxX == 0.0 && dfWrkMinX == 0.0 )
-            {
-                dfWrkMinX = adfExtent[0];
-                dfWrkMaxX = adfExtent[2];
-                dfWrkMaxY = adfExtent[3];
-                dfWrkMinY = adfExtent[1];
-                dfWrkResX = adfThisGeoTransform[1];
-                dfWrkResY = ABS(adfThisGeoTransform[5]);
-            }
-            else
-            {
-                dfWrkMinX = MIN(dfWrkMinX,adfExtent[0]);
-                dfWrkMaxX = MAX(dfWrkMaxX,adfExtent[2]);
-                dfWrkMaxY = MAX(dfWrkMaxY,adfExtent[3]);
-                dfWrkMinY = MIN(dfWrkMinY,adfExtent[1]);
-                dfWrkResX = MIN(dfWrkResX,adfThisGeoTransform[1]);
-                dfWrkResY = MIN(dfWrkResY,ABS(adfThisGeoTransform[5]));
-            }
-        }
-
-        if (iSrc == 0 && papszSrcFiles[1] == NULL)
-        {
-            *phTransformArg = hTransformArg;
-            *phSrcDS = hSrcDS;
-        }
-        else
-        {
-            GDALDestroyGenImgProjTransformer( hTransformArg );
-            GDALClose( hSrcDS );
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Did we have any usable sources?                                 */
-/* -------------------------------------------------------------------- */
-    if( nDstBandCount == 0 )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "No usable source images." );
-        CPLFree( pszThisTargetSRS );
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Turn the suggested region into a geotransform and suggested     */
-/*      number of pixels and lines.                                     */
-/* -------------------------------------------------------------------- */
-    double adfDstGeoTransform[6] = { 0, 0, 0, 0, 0, 0 };
-    int nPixels = 0, nLines = 0;
-    
-    if( bNeedsSuggestedWarpOutput )
-    {
-        adfDstGeoTransform[0] = dfWrkMinX;
-        adfDstGeoTransform[1] = dfWrkResX;
-        adfDstGeoTransform[2] = 0.0;
-        adfDstGeoTransform[3] = dfWrkMaxY;
-        adfDstGeoTransform[4] = 0.0;
-        adfDstGeoTransform[5] = -1 * dfWrkResY;
-
-        nPixels = (int) ((dfWrkMaxX - dfWrkMinX) / dfWrkResX + 0.5);
-        nLines = (int) ((dfWrkMaxY - dfWrkMinY) / dfWrkResY + 0.5);
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Did the user override some parameters?                          */
-/* -------------------------------------------------------------------- */
-    if( dfXRes != 0.0 && dfYRes != 0.0 )
-    {
-        if( dfMinX == 0.0 && dfMinY == 0.0 && dfMaxX == 0.0 && dfMaxY == 0.0 )
-        {
-            dfMinX = adfDstGeoTransform[0];
-            dfMaxX = adfDstGeoTransform[0] + adfDstGeoTransform[1] * nPixels;
-            dfMaxY = adfDstGeoTransform[3];
-            dfMinY = adfDstGeoTransform[3] + adfDstGeoTransform[5] * nLines;
-        }
-        
-        if ( bTargetAlignedPixels )
-        {
-            dfMinX = floor(dfMinX / dfXRes) * dfXRes;
-            dfMaxX = ceil(dfMaxX / dfXRes) * dfXRes;
-            dfMinY = floor(dfMinY / dfYRes) * dfYRes;
-            dfMaxY = ceil(dfMaxY / dfYRes) * dfYRes;
-        }
-
-        nPixels = (int) ((dfMaxX - dfMinX + (dfXRes/2.0)) / dfXRes);
-        nLines = (int) ((dfMaxY - dfMinY + (dfYRes/2.0)) / dfYRes);
-        adfDstGeoTransform[0] = dfMinX;
-        adfDstGeoTransform[3] = dfMaxY;
-        adfDstGeoTransform[1] = dfXRes;
-        adfDstGeoTransform[5] = -dfYRes;
-    }
-
-    else if( nForcePixels != 0 && nForceLines != 0 )
-    {
-        if( dfMinX == 0.0 && dfMinY == 0.0 && dfMaxX == 0.0 && dfMaxY == 0.0 )
-        {
-            dfMinX = dfWrkMinX;
-            dfMaxX = dfWrkMaxX;
-            dfMaxY = dfWrkMaxY;
-            dfMinY = dfWrkMinY;
-        }
-
-        dfXRes = (dfMaxX - dfMinX) / nForcePixels;
-        dfYRes = (dfMaxY - dfMinY) / nForceLines;
-
-        adfDstGeoTransform[0] = dfMinX;
-        adfDstGeoTransform[3] = dfMaxY;
-        adfDstGeoTransform[1] = dfXRes;
-        adfDstGeoTransform[5] = -dfYRes;
-
-        nPixels = nForcePixels;
-        nLines = nForceLines;
-    }
-
-    else if( nForcePixels != 0 )
-    {
-        if( dfMinX == 0.0 && dfMinY == 0.0 && dfMaxX == 0.0 && dfMaxY == 0.0 )
-        {
-            dfMinX = dfWrkMinX;
-            dfMaxX = dfWrkMaxX;
-            dfMaxY = dfWrkMaxY;
-            dfMinY = dfWrkMinY;
-        }
-
-        dfXRes = (dfMaxX - dfMinX) / nForcePixels;
-        dfYRes = dfXRes;
-
-        adfDstGeoTransform[0] = dfMinX;
-        adfDstGeoTransform[3] = dfMaxY;
-        adfDstGeoTransform[1] = dfXRes;
-        adfDstGeoTransform[5] = -dfYRes;
-
-        nPixels = nForcePixels;
-        nLines = (int) ((dfMaxY - dfMinY + (dfYRes/2.0)) / dfYRes);
-    }
-
-    else if( nForceLines != 0 )
-    {
-        if( dfMinX == 0.0 && dfMinY == 0.0 && dfMaxX == 0.0 && dfMaxY == 0.0 )
-        {
-            dfMinX = dfWrkMinX;
-            dfMaxX = dfWrkMaxX;
-            dfMaxY = dfWrkMaxY;
-            dfMinY = dfWrkMinY;
-        }
-
-        dfYRes = (dfMaxY - dfMinY) / nForceLines;
-        dfXRes = dfYRes;
-
-        adfDstGeoTransform[0] = dfMinX;
-        adfDstGeoTransform[3] = dfMaxY;
-        adfDstGeoTransform[1] = dfXRes;
-        adfDstGeoTransform[5] = -dfYRes;
-
-        nPixels = (int) ((dfMaxX - dfMinX + (dfXRes/2.0)) / dfXRes);
-        nLines = nForceLines;
-    }
-
-    else if( dfMinX != 0.0 || dfMinY != 0.0 || dfMaxX != 0.0 || dfMaxY != 0.0 )
-    {
-        dfXRes = adfDstGeoTransform[1];
-        dfYRes = fabs(adfDstGeoTransform[5]);
-
-        nPixels = (int) ((dfMaxX - dfMinX + (dfXRes/2.0)) / dfXRes);
-        nLines = (int) ((dfMaxY - dfMinY + (dfYRes/2.0)) / dfYRes);
-
-        dfXRes = (dfMaxX - dfMinX) / nPixels;
-        dfYRes = (dfMaxY - dfMinY) / nLines;
-
-        adfDstGeoTransform[0] = dfMinX;
-        adfDstGeoTransform[3] = dfMaxY;
-        adfDstGeoTransform[1] = dfXRes;
-        adfDstGeoTransform[5] = -dfYRes;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Do we want to generate an alpha band in the output file?        */
-/* -------------------------------------------------------------------- */
-    if( bEnableSrcAlpha )
-        nDstBandCount--;
-
-    if( bEnableDstAlpha )
-        nDstBandCount++;
-
-/* -------------------------------------------------------------------- */
-/*      Create the output file.                                         */
-/* -------------------------------------------------------------------- */
-    if( !bQuiet )
-        printf( "Creating output file that is %dP x %dL.\n", nPixels, nLines );
-
-    hDstDS = GDALCreate( hDriver, pszFilename, nPixels, nLines, 
-                         nDstBandCount, eDT, *ppapszCreateOptions );
-    
-    if( hDstDS == NULL )
-    {
-        CPLFree( pszThisTargetSRS );
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Write out the projection definition.                            */
-/* -------------------------------------------------------------------- */
-    const char *pszDstMethod = CSLFetchNameValue(papszTO,"DST_METHOD");
-    if( pszDstMethod == NULL || !EQUAL(pszDstMethod, "NO_GEOTRANSFORM") )
-    {
-        if( GDALSetProjection( hDstDS, pszThisTargetSRS ) == CE_Failure ||
-            GDALSetGeoTransform( hDstDS, adfDstGeoTransform ) == CE_Failure )
-        {
-            CPLFree( pszThisTargetSRS );
-            return NULL;
-        }
-    }
-    else
-    {
-        adfDstGeoTransform[0] = 0.0;
-        adfDstGeoTransform[3] = 0.0;
-        adfDstGeoTransform[5] = fabs(adfDstGeoTransform[5]);
-    }
-
-    if (*phTransformArg != NULL)
-        GDALSetGenImgProjTransformerDstGeoTransform( *phTransformArg, adfDstGeoTransform);
-
-/* -------------------------------------------------------------------- */
-/*      Try to set color interpretation of source bands to target       */
-/*      dataset.                                                        */
-/*      FIXME? We should likely do that for other drivers than VRT      */
-/*      but it might create spurious .aux.xml files (at least with HFA, */
-/*      and netCDF)                                                     */
-/* -------------------------------------------------------------------- */
-    if( bVRT || bSetColorInterpretation )
-    {
-        int nBandsToCopy = (int)apeColorInterpretations.size();
-        if ( bEnableSrcAlpha )
-            nBandsToCopy --;
-        for(int iBand = 0; iBand < nBandsToCopy; iBand++)
-        {
-            GDALSetRasterColorInterpretation(
-                GDALGetRasterBand( hDstDS, iBand + 1 ),
-                apeColorInterpretations[iBand] );
-        }
-    }
-    
-/* -------------------------------------------------------------------- */
-/*      Try to set color interpretation of output file alpha band.      */
-/* -------------------------------------------------------------------- */
-    if( bEnableDstAlpha )
-    {
-        GDALSetRasterColorInterpretation( 
-            GDALGetRasterBand( hDstDS, nDstBandCount ), 
-            GCI_AlphaBand );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Copy the color table, if required.                              */
-/* -------------------------------------------------------------------- */
-    if( hCT != NULL )
-    {
-        GDALSetRasterColorTable( GDALGetRasterBand(hDstDS,1), hCT );
-        GDALDestroyColorTable( hCT );
-    }
-
-    CPLFree( pszThisTargetSRS );
-    return hDstDS;
-}
-
-/************************************************************************/
-/*                      GeoTransform_Transformer()                      */
-/*                                                                      */
-/*      Convert points from georef coordinates to pixel/line based      */
-/*      on a geotransform.                                              */
-/************************************************************************/
-
-class CutlineTransformer : public OGRCoordinateTransformation
-{
-public:
-
-    void         *hSrcImageTransformer;
-
-    virtual OGRSpatialReference *GetSourceCS() { return NULL; }
-    virtual OGRSpatialReference *GetTargetCS() { return NULL; }
-
-    virtual int Transform( int nCount, 
-                           double *x, double *y, double *z = NULL ) {
-        int nResult;
-
-        int *pabSuccess = (int *) CPLCalloc(sizeof(int),nCount);
-        nResult = TransformEx( nCount, x, y, z, pabSuccess );
-        CPLFree( pabSuccess );
-
-        return nResult;
-    }
-
-    virtual int TransformEx( int nCount, 
-                             double *x, double *y, double *z = NULL,
-                             int *pabSuccess = NULL ) {
-        return GDALGenImgProjTransform( hSrcImageTransformer, TRUE, 
-                                        nCount, x, y, z, pabSuccess );
-    }
-};
-
-
-/************************************************************************/
-/*                            LoadCutline()                             */
-/*                                                                      */
-/*      Load blend cutline from OGR datasource.                         */
-/************************************************************************/
-
-static void
-LoadCutline( const char *pszCutlineDSName, const char *pszCLayer, 
-             const char *pszCWHERE, const char *pszCSQL, 
-             void **phCutlineRet )
-
-{
-#ifndef OGR_ENABLED
-    CPLError( CE_Failure, CPLE_AppDefined, 
-              "Request to load a cutline failed, this build does not support OGR features.\n" );
-    GDALExit( 1 );
-#else // def OGR_ENABLED
-    OGRRegisterAll();
-
-/* -------------------------------------------------------------------- */
-/*      Open source vector dataset.                                     */
-/* -------------------------------------------------------------------- */
-    OGRDataSourceH hSrcDS;
-
-    hSrcDS = OGROpen( pszCutlineDSName, FALSE, NULL );
-    if( hSrcDS == NULL )
-    {
-        fprintf( stderr, "Cannot open %s.\n", pszCutlineDSName);
-        GDALExit( 1 );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Get the source layer                                            */
-/* -------------------------------------------------------------------- */
-    OGRLayerH hLayer = NULL;
-
-    if( pszCSQL != NULL )
-        hLayer = OGR_DS_ExecuteSQL( hSrcDS, pszCSQL, NULL, NULL ); 
-    else if( pszCLayer != NULL )
-        hLayer = OGR_DS_GetLayerByName( hSrcDS, pszCLayer );
-    else
-        hLayer = OGR_DS_GetLayer( hSrcDS, 0 );
-
-    if( hLayer == NULL )
-    {
-        fprintf( stderr, "Failed to identify source layer from datasource.\n" );
-        GDALExit( 1 );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Apply WHERE clause if there is one.                             */
-/* -------------------------------------------------------------------- */
-    if( pszCWHERE != NULL )
-        OGR_L_SetAttributeFilter( hLayer, pszCWHERE );
-
-/* -------------------------------------------------------------------- */
-/*      Collect the geometries from this layer, and build list of       */
-/*      burn values.                                                    */
-/* -------------------------------------------------------------------- */
-    OGRFeatureH hFeat;
-    OGRGeometryH hMultiPolygon = OGR_G_CreateGeometry( wkbMultiPolygon );
-
-    OGR_L_ResetReading( hLayer );
-    
-    while( (hFeat = OGR_L_GetNextFeature( hLayer )) != NULL )
-    {
-        OGRGeometryH hGeom = OGR_F_GetGeometryRef(hFeat);
-
-        if( hGeom == NULL )
-        {
-            fprintf( stderr, "ERROR: Cutline feature without a geometry.\n" );
-            GDALExit( 1 );
-        }
-        
-        OGRwkbGeometryType eType = wkbFlatten(OGR_G_GetGeometryType( hGeom ));
-
-        if( eType == wkbPolygon )
-            OGR_G_AddGeometry( hMultiPolygon, hGeom );
-        else if( eType == wkbMultiPolygon )
-        {
-            int iGeom;
-
-            for( iGeom = 0; iGeom < OGR_G_GetGeometryCount( hGeom ); iGeom++ )
-            {
-                OGR_G_AddGeometry( hMultiPolygon, 
-                                   OGR_G_GetGeometryRef(hGeom,iGeom) );
-            }
-        }
-        else
-        {
-            fprintf( stderr, "ERROR: Cutline not of polygon type.\n" );
-            GDALExit( 1 );
-        }
-
-        OGR_F_Destroy( hFeat );
-    }
-
-    if( OGR_G_GetGeometryCount( hMultiPolygon ) == 0 )
-    {
-        fprintf( stderr, "ERROR: Did not get any cutline features.\n" );
-        GDALExit( 1 );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Ensure the coordinate system gets set on the geometry.          */
-/* -------------------------------------------------------------------- */
-    OGR_G_AssignSpatialReference(
-        hMultiPolygon, OGR_L_GetSpatialRef(hLayer) );
-
-    *phCutlineRet = (void *) hMultiPolygon;
-
-/* -------------------------------------------------------------------- */
-/*      Cleanup                                                         */
-/* -------------------------------------------------------------------- */
-    if( pszCSQL != NULL )
-        OGR_DS_ReleaseResultSet( hSrcDS, hLayer );
-
-    OGR_DS_Destroy( hSrcDS );
-#endif
-}
-
-/************************************************************************/
-/*                      TransformCutlineToSource()                      */
-/*                                                                      */
-/*      Transform cutline from its SRS to source pixel/line coordinates.*/
-/************************************************************************/
-static void
-TransformCutlineToSource( GDALDatasetH hSrcDS, void *hCutline,
-                          char ***ppapszWarpOptions, char **papszTO_In )
-
-{
-#ifdef OGR_ENABLED
-    OGRGeometryH hMultiPolygon = OGR_G_Clone( (OGRGeometryH) hCutline );
-    char **papszTO = CSLDuplicate( papszTO_In );
-
-/* -------------------------------------------------------------------- */
-/*      Checkout that SRS are the same.                                 */
-/* -------------------------------------------------------------------- */
-    OGRSpatialReferenceH  hRasterSRS = NULL;
-    const char *pszProjection = NULL;
-
-    if( GDALGetProjectionRef( hSrcDS ) != NULL 
-        && strlen(GDALGetProjectionRef( hSrcDS )) > 0 )
-        pszProjection = GDALGetProjectionRef( hSrcDS );
-    else if( GDALGetGCPProjection( hSrcDS ) != NULL )
-        pszProjection = GDALGetGCPProjection( hSrcDS );
-
-    if( pszProjection == NULL || EQUAL( pszProjection, "" ) )
-        pszProjection = CSLFetchNameValue( papszTO, "SRC_SRS" );
-
-    if( pszProjection != NULL )
-    {
-        hRasterSRS = OSRNewSpatialReference(NULL);
-        if( OSRImportFromWkt( hRasterSRS, (char **)&pszProjection ) != CE_None )
-        {
-            OSRDestroySpatialReference(hRasterSRS);
-            hRasterSRS = NULL;
-        }
-    }
-
-    OGRSpatialReferenceH hCutlineSRS = OGR_G_GetSpatialReference( hMultiPolygon );
-    if( hRasterSRS != NULL && hCutlineSRS != NULL )
-    {
-        /* ok, we will reproject */
-    }
-    else if( hRasterSRS != NULL && hCutlineSRS == NULL )
-    {
-        fprintf(stderr,
-                "Warning : the source raster dataset has a SRS, but the cutline features\n"
-                "not.  We assume that the cutline coordinates are expressed in the destination SRS.\n"
-                "If not, cutline results may be incorrect.\n");
-    }
-    else if( hRasterSRS == NULL && hCutlineSRS != NULL )
-    {
-        fprintf(stderr,
-                "Warning : the input vector layer has a SRS, but the source raster dataset does not.\n"
-                "Cutline results may be incorrect.\n");
-    }
-
-    if( hRasterSRS != NULL )
-        OSRDestroySpatialReference(hRasterSRS);
-
-/* -------------------------------------------------------------------- */
-/*      Extract the cutline SRS WKT.                                    */
-/* -------------------------------------------------------------------- */
-    if( hCutlineSRS != NULL )
-    {
-        char *pszCutlineSRS_WKT = NULL;
-
-        OSRExportToWkt( hCutlineSRS, &pszCutlineSRS_WKT );
-        papszTO = CSLSetNameValue( papszTO, "DST_SRS", pszCutlineSRS_WKT );
-        CPLFree( pszCutlineSRS_WKT );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      It may be unwise to let the mask geometry be re-wrapped by      */
-/*      the CENTER_LONG machinery as this can easily screw up world     */
-/*      spanning masks and invert the mask topology.                    */
-/* -------------------------------------------------------------------- */
-    papszTO = CSLSetNameValue( papszTO, "INSERT_CENTER_LONG", "FALSE" );
-
-/* -------------------------------------------------------------------- */
-/*      Transform the geometry to pixel/line coordinates.               */
-/* -------------------------------------------------------------------- */
-    CutlineTransformer oTransformer;
-
-    /* The cutline transformer will *invert* the hSrcImageTransformer */
-    /* so it will convert from the cutline SRS to the source pixel/line */
-    /* coordinates */
-    oTransformer.hSrcImageTransformer = 
-        GDALCreateGenImgProjTransformer2( hSrcDS, NULL, papszTO );
-
-    CSLDestroy( papszTO );
-
-    if( oTransformer.hSrcImageTransformer == NULL )
-        GDALExit( 1 );
-
-    OGR_G_Transform( hMultiPolygon, 
-                     (OGRCoordinateTransformationH) &oTransformer );
-
-    GDALDestroyGenImgProjTransformer( oTransformer.hSrcImageTransformer );
-
-/* -------------------------------------------------------------------- */
-/*      Convert aggregate geometry into WKT.                            */
-/* -------------------------------------------------------------------- */
-    char *pszWKT = NULL;
-
-    OGR_G_ExportToWkt( hMultiPolygon, &pszWKT );
-    OGR_G_DestroyGeometry( hMultiPolygon );
-
-    *ppapszWarpOptions = CSLSetNameValue( *ppapszWarpOptions, 
-                                          "CUTLINE", pszWKT );
-    CPLFree( pszWKT );
-#endif
-}
-
-static void 
-RemoveConflictingMetadata( GDALMajorObjectH hObj, char **papszMetadata, 
-                           const char *pszValueConflict )
-{
-    if ( hObj == NULL ) return;
-
-    char *pszKey = NULL; 
-    const char *pszValueRef; 
-    const char *pszValueComp; 
-    char ** papszMetadataRef = CSLDuplicate( papszMetadata );
-    int nCount = CSLCount( papszMetadataRef ); 
-
-    for( int i = 0; i < nCount; i++ ) 
-    {
-        pszKey = NULL;
-        pszValueRef = CPLParseNameValue( papszMetadataRef[i], &pszKey ); 
-        if( pszKey != NULL )
-        {
-            pszValueComp = GDALGetMetadataItem( hObj, pszKey, NULL );
-            if ( ( pszValueRef == NULL || pszValueComp == NULL ||
-                ! EQUAL( pszValueRef, pszValueComp ) ) &&
-                ( pszValueComp == NULL ||
-                ! EQUAL( pszValueComp, pszValueConflict ) ) ) {
-                GDALSetMetadataItem( hObj, pszKey, pszValueConflict, NULL ); 
-            }
-            CPLFree( pszKey );
-        }
-    } 
-
-    CSLDestroy( papszMetadataRef );
-}
-
diff --git a/apps/gdalwarp_bin.cpp b/apps/gdalwarp_bin.cpp
new file mode 100644
index 0000000..468d898
--- /dev/null
+++ b/apps/gdalwarp_bin.cpp
@@ -0,0 +1,529 @@
+/******************************************************************************
+ * $Id: gdalwarp_bin.cpp 33757 2016-03-20 20:22:33Z goatbar $
+ *
+ * Project:  High Performance Image Reprojector
+ * Purpose:  Test program for high performance warper API.
+ * Author:   Frank Warmerdam <warmerdam at pobox.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2002, i3 - information integration and imaging
+ *                          Fort Collin, CO
+ * Copyright (c) 2007-2015, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_string.h"
+#include "cpl_error.h"
+#include "commonutils.h"
+#include "gdal_utils_priv.h"
+
+CPL_CVSID("$Id: gdalwarp_bin.cpp 33757 2016-03-20 20:22:33Z goatbar $");
+
+/******************************************************************************/
+/*! \page gdalwarp gdalwarp
+
+image reprojection and warping utility
+
+\section gdalwarp_synopsis SYNOPSIS
+
+\htmlonly
+Usage:
+\endhtmlonly
+
+\verbatim
+gdalwarp [--help-general] [--formats]
+    [-s_srs srs_def] [-t_srs srs_def] [-to "NAME=VALUE"]
+    [-order n | -tps | -rpc | -geoloc] [-et err_threshold]
+    [-refine_gcps tolerance [minimum_gcps]]
+    [-te xmin ymin xmax ymax] [-te_srs srs_def]
+    [-tr xres yres] [-tap] [-ts width height]
+    [-ovr level|AUTO|AUTO-n|NONE] [-wo "NAME=VALUE"] [-ot Byte/Int16/...] [-wt Byte/Int16]
+    [-srcnodata "value [value...]"] [-dstnodata "value [value...]"] -dstalpha
+    [-r resampling_method] [-wm memory_in_mb] [-multi] [-q]
+    [-cutline datasource] [-cl layer] [-cwhere expression]
+    [-csql statement] [-cblend dist_in_pixels] [-crop_to_cutline]
+    [-of format] [-co "NAME=VALUE"]* [-overwrite]
+    [-nomd] [-cvmd meta_conflict_value] [-setci] [-oo NAME=VALUE]*
+    [-doo NAME=VALUE]*
+    srcfile* dstfile
+\endverbatim
+
+\section gdalwarp_description DESCRIPTION
+
+<p>
+The gdalwarp utility is an image mosaicing, reprojection and warping
+utility. The program can reproject to any supported projection,
+and can also apply GCPs stored with the image if the image is "raw"
+with control information.
+
+<p>
+<dl>
+<dt> <b>-s_srs</b> <em>srs def</em>:</dt><dd> source spatial reference set.
+The coordinate systems that can be passed are anything supported by the
+OGRSpatialReference.SetFromUserInput() call, which includes EPSG PCS and GCSes
+(i.e. EPSG:4296), PROJ.4 declarations (as above), or the name of a .prj file
+containing well known text.</dd>
+<dt> <b>-t_srs</b> <em>srs_def</em>:</dt><dd> target spatial reference set.
+The coordinate systems that can be passed are anything supported by the
+OGRSpatialReference.SetFromUserInput() call, which includes EPSG PCS and GCSes
+(i.e. EPSG:4296), PROJ.4 declarations (as above), or the name of a .prj file
+containing well known text.</dd>
+<dt> <b>-to</b> <em>NAME=VALUE</em>:</dt><dd> set a transformer option suitable
+to pass to GDALCreateGenImgProjTransformer2(). </dd>
+<dt> <b>-order</b> <em>n</em>:</dt><dd> order of polynomial used for warping
+(1 to 3). The default is to select a polynomial order based on the number of
+GCPs.</dd>
+<dt> <b>-tps</b>:</dt><dd>Force use of thin plate spline transformer based on
+available GCPs.</dd>
+<dt> <b>-rpc</b>:</dt> <dd>Force use of RPCs.</dd>
+<dt> <b>-geoloc</b>:</dt><dd>Force use of Geolocation Arrays.</dd>
+<dt> <b>-et</b> <em>err_threshold</em>:</dt><dd> error threshold for
+transformation approximation (in pixel units - defaults to 0.125, unless, starting
+with GDAL 2.1, the RPC_DEM warping option is specified, in which case, an exact
+transformer, i.e. err_threshold=0, will be used).</dd>
+<dt> <b>-refine_gcps</b> <em>tolerance minimum_gcps</em>:</dt><dd>  (GDAL >= 1.9.0) refines the GCPs by automatically eliminating outliers.
+Outliers will be eliminated until minimum_gcps are left or when no outliers can be detected.
+The tolerance is passed to adjust when a GCP will be eliminated.
+Not that GCP refinement only works with polynomial interpolation.
+The tolerance is in pixel units if no projection is available, otherwise it is in SRS units.
+If minimum_gcps is not provided, the minimum GCPs according to the polynomial model is used.</dd>
+<dt> <b>-te</b> <em>xmin ymin xmax ymax</em>:</dt><dd> set georeferenced
+extents of output file to be created (in target SRS by default, or in the SRS
+specified with -te_srs)
+</dd>
+<dt> <b>-te_srs</b> <i>srs_def</i>:</dt><dd> (GDAL >= 2.0) Specifies the SRS in
+which to interpret the coordinates given with -te. The <i>srs_def</i> may
+be any of the usual GDAL/OGR forms, complete WKT, PROJ.4, EPSG:n or a file
+containing the WKT.
+This must not be confused with -t_srs which is the target SRS of the output
+dataset. -te_srs is a convenience e.g. when knowing the output coordinates in a
+geodetic long/lat SRS, but still wanting a result in a projected coordinate system.
+</dd>
+<dt> <b>-tr</b> <em>xres yres</em>:</dt><dd> set output file resolution (in
+target georeferenced units)</dd>
+<dt> <b>-tap</b>:</dt><dd> (GDAL >= 1.8.0) (target aligned pixels) align
+the coordinates of the extent of the output file to the values of the -tr,
+such that the aligned extent includes the minimum extent.</dd>
+<dt> <b>-ts</b> <em>width height</em>:</dt><dd> set output file size in
+pixels and lines. If width or height is set to 0, the other dimension will be
+guessed from the computed resolution. Note that -ts cannot be used with -tr</dd>
+<dt> <b>-ovr</b> <em>level|AUTO|AUTO-n|NONE></em>:</dt><dd>(GDAL >= 2.0) To
+specify which overview level of source files must be used. The default choice,
+AUTO, will select the overview level whose resolution is the closest to the
+target resolution. Specify an integer value (0-based, i.e. 0=1st overview level)
+to select a particular level. Specify AUTO-n where n is an integer greater or
+equal to 1, to select an overview level below the AUTO one. Or specify NONE to
+force the base resolution to be used (can be useful if overviews have been
+generated with a low quality resampling method, and the warping is done using a
+higher quality resampling method).</dd>
+<dt> <b>-wo</b> <em>"NAME=VALUE"</em>:</dt><dd> Set a warp option.  The
+GDALWarpOptions::papszWarpOptions docs show all options.  Multiple
+ <b>-wo</b> options may be listed.</dd>
+<dt> <b>-ot</b> <em>type</em>:</dt><dd> For the output bands to be of the
+indicated data type.</dd>
+<dt> <b>-wt</b> <em>type</em>:</dt><dd> Working pixel data type. The data type
+of pixels in the source image and destination image buffers.</dd>
+<dt> <b>-r</b> <em>resampling_method</em>:</dt><dd> Resampling method to use. Available methods are:
+<dl>
+<dt><b>near</b></dt>: <dd>nearest neighbour resampling (default, fastest
+algorithm, worst interpolation quality).</dd>
+<dt><b>bilinear</b></dt>: <dd>bilinear resampling.</dd>
+<dt><b>cubic</b></dt>: <dd>cubic resampling.</dd>
+<dt><b>cubicspline</b></dt>: <dd>cubic spline resampling.</dd>
+<dt><b>lanczos</b></dt>: <dd>Lanczos windowed sinc resampling.</dd>
+<dt><b>average</b></dt>: <dd>average resampling, computes the average of all non-NODATA contributing pixels. (GDAL >= 1.10.0)</dd>
+<dt><b>mode</b></dt>: <dd>mode resampling, selects the value which appears most often of all the sampled points. (GDAL >= 1.10.0)</dd>
+<dt><b>max</b></dt>: <dd>maximum resampling, selects the maximum value from all non-NODATA contributing pixels. (GDAL >= 2.0.0)</dd>
+<dt><b>min</b></dt>: <dd>minimum resampling, selects the minimum value from all non-NODATA contributing pixels. (GDAL >= 2.0.0)</dd>
+<dt><b>med</b></dt>: <dd>median resampling, selects the median value of all non-NODATA contributing pixels. (GDAL >= 2.0.0)</dd>
+<dt><b>q1</b></dt>: <dd>first quartile resampling, selects the first quartile value of all non-NODATA contributing pixels. (GDAL >= 2.0.0)</dd>
+<dt><b>q3</b></dt>: <dd>third quartile resampling, selects the third quartile value of all non-NODATA contributing pixels. (GDAL >= 2.0.0)</dd>
+</dl>
+<dt> <b>-srcnodata</b> <em>value [value...]</em>:</dt><dd> Set nodata masking
+values for input bands (different values can be supplied for each band).  If
+more than one value is supplied all values should be quoted to keep them
+together as a single operating system argument.  Masked values will not be
+used in interpolation.  Use a value of <tt>None</tt> to ignore intrinsic nodata settings on the source dataset.</dd>
+<dt> <b>-dstnodata</b> <em>value [value...]</em>:</dt><dd> Set nodata values
+for output bands (different values can be supplied for each band).  If more
+than one value is supplied all values should be quoted to keep them together
+as a single operating system argument.  New files will be initialized to this
+value and if possible the nodata value will be recorded in the output
+file. Use a value of <tt>None</tt> to ensure that nodata is not defined (GDAL>=1.11).
+If this argument is not used then nodata values will be copied from the source dataset (GDAL>=1.11).</dd>
+<dt> <b>-dstalpha</b>:</dt><dd> Create an output alpha band to identify
+nodata (unset/transparent) pixels. </dd>
+<dt> <b>-wm</b> <em>memory_in_mb</em>:</dt><dd> Set the amount of memory (in
+megabytes) that the warp API is allowed to use for caching.</dd>
+<dt> <b>-multi</b>:</dt><dd> Use multithreaded warping implementation.
+Multiple threads will be used to process chunks of image and perform
+input/output operation simultaneously.</dd>
+<dt> <b>-q</b>:</dt><dd> Be quiet.</dd>
+<dt> <b>-of</b> <em>format</em>:</dt><dd> Select the output format. The default is GeoTIFF (GTiff). Use the short format name. </dd>
+<dt> <b>-co</b> <em>"NAME=VALUE"</em>:</dt><dd> passes a creation option to
+the output format driver. Multiple <b>-co</b> options may be listed. See
+format specific documentation for legal creation options for each format.
+</dd>
+
+<dt> <b>-cutline</b> <em>datasource</em>:</dt><dd>Enable use of a blend cutline from the name OGR support datasource.</dd>
+<dt> <b>-cl</b> <em>layername</em>:</dt><dd>Select the named layer from the
+cutline datasource.</dd>
+<dt> <b>-cwhere</b> <em>expression</em>:</dt><dd>Restrict desired cutline features based on attribute query.</dd>
+<dt> <b>-csql</b> <em>query</em>:</dt><dd>Select cutline features using an SQL query instead of from a layer with -cl.</dd>
+<dt> <b>-cblend</b> <em>distance</em>:</dt><dd>Set a blend distance to use to blend over cutlines (in pixels).</dd>
+<dt> <b>-crop_to_cutline</b>:</dt><dd>(GDAL >= 1.8.0) Crop the extent of the target dataset to the extent of the cutline.</dd>
+<dt> <b>-overwrite</b>:</dt><dd>(GDAL >= 1.8.0) Overwrite the target dataset if it already exists.</dd>
+<dt> <b>-nomd</b>:</dt><dd>(GDAL >= 1.10.0) Do not copy metadata. Without this option, dataset and band metadata
+(as well as some band information) will be copied from the first source dataset.
+Items that differ between source datasets will be set to * (see -cvmd option).</dd>
+<dt> <b>-cvmd</b> <em>meta_conflict_value</em>:</dt><dd>(GDAL >= 1.10.0)
+Value to set metadata items that conflict between source datasets (default is "*"). Use "" to remove conflicting items. </dd>
+<dt> <b>-setci</b>:</dt><dd>(GDAL >= 1.10.0)
+Set the color interpretation of the bands of the target dataset from the source dataset.</dd>
+<dt> <b>-oo</b> <em>NAME=VALUE</em>:</dt><dd>(starting with GDAL 2.0) Dataset open option (format specific)</dd>
+<dt> <b>-doo</b> <em>NAME=VALUE</em>:</dt><dd>(starting with GDAL 2.1) Output dataset open option (format specific)</dd>
+
+<dt> <em>srcfile</em>:</dt><dd> The source file name(s). </dd>
+<dt> <em>dstfile</em>:</dt><dd> The destination file name. </dd>
+</dl>
+
+Mosaicing into an existing output file is supported if the output file
+already exists. The spatial extent of the existing file will not
+be modified to accommodate new data, so you may have to remove it in that case, or
+use the -overwrite option.
+
+Polygon cutlines may be used as a mask to restrict the area of the
+destination file that may be updated, including blending.  If the OGR
+layer containing the cutline features has no explicit SRS, the cutline
+features must be in the SRS of the destination file. When writing to a
+not yet existing target dataset, its extent will be the one of the
+original raster unless -te or -crop_to_cutline are specified.
+
+<p>
+\section gdalwarp_example EXAMPLE
+
+For instance, an eight bit spot scene stored in GeoTIFF with
+control points mapping the corners to lat/long could be warped to a UTM
+projection with a command like this:<p>
+
+\verbatim
+gdalwarp -t_srs '+proj=utm +zone=11 +datum=WGS84' raw_spot.tif utm11.tif
+\endverbatim
+
+For instance, the second channel of an ASTER image stored in HDF with
+control points mapping the corners to lat/long could be warped to a UTM
+projection with a command like this:<p>
+
+\verbatim
+gdalwarp HDF4_SDS:ASTER_L1B:"pg-PR1B0000-2002031402_100_001":2 pg-PR1B0000-2002031402_100_001_2.tif
+\endverbatim
+
+<p>
+\section gdalwarp_seealso SEE ALSO
+
+\if man
+http://trac.osgeo.org/gdal/wiki/UserDocs/GdalWarp :
+\else
+<a href="http://trac.osgeo.org/gdal/wiki/UserDocs/GdalWarp">
+\endif
+Wiki page discussing options and behaviours of gdalwarp
+\if man
+\else
+</a>
+\endif
+
+\if man
+\section gdalwarp_author AUTHORS
+Frank Warmerdam <warmerdam at pobox.com>, Silke Reimer <silke at intevation.de>
+\endif
+*/
+
+/************************************************************************/
+/*                               GDALExit()                             */
+/*  This function exits and cleans up GDAL and OGR resources            */
+/*  Perhaps it should be added to C api and used in all apps?           */
+/************************************************************************/
+
+static int GDALExit( int nCode )
+{
+  const char  *pszDebug = CPLGetConfigOption("CPL_DEBUG",NULL);
+  if( pszDebug && (EQUAL(pszDebug,"ON") || EQUAL(pszDebug,"") ) )
+  {
+    GDALDumpOpenDatasets( stderr );
+    CPLDumpSharedList( NULL );
+  }
+
+  GDALDestroyDriverManager();
+
+  OGRCleanupAll();
+
+  exit( nCode );
+}
+
+/************************************************************************/
+/*                               Usage()                                */
+/************************************************************************/
+
+static void Usage(const char* pszErrorMsg = NULL)
+
+{
+    printf(
+        "Usage: gdalwarp [--help-general] [--formats]\n"
+        "    [-s_srs srs_def] [-t_srs srs_def] [-to \"NAME=VALUE\"]\n"
+        "    [-order n | -tps | -rpc | -geoloc] [-et err_threshold]\n"
+        "    [-refine_gcps tolerance [minimum_gcps]]\n"
+        "    [-te xmin ymin xmax ymax] [-tr xres yres] [-tap] [-ts width height]\n"
+        "    [-ovr level|AUTO|AUTO-n|NONE] [-wo \"NAME=VALUE\"] [-ot Byte/Int16/...] [-wt Byte/Int16]\n"
+        "    [-srcnodata \"value [value...]\"] [-dstnodata \"value [value...]\"] -dstalpha\n"
+        "    [-r resampling_method] [-wm memory_in_mb] [-multi] [-q]\n"
+        "    [-cutline datasource] [-cl layer] [-cwhere expression]\n"
+        "    [-csql statement] [-cblend dist_in_pixels] [-crop_to_cutline]\n"
+        "    [-of format] [-co \"NAME=VALUE\"]* [-overwrite]\n"
+        "    [-nomd] [-cvmd meta_conflict_value] [-setci] [-oo NAME=VALUE]*\n"
+        "    [-doo NAME=VALUE]*\n"
+        "    srcfile* dstfile\n"
+        "\n"
+        "Available resampling methods:\n"
+        "    near (default), bilinear, cubic, cubicspline, lanczos, average, mode,  max, min, med, Q1, Q3.\n" );
+
+    if( pszErrorMsg != NULL )
+        fprintf(stderr, "\nFAILURE: %s\n", pszErrorMsg);
+
+    GDALExit( 1 );
+}
+
+/************************************************************************/
+/*                       GDALWarpAppOptionsForBinaryNew()             */
+/************************************************************************/
+
+static GDALWarpAppOptionsForBinary *GDALWarpAppOptionsForBinaryNew(void)
+{
+    return (GDALWarpAppOptionsForBinary*) CPLCalloc(  1, sizeof(GDALWarpAppOptionsForBinary) );
+}
+
+/************************************************************************/
+/*                       GDALWarpAppOptionsForBinaryFree()            */
+/************************************************************************/
+
+static void GDALWarpAppOptionsForBinaryFree( GDALWarpAppOptionsForBinary* psOptionsForBinary )
+{
+    if( psOptionsForBinary )
+    {
+        CSLDestroy(psOptionsForBinary->papszSrcFiles);
+        CPLFree(psOptionsForBinary->pszDstFilename);
+        CSLDestroy(psOptionsForBinary->papszOpenOptions);
+        CSLDestroy(psOptionsForBinary->papszDestOpenOptions);
+        CPLFree(psOptionsForBinary->pszFormat);
+        CPLFree(psOptionsForBinary);
+    }
+}
+
+/************************************************************************/
+/*                                main()                                */
+/************************************************************************/
+
+int main( int argc, char ** argv )
+
+{
+    GDALDatasetH *pahSrcDS = NULL;
+    int nSrcCount = 0;
+
+    EarlySetConfigOptions(argc, argv);
+
+/* -------------------------------------------------------------------- */
+/*      Register standard GDAL drivers, and process generic GDAL        */
+/*      command options.                                                */
+/* -------------------------------------------------------------------- */
+    GDALAllRegister();
+    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
+    if( argc < 1 )
+        GDALExit( -argc );
+
+    for( int i = 0; argv != NULL && argv[i] != NULL; i++ )
+    {
+        if( EQUAL(argv[i], "--utility_version") )
+        {
+            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
+                   argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
+            CSLDestroy( argv );
+            return 0;
+        }
+        else if( EQUAL(argv[i],"--help") )
+        {
+            Usage(NULL);
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Set optimal setting for best performance with huge input VRT.   */
+/*      The rationale for 450 is that typical Linux process allow       */
+/*      only 1024 file descriptors per process and we need to keep some */
+/*      spare for shared libraries, etc. so let's go down to 900.       */
+/*      And some datasets may need 2 file descriptors, so divide by 2   */
+/*      for security.                                                   */
+/* -------------------------------------------------------------------- */
+    if( CPLGetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", NULL) == NULL )
+    {
+        CPLSetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", "450");
+    }
+
+    GDALWarpAppOptionsForBinary* psOptionsForBinary = GDALWarpAppOptionsForBinaryNew();
+    /* coverity[tainted_data] */
+    GDALWarpAppOptions *psOptions = GDALWarpAppOptionsNew(argv + 1, psOptionsForBinary);
+    CSLDestroy( argv );
+
+    if( psOptions == NULL )
+    {
+        Usage(NULL);
+    }
+
+    if( psOptionsForBinary->pszDstFilename == NULL )
+    {
+        Usage("No target filename specified.");
+    }
+
+    if ( CSLCount(psOptionsForBinary->papszSrcFiles) == 1 &&
+         strcmp(psOptionsForBinary->papszSrcFiles[0], psOptionsForBinary->pszDstFilename) == 0 &&
+         psOptionsForBinary->bOverwrite)
+    {
+        CPLError(CE_Failure, CPLE_IllegalArg, "Source and destination datasets must be different.\n");
+        GDALExit(1);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Open Source files.                                              */
+/* -------------------------------------------------------------------- */
+    for(int i = 0; psOptionsForBinary->papszSrcFiles[i] != NULL; i++)
+    {
+        nSrcCount++;
+        pahSrcDS = (GDALDatasetH *) CPLRealloc(pahSrcDS, sizeof(GDALDatasetH) * nSrcCount);
+        pahSrcDS[nSrcCount-1] = GDALOpenEx( psOptionsForBinary->papszSrcFiles[i], GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR, NULL,
+                                            (const char* const* )psOptionsForBinary->papszOpenOptions, NULL );
+
+        if( pahSrcDS[nSrcCount-1] == NULL )
+            GDALExit(2);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Does the output dataset already exist?                          */
+/* -------------------------------------------------------------------- */
+
+    /* FIXME ? source filename=target filename and -overwrite is definitely */
+    /* an error. But I can't imagine of a valid case (without -overwrite), */
+    /* where it would make sense. In doubt, let's keep that dubious possibility... */
+
+    int bOutStreaming = FALSE;
+    if( strcmp(psOptionsForBinary->pszDstFilename, "/vsistdout/") == 0 )
+    {
+        psOptionsForBinary->bQuiet = TRUE;
+        bOutStreaming = TRUE;
+    }
+#ifdef S_ISFIFO
+    else
+    {
+        VSIStatBufL sStat;
+        if( VSIStatExL(psOptionsForBinary->pszDstFilename, &sStat, VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG) == 0 &&
+            S_ISFIFO(sStat.st_mode) )
+        {
+            bOutStreaming = TRUE;
+        }
+    }
+#endif
+
+    GDALDatasetH hDstDS = NULL;
+    if( bOutStreaming )
+    {
+        GDALWarpAppOptionsSetWarpOption(psOptions, "STREAMABLE_OUTPUT", "YES");
+    }
+    else
+    {
+        CPLPushErrorHandler( CPLQuietErrorHandler );
+        hDstDS = GDALOpenEx( psOptionsForBinary->pszDstFilename, GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR | GDAL_OF_UPDATE,
+                             NULL, psOptionsForBinary->papszDestOpenOptions, NULL );
+        CPLPopErrorHandler();
+    }
+
+    if( hDstDS != NULL && psOptionsForBinary->bOverwrite )
+    {
+        GDALClose(hDstDS);
+        hDstDS = NULL;
+    }
+
+    if( hDstDS != NULL && psOptionsForBinary->bCreateOutput )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                 "Output dataset %s exists,\n"
+                 "but some command line options were provided indicating a new dataset\n"
+                 "should be created.  Please delete existing dataset and run again.\n",
+                 psOptionsForBinary->pszDstFilename );
+        GDALExit(1);
+    }
+
+    /* Avoid overwriting an existing destination file that cannot be opened in */
+    /* update mode with a new GTiff file */
+    if ( !bOutStreaming && hDstDS == NULL && !psOptionsForBinary->bOverwrite )
+    {
+        CPLPushErrorHandler( CPLQuietErrorHandler );
+        hDstDS = GDALOpen( psOptionsForBinary->pszDstFilename, GA_ReadOnly );
+        CPLPopErrorHandler();
+
+        if (hDstDS)
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                     "Output dataset %s exists, but cannot be opened in update mode\n",
+                     psOptionsForBinary->pszDstFilename );
+            GDALClose(hDstDS);
+            GDALExit(1);
+        }
+    }
+
+    if( !(psOptionsForBinary->bQuiet) )
+    {
+        GDALWarpAppOptionsSetProgress(psOptions, GDALTermProgress, NULL);
+    }
+
+    if (hDstDS == NULL && !psOptionsForBinary->bQuiet && !psOptionsForBinary->bFormatExplicitlySet)
+        CheckExtensionConsistency(psOptionsForBinary->pszDstFilename, psOptionsForBinary->pszFormat);
+
+    int bUsageError = FALSE;
+    GDALDatasetH hOutDS = GDALWarp(psOptionsForBinary->pszDstFilename, hDstDS,
+                      nSrcCount, pahSrcDS, psOptions, &bUsageError);
+    if( bUsageError )
+        Usage();
+    int nRetCode = (hOutDS) ? 0 : 1;
+
+    GDALWarpAppOptionsFree(psOptions);
+    GDALWarpAppOptionsForBinaryFree(psOptionsForBinary);
+
+    for(int i = 0; i < nSrcCount; i++)
+    {
+        GDALClose(pahSrcDS[i]);
+    }
+    CPLFree(pahSrcDS);
+    GDALClose( hOutDS ? hOutDS : hDstDS );
+
+    GDALDumpOpenDatasets( stderr );
+
+    GDALDestroyDriverManager();
+
+    OGRCleanupAll();
+
+    return nRetCode;
+}
diff --git a/apps/gdalwarp_lib.cpp b/apps/gdalwarp_lib.cpp
new file mode 100644
index 0000000..b5aa5ef
--- /dev/null
+++ b/apps/gdalwarp_lib.cpp
@@ -0,0 +1,2967 @@
+/******************************************************************************
+ * $Id: gdalwarp_lib.cpp 33757 2016-03-20 20:22:33Z goatbar $
+ *
+ * Project:  High Performance Image Reprojector
+ * Purpose:  Test program for high performance warper API.
+ * Author:   Frank Warmerdam <warmerdam at pobox.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2002, i3 - information integration and imaging
+ *                          Fort Collin, CO
+ * Copyright (c) 2007-2015, Even Rouault <even dot rouault at mines-paris dot org>
+ * Copyright (c) 2015, Faza Mahamood
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gdalwarper.h"
+#include "cpl_string.h"
+#include "cpl_error.h"
+#include "ogr_geometry.h"
+#include "ogr_spatialref.h"
+#include "ogr_api.h"
+#include "commonutils.h"
+#include "gdal_priv.h"
+#include <vector>
+#include <algorithm>
+#include "gdal_utils_priv.h"
+
+CPL_CVSID("$Id: gdalwarp_lib.cpp 33757 2016-03-20 20:22:33Z goatbar $");
+
+/************************************************************************/
+/*                        GDALWarpAppOptions                            */
+/************************************************************************/
+
+/** Options for use with GDALWarp(). GDALWarpAppOptions* must be allocated and
+ * freed with GDALWarpAppOptionsNew() and GDALWarpAppOptionsFree() respectively.
+ */
+struct GDALWarpAppOptions
+{
+    /*! set georeferenced extents of output file to be created (in target SRS by default,
+        or in the SRS specified with pszTE_SRS) */
+    double dfMinX;
+    double dfMinY;
+    double dfMaxX;
+    double dfMaxY;
+
+    /*! the SRS in which to interpret the coordinates given in GDALWarpAppOptions::dfMinX,
+        GDALWarpAppOptions::dfMinY, GDALWarpAppOptions::dfMaxX and GDALWarpAppOptions::dfMaxY.
+        The SRS may be any of the usual GDAL/OGR forms,
+        complete WKT, PROJ.4, EPSG:n or a file containing the WKT. It is a
+        convenience e.g. when knowing the output coordinates in a
+        geodetic long/lat SRS, but still wanting a result in a projected
+        coordinate system. */
+    char *pszTE_SRS;
+
+    /*! set output file resolution (in target georeferenced units) */
+    double dfXRes;
+    double dfYRes;
+
+    /*! align the coordinates of the extent of the output file to the values of the
+        GDALWarpAppOptions::dfXRes and GDALWarpAppOptions::dfYRes, such that the
+        aligned extent includes the minimum extent. */
+    int bTargetAlignedPixels;
+
+    /*! set output file size in pixels and lines. If GDALWarpAppOptions::nForcePixels
+        or GDALWarpAppOptions::nForceLines is set to 0, the other dimension will be
+        guessed from the computed resolution. Note that GDALWarpAppOptions::nForcePixels and
+        GDALWarpAppOptions::nForceLines cannot be used with GDALWarpAppOptions::dfXRes and
+        GDALWarpAppOptions::dfYRes. */
+    int nForcePixels;
+    int nForceLines;
+
+    /*! allow or suppress progress monitor and other non-error output */
+    int bQuiet;
+
+    /*! the progress function to use */
+    GDALProgressFunc pfnProgress;
+
+    /*! pointer to the progress data variable */
+    void *pProgressData;
+
+    /*! creates an output alpha band to identify nodata (unset/transparent) pixels
+        when set to TRUE */
+    int bEnableDstAlpha;
+
+    int bEnableSrcAlpha;
+
+    /*! output format. The default is GeoTIFF (GTiff). Use the short format name. */
+    char *pszFormat;
+
+    int bCreateOutput;
+
+    /*! list of warp options. ("NAME1=VALUE1","NAME2=VALUE2",...). The
+        GDALWarpOptions::papszWarpOptions docs show all options. */
+    char **papszWarpOptions;
+
+    double dfErrorThreshold;
+
+    /*! the amount of memory (in megabytes) that the warp API is allowed
+        to use for caching. */
+    double dfWarpMemoryLimit;
+
+    /*! list of create options for the output format driver. See format
+        specific documentation for legal creation options for each format. */
+    char **papszCreateOptions;
+
+    /*! the data type of the output bands */
+    GDALDataType eOutputType;
+
+    /*! working pixel data type. The data type of pixels in the source
+        image and destination image buffers. */
+    GDALDataType eWorkingType;
+
+    /*! the resampling method. Available methods are: near, bilinear,
+        cubic, cubicspline, lanczos, average, mode, max, min, med,
+        q1, q3 */
+    GDALResampleAlg eResampleAlg;
+
+    /*! nodata masking values for input bands (different values can be supplied
+        for each band). ("value1 value2 ..."). Masked values will not be used
+        in interpolation. Use a value of "None" to ignore intrinsic nodata
+        settings on the source dataset. */
+    char *pszSrcNodata;
+
+    /*! nodata values for output bands (different values can be supplied for
+        each band). ("value1 value2 ..."). New files will be initialized to
+        this value and if possible the nodata value will be recorded in the
+        output file. Use a value of "None" to ensure that nodata is not defined.
+        If this argument is not used then nodata values will be copied from
+        the source dataset. */
+    char *pszDstNodata;
+
+    /*! use multithreaded warping implementation. Multiple threads will be used
+        to process chunks of image and perform input/output operation simultaneously. */
+    int bMulti;
+
+    /*! list of transformer options suitable to pass to GDALCreateGenImgProjTransformer2().
+        ("NAME1=VALUE1","NAME2=VALUE2",...) */
+    char **papszTO;
+
+    /*! enable use of a blend cutline from the name OGR support pszCutlineDSName */
+    char *pszCutlineDSName;
+
+    /*! the named layer to be selected from the cutline datasource */
+    char *pszCLayer;
+
+    /*! restrict desired cutline features based on attribute query */
+    char *pszCWHERE;
+
+    /*! SQL query to select the cutline features instead of from a layer
+        with pszCLayer */
+    char *pszCSQL;
+
+    /*! crop the extent of the target dataset to the extent of the cutline */
+    int bCropToCutline;
+
+    /*! copy dataset and band metadata will be copied from the first source dataset. Items that differ between
+        source datasets will be set "*" (see GDALWarpAppOptions::pszMDConflictValue) */
+    int bCopyMetadata;
+
+    /*! copy band information from the first source dataset */
+    int bCopyBandInfo;
+
+    /*! value to set metadata items that conflict between source datasets (default is "*").
+        Use "" to remove conflicting items. */
+    char *pszMDConflictValue;
+
+    /*! set the color interpretation of the bands of the target dataset from the source dataset */
+    int bSetColorInterpretation;
+
+    /*! overview level of source files to be used */
+    int nOvLevel;
+};
+
+static CPLErr
+LoadCutline( const char *pszCutlineDSName, const char *pszCLayer,
+             const char *pszCWHERE, const char *pszCSQL,
+             void **phCutlineRet );
+static CPLErr
+TransformCutlineToSource( GDALDatasetH hSrcDS, void *hCutline,
+                          char ***ppapszWarpOptions, char **papszTO );
+
+static GDALDatasetH
+GDALWarpCreateOutput( int nSrcCount, GDALDatasetH *pahSrcDS, const char *pszFilename,
+                      const char *pszFormat, char **papszTO,
+                      char ***ppapszCreateOptions, GDALDataType eDT,
+                      void ** phTransformArg,
+                      int bSetColorInterpretation,
+                      GDALWarpAppOptions *psOptions);
+
+static void
+RemoveConflictingMetadata( GDALMajorObjectH hObj, char **papszMetadata,
+                           const char *pszValueConflict );
+
+static double GetAverageSegmentLength(OGRGeometryH hGeom)
+{
+    if( hGeom == NULL )
+        return 0;
+    switch(wkbFlatten(OGR_G_GetGeometryType(hGeom)))
+    {
+        case wkbLineString:
+        {
+            if( OGR_G_GetPointCount(hGeom) == 0 )
+                return 0;
+            double dfSum = 0;
+            for(int i=0;i<OGR_G_GetPointCount(hGeom)-1;i++)
+            {
+                double dfX1 = OGR_G_GetX(hGeom, i);
+                double dfY1 = OGR_G_GetY(hGeom, i);
+                double dfX2 = OGR_G_GetX(hGeom, i+1);
+                double dfY2 = OGR_G_GetY(hGeom, i+1);
+                double dfDX = dfX2 - dfX1;
+                double dfDY = dfY2 - dfY1;
+                dfSum += sqrt(dfDX * dfDX + dfDY * dfDY);
+            }
+            return dfSum / OGR_G_GetPointCount(hGeom);
+        }
+
+        case wkbPolygon:
+        case wkbMultiPolygon:
+        case wkbMultiLineString:
+        case wkbGeometryCollection:
+        {
+            if( OGR_G_GetGeometryCount(hGeom) == 0 )
+                return 0;
+            double dfSum = 0;
+            for(int i=0; i< OGR_G_GetGeometryCount(hGeom); i++)
+            {
+                dfSum += GetAverageSegmentLength(OGR_G_GetGeometryRef(hGeom, i));
+            }
+            return dfSum / OGR_G_GetGeometryCount(hGeom);
+        }
+
+        default:
+            return 0;
+    }
+}
+
+/************************************************************************/
+/*                           CropToCutline()                            */
+/************************************************************************/
+
+static CPLErr CropToCutline( void* hCutline, char** papszTO, int nSrcCount, GDALDatasetH *pahSrcDS,
+                           double& dfMinX, double& dfMinY, double& dfMaxX, double &dfMaxY )
+{
+    OGRGeometryH hCutlineGeom = OGR_G_Clone( (OGRGeometryH) hCutline );
+    OGRSpatialReferenceH hCutlineSRS = OGR_G_GetSpatialReference( hCutlineGeom );
+    const char *pszThisTargetSRS = CSLFetchNameValue( papszTO, "DST_SRS" );
+    const char *pszThisSourceSRS = CSLFetchNameValue(papszTO, "SRC_SRS");
+    OGRCoordinateTransformationH hCTCutlineToSrc = NULL;
+    OGRCoordinateTransformationH hCTSrcToDst = NULL;
+    OGRSpatialReferenceH hSrcSRS = NULL, hDstSRS = NULL;
+
+    if( pszThisSourceSRS != NULL )
+    {
+        hSrcSRS = OSRNewSpatialReference(NULL);
+        if( OSRImportFromWkt( hSrcSRS, (char **)&pszThisSourceSRS ) != OGRERR_NONE )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Cannot compute bounding box of cutline.");
+            OSRDestroySpatialReference(hSrcSRS);
+            OGR_G_DestroyGeometry(hCutlineGeom);
+            return CE_Failure;
+        }
+    }
+    else if( nSrcCount == 0 || pahSrcDS[0] == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot compute bounding box of cutline.");
+        OGR_G_DestroyGeometry(hCutlineGeom);
+        return CE_Failure;
+    }
+    else
+    {
+        const char *pszProjection = NULL;
+
+        if( GDALGetProjectionRef( pahSrcDS[0] ) != NULL
+            && strlen(GDALGetProjectionRef( pahSrcDS[0] )) > 0 )
+            pszProjection = GDALGetProjectionRef( pahSrcDS[0] );
+        else if( GDALGetGCPProjection( pahSrcDS[0] ) != NULL )
+            pszProjection = GDALGetGCPProjection( pahSrcDS[0] );
+
+        if( pszProjection == NULL || pszProjection[0] == '\0' )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Cannot compute bounding box of cutline.");
+            OGR_G_DestroyGeometry(hCutlineGeom);
+            return CE_Failure;
+        }
+
+        hSrcSRS = OSRNewSpatialReference(NULL);
+        if( OSRImportFromWkt( hSrcSRS, (char **)&pszProjection ) != OGRERR_NONE )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Cannot compute bounding box of cutline.");
+            OSRDestroySpatialReference(hSrcSRS);
+            OGR_G_DestroyGeometry(hCutlineGeom);
+            return CE_Failure;
+        }
+
+    }
+
+    if ( pszThisTargetSRS != NULL )
+    {
+        hDstSRS = OSRNewSpatialReference(NULL);
+        if( OSRImportFromWkt( hDstSRS, (char **)&pszThisTargetSRS ) != OGRERR_NONE )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Cannot compute bounding box of cutline.");
+            OSRDestroySpatialReference(hSrcSRS);
+            OSRDestroySpatialReference(hDstSRS);
+            OGR_G_DestroyGeometry(hCutlineGeom);
+            return CE_Failure;
+        }
+    }
+    else
+        hDstSRS = OSRClone(hSrcSRS);
+
+    OGRSpatialReferenceH hCutlineOrTargetSRS = hCutlineSRS ? hCutlineSRS : hDstSRS;
+
+    if( !OSRIsSame(hCutlineOrTargetSRS, hSrcSRS) )
+        hCTCutlineToSrc = OCTNewCoordinateTransformation(hCutlineOrTargetSRS, hSrcSRS);
+    if( !OSRIsSame(hSrcSRS, hDstSRS) )
+        hCTSrcToDst = OCTNewCoordinateTransformation(hSrcSRS, hDstSRS);
+
+    OSRDestroySpatialReference(hSrcSRS);
+    hSrcSRS = NULL;
+
+    OSRDestroySpatialReference(hDstSRS);
+    hDstSRS = NULL;
+
+    // Reproject cutline to target SRS, by doing intermediate vertex densification
+    // in source SRS.
+    if( hCTSrcToDst != NULL || hCTCutlineToSrc != NULL )
+    {
+        OGREnvelope sLastEnvelope, sCurEnvelope;
+        OGRGeometryH hTransformedGeom = NULL;
+        OGRGeometryH hGeomInSrcSRS = OGR_G_Clone(hCutlineGeom);
+        if( hCTCutlineToSrc != NULL )
+            OGR_G_Transform( hGeomInSrcSRS, hCTCutlineToSrc );
+
+        for(int nIter=0;nIter<10;nIter++)
+        {
+            if( hTransformedGeom != NULL )
+                OGR_G_DestroyGeometry(hTransformedGeom);
+            hTransformedGeom = OGR_G_Clone(hGeomInSrcSRS);
+            if( hCTSrcToDst != NULL )
+                OGR_G_Transform( hTransformedGeom, hCTSrcToDst );
+            OGR_G_GetEnvelope(hTransformedGeom, &sCurEnvelope);
+            if( nIter > 0 || hCTSrcToDst == NULL )
+            {
+                if( sCurEnvelope.MinX == sLastEnvelope.MinX &&
+                    sCurEnvelope.MinY == sLastEnvelope.MinY &&
+                    sCurEnvelope.MaxX == sLastEnvelope.MaxX &&
+                    sCurEnvelope.MaxY == sLastEnvelope.MaxY )
+                {
+                    break;
+                }
+            }
+            double dfAverageSegmentLength = GetAverageSegmentLength(hGeomInSrcSRS);
+            OGR_G_Segmentize(hGeomInSrcSRS, dfAverageSegmentLength/4);
+
+            memcpy(&sLastEnvelope, &sCurEnvelope, sizeof(OGREnvelope));
+        }
+
+        OGR_G_DestroyGeometry(hGeomInSrcSRS);
+
+        OGR_G_DestroyGeometry(hCutlineGeom);
+        hCutlineGeom = hTransformedGeom;
+    }
+
+    if( hCTCutlineToSrc)
+        OCTDestroyCoordinateTransformation(hCTCutlineToSrc);
+    if( hCTSrcToDst )
+        OCTDestroyCoordinateTransformation(hCTSrcToDst);
+
+    OGREnvelope sEnvelope;
+    OGR_G_GetEnvelope(hCutlineGeom, &sEnvelope);
+
+    dfMinX = sEnvelope.MinX;
+    dfMinY = sEnvelope.MinY;
+    dfMaxX = sEnvelope.MaxX;
+    dfMaxY = sEnvelope.MaxY;
+
+    OGR_G_DestroyGeometry(hCutlineGeom);
+
+    return CE_None;
+}
+
+
+/************************************************************************/
+/*                          GDALWarpAppOptionsClone()                   */
+/************************************************************************/
+
+static
+GDALWarpAppOptions* GDALWarpAppOptionsClone(const GDALWarpAppOptions *psOptionsIn)
+{
+    GDALWarpAppOptions* psOptions = (GDALWarpAppOptions*) CPLMalloc(sizeof(GDALWarpAppOptions));
+    memcpy(psOptions, psOptionsIn, sizeof(GDALWarpAppOptions));
+    psOptions->pszFormat = CPLStrdup(psOptionsIn->pszFormat);
+    psOptions->papszCreateOptions = CSLDuplicate(psOptionsIn->papszCreateOptions);
+    psOptions->papszWarpOptions = CSLDuplicate(psOptionsIn->papszWarpOptions);
+    if( psOptionsIn->pszSrcNodata ) psOptions->pszSrcNodata = CPLStrdup(psOptionsIn->pszSrcNodata);
+    if( psOptionsIn->pszDstNodata ) psOptions->pszDstNodata = CPLStrdup(psOptionsIn->pszDstNodata);
+    psOptions->papszTO = CSLDuplicate(psOptionsIn->papszTO);
+    if( psOptionsIn->pszCutlineDSName ) psOptions->pszCutlineDSName = CPLStrdup(psOptionsIn->pszCutlineDSName);
+    if( psOptionsIn->pszCLayer ) psOptions->pszCLayer = CPLStrdup(psOptionsIn->pszCLayer);
+    if( psOptionsIn->pszCWHERE ) psOptions->pszCWHERE = CPLStrdup(psOptionsIn->pszCWHERE);
+    if( psOptionsIn->pszCSQL ) psOptions->pszCSQL = CPLStrdup(psOptionsIn->pszCSQL);
+    if( psOptionsIn->pszMDConflictValue ) psOptions->pszMDConflictValue = CPLStrdup(psOptionsIn->pszMDConflictValue);
+    if( psOptionsIn->pszTE_SRS ) psOptions->pszTE_SRS = CPLStrdup(psOptionsIn->pszTE_SRS);
+    return psOptions;
+}
+
+/************************************************************************/
+/*                             GDALWarp()                               */
+/************************************************************************/
+
+/**
+ * Image reprojection and warping function.
+ *
+ * This is the equivalent of the <a href="gdal_warp.html">gdalwarp</a> utility.
+ *
+ * GDALWarpAppOptions* must be allocated and freed with GDALWarpAppOptionsNew()
+ * and GDALWarpAppOptionsFree() respectively.
+ * pszDest and hDstDS cannot be used at the same time.
+ *
+ * @param pszDest the destination dataset path or NULL.
+ * @param hDstDS the destination dataset or NULL.
+ * @param nSrcCount the number of input datasets.
+ * @param pahSrcDS the list of input datasets.
+ * @param psOptionsIn the options struct returned by GDALWarpAppOptionsNew() or NULL.
+ * @param pbUsageError the pointer to int variable to determine any usage error has occurred.
+ * @return the output dataset (new dataset that must be closed using GDALClose(), or hDstDS is not NULL) or NULL in case of error.
+ *
+ * @since GDAL 2.1
+ */
+
+GDALDatasetH GDALWarp( const char *pszDest, GDALDatasetH hDstDS, int nSrcCount,
+                       GDALDatasetH *pahSrcDS, const GDALWarpAppOptions *psOptionsIn, int *pbUsageError )
+{
+    CPLErrorReset();
+    if( pszDest == NULL && hDstDS == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "pszDest == NULL && hDstDS == NULL");
+
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        return NULL;
+    }
+    if( pszDest == NULL )
+        pszDest = GDALGetDescription(hDstDS);
+
+    int bMustCloseDstDSInCaseOfError = (hDstDS == NULL);
+    GDALTransformerFunc pfnTransformer = NULL;
+    void *hTransformArg = NULL;
+    int bHasGotErr = FALSE;
+    int bVRT = FALSE;
+    void *hCutline = NULL;
+
+    GDALWarpAppOptions* psOptions =
+        (psOptionsIn) ? GDALWarpAppOptionsClone(psOptionsIn) :
+                        GDALWarpAppOptionsNew(NULL, NULL);
+
+    if( EQUAL(psOptions->pszFormat,"VRT") )
+    {
+        if( hDstDS != NULL )
+        {
+            CPLError(CE_Warning, CPLE_NotSupported,
+                     "VRT output not compatible with existing dataset.");
+            GDALWarpAppOptionsFree(psOptions);
+            return NULL;
+        }
+
+        bVRT = TRUE;
+
+        if( nSrcCount > 1 )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined, "gdalwarp -of VRT just takes into account "
+                            "the first source dataset.\nIf all source datasets "
+                            "are in the same projection, try making a mosaic of\n"
+                            "them with gdalbuildvrt, and use the resulting "
+                            "VRT file as the input of\ngdalwarp -of VRT.");
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Check that incompatible options are not used                    */
+/* -------------------------------------------------------------------- */
+
+    if ((psOptions->nForcePixels != 0 || psOptions->nForceLines != 0) &&
+        (psOptions->dfXRes != 0 && psOptions->dfYRes != 0))
+    {
+        CPLError(CE_Failure, CPLE_IllegalArg, "-tr and -ts options cannot be used at the same time.");
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        GDALWarpAppOptionsFree(psOptions);
+        return NULL;
+    }
+
+    if (psOptions->bTargetAlignedPixels && psOptions->dfXRes == 0 && psOptions->dfYRes == 0)
+    {
+        CPLError(CE_Failure, CPLE_IllegalArg, "-tap option cannot be used without using -tr.");
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        GDALWarpAppOptionsFree(psOptions);
+        return NULL;
+    }
+
+    if( !psOptions->bQuiet && !(psOptions->dfMinX == 0.0 && psOptions->dfMinY == 0.0 && psOptions->dfMaxX == 0.0 && psOptions->dfMaxY == 0.0)  )
+    {
+        if( psOptions->dfMinX >= psOptions->dfMaxX )
+            CPLError(CE_Warning, CPLE_AppDefined, "-ts values have minx >= maxx. This will result in a horizontally flipped image.");
+        if( psOptions->dfMinY >= psOptions->dfMaxY )
+            CPLError(CE_Warning, CPLE_AppDefined, "-ts values have miny >= maxy. This will result in a vertically flipped image.");
+    }
+
+    if( psOptions->dfErrorThreshold < 0 )
+    {
+        // By default, use approximate transformer unless RPC_DEM is specified
+        if( CSLFetchNameValue(psOptions->papszWarpOptions, "RPC_DEM") != NULL )
+            psOptions->dfErrorThreshold = 0.0;
+        else
+            psOptions->dfErrorThreshold = 0.125;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      -te_srs option                                                  */
+/* -------------------------------------------------------------------- */
+    if( psOptions->pszTE_SRS != NULL )
+    {
+        if( psOptions->dfMinX == 0.0 && psOptions->dfMinY == 0.0 && psOptions->dfMaxX == 0.0 && psOptions->dfMaxY == 0.0 )
+        {
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "-te_srs ignored since -te is not specified.");
+        }
+        else
+        {
+            OGRSpatialReference oSRSIn;
+            oSRSIn.SetFromUserInput(psOptions->pszTE_SRS);
+            OGRSpatialReference oSRSDS;
+            int bOK = FALSE;
+            if( CSLFetchNameValue( psOptions->papszTO, "DST_SRS" ) != NULL )
+            {
+                oSRSDS.SetFromUserInput( CSLFetchNameValue( psOptions->papszTO, "DST_SRS" ) );
+                bOK = TRUE;
+            }
+            else if( CSLFetchNameValue( psOptions->papszTO, "SRC_SRS" ) != NULL )
+            {
+                oSRSDS.SetFromUserInput( CSLFetchNameValue( psOptions->papszTO, "SRC_SRS" ) );
+                bOK = TRUE;
+            }
+            else
+            {
+                if( nSrcCount && pahSrcDS[0] && GDALGetProjectionRef(pahSrcDS[0]) && GDALGetProjectionRef(pahSrcDS[0])[0] )
+                {
+                    oSRSDS.SetFromUserInput( GDALGetProjectionRef(pahSrcDS[0]) );
+                    bOK = TRUE;
+                }
+            }
+            if( !bOK )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined, "-te_srs ignored since none of -t_srs, -s_srs is specified or the input dataset has no projection.");
+                GDALWarpAppOptionsFree(psOptions);
+                return NULL;
+            }
+            if( !oSRSIn.IsSame(&oSRSDS) )
+            {
+                OGRCoordinateTransformation* poCT = OGRCreateCoordinateTransformation(&oSRSIn, &oSRSDS);
+                if( !(poCT &&
+                    poCT->Transform(1, &psOptions->dfMinX, &psOptions->dfMinY) &&
+                    poCT->Transform(1, &psOptions->dfMaxX, &psOptions->dfMaxY)) )
+                {
+                    OGRCoordinateTransformation::DestroyCT(poCT);
+
+                    CPLError( CE_Failure, CPLE_AppDefined, "-te_srs ignored since coordinate transformation failed.");
+                    GDALWarpAppOptionsFree(psOptions);
+                    return NULL;
+                }
+                delete poCT;
+            }
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      If we have a cutline datasource read it and attach it in the    */
+/*      warp options.                                                   */
+/* -------------------------------------------------------------------- */
+    if( psOptions->pszCutlineDSName != NULL )
+    {
+        CPLErr eError;
+        eError = LoadCutline( psOptions->pszCutlineDSName, psOptions->pszCLayer, psOptions->pszCWHERE, psOptions->pszCSQL,
+                     &hCutline );
+        if(eError == CE_Failure)
+        {
+            GDALWarpAppOptionsFree(psOptions);
+            return NULL;
+        }
+    }
+
+    if ( psOptions->bCropToCutline && hCutline != NULL )
+    {
+        CPLErr eError;
+        eError = CropToCutline( hCutline, psOptions->papszTO, nSrcCount, pahSrcDS,
+                       psOptions->dfMinX, psOptions->dfMinY, psOptions->dfMaxX, psOptions->dfMaxY );
+        if(eError == CE_Failure)
+        {
+            GDALWarpAppOptionsFree(psOptions);
+            OGR_G_DestroyGeometry( (OGRGeometryH) hCutline );
+            return NULL;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      If not, we need to create it.                                   */
+/* -------------------------------------------------------------------- */
+    void* hUniqueTransformArg = NULL;
+    int bInitDestSetByUser = ( CSLFetchNameValue( psOptions->papszWarpOptions, "INIT_DEST" ) != NULL );
+
+    const char* pszWarpThreads = CSLFetchNameValue(psOptions->papszWarpOptions, "NUM_THREADS");
+    if( pszWarpThreads != NULL )
+    {
+        /* Used by TPS transformer to parallelize direct and inverse matrix computation */
+        psOptions->papszTO = CSLSetNameValue(psOptions->papszTO, "NUM_THREADS", pszWarpThreads);
+    }
+
+    if( hDstDS == NULL )
+    {
+        hDstDS = GDALWarpCreateOutput( nSrcCount, pahSrcDS, pszDest,psOptions->pszFormat,
+                                       psOptions->papszTO, &psOptions->papszCreateOptions,
+                                       psOptions->eOutputType, &hUniqueTransformArg,
+                                       psOptions->bSetColorInterpretation,
+                                       psOptions);
+        if(hDstDS == NULL)
+        {
+            if( hUniqueTransformArg )
+                GDALDestroyTransformer( hUniqueTransformArg );
+            GDALWarpAppOptionsFree(psOptions);
+            if( hCutline != NULL )
+                OGR_G_DestroyGeometry( (OGRGeometryH) hCutline );
+            return NULL;
+        }
+
+        psOptions->bCreateOutput = TRUE;
+
+        if( !bInitDestSetByUser )
+        {
+            if ( psOptions->pszDstNodata == NULL )
+            {
+                psOptions->papszWarpOptions = CSLSetNameValue(psOptions->papszWarpOptions,
+                                                "INIT_DEST", "0");
+            }
+            else
+            {
+                psOptions->papszWarpOptions = CSLSetNameValue(psOptions->papszWarpOptions,
+                                                "INIT_DEST", "NO_DATA" );
+            }
+        }
+
+        CSLDestroy( psOptions->papszCreateOptions );
+        psOptions->papszCreateOptions = NULL;
+    }
+
+    if( hDstDS == NULL )
+    {
+        GDALWarpAppOptionsFree(psOptions);
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Loop over all source files, processing each in turn.            */
+/* -------------------------------------------------------------------- */
+    int iSrc;
+
+    for( iSrc = 0; iSrc < nSrcCount; iSrc++ )
+    {
+        GDALDatasetH hSrcDS;
+
+/* -------------------------------------------------------------------- */
+/*      Open this file.                                                 */
+/* -------------------------------------------------------------------- */
+        hSrcDS = pahSrcDS[iSrc];
+        if( hSrcDS == NULL )
+        {
+            GDALWarpAppOptionsFree(psOptions);
+            if( hCutline != NULL )
+                OGR_G_DestroyGeometry( (OGRGeometryH) hCutline );
+            if( bMustCloseDstDSInCaseOfError )
+                GDALClose(hDstDS);
+            return NULL;
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Check that there's at least one raster band                     */
+/* -------------------------------------------------------------------- */
+        if ( GDALGetRasterCount(hSrcDS) == 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Input file %s has no raster bands.", GDALGetDescription(hSrcDS) );
+            GDALWarpAppOptionsFree(psOptions);
+            if( hCutline != NULL )
+                OGR_G_DestroyGeometry( (OGRGeometryH) hCutline );
+            if( bMustCloseDstDSInCaseOfError )
+                GDALClose(hDstDS);
+            return NULL;
+        }
+
+        if( !psOptions->bQuiet )
+            printf( "Processing input file %s.\n", GDALGetDescription(hSrcDS) );
+
+/* -------------------------------------------------------------------- */
+/*      Get the metadata of the first source DS and copy it to the      */
+/*      destination DS. Copy Band-level metadata and other info, only   */
+/*      if source and destination band count are equal. Any values that */
+/*      conflict between source datasets are set to pszMDConflictValue. */
+/* -------------------------------------------------------------------- */
+        if ( psOptions->bCopyMetadata )
+        {
+            char **papszMetadata = NULL;
+            const char *pszSrcInfo = NULL;
+            const char *pszDstInfo = NULL;
+            GDALRasterBandH hSrcBand = NULL;
+            GDALRasterBandH hDstBand = NULL;
+
+            /* copy metadata from first dataset */
+            if ( iSrc == 0 )
+            {
+                CPLDebug("WARP", "Copying metadata from first source to destination dataset");
+                /* copy dataset-level metadata */
+                papszMetadata = GDALGetMetadata( hSrcDS, NULL );
+
+                char** papszMetadataNew = NULL;
+                for( int i = 0; papszMetadata != NULL && papszMetadata[i] != NULL; i++ )
+                {
+                    // Do not preserve NODATA_VALUES when the output includes an alpha band
+                    if( psOptions->bEnableDstAlpha &&
+                        STARTS_WITH_CI(papszMetadata[i], "NODATA_VALUES=") )
+                    {
+                        continue;
+                    }
+
+                    papszMetadataNew = CSLAddString(papszMetadataNew, papszMetadata[i]);
+                }
+
+                if ( CSLCount(papszMetadataNew) > 0 ) {
+                    if ( GDALSetMetadata( hDstDS, papszMetadataNew, NULL ) != CE_None )
+                         CPLError( CE_Warning, CPLE_AppDefined,
+                                  "error copying metadata to destination dataset." );
+                }
+
+                CSLDestroy(papszMetadataNew);
+
+                /* copy band-level metadata and other info */
+                if ( GDALGetRasterCount( hSrcDS ) == GDALGetRasterCount( hDstDS ) )
+                {
+                    for ( int iBand = 0; iBand < GDALGetRasterCount( hSrcDS ); iBand++ )
+                    {
+                        hSrcBand = GDALGetRasterBand( hSrcDS, iBand + 1 );
+                        hDstBand = GDALGetRasterBand( hDstDS, iBand + 1 );
+                        /* copy metadata, except stats (#5319) */
+                        papszMetadata = GDALGetMetadata( hSrcBand, NULL);
+                        if ( CSLCount(papszMetadata) > 0 )
+                        {
+                            //GDALSetMetadata( hDstBand, papszMetadata, NULL );
+                            papszMetadataNew = NULL;
+                            for( int i = 0; papszMetadata != NULL && papszMetadata[i] != NULL; i++ )
+                            {
+                                if (!STARTS_WITH(papszMetadata[i], "STATISTICS_"))
+                                    papszMetadataNew = CSLAddString(papszMetadataNew, papszMetadata[i]);
+                            }
+                            GDALSetMetadata( hDstBand, papszMetadataNew, NULL );
+                            CSLDestroy(papszMetadataNew);
+                        }
+                        /* copy other info (Description, Unit Type) - what else? */
+                        if ( psOptions->bCopyBandInfo ) {
+                            pszSrcInfo = GDALGetDescription( hSrcBand );
+                            if(  pszSrcInfo != NULL && strlen(pszSrcInfo) > 0 )
+                                GDALSetDescription( hDstBand, pszSrcInfo );
+                            pszSrcInfo = GDALGetRasterUnitType( hSrcBand );
+                            if(  pszSrcInfo != NULL && strlen(pszSrcInfo) > 0 )
+                                GDALSetRasterUnitType( hDstBand, pszSrcInfo );
+                        }
+                    }
+                }
+            }
+            /* remove metadata that conflicts between datasets */
+            else
+            {
+                CPLDebug("WARP",
+                         "Removing conflicting metadata from destination dataset (source #%d)", iSrc );
+                /* remove conflicting dataset-level metadata */
+                RemoveConflictingMetadata( hDstDS, GDALGetMetadata( hSrcDS, NULL ), psOptions->pszMDConflictValue );
+
+                /* remove conflicting copy band-level metadata and other info */
+                if ( GDALGetRasterCount( hSrcDS ) == GDALGetRasterCount( hDstDS ) )
+                {
+                    for ( int iBand = 0; iBand < GDALGetRasterCount( hSrcDS ); iBand++ )
+                    {
+                        hSrcBand = GDALGetRasterBand( hSrcDS, iBand + 1 );
+                        hDstBand = GDALGetRasterBand( hDstDS, iBand + 1 );
+                        /* remove conflicting metadata */
+                        RemoveConflictingMetadata( hDstBand, GDALGetMetadata( hSrcBand, NULL ), psOptions->pszMDConflictValue );
+                        /* remove conflicting info */
+                        if ( psOptions->bCopyBandInfo ) {
+                            pszSrcInfo = GDALGetDescription( hSrcBand );
+                            pszDstInfo = GDALGetDescription( hDstBand );
+                            if( ! ( pszSrcInfo != NULL && strlen(pszSrcInfo) > 0  &&
+                                    pszDstInfo != NULL && strlen(pszDstInfo) > 0  &&
+                                    EQUAL( pszSrcInfo, pszDstInfo ) ) )
+                                GDALSetDescription( hDstBand, "" );
+                            pszSrcInfo = GDALGetRasterUnitType( hSrcBand );
+                            pszDstInfo = GDALGetRasterUnitType( hDstBand );
+                            if( ! ( pszSrcInfo != NULL && strlen(pszSrcInfo) > 0  &&
+                                    pszDstInfo != NULL && strlen(pszDstInfo) > 0  &&
+                                    EQUAL( pszSrcInfo, pszDstInfo ) ) )
+                                GDALSetRasterUnitType( hDstBand, "" );
+                        }
+                    }
+                }
+            }
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Warns if the file has a color table and something more          */
+/*      complicated than nearest neighbour resampling is asked          */
+/* -------------------------------------------------------------------- */
+
+        if ( psOptions->eResampleAlg != GRA_NearestNeighbour &&
+             psOptions->eResampleAlg != GRA_Mode &&
+             GDALGetRasterColorTable(GDALGetRasterBand(hSrcDS, 1)) != NULL)
+        {
+            if( !psOptions->bQuiet )
+                CPLError( CE_Warning, CPLE_AppDefined, "Input file %s has a color table, which will likely lead to "
+                        "bad results when using a resampling method other than "
+                        "nearest neighbour or mode. Converting the dataset prior to 24/32 bit "
+                        "is advised.", GDALGetDescription(hSrcDS) );
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Do we have a source alpha band?                                 */
+/* -------------------------------------------------------------------- */
+        int bEnableSrcAlpha = psOptions->bEnableSrcAlpha;
+        if( GDALGetRasterColorInterpretation(
+                GDALGetRasterBand(hSrcDS,GDALGetRasterCount(hSrcDS)) )
+            == GCI_AlphaBand
+            && !bEnableSrcAlpha )
+        {
+            bEnableSrcAlpha = TRUE;
+            if( !psOptions->bQuiet )
+                printf( "Using band %d of source image as alpha.\n",
+                        GDALGetRasterCount(hSrcDS) );
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Create a transformation object from the source to               */
+/*      destination coordinate system.                                  */
+/* -------------------------------------------------------------------- */
+        if (hUniqueTransformArg)
+            hTransformArg = hUniqueTransformArg;
+        else
+            hTransformArg =
+                GDALCreateGenImgProjTransformer2( hSrcDS, hDstDS, psOptions->papszTO );
+
+        if( hTransformArg == NULL )
+        {
+            GDALWarpAppOptionsFree(psOptions);
+            if( hCutline != NULL )
+                OGR_G_DestroyGeometry( (OGRGeometryH) hCutline );
+            if( bMustCloseDstDSInCaseOfError )
+                GDALClose(hDstDS);
+            return NULL;
+        }
+
+        pfnTransformer = GDALGenImgProjTransform;
+
+/* -------------------------------------------------------------------- */
+/*      Determine if we must work with the full-resolution source       */
+/*      dataset, or one of its overview level.                          */
+/* -------------------------------------------------------------------- */
+        GDALDataset* poSrcDS = (GDALDataset*) hSrcDS;
+        GDALDataset* poSrcOvrDS = NULL;
+        int nOvCount = poSrcDS->GetRasterBand(1)->GetOverviewCount();
+        if( psOptions->nOvLevel <= -2 && nOvCount > 0 )
+        {
+            double adfSuggestedGeoTransform[6];
+            double adfExtent[4];
+            int    nPixels, nLines;
+            /* Compute what the "natural" output resolution (in pixels) would be for this */
+            /* input dataset */
+            if( GDALSuggestedWarpOutput2(hSrcDS, pfnTransformer, hTransformArg,
+                                         adfSuggestedGeoTransform, &nPixels, &nLines,
+                                         adfExtent, 0) == CE_None)
+            {
+                double dfTargetRatio = 1.0 / adfSuggestedGeoTransform[1];
+                if( dfTargetRatio > 1.0 )
+                {
+                    int iOvr;
+                    for( iOvr = -1; iOvr < nOvCount-1; iOvr++ )
+                    {
+                        double dfOvrRatio = (iOvr < 0) ? 1.0 : (double)poSrcDS->GetRasterXSize() /
+                            poSrcDS->GetRasterBand(1)->GetOverview(iOvr)->GetXSize();
+                        double dfNextOvrRatio = (double)poSrcDS->GetRasterXSize() /
+                            poSrcDS->GetRasterBand(1)->GetOverview(iOvr+1)->GetXSize();
+                        if( dfOvrRatio < dfTargetRatio && dfNextOvrRatio > dfTargetRatio )
+                            break;
+                        if( fabs(dfOvrRatio - dfTargetRatio) < 1e-1 )
+                            break;
+                    }
+                    iOvr += (psOptions->nOvLevel+2);
+                    if( iOvr >= 0 )
+                    {
+                        CPLDebug("WARP", "Selecting overview level %d for %s",
+                                 iOvr, GDALGetDescription(hSrcDS));
+                        poSrcOvrDS = GDALCreateOverviewDataset( poSrcDS, iOvr, FALSE, FALSE );
+                    }
+                }
+            }
+        }
+        else if( psOptions->nOvLevel >= 0 )
+        {
+            poSrcOvrDS = GDALCreateOverviewDataset( poSrcDS, psOptions->nOvLevel, TRUE, FALSE );
+            if( poSrcOvrDS == NULL )
+            {
+                if( !psOptions->bQuiet )
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined, "cannot get overview level %d for "
+                            "dataset %s. Defaulting to level %d",
+                            psOptions->nOvLevel, GDALGetDescription(hSrcDS), nOvCount - 1);
+                }
+                if( nOvCount > 0 )
+                    poSrcOvrDS = GDALCreateOverviewDataset( poSrcDS, nOvCount - 1, FALSE, FALSE );
+            }
+            else
+            {
+                CPLDebug("WARP", "Selecting overview level %d for %s",
+                         psOptions->nOvLevel, GDALGetDescription(hSrcDS));
+            }
+        }
+
+        GDALDatasetH hWrkSrcDS = (poSrcOvrDS) ? (GDALDatasetH)poSrcOvrDS : hSrcDS;
+
+        /* We need to recreate the transform when operating on an overview */
+        if( poSrcOvrDS != NULL )
+        {
+            GDALDestroyGenImgProjTransformer( hTransformArg );
+            hTransformArg =
+                GDALCreateGenImgProjTransformer2( hWrkSrcDS, hDstDS, psOptions->papszTO );
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Warp the transformer with a linear approximator unless the      */
+/*      acceptable error is zero.                                       */
+/* -------------------------------------------------------------------- */
+        if( psOptions->dfErrorThreshold != 0.0 )
+        {
+            hTransformArg =
+                GDALCreateApproxTransformer( GDALGenImgProjTransform,
+                                             hTransformArg, psOptions->dfErrorThreshold);
+            pfnTransformer = GDALApproxTransform;
+            GDALApproxTransformerOwnsSubtransformer(hTransformArg, TRUE);
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Clear temporary INIT_DEST settings after the first image.       */
+/* -------------------------------------------------------------------- */
+        if( psOptions->bCreateOutput && iSrc == 1 )
+            psOptions->papszWarpOptions = CSLSetNameValue( psOptions->papszWarpOptions,
+                                                "INIT_DEST", NULL );
+
+/* -------------------------------------------------------------------- */
+/*      Setup warp options.                                             */
+/* -------------------------------------------------------------------- */
+        GDALWarpOptions *psWO = GDALCreateWarpOptions();
+
+        psWO->papszWarpOptions = CSLDuplicate(psOptions->papszWarpOptions);
+        psWO->eWorkingDataType = psOptions->eWorkingType;
+        psWO->eResampleAlg = psOptions->eResampleAlg;
+
+        psWO->hSrcDS = hWrkSrcDS;
+        psWO->hDstDS = hDstDS;
+
+        psWO->pfnTransformer = pfnTransformer;
+        psWO->pTransformerArg = hTransformArg;
+
+        psWO->pfnProgress = psOptions->pfnProgress;
+        psWO->pProgressArg = psOptions->pProgressData;
+
+        if( psOptions->dfWarpMemoryLimit != 0.0 )
+            psWO->dfWarpMemoryLimit = psOptions->dfWarpMemoryLimit;
+
+/* -------------------------------------------------------------------- */
+/*      Setup band mapping.                                             */
+/* -------------------------------------------------------------------- */
+        if( bEnableSrcAlpha )
+            psWO->nBandCount = GDALGetRasterCount(hWrkSrcDS) - 1;
+        else
+            psWO->nBandCount = GDALGetRasterCount(hWrkSrcDS);
+
+        psWO->panSrcBands = (int *) CPLMalloc(psWO->nBandCount*sizeof(int));
+        psWO->panDstBands = (int *) CPLMalloc(psWO->nBandCount*sizeof(int));
+
+        for( int i = 0; i < psWO->nBandCount; i++ )
+        {
+            psWO->panSrcBands[i] = i+1;
+            psWO->panDstBands[i] = i+1;
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Setup alpha bands used if any.                                  */
+/* -------------------------------------------------------------------- */
+        if( bEnableSrcAlpha )
+            psWO->nSrcAlphaBand = GDALGetRasterCount(hWrkSrcDS);
+
+        int bEnableDstAlpha = psOptions->bEnableDstAlpha;
+        if( !bEnableDstAlpha
+            && GDALGetRasterCount(hDstDS) == psWO->nBandCount+1
+            && GDALGetRasterColorInterpretation(
+                GDALGetRasterBand(hDstDS,GDALGetRasterCount(hDstDS)))
+            == GCI_AlphaBand )
+        {
+            if( !psOptions->bQuiet )
+                printf( "Using band %d of destination image as alpha.\n",
+                        GDALGetRasterCount(hDstDS) );
+
+            bEnableDstAlpha = TRUE;
+        }
+
+        if( bEnableDstAlpha )
+            psWO->nDstAlphaBand = GDALGetRasterCount(hDstDS);
+
+/* -------------------------------------------------------------------- */
+/*      Setup NODATA options.                                           */
+/* -------------------------------------------------------------------- */
+        if( psOptions->pszSrcNodata != NULL && !EQUAL(psOptions->pszSrcNodata,"none") )
+        {
+            char **papszTokens = CSLTokenizeString( psOptions->pszSrcNodata );
+            int  nTokenCount = CSLCount(papszTokens);
+
+            psWO->padfSrcNoDataReal = (double *)
+                CPLMalloc(psWO->nBandCount*sizeof(double));
+            psWO->padfSrcNoDataImag = (double *)
+                CPLMalloc(psWO->nBandCount*sizeof(double));
+
+            for( int i = 0; i < psWO->nBandCount; i++ )
+            {
+                if( i < nTokenCount )
+                {
+                    CPLStringToComplex( papszTokens[i],
+                                        psWO->padfSrcNoDataReal + i,
+                                        psWO->padfSrcNoDataImag + i );
+                }
+                else
+                {
+                    psWO->padfSrcNoDataReal[i] = psWO->padfSrcNoDataReal[i-1];
+                    psWO->padfSrcNoDataImag[i] = psWO->padfSrcNoDataImag[i-1];
+                }
+            }
+
+            CSLDestroy( papszTokens );
+
+            psWO->papszWarpOptions = CSLSetNameValue(psWO->papszWarpOptions,
+                                               "UNIFIED_SRC_NODATA", "YES" );
+        }
+
+/* -------------------------------------------------------------------- */
+/*      If -srcnodata was not specified, but the data has nodata        */
+/*      values, use them.                                               */
+/* -------------------------------------------------------------------- */
+        if( psOptions->pszSrcNodata == NULL )
+        {
+            int bHaveNodata = FALSE;
+            double dfReal = 0.0;
+
+            for( int i = 0; !bHaveNodata && i < psWO->nBandCount; i++ )
+            {
+                GDALRasterBandH hBand = GDALGetRasterBand( hWrkSrcDS, i+1 );
+                dfReal = GDALGetRasterNoDataValue( hBand, &bHaveNodata );
+            }
+
+            if( bHaveNodata )
+            {
+                if( !psOptions->bQuiet )
+                {
+                    if (CPLIsNan(dfReal))
+                        printf( "Using internal nodata values (e.g. nan) for image %s.\n",
+                                GDALGetDescription(hSrcDS) );
+                    else
+                        printf( "Using internal nodata values (e.g. %g) for image %s.\n",
+                                dfReal, GDALGetDescription(hSrcDS) );
+                }
+                psWO->padfSrcNoDataReal = (double *)
+                    CPLMalloc(psWO->nBandCount*sizeof(double));
+                psWO->padfSrcNoDataImag = (double *)
+                    CPLMalloc(psWO->nBandCount*sizeof(double));
+
+                for( int i = 0; i < psWO->nBandCount; i++ )
+                {
+                    GDALRasterBandH hBand = GDALGetRasterBand( hWrkSrcDS, i+1 );
+
+                    dfReal = GDALGetRasterNoDataValue( hBand, &bHaveNodata );
+
+                    if( bHaveNodata )
+                    {
+                        psWO->padfSrcNoDataReal[i] = dfReal;
+                        psWO->padfSrcNoDataImag[i] = 0.0;
+                    }
+                    else
+                    {
+                        psWO->padfSrcNoDataReal[i] = -123456.789;
+                        psWO->padfSrcNoDataImag[i] = 0.0;
+                    }
+                }
+            }
+        }
+
+/* -------------------------------------------------------------------- */
+/*      If the output dataset was created, and we have a destination    */
+/*      nodata value, go through marking the bands with the information.*/
+/* -------------------------------------------------------------------- */
+        if( psOptions->pszDstNodata != NULL && !EQUAL(psOptions->pszDstNodata,"none") )
+        {
+            char **papszTokens = CSLTokenizeString( psOptions->pszDstNodata );
+            int  nTokenCount = CSLCount(papszTokens);
+            int bDstNoDataNone = TRUE;
+
+            psWO->padfDstNoDataReal = (double *)
+                CPLMalloc(psWO->nBandCount*sizeof(double));
+            psWO->padfDstNoDataImag = (double *)
+                CPLMalloc(psWO->nBandCount*sizeof(double));
+
+            for( int i = 0; i < psWO->nBandCount; i++ )
+            {
+                psWO->padfDstNoDataReal[i] = -1.1e20;
+                psWO->padfDstNoDataImag[i] = 0.0;
+
+                if( i < nTokenCount )
+                {
+                    if ( papszTokens[i] != NULL && EQUAL(papszTokens[i],"none") )
+                    {
+                        CPLDebug( "WARP", "dstnodata of band %d not set", i );
+                        bDstNoDataNone = TRUE;
+                        continue;
+                    }
+                    else if ( papszTokens[i] == NULL ) // this should not happen, but just in case
+                    {
+                        CPLError( CE_Failure, CPLE_AppDefined, "Error parsing dstnodata arg #%d", i );
+                        bDstNoDataNone = TRUE;
+                        continue;
+                    }
+                    CPLStringToComplex( papszTokens[i],
+                                        psWO->padfDstNoDataReal + i,
+                                        psWO->padfDstNoDataImag + i );
+                    bDstNoDataNone = FALSE;
+                    CPLDebug( "WARP", "dstnodata of band %d set to %f", i, psWO->padfDstNoDataReal[i] );
+                }
+                else
+                {
+                    if ( ! bDstNoDataNone )
+                    {
+                        psWO->padfDstNoDataReal[i] = psWO->padfDstNoDataReal[i-1];
+                        psWO->padfDstNoDataImag[i] = psWO->padfDstNoDataImag[i-1];
+                        CPLDebug( "WARP", "dstnodata of band %d set from previous band", i );
+                    }
+                    else
+                    {
+                        CPLDebug( "WARP", "dstnodata value of band %d not set", i );
+                        continue;
+                    }
+                }
+
+                GDALRasterBandH hBand = GDALGetRasterBand( hDstDS, i+1 );
+                int bClamped = FALSE, bRounded = FALSE;
+                psWO->padfDstNoDataReal[i] = GDALAdjustValueToDataType(
+                                                     GDALGetRasterDataType(hBand),
+                                                     psWO->padfDstNoDataReal[i],
+                                                     &bClamped, &bRounded );
+
+                if (bClamped)
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "for band %d, destination nodata value has been clamped "
+                           "to %.0f, the original value being out of range.",
+                           i + 1, psWO->padfDstNoDataReal[i]);
+                }
+                else if(bRounded)
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "for band %d, destination nodata value has been rounded "
+                           "to %.0f, %s being an integer datatype.",
+                           i + 1, psWO->padfDstNoDataReal[i],
+                           GDALGetDataTypeName(GDALGetRasterDataType(hBand)));
+                }
+
+                if( psOptions->bCreateOutput && iSrc == 0 )
+                {
+                    GDALSetRasterNoDataValue(
+                        GDALGetRasterBand( hDstDS, psWO->panDstBands[i] ),
+                        psWO->padfDstNoDataReal[i] );
+                }
+            }
+
+            CSLDestroy( papszTokens );
+        }
+
+        /* check if the output dataset has already nodata */
+        if ( psOptions->pszDstNodata == NULL )
+        {
+            int bHaveNodataAll = TRUE;
+            for( int i = 0; i < psWO->nBandCount; i++ )
+            {
+                GDALRasterBandH hBand = GDALGetRasterBand( hDstDS, i+1 );
+                int bHaveNodata = FALSE;
+                GDALGetRasterNoDataValue( hBand, &bHaveNodata );
+                bHaveNodataAll &= bHaveNodata;
+            }
+            if( bHaveNodataAll )
+            {
+                psWO->padfDstNoDataReal = (double *)
+                    CPLMalloc(psWO->nBandCount*sizeof(double));
+                psWO->padfDstNoDataImag = (double *)
+                    CPLCalloc(psWO->nBandCount, sizeof(double));
+                for( int i = 0; i < psWO->nBandCount; i++ )
+                {
+                    GDALRasterBandH hBand = GDALGetRasterBand( hDstDS, i+1 );
+                    int bHaveNodata = FALSE;
+                    psWO->padfDstNoDataReal[i] = GDALGetRasterNoDataValue( hBand, &bHaveNodata );
+                    CPLDebug("WARP", "band=%d dstNoData=%f", i, psWO->padfDstNoDataReal[i] );
+                }
+            }
+        }
+
+        /* else try to fill dstNoData from source bands */
+        if ( psOptions->pszDstNodata == NULL && psWO->padfSrcNoDataReal != NULL &&
+             psWO->padfDstNoDataReal == NULL )
+        {
+            psWO->padfDstNoDataReal = (double *)
+                CPLMalloc(psWO->nBandCount*sizeof(double));
+            psWO->padfDstNoDataImag = (double *)
+                CPLMalloc(psWO->nBandCount*sizeof(double));
+
+            if( !psOptions->bQuiet )
+                printf( "Copying nodata values from source %s to destination %s.\n",
+                        GDALGetDescription(hSrcDS), pszDest );
+
+            for( int i = 0; i < psWO->nBandCount; i++ )
+            {
+                psWO->padfDstNoDataReal[i] = psWO->padfSrcNoDataReal[i];
+                psWO->padfDstNoDataImag[i] = psWO->padfSrcNoDataImag[i];
+                CPLDebug("WARP", "srcNoData=%f dstNoData=%f",
+                            psWO->padfSrcNoDataReal[i], psWO->padfDstNoDataReal[i] );
+
+                if( psOptions->bCreateOutput && iSrc == 0 )
+                {
+                    CPLDebug("WARP", "calling GDALSetRasterNoDataValue() for band#%d", i );
+                    GDALSetRasterNoDataValue(
+                        GDALGetRasterBand( hDstDS, psWO->panDstBands[i] ),
+                        psWO->padfDstNoDataReal[i] );
+                }
+            }
+
+            if( psOptions->bCreateOutput && !bInitDestSetByUser && iSrc == 0 )
+            {
+                /* As we didn't know at the beginning if there was source nodata */
+                /* we have initialized INIT_DEST=0. Override this with NO_DATA now */
+                psWO->papszWarpOptions = CSLSetNameValue(psWO->papszWarpOptions,
+                                                   "INIT_DEST", "NO_DATA" );
+            }
+        }
+
+/* -------------------------------------------------------------------- */
+/*      If we have a cutline, transform it into the source              */
+/*      pixel/line coordinate system and insert into warp options.      */
+/* -------------------------------------------------------------------- */
+        if( hCutline != NULL )
+        {
+            CPLErr eError;
+            eError = TransformCutlineToSource( hWrkSrcDS, hCutline,
+                                      &(psWO->papszWarpOptions),
+                                      psOptions->papszTO );
+            if(eError == CE_Failure)
+            {
+                if( hTransformArg != NULL )
+                    GDALDestroyTransformer( hTransformArg );
+                GDALDestroyWarpOptions( psWO );
+                GDALWarpAppOptionsFree(psOptions);
+                if( hCutline != NULL )
+                    OGR_G_DestroyGeometry( (OGRGeometryH) hCutline );
+                if( bMustCloseDstDSInCaseOfError )
+                    GDALClose(hDstDS);
+                if( poSrcOvrDS )
+                    delete poSrcOvrDS;
+                return NULL;
+            }
+        }
+
+/* -------------------------------------------------------------------- */
+/*      If we are producing VRT output, then just initialize it with    */
+/*      the warp options and write out now rather than proceeding       */
+/*      with the operations.                                            */
+/* -------------------------------------------------------------------- */
+        if( bVRT )
+        {
+            GDALSetMetadataItem(hDstDS, "SrcOvrLevel", CPLSPrintf("%d", psOptions->nOvLevel), NULL);
+            if( GDALInitializeWarpedVRT( hDstDS, psWO ) != CE_None )
+            {
+                if( hTransformArg != NULL )
+                    GDALDestroyTransformer( hTransformArg );
+                GDALDestroyWarpOptions( psWO );
+                GDALWarpAppOptionsFree(psOptions);
+                if( hCutline != NULL )
+                    OGR_G_DestroyGeometry( (OGRGeometryH) hCutline );
+                if( bMustCloseDstDSInCaseOfError )
+                    GDALClose(hDstDS);
+                if( poSrcOvrDS )
+                    delete poSrcOvrDS;
+                return NULL;
+            }
+
+            // We need to close it before destroying poSrcOvrDS and warping options
+            CPLString osDstFilename(GDALGetDescription(hDstDS));
+
+            char** papszContent = NULL;
+            if( osDstFilename.size() == 0 )
+                papszContent = CSLDuplicate(GDALGetMetadata(hDstDS, "xml:VRT"));
+
+            GDALClose(hDstDS);
+
+            if( poSrcOvrDS )
+                delete poSrcOvrDS;
+
+            GDALDestroyWarpOptions( psWO );
+
+            GDALWarpAppOptionsFree(psOptions);
+            if( papszContent == NULL )
+                return GDALOpen(osDstFilename, GA_Update);
+            else
+            {
+                GDALDatasetH hDSRet = GDALOpen(papszContent[0], GA_ReadOnly);
+                CSLDestroy(papszContent);
+                return hDSRet;
+            }
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Initialize and execute the warp.                                */
+/* -------------------------------------------------------------------- */
+        GDALWarpOperation oWO;
+
+        if( oWO.Initialize( psWO ) == CE_None )
+        {
+            CPLErr eErr;
+            if( psOptions->bMulti )
+                eErr = oWO.ChunkAndWarpMulti( 0, 0,
+                                       GDALGetRasterXSize( hDstDS ),
+                                       GDALGetRasterYSize( hDstDS ) );
+            else
+                eErr = oWO.ChunkAndWarpImage( 0, 0,
+                                       GDALGetRasterXSize( hDstDS ),
+                                       GDALGetRasterYSize( hDstDS ) );
+            if (eErr != CE_None)
+                bHasGotErr = TRUE;
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Cleanup                                                         */
+/* -------------------------------------------------------------------- */
+        if( hTransformArg != NULL )
+            GDALDestroyTransformer( hTransformArg );
+
+        GDALDestroyWarpOptions( psWO );
+
+        if( poSrcOvrDS )
+            delete poSrcOvrDS;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Final Cleanup.                                                  */
+/* -------------------------------------------------------------------- */
+    CPLErr eErrBefore = CPLGetLastErrorType();
+    GDALFlushCache( hDstDS );
+    if (eErrBefore == CE_None &&
+        CPLGetLastErrorType() != CE_None)
+    {
+        bHasGotErr = TRUE;
+    }
+
+    if( hCutline != NULL )
+        OGR_G_DestroyGeometry( (OGRGeometryH) hCutline );
+
+    GDALWarpAppOptionsFree(psOptions);
+
+    if( bHasGotErr && bMustCloseDstDSInCaseOfError )
+        GDALClose(hDstDS);
+    return (bHasGotErr) ? NULL : hDstDS;
+}
+
+/************************************************************************/
+/*                            LoadCutline()                             */
+/*                                                                      */
+/*      Load blend cutline from OGR datasource.                         */
+/************************************************************************/
+
+static CPLErr
+LoadCutline( const char *pszCutlineDSName, const char *pszCLayer,
+             const char *pszCWHERE, const char *pszCSQL,
+             void **phCutlineRet )
+
+{
+    OGRRegisterAll();
+
+/* -------------------------------------------------------------------- */
+/*      Open source vector dataset.                                     */
+/* -------------------------------------------------------------------- */
+    OGRDataSourceH hSrcDS;
+
+    hSrcDS = OGROpen( pszCutlineDSName, FALSE, NULL );
+    if( hSrcDS == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Cannot open %s.", pszCutlineDSName);
+        return CE_Failure;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Get the source layer                                            */
+/* -------------------------------------------------------------------- */
+    OGRLayerH hLayer = NULL;
+
+    if( pszCSQL != NULL )
+        hLayer = OGR_DS_ExecuteSQL( hSrcDS, pszCSQL, NULL, NULL );
+    else if( pszCLayer != NULL )
+        hLayer = OGR_DS_GetLayerByName( hSrcDS, pszCLayer );
+    else
+        hLayer = OGR_DS_GetLayer( hSrcDS, 0 );
+
+    if( hLayer == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Failed to identify source layer from datasource." );
+        OGR_DS_Destroy( hSrcDS );
+        return CE_Failure;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Apply WHERE clause if there is one.                             */
+/* -------------------------------------------------------------------- */
+    if( pszCWHERE != NULL )
+        OGR_L_SetAttributeFilter( hLayer, pszCWHERE );
+
+/* -------------------------------------------------------------------- */
+/*      Collect the geometries from this layer, and build list of       */
+/*      burn values.                                                    */
+/* -------------------------------------------------------------------- */
+    OGRFeatureH hFeat;
+    OGRGeometryH hMultiPolygon = OGR_G_CreateGeometry( wkbMultiPolygon );
+
+    OGR_L_ResetReading( hLayer );
+
+    while( (hFeat = OGR_L_GetNextFeature( hLayer )) != NULL )
+    {
+        OGRGeometryH hGeom = OGR_F_GetGeometryRef(hFeat);
+
+        if( hGeom == NULL )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "Cutline feature without a geometry." );
+            OGR_F_Destroy( hFeat );
+            goto error;
+        }
+
+        OGRwkbGeometryType eType = wkbFlatten(OGR_G_GetGeometryType( hGeom ));
+
+        if( eType == wkbPolygon )
+            OGR_G_AddGeometry( hMultiPolygon, hGeom );
+        else if( eType == wkbMultiPolygon )
+        {
+            int iGeom;
+
+            for( iGeom = 0; iGeom < OGR_G_GetGeometryCount( hGeom ); iGeom++ )
+            {
+                OGR_G_AddGeometry( hMultiPolygon,
+                                   OGR_G_GetGeometryRef(hGeom,iGeom) );
+            }
+        }
+        else
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "Cutline not of polygon type." );
+            OGR_F_Destroy( hFeat );
+            goto error;
+        }
+
+        OGR_F_Destroy( hFeat );
+    }
+
+    if( OGR_G_GetGeometryCount( hMultiPolygon ) == 0 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Did not get any cutline features." );
+        goto error;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Ensure the coordinate system gets set on the geometry.          */
+/* -------------------------------------------------------------------- */
+    OGR_G_AssignSpatialReference(
+        hMultiPolygon, OGR_L_GetSpatialRef(hLayer) );
+
+    *phCutlineRet = (void *) hMultiPolygon;
+
+/* -------------------------------------------------------------------- */
+/*      Cleanup                                                         */
+/* -------------------------------------------------------------------- */
+    if( pszCSQL != NULL )
+        OGR_DS_ReleaseResultSet( hSrcDS, hLayer );
+
+    OGR_DS_Destroy( hSrcDS );
+
+    return CE_None;
+
+error:
+    OGR_G_DestroyGeometry(hMultiPolygon);
+    if( pszCSQL != NULL )
+        OGR_DS_ReleaseResultSet( hSrcDS, hLayer );
+    OGR_DS_Destroy( hSrcDS );
+    return CE_Failure;
+}
+
+/************************************************************************/
+/*                        GDALWarpCreateOutput()                        */
+/*                                                                      */
+/*      Create the output file based on various command line options,    */
+/*      and the input file.                                             */
+/*      If there's just one source file, then *phTransformArg will be   */
+/*      set in order them to be reused by main function. This saves     */
+/*      transform recomputation, which can be expensive in the -tps case*/
+/************************************************************************/
+
+static GDALDatasetH
+GDALWarpCreateOutput( int nSrcCount, GDALDatasetH *pahSrcDS, const char *pszFilename,
+                      const char *pszFormat, char **papszTO,
+                      char ***ppapszCreateOptions, GDALDataType eDT,
+                      void ** phTransformArg,
+                      int bSetColorInterpretation,
+                      GDALWarpAppOptions *psOptions)
+
+
+{
+    GDALDriverH hDriver;
+    GDALDatasetH hDstDS;
+    void *hTransformArg;
+    GDALColorTableH hCT = NULL;
+    double dfWrkMinX=0, dfWrkMaxX=0, dfWrkMinY=0, dfWrkMaxY=0;
+    double dfWrkResX=0, dfWrkResY=0;
+    int nDstBandCount = 0;
+    std::vector<GDALColorInterp> apeColorInterpretations;
+    int bVRT = FALSE;
+
+    if( EQUAL(pszFormat,"VRT") )
+        bVRT = TRUE;
+
+    /* If (-ts and -te) or (-tr and -te) are specified, we don't need to compute the suggested output extent */
+    int    bNeedsSuggestedWarpOutput =
+                  !( ((psOptions->nForcePixels != 0 && psOptions->nForceLines != 0) || (psOptions->dfXRes != 0 && psOptions->dfYRes != 0)) &&
+                     !(psOptions->dfMinX == 0.0 && psOptions->dfMinY == 0.0 && psOptions->dfMaxX == 0.0 && psOptions->dfMaxY == 0.0) );
+
+    *phTransformArg = NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Find the output driver.                                         */
+/* -------------------------------------------------------------------- */
+    hDriver = GDALGetDriverByName( pszFormat );
+    if( hDriver == NULL
+        || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) == NULL )
+    {
+        int iDr;
+
+        printf( "Output driver `%s' not recognised or does not support\n",
+                pszFormat );
+        printf( "direct output file creation.  The following format drivers are configured\n"
+                "and support direct output:\n" );
+
+        for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
+        {
+            hDriver = GDALGetDriver(iDr);
+
+            if( GDALGetMetadataItem( hDriver, GDAL_DCAP_RASTER, NULL) != NULL &&
+                GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL) != NULL )
+            {
+                printf( "  %s: %s\n",
+                        GDALGetDriverShortName( hDriver  ),
+                        GDALGetDriverLongName( hDriver ) );
+            }
+        }
+        printf( "\n" );
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      For virtual output files, we have to set a special subclass     */
+/*      of dataset to create.                                           */
+/* -------------------------------------------------------------------- */
+    if( bVRT )
+        *ppapszCreateOptions =
+            CSLSetNameValue( *ppapszCreateOptions, "SUBCLASS",
+                             "VRTWarpedDataset" );
+
+/* -------------------------------------------------------------------- */
+/*      Loop over all input files to collect extents.                   */
+/* -------------------------------------------------------------------- */
+    int     iSrc;
+    CPLString osThisTargetSRS;
+    {
+        const char *pszThisTargetSRS = CSLFetchNameValue( papszTO, "DST_SRS" );
+        if( pszThisTargetSRS != NULL )
+            osThisTargetSRS = pszThisTargetSRS;
+    }
+
+    for( iSrc = 0; iSrc < nSrcCount; iSrc++ )
+    {
+        const char *pszThisSourceSRS = CSLFetchNameValue(papszTO,"SRC_SRS");
+
+        if( pahSrcDS[iSrc] == NULL )
+        {
+            if( hCT != NULL )
+                GDALDestroyColorTable( hCT );
+            return NULL;
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Check that there's at least one raster band                     */
+/* -------------------------------------------------------------------- */
+        if ( GDALGetRasterCount(pahSrcDS[iSrc]) == 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Input file %s has no raster bands.", GDALGetDescription(pahSrcDS[iSrc]) );
+            if( hCT != NULL )
+                GDALDestroyColorTable( hCT );
+            return NULL;
+        }
+
+        if( eDT == GDT_Unknown )
+            eDT = GDALGetRasterDataType(GDALGetRasterBand(pahSrcDS[iSrc],1));
+
+/* -------------------------------------------------------------------- */
+/*      If we are processing the first file, and it has a color         */
+/*      table, then we will copy it to the destination file.            */
+/* -------------------------------------------------------------------- */
+        if( iSrc == 0 )
+        {
+            nDstBandCount = GDALGetRasterCount(pahSrcDS[iSrc]);
+            hCT = GDALGetRasterColorTable( GDALGetRasterBand(pahSrcDS[iSrc],1) );
+            if( hCT != NULL )
+            {
+                hCT = GDALCloneColorTable( hCT );
+                if( !psOptions->bQuiet )
+                    printf( "Copying color table from %s to new file.\n",
+                            GDALGetDescription(pahSrcDS[iSrc]) );
+            }
+
+            for(int iBand = 0; iBand < nDstBandCount; iBand++)
+            {
+                apeColorInterpretations.push_back(
+                    GDALGetRasterColorInterpretation(GDALGetRasterBand(pahSrcDS[iSrc],iBand+1)) );
+            }
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Get the sourcesrs from the dataset, if not set already.         */
+/* -------------------------------------------------------------------- */
+        if( pszThisSourceSRS == NULL )
+        {
+            const char *pszMethod = CSLFetchNameValue( papszTO, "METHOD" );
+
+            if( GDALGetProjectionRef( pahSrcDS[iSrc] ) != NULL
+                && strlen(GDALGetProjectionRef( pahSrcDS[iSrc] )) > 0
+                && (pszMethod == NULL || EQUAL(pszMethod,"GEOTRANSFORM")) )
+                pszThisSourceSRS = GDALGetProjectionRef( pahSrcDS[iSrc] );
+
+            else if( GDALGetGCPProjection( pahSrcDS[iSrc] ) != NULL
+                     && strlen(GDALGetGCPProjection(pahSrcDS[iSrc])) > 0
+                     && GDALGetGCPCount( pahSrcDS[iSrc] ) > 1
+                     && (pszMethod == NULL || STARTS_WITH_CI(pszMethod, "GCP_")) )
+                pszThisSourceSRS = GDALGetGCPProjection( pahSrcDS[iSrc] );
+            else if( pszMethod != NULL && EQUAL(pszMethod,"RPC") )
+                pszThisSourceSRS = SRS_WKT_WGS84;
+            else
+                pszThisSourceSRS = "";
+        }
+
+        if( osThisTargetSRS.size() == 0 )
+            osThisTargetSRS = pszThisSourceSRS;
+
+/* -------------------------------------------------------------------- */
+/*      Create a transformation object from the source to               */
+/*      destination coordinate system.                                  */
+/* -------------------------------------------------------------------- */
+        hTransformArg =
+            GDALCreateGenImgProjTransformer2( pahSrcDS[iSrc], NULL, papszTO );
+
+        if( hTransformArg == NULL )
+        {
+            if( hCT != NULL )
+                GDALDestroyColorTable( hCT );
+            return NULL;
+        }
+
+        GDALTransformerInfo* psInfo = (GDALTransformerInfo*)hTransformArg;
+
+/* -------------------------------------------------------------------- */
+/*      Get approximate output definition.                              */
+/* -------------------------------------------------------------------- */
+        if( bNeedsSuggestedWarpOutput )
+        {
+            double adfThisGeoTransform[6];
+            double adfExtent[4];
+            int    nThisPixels, nThisLines;
+
+            if ( GDALSuggestedWarpOutput2( pahSrcDS[iSrc],
+                                        psInfo->pfnTransform, hTransformArg,
+                                        adfThisGeoTransform,
+                                        &nThisPixels, &nThisLines,
+                                        adfExtent, 0 ) != CE_None )
+            {
+                if( hCT != NULL )
+                    GDALDestroyColorTable( hCT );
+                GDALDestroyGenImgProjTransformer( hTransformArg );
+                return NULL;
+            }
+
+            if ( CPLGetConfigOption( "CHECK_WITH_INVERT_PROJ", NULL ) == NULL )
+            {
+                double MinX = adfExtent[0];
+                double MaxX = adfExtent[2];
+                double MaxY = adfExtent[3];
+                double MinY = adfExtent[1];
+                int bSuccess = TRUE;
+
+                /* Check that the edges of the target image are in the validity area */
+                /* of the target projection */
+    #define N_STEPS 20
+                int i,j;
+                for(i=0;i<=N_STEPS && bSuccess;i++)
+                {
+                    for(j=0;j<=N_STEPS && bSuccess;j++)
+                    {
+                        double dfRatioI = i * 1.0 / N_STEPS;
+                        double dfRatioJ = j * 1.0 / N_STEPS;
+                        double expected_x = (1 - dfRatioI) * MinX + dfRatioI * MaxX;
+                        double expected_y = (1 - dfRatioJ) * MinY + dfRatioJ * MaxY;
+                        double x = expected_x;
+                        double y = expected_y;
+                        double z = 0;
+                        /* Target SRS coordinates to source image pixel coordinates */
+                        if (!psInfo->pfnTransform(hTransformArg, TRUE, 1, &x, &y, &z, &bSuccess) || !bSuccess)
+                            bSuccess = FALSE;
+                        /* Source image pixel coordinates to target SRS coordinates */
+                        if (!psInfo->pfnTransform(hTransformArg, FALSE, 1, &x, &y, &z, &bSuccess) || !bSuccess)
+                            bSuccess = FALSE;
+                        if (fabs(x - expected_x) > (MaxX - MinX) / nThisPixels ||
+                            fabs(y - expected_y) > (MaxY - MinY) / nThisLines)
+                            bSuccess = FALSE;
+                    }
+                }
+
+                /* If not, retry with CHECK_WITH_INVERT_PROJ=TRUE that forces ogrct.cpp */
+                /* to check the consistency of each requested projection result with the */
+                /* invert projection */
+                if (!bSuccess)
+                {
+                    CPLSetThreadLocalConfigOption( "CHECK_WITH_INVERT_PROJ", "TRUE" );
+                    CPLDebug("WARP", "Recompute out extent with CHECK_WITH_INVERT_PROJ=TRUE");
+
+                    CPLErr eErr = GDALSuggestedWarpOutput2( pahSrcDS[iSrc],
+                                        psInfo->pfnTransform, hTransformArg,
+                                        adfThisGeoTransform,
+                                        &nThisPixels, &nThisLines,
+                                        adfExtent, 0 );
+                    CPLSetThreadLocalConfigOption( "CHECK_WITH_INVERT_PROJ", NULL );
+                    if( eErr != CE_None )
+                    {
+                        if( hCT != NULL )
+                            GDALDestroyColorTable( hCT );
+                        GDALDestroyGenImgProjTransformer( hTransformArg );
+                        return NULL;
+                    }
+                }
+            }
+
+    /* -------------------------------------------------------------------- */
+    /*      Expand the working bounds to include this region, ensure the    */
+    /*      working resolution is no more than this resolution.             */
+    /* -------------------------------------------------------------------- */
+            if( dfWrkMaxX == 0.0 && dfWrkMinX == 0.0 )
+            {
+                dfWrkMinX = adfExtent[0];
+                dfWrkMaxX = adfExtent[2];
+                dfWrkMaxY = adfExtent[3];
+                dfWrkMinY = adfExtent[1];
+                dfWrkResX = adfThisGeoTransform[1];
+                dfWrkResY = ABS(adfThisGeoTransform[5]);
+            }
+            else
+            {
+                dfWrkMinX = MIN(dfWrkMinX,adfExtent[0]);
+                dfWrkMaxX = MAX(dfWrkMaxX,adfExtent[2]);
+                dfWrkMaxY = MAX(dfWrkMaxY,adfExtent[3]);
+                dfWrkMinY = MIN(dfWrkMinY,adfExtent[1]);
+                dfWrkResX = MIN(dfWrkResX,adfThisGeoTransform[1]);
+                dfWrkResY = MIN(dfWrkResY,ABS(adfThisGeoTransform[5]));
+            }
+        }
+
+        if (nSrcCount == 1)
+        {
+            *phTransformArg = hTransformArg;
+        }
+        else
+        {
+            GDALDestroyGenImgProjTransformer( hTransformArg );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Did we have any usable sources?                                 */
+/* -------------------------------------------------------------------- */
+    if( nDstBandCount == 0 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "No usable source images." );
+        if( hCT != NULL )
+            GDALDestroyColorTable( hCT );
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Turn the suggested region into a geotransform and suggested     */
+/*      number of pixels and lines.                                     */
+/* -------------------------------------------------------------------- */
+    double adfDstGeoTransform[6] = { 0, 0, 0, 0, 0, 0 };
+    int nPixels = 0, nLines = 0;
+
+    if( bNeedsSuggestedWarpOutput )
+    {
+        adfDstGeoTransform[0] = dfWrkMinX;
+        adfDstGeoTransform[1] = dfWrkResX;
+        adfDstGeoTransform[2] = 0.0;
+        adfDstGeoTransform[3] = dfWrkMaxY;
+        adfDstGeoTransform[4] = 0.0;
+        adfDstGeoTransform[5] = -1 * dfWrkResY;
+
+        nPixels = (int) ((dfWrkMaxX - dfWrkMinX) / dfWrkResX + 0.5);
+        nLines = (int) ((dfWrkMaxY - dfWrkMinY) / dfWrkResY + 0.5);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Did the user override some parameters?                          */
+/* -------------------------------------------------------------------- */
+    if( psOptions->dfXRes != 0.0 && psOptions->dfYRes != 0.0 )
+    {
+        if( psOptions->dfMinX == 0.0 && psOptions->dfMinY == 0.0 && psOptions->dfMaxX == 0.0 && psOptions->dfMaxY == 0.0 )
+        {
+            psOptions->dfMinX = adfDstGeoTransform[0];
+            psOptions->dfMaxX = adfDstGeoTransform[0] + adfDstGeoTransform[1] * nPixels;
+            psOptions->dfMaxY = adfDstGeoTransform[3];
+            psOptions->dfMinY = adfDstGeoTransform[3] + adfDstGeoTransform[5] * nLines;
+        }
+
+        if ( psOptions->bTargetAlignedPixels )
+        {
+            psOptions->dfMinX = floor(psOptions->dfMinX / psOptions->dfXRes) * psOptions->dfXRes;
+            psOptions->dfMaxX = ceil(psOptions->dfMaxX / psOptions->dfXRes) * psOptions->dfXRes;
+            psOptions->dfMinY = floor(psOptions->dfMinY / psOptions->dfYRes) * psOptions->dfYRes;
+            psOptions->dfMaxY = ceil(psOptions->dfMaxY / psOptions->dfYRes) * psOptions->dfYRes;
+        }
+
+        nPixels = (int) ((psOptions->dfMaxX - psOptions->dfMinX + (psOptions->dfXRes/2.0)) / psOptions->dfXRes);
+        nLines = (int) ((psOptions->dfMaxY - psOptions->dfMinY + (psOptions->dfYRes/2.0)) / psOptions->dfYRes);
+        adfDstGeoTransform[0] = psOptions->dfMinX;
+        adfDstGeoTransform[3] = psOptions->dfMaxY;
+        adfDstGeoTransform[1] = psOptions->dfXRes;
+        adfDstGeoTransform[5] = -psOptions->dfYRes;
+    }
+
+    else if( psOptions->nForcePixels != 0 && psOptions->nForceLines != 0 )
+    {
+        if( psOptions->dfMinX == 0.0 && psOptions->dfMinY == 0.0 && psOptions->dfMaxX == 0.0 && psOptions->dfMaxY == 0.0 )
+        {
+            psOptions->dfMinX = dfWrkMinX;
+            psOptions->dfMaxX = dfWrkMaxX;
+            psOptions->dfMaxY = dfWrkMaxY;
+            psOptions->dfMinY = dfWrkMinY;
+        }
+
+        psOptions->dfXRes = (psOptions->dfMaxX - psOptions->dfMinX) / psOptions->nForcePixels;
+        psOptions->dfYRes = (psOptions->dfMaxY - psOptions->dfMinY) / psOptions->nForceLines;
+
+        adfDstGeoTransform[0] = psOptions->dfMinX;
+        adfDstGeoTransform[3] = psOptions->dfMaxY;
+        adfDstGeoTransform[1] = psOptions->dfXRes;
+        adfDstGeoTransform[5] = -psOptions->dfYRes;
+
+        nPixels = psOptions->nForcePixels;
+        nLines = psOptions->nForceLines;
+    }
+
+    else if( psOptions->nForcePixels != 0 )
+    {
+        if( psOptions->dfMinX == 0.0 && psOptions->dfMinY == 0.0 && psOptions->dfMaxX == 0.0 && psOptions->dfMaxY == 0.0 )
+        {
+            psOptions->dfMinX = dfWrkMinX;
+            psOptions->dfMaxX = dfWrkMaxX;
+            psOptions->dfMaxY = dfWrkMaxY;
+            psOptions->dfMinY = dfWrkMinY;
+        }
+
+        psOptions->dfXRes = (psOptions->dfMaxX - psOptions->dfMinX) / psOptions->nForcePixels;
+        psOptions->dfYRes = psOptions->dfXRes;
+
+        adfDstGeoTransform[0] = psOptions->dfMinX;
+        adfDstGeoTransform[3] = psOptions->dfMaxY;
+        adfDstGeoTransform[1] = psOptions->dfXRes;
+        adfDstGeoTransform[5] = -psOptions->dfYRes;
+
+        nPixels = psOptions->nForcePixels;
+        nLines = (int) ((psOptions->dfMaxY - psOptions->dfMinY + (psOptions->dfYRes/2.0)) / psOptions->dfYRes);
+    }
+
+    else if( psOptions->nForceLines != 0 )
+    {
+        if( psOptions->dfMinX == 0.0 && psOptions->dfMinY == 0.0 && psOptions->dfMaxX == 0.0 && psOptions->dfMaxY == 0.0 )
+        {
+            psOptions->dfMinX = dfWrkMinX;
+            psOptions->dfMaxX = dfWrkMaxX;
+            psOptions->dfMaxY = dfWrkMaxY;
+            psOptions->dfMinY = dfWrkMinY;
+        }
+
+        psOptions->dfYRes = (psOptions->dfMaxY - psOptions->dfMinY) / psOptions->nForceLines;
+        psOptions->dfXRes = psOptions->dfYRes;
+
+        adfDstGeoTransform[0] = psOptions->dfMinX;
+        adfDstGeoTransform[3] = psOptions->dfMaxY;
+        adfDstGeoTransform[1] = psOptions->dfXRes;
+        adfDstGeoTransform[5] = -psOptions->dfYRes;
+
+        nPixels = (int) ((psOptions->dfMaxX - psOptions->dfMinX + (psOptions->dfXRes/2.0)) / psOptions->dfXRes);
+        nLines = psOptions->nForceLines;
+    }
+
+    else if( psOptions->dfMinX != 0.0 || psOptions->dfMinY != 0.0 || psOptions->dfMaxX != 0.0 || psOptions->dfMaxY != 0.0 )
+    {
+        psOptions->dfXRes = adfDstGeoTransform[1];
+        psOptions->dfYRes = fabs(adfDstGeoTransform[5]);
+
+        nPixels = (int) ((psOptions->dfMaxX - psOptions->dfMinX + (psOptions->dfXRes/2.0)) / psOptions->dfXRes);
+        nLines = (int) ((psOptions->dfMaxY - psOptions->dfMinY + (psOptions->dfYRes/2.0)) / psOptions->dfYRes);
+
+        psOptions->dfXRes = (psOptions->dfMaxX - psOptions->dfMinX) / nPixels;
+        psOptions->dfYRes = (psOptions->dfMaxY - psOptions->dfMinY) / nLines;
+
+        adfDstGeoTransform[0] = psOptions->dfMinX;
+        adfDstGeoTransform[3] = psOptions->dfMaxY;
+        adfDstGeoTransform[1] = psOptions->dfXRes;
+        adfDstGeoTransform[5] = -psOptions->dfYRes;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Do we want to generate an alpha band in the output file?        */
+/* -------------------------------------------------------------------- */
+    if( psOptions->bEnableSrcAlpha )
+        nDstBandCount--;
+
+    if( psOptions->bEnableDstAlpha )
+        nDstBandCount++;
+
+/* -------------------------------------------------------------------- */
+/*      Create the output file.                                         */
+/* -------------------------------------------------------------------- */
+    if( !psOptions->bQuiet )
+        printf( "Creating output file that is %dP x %dL.\n", nPixels, nLines );
+
+    hDstDS = GDALCreate( hDriver, pszFilename, nPixels, nLines,
+                         nDstBandCount, eDT, *ppapszCreateOptions );
+
+    if( hDstDS == NULL )
+    {
+        if( hCT != NULL )
+            GDALDestroyColorTable( hCT );
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Write out the projection definition.                            */
+/* -------------------------------------------------------------------- */
+    const char *pszDstMethod = CSLFetchNameValue(papszTO,"DST_METHOD");
+    if( pszDstMethod == NULL || !EQUAL(pszDstMethod, "NO_GEOTRANSFORM") )
+    {
+        if( GDALSetProjection( hDstDS, osThisTargetSRS.c_str() ) == CE_Failure ||
+            GDALSetGeoTransform( hDstDS, adfDstGeoTransform ) == CE_Failure )
+        {
+            if( hCT != NULL )
+                GDALDestroyColorTable( hCT );
+            return NULL;
+        }
+    }
+    else
+    {
+        adfDstGeoTransform[0] = 0.0;
+        adfDstGeoTransform[3] = 0.0;
+        adfDstGeoTransform[5] = fabs(adfDstGeoTransform[5]);
+    }
+
+    if (*phTransformArg != NULL)
+        GDALSetGenImgProjTransformerDstGeoTransform( *phTransformArg, adfDstGeoTransform);
+
+/* -------------------------------------------------------------------- */
+/*      Try to set color interpretation of source bands to target       */
+/*      dataset.                                                        */
+/*      FIXME? We should likely do that for other drivers than VRT      */
+/*      but it might create spurious .aux.xml files (at least with HFA, */
+/*      and netCDF)                                                     */
+/* -------------------------------------------------------------------- */
+    if( bVRT || bSetColorInterpretation )
+    {
+        int nBandsToCopy = (int)apeColorInterpretations.size();
+        if ( psOptions->bEnableSrcAlpha )
+            nBandsToCopy --;
+        for(int iBand = 0; iBand < nBandsToCopy; iBand++)
+        {
+            GDALSetRasterColorInterpretation(
+                GDALGetRasterBand( hDstDS, iBand + 1 ),
+                apeColorInterpretations[iBand] );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Try to set color interpretation of output file alpha band.      */
+/* -------------------------------------------------------------------- */
+    if( psOptions->bEnableDstAlpha )
+    {
+        GDALSetRasterColorInterpretation(
+            GDALGetRasterBand( hDstDS, nDstBandCount ),
+            GCI_AlphaBand );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Copy the color table, if required.                              */
+/* -------------------------------------------------------------------- */
+    if( hCT != NULL )
+    {
+        GDALSetRasterColorTable( GDALGetRasterBand(hDstDS,1), hCT );
+        GDALDestroyColorTable( hCT );
+    }
+
+    return hDstDS;
+}
+
+/************************************************************************/
+/*                      GeoTransform_Transformer()                      */
+/*                                                                      */
+/*      Convert points from georef coordinates to pixel/line based      */
+/*      on a geotransform.                                              */
+/************************************************************************/
+
+class CutlineTransformer : public OGRCoordinateTransformation
+{
+public:
+
+    void         *hSrcImageTransformer;
+
+    virtual OGRSpatialReference *GetSourceCS() { return NULL; }
+    virtual OGRSpatialReference *GetTargetCS() { return NULL; }
+
+    virtual int Transform( int nCount,
+                           double *x, double *y, double *z = NULL ) {
+        int nResult;
+
+        int *pabSuccess = (int *) CPLCalloc(sizeof(int),nCount);
+        nResult = TransformEx( nCount, x, y, z, pabSuccess );
+        CPLFree( pabSuccess );
+
+        return nResult;
+    }
+
+    virtual int TransformEx( int nCount,
+                             double *x, double *y, double *z = NULL,
+                             int *pabSuccess = NULL ) {
+        return GDALGenImgProjTransform( hSrcImageTransformer, TRUE,
+                                        nCount, x, y, z, pabSuccess );
+    }
+};
+
+static
+double GetMaximumSegmentLength( OGRGeometry* poGeom )
+{
+    switch( wkbFlatten(poGeom->getGeometryType()) )
+    {
+        case wkbLineString:
+        {
+            OGRLineString* poLS = static_cast<OGRLineString*>(poGeom);
+            double dfMaxSquaredLength = 0.0;
+            for(int i=0; i<poLS->getNumPoints()-1;i++)
+            {
+                double dfDeltaX = poLS->getX(i+1) - poLS->getX(i);
+                double dfDeltaY = poLS->getY(i+1) - poLS->getY(i);
+                double dfSquaredLength = dfDeltaX * dfDeltaX + dfDeltaY * dfDeltaY;
+                dfMaxSquaredLength = std::max( dfMaxSquaredLength, dfSquaredLength );
+            }
+            return sqrt(dfMaxSquaredLength);
+        }
+
+        case wkbPolygon:
+        {
+            OGRPolygon* poPoly = static_cast<OGRPolygon*>(poGeom);
+            double dfMaxLength = GetMaximumSegmentLength( poPoly->getExteriorRing() );
+            for(int i=0; i<poPoly->getNumInteriorRings();i++)
+            {
+                dfMaxLength = std::max( dfMaxLength,
+                    GetMaximumSegmentLength( poPoly->getInteriorRing(i) ) );
+            }
+            return dfMaxLength;
+        }
+
+        case wkbMultiPolygon:
+        {
+            OGRMultiPolygon* poMP = static_cast<OGRMultiPolygon*>(poGeom);
+            double dfMaxLength = 0.0;
+            for(int i=0; i<poMP->getNumGeometries();i++)
+            {
+                dfMaxLength = std::max( dfMaxLength,
+                    GetMaximumSegmentLength( poMP->getGeometryRef(i) ) );
+            }
+            return dfMaxLength;
+        }
+
+        default:
+            CPLAssert(0);
+            return 0.0;
+    }
+}
+
+/************************************************************************/
+/*                      TransformCutlineToSource()                      */
+/*                                                                      */
+/*      Transform cutline from its SRS to source pixel/line coordinates.*/
+/************************************************************************/
+static CPLErr
+TransformCutlineToSource( GDALDatasetH hSrcDS, void *hCutline,
+                          char ***ppapszWarpOptions, char **papszTO_In )
+
+{
+    OGRGeometryH hMultiPolygon = OGR_G_Clone( (OGRGeometryH) hCutline );
+    char **papszTO = CSLDuplicate( papszTO_In );
+
+/* -------------------------------------------------------------------- */
+/*      Checkout that if there's a cutline SRS, there's also a raster   */
+/*      one.                                                            */
+/* -------------------------------------------------------------------- */
+    OGRSpatialReferenceH  hRasterSRS = NULL;
+    const char *pszProjection = CSLFetchNameValue( papszTO, "SRC_SRS" );
+    if( pszProjection == NULL )
+    {
+        char** papszMD;
+        if( GDALGetProjectionRef( hSrcDS ) != NULL
+            && strlen(GDALGetProjectionRef( hSrcDS )) > 0 )
+            pszProjection = GDALGetProjectionRef( hSrcDS );
+        else if( GDALGetGCPProjection( hSrcDS ) != NULL
+            && strlen(GDALGetGCPProjection( hSrcDS )) > 0 )
+            pszProjection = GDALGetGCPProjection( hSrcDS );
+        else if( GDALGetMetadata( hSrcDS, "RPC" ) != NULL )
+            pszProjection = SRS_WKT_WGS84;
+        else if( (papszMD = GDALGetMetadata( hSrcDS, "GEOLOCATION" )) != NULL )
+            pszProjection = CSLFetchNameValue( papszMD, "SRS" );
+    }
+
+    if( pszProjection != NULL )
+    {
+        hRasterSRS = OSRNewSpatialReference(NULL);
+        if( OSRImportFromWkt( hRasterSRS, (char **)&pszProjection ) != OGRERR_NONE )
+        {
+            OSRDestroySpatialReference(hRasterSRS);
+            hRasterSRS = NULL;
+        }
+    }
+
+    OGRSpatialReferenceH hCutlineSRS = OGR_G_GetSpatialReference( hMultiPolygon );
+    if( hRasterSRS != NULL && hCutlineSRS != NULL )
+    {
+        /* OK, we will reproject */
+    }
+    else if( hRasterSRS != NULL && hCutlineSRS == NULL )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                "the source raster dataset has a SRS, but the cutline features\n"
+                "not.  We assume that the cutline coordinates are expressed in the destination SRS.\n"
+                "If not, cutline results may be incorrect.");
+    }
+    else if( hRasterSRS == NULL && hCutlineSRS != NULL )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                "the input vector layer has a SRS, but the source raster dataset does not.\n"
+                "Cutline results may be incorrect.");
+    }
+
+    if( hRasterSRS != NULL )
+        OSRDestroySpatialReference(hRasterSRS);
+
+/* -------------------------------------------------------------------- */
+/*      Extract the cutline SRS WKT.                                    */
+/* -------------------------------------------------------------------- */
+    if( hCutlineSRS != NULL )
+    {
+        char *pszCutlineSRS_WKT = NULL;
+
+        OSRExportToWkt( hCutlineSRS, &pszCutlineSRS_WKT );
+        papszTO = CSLSetNameValue( papszTO, "DST_SRS", pszCutlineSRS_WKT );
+        CPLFree( pszCutlineSRS_WKT );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      It may be unwise to let the mask geometry be re-wrapped by      */
+/*      the CENTER_LONG machinery as this can easily screw up world     */
+/*      spanning masks and invert the mask topology.                    */
+/* -------------------------------------------------------------------- */
+    papszTO = CSLSetNameValue( papszTO, "INSERT_CENTER_LONG", "FALSE" );
+
+/* -------------------------------------------------------------------- */
+/*      Transform the geometry to pixel/line coordinates.               */
+/* -------------------------------------------------------------------- */
+    CutlineTransformer oTransformer;
+
+    /* The cutline transformer will *invert* the hSrcImageTransformer */
+    /* so it will convert from the cutline SRS to the source pixel/line */
+    /* coordinates */
+    oTransformer.hSrcImageTransformer =
+        GDALCreateGenImgProjTransformer2( hSrcDS, NULL, papszTO );
+
+    CSLDestroy( papszTO );
+
+    if( oTransformer.hSrcImageTransformer == NULL )
+    {
+        OGR_G_DestroyGeometry( hMultiPolygon );
+        return CE_Failure;
+    }
+
+    // Some transforms like RPC can transform a valid geometry into an invalid
+    // one if the node density of the input geometry isn't sufficient before
+    // reprojection. So after an initial reprojection, we check that the
+    // maximum length of a segment is no longer than 1 pixel, and if not,
+    // we densify the input geometry before doing a new reprojection
+    const double dfMaxLengthInSpatUnits = GetMaximumSegmentLength(
+                reinterpret_cast<OGRGeometry*>(hMultiPolygon) );
+    OGRErr eErr = OGR_G_Transform( hMultiPolygon,
+                     (OGRCoordinateTransformationH) &oTransformer );
+    const double dfInitialMaxLengthInPixels = GetMaximumSegmentLength(
+                            reinterpret_cast<OGRGeometry*>(hMultiPolygon) );
+
+    CPLPushErrorHandler(CPLQuietErrorHandler);
+    const bool bWasValidInitialy = OGR_G_IsValid(hMultiPolygon) != FALSE;
+    CPLPopErrorHandler();
+    bool bDensify = false;
+    if( eErr == OGRERR_NONE && dfInitialMaxLengthInPixels > 1.0 )
+    {
+        const char* pszDensifyCutline = CPLGetConfigOption("GDALWARP_DENSIFY_CUTLINE", "YES");
+        if( EQUAL(pszDensifyCutline, "ONLY_IF_INVALID") )
+        {
+            bDensify = ( OGRGeometryFactory::haveGEOS() && !bWasValidInitialy );
+        }
+        else
+            bDensify = CPLTestBool(pszDensifyCutline);
+    }
+    if( bDensify )
+    {
+        CPLDebug("WARP", "Cutline maximum segment size was %.0f pixel after reprojection to source coordinates.",
+                 dfInitialMaxLengthInPixels);
+
+        // Densify and reproject with the aim of having a 1 pixel density
+        double dfSegmentSize = dfMaxLengthInSpatUnits / dfInitialMaxLengthInPixels;
+        for(int i=0;i<10;i++)
+        {
+            OGR_G_DestroyGeometry( hMultiPolygon );
+            hMultiPolygon = OGR_G_Clone( (OGRGeometryH) hCutline );
+            OGR_G_Segmentize(hMultiPolygon, dfSegmentSize);
+            eErr = OGR_G_Transform( hMultiPolygon,
+                        (OGRCoordinateTransformationH) &oTransformer );
+            if( eErr == OGRERR_NONE )
+            {
+                const double dfMaxLengthInPixels = GetMaximumSegmentLength(
+                                    reinterpret_cast<OGRGeometry*>(hMultiPolygon) );
+                if( bWasValidInitialy )
+                {
+                    // In some cases, the densification itself results in a reprojected
+                    // invalid polygon due to the non-linearity of RPC DEM transformation,
+                    // so in those cases, try a less dense cutline
+                    CPLPushErrorHandler(CPLQuietErrorHandler);
+                    const bool bIsValid = OGR_G_IsValid(hMultiPolygon) != FALSE;
+                    CPLPopErrorHandler();
+                    if( !bIsValid )
+                    {
+                        CPLDebug("WARP", "After densification, cutline maximum segment size is now %.0f pixel, "
+                                 "but cutline is invalid. So trying a less dense cutline.",
+                                 dfMaxLengthInPixels);
+                        dfSegmentSize *= 2;
+                        continue;
+                    }
+                }
+                CPLDebug("WARP", "After densification, cutline maximum segment size is now %.0f pixel.",
+                        dfMaxLengthInPixels);
+            }
+            break;
+        }
+    }
+
+    GDALDestroyGenImgProjTransformer( oTransformer.hSrcImageTransformer );
+
+    if( eErr == OGRERR_FAILURE )
+    {
+        if( CPLTestBool(CPLGetConfigOption("GDALWARP_IGNORE_BAD_CUTLINE", "NO")) )
+            CPLError(CE_Warning, CPLE_AppDefined, "Cutline transformation failed");
+        else
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Cutline transformation failed");
+            OGR_G_DestroyGeometry( hMultiPolygon );
+            return CE_Failure;
+        }
+    }
+    else if( OGRGeometryFactory::haveGEOS() && !OGR_G_IsValid(hMultiPolygon) )
+    {
+        char *pszWKT = NULL;
+        OGR_G_ExportToWkt( hMultiPolygon, &pszWKT );
+        CPLDebug("GDALWARP", "WKT = \"%s\"", pszWKT ? pszWKT : "(null)");
+        //fprintf(stderr, "WKT = \"%s\"\n", pszWKT ? pszWKT : "(null)");
+        CPLFree( pszWKT );
+
+        if( CPLTestBool(CPLGetConfigOption("GDALWARP_IGNORE_BAD_CUTLINE", "NO")) )
+            CPLError(CE_Warning, CPLE_AppDefined, "Cutline is not valid after transformation");
+        else
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Cutline is not valid after transformation");
+            OGR_G_DestroyGeometry( hMultiPolygon );
+            return CE_Failure;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Convert aggregate geometry into WKT.                            */
+/* -------------------------------------------------------------------- */
+    char *pszWKT = NULL;
+
+    OGR_G_ExportToWkt( hMultiPolygon, &pszWKT );
+    //fprintf(stderr, "WKT = \"%s\"\n", pszWKT ? pszWKT : "(null)");
+    OGR_G_DestroyGeometry( hMultiPolygon );
+
+    *ppapszWarpOptions = CSLSetNameValue( *ppapszWarpOptions,
+                                          "CUTLINE", pszWKT );
+    CPLFree( pszWKT );
+    return CE_None;
+}
+
+static void
+RemoveConflictingMetadata( GDALMajorObjectH hObj, char **papszMetadata,
+                           const char *pszValueConflict )
+{
+    if ( hObj == NULL ) return;
+
+    char *pszKey = NULL;
+    const char *pszValueRef;
+    const char *pszValueComp;
+    char ** papszMetadataRef = CSLDuplicate( papszMetadata );
+    int nCount = CSLCount( papszMetadataRef );
+
+    for( int i = 0; i < nCount; i++ )
+    {
+        pszKey = NULL;
+        pszValueRef = CPLParseNameValue( papszMetadataRef[i], &pszKey );
+        if( pszKey != NULL )
+        {
+            pszValueComp = GDALGetMetadataItem( hObj, pszKey, NULL );
+            if ( ( pszValueRef == NULL || pszValueComp == NULL ||
+                ! EQUAL( pszValueRef, pszValueComp ) ) &&
+                ( pszValueComp == NULL ||
+                ! EQUAL( pszValueComp, pszValueConflict ) ) )
+            {
+                if( STARTS_WITH(pszKey, "STATISTICS_") )
+                    GDALSetMetadataItem( hObj, pszKey, NULL, NULL );
+                else
+                    GDALSetMetadataItem( hObj, pszKey, pszValueConflict, NULL );
+            }
+            CPLFree( pszKey );
+        }
+    }
+
+    CSLDestroy( papszMetadataRef );
+}
+
+/************************************************************************/
+/*                             SanitizeSRS                              */
+/************************************************************************/
+
+static char *SanitizeSRS( const char *pszUserInput )
+
+{
+    OGRSpatialReferenceH hSRS;
+    char *pszResult = NULL;
+
+    CPLErrorReset();
+
+    hSRS = OSRNewSpatialReference( NULL );
+    if( OSRSetFromUserInput( hSRS, pszUserInput ) == OGRERR_NONE )
+        OSRExportToWkt( hSRS, &pszResult );
+    else
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Translating source or target SRS failed:\n%s",
+                  pszUserInput );
+    }
+
+    OSRDestroySpatialReference( hSRS );
+
+    return pszResult;
+}
+
+/************************************************************************/
+/*                             GDALWarpAppOptionsNew()                  */
+/************************************************************************/
+
+/**
+ * Allocates a GDALWarpAppOptions struct.
+ *
+ * @param papszArgv NULL terminated list of options (potentially including filename and open options too), or NULL.
+ *                  The accepted options are the ones of the <a href="gdal_warp.html">gdalwarp</a> utility.
+ * @param psOptionsForBinary (output) may be NULL (and should generally be NULL),
+ *                           otherwise (gdal_translate_bin.cpp use case) must be allocated with
+ *                           GDALWarpAppOptionsForBinaryNew() prior to this function. Will be
+ *                           filled with potentially present filename, open options,...
+ * @return pointer to the allocated GDALWarpAppOptions struct. Must be freed with GDALWarpAppOptionsFree().
+ *
+ * @since GDAL 2.1
+ */
+
+GDALWarpAppOptions *GDALWarpAppOptionsNew(char** papszArgv,
+                                          GDALWarpAppOptionsForBinary* psOptionsForBinary)
+{
+    GDALWarpAppOptions *psOptions = (GDALWarpAppOptions *)CPLCalloc(1, sizeof(GDALWarpAppOptions));
+
+    psOptions->dfMinX = 0.0;
+    psOptions->dfMinY = 0.0;
+    psOptions->dfMaxX = 0.0;
+    psOptions->dfMaxY = 0.0;
+    psOptions->dfXRes = 0.0;
+    psOptions->dfYRes = 0.0;
+    psOptions->bTargetAlignedPixels = FALSE;
+    psOptions->nForcePixels = 0;
+    psOptions->nForceLines = 0;
+    psOptions->bQuiet = TRUE;
+    psOptions->pfnProgress = GDALDummyProgress;
+    psOptions->pProgressData = NULL;
+    psOptions->bEnableDstAlpha = FALSE;
+    psOptions->bEnableSrcAlpha = FALSE;
+    psOptions->pszFormat = CPLStrdup("GTiff");
+    psOptions->bCreateOutput = FALSE;
+    psOptions->papszWarpOptions = NULL;
+    psOptions->dfErrorThreshold = -1;
+    psOptions->dfWarpMemoryLimit = 0.0;
+    psOptions->papszCreateOptions = NULL;
+    psOptions->eOutputType = GDT_Unknown;
+    psOptions->eWorkingType = GDT_Unknown;
+    psOptions->eResampleAlg = GRA_NearestNeighbour;
+    psOptions->pszSrcNodata = NULL;
+    psOptions->pszDstNodata = NULL;
+    psOptions->bMulti = FALSE;
+    psOptions->papszTO = NULL;
+    psOptions->pszCutlineDSName = NULL;
+    psOptions->pszCLayer = NULL;
+    psOptions->pszCWHERE = NULL;
+    psOptions->pszCSQL = NULL;
+    psOptions->bCropToCutline = FALSE;
+    psOptions->bCopyMetadata = TRUE;
+    psOptions->bCopyBandInfo = TRUE;
+    psOptions->pszMDConflictValue = CPLStrdup("*");
+    psOptions->bSetColorInterpretation = FALSE;
+    psOptions->nOvLevel = -2;
+
+/* -------------------------------------------------------------------- */
+/*      Parse arguments.                                                */
+/* -------------------------------------------------------------------- */
+    int argc = CSLCount(papszArgv);
+    for( int i = 0; i < argc; i++ )
+    {
+        if( EQUAL(papszArgv[i],"-tps") || EQUAL(papszArgv[i],"-rpc") || EQUAL(papszArgv[i],"-geoloc")  )
+        {
+            const char* pszMethod = CSLFetchNameValue(psOptions->papszTO, "METHOD");
+            if (pszMethod)
+                CPLError(CE_Warning, CPLE_IllegalArg,
+                         "Warning: only one METHOD can be used. Method %s is already defined.",
+                        pszMethod);
+            const char* pszMAX_GCP_ORDER = CSLFetchNameValue(psOptions->papszTO, "MAX_GCP_ORDER");
+            if (pszMAX_GCP_ORDER)
+                CPLError(CE_Warning, CPLE_IllegalArg,
+                         "Warning: only one METHOD can be used. -order %s option was specified, so it is likely that GCP_POLYNOMIAL was implied.",
+                        pszMAX_GCP_ORDER);
+        } /* do not add 'else' in front of the next line */
+
+        if( EQUAL(papszArgv[i],"-co") && i+1 < argc )
+        {
+            psOptions->papszCreateOptions = CSLAddString( psOptions->papszCreateOptions, papszArgv[++i] );
+            psOptions->bCreateOutput = TRUE;
+        }
+        else if( EQUAL(papszArgv[i],"-wo") && i+1 < argc )
+        {
+            psOptions->papszWarpOptions = CSLAddString( psOptions->papszWarpOptions, papszArgv[++i] );
+        }
+        else if( EQUAL(papszArgv[i],"-multi") )
+        {
+            psOptions->bMulti = TRUE;
+        }
+        else if( EQUAL(papszArgv[i],"-q") || EQUAL(papszArgv[i],"-quiet"))
+        {
+            if( psOptionsForBinary )
+                psOptionsForBinary->bQuiet = TRUE;
+        }
+        else if( EQUAL(papszArgv[i],"-dstalpha") )
+        {
+            psOptions->bEnableDstAlpha = TRUE;
+        }
+        else if( EQUAL(papszArgv[i],"-srcalpha") )
+        {
+            psOptions->bEnableSrcAlpha = TRUE;
+        }
+        else if( EQUAL(papszArgv[i],"-of") && i+1 < argc )
+        {
+            CPLFree(psOptions->pszFormat);
+            psOptions->pszFormat = CPLStrdup(papszArgv[++i]);
+            psOptions->bCreateOutput = TRUE;
+            if( psOptionsForBinary )
+            {
+                psOptionsForBinary->bFormatExplicitlySet = TRUE;
+            }
+        }
+        else if( EQUAL(papszArgv[i],"-t_srs") && i+1 < argc )
+        {
+            char *pszSRS = SanitizeSRS(papszArgv[++i]);
+            if(pszSRS == NULL)
+            {
+                GDALWarpAppOptionsFree(psOptions);
+                return NULL;
+            }
+            psOptions->papszTO = CSLSetNameValue( psOptions->papszTO, "DST_SRS", pszSRS );
+            CPLFree( pszSRS );
+        }
+        else if( EQUAL(papszArgv[i],"-s_srs") && i+1 < argc )
+        {
+            char *pszSRS = SanitizeSRS(papszArgv[++i]);
+            if(pszSRS == NULL)
+            {
+                GDALWarpAppOptionsFree(psOptions);
+                return NULL;
+            }
+            psOptions->papszTO = CSLSetNameValue( psOptions->papszTO, "SRC_SRS", pszSRS );
+            CPLFree( pszSRS );
+        }
+        else if( EQUAL(papszArgv[i],"-order") && i+1 < argc )
+        {
+            const char* pszMethod = CSLFetchNameValue(psOptions->papszTO, "METHOD");
+            if (pszMethod)
+                CPLError(CE_Warning, CPLE_IllegalArg,
+                         "Warning: only one METHOD can be used. Method %s is already defined",
+                        pszMethod);
+            psOptions->papszTO = CSLSetNameValue( psOptions->papszTO, "MAX_GCP_ORDER", papszArgv[++i] );
+        }
+        else if( EQUAL(papszArgv[i],"-refine_gcps") && i+1 < argc )
+        {
+            psOptions->papszTO = CSLSetNameValue( psOptions->papszTO, "REFINE_TOLERANCE", papszArgv[++i] );
+            if(CPLAtof(papszArgv[i]) < 0)
+            {
+                CPLError(CE_Failure, CPLE_IllegalArg, "The tolerance for -refine_gcps may not be negative.");
+                GDALWarpAppOptionsFree(psOptions);
+                return NULL;
+            }
+            if (i < argc-1 && atoi(papszArgv[i+1]) >= 0 && isdigit(papszArgv[i+1][0]))
+            {
+                psOptions->papszTO = CSLSetNameValue( psOptions->papszTO, "REFINE_MINIMUM_GCPS", papszArgv[++i] );
+            }
+            else
+            {
+                psOptions->papszTO = CSLSetNameValue( psOptions->papszTO, "REFINE_MINIMUM_GCPS", "-1" );
+            }
+        }
+        else if( EQUAL(papszArgv[i],"-tps") )
+        {
+            psOptions->papszTO = CSLSetNameValue( psOptions->papszTO, "METHOD", "GCP_TPS" );
+        }
+        else if( EQUAL(papszArgv[i],"-rpc") )
+        {
+            psOptions->papszTO = CSLSetNameValue( psOptions->papszTO, "METHOD", "RPC" );
+        }
+        else if( EQUAL(papszArgv[i],"-geoloc") )
+        {
+            psOptions->papszTO = CSLSetNameValue( psOptions->papszTO, "METHOD", "GEOLOC_ARRAY" );
+        }
+        else if( EQUAL(papszArgv[i],"-to") && i+1 < argc )
+        {
+            psOptions->papszTO = CSLAddString( psOptions->papszTO, papszArgv[++i] );
+        }
+        else if( EQUAL(papszArgv[i],"-et") && i+1 < argc )
+        {
+            psOptions->dfErrorThreshold = CPLAtofM(papszArgv[++i]);
+            psOptions->papszWarpOptions = CSLAddString( psOptions->papszWarpOptions, CPLSPrintf("ERROR_THRESHOLD=%.16g", psOptions->dfErrorThreshold) );
+        }
+        else if( EQUAL(papszArgv[i],"-wm") && i+1 < argc )
+        {
+            if( CPLAtofM(papszArgv[i+1]) < 10000 )
+                psOptions->dfWarpMemoryLimit = CPLAtofM(papszArgv[i+1]) * 1024 * 1024;
+            else
+                psOptions->dfWarpMemoryLimit = CPLAtofM(papszArgv[i+1]);
+            i++;
+        }
+        else if( EQUAL(papszArgv[i],"-srcnodata") && i+1 < argc )
+        {
+            CPLFree(psOptions->pszSrcNodata);
+            psOptions->pszSrcNodata = CPLStrdup(papszArgv[++i]);
+        }
+        else if( EQUAL(papszArgv[i],"-dstnodata") && i+1 < argc )
+        {
+            CPLFree(psOptions->pszDstNodata);
+            psOptions->pszDstNodata = CPLStrdup(papszArgv[++i]);
+        }
+        else if( EQUAL(papszArgv[i],"-tr") && i+2 < argc )
+        {
+            psOptions->dfXRes = CPLAtofM(papszArgv[++i]);
+            psOptions->dfYRes = fabs(CPLAtofM(papszArgv[++i]));
+            if( psOptions->dfXRes == 0 || psOptions->dfYRes == 0 )
+            {
+                CPLError(CE_Failure, CPLE_IllegalArg, "Wrong value for -tr parameters.");
+                GDALWarpAppOptionsFree(psOptions);
+                return NULL;
+            }
+            psOptions->bCreateOutput = TRUE;
+        }
+        else if( EQUAL(papszArgv[i],"-tap") )
+        {
+            psOptions->bTargetAlignedPixels = TRUE;
+        }
+        else if( EQUAL(papszArgv[i],"-ot") && i+1 < argc )
+        {
+            int iType;
+
+            for( iType = 1; iType < GDT_TypeCount; iType++ )
+            {
+                if( GDALGetDataTypeName((GDALDataType)iType) != NULL
+                    && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
+                             papszArgv[i+1]) )
+                {
+                    psOptions->eOutputType = (GDALDataType) iType;
+                }
+            }
+
+            if( psOptions->eOutputType == GDT_Unknown )
+            {
+                CPLError(CE_Failure, CPLE_IllegalArg, "Unknown output pixel type: %s.", papszArgv[i+1]);
+                GDALWarpAppOptionsFree(psOptions);
+                return NULL;
+            }
+            i++;
+            psOptions->bCreateOutput = TRUE;
+        }
+        else if( EQUAL(papszArgv[i],"-wt") && i+1 < argc )
+        {
+            int iType;
+
+            for( iType = 1; iType < GDT_TypeCount; iType++ )
+            {
+                if( GDALGetDataTypeName((GDALDataType)iType) != NULL
+                    && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
+                             papszArgv[i+1]) )
+                {
+                    psOptions->eWorkingType = (GDALDataType) iType;
+                }
+            }
+
+            if( psOptions->eWorkingType == GDT_Unknown )
+            {
+                CPLError(CE_Failure, CPLE_IllegalArg, "Unknown working pixel type: %s.", papszArgv[i+1]);
+                GDALWarpAppOptionsFree(psOptions);
+                return NULL;
+            }
+            i++;
+        }
+        else if( EQUAL(papszArgv[i],"-ts") && i+2 < argc )
+        {
+            psOptions->nForcePixels = atoi(papszArgv[++i]);
+            psOptions->nForceLines = atoi(papszArgv[++i]);
+            psOptions->bCreateOutput = TRUE;
+        }
+        else if( EQUAL(papszArgv[i],"-te") && i+4 < argc )
+        {
+            psOptions->dfMinX = CPLAtofM(papszArgv[++i]);
+            psOptions->dfMinY = CPLAtofM(papszArgv[++i]);
+            psOptions->dfMaxX = CPLAtofM(papszArgv[++i]);
+            psOptions->dfMaxY = CPLAtofM(papszArgv[++i]);
+            psOptions->bCreateOutput = TRUE;
+        }
+        else if( EQUAL(papszArgv[i],"-te_srs") && i+1 < argc )
+        {
+            char *pszSRS = SanitizeSRS(papszArgv[++i]);
+            if(pszSRS == NULL)
+            {
+                GDALWarpAppOptionsFree(psOptions);
+                return NULL;
+            }
+            CPLFree(psOptions->pszTE_SRS);
+            psOptions->pszTE_SRS = CPLStrdup(pszSRS);
+            CPLFree(pszSRS);
+            psOptions->bCreateOutput = TRUE;
+        }
+        else if( EQUAL(papszArgv[i],"-rn") )
+            psOptions->eResampleAlg = GRA_NearestNeighbour;
+
+        else if( EQUAL(papszArgv[i],"-rb") )
+            psOptions->eResampleAlg = GRA_Bilinear;
+
+        else if( EQUAL(papszArgv[i],"-rc") )
+            psOptions->eResampleAlg = GRA_Cubic;
+
+        else if( EQUAL(papszArgv[i],"-rcs") )
+            psOptions->eResampleAlg = GRA_CubicSpline;
+
+        else if( EQUAL(papszArgv[i],"-rl") )
+            psOptions->eResampleAlg = GRA_Lanczos;
+
+        else if( EQUAL(papszArgv[i],"-ra") )
+            psOptions->eResampleAlg = GRA_Average;
+
+        else if( EQUAL(papszArgv[i],"-rm") )
+            psOptions->eResampleAlg = GRA_Mode;
+
+        else if( EQUAL(papszArgv[i],"-r") && i+1 < argc )
+        {
+            if ( EQUAL(papszArgv[++i], "near") )
+                psOptions->eResampleAlg = GRA_NearestNeighbour;
+            else if ( EQUAL(papszArgv[i], "bilinear") )
+                psOptions->eResampleAlg = GRA_Bilinear;
+            else if ( EQUAL(papszArgv[i], "cubic") )
+                psOptions->eResampleAlg = GRA_Cubic;
+            else if ( EQUAL(papszArgv[i], "cubicspline") )
+                psOptions->eResampleAlg = GRA_CubicSpline;
+            else if ( EQUAL(papszArgv[i], "lanczos") )
+                psOptions->eResampleAlg = GRA_Lanczos;
+            else if ( EQUAL(papszArgv[i], "average") )
+                psOptions->eResampleAlg = GRA_Average;
+            else if ( EQUAL(papszArgv[i], "mode") )
+                psOptions->eResampleAlg = GRA_Mode;
+            else if ( EQUAL(papszArgv[i], "max") )
+                psOptions->eResampleAlg = GRA_Max;
+            else if ( EQUAL(papszArgv[i], "min") )
+                psOptions->eResampleAlg = GRA_Min;
+            else if ( EQUAL(papszArgv[i], "med") )
+                psOptions->eResampleAlg = GRA_Med;
+            else if ( EQUAL(papszArgv[i], "q1") )
+                psOptions->eResampleAlg = GRA_Q1;
+            else if ( EQUAL(papszArgv[i], "q3") )
+                psOptions->eResampleAlg = GRA_Q3;
+            else
+            {
+                CPLError(CE_Failure, CPLE_IllegalArg, "Unknown resampling method: %s.", papszArgv[i]);
+                GDALWarpAppOptionsFree(psOptions);
+                return NULL;
+            }
+        }
+
+        else if( EQUAL(papszArgv[i],"-cutline") && i+1 < argc )
+        {
+            CPLFree(psOptions->pszCutlineDSName);
+            psOptions->pszCutlineDSName = CPLStrdup(papszArgv[++i]);
+        }
+        else if( EQUAL(papszArgv[i],"-cwhere") && i+1 < argc )
+        {
+            CPLFree(psOptions->pszCWHERE);
+            psOptions->pszCWHERE = CPLStrdup(papszArgv[++i]);
+        }
+        else if( EQUAL(papszArgv[i],"-cl") && i+1 < argc )
+        {
+            CPLFree(psOptions->pszCLayer);
+            psOptions->pszCLayer = CPLStrdup(papszArgv[++i]);
+        }
+        else if( EQUAL(papszArgv[i],"-csql") && i+1 < argc )
+        {
+            CPLFree(psOptions->pszCSQL);
+            psOptions->pszCSQL = CPLStrdup(papszArgv[++i]);
+        }
+        else if( EQUAL(papszArgv[i],"-cblend") && i+1 < argc )
+        {
+            psOptions->papszWarpOptions =
+                CSLSetNameValue( psOptions->papszWarpOptions,
+                                 "CUTLINE_BLEND_DIST", papszArgv[++i] );
+        }
+        else if( EQUAL(papszArgv[i],"-crop_to_cutline")  )
+        {
+            psOptions->bCropToCutline = TRUE;
+            psOptions->bCreateOutput = TRUE;
+        }
+        else if( EQUAL(papszArgv[i],"-overwrite") )
+        {
+            if( psOptionsForBinary )
+                psOptionsForBinary->bOverwrite = TRUE;
+        }
+        else if( EQUAL(papszArgv[i],"-nomd") )
+        {
+            psOptions->bCopyMetadata = FALSE;
+            psOptions->bCopyBandInfo = FALSE;
+        }
+        else if( EQUAL(papszArgv[i],"-cvmd") && i+1 < argc )
+        {
+            CPLFree(psOptions->pszMDConflictValue);
+            psOptions->pszMDConflictValue = CPLStrdup(papszArgv[++i]);
+        }
+        else if( EQUAL(papszArgv[i],"-setci") )
+            psOptions->bSetColorInterpretation = TRUE;
+        else if( EQUAL(papszArgv[i], "-oo") && i+1 < argc )
+        {
+            if( psOptionsForBinary )
+                psOptionsForBinary->papszOpenOptions = CSLAddString(
+                                                psOptionsForBinary->papszOpenOptions,
+                                                papszArgv[++i] );
+        }
+        else if( EQUAL(papszArgv[i], "-doo") && i+1 < argc )
+        {
+            if( psOptionsForBinary )
+                psOptionsForBinary->papszDestOpenOptions = CSLAddString(
+                                                psOptionsForBinary->papszDestOpenOptions,
+                                                papszArgv[++i] );
+        }
+        else if( EQUAL(papszArgv[i], "-ovr") && i+1 < argc )
+        {
+            const char* pszOvLevel = papszArgv[++i];
+            if( EQUAL(pszOvLevel, "AUTO") )
+                psOptions->nOvLevel = -2;
+            else if( STARTS_WITH_CI(pszOvLevel, "AUTO-") )
+                psOptions->nOvLevel = -2-atoi(pszOvLevel + 5);
+            else if( EQUAL(pszOvLevel, "NONE") )
+                psOptions->nOvLevel = -1;
+            else if( CPLGetValueType(pszOvLevel) == CPL_VALUE_INTEGER )
+                psOptions->nOvLevel = atoi(pszOvLevel);
+            else
+            {
+                CPLError(CE_Failure, CPLE_IllegalArg, "Invalid value '%s' for -ov option", pszOvLevel);
+                GDALWarpAppOptionsFree(psOptions);
+                return NULL;
+            }
+        }
+        else if( papszArgv[i][0] == '-' )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unknown option name '%s'", papszArgv[i]);
+            GDALWarpAppOptionsFree(psOptions);
+            return NULL;
+        }
+
+        else
+        {
+            if( psOptionsForBinary )
+            {
+                psOptionsForBinary->papszSrcFiles = CSLAddString( psOptionsForBinary->papszSrcFiles, papszArgv[i] );
+            }
+        }
+    }
+
+    if( psOptionsForBinary )
+        psOptionsForBinary->bCreateOutput = psOptions->bCreateOutput;
+
+    if( psOptionsForBinary )
+        psOptionsForBinary->pszFormat = CPLStrdup(psOptions->pszFormat);
+
+/* -------------------------------------------------------------------- */
+/*      The last filename in the file list is really our destination    */
+/*      file.                                                           */
+/* -------------------------------------------------------------------- */
+    if( psOptionsForBinary && CSLCount(psOptionsForBinary->papszSrcFiles) > 1 )
+    {
+        psOptionsForBinary->pszDstFilename = psOptionsForBinary->papszSrcFiles[CSLCount(psOptionsForBinary->papszSrcFiles)-1];
+        psOptionsForBinary->papszSrcFiles[CSLCount(psOptionsForBinary->papszSrcFiles)-1] = NULL;
+    }
+
+    return psOptions;
+}
+
+/************************************************************************/
+/*                        GDALWarpAppOptionsFree()                    */
+/************************************************************************/
+
+/**
+ * Frees the GDALWarpAppOptions struct.
+ *
+ * @param psOptions the options struct for GDALWarp().
+ *
+ * @since GDAL 2.1
+ */
+
+void GDALWarpAppOptionsFree( GDALWarpAppOptions *psOptions )
+{
+    if( psOptions )
+    {
+        CPLFree(psOptions->pszFormat);
+        CSLDestroy(psOptions->papszWarpOptions);
+        CSLDestroy(psOptions->papszCreateOptions);
+        CPLFree(psOptions->pszSrcNodata);
+        CPLFree(psOptions->pszDstNodata);
+        CSLDestroy(psOptions->papszTO);
+        CPLFree(psOptions->pszCutlineDSName);
+        CPLFree(psOptions->pszCLayer);
+        CPLFree(psOptions->pszCWHERE);
+        CPLFree(psOptions->pszCSQL);
+        CPLFree(psOptions->pszMDConflictValue);
+        CPLFree(psOptions->pszTE_SRS);
+    }
+
+    CPLFree(psOptions);
+}
+
+/************************************************************************/
+/*                 GDALWarpAppOptionsSetProgress()                    */
+/************************************************************************/
+
+/**
+ * Set a progress function.
+ *
+ * @param psOptions the options struct for GDALWarpApp().
+ * @param pfnProgress the progress callback.
+ * @param pProgressData the user data for the progress callback.
+ *
+ * @since GDAL 2.1
+ */
+
+void GDALWarpAppOptionsSetProgress( GDALWarpAppOptions *psOptions,
+                                      GDALProgressFunc pfnProgress, void *pProgressData )
+{
+    psOptions->pfnProgress = pfnProgress ? pfnProgress : GDALDummyProgress;
+    psOptions->pProgressData = pProgressData;
+    if( pfnProgress == GDALTermProgress )
+        psOptions->bQuiet = FALSE;
+}
+
+/************************************************************************/
+/*                 GDALWarpAppOptionsSetWarpOption()                    */
+/************************************************************************/
+
+/**
+ * Set a warp option
+ *
+ * @param psOptions the options struct for GDALWarpApp().
+ * @param pszKey key.
+ * @param pszValue value.
+ *
+ * @since GDAL 2.1
+ */
+
+void GDALWarpAppOptionsSetWarpOption( GDALWarpAppOptions *psOptions,
+                                      const char* pszKey,
+                                      const char* pszValue )
+{
+    psOptions->papszWarpOptions = CSLSetNameValue(psOptions->papszWarpOptions, pszKey, pszValue);
+}
diff --git a/apps/gdalwarpsimple.c b/apps/gdalwarpsimple.c
index f655476..bade362 100644
--- a/apps/gdalwarpsimple.c
+++ b/apps/gdalwarpsimple.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalwarpsimple.c 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: gdalwarpsimple.c 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Mapinfo Image Warper
  * Purpose:  Commandline program for doing a variety of image warps, including
@@ -7,7 +7,7 @@
  * Author:   Frank Warmerdam <warmerdam at pobox.com>
  *
  ******************************************************************************
- * Copyright (c) 2002, i3 - information integration and imaging 
+ * Copyright (c) 2002, i3 - information integration and imaging
  *                          Fort Collin, CO
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -33,12 +33,12 @@
 #include "cpl_string.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: gdalwarpsimple.c 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: gdalwarpsimple.c 33720 2016-03-15 00:39:53Z goatbar $");
 
-static GDALDatasetH 
-GDALWarpCreateOutput( GDALDatasetH hSrcDS, const char *pszFilename, 
-                      const char *pszFormat, const char *pszSourceSRS, 
-                      const char *pszTargetSRS, int nOrder, 
+static GDALDatasetH
+GDALWarpCreateOutput( GDALDatasetH hSrcDS, const char *pszFilename,
+                      const char *pszFormat, const char *pszSourceSRS,
+                      const char *pszTargetSRS, int nOrder,
                       char **papszCreateOptions );
 
 static double	       dfMinX=0.0, dfMinY=0.0, dfMaxX=0.0, dfMaxY=0.0;
@@ -52,7 +52,7 @@ static int             nForcePixels=0, nForceLines=0;
 static void Usage()
 
 {
-    printf( 
+    printf(
         "Usage: gdalwarpsimple [--version] [--formats]\n"
         "    [-s_srs srs_def] [-t_srs srs_def] [-order n] [-et err_threshold]\n"
         "    [-te xmin ymin xmax ymax] [-tr xres yres] [-ts width height]\n"
@@ -71,7 +71,7 @@ char *SanitizeSRS( const char *pszUserInput )
     char *pszResult = NULL;
 
     CPLErrorReset();
-    
+
     hSRS = OSRNewSpatialReference( NULL );
     if( OSRSetFromUserInput( hSRS, pszUserInput ) == OGRERR_NONE )
         OSRExportToWkt( hSRS, &pszResult );
@@ -82,7 +82,7 @@ char *SanitizeSRS( const char *pszUserInput )
                   pszUserInput );
         exit( 1 );
     }
-    
+
     OSRDestroySpatialReference( hSRS );
 
     return pszResult;
@@ -127,7 +127,7 @@ int main( int argc, char ** argv )
             for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
             {
                 GDALDriverH hDriver = GDALGetDriver(iDr);
-                
+
                 printf( "  %s: %s\n",
                         GDALGetDriverShortName( hDriver ),
                         GDALGetDriverLongName( hDriver ) );
@@ -139,7 +139,7 @@ int main( int argc, char ** argv )
         {
             papszCreateOptions = CSLAddString( papszCreateOptions, argv[++i] );
             bCreateOutput = TRUE;
-        }   
+        }
         else if( EQUAL(argv[i],"-of") && i < argc-1 )
         {
             pszFormat = argv[++i];
@@ -198,7 +198,7 @@ int main( int argc, char ** argv )
 /*      Open source dataset.                                            */
 /* -------------------------------------------------------------------- */
     hSrcDS = GDALOpen( pszSrcFilename, GA_ReadOnly );
-    
+
     if( hSrcDS == NULL )
         exit( 2 );
 
@@ -213,12 +213,12 @@ int main( int argc, char ** argv )
 
     if( pszSourceSRS == NULL )
     {
-        if( GDALGetProjectionRef( hSrcDS ) != NULL 
+        if( GDALGetProjectionRef( hSrcDS ) != NULL
             && strlen(GDALGetProjectionRef( hSrcDS )) > 0 )
             pszSourceSRS = CPLStrdup(GDALGetProjectionRef( hSrcDS ));
 
         else if( GDALGetGCPProjection( hSrcDS ) != NULL
-                 && strlen(GDALGetGCPProjection(hSrcDS)) > 0 
+                 && strlen(GDALGetGCPProjection(hSrcDS)) > 0
                  && GDALGetGCPCount( hSrcDS ) > 1 )
             pszSourceSRS = CPLStrdup(GDALGetGCPProjection( hSrcDS ));
         else
@@ -237,7 +237,7 @@ int main( int argc, char ** argv )
 
     if( hDstDS != NULL && bCreateOutput )
     {
-        fprintf( stderr, 
+        fprintf( stderr,
                  "Output dataset %s exists,\n"
                  "but some commandline options were provided indicating a new dataset\n"
                  "should be created.  Please delete existing dataset and run again.",
@@ -250,7 +250,7 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
     if( hDstDS == NULL )
     {
-        hDstDS = GDALWarpCreateOutput( hSrcDS, pszDstFilename, pszFormat, 
+        hDstDS = GDALWarpCreateOutput( hSrcDS, pszDstFilename, pszFormat,
                                        pszSourceSRS, pszTargetSRS, nOrder,
                                        papszCreateOptions );
         papszWarpOptions = CSLSetNameValue( papszWarpOptions, "INIT", "0" );
@@ -265,9 +265,9 @@ int main( int argc, char ** argv )
 /*      Create a transformation object from the source to               */
 /*      destination coordinate system.                                  */
 /* -------------------------------------------------------------------- */
-    hTransformArg = hGenImgProjArg = 
-        GDALCreateGenImgProjTransformer( hSrcDS, pszSourceSRS, 
-                                         hDstDS, pszTargetSRS, 
+    hTransformArg = hGenImgProjArg =
+        GDALCreateGenImgProjTransformer( hSrcDS, pszSourceSRS,
+                                         hDstDS, pszTargetSRS,
                                          TRUE, 1000.0, nOrder );
 
     if( hTransformArg == NULL )
@@ -281,8 +281,8 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
     if( dfErrorThreshold != 0.0 )
     {
-        hTransformArg = hApproxArg = 
-            GDALCreateApproxTransformer( GDALGenImgProjTransform, 
+        hTransformArg = hApproxArg =
+            GDALCreateApproxTransformer( GDALGenImgProjTransform,
                                          hGenImgProjArg, dfErrorThreshold );
         pfnTransformer = GDALApproxTransform;
     }
@@ -290,7 +290,7 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
 /*      Now actually invoke the warper to do the work.                  */
 /* -------------------------------------------------------------------- */
-    GDALSimpleImageWarp( hSrcDS, hDstDS, 0, NULL, 
+    GDALSimpleImageWarp( hSrcDS, hDstDS, 0, NULL,
                          pfnTransformer, hTransformArg,
                          GDALTermProgress, NULL, papszWarpOptions );
 
@@ -311,7 +311,7 @@ int main( int argc, char ** argv )
     GDALDumpOpenDatasets( stderr );
 
     GDALDestroyDriverManager();
-    
+
     exit( 0 );
 }
 
@@ -322,9 +322,9 @@ int main( int argc, char ** argv )
 /*      and the input file.                                             */
 /************************************************************************/
 
-static GDALDatasetH 
-GDALWarpCreateOutput( GDALDatasetH hSrcDS, const char *pszFilename, 
-                      const char *pszFormat, const char *pszSourceSRS, 
+static GDALDatasetH
+GDALWarpCreateOutput( GDALDatasetH hSrcDS, const char *pszFilename,
+                      const char *pszFormat, const char *pszSourceSRS,
                       const char *pszTargetSRS, int nOrder,
                       char **papszCreateOptions )
 
@@ -340,12 +340,12 @@ GDALWarpCreateOutput( GDALDatasetH hSrcDS, const char *pszFilename,
 /*      Find the output driver.                                         */
 /* -------------------------------------------------------------------- */
     hDriver = GDALGetDriverByName( pszFormat );
-    if( hDriver == NULL 
+    if( hDriver == NULL
         || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) == NULL )
     {
         int	iDr;
-        
-        printf( "Output driver `%s' not recognised or does not support\n", 
+
+        printf( "Output driver `%s' not recognised or does not support\n",
                 pszFormat );
         printf( "direct output file creation.  The following format drivers are configured\n"
                 "and support direct output:\n" );
@@ -369,9 +369,9 @@ GDALWarpCreateOutput( GDALDatasetH hSrcDS, const char *pszFilename,
 /*      Create a transformation object from the source to               */
 /*      destination coordinate system.                                  */
 /* -------------------------------------------------------------------- */
-    hTransformArg = 
-        GDALCreateGenImgProjTransformer( hSrcDS, pszSourceSRS, 
-                                         NULL, pszTargetSRS, 
+    hTransformArg =
+        GDALCreateGenImgProjTransformer( hSrcDS, pszSourceSRS,
+                                         NULL, pszTargetSRS,
                                          TRUE, 1000.0, nOrder );
 
     if( hTransformArg == NULL )
@@ -380,8 +380,8 @@ GDALWarpCreateOutput( GDALDatasetH hSrcDS, const char *pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Get approximate output definition.                              */
 /* -------------------------------------------------------------------- */
-    if( GDALSuggestedWarpOutput( hSrcDS, 
-                                 GDALGenImgProjTransform, hTransformArg, 
+    if( GDALSuggestedWarpOutput( hSrcDS,
+                                 GDALGenImgProjTransform, hTransformArg,
                                  adfDstGeoTransform, &nPixels, &nLines )
         != CE_None )
         return NULL;
@@ -449,7 +449,7 @@ GDALWarpCreateOutput( GDALDatasetH hSrcDS, const char *pszFilename,
 /* -------------------------------------------------------------------- */
     printf( "Creating output file is that %dP x %dL.\n", nPixels, nLines );
 
-    hDstDS = GDALCreate( hDriver, pszFilename, nPixels, nLines, 
+    hDstDS = GDALCreate( hDriver, pszFilename, nPixels, nLines,
                          GDALGetRasterCount(hSrcDS),
                          GDALGetRasterDataType(GDALGetRasterBand(hSrcDS,1)),
                          papszCreateOptions );
@@ -472,4 +472,3 @@ GDALWarpCreateOutput( GDALDatasetH hSrcDS, const char *pszFilename,
 
     return hDstDS;
 }
-    
diff --git a/apps/gnm_utilities.dox b/apps/gnm_utilities.dox
new file mode 100644
index 0000000..793354c
--- /dev/null
+++ b/apps/gnm_utilities.dox
@@ -0,0 +1,140 @@
+/*! \page gnm_utilities GNM Utility Programs
+
+There are several Geographical Network Model (GNM) utilities:
+
+<ul>
+<li> \ref gnmmanage - Manages networks
+<li> \ref gnmanalyse - Analyses networks
+</ul>
+
+*/
+
+
+
+
+/*! \page gnmmanage gnmmanage
+
+Manages networks
+
+\section gnmmanage_synopsis SYNOPSIS
+
+\verbatim
+gnmmanage [--help][-q][-quiet][--long-usage]
+          [info]
+          [create [-f format_name] [-t_srs srs_name] [-dsco NAME=VALUE]... ]
+          [import src_dataset_name] [-l layer_name]
+          [connect gfid_src gfid_tgt gfid_con [-c cost] [-ic inv_cost] [-dir dir]]
+          [disconnect gfid_src gfid_tgt gfid_con]
+          [rule rule_str]
+          [autoconnect tolerance]
+          [delete]
+          [change [-bl gfid][-unbl gfid][-unblall]]
+          gnm_name [layer [layer ...]]
+          
+\endverbatim
+
+\section gnmmanage_description DESCRIPTION
+
+The gnmmanage program can perform various managing operations on geographical networks in GDAL. In addition to creating and deleting networks this includes capabilities of managing network's features, topology and rules.
+
+<dl>
+
+<dt> <b>info</b>:</dt><dd> Different information about network: system and class layers, network metadata, network spatial reference. </dd>
+
+<dt> <b>create</b>:</dt><dd> Create network. </dd>
+<dl>
+    <dt> <b>-f</b> <i>format_name</i>:</dt><dd> Output file format name. </dd>
+    <dt> <b>-t_srs</b> <i>srs_name</i>:</dt><dd> Spatial reference input. </dd>
+    <dt> <b>-dsco</b> <i>NAME=VALUE</i>:</dt><dd> Network creation option set as pair name=value. </dd>
+</dl>
+
+<dt> <b>import</b> <i>src_dataset_name</i>:</dt><dd> Import layer with dataset name to copy. </dd>
+<dl>
+    <dt> <b>-l</b> <i>layer_name</i>:</dt><dd> Layer name in dataset. If unset, 0 layer is copied. </dd>
+</dl>
+
+<dt> <b>connect</b> <i>gfid_src</i> <i>gfid_tgt</i> <i>gfid_con</i>:</dt><dd> Make a topological connection, where the gfid_src and gfid_tgt are vertexes and gfid_con is edge (gfid_con can be -1, so the system edge will be inserted). </dd>
+<dl>
+    <dt> <b>-c</b> <i>cost</i> <b>-ic</b> <i>inv_cost</i> <b>-dir</b> <i>dir</i>:</dt><dd> Manually assign the following values: the cost (weight), inverse cost and direction of the edge (optional). </dd>
+</dl>
+
+<dt> <b>disconnect</b> <i>gfid_src</i> <i>gfid_tgt</i> <i>gfid_con</i>:</dt><dd> Removes the connection from the graph. </dd>
+
+<dt> <b>rule</b> <i>rule_str</i>:</dt><dd> Creates a rule in the network by the given rule_str string. </dd>
+
+<dt> <b>autoconnect</b> <i>tolerance</i>:</dt><dd> Create topology automatically with the given double tolerance and layer names. In no layer name provided all layers of network will be used.</dd>
+
+<dt> <b>delete</b>:</dt><dd> Delete network. </dd>
+
+<dt> <b>change</b>:</dt><dd> Change blocking state of network edges or vertices. </dd>
+
+<dt> <b>-bl</b> <i>gfid</i>:</dt><dd> Block feature before the main operation. Blocking features are saved in the special layer. </dd>
+
+<dt> <b>-unbl</b> <i>gfid</i>:</dt><dd> Unblock feature before the main operation. </dd>
+
+<dt> <b>-unblall</b>:</dt><dd> Unblock all blocked features before the main operation. </dd>
+
+
+<dt> <i>gnm_name</i>:</dt><dd> The network to work with (path and name). </dd>
+
+<dt> <i>layer</i>:</dt><dd> The network layer name. </dd>
+
+</dl>
+
+\if man
+\section gnmmanage_author AUTHORS
+Mikhail Gusev <gusevmihs at gmail.com>
+Dmitry Baryshnikov <polimax at mail.ru>
+\endif
+*/
+
+
+
+
+/*! \page gnmanalyse gnmanalyse
+
+Analyses networks
+
+\section gnmanalyse_synopsis SYNOPSIS
+
+\verbatim
+gnmanalyse [--help][-q][-quiet][--long-usage]
+           [dijkstra start_gfid end_gfid [[-alo NAME=VALUE] ...]]]
+           [kpaths start_gfid end_gfid k [[-alo NAME=VALUE] ...]]]
+           [resource [[-alo NAME=VALUE] ...]]]
+           [-ds ds_name][-f ds_format][-l layer_name]
+           [[-dsco NAME=VALUE] ...][-lco NAME=VALUE]
+           gnm_name
+\endverbatim
+
+\section gnmanalyse_description DESCRIPTION
+
+The gnmanalyse program provides analysing capabilities of geographical networks in GDAL. The results of calculations are return in an OGRLayer format or as a console text output if such layer is undefined. All calculations are made considering the blocking state of features. 
+
+<dl>
+
+<dt> <b>dijkstra</b> <i>start_gfid</i> <i>end_gfid</i>:</dt><dd> Calculates the best path between two points using Dijkstra algorithm from start_gfid point to end_gfid point. </dd>
+
+<dt> <b>kpaths</b> <i>start_gfid</i> <i>end_gfid</i>:</dt><dd> Calculates K shortest paths between two points using Yen's algorithm (which internally uses Dijkstra algorithm for single path calculating) from start_gfid point to end_gfid point. </dd>
+
+<dt> <b>resource</b>:</dt><dd> Calculates the "resource distribution". The connected components search is performed using breadth-first search and starting from that features which are marked by rules as 'EMITTERS'. </dd>
+
+<dt> <b>-ds</b> <i>ds_name</i>:</dt><dd> The name&path of the dataset to save the layer with resulting paths. Not need to be existed dataset. </dd>
+
+<dt> <b>-f</b> <i>ds_format</i>:</dt><dd> Define this to set the format of newly created dataset. </dd>
+
+<dt> <b>-l</b> <i>layer_name</i>:</dt><dd> The name of the resulting layer. If the layer exist already - it will be rewritten. </dd>
+
+<dt> <i>gnm_name</i>:</dt><dd> The network to work with (path and name). </dd>
+
+<dt> <b>-dsco</b> <em>NAME=VALUE</em>:</dt><dd> Dataset creation option (format specific)</dd>
+<dt> <b>-lco</b><em>  NAME=VALUE</em>:</dt><dd> Layer creation option (format specific)</dd>
+<dt> <b>-alo</b><em>  NAME=VALUE</em>:</dt><dd> Algorithm option (format specific)</dd>
+</dl>
+
+\if man
+\section gnmmanage_author AUTHORS
+Mikhail Gusev <gusevmihs at gmail.com>
+Dmitry Baryshnikov <polimax at mail.ru>
+\endif
+*/
diff --git a/apps/gnmanalyse.cpp b/apps/gnmanalyse.cpp
new file mode 100755
index 0000000..9bab435
--- /dev/null
+++ b/apps/gnmanalyse.cpp
@@ -0,0 +1,630 @@
+/******************************************************************************
+ * Project:  geography network utility
+ * Purpose:  Analyse GNM networks
+ * Authors:  Mikhail Gusev, gusevmihs at gmail dot com
+ *           Dmitry Baryshnikov, polimax at mail.ru
+ *
+ ******************************************************************************
+ * Copyright (C) 2014 Mikhail Gusev
+ * Copyright (c) 2014-2015, NextGIS <info at nextgis.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gnm.h"
+#include "commonutils.h"
+#include "ogr_p.h"
+
+enum operation
+{
+    op_unknown = 0, /** no operation */
+    op_dijkstra,    /** create shortest path using Dijkstra algorithm */
+    op_kpaths,      /** create k shortest paths using Yens algorithm */
+    op_resource    /** create resource distribution layer */
+};
+
+/************************************************************************/
+/*                               Usage()                                */
+/************************************************************************/
+static void Usage(const char* pszAdditionalMsg, int bShort = TRUE)
+{
+    printf("Usage: gnmanalyse [--help][-q][-quiet][--long-usage]\n"
+           "                  [dijkstra start_gfid end_gfid [[-alo NAME=VALUE] ...]]\n"
+           "                  [kpaths start_gfid end_gfid k [[-alo NAME=VALUE] ...]]\n"
+           "                  [resource [[-alo NAME=VALUE] ...]]\n"
+           "                  [-ds ds_name][-f ds_format][-l layer_name]\n"
+           "                  [[-dsco NAME=VALUE] ...][-lco NAME=VALUE]\n"
+           "                  gnm_name\n");
+
+    if (bShort)
+    {
+        printf("\nNote: gnmanalyse --long-usage for full help.\n");
+        if (pszAdditionalMsg)
+            fprintf(stderr, "\nFAILURE: %s\n", pszAdditionalMsg);
+        exit(1);
+    }
+
+    printf("\n   dijkstra start_gfid end_gfid: calculates the best path between two points using Dijkstra algorithm from start_gfid point to end_gfid point\n"
+           "   kpaths start_gfid end_gfid k: calculates k (up to 10) best paths between two points using Yen\'s algorithm (which internally uses Dijkstra algorithm for single path calculating) from start_gfid point to end_gfid point\n"
+           "   resource: calculates the \"resource distribution\". The connected components search is performed using breadth-first search and starting from that features which are marked by rules as \'EMITTERS\'\n"
+           "   -ds ds_name: the name&path of the dataset to save the layer with resulting paths. Not need to be existed dataset\n"
+           "   -f ds_format: define this to set the format of newly created dataset\n"
+           "   -l layer_name: the name of the resulting layer. If the layer exists already - it will be rewritten. For K shortest paths several layers are created in format layer_nameN, where N - is number of the path (0 - is the most shortest one)\n"
+           "   -dsco NAME=VALUE: Dataset creation option (format specific)\n"
+           "   -lco  NAME=VALUE: Layer creation option (format specific)\n"
+           "   -alo  NAME=VALUE: Algorithm option (format specific)\n"
+           "   gnm_name: the network to work with (path and name)\n"
+           );
+
+    if (pszAdditionalMsg)
+        fprintf(stderr, "\nFAILURE: %s\n", pszAdditionalMsg);
+
+    exit(1);
+}
+
+static void Usage(int bShort = TRUE)
+{
+    Usage(NULL, bShort);
+}
+
+/************************************************************************/
+/*                   GetLayerAndOverwriteIfNecessary()                  */
+/************************************************************************/
+
+static OGRLayer* GetLayerAndOverwriteIfNecessary(GDALDataset *poDstDS,
+                                                 const char* pszNewLayerName,
+                                                 int bOverwrite,
+                                                 int* pbErrorOccurred)
+{
+    if( pbErrorOccurred )
+        *pbErrorOccurred = FALSE;
+
+    /* GetLayerByName() can instantiate layers that would have been */
+    /* 'hidden' otherwise, for example, non-spatial tables in a */
+    /* PostGIS-enabled database, so this apparently useless command is */
+    /* not useless... (#4012) */
+    CPLPushErrorHandler(CPLQuietErrorHandler);
+    OGRLayer* poDstLayer = poDstDS->GetLayerByName(pszNewLayerName);
+    CPLPopErrorHandler();
+    CPLErrorReset();
+
+    int iLayer = -1;
+    if (poDstLayer != NULL)
+    {
+        int nLayerCount = poDstDS->GetLayerCount();
+        for( iLayer = 0; iLayer < nLayerCount; iLayer++ )
+        {
+            OGRLayer        *poLayer = poDstDS->GetLayer(iLayer);
+            if (poLayer == poDstLayer)
+                break;
+        }
+
+        if (iLayer == nLayerCount)
+            /* should not happen with an ideal driver */
+            poDstLayer = NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      If the user requested overwrite, and we have the layer in       */
+/*      question we need to delete it now so it will get recreated      */
+/*      (overwritten).                                                  */
+/* -------------------------------------------------------------------- */
+    if( poDstLayer != NULL && bOverwrite )
+    {
+        if( poDstDS->DeleteLayer( iLayer ) != OGRERR_NONE )
+        {
+            fprintf( stderr,
+                     "DeleteLayer() failed when overwrite requested.\n" );
+            if( pbErrorOccurred )
+                *pbErrorOccurred = TRUE;
+        }
+        poDstLayer = NULL;
+    }
+
+    return poDstLayer;
+}
+
+/************************************************************************/
+/*                     CreateAndFillOutputDataset                       */
+/************************************************************************/
+static OGRErr CreateAndFillOutputDataset(OGRLayer* poSrcLayer,
+                                         const char* pszDestDataSource,
+                                         const char* pszFormat,
+                                         const char* pszLayer,
+                                         char** papszDSCO,
+                                         char** papszLCO,
+                                         int bQuiet)
+{
+    GDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName(pszFormat);
+    if( poDriver == NULL )
+    {
+        fprintf( stderr, "%s driver not available\n", pszFormat );
+        return OGRERR_FAILURE;
+    }
+
+    if( !CPLTestBool(
+            CSLFetchNameValueDef(poDriver->GetMetadata(), GDAL_DCAP_CREATE,
+                                 "FALSE") ) )
+    {
+        fprintf( stderr,  "%s driver does not support data source creation.\n",
+                pszFormat );
+        return OGRERR_FAILURE;
+    }
+
+    GDALDataset* poODS = poDriver->Create( pszDestDataSource, 0, 0, 0,
+                                         GDT_Unknown, papszDSCO );
+    if( poODS == NULL )
+    {
+        fprintf( stderr,  "%s driver failed to create %s\n",
+                pszFormat, pszDestDataSource );
+        return OGRERR_FAILURE;
+    }
+
+    if(NULL == pszLayer)
+        pszLayer = poSrcLayer->GetName();
+    int nError;
+    GetLayerAndOverwriteIfNecessary(poODS, pszLayer, TRUE, &nError);
+    if(nError == TRUE)
+    {
+        return OGRERR_FAILURE;
+    }
+
+    // create layer
+    OGRLayer * poLayer = poODS->CopyLayer(poSrcLayer, pszLayer, papszLCO);
+    if (NULL == poLayer)
+    {
+        fprintf(stderr, "\nFAILURE: Can not copy path to %s\n",
+                pszDestDataSource);
+        GDALClose(poODS);
+
+        return OGRERR_FAILURE;
+    }
+
+    if (bQuiet == FALSE)
+    {
+        printf("\nPath successfully copied and added to the network at %s\n",
+            pszDestDataSource);
+    }
+
+    GDALClose(poODS);
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           ReportOnLayer()                            */
+/************************************************************************/
+
+static void ReportOnLayer( OGRLayer * poLayer, int bVerbose )
+
+{
+    OGRFeatureDefn      *poDefn = poLayer->GetLayerDefn();
+
+/* -------------------------------------------------------------------- */
+/*      Report various overall information.                             */
+/* -------------------------------------------------------------------- */
+    printf( "\n" );
+
+    printf( "Layer name: %s\n", poLayer->GetName() );
+
+    if( bVerbose )
+    {
+        int nGeomFieldCount =
+            poLayer->GetLayerDefn()->GetGeomFieldCount();
+        if( nGeomFieldCount > 1 )
+        {
+            for(int iGeom = 0;iGeom < nGeomFieldCount; iGeom ++ )
+            {
+                OGRGeomFieldDefn* poGFldDefn =
+                    poLayer->GetLayerDefn()->GetGeomFieldDefn(iGeom);
+                printf( "Geometry (%s): %s\n", poGFldDefn->GetNameRef(),
+                    OGRGeometryTypeToName( poGFldDefn->GetType() ) );
+            }
+        }
+        else
+        {
+            printf( "Geometry: %s\n",
+                    OGRGeometryTypeToName( poLayer->GetGeomType() ) );
+        }
+
+        printf( "Feature Count: " CPL_FRMT_GIB "\n", poLayer->GetFeatureCount() );
+
+        OGREnvelope oExt;
+        if( nGeomFieldCount > 1 )
+        {
+            for(int iGeom = 0;iGeom < nGeomFieldCount; iGeom ++ )
+            {
+                if (poLayer->GetExtent(iGeom, &oExt, TRUE) == OGRERR_NONE)
+                {
+                    OGRGeomFieldDefn* poGFldDefn =
+                        poLayer->GetLayerDefn()->GetGeomFieldDefn(iGeom);
+                    CPLprintf("Extent (%s): (%f, %f) - (%f, %f)\n",
+                           poGFldDefn->GetNameRef(),
+                           oExt.MinX, oExt.MinY, oExt.MaxX, oExt.MaxY);
+                }
+            }
+        }
+        else if ( poLayer->GetExtent(&oExt, TRUE) == OGRERR_NONE)
+        {
+            CPLprintf("Extent: (%f, %f) - (%f, %f)\n",
+                   oExt.MinX, oExt.MinY, oExt.MaxX, oExt.MaxY);
+        }
+
+        char    *pszWKT;
+
+        if( nGeomFieldCount > 1 )
+        {
+            for(int iGeom = 0;iGeom < nGeomFieldCount; iGeom ++ )
+            {
+                OGRGeomFieldDefn* poGFldDefn =
+                    poLayer->GetLayerDefn()->GetGeomFieldDefn(iGeom);
+                OGRSpatialReference* poSRS = poGFldDefn->GetSpatialRef();
+                if( poSRS == NULL )
+                    pszWKT = CPLStrdup( "(unknown)" );
+                else
+                {
+                    poSRS->exportToPrettyWkt( &pszWKT );
+                }
+
+                printf( "SRS WKT (%s):\n%s\n",
+                        poGFldDefn->GetNameRef(), pszWKT );
+                CPLFree( pszWKT );
+            }
+        }
+        else
+        {
+            if( poLayer->GetSpatialRef() == NULL )
+                pszWKT = CPLStrdup( "(unknown)" );
+            else
+            {
+                poLayer->GetSpatialRef()->exportToPrettyWkt( &pszWKT );
+            }
+
+            printf( "Layer SRS WKT:\n%s\n", pszWKT );
+            CPLFree( pszWKT );
+        }
+
+        if( strlen(poLayer->GetFIDColumn()) > 0 )
+            printf( "FID Column = %s\n",
+                    poLayer->GetFIDColumn() );
+
+        for(int iGeom = 0;iGeom < nGeomFieldCount; iGeom ++ )
+        {
+            OGRGeomFieldDefn* poGFldDefn =
+                poLayer->GetLayerDefn()->GetGeomFieldDefn(iGeom);
+            if( nGeomFieldCount == 1 &&
+                EQUAL(poGFldDefn->GetNameRef(), "")  && poGFldDefn->IsNullable() )
+                break;
+            printf( "Geometry Column ");
+            if( nGeomFieldCount > 1 )
+                printf("%d ", iGeom + 1);
+            if( !poGFldDefn->IsNullable() )
+                printf("NOT NULL ");
+            printf("= %s\n", poGFldDefn->GetNameRef() );
+        }
+
+        for( int iAttr = 0; iAttr < poDefn->GetFieldCount(); iAttr++ )
+        {
+            OGRFieldDefn    *poField = poDefn->GetFieldDefn( iAttr );
+            const char* pszType = (poField->GetSubType() != OFSTNone) ?
+                CPLSPrintf("%s(%s)",
+                           poField->GetFieldTypeName( poField->GetType() ),
+                           poField->GetFieldSubTypeName(poField->GetSubType())) :
+                poField->GetFieldTypeName( poField->GetType() );
+            printf( "%s: %s (%d.%d)",
+                    poField->GetNameRef(),
+                    pszType,
+                    poField->GetWidth(),
+                    poField->GetPrecision() );
+            if( !poField->IsNullable() )
+                printf(" NOT NULL");
+            if( poField->GetDefault() != NULL )
+                printf(" DEFAULT %s", poField->GetDefault() );
+            printf( "\n" );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Read, and dump features.                                        */
+/* -------------------------------------------------------------------- */
+    OGRFeature  *poFeature = NULL;
+    while( (poFeature = poLayer->GetNextFeature()) != NULL )
+    {
+        poFeature->DumpReadable( NULL );
+        OGRFeature::DestroyFeature( poFeature );
+    }
+}
+
+/************************************************************************/
+/*                                main()                                */
+/************************************************************************/
+
+#define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg) \
+    do { if (iArg + nExtraArg >= nArgc) \
+        Usage(CPLSPrintf("%s option requires %d argument(s)", papszArgv[iArg], \
+                nExtraArg)); \
+        } while(0)
+
+int main( int nArgc, char ** papszArgv )
+
+{
+    int bQuiet = FALSE;
+
+    const char *pszDataSource = NULL;
+
+    GNMGFID nFromFID = -1;
+    GNMGFID nToFID = -1;
+    int nK = 1;
+    const char *pszDataset = NULL;
+    const char *pszFormat = "ESRI Shapefile";
+    const char *pszLayer = NULL;
+    GNMNetwork *poDS = NULL;
+    OGRLayer* poResultLayer = NULL;
+    char  **papszDSCO = NULL, **papszLCO = NULL, **papszALO = NULL;
+
+    operation stOper = op_unknown;
+
+    int          nRet = 0;
+
+    // Check strict compilation and runtime library version as we use C++ API
+    if (! GDAL_CHECK_VERSION(papszArgv[0]))
+        exit(1);
+
+    EarlySetConfigOptions(nArgc, papszArgv);
+
+/* -------------------------------------------------------------------- */
+/*      Register format(s).                                             */
+/* -------------------------------------------------------------------- */
+    GDALAllRegister();
+
+/* -------------------------------------------------------------------- */
+/*      Processing command line arguments.                              */
+/* -------------------------------------------------------------------- */
+    nArgc = GDALGeneralCmdLineProcessor( nArgc, &papszArgv, GDAL_OF_GNM );
+
+    if( nArgc < 1 )
+    {
+        exit( -nArgc );
+    }
+
+
+
+    for( int iArg = 1; iArg < nArgc; iArg++ )
+    {
+        if( EQUAL(papszArgv[1], "--utility_version") )
+        {
+            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
+                    papszArgv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
+            CSLDestroy( papszArgv );
+            return 0;
+        }
+
+        else if( EQUAL(papszArgv[iArg],"--help") )
+        {
+            Usage();
+        }
+
+        else if ( EQUAL(papszArgv[iArg], "--long-usage") )
+        {
+            Usage(FALSE);
+        }
+
+        else if( EQUAL(papszArgv[iArg],"-q") || EQUAL(papszArgv[iArg],"-quiet") )
+        {
+            bQuiet = TRUE;
+        }
+
+        else if( EQUAL(papszArgv[iArg],"dijkstra") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2);
+            stOper = op_dijkstra;
+            nFromFID = atoi(papszArgv[++iArg]);
+            nToFID = atoi(papszArgv[++iArg]);
+        }
+
+        else if( EQUAL(papszArgv[iArg],"kpaths") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(3);
+            stOper = op_kpaths;
+            nFromFID = atoi(papszArgv[++iArg]);
+            nToFID = atoi(papszArgv[++iArg]);
+            nK = atoi(papszArgv[++iArg]);
+        }
+
+        else if( EQUAL(papszArgv[iArg],"resource") )
+        {
+            stOper = op_resource;
+        }
+
+        else if( EQUAL(papszArgv[iArg],"-ds") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszDataset = papszArgv[++iArg];
+        }
+
+        else if( EQUAL(papszArgv[iArg],"-f") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszFormat = papszArgv[++iArg];
+        }
+
+        else if( EQUAL(papszArgv[iArg],"-l") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszLayer = papszArgv[++iArg];
+        }
+        else if( EQUAL(papszArgv[iArg],"-dsco") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            papszDSCO = CSLAddString(papszDSCO, papszArgv[++iArg] );
+        }
+        else if( EQUAL(papszArgv[iArg],"-lco") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            papszLCO = CSLAddString(papszLCO, papszArgv[++iArg] );
+        }
+        else if( EQUAL(papszArgv[iArg],"-alo") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            papszALO = CSLAddString(papszALO, papszArgv[++iArg] );
+        }
+        else if( papszArgv[iArg][0] == '-' )
+        {
+            Usage(CPLSPrintf("Unknown option name '%s'", papszArgv[iArg]));
+        }
+
+        else if( pszDataSource == NULL )
+            pszDataSource = papszArgv[iArg];
+    }
+
+// do the work ////////////////////////////////////////////////////////////////
+
+    if(stOper == op_dijkstra)
+    {
+        if(pszDataSource == NULL)
+            Usage("No network dataset provided");
+
+        if(nFromFID == -1 || nToFID == -1)
+            Usage("Invalid input from or to identificators");
+
+        // open
+        poDS = (GNMNetwork*) GDALOpenEx( pszDataSource,
+                             GDAL_OF_UPDATE | GDAL_OF_GNM, NULL, NULL, NULL );
+        if(NULL == poDS)
+        {
+            fprintf( stderr, "\nFailed to open network at %s\n", pszDataSource);
+            nRet = 1;
+            goto exit;
+        }
+
+        poResultLayer = poDS->GetPath(nFromFID, nToFID, GATDijkstraShortestPath,
+                                      papszALO);
+        if(NULL == pszDataset)
+        {
+            ReportOnLayer(poResultLayer, bQuiet == FALSE);
+        }
+        else
+        {
+            if(CreateAndFillOutputDataset(poResultLayer, pszDataset, pszFormat,
+                                          pszLayer, papszDSCO, papszLCO, bQuiet)
+                    != OGRERR_NONE)
+            {
+                nRet = 1;
+                goto exit;
+            }
+        }
+    }
+    else if(stOper == op_kpaths)
+    {
+        if(pszDataSource == NULL)
+            Usage("No network dataset provided");
+
+        if(nFromFID == -1 || nToFID == -1)
+            Usage("Invalid input from or to identificators");
+
+        // open
+        poDS = (GNMNetwork*) GDALOpenEx( pszDataSource,
+                             GDAL_OF_UPDATE | GDAL_OF_GNM, NULL, NULL, NULL );
+        if(NULL == poDS)
+        {
+            fprintf( stderr, "\nFailed to open network at %s\n", pszDataSource);
+            nRet = 1;
+            goto exit;
+        }
+
+        if(CSLFindName(papszALO, GNM_MD_NUM_PATHS) == -1)
+        {
+            CPLDebug("GNM", "No K in options, add %d value", nK);
+            papszALO = CSLAddNameValue(papszALO, GNM_MD_NUM_PATHS,
+                                       CPLSPrintf("%d", nK));
+        }
+
+        poResultLayer = poDS->GetPath(nFromFID, nToFID, GATKShortestPath,
+                                      papszALO);
+
+        if(NULL == pszDataset)
+        {
+            ReportOnLayer(poResultLayer, bQuiet == FALSE);
+        }
+        else
+        {
+            if(CreateAndFillOutputDataset(poResultLayer, pszDataset, pszFormat,
+                                          pszLayer, papszDSCO, papszLCO, bQuiet)
+                    != OGRERR_NONE)
+            {
+                nRet = 1;
+                goto exit;
+            }
+        }
+    }
+    else if(stOper == op_resource)
+    {
+        if(pszDataSource == NULL)
+            Usage("No network dataset provided");
+
+        // open
+        poDS = (GNMNetwork*) GDALOpenEx( pszDataSource,
+                             GDAL_OF_UPDATE | GDAL_OF_GNM, NULL, NULL, NULL );
+        if(NULL == poDS)
+        {
+            fprintf( stderr, "\nFailed to open network at %s\n", pszDataSource);
+            nRet = 1;
+            goto exit;
+        }
+
+        poResultLayer = poDS->GetPath(nFromFID, nToFID, GATConnectedComponents,
+                                      papszALO);
+
+        if(NULL == pszDataset)
+        {
+            ReportOnLayer(poResultLayer, bQuiet == FALSE);
+        }
+        else
+        {
+            if(CreateAndFillOutputDataset(poResultLayer, pszDataset, pszFormat,
+                                          pszLayer, papszDSCO, papszLCO, bQuiet)
+                    != OGRERR_NONE)
+            {
+                nRet = 1;
+                goto exit;
+            }
+        }
+    }
+    else
+    {
+        printf("\nNeed an operation. See help what you can do with gnmanalyse:\n");
+        Usage();
+    }
+
+ exit:
+    CSLDestroy(papszDSCO);
+    CSLDestroy(papszLCO);
+    CSLDestroy(papszALO);
+    CSLDestroy( papszArgv );
+
+    if(poResultLayer != NULL)
+        poDS->ReleaseResultSet(poResultLayer);
+
+    if( poDS != NULL )
+        GDALClose( (GDALDatasetH)poDS );
+
+    GDALDestroyDriverManager();
+
+    return nRet;
+}
diff --git a/apps/gnmmanage.cpp b/apps/gnmmanage.cpp
new file mode 100755
index 0000000..7c52708
--- /dev/null
+++ b/apps/gnmmanage.cpp
@@ -0,0 +1,921 @@
+/******************************************************************************
+ * Project:  Geography Network utility
+ * Purpose:  To manage GNM networks
+ * Authors:  Mikhail Gusev, gusevmihs at gmail dot com
+ *           Dmitry Baryshnikov, polimax at mail.ru
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Mikhail Gusev
+ * Copyright (c) 2014-2015, NextGIS <info at nextgis.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gdal.h"
+#include "commonutils.h"
+#include "cpl_string.h"
+#include "gnm.h"
+
+//#include "ogr_p.h"
+//#include "gnm.h"
+//#include "gnm_api.h"
+
+CPL_CVSID("$Id$");
+
+enum operation
+{
+    op_unknown = 0, /** no operation */
+    op_info,        /** print information about network */
+    op_create,      /** create a new network */
+    op_import,      /** add a OGR layer to the network */
+    op_connect,     /** connect features from layers added to the network */
+    op_disconnect,  /** disconnect features from layers added to the network */
+    op_rule,        /** add connect rule */
+    op_autoconnect, /** try to connect features base on their tolerance */
+    op_delete,      /** delete network */
+    op_change_st    /** change vertex or edge blocking state */
+};
+
+/************************************************************************/
+/*                               Usage()                                */
+/************************************************************************/
+
+static void Usage(const char* pszAdditionalMsg, int bShort = TRUE) CPL_NO_RETURN;
+
+static void Usage(const char* pszAdditionalMsg, int bShort)
+{
+    printf("Usage: gnmmanage [--help][-q][-quiet][--long-usage]\n"
+           "                 [info]\n"
+           "                 [create [-f format_name] [-t_srs srs_name] [-dsco NAME=VALUE]... ]\n"
+           "                 [import src_dataset_name] [-l layer_name]\n"
+           "                 [connect gfid_src gfid_tgt gfid_con [-c cost] [-ic inv_cost] [-dir dir]]\n"
+           "                 [disconnect gfid_src gfid_tgt gfid_con]\n"
+           "                 [rule rule_str]\n"
+           "                 [autoconnect tolerance]\n"
+           "                 [delete]\n"
+           "                 [change [-bl gfid][-unbl gfid][-unblall]]\n"
+           "                 gnm_name [layer [layer ...]]\n");
+
+    if (bShort)
+    {
+        printf("\nNote: gnmmanage --long-usage for full help.\n");
+        if (pszAdditionalMsg)
+            fprintf(stderr, "\nFAILURE: %s\n", pszAdditionalMsg);
+        exit(1);
+    }
+
+    printf("\n   info: different information about network: system and class "
+           "layers, network metadata, network spatial reference\n"
+           "   create: create network\n"
+           "      -f format_name: output file format name, possible values are:\n");
+
+    int nGNMDriverCounter = 1;
+    for(int iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
+    {
+        GDALDriverH hDriver = GDALGetDriver(iDr);
+
+        const char *pszRFlag = "", *pszWFlag, *pszVirtualIO, *pszSubdatasets;
+        char** papszMD = GDALGetMetadata( hDriver, NULL );
+
+        if( CSLFetchBoolean( papszMD, GDAL_DCAP_RASTER, FALSE ) )
+            continue;
+        if( CSLFetchBoolean( papszMD, GDAL_DCAP_VECTOR, FALSE ) )
+            continue;
+
+        if( CSLFetchBoolean( papszMD, GDAL_DCAP_OPEN, FALSE ) )
+            pszRFlag = "r";
+
+        if( CSLFetchBoolean( papszMD, GDAL_DCAP_CREATE, FALSE ) )
+            pszWFlag = "w+";
+        else if( CSLFetchBoolean( papszMD, GDAL_DCAP_CREATECOPY, FALSE ) )
+            pszWFlag = "w";
+        else
+            pszWFlag = "o";
+
+        if( CSLFetchBoolean( papszMD, GDAL_DCAP_VIRTUALIO, FALSE ) )
+            pszVirtualIO = "v";
+        else
+            pszVirtualIO = "";
+
+        if( CSLFetchBoolean( papszMD, GDAL_DMD_SUBDATASETS, FALSE ) )
+            pszSubdatasets = "s";
+        else
+            pszSubdatasets = "";
+
+        printf( "          %d. %s (%s%s%s%s): %s\n",
+                nGNMDriverCounter++,
+                GDALGetDriverShortName( hDriver ),
+                pszRFlag, pszWFlag, pszVirtualIO, pszSubdatasets,
+                GDALGetDriverLongName( hDriver ) );
+    }
+
+    printf("      -t_srs srs_name: spatial reference input\n"
+           "      -dsco NAME=VALUE: network creation option set as pair=value\n"
+           "   import src_dataset_name: import external layer where src_dataset_name is a dataset name to copy from\n"
+           "      -l layer_name: layer name in dataset. If unset, 0 layer is copied\n"
+           "   connect gfid_src gfid_tgt gfid_con: make a topological connection, where the gfid_src and gfid_tgt are vertexes and gfid_con is edge (gfid_con can be -1, so the virtual connection will be created)\n"
+           "      -c cost -ic inv_cost -dir dir: manually assign the following values: the cost (weight), inverse cost and direction of the edge (optional)\n"
+           "   disconnect gfid_src gfid_tgt gfid_con: removes the connection from the graph\n"
+           "   rule rule_str: creates a rule in the network by the given rule_str string\n"
+           "   autoconnect tolerance: create topology automatically with the given double tolerance\n"
+           "   delete: delete network\n"
+           "   change: modify blocking state of vertices and edges ans save them in the network"
+           "   -bl gfid: block feature before the main operation. Blocking features are saved in the special layer\n"
+           "   -unbl gfid: unblock feature before the main operation\n"
+           "   -unblall: unblock all blocked features before the main operation\n"
+           "   gnm_name: the network to work with (path and name)\n"
+           );
+
+    if (pszAdditionalMsg)
+        fprintf(stderr, "\nFAILURE: %s\n", pszAdditionalMsg);
+
+    exit(1);
+}
+
+static void Usage(int bShort = TRUE)
+{
+    Usage(NULL, bShort);
+}
+
+
+/************************************************************************/
+/*                                main()                                */
+/************************************************************************/
+
+#define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg) \
+    do { if (iArg + nExtraArg >= nArgc) \
+        Usage(CPLSPrintf("%s option requires %d argument(s)", papszArgv[iArg], nExtraArg)); } while(0)
+
+int main( int nArgc, char ** papszArgv )
+
+{
+    int bQuiet = FALSE;
+    const char *pszFormat = NULL;
+    const char *pszSRS = NULL;
+    GNMGFID nSrcFID = -1;
+    GNMGFID nTgtFID = -1;
+    GNMGFID nConFID = -1;
+    double dfDirCost = 1.0;
+    double dfInvCost = 1.0;
+    GNMDirection eDir = GNM_EDGE_DIR_BOTH;
+    const char *pszRuleStr = "";
+    const char *pszDataSource = NULL;
+    char **papszDSCO = NULL;
+    const char *pszInputDataset = NULL;
+    const char *pszInputLayer = NULL;
+    double dfTolerance = 0.0001;
+    operation stOper = op_unknown;
+    char **papszLayers = NULL;
+    GNMNetwork *poDS = NULL;
+    std::vector<GNMGFID> anFIDsToBlock;
+    std::vector<GNMGFID> anFIDsToUnblock;
+    bool bUnblockAll = false;
+    int          nRet = 0;
+
+    // Check strict compilation and runtime library version as we use C++ API
+    if (! GDAL_CHECK_VERSION(papszArgv[0]))
+        exit(1);
+
+    EarlySetConfigOptions(nArgc, papszArgv);
+
+/* -------------------------------------------------------------------- */
+/*      Register format(s).                                             */
+/* -------------------------------------------------------------------- */
+    GDALAllRegister();
+
+/* -------------------------------------------------------------------- */
+/*      Processing command line arguments.                              */
+/* -------------------------------------------------------------------- */
+    nArgc = GDALGeneralCmdLineProcessor( nArgc, &papszArgv, GDAL_OF_GNM );
+
+    if( nArgc < 1 )
+    {
+        exit( -nArgc );
+    }
+
+    for( int iArg = 1; iArg < nArgc; iArg++ )
+    {
+        if( EQUAL(papszArgv[1], "--utility_version") )
+        {
+            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
+                    papszArgv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
+            CSLDestroy( papszArgv );
+            return 0;
+        }
+
+        else if( EQUAL(papszArgv[iArg],"--help") )
+        {
+            Usage();
+        }
+
+        else if ( EQUAL(papszArgv[iArg], "--long-usage") )
+        {
+            Usage(FALSE);
+        }
+
+        else if( EQUAL(papszArgv[iArg],"-q") || EQUAL(papszArgv[iArg],"-quiet") )
+        {
+            bQuiet = TRUE;
+        }
+
+        else if ( EQUAL(papszArgv[iArg],"info") )
+        {
+            stOper = op_info;
+        }
+
+        else if( EQUAL(papszArgv[iArg],"-f") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszFormat = papszArgv[++iArg];
+        }
+
+        else if( EQUAL(papszArgv[iArg],"-dsco") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            papszDSCO = CSLAddString(papszDSCO, papszArgv[++iArg] );
+        }
+
+        else if( EQUAL(papszArgv[iArg],"create") )
+        {
+            stOper = op_create;
+        }
+
+        else if( EQUAL(papszArgv[iArg],"-t_srs") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszSRS = papszArgv[++iArg];
+        }
+
+        else if( EQUAL(papszArgv[iArg],"import") )
+        {
+            stOper = op_import;
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszInputDataset = papszArgv[++iArg];
+        }
+
+        else if( EQUAL(papszArgv[iArg],"-l") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszInputLayer = papszArgv[++iArg];
+        }
+
+        else if( EQUAL(papszArgv[iArg],"connect") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(3);
+            stOper = op_connect;
+            nSrcFID = atoi(papszArgv[++iArg]);
+            nTgtFID = atoi(papszArgv[++iArg]);
+            nConFID = atoi(papszArgv[++iArg]);
+        }
+
+        else if( EQUAL(papszArgv[iArg],"-c") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            dfDirCost = CPLAtofM(papszArgv[++iArg]);
+        }
+        else if( EQUAL(papszArgv[iArg],"-ic") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            dfInvCost = CPLAtofM(papszArgv[++iArg]);
+        }
+        else if( EQUAL(papszArgv[iArg],"-dir") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            eDir = atoi(papszArgv[++iArg]);
+        }
+
+        else if( EQUAL(papszArgv[iArg],"disconnect") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(3);
+            stOper = op_disconnect;
+            nSrcFID = atoi(papszArgv[++iArg]);
+            nTgtFID = atoi(papszArgv[++iArg]);
+            nConFID = atoi(papszArgv[++iArg]);
+        }
+
+        else if ( EQUAL(papszArgv[iArg],"autoconnect") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            stOper = op_autoconnect;
+            dfTolerance = CPLAtofM(papszArgv[++iArg]);
+        }
+
+        else if ( EQUAL(papszArgv[iArg],"rule") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            stOper = op_rule;
+            pszRuleStr = papszArgv[++iArg];
+        }
+
+        else if ( EQUAL(papszArgv[iArg],"delete") )
+        {
+            stOper = op_delete;
+        }
+
+        else if( EQUAL(papszArgv[iArg],"change") )
+        {
+            stOper = op_change_st;
+        }
+
+        else if( EQUAL(papszArgv[iArg],"-bl") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            anFIDsToBlock.push_back(atoi(papszArgv[++iArg]));
+        }
+
+        else if( EQUAL(papszArgv[iArg],"-unbl") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            anFIDsToUnblock.push_back(atoi(papszArgv[++iArg]));
+        }
+
+        else if( EQUAL(papszArgv[iArg],"-unblall") )
+        {
+            bUnblockAll = true;
+        }
+
+        else if( papszArgv[iArg][0] == '-' )
+        {
+            Usage(CPLSPrintf("Unknown option name '%s'", papszArgv[iArg]));
+        }
+
+        else if( pszDataSource == NULL )
+            pszDataSource = papszArgv[iArg];
+        else
+            papszLayers = CSLAddString( papszLayers, papszArgv[iArg] );
+    }
+
+// do the work ////////////////////////////////////////////////////////////////
+
+    if(stOper == op_info)
+    {
+        if(pszDataSource == NULL)
+            Usage("No network dataset provided");
+
+        //TODO for output:
+        // stats about graph and blocked features
+
+        // open
+
+        poDS = (GNMNetwork*) GDALOpenEx( pszDataSource, GDAL_OF_READONLY |
+                                    GDAL_OF_GNM, NULL, NULL, NULL );
+
+        GDALDriver         *poDriver = NULL;
+        if( poDS != NULL )
+            poDriver = poDS->GetDriver();
+
+        if( poDS == NULL )
+        {
+            fprintf(stderr, "FAILURE:\nUnable to open datasource `%s'.\n",
+                    pszDataSource);
+            exit(1);
+        }
+
+        CPLAssert( poDriver != NULL);
+
+        printf( "INFO: Open of `%s'\n      using driver `%s' successful.\n",
+                    pszDataSource, poDriver->GetDescription() );
+
+        // Report projection.
+        int nMajor = poDS->GetVersion() / 100;
+        printf( "Network version: %d.%d.\n", nMajor,
+                                            poDS->GetVersion() - nMajor * 100 );
+        const char* pszName = poDS->GetName();
+        if(NULL != pszName)
+            printf( "Network name: %s.\n", pszName );
+        const char* pszDescript = poDS->GetDescription();
+        if(NULL != pszDescript)
+            printf( "Network description: %s.\n", pszDescript );
+
+        char *pszProjection = (char*)poDS->GetProjectionRef();
+        OGRSpatialReferenceH hSRS = OSRNewSpatialReference(NULL);
+        if( OSRImportFromWkt( hSRS, &pszProjection ) == CE_None )
+        {
+            char *pszPrettyWkt = NULL;
+            OSRExportToPrettyWkt( hSRS, &pszPrettyWkt, FALSE );
+
+            printf( "Coordinate System is:\n%s\n", pszPrettyWkt );
+            CPLFree( pszPrettyWkt );
+        }
+        else
+        {
+            printf( "Coordinate System is '%s'\n", pszProjection );
+        }
+        OSRDestroySpatialReference(hSRS);
+
+        // report layers
+        if(poDS->GetLayerCount() > 0)
+        {
+            printf("\nNetwork\'s layers: \n");
+            for (int iLayer = 0; iLayer < poDS->GetLayerCount(); iLayer++)
+            {
+                OGRLayer *poLayer = poDS->GetLayer(iLayer);
+
+                if (poLayer != NULL)
+                {
+                    printf("  %d: %s", iLayer + 1, poLayer->GetName());
+
+                    int nGeomFieldCount = poLayer->GetLayerDefn()->GetGeomFieldCount();
+                    if (nGeomFieldCount > 1)
+                    {
+                        printf(" (");
+                        for (int iGeom = 0; iGeom < nGeomFieldCount; iGeom++)
+                        {
+                            if (iGeom > 0)
+                                printf(", ");
+                            OGRGeomFieldDefn* poGFldDefn =
+                                poLayer->GetLayerDefn()->GetGeomFieldDefn(iGeom);
+                            printf("%s", OGRGeometryTypeToName( poGFldDefn->GetType()) );
+                        }
+                        printf(")");
+                    }
+                    else if (poLayer->GetGeomType() != wkbUnknown)
+                        printf(" (%s)", OGRGeometryTypeToName( poLayer->GetGeomType()) );
+
+                    printf("\n");
+                }
+            }
+        }
+
+        // report rules
+        GNMGenericNetwork* poGenericNetwork =
+                                         dynamic_cast<GNMGenericNetwork*>(poDS);
+
+        if(NULL != poGenericNetwork)
+        {
+            CPLStringList oList(poGenericNetwork->GetRules());
+            if(oList.Count() > 0)
+            {
+                printf("\nNetwork\'s rules: \n");
+                for(int iRule = 0; iRule < oList.Count(); ++iRule)
+                {
+                    printf("  %d: %s\n", iRule + 1, oList[iRule]);
+                }
+            }
+        }
+
+    }
+    else if(stOper == op_create)
+    {
+        const char* pszPath;
+        const char* pszNetworkName = CSLFetchNameValue(papszDSCO, GNM_MD_NAME);
+
+        if(pszDataSource == NULL)
+            Usage("No network dataset provided");
+
+        //the DSCO have priority on input keys
+        if(NULL == pszNetworkName)
+        {
+            pszPath = CPLGetPath(pszDataSource);
+            pszNetworkName = CPLGetBasename(pszDataSource);
+            papszDSCO = CSLAddNameValue(papszDSCO, GNM_MD_NAME, pszNetworkName);
+        }
+        else
+        {
+            pszPath = pszDataSource;
+        }
+
+        if( pszNetworkName == NULL)
+            Usage("No dataset name provided");
+
+        const char* pszFinalSRS = CSLFetchNameValue(papszDSCO, GNM_MD_SRS);
+        if(NULL == pszFinalSRS)
+        {
+            pszFinalSRS = pszSRS;
+            papszDSCO = CSLAddNameValue(papszDSCO, GNM_MD_SRS, pszSRS);
+        }
+
+        if(NULL == pszFinalSRS)
+            Usage("No spatial reference provided");
+        if( pszFormat == NULL )
+            Usage("No output format provided");
+
+        GDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName(pszFormat);
+        if( poDriver == NULL )
+        {
+            Usage( CPLSPrintf("%s driver not available", pszFormat) );
+        }
+
+        char** papszMD = poDriver->GetMetadata();
+
+        if( !CSLFetchBoolean( papszMD, GDAL_DCAP_GNM, FALSE ) )
+            Usage("not a GNM driver");
+
+        poDS = (GNMNetwork*) poDriver->Create( pszPath, 0, 0, 0, GDT_Unknown,
+                                              papszDSCO );
+
+        if (NULL == poDS)
+        {
+            fprintf(stderr, "\nFAILURE: Failed to create network in a new dataset at "
+                    "%s and with driver %s\n", CPLFormFilename(pszPath,
+                    pszNetworkName, NULL) ,pszFormat);
+            nRet = 1;
+        }
+        else
+        {
+            if (bQuiet == FALSE)
+                printf("\nNetwork created successfully in a "
+                   "new dataset at %s\n", CPLFormFilename(pszPath,
+                    pszNetworkName, NULL));
+        }
+
+    }
+    else if(stOper == op_import)
+    {
+        if(pszDataSource == NULL)
+            Usage("No network dataset provided");
+
+        if(pszInputDataset == NULL)
+            Usage("No input dataset name provided");
+
+
+        // open
+        poDS = (GNMNetwork*) GDALOpenEx( pszDataSource,
+                             GDAL_OF_READONLY | GDAL_OF_GNM, NULL, NULL, NULL );
+
+        if(NULL == poDS)
+        {
+            printf("\nFailed to open network at %s\n",pszDataSource);
+            goto exit;
+        }
+
+        GDALDataset *poSrcDS = (GDALDataset*) GDALOpenEx(pszInputDataset,
+                          GDAL_OF_VECTOR | GDAL_OF_READONLY, NULL, NULL, NULL );
+        if(NULL == poSrcDS)
+        {
+            fprintf(stderr, "\nFAILURE: Can not open dataset at %s\n",
+                            pszInputDataset);
+
+            nRet = 1;
+            goto exit;
+        }
+
+        OGRLayer *poSrcLayer;
+        if (pszInputLayer != NULL)
+            poSrcLayer = poSrcDS->GetLayerByName(pszInputLayer);
+        else
+            poSrcLayer = poSrcDS->GetLayer(0);
+
+        if (NULL == poSrcLayer)
+        {
+            if (pszInputLayer != NULL)
+                fprintf(stderr, "\nFAILURE: Can not open layer %s in %s\n",
+                    pszInputLayer,pszInputDataset);
+            else
+                fprintf(stderr, "\nFAILURE: Can not open layer in %s\n",
+                pszInputDataset);
+
+            GDALClose(poSrcDS);
+
+            nRet = 1;
+            goto exit;
+        }
+
+        OGRLayer * poLayer = poDS->CopyLayer(poSrcLayer, poSrcLayer->GetName());
+        if (NULL == poLayer)
+        {
+            if (pszInputLayer != NULL)
+                fprintf(stderr, "\nFAILURE: Can not copy layer %s from %s\n",
+                    pszInputLayer,pszInputDataset);
+            else
+                fprintf(stderr, "\nFAILURE: Can not copy layer from %s\n",
+                pszInputDataset);
+            GDALClose(poSrcDS);
+
+            nRet = 1;
+            goto exit;
+        }
+
+        if (bQuiet == FALSE)
+        {
+            if (pszInputLayer != NULL)
+                printf("\nLayer %s successfully copied from %s and added to the network at %s\n",
+                pszInputLayer, pszInputDataset, pszDataSource);
+            else
+                printf("\nLayer successfully copied from %s and added to the network at %s\n",
+                pszInputDataset, pszDataSource);
+        }
+
+        GDALClose(poSrcDS);
+    }
+    else if (stOper == op_connect)
+    {
+        if(pszDataSource == NULL)
+            Usage("No network dataset provided");
+
+        // open
+        poDS = (GNMNetwork*) GDALOpenEx( pszDataSource,
+                             GDAL_OF_UPDATE | GDAL_OF_GNM, NULL, NULL, NULL );
+
+        if(NULL == poDS)
+        {
+            fprintf( stderr, "\nFailed to open network at %s\n", pszDataSource);
+            nRet = 1;
+            goto exit;
+        }
+
+        GNMGenericNetwork* poGenericNetwork =
+                                         dynamic_cast<GNMGenericNetwork*>(poDS);
+
+        if(NULL == poGenericNetwork)
+        {
+            fprintf( stderr, "\nUnsupported datasource type for this operation\n");
+            nRet = 1;
+            goto exit;
+        }
+
+        if(poGenericNetwork->ConnectFeatures(nSrcFID, nTgtFID, nConFID,
+                            dfDirCost, dfInvCost, eDir) != CE_None )
+        {
+            fprintf( stderr, "Failed to connect features\n" );
+            nRet = 1;
+            goto exit;
+        }
+
+        if (bQuiet == FALSE)
+        {
+            printf("Features connected successfully\n");
+        }
+    }
+    else if (stOper == op_disconnect)
+    {
+        if(pszDataSource == NULL)
+            Usage("No network dataset provided");
+
+        // open
+        poDS = (GNMNetwork*) GDALOpenEx( pszDataSource,
+                             GDAL_OF_UPDATE | GDAL_OF_GNM, NULL, NULL, NULL );
+
+        if(NULL == poDS)
+        {
+            fprintf( stderr, "\nFailed to open network at %s\n", pszDataSource);
+            nRet = 1;
+            goto exit;
+        }
+
+        GNMGenericNetwork* poGenericNetwork =
+                                         dynamic_cast<GNMGenericNetwork*>(poDS);
+
+        if(NULL == poGenericNetwork)
+        {
+            fprintf( stderr, "\nUnsupported datasource type for this operation\n");
+            nRet = 1;
+            goto exit;
+        }
+
+        if(poGenericNetwork->DisconnectFeatures(nSrcFID, nTgtFID, nConFID)
+                != CE_None )
+        {
+            fprintf( stderr, "Failed to disconnect features\n" );
+            nRet = 1;
+            goto exit;
+        }
+
+        if (bQuiet == FALSE)
+        {
+            printf("Features disconnected successfully\n");
+        }
+    }
+    else if (stOper == op_rule)
+    {
+        if(pszDataSource == NULL)
+            Usage("No network dataset provided");
+
+        // open
+        poDS = (GNMNetwork*) GDALOpenEx( pszDataSource,
+                             GDAL_OF_UPDATE | GDAL_OF_GNM, NULL, NULL, NULL );
+
+        if(NULL == poDS)
+        {
+            fprintf( stderr, "\nFailed to open network at %s\n", pszDataSource);
+            nRet = 1;
+            goto exit;
+        }
+
+        GNMGenericNetwork* poGenericNetwork =
+                                         dynamic_cast<GNMGenericNetwork*>(poDS);
+
+        if(NULL == poGenericNetwork)
+        {
+            fprintf( stderr, "\nUnsupported datasource type for this operation\n");
+            nRet = 1;
+            goto exit;
+        }
+
+        if(poGenericNetwork->CreateRule(pszRuleStr) != CE_None )
+        {
+            fprintf( stderr, "Failed to create rule %s\n", pszRuleStr );
+            nRet = 1;
+            goto exit;
+        }
+
+        if (bQuiet == FALSE)
+        {
+            printf("Create rule '%s' successfully\n", pszRuleStr);
+        }
+    }
+    else if (stOper == op_autoconnect)
+    {
+        if(pszDataSource == NULL)
+            Usage("No network dataset provided");
+
+        // open
+        poDS = (GNMNetwork*) GDALOpenEx( pszDataSource,
+                             GDAL_OF_UPDATE | GDAL_OF_GNM, NULL, NULL, NULL );
+
+        if(NULL == poDS)
+        {
+            fprintf( stderr, "\nFailed to open network at %s\n", pszDataSource);
+            nRet = 1;
+            goto exit;
+        }
+
+        GNMGenericNetwork* poGenericNetwork =
+                                         dynamic_cast<GNMGenericNetwork*>(poDS);
+
+        if(NULL == poGenericNetwork)
+        {
+            fprintf( stderr, "\nUnsupported datasource type for this operation\n");
+            nRet = 1;
+            goto exit;
+        }
+
+        if(CSLCount(papszLayers) == 0 && poDS->GetLayerCount() > 1)
+        {
+            if(bQuiet == FALSE)
+            {
+                printf("No layers provided. Use all layers of network:\n");
+            }
+
+            for(int i = 0; i < poDS->GetLayerCount(); ++i)
+            {
+                OGRLayer* poLayer = poDS->GetLayer(i);
+                if(bQuiet == FALSE)
+                {
+                    printf("%d. %s\n", i + 1, poLayer->GetName());
+                }
+                papszLayers = CSLAddString(papszLayers, poLayer->GetName() );
+            }
+        }
+
+        if(poGenericNetwork->ConnectPointsByLines(papszLayers, dfTolerance,
+                                        dfDirCost, dfInvCost, eDir) != CE_None )
+        {
+            fprintf( stderr, "Failed to autoconnect features\n" );
+            nRet = 1;
+            goto exit;
+        }
+
+        if (bQuiet == FALSE)
+        {
+            printf("Features connected successfully\n");
+        }
+
+    }
+    else if(stOper == op_delete)
+    {
+        if(pszDataSource == NULL)
+            Usage("No network dataset provided");
+
+        // open
+        poDS = (GNMNetwork*) GDALOpenEx( pszDataSource,
+                             GDAL_OF_UPDATE | GDAL_OF_GNM, NULL, NULL, NULL );
+
+        if(NULL == poDS)
+        {
+            fprintf( stderr, "\nFailed to open network at %s\n", pszDataSource);
+            nRet = 1;
+            goto exit;
+        }
+
+        if( poDS->Delete() != CE_None )
+        {
+            fprintf( stderr, "Delete failed.\n" );
+            nRet = 1;
+            goto exit;
+        }
+
+        if (bQuiet == FALSE)
+        {
+            printf("Delete successfully\n");
+        }
+
+       /** if hDriver == NULL this code delete everything in folder,
+        *  not only GNM files
+
+        GDALDriverH hDriver = NULL;
+        if( pszFormat != NULL )
+        {
+            hDriver = GDALGetDriverByName( pszFormat );
+            if( hDriver == NULL )
+            {
+                fprintf( stderr, "Unable to find driver named '%s'.\n",
+                         pszFormat );
+                exit( 1 );
+            }
+        }
+        GDALDeleteDataset( hDriver, pszDataSource );
+        */
+    }
+    else if(stOper == op_change_st)
+    {
+        if(pszDataSource == NULL)
+            Usage("No dataset in input");
+
+        // open
+        poDS = (GNMNetwork*) GDALOpenEx( pszDataSource,
+                             GDAL_OF_UPDATE | GDAL_OF_GNM, NULL, NULL, NULL );
+
+        if(NULL == poDS)
+        {
+            fprintf( stderr, "\nFailed to open network at %s\n", pszDataSource);
+            nRet = 1;
+            goto exit;
+        }
+
+        GNMGenericNetwork* poGenericNetwork =
+                                         dynamic_cast<GNMGenericNetwork*>(poDS);
+
+        if(NULL == poGenericNetwork)
+        {
+            fprintf( stderr, "\nUnsupported datasource type for this operation\n");
+            nRet = 1;
+            goto exit;
+        }
+
+        if(bUnblockAll)
+        {
+            if(poGenericNetwork->ChangeAllBlockState(false) != CE_None)
+            {
+                fprintf( stderr, "\nChange all block state failed\n");
+                nRet = 1;
+                goto exit;
+            }
+        }
+        else
+        {
+            size_t i;
+            for(i = 0; i < anFIDsToBlock.size(); ++i)
+            {
+                if(poGenericNetwork->ChangeBlockState(anFIDsToBlock[i], true)
+                        != CE_None)
+                {
+                    fprintf( stderr, "\nChange block state of id "
+                                     GNMGFIDFormat " failed\n", anFIDsToBlock[i]);
+                    nRet = 1;
+                    goto exit;
+                }
+            }
+
+            for(i = 0; i < anFIDsToUnblock.size(); ++i)
+            {
+                if(poGenericNetwork->ChangeBlockState(anFIDsToUnblock[i], false)
+                        != CE_None)
+                {
+                    fprintf( stderr, "\nChange block state of id "
+                                     GNMGFIDFormat " failed\n", anFIDsToBlock[i]);
+                    nRet = 1;
+                    goto exit;
+                }
+            }
+        }
+
+        if (bQuiet == FALSE)
+        {
+            printf("Change block state successfully\n");
+        }
+    }
+    else
+    {
+        printf("\nNeed an operation. See help what you can do with gnmmanage:\n");
+        Usage();
+    }
+
+exit:
+    CSLDestroy( papszArgv );
+    CSLDestroy( papszDSCO );
+    CSLDestroy( papszLayers );
+
+    if( poDS != NULL )
+        GDALClose( (GDALDatasetH)poDS );
+
+    GDALDestroyDriverManager();
+
+    return nRet;
+}
diff --git a/apps/makefile.vc b/apps/makefile.vc
index 78b564b..80f7d5f 100644
--- a/apps/makefile.vc
+++ b/apps/makefile.vc
@@ -7,6 +7,8 @@ LIBS	=	$(GDAL_ROOT)\gdal_i.lib
 
 XTRAFLAGS =	-I..\gcore -I..\port -I..\frmts\vrt -I..\alg -I..\ogr -I..\ogr\ogrsf_frmts  $(GEOS_CFLAGS) -I..\ogr\ogrsf_frmts\geojson\libjson -I..\ogr\ogrsf_frmts\geojson
 
+EXTRAFLAGS =    -I..\frmts\vrt -I..\ogr\ogrsf_frmts\geojson\libjson -I..\ogr\ogrsf_frmts\geojson
+
 !INCLUDE ..\nmake.opt
 
 !IFDEF INCLUDE_OGR_FRMTS
@@ -15,17 +17,26 @@ OGR_PROGRAMS =	gdal_contour.exe gdaltindex.exe gdal_rasterize.exe \
 		gdalbuildvrt.exe testepsg.exe
 !ENDIF
 
+!IFDEF INCLUDE_GNM_FRMTS
+GNM_PROGRAMS =	gnmmanage.exe gnmanalyse.exe
+!ENDIF
+
+
 default:	gdal_translate.exe gdalinfo.exe gdalserver.exe gdaladdo.exe gdalwarp.exe \
 		nearblack.exe gdalmanage.exe gdalenhance.exe gdaltransform.exe\
-		gdaldem.exe gdallocationinfo.exe gdalsrsinfo.exe $(OGR_PROGRAMS)
+		gdaldem.exe gdallocationinfo.exe gdalsrsinfo.exe $(OGR_PROGRAMS) $(GNM_PROGRAMS)
 
 all:	default multireadtest.exe \
 			dumpoverviews.exe gdalwarpsimple.exe gdalflattenmask.exe \
 			gdaltorture.exe gdal2ogr.exe test_ogrsf.exe
+OBJ = commonutils.obj gdalinfo_lib.obj gdal_translate_lib.obj gdalwarp_lib.obj ogr2ogr_lib.obj \
+	gdaldem_lib.obj nearblack_lib.obj gdal_grid_lib.obj gdal_rasterize_lib.obj gdalbuildvrt_lib.obj
 
-gdalinfo.exe:	gdalinfo.c commonutils.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gdalinfo.c commonutils.cpp $(XTRAOBJ) $(LIBS) \
-		/link $(LINKER_FLAGS)
+appslib: $(OBJ)
+
+gdalinfo.exe:	gdalinfo_bin.cpp $(GDALLIB) $(XTRAOBJ) 
+	$(CC) $(XTRAFLAGS) $(CFLAGS) gdalinfo_bin.cpp $(XTRAOBJ) $(LIBS) \
+		/Fe$@ /link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 	
 gdalserver.exe:	gdalserver.c $(GDALLIB) $(XTRAOBJ) 
@@ -33,9 +44,9 @@ gdalserver.exe:	gdalserver.c $(GDALLIB) $(XTRAOBJ)
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 	
-gdal_translate.exe:	gdal_translate.cpp commonutils.cpp $(GDALLIB) $(XTRAOBJ)
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gdal_translate.cpp commonutils.cpp $(XTRAOBJ) $(LIBS) \
-		/link $(LINKER_FLAGS)
+gdal_translate.exe:	gdal_translate_bin.cpp $(GDALLIB) $(XTRAOBJ)
+	$(CC) $(XTRAFLAGS) $(CFLAGS) gdal_translate_bin.cpp $(XTRAOBJ) $(LIBS) \
+		/Fe$@ /link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 	
 gdaladdo.exe:	gdaladdo.cpp $(GDALLIB) $(XTRAOBJ)
@@ -58,14 +69,14 @@ gdallocationinfo.exe:	gdallocationinfo.cpp $(GDALLIB) $(XTRAOBJ)
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 	
-gdalsrsinfo.exe:	gdalsrsinfo.cpp commonutils.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gdalsrsinfo.cpp commonutils.cpp $(XTRAOBJ) $(LIBS) \
+gdalsrsinfo.exe:	gdalsrsinfo.cpp $(GDALLIB) $(XTRAOBJ) 
+	$(CC) $(XTRAFLAGS) $(CFLAGS) gdalsrsinfo.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 	
-gdalwarp.exe:	gdalwarp.cpp commonutils.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gdalwarp.cpp commonutils.cpp $(XTRAOBJ) $(LIBS) \
-		/link $(LINKER_FLAGS)
+gdalwarp.exe:	gdalwarp_bin.cpp $(GDALLIB) $(XTRAOBJ) 
+	$(CC) $(XTRAFLAGS) $(CFLAGS) gdalwarp_bin.cpp $(XTRAOBJ) $(LIBS) \
+		/Fe$@ /link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 	
 gdal_contour.exe:	gdal_contour.cpp $(GDALLIB) $(XTRAOBJ) 
@@ -73,24 +84,24 @@ gdal_contour.exe:	gdal_contour.cpp $(GDALLIB) $(XTRAOBJ)
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 	
-nearblack.exe:	nearblack.cpp commonutils.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) nearblack.cpp commonutils.cpp $(XTRAOBJ) $(LIBS) \
-		/link $(LINKER_FLAGS)
+nearblack.exe:	nearblack_bin.cpp $(GDALLIB) $(XTRAOBJ) 
+	$(CC) $(XTRAFLAGS) $(CFLAGS) nearblack_bin.cpp $(XTRAOBJ) $(LIBS) \
+		/Fe$@ /link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 	
-gdalenhance.exe:	gdalenhance.cpp commonutils.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gdalenhance.cpp commonutils.cpp $(XTRAOBJ) $(LIBS) \
+gdalenhance.exe:	gdalenhance.cpp $(GDALLIB) $(XTRAOBJ) 
+	$(CC) $(XTRAFLAGS) $(CFLAGS) gdalenhance.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 	
-gdaldem.exe:	gdaldem.cpp commonutils.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gdaldem.cpp commonutils.cpp $(XTRAOBJ) $(LIBS) \
-		/link $(LINKER_FLAGS)
+gdaldem.exe:	gdaldem_bin.cpp $(GDALLIB) $(XTRAOBJ) 
+	$(CC) $(XTRAFLAGS) $(CFLAGS) gdaldem_bin.cpp $(XTRAOBJ) $(LIBS) \
+		/Fe$@ /link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 	
-gdal_grid.exe:	gdal_grid.cpp commonutils.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gdal_grid.cpp commonutils.cpp $(XTRAOBJ) $(LIBS) \
-		/link $(LINKER_FLAGS)
+gdal_grid.exe:	gdal_grid_bin.cpp $(GDALLIB) $(XTRAOBJ) 
+	$(CC) $(XTRAFLAGS) $(CFLAGS) gdal_grid_bin.cpp $(XTRAOBJ) $(LIBS) \
+		/Fe$@ /link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 
 gdalmanage.exe:	gdalmanage.cpp $(GDALLIB) $(XTRAOBJ) 
@@ -103,9 +114,9 @@ gdaltindex.exe:	gdaltindex.c $(GDALLIB) $(XTRAOBJ)
 		$(XTRAOBJ) $(LIBS) /link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 	
-gdal_rasterize.exe:	gdal_rasterize.cpp commonutils.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gdal_rasterize.cpp commonutils.cpp $(XTRAOBJ) $(LIBS) \
-		/link $(LINKER_FLAGS)
+gdal_rasterize.exe:	gdal_rasterize_bin.cpp $(GDALLIB) $(XTRAOBJ) 
+	$(CC) $(XTRAFLAGS) $(CFLAGS) gdal_rasterize_bin.cpp $(XTRAOBJ) $(LIBS) \
+		/Fe$@ /link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 
 multireadtest.exe:	multireadtest.cpp $(GDALLIB) $(XTRAOBJ) 
@@ -123,13 +134,13 @@ testreprojmulti.exe:	testreprojmulti.cpp $(GDALLIB) $(XTRAOBJ)
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 	
-ogr2ogr.exe:	ogr2ogr.cpp commonutils.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) ogr2ogr.cpp commonutils.cpp $(XTRAOBJ) $(LIBS) \
-		/link $(LINKER_FLAGS)
+ogr2ogr.exe:	ogr2ogr_bin.cpp $(GDALLIB) $(XTRAOBJ) 
+	$(CC) $(XTRAFLAGS) $(CFLAGS) ogr2ogr_bin.cpp $(XTRAOBJ) $(LIBS) \
+		/Fe$@ /link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 	
-ogrinfo.exe:	ogrinfo.cpp commonutils.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) ogrinfo.cpp commonutils.cpp $(XTRAOBJ) $(LIBS) \
+ogrinfo.exe:	ogrinfo.cpp $(GDALLIB) $(XTRAOBJ) 
+	$(CC) $(XTRAFLAGS) $(CFLAGS) ogrinfo.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 	
@@ -138,8 +149,8 @@ ogrtindex.exe:	ogrtindex.cpp $(GDALLIB) $(XTRAOBJ)
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 
-ogrlineref.exe:	ogrlineref.cpp commonutils.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) ogrlineref.cpp commonutils.cpp $(XTRAOBJ) $(LIBS) \
+ogrlineref.exe:	ogrlineref.cpp $(GDALLIB) $(XTRAOBJ) 
+	$(CC) $(XTRAFLAGS) $(CFLAGS) ogrlineref.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 	
@@ -148,14 +159,14 @@ testepsg.exe:	testepsg.cpp $(GDALLIB) $(XTRAOBJ)
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 	
-test_ogrsf.exe:	test_ogrsf.cpp commonutils.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) test_ogrsf.cpp commonutils.cpp $(XTRAOBJ) $(LIBS) \
+test_ogrsf.exe:	test_ogrsf.cpp $(GDALLIB) $(XTRAOBJ) 
+	$(CC) $(XTRAFLAGS) $(CFLAGS) test_ogrsf.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 	
-gdalbuildvrt.exe:	gdalbuildvrt.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gdalbuildvrt.cpp $(XTRAOBJ) $(LIBS) \
-		/link $(LINKER_FLAGS)
+gdalbuildvrt.exe:	gdalbuildvrt_bin.cpp $(GDALLIB) $(XTRAOBJ) 
+	$(CC) $(XTRAFLAGS) $(CFLAGS) gdalbuildvrt_bin.cpp $(XTRAOBJ) $(LIBS) \
+		/Fe$@ /link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 	
 dumpoverviews.exe:	dumpoverviews.cpp $(GDALLIB) $(XTRAOBJ) 
@@ -177,6 +188,16 @@ gdal2ogr.exe:	gdal2ogr.c $(GDALLIB) $(XTRAOBJ)
 	$(CC) $(XTRAFLAGS) $(CFLAGS) gdal2ogr.c $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
+    
+gnmmanage.exe:	gnmmanage.cpp $(GDALLIB) $(XTRAOBJ) 
+	$(CC) $(XTRAFLAGS) $(CFLAGS) gnmmanage.cpp $(XTRAOBJ) $(LIBS) \
+		/link $(LINKER_FLAGS)
+	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1	
+
+gnmanalyse.exe:	gnmanalyse.cpp $(GDALLIB) $(XTRAOBJ) 
+	$(CC) $(XTRAFLAGS) $(CFLAGS) gnmanalyse.cpp $(XTRAOBJ) $(LIBS) \
+		/link $(LINKER_FLAGS)
+	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 	
 clean:
 	-del *.obj
diff --git a/apps/multireadtest.cpp b/apps/multireadtest.cpp
index d34d61d..74c1f2b 100644
--- a/apps/multireadtest.cpp
+++ b/apps/multireadtest.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: multireadtest.cpp 28459 2015-02-12 13:48:21Z rouault $
+ * $Id: multireadtest.cpp 33615 2016-03-02 20:19:22Z goatbar $
  *
  * Project:  GDAL Utilities
- * Purpose:  Multithreading test application.
+ * Purpose:  Multi-threading test application.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -32,7 +32,7 @@
 #include "cpl_multiproc.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: multireadtest.cpp 28459 2015-02-12 13:48:21Z rouault $");
+CPL_CVSID("$Id: multireadtest.cpp 33615 2016-03-02 20:19:22Z goatbar $");
 
 static int nThreadCount = 4, nIterations = 1, bLockOnOpen = TRUE;
 static int nOpenIterations = 1;
@@ -87,7 +87,7 @@ int main( int argc, char ** argv )
             pszFilename = argv[iArg];
         else
         {
-            printf( "Unrecognised argument: %s\n", argv[iArg] );
+            printf( "Unrecognized argument: %s\n", argv[iArg] );
             Usage();
         }
     }
@@ -112,14 +112,14 @@ int main( int argc, char ** argv )
     if( hDS == NULL )
         exit( 1 );
 
-    nChecksum = GDALChecksumImage( GDALGetRasterBand( hDS, 1 ), 
-                                   0, 0, 
-                                   GDALGetRasterXSize( hDS ), 
+    nChecksum = GDALChecksumImage( GDALGetRasterBand( hDS, 1 ),
+                                   0, 0,
+                                   GDALGetRasterXSize( hDS ),
                                    GDALGetRasterYSize( hDS ) );
-    
+
     GDALClose( hDS );
 
-    printf( "Got checksum %d, launching %d worker threads on %s, %d iterations.\n", 
+    printf( "Got checksum %d, launching %d worker threads on %s, %d iterations.\n",
             nChecksum, nThreadCount, pszFilename, nIterations );
 
 /* -------------------------------------------------------------------- */
@@ -147,11 +147,11 @@ int main( int argc, char ** argv )
     CPLReleaseMutex( pGlobalMutex );
 
     printf( "All threads complete.\n" );
-    
+
     CSLDestroy( argv );
-    
+
     GDALDestroyDriverManager();
-    
+
     return 0;
 }
 
@@ -179,10 +179,10 @@ static void WorkerFunc( void * )
         for( iIter = 0; iIter < nIterations && hDS != NULL; iIter++ )
         {
             int nMyChecksum;
-        
-            nMyChecksum = GDALChecksumImage( GDALGetRasterBand( hDS, 1 ), 
-                                             0, 0, 
-                                             GDALGetRasterXSize( hDS ), 
+
+            nMyChecksum = GDALChecksumImage( GDALGetRasterBand( hDS, 1 ),
+                                             0, 0,
+                                             GDALGetRasterXSize( hDS ),
                                              GDALGetRasterYSize( hDS ) );
 
             if( nMyChecksum != nChecksum )
diff --git a/apps/nearblack.cpp b/apps/nearblack.cpp
deleted file mode 100644
index a55875c..0000000
--- a/apps/nearblack.cpp
+++ /dev/null
@@ -1,779 +0,0 @@
-/******************************************************************************
- * $Id: nearblack.cpp 28039 2014-11-30 18:24:59Z rouault $
- *
- * Project:  GDAL Utilities
- * Purpose:  Convert nearly black or nearly white border to exact black/white.
- * Author:   Frank Warmerdam, warmerdam at pobox.com
- *
- * ****************************************************************************
- * Copyright (c) 2006, MapShots Inc (www.mapshots.com)
- * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "gdal.h"
-#include "cpl_conv.h"
-#include "cpl_string.h"
-#include <vector>
-#include "commonutils.h"
-
-CPL_CVSID("$Id: nearblack.cpp 28039 2014-11-30 18:24:59Z rouault $");
-
-typedef std::vector<int> Color;
-typedef std::vector< Color > Colors;
-
-static void ProcessLine( GByte *pabyLine, GByte *pabyMask, int iStart,
-                         int iEnd, int nSrcBands, int nDstBands, int nNearDist,
-                         int nMaxNonBlack, int bNearWhite, Colors *poColors,
-                         int *panLastLineCounts, int bDoHorizontalCheck,
-                         int bDoVerticalCheck, int bBottomUp);
-
-/************************************************************************/
-/*                            IsInt()                                   */
-/************************************************************************/
-
-int IsInt( const char *pszArg )
-{
-    if( pszArg[0] == '-' )
-        pszArg++;
-
-    if( *pszArg == '\0' )
-        return FALSE;
-
-    while( *pszArg != '\0' )
-    {
-        if( *pszArg < '0' || *pszArg > '9' )
-            return FALSE;
-        pszArg++;
-    }
-
-    return TRUE;
-}
-
-/************************************************************************/
-/*                               Usage()                                */
-/************************************************************************/
-
-void Usage(const char* pszErrorMsg = NULL)
-{
-    printf( "nearblack [-of format] [-white | [-color c1,c2,c3...cn]*] [-near dist] [-nb non_black_pixels]\n"
-            "          [-setalpha] [-setmask] [-o outfile] [-q] [-co \"NAME=VALUE\"]* infile\n" );
-
-    if( pszErrorMsg != NULL )
-        fprintf(stderr, "\nFAILURE: %s\n", pszErrorMsg);
-
-    exit( 1 );
-}
-
-/************************************************************************/
-/*                                main()                                */
-/************************************************************************/
-
-#define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg) \
-    do { if (i + nExtraArg >= argc) \
-        Usage(CPLSPrintf("%s option requires %d argument(s)", argv[i], nExtraArg)); } while(0)
-
-int main( int argc, char ** argv )
-
-{
-    /* Check that we are running against at least GDAL 1.4 (probably older in fact !) */
-    /* Note to developers : if we use newer API, please change the requirement */
-    if (atoi(GDALVersionInfo("VERSION_NUM")) < 1400)
-    {
-        fprintf(stderr, "At least, GDAL >= 1.4.0 is required for this version of %s, "
-                "which was compiled against GDAL %s\n", argv[0], GDAL_RELEASE_NAME);
-        exit(1);
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Generic arg processing.                                         */
-/* -------------------------------------------------------------------- */
-    GDALAllRegister();
-    GDALSetCacheMax( 100000000 );
-    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
-    if( argc < 1 )
-        exit( -argc );
-    
-/* -------------------------------------------------------------------- */
-/*      Parse arguments.                                                */
-/* -------------------------------------------------------------------- */
-    int i;
-    const char *pszOutFile = NULL;
-    const char *pszInFile = NULL;
-    int nMaxNonBlack = 2;
-    int nNearDist = 15;
-    int bNearWhite = FALSE;
-    int bSetAlpha = FALSE;
-    int bSetMask = FALSE;
-    const char* pszDriverName = "HFA";
-    int bFormatExplicitlySet = FALSE;
-    char** papszCreationOptions = NULL;
-    int bQuiet = FALSE;
-
-    Colors oColors;
-    
-    for( i = 1; i < argc; i++ )
-    {
-        if( EQUAL(argv[i], "--utility_version") )
-        {
-            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
-                   argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
-            return 0;
-        }
-        else if( EQUAL(argv[i], "--help") )
-            Usage();
-        else if( EQUAL(argv[i], "-o") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszOutFile = argv[++i];
-        }
-        else if( EQUAL(argv[i], "-of") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszDriverName = argv[++i];
-            bFormatExplicitlySet = TRUE;
-        }
-        else if( EQUAL(argv[i], "-white") ) {
-            bNearWhite = TRUE;
-        }
-
-        /***** -color c1,c2,c3...cn *****/
-        
-        else if( EQUAL(argv[i], "-color") ) {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            Color oColor;
-            
-            /***** tokenize the arg on , *****/
-            
-            char **papszTokens;
-            papszTokens = CSLTokenizeString2( argv[++i], ",", 0 );
-
-            /***** loop over the tokens *****/
-            
-            int iToken;
-            for( iToken = 0; papszTokens && papszTokens[iToken]; iToken++ )
-            {
-
-                /***** ensure the token is an int and add it to the color *****/
-                
-                if ( IsInt( papszTokens[iToken] ) )
-                    oColor.push_back( atoi( papszTokens[iToken] ) );
-                else {
-                    CPLError(CE_Failure, CPLE_AppDefined,
-                             "Colors must be valid integers." );
-                    CSLDestroy( papszTokens );
-                    exit(1);
-                }
-            }
-            
-            CSLDestroy( papszTokens );
-
-            /***** check if the number of bands is consistent *****/
-
-            if ( oColors.size() > 0 &&
-                 oColors.front().size() != oColor.size() )
-            {
-                CPLError(CE_Failure, CPLE_AppDefined,
-                         "ERROR: all -color args must have the same number of values.\n" );
-                exit(1);
-            }
-
-            /***** add the color to the colors *****/
-            
-            oColors.push_back( oColor );
-            
-        }
-        
-        else if( EQUAL(argv[i], "-nb") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            nMaxNonBlack = atoi(argv[++i]);
-        }
-        else if( EQUAL(argv[i], "-near") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            nNearDist = atoi(argv[++i]);
-        }
-        else if( EQUAL(argv[i], "-setalpha") )
-            bSetAlpha = TRUE;
-        else if( EQUAL(argv[i], "-setmask") )
-            bSetMask = TRUE;
-        else if( EQUAL(argv[i], "-q") || EQUAL(argv[i], "-quiet") )
-            bQuiet = TRUE;
-        else if( EQUAL(argv[i], "-co") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            papszCreationOptions = CSLAddString(papszCreationOptions, argv[++i]);
-        }
-        else if( argv[i][0] == '-' )
-            Usage(CPLSPrintf("Unknown option name '%s'", argv[i]));
-        else if( pszInFile == NULL )
-            pszInFile = argv[i];
-        else
-            Usage("Too many command options.");
-    }
-
-    if( pszInFile == NULL )
-        Usage("No input file specified.");
-
-    if( pszOutFile == NULL )
-        pszOutFile = pszInFile;
-
-/* -------------------------------------------------------------------- */
-/*      Open input file.                                                */
-/* -------------------------------------------------------------------- */
-    GDALDatasetH hInDS, hOutDS = NULL;
-    int nXSize, nYSize, nBands;
-
-    if( pszOutFile == pszInFile )
-        hInDS = hOutDS = GDALOpen( pszInFile, GA_Update );
-    else
-        hInDS = GDALOpen( pszInFile, GA_ReadOnly );
-
-    if( hInDS == NULL )
-        exit( 1 );
-
-    nXSize = GDALGetRasterXSize( hInDS );
-    nYSize = GDALGetRasterYSize( hInDS );
-    nBands = GDALGetRasterCount( hInDS );
-    int nDstBands = nBands;
-
-    if( hOutDS != NULL && papszCreationOptions != NULL)
-    {
-        CPLError(CE_Warning, CPLE_AppDefined,
-                  "Warning: creation options are ignored when writing to an existing file.");
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Do we need to create output file?                               */
-/* -------------------------------------------------------------------- */
-    if( hOutDS == NULL )
-    {
-        GDALDriverH hDriver = GDALGetDriverByName( pszDriverName );
-        if (hDriver == NULL)
-            exit(1);
-
-        if (!bQuiet && !bFormatExplicitlySet)
-            CheckExtensionConsistency(pszOutFile, pszDriverName);
-
-        if (bSetAlpha)
-        {
-            /***** fixme there should be a way to preserve alpha band data not in the collar *****/
-            if (nBands == 4)
-                nBands --;
-            else
-                nDstBands ++;
-        }
-
-        if (bSetMask)
-        {
-            if (nBands == 4)
-                nDstBands = nBands = 3;
-        }
-
-        hOutDS = GDALCreate( hDriver, pszOutFile, 
-                             nXSize, nYSize, nDstBands, GDT_Byte, 
-                             papszCreationOptions );
-        if( hOutDS == NULL )
-            exit( 1 );
-
-        double adfGeoTransform[6];
-
-        if( GDALGetGeoTransform( hInDS, adfGeoTransform ) == CE_None )
-        {
-            GDALSetGeoTransform( hOutDS, adfGeoTransform );
-            GDALSetProjection( hOutDS, GDALGetProjectionRef( hInDS ) );
-        }
-    }
-    else
-    {
-        if (bSetAlpha)
-        {
-            if (nBands != 4 &&
-                (nBands < 2 ||
-                 GDALGetRasterColorInterpretation(GDALGetRasterBand(hOutDS, nBands)) != GCI_AlphaBand))
-            {
-                CPLError(CE_Failure, CPLE_AppDefined,
-                        "Last band is not an alpha band.");
-                exit(1);
-            }
-
-            nBands --;
-        }
-
-        if (bSetMask)
-        {
-            if (nBands == 4)
-                nDstBands = nBands = 3;
-        }
-    }
-
-    /***** set a color if there are no colors set? *****/
-
-    if ( oColors.size() == 0) {
-        Color oColor;
-
-        /***** loop over the bands to get the right number of values *****/
-
-        int iBand;
-        for (iBand = 0; iBand < nBands ; iBand++) {
-
-            /***** black or white? *****/
-
-            if (bNearWhite) 
-                oColor.push_back(255);
-            else
-                oColor.push_back(0);
-        }
-
-        /***** add the color to the colors *****/
-
-        oColors.push_back(oColor);
-            
-    }
-
-    /***** does the number of bands match the number of color values? *****/
-
-    if ( (int)oColors.front().size() != nBands ) {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "-color args must have the same number of values as the non alpha input band count.\n" );
-        exit(1); 
-    }
-
-    /***** check the input and output datasets are the same size *****/
-    
-    if (GDALGetRasterXSize(hOutDS) != nXSize ||
-        GDALGetRasterYSize(hOutDS) != nYSize)
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "The dimensions of the output dataset don't match "
-                 "the dimensions of the input dataset.");
-        exit(1);
-    }
-
-
-    int iBand;
-    for( iBand = 0; iBand < nBands; iBand++ )
-    {
-        GDALRasterBandH hBand = GDALGetRasterBand(hInDS, iBand+1);
-        if (GDALGetRasterDataType(hBand) != GDT_Byte)
-        {
-            CPLError(CE_Warning, CPLE_AppDefined,
-                     "Band %d is not of type GDT_Byte. It can lead to unexpected results.", iBand+1);
-        }
-        if (GDALGetRasterColorTable(hBand) != NULL)
-        {
-            CPLError(CE_Warning, CPLE_AppDefined,
-                     "Band %d has a color table, which is ignored by nearblack. "
-                     "It can lead to unexpected results.", iBand+1);
-        }
-    }
-
-    GDALRasterBandH hMaskBand = NULL;
-    
-    if (bSetMask) {
-
-        /***** if there isn't already a mask band on the output file create one *****/
-        
-        if ( GMF_PER_DATASET != GDALGetMaskFlags( GDALGetRasterBand(hOutDS, 1) ) )
-        {
-
-            if ( CE_None != GDALCreateDatasetMaskBand(hOutDS, GMF_PER_DATASET) ) {
-                CPLError(CE_Failure, CPLE_AppDefined,
-                         "Failed to create mask band on output DS");
-                bSetMask = FALSE;
-            }
-        }
-
-        if (bSetMask) {
-            hMaskBand = GDALGetMaskBand(GDALGetRasterBand(hOutDS, 1));
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Allocate a line buffer.                                         */
-/* -------------------------------------------------------------------- */
-    GByte *pabyLine;
-    GByte *pabyMask=NULL;
-    
-    int   *panLastLineCounts;
-
-    pabyLine = (GByte *) CPLMalloc(nXSize * nDstBands);
-    
-    if (bSetMask)
-        pabyMask = (GByte *) CPLMalloc(nXSize);
-    
-    panLastLineCounts = (int *) CPLCalloc(sizeof(int),nXSize);
-
-/* -------------------------------------------------------------------- */
-/*      Processing data one line at a time.                             */
-/* -------------------------------------------------------------------- */
-    int iLine;
-
-    for( iLine = 0; iLine < nYSize; iLine++ )
-    {
-        CPLErr eErr;
-
-        eErr = GDALDatasetRasterIO( hInDS, GF_Read, 0, iLine, nXSize, 1, 
-                                    pabyLine, nXSize, 1, GDT_Byte, 
-                                    nBands, NULL, nDstBands, nXSize * nDstBands, 1 );
-        if( eErr != CE_None )
-            break;
-        
-        if (bSetAlpha)
-        {
-            int iCol;
-            for(iCol = 0; iCol < nXSize; iCol ++)
-            {
-                pabyLine[iCol * nDstBands + nDstBands - 1] = 255;
-            }
-        }
-        
-        if (bSetMask)
-        {
-            int iCol;
-            for(iCol = 0; iCol < nXSize; iCol ++)
-            {
-                pabyMask[iCol] = 255;
-            }
-        }
-        
-        ProcessLine( pabyLine, pabyMask, 0, nXSize-1, nBands, nDstBands,
-                     nNearDist, nMaxNonBlack, bNearWhite, &oColors,
-                     panLastLineCounts,
-                     TRUE, // bDoHorizontalCheck
-                     TRUE, // bDoVerticalCheck
-                     FALSE // bBottomUp
-                    );
-        ProcessLine( pabyLine, pabyMask, nXSize-1, 0, nBands, nDstBands,
-                     nNearDist, nMaxNonBlack, bNearWhite, &oColors,
-                     panLastLineCounts,
-                     TRUE,  // bDoHorizontalCheck
-                     FALSE, // bDoVerticalCheck
-                     FALSE  // bBottomUp
-                    );
-        
-        eErr = GDALDatasetRasterIO( hOutDS, GF_Write, 0, iLine, nXSize, 1, 
-                                    pabyLine, nXSize, 1, GDT_Byte, 
-                                    nDstBands, NULL, nDstBands, nXSize * nDstBands, 1 );
-
-        if( eErr != CE_None )
-            break;
-    
-        /***** write out the mask band line *****/
-
-        if (bSetMask) {
-
-            eErr = GDALRasterIO ( hMaskBand, GF_Write, 0, iLine, nXSize, 1,
-                                  pabyMask, nXSize, 1, GDT_Byte,
-                                  0, 0 );
-                             
-            if( eErr != CE_None ) {
-                CPLError(CE_Warning, CPLE_AppDefined,
-                         "ERROR writeing out line to mask band.");
-               break;
-            }
-        }
-        
-        if (!bQuiet)
-            GDALTermProgress( 0.5 * ((iLine+1) / (double) nYSize), NULL, NULL );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Now process from the bottom back up                            .*/
-/* -------------------------------------------------------------------- */
-    memset( panLastLineCounts, 0, sizeof(int) * nXSize);
-    
-    for( iLine = nYSize-1; iLine >= 0; iLine-- )
-    {
-        CPLErr eErr;
-
-        eErr = GDALDatasetRasterIO( hOutDS, GF_Read, 0, iLine, nXSize, 1, 
-                                    pabyLine, nXSize, 1, GDT_Byte, 
-                                    nDstBands, NULL, nDstBands, nXSize * nDstBands, 1 );
-        if( eErr != CE_None )
-            break;
-
-        /***** read the mask band line back in *****/
-
-        if (bSetMask) {
-
-            eErr = GDALRasterIO ( hMaskBand, GF_Read, 0, iLine, nXSize, 1,
-                                  pabyMask, nXSize, 1, GDT_Byte,
-                                  0, 0 );
-                             
-                                
-            if( eErr != CE_None )
-                break;
-        }
-
-        
-        ProcessLine( pabyLine, pabyMask, 0, nXSize-1, nBands, nDstBands,
-                     nNearDist, nMaxNonBlack, bNearWhite, &oColors,
-                     panLastLineCounts,
-                     TRUE, // bDoHorizontalCheck
-                     TRUE, // bDoVerticalCheck
-                     TRUE  // bBottomUp
-                   );
-        ProcessLine( pabyLine, pabyMask, nXSize-1, 0, nBands, nDstBands,
-                     nNearDist, nMaxNonBlack, bNearWhite, &oColors,
-                     panLastLineCounts,
-                     TRUE,  // bDoHorizontalCheck
-                     FALSE, // bDoVerticalCheck
-                     TRUE   // bBottomUp
-                    );
-        
-        eErr = GDALDatasetRasterIO( hOutDS, GF_Write, 0, iLine, nXSize, 1, 
-                                    pabyLine, nXSize, 1, GDT_Byte, 
-                                    nDstBands, NULL, nDstBands, nXSize * nDstBands, 1 );
-        if( eErr != CE_None )
-            break;
-
-        /***** write out the mask band line *****/
-
-        if (bSetMask) {
-
-            eErr = GDALRasterIO ( hMaskBand, GF_Write, 0, iLine, nXSize, 1,
-                                  pabyMask, nXSize, 1, GDT_Byte,
-                                  0, 0 );
-                             
-                                
-            if( eErr != CE_None )
-                break;
-        }
-
-        
-        if (!bQuiet)
-            GDALTermProgress( 0.5 + 0.5 * (nYSize-iLine) / (double) nYSize, 
-                            NULL, NULL );
-    }
-
-    CPLFree(pabyLine);
-    if (bSetMask)
-        CPLFree(pabyMask);
-    
-    CPLFree( panLastLineCounts );
-
-    GDALClose( hOutDS );
-    if( hInDS != hOutDS )
-        GDALClose( hInDS );
-    GDALDumpOpenDatasets( stderr );
-    CSLDestroy( argv );
-    CSLDestroy( papszCreationOptions );
-    GDALDestroyDriverManager();
-    
-    return 0;
-}
-
-/************************************************************************/
-/*                            ProcessLine()                             */
-/*                                                                      */
-/*      Process a single scanline of image data.                        */
-/************************************************************************/
-
-static void ProcessLine( GByte *pabyLine, GByte *pabyMask, int iStart,
-                        int iEnd, int nSrcBands, int nDstBands, int nNearDist,
-                        int nMaxNonBlack, int bNearWhite, Colors *poColors,
-                        int *panLastLineCounts, int bDoHorizontalCheck,
-                        int bDoVerticalCheck, int bBottomUp )
-{
-    int iDir, i;
-    GByte nReplacevalue = 0;
-    if( bNearWhite )
-        nReplacevalue = 255;
-
-    /* -------------------------------------------------------------------- */
-    /*      Vertical checking.                                              */
-    /* -------------------------------------------------------------------- */
-    
-    if( bDoVerticalCheck )
-    {
-        int nXSize = MAX(iStart+1,iEnd+1);
-
-        for( i = 0; i < nXSize; i++ )
-        {
-
-            // are we already terminated for this column?
-
-            if( panLastLineCounts[i] > nMaxNonBlack )
-                continue;
-
-            /***** is the pixel valid data? ****/
-
-            int bIsNonBlack = FALSE;
-
-            /***** loop over the colors *****/
-
-            int iColor;
-            for (iColor = 0; iColor < (int)poColors->size(); iColor++) {
-
-                Color oColor = (*poColors)[iColor];
-
-                bIsNonBlack = FALSE;
-
-                /***** loop over the bands *****/
-
-                int iBand;
-                for( iBand = 0; iBand < nSrcBands; iBand++ )
-                {
-                    int nPix = pabyLine[i * nDstBands + iBand];
-
-                    if( oColor[iBand] - nPix > nNearDist ||
-                       nPix > nNearDist + oColor[iBand] )
-                    {
-                        bIsNonBlack = TRUE;
-                        break;
-                    }
-                }
-                
-                if (bIsNonBlack == FALSE)
-                    break;          
-            }
-
-            if (bIsNonBlack) {
-                panLastLineCounts[i]++;
-
-                if( panLastLineCounts[i] > nMaxNonBlack )
-                    continue; 
-            }
-            //else
-            //  panLastLineCounts[i] = 0; // not sure this even makes sense 
-
-            /***** replace the pixel values *****/
-
-            int iBand;
-            for( iBand = 0; iBand < nSrcBands; iBand++ )
-                pabyLine[i * nDstBands + iBand] = nReplacevalue;
-
-            /***** alpha *****/
-
-            if( nDstBands > nSrcBands )
-                pabyLine[i * nDstBands + nDstBands - 1] = 0;
-
-            /***** mask *****/
-
-            if (pabyMask != NULL)
-                pabyMask[i] = 0;
-        }
-    }
-
-    /* -------------------------------------------------------------------- */
-    /*      Horizontal Checking.                                            */
-    /* -------------------------------------------------------------------- */
-    
-    if( bDoHorizontalCheck )
-    {
-        int nNonBlackPixels = 0;
-
-        /***** on a bottom up pass assume nMaxNonBlack is 0 *****/ 
-
-        if (bBottomUp)
-            nMaxNonBlack = 0;
-
-        if( iStart < iEnd )
-            iDir = 1;
-        else
-            iDir = -1;
-        int bDoTest = TRUE;
-
-        for( i = iStart; i != iEnd; i += iDir )
-        {
-
-            /***** not seen any valid data? *****/
-
-            if ( bDoTest ) {
-
-                /***** is the pixel valid data? ****/
-
-                int bIsNonBlack = FALSE;
-
-                /***** loop over the colors *****/
-
-                int iColor;
-                for (iColor = 0; iColor < (int)poColors->size(); iColor++) {
-
-                    Color oColor = (*poColors)[iColor];
-
-                    bIsNonBlack = FALSE;
-
-                    /***** loop over the bands *****/
-
-                    int iBand;
-                    for( iBand = 0; iBand < nSrcBands; iBand++ )
-                    {
-                        int nPix = pabyLine[i * nDstBands + iBand];
-
-                        if( oColor[iBand] - nPix > nNearDist ||
-                           nPix > nNearDist + oColor[iBand] )
-                        {
-                            bIsNonBlack = TRUE;
-                            break;
-                        }
-                    }
-                    
-                    if (bIsNonBlack == FALSE)
-                        break;          
-                }
-
-                if (bIsNonBlack) {
-
-                    /***** use nNonBlackPixels in grey areas  *****/
-                    /***** from the verical pass's grey areas ****/
-
-                    if( panLastLineCounts[i] <= nMaxNonBlack )
-                        nNonBlackPixels = panLastLineCounts[i];
-                    else 
-                        nNonBlackPixels++;
-                }
-
-                if( nNonBlackPixels > nMaxNonBlack ) {
-                    bDoTest = FALSE;
-                    continue;
-                }
-
-                /***** replace the pixel values *****/
-
-                int iBand;
-                for( iBand = 0; iBand < nSrcBands; iBand++ )
-                    pabyLine[i * nDstBands + iBand] = nReplacevalue;
-
-                /***** alpha *****/
-
-                if( nDstBands > nSrcBands )
-                    pabyLine[i * nDstBands + nDstBands - 1] = 0;
-
-                /***** mask *****/
-
-                if (pabyMask != NULL)
-                    pabyMask[i] = 0;
-            }
-
-            /***** seen valid data but test if the *****/
-            /***** vertical pass saw any non valid data *****/
-
-            else if( panLastLineCounts[i] == 0 ) {
-                bDoTest = TRUE;
-                nNonBlackPixels = 0;
-            }        
-        }
-    }
-
-}
-
diff --git a/apps/nearblack_bin.cpp b/apps/nearblack_bin.cpp
new file mode 100644
index 0000000..e834200
--- /dev/null
+++ b/apps/nearblack_bin.cpp
@@ -0,0 +1,164 @@
+/******************************************************************************
+ * $Id: nearblack_bin.cpp 33011 2016-01-15 22:20:29Z goatbar $
+ *
+ * Project:  GDAL Utilities
+ * Purpose:  Convert nearly black or nearly white border to exact black/white.
+ * Authors:  Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_string.h"
+#include "commonutils.h"
+#include "gdal_utils_priv.h"
+
+CPL_CVSID("$Id: nearblack_bin.cpp 33011 2016-01-15 22:20:29Z goatbar $");
+
+/************************************************************************/
+/*                               Usage()                                */
+/************************************************************************/
+
+static void Usage(const char* pszErrorMsg = NULL)
+{
+    printf( "nearblack [-of format] [-white | [-color c1,c2,c3...cn]*] [-near dist] [-nb non_black_pixels]\n"
+            "          [-setalpha] [-setmask] [-o outfile] [-q] [-co \"NAME=VALUE\"]* infile\n" );
+
+    if( pszErrorMsg != NULL )
+        fprintf(stderr, "\nFAILURE: %s\n", pszErrorMsg);
+
+    exit( 1 );
+}
+
+/************************************************************************/
+/*                       GDALNearblackOptionsForBinaryNew()             */
+/************************************************************************/
+
+static GDALNearblackOptionsForBinary *GDALNearblackOptionsForBinaryNew(void)
+{
+    return (GDALNearblackOptionsForBinary*) CPLCalloc(  1, sizeof(GDALNearblackOptionsForBinary) );
+}
+
+/************************************************************************/
+/*                       GDALNearblackOptionsForBinaryFree()            */
+/************************************************************************/
+
+static void GDALNearblackOptionsForBinaryFree( GDALNearblackOptionsForBinary* psOptionsForBinary )
+{
+    if( psOptionsForBinary )
+    {
+        CPLFree(psOptionsForBinary->pszInFile);
+        CPLFree(psOptionsForBinary->pszOutFile);
+        CPLFree(psOptionsForBinary->pszFormat);
+        CPLFree(psOptionsForBinary);
+    }
+}
+/************************************************************************/
+/*                                main()                                */
+/************************************************************************/
+
+int main(int argc, char** argv)
+{
+    /* Check strict compilation and runtime library version as we use C++ API */
+    if (! GDAL_CHECK_VERSION(argv[0]))
+        exit(1);
+
+    EarlySetConfigOptions(argc, argv);
+
+/* -------------------------------------------------------------------- */
+/*      Generic arg processing.                                         */
+/* -------------------------------------------------------------------- */
+    GDALAllRegister();
+    if( CPLGetConfigOption("GDAL_CACHEMAX", NULL) == NULL )
+	GDALSetCacheMax( 100000000 );
+    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
+    if( argc < 1 )
+        exit( -argc );
+
+    for( int i = 0; i < argc; i++ )
+    {
+        if( EQUAL(argv[i], "--utility_version") )
+        {
+            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
+                   argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
+            CSLDestroy( argv );
+            return 0;
+        }
+        else if( EQUAL(argv[i],"--help") )
+        {
+            Usage();
+        }
+    }
+
+    GDALNearblackOptionsForBinary* psOptionsForBinary = GDALNearblackOptionsForBinaryNew();
+    GDALNearblackOptions *psOptions = GDALNearblackOptionsNew(argv + 1, psOptionsForBinary);
+    CSLDestroy( argv );
+
+    if( psOptions == NULL )
+    {
+        Usage();
+    }
+
+    if( !(psOptionsForBinary->bQuiet) )
+    {
+        GDALNearblackOptionsSetProgress(psOptions, GDALTermProgress, NULL);
+    }
+
+    if( psOptionsForBinary->pszInFile == NULL )
+        Usage("No input file specified.");
+
+    if( psOptionsForBinary->pszOutFile == NULL )
+        psOptionsForBinary->pszOutFile = CPLStrdup(psOptionsForBinary->pszInFile);
+    else if (!psOptionsForBinary->bQuiet && !psOptionsForBinary->bFormatExplicitlySet)
+        CheckExtensionConsistency(psOptionsForBinary->pszOutFile, psOptionsForBinary->pszFormat);
+
+/* -------------------------------------------------------------------- */
+/*      Open input file.                                                */
+/* -------------------------------------------------------------------- */
+    GDALDatasetH hInDS, hOutDS = NULL;
+
+    if( strcmp(psOptionsForBinary->pszOutFile, psOptionsForBinary->pszInFile) == 0 )
+        hInDS = hOutDS = GDALOpen( psOptionsForBinary->pszInFile, GA_Update );
+    else
+        hInDS = GDALOpen( psOptionsForBinary->pszInFile, GA_ReadOnly );
+
+    if( hInDS == NULL )
+        exit( 1 );
+
+    int bUsageError = FALSE;
+    GDALDatasetH hRetDS = GDALNearblack(psOptionsForBinary->pszOutFile,
+                                        hOutDS,
+                                        hInDS,
+                                        psOptions, &bUsageError);
+    if(bUsageError == TRUE)
+        Usage();
+    int nRetCode = (hRetDS) ? 0 : 1;
+
+    GDALClose(hInDS);
+    if( hRetDS != hInDS )
+        GDALClose(hOutDS);
+    GDALNearblackOptionsFree(psOptions);
+    GDALNearblackOptionsForBinaryFree(psOptionsForBinary);
+
+    GDALDestroyDriverManager();
+
+    return nRetCode;
+}
diff --git a/apps/nearblack_lib.cpp b/apps/nearblack_lib.cpp
new file mode 100644
index 0000000..4db0fb2
--- /dev/null
+++ b/apps/nearblack_lib.cpp
@@ -0,0 +1,926 @@
+/******************************************************************************
+ * $Id: nearblack_lib.cpp 33615 2016-03-02 20:19:22Z goatbar $
+ *
+ * Project:  GDAL Utilities
+ * Purpose:  Convert nearly black or nearly white border to exact black/white.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ * ****************************************************************************
+ * Copyright (c) 2006, MapShots Inc (www.mapshots.com)
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gdal.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include <vector>
+#include "gdal_utils_priv.h"
+
+CPL_CVSID("$Id: nearblack_lib.cpp 33615 2016-03-02 20:19:22Z goatbar $");
+
+typedef std::vector<int> Color;
+typedef std::vector< Color > Colors;
+
+struct GDALNearblackOptions
+{
+    /*! output format. The default is GeoTIFF(GTiff). Use the short format name. */
+    char *pszFormat;
+
+    /*! the progress function to use */
+    GDALProgressFunc pfnProgress;
+
+    /*! pointer to the progress data variable */
+    void *pProgressData;
+
+    int nMaxNonBlack;
+    int nNearDist;
+    int bNearWhite;
+    int bSetAlpha;
+    int bSetMask;
+
+    Colors oColors;
+
+    char** papszCreationOptions;
+};
+
+static void ProcessLine( GByte *pabyLine, GByte *pabyMask, int iStart,
+                         int iEnd, int nSrcBands, int nDstBands, int nNearDist,
+                         int nMaxNonBlack, int bNearWhite, Colors *poColors,
+                         int *panLastLineCounts, int bDoHorizontalCheck,
+                         int bDoVerticalCheck, int bBottomUp);
+
+/************************************************************************/
+/*                            GDALNearblack()                           */
+/************************************************************************/
+
+/**
+ * Convert nearly black/white borders to exact value.
+ *
+ * This is the equivalent of the <a href="nearblack.html">nearblack</a> utility.
+ *
+ * GDALNearblackOptions* must be allocated and freed with GDALNearblackOptionsNew()
+ * and GDALNearblackOptionsFree() respectively.
+ * pszDest and hDstDS cannot be used at the same time.
+ *
+ * In-place update (i.e. hDstDS == hSrcDataset) is possible for formats that
+ * support it, and if the dataset is opened in update mode.
+ *
+ * @param pszDest the destination dataset path or NULL.
+ * @param hDstDS the destination dataset or NULL. Might be equal to hSrcDataset.
+ * @param hSrcDataset the source dataset handle.
+ * @param psOptionsIn the options struct returned by GDALNearblackOptionsNew() or NULL.
+ * @param pbUsageError the pointer to int variable to determine any usage error has occurred or NULL.
+ * @return the output dataset (new dataset that must be closed using GDALClose(), or hDstDS is not NULL) or NULL in case of error.
+ *
+ * @since GDAL 2.1
+ */
+
+GDALDatasetH CPL_DLL GDALNearblack( const char *pszDest, GDALDatasetH hDstDS,
+                                    GDALDatasetH hSrcDataset,
+                                    const GDALNearblackOptions *psOptionsIn, int *pbUsageError )
+
+{
+    if( pszDest == NULL && hDstDS == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "pszDest == NULL && hDstDS == NULL");
+
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        return NULL;
+    }
+    if( hSrcDataset == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "hSrcDataset== NULL");
+
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        return NULL;
+    }
+
+    GDALNearblackOptions* psOptionsToFree = NULL;
+    const GDALNearblackOptions* psOptions;
+    if( psOptionsIn )
+        psOptions = psOptionsIn;
+    else
+    {
+        psOptionsToFree = GDALNearblackOptionsNew(NULL, NULL);
+        psOptions = psOptionsToFree;
+    }
+
+    int bCloseOutDSOnError = (hDstDS == NULL);
+    if( pszDest == NULL )
+        pszDest = GDALGetDescription(hDstDS);
+
+    int nXSize = GDALGetRasterXSize( hSrcDataset );
+    int nYSize = GDALGetRasterYSize( hSrcDataset );
+    int nBands = GDALGetRasterCount( hSrcDataset );
+    int nDstBands = nBands;
+
+    int nMaxNonBlack = psOptions->nMaxNonBlack;
+    int nNearDist = psOptions->nNearDist;
+    int bNearWhite = psOptions->bNearWhite;
+    int bSetAlpha = psOptions->bSetAlpha;
+    int bSetMask = psOptions->bSetMask;
+    Colors oColors = psOptions->oColors;
+
+/* -------------------------------------------------------------------- */
+/*      Do we need to create output file?                               */
+/* -------------------------------------------------------------------- */
+    if( hDstDS == NULL )
+    {
+        GDALDriverH hDriver = GDALGetDriverByName( psOptions->pszFormat );
+        if (hDriver == NULL)
+        {
+            GDALNearblackOptionsFree(psOptionsToFree);
+            return NULL;
+        }
+
+        if (bSetAlpha)
+        {
+            /***** FIXME there should be a way to preserve alpha band data not in the collar *****/
+            if (nBands == 4)
+                nBands --;
+            else
+                nDstBands ++;
+        }
+
+        if (bSetMask)
+        {
+            if (nBands == 4)
+                nDstBands = nBands = 3;
+        }
+
+        hDstDS = GDALCreate( hDriver, pszDest,
+                             nXSize, nYSize, nDstBands, GDT_Byte,
+                             psOptions->papszCreationOptions );
+        if( hDstDS == NULL )
+        {
+            GDALNearblackOptionsFree(psOptionsToFree);
+            return NULL;
+        }
+
+        double adfGeoTransform[6];
+
+        if( GDALGetGeoTransform( hSrcDataset, adfGeoTransform ) == CE_None )
+        {
+            GDALSetGeoTransform( hDstDS, adfGeoTransform );
+            GDALSetProjection( hDstDS, GDALGetProjectionRef( hSrcDataset ) );
+        }
+    }
+    else
+    {
+        if( psOptions->papszCreationOptions != NULL)
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                    "Warning: creation options are ignored when writing to an existing file.");
+        }
+
+        /***** check the input and output datasets are the same size *****/
+        if (GDALGetRasterXSize(hDstDS) != nXSize ||
+            GDALGetRasterYSize(hDstDS) != nYSize)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                    "The dimensions of the output dataset don't match "
+                    "the dimensions of the input dataset.");
+            GDALNearblackOptionsFree(psOptionsToFree);
+            return NULL;
+        }
+
+        if (bSetAlpha)
+        {
+            if (nBands != 4 &&
+                (nBands < 2 ||
+                 GDALGetRasterColorInterpretation(GDALGetRasterBand(hDstDS, nBands)) != GCI_AlphaBand))
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                        "Last band is not an alpha band.");
+                GDALNearblackOptionsFree(psOptionsToFree);
+                return NULL;
+            }
+
+            nBands --;
+        }
+
+        if (bSetMask)
+        {
+            if (nBands == 4)
+                nDstBands = nBands = 3;
+        }
+    }
+
+    /***** set a color if there are no colors set? *****/
+
+    if ( oColors.size() == 0) {
+        Color oColor;
+
+        /***** loop over the bands to get the right number of values *****/
+
+        int iBand;
+        for (iBand = 0; iBand < nBands ; iBand++) {
+
+            /***** black or white? *****/
+
+            if (bNearWhite)
+                oColor.push_back(255);
+            else
+                oColor.push_back(0);
+        }
+
+        /***** add the color to the colors *****/
+
+        oColors.push_back(oColor);
+    }
+
+    /***** does the number of bands match the number of color values? *****/
+
+    if ( (int)oColors.front().size() != nBands ) {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "-color args must have the same number of values as the non alpha input band count.\n" );
+        GDALNearblackOptionsFree(psOptionsToFree);
+        if( bCloseOutDSOnError )
+            GDALClose(hDstDS);
+        return NULL;
+    }
+
+    int iBand;
+    for( iBand = 0; iBand < nBands; iBand++ )
+    {
+        GDALRasterBandH hBand = GDALGetRasterBand(hSrcDataset, iBand+1);
+        if (GDALGetRasterDataType(hBand) != GDT_Byte)
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Band %d is not of type GDT_Byte. It can lead to unexpected results.", iBand+1);
+        }
+        if (GDALGetRasterColorTable(hBand) != NULL)
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Band %d has a color table, which is ignored by nearblack. "
+                     "It can lead to unexpected results.", iBand+1);
+        }
+    }
+
+    GDALRasterBandH hMaskBand = NULL;
+
+    if (bSetMask) {
+
+        /***** if there isn't already a mask band on the output file create one *****/
+
+        if ( GMF_PER_DATASET != GDALGetMaskFlags( GDALGetRasterBand(hDstDS, 1) ) )
+        {
+
+            if ( CE_None != GDALCreateDatasetMaskBand(hDstDS, GMF_PER_DATASET) ) {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Failed to create mask band on output DS");
+                bSetMask = FALSE;
+            }
+        }
+
+        if (bSetMask) {
+            hMaskBand = GDALGetMaskBand(GDALGetRasterBand(hDstDS, 1));
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Allocate a line buffer.                                         */
+/* -------------------------------------------------------------------- */
+    GByte *pabyLine;
+    GByte *pabyMask=NULL;
+
+    int   *panLastLineCounts;
+
+    pabyLine = (GByte *) CPLMalloc(nXSize * nDstBands);
+
+    if (bSetMask)
+        pabyMask = (GByte *) CPLMalloc(nXSize);
+
+    panLastLineCounts = (int *) CPLCalloc(sizeof(int),nXSize);
+
+/* -------------------------------------------------------------------- */
+/*      Processing data one line at a time.                             */
+/* -------------------------------------------------------------------- */
+    int iLine;
+
+    for( iLine = 0; iLine < nYSize; iLine++ )
+    {
+        CPLErr eErr;
+
+        eErr = GDALDatasetRasterIO( hSrcDataset, GF_Read, 0, iLine, nXSize, 1,
+                                    pabyLine, nXSize, 1, GDT_Byte,
+                                    nBands, NULL, nDstBands, nXSize * nDstBands, 1 );
+        if( eErr != CE_None )
+        {
+            if( bCloseOutDSOnError )
+                GDALClose(hDstDS);
+            hDstDS = NULL;
+            break;
+        }
+
+        if (bSetAlpha)
+        {
+            int iCol;
+            for(iCol = 0; iCol < nXSize; iCol ++)
+            {
+                pabyLine[iCol * nDstBands + nDstBands - 1] = 255;
+            }
+        }
+
+        if (bSetMask)
+        {
+            int iCol;
+            for(iCol = 0; iCol < nXSize; iCol ++)
+            {
+                pabyMask[iCol] = 255;
+            }
+        }
+
+        ProcessLine( pabyLine, pabyMask, 0, nXSize-1, nBands, nDstBands,
+                     nNearDist, nMaxNonBlack, bNearWhite, &oColors,
+                     panLastLineCounts,
+                     TRUE, // bDoHorizontalCheck
+                     TRUE, // bDoVerticalCheck
+                     FALSE // bBottomUp
+                    );
+        ProcessLine( pabyLine, pabyMask, nXSize-1, 0, nBands, nDstBands,
+                     nNearDist, nMaxNonBlack, bNearWhite, &oColors,
+                     panLastLineCounts,
+                     TRUE,  // bDoHorizontalCheck
+                     FALSE, // bDoVerticalCheck
+                     FALSE  // bBottomUp
+                    );
+
+        eErr = GDALDatasetRasterIO( hDstDS, GF_Write, 0, iLine, nXSize, 1,
+                                    pabyLine, nXSize, 1, GDT_Byte,
+                                    nDstBands, NULL, nDstBands, nXSize * nDstBands, 1 );
+
+        if( eErr != CE_None )
+        {
+            if( bCloseOutDSOnError )
+                GDALClose(hDstDS);
+            hDstDS = NULL;
+            break;
+        }
+
+        /***** write out the mask band line *****/
+
+        if (bSetMask) {
+
+            eErr = GDALRasterIO ( hMaskBand, GF_Write, 0, iLine, nXSize, 1,
+                                  pabyMask, nXSize, 1, GDT_Byte,
+                                  0, 0 );
+            if( eErr != CE_None )
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "ERROR writing out line to mask band.");
+                if( bCloseOutDSOnError )
+                    GDALClose(hDstDS);
+                hDstDS = NULL;
+                break;
+            }
+        }
+
+        if( !(psOptions->pfnProgress( 0.5 * ((iLine+1) / (double) nYSize), NULL, psOptions->pProgressData )) )
+        {
+            if( bCloseOutDSOnError )
+                GDALClose(hDstDS);
+            hDstDS = NULL;
+            break;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Now process from the bottom back up                            .*/
+/* -------------------------------------------------------------------- */
+    memset( panLastLineCounts, 0, sizeof(int) * nXSize);
+
+    for( iLine = nYSize-1; hDstDS != NULL && iLine >= 0; iLine-- )
+    {
+        CPLErr eErr;
+
+        eErr = GDALDatasetRasterIO( hDstDS, GF_Read, 0, iLine, nXSize, 1,
+                                    pabyLine, nXSize, 1, GDT_Byte,
+                                    nDstBands, NULL, nDstBands, nXSize * nDstBands, 1 );
+        if( eErr != CE_None )
+        {
+            if( bCloseOutDSOnError )
+                GDALClose(hDstDS);
+            hDstDS = NULL;
+            break;
+        }
+
+        /***** read the mask band line back in *****/
+
+        if (bSetMask) {
+
+            eErr = GDALRasterIO ( hMaskBand, GF_Read, 0, iLine, nXSize, 1,
+                                  pabyMask, nXSize, 1, GDT_Byte,
+                                  0, 0 );
+            if( eErr != CE_None )
+            {
+                if( bCloseOutDSOnError )
+                    GDALClose(hDstDS);
+                hDstDS = NULL;
+                break;
+            }
+        }
+
+        ProcessLine( pabyLine, pabyMask, 0, nXSize-1, nBands, nDstBands,
+                     nNearDist, nMaxNonBlack, bNearWhite, &oColors,
+                     panLastLineCounts,
+                     TRUE, // bDoHorizontalCheck
+                     TRUE, // bDoVerticalCheck
+                     TRUE  // bBottomUp
+                   );
+        ProcessLine( pabyLine, pabyMask, nXSize-1, 0, nBands, nDstBands,
+                     nNearDist, nMaxNonBlack, bNearWhite, &oColors,
+                     panLastLineCounts,
+                     TRUE,  // bDoHorizontalCheck
+                     FALSE, // bDoVerticalCheck
+                     TRUE   // bBottomUp
+                    );
+
+        eErr = GDALDatasetRasterIO( hDstDS, GF_Write, 0, iLine, nXSize, 1,
+                                    pabyLine, nXSize, 1, GDT_Byte,
+                                    nDstBands, NULL, nDstBands, nXSize * nDstBands, 1 );
+        if( eErr != CE_None )
+        {
+            if( bCloseOutDSOnError )
+                GDALClose(hDstDS);
+            hDstDS = NULL;
+            break;
+        }
+
+        /***** write out the mask band line *****/
+
+        if (bSetMask) {
+
+            eErr = GDALRasterIO ( hMaskBand, GF_Write, 0, iLine, nXSize, 1,
+                                  pabyMask, nXSize, 1, GDT_Byte,
+                                  0, 0 );
+            if( eErr != CE_None )
+            {
+                if( bCloseOutDSOnError )
+                    GDALClose(hDstDS);
+                hDstDS = NULL;
+                break;
+            }
+        }
+
+
+        if( !(psOptions->pfnProgress( 0.5 + 0.5 * (nYSize-iLine) / (double) nYSize, NULL, psOptions->pProgressData )) )
+        {
+            if( bCloseOutDSOnError )
+                GDALClose(hDstDS);
+            hDstDS = NULL;
+            break;
+        }
+    }
+
+    CPLFree(pabyLine);
+    if (bSetMask)
+        CPLFree(pabyMask);
+
+    CPLFree( panLastLineCounts );
+
+    return hDstDS;
+}
+
+/************************************************************************/
+/*                            ProcessLine()                             */
+/*                                                                      */
+/*      Process a single scanline of image data.                        */
+/************************************************************************/
+
+static void ProcessLine( GByte *pabyLine, GByte *pabyMask, int iStart,
+                        int iEnd, int nSrcBands, int nDstBands, int nNearDist,
+                        int nMaxNonBlack, int bNearWhite, Colors *poColors,
+                        int *panLastLineCounts, int bDoHorizontalCheck,
+                        int bDoVerticalCheck, int bBottomUp )
+{
+    int iDir, i;
+    GByte nReplacevalue = 0;
+    if( bNearWhite )
+        nReplacevalue = 255;
+
+    /* -------------------------------------------------------------------- */
+    /*      Vertical checking.                                              */
+    /* -------------------------------------------------------------------- */
+
+    if( bDoVerticalCheck )
+    {
+        int nXSize = MAX(iStart+1,iEnd+1);
+
+        for( i = 0; i < nXSize; i++ )
+        {
+
+            // are we already terminated for this column?
+
+            if( panLastLineCounts[i] > nMaxNonBlack )
+                continue;
+
+            /***** is the pixel valid data? ****/
+
+            int bIsNonBlack = FALSE;
+
+            /***** loop over the colors *****/
+
+            int iColor;
+            for (iColor = 0; iColor < (int)poColors->size(); iColor++) {
+
+                Color oColor = (*poColors)[iColor];
+
+                bIsNonBlack = FALSE;
+
+                /***** loop over the bands *****/
+
+                int iBand;
+                for( iBand = 0; iBand < nSrcBands; iBand++ )
+                {
+                    int nPix = pabyLine[i * nDstBands + iBand];
+
+                    if( oColor[iBand] - nPix > nNearDist ||
+                       nPix > nNearDist + oColor[iBand] )
+                    {
+                        bIsNonBlack = TRUE;
+                        break;
+                    }
+                }
+
+                if (bIsNonBlack == FALSE)
+                    break;
+            }
+
+            if (bIsNonBlack) {
+                panLastLineCounts[i]++;
+
+                if( panLastLineCounts[i] > nMaxNonBlack )
+                    continue;
+            }
+            //else
+            //  panLastLineCounts[i] = 0; // not sure this even makes sense
+
+            /***** replace the pixel values *****/
+
+            int iBand;
+            for( iBand = 0; iBand < nSrcBands; iBand++ )
+                pabyLine[i * nDstBands + iBand] = nReplacevalue;
+
+            /***** alpha *****/
+
+            if( nDstBands > nSrcBands )
+                pabyLine[i * nDstBands + nDstBands - 1] = 0;
+
+            /***** mask *****/
+
+            if (pabyMask != NULL)
+                pabyMask[i] = 0;
+        }
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Horizontal Checking.                                            */
+    /* -------------------------------------------------------------------- */
+
+    if( bDoHorizontalCheck )
+    {
+        int nNonBlackPixels = 0;
+
+        /***** on a bottom up pass assume nMaxNonBlack is 0 *****/
+
+        if (bBottomUp)
+            nMaxNonBlack = 0;
+
+        if( iStart < iEnd )
+            iDir = 1;
+        else
+            iDir = -1;
+        int bDoTest = TRUE;
+
+        for( i = iStart; i != iEnd; i += iDir )
+        {
+
+            /***** not seen any valid data? *****/
+
+            if ( bDoTest ) {
+
+                /***** is the pixel valid data? ****/
+
+                int bIsNonBlack = FALSE;
+
+                /***** loop over the colors *****/
+
+                int iColor;
+                for (iColor = 0; iColor < (int)poColors->size(); iColor++) {
+
+                    Color oColor = (*poColors)[iColor];
+
+                    bIsNonBlack = FALSE;
+
+                    /***** loop over the bands *****/
+
+                    int iBand;
+                    for( iBand = 0; iBand < nSrcBands; iBand++ )
+                    {
+                        int nPix = pabyLine[i * nDstBands + iBand];
+
+                        if( oColor[iBand] - nPix > nNearDist ||
+                           nPix > nNearDist + oColor[iBand] )
+                        {
+                            bIsNonBlack = TRUE;
+                            break;
+                        }
+                    }
+
+                    if (bIsNonBlack == FALSE)
+                        break;
+                }
+
+                if (bIsNonBlack) {
+
+                    /***** use nNonBlackPixels in grey areas  *****/
+                    /***** from the vertical pass's grey areas ****/
+
+                    if( panLastLineCounts[i] <= nMaxNonBlack )
+                        nNonBlackPixels = panLastLineCounts[i];
+                    else
+                        nNonBlackPixels++;
+                }
+
+                if( nNonBlackPixels > nMaxNonBlack ) {
+                    bDoTest = FALSE;
+                    continue;
+                }
+
+                /***** replace the pixel values *****/
+
+                int iBand;
+                for( iBand = 0; iBand < nSrcBands; iBand++ )
+                    pabyLine[i * nDstBands + iBand] = nReplacevalue;
+
+                /***** alpha *****/
+
+                if( nDstBands > nSrcBands )
+                    pabyLine[i * nDstBands + nDstBands - 1] = 0;
+
+                /***** mask *****/
+
+                if (pabyMask != NULL)
+                    pabyMask[i] = 0;
+            }
+
+            /***** seen valid data but test if the *****/
+            /***** vertical pass saw any non valid data *****/
+
+            else if( panLastLineCounts[i] == 0 ) {
+                bDoTest = TRUE;
+                nNonBlackPixels = 0;
+            }
+        }
+    }
+
+}
+
+
+/************************************************************************/
+/*                            IsInt()                                   */
+/************************************************************************/
+
+static int IsInt( const char *pszArg )
+{
+    if( pszArg[0] == '-' )
+        pszArg++;
+
+    if( *pszArg == '\0' )
+        return FALSE;
+
+    while( *pszArg != '\0' )
+    {
+        if( *pszArg < '0' || *pszArg > '9' )
+            return FALSE;
+        pszArg++;
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                           GDALNearblackOptionsNew()              */
+/************************************************************************/
+
+/**
+ * Allocates a GDALNearblackOptions struct.
+ *
+ * @param papszArgv NULL terminated list of options (potentially including filename and open options too), or NULL.
+ *                  The accepted options are the ones of the <a href="nearblack.html">nearblack</a> utility.
+ * @param psOptionsForBinary (output) may be NULL (and should generally be NULL),
+ *                           otherwise (gdal_translate_bin.cpp use case) must be allocated with
+ *                           GDALNearblackOptionsForBinaryNew() prior to this function. Will be
+ *                           filled with potentially present filename, open options,...
+ * @return pointer to the allocated GDALNearblackOptions struct. Must be freed with GDALNearblackOptionsFree().
+ *
+ * @since GDAL 2.1
+ */
+
+GDALNearblackOptions *GDALNearblackOptionsNew(char** papszArgv,
+                                                      GDALNearblackOptionsForBinary* psOptionsForBinary)
+{
+    GDALNearblackOptions *psOptions = new GDALNearblackOptions;
+
+    psOptions->pszFormat = CPLStrdup("HFA");
+    psOptions->pfnProgress = GDALDummyProgress;
+    psOptions->pProgressData = NULL;
+    psOptions->papszCreationOptions = NULL;
+    psOptions->nMaxNonBlack = 2;
+    psOptions->nNearDist = 15;
+    psOptions->bNearWhite = FALSE;
+    psOptions->bSetAlpha = FALSE;
+    psOptions->bSetMask = FALSE;
+
+/* -------------------------------------------------------------------- */
+/*      Handle command line arguments.                                  */
+/* -------------------------------------------------------------------- */
+    int argc = CSLCount(papszArgv);
+    for( int i = 0; i < argc; i++ )
+    {
+        if( EQUAL(papszArgv[i],"-of") && i < argc-1 )
+        {
+            ++i;
+            CPLFree(psOptions->pszFormat);
+            psOptions->pszFormat = CPLStrdup(papszArgv[i]);
+            if( psOptionsForBinary )
+            {
+                psOptionsForBinary->bFormatExplicitlySet = TRUE;
+            }
+        }
+
+        else if( EQUAL(papszArgv[i],"-q") || EQUAL(papszArgv[i],"-quiet") )
+        {
+            if( psOptionsForBinary )
+                psOptionsForBinary->bQuiet = TRUE;
+        }
+        else if( EQUAL(papszArgv[i],"-co") && i+1<argc )
+        {
+            psOptions->papszCreationOptions = CSLAddString( psOptions->papszCreationOptions, papszArgv[++i] );
+        }
+        else if( EQUAL(papszArgv[i], "-o") && i+1<argc )
+        {
+            i++;
+            if( psOptionsForBinary )
+            {
+                CPLFree(psOptionsForBinary->pszOutFile);
+                psOptionsForBinary->pszOutFile = CPLStrdup(papszArgv[i]);
+            }
+        }
+        else if( EQUAL(papszArgv[i], "-white") ) {
+            psOptions->bNearWhite = TRUE;
+        }
+
+        /***** -color c1,c2,c3...cn *****/
+
+        else if( EQUAL(papszArgv[i], "-color") && i+1<argc )
+        {
+            Color oColor;
+
+            /***** tokenize the arg on , *****/
+
+            char **papszTokens;
+            papszTokens = CSLTokenizeString2( papszArgv[++i], ",", 0 );
+
+            /***** loop over the tokens *****/
+
+            int iToken;
+            for( iToken = 0; papszTokens && papszTokens[iToken]; iToken++ )
+            {
+
+                /***** ensure the token is an int and add it to the color *****/
+
+                if ( IsInt( papszTokens[iToken] ) )
+                    oColor.push_back( atoi( papszTokens[iToken] ) );
+                else {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Colors must be valid integers." );
+                    CSLDestroy( papszTokens );
+
+                    GDALNearblackOptionsFree(psOptions);
+                    return NULL;
+                }
+            }
+
+            CSLDestroy( papszTokens );
+
+            /***** check if the number of bands is consistent *****/
+
+            if ( psOptions->oColors.size() > 0 &&
+                 psOptions->oColors.front().size() != oColor.size() )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "all -color args must have the same number of values.\n" );
+                GDALNearblackOptionsFree(psOptions);
+                return NULL;
+            }
+
+            /***** add the color to the colors *****/
+
+            psOptions->oColors.push_back( oColor );
+        }
+
+        else if( EQUAL(papszArgv[i], "-nb") && i+1<argc )
+        {
+            psOptions->nMaxNonBlack = atoi(papszArgv[++i]);
+        }
+        else if( EQUAL(papszArgv[i], "-near") && i+1<argc )
+        {
+            psOptions->nNearDist = atoi(papszArgv[++i]);
+        }
+        else if( EQUAL(papszArgv[i], "-setalpha") )
+            psOptions->bSetAlpha = TRUE;
+        else if( EQUAL(papszArgv[i], "-setmask") )
+            psOptions->bSetMask = TRUE;
+        else if( papszArgv[i][0] == '-' )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unknown option name '%s'", papszArgv[i]);
+            GDALNearblackOptionsFree(psOptions);
+            return NULL;
+        }
+        else if( psOptionsForBinary && psOptionsForBinary->pszInFile == NULL )
+        {
+            psOptionsForBinary->pszInFile = CPLStrdup(papszArgv[i]);
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Too many command options '%s'", papszArgv[i]);
+            GDALNearblackOptionsFree(psOptions);
+            return NULL;
+        }
+    }
+
+    if( psOptionsForBinary )
+    {
+        psOptionsForBinary->pszFormat = CPLStrdup(psOptions->pszFormat);
+    }
+
+    return psOptions;
+}
+
+/************************************************************************/
+/*                       GDALNearblackOptionsFree()                     */
+/************************************************************************/
+
+/**
+ * Frees the GDALNearblackOptions struct.
+ *
+ * @param psOptions the options struct for GDALNearblack().
+ *
+ * @since GDAL 2.1
+ */
+
+void GDALNearblackOptionsFree(GDALNearblackOptions *psOptions)
+{
+    if( psOptions )
+    {
+        CPLFree(psOptions->pszFormat);
+        CSLDestroy(psOptions->papszCreationOptions);
+
+        delete psOptions;
+    }
+}
+
+/************************************************************************/
+/*                  GDALNearblackOptionsSetProgress()                   */
+/************************************************************************/
+
+/**
+ * Set a progress function.
+ *
+ * @param psOptions the options struct for GDALNearblack().
+ * @param pfnProgress the progress callback.
+ * @param pProgressData the user data for the progress callback.
+ *
+ * @since GDAL 2.1
+ */
+
+void GDALNearblackOptionsSetProgress( GDALNearblackOptions *psOptions,
+                                      GDALProgressFunc pfnProgress, void *pProgressData )
+{
+    psOptions->pfnProgress = pfnProgress ? pfnProgress : GDALDummyProgress;
+    psOptions->pProgressData = pProgressData;
+}
diff --git a/apps/ogr2ogr.cpp b/apps/ogr2ogr.cpp
deleted file mode 100644
index 8420b14..0000000
--- a/apps/ogr2ogr.cpp
+++ /dev/null
@@ -1,4121 +0,0 @@
-/******************************************************************************
- * $Id: ogr2ogr.cpp 33112 2016-01-23 17:09:34Z rouault $
- *
- * Project:  OpenGIS Simple Features Reference Implementation
- * Purpose:  Simple client for translating between formats.
- * Author:   Frank Warmerdam, warmerdam at pobox.com
- *
- ******************************************************************************
- * Copyright (c) 1999, Frank Warmerdam
- * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "ogrsf_frmts.h"
-#include "ogr_p.h"
-#include "cpl_conv.h"
-#include "cpl_string.h"
-#include "ogr_api.h"
-#include "gdal.h"
-#include "gdal_alg.h"
-#include "commonutils.h"
-#include <map>
-#include <vector>
-
-CPL_CVSID("$Id: ogr2ogr.cpp 33112 2016-01-23 17:09:34Z rouault $");
-
-static int bSkipFailures = FALSE;
-static int bLayerTransaction = -1;
-static int bForceTransaction = FALSE;
-static int nGroupTransactions = 20000;
-static GIntBig nFIDToFetch = OGRNullFID;
-
-#define COORD_DIM_LAYER_DIM -2
-
-static void Usage(int bShort = TRUE);
-static void Usage(const char* pszAdditionalMsg, int bShort = TRUE);
-
-typedef enum
-{
-    NONE,
-    SEGMENTIZE,
-    SIMPLIFY_PRESERVE_TOPOLOGY,
-} GeomOperation;
-
-typedef struct
-{
-    OGRLayer *   poSrcLayer;
-    GIntBig      nFeaturesRead;
-    int          bPerFeatureCT;
-    OGRLayer    *poDstLayer;
-    OGRCoordinateTransformation **papoCT; // size: poDstLayer->GetLayerDefn()->GetFieldCount();
-    char       ***papapszTransformOptions; // size: poDstLayer->GetLayerDefn()->GetFieldCount();
-    int         *panMap;
-    int          iSrcZField;
-    int          iSrcFIDField;
-    int          iRequestedSrcGeomField;
-    int          bPreserveFID;
-} TargetLayerInfo;
-
-typedef struct
-{
-    OGRLayer         *poSrcLayer;
-    TargetLayerInfo  *psInfo;
-} AssociatedLayers;
-
-typedef struct
-{
-    int bPromoteToMulti;
-    int bConvertToLinear;
-    int bConvertToCurve;
-} GeometryConversion;
-
-class SetupTargetLayer
-{
-public:
-    GDALDataset *poDstDS;
-    char ** papszLCO;
-    OGRSpatialReference *poOutputSRSIn;
-    int bNullifyOutputSRS;
-    char **papszSelFields;
-    int bAppend;
-    int bAddMissingFields;
-    int eGTypeIn;
-    GeometryConversion sGeomConversion;
-    int nCoordDim;
-    int bOverwrite;
-    char** papszFieldTypesToString;
-    char** papszMapFieldType;
-    int bUnsetFieldWidth;
-    int bExplodeCollections;
-    const char* pszZField;
-    char **papszFieldMap;
-    const char* pszWHERE;
-    int bExactFieldNameMatch;
-    int bQuiet;
-    int bForceNullable;
-    int bUnsetDefault;
-    int bUnsetFid;
-    int bPreserveFID;
-    int bCopyMD;
-
-    TargetLayerInfo*            Setup(OGRLayer * poSrcLayer,
-                                      const char *pszNewLayerName);
-};
-
-class LayerTranslator
-{
-public:
-    GDALDataset *poSrcDS;
-    GDALDataset *poODS;
-    int bTransform;
-    int bWrapDateline;
-    const char* pszDateLineOffset;
-    OGRSpatialReference *poOutputSRSIn;
-    int bNullifyOutputSRS;
-    OGRSpatialReference *poUserSourceSRS;
-    OGRCoordinateTransformation *poGCPCoordTrans;
-    int eGTypeIn;
-    GeometryConversion sGeomConversion;
-    int nCoordDim;
-    GeomOperation eGeomOp;
-    double dfGeomOpParam;
-    OGRGeometry* poClipSrc;
-    OGRGeometry *poClipDst;
-    int bExplodeCollectionsIn;
-    vsi_l_offset nSrcFileSize;
-
-    int                 Translate(TargetLayerInfo* psInfo,
-                                  GIntBig nCountLayerFeatures,
-                                  GIntBig* pnReadFeatureCount,
-                                  GDALProgressFunc pfnProgress,
-                                  void *pProgressArg);
-};
-
-static OGRLayer* GetLayerAndOverwriteIfNecessary(GDALDataset *poDstDS,
-                                                 const char* pszNewLayerName,
-                                                 int bOverwrite,
-                                                 int* pbErrorOccured);
-
-static void FreeTargetLayerInfo(TargetLayerInfo* psInfo);
-
-/* -------------------------------------------------------------------- */
-/*                  CheckDestDataSourceNameConsistency()                */
-/* -------------------------------------------------------------------- */
-
-static
-void CheckDestDataSourceNameConsistency(const char* pszDestFilename,
-                                        const char* pszDriverName)
-{
-    int i;
-    char* pszDestExtension = CPLStrdup(CPLGetExtension(pszDestFilename));
-
-    CheckExtensionConsistency(pszDestFilename, pszDriverName);
-
-    static const char* apszBeginName[][2] =  { { "PG:"      , "PG" },
-                                               { "MySQL:"   , "MySQL" },
-                                               { "CouchDB:" , "CouchDB" },
-                                               { "GFT:"     , "GFT" },
-                                               { "MSSQL:"   , "MSSQLSpatial" },
-                                               { "ODBC:"    , "ODBC" },
-                                               { "OCI:"     , "OCI" },
-                                               { "SDE:"     , "SDE" },
-                                               { "WFS:"     , "WFS" },
-                                               { NULL, NULL }
-                                             };
-
-    for(i=0; apszBeginName[i][0] != NULL; i++)
-    {
-        if (EQUALN(pszDestFilename, apszBeginName[i][0], strlen(apszBeginName[i][0])) &&
-            !EQUAL(pszDriverName, apszBeginName[i][1]))
-        {
-            fprintf(stderr,
-                    "Warning: The target file has a name which is normally recognized by the %s driver,\n"
-                    "but the requested output driver is %s. Is it really what you want ?\n",
-                    apszBeginName[i][1],
-                    pszDriverName);
-            break;
-        }
-    }
-
-    CPLFree(pszDestExtension);
-}
-
-/************************************************************************/
-/*                            IsNumber()                               */
-/************************************************************************/
-
-static int IsNumber(const char* pszStr)
-{
-    if (*pszStr == '-' || *pszStr == '+')
-        pszStr ++;
-    if (*pszStr == '.')
-        pszStr ++;
-    return (*pszStr >= '0' && *pszStr <= '9');
-}
-
-/************************************************************************/
-/*                           LoadGeometry()                             */
-/************************************************************************/
-
-static OGRGeometry* LoadGeometry( const char* pszDS,
-                                  const char* pszSQL,
-                                  const char* pszLyr,
-                                  const char* pszWhere)
-{
-    GDALDataset         *poDS;
-    OGRLayer            *poLyr;
-    OGRFeature          *poFeat;
-    OGRGeometry         *poGeom = NULL;
-        
-    poDS = (GDALDataset*) OGROpen( pszDS, FALSE, NULL );
-    if (poDS == NULL)
-        return NULL;
-
-    if (pszSQL != NULL)
-        poLyr = poDS->ExecuteSQL( pszSQL, NULL, NULL ); 
-    else if (pszLyr != NULL)
-        poLyr = poDS->GetLayerByName(pszLyr);
-    else
-        poLyr = poDS->GetLayer(0);
-        
-    if (poLyr == NULL)
-    {
-        fprintf( stderr, "Failed to identify source layer from datasource.\n" );
-        GDALClose(( GDALDatasetH) poDS);
-        return NULL;
-    }
-    
-    if (pszWhere)
-        poLyr->SetAttributeFilter(pszWhere);
-        
-    while ((poFeat = poLyr->GetNextFeature()) != NULL)
-    {
-        OGRGeometry* poSrcGeom = poFeat->GetGeometryRef();
-        if (poSrcGeom)
-        {
-            OGRwkbGeometryType eType = wkbFlatten( poSrcGeom->getGeometryType() );
-            
-            if (poGeom == NULL)
-                poGeom = OGRGeometryFactory::createGeometry( wkbMultiPolygon );
-
-            if( eType == wkbPolygon )
-                ((OGRGeometryCollection*)poGeom)->addGeometry( poSrcGeom );
-            else if( eType == wkbMultiPolygon )
-            {
-                int iGeom;
-                int nGeomCount = OGR_G_GetGeometryCount( (OGRGeometryH)poSrcGeom );
-
-                for( iGeom = 0; iGeom < nGeomCount; iGeom++ )
-                {
-                    ((OGRGeometryCollection*)poGeom)->addGeometry(
-                                ((OGRGeometryCollection*)poSrcGeom)->getGeometryRef(iGeom) );
-                }
-            }
-            else
-            {
-                fprintf( stderr, "ERROR: Geometry not of polygon type.\n" );
-                OGRGeometryFactory::destroyGeometry(poGeom);
-                OGRFeature::DestroyFeature(poFeat);
-                if( pszSQL != NULL )
-                    poDS->ReleaseResultSet( poLyr );
-                GDALClose(( GDALDatasetH) poDS);
-                return NULL;
-            }
-        }
-    
-        OGRFeature::DestroyFeature(poFeat);
-    }
-    
-    if( pszSQL != NULL )
-        poDS->ReleaseResultSet( poLyr );
-    GDALClose(( GDALDatasetH) poDS);
-    
-    return poGeom;
-}
-
-
-/************************************************************************/
-/*                     OGRSplitListFieldLayer                           */
-/************************************************************************/
-
-typedef struct
-{
-    int          iSrcIndex;
-    OGRFieldType eType;
-    int          nMaxOccurences;
-    int          nWidth;
-} ListFieldDesc;
-
-class OGRSplitListFieldLayer : public OGRLayer
-{
-    OGRLayer                    *poSrcLayer;
-    OGRFeatureDefn              *poFeatureDefn;
-    ListFieldDesc               *pasListFields;
-    int                          nListFieldCount;
-    int                          nMaxSplitListSubFields;
-
-    OGRFeature                  *TranslateFeature(OGRFeature* poSrcFeature);
-
-  public:
-                                 OGRSplitListFieldLayer(OGRLayer* poSrcLayer,
-                                                        int nMaxSplitListSubFields);
-                                ~OGRSplitListFieldLayer();
-
-    int                          BuildLayerDefn(GDALProgressFunc pfnProgress,
-                                                void *pProgressArg);
-
-    virtual OGRFeature          *GetNextFeature();
-    virtual OGRFeature          *GetFeature(GIntBig nFID);
-    virtual OGRFeatureDefn      *GetLayerDefn();
-
-    virtual void                 ResetReading() { poSrcLayer->ResetReading(); }
-    virtual int                  TestCapability(const char*) { return FALSE; }
-
-    virtual GIntBig              GetFeatureCount( int bForce = TRUE )
-    {
-        return poSrcLayer->GetFeatureCount(bForce);
-    }
-
-    virtual OGRSpatialReference *GetSpatialRef()
-    {
-        return poSrcLayer->GetSpatialRef();
-    }
-
-    virtual OGRGeometry         *GetSpatialFilter()
-    {
-        return poSrcLayer->GetSpatialFilter();
-    }
-
-    virtual OGRStyleTable       *GetStyleTable()
-    {
-        return poSrcLayer->GetStyleTable();
-    }
-
-    virtual void                 SetSpatialFilter( OGRGeometry *poGeom )
-    {
-        poSrcLayer->SetSpatialFilter(poGeom);
-    }
-
-    virtual void                 SetSpatialFilter( int iGeom, OGRGeometry *poGeom )
-    {
-        poSrcLayer->SetSpatialFilter(iGeom, poGeom);
-    }
-
-    virtual void                 SetSpatialFilterRect( double dfMinX, double dfMinY,
-                                                       double dfMaxX, double dfMaxY )
-    {
-        poSrcLayer->SetSpatialFilterRect(dfMinX, dfMinY, dfMaxX, dfMaxY);
-    }
-
-    virtual void                 SetSpatialFilterRect( int iGeom,
-                                                       double dfMinX, double dfMinY,
-                                                       double dfMaxX, double dfMaxY )
-    {
-        poSrcLayer->SetSpatialFilterRect(iGeom, dfMinX, dfMinY, dfMaxX, dfMaxY);
-    }
-
-    virtual OGRErr               SetAttributeFilter( const char *pszFilter )
-    {
-        return poSrcLayer->SetAttributeFilter(pszFilter);
-    }
-};
-
-/************************************************************************/
-/*                    OGRSplitListFieldLayer()                          */
-/************************************************************************/
-
-OGRSplitListFieldLayer::OGRSplitListFieldLayer(OGRLayer* poSrcLayer,
-                                               int nMaxSplitListSubFields)
-{
-    this->poSrcLayer = poSrcLayer;
-    if (nMaxSplitListSubFields < 0)
-        nMaxSplitListSubFields = INT_MAX;
-    this->nMaxSplitListSubFields = nMaxSplitListSubFields;
-    poFeatureDefn = NULL;
-    pasListFields = NULL;
-    nListFieldCount = 0;
-}
-
-/************************************************************************/
-/*                   ~OGRSplitListFieldLayer()                          */
-/************************************************************************/
-
-OGRSplitListFieldLayer::~OGRSplitListFieldLayer()
-{
-    if( poFeatureDefn )
-        poFeatureDefn->Release();
-
-    CPLFree(pasListFields);
-}
-
-/************************************************************************/
-/*                       BuildLayerDefn()                               */
-/************************************************************************/
-
-int  OGRSplitListFieldLayer::BuildLayerDefn(GDALProgressFunc pfnProgress,
-                                            void *pProgressArg)
-{
-    CPLAssert(poFeatureDefn == NULL);
-    
-    OGRFeatureDefn* poSrcFieldDefn = poSrcLayer->GetLayerDefn();
-    
-    int nSrcFields = poSrcFieldDefn->GetFieldCount();
-    pasListFields =
-            (ListFieldDesc*)CPLCalloc(sizeof(ListFieldDesc), nSrcFields);
-    nListFieldCount = 0;
-    int i;
-    
-    /* Establish the list of fields of list type */
-    for(i=0;i<nSrcFields;i++)
-    {
-        OGRFieldType eType = poSrcFieldDefn->GetFieldDefn(i)->GetType();
-        if (eType == OFTIntegerList ||
-            eType == OFTInteger64List ||
-            eType == OFTRealList ||
-            eType == OFTStringList)
-        {
-            pasListFields[nListFieldCount].iSrcIndex = i;
-            pasListFields[nListFieldCount].eType = eType;
-            if (nMaxSplitListSubFields == 1)
-                pasListFields[nListFieldCount].nMaxOccurences = 1;
-            nListFieldCount++;
-        }
-    }
-
-    if (nListFieldCount == 0)
-        return FALSE;
-
-    /* No need for full scan if the limit is 1. We just to have to create */
-    /* one and a single one field */
-    if (nMaxSplitListSubFields != 1)
-    {
-        poSrcLayer->ResetReading();
-        OGRFeature* poSrcFeature;
-
-        GIntBig nFeatureCount = 0;
-        if (poSrcLayer->TestCapability(OLCFastFeatureCount))
-            nFeatureCount = poSrcLayer->GetFeatureCount();
-        GIntBig nFeatureIndex = 0;
-
-        /* Scan the whole layer to compute the maximum number of */
-        /* items for each field of list type */
-        while( (poSrcFeature = poSrcLayer->GetNextFeature()) != NULL )
-        {
-            for(i=0;i<nListFieldCount;i++)
-            {
-                int nCount = 0;
-                OGRField* psField =
-                        poSrcFeature->GetRawFieldRef(pasListFields[i].iSrcIndex);
-                switch(pasListFields[i].eType)
-                {
-                    case OFTIntegerList:
-                        nCount = psField->IntegerList.nCount;
-                        break;
-                    case OFTRealList:
-                        nCount = psField->RealList.nCount;
-                        break;
-                    case OFTStringList:
-                    {
-                        nCount = psField->StringList.nCount;
-                        char** paList = psField->StringList.paList;
-                        int j;
-                        for(j=0;j<nCount;j++)
-                        {
-                            int nWidth = strlen(paList[j]);
-                            if (nWidth > pasListFields[i].nWidth)
-                                pasListFields[i].nWidth = nWidth;
-                        }
-                        break;
-                    }
-                    default:
-                        CPLAssert(0);
-                        break;
-                }
-                if (nCount > pasListFields[i].nMaxOccurences)
-                {
-                    if (nCount > nMaxSplitListSubFields)
-                        nCount = nMaxSplitListSubFields;
-                    pasListFields[i].nMaxOccurences = nCount;
-                }
-            }
-            OGRFeature::DestroyFeature(poSrcFeature);
-
-            nFeatureIndex ++;
-            if (pfnProgress != NULL && nFeatureCount != 0)
-                pfnProgress(nFeatureIndex * 1.0 / nFeatureCount, "", pProgressArg);
-        }
-    }
-
-    /* Now let's build the target feature definition */
-
-    poFeatureDefn =
-            OGRFeatureDefn::CreateFeatureDefn( poSrcFieldDefn->GetName() );
-    poFeatureDefn->Reference();
-    poFeatureDefn->SetGeomType( wkbNone );
-    
-    for(i=0;i<poSrcFieldDefn->GetGeomFieldCount();i++)
-    {
-        poFeatureDefn->AddGeomFieldDefn(poSrcFieldDefn->GetGeomFieldDefn(i));
-    }
-
-    int iListField = 0;
-    for(i=0;i<nSrcFields;i++)
-    {
-        OGRFieldType eType = poSrcFieldDefn->GetFieldDefn(i)->GetType();
-        if (eType == OFTIntegerList ||
-            eType == OFTInteger64List ||
-            eType == OFTRealList ||
-            eType == OFTStringList)
-        {
-            int nMaxOccurences = pasListFields[iListField].nMaxOccurences;
-            int nWidth = pasListFields[iListField].nWidth;
-            iListField ++;
-            int j;
-            if (nMaxOccurences == 1)
-            {
-                OGRFieldDefn oFieldDefn(poSrcFieldDefn->GetFieldDefn(i)->GetNameRef(),
-                                            (eType == OFTIntegerList) ? OFTInteger :
-                                            (eType == OFTInteger64List) ? OFTInteger64 :
-                                            (eType == OFTRealList) ?    OFTReal :
-                                                                        OFTString);
-                poFeatureDefn->AddFieldDefn(&oFieldDefn);
-            }
-            else
-            {
-                for(j=0;j<nMaxOccurences;j++)
-                {
-                    CPLString osFieldName;
-                    osFieldName.Printf("%s%d",
-                        poSrcFieldDefn->GetFieldDefn(i)->GetNameRef(), j+1);
-                    OGRFieldDefn oFieldDefn(osFieldName.c_str(),
-                                            (eType == OFTIntegerList) ? OFTInteger :
-                                            (eType == OFTInteger64List) ? OFTInteger64 :
-                                            (eType == OFTRealList) ?    OFTReal :
-                                                                        OFTString);
-                    oFieldDefn.SetWidth(nWidth);
-                    poFeatureDefn->AddFieldDefn(&oFieldDefn);
-                }
-            }
-        }
-        else
-        {
-            poFeatureDefn->AddFieldDefn(poSrcFieldDefn->GetFieldDefn(i));
-        }
-    }
-
-    return TRUE;
-}
-
-
-/************************************************************************/
-/*                       TranslateFeature()                             */
-/************************************************************************/
-
-OGRFeature *OGRSplitListFieldLayer::TranslateFeature(OGRFeature* poSrcFeature)
-{
-    if (poSrcFeature == NULL)
-        return NULL;
-    if (poFeatureDefn == NULL)
-        return poSrcFeature;
-
-    OGRFeature* poFeature = OGRFeature::CreateFeature(poFeatureDefn);
-    poFeature->SetFID(poSrcFeature->GetFID());
-    for(int i=0;i<poFeature->GetGeomFieldCount();i++)
-    {
-        poFeature->SetGeomFieldDirectly(i, poSrcFeature->StealGeometry(i));
-    }
-    poFeature->SetStyleString(poFeature->GetStyleString());
-
-    OGRFeatureDefn* poSrcFieldDefn = poSrcLayer->GetLayerDefn();
-    int nSrcFields = poSrcFeature->GetFieldCount();
-    int iSrcField;
-    int iDstField = 0;
-    int iListField = 0;
-    int j;
-    for(iSrcField=0;iSrcField<nSrcFields;iSrcField++)
-    {
-        OGRFieldType eType = poSrcFieldDefn->GetFieldDefn(iSrcField)->GetType();
-        OGRField* psField = poSrcFeature->GetRawFieldRef(iSrcField);
-        switch(eType)
-        {
-            case OFTIntegerList:
-            {
-                int nCount = psField->IntegerList.nCount;
-                if (nCount > nMaxSplitListSubFields)
-                    nCount = nMaxSplitListSubFields;
-                int* paList = psField->IntegerList.paList;
-                for(j=0;j<nCount;j++)
-                    poFeature->SetField(iDstField + j, paList[j]);
-                iDstField += pasListFields[iListField].nMaxOccurences;
-                iListField++;
-                break;
-            }
-            case OFTInteger64List:
-            {
-                int nCount = psField->Integer64List.nCount;
-                if (nCount > nMaxSplitListSubFields)
-                    nCount = nMaxSplitListSubFields;
-                GIntBig* paList = psField->Integer64List.paList;
-                for(j=0;j<nCount;j++)
-                    poFeature->SetField(iDstField + j, paList[j]);
-                iDstField += pasListFields[iListField].nMaxOccurences;
-                iListField++;
-                break;
-            }
-            case OFTRealList:
-            {
-                int nCount = psField->RealList.nCount;
-                if (nCount > nMaxSplitListSubFields)
-                    nCount = nMaxSplitListSubFields;
-                double* paList = psField->RealList.paList;
-                for(j=0;j<nCount;j++)
-                    poFeature->SetField(iDstField + j, paList[j]);
-                iDstField += pasListFields[iListField].nMaxOccurences;
-                iListField++;
-                break;
-            }
-            case OFTStringList:
-            {
-                int nCount = psField->StringList.nCount;
-                if (nCount > nMaxSplitListSubFields)
-                    nCount = nMaxSplitListSubFields;
-                char** paList = psField->StringList.paList;
-                for(j=0;j<nCount;j++)
-                    poFeature->SetField(iDstField + j, paList[j]);
-                iDstField += pasListFields[iListField].nMaxOccurences;
-                iListField++;
-                break;
-            }
-            default:
-                poFeature->SetField(iDstField, psField);
-                iDstField ++;
-                break;
-        }
-    }
-
-    OGRFeature::DestroyFeature(poSrcFeature);
-
-    return poFeature;
-}
-
-/************************************************************************/
-/*                       GetNextFeature()                               */
-/************************************************************************/
-
-OGRFeature *OGRSplitListFieldLayer::GetNextFeature()
-{
-    return TranslateFeature(poSrcLayer->GetNextFeature());
-}
-
-/************************************************************************/
-/*                           GetFeature()                               */
-/************************************************************************/
-
-OGRFeature *OGRSplitListFieldLayer::GetFeature(GIntBig nFID)
-{
-    return TranslateFeature(poSrcLayer->GetFeature(nFID));
-}
-
-/************************************************************************/
-/*                        GetLayerDefn()                                */
-/************************************************************************/
-
-OGRFeatureDefn* OGRSplitListFieldLayer::GetLayerDefn()
-{
-    if (poFeatureDefn == NULL)
-        return poSrcLayer->GetLayerDefn();
-    return poFeatureDefn;
-}
-
-/************************************************************************/
-/*                            GCPCoordTransformation()                  */
-/*                                                                      */
-/*      Apply GCP Transform to points                                   */
-/************************************************************************/
-
-class GCPCoordTransformation : public OGRCoordinateTransformation
-{
-public:
-
-    void               *hTransformArg;
-    int                 bUseTPS;
-    OGRSpatialReference* poSRS;
-
-    GCPCoordTransformation( int nGCPCount,
-                            const GDAL_GCP *pasGCPList,
-                            int  nReqOrder,
-                            OGRSpatialReference* poSRS)
-    {
-        if( nReqOrder < 0 )
-        {
-            bUseTPS = TRUE;
-            hTransformArg = 
-                GDALCreateTPSTransformer( nGCPCount, pasGCPList, FALSE );
-        }
-        else
-        {
-            bUseTPS = FALSE;
-            hTransformArg = 
-                GDALCreateGCPTransformer( nGCPCount, pasGCPList, nReqOrder, FALSE );
-        }
-        this->poSRS = poSRS;
-        if( poSRS) 
-            poSRS->Reference();
-    }
-
-    int IsValid() const { return hTransformArg != NULL; }
-
-    virtual ~GCPCoordTransformation()
-    {
-        if( hTransformArg != NULL )
-        {
-            if( bUseTPS )
-                GDALDestroyTPSTransformer(hTransformArg);
-            else
-                GDALDestroyGCPTransformer(hTransformArg);
-        }
-        if( poSRS) 
-            poSRS->Dereference();
-    }
-
-    virtual OGRSpatialReference *GetSourceCS() { return poSRS; }
-    virtual OGRSpatialReference *GetTargetCS() { return poSRS; }
-
-    virtual int Transform( int nCount, 
-                           double *x, double *y, double *z = NULL )
-    {
-        int *pabSuccess = (int *) CPLMalloc(sizeof(int) * nCount );
-        int bOverallSuccess, i;
-
-        bOverallSuccess = TransformEx( nCount, x, y, z, pabSuccess );
-
-        for( i = 0; i < nCount; i++ )
-        {
-            if( !pabSuccess[i] )
-            {
-                bOverallSuccess = FALSE;
-                break;
-            }
-        }
-
-        CPLFree( pabSuccess );
-
-        return bOverallSuccess;
-    }
-
-    virtual int TransformEx( int nCount, 
-                             double *x, double *y, double *z = NULL,
-                             int *pabSuccess = NULL )
-    {
-        if( bUseTPS )
-            return GDALTPSTransform( hTransformArg, FALSE, 
-                                 nCount, x, y, z, pabSuccess );
-        else
-            return GDALGCPTransform( hTransformArg, FALSE, 
-                                 nCount, x, y, z, pabSuccess );
-    }
-};
-
-/************************************************************************/
-/*                            CompositeCT                               */
-/************************************************************************/
-
-class CompositeCT : public OGRCoordinateTransformation
-{
-public:
-
-    OGRCoordinateTransformation* poCT1;
-    OGRCoordinateTransformation* poCT2;
-
-    CompositeCT( OGRCoordinateTransformation* poCT1, /* will not be deleted */
-                 OGRCoordinateTransformation* poCT2  /* deleted with OGRCoordinateTransformation::DestroyCT() */ )
-    {
-        this->poCT1 = poCT1;
-        this->poCT2 = poCT2;
-    }
-
-    virtual ~CompositeCT()
-    {
-        OGRCoordinateTransformation::DestroyCT(poCT2);
-    }
-
-    virtual OGRSpatialReference *GetSourceCS()
-    {
-        return poCT1 ? poCT1->GetSourceCS() :
-               poCT2 ? poCT2->GetSourceCS() : NULL;
-    }
-
-    virtual OGRSpatialReference *GetTargetCS()
-    {
-        return poCT2 ? poCT2->GetTargetCS() :
-               poCT1 ? poCT1->GetTargetCS() : NULL;
-    }
-
-    virtual int Transform( int nCount, 
-                           double *x, double *y, double *z = NULL )
-    {
-        int nResult = TRUE;
-        if( poCT1 )
-            nResult = poCT1->Transform(nCount, x, y, z);
-        if( nResult && poCT2 )
-            nResult = poCT2->Transform(nCount, x, y, z);
-        return nResult;
-    }
-
-    virtual int TransformEx( int nCount, 
-                             double *x, double *y, double *z = NULL,
-                             int *pabSuccess = NULL )
-    {
-        int nResult = TRUE;
-        if( poCT1 )
-            nResult = poCT1->TransformEx(nCount, x, y, z, pabSuccess);
-        if( nResult && poCT2 )
-            nResult = poCT2->TransformEx(nCount, x, y, z, pabSuccess);
-        return nResult;
-    }
-};
-
-/************************************************************************/
-/*                        ApplySpatialFilter()                          */
-/************************************************************************/
-
-void ApplySpatialFilter(OGRLayer* poLayer, OGRGeometry* poSpatialFilter,
-                        OGRSpatialReference* poSpatSRS,
-                        const char* pszGeomField,
-                        OGRSpatialReference* poSourceSRS)
-{
-    if( poSpatialFilter != NULL )
-    {
-        OGRGeometry* poSpatialFilterReprojected = NULL;
-        if( poSpatSRS )
-        {
-            poSpatialFilterReprojected = poSpatialFilter->clone();
-            poSpatialFilterReprojected->assignSpatialReference(poSpatSRS);
-            OGRSpatialReference* poSpatialFilterTargetSRS  = poSourceSRS ? poSourceSRS : poLayer->GetSpatialRef();
-            if( poSpatialFilterTargetSRS )
-                poSpatialFilterReprojected->transformTo(poSpatialFilterTargetSRS);
-            else
-                fprintf(stderr, "Warning: cannot determine layer SRS for %s.\n", poLayer->GetDescription());
-        }
-
-        if( pszGeomField != NULL )
-        {
-            int iGeomField = poLayer->GetLayerDefn()->GetGeomFieldIndex(pszGeomField);
-            if( iGeomField >= 0 )
-                poLayer->SetSpatialFilter( iGeomField,
-                    poSpatialFilterReprojected ? poSpatialFilterReprojected : poSpatialFilter );
-            else
-                printf("WARNING: Cannot find geometry field %s.\n",
-                    pszGeomField);
-        }
-        else
-            poLayer->SetSpatialFilter( poSpatialFilterReprojected ? poSpatialFilterReprojected : poSpatialFilter );
-
-        delete poSpatialFilterReprojected;
-    }
-}
-             
-/************************************************************************/
-/*                          GetFieldType()                              */
-/************************************************************************/
-
-int GetFieldType(const char* pszArg, int* pnSubFieldType)
-{
-    *pnSubFieldType = OFSTNone;
-    int nLengthBeforeParenthesis = strlen(pszArg);
-    const char* pszOpenParenthesis = strchr(pszArg, '(');
-    if( pszOpenParenthesis )
-        nLengthBeforeParenthesis = pszOpenParenthesis - pszArg;
-    for( int iType = 0; iType <= (int) OFTMaxType; iType++ )
-    {
-         const char* pszFieldTypeName = OGRFieldDefn::GetFieldTypeName(
-                                                       (OGRFieldType)iType);
-         if( EQUALN(pszArg,pszFieldTypeName,nLengthBeforeParenthesis) &&
-             pszFieldTypeName[nLengthBeforeParenthesis] == '\0' )
-         {
-             if( pszOpenParenthesis != NULL )
-             {
-                 *pnSubFieldType = -1;
-                 CPLString osArgSubType = pszOpenParenthesis + 1;
-                 if( osArgSubType.size() && osArgSubType[osArgSubType.size()-1] == ')' )
-                     osArgSubType.resize(osArgSubType.size()-1);
-                 for( int iSubType = 0; iSubType <= (int) OFSTMaxSubType; iSubType++ )
-                 {
-                     const char* pszFieldSubTypeName = OGRFieldDefn::GetFieldSubTypeName(
-                                                       (OGRFieldSubType)iSubType);
-                     if( EQUAL( pszFieldSubTypeName, osArgSubType ) )
-                     {
-                         *pnSubFieldType = iSubType;
-                         break;
-                     }
-                 }
-             }
-             return iType;
-         }
-     }
-     return -1;
-}
-             
-/************************************************************************/
-/*                           IsFieldType()                              */
-/************************************************************************/
-
-static int IsFieldType(const char* pszArg)
-{
-    int iSubType;
-    return GetFieldType(pszArg, &iSubType) >= 0 && iSubType >= 0;
-}
-
-/************************************************************************/
-/*                                main()                                */
-/************************************************************************/
-
-#define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg) \
-    do { if (iArg + nExtraArg >= nArgc) \
-        Usage(CPLSPrintf("%s option requires %d argument(s)", papszArgv[iArg], nExtraArg)); } while(0)
-
-int main( int nArgc, char ** papszArgv )
-
-{
-    int          nRetCode = 0;
-    int          bQuiet = FALSE;
-    int          bFormatExplicitlySet = FALSE;
-    const char  *pszFormat = "ESRI Shapefile";
-    const char  *pszDataSource = NULL;
-    const char  *pszDestDataSource = NULL;
-    char        **papszLayers = NULL;
-    char        **papszDSCO = NULL, **papszLCO = NULL;
-    int         bTransform = FALSE;
-    int         bAppend = FALSE, bUpdate = FALSE, bOverwrite = FALSE;
-    int         bAddMissingFields = FALSE;
-    const char  *pszOutputSRSDef = NULL;
-    const char  *pszSourceSRSDef = NULL;
-    OGRSpatialReference *poOutputSRS = NULL;
-    int         bNullifyOutputSRS = FALSE;
-    int         bExactFieldNameMatch = TRUE;
-    OGRSpatialReference *poSourceSRS = NULL;
-    char        *pszNewLayerName = NULL;
-    const char  *pszWHERE = NULL;
-    OGRGeometry *poSpatialFilter = NULL;
-    const char  *pszGeomField = NULL;
-    const char  *pszSelect;
-    char        **papszSelFields = NULL;
-    const char  *pszSQLStatement = NULL;
-    const char  *pszDialect = NULL;
-    int         eGType = -2;
-    GeometryConversion sGeomConversion;
-    sGeomConversion.bPromoteToMulti = FALSE;
-    sGeomConversion.bConvertToLinear = FALSE;
-    sGeomConversion.bConvertToCurve = FALSE;
-    GeomOperation eGeomOp = NONE;
-    double       dfGeomOpParam = 0;
-    char        **papszFieldTypesToString = NULL;
-    char        **papszMapFieldType = NULL;
-    int          bUnsetFieldWidth = FALSE;
-    int          bDisplayProgress = FALSE;
-    GDALProgressFunc pfnProgress = NULL;
-    void        *pProgressArg = NULL;
-    int          bWrapDateline = FALSE;
-    const char  *pszDateLineOffset = "10";
-    int          bClipSrc = FALSE;
-    OGRGeometry* poClipSrc = NULL;
-    const char  *pszClipSrcDS = NULL;
-    const char  *pszClipSrcSQL = NULL;
-    const char  *pszClipSrcLayer = NULL;
-    const char  *pszClipSrcWhere = NULL;
-    OGRGeometry *poClipDst = NULL;
-    const char  *pszClipDstDS = NULL;
-    const char  *pszClipDstSQL = NULL;
-    const char  *pszClipDstLayer = NULL;
-    const char  *pszClipDstWhere = NULL;
-    int          bSplitListFields = FALSE;
-    int          nMaxSplitListSubFields = -1;
-    int          bExplodeCollections = FALSE;
-    const char  *pszZField = NULL;
-    const char  *pszFieldMap = NULL;
-    char        **papszFieldMap = NULL;
-    int          nCoordDim = -1;
-    char       **papszOpenOptions = NULL;
-    char       **papszDestOpenOptions = NULL;
-    int          bForceNullable = FALSE;
-    int          bUnsetDefault = FALSE;
-    int          bUnsetFid = FALSE;
-    int          bPreserveFID = FALSE;
-    int          bCopyMD = TRUE;
-    char       **papszMetadataOptions = NULL;
-    CPLString    osSpatSRSDef;
-    OGRSpatialReference* poSpatSRS = NULL;
-
-    int          nGCPCount = 0;
-    GDAL_GCP    *pasGCPs = NULL;
-    int          nTransformOrder = 0;  /* Default to 0 for now... let the lib decide */
-
-    /* Check strict compilation and runtime library version as we use C++ API */
-    if (! GDAL_CHECK_VERSION(papszArgv[0]))
-        exit(1);
-
-    EarlySetConfigOptions(nArgc, papszArgv);
-
-/* -------------------------------------------------------------------- */
-/*      Register format(s).                                             */
-/* -------------------------------------------------------------------- */
-    OGRRegisterAll();
-
-/* -------------------------------------------------------------------- */
-/*      Processing command line arguments.                              */
-/* -------------------------------------------------------------------- */
-    nArgc = OGRGeneralCmdLineProcessor( nArgc, &papszArgv, 0 );
-    
-    if( nArgc < 1 )
-        exit( -nArgc );
-
-    for( int iArg = 1; iArg < nArgc; iArg++ )
-    {
-        if( EQUAL(papszArgv[iArg], "--utility_version") )
-        {
-            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
-                   papszArgv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
-            return 0;
-        }
-        else if( EQUAL(papszArgv[iArg],"--help") )
-            Usage();
-        else if ( EQUAL(papszArgv[iArg], "--long-usage") )
-        {
-            Usage(FALSE);
-        }
-
-        else if( EQUAL(papszArgv[iArg],"-q") || EQUAL(papszArgv[iArg],"-quiet") )
-        {
-            bQuiet = TRUE;
-        }
-        else if( EQUAL(papszArgv[iArg],"-f") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            bFormatExplicitlySet = TRUE;
-            pszFormat = papszArgv[++iArg];
-        }
-        else if( EQUAL(papszArgv[iArg],"-dsco") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            papszDSCO = CSLAddString(papszDSCO, papszArgv[++iArg] );
-        }
-        else if( EQUAL(papszArgv[iArg],"-lco") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            papszLCO = CSLAddString(papszLCO, papszArgv[++iArg] );
-        }
-        else if( EQUAL(papszArgv[iArg],"-oo") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            papszOpenOptions = CSLAddString(papszOpenOptions, papszArgv[++iArg] );
-        }
-        else if( EQUAL(papszArgv[iArg],"-doo") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            papszDestOpenOptions = CSLAddString(papszDestOpenOptions, papszArgv[++iArg] );
-        }
-        else if( EQUAL(papszArgv[iArg],"-preserve_fid") )
-        {
-            bPreserveFID = TRUE;
-        }
-        else if( EQUALN(papszArgv[iArg],"-skip",5) )
-        {
-            bSkipFailures = TRUE;
-            nGroupTransactions = 1; /* #2409 */
-        }
-        else if( EQUAL(papszArgv[iArg],"-append") )
-        {
-            bAppend = TRUE;
-            bUpdate = TRUE;
-        }
-        else if( EQUAL(papszArgv[iArg],"-overwrite") )
-        {
-            bOverwrite = TRUE;
-            bUpdate = TRUE;
-        }
-        else if( EQUAL(papszArgv[iArg],"-addfields") )
-        {
-            bAddMissingFields = TRUE;
-            bAppend = TRUE;
-            bUpdate = TRUE;
-        }
-        else if( EQUAL(papszArgv[iArg],"-update") )
-        {
-            bUpdate = TRUE;
-        }
-        else if( EQUAL(papszArgv[iArg],"-relaxedFieldNameMatch") )
-        {
-            bExactFieldNameMatch = FALSE;
-        }
-        else if( EQUAL(papszArgv[iArg],"-fid") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            nFIDToFetch = CPLAtoGIntBig(papszArgv[++iArg]);
-        }
-        else if( EQUAL(papszArgv[iArg],"-sql") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszSQLStatement = papszArgv[++iArg];
-        }
-        else if( EQUAL(papszArgv[iArg],"-dialect") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszDialect = papszArgv[++iArg];
-        }
-        else if( EQUAL(papszArgv[iArg],"-nln") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszNewLayerName = CPLStrdup(papszArgv[++iArg]);
-        }
-        else if( EQUAL(papszArgv[iArg],"-nlt") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            int bIs3D = FALSE;
-            CPLString osGeomName = papszArgv[iArg+1];
-            if (strlen(papszArgv[iArg+1]) > 3 &&
-                EQUALN(papszArgv[iArg+1] + strlen(papszArgv[iArg+1]) - 3, "25D", 3))
-            {
-                bIs3D = TRUE;
-                osGeomName.resize(osGeomName.size() - 3);
-            }
-            else if (strlen(papszArgv[iArg+1]) > 1 &&
-                EQUALN(papszArgv[iArg+1] + strlen(papszArgv[iArg+1]) - 1, "Z", 1))
-            {
-                bIs3D = TRUE;
-                osGeomName.resize(osGeomName.size() - 1);
-            }
-            if( EQUAL(osGeomName,"NONE") )
-                eGType = wkbNone;
-            else if( EQUAL(osGeomName,"GEOMETRY") )
-                eGType = wkbUnknown;
-            else if( EQUAL(osGeomName,"PROMOTE_TO_MULTI") )
-                sGeomConversion.bPromoteToMulti = TRUE;
-            else if( EQUAL(osGeomName,"CONVERT_TO_LINEAR") )
-                sGeomConversion.bConvertToLinear = TRUE;
-            else if( EQUAL(osGeomName,"CONVERT_TO_CURVE") )
-                sGeomConversion.bConvertToCurve = TRUE;
-            else
-            {
-                eGType = OGRFromOGCGeomType(osGeomName);
-                if (eGType == wkbUnknown)
-                {
-                    fprintf( stderr, "-nlt %s: type not recognised.\n",
-                            papszArgv[iArg+1] );
-                    exit( 1 );
-                }
-            }
-            if (eGType != -2 && eGType != wkbNone && bIs3D)
-                eGType = wkbSetZ((OGRwkbGeometryType)eGType);
-
-            iArg++;
-        }
-        else if( EQUAL(papszArgv[iArg],"-dim")  )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            if( EQUAL(papszArgv[iArg+1], "layer_dim") )
-                nCoordDim = COORD_DIM_LAYER_DIM;
-            else
-            {
-                nCoordDim = atoi(papszArgv[iArg+1]);
-                if( nCoordDim != 2 && nCoordDim != 3 )
-                {
-                    fprintf( stderr, "-dim %s: value not handled.\n",
-                            papszArgv[iArg+1] );
-                    exit( 1 );
-                }
-            }
-            iArg ++;
-        }
-        else if( EQUAL(papszArgv[iArg],"-tg") ||
-                 EQUAL(papszArgv[iArg],"-gt") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            ++iArg;
-            /* If skipfailures is already set we should not
-            modify nGroupTransactions = 1  #2409 */
-            if ( !bSkipFailures )
-            {
-                if( EQUAL(papszArgv[iArg], "unlimited") )
-                    nGroupTransactions = -1;
-                else
-                    nGroupTransactions = atoi(papszArgv[iArg]);
-            }
-        }
-        else if ( EQUAL(papszArgv[iArg],"-ds_transaction") )
-        {
-            bLayerTransaction = FALSE;
-            bForceTransaction = TRUE;
-        }
-        /* Undocumented. Just a provision. Default behaviour should be OK */
-        else if ( EQUAL(papszArgv[iArg],"-lyr_transaction") )
-        {
-            bLayerTransaction = TRUE;
-        }
-        else if( EQUAL(papszArgv[iArg],"-s_srs") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszSourceSRSDef = papszArgv[++iArg];
-        }
-        else if( EQUAL(papszArgv[iArg],"-a_srs") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszOutputSRSDef = papszArgv[++iArg];
-            if (EQUAL(pszOutputSRSDef, "NULL") ||
-                EQUAL(pszOutputSRSDef, "NONE"))
-            {
-                pszOutputSRSDef = NULL;
-                bNullifyOutputSRS = TRUE;
-            }
-        }
-        else if( EQUAL(papszArgv[iArg],"-t_srs") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszOutputSRSDef = papszArgv[++iArg];
-            bTransform = TRUE;
-        }
-        else if( EQUAL(papszArgv[iArg],"-spat") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(4);
-            OGRLinearRing  oRing;
-
-            oRing.addPoint( CPLAtof(papszArgv[iArg+1]), CPLAtof(papszArgv[iArg+2]) );
-            oRing.addPoint( CPLAtof(papszArgv[iArg+1]), CPLAtof(papszArgv[iArg+4]) );
-            oRing.addPoint( CPLAtof(papszArgv[iArg+3]), CPLAtof(papszArgv[iArg+4]) );
-            oRing.addPoint( CPLAtof(papszArgv[iArg+3]), CPLAtof(papszArgv[iArg+2]) );
-            oRing.addPoint( CPLAtof(papszArgv[iArg+1]), CPLAtof(papszArgv[iArg+2]) );
-
-            poSpatialFilter = OGRGeometryFactory::createGeometry(wkbPolygon);
-            ((OGRPolygon *) poSpatialFilter)->addRing( &oRing );
-            iArg += 4;
-        }
-        else if( EQUAL(papszArgv[iArg],"-spat_srs") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            osSpatSRSDef = papszArgv[++iArg];
-        }
-        else if( EQUAL(papszArgv[iArg],"-geomfield") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszGeomField = papszArgv[++iArg];
-        }
-        else if( EQUAL(papszArgv[iArg],"-where") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszWHERE = papszArgv[++iArg];
-        }
-        else if( EQUAL(papszArgv[iArg],"-select") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszSelect = papszArgv[++iArg];
-            papszSelFields = CSLTokenizeStringComplex(pszSelect, " ,", 
-                                                      FALSE, FALSE );
-        }
-        else if( EQUAL(papszArgv[iArg],"-segmentize") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            eGeomOp = SEGMENTIZE;
-            dfGeomOpParam = CPLAtof(papszArgv[++iArg]);
-        }
-        else if( EQUAL(papszArgv[iArg],"-simplify") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            eGeomOp = SIMPLIFY_PRESERVE_TOPOLOGY;
-            dfGeomOpParam = CPLAtof(papszArgv[++iArg]);
-        }
-        else if( EQUAL(papszArgv[iArg],"-fieldTypeToString") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            papszFieldTypesToString =
-                    CSLTokenizeStringComplex(papszArgv[++iArg], " ,", 
-                                             FALSE, FALSE );
-            char** iter = papszFieldTypesToString;
-            while(*iter)
-            {
-                if (IsFieldType(*iter))
-                {
-                    /* Do nothing */
-                }
-                else if (EQUAL(*iter, "All"))
-                {
-                    CSLDestroy(papszFieldTypesToString);
-                    papszFieldTypesToString = NULL;
-                    papszFieldTypesToString = CSLAddString(papszFieldTypesToString, "All");
-                    break;
-                }
-                else
-                {
-                    Usage(CPLSPrintf("Unhandled type for fieldTypeToString option : %s",
-                            *iter));
-                }
-                iter ++;
-            }
-        }
-        else if( EQUAL(papszArgv[iArg],"-mapFieldType") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            papszMapFieldType =
-                    CSLTokenizeStringComplex(papszArgv[++iArg], " ,", 
-                                             FALSE, FALSE );
-            char** iter = papszMapFieldType;
-            while(*iter)
-            {
-                char* pszKey = NULL;
-                const char* pszValue = CPLParseNameValue(*iter, &pszKey);
-                if( pszKey && pszValue)
-                {
-                    if( !((IsFieldType(pszKey) || EQUAL(pszKey, "All")) && IsFieldType(pszValue)) )
-                    {
-                        Usage("Invalid value for -mapFieldType");
-                    }
-                }
-                CPLFree(pszKey);
-                iter ++;
-            }
-        }
-        else if( EQUAL(papszArgv[iArg],"-unsetFieldWidth") )
-        {
-            bUnsetFieldWidth = TRUE;
-        }
-        else if( EQUAL(papszArgv[iArg],"-progress") )
-        {
-            bDisplayProgress = TRUE;
-        }
-        else if( EQUAL(papszArgv[iArg],"-wrapdateline") )
-        {
-            bWrapDateline = TRUE;
-        }
-        else if( EQUAL(papszArgv[iArg],"-datelineoffset") && iArg < nArgc-1 )
-        {
-            pszDateLineOffset = papszArgv[++iArg];
-        }        
-        else if( EQUAL(papszArgv[iArg],"-clipsrc") )
-        {
-            if (iArg + 1 >= nArgc)
-                Usage(CPLSPrintf("%s option requires 1 or 4 arguments", papszArgv[iArg]));
-
-            VSIStatBufL  sStat;
-            bClipSrc = TRUE;
-            if ( IsNumber(papszArgv[iArg+1])
-                 && papszArgv[iArg+2] != NULL 
-                 && papszArgv[iArg+3] != NULL 
-                 && papszArgv[iArg+4] != NULL)
-            {
-                OGRLinearRing  oRing;
-
-                oRing.addPoint( CPLAtof(papszArgv[iArg+1]), CPLAtof(papszArgv[iArg+2]) );
-                oRing.addPoint( CPLAtof(papszArgv[iArg+1]), CPLAtof(papszArgv[iArg+4]) );
-                oRing.addPoint( CPLAtof(papszArgv[iArg+3]), CPLAtof(papszArgv[iArg+4]) );
-                oRing.addPoint( CPLAtof(papszArgv[iArg+3]), CPLAtof(papszArgv[iArg+2]) );
-                oRing.addPoint( CPLAtof(papszArgv[iArg+1]), CPLAtof(papszArgv[iArg+2]) );
-
-                poClipSrc = OGRGeometryFactory::createGeometry(wkbPolygon);
-                ((OGRPolygon *) poClipSrc)->addRing( &oRing );
-                iArg += 4;
-            }
-            else if ((EQUALN(papszArgv[iArg+1], "POLYGON", 7) ||
-                      EQUALN(papszArgv[iArg+1], "MULTIPOLYGON", 12)) &&
-                      VSIStatL(papszArgv[iArg+1], &sStat) != 0)
-            {
-                char* pszTmp = (char*) papszArgv[iArg+1];
-                OGRGeometryFactory::createFromWkt(&pszTmp, NULL, &poClipSrc);
-                if (poClipSrc == NULL)
-                {
-                    Usage("Invalid geometry. Must be a valid POLYGON or MULTIPOLYGON WKT");
-                }
-                iArg ++;
-            }
-            else if (EQUAL(papszArgv[iArg+1], "spat_extent") )
-            {
-                iArg ++;
-            }
-            else
-            {
-                pszClipSrcDS = papszArgv[iArg+1];
-                iArg ++;
-            }
-        }
-        else if( EQUAL(papszArgv[iArg],"-clipsrcsql")  )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszClipSrcSQL = papszArgv[iArg+1];
-            iArg ++;
-        }
-        else if( EQUAL(papszArgv[iArg],"-clipsrclayer") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszClipSrcLayer = papszArgv[iArg+1];
-            iArg ++;
-        }
-        else if( EQUAL(papszArgv[iArg],"-clipsrcwhere") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszClipSrcWhere = papszArgv[iArg+1];
-            iArg ++;
-        }
-        else if( EQUAL(papszArgv[iArg],"-clipdst") )
-        {
-            if (iArg + 1 >= nArgc)
-                Usage(CPLSPrintf("%s option requires 1 or 4 arguments", papszArgv[iArg]));
-
-            VSIStatBufL  sStat;
-            if ( IsNumber(papszArgv[iArg+1])
-                 && papszArgv[iArg+2] != NULL 
-                 && papszArgv[iArg+3] != NULL 
-                 && papszArgv[iArg+4] != NULL)
-            {
-                OGRLinearRing  oRing;
-
-                oRing.addPoint( CPLAtof(papszArgv[iArg+1]), CPLAtof(papszArgv[iArg+2]) );
-                oRing.addPoint( CPLAtof(papszArgv[iArg+1]), CPLAtof(papszArgv[iArg+4]) );
-                oRing.addPoint( CPLAtof(papszArgv[iArg+3]), CPLAtof(papszArgv[iArg+4]) );
-                oRing.addPoint( CPLAtof(papszArgv[iArg+3]), CPLAtof(papszArgv[iArg+2]) );
-                oRing.addPoint( CPLAtof(papszArgv[iArg+1]), CPLAtof(papszArgv[iArg+2]) );
-
-                poClipDst = OGRGeometryFactory::createGeometry(wkbPolygon);
-                ((OGRPolygon *) poClipDst)->addRing( &oRing );
-                iArg += 4;
-            }
-            else if ((EQUALN(papszArgv[iArg+1], "POLYGON", 7) ||
-                      EQUALN(papszArgv[iArg+1], "MULTIPOLYGON", 12)) &&
-                      VSIStatL(papszArgv[iArg+1], &sStat) != 0)
-            {
-                char* pszTmp = (char*) papszArgv[iArg+1];
-                OGRGeometryFactory::createFromWkt(&pszTmp, NULL, &poClipDst);
-                if (poClipDst == NULL)
-                {
-                    Usage("Invalid geometry. Must be a valid POLYGON or MULTIPOLYGON WKT");
-                }
-                iArg ++;
-            }
-            else
-            {
-                pszClipDstDS = papszArgv[iArg+1];
-                iArg ++;
-            }
-        }
-        else if( EQUAL(papszArgv[iArg],"-clipdstsql") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszClipDstSQL = papszArgv[iArg+1];
-            iArg ++;
-        }
-        else if( EQUAL(papszArgv[iArg],"-clipdstlayer") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszClipDstLayer = papszArgv[iArg+1];
-            iArg ++;
-        }
-        else if( EQUAL(papszArgv[iArg],"-clipdstwhere") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszClipDstWhere = papszArgv[iArg+1];
-            iArg ++;
-        }
-        else if( EQUAL(papszArgv[iArg],"-splitlistfields") )
-        {
-            bSplitListFields = TRUE;
-        }
-        else if ( EQUAL(papszArgv[iArg],"-maxsubfields") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            if (IsNumber(papszArgv[iArg+1]))
-            {
-                int nTemp = atoi(papszArgv[iArg+1]);
-                if (nTemp > 0)
-                {
-                    nMaxSplitListSubFields = nTemp;
-                    iArg ++;
-                }
-            }
-        }
-        else if( EQUAL(papszArgv[iArg],"-explodecollections") )
-        {
-            bExplodeCollections = TRUE;
-        }
-        else if( EQUAL(papszArgv[iArg],"-zfield") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszZField = papszArgv[iArg+1];
-            iArg ++;
-        }
-        else if( EQUAL(papszArgv[iArg],"-gcp") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(4);
-            char* endptr = NULL;
-            /* -gcp pixel line easting northing [elev] */
-
-            nGCPCount++;
-            pasGCPs = (GDAL_GCP *) 
-                CPLRealloc( pasGCPs, sizeof(GDAL_GCP) * nGCPCount );
-            GDALInitGCPs( 1, pasGCPs + nGCPCount - 1 );
-
-            pasGCPs[nGCPCount-1].dfGCPPixel = CPLAtof(papszArgv[++iArg]);
-            pasGCPs[nGCPCount-1].dfGCPLine = CPLAtof(papszArgv[++iArg]);
-            pasGCPs[nGCPCount-1].dfGCPX = CPLAtof(papszArgv[++iArg]);
-            pasGCPs[nGCPCount-1].dfGCPY = CPLAtof(papszArgv[++iArg]);
-            if( papszArgv[iArg+1] != NULL 
-                && (CPLStrtod(papszArgv[iArg+1], &endptr) != 0.0 || papszArgv[iArg+1][0] == '0') )
-            {
-                /* Check that last argument is really a number and not a filename */
-                /* looking like a number (see ticket #863) */
-                if (endptr && *endptr == 0)
-                    pasGCPs[nGCPCount-1].dfGCPZ = CPLAtof(papszArgv[++iArg]);
-            }
-
-            /* should set id and info? */
-        }
-        else if( EQUAL(papszArgv[iArg],"-tps") )
-        {
-            nTransformOrder = -1;
-        }
-        else if( EQUAL(papszArgv[iArg],"-order") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            nTransformOrder = atoi( papszArgv[++iArg] );
-        }
-        else if( EQUAL(papszArgv[iArg],"-fieldmap") && papszArgv[iArg+1] != NULL)
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszFieldMap = papszArgv[++iArg];
-            papszFieldMap = CSLTokenizeStringComplex(pszFieldMap, ",", 
-                                                      FALSE, FALSE );
-        }
-        else if( EQUAL(papszArgv[iArg],"-forceNullable") )
-        {
-            bForceNullable = TRUE;
-        }
-        else if( EQUAL(papszArgv[iArg],"-unsetDefault") )
-        {
-            bUnsetDefault = TRUE;
-        }
-        else if( EQUAL(papszArgv[iArg],"-unsetFid") )
-        {
-            bUnsetFid = TRUE;
-        }
-        else if( EQUAL(papszArgv[iArg],"-nomd") )
-        {
-            bCopyMD = FALSE;
-        }
-        else if( EQUAL(papszArgv[iArg],"-mo") )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            papszMetadataOptions = CSLAddString( papszMetadataOptions,
-                                                 papszArgv[++iArg] );
-        }
-        else if( papszArgv[iArg][0] == '-' )
-        {
-            Usage(CPLSPrintf("Unknown option name '%s'", papszArgv[iArg]));
-        }
-        else if( pszDestDataSource == NULL )
-            pszDestDataSource = papszArgv[iArg];
-        else if( pszDataSource == NULL )
-            pszDataSource = papszArgv[iArg];
-        else
-            papszLayers = CSLAddString( papszLayers, papszArgv[iArg] );
-    }
-
-    if( pszDataSource == NULL )
-    {
-        if( pszDestDataSource == NULL )
-            Usage("no target datasource provided");
-        else
-            Usage("no source datasource provided");
-    }
-
-    if( bPreserveFID && bExplodeCollections )
-    {
-        Usage("cannot use -preserve_fid and -explodecollections at the same time.");
-    }
-
-    if (pszFieldMap && !bAppend)
-    {
-        Usage("if -fieldmap is specified, -append must also be specified");
-    }
-
-    if (pszFieldMap && bAddMissingFields)
-    {
-        Usage("if -addfields is specified, -fieldmap cannot be used.");
-    }
-
-    if( papszFieldTypesToString && papszMapFieldType )
-    {
-        Usage("-fieldTypeToString and -mapFieldType are exclusive.");
-    }
-
-    if( pszSourceSRSDef != NULL && pszOutputSRSDef == NULL && osSpatSRSDef.size() == 0 )
-    {
-        Usage("if -s_srs is specified, -t_srs and/or -spat_srs must also be specified.");
-    }
-
-    if( bClipSrc && pszClipSrcDS != NULL)
-    {
-        poClipSrc = LoadGeometry(pszClipSrcDS, pszClipSrcSQL, pszClipSrcLayer, pszClipSrcWhere);
-        if (poClipSrc == NULL)
-        {
-            Usage("cannot load source clip geometry");
-        }
-    }
-    else if( bClipSrc && poClipSrc == NULL )
-    {
-        if (poSpatialFilter)
-            poClipSrc = poSpatialFilter->clone();
-        if (poClipSrc == NULL)
-        {
-            Usage("-clipsrc must be used with -spat option or a\n"
-                             "bounding box, WKT string or datasource must be specified");
-        }
-    }
-    
-    if( pszClipDstDS != NULL)
-    {
-        poClipDst = LoadGeometry(pszClipDstDS, pszClipDstSQL, pszClipDstLayer, pszClipDstWhere);
-        if (poClipDst == NULL)
-        {
-            Usage("cannot load dest clip geometry");
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Open data source.                                               */
-/* -------------------------------------------------------------------- */
-    GDALDataset         *poDS;
-    GDALDataset         *poODS = NULL;
-    GDALDriver          *poDriver = NULL;
-    int                  bCloseODS = TRUE;
-
-    /* Avoid opening twice the same datasource if it is both the input and output */
-    /* Known to cause problems with at least FGdb and SQlite drivers. See #4270 */
-    if (bUpdate && strcmp(pszDestDataSource, pszDataSource) == 0)
-    {
-        poODS = poDS = (GDALDataset*) GDALOpenEx( pszDataSource,
-                GDAL_OF_UPDATE | GDAL_OF_VECTOR, NULL, papszOpenOptions, NULL );
-        if( poDS != NULL )
-            poDriver = poDS->GetDriver();
-
-        /* Restrict to those 2 drivers. For example it is known to break with */
-        /* the PG driver due to the way it manages transactions... */
-        if (poDS && !(EQUAL(poDriver->GetDescription(), "FileGDB") ||
-                      EQUAL(poDriver->GetDescription(), "SQLite") ||
-                      EQUAL(poDriver->GetDescription(), "GPKG")))
-        {
-            poDS = (GDALDataset*) GDALOpenEx( pszDataSource,
-                            GDAL_OF_VECTOR, NULL, papszOpenOptions, NULL );
-        }
-        else
-            bCloseODS = FALSE;
-        if (poDS)
-        {
-            if (bOverwrite || bAppend)
-            {
-                /* Various tests to avoid overwriting the source layer(s) */
-                /* or to avoid appending a layer to itself */
-                int bError = FALSE;
-                if (pszNewLayerName == NULL)
-                    bError = TRUE;
-                else if (CSLCount(papszLayers) == 1)
-                    bError = strcmp(pszNewLayerName, papszLayers[0]) == 0;
-                else if (pszSQLStatement == NULL)
-                    bError = TRUE;
-                if (bError)
-                {
-                    fprintf( stderr,
-                             "ERROR: -nln name must be specified combined with "
-                             "a single source layer name,\nor a -sql statement, and "
-                             "name must be different from an existing layer.\n");
-                    exit(1);
-                }
-            }
-        }
-    }
-    else
-        poDS = (GDALDataset*) GDALOpenEx( pszDataSource,
-                            GDAL_OF_VECTOR, NULL, papszOpenOptions, NULL );
-
-/* -------------------------------------------------------------------- */
-/*      Report failure                                                  */
-/* -------------------------------------------------------------------- */
-    if( poDS == NULL )
-    {
-        OGRSFDriverRegistrar    *poR = OGRSFDriverRegistrar::GetRegistrar();
-        
-        fprintf( stderr, "FAILURE:\n"
-                "Unable to open datasource `%s' with the following drivers.\n",
-                pszDataSource );
-
-        for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
-        {
-            fprintf( stderr, "  -> %s\n", poR->GetDriver(iDriver)->GetDescription() );
-        }
-
-        exit( 1 );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Try opening the output datasource as an existing, writable      */
-/* -------------------------------------------------------------------- */
-
-    if( bUpdate && poODS == NULL )
-    {
-        poODS = (GDALDataset*) GDALOpenEx( pszDestDataSource,
-                GDAL_OF_UPDATE | GDAL_OF_VECTOR, NULL, papszDestOpenOptions, NULL );
-        if( poODS != NULL )
-            poDriver = poODS->GetDriver();
-
-        if( poODS == NULL )
-        {
-            if (bOverwrite || bAppend)
-            {
-                poODS = (GDALDataset*) GDALOpenEx( pszDestDataSource,
-                            GDAL_OF_VECTOR, NULL, papszDestOpenOptions, NULL );
-                if (poODS == NULL)
-                {
-                    /* ok the datasource doesn't exist at all */
-                    bUpdate = FALSE;
-                }
-                else
-                {
-                    if( poODS != NULL )
-                        poDriver = poODS->GetDriver();
-                    GDALClose( (GDALDatasetH) poODS );
-                    poODS = NULL;
-                }
-            }
-
-            if (bUpdate)
-            {
-                fprintf( stderr, "FAILURE:\n"
-                        "Unable to open existing output datasource `%s'.\n",
-                        pszDestDataSource );
-                exit( 1 );
-            }
-        }
-        else if( CSLCount(papszDSCO) > 0 )
-        {
-            fprintf( stderr, "WARNING: Datasource creation options ignored since an existing datasource\n"
-                    "         being updated.\n" );
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Find the output driver.                                         */
-/* -------------------------------------------------------------------- */
-    if( !bUpdate )
-    {
-        if (!bQuiet && !bFormatExplicitlySet)
-            CheckDestDataSourceNameConsistency(pszDestDataSource, pszFormat);
-
-        OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
-        int                  iDriver;
-
-        poDriver = poR->GetDriverByName(pszFormat);
-        if( poDriver == NULL )
-        {
-            fprintf( stderr, "Unable to find driver `%s'.\n", pszFormat );
-            fprintf( stderr,  "The following drivers are available:\n" );
-        
-            for( iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
-            {
-                fprintf( stderr,  "  -> `%s'\n", poR->GetDriver(iDriver)->GetDescription() );
-            }
-            exit( 1 );
-        }
-
-        if( !CSLTestBoolean( CSLFetchNameValueDef(poDriver->GetMetadata(), GDAL_DCAP_CREATE, "FALSE") ) )
-        {
-            fprintf( stderr,  "%s driver does not support data source creation.\n",
-                    pszFormat );
-            exit( 1 );
-        }
-        
-        if( papszDestOpenOptions != NULL )
-        {
-            fprintf(stderr, "-doo ignored when creating the output datasource.\n");
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Special case to improve user experience when translating        */
-/*      a datasource with multiple layers into a shapefile. If the      */
-/*      user gives a target datasource with .shp and it does not exist, */
-/*      the shapefile driver will try to create a file, but this is not */
-/*      appropriate because here we have several layers, so create      */
-/*      a directory instead.                                            */
-/* -------------------------------------------------------------------- */
-        VSIStatBufL  sStat;
-        if (EQUAL(poDriver->GetDescription(), "ESRI Shapefile") &&
-            pszSQLStatement == NULL &&
-            (CSLCount(papszLayers) > 1 ||
-             (CSLCount(papszLayers) == 0 && poDS->GetLayerCount() > 1)) &&
-            pszNewLayerName == NULL &&
-            EQUAL(CPLGetExtension(pszDestDataSource), "SHP") &&
-            VSIStatL(pszDestDataSource, &sStat) != 0)
-        {
-            if (VSIMkdir(pszDestDataSource, 0755) != 0)
-            {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                      "Failed to create directory %s\n"
-                      "for shapefile datastore.\n",
-                      pszDestDataSource );
-                exit(1);
-            }
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Create the output data source.                                  */
-/* -------------------------------------------------------------------- */
-        poODS = poDriver->Create( pszDestDataSource, 0, 0, 0, GDT_Unknown, papszDSCO );
-        if( poODS == NULL )
-        {
-            fprintf( stderr,  "%s driver failed to create %s\n", 
-                    pszFormat, pszDestDataSource );
-            exit( 1 );
-        }
-        
-        if( bCopyMD )
-        {
-            char** papszDomains = poDS->GetMetadataDomainList();
-            for(char** papszIter = papszDomains; papszIter && *papszIter; ++papszIter )
-            {
-                char** papszMD = poDS->GetMetadata(*papszIter);
-                if( papszMD )
-                    poODS->SetMetadata(papszMD, *papszIter);
-            }
-            CSLDestroy(papszDomains);
-        }
-        for(char** papszIter = papszMetadataOptions; papszIter && *papszIter; ++papszIter )
-        {
-            char    *pszKey = NULL;
-            const char *pszValue;
-            pszValue = CPLParseNameValue( *papszIter, &pszKey );
-            if( pszKey )
-            {
-                poODS->SetMetadataItem(pszKey,pszValue);
-                CPLFree( pszKey );
-            }
-        }
-    }
-
-    if( bLayerTransaction < 0 )
-        bLayerTransaction = !poODS->TestCapability(ODsCTransactions);
-
-/* -------------------------------------------------------------------- */
-/*      Parse the output SRS definition if possible.                    */
-/* -------------------------------------------------------------------- */
-    if( pszOutputSRSDef != NULL )
-    {
-        poOutputSRS = (OGRSpatialReference*)OSRNewSpatialReference(NULL);
-        if( poOutputSRS->SetFromUserInput( pszOutputSRSDef ) != OGRERR_NONE )
-        {
-            fprintf( stderr,  "Failed to process SRS definition: %s\n", 
-                    pszOutputSRSDef );
-            exit( 1 );
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Parse the source SRS definition if possible.                    */
-/* -------------------------------------------------------------------- */
-    if( pszSourceSRSDef != NULL )
-    {
-        poSourceSRS = (OGRSpatialReference*)OSRNewSpatialReference(NULL);
-        if( poSourceSRS->SetFromUserInput( pszSourceSRSDef ) != OGRERR_NONE )
-        {
-            fprintf( stderr,  "Failed to process SRS definition: %s\n", 
-                    pszSourceSRSDef );
-            exit( 1 );
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Parse spatial filter SRS if needed.                             */
-/* -------------------------------------------------------------------- */
-    if( poSpatialFilter != NULL && osSpatSRSDef.size() )
-    {
-        if( pszSQLStatement )
-        {
-            fprintf(stderr, "-spat_srs not compatible with -sql.\n");
-            exit(1);
-        }
-        OGREnvelope sEnvelope;
-        poSpatialFilter->getEnvelope(&sEnvelope);
-        poSpatSRS = new OGRSpatialReference();
-        if( poSpatSRS->SetFromUserInput( osSpatSRSDef ) != OGRERR_NONE )
-        {
-            fprintf( stderr,  "Failed to process SRS definition: %s\n", 
-                    osSpatSRSDef.c_str() );
-            exit( 1 );
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Create a transformation object from the source to               */
-/*      destination coordinate system.                                  */
-/* -------------------------------------------------------------------- */
-    GCPCoordTransformation *poGCPCoordTrans = NULL;
-    if( nGCPCount > 0 )
-    {
-        poGCPCoordTrans = new GCPCoordTransformation( nGCPCount, pasGCPs, 
-                                                      nTransformOrder, 
-                                                      poSourceSRS ? poSourceSRS : poOutputSRS );
-        if( !(poGCPCoordTrans->IsValid()) )
-        {
-            delete poGCPCoordTrans;
-            poGCPCoordTrans = NULL;
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      For OSM file.                                                   */
-/* -------------------------------------------------------------------- */
-    int         bSrcIsOSM = (strcmp(poDS->GetDriverName(), "OSM") == 0);
-    vsi_l_offset nSrcFileSize = 0;
-    if( bSrcIsOSM && strcmp(poDS->GetDescription(), "/vsistdin/") != 0)
-    {
-        VSIStatBufL sStat;
-        if( VSIStatL(poDS->GetDescription(), &sStat) == 0 )
-            nSrcFileSize = sStat.st_size;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Create layer setup and transformer objects.                     */
-/* -------------------------------------------------------------------- */
-    SetupTargetLayer oSetup;
-    oSetup.poDstDS = poODS;
-    oSetup.papszLCO = papszLCO;
-    oSetup.poOutputSRSIn = poOutputSRS;
-    oSetup.bNullifyOutputSRS = bNullifyOutputSRS;
-    oSetup.papszSelFields = papszSelFields;
-    oSetup.bAppend = bAppend;
-    oSetup.bAddMissingFields = bAddMissingFields;
-    oSetup.eGTypeIn = eGType;
-    oSetup.sGeomConversion = sGeomConversion;
-    oSetup.nCoordDim = nCoordDim;
-    oSetup.bOverwrite = bOverwrite;
-    oSetup.papszFieldTypesToString = papszFieldTypesToString;
-    oSetup.papszMapFieldType = papszMapFieldType;
-    oSetup.bUnsetFieldWidth = bUnsetFieldWidth;
-    oSetup.bExplodeCollections = bExplodeCollections;
-    oSetup.pszZField = pszZField;
-    oSetup.papszFieldMap = papszFieldMap;
-    oSetup.pszWHERE = pszWHERE;
-    oSetup.bExactFieldNameMatch = bExactFieldNameMatch;
-    oSetup.bQuiet = bQuiet;
-    oSetup.bForceNullable = bForceNullable;
-    oSetup.bUnsetDefault = bUnsetDefault;
-    oSetup.bUnsetFid = bUnsetFid;
-    oSetup.bPreserveFID = bPreserveFID;
-    oSetup.bCopyMD = bCopyMD;
-
-    LayerTranslator oTranslator;
-    oTranslator.poSrcDS = poDS;
-    oTranslator.poODS = poODS;
-    oTranslator.bTransform = bTransform;
-    oTranslator.bWrapDateline = bWrapDateline;
-    oTranslator.pszDateLineOffset = pszDateLineOffset;
-    oTranslator.poOutputSRSIn = poOutputSRS;
-    oTranslator.bNullifyOutputSRS = bNullifyOutputSRS;
-    oTranslator.poUserSourceSRS = poSourceSRS;
-    oTranslator.poGCPCoordTrans = poGCPCoordTrans;
-    oTranslator.eGTypeIn = eGType;
-    oTranslator.sGeomConversion = sGeomConversion;
-    oTranslator.nCoordDim = nCoordDim;
-    oTranslator.eGeomOp = eGeomOp;
-    oTranslator.dfGeomOpParam = dfGeomOpParam;
-    oTranslator.poClipSrc = poClipSrc;
-    oTranslator.poClipDst = poClipDst;
-    oTranslator.bExplodeCollectionsIn = bExplodeCollections;
-    oTranslator.nSrcFileSize = nSrcFileSize;
-
-    if( nGroupTransactions )
-    {
-        if( !bLayerTransaction )
-            poODS->StartTransaction(bForceTransaction);
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Special case for -sql clause.  No source layers required.       */
-/* -------------------------------------------------------------------- */
-    if( pszSQLStatement != NULL )
-    {
-        OGRLayer *poResultSet;
-
-        /* Special case: if output=input, then we must likely destroy the */
-        /* old table before to avoid transaction issues. */
-        if( poDS == poODS && pszNewLayerName != NULL && bOverwrite )
-            GetLayerAndOverwriteIfNecessary(poODS, pszNewLayerName, bOverwrite, NULL);
-
-        if( pszWHERE != NULL )
-            fprintf( stderr,  "-where clause ignored in combination with -sql.\n" );
-        if( CSLCount(papszLayers) > 0 )
-            fprintf( stderr,  "layer names ignored in combination with -sql.\n" );
-        
-        poResultSet = poDS->ExecuteSQL( pszSQLStatement,
-                                        (pszGeomField == NULL) ? poSpatialFilter : NULL, 
-                                        pszDialect );
-
-        if( poResultSet != NULL )
-        {
-            if( poSpatialFilter != NULL && pszGeomField != NULL )
-            {
-                int iGeomField = poResultSet->GetLayerDefn()->GetGeomFieldIndex(pszGeomField);
-                if( iGeomField >= 0 )
-                    poResultSet->SetSpatialFilter( iGeomField, poSpatialFilter );
-                else
-                    printf("WARNING: Cannot find geometry field %s.\n",
-                           pszGeomField);
-            }
-
-            GIntBig nCountLayerFeatures = 0;
-            if (bDisplayProgress)
-            {
-                if (bSrcIsOSM)
-                {
-                    pfnProgress = GDALTermProgress;
-                }
-                else if (!poResultSet->TestCapability(OLCFastFeatureCount))
-                {
-                    fprintf( stderr, "Progress turned off as fast feature count is not available.\n");
-                    bDisplayProgress = FALSE;
-                }
-                else
-                {
-                    nCountLayerFeatures = poResultSet->GetFeatureCount();
-                    pfnProgress = GDALTermProgress;
-                }
-            }
-
-            OGRLayer* poPassedLayer = poResultSet;
-            if (bSplitListFields)
-            {
-                poPassedLayer = new OGRSplitListFieldLayer(poPassedLayer, nMaxSplitListSubFields);
-                int nRet = ((OGRSplitListFieldLayer*)poPassedLayer)->BuildLayerDefn(NULL, NULL);
-                if (!nRet)
-                {
-                    delete poPassedLayer;
-                    poPassedLayer = poResultSet;
-                }
-            }
-
-/* -------------------------------------------------------------------- */
-/*      Special case to improve user experience when translating into   */
-/*      single file shapefile and source has only one layer, and that   */
-/*      the layer name isn't specified                                  */
-/* -------------------------------------------------------------------- */
-            VSIStatBufL  sStat;
-            if (EQUAL(poDriver->GetDescription(), "ESRI Shapefile") &&
-                pszNewLayerName == NULL &&
-                VSIStatL(pszDestDataSource, &sStat) == 0 && VSI_ISREG(sStat.st_mode))
-            {
-                pszNewLayerName = CPLStrdup(CPLGetBasename(pszDestDataSource));
-            }
-
-            TargetLayerInfo* psInfo = oSetup.Setup(poPassedLayer,
-                                                   pszNewLayerName);
-
-            poPassedLayer->ResetReading();
-
-            if( psInfo == NULL ||
-                !oTranslator.Translate( psInfo,
-                                        nCountLayerFeatures, NULL,
-                                        pfnProgress, pProgressArg ))
-            {
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                          "Terminating translation prematurely after failed\n"
-                          "translation from sql statement." );
-
-                nRetCode = 1;
-            }
-
-            FreeTargetLayerInfo(psInfo);
-
-            if (poPassedLayer != poResultSet)
-                delete poPassedLayer;
-
-            poDS->ReleaseResultSet( poResultSet );
-        }
-        else
-        {
-            if( CPLGetLastErrorNo() != 0 )
-                nRetCode = 1;
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Special case for layer interleaving mode.                       */
-/* -------------------------------------------------------------------- */
-    else if( bSrcIsOSM &&
-                CSLTestBoolean(CPLGetConfigOption("OGR_INTERLEAVED_READING", "YES")) )
-    {
-        CPLSetConfigOption("OGR_INTERLEAVED_READING", "YES");
-
-        if (bSplitListFields)
-        {
-            fprintf( stderr, "FAILURE: -splitlistfields not supported in this mode\n" );
-            exit( 1 );
-        }
-
-        int nSrcLayerCount = poDS->GetLayerCount();
-        AssociatedLayers* pasAssocLayers =
-            (AssociatedLayers* ) CPLCalloc(nSrcLayerCount, sizeof(AssociatedLayers));
-
-/* -------------------------------------------------------------------- */
-/*      Special case to improve user experience when translating into   */
-/*      single file shapefile and source has only one layer, and that   */
-/*      the layer name isn't specified                                  */
-/* -------------------------------------------------------------------- */
-        VSIStatBufL  sStat;
-        if (EQUAL(poDriver->GetDescription(), "ESRI Shapefile") &&
-            (CSLCount(papszLayers) == 1 || nSrcLayerCount == 1) && pszNewLayerName == NULL &&
-            VSIStatL(pszDestDataSource, &sStat) == 0 && VSI_ISREG(sStat.st_mode))
-        {
-            pszNewLayerName = CPLStrdup(CPLGetBasename(pszDestDataSource));
-        }
-
-        if ( bDisplayProgress && bSrcIsOSM )
-            pfnProgress = GDALTermProgress;
-
-/* -------------------------------------------------------------------- */
-/*      If no target layer specified, use all source layers.            */
-/* -------------------------------------------------------------------- */
-        int iLayer;
-        if ( CSLCount(papszLayers) == 0)
-        {
-            papszLayers = (char**) CPLCalloc(sizeof(char*), nSrcLayerCount + 1);
-            for( iLayer = 0; iLayer < nSrcLayerCount; iLayer++ )
-            {
-                OGRLayer        *poLayer = poDS->GetLayer(iLayer);
-
-                if( poLayer == NULL )
-                {
-                    fprintf( stderr, "FAILURE: Couldn't fetch advertised layer %d!\n",
-                            iLayer );
-                    exit( 1 );
-                }
-
-                papszLayers[iLayer] = CPLStrdup(poLayer->GetName());
-            }
-        }
-        else
-        {
-            if ( bSrcIsOSM )
-            {
-                CPLString osInterestLayers = "SET interest_layers =";
-                for( iLayer = 0; papszLayers[iLayer] != NULL; iLayer++ )
-                {
-                    if( iLayer != 0 ) osInterestLayers += ",";
-                    osInterestLayers += papszLayers[iLayer];
-                }
-
-                poDS->ExecuteSQL(osInterestLayers.c_str(), NULL, NULL);
-            }
-        }
-
-/* -------------------------------------------------------------------- */
-/*      First pass to set filters and create target layers.             */
-/* -------------------------------------------------------------------- */
-        for( iLayer = 0; iLayer < nSrcLayerCount; iLayer++ )
-        {
-            OGRLayer        *poLayer = poDS->GetLayer(iLayer);
-            if( poLayer == NULL )
-            {
-                fprintf( stderr, "FAILURE: Couldn't fetch advertised layer %d!\n",
-                        iLayer );
-                exit( 1 );
-            }
-
-            pasAssocLayers[iLayer].poSrcLayer = poLayer;
-
-            if( CSLFindString(papszLayers, poLayer->GetName()) >= 0 )
-            {
-                if( pszWHERE != NULL )
-                {
-                    if( poLayer->SetAttributeFilter( pszWHERE ) != OGRERR_NONE )
-                    {
-                        fprintf( stderr, "FAILURE: SetAttributeFilter(%s) on layer '%s' failed.\n",
-                                 pszWHERE, poLayer->GetName() );
-                        if (!bSkipFailures)
-                            exit( 1 );
-                    }
-                }
-
-                ApplySpatialFilter(poLayer, poSpatialFilter, poSpatSRS, pszGeomField, poSourceSRS );
-
-                TargetLayerInfo* psInfo = oSetup.Setup(poLayer,
-                                                       pszNewLayerName);
-
-                if( psInfo == NULL && !bSkipFailures )
-                    exit(1);
-
-                pasAssocLayers[iLayer].psInfo = psInfo;
-            }
-            else
-            {
-                pasAssocLayers[iLayer].psInfo = NULL;
-            }
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Second pass to process features in a interleaved layer mode.    */
-/* -------------------------------------------------------------------- */
-        int bHasLayersNonEmpty;
-        do
-        {
-            bHasLayersNonEmpty = FALSE;
-
-            for( iLayer = 0; iLayer < nSrcLayerCount;  iLayer++ )
-            {
-                OGRLayer        *poLayer = pasAssocLayers[iLayer].poSrcLayer;
-                TargetLayerInfo *psInfo = pasAssocLayers[iLayer].psInfo;
-                GIntBig nReadFeatureCount = 0;
-
-                if( psInfo )
-                {
-                    if( !oTranslator.Translate( psInfo,
-                                                0, &nReadFeatureCount,
-                                                pfnProgress, pProgressArg )
-                        && !bSkipFailures )
-                    {
-                        CPLError( CE_Failure, CPLE_AppDefined,
-                                "Terminating translation prematurely after failed\n"
-                                "translation of layer %s (use -skipfailures to skip errors)\n",
-                                poLayer->GetName() );
-
-                        nRetCode = 1;
-                        break;
-                    }
-                }
-                else
-                {
-                    /* No matching target layer : just consumes the features */
-
-                    OGRFeature* poFeature;
-                    while( (poFeature = poLayer->GetNextFeature()) != NULL )
-                    {
-                        nReadFeatureCount ++;
-                        OGRFeature::DestroyFeature(poFeature);
-                    }
-                }
-
-                if( nReadFeatureCount != 0 )
-                    bHasLayersNonEmpty = TRUE;
-            }
-        }
-        while( bHasLayersNonEmpty );
-
-        if (pfnProgress)
-        {
-            pfnProgress(1.0, "", pProgressArg);
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Cleanup.                                                        */
-/* -------------------------------------------------------------------- */
-        for( iLayer = 0; iLayer < nSrcLayerCount;  iLayer++ )
-        {
-            if( pasAssocLayers[iLayer].psInfo )
-                FreeTargetLayerInfo(pasAssocLayers[iLayer].psInfo);
-        }
-        CPLFree(pasAssocLayers);
-    }
-
-    else
-    {
-        int nLayerCount = 0;
-        OGRLayer** papoLayers = NULL;
-
-/* -------------------------------------------------------------------- */
-/*      Process each data source layer.                                 */
-/* -------------------------------------------------------------------- */
-        if ( CSLCount(papszLayers) == 0)
-        {
-            nLayerCount = poDS->GetLayerCount();
-            papoLayers = (OGRLayer**)CPLMalloc(sizeof(OGRLayer*) * nLayerCount);
-
-            for( int iLayer = 0; 
-                 iLayer < nLayerCount; 
-                 iLayer++ )
-            {
-                OGRLayer        *poLayer = poDS->GetLayer(iLayer);
-
-                if( poLayer == NULL )
-                {
-                    fprintf( stderr, "FAILURE: Couldn't fetch advertised layer %d!\n",
-                            iLayer );
-                    exit( 1 );
-                }
-
-                papoLayers[iLayer] = poLayer;
-            }
-        }
-/* -------------------------------------------------------------------- */
-/*      Process specified data source layers.                           */
-/* -------------------------------------------------------------------- */
-        else
-        {
-            nLayerCount = CSLCount(papszLayers);
-            papoLayers = (OGRLayer**)CPLMalloc(sizeof(OGRLayer*) * nLayerCount);
-
-            for( int iLayer = 0; 
-                papszLayers[iLayer] != NULL; 
-                iLayer++ )
-            {
-                OGRLayer        *poLayer = poDS->GetLayerByName(papszLayers[iLayer]);
-
-                if( poLayer == NULL )
-                {
-                    fprintf( stderr, "FAILURE: Couldn't fetch requested layer '%s'!\n",
-                             papszLayers[iLayer] );
-                    if (!bSkipFailures)
-                        exit( 1 );
-                }
-
-                papoLayers[iLayer] = poLayer;
-            }
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Special case to improve user experience when translating into   */
-/*      single file shapefile and source has only one layer, and that   */
-/*      the layer name isn't specified                                  */
-/* -------------------------------------------------------------------- */
-        VSIStatBufL  sStat;
-        if (EQUAL(poDriver->GetDescription(), "ESRI Shapefile") &&
-            nLayerCount == 1 && pszNewLayerName == NULL &&
-            VSIStatL(pszDestDataSource, &sStat) == 0 && VSI_ISREG(sStat.st_mode))
-        {
-            pszNewLayerName = CPLStrdup(CPLGetBasename(pszDestDataSource));
-        }
-
-        GIntBig* panLayerCountFeatures = (GIntBig*) CPLCalloc(sizeof(GIntBig), nLayerCount);
-        GIntBig nCountLayersFeatures = 0;
-        GIntBig nAccCountFeatures = 0;
-        int iLayer;
-
-        /* First pass to apply filters and count all features if necessary */
-        for( iLayer = 0; 
-            iLayer < nLayerCount; 
-            iLayer++ )
-        {
-            OGRLayer        *poLayer = papoLayers[iLayer];
-            if (poLayer == NULL)
-                continue;
-
-            if( pszWHERE != NULL )
-            {
-                if( poLayer->SetAttributeFilter( pszWHERE ) != OGRERR_NONE )
-                {
-                    fprintf( stderr, "FAILURE: SetAttributeFilter(%s) on layer '%s' failed.\n",
-                             pszWHERE, poLayer->GetName() );
-                    if (!bSkipFailures)
-                        exit( 1 );
-                }
-            }
-
-            ApplySpatialFilter(poLayer, poSpatialFilter, poSpatSRS, pszGeomField, poSourceSRS);
-
-            if (bDisplayProgress && !bSrcIsOSM)
-            {
-                if (!poLayer->TestCapability(OLCFastFeatureCount))
-                {
-                    fprintf( stderr, "Progress turned off as fast feature count is not available.\n");
-                    bDisplayProgress = FALSE;
-                }
-                else
-                {
-                    panLayerCountFeatures[iLayer] = poLayer->GetFeatureCount();
-                    nCountLayersFeatures += panLayerCountFeatures[iLayer];
-                }
-            }
-        }
-
-        /* Second pass to do the real job */
-        for( iLayer = 0; 
-            iLayer < nLayerCount && nRetCode == 0; 
-            iLayer++ )
-        {
-            OGRLayer        *poLayer = papoLayers[iLayer];
-            if (poLayer == NULL)
-                continue;
-
-
-            OGRLayer* poPassedLayer = poLayer;
-            if (bSplitListFields)
-            {
-                poPassedLayer = new OGRSplitListFieldLayer(poPassedLayer, nMaxSplitListSubFields);
-
-                if (bDisplayProgress && nMaxSplitListSubFields != 1)
-                {
-                    pfnProgress = GDALScaledProgress;
-                    pProgressArg = 
-                        GDALCreateScaledProgress(nAccCountFeatures * 1.0 / nCountLayersFeatures,
-                                                (nAccCountFeatures + panLayerCountFeatures[iLayer] / 2) * 1.0 / nCountLayersFeatures,
-                                                GDALTermProgress,
-                                                NULL);
-                }
-                else
-                {
-                    pfnProgress = NULL;
-                    pProgressArg = NULL;
-                }
-
-                int nRet = ((OGRSplitListFieldLayer*)poPassedLayer)->BuildLayerDefn(pfnProgress, pProgressArg);
-                if (!nRet)
-                {
-                    delete poPassedLayer;
-                    poPassedLayer = poLayer;
-                }
-
-                if (bDisplayProgress)
-                    GDALDestroyScaledProgress(pProgressArg);
-            }
-
-
-            if (bDisplayProgress)
-            {
-                if ( bSrcIsOSM )
-                    pfnProgress = GDALTermProgress;
-                else
-                {
-                    pfnProgress = GDALScaledProgress;
-                    GIntBig nStart = 0;
-                    if (poPassedLayer != poLayer && nMaxSplitListSubFields != 1)
-                        nStart = panLayerCountFeatures[iLayer] / 2;
-                    pProgressArg =
-                        GDALCreateScaledProgress((nAccCountFeatures + nStart) * 1.0 / nCountLayersFeatures,
-                                                (nAccCountFeatures + panLayerCountFeatures[iLayer]) * 1.0 / nCountLayersFeatures,
-                                                GDALTermProgress,
-                                                NULL);
-                }
-            }
-
-            nAccCountFeatures += panLayerCountFeatures[iLayer];
-
-            TargetLayerInfo* psInfo = oSetup.Setup(poPassedLayer,
-                                                   pszNewLayerName);
-
-            poPassedLayer->ResetReading();
-
-            if( (psInfo == NULL ||
-                !oTranslator.Translate( psInfo,
-                                        panLayerCountFeatures[iLayer], NULL,
-                                        pfnProgress, pProgressArg ))
-                && !bSkipFailures )
-            {
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                        "Terminating translation prematurely after failed\n"
-                        "translation of layer %s (use -skipfailures to skip errors)\n", 
-                        poLayer->GetName() );
-
-                nRetCode = 1;
-            }
-
-            FreeTargetLayerInfo(psInfo);
-
-            if (poPassedLayer != poLayer)
-                delete poPassedLayer;
-
-            if (bDisplayProgress && !bSrcIsOSM)
-                GDALDestroyScaledProgress(pProgressArg);
-        }
-
-        CPLFree(panLayerCountFeatures);
-        CPLFree(papoLayers);
-    }
-/* -------------------------------------------------------------------- */
-/*      Process DS style table                                          */
-/* -------------------------------------------------------------------- */
-
-    poODS->SetStyleTable( poDS->GetStyleTable () );
-
-    if( nGroupTransactions )
-    {
-        if( !bLayerTransaction )
-        {
-            if( nRetCode != 0 && !bSkipFailures )
-                poODS->RollbackTransaction();
-            else
-                poODS->CommitTransaction();
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Close down.                                                     */
-/* -------------------------------------------------------------------- */
-    if (bCloseODS)
-        GDALClose( (GDALDatasetH)poODS );
-    GDALClose( (GDALDatasetH)poDS );
-    OGRGeometryFactory::destroyGeometry(poSpatialFilter);
-    OGRGeometryFactory::destroyGeometry(poClipSrc);
-    OGRGeometryFactory::destroyGeometry(poClipDst);
-
-    delete poGCPCoordTrans;
-    if( pasGCPs != NULL )
-    {
-        GDALDeinitGCPs( nGCPCount, pasGCPs );
-        CPLFree( pasGCPs );
-    }
-
-    /* Destroy them after the last potential user */
-    OGRSpatialReference::DestroySpatialReference(poOutputSRS);
-    OGRSpatialReference::DestroySpatialReference(poSourceSRS);
-    OGRSpatialReference::DestroySpatialReference(poSpatSRS);
-
-    CSLDestroy(papszSelFields);
-    CSLDestroy( papszFieldMap );
-    CSLDestroy( papszMapFieldType );
-    CSLDestroy( papszArgv );
-    CSLDestroy( papszLayers );
-    CSLDestroy( papszDSCO );
-    CSLDestroy( papszLCO );
-    CSLDestroy( papszOpenOptions );
-    CSLDestroy( papszDestOpenOptions );
-    CSLDestroy( papszFieldTypesToString );
-    CSLDestroy( papszMetadataOptions );
-    CPLFree( pszNewLayerName );
-
-    OGRCleanupAll();
-
-#ifdef DBMALLOC
-    malloc_dump(1);
-#endif
-    
-    return nRetCode;
-}
-
-/************************************************************************/
-/*                               Usage()                                */
-/************************************************************************/
-
-static void Usage(int bShort)
-{
-    Usage(NULL, bShort);
-}
-
-static void Usage(const char* pszAdditionalMsg, int bShort)
-
-{
-    OGRSFDriverRegistrar        *poR = OGRSFDriverRegistrar::GetRegistrar();
-
-
-    printf( "Usage: ogr2ogr [--help-general] [-skipfailures] [-append] [-update]\n"
-            "               [-select field_list] [-where restricted_where]\n"
-            "               [-progress] [-sql <sql statement>] [-dialect dialect]\n"
-            "               [-preserve_fid] [-fid FID]\n"
-            "               [-spat xmin ymin xmax ymax] [-spat_srs srs_def] [-geomfield field]\n"
-            "               [-a_srs srs_def] [-t_srs srs_def] [-s_srs srs_def]\n"
-            "               [-f format_name] [-overwrite] [[-dsco NAME=VALUE] ...]\n"
-            "               dst_datasource_name src_datasource_name\n"
-            "               [-lco NAME=VALUE] [-nln name] \n"
-            "               [-nlt type|PROMOTE_TO_MULTI|CONVERT_TO_LINEAR]\n"
-            "               [-dim 2|3|layer_dim] [layer [layer ...]]\n"
-            "\n"
-            "Advanced options :\n"
-            "               [-gt n] [-ds_transaction]\n"
-            "               [[-oo NAME=VALUE] ...] [[-doo NAME=VALUE] ...]\n"
-            "               [-clipsrc [xmin ymin xmax ymax]|WKT|datasource|spat_extent]\n"
-            "               [-clipsrcsql sql_statement] [-clipsrclayer layer]\n"
-            "               [-clipsrcwhere expression]\n"
-            "               [-clipdst [xmin ymin xmax ymax]|WKT|datasource]\n"
-            "               [-clipdstsql sql_statement] [-clipdstlayer layer]\n"
-            "               [-clipdstwhere expression]\n"
-            "               [-wrapdateline][-datelineoffset val]\n"
-            "               [[-simplify tolerance] | [-segmentize max_dist]]\n"
-            "               [-addfields] [-unsetFid]\n"
-            "               [-relaxedFieldNameMatch] [-forceNullable] [-unsetDefault]\n"
-            "               [-fieldTypeToString All|(type1[,type2]*)] [-unsetFieldWidth]\n"
-            "               [-mapFieldType srctype|All=dsttype[,srctype2=dsttype2]*]\n"
-            "               [-fieldmap identity | index1[,index2]*]\n"
-            "               [-splitlistfields] [-maxsubfields val]\n"
-            "               [-explodecollections] [-zfield field_name]\n"
-            "               [-gcp pixel line easting northing [elevation]]* [-order n | -tps]\n"
-            "               [-nomd] [-mo \"META-TAG=VALUE\"]*\n");
-
-    if (bShort)
-    {
-        printf( "\nNote: ogr2ogr --long-usage for full help.\n");
-        if( pszAdditionalMsg )
-            fprintf(stderr, "\nFAILURE: %s\n", pszAdditionalMsg);
-        exit( 1 );
-    }
-
-    printf("\n -f format_name: output file format name, possible values are:\n");
-
-    for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
-    {
-        GDALDriver *poDriver = poR->GetDriver(iDriver);
-
-        if( CSLTestBoolean( CSLFetchNameValueDef(poDriver->GetMetadata(), GDAL_DCAP_CREATE, "FALSE") ) )
-            printf( "     -f \"%s\"\n", poDriver->GetDescription() );
-    }
-
-    printf( " -append: Append to existing layer instead of creating new if it exists\n"
-            " -overwrite: delete the output layer and recreate it empty\n"
-            " -update: Open existing output datasource in update mode\n"
-            " -progress: Display progress on terminal. Only works if input layers have the \n"
-            "                                          \"fast feature count\" capability\n"
-            " -select field_list: Comma-delimited list of fields from input layer to\n"
-            "                     copy to the new layer (defaults to all)\n" 
-            " -where restricted_where: Attribute query (like SQL WHERE)\n" 
-            " -wrapdateline: split geometries crossing the dateline meridian\n"
-            "                (long. = +/- 180deg)\n" 
-            " -datelineoffset: offset from dateline in degrees\n"
-            "                (default long. = +/- 10deg,\n"
-            "                geometries within 170deg to -170deg will be splited)\n" 
-            " -sql statement: Execute given SQL statement and save result.\n"
-            " -dialect value: select a dialect, usually OGRSQL to avoid native sql.\n"
-            " -skipfailures: skip features or layers that fail to convert\n"
-            " -gt n: group n features per transaction (default 20000). n can be set to unlimited\n"
-            " -spat xmin ymin xmax ymax: spatial query extents\n"
-            " -simplify tolerance: distance tolerance for simplification.\n"
-            " -segmentize max_dist: maximum distance between 2 nodes.\n"
-            "                       Used to create intermediate points\n"
-            " -dsco NAME=VALUE: Dataset creation option (format specific)\n"
-            " -lco  NAME=VALUE: Layer creation option (format specific)\n"
-            " -oo   NAME=VALUE: Input dataset open option (format specific)\n"
-            " -doo  NAME=VALUE: Destination dataset open option (format specific)\n"
-            " -nln name: Assign an alternate name to the new layer\n"
-            " -nlt type: Force a geometry type for new layer.  One of NONE, GEOMETRY,\n"
-            "      POINT, LINESTRING, POLYGON, GEOMETRYCOLLECTION, MULTIPOINT,\n"
-            "      MULTIPOLYGON, or MULTILINESTRING, or PROMOTE_TO_MULTI.  Add \"25D\" for 3D layers.\n"
-            "      Default is type of source layer.\n"
-            " -dim dimension: Force the coordinate dimension to the specified value.\n"
-            " -fieldTypeToString type1,...: Converts fields of specified types to\n"
-            "      fields of type string in the new layer. Valid types are : Integer,\n"
-            "      Integer64, Real, String, Date, Time, DateTime, Binary, IntegerList, Integer64List, RealList,\n"
-            "      StringList. Special value All will convert all fields to strings.\n"
-            " -fieldmap index1,index2,...: Specifies the list of field indexes to be\n"
-            "      copied from the source to the destination. The (n)th value specified\n"
-            "      in the list is the index of the field in the target layer definition\n"
-            "      in which the n(th) field of the source layer must be copied. Index count\n"
-            "      starts at zero. There must be exactly as many values in the list as\n"
-            "      the count of the fields in the source layer. We can use the 'identity'\n"
-            "      setting to specify that the fields should be transferred by using the\n"
-            "      same order. This setting should be used along with the append setting.");
-
-    printf(" -a_srs srs_def: Assign an output SRS\n"
-           " -t_srs srs_def: Reproject/transform to this SRS on output\n"
-           " -s_srs srs_def: Override source SRS\n"
-           "\n" 
-           " Srs_def can be a full WKT definition (hard to escape properly),\n"
-           " or a well known definition (ie. EPSG:4326) or a file with a WKT\n"
-           " definition.\n" );
-
-    if( pszAdditionalMsg )
-        fprintf(stderr, "\nFAILURE: %s\n", pszAdditionalMsg);
-
-    exit( 1 );
-}
-
-/************************************************************************/
-/*                               SetZ()                                 */
-/************************************************************************/
-static void SetZ (OGRGeometry* poGeom, double dfZ )
-{
-    if (poGeom == NULL)
-        return;
-    switch (wkbFlatten(poGeom->getGeometryType()))
-    {
-        case wkbPoint:
-            ((OGRPoint*)poGeom)->setZ(dfZ);
-            break;
-
-        case wkbLineString:
-        case wkbLinearRing:
-        {
-            int i;
-            OGRLineString* poLS = (OGRLineString*) poGeom;
-            for(i=0;i<poLS->getNumPoints();i++)
-                poLS->setPoint(i, poLS->getX(i), poLS->getY(i), dfZ);
-            break;
-        }
-
-        case wkbPolygon:
-        {
-            int i;
-            OGRPolygon* poPoly = (OGRPolygon*) poGeom;
-            SetZ(poPoly->getExteriorRing(), dfZ);
-            for(i=0;i<poPoly->getNumInteriorRings();i++)
-                SetZ(poPoly->getInteriorRing(i), dfZ);
-            break;
-        }
-
-        case wkbMultiPoint:
-        case wkbMultiLineString:
-        case wkbMultiPolygon:
-        case wkbGeometryCollection:
-        {
-            int i;
-            OGRGeometryCollection* poGeomColl = (OGRGeometryCollection*) poGeom;
-            for(i=0;i<poGeomColl->getNumGeometries();i++)
-                SetZ(poGeomColl->getGeometryRef(i), dfZ);
-            break;
-        }
-
-        default:
-            break;
-    }
-}
-
-/************************************************************************/
-/*                       ForceCoordDimension()                          */
-/************************************************************************/
-
-static int ForceCoordDimension(int eGType, int nCoordDim)
-{
-    if( nCoordDim == 2 && eGType != wkbNone )
-        return wkbFlatten(eGType);
-    else if( nCoordDim == 3 && eGType != wkbNone )
-        return wkbSetZ((OGRwkbGeometryType)eGType);
-    else
-        return eGType;
-}
-
-/************************************************************************/
-/*                   GetLayerAndOverwriteIfNecessary()                  */
-/************************************************************************/
-
-static OGRLayer* GetLayerAndOverwriteIfNecessary(GDALDataset *poDstDS,
-                                                 const char* pszNewLayerName,
-                                                 int bOverwrite,
-                                                 int* pbErrorOccured)
-{
-    if( pbErrorOccured )
-        *pbErrorOccured = FALSE;
-
-    /* GetLayerByName() can instanciate layers that would have been */
-    /* 'hidden' otherwise, for example, non-spatial tables in a */
-    /* Postgis-enabled database, so this apparently useless command is */
-    /* not useless... (#4012) */
-    CPLPushErrorHandler(CPLQuietErrorHandler);
-    OGRLayer* poDstLayer = poDstDS->GetLayerByName(pszNewLayerName);
-    CPLPopErrorHandler();
-    CPLErrorReset();
-
-    int iLayer = -1;
-    if (poDstLayer != NULL)
-    {
-        int nLayerCount = poDstDS->GetLayerCount();
-        for( iLayer = 0; iLayer < nLayerCount; iLayer++ )
-        {
-            OGRLayer        *poLayer = poDstDS->GetLayer(iLayer);
-            if (poLayer == poDstLayer)
-                break;
-        }
-
-        if (iLayer == nLayerCount)
-            /* shouldn't happen with an ideal driver */
-            poDstLayer = NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      If the user requested overwrite, and we have the layer in       */
-/*      question we need to delete it now so it will get recreated      */
-/*      (overwritten).                                                  */
-/* -------------------------------------------------------------------- */
-    if( poDstLayer != NULL && bOverwrite )
-    {
-        if( poDstDS->DeleteLayer( iLayer ) != OGRERR_NONE )
-        {
-            fprintf( stderr,
-                     "DeleteLayer() failed when overwrite requested.\n" );
-            if( pbErrorOccured )
-                *pbErrorOccured = TRUE;
-        }
-        poDstLayer = NULL;
-    }
-
-    return poDstLayer;
-}
-
-/************************************************************************/
-/*                          ConvertType()                               */
-/************************************************************************/
-
-static OGRwkbGeometryType ConvertType(GeometryConversion sGeomConversion,
-                                      OGRwkbGeometryType eGType)
-{
-    OGRwkbGeometryType eRetType = eGType;
-    if ( sGeomConversion.bPromoteToMulti )
-    {
-        if( !OGR_GT_IsSubClassOf(eGType, wkbGeometryCollection) )
-            eRetType = OGR_GT_GetCollection(eGType);
-    }
-    else if ( sGeomConversion.bConvertToLinear )
-        eRetType = OGR_GT_GetLinear(eGType);
-    if ( sGeomConversion.bConvertToCurve )
-        eRetType = OGR_GT_GetCurve(eGType);
-    return eRetType;
-}
-
-/************************************************************************/
-/*                        DoFieldTypeConversion()                       */
-/************************************************************************/
-
-void DoFieldTypeConversion(GDALDataset* poDstDS, OGRFieldDefn& oFieldDefn,
-                           char** papszFieldTypesToString,
-                           char** papszMapFieldType,
-                           int bUnsetFieldWidth,
-                           int bQuiet,
-                           int bForceNullable,
-                           int bUnsetDefault)
-{
-    if (papszFieldTypesToString != NULL )
-    {
-        CPLString osLookupString;
-        osLookupString.Printf("%s(%s)",
-                        OGRFieldDefn::GetFieldTypeName(oFieldDefn.GetType()),
-                        OGRFieldDefn::GetFieldSubTypeName(oFieldDefn.GetSubType()));
-                                  
-        int iIdx = CSLFindString(papszFieldTypesToString, osLookupString);
-        if( iIdx < 0 )
-            iIdx = CSLFindString(papszFieldTypesToString,
-                                        OGRFieldDefn::GetFieldTypeName(oFieldDefn.GetType()));
-        if( iIdx < 0 )
-            iIdx = CSLFindString(papszFieldTypesToString, "All");
-        if( iIdx >= 0 )
-        {
-            oFieldDefn.SetSubType(OFSTNone);
-            oFieldDefn.SetType(OFTString);
-        }
-    }
-    else if (papszMapFieldType != NULL)
-    {
-        CPLString osLookupString;
-        osLookupString.Printf("%s(%s)",
-                        OGRFieldDefn::GetFieldTypeName(oFieldDefn.GetType()),
-                        OGRFieldDefn::GetFieldSubTypeName(oFieldDefn.GetSubType()));
-                                  
-        const char* pszType = CSLFetchNameValue(papszMapFieldType, osLookupString);
-        if( pszType == NULL )
-            pszType = CSLFetchNameValue(papszMapFieldType,
-                                        OGRFieldDefn::GetFieldTypeName(oFieldDefn.GetType()));
-        if( pszType == NULL )
-            pszType = CSLFetchNameValue(papszMapFieldType, "All");
-        if( pszType != NULL )
-        {
-            int iSubType;
-            int iType = GetFieldType(pszType, &iSubType);
-            if( iType >= 0 && iSubType >= 0 )
-            {
-                oFieldDefn.SetSubType(OFSTNone);
-                oFieldDefn.SetType((OGRFieldType)iType);
-                oFieldDefn.SetSubType((OGRFieldSubType)iSubType);
-                if( iType == OFTInteger )
-                    oFieldDefn.SetWidth(0);
-            }
-        }
-    }
-    if( bUnsetFieldWidth )
-    {
-        oFieldDefn.SetWidth(0);
-        oFieldDefn.SetPrecision(0);
-    }
-    if( bForceNullable )
-        oFieldDefn.SetNullable(TRUE);
-    if( bUnsetDefault )
-        oFieldDefn.SetDefault(NULL);
-
-    if( poDstDS->GetDriver() != NULL &&
-        poDstDS->GetDriver()->GetMetadataItem(GDAL_DMD_CREATIONFIELDDATATYPES) != NULL &&
-        strstr(poDstDS->GetDriver()->GetMetadataItem(GDAL_DMD_CREATIONFIELDDATATYPES),
-                OGRFieldDefn::GetFieldTypeName(oFieldDefn.GetType())) == NULL )
-    {
-        if( oFieldDefn.GetType() == OFTInteger64 )
-        {
-            if( !bQuiet )
-            {
-                CPLError(CE_Warning, CPLE_AppDefined,
-                        "The output driver does not seem to natively support %s "
-                        "type for field %s. Converting it to Real instead. "
-                        "-mapFieldType can be used to control field type conversion.",
-                        OGRFieldDefn::GetFieldTypeName(oFieldDefn.GetType()),
-                        oFieldDefn.GetNameRef());
-            }
-            oFieldDefn.SetType(OFTReal);
-        }
-        else if( !bQuiet )
-        {
-            CPLError(CE_Warning, CPLE_AppDefined,
-                        "The output driver does not natively support %s type for "
-                        "field %s. Misconversion can happen. "
-                        "-mapFieldType can be used to control field type conversion.",
-                        OGRFieldDefn::GetFieldTypeName(oFieldDefn.GetType()),
-                        oFieldDefn.GetNameRef());
-        }
-    }
-    else if( poDstDS->GetDriver() != NULL &&
-             poDstDS->GetDriver()->GetMetadataItem(GDAL_DMD_CREATIONFIELDDATATYPES) == NULL )
-    {
-        // All drivers supporting OFTInteger64 should advertize it theoretically
-        if( oFieldDefn.GetType() == OFTInteger64 )
-        {
-            if( !bQuiet )
-            {
-                CPLError(CE_Warning, CPLE_AppDefined,
-                        "The output driver does not seem to natively support %s type "
-                        "for field %s. Converting it to Real instead. "
-                        "-mapFieldType can be used to control field type conversion.",
-                        OGRFieldDefn::GetFieldTypeName(oFieldDefn.GetType()),
-                        oFieldDefn.GetNameRef());
-            }
-            oFieldDefn.SetType(OFTReal);
-        }
-    }
-}
-
-/************************************************************************/
-/*                   SetupTargetLayer::Setup()                          */
-/************************************************************************/
-
-TargetLayerInfo* SetupTargetLayer::Setup(OGRLayer* poSrcLayer,
-                                         const char* pszNewLayerName)
-{
-    OGRLayer    *poDstLayer;
-    OGRFeatureDefn *poSrcFDefn;
-    OGRFeatureDefn *poDstFDefn = NULL;
-    int eGType = eGTypeIn;
-    int bPreserveFID = this->bPreserveFID;
-
-    if( pszNewLayerName == NULL )
-        pszNewLayerName = poSrcLayer->GetName();
-
-/* -------------------------------------------------------------------- */
-/*      Get other info.                                                 */
-/* -------------------------------------------------------------------- */
-    poSrcFDefn = poSrcLayer->GetLayerDefn();
-
-/* -------------------------------------------------------------------- */
-/*      Find requested geometry fields.                                 */
-/* -------------------------------------------------------------------- */
-    std::vector<int> anRequestedGeomFields;
-    int nSrcGeomFieldCount = poSrcFDefn->GetGeomFieldCount();
-    if (papszSelFields && !bAppend )
-    {
-        for( int iField=0; papszSelFields[iField] != NULL; iField++)
-        {
-            int iSrcField = poSrcFDefn->GetFieldIndex(papszSelFields[iField]);
-            if (iSrcField >= 0)
-            {
-                /* do nothing */
-            }
-            else
-            {
-                iSrcField = poSrcFDefn->GetGeomFieldIndex(papszSelFields[iField]);
-                if( iSrcField >= 0)
-                {
-                    anRequestedGeomFields.push_back(iSrcField);
-                }
-                else
-                {
-                    fprintf( stderr, "Field '%s' not found in source layer.\n",
-                            papszSelFields[iField] );
-                    if( !bSkipFailures )
-                        return NULL;
-                }
-            }
-        }
-
-        if( anRequestedGeomFields.size() > 1 &&
-            !poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer) )
-        {
-            fprintf( stderr, "Several geometry fields requested, but output "
-                                "datasource does not support multiple geometry "
-                                "fields.\n" );
-            if( !bSkipFailures )
-                return NULL;
-            else
-                anRequestedGeomFields.resize(0);
-        }
-    }
-
-    OGRSpatialReference* poOutputSRS = poOutputSRSIn;
-    if( poOutputSRS == NULL && !bNullifyOutputSRS )
-    {
-        if( nSrcGeomFieldCount == 1 || anRequestedGeomFields.size() == 0 )
-            poOutputSRS = poSrcLayer->GetSpatialRef();
-        else if( anRequestedGeomFields.size() == 1 )
-        {
-            int iSrcGeomField = anRequestedGeomFields[0];
-            poOutputSRS = poSrcFDefn->GetGeomFieldDefn(iSrcGeomField)->
-                GetSpatialRef();
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Find the layer.                                                 */
-/* -------------------------------------------------------------------- */
-
-    int bErrorOccured;
-    poDstLayer = GetLayerAndOverwriteIfNecessary(poDstDS,
-                                                 pszNewLayerName,
-                                                 bOverwrite,
-                                                 &bErrorOccured);
-    if( bErrorOccured )
-        return NULL;
-
-/* -------------------------------------------------------------------- */
-/*      If the layer does not exist, then create it.                    */
-/* -------------------------------------------------------------------- */
-    if( poDstLayer == NULL )
-    {
-        if( !poDstDS->TestCapability( ODsCCreateLayer ) )
-        {
-            fprintf( stderr,
-              "Layer %s not found, and CreateLayer not supported by driver.\n",
-                     pszNewLayerName );
-            return NULL;
-        }
-
-        int bForceGType = ( eGType != -2 );
-        if( !bForceGType )
-        {
-            if( anRequestedGeomFields.size() == 0 )
-            {
-                eGType = poSrcFDefn->GetGeomType();
-            }
-            else if( anRequestedGeomFields.size() == 1  )
-            {
-                int iSrcGeomField = anRequestedGeomFields[0];
-                eGType = poSrcFDefn->GetGeomFieldDefn(iSrcGeomField)->GetType();
-            }
-            else
-                eGType = wkbNone;
-
-            int bHasZ = wkbHasZ((OGRwkbGeometryType)eGType);
-            eGType = ConvertType(sGeomConversion, (OGRwkbGeometryType)eGType);
-
-            if ( bExplodeCollections )
-            {
-                OGRwkbGeometryType eFGType = wkbFlatten(eGType);
-                if (eFGType == wkbMultiPoint)
-                {
-                    eGType = wkbPoint;
-                }
-                else if (eFGType == wkbMultiLineString)
-                {
-                    eGType = wkbLineString;
-                }
-                else if (eFGType == wkbMultiPolygon)
-                {
-                    eGType = wkbPolygon;
-                }
-                else if (eFGType == wkbGeometryCollection ||
-                         eFGType == wkbMultiCurve ||
-                         eFGType == wkbMultiSurface)
-                {
-                    eGType = wkbUnknown;
-                }
-            }
-
-            if ( bHasZ || (pszZField && eGType != wkbNone) )
-                eGType = wkbSetZ((OGRwkbGeometryType)eGType);
-        }
-
-        eGType = ForceCoordDimension(eGType, nCoordDim);
-
-        CPLErrorReset();
-
-        char** papszLCOTemp = CSLDuplicate(papszLCO);
-
-        int eGCreateLayerType = eGType;
-        if( anRequestedGeomFields.size() == 0 &&
-            nSrcGeomFieldCount > 1 &&
-            poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer) )
-        {
-            eGCreateLayerType = wkbNone;
-        }
-        else if( anRequestedGeomFields.size() == 1 &&
-                 poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer) )
-        {
-            eGCreateLayerType = wkbNone;
-        }
-        // If the source feature has a single geometry column that is not nullable
-        // and that ODsCCreateGeomFieldAfterCreateLayer is available, use it
-        // so as to be able to set the not null constraint (if the driver supports it)
-        else if( anRequestedGeomFields.size() == 0 &&
-                 nSrcGeomFieldCount == 1 &&
-                 poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer) &&
-                 !poSrcFDefn->GetGeomFieldDefn(0)->IsNullable() &&
-                 !bForceNullable)
-        {
-            anRequestedGeomFields.push_back(0);
-            eGCreateLayerType = wkbNone;
-        }
-        // If the source feature first geometry column is not nullable
-        // and that GEOMETRY_NULLABLE creation option is available, use it
-        // so as to be able to set the not null constraint (if the driver supports it)
-        else if( anRequestedGeomFields.size() == 0 &&
-                 nSrcGeomFieldCount >= 1 &&
-                 !poSrcFDefn->GetGeomFieldDefn(0)->IsNullable() &&
-                 poDstDS->GetDriver()->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST) != NULL &&
-                 strstr(poDstDS->GetDriver()->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST), "GEOMETRY_NULLABLE") != NULL &&
-                 CSLFetchNameValue(papszLCO, "GEOMETRY_NULLABLE") == NULL&&
-                 !bForceNullable )
-        {
-            papszLCOTemp = CSLSetNameValue(papszLCOTemp, "GEOMETRY_NULLABLE", "NO");
-            CPLDebug("OGR2OGR", "Using GEOMETRY_NULLABLE=NO");
-        }
-
-        // Force FID column as 64 bit if the source feature has a 64 bit FID,
-        // the target driver supports 64 bit FID and the user didn't set it
-        // manually.
-        if( poSrcLayer->GetMetadataItem(OLMD_FID64) != NULL &&
-            EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES") &&
-            poDstDS->GetDriver()->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST) != NULL &&
-            strstr(poDstDS->GetDriver()->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST), "FID64") != NULL &&
-            CSLFetchNameValue(papszLCO, "FID64") == NULL )
-        {
-            papszLCOTemp = CSLSetNameValue(papszLCOTemp, "FID64", "YES");
-            CPLDebug("OGR2OGR", "Using FID64=YES");
-        }
-
-        // If output driver supports FID layer creation option, set it with
-        // the FID column name of the source layer
-        if( !bUnsetFid && !bAppend &&
-            poSrcLayer->GetFIDColumn() != NULL &&
-            !EQUAL(poSrcLayer->GetFIDColumn(), "") &&
-            poDstDS->GetDriver()->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST) != NULL &&
-            strstr(poDstDS->GetDriver()->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST), "='FID'") != NULL &&
-            CSLFetchNameValue(papszLCO, "FID") == NULL )
-        {
-            papszLCOTemp = CSLSetNameValue(papszLCOTemp, "FID", poSrcLayer->GetFIDColumn());
-            CPLDebug("OGR2OGR", "Using FID=%s and -preserve_fid", poSrcLayer->GetFIDColumn());
-            bPreserveFID = TRUE;
-        }
-
-        poDstLayer = poDstDS->CreateLayer( pszNewLayerName, poOutputSRS,
-                                           (OGRwkbGeometryType) eGCreateLayerType,
-                                           papszLCOTemp );
-        CSLDestroy(papszLCOTemp);
-
-        if( poDstLayer == NULL )
-            return NULL;
-        
-        if( bCopyMD )
-        {
-            char** papszDomains = poSrcLayer->GetMetadataDomainList();
-            for(char** papszIter = papszDomains; papszIter && *papszIter; ++papszIter )
-            {
-                if( !EQUAL(*papszIter, "IMAGE_STRUCTURE") &&
-                    !EQUAL(*papszIter, "SUBDATASETS") )
-                {
-                    char** papszMD = poSrcLayer->GetMetadata(*papszIter);
-                    if( papszMD )
-                        poDstLayer->SetMetadata(papszMD, *papszIter);
-                }
-            }
-            CSLDestroy(papszDomains);
-        }
-
-        if( anRequestedGeomFields.size() == 0 &&
-            nSrcGeomFieldCount > 1 &&
-            poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer) )
-        {
-            for(int i = 0; i < nSrcGeomFieldCount; i ++)
-            {
-                anRequestedGeomFields.push_back(i);
-            }
-        }
-
-        if( anRequestedGeomFields.size() > 1 ||
-            (anRequestedGeomFields.size() == 1 &&
-                 poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer)) )
-        {
-            for(int i = 0; i < (int)anRequestedGeomFields.size(); i ++)
-            {
-                int iSrcGeomField = anRequestedGeomFields[i];
-                OGRGeomFieldDefn oGFldDefn
-                    (poSrcFDefn->GetGeomFieldDefn(iSrcGeomField));
-                if( poOutputSRSIn != NULL )
-                    oGFldDefn.SetSpatialRef(poOutputSRSIn);
-                if( bForceGType )
-                    oGFldDefn.SetType((OGRwkbGeometryType) eGType);
-                else
-                {
-                    eGType = oGFldDefn.GetType();
-                    eGType = ConvertType(sGeomConversion, (OGRwkbGeometryType)eGType);
-                    eGType = ForceCoordDimension(eGType, nCoordDim);
-                    oGFldDefn.SetType((OGRwkbGeometryType) eGType);
-                }
-                if( bForceNullable )
-                    oGFldDefn.SetNullable(TRUE);
-                poDstLayer->CreateGeomField(&oGFldDefn);
-            }
-        }
-
-        bAppend = FALSE;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Otherwise we will append to it, if append was requested.        */
-/* -------------------------------------------------------------------- */
-    else if( !bAppend )
-    {
-        fprintf( stderr, "FAILED: Layer %s already exists, and -append not specified.\n"
-                         "        Consider using -append, or -overwrite.\n",
-                pszNewLayerName );
-        return NULL;
-    }
-    else
-    {
-        if( CSLCount(papszLCO) > 0 )
-        {
-            fprintf( stderr, "WARNING: Layer creation options ignored since an existing layer is\n"
-                             "         being appended to.\n" );
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Process Layer style table                                       */
-/* -------------------------------------------------------------------- */
-
-    poDstLayer->SetStyleTable( poSrcLayer->GetStyleTable () );
-/* -------------------------------------------------------------------- */
-/*      Add fields.  Default to copy all field.                         */
-/*      If only a subset of all fields requested, then output only      */
-/*      the selected fields, and in the order that they were            */
-/*      selected.                                                       */
-/* -------------------------------------------------------------------- */
-    int         nSrcFieldCount = poSrcFDefn->GetFieldCount();
-    int         iField, *panMap;
-    int         iSrcFIDField = -1;
-
-    // Initialize the index-to-index map to -1's
-    panMap = (int *) VSIMalloc( sizeof(int) * nSrcFieldCount );
-    for( iField=0; iField < nSrcFieldCount; iField++)
-        panMap[iField] = -1;
-
-    /* Caution : at the time of writing, the MapInfo driver */
-    /* returns NULL until a field has been added */
-    poDstFDefn = poDstLayer->GetLayerDefn();
-
-    if (papszFieldMap && bAppend)
-    {
-        int bIdentity = FALSE;
-
-        if (EQUAL(papszFieldMap[0], "identity"))
-            bIdentity = TRUE;
-        else if (CSLCount(papszFieldMap) != nSrcFieldCount)
-        {
-            fprintf( stderr, "Field map should contain the value 'identity' or "
-                    "the same number of integer values as the source field count.\n");
-            VSIFree(panMap);
-            return NULL;
-        }
-
-        for( iField=0; iField < nSrcFieldCount; iField++)
-        {
-            panMap[iField] = bIdentity? iField : atoi(papszFieldMap[iField]);
-            if (panMap[iField] >= poDstFDefn->GetFieldCount())
-            {
-                fprintf( stderr, "Invalid destination field index %d.\n", panMap[iField]);
-                VSIFree(panMap);
-                return NULL;
-            }
-        }
-    }
-    else if (papszSelFields && !bAppend )
-    {
-        int  nDstFieldCount = 0;
-        if (poDstFDefn)
-            nDstFieldCount = poDstFDefn->GetFieldCount();
-        for( iField=0; papszSelFields[iField] != NULL; iField++)
-        {
-            int iSrcField = poSrcFDefn->GetFieldIndex(papszSelFields[iField]);
-            if (iSrcField >= 0)
-            {
-                OGRFieldDefn* poSrcFieldDefn = poSrcFDefn->GetFieldDefn(iSrcField);
-                OGRFieldDefn oFieldDefn( poSrcFieldDefn );
-
-                DoFieldTypeConversion(poDstDS, oFieldDefn,
-                                      papszFieldTypesToString,
-                                      papszMapFieldType,
-                                      bUnsetFieldWidth,
-                                      bQuiet,
-                                      bForceNullable,
-                                      bUnsetDefault);
-
-                /* The field may have been already created at layer creation */
-                int iDstField = -1;
-                if (poDstFDefn)
-                    iDstField = poDstFDefn->GetFieldIndex(oFieldDefn.GetNameRef());
-                if (iDstField >= 0)
-                {
-                    panMap[iSrcField] = iDstField;
-                }
-                else if (poDstLayer->CreateField( &oFieldDefn ) == OGRERR_NONE)
-                {
-                    /* now that we've created a field, GetLayerDefn() won't return NULL */
-                    if (poDstFDefn == NULL)
-                        poDstFDefn = poDstLayer->GetLayerDefn();
-
-                    /* Sanity check : if it fails, the driver is buggy */
-                    if (poDstFDefn != NULL &&
-                        poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
-                    {
-                        CPLError(CE_Warning, CPLE_AppDefined,
-                                 "The output driver has claimed to have added the %s field, but it did not!",
-                                 oFieldDefn.GetNameRef() );
-                    }
-                    else
-                    {
-                        panMap[iSrcField] = nDstFieldCount;
-                        nDstFieldCount ++;
-                    }
-                }
-            }
-        }
-
-        /* -------------------------------------------------------------------- */
-        /* Use SetIgnoredFields() on source layer if available                  */
-        /* -------------------------------------------------------------------- */
-        if (poSrcLayer->TestCapability(OLCIgnoreFields))
-        {
-            int iSrcField;
-            char** papszIgnoredFields = NULL;
-            int bUseIgnoredFields = TRUE;
-            char** papszWHEREUsedFields = NULL;
-
-            if (pszWHERE)
-            {
-                /* We must not ignore fields used in the -where expression (#4015) */
-                OGRFeatureQuery oFeatureQuery;
-                if ( oFeatureQuery.Compile( poSrcLayer->GetLayerDefn(), pszWHERE, FALSE, NULL ) == OGRERR_NONE )
-                {
-                    papszWHEREUsedFields = oFeatureQuery.GetUsedFields();
-                }
-                else
-                {
-                    bUseIgnoredFields = FALSE;
-                }
-            }
-
-            for(iSrcField=0;bUseIgnoredFields && iSrcField<poSrcFDefn->GetFieldCount();iSrcField++)
-            {
-                const char* pszFieldName =
-                    poSrcFDefn->GetFieldDefn(iSrcField)->GetNameRef();
-                int bFieldRequested = FALSE;
-                for( iField=0; papszSelFields[iField] != NULL; iField++)
-                {
-                    if (EQUAL(pszFieldName, papszSelFields[iField]))
-                    {
-                        bFieldRequested = TRUE;
-                        break;
-                    }
-                }
-                bFieldRequested |= CSLFindString(papszWHEREUsedFields, pszFieldName) >= 0;
-                bFieldRequested |= (pszZField != NULL && EQUAL(pszFieldName, pszZField));
-
-                /* If source field not requested, add it to ignored files list */
-                if (!bFieldRequested)
-                    papszIgnoredFields = CSLAddString(papszIgnoredFields, pszFieldName);
-            }
-            if (bUseIgnoredFields)
-                poSrcLayer->SetIgnoredFields((const char**)papszIgnoredFields);
-            CSLDestroy(papszIgnoredFields);
-            CSLDestroy(papszWHEREUsedFields);
-        }
-    }
-    else if( !bAppend || bAddMissingFields )
-    {
-        int nDstFieldCount = 0;
-        if (poDstFDefn)
-            nDstFieldCount = poDstFDefn->GetFieldCount();
-
-        /* Save the map of existing fields, before creating new ones */
-        /* This helps when converting a source layer that has duplicated field names */
-        /* which is a bad idea */
-        std::map<CPLString, int> oMapExistingFields;
-        for( iField = 0; iField < nDstFieldCount; iField++ )
-        {
-            const char* pszFieldName = poDstFDefn->GetFieldDefn(iField)->GetNameRef();
-            CPLString osUpperFieldName(CPLString(pszFieldName).toupper());
-            if( oMapExistingFields.find(osUpperFieldName) == oMapExistingFields.end() )
-                oMapExistingFields[osUpperFieldName] = iField;
-            /*else
-                CPLError(CE_Warning, CPLE_AppDefined,
-                         "The target layer has already a duplicated field name '%s' before "
-                         "adding the fields of the source layer", pszFieldName); */
-        }
-
-        const char* pszFIDColumn = poDstLayer->GetFIDColumn();
-
-        for( iField = 0; iField < nSrcFieldCount; iField++ )
-        {
-            OGRFieldDefn* poSrcFieldDefn = poSrcFDefn->GetFieldDefn(iField);
-            OGRFieldDefn oFieldDefn( poSrcFieldDefn );
-
-            // Avoid creating a field with the same name as the FID column
-            if( pszFIDColumn != NULL && EQUAL(pszFIDColumn, oFieldDefn.GetNameRef()) &&
-                (oFieldDefn.GetType() == OFTInteger || oFieldDefn.GetType() == OFTInteger64) )
-            {
-                iSrcFIDField = iField;
-                continue;
-            }
-
-            DoFieldTypeConversion(poDstDS, oFieldDefn,
-                                  papszFieldTypesToString,
-                                  papszMapFieldType,
-                                  bUnsetFieldWidth,
-                                  bQuiet,
-                                  bForceNullable,
-                                  bUnsetDefault);
-
-            /* The field may have been already created at layer creation */
-            std::map<CPLString, int>::iterator oIter =
-                oMapExistingFields.find(CPLString(oFieldDefn.GetNameRef()).toupper());
-            if( oIter != oMapExistingFields.end() )
-            {
-                panMap[iField] = oIter->second;
-                continue;
-            }
-
-            int bHasRenamed = FALSE;
-            /* In case the field name already exists in the target layer, */
-            /* build a unique field name */
-            if( poDstFDefn != NULL &&
-                poDstFDefn->GetFieldIndex(oFieldDefn.GetNameRef()) >= 0 )
-            {
-                int nTry = 1;
-                while(TRUE)
-                {
-                    ++nTry;
-                    CPLString osTmpName;
-                    osTmpName.Printf("%s%d", oFieldDefn.GetNameRef(), nTry);
-                    /* Check that the proposed name doesn't exist either in the already */
-                    /* created fields or in the source fields */
-                    if( poDstFDefn->GetFieldIndex(osTmpName) < 0 &&
-                        poSrcFDefn->GetFieldIndex(osTmpName) < 0 )
-                    {
-                        bHasRenamed = TRUE;
-                        oFieldDefn.SetName(osTmpName);
-                        break;
-                    }
-                }
-            }
-
-            if (poDstLayer->CreateField( &oFieldDefn ) == OGRERR_NONE)
-            {
-                /* now that we've created a field, GetLayerDefn() won't return NULL */
-                if (poDstFDefn == NULL)
-                    poDstFDefn = poDstLayer->GetLayerDefn();
-
-                /* Sanity check : if it fails, the driver is buggy */
-                if (poDstFDefn != NULL &&
-                    poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
-                {
-                    CPLError(CE_Warning, CPLE_AppDefined,
-                             "The output driver has claimed to have added the %s field, but it did not!",
-                             oFieldDefn.GetNameRef() );
-                }
-                else
-                {
-                    if( bHasRenamed )
-                    {
-                        const char* pszNewFieldName =
-                            poDstFDefn->GetFieldDefn(nDstFieldCount)->GetNameRef();
-                        CPLError(CE_Warning, CPLE_AppDefined,
-                                 "Field '%s' already exists. Renaming it as '%s'",
-                                 poSrcFieldDefn->GetNameRef(), pszNewFieldName);
-                    }
-
-                    panMap[iField] = nDstFieldCount;
-                    nDstFieldCount ++;
-                }
-            }
-        }
-    }
-    else
-    {
-        /* For an existing layer, build the map by fetching the index in the destination */
-        /* layer for each source field */
-        if (poDstFDefn == NULL)
-        {
-            fprintf( stderr, "poDstFDefn == NULL.\n" );
-            VSIFree(panMap);
-            return NULL;
-        }
-
-        for( iField = 0; iField < nSrcFieldCount; iField++ )
-        {
-            OGRFieldDefn* poSrcFieldDefn = poSrcFDefn->GetFieldDefn(iField);
-            int iDstField = poDstLayer->FindFieldIndex(poSrcFieldDefn->GetNameRef(), bExactFieldNameMatch);
-            if (iDstField >= 0)
-                panMap[iField] = iDstField;
-            else
-                CPLDebug("OGR2OGR", "Skipping field '%s' not found in destination layer '%s'.",
-                         poSrcFieldDefn->GetNameRef(), poDstLayer->GetName() );
-        }
-    }
-
-    int iSrcZField = -1;
-    if (pszZField != NULL)
-    {
-        iSrcZField = poSrcFDefn->GetFieldIndex(pszZField);
-    }
-
-    TargetLayerInfo* psInfo = (TargetLayerInfo*)
-                                            CPLMalloc(sizeof(TargetLayerInfo));
-    psInfo->nFeaturesRead = 0;
-    psInfo->bPerFeatureCT = FALSE;
-    psInfo->poSrcLayer = poSrcLayer;
-    psInfo->poDstLayer = poDstLayer;
-    psInfo->papoCT = (OGRCoordinateTransformation**)
-        CPLCalloc(poDstLayer->GetLayerDefn()->GetGeomFieldCount(),
-                  sizeof(OGRCoordinateTransformation*));
-    psInfo->papapszTransformOptions = (char***)
-        CPLCalloc(poDstLayer->GetLayerDefn()->GetGeomFieldCount(),
-                  sizeof(char**));
-    psInfo->panMap = panMap;
-    psInfo->iSrcZField = iSrcZField;
-    psInfo->iSrcFIDField = iSrcFIDField;
-    if( anRequestedGeomFields.size() == 1 )
-        psInfo->iRequestedSrcGeomField = anRequestedGeomFields[0];
-    else
-        psInfo->iRequestedSrcGeomField = -1;
-    psInfo->bPreserveFID = bPreserveFID;
-
-    return psInfo;
-}
-
-/************************************************************************/
-/*                         FreeTargetLayerInfo()                        */
-/************************************************************************/
-
-static void FreeTargetLayerInfo(TargetLayerInfo* psInfo)
-{
-    if( psInfo == NULL )
-        return;
-    for(int i=0;i<psInfo->poDstLayer->GetLayerDefn()->GetGeomFieldCount();i++)
-    {
-        delete psInfo->papoCT[i];
-        CSLDestroy(psInfo->papapszTransformOptions[i]);
-    }
-    CPLFree(psInfo->papoCT);
-    CPLFree(psInfo->papapszTransformOptions);
-    CPLFree(psInfo->panMap);
-    CPLFree(psInfo);
-}
-
-/************************************************************************/
-/*                               SetupCT()                              */
-/************************************************************************/
-
-static int SetupCT( TargetLayerInfo* psInfo,
-                    OGRLayer* poSrcLayer,
-                    int bTransform,
-                    int bWrapDateline,
-                    const char* pszDateLineOffset,
-                    OGRSpatialReference* poUserSourceSRS,
-                    OGRFeature* poFeature,
-                    OGRSpatialReference* poOutputSRS,
-                    OGRCoordinateTransformation* poGCPCoordTrans)
-{
-    OGRLayer    *poDstLayer = psInfo->poDstLayer;
-    int nDstGeomFieldCount = poDstLayer->GetLayerDefn()->GetGeomFieldCount();
-    for( int iGeom = 0; iGeom < nDstGeomFieldCount; iGeom ++ )
-    {
-/* -------------------------------------------------------------------- */
-/*      Setup coordinate transformation if we need it.                  */
-/* -------------------------------------------------------------------- */
-        OGRSpatialReference* poSourceSRS = NULL;
-        OGRCoordinateTransformation* poCT = NULL;
-        char** papszTransformOptions = NULL;
-        
-        int iSrcGeomField;
-        if( psInfo->iRequestedSrcGeomField >= 0 )
-            iSrcGeomField = psInfo->iRequestedSrcGeomField;
-        else
-        {
-            iSrcGeomField = poSrcLayer->GetLayerDefn()->GetGeomFieldIndex(
-                poDstLayer->GetLayerDefn()->GetGeomFieldDefn(iGeom)->GetNameRef());
-            if( iSrcGeomField < 0 )
-            {
-                if( nDstGeomFieldCount == 1 && 
-                    poSrcLayer->GetLayerDefn()->GetGeomFieldCount() > 0 )
-                {
-                    iSrcGeomField = 0;
-                }
-                else
-                    continue;
-            }
-        }
-        
-        if( bTransform || bWrapDateline )
-        {
-            if( psInfo->nFeaturesRead == 0 )
-            {
-                poSourceSRS = poUserSourceSRS;
-                if( poSourceSRS == NULL )
-                {
-                    if( iSrcGeomField > 0 )
-                        poSourceSRS = poSrcLayer->GetLayerDefn()->
-                            GetGeomFieldDefn(iSrcGeomField)->GetSpatialRef();
-                    else
-                        poSourceSRS = poSrcLayer->GetSpatialRef();
-                }
-            }
-            if( poSourceSRS == NULL )
-            {
-                OGRGeometry* poSrcGeometry =
-                    poFeature->GetGeomFieldRef(iSrcGeomField);
-                if( poSrcGeometry )
-                    poSourceSRS = poSrcGeometry->getSpatialReference();
-                psInfo->bPerFeatureCT = TRUE;
-            }
-        }
-
-        if( bTransform )
-        {
-            if( poSourceSRS == NULL )
-            {
-                fprintf( stderr, "Can't transform coordinates, source layer has no\n"
-                        "coordinate system.  Use -s_srs to set one.\n" );
-
-                return FALSE;
-            }
-
-            CPLAssert( NULL != poSourceSRS );
-            CPLAssert( NULL != poOutputSRS );
-
-            if( psInfo->papoCT[iGeom] != NULL &&
-                psInfo->papoCT[iGeom]->GetSourceCS() == poSourceSRS )
-            {
-                poCT = psInfo->papoCT[iGeom];
-            }
-            else
-            {
-                poCT = OGRCreateCoordinateTransformation( poSourceSRS, poOutputSRS );
-                if( poCT == NULL )
-                {
-                    char        *pszWKT = NULL;
-
-                    fprintf( stderr, "Failed to create coordinate transformation between the\n"
-                        "following coordinate systems.  This may be because they\n"
-                        "are not transformable, or because projection services\n"
-                        "(PROJ.4 DLL/.so) could not be loaded.\n" );
-
-                    poSourceSRS->exportToPrettyWkt( &pszWKT, FALSE );
-                    fprintf( stderr,  "Source:\n%s\n", pszWKT );
-                    CPLFree(pszWKT);
-
-                    poOutputSRS->exportToPrettyWkt( &pszWKT, FALSE );
-                    fprintf( stderr,  "Target:\n%s\n", pszWKT );
-                    CPLFree(pszWKT);
-
-                    return FALSE;
-                }
-                if( poGCPCoordTrans != NULL )
-                    poCT = new CompositeCT( poGCPCoordTrans, poCT );
-            }
-
-            if( poCT != psInfo->papoCT[iGeom] )
-            {
-                delete psInfo->papoCT[iGeom];
-                psInfo->papoCT[iGeom] = poCT;
-            }
-        }
-        else
-        {
-            poCT = poGCPCoordTrans;
-        }
-
-        if (bWrapDateline)
-        {
-            if (bTransform && poCT != NULL && poOutputSRS != NULL && poOutputSRS->IsGeographic())
-            {
-                papszTransformOptions =
-                    CSLAddString(papszTransformOptions, "WRAPDATELINE=YES");
-                CPLString soOffset("DATELINEOFFSET=");
-                soOffset += pszDateLineOffset;
-                papszTransformOptions =
-                    CSLAddString(papszTransformOptions, soOffset);
-            }
-            else if (poSourceSRS != NULL && poSourceSRS->IsGeographic())
-            {
-                papszTransformOptions =
-                    CSLAddString(papszTransformOptions, "WRAPDATELINE=YES");
-                CPLString soOffset("DATELINEOFFSET=");
-                soOffset += pszDateLineOffset;
-                papszTransformOptions =
-                    CSLAddString(papszTransformOptions, soOffset);
-            }
-            else
-            {
-                static int bHasWarned = FALSE;
-                if( !bHasWarned )
-                    fprintf(stderr, "-wrapdateline option only works when reprojecting to a geographic SRS\n");
-                bHasWarned = TRUE;
-            }
-
-            CSLDestroy(psInfo->papapszTransformOptions[iGeom]);
-            psInfo->papapszTransformOptions[iGeom] = papszTransformOptions;
-        }
-    }
-    return TRUE;
-}
-/************************************************************************/
-/*                     LayerTranslator::Translate()                     */
-/************************************************************************/
-
-int LayerTranslator::Translate( TargetLayerInfo* psInfo,
-                                GIntBig nCountLayerFeatures,
-                                GIntBig* pnReadFeatureCount,
-                                GDALProgressFunc pfnProgress,
-                                void *pProgressArg )
-{
-    OGRLayer    *poSrcLayer;
-    OGRLayer    *poDstLayer;
-    int         *panMap = NULL;
-    int         iSrcZField;
-    int         eGType = eGTypeIn;
-    OGRSpatialReference* poOutputSRS = poOutputSRSIn;
-    int         bExplodeCollections = bExplodeCollectionsIn;
-    int         bPreserveFID;
-
-    poSrcLayer = psInfo->poSrcLayer;
-    poDstLayer = psInfo->poDstLayer;
-    panMap = psInfo->panMap;
-    iSrcZField = psInfo->iSrcZField;
-    bPreserveFID = psInfo->bPreserveFID;
-    int nSrcGeomFieldCount = poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
-    int nDstGeomFieldCount = poDstLayer->GetLayerDefn()->GetGeomFieldCount();
-
-    if( poOutputSRS == NULL && !bNullifyOutputSRS )
-    {
-        if( nSrcGeomFieldCount == 1 )
-        {
-            poOutputSRS = poSrcLayer->GetSpatialRef();
-        }
-        else if( psInfo->iRequestedSrcGeomField > 0 )
-        {
-            poOutputSRS = poSrcLayer->GetLayerDefn()->GetGeomFieldDefn(
-                psInfo->iRequestedSrcGeomField)->GetSpatialRef();
-        }
-
-    }
-
-    if( bExplodeCollections && nDstGeomFieldCount > 1 )
-    {
-        bExplodeCollections = FALSE;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Transfer features.                                              */
-/* -------------------------------------------------------------------- */
-    OGRFeature  *poFeature;
-    int         nFeaturesInTransaction = 0;
-    GIntBig      nCount = 0; /* written + failed */
-    GIntBig      nFeaturesWritten = 0;
-
-    if( nGroupTransactions )
-    {
-        if( bLayerTransaction )
-            poDstLayer->StartTransaction();
-    }
-
-    while( TRUE )
-    {
-        OGRFeature      *poDstFeature = NULL;
-
-        if( nFIDToFetch != OGRNullFID )
-            poFeature = poSrcLayer->GetFeature(nFIDToFetch);
-        else
-            poFeature = poSrcLayer->GetNextFeature();
-
-        if( poFeature == NULL )
-            break;
-
-        if( psInfo->nFeaturesRead == 0 || psInfo->bPerFeatureCT )
-        {
-            if( !SetupCT( psInfo, poSrcLayer, bTransform, bWrapDateline,
-                          pszDateLineOffset, poUserSourceSRS,
-                          poFeature, poOutputSRS, poGCPCoordTrans) )
-            {
-                OGRFeature::DestroyFeature( poFeature );
-                return FALSE;
-            }
-        }
-
-        psInfo->nFeaturesRead ++;
-
-        int nParts = 0;
-        int nIters = 1;
-        if (bExplodeCollections)
-        {
-            OGRGeometry* poSrcGeometry;
-            if( psInfo->iRequestedSrcGeomField >= 0 )
-                poSrcGeometry = poFeature->GetGeomFieldRef(
-                                        psInfo->iRequestedSrcGeomField);
-            else
-                poSrcGeometry = poFeature->GetGeometryRef();
-            if (poSrcGeometry &&
-                OGR_GT_IsSubClassOf(poSrcGeometry->getGeometryType(), wkbGeometryCollection) )
-            {
-                nParts = ((OGRGeometryCollection*)poSrcGeometry)->getNumGeometries();
-                nIters = nParts;
-                if (nIters == 0)
-                    nIters = 1;
-            }
-        }
-
-        for(int iPart = 0; iPart < nIters; iPart++)
-        {
-            if( ++nFeaturesInTransaction == nGroupTransactions )
-            {
-                if( bLayerTransaction )
-                {
-                    poDstLayer->CommitTransaction();
-                    poDstLayer->StartTransaction();
-                }
-                else
-                {
-                    poODS->CommitTransaction();
-                    poODS->StartTransaction(bForceTransaction);
-                }
-                nFeaturesInTransaction = 0;
-            }
-
-            CPLErrorReset();
-            poDstFeature = OGRFeature::CreateFeature( poDstLayer->GetLayerDefn() );
-
-            /* Optimization to avoid duplicating the source geometry in the */
-            /* target feature : we steal it from the source feature for now... */
-            OGRGeometry* poStolenGeometry = NULL;
-            if( !bExplodeCollections && nSrcGeomFieldCount == 1 &&
-                nDstGeomFieldCount == 1 )
-            {
-                poStolenGeometry = poFeature->StealGeometry();
-            }
-            else if( !bExplodeCollections &&
-                     psInfo->iRequestedSrcGeomField >= 0 )
-            {
-                poStolenGeometry = poFeature->StealGeometry(
-                    psInfo->iRequestedSrcGeomField);
-            }
-
-            if( poDstFeature->SetFrom( poFeature, panMap, TRUE ) != OGRERR_NONE )
-            {
-                if( nGroupTransactions )
-                {
-                    if( bLayerTransaction )
-                    {
-                        poDstLayer->CommitTransaction();
-                    }
-                }
-
-                CPLError( CE_Failure, CPLE_AppDefined,
-                        "Unable to translate feature " CPL_FRMT_GIB " from layer %s.\n",
-                        poFeature->GetFID(), poSrcLayer->GetName() );
-
-                OGRFeature::DestroyFeature( poFeature );
-                OGRFeature::DestroyFeature( poDstFeature );
-                OGRGeometryFactory::destroyGeometry( poStolenGeometry );
-                return FALSE;
-            }
-
-            /* ... and now we can attach the stolen geometry */
-            if( poStolenGeometry )
-            {
-                poDstFeature->SetGeometryDirectly(poStolenGeometry);
-            }
-
-            if( bPreserveFID )
-                poDstFeature->SetFID( poFeature->GetFID() );
-            else if( psInfo->iSrcFIDField >= 0 &&
-                     poFeature->IsFieldSet(psInfo->iSrcFIDField))
-                poDstFeature->SetFID( poFeature->GetFieldAsInteger64(psInfo->iSrcFIDField) );
-            
-            for( int iGeom = 0; iGeom < nDstGeomFieldCount; iGeom ++ )
-            {
-                OGRGeometry* poDstGeometry = poDstFeature->GetGeomFieldRef(iGeom);
-                if (poDstGeometry == NULL)
-                    continue;
-
-                if (nParts > 0)
-                {
-                    /* For -explodecollections, extract the iPart(th) of the geometry */
-                    OGRGeometry* poPart = ((OGRGeometryCollection*)poDstGeometry)->getGeometryRef(iPart);
-                    ((OGRGeometryCollection*)poDstGeometry)->removeGeometry(iPart, FALSE);
-                    poDstFeature->SetGeomFieldDirectly(iGeom, poPart);
-                    poDstGeometry = poPart;
-                }
-
-                if (iSrcZField != -1)
-                {
-                    SetZ(poDstGeometry, poFeature->GetFieldAsDouble(iSrcZField));
-                    /* This will correct the coordinate dimension to 3 */
-                    OGRGeometry* poDupGeometry = poDstGeometry->clone();
-                    poDstFeature->SetGeomFieldDirectly(iGeom, poDupGeometry);
-                    poDstGeometry = poDupGeometry;
-                }
-
-                if (nCoordDim == 2 || nCoordDim == 3)
-                    poDstGeometry->setCoordinateDimension( nCoordDim );
-                else if ( nCoordDim == COORD_DIM_LAYER_DIM )
-                    poDstGeometry->setCoordinateDimension(
-                        wkbHasZ(poDstLayer->GetLayerDefn()->GetGeomFieldDefn(iGeom)->GetType()) ? 3 : 2 );
-
-                if (eGeomOp == SEGMENTIZE)
-                {
-                    if (dfGeomOpParam > 0)
-                        poDstGeometry->segmentize(dfGeomOpParam);
-                }
-                else if (eGeomOp == SIMPLIFY_PRESERVE_TOPOLOGY)
-                {
-                    if (dfGeomOpParam > 0)
-                    {
-                        OGRGeometry* poNewGeom = poDstGeometry->SimplifyPreserveTopology(dfGeomOpParam);
-                        if (poNewGeom)
-                        {
-                            poDstFeature->SetGeomFieldDirectly(iGeom, poNewGeom);
-                            poDstGeometry = poNewGeom;
-                        }
-                    }
-                }
-
-                if (poClipSrc)
-                {
-                    OGRGeometry* poClipped = poDstGeometry->Intersection(poClipSrc);
-                    if (poClipped == NULL || poClipped->IsEmpty())
-                    {
-                        OGRGeometryFactory::destroyGeometry(poClipped);
-                        goto end_loop;
-                    }
-                    poDstFeature->SetGeomFieldDirectly(iGeom, poClipped);
-                    poDstGeometry = poClipped;
-                }
-                
-                OGRCoordinateTransformation* poCT = psInfo->papoCT[iGeom];
-                if( !bTransform )
-                    poCT = poGCPCoordTrans;
-                char** papszTransformOptions = psInfo->papapszTransformOptions[iGeom];
-
-                if( poCT != NULL || papszTransformOptions != NULL)
-                {
-                    OGRGeometry* poReprojectedGeom =
-                        OGRGeometryFactory::transformWithOptions(poDstGeometry, poCT, papszTransformOptions);
-                    if( poReprojectedGeom == NULL )
-                    {
-                        if( nGroupTransactions )
-                        {
-                            if( bLayerTransaction )
-                            {
-                                poDstLayer->CommitTransaction();
-                            }
-                        }
-
-                        fprintf( stderr, "Failed to reproject feature %d (geometry probably out of source or destination SRS).\n",
-                                (int) poFeature->GetFID() );
-                        if( !bSkipFailures )
-                        {
-                            OGRFeature::DestroyFeature( poFeature );
-                            OGRFeature::DestroyFeature( poDstFeature );
-                            return FALSE;
-                        }
-                    }
-
-                    poDstFeature->SetGeomFieldDirectly(iGeom, poReprojectedGeom);
-                    poDstGeometry = poReprojectedGeom;
-                }
-                else if (poOutputSRS != NULL)
-                {
-                    poDstGeometry->assignSpatialReference(poOutputSRS);
-                }
-
-                if (poClipDst)
-                {
-                    if( poDstGeometry == NULL )
-                        goto end_loop;
-
-                    OGRGeometry* poClipped = poDstGeometry->Intersection(poClipDst);
-                    if (poClipped == NULL || poClipped->IsEmpty())
-                    {
-                        OGRGeometryFactory::destroyGeometry(poClipped);
-                        goto end_loop;
-                    }
-
-                    poDstFeature->SetGeomFieldDirectly(iGeom, poClipped);
-                    poDstGeometry = poClipped;
-                }
-
-                if( eGType != -2 )
-                {
-                    poDstFeature->SetGeomFieldDirectly(iGeom, 
-                        OGRGeometryFactory::forceTo(
-                            poDstFeature->StealGeometry(iGeom), (OGRwkbGeometryType)eGType) );
-                }
-                else if( sGeomConversion.bPromoteToMulti ||
-                         sGeomConversion.bConvertToLinear ||
-                         sGeomConversion.bConvertToCurve )
-                {
-                    poDstGeometry = poDstFeature->StealGeometry(iGeom);
-                    if( poDstGeometry != NULL )
-                    {
-                        OGRwkbGeometryType eTargetType = poDstGeometry->getGeometryType();
-                        eTargetType = ConvertType(sGeomConversion, eTargetType);
-                        poDstGeometry = OGRGeometryFactory::forceTo(poDstGeometry, eTargetType);
-                        poDstFeature->SetGeomFieldDirectly(iGeom, poDstGeometry);
-                    }
-                }
-            }
-
-            CPLErrorReset();
-            if( poDstLayer->CreateFeature( poDstFeature ) == OGRERR_NONE )
-            {
-                nFeaturesWritten ++;
-                if( (bPreserveFID && poDstFeature->GetFID() != poFeature->GetFID()) ||
-                    (!bPreserveFID && psInfo->iSrcFIDField >= 0 && poFeature->IsFieldSet(psInfo->iSrcFIDField) &&
-                     poDstFeature->GetFID() != poFeature->GetFieldAsInteger64(psInfo->iSrcFIDField)) )
-                {
-                    CPLError( CE_Warning, CPLE_AppDefined,
-                              "Feature id not preserved");
-                }
-            }
-            else if( !bSkipFailures )
-            {
-                if( nGroupTransactions )
-                {
-                    if( bLayerTransaction )
-                        poDstLayer->RollbackTransaction();
-                }
-
-                CPLError( CE_Failure, CPLE_AppDefined,
-                        "Unable to write feature " CPL_FRMT_GIB " from layer %s.\n",
-                        poFeature->GetFID(), poSrcLayer->GetName() );
-
-                OGRFeature::DestroyFeature( poFeature );
-                OGRFeature::DestroyFeature( poDstFeature );
-                return FALSE;
-            }
-            else
-            {
-                CPLDebug( "OGR2OGR", "Unable to write feature " CPL_FRMT_GIB " into layer %s.\n",
-                           poFeature->GetFID(), poSrcLayer->GetName() );
-                if( nGroupTransactions )
-                {
-                    if( bLayerTransaction )
-                    {
-                        poDstLayer->RollbackTransaction();
-                        poDstLayer->StartTransaction();
-                    }
-                    else
-                    {
-                        poODS->RollbackTransaction();
-                        poODS->StartTransaction(bForceTransaction);
-                    }
-                }
-            }
-
-end_loop:
-            OGRFeature::DestroyFeature( poDstFeature );
-        }
-
-        OGRFeature::DestroyFeature( poFeature );
-
-        /* Report progress */
-        nCount ++;
-        if (pfnProgress)
-        {
-            if (nSrcFileSize != 0)
-            {
-                if ((nCount % 1000) == 0)
-                {
-                    OGRLayer* poFCLayer = poSrcDS->ExecuteSQL("GetBytesRead()", NULL, NULL);
-                    if( poFCLayer != NULL )
-                    {
-                        OGRFeature* poFeat = poFCLayer->GetNextFeature();
-                        if( poFeat )
-                        {
-                            const char* pszReadSize = poFeat->GetFieldAsString(0);
-                            GUIntBig nReadSize = CPLScanUIntBig( pszReadSize, 32 );
-                            pfnProgress(nReadSize * 1.0 / nSrcFileSize, "", pProgressArg);
-                            OGRFeature::DestroyFeature( poFeat );
-                        }
-                    }
-                    poSrcDS->ReleaseResultSet(poFCLayer);
-                }
-            }
-            else
-            {
-                pfnProgress(nCount * 1.0 / nCountLayerFeatures, "", pProgressArg);
-            }
-        }
-
-        if (pnReadFeatureCount)
-            *pnReadFeatureCount = nCount;
-        
-        if( nFIDToFetch != OGRNullFID )
-            break;
-    }
-
-    if( nGroupTransactions )
-    {
-        if( bLayerTransaction )
-        {
-            poDstLayer->CommitTransaction();
-        }
-    }
-
-    CPLDebug("OGR2OGR", CPL_FRMT_GIB " features written in layer '%s'",
-             nFeaturesWritten, poDstLayer->GetName());
-
-    return TRUE;
-}
diff --git a/apps/ogr2ogr_bin.cpp b/apps/ogr2ogr_bin.cpp
new file mode 100644
index 0000000..44fb413
--- /dev/null
+++ b/apps/ogr2ogr_bin.cpp
@@ -0,0 +1,403 @@
+/******************************************************************************
+ * $Id: ogr2ogr_bin.cpp 33615 2016-03-02 20:19:22Z goatbar $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Simple client for translating between formats.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2008-2015, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogrsf_frmts.h"
+#include "ogr_p.h"
+#include "gdal_utils_priv.h"
+#include "commonutils.h"
+
+CPL_CVSID("$Id: ogr2ogr_bin.cpp 33615 2016-03-02 20:19:22Z goatbar $");
+
+static void Usage(int bShort = TRUE);
+static void Usage(const char* pszAdditionalMsg, int bShort = TRUE);
+
+/************************************************************************/
+/*                 GDALVectorTranslateOptionsForBinaryNew()             */
+/************************************************************************/
+
+static GDALVectorTranslateOptionsForBinary *GDALVectorTranslateOptionsForBinaryNew(void)
+{
+    return (GDALVectorTranslateOptionsForBinary*) CPLCalloc(  1, sizeof(GDALVectorTranslateOptionsForBinary) );
+}
+
+/************************************************************************/
+/*                  GDALVectorTranslateOptionsForBinaryFree()           */
+/************************************************************************/
+
+static void GDALVectorTranslateOptionsForBinaryFree( GDALVectorTranslateOptionsForBinary* psOptionsForBinary )
+{
+    if( psOptionsForBinary )
+    {
+        CPLFree(psOptionsForBinary->pszDataSource);
+        CPLFree(psOptionsForBinary->pszDestDataSource);
+        CSLDestroy(psOptionsForBinary->papszOpenOptions);
+        CPLFree(psOptionsForBinary->pszFormat);
+        CPLFree(psOptionsForBinary);
+    }
+}
+
+/* -------------------------------------------------------------------- */
+/*                  CheckDestDataSourceNameConsistency()                */
+/* -------------------------------------------------------------------- */
+
+static
+void CheckDestDataSourceNameConsistency(const char* pszDestFilename,
+                                        const char* pszDriverName)
+{
+    int i;
+    char* pszDestExtension = CPLStrdup(CPLGetExtension(pszDestFilename));
+
+    if( EQUAL(pszDriverName, "GMT") )
+        pszDriverName = "OGR_GMT";
+    CheckExtensionConsistency(pszDestFilename, pszDriverName);
+
+    static const char* apszBeginName[][2] =  { { "PG:"      , "PostgreSQL" },
+                                               { "MySQL:"   , "MySQL" },
+                                               { "CouchDB:" , "CouchDB" },
+                                               { "GFT:"     , "GFT" },
+                                               { "MSSQL:"   , "MSSQLSpatial" },
+                                               { "ODBC:"    , "ODBC" },
+                                               { "OCI:"     , "OCI" },
+                                               { "SDE:"     , "SDE" },
+                                               { "WFS:"     , "WFS" },
+                                               { NULL, NULL }
+                                             };
+
+    for(i=0; apszBeginName[i][0] != NULL; i++)
+    {
+        if (EQUALN(pszDestFilename, apszBeginName[i][0], strlen(apszBeginName[i][0])) &&
+            !EQUAL(pszDriverName, apszBeginName[i][1]))
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                    "The target file has a name which is normally recognized by the %s driver,\n"
+                    "but the requested output driver is %s. Is it really what you want ?\n",
+                    apszBeginName[i][1],
+                    pszDriverName);
+            break;
+        }
+    }
+
+    CPLFree(pszDestExtension);
+}
+
+/************************************************************************/
+/*                                main()                                */
+/************************************************************************/
+
+int main( int nArgc, char ** papszArgv )
+{
+    GDALDatasetH hDS = NULL;
+    GDALDatasetH hODS = NULL;
+    int bCloseODS = TRUE;
+    int bUsageError = FALSE;
+    GDALDatasetH hDstDS;
+    int nRetCode = 1;
+    GDALVectorTranslateOptionsForBinary* psOptionsForBinary;
+    GDALVectorTranslateOptions *psOptions;
+
+    /* Check strict compilation and runtime library version as we use C++ API */
+    if (! GDAL_CHECK_VERSION(papszArgv[0]))
+        exit(1);
+
+    EarlySetConfigOptions(nArgc, papszArgv);
+
+/* -------------------------------------------------------------------- */
+/*      Register format(s).                                             */
+/* -------------------------------------------------------------------- */
+    OGRRegisterAll();
+
+/* -------------------------------------------------------------------- */
+/*      Processing command line arguments.                              */
+/* -------------------------------------------------------------------- */
+    nArgc = OGRGeneralCmdLineProcessor( nArgc, &papszArgv, 0 );
+
+    if( nArgc < 1 )
+    {
+        papszArgv = NULL;
+        nRetCode = -nArgc;
+        goto exit;
+    }
+
+    for( int iArg = 1; iArg < nArgc; iArg++ )
+    {
+        if( EQUAL(papszArgv[iArg], "--utility_version") )
+        {
+            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
+                   papszArgv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
+            goto exit;
+        }
+        else if( EQUAL(papszArgv[iArg],"--help") )
+        {
+            Usage();
+            goto exit;
+        }
+        else if ( EQUAL(papszArgv[iArg], "--long-usage") )
+        {
+            Usage(FALSE);
+            goto exit;
+        }
+    }
+
+    psOptionsForBinary = GDALVectorTranslateOptionsForBinaryNew();
+    psOptions = GDALVectorTranslateOptionsNew(papszArgv + 1, psOptionsForBinary);
+
+    if( psOptions == NULL )
+    {
+        Usage();
+        GDALVectorTranslateOptionsForBinaryFree(psOptionsForBinary);
+        goto exit;
+    }
+
+    if( psOptionsForBinary->pszDataSource == NULL ||
+        psOptionsForBinary->pszDestDataSource == NULL )
+    {
+        if( psOptionsForBinary->pszDestDataSource == NULL )
+            Usage("no target datasource provided");
+        else
+            Usage("no source datasource provided");
+        GDALVectorTranslateOptionsFree(psOptions);
+        GDALVectorTranslateOptionsForBinaryFree(psOptionsForBinary);
+        goto exit;
+    }
+
+    if( strcmp(psOptionsForBinary->pszDestDataSource, "/vsistdout/") == 0 )
+        psOptionsForBinary->bQuiet = TRUE;
+
+    if (!psOptionsForBinary->bQuiet && psOptionsForBinary->bFormatExplicitlySet)
+    {
+        CheckDestDataSourceNameConsistency(psOptionsForBinary->pszDestDataSource,
+                                           psOptionsForBinary->pszFormat);
+
+    }
+/* -------------------------------------------------------------------- */
+/*      Open data source.                                               */
+/* -------------------------------------------------------------------- */
+
+    /* Avoid opening twice the same datasource if it is both the input and output */
+    /* Known to cause problems with at least FGdb, SQlite and GPKG drivers. See #4270 */
+    if (psOptionsForBinary->eAccessMode != ACCESS_CREATION &&
+        strcmp(psOptionsForBinary->pszDestDataSource, psOptionsForBinary->pszDataSource) == 0)
+    {
+        hODS = GDALOpenEx( psOptionsForBinary->pszDataSource,
+                GDAL_OF_UPDATE | GDAL_OF_VECTOR, NULL, psOptionsForBinary->papszOpenOptions, NULL );
+        GDALDriverH hDriver = NULL;
+        if( hODS != NULL )
+            hDriver = GDALGetDatasetDriver(hODS);
+
+        /* Restrict to those 3 drivers. For example it is known to break with */
+        /* the PG driver due to the way it manages transactions... */
+        if (hDriver && !(EQUAL(GDALGetDescription(hDriver), "FileGDB") ||
+                         EQUAL(GDALGetDescription(hDriver), "SQLite") ||
+                         EQUAL(GDALGetDescription(hDriver), "GPKG")))
+        {
+            hDS = GDALOpenEx( psOptionsForBinary->pszDataSource,
+                        GDAL_OF_VECTOR, NULL, psOptionsForBinary->papszOpenOptions, NULL );
+        }
+        else
+        {
+            hDS = hODS;
+            bCloseODS = FALSE;
+        }
+    }
+    else
+    {
+        hDS = GDALOpenEx( psOptionsForBinary->pszDataSource,
+                        GDAL_OF_VECTOR, NULL, psOptionsForBinary->papszOpenOptions, NULL );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Report failure                                                  */
+/* -------------------------------------------------------------------- */
+    if( hDS == NULL )
+    {
+        OGRSFDriverRegistrar    *poR = OGRSFDriverRegistrar::GetRegistrar();
+
+        fprintf( stderr, "FAILURE:\n"
+                "Unable to open datasource `%s' with the following drivers.\n",
+                psOptionsForBinary->pszDataSource );
+
+        for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
+        {
+            fprintf( stderr, "  -> %s\n", poR->GetDriver(iDriver)->GetDescription() );
+        }
+
+        GDALVectorTranslateOptionsFree(psOptions);
+        GDALVectorTranslateOptionsForBinaryFree(psOptionsForBinary);
+        goto exit;
+    }
+
+    if( !(psOptionsForBinary->bQuiet) )
+    {
+        GDALVectorTranslateOptionsSetProgress(psOptions, GDALTermProgress, NULL);
+    }
+
+    hDstDS = GDALVectorTranslate(psOptionsForBinary->pszDestDataSource, hODS,
+                                              1, &hDS, psOptions, &bUsageError);
+    if( bUsageError )
+        Usage();
+    else
+        nRetCode = (hDstDS) ? 0 : 1;
+
+    GDALVectorTranslateOptionsFree(psOptions);
+    GDALVectorTranslateOptionsForBinaryFree(psOptionsForBinary);
+
+    if(hDS)
+        GDALClose(hDS);
+    if(bCloseODS)
+        GDALClose(hDstDS);
+
+exit:
+    CSLDestroy( papszArgv );
+    OGRCleanupAll();
+
+    return nRetCode;
+}
+
+/************************************************************************/
+/*                               Usage()                                */
+/************************************************************************/
+
+static void Usage(int bShort)
+{
+    Usage(NULL, bShort);
+}
+
+static void Usage(const char* pszAdditionalMsg, int bShort)
+
+{
+    OGRSFDriverRegistrar        *poR = OGRSFDriverRegistrar::GetRegistrar();
+
+
+    printf( "Usage: ogr2ogr [--help-general] [-skipfailures] [-append] [-update]\n"
+            "               [-select field_list] [-where restricted_where|@filename]\n"
+            "               [-progress] [-sql <sql statement>|@filename] [-dialect dialect]\n"
+            "               [-preserve_fid] [-fid FID]\n"
+            "               [-spat xmin ymin xmax ymax] [-spat_srs srs_def] [-geomfield field]\n"
+            "               [-a_srs srs_def] [-t_srs srs_def] [-s_srs srs_def]\n"
+            "               [-f format_name] [-overwrite] [[-dsco NAME=VALUE] ...]\n"
+            "               dst_datasource_name src_datasource_name\n"
+            "               [-lco NAME=VALUE] [-nln name] \n"
+            "               [-nlt type|PROMOTE_TO_MULTI|CONVERT_TO_LINEAR]\n"
+            "               [-dim 2|3|layer_dim] [layer [layer ...]]\n"
+            "\n"
+            "Advanced options :\n"
+            "               [-gt n] [-ds_transaction]\n"
+            "               [[-oo NAME=VALUE] ...] [[-doo NAME=VALUE] ...]\n"
+            "               [-clipsrc [xmin ymin xmax ymax]|WKT|datasource|spat_extent]\n"
+            "               [-clipsrcsql sql_statement] [-clipsrclayer layer]\n"
+            "               [-clipsrcwhere expression]\n"
+            "               [-clipdst [xmin ymin xmax ymax]|WKT|datasource]\n"
+            "               [-clipdstsql sql_statement] [-clipdstlayer layer]\n"
+            "               [-clipdstwhere expression]\n"
+            "               [-wrapdateline][-datelineoffset val]\n"
+            "               [[-simplify tolerance] | [-segmentize max_dist]]\n"
+            "               [-addfields] [-unsetFid]\n"
+            "               [-relaxedFieldNameMatch] [-forceNullable] [-unsetDefault]\n"
+            "               [-fieldTypeToString All|(type1[,type2]*)] [-unsetFieldWidth]\n"
+            "               [-mapFieldType srctype|All=dsttype[,srctype2=dsttype2]*]\n"
+            "               [-fieldmap identity | index1[,index2]*]\n"
+            "               [-splitlistfields] [-maxsubfields val]\n"
+            "               [-explodecollections] [-zfield field_name]\n"
+            "               [-gcp pixel line easting northing [elevation]]* [-order n | -tps]\n"
+            "               [-nomd] [-mo \"META-TAG=VALUE\"]* [-noNativeData]\n");
+
+    if (bShort)
+    {
+        printf( "\nNote: ogr2ogr --long-usage for full help.\n");
+        if( pszAdditionalMsg )
+            fprintf(stderr, "\nFAILURE: %s\n", pszAdditionalMsg);
+        exit( 1 );
+    }
+
+    printf("\n -f format_name: output file format name, possible values are:\n");
+
+    for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
+    {
+        GDALDriver *poDriver = poR->GetDriver(iDriver);
+
+        if( CPLTestBool( CSLFetchNameValueDef(poDriver->GetMetadata(), GDAL_DCAP_CREATE, "FALSE") ) )
+            printf( "     -f \"%s\"\n", poDriver->GetDescription() );
+    }
+
+    printf( " -append: Append to existing layer instead of creating new if it exists\n"
+            " -overwrite: delete the output layer and recreate it empty\n"
+            " -update: Open existing output datasource in update mode\n"
+            " -progress: Display progress on terminal. Only works if input layers have the \n"
+            "                                          \"fast feature count\" capability\n"
+            " -select field_list: Comma-delimited list of fields from input layer to\n"
+            "                     copy to the new layer (defaults to all)\n"
+            " -where restricted_where: Attribute query (like SQL WHERE)\n"
+            " -wrapdateline: split geometries crossing the dateline meridian\n"
+            "                (long. = +/- 180deg)\n"
+            " -datelineoffset: offset from dateline in degrees\n"
+            "                (default long. = +/- 10deg,\n"
+            "                geometries within 170deg to -170deg will be split)\n"
+            " -sql statement: Execute given SQL statement and save result.\n"
+            " -dialect value: select a dialect, usually OGRSQL to avoid native sql.\n"
+            " -skipfailures: skip features or layers that fail to convert\n"
+            " -gt n: group n features per transaction (default 20000). n can be set to unlimited\n"
+            " -spat xmin ymin xmax ymax: spatial query extents\n"
+            " -simplify tolerance: distance tolerance for simplification.\n"
+            " -segmentize max_dist: maximum distance between 2 nodes.\n"
+            "                       Used to create intermediate points\n"
+            " -dsco NAME=VALUE: Dataset creation option (format specific)\n"
+            " -lco  NAME=VALUE: Layer creation option (format specific)\n"
+            " -oo   NAME=VALUE: Input dataset open option (format specific)\n"
+            " -doo  NAME=VALUE: Destination dataset open option (format specific)\n"
+            " -nln name: Assign an alternate name to the new layer\n"
+            " -nlt type: Force a geometry type for new layer.  One of NONE, GEOMETRY,\n"
+            "      POINT, LINESTRING, POLYGON, GEOMETRYCOLLECTION, MULTIPOINT,\n"
+            "      MULTIPOLYGON, or MULTILINESTRING, or PROMOTE_TO_MULTI or CONVERT_TO_LINEAR.  Add \"25D\" for 3D layers.\n"
+            "      Default is type of source layer.\n"
+            " -dim dimension: Force the coordinate dimension to the specified value.\n"
+            " -fieldTypeToString type1,...: Converts fields of specified types to\n"
+            "      fields of type string in the new layer. Valid types are : Integer,\n"
+            "      Integer64, Real, String, Date, Time, DateTime, Binary, IntegerList, Integer64List, RealList,\n"
+            "      StringList. Special value All will convert all fields to strings.\n"
+            " -fieldmap index1,index2,...: Specifies the list of field indexes to be\n"
+            "      copied from the source to the destination. The (n)th value specified\n"
+            "      in the list is the index of the field in the target layer definition\n"
+            "      in which the n(th) field of the source layer must be copied. Index count\n"
+            "      starts at zero. There must be exactly as many values in the list as\n"
+            "      the count of the fields in the source layer. We can use the 'identity'\n"
+            "      setting to specify that the fields should be transferred by using the\n"
+            "      same order. This setting should be used along with the append setting.");
+
+    printf(" -a_srs srs_def: Assign an output SRS\n"
+           " -t_srs srs_def: Reproject/transform to this SRS on output\n"
+           " -s_srs srs_def: Override source SRS\n"
+           "\n"
+           " Srs_def can be a full WKT definition (hard to escape properly),\n"
+           " or a well known definition (i.e. EPSG:4326) or a file with a WKT\n"
+           " definition.\n" );
+
+    if( pszAdditionalMsg )
+        fprintf(stderr, "\nFAILURE: %s\n", pszAdditionalMsg);
+}
diff --git a/apps/ogr2ogr_lib.cpp b/apps/ogr2ogr_lib.cpp
new file mode 100644
index 0000000..f1c506e
--- /dev/null
+++ b/apps/ogr2ogr_lib.cpp
@@ -0,0 +1,4599 @@
+/******************************************************************************
+ * $Id: ogr2ogr_lib.cpp 33615 2016-03-02 20:19:22Z goatbar $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Simple client for translating between formats.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2008-2015, Even Rouault <even dot rouault at mines-paris dot org>
+ * Copyright (c) 2015, Faza Mahamood
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogrsf_frmts.h"
+#include "ogr_p.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "cpl_error.h"
+#include "ogr_api.h"
+#include "gdal.h"
+#include "gdal_utils_priv.h"
+#include "gdal_alg.h"
+#include "commonutils.h"
+#include <map>
+#include <vector>
+
+CPL_CVSID("$Id: ogr2ogr_lib.cpp 33615 2016-03-02 20:19:22Z goatbar $");
+
+typedef enum
+{
+    GEOMOP_NONE,
+    GEOMOP_SEGMENTIZE,
+    GEOMOP_SIMPLIFY_PRESERVE_TOPOLOGY,
+} GeomOperation;
+
+typedef enum
+{
+    GTC_DEFAULT,
+    GTC_PROMOTE_TO_MULTI,
+    GTC_CONVERT_TO_LINEAR,
+    GTC_CONVERT_TO_CURVE,
+} GeomTypeConversion;
+
+#define GEOMTYPE_UNCHANGED  -2
+
+#define COORD_DIM_UNCHANGED -1
+#define COORD_DIM_LAYER_DIM -2
+#define COORD_DIM_XYM -3
+
+/************************************************************************/
+/*                        GDALVectorTranslateOptions                    */
+/************************************************************************/
+
+/** Options for use with GDALVectorTranslate(). GDALVectorTranslateOptions* must be allocated and
+ * freed with GDALVectorTranslateOptionsNew() and GDALVectorTranslateOptionsFree() respectively.
+ */
+struct GDALVectorTranslateOptions
+{
+    /*! continue after a failure, skipping the failed feature */
+    bool bSkipFailures;
+
+    /*! use layer level transaction. If set to FALSE, then it is interpreted as dataset level transaction. */
+    int nLayerTransaction;
+
+    /*! force the use of particular transaction type based on GDALVectorTranslate::nLayerTransaction */
+    bool bForceTransaction;
+
+    /*! group nGroupTransactions features per transaction (default 20000). Increase the value for better
+        performance when writing into DBMS drivers that have transaction support. nGroupTransactions can
+        be set to -1 to load the data into a single transaction */
+    int nGroupTransactions;
+
+    /*! If provided, only the feature with this feature id will be reported. Operates exclusive of
+        the spatial or attribute queries. Note: if you want to select several features based on their
+        feature id, you can also use the fact the 'fid' is a special field recognized by OGR SQL.
+        So GDALVectorTranslateOptions::pszWHERE = "fid in (1,3,5)" would select features 1, 3 and 5. */
+    GIntBig nFIDToFetch;
+
+    /*! allow or suppress progress monitor and other non-error output */
+    bool bQuiet;
+
+    /*! output file format name (default is ESRI Shapefile) */
+    char *pszFormat;
+
+    /*! list of layers of the source dataset which needs to be selected */
+    char **papszLayers;
+
+    /*! dataset creation option (format specific) */
+    char **papszDSCO;
+
+    /*! layer creation option (format specific) */
+    char **papszLCO;
+
+    /*! access modes */
+    GDALVectorTranslateAccessMode eAccessMode;
+
+    /*! It has the effect of adding, to existing target layers, the new fields found in source layers.
+        This option is useful when merging files that have non-strictly identical structures. This might
+        not work for output formats that don't support adding fields to existing non-empty layers. */
+    bool bAddMissingFields;
+
+    /*! It must be set to true to trigger reprojection, otherwise only SRS assignment is done. */
+    bool bTransform;
+
+    /*! output SRS. GDALVectorTranslateOptions::bTransform must be set to true to trigger reprojection,
+        otherwise only SRS assignment is done. */
+    char *pszOutputSRSDef;
+
+    /*! override source SRS */
+    char *pszSourceSRSDef;
+
+    bool bNullifyOutputSRS;
+
+    /*! If set to false, then field name matching between source and existing target layer is done
+        in a more relaxed way if the target driver has an implementation for it. */
+    bool bExactFieldNameMatch;
+
+    /*! an alternate name to the new layer */
+    char *pszNewLayerName;
+
+    /*! attribute query (like SQL WHERE) */
+    char *pszWHERE;
+
+    /*! name of the geometry field on which the spatial filter operates on. */
+    char *pszGeomField;
+
+    /*! list of fields from input layer to copy to the new layer. A field is skipped if
+        mentioned previously in the list even if the input layer has duplicate field names.
+        (Defaults to all; any field is skipped if a subsequent field with same name is
+        found.) Geometry fields can also be specified in the list. */
+    char **papszSelFields;
+
+    /*! SQL statement to execute. The resulting table/layer will be saved to the output. */
+    char *pszSQLStatement;
+
+    /*! SQL dialect. In some cases can be used to use (unoptimized) OGR SQL instead of the
+        native SQL of an RDBMS by using "OGRSQL". The "SQLITE" dialect can also be used with
+        any datasource. */
+    char *pszDialect;
+
+    /*! the geometry type for the created layer */
+    int eGType;
+
+    GeomTypeConversion eGeomTypeConversion;
+
+    /*! Geometric operation to perform */
+    GeomOperation eGeomOp;
+
+    /*! the parameter to geometric operation */
+    double dfGeomOpParam;
+
+    /*! list of field types to convert to a field of type string in the destination layer.
+        Valid types are: Integer, Integer64, Real, String, Date, Time, DateTime, Binary,
+        IntegerList, Integer64List, RealList, StringList. Special value "All" can be
+        used to convert all fields to strings. This is an alternate way to using the CAST
+        operator of OGR SQL, that may avoid typing a long SQL query. Note that this does
+        not influence the field types used by the source driver, and is only an afterwards
+        conversion. */
+    char **papszFieldTypesToString;
+
+    /*! list of field types and the field type after conversion in the destination layer.
+        ("srctype1=dsttype1","srctype2=dsttype2",...).
+        Valid types are : Integer, Integer64, Real, String, Date, Time, DateTime, Binary,
+        IntegerList, Integer64List, RealList, StringList. Types can also include subtype
+        between parenthesis, such as Integer(Boolean), Real(Float32), ... Special value
+        "All" can be used to convert all fields to another type. This is an alternate way to
+        using the CAST operator of OGR SQL, that may avoid typing a long SQL query.
+        This is a generalization of GDALVectorTranslateOptions::papszFieldTypeToString. Note that this does not influence
+        the field types used by the source driver, and is only an afterwards conversion. */
+    char **papszMapFieldType;
+
+    /*! set field width and precision to 0 */
+    bool bUnsetFieldWidth;
+
+    /*! display progress on terminal. Only works if input layers have the "fast feature count"
+    capability */
+    bool bDisplayProgress;
+
+    /*! split geometries crossing the dateline meridian */
+    bool bWrapDateline;
+
+    /*! offset from dateline in degrees (default long. = +/- 10deg, geometries
+    within 170deg to -170deg will be split) */
+    double dfDateLineOffset;
+
+    /*! clip geometries when it is set to true */
+    bool bClipSrc;
+
+    OGRGeometryH hClipSrc;
+
+    /*! clip datasource */
+    char *pszClipSrcDS;
+
+    /*! select desired geometries using an SQL query */
+    char *pszClipSrcSQL;
+
+    /*! selected named layer from the source clip datasource */
+    char *pszClipSrcLayer;
+
+    /*! restrict desired geometries based on attribute query */
+    char *pszClipSrcWhere;
+
+    OGRGeometryH hClipDst;
+
+    /*! destination clip datasource */
+    char *pszClipDstDS;
+
+    /*! select desired geometries using an SQL query */
+    char *pszClipDstSQL;
+
+    /*! selected named layer from the destination clip datasource */
+    char *pszClipDstLayer;
+
+    /*! restrict desired geometries based on attribute query */
+    char *pszClipDstWhere;
+
+    /*! split fields of type StringList, RealList or IntegerList into as many fields
+        of type String, Real or Integer as necessary. */
+    bool bSplitListFields;
+
+    /*! limit the number of subfields created for each split field. */
+    int nMaxSplitListSubFields;
+
+    /*! produce one feature for each geometry in any kind of geometry collection in the
+        source file */
+    bool bExplodeCollections;
+
+    /*! uses the specified field to fill the Z coordinates of geometries */
+    char *pszZField;
+
+    /*! the list of field indexes to be copied from the source to the destination. The (n)th value
+        specified in the list is the index of the field in the target layer definition in which the
+        n(th) field of the source layer must be copied. Index count starts at zero. There must be
+        exactly as many values in the list as the count of the fields in the source layer.
+        We can use the "identity" option to specify that the fields should be transferred by using
+        the same order. This option should be used along with the
+        GDALVectorTranslateOptions::eAccessMode = ACCESS_APPEND option. */
+    char **papszFieldMap;
+
+    /*! force the coordinate dimension to nCoordDim (valid values are 2 or 3). This affects both
+        the layer geometry type, and feature geometries. */
+    int nCoordDim;
+
+    /*! destination dataset open option (format specific), only valid in update mode */
+    char **papszDestOpenOptions;
+
+    /*! If set to true, does not propagate not-nullable constraints to target layer if they exist
+        in source layer */
+    bool bForceNullable;
+
+    /*! If set to true, does not propagate default field values to target layer if they exist in
+        source layer */
+    bool bUnsetDefault;
+
+    /*! to prevent the new default behaviour that consists in, if the output driver has a FID layer
+        creation option and we are not in append mode, to preserve the name of the source FID column
+        and source feature IDs */
+    bool bUnsetFid;
+
+    /*! use the FID of the source features instead of letting the output driver to automatically
+        assign a new one. If not in append mode, this behaviour becomes the default if the output
+        driver has a FID layer creation option. In which case the name of the source FID column will
+        be used and source feature IDs will be attempted to be preserved. This behaviour can be
+        disabled by option GDALVectorTranslateOptions::bUnsetFid */
+    bool bPreserveFID;
+
+    /*! set it to false to disable copying of metadata from source dataset and layers into target dataset and
+        layers, when supported by output driver. */
+    bool bCopyMD;
+
+    /*! list of metadata key and value to set on the output dataset, when supported by output driver.
+        ("META-TAG1=VALUE1","META-TAG2=VALUE2") */
+    char **papszMetadataOptions;
+
+    /*! override spatial filter SRS */
+    char *pszSpatSRSDef;
+
+    /*! size of the list GDALVectorTranslateOptions::pasGCPs */
+    int nGCPCount;
+
+    /*! list of ground control points to be added */
+    GDAL_GCP *pasGCPs;
+
+    /*! order of polynomial used for warping (1 to 3). The default is to select a polynomial
+        order based on the number of GCPs */
+    int nTransformOrder;
+
+    /*! spatial query extents, in the SRS of the source layer(s) (or the one specified with
+        GDALVectorTranslateOptions::pszSpatSRSDef). Only features whose geometry intersects the extents
+        will be selected. The geometries will not be clipped unless GDALVectorTranslateOptions::bClipSrc
+        is true. */
+    OGRGeometryH hSpatialFilter;
+
+    /*! the progress function to use */
+    GDALProgressFunc pfnProgress;
+
+    /*! pointer to the progress data variable */
+    void *pProgressData;
+
+    /*! Whether layer and feature native data must be transferred. */
+    bool bNativeData;
+};
+
+typedef struct
+{
+    OGRLayer *   poSrcLayer;
+    GIntBig      nFeaturesRead;
+    bool         bPerFeatureCT;
+    OGRLayer    *poDstLayer;
+    OGRCoordinateTransformation **papoCT; // size: poDstLayer->GetLayerDefn()->GetFieldCount();
+    char       ***papapszTransformOptions; // size: poDstLayer->GetLayerDefn()->GetFieldCount();
+    int         *panMap;
+    int          iSrcZField;
+    int          iSrcFIDField;
+    int          iRequestedSrcGeomField;
+    bool         bPreserveFID;
+} TargetLayerInfo;
+
+typedef struct
+{
+    OGRLayer         *poSrcLayer;
+    TargetLayerInfo  *psInfo;
+} AssociatedLayers;
+
+class SetupTargetLayer
+{
+public:
+    GDALDataset          *m_poDstDS;
+    char                **m_papszLCO;
+    OGRSpatialReference  *m_poOutputSRS;
+    bool                  m_bNullifyOutputSRS;
+    char                **m_papszSelFields;
+    bool                  m_bAppend;
+    bool                  m_bAddMissingFields;
+    int                   m_eGType;
+    GeomTypeConversion    m_eGeomTypeConversion;
+    int                   m_nCoordDim;
+    bool                  m_bOverwrite;
+    char                **m_papszFieldTypesToString;
+    char                **m_papszMapFieldType;
+    bool                  m_bUnsetFieldWidth;
+    bool                  m_bExplodeCollections;
+    const char           *m_pszZField;
+    char                **m_papszFieldMap;
+    const char           *m_pszWHERE;
+    bool                  m_bExactFieldNameMatch;
+    bool                  m_bQuiet;
+    bool                  m_bForceNullable;
+    bool                  m_bUnsetDefault;
+    bool                  m_bUnsetFid;
+    bool                  m_bPreserveFID;
+    bool                  m_bCopyMD;
+    bool                  m_bNativeData;
+
+    TargetLayerInfo*            Setup(OGRLayer * poSrcLayer,
+                                      const char *pszNewLayerName,
+                                      GDALVectorTranslateOptions *psOptions);
+};
+
+class LayerTranslator
+{
+public:
+    GDALDataset                  *m_poSrcDS;
+    GDALDataset                  *m_poODS;
+    bool                          m_bTransform;
+    bool                          m_bWrapDateline;
+    CPLString                     m_osDateLineOffset;
+    OGRSpatialReference          *m_poOutputSRS;
+    bool                          m_bNullifyOutputSRS;
+    OGRSpatialReference          *m_poUserSourceSRS;
+    OGRCoordinateTransformation  *m_poGCPCoordTrans;
+    int                           m_eGType;
+    GeomTypeConversion            m_eGeomTypeConversion;
+    int                           m_nCoordDim;
+    GeomOperation                 m_eGeomOp;
+    double                        m_dfGeomOpParam;
+    OGRGeometry                  *m_poClipSrc;
+    OGRGeometry                  *m_poClipDst;
+    bool                          m_bExplodeCollections;
+    vsi_l_offset                  m_nSrcFileSize;
+    bool                          m_bNativeData;
+
+    int                 Translate(TargetLayerInfo* psInfo,
+                                  GIntBig nCountLayerFeatures,
+                                  GIntBig* pnReadFeatureCount,
+                                  GDALProgressFunc pfnProgress,
+                                  void *pProgressArg,
+                                  GDALVectorTranslateOptions *psOptions);
+};
+
+static OGRLayer* GetLayerAndOverwriteIfNecessary(GDALDataset *poDstDS,
+                                                 const char* pszNewLayerName,
+                                                 bool bOverwrite,
+                                                 bool* pbErrorOccurred);
+
+static void FreeTargetLayerInfo(TargetLayerInfo* psInfo);
+
+/************************************************************************/
+/*                           LoadGeometry()                             */
+/************************************************************************/
+
+static OGRGeometry* LoadGeometry( const char* pszDS,
+                                  const char* pszSQL,
+                                  const char* pszLyr,
+                                  const char* pszWhere)
+{
+    GDALDataset *poDS = (GDALDataset*) OGROpen( pszDS, FALSE, NULL );
+    if (poDS == NULL)
+        return NULL;
+
+    OGRLayer *poLyr;
+    if (pszSQL != NULL)
+        poLyr = poDS->ExecuteSQL( pszSQL, NULL, NULL );
+    else if (pszLyr != NULL)
+        poLyr = poDS->GetLayerByName(pszLyr);
+    else
+        poLyr = poDS->GetLayer(0);
+
+    if (poLyr == NULL)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Failed to identify source layer from datasource." );
+        GDALClose(( GDALDatasetH) poDS);
+        return NULL;
+    }
+
+    if (pszWhere)
+        poLyr->SetAttributeFilter(pszWhere);
+
+    OGRGeometry *poGeom = NULL;
+    OGRFeature *poFeat;
+    while ((poFeat = poLyr->GetNextFeature()) != NULL)
+    {
+        OGRGeometry* poSrcGeom = poFeat->GetGeometryRef();
+        if (poSrcGeom)
+        {
+            OGRwkbGeometryType eType = wkbFlatten( poSrcGeom->getGeometryType() );
+
+            if (poGeom == NULL)
+                poGeom = OGRGeometryFactory::createGeometry( wkbMultiPolygon );
+
+            if( eType == wkbPolygon )
+                ((OGRGeometryCollection*)poGeom)->addGeometry( poSrcGeom );
+            else if( eType == wkbMultiPolygon )
+            {
+                int iGeom;
+                int nGeomCount = OGR_G_GetGeometryCount( (OGRGeometryH)poSrcGeom );
+
+                for( iGeom = 0; iGeom < nGeomCount; iGeom++ )
+                {
+                    ((OGRGeometryCollection*)poGeom)->addGeometry(
+                                ((OGRGeometryCollection*)poSrcGeom)->getGeometryRef(iGeom) );
+                }
+            }
+            else
+            {
+                CPLError( CE_Failure, CPLE_AppDefined, "Geometry not of polygon type." );
+                OGRGeometryFactory::destroyGeometry(poGeom);
+                OGRFeature::DestroyFeature(poFeat);
+                if( pszSQL != NULL )
+                    poDS->ReleaseResultSet( poLyr );
+                GDALClose(( GDALDatasetH) poDS);
+                return NULL;
+            }
+        }
+
+        OGRFeature::DestroyFeature(poFeat);
+    }
+
+    if( pszSQL != NULL )
+        poDS->ReleaseResultSet( poLyr );
+    GDALClose(( GDALDatasetH) poDS);
+
+    return poGeom;
+}
+
+
+/************************************************************************/
+/*                     OGRSplitListFieldLayer                           */
+/************************************************************************/
+
+typedef struct
+{
+    int          iSrcIndex;
+    OGRFieldType eType;
+    int          nMaxOccurrences;
+    int          nWidth;
+} ListFieldDesc;
+
+class OGRSplitListFieldLayer : public OGRLayer
+{
+    OGRLayer                    *poSrcLayer;
+    OGRFeatureDefn              *poFeatureDefn;
+    ListFieldDesc               *pasListFields;
+    int                          nListFieldCount;
+    int                          nMaxSplitListSubFields;
+
+    OGRFeature                  *TranslateFeature(OGRFeature* poSrcFeature);
+
+  public:
+                                 OGRSplitListFieldLayer(OGRLayer* poSrcLayer,
+                                                        int nMaxSplitListSubFields);
+                                ~OGRSplitListFieldLayer();
+
+    bool                        BuildLayerDefn(GDALProgressFunc pfnProgress,
+                                                void *pProgressArg);
+
+    virtual OGRFeature          *GetNextFeature();
+    virtual OGRFeature          *GetFeature(GIntBig nFID);
+    virtual OGRFeatureDefn      *GetLayerDefn();
+
+    virtual void                 ResetReading() { poSrcLayer->ResetReading(); }
+    virtual int                  TestCapability(const char*) { return FALSE; }
+
+    virtual GIntBig              GetFeatureCount( int bForce = TRUE )
+    {
+        return poSrcLayer->GetFeatureCount(bForce);
+    }
+
+    virtual OGRSpatialReference *GetSpatialRef()
+    {
+        return poSrcLayer->GetSpatialRef();
+    }
+
+    virtual OGRGeometry         *GetSpatialFilter()
+    {
+        return poSrcLayer->GetSpatialFilter();
+    }
+
+    virtual OGRStyleTable       *GetStyleTable()
+    {
+        return poSrcLayer->GetStyleTable();
+    }
+
+    virtual void                 SetSpatialFilter( OGRGeometry *poGeom )
+    {
+        poSrcLayer->SetSpatialFilter(poGeom);
+    }
+
+    virtual void                 SetSpatialFilter( int iGeom, OGRGeometry *poGeom )
+    {
+        poSrcLayer->SetSpatialFilter(iGeom, poGeom);
+    }
+
+    virtual void                 SetSpatialFilterRect( double dfMinX, double dfMinY,
+                                                       double dfMaxX, double dfMaxY )
+    {
+        poSrcLayer->SetSpatialFilterRect(dfMinX, dfMinY, dfMaxX, dfMaxY);
+    }
+
+    virtual void                 SetSpatialFilterRect( int iGeom,
+                                                       double dfMinX, double dfMinY,
+                                                       double dfMaxX, double dfMaxY )
+    {
+        poSrcLayer->SetSpatialFilterRect(iGeom, dfMinX, dfMinY, dfMaxX, dfMaxY);
+    }
+
+    virtual OGRErr               SetAttributeFilter( const char *pszFilter )
+    {
+        return poSrcLayer->SetAttributeFilter(pszFilter);
+    }
+};
+
+/************************************************************************/
+/*                    OGRSplitListFieldLayer()                          */
+/************************************************************************/
+
+OGRSplitListFieldLayer::OGRSplitListFieldLayer(OGRLayer* poSrcLayerIn,
+                                               int nMaxSplitListSubFieldsIn)
+{
+    poSrcLayer = poSrcLayerIn;
+    nMaxSplitListSubFields = nMaxSplitListSubFieldsIn;
+    if (nMaxSplitListSubFields < 0)
+        nMaxSplitListSubFields = INT_MAX;
+    poFeatureDefn = NULL;
+    pasListFields = NULL;
+    nListFieldCount = 0;
+}
+
+/************************************************************************/
+/*                   ~OGRSplitListFieldLayer()                          */
+/************************************************************************/
+
+OGRSplitListFieldLayer::~OGRSplitListFieldLayer()
+{
+    if( poFeatureDefn )
+        poFeatureDefn->Release();
+
+    CPLFree(pasListFields);
+}
+
+/************************************************************************/
+/*                       BuildLayerDefn()                               */
+/************************************************************************/
+
+bool OGRSplitListFieldLayer::BuildLayerDefn(GDALProgressFunc pfnProgress,
+                                            void *pProgressArg)
+{
+    CPLAssert(poFeatureDefn == NULL);
+
+    OGRFeatureDefn* poSrcFieldDefn = poSrcLayer->GetLayerDefn();
+
+    int nSrcFields = poSrcFieldDefn->GetFieldCount();
+    pasListFields =
+            (ListFieldDesc*)CPLCalloc(sizeof(ListFieldDesc), nSrcFields);
+    nListFieldCount = 0;
+
+    /* Establish the list of fields of list type */
+    for( int i=0; i<nSrcFields; ++i )
+    {
+        OGRFieldType eType = poSrcFieldDefn->GetFieldDefn(i)->GetType();
+        if (eType == OFTIntegerList ||
+            eType == OFTInteger64List ||
+            eType == OFTRealList ||
+            eType == OFTStringList)
+        {
+            pasListFields[nListFieldCount].iSrcIndex = i;
+            pasListFields[nListFieldCount].eType = eType;
+            if (nMaxSplitListSubFields == 1)
+                pasListFields[nListFieldCount].nMaxOccurrences = 1;
+            nListFieldCount++;
+        }
+    }
+
+    if (nListFieldCount == 0)
+        return false;
+
+    /* No need for full scan if the limit is 1. We just to have to create */
+    /* one and a single one field */
+    if (nMaxSplitListSubFields != 1)
+    {
+        poSrcLayer->ResetReading();
+        OGRFeature* poSrcFeature;
+
+        GIntBig nFeatureCount = 0;
+        if (poSrcLayer->TestCapability(OLCFastFeatureCount))
+            nFeatureCount = poSrcLayer->GetFeatureCount();
+        GIntBig nFeatureIndex = 0;
+
+        /* Scan the whole layer to compute the maximum number of */
+        /* items for each field of list type */
+        while( (poSrcFeature = poSrcLayer->GetNextFeature()) != NULL )
+        {
+            for( int i=0; i<nListFieldCount; ++i )
+            {
+                int nCount = 0;
+                OGRField* psField =
+                        poSrcFeature->GetRawFieldRef(pasListFields[i].iSrcIndex);
+                switch(pasListFields[i].eType)
+                {
+                    case OFTIntegerList:
+                        nCount = psField->IntegerList.nCount;
+                        break;
+                    case OFTRealList:
+                        nCount = psField->RealList.nCount;
+                        break;
+                    case OFTStringList:
+                    {
+                        nCount = psField->StringList.nCount;
+                        char** paList = psField->StringList.paList;
+                        int j;
+                        for(j=0;j<nCount;j++)
+                        {
+                            int nWidth = static_cast<int>(strlen(paList[j]));
+                            if (nWidth > pasListFields[i].nWidth)
+                                pasListFields[i].nWidth = nWidth;
+                        }
+                        break;
+                    }
+                    default:
+                        CPLAssert(0);
+                        break;
+                }
+                if (nCount > pasListFields[i].nMaxOccurrences)
+                {
+                    if (nCount > nMaxSplitListSubFields)
+                        nCount = nMaxSplitListSubFields;
+                    pasListFields[i].nMaxOccurrences = nCount;
+                }
+            }
+            OGRFeature::DestroyFeature(poSrcFeature);
+
+            nFeatureIndex ++;
+            if (pfnProgress != NULL && nFeatureCount != 0)
+                pfnProgress(nFeatureIndex * 1.0 / nFeatureCount, "", pProgressArg);
+        }
+    }
+
+    /* Now let's build the target feature definition */
+
+    poFeatureDefn =
+            OGRFeatureDefn::CreateFeatureDefn( poSrcFieldDefn->GetName() );
+    poFeatureDefn->Reference();
+    poFeatureDefn->SetGeomType( wkbNone );
+
+    for( int i=0; i < poSrcFieldDefn->GetGeomFieldCount(); ++i )
+    {
+        poFeatureDefn->AddGeomFieldDefn(poSrcFieldDefn->GetGeomFieldDefn(i));
+    }
+
+    int iListField = 0;
+    for( int i=0;i<nSrcFields; ++i)
+    {
+        OGRFieldType eType = poSrcFieldDefn->GetFieldDefn(i)->GetType();
+        if (eType == OFTIntegerList ||
+            eType == OFTInteger64List ||
+            eType == OFTRealList ||
+            eType == OFTStringList)
+        {
+            int nMaxOccurrences = pasListFields[iListField].nMaxOccurrences;
+            int nWidth = pasListFields[iListField].nWidth;
+            iListField ++;
+            int j;
+            if (nMaxOccurrences == 1)
+            {
+                OGRFieldDefn oFieldDefn(poSrcFieldDefn->GetFieldDefn(i)->GetNameRef(),
+                                            (eType == OFTIntegerList) ? OFTInteger :
+                                            (eType == OFTInteger64List) ? OFTInteger64 :
+                                            (eType == OFTRealList) ?    OFTReal :
+                                                                        OFTString);
+                poFeatureDefn->AddFieldDefn(&oFieldDefn);
+            }
+            else
+            {
+                for(j=0;j<nMaxOccurrences;j++)
+                {
+                    CPLString osFieldName;
+                    osFieldName.Printf("%s%d",
+                        poSrcFieldDefn->GetFieldDefn(i)->GetNameRef(), j+1);
+                    OGRFieldDefn oFieldDefn(osFieldName.c_str(),
+                                            (eType == OFTIntegerList) ? OFTInteger :
+                                            (eType == OFTInteger64List) ? OFTInteger64 :
+                                            (eType == OFTRealList) ?    OFTReal :
+                                                                        OFTString);
+                    oFieldDefn.SetWidth(nWidth);
+                    poFeatureDefn->AddFieldDefn(&oFieldDefn);
+                }
+            }
+        }
+        else
+        {
+            poFeatureDefn->AddFieldDefn(poSrcFieldDefn->GetFieldDefn(i));
+        }
+    }
+
+    return true;
+}
+
+
+/************************************************************************/
+/*                       TranslateFeature()                             */
+/************************************************************************/
+
+OGRFeature *OGRSplitListFieldLayer::TranslateFeature(OGRFeature* poSrcFeature)
+{
+    if (poSrcFeature == NULL)
+        return NULL;
+    if (poFeatureDefn == NULL)
+        return poSrcFeature;
+
+    OGRFeature* poFeature = OGRFeature::CreateFeature(poFeatureDefn);
+    poFeature->SetFID(poSrcFeature->GetFID());
+    for(int i=0;i<poFeature->GetGeomFieldCount();i++)
+    {
+        poFeature->SetGeomFieldDirectly(i, poSrcFeature->StealGeometry(i));
+    }
+    poFeature->SetStyleString(poFeature->GetStyleString());
+
+    OGRFeatureDefn* poSrcFieldDefn = poSrcLayer->GetLayerDefn();
+    int nSrcFields = poSrcFeature->GetFieldCount();
+    int iDstField = 0;
+    int iListField = 0;
+
+    for( int iSrcField=0; iSrcField < nSrcFields; ++iSrcField)
+    {
+        const OGRFieldType eType = poSrcFieldDefn->GetFieldDefn(iSrcField)->GetType();
+        OGRField* psField = poSrcFeature->GetRawFieldRef(iSrcField);
+        switch(eType)
+        {
+            case OFTIntegerList:
+            {
+                int nCount = psField->IntegerList.nCount;
+                if (nCount > nMaxSplitListSubFields)
+                    nCount = nMaxSplitListSubFields;
+                int* paList = psField->IntegerList.paList;
+                for( int j=0;j<nCount; ++j)
+                    poFeature->SetField(iDstField + j, paList[j]);
+                iDstField += pasListFields[iListField].nMaxOccurrences;
+                iListField++;
+                break;
+            }
+            case OFTInteger64List:
+            {
+                int nCount = psField->Integer64List.nCount;
+                if (nCount > nMaxSplitListSubFields)
+                    nCount = nMaxSplitListSubFields;
+                GIntBig* paList = psField->Integer64List.paList;
+                for( int j=0; j < nCount; ++j )
+                    poFeature->SetField(iDstField + j, paList[j]);
+                iDstField += pasListFields[iListField].nMaxOccurrences;
+                iListField++;
+                break;
+            }
+            case OFTRealList:
+            {
+                int nCount = psField->RealList.nCount;
+                if (nCount > nMaxSplitListSubFields)
+                    nCount = nMaxSplitListSubFields;
+                double* paList = psField->RealList.paList;
+                for( int j=0; j < nCount; ++j )
+                    poFeature->SetField(iDstField + j, paList[j]);
+                iDstField += pasListFields[iListField].nMaxOccurrences;
+                iListField++;
+                break;
+            }
+            case OFTStringList:
+            {
+                int nCount = psField->StringList.nCount;
+                if (nCount > nMaxSplitListSubFields)
+                    nCount = nMaxSplitListSubFields;
+                char** paList = psField->StringList.paList;
+                for( int j=0; j < nCount; ++j )
+                    poFeature->SetField(iDstField + j, paList[j]);
+                iDstField += pasListFields[iListField].nMaxOccurrences;
+                iListField++;
+                break;
+            }
+            default:
+                poFeature->SetField(iDstField, psField);
+                iDstField ++;
+                break;
+        }
+    }
+
+    OGRFeature::DestroyFeature(poSrcFeature);
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                       GetNextFeature()                               */
+/************************************************************************/
+
+OGRFeature *OGRSplitListFieldLayer::GetNextFeature()
+{
+    return TranslateFeature(poSrcLayer->GetNextFeature());
+}
+
+/************************************************************************/
+/*                           GetFeature()                               */
+/************************************************************************/
+
+OGRFeature *OGRSplitListFieldLayer::GetFeature(GIntBig nFID)
+{
+    return TranslateFeature(poSrcLayer->GetFeature(nFID));
+}
+
+/************************************************************************/
+/*                        GetLayerDefn()                                */
+/************************************************************************/
+
+OGRFeatureDefn* OGRSplitListFieldLayer::GetLayerDefn()
+{
+    if (poFeatureDefn == NULL)
+        return poSrcLayer->GetLayerDefn();
+    return poFeatureDefn;
+}
+
+/************************************************************************/
+/*                            GCPCoordTransformation()                  */
+/*                                                                      */
+/*      Apply GCP Transform to points                                   */
+/************************************************************************/
+
+class GCPCoordTransformation : public OGRCoordinateTransformation
+{
+public:
+
+    void               *hTransformArg;
+    bool                 bUseTPS;
+    OGRSpatialReference* poSRS;
+
+    GCPCoordTransformation( int nGCPCount,
+                            const GDAL_GCP *pasGCPList,
+                            int  nReqOrder,
+                            OGRSpatialReference* poSRSIn)
+    {
+        if( nReqOrder < 0 )
+        {
+            bUseTPS = true;
+            hTransformArg =
+                GDALCreateTPSTransformer( nGCPCount, pasGCPList, FALSE );
+        }
+        else
+        {
+            bUseTPS = false;
+            hTransformArg =
+                GDALCreateGCPTransformer( nGCPCount, pasGCPList, nReqOrder, FALSE );
+        }
+        poSRS = poSRSIn;
+        if( poSRS)
+            poSRS->Reference();
+    }
+
+    bool IsValid() const { return hTransformArg != NULL; }
+
+    virtual ~GCPCoordTransformation()
+    {
+        if( hTransformArg != NULL )
+        {
+            if( bUseTPS )
+                GDALDestroyTPSTransformer(hTransformArg);
+            else
+                GDALDestroyGCPTransformer(hTransformArg);
+        }
+        if( poSRS)
+            poSRS->Dereference();
+    }
+
+    virtual OGRSpatialReference *GetSourceCS() { return poSRS; }
+    virtual OGRSpatialReference *GetTargetCS() { return poSRS; }
+
+    virtual int Transform( int nCount,
+                           double *x, double *y, double *z = NULL )
+    {
+        int *pabSuccess = (int *) CPLMalloc(sizeof(int) * nCount );
+
+        bool bOverallSuccess = CPL_TO_BOOL(TransformEx( nCount, x, y, z, pabSuccess ));
+
+        for( int i = 0; i < nCount; ++i )
+        {
+            if( !pabSuccess[i] )
+            {
+                bOverallSuccess = false;
+                break;
+            }
+        }
+
+        CPLFree( pabSuccess );
+
+        return bOverallSuccess;
+    }
+
+    virtual int TransformEx( int nCount,
+                             double *x, double *y, double *z = NULL,
+                             int *pabSuccess = NULL )
+    {
+        if( bUseTPS )
+            return GDALTPSTransform( hTransformArg, FALSE,
+                                 nCount, x, y, z, pabSuccess );
+        else
+            return GDALGCPTransform( hTransformArg, FALSE,
+                                 nCount, x, y, z, pabSuccess );
+    }
+};
+
+/************************************************************************/
+/*                            CompositeCT                               */
+/************************************************************************/
+
+class CompositeCT : public OGRCoordinateTransformation
+{
+public:
+
+    OGRCoordinateTransformation* poCT1;
+    OGRCoordinateTransformation* poCT2;
+
+    CompositeCT( OGRCoordinateTransformation* poCT1In, /* will not be deleted */
+                 OGRCoordinateTransformation* poCT2In  /* deleted with OGRCoordinateTransformation::DestroyCT() */ )
+    {
+        poCT1 = poCT1In;
+        poCT2 = poCT2In;
+    }
+
+    virtual ~CompositeCT()
+    {
+        OGRCoordinateTransformation::DestroyCT(poCT2);
+    }
+
+    virtual OGRSpatialReference *GetSourceCS()
+    {
+        return poCT1 ? poCT1->GetSourceCS() :
+               poCT2 ? poCT2->GetSourceCS() : NULL;
+    }
+
+    virtual OGRSpatialReference *GetTargetCS()
+    {
+        return poCT2 ? poCT2->GetTargetCS() :
+               poCT1 ? poCT1->GetTargetCS() : NULL;
+    }
+
+    virtual int Transform( int nCount,
+                           double *x, double *y, double *z = NULL )
+    {
+        int nResult = TRUE;
+        if( poCT1 )
+            nResult = poCT1->Transform(nCount, x, y, z);
+        if( nResult && poCT2 )
+            nResult = poCT2->Transform(nCount, x, y, z);
+        return nResult;
+    }
+
+    virtual int TransformEx( int nCount,
+                             double *x, double *y, double *z = NULL,
+                             int *pabSuccess = NULL )
+    {
+        int nResult = TRUE;
+        if( poCT1 )
+            nResult = poCT1->TransformEx(nCount, x, y, z, pabSuccess);
+        if( nResult && poCT2 )
+            nResult = poCT2->TransformEx(nCount, x, y, z, pabSuccess);
+        return nResult;
+    }
+};
+
+/************************************************************************/
+/*                        ApplySpatialFilter()                          */
+/************************************************************************/
+
+static
+void ApplySpatialFilter(OGRLayer* poLayer, OGRGeometry* poSpatialFilter,
+                        OGRSpatialReference* poSpatSRS,
+                        const char* pszGeomField,
+                        OGRSpatialReference* poSourceSRS)
+{
+    if( poSpatialFilter != NULL )
+    {
+        OGRGeometry* poSpatialFilterReprojected = NULL;
+        if( poSpatSRS )
+        {
+            poSpatialFilterReprojected = poSpatialFilter->clone();
+            poSpatialFilterReprojected->assignSpatialReference(poSpatSRS);
+            OGRSpatialReference* poSpatialFilterTargetSRS  = poSourceSRS ? poSourceSRS : poLayer->GetSpatialRef();
+            if( poSpatialFilterTargetSRS )
+                poSpatialFilterReprojected->transformTo(poSpatialFilterTargetSRS);
+            else
+                CPLError(CE_Warning, CPLE_AppDefined, "cannot determine layer SRS for %s.", poLayer->GetDescription());
+        }
+
+        if( pszGeomField != NULL )
+        {
+            int iGeomField = poLayer->GetLayerDefn()->GetGeomFieldIndex(pszGeomField);
+            if( iGeomField >= 0 )
+                poLayer->SetSpatialFilter( iGeomField,
+                    poSpatialFilterReprojected ? poSpatialFilterReprojected : poSpatialFilter );
+            else
+                CPLError( CE_Warning, CPLE_AppDefined,"Cannot find geometry field %s.",
+                    pszGeomField);
+        }
+        else
+            poLayer->SetSpatialFilter( poSpatialFilterReprojected ? poSpatialFilterReprojected : poSpatialFilter );
+
+        delete poSpatialFilterReprojected;
+    }
+}
+
+/************************************************************************/
+/*                            GetFieldType()                            */
+/************************************************************************/
+
+static int GetFieldType(const char* pszArg, int* pnSubFieldType)
+{
+    *pnSubFieldType = OFSTNone;
+    int nLengthBeforeParenthesis = static_cast<int>(strlen(pszArg));
+    const char* pszOpenParenthesis = strchr(pszArg, '(');
+    if( pszOpenParenthesis )
+        nLengthBeforeParenthesis = static_cast<int>(pszOpenParenthesis - pszArg);
+    for( int iType = 0; iType <= (int) OFTMaxType; iType++ )
+    {
+         const char* pszFieldTypeName = OGRFieldDefn::GetFieldTypeName(
+                                                       (OGRFieldType)iType);
+         if( EQUALN(pszArg,pszFieldTypeName,nLengthBeforeParenthesis) &&
+             pszFieldTypeName[nLengthBeforeParenthesis] == '\0' )
+         {
+             if( pszOpenParenthesis != NULL )
+             {
+                 *pnSubFieldType = -1;
+                 CPLString osArgSubType = pszOpenParenthesis + 1;
+                 if( osArgSubType.size() && osArgSubType[osArgSubType.size()-1] == ')' )
+                     osArgSubType.resize(osArgSubType.size()-1);
+                 for( int iSubType = 0; iSubType <= (int) OFSTMaxSubType; iSubType++ )
+                 {
+                     const char* pszFieldSubTypeName = OGRFieldDefn::GetFieldSubTypeName(
+                                                       (OGRFieldSubType)iSubType);
+                     if( EQUAL( pszFieldSubTypeName, osArgSubType ) )
+                     {
+                         *pnSubFieldType = iSubType;
+                         break;
+                     }
+                 }
+             }
+             return iType;
+         }
+     }
+     return -1;
+}
+
+/************************************************************************/
+/*                            IsNumber()                               */
+/************************************************************************/
+
+static bool IsNumber(const char* pszStr)
+{
+    if (*pszStr == '-' || *pszStr == '+')
+        pszStr ++;
+    if (*pszStr == '.')
+        pszStr ++;
+    return (*pszStr >= '0' && *pszStr <= '9');
+}
+
+/************************************************************************/
+/*                           IsFieldType()                              */
+/************************************************************************/
+
+static bool IsFieldType(const char* pszArg)
+{
+    int iSubType;
+    return GetFieldType(pszArg, &iSubType) >= 0 && iSubType >= 0;
+}
+
+/************************************************************************/
+/*                      GDALVectorTranslateOptionsClone()               */
+/************************************************************************/
+
+static
+GDALVectorTranslateOptions* GDALVectorTranslateOptionsClone(const GDALVectorTranslateOptions *psOptionsIn)
+{
+    GDALVectorTranslateOptions* psOptions = (GDALVectorTranslateOptions*) CPLMalloc(sizeof(GDALVectorTranslateOptions));
+    memcpy(psOptions, psOptionsIn, sizeof(GDALVectorTranslateOptions));
+
+    psOptions->pszFormat = CPLStrdup(psOptionsIn->pszFormat);
+    if( psOptionsIn->pszOutputSRSDef ) psOptions->pszOutputSRSDef = CPLStrdup(psOptionsIn->pszOutputSRSDef);
+    if( psOptionsIn->pszSourceSRSDef ) psOptions->pszSourceSRSDef = CPLStrdup(psOptionsIn->pszSourceSRSDef);
+    if( psOptionsIn->pszNewLayerName ) psOptions->pszNewLayerName = CPLStrdup(psOptionsIn->pszNewLayerName);
+    if( psOptionsIn->pszWHERE ) psOptions->pszWHERE = CPLStrdup(psOptionsIn->pszWHERE);
+    if( psOptionsIn->pszGeomField ) psOptions->pszGeomField = CPLStrdup(psOptionsIn->pszGeomField);
+    if( psOptionsIn->pszSQLStatement ) psOptions->pszSQLStatement = CPLStrdup(psOptionsIn->pszSQLStatement);
+    if( psOptionsIn->pszDialect ) psOptions->pszDialect = CPLStrdup(psOptionsIn->pszDialect);
+    if( psOptionsIn->pszClipSrcDS ) psOptions->pszClipSrcDS = CPLStrdup(psOptionsIn->pszClipSrcDS);
+    if( psOptionsIn->pszClipSrcSQL ) psOptions->pszClipSrcSQL = CPLStrdup(psOptionsIn->pszClipSrcSQL);
+    if( psOptionsIn->pszClipSrcLayer ) psOptions->pszClipSrcLayer = CPLStrdup(psOptionsIn->pszClipSrcLayer);
+    if( psOptionsIn->pszClipSrcWhere ) psOptions->pszClipSrcWhere = CPLStrdup(psOptionsIn->pszClipSrcWhere);
+    if( psOptionsIn->pszClipDstDS ) psOptions->pszClipDstDS = CPLStrdup(psOptionsIn->pszClipDstDS);
+    if( psOptionsIn->pszClipDstSQL ) psOptions->pszClipDstSQL = CPLStrdup(psOptionsIn->pszClipDstSQL);
+    if( psOptionsIn->pszClipDstLayer ) psOptions->pszClipDstLayer = CPLStrdup(psOptionsIn->pszClipDstLayer);
+    if( psOptionsIn->pszClipDstWhere ) psOptions->pszClipDstWhere = CPLStrdup(psOptionsIn->pszClipDstWhere);
+    if( psOptionsIn->pszZField ) psOptions->pszZField = CPLStrdup(psOptionsIn->pszZField);
+    if( psOptionsIn->pszSpatSRSDef ) psOptions->pszSpatSRSDef = CPLStrdup(psOptionsIn->pszSpatSRSDef);
+    psOptions->papszSelFields = CSLDuplicate(psOptionsIn->papszSelFields);
+    psOptions->papszFieldMap = CSLDuplicate(psOptionsIn->papszFieldMap);
+    psOptions->papszMapFieldType = CSLDuplicate(psOptionsIn->papszMapFieldType);
+    psOptions->papszLayers = CSLDuplicate(psOptionsIn->papszLayers);
+    psOptions->papszDSCO = CSLDuplicate(psOptionsIn->papszDSCO);
+    psOptions->papszLCO = CSLDuplicate(psOptionsIn->papszLCO);
+    psOptions->papszDestOpenOptions = CSLDuplicate(psOptionsIn->papszDestOpenOptions);
+    psOptions->papszFieldTypesToString = CSLDuplicate(psOptionsIn->papszFieldTypesToString);
+    psOptions->papszMetadataOptions = CSLDuplicate(psOptionsIn->papszMetadataOptions);
+    if( psOptionsIn->nGCPCount )
+        psOptions->pasGCPs = GDALDuplicateGCPs( psOptionsIn->nGCPCount, psOptionsIn->pasGCPs );
+    psOptions->hClipSrc = ( psOptionsIn->hClipSrc != NULL ) ? OGR_G_Clone(psOptionsIn->hClipSrc) : NULL;
+    psOptions->hClipDst = ( psOptionsIn->hClipDst != NULL ) ? OGR_G_Clone(psOptionsIn->hClipDst) : NULL;
+    psOptions->hSpatialFilter = ( psOptionsIn->hSpatialFilter != NULL ) ? OGR_G_Clone(psOptionsIn->hSpatialFilter) : NULL;
+
+    return psOptions;
+}
+
+/************************************************************************/
+/*                           GDALVectorTranslate()                      */
+/************************************************************************/
+/**
+ * Converts vector data between file formats.
+ *
+ * This is the equivalent of the <a href="ogr2ogr.html">ogr2ogr</a> utility.
+ *
+ * GDALVectorTranslateOptions* must be allocated and freed with GDALVectorTranslateOptionsNew()
+ * and GDALVectorTranslateOptionsFree() respectively.
+ * pszDest and hDstDS cannot be used at the same time.
+ *
+ * @param pszDest the destination dataset path or NULL.
+ * @param hDstDS the destination dataset or NULL.
+ * @param nSrcCount the number of input datasets (only 1 supported currently)
+ * @param pahSrcDS the list of input datasets.
+ * @param psOptionsIn the options struct returned by GDALVectorTranslateOptionsNew() or NULL.
+ * @param pbUsageError the pointer to int variable to determine any usage error has occurred
+ * @return the output dataset (new dataset that must be closed using GDALClose(), or hDstDS is not NULL) or NULL in case of error.
+ *
+ * @since GDAL 2.1
+ */
+
+GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int nSrcCount,
+                                  GDALDatasetH *pahSrcDS,
+                                  const GDALVectorTranslateOptions *psOptionsIn, int *pbUsageError )
+
+{
+    OGRSpatialReference oOutputSRS;
+    OGRSpatialReference oSourceSRS;
+    OGRSpatialReference oSpatSRS;
+    OGRSpatialReference *poOutputSRS = NULL;
+    OGRSpatialReference *poSourceSRS = NULL;
+    OGRSpatialReference* poSpatSRS = NULL;
+    bool bAppend = false;
+    bool bUpdate = false;
+    bool bOverwrite = false;
+    CPLString osDateLineOffset;
+    int nRetCode = 0;
+
+    if( pszDest == NULL && hDstDS == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "pszDest == NULL && hDstDS == NULL");
+
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        return NULL;
+    }
+    if( nSrcCount != 1 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "nSrcCount != 1");
+
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        return NULL;
+    }
+
+    GDALDatasetH hSrcDS = pahSrcDS[0];
+    if( hSrcDS == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "hSrcDS == NULL");
+
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        return NULL;
+    }
+
+    GDALVectorTranslateOptions* psOptions =
+        (psOptionsIn) ? GDALVectorTranslateOptionsClone(psOptionsIn) :
+                        GDALVectorTranslateOptionsNew(NULL, NULL);
+
+    if( psOptions->eAccessMode == ACCESS_UPDATE )
+    {
+        bUpdate = true;
+    }
+    else if ( psOptions->eAccessMode == ACCESS_APPEND )
+    {
+        bAppend = true;
+        bUpdate = true;
+    }
+    else if ( psOptions->eAccessMode == ACCESS_OVERWRITE )
+    {
+        bOverwrite = true;
+        bUpdate = true;
+    }
+
+    osDateLineOffset = CPLOPrintf("%g", psOptions->dfDateLineOffset);
+
+    if( psOptions->bPreserveFID && psOptions->bExplodeCollections )
+    {
+        CPLError( CE_Failure, CPLE_IllegalArg, "cannot use -preserve_fid and -explodecollections at the same time.");
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        GDALVectorTranslateOptionsFree(psOptions);
+        return NULL;
+    }
+
+    if (psOptions->papszFieldMap && !bAppend)
+    {
+        CPLError( CE_Failure, CPLE_IllegalArg, "if -fieldmap is specified, -append must also be specified");
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        GDALVectorTranslateOptionsFree(psOptions);
+        return NULL;
+    }
+
+    if (psOptions->papszFieldMap && psOptions->bAddMissingFields)
+    {
+        CPLError( CE_Failure, CPLE_IllegalArg, "if -addfields is specified, -fieldmap cannot be used.");
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        GDALVectorTranslateOptionsFree(psOptions);
+        return NULL;
+    }
+
+    if( psOptions->papszFieldTypesToString && psOptions->papszMapFieldType )
+    {
+        CPLError( CE_Failure, CPLE_IllegalArg, "-fieldTypeToString and -mapFieldType are exclusive.");
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        GDALVectorTranslateOptionsFree(psOptions);
+        return NULL;
+    }
+
+    if( psOptions->pszSourceSRSDef != NULL && psOptions->pszOutputSRSDef == NULL && psOptions->pszSpatSRSDef == NULL )
+    {
+        CPLError( CE_Failure, CPLE_IllegalArg, "if -s_srs is specified, -t_srs and/or -spat_srs must also be specified.");
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        GDALVectorTranslateOptionsFree(psOptions);
+        return NULL;
+    }
+
+    if( psOptions->bClipSrc && psOptions->pszClipSrcDS != NULL)
+    {
+        psOptions->hClipSrc = (OGRGeometryH) LoadGeometry(psOptions->pszClipSrcDS, psOptions->pszClipSrcSQL, psOptions->pszClipSrcLayer, psOptions->pszClipSrcWhere);
+        if (psOptions->hClipSrc == NULL)
+        {
+            CPLError( CE_Failure,CPLE_IllegalArg, "cannot load source clip geometry");
+            GDALVectorTranslateOptionsFree(psOptions);
+            return NULL;
+        }
+    }
+    else if( psOptions->bClipSrc && psOptions->hClipSrc == NULL )
+    {
+        if (psOptions->hSpatialFilter)
+            psOptions->hClipSrc = (OGRGeometryH)((OGRGeometry *)(psOptions->hSpatialFilter))->clone();
+        if (psOptions->hClipSrc == NULL)
+        {
+            CPLError( CE_Failure, CPLE_IllegalArg, "-clipsrc must be used with -spat option or a\n"
+                             "bounding box, WKT string or datasource must be specified");
+            if(pbUsageError)
+                *pbUsageError = TRUE;
+            GDALVectorTranslateOptionsFree(psOptions);
+            return NULL;
+        }
+    }
+
+    if( psOptions->pszClipDstDS != NULL)
+    {
+        psOptions->hClipDst = (OGRGeometryH) LoadGeometry(psOptions->pszClipDstDS, psOptions->pszClipDstSQL, psOptions->pszClipDstLayer, psOptions->pszClipDstWhere);
+        if (psOptions->hClipDst == NULL)
+        {
+            CPLError( CE_Failure, CPLE_IllegalArg, "cannot load dest clip geometry");
+            GDALVectorTranslateOptionsFree(psOptions);
+            return NULL;
+        }
+    }
+
+    GDALDataset *poDS = (GDALDataset *) hSrcDS;
+    GDALDataset *poODS = NULL;
+    GDALDriver *poDriver = NULL;
+    CPLString osDestFilename;
+
+    if(hDstDS)
+    {
+        poODS = (GDALDataset *) hDstDS;
+        osDestFilename = poODS->GetDescription();
+    }
+    else
+        osDestFilename = pszDest;
+
+    /* Various tests to avoid overwriting the source layer(s) */
+    /* or to avoid appending a layer to itself */
+    if( bUpdate && strcmp(osDestFilename, poDS->GetDescription()) == 0 &&
+        (bOverwrite || bAppend) )
+    {
+        bool bError = false;
+        if (psOptions->pszNewLayerName == NULL)
+            bError = true;
+        else if (CSLCount(psOptions->papszLayers) == 1)
+            bError = strcmp(psOptions->pszNewLayerName, psOptions->papszLayers[0]) == 0;
+        else if (psOptions->pszSQLStatement == NULL)
+            bError = true;
+        if (bError)
+        {
+            CPLError( CE_Failure, CPLE_IllegalArg,
+                        "-nln name must be specified combined with "
+                        "a single source layer name,\nor a -sql statement, and "
+                        "name must be different from an existing layer.");
+            GDALVectorTranslateOptionsFree(psOptions);
+            return NULL;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Try opening the output datasource as an existing, writable      */
+/* -------------------------------------------------------------------- */
+
+    if( bUpdate && poODS == NULL )
+    {
+        poODS = (GDALDataset*) GDALOpenEx( osDestFilename,
+                GDAL_OF_UPDATE | GDAL_OF_VECTOR, NULL, psOptions->papszDestOpenOptions, NULL );
+
+        if( poODS == NULL )
+        {
+            if (bOverwrite || bAppend)
+            {
+                poODS = (GDALDataset*) GDALOpenEx( osDestFilename,
+                            GDAL_OF_VECTOR, NULL, psOptions->papszDestOpenOptions, NULL );
+                if (poODS == NULL)
+                {
+                    /* OK the datasource doesn't exist at all */
+                    bUpdate = false;
+                }
+                else
+                {
+                    if( poODS != NULL )
+                        poDriver = poODS->GetDriver();
+                    GDALClose( (GDALDatasetH) poODS );
+                    poODS = NULL;
+                }
+            }
+
+            if (bUpdate)
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                        "Unable to open existing output datasource `%s'.",
+                        osDestFilename.c_str() );
+                GDALVectorTranslateOptionsFree(psOptions);
+                return NULL;
+            }
+        }
+        else if( CSLCount(psOptions->papszDSCO) > 0 )
+        {
+            CPLError( CE_Warning, CPLE_AppDefined, "Datasource creation options ignored since an existing datasource\n"
+                    "         being updated." );
+        }
+    }
+
+    if( poODS )
+        poDriver = poODS->GetDriver();
+
+/* -------------------------------------------------------------------- */
+/*      Find the output driver.                                         */
+/* -------------------------------------------------------------------- */
+    if( !bUpdate )
+    {
+        OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
+
+        poDriver = poR->GetDriverByName(psOptions->pszFormat);
+        if( poDriver == NULL )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "Unable to find driver `%s'.", psOptions->pszFormat );
+            fprintf( stderr,  "The following drivers are available:\n" );
+
+            for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
+            {
+                fprintf( stderr,  "  -> `%s'\n", poR->GetDriver(iDriver)->GetDescription() );
+            }
+            GDALVectorTranslateOptionsFree(psOptions);
+            return NULL;
+        }
+
+        if( !CPLTestBool( CSLFetchNameValueDef(poDriver->GetMetadata(), GDAL_DCAP_CREATE, "FALSE") ) )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "%s driver does not support data source creation.",
+                    psOptions->pszFormat );
+            GDALVectorTranslateOptionsFree(psOptions);
+            return NULL;
+        }
+
+        if( psOptions->papszDestOpenOptions != NULL )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined, "-doo ignored when creating the output datasource.");
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Special case to improve user experience when translating        */
+/*      a datasource with multiple layers into a shapefile. If the      */
+/*      user gives a target datasource with .shp and it does not exist, */
+/*      the shapefile driver will try to create a file, but this is not */
+/*      appropriate because here we have several layers, so create      */
+/*      a directory instead.                                            */
+/* -------------------------------------------------------------------- */
+        VSIStatBufL  sStat;
+        if (EQUAL(poDriver->GetDescription(), "ESRI Shapefile") &&
+            psOptions->pszSQLStatement == NULL &&
+            (CSLCount(psOptions->papszLayers) > 1 ||
+             (CSLCount(psOptions->papszLayers) == 0 && poDS->GetLayerCount() > 1)) &&
+            psOptions->pszNewLayerName == NULL &&
+            EQUAL(CPLGetExtension(osDestFilename), "SHP") &&
+            VSIStatL(osDestFilename, &sStat) != 0)
+        {
+            if (VSIMkdir(osDestFilename, 0755) != 0)
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                      "Failed to create directory %s\n"
+                      "for shapefile datastore.",
+                      osDestFilename.c_str() );
+                GDALVectorTranslateOptionsFree(psOptions);
+                return NULL;
+            }
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Create the output data source.                                  */
+/* -------------------------------------------------------------------- */
+        poODS = poDriver->Create( osDestFilename, 0, 0, 0, GDT_Unknown, psOptions->papszDSCO );
+        if( poODS == NULL )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "%s driver failed to create %s",
+                    psOptions->pszFormat, osDestFilename.c_str() );
+            GDALVectorTranslateOptionsFree(psOptions);
+            return NULL;
+        }
+
+        if( psOptions->bCopyMD )
+        {
+            char** papszDomains = poDS->GetMetadataDomainList();
+            for(char** papszIter = papszDomains; papszIter && *papszIter; ++papszIter )
+            {
+                char** papszMD = poDS->GetMetadata(*papszIter);
+                if( papszMD )
+                    poODS->SetMetadata(papszMD, *papszIter);
+            }
+            CSLDestroy(papszDomains);
+        }
+        for(char** papszIter = psOptions->papszMetadataOptions; papszIter && *papszIter; ++papszIter )
+        {
+            char    *pszKey = NULL;
+            const char *pszValue = CPLParseNameValue( *papszIter, &pszKey );
+            if( pszKey )
+            {
+                poODS->SetMetadataItem(pszKey,pszValue);
+                CPLFree( pszKey );
+            }
+        }
+    }
+
+    if( psOptions->nLayerTransaction < 0 )
+        psOptions->nLayerTransaction = !poODS->TestCapability(ODsCTransactions);
+
+/* -------------------------------------------------------------------- */
+/*      Parse the output SRS definition if possible.                    */
+/* -------------------------------------------------------------------- */
+    if( psOptions->pszOutputSRSDef != NULL )
+    {
+        if( oOutputSRS.SetFromUserInput( psOptions->pszOutputSRSDef ) != OGRERR_NONE )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "Failed to process SRS definition: %s",
+                    psOptions->pszOutputSRSDef );
+            GDALVectorTranslateOptionsFree(psOptions);
+            if( hDstDS == NULL ) GDALClose( poODS );
+            return NULL;
+        }
+        poOutputSRS = &oOutputSRS;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Parse the source SRS definition if possible.                    */
+/* -------------------------------------------------------------------- */
+    if( psOptions->pszSourceSRSDef != NULL )
+    {
+        if( oSourceSRS.SetFromUserInput( psOptions->pszSourceSRSDef ) != OGRERR_NONE )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "Failed to process SRS definition: %s",
+                    psOptions->pszSourceSRSDef );
+            GDALVectorTranslateOptionsFree(psOptions);
+            if( hDstDS == NULL ) GDALClose( poODS );
+            return NULL;
+        }
+        poSourceSRS = &oSourceSRS;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Parse spatial filter SRS if needed.                             */
+/* -------------------------------------------------------------------- */
+    if( psOptions->hSpatialFilter != NULL && psOptions->pszSpatSRSDef != NULL )
+    {
+        if( psOptions->pszSQLStatement )
+        {
+            CPLError( CE_Failure, CPLE_IllegalArg, "-spat_srs not compatible with -sql.");
+            GDALVectorTranslateOptionsFree(psOptions);
+            if( hDstDS == NULL ) GDALClose( poODS );
+            return NULL;
+        }
+        OGREnvelope sEnvelope;
+        ((OGRGeometry*)psOptions->hSpatialFilter)->getEnvelope(&sEnvelope);
+        if( oSpatSRS.SetFromUserInput( psOptions->pszSpatSRSDef ) != OGRERR_NONE )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "Failed to process SRS definition: %s",
+                    psOptions->pszSpatSRSDef );
+            GDALVectorTranslateOptionsFree(psOptions);
+            if( hDstDS == NULL ) GDALClose( poODS );
+            return NULL;
+        }
+        poSpatSRS = &oSpatSRS;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create a transformation object from the source to               */
+/*      destination coordinate system.                                  */
+/* -------------------------------------------------------------------- */
+    GCPCoordTransformation *poGCPCoordTrans = NULL;
+    if( psOptions->nGCPCount > 0 )
+    {
+        poGCPCoordTrans = new GCPCoordTransformation( psOptions->nGCPCount, psOptions->pasGCPs,
+                                                      psOptions->nTransformOrder,
+                                                      poSourceSRS ? poSourceSRS : poOutputSRS );
+        if( !(poGCPCoordTrans->IsValid()) )
+        {
+            delete poGCPCoordTrans;
+            poGCPCoordTrans = NULL;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      For OSM file.                                                   */
+/* -------------------------------------------------------------------- */
+    int         bSrcIsOSM = (strcmp(poDS->GetDriverName(), "OSM") == 0);
+    vsi_l_offset nSrcFileSize = 0;
+    if( bSrcIsOSM && strcmp(poDS->GetDescription(), "/vsistdin/") != 0)
+    {
+        VSIStatBufL sStat;
+        if( VSIStatL(poDS->GetDescription(), &sStat) == 0 )
+            nSrcFileSize = sStat.st_size;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create layer setup and transformer objects.                     */
+/* -------------------------------------------------------------------- */
+    SetupTargetLayer oSetup;
+    oSetup.m_poDstDS = poODS;
+    oSetup.m_papszLCO = psOptions->papszLCO;
+    oSetup.m_poOutputSRS = poOutputSRS;
+    oSetup.m_bNullifyOutputSRS = psOptions->bNullifyOutputSRS;
+    oSetup.m_papszSelFields = psOptions->papszSelFields;
+    oSetup.m_bAppend = bAppend;
+    oSetup.m_bAddMissingFields = psOptions->bAddMissingFields;
+    oSetup.m_eGType = psOptions->eGType;
+    oSetup.m_eGeomTypeConversion = psOptions->eGeomTypeConversion;
+    oSetup.m_nCoordDim = psOptions->nCoordDim;
+    oSetup.m_bOverwrite = bOverwrite;
+    oSetup.m_papszFieldTypesToString = psOptions->papszFieldTypesToString;
+    oSetup.m_papszMapFieldType = psOptions->papszMapFieldType;
+    oSetup.m_bUnsetFieldWidth = psOptions->bUnsetFieldWidth;
+    oSetup.m_bExplodeCollections = psOptions->bExplodeCollections;
+    oSetup.m_pszZField = psOptions->pszZField;
+    oSetup.m_papszFieldMap = psOptions->papszFieldMap;
+    oSetup.m_pszWHERE = psOptions->pszWHERE;
+    oSetup.m_bExactFieldNameMatch = psOptions->bExactFieldNameMatch;
+    oSetup.m_bQuiet = psOptions->bQuiet;
+    oSetup.m_bForceNullable = psOptions->bForceNullable;
+    oSetup.m_bUnsetDefault = psOptions->bUnsetDefault;
+    oSetup.m_bUnsetFid = psOptions->bUnsetFid;
+    oSetup.m_bPreserveFID = psOptions->bPreserveFID;
+    oSetup.m_bCopyMD = psOptions->bCopyMD;
+    oSetup.m_bNativeData = psOptions->bNativeData;
+
+    LayerTranslator oTranslator;
+    oTranslator.m_poSrcDS = poDS;
+    oTranslator.m_poODS = poODS;
+    oTranslator.m_bTransform = psOptions->bTransform;
+    oTranslator.m_bWrapDateline = psOptions->bWrapDateline;
+    oTranslator.m_osDateLineOffset = osDateLineOffset;
+    oTranslator.m_poOutputSRS = poOutputSRS;
+    oTranslator.m_bNullifyOutputSRS = psOptions->bNullifyOutputSRS;
+    oTranslator.m_poUserSourceSRS = poSourceSRS;
+    oTranslator.m_poGCPCoordTrans = poGCPCoordTrans;
+    oTranslator.m_eGType = psOptions->eGType;
+    oTranslator.m_eGeomTypeConversion = psOptions->eGeomTypeConversion;
+    oTranslator.m_nCoordDim = psOptions->nCoordDim;
+    oTranslator.m_eGeomOp = psOptions->eGeomOp;
+    oTranslator.m_dfGeomOpParam = psOptions->dfGeomOpParam;
+    oTranslator.m_poClipSrc = (OGRGeometry *)psOptions->hClipSrc;
+    oTranslator.m_poClipDst = (OGRGeometry *)psOptions->hClipDst;
+    oTranslator.m_bExplodeCollections = psOptions->bExplodeCollections;
+    oTranslator.m_nSrcFileSize = nSrcFileSize;
+    oTranslator.m_bNativeData = psOptions->bNativeData;
+
+    if( psOptions->nGroupTransactions )
+    {
+        if( !psOptions->nLayerTransaction )
+            poODS->StartTransaction(psOptions->bForceTransaction);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Special case for -sql clause.  No source layers required.       */
+/* -------------------------------------------------------------------- */
+    if( psOptions->pszSQLStatement != NULL )
+    {
+        /* Special case: if output=input, then we must likely destroy the */
+        /* old table before to avoid transaction issues. */
+        if( poDS == poODS && psOptions->pszNewLayerName != NULL && bOverwrite )
+            GetLayerAndOverwriteIfNecessary(poODS, psOptions->pszNewLayerName, bOverwrite, NULL);
+
+        if( psOptions->pszWHERE != NULL )
+            CPLError( CE_Warning, CPLE_AppDefined, "-where clause ignored in combination with -sql." );
+        if( CSLCount(psOptions->papszLayers) > 0 )
+            CPLError( CE_Warning, CPLE_AppDefined, "layer names ignored in combination with -sql." );
+
+        OGRLayer *poResultSet
+            = poDS->ExecuteSQL( psOptions->pszSQLStatement,
+                                (psOptions->pszGeomField == NULL) ? (OGRGeometry*)psOptions->hSpatialFilter : NULL,
+                                psOptions->pszDialect );
+
+        if( poResultSet != NULL )
+        {
+            if( psOptions->hSpatialFilter != NULL && psOptions->pszGeomField != NULL )
+            {
+                int iGeomField = poResultSet->GetLayerDefn()->GetGeomFieldIndex(psOptions->pszGeomField);
+                if( iGeomField >= 0 )
+                    poResultSet->SetSpatialFilter( iGeomField, (OGRGeometry*)psOptions->hSpatialFilter );
+                else
+                    CPLError( CE_Warning, CPLE_AppDefined, "Cannot find geometry field %s.",
+                           psOptions->pszGeomField);
+            }
+
+            GIntBig nCountLayerFeatures = 0;
+            GDALProgressFunc pfnProgress = NULL;
+            void        *pProgressArg = NULL;
+            if (psOptions->bDisplayProgress)
+            {
+                if (bSrcIsOSM)
+                {
+                    pfnProgress = psOptions->pfnProgress;
+                    pProgressArg = psOptions->pProgressData;
+                }
+                else if (!poResultSet->TestCapability(OLCFastFeatureCount))
+                {
+                    CPLError( CE_Warning, CPLE_AppDefined, "Progress turned off as fast feature count is not available.");
+                    psOptions->bDisplayProgress = false;
+                }
+                else
+                {
+                    nCountLayerFeatures = poResultSet->GetFeatureCount();
+                    pfnProgress = psOptions->pfnProgress;
+                    pProgressArg = psOptions->pProgressData;
+                }
+            }
+
+            OGRLayer* poPassedLayer = poResultSet;
+            if (psOptions->bSplitListFields)
+            {
+                poPassedLayer = new OGRSplitListFieldLayer(poPassedLayer, psOptions->nMaxSplitListSubFields);
+                int nRet = ((OGRSplitListFieldLayer*)poPassedLayer)->BuildLayerDefn(NULL, NULL);
+                if (!nRet)
+                {
+                    delete poPassedLayer;
+                    poPassedLayer = poResultSet;
+                }
+            }
+
+/* -------------------------------------------------------------------- */
+/*      Special case to improve user experience when translating into   */
+/*      single file shapefile and source has only one layer, and that   */
+/*      the layer name isn't specified                                  */
+/* -------------------------------------------------------------------- */
+            VSIStatBufL  sStat;
+            if (EQUAL(poDriver->GetDescription(), "ESRI Shapefile") &&
+                psOptions->pszNewLayerName == NULL &&
+                VSIStatL(osDestFilename, &sStat) == 0 && VSI_ISREG(sStat.st_mode))
+            {
+                psOptions->pszNewLayerName = CPLStrdup(CPLGetBasename(osDestFilename));
+            }
+
+            TargetLayerInfo* psInfo = oSetup.Setup(poPassedLayer,
+                                                   psOptions->pszNewLayerName,
+                                                   psOptions);
+
+            poPassedLayer->ResetReading();
+
+            if( psInfo == NULL ||
+                !oTranslator.Translate( psInfo,
+                                        nCountLayerFeatures, NULL,
+                                        pfnProgress, pProgressArg, psOptions ))
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Terminating translation prematurely after failed\n"
+                          "translation from sql statement." );
+
+                nRetCode = 1;
+            }
+
+            FreeTargetLayerInfo(psInfo);
+
+            if (poPassedLayer != poResultSet)
+                delete poPassedLayer;
+
+            poDS->ReleaseResultSet( poResultSet );
+        }
+        else
+        {
+            if( CPLGetLastErrorNo() != 0 )
+                nRetCode = 1;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Special case for layer interleaving mode.                       */
+/* -------------------------------------------------------------------- */
+    else if( bSrcIsOSM &&
+                CPLTestBool(CPLGetConfigOption("OGR_INTERLEAVED_READING", "YES")) )
+    {
+        CPLSetConfigOption("OGR_INTERLEAVED_READING", "YES");
+
+        if (psOptions->bSplitListFields)
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "-splitlistfields not supported in this mode" );
+            GDALVectorTranslateOptionsFree(psOptions);
+            if( hDstDS == NULL ) GDALClose( poODS );
+            delete poGCPCoordTrans;
+            return NULL;
+        }
+
+        int nSrcLayerCount = poDS->GetLayerCount();
+        AssociatedLayers* pasAssocLayers =
+            (AssociatedLayers* ) CPLCalloc(nSrcLayerCount, sizeof(AssociatedLayers));
+
+/* -------------------------------------------------------------------- */
+/*      Special case to improve user experience when translating into   */
+/*      single file shapefile and source has only one layer, and that   */
+/*      the layer name isn't specified                                  */
+/* -------------------------------------------------------------------- */
+        VSIStatBufL  sStat;
+        if (EQUAL(poDriver->GetDescription(), "ESRI Shapefile") &&
+            (CSLCount(psOptions->papszLayers) == 1 || nSrcLayerCount == 1) && psOptions->pszNewLayerName == NULL &&
+            VSIStatL(osDestFilename, &sStat) == 0 && VSI_ISREG(sStat.st_mode))
+        {
+            psOptions->pszNewLayerName = CPLStrdup(CPLGetBasename(osDestFilename));
+        }
+
+        GDALProgressFunc pfnProgress = NULL;
+        void        *pProgressArg = NULL;
+        if ( psOptions->bDisplayProgress && bSrcIsOSM )
+        {
+            pfnProgress = psOptions->pfnProgress;
+            pProgressArg = psOptions->pProgressData;
+        }
+
+/* -------------------------------------------------------------------- */
+/*      If no target layer specified, use all source layers.            */
+/* -------------------------------------------------------------------- */
+        int iLayer;
+        if ( CSLCount(psOptions->papszLayers) == 0)
+        {
+            psOptions->papszLayers = (char**) CPLCalloc(sizeof(char*), nSrcLayerCount + 1);
+            for( iLayer = 0; iLayer < nSrcLayerCount; iLayer++ )
+            {
+                OGRLayer        *poLayer = poDS->GetLayer(iLayer);
+
+                if( poLayer == NULL )
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined, "Couldn't fetch advertised layer %d!",
+                            iLayer );
+                    GDALVectorTranslateOptionsFree(psOptions);
+                    if( hDstDS == NULL ) GDALClose( poODS );
+                    delete poGCPCoordTrans;
+                    return NULL;
+                }
+
+                psOptions->papszLayers[iLayer] = CPLStrdup(poLayer->GetName());
+            }
+        }
+        else
+        {
+            if ( bSrcIsOSM )
+            {
+                CPLString osInterestLayers = "SET interest_layers =";
+                for( iLayer = 0; psOptions->papszLayers[iLayer] != NULL; iLayer++ )
+                {
+                    if( iLayer != 0 ) osInterestLayers += ",";
+                    osInterestLayers += psOptions->papszLayers[iLayer];
+                }
+
+                poDS->ExecuteSQL(osInterestLayers.c_str(), NULL, NULL);
+            }
+        }
+
+/* -------------------------------------------------------------------- */
+/*      First pass to set filters and create target layers.             */
+/* -------------------------------------------------------------------- */
+        for( iLayer = 0; iLayer < nSrcLayerCount; iLayer++ )
+        {
+            OGRLayer        *poLayer = poDS->GetLayer(iLayer);
+            if( poLayer == NULL )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined, "Couldn't fetch advertised layer %d!",
+                        iLayer );
+                GDALVectorTranslateOptionsFree(psOptions);
+                if( hDstDS == NULL ) GDALClose( poODS );
+                delete poGCPCoordTrans;
+                return NULL;
+            }
+
+            pasAssocLayers[iLayer].poSrcLayer = poLayer;
+
+            if( CSLFindString(psOptions->papszLayers, poLayer->GetName()) >= 0 )
+            {
+                if( psOptions->pszWHERE != NULL )
+                {
+                    if( poLayer->SetAttributeFilter( psOptions->pszWHERE ) != OGRERR_NONE )
+                    {
+                        CPLError( CE_Failure, CPLE_AppDefined, "SetAttributeFilter(%s) on layer '%s' failed.",
+                                 psOptions->pszWHERE, poLayer->GetName() );
+                        if (!psOptions->bSkipFailures)
+                        {
+                            GDALVectorTranslateOptionsFree(psOptions);
+                            if( hDstDS == NULL ) GDALClose( poODS );
+                            delete poGCPCoordTrans;
+                            return NULL;
+                        }
+                    }
+                }
+
+                ApplySpatialFilter(poLayer, (OGRGeometry*)psOptions->hSpatialFilter, poSpatSRS, psOptions->pszGeomField, poSourceSRS );
+
+                TargetLayerInfo* psInfo = oSetup.Setup(poLayer,
+                                                       psOptions->pszNewLayerName,
+                                                       psOptions);
+
+                if( psInfo == NULL && !psOptions->bSkipFailures )
+                {
+                    GDALVectorTranslateOptionsFree(psOptions);
+                    if( hDstDS == NULL ) GDALClose( poODS );
+                    delete poGCPCoordTrans;
+                    return NULL;
+                }
+
+                pasAssocLayers[iLayer].psInfo = psInfo;
+            }
+            else
+            {
+                pasAssocLayers[iLayer].psInfo = NULL;
+            }
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Second pass to process features in a interleaved layer mode.    */
+/* -------------------------------------------------------------------- */
+        bool bHasLayersNonEmpty;
+        do
+        {
+            bHasLayersNonEmpty = false;
+
+            for( iLayer = 0; iLayer < nSrcLayerCount;  iLayer++ )
+            {
+                OGRLayer        *poLayer = pasAssocLayers[iLayer].poSrcLayer;
+                TargetLayerInfo *psInfo = pasAssocLayers[iLayer].psInfo;
+                GIntBig nReadFeatureCount = 0;
+
+                if( psInfo )
+                {
+                    if( !oTranslator.Translate( psInfo,
+                                                0, &nReadFeatureCount,
+                                                pfnProgress, pProgressArg, psOptions )
+                        && !psOptions->bSkipFailures )
+                    {
+                        CPLError( CE_Failure, CPLE_AppDefined,
+                                "Terminating translation prematurely after failed\n"
+                                "translation of layer %s (use -skipfailures to skip errors)",
+                                poLayer->GetName() );
+
+                        nRetCode = 1;
+                        break;
+                    }
+                }
+                else
+                {
+                    /* No matching target layer : just consumes the features */
+
+                    OGRFeature* poFeature;
+                    while( (poFeature = poLayer->GetNextFeature()) != NULL )
+                    {
+                        nReadFeatureCount ++;
+                        OGRFeature::DestroyFeature(poFeature);
+                    }
+                }
+
+                if( nReadFeatureCount != 0 )
+                    bHasLayersNonEmpty = true;
+            }
+        }
+        while( bHasLayersNonEmpty );
+
+        if (pfnProgress)
+        {
+            pfnProgress(1.0, "", pProgressArg);
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Cleanup.                                                        */
+/* -------------------------------------------------------------------- */
+        for( iLayer = 0; iLayer < nSrcLayerCount;  iLayer++ )
+        {
+            if( pasAssocLayers[iLayer].psInfo )
+                FreeTargetLayerInfo(pasAssocLayers[iLayer].psInfo);
+        }
+        CPLFree(pasAssocLayers);
+    }
+
+    else
+    {
+        int nLayerCount = 0;
+        OGRLayer** papoLayers = NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Process each data source layer.                                 */
+/* -------------------------------------------------------------------- */
+        if ( CSLCount(psOptions->papszLayers) == 0)
+        {
+            nLayerCount = poDS->GetLayerCount();
+            papoLayers = (OGRLayer**)CPLMalloc(sizeof(OGRLayer*) * nLayerCount);
+
+            for( int iLayer = 0;
+                 iLayer < nLayerCount;
+                 iLayer++ )
+            {
+                OGRLayer        *poLayer = poDS->GetLayer(iLayer);
+
+                if( poLayer == NULL )
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined, "Couldn't fetch advertised layer %d!",
+                            iLayer );
+                    GDALVectorTranslateOptionsFree(psOptions);
+                    if( hDstDS == NULL ) GDALClose( poODS );
+                    delete poGCPCoordTrans;
+                    return NULL;
+                }
+
+                papoLayers[iLayer] = poLayer;
+            }
+        }
+/* -------------------------------------------------------------------- */
+/*      Process specified data source layers.                           */
+/* -------------------------------------------------------------------- */
+        else
+        {
+            nLayerCount = CSLCount(psOptions->papszLayers);
+            papoLayers = (OGRLayer**)CPLMalloc(sizeof(OGRLayer*) * nLayerCount);
+
+            for( int iLayer = 0;
+                psOptions->papszLayers[iLayer] != NULL;
+                iLayer++ )
+            {
+                OGRLayer        *poLayer = poDS->GetLayerByName(psOptions->papszLayers[iLayer]);
+
+                if( poLayer == NULL )
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined, "Couldn't fetch requested layer '%s'!",
+                             psOptions->papszLayers[iLayer] );
+                    if (!psOptions->bSkipFailures)
+                    {
+                        GDALVectorTranslateOptionsFree(psOptions);
+                        if( hDstDS == NULL ) GDALClose( poODS );
+                        delete poGCPCoordTrans;
+                        return NULL;
+                    }
+                }
+
+                papoLayers[iLayer] = poLayer;
+            }
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Special case to improve user experience when translating into   */
+/*      single file shapefile and source has only one layer, and that   */
+/*      the layer name isn't specified                                  */
+/* -------------------------------------------------------------------- */
+        VSIStatBufL  sStat;
+        if (EQUAL(poDriver->GetDescription(), "ESRI Shapefile") &&
+            nLayerCount == 1 && psOptions->pszNewLayerName == NULL &&
+            VSIStatL(osDestFilename, &sStat) == 0 && VSI_ISREG(sStat.st_mode))
+        {
+            psOptions->pszNewLayerName = CPLStrdup(CPLGetBasename(osDestFilename));
+        }
+
+        GIntBig* panLayerCountFeatures = (GIntBig*) CPLCalloc(sizeof(GIntBig), nLayerCount);
+        GIntBig nCountLayersFeatures = 0;
+        GIntBig nAccCountFeatures = 0;
+        int iLayer;
+
+        /* First pass to apply filters and count all features if necessary */
+        for( iLayer = 0;
+            iLayer < nLayerCount;
+            iLayer++ )
+        {
+            OGRLayer        *poLayer = papoLayers[iLayer];
+            if (poLayer == NULL)
+                continue;
+
+            if( psOptions->pszWHERE != NULL )
+            {
+                if( poLayer->SetAttributeFilter( psOptions->pszWHERE ) != OGRERR_NONE )
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined, "SetAttributeFilter(%s) on layer '%s' failed.",
+                             psOptions->pszWHERE, poLayer->GetName() );
+                    if (!psOptions->bSkipFailures)
+                    {
+                        GDALVectorTranslateOptionsFree(psOptions);
+                        if( hDstDS == NULL ) GDALClose( poODS );
+                        delete poGCPCoordTrans;
+                        return NULL;
+                    }
+                }
+            }
+
+            ApplySpatialFilter(poLayer, (OGRGeometry*)psOptions->hSpatialFilter, poSpatSRS, psOptions->pszGeomField, poSourceSRS);
+
+            if (psOptions->bDisplayProgress && !bSrcIsOSM)
+            {
+                if (!poLayer->TestCapability(OLCFastFeatureCount))
+                {
+                    CPLError(CE_Warning, CPLE_NotSupported, "Progress turned off as fast feature count is not available.");
+                    psOptions->bDisplayProgress = false;
+                }
+                else
+                {
+                    panLayerCountFeatures[iLayer] = poLayer->GetFeatureCount();
+                    nCountLayersFeatures += panLayerCountFeatures[iLayer];
+                }
+            }
+        }
+
+        /* Second pass to do the real job */
+        for( iLayer = 0;
+            iLayer < nLayerCount && nRetCode == 0;
+            iLayer++ )
+        {
+            OGRLayer        *poLayer = papoLayers[iLayer];
+            if (poLayer == NULL)
+                continue;
+
+            GDALProgressFunc pfnProgress = NULL;
+            void        *pProgressArg = NULL;
+
+            OGRLayer* poPassedLayer = poLayer;
+            if (psOptions->bSplitListFields)
+            {
+                poPassedLayer = new OGRSplitListFieldLayer(poPassedLayer, psOptions->nMaxSplitListSubFields);
+
+                if (psOptions->bDisplayProgress && psOptions->nMaxSplitListSubFields != 1 &&
+                    nCountLayersFeatures != 0)
+                {
+                    pfnProgress = GDALScaledProgress;
+                    pProgressArg =
+                        GDALCreateScaledProgress(nAccCountFeatures * 1.0 / nCountLayersFeatures,
+                                                (nAccCountFeatures + panLayerCountFeatures[iLayer] / 2) * 1.0 / nCountLayersFeatures,
+                                                psOptions->pfnProgress,
+                                                psOptions->pProgressData);
+                }
+                else
+                {
+                    pfnProgress = NULL;
+                    pProgressArg = NULL;
+                }
+
+                int nRet = ((OGRSplitListFieldLayer*)poPassedLayer)->BuildLayerDefn(pfnProgress, pProgressArg);
+                if (!nRet)
+                {
+                    delete poPassedLayer;
+                    poPassedLayer = poLayer;
+                }
+
+                if (psOptions->bDisplayProgress)
+                    GDALDestroyScaledProgress(pProgressArg);
+                pfnProgress = NULL;
+                pProgressArg = NULL;
+            }
+
+
+            if (psOptions->bDisplayProgress)
+            {
+                if ( bSrcIsOSM )
+                {
+                    pfnProgress = psOptions->pfnProgress;
+                    pProgressArg = psOptions->pProgressData;
+                }
+                else if( nCountLayersFeatures != 0 )
+                {
+                    pfnProgress = GDALScaledProgress;
+                    GIntBig nStart = 0;
+                    if (poPassedLayer != poLayer && psOptions->nMaxSplitListSubFields != 1)
+                        nStart = panLayerCountFeatures[iLayer] / 2;
+                    pProgressArg =
+                        GDALCreateScaledProgress((nAccCountFeatures + nStart) * 1.0 / nCountLayersFeatures,
+                                                (nAccCountFeatures + panLayerCountFeatures[iLayer]) * 1.0 / nCountLayersFeatures,
+                                                psOptions->pfnProgress,
+                                                psOptions->pProgressData);
+                }
+            }
+
+            nAccCountFeatures += panLayerCountFeatures[iLayer];
+
+            TargetLayerInfo* psInfo = oSetup.Setup(poPassedLayer,
+                                                   psOptions->pszNewLayerName,
+                                                   psOptions);
+
+            poPassedLayer->ResetReading();
+
+            if( (psInfo == NULL ||
+                !oTranslator.Translate( psInfo,
+                                        panLayerCountFeatures[iLayer], NULL,
+                                        pfnProgress, pProgressArg, psOptions ))
+                && !psOptions->bSkipFailures )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                        "Terminating translation prematurely after failed\n"
+                        "translation of layer %s (use -skipfailures to skip errors)",
+                        poLayer->GetName() );
+
+                nRetCode = 1;
+            }
+
+            FreeTargetLayerInfo(psInfo);
+
+            if (poPassedLayer != poLayer)
+                delete poPassedLayer;
+
+            if (psOptions->bDisplayProgress && !bSrcIsOSM)
+                GDALDestroyScaledProgress(pProgressArg);
+        }
+
+        CPLFree(panLayerCountFeatures);
+        CPLFree(papoLayers);
+    }
+/* -------------------------------------------------------------------- */
+/*      Process DS style table                                          */
+/* -------------------------------------------------------------------- */
+
+    poODS->SetStyleTable( poDS->GetStyleTable () );
+
+    if( psOptions->nGroupTransactions )
+    {
+        if( !psOptions->nLayerTransaction )
+        {
+            if( nRetCode != 0 && !psOptions->bSkipFailures )
+                poODS->RollbackTransaction();
+            else
+                poODS->CommitTransaction();
+        }
+    }
+
+    delete poGCPCoordTrans;
+
+    GDALVectorTranslateOptionsFree(psOptions);
+    if(nRetCode == 0)
+        return (GDALDatasetH) poODS;
+    else
+    {
+        if( hDstDS == NULL ) GDALClose( poODS );
+        return NULL;
+    }
+}
+
+
+/************************************************************************/
+/*                               SetZ()                                 */
+/************************************************************************/
+static void SetZ (OGRGeometry* poGeom, double dfZ )
+{
+    if (poGeom == NULL)
+        return;
+    switch (wkbFlatten(poGeom->getGeometryType()))
+    {
+        case wkbPoint:
+            ((OGRPoint*)poGeom)->setZ(dfZ);
+            break;
+
+        case wkbLineString:
+        case wkbLinearRing:
+        {
+            int i;
+            OGRLineString* poLS = (OGRLineString*) poGeom;
+            for(i=0;i<poLS->getNumPoints();i++)
+                poLS->setPoint(i, poLS->getX(i), poLS->getY(i), dfZ);
+            break;
+        }
+
+        case wkbPolygon:
+        {
+            int i;
+            OGRPolygon* poPoly = (OGRPolygon*) poGeom;
+            SetZ(poPoly->getExteriorRing(), dfZ);
+            for(i=0;i<poPoly->getNumInteriorRings();i++)
+                SetZ(poPoly->getInteriorRing(i), dfZ);
+            break;
+        }
+
+        case wkbMultiPoint:
+        case wkbMultiLineString:
+        case wkbMultiPolygon:
+        case wkbGeometryCollection:
+        {
+            int i;
+            OGRGeometryCollection* poGeomColl = (OGRGeometryCollection*) poGeom;
+            for(i=0;i<poGeomColl->getNumGeometries();i++)
+                SetZ(poGeomColl->getGeometryRef(i), dfZ);
+            break;
+        }
+
+        default:
+            break;
+    }
+}
+
+/************************************************************************/
+/*                       ForceCoordDimension()                          */
+/************************************************************************/
+
+static int ForceCoordDimension(int eGType, int nCoordDim)
+{
+    if( nCoordDim == 2 && eGType != wkbNone )
+        return wkbFlatten(eGType);
+    else if( nCoordDim == 3 && eGType != wkbNone )
+        return wkbSetZ(wkbFlatten((OGRwkbGeometryType)eGType));
+    else if( nCoordDim == COORD_DIM_XYM && eGType != wkbNone )
+        return wkbSetM(wkbFlatten((OGRwkbGeometryType)eGType));
+    else if( nCoordDim == 4 && eGType != wkbNone )
+        return OGR_GT_SetModifier((OGRwkbGeometryType)eGType, TRUE, TRUE);
+    else
+        return eGType;
+}
+
+/************************************************************************/
+/*                   GetLayerAndOverwriteIfNecessary()                  */
+/************************************************************************/
+
+static OGRLayer* GetLayerAndOverwriteIfNecessary(GDALDataset *poDstDS,
+                                                 const char* pszNewLayerName,
+                                                 bool bOverwrite,
+                                                 bool* pbErrorOccurred)
+{
+    if( pbErrorOccurred )
+        *pbErrorOccurred = false;
+
+    /* GetLayerByName() can instantiate layers that would have been */
+    /* 'hidden' otherwise, for example, non-spatial tables in a */
+    /* PostGIS-enabled database, so this apparently useless command is */
+    /* not useless. (#4012) */
+    CPLPushErrorHandler(CPLQuietErrorHandler);
+    OGRLayer* poDstLayer = poDstDS->GetLayerByName(pszNewLayerName);
+    CPLPopErrorHandler();
+    CPLErrorReset();
+
+    int iLayer = -1;
+    if (poDstLayer != NULL)
+    {
+        int nLayerCount = poDstDS->GetLayerCount();
+        for( iLayer = 0; iLayer < nLayerCount; iLayer++ )
+        {
+            OGRLayer        *poLayer = poDstDS->GetLayer(iLayer);
+            if (poLayer == poDstLayer)
+                break;
+        }
+
+        if (iLayer == nLayerCount)
+            /* should not happen with an ideal driver */
+            poDstLayer = NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      If the user requested overwrite, and we have the layer in       */
+/*      question we need to delete it now so it will get recreated      */
+/*      (overwritten).                                                  */
+/* -------------------------------------------------------------------- */
+    if( poDstLayer != NULL && bOverwrite )
+    {
+        if( poDstDS->DeleteLayer( iLayer ) != OGRERR_NONE )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                     "DeleteLayer() failed when overwrite requested." );
+            if( pbErrorOccurred )
+                *pbErrorOccurred = true;
+        }
+        poDstLayer = NULL;
+    }
+
+    return poDstLayer;
+}
+
+/************************************************************************/
+/*                          ConvertType()                               */
+/************************************************************************/
+
+static OGRwkbGeometryType ConvertType(GeomTypeConversion eGeomTypeConversion,
+                                      OGRwkbGeometryType eGType)
+{
+    OGRwkbGeometryType eRetType = eGType;
+    if ( eGeomTypeConversion == GTC_PROMOTE_TO_MULTI )
+    {
+        if( !OGR_GT_IsSubClassOf(eGType, wkbGeometryCollection) )
+            eRetType = OGR_GT_GetCollection(eGType);
+    }
+    else if ( eGeomTypeConversion == GTC_CONVERT_TO_LINEAR )
+        eRetType = OGR_GT_GetLinear(eGType);
+    if ( eGeomTypeConversion == GTC_CONVERT_TO_CURVE )
+        eRetType = OGR_GT_GetCurve(eGType);
+    return eRetType;
+}
+
+/************************************************************************/
+/*                        DoFieldTypeConversion()                       */
+/************************************************************************/
+
+static
+void DoFieldTypeConversion(GDALDataset* poDstDS, OGRFieldDefn& oFieldDefn,
+                           char** papszFieldTypesToString,
+                           char** papszMapFieldType,
+                           bool bUnsetFieldWidth,
+                           bool bQuiet,
+                           bool bForceNullable,
+                           bool bUnsetDefault)
+{
+    if (papszFieldTypesToString != NULL )
+    {
+        CPLString osLookupString;
+        osLookupString.Printf("%s(%s)",
+                        OGRFieldDefn::GetFieldTypeName(oFieldDefn.GetType()),
+                        OGRFieldDefn::GetFieldSubTypeName(oFieldDefn.GetSubType()));
+
+        int iIdx = CSLFindString(papszFieldTypesToString, osLookupString);
+        if( iIdx < 0 )
+            iIdx = CSLFindString(papszFieldTypesToString,
+                                        OGRFieldDefn::GetFieldTypeName(oFieldDefn.GetType()));
+        if( iIdx < 0 )
+            iIdx = CSLFindString(papszFieldTypesToString, "All");
+        if( iIdx >= 0 )
+        {
+            oFieldDefn.SetSubType(OFSTNone);
+            oFieldDefn.SetType(OFTString);
+        }
+    }
+    else if (papszMapFieldType != NULL)
+    {
+        CPLString osLookupString;
+        osLookupString.Printf("%s(%s)",
+                        OGRFieldDefn::GetFieldTypeName(oFieldDefn.GetType()),
+                        OGRFieldDefn::GetFieldSubTypeName(oFieldDefn.GetSubType()));
+
+        const char* pszType = CSLFetchNameValue(papszMapFieldType, osLookupString);
+        if( pszType == NULL )
+            pszType = CSLFetchNameValue(papszMapFieldType,
+                                        OGRFieldDefn::GetFieldTypeName(oFieldDefn.GetType()));
+        if( pszType == NULL )
+            pszType = CSLFetchNameValue(papszMapFieldType, "All");
+        if( pszType != NULL )
+        {
+            int iSubType;
+            int iType = GetFieldType(pszType, &iSubType);
+            if( iType >= 0 && iSubType >= 0 )
+            {
+                oFieldDefn.SetSubType(OFSTNone);
+                oFieldDefn.SetType((OGRFieldType)iType);
+                oFieldDefn.SetSubType((OGRFieldSubType)iSubType);
+                if( iType == OFTInteger )
+                    oFieldDefn.SetWidth(0);
+            }
+        }
+    }
+    if( bUnsetFieldWidth )
+    {
+        oFieldDefn.SetWidth(0);
+        oFieldDefn.SetPrecision(0);
+    }
+    if( bForceNullable )
+        oFieldDefn.SetNullable(TRUE);
+    if( bUnsetDefault )
+        oFieldDefn.SetDefault(NULL);
+
+    if( poDstDS->GetDriver() != NULL &&
+        poDstDS->GetDriver()->GetMetadataItem(GDAL_DMD_CREATIONFIELDDATATYPES) != NULL &&
+        strstr(poDstDS->GetDriver()->GetMetadataItem(GDAL_DMD_CREATIONFIELDDATATYPES),
+                OGRFieldDefn::GetFieldTypeName(oFieldDefn.GetType())) == NULL )
+    {
+        if( oFieldDefn.GetType() == OFTInteger64 )
+        {
+            if( !bQuiet )
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                        "The output driver does not seem to natively support %s "
+                        "type for field %s. Converting it to Real instead. "
+                        "-mapFieldType can be used to control field type conversion.",
+                        OGRFieldDefn::GetFieldTypeName(oFieldDefn.GetType()),
+                        oFieldDefn.GetNameRef());
+            }
+            oFieldDefn.SetType(OFTReal);
+        }
+        else if( !bQuiet )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                        "The output driver does not natively support %s type for "
+                        "field %s. Misconversion can happen. "
+                        "-mapFieldType can be used to control field type conversion.",
+                        OGRFieldDefn::GetFieldTypeName(oFieldDefn.GetType()),
+                        oFieldDefn.GetNameRef());
+        }
+    }
+    else if( poDstDS->GetDriver() != NULL &&
+             poDstDS->GetDriver()->GetMetadataItem(GDAL_DMD_CREATIONFIELDDATATYPES) == NULL )
+    {
+        // All drivers supporting OFTInteger64 should advertise it theoretically
+        if( oFieldDefn.GetType() == OFTInteger64 )
+        {
+            if( !bQuiet )
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                        "The output driver does not seem to natively support %s type "
+                        "for field %s. Converting it to Real instead. "
+                        "-mapFieldType can be used to control field type conversion.",
+                        OGRFieldDefn::GetFieldTypeName(oFieldDefn.GetType()),
+                        oFieldDefn.GetNameRef());
+            }
+            oFieldDefn.SetType(OFTReal);
+        }
+    }
+}
+
+/************************************************************************/
+/*                   SetupTargetLayer::Setup()                          */
+/************************************************************************/
+
+TargetLayerInfo* SetupTargetLayer::Setup(OGRLayer* poSrcLayer,
+                                         const char* pszNewLayerName,
+                                         GDALVectorTranslateOptions *psOptions)
+{
+    OGRLayer    *poDstLayer;
+    OGRFeatureDefn *poSrcFDefn;
+    OGRFeatureDefn *poDstFDefn = NULL;
+    int eGType = m_eGType;
+    bool bPreserveFID = m_bPreserveFID;
+    bool bAppend = m_bAppend;
+
+    if( pszNewLayerName == NULL )
+        pszNewLayerName = poSrcLayer->GetName();
+
+/* -------------------------------------------------------------------- */
+/*      Get other info.                                                 */
+/* -------------------------------------------------------------------- */
+    poSrcFDefn = poSrcLayer->GetLayerDefn();
+
+/* -------------------------------------------------------------------- */
+/*      Find requested geometry fields.                                 */
+/* -------------------------------------------------------------------- */
+    std::vector<int> anRequestedGeomFields;
+    int nSrcGeomFieldCount = poSrcFDefn->GetGeomFieldCount();
+    if (m_papszSelFields && !bAppend )
+    {
+        for( int iField=0; m_papszSelFields[iField] != NULL; iField++)
+        {
+            int iSrcField = poSrcFDefn->GetFieldIndex(m_papszSelFields[iField]);
+            if (iSrcField >= 0)
+            {
+                /* do nothing */
+            }
+            else
+            {
+                iSrcField = poSrcFDefn->GetGeomFieldIndex(m_papszSelFields[iField]);
+                if( iSrcField >= 0)
+                {
+                    anRequestedGeomFields.push_back(iSrcField);
+                }
+                else
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined, "Field '%s' not found in source layer.",
+                              m_papszSelFields[iField] );
+                    if( !psOptions->bSkipFailures )
+                        return NULL;
+                }
+            }
+        }
+
+        if( anRequestedGeomFields.size() > 1 &&
+            !m_poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer) )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "Several geometry fields requested, but output "
+                                "datasource does not support multiple geometry "
+                                "fields." );
+            if( !psOptions->bSkipFailures )
+                return NULL;
+            else
+                anRequestedGeomFields.resize(0);
+        }
+    }
+
+    OGRSpatialReference* poOutputSRS = m_poOutputSRS;
+    if( poOutputSRS == NULL && !m_bNullifyOutputSRS )
+    {
+        if( nSrcGeomFieldCount == 1 || anRequestedGeomFields.size() == 0 )
+            poOutputSRS = poSrcLayer->GetSpatialRef();
+        else if( anRequestedGeomFields.size() == 1 )
+        {
+            int iSrcGeomField = anRequestedGeomFields[0];
+            poOutputSRS = poSrcFDefn->GetGeomFieldDefn(iSrcGeomField)->
+                GetSpatialRef();
+        }
+    }
+
+    int iSrcZField = -1;
+    if (m_pszZField != NULL)
+    {
+        iSrcZField = poSrcFDefn->GetFieldIndex(m_pszZField);
+        if( iSrcZField < 0 )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "zfield '%s' does not exist in layer %s",
+                     m_pszZField, poSrcLayer->GetName());
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Find the layer.                                                 */
+/* -------------------------------------------------------------------- */
+
+    bool bErrorOccurred;
+    poDstLayer = GetLayerAndOverwriteIfNecessary(m_poDstDS,
+                                                 pszNewLayerName,
+                                                 m_bOverwrite,
+                                                 &bErrorOccurred);
+    if( bErrorOccurred )
+        return NULL;
+
+/* -------------------------------------------------------------------- */
+/*      If the layer does not exist, then create it.                    */
+/* -------------------------------------------------------------------- */
+    if( poDstLayer == NULL )
+    {
+        if( !m_poDstDS->TestCapability( ODsCCreateLayer ) )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+              "Layer %s not found, and CreateLayer not supported by driver.",
+                     pszNewLayerName );
+            return NULL;
+        }
+
+        bool bForceGType = ( eGType != GEOMTYPE_UNCHANGED );
+        if( !bForceGType )
+        {
+            if( anRequestedGeomFields.size() == 0 )
+            {
+                eGType = poSrcFDefn->GetGeomType();
+            }
+            else if( anRequestedGeomFields.size() == 1  )
+            {
+                int iSrcGeomField = anRequestedGeomFields[0];
+                eGType = poSrcFDefn->GetGeomFieldDefn(iSrcGeomField)->GetType();
+            }
+            else
+                eGType = wkbNone;
+
+            bool bHasZ = CPL_TO_BOOL(wkbHasZ((OGRwkbGeometryType)eGType));
+            eGType = ConvertType(m_eGeomTypeConversion, (OGRwkbGeometryType)eGType);
+
+            if ( m_bExplodeCollections )
+            {
+                OGRwkbGeometryType eFGType = wkbFlatten(eGType);
+                if (eFGType == wkbMultiPoint)
+                {
+                    eGType = wkbPoint;
+                }
+                else if (eFGType == wkbMultiLineString)
+                {
+                    eGType = wkbLineString;
+                }
+                else if (eFGType == wkbMultiPolygon)
+                {
+                    eGType = wkbPolygon;
+                }
+                else if (eFGType == wkbGeometryCollection ||
+                         eFGType == wkbMultiCurve ||
+                         eFGType == wkbMultiSurface)
+                {
+                    eGType = wkbUnknown;
+                }
+            }
+
+            if ( bHasZ || (iSrcZField >= 0 && eGType != wkbNone) )
+                eGType = wkbSetZ((OGRwkbGeometryType)eGType);
+        }
+
+        eGType = ForceCoordDimension(eGType, m_nCoordDim);
+
+        CPLErrorReset();
+
+        char** papszLCOTemp = CSLDuplicate(m_papszLCO);
+
+        int eGCreateLayerType = eGType;
+        if( anRequestedGeomFields.size() == 0 &&
+            nSrcGeomFieldCount > 1 &&
+            m_poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer) )
+        {
+            eGCreateLayerType = wkbNone;
+        }
+        else if( anRequestedGeomFields.size() == 1 &&
+                 m_poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer) )
+        {
+            eGCreateLayerType = wkbNone;
+        }
+        // If the source feature has a single geometry column that is not nullable
+        // and that ODsCCreateGeomFieldAfterCreateLayer is available, use it
+        // so as to be able to set the not null constraint (if the driver supports it)
+        else if( anRequestedGeomFields.size() == 0 &&
+                 nSrcGeomFieldCount == 1 &&
+                 m_poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer) &&
+                 !poSrcFDefn->GetGeomFieldDefn(0)->IsNullable() &&
+                 !m_bForceNullable)
+        {
+            anRequestedGeomFields.push_back(0);
+            eGCreateLayerType = wkbNone;
+        }
+        // If the source feature first geometry column is not nullable
+        // and that GEOMETRY_NULLABLE creation option is available, use it
+        // so as to be able to set the not null constraint (if the driver supports it)
+        else if( anRequestedGeomFields.size() == 0 &&
+                 nSrcGeomFieldCount >= 1 &&
+                 !poSrcFDefn->GetGeomFieldDefn(0)->IsNullable() &&
+                 m_poDstDS->GetDriver()->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST) != NULL &&
+                 strstr(m_poDstDS->GetDriver()->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST), "GEOMETRY_NULLABLE") != NULL &&
+                 CSLFetchNameValue(m_papszLCO, "GEOMETRY_NULLABLE") == NULL&&
+                 !m_bForceNullable )
+        {
+            papszLCOTemp = CSLSetNameValue(papszLCOTemp, "GEOMETRY_NULLABLE", "NO");
+            CPLDebug("GDALVectorTranslate", "Using GEOMETRY_NULLABLE=NO");
+        }
+
+        // Force FID column as 64 bit if the source feature has a 64 bit FID,
+        // the target driver supports 64 bit FID and the user didn't set it
+        // manually.
+        if( poSrcLayer->GetMetadataItem(OLMD_FID64) != NULL &&
+            EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES") &&
+            m_poDstDS->GetDriver()->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST) != NULL &&
+            strstr(m_poDstDS->GetDriver()->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST), "FID64") != NULL &&
+            CSLFetchNameValue(m_papszLCO, "FID64") == NULL )
+        {
+            papszLCOTemp = CSLSetNameValue(papszLCOTemp, "FID64", "YES");
+            CPLDebug("GDALVectorTranslate", "Using FID64=YES");
+        }
+
+        // If output driver supports FID layer creation option, set it with
+        // the FID column name of the source layer
+        if( !m_bUnsetFid && !bAppend &&
+            poSrcLayer->GetFIDColumn() != NULL &&
+            !EQUAL(poSrcLayer->GetFIDColumn(), "") &&
+            m_poDstDS->GetDriver()->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST) != NULL &&
+            strstr(m_poDstDS->GetDriver()->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST), "='FID'") != NULL &&
+            CSLFetchNameValue(m_papszLCO, "FID") == NULL )
+        {
+            papszLCOTemp = CSLSetNameValue(papszLCOTemp, "FID", poSrcLayer->GetFIDColumn());
+            CPLDebug("GDALVectorTranslate", "Using FID=%s and -preserve_fid", poSrcLayer->GetFIDColumn());
+            bPreserveFID = true;
+        }
+
+        if( m_bNativeData &&
+            poSrcLayer->GetMetadataItem("NATIVE_DATA", "NATIVE_DATA") != NULL &&
+            poSrcLayer->GetMetadataItem("NATIVE_MEDIA_TYPE", "NATIVE_DATA") != NULL &&
+            m_poDstDS->GetDriver()->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST) != NULL &&
+            strstr(m_poDstDS->GetDriver()->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST), "NATIVE_DATA") != NULL &&
+            strstr(m_poDstDS->GetDriver()->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST), "NATIVE_MEDIA_TYPE") != NULL )
+        {
+            papszLCOTemp = CSLSetNameValue(papszLCOTemp, "NATIVE_DATA",
+                    poSrcLayer->GetMetadataItem("NATIVE_DATA", "NATIVE_DATA"));
+            papszLCOTemp = CSLSetNameValue(papszLCOTemp, "NATIVE_MEDIA_TYPE",
+                    poSrcLayer->GetMetadataItem("NATIVE_MEDIA_TYPE", "NATIVE_DATA"));
+            CPLDebug("GDALVectorTranslate", "Transferring layer NATIVE_DATA");
+        }
+
+        OGRSpatialReference* poOutputSRSClone = NULL;
+        if( poOutputSRS != NULL )
+        {
+            poOutputSRSClone = poOutputSRS->Clone();
+        }
+        poDstLayer = m_poDstDS->CreateLayer( pszNewLayerName, poOutputSRSClone,
+                                           (OGRwkbGeometryType) eGCreateLayerType,
+                                           papszLCOTemp );
+        CSLDestroy(papszLCOTemp);
+
+        if( poOutputSRSClone != NULL )
+        {
+            poOutputSRSClone->Release();
+        }
+
+        if( poDstLayer == NULL )
+        {
+            return NULL;
+        }
+
+        if( m_bCopyMD )
+        {
+            char** papszDomains = poSrcLayer->GetMetadataDomainList();
+            for(char** papszIter = papszDomains; papszIter && *papszIter; ++papszIter )
+            {
+                if( !EQUAL(*papszIter, "IMAGE_STRUCTURE") &&
+                    !EQUAL(*papszIter, "SUBDATASETS") )
+                {
+                    char** papszMD = poSrcLayer->GetMetadata(*papszIter);
+                    if( papszMD )
+                        poDstLayer->SetMetadata(papszMD, *papszIter);
+                }
+            }
+            CSLDestroy(papszDomains);
+        }
+
+        if( anRequestedGeomFields.size() == 0 &&
+            nSrcGeomFieldCount > 1 &&
+            m_poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer) )
+        {
+            for(int i = 0; i < nSrcGeomFieldCount; i ++)
+            {
+                anRequestedGeomFields.push_back(i);
+            }
+        }
+
+        if( anRequestedGeomFields.size() > 1 ||
+            (anRequestedGeomFields.size() == 1 &&
+                 m_poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer)) )
+        {
+            for(int i = 0; i < (int)anRequestedGeomFields.size(); i ++)
+            {
+                int iSrcGeomField = anRequestedGeomFields[i];
+                OGRGeomFieldDefn oGFldDefn
+                    (poSrcFDefn->GetGeomFieldDefn(iSrcGeomField));
+                if( m_poOutputSRS != NULL )
+                {
+                    poOutputSRSClone = m_poOutputSRS->Clone();
+                    oGFldDefn.SetSpatialRef(poOutputSRSClone);
+                    poOutputSRSClone->Release();
+                }
+                if( bForceGType )
+                    oGFldDefn.SetType((OGRwkbGeometryType) eGType);
+                else
+                {
+                    eGType = oGFldDefn.GetType();
+                    eGType = ConvertType(m_eGeomTypeConversion, (OGRwkbGeometryType)eGType);
+                    eGType = ForceCoordDimension(eGType, m_nCoordDim);
+                    oGFldDefn.SetType((OGRwkbGeometryType) eGType);
+                }
+                if( m_bForceNullable )
+                    oGFldDefn.SetNullable(TRUE);
+                poDstLayer->CreateGeomField(&oGFldDefn);
+            }
+        }
+
+        bAppend = false;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Otherwise we will append to it, if append was requested.        */
+/* -------------------------------------------------------------------- */
+    else if( !bAppend )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Layer %s already exists, and -append not specified.\n"
+                         "        Consider using -append, or -overwrite.",
+                pszNewLayerName );
+        return NULL;
+    }
+    else
+    {
+        if( CSLCount(m_papszLCO) > 0 )
+        {
+            CPLError( CE_Warning, CPLE_AppDefined, "Layer creation options ignored since an existing layer is\n"
+                                                  "         being appended to." );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Process Layer style table                                       */
+/* -------------------------------------------------------------------- */
+
+    poDstLayer->SetStyleTable( poSrcLayer->GetStyleTable () );
+/* -------------------------------------------------------------------- */
+/*      Add fields.  Default to copy all field.                         */
+/*      If only a subset of all fields requested, then output only      */
+/*      the selected fields, and in the order that they were            */
+/*      selected.                                                       */
+/* -------------------------------------------------------------------- */
+    int         nSrcFieldCount = poSrcFDefn->GetFieldCount();
+    int         iSrcFIDField = -1;
+
+    // Initialize the index-to-index map to -1's
+    int *panMap = (int *) VSIMalloc( sizeof(int) * nSrcFieldCount );
+    for( int iField=0; iField < nSrcFieldCount; iField++)
+        panMap[iField] = -1;
+
+    /* Caution : at the time of writing, the MapInfo driver */
+    /* returns NULL until a field has been added */
+    poDstFDefn = poDstLayer->GetLayerDefn();
+
+    if (m_papszFieldMap && bAppend)
+    {
+        bool bIdentity = false;
+
+        if (EQUAL(m_papszFieldMap[0], "identity"))
+            bIdentity = true;
+        else if (CSLCount(m_papszFieldMap) != nSrcFieldCount)
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "Field map should contain the value 'identity' or "
+                    "the same number of integer values as the source field count.");
+            VSIFree(panMap);
+            return NULL;
+        }
+
+        for( int iField=0; iField < nSrcFieldCount; iField++)
+        {
+            panMap[iField] = bIdentity? iField : atoi(m_papszFieldMap[iField]);
+            if (panMap[iField] >= poDstFDefn->GetFieldCount())
+            {
+                CPLError( CE_Failure, CPLE_AppDefined, "Invalid destination field index %d.", panMap[iField]);
+                VSIFree(panMap);
+                return NULL;
+            }
+        }
+    }
+    else if (m_papszSelFields && !bAppend )
+    {
+        int  nDstFieldCount = 0;
+        if (poDstFDefn)
+            nDstFieldCount = poDstFDefn->GetFieldCount();
+        for( int iField=0; m_papszSelFields[iField] != NULL; iField++)
+        {
+            int iSrcField = poSrcFDefn->GetFieldIndex(m_papszSelFields[iField]);
+            if (iSrcField >= 0)
+            {
+                OGRFieldDefn* poSrcFieldDefn = poSrcFDefn->GetFieldDefn(iSrcField);
+                OGRFieldDefn oFieldDefn( poSrcFieldDefn );
+
+                DoFieldTypeConversion(m_poDstDS, oFieldDefn,
+                                      m_papszFieldTypesToString,
+                                      m_papszMapFieldType,
+                                      m_bUnsetFieldWidth,
+                                      psOptions->bQuiet,
+                                      m_bForceNullable,
+                                      m_bUnsetDefault);
+
+                /* The field may have been already created at layer creation */
+                int iDstField = -1;
+                if (poDstFDefn)
+                    iDstField = poDstFDefn->GetFieldIndex(oFieldDefn.GetNameRef());
+                if (iDstField >= 0)
+                {
+                    panMap[iSrcField] = iDstField;
+                }
+                else if (poDstLayer->CreateField( &oFieldDefn ) == OGRERR_NONE)
+                {
+                    /* now that we've created a field, GetLayerDefn() won't return NULL */
+                    if (poDstFDefn == NULL)
+                        poDstFDefn = poDstLayer->GetLayerDefn();
+
+                    /* Sanity check : if it fails, the driver is buggy */
+                    if (poDstFDefn != NULL &&
+                        poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
+                    {
+                        CPLError(CE_Warning, CPLE_AppDefined,
+                                 "The output driver has claimed to have added the %s field, but it did not!",
+                                 oFieldDefn.GetNameRef() );
+                    }
+                    else
+                    {
+                        panMap[iSrcField] = nDstFieldCount;
+                        nDstFieldCount ++;
+                    }
+                }
+            }
+        }
+
+        /* -------------------------------------------------------------------- */
+        /* Use SetIgnoredFields() on source layer if available                  */
+        /* -------------------------------------------------------------------- */
+        if (poSrcLayer->TestCapability(OLCIgnoreFields))
+        {
+            int iSrcField;
+            char** papszIgnoredFields = NULL;
+            bool bUseIgnoredFields = true;
+            char** papszWHEREUsedFields = NULL;
+
+            if (m_pszWHERE)
+            {
+                /* We must not ignore fields used in the -where expression (#4015) */
+                OGRFeatureQuery oFeatureQuery;
+                if ( oFeatureQuery.Compile( poSrcLayer->GetLayerDefn(), m_pszWHERE, FALSE, NULL ) == OGRERR_NONE )
+                {
+                    papszWHEREUsedFields = oFeatureQuery.GetUsedFields();
+                }
+                else
+                {
+                    bUseIgnoredFields = false;
+                }
+            }
+
+            for(iSrcField=0;bUseIgnoredFields && iSrcField<poSrcFDefn->GetFieldCount();iSrcField++)
+            {
+                const char* pszFieldName =
+                    poSrcFDefn->GetFieldDefn(iSrcField)->GetNameRef();
+                bool bFieldRequested = false;
+                for( int iField=0; m_papszSelFields[iField] != NULL; iField++)
+                {
+                    if (EQUAL(pszFieldName, m_papszSelFields[iField]))
+                    {
+                        bFieldRequested = true;
+                        break;
+                    }
+                }
+                bFieldRequested |= CSLFindString(papszWHEREUsedFields, pszFieldName) >= 0;
+                bFieldRequested |= (m_pszZField != NULL && EQUAL(pszFieldName, m_pszZField));
+
+                /* If source field not requested, add it to ignored files list */
+                if (!bFieldRequested)
+                    papszIgnoredFields = CSLAddString(papszIgnoredFields, pszFieldName);
+            }
+            if (bUseIgnoredFields)
+                poSrcLayer->SetIgnoredFields((const char**)papszIgnoredFields);
+            CSLDestroy(papszIgnoredFields);
+            CSLDestroy(papszWHEREUsedFields);
+        }
+    }
+    else if( !bAppend || m_bAddMissingFields )
+    {
+        int nDstFieldCount = 0;
+        if (poDstFDefn)
+            nDstFieldCount = poDstFDefn->GetFieldCount();
+
+        /* Save the map of existing fields, before creating new ones */
+        /* This helps when converting a source layer that has duplicated field names */
+        /* which is a bad idea */
+        std::map<CPLString, int> oMapExistingFields;
+        for( int iField = 0; iField < nDstFieldCount; iField++ )
+        {
+            const char* pszFieldName = poDstFDefn->GetFieldDefn(iField)->GetNameRef();
+            CPLString osUpperFieldName(CPLString(pszFieldName).toupper());
+            if( oMapExistingFields.find(osUpperFieldName) == oMapExistingFields.end() )
+                oMapExistingFields[osUpperFieldName] = iField;
+            /*else
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "The target layer has already a duplicated field name '%s' before "
+                         "adding the fields of the source layer", pszFieldName); */
+        }
+
+        const char* pszFIDColumn = poDstLayer->GetFIDColumn();
+
+        for( int iField = 0; iField < nSrcFieldCount; iField++ )
+        {
+            OGRFieldDefn* poSrcFieldDefn = poSrcFDefn->GetFieldDefn(iField);
+            OGRFieldDefn oFieldDefn( poSrcFieldDefn );
+
+            // Avoid creating a field with the same name as the FID column
+            if( pszFIDColumn != NULL && EQUAL(pszFIDColumn, oFieldDefn.GetNameRef()) &&
+                (oFieldDefn.GetType() == OFTInteger || oFieldDefn.GetType() == OFTInteger64) )
+            {
+                iSrcFIDField = iField;
+                continue;
+            }
+
+            DoFieldTypeConversion(m_poDstDS, oFieldDefn,
+                                  m_papszFieldTypesToString,
+                                  m_papszMapFieldType,
+                                  m_bUnsetFieldWidth,
+                                  psOptions->bQuiet,
+                                  m_bForceNullable,
+                                  m_bUnsetDefault);
+
+            /* The field may have been already created at layer creation */
+            std::map<CPLString, int>::iterator oIter =
+                oMapExistingFields.find(CPLString(oFieldDefn.GetNameRef()).toupper());
+            if( oIter != oMapExistingFields.end() )
+            {
+                panMap[iField] = oIter->second;
+                continue;
+            }
+
+            bool bHasRenamed = false;
+            /* In case the field name already exists in the target layer, */
+            /* build a unique field name */
+            if( poDstFDefn != NULL &&
+                poDstFDefn->GetFieldIndex(oFieldDefn.GetNameRef()) >= 0 )
+            {
+                int nTry = 1;
+                while( true )
+                {
+                    ++nTry;
+                    CPLString osTmpName;
+                    osTmpName.Printf("%s%d", oFieldDefn.GetNameRef(), nTry);
+                    /* Check that the proposed name doesn't exist either in the already */
+                    /* created fields or in the source fields */
+                    if( poDstFDefn->GetFieldIndex(osTmpName) < 0 &&
+                        poSrcFDefn->GetFieldIndex(osTmpName) < 0 )
+                    {
+                        bHasRenamed = true;
+                        oFieldDefn.SetName(osTmpName);
+                        break;
+                    }
+                }
+            }
+
+            if (poDstLayer->CreateField( &oFieldDefn ) == OGRERR_NONE)
+            {
+                /* now that we've created a field, GetLayerDefn() won't return NULL */
+                if (poDstFDefn == NULL)
+                    poDstFDefn = poDstLayer->GetLayerDefn();
+
+                /* Sanity check : if it fails, the driver is buggy */
+                if (poDstFDefn != NULL &&
+                    poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "The output driver has claimed to have added the %s field, but it did not!",
+                             oFieldDefn.GetNameRef() );
+                }
+                else
+                {
+                    if( bHasRenamed )
+                    {
+                        const char* pszNewFieldName =
+                            poDstFDefn->GetFieldDefn(nDstFieldCount)->GetNameRef();
+                        CPLError(CE_Warning, CPLE_AppDefined,
+                                 "Field '%s' already exists. Renaming it as '%s'",
+                                 poSrcFieldDefn->GetNameRef(), pszNewFieldName);
+                    }
+
+                    panMap[iField] = nDstFieldCount;
+                    nDstFieldCount ++;
+                }
+            }
+        }
+    }
+    else
+    {
+        /* For an existing layer, build the map by fetching the index in the destination */
+        /* layer for each source field */
+        if (poDstFDefn == NULL)
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "poDstFDefn == NULL." );
+            VSIFree(panMap);
+            return NULL;
+        }
+
+        for( int iField = 0; iField < nSrcFieldCount; iField++ )
+        {
+            OGRFieldDefn* poSrcFieldDefn = poSrcFDefn->GetFieldDefn(iField);
+            int iDstField = poDstLayer->FindFieldIndex(poSrcFieldDefn->GetNameRef(), m_bExactFieldNameMatch);
+            if (iDstField >= 0)
+                panMap[iField] = iDstField;
+            else
+                CPLDebug("GDALVectorTranslate", "Skipping field '%s' not found in destination layer '%s'.",
+                         poSrcFieldDefn->GetNameRef(), poDstLayer->GetName() );
+        }
+    }
+
+    TargetLayerInfo* psInfo = (TargetLayerInfo*)
+                                            CPLMalloc(sizeof(TargetLayerInfo));
+    psInfo->nFeaturesRead = 0;
+    psInfo->bPerFeatureCT = false;
+    psInfo->poSrcLayer = poSrcLayer;
+    psInfo->poDstLayer = poDstLayer;
+    psInfo->papoCT = (OGRCoordinateTransformation**)
+        CPLCalloc(poDstLayer->GetLayerDefn()->GetGeomFieldCount(),
+                  sizeof(OGRCoordinateTransformation*));
+    psInfo->papapszTransformOptions = (char***)
+        CPLCalloc(poDstLayer->GetLayerDefn()->GetGeomFieldCount(),
+                  sizeof(char**));
+    psInfo->panMap = panMap;
+    psInfo->iSrcZField = iSrcZField;
+    psInfo->iSrcFIDField = iSrcFIDField;
+    if( anRequestedGeomFields.size() == 1 )
+        psInfo->iRequestedSrcGeomField = anRequestedGeomFields[0];
+    else
+        psInfo->iRequestedSrcGeomField = -1;
+    psInfo->bPreserveFID = bPreserveFID;
+
+    return psInfo;
+}
+
+/************************************************************************/
+/*                         FreeTargetLayerInfo()                        */
+/************************************************************************/
+
+static void FreeTargetLayerInfo(TargetLayerInfo* psInfo)
+{
+    if( psInfo == NULL )
+        return;
+    for(int i=0;i<psInfo->poDstLayer->GetLayerDefn()->GetGeomFieldCount();i++)
+    {
+        delete psInfo->papoCT[i];
+        CSLDestroy(psInfo->papapszTransformOptions[i]);
+    }
+    CPLFree(psInfo->papoCT);
+    CPLFree(psInfo->papapszTransformOptions);
+    CPLFree(psInfo->panMap);
+    CPLFree(psInfo);
+}
+
+/************************************************************************/
+/*                               SetupCT()                              */
+/************************************************************************/
+
+static bool SetupCT( TargetLayerInfo* psInfo,
+                    OGRLayer* poSrcLayer,
+                    bool bTransform,
+                    bool bWrapDateline,
+                    const CPLString& osDateLineOffset,
+                    OGRSpatialReference* poUserSourceSRS,
+                    OGRFeature* poFeature,
+                    OGRSpatialReference* poOutputSRS,
+                    OGRCoordinateTransformation* poGCPCoordTrans)
+{
+    OGRLayer    *poDstLayer = psInfo->poDstLayer;
+    int nDstGeomFieldCount = poDstLayer->GetLayerDefn()->GetGeomFieldCount();
+    for( int iGeom = 0; iGeom < nDstGeomFieldCount; iGeom ++ )
+    {
+/* -------------------------------------------------------------------- */
+/*      Setup coordinate transformation if we need it.                  */
+/* -------------------------------------------------------------------- */
+        OGRSpatialReference* poSourceSRS = NULL;
+        OGRCoordinateTransformation* poCT = NULL;
+        char** papszTransformOptions = NULL;
+
+        int iSrcGeomField;
+        if( psInfo->iRequestedSrcGeomField >= 0 )
+            iSrcGeomField = psInfo->iRequestedSrcGeomField;
+        else
+        {
+            iSrcGeomField = poSrcLayer->GetLayerDefn()->GetGeomFieldIndex(
+                poDstLayer->GetLayerDefn()->GetGeomFieldDefn(iGeom)->GetNameRef());
+            if( iSrcGeomField < 0 )
+            {
+                if( nDstGeomFieldCount == 1 &&
+                    poSrcLayer->GetLayerDefn()->GetGeomFieldCount() > 0 )
+                {
+                    iSrcGeomField = 0;
+                }
+                else
+                    continue;
+            }
+        }
+
+        if( bTransform || bWrapDateline )
+        {
+            if( psInfo->nFeaturesRead == 0 )
+            {
+                poSourceSRS = poUserSourceSRS;
+                if( poSourceSRS == NULL )
+                {
+                    if( iSrcGeomField > 0 )
+                        poSourceSRS = poSrcLayer->GetLayerDefn()->
+                            GetGeomFieldDefn(iSrcGeomField)->GetSpatialRef();
+                    else
+                        poSourceSRS = poSrcLayer->GetSpatialRef();
+                }
+            }
+            if( poSourceSRS == NULL )
+            {
+                OGRGeometry* poSrcGeometry =
+                    poFeature->GetGeomFieldRef(iSrcGeomField);
+                if( poSrcGeometry )
+                    poSourceSRS = poSrcGeometry->getSpatialReference();
+                psInfo->bPerFeatureCT = true;
+            }
+        }
+
+        if( bTransform )
+        {
+            if( poSourceSRS == NULL )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined, "Can't transform coordinates, source layer has no\n"
+                        "coordinate system.  Use -s_srs to set one." );
+
+                return false;
+            }
+
+            CPLAssert( NULL != poSourceSRS );
+            CPLAssert( NULL != poOutputSRS );
+
+            if( psInfo->papoCT[iGeom] != NULL &&
+                psInfo->papoCT[iGeom]->GetSourceCS() == poSourceSRS )
+            {
+                poCT = psInfo->papoCT[iGeom];
+            }
+            else
+            {
+                poCT = OGRCreateCoordinateTransformation( poSourceSRS, poOutputSRS );
+                if( poCT == NULL )
+                {
+                    char        *pszWKT = NULL;
+
+                    CPLError( CE_Failure, CPLE_AppDefined, "Failed to create coordinate transformation between the\n"
+                        "following coordinate systems.  This may be because they\n"
+                        "are not transformable, or because projection services\n"
+                        "(PROJ.4 DLL/.so) could not be loaded." );
+
+                    poSourceSRS->exportToPrettyWkt( &pszWKT, FALSE );
+                    CPLError( CE_Failure, CPLE_AppDefined,  "Source:\n%s", pszWKT );
+                    CPLFree(pszWKT);
+
+                    poOutputSRS->exportToPrettyWkt( &pszWKT, FALSE );
+                    CPLError( CE_Failure, CPLE_AppDefined,  "Target:\n%s", pszWKT );
+                    CPLFree(pszWKT);
+
+                    return false;
+                }
+                if( poGCPCoordTrans != NULL )
+                    poCT = new CompositeCT( poGCPCoordTrans, poCT );
+            }
+
+            if( poCT != psInfo->papoCT[iGeom] )
+            {
+                delete psInfo->papoCT[iGeom];
+                psInfo->papoCT[iGeom] = poCT;
+            }
+        }
+        else
+        {
+            poCT = poGCPCoordTrans;
+        }
+
+        if (bWrapDateline)
+        {
+            if (bTransform && poCT != NULL && poOutputSRS != NULL && poOutputSRS->IsGeographic())
+            {
+                papszTransformOptions =
+                    CSLAddString(papszTransformOptions, "WRAPDATELINE=YES");
+                if( osDateLineOffset.size() )
+                {
+                    CPLString soOffset("DATELINEOFFSET=");
+                    soOffset += osDateLineOffset;
+                    papszTransformOptions =
+                        CSLAddString(papszTransformOptions, soOffset);
+                }
+            }
+            else if (poSourceSRS != NULL && poSourceSRS->IsGeographic())
+            {
+                papszTransformOptions =
+                    CSLAddString(papszTransformOptions, "WRAPDATELINE=YES");
+                if( osDateLineOffset.size() )
+                {
+                    CPLString soOffset("DATELINEOFFSET=");
+                    soOffset += osDateLineOffset;
+                    papszTransformOptions =
+                        CSLAddString(papszTransformOptions, soOffset);
+                }
+            }
+            else
+            {
+                static bool bHasWarned = false;
+                if( !bHasWarned )
+                    CPLError( CE_Failure, CPLE_IllegalArg, "-wrapdateline option only works when reprojecting to a geographic SRS");
+                bHasWarned = true;
+            }
+
+            CSLDestroy(psInfo->papapszTransformOptions[iGeom]);
+            psInfo->papapszTransformOptions[iGeom] = papszTransformOptions;
+        }
+    }
+    return true;
+}
+
+/************************************************************************/
+/*                     LayerTranslator::Translate()                     */
+/************************************************************************/
+
+int LayerTranslator::Translate( TargetLayerInfo* psInfo,
+                                GIntBig nCountLayerFeatures,
+                                GIntBig* pnReadFeatureCount,
+                                GDALProgressFunc pfnProgress,
+                                void *pProgressArg,
+                                GDALVectorTranslateOptions *psOptions )
+{
+    OGRLayer    *poSrcLayer;
+    OGRLayer    *poDstLayer;
+    const int         eGType = m_eGType;
+    OGRSpatialReference* poOutputSRS = m_poOutputSRS;
+
+    poSrcLayer = psInfo->poSrcLayer;
+    poDstLayer = psInfo->poDstLayer;
+    int* const panMap = psInfo->panMap;
+    const int iSrcZField = psInfo->iSrcZField;
+    const bool bPreserveFID = psInfo->bPreserveFID;
+    const int nSrcGeomFieldCount = poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
+    const int nDstGeomFieldCount = poDstLayer->GetLayerDefn()->GetGeomFieldCount();
+    const bool bExplodeCollections = m_bExplodeCollections && nDstGeomFieldCount <= 1;
+
+    if( poOutputSRS == NULL && !m_bNullifyOutputSRS )
+    {
+        if( nSrcGeomFieldCount == 1 )
+        {
+            poOutputSRS = poSrcLayer->GetSpatialRef();
+        }
+        else if( psInfo->iRequestedSrcGeomField > 0 )
+        {
+            poOutputSRS = poSrcLayer->GetLayerDefn()->GetGeomFieldDefn(
+                psInfo->iRequestedSrcGeomField)->GetSpatialRef();
+        }
+
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Transfer features.                                              */
+/* -------------------------------------------------------------------- */
+    OGRFeature  *poFeature;
+    int         nFeaturesInTransaction = 0;
+    GIntBig      nCount = 0; /* written + failed */
+    GIntBig      nFeaturesWritten = 0;
+
+    if( psOptions->nGroupTransactions )
+    {
+        if( psOptions->nLayerTransaction )
+        {
+            if( poDstLayer->StartTransaction() != OGRERR_NONE )
+                return false;
+        }
+    }
+
+    bool bRet = true;
+    while( true )
+    {
+        OGRFeature      *poDstFeature = NULL;
+
+        if( psOptions->nFIDToFetch != OGRNullFID )
+            poFeature = poSrcLayer->GetFeature(psOptions->nFIDToFetch);
+        else
+            poFeature = poSrcLayer->GetNextFeature();
+
+        if( poFeature == NULL )
+            break;
+
+        if( psInfo->nFeaturesRead == 0 || psInfo->bPerFeatureCT )
+        {
+            if( !SetupCT( psInfo, poSrcLayer, m_bTransform, m_bWrapDateline,
+                          m_osDateLineOffset, m_poUserSourceSRS,
+                          poFeature, poOutputSRS, m_poGCPCoordTrans) )
+            {
+                OGRFeature::DestroyFeature( poFeature );
+                return false;
+            }
+        }
+
+        psInfo->nFeaturesRead ++;
+
+        int nParts = 0;
+        int nIters = 1;
+        if (bExplodeCollections)
+        {
+            OGRGeometry* poSrcGeometry;
+            if( psInfo->iRequestedSrcGeomField >= 0 )
+                poSrcGeometry = poFeature->GetGeomFieldRef(
+                                        psInfo->iRequestedSrcGeomField);
+            else
+                poSrcGeometry = poFeature->GetGeometryRef();
+            if (poSrcGeometry &&
+                OGR_GT_IsSubClassOf(poSrcGeometry->getGeometryType(), wkbGeometryCollection) )
+            {
+                nParts = ((OGRGeometryCollection*)poSrcGeometry)->getNumGeometries();
+                nIters = nParts;
+                if (nIters == 0)
+                    nIters = 1;
+            }
+        }
+
+        for(int iPart = 0; iPart < nIters; iPart++)
+        {
+            if( ++nFeaturesInTransaction == psOptions->nGroupTransactions )
+            {
+                if( psOptions->nLayerTransaction )
+                {
+                    if( poDstLayer->CommitTransaction() != OGRERR_NONE ||
+                        poDstLayer->StartTransaction() != OGRERR_NONE )
+                    {
+                        OGRFeature::DestroyFeature( poFeature );
+                        return false;
+                    }
+                }
+                else
+                {
+                    if( m_poODS->CommitTransaction() != OGRERR_NONE ||
+                        m_poODS->StartTransaction(psOptions->bForceTransaction) != OGRERR_NONE )
+                    {
+                        OGRFeature::DestroyFeature( poFeature );
+                        return false;
+                    }
+                }
+                nFeaturesInTransaction = 0;
+            }
+
+            CPLErrorReset();
+            poDstFeature = OGRFeature::CreateFeature( poDstLayer->GetLayerDefn() );
+
+            /* Optimization to avoid duplicating the source geometry in the */
+            /* target feature : we steal it from the source feature for now... */
+            OGRGeometry* poStolenGeometry = NULL;
+            if( !bExplodeCollections && nSrcGeomFieldCount == 1 &&
+                nDstGeomFieldCount == 1 )
+            {
+                poStolenGeometry = poFeature->StealGeometry();
+            }
+            else if( !bExplodeCollections &&
+                     psInfo->iRequestedSrcGeomField >= 0 )
+            {
+                poStolenGeometry = poFeature->StealGeometry(
+                    psInfo->iRequestedSrcGeomField);
+            }
+
+            if( poDstFeature->SetFrom( poFeature, panMap, TRUE ) != OGRERR_NONE )
+            {
+                if( psOptions->nGroupTransactions )
+                {
+                    if( psOptions->nLayerTransaction )
+                    {
+                        if( poDstLayer->CommitTransaction() != OGRERR_NONE )
+                        {
+                            OGRFeature::DestroyFeature( poFeature );
+                            OGRFeature::DestroyFeature( poDstFeature );
+                            OGRGeometryFactory::destroyGeometry( poStolenGeometry );
+                            return false;
+                        }
+                    }
+                }
+
+                CPLError( CE_Failure, CPLE_AppDefined,
+                        "Unable to translate feature " CPL_FRMT_GIB " from layer %s.",
+                        poFeature->GetFID(), poSrcLayer->GetName() );
+
+                OGRFeature::DestroyFeature( poFeature );
+                OGRFeature::DestroyFeature( poDstFeature );
+                OGRGeometryFactory::destroyGeometry( poStolenGeometry );
+                return false;
+            }
+
+            /* ... and now we can attach the stolen geometry */
+            if( poStolenGeometry )
+            {
+                poDstFeature->SetGeometryDirectly(poStolenGeometry);
+            }
+
+            if( bPreserveFID )
+                poDstFeature->SetFID( poFeature->GetFID() );
+            else if( psInfo->iSrcFIDField >= 0 &&
+                     poFeature->IsFieldSet(psInfo->iSrcFIDField))
+                poDstFeature->SetFID( poFeature->GetFieldAsInteger64(psInfo->iSrcFIDField) );
+
+            /* Erase native data if asked explicitly */
+            if( !m_bNativeData )
+            {
+                poDstFeature->SetNativeData(NULL);
+                poDstFeature->SetNativeMediaType(NULL);
+            }
+
+            for( int iGeom = 0; iGeom < nDstGeomFieldCount; iGeom ++ )
+            {
+                OGRGeometry* poDstGeometry = poDstFeature->StealGeometry(iGeom);
+                if (poDstGeometry == NULL)
+                    continue;
+
+                if (nParts > 0)
+                {
+                    /* For -explodecollections, extract the iPart(th) of the geometry */
+                    OGRGeometry* poPart = ((OGRGeometryCollection*)poDstGeometry)->getGeometryRef(iPart);
+                    ((OGRGeometryCollection*)poDstGeometry)->removeGeometry(iPart, FALSE);
+                    delete poDstGeometry;
+                    poDstGeometry = poPart;
+                }
+
+                if (iSrcZField != -1)
+                {
+                    SetZ(poDstGeometry, poFeature->GetFieldAsDouble(iSrcZField));
+                    /* This will correct the coordinate dimension to 3 */
+                    OGRGeometry* poDupGeometry = poDstGeometry->clone();
+                    delete poDstGeometry;
+                    poDstGeometry = poDupGeometry;
+                }
+
+                if (m_nCoordDim == 2 || m_nCoordDim == 3)
+                    poDstGeometry->setCoordinateDimension( m_nCoordDim );
+                else if (m_nCoordDim == 4)
+                {
+                    poDstGeometry->set3D( TRUE );
+                    poDstGeometry->setMeasured( TRUE );
+                }
+                else if (m_nCoordDim == COORD_DIM_XYM)
+                {
+                    poDstGeometry->set3D( FALSE );
+                    poDstGeometry->setMeasured( TRUE );
+                }
+                else if ( m_nCoordDim == COORD_DIM_LAYER_DIM )
+                {
+                    const OGRwkbGeometryType eDstLayerGeomType =
+                      poDstLayer->GetLayerDefn()->GetGeomFieldDefn(iGeom)->GetType();
+                    poDstGeometry->set3D( wkbHasZ(eDstLayerGeomType) );
+                    poDstGeometry->setMeasured( wkbHasM(eDstLayerGeomType) );
+                }
+
+                if (m_eGeomOp == GEOMOP_SEGMENTIZE)
+                {
+                    if (m_dfGeomOpParam > 0)
+                        poDstGeometry->segmentize(m_dfGeomOpParam);
+                }
+                else if (m_eGeomOp == GEOMOP_SIMPLIFY_PRESERVE_TOPOLOGY)
+                {
+                    if (m_dfGeomOpParam > 0)
+                    {
+                        OGRGeometry* poNewGeom = poDstGeometry->SimplifyPreserveTopology(m_dfGeomOpParam);
+                        if (poNewGeom)
+                        {
+                            delete poDstGeometry;
+                            poDstGeometry = poNewGeom;
+                        }
+                    }
+                }
+
+                if (m_poClipSrc)
+                {
+                    OGRGeometry* poClipped = poDstGeometry->Intersection(m_poClipSrc);
+                    delete poDstGeometry;
+                    if (poClipped == NULL || poClipped->IsEmpty())
+                    {
+                        delete poClipped;
+                        goto end_loop;
+                    }
+                    poDstGeometry = poClipped;
+                }
+
+                OGRCoordinateTransformation* poCT = psInfo->papoCT[iGeom];
+                if( !m_bTransform )
+                    poCT = m_poGCPCoordTrans;
+                char** papszTransformOptions = psInfo->papapszTransformOptions[iGeom];
+
+                if( poCT != NULL || papszTransformOptions != NULL)
+                {
+                    OGRGeometry* poReprojectedGeom =
+                        OGRGeometryFactory::transformWithOptions(poDstGeometry, poCT, papszTransformOptions);
+                    if( poReprojectedGeom == NULL )
+                    {
+                        if( psOptions->nGroupTransactions )
+                        {
+                            if( psOptions->nLayerTransaction )
+                            {
+                                if( poDstLayer->CommitTransaction() != OGRERR_NONE &&
+                                    !psOptions->bSkipFailures )
+                                {
+                                    OGRFeature::DestroyFeature( poFeature );
+                                    OGRFeature::DestroyFeature( poDstFeature );
+                                    delete poDstGeometry;
+                                    return false;
+                                }
+                            }
+                        }
+
+                        CPLError( CE_Failure, CPLE_AppDefined, "Failed to reproject feature " CPL_FRMT_GIB " (geometry probably out of source or destination SRS).",
+                                  poFeature->GetFID() );
+                        if( !psOptions->bSkipFailures )
+                        {
+                            OGRFeature::DestroyFeature( poFeature );
+                            OGRFeature::DestroyFeature( poDstFeature );
+                            delete poDstGeometry;
+                            return false;
+                        }
+                    }
+
+                    delete poDstGeometry;
+                    poDstGeometry = poReprojectedGeom;
+                }
+                else if (poOutputSRS != NULL)
+                {
+                    poDstGeometry->assignSpatialReference(poOutputSRS);
+                }
+
+                if (m_poClipDst)
+                {
+                    if( poDstGeometry == NULL )
+                        goto end_loop;
+
+                    OGRGeometry* poClipped = poDstGeometry->Intersection(m_poClipDst);
+                    delete poDstGeometry;
+                    if (poClipped == NULL || poClipped->IsEmpty())
+                    {
+                        delete poClipped;
+                        goto end_loop;
+                    }
+
+                    poDstGeometry = poClipped;
+                }
+
+                if( eGType != GEOMTYPE_UNCHANGED )
+                {
+                    poDstGeometry = OGRGeometryFactory::forceTo(
+                            poDstGeometry, (OGRwkbGeometryType)eGType);
+                }
+                else if( m_eGeomTypeConversion == GTC_PROMOTE_TO_MULTI ||
+                         m_eGeomTypeConversion == GTC_CONVERT_TO_LINEAR ||
+                         m_eGeomTypeConversion == GTC_CONVERT_TO_CURVE )
+                {
+                    if( poDstGeometry != NULL )
+                    {
+                        OGRwkbGeometryType eTargetType = poDstGeometry->getGeometryType();
+                        eTargetType = ConvertType(m_eGeomTypeConversion, eTargetType);
+                        poDstGeometry = OGRGeometryFactory::forceTo(poDstGeometry, eTargetType);
+                    }
+                }
+
+                poDstFeature->SetGeomFieldDirectly(iGeom, poDstGeometry);
+            }
+
+            CPLErrorReset();
+            if( poDstLayer->CreateFeature( poDstFeature ) == OGRERR_NONE )
+            {
+                nFeaturesWritten ++;
+                if( (bPreserveFID && poDstFeature->GetFID() != poFeature->GetFID()) ||
+                    (!bPreserveFID && psInfo->iSrcFIDField >= 0 && poFeature->IsFieldSet(psInfo->iSrcFIDField) &&
+                     poDstFeature->GetFID() != poFeature->GetFieldAsInteger64(psInfo->iSrcFIDField)) )
+                {
+                    CPLError( CE_Warning, CPLE_AppDefined,
+                              "Feature id not preserved");
+                }
+            }
+            else if( !psOptions->bSkipFailures )
+            {
+                if( psOptions->nGroupTransactions )
+                {
+                    if( psOptions->nLayerTransaction )
+                        poDstLayer->RollbackTransaction();
+                }
+
+                CPLError( CE_Failure, CPLE_AppDefined,
+                        "Unable to write feature " CPL_FRMT_GIB " from layer %s.",
+                        poFeature->GetFID(), poSrcLayer->GetName() );
+
+                OGRFeature::DestroyFeature( poFeature );
+                OGRFeature::DestroyFeature( poDstFeature );
+                return false;
+            }
+            else
+            {
+                CPLDebug( "GDALVectorTranslate", "Unable to write feature " CPL_FRMT_GIB " into layer %s.",
+                           poFeature->GetFID(), poSrcLayer->GetName() );
+                if( psOptions->nGroupTransactions )
+                {
+                    if( psOptions->nLayerTransaction )
+                    {
+                        poDstLayer->RollbackTransaction();
+                        CPL_IGNORE_RET_VAL(poDstLayer->StartTransaction());
+                    }
+                    else
+                    {
+                        m_poODS->RollbackTransaction();
+                        m_poODS->StartTransaction(psOptions->bForceTransaction);
+                    }
+                }
+            }
+
+end_loop:
+            OGRFeature::DestroyFeature( poDstFeature );
+        }
+
+        OGRFeature::DestroyFeature( poFeature );
+
+        /* Report progress */
+        nCount ++;
+        bool bGoOn = true;
+        if (pfnProgress)
+        {
+            if (m_nSrcFileSize != 0)
+            {
+                if ((nCount % 1000) == 0)
+                {
+                    OGRLayer* poFCLayer = m_poSrcDS->ExecuteSQL("GetBytesRead()", NULL, NULL);
+                    if( poFCLayer != NULL )
+                    {
+                        OGRFeature* poFeat = poFCLayer->GetNextFeature();
+                        if( poFeat )
+                        {
+                            const char* pszReadSize = poFeat->GetFieldAsString(0);
+                            GUIntBig nReadSize = CPLScanUIntBig( pszReadSize, 32 );
+                            bGoOn = pfnProgress(nReadSize * 1.0 / m_nSrcFileSize, "", pProgressArg) != FALSE;
+                            OGRFeature::DestroyFeature( poFeat );
+                        }
+                    }
+                    m_poSrcDS->ReleaseResultSet(poFCLayer);
+                }
+            }
+            else
+            {
+                bGoOn = pfnProgress(nCount * 1.0 / nCountLayerFeatures, "", pProgressArg) != FALSE;
+            }
+        }
+        if( !bGoOn )
+        {
+            bRet = false;
+            break;
+        }
+
+        if (pnReadFeatureCount)
+            *pnReadFeatureCount = nCount;
+
+        if( psOptions->nFIDToFetch != OGRNullFID )
+            break;
+    }
+
+    if( psOptions->nGroupTransactions )
+    {
+        if( psOptions->nLayerTransaction )
+        {
+            if( poDstLayer->CommitTransaction() != OGRERR_NONE )
+                bRet = false;
+        }
+    }
+
+    CPLDebug("GDALVectorTranslate", CPL_FRMT_GIB " features written in layer '%s'",
+             nFeaturesWritten, poDstLayer->GetName());
+
+    return bRet;
+}
+
+/************************************************************************/
+/*                             RemoveBOM()                              */
+/************************************************************************/
+
+/* Remove potential UTF-8 BOM from data (must be NUL terminated) */
+static void RemoveBOM(GByte* pabyData)
+{
+    if( pabyData[0] == 0xEF && pabyData[1] == 0xBB && pabyData[2] == 0xBF )
+    {
+        memmove(pabyData, pabyData + 3, strlen((const char*)pabyData + 3) + 1);
+    }
+}
+
+/************************************************************************/
+/*                       GDALVectorTranslateOptionsNew()                */
+/************************************************************************/
+
+/**
+ * allocates a GDALVectorTranslateOptions struct.
+ *
+ * @param papszArgv NULL terminated list of options (potentially including filename and open options too), or NULL.
+ *                  The accepted options are the ones of the <a href="ogr2ogr.html">ogr2ogr</a> utility.
+ * @param psOptionsForBinary (output) may be NULL (and should generally be NULL),
+ *                           otherwise (gdal_translate_bin.cpp use case) must be allocated with
+ *                           GDALVectorTranslateOptionsForBinaryNew() prior to this function. Will be
+ *                           filled with potentially present filename, open options,...
+ * @return pointer to the allocated GDALVectorTranslateOptions struct. Must be freed with GDALVectorTranslateOptionsFree().
+ *
+ * @since GDAL 2.1
+ */
+GDALVectorTranslateOptions *GDALVectorTranslateOptionsNew(char** papszArgv,
+                                                      GDALVectorTranslateOptionsForBinary* psOptionsForBinary)
+{
+    GDALVectorTranslateOptions *psOptions = (GDALVectorTranslateOptions *) CPLCalloc( 1, sizeof(GDALVectorTranslateOptions) );
+
+    psOptions->eAccessMode = ACCESS_CREATION;
+    psOptions->bSkipFailures = false;
+    psOptions->nLayerTransaction = -1;
+    psOptions->bForceTransaction = false;
+    psOptions->nGroupTransactions = 20000;
+    psOptions->nFIDToFetch = OGRNullFID;
+    psOptions->bQuiet = false;
+    psOptions->pszFormat = CPLStrdup("ESRI Shapefile");
+    psOptions->papszLayers = NULL;
+    psOptions->papszDSCO = NULL;
+    psOptions->papszLCO = NULL;
+    psOptions->bTransform = false;
+    psOptions->bAddMissingFields = false;
+    psOptions->pszOutputSRSDef = NULL;
+    psOptions->pszSourceSRSDef = NULL;
+    psOptions->bNullifyOutputSRS = false;
+    psOptions->bExactFieldNameMatch = true;
+    psOptions->pszNewLayerName = NULL;
+    psOptions->pszWHERE = NULL;
+    psOptions->pszGeomField = NULL;
+    psOptions->papszSelFields = NULL;
+    psOptions->pszSQLStatement = NULL;
+    psOptions->pszDialect = NULL;
+    psOptions->eGType = GEOMTYPE_UNCHANGED;
+    psOptions->eGeomTypeConversion = GTC_DEFAULT;
+    psOptions->eGeomOp = GEOMOP_NONE;
+    psOptions->dfGeomOpParam = 0;
+    psOptions->papszFieldTypesToString = NULL;
+    psOptions->papszMapFieldType = NULL;
+    psOptions->bUnsetFieldWidth = false;
+    psOptions->bDisplayProgress = false;
+    psOptions->bWrapDateline = false;
+    psOptions->dfDateLineOffset = 10.0;
+    psOptions->bClipSrc = false;
+    psOptions->hClipSrc = NULL;
+    psOptions->pszClipSrcDS = NULL;
+    psOptions->pszClipSrcSQL = NULL;
+    psOptions->pszClipSrcLayer = NULL;
+    psOptions->pszClipSrcWhere = NULL;
+    psOptions->hClipDst = NULL;
+    psOptions->pszClipDstDS = NULL;
+    psOptions->pszClipDstSQL = NULL;
+    psOptions->pszClipDstLayer = NULL;
+    psOptions->pszClipDstWhere = NULL;
+    psOptions->bSplitListFields = false;
+    psOptions->nMaxSplitListSubFields = -1;
+    psOptions->bExplodeCollections = false;
+    psOptions->pszZField = NULL;
+    psOptions->papszFieldMap = NULL;
+    psOptions->nCoordDim = COORD_DIM_UNCHANGED;
+    psOptions->papszDestOpenOptions = NULL;
+    psOptions->bForceNullable = false;
+    psOptions->bUnsetDefault = false;
+    psOptions->bUnsetFid = false;
+    psOptions->bPreserveFID = false;
+    psOptions->bCopyMD = true;
+    psOptions->papszMetadataOptions = NULL;
+    psOptions->pszSpatSRSDef = NULL;
+    psOptions->nGCPCount = 0;
+    psOptions->pasGCPs = NULL;
+    psOptions->nTransformOrder = 0;  /* Default to 0 for now... let the lib decide */
+    psOptions->hSpatialFilter = NULL;
+    psOptions->bNativeData = true;
+
+    int nArgc = CSLCount(papszArgv);
+    for( int i = 0; i < nArgc; i++ )
+    {
+        if( EQUAL(papszArgv[i],"-q") || EQUAL(papszArgv[i],"-quiet") )
+        {
+            if( psOptionsForBinary )
+                psOptionsForBinary->bQuiet = TRUE;
+        }
+        else if( EQUAL(papszArgv[i],"-f") && i+1 < nArgc )
+        {
+            CPLFree(psOptions->pszFormat);
+            psOptions->pszFormat = CPLStrdup(papszArgv[++i]);
+            if( psOptionsForBinary )
+            {
+                psOptionsForBinary->bFormatExplicitlySet = TRUE;
+            }
+        }
+        else if( EQUAL(papszArgv[i],"-dsco") && i+1 < nArgc )
+        {
+            psOptions->papszDSCO = CSLAddString(psOptions->papszDSCO, papszArgv[++i] );
+        }
+        else if( EQUAL(papszArgv[i],"-lco") && i+1 < nArgc )
+        {
+            psOptions->papszLCO = CSLAddString(psOptions->papszLCO, papszArgv[++i] );
+        }
+        else if( EQUAL(papszArgv[i],"-oo") && i+1 < nArgc )
+        {
+            ++i;
+            if( psOptionsForBinary )
+            {
+                psOptionsForBinary->papszOpenOptions = CSLAddString(psOptionsForBinary->papszOpenOptions, papszArgv[i] );
+            }
+        }
+        else if( EQUAL(papszArgv[i],"-doo") && i+1 < nArgc )
+        {
+            ++i;
+            psOptions->papszDestOpenOptions = CSLAddString(psOptions->papszDestOpenOptions, papszArgv[i] );
+        }
+        else if( EQUAL(papszArgv[i],"-preserve_fid") )
+        {
+            psOptions->bPreserveFID = true;
+        }
+        else if( STARTS_WITH_CI(papszArgv[i], "-skip") )
+        {
+            psOptions->bSkipFailures = true;
+            psOptions->nGroupTransactions = 1; /* #2409 */
+        }
+        else if( EQUAL(papszArgv[i],"-append") )
+        {
+            psOptions->eAccessMode = ACCESS_APPEND;
+        }
+        else if( EQUAL(papszArgv[i],"-overwrite") )
+        {
+            psOptions->eAccessMode = ACCESS_OVERWRITE;
+        }
+        else if( EQUAL(papszArgv[i],"-addfields") )
+        {
+            psOptions->bAddMissingFields = true;
+            psOptions->eAccessMode = ACCESS_APPEND;
+        }
+        else if( EQUAL(papszArgv[i],"-update") )
+        {
+            psOptions->eAccessMode = ACCESS_UPDATE;
+        }
+        else if( EQUAL(papszArgv[i],"-relaxedFieldNameMatch") )
+        {
+            psOptions->bExactFieldNameMatch = false;
+        }
+        else if( EQUAL(papszArgv[i],"-fid") && i+1 < nArgc )
+        {
+            psOptions->nFIDToFetch = CPLAtoGIntBig(papszArgv[++i]);
+        }
+        else if( EQUAL(papszArgv[i],"-sql") && i+1 < nArgc )
+        {
+            i++;
+            CPLFree(psOptions->pszSQLStatement);
+            GByte* pabyRet = NULL;
+            if( papszArgv[i][0] == '@' &&
+                VSIIngestFile( NULL, papszArgv[i] + 1, &pabyRet, NULL, 1024*1024) )
+            {
+                RemoveBOM(pabyRet);
+                psOptions->pszSQLStatement = (char*)pabyRet;
+            }
+            else
+            {
+                psOptions->pszSQLStatement = CPLStrdup(papszArgv[i]);
+            }
+        }
+        else if( EQUAL(papszArgv[i],"-dialect") && i+1 < nArgc )
+        {
+            CPLFree(psOptions->pszDialect);
+            psOptions->pszDialect = CPLStrdup(papszArgv[++i]);
+        }
+        else if( EQUAL(papszArgv[i],"-nln") && i+1 < nArgc )
+        {
+            CPLFree(psOptions->pszNewLayerName);
+            psOptions->pszNewLayerName = CPLStrdup(papszArgv[++i]);
+        }
+        else if( EQUAL(papszArgv[i],"-nlt") && i+1 < nArgc )
+        {
+            bool bIs3D = false;
+            CPLString osGeomName = papszArgv[i+1];
+            if (strlen(papszArgv[i+1]) > 3 &&
+                STARTS_WITH_CI(papszArgv[i+1] + strlen(papszArgv[i+1]) - 3, "25D"))
+            {
+                bIs3D = true;
+                osGeomName.resize(osGeomName.size() - 3);
+            }
+            else if (strlen(papszArgv[i+1]) > 1 &&
+                STARTS_WITH_CI(papszArgv[i+1] + strlen(papszArgv[i+1]) - 1, "Z"))
+            {
+                bIs3D = true;
+                osGeomName.resize(osGeomName.size() - 1);
+            }
+            if( EQUAL(osGeomName,"NONE") )
+                psOptions->eGType = wkbNone;
+            else if( EQUAL(osGeomName,"GEOMETRY") )
+                psOptions->eGType = wkbUnknown;
+            else if( EQUAL(osGeomName,"PROMOTE_TO_MULTI") )
+                psOptions->eGeomTypeConversion = GTC_PROMOTE_TO_MULTI;
+            else if( EQUAL(osGeomName,"CONVERT_TO_LINEAR") )
+                psOptions->eGeomTypeConversion = GTC_CONVERT_TO_LINEAR;
+            else if( EQUAL(osGeomName,"CONVERT_TO_CURVE") )
+                psOptions->eGeomTypeConversion = GTC_CONVERT_TO_CURVE;
+            else
+            {
+                psOptions->eGType = OGRFromOGCGeomType(osGeomName);
+                if (psOptions->eGType == wkbUnknown)
+                {
+                    CPLError(CE_Failure, CPLE_IllegalArg,
+                             "-nlt %s: type not recognised.",
+                            papszArgv[i+1] );
+                    GDALVectorTranslateOptionsFree(psOptions);
+                    return NULL;
+                }
+            }
+            if (psOptions->eGType != GEOMTYPE_UNCHANGED && psOptions->eGType != wkbNone && bIs3D)
+                psOptions->eGType = wkbSetZ((OGRwkbGeometryType)psOptions->eGType);
+
+            i++;
+        }
+        else if( EQUAL(papszArgv[i],"-dim") && i+1 < nArgc )
+        {
+            if( EQUAL(papszArgv[i+1], "layer_dim") )
+                psOptions->nCoordDim = COORD_DIM_LAYER_DIM;
+            else if( EQUAL(papszArgv[i+1], "XY") || EQUAL(papszArgv[i+1], "2") )
+                psOptions->nCoordDim = 2;
+            else if( EQUAL(papszArgv[i+1], "XYZ") || EQUAL(papszArgv[i+1], "3") )
+                psOptions->nCoordDim = 3;
+            else if( EQUAL(papszArgv[i+1], "XYM") )
+                psOptions->nCoordDim = COORD_DIM_XYM;
+            else if( EQUAL(papszArgv[i+1], "XYZM") )
+                psOptions->nCoordDim = 4;
+            else
+            {
+                CPLError(CE_Failure, CPLE_IllegalArg,"-dim %s: value not handled.",
+                         papszArgv[i+1] );
+                GDALVectorTranslateOptionsFree(psOptions);
+                return NULL;
+            }
+            i++;
+        }
+        else if( (EQUAL(papszArgv[i],"-tg") ||
+                 EQUAL(papszArgv[i],"-gt")) && i+1 < nArgc )
+        {
+            ++i;
+            /* If skipfailures is already set we should not
+               modify nGroupTransactions = 1  #2409 */
+            if ( !psOptions->bSkipFailures )
+            {
+                if( EQUAL(papszArgv[i], "unlimited") )
+                    psOptions->nGroupTransactions = -1;
+                else
+                    psOptions->nGroupTransactions = atoi(papszArgv[i]);
+            }
+        }
+        else if ( EQUAL(papszArgv[i],"-ds_transaction") )
+        {
+            psOptions->nLayerTransaction = FALSE;
+            psOptions->bForceTransaction = true;
+        }
+        /* Undocumented. Just a provision. Default behaviour should be OK */
+        else if ( EQUAL(papszArgv[i],"-lyr_transaction") )
+        {
+            psOptions->nLayerTransaction = TRUE;
+        }
+        else if( EQUAL(papszArgv[i],"-s_srs") && i+1 < nArgc )
+        {
+            CPLFree(psOptions->pszSourceSRSDef);
+            psOptions->pszSourceSRSDef = CPLStrdup(papszArgv[++i]);
+        }
+        else if( EQUAL(papszArgv[i],"-a_srs") && i+1 < nArgc )
+        {
+            CPLFree(psOptions->pszOutputSRSDef);
+            psOptions->pszOutputSRSDef = CPLStrdup(papszArgv[++i]);
+            if (EQUAL(psOptions->pszOutputSRSDef, "NULL") ||
+                EQUAL(psOptions->pszOutputSRSDef, "NONE"))
+            {
+                psOptions->pszOutputSRSDef = NULL;
+                psOptions->bNullifyOutputSRS = true;
+            }
+        }
+        else if( EQUAL(papszArgv[i],"-t_srs") && i+1 < nArgc )
+        {
+            CPLFree(psOptions->pszOutputSRSDef);
+            psOptions->pszOutputSRSDef = CPLStrdup(papszArgv[++i]);
+            psOptions->bTransform = true;
+        }
+        else if( EQUAL(papszArgv[i],"-spat") && i+4 < nArgc )
+        {
+            OGRLinearRing  oRing;
+
+            oRing.addPoint( CPLAtof(papszArgv[i+1]), CPLAtof(papszArgv[i+2]) );
+            oRing.addPoint( CPLAtof(papszArgv[i+1]), CPLAtof(papszArgv[i+4]) );
+            oRing.addPoint( CPLAtof(papszArgv[i+3]), CPLAtof(papszArgv[i+4]) );
+            oRing.addPoint( CPLAtof(papszArgv[i+3]), CPLAtof(papszArgv[i+2]) );
+            oRing.addPoint( CPLAtof(papszArgv[i+1]), CPLAtof(papszArgv[i+2]) );
+
+            OGRPolygon* poSpatialFilter = (OGRPolygon*) OGRGeometryFactory::createGeometry(wkbPolygon);
+            poSpatialFilter->addRing( &oRing );
+            OGR_G_DestroyGeometry(psOptions->hSpatialFilter);
+            psOptions->hSpatialFilter = (OGRGeometryH) poSpatialFilter;
+            i += 4;
+        }
+        else if( EQUAL(papszArgv[i],"-spat_srs") && i+1 < nArgc )
+        {
+            CPLFree(psOptions->pszSpatSRSDef);
+            psOptions->pszSpatSRSDef = CPLStrdup(papszArgv[++i]);
+        }
+        else if( EQUAL(papszArgv[i],"-geomfield") && i+1 < nArgc )
+        {
+            CPLFree(psOptions->pszGeomField);
+            psOptions->pszGeomField = CPLStrdup(papszArgv[++i]);
+        }
+        else if( EQUAL(papszArgv[i],"-where") && i+1 < nArgc )
+        {
+            i++;
+            CPLFree(psOptions->pszWHERE);
+            GByte* pabyRet = NULL;
+            if( papszArgv[i][0] == '@' &&
+                VSIIngestFile( NULL, papszArgv[i] + 1, &pabyRet, NULL, 1024*1024) )
+            {
+                RemoveBOM(pabyRet);
+                psOptions->pszWHERE = (char*)pabyRet;
+            }
+            else
+            {
+                psOptions->pszWHERE = CPLStrdup(papszArgv[i]);
+            }
+        }
+        else if( EQUAL(papszArgv[i],"-select") && i+1 < nArgc )
+        {
+            const char* pszSelect = papszArgv[++i];
+            CSLDestroy(psOptions->papszSelFields);
+            psOptions->papszSelFields = CSLTokenizeStringComplex(pszSelect, " ,",
+                                                      FALSE, FALSE );
+        }
+        else if( EQUAL(papszArgv[i],"-segmentize") && i+1 < nArgc )
+        {
+            psOptions->eGeomOp = GEOMOP_SEGMENTIZE;
+            psOptions->dfGeomOpParam = CPLAtof(papszArgv[++i]);
+        }
+        else if( EQUAL(papszArgv[i],"-simplify") && i+1 < nArgc )
+        {
+            psOptions->eGeomOp = GEOMOP_SIMPLIFY_PRESERVE_TOPOLOGY;
+            psOptions->dfGeomOpParam = CPLAtof(papszArgv[++i]);
+        }
+        else if( EQUAL(papszArgv[i],"-fieldTypeToString") && i+1 < nArgc )
+        {
+            CSLDestroy(psOptions->papszFieldTypesToString);
+            psOptions->papszFieldTypesToString =
+                    CSLTokenizeStringComplex(papszArgv[++i], " ,",
+                                             FALSE, FALSE );
+            char** iter = psOptions->papszFieldTypesToString;
+            while(*iter)
+            {
+                if (IsFieldType(*iter))
+                {
+                    /* Do nothing */
+                }
+                else if (EQUAL(*iter, "All"))
+                {
+                    CSLDestroy(psOptions->papszFieldTypesToString);
+                    psOptions->papszFieldTypesToString = NULL;
+                    psOptions->papszFieldTypesToString = CSLAddString(psOptions->papszFieldTypesToString, "All");
+                    break;
+                }
+                else
+                {
+                    CPLError(CE_Failure, CPLE_IllegalArg,
+                             "Unhandled type for fieldTypeToString option : %s",
+                            *iter);
+                    GDALVectorTranslateOptionsFree(psOptions);
+                    return NULL;
+                }
+                iter ++;
+            }
+        }
+        else if( EQUAL(papszArgv[i],"-mapFieldType") && i+1 < nArgc )
+        {
+            CSLDestroy(psOptions->papszMapFieldType);
+            psOptions->papszMapFieldType =
+                    CSLTokenizeStringComplex(papszArgv[++i], " ,",
+                                             FALSE, FALSE );
+            char** iter = psOptions->papszMapFieldType;
+            while(*iter)
+            {
+                char* pszKey = NULL;
+                const char* pszValue = CPLParseNameValue(*iter, &pszKey);
+                if( pszKey && pszValue)
+                {
+                    if( !((IsFieldType(pszKey) || EQUAL(pszKey, "All")) && IsFieldType(pszValue)) )
+                    {
+                        CPLError(CE_Failure, CPLE_IllegalArg,
+                                "Invalid value for -mapFieldType : %s",
+                                *iter);
+                        CPLFree(pszKey);
+                        GDALVectorTranslateOptionsFree(psOptions);
+                        return NULL;
+                    }
+                }
+                CPLFree(pszKey);
+                iter ++;
+            }
+        }
+        else if( EQUAL(papszArgv[i],"-unsetFieldWidth") )
+        {
+            psOptions->bUnsetFieldWidth = true;
+        }
+        else if( EQUAL(papszArgv[i],"-progress") )
+        {
+            psOptions->bDisplayProgress = true;
+        }
+        else if( EQUAL(papszArgv[i],"-wrapdateline") )
+        {
+            psOptions->bWrapDateline = true;
+        }
+        else if( EQUAL(papszArgv[i],"-datelineoffset") && i < nArgc-1 )
+        {
+            psOptions->dfDateLineOffset = CPLAtof(papszArgv[++i]);
+        }
+        else if( EQUAL(papszArgv[i],"-clipsrc") )
+        {
+            if (i + 1 >= nArgc)
+            {
+                CPLError(CE_Failure, CPLE_IllegalArg, "%s option requires 1 or 4 arguments", papszArgv[i]);
+                GDALVectorTranslateOptionsFree(psOptions);
+                return NULL;
+            }
+
+            VSIStatBufL  sStat;
+            psOptions->bClipSrc = true;
+            if ( IsNumber(papszArgv[i+1])
+                 && papszArgv[i+2] != NULL
+                 && papszArgv[i+3] != NULL
+                 && papszArgv[i+4] != NULL)
+            {
+                OGRLinearRing  oRing;
+
+                oRing.addPoint( CPLAtof(papszArgv[i+1]), CPLAtof(papszArgv[i+2]) );
+                oRing.addPoint( CPLAtof(papszArgv[i+1]), CPLAtof(papszArgv[i+4]) );
+                oRing.addPoint( CPLAtof(papszArgv[i+3]), CPLAtof(papszArgv[i+4]) );
+                oRing.addPoint( CPLAtof(papszArgv[i+3]), CPLAtof(papszArgv[i+2]) );
+                oRing.addPoint( CPLAtof(papszArgv[i+1]), CPLAtof(papszArgv[i+2]) );
+
+                OGR_G_DestroyGeometry(psOptions->hClipSrc);
+                psOptions->hClipSrc = (OGRGeometryH) OGRGeometryFactory::createGeometry(wkbPolygon);
+                ((OGRPolygon *) psOptions->hClipSrc)->addRing( &oRing );
+                i += 4;
+            }
+            else if ((STARTS_WITH_CI(papszArgv[i+1], "POLYGON") ||
+                      STARTS_WITH_CI(papszArgv[i+1], "MULTIPOLYGON")) &&
+                      VSIStatL(papszArgv[i+1], &sStat) != 0)
+            {
+                char* pszTmp = (char*) papszArgv[i+1];
+                OGR_G_DestroyGeometry(psOptions->hClipSrc);
+                OGRGeometryFactory::createFromWkt(&pszTmp, NULL, (OGRGeometry **)&psOptions->hClipSrc);
+                if (psOptions->hClipSrc == NULL)
+                {
+                    CPLError(CE_Failure, CPLE_IllegalArg,
+                             "Invalid geometry. Must be a valid POLYGON or MULTIPOLYGON WKT");
+                    GDALVectorTranslateOptionsFree(psOptions);
+                    return NULL;
+                }
+                i ++;
+            }
+            else if (EQUAL(papszArgv[i+1], "spat_extent") )
+            {
+                i ++;
+            }
+            else
+            {
+                CPLFree(psOptions->pszClipSrcDS);
+                psOptions->pszClipSrcDS = CPLStrdup(papszArgv[i+1]);
+                i ++;
+            }
+        }
+        else if( EQUAL(papszArgv[i],"-clipsrcsql") && i+1 < nArgc )
+        {
+            CPLFree(psOptions->pszClipSrcSQL);
+            psOptions->pszClipSrcSQL = CPLStrdup(papszArgv[i+1]);
+            i ++;
+        }
+        else if( EQUAL(papszArgv[i],"-clipsrclayer") && i+1 < nArgc )
+        {
+            CPLFree(psOptions->pszClipSrcLayer);
+            psOptions->pszClipSrcLayer = CPLStrdup(papszArgv[i+1]);
+            i ++;
+        }
+        else if( EQUAL(papszArgv[i],"-clipsrcwhere") && i+1 < nArgc )
+        {
+            CPLFree(psOptions->pszClipSrcWhere);
+            psOptions->pszClipSrcWhere = CPLStrdup(papszArgv[i+1]);
+            i ++;
+        }
+        else if( EQUAL(papszArgv[i],"-clipdst") )
+        {
+            if (i + 1 >= nArgc)
+            {
+                CPLError(CE_Failure, CPLE_IllegalArg, "%s option requires 1 or 4 arguments", papszArgv[i]);
+                GDALVectorTranslateOptionsFree(psOptions);
+                return NULL;
+            }
+
+            VSIStatBufL  sStat;
+            if ( IsNumber(papszArgv[i+1])
+                 && papszArgv[i+2] != NULL
+                 && papszArgv[i+3] != NULL
+                 && papszArgv[i+4] != NULL)
+            {
+                OGRLinearRing  oRing;
+
+                oRing.addPoint( CPLAtof(papszArgv[i+1]), CPLAtof(papszArgv[i+2]) );
+                oRing.addPoint( CPLAtof(papszArgv[i+1]), CPLAtof(papszArgv[i+4]) );
+                oRing.addPoint( CPLAtof(papszArgv[i+3]), CPLAtof(papszArgv[i+4]) );
+                oRing.addPoint( CPLAtof(papszArgv[i+3]), CPLAtof(papszArgv[i+2]) );
+                oRing.addPoint( CPLAtof(papszArgv[i+1]), CPLAtof(papszArgv[i+2]) );
+
+                OGR_G_DestroyGeometry(psOptions->hClipDst);
+                psOptions->hClipDst = (OGRGeometryH) OGRGeometryFactory::createGeometry(wkbPolygon);
+                ((OGRPolygon *) psOptions->hClipDst)->addRing( &oRing );
+                i += 4;
+            }
+            else if ((STARTS_WITH_CI(papszArgv[i+1], "POLYGON") ||
+                      STARTS_WITH_CI(papszArgv[i+1], "MULTIPOLYGON")) &&
+                      VSIStatL(papszArgv[i+1], &sStat) != 0)
+            {
+                char* pszTmp = (char*) papszArgv[i+1];
+                OGR_G_DestroyGeometry(psOptions->hClipDst);
+                OGRGeometryFactory::createFromWkt(&pszTmp, NULL, (OGRGeometry **)&psOptions->hClipDst);
+                if (psOptions->hClipDst == NULL)
+                {
+                    CPLError(CE_Failure, CPLE_IllegalArg,
+                             "Invalid geometry. Must be a valid POLYGON or MULTIPOLYGON WKT");
+                    GDALVectorTranslateOptionsFree(psOptions);
+                    return NULL;
+                }
+                i ++;
+            }
+            else
+            {
+                CPLFree(psOptions->pszClipDstDS);
+                psOptions->pszClipDstDS = CPLStrdup(papszArgv[i+1]);
+                i ++;
+            }
+        }
+        else if( EQUAL(papszArgv[i],"-clipdstsql") && i+1 < nArgc )
+        {
+            CPLFree(psOptions->pszClipDstSQL);
+            psOptions->pszClipDstSQL = CPLStrdup(papszArgv[i+1]);
+            i ++;
+        }
+        else if( EQUAL(papszArgv[i],"-clipdstlayer") && i+1 < nArgc )
+        {
+            CPLFree(psOptions->pszClipDstLayer);
+            psOptions->pszClipDstLayer = CPLStrdup(papszArgv[i+1]);
+            i ++;
+        }
+        else if( EQUAL(papszArgv[i],"-clipdstwhere") && i+1 < nArgc )
+        {
+            CPLFree(psOptions->pszClipDstWhere);
+            psOptions->pszClipDstWhere = CPLStrdup(papszArgv[i+1]);
+            i ++;
+        }
+        else if( EQUAL(papszArgv[i],"-splitlistfields") )
+        {
+            psOptions->bSplitListFields = true;
+        }
+        else if ( EQUAL(papszArgv[i],"-maxsubfields") && i+1 < nArgc )
+        {
+            if (IsNumber(papszArgv[i+1]))
+            {
+                int nTemp = atoi(papszArgv[i+1]);
+                if (nTemp > 0)
+                {
+                    psOptions->nMaxSplitListSubFields = nTemp;
+                    i ++;
+                }
+            }
+        }
+        else if( EQUAL(papszArgv[i],"-explodecollections") )
+        {
+            psOptions->bExplodeCollections = true;
+        }
+        else if( EQUAL(papszArgv[i],"-zfield") && i+1 < nArgc )
+        {
+            CPLFree(psOptions->pszZField);
+            psOptions->pszZField = CPLStrdup(papszArgv[i+1]);
+            i ++;
+        }
+        else if( EQUAL(papszArgv[i],"-gcp") && i+4 < nArgc )
+        {
+            char* endptr = NULL;
+            /* -gcp pixel line easting northing [elev] */
+
+            psOptions->nGCPCount++;
+            psOptions->pasGCPs = (GDAL_GCP *)
+                CPLRealloc( psOptions->pasGCPs, sizeof(GDAL_GCP) * psOptions->nGCPCount );
+            GDALInitGCPs( 1, psOptions->pasGCPs + psOptions->nGCPCount - 1 );
+
+            psOptions->pasGCPs[psOptions->nGCPCount-1].dfGCPPixel = CPLAtof(papszArgv[++i]);
+            psOptions->pasGCPs[psOptions->nGCPCount-1].dfGCPLine = CPLAtof(papszArgv[++i]);
+            psOptions->pasGCPs[psOptions->nGCPCount-1].dfGCPX = CPLAtof(papszArgv[++i]);
+            psOptions->pasGCPs[psOptions->nGCPCount-1].dfGCPY = CPLAtof(papszArgv[++i]);
+            if( papszArgv[i+1] != NULL
+                && (CPLStrtod(papszArgv[i+1], &endptr) != 0.0 || papszArgv[i+1][0] == '0') )
+            {
+                /* Check that last argument is really a number and not a filename */
+                /* looking like a number (see ticket #863) */
+                if (endptr && *endptr == 0)
+                    psOptions->pasGCPs[psOptions->nGCPCount-1].dfGCPZ = CPLAtof(papszArgv[++i]);
+            }
+
+            /* should set id and info? */
+        }
+        else if( EQUAL(papszArgv[i],"-tps") )
+        {
+            psOptions->nTransformOrder = -1;
+        }
+        else if( EQUAL(papszArgv[i],"-order") && i+1 < nArgc )
+        {
+            psOptions->nTransformOrder = atoi( papszArgv[++i] );
+        }
+        else if( EQUAL(papszArgv[i],"-fieldmap") && i+1 < nArgc )
+        {
+            CSLDestroy(psOptions->papszFieldMap);
+            psOptions->papszFieldMap = CSLTokenizeStringComplex(papszArgv[++i], ",",
+                                                      FALSE, FALSE );
+        }
+        else if( EQUAL(papszArgv[i],"-forceNullable") )
+        {
+            psOptions->bForceNullable = true;
+        }
+        else if( EQUAL(papszArgv[i],"-unsetDefault") )
+        {
+            psOptions->bUnsetDefault = true;
+        }
+        else if( EQUAL(papszArgv[i],"-unsetFid") )
+        {
+            psOptions->bUnsetFid = true;
+        }
+        else if( EQUAL(papszArgv[i],"-nomd") )
+        {
+            psOptions->bCopyMD = false;
+        }
+        else if( EQUAL(papszArgv[i],"-noNativeData") )
+        {
+            psOptions->bNativeData = false;
+        }
+        else if( EQUAL(papszArgv[i],"-mo") && i+1 < nArgc )
+        {
+            psOptions->papszMetadataOptions = CSLAddString( psOptions->papszMetadataOptions,
+                                                 papszArgv[++i] );
+        }
+        else if( papszArgv[i][0] == '-' )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unknown option name '%s'", papszArgv[i]);
+            GDALVectorTranslateOptionsFree(psOptions);
+            return NULL;
+        }
+        else if( psOptionsForBinary && psOptionsForBinary->pszDestDataSource == NULL )
+            psOptionsForBinary->pszDestDataSource = CPLStrdup(papszArgv[i]);
+        else if(  psOptionsForBinary && psOptionsForBinary->pszDataSource == NULL )
+            psOptionsForBinary->pszDataSource = CPLStrdup(papszArgv[i]);
+        else
+            psOptions->papszLayers = CSLAddString( psOptions->papszLayers, papszArgv[i] );
+    }
+
+    if( psOptionsForBinary )
+    {
+        psOptionsForBinary->pszFormat = CPLStrdup(psOptions->pszFormat);
+        psOptionsForBinary->eAccessMode = psOptions->eAccessMode;
+
+        if( !(CPLTestBool(CSLFetchNameValueDef(
+                psOptionsForBinary->papszOpenOptions, "NATIVE_DATA",
+                CSLFetchNameValueDef(
+                    psOptionsForBinary->papszOpenOptions, "@NATIVE_DATA", "TRUE")))) )
+        {
+            psOptions->bNativeData = false;
+        }
+
+        if( psOptions->bNativeData &&
+            CSLFetchNameValue(psOptionsForBinary->papszOpenOptions,
+                              "NATIVE_DATA") == NULL &&
+            CSLFetchNameValue(psOptionsForBinary->papszOpenOptions,
+                              "@NATIVE_DATA") == NULL )
+        {
+            psOptionsForBinary->papszOpenOptions = CSLAddString(
+                psOptionsForBinary->papszOpenOptions, "@NATIVE_DATA=YES" );
+        }
+    }
+
+    return psOptions;
+}
+
+/************************************************************************/
+/*                      GDALVectorTranslateOptionsFree()                */
+/************************************************************************/
+
+/**
+ * Frees the GDALVectorTranslateOptions struct.
+ *
+ * @param psOptions the options struct for GDALVectorTranslate().
+ * @since GDAL 2.1
+ */
+
+void GDALVectorTranslateOptionsFree( GDALVectorTranslateOptions *psOptions )
+{
+    if( psOptions == NULL )
+        return;
+
+    CPLFree( psOptions->pszFormat );
+    CPLFree( psOptions->pszOutputSRSDef);
+    CPLFree( psOptions->pszSourceSRSDef);
+    CPLFree( psOptions->pszNewLayerName);
+    CPLFree( psOptions->pszWHERE );
+    CPLFree( psOptions->pszGeomField );
+    CPLFree( psOptions->pszSQLStatement );
+    CPLFree( psOptions->pszDialect );
+    CPLFree( psOptions->pszClipSrcDS );
+    CPLFree( psOptions->pszClipSrcSQL );
+    CPLFree( psOptions->pszClipSrcLayer );
+    CPLFree( psOptions->pszClipSrcWhere );
+    CPLFree( psOptions->pszClipDstDS );
+    CPLFree( psOptions->pszClipDstSQL );
+    CPLFree( psOptions->pszClipDstLayer );
+    CPLFree( psOptions->pszClipDstWhere );
+    CPLFree( psOptions->pszZField );
+    CPLFree( psOptions->pszSpatSRSDef );
+    CSLDestroy(psOptions->papszSelFields);
+    CSLDestroy( psOptions->papszFieldMap );
+    CSLDestroy( psOptions->papszMapFieldType );
+    CSLDestroy( psOptions->papszLayers );
+    CSLDestroy( psOptions->papszDSCO );
+    CSLDestroy( psOptions->papszLCO );
+    CSLDestroy( psOptions->papszDestOpenOptions );
+    CSLDestroy( psOptions->papszFieldTypesToString );
+    CSLDestroy( psOptions->papszMetadataOptions );
+
+    if( psOptions->pasGCPs != NULL )
+    {
+        GDALDeinitGCPs( psOptions->nGCPCount, psOptions->pasGCPs );
+        CPLFree( psOptions->pasGCPs );
+    }
+
+    if( psOptions->hClipSrc != NULL )
+        OGR_G_DestroyGeometry( psOptions->hClipSrc );
+    if( psOptions->hClipDst != NULL )
+        OGR_G_DestroyGeometry( psOptions->hClipDst );
+    if( psOptions->hSpatialFilter != NULL )
+        OGR_G_DestroyGeometry( psOptions->hSpatialFilter );
+
+    CPLFree(psOptions);
+}
+
+/************************************************************************/
+/*                 GDALVectorTranslateOptionsSetProgress()              */
+/************************************************************************/
+
+/**
+ * Set a progress function.
+ *
+ * @param psOptions the options struct for GDALVectorTranslate().
+ * @param pfnProgress the progress callback.
+ * @param pProgressData the user data for the progress callback.
+ *
+ * @since GDAL 2.1
+ */
+
+void GDALVectorTranslateOptionsSetProgress( GDALVectorTranslateOptions *psOptions,
+                                      GDALProgressFunc pfnProgress, void *pProgressData )
+{
+    psOptions->pfnProgress = pfnProgress ? pfnProgress : GDALDummyProgress;
+    psOptions->pProgressData = pProgressData;
+    if( pfnProgress == GDALTermProgress )
+        psOptions->bQuiet = false;
+}
diff --git a/apps/ogr_utilities.dox b/apps/ogr_utilities.dox
index 8f1495a..8e8cc4b 100644
--- a/apps/ogr_utilities.dox
+++ b/apps/ogr_utilities.dox
@@ -11,6 +11,57 @@ toolkit:
 <li> \ref ogrlineref - Create linear reference and provide some calculations using it
 </ul>
 
+\section gdal_utilities_switches General Command Line Switches
+All GDAL OGR command line utility programs support the following 
+"general" options.<p>
+
+<dl>
+<dt> <b>\-\-version</b></dt><dd> Report the version of GDAL and exit.</dd>
+
+<dt> <b>\-\-formats</b></dt><dd> List all vector formats supported by this
+GDAL build (read-only and read-write) and exit. The format support is indicated
+ as follows: 'ro' is read-only driver; 
+'rw' is read or write (i.e. supports CreateCopy);
+'rw+' is read, write and update (i.e. supports Create).
+A 'v' is appended for formats supporting virtual IO (/vsimem, /vsigzip, /vsizip, etc).
+A 's' is appended for formats supporting subdatasets.
+</dd>
+
+<dt> <b>\-\-format</b> <i>format</i></dt><dd>
+List detailed information about a single format driver.  The <i>format</i> 
+should be the short name reported in the <b>\-\-formats</b> list, such as 
+GML.</dd>
+
+<dt> <b>\-\-optfile</b> <i>file</i></dt><dd>
+Read the named file and substitute the contents into the command line
+options list.  Lines beginning with # will be ignored.  Multi-word arguments
+may be kept together with double quotes. 
+</dd>
+
+<dt> <b>\-\-config</b> <i>key value</i></dt><dd>
+Sets the named <a href="http://trac.osgeo.org/gdal/wiki/ConfigOptions">
+configuration keyword</a> to the given value, as opposed to 
+setting them as environment variables.  Some common configuration keywords
+are SHAPE_ENCODING (force shapefile driver to read DBF files with the given
+character encoding) and CPL_TEMPDIR (define the location of temporary files).
+Individual drivers may be influenced by other configuration options.  
+</dd>
+
+<dt> <b>\-\-debug</b> <i>value</i></dt><dd>
+Control what debugging messages are emitted.  A value of <i>ON</i> will
+enable all debug messages.  A value of <i>OFF</i> will disable all debug
+messages.  Another value will select only debug messages containing that
+string in the debug prefix code.  
+</dd>
+
+<dt> <b>\-\-help-general</b></dt><dd>
+Gives a brief usage message for the generic GDAL OGR command line options 
+and exit.
+</dd>
+
+</dl>
+
+
 */
 
 /*! \page ogrinfo ogrinfo
@@ -24,10 +75,10 @@ Usage:
 \endhtmlonly
 
 \verbatim
-ogrinfo [--help-general] [-ro] [-q] [-where restricted_where]
+ogrinfo [--help-general] [-ro] [-q] [-where restricted_where|@filename]
         [-spat xmin ymin xmax ymax] [-geomfield field] [-fid fid]
-        [-sql statement] [-dialect dialect] [-al] [-so] [-fields={YES/NO}]
-        [-geom={YES/NO/SUMMARY}] [-formats] [[-oo NAME=VALUE] ...]
+        [-sql statement|@filename] [-dialect dialect] [-al] [-so] [-fields={YES/NO}]
+        [-geom={YES/NO/SUMMARY/WKT/ISO_WKT}] [-formats] [[-oo NAME=VALUE] ...]
         [-nomd] [-listmdd] [-mdd domain|`all`]*
         [-nocount] [-noextent]
         datasource_name [layer [layer ...]]
@@ -50,9 +101,11 @@ extents.</dd>
 coordinate system, layer schema, extents, and feature count. </dd>
 <dt> <b>-where</b> <i>restricted_where</i>:</dt><dd> An attribute query in a restricted
 form of the queries used in the SQL WHERE statement.   Only features matching
-the attribute query will be reported.</dd>
+the attribute query will be reported. Starting with GDAL 2.1, the @filename syntax
+can be used to indicate that the content is in the pointed filename.</dd>
 <dt> <b>-sql</b> <i>statement</i>:</dt><dd> Execute the indicated SQL statement
-and return the result.</dd>
+and return the result. Starting with GDAL 2.1, the @filename syntax
+can be used to indicate that the content is in the pointed filename.</dd>
 <dt> <b>-dialect</b> <em>dialect</em>:</dt><dd> SQL dialect.  In some cases can be used to use (unoptimized) OGR SQL instead of the native SQL of an RDBMS by passing OGRSQL.
 Starting with GDAL 1.10, the "SQLITE" dialect can also be used with any datasource.</dd>
 <dt> <b>-spat</b> <i>xmin ymin xmax ymax</i>:</dt><dd> The area of interest.  Only
@@ -66,10 +119,14 @@ also use the fact the 'fid' is a special field recognized by OGR SQL. So, '-wher
 would select features 1, 3 and 5.</dd>
 <dt> <b>-fields</b>={YES/NO}:</dt><dd> (starting with GDAL 1.6.0) If set to NO,
 the feature dump will not display field values. Default value is YES.</dd>
-<dt> <b>-geom</b>={YES/NO/SUMMARY}:</dt><dd> (starting with GDAL 1.6.0) If set to NO,
-the feature dump will not display the geometry. If set to SUMMARY, only a
-summary of the geometry will be displayed. If set to YES, the geometry will be reported in full OGC WKT format.
-Default value is YES.</dd>
+<dt> <b>-geom</b>={YES/NO/SUMMARY/WKT/ISO_WKT}:</dt><dd> (starting
+with GDAL 1.6.0) If set to NO, the feature dump will not display the
+geometry. If set to SUMMARY, only a summary of the geometry will be
+displayed. If set to YES or ISO_WKT, the geometry will be reported in
+full OGC WKT format. If set to WKT the geometry will be reported in
+legacy WKT. Default value is YES. (WKT and ISO_WKT are available
+starting with GDAL 2.1, which also changes the default to
+ISO_WKT)</dd>
 <dt> <b>-oo</b> <em>NAME=VALUE</em>:</dt><dd>(starting with GDAL 2.0) Dataset open option (format specific)</dd>
 <dt> <b>-nomd</b></dt><dd>(starting with GDAL 2.0)  Suppress metadata printing. Some datasets may contain a lot
 of metadata strings.</dd>
@@ -78,7 +135,7 @@ of metadata strings.</dd>
 "all" can be used to report metadata in all domains</dd>
 <dt> <b>-nocount</b></dt><dd>(starting with GDAL 2.0)  Suppress feature count printing.</dd>
 <dt> <b>-noextent</b></dt><dd>(starting with GDAL 2.0)  Suppress spatial extent printing.</dd>
-<dt> <b>--formats</b>:</dt><dd> List the format drivers that are
+<dt> <b>\-\-formats</b>:</dt><dd> List the format drivers that are
 enabled.</dd>
 <dt> <i>datasource_name</i>:</dt><dd> The data source to open.  May be a filename, 
 directory or other virtual name.  See the <a href="ogr/ogr_formats.html">OGR Vector
@@ -87,7 +144,7 @@ Formats</a> list for supported datasources.</dd>
 </dl>
 
 If no layer names are passed then ogrinfo will report a list of available
-layers (and their layerwide geometry type).  If layer name(s) are given then
+layers (and their layer wide geometry type).  If layer name(s) are given then
 their extents, coordinate system, feature count, geometry type, schema and
 all features matching query parameters will be reported to the terminal. 
 If no query parameters are provided, all features are reported.  
@@ -182,8 +239,8 @@ Usage:
 
 \verbatim
 Usage: ogr2ogr [--help-general] [-skipfailures] [-append] [-update]
-               [-select field_list] [-where restricted_where] 
-               [-progress] [-sql <sql statement>] [-dialect dialect]
+               [-select field_list] [-where restricted_where|@filename] 
+               [-progress] [-sql <sql statement>|@filename] [-dialect dialect]
                [-preserve_fid] [-fid FID]
                [-spat xmin ymin xmax ymax] [-spat_srs srs_def] [-geomfield field]
                [-a_srs srs_def] [-t_srs srs_def] [-s_srs srs_def]
@@ -191,7 +248,7 @@ Usage: ogr2ogr [--help-general] [-skipfailures] [-append] [-update]
                dst_datasource_name src_datasource_name
                [-lco NAME=VALUE] [-nln name]
                [-nlt type|PROMOTE_TO_MULTI|CONVERT_TO_LINEAR]
-               [-dim 2|3|layer_dim] [layer [layer ...]]
+               [-dim XY|XYZ|XYM|XYZM|2|3|layer_dim] [layer [layer ...]]
 
 Advanced options :
                [-gt n]
@@ -212,7 +269,7 @@ Advanced options :
                [-splitlistfields] [-maxsubfields val]
                [-explodecollections] [-zfield field_name]
                [-gcp pixel line easting northing [elevation]]* [-order n | -tps]
-               [-nomd] [-mo \"META-TAG=VALUE\"]*
+               [-nomd] [-mo \"META-TAG=VALUE\"]* [-noNativeData]
 
 \endverbatim
 
@@ -245,10 +302,12 @@ same name is found.) Starting with OGR 1.11, geometry fields can also be specifi
 in the list.</dd>
 <dt> <b>-progress</b>:</dt><dd> (starting with GDAL 1.7.0) Display progress on terminal. Only works if input layers have the "fast feature count" capability.</dd>
 <dt> <b>-sql</b> <em>sql_statement</em>:</dt><dd> SQL statement to execute.
-The resulting table/layer will be saved to the output.</dd>
+The resulting table/layer will be saved to the output. Starting with GDAL 2.1, the @filename syntax
+can be used to indicate that the content is in the pointed filename.</dd>
 <dt> <b>-dialect</b> <em>dialect</em>:</dt><dd> SQL dialect.  In some cases can be used to use (unoptimized) OGR SQL instead of the native SQL of an RDBMS by passing OGRSQL.
 Starting with GDAL 1.10, the "SQLITE" dialect can also be used with any datasource.</dd>
-<dt> <b>-where</b><em> restricted_where</em>:</dt><dd> Attribute query (like SQL WHERE)</dd>
+<dt> <b>-where</b><em> restricted_where</em>:</dt><dd> Attribute query (like SQL WHERE).
+Starting with GDAL 2.1, the @filename syntax can be used to indicate that the content is in the pointed filename.</dd>
 <dt> <b>-skipfailures</b>:</dt><dd>Continue after a failure, skipping the failed feature.</dd>
 <dt> <b>-spat</b><em> xmin ymin xmax ymax</em>:</dt><dd> spatial query extents, in the
 SRS of the source layer(s) (or the one specified with -spat_srs). Only features
@@ -259,23 +318,29 @@ on which the spatial filter operates on.</dd>
 <dt> <b>-dsco</b> <em>NAME=VALUE</em>:</dt><dd> Dataset creation option (format specific)</dd>
 <dt> <b>-lco</b><em>  NAME=VALUE</em>:</dt><dd> Layer creation option (format specific)</dd>
 <dt> <b>-nln</b><em> name</em>:</dt><dd> Assign an alternate name to the new layer</dd>
-<dt> <b>-nlt</b><em> type</em>:</dt><dd> Define the geometry type for the 
-created layer.  One of NONE, GEOMETRY, POINT, LINESTRING, POLYGON, 
-GEOMETRYCOLLECTION, MULTIPOINT, MULTIPOLYGON or MULTILINESTRING. And CIRCULARSTRING,
-COMPOUNDCURVE, CURVEPOLYGON, MULTICURVE and MULTISURFACE for GDAL 2.0 non-linear geometry
-types. 
-Add "25D" to the name to get 2.5D versions.
-Starting with GDAL 1.10, PROMOTE_TO_MULTI can be used to automatically promote layers
-that mix polygon or multipolygons to multipolygons, and layers that mix linestrings or
-multilinestrings to multilinestrings. Can be useful when converting shapefiles to PostGIS
-(and other target drivers) that implements strict checks for geometry type.
-Starting with GDAL 2.0, CONVERT_TO_LINEAR can be used to to convert non-linear geometries
-types into linear geometries by approximating them.</dd>
-<dt> <b>-dim</b><em> val</em>:</dt><dd>(starting with GDAL 1.10) Force the coordinate dimension to val (valid values are 2 or 3).
-This affects both the layer geometry type, and feature geometries.
-Starting with GDAL 1.11, the value can be set to "layer_dim" to instruct feature geometries to be promoted
-to the coordinate dimension declared by the layer.
-</dd>
+<dt> <b>-nlt</b><em> type</em>:</dt><dd> Define the geometry type for
+the created layer. One of NONE, GEOMETRY, POINT, LINESTRING, POLYGON,
+GEOMETRYCOLLECTION, MULTIPOINT, MULTIPOLYGON or MULTILINESTRING. And
+CIRCULARSTRING, COMPOUNDCURVE, CURVEPOLYGON, MULTICURVE and
+MULTISURFACE for GDAL 2.0 non-linear geometry types. Add "Z", "M", or
+"ZM" to the name to get coordinates with elevation, measure, or
+elevation and measure. Starting with GDAL 1.10, PROMOTE_TO_MULTI can
+be used to automatically promote layers that mix polygon or
+multipolygons to multipolygons, and layers that mix linestrings or
+multilinestrings to multilinestrings. Can be useful when converting
+shapefiles to PostGIS and other target drivers that implement strict
+checks for geometry types. Starting with GDAL 2.0, CONVERT_TO_LINEAR
+can be used to to convert non-linear geometries types into linear
+geometries by approximating them. Starting with 2.1 the type can be
+defined as measured ("25D" remains as an alias for single "Z").</dd>
+<dt> <b>-dim</b><em> val</em>:</dt><dd>(starting with GDAL 1.10) Force
+the coordinate dimension to val (valid values are XY, XYZ, XYM, and
+XYZM - for backwards compatibility 2 is an alias for XY and 3 is an
+alias for XYZ). This affects both the layer geometry type, and feature
+geometries. Starting with GDAL 1.11, the value can be set to
+"layer_dim" to instruct feature geometries to be promoted to the
+coordinate dimension declared by the layer. Support for M was added in
+GDAL 2.1</dd>
 <dt> <b>-a_srs</b><em> srs_def</em>:</dt><dd> Assign an output SRS</dd>
 <dt> <b>-t_srs</b><em> srs_def</em>:</dt><dd> Reproject/transform to this SRS on output</dd>
 <dt> <b>-s_srs</b><em> srs_def</em>:</dt><dd> Override source SRS</dd>
@@ -292,7 +357,7 @@ would select features 1, 3 and 5.</dd>
 </dl>
 
 Srs_def can be a full WKT definition (hard to escape properly), or a well
-known definition (ie. EPSG:4326) or a file with a WKT definition.
+known definition (i.e. EPSG:4326) or a file with a WKT definition.
 
 Advanced options :
 
@@ -323,7 +388,7 @@ you will generally want to use it in combination of the -clipdstlayer, -clipdstw
 <dt> <b>-clipdstlayer</b> <em>layername</em>:</dt><dd>Select the named layer from the destination clip datasource.</dd>
 <dt> <b>-clipdstwhere</b> <em>expression</em>:</dt><dd>Restrict desired geometries based on attribute query.</dd>
 <dt> <b>-wrapdateline</b>:</dt><dd> (starting with GDAL 1.7.0) split geometries crossing the dateline meridian (long. = +/- 180deg)</dd>
-<dt> <b>-datelineoffset</b>:</dt><dd> (starting with GDAL 1.10) offset from dateline in degrees (default long. = +/- 10deg, geometries within 170deg to -170deg will be splited)</dd>
+<dt> <b>-datelineoffset</b>:</dt><dd> (starting with GDAL 1.10) offset from dateline in degrees (default long. = +/- 10deg, geometries within 170deg to -170deg will be split)</dd>
 <dt> <b>-simplify</b><em> tolerance</em>:</dt><dd> (starting with GDAL 1.9.0) distance tolerance for simplification.
 Note: the algorithm used preserves topology per feature, in particular for polygon geometries, but not for a whole layer.</dd>
 <dt> <b>-segmentize</b><em> max_dist</em>:</dt><dd> (starting with GDAL 1.6.0) maximum distance between 2 nodes.
@@ -381,6 +446,9 @@ from source dataset and layers into target dataset and layers, when supported by
 output driver.</dd>
 <dt> <b>-mo</b> <i>"META-TAG=VALUE"</i>:</dt><dd>(starting with GDAL 2.0)  Passes a metadata key and
 value to set on the output dataset, when supported by output driver.</dd>
+<dt> <b>-noNativeData</b>:</dt><dd>(starting with GDAL 2.1) To disable copying of
+native data, i.e. details of source format not captured by OGR abstraction, that
+are otherwise preserved by some drivers (like GeoJSON) when converting to same format.</dd>
 
 </dl>
 
@@ -399,6 +467,10 @@ performance boot. See the PG driver documentation page.
 
 More generally, consult the documentation page of the input and output drivers for performance hints.
 
+\section ogr2ogr_api C API
+
+Starting with GDAL 2.1, this utility is also callable from C with GDALVectorTranslate().
+
 \section ogr2ogr_example EXAMPLE
 
 Example appending to an existing layer (both flags need to be used):
@@ -532,10 +604,10 @@ The ogrlineref program can be used to create a linear reference - a file contain
 a segments of special length (e.g. 1 km in reference units) and get coordinates, 
 linear referenced distances or sublines (subpaths) from this file. The utility not
 required the M or Z values in geometry. The results can be stored in any OGR supported 
-format. Also some information writed to the stdout.  
+format. Also some information is written to the stdout.
 
 <dl>
-<dt><b>--help-general</b>:</dt><dd> Show the usage.</dd>
+<dt><b>\-\-help-general</b>:</dt><dd> Show the usage.</dd>
 <dt><b>-progress</b>:</dt><dd> Show progress.</dd>
 <dt><b>-quiet</b>:</dt><dd> Suppress all messages except errors and results.</dd>
 <dt><b>-f</b> <em>format_name</em>:</dt><dd> Select an output format name.
@@ -548,14 +620,14 @@ format. Also some information writed to the stdout.
 <dt> <b>-l</b><em>src_line_datasource_name</em>:</dt><dd> The path to input linestring 
     datasource (e.g. the road)</dd>
 <dt> <b>-ln</b><em>layer_name</em>:</dt><dd> The layer name in datasource</dd>
-<dt> <b>-lf</b><em>field_name</em>:</dt><dd> The field name of uniq values to 
+<dt> <b>-lf</b><em>field_name</em>:</dt><dd> The field name of unique values to 
     separate the input lines (e.g. the set of roads)</dd>
 <dt> <b>-p</b><em>src_repers_datasource_name</em>:</dt><dd> The path to linear 
     references points (e.g. the road mile-stones)</dd>
 <dt> <b>-pn</b><em>layer_name</em>:</dt><dd> The layer name in datasource</dd>
 <dt> <b>-pm</b><em>pos_field_name</em>:</dt><dd> The field name of distances 
     along path (e.g. mile-stones values)</dd>
-<dt> <b>-pf</b><em>field_name</em>:</dt><dd> The field name of uniq values to 
+<dt> <b>-pf</b><em>field_name</em>:</dt><dd> The field name of unique values to 
     map input reference points to lines</dd>
 <dt> <b>-r</b><em>src_parts_datasource_name</em>:</dt><dd> The path to linear 
     reference file</dd>
@@ -564,9 +636,9 @@ format. Also some information writed to the stdout.
     reference file (linestring datasource)</dd>
 <dt> <b>-on</b><em>layer_name</em>:</dt><dd> The layer name in datasource</dd>
 <dt> <b>-of</b><em>field_name</em>:</dt><dd> The field name for storing the 
-    uniq values of input lines</dd>
+    unique values of input lines</dd>
 <dt> <b>-s</b><em>step</em>:</dt><dd> The part size in linear units</dd>
-<dt> <b>-get_pos</b>:</dt><dd> Return linear referenced postion for input X, Y</dd>
+<dt> <b>-get_pos</b>:</dt><dd> Return linear referenced position for input X, Y</dd>
 <dt> <b>-x</b><em>long</em>:</dt><dd> Input X coordinate</dd>
 <dt> <b>-y</b><em>lat</em>:</dt><dd> Input Y coordinate</dd>
 <dt> <b>-get_coord</b>:</dt><dd> Return point on path for input linear distance</dd>
diff --git a/apps/ogrdissolve.cpp b/apps/ogrdissolve.cpp
index 7895a28..430316e 100644
--- a/apps/ogrdissolve.cpp
+++ b/apps/ogrdissolve.cpp
@@ -38,12 +38,12 @@ CPL_CVSID("$Id: ogr2ogr.cpp 11636 2007-06-10 06:02:56Z mloskot $");
 
 static void Usage();
 
-static int DissolveLayer(  OGRDataSource *poSrcDS, 
+static int DissolveLayer(  OGRDataSource *poSrcDS,
                            OGRLayer * poSrcLayer,
                            OGRDataSource *poDstDS,
                            char ** papszLSCO,
                            const char *pszNewLayerName,
-                           int bTransform, 
+                           int bTransform,
                            OGRSpatialReference *poOutputSRS,
                            OGRSpatialReference *poSourceSRS,
                            char **papszSelFields,
@@ -95,7 +95,7 @@ int main( int nArgc, char ** papszArgv )
 /*      Processing command line arguments.                              */
 /* -------------------------------------------------------------------- */
     nArgc = OGRGeneralCmdLineProcessor( nArgc, &papszArgv, 0 );
-    
+
     if( nArgc < 1 )
         exit( -nArgc );
 
@@ -117,7 +117,7 @@ int main( int nArgc, char ** papszArgv )
         {
             bPreserveFID = TRUE;
         }
-        else if( EQUALN(papszArgv[iArg],"-skip",5) )
+        else if( STARTS_WITH_CI(papszArgv[iArg], "-skip") )
         {
             bSkipFailures = TRUE;
         }
@@ -150,13 +150,13 @@ int main( int nArgc, char ** papszArgv )
             int bIs3D = FALSE;
             CPLString osGeomName = papszArgv[iArg+1];
             if (strlen(papszArgv[iArg+1]) > 3 &&
-                EQUALN(papszArgv[iArg+1] + strlen(papszArgv[iArg+1]) - 3, "25D", 3))
+                STARTS_WITH_CI(papszArgv[iArg+1] + strlen(papszArgv[iArg+1]) - 3, "25D"))
             {
                 bIs3D = TRUE;
                 osGeomName.resize(osGeomName.size() - 3);
             }
             else if (strlen(papszArgv[iArg+1]) > 1 &&
-                EQUALN(papszArgv[iArg+1] + strlen(papszArgv[iArg+1]) - 1, "Z", 1))
+                STARTS_WITH_CI(papszArgv[iArg+1] + strlen(papszArgv[iArg+1]) - 1, "Z"))
             {
                 bIs3D = TRUE;
                 osGeomName.resize(osGeomName.size() - 1);
@@ -196,10 +196,10 @@ int main( int nArgc, char ** papszArgv )
             pszOutputSRSDef = papszArgv[++iArg];
             bTransform = TRUE;
         }
-        else if( EQUAL(papszArgv[iArg],"-spat") 
-                 && papszArgv[iArg+1] != NULL 
-                 && papszArgv[iArg+2] != NULL 
-                 && papszArgv[iArg+3] != NULL 
+        else if( EQUAL(papszArgv[iArg],"-spat")
+                 && papszArgv[iArg+1] != NULL
+                 && papszArgv[iArg+2] != NULL
+                 && papszArgv[iArg+3] != NULL
                  && papszArgv[iArg+4] != NULL )
         {
             OGRLinearRing  oRing;
@@ -221,7 +221,7 @@ int main( int nArgc, char ** papszArgv )
         else if( EQUAL(papszArgv[iArg],"-select") && papszArgv[iArg+1] != NULL)
         {
             pszSelect = papszArgv[++iArg];
-            papszSelFields = CSLTokenizeStringComplex(pszSelect, " ,", 
+            papszSelFields = CSLTokenizeStringComplex(pszSelect, " ,",
                                                       FALSE, FALSE );
         }
         else if( papszArgv[iArg][0] == '-' )
@@ -243,7 +243,7 @@ int main( int nArgc, char ** papszArgv )
 /*      Open data source.                                               */
 /* -------------------------------------------------------------------- */
     OGRDataSource       *poDS;
-        
+
     poDS = OGRSFDriverRegistrar::Open( pszDataSource, FALSE );
 
 /* -------------------------------------------------------------------- */
@@ -252,7 +252,7 @@ int main( int nArgc, char ** papszArgv )
     if( poDS == NULL )
     {
         OGRSFDriverRegistrar    *poR = OGRSFDriverRegistrar::GetRegistrar();
-        
+
         printf( "FAILURE:\n"
                 "Unable to open datasource `%s' with the following drivers.\n",
                 pszDataSource );
@@ -269,7 +269,7 @@ int main( int nArgc, char ** papszArgv )
 /*      Try opening the output datasource as an existing, writable      */
 /* -------------------------------------------------------------------- */
     OGRDataSource       *poODS;
-    
+
     if( bUpdate )
     {
         poODS = OGRSFDriverRegistrar::Open( pszDestDataSource, TRUE );
@@ -305,7 +305,7 @@ int main( int nArgc, char ** papszArgv )
         {
             printf( "Unable to find driver `%s'.\n", pszFormat );
             printf( "The following drivers are available:\n" );
-        
+
             for( iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
             {
                 printf( "  -> `%s'\n", poR->GetDriver(iDriver)->GetName() );
@@ -326,7 +326,7 @@ int main( int nArgc, char ** papszArgv )
         poODS = poDriver->CreateDataSource( pszDestDataSource, papszDSCO );
         if( poODS == NULL )
         {
-            printf( "%s driver failed to create %s\n", 
+            printf( "%s driver failed to create %s\n",
                     pszFormat, pszDestDataSource );
             exit( 1 );
         }
@@ -340,7 +340,7 @@ int main( int nArgc, char ** papszArgv )
         poOutputSRS = new OGRSpatialReference();
         if( poOutputSRS->SetFromUserInput( pszOutputSRSDef ) != OGRERR_NONE )
         {
-            printf( "Failed to process SRS definition: %s\n", 
+            printf( "Failed to process SRS definition: %s\n",
                     pszOutputSRSDef );
             exit( 1 );
         }
@@ -354,7 +354,7 @@ int main( int nArgc, char ** papszArgv )
         poSourceSRS = new OGRSpatialReference();
         if( poSourceSRS->SetFromUserInput( pszSourceSRSDef ) != OGRERR_NONE )
         {
-            printf( "Failed to process SRS definition: %s\n", 
+            printf( "Failed to process SRS definition: %s\n",
                     pszSourceSRSDef );
             exit( 1 );
         }
@@ -371,18 +371,18 @@ int main( int nArgc, char ** papszArgv )
             printf( "-where clause ignored in combination with -sql.\n" );
         if( CSLCount(papszLayers) > 0 )
             printf( "layer names ignored in combination with -sql.\n" );
-        
-        poResultSet = poDS->ExecuteSQL( pszSQLStatement, poSpatialFilter, 
+
+        poResultSet = poDS->ExecuteSQL( pszSQLStatement, poSpatialFilter,
                                         NULL );
 
         if( poResultSet != NULL )
         {
-            if( !DissolveLayer( poDS, poResultSet, poODS, papszLCO, 
+            if( !DissolveLayer( poDS, poResultSet, poODS, papszLCO,
                                  pszNewLayerName, bTransform, poOutputSRS,
                                  poSourceSRS, papszSelFields, bAppend, eGType,
                                  bOverwrite ))
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "Terminating translation prematurely after failed\n"
                           "translation from sql statement." );
 
@@ -395,8 +395,8 @@ int main( int nArgc, char ** papszArgv )
 /* -------------------------------------------------------------------- */
 /*      Process each data source layer.                                 */
 /* -------------------------------------------------------------------- */
-    for( int iLayer = 0; 
-         pszSQLStatement == NULL && iLayer < poDS->GetLayerCount(); 
+    for( int iLayer = 0;
+         pszSQLStatement == NULL && iLayer < poDS->GetLayerCount();
          iLayer++ )
     {
         OGRLayer        *poLayer = poDS->GetLayer(iLayer);
@@ -414,19 +414,19 @@ int main( int nArgc, char ** papszArgv )
         {
             if( pszWHERE != NULL )
                 poLayer->SetAttributeFilter( pszWHERE );
-            
+
             if( poSpatialFilter != NULL )
                 poLayer->SetSpatialFilter( poSpatialFilter );
-            
-            if( !DissolveLayer( poDS, poLayer, poODS, papszLCO, 
+
+            if( !DissolveLayer( poDS, poLayer, poODS, papszLCO,
                                  pszNewLayerName, bTransform, poOutputSRS,
                                  poSourceSRS, papszSelFields, bAppend, eGType,
-                                 bOverwrite ) 
+                                 bOverwrite )
                 && !bSkipFailures )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "Terminating translation prematurely after failed\n"
-                          "translation of layer %s\n", 
+                          "translation of layer %s\n",
                           poLayer->GetLayerDefn()->GetName() );
 
                 exit( 1 );
@@ -453,7 +453,7 @@ int main( int nArgc, char ** papszArgv )
 #ifdef DBMALLOC
     malloc_dump(1);
 #endif
-    
+
     return 0;
 }
 
@@ -468,7 +468,7 @@ static void Usage()
 
     printf( "Usage: ogr2ogr [--help-general] [-skipfailures] [-append] [-update]\n"
             "               [-select field_list] [-where restricted_where] \n"
-            "               [-sql <sql statement>] \n" 
+            "               [-sql <sql statement>] \n"
             "               [-spat xmin ymin xmax ymax] [-preserve_fid] [-fid FID]\n"
             "               [-a_srs srs_def] [-t_srs srs_def] [-s_srs srs_def]\n"
             "               [-f format_name] [-overwrite] [[-dsco NAME=VALUE] ...]\n"
@@ -476,7 +476,7 @@ static void Usage()
             "               [-lco NAME=VALUE] [-nln name] [-nlt type] [layer [layer ...]]\n"
             "\n"
             " -f format_name: output file format name, possible values are:\n");
-    
+
     for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
     {
         OGRSFDriver *poDriver = poR->GetDriver(iDriver);
@@ -489,8 +489,8 @@ static void Usage()
             " -overwrite: delete the output layer and recreate it empty\n"
             " -update: Open existing output datasource in update mode\n"
             " -select field_list: Comma-delimited list of fields from input layer to\n"
-            "                     copy to the new layer (defaults to all)\n" 
-            " -where restricted_where: Attribute query (like SQL WHERE)\n" 
+            "                     copy to the new layer (defaults to all)\n"
+            " -where restricted_where: Attribute query (like SQL WHERE)\n"
             " -sql statement: Execute given SQL statement and save result.\n"
             " -skipfailures: skip features or layers that fail to convert\n"
             " -spat xmin ymin xmax ymax: spatial query extents\n"
@@ -505,16 +505,16 @@ static void Usage()
     printf(" -a_srs srs_def: Assign an output SRS\n"
            " -t_srs srs_def: Reproject/transform to this SRS on output\n"
            " -s_srs srs_def: Override source SRS\n"
-           "\n" 
+           "\n"
            " Srs_def can be a full WKT definition (hard to escape properly),\n"
-           " or a well known definition (ie. EPSG:4326) or a file with a WKT\n"
+           " or a well known definition (i.e. EPSG:4326) or a file with a WKT\n"
            " definition.\n" );
 
     exit( 1 );
 }
 
 
-StringGeometryMap* CollectGeometries(   OGRLayer* poSrcLayer, 
+StringGeometryMap* CollectGeometries(   OGRLayer* poSrcLayer,
                                         const char** papszFields) {
 
 /* -------------------------------------------------------------------- */
@@ -523,37 +523,36 @@ StringGeometryMap* CollectGeometries(   OGRLayer* poSrcLayer,
 /*      are a GeometryCollection of all of the geometries for records   */
 /*      with that value.                                                */
 /* -------------------------------------------------------------------- */
-    
+
     StringGeometryMMap poGeometriesMap;
 
-    
     OGRFeature  *poFeature;
-    
+
     poSrcLayer->ResetReading();
 
     int iField;
 /* -------------------------------------------------------------------- */
-/*      Get all of the features and put them in a multimap.  This may   */
+/*      Get all of the features and put them in a multi map.  This may   */
 /*      include values for which the selected fields is NULL.           */
 /* -------------------------------------------------------------------- */
 
-    while( TRUE )
+    while( true )
     {
 
         poFeature = poSrcLayer->GetNextFeature();
-        
+
         if( poFeature == NULL )
             break;
         CPLString poKey("");
-        
+
         for( iField=0; papszFields[iField] != NULL; iField++) {
             int nField = poFeature->GetFieldIndex(papszFields[iField]);
             poKey = poKey + poFeature->GetFieldAsString(nField);
         }
-        
+
         if (poFeature->GetGeometryRef()->IsValid()) {
         poGeometriesMap.insert(std::make_pair(
-                        CPLString(  poKey), 
+                        CPLString(  poKey),
                                     poFeature->GetGeometryRef()
                                  )
                      );
@@ -570,11 +569,11 @@ StringGeometryMap* CollectGeometries(   OGRLayer* poSrcLayer,
 /* -------------------------------------------------------------------- */
 
     typedef std::map<CPLString, int> StringIntMap;
-    StringIntMap::const_iterator ipos;    
-    StringIntMap poFieldsmap;    
+    StringIntMap::const_iterator ipos;
+    StringIntMap poFieldsmap;
 
     StringGeometryMMap::const_iterator pos;
-    
+
     for (pos = poGeometriesMap.begin();
          pos != poGeometriesMap.end();
          ++pos) {
@@ -582,11 +581,11 @@ StringGeometryMap* CollectGeometries(   OGRLayer* poSrcLayer,
              /* we currently throw out any null field values at this time */
            //  if (!(pos->first.empty())) {
                  poFieldsmap[CPLString(pos->first.c_str())] = 1;
-         //    } 
+         //    }
     }
 
 /* -------------------------------------------------------------------- */
-/*      Make a new map of GeometryCollections for each value in the     */
+/*      Make a new map of GeometryCollection for each value in the     */
 /*      poFieldsmap.  This is a 1:1 relationship, and all of the        */
 /*      geometries for a given field are all put into the same          */
 /*      GeometryCollection.  After we build the poCollections, we will  */
@@ -595,14 +594,13 @@ StringGeometryMap* CollectGeometries(   OGRLayer* poSrcLayer,
 
     StringGeometryColMap poCollections;
 
-             
     CPLDebug("CollectGeometries", "Field map size: %d", poFieldsmap.size());
 
     for (ipos = poFieldsmap.begin();
          ipos != poFieldsmap.end();
-         ++ipos) 
-         {   
-    
+         ++ipos)
+         {
+
               CPLString fid = ipos->first;
               CPLDebug ("CollectGeometries", "First %s Second %d", ipos->first.c_str(), ipos->second);
 
@@ -611,14 +609,13 @@ StringGeometryMap* CollectGeometries(   OGRLayer* poSrcLayer,
 
              for (pos = poGeometriesMap.lower_bound(fid);
                   pos != poGeometriesMap.upper_bound(fid);
-                  ++pos) {     
+                  ++pos) {
                       geom->addGeometry(pos->second);
-             }    
+             }
              poCollections.insert(std::make_pair(fid, geom));
     }
-    
-    
-    CPLDebug("CollectGeometries", "Geo map size: %d", poCollections.size()); 
+
+    CPLDebug("CollectGeometries", "Geo map size: %d", poCollections.size());
 
 /* -------------------------------------------------------------------- */
 /*      Loop through our poCollections map and buffer(0) each           */
@@ -628,12 +625,12 @@ StringGeometryMap* CollectGeometries(   OGRLayer* poSrcLayer,
     StringGeometryMap* buffers = new StringGeometryMap;
 
     StringGeometryColMap::const_iterator collections_i;
-        
+
     for (   collections_i = poCollections.begin();
             collections_i != poCollections.end();
             ++collections_i){
-                CPLDebug(   "CollectGeometries", 
-                            "poCollections Geometry size %d", 
+                CPLDebug(   "CollectGeometries",
+                            "poCollections Geometry size %d",
                             collections_i->second->getNumGeometries());
                 OGRGeometry* buffer = collections_i->second->Buffer(0);
                 buffers->insert(std::make_pair(collections_i->first, buffer));
@@ -642,10 +639,10 @@ StringGeometryMap* CollectGeometries(   OGRLayer* poSrcLayer,
 
     for (collections_i = poCollections.begin();
           collections_i != poCollections.end();
-          ++collections_i) {     
+          ++collections_i) {
               delete collections_i->second;
-     }     
-    
+    }
+
     return buffers;
 }
 
@@ -653,7 +650,7 @@ GeometriesList* FlattenGeometries(GeometriesList* input) {
 
     GeometriesList::const_iterator geometry_i;
     GeometriesList* output = new GeometriesList;
-    
+
     CPLDebug("CollectGeometries", "Input geometries in FlattenGeometries size: %d", input->size());
     for (   geometry_i = input->begin();
             geometry_i != input->end();
@@ -662,13 +659,13 @@ GeometriesList* FlattenGeometries(GeometriesList* input) {
                 OGRGeometry* buffer = (*geometry_i);
                 // int nGeometries = buffer->getNumGeometries();
                 OGRwkbGeometryType iGType = buffer->getGeometryType();
-                
+
                 if (iGType == wkbPolygon) {
                         OGRPolygon* geom = (OGRPolygon*)buffer;
                         output->push_back((OGRGeometry*)geom);
-                CPLDebug(   "CollectGeometries", 
-                            "Collapsing wkbPolygon geometries......" 
-                            );               
+                CPLDebug(   "CollectGeometries",
+                            "Collapsing wkbPolygon geometries......"
+                            );
                 }
                 if (iGType == wkbMultiPolygon) {
                         OGRMultiPolygon* geom = (OGRMultiPolygon*)buffer;
@@ -677,9 +674,9 @@ GeometriesList* FlattenGeometries(GeometriesList* input) {
                             output->push_back((OGRGeometry*)g);
                         }
 
-                CPLDebug(   "CollectGeometries", 
-                            "Collapsing wkbMultiPolygon geometries......" 
-                            );                  
+                CPLDebug(   "CollectGeometries",
+                            "Collapsing wkbMultiPolygon geometries......"
+                            );
                 }
                 if (iGType == wkbGeometryCollection) {
                         OGRGeometryCollection* geom = (OGRGeometryCollection*)buffer;
@@ -687,35 +684,34 @@ GeometriesList* FlattenGeometries(GeometriesList* input) {
                             GeometriesList::const_iterator g_i;
                         for (int i=0; i< geom->getNumGeometries(); i++) {
                             OGRGeometry* g = (OGRGeometry*)geom->getGeometryRef(i);
-                            collection->push_back(g);                            
+                            collection->push_back(g);
                         }
                             GeometriesList* collapsed = FlattenGeometries(collection);
                             for (g_i=collapsed->begin(); g_i!=collapsed->end(); g_i++){
-                               output->push_back((OGRGeometry*)(*g_i)); 
-                CPLDebug(   "CollectGeometries", 
-                            "Collapsing wkbGeometryCollection geometries......" 
+                               output->push_back((OGRGeometry*)(*g_i));
+                CPLDebug(   "CollectGeometries",
+                            "Collapsing wkbGeometryCollection geometries......"
                             );
 
-                            }               
+                            }
                 }
-                // CPLDebug(   "CollectGeometries", 
-                //             "Buffered Geometry size %d", 
+                // CPLDebug(   "CollectGeometries",
+                //             "Buffered Geometry size %d",
                 //             nGeometries);
+    }
 
-    }    
-    
     return output;
 }
 /************************************************************************/
 /*                           DissolveLayer()                            */
 /************************************************************************/
 
-static int DissolveLayer( OGRDataSource *poSrcDS, 
+static int DissolveLayer( OGRDataSource *poSrcDS,
                            OGRLayer * poSrcLayer,
                            OGRDataSource *poDstDS,
                            char **papszLCO,
                            const char *pszNewLayerName,
-                           int bTransform, 
+                           int bTransform,
                            OGRSpatialReference *poOutputSRS,
                            OGRSpatialReference *poSourceSRS,
                            char **papszSelFields,
@@ -766,21 +762,21 @@ static int DissolveLayer( OGRDataSource *poSrcDS,
                    "following coordinate systems.  This may be because they\n"
                    "are not transformable, or because projection services\n"
                    "(PROJ.4 DLL/.so) could not be loaded.\n" );
-            
+
             poSourceSRS->exportToPrettyWkt( &pszWKT, FALSE );
             printf( "Source:\n%s\n", pszWKT );
-            
+
             poOutputSRS->exportToPrettyWkt( &pszWKT, FALSE );
             printf( "Target:\n%s\n", pszWKT );
             exit( 1 );
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Get other info.                                                 */
 /* -------------------------------------------------------------------- */
     poFDefn = poSrcLayer->GetLayerDefn();
-    
+
     if( poOutputSRS == NULL )
         poOutputSRS = poSrcLayer->GetSpatialRef();
 
@@ -794,14 +790,14 @@ static int DissolveLayer( OGRDataSource *poSrcDS,
     {
         OGRLayer        *poLayer = poDstDS->GetLayer(iLayer);
 
-        if( poLayer != NULL 
+        if( poLayer != NULL
             && EQUAL(poLayer->GetLayerDefn()->GetName(),pszNewLayerName) )
         {
             poDstLayer = poLayer;
             break;
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      If the user requested overwrite, and we have the layer in       */
 /*      question we need to delete it now so it will get recreated      */
@@ -811,7 +807,7 @@ static int DissolveLayer( OGRDataSource *poSrcDS,
     {
         if( poDstDS->DeleteLayer( iLayer ) != OGRERR_NONE )
         {
-            fprintf( stderr, 
+            fprintf( stderr,
                      "DeleteLayer() failed when overwrite requested.\n" );
             return FALSE;
         }
@@ -828,8 +824,8 @@ static int DissolveLayer( OGRDataSource *poSrcDS,
 
         if( !poDstDS->TestCapability( ODsCCreateLayer ) )
         {
-            fprintf( stderr, 
-              "Layer %s not found, and CreateLayer not supported by driver.", 
+            fprintf( stderr,
+              "Layer %s not found, and CreateLayer not supported by driver.",
                      pszNewLayerName );
             return FALSE;
         }
@@ -837,7 +833,7 @@ static int DissolveLayer( OGRDataSource *poSrcDS,
         CPLErrorReset();
 
         poDstLayer = poDstDS->CreateLayer( pszNewLayerName, poOutputSRS,
-                                           (OGRwkbGeometryType) eGType, 
+                                           (OGRwkbGeometryType) eGType,
                                            papszLCO );
 
         if( poDstLayer == NULL )
@@ -874,7 +870,7 @@ static int DissolveLayer( OGRDataSource *poSrcDS,
                 poDstLayer->CreateField( poFDefn->GetFieldDefn(iSrcField) );
             else
             {
-                printf( "Field '%s' not found in source layer.\n", 
+                printf( "Field '%s' not found in source layer.\n",
                         papszSelFields[iField] );
                 if( !bSkipFailures )
                     return FALSE;
@@ -892,18 +888,18 @@ static int DissolveLayer( OGRDataSource *poSrcDS,
 /* -------------------------------------------------------------------- */
     OGRFeature  *poFeature;
     int         nFeaturesInTransaction = 0;
-    
+
     poSrcLayer->ResetReading();
 
     if( nGroupTransactions )
         poDstLayer->StartTransaction();
 
-    StringGeometryMap* buffers = CollectGeometries(poSrcLayer, 
+    StringGeometryMap* buffers = CollectGeometries(poSrcLayer,
                                                    (const char**)papszSelFields);
 
     StringGeometryMap::const_iterator buffers_i;
     GeometriesList* input = new GeometriesList;
-    
+
     CPLDebug("CollectGeometries", "Buffers size: %d", buffers->size());
     for (   buffers_i = buffers->begin();
             buffers_i != buffers->end();
@@ -911,7 +907,7 @@ static int DissolveLayer( OGRDataSource *poSrcDS,
                 input->push_back(buffers_i->second);
     }
     GeometriesList* geometries = FlattenGeometries(input);
-    
+
     GeometriesList::const_iterator g_i;
     for (g_i=geometries->begin();
     g_i!=geometries->end();
@@ -919,92 +915,86 @@ static int DissolveLayer( OGRDataSource *poSrcDS,
         OGRFeature* feature = new OGRFeature(poFDefn);
         feature->SetGeometry((*g_i));
         feature->SetField("TAXDIST","fid");
-        poDstLayer->CreateFeature(feature);        
+        poDstLayer->CreateFeature(feature);
     }
-    
-    
-    
 
     if( nGroupTransactions )
         poDstLayer->CommitTransaction();
-        
 
-
-            
       //  getGeometryType
 //     if( pszNewLayerName == NULL )
 //         pszNewLayerName = poSrcLayer->GetLayerDefn()->GetName();
-// 
+//
 //     if( wkbFlatten(eGType) == wkbPolygon )
 //         bForceToPolygon = TRUE;
 //     else if( wkbFlatten(eGType) == wkbMultiPolygon )
 //         bForceToMultiPolygon = TRUE;
-// 
+//
 // /* -------------------------------------------------------------------- */
 // /*      Setup coordinate transformation if we need it.                  */
 // /* -------------------------------------------------------------------- */
 //     OGRCoordinateTransformation *poCT = NULL;
-// 
+//
 //     if( bTransform )
 //     {
 //         if( poSourceSRS == NULL )
 //             poSourceSRS = poSrcLayer->GetSpatialRef();
-// 
+//
 //         if( poSourceSRS == NULL )
 //         {
 //             printf( "Can't transform coordinates, source layer has no\n"
 //                     "coordinate system.  Use -s_srs to set one.\n" );
 //             exit( 1 );
 //         }
-// 
+//
 //         CPLAssert( NULL != poSourceSRS );
 //         CPLAssert( NULL != poOutputSRS );
-// 
+//
 //         poCT = OGRCreateCoordinateTransformation( poSourceSRS, poOutputSRS );
 //         if( poCT == NULL )
 //         {
 //             char        *pszWKT = NULL;
-// 
+//
 //             printf("Failed to create coordinate transformation between the\n"
 //                    "following coordinate systems.  This may be because they\n"
 //                    "are not transformable, or because projection services\n"
 //                    "(PROJ.4 DLL/.so) could not be loaded.\n" );
-//             
+//
 //             poSourceSRS->exportToPrettyWkt( &pszWKT, FALSE );
 //             printf( "Source:\n%s\n", pszWKT );
-//             
+//
 //             poOutputSRS->exportToPrettyWkt( &pszWKT, FALSE );
 //             printf( "Target:\n%s\n", pszWKT );
 //             exit( 1 );
 //         }
 //     }
-//     
+//
 // /* -------------------------------------------------------------------- */
 // /*      Get other info.                                                 */
 // /* -------------------------------------------------------------------- */
 //     poFDefn = poSrcLayer->GetLayerDefn();
-//     
+//
 //     if( poOutputSRS == NULL )
 //         poOutputSRS = poSrcLayer->GetSpatialRef();
-// 
+//
 // /* -------------------------------------------------------------------- */
 // /*      Find the layer.                                                 */
 // /* -------------------------------------------------------------------- */
 //     int iLayer = -1;
 //     poDstLayer = NULL;
-// 
+//
 //     for( iLayer = 0; iLayer < poDstDS->GetLayerCount(); iLayer++ )
 //     {
 //         OGRLayer        *poLayer = poDstDS->GetLayer(iLayer);
-// 
-//         if( poLayer != NULL 
+//
+//         if( poLayer != NULL
 //             && EQUAL(poLayer->GetLayerDefn()->GetName(),pszNewLayerName) )
 //         {
 //             poDstLayer = poLayer;
 //             break;
 //         }
 //     }
-//     
+//
 // /* -------------------------------------------------------------------- */
 // /*      If the user requested overwrite, and we have the layer in       */
 // /*      question we need to delete it now so it will get recreated      */
@@ -1014,13 +1004,13 @@ static int DissolveLayer( OGRDataSource *poSrcDS,
 //     {
 //         if( poDstDS->DeleteLayer( iLayer ) != OGRERR_NONE )
 //         {
-//             fprintf( stderr, 
+//             fprintf( stderr,
 //                      "DeleteLayer() failed when overwrite requested.\n" );
 //             return FALSE;
 //         }
 //         poDstLayer = NULL;
 //     }
-// 
+//
 // /* -------------------------------------------------------------------- */
 // /*      If the layer does not exist, then create it.                    */
 // /* -------------------------------------------------------------------- */
@@ -1028,27 +1018,27 @@ static int DissolveLayer( OGRDataSource *poSrcDS,
 //     {
 //         if( eGType == -2 )
 //             eGType = poFDefn->GetGeomType();
-// 
+//
 //         if( !poDstDS->TestCapability( ODsCCreateLayer ) )
 //         {
-//             fprintf( stderr, 
-//               "Layer %s not found, and CreateLayer not supported by driver.", 
+//             fprintf( stderr,
+//               "Layer %s not found, and CreateLayer not supported by driver.",
 //                      pszNewLayerName );
 //             return FALSE;
 //         }
-// 
+//
 //         CPLErrorReset();
-// 
+//
 //         poDstLayer = poDstDS->CreateLayer( pszNewLayerName, poOutputSRS,
-//                                            (OGRwkbGeometryType) eGType, 
+//                                            (OGRwkbGeometryType) eGType,
 //                                            papszLCO );
-// 
+//
 //         if( poDstLayer == NULL )
 //             return FALSE;
-// 
+//
 //         bAppend = FALSE;
 //     }
-// 
+//
 // /* -------------------------------------------------------------------- */
 // /*      Otherwise we will append to it, if append was requested.        */
 // /* -------------------------------------------------------------------- */
@@ -1059,7 +1049,7 @@ static int DissolveLayer( OGRDataSource *poSrcDS,
 //                 pszNewLayerName );
 //         return FALSE;
 //     }
-// 
+//
 // /* -------------------------------------------------------------------- */
 // /*      Add fields.  Default to copy all field.                         */
 // /*      If only a subset of all fields requested, then output only      */
@@ -1067,7 +1057,7 @@ static int DissolveLayer( OGRDataSource *poSrcDS,
 // /*      selected.                                                       */
 // /* -------------------------------------------------------------------- */
 //     int         iField;
-// 
+//
 //     if (papszSelFields && !bAppend )
 //     {
 //         for( iField=0; papszSelFields[iField] != NULL; iField++)
@@ -1077,7 +1067,7 @@ static int DissolveLayer( OGRDataSource *poSrcDS,
 //                 poDstLayer->CreateField( poFDefn->GetFieldDefn(iSrcField) );
 //             else
 //             {
-//                 printf( "Field '%s' not found in source layer.\n", 
+//                 printf( "Field '%s' not found in source layer.\n",
 //                         papszSelFields[iField] );
 //                 if( !bSkipFailures )
 //                     return FALSE;
@@ -1089,22 +1079,22 @@ static int DissolveLayer( OGRDataSource *poSrcDS,
 //         for( iField = 0; iField < poFDefn->GetFieldCount(); iField++ )
 //             poDstLayer->CreateField( poFDefn->GetFieldDefn(iField) );
 //     }
-// 
+//
 // /* -------------------------------------------------------------------- */
 // /*      Transfer features.                                              */
 // /* -------------------------------------------------------------------- */
 //     OGRFeature  *poFeature;
 //     int         nFeaturesInTransaction = 0;
-//     
+//
 //     poSrcLayer->ResetReading();
-// 
+//
 //     if( nGroupTransactions )
 //         poDstLayer->StartTransaction();
-// 
-//     while( TRUE )
+//
+//     while( true )
 //     {
 //         OGRFeature      *poDstFeature = NULL;
-// 
+//
 //         if( nFIDToFetch != OGRNullFID )
 //         {
 //             // Only fetch feature on first pass.
@@ -1115,37 +1105,37 @@ static int DissolveLayer( OGRDataSource *poSrcDS,
 //         }
 //         else
 //             poFeature = poSrcLayer->GetNextFeature();
-//         
+//
 //         if( poFeature == NULL )
 //             break;
-// 
+//
 //         if( ++nFeaturesInTransaction == nGroupTransactions )
 //         {
 //             poDstLayer->CommitTransaction();
 //             poDstLayer->StartTransaction();
 //             nFeaturesInTransaction = 0;
 //         }
-// 
+//
 //         CPLErrorReset();
 //            poFDefn = poSrcLayer->GetLayerDefn();
-// 
+//
 //         if( poDstFeature->SetFrom( poFeature, TRUE ) != OGRERR_NONE )
 //         {
 //             if( nGroupTransactions )
 //                 poDstLayer->CommitTransaction();
-//             
+//
 //             CPLError( CE_Failure, CPLE_AppDefined,
 //                       "Unable to translate feature %d from layer %s.\n",
 //                       poFeature->GetFID(), poFDefn->GetName() );
-//             
+//
 //             OGRFeature::DestroyFeature( poFeature );
 //             OGRFeature::DestroyFeature( poDstFeature );
 //             return FALSE;
 //         }
-// 
+//
 //         if( bPreserveFID )
 //             poDstFeature->SetFID( poFeature->GetFID() );
-//         
+//
 //         if( poCT && poDstFeature->GetGeometryRef() != NULL )
 //         {
 //             eErr = poDstFeature->GetGeometryRef()->transform( poCT );
@@ -1153,8 +1143,8 @@ static int DissolveLayer( OGRDataSource *poSrcDS,
 //             {
 //                 if( nGroupTransactions )
 //                     poDstLayer->CommitTransaction();
-// 
-//                 printf( "Failed to transform feature %d.\n", 
+//
+//                 printf( "Failed to transform feature %d.\n",
 //                         (int) poFeature->GetFID() );
 //                 if( !bSkipFailures )
 //                 {
@@ -1164,40 +1154,40 @@ static int DissolveLayer( OGRDataSource *poSrcDS,
 //                 }
 //             }
 //         }
-// 
+//
 //         if( poDstFeature->GetGeometryRef() != NULL && bForceToPolygon )
 //         {
-//             poDstFeature->SetGeometryDirectly( 
+//             poDstFeature->SetGeometryDirectly(
 //                 OGRGeometryFactory::forceToPolygon(
 //                     poDstFeature->StealGeometry() ) );
 //         }
-//                     
+//
 //         if( poDstFeature->GetGeometryRef() != NULL && bForceToMultiPolygon )
 //         {
-//             poDstFeature->SetGeometryDirectly( 
+//             poDstFeature->SetGeometryDirectly(
 //                 OGRGeometryFactory::forceToMultiPolygon(
 //                     poDstFeature->StealGeometry() ) );
 //         }
-//                     
+//
 //         OGRFeature::DestroyFeature( poFeature );
-// 
+//
 //         CPLErrorReset();
-//         if( poDstLayer->CreateFeature( poDstFeature ) != OGRERR_NONE 
+//         if( poDstLayer->CreateFeature( poDstFeature ) != OGRERR_NONE
 //             && !bSkipFailures )
 //         {
 //             if( nGroupTransactions )
 //                 poDstLayer->RollbackTransaction();
-// 
+//
 //             OGRFeature::DestroyFeature( poDstFeature );
 //             return FALSE;
 //         }
-// 
+//
 //         OGRFeature::DestroyFeature( poDstFeature );
 //     }
-// 
+//
 //     if( nGroupTransactions )
 //         poDstLayer->CommitTransaction();
-// 
+//
 // /* -------------------------------------------------------------------- */
 // /*      Cleaning                                                        */
 // /* -------------------------------------------------------------------- */
@@ -1205,4 +1195,3 @@ static int DissolveLayer( OGRDataSource *poSrcDS,
 
     return TRUE;
 }
-
diff --git a/apps/ogrinfo.cpp b/apps/ogrinfo.cpp
index 8f21308..76666ce 100644
--- a/apps/ogrinfo.cpp
+++ b/apps/ogrinfo.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrinfo.cpp 28977 2015-04-22 22:21:03Z rouault $
+ * $Id: ogrinfo.cpp 33615 2016-03-02 20:19:22Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Simple client for viewing OGR driver data.
@@ -36,17 +36,18 @@
 #include "cpl_multiproc.h"
 #include "commonutils.h"
 
-CPL_CVSID("$Id: ogrinfo.cpp 28977 2015-04-22 22:21:03Z rouault $");
+CPL_CVSID("$Id: ogrinfo.cpp 33615 2016-03-02 20:19:22Z goatbar $");
 
 int     bReadOnly = FALSE;
 int     bVerbose = TRUE;
+bool    bSuperQuiet = false;
 int     bSummaryOnly = FALSE;
 GIntBig nFetchFID = OGRNullFID;
 char**  papszOptions = NULL;
 
 static void Usage(const char* pszErrorMsg = NULL);
 
-static void ReportOnLayer( OGRLayer *, const char *, const char* pszGeomField, 
+static void ReportOnLayer( OGRLayer *, const char *, const char* pszGeomField,
                            OGRGeometry *,
                            int bListMDD,
                            int bShowMetadata,
@@ -59,6 +60,19 @@ static void GDALInfoReportMetadata( GDALMajorObjectH hObject,
                                     char **papszExtraMDDomains );
 
 /************************************************************************/
+/*                             RemoveBOM()                              */
+/************************************************************************/
+
+/* Remove potential UTF-8 BOM from data (must be NUL terminated) */
+static void RemoveBOM(GByte* pabyData)
+{
+    if( pabyData[0] == 0xEF && pabyData[1] == 0xBB && pabyData[2] == 0xBF )
+    {
+        memmove(pabyData, pabyData + 3, strlen((const char*)pabyData + 3) + 1);
+    }
+}
+
+/************************************************************************/
 /*                                main()                                */
 /************************************************************************/
 
@@ -69,12 +83,12 @@ static void GDALInfoReportMetadata( GDALMajorObjectH hObject,
 int main( int nArgc, char ** papszArgv )
 
 {
-    const char *pszWHERE = NULL;
+    char *pszWHERE = NULL;
     const char  *pszDataSource = NULL;
     char        **papszLayers = NULL;
     OGRGeometry *poSpatialFilter = NULL;
     int         nRepeatCount = 1, bAllLayers = FALSE;
-    const char  *pszSQLStatement = NULL;
+    char  *pszSQLStatement = NULL;
     const char  *pszDialect = NULL;
     int          nRet = 0;
     const char* pszGeomField = NULL;
@@ -83,7 +97,7 @@ int main( int nArgc, char ** papszArgv )
     int                 bListMDD = FALSE;
     int                  bShowMetadata = TRUE;
     int         bFeatureCount = TRUE, bExtent = TRUE;
-    
+
     /* Check strict compilation and runtime library version as we use C++ API */
     if (! GDAL_CHECK_VERSION(papszArgv[0]))
         exit(1);
@@ -94,12 +108,12 @@ int main( int nArgc, char ** papszArgv )
 /*      Register format(s).                                             */
 /* -------------------------------------------------------------------- */
     OGRRegisterAll();
-    
+
 /* -------------------------------------------------------------------- */
 /*      Processing command line arguments.                              */
 /* -------------------------------------------------------------------- */
     nArgc = OGRGeneralCmdLineProcessor( nArgc, &papszArgv, 0 );
-    
+
     if( nArgc < 1 )
         exit( -nArgc );
 
@@ -109,14 +123,21 @@ int main( int nArgc, char ** papszArgv )
         {
             printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
                    papszArgv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
+            CSLDestroy( papszArgv );
             return 0;
         }
         else if( EQUAL(papszArgv[iArg],"--help") )
             Usage();
-        else if( EQUAL(papszArgv[iArg],"-ro") )
+       else if( EQUAL(papszArgv[iArg],"-ro") )
             bReadOnly = TRUE;
         else if( EQUAL(papszArgv[iArg],"-q") || EQUAL(papszArgv[iArg],"-quiet"))
             bVerbose = FALSE;
+        else if( EQUAL(papszArgv[iArg],"-qq") )
+        {
+            /* Undocumented: mainly only useful for AFL testing */
+            bVerbose = FALSE;
+            bSuperQuiet = true;
+        }
         else if( EQUAL(papszArgv[iArg],"-fid") )
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
@@ -145,12 +166,36 @@ int main( int nArgc, char ** papszArgv )
         else if( EQUAL(papszArgv[iArg],"-where") )
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszWHERE = papszArgv[++iArg];
+            iArg++;
+            CPLFree(pszWHERE);
+            GByte* pabyRet = NULL;
+            if( papszArgv[iArg][0] == '@' &&
+                VSIIngestFile( NULL, papszArgv[iArg] + 1, &pabyRet, NULL, 1024*1024) )
+            {
+                RemoveBOM(pabyRet);
+                pszWHERE = (char*)pabyRet;
+            }
+            else
+            {
+                pszWHERE = CPLStrdup(papszArgv[iArg]);
+            }
         }
         else if( EQUAL(papszArgv[iArg],"-sql") )
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszSQLStatement = papszArgv[++iArg];
+            iArg++;
+            CPLFree(pszSQLStatement);
+            GByte* pabyRet = NULL;
+            if( papszArgv[iArg][0] == '@' &&
+                VSIIngestFile( NULL, papszArgv[iArg] + 1, &pabyRet, NULL, 1024*1024) )
+            {
+                RemoveBOM(pabyRet);
+                pszSQLStatement = (char*)pabyRet;
+            }
+            else
+            {
+                pszSQLStatement = CPLStrdup(papszArgv[iArg]);
+            }
         }
         else if( EQUAL(papszArgv[iArg],"-dialect") )
         {
@@ -166,22 +211,26 @@ int main( int nArgc, char ** papszArgv )
         {
             bAllLayers = TRUE;
         }
-        else if( EQUAL(papszArgv[iArg],"-so") 
+        else if( EQUAL(papszArgv[iArg],"-so")
                  || EQUAL(papszArgv[iArg],"-summary")  )
         {
             bSummaryOnly = TRUE;
         }
-        else if( EQUALN(papszArgv[iArg],"-fields=", strlen("-fields=")) )
+        else if( STARTS_WITH_CI(papszArgv[iArg], "-fields=") )
         {
             char* pszTemp = (char*)CPLMalloc(32 + strlen(papszArgv[iArg]));
-            sprintf(pszTemp, "DISPLAY_FIELDS=%s", papszArgv[iArg] + strlen("-fields="));
+            snprintf(pszTemp,
+                    32 + strlen(papszArgv[iArg]),
+                    "DISPLAY_FIELDS=%s", papszArgv[iArg] + strlen("-fields="));
             papszOptions = CSLAddString(papszOptions, pszTemp);
             CPLFree(pszTemp);
         }
-        else if( EQUALN(papszArgv[iArg],"-geom=", strlen("-geom=")) )
+        else if( STARTS_WITH_CI(papszArgv[iArg], "-geom=") )
         {
             char* pszTemp = (char*)CPLMalloc(32 + strlen(papszArgv[iArg]));
-            sprintf(pszTemp, "DISPLAY_GEOMETRY=%s", papszArgv[iArg] + strlen("-geom="));
+            snprintf(pszTemp,
+                    32 + strlen(papszArgv[iArg]),
+                    "DISPLAY_GEOMETRY=%s", papszArgv[iArg] + strlen("-geom="));
             papszOptions = CSLAddString(papszOptions, pszTemp);
             CPLFree(pszTemp);
         }
@@ -224,13 +273,14 @@ int main( int nArgc, char ** papszArgv )
     if( pszDialect != NULL && pszWHERE != NULL && pszSQLStatement == NULL )
         printf("Warning: -dialect is ignored with -where. Use -sql instead");
 
+#ifdef __AFL_HAVE_MANUAL_CONTROL
+    while (__AFL_LOOP(1000)) {
+#endif
 /* -------------------------------------------------------------------- */
 /*      Open data source.                                               */
 /* -------------------------------------------------------------------- */
-    GDALDataset        *poDS = NULL;
-    GDALDriver         *poDriver = NULL;
-
-    poDS = (GDALDataset*) GDALOpenEx( pszDataSource,
+    GDALDataset *poDS
+        = (GDALDataset*) GDALOpenEx( pszDataSource,
             (!bReadOnly ? GDAL_OF_UPDATE : GDAL_OF_READONLY) | GDAL_OF_VECTOR,
             NULL, papszOpenOptions, NULL );
     if( poDS == NULL && !bReadOnly )
@@ -243,6 +293,8 @@ int main( int nArgc, char ** papszArgv )
             bReadOnly = TRUE;
         }
     }
+
+    GDALDriver *poDriver = NULL;
     if( poDS != NULL )
         poDriver = poDS->GetDriver();
 
@@ -251,12 +303,13 @@ int main( int nArgc, char ** papszArgv )
 /* -------------------------------------------------------------------- */
     if( poDS == NULL )
     {
-        OGRSFDriverRegistrar    *poR = OGRSFDriverRegistrar::GetRegistrar();
-        
         printf( "FAILURE:\n"
                 "Unable to open datasource `%s' with the following drivers.\n",
                 pszDataSource );
-
+#ifdef __AFL_HAVE_MANUAL_CONTROL
+        continue;
+#else
+        OGRSFDriverRegistrar    *poR = OGRSFDriverRegistrar::GetRegistrar();
         for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
         {
             printf( "  -> %s\n", poR->GetDriver(iDriver)->GetDescription() );
@@ -264,6 +317,7 @@ int main( int nArgc, char ** papszArgv )
 
         nRet = 1;
         goto end;
+#endif
     }
 
     CPLAssert( poDriver != NULL);
@@ -293,16 +347,15 @@ int main( int nArgc, char ** papszArgv )
 /* -------------------------------------------------------------------- */
     if( pszSQLStatement != NULL )
     {
-        OGRLayer *poResultSet = NULL;
-
         nRepeatCount = 0;  // skip layer reporting.
 
         if( CSLCount(papszLayers) > 0 )
             printf( "layer names ignored in combination with -sql.\n" );
-        
-        poResultSet = poDS->ExecuteSQL( pszSQLStatement,
-                                        (pszGeomField == NULL) ? poSpatialFilter: NULL, 
-                                        pszDialect );
+
+        OGRLayer *poResultSet
+            = poDS->ExecuteSQL( pszSQLStatement,
+                                (pszGeomField == NULL) ? poSpatialFilter: NULL,
+                                pszDialect );
 
         if( poResultSet != NULL )
         {
@@ -327,15 +380,17 @@ int main( int nArgc, char ** papszArgv )
         }
     }
 
-    CPLDebug( "OGR", "GetLayerCount() = %d\n", poDS->GetLayerCount() );
-
+    /* coverity[tainted_data] */
     for( int iRepeat = 0; iRepeat < nRepeatCount; iRepeat++ )
     {
-        if ( CSLCount(papszLayers) == 0 )
+        if ( papszLayers == NULL || *papszLayers == NULL )
         {
-/* -------------------------------------------------------------------- */ 
-/*      Process each data source layer.                                 */ 
-/* -------------------------------------------------------------------- */ 
+            if( iRepeat == 0 )
+                CPLDebug( "OGR", "GetLayerCount() = %d\n", poDS->GetLayerCount() );
+
+/* -------------------------------------------------------------------- */
+/*      Process each data source layer.                                 */
+/* -------------------------------------------------------------------- */
             for( int iLayer = 0; iLayer < poDS->GetLayerCount(); iLayer++ )
             {
                 OGRLayer        *poLayer = poDS->GetLayer(iLayer);
@@ -364,15 +419,15 @@ int main( int nArgc, char ** papszArgv )
                                 printf(", ");
                             OGRGeomFieldDefn* poGFldDefn =
                                 poLayer->GetLayerDefn()->GetGeomFieldDefn(iGeom);
-                            printf( "%s", 
-                                OGRGeometryTypeToName( 
+                            printf( "%s",
+                                OGRGeometryTypeToName(
                                     poGFldDefn->GetType() ) );
                         }
                         printf( ")");
                     }
                     else if( poLayer->GetGeomType() != wkbUnknown )
-                        printf( " (%s)", 
-                                OGRGeometryTypeToName( 
+                        printf( " (%s)",
+                                OGRGeometryTypeToName(
                                     poLayer->GetGeomType() ) );
 
                     printf( "\n" );
@@ -390,11 +445,13 @@ int main( int nArgc, char ** papszArgv )
         }
         else
         {
-/* -------------------------------------------------------------------- */ 
-/*      Process specified data source layers.                           */ 
-/* -------------------------------------------------------------------- */ 
-            char** papszIter = papszLayers;
-            for( ; *papszIter != NULL; papszIter++ )
+/* -------------------------------------------------------------------- */
+/*      Process specified data source layers.                           */
+/* -------------------------------------------------------------------- */
+
+            for( char** papszIter = papszLayers;
+                 *papszIter != NULL;
+                 ++papszIter )
             {
                 OGRLayer        *poLayer = poDS->GetLayerByName(*papszIter);
 
@@ -418,16 +475,23 @@ int main( int nArgc, char ** papszArgv )
 /* -------------------------------------------------------------------- */
 /*      Close down.                                                     */
 /* -------------------------------------------------------------------- */
+    GDALClose( (GDALDatasetH)poDS );
+
+#ifdef __AFL_HAVE_MANUAL_CONTROL
+    }
+#else
 end:
+#endif
+
     CSLDestroy( papszArgv );
     CSLDestroy( papszLayers );
     CSLDestroy( papszOptions );
     CSLDestroy( papszOpenOptions );
     CSLDestroy( papszExtraMDDomains );
-    if( poDS != NULL )
-        GDALClose( (GDALDatasetH)poDS );
     if (poSpatialFilter)
         OGRGeometryFactory::destroyGeometry( poSpatialFilter );
+    CPLFree(pszSQLStatement);
+    CPLFree(pszWHERE);
 
     OGRCleanupAll();
 
@@ -441,9 +505,9 @@ end:
 static void Usage(const char* pszErrorMsg)
 
 {
-    printf( "Usage: ogrinfo [--help-general] [-ro] [-q] [-where restricted_where]\n"
+    printf( "Usage: ogrinfo [--help-general] [-ro] [-q] [-where restricted_where|@filename]\n"
             "               [-spat xmin ymin xmax ymax] [-geomfield field] [-fid fid]\n"
-            "               [-sql statement] [-dialect sql_dialect] [-al] [-so] [-fields={YES/NO}]\n"
+            "               [-sql statement|@filename] [-dialect sql_dialect] [-al] [-so] [-fields={YES/NO}]\n"
             "               [-geom={YES/NO/SUMMARY}] [-formats] [[-oo NAME=VALUE] ...]\n"
             "               [-nomd] [-listmdd] [-mdd domain|`all`]*\n"
             "               [-nocount] [-noextent]\n"
@@ -460,7 +524,7 @@ static void Usage(const char* pszErrorMsg)
 /************************************************************************/
 
 static void ReportOnLayer( OGRLayer * poLayer, const char *pszWHERE,
-                           const char* pszGeomField, 
+                           const char* pszGeomField,
                            OGRGeometry *poSpatialFilter,
                            int bListMDD,
                            int bShowMetadata,
@@ -501,9 +565,12 @@ static void ReportOnLayer( OGRLayer * poLayer, const char *pszWHERE,
 /* -------------------------------------------------------------------- */
 /*      Report various overall information.                             */
 /* -------------------------------------------------------------------- */
-    printf( "\n" );
-    
-    printf( "Layer name: %s\n", poLayer->GetName() );
+    if( !bSuperQuiet )
+    {
+        printf( "\n" );
+
+        printf( "Layer name: %s\n", poLayer->GetName() );
+    }
 
     GDALInfoReportMetadata( (GDALMajorObjectH)poLayer,
                             bListMDD,
@@ -520,19 +587,19 @@ static void ReportOnLayer( OGRLayer * poLayer, const char *pszWHERE,
             {
                 OGRGeomFieldDefn* poGFldDefn =
                     poLayer->GetLayerDefn()->GetGeomFieldDefn(iGeom);
-                printf( "Geometry (%s): %s\n", poGFldDefn->GetNameRef(), 
+                printf( "Geometry (%s): %s\n", poGFldDefn->GetNameRef(),
                     OGRGeometryTypeToName( poGFldDefn->GetType() ) );
             }
         }
         else
         {
-            printf( "Geometry: %s\n", 
+            printf( "Geometry: %s\n",
                     OGRGeometryTypeToName( poLayer->GetGeomType() ) );
         }
-        
+
         if( bFeatureCount )
             printf( "Feature Count: " CPL_FRMT_GIB "\n", poLayer->GetFeatureCount() );
-        
+
         OGREnvelope oExt;
         if( bExtent && nGeomFieldCount > 1 )
         {
@@ -550,12 +617,12 @@ static void ReportOnLayer( OGRLayer * poLayer, const char *pszWHERE,
         }
         else if ( bExtent && poLayer->GetExtent(&oExt, TRUE) == OGRERR_NONE)
         {
-            CPLprintf("Extent: (%f, %f) - (%f, %f)\n", 
+            CPLprintf("Extent: (%f, %f) - (%f, %f)\n",
                    oExt.MinX, oExt.MinY, oExt.MaxX, oExt.MaxY);
         }
 
         char    *pszWKT;
-        
+
         if( nGeomFieldCount > 1 )
         {
             for(int iGeom = 0;iGeom < nGeomFieldCount; iGeom ++ )
@@ -582,14 +649,14 @@ static void ReportOnLayer( OGRLayer * poLayer, const char *pszWHERE,
             else
             {
                 poLayer->GetSpatialRef()->exportToPrettyWkt( &pszWKT );
-            }            
+            }
 
             printf( "Layer SRS WKT:\n%s\n", pszWKT );
             CPLFree( pszWKT );
         }
-    
+
         if( strlen(poLayer->GetFIDColumn()) > 0 )
-            printf( "FID Column = %s\n", 
+            printf( "FID Column = %s\n",
                     poLayer->GetFIDColumn() );
 
         for(int iGeom = 0;iGeom < nGeomFieldCount; iGeom ++ )
@@ -637,7 +704,8 @@ static void ReportOnLayer( OGRLayer * poLayer, const char *pszWHERE,
     {
         while( (poFeature = poLayer->GetNextFeature()) != NULL )
         {
-            poFeature->DumpReadable( NULL, papszOptions );
+            if( !bSuperQuiet )
+                poFeature->DumpReadable( NULL, papszOptions );
             OGRFeature::DestroyFeature( poFeature );
         }
     }
@@ -646,7 +714,7 @@ static void ReportOnLayer( OGRLayer * poLayer, const char *pszWHERE,
         poFeature = poLayer->GetFeature( nFetchFID );
         if( poFeature == NULL )
         {
-            printf( "Unable to locate feature id " CPL_FRMT_GIB " on this layer.\n", 
+            printf( "Unable to locate feature id " CPL_FRMT_GIB " on this layer.\n",
                     nFetchFID );
         }
         else
@@ -665,18 +733,16 @@ static void GDALInfoPrintMetadata( GDALMajorObjectH hObject,
                                    const char *pszDisplayedname,
                                    const char *pszIndent)
 {
-    int i;
-    char **papszMetadata;
-    int bIsxml = FALSE;
+    bool bIsxml = false;
 
-    if (pszDomain != NULL && EQUALN(pszDomain, "xml:", 4))
-        bIsxml = TRUE;
+    if (pszDomain != NULL && STARTS_WITH_CI(pszDomain, "xml:"))
+        bIsxml = true;
 
-    papszMetadata = GDALGetMetadata( hObject, pszDomain );
+    char **papszMetadata = GDALGetMetadata( hObject, pszDomain );
     if( CSLCount(papszMetadata) > 0 )
     {
         printf( "%s%s:\n", pszIndent, pszDisplayedname );
-        for( i = 0; papszMetadata[i] != NULL; i++ )
+        for( int i = 0; papszMetadata[i] != NULL; i++ )
         {
             if (bIsxml)
                 printf( "%s%s\n", pszIndent, papszMetadata[i] );
@@ -730,7 +796,6 @@ static void GDALInfoReportMetadata( GDALMajorObjectH hObject,
     /* -------------------------------------------------------------------- */
     if (papszExtraMDDomains != NULL) {
         char **papszExtraMDDomainsExpanded = NULL;
-        int iMDD;
 
         if( EQUAL(papszExtraMDDomains[0], "all") &&
             papszExtraMDDomains[1] == NULL )
@@ -753,7 +818,8 @@ static void GDALInfoReportMetadata( GDALMajorObjectH hObject,
             papszExtraMDDomainsExpanded = CSLDuplicate(papszExtraMDDomains);
         }
 
-        for( iMDD = 0; iMDD < CSLCount(papszExtraMDDomainsExpanded); iMDD++ )
+        for( int iMDD = 0; papszExtraMDDomainsExpanded != NULL &&
+                           papszExtraMDDomainsExpanded[iMDD] != NULL; iMDD++ )
         {
             char pszDisplayedname[256];
             snprintf(pszDisplayedname, 256, "Metadata (%s)", papszExtraMDDomainsExpanded[iMDD]);
diff --git a/apps/ogrlineref.cpp b/apps/ogrlineref.cpp
index cf94e7c..b623bc0 100644
--- a/apps/ogrlineref.cpp
+++ b/apps/ogrlineref.cpp
@@ -44,7 +44,7 @@
 #define FIELD_FINISH "end"
 #define FIELD_SCALE_FACTOR "scale"
 #define DELTA 0.00000001 //- delta
-#define TOLLERANCE 0.00008983153
+#define TOLERANCE 0.00008983153
 
 #if defined(HAVE_GEOS)
 #if GEOS_VERSION_MAJOR > 3 || (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR >= 2)
@@ -71,7 +71,9 @@ typedef struct _curve_data
 /************************************************************************/
 /*                               Usage()                                */
 /************************************************************************/
-static void Usage(const char* pszAdditionalMsg, int bShort = TRUE)
+static void Usage(const char* pszAdditionalMsg, int bShort = TRUE) CPL_NO_RETURN;
+
+static void Usage(const char* pszAdditionalMsg, int bShort)
 {
     OGRSFDriverRegistrar        *poR = OGRSFDriverRegistrar::GetRegistrar();
 
@@ -101,7 +103,7 @@ static void Usage(const char* pszAdditionalMsg, int bShort = TRUE)
     {
         GDALDriver *poDriver = poR->GetDriver(iDriver);
 
-        if( CSLTestBoolean( CSLFetchNameValueDef(poDriver->GetMetadata(), GDAL_DCAP_CREATE, "FALSE") ) )
+        if( CPLTestBool( CSLFetchNameValueDef(poDriver->GetMetadata(), GDAL_DCAP_CREATE, "FALSE") ) )
             printf("     -f \"%s\"\n", poDriver->GetDescription());
     }
 
@@ -111,10 +113,10 @@ static void Usage(const char* pszAdditionalMsg, int bShort = TRUE)
         " -lco  NAME=VALUE: Layer creation option (format specific)\n"
         " -l src_line_datasource_name: Datasource of line path name\n"
         " -ln layer_name: Layer name in datasource (optional)\n"
-        " -lf field_name: Field name for uniq paths in layer (optional)\n"
+        " -lf field_name: Field name for unique paths in layer (optional)\n"
         " -p src_repers_datasource_name: Datasource of repers name\n"
         " -pn layer_name: Layer name in datasource (optional)\n"
-        " -pm pos_field_name: Line postion field name\n"
+        " -pm pos_field_name: Line position field name\n"
         " -pf field_name: Field name for correspondence repers of separate paths in layer (optional)\n"
         " -r src_parts_datasource_name: Parts datasource name\n"
         " -rn layer_name: Layer name in datasource (optional)\n"
@@ -146,7 +148,7 @@ static OGRLayer* SetupTargetLayer(OGRLayer * poSrcLayer, GDALDataset *poDstDS, c
     OGRSpatialReference *poOutputSRS;
 
     CPLString szLayerName;
-    
+
     if (pszNewLayerName == NULL)
     {
         szLayerName = CPLGetBasename(poDstDS->GetDescription());
@@ -171,9 +173,9 @@ static OGRLayer* SetupTargetLayer(OGRLayer * poSrcLayer, GDALDataset *poDstDS, c
     /*      Find the layer.                                                 */
     /* -------------------------------------------------------------------- */
 
-    /* GetLayerByName() can instanciate layers that would have been */
+    /* GetLayerByName() can instantiate layers that would have been */
     /* 'hidden' otherwise, for example, non-spatial tables in a */
-    /* Postgis-enabled database, so this apparently useless command is */
+    /* PostGIS-enabled database, so this apparently useless command is */
     /* not useless... (#4012) */
     CPLPushErrorHandler(CPLQuietErrorHandler);
     poDstLayer = poDstDS->GetLayerByName(szLayerName);
@@ -192,7 +194,7 @@ static OGRLayer* SetupTargetLayer(OGRLayer * poSrcLayer, GDALDataset *poDstDS, c
         }
 
         if (iLayer == nLayerCount)
-            /* shouldn't happen with an ideal driver */
+            /* should not happen with an ideal driver */
             poDstLayer = NULL;
     }
 
@@ -246,7 +248,7 @@ static OGRLayer* SetupTargetLayer(OGRLayer * poSrcLayer, GDALDataset *poDstDS, c
     }
 
     //create beg, end, scale factor fields
-    OGRFieldDefn oFieldDefn_Beg = OGRFieldDefn(FIELD_START, OFTReal);
+    OGRFieldDefn oFieldDefn_Beg(FIELD_START, OFTReal);
     if (poDstLayer->CreateField(&oFieldDefn_Beg) != OGRERR_NONE)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Create %s field failed!",
@@ -254,7 +256,7 @@ static OGRLayer* SetupTargetLayer(OGRLayer * poSrcLayer, GDALDataset *poDstDS, c
         return NULL;
     }
 
-    OGRFieldDefn oFieldDefn_End = OGRFieldDefn(FIELD_FINISH, OFTReal);
+    OGRFieldDefn oFieldDefn_End(FIELD_FINISH, OFTReal);
     if (poDstLayer->CreateField(&oFieldDefn_End) != OGRERR_NONE)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Create %s field failed!",
@@ -262,7 +264,7 @@ static OGRLayer* SetupTargetLayer(OGRLayer * poSrcLayer, GDALDataset *poDstDS, c
         return NULL;
     }
 
-    OGRFieldDefn oFieldDefn_SF = OGRFieldDefn(FIELD_SCALE_FACTOR, OFTReal);
+    OGRFieldDefn oFieldDefn_SF(FIELD_SCALE_FACTOR, OFTReal);
     if (poDstLayer->CreateField(&oFieldDefn_SF) != OGRERR_NONE)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Create %s field failed!",
@@ -273,7 +275,7 @@ static OGRLayer* SetupTargetLayer(OGRLayer * poSrcLayer, GDALDataset *poDstDS, c
     if (pszOutputSepFieldName != NULL)
     {
         OGRFieldDefn  oSepField(pszOutputSepFieldName, OFTString);
-        oSepField.SetWidth(255);
+        oSepField.SetWidth(254);
         if (poDstLayer->CreateField(&oSepField) != OGRERR_NONE)
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Create %s field failed!",
@@ -378,7 +380,7 @@ void CheckDestDataSourceNameConsistency(const char* pszDestFilename,
 // AddFeature
 //------------------------------------------------------------------------
 
-OGRErr AddFeature(OGRLayer* const poOutLayer, OGRLineString* pPart, double dfFrom, double dfTo, double dfScaleFactor, int bQuiet, const char* pszOutputSepFieldName = NULL, const char* pszOutputSepFieldValue = NULL)
+static OGRErr AddFeature(OGRLayer* const poOutLayer, OGRLineString* pPart, double dfFrom, double dfTo, double dfScaleFactor, int bQuiet, const char* pszOutputSepFieldName = NULL, const char* pszOutputSepFieldValue = NULL)
 {
     OGRFeature *poFeature;
 
@@ -410,7 +412,7 @@ OGRErr AddFeature(OGRLayer* const poOutLayer, OGRLineString* pPart, double dfFro
 //------------------------------------------------------------------------
 // CreateSubline
 //------------------------------------------------------------------------
-OGRErr CreateSubline(OGRLayer* const poPkLayer,
+static OGRErr CreateSubline(OGRLayer* const poPkLayer,
                      double dfPosBeg,
                      double dfPosEnd,
                      OGRLayer* const poOutLayer,
@@ -424,8 +426,10 @@ OGRErr CreateSubline(OGRLayer* const poPkLayer,
     pFeature = poPkLayer->GetNextFeature();
     if (NULL != pFeature)
     {
-        dfBeg = pFeature->GetFieldAsDouble(FIELD_START);
-        dfEnd = pFeature->GetFieldAsDouble(FIELD_FINISH);
+        // FIXME: Clang Static Analyzer rightly found that the following
+        // code is dead
+        /*dfBeg = pFeature->GetFieldAsDouble(FIELD_START);
+        dfEnd = pFeature->GetFieldAsDouble(FIELD_FINISH);*/
         OGRFeature::DestroyFeature(pFeature);
     }
     else
@@ -458,7 +462,7 @@ OGRErr CreateSubline(OGRLayer* const poPkLayer,
     poPkLayer->ResetReading();
 
     std::map<double, OGRFeature *> moParts;
-    
+
     while ((pFeature = poPkLayer->GetNextFeature()) != NULL)
     {
         double dfStart = pFeature->GetFieldAsDouble(FIELD_START);
@@ -466,7 +470,7 @@ OGRErr CreateSubline(OGRLayer* const poPkLayer,
     }
 
     OGRLineString SubLine;
-    
+
     if (moParts.size() == 0)
     {
         fprintf(stderr, "Get parts for positions %f - %f failed\n", dfPosBeg, dfPosEnd);
@@ -493,7 +497,7 @@ OGRErr CreateSubline(OGRLayer* const poPkLayer,
     }
     else
     {
-        int nCounter = moParts.size();
+        int nCounter = static_cast<int>(moParts.size());
         std::map<double, OGRFeature *>::iterator IT = moParts.begin();
         OGRLineString *pOutLine = new OGRLineString();
         //get first part
@@ -507,6 +511,7 @@ OGRErr CreateSubline(OGRLayer* const poPkLayer,
         OGRLineString *pSubLine = pLine->getSubLine(dfPosBegCorr, pLine->get_Length(), FALSE);
 
         pOutLine->addSubLineString(pSubLine);
+        delete pSubLine;
         OGRFeature::DestroyFeature(IT->second);
 
         ++IT;
@@ -531,20 +536,19 @@ OGRErr CreateSubline(OGRLayer* const poPkLayer,
         pSubLine = pLine->getSubLine(0, dfPosEndCorr, FALSE);
 
         pOutLine->addSubLineString(pSubLine);
+        delete pSubLine;
 
         OGRFeature::DestroyFeature(IT->second);
         //store
         return AddFeature(poOutLayer, pOutLine, dfPosBeg, dfPosEnd, 1.0, bQuiet);
     }
-
-    //should never reach here
-    return OGRERR_NONE;
 }
 
 //------------------------------------------------------------------------
 // Project
 //------------------------------------------------------------------------
-double Project(OGRLineString* pLine, OGRPoint* pPoint)
+#ifdef HAVE_GEOS_PROJECT
+static double Project(OGRLineString* pLine, OGRPoint* pPoint)
 {
     if(NULL == pLine || NULL == pPoint)
         return -1;
@@ -555,16 +559,18 @@ double Project(OGRLineString* pLine, OGRPoint* pPoint)
     pLine->EndPoint(&TestPoint);
     if(TestPoint.Equals(pPoint))
         return pLine->get_Length();
-        
-    return pLine->Project(pPoint);    
+
+    return pLine->Project(pPoint);
 }
+#endif
 
 //------------------------------------------------------------------------
 // CreatePartsFromLineString
 //------------------------------------------------------------------------
-
-OGRErr CreatePartsFromLineString(OGRLineString* pPathGeom, OGRLayer* const poPkLayer, int nMValField, double dfStep, OGRLayer* const poOutLayer, int bDisplayProgress, int bQuiet, const char* pszOutputSepFieldName = NULL, const char* pszOutputSepFieldValue = NULL)
+#ifdef HAVE_GEOS_PROJECT
+static OGRErr CreatePartsFromLineString(OGRLineString* pPathGeom, OGRLayer* const poPkLayer, int nMValField, double dfStep, OGRLayer* const poOutLayer, int bDisplayProgress, int bQuiet, const char* pszOutputSepFieldName = NULL, const char* pszOutputSepFieldValue = NULL)
 {
+    // TODO: What is a reper?
     //check repers type
     OGRwkbGeometryType eGeomType = poPkLayer->GetGeomType();
     if (wkbFlatten(eGeomType) != wkbPoint)
@@ -593,7 +599,7 @@ OGRErr CreatePartsFromLineString(OGRLineString* pPathGeom, OGRLayer* const poPkL
                         "The distance %f is already present in repers file!", dfReperPos);
                 }
             }
-            //check if reper is incide the path
+            // Check if reper is inside the path
             dfTestDistance = Project(pPathGeom, pPt);
             if (dfTestDistance < 0)
             {
@@ -602,13 +608,16 @@ OGRErr CreatePartsFromLineString(OGRLineString* pPathGeom, OGRLayer* const poPkL
                     CPLError(CE_Warning, CPLE_AppDefined,
                         "The distance %f is out of path!", dfReperPos);
                 }
+                delete pPt;
             }
             else
             {
                 double dfDist = pPathGeom->Distance(pPt);
-                if (dfDist < TOLLERANCE)
+                if (dfDist < TOLERANCE)
                     moRepers[dfReperPos] = pPt;
-            }           
+                else
+                    delete pPt;
+            }
         }
         OGRFeature::DestroyFeature(pReperFeature);
     }
@@ -659,11 +668,11 @@ OGRErr CreatePartsFromLineString(OGRLineString* pPathGeom, OGRLayer* const poPkL
         fprintf(stdout, "Create parts\n");
     }
 
-    //get first part 
+    //get first part
     //If first point is not at the beginning of the path
     //The first part should be from the beginning of the path to the first point. length == part.getLength
     OGRPoint *pPtBeg(NULL), *pPtEnd(NULL);
-    double dfPtBegPosition, dfPtEndPosition;
+    double dfPtBegPosition = 0.0, dfPtEndPosition = 0.0;
 
     if (dfDistance1 > DELTA)
     {
@@ -677,7 +686,7 @@ OGRErr CreatePartsFromLineString(OGRLineString* pPathGeom, OGRLayer* const poPkL
                 //convert to UTM/WGS84
                 OGRPoint pt;
                 pPart->Value(dfLen / 2, &pt);
-                int nZoneEnv = 30 + (pt.getX() + 3.0) / 6.0 + 0.5;
+                int nZoneEnv = static_cast<int>(30 + (pt.getX() + 3.0) / 6.0 + 0.5);
                 int nEPSG;
                 if (pt.getY() > 0)
                 {
@@ -786,7 +795,7 @@ OGRErr CreatePartsFromLineString(OGRLineString* pPathGeom, OGRLayer* const poPkL
                 //convert to UTM/WGS84
                 OGRPoint pt;
                 pPart->Value(dfLen / 2, &pt);
-                int nZoneEnv = 30 + (pt.getX() + 3.0) / 6.0 + 0.5;
+                int nZoneEnv = static_cast<int>(30 + (pt.getX() + 3.0) / 6.0 + 0.5);
                 int nEPSG;
                 if (pt.getY() > 0)
                 {
@@ -832,20 +841,25 @@ OGRErr CreatePartsFromLineString(OGRLineString* pPathGeom, OGRLayer* const poPkL
         fprintf(stdout, "\nCreate pickets\n");
     }
 
-    long nBegin = 0;
-    
+    double dfRoundBeg;
+
     if (pPtBeg != NULL)
-        nBegin = ceil(dfPtBegPosition / dfStep) * dfStep;
+        dfRoundBeg = ceil(dfPtBegPosition / dfStep) * dfStep;
     else
-        nBegin = ceil(dfBeginPosition / dfStep) * dfStep;
-
-    double dfRoundBeg = nBegin;
+        dfRoundBeg = ceil(dfBeginPosition / dfStep) * dfStep;
 
     if (pPtEnd != NULL)
         dfEndPosition = dfPtEndPosition;
 
     dfFactor = dfStep / (dfEndPosition - dfRoundBeg);
     nCount = 0;
+    for( std::map<double, OGRPoint*>::iterator oIter = moRepers.begin();
+                                               oIter != moRepers.end();
+                                               ++oIter)
+    {
+        delete oIter->second;
+    }
+
     moRepers.clear();
 
     if (pPtBeg != NULL)
@@ -875,6 +889,12 @@ OGRErr CreatePartsFromLineString(OGRLineString* pPathGeom, OGRLayer* const poPkL
         }
     }
 
+    for (int i = 0; i < (int)astSubLines.size(); i++)
+    {
+        delete astSubLines[i].pPart;
+    }
+    astSubLines.clear();
+
     if (!bQuiet)
     {
         fprintf(stdout, "\nCreate sublines\n");
@@ -910,6 +930,14 @@ OGRErr CreatePartsFromLineString(OGRLineString* pPathGeom, OGRLayer* const poPkL
         ++IT;
     }
 
+    for( std::map<double, OGRPoint*>::iterator oIter = moRepers.begin();
+                                               oIter != moRepers.end();
+                                               ++oIter)
+    {
+        delete oIter->second;
+    }
+
+
     if (!bQuiet)
     {
         fprintf(stdout, "\nSuccess!\n\n");
@@ -923,11 +951,13 @@ OGRErr CreatePartsFromLineString(OGRLineString* pPathGeom, OGRLayer* const poPkL
 
     return OGRERR_NONE;
 }
+#endif
 
 //------------------------------------------------------------------------
 // CreateParts
 //------------------------------------------------------------------------
-OGRErr CreateParts(OGRLayer* const poLnLayer, OGRLayer* const poPkLayer, int nMValField, double dfStep, OGRLayer* const poOutLayer, int bDisplayProgress, int bQuiet, const char* pszOutputSepFieldName = NULL, const char* pszOutputSepFieldValue = NULL)
+#ifdef HAVE_GEOS_PROJECT
+static OGRErr CreateParts(OGRLayer* const poLnLayer, OGRLayer* const poPkLayer, int nMValField, double dfStep, OGRLayer* const poOutLayer, int bDisplayProgress, int bQuiet, const char* pszOutputSepFieldName = NULL, const char* pszOutputSepFieldValue = NULL)
 {
     OGRErr eRetCode = OGRERR_FAILURE;
 
@@ -941,13 +971,13 @@ OGRErr CreateParts(OGRLayer* const poLnLayer, OGRLayer* const poPkLayer, int nMV
 
     poLnLayer->ResetReading();
     //get first geometry
-    //TODO: attruibute filter for path geometry 
+    // TODO: Attribute filter for path geometry.
     OGRFeature* pPathFeature = poLnLayer->GetNextFeature();
     if (NULL != pPathFeature)
     {
         OGRGeometry* pGeom = pPathFeature->GetGeometryRef();
 
-        if (wkbFlatten(pGeom->getGeometryType()) == wkbMultiLineString)
+        if (pGeom != NULL && wkbFlatten(pGeom->getGeometryType()) == wkbMultiLineString)
         {
             if (!bQuiet)
             {
@@ -972,7 +1002,9 @@ OGRErr CreateParts(OGRLayer* const poLnLayer, OGRLayer* const poPkLayer, int nMV
         {
             if (NULL != pGeom)
             {
-                eRetCode = CreatePartsFromLineString((OGRLineString*)pGeom->clone(), poPkLayer, nMValField, dfStep, poOutLayer, bDisplayProgress, bQuiet, pszOutputSepFieldName, pszOutputSepFieldValue);
+                OGRLineString* pGeomClone = (OGRLineString*)pGeom->clone();
+                eRetCode = CreatePartsFromLineString(pGeomClone, poPkLayer, nMValField, dfStep, poOutLayer, bDisplayProgress, bQuiet, pszOutputSepFieldName, pszOutputSepFieldValue);
+                delete pGeomClone;
             }
         }
 
@@ -983,13 +1015,15 @@ OGRErr CreateParts(OGRLayer* const poLnLayer, OGRLayer* const poPkLayer, int nMV
 
     return eRetCode;
 }
+#endif
 
 //------------------------------------------------------------------------
 // CreatePartsMultiple
 //------------------------------------------------------------------------
-OGRErr CreatePartsMultiple(OGRLayer* const poLnLayer, const char* pszLineSepFieldName, OGRLayer* const poPkLayer, const char* pszPicketsSepFieldName, int nMValField, double dfStep, OGRLayer* const poOutLayer, const char* pszOutputSepFieldName, int bDisplayProgress, int bQuiet)
+#ifdef HAVE_GEOS_PROJECT
+static OGRErr CreatePartsMultiple(OGRLayer* const poLnLayer, const char* pszLineSepFieldName, OGRLayer* const poPkLayer, const char* pszPicketsSepFieldName, int nMValField, double dfStep, OGRLayer* const poOutLayer, const char* pszOutputSepFieldName, int bDisplayProgress, int bQuiet)
 {
-    //read all sep field values into array
+    //read all separate field values into array
     std::set<CPLString> asIDs;
 
     OGRFeatureDefn *pDefn = poLnLayer->GetLayerDefn();
@@ -1014,11 +1048,11 @@ OGRErr CreatePartsMultiple(OGRLayer* const poLnLayer, const char* pszLineSepFiel
     {
         //create select clause
         CPLString sLineWhere;
-        sLineWhere.Printf("%s = \"%s\"", pszLineSepFieldName, it->c_str());
+        sLineWhere.Printf("%s = '%s'", pszLineSepFieldName, it->c_str());
         poLnLayer->SetAttributeFilter(sLineWhere);
 
         CPLString sPkWhere;
-        sPkWhere.Printf("%s = \"%s\"", pszPicketsSepFieldName, it->c_str());
+        sPkWhere.Printf("%s = '%s'", pszPicketsSepFieldName, it->c_str());
         poPkLayer->SetAttributeFilter(sPkWhere);
 
         if (!bQuiet)
@@ -1032,11 +1066,13 @@ OGRErr CreatePartsMultiple(OGRLayer* const poLnLayer, const char* pszLineSepFiel
 
     return OGRERR_NONE;
 }
+#endif
 
 //------------------------------------------------------------------------
 // GetPosition
 //------------------------------------------------------------------------
-OGRErr GetPosition(OGRLayer* const poPkLayer,
+#ifdef HAVE_GEOS_PROJECT
+static OGRErr GetPosition(OGRLayer* const poPkLayer,
                    double dfX,
                    double dfY,
                    CPL_UNUSED int bDisplayProgress,
@@ -1050,7 +1086,7 @@ OGRErr GetPosition(OGRLayer* const poPkLayer,
 
     poPkLayer->ResetReading();
     OGRLineString *pCloserPart = NULL;
-    double dfBeg, dfScale;
+    double dfBeg = 0.0, dfScale = 0.0;
     double dfMinDistance = std::numeric_limits<double>::max();
     OGRFeature* pFeature = NULL;
     while ((pFeature = poPkLayer->GetNextFeature()) != NULL)
@@ -1080,6 +1116,7 @@ OGRErr GetPosition(OGRLayer* const poPkLayer,
     //now we have closest part
     //get real distance
     double dfRealDist = Project(pCloserPart, &pt);
+    delete pCloserPart;
     //compute reference distance
     double dfRefDist = dfBeg + dfRealDist / dfScale;
     if (bQuiet == TRUE)
@@ -1093,11 +1130,12 @@ OGRErr GetPosition(OGRLayer* const poPkLayer,
 
     return OGRERR_NONE;
 }
+#endif
 
 //------------------------------------------------------------------------
 // GetCoordinates
 //------------------------------------------------------------------------
-OGRErr GetCoordinates(OGRLayer* const poPkLayer,
+static OGRErr GetCoordinates(OGRLayer* const poPkLayer,
                       double dfPos,
                       CPL_UNUSED int bDisplayProgress,
                       int bQuiet)
@@ -1164,23 +1202,32 @@ int main( int nArgc, char ** papszArgv )
     const char  *pszPartsDataSource = NULL;
     char  *pszOutputLayerName = NULL;
     const char  *pszLineLayerName = NULL;
+#ifdef HAVE_GEOS_PROJECT
     const char  *pszPicketsLayerName = NULL;
     const char  *pszPicketsMField = NULL;
+#endif
     const char  *pszPartsLayerName = NULL;
 
+#ifdef HAVE_GEOS_PROJECT
     const char  *pszLineSepFieldName = NULL;
     const char  *pszPicketsSepFieldName = NULL;
     const char  *pszOutputSepFieldName = "uniq_uid";
-    
+#endif
+
     char        **papszDSCO = NULL, **papszLCO = NULL;
-    
+
     operation stOper = op_unknown;
-    double dfX(-100000000), dfY(-100000000), dfPos(-100000000);
+#ifdef HAVE_GEOS_PROJECT
+    double dfX(-100000000), dfY(-100000000);
+#endif
+    double dfPos(-100000000);
 
     int bDisplayProgress = FALSE;
-    
+
     double dfPosBeg(-100000000), dfPosEnd(-100000000);
+#ifdef HAVE_GEOS_PROJECT
     double dfStep(-100000000);
+#endif
 
     /* Check strict compilation and runtime library version as we use C++ API */
     if (! GDAL_CHECK_VERSION(papszArgv[0]))
@@ -1197,7 +1244,7 @@ int main( int nArgc, char ** papszArgv )
 /*      Processing command line arguments.                              */
 /* -------------------------------------------------------------------- */
     nArgc = OGRGeneralCmdLineProcessor( nArgc, &papszArgv, 0 );
-    
+
     if( nArgc < 1 )
         exit( -nArgc );
 
@@ -1207,6 +1254,7 @@ int main( int nArgc, char ** papszArgv )
         {
             printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
                    papszArgv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
+            CSLDestroy( papszArgv );
             return 0;
         }
         else if( EQUAL(papszArgv[iArg],"--help") )
@@ -1235,7 +1283,7 @@ int main( int nArgc, char ** papszArgv )
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
             papszLCO = CSLAddString(papszLCO, papszArgv[++iArg] );
-        }        
+        }
         else if( EQUAL(papszArgv[iArg],"-create") )
         {
             stOper = op_create;
@@ -1243,105 +1291,145 @@ int main( int nArgc, char ** papszArgv )
         else if( EQUAL(papszArgv[iArg],"-get_pos") )
         {
             stOper = op_get_pos;
-        }        
+        }
         else if( EQUAL(papszArgv[iArg],"-get_coord") )
         {
             stOper = op_get_coord;
-        }        
+        }
         else if( EQUAL(papszArgv[iArg],"-get_subline") )
         {
             stOper = op_get_subline;
-        }        
+        }
         else if( EQUAL(papszArgv[iArg],"-l") )
         {
              CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
            pszLineDataSource = papszArgv[++iArg];
-        }        
+        }
         else if( EQUAL(papszArgv[iArg],"-ln") )
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
             pszLineLayerName = papszArgv[++iArg];
-        }    
+        }
         else if (EQUAL(papszArgv[iArg], "-lf"))
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+#ifdef HAVE_GEOS_PROJECT
             pszLineSepFieldName = papszArgv[++iArg];
+#else
+            fprintf( stderr, "GEOS support not enabled or incompatible version.\n" );
+            exit( 1 );
+#endif
         }
         else if( EQUAL(papszArgv[iArg],"-p") )
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
             pszPicketsDataSource = papszArgv[++iArg];
-        }        
+        }
         else if( EQUAL(papszArgv[iArg],"-pn") )
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+#ifdef HAVE_GEOS_PROJECT
             pszPicketsLayerName = papszArgv[++iArg];
-        }    
+#else
+            fprintf( stderr, "GEOS support not enabled or incompatible version.\n" );
+            exit( 1 );
+#endif
+        }
         else if( EQUAL(papszArgv[iArg],"-pm") )
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+#ifdef HAVE_GEOS_PROJECT
             pszPicketsMField = papszArgv[++iArg];
+#else
+            fprintf( stderr, "GEOS support not enabled or incompatible version.\n" );
+            exit( 1 );
+#endif
         }
         else if (EQUAL(papszArgv[iArg], "-pf"))
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+#ifdef HAVE_GEOS_PROJECT
             pszPicketsSepFieldName = papszArgv[++iArg];
+#else
+            fprintf( stderr, "GEOS support not enabled or incompatible version.\n" );
+            exit( 1 );
+#endif
         }
         else if( EQUAL(papszArgv[iArg],"-r") )
         {
              CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
            pszPartsDataSource = papszArgv[++iArg];
-        }        
+        }
         else if( EQUAL(papszArgv[iArg],"-rn") )
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
             pszPartsLayerName = papszArgv[++iArg];
-        }         
+        }
         else if( EQUAL(papszArgv[iArg],"-o") )
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
             pszOutputDataSource = papszArgv[++iArg];
-        }   
+        }
         else if( EQUAL(papszArgv[iArg],"-on") )
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
             pszOutputLayerName = CPLStrdup(papszArgv[++iArg]);
-        }        
+        }
         else if (EQUAL(papszArgv[iArg], "-of"))
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+#ifdef HAVE_GEOS_PROJECT
             pszOutputSepFieldName = papszArgv[++iArg];
+#else
+            fprintf( stderr, "GEOS support not enabled or incompatible version.\n" );
+            exit( 1 );
+#endif
         }
         else if( EQUAL(papszArgv[iArg],"-x") )
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+#ifdef HAVE_GEOS_PROJECT
             dfX = CPLAtofM(papszArgv[++iArg]);
-        } 
+#else
+            fprintf( stderr, "GEOS support not enabled or incompatible version.\n" );
+            exit( 1 );
+#endif
+        }
         else if( EQUAL(papszArgv[iArg],"-y") )
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+#ifdef HAVE_GEOS_PROJECT
             dfY = CPLAtofM(papszArgv[++iArg]);
-        } 
+#else
+            fprintf( stderr, "GEOS support not enabled or incompatible version.\n" );
+            exit( 1 );
+#endif
+        }
         else if( EQUAL(papszArgv[iArg],"-m") )
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
             dfPos = CPLAtofM(papszArgv[++iArg]);
-        }  
+        }
         else if( EQUAL(papszArgv[iArg],"-mb") )
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
             dfPosBeg = CPLAtofM(papszArgv[++iArg]);
-        }  
+        }
         else if( EQUAL(papszArgv[iArg],"-me") )
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
             dfPosEnd = CPLAtofM(papszArgv[++iArg]);
-        }  
+        }
         else if( EQUAL(papszArgv[iArg],"-s") )
         {
             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+#ifdef HAVE_GEOS_PROJECT
             dfStep = CPLAtofM(papszArgv[++iArg]);
-        }  
+#else
+            fprintf( stderr, "GEOS support not enabled or incompatible version.\n" );
+            exit( 1 );
+#endif
+        }
         else if( EQUAL(papszArgv[iArg],"-progress") )
         {
             bDisplayProgress = TRUE;
@@ -1352,7 +1440,7 @@ int main( int nArgc, char ** papszArgv )
         }
     }
 
-    
+
     if(stOper == op_create)
     {
 #ifdef HAVE_GEOS_PROJECT
@@ -1366,7 +1454,7 @@ int main( int nArgc, char ** papszArgv )
             Usage("no position field provided");
         else  if (dfStep == -100000000)
             Usage("no step provided");
-            
+
     /* -------------------------------------------------------------------- */
     /*      Open data source.                                               */
     /* -------------------------------------------------------------------- */
@@ -1384,7 +1472,7 @@ int main( int nArgc, char ** papszArgv )
         if( poLnDS == NULL )
         {
             OGRSFDriverRegistrar    *poR = OGRSFDriverRegistrar::GetRegistrar();
-            
+
             fprintf( stderr, "FAILURE:\n"
                     "Unable to open path datasource `%s' with the following drivers.\n",
                     pszLineDataSource);
@@ -1396,7 +1484,7 @@ int main( int nArgc, char ** papszArgv )
 
             exit( 1 );
         }
-        
+
         poPkDS = (GDALDataset*) OGROpen( pszPicketsDataSource, FALSE, NULL );
     /* -------------------------------------------------------------------- */
     /*      Report failure                                                  */
@@ -1404,7 +1492,7 @@ int main( int nArgc, char ** papszArgv )
         if( poPkDS == NULL )
         {
             OGRSFDriverRegistrar    *poR = OGRSFDriverRegistrar::GetRegistrar();
-            
+
             fprintf( stderr, "FAILURE:\n"
                     "Unable to open repers datasource `%s' with the following drivers.\n",
                     pszPicketsDataSource);
@@ -1416,8 +1504,7 @@ int main( int nArgc, char ** papszArgv )
 
             exit( 1 );
         }
-    
-    
+
     /* -------------------------------------------------------------------- */
     /*      Find the output driver.                                         */
     /* -------------------------------------------------------------------- */
@@ -1433,7 +1520,7 @@ int main( int nArgc, char ** papszArgv )
         {
             fprintf( stderr, "Unable to find driver `%s'.\n", pszFormat );
             fprintf( stderr,  "The following drivers are available:\n" );
-        
+
             for( iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
             {
                 fprintf( stderr,  "  -> `%s'\n", poR->GetDriver(iDriver)->GetDescription() );
@@ -1441,7 +1528,7 @@ int main( int nArgc, char ** papszArgv )
             exit( 1 );
         }
 
-        if( !CSLTestBoolean( CSLFetchNameValueDef(poDriver->GetMetadata(), GDAL_DCAP_CREATE, "FALSE") ) )
+        if( !CPLTestBool( CSLFetchNameValueDef(poDriver->GetMetadata(), GDAL_DCAP_CREATE, "FALSE") ) )
         {
             fprintf( stderr,  "%s driver does not support data source creation.\n",
                     pszFormat );
@@ -1454,7 +1541,7 @@ int main( int nArgc, char ** papszArgv )
         poODS = poDriver->Create( pszOutputDataSource, 0, 0, 0, GDT_Unknown, papszDSCO );
         if( poODS == NULL )
         {
-            fprintf( stderr,  "%s driver failed to create %s\n", 
+            fprintf( stderr,  "%s driver failed to create %s\n",
                     pszFormat, pszOutputDataSource );
             exit( 1 );
         }
@@ -1469,13 +1556,13 @@ int main( int nArgc, char ** papszArgv )
         {
             poLnLayer = poLnDS->GetLayerByName(pszLineLayerName);
         }
-        
+
         if(poLnLayer == NULL)
         {
             fprintf( stderr, "Get path layer failed.\n" );
             exit( 1 );
-        }   
-        
+        }
+
         if(pszPicketsLayerName == NULL)
         {
             poPkLayer = poPkDS->GetLayer(0);
@@ -1484,13 +1571,13 @@ int main( int nArgc, char ** papszArgv )
         {
             poPkLayer = poPkDS->GetLayerByName(pszPicketsLayerName);
         }
-        
+
         if(poPkLayer == NULL)
         {
             fprintf( stderr, "Get repers layer failed.\n" );
-            exit( 1 );    
+            exit( 1 );
         }
-                 
+
         OGRFeatureDefn *poPkFDefn = poPkLayer->GetLayerDefn();
         int nMValField = poPkFDefn->GetFieldIndex( pszPicketsMField );
 
@@ -1500,8 +1587,8 @@ int main( int nArgc, char ** papszArgv )
             if(poOutLayer == NULL)
             {
                 fprintf( stderr, "Create output layer failed.\n" );
-                exit( 1 );    
-            }    
+                exit( 1 );
+            }
 
             //do the work
             eErr = CreatePartsMultiple(poLnLayer, pszLineSepFieldName, poPkLayer, pszPicketsSepFieldName, nMValField, dfStep, poOutLayer, pszOutputSepFieldName, bDisplayProgress, bQuiet);
@@ -1512,28 +1599,28 @@ int main( int nArgc, char ** papszArgv )
             if(poOutLayer == NULL)
             {
                 fprintf( stderr, "Create output layer failed.\n" );
-                exit( 1 );    
-            }     
-        
+                exit( 1 );
+            }
+
             //do the work
             eErr = CreateParts(poLnLayer, poPkLayer, nMValField, dfStep, poOutLayer, bDisplayProgress, bQuiet);
         }
-        
-        //clean up        
+
+        //clean up
         GDALClose( (GDALDatasetH)poLnDS);
         GDALClose( (GDALDatasetH)poPkDS);
         GDALClose( (GDALDatasetH)poODS);
-            
+
         if (NULL != pszOutputLayerName)
             CPLFree(pszOutputLayerName);
 #else //HAVE_GEOS_PROJECT
         fprintf( stderr, "GEOS support not enabled or incompatible version.\n" );
-        exit( 1 );       
-#endif //HAVE_GEOS_PROJECT            
+        exit( 1 );
+#endif //HAVE_GEOS_PROJECT
     }
     else if(stOper == op_get_pos)
     {
-#ifdef HAVE_GEOS_PROJECT    
+#ifdef HAVE_GEOS_PROJECT
         GDALDataset *poPartsDS = NULL;
         OGRLayer *poPartsLayer = NULL;
 
@@ -1541,7 +1628,7 @@ int main( int nArgc, char ** papszArgv )
             Usage("no parts datasource provided");
         else if(dfX == -100000000 || dfY == -100000000)
             Usage("no coordinates provided");
-            
+
         poPartsDS = (GDALDataset*) OGROpen( pszPartsDataSource, FALSE, NULL );
     /* -------------------------------------------------------------------- */
     /*      Report failure                                                  */
@@ -1549,7 +1636,7 @@ int main( int nArgc, char ** papszArgv )
         if (poPartsDS == NULL)
         {
             OGRSFDriverRegistrar    *poR = OGRSFDriverRegistrar::GetRegistrar();
-            
+
             fprintf( stderr, "FAILURE:\n"
                     "Unable to open parts datasource `%s' with the following drivers.\n",
                     pszPicketsDataSource);
@@ -1561,7 +1648,7 @@ int main( int nArgc, char ** papszArgv )
 
             exit( 1 );
         }
-            
+
         if(pszPartsLayerName == NULL)
         {
             poPartsLayer = poPartsDS->GetLayer(0);
@@ -1570,12 +1657,12 @@ int main( int nArgc, char ** papszArgv )
         {
             poPartsLayer = poPartsDS->GetLayerByName(pszPartsLayerName);
         }
-        
+
         if (poPartsLayer == NULL)
         {
             fprintf( stderr, "Get parts layer failed.\n" );
-            exit( 1 );    
-        }  
+            exit( 1 );
+        }
 
         //do the work
         eErr = GetPosition(poPartsLayer, dfX, dfY, bDisplayProgress, bQuiet);
@@ -1584,8 +1671,8 @@ int main( int nArgc, char ** papszArgv )
         GDALClose( (GDALDatasetH)poPartsDS);
 #else //HAVE_GEOS_PROJECT
         fprintf( stderr, "GEOS support not enabled or incompatible version.\n" );
-        exit( 1 );       
-#endif //HAVE_GEOS_PROJECT            
+        exit( 1 );
+#endif //HAVE_GEOS_PROJECT
     }
     else if(stOper == op_get_coord)
     {
@@ -1596,7 +1683,7 @@ int main( int nArgc, char ** papszArgv )
             Usage("no parts datasource provided");
         else if(dfPos == -100000000)
             Usage("no position provided");
-            
+
         poPartsDS = (GDALDataset*) OGROpen(pszPartsDataSource, FALSE, NULL);
     /* -------------------------------------------------------------------- */
     /*      Report failure                                                  */
@@ -1604,7 +1691,7 @@ int main( int nArgc, char ** papszArgv )
         if (poPartsDS == NULL)
         {
             OGRSFDriverRegistrar    *poR = OGRSFDriverRegistrar::GetRegistrar();
-            
+
             fprintf( stderr, "FAILURE:\n"
                     "Unable to open parts datasource `%s' with the following drivers.\n",
                     pszPicketsDataSource);
@@ -1616,7 +1703,7 @@ int main( int nArgc, char ** papszArgv )
 
             exit( 1 );
         }
-            
+
         if(pszPartsLayerName == NULL)
         {
             poPartsLayer = poPartsDS->GetLayer(0);
@@ -1625,12 +1712,12 @@ int main( int nArgc, char ** papszArgv )
         {
             poPartsLayer = poPartsDS->GetLayerByName(pszPartsLayerName);
         }
-        
+
         if (poPartsLayer == NULL)
         {
             fprintf( stderr, "Get parts layer failed.\n" );
-            exit( 1 );    
-        }     
+            exit( 1 );
+        }
         //do the work
         eErr = GetCoordinates(poPartsLayer, dfPos, bDisplayProgress, bQuiet);
 
@@ -1699,7 +1786,7 @@ int main( int nArgc, char ** papszArgv )
             exit(1);
         }
 
-        if( !CSLTestBoolean( CSLFetchNameValueDef(poDriver->GetMetadata(), GDAL_DCAP_CREATE, "FALSE") ) )
+        if( !CPLTestBool( CSLFetchNameValueDef(poDriver->GetMetadata(), GDAL_DCAP_CREATE, "FALSE") ) )
         {
             fprintf(stderr, "%s driver does not support data source creation.\n",
                 pszFormat);
@@ -1744,7 +1831,7 @@ int main( int nArgc, char ** papszArgv )
         //do the work
         eErr = CreateSubline(poPartsLayer, dfPosBeg, dfPosEnd, poOutLayer, bDisplayProgress, bQuiet);
 
-        //clean up        
+        //clean up
         GDALClose( (GDALDatasetH) poPartsDS);
         GDALClose( (GDALDatasetH) poODS);
 
@@ -1754,8 +1841,8 @@ int main( int nArgc, char ** papszArgv )
     else
     {
         Usage("no operation provided");
-    }  
-    
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Close down.                                                     */
 /* -------------------------------------------------------------------- */
@@ -1769,6 +1856,6 @@ int main( int nArgc, char ** papszArgv )
 #ifdef DBMALLOC
     malloc_dump(1);
 #endif
-    
+
     return eErr == OGRERR_NONE ? 0 : 1;
 }
diff --git a/apps/ogrtindex.cpp b/apps/ogrtindex.cpp
index 334a3ad..6b3ebfe 100644
--- a/apps/ogrtindex.cpp
+++ b/apps/ogrtindex.cpp
@@ -1,9 +1,9 @@
 /******************************************************************************
- * $Id: ogrtindex.cpp 28387 2015-01-30 17:10:41Z rouault $
+ * $Id: ogrtindex.cpp 33615 2016-03-02 20:19:22Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Program to generate a UMN MapServer compatible tile index for a
- *           set of OGR data sources. 
+ *           set of OGR data sources.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -36,7 +36,7 @@
 
 #include <cassert>
 
-CPL_CVSID("$Id: ogrtindex.cpp 28387 2015-01-30 17:10:41Z rouault $");
+CPL_CVSID("$Id: ogrtindex.cpp 33615 2016-03-02 20:19:22Z goatbar $");
 
 static void Usage();
 
@@ -56,7 +56,7 @@ int main( int nArgc, char ** papszArgv )
     char* current_path = NULL;
     int accept_different_schemas = FALSE;
     int bFirstWarningForNonMatchingAttributes = TRUE;
-    
+
     /* Check strict compilation and runtime library version as we use C++ API */
     if (! GDAL_CHECK_VERSION(papszArgv[0]))
         exit(1);
@@ -64,7 +64,7 @@ int main( int nArgc, char ** papszArgv )
 /*      Register format(s).                                             */
 /* -------------------------------------------------------------------- */
     OGRRegisterAll();
-    
+
 /* -------------------------------------------------------------------- */
 /*      Processing command line arguments.                              */
 /* -------------------------------------------------------------------- */
@@ -96,7 +96,7 @@ int main( int nArgc, char ** papszArgv )
         {
             pszTileIndexField = papszArgv[++iArg];
         }
-        else if( EQUAL(papszArgv[iArg],"-lnum") 
+        else if( EQUAL(papszArgv[iArg],"-lnum")
                  || EQUAL(papszArgv[iArg],"-lname") )
         {
             iArg++;
@@ -144,7 +144,7 @@ int main( int nArgc, char ** papszArgv )
         {
             fprintf( stderr, "Unable to find driver `%s'.\n", pszFormat );
             fprintf( stderr, "The following drivers are available:\n" );
-        
+
             for( iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
             {
                 fprintf( stderr, "  -> `%s'\n", poR->GetDriver(iDriver)->GetDescription() );
@@ -152,7 +152,7 @@ int main( int nArgc, char ** papszArgv )
             exit( 1 );
         }
 
-        if( !CSLTestBoolean( CSLFetchNameValueDef(poDriver->GetMetadata(), GDAL_DCAP_CREATE, "FALSE") ) )
+        if( !CPLTestBool( CSLFetchNameValueDef(poDriver->GetMetadata(), GDAL_DCAP_CREATE, "FALSE") ) )
         {
             fprintf( stderr, "%s driver does not support data source creation.\n",
                     pszFormat );
@@ -162,11 +162,11 @@ int main( int nArgc, char ** papszArgv )
 /* -------------------------------------------------------------------- */
 /*      Now create it.                                                  */
 /* -------------------------------------------------------------------- */
-        
+
         poDstDS = poDriver->Create( pszOutputName, 0, 0, 0, GDT_Unknown, NULL );
         if( poDstDS == NULL )
         {
-            fprintf( stderr, "%s driver failed to create %s\n", 
+            fprintf( stderr, "%s driver failed to create %s\n",
                     pszFormat, pszOutputName );
             exit( 1 );
         }
@@ -174,16 +174,16 @@ int main( int nArgc, char ** papszArgv )
         if( poDstDS->GetLayerCount() == 0 )
         {
             OGRFieldDefn oLocation( pszTileIndexField, OFTString );
-            
+
             oLocation.SetWidth( 200 );
-            
+
             if( nFirstSourceDataset < nArgc && papszArgv[nFirstSourceDataset][0] == '-' )
             {
                 nFirstSourceDataset++;
             }
-            
+
             OGRSpatialReference* poSrcSpatialRef = NULL;
-            
+
             /* Fetches the SRS of the first layer and use it when creating the tileindex layer */
             if (nFirstSourceDataset < nArgc)
             {
@@ -199,10 +199,10 @@ int main( int nArgc, char ** papszArgv )
 
                         for( iArg = 1; iArg < nArgc && !bRequested; iArg++ )
                         {
-                            if( EQUAL(papszArgv[iArg],"-lnum") 
+                            if( EQUAL(papszArgv[iArg],"-lnum")
                                 && atoi(papszArgv[iArg+1]) == iLayer )
                                 bRequested = TRUE;
-                            else if( EQUAL(papszArgv[iArg],"-lname") 
+                            else if( EQUAL(papszArgv[iArg],"-lname")
                                      && EQUAL(papszArgv[iArg+1],
                                               poLayer->GetLayerDefn()->GetName()) )
                                 bRequested = TRUE;
@@ -210,19 +210,19 @@ int main( int nArgc, char ** papszArgv )
 
                         if( !bRequested )
                             continue;
-                            
+
                         if ( poLayer->GetSpatialRef() )
                             poSrcSpatialRef = poLayer->GetSpatialRef()->Clone();
                         break;
                     }
                 }
-                
+
                 GDALClose( (GDALDatasetH)poDS );
             }
 
             poDstLayer = poDstDS->CreateLayer( "tileindex", poSrcSpatialRef );
             poDstLayer->CreateField( &oLocation, OFTString );
-            
+
             OGRSpatialReference::DestroySpatialReference( poSrcSpatialRef );
         }
     }
@@ -239,11 +239,11 @@ int main( int nArgc, char ** papszArgv )
         exit( 1 );
     }
 
-    iTileIndexField = 
+    iTileIndexField =
         poDstLayer->GetLayerDefn()->GetFieldIndex( pszTileIndexField );
     if( iTileIndexField == -1 )
     {
-        fprintf( stderr, "Can't find %s field in tile index dataset.\n", 
+        fprintf( stderr, "Can't find %s field in tile index dataset.\n",
                 pszTileIndexField );
         exit( 1 );
     }
@@ -269,7 +269,7 @@ int main( int nArgc, char ** papszArgv )
                 GDALDataset       *poDS;
                 char* filename = CPLStrdup(existingLayersTab[i]);
                 int j;
-                for(j=strlen(filename)-1;j>=0;j--)
+                for(j=static_cast<int>(strlen(filename))-1;j>=0;j--)
                 {
                     if (filename[j] == ',')
                         break;
@@ -287,7 +287,7 @@ int main( int nArgc, char ** papszArgv )
                             alreadyExistingSpatialRefValid = TRUE;
                             alreadyExistingSpatialRef =
                                     (poLayer->GetSpatialRef()) ? poLayer->GetSpatialRef()->Clone() : NULL;
-                                    
+
                             if (poFeatureDefn == NULL)
                                 poFeatureDefn = poLayer->GetLayerDefn()->Clone();
                         }
@@ -323,7 +323,7 @@ int main( int nArgc, char ** papszArgv )
             nFirstSourceDataset++;
             continue;
         }
-        
+
         char* fileNameToWrite;
         VSIStatBuf sStatBuf;
 
@@ -341,7 +341,7 @@ int main( int nArgc, char ** papszArgv )
 
         if( poDS == NULL )
         {
-            fprintf( stderr, "Failed to open dataset %s, skipping.\n", 
+            fprintf( stderr, "Failed to open dataset %s, skipping.\n",
                     papszArgv[nFirstSourceDataset] );
             CPLFree(fileNameToWrite);
             continue;
@@ -359,10 +359,10 @@ int main( int nArgc, char ** papszArgv )
 
             for( iArg = 1; iArg < nArgc && !bRequested; iArg++ )
             {
-                if( EQUAL(papszArgv[iArg],"-lnum") 
+                if( EQUAL(papszArgv[iArg],"-lnum")
                     && atoi(papszArgv[iArg+1]) == iLayer )
                     bRequested = TRUE;
-                else if( EQUAL(papszArgv[iArg],"-lname") 
+                else if( EQUAL(papszArgv[iArg],"-lname")
                          && EQUAL(papszArgv[iArg+1],
                                   poLayer->GetLayerDefn()->GetName()) )
                     bRequested = TRUE;
@@ -375,7 +375,7 @@ int main( int nArgc, char ** papszArgv )
             for(i=0;i<nExistingLayers;i++)
             {
                 char        szLocation[5000];
-                sprintf( szLocation, "%s,%d", 
+                snprintf( szLocation, sizeof(szLocation), "%s,%d",
                         fileNameToWrite, iLayer );
                 if (EQUAL(szLocation, existingLayersTab[i]))
                 {
@@ -438,20 +438,20 @@ int main( int nArgc, char ** papszArgv )
                     }
 					continue;
 				}
-				
+
                 int bSkip = FALSE;
 				for( int fn = 0; fn < poFeatureDefnCur->GetFieldCount(); fn++ )
 				{
  					OGRFieldDefn* poField = poFeatureDefn->GetFieldDefn(fn);
  					OGRFieldDefn* poFieldCur = poFeatureDefnCur->GetFieldDefn(fn);
 
-					/* XXX - Should those pointers be checked against NULL? */ 
+					/* XXX - Should those pointers be checked against NULL? */
 					assert(NULL != poField);
 					assert(NULL != poFieldCur);
 
-					if( poField->GetType() != poFieldCur->GetType() 
-						|| poField->GetWidth() != poFieldCur->GetWidth() 
-						|| poField->GetPrecision() != poFieldCur->GetPrecision() 
+					if( poField->GetType() != poFieldCur->GetType()
+						|| poField->GetWidth() != poFieldCur->GetWidth()
+						|| poField->GetPrecision() != poFieldCur->GetPrecision()
 						|| !EQUAL( poField->GetNameRef(), poFieldCur->GetNameRef() ) )
 					{
 						fprintf( stderr, "Schema of attributes of layer %s of %s does not match ... skipping it.\n",
@@ -462,11 +462,11 @@ int main( int nArgc, char ** papszArgv )
                                              "but this may result in a tileindex incompatible with MapServer\n");
                             bFirstWarningForNonMatchingAttributes = FALSE;
                         }
-                        bSkip = TRUE; 
+                        bSkip = TRUE;
                         break;
 					}
 				}
-                
+
                 if (bSkip)
                     continue;
 			}
@@ -482,12 +482,12 @@ int main( int nArgc, char ** papszArgv )
 
             if( poLayer->GetExtent( &sExtents, TRUE ) != OGRERR_NONE )
             {
-                fprintf( stderr, "GetExtent() failed on layer %s of %s, skipping.\n", 
-                        poLayer->GetLayerDefn()->GetName(), 
+                fprintf( stderr, "GetExtent() failed on layer %s of %s, skipping.\n",
+                        poLayer->GetLayerDefn()->GetName(),
                         papszArgv[nFirstSourceDataset] );
                 continue;
             }
-            
+
             oRing.addPoint( sExtents.MinX, sExtents.MinY );
             oRing.addPoint( sExtents.MinX, sExtents.MaxY );
             oRing.addPoint( sExtents.MaxX, sExtents.MaxY );
@@ -502,7 +502,7 @@ int main( int nArgc, char ** papszArgv )
             char        szLocation[5000];
             OGRFeature  oTileFeat( poDstLayer->GetLayerDefn() );
 
-            sprintf( szLocation, "%s,%d", 
+            snprintf( szLocation, sizeof(szLocation), "%s,%d",
                      fileNameToWrite, iLayer );
             oTileFeat.SetGeometry( &oRegion );
             oTileFeat.SetField( iTileIndexField, szLocation );
@@ -527,12 +527,12 @@ int main( int nArgc, char ** papszArgv )
 /* -------------------------------------------------------------------- */
     GDALClose( (GDALDatasetH) poDstDS );
 	OGRFeatureDefn::DestroyFeatureDefn( poFeatureDefn );
-  
+
     if (alreadyExistingSpatialRef != NULL)
         OGRSpatialReference::DestroySpatialReference( alreadyExistingSpatialRef );
-  
+
     CPLFree(current_path);
-    
+
     if (nExistingLayers)
     {
         int i;
diff --git a/apps/test_ogrsf.cpp b/apps/test_ogrsf.cpp
index 9fdf23e..34c7d84 100644
--- a/apps/test_ogrsf.cpp
+++ b/apps/test_ogrsf.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: test_ogrsf.cpp 29262 2015-05-29 09:28:38Z rouault $
+ * $Id: test_ogrsf.cpp 33647 2016-03-05 16:43:00Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
- * Purpose:  Formal test harnass for OGRLayer implementations.
+ * Purpose:  Formal test harness for OGRLayer implementations.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -35,7 +35,9 @@
 #include "ogr_p.h"
 #include "commonutils.h"
 
-CPL_CVSID("$Id: test_ogrsf.cpp 29262 2015-05-29 09:28:38Z rouault $");
+#include <limits>
+
+CPL_CVSID("$Id: test_ogrsf.cpp 33647 2016-03-05 16:43:00Z rouault $");
 
 int     bReadOnly = FALSE;
 int     bVerbose = TRUE;
@@ -118,6 +120,7 @@ int main( int nArgc, char ** papszArgv )
         {
             printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
                    papszArgv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
+            CSLDestroy(papszArgv);
             return 0;
         }
         else if( EQUAL(papszArgv[iArg],"-ro") )
@@ -213,11 +216,11 @@ int main( int nArgc, char ** papszArgv )
     CSLDestroy(papszOpenOptions);
     CSLDestroy(papszDSCO);
     CSLDestroy(papszLCO);
-    
+
 #ifdef DBMALLOC
     malloc_dump(1);
 #endif
-    
+
     return (bRet) ? 0 : 1;
 }
 
@@ -230,10 +233,16 @@ static void ThreadFunction( void* user_data )
 {
     ThreadContext* psContext = (ThreadContext* )user_data;
     psContext->bRet = TRUE;
+#ifdef __AFL_HAVE_MANUAL_CONTROL
+    while (__AFL_LOOP(1000)) {
+#endif
     for( int iLoop = 0; psContext->bRet && iLoop < nLoops; iLoop ++ )
     {
         ThreadFunctionInternal(psContext);
     }
+#ifdef __AFL_HAVE_MANUAL_CONTROL
+    }
+#endif
 }
 
 /************************************************************************/
@@ -312,7 +321,7 @@ static int TestDataset( GDALDriver** ppoDriver )
     if( poDS == NULL )
     {
         OGRSFDriverRegistrar    *poR = OGRSFDriverRegistrar::GetRegistrar();
-        
+
         printf( "FAILURE:\n"
                 "Unable to open datasource `%s' with the following drivers.\n",
                 pszDataSource );
@@ -338,13 +347,14 @@ static int TestDataset( GDALDriver** ppoDriver )
                 "      different from user name `%s'.\n",
                 poDS->GetDescription(), pszDataSource );
     }
-    
+
 /* -------------------------------------------------------------------- */
-/*      Process optionnal SQL request.                                  */
+/*      Process optional SQL request.                                   */
 /* -------------------------------------------------------------------- */
     if (pszSQLStatement != NULL)
     {
-        OGRLayer  *poResultSet = poDS->ExecuteSQL(pszSQLStatement, NULL, pszDialect);
+        OGRLayer *poResultSet
+            = poDS->ExecuteSQL(pszSQLStatement, NULL, pszDialect);
         if (poResultSet == NULL)
         {
             GDALClose( (GDALDatasetH)poDS );
@@ -357,7 +367,7 @@ static int TestDataset( GDALDriver** ppoDriver )
                         poResultSet->GetName() );
         }
         bRet = TestOGRLayer( poDS, poResultSet, TRUE );
-        
+
         poDS->ReleaseResultSet(poResultSet);
 
         bRetLocal = TestDSErrorConditions(poDS);
@@ -422,14 +432,14 @@ static int TestDataset( GDALDriver** ppoDriver )
                 GDALClose( (GDALDatasetH)poDS );
                 return FALSE;
             }
-            
+
             if( bVerbose )
             {
                 printf( "INFO: Testing layer %s.\n",
                         poLayer->GetName() );
             }
             bRet &= TestOGRLayer( poDS, poLayer, FALSE );
-            
+
             papszLayerIter ++;
         }
 
@@ -528,27 +538,29 @@ static int TestCreateLayer( GDALDriver* poDriver, OGRwkbGeometryType eGeomType )
                    poDriver->GetDescription());
             bRet = FALSE;
         }
-        
+
         if( LOG_ACTION(poLayer->GetLayerDefn()) == NULL )
         {
             printf("ERROR: %s: GetLayerDefn() returns NUL just after layer creation.\n",
                    poDriver->GetDescription());
             bRet = FALSE;
         }
-        
+
         // Create fields of various types
         int bCreateField = LOG_ACTION(poLayer->TestCapability(OLCCreateField));
         int iFieldStr = -1, iFieldInt = -1, iFieldReal = -1, iFieldDate = -1, iFieldDateTime = -1;
-
-        OGRFieldDefn oFieldStr("str", OFTString);
-        CPLPushErrorHandler(CPLQuietErrorHandler);
-        int bStrFieldOK = (LOG_ACTION(poLayer->CreateField(&oFieldStr)) == OGRERR_NONE);
-        CPLPopErrorHandler();
-        if( bStrFieldOK && (iFieldStr = LOG_ACTION(poLayer->GetLayerDefn())->GetFieldIndex("str")) < 0 )
+        int bStrFieldOK;
         {
-            printf("ERROR: %s: CreateField(str) returned OK but field was not created.\n",
-                   poDriver->GetDescription());
-            bRet = FALSE;
+            OGRFieldDefn oFieldStr("str", OFTString);
+            CPLPushErrorHandler(CPLQuietErrorHandler);
+            bStrFieldOK = (LOG_ACTION(poLayer->CreateField(&oFieldStr)) == OGRERR_NONE);
+            CPLPopErrorHandler();
+            if( bStrFieldOK && (iFieldStr = LOG_ACTION(poLayer->GetLayerDefn())->GetFieldIndex("str")) < 0 )
+            {
+                printf("ERROR: %s: CreateField(str) returned OK but field was not created.\n",
+                    poDriver->GetDescription());
+                bRet = FALSE;
+            }
         }
 
         OGRFieldDefn oFieldInt("int", OFTInteger);
@@ -685,7 +697,7 @@ static int TestCreateLayer( GDALDriver* poDriver, OGRwkbGeometryType eGeomType )
                    poDriver->GetDescription(), __LINE__);
         }
         delete poFeature;
-        
+
         /* Test feature with incompatible geometry */
         poFeature = new OGRFeature( poLayer->GetLayerDefn() );
         if( bStrFieldOK )
@@ -730,7 +742,7 @@ static int TestCreateLayer( GDALDriver* poDriver, OGRwkbGeometryType eGeomType )
         LOG_ACTION(poLayer->ResetReading());
         delete LOG_ACTION(poLayer->GetNextFeature());
         CPLPopErrorHandler();
-        
+
         osLayerNameToTest = poLayer->GetName();
         eExpectedGeomType = poLayer->GetGeomType();
 
@@ -752,7 +764,7 @@ static int TestCreateLayer( GDALDriver* poDriver, OGRwkbGeometryType eGeomType )
             CPLPopErrorHandler();
 
             poFeature = new OGRFeature( poLayer2->GetLayerDefn() );
-            const char* pszWKT = GetWKT(eGeomType);
+            pszWKT = GetWKT(eGeomType);
             if( pszWKT != NULL )
             {
                 OGRGeometry* poGeom = NULL;
@@ -777,7 +789,7 @@ static int TestCreateLayer( GDALDriver* poDriver, OGRwkbGeometryType eGeomType )
         CPLPushErrorHandler(CPLQuietErrorHandler);
         eErr = LOG_ACTION(poDS->DeleteLayer(0));
         CPLPopErrorHandler();
-        if( eErr == CE_None )
+        if( eErr == OGRERR_NONE )
         {
             if( !bDeleteLayerCap )
             {
@@ -785,7 +797,7 @@ static int TestCreateLayer( GDALDriver* poDriver, OGRwkbGeometryType eGeomType )
                    poDriver->GetDescription());
                 bRet = FALSE;
             }
-            
+
             if( LOG_ACTION(poDS->GetLayerByName(CPLGetFilename(osFilename))) != NULL )
             {
                 printf("ERROR: %s: DeleteLayer() declared success, but layer can still be fetched.\n",
@@ -828,15 +840,17 @@ static int TestCreateLayer( GDALDriver* poDriver, OGRwkbGeometryType eGeomType )
             {
                 if( poLayer->GetGeomType() != eExpectedGeomType )
                 {
-                    printf("ERROR: %s: GetGeomType() returns %d but %d was expected (and %d originaly set).\n",
-                    poDriver->GetDescription(), poLayer->GetGeomType(), eExpectedGeomType, eGeomType);
+                    printf( "ERROR: %s: GetGeomType() returns %d but %d "
+                            "was expected (and %d originally set).\n",
+                            poDriver->GetDescription(), poLayer->GetGeomType(),
+                            eExpectedGeomType, eGeomType);
                     bRet = FALSE;
                 }
             }
             LOG_ACTION(GDALClose(poDS));
         }
     }
-    
+
     CPLPushErrorHandler(CPLQuietErrorHandler);
     LOG_ACTION(poDriver->Delete(osFilename));
     CPLPopErrorHandler();
@@ -853,7 +867,7 @@ static int TestCreateLayer( GDALDriver* poDriver, OGRwkbGeometryType eGeomType )
             poLayer = LOG_ACTION(poDS->CreateLayer(CPLGetFilename(osFilename), NULL, eGeomType));
             CPLPopErrorHandler();
             LOG_ACTION(GDALClose(poDS));
-        
+
             CPLPushErrorHandler(CPLQuietErrorHandler);
             LOG_ACTION(poDriver->Delete(osFilename));
             CPLPopErrorHandler();
@@ -888,12 +902,12 @@ static int TestCreate( GDALDriver* poDriver, int bFromAllDrivers )
     CPLPopErrorHandler();
     if( poDS != NULL )
     {
-        /* Sometimes actual file creation is differed */
+        /* Sometimes actual file creation is deferred */
         CPLPushErrorHandler(CPLQuietErrorHandler);
         OGRLayer* poLayer = LOG_ACTION(poDS->CreateLayer("test", NULL, wkbPoint));
         CPLPopErrorHandler();
 
-        /* Or sometimes writing is differed at dataset closing */
+        /* Or sometimes writing is deferred at dataset closing */
         CPLErrorReset();
         CPLPushErrorHandler(CPLQuietErrorHandler);
         LOG_ACTION(GDALClose(poDS));
@@ -970,7 +984,7 @@ static int TestBasic( OGRLayer *poLayer )
                 "poLayer->GetDescription() = %s\n",
                     pszLayerName, poLayer->GetDescription());
     }
-    
+
     if( eGeomType != LOG_ACTION(poFDefn->GetGeomType()) )
     {
         bRet = FALSE;
@@ -1126,7 +1140,7 @@ bye:
 /*                          GetLayerNameForSQL()                        */
 /************************************************************************/
 
-const char* GetLayerNameForSQL( GDALDataset* poDS, const char* pszLayerName )
+static const char* GetLayerNameForSQL( GDALDataset* poDS, const char* pszLayerName )
 {
     int i;
     char ch;
@@ -1163,6 +1177,9 @@ const char* GetLayerNameForSQL( GDALDataset* poDS, const char* pszLayerName )
     if (EQUAL(poDS->GetDriverName(), "SQLAnywhere"))
         return pszLayerName;
 
+    if (EQUAL(poDS->GetDriverName(), "DB2ODBC"))
+        return pszLayerName;
+
     return CPLSPrintf("\"%s\"", pszLayerName);
 }
 
@@ -1214,7 +1231,7 @@ static int TestOGRLayerFeatureCount( GDALDataset* poDS, OGRLayer *poLayer, int b
                 && !bWarnAboutSRS )
             {
                 char        *pszLayerSRSWKT, *pszFeatureSRSWKT;
-                
+
                 bWarnAboutSRS = TRUE;
 
                 if( poGFldSRS != NULL )
@@ -1238,7 +1255,7 @@ static int TestOGRLayerFeatureCount( GDALDataset* poDS, OGRLayer *poLayer, int b
                 CPLFree( pszFeatureSRSWKT );
             }
         }
-        
+
         OGRFeature::DestroyFeature(poFeature);
     }
 
@@ -1265,7 +1282,7 @@ static int TestOGRLayerFeatureCount( GDALDataset* poDS, OGRLayer *poLayer, int b
     }
     else if( bVerbose )
         printf( "INFO: Feature count verified.\n" );
-        
+
     if (!bIsSQLLayer)
     {
         CPLString osSQL;
@@ -1316,14 +1333,14 @@ static int TestOGRLayerRandomRead( OGRLayer *poLayer )
     int         iFeature;
 
     LOG_ACTION(poLayer->SetSpatialFilter( NULL ));
-    
+
     if( LOG_ACTION(poLayer->GetFeatureCount()) < 5 )
     {
         if( bVerbose )
             printf( "INFO: Only " CPL_FRMT_GIB " features on layer,"
                     "skipping random read test.\n",
                     poLayer->GetFeatureCount() );
-        
+
         return bRet;
     }
 
@@ -1331,7 +1348,7 @@ static int TestOGRLayerRandomRead( OGRLayer *poLayer )
 /*      Fetch five features.                                            */
 /* -------------------------------------------------------------------- */
     LOG_ACTION(poLayer->ResetReading());
-    
+
     for( iFeature = 0; iFeature < 5; iFeature++ )
     {
         papoFeatures[iFeature] = NULL;
@@ -1438,14 +1455,14 @@ static int TestOGRLayerSetNextByIndex( OGRLayer *poLayer )
     memset(papoFeatures, 0, sizeof(papoFeatures));
 
     LOG_ACTION(poLayer->SetSpatialFilter( NULL ));
-    
+
     if( LOG_ACTION(poLayer->GetFeatureCount()) < 5 )
     {
         if( bVerbose )
             printf( "INFO: Only " CPL_FRMT_GIB " features on layer,"
                     "skipping SetNextByIndex test.\n",
                     poLayer->GetFeatureCount() );
-        
+
         return bRet;
     }
 
@@ -1453,7 +1470,7 @@ static int TestOGRLayerSetNextByIndex( OGRLayer *poLayer )
 /*      Fetch five features.                                            */
 /* -------------------------------------------------------------------- */
     LOG_ACTION(poLayer->ResetReading());
-    
+
     for( iFeature = 0; iFeature < 5; iFeature++ )
     {
         papoFeatures[iFeature] = LOG_ACTION(poLayer->GetNextFeature());
@@ -1474,7 +1491,7 @@ static int TestOGRLayerSetNextByIndex( OGRLayer *poLayer )
         printf( "ERROR: SetNextByIndex(%d) failed.\n", 1 );
         goto end;
     }
-    
+
     poFeature = LOG_ACTION(poLayer->GetNextFeature());
     if( poFeature == NULL || !poFeature->Equal( papoFeatures[1] ) )
     {
@@ -1488,7 +1505,7 @@ static int TestOGRLayerSetNextByIndex( OGRLayer *poLayer )
     }
 
     OGRFeature::DestroyFeature(poFeature);
-    
+
     poFeature = LOG_ACTION(poLayer->GetNextFeature());
     if( poFeature == NULL || !poFeature->Equal( papoFeatures[2] ) )
     {
@@ -1503,7 +1520,7 @@ static int TestOGRLayerSetNextByIndex( OGRLayer *poLayer )
 
     OGRFeature::DestroyFeature(poFeature);
     poFeature = NULL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Test feature at index 3.                                        */
 /* -------------------------------------------------------------------- */
@@ -1513,7 +1530,7 @@ static int TestOGRLayerSetNextByIndex( OGRLayer *poLayer )
         printf( "ERROR: SetNextByIndex(%d) failed.\n", 3 );
         goto end;
     }
-    
+
     poFeature = LOG_ACTION(poLayer->GetNextFeature());
     if( !poFeature->Equal( papoFeatures[3] ) )
     {
@@ -1527,7 +1544,7 @@ static int TestOGRLayerSetNextByIndex( OGRLayer *poLayer )
     }
 
     OGRFeature::DestroyFeature(poFeature);
-    
+
     poFeature = LOG_ACTION(poLayer->GetNextFeature());
     if( !poFeature->Equal( papoFeatures[4] ) )
     {
@@ -1581,7 +1598,7 @@ static int TestOGRLayerRandomWrite( OGRLayer *poLayer )
             printf( "INFO: Only " CPL_FRMT_GIB " features on layer,"
                     "skipping random write test.\n",
                     poLayer->GetFeatureCount() );
-        
+
         return bRet;
     }
 
@@ -1597,7 +1614,7 @@ static int TestOGRLayerRandomWrite( OGRLayer *poLayer )
 /*      Fetch five features.                                            */
 /* -------------------------------------------------------------------- */
     LOG_ACTION(poLayer->ResetReading());
-    
+
     for( iFeature = 0; iFeature < 5; iFeature++ )
     {
         papoFeatures[iFeature] = LOG_ACTION(poLayer->GetNextFeature());
@@ -1686,15 +1703,6 @@ end:
     return bRet;
 }
 
-#ifndef INFINITY
-    static CPL_INLINE double CPLInfinity(void)
-    {
-        static double ZERO = 0;
-        return 1.0 / ZERO; /* MSVC doesn't like 1.0 / 0.0 */
-    }
-    #define INFINITY CPLInfinity()
-#endif
-
 /************************************************************************/
 /*                         TestSpatialFilter()                          */
 /*                                                                      */
@@ -1760,13 +1768,13 @@ static int TestSpatialFilter( OGRLayer *poLayer, int iGeomField )
 /* -------------------------------------------------------------------- */
 /*      Construct inclusive filter.                                     */
 /* -------------------------------------------------------------------- */
-    
+
     oRing.setPoint( 0, sEnvelope.MinX - 2 * epsilon, sEnvelope.MinY - 2 * epsilon );
     oRing.setPoint( 1, sEnvelope.MinX - 2 * epsilon, sEnvelope.MaxY + 1 * epsilon );
     oRing.setPoint( 2, sEnvelope.MaxX + 1 * epsilon, sEnvelope.MaxY + 1 * epsilon );
     oRing.setPoint( 3, sEnvelope.MaxX + 1 * epsilon, sEnvelope.MinY - 2 * epsilon );
     oRing.setPoint( 4, sEnvelope.MinX - 2 * epsilon, sEnvelope.MinY - 2 * epsilon );
-    
+
     oInclusiveFilter.addRing( &oRing );
 
     LOG_ACTION(poLayer->SetSpatialFilter( iGeomField, &oInclusiveFilter ));
@@ -1808,7 +1816,7 @@ static int TestSpatialFilter( OGRLayer *poLayer, int iGeomField )
     oRing.setPoint( 2, sEnvelope.MinX - 1 * epsilon, sEnvelope.MinY - 1 * epsilon );
     oRing.setPoint( 3, sEnvelope.MinX - 2 * epsilon, sEnvelope.MinY - 1 * epsilon );
     oRing.setPoint( 4, sEnvelope.MinX - 2 * epsilon, sEnvelope.MinY - 2 * epsilon );
-    
+
     oExclusiveFilter.addRing( &oRing );
 
     LOG_ACTION(poLayer->SetSpatialFilter( iGeomField, &oExclusiveFilter ));
@@ -1888,8 +1896,8 @@ static int TestSpatialFilter( OGRLayer *poLayer, int iGeomField )
 /*     Test infinity envelope                                           */
 /* -------------------------------------------------------------------- */
 
-#define NEG_INF -INFINITY
-#define POS_INF INFINITY
+#define NEG_INF -std::numeric_limits<double>::infinity()
+#define POS_INF std::numeric_limits<double>::infinity()
 
     oRing.setPoint( 0, NEG_INF, NEG_INF );
     oRing.setPoint( 1, NEG_INF, POS_INF );
@@ -2029,7 +2037,7 @@ static int TestFullSpatialFilter( OGRLayer *poLayer, int iGeomField )
         oRing.setPoint( 2, sEnvelope.MaxX + 1 * epsilon, sEnvelope.MaxY + 1 * epsilon );
         oRing.setPoint( 3, sEnvelope.MaxX + 1 * epsilon, sEnvelope.MinY - 2 * epsilon );
         oRing.setPoint( 4, sEnvelope.MinX - 2 * epsilon, sEnvelope.MinY - 2 * epsilon );
-        
+
         oInclusiveFilter.addRing( &oRing );
 
         LOG_ACTION(poLayer->SetSpatialFilter( iGeomField, &oInclusiveFilter ));
@@ -2066,7 +2074,7 @@ static int TestFullSpatialFilter( OGRLayer *poLayer, int iGeomField )
 /*     Reset spatial filter                                             */
 /* -------------------------------------------------------------------- */
     LOG_ACTION(poLayer->SetSpatialFilter( NULL ));
-    
+
     if( bRet && bVerbose )
     {
         printf( "INFO: Full spatial filter succeeded.\n");
@@ -2111,11 +2119,11 @@ static int TestSpatialFilter( OGRLayer *poLayer )
     for( int iGeom = 0; iGeom < nGeomFieldCount; iGeom ++ )
     {
         bRet &= TestSpatialFilter(poLayer, iGeom);
-        
+
         if( bFullSpatialFilter )
             bRet &= TestFullSpatialFilter( poLayer, iGeom );
     }
-    
+
     OGRPolygon oPolygon;
     CPLErrorReset();
     CPLPushErrorHandler(CPLQuietErrorHandler);
@@ -2332,7 +2340,7 @@ static int TestAttributeFilter( CPL_UNUSED GDALDataset* poDS, OGRLayer *poLayer
     {
         printf( "INFO: Attribute filter exclusion seems to work.\n" );
     }
-    
+
     if( poFeature2 == NULL || !poFeature2->Equal(poTargetFeature) )
     {
         bRet = FALSE;
@@ -2543,7 +2551,7 @@ static int TestGetExtent ( OGRLayer *poLayer )
         bRet &= TestGetExtent(poLayer, iGeom);
 
     OGREnvelope sExtent;
-    
+
     CPLPushErrorHandler(CPLQuietErrorHandler);
     OGRErr eErr = LOG_ACTION(poLayer->GetExtent(-1, &sExtent, TRUE));
     CPLPopErrorHandler();
@@ -2552,7 +2560,7 @@ static int TestGetExtent ( OGRLayer *poLayer )
         printf("ERROR: poLayer->GetExtent(-1) should fail.\n");
         bRet = FALSE;
     }
-    
+
     CPLPushErrorHandler(CPLQuietErrorHandler);
     eErr = LOG_ACTION(poLayer->GetExtent(nGeomFieldCount, &sExtent, TRUE));
     CPLPopErrorHandler();
@@ -2581,7 +2589,7 @@ static int TestOGRLayerDeleteAndCreateFeature( OGRLayer *poLayer )
     GIntBig nFID;
 
     LOG_ACTION(poLayer->SetSpatialFilter( NULL ));
-    
+
     if( !LOG_ACTION(poLayer->TestCapability( OLCRandomRead )) )
     {
         if( bVerbose )
@@ -2596,7 +2604,7 @@ static int TestOGRLayerDeleteAndCreateFeature( OGRLayer *poLayer )
             printf( "INFO: No feature available on layer '%s',"
                     "skipping delete/create feature test.\n",
                     poLayer->GetName() );
-        
+
         return bRet;
     }
 /* -------------------------------------------------------------------- */
@@ -2627,7 +2635,7 @@ static int TestOGRLayerDeleteAndCreateFeature( OGRLayer *poLayer )
         printf( "ERROR: Attempt to DeleteFeature() failed.\n" );
         goto end;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Now re-read the feature to verify the delete effect worked.     */
 /* -------------------------------------------------------------------- */
@@ -2679,7 +2687,7 @@ static int TestOGRLayerDeleteAndCreateFeature( OGRLayer *poLayer )
         printf( "INFO: Create Feature test passed.\n" );
     }
     OGRFeature::DestroyFeature(poFeatureTest);
-    
+
 end:
 /* -------------------------------------------------------------------- */
 /*      Cleanup.                                                        */
@@ -2996,7 +3004,7 @@ static int TestLayerSQL( GDALDataset* poDS, OGRLayer * poLayer )
 
     CPLString osSQL;
 
-    /* Test consistency between result layer and traditionnal layer */
+    /* Test consistency between result layer and traditional layer */
     LOG_ACTION(poLayer->ResetReading());
     poLayerFeat = LOG_ACTION(poLayer->GetNextFeature());
 
@@ -3160,7 +3168,7 @@ static int TestLayerSQL( GDALDataset* poDS, OGRLayer * poLayer )
         printf( "ERROR: ExecuteSQL() should have returned a non-NULL result.\n");
         bRet = FALSE;
     }
-    
+
     if( bRet && bVerbose )
         printf("INFO: TestLayerSQL passed.\n");
 
@@ -3190,7 +3198,7 @@ static int TestOGRLayer( GDALDataset* poDS, OGRLayer * poLayer, int bIsSQLLayer
 /*      Basic tests.                                                   */
 /* -------------------------------------------------------------------- */
     bRet &= TestBasic( poLayer );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Test feature count accuracy.                                    */
 /* -------------------------------------------------------------------- */
@@ -3215,7 +3223,7 @@ static int TestOGRLayer( GDALDataset* poDS, OGRLayer * poLayer, int bIsSQLLayer
 /*      Test random reading.                                            */
 /* -------------------------------------------------------------------- */
     bRet &= TestOGRLayerRandomRead( poLayer );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Test SetNextByIndex.                                            */
 /* -------------------------------------------------------------------- */
@@ -3228,7 +3236,7 @@ static int TestOGRLayer( GDALDataset* poDS, OGRLayer * poLayer, int bIsSQLLayer
     {
         bRet &= TestOGRLayerDeleteAndCreateFeature( poLayer );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Test random writing.                                            */
 /* -------------------------------------------------------------------- */
@@ -3277,7 +3285,7 @@ static int TestOGRLayer( GDALDataset* poDS, OGRLayer * poLayer, int bIsSQLLayer
 /*                        TestInterleavedReading()                      */
 /************************************************************************/
 
-static int TestInterleavedReading( const char* pszDataSource, char** papszLayers )
+static int TestInterleavedReading( const char* pszDataSourceIn, char** papszLayersIn )
 {
     int bRet = TRUE;
     GDALDataset* poDS = NULL;
@@ -3294,7 +3302,7 @@ static int TestInterleavedReading( const char* pszDataSource, char** papszLayers
     OGRFeature* poFeature22 = NULL;
 
     /* Check that we have 2 layers with at least 2 features */
-    poDS = LOG_ACTION((GDALDataset*) GDALOpenEx( pszDataSource,
+    poDS = LOG_ACTION((GDALDataset*) GDALOpenEx( pszDataSourceIn,
                             GDAL_OF_VECTOR, NULL, papszOpenOptions, NULL ));
     if (poDS == NULL)
     {
@@ -3305,8 +3313,8 @@ static int TestInterleavedReading( const char* pszDataSource, char** papszLayers
         goto bye;
     }
 
-    poLayer1 = LOG_ACTION(papszLayers ? poDS->GetLayerByName(papszLayers[0]) : poDS->GetLayer(0));
-    poLayer2 = LOG_ACTION(papszLayers ? poDS->GetLayerByName(papszLayers[1]) : poDS->GetLayer(1));
+    poLayer1 = LOG_ACTION(papszLayersIn ? poDS->GetLayerByName(papszLayersIn[0]) : poDS->GetLayer(0));
+    poLayer2 = LOG_ACTION(papszLayersIn ? poDS->GetLayerByName(papszLayersIn[1]) : poDS->GetLayer(1));
     if (poLayer1 == NULL || poLayer2 == NULL ||
         LOG_ACTION(poLayer1->GetFeatureCount()) < 2 || LOG_ACTION(poLayer2->GetFeatureCount()) < 2)
     {
@@ -3319,9 +3327,9 @@ static int TestInterleavedReading( const char* pszDataSource, char** papszLayers
 
     /* Test normal reading */
     LOG_ACTION(GDALClose( (GDALDatasetH)poDS ));
-    poDS = LOG_ACTION((GDALDataset*) GDALOpenEx( pszDataSource,
+    poDS = LOG_ACTION((GDALDataset*) GDALOpenEx( pszDataSourceIn,
                                 GDAL_OF_VECTOR, NULL, papszOpenOptions, NULL ));
-    poDS2 = LOG_ACTION((GDALDataset*) GDALOpenEx( pszDataSource,
+    poDS2 = LOG_ACTION((GDALDataset*) GDALOpenEx( pszDataSourceIn,
                                 GDAL_OF_VECTOR, NULL, papszOpenOptions, NULL ));
     if (poDS == NULL || poDS2 == NULL)
     {
@@ -3332,8 +3340,8 @@ static int TestInterleavedReading( const char* pszDataSource, char** papszLayers
         goto bye;
     }
 
-    poLayer1 = LOG_ACTION(papszLayers ? poDS->GetLayerByName(papszLayers[0]) : poDS->GetLayer(0));
-    poLayer2 = LOG_ACTION(papszLayers ? poDS->GetLayerByName(papszLayers[1]) : poDS->GetLayer(1));
+    poLayer1 = LOG_ACTION(papszLayersIn ? poDS->GetLayerByName(papszLayersIn[0]) : poDS->GetLayer(0));
+    poLayer2 = LOG_ACTION(papszLayersIn ? poDS->GetLayerByName(papszLayersIn[1]) : poDS->GetLayer(1));
     if (poLayer1 == NULL || poLayer2 == NULL)
     {
         printf( "ERROR: Skipping TestInterleavedReading(). Test conditions are not met\n" );
@@ -3354,8 +3362,8 @@ static int TestInterleavedReading( const char* pszDataSource, char** papszLayers
     }
 
     /* Test interleaved reading */
-    poLayer1 = LOG_ACTION(papszLayers ? poDS2->GetLayerByName(papszLayers[0]) : poDS2->GetLayer(0));
-    poLayer2 = LOG_ACTION(papszLayers ? poDS2->GetLayerByName(papszLayers[1]) : poDS2->GetLayer(1));
+    poLayer1 = LOG_ACTION(papszLayersIn ? poDS2->GetLayerByName(papszLayersIn[0]) : poDS2->GetLayer(0));
+    poLayer2 = LOG_ACTION(papszLayersIn ? poDS2->GetLayerByName(papszLayersIn[1]) : poDS2->GetLayer(1));
     if (poLayer1 == NULL || poLayer2 == NULL)
     {
         printf( "ERROR: Skipping TestInterleavedReading(). Test conditions are not met\n" );
@@ -3476,13 +3484,20 @@ static int TestVirtualIO( GDALDataset * poDS )
 {
     int bRet = TRUE;
 
-    if( strncmp( poDS->GetDescription(), "/vsimem/", strlen("/vsimem/") ) == 0 )
+    if( STARTS_WITH(poDS->GetDescription(), "/vsimem/") )
         return TRUE;
 
     VSIStatBufL sStat;
     if( !(VSIStatL( poDS->GetDescription(), &sStat) == 0) )
         return TRUE;
 
+    // Don't try with ODBC (will avoid a useless error message in ogr_odbc.py)
+    if( poDS->GetDriver() != NULL &&
+        EQUAL(poDS->GetDriver()->GetDescription(), "ODBC") )
+    {
+        return TRUE;
+    }
+
     char** papszFileList = LOG_ACTION(poDS->GetFileList());
     char** papszIter = papszFileList;
     CPLString osPath;
@@ -3512,7 +3527,7 @@ static int TestVirtualIO( GDALDataset * poDS )
         /* CPLDebug("test_ogrsf", "Copying %s to %s", *papszIter, pszDestFile); */
         CPLCopyFile( pszDestFile, *papszIter );
     }
-    
+
     const char* pszVirtFile;
     if( VSI_ISREG(sStat.st_mode) )
         pszVirtFile = CPLFormFilename(osVirtPath, CPLGetFilename(poDS->GetDescription()), NULL);
diff --git a/apps/testepsg.cpp b/apps/testepsg.cpp
index 14afe82..93f29e4 100644
--- a/apps/testepsg.cpp
+++ b/apps/testepsg.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: testepsg.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: testepsg.cpp 33615 2016-03-02 20:19:22Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Test mainline for translating EPSG definitions into WKT.
@@ -34,14 +34,14 @@
 #include "ogr_p.h"
 #include "cpl_multiproc.h"
 
-void Usage()
+static void Usage()
 
 {
     printf( "testepsg [-xml] [-t src_def trg_def x y z]* [def]*\n" );
     printf( "  -t: transform a coordinate from source GCS/PCS to target GCS/PCS\n" );
     printf( "\n" );
     printf( "def's  on their own are translated to WKT & XML and printed.\n" );
-    printf( "def's may be of any user input format, a WKT def, an\n" ); 
+    printf( "def's may be of any user input format, a WKT def, an\n" );
     printf( "EPSG:n definition or the name of a file containing WKT/XML.\n");
 }
 
@@ -64,34 +64,34 @@ int main( int nArgc, char ** papszArgv )
     {
         if( EQUAL(papszArgv[i],"-xml") )
             bReportXML = TRUE;
-        
+
         else if( EQUAL(papszArgv[i],"-t") && i < nArgc - 4 )
         {
             OGRSpatialReference oSourceSRS, oTargetSRS;
             OGRCoordinateTransformation *poCT;
             double                      x, y, z_orig, z;
             int                         nArgsUsed = 4;
-            
+
             if( oSourceSRS.SetFromUserInput(papszArgv[i+1]) != OGRERR_NONE )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                          "SetFromUserInput(%s) failed.", 
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "SetFromUserInput(%s) failed.",
                           papszArgv[i+1] );
                 continue;
             }
             if( oTargetSRS.SetFromUserInput(papszArgv[i+2]) != OGRERR_NONE )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                          "SetFromUserInput(%s) failed.", 
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "SetFromUserInput(%s) failed.",
                           papszArgv[i+2] );
                 continue;
             }
-            
+
             poCT = OGRCreateCoordinateTransformation( &oSourceSRS,
                                                       &oTargetSRS );
             x = CPLAtof( papszArgv[i+3] );
             y = CPLAtof( papszArgv[i+4] );
-            if( i < nArgc - 5 
+            if( i < nArgc - 5
                 && (CPLAtof(papszArgv[i+5]) > 0.0 || papszArgv[i+5][0] == '0') )
             {
                 z_orig = z = CPLAtof(papszArgv[i+5]);
@@ -99,23 +99,24 @@ int main( int nArgc, char ** papszArgv )
             }
             else
                 z_orig = z = 0;
-            
+
             if( poCT == NULL || !poCT->Transform( 1, &x, &y, &z ) )
                 printf( "Transformation failed.\n" );
             else
-                printf( "(%f,%f,%f) -> (%f,%f,%f)\n", 
+                printf( "(%f,%f,%f) -> (%f,%f,%f)\n",
                         CPLAtof( papszArgv[i+3] ),
                         CPLAtof( papszArgv[i+4] ),
-                        z_orig, 
+                        z_orig,
                         x, y, z );
-            
+
             i += nArgsUsed;
         }
-        else 
+        else
         {
+            /* coverity[tainted_data] */
             if( oSRS.SetFromUserInput(papszArgv[i]) != OGRERR_NONE )
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                          "Error occured translating %s.\n", 
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Error occurred translating %s.\n",
                           papszArgv[i] );
             else
             {
@@ -125,16 +126,16 @@ int main( int nArgc, char ** papszArgv )
                     printf( "Validate Fails.\n" );
                 else
                     printf( "Validate Succeeds.\n" );
-                
+
                 oSRS.exportToPrettyWkt( &pszWKT, FALSE );
-                printf( "WKT[%s] =\n%s\n", 
+                printf( "WKT[%s] =\n%s\n",
                         papszArgv[i], pszWKT );
                 CPLFree( pszWKT );
 
                 printf( "\n" );
 
                 oSRS.exportToPrettyWkt( &pszWKT, TRUE );
-                printf( "Simplified WKT[%s] =\n%s\n", 
+                printf( "Simplified WKT[%s] =\n%s\n",
                         papszArgv[i], pszWKT );
                 CPLFree( pszWKT );
 
@@ -145,7 +146,7 @@ int main( int nArgc, char ** papszArgv )
                 poSRS2 = oSRS.Clone();
                 poSRS2->StripCTParms();
                 poSRS2->exportToWkt( &pszWKT );
-                printf( "Old Style WKT[%s] = %s\n", 
+                printf( "Old Style WKT[%s] = %s\n",
                         papszArgv[i], pszWKT );
                 CPLFree( pszWKT );
                 OGRSpatialReference::DestroySpatialReference( poSRS2 );
@@ -153,13 +154,13 @@ int main( int nArgc, char ** papszArgv )
                 poSRS2 = oSRS.Clone();
                 poSRS2->morphToESRI();
                 poSRS2->exportToPrettyWkt( &pszWKT, FALSE );
-                printf( "ESRI'ified WKT[%s] = \n%s\n", 
+                printf( "ESRI'ified WKT[%s] = \n%s\n",
                         papszArgv[i], pszWKT );
                 CPLFree( pszWKT );
                 OGRSpatialReference::DestroySpatialReference( poSRS2 );
 
                 oSRS.exportToProj4( &pszWKT );
-                printf( "PROJ.4 rendering of [%s] = %s\n", 
+                printf( "PROJ.4 rendering of [%s] = %s\n",
                         papszArgv[i], pszWKT );
                 CPLFree( pszWKT );
 
@@ -169,7 +170,7 @@ int main( int nArgc, char ** papszArgv )
                     char       *pszRawXML;
                     if( oSRS.exportToXML(&pszRawXML) == OGRERR_NONE )
                     {
-                        printf( "XML[%s] =\n%s\n", 
+                        printf( "XML[%s] =\n%s\n",
                                 papszArgv[i], pszRawXML );
                         CPLFree( pszRawXML );
                     }
@@ -188,6 +189,6 @@ int main( int nArgc, char ** papszArgv )
     OSRCleanup();
     CPLFinderClean();
     CPLCleanupTLS();
-    
+
     return 0;
 }
diff --git a/apps/testreprojmulti.cpp b/apps/testreprojmulti.cpp
index 62d5d3d..6b9fecc 100644
--- a/apps/testreprojmulti.cpp
+++ b/apps/testreprojmulti.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: testreprojmulti.cpp 28039 2014-11-30 18:24:59Z rouault $
+ * $Id: testreprojmulti.cpp 33011 2016-01-15 22:20:29Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Test multi-threaded reprojection
@@ -34,7 +34,7 @@
 #include "cpl_multiproc.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: testreprojmulti.cpp 28039 2014-11-30 18:24:59Z rouault $");
+CPL_CVSID("$Id: testreprojmulti.cpp 33011 2016-01-15 22:20:29Z goatbar $");
 
 double* padfRefX;
 double* padfRefY;
@@ -55,7 +55,7 @@ void ReprojFunc(void* unused)
     OGRCoordinateTransformation *poCTInThread;
     if (!bCreateCTInThread)
         poCTInThread = poCT;
-    while(TRUE)
+    while( true )
     {
         if (bCreateCTInThread)
             poCTInThread = OGRCreateCoordinateTransformation(&oSrcSRS,&oDstSRS);
@@ -77,7 +77,7 @@ void ReprojFunc(void* unused)
 int main(int argc, char* argv[])
 {
     int nThreads = 2;
-    
+
     int i;
     for(i=0;i<argc;i++)
     {
diff --git a/bridge/bridge_test.cpp b/bridge/bridge_test.cpp
index 12ef30d..e8df0af 100644
--- a/bridge/bridge_test.cpp
+++ b/bridge/bridge_test.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: bridge_test.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: bridge_test.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  GDAL Bridge
  * Purpose:  Simple mainline for testing bridge.  This is a slightly modified
@@ -34,8 +34,8 @@
 #include <math.h>
 #include "gdalbridge.h"
 
-static int 
-GDALInfoReportCorner( GDALDatasetH hDataset, 
+static int
+GDALInfoReportCorner( GDALDatasetH hDataset,
                       const char * corner_name,
                       double x, double y );
 
@@ -52,7 +52,7 @@ int main( int argc, char ** argv )
 
     if( !GDALBridgeInitialize( "..", stderr ) )
     {
-        fprintf( stderr, "Unable to intiailize GDAL bridge.\n" );
+        fprintf( stderr, "Unable to initialize GDAL bridge.\n" );
         exit( 10 );
     }
 
@@ -65,7 +65,7 @@ int main( int argc, char ** argv )
     GDALAllRegister();
 
     hDataset = GDALOpen( argv[1], GA_ReadOnly );
-    
+
     if( hDataset == NULL )
     {
         fprintf( stderr,
@@ -73,7 +73,7 @@ int main( int argc, char ** argv )
                  CPLGetLastErrorNo(), CPLGetLastErrorMsg() );
         exit( 1 );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Report general info.                                            */
 /* -------------------------------------------------------------------- */
@@ -83,7 +83,7 @@ int main( int argc, char ** argv )
             GDALGetDriverLongName( hDriver ) );
 
     printf( "Size is %d, %d\n",
-            GDALGetRasterXSize( hDataset ), 
+            GDALGetRasterXSize( hDataset ),
             GDALGetRasterYSize( hDataset ) );
 
 /* -------------------------------------------------------------------- */
@@ -132,13 +132,13 @@ int main( int argc, char ** argv )
         for( i = 0; i < GDALGetGCPCount(hDataset); i++ )
         {
             const GDAL_GCP	*psGCP;
-            
+
             psGCP = GDALGetGCPs( hDataset ) + i;
 
             printf( "GCP[%3d]: Id=%s, Info=%s\n"
-                    "          (%g,%g) -> (%g,%g,%g)\n", 
-                    i, psGCP->pszId, psGCP->pszInfo, 
-                    psGCP->dfGCPPixel, psGCP->dfGCPLine, 
+                    "          (%g,%g) -> (%g,%g,%g)\n",
+                    i, psGCP->pszId, psGCP->pszInfo,
+                    psGCP->dfGCPPixel, psGCP->dfGCPLine,
                     psGCP->dfGCPX, psGCP->dfGCPY, psGCP->dfGCPZ );
         }
     }
@@ -173,17 +173,17 @@ int main( int argc, char ** argv )
 /*      Report corners.                                                 */
 /* -------------------------------------------------------------------- */
     printf( "Corner Coordinates:\n" );
-    GDALInfoReportCorner( hDataset, "Upper Left", 
+    GDALInfoReportCorner( hDataset, "Upper Left",
                           0.0, 0.0 );
-    GDALInfoReportCorner( hDataset, "Lower Left", 
+    GDALInfoReportCorner( hDataset, "Lower Left",
                           0.0, GDALGetRasterYSize(hDataset));
-    GDALInfoReportCorner( hDataset, "Upper Right", 
+    GDALInfoReportCorner( hDataset, "Upper Right",
                           GDALGetRasterXSize(hDataset), 0.0 );
-    GDALInfoReportCorner( hDataset, "Lower Right", 
-                          GDALGetRasterXSize(hDataset), 
+    GDALInfoReportCorner( hDataset, "Lower Right",
+                          GDALGetRasterXSize(hDataset),
                           GDALGetRasterYSize(hDataset) );
-    GDALInfoReportCorner( hDataset, "Center", 
-                          GDALGetRasterXSize(hDataset)/2.0, 
+    GDALInfoReportCorner( hDataset, "Center",
+                          GDALGetRasterXSize(hDataset)/2.0,
                           GDALGetRasterYSize(hDataset)/2.0 );
 
 /* ==================================================================== */
@@ -205,11 +205,11 @@ int main( int argc, char ** argv )
         dfMin = GDALGetRasterMinimum( hBand, &bGotMin );
         dfMax = GDALGetRasterMaximum( hBand, &bGotMax );
         printf( "  Min=%.3f/%d, Max=%.3f/%d",  dfMin, bGotMin, dfMax, bGotMax);
-        
+
         if( bComputeMinMax )
         {
             GDALComputeRasterMinMax( hBand, TRUE, adfCMinMax );
-            printf( ", Computed Min/Max=%.3f,%.3f", 
+            printf( ", Computed Min/Max=%.3f,%.3f",
                     adfCMinMax[0], adfCMinMax[1] );
         }
         printf( "\n" );
@@ -225,7 +225,7 @@ int main( int argc, char ** argv )
             int		iOverview;
 
             printf( "  Overviews: " );
-            for( iOverview = 0; 
+            for( iOverview = 0;
                  iOverview < GDALGetOverviewCount(hBand);
                  iOverview++ )
             {
@@ -235,7 +235,7 @@ int main( int argc, char ** argv )
                     printf( ", " );
 
                 hOverview = GDALGetOverview( hBand, iOverview );
-                printf( "%dx%d", 
+                printf( "%dx%d",
                         GDALGetRasterBandXSize( hOverview ),
                         GDALGetRasterBandYSize( hOverview ) );
             }
@@ -258,9 +258,9 @@ int main( int argc, char ** argv )
             int			i;
 
             hTable = GDALGetRasterColorTable( hBand );
-            printf( "  Color Table (%s with %d entries)\n", 
+            printf( "  Color Table (%s with %d entries)\n",
                     GDALGetPaletteInterpretationName(
-                        GDALGetPaletteInterpretation( hTable )), 
+                        GDALGetPaletteInterpretation( hTable )),
                     GDALGetColorEntryCount( hTable ) );
 
             for( i = 0; i < GDALGetColorEntryCount( hTable ); i++ )
@@ -268,8 +268,8 @@ int main( int argc, char ** argv )
                 GDALColorEntry	sEntry;
 
                 GDALGetColorEntryAsRGB( hTable, i, &sEntry );
-                printf( "  %3d: %d,%d,%d,%d\n", 
-                        i, 
+                printf( "  %3d: %d,%d,%d,%d\n",
+                        i,
                         sEntry.c1,
                         sEntry.c2,
                         sEntry.c3,
@@ -279,7 +279,7 @@ int main( int argc, char ** argv )
     }
 
     GDALClose( hDataset );
-    
+
     exit( 0 );
 }
 
@@ -287,8 +287,8 @@ int main( int argc, char ** argv )
 /*                        GDALInfoReportCorner()                        */
 /************************************************************************/
 
-static int 
-GDALInfoReportCorner( GDALDatasetH hDataset, 
+static int
+GDALInfoReportCorner( GDALDatasetH hDataset,
                       const char * corner_name,
                       double x, double y )
 
@@ -297,9 +297,9 @@ GDALInfoReportCorner( GDALDatasetH hDataset,
     const char  *pszProjection;
     double	adfGeoTransform[6];
     OGRCoordinateTransformationH hTransform = NULL;
-        
+
     printf( "%-11s ", corner_name );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Transform the point into georeferenced coordinates.             */
 /* -------------------------------------------------------------------- */
@@ -356,19 +356,18 @@ GDALInfoReportCorner( GDALDatasetH hDataset,
 /* -------------------------------------------------------------------- */
 /*      Transform to latlong and report.                                */
 /* -------------------------------------------------------------------- */
-    if( hTransform != NULL 
+    if( hTransform != NULL
         && OCTTransform(hTransform,1,&dfGeoX,&dfGeoY,NULL) )
     {
-        
+
         printf( "(%s,", GDALDecToDMS( dfGeoX, "Long", 2 ) );
         printf( "%s)", GDALDecToDMS( dfGeoY, "Lat", 2 ) );
     }
 
     if( hTransform != NULL )
         OCTDestroyCoordinateTransformation( hTransform );
-    
+
     printf( "\n" );
 
     return TRUE;
 }
-
diff --git a/bridge/gbgetsymbol.cpp b/bridge/gbgetsymbol.cpp
index 1906fb7..e48e927 100644
--- a/bridge/gbgetsymbol.cpp
+++ b/bridge/gbgetsymbol.cpp
@@ -1,7 +1,7 @@
 /******************************************************************************
- * $Id: gbgetsymbol.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: gbgetsymbol.cpp 32058 2015-12-07 05:09:48Z goatbar $
  *
- * Project:  GDAL Bridge 
+ * Project:  GDAL Bridge
  * Purpose:  Fetch a function pointer from a shared library / DLL.
  * Author:   Frank Warmerdam, warmerda at home.com
  *
@@ -49,14 +49,14 @@
 /*       o Attempt to look for the library in non-standard              */
 /*         locations.                                                   */
 /*       o Attempt to try variations on the symbol name, like           */
-/*         pre-prending or post-pending an underscore.                  */
+/*         pre-pending or post-pending an underscore.                   */
 /************************************************************************/
 
 void *GBGetSymbol( const char * pszLibrary, const char * pszSymbolName )
 
 {
-    void	*pLibrary;
-    void	*pSymbol;
+    void *pLibrary;
+    void *pSymbol;
 
     pLibrary = dlopen(pszLibrary, RTLD_LAZY);
     if( pLibrary == NULL )
@@ -71,7 +71,7 @@ void *GBGetSymbol( const char * pszLibrary, const char * pszSymbolName )
         fprintf( stderr, "GBGetSymbol(): %s\n", dlerror() );
         return NULL;
     }
-    
+
     return( pSymbol );
 }
 
@@ -94,14 +94,14 @@ void *GBGetSymbol( const char * pszLibrary, const char * pszSymbolName )
 /*       o Attempt to look for the library in non-standard              */
 /*         locations.                                                   */
 /*       o Attempt to try variations on the symbol name, like           */
-/*         pre-prending or post-pending an underscore.                  */
+/*         pre-pending or post-pending an underscore.                   */
 /************************************************************************/
 
 void *GBGetSymbol( const char * pszLibrary, const char * pszSymbolName )
 
 {
-    void	*pLibrary;
-    void	*pSymbol;
+    void *pLibrary;
+    void *pSymbol;
 
     pLibrary = LoadLibrary(pszLibrary);
     if( pLibrary == NULL )
@@ -118,7 +118,7 @@ void *GBGetSymbol( const char * pszLibrary, const char * pszSymbolName )
                  pszSymbolName );
         return NULL;
     }
-    
+
     return( pSymbol );
 }
 
diff --git a/bridge/gdalbridge.cpp b/bridge/gdalbridge.cpp
index 4f63fdd..9b0a5e9 100644
--- a/bridge/gdalbridge.cpp
+++ b/bridge/gdalbridge.cpp
@@ -1,7 +1,7 @@
 /******************************************************************************
- * $Id: gdalbridge.cpp 28831 2015-04-01 16:46:05Z rouault $
+ * $Id: gdalbridge.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
- * Project:  GDAL Bridge 
+ * Project:  GDAL Bridge
  * Purpose:  Implementation of GDALBridgeInitialize()
  * Author:   Frank Warmerdam, warmerda at home.com
  *
@@ -68,13 +68,13 @@ static const char *papszSOFilenames[] = {
 /*      list of missing entry points.                                   */
 /************************************************************************/
 
-static void *GBGetSymbolCheck( const char *pszLibrary, 
+static void *GBGetSymbolCheck( const char *pszLibrary,
                                const char *pszSymbolName,
                                char **papszErrorList )
 
 {
     void	*pReturn;
-    
+
     pReturn = GBGetSymbol( pszLibrary, pszSymbolName );
 
     if( pReturn == NULL && papszErrorList != NULL )
@@ -104,7 +104,7 @@ int GDALBridgeInitialize( const char * pszTargetDir, FILE *fpReportFailure )
     void	*pfnTest = NULL;
     int		iSOFile;
     char        *apszFailed[MAX_SYMBOL];
-    
+
 /* -------------------------------------------------------------------- */
 /*      Do we want to force reporting on?                               */
 /* -------------------------------------------------------------------- */
@@ -151,59 +151,59 @@ int GDALBridgeInitialize( const char * pszTargetDir, FILE *fpReportFailure )
 
         if( fpReportFailure == NULL )
             return FALSE;
-        
 
-        fprintf( fpReportFailure, 
+
+        fprintf( fpReportFailure,
                  "GBBridgeInitialize() failed to find an suitable GDAL .DLL/.so file.\n" );
-        fprintf( fpReportFailure, 
+        fprintf( fpReportFailure,
                  "The following filenames were searched for:\n" );
-        
+
         for( iSOFile = 0; papszSOFilenames[iSOFile] != NULL; iSOFile++ )
             fprintf( fpReportFailure, "  o %s\n", papszSOFilenames[iSOFile] );
 
         fprintf( fpReportFailure, "\n" );
         fprintf( fpReportFailure, "The following locations were searched:\n" );
-        
+
         if( pszTargetDir != NULL )
             fprintf( fpReportFailure, "  o %s\n", pszTargetDir );
-        
+
         if( getenv( "GDAL_HOME" ) != NULL )
             fprintf( fpReportFailure, "  o %s\n", getenv( "GDAL_HOME" ) );
-        
+
         fprintf( fpReportFailure, "  o System default locations.\n" );
         fprintf( fpReportFailure, "\n" );
 
         fprintf( fpReportFailure, "\n" );
-#ifdef __unix__        
+#ifdef __unix__
         if( getenv("LD_LIBRARY_PATH") != NULL )
         {
-            fprintf( fpReportFailure, 
+            fprintf( fpReportFailure,
                      "System default locations may be influenced by:\n" );
-            fprintf( fpReportFailure, 
+            fprintf( fpReportFailure,
                      "LD_LIBRARY_PATH = %s\n", getenv("LD_LIBRARY_PATH") );
         }
 #else
         if( getenv("PATH") != NULL )
         {
-            fprintf( fpReportFailure, 
+            fprintf( fpReportFailure,
                      "System default locations may be influenced by:\n" );
-            fprintf( fpReportFailure, 
+            fprintf( fpReportFailure,
                      "PATH = %s\n", getenv("PATH") );
         }
-#endif        
-        
+#endif
+
         return FALSE;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Start loading functions.                                        */
 /* -------------------------------------------------------------------- */
     apszFailed[0] = NULL;
-    
+
     GDALGetDataTypeSize = (int (*)(GDALDataType))
         GBGetSymbolCheck( szPath, "GDALGetDataTypeSize", apszFailed );
 
-    GDALAllRegister = (void (*)(void)) 
+    GDALAllRegister = (void (*)(void))
         GBGetSymbolCheck( szPath, "GDALAllRegister", apszFailed );
 
     GDALCreate = (GDALDatasetH (*)(GDALDriverH, const char *, int, int, int,
@@ -282,7 +282,7 @@ int GDALBridgeInitialize( const char * pszTargetDir, FILE *fpReportFailure )
 
     GDALReadBlock = (CPLErr (*)(GDALRasterBandH, int, int, void *))
         GBGetSymbolCheck( szPath, "GDALReadBlock", apszFailed );
-    
+
     GDALWriteBlock = (CPLErr (*)(GDALRasterBandH, int, int, void *))
         GBGetSymbolCheck( szPath, "GDALWriteBlock", apszFailed );
 
@@ -303,13 +303,13 @@ int GDALBridgeInitialize( const char * pszTargetDir, FILE *fpReportFailure )
 
     GDALGetRasterMinimum = (double (*)(GDALRasterBandH, int *))
         GBGetSymbolCheck( szPath, "GDALGetRasterMinimum", apszFailed );
-        
+
     GDALGetRasterMaximum = (double (*)(GDALRasterBandH, int *))
         GBGetSymbolCheck( szPath, "GDALGetRasterMaximum", apszFailed );
-        
+
     GDALComputeRasterMinMax = (void (*)(GDALRasterBandH, int, double *))
         GBGetSymbolCheck( szPath, "GDALComputeRasterMinMax", apszFailed );
-        
+
     GDALGetRasterColorInterpretation = (GDALColorInterp (*)(GDALRasterBandH))
         GBGetSymbolCheck( szPath, "GDALGetRasterColorInterpretation", apszFailed );
 
@@ -337,7 +337,7 @@ int GDALBridgeInitialize( const char * pszTargetDir, FILE *fpReportFailure )
     GDALGetColorEntryAsRGB = (int (*)(GDALColorTableH,int,
                                       GDALColorEntry*))
         GBGetSymbolCheck( szPath, "GDALGetColorEntryAsRGB", apszFailed );
-    
+
     GDALSetColorEntry = (void (*)(GDALColorTableH, int, const GDALColorEntry*))
         GBGetSymbolCheck( szPath, "GDALSetColorEntry", apszFailed );
 
@@ -346,18 +346,18 @@ int GDALBridgeInitialize( const char * pszTargetDir, FILE *fpReportFailure )
 /* -------------------------------------------------------------------- */
     GDALGetMetadata = (char **(*)(GDALMajorObjectH, const char *))
         GBGetSymbolCheck( szPath, "GDALGetMetadata", apszFailed );
-    
+
     GDALSetMetadata = (CPLErr(*)(GDALMajorObjectH, char **, const char *))
         GBGetSymbolCheck( szPath, "GDALSetMetadata", apszFailed );
-    
+
     GDALGetMetadataItem = (const char *(*)(GDALMajorObjectH, const char *,
                                            const char *))
         GBGetSymbolCheck( szPath, "GDALGetMetadataItem", apszFailed );
 
-    GDALSetMetadataItem = (CPLErr (*)(GDALMajorObjectH, const char *, 
+    GDALSetMetadataItem = (CPLErr (*)(GDALMajorObjectH, const char *,
                                       const char *, const char *))
         GBGetSymbolCheck( szPath, "GDALSetMetadataItem", apszFailed );
-    
+
 /* -------------------------------------------------------------------- */
 /*      CPL                                                             */
 /* -------------------------------------------------------------------- */
@@ -408,38 +408,38 @@ int GDALBridgeInitialize( const char * pszTargetDir, FILE *fpReportFailure )
 
     OSRExportToWkt = (OGRErr (*)(OGRSpatialReferenceH, char **))
         GBGetSymbolCheck( szPath, "OSRExportToWkt", apszFailed );
-    
+
     OSRExportToPrettyWkt = (OGRErr (*)(OGRSpatialReferenceH, char **, int))
         GBGetSymbolCheck( szPath, "OSRExportToPrettyWkt", apszFailed );
-    
+
     OSRExportToProj4 = (OGRErr (*)(OGRSpatialReferenceH, char **))
         GBGetSymbolCheck( szPath, "OSRExportToProj4", apszFailed );
-    
-    OSRSetAttrValue = (OGRErr (*)(OGRSpatialReferenceH, const char *, 
+
+    OSRSetAttrValue = (OGRErr (*)(OGRSpatialReferenceH, const char *,
                                   const char *))
         GBGetSymbolCheck( szPath, "OSRSetAttrValue", apszFailed );
-    
+
     OSRGetAttrValue = (const char *(*)(OGRSpatialReferenceH, const char *,int))
         GBGetSymbolCheck( szPath, "OSRGetAttrValue", apszFailed );
-    
+
     OSRSetLinearUnits = (OGRErr (*)(OGRSpatialReferenceH, const char *,double))
         GBGetSymbolCheck( szPath, "OSRSetLinearUnits", apszFailed );
-    
+
     OSRGetLinearUnits = (double (*)(OGRSpatialReferenceH, char **))
         GBGetSymbolCheck( szPath, "OSRGetLinearUnits", apszFailed );
-    
+
     OSRIsGeographic = (int (*)(OGRSpatialReferenceH))
         GBGetSymbolCheck( szPath, "OSRIsGeographic", apszFailed );
-    
+
     OSRIsProjected = (int (*)(OGRSpatialReferenceH))
         GBGetSymbolCheck( szPath, "OSRIsProjected", apszFailed );
-    
+
     OSRIsSameGeogCS = (int (*)(OGRSpatialReferenceH,OGRSpatialReferenceH))
         GBGetSymbolCheck( szPath, "OSRIsSameGeogCS", apszFailed );
-    
+
     OSRIsSame = (int (*)(OGRSpatialReferenceH,OGRSpatialReferenceH))
         GBGetSymbolCheck( szPath, "OSRIsSame", apszFailed );
-    
+
     OSRSetProjCS = (OGRErr (*)(OGRSpatialReferenceH,const char*))
         GBGetSymbolCheck( szPath, "OSRSetProjCS", apszFailed );
 
@@ -456,7 +456,7 @@ int GDALBridgeInitialize( const char * pszTargetDir, FILE *fpReportFailure )
                                 const char * pszUnits /* = NULL */,
                                 double dfConvertToRadians /* = 0.0 */ ))
         GBGetSymbolCheck( szPath, "OSRSetGeogCS", apszFailed );
-        
+
     OSRGetSemiMajor = (double (*)(OGRSpatialReferenceH, OGRErr *))
         GBGetSymbolCheck( szPath, "OSRGetSemiMajor", apszFailed );
 
@@ -466,14 +466,14 @@ int GDALBridgeInitialize( const char * pszTargetDir, FILE *fpReportFailure )
     OSRGetInvFlattening = (double (*)(OGRSpatialReferenceH, OGRErr *))
         GBGetSymbolCheck( szPath, "OSRGetInvFlattening", apszFailed );
 
-    OSRSetAuthority = (OGRErr (*)(OGRSpatialReferenceH, const char *, 
+    OSRSetAuthority = (OGRErr (*)(OGRSpatialReferenceH, const char *,
                                   const char *, int))
         GBGetSymbolCheck( szPath, "OSRSetAuthority", apszFailed );
 
     OSRSetProjParm = (OGRErr (*)(OGRSpatialReferenceH, const char *, double))
         GBGetSymbolCheck( szPath, "OSRSetProjParm", apszFailed );
 
-    OSRGetProjParm = (double (*)(OGRSpatialReferenceH, const char *, 
+    OSRGetProjParm = (double (*)(OGRSpatialReferenceH, const char *,
                                  double, OGRErr *))
         GBGetSymbolCheck( szPath, "OSRGetProjParm", apszFailed );
 
@@ -483,16 +483,16 @@ int GDALBridgeInitialize( const char * pszTargetDir, FILE *fpReportFailure )
     OSRGetUTMZone = (int (*)(OGRSpatialReferenceH, int *))
         GBGetSymbolCheck( szPath, "OSRGetUTMZone", apszFailed );
 
-    OCTNewCoordinateTransformation = (OGRCoordinateTransformationH 
+    OCTNewCoordinateTransformation = (OGRCoordinateTransformationH
                      (*)(OGRSpatialReferenceH, OGRSpatialReferenceH))
         GBGetSymbolCheck( szPath, "OCTNewCoordinateTransformation",apszFailed);
 
-    OCTDestroyCoordinateTransformation = 
+    OCTDestroyCoordinateTransformation =
         (void (*)(OGRCoordinateTransformationH))
         GBGetSymbolCheck( szPath, "OCTDestroyCoordinateTransformation",
                           apszFailed );
 
-    OCTTransform = (int (*)(OGRCoordinateTransformationH, int, 
+    OCTTransform = (int (*)(OGRCoordinateTransformationH, int,
                             double *, double *, double *))
         GBGetSymbolCheck( szPath, "OCTTransform", apszFailed );
 
@@ -502,13 +502,13 @@ int GDALBridgeInitialize( const char * pszTargetDir, FILE *fpReportFailure )
     if( apszFailed[0] != NULL && fpReportFailure != NULL )
     {
         int	iError;
-        
-        fprintf( fpReportFailure, 
+
+        fprintf( fpReportFailure,
                  "While a GDAL .DLL/.so was found at `%s'\n"
                  "it appears to be missing the following entry points.\n"
                  "Consider upgrading to a more recent GDAL library.\n",
                  szPath );
-        
+
         for( iError = 0; apszFailed[iError] != NULL; iError++ )
         {
             fprintf( fpReportFailure, "  o %s\n", apszFailed[iError] );
@@ -518,5 +518,3 @@ int GDALBridgeInitialize( const char * pszTargetDir, FILE *fpReportFailure )
 
     return apszFailed[0] == NULL;
 }
-
-
diff --git a/bridge/gdalbridge.h b/bridge/gdalbridge.h
index bd6ee93..57f9f97 100644
--- a/bridge/gdalbridge.h
+++ b/bridge/gdalbridge.h
@@ -1,7 +1,7 @@
 /******************************************************************************
- * $Id: gdalbridge.h 17542 2009-08-19 17:02:26Z mloskot $
+ * $Id: gdalbridge.h 33713 2016-03-12 17:41:57Z goatbar $
  *
- * Project:  GDAL Bridge 
+ * Project:  GDAL Bridge
  * Purpose:  Declarations for GDAL Bridge support.
  * Author:   Frank Warmerdam, warmerda at home.com
  *
@@ -40,7 +40,7 @@ extern "C" {
 #endif
 
 #include <stdio.h>
-    
+
 /* ==================================================================== */
 /*      Standard types and defines normally supplied by cpl_port.h.     */
 /* ==================================================================== */
@@ -125,7 +125,7 @@ typedef enum
 } GDALColorInterp;
 
 /*! Types of color interpretations for a GDALColorTable. */
-typedef enum 
+typedef enum
 {
   /*! Grayscale (in GDALColorEntry.c1) */                      GPI_Gray=0,
   /*! Red, Green, Blue and Alpha in (in c1, c2, c3 and c4) */  GPI_RGB=1,
@@ -145,7 +145,7 @@ typedef enum
     CE_Warning = 2,
     CE_Failure = 3,
     CE_Fatal = 4
-  
+
 } CPLErr;
 
 #define CPLE_AppDefined			1
@@ -185,7 +185,7 @@ GDAL_ENTRY CPLErr (*pfnCPLGetLastErrorType)() GDAL_NULL;
 #define CPLGetLastErrorType pfnCPLGetLastErrorType
 
 GDAL_ENTRY const char *(*pfnCPLGetLastErrorMsg)() GDAL_NULL;
-#define CPLGetLastErrorMsg pfnCPLGetLastErrorMsg 
+#define CPLGetLastErrorMsg pfnCPLGetLastErrorMsg
 
 GDAL_ENTRY void (*pfnCPLPushErrorHandler)( CPLErrorHandler ) GDAL_NULL;
 #define CPLPushErrorHandler pfnCPLPushErrorHandler
@@ -213,7 +213,7 @@ typedef void *OGRCoordinateTransformationH;
 typedef struct
 {
     /** Unique identifier, often numeric */
-    char	*pszId; 
+    char	*pszId;
 
     /** Informational message or "" */
     char	*pszInfo;
@@ -265,7 +265,7 @@ GDAL_ENTRY GDALDriverH (*pfnGDALIdentifyDriver)( const char *, char ** ) GDAL_NU
 /*      GDALMajorObject                                                 */
 /* ==================================================================== */
 
-GDAL_ENTRY char **(*pfnGDALGetMetadata)( GDALMajorObjectH, 
+GDAL_ENTRY char **(*pfnGDALGetMetadata)( GDALMajorObjectH,
                                          const char * ) GDAL_NULL;
 #define GDALGetMetadata pfnGDALGetMetadata
 
@@ -273,9 +273,9 @@ GDAL_ENTRY CPLErr (*pfnGDALSetMetadata)( GDALMajorObjectH, char **,
                                          const char * ) GDAL_NULL;
 #define GDALSetMetadata pfnGDALSetMetadata
 
-GDAL_ENTRY const char *(*pfnGDALGetMetadataItem)( GDALMajorObjectH, 
+GDAL_ENTRY const char *(*pfnGDALGetMetadataItem)( GDALMajorObjectH,
                                       const char *, const char * ) GDAL_NULL;
-#define GDALGetMetadataItem pfnGDALGetMetadataItem 
+#define GDALGetMetadataItem pfnGDALGetMetadataItem
 
 GDAL_ENTRY CPLErr (*pfnGDALSetMetadataItem)( GDALMajorObjectH,
                                              const char *, const char *,
@@ -367,11 +367,11 @@ GDAL_ENTRY int (*pGDALGetOverviewCount)( GDALRasterBandH ) GDAL_NULL;
 GDAL_ENTRY GDALRasterBandH (*pGDALGetOverview)( GDALRasterBandH, int ) GDAL_NULL;
 #define GDALGetOverview pGDALGetOverview
 
-GDAL_ENTRY double (*pGDALGetRasterNoDataValue)( GDALRasterBandH, int * ) 
+GDAL_ENTRY double (*pGDALGetRasterNoDataValue)( GDALRasterBandH, int * )
     GDAL_NULL;
 #define GDALGetRasterNoDataValue pGDALGetRasterNoDataValue
 
-GDAL_ENTRY CPLErr (*pGDALSetRasterNoDataValue)( GDALRasterBandH, double ) 
+GDAL_ENTRY CPLErr (*pGDALSetRasterNoDataValue)( GDALRasterBandH, double )
     GDAL_NULL;
 #define GDALSetRasterNoDataValue pGDALSetRasterNoDataValue
 
@@ -385,7 +385,7 @@ GDAL_ENTRY double (*pGDALGetRasterMinimum)( GDALRasterBandH, int * ) GDAL_NULL;
 GDAL_ENTRY double (*pGDALGetRasterMaximum)( GDALRasterBandH, int * ) GDAL_NULL;
 #define GDALGetRasterMaximum pGDALGetRasterMaximum
 
-GDAL_ENTRY void (*pGDALComputeRasterMinMax)( GDALRasterBandH, int, 
+GDAL_ENTRY void (*pGDALComputeRasterMinMax)( GDALRasterBandH, int,
                                              double * ) GDAL_NULL;
 #define GDALComputeRasterMinMax pGDALComputeRasterMinMax
 
@@ -412,16 +412,16 @@ GDAL_ENTRY int (*pfnGDALGetRasterBandYSize)( GDALRasterBandH ) GDAL_NULL;
 typedef struct
 {
     /*! gray, red, cyan or hue */
-    short      c1;      
+    short      c1;
 
-    /*! green, magenta, or lightness */    
-    short      c2;      
+    /*! green, magenta, or lightness */
+    short      c2;
 
     /*! blue, yellow, or saturation */
-    short      c3;      
+    short      c3;
 
     /*! alpha or blackband */
-    short      c4;      
+    short      c4;
 } GDALColorEntry;
 
 GDAL_ENTRY GDALPaletteInterp (*pGDALGetPaletteInterpretation)( GDALColorTableH ) GDAL_NULL;
@@ -436,11 +436,11 @@ GDAL_ENTRY int (*pGDALGetColorEntryCount)( GDALColorTableH ) GDAL_NULL;
 GDAL_ENTRY const GDALColorEntry *(*pGDALGetColorEntry)( GDALColorTableH, int ) GDAL_NULL;
 #define GDALGetColorEntry pGDALGetColorEntry
 
-GDAL_ENTRY int (*pGDALGetColorEntryAsRGB)( GDALColorTableH, int, 
+GDAL_ENTRY int (*pGDALGetColorEntryAsRGB)( GDALColorTableH, int,
                                            GDALColorEntry *) GDAL_NULL;
 #define GDALGetColorEntryAsRGB pGDALGetColorEntryAsRGB
 
-GDAL_ENTRY void (*pGDALSetColorEntry)( GDALColorTableH, int, 
+GDAL_ENTRY void (*pGDALSetColorEntry)( GDALColorTableH, int,
                                        const GDALColorEntry * ) GDAL_NULL;
 #define GDALSetColorEntry pGDALSetColorEntry
 
@@ -455,15 +455,15 @@ GDAL_ENTRY const char *(*pGDALDecToDMS)( double, const char *, int ) GDAL_NULL;
 /*      ogr_srs_api.h services.                                         */
 /* -------------------------------------------------------------------- */
 
-GDAL_ENTRY OGRSpatialReferenceH 
+GDAL_ENTRY OGRSpatialReferenceH
 	(*pOSRNewSpatialReference)( const char * ) GDAL_NULL;
 #define OSRNewSpatialReference pOSRNewSpatialReference
 
-GDAL_ENTRY OGRSpatialReferenceH 
+GDAL_ENTRY OGRSpatialReferenceH
 	(*pOSRCloneGeogCS)( OGRSpatialReferenceH ) GDAL_NULL;
 #define OSRCloneGeogCS pOSRCloneGeogCS
 
-GDAL_ENTRY void 
+GDAL_ENTRY void
 	(*pOSRDestroySpatialReference)( OGRSpatialReferenceH ) GDAL_NULL;
 #define OSRDestroySpatialReference pOSRDestroySpatialReference
 
@@ -476,27 +476,27 @@ GDAL_ENTRY int (*pOSRDereference)( OGRSpatialReferenceH ) GDAL_NULL;
 GDAL_ENTRY OGRErr (*pOSRImportFromEPSG)( OGRSpatialReferenceH, int ) GDAL_NULL;
 #define OSRImportFromEPSG pOSRImportFromEPSG
 
-GDAL_ENTRY OGRErr 
+GDAL_ENTRY OGRErr
 	(*pOSRImportFromWkt)( OGRSpatialReferenceH, char ** ) GDAL_NULL;
 #define OSRImportFromWkt pOSRImportFromWkt
 
-GDAL_ENTRY OGRErr 
+GDAL_ENTRY OGRErr
 	(*pOSRImportFromProj4)( OGRSpatialReferenceH, const char *) GDAL_NULL;
 #define OSRImportFromProj4 pOSRImportFromProj4
 
-GDAL_ENTRY OGRErr 
+GDAL_ENTRY OGRErr
 	(*pOSRExportToWkt)( OGRSpatialReferenceH, char ** ) GDAL_NULL;
 #define OSRExportToWkt pOSRExportToWkt
 
-GDAL_ENTRY OGRErr 
+GDAL_ENTRY OGRErr
        (*pOSRExportToPrettyWkt)( OGRSpatialReferenceH, char **, int) GDAL_NULL;
 #define OSRExportToPrettyWkt pOSRExportToPrettyWkt
 
-GDAL_ENTRY OGRErr 
+GDAL_ENTRY OGRErr
 	(*pOSRExportToProj4)( OGRSpatialReferenceH, char **) GDAL_NULL;
 #define OSRExportToProj4 pOSRExportToProj4
 
-GDAL_ENTRY OGRErr 
+GDAL_ENTRY OGRErr
 	(*pOSRSetAttrValue)( OGRSpatialReferenceH hSRS,
                              const char * pszNodePath,
                              const char * pszNewNodeValue ) GDAL_NULL;
@@ -506,11 +506,11 @@ GDAL_ENTRY const char * (*pOSRGetAttrValue)( OGRSpatialReferenceH hSRS,
                            const char * pszName, int iChild ) GDAL_NULL;
 #define OSRGetAttrValue pOSRGetAttrValue
 
-GDAL_ENTRY OGRErr (*pOSRSetLinearUnits)( OGRSpatialReferenceH, const char *, 
+GDAL_ENTRY OGRErr (*pOSRSetLinearUnits)( OGRSpatialReferenceH, const char *,
                                          double ) GDAL_NULL;
 #define OSRSetLinearUnits pOSRSetLinearUnits
 
-GDAL_ENTRY double (*pOSRGetLinearUnits)( OGRSpatialReferenceH, 
+GDAL_ENTRY double (*pOSRGetLinearUnits)( OGRSpatialReferenceH,
                                          char ** ) GDAL_NULL;
 #define OSRGetLinearUnits pOSRGetLinearUnits
 
@@ -520,15 +520,15 @@ GDAL_ENTRY int (*pOSRIsGeographic)( OGRSpatialReferenceH ) GDAL_NULL;
 GDAL_ENTRY int (*pOSRIsProjected)( OGRSpatialReferenceH ) GDAL_NULL;
 #define OSRIsProjected pOSRIsProjected
 
-GDAL_ENTRY int (*pOSRIsSameGeogCS)( OGRSpatialReferenceH, 
+GDAL_ENTRY int (*pOSRIsSameGeogCS)( OGRSpatialReferenceH,
                                     OGRSpatialReferenceH ) GDAL_NULL;
 #define OSRIsSameGeogCS pOSRIsSameGeogCS
 
-GDAL_ENTRY int (*pOSRIsSame)( OGRSpatialReferenceH, 
+GDAL_ENTRY int (*pOSRIsSame)( OGRSpatialReferenceH,
                               OGRSpatialReferenceH ) GDAL_NULL;
 #define OSRIsSame pOSRIsSame
 
-GDAL_ENTRY OGRErr (*pOSRSetProjCS)( OGRSpatialReferenceH hSRS, 
+GDAL_ENTRY OGRErr (*pOSRSetProjCS)( OGRSpatialReferenceH hSRS,
                                     const char * pszName ) GDAL_NULL;
 #define OSRSetProjCS pOSRSetProjCS
 
@@ -547,15 +547,15 @@ GDAL_ENTRY OGRErr (*pOSRSetGeogCS)( OGRSpatialReferenceH hSRS,
                       double dfConvertToRadians /* = 0.0 */ ) GDAL_NULL;
 #define OSRSetGeogCS pOSRSetGeogCS
 
-GDAL_ENTRY double (*pOSRGetSemiMajor)( OGRSpatialReferenceH, 
+GDAL_ENTRY double (*pOSRGetSemiMajor)( OGRSpatialReferenceH,
                                        OGRErr * /* = NULL */ ) GDAL_NULL;
 #define OSRGetSemiMajor pOSRGetSemiMajor
 
-GDAL_ENTRY double (*pOSRGetSemiMinor)( OGRSpatialReferenceH, 
+GDAL_ENTRY double (*pOSRGetSemiMinor)( OGRSpatialReferenceH,
                                        OGRErr * /* = NULL */ ) GDAL_NULL;
 #define OSRGetSemiMinor pOSRGetSemiMinor
 
-GDAL_ENTRY double (*pOSRGetInvFlattening)( OGRSpatialReferenceH, 
+GDAL_ENTRY double (*pOSRGetInvFlattening)( OGRSpatialReferenceH,
                                            OGRErr * /*=NULL*/) GDAL_NULL;
 #define OSRGetInvFlattening pOSRGetInvFlattening
 
@@ -565,21 +565,21 @@ GDAL_ENTRY OGRErr (*pOSRSetAuthority)( OGRSpatialReferenceH hSRS,
                                        int nCode ) GDAL_NULL;
 #define OSRSetAuthority pOSRSetAuthority
 
-GDAL_ENTRY OGRErr (*pOSRSetProjParm)( OGRSpatialReferenceH, 
+GDAL_ENTRY OGRErr (*pOSRSetProjParm)( OGRSpatialReferenceH,
                                       const char *, double ) GDAL_NULL;
 #define OSRSetProjParm pOSRSetProjParm
 
 GDAL_ENTRY double (*pOSRGetProjParm)( OGRSpatialReferenceH hSRS,
-                                      const char * pszParmName, 
+                                      const char * pszParmName,
                                       double dfDefault /* = 0.0 */,
                                       OGRErr * /* = NULL */ ) GDAL_NULL;
 #define OSRGetProjParm pOSRGetProjParm
 
-GDAL_ENTRY OGRErr (*pOSRSetUTM)( OGRSpatialReferenceH hSRS, 
+GDAL_ENTRY OGRErr (*pOSRSetUTM)( OGRSpatialReferenceH hSRS,
                                  int nZone, int bNorth ) GDAL_NULL;
 #define OSRSetUTM pOSRSetUTM
 
-GDAL_ENTRY int (*pOSRGetUTMZone)( OGRSpatialReferenceH hSRS, 
+GDAL_ENTRY int (*pOSRGetUTMZone)( OGRSpatialReferenceH hSRS,
                                   int *pbNorth ) GDAL_NULL;
 #define OSRGetUTMZone pOSRGetUTMZone
 
@@ -593,9 +593,9 @@ GDAL_ENTRY void (*pOCTDestroyCoordinateTransformation)
 #define OCTDestroyCoordinateTransformation pOCTDestroyCoordinateTransformation
 
 GDAL_ENTRY int (*pOCTTransform)( OGRCoordinateTransformationH hCT,
-                                 int nCount, double *x, double *y, 
+                                 int nCount, double *x, double *y,
                                  double *z ) GDAL_NULL;
-#define OCTTransform pOCTTransform 
+#define OCTTransform pOCTTransform
 
 /* ==================================================================== */
 /*      Some "standard" strings.                                        */
@@ -650,8 +650,6 @@ GDAL_ENTRY int (*pOCTTransform)( OGRCoordinateTransformationH hCT,
                                 "Tunisia_Mining_Grid"
 #define SRS_PT_VANDERGRINTEN    "VanDerGrinten"
 
-                                
-
 #define SRS_PP_CENTRAL_MERIDIAN         "central_meridian"
 #define SRS_PP_SCALE_FACTOR             "scale_factor"
 #define SRS_PP_STANDARD_PARALLEL_1      "standard_parallel_1"
@@ -700,7 +698,7 @@ GDAL_ENTRY int (*pOCTTransform)( OGRCoordinateTransformationH hCT,
 #define SRS_DN_NAD83            "North American Datum 1983"
 #define SRS_DN_WGS84            "World Geodetic System 1984"
 
-#define SRS_WGS84_SEMIMAJOR     6378137.0                                
+#define SRS_WGS84_SEMIMAJOR     6378137.0
 #define SRS_WGS84_INVFLATTENING 298.257223563
 
 #endif
diff --git a/config.guess b/config.guess
index 278f9e9..d76a50e 100755
--- a/config.guess
+++ b/config.guess
@@ -1,14 +1,12 @@
 #! /bin/sh
 # Attempt to guess a canonical system name.
-#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-#   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
-#   Inc.
+#   Copyright 1992-2015 Free Software Foundation, Inc.
 
-timestamp='2007-07-22'
+timestamp='2015-11-24'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
+# the Free Software Foundation; either version 3 of the License, or
 # (at your option) any later version.
 #
 # This program is distributed in the hope that it will be useful, but
@@ -17,26 +15,22 @@ timestamp='2007-07-22'
 # General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
-# 02110-1301, USA.
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 #
 # As a special exception to the GNU General Public License, if you
 # distribute this file as part of a program that contains a
 # configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-
-# Originally written by Per Bothner <per at bothner.com>.
-# Please send patches to <config-patches at gnu.org>.  Submit a context
-# diff and a properly formatted ChangeLog entry.
+# the same distribution terms that you use for the rest of that
+# program.  This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
 #
-# This script attempts to guess a canonical system name similar to
-# config.sub.  If it succeeds, it prints the system name on stdout, and
-# exits with 0.  Otherwise, it exits with 1.
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
 #
-# The plan is that this can be called by configure scripts if you
-# don't specify an explicit build system type.
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+#
+# Please send patches to <config-patches at gnu.org>.
+
 
 me=`echo "$0" | sed -e 's,.*/,,'`
 
@@ -56,8 +50,7 @@ version="\
 GNU config.guess ($timestamp)
 
 Originally written by Per Bothner.
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
-Free Software Foundation, Inc.
+Copyright 1992-2015 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -139,12 +132,33 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
 UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
 UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
 
+case "${UNAME_SYSTEM}" in
+Linux|GNU|GNU/*)
+	# If the system lacks a compiler, then just pick glibc.
+	# We could probably try harder.
+	LIBC=gnu
+
+	eval $set_cc_for_build
+	cat <<-EOF > $dummy.c
+	#include <features.h>
+	#if defined(__UCLIBC__)
+	LIBC=uclibc
+	#elif defined(__dietlibc__)
+	LIBC=dietlibc
+	#else
+	LIBC=gnu
+	#endif
+	EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+	;;
+esac
+
 # Note: order is significant - the case branches are not exclusive.
 
 case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     *:NetBSD:*:*)
 	# NetBSD (nbsd) targets should (where applicable) match one or
-	# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+	# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
 	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
 	# switched to ELF, *-*-netbsd* would select the old
 	# object file format.  This provides both forward
@@ -154,23 +168,30 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 	# Note: NetBSD doesn't particularly care about the vendor
 	# portion of the name.  We always set it to "unknown".
 	sysctl="sysctl -n hw.machine_arch"
-	UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
-	    /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+	UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
+	    /sbin/$sysctl 2>/dev/null || \
+	    /usr/sbin/$sysctl 2>/dev/null || \
+	    echo unknown)`
 	case "${UNAME_MACHINE_ARCH}" in
 	    armeb) machine=armeb-unknown ;;
 	    arm*) machine=arm-unknown ;;
 	    sh3el) machine=shl-unknown ;;
 	    sh3eb) machine=sh-unknown ;;
 	    sh5el) machine=sh5le-unknown ;;
+	    earmv*)
+		arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
+		endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'`
+		machine=${arch}${endian}-unknown
+		;;
 	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
 	esac
 	# The Operating System including object format, if it has switched
 	# to ELF recently, or will in the future.
 	case "${UNAME_MACHINE_ARCH}" in
-	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+	    arm*|earm*|i386|m68k|ns32k|sh3*|sparc|vax)
 		eval $set_cc_for_build
 		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
-			| grep __ELF__ >/dev/null
+			| grep -q __ELF__
 		then
 		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
 		    # Return netbsd for either.  FIX?
@@ -180,7 +201,14 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 		fi
 		;;
 	    *)
-	        os=netbsd
+		os=netbsd
+		;;
+	esac
+	# Determine ABI tags.
+	case "${UNAME_MACHINE_ARCH}" in
+	    earm*)
+		expr='s/^earmv[0-9]/-eabi/;s/eb$//'
+		abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"`
 		;;
 	esac
 	# The OS release
@@ -193,13 +221,17 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 		release='-gnu'
 		;;
 	    *)
-		release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+		release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2`
 		;;
 	esac
 	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
 	# contains redundant information, the shorter form:
 	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
-	echo "${machine}-${os}${release}"
+	echo "${machine}-${os}${release}${abi}"
+	exit ;;
+    *:Bitrig:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
+	echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
 	exit ;;
     *:OpenBSD:*:*)
 	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
@@ -217,13 +249,16 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     *:MirBSD:*:*)
 	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
 	exit ;;
+    *:Sortix:*:*)
+	echo ${UNAME_MACHINE}-unknown-sortix
+	exit ;;
     alpha:OSF1:*:*)
 	case $UNAME_RELEASE in
 	*4.0)
 		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
 		;;
 	*5.*)
-	        UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
 		;;
 	esac
 	# According to Compaq, /usr/sbin/psrinfo has been available on
@@ -269,7 +304,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 	# A Xn.n version is an unreleased experimental baselevel.
 	# 1.2 uses "1.2" for uname -r.
 	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
-	exit ;;
+	# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+	exitcode=$?
+	trap '' 0
+	exit $exitcode ;;
     Alpha\ *:Windows_NT*:*)
 	# How do we know it's Interix rather than the generic POSIX subsystem?
 	# Should we change UNAME_MACHINE based on the output of uname instead
@@ -295,12 +333,12 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 	echo s390-ibm-zvmoe
 	exit ;;
     *:OS400:*:*)
-        echo powerpc-ibm-os400
+	echo powerpc-ibm-os400
 	exit ;;
     arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
 	echo arm-acorn-riscix${UNAME_RELEASE}
 	exit ;;
-    arm:riscos:*:*|arm:RISCOS:*:*)
+    arm*:riscos:*:*|arm*:RISCOS:*:*)
 	echo arm-unknown-riscos
 	exit ;;
     SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
@@ -324,14 +362,33 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 	case `/usr/bin/uname -p` in
 	    sparc) echo sparc-icl-nx7; exit ;;
 	esac ;;
+    s390x:SunOS:*:*)
+	echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
     sun4H:SunOS:5.*:*)
 	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
 	exit ;;
     sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
 	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
 	exit ;;
+    i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+	echo i386-pc-auroraux${UNAME_RELEASE}
+	exit ;;
     i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
-	echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	eval $set_cc_for_build
+	SUN_ARCH="i386"
+	# If there is a compiler, see if it is configured for 64-bit objects.
+	# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+	# This test works for both compilers.
+	if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+	    if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+		(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+		grep IS_64BIT_ARCH >/dev/null
+	    then
+		SUN_ARCH="x86_64"
+	    fi
+	fi
+	echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
 	exit ;;
     sun4*:SunOS:6*:*)
 	# According to config.sub, this is the proper way to canonicalize
@@ -375,23 +432,23 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     # MiNT.  But MiNT is downward compatible to TOS, so this should
     # be no problem.
     atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
-        echo m68k-atari-mint${UNAME_RELEASE}
+	echo m68k-atari-mint${UNAME_RELEASE}
 	exit ;;
     atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
 	echo m68k-atari-mint${UNAME_RELEASE}
-        exit ;;
+	exit ;;
     *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
-        echo m68k-atari-mint${UNAME_RELEASE}
+	echo m68k-atari-mint${UNAME_RELEASE}
 	exit ;;
     milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
-        echo m68k-milan-mint${UNAME_RELEASE}
-        exit ;;
+	echo m68k-milan-mint${UNAME_RELEASE}
+	exit ;;
     hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
-        echo m68k-hades-mint${UNAME_RELEASE}
-        exit ;;
+	echo m68k-hades-mint${UNAME_RELEASE}
+	exit ;;
     *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
-        echo m68k-unknown-mint${UNAME_RELEASE}
-        exit ;;
+	echo m68k-unknown-mint${UNAME_RELEASE}
+	exit ;;
     m68k:machten:*:*)
 	echo m68k-apple-machten${UNAME_RELEASE}
 	exit ;;
@@ -461,8 +518,8 @@ EOF
 	echo m88k-motorola-sysv3
 	exit ;;
     AViiON:dgux:*:*)
-        # DG/UX returns AViiON for all architectures
-        UNAME_PROCESSOR=`/usr/bin/uname -p`
+	# DG/UX returns AViiON for all architectures
+	UNAME_PROCESSOR=`/usr/bin/uname -p`
 	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
 	then
 	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
@@ -475,7 +532,7 @@ EOF
 	else
 	    echo i586-dg-dgux${UNAME_RELEASE}
 	fi
- 	exit ;;
+	exit ;;
     M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
 	echo m88k-dolphin-sysv3
 	exit ;;
@@ -532,15 +589,16 @@ EOF
 		echo rs6000-ibm-aix3.2
 	fi
 	exit ;;
-    *:AIX:*:[45])
+    *:AIX:*:[4567])
 	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
 	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
 		IBM_ARCH=rs6000
 	else
 		IBM_ARCH=powerpc
 	fi
-	if [ -x /usr/bin/oslevel ] ; then
-		IBM_REV=`/usr/bin/oslevel`
+	if [ -x /usr/bin/lslpp ] ; then
+		IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
+			   awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
 	else
 		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
 	fi
@@ -575,52 +633,52 @@ EOF
 	    9000/[678][0-9][0-9])
 		if [ -x /usr/bin/getconf ]; then
 		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
-                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
-                    case "${sc_cpu_version}" in
-                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
-                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
-                      532)                      # CPU_PA_RISC2_0
-                        case "${sc_kernel_bits}" in
-                          32) HP_ARCH="hppa2.0n" ;;
-                          64) HP_ARCH="hppa2.0w" ;;
+		    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+		    case "${sc_cpu_version}" in
+		      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+		      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+		      532)                      # CPU_PA_RISC2_0
+			case "${sc_kernel_bits}" in
+			  32) HP_ARCH="hppa2.0n" ;;
+			  64) HP_ARCH="hppa2.0w" ;;
 			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
-                        esac ;;
-                    esac
+			esac ;;
+		    esac
 		fi
 		if [ "${HP_ARCH}" = "" ]; then
 		    eval $set_cc_for_build
-		    sed 's/^              //' << EOF >$dummy.c
+		    sed 's/^		//' << EOF >$dummy.c
 
-              #define _HPUX_SOURCE
-              #include <stdlib.h>
-              #include <unistd.h>
+		#define _HPUX_SOURCE
+		#include <stdlib.h>
+		#include <unistd.h>
 
-              int main ()
-              {
-              #if defined(_SC_KERNEL_BITS)
-                  long bits = sysconf(_SC_KERNEL_BITS);
-              #endif
-                  long cpu  = sysconf (_SC_CPU_VERSION);
+		int main ()
+		{
+		#if defined(_SC_KERNEL_BITS)
+		    long bits = sysconf(_SC_KERNEL_BITS);
+		#endif
+		    long cpu  = sysconf (_SC_CPU_VERSION);
 
-                  switch (cpu)
-              	{
-              	case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
-              	case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
-              	case CPU_PA_RISC2_0:
-              #if defined(_SC_KERNEL_BITS)
-              	    switch (bits)
-              		{
-              		case 64: puts ("hppa2.0w"); break;
-              		case 32: puts ("hppa2.0n"); break;
-              		default: puts ("hppa2.0"); break;
-              		} break;
-              #else  /* !defined(_SC_KERNEL_BITS) */
-              	    puts ("hppa2.0"); break;
-              #endif
-              	default: puts ("hppa1.0"); break;
-              	}
-                  exit (0);
-              }
+		    switch (cpu)
+			{
+			case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+			case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+			case CPU_PA_RISC2_0:
+		#if defined(_SC_KERNEL_BITS)
+			    switch (bits)
+				{
+				case 64: puts ("hppa2.0w"); break;
+				case 32: puts ("hppa2.0n"); break;
+				default: puts ("hppa2.0"); break;
+				} break;
+		#else  /* !defined(_SC_KERNEL_BITS) */
+			    puts ("hppa2.0"); break;
+		#endif
+			default: puts ("hppa1.0"); break;
+			}
+		    exit (0);
+		}
 EOF
 		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
 		    test -z "$HP_ARCH" && HP_ARCH=hppa
@@ -640,7 +698,7 @@ EOF
 	    # => hppa64-hp-hpux11.23
 
 	    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
-		grep __LP64__ >/dev/null
+		grep -q __LP64__
 	    then
 		HP_ARCH="hppa2.0w"
 	    else
@@ -711,22 +769,22 @@ EOF
 	exit ;;
     C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
 	echo c1-convex-bsd
-        exit ;;
+	exit ;;
     C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
 	if getsysinfo -f scalar_acc
 	then echo c32-convex-bsd
 	else echo c2-convex-bsd
 	fi
-        exit ;;
+	exit ;;
     C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
 	echo c34-convex-bsd
-        exit ;;
+	exit ;;
     C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
 	echo c38-convex-bsd
-        exit ;;
+	exit ;;
     C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
 	echo c4-convex-bsd
-        exit ;;
+	exit ;;
     CRAY*Y-MP:*:*:*)
 	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
 	exit ;;
@@ -750,14 +808,14 @@ EOF
 	exit ;;
     F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
 	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
-        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
-        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
-        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
-        exit ;;
+	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+	FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+	echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
     5000:UNIX_System_V:4.*:*)
-        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
-        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
-        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+	FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+	echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
 	exit ;;
     i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
 	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
@@ -769,40 +827,51 @@ EOF
 	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
 	exit ;;
     *:FreeBSD:*:*)
-	case ${UNAME_MACHINE} in
-	    pc98)
-		echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	UNAME_PROCESSOR=`/usr/bin/uname -p`
+	case ${UNAME_PROCESSOR} in
 	    amd64)
 		echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
 	    *)
-		echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+		echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
 	esac
 	exit ;;
     i*:CYGWIN*:*)
 	echo ${UNAME_MACHINE}-pc-cygwin
 	exit ;;
+    *:MINGW64*:*)
+	echo ${UNAME_MACHINE}-pc-mingw64
+	exit ;;
     *:MINGW*:*)
 	echo ${UNAME_MACHINE}-pc-mingw32
 	exit ;;
+    *:MSYS*:*)
+	echo ${UNAME_MACHINE}-pc-msys
+	exit ;;
     i*:windows32*:*)
-    	# uname -m includes "-pc" on this system.
-    	echo ${UNAME_MACHINE}-mingw32
+	# uname -m includes "-pc" on this system.
+	echo ${UNAME_MACHINE}-mingw32
 	exit ;;
     i*:PW*:*)
 	echo ${UNAME_MACHINE}-pc-pw32
 	exit ;;
-    *:Interix*:[3456]*)
-    	case ${UNAME_MACHINE} in
+    *:Interix*:*)
+	case ${UNAME_MACHINE} in
 	    x86)
 		echo i586-pc-interix${UNAME_RELEASE}
 		exit ;;
-	    EM64T | authenticamd)
+	    authenticamd | genuineintel | EM64T)
 		echo x86_64-unknown-interix${UNAME_RELEASE}
 		exit ;;
+	    IA64)
+		echo ia64-unknown-interix${UNAME_RELEASE}
+		exit ;;
 	esac ;;
     [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
 	echo i${UNAME_MACHINE}-pc-mks
 	exit ;;
+    8664:Windows_NT:*)
+	echo x86_64-pc-mks
+	exit ;;
     i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
 	# How do we know it's Interix rather than the generic POSIX subsystem?
 	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
@@ -823,203 +892,160 @@ EOF
 	exit ;;
     *:GNU:*:*)
 	# the GNU system
-	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
 	exit ;;
     *:GNU/*:*:*)
 	# other systems with GNU libc and userland
-	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
 	exit ;;
     i*86:Minix:*:*)
 	echo ${UNAME_MACHINE}-pc-minix
 	exit ;;
+    aarch64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    aarch64_be:Linux:*:*)
+	UNAME_MACHINE=aarch64_be
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    alpha:Linux:*:*)
+	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+	  EV5)   UNAME_MACHINE=alphaev5 ;;
+	  EV56)  UNAME_MACHINE=alphaev56 ;;
+	  PCA56) UNAME_MACHINE=alphapca56 ;;
+	  PCA57) UNAME_MACHINE=alphapca56 ;;
+	  EV6)   UNAME_MACHINE=alphaev6 ;;
+	  EV67)  UNAME_MACHINE=alphaev67 ;;
+	  EV68*) UNAME_MACHINE=alphaev68 ;;
+	esac
+	objdump --private-headers /bin/sh | grep -q ld.so.1
+	if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    arc:Linux:*:* | arceb:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
     arm*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	eval $set_cc_for_build
+	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+	    | grep -q __ARM_EABI__
+	then
+	    echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	else
+	    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+		| grep -q __ARM_PCS_VFP
+	    then
+		echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
+	    else
+		echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
+	    fi
+	fi
 	exit ;;
     avr32*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     cris:Linux:*:*)
-	echo cris-axis-linux-gnu
+	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
 	exit ;;
     crisv32:Linux:*:*)
-	echo crisv32-axis-linux-gnu
+	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+	exit ;;
+    e2k:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     frv:Linux:*:*)
-    	echo frv-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    hexagon:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    i*86:Linux:*:*)
+	echo ${UNAME_MACHINE}-pc-linux-${LIBC}
 	exit ;;
     ia64:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     m32r*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     m68*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
-    mips:Linux:*:*)
-	eval $set_cc_for_build
-	sed 's/^	//' << EOF >$dummy.c
-	#undef CPU
-	#undef mips
-	#undef mipsel
-	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
-	CPU=mipsel
-	#else
-	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
-	CPU=mips
-	#else
-	CPU=
-	#endif
-	#endif
-EOF
-	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
-	    /^CPU/{
-		s: ::g
-		p
-	    }'`"
-	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
-	;;
-    mips64:Linux:*:*)
+    mips:Linux:*:* | mips64:Linux:*:*)
 	eval $set_cc_for_build
 	sed 's/^	//' << EOF >$dummy.c
 	#undef CPU
-	#undef mips64
-	#undef mips64el
+	#undef ${UNAME_MACHINE}
+	#undef ${UNAME_MACHINE}el
 	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
-	CPU=mips64el
+	CPU=${UNAME_MACHINE}el
 	#else
 	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
-	CPU=mips64
+	CPU=${UNAME_MACHINE}
 	#else
 	CPU=
 	#endif
 	#endif
 EOF
-	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
-	    /^CPU/{
-		s: ::g
-		p
-	    }'`"
-	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
+	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
 	;;
-    or32:Linux:*:*)
-	echo or32-unknown-linux-gnu
+    openrisc*:Linux:*:*)
+	echo or1k-unknown-linux-${LIBC}
 	exit ;;
-    ppc:Linux:*:*)
-	echo powerpc-unknown-linux-gnu
+    or32:Linux:*:* | or1k*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
-    ppc64:Linux:*:*)
-	echo powerpc64-unknown-linux-gnu
+    padre:Linux:*:*)
+	echo sparc-unknown-linux-${LIBC}
 	exit ;;
-    alpha:Linux:*:*)
-	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
-	  EV5)   UNAME_MACHINE=alphaev5 ;;
-	  EV56)  UNAME_MACHINE=alphaev56 ;;
-	  PCA56) UNAME_MACHINE=alphapca56 ;;
-	  PCA57) UNAME_MACHINE=alphapca56 ;;
-	  EV6)   UNAME_MACHINE=alphaev6 ;;
-	  EV67)  UNAME_MACHINE=alphaev67 ;;
-	  EV68*) UNAME_MACHINE=alphaev68 ;;
-        esac
-	objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
-	if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
-	echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+	echo hppa64-unknown-linux-${LIBC}
 	exit ;;
     parisc:Linux:*:* | hppa:Linux:*:*)
 	# Look for CPU level
 	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
-	  PA7*) echo hppa1.1-unknown-linux-gnu ;;
-	  PA8*) echo hppa2.0-unknown-linux-gnu ;;
-	  *)    echo hppa-unknown-linux-gnu ;;
+	  PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
+	  PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
+	  *)    echo hppa-unknown-linux-${LIBC} ;;
 	esac
 	exit ;;
-    parisc64:Linux:*:* | hppa64:Linux:*:*)
-	echo hppa64-unknown-linux-gnu
+    ppc64:Linux:*:*)
+	echo powerpc64-unknown-linux-${LIBC}
+	exit ;;
+    ppc:Linux:*:*)
+	echo powerpc-unknown-linux-${LIBC}
+	exit ;;
+    ppc64le:Linux:*:*)
+	echo powerpc64le-unknown-linux-${LIBC}
+	exit ;;
+    ppcle:Linux:*:*)
+	echo powerpcle-unknown-linux-${LIBC}
 	exit ;;
     s390:Linux:*:* | s390x:Linux:*:*)
-	echo ${UNAME_MACHINE}-ibm-linux
+	echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
 	exit ;;
     sh64*:Linux:*:*)
-    	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     sh*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     sparc:Linux:*:* | sparc64:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    tile*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     vax:Linux:*:*)
-	echo ${UNAME_MACHINE}-dec-linux-gnu
+	echo ${UNAME_MACHINE}-dec-linux-${LIBC}
 	exit ;;
     x86_64:Linux:*:*)
-	echo x86_64-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-pc-linux-${LIBC}
 	exit ;;
-    xtensa:Linux:*:*)
-    	echo xtensa-unknown-linux-gnu
+    xtensa*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
-    i*86:Linux:*:*)
-	# The BFD linker knows what the default object file format is, so
-	# first see if it will tell us. cd to the root directory to prevent
-	# problems with other programs or directories called `ld' in the path.
-	# Set LC_ALL=C to ensure ld outputs messages in English.
-	ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
-			 | sed -ne '/supported targets:/!d
-				    s/[ 	][ 	]*/ /g
-				    s/.*supported targets: *//
-				    s/ .*//
-				    p'`
-        case "$ld_supported_targets" in
-	  elf32-i386)
-		TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
-		;;
-	  a.out-i386-linux)
-		echo "${UNAME_MACHINE}-pc-linux-gnuaout"
-		exit ;;
-	  coff-i386)
-		echo "${UNAME_MACHINE}-pc-linux-gnucoff"
-		exit ;;
-	  "")
-		# Either a pre-BFD a.out linker (linux-gnuoldld) or
-		# one that does not give us useful --help.
-		echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
-		exit ;;
-	esac
-	# Determine whether the default compiler is a.out or elf
-	eval $set_cc_for_build
-	sed 's/^	//' << EOF >$dummy.c
-	#include <features.h>
-	#ifdef __ELF__
-	# ifdef __GLIBC__
-	#  if __GLIBC__ >= 2
-	LIBC=gnu
-	#  else
-	LIBC=gnulibc1
-	#  endif
-	# else
-	LIBC=gnulibc1
-	# endif
-	#else
-	#if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
-	LIBC=gnu
-	#else
-	LIBC=gnuaout
-	#endif
-	#endif
-	#ifdef __dietlibc__
-	LIBC=dietlibc
-	#endif
-EOF
-	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
-	    /^LIBC/{
-		s: ::g
-		p
-	    }'`"
-	test x"${LIBC}" != x && {
-		echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
-		exit
-	}
-	test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
-	;;
     i*86:DYNIX/ptx:4*:*)
 	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
 	# earlier versions are messed up and put the nodename in both
@@ -1027,11 +1053,11 @@ EOF
 	echo i386-sequent-sysv4
 	exit ;;
     i*86:UNIX_SV:4.2MP:2.*)
-        # Unixware is an offshoot of SVR4, but it has its own version
-        # number series starting with 2...
-        # I am not positive that other SVR4 systems won't match this,
+	# Unixware is an offshoot of SVR4, but it has its own version
+	# number series starting with 2...
+	# I am not positive that other SVR4 systems won't match this,
 	# I just have to hope.  -- rms.
-        # Use sysv4.2uw... so that sysv4* matches it.
+	# Use sysv4.2uw... so that sysv4* matches it.
 	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
 	exit ;;
     i*86:OS/2:*:*)
@@ -1048,7 +1074,7 @@ EOF
     i*86:syllable:*:*)
 	echo ${UNAME_MACHINE}-pc-syllable
 	exit ;;
-    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
 	echo i386-unknown-lynxos${UNAME_RELEASE}
 	exit ;;
     i*86:*DOS:*:*)
@@ -1063,7 +1089,7 @@ EOF
 	fi
 	exit ;;
     i*86:*:5:[678]*)
-    	# UnixWare 7.x, OpenUNIX and OpenServer 6.
+	# UnixWare 7.x, OpenUNIX and OpenServer 6.
 	case `/bin/uname -X | grep "^Machine"` in
 	    *486*)	     UNAME_MACHINE=i486 ;;
 	    *Pentium)	     UNAME_MACHINE=i586 ;;
@@ -1091,10 +1117,13 @@ EOF
 	exit ;;
     pc:*:*:*)
 	# Left here for compatibility:
-        # uname -m prints for DJGPP always 'pc', but it prints nothing about
-        # the processor, so we play safe by assuming i386.
-	echo i386-pc-msdosdjgpp
-        exit ;;
+	# uname -m prints for DJGPP always 'pc', but it prints nothing about
+	# the processor, so we play safe by assuming i586.
+	# Note: whatever this is, it MUST be the same as what config.sub
+	# prints for the "djgpp" host, or else GDB configure will decide that
+	# this is a cross-build.
+	echo i586-pc-msdosdjgpp
+	exit ;;
     Intel:Mach:3*:*)
 	echo i386-pc-mach3
 	exit ;;
@@ -1129,8 +1158,18 @@ EOF
 	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
 	  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
     3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
-        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-          && { echo i486-ncr-sysv4; exit; } ;;
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4; exit; } ;;
+    NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+	OS_REL='.3'
+	test -r /etc/.relid \
+	    && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	    && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	    && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+	    && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
     m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
 	echo m68k-unknown-lynxos${UNAME_RELEASE}
 	exit ;;
@@ -1143,7 +1182,7 @@ EOF
     rs6000:LynxOS:2.*:*)
 	echo rs6000-unknown-lynxos${UNAME_RELEASE}
 	exit ;;
-    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
 	echo powerpc-unknown-lynxos${UNAME_RELEASE}
 	exit ;;
     SM[BE]S:UNIX_SV:*:*)
@@ -1163,10 +1202,10 @@ EOF
 		echo ns32k-sni-sysv
 	fi
 	exit ;;
-    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
-                      # says <Richard.M.Bartel at ccMail.Census.GOV>
-        echo i586-unisys-sysv4
-        exit ;;
+    PENTIUM:*:4.0*:*)	# Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+			# says <Richard.M.Bartel at ccMail.Census.GOV>
+	echo i586-unisys-sysv4
+	exit ;;
     *:UNIX_System_V:4*:FTX*)
 	# From Gerald Hewes <hewes at openmarket.com>.
 	# How about differentiating between stratus architectures? -djm
@@ -1192,11 +1231,11 @@ EOF
 	exit ;;
     R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
 	if [ -d /usr/nec ]; then
-	        echo mips-nec-sysv${UNAME_RELEASE}
+		echo mips-nec-sysv${UNAME_RELEASE}
 	else
-	        echo mips-unknown-sysv${UNAME_RELEASE}
+		echo mips-unknown-sysv${UNAME_RELEASE}
 	fi
-        exit ;;
+	exit ;;
     BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
 	echo powerpc-be-beos
 	exit ;;
@@ -1206,6 +1245,12 @@ EOF
     BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
 	echo i586-pc-beos
 	exit ;;
+    BePC:Haiku:*:*)	# Haiku running on Intel PC compatible.
+	echo i586-pc-haiku
+	exit ;;
+    x86_64:Haiku:*:*)
+	echo x86_64-unknown-haiku
+	exit ;;
     SX-4:SUPER-UX:*:*)
 	echo sx4-nec-superux${UNAME_RELEASE}
 	exit ;;
@@ -1232,9 +1277,31 @@ EOF
 	exit ;;
     *:Darwin:*:*)
 	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
-	case $UNAME_PROCESSOR in
-	    unknown) UNAME_PROCESSOR=powerpc ;;
-	esac
+	eval $set_cc_for_build
+	if test "$UNAME_PROCESSOR" = unknown ; then
+	    UNAME_PROCESSOR=powerpc
+	fi
+	if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
+	    if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+		if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+		    (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+		    grep IS_64BIT_ARCH >/dev/null
+		then
+		    case $UNAME_PROCESSOR in
+			i386) UNAME_PROCESSOR=x86_64 ;;
+			powerpc) UNAME_PROCESSOR=powerpc64 ;;
+		    esac
+		fi
+	    fi
+	elif test "$UNAME_PROCESSOR" = i386 ; then
+	    # Avoid executing cc on OS X 10.9, as it ships with a stub
+	    # that puts up a graphical alert prompting to install
+	    # developer tools.  Any system running Mac OS X 10.7 or
+	    # later (Darwin 11 and later) is required to have a 64-bit
+	    # processor. This is not true of the ARM version of Darwin
+	    # that Apple uses in portable devices.
+	    UNAME_PROCESSOR=x86_64
+	fi
 	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
 	exit ;;
     *:procnto*:*:* | *:QNX:[0123456789]*:*)
@@ -1248,7 +1315,10 @@ EOF
     *:QNX:*:4*)
 	echo i386-pc-qnx
 	exit ;;
-    NSE-?:NONSTOP_KERNEL:*:*)
+    NEO-?:NONSTOP_KERNEL:*:*)
+	echo neo-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    NSE-*:NONSTOP_KERNEL:*:*)
 	echo nse-tandem-nsk${UNAME_RELEASE}
 	exit ;;
     NSR-?:NONSTOP_KERNEL:*:*)
@@ -1293,13 +1363,13 @@ EOF
 	echo pdp10-unknown-its
 	exit ;;
     SEI:*:*:SEIUX)
-        echo mips-sei-seiux${UNAME_RELEASE}
+	echo mips-sei-seiux${UNAME_RELEASE}
 	exit ;;
     *:DragonFly:*:*)
 	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
 	exit ;;
     *:*VMS:*:*)
-    	UNAME_MACHINE=`(uname -p) 2>/dev/null`
+	UNAME_MACHINE=`(uname -p) 2>/dev/null`
 	case "${UNAME_MACHINE}" in
 	    A*) echo alpha-dec-vms ; exit ;;
 	    I*) echo ia64-dec-vms ; exit ;;
@@ -1314,158 +1384,13 @@ EOF
     i*86:rdos:*:*)
 	echo ${UNAME_MACHINE}-pc-rdos
 	exit ;;
-esac
-
-#echo '(No uname command or uname output not recognized.)' 1>&2
-#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
-
-eval $set_cc_for_build
-cat >$dummy.c <<EOF
-#ifdef _SEQUENT_
-# include <sys/types.h>
-# include <sys/utsname.h>
-#endif
-main ()
-{
-#if defined (sony)
-#if defined (MIPSEB)
-  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
-     I don't know....  */
-  printf ("mips-sony-bsd\n"); exit (0);
-#else
-#include <sys/param.h>
-  printf ("m68k-sony-newsos%s\n",
-#ifdef NEWSOS4
-          "4"
-#else
-	  ""
-#endif
-         ); exit (0);
-#endif
-#endif
-
-#if defined (__arm) && defined (__acorn) && defined (__unix)
-  printf ("arm-acorn-riscix\n"); exit (0);
-#endif
-
-#if defined (hp300) && !defined (hpux)
-  printf ("m68k-hp-bsd\n"); exit (0);
-#endif
-
-#if defined (NeXT)
-#if !defined (__ARCHITECTURE__)
-#define __ARCHITECTURE__ "m68k"
-#endif
-  int version;
-  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
-  if (version < 4)
-    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
-  else
-    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
-  exit (0);
-#endif
-
-#if defined (MULTIMAX) || defined (n16)
-#if defined (UMAXV)
-  printf ("ns32k-encore-sysv\n"); exit (0);
-#else
-#if defined (CMU)
-  printf ("ns32k-encore-mach\n"); exit (0);
-#else
-  printf ("ns32k-encore-bsd\n"); exit (0);
-#endif
-#endif
-#endif
-
-#if defined (__386BSD__)
-  printf ("i386-pc-bsd\n"); exit (0);
-#endif
-
-#if defined (sequent)
-#if defined (i386)
-  printf ("i386-sequent-dynix\n"); exit (0);
-#endif
-#if defined (ns32000)
-  printf ("ns32k-sequent-dynix\n"); exit (0);
-#endif
-#endif
-
-#if defined (_SEQUENT_)
-    struct utsname un;
-
-    uname(&un);
-
-    if (strncmp(un.version, "V2", 2) == 0) {
-	printf ("i386-sequent-ptx2\n"); exit (0);
-    }
-    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
-	printf ("i386-sequent-ptx1\n"); exit (0);
-    }
-    printf ("i386-sequent-ptx\n"); exit (0);
-
-#endif
-
-#if defined (vax)
-# if !defined (ultrix)
-#  include <sys/param.h>
-#  if defined (BSD)
-#   if BSD == 43
-      printf ("vax-dec-bsd4.3\n"); exit (0);
-#   else
-#    if BSD == 199006
-      printf ("vax-dec-bsd4.3reno\n"); exit (0);
-#    else
-      printf ("vax-dec-bsd\n"); exit (0);
-#    endif
-#   endif
-#  else
-    printf ("vax-dec-bsd\n"); exit (0);
-#  endif
-# else
-    printf ("vax-dec-ultrix\n"); exit (0);
-# endif
-#endif
-
-#if defined (alliant) && defined (i860)
-  printf ("i860-alliant-bsd\n"); exit (0);
-#endif
-
-  exit (1);
-}
-EOF
-
-$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
-	{ echo "$SYSTEM_NAME"; exit; }
-
-# Apollos put the system type in the environment.
-
-test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
-
-# Convex versions that predate uname can use getsysinfo(1)
-
-if [ -x /usr/convex/getsysinfo ]
-then
-    case `getsysinfo -f cpu_type` in
-    c1*)
-	echo c1-convex-bsd
+    i*86:AROS:*:*)
+	echo ${UNAME_MACHINE}-pc-aros
 	exit ;;
-    c2*)
-	if getsysinfo -f scalar_acc
-	then echo c32-convex-bsd
-	else echo c2-convex-bsd
-	fi
-	exit ;;
-    c34*)
-	echo c34-convex-bsd
+    x86_64:VMkernel:*:*)
+	echo ${UNAME_MACHINE}-unknown-esx
 	exit ;;
-    c38*)
-	echo c38-convex-bsd
-	exit ;;
-    c4*)
-	echo c4-convex-bsd
-	exit ;;
-    esac
-fi
+esac
 
 cat >&2 <<EOF
 $0: unable to guess system type
@@ -1474,9 +1399,9 @@ This script, last modified $timestamp, has failed to recognize
 the operating system you are using. It is advised that you
 download the most up to date version of the config scripts from
 
-  http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
 and
-  http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
 
 If the version you run ($0) is already up to date, please
 send the following data and any information you think might be
diff --git a/config.sub b/config.sub
index 1761d8b..1acc966 100755
--- a/config.sub
+++ b/config.sub
@@ -1,44 +1,40 @@
 #! /bin/sh
 # Configuration validation subroutine script.
-#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-#   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
-#   Inc.
+#   Copyright 1992-2015 Free Software Foundation, Inc.
 
-timestamp='2007-06-28'
+timestamp='2015-08-20'
 
-# This file is (in principle) common to ALL GNU software.
-# The presence of a machine in this file suggests that SOME GNU software
-# can handle that machine.  It does not imply ALL GNU software can.
-#
-# This file is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
 # (at your option) any later version.
 #
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
-# 02110-1301, USA.
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 #
 # As a special exception to the GNU General Public License, if you
 # distribute this file as part of a program that contains a
 # configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
+# the same distribution terms that you use for the rest of that
+# program.  This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
 
 
-# Please send patches to <config-patches at gnu.org>.  Submit a context
-# diff and a properly formatted ChangeLog entry.
+# Please send patches to <config-patches at gnu.org>.
 #
 # Configuration subroutine to validate and canonicalize a configuration type.
 # Supply the specified configuration type as an argument.
 # If it is invalid, we print an error message on stderr and exit with code 1.
 # Otherwise, we print the canonical config type on stdout and succeed.
 
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
 # This file is supposed to be the same for all GNU packages
 # and recognize all the CPU types, system types and aliases
 # that are meaningful with *any* GNU software.
@@ -72,8 +68,7 @@ Report bugs and patches to <config-patches at gnu.org>."
 version="\
 GNU config.sub ($timestamp)
 
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
-Free Software Foundation, Inc.
+Copyright 1992-2015 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -120,12 +115,18 @@ esac
 # Here we must recognize all the valid KERNEL-OS combinations.
 maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
 case $maybe_os in
-  nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
-  uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+  nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
+  linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+  knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
+  kopensolaris*-gnu* | \
   storm-chaos* | os2-emx* | rtmk-nova*)
     os=-$maybe_os
     basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
     ;;
+  android-linux)
+    os=-linux-android
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
+    ;;
   *)
     basic_machine=`echo $1 | sed 's/-[^-]*$//'`
     if [ $basic_machine != $1 ]
@@ -148,10 +149,13 @@ case $os in
 	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
 	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
 	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-	-apple | -axis | -knuth | -cray)
+	-apple | -axis | -knuth | -cray | -microblaze*)
 		os=
 		basic_machine=$1
 		;;
+	-bluegene*)
+		os=-cnk
+		;;
 	-sim | -cisco | -oki | -wec | -winbond)
 		os=
 		basic_machine=$1
@@ -166,10 +170,10 @@ case $os in
 		os=-chorusos
 		basic_machine=$1
 		;;
- 	-chorusrdb)
- 		os=-chorusrdb
+	-chorusrdb)
+		os=-chorusrdb
 		basic_machine=$1
- 		;;
+		;;
 	-hiux*)
 		os=-hiuxwe2
 		;;
@@ -214,6 +218,12 @@ case $os in
 	-isc*)
 		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
 		;;
+	-lynx*178)
+		os=-lynxos178
+		;;
+	-lynx*5)
+		os=-lynxos5
+		;;
 	-lynx*)
 		os=-lynxos
 		;;
@@ -238,59 +248,91 @@ case $basic_machine in
 	# Some are omitted here because they have special meanings below.
 	1750a | 580 \
 	| a29k \
+	| aarch64 | aarch64_be \
 	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
 	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
 	| am33_2.0 \
-	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+	| arc | arceb \
+	| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
+	| avr | avr32 \
+	| ba \
+	| be32 | be64 \
 	| bfin \
-	| c4x | clipper \
+	| c4x | c8051 | clipper \
 	| d10v | d30v | dlx | dsp16xx \
-	| fido | fr30 | frv \
+	| e2k | epiphany \
+	| fido | fr30 | frv | ft32 \
 	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+	| hexagon \
 	| i370 | i860 | i960 | ia64 \
 	| ip2k | iq2000 \
+	| k1om \
+	| le32 | le64 \
+	| lm32 \
 	| m32c | m32r | m32rle | m68000 | m68k | m88k \
-	| maxq | mb | microblaze | mcore | mep \
+	| maxq | mb | microblaze | microblazeel | mcore | mep | metag \
 	| mips | mipsbe | mipseb | mipsel | mipsle \
 	| mips16 \
 	| mips64 | mips64el \
-	| mips64vr | mips64vrel \
+	| mips64octeon | mips64octeonel \
 	| mips64orion | mips64orionel \
+	| mips64r5900 | mips64r5900el \
+	| mips64vr | mips64vrel \
 	| mips64vr4100 | mips64vr4100el \
 	| mips64vr4300 | mips64vr4300el \
 	| mips64vr5000 | mips64vr5000el \
 	| mips64vr5900 | mips64vr5900el \
 	| mipsisa32 | mipsisa32el \
 	| mipsisa32r2 | mipsisa32r2el \
+	| mipsisa32r6 | mipsisa32r6el \
 	| mipsisa64 | mipsisa64el \
 	| mipsisa64r2 | mipsisa64r2el \
+	| mipsisa64r6 | mipsisa64r6el \
 	| mipsisa64sb1 | mipsisa64sb1el \
 	| mipsisa64sr71k | mipsisa64sr71kel \
+	| mipsr5900 | mipsr5900el \
 	| mipstx39 | mipstx39el \
 	| mn10200 | mn10300 \
+	| moxie \
 	| mt \
 	| msp430 \
-	| nios | nios2 \
+	| nds32 | nds32le | nds32be \
+	| nios | nios2 | nios2eb | nios2el \
 	| ns16k | ns32k \
-	| or32 \
+	| open8 | or1k | or1knd | or32 \
 	| pdp10 | pdp11 | pj | pjl \
-	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+	| powerpc | powerpc64 | powerpc64le | powerpcle \
 	| pyramid \
+	| riscv32 | riscv64 \
+	| rl78 | rx \
 	| score \
-	| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+	| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
 	| sh64 | sh64le \
 	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
 	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
-	| spu | strongarm \
-	| tahoe | thumb | tic4x | tic80 | tron \
-	| v850 | v850e \
+	| spu \
+	| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
+	| ubicom32 \
+	| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
+	| visium \
 	| we32k \
-	| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
-	| z8k)
+	| x86 | xc16x | xstormy16 | xtensa \
+	| z8k | z80)
 		basic_machine=$basic_machine-unknown
 		;;
-	m6811 | m68hc11 | m6812 | m68hc12)
-		# Motorola 68HC11/12.
+	c54x)
+		basic_machine=tic54x-unknown
+		;;
+	c55x)
+		basic_machine=tic55x-unknown
+		;;
+	c6x)
+		basic_machine=tic6x-unknown
+		;;
+	leon|leon[3-9])
+		basic_machine=sparc-$basic_machine
+		;;
+	m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
 		basic_machine=$basic_machine-unknown
 		os=-none
 		;;
@@ -300,6 +342,21 @@ case $basic_machine in
 		basic_machine=mt-unknown
 		;;
 
+	strongarm | thumb | xscale)
+		basic_machine=arm-unknown
+		;;
+	xgate)
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	xscaleeb)
+		basic_machine=armeb-unknown
+		;;
+
+	xscaleel)
+		basic_machine=armel-unknown
+		;;
+
 	# We use `pc' rather than `unknown'
 	# because (1) that's what they normally are, and
 	# (2) the word "unknown" tends to confuse beginning users.
@@ -314,64 +371,89 @@ case $basic_machine in
 	# Recognize the basic CPU types with company name.
 	580-* \
 	| a29k-* \
+	| aarch64-* | aarch64_be-* \
 	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
 	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
-	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
 	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
 	| avr-* | avr32-* \
+	| ba-* \
+	| be32-* | be64-* \
 	| bfin-* | bs2000-* \
-	| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
-	| clipper-* | craynv-* | cydra-* \
+	| c[123]* | c30-* | [cjt]90-* | c4x-* \
+	| c8051-* | clipper-* | craynv-* | cydra-* \
 	| d10v-* | d30v-* | dlx-* \
-	| elxsi-* \
+	| e2k-* | elxsi-* \
 	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
 	| h8300-* | h8500-* \
 	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+	| hexagon-* \
 	| i*86-* | i860-* | i960-* | ia64-* \
 	| ip2k-* | iq2000-* \
+	| k1om-* \
+	| le32-* | le64-* \
+	| lm32-* \
 	| m32c-* | m32r-* | m32rle-* \
 	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
-	| m88110-* | m88k-* | maxq-* | mcore-* \
+	| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
+	| microblaze-* | microblazeel-* \
 	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
 	| mips16-* \
 	| mips64-* | mips64el-* \
-	| mips64vr-* | mips64vrel-* \
+	| mips64octeon-* | mips64octeonel-* \
 	| mips64orion-* | mips64orionel-* \
+	| mips64r5900-* | mips64r5900el-* \
+	| mips64vr-* | mips64vrel-* \
 	| mips64vr4100-* | mips64vr4100el-* \
 	| mips64vr4300-* | mips64vr4300el-* \
 	| mips64vr5000-* | mips64vr5000el-* \
 	| mips64vr5900-* | mips64vr5900el-* \
 	| mipsisa32-* | mipsisa32el-* \
 	| mipsisa32r2-* | mipsisa32r2el-* \
+	| mipsisa32r6-* | mipsisa32r6el-* \
 	| mipsisa64-* | mipsisa64el-* \
 	| mipsisa64r2-* | mipsisa64r2el-* \
+	| mipsisa64r6-* | mipsisa64r6el-* \
 	| mipsisa64sb1-* | mipsisa64sb1el-* \
 	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+	| mipsr5900-* | mipsr5900el-* \
 	| mipstx39-* | mipstx39el-* \
 	| mmix-* \
 	| mt-* \
 	| msp430-* \
-	| nios-* | nios2-* \
+	| nds32-* | nds32le-* | nds32be-* \
+	| nios-* | nios2-* | nios2eb-* | nios2el-* \
 	| none-* | np1-* | ns16k-* | ns32k-* \
+	| open8-* \
+	| or1k*-* \
 	| orion-* \
 	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
-	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
 	| pyramid-* \
-	| romp-* | rs6000-* \
-	| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+	| riscv32-* | riscv64-* \
+	| rl78-* | romp-* | rs6000-* | rx-* \
+	| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
 	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
 	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
 	| sparclite-* \
-	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
-	| tahoe-* | thumb-* \
+	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \
+	| tahoe-* \
 	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+	| tile*-* \
 	| tron-* \
-	| v850-* | v850e-* | vax-* \
+	| ubicom32-* \
+	| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
+	| vax-* \
+	| visium-* \
 	| we32k-* \
-	| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
-	| xstormy16-* | xtensa-* \
+	| x86-* | x86_64-* | xc16x-* | xps100-* \
+	| xstormy16-* | xtensa*-* \
 	| ymp-* \
-	| z8k-*)
+	| z8k-* | z80-*)
+		;;
+	# Recognize the basic CPU types without company name, with glob match.
+	xtensa*)
+		basic_machine=$basic_machine-unknown
 		;;
 	# Recognize the various machine names and aliases which stand
 	# for a CPU type and a company and sometimes even an OS.
@@ -389,7 +471,7 @@ case $basic_machine in
 		basic_machine=a29k-amd
 		os=-udi
 		;;
-    	abacus)
+	abacus)
 		basic_machine=abacus-unknown
 		;;
 	adobe68k)
@@ -435,6 +517,13 @@ case $basic_machine in
 		basic_machine=m68k-apollo
 		os=-bsd
 		;;
+	aros)
+		basic_machine=i386-pc
+		os=-aros
+		;;
+        asmjs)
+		basic_machine=asmjs-unknown
+		;;
 	aux)
 		basic_machine=m68k-apple
 		os=-aux
@@ -443,10 +532,35 @@ case $basic_machine in
 		basic_machine=ns32k-sequent
 		os=-dynix
 		;;
+	blackfin)
+		basic_machine=bfin-unknown
+		os=-linux
+		;;
+	blackfin-*)
+		basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	bluegene*)
+		basic_machine=powerpc-ibm
+		os=-cnk
+		;;
+	c54x-*)
+		basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c55x-*)
+		basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c6x-*)
+		basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
 	c90)
 		basic_machine=c90-cray
 		os=-unicos
 		;;
+	cegcc)
+		basic_machine=arm-unknown
+		os=-cegcc
+		;;
 	convex-c1)
 		basic_machine=c1-convex
 		os=-bsd
@@ -475,7 +589,7 @@ case $basic_machine in
 		basic_machine=craynv-cray
 		os=-unicosmp
 		;;
-	cr16)
+	cr16 | cr16-*)
 		basic_machine=cr16-unknown
 		os=-elf
 		;;
@@ -514,6 +628,10 @@ case $basic_machine in
 		basic_machine=m88k-motorola
 		os=-sysv3
 		;;
+	dicos)
+		basic_machine=i686-pc
+		os=-dicos
+		;;
 	djgpp)
 		basic_machine=i586-pc
 		os=-msdosdjgpp
@@ -629,7 +747,6 @@ case $basic_machine in
 	i370-ibm* | ibm*)
 		basic_machine=i370-ibm
 		;;
-# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
 	i*86v32)
 		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
 		os=-sysv32
@@ -668,6 +785,17 @@ case $basic_machine in
 		basic_machine=m68k-isi
 		os=-sysv
 		;;
+	leon-*|leon[3-9]-*)
+		basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
+		;;
+	m68knommu)
+		basic_machine=m68k-unknown
+		os=-linux
+		;;
+	m68knommu-*)
+		basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
 	m88k-omron*)
 		basic_machine=m88k-omron
 		;;
@@ -679,8 +807,15 @@ case $basic_machine in
 		basic_machine=ns32k-utek
 		os=-sysv
 		;;
+	microblaze*)
+		basic_machine=microblaze-xilinx
+		;;
+	mingw64)
+		basic_machine=x86_64-pc
+		os=-mingw64
+		;;
 	mingw32)
-		basic_machine=i386-pc
+		basic_machine=i686-pc
 		os=-mingw32
 		;;
 	mingw32ce)
@@ -708,6 +843,10 @@ case $basic_machine in
 		basic_machine=powerpc-unknown
 		os=-morphos
 		;;
+	moxiebox)
+		basic_machine=moxie-unknown
+		os=-moxiebox
+		;;
 	msdos)
 		basic_machine=i386-pc
 		os=-msdos
@@ -715,10 +854,18 @@ case $basic_machine in
 	ms1-*)
 		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
 		;;
+	msys)
+		basic_machine=i686-pc
+		os=-msys
+		;;
 	mvs)
 		basic_machine=i370-ibm
 		os=-mvs
 		;;
+	nacl)
+		basic_machine=le32-unknown
+		os=-nacl
+		;;
 	ncr3000)
 		basic_machine=i486-ncr
 		os=-sysv4
@@ -783,6 +930,12 @@ case $basic_machine in
 	np1)
 		basic_machine=np1-gould
 		;;
+	neo-tandem)
+		basic_machine=neo-tandem
+		;;
+	nse-tandem)
+		basic_machine=nse-tandem
+		;;
 	nsr-tandem)
 		basic_machine=nsr-tandem
 		;;
@@ -813,6 +966,14 @@ case $basic_machine in
 		basic_machine=i860-intel
 		os=-osf
 		;;
+	parisc)
+		basic_machine=hppa-unknown
+		os=-linux
+		;;
+	parisc-*)
+		basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
 	pbd)
 		basic_machine=sparc-tti
 		;;
@@ -857,9 +1018,10 @@ case $basic_machine in
 		;;
 	power)	basic_machine=power-ibm
 		;;
-	ppc)	basic_machine=powerpc-unknown
+	ppc | ppcbe)	basic_machine=powerpc-unknown
 		;;
-	ppc-*)	basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+	ppc-* | ppcbe-*)
+		basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
 		;;
 	ppcle | powerpclittle | ppc-le | powerpc-little)
 		basic_machine=powerpcle-unknown
@@ -884,7 +1046,11 @@ case $basic_machine in
 		basic_machine=i586-unknown
 		os=-pw32
 		;;
-	rdos)
+	rdos | rdos64)
+		basic_machine=x86_64-pc
+		os=-rdos
+		;;
+	rdos32)
 		basic_machine=i386-pc
 		os=-rdos
 		;;
@@ -953,6 +1119,9 @@ case $basic_machine in
 		basic_machine=i860-stratus
 		os=-sysv4
 		;;
+	strongarm-* | thumb-*)
+		basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
 	sun2)
 		basic_machine=m68000-sun
 		;;
@@ -1009,17 +1178,9 @@ case $basic_machine in
 		basic_machine=t90-cray
 		os=-unicos
 		;;
-	tic54x | c54x*)
-		basic_machine=tic54x-unknown
-		os=-coff
-		;;
-	tic55x | c55x*)
-		basic_machine=tic55x-unknown
-		os=-coff
-		;;
-	tic6x | c6x*)
-		basic_machine=tic6x-unknown
-		os=-coff
+	tile*)
+		basic_machine=$basic_machine-unknown
+		os=-linux-gnu
 		;;
 	tx39)
 		basic_machine=mipstx39-unknown
@@ -1088,6 +1249,9 @@ case $basic_machine in
 	xps | xps100)
 		basic_machine=xps100-honeywell
 		;;
+	xscale-* | xscalee[bl]-*)
+		basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
+		;;
 	ymp)
 		basic_machine=ymp-cray
 		os=-unicos
@@ -1096,6 +1260,10 @@ case $basic_machine in
 		basic_machine=z8k-unknown
 		os=-sim
 		;;
+	z80-*-coff)
+		basic_machine=z80-unknown
+		os=-sim
+		;;
 	none)
 		basic_machine=none-none
 		os=-none
@@ -1134,7 +1302,7 @@ case $basic_machine in
 	we32k)
 		basic_machine=we32k-att
 		;;
-	sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+	sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
 		basic_machine=sh-unknown
 		;;
 	sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
@@ -1181,9 +1349,12 @@ esac
 if [ x"$os" != x"" ]
 then
 case $os in
-        # First match some system type aliases
-        # that might get confused with valid system types.
+	# First match some system type aliases
+	# that might get confused with valid system types.
 	# -solaris* is a basic system type, with this one exception.
+	-auroraux)
+		os=-auroraux
+		;;
 	-solaris1 | -solaris1.*)
 		os=`echo $os | sed -e 's|solaris1|sunos4|'`
 		;;
@@ -1204,29 +1375,31 @@ case $os in
 	# Each alternative MUST END IN A *, to match a version number.
 	# -sysv* is not here because it comes later, after sysvr4.
 	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
-	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
-	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
+	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+	      | -sym* | -kopensolaris* | -plan9* \
 	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
-	      | -aos* \
+	      | -aos* | -aros* | -cloudabi* | -sortix* \
 	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
 	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
 	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
-	      | -openbsd* | -solidbsd* \
+	      | -bitrig* | -openbsd* | -solidbsd* \
 	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
 	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
 	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
 	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
-	      | -chorusos* | -chorusrdb* \
-	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
-	      | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
-	      | -uxpv* | -beos* | -mpeix* | -udk* \
+	      | -chorusos* | -chorusrdb* | -cegcc* \
+	      | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+	      | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
+	      | -linux-newlib* | -linux-musl* | -linux-uclibc* \
+	      | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
 	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
 	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
 	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
 	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
 	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
 	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
-	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
+	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
 	# Remember, each alternative MUST END IN *, to match a version number.
 		;;
 	-qnx*)
@@ -1265,7 +1438,7 @@ case $os in
 	-opened*)
 		os=-openedition
 		;;
-        -os400*)
+	-os400*)
 		os=-os400
 		;;
 	-wince*)
@@ -1314,7 +1487,7 @@ case $os in
 	-sinix*)
 		os=-sysv4
 		;;
-        -tpf*)
+	-tpf*)
 		os=-tpf
 		;;
 	-triton*)
@@ -1350,12 +1523,14 @@ case $os in
 	-aros*)
 		os=-aros
 		;;
-	-kaos*)
-		os=-kaos
-		;;
 	-zvmoe)
 		os=-zvmoe
 		;;
+	-dicos*)
+		os=-dicos
+		;;
+	-nacl*)
+		;;
 	-none)
 		;;
 	*)
@@ -1378,10 +1553,10 @@ else
 # system, and we'll never get to this point.
 
 case $basic_machine in
-        score-*)
+	score-*)
 		os=-elf
 		;;
-        spu-*)
+	spu-*)
 		os=-elf
 		;;
 	*-acorn)
@@ -1393,8 +1568,23 @@ case $basic_machine in
 	arm*-semi)
 		os=-aout
 		;;
-        c4x-* | tic4x-*)
-        	os=-coff
+	c4x-* | tic4x-*)
+		os=-coff
+		;;
+	c8051-*)
+		os=-elf
+		;;
+	hexagon-*)
+		os=-elf
+		;;
+	tic54x-*)
+		os=-coff
+		;;
+	tic55x-*)
+		os=-coff
+		;;
+	tic6x-*)
+		os=-coff
 		;;
 	# This must come before the *-dec entry.
 	pdp10-*)
@@ -1414,14 +1604,11 @@ case $basic_machine in
 		;;
 	m68000-sun)
 		os=-sunos3
-		# This also exists in the configure program, but was not the
-		# default.
-		# os=-sunos4
 		;;
 	m68*-cisco)
 		os=-aout
 		;;
-        mep-*)
+	mep-*)
 		os=-elf
 		;;
 	mips*-cisco)
@@ -1448,7 +1635,7 @@ case $basic_machine in
 	*-ibm)
 		os=-aix
 		;;
-    	*-knuth)
+	*-knuth)
 		os=-mmixware
 		;;
 	*-wec)
@@ -1553,7 +1740,7 @@ case $basic_machine in
 			-sunos*)
 				vendor=sun
 				;;
-			-aix*)
+			-cnk*|-aix*)
 				vendor=ibm
 				;;
 			-beos*)
diff --git a/configure b/configure
index 5dc3234..1d7b76b 100755
--- a/configure
+++ b/configure
@@ -631,6 +631,8 @@ ac_includes_default="\
 
 ac_subst_vars='LTLIBOBJS
 LIBOBJS
+USE_ONLY_CRYPTODLL_ALG
+HAVE_CRYPTOPP
 HAVE_ARMADILLO
 RASDAMAN_LIB
 RASDAMAN_INC
@@ -652,14 +654,20 @@ GDAL_VERSION_MINOR
 GDAL_VERSION_MAJOR
 PROJ_INCLUDE
 PROJ_STATIC
+PDFIUM_PLUGIN_LIB
+PDFIUM_INC
+HAVE_PDFIUM
+PODOFO_PLUGIN_LIB
 PODOFO_INC
 HAVE_PODOFO
+POPPLER_PLUGIN_LIB
 POPPLER_INC
 POPPLER_0_23_OR_LATER
 POPPLER_0_20_OR_LATER
 POPPLER_BASE_STREAM_HAS_TWO_ARGS
 POPPLER_HAS_OPTCONTENT
 HAVE_POPPLER
+PDF_PLUGIN
 PAM_SETTING
 JSON_INCLUDE
 LIBJSONC_SETTING
@@ -667,6 +675,7 @@ FREEXL_INCLUDE
 HAVE_FREEXL
 OPENCL_LIB
 OPENCL_FLAGS
+QHULL_SETTING
 GEOS_CONFIG
 GEOS_VERSION
 HAVE_GEOS
@@ -684,13 +693,14 @@ HAVE_PCRE
 SQLITE_HAS_COLUMN_METADATA
 HAVE_SQLITE
 SQLITE_INC
-SQLITE3_LDFLAGS
-SQLITE3_CFLAGS
-SQLITE3_VERSION
 SPATIALITE_412_OR_LATER
 SPATIALITE_AMALGAMATION
 SPATIALITE_INC
+SPATIALITE_SONAME
 HAVE_SPATIALITE
+SQLITE3_LDFLAGS
+SQLITE3_CFLAGS
+SQLITE3_VERSION
 LIBXML2_LIB
 LIBXML2_INC
 HAVE_LIBXML2
@@ -730,7 +740,7 @@ MYSQL_LIB
 MYSQL_INC
 HAVE_MYSQL
 MYSQL_CONFIG
-OGR_ENABLED
+GNM_ENABLED
 OPT_GDAL_FORMATS
 ORACLE_OCI_LDFLAGS
 ORACLE_OCI_CFLAGS
@@ -766,6 +776,9 @@ HAVE_HDF5
 HDF4_HAS_MAXOPENFILES
 HDF4_INCLUDE
 HAVE_HDF4
+MONGODB_INC
+MONGODB_LIB
+MONGODB_ENABLED
 SOSI_INC
 SOSI_LIB
 SOSI_ENABLED
@@ -804,11 +817,15 @@ LIBZ_SETTING
 RENAME_INTERNAL_LIBGEOTIFF_SYMBOLS
 RENAME_INTERNAL_LIBTIFF_SYMBOLS
 HAVE_HIDE_INTERNAL_SYMBOLS
+CXXFLAGS_NO_LTO_IF_AVX_NONDEFAULT
+CFLAGS_NO_LTO_IF_AVX_NONDEFAULT
 HAVE_AVX_AT_COMPILE_TIME
 AVXFLAGS
 HAVE_SSE_AT_COMPILE_TIME
 SSEFLAGS
 HAVE_GCC_ATOMIC_BUILTINS
+CXXFLAGS_NOFTRAPV
+CFLAGS_NOFTRAPV
 HAVE_LIBTOOL
 SO_EXT
 LD_SHARED
@@ -838,6 +855,10 @@ LIBTOOL
 OBJDUMP
 DLLTOOL
 AS
+NO_LOGICAL_OP_FLAG
+NO_NON_VIRTUAL_DTOR_FLAG
+NO_SIGN_COMPARE
+NO_UNUSED_PARAMETER_FLAG
 C_WFLAGS
 CXX_WFLAGS
 ac_ct_CXX
@@ -912,6 +933,7 @@ with_unix_stdio_64
 enable_debug
 with_sse
 with_avx
+enable_lto
 with_hide_internal_symbols
 with_rename_internal_libtiff_symbols
 with_rename_internal_libgeotiff_symbols
@@ -938,6 +960,8 @@ with_gif
 with_ogdi
 with_fme
 with_sosi
+with_mongocxx
+with_boost_lib_path
 with_hdf4
 with_hdf5
 with_kea
@@ -956,7 +980,7 @@ with_oci
 with_oci_include
 with_oci_lib
 with_grib
-with_ogr
+with_gnm
 with_mysql
 with_ingres
 with_xerces
@@ -973,6 +997,7 @@ with_dods_root
 with_curl
 with_xml2
 with_spatialite
+with_spatialite_soname
 with_sqlite3
 with_pcre
 with_dwgdirect
@@ -982,16 +1007,21 @@ with_sde_version
 with_epsilon
 with_webp
 with_geos
+with_qhull
 with_opencl
 with_opencl_include
 with_opencl_lib
 with_freexl
 with_libjson_c
 with_pam
+enable_pdf_plugin
 with_poppler
 with_podofo
 with_podofo_lib
 with_podofo_extra_lib_for_test
+with_pdfium
+with_pdfium_lib
+with_pdfium_extra_lib_for_test
 with_static_proj4
 with_gdal_ver
 with_
@@ -1004,6 +1034,7 @@ with_jvm_lib
 with_jvm_lib_add_rpath
 with_rasdaman
 with_armadillo
+with_cryptopp
 '
       ac_precious_vars='build_alias
 host_alias
@@ -1638,7 +1669,11 @@ Optional Features:
                           optimize for fast installation [default=yes]
   --disable-libtool-lock  avoid locking (might break parallel builds)
   --enable-debug          enable debugging (disabled by default)
+  --enable-lto            enable LTO(link time optimization) (disabled by
+                          default)
   --disable-rpath         do not hardcode runtime library paths
+  --enable-pdf-plugin     enable PDF driver as a plugin (included in libgdal
+                          by default)
 
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
@@ -1672,7 +1707,7 @@ Optional Packages:
   --with-png=ARG        Include PNG support (ARG=internal, no or path)
   --with-dds=ARG        Include DDS support (ARG=no, or path)
   --with-gta=ARG        Include GTA support (ARG=no or libgta tree prefix)
-  --with-pcidsk=ARG     Path to external PCIDSK SDK, or internal (default), or old
+  --with-pcidsk=ARG     Path to external PCIDSK SDK or internal (default)
   --with-libtiff=ARG    Libtiff library to use (ARG=internal, yes or path)
   --with-geotiff=ARG    Libgeotiff library to use (ARG=internal, yes or path)
   --with-jpeg=ARG       Include JPEG support (ARG=internal, no or path)
@@ -1681,6 +1716,8 @@ Optional Packages:
   --with-ogdi=ARG       Include OGDI support (ARG=path)
   --with-fme=ARG        Include FMEObjects support (ARG=FME_HOME path)
   --with-sosi=ARG        Include SOSI support (ARG=SOSI lib Path, yes or no)
+  --with-mongocxx=ARG        Include MongoCXX support (ARG=Path, yes or no)
+  --with-boost-lib-path=ARG   Path to boost libraries for mongocxx client
   --with-hdf4=ARG       Include HDF4 support (ARG=path)
   --with-hdf5=ARG       Include HDF5 support (ARG=path)
   --with-kea=ARG      Include kealib (ARG=path to kea-config) [default=yes]
@@ -1702,7 +1739,7 @@ Optional Packages:
                           use Oracle OCI API headers from given path
   --with-oci-lib=[DIR]    use Oracle OCI API libraries from given path
   --without-grib          Disable GRIB driver
-  --without-ogr         Don't build OGR into shared library
+  --with-gnm            Build GNM into shared library
   --with-mysql=ARG      Include MySQL (ARG=path to mysql_config) [default=no]
   --with-ingres=ARG     Include Ingres (ARG=$II_SYSTEM)
   --with-xerces=[ARG]     use Xerces C++ Parser from given prefix (ARG=path);
@@ -1721,7 +1758,8 @@ Optional Packages:
   --with-dods-root=ARG  Include DODS support (ARG=no or absolute path)
   --with-curl=ARG       Include curl (ARG=path to curl-config.)
   --with-xml2=ARG       Include libxml2 (ARG=path to xml2-config.)
-  --with-spatialite=ARG Include SpatiaLite support (ARG=no(default), yes or path)
+  --with-spatialite=ARG Include SpatiaLite support (ARG=no(default), yes, dlopen (only supported for Spatialite >= 4.1.2) or path)
+  --with-spatialite-soname=ARG Spatialite shared object name (e.g. libspatialite.so), only used if --with-spatiliate=dlopen
   --with-sqlite3=[ARG]    use SQLite 3 library [default=yes], optionally
                           specify the prefix for sqlite3 library
   --with-pcre             Include libpcre support (REGEXP support for SQLite)
@@ -1734,16 +1772,20 @@ Optional Packages:
   --with-webp=ARG    Include WEBP support (ARG=no, yes or libwebp install root path)
   --with-geos=ARG         Include GEOS support (ARG=yes, no or geos-config
                           path)
+  --with-qhull=ARG     Include QHull support (ARG=no, yes, internal)
   --with-opencl=ARG       Include OpenCL (GPU) support
   --with-opencl-include=ARG OpenCL Include directory (with a CL subdirectory)
-  --with-opencl-lib=ARG   OpenCL Link Flags (ie. -L/xxx -lOpenCL)
+  --with-opencl-lib=ARG   OpenCL Link Flags (i.e. -L/xxx -lOpenCL)
   --with-freexl=ARG    Include freexl support (ARG=no, yes (default) or libfreexl install path)
   --with-libjson-c=ARG       Include libjson-c support (ARG=internal or libjson-c directory)
   --without-pam         Disable PAM (.aux.xml) support
   --with-poppler=ARG    Include poppler(for PDF) support (ARG=no(default), yes or poppler install path)
   --with-podofo=ARG    Include podofo(for PDF) support (ARG=no(default), yes or podofo install path)
-  --with-podofo-lib=ARG   podofo Link Flags (ie. -L/xxx -lpodofo ...). Mainly for static libpodofo
-  --with-podofo-extra-lib-for-test=ARG   Additional libraries to pass the detection test, but not used for libgdal linking (ie. -ljpeg ...). Mainly for static libpodofo
+  --with-podofo-lib=ARG   podofo Link Flags (i.e. -L/xxx -lpodofo ...). Mainly for static libpodofo
+  --with-podofo-extra-lib-for-test=ARG   Additional libraries to pass the detection test, but not used for libgdal linking (i.e. -ljpeg ...). Mainly for static libpodofo
+  --with-pdfium=ARG    Include pdfium (for PDF) support (ARG=no(default), yes or pdfium install path)
+  --with-pdfium-lib=ARG   pdfium Link Flags (i.e. -L/xxx -lpdfium ...). Mainly for static libpdfium
+  --with-pdfium-extra-lib-for-test=ARG   Additional libraries to pass the detection test, but not used for libgdal linking (i.e. -ljpeg ...). Mainly for static libpdfium
   --with-static-proj4=ARG Compile with PROJ.4 statically (ARG=no or path)
   --with-gdal-ver=ARG   Override GDAL version
   --with-macosx-framework         Build and install GDAL as a Mac OS X Framework
@@ -1756,6 +1798,8 @@ Optional Packages:
   --with-jvm-lib-add-rpath    Add the libjvm path to the RPATH (no by default)
   --with-rasdaman=DIR        Include rasdaman support (DIR is rasdaman's install dir).
   --with-armadillo=ARG       Include Armadillo support for faster TPS transform computation (ARG=yes/no/path to armadillo install root) [default=no]
+  --with-cryptopp=ARG       Include cryptopp support (ARG=yes, no or path)
+  --without-mrf           Disable MRF driver
 
 Some influential environment variables:
   CC          C compiler command
@@ -4225,386 +4269,366 @@ case ".$ac_cv_cxxflags_warn_all" in
  ;;
 esac
 
-CXX_WFLAGS=$CXX_WFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -Wextra" >&5
+$as_echo_n "checking whether C compiler accepts -Werror -Wextra... " >&6; }
+if ${ax_cv_check_cflags___Werror__Wextra+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
 
-C_WFLAGS=$C_WFLAGS
+  ax_check_save_flags=$CFLAGS
+  CFLAGS="$CFLAGS  -Werror -Wextra"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
 
+int
+main ()
+{
 
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$CC"; then
-  ac_cv_prog_CC="$CC" # Let the user override the test.
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ax_cv_check_cflags___Werror__Wextra=yes
 else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_CC="${ac_tool_prefix}gcc"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
+  ax_cv_check_cflags___Werror__Wextra=no
 fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CFLAGS=$ax_check_save_flags
 fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__Wextra" >&5
+$as_echo "$ax_cv_check_cflags___Werror__Wextra" >&6; }
+if test "x$ax_cv_check_cflags___Werror__Wextra" = xyes; then :
+  C_WFLAGS="$C_WFLAGS -Wextra" CXX_WFLAGS="$CXX_WFLAGS -Wextra"
 else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+  :
 fi
 
-
-fi
-if test -z "$ac_cv_prog_CC"; then
-  ac_ct_CC=$CC
-  # Extract the first word of "gcc", so it can be a program name with args.
-set dummy gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -Winit-self" >&5
+$as_echo_n "checking whether C compiler accepts -Werror -Winit-self... " >&6; }
+if ${ax_cv_check_cflags___Werror__Winit_self+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  if test -n "$ac_ct_CC"; then
-  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_CC="gcc"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
 
+  ax_check_save_flags=$CFLAGS
+  CFLAGS="$CFLAGS  -Werror -Winit-self"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ax_cv_check_cflags___Werror__Winit_self=yes
+else
+  ax_cv_check_cflags___Werror__Winit_self=no
 fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CFLAGS=$ax_check_save_flags
 fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__Winit_self" >&5
+$as_echo "$ax_cv_check_cflags___Werror__Winit_self" >&6; }
+if test "x$ax_cv_check_cflags___Werror__Winit_self" = xyes; then :
+  C_WFLAGS="$C_WFLAGS -Winit-self" CXX_WFLAGS="$CXX_WFLAGS -Winit-self"
 else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+  :
 fi
 
-  if test "x$ac_ct_CC" = x; then
-    CC=""
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    CC=$ac_ct_CC
-  fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -Wunused-parameter" >&5
+$as_echo_n "checking whether C compiler accepts -Werror -Wunused-parameter... " >&6; }
+if ${ax_cv_check_cflags___Werror__Wunused_parameter+:} false; then :
+  $as_echo_n "(cached) " >&6
 else
-  CC="$ac_cv_prog_CC"
+
+  ax_check_save_flags=$CFLAGS
+  CFLAGS="$CFLAGS  -Werror -Wunused-parameter"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ax_cv_check_cflags___Werror__Wunused_parameter=yes
+else
+  ax_cv_check_cflags___Werror__Wunused_parameter=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__Wunused_parameter" >&5
+$as_echo "$ax_cv_check_cflags___Werror__Wunused_parameter" >&6; }
+if test "x$ax_cv_check_cflags___Werror__Wunused_parameter" = xyes; then :
+  C_WFLAGS="$C_WFLAGS -Wunused-parameter" CXX_WFLAGS="$CXX_WFLAGS -Wunused-parameter" NO_UNUSED_PARAMETER_FLAG="-Wno-unused-parameter"
+else
+  :
 fi
 
-if test -z "$CC"; then
-          if test -n "$ac_tool_prefix"; then
-    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -Wmissing-prototypes" >&5
+$as_echo_n "checking whether C compiler accepts -Werror -Wmissing-prototypes... " >&6; }
+if ${ax_cv_check_cflags___Werror__Wmissing_prototypes+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  if test -n "$CC"; then
-  ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_CC="${ac_tool_prefix}cc"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
 
+  ax_check_save_flags=$CFLAGS
+  CFLAGS="$CFLAGS  -Werror -Wmissing-prototypes"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ax_cv_check_cflags___Werror__Wmissing_prototypes=yes
+else
+  ax_cv_check_cflags___Werror__Wmissing_prototypes=no
 fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CFLAGS=$ax_check_save_flags
 fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__Wmissing_prototypes" >&5
+$as_echo "$ax_cv_check_cflags___Werror__Wmissing_prototypes" >&6; }
+if test "x$ax_cv_check_cflags___Werror__Wmissing_prototypes" = xyes; then :
+  C_WFLAGS="$C_WFLAGS -Wmissing-prototypes"
 else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+  :
 fi
 
-
-  fi
-fi
-if test -z "$CC"; then
-  # Extract the first word of "cc", so it can be a program name with args.
-set dummy cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -Wmissing-declarations" >&5
+$as_echo_n "checking whether C compiler accepts -Werror -Wmissing-declarations... " >&6; }
+if ${ax_cv_check_cflags___Werror__Wmissing_declarations+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  if test -n "$CC"; then
-  ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-  ac_prog_rejected=no
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
-       ac_prog_rejected=yes
-       continue
-     fi
-    ac_cv_prog_CC="cc"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
 
-if test $ac_prog_rejected = yes; then
-  # We found a bogon in the path, so make sure we never use it.
-  set dummy $ac_cv_prog_CC
-  shift
-  if test $# != 0; then
-    # We chose a different compiler from the bogus one.
-    # However, it has the same basename, so the bogon will be chosen
-    # first if we set CC to just the basename; use the full file name.
-    shift
-    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
-  fi
-fi
+  ax_check_save_flags=$CFLAGS
+  CFLAGS="$CFLAGS  -Werror -Wmissing-declarations"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ax_cv_check_cflags___Werror__Wmissing_declarations=yes
+else
+  ax_cv_check_cflags___Werror__Wmissing_declarations=no
 fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CFLAGS=$ax_check_save_flags
 fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__Wmissing_declarations" >&5
+$as_echo "$ax_cv_check_cflags___Werror__Wmissing_declarations" >&6; }
+if test "x$ax_cv_check_cflags___Werror__Wmissing_declarations" = xyes; then :
+  C_WFLAGS="$C_WFLAGS -Wmissing-declarations"
 else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+  :
 fi
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -Wformat" >&5
+$as_echo_n "checking whether C compiler accepts -Werror -Wformat... " >&6; }
+if ${ax_cv_check_cflags___Werror__Wformat+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
 
-fi
-if test -z "$CC"; then
-  if test -n "$ac_tool_prefix"; then
-  for ac_prog in cl.exe
-  do
-    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
-set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$CC"; then
-  ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
+  ax_check_save_flags=$CFLAGS
+  CFLAGS="$CFLAGS  -Werror -Wformat"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
 
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ax_cv_check_cflags___Werror__Wformat=yes
+else
+  ax_cv_check_cflags___Werror__Wformat=no
 fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CFLAGS=$ax_check_save_flags
 fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__Wformat" >&5
+$as_echo "$ax_cv_check_cflags___Werror__Wformat" >&6; }
+if test "x$ax_cv_check_cflags___Werror__Wformat" = xyes; then :
+  C_WFLAGS="$C_WFLAGS -Wformat" CXX_WFLAGS="$CXX_WFLAGS -Wformat"
 else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+  :
 fi
 
-
-    test -n "$CC" && break
-  done
-fi
-if test -z "$CC"; then
-  ac_ct_CC=$CC
-  for ac_prog in cl.exe
-do
-  # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -Wformat -Werror=format-security -Wno-format-nonliteral" >&5
+$as_echo_n "checking whether C compiler accepts -Werror -Wformat -Werror=format-security -Wno-format-nonliteral... " >&6; }
+if ${ax_cv_check_cflags___Werror__Wformat__Werror_format_security__Wno_format_nonliteral+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  if test -n "$ac_ct_CC"; then
-  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_CC="$ac_prog"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
 
+  ax_check_save_flags=$CFLAGS
+  CFLAGS="$CFLAGS  -Werror -Wformat -Werror=format-security -Wno-format-nonliteral"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ax_cv_check_cflags___Werror__Wformat__Werror_format_security__Wno_format_nonliteral=yes
+else
+  ax_cv_check_cflags___Werror__Wformat__Werror_format_security__Wno_format_nonliteral=no
 fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CFLAGS=$ax_check_save_flags
 fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__Wformat__Werror_format_security__Wno_format_nonliteral" >&5
+$as_echo "$ax_cv_check_cflags___Werror__Wformat__Werror_format_security__Wno_format_nonliteral" >&6; }
+if test "x$ax_cv_check_cflags___Werror__Wformat__Werror_format_security__Wno_format_nonliteral" = xyes; then :
+  C_WFLAGS="$C_WFLAGS -Werror=format-security -Wno-format-nonliteral" CXX_WFLAGS="$CXX_WFLAGS -Werror=format-security -Wno-format-nonliteral"
 else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+  :
 fi
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -Wshorten-64-to-32" >&5
+$as_echo_n "checking whether C compiler accepts -Werror -Wshorten-64-to-32... " >&6; }
+if ${ax_cv_check_cflags___Werror__Wshorten_64_to_32+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
 
-  test -n "$ac_ct_CC" && break
-done
+  ax_check_save_flags=$CFLAGS
+  CFLAGS="$CFLAGS  -Werror -Wshorten-64-to-32"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
 
-  if test "x$ac_ct_CC" = x; then
-    CC=""
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    CC=$ac_ct_CC
-  fi
-fi
+int
+main ()
+{
 
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ax_cv_check_cflags___Werror__Wshorten_64_to_32=yes
+else
+  ax_cv_check_cflags___Werror__Wshorten_64_to_32=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__Wshorten_64_to_32" >&5
+$as_echo "$ax_cv_check_cflags___Werror__Wshorten_64_to_32" >&6; }
+if test "x$ax_cv_check_cflags___Werror__Wshorten_64_to_32" = xyes; then :
+  C_WFLAGS="$C_WFLAGS -Wshorten-64-to-32" CXX_WFLAGS="$CXX_WFLAGS -Wshorten-64-to-32"
+else
+  :
 fi
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -Wlogical-op" >&5
+$as_echo_n "checking whether C compiler accepts -Werror -Wlogical-op... " >&6; }
+if ${ax_cv_check_cflags___Werror__Wlogical_op+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
 
-test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "no acceptable C compiler found in \$PATH
-See \`config.log' for more details" "$LINENO" 5; }
+  ax_check_save_flags=$CFLAGS
+  CFLAGS="$CFLAGS  -Werror -Wlogical-op"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
 
-# Provide some information about the compiler.
-$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
-set X $ac_compile
-ac_compiler=$2
-for ac_option in --version -v -V -qversion; do
-  { { ac_try="$ac_compiler $ac_option >&5"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
-  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
-  ac_status=$?
-  if test -s conftest.err; then
-    sed '10a\
-... rest of stderr output deleted ...
-         10q' conftest.err >conftest.er1
-    cat conftest.er1 >&5
-  fi
-  rm -f conftest.er1 conftest.err
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }
-done
+int
+main ()
+{
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
-$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
-if ${ac_cv_c_compiler_gnu+:} false; then :
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ax_cv_check_cflags___Werror__Wlogical_op=yes
+else
+  ax_cv_check_cflags___Werror__Wlogical_op=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__Wlogical_op" >&5
+$as_echo "$ax_cv_check_cflags___Werror__Wlogical_op" >&6; }
+if test "x$ax_cv_check_cflags___Werror__Wlogical_op" = xyes; then :
+  C_WFLAGS="$C_WFLAGS -Wlogical-op" CXX_WFLAGS="$CXX_WFLAGS -Wlogical-op" NO_LOGICAL_OP_FLAG="-Wno-logical-op"
+else
+  :
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -Wshadow" >&5
+$as_echo_n "checking whether C compiler accepts -Werror -Wshadow... " >&6; }
+if ${ax_cv_check_cflags___Werror__Wshadow+:} false; then :
   $as_echo_n "(cached) " >&6
 else
+
+  ax_check_save_flags=$CFLAGS
+  CFLAGS="$CFLAGS  -Werror -Wshadow"
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 int
 main ()
 {
-#ifndef __GNUC__
-       choke me
-#endif
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  ac_compiler_gnu=yes
+  ax_cv_check_cflags___Werror__Wshadow=yes
 else
-  ac_compiler_gnu=no
+  ax_cv_check_cflags___Werror__Wshadow=no
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-ac_cv_c_compiler_gnu=$ac_compiler_gnu
-
+  CFLAGS=$ax_check_save_flags
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
-$as_echo "$ac_cv_c_compiler_gnu" >&6; }
-if test $ac_compiler_gnu = yes; then
-  GCC=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__Wshadow" >&5
+$as_echo "$ax_cv_check_cflags___Werror__Wshadow" >&6; }
+if test "x$ax_cv_check_cflags___Werror__Wshadow" = xyes; then :
+  C_WFLAGS="$C_WFLAGS -Wshadow" CXX_WFLAGS="$CXX_WFLAGS -Wshadow"
 else
-  GCC=
+  :
 fi
-ac_test_CFLAGS=${CFLAGS+set}
-ac_save_CFLAGS=$CFLAGS
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
-$as_echo_n "checking whether $CC accepts -g... " >&6; }
-if ${ac_cv_prog_cc_g+:} false; then :
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -Werror=vla" >&5
+$as_echo_n "checking whether C compiler accepts -Werror -Werror=vla... " >&6; }
+if ${ax_cv_check_cflags___Werror__Werror_vla+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  ac_save_c_werror_flag=$ac_c_werror_flag
-   ac_c_werror_flag=yes
-   ac_cv_prog_cc_g=no
-   CFLAGS="-g"
-   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+
+  ax_check_save_flags=$CFLAGS
+  CFLAGS="$CFLAGS  -Werror -Werror=vla"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 int
@@ -4616,10 +4640,30 @@ main ()
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_prog_cc_g=yes
+  ax_cv_check_cflags___Werror__Werror_vla=yes
 else
-  CFLAGS=""
-      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+  ax_cv_check_cflags___Werror__Werror_vla=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__Werror_vla" >&5
+$as_echo "$ax_cv_check_cflags___Werror__Werror_vla" >&6; }
+if test "x$ax_cv_check_cflags___Werror__Werror_vla" = xyes; then :
+  C_WFLAGS="$C_WFLAGS -Werror=vla" CXX_WFLAGS="$CXX_WFLAGS -Werror=vla"
+else
+  :
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -Werror=declaration-after-statement" >&5
+$as_echo_n "checking whether C compiler accepts -Werror -Werror=declaration-after-statement... " >&6; }
+if ${ax_cv_check_cflags___Werror__Werror_declaration_after_statement+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+  ax_check_save_flags=$CFLAGS
+  CFLAGS="$CFLAGS  -Werror -Werror=declaration-after-statement"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 int
@@ -4631,11 +4675,32 @@ main ()
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
+  ax_cv_check_cflags___Werror__Werror_declaration_after_statement=yes
+else
+  ax_cv_check_cflags___Werror__Werror_declaration_after_statement=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__Werror_declaration_after_statement" >&5
+$as_echo "$ax_cv_check_cflags___Werror__Werror_declaration_after_statement" >&6; }
+if test "x$ax_cv_check_cflags___Werror__Werror_declaration_after_statement" = xyes; then :
+  C_WFLAGS="$C_WFLAGS -Wdeclaration-after-statement"
+else
+  :
+fi
 
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -Wnull-dereference" >&5
+$as_echo_n "checking whether C compiler accepts -Werror -Wnull-dereference... " >&6; }
+if ${ax_cv_check_cflags___Werror__Wnull_dereference+:} false; then :
+  $as_echo_n "(cached) " >&6
 else
-  ac_c_werror_flag=$ac_save_c_werror_flag
-	 CFLAGS="-g"
-	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+
+  ax_check_save_flags=$CFLAGS
+  CFLAGS="$CFLAGS  -Werror -Wnull-dereference"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 int
@@ -4647,14 +4712,758 @@ main ()
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_prog_cc_g=yes
+  ax_cv_check_cflags___Werror__Wnull_dereference=yes
+else
+  ax_cv_check_cflags___Werror__Wnull_dereference=no
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CFLAGS=$ax_check_save_flags
 fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__Wnull_dereference" >&5
+$as_echo "$ax_cv_check_cflags___Werror__Wnull_dereference" >&6; }
+if test "x$ax_cv_check_cflags___Werror__Wnull_dereference" = xyes; then :
+  C_WFLAGS="$C_WFLAGS -Wnull-dereference" CXX_WFLAGS="$CXX_WFLAGS -Wnull-dereference"
+else
+  :
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -Wduplicated-cond" >&5
+$as_echo_n "checking whether C compiler accepts -Werror -Wduplicated-cond... " >&6; }
+if ${ax_cv_check_cflags___Werror__Wduplicated_cond+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+  ax_check_save_flags=$CFLAGS
+  CFLAGS="$CFLAGS  -Werror -Wduplicated-cond"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ax_cv_check_cflags___Werror__Wduplicated_cond=yes
+else
+  ax_cv_check_cflags___Werror__Wduplicated_cond=no
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-   ac_c_werror_flag=$ac_save_c_werror_flag
+  CFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__Wduplicated_cond" >&5
+$as_echo "$ax_cv_check_cflags___Werror__Wduplicated_cond" >&6; }
+if test "x$ax_cv_check_cflags___Werror__Wduplicated_cond" = xyes; then :
+  C_WFLAGS="$C_WFLAGS -Wduplicated-cond" CXX_WFLAGS="$CXX_WFLAGS -Wduplicated-cond"
+else
+  :
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -Wno-sign-compare" >&5
+$as_echo_n "checking whether C compiler accepts -Werror -Wno-sign-compare... " >&6; }
+if ${ax_cv_check_cflags___Werror__Wno_sign_compare+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+  ax_check_save_flags=$CFLAGS
+  CFLAGS="$CFLAGS  -Werror -Wno-sign-compare"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ax_cv_check_cflags___Werror__Wno_sign_compare=yes
+else
+  ax_cv_check_cflags___Werror__Wno_sign_compare=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__Wno_sign_compare" >&5
+$as_echo "$ax_cv_check_cflags___Werror__Wno_sign_compare" >&6; }
+if test "x$ax_cv_check_cflags___Werror__Wno_sign_compare" = xyes; then :
+  NO_SIGN_COMPARE="-Wno-sign-compare"
+else
+  :
+fi
+
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler accepts -Werror -Wunused-private-field" >&5
+$as_echo_n "checking whether C++ compiler accepts -Werror -Wunused-private-field... " >&6; }
+if ${ax_cv_check_cxxflags___Werror__Wunused_private_field+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+  ax_check_save_flags=$CXXFLAGS
+  CXXFLAGS="$CXXFLAGS  -Werror -Wunused-private-field"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ax_cv_check_cxxflags___Werror__Wunused_private_field=yes
+else
+  ax_cv_check_cxxflags___Werror__Wunused_private_field=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CXXFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cxxflags___Werror__Wunused_private_field" >&5
+$as_echo "$ax_cv_check_cxxflags___Werror__Wunused_private_field" >&6; }
+if test "x$ax_cv_check_cxxflags___Werror__Wunused_private_field" = xyes; then :
+  CXX_WFLAGS="$CXX_WFLAGS -Wunused-private-field"
+else
+  :
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler accepts -Werror -Wmissing-prototypes" >&5
+$as_echo_n "checking whether C++ compiler accepts -Werror -Wmissing-prototypes... " >&6; }
+if ${ax_cv_check_cxxflags___Werror__Wmissing_prototypes+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+  ax_check_save_flags=$CXXFLAGS
+  CXXFLAGS="$CXXFLAGS  -Werror -Wmissing-prototypes"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ax_cv_check_cxxflags___Werror__Wmissing_prototypes=yes
+else
+  ax_cv_check_cxxflags___Werror__Wmissing_prototypes=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CXXFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cxxflags___Werror__Wmissing_prototypes" >&5
+$as_echo "$ax_cv_check_cxxflags___Werror__Wmissing_prototypes" >&6; }
+if test "x$ax_cv_check_cxxflags___Werror__Wmissing_prototypes" = xyes; then :
+  CXX_WFLAGS="$CXX_WFLAGS -Wmissing-prototypes"
+else
+  :
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler accepts -Werror -Wmissing-declarations" >&5
+$as_echo_n "checking whether C++ compiler accepts -Werror -Wmissing-declarations... " >&6; }
+if ${ax_cv_check_cxxflags___Werror__Wmissing_declarations+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+  ax_check_save_flags=$CXXFLAGS
+  CXXFLAGS="$CXXFLAGS  -Werror -Wmissing-declarations"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ax_cv_check_cxxflags___Werror__Wmissing_declarations=yes
+else
+  ax_cv_check_cxxflags___Werror__Wmissing_declarations=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CXXFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cxxflags___Werror__Wmissing_declarations" >&5
+$as_echo "$ax_cv_check_cxxflags___Werror__Wmissing_declarations" >&6; }
+if test "x$ax_cv_check_cxxflags___Werror__Wmissing_declarations" = xyes; then :
+  CXX_WFLAGS="$CXX_WFLAGS -Wmissing-declarations"
+else
+  :
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler accepts -Werror -Wnon-virtual-dtor" >&5
+$as_echo_n "checking whether C++ compiler accepts -Werror -Wnon-virtual-dtor... " >&6; }
+if ${ax_cv_check_cxxflags___Werror__Wnon_virtual_dtor+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+  ax_check_save_flags=$CXXFLAGS
+  CXXFLAGS="$CXXFLAGS  -Werror -Wnon-virtual-dtor"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ax_cv_check_cxxflags___Werror__Wnon_virtual_dtor=yes
+else
+  ax_cv_check_cxxflags___Werror__Wnon_virtual_dtor=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CXXFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cxxflags___Werror__Wnon_virtual_dtor" >&5
+$as_echo "$ax_cv_check_cxxflags___Werror__Wnon_virtual_dtor" >&6; }
+if test "x$ax_cv_check_cxxflags___Werror__Wnon_virtual_dtor" = xyes; then :
+  CXX_WFLAGS="$CXX_WFLAGS -Wnon-virtual-dtor" NO_NON_VIRTUAL_DTOR_FLAG="-Wno-non-virtual-dtor"
+else
+  :
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler accepts -Werror -Woverloaded-virtual" >&5
+$as_echo_n "checking whether C++ compiler accepts -Werror -Woverloaded-virtual... " >&6; }
+if ${ax_cv_check_cxxflags___Werror__Woverloaded_virtual+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+  ax_check_save_flags=$CXXFLAGS
+  CXXFLAGS="$CXXFLAGS  -Werror -Woverloaded-virtual"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ax_cv_check_cxxflags___Werror__Woverloaded_virtual=yes
+else
+  ax_cv_check_cxxflags___Werror__Woverloaded_virtual=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CXXFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cxxflags___Werror__Woverloaded_virtual" >&5
+$as_echo "$ax_cv_check_cxxflags___Werror__Woverloaded_virtual" >&6; }
+if test "x$ax_cv_check_cxxflags___Werror__Woverloaded_virtual" = xyes; then :
+  CXX_WFLAGS="$CXX_WFLAGS -Woverloaded-virtual"
+else
+  :
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler accepts -Werror -fno-operator-names" >&5
+$as_echo_n "checking whether C++ compiler accepts -Werror -fno-operator-names... " >&6; }
+if ${ax_cv_check_cxxflags___Werror__fno_operator_names+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+  ax_check_save_flags=$CXXFLAGS
+  CXXFLAGS="$CXXFLAGS  -Werror -fno-operator-names"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ax_cv_check_cxxflags___Werror__fno_operator_names=yes
+else
+  ax_cv_check_cxxflags___Werror__fno_operator_names=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CXXFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cxxflags___Werror__fno_operator_names" >&5
+$as_echo "$ax_cv_check_cxxflags___Werror__fno_operator_names" >&6; }
+if test "x$ax_cv_check_cxxflags___Werror__fno_operator_names" = xyes; then :
+  CXX_WFLAGS="$CXX_WFLAGS -fno-operator-names"
+else
+  :
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+CXX_WFLAGS=$CXX_WFLAGS
+
+C_WFLAGS=$C_WFLAGS
+
+NO_UNUSED_PARAMETER_FLAG=$NO_UNUSED_PARAMETER_FLAG
+
+NO_SIGN_COMPARE=$NO_SIGN_COMPARE
+
+NO_NON_VIRTUAL_DTOR_FLAG=$NO_NON_VIRTUAL_DTOR_FLAG
+
+NO_LOGICAL_OP_FLAG=$NO_LOGICAL_OP_FLAG
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+else
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
 $as_echo "$ac_cv_prog_cc_g" >&6; }
@@ -6074,10 +6883,10 @@ else
   cygwin* | mingw* | cegcc*)
     # On Win9x/ME, this test blows up -- it succeeds, but takes
     # about 5 minutes as the teststring grows exponentially.
-    # Worse, since 9x/ME are not pre-emptively multitasking,
+    # Worse, since 9x/ME are not preemptively multitasking,
     # you end up with a "frozen" computer, even though with patience
     # the test eventually succeeds (with a max line length of 256k).
-    # Instead, let's just punt: use the minimum linelength reported by
+    # Instead, let's just punt: use the minimum line length reported by
     # all of the supported platforms: 8192 (on NT/2K/XP).
     lt_cv_sys_max_cmd_len=8192;
     ;;
@@ -9956,7 +10765,7 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie
 
   case $host_os in
   cygwin* | mingw* | pw32* | cegcc*)
-    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # FIXME: the MSVC++ port hasn't been tested in a long time
     # When not using gcc, we currently assume that we are using
     # Microsoft Visual C++.
     if test "$GCC" != yes; then
@@ -12527,7 +13336,7 @@ else
 #  endif
 #endif
 
-/* When -fvisbility=hidden is used, assume the code has been annotated
+/* When -fvisibility=hidden is used, assume the code has been annotated
    correspondingly for the symbols needed.  */
 #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
 int fnord () __attribute__((visibility("default")));
@@ -12633,7 +13442,7 @@ else
 #  endif
 #endif
 
-/* When -fvisbility=hidden is used, assume the code has been annotated
+/* When -fvisibility=hidden is used, assume the code has been annotated
    correspondingly for the symbols needed.  */
 #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
 int fnord () __attribute__((visibility("default")));
@@ -16020,6 +16829,42 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifndef __cplusplus
+    #error "broken C++"
+    #endif
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+else
+  CXX=;
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+if test "x$CXX" == x ; then
+  as_fn_error $? "\"You don't have a working C++ compiler.\"" "$LINENO" 5
+fi
+
 
 # Check whether --with-libtool was given.
 if test "${with_libtool+set}" = set; then :
@@ -17263,6 +18108,28 @@ _ACEOF
 fi
 done
 
+for ac_func in mmap
+do :
+  ac_fn_c_check_func "$LINENO" "mmap" "ac_cv_func_mmap"
+if test "x$ac_cv_func_mmap" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_MMAP 1
+_ACEOF
+
+fi
+done
+
+for ac_func in statvfs
+do :
+  ac_fn_c_check_func "$LINENO" "statvfs" "ac_cv_func_statvfs"
+if test "x$ac_cv_func_statvfs" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_STATVFS 1
+_ACEOF
+
+fi
+done
+
 
 
 ac_ext=cpp
@@ -17326,34 +18193,75 @@ int
 main ()
 {
 
-  ;
-  return 0;
-}
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+  ac_cv_func_localtime_r=yes
+else
+  ac_cv_func_localtime_r=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_localtime_r" >&5
+$as_echo "$ac_cv_func_localtime_r" >&6; }
+if test $ac_cv_func_localtime_r = yes; then :
+
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_fn_c_check_func "$LINENO" "setlocale" "ac_cv_func_setlocale"
+if test "x$ac_cv_func_setlocale" = xyes; then :
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uselocale" >&5
+$as_echo_n "checking for uselocale... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#define _XOPEN_SOURCE 700
+#include <locale.h>
+
+int
+main ()
+{
+
+    locale_t alocale = newlocale (LC_NUMERIC_MASK, "C", 0);
+    locale_t oldlocale = uselocale(alocale);
+    uselocale(oldlocale);
+    freelocale(alocale);
+    return 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_USELOCALE 1
 _ACEOF
-if ac_fn_cxx_try_link "$LINENO"; then :
-  ac_cv_func_localtime_r=yes
-else
-  ac_cv_func_localtime_r=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_localtime_r" >&5
-$as_echo "$ac_cv_func_localtime_r" >&6; }
-if test $ac_cv_func_localtime_r = yes; then :
 
-fi
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
+else
 
-ac_fn_c_check_func "$LINENO" "setlocale" "ac_cv_func_setlocale"
-if test "x$ac_cv_func_setlocale" = xyes; then :
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 
 fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
 
 OPT_GDAL_FORMATS=
@@ -17371,6 +18279,9 @@ else
 fi
 
 
+CFLAGS_NOFTRAPV="$CFLAGS"
+CXXFLAGS_NOFTRAPV="$CXXFLAGS"
+
 if test "x$enable_debug" = "xyes" ; then
 
 
@@ -17387,20 +18298,45 @@ if test "x$enable_debug" = "xyes" ; then
   CXXFLAGS="$CXXFLAGS -g -DDEBUG"
   CFLAGS="$CFLAGS -g -DDEBUG"
 
+  CFLAGS_NOFTRAPV="$CFLAGS"
+  CXXFLAGS_NOFTRAPV="$CXXFLAGS"
+
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, modified CFLAGS=\"$CFLAGS\"" >&5
 $as_echo "yes, modified CFLAGS=\"$CFLAGS\"" >&6; }
+
+  # Some clang version on 32 bits have linking error with 64bit operations (undefined reference to `__mulodi4')
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -ftrapv can be used" >&5
+$as_echo_n "checking whether -ftrapv can be used... " >&6; }
+  rm -f testftrapv.c
+  echo 'int main(int argc, char** argv) { return (long long)argc * argc; } ' > testftrapv.c
+  if test -z "`${CC} ${CFLAGS} -ftrapv testftrapv.c -o testftrapv 2>&1`" ; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+    CFLAGS="$CFLAGS -ftrapv"
+    CXXFLAGS="$CXXFLAGS -ftrapv"
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+  fi
+  rm -f testftrapv.* testftrapv
+
 else
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, CFLAGS=\"$CFLAGS\"" >&5
 $as_echo "no, CFLAGS=\"$CFLAGS\"" >&6; }
 fi
 
+CFLAGS_NOFTRAPV=$CFLAGS_NOFTRAPV
+
+CXXFLAGS_NOFTRAPV=$CXXFLAGS_NOFTRAPV
+
+
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GCC 4.1 atomic builtins are available" >&5
 $as_echo_n "checking whether GCC 4.1 atomic builtins are available... " >&6; }
 
 rm -f atomicbuiltins.c
-echo 'int main(int argc, char* argv) { int i; __sync_add_and_fetch(&i, 1); __sync_sub_and_fetch(&i, 1); return 0; } ' > atomicbuiltins.c
-if test -z "`${CC} atomicbuiltins.c -o atomicbuiltins 2>&1`" ; then
+echo 'int main(int argc, char** argv) { int i; __sync_add_and_fetch(&i, 1); __sync_sub_and_fetch(&i, 1); __sync_bool_compare_and_swap(&i, 0, 1); return 0; } ' > atomicbuiltins.c
+if test -z "`${CC} ${CFLAGS} atomicbuiltins.c -o atomicbuiltins 2>&1`" ; then
     HAVE_GCC_ATOMIC_BUILTINS=yes
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
@@ -17509,7 +18445,12 @@ if test "$with_avx" = "yes" -o "$with_avx" = ""; then
     rm -f detectavx.cpp
     echo '#ifdef __AVX__' > detectavx.cpp
     echo '#include <immintrin.h>' >> detectavx.cpp
-    echo 'void foo() { unsigned int nXCRLow, nXCRHigh; __asm__ ("xgetbv" : "=a" (nXCRLow), "=d" (nXCRHigh) : "c" (0)); float fEpsilon = 0.0000000000001f; __m256 ymm_small = _mm256_set_ps(fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon); } int main() { return 0; }' >> detectavx.cpp
+    echo 'int foo() { unsigned int nXCRLow, nXCRHigh;' >> detectavx.cpp
+    echo '__asm__ ("xgetbv" : "=a" (nXCRLow), "=d" (nXCRHigh) : "c" (0));' >> detectavx.cpp
+    echo 'float fEpsilon = 0.0000000000001f;' >> detectavx.cpp
+    echo '__m256 ymm_small = _mm256_set_ps(fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon);' >> detectavx.cpp
+    echo 'return (int)nXCRLow + _mm256_movemask_ps(ymm_small); }' >> detectavx.cpp
+    echo 'int main(int argc, char**) { if( argc == 0 ) return foo(); return 0; }' >> detectavx.cpp
     echo '#else' >> detectavx.cpp
     echo 'some_error' >> detectavx.cpp
     echo '#endif' >> detectavx.cpp
@@ -17568,6 +18509,49 @@ HAVE_AVX_AT_COMPILE_TIME=$HAVE_AVX_AT_COMPILE_TIME
 
 
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking to enable LTO (link time optimization) build" >&5
+$as_echo_n "checking to enable LTO (link time optimization) build... " >&6; }
+
+# Check whether --enable-lto was given.
+if test "${enable_lto+set}" = set; then :
+  enableval=$enable_lto;
+fi
+
+
+CFLAGS_NO_LTO_IF_AVX_NONDEFAULT="$CFLAGS"
+CXXFLAGS_NO_LTO_IF_AVX_NONDEFAULT="$CXXFLAGS"
+
+if test "x$enable_lto" = "xyes" ; then
+
+
+  CXXFLAGS=`echo "$CXXFLAGS" | sed "s/-g //"`
+  CFLAGS=`echo "$CFLAGS" | sed "s/-g //"`
+
+
+  CXXFLAGS="$CXXFLAGS -flto"
+  CFLAGS="$CFLAGS -flto"
+  LDFLAGS="$LDFLAGS -flto"
+
+      if test "$HAVE_AVX_AT_COMPILE_TIME" = "yes"; then
+    if test "$AVXFLAGS" = ""; then
+        CFLAGS_NO_LTO_IF_AVX_NONDEFAULT="$CFLAGS"
+        CXXFLAGS_NO_LTO_IF_AVX_NONDEFAULT="$CXXFLAGS"
+    fi
+  fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+CFLAGS_NO_LTO_IF_AVX_NONDEFAULT=$CFLAGS_NO_LTO_IF_AVX_NONDEFAULT
+
+CXXFLAGS_NO_LTO_IF_AVX_NONDEFAULT=$CXXFLAGS_NO_LTO_IF_AVX_NONDEFAULT
+
+
+
 echo "#include <winsock2.h>" > test_ws2_32.c
 echo "#include <ws2tcpip.h>" >> test_ws2_32.c
 echo "void foo() {}" >> test_ws2_32.c
@@ -20184,11 +21168,11 @@ $as_echo_n "checking for PCIDSK... " >&6; }
 PCIDSK_LIB=
 PCIDSK_INCLUDE=
 
-if test "$with_pcidsk" = "old" -o "$with_pcidsk" = "no" ; then
+if test "$with_pcidsk" = "no" ; then
 
-  PCIDSK_SETTING=old
+  PCIDSK_SETTING=no
 
-  echo "pcidsk support using pre-PCIDSK SDK (old) implementation."
+  echo "pcidsk support disabled."
 
 elif test "$with_pcidsk" = "" -o "$with_pcidsk" = "yes" -o "$with_pcidsk" = "internal" ; then
 
@@ -20206,13 +21190,17 @@ else
 
 fi
 
-PCIDSK_SETTING=$PCIDSK_SETTING
+if test "$with_pcidsk" != "no" ; then
+
+  PCIDSK_SETTING=$PCIDSK_SETTING
 
-PCIDSK_LIB=$PCIDSK_LIB
+  PCIDSK_LIB=$PCIDSK_LIB
 
-PCIDSK_INCLUDE=$PCIDSK_INCLUDE
+  PCIDSK_INCLUDE=$PCIDSK_INCLUDE
 
 
+fi
+
 
 
 # Check whether --with-libtiff was given.
@@ -21287,6 +22275,95 @@ SOSI_INC=$SOSI_INC
 
 
 
+
+# Check whether --with-mongocxx was given.
+if test "${with_mongocxx+set}" = set; then :
+  withval=$with_mongocxx;
+fi
+
+
+MONGODB_ENABLED=no
+
+if test "$with_mongocxx" = "no" ; then
+
+  echo "MONGODB support disabled."
+
+elif test "$with_mongocxx" = "yes" -o "$with_mongocxx" = "" ; then
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MongoCXX" >&5
+$as_echo_n "checking for MongoCXX... " >&6; }
+
+    rm -f testmongocxx.*
+    rm -f testmongocxx
+    echo "#include <mongo/client/dbclient.h>" > testmongocxx.cpp
+    echo "using namespace mongo;" >> testmongocxx.cpp
+    echo "int main() { client::initialize(client::Options()); return 0; }" >> testmongocxx.cpp
+    if test -z "`${CXX} ${CPPFLAGS} testmongocxx.cpp -lmongoclient -lboost_system -lboost_thread -lboost_regex -o testmongocxx 2>&1`" ; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: MongoCXX found" >&5
+$as_echo "MongoCXX found" >&6; }
+        MONGODB_ENABLED="yes"
+        MONGODB_LIB=" -lmongoclient -lboost_system -lboost_thread -lboost_regex"
+    else
+        if test "$with_mongocxx" = "yes"; then
+            as_fn_error $? "MongoCXX not found." "$LINENO" 5
+        else
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: MongoCXX not found." >&5
+$as_echo "MongoCXX not found." >&6; }
+        fi
+    fi
+    rm -f testmongocxx.*
+    rm -f testmongocxx
+
+else
+
+
+# Check whether --with-boost-lib-path was given.
+if test "${with_boost_lib_path+set}" = set; then :
+  withval=$with_boost_lib_path;
+fi
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libmongoclient.so in in $with_mongocxx/lib" >&5
+$as_echo_n "checking for libmongoclient.so in in $with_mongocxx/lib... " >&6; }
+  MONGODB_ENABLED=yes
+  if test -r $with_mongocxx/lib/libmongoclient.so; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: found." >&5
+$as_echo "found." >&6; }
+    MONGODB_LIB="-L$with_mongocxx/lib -lmongoclient"
+  elif test -r $with_mongocxx/lib/libmongoclient.dylib; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: found." >&5
+$as_echo "found." >&6; }
+    MONGODB_LIB="-L$with_mongocxx/lib -lmongoclient"
+  else
+    as_fn_error $? "not found." "$LINENO" 5
+  fi
+
+  if test "$with_boost_lib_path" = "" ; then
+    MONGODB_LIB="$MONGODB_LIB -lboost_system -lboost_thread -lboost_regex"
+  else
+    MONGODB_LIB="$MONGODB_LIB -L$with_boost_lib_path -lboost_system -lboost_thread -lboost_regex"
+  fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mongo/client/dbclient.h in $with_mongocxx/include" >&5
+$as_echo_n "checking for mongo/client/dbclient.h in $with_mongocxx/include... " >&6; }
+  if test -r $with_mongocxx/include/mongo/client/dbclient.h ; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: found." >&5
+$as_echo "found." >&6; }
+    MONGODB_INC="-I$with_mongocxx/include"
+  else
+    as_fn_error $? "not found." "$LINENO" 5
+  fi
+
+fi
+
+MONGODB_ENABLED=$MONGODB_ENABLED
+
+MONGODB_LIB=$MONGODB_LIB
+
+MONGODB_INC=$MONGODB_INC
+
+
+
 HDF4_INCLUDE=""
 
 
@@ -23696,21 +24773,29 @@ OPT_GDAL_FORMATS=$OPT_GDAL_FORMATS
 
 
 
+OGR_ENABLED=yes
+
+
+GNM_ENABLED=no
 
-# Check whether --with-ogr was given.
-if test "${with_ogr+set}" = set; then :
-  withval=$with_ogr;
+
+# Check whether --with-gnm was given.
+if test "${with_gnm+set}" = set; then :
+  withval=$with_gnm;
 fi
 
 
-if test "$with_ogr" = yes -o x"$with_ogr" = x ; then
-  echo checking for OGR ... enabled
-  OGR_ENABLED=yes
+if test "$with_gnm" = "" ; then
+  GNM_ENABLED=no
+  echo "GNM support disabled."
+elif test "$with_gnm" = "yes"; then
+  echo checking for GNM ... enabled
+  GNM_ENABLED=yes
 else
-  echo checking for OGR ... disabled by user
-  OGR_ENABLED=no
+  echo checking for GNM ... disabled by user
+  GNM_ENABLED=no
 fi
-OGR_ENABLED=$OGR_ENABLED
+GNM_ENABLED=$GNM_ENABLED
 
 
 
@@ -25025,27 +26110,228 @@ if test "$HAVE_LIBKML" = "yes"; then
     LIBS="$LIBKML_LDFLAGS $LIBS"
 fi
 
-HAVE_LIBKML=$HAVE_LIBKML
-
-LIBKML_INCLUDE=$LIBKML_CFLAGS
-
+HAVE_LIBKML=$HAVE_LIBKML
+
+LIBKML_INCLUDE=$LIBKML_CFLAGS
+
+
+
+
+# Check whether --with-odbc was given.
+if test "${with_odbc+set}" = set; then :
+  withval=$with_odbc;
+fi
+
+
+if test "$with_odbc" = "no" ; then
+
+  ODBC_SETTING=no
+
+  echo "ODBC support disabled."
+
+elif test "$with_odbc" = "yes" -o "$with_odbc" = "" ; then
+  ODBC_SETTING=no
+
+  echo "check for unixODBC"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SQLConnect in -lodbc" >&5
+$as_echo_n "checking for SQLConnect in -lodbc... " >&6; }
+if ${ac_cv_lib_odbc_SQLConnect+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lodbc  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char SQLConnect ();
+int
+main ()
+{
+return SQLConnect ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_odbc_SQLConnect=yes
+else
+  ac_cv_lib_odbc_SQLConnect=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_odbc_SQLConnect" >&5
+$as_echo "$ac_cv_lib_odbc_SQLConnect" >&6; }
+if test "x$ac_cv_lib_odbc_SQLConnect" = xyes; then :
+  ODBC_LIBS="-lodbc -lodbcinst"
+fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SQLInstallDriverEx in -lodbcinst" >&5
+$as_echo_n "checking for SQLInstallDriverEx in -lodbcinst... " >&6; }
+if ${ac_cv_lib_odbcinst_SQLInstallDriverEx+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lodbcinst  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char SQLInstallDriverEx ();
+int
+main ()
+{
+return SQLInstallDriverEx ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_odbcinst_SQLInstallDriverEx=yes
+else
+  ac_cv_lib_odbcinst_SQLInstallDriverEx=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_odbcinst_SQLInstallDriverEx" >&5
+$as_echo "$ac_cv_lib_odbcinst_SQLInstallDriverEx" >&6; }
+if test "x$ac_cv_lib_odbcinst_SQLInstallDriverEx" = xyes; then :
+  ODBC_SETTING=yes
+fi
+
+
+  if test "$ODBC_SETTING" = "no" ; then
+    echo "check for windows ODBC"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lodbc32" >&5
+$as_echo_n "checking for main in -lodbc32... " >&6; }
+if ${ac_cv_lib_odbc32_main+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lodbc32  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_odbc32_main=yes
+else
+  ac_cv_lib_odbc32_main=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_odbc32_main" >&5
+$as_echo "$ac_cv_lib_odbc32_main" >&6; }
+if test "x$ac_cv_lib_odbc32_main" = xyes; then :
+  ODBC_LIBS="-lodbc32 -lodbccp32"
+fi
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SQLInstallDriverEx in -lodbccp32" >&5
+$as_echo_n "checking for SQLInstallDriverEx in -lodbccp32... " >&6; }
+if ${ac_cv_lib_odbccp32_SQLInstallDriverEx+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lodbccp32  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char SQLInstallDriverEx ();
+int
+main ()
+{
+return SQLInstallDriverEx ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_odbccp32_SQLInstallDriverEx=yes
+else
+  ac_cv_lib_odbccp32_SQLInstallDriverEx=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_odbccp32_SQLInstallDriverEx" >&5
+$as_echo "$ac_cv_lib_odbccp32_SQLInstallDriverEx" >&6; }
+if test "x$ac_cv_lib_odbccp32_SQLInstallDriverEx" = xyes; then :
+  ODBC_SETTING=yes
+fi
+
+  fi
 
+  if test "$ODBC_SETTING" = "yes" ; then
+    for ac_header in sql.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "sql.h" "ac_cv_header_sql_h" "#ifdef _WIN32
+# include <windows.h>
+#endif
 
+"
+if test "x$ac_cv_header_sql_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SQL_H 1
+_ACEOF
 
-# Check whether --with-odbc was given.
-if test "${with_odbc+set}" = set; then :
-  withval=$with_odbc;
+else
+  ODBC_SETTING=no
 fi
 
+done
 
-if test "$with_odbc" = "no" ; then
-
-  ODBC_SETTING=no
+    if test "$ODBC_SETTING" = "no" ; then
+      if test -f /usr/local/include/sql.h ; then
+        ODBC_SETTING=yes
+        echo "using sql.h from /usr/local/include"
+      elif test -f /usr/include/sql.h ; then
+        ODBC_SETTING=yes
+        echo "using sql.h from /usr/include"
+      else
+        echo "sql.h not found"
+      fi
+    fi
+  fi
 
-  echo "ODBC support disabled."
+  if test "$ODBC_SETTING" = "yes"  ; then
+    LIBS="$ODBC_LIBS $LIBS"
+  fi
 
-elif test "$with_odbc" = "yes" -o "$with_odbc" = "" ; then
+else
 
+  ODBC_SETTING=yes
+  ODBC_LIBS=""
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SQLConnect in -lodbc" >&5
 $as_echo_n "checking for SQLConnect in -lodbc... " >&6; }
 if ${ac_cv_lib_odbc_SQLConnect+:} false; then :
@@ -25083,71 +26369,47 @@ fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_odbc_SQLConnect" >&5
 $as_echo "$ac_cv_lib_odbc_SQLConnect" >&6; }
 if test "x$ac_cv_lib_odbc_SQLConnect" = xyes; then :
-  ODBC_SETTING=yes
-else
-  ODBC_SETTING=no
+  ODBC_LIBS="-lodbc -lodbcinst"
 fi
 
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SQLInstallDriverEx in -lodbcinst" >&5
-$as_echo_n "checking for SQLInstallDriverEx in -lodbcinst... " >&6; }
-if ${ac_cv_lib_odbcinst_SQLInstallDriverEx+:} false; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lodbc32" >&5
+$as_echo_n "checking for main in -lodbc32... " >&6; }
+if ${ac_cv_lib_odbc32_main+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-lodbcinst  $LIBS"
+LIBS="-lodbc32  $LIBS"
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char SQLInstallDriverEx ();
+
 int
 main ()
 {
-return SQLInstallDriverEx ();
+return main ();
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_odbcinst_SQLInstallDriverEx=yes
+  ac_cv_lib_odbc32_main=yes
 else
-  ac_cv_lib_odbcinst_SQLInstallDriverEx=no
+  ac_cv_lib_odbc32_main=no
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_odbcinst_SQLInstallDriverEx" >&5
-$as_echo "$ac_cv_lib_odbcinst_SQLInstallDriverEx" >&6; }
-if test "x$ac_cv_lib_odbcinst_SQLInstallDriverEx" = xyes; then :
-  ODBC_SETTING=yes
-else
-  ODBC_SETTING=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_odbc32_main" >&5
+$as_echo "$ac_cv_lib_odbc32_main" >&6; }
+if test "x$ac_cv_lib_odbc32_main" = xyes; then :
+  ODBC_LIBS="-lodbc32 -lodbccp32"
 fi
 
-
-  if test "$ODBC_SETTING" = "yes" ; then
-    if test -f /usr/local/include/sql.h -o -f /usr/include/sql.h ; then
-      ODBC_SETTING=yes
-    else
-      echo "odbc library found, but sql.h missing, ODBC support disabled."
-      ODBC_SETTING=no
-    fi
-  fi
-
-  if test "$ODBC_SETTING" = "yes"  ; then
-    LIBS="-lodbc -lodbcinst $LIBS"
+  if test "$ODBC_LIBS" = ""; then
+    as_fn_error $? "Cannot find ODBC libs" "$LINENO" 5
   fi
-
-else
-
-  ODBC_SETTING=yes
-  LIBS="-L$with_odbc -L$with_odbc/lib -lodbc -lodbcinst $LIBS"
+  LIBS="-L$with_odbc -L$with_odbc/lib $ODBC_LIBS $LIBS"
   EXTRA_INCLUDES="-I$with_odbc -I$with_odbc/include $EXTRA_INCLUDES"
 
   echo "using odbc library from $with_odbc."
@@ -25506,8 +26768,8 @@ OCI_INCLUDE=$OCI_INCLUDE
 
 HAVE_DODS=no
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking Checking for DODS" >&5
-$as_echo_n "checking Checking for DODS... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for DODS" >&5
+$as_echo_n "checking for DODS... " >&6; }
 
 # Check whether --with-dods_root was given.
 if test "${with_dods_root+set}" = set; then :
@@ -25646,33 +26908,257 @@ IFS=$as_save_IFS
   ;;
 esac
 fi
-LIBCURL_CONFIG=$ac_cv_path_LIBCURL_CONFIG
-if test -n "$LIBCURL_CONFIG"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBCURL_CONFIG" >&5
-$as_echo "$LIBCURL_CONFIG" >&6; }
+LIBCURL_CONFIG=$ac_cv_path_LIBCURL_CONFIG
+if test -n "$LIBCURL_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBCURL_CONFIG" >&5
+$as_echo "$LIBCURL_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+
+if test "$LIBCURL_CONFIG" != "no" ; then
+
+  CURL_VERNUM=`$LIBCURL_CONFIG --vernum`
+  CURL_VER=`$LIBCURL_CONFIG --version | awk '{print $2}'`
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result:         found libcurl version $CURL_VER" >&5
+$as_echo "        found libcurl version $CURL_VER" >&6; }
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for curl_global_init in -lcurl" >&5
+$as_echo_n "checking for curl_global_init in -lcurl... " >&6; }
+if ${ac_cv_lib_curl_curl_global_init+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcurl `$LIBCURL_CONFIG --libs` $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char curl_global_init ();
+int
+main ()
+{
+return curl_global_init ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_curl_curl_global_init=yes
+else
+  ac_cv_lib_curl_curl_global_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curl_curl_global_init" >&5
+$as_echo "$ac_cv_lib_curl_curl_global_init" >&6; }
+if test "x$ac_cv_lib_curl_curl_global_init" = xyes; then :
+  CURL_SETTING=yes
+else
+  CURL_SETTING=no
+fi
+
+
+fi
+
+if test "$CURL_SETTING" = "yes" ; then
+
+  CURL_INC=`$LIBCURL_CONFIG --cflags`
+  CURL_LIB=`$LIBCURL_CONFIG --libs`
+  OPT_GDAL_FORMATS="wcs wms plmosaic wmts $OPT_GDAL_FORMATS"
+
+fi
+
+CURL_SETTING=$CURL_SETTING
+
+CURL_INC=$CURL_INC
+
+CURL_LIB=$CURL_LIB
+
+
+
+HAVE_LIBXML2=no
+LIBXML2_INC=
+LIBXML2_LIB=
+
+
+# Check whether --with-xml2 was given.
+if test "${with_xml2+set}" = set; then :
+  withval=$with_xml2;
+fi
+
+
+if test "`basename xx/$with_xml2`" = "xml2-config" ; then
+  LIBXML2_CONFIG="$with_xml2"
+elif test "$with_xml2" = "no" ; then
+  LIBXML2_CONFIG=no
+else
+  # Extract the first word of "xml2-config", so it can be a program name with args.
+set dummy xml2-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_LIBXML2_CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $LIBXML2_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_LIBXML2_CONFIG="$LIBXML2_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_LIBXML2_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_LIBXML2_CONFIG" && ac_cv_path_LIBXML2_CONFIG="no"
+  ;;
+esac
+fi
+LIBXML2_CONFIG=$ac_cv_path_LIBXML2_CONFIG
+if test -n "$LIBXML2_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBXML2_CONFIG" >&5
+$as_echo "$LIBXML2_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+
+if test "$LIBXML2_CONFIG" != "no" ; then
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for xmlParseDoc in -lxml2" >&5
+$as_echo_n "checking for xmlParseDoc in -lxml2... " >&6; }
+if ${ac_cv_lib_xml2_xmlParseDoc+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lxml2 `$LIBXML2_CONFIG --libs` $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char xmlParseDoc ();
+int
+main ()
+{
+return xmlParseDoc ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_xml2_xmlParseDoc=yes
+else
+  ac_cv_lib_xml2_xmlParseDoc=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_xml2_xmlParseDoc" >&5
+$as_echo "$ac_cv_lib_xml2_xmlParseDoc" >&6; }
+if test "x$ac_cv_lib_xml2_xmlParseDoc" = xyes; then :
+  HAVE_LIBXML2=yes
 else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+  HAVE_LIBXML2=no
 fi
 
 
 fi
 
-if test "$LIBCURL_CONFIG" != "no" ; then
+if test "$HAVE_LIBXML2" = "yes" ; then
 
-  CURL_VERNUM=`$LIBCURL_CONFIG --vernum`
-  CURL_VER=`$LIBCURL_CONFIG --version | awk '{print $2}'`
+  LIBXML2_INC=`$LIBXML2_CONFIG --cflags`
+  LIBXML2_LIB=`$LIBXML2_CONFIG --libs`
 
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result:         found libcurl version $CURL_VER" >&5
-$as_echo "        found libcurl version $CURL_VER" >&6; }
+fi
 
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for curl_global_init in -lcurl" >&5
-$as_echo_n "checking for curl_global_init in -lcurl... " >&6; }
-if ${ac_cv_lib_curl_curl_global_init+:} false; then :
+HAVE_LIBXML2=$HAVE_LIBXML2
+
+LIBXML2_INC=$LIBXML2_INC
+
+LIBXML2_LIB=$LIBXML2_LIB
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for spatialite" >&5
+$as_echo_n "checking for spatialite... " >&6; }
+
+
+# Check whether --with-spatialite was given.
+if test "${with_spatialite+set}" = set; then :
+  withval=$with_spatialite;
+fi
+
+
+
+# Check whether --with-spatialite-soname was given.
+if test "${with_spatialite_soname+set}" = set; then :
+  withval=$with_spatialite_soname;
+fi
+
+
+HAVE_SPATIALITE=no
+SPATIALITE_AMALGAMATION=no
+
+if test -z "$with_spatialite" -o "$with_spatialite" = "no"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5
+$as_echo "disabled" >&6; }
+elif test "$with_spatialite" = "yes"; then
+    for ac_header in sqlite3.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "sqlite3.h" "ac_cv_header_sqlite3_h" "$ac_includes_default"
+if test "x$ac_cv_header_sqlite3_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SQLITE3_H 1
+_ACEOF
+
+fi
+
+done
+
+    if test "$ac_cv_header_sqlite3_h" = "yes"; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for spatialite.h in /usr/include or /usr/local/include" >&5
+$as_echo_n "checking for spatialite.h in /usr/include or /usr/local/include... " >&6; }
+        if test -f "/usr/include/spatialite.h" -o -f "/usr/local/include/spatialite.h"; then
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5
+$as_echo "found" >&6; }
+            { $as_echo "$as_me:${as_lineno-$LINENO}: checking for spatialite_init in -lspatialite" >&5
+$as_echo_n "checking for spatialite_init in -lspatialite... " >&6; }
+if ${ac_cv_lib_spatialite_spatialite_init+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-lcurl `$LIBCURL_CONFIG --libs` $LIBS"
+LIBS="-lspatialite  $LIBS"
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -25682,119 +27168,173 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 #ifdef __cplusplus
 extern "C"
 #endif
-char curl_global_init ();
+char spatialite_init ();
 int
 main ()
 {
-return curl_global_init ();
+return spatialite_init ();
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_curl_curl_global_init=yes
+  ac_cv_lib_spatialite_spatialite_init=yes
 else
-  ac_cv_lib_curl_curl_global_init=no
+  ac_cv_lib_spatialite_spatialite_init=no
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curl_curl_global_init" >&5
-$as_echo "$ac_cv_lib_curl_curl_global_init" >&6; }
-if test "x$ac_cv_lib_curl_curl_global_init" = xyes; then :
-  CURL_SETTING=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_spatialite_spatialite_init" >&5
+$as_echo "$ac_cv_lib_spatialite_spatialite_init" >&6; }
+if test "x$ac_cv_lib_spatialite_spatialite_init" = xyes; then :
+  SPATIALITE_INIT_FOUND=yes
 else
-  CURL_SETTING=no
-fi
-
-
+  SPATIALITE_INIT_FOUND=no
 fi
 
-if test "$CURL_SETTING" = "yes" ; then
+            if test "$SPATIALITE_INIT_FOUND" = "yes"; then
+                HAVE_SPATIALITE=yes
+                SPATIALITE_LIBS="-lspatialite -lsqlite3"
+                LIBS="$LIBS $SPATIALITE_LIBS"
+                HAVE_SQLITE3=yes
+            fi
+        else
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found : spatialite support disabled" >&5
+$as_echo "not found : spatialite support disabled" >&6; }
+        fi
+    fi
+elif test "$with_spatialite" = "dlopen"; then
+  HAVE_SPATIALITE=dlopen
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: dlopen" >&5
+$as_echo "dlopen" >&6; }
 
-  CURL_INC=`$LIBCURL_CONFIG --cflags`
-  CURL_LIB=`$LIBCURL_CONFIG --libs`
-  OPT_GDAL_FORMATS="wcs wms plmosaic $OPT_GDAL_FORMATS"
+  if test "$with_spatialite_soname" != ""; then
+      SPATIALITE_SONAME="$with_spatialite_soname"
+  else
+      SPATIALITE_SONAME="spatialite.so"
+  fi
+else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for spatialite_init in -lspatialite" >&5
+$as_echo_n "checking for spatialite_init in -lspatialite... " >&6; }
+if ${ac_cv_lib_spatialite_spatialite_init+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lspatialite -L$with_spatialite/lib -lspatialite $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
 
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char spatialite_init ();
+int
+main ()
+{
+return spatialite_init ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_spatialite_spatialite_init=yes
+else
+  ac_cv_lib_spatialite_spatialite_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_spatialite_spatialite_init" >&5
+$as_echo "$ac_cv_lib_spatialite_spatialite_init" >&6; }
+if test "x$ac_cv_lib_spatialite_spatialite_init" = xyes; then :
+  SPATIALITE_INIT_FOUND=yes
+else
+  SPATIALITE_INIT_FOUND=no
 fi
 
-CURL_SETTING=$CURL_SETTING
+    if test -f "$with_spatialite/include/spatialite.h" -a \
+        -f "$with_spatialite/include/spatialite/sqlite3.h" -a \
+        "$SPATIALITE_INIT_FOUND" = "yes"; then
 
-CURL_INC=$CURL_INC
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled" >&5
+$as_echo "enabled" >&6; }
+        HAVE_SPATIALITE=yes
+        SPATIALITE_AMALGAMATION=yes
 
-CURL_LIB=$CURL_LIB
+        # SpatiaLite amalgamation availability implies SQLite availability
+        # Caution : don't include the include/spatialite subdir in the include dir
+        # as there's a spatialite.h file in it, which we don't want to include.
+        # We want to include include/spatialite.h instead !
+        SQLITE3_CFLAGS="-I$with_spatialite/include"
+        SPATIALITE_LIBS="-L$with_spatialite/lib -lspatialite"
+        LIBS="$LIBS $SPATIALITE_LIBS"
+        HAVE_SQLITE3=yes
 
+    elif test -f "$with_spatialite/include/spatialite.h" -a \
+        "$SPATIALITE_INIT_FOUND" = "yes"; then
 
+        SQLITE3_REQ_VERSION="3.0.0"
 
-HAVE_LIBXML2=no
-LIBXML2_INC=
-LIBXML2_LIB=
 
+# Check whether --with-sqlite3 was given.
+if test "${with_sqlite3+set}" = set; then :
+  withval=$with_sqlite3;
+        if test "$withval" = "no"; then
+            WANT_SQLITE3="no"
+        elif test "$withval" = "yes"; then
+            WANT_SQLITE3="yes"
+            ac_sqlite3_path=""
+        else
+            WANT_SQLITE3="yes"
+            ac_sqlite3_path="$withval"
+        fi
+
+else
+  WANT_SQLITE3="yes"
 
-# Check whether --with-xml2 was given.
-if test "${with_xml2+set}" = set; then :
-  withval=$with_xml2;
 fi
 
 
-if test "`basename xx/$with_xml2`" = "xml2-config" ; then
-  LIBXML2_CONFIG="$with_xml2"
-elif test "$with_xml2" = "no" ; then
-  LIBXML2_CONFIG=no
-else
-  # Extract the first word of "xml2-config", so it can be a program name with args.
-set dummy xml2-config; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_LIBXML2_CONFIG+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  case $LIBXML2_CONFIG in
-  [\\/]* | ?:[\\/]*)
-  ac_cv_path_LIBXML2_CONFIG="$LIBXML2_CONFIG" # Let the user override the test with a path.
-  ;;
-  *)
-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_path_LIBXML2_CONFIG="$as_dir/$ac_word$ac_exec_ext"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
+    SQLITE3_CFLAGS=""
+    SQLITE3_LDFLAGS=""
+    SQLITE3_VERSION=""
+    HAVE_SQLITE3="no"
 
-  test -z "$ac_cv_path_LIBXML2_CONFIG" && ac_cv_path_LIBXML2_CONFIG="no"
-  ;;
-esac
-fi
-LIBXML2_CONFIG=$ac_cv_path_LIBXML2_CONFIG
-if test -n "$LIBXML2_CONFIG"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBXML2_CONFIG" >&5
-$as_echo "$LIBXML2_CONFIG" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
+    sqlite3_version_req=$SQLITE3_REQ_VERSION
+    sqlite3_version_req_shorten=`expr $sqlite3_version_req : '\([0-9]*\.[0-9]*\)'`
+    sqlite3_version_req_major=`expr $sqlite3_version_req : '\([0-9]*\)'`
+    sqlite3_version_req_minor=`expr $sqlite3_version_req : '[0-9]*\.\([0-9]*\)'`
+    sqlite3_version_req_micro=`expr $sqlite3_version_req : '[0-9]*\.[0-9]*\.\([0-9]*\)'`
+    if test "x$sqlite3_version_req_micro" = "x" ; then
+        sqlite3_version_req_micro="0"
+    fi
 
+    sqlite3_version_req_number=`expr $sqlite3_version_req_major \* 1000000 \
+                               \+ $sqlite3_version_req_minor \* 1000 \
+                               \+ $sqlite3_version_req_micro`
 
-fi
+    if test "x$WANT_SQLITE3" = "xyes"; then
+        ac_sqlite3_header="sqlite3.h"
+        LIB_SQLITE3_FOUND=no
 
-if test "$LIBXML2_CONFIG" != "no" ; then
+        if test "$ac_sqlite3_path" != ""; then
 
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for xmlParseDoc in -lxml2" >&5
-$as_echo_n "checking for xmlParseDoc in -lxml2... " >&6; }
-if ${ac_cv_lib_xml2_xmlParseDoc+:} false; then :
+            unset ac_cv_lib_sqlite3_sqlite3_open
+            saved_LIBS="$LIBS"
+            LIBS=""
+            { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sqlite3_open in -lsqlite3" >&5
+$as_echo_n "checking for sqlite3_open in -lsqlite3... " >&6; }
+if ${ac_cv_lib_sqlite3_sqlite3_open+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-lxml2 `$LIBXML2_CONFIG --libs` $LIBS"
+LIBS="-lsqlite3 -L$ac_sqlite3_path/lib $LIBS"
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -25804,89 +27344,54 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 #ifdef __cplusplus
 extern "C"
 #endif
-char xmlParseDoc ();
+char sqlite3_open ();
 int
 main ()
 {
-return xmlParseDoc ();
+return sqlite3_open ();
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_xml2_xmlParseDoc=yes
+  ac_cv_lib_sqlite3_sqlite3_open=yes
 else
-  ac_cv_lib_xml2_xmlParseDoc=no
+  ac_cv_lib_sqlite3_sqlite3_open=no
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_xml2_xmlParseDoc" >&5
-$as_echo "$ac_cv_lib_xml2_xmlParseDoc" >&6; }
-if test "x$ac_cv_lib_xml2_xmlParseDoc" = xyes; then :
-  HAVE_LIBXML2=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sqlite3_sqlite3_open" >&5
+$as_echo "$ac_cv_lib_sqlite3_sqlite3_open" >&6; }
+if test "x$ac_cv_lib_sqlite3_sqlite3_open" = xyes; then :
+  LIB_SQLITE3_FOUND=yes
 else
-  HAVE_LIBXML2=no
-fi
-
-
-fi
-
-if test "$HAVE_LIBXML2" = "yes" ; then
-
-  LIBXML2_INC=`$LIBXML2_CONFIG --cflags`
-  LIBXML2_LIB=`$LIBXML2_CONFIG --libs`
-
-fi
-
-HAVE_LIBXML2=$HAVE_LIBXML2
-
-LIBXML2_INC=$LIBXML2_INC
-
-LIBXML2_LIB=$LIBXML2_LIB
-
-
-
-
-# Check whether --with-spatialite was given.
-if test "${with_spatialite+set}" = set; then :
-  withval=$with_spatialite;
+  LIB_SQLITE3_FOUND=no
 fi
 
+            LIBS="$saved_LIBS"
+            if test "$LIB_SQLITE3_FOUND" = "yes"; then
+                ac_sqlite3_ldflags="-L$ac_sqlite3_path/lib"
+            fi
 
-HAVE_SPATIALITE=no
-SPATIALITE_AMALGAMATION=no
-
-if test -z "$with_spatialite" -o "$with_spatialite" = "no"; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5
-$as_echo "disabled" >&6; }
-elif test "$with_spatialite" = "yes"; then
-    for ac_header in sqlite3.h
-do :
-  ac_fn_c_check_header_mongrel "$LINENO" "sqlite3.h" "ac_cv_header_sqlite3_h" "$ac_includes_default"
-if test "x$ac_cv_header_sqlite3_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_SQLITE3_H 1
-_ACEOF
-
-fi
-
-done
+            ac_sqlite3_cppflags="-I$ac_sqlite3_path/include"
+        else
+            for ac_sqlite3_path_tmp in /usr /usr/local /opt ; do
+                if test -f "$ac_sqlite3_path_tmp/include/$ac_sqlite3_header" \
+                    && test -r "$ac_sqlite3_path_tmp/include/$ac_sqlite3_header"; then
+                    ac_sqlite3_path=$ac_sqlite3_path_tmp
 
-    if test "$ac_cv_header_sqlite3_h" = "yes"; then
-        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for spatialite.h in /usr/include or /usr/local/include" >&5
-$as_echo_n "checking for spatialite.h in /usr/include or /usr/local/include... " >&6; }
-        if test -f "/usr/include/spatialite.h" -o -f "/usr/local/include/spatialite.h"; then
-            { $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5
-$as_echo "found" >&6; }
-            { $as_echo "$as_me:${as_lineno-$LINENO}: checking for spatialite_init in -lspatialite" >&5
-$as_echo_n "checking for spatialite_init in -lspatialite... " >&6; }
-if ${ac_cv_lib_spatialite_spatialite_init+:} false; then :
+                    unset ac_cv_lib_sqlite3_sqlite3_open
+                    saved_LIBS="$LIBS"
+                    LIBS=""
+                    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sqlite3_open in -lsqlite3" >&5
+$as_echo_n "checking for sqlite3_open in -lsqlite3... " >&6; }
+if ${ac_cv_lib_sqlite3_sqlite3_open+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-lspatialite  $LIBS"
+LIBS="-lsqlite3  $LIBS"
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -25896,51 +27401,46 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 #ifdef __cplusplus
 extern "C"
 #endif
-char spatialite_init ();
+char sqlite3_open ();
 int
 main ()
 {
-return spatialite_init ();
+return sqlite3_open ();
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_spatialite_spatialite_init=yes
+  ac_cv_lib_sqlite3_sqlite3_open=yes
 else
-  ac_cv_lib_spatialite_spatialite_init=no
+  ac_cv_lib_sqlite3_sqlite3_open=no
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_spatialite_spatialite_init" >&5
-$as_echo "$ac_cv_lib_spatialite_spatialite_init" >&6; }
-if test "x$ac_cv_lib_spatialite_spatialite_init" = xyes; then :
-  SPATIALITE_INIT_FOUND=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sqlite3_sqlite3_open" >&5
+$as_echo "$ac_cv_lib_sqlite3_sqlite3_open" >&6; }
+if test "x$ac_cv_lib_sqlite3_sqlite3_open" = xyes; then :
+  LIB_SQLITE3_FOUND=yes
 else
-  SPATIALITE_INIT_FOUND=no
+  LIB_SQLITE3_FOUND=no
 fi
 
-            if test "$SPATIALITE_INIT_FOUND" = "yes"; then
-                HAVE_SPATIALITE=yes
-                SPATIALITE_LIBS="-lspatialite -lsqlite3"
-                LIBS="$LIBS $SPATIALITE_LIBS"
-                HAVE_SQLITE3=yes
-            fi
-        else
-            { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found : spatialite support disabled" >&5
-$as_echo "not found : spatialite support disabled" >&6; }
-        fi
-    fi
-else
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for spatialite_init in -lspatialite" >&5
-$as_echo_n "checking for spatialite_init in -lspatialite... " >&6; }
-if ${ac_cv_lib_spatialite_spatialite_init+:} false; then :
+                    LIBS="$saved_LIBS"
+                    if test "$LIB_SQLITE3_FOUND" = "yes"; then
+                        ac_sqlite3_ldflags=""
+                    else
+                        unset ac_cv_lib_sqlite3_sqlite3_open
+                        saved_LIBS="$LIBS"
+                        LIBS=""
+                        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sqlite3_open in -lsqlite3" >&5
+$as_echo_n "checking for sqlite3_open in -lsqlite3... " >&6; }
+if ${ac_cv_lib_sqlite3_sqlite3_open+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-lspatialite -L$with_spatialite/lib -lspatialite $LIBS"
+LIBS="-lsqlite3 -L$ac_sqlite3_path_tmp/lib $LIBS"
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -25950,72 +27450,152 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 #ifdef __cplusplus
 extern "C"
 #endif
-char spatialite_init ();
+char sqlite3_open ();
 int
 main ()
 {
-return spatialite_init ();
+return sqlite3_open ();
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_spatialite_spatialite_init=yes
+  ac_cv_lib_sqlite3_sqlite3_open=yes
 else
-  ac_cv_lib_spatialite_spatialite_init=no
+  ac_cv_lib_sqlite3_sqlite3_open=no
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_spatialite_spatialite_init" >&5
-$as_echo "$ac_cv_lib_spatialite_spatialite_init" >&6; }
-if test "x$ac_cv_lib_spatialite_spatialite_init" = xyes; then :
-  SPATIALITE_INIT_FOUND=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sqlite3_sqlite3_open" >&5
+$as_echo "$ac_cv_lib_sqlite3_sqlite3_open" >&6; }
+if test "x$ac_cv_lib_sqlite3_sqlite3_open" = xyes; then :
+  LIB_SQLITE3_FOUND=yes
 else
-  SPATIALITE_INIT_FOUND=no
+  LIB_SQLITE3_FOUND=no
+fi
+
+                        LIBS="$saved_LIBS"
+                        if test "$LIB_SQLITE3_FOUND" = "yes"; then
+                            ac_sqlite3_ldflags="-L$ac_sqlite3_path_tmp/lib"
+                        fi
+                    fi
+
+                    ac_sqlite3_cppflags="-I$ac_sqlite3_path_tmp/include"
+                    break;
+                fi
+            done
+        fi
+
+        if test "$LIB_SQLITE3_FOUND" = "no"; then
+            WANT_SQLITE3="no"
+        fi
+    fi
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SQLite3 library >= $sqlite3_version_req" >&5
+$as_echo_n "checking for SQLite3 library >= $sqlite3_version_req... " >&6; }
+
+    if test "x$WANT_SQLITE3" = "xyes"; then
+
+        ac_sqlite3_ldflags="$ac_sqlite3_ldflags -lsqlite3"
+
+        saved_CPPFLAGS="$CPPFLAGS"
+        CPPFLAGS="$CPPFLAGS $ac_sqlite3_cppflags"
+
+        ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+            #include <sqlite3.h>
+int
+main ()
+{
+
+#if (SQLITE_VERSION_NUMBER >= $sqlite3_version_req_number)
+// Everything is okay
+#else
+#  error SQLite version is too old
+#endif
+
+
+  ;
+  return 0;
+}
+
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+            HAVE_SQLITE3="yes"
+            success="yes"
+
+else
+
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+            HAVE_SQLITE3="no"
+            success="no"
+
+
 fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+        ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+        CPPFLAGS="$saved_CPPFLAGS"
+
+        if test "$success" = "yes"; then
+
+            SQLITE3_CFLAGS="$ac_sqlite3_cppflags"
+            SQLITE3_LDFLAGS="$ac_sqlite3_ldflags"
+
+            ac_sqlite3_header_path="$ac_sqlite3_path/include/$ac_sqlite3_header"
+
+                        if test "x$ac_sqlite3_header_path" != "x"; then
+                ac_sqlite3_version=`cat $ac_sqlite3_header_path \
+                    | grep '#define.*SQLITE_VERSION.*\"' | sed -e 's/.* "//' \
+                        | sed -e 's/"//'`
+                if test $ac_sqlite3_version != ""; then
+                    SQLITE3_VERSION=$ac_sqlite3_version
+                else
+                    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Can not find SQLITE_VERSION macro in sqlite3.h header to retrieve SQLite version!" >&5
+$as_echo "$as_me: WARNING: Can not find SQLITE_VERSION macro in sqlite3.h header to retrieve SQLite version!" >&2;}
+                fi
+            fi
 
-    if test -f "$with_spatialite/include/spatialite.h" -a \
-        -f "$with_spatialite/include/spatialite/sqlite3.h" -a \
-        "$SPATIALITE_INIT_FOUND" = "yes"; then
 
-        { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled" >&5
-$as_echo "enabled" >&6; }
-        HAVE_SPATIALITE=yes
-        SPATIALITE_AMALGAMATION=yes
+        fi
 
-        # SpatiaLite amalgamation availability implies SQLite availability
-        # Caution : don't include the include/spatialite subdir in the include dir
-        # as there's a spatialite.h file in it, which we don't want to include.
-        # We want to include include/spatialite.h instead !
-        SQLITE3_CFLAGS="-I$with_spatialite/include"
-        SPATIALITE_LIBS="-L$with_spatialite/lib -lspatialite"
-        LIBS="$LIBS $SPATIALITE_LIBS"
-        HAVE_SQLITE3=yes
 
-    elif test -f "$with_spatialite/include/spatialite.h" -a \
-        "$SPATIALITE_INIT_FOUND" = "yes"; then
-        for ac_header in sqlite3.h
-do :
-  ac_fn_c_check_header_mongrel "$LINENO" "sqlite3.h" "ac_cv_header_sqlite3_h" "$ac_includes_default"
-if test "x$ac_cv_header_sqlite3_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_SQLITE3_H 1
-_ACEOF
 
-fi
 
-done
+    else
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5
+$as_echo "disabled" >&6; }
+    fi
 
-        if test "$ac_cv_header_sqlite3_h" = "yes"; then
-            { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled" >&5
-$as_echo "enabled" >&6; }
+
+        if test "$HAVE_SQLITE3" = "yes"; then
             SPATIALITE_INC="-I$with_spatialite/include"
             HAVE_SPATIALITE=yes
-            SPATIALITE_LIBS="-L$with_spatialite/lib -lspatialite -lsqlite3"
-            LIBS="$LIBS $SPATIALITE_LIBS"
-            HAVE_SQLITE3=yes
+            SPATIALITE_LIBS="-L$with_spatialite/lib -lspatialite"
+            LIBS="$SQLITE3_LDFLAGS $LIBS $SPATIALITE_LIBS"
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: spatialite enabled" >&5
+$as_echo "spatialite enabled" >&6; }
+        else
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: spatialite disabled" >&5
+$as_echo "spatialite disabled" >&6; }
         fi
     else
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5
@@ -26073,6 +27653,8 @@ fi
 
 HAVE_SPATIALITE=$HAVE_SPATIALITE
 
+SPATIALITE_SONAME=$SPATIALITE_SONAME
+
 SPATIALITE_INC=$SPATIALITE_INC
 
 SPATIALITE_AMALGAMATION=$SPATIALITE_AMALGAMATION
@@ -26081,7 +27663,7 @@ SPATIALITE_412_OR_LATER=$SPATIALITE_412_OR_LATER
 
 
 
-if test "${HAVE_SPATIALITE}" = "no" ; then
+if test "${HAVE_SPATIALITE}" = "no" -o "${HAVE_SPATIALITE}" = "dlopen" ; then
     SQLITE3_REQ_VERSION="3.0.0"
 
 
@@ -26344,7 +27926,7 @@ else
             { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
 $as_echo "not found" >&6; }
             HAVE_SQLITE3="no"
-            succees="no"
+            success="no"
 
 
 fi
@@ -27508,6 +29090,104 @@ $as_echo "$as_me: Using C API from GEOS $GEOS_VERSION" >&6;}
 fi
 
 
+
+# Check whether --with-qhull was given.
+if test "${with_qhull+set}" = set; then :
+  withval=$with_qhull;
+fi
+
+
+QHULL_SETTING=no
+
+if test "$with_qhull" = "no" ; then
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: QHull support disabled." >&5
+$as_echo "$as_me: QHull support disabled." >&6;}
+
+elif test "$with_qhull" = "yes" -o "$with_qhull" = "" ; then
+
+  # Only qhull 2012 is reliable on certain datasets. Older Ubuntu have
+  # qhull/qhull.h
+  for ac_header in qhull/libqhull.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "qhull/libqhull.h" "ac_cv_header_qhull_libqhull_h" "$ac_includes_default"
+if test "x$ac_cv_header_qhull_libqhull_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_QHULL_LIBQHULL_H 1
+_ACEOF
+
+fi
+
+done
+
+  if test "$ac_cv_header_qhull_libqhull_h" = "yes"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for qh_new_qhull in -lqhull" >&5
+$as_echo_n "checking for qh_new_qhull in -lqhull... " >&6; }
+if ${ac_cv_lib_qhull_qh_new_qhull+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lqhull  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char qh_new_qhull ();
+int
+main ()
+{
+return qh_new_qhull ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_qhull_qh_new_qhull=yes
+else
+  ac_cv_lib_qhull_qh_new_qhull=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_qhull_qh_new_qhull" >&5
+$as_echo "$ac_cv_lib_qhull_qh_new_qhull" >&6; }
+if test "x$ac_cv_lib_qhull_qh_new_qhull" = xyes; then :
+  QHULL_SETTING=yes
+else
+  QHULL_SETTING=no
+fi
+
+    if test "$QHULL_SETTING" = "yes"; then
+        QHULL_SETTING=external
+        if test -f /usr/include/qhull/libqhull.h; then
+            EXTRA_INCLUDES="-I/usr/include/qhull $EXTRA_INCLUDES"
+        else
+            EXTRA_INCLUDES="-I/usr/include/local/qhull $EXTRA_INCLUDES"
+        fi
+        LIBS="-lqhull $LIBS"
+    fi
+  fi
+  if test "$QHULL_SETTING" = "no" ; then
+    if test "$with_qhull" = "yes"; then
+        as_fn_error $? "--with-qhull requested, but library not found!" "$LINENO" 5
+    else
+        QHULL_SETTING=internal
+    fi
+  fi
+else
+  QHULL_SETTING=internal
+fi
+
+QHULL_SETTING=$QHULL_SETTING
+
+
+
 OPENCL_SETTING=no
 OPENCL_FLAGS=
 OPENCL_LIB=
@@ -28314,6 +29994,32 @@ PAM_SETTING=$PAM_SETTING
 
 
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build PDF driver as a plugin" >&5
+$as_echo_n "checking whether to build PDF driver as a plugin... " >&6; }
+
+# Check whether --enable-pdf_plugin was given.
+if test "${enable_pdf_plugin+set}" = set; then :
+  enableval=$enable_pdf_plugin;
+fi
+
+
+PDF_PLUGIN=no
+if test "x$enable_pdf_plugin" = "xyes" ; then
+
+  PDF_PLUGIN=yes
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+PDF_PLUGIN=$PDF_PLUGIN
+
+
+
+
 
 # Check whether --with-poppler was given.
 if test "${with_poppler+set}" = set; then :
@@ -28357,10 +30063,13 @@ if test "$with_poppler" != "no" -a "$with_poppler" != ""; then
     fi
 
     if test "$HAVE_POPPLER" = "yes"; then
-        LIBS="${TEST_POPPLER_LIB} ${LIBS}"
+        if test "$PDF_PLUGIN" = "no"; then
+            LIBS="${TEST_POPPLER_LIB} ${LIBS}"
+        fi
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
         POPPLER_INC=$TEST_POPPLER_INC
+        POPPLER_PLUGIN_LIB="${TEST_POPPLER_LIB}"
 
         # And now try another dirty thing, but this one is
         # optional.
@@ -28461,6 +30170,8 @@ POPPLER_0_23_OR_LATER=$POPPLER_0_23_OR_LATER
 
 POPPLER_INC=$POPPLER_INC
 
+POPPLER_PLUGIN_LIB=$POPPLER_PLUGIN_LIB
+
 
 
 
@@ -28496,10 +30207,15 @@ fi
         rm -f testpodofo.*
         echo '#include <podofo.h>' > testpodofo.cpp
         echo 'int main(int argc, char** argv) { PoDoFo::PdfError::EnableDebug( 0 ); return 0; } ' >> testpodofo.cpp
-        if test -z "`${CXX} testpodofo.cpp -o testpodofo ${TEST_PODOFO_INC} ${PODOFO_LIB}  2>&1`" ; then
+        ${CXX} testpodofo.cpp -o testpodofo ${TEST_PODOFO_INC} ${PODOFO_LIB} 2>/dev/null
+        RETVAL=$?
+        if test $RETVAL -eq 0; then
             HAVE_PODOFO=yes
-            LIBS="${PODOFO_LIB} ${LIBS}"
+            if test "$PDF_PLUGIN" = "no"; then
+                LIBS="${PODOFO_LIB} ${LIBS}"
+            fi
             PODOFO_INC=$TEST_PODOFO_INC
+            PODOFO_PLUGIN_LIB="${PODOFO_LIB}"
             { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
         fi
@@ -28511,7 +30227,7 @@ $as_echo "yes" >&6; }
         if test "x$with_podofo_lib" != "x" ; then
             PODOFO_LIB="$with_podofo_lib"
         else
-            # This may be a static libpodofo.a, so add dependant libraries
+            # This may be a static libpodofo.a, so add dependent libraries.
             PODOFO_LIB="$PODOFO_LIB -lfreetype -lfontconfig -lpthread"
         fi
 
@@ -28531,10 +30247,15 @@ fi
         rm -f testpodofo.*
         echo '#include <podofo.h>' > testpodofo.cpp
         echo 'int main(int argc, char** argv) { PoDoFo::PdfError::EnableDebug( 0 ); return 0; } ' >> testpodofo.cpp
-        if test -z "`${CXX} testpodofo.cpp -o testpodofo ${TEST_PODOFO_INC} ${TEST_PODOFO_LIB} 2>&1`" ; then
+        ${CXX} testpodofo.cpp -o testpodofo ${TEST_PODOFO_INC} ${TEST_PODOFO_LIB} 2>/dev/null
+        RETVAL=$?
+        if test $RETVAL -eq 0; then
             HAVE_PODOFO=yes
-            LIBS="${PODOFO_LIB} ${LIBS}"
+            if test "$PDF_PLUGIN" = "no"; then
+                LIBS="${PODOFO_LIB} ${LIBS}"
+            fi
             PODOFO_INC=$TEST_PODOFO_INC
+            PODOFO_PLUGIN_LIB="${PODOFO_LIB}"
             { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
         else
@@ -28553,6 +30274,131 @@ HAVE_PODOFO=$HAVE_PODOFO
 
 PODOFO_INC=$PODOFO_INC
 
+PODOFO_PLUGIN_LIB=$PODOFO_PLUGIN_LIB
+
+
+
+
+# Check whether --with-pdfium was given.
+if test "${with_pdfium+set}" = set; then :
+  withval=$with_pdfium;
+fi
+
+
+HAVE_PDFIUM=no
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pdfium" >&5
+$as_echo_n "checking for pdfium... " >&6; }
+
+if test "$with_pdfium" != "no" -a "$with_pdfium" != ""; then
+
+
+# Check whether --with-pdfium-lib was given.
+if test "${with_pdfium_lib+set}" = set; then :
+  withval=$with_pdfium_lib;
+fi
+
+
+    if test "$with_pdfium" = "yes" ; then
+        TEST_PDFIUM_INC="-I/usr/include -I/usr/include/pdfium"
+        PDFIUM_LIB="-lpdfium"
+        PDFIUM_LIBDIR="/usr"
+    else
+        TEST_PDFIUM_INC="-I$with_pdfium -I$with_pdfium/include -I$with_pdfium/include/pdfium"
+        PDFIUM_LIB="-L$with_pdfium -L$with_pdfium/lib -lpdfium"
+        PDFIUM_LIBDIR="$with_pdfium"
+    fi
+
+    if test ! -z "`uname | grep Darwin`" ; then
+        PDFIUM_LIB="-stdlib=libstdc++ $PDFIUM_LIB"
+    fi
+
+    if test "x$with_pdfium_lib" = "x" ; then
+        rm -f testpdfium.*
+        echo '#include <fpdfview.h>' > testpdfium.cpp
+        echo '#include <core/include/fpdfapi/fpdf_page.h>' >> testpdfium.cpp
+        echo 'int main(int argc, char** argv) { FPDF_InitLibrary(); FPDF_DestroyLibrary(); return 0; } ' >> testpdfium.cpp
+        TEST_CXX_FLAGS="-std=c++0x"
+        if test ! -z "`uname | grep Darwin`" ; then
+          TEST_CXX_FLAGS="$TEST_CXX_FLAGS -stdlib=libstdc++"
+        fi
+        if test -z "`${CXX} $TEST_CXX_FLAGS testpdfium.cpp -o testpdfium ${TEST_PDFIUM_INC} ${PDFIUM_LIB}  2>&1`" ; then
+            HAVE_PDFIUM=yes
+            CXXFLAGS="$TEST_CXX_FLAGS $CXXFLAGS"
+            if test "$PDF_PLUGIN" = "no"; then
+                LIBS="${PDFIUM_LIB} ${LIBS}"
+            fi
+            PDFIUM_PLUGIN_LIB="${PDFIUM_LIB}"
+            PDFIUM_INC=$TEST_PDFIUM_INC
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+        fi
+        rm -f testpdfium.*
+        rm -f testpdfium
+    fi
+
+    if test "$HAVE_PDFIUM" = "no"; then
+        if test "x$with_pdfium_lib" != "x" ; then
+            PDFIUM_LIB="$with_pdfium_lib"
+        else
+            # This may be a static libpdfium.a, so add dependent libraries.
+            PDFIUM_LIB="-L$PDFIUM_LIBDIR -L$PDFIUM_LIBDIR/lib/pdfium -lpdfium -lfpdfdoc -lfpdfapi -lfpdftext -lformfiller -lpdfwindow"
+            PDFIUM_LIB="$PDFIUM_LIB -lfxedit -lfpdfdoc -lfxcodec -lfx_libopenjpeg -lfx_lcms2 -lfx_libjpeg -lfx_zlib"
+            PDFIUM_LIB="$PDFIUM_LIB -lfdrm -lfxge -lfreetype -lfx_agg -lfxcrt -lbigint"
+            if test ! -z "`uname | grep Darwin`" ; then
+                PDFIUM_LIB="-framework AppKit -framework CoreFoundation $PDFIUM_LIB"
+            fi
+        fi
+
+
+# Check whether --with-pdfium-extra-lib-for-test was given.
+if test "${with_pdfium_extra_lib_for_test+set}" = set; then :
+  withval=$with_pdfium_extra_lib_for_test;
+fi
+
+
+        if test "x$with_pdfium_extra_lib_for_test" = "x" ; then
+            TEST_PDFIUM_LIB="$PDFIUM_LIB"
+        else
+            TEST_PDFIUM_LIB="$PDFIUM_LIB $with_pdfium_extra_lib_for_test"
+        fi
+
+        rm -f testpdfium.*
+        echo '#include <fpdfview.h>' > testpdfium.cpp
+        echo '#include <core/include/fpdfapi/fpdf_page.h>' >> testpdfium.cpp
+        echo 'int main(int argc, char** argv) { FPDF_InitLibrary(); FPDF_DestroyLibrary(); return 0; } ' >> testpdfium.cpp
+        TEST_CXX_FLAGS="-std=c++0x"
+        if test ! -z "`uname | grep Darwin`" ; then
+          TEST_CXX_FLAGS="$TEST_CXX_FLAGS -stdlib=libstdc++"
+        fi
+        if test -z "`${CXX} $TEST_CXX_FLAGS testpdfium.cpp -o testpdfium ${TEST_PDFIUM_INC} ${TEST_PDFIUM_LIB} 2>&1`" ; then
+            HAVE_PDFIUM=yes
+            CXXFLAGS="$TEST_CXX_FLAGS $CXXFLAGS"
+            if test "$PDF_PLUGIN" = "no"; then
+                LIBS="${PDFIUM_LIB} ${LIBS}"
+            fi
+            PDFIUM_PLUGIN_LIB="${PDFIUM_LIB}"
+            PDFIUM_INC=$TEST_PDFIUM_INC
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+        else
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+        fi
+        rm -f testpdfium.*
+        rm -f testpdfium
+    fi
+else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5
+$as_echo "disabled" >&6; }
+fi
+
+HAVE_PDFIUM=$HAVE_PDFIUM
+
+PDFIUM_INC=$PDFIUM_INC
+
+PDFIUM_PLUGIN_LIB=$PDFIUM_PLUGIN_LIB
+
 
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link PROJ.4 library" >&5
@@ -29793,6 +31639,166 @@ HAVE_ARMADILLO=$HAVE_ARMADILLO
 
 
 
+
+# Check whether --with-cryptopp was given.
+if test "${with_cryptopp+set}" = set; then :
+  withval=$with_cryptopp;
+fi
+
+
+HAVE_CRYPTOPP=no
+USE_ONLY_CRYPTODLL_ALG=yes
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for cryptopp" >&5
+$as_echo_n "checking for cryptopp... " >&6; }
+
+if test "$with_cryptopp" = "no" ; then
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5
+$as_echo "disabled" >&6; }
+
+elif test "$with_cryptopp" = "yes" -o "$with_cryptopp" = "" ; then
+
+    rm -f testcryptopp.*
+    echo '#include <cryptopp/aes.h>' > testcryptopp.cpp
+    # Catch issue with clang++ (https://groups.google.com/forum/#!topic/cryptopp-users/DfWHy3bT0KI)
+    echo '#include <cryptopp/osrng.h>' >> testcryptopp.cpp
+    echo 'int main(int argc, char** argv) { CryptoPP::AES::Encryption oEnc; return 0; } ' >> testcryptopp.cpp
+    ${CXX} ${CXXFLAGS} testcryptopp.cpp -o testcryptopp -lcryptopp 2>/dev/null
+    RETVAL=$?
+    if test $RETVAL -eq 0; then
+        HAVE_CRYPTOPP=yes
+        LIBS="-lcryptopp ${LIBS}"
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+    else
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+        if test "$with_cryptopp" = "yes"; then
+            as_fn_error $? "--with-cryptopp was requested, but not available" "$LINENO" 5
+        fi
+    fi
+    rm -f testcryptopp.*
+    rm -f testcryptopp
+
+    if test "$HAVE_CRYPTOPP" = "yes"; then
+
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking if cryptopp has all cipher methods builtin" >&5
+$as_echo_n "checking if cryptopp has all cipher methods builtin... " >&6; }
+        rm -f testcryptopp.*
+        echo '#include <cryptopp/blowfish.h>' > testcryptopp.cpp
+        echo 'int main(int argc, char** argv) { CryptoPP::Blowfish::Encryption oEnc; return 0; } ' >> testcryptopp.cpp
+        ${CXX} ${CXXFLAGS} testcryptopp.cpp -o testcryptopp -lcryptopp 2>/dev/null
+        RETVAL=$?
+        if test $RETVAL -eq 0; then
+            USE_ONLY_CRYPTODLL_ALG=no
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+        else
+            USE_ONLY_CRYPTODLL_ALG=yes
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+        fi
+        rm -f testcryptopp.*
+        rm -f testcryptopp
+    fi
+
+else
+
+    rm -f testcryptopp.*
+    echo '#include <cryptopp/aes.h>' > testcryptopp.cpp
+    # Catch issue with clang++ (https://groups.google.com/forum/#!topic/cryptopp-users/DfWHy3bT0KI)
+    echo '#include <cryptopp/osrng.h>' >> testcryptopp.cpp
+    echo 'int main(int argc, char** argv) { CryptoPP::AES::Encryption oEnc; return 0; } ' >> testcryptopp.cpp
+    ${CXX} ${CXXFLAGS} testcryptopp.cpp -I$with_cryptopp/include -o testcryptopp -L$with_cryptopp/lib -lcryptopp 2>/dev/null
+    RETVAL=$?
+    if test $RETVAL -eq 0; then
+        HAVE_CRYPTOPP=yes
+        LIBS="-L$with_cryptopp/lib -lcryptopp ${LIBS}"
+        EXTRA_INCLUDES="-I$with_cryptopp/include $EXTRA_INCLUDES"
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+    else
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+    fi
+    rm -f testcryptopp.*
+    rm -f testcryptopp
+
+    if test "$HAVE_CRYPTOPP" = "yes"; then
+
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking if cryptopp has all cipher methods builtin" >&5
+$as_echo_n "checking if cryptopp has all cipher methods builtin... " >&6; }
+        rm -f testcryptopp.*
+        echo '#include <cryptopp/blowfish.h>' > testcryptopp.cpp
+        echo 'int main(int argc, char** argv) { CryptoPP::Blowfish::Encryption oEnc; return 0; } ' >> testcryptopp.cpp
+        ${CXX} ${CXXFLAGS} testcryptopp.cpp -I$with_cryptopp/include -o testcryptopp -L$with_cryptopp/lib -lcryptopp 2>/dev/null
+        RETVAL=$?
+        if test $RETVAL -eq 0; then
+            USE_ONLY_CRYPTODLL_ALG=no
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+        else
+            USE_ONLY_CRYPTODLL_ALG=yes
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+        fi
+        rm -f testcryptopp.*
+        rm -f testcryptopp
+    fi
+
+fi
+
+HAVE_CRYPTOPP=$HAVE_CRYPTOPP
+
+USE_ONLY_CRYPTODLL_ALG=$USE_ONLY_CRYPTODLL_ALG
+
+
+
+
+
+# Check whether --with-grib was given.
+if test "${with_grib+set}" = set; then :
+  withval=$with_grib;
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for MRF" >&5
+$as_echo_n "checking for MRF... " >&6; }
+if test "$with_mrf" = yes -o x"$with_mrf" = x ; then
+    OPT_GDAL_FORMATS="mrf $OPT_GDAL_FORMATS"
+    HAVE_MRF=yes
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled" >&5
+$as_echo "enabled" >&6; }
+else
+    HAVE_MRF=no
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled by user" >&5
+$as_echo "disabled by user" >&6; }
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if sprintf can be overloaded for GDAL compilation" >&5
+$as_echo_n "checking if sprintf can be overloaded for GDAL compilation... " >&6; }
+echo '#define _XOPEN_SOURCE' > testdeprecated.cpp
+echo '#include <vector>' >> testdeprecated.cpp
+echo '#include <stdio.h>' >> testdeprecated.cpp
+echo 'extern "C"' >> testdeprecated.cpp
+echo '{' >> testdeprecated.cpp
+echo 'int sprintf(char *str, const char* fmt, ...);' >> testdeprecated.cpp
+echo '}' >> testdeprecated.cpp
+${CXX} ${CXXFLAGS} testdeprecated.cpp -c 2>/dev/null
+RETVAL=$?
+if test $RETVAL -eq 0; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+    CPPFLAGS="$CPPFLAGS -DDONT_DEPRECATE_SPRINTF"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f testdeprecated.*
+rm -f testdeprecated
+
 ac_config_files="$ac_config_files GDALmake.opt"
 
 
@@ -32221,6 +34227,9 @@ echo "  LIBZ support:              ${LIBZ_SETTING}"
 echo "  LIBLZMA support:           ${LIBLZMA_SETTING}"
 
 
+echo "  cryptopp support:          ${HAVE_CRYPTOPP}"
+
+
 echo "  GRASS support:             ${GRASS_SETTING}"
 
 
@@ -32314,6 +34323,9 @@ echo "  cURL support (wms/wcs/...):${CURL_SETTING}"
 echo "  PostgreSQL support:        ${HAVE_PG}"
 
 
+echo "  MRF support:               ${HAVE_MRF}"
+
+
 echo "  MySQL support:             ${HAVE_MYSQL}"
 
 
@@ -32373,6 +34385,11 @@ echo "  PCRE support:              ${HAVE_PCRE}"
 
 echo "  SpatiaLite support:        ${HAVE_SPATIALITE}"
 
+if test "x$SPATIALITE_SONAME" != "x"; then
+
+echo "  SpatiaLite shared obj name:${SPATIALITE_SONAME}"
+
+fi
 
 echo "  DWGdirect support          ${HAVE_DWGDIRECT}"
 
@@ -32383,12 +34400,18 @@ echo "  INFORMIX DataBlade support:${HAVE_IDB}"
 echo "  GEOS support:              ${HAVE_GEOS_RESULT}"
 
 
+echo "  QHull support:             ${QHULL_SETTING}"
+
+
 echo "  Poppler support:           ${HAVE_POPPLER}"
 
 
 echo "  Podofo support:            ${HAVE_PODOFO}"
 
 
+echo "  PDFium support:            ${HAVE_PDFIUM}"
+
+
 echo "  OpenCL support:            ${OPENCL_SETTING}"
 
 
@@ -32401,6 +34424,9 @@ echo "  FreeXL support:            ${HAVE_FREEXL}"
 echo "  SOSI support:              ${SOSI_ENABLED}"
 
 
+echo "  MongoDB support:           ${MONGODB_ENABLED}"
+
+
 echo ""
 
 if test ! -z "`uname | grep Darwin`" ; then
@@ -32426,7 +34452,7 @@ echo ""
 echo "  Statically link PROJ.4:    ${PROJ_STATIC}"
 
 
-echo "  enable OGR building:       ${OGR_ENABLED}"
+echo "  enable GNM building:       ${GNM_ENABLED}"
 
 
 echo "  enable pthread support:    ${PTHREAD_ENABLED}"
@@ -32441,10 +34467,20 @@ echo "  hide internal symbols:     ${HAVE_HIDE_INTERNAL_SYMBOLS}"
 echo ""
 
 
-if test "$HAVE_PODOFO" = "yes" -a "$HAVE_POPPLER" = "yes" ; then
+if test "$HAVE_PODOFO" = "yes" -a "$HAVE_POPPLER" = "yes"  -a "$HAVE_PDFIUM" = "yes"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-podofo, --with-poppler and --with-pdfium available. This is unusual setup, but will work. Pdfium will be used by default..." >&5
+$as_echo "$as_me: WARNING: --with-podofo, --with-poppler and --with-pdfium available. This is unusual setup, but will work. Pdfium will be used by default..." >&2;}
+elif test "$HAVE_PODOFO" = "yes" -a "$HAVE_POPPLER" = "yes" ; then
     { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-podofo and --with-poppler are both available. This is unusual setup, but will work. Poppler will be used by default..." >&5
 $as_echo "$as_me: WARNING: --with-podofo and --with-poppler are both available. This is unusual setup, but will work. Poppler will be used by default..." >&2;}
+elif test "$HAVE_POPPLER" = "yes" -a "$HAVE_PDFIUM" = "yes" ; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-poppler and --with-pdfium are both available. This is unusual setup, but will work. Pdfium will be used by default..." >&5
+$as_echo "$as_me: WARNING: --with-poppler and --with-pdfium are both available. This is unusual setup, but will work. Pdfium will be used by default..." >&2;}
+elif test "$HAVE_PODOFO" = "yes" -a "$HAVE_PDFIUM" = "yes" ; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-podofo and --with-pdfium are both available. This is unusual setup, but will work. Pdfium will be used by default..." >&5
+$as_echo "$as_me: WARNING: --with-podofo and --with-pdfium are both available. This is unusual setup, but will work. Pdfium will be used by default..." >&2;}
 fi
+
 if test "$HAVE_LIBXML2" = "yes" -a "$FGDB_ENABLED" = "yes"; then
     { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-libxml2 and --with-fgdb are both available. There might be some incompatibility between system libxml2 and the embedded copy within libFileGDBAPI" >&5
 $as_echo "$as_me: WARNING: --with-libxml2 and --with-fgdb are both available. There might be some incompatibility between system libxml2 and the embedded copy within libFileGDBAPI" >&2;}
diff --git a/configure.in b/configure.in
index a73a302..94813d2 100644
--- a/configure.in
+++ b/configure.in
@@ -1,5 +1,5 @@
 dnl ***************************************************************************
-dnl $Id: configure.in 33151 2016-01-24 21:26:46Z rouault $
+dnl $Id: configure.in 33757 2016-03-20 20:22:33Z goatbar $
 dnl
 dnl Project:  GDAL
 dnl Purpose:  Configure source file.
@@ -47,8 +47,52 @@ AC_CANONICAL_HOST
 dnl Enable as much warnings as possible
 AX_CFLAGS_WARN_ALL(C_WFLAGS)
 AX_CXXFLAGS_WARN_ALL(CXX_WFLAGS)
+AX_CHECK_COMPILE_FLAG([-Werror -Wextra],[C_WFLAGS="$C_WFLAGS -Wextra" CXX_WFLAGS="$CXX_WFLAGS -Wextra"])
+AX_CHECK_COMPILE_FLAG([-Werror -Winit-self],[C_WFLAGS="$C_WFLAGS -Winit-self" CXX_WFLAGS="$CXX_WFLAGS -Winit-self"])
+AX_CHECK_COMPILE_FLAG([-Werror -Wunused-parameter], [C_WFLAGS="$C_WFLAGS -Wunused-parameter" CXX_WFLAGS="$CXX_WFLAGS -Wunused-parameter" NO_UNUSED_PARAMETER_FLAG="-Wno-unused-parameter"])
+AX_CHECK_COMPILE_FLAG([-Werror -Wmissing-prototypes], [C_WFLAGS="$C_WFLAGS -Wmissing-prototypes"])
+AX_CHECK_COMPILE_FLAG([-Werror -Wmissing-declarations], [C_WFLAGS="$C_WFLAGS -Wmissing-declarations"])
+AX_CHECK_COMPILE_FLAG([-Werror -Wformat], [C_WFLAGS="$C_WFLAGS -Wformat" CXX_WFLAGS="$CXX_WFLAGS -Wformat"])
+AX_CHECK_COMPILE_FLAG([-Werror -Wformat -Werror=format-security -Wno-format-nonliteral], [C_WFLAGS="$C_WFLAGS -Werror=format-security -Wno-format-nonliteral" CXX_WFLAGS="$CXX_WFLAGS -Werror=format-security -Wno-format-nonliteral"])
+AX_CHECK_COMPILE_FLAG([-Werror -Wshorten-64-to-32], [C_WFLAGS="$C_WFLAGS -Wshorten-64-to-32" CXX_WFLAGS="$CXX_WFLAGS -Wshorten-64-to-32"])
+AX_CHECK_COMPILE_FLAG([-Werror -Wlogical-op], [C_WFLAGS="$C_WFLAGS -Wlogical-op" CXX_WFLAGS="$CXX_WFLAGS -Wlogical-op" NO_LOGICAL_OP_FLAG="-Wno-logical-op"])
+AX_CHECK_COMPILE_FLAG([-Werror -Wshadow], [C_WFLAGS="$C_WFLAGS -Wshadow" CXX_WFLAGS="$CXX_WFLAGS -Wshadow"])
+
+dnl Error out on things that will fail with MSVC
+AX_CHECK_COMPILE_FLAG([-Werror -Werror=vla], [C_WFLAGS="$C_WFLAGS -Werror=vla" CXX_WFLAGS="$CXX_WFLAGS -Werror=vla"])
+AX_CHECK_COMPILE_FLAG([-Werror -Werror=declaration-after-statement], [C_WFLAGS="$C_WFLAGS -Wdeclaration-after-statement"])
+
+dnl -Wclobbered is not reliable on most gcc versions
+dnl AX_CHECK_COMPILE_FLAG([-Werror -Wno-clobbered], [C_WFLAGS="$C_WFLAGS -Wno-clobbered" CXX_WFLAGS="$CXX_WFLAGS -Wno-clobbered"])
+
+dnl GCC 6 warnings
+AX_CHECK_COMPILE_FLAG([-Werror -Wnull-dereference], [C_WFLAGS="$C_WFLAGS -Wnull-dereference" CXX_WFLAGS="$CXX_WFLAGS -Wnull-dereference"])
+AX_CHECK_COMPILE_FLAG([-Werror -Wduplicated-cond], [C_WFLAGS="$C_WFLAGS -Wduplicated-cond" CXX_WFLAGS="$CXX_WFLAGS -Wduplicated-cond"])
+
+AX_CHECK_COMPILE_FLAG([-Werror -Wno-sign-compare], [NO_SIGN_COMPARE="-Wno-sign-compare"])
+
+dnl C++ specific stuff
+
+AC_LANG_PUSH([C++])
+AX_CHECK_COMPILE_FLAG([-Werror -Wunused-private-field], [CXX_WFLAGS="$CXX_WFLAGS -Wunused-private-field"])
+AX_CHECK_COMPILE_FLAG([-Werror -Wmissing-prototypes], [CXX_WFLAGS="$CXX_WFLAGS -Wmissing-prototypes"])
+AX_CHECK_COMPILE_FLAG([-Werror -Wmissing-declarations], [CXX_WFLAGS="$CXX_WFLAGS -Wmissing-declarations"])
+AX_CHECK_COMPILE_FLAG([-Werror -Wnon-virtual-dtor], [CXX_WFLAGS="$CXX_WFLAGS -Wnon-virtual-dtor" NO_NON_VIRTUAL_DTOR_FLAG="-Wno-non-virtual-dtor"])
+
+dnl Clang enables -Woverloaded-virtual if -Wall is defined, but not GCC
+AX_CHECK_COMPILE_FLAG([-Werror -Woverloaded-virtual], [CXX_WFLAGS="$CXX_WFLAGS -Woverloaded-virtual"])
+
+dnl Forbid use of 'or', 'and', ... alias operators
+AX_CHECK_COMPILE_FLAG([-Werror -fno-operator-names], [CXX_WFLAGS="$CXX_WFLAGS -fno-operator-names"])
+
+AC_LANG_POP([C++])
+
 AC_SUBST(CXX_WFLAGS,$CXX_WFLAGS)
 AC_SUBST(C_WFLAGS,$C_WFLAGS)
+AC_SUBST(NO_UNUSED_PARAMETER_FLAG,$NO_UNUSED_PARAMETER_FLAG)
+AC_SUBST(NO_SIGN_COMPARE,$NO_SIGN_COMPARE)
+AC_SUBST(NO_NON_VIRTUAL_DTOR_FLAG,$NO_NON_VIRTUAL_DTOR_FLAG)
+AC_SUBST(NO_LOGICAL_OP_FLAG,$NO_LOGICAL_OP_FLAG)
 
 dnl Checks for programs.
 AC_PROG_CC
@@ -56,6 +100,19 @@ AC_PROG_CXX
 AC_LIBTOOL_WIN32_DLL
 AC_PROG_LIBTOOL
 
+dnl Check that CXX is really a working compiler
+AC_LANG_PUSH([C++])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+  [[#ifndef __cplusplus
+    #error "broken C++"
+    #endif]])],,
+  [CXX=;])
+AC_LANG_POP([C++])
+
+if test "x$CXX" == x ; then
+  AC_MSG_ERROR("You don't have a working C++ compiler.")
+fi
+
 dnl switch between libtool and native build system
 AC_ARG_WITH(libtool, [  --without-libtool     Don't use libtool to build the library],,)
 
@@ -84,7 +141,7 @@ AC_SUBST(HAVE_LIBTOOL,$with_libtool)
 dnl Checks for libraries.
 AC_CHECK_LIB(dl,dlopen,,,)
 
-dnl Needed on Solaris. 
+dnl Needed on Solaris.
 AC_CHECK_LIB(rt,nanosleep,,,)
 
 dnl We don't need to add math library to all targets
@@ -120,7 +177,7 @@ AC_CHECK_TYPES([int8, int16, int32],,,
 
 dnl We need the following lines for libtiff too.
 HAVE_IEEEFP=1
-AC_DEFINE_UNQUOTED(HAVE_IEEEFP, $HAVE_IEEEFP, [Define as 0 or 1 according to the floating point format suported by the machine])
+AC_DEFINE_UNQUOTED(HAVE_IEEEFP, $HAVE_IEEEFP, [Define as 0 or 1 according to the floating point format supported by the machine])
 
 dnl Check the native cpu bit order (also libtiff stuff).
 AC_MSG_CHECKING([native cpu bit order])
@@ -150,8 +207,10 @@ AC_CHECK_FUNCS(readlink)
 AC_CHECK_FUNCS(lstat)
 AC_CHECK_FUNCS(posix_spawnp)
 AC_CHECK_FUNCS(vfork)
+AC_CHECK_FUNCS(mmap)
+AC_CHECK_FUNCS(statvfs)
 
-dnl Make sure at least these are checked under C++.  Prototypes missing on 
+dnl Make sure at least these are checked under C++.  Prototypes missing on
 dnl some platforms.
 
 AC_LANG_PUSH(C++)
@@ -161,6 +220,27 @@ AC_LANG_POP(C++)
 
 AC_CHECK_FUNC(setlocale)
 
+AC_MSG_CHECKING([for uselocale])
+AC_TRY_COMPILE(
+  [
+#define _XOPEN_SOURCE 700
+#include <locale.h>
+  ], [
+    locale_t alocale = newlocale (LC_NUMERIC_MASK, "C", 0);
+    locale_t oldlocale = uselocale(alocale);
+    uselocale(oldlocale);
+    freelocale(alocale);
+    return 0;
+  ],
+  [
+    AC_MSG_RESULT([yes])
+    AC_DEFINE_UNQUOTED(HAVE_USELOCALE, 1,
+          [Define to 1 if you have the `uselocale' function.])
+  ], [
+    AC_MSG_RESULT([no])
+])
+
+
 OPT_GDAL_FORMATS=
 EXTRA_INCLUDES=
 
@@ -175,30 +255,53 @@ AC_ARG_ENABLE(debug,
 			     [enable debugging (disabled by default)]),
 	      [HAVE_DEBUG=$enableval], [HAVE_DEBUG=yes])
 
+CFLAGS_NOFTRAPV="$CFLAGS"
+CXXFLAGS_NOFTRAPV="$CXXFLAGS"
+
 if test "x$enable_debug" = "xyes" ; then
 
   dnl Try to strip out optimization.
 
-  CXXFLAGS=`echo "$CXXFLAGS " | sed "s/-O2 //"` 
-  CFLAGS=`echo "$CFLAGS " | sed "s/-O2 //"` 
-  CXXFLAGS=`echo "$CXXFLAGS" | sed "s/-O //"` 
-  CFLAGS=`echo "$CFLAGS" | sed "s/-O //"` 
+  CXXFLAGS=`echo "$CXXFLAGS " | sed "s/-O2 //"`
+  CFLAGS=`echo "$CFLAGS " | sed "s/-O2 //"`
+  CXXFLAGS=`echo "$CXXFLAGS" | sed "s/-O //"`
+  CFLAGS=`echo "$CFLAGS" | sed "s/-O //"`
 
-  dnl remove existing -g to avoid duplicates. 
+  dnl remove existing -g to avoid duplicates.
 
-  CXXFLAGS=`echo "$CXXFLAGS" | sed "s/-g //"` 
-  CFLAGS=`echo "$CFLAGS" | sed "s/-g //"` 
+  CXXFLAGS=`echo "$CXXFLAGS" | sed "s/-g //"`
+  CFLAGS=`echo "$CFLAGS" | sed "s/-g //"`
 
   dnl add -g and -DDEBUG
 
   CXXFLAGS="$CXXFLAGS -g -DDEBUG"
   CFLAGS="$CFLAGS -g -DDEBUG"
 
+  CFLAGS_NOFTRAPV="$CFLAGS"
+  CXXFLAGS_NOFTRAPV="$CXXFLAGS"
+
   AC_MSG_RESULT([yes, modified CFLAGS="$CFLAGS"])
+
+  # Some clang version on 32 bits have linking error with 64bit operations (undefined reference to `__mulodi4')
+  AC_MSG_CHECKING([whether -ftrapv can be used])
+  rm -f testftrapv.c
+  echo 'int main(int argc, char** argv) { return (long long)argc * argc; } ' > testftrapv.c
+  if test -z "`${CC} ${CFLAGS} -ftrapv testftrapv.c -o testftrapv 2>&1`" ; then
+    AC_MSG_RESULT([yes])
+    CFLAGS="$CFLAGS -ftrapv"
+    CXXFLAGS="$CXXFLAGS -ftrapv"
+  else
+    AC_MSG_RESULT([no])
+  fi
+  rm -f testftrapv.* testftrapv
+
 else
   AC_MSG_RESULT([no, CFLAGS="$CFLAGS"])
 fi
 
+AC_SUBST(CFLAGS_NOFTRAPV,$CFLAGS_NOFTRAPV)
+AC_SUBST(CXXFLAGS_NOFTRAPV,$CXXFLAGS_NOFTRAPV)
+
 dnl ---------------------------------------------------------------------------
 dnl Check if GCC 4.1 atomic builtins are really available
 dnl (some GCC versions are broken w.r.t this on some exotic architectures...)
@@ -207,8 +310,8 @@ dnl ---------------------------------------------------------------------------
 AC_MSG_CHECKING([whether GCC 4.1 atomic builtins are available])
 
 rm -f atomicbuiltins.c
-echo 'int main(int argc, char* argv[]) { int i; __sync_add_and_fetch(&i, 1); __sync_sub_and_fetch(&i, 1); return 0; } ' > atomicbuiltins.c
-if test -z "`${CC} atomicbuiltins.c -o atomicbuiltins 2>&1`" ; then
+echo 'int main(int argc, char** argv) { int i; __sync_add_and_fetch(&i, 1); __sync_sub_and_fetch(&i, 1); __sync_bool_compare_and_swap(&i, 0, 1); return 0; } ' > atomicbuiltins.c
+if test -z "`${CC} ${CFLAGS} atomicbuiltins.c -o atomicbuiltins 2>&1`" ; then
     HAVE_GCC_ATOMIC_BUILTINS=yes
     AC_MSG_RESULT([yes])
     AC_DEFINE_UNQUOTED(HAVE_GCC_ATOMIC_BUILTINS,1, [Define to 1 if GCC atomic builtins are available])
@@ -301,7 +404,12 @@ if test "$with_avx" = "yes" -o "$with_avx" = ""; then
     rm -f detectavx.cpp
     echo '#ifdef __AVX__' > detectavx.cpp
     echo '#include <immintrin.h>' >> detectavx.cpp
-    echo 'void foo() { unsigned int nXCRLow, nXCRHigh; __asm__ ("xgetbv" : "=a" (nXCRLow), "=d" (nXCRHigh) : "c" (0)); float fEpsilon = 0.0000000000001f; __m256 ymm_small = _mm256_set_ps(fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon); } int main() { return 0; }' >> detectavx.cpp
+    echo 'int foo() { unsigned int nXCRLow, nXCRHigh;' >> detectavx.cpp
+    echo '__asm__ ("xgetbv" : "=a" (nXCRLow), "=d" (nXCRHigh) : "c" (0));' >> detectavx.cpp
+    echo 'float fEpsilon = 0.0000000000001f;' >> detectavx.cpp
+    echo '__m256 ymm_small = _mm256_set_ps(fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon);' >> detectavx.cpp
+    echo 'return (int)nXCRLow + _mm256_movemask_ps(ymm_small); }' >> detectavx.cpp
+    echo 'int main(int argc, char**) { if( argc == 0 ) return foo(); return 0; }' >> detectavx.cpp
     echo '#else' >> detectavx.cpp
     echo 'some_error' >> detectavx.cpp
     echo '#endif' >> detectavx.cpp
@@ -355,6 +463,49 @@ AC_SUBST(AVXFLAGS,$AVXFLAGS)
 AC_SUBST(HAVE_AVX_AT_COMPILE_TIME,$HAVE_AVX_AT_COMPILE_TIME)
 
 dnl ---------------------------------------------------------------------------
+dnl Check for --enable-lto
+dnl ---------------------------------------------------------------------------
+
+AC_MSG_CHECKING([to enable LTO (link time optimization) build])
+
+AC_ARG_ENABLE(lto,
+              AS_HELP_STRING([--enable-lto],
+                             [enable LTO(link time optimization) (disabled by default)]))
+
+CFLAGS_NO_LTO_IF_AVX_NONDEFAULT="$CFLAGS"
+CXXFLAGS_NO_LTO_IF_AVX_NONDEFAULT="$CXXFLAGS"
+
+if test "x$enable_lto" = "xyes" ; then
+
+  dnl remove existing -g.
+
+  CXXFLAGS=`echo "$CXXFLAGS" | sed "s/-g //"`
+  CFLAGS=`echo "$CFLAGS" | sed "s/-g //"`
+
+  dnl add -flto
+
+  CXXFLAGS="$CXXFLAGS -flto"
+  CFLAGS="$CFLAGS -flto"
+  LDFLAGS="$LDFLAGS -flto"
+
+  dnl in case we have avx available by default, then we can compile everything
+  dnl with -flto
+  if test "$HAVE_AVX_AT_COMPILE_TIME" = "yes"; then
+    if test "$AVXFLAGS" = ""; then
+        CFLAGS_NO_LTO_IF_AVX_NONDEFAULT="$CFLAGS"
+        CXXFLAGS_NO_LTO_IF_AVX_NONDEFAULT="$CXXFLAGS"
+    fi
+  fi
+
+  AC_MSG_RESULT([yes])
+else
+  AC_MSG_RESULT([no])
+fi
+
+AC_SUBST(CFLAGS_NO_LTO_IF_AVX_NONDEFAULT,$CFLAGS_NO_LTO_IF_AVX_NONDEFAULT)
+AC_SUBST(CXXFLAGS_NO_LTO_IF_AVX_NONDEFAULT,$CXXFLAGS_NO_LTO_IF_AVX_NONDEFAULT)
+
+dnl ---------------------------------------------------------------------------
 dnl Check if we need -lws2_32
 dnl ---------------------------------------------------------------------------
 
@@ -383,7 +534,7 @@ fi
 rm -f test_getaddrinfo*
 
 dnl ---------------------------------------------------------------------------
-dnl Check if user requests hidding internal symbols
+dnl Check if user requests hiding internal symbols
 dnl ---------------------------------------------------------------------------
 
 AC_ARG_WITH(hide_internal_symbols,[  --with-hide-internal-symbols[=ARG] Try to hide internal symbols (ARG=yes/no)],,)
@@ -416,7 +567,7 @@ else
 fi
 
 if test "$HAVE_HIDE_INTERNAL_SYMBOLS" = "yes" ; then
-  AC_DEFINE_UNQUOTED(USE_GCC_VISIBILITY_FLAG,1, [Define to 1 if you want to use the -fvisibility GCC flag]) 
+  AC_DEFINE_UNQUOTED(USE_GCC_VISIBILITY_FLAG,1, [Define to 1 if you want to use the -fvisibility GCC flag])
 fi
 
 AC_SUBST(HAVE_HIDE_INTERNAL_SYMBOLS,$HAVE_HIDE_INTERNAL_SYMBOLS)
@@ -451,7 +602,7 @@ AC_MSG_CHECKING([for local include/lib path])
 AC_ARG_WITH(local,[  --with-local[=dir]      Include /usr/local or other local tree for INCLUDE/LIBS],,)
 
 if test "$with_local" != "no" -a "$with_local" != "" ; then
-  
+
   if test "$with_local" = "yes" ; then
     ADD_PREFIX=/usr/local
   else
@@ -546,7 +697,7 @@ if test "$with_threads" = "yes" -o "$with_threads" = "" ; then
 elif test "$with_threads" != "no" ; then
 
   THREAD_FLAG=CPL_MULTIPROC_PTHREAD
-  THREAD_LIB="$with_threads"  
+  THREAD_LIB="$with_threads"
 
   AC_CHECKING(whether we should include thread/mutex support...)
   AC_MSG_RESULT([        using threads with link options "$THREAD_LIB".])
@@ -561,7 +712,7 @@ if test "$THREAD_FLAG" = "CPL_MULTIPROC_PTHREAD" ; then
   PTHREAD_ENABLED="yes"
 fi
 
-LIBS="$THREAD_LIB $LIBS" 
+LIBS="$THREAD_LIB $LIBS"
 
 dnl ---------------------------------------------------------------------------
 dnl Check if mremap() with 5 args is available
@@ -718,7 +869,7 @@ AC_ARG_WITH(pg,
 
 if test "x$with_pg" = "xyes" -o "x$with_pg" = "x" ; then
   AC_PATH_PROG(PG_CONFIG, pg_config, no)
-else 
+else
   PG_CONFIG=$with_pg
 fi
 
@@ -746,7 +897,7 @@ else
   AC_MSG_RESULT([yes])
 
   AC_CHECK_LIB(pq,PQconnectdb,HAVE_PG=yes,HAVE_PG=no,-L`$PG_CONFIG --libdir`)
-  
+
   if test "${HAVE_PG}" = "yes" ; then
     LIBS=-L`$PG_CONFIG --libdir`" -lpq $LIBS"
     PG_INC=-I`$PG_CONFIG --includedir`" -I"`$PG_CONFIG --includedir-server`
@@ -801,9 +952,9 @@ if test "$with_grass" != "yes" -a "$with_grass" != "no" ; then
   if test "$GRASS_SETTING" = "no" ; then
     AC_CHECK_LIB(grass_gis,G_asprintf,GRASS_SETTING=grass57+,GRASS_SETTING=no,-L$with_grass/lib -lgrass_datetime)
   fi
-   
-  if test "$GRASS_SETTING" != "no" ; then   
-    if test "$GRASS_SETTING" = "grass70+" ; then   
+
+  if test "$GRASS_SETTING" != "no" ; then
+    if test "$GRASS_SETTING" = "grass70+" ; then
       G_RASTLIBS="-lgrass_raster -lgrass_imagery"
       G_VECTLIBS="-lgrass_vector -lgrass_dig2 -lgrass_dgl -lgrass_rtree -lgrass_linkm -lgrass_dbmiclient -lgrass_dbmibase"
       LIBS="-L$with_grass/lib $G_VECTLIBS $G_RASTLIBS -lgrass_gproj -lgrass_gmath -lgrass_gis -lgrass_datetime $LIBS"
@@ -828,7 +979,7 @@ elif test "$with_libgrass" = "yes" -o "$with_libgrass" = "" ; then
 
   AC_CHECK_LIB(grass5,G_gisinit_2,GRASS_SETTING=libgrass,GRASS_SETTING=no,)
 
-  if test "$GRASS_SETTING" = "libgrass" ; then   
+  if test "$GRASS_SETTING" = "libgrass" ; then
     LIBS="-lgrass5 $LIBS"
   fi
 
@@ -836,7 +987,7 @@ else
 
   AC_CHECK_LIB(grass5,G_gisinit_2,GRASS_SETTING=libgrass,GRASS_SETTING=no,-L$with_libgrass/lib)
 
-  if test "$GRASS_SETTING" = "libgrass" ; then   
+  if test "$GRASS_SETTING" = "libgrass" ; then
     LIBS="-L$with_libgrass -L$with_libgrass/lib -lgrass5 $LIBS"
     GRASS_INCLUDE="-I$with_libgrass -I$with_libgrass/include $EXTRA_INCLUDES"
   else
@@ -869,7 +1020,7 @@ elif test "$with_cfitsio" = "yes" -o "$with_cfitsio" = "" ; then
 
   AC_CHECK_LIB(cfitsio,ffopen,FITS_SETTING=external,FITS_SETTING=no,)
 
-  if test "$FITS_SETTING" = "external" ; then   
+  if test "$FITS_SETTING" = "external" ; then
     LIBS="-lcfitsio $LIBS"
     echo "using pre-installed libcfitsio."
   else
@@ -965,10 +1116,10 @@ elif test "$with_png" = "yes" -o "$with_png" = "" ; then
   AC_CHECK_LIB([png], [png_set_IHDR], [PNG_SETTING=external], [PNG_SETTING=internal], [$LIBS])
   AC_CHECK_HEADERS([png.h])
 
-  if test "$PNG_SETTING" = "external" -a "$ac_cv_header_png_h" = "no" ; then   
+  if test "$PNG_SETTING" = "external" -a "$ac_cv_header_png_h" = "no" ; then
     PNG_SETTING=internal
   fi
-  if test "$PNG_SETTING" = "external" ; then   
+  if test "$PNG_SETTING" = "external" ; then
     LIBS="-lpng $LIBS"
     echo "using pre-installed libpng."
   else
@@ -1070,18 +1221,18 @@ dnl ---------------------------------------------------------------------------
 dnl Select PCIDSK options.
 dnl ---------------------------------------------------------------------------
 
-AC_ARG_WITH([pcidsk], [  --with-pcidsk[=ARG]     Path to external PCIDSK SDK, or internal (default), or old],,)
+AC_ARG_WITH([pcidsk], [  --with-pcidsk[=ARG]     Path to external PCIDSK SDK or internal (default)],,)
 
 AC_MSG_CHECKING([for PCIDSK])
 
 PCIDSK_LIB=
 PCIDSK_INCLUDE=
 
-if test "$with_pcidsk" = "old" -o "$with_pcidsk" = "no" ; then
+if test "$with_pcidsk" = "no" ; then
 
-  PCIDSK_SETTING=old
+  PCIDSK_SETTING=no
 
-  echo "pcidsk support using pre-PCIDSK SDK (old) implementation."
+  echo "pcidsk support disabled."
 
 elif test "$with_pcidsk" = "" -o "$with_pcidsk" = "yes" -o "$with_pcidsk" = "internal" ; then
 
@@ -1099,9 +1250,13 @@ else
 
 fi
 
-AC_SUBST([PCIDSK_SETTING], [$PCIDSK_SETTING])
-AC_SUBST([PCIDSK_LIB], [$PCIDSK_LIB])
-AC_SUBST([PCIDSK_INCLUDE], [$PCIDSK_INCLUDE])
+if test "$with_pcidsk" != "no" ; then
+
+  AC_SUBST([PCIDSK_SETTING], [$PCIDSK_SETTING])
+  AC_SUBST([PCIDSK_LIB], [$PCIDSK_LIB])
+  AC_SUBST([PCIDSK_INCLUDE], [$PCIDSK_INCLUDE])
+
+fi
 
 dnl ---------------------------------------------------------------------------
 dnl Select a libtiff library to use.
@@ -1123,7 +1278,7 @@ if test "x${with_libtiff}" = "xyes" -o "x${with_libtiff}" = "x" ; then
     AC_CHECK_LIB(tiff,_TIFFsetDoubleArray,TIFF_SETTING=external,TIFF_SETTING=internal,)
   fi
 
-  if test "$TIFF_SETTING" = "external" ; then   
+  if test "$TIFF_SETTING" = "external" ; then
     LIBS="-ltiff $LIBS"
     AC_MSG_RESULT([using pre-installed libtiff.])
   else
@@ -1176,12 +1331,12 @@ if test "$with_geotiff" = "yes" -o "$with_geotiff" = "" ; then
   if test "$TIFF_SETTING" = "internal" ; then
     GEOTIFF_SETTING=internal
   else
-    dnl We now require libgeotiff 1.2.1 (for XTIFFClientOpen). 
+    dnl We now require libgeotiff 1.2.1 (for XTIFFClientOpen).
     AC_CHECK_LIB(geotiff,XTIFFClientOpen,GEOTIFF_SETTING=external,GEOTIFF_SETTING=internal)
 
   fi
 
-  if test "$GEOTIFF_SETTING" = "external" ; then   
+  if test "$GEOTIFF_SETTING" = "external" ; then
 
     dnl Now search for headers
     if test -r /usr/include/geotiff.h ; then
@@ -1218,7 +1373,7 @@ else
 
   GEOTIFF_SETTING=external
 
-  dnl We now require libgeotiff 1.2.1 (for XTIFFClientOpen). 
+  dnl We now require libgeotiff 1.2.1 (for XTIFFClientOpen).
   dnl first check if $with_geotiff/lib has the library:
   AC_CHECK_LIB(geotiff,XTIFFClientOpen,GEOTIFF_SETTING=external,GEOTIFF_SETTING=not_found,-L$with_geotiff/lib)
 
@@ -1279,7 +1434,7 @@ elif test "$with_jpeg" = "yes" -o "$with_jpeg" = "" ; then
     rm -f conftest*
   fi
 
-  if test "$JPEG_SETTING" = "external" ; then   
+  if test "$JPEG_SETTING" = "external" ; then
     LIBS="-ljpeg $LIBS"
     echo "using pre-installed libjpeg."
   else
@@ -1372,7 +1527,7 @@ elif test "$with_gif" = "yes" -o "$with_gif" = "" ; then
   AC_CHECK_LIB(gif,DGifOpenFileName,GIF_SETTING=external,GIF_SETTING=internal,)
   AC_CHECK_HEADERS(gif_lib.h)
 
-  if test "$GIF_SETTING" = "external" ; then   
+  if test "$GIF_SETTING" = "external" ; then
     LIBS="-lgif $LIBS"
     echo "using pre-installed libgif."
   else
@@ -1434,12 +1589,12 @@ elif test "$with_ogdi" = "yes" -o "$with_ogdi" = "" ; then
 
   if test "$OGDI_INCLUDE" != "" -o "$ac_cv_header_ecs_h" = "yes"; then
     AC_CHECK_LIB(ogdi,cln_GetLayerCapabilities,HAVE_OGDI=yes,HAVE_OGDI=no,)
-    if test "$HAVE_OGDI" = "yes" ; then   
+    if test "$HAVE_OGDI" = "yes" ; then
       LIBS="-logdi $LIBS"
     else
       dnl For backward compatibility. Retry with ogdi31 as a name
       AC_CHECK_LIB(ogdi31,cln_GetLayerCapabilities,HAVE_OGDI=yes,HAVE_OGDI=no,)
-      if test "$HAVE_OGDI" = "yes" ; then   
+      if test "$HAVE_OGDI" = "yes" ; then
         LIBS="-logdi31 $LIBS"
       fi
     fi
@@ -1506,33 +1661,33 @@ elif test "$with_fme" = "yes" ; then
 
   if test "$FME_HOME" = "" ; then
     AC_MSG_ERROR([no, FME_HOME not defined!])
-  elif test -f $FME_HOME/fmeobjects/cpp/isession.h ; then 
+  elif test -f $FME_HOME/fmeobjects/cpp/isession.h ; then
     AC_MSG_RESULT([yes])
     X_FME_HOME=$FME_HOME
   else
     AC_MSG_ERROR([FME_HOME defined, but $FME_HOME/fmeobjects/cpp/issesion.h not found.])
   fi
-    
+
 elif test "$with_fme" = "" ; then
 
   if test "$FME_HOME" = "" ; then
     AC_MSG_RESULT([no])
-  elif test -f $FME_HOME/fmeobjects/cpp/isession.h ; then 
+  elif test -f $FME_HOME/fmeobjects/cpp/isession.h ; then
     AC_MSG_RESULT([yes])
     X_FME_HOME=$FME_HOME
   else
     AC_MSG_RESULT([no, FME_HOME defined, but $FME_HOME/fmeobjects/cpp/issesion.h not found.])
   fi
-    
+
 else
 
-  if test -f $with_fme/fmeobjects/cpp/isession.h ; then 
+  if test -f $with_fme/fmeobjects/cpp/isession.h ; then
     AC_MSG_RESULT([yes])
     X_FME_HOME=$with_fme
   else
     AC_MSG_ERROR([$with_fme/fmeobjects/cpp/issesion.h not found!])
   fi
-  
+
 fi
 
 AC_SUBST(X_FME_HOME,$X_FME_HOME)
@@ -1596,10 +1751,82 @@ AC_SUBST(SOSI_LIB, $SOSI_LIB)
 AC_SUBST(SOSI_INC, $SOSI_INC)
 
 dnl ---------------------------------------------------------------------------
+dnl MongoCXX driver
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(mongocxx,[  --with-mongocxx[=ARG]        Include MongoCXX support (ARG=Path, yes or no)],,)
+
+MONGODB_ENABLED=no
+
+if test "$with_mongocxx" = "no" ; then
+
+  echo "MONGODB support disabled."
+
+elif test "$with_mongocxx" = "yes" -o "$with_mongocxx" = "" ; then
+
+    AC_MSG_CHECKING([for MongoCXX])
+
+    rm -f testmongocxx.*
+    rm -f testmongocxx
+    echo "#include <mongo/client/dbclient.h>" > testmongocxx.cpp
+    echo "using namespace mongo;" >> testmongocxx.cpp
+    echo "int main() { client::initialize(client::Options()); return 0; }" >> testmongocxx.cpp
+    if test -z "`${CXX} ${CPPFLAGS} testmongocxx.cpp -lmongoclient -lboost_system -lboost_thread -lboost_regex -o testmongocxx 2>&1`" ; then
+        AC_MSG_RESULT([MongoCXX found])
+        MONGODB_ENABLED="yes"
+        MONGODB_LIB=" -lmongoclient -lboost_system -lboost_thread -lboost_regex"
+    else
+        if test "$with_mongocxx" = "yes"; then
+            AC_MSG_ERROR([MongoCXX not found.])
+        else
+            AC_MSG_RESULT([MongoCXX not found.])
+        fi
+    fi
+    rm -f testmongocxx.*
+    rm -f testmongocxx
+
+else
+
+  AC_ARG_WITH(boost-lib-path,
+          [  --with-boost-lib-path=ARG   Path to boost libraries for mongocxx client],,,)
+
+  AC_MSG_CHECKING([for libmongoclient.so in in $with_mongocxx/lib])
+  MONGODB_ENABLED=yes
+  if test -r $with_mongocxx/lib/libmongoclient.so; then
+    AC_MSG_RESULT([found.])
+    MONGODB_LIB="-L$with_mongocxx/lib -lmongoclient"
+  elif test -r $with_mongocxx/lib/libmongoclient.dylib; then
+    AC_MSG_RESULT([found.])
+    MONGODB_LIB="-L$with_mongocxx/lib -lmongoclient"
+  else
+    AC_MSG_ERROR([not found.])
+  fi
+
+  if test "$with_boost_lib_path" = "" ; then
+    MONGODB_LIB="$MONGODB_LIB -lboost_system -lboost_thread -lboost_regex"
+  else
+    MONGODB_LIB="$MONGODB_LIB -L$with_boost_lib_path -lboost_system -lboost_thread -lboost_regex"
+  fi
+
+  AC_MSG_CHECKING([for mongo/client/dbclient.h in $with_mongocxx/include])
+  if test -r $with_mongocxx/include/mongo/client/dbclient.h ; then
+    AC_MSG_RESULT([found.])
+    MONGODB_INC="-I$with_mongocxx/include"
+  else
+    AC_MSG_ERROR([not found.])
+  fi
+
+fi
+
+AC_SUBST(MONGODB_ENABLED, $MONGODB_ENABLED)
+AC_SUBST(MONGODB_LIB, $MONGODB_LIB)
+AC_SUBST(MONGODB_INC, $MONGODB_INC)
+
+dnl ---------------------------------------------------------------------------
 dnl Select an HDF4 Library to use, or disable driver.
 dnl
 dnl We assume the user will have libjpeg and libz from other sources when
-dnl linking against static HDF4 libraries. 
+dnl linking against static HDF4 libraries.
 dnl ---------------------------------------------------------------------------
 
 HDF4_INCLUDE=""
@@ -1734,11 +1961,11 @@ elif test "$with_hdf5" = "yes" -o "$with_hdf5" = "" ; then
 
   AC_CHECK_LIB(hdf5,H5Fopen,HAVE_HDF5=yes,HAVE_HDF5=no,)
 
-  if test "$HAVE_HDF5" = "yes" ; then   
+  if test "$HAVE_HDF5" = "yes" ; then
     LIBS="-lhdf5 $LIBS"
   fi
 
-dnl Some Linux distros install hdf include files here. 
+dnl Some Linux distros install hdf include files here.
   if test "$HAVE_HDF5" = "yes" -a -r /usr/include/hdf5.h ; then
     HDF5_INCLUDE="-I/usr/include"
   fi
@@ -1820,7 +2047,7 @@ else
   HAVE_KEA=yes
   KEA_LIB="`$KEA_CONFIG --libs --hdflibs`"
   KEA_INC="`$KEA_CONFIG --cflags --hdfcflags`"
-  AC_MSG_RESULT([yes]) 
+  AC_MSG_RESULT([yes])
 fi
 
 AC_SUBST(HAVE_KEA,$HAVE_KEA)
@@ -1869,7 +2096,7 @@ else
     echo "did not get netCDF version from $NETCDF_NCCONFIG ... using fallback"
     NETCDF_NCCONFIG=
   fi
-  
+
   dnl test linking using flags from nc-config
   if test "$NETCDF_NCCONFIG" != "" ; then
 
@@ -1877,9 +2104,9 @@ else
     NETCDF_VERSION=`$NETCDF_NCCONFIG --version`
     NETCDF_PREFIX=`$NETCDF_NCCONFIG --prefix`
     NETCDF_INCLUDEDIR=`$NETCDF_NCCONFIG --includedir`
-    NETCDF_LIBS=`$NETCDF_NCCONFIG --libs` 
+    NETCDF_LIBS=`$NETCDF_NCCONFIG --libs`
     echo ""
-    AC_MSG_RESULT([ got version="$NETCDF_VERSION", prefix="$NETCDF_PREFIX", 
+    AC_MSG_RESULT([ got version="$NETCDF_VERSION", prefix="$NETCDF_PREFIX",
  libs="$NETCDF_LIBS", includedir="$NETCDF_INCLUDEDIR"])
 
     AC_CHECK_LIB([netcdf], [nc_open], [NETCDF_SETTING=yes], [NETCDF_SETTING=no], $NETCDF_LIBS)
@@ -2019,7 +2246,7 @@ elif test "$with_jasper" = "yes" -o "$with_jasper" = "" ; then
   AC_CHECK_LIB(jasper,jp2_decode,HAVE_JASPER=yes,HAVE_JASPER=no,)
   AC_CHECK_LIB(jasper,pgx_decode,HAVE_JASPER=yes,HAVE_JASPER=no,)
 
-  if test "$HAVE_JASPER" = "yes" ; then   
+  if test "$HAVE_JASPER" = "yes" ; then
     LIBS="-ljasper $LIBS"
   fi
 else
@@ -2033,7 +2260,7 @@ fi
 
 if test "$HAVE_JASPER" != "no" ; then
   OPT_GDAL_FORMATS="jpeg2000 $OPT_GDAL_FORMATS"
-  
+
   dnl Test whether we have UUID JasPer hack
 
   AC_CHECK_LIB(jasper,jp2_encode_uuid,HAVE_JASPER_UUID=yes,HAVE_JASPER_UUID=no,)
@@ -2157,7 +2384,7 @@ else
   fi
 
   AC_MSG_CHECKING([for FileGDBAPI.h in $with_fgdb/include])
-  if test -r $with_fgdb/include/FileGDBAPI.h ; then  
+  if test -r $with_fgdb/include/FileGDBAPI.h ; then
     AC_MSG_RESULT([found.])
     FGDB_INC="-I$with_fgdb/include"
   else
@@ -2195,13 +2422,13 @@ elif test "$with_ecw" = "yes" -o "$with_ecw" = "" ; then
 
   AC_CHECK_LIB(NCSEcw,NCScbmOpenFileView,ECW_SETTING=yes,ECW_SETTING=no,-lNCSCnet -lNCSUtil)
 
-  if test "$ECW_SETTING" = "yes" ; then   
+  if test "$ECW_SETTING" = "yes" ; then
     ECW_LIBS="-lNCSEcw -lNCSEcwC -lNCSCnet -lNCSUtil"
   fi
 
   if test "$ECW_SETTING" = "no" ; then
     AC_CHECK_LIB(ecwj2,NCScbmOpenFileView,ECW_SETTING=yes,ECW_SETTING=no,$CARBON_FRAMEWORK)
-    if test "$ECW_SETTING" = "yes" ; then   
+    if test "$ECW_SETTING" = "yes" ; then
       ECW_LIBS="-lecwj2 $CARBON_FRAMEWORK"
     fi
   fi
@@ -2212,7 +2439,7 @@ else
   ECW_CONF="release"
   ECW_FLAGS="-DLINUX -DX86 -DPOSIX -DHAVE_COMPRESS -DECW_COMPRESS_RW_SDK_VERSION"
   ECW_FRAMEWORK_COCOA=""
-  if test "`arch`" = "x86_64" ; then 
+  if test "`arch`" = "x86_64" ; then
     ECW_ARCH="x64"
   fi
   if test ! -z "`uname | grep Darwin`" ; then
@@ -2221,7 +2448,7 @@ else
     ECW_FLAGS=""
     ECW_FRAMEWORK_COCOA=" -framework Cocoa "
   fi
-  
+
   ECW_SETTING=yes
   if test -r $with_ecw/lib/libNCSCnet.so -o -r $with_ecw/lib/libNCSCnet.dylib ; then
     ECW_LIBS="-L$with_ecw/lib -lNCSEcw -lNCSEcwC -lNCSCnet -lNCSUtil"
@@ -2258,14 +2485,14 @@ else
   fi
 
   AC_MSG_CHECKING([for NCSECWClient.h in $with_ecw/include])
-  if test -r $with_ecw/include/NCSECWClient.h ; then  
+  if test -r $with_ecw/include/NCSECWClient.h ; then
     AC_MSG_RESULT([found.])
     ECW_INCLUDE="-I$with_ecw/include"
   else
     AC_MSG_ERROR([not found.])
   fi
   AC_MSG_CHECKING([for ECWJP2BuildNumber.h in $with_ecw/include])
-  if test -r $with_ecw/include/ECWJP2BuildNumber.h ; then  
+  if test -r $with_ecw/include/ECWJP2BuildNumber.h ; then
     AC_MSG_RESULT([found.])
     ECW_FLAGS="-DHAVE_ECW_BUILDNUMBER_H $ECW_FLAGS"
   else
@@ -2296,7 +2523,7 @@ if test "$with_kakadu" = "no" -o "$with_kakadu" = "" ; then
   HAVE_KAKADU=no
 elif test "$with_kakadu" = "yes" ; then
   AC_MSG_ERROR([
-For JPEG2000 support using Kakadu you need provide the path to the Kakadu 
+For JPEG2000 support using Kakadu you need provide the path to the Kakadu
 build directory.  Note that Kakadu is *not* free software.])
 else
   KAKDIR=$with_kakadu
@@ -2398,10 +2625,10 @@ else
     MRSID_KAKADU_LIB=""
     if test "$HAVE_KAKADU" = "no" ; then
       if test x"$with_jp2mrsid" = x"" -o x"$with_jp2mrsid" = x"yes" ; then
-        if test -r "$with_mrsid/3rd-party/$_LIBPART/libltikdu.a" ; then 
+        if test -r "$with_mrsid/3rd-party/$_LIBPART/libltikdu.a" ; then
           with_jp2mrsid=yes
           MRSID_KAKADU_LIB=-lltikdu
-        elif test -r "$with_mrsid/3rd-party/$_LIBPART/liblt_kakadu.a" ; then 
+        elif test -r "$with_mrsid/3rd-party/$_LIBPART/liblt_kakadu.a" ; then
           with_jp2mrsid=yes
           MRSID_KAKADU_LIB=-llt_kakadu
         elif test -e "$with_mrsid/lib/libltidsdk.so" \
@@ -2497,7 +2724,7 @@ AC_ARG_WITH([msg],
 HAVE_MSG=no
 HAVE_EUMETSATWT=no
 
-if test "x$with_msg" = "xyes" ; then 
+if test "x$with_msg" = "xyes" ; then
     AC_MSG_CHECKING([for EUMETSAT Wavelet Transformation Software])
 
     if test -d "frmts/msg/PublicDecompWT" -a \
@@ -2512,7 +2739,7 @@ fi
 AC_MSG_CHECKING([for MSG])
 
 if test "x$with_msg" = "xyes" -o "x$with_msg" = "x" \
-    -a "x$HAVE_EUMETSATWT" = "xyes"; then 
+    -a "x$HAVE_EUMETSATWT" = "xyes"; then
     OPT_GDAL_FORMATS="msg $OPT_GDAL_FORMATS"
     HAVE_MSG=yes
     AC_MSG_RESULT([enabled])
@@ -2577,16 +2804,26 @@ AC_SUBST([OPT_GDAL_FORMATS], [$OPT_GDAL_FORMATS])
 
 dnl ---------------------------------------------------------------------------
 
-AC_ARG_WITH(ogr,[  --without-ogr         Don't build OGR into shared library],,)
+dnl Always build with OGR support.
+OGR_ENABLED=yes
+
+dnl ---------------------------------------------------------------------------
+
+GNM_ENABLED=no
 
-if test "$with_ogr" = yes -o x"$with_ogr" = x ; then
-  echo checking for OGR ... enabled
-  OGR_ENABLED=yes
+AC_ARG_WITH(gnm,[  --with-gnm            Build GNM into shared library],,)
+
+if test "$with_gnm" = "" ; then
+  GNM_ENABLED=no
+  echo "GNM support disabled."
+elif test "$with_gnm" = "yes"; then
+  echo checking for GNM ... enabled
+  GNM_ENABLED=yes
 else
-  echo checking for OGR ... disabled by user
-  OGR_ENABLED=no
+  echo checking for GNM ... disabled by user
+  GNM_ENABLED=no
 fi
-AC_SUBST(OGR_ENABLED,$OGR_ENABLED)
+AC_SUBST(GNM_ENABLED,$GNM_ENABLED)
 
 dnl ---------------------------------------------------------------------------
 dnl Select an MySQL Library to use, or disable driver.
@@ -2635,7 +2872,7 @@ else
       HAVE_MYSQL=yes
       MYSQL_LIB="`$MYSQL_CONFIG --libs`"
       MYSQL_INC="`$MYSQL_CONFIG --include`"
-      AC_MSG_RESULT([yes]) 
+      AC_MSG_RESULT([yes])
   fi
 fi
 
@@ -2663,7 +2900,7 @@ else
   HAVE_INGRES=yes
   II_SYSTEM=$with_ingres
   INGRES_LIB="-L$II_SYSTEM/ingres/lib \
-	-liiapi.1 -lcompat.1 -lq.1 -lframe.1" 
+	-liiapi.1 -lcompat.1 -lq.1 -lframe.1"
   INGRES_INC=-I$II_SYSTEM/ingres/files
 fi
 
@@ -2685,7 +2922,7 @@ fi
 
 AC_SUBST([HAVE_XERCES], $HAVE_XERCES)
 AC_SUBST([XERCES_INCLUDE], $XERCES_CFLAGS)
-  
+
 dnl ---------------------------------------------------------------------------
 dnl Enable NAS if we have Xerces.
 dnl ---------------------------------------------------------------------------
@@ -2725,7 +2962,7 @@ fi
 
 AC_SUBST([HAVE_LIBKML], $HAVE_LIBKML)
 AC_SUBST([LIBKML_INCLUDE], $LIBKML_CFLAGS)
-  
+
 dnl ---------------------------------------------------------------------------
 dnl Check for ODBC support.
 dnl ---------------------------------------------------------------------------
@@ -2739,27 +2976,51 @@ if test "$with_odbc" = "no" ; then
   echo "ODBC support disabled."
 
 elif test "$with_odbc" = "yes" -o "$with_odbc" = "" ; then
+  ODBC_SETTING=no
+
+  echo "check for unixODBC"
+  AC_CHECK_LIB(odbc,SQLConnect,[ODBC_LIBS="-lodbc -lodbcinst"])
+  AC_CHECK_LIB(odbcinst,SQLInstallDriverEx,ODBC_SETTING=yes)
 
-  AC_CHECK_LIB(odbc,SQLConnect,ODBC_SETTING=yes,ODBC_SETTING=no,)
-  AC_CHECK_LIB(odbcinst,SQLInstallDriverEx,ODBC_SETTING=yes,ODBC_SETTING=no,)
+  if test "$ODBC_SETTING" = "no" ; then
+    echo "check for windows ODBC"
+    AC_CHECK_LIB(odbc32,main,[ODBC_LIBS="-lodbc32 -lodbccp32"])
+    AC_CHECK_LIB(odbccp32,SQLInstallDriverEx,ODBC_SETTING=yes)
+  fi
 
   if test "$ODBC_SETTING" = "yes" ; then
-    if test -f /usr/local/include/sql.h -o -f /usr/include/sql.h ; then
-      ODBC_SETTING=yes
-    else
-      echo "odbc library found, but sql.h missing, ODBC support disabled." 
-      ODBC_SETTING=no
+    AC_CHECK_HEADERS(sql.h,,[ODBC_SETTING=no],
+[#ifdef _WIN32
+# include <windows.h>
+#endif
+])
+    if test "$ODBC_SETTING" = "no" ; then
+      if test -f /usr/local/include/sql.h ; then
+        ODBC_SETTING=yes
+        echo "using sql.h from /usr/local/include"
+      elif test -f /usr/include/sql.h ; then
+        ODBC_SETTING=yes
+        echo "using sql.h from /usr/include"
+      else
+        echo "sql.h not found"
+      fi
     fi
   fi
 
-  if test "$ODBC_SETTING" = "yes"  ; then   
-    LIBS="-lodbc -lodbcinst $LIBS"
+  if test "$ODBC_SETTING" = "yes"  ; then
+    LIBS="$ODBC_LIBS $LIBS"
   fi
 
 else
 
   ODBC_SETTING=yes
-  LIBS="-L$with_odbc -L$with_odbc/lib -lodbc -lodbcinst $LIBS"
+  ODBC_LIBS=""
+  AC_CHECK_LIB(odbc,SQLConnect,ODBC_LIBS="-lodbc -lodbcinst")
+  AC_CHECK_LIB(odbc32,main,ODBC_LIBS="-lodbc32 -lodbccp32")
+  if test "$ODBC_LIBS" = ""; then
+    AC_MSG_ERROR([Cannot find ODBC libs])
+  fi
+  LIBS="-L$with_odbc -L$with_odbc/lib $ODBC_LIBS $LIBS"
   EXTRA_INCLUDES="-I$with_odbc -I$with_odbc/include $EXTRA_INCLUDES"
 
   echo "using odbc library from $with_odbc."
@@ -2788,7 +3049,7 @@ dnl ---------------------------------------------------------------------------
 
 HAVE_DODS=no
 
-AC_MSG_CHECKING(Checking for DODS)
+AC_MSG_CHECKING(for DODS)
 AC_ARG_WITH(dods_root,
     [  --with-dods-root[=ARG]  Include DODS support (ARG=no or absolute path)],
     ,,)
@@ -2811,7 +3072,7 @@ else
         dnl libs from dap-config gets added further down
         AC_MSG_RESULT([libdap $LIBDAP_VER])
     else
-        dnl Check the version by compiling test programs 
+        dnl Check the version by compiling test programs
 
         dnl Test if we have libdap >= 3.10
         dnl From libdap 3.10, AISConnect.h has been renamed as Connect.h
@@ -2848,16 +3109,16 @@ else
 
 
     dnl Add the DODS libraries to LIBS
-    if test -x $DODS_BIN/opendap-config ; then 
+    if test -x $DODS_BIN/opendap-config ; then
       dnl OPeNDAP 3.4 and earlier lack opendap-config, but use it if avail.
       LIBS="$LIBS `$DODS_BIN/opendap-config --libs`"
-    elif test -x $DODS_BIN/dap-config ; then 
+    elif test -x $DODS_BIN/dap-config ; then
       dnl OPeNDAP 3.4 and earlier lack opendap-config, but use it if avail.
       LIBS="$LIBS `$DODS_BIN/dap-config --libs`"
     else
       dnl Otherwise try to put things together in a more primitive way.
       LIBS="$LIBS -L$DODS_LIB -ldap++ -lpthread -lrx"
-    
+
       dnl Add curl to LIBS; it might be local to DODS or generally installed
       if test -x $DODS_BIN/curl-config; then
           LIBS="$LIBS  `$DODS_BIN/curl-config --libs`"
@@ -2873,7 +3134,7 @@ else
           LIBS="$LIBS  `xml2-config --libs`"
       else
           AC_MSG_ERROR([You gave a dods root, but I can't find xml2!])
-      fi 
+      fi
     fi
 
     OPT_GDAL_FORMATS="dods $OPT_GDAL_FORMATS"
@@ -2886,7 +3147,7 @@ dnl This is used by the GNUmakefile in frmts/dods (via GDALmake.opt)
 AC_SUBST(DODS_INC)
 
 dnl ---------------------------------------------------------------------------
-dnl Check for curl (ie. for wcs).
+dnl Check for curl (i.e. for wcs).
 dnl ---------------------------------------------------------------------------
 CURL_SETTING=no
 CURL_INC=
@@ -2912,16 +3173,16 @@ if test "$LIBCURL_CONFIG" != "no" ; then
   CURL_VER=`$LIBCURL_CONFIG --version | awk '{print $2}'`
 
   AC_MSG_RESULT([        found libcurl version $CURL_VER])
-  
+
   AC_CHECK_LIB(curl,curl_global_init,CURL_SETTING=yes,CURL_SETTING=no,`$LIBCURL_CONFIG --libs`)
 
 fi
 
 if test "$CURL_SETTING" = "yes" ; then
-  
+
   CURL_INC=`$LIBCURL_CONFIG --cflags`
   CURL_LIB=`$LIBCURL_CONFIG --libs`
-  OPT_GDAL_FORMATS="wcs wms plmosaic $OPT_GDAL_FORMATS"
+  OPT_GDAL_FORMATS="wcs wms plmosaic wmts $OPT_GDAL_FORMATS"
 
 fi
 
@@ -2969,8 +3230,14 @@ dnl ---------------------------------------------------------------------------
 dnl Check for SpatiaLite.
 dnl ---------------------------------------------------------------------------
 
+AC_MSG_CHECKING(for spatialite)
+
 AC_ARG_WITH(spatialite,
-    [  --with-spatialite=ARG Include SpatiaLite support (ARG=no(default), yes or path)],
+    [  --with-spatialite=ARG Include SpatiaLite support (ARG=no(default), yes, dlopen (only supported for Spatialite >= 4.1.2) or path)],
+    ,,)
+
+AC_ARG_WITH(spatialite-soname,
+    [  --with-spatialite-soname=ARG Spatialite shared object name (e.g. libspatialite.so), only used if --with-spatiliate=dlopen],
     ,,)
 
 HAVE_SPATIALITE=no
@@ -2995,6 +3262,15 @@ elif test "$with_spatialite" = "yes"; then
             AC_MSG_RESULT(not found : spatialite support disabled)
         fi
     fi
+elif test "$with_spatialite" = "dlopen"; then
+  HAVE_SPATIALITE=dlopen
+  AC_MSG_RESULT(dlopen)
+
+  if test "$with_spatialite_soname" != ""; then
+      SPATIALITE_SONAME="$with_spatialite_soname"
+  else
+      SPATIALITE_SONAME="spatialite.so"
+  fi
 else
     AC_CHECK_LIB(spatialite,spatialite_init,SPATIALITE_INIT_FOUND=yes,SPATIALITE_INIT_FOUND=no,-L$with_spatialite/lib -lspatialite)
     if test -f "$with_spatialite/include/spatialite.h" -a \
@@ -3016,14 +3292,18 @@ else
 
     elif test -f "$with_spatialite/include/spatialite.h" -a \
         "$SPATIALITE_INIT_FOUND" = "yes"; then
-        AC_CHECK_HEADERS(sqlite3.h)
-        if test "$ac_cv_header_sqlite3_h" = "yes"; then
-            AC_MSG_RESULT(enabled)
+
+        SQLITE3_REQ_VERSION="3.0.0"
+        AX_LIB_SQLITE3($SQLITE3_REQ_VERSION)
+
+        if test "$HAVE_SQLITE3" = "yes"; then
             SPATIALITE_INC="-I$with_spatialite/include"
             HAVE_SPATIALITE=yes
-            SPATIALITE_LIBS="-L$with_spatialite/lib -lspatialite -lsqlite3"
-            LIBS="$LIBS $SPATIALITE_LIBS"
-            HAVE_SQLITE3=yes
+            SPATIALITE_LIBS="-L$with_spatialite/lib -lspatialite"
+            LIBS="$SQLITE3_LDFLAGS $LIBS $SPATIALITE_LIBS"
+            AC_MSG_RESULT(spatialite enabled)
+        else
+            AC_MSG_RESULT(spatialite disabled)
         fi
     else
         AC_MSG_RESULT(disabled)
@@ -3038,6 +3318,7 @@ if test "$HAVE_SPATIALITE" = "yes"; then
 fi
 
 AC_SUBST([HAVE_SPATIALITE], $HAVE_SPATIALITE)
+AC_SUBST([SPATIALITE_SONAME], $SPATIALITE_SONAME)
 AC_SUBST([SPATIALITE_INC], $SPATIALITE_INC)
 AC_SUBST([SPATIALITE_AMALGAMATION], $SPATIALITE_AMALGAMATION)
 AC_SUBST([SPATIALITE_412_OR_LATER], $SPATIALITE_412_OR_LATER)
@@ -3046,7 +3327,7 @@ dnl ---------------------------------------------------------------------------
 dnl Check for SQLite (only if SpatiaLite is not detected)
 dnl ---------------------------------------------------------------------------
 
-if test "${HAVE_SPATIALITE}" = "no" ; then
+if test "${HAVE_SPATIALITE}" = "no" -o "${HAVE_SPATIALITE}" = "dlopen" ; then
     SQLITE3_REQ_VERSION="3.0.0"
     AX_LIB_SQLITE3($SQLITE3_REQ_VERSION)
 
@@ -3109,7 +3390,7 @@ AC_MSG_CHECKING(Checking for DWGdirect)
 AC_ARG_WITH(dwgdirect,
     [  --with-dwgdirect[=path] Include DWG direct support],
     ,,)
-    
+
 if test -z "$with_dwgdirect" -o "$with_dwgdirect" = "no"; then
     AC_MSG_RESULT(disabled)
     HAVE_DWGDIRECT=no
@@ -3262,7 +3543,7 @@ if test "$with_epsilon" = "yes" ; then
 
   AC_CHECK_LIB(epsilon,eps_read_block_header,EPSILON_SETTING=yes,EPSILON_SETTING=no,)
 
-  if test "$EPSILON_SETTING" = "yes" ; then   
+  if test "$EPSILON_SETTING" = "yes" ; then
     LIBS="-lepsilon $LIBS"
   else
     echo "libepsilon not found - EPSILON support disabled"
@@ -3272,7 +3553,7 @@ elif test "$with_epsilon" != "no" -a "$with_epsilon" != ""; then
 
   AC_CHECK_LIB(epsilon,eps_read_block_header,EPSILON_SETTING=yes,EPSILON_SETTING=no,-L$with_epsilon/lib -lepsilon)
 
-  if test "$EPSILON_SETTING" = "yes" ; then   
+  if test "$EPSILON_SETTING" = "yes" ; then
     LIBS="-L$with_epsilon/lib -lepsilon $LIBS"
     EXTRA_INCLUDES="-I$with_epsilon/include $EXTRA_INCLUDES"
   else
@@ -3334,6 +3615,48 @@ if test "${HAVE_GEOS}" = "yes" ; then
 fi
 
 dnl ---------------------------------------------------------------------------
+dnl Check if QHull library is available.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(qhull,[  --with-qhull[=ARG]     Include QHull support (ARG=no, yes, internal)],,)
+
+QHULL_SETTING=no
+
+if test "$with_qhull" = "no" ; then
+
+  AC_MSG_NOTICE([QHull support disabled.])
+
+elif test "$with_qhull" = "yes" -o "$with_qhull" = "" ; then
+
+  # Only qhull 2012 is reliable on certain datasets. Older Ubuntu have
+  # qhull/qhull.h
+  AC_CHECK_HEADERS([qhull/libqhull.h])
+  if test "$ac_cv_header_qhull_libqhull_h" = "yes"; then
+    AC_CHECK_LIB(qhull,qh_new_qhull,QHULL_SETTING=yes,QHULL_SETTING=no,)
+    if test "$QHULL_SETTING" = "yes"; then
+        QHULL_SETTING=external
+        if test -f /usr/include/qhull/libqhull.h; then
+            EXTRA_INCLUDES="-I/usr/include/qhull $EXTRA_INCLUDES"
+        else
+            EXTRA_INCLUDES="-I/usr/include/local/qhull $EXTRA_INCLUDES"
+        fi
+        LIBS="-lqhull $LIBS"
+    fi
+  fi
+  if test "$QHULL_SETTING" = "no" ; then
+    if test "$with_qhull" = "yes"; then
+        AC_MSG_ERROR([--with-qhull requested, but library not found!])
+    else
+        QHULL_SETTING=internal
+    fi
+  fi
+else
+  QHULL_SETTING=internal
+fi
+
+AC_SUBST([QHULL_SETTING],$QHULL_SETTING)
+
+dnl ---------------------------------------------------------------------------
 dnl Check if opencl library is available.
 dnl ---------------------------------------------------------------------------
 
@@ -3364,10 +3687,10 @@ if test "$with_opencl" = "yes" ; then
   else
     OPENCL_FLAGS="-I$with_opencl_include -DHAVE_OPENCL"
   fi
-    
+
   AC_ARG_WITH(opencl-lib,
-      [  --with-opencl-lib=ARG   OpenCL Link Flags (ie. -L/xxx -lOpenCL)],,,)
-     
+      [  --with-opencl-lib=ARG   OpenCL Link Flags (i.e. -L/xxx -lOpenCL)],,,)
+
   if test "x$with_opencl_lib" = "x" ; then
     if test ! -z "`uname | grep Darwin`" ; then
       OPENCL_LIB="-framework OpenCL"
@@ -3553,6 +3876,29 @@ fi
 AC_SUBST(PAM_SETTING, $PAM_SETTING)
 
 dnl ---------------------------------------------------------------------------
+dnl Check if the PDF driver should be built as a plugin
+dnl ---------------------------------------------------------------------------
+
+AC_MSG_CHECKING([whether to build PDF driver as a plugin])
+
+AC_ARG_ENABLE(pdf_plugin,
+              AS_HELP_STRING([--enable-pdf-plugin],
+                             [enable PDF driver as a plugin (included in libgdal by default)]),,)
+
+PDF_PLUGIN=no
+if test "x$enable_pdf_plugin" = "xyes" ; then
+
+  PDF_PLUGIN=yes
+
+  AC_MSG_RESULT([yes])
+else
+  AC_MSG_RESULT([no])
+fi
+
+AC_SUBST(PDF_PLUGIN, $PDF_PLUGIN)
+
+
+dnl ---------------------------------------------------------------------------
 dnl Check if libpoppler is available
 dnl ---------------------------------------------------------------------------
 
@@ -3593,9 +3939,12 @@ if test "$with_poppler" != "no" -a "$with_poppler" != ""; then
     fi
 
     if test "$HAVE_POPPLER" = "yes"; then
-        LIBS="${TEST_POPPLER_LIB} ${LIBS}"
+        if test "$PDF_PLUGIN" = "no"; then
+            LIBS="${TEST_POPPLER_LIB} ${LIBS}"
+        fi
         AC_MSG_RESULT([yes])
         POPPLER_INC=$TEST_POPPLER_INC
+        POPPLER_PLUGIN_LIB="${TEST_POPPLER_LIB}"
 
         # And now try another dirty thing, but this one is
         # optional.
@@ -3676,6 +4025,7 @@ AC_SUBST(POPPLER_BASE_STREAM_HAS_TWO_ARGS, $POPPLER_BASE_STREAM_HAS_TWO_ARGS)
 AC_SUBST(POPPLER_0_20_OR_LATER, $POPPLER_0_20_OR_LATER)
 AC_SUBST(POPPLER_0_23_OR_LATER, $POPPLER_0_23_OR_LATER)
 AC_SUBST(POPPLER_INC, $POPPLER_INC)
+AC_SUBST(POPPLER_PLUGIN_LIB, $POPPLER_PLUGIN_LIB)
 
 dnl ---------------------------------------------------------------------------
 dnl Check if libpodofo is available
@@ -3690,7 +4040,7 @@ AC_MSG_CHECKING([for podofo])
 if test "$with_podofo" != "no" -a "$with_podofo" != ""; then
 
     AC_ARG_WITH(podofo-lib,
-      [  --with-podofo-lib=ARG   podofo Link Flags (ie. -L/xxx -lpodofo ...). Mainly for static libpodofo],,,)
+      [  --with-podofo-lib=ARG   podofo Link Flags (i.e. -L/xxx -lpodofo ...). Mainly for static libpodofo],,,)
 
     if test "$with_podofo" = "yes" ; then
         TEST_PODOFO_INC="-I/usr/include -I/usr/include/podofo"
@@ -3704,10 +4054,15 @@ if test "$with_podofo" != "no" -a "$with_podofo" != ""; then
         rm -f testpodofo.*
         echo '#include <podofo.h>' > testpodofo.cpp
         echo 'int main(int argc, char** argv) { PoDoFo::PdfError::EnableDebug( 0 ); return 0; } ' >> testpodofo.cpp
-        if test -z "`${CXX} testpodofo.cpp -o testpodofo ${TEST_PODOFO_INC} ${PODOFO_LIB}  2>&1`" ; then
+        ${CXX} testpodofo.cpp -o testpodofo ${TEST_PODOFO_INC} ${PODOFO_LIB} 2>/dev/null
+        RETVAL=$?
+        if test $RETVAL -eq 0; then
             HAVE_PODOFO=yes
-            LIBS="${PODOFO_LIB} ${LIBS}"
+            if test "$PDF_PLUGIN" = "no"; then
+                LIBS="${PODOFO_LIB} ${LIBS}"
+            fi
             PODOFO_INC=$TEST_PODOFO_INC
+            PODOFO_PLUGIN_LIB="${PODOFO_LIB}"
             AC_MSG_RESULT([yes])
         fi
         rm -f testpodofo.*
@@ -3718,12 +4073,12 @@ if test "$with_podofo" != "no" -a "$with_podofo" != ""; then
         if test "x$with_podofo_lib" != "x" ; then
             PODOFO_LIB="$with_podofo_lib"
         else
-            # This may be a static libpodofo.a, so add dependant libraries
+            # This may be a static libpodofo.a, so add dependent libraries.
             PODOFO_LIB="$PODOFO_LIB -lfreetype -lfontconfig -lpthread"
         fi
 
         AC_ARG_WITH(podofo-extra-lib-for-test,
-          [  --with-podofo-extra-lib-for-test=ARG   Additional libraries to pass the detection test, but not used for libgdal linking (ie. -ljpeg ...). Mainly for static libpodofo],,,)
+          [  --with-podofo-extra-lib-for-test=ARG   Additional libraries to pass the detection test, but not used for libgdal linking (i.e. -ljpeg ...). Mainly for static libpodofo],,,)
 
         if test "x$with_podofo_extra_lib_for_test" = "x" ; then
             TEST_PODOFO_LIB="$PODOFO_LIB"
@@ -3734,10 +4089,15 @@ if test "$with_podofo" != "no" -a "$with_podofo" != ""; then
         rm -f testpodofo.*
         echo '#include <podofo.h>' > testpodofo.cpp
         echo 'int main(int argc, char** argv) { PoDoFo::PdfError::EnableDebug( 0 ); return 0; } ' >> testpodofo.cpp
-        if test -z "`${CXX} testpodofo.cpp -o testpodofo ${TEST_PODOFO_INC} ${TEST_PODOFO_LIB} 2>&1`" ; then
+        ${CXX} testpodofo.cpp -o testpodofo ${TEST_PODOFO_INC} ${TEST_PODOFO_LIB} 2>/dev/null
+        RETVAL=$?
+        if test $RETVAL -eq 0; then
             HAVE_PODOFO=yes
-            LIBS="${PODOFO_LIB} ${LIBS}"
+            if test "$PDF_PLUGIN" = "no"; then
+                LIBS="${PODOFO_LIB} ${LIBS}"
+            fi
             PODOFO_INC=$TEST_PODOFO_INC
+            PODOFO_PLUGIN_LIB="${PODOFO_LIB}"
             AC_MSG_RESULT([yes])
         else
             AC_MSG_RESULT([no])
@@ -3751,6 +4111,117 @@ fi
 
 AC_SUBST(HAVE_PODOFO, $HAVE_PODOFO)
 AC_SUBST(PODOFO_INC, $PODOFO_INC)
+AC_SUBST(PODOFO_PLUGIN_LIB, $PODOFO_PLUGIN_LIB)
+
+dnl ---------------------------------------------------------------------------
+dnl Check if libpdfium is available
+dnl
+dnl Support for open-source PDFium library
+dnl
+dnl Copyright (C) 2015 Klokan Technologies GmbH (http://www.klokantech.com/)
+dnl Author: Martin Mikita <martin.mikita at klokantech.com>, xmikit00 @ FIT VUT Brno
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(pdfium,[  --with-pdfium[=ARG]    Include pdfium (for PDF) support (ARG=no(default), yes or pdfium install path)],,)
+
+HAVE_PDFIUM=no
+
+AC_MSG_CHECKING([for pdfium])
+
+if test "$with_pdfium" != "no" -a "$with_pdfium" != ""; then
+
+    AC_ARG_WITH(pdfium-lib,
+      [  --with-pdfium-lib=ARG   pdfium Link Flags (i.e. -L/xxx -lpdfium ...). Mainly for static libpdfium],,,)
+
+    if test "$with_pdfium" = "yes" ; then
+        TEST_PDFIUM_INC="-I/usr/include -I/usr/include/pdfium"
+        PDFIUM_LIB="-lpdfium"
+        PDFIUM_LIBDIR="/usr"
+    else
+        TEST_PDFIUM_INC="-I$with_pdfium -I$with_pdfium/include -I$with_pdfium/include/pdfium"
+        PDFIUM_LIB="-L$with_pdfium -L$with_pdfium/lib -lpdfium"
+        PDFIUM_LIBDIR="$with_pdfium"
+    fi
+
+    if test ! -z "`uname | grep Darwin`" ; then
+        PDFIUM_LIB="-stdlib=libstdc++ $PDFIUM_LIB"
+    fi
+
+    if test "x$with_pdfium_lib" = "x" ; then
+        rm -f testpdfium.*
+        echo '#include <fpdfview.h>' > testpdfium.cpp
+        echo '#include <core/include/fpdfapi/fpdf_page.h>' >> testpdfium.cpp
+        echo 'int main(int argc, char** argv) { FPDF_InitLibrary(); FPDF_DestroyLibrary(); return 0; } ' >> testpdfium.cpp
+        TEST_CXX_FLAGS="-std=c++0x"
+        if test ! -z "`uname | grep Darwin`" ; then
+          TEST_CXX_FLAGS="$TEST_CXX_FLAGS -stdlib=libstdc++"
+        fi
+        if test -z "`${CXX} $TEST_CXX_FLAGS testpdfium.cpp -o testpdfium ${TEST_PDFIUM_INC} ${PDFIUM_LIB}  2>&1`" ; then
+            HAVE_PDFIUM=yes
+            CXXFLAGS="$TEST_CXX_FLAGS $CXXFLAGS"
+            if test "$PDF_PLUGIN" = "no"; then
+                LIBS="${PDFIUM_LIB} ${LIBS}"
+            fi
+            PDFIUM_PLUGIN_LIB="${PDFIUM_LIB}"
+            PDFIUM_INC=$TEST_PDFIUM_INC
+            AC_MSG_RESULT([yes])
+        fi
+        rm -f testpdfium.*
+        rm -f testpdfium
+    fi
+
+    if test "$HAVE_PDFIUM" = "no"; then
+        if test "x$with_pdfium_lib" != "x" ; then
+            PDFIUM_LIB="$with_pdfium_lib"
+        else
+            # This may be a static libpdfium.a, so add dependent libraries.
+            PDFIUM_LIB="-L$PDFIUM_LIBDIR -L$PDFIUM_LIBDIR/lib/pdfium -lpdfium -lfpdfdoc -lfpdfapi -lfpdftext -lformfiller -lpdfwindow"
+            PDFIUM_LIB="$PDFIUM_LIB -lfxedit -lfpdfdoc -lfxcodec -lfx_libopenjpeg -lfx_lcms2 -lfx_libjpeg -lfx_zlib"
+            PDFIUM_LIB="$PDFIUM_LIB -lfdrm -lfxge -lfreetype -lfx_agg -lfxcrt -lbigint"
+            if test ! -z "`uname | grep Darwin`" ; then
+                PDFIUM_LIB="-framework AppKit -framework CoreFoundation $PDFIUM_LIB"
+            fi
+        fi
+
+        AC_ARG_WITH(pdfium-extra-lib-for-test,
+          [  --with-pdfium-extra-lib-for-test=ARG   Additional libraries to pass the detection test, but not used for libgdal linking (i.e. -ljpeg ...). Mainly for static libpdfium],,,)
+
+        if test "x$with_pdfium_extra_lib_for_test" = "x" ; then
+            TEST_PDFIUM_LIB="$PDFIUM_LIB"
+        else
+            TEST_PDFIUM_LIB="$PDFIUM_LIB $with_pdfium_extra_lib_for_test"
+        fi
+
+        rm -f testpdfium.*
+        echo '#include <fpdfview.h>' > testpdfium.cpp
+        echo '#include <core/include/fpdfapi/fpdf_page.h>' >> testpdfium.cpp
+        echo 'int main(int argc, char** argv) { FPDF_InitLibrary(); FPDF_DestroyLibrary(); return 0; } ' >> testpdfium.cpp
+        TEST_CXX_FLAGS="-std=c++0x"
+        if test ! -z "`uname | grep Darwin`" ; then
+          TEST_CXX_FLAGS="$TEST_CXX_FLAGS -stdlib=libstdc++"
+        fi
+        if test -z "`${CXX} $TEST_CXX_FLAGS testpdfium.cpp -o testpdfium ${TEST_PDFIUM_INC} ${TEST_PDFIUM_LIB} 2>&1`" ; then
+            HAVE_PDFIUM=yes
+            CXXFLAGS="$TEST_CXX_FLAGS $CXXFLAGS"
+            if test "$PDF_PLUGIN" = "no"; then
+                LIBS="${PDFIUM_LIB} ${LIBS}"
+            fi
+            PDFIUM_PLUGIN_LIB="${PDFIUM_LIB}"
+            PDFIUM_INC=$TEST_PDFIUM_INC
+            AC_MSG_RESULT([yes])
+        else
+            AC_MSG_RESULT([no])
+        fi
+        rm -f testpdfium.*
+        rm -f testpdfium
+    fi
+else
+    AC_MSG_RESULT([disabled])
+fi
+
+AC_SUBST(HAVE_PDFIUM, $HAVE_PDFIUM)
+AC_SUBST(PDFIUM_INC, $PDFIUM_INC)
+AC_SUBST(PDFIUM_PLUGIN_LIB, $PDFIUM_PLUGIN_LIB)
 
 dnl ---------------------------------------------------------------------------
 dnl PROJ.4 related stuff.
@@ -3777,7 +4248,7 @@ else
     LIBS="$PROJ_LIB $ORIG_LIBS"
     AC_CHECK_LIB(proj,pj_init,PROJ_STATIC=yes,PROJ_STATIC=no,)
   else
-  
+
     LIBS="-L$with_static_proj4/lib $PROJ_LIB $ORIG_LIBS"
     AC_CHECK_LIB(proj,pj_init,PROJ_STATIC=yes,PROJ_STATIC=no,)
 
@@ -3826,7 +4297,7 @@ else
   elif test -r "$with_static_proj4/proj_api.h" ; then
     PROJ_INCLUDE="-I$with_static_proj4"
   fi
-  
+
 fi
 
 AC_SUBST(PROJ_STATIC)
@@ -3912,7 +4383,7 @@ AC_SUBST(EXE_EXT)
 AC_SUBST(SO_EXT)
 
 dnl ---------------------------------------------------------------------------
-dnl Which "true" program should we use? 
+dnl Which "true" program should we use?
 dnl ---------------------------------------------------------------------------
 BINTRUE=/bin/true
 
@@ -3928,7 +4399,7 @@ export BINTRUE
 AC_SUBST(BINTRUE,$BINTRUE)
 
 dnl ---------------------------------------------------------------------------
-dnl If datadir is set to @prefix@/share, the modify it to be 
+dnl If datadir is set to @prefix@/share, the modify it to be
 dnl @prefix@/share/gdal.  I wish we could default this.
 dnl ---------------------------------------------------------------------------
 if test "$datadir" = '${prefix}/share' ; then
@@ -3942,15 +4413,15 @@ fi
 
 dnl ---------------------------------------------------------------------------
 dnl By default mandir is $datarootdir/man which would be
-dnl /usr/local/share/gdal/man but we want man pages in /usr/local/man. 
+dnl /usr/local/share/gdal/man but we want man pages in /usr/local/man.
 dnl ---------------------------------------------------------------------------
 mandir='${prefix}/man'
 
 dnl ---------------------------------------------------------------------------
-dnl Capture GDAL_PREFIX for the cpl_config.h include file. 
+dnl Capture GDAL_PREFIX for the cpl_config.h include file.
 dnl ---------------------------------------------------------------------------
 
-if test "$prefix" = "NONE" ; then 
+if test "$prefix" = "NONE" ; then
   GDAL_PREFIX=/usr/local
 else
   GDAL_PREFIX=${prefix}
@@ -4408,6 +4879,148 @@ fi
 
 AC_SUBST(HAVE_ARMADILLO,$HAVE_ARMADILLO)
 
+dnl ---------------------------------------------------------------------------
+dnl libcryptopp
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(cryptopp,[  --with-cryptopp[=ARG]       Include cryptopp support (ARG=yes, no or path)],,)
+
+HAVE_CRYPTOPP=no
+USE_ONLY_CRYPTODLL_ALG=yes
+
+AC_MSG_CHECKING([for cryptopp])
+
+if test "$with_cryptopp" = "no" ; then
+
+  AC_MSG_RESULT([disabled])
+
+elif test "$with_cryptopp" = "yes" -o "$with_cryptopp" = "" ; then
+
+    rm -f testcryptopp.*
+    echo '#include <cryptopp/aes.h>' > testcryptopp.cpp
+    # Catch issue with clang++ (https://groups.google.com/forum/#!topic/cryptopp-users/DfWHy3bT0KI)
+    echo '#include <cryptopp/osrng.h>' >> testcryptopp.cpp
+    echo 'int main(int argc, char** argv) { CryptoPP::AES::Encryption oEnc; return 0; } ' >> testcryptopp.cpp
+    ${CXX} ${CXXFLAGS} testcryptopp.cpp -o testcryptopp -lcryptopp 2>/dev/null
+    RETVAL=$?
+    if test $RETVAL -eq 0; then
+        HAVE_CRYPTOPP=yes
+        LIBS="-lcryptopp ${LIBS}"
+        AC_MSG_RESULT([yes])
+    else
+        AC_MSG_RESULT([no])
+        if test "$with_cryptopp" = "yes"; then
+            AC_MSG_ERROR([--with-cryptopp was requested, but not available])
+        fi
+    fi
+    rm -f testcryptopp.*
+    rm -f testcryptopp
+
+    if test "$HAVE_CRYPTOPP" = "yes"; then
+
+        AC_MSG_CHECKING([if cryptopp has all cipher methods builtin])
+        rm -f testcryptopp.*
+        echo '#include <cryptopp/blowfish.h>' > testcryptopp.cpp
+        echo 'int main(int argc, char** argv) { CryptoPP::Blowfish::Encryption oEnc; return 0; } ' >> testcryptopp.cpp
+        ${CXX} ${CXXFLAGS} testcryptopp.cpp -o testcryptopp -lcryptopp 2>/dev/null
+        RETVAL=$?
+        if test $RETVAL -eq 0; then
+            USE_ONLY_CRYPTODLL_ALG=no
+            AC_MSG_RESULT([yes])
+        else
+            USE_ONLY_CRYPTODLL_ALG=yes
+            AC_MSG_RESULT([no])
+        fi
+        rm -f testcryptopp.*
+        rm -f testcryptopp
+    fi
+
+else
+
+    rm -f testcryptopp.*
+    echo '#include <cryptopp/aes.h>' > testcryptopp.cpp
+    # Catch issue with clang++ (https://groups.google.com/forum/#!topic/cryptopp-users/DfWHy3bT0KI)
+    echo '#include <cryptopp/osrng.h>' >> testcryptopp.cpp
+    echo 'int main(int argc, char** argv) { CryptoPP::AES::Encryption oEnc; return 0; } ' >> testcryptopp.cpp
+    ${CXX} ${CXXFLAGS} testcryptopp.cpp -I$with_cryptopp/include -o testcryptopp -L$with_cryptopp/lib -lcryptopp 2>/dev/null
+    RETVAL=$?
+    if test $RETVAL -eq 0; then
+        HAVE_CRYPTOPP=yes
+        LIBS="-L$with_cryptopp/lib -lcryptopp ${LIBS}"
+        EXTRA_INCLUDES="-I$with_cryptopp/include $EXTRA_INCLUDES"
+        AC_MSG_RESULT([yes])
+    else
+        AC_MSG_RESULT([no])
+    fi
+    rm -f testcryptopp.*
+    rm -f testcryptopp
+
+    if test "$HAVE_CRYPTOPP" = "yes"; then
+
+        AC_MSG_CHECKING([if cryptopp has all cipher methods builtin])
+        rm -f testcryptopp.*
+        echo '#include <cryptopp/blowfish.h>' > testcryptopp.cpp
+        echo 'int main(int argc, char** argv) { CryptoPP::Blowfish::Encryption oEnc; return 0; } ' >> testcryptopp.cpp
+        ${CXX} ${CXXFLAGS} testcryptopp.cpp -I$with_cryptopp/include -o testcryptopp -L$with_cryptopp/lib -lcryptopp 2>/dev/null
+        RETVAL=$?
+        if test $RETVAL -eq 0; then
+            USE_ONLY_CRYPTODLL_ALG=no
+            AC_MSG_RESULT([yes])
+        else
+            USE_ONLY_CRYPTODLL_ALG=yes
+            AC_MSG_RESULT([no])
+        fi
+        rm -f testcryptopp.*
+        rm -f testcryptopp
+    fi
+
+fi
+
+AC_SUBST(HAVE_CRYPTOPP,$HAVE_CRYPTOPP)
+AC_SUBST(USE_ONLY_CRYPTODLL_ALG,$USE_ONLY_CRYPTODLL_ALG)
+
+
+dnl ---------------------------------------------------------------------------
+dnl Whether to include MRF in the build
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH([grib],
+            AS_HELP_STRING([--without-mrf],
+               [Disable MRF driver]),,)
+
+AC_MSG_CHECKING([for MRF])
+if test "$with_mrf" = yes -o x"$with_mrf" = x ; then
+    OPT_GDAL_FORMATS="mrf $OPT_GDAL_FORMATS"
+    HAVE_MRF=yes
+    AC_MSG_RESULT([enabled])
+else
+    HAVE_MRF=no
+    AC_MSG_RESULT([disabled by user])
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl Test if sprintf can be overloaded with _XOPEN_SOURCE being defined or other,
+dnl includes being included before, which mingw64 4.8 doesn't like (#6390)
+dnl ---------------------------------------------------------------------------
+
+AC_MSG_CHECKING([if sprintf can be overloaded for GDAL compilation])
+echo '#define _XOPEN_SOURCE' > testdeprecated.cpp
+echo '#include <vector>' >> testdeprecated.cpp
+echo '#include <stdio.h>' >> testdeprecated.cpp
+echo 'extern "C"' >> testdeprecated.cpp
+echo '{' >> testdeprecated.cpp
+echo 'int sprintf(char *str, const char* fmt, ...);' >> testdeprecated.cpp
+echo '}' >> testdeprecated.cpp
+${CXX} ${CXXFLAGS} testdeprecated.cpp -c 2>/dev/null
+RETVAL=$?
+if test $RETVAL -eq 0; then
+    AC_MSG_RESULT([yes])
+else
+    CPPFLAGS="$CPPFLAGS -DDONT_DEPRECATE_SPRINTF"
+    AC_MSG_RESULT([no])
+fi
+rm -f testdeprecated.*
+rm -f testdeprecated
 
 AC_OUTPUT(GDALmake.opt)
 
@@ -4426,12 +5039,13 @@ LOC_MSG([  LIBTOOL support:           ${with_libtool}])
 LOC_MSG()
 LOC_MSG([  LIBZ support:              ${LIBZ_SETTING}])
 LOC_MSG([  LIBLZMA support:           ${LIBLZMA_SETTING}])
+LOC_MSG([  cryptopp support:          ${HAVE_CRYPTOPP}])
 LOC_MSG([  GRASS support:             ${GRASS_SETTING}])
 LOC_MSG([  CFITSIO support:           ${FITS_SETTING}])
 LOC_MSG([  PCRaster support:          ${PCRASTER_SETTING}])
 LOC_MSG([  LIBPNG support:            ${PNG_SETTING}])
 LOC_MSG([  DDS support:               ${DDS_SETTING}])
-LOC_MSG([  GTA support:               ${GTA_SETTING}]) 
+LOC_MSG([  GTA support:               ${GTA_SETTING}])
 LOC_MSG([  LIBTIFF support:           ${TIFF_SETTING} (BigTIFF=${HAVE_BIGTIFF})])
 LOC_MSG([  LIBGEOTIFF support:        ${GEOTIFF_SETTING}])
 LOC_MSG([  LIBJPEG support:           ${JPEG_SETTING}])
@@ -4459,6 +5073,7 @@ LOC_MSG([  EPSILON support:           ${EPSILON_SETTING}])
 LOC_MSG([  WebP support:              ${WEBP_SETTING}])
 LOC_MSG([  cURL support (wms/wcs/...):${CURL_SETTING}])
 LOC_MSG([  PostgreSQL support:        ${HAVE_PG}])
+LOC_MSG([  MRF support:               ${HAVE_MRF}])
 LOC_MSG([  MySQL support:             ${HAVE_MYSQL}])
 LOC_MSG([  Ingres support:            ${HAVE_INGRES}])
 LOC_MSG([  Xerces-C support:          ${HAVE_XERCES}])
@@ -4479,15 +5094,21 @@ LOC_MSG([  DODS support:              ${HAVE_DODS}])
 LOC_MSG([  SQLite support:            ${HAVE_SQLITE}])
 LOC_MSG([  PCRE support:              ${HAVE_PCRE}])
 LOC_MSG([  SpatiaLite support:        ${HAVE_SPATIALITE}])
+if test "x$SPATIALITE_SONAME" != "x"; then
+LOC_MSG([  SpatiaLite shared obj name:${SPATIALITE_SONAME}])
+fi
 LOC_MSG([  DWGdirect support          ${HAVE_DWGDIRECT}])
 LOC_MSG([  INFORMIX DataBlade support:${HAVE_IDB}])
 LOC_MSG([  GEOS support:              ${HAVE_GEOS_RESULT}])
+LOC_MSG([  QHull support:             ${QHULL_SETTING}])
 LOC_MSG([  Poppler support:           ${HAVE_POPPLER}])
 LOC_MSG([  Podofo support:            ${HAVE_PODOFO}])
+LOC_MSG([  PDFium support:            ${HAVE_PDFIUM}])
 LOC_MSG([  OpenCL support:            ${OPENCL_SETTING}])
 LOC_MSG([  Armadillo support:         ${HAVE_ARMADILLO}])
 LOC_MSG([  FreeXL support:            ${HAVE_FREEXL}])
 LOC_MSG([  SOSI support:              ${SOSI_ENABLED}])
+LOC_MSG([  MongoDB support:           ${MONGODB_ENABLED}])
 LOC_MSG()
 if test ! -z "`uname | grep Darwin`" ; then
   LOC_MSG([  Mac OS X Framework :       ${MACOSX_FRAMEWORK}])
@@ -4501,15 +5122,22 @@ fi
 LOC_MSG([  SWIG Bindings:             ${WHAT_BINDINGS}])
 LOC_MSG()
 LOC_MSG([  Statically link PROJ.4:    ${PROJ_STATIC}])
-LOC_MSG([  enable OGR building:       ${OGR_ENABLED}])
+LOC_MSG([  enable GNM building:       ${GNM_ENABLED}])
 LOC_MSG([  enable pthread support:    ${PTHREAD_ENABLED}])
 LOC_MSG([  enable POSIX iconv support:${am_cv_func_iconv}])
 LOC_MSG([  hide internal symbols:     ${HAVE_HIDE_INTERNAL_SYMBOLS}])
 LOC_MSG()
 
-if test "$HAVE_PODOFO" = "yes" -a "$HAVE_POPPLER" = "yes" ; then
+if test "$HAVE_PODOFO" = "yes" -a "$HAVE_POPPLER" = "yes"  -a "$HAVE_PDFIUM" = "yes"; then
+    AC_MSG_WARN([--with-podofo, --with-poppler and --with-pdfium available. This is unusual setup, but will work. Pdfium will be used by default...])
+elif test "$HAVE_PODOFO" = "yes" -a "$HAVE_POPPLER" = "yes" ; then
     AC_MSG_WARN([--with-podofo and --with-poppler are both available. This is unusual setup, but will work. Poppler will be used by default...])
+elif test "$HAVE_POPPLER" = "yes" -a "$HAVE_PDFIUM" = "yes" ; then
+    AC_MSG_WARN([--with-poppler and --with-pdfium are both available. This is unusual setup, but will work. Pdfium will be used by default...])
+elif test "$HAVE_PODOFO" = "yes" -a "$HAVE_PDFIUM" = "yes" ; then
+    AC_MSG_WARN([--with-podofo and --with-pdfium are both available. This is unusual setup, but will work. Pdfium will be used by default...])
 fi
+
 if test "$HAVE_LIBXML2" = "yes" -a "$FGDB_ENABLED" = "yes"; then
     AC_MSG_WARN([--with-libxml2 and --with-fgdb are both available. There might be some incompatibility between system libxml2 and the embedded copy within libFileGDBAPI])
 fi
diff --git a/data/compdcs.csv b/data/compdcs.csv
index 0ab7840..bfd7b4d 100644
--- a/data/compdcs.csv
+++ b/data/compdcs.csv
@@ -124,7 +124,10 @@
 6696,"JGD2000 + JGD2000 (vertical) height",4612,6694,1,0
 6697,"JGD2011 + JGD2011 (vertical) height",6668,6695,1,0
 6700,"Tokyo + JSLD72 height",4301,6693,1,0
-6871,"WGS 84 / Pseudo-Mercator +  EGM2008 geoid height",3857,3855,1,0
+6871,"WGS 84 / Pseudo-Mercator +  EGM2008 geoid height",3857,3855,1,1
+6893,"WGS 84 / World Mercator +  EGM2008 height",3395,3855,1,0
+6917,"SVY21 + SHD height",4757,6916,1,0
+6927,"SVY21 / Singapore TM + SHD height",3414,6916,1,0
 7400,"NTF (Paris) + NGF IGN69 height",4807,5720,1,0
 7401,"NTF (Paris) / France II + NGF Lallemand",27582,5719,1,1
 7402,"NTF (Paris) / France II + NGF IGN69",27582,5720,1,1
diff --git a/data/coordinate_axis.csv b/data/coordinate_axis.csv
index 12ca0ed..1bfc028 100644
--- a/data/coordinate_axis.csv
+++ b/data/coordinate_axis.csv
@@ -32,6 +32,8 @@ coord_sys_code,coord_axis_name_code,coord_axis_orientation,coord_axis_abbreviati
 1039,9906,east,E,9002,1
 1039,9907,north,N,9002,2
 1043,9905,down,D,9003,1
+1044,9906,North along 90°W,E,9001,2
+1044,9907,North along 180°E,N,9001,1
 4400,9906,east,E,9001,1
 4400,9907,north,N,9001,2
 4401,9906,east,E,9062,1
@@ -157,7 +159,7 @@ coord_sys_code,coord_axis_name_code,coord_axis_orientation,coord_axis_abbreviati
 6402,9901,north,Lat,9108,1
 6402,9902,east,Long,9108,2
 6403,9901,north,Lat,9105,1
-6403,9902,east,Long,9105,2
+6403,9902,east,Lon,9105,2
 6404,9926,north,Lat,9122,1
 6404,9927,east,Long,9122,2
 6404,9928,up,R,9001,3
@@ -202,32 +204,32 @@ coord_sys_code,coord_axis_name_code,coord_axis_orientation,coord_axis_abbreviati
 6420,9902,east,Long,9120,2
 6420,9903,up,h,9001,3
 6421,9901,north,Lat,9105,1
-6421,9902,east,Long,9105,2
+6421,9902,east,Lon,9105,2
 6421,9903,up,h,9001,3
 6422,9901,north,Lat,9122,1
-6422,9902,east,Long,9122,2
+6422,9902,east,Lon,9122,2
 6423,9901,north,Lat,9122,1
-6423,9902,east,Long,9122,2
+6423,9902,east,Lon,9122,2
 6423,9903,up,h,9001,3
 6424,9901,north,Lat,9122,2
-6424,9902,east,Long,9122,1
+6424,9902,east,Lon,9122,1
 6425,9901,north,Lat,9105,2
-6425,9902,east,Long,9105,1
+6425,9902,east,Lon,9105,1
 6426,9901,north,Lat,9122,2
-6426,9902,east,Long,9122,1
+6426,9902,east,Lon,9122,1
 6426,9903,up,h,9001,3
 6427,9901,north,Lat,9105,2
-6427,9902,east,Long,9105,1
+6427,9902,east,Lon,9105,1
 6427,9903,up,h,9001,3
 6428,9901,north,Lat,9101,1
-6428,9902,east,Long,9101,2
+6428,9902,east,Lon,9101,2
 6429,9901,north,Lat,9101,2
-6429,9902,east,Long,9101,1
+6429,9902,east,Lon,9101,1
 6430,9901,north,Lat,9101,1
-6430,9902,east,Long,9101,2
+6430,9902,east,Lon,9101,2
 6430,9903,up,h,9001,3
 6431,9901,north,Lat,9101,2
-6431,9902,east,Long,9101,1
+6431,9902,east,Lon,9101,1
 6431,9903,up,h,9001,3
 6495,9905,down,D,9002,1
 6496,9904,up,H,9095,1
@@ -243,10 +245,10 @@ coord_sys_code,coord_axis_name_code,coord_axis_orientation,coord_axis_abbreviati
 6502,9909,south,X,9031,2
 6503,9908,west,Y,9001,1
 6503,9909,south,X,9001,2
-6504,9918,north-east,e,9001,2
-6504,9919,north-west,n,9001,1
-6505,9913,north-west,n,9001,1
-6505,9914,north-east,e,9001,2
+6504,9918,northeast,e,9001,2
+6504,9919,northwest,n,9001,1
+6505,9913,northwest,n,9001,1
+6505,9914,northeast,e,9001,2
 6506,9913,east-south-east,I,9205,1
 6506,9914,north-north-east,J,9204,2
 6507,9913,north,X,9001,1
@@ -255,8 +257,8 @@ coord_sys_code,coord_axis_name_code,coord_axis_orientation,coord_axis_abbreviati
 6508,9921,north north east,J,9209,1
 6509,9908,west,M,9001,2
 6509,9909,south,P,9001,1
-6510,9918,north-east,x,9001,1
-6510,9919,north-west,y,9001,2
+6510,9918,northeast,x,9001,1
+6510,9919,northwest,y,9001,2
 6511,9922,Along receiver lines,I,9208,1
 6511,9923,Across receiver lines,J,9209,2
 6512,9916,up,z,9001,3
diff --git a/data/datum_shift.csv b/data/datum_shift.csv
index baca1f3..693842b 100644
--- a/data/datum_shift.csv
+++ b/data/datum_shift.csv
@@ -10,12 +10,12 @@
 9,1889,4616,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,2779,29.98,30.21,-16.11,-15.79,1,1,9603,-289,-124,60,,,,,0
 10,1965,4616,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,2779,29.98,30.21,-16.11,-15.79,1,0,9603,-289,-124,60,,,,,1
 11,1842,4617,4326,"For many purposes NAD83(CSRS) can be considered to be coincident with WGS 84.","Approximation at the +/- 1m level assuming that NAD83(CSRS) is equivalent to WGS 84.",1061,40.04,86.46,-141.01,-47.74,1,0,9603,0,0,0,,,,,1
-12,1946,4617,4326,"Approximation derived from tfm code 6864 ignoring time-dependent parameters and assuming ITRF96(1997.0) and WGS 84 can be considered the same within the accuracy of the transformation.",Geodesy.,1061,40.04,86.46,-141.01,-47.74,1,0,9607,-0.991,1.9072,0.5129,-0.0257899075194932,-0.0096500989602704,-0.0116599432323421,0,0
+12,1946,4617,4326,"Approximation derived from tfm code 6864 ignoring time-dependent parameters and assuming ITRF96(1997.0) and WGS 84 can be considered the same within the accuracy of the transformation.",Geodesy.,1061,40.04,86.46,-141.01,-47.74,1,0,9607,-0.991,1.9072,0.5129,-0.02578991,-0.00965010,-0.0116599,0,0
 13,1864,4618,4326,Derived at 84 stations.,"For military purposes only. Accuracy 15m, 6m and 9m in X, Y and Z axes.",4016,-45,12.52,-81.41,-34.74,1,0,9603,-57,1,-41,,,,,0
 14,1865,4618,4326,"Derived at 10 stations. Note: SAD69 not adopted in Argentina: see Campo Inchauspe (CRS code 4221).",For military purposes only. Accuracy 5m in each axis.,3215,-52.43,-21.78,-73.59,-53.65,1,0,9603,-62,-1,-37,,,,,0
 15,1866,4618,4326,"Derived at 4 stations. Note: SAD69 not adopted in Bolivia: see PSAD56 (CRS code 4248).",For military purposes. Accuracy 15m in each axis.,1049,-22.91,-9.67,-69.66,-57.52,1,0,9603,-61,2,-48,,,,,0
 16,1867,4618,4326,Derived at 22 stations.,"For military purposes only. Accuracy 3m, 5m and 5m in X, Y and Z axes.",3887,-33.78,4.43,-60.58,-34.74,1,0,9603,-60,-2,-41,,,,,0
-17,1868,4618,4326,"Derived at 9 stations. Note: SAD69 not adopted in Chile.","For military purposes only. Accuracy 15m, 8m and 11m in X, Y and Z axes.",3227,-45,-17.5,-75.22,-67,1,0,9603,-75,-1,-44,,,,,0
+17,1868,4618,4326,"Derived at 9 stations. Note: SAD69 not adopted in Chile north of 43°30'S. Replaced by SAD69 to WGS 84 (17) to (19) (codes 6974, 6975 and 6976).","For military purposes only. Accuracy 15m, 8m and 11m in X, Y and Z axes.",3227,-45,-17.5,-75.22,-67,1,0,9603,-75,-1,-44,,,,,0
 18,1869,4618,4326,"Derived at 7 stations. Note: SAD69 not adopted in Colombia: see Bogota 1975 (CRS code 4218).","For military purposes only. Accuracy 6m, 6m and 5m in X, Y and Z axes.",3229,-4.23,12.52,-79.1,-66.87,1,0,9603,-44,6,-36,,,,,0
 19,1870,4618,4326,"Derived at 11 stations. Note: SAD69 not adopted in Ecuador: see PSAD56 (CRS code 4248).",For military purposes. Accuracy 3m in each axis.,3241,-5.01,1.45,-81.03,-75.21,1,0,9603,-48,3,-44,,,,,0
 20,1871,4618,4326,"Derived at 1 station. Note: SAD69 not adopted in Ecuador.",For military purposes. Accuracy 25m in each axis.,2356,-1.41,0.18,-91.72,-89.19,1,0,9603,-47,26,-42,,,,,0
@@ -24,761 +24,805 @@
 23,1874,4618,4326,"Derived at 6 stations. Note: SAD69 not adopted in Peru: see PSAD56 (CRS code 4248).",For military purposes. Accuracy 5m in each axis.,3292,-18.35,-0.03,-81.41,-68.67,1,0,9603,-58,0,-44,,,,,0
 24,1875,4618,4326,"Derived at 1 station. Note: SAD69 not adopted in Trinidad and Tobago.",For military purposes only. Accuracy 25m in each axis.,3143,9.99,10.9,-61.97,-60.86,1,0,9603,-45,12,-33,,,,,0
 25,1876,4618,4326,"Derived at 5 stations. Note: SAD69 not adopted in Venezuela: see PSAD56 (CRS code 4248).","For military purposes only. Accuracy 3m, 6m and 3m in X, Y and Z axes.",3327,0.64,12.25,-73.38,-59.8,1,0,9603,-45,8,-33,,,,,0
-26,1877,4618,4326,"Derived by Brazilian Institute of Geography and Statistics (IBGE) in 1989 at Chua origin point. In use by Shell throughout Brazil. For use by Petrobras and ANP, replaced by tfm code 5882 from 1994.",Medium and small scale mapping. Valid for transforming GPS observations conducted in the period 1987 to 1993 inclusive.,1053,-35.71,7.04,-74.01,-25.28,1,0,9603,-66.87,4.37,-38.52,,,,,0
-27,5882,4618,4326,"Parameter values from SAD69 to SIRGAS 2000 (1) (tfm code 15485) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Used by ANP and Petrobras throughout Brazil from 1994, relacing use of tfm code 1877.","Accuracy generally better than 1m except in Amazon basin where it degenerates to 5m. Should be used only to transform data obtained independently of the classical geodetic network (GPS observations conducted after 1994).",1053,-35. [...]
-28,1879,4619,4326,"Parameter values taken from SWEREF to ETRS89 (1) (code 1878) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation.",Geographic Information Systems.,1225,54.96,69.07,10.03,24.17,1,0,9603,0,0,0,,,,,1
-29,1880,4620,4326,Derived at one point in each of Burkina Faso and Niger.,For military purposes. Accuracy 25m in each axis.,2791,11.83,14.23,-4.64,4,1,0,9603,-106,-129,165,,,,,1
-30,1903,4621,4326,,"Accuracy +/- 10 metres.",2828,17.82,18.17,-63.21,-62.73,1,0,9603,137,248,-430,,,,,1
-31,1904,4622,4326,,"Accuracy +/- 10 metres.",2829,15.8,16.55,-61.85,-60.97,1,0,9603,-467,-16,-300,,,,,1
-32,1905,4622,4326,,"Accuracy +/- 0.1 metre.",2829,15.8,16.55,-61.85,-60.97,1,0,9606,-472.29,-5.63,-304.12,0.4362,-0.8374,0.2563,1.8984,0
-33,1906,4623,4326,,"Accuracy +/- 10 metres.",3105,3.43,5.81,-54.45,-51.61,1,0,9603,-186,230,110,,,,,1
-34,1907,4624,4326,,"Accuracy +/- 2 metres.",1097,2.11,8.88,-54.6,-49.46,1,1,9603,2,2,-2,,,,,0
-35,4840,4624,4326,"Replaces RGFG95 to WGS 84 (1) (code 1907) which was not put into official use but issued in error.","Accuracy +/- 2 metres.",1097,2.11,8.88,-54.6,-49.46,1,0,9603,0,0,0,,,,,1
-36,1909,4625,4326,,"Accuracy +/- 10 metres.",3276,14.35,14.93,-61.29,-60.76,1,0,9603,186,482,151,,,,,1
-37,1910,4625,4326,,"Accuracy +/- 0.1 metre.",3276,14.35,14.93,-61.29,-60.76,1,0,9606,126.93,547.94,130.41,-2.7867,5.1612,-0.8584,13.8227,0
-38,1911,4626,4326,Derived at 1 station.,"Accuracy +/- 30 metres.",1196,-25.92,-10.6,37.58,58.27,1,1,9603,94,-948,-1292,,,,,0
-39,15751,4626,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,3337,-21.42,-20.81,55.16,55.91,1,0,9603,94,-948,-1262,,,,,1
-40,1912,4627,4326,,"Accuracy +/- 1 metre.",3902,-24.72,-18.28,51.83,58.24,1,0,9603,0,0,0,,,,,1
-41,1924,4628,4326,,"Accuracy +/- 10 metres.",2811,-17.93,-17.41,-150,-149.11,1,0,9603,162,117,154,,,,,1
-42,1913,4629,4326,,"Accuracy +/- 10 metres.",2812,-16.96,-16.17,-151.91,-150.89,1,0,9603,65,342,77,,,,,0
-43,15770,4629,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from Tahaa 54 to RGPF (1) (tfm code 15758).","Accuracy +/- 1 metre.",2812,-16.96,-16.17,-151.91,-150.89,1,0,9607,72.438,345.918,79.486,-1.6045,-0.8823,-0.5565,1.3746,1
-44,1914,4630,4326,,"Accuracy +/- 10 metres.",3129,-9.57,-8.72,-140.31,-139.44,1,0,9603,84,274,65,,,,,1
-45,15775,4630,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from IGN72 Nuku Hiva to RGPF (1) (tfm code 15763).","Accuracy +/- 1 metre.",2810,-9.01,-8.72,-140.31,-139.96,1,0,9607,165.732,216.72,180.505,-0.6434,-0.4512,-0.0791,7.4204,0
-46,15776,4630,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from IGN72 Nuku Hiva to RGPF (2) (tfm code 15764).","Accuracy +/- 2 metres.",3127,-9,-8.81,-139.66,-139.44,1,0,9607,1363.785,1362.687,398.811,-4.5322,-6.7579,-1.0574,268.361,0
-47,15777,4630,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from IGN72 Nuku Hiva to RGPF (2) (tfm code 15765).","Accuracy +/- 1 metre.",3128,-9.57,-9.27,-140.21,-139.95,1,0,9607,259.551,297.612,197.833,1.4866,2.1224,0.4612,27.0249,0
-48,1915,4631,4326,"Also published in US NIMA/NGA TR8350.2 which gives accuracy of +/-25m in each axis and states that derived at one station.","Accuracy +/- 10 metres.",2816,-49.78,-48.6,68.69,70.62,1,1,9603,145,-187,103,,,,,0
-49,1916,4632,4326,,"Accuracy +/- 10 metres.",3340,-13.05,-12.61,44.98,45.35,1,0,9603,-382,-59,-262,,,,,1
-50,1272,4121,4326,,For applications requiring 1m or better accuracy.,3254,34.88,41.75,19.57,28.3,1,0,9603,-199.87,74.79,246.62,,,,,1
-51,1918,4634,4326,,"Accuracy +/- 10 metres.",1174,-26.45,-14.83,156.25,174.28,1,1,9603,-13,-348,292,,,,,0
-52,1929,4634,4326,,"Accuracy better than +/- 1 metre.",2822,-22.45,-20.03,163.92,167.09,1,1,9606,97.295,-263.247,310.882,-1.5999,0.8386,3.1409,13.3259,0
-53,1639,4123,4326,"Parameter values from KKJ to ETRS89 (1) (code 1638). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaced by KKJ to WGS 84 (2) (code 10099).",For applications to an accuracy of 1 to 2 metres.,3333,59.75,70.09,19.24,31.59,1,0,9606,-90.7,-106.1,-119.2,4.09,0.218,-1.05,1.37,0
-54,10099,4123,4326,"Parameter values from KKJ to ETRS89 (2) (code 10098). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaces KKJ to WGS 84 (1) (code 1639).",For applications to an accuracy of 1 to 2 metres.,3333,59.75,70.09,19.24,31.59,1,0,9607,-96.062,-82.428,-121.753,-4.801,-0.345,1.376,1.496,1
-55,1680,4124,4326,"Parameter values from RT90 to ETRS89 (1) (code 1437) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaced by RT90 to WGS 84 (2) (code 1896) from 2001.","Approximation at the +/- 1m level.",1225,54.96,69.07,10.03,24.17,1,0,9607,419.3836,99.3335,591.3451,-0.850389,-1.817277,7.862238,-0.99496,0
-56,1788,4124,4326,"Parameter values from RT90 to ETRS89 (1) (code 1787) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Supersedes RT90 to WGS 84 (1) (code 1680).","Approximation at the +/- 1m level.",1225,54.96,69.07,10.03,24.17,1,1,9607,414.1,41.3,603.1,-0.855,2.141,-7.023,0,0
-57,1896,4124,4326,"Parameter values from RT90 to SWEREF99 (1) (code 1895) assuming that SWEREF99 is equivalent to WGS 84 within the accuracy of the transformation. Replaces RT90 to WGS 84 (1) (code 1680).","Approximation at the +/- 1m level.",1225,54.96,69.07,10.03,24.17,1,0,9607,414.1,41.3,603.1,0.855,-2.141,7.023,0,1
-58,1282,4125,4326,Datum shift derived through ITRF93.,Oil exploration.,1328,-1.24,0,116.72,117.99,1,1,9603,-404.78,685.68,45.47,,,,,0
-59,1923,4638,4326,,"Accuracy +/- 10 metres.",3299,46.69,47.19,-56.48,-56.07,1,0,9603,30,430,368,,,,,1
-60,1683,4127,4326,"Parameter values taken from Tete to Moznet (1) (code 1297) assuming that Moznet is equivalent to WGS 84 within the accuracy of the transformation.",Residuals as high as 30 metres.,3281,-26.87,-10.42,30.21,40.9,1,0,9607,-115.064,-87.39,-101.716,0.058,-4.001,2.062,9.366,0
-61,1684,4127,4326,"Parameter values taken from Tete to Moznet (2) (code 1298) assuming that Moznet is equivalent to WGS 84 within the accuracy of the transformation.",Residuals are generally under 1 metre.,2350,-26.87,-23.91,31.91,34.5,1,0,9607,-82.875,-57.097,-156.768,2.158,-1.524,0.982,-0.359,0
-62,1685,4127,4326,"Parameter values taken from Tete to Moznet (3) (code 1299) assuming that Moznet is equivalent to WGS 84 within the accuracy of the transformation.",Residuals are generally under 4 metres.,2351,-24.91,-19.74,31.29,35.65,1,0,9607,-138.527,-91.999,-114.591,0.14,-3.363,2.217,11.748,0
-63,1686,4127,4326,"Parameter values taken from Tete to Moznet (4) (code 1300) assuming that Moznet is equivalent to WGS 84 within the accuracy of the transformation.",Residuals are generally under 3 metres.,2352,-19.91,-14.01,30.21,39.18,1,0,9607,-73.472,-51.66,-112.482,-0.953,-4.6,2.368,0.586,1
-64,1687,4127,4326,"Parameter values taken from Tete to Moznet (5) (code 1301) assuming that Moznet is equivalent to WGS 84 within the accuracy of the transformation.",Residuals are 5-10 metres.,2353,-16.94,-10.42,34.36,40.9,1,0,9607,219.315,168.975,-166.145,-0.198,-5.926,2.356,-57.104,0
-65,1934,4640,4326,RRAF 1991 was defined to be WGS84 at a single point in Martinique during the 1988 Tango mission.,"Accuracy +/- 1 metre.",2824,14.08,18.54,-63.66,-57.52,1,1,9603,0,0,0,,,,,0
-66,1928,4641,4326,Withdrawn by information source and replaced by improved information - see tfm code 15901.,"Accuracy better than +/- 1 metre.",2819,-21.71,-21.32,167.75,168.19,1,0,9606,-408.809,366.856,-412.987,1.8842,-0.5308,2.1655,-121.0993,0
-67,15783,4641,4326,Withdrawn by information source and replaced by improved information from local authority - see tfm code 15901.,Accuracy 5 metres.,2819,-21.71,-21.32,167.75,168.19,1,0,9603,287,178,-136,,,,,0
-68,15901,4641,4326,"Parameter values taken from IGN53 Mare to RGNC91-93 (1) ( code 15884) assuming that RGNC91-93 is equivalent to WGS 84 to within the accuracy of the transformation.",Accuracy 2 metres.,2819,-21.71,-21.32,167.75,168.19,1,0,9603,287.58,177.78,-135.41,,,,,1
-69,1302,4130,4326,,For many purposes Moznet can be considered to be coincident with WGS 84. Accuracy better than 1 metre.,1167,-27.71,-10.09,30.21,43.03,1,0,9607,0,0,0,0,0,0,0,1
-70,1542,4131,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,2359,14,18,105.61,109.32,1,0,9603,198,881,317,,,,,1
-71,1543,4131,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2360,8.58,8.83,106.49,106.79,1,0,9603,182,915,344,,,,,0
-72,1513,4132,4326,Derived in 1998 in Kangan district by Geoid for Total. Used for South Pars phases 2 and 3.,Oil exploration.,2362,27.3,28.2,51.8,53.01,1,0,9603,-241.54,-163.64,396.06,,,,,1
-73,1854,4132,4326,Derived by Geoid for Elf in 1999. EGM96 geoid used.,Oil Exploration,2782,26.21,26.87,52.49,53.43,1,0,9603,-239.1,-170.02,397.5,,,,,0
-74,1855,4132,4326,Derived by Geoid for Elf in 1999. EGM96 geoid used.,Oil Exploration,2781,29.16,29.39,50.22,50.42,1,0,9603,-244.72,-162.773,400.75,,,,,0
-75,1333,4133,4326,,"?",3246,57.52,59.75,21.74,28.2,1,0,9607,0.055,-0.541,-0.185,-0.0183,0.0003,0.007,-0.014,1
-76,1439,4134,4326,"Replaced PSD93 to WGS 84 (2) (code 8581) in 1997.","Oil exploration. Residuals 0.5m at 67% probability level.",3288,16.59,26.58,51.99,59.91,1,0,9606,-180.624,-225.516,173.919,-0.81,-1.898,8.336,16.71006,1
-77,1617,4134,4326,Accuracy better than 0.5m in block 4.,Oil exploration.,2404,19.58,21.17,56.5,59.02,1,0,9606,-191.808,-250.512,167.861,-0.792,-1.653,8.558,20.703,0
-78,15824,4135,4326,Derived at 15 satellite stations.,"Military mapping. Accuracy +/- 25m in X axis, +/- 20m in Y and Z axes.",1334,18.87,22.29,-160.3,-154.74,1,0,9603,61,-285,-181,,,,,1
-79,15825,4135,4326,Derived at 2 satellite stations.,"Military mapping. Accuracy +/- 25m in each axis.",1546,18.87,20.33,-156.1,-154.74,1,0,9603,89,-279,-183,,,,,0
-80,15826,4135,4326,Derived at 3 satellite stations.,"Military mapping. Accuracy +/- 20m in each axis.",1549,21.81,22.29,-159.85,-159.23,1,0,9603,45,-290,-172,,,,,0
-81,15827,4135,4326,Derived at 2 satellite stations.,"Military mapping. Accuracy +/- 25m in each axis.",1547,20.45,21.26,-157.36,-155.93,1,0,9603,65,-290,-190,,,,,0
-82,15828,4135,4326,Derived at 8 satellite stations.,"Military mapping only. Accuracy +/- 10m in X axis, +/- 6m in Y and Z axes.",1548,21.2,21.75,-158.33,-157.61,1,0,9603,58,-283,-182,,,,,0
-83,6208,6207,4326,Derived at 11 points.,"Topographic mapping. Accuracy 0.26m (1-sigma).",1171,26.36,30.43,80.05,88.2,1,0,9603,293.17,726.18,245.36,,,,,1
-84,1893,4139,4326,Derived at 11 stations.,For military purposes only. Accuracy 3m in each axis.,1335,17.62,18.78,-67.97,-64.25,1,0,9603,11,72,-101,,,,,1
-85,1473,4140,4326,"For many purposes NAD83(CSRS98) can be considered to be coincident with WGS 84.","Approximation at the +/- 1m level assuming that NAD83(CSRS98) is equivalent to WGS 84.",1336,44.61,62.56,-120,-57.1,1,1,9603,0,0,0,,,,,0
-86,1073,4141,4326,For more accurate transformation contact Survey of Israel.,"Accuracy: 2m",2603,29.45,33.28,34.17,35.69,1,0,9603,-48,55,52,,,,,1
-87,1469,4142,4326,,"?",2282,5.15,5.54,-4.22,-3.85,1,0,9603,-125,53,467,,,,,1
-88,1470,4143,4326,"Derived in Abidjan for use in the immediate area, but used by E&P industry more widely onshore and offshore. A similar transformation (tfm code 6872) was used by Western Geophysical for offshore surveys in the 1990s.",Accuracy is submetre in the area around Abidjan but unknown farther afield. There is some evidence of unknown reliability that suggests accuracy of better than 2m throughout offshore.,1075,1.02,10.74,-8.61,-2.48,1,0,9603,-124.76,53,466.79,,,,,1
-89,6872,4143,4326,"Derived and used by Western Geophysical for offshore surveys in the 1990s, but exact provenance uncertain. Used by OMV.",Accuracy uncertain but there is some evidence of unknown reliability that suggests accuracy of better than 2m throughout offshore.,2296,1.02,5.19,-7.55,-3.11,1,0,9603,-123.1,53.2,465.4,,,,,0
-90,1155,4144,4326,Derived at 6 stations.,"For military purposes. Accuracy 10m, 8m and 12m in X, Y and Z axes.",3217,20.52,26.63,88.04,92.67,1,0,9603,282,726,254,,,,,0
-91,1533,4144,4326,,Oil exploration.,2361,9.48,17.87,93.94,99.66,1,0,9603,214,804,268,,,,,1
-92,1247,4145,4326,"Care! DMA ellipsoid is inconsistent with EPSG ellipsoid - transformation parameter values may not be appropriate. No accuracy estimate available.",For military purposes.,3289,23.64,37.07,60.86,77.83,1,0,9603,283,682,231,,,,,1
-93,15494,4145,4326,Derived by Fugro-Geodetic in 2004 at 6 closely-spaced stations. Used by OMV in all blocks in Pakistan where operator.,Oil exploration.,3589,25.88,27.67,68.24,69.3,1,0,9603,274.164,677.282,226.704,,,,,0
-94,15701,4145,4326,Derived at Geodetic Survey office in Karachi in 1997.,Oil exploration.,2985,21.05,25.39,64,68.24,1,0,9603,275.57,676.78,229.6,,,,,0
-95,15702,4145,4326,"Derived at station S0001, an approximate offset to Survey of India primary station Kat Baman, in 1992 from 180 single point Transit passes observed in 1991 by Fugro-Geodetic for UTP.",Oil exploration.,2984,24,25.64,67.74,69.87,1,0,9603,278.9,684.39,226.05,,,,,0
-96,15703,4145,4326,Derived at Chitrawala triangulation station by Fugro-Geodetic for UTP.,Oil exploration.,2982,24.69,25.76,66.83,68,1,0,9603,271.905,669.593,231.495,,,,,0
-97,15704,4145,4326,Derived by Western Geophysical for UTP 1996 East Sind 2D survey.,Oil exploration.,2983,24.16,28.61,68.27,71.11,1,0,9606,230.25,632.76,161.03,-1.114,1.115,1.212,12.584,0
-98,1156,4146,4326,"Care! DMA ellipsoid is inconsistent with EPSG ellipsoid - transformation parameter values may not be appropriate. Also source CRS may not apply to Nepal. Derived at 7 stations.","For military purposes. Accuracy 12m, 10m and 15m in X, Y and Z axes.",2411,8.02,35.51,68.08,97.39,1,0,9603,295,736,257,,,,,1
-99,1544,4147,4326,Derived in Vung Tau area.,Oil exploration.,1494,9.02,11.03,105.49,107.59,1,0,9603,-17.51,-108.32,-62.39,,,,,1
-100,1505,4148,4326,,For many purposes Hartebeesthoek94 datum can be considered to be coincident with WGS 84.,1215,-50.32,-22.13,13.33,42.85,1,0,9603,0,0,0,,,,,1
-101,1508,4149,4326,"Implemented in Bundesamt für Landestopographie programme GRANIT.","?",1286,45.82,47.81,5.96,10.49,1,1,9607,660.077,13.551,369.344,0.804816,0.577692,0.952236,5.66,0
-102,1510,4149,4326,"These parameters are strictly between CH1903+ and CHTRF95 but are used from CH1903 as an approximation which is within the accuracy of the distortions in the CH1903 network.",Accuracy 1.5 metres.,1286,45.82,47.81,5.96,10.49,1,1,9603,674.374,15.056,405.346,,,,,0
-103,1753,4149,4326,"Implemented in Bundesamt für Landestopographie programme GRANIT. Used from 1987 to 1997. Not recommended for current usage - replaced by CH1903 to WGS 84 (2) (code 1766).","?",1286,45.82,47.81,5.96,10.49,1,0,9607,660.077,13.551,369.344,0.804816,0.577692,0.952236,5.66,0
-104,1766,4149,4326,"These parameters are derive from CH1903+ to ETRS89 (code 1647) and are used at lesser precision from CH1903 to WGS 84 as an approximation which is within the accuracy of the distortions in the CH1903 network. Replaces CH1903 to WGS 84 (1) (code 1753).",Accuracy 1.5 metres.,1286,45.82,47.81,5.96,10.49,1,0,9603,674.4,15.1,405.3,,,,,1
-105,1676,4150,4326,"Parameter values are from CH1903+ to CHTRF95 (1) (code 1509) assuming that CHTRF95 is equivalent to WGS 84. That transformation is also given as CH1903+ to ETRS89 (1) (code 1647). CHTRF95 is a realisation of ETRS89.","Approximation at the +/- 1m level.",1286,45.82,47.81,5.96,10.49,1,0,9603,674.374,15.056,405.346,,,,,1
-106,1511,4151,4326,,For many purposes CHTRF95 can be considered to be coincident with WGS 84.,1286,45.82,47.81,5.96,10.49,1,0,9603,0,0,0,,,,,1
-107,1580,4152,4326,"For many purposes NAD83(HARN) can be considered to be coincident with WGS 84.","Approximation at the +/- 1m level assuming that NAD83(HARN) is equivalent to WGS 84.",1337,-14.59,49.38,144.58,-64.51,1,0,9603,0,0,0,,,,,1
-108,1900,4152,4326,"Approximation derived ignoring time-dependent parameters and assuming ITRF94(1996.0) and WGS 84, plus NAD83(CORS94) and NAD83(HARN), can be considered the same within the accuracy of the transformation. Replaced by NAD83(HARN) to WGS 84 (3) (code 1901).",Historical record only - superseded - see remarks.,1323,24.41,49.38,-124.79,-66.91,1,0,9607,-0.9738,1.9453,0.5486,-0.0275507901704247,-0.0100492213603585,-0.0113590028800276,0,0
-109,1901,4152,4326,"Approximation derived from tfm code 6864 ignoring time-dependent parameters and assuming ITRF96(1997.0) and WGS 84, plus NAD83(CORS96) and NAD83(HARN), can be considered the same within the accuracy of the tfm. In USA only replaces tfm code 1900.","Geodesy. Accuracy with respect to CORS at stations adjusted to HARN network is better than 0.05-0.07m. For locations outside a HARN network (i.e. NAD83), accuracy may be only 1m but will usually be better than 0.5m.",1323,2 [...]
-110,15930,4152,4326,"Accuracy 0.1 to 0.2m in California, 0.05-0.11 in Oregon, elsewhere better than 0.05m.",For applications to an accuracy of 0.2 metre.,1323,24.41,49.38,-124.79,-66.91,1,1,9603,0,0,0,,,,,0
-111,1512,4153,4326,"Derived in 1998 at Assaluyeh (Taheri refinery) by Geoid for Total. Used for South Pars phases 2 and 3.",Oil industry engineering survey. Used only for terminal site.,1338,27.39,27.61,52.5,52.71,1,0,9603,-133.63,-157.5,-158.62,,,,,1
-112,1141,4154,4326,"Given by DMA as from ED50. OGP interpret that as ED50(ED77) in Iran. Derived at 27 stations.","For military purposes. Accuracy 9m, 12m and 11m in X, Y and Z axes.",1123,23.34,39.78,44.03,63.34,1,0,9603,-117,-132,-164,,,,,1
-113,1514,4154,4326,"Used for South Pars phases 6, 7 and 8.","Transformation for whole country: accuracy about 1m.",1123,23.34,39.78,44.03,63.34,1,0,9606,-110.33,-97.73,-119.85,0.3423,1.1634,0.2715,0.063,0
-114,1856,4154,4326,Derived in Kangan district by Geoid for Total in 1998. Used for South Pars phases 2 and 3.,Petroleum Exploration and Production.,2783,26.58,26.71,52.07,52.28,1,0,9603,-122.89,-159.08,-168.74,,,,,0
-115,1857,4154,4326,Derived in 1999 on Lavan island by Geoid for Elf.,Petroleum Exploration and Production.,2782,26.21,26.87,52.49,53.43,1,0,9603,-84.78,-107.55,-137.25,,,,,0
-116,1858,4154,4326,Derived by Geoid for Elf in 1999. EGM96 geoid used.,Petroleum Exploration and Production.,2781,29.16,29.39,50.22,50.42,1,0,9603,-123.92,-155.515,-157.721,,,,,0
-117,15745,4154,4326,Derived in Tombak district in March 2005. Used for South Pars phase 11.,Petroleum Exploration and Production.,3140,26.46,26.64,52.22,52.41,1,0,9603,-123.02,-158.95,-168.47,,,,,0
-118,1518,4155,4326,,Accuracy 25m in each axis.,3257,7.19,12.68,-15.13,-7.65,1,0,9603,-83,37,124,,,,,1
-119,1623,4156,4326,"Parameter values from S-JTSK to ETRS89 (1) (code 1622). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaced by S-JTSK to WGS 84 (5) (code 5239).",For applications to an accuracy of 1 metre.,1079,48.58,51.06,12.09,18.86,1,0,9606,570.8,85.7,462.8,4.998,1.587,5.261,3.56,0
-120,1625,4156,4326,"Parameter values from S-JTSK to ETRS89 (2) (code 1624). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1211,47.73,49.61,16.84,22.56,1,1,9606,559,68.7,451.5,7.92,4.073,4.251,5.71,0
-121,4828,4156,4326,"Parameter values from S-JTSK to ETRS89 (4) (code 4827). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1211,47.73,49.61,16.84,22.56,1,1,9606,485,169.5,483.5,7.786,4.398,4.103,0,0
-122,4836,4156,4326,"Parameter values from S-JTSK to ETRS89 (4) (code 4827). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1211,47.73,49.61,16.84,22.56,1,0,9606,485,169.5,483.8,7.786,4.398,4.103,0,0
-123,5239,4156,4326,"Parameter values from S-JTSK/05 to WGS 84 (1) (code 5227). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaces tfm code 1622.",For applications to an accuracy of 1 metre.,1079,48.58,51.06,12.09,18.86,1,0,9607,572.213,85.334,461.94,-4.9732,-1.529,-5.2484,3.5378,0
-124,15965,4156,4326,Derived at 6 stations.,"For military purposes. Accuracy 4m, 2m and 3m in X, Y and Z axes.",1306,47.73,51.06,12.09,22.56,1,0,9603,589,76,480,,,,,1
-125,1283,4669,4326,,LKS94 is a realisation of ETRS89 coincident to WGS 84 within 1 metre. This transformation has an accuracy equal to the coincidence figure.,1145,53.89,56.45,19.02,26.82,1,0,9603,0,0,0,,,,,1
-126,1099,4670,4326,"Parameter values taken from IGM95 to ETRS89 (1) (code 1098) assuming that ETRS89 is coincident with WGS 84 within the accuracy of the transformation.",Approximation at the 1m level.,3343,34.76,47.1,5.93,18.99,1,0,9603,0,0,0,,,,,1
-127,1859,4159,4326,"Used by Repsol in Murzuq field, and PetroCanada and previous licence holders in NC177 and 72 (En Naga field). Reliability of connection to ELD79 questionned.",Oil Exploration,2785,27.32,27.67,18.37,18.72,1,0,9603,-69.06,-90.71,-142.56,,,,,0
-128,1860,4159,4326,Derived December 2001 by NAGECO. Connected to ITRF via Remsa 2000 data. Used by TotalFinaElf.,Oil Exploration. 3-dimensional SD at 11 points is 0.5m.,2785,27.32,27.67,18.37,18.72,1,0,9603,-113.997,-97.076,-152.312,,,,,0
-129,1861,4159,4326,Derived by GEOID in 1994 from Transit satellite data. Used by TotalFinaElf.,Oil Exploration,2786,29.61,30.07,17.13,17.51,1,0,9603,-114.5,-96.1,-151.9,,,,,0
-130,1862,4159,4326,"Derived by Geoid in 2000 from ITRF connection by NAGECO for TotalFinaElf. For historic compatibility TFE use the 1994 tfm ELD79 to WGS 84 (3) (code 1861) rather than this transformation.",Oil Exploration,2786,29.61,30.07,17.13,17.51,1,0,9606,-194.513,-63.978,-25.759,-3.4027,3.756,-3.352,-0.9175,0
-131,1863,4159,4326,"Derived for the Great Man-made River Authority (GMRA).",Engineering survey and oil exploration,2786,29.61,30.07,17.13,17.51,1,0,9607,-389.691,64.502,210.209,-0.086,-14.314,6.39,0.9264,0
-132,15707,4159,4326,"Used by Petrocanada and previous licence holders in Amal field, concession 12.",Oil exploration and production,2987,29.1,29.8,20.8,21.4,1,0,9603,-118.996,-111.177,-198.687,,,,,0
-133,15778,4159,4326,"Derived by Total at stations SDL 130-03, 04 and 05 in May 2005.",Oil exploration and production.,3142,27.5,28.07,21.25,21.59,1,0,9603,-114.7,-98.5,-150.7,,,,,0
-134,15909,4159,4326,Derived at 29 stations throughout Libya in May 2006.,For applications to an accuracy of 5 metres.,3271,19.49,33.23,9.31,25.21,1,0,9603,-115.8543,-99.0583,-152.4616,,,,,1
-135,15923,4159,4326,"Derived by SDL for Total in Cyrenaica blocks 2 & 4.",Oil and gas exploration.,3477,32,32.8,22.49,23,1,0,9603,-117.7,-100.3,-152.4,,,,,0
-136,1080,4672,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,2889,-44.64,-43.3,-177.25,-175.54,1,0,9603,175,-38,113,,,,,1
-137,1081,4673,4326,Derived at 4 stations using concatenation through WGS72. Parameter vales are also used to transform CI1979 to NZGD2000 - see tfm code 1082.,For applications requiring 2m accuracy.,2889,-44.64,-43.3,-177.25,-175.54,1,0,9607,174.05,-25.49,112.57,0,0,-0.554,0.2263,1
-138,15894,4674,4326,,Accuracy 1m.,3418,-59.87,32.72,-122.19,-25.28,1,0,9603,0,0,0,,,,,1
-139,1070,4675,4326,Derived at 5 stations.,For military purposes only. Accuracy 3m in each axis.,3255,13.18,13.7,144.58,145.01,1,0,9603,-100,-248,259,,,,,1
-140,1682,4164,4326,"Parameter values taken from South Yemen to Yemen NGN96 (1) (code 1539) assuming that NGN96 is equivalent to WGS 84 within the accuracy of the transformation.","Approximation at the +/- 5m level.",1340,12.54,19,43.37,53.14,1,0,9603,-76,-138,67,,,,,1
-141,1547,4165,4326,Derived at 2 stations.,For military purposes only. Accuracy 25m in each axis.,3258,10.87,12.69,-16.77,-13.64,1,0,9603,-173,253,27,,,,,1
-142,1065,4678,4326,Derived at 25 stations.,Accuracy 5m.,1138,13.92,22.5,100.09,107.7,1,0,9603,44.585,-131.212,-39.544,,,,,1
-143,1565,4167,4326,,Assumes NZGD2000 is coincident to WGS 84 to the 1m accuracy level.,1175,-55.95,-25.88,160.6,-171.2,1,0,9603,0,0,0,,,,,1
-144,1569,4168,4326,Derived at 3 common points.,Military survey,1104,1.4,11.16,-3.79,2.1,1,0,9603,-199,32,322,,,,,1
-145,15495,4168,4326,Derived via WGS 72BE. Found in use within oil industry erroneously concatenated via WGS 72. See tfm code 8571.,Oil industry.,1505,1.4,6.06,-3.79,2.1,1,0,9606,-171.16,17.29,325.21,0,0,0.814,-0.38,0
-146,1577,4169,4326,Transformation based on observations at 2 stations in 1993.,For military purposes. One sigma uncertainty is 25m in each axis.,3109,-14.43,-14.11,-170.88,-169.38,1,0,9603,-115,118,426,,,,,1
-147,1581,4170,4326,,For military purposes. Accuracy 1m in each axis.,3448,-59.87,16.75,-113.21,-26,1,0,9603,0,0,0,,,,,1
-148,1671,4171,4326,"Parameter values from RGF93 to ETRS89 (1) (code 1591) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation.","Approximation at the +/- 1m level.",1096,41.15,51.56,-9.86,10.38,1,0,9603,0,0,0,,,,,1
-149,1598,4172,4326,,"?",1033,-58.41,-21.78,-73.59,-52.63,1,1,9603,0,0,0,,,,,0
-150,1678,4173,4326,Assumes that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. IRENET95 is a regional realisation of ETRS89.,"Approximation at the +/- 1m level.",1305,51.39,55.43,-10.56,-5.34,1,0,9603,0,0,0,,,,,1
-151,15738,4686,4326,,MAGNA-SIRGAS is a realisation of WGS 84 coincident to within 1 metre. This transformation has an accuracy equal to the coincidence figure.,1070,-4.23,15.51,-84.77,-66.87,1,0,9603,0,0,0,,,,,1
-152,1614,4175,4326,"Determined at 8 stations. Info. source has the source CRS as Sierra Leone 1960. Sierra Leone 1968 is a readjustment of the 1960 network: coordinates changed by less than 3 metres.","Accuracy +/- 15m in each axis.",3306,6.88,10,-13.35,-10.26,1,0,9603,-88,4,101,,,,,1
-153,1890,4176,4326,For many purposes Australian Antarctic can be considered to be coincident with WGS 84.,"Approximation at the +/- 1m level assuming that Australian Antarctic is equivalent to WGS 84.",1278,-90,-60,45,160,1,0,9603,0,0,0,,,,,1
-154,15773,4689,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from IGN63 Hiva Oa to RGPF (1) (tfm code 15761).","Accuracy +/- 1 metre.",3131,-9.89,-9.64,-139.23,-138.75,1,0,9607,410.721,55.049,80.746,-2.5779,-2.3514,-0.6664,17.3311,1
-155,15774,4689,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from IGN63 Hiva Oa to RGPF (2) (tfm code 15762).","Accuracy +/- 2 metres.",3132,-10.08,-9.86,-139.19,-138.98,1,0,9607,374.716,-58.407,-0.957,-16.2111,-11.4626,-5.5357,-0.5409,0
-156,1675,4178,4326,"Parameter values from Pulkovo 1942(83) to ETRS89 (1) (code 1674) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation.",Residuals under 2 m.,1343,50.2,54.74,9.92,15.04,1,0,9607,24,-123,-94,-0.02,0.25,0.13,1.1,0
-157,15996,4178,4326,Derived at 5 stations.,For military purposes. Accuracy 2m in each axis.,1119,45.74,48.58,16.11,22.9,1,0,9603,28,-121,-77,,,,,0
-158,15998,4178,4326,Derived at 6 stations.,"For military purposes only. Accuracy 3m, 3m and 2m in X, Y and Z axes.",1306,47.73,51.06,12.09,22.56,1,0,9603,26,-121,-78,,,,,1
-159,1645,4179,4326,"Parameter values from Pulkovo 1942(58) to ETRS89 (1) (code 1644). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,3293,49,54.89,14.14,24.15,1,0,9606,33.4,-146.6,-76.3,-0.359,-0.053,0.844,-0.84,1
-160,15496,4179,4326,,Oil exploration,1197,43.44,48.27,20.26,31.41,1,0,9603,44.107,-116.147,-54.648,,,,,0
-161,15497,4179,4326,Derived at 4 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",1197,43.44,48.27,20.26,31.41,1,0,9603,28,-121,-77,,,,,0
-162,15995,4179,4326,"Parameter values taken from Pulkovo 1942(58) to ETRS89 (4) (code 15994) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation.","Accuracy of 1.5 to 3 metres horizontal, 3 to 5m vertical.",1197,43.44,48.27,20.26,31.41,1,0,9607,2.329,-147.042,-92.08,0.309,-0.325,-0.497,5.69,0
-163,15997,4179,4326,Derived at 11 stations.,"For military purposes only. Accuracy 4m, 2m and 4m in X, Y and Z axes.",3293,49,54.89,14.14,24.15,1,0,9603,23,-124,-82,,,,,0
-164,15999,4179,4326,Derived at 7 stations.,For military purposes. Accuracy 3m in each axis.,3212,39.64,42.67,19.22,21.06,1,0,9603,24,-130,-92,,,,,0
-165,1649,4180,4326,"Parameter values taken from EST97 to ETRS89 (1) (code 1648). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1090,57.52,60,20.37,28.2,1,0,9603,0,0,0,,,,,1
-166,1643,4181,4326,"Parameter values from Luxembourg 1930 to ETRS89 (1) (code 1642). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1146,49.44,50.19,5.73,6.53,1,0,9606,-193,13.7,-39.3,-0.41,-2.933,2.688,0.43,0
-167,5486,4181,4326,"Parameter values from Luxembourg 1930 to ETRS89 (3) (code 5485) assuming ETRS89 and WGS 84 are coincident within the one metre level. Replaces tfm code 1643. For an equivalent transformation using the Molodensky-Badekas method see code 5484.",For applications to an accuracy of 1 metre.,1146,49.44,50.19,5.73,6.53,1,0,9607,-189.6806,18.3463,-42.7695,0.33746,3.09264,-2.53861,0.4598,1
-168,1210,4694,4326,,POSGAR 94 is a local realisation of WGS 84.,1033,-58.41,-21.78,-73.59,-52.63,1,0,9603,0,0,0,,,,,1
-169,1886,4183,4326,Derived at 5 stations.,For military purposes only. Accuracy 3m in each axis.,1301,38.32,39.14,-28.9,-26.97,1,0,9603,-104,167,-38,,,,,1
-170,1885,4184,4326,Derived at 2 stations.,For military purposes only. Accuracy 25m in each axis.,1345,36.87,37.96,-25.92,-24.62,1,0,9603,-203,141,53,,,,,1
-171,15794,4708,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,1069,-12.25,-12.08,96.76,96.92,1,0,9603,-491,-22,435,,,,,1
-172,15850,4698,4326,"Also published in US NIMA/NGA TR8350.2 which gives accuracy of +/-25m in each axis and states that derived at one station.","Accuracy +/- 10 metres.",2816,-49.78,-48.6,68.69,70.62,1,0,9603,145,-187,103,,,,,1
-173,15784,4699,4326,Derived at 17 stations in 1994 by University of East London. Residuals less than 2m.,Accuracy 2m.,3209,-20.57,-19.94,57.25,57.85,1,0,9603,-770.1,158.4,-498.2,,,,,1
-174,1955,4188,4326,"Parameter values from TM75 to ETRS89 (2) (code 1953). Assumes each pair of (i) OSNI 1952 and TM75, and (ii) ETRS89 and WGS 84, can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,2530,53.96,55.36,-8.18,-5.34,1,0,9606,482.5,-130.6,564.6,-1.042,-0.214,-0.631,8.15,1
-175,1768,4189,4326,,"Approximation at the +/- 1m level.",1251,0.64,16.75,-73.38,-58.95,1,0,9603,0,0,0,,,,,1
-176,1773,4190,4326,,"Approximation at the +/- 1m level.",1033,-58.41,-21.78,-73.59,-52.63,1,0,9603,0,0,0,,,,,1
-177,15780,4190,4326,,"Approximation at the +/- 1m level.",1033,-58.41,-21.78,-73.59,-52.63,1,1,9603,0,0,0,,,,,0
-178,15873,4192,4326,Derived at Manoca tower assuming the pyramid on the tower and the centre of the tower reservoir are co-located. This assumption carries a few metres uncertainty.,Oil exploration.,2555,2.16,4.99,8.45,10.4,1,0,9603,-206.1,-174.7,-87.7,,,,,1
-179,1796,4193,4326,"Derived at two points, checked at a third by Stolt Comex Seaway and Geoid for Elf.",Oil industry,2555,2.16,4.99,8.45,10.4,1,0,9603,-70.9,-151.8,-41.4,,,,,1
-180,1797,4194,4326,Derived at 2 stations.,"For military purposes. Accuracy 25m, 25m and 32m in X, Y and Z axes.",3362,59.74,79,-73.29,-42.52,1,0,9603,164,138,-189,,,,,1
-181,1798,4194,4326,,Topographic mapping.,3362,59.74,79,-73.29,-42.52,1,0,9606,163.511,127.533,-159.789,0,0,0.814,-0.6,0
-182,1799,4195,4326,,Topographic mapping.,2570,68.66,74.58,-29.69,-19.89,1,0,9606,105,326,-102.5,0,0,0.814,-0.6,1
-183,1800,4196,4326,,Topographic mapping.,2571,65.52,65.91,-38.86,-36.81,1,0,9606,-45,417,-3.5,0,0,0.814,-0.6,1
-184,15796,4709,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,3200,24.67,24.89,141.2,141.42,1,0,9603,145,75,-272,,,,,1
-185,15798,4710,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,3183,-16.08,-15.85,-5.85,-5.58,1,0,9603,-320,550,-494,,,,,1
-186,15799,4711,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,1872,24.22,24.35,153.91,154.05,1,0,9603,124,-234,-25,,,,,1
-187,1281,4200,4326,"Derived through concatenation of Pulkovo 1995 to PZ-90 (1) (tfm code 1257) and PZ-90 to WGS 84 (2) (tfm code 1244). Mandated for use in Russia by GOST R 51794-2001, but this has been superseded by GOST R 51794-2008. Replaced by tfm code 5043.",Accuracy 1 metre.,1198,39.87,85.2,18.92,-168.97,1,0,9607,24.82,-131.21,-82.66,0,0,-0.16,-0.12,0
-188,5043,4200,4326,"Derived through concatenation of Pulkovo 1995 to PZ-90.02 to WGS 84. Replaces Pulkovo 1995 to WGS 84 (1), tfm code 1281.",Accuracy 1 metre.,1198,39.87,85.2,18.92,-168.97,1,0,9607,24.47,-130.89,-81.56,0,0,-0.13,-0.22,1
-189,1100,4201,4326,Derived at 22 stations.,For military purposes only. Accuracy 5m in each axis.,1271,3.4,22.24,21.82,47.99,1,0,9603,-166,-15,204,,,,,1
-190,1101,4201,4326,"Derived at 1 station connected to the Adindan network through the 1968-69 12th parallel traverse. Note: Adindan datum is used in Ethiopia and Sudan, not Burkino Faso.",For military purposes. Accuracy 25m in each axis.,1057,9.39,15.09,-5.53,2.4,1,0,9603,-118,-14,218,,,,,0
-191,1102,4201,4326,"Derived at 1 station connected to the Adindan network through the 1968-69 12th parallel traverse. Note: Adindan datum is used in Ethiopia and Sudan, not Cameroon.",For military purposes. Accuracy 25m in each axis.,3226,1.65,13.09,8.45,16.21,1,0,9603,-134,-2,210,,,,,0
-192,1103,4201,4326,Derived at 8 stations.,For military purposes. Accuracy 3m in each axis.,1091,3.4,14.89,32.99,47.99,1,0,9603,-165,-11,206,,,,,0
-193,1104,4201,4326,"Derived at 1 station connected to the Adindan network through the 1968-69 12th parallel traverse. Note: Adindan datum is used in Ethiopia and Sudan, not Mali.",For military purposes. Accuracy 25m in each axis.,1153,10.14,25.01,-12.25,4.26,1,0,9603,-123,-20,220,,,,,0
-194,1105,4201,4326,"Derived at 2 stations connected to the Adindan network through the 1968-69 12th parallel traverse. Note: Adindan datum is used in Ethiopia and Sudan, not Senegal.",For military purposes. Accuracy 25m in each axis.,3304,12.29,16.7,-17.59,-11.36,1,0,9603,-128,-18,224,,,,,0
-195,1106,4201,4326,Derived at 14 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",3311,3.49,22.24,21.82,38.66,1,0,9603,-161,-14,205,,,,,0
-196,1108,4202,4326,Derived at 105 stations.,For military purposes only. Accuracy 3m in each axis.,2575,-43.7,-9.86,112.85,153.69,1,0,9603,-133,-48,148,,,,,0
-197,1665,4202,4326,"Parameter values from AGD66 to GDA94 (2) (code 1458). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation.",Recommended for mid-accuracy use in A.C.T. 1m accuracy.,2283,-35.93,-35.12,148.76,149.4,1,0,9607,-129.193,-41.212,130.73,-0.246,-0.374,-0.329,-2.955,0
-198,1666,4202,4326,"Parameter values from AGD66 to GDA94 (4) (code 1460). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation.",Recommended for mid-accuracy use in NSW and Victoria. 1m accuracy.,2286,-39.2,-28.15,140.96,153.69,1,0,9607,-119.353,-48.301,139.484,-0.415,-0.26,-0.437,-0.613,0
-199,1667,4202,4326,"Parameter values from AGD66 to GDA94 (8) (code 1594). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation.",Recommended for mid-accuracy use in Tasmania. 1m accuracy.,1282,-43.7,-39.52,143.77,148.55,1,0,9607,-120.271,-64.543,161.632,-0.217,0.067,0.129,2.499,0
-200,1668,4202,4326,"Parameter values from AGD66 to GDA94 (9) (code 1595). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation.",Recommended for mid-accuracy use in Northern Territory. 1m accuracy.,2284,-26.01,-10.86,128.99,138,1,0,9607,-124.133,-42.003,137.4,0.008,-0.557,-0.178,-1.854,0
-201,5841,4202,4326,Derived at 25 stations in 2007.,"Accuracy 2m in 2007. Due to significant tectonic activity in PNG, AGD66 and WGS 84 are separating by approximately 7cm per year.",4013,-8.28,-5.59,142.24,144.75,1,0,9603,-124,-60,154,,,,,0
-202,15788,4202,4326,"Parameter values from AGD66 to GDA94 (1) (code 1278). Derived at 162 stations. Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation.",5m accuracy.,2575,-43.7,-9.86,112.85,153.69,1,0,9603,-127.8,-52.3,152.9,,,,,0
-203,15980,4202,4326,"Parameter values from AGD66 to GDA94 (12) (code 15979). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation. Use only offshore: onshore tfms 1665-68 for ACT, NSW/Vic, Tas and NT respectively are more accurate.",3m accuracy.,3559,-47.2,-8.88,109.23,163.2,1,0,9607,-117.808,-51.536,137.784,-0.303,-0.446,-0.234,-0.29,1
-204,1109,4203,4326,"Derived at 90 stations. Note: AGD84 officially adopted only in Queensland, South Australia and Western Australia.",For military purposes only. Accuracy 2m in each axis.,2575,-43.7,-9.86,112.85,153.69,1,0,9603,-134,-48,149,,,,,1
-205,1236,4203,4326,"""Higgins parameters"". Replaced by AGD84 to GDA94 (2) (code 1280) and AGD84 to WGS 84 (7) (code 1669). Note: AGD84 officially adopted only in Queensland, South Australia and Western Australia.",Preliminary estimate.,2575,-43.7,-9.86,112.85,153.69,1,0,9607,-116,-50.47,141.69,-0.23,-0.39,-0.344,0.0983,0
-206,1669,4203,4326,"Parameter values from AGD84 to GDA94 (2) (code 1280). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaces AGD84 to WGS 84 (2) (code 1236). Note: AGD84 officially adopted only in Qld, SA and WA.",1m accuracy.,2575,-43.7,-9.86,112.85,153.69,1,0,9607,-117.763,-51.51,139.061,-0.292,-0.443,-0.277,-0.191,0
-207,15789,4203,4326,"Parameter values from AGD84 to GDA94 (1) (code 1279). Derived at 327 stations. Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the tfm. AGD84 officially adopted only in Queensland, South Australia and Western Australia.",5m accuracy.,2575,-43.7,-9.86,112.85,153.69,1,0,9603,-128.5,-53,153.4,,,,,0
-208,1055,4204,4326,Derived at station K1.,1 metre accuracy.,3267,28.53,30.09,46.54,48.48,1,0,9603,-145.7,-249.1,1.5,,,,,0
-209,1056,4204,4326,"Derivation is more precise, but no evidence that accuracy is better than Ain el Abd to WGS 84 (3). OGP recommends using Ain el Abd to WGS 84 (3).",1 metre accuracy.,3267,28.53,30.09,46.54,48.48,1,0,9607,-85.645,-273.077,-79.708,-2.289,1.421,-2.532,3.194,0
-210,1057,4204,4326,.,1 metre accuracy.,2956,29.1,30.09,46.54,48.42,1,0,9607,-202.234,-168.351,-63.51,-3.545,-0.659,1.945,2.1,0
-211,1058,4204,4326,,1 metre accuracy.,2957,28.53,29.45,46.54,48.48,1,0,9607,-18.944,-379.364,-24.063,-0.04,0.764,-6.431,3.657,0
-212,1110,4204,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,3943,25.53,26.34,50.39,50.85,1,0,9603,-150,-250,-1,,,,,0
-213,1111,4204,4326,Derived at 9 stations.,For military purposes. Accuracy 10m in each axis.,3303,15.61,32.16,34.51,55.67,1,0,9603,-143,-236,7,,,,,1
-214,1107,4205,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,3308,-1.71,12.03,40.99,51.47,1,0,9603,-43,-163,45,,,,,1
-215,15805,4718,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3198,-8.86,-7.52,156.44,158.2,1,0,9603,230,-199,-752,,,,,1
-216,15807,4718,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3197,-9.98,-9.2,159.55,160.88,1,0,9603,252,-209,-751,,,,,0
-217,1656,4207,4326,"Parameter values from Lisbon to ETRS89 (1) (code 1655). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaced by Lisbon to WGS 84 (4) (code 1988).",For applications to an accuracy of 3 metres.,1294,36.95,42.16,-9.56,-6.19,1,0,9606,-280.9,-89.8,130.2,-1.721,0.355,-0.371,-5.92,0
-218,1944,4207,4326,"Parameter values from Lisbon to ETRS89 (2) (code 1790). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 2 metres.,1294,36.95,42.16,-9.56,-6.19,1,1,9606,-282.1,-72.2,120,-1.592,0.145,-0.89,-4.46,0
-219,1984,4207,4326,,For low resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9603,-304.046,-60.576,103.64,,,,,1
-220,1988,4207,4326,,For medium resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9607,-288.885,-91.744,126.244,1.691,-0.41,0.211,-4.598,0
-221,1549,4208,4326,,Oil exploration.,2307,-28.41,-17.59,-48.8,-35.18,1,1,9603,-158,315,-148,,,,,0
-222,1550,4208,4326,"Replaced by Aratu to WGS 84 (18) (tfm code 5061) which Petrobras now recommends for the area.",Oil exploration.,2308,-9.8,-8.39,-39.04,-37.09,1,0,9603,-139.62,290.53,-150.29,,,,,0
-223,1551,4208,4326,"Replaced by Aratu to WGS 84 (18) (tfm code 5061) which Petrobras now recommends for the area.",Oil exploration.,2309,-10.61,-9.79,-39.14,-37.99,1,0,9603,-141.15,293.44,-150.56,,,,,0
-224,1552,4208,4326,"Replaced by Aratu to WGS 84 (18) (tfm code 5061) which Petrobras now recommends for the area.",Oil exploration.,2310,-12.27,-10.6,-39.07,-37.98,1,0,9603,-142.48,296.03,-149.74,,,,,0
-225,10089,4208,4326,"Used by ExxonMobil for block BMS1. See WGS 84 (13) (tfm code 5051) which Petrobras now recommends for the area.",Oil exploration.,2962,-28.41,-22.66,-48.8,-40.2,1,0,9603,-163.466,317.396,-147.538,,,,,0
-226,10090,4208,4326,"Used by ExxonMobil for block BC10. Derived from earlier Shell position vector tfm of dX = -181m, dY = +294m, dZ = -144.5m, rX = rY = 0, rZ = +0.554s, dS = +0.219 ppm. See Aratu to WGS 84 (14) (tfm code 5053) which Petrobras now recommends for the area.",Oil exploration.,2963,-25.91,-20.45,-42.04,-37.11,1,0,9603,-170,305,-145,,,,,0
-227,10091,4208,4326,"Used by ExxonMobil for block BMES1. See Aratu to WGS 84 (15) (tfm code 5055) which Petrobras now recommends for the area.",Oil exploration.,2964,-22.04,-17.59,-40.37,-35.18,1,0,9603,-162.904,312.531,-137.109,,,,,0
-228,10092,4208,4326,"Used by ExxonMobil for block BP1. Also used by BG as part of a concatenated tfm to SAD69 for offshore regional studies. See WGS 84 (13) (tfm code 5051) for transformation Petrobras now recommends for the area.",Oil exploration.,2965,-35.71,-28.11,-53.38,-44.71,1,0,9603,-158,309,-151,,,,,0
-229,10093,4208,4326,"Used by ExxonMobil for offshore regional studies. See Aratu to WGS 84 (13) through (21) (tfm codes 5051-67 [odd numbers only]) which Petrobras now recommends for various areas.",Oil exploration.,2966,-34,-18,-53.38,-35.19,1,0,9603,-161,308,-142,,,,,0
-230,10094,4208,4326,Derived by IGN in 1992 at 7 stations within Nouakchott city.,Oil exploration.,2972,17.89,18.25,-16.11,-15.83,1,1,9603,124.5,-63.5,-281,,,,,0
-231,5051,4208,4326,"Parameters from Aratu to SIRGAS 2000 (1) (tfm code 5050) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area. Replaces tfm codes 15711 and 15734.",Oil exploration.,3700,-35.71,-22.66,-53.38,-40.2,1,0,9603,-157.84,308.54,-146.6,,,,,0
-232,5053,4208,4326,"Parameters from Aratu to SIRGAS 2000 (2) (tfm code 5052) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area. Replaces tfm codes 15710 and 15754.",Oil exploration.,2963,-25.91,-20.45,-42.04,-37.11,1,0,9603,-160.31,314.82,-142.25,,,,,0
-233,5055,4208,4326,"Parameters from Aratu to SIRGAS 2000 (3) (tfm code 5054) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area. Replaces tfms 15712 and 15754.",Oil exploration.,2964,-22.04,-17.59,-40.37,-35.18,1,0,9603,-161.11,310.25,-144.64,,,,,0
-234,5057,4208,4326,"Parameters from Aratu to SIRGAS 2000 (4) (tfm code 5056) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area.",Oil exploration.,3699,-17.7,-13.01,-39.22,-34.6,1,0,9603,-160.4,302.29,-144.19,,,,,0
-235,5059,4208,4326,"Parameters from Aratu to SIRGAS 2000 (5) (tfm code 5058) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area.",Oil exploration.,3692,-13.57,-11.18,-39.09,-35.31,1,0,9603,-153.54,302.33,-152.37,,,,,0
-236,5061,4208,4326,"Parameters from Aratu to SIRGAS 2000 (6) (tfm code 5060) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area. Replaces tfms 1550-1552.",Oil exploration.,3693,-12.27,-8.39,-39.14,-37.09,1,0,9603,-151.5,300.09,-151.15,,,,,0
-237,5063,4208,4326,"Parameters from Aratu to SIRGAS 2000 (7) (tfm code 5062) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area.",Oil exploration.,3696,-13.58,-8.73,-37.34,-32.01,1,0,9603,-156.8,298.41,-147.41,,,,,0
-238,5065,4208,4326,"Parameters from Aratu to SIRGAS 2000 (8) (tfm code 5064) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation.Petrobras preferred parameters for all purposes in the area.",Oil exploration.,3697,-10.17,-4.6,-35.1,-29.13,1,0,9603,-157.4,295.05,-150.19,,,,,0
-239,5067,4208,4326,"Parameters from Aratu to SIRGAS 2000 (9) (tfm code 5066) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area.",Oil exploration.,3698,-6.5,4.26,-44.79,-26,1,0,9603,-151.99,287.04,-147.45,,,,,1
-240,15710,4208,4326,"Replaced by Aratu to WGS 84 (14) (tfm code 5053) which Petrobras now recommends for the area.",Oil exploration.,2963,-25.91,-20.45,-42.04,-37.11,1,0,9603,-160,315,-142,,,,,0
-241,15711,4208,4326,"Replaced by Aratu to WGS 84 (13) (tfm code 5051) which Petrobras now recommends for the area.",Oil exploration.,2962,-28.41,-22.66,-48.8,-40.2,1,0,9603,-158,309,-147,,,,,0
-242,15712,4208,4326,"Replaced by Aratu to WGS 84 (15) (tfm code 5055) which Petrobras now recommends for the area.",Oil exploration.,2964,-22.04,-17.59,-40.37,-35.18,1,0,9603,-161,310,-145,,,,,0
-243,15754,4208,4326,"Mean for 3 basins. See Aratu to WGS 84 (10) through (12) (codes 15710-12) for transformations for individual basins. Replaced by Aratu to WGS 84 (13) through (15) (tfm codes 5051, 5053 and 5055) which Petrobras now recommends for the areas.",Oil exploration.,2307,-28.41,-17.59,-48.8,-35.18,1,0,9603,-158,315,-148,,,,,0
-244,1113,4209,4326,Derived at 41 stations.,"For military purposes only. Accuracy 20m, 33m and 20m in X, Y and Z axes.",2312,-30.66,-8.19,19.99,35.93,1,0,9603,-143,-90,-294,,,,,1
-245,1114,4209,4326,Derived at 9 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",1051,-26.88,-17.78,19.99,29.38,1,0,9603,-138,-105,-289,,,,,0
-246,1115,4209,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,1058,-4.45,-2.3,28.98,30.86,1,1,9603,-153,-5,-292,,,,,0
-247,1116,4209,4326,Derived at 5 stations.,"For military purposes. Accuracy 3m, 3m and 8m in X, Y and Z axes.",1141,-30.66,-28.57,27.01,29.46,1,0,9603,-125,-108,-295,,,,,0
-248,1117,4209,4326,Derived at 6 stations.,"For military purposes. Accuracy 9m, 24m and 8m in X, Y and Z axes.",1150,-17.14,-9.37,32.68,35.93,1,0,9603,-161,-73,-317,,,,,0
-249,1118,4209,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,1224,-27.32,-25.72,30.79,32.14,1,0,9603,-134,-105,-295,,,,,0
-250,1119,4209,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,1259,-13.46,5.39,11.79,31.31,1,1,9603,-169,-19,-278,,,,,0
-251,1120,4209,4326,Derived at 5 stations.,"For military purposes. Accuracy 21m, 21m and 27m in X, Y and Z axes.",1260,-18.08,-8.19,21.99,33.71,1,0,9603,-147,-74,-283,,,,,0
-252,1121,4209,4326,Derived at 10 stations.,"For military purposes. Accuracy 5m, 8m and 11m in X, Y and Z axes.",1261,-22.42,-15.61,25.23,33.08,1,0,9603,-142,-96,-293,,,,,0
-253,1122,4210,4326,Derived at 25 stations.,For military purposes only. Accuracy 20m in each axis.,2311,-11.75,4.63,29.34,41.91,1,0,9603,-160,-6,-302,,,,,1
-254,1284,4210,4326,Derived at 24 stations.,"For military purposes. Accuracy 4m, 3m and 3m in X, Y and Z axes.",3264,-4.72,4.63,33.9,41.91,1,0,9603,-157,-2,-299,,,,,0
-255,1285,4210,4326,Derived at 12 stations.,"For military purposes. Accuracy 6m, 9m and 10m in X, Y and Z axes.",3316,-11.75,-0.99,29.34,40.48,1,0,9603,-175,-23,-303,,,,,0
-256,3998,4210,4326,"Derived at 3 stations. From inspection of parameter values and geographic applicability of CRS, OGP believes that the published source CRS (Arc 1950) has been misidentified by information source. Analysis of TR8350.2 contour charts suggest Arc 1960.",For military purposes. Accuracy 20m in each axis.,1058,-4.45,-2.3,28.98,30.86,1,0,9603,-153,-5,-292,,,,,0
-257,1123,4211,4326,"Note: The area of use cited for this transformation (Sumatra) is not consistent with the area of use (Java) for the Batavia (Genuk) coordinate reference system. Derived at 5 stations.",For military purposes. Accuracy 3m in each axis.,1355,-5.99,5.97,95.16,106.13,1,0,9603,-377,681,-50,,,,,1
-258,1813,4211,4326,Used by ARCO offshore NW Java area.,Oil industry operations.,2577,-6.89,-4.07,105.77,110.01,1,0,9603,-378.873,676.002,-46.255,,,,,0
-259,1814,4211,4326,Used by PT Komaritim for Nippon Steel during East Java Gas Pipeline construction.,Oil industry operations.,2588,-8.46,-6.8,112.8,117.01,1,0,9603,-377.7,675.1,-52.2,,,,,0
-260,15793,4212,4326,"Derived at 2 stations (S40 and M1, St Annes Tower) in 2004.",Accuracy 2.5m.,3218,13,13.39,-59.71,-59.37,1,0,9603,31.95,300.99,419.19,,,,,1
-261,15809,4725,4326,"Derived at 2 satellite stations. Note: NGA online html files carry a different dZ value - OGP believe this is an erroneous transcription from the TR8350.2 line above.","Military and topographic mapping. Accuracy +/- 25m in each axis.",3201,16.67,16.79,-169.59,-169.47,1,0,9603,189,-79,-202,,,,,1
-262,6143,4726,4326,"Parameter values are taken from SIGD59 to CIGD11 (1) (code 6137) assuming that CIGD11 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1m.,3186,19.63,19.78,-80.14,-79.69,1,0,9607,8.853,-52.644,180.304,0.393,2.323,-2.96,-24.081,1
-263,15814,4726,4326,Determined from 1 satellite station.,"Military mapping. Accuracy +/- 25m in each axis.",3186,19.63,19.78,-80.14,-79.69,1,0,9603,42,124,147,,,,,0
-264,15829,4726,4326,Determined from 2 satellite stations.,"Topographic survey. Accuracy +/- 1m.",3186,19.63,19.78,-80.14,-79.69,1,0,9603,44.4,109,151.7,,,,,0
-265,15800,4713,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,1081,10.94,12.72,41.75,44.15,1,0,9603,-79,-129,145,,,,,1
-266,1124,4216,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,3221,32.21,32.43,-64.89,-64.61,1,0,9603,-73,213,296,,,,,1
-267,15970,4216,4326,"Parameter values from Bermuda 1957 to BDA2000 (1) (code 15969). Assumes BDA2000 and WGS 84 can be considered the same to within the accuracy of the transformation.","Accuracy +/- 1 metre.",3221,32.21,32.43,-64.89,-64.61,1,0,9607,-292.295,248.758,429.447,-4.9971,-2.99,-6.6906,1.0289,0
-268,15819,4729,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25 m in each axis.",3208,-25.14,-25,-130.16,-130.01,1,0,9603,185,165,42,,,,,1
-269,1125,4218,4326,Derived in 1987 at 7 stations.,"For military purposes. Accuracy 6m, 5m and 6m in X, Y and Z axes.",3686,-4.23,13.68,-79.1,-66.87,1,0,9603,307,304,-318,,,,,1
-270,1597,4218,4326,Derived in 1995 by WGC at first order stations Recreo and Mena via multi-day ties to 4 IGS stations. Residuals under 20cm.,Oil exploration.,2315,4.75,5.68,-73,-72.25,1,0,9603,304.5,306.5,-318.1,,,,,0
-271,15715,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (1) (tfm code 15714).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3082,9.8,12.52,-73,-71.06,1,0,9607,-806.413,-263.5,-622.671,12.4142185637707,-2.99084175323096,-39.0346863906349,-20.81616,0
-272,15717,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (2) (tfm code 15716).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3083,9.39,11.59,-76.08,-73,1,0,9607,100.783,187.382,-47,-9.22383004903209,2.42380329967319,-8.30827832824698,-13.56561,0
-273,15719,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (3) (tfm code 15718).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3084,8,9.4,-77.48,-74.39,1,0,9607,336.026,348.565,252.978,-17.2412894390071,-6.30649282215535,1.56204977191825,-5.771909,0
-274,15721,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (4) (tfm code 15720).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3085,5,9.4,-74.4,-71.99,1,0,9607,963.273,486.386,190.997,-16.4850360280866,-1.66882584284416,21.6928490465265,-13.89914,0
-275,15723,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (5) (tfm code 15722).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3086,5,8.01,-77.92,-74.39,1,0,9607,-90.29,247.559,-21.989,-8.69688534851263,-4.18803362841004,-12.8082668496251,2.181658,0
-276,15725,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (6) (tfm code 15724).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3087,3,5.01,-77.68,-74.39,1,0,9607,-0.562,244.299,-456.938,6.8668709851194,-8.25267346177889,-9.2967797230575,3.74656,0
-277,15727,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (7) (tfm code 15726).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3088,-1.13,3.01,-79.1,-74,1,0,9607,-305.356,222.004,-30.023,-9.69049385992583,1.03196819622539,-19.7573941768278,6.325747,0
-278,15729,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (8) (tfm code 15728).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3089,-4.23,7.1,-74.4,-66.87,1,0,9607,221.899,274.136,-397.554,2.80844591036278,-0.44850858891268,-2.81017234679107,-2.199943,0
-279,1126,4219,4326,Accuracy estimate not available.,For military purposes.,1287,-3.3,-1.44,105.07,108.35,1,0,9603,-384,664,-48,,,,,1
-280,1318,4220,4326,,Used for oil exploration by Conoco.,2316,-8.59,-7.75,12.58,13.4,1,0,9603,-42.01,-332.21,-229.75,,,,,0
-281,1319,4220,4326,,Used for oil exploration by Texaco.,2317,-7.01,-6.01,12.08,12.84,1,0,9603,-40,-354,-224,,,,,0
-282,1320,4220,4326,"Replaced by Camacupa to WGS 84 (9). Used by Shell prior to 1994.",Oil exploration prior to 1994.,2321,-7.26,-6.03,11.08,12.09,1,0,9606,-37.2,-370.6,-224,0,0,0.554,0.219,0
-283,1321,4220,4326,"Derived as mean of 123 Transit passes at station Cabo Ledo NE base in November 1990. Used by Elf for block 7 up to December 1992 then replaced by Camacupa to WGS 84 (7). Used by Total in block 8, ExxonMobil block 24, Western Geophysical for spec. data.",Oil exploration.,2320,-17.26,-6.01,8.2,13.86,1,0,9603,-41.8,-342.2,-228.2,,,,,0
-284,1322,4220,4326,"Derived at station Djeno during coordination of platform PAL F2 in February 1992. Used by Elf for block 3 up to December 1992 then replaced by Camacupa to WGS 84 (7).",Oil exploration.,2318,-7.34,-6.66,11.74,12.5,1,0,9603,-55.5,-348,-229.2,,,,,0
-285,1323,4220,4326,Derived at Luanda observatory December 1992.,Used for oil exploration by Elf for 1993 block 7 shallow water survey.,2319,-10.09,-9.41,12.66,13.39,1,0,9603,-43,-337,-233,,,,,0
-286,1324,4220,4326,"Derived at platform PAL F2 in December 1992. For use in blocks 3, 7 and 17, replaced by Camacupa to WGS 84 (10) (code 1327).","Used for oil exploration by Elf for blocks 3, 7 and 17 between December 1992 and 1994 then superseded by Camacupa to WGS 84 (10). Used by Exxon for block 15 since 1993.",2322,-10.09,-6.03,10.83,13.39,1,0,9603,-48,-345,-231,,,,,0
-287,1325,4220,4326,"Derived at platform PAL F2 in December 1992. Used by Total for block 2 between December 1992 and 1994 then replaced by Camacupa to WGS 84 (10).",Oil exploration between December 1992 and 1994.,2317,-7.01,-6.01,12.08,12.84,1,0,9603,-48.6,-345.1,-230.8,,,,,0
-288,1326,4220,4326,"Derived by GPS on two Topnav DGPS reference stations at Djeno and Luanda. Replaces Camacupa to WGS 84 (3). In block 18 replaced by BP from 1999 by Camacupa to WGS 84 (10).",Used by Shell since 1994.,2323,-8.34,-6.03,11.08,12.75,1,0,9606,-41.057,-374.564,-226.287,0,0,0.554,0.219,0
-289,1327,4220,4326,Derived at platform PAL F2 in 1994 by Topnav using Doris.,Used for oil exploration by Elf in blocks 3 and 17 since 1994. Used by Total in block 2 since 1994. Adopted by BP-Amoco Elf and Exxon for blocks 18 and 31-33 in 1999.,2324,-8.59,-6.01,10.41,12.84,1,0,9603,-50.9,-347.6,-231,,,,,1
-290,1127,4221,4326,Derived at 20 stations.,For military purposes. Accuracy 5m in each axis.,3843,-54.93,-21.78,-73.59,-53.65,1,0,9603,-148,136,90,,,,,1
-291,1527,4221,4326,"Derived through ties at 2 stations (Cerro Colorado and Chihuido Sur) to 4 IGS stations in February 1995",Oil exploration.,2325,-37.5,-36.14,-70.5,-70.03,1,0,9603,-154.5,150.7,100.4,,,,,0
-292,1128,4222,4326,Derived at 5 stations.,"For military purposes. Accuracy 3m, 6m and 6m in X, Y and Z axes.",3309,-34.88,-22.13,16.45,32.95,1,0,9603,-136,-108,-292,,,,,1
-293,1129,4222,4326,"Parameter values are from Cape to Hartebeesthoek94 (1) (code 1504) assuming that Hartebeesthoek94 and WGS 84 are equivalent within the accuracy of the transformation. Residuals should not exceed 15 metres.",Accuracy 15m.,3309,-34.88,-22.13,16.45,32.95,1,0,9603,-134.73,-110.92,-292.66,,,,,0
-294,1130,4223,4326,Derived at 5 stations.,"For military purposes. Accuracy 6m, 9m and 8m in X, Y and Z axes.",1236,30.23,38.41,7.49,13.67,1,0,9603,-263,6,431,,,,,1
-295,1538,4223,4326,Derived at station Chaffar January 1995.,Oil exploration.,1489,33.22,38.41,7.81,13.67,1,0,9603,-260.1,5.5,432.2,,,,,0
-296,1131,4224,4326,Derived at 6 stations.,"For military purposes. Accuracy 6m, 9m and 5m in X, Y and Z axes.",3675,-22,-19.29,-62.57,-57.81,1,0,9603,-134,229,-29,,,,,0
-297,3972,4224,4326,"Mandatory for SICAD use until 2005. Replaced by Chua to SIRGAS 2000 (tfm code 4069).","Used by governmental agencies in Distrito Federal until adoption of SIRGAS 2000 by Brazil in 2005. Legally mandated for Cartography System of Distrito Federal (SICAD) until 2005.",3619,-15.94,-15.37,-48.1,-47.1,1,0,9603,-143.87,243.37,-33.52,,,,,1
-298,4834,4224,4326,"Parameter values from Chua to SIRGAS 2000 (1) (tfm code 4069) assuming that within the tfm accuracy SIRGAS 2000 is equivalent to WGS 84.","Cartography System of Distrito Federal (SICAD)",3619,-15.94,-15.37,-48.1,-47.1,1,0,9603,-144.35,242.88,-33.2,,,,,0
-299,1132,4225,4326,Derived at 17 stations.,"For military purposes. Accuracy 5m, 3m and 5m in X, Y and Z axes.",1293,-33.78,-2.68,-58.16,-34.74,1,0,9603,-206,172,-6,,,,,0
-300,6192,4225,4326,"Formed by concatenation of tfms codes 6191 and 1877. Used by Petrobras and ANP until February 2005 when replaced by Corrego Alegre 1970-72 to WGS 84 (4) (tfm code 6194).",Medium and small scale mapping.,1293,-33.78,-2.68,-58.16,-34.74,1,0,9603,-205.57,168.77,-4.12,,,,,1
-301,6194,4225,4326,"Parameter values from Corrego Alegre to SIRGAS 2000 (2) (tfm code 6193) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Used by ANP and Petrobras from February 2005, replacing use of tfm code 6192.",Medium and small scale mapping.,1293,-33.78,-2.68,-58.16,-34.74,1,0,9603,-206.05,168.28,-3.82,,,,,0
-302,1585,4227,4326,,"?",1227,32.31,37.3,34.96,42.38,1,1,9603,-177.5,14.1,237.6,,,,,0
-303,1586,4227,4326,"Derived in 1995 by CGG for Al Furat Petroleum Company. Can be approximated using geocentric translations of dX=-174.3m, dY=+14.1m, dZ=+237.6m.",Oil exploration.,2327,35.33,35.9,39.15,40.41,1,0,9606,-175.09,1.218,238.831,-0.047,0.019,0.808,0.1698,0
-304,1587,4227,4326,Derived at four stations by Topnav in 1997.,Oil exploration.,2328,35.79,36.5,40.5,41.39,1,0,9603,-191.77,15.01,235.07,,,,,0
-305,15741,4227,4326,Derived by Elf in 1991 from tfm code 1584 concatenated with a tfm from WGS72BE to WGS84.,Oil exploration. Accuracy 5m.,2329,34.49,35.9,39.3,40.81,1,0,9603,-187.5,14.1,237.6,,,,,0
-306,15742,4227,4326,Derived for 1998 Omar seismic survey and used in 2000 for El Isba seismic survey.,Oil exploration. Accuracy 5m.,3314,32.31,37.3,35.61,42.38,1,0,9603,-190.421,8.532,238.69,,,,,1
-307,15743,4227,4326,"Derived 2005 at 5 triangulation stations and using (EGM96 geoid model +1.15m). Used by Total/DEZPC for Jafra and Mazraa seismic surveys. Can be approximated using geocentric translations of dX=-190.6m, dY=+8.8m, dZ=+239.6m.",Oil exploration. Accuracy 0.5m.,2329,34.49,35.9,39.3,40.81,1,0,9606,-83.58,-397.54,458.78,-17.595,-2.847,4.256,3.225,0
-308,1244,4740,4326,"Mandated for use in Russia by GosStandard of Russia Decree #327 of August 9, 2001. Republished but with one significant figure less precision to parameter values in GOST R 51794-2008 of December 18 2008.",Geodetic applications. Accuracy better than 0.5 metre.,1198,39.87,85.2,18.92,-168.97,1,0,9607,-1.08,-0.27,-0.9,0,0,-0.16,-0.12,0
-309,15843,4740,4326,"Derived through Glonass and GPS at 30 stations throughout USSR - Former Soviet Union (FSU).",Geodetic applications. Accuracy better than 1.5 metres.,1262,-90,90,-180,180,1,0,9607,0,0,1.5,0,0,-0.076,0,1
-310,1148,4229,4326,Derived at 14 stations.,"For military purposes. Accuracy 3m, 6m and 8m in X, Y and Z axes.",1086,21.89,33.82,24.7,37.91,1,0,9603,-130,110,-13,,,,,1
-311,1546,4229,4326,,Used for oil exploration by GUPCO.,2341,27.19,30.01,32.34,34.27,1,1,9603,-146.21,112.63,4.05,,,,,0
-312,1075,4230,4326,"Derived in 1987 by Geodetic for TPAO. Used on BP 1991/92 2D seismic surveys in central and eastern Turkish sector of Black Sea. In Turkey, replaced by tfm code 1784. Also adopted for use offshore Israel.",Oil Exploration,2896,31.35,43.45,28.03,41.47,1,0,9603,-89.05,-87.03,-124.56,,,,,0
-313,1087,4230,4326,,Topographic mapping.,1130,29.18,33.38,34.88,39.31,1,0,9603,-112,-110.3,-140.2,,,,,0
-314,1133,4230,4326,Derived at 85 stations. In Germany will be accepted by LBA for minerals management purposes as alternative to tfm 1052 or 1998.,"For military purposes. Accepted for minerals management in Germany. Accuracy 3m, 8m and 5m in X, Y and Z axes.",2420,34.88,71.21,-9.56,31.59,1,0,9603,-87,-98,-121,,,,,1
-315,1134,4230,4326,Derived at 52 stations.,For military purposes only. Accuracy 3m each axis.,2421,42.33,57.8,-4.87,17.17,1,0,9603,-87,-96,-120,,,,,0
-316,1135,4230,4326,Accuracy estimate not available.,For military purposes only.,2345,15.61,37.39,34.17,55.67,1,0,9603,-103,-106,-141,,,,,0
-317,1136,4230,4326,Derived at 4 stations.,For military purposes only. Accuracy 15m in each axis.,1078,32.88,36.21,29.95,35.2,1,0,9603,-104,-101,-140,,,,,0
-318,1137,4230,4326,Derived at 14 stations.,"For military purposes. Accuracy 6m, 8m and 8m in X, Y and Z axes.",2595,25.71,31.68,24.7,30,1,0,9603,-130,-117,-151,,,,,0
-319,1138,4230,4326,Derived at 40 stations.,For military purposes only. Accuracy 3m in each axis.,2343,49.11,60.9,-10.56,1.84,1,0,9603,-86,-96,-120,,,,,0
-320,1139,4230,4326,Derived at 20 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",2344,57.93,71.21,4.68,31.59,1,0,9603,-87,-95,-120,,,,,0
-321,1140,4230,4326,Derived at 2 stations.,For military purposes only. Accuracy 25m in each axis.,3254,34.88,41.75,19.57,28.3,1,0,9603,-84,-95,-130,,,,,0
-322,1142,4230,4326,Derived at 2 stations.,For military purposes only. Accuracy 25m in each axis.,2339,38.82,41.31,8.08,9.89,1,0,9603,-97,-103,-120,,,,,0
-323,1143,4230,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,2340,36.59,38.35,12.36,15.71,1,0,9603,-97,-88,-135,,,,,0
-324,1144,4230,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,3275,35.74,36.05,14.27,14.63,1,0,9603,-107,-88,-149,,,,,0
-325,1145,4230,4326,Derived at 18 stations.,"For military purposes only. Accuracy 5m, 6m and 3m in X, Y and Z axes.",2338,35.26,43.82,-9.56,3.39,1,0,9603,-84,-107,-120,,,,,0
-326,1245,4230,4326,Derived at 4 stations.,For military purposes only. Accuracy 25m in each axis.,1236,30.23,38.41,7.49,13.67,1,0,9603,-112,-77,-145,,,,,0
-327,1275,4230,4326,"These same parameter values are used to transform to ETRS89. See ED50 to ETRS89 (10) (code 1650).",For applications to an accuracy of 2 metres.,1096,41.15,51.56,-9.86,10.38,1,0,9603,-84,-97,-117,,,,,0
-328,1311,4230,4326,"Based on ED50 to WGS72 (precise ephemeris) 6-nations agreement of 1981 to which precise to broadcast and broadcast to WGS 84 transformations have been concatenated.",Recommended transformation for UKCS and IrishCS petroleum purposes.,2342,47.42,63.89,-16.1,10.86,1,0,9606,-89.5,-93.8,-123.1,0,0,-0.156,1.2,0
-329,1440,4230,4326,,Used in oil industry.,3254,34.88,41.75,19.57,28.3,1,0,9603,-86,-92.2,-127.5,,,,,0
-330,1612,4230,4326,"Parameter values are taken from ED50 to ETRS89 (1), code 1588. Adopted for ED50 to WGS84 transformations offshore Norway north of 62N from April 2001 when it replaced code 1590. Included in Statens Kartverk programme wsktrans from v4.0.",Oil industry offshore.,2601,62,84.17,-3.7,39.65,1,0,9606,-116.641,-56.931,-110.559,0.893,0.921,-0.917,-3.52,0
-331,1613,4230,4326,"Approximation to 1 metre of concatenated transformation ED50 to WGS 84 (14), code 8653. 8653 remains the transformation promulgated by Statens Kartverk but 1613 recommended by EPSG for practical oil industry usage.",Approximation to 1 metre for oil industry use.,2334,56.08,62,1.37,11.14,1,0,9606,-90.365,-101.13,-123.384,0.333,0.077,0.894,1.994,0
-332,1627,4230,4326,"Parameter values from ED50 to ETRS89 (4) (code 1626). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,3237,54.51,57.8,8,15.24,1,0,9606,-81.1,-89.4,-115.8,0.485,0.024,0.413,-0.54,0
-333,1629,4230,4326,"Parameter values from ED50 to ETRS89 (5) (code 1628). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1105,36,36.16,-5.42,-4.89,1,0,9603,-116.8,-106.4,-154.4,,,,,0
-334,1631,4230,4326,"Parameter values from ED50 to ETRS89 (6) (code 1630). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1.5 metres.,2335,38.59,40.11,1.14,4.39,1,0,9606,-181.5,-90.3,-187.2,0.144,0.492,-0.394,17.57,0
-335,1633,4230,4326,"Parameter values from ED50 to ETRS89 (7) (code 1632). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1.5 metres.,2336,35.26,43.56,-7.54,3.39,1,0,9606,-131,-100.3,-163.4,-1.244,-0.02,-1.144,9.39,0
-336,1635,4230,4326,"Parameter values from ED50 to ETRS89 (8) (code 1634). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1.5 metres.,2337,41.5,43.82,-9.37,-4.5,1,0,9606,-178.4,-83.2,-221.3,0.54,-0.532,-0.126,21.2,0
-337,1784,4230,4326,"Parameter values from ED50 to ETRS89 (9) (code 1783). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 2 metres.,1237,34.42,43.45,25.62,44.83,1,0,9606,-84.1,-101.8,-129.7,0,0,0.468,1.05,0
-338,1810,4230,4326,Derived via concatenation through WGS72. The ED50 to WGS72 step is the Sepplin 1974 value for all Europe.,Oil industry exploration and production operations.,2595,25.71,31.68,24.7,30,1,0,9606,-84,-103,-122.5,0,0,0.554,0.2263,0
-339,1853,4230,4326,Derived at a single point in Galway docks.,Used by Enterprise for Corrib.,2961,53.75,55.76,-12.5,-9.49,1,0,9603,-82.31,-95.23,-114.96,,,,,0
-340,1961,4230,4326,"Parameter values taken from ED87 to WGS 84 (2) (tfm code 1960) assuming that ED87 is identical to ED50. Errors caused by this assumption can reach 3m.",Used by NAM for offshore operations.,1630,51.45,55.77,2.53,6.41,1,1,9606,-83.11,-97.38,-117.22,0.005693,-0.04469,0.4428,1.218,0
-341,1985,4230,4326,May be taken as a transformation from ED50 to ETRS89 - see tfm code 5040.,For low resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9603,-87.987,-108.639,-121.593,,,,,0
-342,1989,4230,4326,,For medium resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9607,-74.292,-135.889,-104.967,0.524,0.136,-0.61,-3.761,0
-343,1998,4230,4326,"Approximation to better than 0.5m of transformation adopted in June 2003 (see ED50 to WGS 84 (35), code 1052). Acceptable to Landesbergamt for Lower Saxony and Bundesanstalt für Seeschifffahrt und Hydrographie.",Recommended transformation for Germany North Sea petroleum purposes.,2879,53.6,55.92,3.34,8.88,1,0,9606,-157.89,-17.16,-78.41,2.118,2.697,-1.434,-5.38,0
-344,1999,4230,4326,"Parameter values taken from ED87 to WGS 84 (2) (tfm code 1960) assuming that ED87 is identical to ED50. Errors caused by this assumption can reach 3m.",Used by NAM for offshore operations.,1630,51.45,55.77,2.53,6.41,1,1,9606,-83.11,-97.38,-117.22,0.005693,-0.04469,0.04428,1.218,0
-345,3904,4230,4326,"Parameter values from ED87 to WGS 84 (32) (tfm code 3905), assuming that ED87 is identical to ED50. Errors caused by this assumption can reach 3-5m. Used by NAM for offshore operations until mid 2004, then replaced by tfm code 1311.","E&P operations in the Dutch sector of the North Sea.",1630,51.45,55.77,2.53,6.41,1,0,9606,-83.11,-97.38,-117.22,0.00569290865241986,-0.0446975835137458,0.0442850539012516,0.1218,0
-346,15964,4230,4326,Developed by the Portuguese Hydrographic Institute and used by the Directorate of Energy and Geology.,Hydrography and minerals management offshore Portugal.,3537,34.91,41.88,-13.87,-7.24,1,0,9603,-86.277,-108.879,-120.181,,,,,0
-347,1146,4231,4326,,"?",2330,51.03,62.01,-5.05,11.14,1,0,9606,-82.981,-99.719,-110.709,-0.104700015651026,0.0310016003789386,0.0804020214751182,-0.3143,0
-348,1960,4231,4326,,Scientific research.,1297,34.88,71.21,-10.56,31.59,1,1,9606,-83.11,-97.38,-117.22,0.005693,-0.04469,0.04428,1.218,0
-349,3905,4231,4326,"Parameter values taken from ED87 to ETRS89 (1) (tfm code 4078) assuming that ETRS89 is coincident with WGS 84 within the accuracy of the transformation. Used as a tfm between ED50 and WGS 84 - see code 3904.",Scientific research.,1297,34.88,71.21,-10.56,31.59,1,0,9606,-83.11,-97.38,-117.22,0.00569290865241986,-0.0446975835137458,0.0442850539012516,0.1218,1
-350,1256,4232,4326,Derived at 7 stations.,"For military purposes. Accuracy 3m, 3m and 9m in X, Y and Z axes.",4009,16.59,26.42,51.99,59.91,1,0,9603,-346,-1,224,,,,,1
-351,1438,4232,4326,,Oil exploration.,4009,16.59,26.42,51.99,59.91,1,0,9606,-333.102,-11.02,230.69,0,0,0.554,0.219,0
-352,1894,4233,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1152,-3.47,8.1,69.29,77.08,1,1,9603,-133,-321,50,,,,,0
-353,15817,4727,4326,"Derived at 1 satellite station. Information source states ""provided for historical purposes only. These parameter [values] should not be used"". Replaced by Midway 1961 to WGS 84 (2) (tfm code 15818).","Military and topographic mapping. Accuracy +/- 25m in each axis.",3202,28.13,28.28,-177.45,-177.31,1,0,9603,912,-58,1227,,,,,0
-354,15818,4727,4326,"Derived at 1 satellite station. Replaces Midway 1961 to WGS 84 (1) (tfm code 15817).","Military and topographic mapping. Accuracy +/- 25m in each axis.",3202,28.13,28.28,-177.45,-177.31,1,0,9603,403,-81,277,,,,,1
-355,1152,4236,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,3315,21.87,25.34,119.25,122.06,1,0,9603,-637,-549,-203,,,,,1
-356,1242,4237,4326,"Parameter value error in info source Hungarian text but correct in English summary. Replaces HD72 to WGS 84 (2) (code 1831).",Accuracy at metre level throughout Hungary.,1119,45.74,48.58,16.11,22.9,1,0,9603,52.17,-71.82,-14.9,,,,,1
-357,1448,4237,4326,"Parameter values taken from HD72 to ETRS89 (2) (code 1449) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaces HD72 to WGS 84 (1) (code 1830).","Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84.",1119,45.74,48.58,16.11,22.9,1,0,9607,52.684,-71.194,-13.975,0.312,0.1063,0.3729,1.0191,0
-358,1677,4237,4326,"Parameter values taken from HD72 to ETRS89 (1) (code 1273) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation.","Approximation at the +/- 1m level.",1119,45.74,48.58,16.11,22.9,1,1,9607,56,75.77,15.31,-0.37,-0.2,-0.21,-1.01,0
-359,1830,4237,4326,"Parameter values taken from HD72 to ETRS89 (1) (code 1829) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. OGP recommends use of newer MSZ 7222 equivalent (tfm code 1448) in preference to this transformation.","Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84.",1119,45.74,48.58,16.11,22.9,1,0,9607,56,-75.77,-15.31,0.37,0.2,0.21,1.01,0
-360,1831,4237,4326,"Derived at fundamental point Szolohegy and tested at 99 stations throughout Hungary. OGP recommends use of newer transformation (tfm code 1242) in preference to this transformation.",Accuracy better than 1m in all three dimensions throughout Hungary.,1119,45.74,48.58,16.11,22.9,1,0,9603,57.01,-69.97,-9.29,,,,,0
-361,1248,4238,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,4020,-10.98,5.97,95.16,141.01,1,0,9603,-24,-15,5,,,,,1
-362,1832,4238,4326,"Derived via coordinates of 2 Pulse8 stations. Use of ID74 to WGS 84 (3) (code 1833) is recommended.",For oil industry purposes.,4020,-10.98,5.97,95.16,141.01,1,0,9606,2.691,-14.757,4.724,0,0,0.774,-0.6,0
-363,1833,4238,4326,"Parameter values from ID74 to DGN95 (1) (code 15911) assuming that DGN95 is equivalent to WGS 84 within the accuracy of the transformation.","Standard deviations of translations are 1.3, 1.1 and 3.6m, of rotations 0.11, 0.06 and 0.04 sec and ppm 0.18.",4020,-10.98,5.97,95.16,141.01,1,0,9607,-1.977,-13.06,-9.993,-0.364,-0.254,-0.689,-1.037,0
-364,1153,4239,4326,Derived at 11 stations.,"For military purposes. Accuracy 15m, 6m and 12m in X, Y and Z axes.",3317,5.63,20.46,97.34,105.64,1,0,9603,217,823,299,,,,,1
-365,1154,4240,4326,"Derived at 62 stations. Replaced by Indian 1975 to WGS 84 (2) (code 1304).","For military purposes. Accuracy 3m, 2m and 3m in X, Y and Z axes.",3741,5.63,20.46,97.34,105.64,1,0,9603,209,818,290,,,,,0
-366,1304,4240,4326,"Derived at 62 stations. Replaces Indian 1975 to WGS 84 (1) (code 1154).","For military purposes. Accuracy 3m, 2m and 3m in X, Y and Z axes.",3741,5.63,20.46,97.34,105.64,1,0,9603,210,814,289,,,,,1
-367,1537,4240,4326,Derived in 1995 at point RTSD181.,Oil exploration.,2358,6.74,8.16,102.16,103.05,1,0,9603,204.64,834.74,293.8,,,,,0
-368,1812,4240,4326,,Cadastral survey.,3317,5.63,20.46,97.34,105.64,1,0,9606,293,836,318,0.5,1.6,-2.8,2.1,0
-369,1084,4242,4326,Derived via NAD27 and WGS 72. Preliminary values derived by Survey Department but not officially promulgated.,For applications requiring 5m accuracy.,3342,17.64,18.58,-78.43,-76.17,1,0,9603,70,207,389.5,,,,,1
-370,1085,4242,4326,"Derived at 4 stations, tested at a further 9.",For applications requiring 2m accuracy.,3342,17.64,18.58,-78.43,-76.17,1,0,9603,65.334,212.46,387.63,,,,,0
-371,1086,4242,4326,"Derived at 4 stations, tested at a further 9.",For applications requiring 1m accuracy.,3342,17.64,18.58,-78.43,-76.17,1,1,9607,-33.722,153.789,94.959,8.581,4.478,-4.54,-8.95,0
-372,15927,4242,4326,"Derived at 4 stations, tested at a further 9. Also used as tfm to JAD69 to JAD2001 (see code 15926).
+26,1877,4618,4326,"Derived by Brazilian Institute of Geography and Statistics (IBGE) in 1989 at Chua origin point. In use by Shell throughout Brazil. For use by Petrobras and ANP, replaced by tfm code 5882 from 1994.",Medium and small scale mapping. Valid for transforming GPS observations conducted in the period 1987 to 1993 inclusive.,1053,-35.71,7.04,-74.01,-25.28,1,0,9603,-66.87,4.37,-38.52,,,,,1
+27,5882,4618,4326,"Parameter values from SAD69 to SIRGAS 2000 (1) (tfm code 15485) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Used by ANP and Petrobras throughout Brazil from 1994, relacing use of tfm code 1877.","Accuracy generally better than 1m except in Amazon basin where it degenerates to 5m. Should be used only to transform data obtained independently of the classical geodetic network (GPS observations conducted after 1994).",1053,-35. [...]
+28,6967,4618,4326,"Also used as a transformation from SAD69 to WGS 84 - see code 6974. Note: SAD69 adopted in Chile only south of 43°30'S.",Small and medium scale cartographic mapping.,4232,-32,-17.5,-71.77,-67,1,1,9603,-59,-11,-52,,,,,0
+29,6969,4618,4326,"Also used as a transformation from SAD69 to WGS 84 - see code 6976. Note: SAD69 adopted in Chile only south of 43°30'S.",Small and medium scale cartographic mapping.,4221,-43.5,-35.99,-74.48,-70.39,1,1,9603,-72,10,-32,,,,,0
+30,6974,4618,4326,"Derived at 8 stations. Along with transformations 6975 and 6976, replaces SAD69 to WGS 84 (5) (code 1868). Also used as a transformation from SAD69 to SIRGAS-Chile - see code 7448. Note: SAD69 adopted by Chile authorities only south of 43°30'S.",For military purposes only. Accuracy 2m in each axis.,4232,-32,-17.5,-71.77,-67,1,0,9603,-59,-11,-52,,,,,0
+31,6975,4618,4326,"Derived at 6 stations. Along with transformations 6974 and 6976, replaces SAD69 to WGS 84 (5) (code 1868). Also used as a transformation from SAD69 to SIRGAS-Chile - see code 6968. Note: SAD69 adopted by Chile authorities only south of 43°30'S.",For military purposes only. Accuracy 2m in each axis.,4224,-36,-31.99,-72.87,-69.77,1,0,9603,-64,0,-32,,,,,0
+32,6976,4618,4326,"Derived at 4 stations. Along with transformations 6974 and 6975, replaces SAD69 to WGS 84 (5) (code 1868). Also used as a transformation from SAD69 to SIRGAS-Chile - see code 7449. Note: SAD69 adopted by Chile authorities only south of 43°30'S.",For military purposes only. Accuracy 4m in each axis.,4221,-43.5,-35.99,-74.48,-70.39,1,0,9603,-72,10,-32,,,,,0
+33,6977,4618,4326,"Derived at 6 stations. Also used as a transformation from SAD69 to SIRGAS-Chile - see code 6970.  Unlike IGM Chile, NGA extends use of this tfm to all Chile south of 44°S.","For military purposes only. Accuracy 3m, 3m and 4m in X, Y and Z axes.",2805,-55.96,-51.99,-74.83,-66.33,1,0,9603,-79,13,-14,,,,,0
+34,1879,4619,4326,"Parameter values taken from SWEREF to ETRS89 (1) (code 1878) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation.",Geographic Information Systems.,1225,54.96,69.07,10.03,24.17,1,0,9603,0,0,0,,,,,1
+35,1880,4620,4326,Derived at one point in each of Burkina Faso and Niger.,For military purposes. Accuracy 25m in each axis.,2791,11.83,14.23,-4.64,4,1,0,9603,-106,-129,165,,,,,1
+36,1903,4621,4326,,"Accuracy +/- 10 metres.",2828,17.82,18.17,-63.21,-62.73,1,0,9603,137,248,-430,,,,,1
+37,1904,4622,4326,,"Accuracy +/- 10 metres.",2829,15.8,16.55,-61.85,-60.97,1,0,9603,-467,-16,-300,,,,,1
+38,1905,4622,4326,,"Accuracy +/- 0.1 metre.",2829,15.8,16.55,-61.85,-60.97,1,0,9606,-472.29,-5.63,-304.12,0.4362,-0.8374,0.2563,1.8984,0
+39,1906,4623,4326,,"Accuracy +/- 10 metres.",3105,3.43,5.81,-54.45,-51.61,1,0,9603,-186,230,110,,,,,1
+40,1907,4624,4326,,"Accuracy +/- 2 metres.",1097,2.11,8.88,-54.6,-49.46,1,1,9603,2,2,-2,,,,,0
+41,4840,4624,4326,"Replaces RGFG95 to WGS 84 (1) (code 1907) which was not put into official use but issued in error.","Accuracy +/- 2 metres.",1097,2.11,8.88,-54.6,-49.46,1,0,9603,0,0,0,,,,,1
+42,1909,4625,4326,,"Accuracy +/- 10 metres.",3276,14.35,14.93,-61.29,-60.76,1,0,9603,186,482,151,,,,,1
+43,1910,4625,4326,,"Accuracy +/- 0.1 metre.",3276,14.35,14.93,-61.29,-60.76,1,0,9606,126.93,547.94,130.41,-2.7867,5.1612,-0.8584,13.8227,0
+44,1911,4626,4326,Derived at 1 station.,"Accuracy +/- 30 metres.",1196,-25.92,-10.6,37.58,58.27,1,1,9603,94,-948,-1292,,,,,0
+45,15751,4626,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,3337,-21.42,-20.81,55.16,55.91,1,0,9603,94,-948,-1262,,,,,1
+46,1912,4627,4326,,"Accuracy +/- 1 metre.",3902,-24.72,-18.28,51.83,58.24,1,0,9603,0,0,0,,,,,1
+47,1924,4628,4326,,"Accuracy +/- 10 metres.",2811,-17.93,-17.41,-150,-149.11,1,0,9603,162,117,154,,,,,1
+48,1913,4629,4326,,"Accuracy +/- 10 metres.",2812,-16.96,-16.17,-151.91,-150.89,1,0,9603,65,342,77,,,,,0
+49,15770,4629,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from Tahaa 54 to RGPF (1) (tfm code 15758).","Accuracy +/- 1 metre.",2812,-16.96,-16.17,-151.91,-150.89,1,0,9607,72.438,345.918,79.486,-1.6045,-0.8823,-0.5565,1.3746,1
+50,1914,4630,4326,,"Accuracy +/- 10 metres.",3129,-9.57,-8.72,-140.31,-139.44,1,0,9603,84,274,65,,,,,1
+51,15775,4630,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from IGN72 Nuku Hiva to RGPF (1) (tfm code 15763).","Accuracy +/- 1 metre.",2810,-9.01,-8.72,-140.31,-139.96,1,0,9607,165.732,216.72,180.505,-0.6434,-0.4512,-0.0791,7.4204,0
+52,15776,4630,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from IGN72 Nuku Hiva to RGPF (2) (tfm code 15764).","Accuracy +/- 2 metres.",3127,-9,-8.81,-139.66,-139.44,1,0,9607,1363.785,1362.687,398.811,-4.5322,-6.7579,-1.0574,268.361,0
+53,15777,4630,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from IGN72 Nuku Hiva to RGPF (2) (tfm code 15765).","Accuracy +/- 1 metre.",3128,-9.57,-9.27,-140.21,-139.95,1,0,9607,259.551,297.612,197.833,1.4866,2.1224,0.4612,27.0249,0
+54,1915,4631,4326,"Also published in US NIMA/NGA TR8350.2 which gives accuracy of +/-25m in each axis and states that derived at one station.","Accuracy +/- 10 metres.",2816,-49.78,-48.6,68.69,70.62,1,1,9603,145,-187,103,,,,,0
+55,1916,4632,4326,,"Accuracy +/- 10 metres.",3340,-13.05,-12.61,44.98,45.35,1,0,9603,-382,-59,-262,,,,,1
+56,1272,4121,4326,,For applications requiring 1m or better accuracy.,3254,34.88,41.75,19.57,28.3,1,0,9603,-199.87,74.79,246.62,,,,,1
+57,1918,4634,4326,,"Accuracy +/- 10 metres.",1174,-26.45,-14.83,156.25,174.28,1,1,9603,-13,-348,292,,,,,0
+58,1929,4634,4326,,"Accuracy better than +/- 1 metre.",2822,-22.45,-20.03,163.92,167.09,1,1,9606,97.295,-263.247,310.882,-1.5999,0.8386,3.1409,13.3259,0
+59,1639,4123,4326,"Parameter values from KKJ to ETRS89 (1) (code 1638). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaced by KKJ to WGS 84 (2) (code 10099).",For applications to an accuracy of 1 to 2 metres.,3333,59.75,70.09,19.24,31.59,1,0,9606,-90.7,-106.1,-119.2,4.09,0.218,-1.05,1.37,0
+60,10099,4123,4326,"Parameter values from KKJ to ETRS89 (2) (code 10098). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaces KKJ to WGS 84 (1) (code 1639).",For applications to an accuracy of 1 to 2 metres.,3333,59.75,70.09,19.24,31.59,1,0,9607,-96.062,-82.428,-121.753,-4.801,-0.345,1.376,1.496,1
+61,1680,4124,4326,"Parameter values from RT90 to ETRS89 (1) (code 1437) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaced by RT90 to WGS 84 (2) (code 1896) from 2001.","Approximation at the +/- 1m level.",1225,54.96,69.07,10.03,24.17,1,0,9607,419.3836,99.3335,591.3451,-0.850389,-1.817277,7.862238,-0.99496,0
+62,1788,4124,4326,"Parameter values from RT90 to ETRS89 (1) (code 1787) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Supersedes RT90 to WGS 84 (1) (code 1680).","Approximation at the +/- 1m level.",1225,54.96,69.07,10.03,24.17,1,1,9607,414.1,41.3,603.1,-0.855,2.141,-7.023,0,0
+63,1896,4124,4326,"Parameter values from RT90 to SWEREF99 (1) (code 1895) assuming that SWEREF99 is equivalent to WGS 84 within the accuracy of the transformation. Replaces RT90 to WGS 84 (1) (code 1680).","Approximation at the +/- 1m level.",1225,54.96,69.07,10.03,24.17,1,0,9607,414.1,41.3,603.1,0.855,-2.141,7.023,0,1
+64,1282,4125,4326,Datum shift derived through ITRF93.,Oil exploration.,1328,-1.24,0,116.72,117.99,1,1,9603,-404.78,685.68,45.47,,,,,0
+65,1923,4638,4326,,"Accuracy +/- 10 metres.",3299,46.69,47.19,-56.48,-56.07,1,0,9603,30,430,368,,,,,1
+66,1683,4127,4326,"Parameter values taken from Tete to Moznet (1) (code 1297) assuming that Moznet is equivalent to WGS 84 within the accuracy of the transformation.",Residuals as high as 30 metres.,3281,-26.87,-10.42,30.21,40.9,1,0,9607,-115.064,-87.39,-101.716,0.058,-4.001,2.062,9.366,0
+67,1684,4127,4326,"Parameter values taken from Tete to Moznet (2) (code 1298) assuming that Moznet is equivalent to WGS 84 within the accuracy of the transformation.",Residuals are generally under 1 metre.,2350,-26.87,-23.91,31.91,34.5,1,0,9607,-82.875,-57.097,-156.768,2.158,-1.524,0.982,-0.359,0
+68,1685,4127,4326,"Parameter values taken from Tete to Moznet (3) (code 1299) assuming that Moznet is equivalent to WGS 84 within the accuracy of the transformation.",Residuals are generally under 4 metres.,2351,-24.91,-19.74,31.29,35.65,1,0,9607,-138.527,-91.999,-114.591,0.14,-3.363,2.217,11.748,0
+69,1686,4127,4326,"Parameter values taken from Tete to Moznet (4) (code 1300) assuming that Moznet is equivalent to WGS 84 within the accuracy of the transformation.",Residuals are generally under 3 metres.,2352,-19.91,-14.01,30.21,39.18,1,0,9607,-73.472,-51.66,-112.482,-0.953,-4.6,2.368,0.586,0
+70,1687,4127,4326,"Parameter values taken from Tete to Moznet (5) (code 1301) assuming that Moznet is equivalent to WGS 84 within the accuracy of the transformation.",Residuals are 5-10 metres.,2353,-16.94,-10.42,34.36,40.9,1,0,9607,219.315,168.975,-166.145,-0.198,-5.926,2.356,-57.104,0
+71,6901,4127,4326,Derived at 4 stations.,For military purposes. Accuracy 10m in each axis.,3281,-26.87,-10.42,30.21,40.9,1,0,9603,-80,-100,-228,,,,,1
+72,1934,4640,4326,RRAF 1991 was defined to be WGS84 at a single point in Martinique during the 1988 Tango mission.,"Accuracy +/- 1 metre.",2824,14.08,18.54,-63.66,-57.52,1,1,9603,0,0,0,,,,,0
+73,1928,4641,4326,Withdrawn by information source and replaced by improved information - see tfm code 15901.,"Accuracy better than +/- 1 metre.",2819,-21.71,-21.32,167.75,168.19,1,0,9606,-408.809,366.856,-412.987,1.8842,-0.5308,2.1655,-121.0993,0
+74,15901,4641,4326,"Parameter values taken from IGN53 Mare to RGNC91-93 (1) ( code 15884) assuming that RGNC91-93 is equivalent to WGS 84 to within the accuracy of the transformation.",Accuracy 2 metres.,2819,-21.71,-21.32,167.75,168.19,1,0,9603,287.58,177.78,-135.41,,,,,1
+75,15783,4641,4326,Withdrawn by information source and replaced by improved information from local authority - see tfm code 15901.,Accuracy 5 metres.,2819,-21.71,-21.32,167.75,168.19,1,0,9603,287,178,-136,,,,,0
+76,1302,4130,4326,,For many purposes Moznet can be considered to be coincident with WGS 84. Accuracy better than 1 metre.,1167,-27.71,-10.09,30.21,43.03,1,0,9607,0,0,0,0,0,0,0,1
+77,1542,4131,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,2359,14,18,105.61,109.32,1,0,9603,198,881,317,,,,,1
+78,1543,4131,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2360,8.58,8.83,106.49,106.79,1,0,9603,182,915,344,,,,,0
+79,1513,4132,4326,Derived in 1998 in Kangan district by Geoid for Total. Used for South Pars phases 2 and 3.,Oil exploration.,2362,27.3,28.2,51.8,53.01,1,0,9603,-241.54,-163.64,396.06,,,,,1
+80,1854,4132,4326,Derived by Geoid for Elf in 1999. EGM96 geoid used.,Oil Exploration,2782,26.21,26.87,52.49,53.43,1,0,9603,-239.1,-170.02,397.5,,,,,0
+81,1855,4132,4326,Derived by Geoid for Elf in 1999. EGM96 geoid used.,Oil Exploration,2781,29.16,29.39,50.22,50.42,1,0,9603,-244.72,-162.773,400.75,,,,,0
+82,1333,4133,4326,,"?",3246,57.52,59.75,21.74,28.2,1,0,9607,0.055,-0.541,-0.185,-0.0183,0.0003,0.007,-0.014,1
+83,1439,4134,4326,"Replaced PSD93 to WGS 84 (2) (code 8581) in 1997.","Oil exploration. Residuals 0.5m at 67% probability level.",3288,16.59,26.58,51.99,59.91,1,0,9606,-180.624,-225.516,173.919,-0.81,-1.898,8.336,16.71006,1
+84,1617,4134,4326,Accuracy better than 0.5m in block 4.,Oil exploration.,2404,19.58,21.17,56.5,59.02,1,0,9606,-191.808,-250.512,167.861,-0.792,-1.653,8.558,20.703,0
+85,15824,4135,4326,Derived at 15 satellite stations.,"Military mapping. Accuracy +/- 25m in X axis, +/- 20m in Y and Z axes.",1334,18.87,22.29,-160.3,-154.74,1,0,9603,61,-285,-181,,,,,1
+86,15825,4135,4326,Derived at 2 satellite stations.,"Military mapping. Accuracy +/- 25m in each axis.",1546,18.87,20.33,-156.1,-154.74,1,0,9603,89,-279,-183,,,,,0
+87,15826,4135,4326,Derived at 3 satellite stations.,"Military mapping. Accuracy +/- 20m in each axis.",1549,21.81,22.29,-159.85,-159.23,1,0,9603,45,-290,-172,,,,,0
+88,15827,4135,4326,Derived at 2 satellite stations.,"Military mapping. Accuracy +/- 25m in each axis.",1547,20.45,21.26,-157.36,-155.93,1,0,9603,65,-290,-190,,,,,0
+89,15828,4135,4326,Derived at 8 satellite stations.,"Military mapping only. Accuracy +/- 10m in X axis, +/- 6m in Y and Z axes.",1548,21.2,21.75,-158.33,-157.61,1,0,9603,58,-283,-182,,,,,0
+90,6208,6207,4326,Derived at 11 points.,"Topographic mapping. Accuracy 0.26m (1-sigma).",1171,26.36,30.43,80.05,88.2,1,0,9603,293.17,726.18,245.36,,,,,1
+91,1893,4139,4326,Derived at 11 stations.,For military purposes only. Accuracy 3m in each axis.,1335,17.62,18.78,-67.97,-64.25,1,0,9603,11,72,-101,,,,,1
+92,1473,4140,4326,"For many purposes NAD83(CSRS98) can be considered to be coincident with WGS 84.","Approximation at the +/- 1m level assuming that NAD83(CSRS98) is equivalent to WGS 84.",1336,44.61,62.56,-120,-57.1,1,1,9603,0,0,0,,,,,0
+93,1073,4141,4326,For more accurate transformation contact Survey of Israel.,"Accuracy: 2m",2603,29.45,33.28,34.17,35.69,1,0,9603,-48,55,52,,,,,1
+94,1469,4142,4326,,"?",2282,5.15,5.54,-4.22,-3.85,1,0,9603,-125,53,467,,,,,1
+95,1470,4143,4326,"Derived in Abidjan for use in the immediate area, but used by E&P industry more widely onshore and offshore. A similar transformation (tfm code 6872) was used by Western Geophysical for offshore surveys in the 1990s.",Accuracy is submetre in the area around Abidjan but unknown farther afield. There is some evidence of unknown reliability that suggests accuracy of better than 2m throughout offshore.,1075,1.02,10.74,-8.61,-2.48,1,0,9603,-124.76,53,466.79,,,,,1
+96,6872,4143,4326,"Derived and used by Western Geophysical for offshore surveys in the 1990s, but exact provenance uncertain. Used by OMV.",Accuracy uncertain but there is some evidence of unknown reliability that suggests accuracy of better than 2m throughout offshore.,2296,1.02,5.19,-7.55,-3.11,1,0,9603,-123.1,53.2,465.4,,,,,0
+97,1155,4144,4326,Derived at 6 stations.,"For military purposes. Accuracy 10m, 8m and 12m in X, Y and Z axes.",3217,20.52,26.63,88.04,92.67,1,0,9603,282,726,254,,,,,0
+98,1533,4144,4326,,Oil exploration.,2361,9.48,17.87,93.94,99.66,1,0,9603,214,804,268,,,,,1
+99,1247,4145,4326,"Care! DMA ellipsoid is inconsistent with EPSG ellipsoid - transformation parameter values may not be appropriate. No accuracy estimate available.",For military purposes.,3289,23.64,37.07,60.86,77.83,1,0,9603,283,682,231,,,,,1
+100,15701,4145,4326,Derived at Geodetic Survey office in Karachi in 1997.,Oil exploration.,2985,21.05,25.39,64,68.24,1,0,9603,275.57,676.78,229.6,,,,,0
+101,15702,4145,4326,"Derived at station S0001, an approximate offset to Survey of India primary station Kat Baman, in 1992 from 180 single point Transit passes observed in 1991 by Fugro-Geodetic for UTP.",Oil exploration.,2984,24,25.64,67.74,69.87,1,0,9603,278.9,684.39,226.05,,,,,0
+102,15703,4145,4326,Derived at Chitrawala triangulation station by Fugro-Geodetic for UTP.,Oil exploration.,2982,24.69,25.76,66.83,68,1,0,9603,271.905,669.593,231.495,,,,,0
+103,15704,4145,4326,Derived by Western Geophysical for UTP 1996 East Sind 2D survey.,Oil exploration.,2983,24.16,28.61,68.27,71.11,1,0,9606,230.25,632.76,161.03,-1.114,1.115,1.212,12.584,0
+104,15494,4145,4326,Derived by Fugro-Geodetic in 2004 at 6 closely-spaced stations. Used by OMV in all blocks in Pakistan where operator.,Oil exploration.,3589,25.88,27.67,68.24,69.3,1,0,9603,274.164,677.282,226.704,,,,,0
+105,1156,4146,4326,"Care! DMA ellipsoid is inconsistent with EPSG ellipsoid - transformation parameter values may not be appropriate. Also source CRS may not apply to Nepal. Derived at 7 stations.","For military purposes. Accuracy 12m, 10m and 15m in X, Y and Z axes.",2411,8.02,35.51,68.08,97.39,1,0,9603,295,736,257,,,,,1
+106,1544,4147,4326,Derived in Vung Tau area.,Oil exploration.,1494,9.02,11.03,105.49,107.59,1,0,9603,-17.51,-108.32,-62.39,,,,,1
+107,1505,4148,4326,,For many purposes Hartebeesthoek94 datum can be considered to be coincident with WGS 84.,1215,-50.32,-22.13,13.33,42.85,1,0,9603,0,0,0,,,,,1
+108,1508,4149,4326,"Implemented in Bundesamt für Landestopographie programme GRANIT.","?",1286,45.82,47.81,5.96,10.49,1,1,9607,660.077,13.551,369.344,0.80482,0.57769,0.95224,5.66,0
+109,1510,4149,4326,"These parameters are strictly between CH1903+ and CHTRF95 but are used from CH1903 as an approximation which is within the accuracy of the distortions in the CH1903 network.",Accuracy 1.5 metres.,1286,45.82,47.81,5.96,10.49,1,1,9603,674.374,15.056,405.346,,,,,0
+110,1753,4149,4326,"Implemented in Bundesamt für Landestopografie programme GRANIT. Used from 1987 to 1997. Not recommended for current usage - replaced by CH1903 to WGS 84 (2) (code 1766).",Used in programme GRANIT between 1987 and 1997.,1286,45.82,47.81,5.96,10.49,1,0,9607,660.077,13.551,369.344,0.80482,0.57769,0.95224,5.66,0
+111,1766,4149,4326,"These parameters are derive from CH1903+ to ETRS89 (code 1647) and are used at lesser precision from CH1903 to WGS 84 as an approximation which is within the accuracy of the distortions in the CH1903 network. Replaces CH1903 to WGS 84 (1) (code 1753).",Accuracy 1.5 metres.,1286,45.82,47.81,5.96,10.49,1,0,9603,674.4,15.1,405.3,,,,,1
+112,1676,4150,4326,"Parameter values are from CH1903+ to CHTRF95 (1) (code 1509) assuming that CHTRF95 is equivalent to WGS 84. That transformation is also given as CH1903+ to ETRS89 (1) (code 1647). CHTRF95 is a realisation of ETRS89.","Approximation at the +/- 1m level.",1286,45.82,47.81,5.96,10.49,1,0,9603,674.374,15.056,405.346,,,,,1
+113,1511,4151,4326,,For many purposes CHTRF95 can be considered to be coincident with WGS 84.,1286,45.82,47.81,5.96,10.49,1,0,9603,0,0,0,,,,,1
+114,1580,4152,4326,"For many purposes NAD83(HARN) can be considered to be coincident with WGS 84.","Approximation at the +/- 1m level assuming that NAD83(HARN) is equivalent to WGS 84.",1337,-14.59,49.38,144.58,-64.51,1,0,9603,0,0,0,,,,,1
+115,1900,4152,4326,"Approximation derived ignoring time-dependent parameters and assuming ITRF94(1996.0) and WGS 84, plus NAD83(CORS94) and NAD83(HARN), can be considered the same within the accuracy of the transformation. Replaced by NAD83(HARN) to WGS 84 (3) (code 1901).",Historical record only - superseded - see remarks.,1323,24.41,49.38,-124.79,-66.91,1,0,9607,-0.9738,1.9453,0.5486,-0.0275508,-0.010049,-0.011359,0,0
+116,1901,4152,4326,"Approximation derived from tfm code 6864 ignoring time-dependent parameters and assuming ITRF96(1997.0) and WGS 84, plus NAD83(CORS96) and NAD83(HARN), can be considered the same within the accuracy of the tfm. In USA only replaces tfm code 1900.","Geodesy. Accuracy with respect to CORS at stations adjusted to HARN network is better than 0.05-0.07m. For locations outside a HARN network (i.e. NAD83), accuracy may be only 1m but will usually be better than 0.5m.",1323,2 [...]
+117,15930,4152,4326,"Accuracy 0.1 to 0.2m in California, 0.05-0.11 in Oregon, elsewhere better than 0.05m.",For applications to an accuracy of 0.2 metre.,1323,24.41,49.38,-124.79,-66.91,1,1,9603,0,0,0,,,,,0
+118,1512,4153,4326,"Derived in 1998 at Assaluyeh (Taheri refinery) by Geoid for Total. Used for South Pars phases 2 and 3.",Oil industry engineering survey. Used only for terminal site.,1338,27.39,27.61,52.5,52.71,1,0,9603,-133.63,-157.5,-158.62,,,,,1
+119,1141,4154,4326,"Given by DMA as from ED50. OGP interpret that as ED50(ED77) in Iran. Derived at 27 stations.","For military purposes. Accuracy 9m, 12m and 11m in X, Y and Z axes.",1123,23.34,39.78,44.03,63.34,1,0,9603,-117,-132,-164,,,,,1
+120,1514,4154,4326,"Used for South Pars phases 6, 7 and 8.","Transformation for whole country: accuracy about 1m.",1123,23.34,39.78,44.03,63.34,1,0,9606,-110.33,-97.73,-119.85,0.3423,1.1634,0.2715,0.063,0
+121,1856,4154,4326,Derived in Kangan district by Geoid for Total in 1998. Used for South Pars phases 2 and 3.,Petroleum Exploration and Production.,2783,26.58,26.71,52.07,52.28,1,0,9603,-122.89,-159.08,-168.74,,,,,0
+122,1857,4154,4326,Derived in 1999 on Lavan island by Geoid for Elf.,Petroleum Exploration and Production.,2782,26.21,26.87,52.49,53.43,1,0,9603,-84.78,-107.55,-137.25,,,,,0
+123,1858,4154,4326,Derived by Geoid for Elf in 1999. EGM96 geoid used.,Petroleum Exploration and Production.,2781,29.16,29.39,50.22,50.42,1,0,9603,-123.92,-155.515,-157.721,,,,,0
+124,15745,4154,4326,Derived in Tombak district in March 2005. Used for South Pars phase 11.,Petroleum Exploration and Production.,3140,26.46,26.64,52.22,52.41,1,0,9603,-123.02,-158.95,-168.47,,,,,0
+125,1518,4155,4326,,Accuracy 25m in each axis.,3257,7.19,12.68,-15.13,-7.65,1,0,9603,-83,37,124,,,,,1
+126,1623,4156,4326,"Parameter values from S-JTSK to ETRS89 (1) (code 1622). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaced by S-JTSK to WGS 84 (5) (code 5239).",For applications to an accuracy of 1 metre.,1079,48.58,51.06,12.09,18.86,1,0,9606,570.8,85.7,462.8,4.998,1.587,5.261,3.56,0
+127,1625,4156,4326,"Parameter values from S-JTSK to ETRS89 (2) (code 1624). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1211,47.73,49.61,16.84,22.56,1,1,9606,559,68.7,451.5,7.92,4.073,4.251,5.71,0
+128,4828,4156,4326,"Parameter values from S-JTSK to ETRS89 (4) (code 4827). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1211,47.73,49.61,16.84,22.56,1,1,9606,485,169.5,483.5,7.786,4.398,4.103,0,0
+129,4836,4156,4326,"Parameter values from S-JTSK to ETRS89 (4) (code 4827). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1211,47.73,49.61,16.84,22.56,1,0,9606,485,169.5,483.8,7.786,4.398,4.103,0,0
+130,5239,4156,4326,"Parameter values from S-JTSK/05 to WGS 84 (1) (code 5227). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaces tfm code 1622.",For applications to an accuracy of 1 metre.,1079,48.58,51.06,12.09,18.86,1,0,9607,572.213,85.334,461.94,-4.9732,-1.529,-5.2484,3.5378,0
+131,15965,4156,4326,Derived at 6 stations.,"For military purposes. Accuracy 4m, 2m and 3m in X, Y and Z axes.",1306,47.73,51.06,12.09,22.56,1,0,9603,589,76,480,,,,,1
+132,1283,4669,4326,,LKS94 is a realisation of ETRS89 coincident to WGS 84 within 1 metre. This transformation has an accuracy equal to the coincidence figure.,1145,53.89,56.45,19.02,26.82,1,0,9603,0,0,0,,,,,1
+133,1099,4670,4326,"Parameter values taken from IGM95 to ETRS89 (1) (code 1098) assuming that ETRS89 is coincident with WGS 84 within the accuracy of the transformation.",Approximation at the 1m level.,3343,34.76,47.1,5.93,18.99,1,0,9603,0,0,0,,,,,1
+134,1859,4159,4326,"Used by Repsol in Murzuq field, and PetroCanada and previous licence holders in NC177 and 72 (En Naga field). Reliability of connection to ELD79 questionned.",Oil Exploration,2785,27.32,27.67,18.37,18.72,1,0,9603,-69.06,-90.71,-142.56,,,,,0
+135,1860,4159,4326,Derived December 2001 by NAGECO. Connected to ITRF via Remsa 2000 data. Used by TotalFinaElf.,Oil Exploration. 3-dimensional SD at 11 points is 0.5m.,2785,27.32,27.67,18.37,18.72,1,0,9603,-113.997,-97.076,-152.312,,,,,0
+136,1861,4159,4326,Derived by GEOID in 1994 from Transit satellite data. Used by TotalFinaElf.,Oil Exploration,2786,29.61,30.07,17.13,17.51,1,0,9603,-114.5,-96.1,-151.9,,,,,0
+137,1862,4159,4326,"Derived by Geoid in 2000 from ITRF connection by NAGECO for TotalFinaElf. For historic compatibility TFE use the 1994 tfm ELD79 to WGS 84 (3) (code 1861) rather than this transformation.",Oil Exploration,2786,29.61,30.07,17.13,17.51,1,0,9606,-194.513,-63.978,-25.759,-3.4027,3.756,-3.352,-0.9175,0
+138,1863,4159,4326,"Derived for the Great Man-made River Authority (GMRA).",Engineering survey and oil exploration,2786,29.61,30.07,17.13,17.51,1,0,9607,-389.691,64.502,210.209,-0.086,-14.314,6.39,0.9264,0
+139,15707,4159,4326,"Used by Petrocanada and previous licence holders in Amal field, concession 12.",Oil exploration and production,2987,29.1,29.8,20.8,21.4,1,0,9603,-118.996,-111.177,-198.687,,,,,0
+140,15778,4159,4326,"Derived by Total at stations SDL 130-03, 04 and 05 in May 2005.",Oil exploration and production.,3142,27.5,28.07,21.25,21.59,1,0,9603,-114.7,-98.5,-150.7,,,,,0
+141,15909,4159,4326,Derived at 29 stations throughout Libya in May 2006.,For applications to an accuracy of 5 metres.,3271,19.49,33.23,9.31,25.21,1,0,9603,-115.8543,-99.0583,-152.4616,,,,,1
+142,15923,4159,4326,"Derived by SDL for Total in Cyrenaica blocks 2 & 4.",Oil and gas exploration.,3477,32,32.8,22.49,23,1,0,9603,-117.7,-100.3,-152.4,,,,,0
+143,1080,4672,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,2889,-44.64,-43.3,-177.25,-175.54,1,0,9603,175,-38,113,,,,,1
+144,1081,4673,4326,Derived at 4 stations using concatenation through WGS72. Parameter vales are also used to transform CI1979 to NZGD2000 - see tfm code 1082.,For applications requiring 2m accuracy.,2889,-44.64,-43.3,-177.25,-175.54,1,0,9607,174.05,-25.49,112.57,0,0,-0.554,0.2263,1
+145,15894,4674,4326,,Accuracy 1m.,3418,-59.87,32.72,-122.19,-25.28,1,0,9603,0,0,0,,,,,1
+146,1070,4675,4326,Derived at 5 stations.,For military purposes only. Accuracy 3m in each axis.,3255,13.18,13.7,144.58,145.01,1,0,9603,-100,-248,259,,,,,1
+147,1682,4164,4326,"Parameter values taken from South Yemen to Yemen NGN96 (1) (code 1539) assuming that NGN96 is equivalent to WGS 84 within the accuracy of the transformation.","Approximation at the +/- 5m level.",1340,12.54,19,43.37,53.14,1,0,9603,-76,-138,67,,,,,1
+148,1547,4165,4326,Derived at 2 stations.,For military purposes only. Accuracy 25m in each axis.,3258,10.87,12.69,-16.77,-13.64,1,0,9603,-173,253,27,,,,,1
+149,1065,4678,4326,Derived at 25 stations.,Accuracy 5m.,1138,13.92,22.5,100.09,107.7,1,0,9603,44.585,-131.212,-39.544,,,,,1
+150,1565,4167,4326,,Assumes NZGD2000 is coincident to WGS 84 to the 1m accuracy level.,1175,-55.95,-25.88,160.6,-171.2,1,0,9603,0,0,0,,,,,1
+151,1569,4168,4326,Derived at 3 common points.,Military survey,1104,1.4,11.16,-3.79,2.1,1,0,9603,-199,32,322,,,,,1
+152,6896,4168,4326,Derived at 4 stations.,"For military purposes. Accuracy 3m, 4m and 3m in X, Y and Z axes.",3252,4.67,11.16,-3.25,1.23,1,0,9603,-170,33,326,,,,,0
+153,15495,4168,4326,Derived via WGS 72BE. Found in use within oil industry erroneously concatenated via WGS 72. See tfm code 8571.,Oil industry.,1505,1.4,6.06,-3.79,2.1,1,0,9606,-171.16,17.29,325.21,0,0,0.814,-0.38,0
+154,1577,4169,4326,Transformation based on observations at 2 stations in 1993.,For military purposes. One sigma uncertainty is 25m in each axis.,3109,-14.43,-14.11,-170.88,-169.38,1,0,9603,-115,118,426,,,,,1
+155,1581,4170,4326,,For military purposes. Accuracy 1m in each axis.,3448,-59.87,16.75,-113.21,-26,1,0,9603,0,0,0,,,,,1
+156,1671,4171,4326,"Parameter values from RGF93 to ETRS89 (1) (code 1591) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation.","Approximation at the +/- 1m level.",1096,41.15,51.56,-9.86,10.38,1,0,9603,0,0,0,,,,,1
+157,1598,4172,4326,,"?",1033,-58.41,-21.78,-73.59,-52.63,1,1,9603,0,0,0,,,,,0
+158,1678,4173,4326,Assumes that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. IRENET95 is a regional realisation of ETRS89.,"Approximation at the +/- 1m level.",1305,51.39,55.43,-10.56,-5.34,1,0,9603,0,0,0,,,,,1
+159,15738,4686,4326,,MAGNA-SIRGAS is a realisation of WGS 84 coincident to within 1 metre. This transformation has an accuracy equal to the coincidence figure.,1070,-4.23,15.51,-84.77,-66.87,1,0,9603,0,0,0,,,,,1
+160,1614,4175,4326,"Determined at 8 stations. Info. source has the source CRS as Sierra Leone 1960. Sierra Leone 1968 is a readjustment of the 1960 network: coordinates changed by less than 3 metres.","Accuracy +/- 15m in each axis.",3306,6.88,10,-13.35,-10.26,1,0,9603,-88,4,101,,,,,1
+161,1890,4176,4326,For many purposes Australian Antarctic can be considered to be coincident with WGS 84.,"Approximation at the +/- 1m level assuming that Australian Antarctic is equivalent to WGS 84.",1278,-90,-60,45,160,1,0,9603,0,0,0,,,,,1
+162,15773,4689,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from IGN63 Hiva Oa to RGPF (1) (tfm code 15761).","Accuracy +/- 1 metre.",3131,-9.89,-9.64,-139.23,-138.75,1,0,9607,410.721,55.049,80.746,-2.5779,-2.3514,-0.6664,17.3311,1
+163,15774,4689,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from IGN63 Hiva Oa to RGPF (2) (tfm code 15762).","Accuracy +/- 2 metres.",3132,-10.08,-9.86,-139.19,-138.98,1,0,9607,374.716,-58.407,-0.957,-16.2111,-11.4626,-5.5357,-0.5409,0
+164,1675,4178,4326,"Parameter values from Pulkovo 1942(83) to ETRS89 (1) (code 1674) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation.",Residuals under 2 m.,1343,50.2,54.74,9.92,15.04,1,0,9607,24,-123,-94,-0.02,0.25,0.13,1.1,0
+165,15996,4178,4326,Derived at 5 stations.,For military purposes. Accuracy 2m in each axis.,1119,45.74,48.58,16.11,22.9,1,0,9603,28,-121,-77,,,,,0
+166,15998,4178,4326,Derived at 6 stations.,"For military purposes only. Accuracy 3m, 3m and 2m in X, Y and Z axes.",1306,47.73,51.06,12.09,22.56,1,0,9603,26,-121,-78,,,,,1
+167,1645,4179,4326,"Parameter values from Pulkovo 1942(58) to ETRS89 (1) (code 1644). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,3293,49,54.89,14.14,24.15,1,0,9606,33.4,-146.6,-76.3,-0.359,-0.053,0.844,-0.84,1
+168,15496,4179,4326,,Oil exploration,1197,43.44,48.27,20.26,31.41,1,0,9603,44.107,-116.147,-54.648,,,,,0
+169,15497,4179,4326,Derived at 4 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",1197,43.44,48.27,20.26,31.41,1,0,9603,28,-121,-77,,,,,0
+170,15995,4179,4326,"Parameter values taken from Pulkovo 1942(58) to ETRS89 (4) (code 15994) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation.","Accuracy of 1.5 to 3 metres horizontal, 3 to 5m vertical.",1197,43.44,48.27,20.26,31.41,1,0,9607,2.329,-147.042,-92.08,0.309,-0.325,-0.497,5.69,0
+171,15997,4179,4326,Derived at 11 stations.,"For military purposes only. Accuracy 4m, 2m and 4m in X, Y and Z axes.",3293,49,54.89,14.14,24.15,1,0,9603,23,-124,-82,,,,,0
+172,15999,4179,4326,Derived at 7 stations.,For military purposes. Accuracy 3m in each axis.,3212,39.64,42.67,19.22,21.06,1,0,9603,24,-130,-92,,,,,0
+173,1649,4180,4326,"Parameter values taken from EST97 to ETRS89 (1) (code 1648). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1090,57.52,60,20.37,28.2,1,0,9603,0,0,0,,,,,1
+174,1643,4181,4326,"Parameter values from Luxembourg 1930 to ETRS89 (1) (code 1642). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1146,49.44,50.19,5.73,6.53,1,0,9606,-193,13.7,-39.3,-0.41,-2.933,2.688,0.43,0
+175,5486,4181,4326,"Parameter values from Luxembourg 1930 to ETRS89 (3) (code 5485) assuming ETRS89 and WGS 84 are coincident within the one metre level. Replaces tfm code 1643. For an equivalent transformation using the Molodensky-Badekas method see code 5484.",For applications to an accuracy of 1 metre.,1146,49.44,50.19,5.73,6.53,1,0,9607,-189.6806,18.3463,-42.7695,0.33746,3.09264,-2.53861,0.4598,1
+176,1210,4694,4326,,POSGAR 94 is a local realisation of WGS 84.,1033,-58.41,-21.78,-73.59,-52.63,1,0,9603,0,0,0,,,,,1
+177,1886,4183,4326,Derived at 5 stations.,For military purposes only. Accuracy 3m in each axis.,1301,38.32,39.14,-28.9,-26.97,1,0,9603,-104,167,-38,,,,,1
+178,1885,4184,4326,Derived at 2 stations.,For military purposes only. Accuracy 25m in each axis.,1345,36.87,37.96,-25.92,-24.62,1,0,9603,-203,141,53,,,,,1
+179,15794,4708,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,1069,-12.25,-12.08,96.76,96.92,1,0,9603,-491,-22,435,,,,,1
+180,15850,4698,4326,"Also published in US NIMA/NGA TR8350.2 which gives accuracy of +/-25m in each axis and states that derived at one station.","Accuracy +/- 10 metres.",2816,-49.78,-48.6,68.69,70.62,1,0,9603,145,-187,103,,,,,1
+181,15784,4699,4326,Derived at 17 stations in 1994 by University of East London. Residuals less than 2m.,Accuracy 2m.,3209,-20.57,-19.94,57.25,57.85,1,0,9603,-770.1,158.4,-498.2,,,,,1
+182,1955,4188,4326,"Parameter values from TM75 to ETRS89 (2) (code 1953). Assumes each pair of (i) OSNI 1952 and TM75, and (ii) ETRS89 and WGS 84, can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,2530,53.96,55.36,-8.18,-5.34,1,0,9606,482.5,-130.6,564.6,-1.042,-0.214,-0.631,8.15,1
+183,1768,4189,4326,,"Approximation at the +/- 1m level.",1251,0.64,16.75,-73.38,-58.95,1,0,9603,0,0,0,,,,,1
+184,1773,4190,4326,,"Approximation at the +/- 1m level.",1033,-58.41,-21.78,-73.59,-52.63,1,0,9603,0,0,0,,,,,1
+185,15780,4190,4326,,"Approximation at the +/- 1m level.",1033,-58.41,-21.78,-73.59,-52.63,1,1,9603,0,0,0,,,,,0
+186,6964,4191,4326,"Parameter values from Albanian 1987 to ETRS89 (1) (code 6963). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.","Use only for horizontal coordinates; geoid heights must be calculated with ALBGEO3 software.",3212,39.64,42.67,19.22,21.06,1,0,9607,-44.183,-0.58,-38.489,2.3867,2.7072,-3.5196,-8.2703,1
+187,15873,4192,4326,Derived at Manoca tower assuming the pyramid on the tower and the centre of the tower reservoir are co-located. This assumption carries a few metres uncertainty.,Oil exploration.,2555,2.16,4.99,8.45,10.4,1,0,9603,-206.1,-174.7,-87.7,,,,,1
+188,1796,4193,4326,"Derived at two points, checked at a third by Stolt Comex Seaway and Geoid for Elf.",Oil industry,2555,2.16,4.99,8.45,10.4,1,0,9603,-70.9,-151.8,-41.4,,,,,1
+189,1797,4194,4326,Derived at 2 stations.,"For military purposes. Accuracy 25m, 25m and 32m in X, Y and Z axes.",3362,59.74,79,-73.29,-42.52,1,0,9603,164,138,-189,,,,,1
+190,1798,4194,4326,,Topographic mapping.,3362,59.74,79,-73.29,-42.52,1,0,9606,163.511,127.533,-159.789,0,0,0.814,-0.6,0
+191,1799,4195,4326,,Topographic mapping.,2570,68.66,74.58,-29.69,-19.89,1,0,9606,105,326,-102.5,0,0,0.814,-0.6,1
+192,1800,4196,4326,,Topographic mapping.,2571,65.52,65.91,-38.86,-36.81,1,0,9606,-45,417,-3.5,0,0,0.814,-0.6,1
+193,15796,4709,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,3200,24.67,24.89,141.2,141.42,1,0,9603,145,75,-272,,,,,1
+194,15798,4710,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,3183,-16.08,-15.85,-5.85,-5.58,1,0,9603,-320,550,-494,,,,,1
+195,15799,4711,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,1872,24.22,24.35,153.91,154.05,1,0,9603,124,-234,-25,,,,,1
+196,1281,4200,4326,"Derived through concatenation of Pulkovo 1995 to PZ-90 (1) (tfm code 1257) and PZ-90 to WGS 84 (2) (tfm code 1244). Mandated for use in Russia by GOST R 51794-2001, but this has been superseded by GOST R 51794-2008. Replaced by tfm code 5043.",Accuracy 1 metre.,1198,39.87,85.2,18.92,-168.97,1,0,9607,24.82,-131.21,-82.66,0,0,-0.16,-0.12,0
+197,5043,4200,4326,"Derived through concatenation of Pulkovo 1995 to PZ-90.02 to WGS 84. Replaces Pulkovo 1995 to WGS 84 (1), tfm code 1281.",Accuracy 1 metre.,1198,39.87,85.2,18.92,-168.97,1,0,9607,24.47,-130.89,-81.56,0,0,-0.13,-0.22,1
+198,1100,4201,4326,Derived at 22 stations.,For military purposes only. Accuracy 5m in each axis.,1271,3.4,22.24,21.82,47.99,1,0,9603,-166,-15,204,,,,,1
+199,1101,4201,4326,"Derived at 1 station connected to the Adindan (Blue Nile 1958) network through the 1968-69 12th parallel traverse. Note: the Adindan (Blue Nile 1958) CRS is used in Ethiopia and Sudan, not Burkino Faso.",For military purposes. Accuracy 25m in each axis.,1057,9.39,15.09,-5.53,2.4,1,0,9603,-118,-14,218,,,,,0
+200,1102,4201,4326,"Derived at 1 station connected to the Adindan (Blue Nile 1958) network through the 1968-69 12th parallel traverse. Note: the Adindan (Blue Nile 1958) CRS is used in Ethiopia and Sudan, not Cameroon.",For military purposes. Accuracy 25m in each axis.,3226,1.65,13.09,8.45,16.21,1,0,9603,-134,-2,210,,,,,0
+201,1103,4201,4326,Derived at 8 stations.,For military purposes. Accuracy 3m in each axis.,1091,3.4,14.89,32.99,47.99,1,0,9603,-165,-11,206,,,,,0
+202,1104,4201,4326,"Derived at 1 station connected to the Adindan (Blue Nile 1958) network through the 1968-69 12th parallel traverse. Note: the Adindan (Blue Nile 1958) CRS is used in Ethiopia and Sudan, not Mali.",For military purposes. Accuracy 25m in each axis.,1153,10.14,25.01,-12.25,4.26,1,0,9603,-123,-20,220,,,,,0
+203,1105,4201,4326,"Derived at 2 stations connected to the Adindan (Blue Nile 1958) network through the 1968-69 12th parallel traverse. Note: The Adindan (Blue Nile 1958) CRS is used in Ethiopia and Sudan, not Senegal.",For military purposes. Accuracy 25m in each axis.,3304,12.29,16.7,-17.59,-11.36,1,0,9603,-128,-18,224,,,,,0
+204,1106,4201,4326,Derived at 14 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",3311,3.49,22.24,21.82,38.66,1,0,9603,-161,-14,205,,,,,0
+205,1108,4202,4326,"Derived at 105 stations. Replaced by AGD66 to WGS 84 (20) (code 6905).",For military purposes only. Accuracy 3m in each axis.,2575,-43.7,-9.86,112.85,153.69,1,0,9603,-133,-48,148,,,,,0
+206,1665,4202,4326,"Parameter values from AGD66 to GDA94 (2) (code 1458). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation.",Recommended for mid-accuracy use in A.C.T. 1m accuracy.,2283,-35.93,-35.12,148.76,149.4,1,0,9607,-129.193,-41.212,130.73,-0.246,-0.374,-0.329,-2.955,0
+207,1666,4202,4326,"Parameter values from AGD66 to GDA94 (4) (code 1460). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation.",Recommended for mid-accuracy use in NSW and Victoria. 1m accuracy.,2286,-39.2,-28.15,140.96,153.69,1,0,9607,-119.353,-48.301,139.484,-0.415,-0.26,-0.437,-0.613,0
+208,1667,4202,4326,"Parameter values from AGD66 to GDA94 (8) (code 1594). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation.",Recommended for mid-accuracy use in Tasmania. 1m accuracy.,1282,-43.7,-39.52,143.77,148.55,1,0,9607,-120.271,-64.543,161.632,-0.217,0.067,0.129,2.499,0
+209,1668,4202,4326,"Parameter values from AGD66 to GDA94 (9) (code 1595). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation.",Recommended for mid-accuracy use in Northern Territory. 1m accuracy.,2284,-26.01,-10.86,128.99,138,1,0,9607,-124.133,-42.003,137.4,0.008,-0.557,-0.178,-1.854,0
+210,5841,4202,4326,Derived at 25 stations in 2007.,"Accuracy 2m in 2007. Due to significant tectonic activity in PNG, AGD66 and WGS 84 are separating by approximately 7cm per year.",4013,-8.28,-5.59,142.24,144.75,1,0,9603,-124,-60,154,,,,,0
+211,6905,4202,4326,"Derived at 161 stations. Replaces AGD66 to WGS 84 (1) (code 1108).",For military purposes only. Accuracy 5m in each axis.,2575,-43.7,-9.86,112.85,153.69,1,0,9603,-128,-52,153,,,,,0
+212,6943,4202,4326,"Parameter values taken from AGD66 to PNG94 (3) (code 6938). Approximation at the +/- 5m level assuming that PNG94 is equivalent to WGS 84 within the accuracy of the transformation.",Low accuracy transformation suitable for mapping and navigation purposes only.,4214,-10.76,-2.53,140.85,150.96,1,0,9603,-129,-58,152,,,,,0
+213,6944,4202,4326,"Parameter values taken from AGD66 to PNG94 (5) (code 6940). Approximation at the +/- 4m level assuming that PNG94 is equivalent to WGS 84 within the accuracy of the transformation.",Low accuracy transformation suitable for mapping and navigation purposes only.,4013,-8.28,-5.59,142.24,144.75,1,0,9603,-131.3,-55.3,151.8,,,,,0
+214,6945,4202,4326,"Parameter values taken from AGD66 to PNG94 (7) (code 6942). Approximation at the +/- 4m level assuming that PNG94 is equivalent to WGS 84 within the accuracy of the transformation.",Low accuracy transformation suitable for mapping and navigation purposes only.,4216,-6.6,-5.05,140.89,141.54,1,0,9603,-137.4,-58.9,150.4,,,,,0
+215,15788,4202,4326,"Parameter values from AGD66 to GDA94 (1) (code 1278). Derived at 162 stations. Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation.",5m accuracy.,2575,-43.7,-9.86,112.85,153.69,1,0,9603,-127.8,-52.3,152.9,,,,,0
+216,15980,4202,4326,"Parameter values from AGD66 to GDA94 (12) (code 15979). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation. Use only offshore: onshore tfms 1665-68 for ACT, NSW/Vic, Tas and NT respectively are more accurate.",3m accuracy.,3559,-47.2,-8.88,109.23,163.2,1,0,9607,-117.808,-51.536,137.784,-0.303,-0.446,-0.234,-0.29,1
+217,1109,4203,4326,"Derived at 90 stations. Note: AGD84 officially adopted only in Queensland, South Australia and Western Australia.",For military purposes only. Accuracy 2m in each axis.,2575,-43.7,-9.86,112.85,153.69,1,0,9603,-134,-48,149,,,,,1
+218,1236,4203,4326,"""Higgins parameters"". Replaced by AGD84 to GDA94 (2) (code 1280) and AGD84 to WGS 84 (7) (code 1669). Note: AGD84 officially adopted only in Queensland, South Australia and Western Australia.",Preliminary estimate.,2575,-43.7,-9.86,112.85,153.69,1,0,9607,-116,-50.47,141.69,-0.23,-0.39,-0.344,0.0983,0
+219,1669,4203,4326,"Parameter values from AGD84 to GDA94 (2) (code 1280). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaces AGD84 to WGS 84 (2) (code 1236). Note: AGD84 officially adopted only in Qld, SA and WA.",1m accuracy.,2575,-43.7,-9.86,112.85,153.69,1,0,9607,-117.763,-51.51,139.061,-0.292,-0.443,-0.277,-0.191,0
+220,15789,4203,4326,"Parameter values from AGD84 to GDA94 (1) (code 1279). Derived at 327 stations. Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the tfm. AGD84 officially adopted only in Queensland, South Australia and Western Australia.",5m accuracy.,2575,-43.7,-9.86,112.85,153.69,1,0,9603,-128.5,-53,153.4,,,,,0
+221,1055,4204,4326,Derived at station K1.,1 metre accuracy.,3267,28.53,30.09,46.54,48.48,1,0,9603,-145.7,-249.1,1.5,,,,,0
+222,1056,4204,4326,"Derivation is more precise, but no evidence that accuracy is better than Ain el Abd to WGS 84 (3). OGP recommends using Ain el Abd to WGS 84 (3).",1 metre accuracy.,3267,28.53,30.09,46.54,48.48,1,0,9607,-85.645,-273.077,-79.708,-2.289,1.421,-2.532,3.194,0
+223,1057,4204,4326,.,1 metre accuracy.,2956,29.1,30.09,46.54,48.42,1,0,9607,-202.234,-168.351,-63.51,-3.545,-0.659,1.945,2.1,0
+224,1058,4204,4326,,1 metre accuracy.,2957,28.53,29.45,46.54,48.48,1,0,9607,-18.944,-379.364,-24.063,-0.04,0.764,-6.431,3.657,0
+225,1110,4204,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,3943,25.53,26.34,50.39,50.85,1,0,9603,-150,-250,-1,,,,,0
+226,1111,4204,4326,Derived at 9 stations.,For military purposes. Accuracy 10m in each axis.,3303,15.61,32.16,34.51,55.67,1,0,9603,-143,-236,7,,,,,1
+227,1107,4205,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,3308,-1.71,12.03,40.99,51.47,1,0,9603,-43,-163,45,,,,,1
+228,15846,4706,4326,"Sometime referred to as ""Egypt 1907 to WGS 84"". However, application to WGS 84 coordinates of the reverse of this tfm results in Gulf of Suez S-650 TL, not Egypt 1907, position. Gulf of Suez S-650 TL and Egypt 1907 CRSs differ by some 20 metres.",Used for oil exploration by GUPCO.,2341,27.19,30.01,32.34,34.27,1,0,9603,-146.21,112.63,4.05,,,,,1
+229,1656,4207,4326,"Parameter values from Lisbon to ETRS89 (1) (code 1655). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaced by Lisbon to WGS 84 (4) (code 1988).",For applications to an accuracy of 3 metres.,1294,36.95,42.16,-9.56,-6.19,1,0,9606,-280.9,-89.8,130.2,-1.721,0.355,-0.371,-5.92,0
+230,1944,4207,4326,"Parameter values from Lisbon to ETRS89 (2) (code 1790). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 2 metres.,1294,36.95,42.16,-9.56,-6.19,1,1,9606,-282.1,-72.2,120,-1.592,0.145,-0.89,-4.46,0
+231,1984,4207,4326,,For low resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9603,-304.046,-60.576,103.64,,,,,1
+232,1988,4207,4326,,For medium resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9607,-288.885,-91.744,126.244,1.691,-0.41,0.211,-4.598,0
+233,6898,4207,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1294,36.95,42.16,-9.56,-6.19,1,0,9603,-306,-62,105,,,,,0
+234,15877,4720,4326,"Suitable for GIS mapping purposes but not rigorous surveying. Very similar results may be obtained through Fiji 1986 to WGS 84 (1) (tfm code 15876).","Horizontal accuracy 2m, vertical accuracy approximately 40 metres..",3398,-19.22,-16.1,176.81,-179.77,1,0,9607,-35.173,136.571,-36.964,1.37,-0.842,-4.718,-1.537,0
+235,15876,4720,4326,"Approximation at the +/- 2m level assuming that Fiji 1986 is equivalent to WGS 72. Parameter values taken from WGS 72 to WGS 84 (1) (tfm code 1237).",tbc,1094,-20.81,-12.42,176.81,-178.15,1,0,9606,0,0,4.5,0,0,0.554,0.2263,1
+236,1113,4209,4326,Derived at 41 stations.,"For military purposes only. Accuracy 20m, 33m and 20m in X, Y and Z axes.",2312,-30.66,-8.19,19.99,35.93,1,0,9603,-143,-90,-294,,,,,1
+237,1114,4209,4326,Derived at 9 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",1051,-26.88,-17.78,19.99,29.38,1,0,9603,-138,-105,-289,,,,,0
+238,1115,4209,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,1058,-4.45,-2.3,28.98,30.86,1,1,9603,-153,-5,-292,,,,,0
+239,1116,4209,4326,Derived at 5 stations.,"For military purposes. Accuracy 3m, 3m and 8m in X, Y and Z axes.",1141,-30.66,-28.57,27.01,29.46,1,0,9603,-125,-108,-295,,,,,0
+240,1117,4209,4326,Derived at 6 stations.,"For military purposes. Accuracy 9m, 24m and 8m in X, Y and Z axes.",1150,-17.14,-9.37,32.68,35.93,1,0,9603,-161,-73,-317,,,,,0
+241,1118,4209,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,1224,-27.32,-25.72,30.79,32.14,1,0,9603,-134,-105,-295,,,,,0
+242,1119,4209,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,1259,-13.46,5.39,11.79,31.31,1,1,9603,-169,-19,-278,,,,,0
+243,1120,4209,4326,Derived at 5 stations.,"For military purposes. Accuracy 21m, 21m and 27m in X, Y and Z axes.",1260,-18.08,-8.19,21.99,33.71,1,0,9603,-147,-74,-283,,,,,0
+244,1121,4209,4326,"Derived at 10 stations. Replaced by Arc 1950 to WGS 84 (10), tfm code 6906.","For military purposes. Accuracy 5m, 8m and 11m in X, Y and Z axes.",1261,-22.42,-15.61,25.23,33.08,1,0,9603,-142,-96,-293,,,,,0
+245,6904,4209,4326,"Derived at 7 stations. Info source gives source CRS as Arc 1960. From inspection of parameter values, comparison of those from DMA TR8350.2 transformations and geographic applicability of CRS, OGP believes that this should be Arc 1950.","For military purposes only. Accuracy 13m, 25m and 7m in X, Y and Z axes.",1150,-17.14,-9.37,32.68,35.93,1,0,9603,-179,-81,-314,,,,,0
+246,6906,4209,4326,"Derived at 38 stations. Replaces Arc 1950 to WGS 84 (9), tfm code 1121.","For military purposes. Accuracy 10m in each of X, Y and Z axes.",1261,-22.42,-15.61,25.23,33.08,1,0,9603,-145,-97,-292,,,,,0
+247,1122,4210,4326,Derived at 25 stations.,For military purposes only. Accuracy 20m in each axis.,2311,-11.75,4.63,29.34,41.91,1,0,9603,-160,-6,-302,,,,,1
+248,1284,4210,4326,Derived at 24 stations.,"For military purposes. Accuracy 4m, 3m and 3m in X, Y and Z axes.",3264,-4.72,4.63,33.9,41.91,1,0,9603,-157,-2,-299,,,,,0
+249,1285,4210,4326,Derived at 12 stations.,"For military purposes. Accuracy 6m, 9m and 10m in X, Y and Z axes.",3316,-11.75,-0.99,29.34,40.48,1,0,9603,-175,-23,-303,,,,,0
+250,3998,4210,4326,"Derived at 3 stations. From inspection of parameter values and geographic applicability of CRS, OGP believes that the published source CRS (Arc 1950) has been misidentified by information source. Analysis of TR8350.2 contour charts suggest Arc 1960.",For military purposes. Accuracy 20m in each axis.,1058,-4.45,-2.3,28.98,30.86,1,0,9603,-153,-5,-292,,,,,0
+251,1123,4211,4326,"Note: The area of use cited for this transformation (Sumatra) is not consistent with the area of use (Java) for the Batavia (Genuk) coordinate reference system. Derived at 5 stations.",For military purposes. Accuracy 3m in each axis.,1355,-5.99,5.97,95.16,106.13,1,0,9603,-377,681,-50,,,,,1
+252,1813,4211,4326,Used by ARCO offshore NW Java area.,Oil industry operations.,2577,-6.89,-4.07,105.77,110.01,1,0,9603,-378.873,676.002,-46.255,,,,,0
+253,1814,4211,4326,Used by PT Komaritim for Nippon Steel during East Java Gas Pipeline construction.,Oil industry operations.,2588,-8.46,-6.8,112.8,117.01,1,0,9603,-377.7,675.1,-52.2,,,,,0
+254,15793,4212,4326,"Derived at 2 stations (S40 and M1, St Annes Tower) in 2004.",Accuracy 2.5m.,3218,13,13.39,-59.71,-59.37,1,0,9603,31.95,300.99,419.19,,,,,1
+255,15809,4725,4326,"Derived at 2 satellite stations. Note: NGA online html files carry a different dZ value - OGP believe this is an erroneous transcription from the TR8350.2 line above.","Military and topographic mapping. Accuracy +/- 25m in each axis.",3201,16.67,16.79,-169.59,-169.47,1,0,9603,189,-79,-202,,,,,1
+256,6143,4726,4326,"Parameter values are taken from SIGD59 to CIGD11 (1) (code 6137) assuming that CIGD11 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1m.,3186,19.63,19.78,-80.14,-79.69,1,0,9607,8.853,-52.644,180.304,0.393,2.323,-2.96,-24.081,1
+257,15814,4726,4326,Determined from 1 satellite station.,"Military mapping. Accuracy +/- 25m in each axis.",3186,19.63,19.78,-80.14,-79.69,1,0,9603,42,124,147,,,,,0
+258,15829,4726,4326,Determined from 2 satellite stations.,"Topographic survey. Accuracy +/- 1m.",3186,19.63,19.78,-80.14,-79.69,1,0,9603,44.4,109,151.7,,,,,0
+259,6907,4713,4326,"Derived at 2 stations. Replaces Ayabelle Lighthouse to WGS 84 (1) (code 15800).",For military purposes only. Accuracy 10m in each axis.,3238,10.94,12.72,41.75,43.48,1,0,9603,-77,-128,142,,,,,1
+260,15800,4713,4326,"Derived at 1 satellite station. Replaced by Ayabelle Lighthouse to WGS 84 (2) (code 6907).",For military purposes only. Accuracy 25m in each axis.,1081,10.94,12.72,41.75,44.15,1,0,9603,-79,-129,145,,,,,0
+261,1124,4216,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,3221,32.21,32.43,-64.89,-64.61,1,0,9603,-73,213,296,,,,,1
+262,15970,4216,4326,"Parameter values from Bermuda 1957 to BDA2000 (1) (code 15969). Assumes BDA2000 and WGS 84 can be considered the same to within the accuracy of the transformation.","Accuracy +/- 1 metre.",3221,32.21,32.43,-64.89,-64.61,1,0,9607,-292.295,248.758,429.447,-4.9971,-2.99,-6.6906,1.0289,0
+263,15819,4729,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25 m in each axis.",3208,-25.14,-25,-130.16,-130.01,1,0,9603,185,165,42,,,,,1
+264,1125,4218,4326,Derived in 1987 at 7 stations.,"For military purposes. Accuracy 6m, 5m and 6m in X, Y and Z axes.",3686,-4.23,13.68,-79.1,-66.87,1,0,9603,307,304,-318,,,,,1
+265,1597,4218,4326,Derived in 1995 by WGC at first order stations Recreo and Mena via multi-day ties to 4 IGS stations. Residuals under 20cm.,Oil exploration.,2315,4.75,5.68,-73,-72.25,1,0,9603,304.5,306.5,-318.1,,,,,0
+266,15715,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (1) (tfm code 15714).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3082,9.8,12.52,-73,-71.06,1,0,9607,-806.413,-263.5,-622.671,12.414219,-2.9908418,-39.034686,-20.81616,0
+267,15717,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (2) (tfm code 15716).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3083,9.39,11.59,-76.08,-73,1,0,9607,100.783,187.382,-47,-9.2238300,2.4238033,-8.3082783,-13.56561,0
+268,15719,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (3) (tfm code 15718).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3084,8,9.4,-77.48,-74.39,1,0,9607,336.026,348.565,252.978,-17.241289,-6.3064928,1.5620498,-5.771909,0
+269,15721,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (4) (tfm code 15720).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3085,5,9.4,-74.4,-71.99,1,0,9607,963.273,486.386,190.997,-16.485036,-1.6688258,21.692849,-13.89914,0
+270,15723,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (5) (tfm code 15722).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3086,5,8.01,-77.92,-74.39,1,0,9607,-90.29,247.559,-21.989,-8.6968853,-4.1880336,-12.808267,2.181658,0
+271,15725,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (6) (tfm code 15724).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3087,3,5.01,-77.68,-74.39,1,0,9607,-0.562,244.299,-456.938,6.8668710,-8.2526735,-9.2967797,3.74656,0
+272,15727,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (7) (tfm code 15726).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3088,-1.13,3.01,-79.1,-74,1,0,9607,-305.356,222.004,-30.023,-9.6904939,1.0319682,-19.757394,6.325747,0
+273,15729,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (8) (tfm code 15728).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3089,-4.23,7.1,-74.4,-66.87,1,0,9607,221.899,274.136,-397.554,2.8084459,-0.44850859,-2.810172,-2.199943,0
+274,1126,4219,4326,Accuracy estimate not available.,For military purposes.,1287,-3.3,-1.44,105.07,108.35,1,0,9603,-384,664,-48,,,,,1
+275,1318,4220,4326,,Used for oil exploration by Conoco.,2316,-8.59,-7.75,12.58,13.4,1,0,9603,-42.01,-332.21,-229.75,,,,,0
+276,1319,4220,4326,,Used for oil exploration by Texaco.,2317,-7.01,-6.01,12.08,12.84,1,0,9603,-40,-354,-224,,,,,0
+277,1320,4220,4326,"Replaced by Camacupa to WGS 84 (9). Used by Shell prior to 1994.",Oil exploration prior to 1994.,2321,-7.26,-6.03,11.08,12.09,1,0,9606,-37.2,-370.6,-224,0,0,0.554,0.219,0
+278,1321,4220,4326,"Derived as mean of 123 Transit passes at station Cabo Ledo NE base in November 1990. Used by Elf for block 7 up to December 1992 then replaced by Camacupa to WGS 84 (7). Used by Total in block 8, ExxonMobil block 24, Western Geophysical for spec. data.",Oil exploration.,2320,-17.26,-6.01,8.2,13.86,1,0,9603,-41.8,-342.2,-228.2,,,,,0
+279,1322,4220,4326,"Derived at station Djeno during coordination of platform PAL F2 in February 1992. Used by Elf for block 3 up to December 1992 then replaced by Camacupa to WGS 84 (7).",Oil exploration.,2318,-7.34,-6.66,11.74,12.5,1,0,9603,-55.5,-348,-229.2,,,,,0
+280,1323,4220,4326,Derived at Luanda observatory December 1992.,Used for oil exploration by Elf for 1993 block 7 shallow water survey.,2319,-10.09,-9.41,12.66,13.39,1,0,9603,-43,-337,-233,,,,,0
+281,1324,4220,4326,"Derived at platform PAL F2 in December 1992. For use in blocks 3, 7 and 17, replaced by Camacupa to WGS 84 (10) (code 1327).","Used for oil exploration by Elf for blocks 3, 7 and 17 between December 1992 and 1994 then superseded by Camacupa to WGS 84 (10). Used by Exxon for block 15 since 1993.",2322,-10.09,-6.03,10.83,13.39,1,0,9603,-48,-345,-231,,,,,0
+282,1325,4220,4326,"Derived at platform PAL F2 in December 1992. Used by Total for block 2 between December 1992 and 1994 then replaced by Camacupa to WGS 84 (10).",Oil exploration between December 1992 and 1994.,2317,-7.01,-6.01,12.08,12.84,1,0,9603,-48.6,-345.1,-230.8,,,,,0
+283,1326,4220,4326,"Derived by GPS on two Topnav DGPS reference stations at Djeno and Luanda. Replaces Camacupa to WGS 84 (3). In block 18 replaced by BP from 1999 by Camacupa to WGS 84 (10).",Used by Shell since 1994.,2323,-8.34,-6.03,11.08,12.75,1,0,9606,-41.057,-374.564,-226.287,0,0,0.554,0.219,0
+284,1327,4220,4326,Derived at platform PAL F2 in 1994 by Topnav using Doris.,Used for oil exploration by Elf in blocks 3 and 17 since 1994. Used by Total in block 2 since 1994. Adopted by BP-Amoco Elf and Exxon for blocks 18 and 31-33 in 1999.,2324,-8.59,-6.01,10.41,12.84,1,0,9603,-50.9,-347.6,-231,,,,,1
+285,1127,4221,4326,Derived at 20 stations.,For military purposes. Accuracy 5m in each axis.,3843,-54.93,-21.78,-73.59,-53.65,1,0,9603,-148,136,90,,,,,1
+286,1527,4221,4326,"Derived through ties at 2 stations (Cerro Colorado and Chihuido Sur) to 4 IGS stations in February 1995",Oil exploration.,2325,-37.5,-36.14,-70.5,-70.03,1,0,9603,-154.5,150.7,100.4,,,,,0
+287,1128,4222,4326,Derived at 5 stations.,"For military purposes. Accuracy 3m, 6m and 6m in X, Y and Z axes.",3309,-34.88,-22.13,16.45,32.95,1,0,9603,-136,-108,-292,,,,,1
+288,1129,4222,4326,"Parameter values are from Cape to Hartebeesthoek94 (1) (code 1504) assuming that Hartebeesthoek94 and WGS 84 are equivalent within the accuracy of the transformation. Residuals should not exceed 15 metres.",Accuracy 15m.,3309,-34.88,-22.13,16.45,32.95,1,0,9603,-134.73,-110.92,-292.66,,,,,0
+289,1130,4223,4326,Derived at 5 stations.,"For military purposes. Accuracy 6m, 9m and 8m in X, Y and Z axes.",1236,30.23,38.41,7.49,13.67,1,0,9603,-263,6,431,,,,,1
+290,1538,4223,4326,Derived at station Chaffar January 1995.,Oil exploration.,1489,33.22,38.41,7.81,13.67,1,0,9603,-260.1,5.5,432.2,,,,,0
+291,1131,4224,4326,Derived at 6 stations.,"For military purposes. Accuracy 6m, 9m and 5m in X, Y and Z axes.",3675,-22,-19.29,-62.57,-57.81,1,0,9603,-134,229,-29,,,,,0
+292,3972,4224,4326,"Mandatory for SICAD use until 2005. Replaced by Chua to SIRGAS 2000 (tfm code 4069).","Used by governmental agencies in Distrito Federal until adoption of SIRGAS 2000 by Brazil in 2005. Legally mandated for Cartography System of Distrito Federal (SICAD) until 2005.",3619,-15.94,-15.37,-48.1,-47.1,1,0,9603,-143.87,243.37,-33.52,,,,,1
+293,4834,4224,4326,"Parameter values from Chua to SIRGAS 2000 (1) (tfm code 4069) assuming that within the tfm accuracy SIRGAS 2000 is equivalent to WGS 84.","Cartography System of Distrito Federal (SICAD)",3619,-15.94,-15.37,-48.1,-47.1,1,0,9603,-144.35,242.88,-33.2,,,,,0
+294,1132,4225,4326,Derived at 17 stations.,"For military purposes. Accuracy 5m, 3m and 5m in X, Y and Z axes.",1293,-33.78,-2.68,-58.16,-34.74,1,0,9603,-206,172,-6,,,,,0
+295,6192,4225,4326,"Formed by concatenation of tfms codes 6191 and 1877. Used by Petrobras and ANP until February 2005 when replaced by Corrego Alegre 1970-72 to WGS 84 (4) (tfm code 6194).",Medium and small scale mapping.,1293,-33.78,-2.68,-58.16,-34.74,1,0,9603,-205.57,168.77,-4.12,,,,,1
+296,6194,4225,4326,"Parameter values from Corrego Alegre to SIRGAS 2000 (2) (tfm code 6193) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Used by ANP and Petrobras from February 2005, replacing use of tfm code 6192.",Medium and small scale mapping.,1293,-33.78,-2.68,-58.16,-34.74,1,0,9603,-206.05,168.28,-3.82,,,,,0
+297,15842,4739,4326,"Derived at 2 satellite stations. Care: does not use Hong Kong 1963 (code 4838) as the source CRS.","Military mapping. Accuracy +/- 1m.",1118,22.13,22.58,113.76,114.51,1,0,9603,-156,-271,-189,,,,,1
+298,1244,4740,4326,"Mandated for use in Russia by GosStandard of Russia Decree #327 of August 9, 2001. Republished but with one significant figure less precision to parameter values in GOST R 51794-2008 of December 18 2008.",Geodetic applications. Accuracy better than 0.5 metre.,1198,39.87,85.2,18.92,-168.97,1,0,9607,-1.08,-0.27,-0.9,0,0,-0.16,-0.12,0
+299,15843,4740,4326,"Derived through Glonass and GPS at 30 stations throughout USSR - Former Soviet Union (FSU).",Geodetic applications. Accuracy better than 1.5 metres.,1262,-90,90,-180,180,1,0,9607,0,0,1.5,0,0,-0.076,0,1
+300,1148,4229,4326,Derived at 14 stations.,"For military purposes. Accuracy 3m, 6m and 8m in X, Y and Z axes.",1086,21.89,33.82,24.7,37.91,1,0,9603,-130,110,-13,,,,,1
+301,1546,4229,4326,,Used for oil exploration by GUPCO.,2341,27.19,30.01,32.34,34.27,1,1,9603,-146.21,112.63,4.05,,,,,0
+302,1075,4230,4326,"Derived in 1987 by Geodetic for TPAO. Used on BP 1991/92 2D seismic surveys in central and eastern Turkish sector of Black Sea. In Turkey, replaced by tfm code 1784. Also adopted for use offshore Israel.",Oil Exploration,2896,31.35,43.45,28.03,41.47,1,0,9603,-89.05,-87.03,-124.56,,,,,0
+303,1087,4230,4326,,Topographic mapping.,1130,29.18,33.38,34.88,39.31,1,0,9603,-112,-110.3,-140.2,,,,,0
+304,1133,4230,4326,Derived at 85 stations. In Germany will be accepted by LBA for minerals management purposes as alternative to tfm 1052 or 1998.,"For military purposes. Accepted for minerals management in Germany. Accuracy 3m, 8m and 5m in X, Y and Z axes.",2420,34.88,71.21,-9.56,31.59,1,0,9603,-87,-98,-121,,,,,1
+305,1134,4230,4326,Derived at 52 stations.,For military purposes only. Accuracy 3m each axis.,2421,42.33,57.8,-4.87,17.17,1,0,9603,-87,-96,-120,,,,,0
+306,1135,4230,4326,Accuracy estimate not available.,For military purposes only.,2345,15.61,37.39,34.17,55.67,1,0,9603,-103,-106,-141,,,,,0
+307,1136,4230,4326,Derived at 4 stations.,For military purposes only. Accuracy 15m in each axis.,1078,32.88,36.21,29.95,35.2,1,0,9603,-104,-101,-140,,,,,0
+308,1137,4230,4326,Derived at 14 stations.,"For military purposes. Accuracy 6m, 8m and 8m in X, Y and Z axes.",2595,25.71,31.68,24.7,30,1,0,9603,-130,-117,-151,,,,,0
+309,1138,4230,4326,Derived at 40 stations.,For military purposes only. Accuracy 3m in each axis.,2343,49.11,60.9,-10.56,1.84,1,0,9603,-86,-96,-120,,,,,0
+310,1139,4230,4326,Derived at 20 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",2344,57.93,71.21,4.68,31.59,1,0,9603,-87,-95,-120,,,,,0
+311,1140,4230,4326,Derived at 2 stations.,For military purposes only. Accuracy 25m in each axis.,3254,34.88,41.75,19.57,28.3,1,0,9603,-84,-95,-130,,,,,0
+312,1142,4230,4326,Derived at 2 stations.,For military purposes only. Accuracy 25m in each axis.,2339,38.82,41.31,8.08,9.89,1,0,9603,-97,-103,-120,,,,,0
+313,1143,4230,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,2340,36.59,38.35,12.36,15.71,1,0,9603,-97,-88,-135,,,,,0
+314,1144,4230,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,3275,35.74,36.05,14.27,14.63,1,0,9603,-107,-88,-149,,,,,0
+315,1145,4230,4326,Derived at 18 stations.,"For military purposes only. Accuracy 5m, 6m and 3m in X, Y and Z axes.",2338,35.26,43.82,-9.56,3.39,1,0,9603,-84,-107,-120,,,,,0
+316,1245,4230,4326,Derived at 4 stations.,For military purposes only. Accuracy 25m in each axis.,1236,30.23,38.41,7.49,13.67,1,0,9603,-112,-77,-145,,,,,0
+317,1275,4230,4326,"These same parameter values are used to transform to ETRS89. See ED50 to ETRS89 (10) (code 1650).",For applications to an accuracy of 2 metres.,1096,41.15,51.56,-9.86,10.38,1,0,9603,-84,-97,-117,,,,,0
+318,1311,4230,4326,"Based on ED50 to WGS72 (precise ephemeris) 6-nations agreement of 1981 to which precise to broadcast and broadcast to WGS 84 transformations have been concatenated.",Recommended transformation for UKCS and IrishCS petroleum purposes.,2342,47.42,63.89,-16.1,10.86,1,0,9606,-89.5,-93.8,-123.1,0,0,-0.156,1.2,0
+319,1440,4230,4326,,Used in oil industry.,3254,34.88,41.75,19.57,28.3,1,0,9603,-86,-92.2,-127.5,,,,,0
+320,1612,4230,4326,"Parameter values are taken from ED50 to ETRS89 (1), code 1588. Adopted for ED50 to WGS84 transformations offshore Norway north of 62N from April 2001 when it replaced code 1590. Included in Statens Kartverk programme wsktrans from v4.0.",Oil industry offshore.,2601,62,84.17,-3.7,39.65,1,0,9606,-116.641,-56.931,-110.559,0.893,0.921,-0.917,-3.52,0
+321,1613,4230,4326,"Approximation to 1 metre of concatenated transformation ED50 to WGS 84 (14), code 8653. 8653 remains the transformation promulgated by Statens Kartverk but 1613 recommended by EPSG for practical oil industry usage.",Approximation to 1 metre for oil industry use.,2334,56.08,62,1.37,11.14,1,0,9606,-90.365,-101.13,-123.384,0.333,0.077,0.894,1.994,0
+322,1627,4230,4326,"Parameter values from ED50 to ETRS89 (4) (code 1626). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,3237,54.51,57.8,8,15.24,1,0,9606,-81.1,-89.4,-115.8,0.485,0.024,0.413,-0.54,0
+323,1629,4230,4326,"Parameter values from ED50 to ETRS89 (5) (code 1628). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1105,36,36.16,-5.42,-4.89,1,0,9603,-116.8,-106.4,-154.4,,,,,0
+324,1631,4230,4326,"Parameter values from ED50 to ETRS89 (6) (code 1630). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1.5 metres.,2335,38.59,40.11,1.14,4.39,1,0,9606,-181.5,-90.3,-187.2,0.144,0.492,-0.394,17.57,0
+325,1633,4230,4326,"Parameter values from ED50 to ETRS89 (7) (code 1632). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1.5 metres.,2336,35.26,43.56,-7.54,3.39,1,0,9606,-131,-100.3,-163.4,-1.244,-0.02,-1.144,9.39,0
+326,1635,4230,4326,"Parameter values from ED50 to ETRS89 (8) (code 1634). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1.5 metres.,2337,41.5,43.82,-9.37,-4.5,1,0,9606,-178.4,-83.2,-221.3,0.54,-0.532,-0.126,21.2,0
+327,1784,4230,4326,"Parameter values from ED50 to ETRS89 (9) (code 1783). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 2 metres.,1237,34.42,43.45,25.62,44.83,1,0,9606,-84.1,-101.8,-129.7,0,0,0.468,1.05,0
+328,1810,4230,4326,Derived via concatenation through WGS72. The ED50 to WGS72 step is the Sepplin 1974 value for all Europe.,Oil industry exploration and production operations.,2595,25.71,31.68,24.7,30,1,0,9606,-84,-103,-122.5,0,0,0.554,0.2263,0
+329,1853,4230,4326,Derived at a single point in Galway docks.,Used by Enterprise for Corrib.,2961,53.75,55.76,-12.5,-9.49,1,0,9603,-82.31,-95.23,-114.96,,,,,0
+330,1961,4230,4326,"Parameter values taken from ED87 to WGS 84 (2) (tfm code 1960) assuming that ED87 is identical to ED50. Errors caused by this assumption can reach 3m.",Used by NAM for offshore operations.,1630,51.45,55.77,2.53,6.41,1,1,9606,-83.11,-97.38,-117.22,0.005693,-0.04469,0.4428,1.218,0
+331,1985,4230,4326,May be taken as a transformation from ED50 to ETRS89 - see tfm code 5040.,For low resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9603,-87.987,-108.639,-121.593,,,,,0
+332,1989,4230,4326,,For medium resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9607,-74.292,-135.889,-104.967,0.524,0.136,-0.61,-3.761,0
+333,1998,4230,4326,"Approximation to better than 0.5m of transformation adopted in June 2003 (see ED50 to WGS 84 (35), code 1052). Acceptable to Landesbergamt for Lower Saxony and Bundesanstalt für Seeschifffahrt und Hydrographie.",Recommended transformation for Germany North Sea petroleum purposes.,2879,53.6,55.92,3.34,8.88,1,0,9606,-157.89,-17.16,-78.41,2.118,2.697,-1.434,-5.38,0
+334,1999,4230,4326,"Parameter values taken from ED87 to WGS 84 (2) (tfm code 1960) assuming that ED87 is identical to ED50. Errors caused by this assumption can reach 3m.",Used by NAM for offshore operations.,1630,51.45,55.77,2.53,6.41,1,1,9606,-83.11,-97.38,-117.22,0.005693,-0.04469,0.04428,1.218,0
+335,3904,4230,4326,"Parameter values from ED87 to WGS 84 (32) (tfm code 3905), assuming that ED87 is identical to ED50. Errors caused by this assumption can reach 3-5m. Used by NAM for offshore operations until mid 2004, then replaced by tfm code 1311.","E&P operations in the Dutch sector of the North Sea.",1630,51.45,55.77,2.53,6.41,1,0,9606,-83.11,-97.38,-117.22,0.005693,-0.044698,0.044285,0.1218,0
+336,15964,4230,4326,Developed by the Portuguese Hydrographic Institute and used by the Directorate of Energy and Geology.,Hydrography and minerals management offshore Portugal.,3537,34.91,41.88,-13.87,-7.24,1,0,9603,-86.277,-108.879,-120.181,,,,,0
+337,1146,4231,4326,,"?",2330,51.03,62.01,-5.05,11.14,1,0,9606,-82.981,-99.719,-110.709,-0.10470,0.031002,0.080402,-0.3143,0
+338,1960,4231,4326,,Scientific research.,1297,34.88,71.21,-10.56,31.59,1,1,9606,-83.11,-97.38,-117.22,0.005693,-0.04469,0.04428,1.218,0
+339,3905,4231,4326,"Parameter values taken from ED87 to ETRS89 (1) (tfm code 4078) assuming that ETRS89 is coincident with WGS 84 within the accuracy of the transformation. Used as a tfm between ED50 and WGS 84 - see code 3904.",Scientific research.,1297,34.88,71.21,-10.56,31.59,1,0,9606,-83.11,-97.38,-117.22,0.005693,-0.044698,0.044285,0.1218,1
+340,1256,4232,4326,"Derived at 7 stations. Replaced by Fahud to WGS 84 (3) (code 6908).","For military purposes. Accuracy 3m, 3m and 9m in X, Y and Z axes.",4009,16.59,26.42,51.99,59.91,1,0,9603,-346,-1,224,,,,,0
+341,1438,4232,4326,,Oil exploration.,4009,16.59,26.42,51.99,59.91,1,0,9606,-333.102,-11.02,230.69,0,0,0.554,0.219,1
+342,6908,4232,4326,"Derived at 11 stations. Replaces Fahud to WGS 84 (1) (code 1256).","For military purposes. Accuracy 3m, 3m and 6m in X, Y and Z axes.",4009,16.59,26.42,51.99,59.91,1,0,9603,-345,3,223,,,,,0
+343,1894,4233,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1152,-3.47,8.1,69.29,77.08,1,1,9603,-133,-321,50,,,,,0
+344,7033,4744,4326,Derived by concatenation of parameter values published by IGN Paris from Nahrwan 1934 to WGS 72 at the Nahrwan SE Base station near Baghdad with DMA WGS 72 to WGS 84 parameter values. For more accurate transformation away from origin see codes 7008-7032.,Oil exploration.,3625,29.06,37.39,38.79,48.61,1,0,9603,-242.2,-144.9,370.3,,,,,1
+345,15817,4727,4326,"Derived at 1 satellite station. Information source states ""provided for historical purposes only. These parameter [values] should not be used"". Replaced by Midway 1961 to WGS 84 (2) (tfm code 15818).","Military and topographic mapping. Accuracy +/- 25m in each axis.",3202,28.13,28.28,-177.45,-177.31,1,0,9603,912,-58,1227,,,,,0
+346,15818,4727,4326,"Derived at 1 satellite station. Replaces Midway 1961 to WGS 84 (1) (tfm code 15817).","Military and topographic mapping. Accuracy +/- 25m in each axis.",3202,28.13,28.28,-177.45,-177.31,1,0,9603,403,-81,277,,,,,1
+347,1152,4236,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,3315,21.87,25.34,119.25,122.06,1,0,9603,-637,-549,-203,,,,,1
+348,1242,4237,4326,"Parameter value error in info source Hungarian text but correct in English summary. Replaces HD72 to WGS 84 (2) (code 1831).",Accuracy at metre level throughout Hungary.,1119,45.74,48.58,16.11,22.9,1,0,9603,52.17,-71.82,-14.9,,,,,1
+349,1448,4237,4326,"Parameter values taken from HD72 to ETRS89 (2) (code 1449) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaces HD72 to WGS 84 (1) (code 1830).","Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84.",1119,45.74,48.58,16.11,22.9,1,0,9607,52.684,-71.194,-13.975,0.312,0.1063,0.3729,1.0191,0
+350,1677,4237,4326,"Parameter values taken from HD72 to ETRS89 (1) (code 1273) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation.","Approximation at the +/- 1m level.",1119,45.74,48.58,16.11,22.9,1,1,9607,56,75.77,15.31,-0.37,-0.2,-0.21,-1.01,0
+351,1830,4237,4326,"Parameter values taken from HD72 to ETRS89 (1) (code 1829) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. OGP recommends use of newer MSZ 7222 equivalent (tfm code 1448) in preference to this transformation.","Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84.",1119,45.74,48.58,16.11,22.9,1,0,9607,56,-75.77,-15.31,0.37,0.2,0.21,1.01,0
+352,1831,4237,4326,"Derived at fundamental point Szolohegy and tested at 99 stations throughout Hungary. OGP recommends use of newer transformation (tfm code 1242) in preference to this transformation.",Accuracy better than 1m in all three dimensions throughout Hungary.,1119,45.74,48.58,16.11,22.9,1,0,9603,57.01,-69.97,-9.29,,,,,0
+353,1248,4238,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,4020,-10.98,5.97,95.16,141.01,1,0,9603,-24,-15,5,,,,,1
+354,1832,4238,4326,"Derived via coordinates of 2 Pulse8 stations. Use of ID74 to WGS 84 (3) (code 1833) is recommended.",For oil industry purposes.,4020,-10.98,5.97,95.16,141.01,1,0,9606,2.691,-14.757,4.724,0,0,0.774,-0.6,0
+355,1833,4238,4326,"Parameter values from ID74 to DGN95 (1) (code 15911) assuming that DGN95 is equivalent to WGS 84 within the accuracy of the transformation.","Standard deviations of translations are 1.3, 1.1 and 3.6m, of rotations 0.11, 0.06 and 0.04 sec and ppm 0.18.",4020,-10.98,5.97,95.16,141.01,1,0,9607,-1.977,-13.06,-9.993,-0.364,-0.254,-0.689,-1.037,0
+356,1153,4239,4326,Derived at 11 stations.,"For military purposes. Accuracy 15m, 6m and 12m in X, Y and Z axes.",3317,5.63,20.46,97.34,105.64,1,0,9603,217,823,299,,,,,1
+357,1154,4240,4326,"Derived at 62 stations. Replaced by Indian 1975 to WGS 84 (2) (code 1304).","For military purposes. Accuracy 3m, 2m and 3m in X, Y and Z axes.",3741,5.63,20.46,97.34,105.64,1,0,9603,209,818,290,,,,,0
+358,1304,4240,4326,"Derived at 62 stations. Replaces Indian 1975 to WGS 84 (1) (code 1154).","For military purposes. Accuracy 3m, 2m and 3m in X, Y and Z axes.",3741,5.63,20.46,97.34,105.64,1,0,9603,210,814,289,,,,,1
+359,1537,4240,4326,Derived in 1995 at point RTSD181.,Oil exploration.,2358,6.74,8.16,102.16,103.05,1,0,9603,204.64,834.74,293.8,,,,,0
+360,1812,4240,4326,,Cadastral survey.,3317,5.63,20.46,97.34,105.64,1,0,9606,293,836,318,0.5,1.6,-2.8,2.1,0
+361,1084,4242,4326,Derived via NAD27 and WGS 72. Preliminary values derived by Survey Department but not officially promulgated.,For applications requiring 5m accuracy.,3342,17.64,18.58,-78.43,-76.17,1,0,9603,70,207,389.5,,,,,1
+362,1085,4242,4326,"Derived at 4 stations, tested at a further 9.",For applications requiring 2m accuracy.,3342,17.64,18.58,-78.43,-76.17,1,0,9603,65.334,212.46,387.63,,,,,0
+363,1086,4242,4326,"Derived at 4 stations, tested at a further 9.",For applications requiring 1m accuracy.,3342,17.64,18.58,-78.43,-76.17,1,1,9607,-33.722,153.789,94.959,8.581,4.478,-4.54,-8.95,0
+364,15927,4242,4326,"Derived at 4 stations, tested at a further 9. Also used as tfm to JAD69 to JAD2001 (see code 15926).
 Note: Info source paper contains an error in sign of dS, subsequently confirmed by primary author and NLA of Jamaica, and corrected in this record.",For applications requiring 1m accuracy.,3342,17.64,18.58,-78.43,-76.17,1,0,9607,-33.722,153.789,94.959,8.581,4.478,-4.54,8.95,0
-373,1930,4642,4326,,"Accuracy better than +/- 1 metre.",2820,-22.73,-22.49,167.36,167.61,1,1,9606,244.416,85.339,168.114,-8.9353,7.7523,12.5953,14.268,0
-374,15848,4642,4326,,"Accuracy +/- 10 metres.",2820,-22.73,-22.49,167.36,167.61,1,0,9603,-13,-348,292,,,,,1
-375,1157,4244,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,3310,5.86,9.88,79.64,81.95,1,0,9603,-97,787,86,,,,,1
-376,1158,4245,4326,Derived at 6 stations.,"For military purposes. Accuracy 10m, 8m and 6m in X, Y and Z axes.",1309,1.13,6.72,99.59,104.6,1,0,9603,-11,851,5,,,,,1
-377,1059,4246,4326,,1 metre accuracy.,3267,28.53,30.09,46.54,48.48,1,0,9603,-294.7,-200.1,525.5,,,,,1
-378,1516,4247,4326,Also used for PSAD56 to WGS 84 transformations.,"Parameter values estimated accuracy: ± 2.0m; ± 2.7m; ± 1.3m respectively.",2363,3.56,10.8,-67.49,-59.8,1,0,9603,-273.5,110.6,-357.9,,,,,1
-379,1201,4248,4326,Derived at 63 stations. DMA also lists Colombia as area of applicability but PSAD56 is not used in that country.,"For military purposes only. Accuracy 17m, 27m and 27m in X, Y and Z axes.",2399,-45,12.52,-81.41,-56.47,1,0,9603,-288,175,-376,,,,,1
-380,1202,4248,4326,Derived at 5 stations.,"For military purposes only. Accuracy 5m, 11m and 14m in X, Y and Z axes.",1049,-22.91,-9.67,-69.66,-57.52,1,0,9603,-270,188,-388,,,,,0
-381,1203,4248,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2402,-21.51,-17.5,-70.49,-68.18,1,0,9603,-270,183,-390,,,,,0
-382,1204,4248,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,2403,-45,-38.99,-75.22,-71.1,1,0,9603,-305,243,-442,,,,,0
-383,1205,4248,4326,"Derived at 4 stations. Note that although the PSAD56 network included Colombia the CRS is not used there: see Bogota 1975 (CRS code 4218).",For military purposes. Accuracy 15m in each axis.,3229,-4.23,12.52,-79.1,-66.87,1,0,9603,-282,169,-371,,,,,0
-384,1206,4248,4326,Derived at 11 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",3241,-5.01,1.45,-81.03,-75.21,1,0,9603,-278,171,-367,,,,,0
-385,1207,4248,4326,Derived at 9 stations.,"For military purposes. Accuracy 6m, 14m and 5m in X, Y and Z axes.",1114,1.18,10.7,-61.39,-55.77,1,0,9603,-298,159,-369,,,,,0
-386,1208,4248,4326,Derived at 6 stations.,"For military purposes only. Accuracy 6m, 8m and 12m in X, Y and Z axes.",1189,-21.05,-0.03,-84.68,-68.67,1,0,9603,-279,175,-379,,,,,0
-387,1209,4248,4326,Derived at 24 stations.,"For military purposes only. Accuracy 9m, 14m and 15m in X, Y and Z axes.",1251,0.64,16.75,-73.38,-58.95,1,0,9603,-295,173,-371,,,,,0
-388,1582,4248,4326,Derived May 1995 by Geoid for Total. OSU91A geoid model used.,Oil exploration.,2400,-14.43,-13.56,-68.96,-67.79,1,0,9603,-259.73,173.12,-398.27,,,,,0
-389,1583,4248,4326,Derived July 1997 by Geoid from data recorded by UGA for Total. OSU91A geoid model used.,Oil exploration.,2401,-21.71,-21.09,-63.44,-62.95,1,0,9603,-307.7,265.3,-363.5,,,,,0
-390,1811,4248,4326,Used by Petrobras for shelf operations.,Oil industry exploration.,1754,-1.05,5.6,-51.64,-48,1,0,9603,-291.87,106.37,-364.52,,,,,0
-391,3990,4248,4326,"Parameter values from PSAD56 to SIRGAS 1995 (1) (code 3971). Assumes SIRGAS 1995 and WGS 84 can be considered the same to within the accuracy of the transformation.","Suitable for mapping at 1:25,000 scale and smaller.",3241,-5.01,1.45,-81.03,-75.21,1,0,9607,-60.31,245.935,31.008,-12.324,-3.755,7.37,0.447,0
-392,15967,4761,4326,"Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84. HTRS96 is a regional realisation of ETRS89.","Accuracy +/- 1 metre.",1076,41.62,46.54,13,19.43,1,0,9603,0,0,0,,,,,1
-393,1159,4250,4326,Derived at 8 stations.,"For military purposes. Accuracy 2m, 3m and 2m in X, Y and Z axes.",1104,1.4,11.16,-3.79,2.1,1,0,9603,-130,29,364,,,,,1
-394,1160,4251,4326,Derived at 4 stations.,For military purposes only. Accuracy 15m in each axis.,3270,4.29,8.52,-11.52,-7.36,1,0,9603,-90,40,88,,,,,1
-395,1887,4182,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,1344,39.3,39.77,-31.34,-31.02,1,0,9603,-425,-169,81,,,,,1
-396,1982,4182,4326,Derived at 2 stations in 1999.,For low resolution applications.,1344,39.3,39.77,-31.34,-31.02,1,0,9603,-422.651,-172.995,84.02,,,,,0
-397,1161,4253,4326,Derived at 6 stations.,"For military purposes. Accuracy 8m, 11m and 9m in X, Y and Z axes.",2364,7.75,19.45,116.89,125.88,1,0,9603,-133,-77,-51,,,,,1
-398,1162,4253,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2365,4.99,10.52,119.76,126.65,1,0,9603,-133,-79,-72,,,,,0
-399,1529,4254,4326,"Derived through ties at 3 stations (RC03, TOTAL11 and MP12) to 3 IGS stations in November 1995",Oil exploration.,2357,-55.11,-52.59,-68.64,-63.73,1,0,9606,18.38,192.45,96.82,0.056,-0.142,-0.2,-0.0013,0
-400,1892,4254,4326,Derived at 2 stations. As the source CRS was used for the border survey this transformation is probably also applicable to adjacent areas of Argentina.,Accuracy 25m in each axis.,2805,-55.96,-52.4,-74.83,-66.33,1,0,9603,16,196,93,,,,,1
-401,1246,4255,4326,Accuracy estimate not available.,For military purposes only.,1024,29.4,38.48,60.5,74.92,1,0,9603,-333,-222,114,,,,,1
-402,1164,4256,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2369,-4.84,-4.5,55.32,55.6,1,0,9603,41,-220,-134,,,,,1
-403,1837,4257,4326,,Oil exploration.,1316,-6.54,-1.88,118.71,120.78,1,0,9603,-587.8,519.75,145.76,,,,,1
-404,1149,4258,4326,,ETRS89 and WGS 84 are realisations of ITRS coincident to within 1 metre. This transformation has an accuracy equal to the coincidence figure.,1298,32.88,84.17,-16.1,39.65,1,0,9603,0,0,0,,,,,1
-405,1571,4258,4326,"Dutch sources also quote an equivalent transformation with parameter values dX=+593.032 dY=+26.000 dZ=+478.741m, rX rY rZ and dS as this tfm. These values belong to a different transformation method and cannot be used with the Coordinate Frame method.",Accuracy 0.5m,1172,50.75,55.77,2.53,7.22,1,1,9607,565.04,49.91,465.84,0.409394387439237,-0.359705195614311,1.86849100035057,4.0772,0
-406,1330,4259,4326,"Derived at Station Y in April 1989 using 572 transit satellite passes. Computed value for dZ was -96.42 but -96.38 has been utilised. Replaced Malongo 1987 to WGS 84 (3) (code 15791) in 1989. Replaced by Malongo 1987 to WGS 84 (2) (code 1557) in 1990.",Offshore oil exploration and production between April 1989 and June 1990.,3180,-6.04,-5.05,10.53,12.37,1,0,9603,-252.95,-4.11,-96.38,,,,,0
-407,1557,4259,4326,"Derived at station Y in July 1990 through Transit single point positioning using 187 passes by Geodetic Survey Ltd. Replaces Malongo 1987 to WGS 84 (1) (trf code 1330).",Offshore oil exploration and production from June 1990.,3180,-6.04,-5.05,10.53,12.37,1,0,9603,-254.1,-5.36,-100.29,,,,,1
-408,15791,4259,4326,"Derived via WGS 72BE by Geodetic for Chevron in 1987 by single point Transit translocation at 1 station (Malongo Y). Replaced in 1989 by Malongo 1987 to WGS 84 (1) (code 1330).",Oil industry exploration and production between September 1987 and April 1989.,3180,-6.04,-5.05,10.53,12.37,1,0,9603,-259.99,-5.28,-97.09,,,,,0
-409,1316,4260,4326,,"?",1060,1.65,13.09,8.32,16.21,1,1,9603,-70.9,-151.8,-41.4,,,,,0
-410,1166,4261,4326,Derived at 9 stations.,"For military purposes. Accuracy 5m, 3m and 3m in X, Y and Z axes.",3280,27.66,35.97,-13.24,-1.01,1,0,9603,31,146,47,,,,,1
-411,1165,4262,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1089,12.36,18.1,36.44,43.31,1,0,9603,639,405,60,,,,,1
-412,1067,4263,4326,"Used by Statoil for deep water blocks 210, 213, 217 and 218. Parameter values interpolated from Racal Survey geocentric translation contour charts for each of these four blocks and then meaned.",Oil industry exploration and production.,3817,3.24,5.54,4.41,6.29,1,0,9603,-92.1,-89.9,114.9,,,,,0
-413,1167,4263,4326,"Derived at 2 stations. Note: Minna is used in Nigeria, not Cameroon.",For military purposes only. Accuracy 25m in each axis.,3226,1.65,13.09,8.45,16.21,1,0,9603,-81,-84,115,,,,,0
-414,1168,4263,4326,Derived at 6 stations.,"For military purposes. Accuracy 3m, 6m and 5m in X, Y and Z axes.",1178,1.92,13.9,2.66,14.65,1,0,9603,-92,-93,122,,,,,1
-415,1534,4263,4326,,Oil exploration.,2371,4.22,6.95,4.35,9.45,1,1,9606,-111.92,-87.85,114.5,1.875,0.202,0.219,0.032,0
-416,1754,4263,4326,"Derived at 8 stations across the Niger delta. Used by Shell SPDC throughout southern Nigeria onshore, delta and shallow offshore from 1994 and by Total in OPL246. Sometimes given with parameter values to greater resolution; values here are adequate.",Oil exploration.,2371,4.22,6.95,4.35,9.45,1,0,9606,-111.92,-87.85,114.5,1.875,0.202,0.219,0.032,0
-417,1818,4263,4326,Concatenated via WGS 72BE.,Oil industry operations.,1717,1.92,6.14,2.66,7.82,1,0,9606,-89,-112,125.9,0,0,0.814,-0.38,0
-418,1819,4263,4326,Used by Shell in southern Nigeria and Total in OPL246.,Oil industry operations.,2371,4.22,6.95,4.35,9.45,1,1,9606,-111.92,-87.85,114.5,1.875,0.202,0.219,0.032,0
-419,1820,4263,4326,Derived by Nortech at station L40 Minna using NNPC 1989 GPS network tied to 4 ADOS stations. Used by Conoco in OPLs 219-220 to cm precision and ExxonMobil in OPL 209 to dm precision..,Oil industry operations.,3813,3.25,5.54,4.01,6.96,1,0,9603,-93.2,-93.31,121.156,,,,,0
-420,1821,4263,4326,"Derived by Elf Petroleum Nigeria in 1994 at 3 stations (M101 onshore, offshore platforms XSW06 and XSV39) and used in OMLs 99-102 and OPLs 222-223.",Oil industry operations.,3814,3.25,4.51,7.16,8.25,1,0,9603,-88.98,-83.23,113.55,,,,,0
-421,1822,4263,4326,"Used by Shell SNEPCO for OPLs 209-213 and 316. Derived during 1990 Niger Delta control survey at 4 stations (XSU27, 30 31 and 35).",Oil industry exploration and production.,3815,4.22,6.31,3.83,5.17,1,0,9603,-92.726,-90.304,115.735,,,,,0
-422,1823,4263,4326,"Used by Shell SNEPCO for OPLs 217-223. Derived during 1990 Niger Delta control survey at 4 stations (XSU38, 41, 44 and 45).",Oil industry exploration and production.,3816,3.24,3.86,5.58,8,1,0,9603,-93.134,-86.647,114.196,,,,,0
-423,1824,4263,4326,Used by Shell SNEPCO for Gongola basin.,Oil industry exploration and production.,3824,8.78,11.63,9.41,12.13,1,0,9603,-93,-94,124,,,,,0
-424,6196,4263,4326,Used by Addax for OPL 118 and OML 124. Derived in 1999 at 4 stations during  extension into OPL 118 of control in Chevron block OML 53.,Oil industry exploration and production.,4127,5.56,5.74,6.72,6.97,1,0,9603,-93.179,-87.124,114.338,,,,,0
-425,15493,4263,4326,"Adopted by MPN for all joint venture operations from 1/1/1996.",Oil industry exploration and production.,3590,3.99,5.01,5.99,8.01,1,0,9603,-94.031,-83.317,116.708,,,,,0
-426,15705,4263,4326,"Derived via WGS 72(BE). Minna to WGS 72(BE) transformation derived in 1981 for Mobil E&P Nigeria (MEPCON) by Geodetic Survey through Transit translocation at six stations in southern Nigeria. Used by MEPCON in blocks OPL 215 and 221.",Oil industry exploration.,3819,3.25,4.23,5.02,7.31,1,0,9606,-83.13,-104.95,114.63,0,0,0.554,0,0
-427,15706,4263,4326,Used by Elf in Blocks OPL 222 and OPL 223 and by Mobil in 1994.,Oil industry exploration.,1717,1.92,6.14,2.66,7.82,1,0,9603,-93.6,-83.7,113.8,,,,,0
-428,15755,4263,4326,Derived in 1995 at unspecified DMA ADOS stations and Racal stations M101 and ZVS3003. Used by Elf in onshore Block OML 58.,Oil industry exploration and production. Accuracy 0.5m.,3113,5.05,5.36,6.53,6.84,1,0,9603,-90.2,-87.32,114.17,,,,,0
-429,1329,4264,4326,"Superseded in 1990 by trf Malongo 1987 to WGS 84 (2), code 1557. Malongo 1987 is an offshore extension of the Mhast cooordinate system.","Used for oil exploration by Chevron until superseded in 1990 by trf Malongo 1987 to WGS 84 (2), code 1557.",1317,-6.04,-5.05,10.53,12.18,1,1,9603,-252.95,-4.11,-96.38,,,,,0
-430,1088,4265,4326,,Oil exploration and production,2882,43.62,45.73,12.22,13.96,1,0,9603,-223.7,-67.38,1.34,,,,,0
-431,1089,4265,4326,,Oil exploration and production,2883,41.95,44.04,13.61,16.14,1,0,9603,-225.4,-67.7,7.85,,,,,0
-432,1090,4265,4326,,Oil exploration and production,2884,40.72,42.28,15.95,18.63,1,0,9603,-227.1,-68.1,14.4,,,,,0
-433,1091,4265,4326,,Marine navigation,2885,39.77,41.03,17.95,18.99,1,0,9603,-231.61,-68.21,13.93,,,,,0
-434,1092,4265,4326,,Marine navigation,2886,37.67,40.47,16.55,18.93,1,0,9603,-225.06,-67.37,14.61,,,,,0
-435,1093,4265,4326,,Marine navigation,2887,35.22,37.48,13,15.16,1,0,9603,-229.08,-65.73,20.21,,,,,0
-436,1094,4265,4326,,Marine navigation,2888,35.28,38.45,10.68,13.01,1,0,9603,-230.47,-56.08,22.43,,,,,0
-437,1169,4265,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2339,38.82,41.31,8.08,9.89,1,0,9603,-225,-65,9,,,,,0
-438,1660,4265,4326,"Parameter values from Monte Mario to ETRS89 (1) (code 1659). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.","Accuracy: 4 metres",2372,37.86,47.1,6.62,18.58,1,0,9606,-104.1,-49.1,-9.9,0.971,-2.917,0.714,-11.68,1
-439,1662,4265,4326,"Parameter values from Monte Mario to ETRS89 (2) (code 1661). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.","Accuracy: 4 metres",2339,38.82,41.31,8.08,9.89,1,0,9606,-168.6,-34,38.6,-0.374,-0.679,-1.379,-9.48,0
-440,1664,4265,4326,"Parameter values from Monte Mario to ETRS89 (3) (code 1663). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.","Accuracy: 4 metres",2340,36.59,38.35,12.36,15.71,1,0,9606,-50.2,-50.4,84.8,-0.69,-2.012,0.459,-28.08,0
-441,1163,4266,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1100,-6.37,2.32,7.03,14.52,1,0,9603,-74,-130,42,,,,,1
-442,1532,4266,4326,Derived as mean of Doris determinations at 3 stations in Port Gentil area in 1994.,Oil exploration.,1100,-6.37,2.32,7.03,14.52,1,0,9603,-80.7,-132.5,41.1,,,,,0
-443,1170,4267,4326,Derived at 15 stations.,"For military purposes. Accuracy 3m, 9m and 12m in X, Y and Z axes.",2418,13,23.25,-85.01,-59.37,1,0,9603,-3,142,183,,,,,0
-444,1171,4267,4326,Derived at 19 stations.,"For military purposes only. Accuracy 8m, 3m and 5m in X, Y and Z axes.",2419,7.98,18.49,-92.29,-82.53,1,0,9603,0,125,194,,,,,0
-445,1172,4267,4326,Derived at 112 stations.,"For military purposes only. Accuracy 15m, 11m and 6m in X, Y and Z axes.",1061,40.04,86.46,-141.01,-47.74,1,0,9603,-10,158,187,,,,,1
-446,1173,4267,4326,Derived at 405 stations.,"For military purposes only. Accuracy 5m, 5m and 6m in X, Y and Z axes.",1323,24.41,49.38,-124.79,-66.91,1,0,9603,-8,160,176,,,,,0
-447,1174,4267,4326,Derived at 129 stations.,"For military purposes only. Accuracy 5m, 5m and 8m in X, Y and Z axes.",2389,24.41,49.38,-97.22,-66.91,1,0,9603,-9,161,179,,,,,0
-448,1175,4267,4326,Derived at 276 stations.,"For military purposes only. Accuracy 5m, 3m and 3m in X, Y and Z axes.",2390,25.83,49.05,-124.79,-89.64,1,0,9603,-8,159,175,,,,,0
-449,1176,4267,4326,Derived at 47 stations.,"For military purposes only. Accuracy 5m, 9m and 5m in X, Y and Z axes.",2412,54.34,71.4,-168.26,-129.99,1,0,9603,-5,135,172,,,,,0
-450,1177,4267,4326,Derived at 11 stations.,"For military purposes. Accuracy 5m, 3m and 5m in X, Y and Z axes.",2413,20.86,27.29,-79.04,-72.68,1,0,9603,-4,154,178,,,,,0
-451,1178,4267,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2414,23.9,24.19,-74.6,-74.37,1,0,9603,1,140,165,,,,,0
-452,1179,4267,4326,Derived at 25 stations.,"For military purposes only. Accuracy 8m, 8m and 6m in X, Y and Z axes.",2384,48.25,60.01,-139.04,-109.98,1,0,9603,-7,162,188,,,,,0
-453,1180,4267,4326,Derived at 25 stations.,"For military purposes only. Accuracy 9m, 5m and 5m in X, Y and Z axes.",2415,41.67,60.01,-102,-74.35,1,0,9603,-9,157,184,,,,,0
-454,1181,4267,4326,Derived at 37 stations.,"For military purposes only. Accuracy 6m, 6m and 3m in X, Y and Z axes.",2416,43.41,62.62,-79.85,-52.54,1,0,9603,-22,160,190,,,,,0
-455,1182,4267,4326,Derived at 17 stations.,"For military purposes only. Accuracy 5m, 5m and 3m in X, Y and Z axes.",2410,49,83.17,-136.46,-60.72,1,0,9603,4,159,188,,,,,0
-456,1183,4267,4326,Derived at 8 stations.,"For military purposes only. Accuracy 5m, 8m and 3m in X, Y and Z axes.",2417,59.99,69.7,-141.01,-123.91,1,0,9603,-7,139,181,,,,,0
-457,1184,4267,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,2385,8.82,9.45,-80.07,-79.46,1,0,9603,0,125,201,,,,,0
-458,1185,4267,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,3235,19.77,23.25,-85.01,-74.07,1,0,9603,-9,152,178,,,,,0
-459,1186,4267,4326,"Derived at 2 stations. Note: NAD27 is not used in Greenland.",For military purposes. Accuracy 25m in each axis.,2386,75.86,79.2,-73.29,-60.98,1,0,9603,11,114,195,,,,,0
-460,1187,4267,4326,Derived at 22 stations.,"For military purposes only. Accuracy 8m, 6m and 6m in X, Y and Z axes.",3278,14.51,32.72,-118.47,-86.68,1,0,9603,-12,130,190,,,,,0
-461,1249,4267,4326,Derived at 6 stations.,"For military purposes only. Accuracy 6m, 8m and 10m in X, Y and Z axes.",2387,51.54,54.34,-178.3,-164.84,1,0,9603,-2,152,149,,,,,0
-462,1250,4267,4326,Derived at 5 stations.,For military purposes. Accuracy 10m in each axis.,2388,51.3,53.07,172.42,179.86,1,0,9603,2,204,105,,,,,0
-463,1530,4267,4326,,Accuracy 3m.,1077,18.83,25.51,-87.01,-73.57,1,0,9603,-4.2,135.4,181.9,,,,,0
-464,15699,4267,4326,"Developed by John E Chance and Associates at 19°44'N, 92°21'W. Geoid height used =-13.34m.","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3462,17.85,20.89,-94.79,-89.75,1,0,9603,-2,124.7,196,,,,,0
-465,15852,4267,4326,"Developed by John E Chance and Associates. Replaced by NAD27 to WGS 84 (79) (tfm code 15851).","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3358,23.82,30.25,-87.25,-81.17,1,0,9603,-3,154,177,,,,,0
-466,15853,4267,4326,"Developed by John E Chance and Associates. Replaced by NAD27 to WGS 84 (79) (tfm code 15851).","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3359,25.61,30.23,-95,-87.25,1,0,9603,-7,151,175,,,,,0
-467,15854,4267,4326,"Developed by John E Chance and Associates. Replaced by NAD27 to WGS 84 (79) (tfm code 15851).","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3360,25.97,28.97,-97.22,-95,1,0,9603,-7,151,178,,,,,0
-468,15855,4267,4326,"Developed by John E Chance and Associates at 21°55'N, 97°20'W. Geoid height used =-17m.","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3361,21.51,22.75,-98.1,-96.89,1,0,9603,-8,125,190,,,,,0
-469,15856,4267,4326,"Developed by EnSoCo Inc. Replaced by NAD27 to WGS 84 (79) (tfm code 15851).",Oil exploration and production. Accuracy 8 metres.,3357,23.82,30.25,-97.22,-81.17,1,0,9603,-7,158,172,,,,,0
-470,15913,4267,4326,"Developed by John E Chance and Associates at 21°33'N, 92°33'W. Geoid height used =-16.7m.","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3461,20.87,23.01,-94.33,-88.67,1,0,9603,0,125,196,,,,,0
-471,15978,4267,4326,,Accuracy 1m.,1077,18.83,25.51,-87.01,-73.57,1,0,9607,2.478,149.752,197.726,-0.526,-0.498,0.501,0.685,0
-472,1188,4269,4326,Derived at 354 stations.,Accuracy 2m in each axis.,1325,23.81,86.46,-172.54,-47.74,1,0,9603,0,0,0,,,,,1
-473,1251,4269,4326,Derived at 4 stations.,"For military purposes only. Accuracy 5m, 2m and 5m in X, Y and Z axes.",2157,51.3,54.34,172.42,-164.84,1,0,9603,-2,0,4,,,,,0
-474,1252,4269,4326,Derived at 6 stations.,For military purposes only. Accuracy 2m in each axis.,3883,15.56,25.58,-163.74,-151.27,1,0,9603,1,1,-1,,,,,0
-475,1308,4269,4326,"Strictly between NAD83 and ITRF94(1996.0). Superseded by NAD83 to WGS 84 (5) (code 1515).",Historical record only - superseded - see remarks.,1323,24.41,49.38,-124.79,-66.91,1,1,9607,-0.9738,1.9453,0.5486,-0.0275507901704247,-0.0100492213603585,-0.0113590028800276,0,0
-476,1515,4269,4326,"Strictly between NAD83 and ITRF96(1997.0). Supersedes NAD83 to WGS 84 (4) (code 1308).",Geodesy.,1323,24.41,49.38,-124.79,-66.91,1,1,9607,-0.991,1.9072,0.5129,-0.0257899075194932,-0.0096500989602704,-0.0116599432323421,0,0
-477,1189,4270,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,2391,20.12,20.74,58.58,59.01,1,0,9603,-247,-148,369,,,,,0
-478,1190,4270,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,3968,24.63,28.57,47.95,50.81,1,0,9603,-243,-192,477,,,,,0
-479,1191,4270,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,1243,22.63,26.27,51.5,57.13,1,0,9603,-249,-156,381,,,,,0
-480,1531,4270,4326,Parameter values adopted by Total are mean of those derived by Oceonics and Geoid through ties at platform AK1 to 4 IGS stations in March 1995.,Oil exploration.,2392,25.33,25.54,53.03,53.4,1,0,9603,-245,-153.9,382.8,,,,,0
-481,1536,4270,4326,"Derived by Brown & Root in 1992 for Qatar General Petroleum Corporation North Field development. Adopted by QGPC for all offshore Qatar.",Oil exploration.,2406,24.64,27.05,50.55,53.04,1,0,9603,-250.2,-153.09,391.7,,,,,0
-482,15871,4270,4326,Derived by concatenation of parameter values published by IGN Paris from Nahrwan 1967 to WGS 72 at the Nahrwan SE Base trig station near Baghdad with DMA WGS 72 to WGS 84 parameter values.,Oil exploration.,3625,29.06,37.39,38.79,48.61,1,0,9603,-242.2,-144.9,370.3,,,,,1
-483,15937,4270,4326,Parameter values adopted by Total are mean of those derived by Oceonics and Geoid through ties at station TC58 to 4 IGS stations in March 1995.,Oil exploration.,3509,24,25.64,51.5,54.85,1,0,9603,-245.8,-152.2,382.9,,,,,0
-484,15938,4270,4326,Derived via WGS 72BE from Transit observations at station TC58 in 1976 by BP for ADMA.,Oil exploration.,3509,24,25.64,51.5,54.85,1,0,9606,-225.4,-158.7,380.8,0,0,0.814,-0.38,0
-485,15952,4270,4326,"Used by DPC for Al Fateh field. Applying this transformation gives same result as Nahrwan 1967 to WGS 84 (8) (code 15938).",Oil exploration and production.,3530,24.94,25.8,54.06,55.3,1,0,9603,-244.2,-149.8,379.3,,,,,0
-486,15953,4270,4326,Used by Dubai Municipality before 1994.,Municipal operations.,3531,24.85,25.34,54.84,55.55,1,0,9603,-250.7,-157.9,380.4,,,,,0
-487,1192,4271,4326,"CAUTION: OGP believes that these parameter values include a blunder and that if NIMA transformation parameters are to be used the 1987 version (EPSG code 1307) be used.",For military purposes only. Accuracy given by NIMA 15m in each axis. EPSG believes there is an 8-10m blunder in dX.,1322,11.09,11.4,-60.9,-60.47,1,0,9603,-10,375,165,,,,,1
-488,1307,4271,4326,"(1) See remarks for tfm code 1192. (2) Naparima 1972 is an extension to Tobago of the Napaima 1955 geographic CRS of Trindad. In Trinidad this transformation may also be considered to use Napaima 1955 (code 4158) as its source CRS: see tfm code 1556.",For military purposes only. Accuracy 15m in each axis.,1322,11.09,11.4,-60.9,-60.47,1,0,9603,-2,374,172,,,,,0
-489,1151,4272,4326,Derived at 14 stations.,"For military purposes only. Accuracy 5m, 3m and 5m in X, Y and Z axes.",3285,-47.65,-33.89,165.87,179.27,1,0,9603,84,-22,209,,,,,0
-490,1564,4272,4326,"These parameter values are taken from NZGD49 to NZGD2000 (2) (code 1701) and assume that NZGD2000 and WGS 84 are coincident to within the accuracy of the transformation. For improved accuracy use NZGD49 to WGS 84 (4) (code 1670).",Transformation accuracy about 4 metres.,3285,-47.65,-33.89,165.87,179.27,1,0,9607,59.47,-5.04,187.44,-0.47,0.1,-1.024,-4.5993,1
-491,15975,4272,4326,"These parameter values are taken from NZGD49 to NZGD2000 (1) (code 1566) and assume that NZGD2000 and WGS 84 are coincident to within the accuracy of the tfm. For better accuracy use NZGD49 to WGS 84 (2) (code 1564) or NZGD49 to WGS 84 (3) (code 1670).",5m accuracy.,3285,-47.65,-33.89,165.87,179.27,1,0,9603,54.4,-20.1,183.1,,,,,0
-492,1654,4273,4326,"Parameter values from NGO 1948 to ETRS89 (1) (code 1653). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 3 metres.,1352,57.93,71.21,4.68,31.22,1,0,9606,278.3,93,474.5,7.889,0.05,-6.61,6.21,1
-493,1658,4274,4326,"Parameter values from Datum 73 to ETRS89 (1) (code 1657). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaced by Datum 73 to WGS 84 (4) (tfm code 1987).",For applications to an accuracy of 2 metres.,1294,36.95,42.16,-9.56,-6.19,1,0,9606,-238.2,85.2,29.9,0.166,0.046,1.248,2.03,0
-494,1945,4274,4326,"Parameter values from Datum 73 to ETRS89 (2) (code 1792). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1294,36.95,42.16,-9.56,-6.19,1,1,9606,-231,102.6,29.8,0.615,-0.198,0.881,1.79,0
-495,1983,4274,4326,,For low resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9603,-223.237,110.193,36.649,,,,,1
-496,1987,4274,4326,,For medium resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9607,-239.749,88.181,30.488,-0.263,-0.082,-1.211,2.229,0
-497,1193,4275,4326,"These same parameter values are used to transform to ETRS89. See NTF to ETRS89 (1) (code 1651).",For applications to an accuracy of 2 metres.,3694,41.31,51.14,-4.87,9.63,1,0,9603,-168,-60,320,,,,,1
-498,1195,4277,4326,Derived at 38 stations.,"For military purposes only. Accuracy 10m, 10m and 15m in X, Y and Z axes.",1264,49.81,60.9,-8.74,1.84,1,0,9603,375,-111,431,,,,,0
-499,1196,4277,4326,Derived at 24 stations.,"For military purposes only. Accuracy 5m, 5m and 6m in X, Y and Z axes.",2395,49.81,55.85,-6.5,1.84,1,0,9603,371,-112,434,,,,,0
-500,1197,4277,4326,Derived at 25 stations.,"For military purposes only. Accuracy 10m, 10m and 15m in X, Y and Z axes.",2396,49.81,55.85,-6.5,1.84,1,0,9603,371,-111,434,,,,,0
-501,1198,4277,4326,Derived at 13 stations.,For military purposes only. Accuracy 10m in each axis.,2397,54.57,60.9,-8.74,-0.65,1,0,9603,384,-111,425,,,,,0
-502,1199,4277,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,2398,51.28,53.48,-5.34,-2.65,1,0,9603,370,-108,434,,,,,0
-503,1314,4277,4326,"For a more accurate transformation see OSGB 1936 / British National Grid to ETRS89 (2) (code 1039): contact the Ordnance Survey of Great Britain (http://www.gps.gov.uk/gpssurveying.asp) for details.",Oil exploration. Accuracy better than 4m and generally better than 2m.,1264,49.81,60.9,-8.74,1.84,1,0,9606,446.448,-125.157,542.06,0.15,0.247,0.842,-20.489,1
-504,5622,4277,4326,Derived by CGG for 1994 3D seismic survey.,Oil exploration and production.,3893,50.53,50.8,-2.2,-1.68,1,0,9603,370.396,-108.938,435.682,,,,,0
-505,4560,4558,4326,"Approximation at the +/- 1m level assuming that RRAF91 is equivalent to WGS 84 within the accuracy of the transformation.","Accuracy +/- 1 metre.",2824,14.08,18.54,-63.66,-57.52,1,0,9603,0,0,0,,,,,1
-506,1074,4281,4326,"Not recognised by Survey of Israel. See Palestine 1923 to WGS 84 (2) (code 8650).","Oil Exploration. Accuracy: 1m to north and 5m to south of east-west line through Beersheba (31°15'N).",2603,29.45,33.28,34.17,35.69,1,0,9606,-275.7224,94.7824,340.8944,-8.001,-4.42,-11.821,1,1
-507,1200,4282,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1072,-6.91,3.72,8.84,18.65,1,0,9603,-148,51,-291,,,,,1
-508,1801,4282,4326,"Derived in 1994 by CGG/Topnav using DORIS system on various stations along the coastline.","?",2574,-6.91,-3.55,8.84,12.34,1,0,9603,-145,52.7,-291.6,,,,,0
-509,1802,4282,4326,Derived by Geoid for Elf in May 1995 using GPS and IGS data by tying 4 geodetic points to ITRF93 epoch 1995.4.,Used by Elf since May 1995 for all offshore Congo operations.,2574,-6.91,-3.55,8.84,12.34,1,0,9606,-178.3,-316.7,-131.5,5.278,6.077,10.979,19.166,0
-510,1150,4283,4326,,GDA94 is a realisation of WGS 84 coincident to within 1 metre. This transformation has an accuracy equal to the coincidence figure.,2575,-43.7,-9.86,112.85,153.69,1,0,9603,0,0,0,,,,,1
-511,1254,4284,4326,Accuracy estimate not available.,For military purposes.,1198,39.87,85.2,18.92,-168.97,1,0,9603,28,-130,-95,,,,,0
-512,1267,4284,4326,"Derived through concatenation of Pulkovo 1942 to PZ-90 (1) (tfm code 15844) and PZ-90 to WGS 84 (2) (tfm code 1244. Mandated for use in Russia by GOST R 51794-2001, but this has been superseded by GOST R 51794-2008. Replaced by tfm code 5044.",Accuracy 4 metres.,1198,39.87,85.2,18.92,-168.97,1,0,9607,23.92,-141.27,-80.9,0,-0.35,-0.82,-0.12,1
-513,1287,4284,4326,Derived at 5 stations.,For military purposes. Accuracy 2m in each axis.,1119,45.74,48.58,16.11,22.9,1,1,9603,28,-121,-77,,,,,0
-514,1288,4284,4326,Derived at 11 stations.,"For military purposes only. Accuracy 4m, 2m and 4m in X, Y and Z axes.",1192,49,55.93,14.14,24.15,1,1,9603,23,-124,-82,,,,,0
-515,1289,4284,4326,Derived at 6 stations.,"For military purposes only. Accuracy 3m, 3m and 2m in X, Y and Z axes.",1306,47.73,51.06,12.09,22.56,1,1,9603,26,-121,-78,,,,,0
-516,1290,4284,4326,Derived at 5 stations.,For military purposes. Accuracy 2m in each axis.,1139,55.67,58.09,19.06,28.24,1,0,9603,24,-124,-82,,,,,0
-517,1291,4284,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,1131,40.59,55.45,46.49,87.35,1,0,9603,15,-130,-84,,,,,0
-518,1292,4284,4326,Derived at 7 stations.,For military purposes. Accuracy 3m in each axis.,1025,39.63,42.67,18.46,21.06,1,1,9603,24,-130,-92,,,,,0
-519,1293,4284,4326,Derived at 4 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",1197,43.44,48.27,20.26,31.41,1,1,9603,28,-121,-77,,,,,0
-520,1303,4284,4326,Mean of 13 stations along entire Kazak coastline.,Residuals under 2 m.,2405,41.15,46.97,48.9,53.15,1,0,9606,43.822,-108.842,-119.585,1.455,-0.761,0.737,0.549,0
-521,1334,4284,4326,,"?",3246,57.52,59.75,21.74,28.2,1,0,9607,21.58719,-97.54127,-60.92546,-1.01378,-0.58117,-0.2348,-4.6121,0
-522,1679,4284,4326,"Parameter values taken from Pulkovo 1942 to LKS94(ETRS89) (1) (code 1274) assuming that LKS94(ETRS89) is equivalent to WGS 84 within the accuracy of the transformation.","Approximation at the +/- 9m level.",1145,53.89,56.45,19.02,26.82,1,0,9607,-40.595,-18.55,-69.339,-2.508,-1.832,2.611,-4.299,0
-523,1807,4284,4326,"Derived via WGS72 values taken from SOCAR Magnavox 1502 manual. Used by AIOC 1995-1997 then replaced by the AIOC97 values (tfm code 1808).
+365,1930,4642,4326,,"Accuracy better than +/- 1 metre.",2820,-22.73,-22.49,167.36,167.61,1,1,9606,244.416,85.339,168.114,-8.9353,7.7523,12.5953,14.268,0
+366,15848,4642,4326,,"Accuracy +/- 10 metres.",2820,-22.73,-22.49,167.36,167.61,1,0,9603,-13,-348,292,,,,,1
+367,1157,4244,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,3310,5.86,9.88,79.64,81.95,1,0,9603,-97,787,86,,,,,1
+368,1158,4245,4326,Derived at 6 stations.,"For military purposes. Accuracy 10m, 8m and 6m in X, Y and Z axes.",4223,1.13,7.81,99.59,105.82,1,0,9603,-11,851,5,,,,,1
+369,1059,4246,4326,,1 metre accuracy.,3267,28.53,30.09,46.54,48.48,1,0,9603,-294.7,-200.1,525.5,,,,,1
+370,1516,4247,4326,Also used for PSAD56 to WGS 84 transformations.,"Parameter values estimated accuracy: ± 2.0m; ± 2.7m; ± 1.3m respectively.",2363,3.56,10.8,-67.49,-59.8,1,0,9603,-273.5,110.6,-357.9,,,,,1
+371,1201,4248,4326,Derived at 63 stations. DMA also lists Colombia as area of applicability but PSAD56 is not used in that country.,"For military purposes only. Accuracy 17m, 27m and 27m in X, Y and Z axes.",2399,-45,12.52,-81.41,-56.47,1,0,9603,-288,175,-376,,,,,1
+372,1202,4248,4326,Derived at 5 stations.,"For military purposes only. Accuracy 5m, 11m and 14m in X, Y and Z axes.",1049,-22.91,-9.67,-69.66,-57.52,1,0,9603,-270,188,-388,,,,,0
+373,1203,4248,4326,"Derived at 1 station. Replaced by PSAD56 to WGS 84 (15) (code 6971).",For military purposes. Accuracy 25m in each axis.,2402,-21.51,-17.5,-70.49,-68.18,1,0,9603,-270,183,-390,,,,,0
+374,1204,4248,4326,"Derived at 3 stations. Replaced by PSAD56 to WGS 84 (17) (code 6973).",For military purposes. Accuracy 20m in each axis.,2403,-45,-38.99,-75.22,-71.1,1,0,9603,-305,243,-442,,,,,0
+375,1205,4248,4326,"Derived at 4 stations. Note that although the PSAD56 network included Colombia the CRS is not used there: see Bogota 1975 (CRS code 4218).",For military purposes. Accuracy 15m in each axis.,3229,-4.23,12.52,-79.1,-66.87,1,0,9603,-282,169,-371,,,,,0
+376,1206,4248,4326,Derived at 11 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",3241,-5.01,1.45,-81.03,-75.21,1,0,9603,-278,171,-367,,,,,0
+377,1207,4248,4326,Derived at 9 stations.,"For military purposes. Accuracy 6m, 14m and 5m in X, Y and Z axes.",1114,1.18,10.7,-61.39,-55.77,1,0,9603,-298,159,-369,,,,,0
+378,1208,4248,4326,Derived at 6 stations.,"For military purposes only. Accuracy 6m, 8m and 12m in X, Y and Z axes.",1189,-21.05,-0.03,-84.68,-68.67,1,0,9603,-279,175,-379,,,,,0
+379,1209,4248,4326,Derived at 24 stations.,"For military purposes only. Accuracy 9m, 14m and 15m in X, Y and Z axes.",1251,0.64,16.75,-73.38,-58.95,1,0,9603,-295,173,-371,,,,,0
+380,1582,4248,4326,Derived May 1995 by Geoid for Total. OSU91A geoid model used.,Oil exploration.,2400,-14.43,-13.56,-68.96,-67.79,1,0,9603,-259.73,173.12,-398.27,,,,,0
+381,1583,4248,4326,Derived July 1997 by Geoid from data recorded by UGA for Total. OSU91A geoid model used.,Oil exploration.,2401,-21.71,-21.09,-63.44,-62.95,1,0,9603,-307.7,265.3,-363.5,,,,,0
+382,1811,4248,4326,Used by Petrobras for shelf operations.,Oil industry exploration.,1754,-1.05,5.6,-51.64,-48,1,0,9603,-291.87,106.37,-364.52,,,,,0
+383,3990,4248,4326,"Parameter values from PSAD56 to SIRGAS 1995 (1) (code 3971). Assumes SIRGAS 1995 and WGS 84 can be considered the same to within the accuracy of the transformation.","Suitable for mapping at 1:25,000 scale and smaller.",3241,-5.01,1.45,-81.03,-75.21,1,0,9607,-60.31,245.935,31.008,-12.324,-3.755,7.37,0.447,0
+384,6971,4248,4326,"Derived at 5 stations. Replaces PSAD56 to WGS 84 (3) (code 1203). Also used as a transformation from PSAD56 to SIRGAS-Chile - see code 6949.",For military purposes. Accuracy 10m in each axis.,4231,-26,-17.5,-70.79,-67,1,0,9603,-302,272,-360,,,,,0
+385,6972,4248,4326,Derived at 7 stations. Also used as a transformation from PSAD56 to SIRGAS-Chile - see code 6950.,For military purposes. Accuracy 10m in each axis.,4222,-36,-26,-72.87,-68.28,1,0,9603,-328,340,-329,,,,,0
+386,6973,4248,4326,"Derived at 6 stations. Replaces PSAD56 to WGS 84 (4) (code 1204). Info source gives S limit as 44°S but Chilean IGM states that PSAD56 limit is 43°30'S. Also used as a transformation from PSAD56 to SIRGAS-Chile - see code 6951.",For military purposes. Accuracy 10m in each axis.,4221,-43.5,-35.99,-74.48,-70.39,1,0,9603,-352,403,-287,,,,,0
+387,15967,4761,4326,"Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84. HTRS96 is a regional realisation of ETRS89.","Accuracy +/- 1 metre.",1076,41.62,46.54,13,19.43,1,0,9603,0,0,0,,,,,1
+388,1159,4250,4326,Derived at 8 stations.,"For military purposes. Accuracy 2m, 3m and 2m in X, Y and Z axes.",1104,1.4,11.16,-3.79,2.1,1,0,9603,-130,29,364,,,,,1
+389,1160,4251,4326,Derived at 4 stations.,For military purposes only. Accuracy 15m in each axis.,3270,4.29,8.52,-11.52,-7.36,1,0,9603,-90,40,88,,,,,1
+390,1887,4182,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,1344,39.3,39.77,-31.34,-31.02,1,0,9603,-425,-169,81,,,,,1
+391,1982,4182,4326,Derived at 2 stations in 1999.,For low resolution applications.,1344,39.3,39.77,-31.34,-31.02,1,0,9603,-422.651,-172.995,84.02,,,,,0
+392,1161,4253,4326,Derived at 6 stations.,"For military purposes. Accuracy 8m, 11m and 9m in X, Y and Z axes.",2364,7.75,19.45,116.89,125.88,1,0,9603,-133,-77,-51,,,,,1
+393,1162,4253,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2365,4.99,10.52,119.76,126.65,1,0,9603,-133,-79,-72,,,,,0
+394,1529,4254,4326,"Derived through ties at 3 stations (RC03, TOTAL11 and MP12) to 3 IGS stations in November 1995",Oil exploration.,2357,-55.11,-52.59,-68.64,-63.73,1,0,9606,18.38,192.45,96.82,0.056,-0.142,-0.2,-0.0013,0
+395,1892,4254,4326,Derived at 2 stations. As the source CRS was used for the border survey this transformation is probably also applicable to adjacent areas of Argentina.,Accuracy 25m in each axis.,2805,-55.96,-51.99,-74.83,-66.33,1,0,9603,16,196,93,,,,,1
+396,1246,4255,4326,Accuracy estimate not available.,For military purposes only.,1024,29.4,38.48,60.5,74.92,1,0,9603,-333,-222,114,,,,,1
+397,1164,4256,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2369,-4.86,-4.5,55.3,55.59,1,0,9603,41,-220,-134,,,,,1
+398,1549,4208,4326,,Oil exploration.,2307,-28.41,-17.59,-48.8,-35.18,1,1,9603,-158,315,-148,,,,,0
+399,1550,4208,4326,"Replaced by Aratu to WGS 84 (18) (tfm code 5061) which Petrobras now recommends for the area.",Oil exploration.,2308,-9.8,-8.39,-39.04,-37.09,1,0,9603,-139.62,290.53,-150.29,,,,,0
+400,1551,4208,4326,"Replaced by Aratu to WGS 84 (18) (tfm code 5061) which Petrobras now recommends for the area.",Oil exploration.,2309,-10.61,-9.79,-39.14,-37.99,1,0,9603,-141.15,293.44,-150.56,,,,,0
+401,1552,4208,4326,"Replaced by Aratu to WGS 84 (18) (tfm code 5061) which Petrobras now recommends for the area.",Oil exploration.,2310,-12.27,-10.6,-39.07,-37.98,1,0,9603,-142.48,296.03,-149.74,,,,,0
+402,10089,4208,4326,"Used by ExxonMobil for block BMS1. See WGS 84 (13) (tfm code 5051) which Petrobras now recommends for the area.",Oil exploration.,2962,-28.41,-22.66,-48.8,-40.2,1,0,9603,-163.466,317.396,-147.538,,,,,0
+403,10090,4208,4326,"Used by ExxonMobil for block BC10. Derived from earlier Shell position vector tfm of dX = -181m, dY = +294m, dZ = -144.5m, rX = rY = 0, rZ = +0.554s, dS = +0.219 ppm. See Aratu to WGS 84 (14) (tfm code 5053) which Petrobras now recommends for the area.",Oil exploration.,2963,-25.91,-20.45,-42.04,-37.11,1,0,9603,-170,305,-145,,,,,0
+404,10091,4208,4326,"Used by ExxonMobil for block BMES1. See Aratu to WGS 84 (15) (tfm code 5055) which Petrobras now recommends for the area.",Oil exploration.,2964,-22.04,-17.59,-40.37,-35.18,1,0,9603,-162.904,312.531,-137.109,,,,,0
+405,10092,4208,4326,"Used by ExxonMobil for block BP1. Also used by BG as part of a concatenated tfm to SAD69 for offshore regional studies. See WGS 84 (13) (tfm code 5051) for transformation Petrobras now recommends for the area.",Oil exploration.,2965,-35.71,-28.11,-53.38,-44.71,1,0,9603,-158,309,-151,,,,,0
+406,10093,4208,4326,"Used by ExxonMobil for offshore regional studies. See Aratu to WGS 84 (13) through (21) (tfm codes 5051-67 [odd numbers only]) which Petrobras now recommends for various areas.",Oil exploration.,2966,-34,-18,-53.38,-35.19,1,0,9603,-161,308,-142,,,,,0
+407,10094,4208,4326,Derived by IGN in 1992 at 7 stations within Nouakchott city.,Oil exploration.,2972,17.89,18.25,-16.11,-15.83,1,1,9603,124.5,-63.5,-281,,,,,0
+408,15710,4208,4326,"Replaced by Aratu to WGS 84 (14) (tfm code 5053) which Petrobras now recommends for the area.",Oil exploration.,2963,-25.91,-20.45,-42.04,-37.11,1,0,9603,-160,315,-142,,,,,0
+409,15711,4208,4326,"Replaced by Aratu to WGS 84 (13) (tfm code 5051) which Petrobras now recommends for the area.",Oil exploration.,2962,-28.41,-22.66,-48.8,-40.2,1,0,9603,-158,309,-147,,,,,0
+410,15712,4208,4326,"Replaced by Aratu to WGS 84 (15) (tfm code 5055) which Petrobras now recommends for the area.",Oil exploration.,2964,-22.04,-17.59,-40.37,-35.18,1,0,9603,-161,310,-145,,,,,0
+411,5051,4208,4326,"Parameters from Aratu to SIRGAS 2000 (1) (tfm code 5050) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area. Replaces tfm codes 15711 and 15734.",Oil exploration.,3700,-35.71,-22.66,-53.38,-40.2,1,0,9603,-157.84,308.54,-146.6,,,,,0
+412,5053,4208,4326,"Parameters from Aratu to SIRGAS 2000 (2) (tfm code 5052) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area. Replaces tfm codes 15710 and 15754.",Oil exploration.,2963,-25.91,-20.45,-42.04,-37.11,1,0,9603,-160.31,314.82,-142.25,,,,,0
+413,5055,4208,4326,"Parameters from Aratu to SIRGAS 2000 (3) (tfm code 5054) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area. Replaces tfms 15712 and 15754.",Oil exploration.,2964,-22.04,-17.59,-40.37,-35.18,1,0,9603,-161.11,310.25,-144.64,,,,,0
+414,5057,4208,4326,"Parameters from Aratu to SIRGAS 2000 (4) (tfm code 5056) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area.",Oil exploration.,3699,-17.7,-13.01,-39.22,-34.6,1,0,9603,-160.4,302.29,-144.19,,,,,0
+415,5059,4208,4326,"Parameters from Aratu to SIRGAS 2000 (5) (tfm code 5058) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area.",Oil exploration.,3692,-13.57,-11.18,-39.09,-35.31,1,0,9603,-153.54,302.33,-152.37,,,,,0
+416,5061,4208,4326,"Parameters from Aratu to SIRGAS 2000 (6) (tfm code 5060) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area. Replaces tfms 1550-1552.",Oil exploration.,3693,-12.27,-8.39,-39.14,-37.09,1,0,9603,-151.5,300.09,-151.15,,,,,0
+417,5063,4208,4326,"Parameters from Aratu to SIRGAS 2000 (7) (tfm code 5062) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area.",Oil exploration.,3696,-13.58,-8.73,-37.34,-32.01,1,0,9603,-156.8,298.41,-147.41,,,,,0
+418,5065,4208,4326,"Parameters from Aratu to SIRGAS 2000 (8) (tfm code 5064) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation.Petrobras preferred parameters for all purposes in the area.",Oil exploration.,3697,-10.17,-4.6,-35.1,-29.13,1,0,9603,-157.4,295.05,-150.19,,,,,0
+419,5067,4208,4326,"Parameters from Aratu to SIRGAS 2000 (9) (tfm code 5066) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area.",Oil exploration.,3698,-6.5,4.26,-44.79,-26,1,0,9603,-151.99,287.04,-147.45,,,,,1
+420,15754,4208,4326,"Mean for 3 basins. See Aratu to WGS 84 (10) through (12) (codes 15710-12) for transformations for individual basins. Replaced by Aratu to WGS 84 (13) through (15) (tfm codes 5051, 5053 and 5055) which Petrobras now recommends for the areas.",Oil exploration.,2307,-28.41,-17.59,-48.8,-35.18,1,0,9603,-158,315,-148,,,,,0
+421,1149,4258,4326,,ETRS89 and WGS 84 are realisations of ITRS coincident to within 1 metre. This transformation has an accuracy equal to the coincidence figure.,1298,32.88,84.17,-16.1,39.65,1,0,9603,0,0,0,,,,,1
+422,1571,4258,4326,"Dutch sources also quote an equivalent transformation with parameter values dX=+593.032 dY=+26.000 dZ=+478.741m, rX rY rZ and dS as this tfm. These values belong to a different transformation method and cannot be used with the Coordinate Frame method.",Accuracy 0.5m,1172,50.75,55.77,2.53,7.22,1,1,9607,565.04,49.91,465.84,0.409394,-0.359705,1.86849,4.0772,0
+423,1330,4259,4326,"Derived at Station Y in April 1989 using 572 transit satellite passes. Computed value for dZ was -96.42 but -96.38 has been utilised. Replaced Malongo 1987 to WGS 84 (3) (code 15791) in 1989. Replaced by Malongo 1987 to WGS 84 (2) (code 1557) in 1990.",Offshore oil exploration and production between April 1989 and June 1990.,3180,-6.04,-5.05,10.53,12.37,1,0,9603,-252.95,-4.11,-96.38,,,,,0
+424,1557,4259,4326,"Derived at station Y in July 1990 through Transit single point positioning using 187 passes by Geodetic Survey Ltd. Replaces Malongo 1987 to WGS 84 (1) (trf code 1330).",Offshore oil exploration and production from June 1990.,3180,-6.04,-5.05,10.53,12.37,1,0,9603,-254.1,-5.36,-100.29,,,,,1
+425,15791,4259,4326,"Derived via WGS 72BE by Geodetic for Chevron in 1987 by single point Transit translocation at 1 station (Malongo Y). Replaced in 1989 by Malongo 1987 to WGS 84 (1) (code 1330).",Oil industry exploration and production between September 1987 and April 1989.,3180,-6.04,-5.05,10.53,12.37,1,0,9603,-259.99,-5.28,-97.09,,,,,0
+426,1316,4260,4326,,"?",1060,1.65,13.09,8.32,16.21,1,1,9603,-70.9,-151.8,-41.4,,,,,0
+427,1166,4261,4326,Derived at 9 stations.,"For military purposes. Accuracy 5m, 3m and 3m in X, Y and Z axes.",3280,27.66,35.97,-13.24,-1.01,1,0,9603,31,146,47,,,,,1
+428,1165,4262,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1089,12.36,18.1,36.44,43.31,1,0,9603,639,405,60,,,,,1
+429,1067,4263,4326,"Used by Statoil for deep water blocks 210, 213, 217 and 218. Parameter values interpolated from Racal Survey geocentric translation contour charts for each of these four blocks and then meaned.",Oil industry exploration and production.,3817,3.24,5.54,4.41,6.29,1,0,9603,-92.1,-89.9,114.9,,,,,0
+430,1167,4263,4326,"Derived at 2 stations. Note: Minna is used in Nigeria, not Cameroon.",For military purposes only. Accuracy 25m in each axis.,3226,1.65,13.09,8.45,16.21,1,0,9603,-81,-84,115,,,,,0
+431,1168,4263,4326,Derived at 6 stations.,"For military purposes. Accuracy 3m, 6m and 5m in X, Y and Z axes.",1178,1.92,13.9,2.66,14.65,1,0,9603,-92,-93,122,,,,,1
+432,1534,4263,4326,,Oil exploration.,2371,4.22,6.95,4.35,9.45,1,1,9606,-111.92,-87.85,114.5,1.875,0.202,0.219,0.032,0
+433,1754,4263,4326,"Derived at 8 stations across the Niger delta. Used by Shell SPDC throughout southern Nigeria onshore, delta and shallow offshore from 1994 and by Total in OPL246. Sometimes given with parameter values to greater resolution; values here are adequate.",Oil exploration.,2371,4.22,6.95,4.35,9.45,1,0,9606,-111.92,-87.85,114.5,1.875,0.202,0.219,0.032,0
+434,1818,4263,4326,Concatenated via WGS 72BE.,Oil industry operations.,1717,1.92,6.14,2.66,7.82,1,0,9606,-89,-112,125.9,0,0,0.814,-0.38,0
+435,1819,4263,4326,Used by Shell in southern Nigeria and Total in OPL246.,Oil industry operations.,2371,4.22,6.95,4.35,9.45,1,1,9606,-111.92,-87.85,114.5,1.875,0.202,0.219,0.032,0
+436,1820,4263,4326,Derived by Nortech at station L40 Minna using NNPC 1989 GPS network tied to 4 ADOS stations. Used by Conoco in OPLs 219-220 to cm precision and ExxonMobil in OPL 209 to dm precision..,Oil industry operations.,3813,3.25,5.54,4.01,6.96,1,0,9603,-93.2,-93.31,121.156,,,,,0
+437,1821,4263,4326,"Derived by Elf Petroleum Nigeria in 1994 at 3 stations (M101 onshore, offshore platforms XSW06 and XSV39) and used in OMLs 99-102 and OPLs 222-223.",Oil industry operations.,3814,3.25,4.51,7.16,8.25,1,0,9603,-88.98,-83.23,113.55,,,,,0
+438,1822,4263,4326,"Used by Shell SNEPCO for OPLs 209-213 and 316. Derived during 1990 Niger Delta control survey at 4 stations (XSU27, 30 31 and 35).",Oil industry exploration and production.,3815,4.22,6.31,3.83,5.17,1,0,9603,-92.726,-90.304,115.735,,,,,0
+439,1823,4263,4326,"Used by Shell SNEPCO for OPLs 217-223. Derived during 1990 Niger Delta control survey at 4 stations (XSU38, 41, 44 and 45).",Oil industry exploration and production.,3816,3.24,3.86,5.58,8,1,0,9603,-93.134,-86.647,114.196,,,,,0
+440,1824,4263,4326,Used by Shell SNEPCO for Gongola basin.,Oil industry exploration and production.,3824,8.78,11.63,9.41,12.13,1,0,9603,-93,-94,124,,,,,0
+441,15706,4263,4326,Used by Elf in Blocks OPL 222 and OPL 223 and by Mobil in 1994.,Oil industry exploration.,1717,1.92,6.14,2.66,7.82,1,0,9603,-93.6,-83.7,113.8,,,,,0
+442,15705,4263,4326,"Derived via WGS 72(BE). Minna to WGS 72(BE) transformation derived in 1981 for Mobil E&P Nigeria (MEPCON) by Geodetic Survey through Transit translocation at six stations in southern Nigeria. Used by MEPCON in blocks OPL 215 and 221.",Oil industry exploration.,3819,3.25,4.23,5.02,7.31,1,0,9606,-83.13,-104.95,114.63,0,0,0.554,0,0
+443,6196,4263,4326,Used by Addax for OPL 118 and OML 124. Derived in 1999 at 4 stations during  extension into OPL 118 of control in Chevron block OML 53.,Oil industry exploration and production.,4127,5.56,5.74,6.72,6.97,1,0,9603,-93.179,-87.124,114.338,,,,,0
+444,15493,4263,4326,"Adopted by MPN for all joint venture operations from 1/1/1996.",Oil industry exploration and production.,3590,3.99,5.01,5.99,8.01,1,0,9603,-94.031,-83.317,116.708,,,,,0
+445,15755,4263,4326,Derived in 1995 at unspecified DMA ADOS stations and Racal stations M101 and ZVS3003. Used by Elf in onshore Block OML 58.,Oil industry exploration and production. Accuracy 0.5m.,3113,5.05,5.36,6.53,6.84,1,0,9603,-90.2,-87.32,114.17,,,,,0
+446,1329,4264,4326,"Superseded in 1990 by trf Malongo 1987 to WGS 84 (2), code 1557. Malongo 1987 is an offshore extension of the Mhast cooordinate system.","Used for oil exploration by Chevron until superseded in 1990 by trf Malongo 1987 to WGS 84 (2), code 1557.",1317,-6.04,-5.05,10.53,12.18,1,1,9603,-252.95,-4.11,-96.38,,,,,0
+447,1088,4265,4326,,Oil exploration and production,2882,43.62,45.73,12.22,13.96,1,0,9603,-223.7,-67.38,1.34,,,,,0
+448,1089,4265,4326,,Oil exploration and production,2883,41.95,44.04,13.61,16.14,1,0,9603,-225.4,-67.7,7.85,,,,,0
+449,1090,4265,4326,,Oil exploration and production,2884,40.72,42.28,15.95,18.63,1,0,9603,-227.1,-68.1,14.4,,,,,0
+450,1091,4265,4326,,Marine navigation,2885,39.77,41.03,17.95,18.99,1,0,9603,-231.61,-68.21,13.93,,,,,0
+451,1092,4265,4326,,Marine navigation,2886,37.67,40.47,16.55,18.93,1,0,9603,-225.06,-67.37,14.61,,,,,0
+452,1093,4265,4326,,Marine navigation,2887,35.22,37.48,13,15.16,1,0,9603,-229.08,-65.73,20.21,,,,,0
+453,1094,4265,4326,,Marine navigation,2888,35.28,38.45,10.68,13.01,1,0,9603,-230.47,-56.08,22.43,,,,,0
+454,1169,4265,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2339,38.82,41.31,8.08,9.89,1,0,9603,-225,-65,9,,,,,0
+455,1660,4265,4326,"Parameter values from Monte Mario to ETRS89 (1) (code 1659). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.","Accuracy: 4 metres",2372,37.86,47.1,6.62,18.58,1,0,9606,-104.1,-49.1,-9.9,0.971,-2.917,0.714,-11.68,1
+456,1662,4265,4326,"Parameter values from Monte Mario to ETRS89 (2) (code 1661). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.","Accuracy: 4 metres",2339,38.82,41.31,8.08,9.89,1,0,9606,-168.6,-34,38.6,-0.374,-0.679,-1.379,-9.48,0
+457,1664,4265,4326,"Parameter values from Monte Mario to ETRS89 (3) (code 1663). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.","Accuracy: 4 metres",2340,36.59,38.35,12.36,15.71,1,0,9606,-50.2,-50.4,84.8,-0.69,-2.012,0.459,-28.08,0
+458,1163,4266,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1100,-6.37,2.32,7.03,14.52,1,0,9603,-74,-130,42,,,,,1
+459,1532,4266,4326,Derived as mean of Doris determinations at 3 stations in Port Gentil area in 1994.,Oil exploration.,1100,-6.37,2.32,7.03,14.52,1,0,9603,-80.7,-132.5,41.1,,,,,0
+460,1170,4267,4326,Derived at 15 stations.,"For military purposes. Accuracy 3m, 9m and 12m in X, Y and Z axes.",2418,13,23.25,-85.01,-59.37,1,0,9603,-3,142,183,,,,,0
+461,1171,4267,4326,Derived at 19 stations.,"For military purposes only. Accuracy 8m, 3m and 5m in X, Y and Z axes.",2419,7.98,18.49,-92.29,-82.53,1,0,9603,0,125,194,,,,,0
+462,1172,4267,4326,Derived at 112 stations.,"For military purposes only. Accuracy 15m, 11m and 6m in X, Y and Z axes.",1061,40.04,86.46,-141.01,-47.74,1,0,9603,-10,158,187,,,,,1
+463,1173,4267,4326,Derived at 405 stations.,"For military purposes only. Accuracy 5m, 5m and 6m in X, Y and Z axes.",1323,24.41,49.38,-124.79,-66.91,1,0,9603,-8,160,176,,,,,0
+464,1174,4267,4326,Derived at 129 stations.,"For military purposes only. Accuracy 5m, 5m and 8m in X, Y and Z axes.",2389,24.41,49.38,-97.22,-66.91,1,0,9603,-9,161,179,,,,,0
+465,1175,4267,4326,Derived at 276 stations.,"For military purposes only. Accuracy 5m, 3m and 3m in X, Y and Z axes.",2390,25.83,49.05,-124.79,-89.64,1,0,9603,-8,159,175,,,,,0
+466,1176,4267,4326,Derived at 47 stations.,"For military purposes only. Accuracy 5m, 9m and 5m in X, Y and Z axes.",2412,54.34,71.4,-168.26,-129.99,1,0,9603,-5,135,172,,,,,0
+467,1177,4267,4326,Derived at 11 stations.,"For military purposes. Accuracy 5m, 3m and 5m in X, Y and Z axes.",2413,20.86,27.29,-79.04,-72.68,1,0,9603,-4,154,178,,,,,0
+468,1178,4267,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2414,23.9,24.19,-74.6,-74.37,1,0,9603,1,140,165,,,,,0
+469,1179,4267,4326,Derived at 25 stations.,"For military purposes only. Accuracy 8m, 8m and 6m in X, Y and Z axes.",2384,48.25,60.01,-139.04,-109.98,1,0,9603,-7,162,188,,,,,0
+470,1180,4267,4326,Derived at 25 stations.,"For military purposes only. Accuracy 9m, 5m and 5m in X, Y and Z axes.",2415,41.67,60.01,-102,-74.35,1,0,9603,-9,157,184,,,,,0
+471,1181,4267,4326,Derived at 37 stations.,"For military purposes only. Accuracy 6m, 6m and 3m in X, Y and Z axes.",2416,43.41,62.62,-79.85,-52.54,1,0,9603,-22,160,190,,,,,0
+472,1182,4267,4326,Derived at 17 stations.,"For military purposes only. Accuracy 5m, 5m and 3m in X, Y and Z axes.",2410,49,83.17,-136.46,-60.72,1,0,9603,4,159,188,,,,,0
+473,1183,4267,4326,Derived at 8 stations.,"For military purposes only. Accuracy 5m, 8m and 3m in X, Y and Z axes.",2417,59.99,69.7,-141.01,-123.91,1,0,9603,-7,139,181,,,,,0
+474,1184,4267,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,2385,8.82,9.45,-80.07,-79.46,1,0,9603,0,125,201,,,,,0
+475,1185,4267,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,3235,19.77,23.25,-85.01,-74.07,1,0,9603,-9,152,178,,,,,0
+476,1186,4267,4326,"Derived at 2 stations. Note: NAD27 is not used in Greenland.",For military purposes. Accuracy 25m in each axis.,2386,75.86,79.2,-73.29,-60.98,1,0,9603,11,114,195,,,,,0
+477,1187,4267,4326,Derived at 22 stations.,"For military purposes only. Accuracy 8m, 6m and 6m in X, Y and Z axes.",3278,14.51,32.72,-118.47,-86.68,1,0,9603,-12,130,190,,,,,0
+478,1249,4267,4326,Derived at 6 stations.,"For military purposes only. Accuracy 6m, 8m and 10m in X, Y and Z axes.",2387,51.54,54.34,-178.3,-164.84,1,0,9603,-2,152,149,,,,,0
+479,1250,4267,4326,Derived at 5 stations.,For military purposes. Accuracy 10m in each axis.,2388,51.3,53.07,172.42,179.86,1,0,9603,2,204,105,,,,,0
+480,1530,4267,4326,,Accuracy 3m.,1077,18.83,25.51,-87.01,-73.57,1,0,9603,-4.2,135.4,181.9,,,,,0
+481,15699,4267,4326,"Developed by John E Chance and Associates at 19°44'N, 92°21'W. Geoid height used =-13.34m.","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3462,17.85,20.89,-94.79,-89.75,1,0,9603,-2,124.7,196,,,,,0
+482,15852,4267,4326,"Developed by John E Chance and Associates. Replaced by NAD27 to WGS 84 (79) (tfm code 15851).","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3358,23.82,30.25,-87.25,-81.17,1,0,9603,-3,154,177,,,,,0
+483,15853,4267,4326,"Developed by John E Chance and Associates. Replaced by NAD27 to WGS 84 (79) (tfm code 15851).","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3359,25.61,30.23,-95,-87.25,1,0,9603,-7,151,175,,,,,0
+484,15854,4267,4326,"Developed by John E Chance and Associates. Replaced by NAD27 to WGS 84 (79) (tfm code 15851).","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3360,25.97,28.97,-97.22,-95,1,0,9603,-7,151,178,,,,,0
+485,15855,4267,4326,"Developed by John E Chance and Associates at 21°55'N, 97°20'W. Geoid height used =-17m.","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3361,21.51,22.75,-98.1,-96.89,1,0,9603,-8,125,190,,,,,0
+486,15856,4267,4326,"Developed by EnSoCo Inc. Replaced by NAD27 to WGS 84 (79) (tfm code 15851).",Oil exploration and production. Accuracy 8 metres.,3357,23.82,30.25,-97.22,-81.17,1,0,9603,-7,158,172,,,,,0
+487,15913,4267,4326,"Developed by John E Chance and Associates at 21°33'N, 92°33'W. Geoid height used =-16.7m.","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3461,20.87,23.01,-94.33,-88.67,1,0,9603,0,125,196,,,,,0
+488,15978,4267,4326,,Accuracy 1m.,1077,18.83,25.51,-87.01,-73.57,1,0,9607,2.478,149.752,197.726,-0.526,-0.498,0.501,0.685,0
+489,1188,4269,4326,Derived at 354 stations.,Accuracy 2m in each axis.,1325,23.81,86.46,-172.54,-47.74,1,0,9603,0,0,0,,,,,1
+490,1251,4269,4326,Derived at 4 stations.,"For military purposes only. Accuracy 5m, 2m and 5m in X, Y and Z axes.",2157,51.3,54.34,172.42,-164.84,1,0,9603,-2,0,4,,,,,0
+491,1252,4269,4326,Derived at 6 stations.,For military purposes only. Accuracy 2m in each axis.,3883,15.56,25.58,-163.74,-151.27,1,0,9603,1,1,-1,,,,,0
+492,1308,4269,4326,"Strictly between NAD83 and ITRF94(1996.0). Superseded by NAD83 to WGS 84 (5) (code 1515).",Historical record only - superseded - see remarks.,1323,24.41,49.38,-124.79,-66.91,1,1,9607,-0.9738,1.9453,0.5486,-0.0275508,-0.010049,-0.011359,0,0
+493,1515,4269,4326,"Strictly between NAD83 and ITRF96(1997.0). Supersedes NAD83 to WGS 84 (4) (code 1308).",Geodesy.,1323,24.41,49.38,-124.79,-66.91,1,1,9607,-0.991,1.9072,0.5129,-0.02578991,-0.00965010,-0.0116599,0,0
+494,1189,4270,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,2391,20.12,20.74,58.58,59.01,1,0,9603,-247,-148,369,,,,,0
+495,1190,4270,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,3968,24.63,28.57,47.95,50.81,1,0,9603,-243,-192,477,,,,,0
+496,1191,4270,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,1243,22.63,26.27,51.5,57.13,1,0,9603,-249,-156,381,,,,,1
+497,1531,4270,4326,Parameter values adopted by Total are mean of those derived by Oceonics and Geoid through ties at platform AK1 to 4 IGS stations in March 1995.,Oil exploration.,2392,25.33,25.54,53.03,53.4,1,0,9603,-245,-153.9,382.8,,,,,0
+498,1536,4270,4326,"Derived by Brown & Root in 1992 for Qatar General Petroleum Corporation North Field development. Adopted by QGPC for all offshore Qatar.",Oil exploration.,2406,24.64,27.05,50.55,53.04,1,0,9603,-250.2,-153.09,391.7,,,,,0
+499,15871,4270,4326,Derived by concatenation of parameter values published by IGN Paris from Nahrwan 1967 to WGS 72 at the Nahrwan SE Base trig station near Baghdad with DMA WGS 72 to WGS 84 parameter values.,Oil exploration.,3625,29.06,37.39,38.79,48.61,1,1,9603,-242.2,-144.9,370.3,,,,,0
+500,6998,4270,4326,Derived via WGS 72 but provenance uncertain. In ADMA replaces tfm code 15938. In ADCO replaced by tfm code 6999 from October 2013.,Oil exploration and production.,4226,22.63,25.64,51.5,56.03,1,0,9607,-233.4,-160.7,381.5,0,0,-0.554,0.2263,0
+501,6999,4270,4326,"Derived in October 2013 at four control points of the ADCO CRF and evaluated at four others. Estimated horizontal accuracy of 0.14 m at the 95% confidence level.","Oil exploration and production horizontal coordinate transformation. Although a 3D transformation, should not be used for vertical dimension.",4225,22.63,24.95,51.56,56.03,1,0,9607,-253.4392,-148.452,386.5267,-0.15605,-0.43,0.1013,-0.0424,0
+502,7002,4270,4326,,Abu Dhabi Municipality GIS.,4229,24.24,24.64,54.2,54.71,1,0,9607,-246.1633,-152.9047,382.6047,-0.0989,-0.1382,-0.0768,2.1e-06,0
+503,7003,4270,4326,,Abu Dhabi Municipality GIS.,1850,22.76,24.32,51.56,54.01,1,0,9607,-242.8907,-149.0671,384.416,-0.19044,-0.24987,-0.13925,0.0001746,0
+504,7004,4270,4326,,Abu Dhabi Municipality GIS.,4227,22.63,24.95,53.99,56.03,1,0,9607,-246.734,-153.4345,382.1477,0.116617,0.165167,0.091327,1.94e-05,0
+505,15937,4270,4326,Parameter values adopted by Total are mean of those derived by Oceonics and Geoid through ties at station TC58 to 4 IGS stations in March 1995.,Oil exploration.,3509,24,25.64,51.5,54.85,1,0,9603,-245.8,-152.2,382.9,,,,,0
+506,15938,4270,4326,Derived via WGS 72BE from Transit observations at station TC58 in 1976 by BP for ADMA.,Oil exploration.,3509,24,25.64,51.5,54.85,1,0,9606,-225.4,-158.7,380.8,0,0,0.814,-0.38,0
+507,15952,4270,4326,"Used by DPC for Al Fateh field. Applying this transformation gives same result as Nahrwan 1967 to WGS 84 (8) (code 15938).",Oil exploration and production.,3530,24.94,25.8,54.06,55.3,1,0,9603,-244.2,-149.8,379.3,,,,,0
+508,15953,4270,4326,Used by Dubai Municipality before 1994.,Municipal operations.,3531,24.85,25.34,54.84,55.55,1,0,9603,-250.7,-157.9,380.4,,,,,0
+509,1192,4271,4326,"CAUTION: OGP believes that these parameter values include a blunder and that if NIMA transformation parameters are to be used the 1987 version (EPSG code 1307) be used.",For military purposes only. Accuracy given by NIMA 15m in each axis. EPSG believes there is an 8-10m blunder in dX.,1322,11.09,11.4,-60.9,-60.47,1,0,9603,-10,375,165,,,,,1
+510,1307,4271,4326,"(1) See remarks for tfm code 1192. (2) Naparima 1972 is an extension to Tobago of the Napaima 1955 geographic CRS of Trindad. In Trinidad this transformation may also be considered to use Napaima 1955 (code 4158) as its source CRS: see tfm code 1556.",For military purposes only. Accuracy 15m in each axis.,1322,11.09,11.4,-60.9,-60.47,1,0,9603,-2,374,172,,,,,0
+511,1151,4272,4326,Derived at 14 stations.,"For military purposes only. Accuracy 5m, 3m and 5m in X, Y and Z axes.",3285,-47.65,-33.89,165.87,179.27,1,0,9603,84,-22,209,,,,,0
+512,1564,4272,4326,"These parameter values are taken from NZGD49 to NZGD2000 (2) (code 1701) and assume that NZGD2000 and WGS 84 are coincident to within the accuracy of the transformation. For improved accuracy use NZGD49 to WGS 84 (4) (code 1670).",Transformation accuracy about 4 metres.,3285,-47.65,-33.89,165.87,179.27,1,0,9607,59.47,-5.04,187.44,-0.47,0.1,-1.024,-4.5993,1
+513,15975,4272,4326,"These parameter values are taken from NZGD49 to NZGD2000 (1) (code 1566) and assume that NZGD2000 and WGS 84 are coincident to within the accuracy of the tfm. For better accuracy use NZGD49 to WGS 84 (2) (code 1564) or NZGD49 to WGS 84 (3) (code 1670).",5m accuracy.,3285,-47.65,-33.89,165.87,179.27,1,0,9603,54.4,-20.1,183.1,,,,,0
+514,1654,4273,4326,"Parameter values from NGO 1948 to ETRS89 (1) (code 1653). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 3 metres.,1352,57.93,71.21,4.68,31.22,1,0,9606,278.3,93,474.5,7.889,0.05,-6.61,6.21,1
+515,1658,4274,4326,"Parameter values from Datum 73 to ETRS89 (1) (code 1657). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaced by Datum 73 to WGS 84 (4) (tfm code 1987).",For applications to an accuracy of 2 metres.,1294,36.95,42.16,-9.56,-6.19,1,0,9606,-238.2,85.2,29.9,0.166,0.046,1.248,2.03,0
+516,1945,4274,4326,"Parameter values from Datum 73 to ETRS89 (2) (code 1792). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1294,36.95,42.16,-9.56,-6.19,1,1,9606,-231,102.6,29.8,0.615,-0.198,0.881,1.79,0
+517,1983,4274,4326,,For low resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9603,-223.237,110.193,36.649,,,,,1
+518,1987,4274,4326,,For medium resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9607,-239.749,88.181,30.488,-0.263,-0.082,-1.211,2.229,0
+519,1193,4275,4326,"These same parameter values are used to transform to ETRS89. See NTF to ETRS89 (1) (code 1651).",For applications to an accuracy of 2 metres.,3694,41.31,51.14,-4.87,9.63,1,0,9603,-168,-60,320,,,,,1
+520,1195,4277,4326,Derived at 38 stations.,"For military purposes only. Accuracy 10m, 10m and 15m in X, Y and Z axes.",1264,49.81,60.9,-8.74,1.84,1,0,9603,375,-111,431,,,,,0
+521,1196,4277,4326,Derived at 24 stations.,"For military purposes only. Accuracy 5m, 5m and 6m in X, Y and Z axes.",2395,49.81,55.85,-6.5,1.84,1,0,9603,371,-112,434,,,,,0
+522,1197,4277,4326,Derived at 25 stations.,"For military purposes only. Accuracy 10m, 10m and 15m in X, Y and Z axes.",2396,49.81,55.85,-6.5,1.84,1,0,9603,371,-111,434,,,,,0
+523,1198,4277,4326,Derived at 13 stations.,For military purposes only. Accuracy 10m in each axis.,2397,54.57,60.9,-8.74,-0.65,1,0,9603,384,-111,425,,,,,0
+524,1199,4277,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,2398,51.28,53.48,-5.34,-2.65,1,0,9603,370,-108,434,,,,,0
+525,1314,4277,4326,"For a more accurate transformation see OSGB 1936 / British National Grid to ETRS89 (2) (code 1039): contact the Ordnance Survey of Great Britain (http://www.gps.gov.uk/gpssurveying.asp) for details.",Oil exploration. Accuracy better than 4m and generally better than 2m.,1264,49.81,60.9,-8.74,1.84,1,0,9606,446.448,-125.157,542.06,0.15,0.247,0.842,-20.489,1
+526,5622,4277,4326,Derived by CGG for 1994 3D seismic survey.,Oil exploration and production.,3893,50.53,50.8,-2.2,-1.68,1,0,9603,370.396,-108.938,435.682,,,,,0
+527,4560,4558,4326,"Approximation at the +/- 1m level assuming that RRAF91 is equivalent to WGS 84 within the accuracy of the transformation.","Accuracy +/- 1 metre.",2824,14.08,18.54,-63.66,-57.52,1,0,9603,0,0,0,,,,,1
+528,1074,4281,4326,"Not recognised by Survey of Israel. See Palestine 1923 to WGS 84 (2) (code 8650).","Oil Exploration. Accuracy: 1m to north and 5m to south of east-west line through Beersheba (31°15'N).",2603,29.45,33.28,34.17,35.69,1,0,9606,-275.7224,94.7824,340.8944,-8.001,-4.42,-11.821,1,1
+529,1200,4282,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1072,-6.91,3.72,8.84,18.65,1,0,9603,-148,51,-291,,,,,1
+530,1801,4282,4326,"Derived in 1994 by CGG/Topnav using DORIS system on various stations along the coastline.","?",2574,-6.91,-3.55,8.84,12.34,1,0,9603,-145,52.7,-291.6,,,,,0
+531,1802,4282,4326,Derived by Geoid for Elf in May 1995 using GPS and IGS data by tying 4 geodetic points to ITRF93 epoch 1995.4.,Used by Elf since May 1995 for all offshore Congo operations.,2574,-6.91,-3.55,8.84,12.34,1,0,9606,-178.3,-316.7,-131.5,5.278,6.077,10.979,19.166,0
+532,1150,4283,4326,,GDA94 is a realisation of WGS 84 coincident to within 1 metre. This transformation has an accuracy equal to the coincidence figure.,2575,-43.7,-9.86,112.85,153.69,1,0,9603,0,0,0,,,,,1
+533,1254,4284,4326,Accuracy estimate not available.,For military purposes.,1198,39.87,85.2,18.92,-168.97,1,0,9603,28,-130,-95,,,,,0
+534,1267,4284,4326,"Derived through concatenation of Pulkovo 1942 to PZ-90 (1) (tfm code 15844) and PZ-90 to WGS 84 (2) (tfm code 1244. Mandated for use in Russia by GOST R 51794-2001, but this has been superseded by GOST R 51794-2008. Replaced by tfm code 5044.",Accuracy 4 metres.,1198,39.87,85.2,18.92,-168.97,1,0,9607,23.92,-141.27,-80.9,0,-0.35,-0.82,-0.12,1
+535,1287,4284,4326,Derived at 5 stations.,For military purposes. Accuracy 2m in each axis.,1119,45.74,48.58,16.11,22.9,1,1,9603,28,-121,-77,,,,,0
+536,1288,4284,4326,Derived at 11 stations.,"For military purposes only. Accuracy 4m, 2m and 4m in X, Y and Z axes.",1192,49,55.93,14.14,24.15,1,1,9603,23,-124,-82,,,,,0
+537,1289,4284,4326,Derived at 6 stations.,"For military purposes only. Accuracy 3m, 3m and 2m in X, Y and Z axes.",1306,47.73,51.06,12.09,22.56,1,1,9603,26,-121,-78,,,,,0
+538,1290,4284,4326,Derived at 5 stations.,For military purposes. Accuracy 2m in each axis.,1139,55.67,58.09,19.06,28.24,1,0,9603,24,-124,-82,,,,,0
+539,1291,4284,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,1131,40.59,55.45,46.49,87.35,1,0,9603,15,-130,-84,,,,,0
+540,1292,4284,4326,Derived at 7 stations.,For military purposes. Accuracy 3m in each axis.,1025,39.63,42.67,18.46,21.06,1,1,9603,24,-130,-92,,,,,0
+541,1293,4284,4326,Derived at 4 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",1197,43.44,48.27,20.26,31.41,1,1,9603,28,-121,-77,,,,,0
+542,1303,4284,4326,Mean of 13 stations along entire Kazak coastline.,Residuals under 2 m.,2405,41.15,46.97,48.9,53.15,1,0,9606,43.822,-108.842,-119.585,1.455,-0.761,0.737,0.549,0
+543,1334,4284,4326,,"?",3246,57.52,59.75,21.74,28.2,1,0,9607,21.58719,-97.54127,-60.92546,-1.01378,-0.58117,-0.2348,-4.6121,0
+544,1679,4284,4326,"Parameter values taken from Pulkovo 1942 to LKS94(ETRS89) (1) (code 1274) assuming that LKS94(ETRS89) is equivalent to WGS 84 within the accuracy of the transformation.","Approximation at the +/- 9m level.",1145,53.89,56.45,19.02,26.82,1,0,9607,-40.595,-18.55,-69.339,-2.508,-1.832,2.611,-4.299,0
+545,1807,4284,4326,"Derived via WGS72 values taken from SOCAR Magnavox 1502 manual. Used by AIOC 1995-1997 then replaced by the AIOC97 values (tfm code 1808).
 Do not confuse with AIOC95 vertical datum as used in southern Caspian Sea and at Sangachal terminal by AIOC.",Oil industry operations by AIOC prior to 1997.,1038,37.89,42.59,44.77,51.73,1,0,9606,27,-135,-84.5,0,0,0.554,0.2263,0
-524,1808,4284,4326,"Mean of 3 stations in western Georgia, 4 stations in eastern Georgia and 4 stations in eastern Azerbaijan. Derived for use on AIOC early oil western export pipeline, but adopted for all AIOC work replacing the 1995 AIOC transformation (code 1807).",Oil industry operations.,2593,37.89,43.59,39.99,51.73,1,0,9606,686.1,-123.5,-574.4,8.045,-23.366,10.791,-2.926,0
-525,1809,4284,4326,Parameter values calculated by Elf Exploration and Production based on geodetic survey carried out by Azerbaijan State Committee for Geodesy and Cartography.,Oil industry operations.,2594,38.31,40.33,48.93,50.4,1,0,9606,926.4,-715.9,-186.4,-10.364,-20.78,26.452,-7.224,0
-526,5044,4284,4326,"Derived through concatenation of Pulkovo 1942 to PZ-90.02 to WGS 84. Replaces Pulkovo 1942 to WGS 84 (17) (code 1267).",Accuracy 3 metres.,1198,39.87,85.2,18.92,-168.97,1,0,9607,23.57,-140.95,-79.8,0,-0.35,-0.79,-0.22,0
-527,15865,4284,4326,"Derived via PZ-90 at 30 stations throughout USSR (Former Soviet Union, FSU) through concatenation of Pulkovo 1942 to PZ-90 (1) (tfm code 15844) and PZ-90 to WGS 84 (1) (tfm code 15843).",Accuracy 4.5 metres.,2423,35.14,81.91,19.57,-168.97,1,0,9607,25,-141,-78.5,0,-0.35,-0.736,0,0
-528,1561,4285,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,1346,24.55,26.2,50.69,51.68,1,0,9603,-128,-283,22,,,,,0
-529,1562,4285,4326,"Derived by Brown & Root in 1992 for Qatar General Petroleum Corporation.",Oil exploration.,2406,24.64,27.05,50.55,53.04,1,0,9603,-128.16,-282.42,21.93,,,,,1
-530,1563,4285,4326,"Derived by Qatar Centre for GIS. See Qatar 1974 to WGS 84 (2) (code 1562) for transformation used by QGPC for offshore petroleum industry.",Oil exploration.,1346,24.55,26.2,50.69,51.68,1,0,9603,-128.033,-283.697,21.052,,,,,0
-531,1211,4287,4326,Derived at 2 stations.,"For military purposes. Accuracy 25m, 25m and 32m in X, Y and Z axes.",2407,59.75,72,-55,-40,1,1,9603,164,138,-189,,,,,0
-532,1112,4289,4326,"Replaced by Amersfoort to WGS 84 (2) (code 1672).","?",1275,50.75,53.7,3.2,7.22,1,0,9606,593.16,26.15,478.54,-1.30439800822601,-0.103297414968546,-1.14450153042326,4.0775,0
-533,1672,4289,4326,"Parameter values from Amersfoort to ETRS89 (1) (code 1751) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaces Amersfoort to WGS 84 (1) (code 1112). Replaced by Amersfoort to WGS 84 (3) (code 15934).","Approximation at the +/- 1m level.",1275,50.75,53.7,3.2,7.22,1,0,9607,565.04,49.91,465.84,0.409394387439237,-0.359705195614311,1.86849100035057,4.0772,0
-534,4833,4289,4326,"Parameter values from Amersfoort to ETRS89 (5) (tfm code 4830) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaces Amersfoort to WGS 84 (3) (code 15934).","Approximation at the +/- 1m level.",1275,50.75,53.7,3.2,7.22,1,0,9607,565.4171,50.3319,465.5524,0.398957388243134,-0.343987817378283,1.87740163998045,4.0725,1
-535,15934,4289,4326,"Parameter values from Amersfoort to ETRS89 (3) (tfm code 15739) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaces Amersfoort to WGS 84 (2) (code 1672). Replaced by Amersfoort to WGS 84 (4) (tfm code 4833).","Approximation at the +/- 1m level.",1275,50.75,53.7,3.2,7.22,1,0,9607,565.2369,50.0087,465.658,0.406857330322398,-0.350732676542563,1.8703473836068,4.0812,0
-536,1212,4291,4326,Derived at 84 stations.,"For military purposes only. Accuracy 15m, 6m and 9m in X, Y and Z axes.",1341,-56.15,13,-82,-34,1,1,9603,-57,1,-41,,,,,0
-537,1213,4291,4326,Derived at 10 stations.,For military purposes only. Accuracy 5m in each axis.,1033,-58.41,-21.78,-73.59,-52.63,1,1,9603,-62,-1,-37,,,,,0
-538,1214,4291,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,1049,-22.91,-9.67,-69.66,-57.52,1,1,9603,-61,2,-48,,,,,0
-539,1215,4291,4326,Derived at 22 stations.,"For military purposes only. Accuracy 3m, 5m and 5m in X, Y and Z axes.",1053,-35.71,7.04,-74.01,-25.28,1,1,9603,-60,-2,-41,,,,,0
-540,1216,4291,4326,Derived at 9 stations.,"For military purposes only. Accuracy 15m, 8m and 11m in X, Y and Z axes.",1066,-59.87,-17.5,-113.21,-65.72,1,1,9603,-75,-1,-44,,,,,0
-541,1217,4291,4326,Derived at 7 stations.,"For military purposes only. Accuracy 6m, 6m and 5m in X, Y and Z axes.",1070,-4.23,15.51,-84.77,-66.87,1,1,9603,-44,6,-36,,,,,0
-542,1218,4291,4326,Derived at 11 stations.,For military purposes. Accuracy 3m in each axis.,1085,-5.01,5,-95.35,-75.21,1,1,9603,-48,3,-44,,,,,0
-543,1219,4291,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2356,-1.41,0.18,-91.72,-89.19,1,1,9603,-47,26,-42,,,,,0
-544,1220,4291,4326,Derived at 5 stations.,"For military purposes only. Accuracy 9m, 5m and 5m in X, Y and Z axes.",1114,1.18,10.7,-61.39,-55.77,1,1,9603,-53,3,-47,,,,,0
-545,1221,4291,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,1188,-27.59,-19.29,-62.65,-54.24,1,1,9603,-61,2,-33,,,,,0
-546,1222,4291,4326,Derived at 6 stations.,For military purposes. Accuracy 5m in each axis.,1189,-21.05,-0.03,-84.68,-68.67,1,1,9603,-58,0,-44,,,,,0
-547,1223,4291,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1235,9.83,12.34,-62.09,-57.28,1,1,9603,-45,12,-33,,,,,0
-548,1224,4291,4326,Derived at 5 stations.,"For military purposes only. Accuracy 3m, 6m and 3m in X, Y and Z axes.",1251,0.64,16.75,-73.38,-58.95,1,1,9603,-45,8,-33,,,,,0
-549,1548,4291,4326,"Derived by Brazilean Institute of Geography and Statistics (IGBE) in 1989. Used by ANP.",Medium and small scale mapping.,1053,-35.71,7.04,-74.01,-25.28,1,1,9603,-66.87,4.37,-38.52,,,,,0
-550,1225,4292,4326,Derived at 5 stations.,For military purposes. Accuracy 1m in each axis.,2355,-52.51,-51.16,-59.98,-57.61,1,0,9603,-355,21,72,,,,,1
-551,1226,4293,4326,"Derived at 3 stations. 
+546,1808,4284,4326,"Mean of 3 stations in western Georgia, 4 stations in eastern Georgia and 4 stations in eastern Azerbaijan. Derived for use on AIOC early oil western export pipeline, but adopted for all AIOC work replacing the 1995 AIOC transformation (code 1807).",Oil industry operations.,2593,37.89,43.59,39.99,51.73,1,0,9606,686.1,-123.5,-574.4,8.045,-23.366,10.791,-2.926,0
+547,1809,4284,4326,Parameter values calculated by Elf Exploration and Production based on geodetic survey carried out by Azerbaijan State Committee for Geodesy and Cartography.,Oil industry operations.,2594,38.31,40.33,48.93,50.4,1,0,9606,926.4,-715.9,-186.4,-10.364,-20.78,26.452,-7.224,0
+548,5044,4284,4326,"Derived through concatenation of Pulkovo 1942 to PZ-90.02 to WGS 84. Replaces Pulkovo 1942 to WGS 84 (17) (code 1267).",Accuracy 3 metres.,1198,39.87,85.2,18.92,-168.97,1,0,9607,23.57,-140.95,-79.8,0,-0.35,-0.79,-0.22,0
+549,15865,4284,4326,"Derived via PZ-90 at 30 stations throughout USSR (Former Soviet Union, FSU) through concatenation of Pulkovo 1942 to PZ-90 (1) (tfm code 15844) and PZ-90 to WGS 84 (1) (tfm code 15843).",Accuracy 4.5 metres.,2423,35.14,81.91,19.57,-168.97,1,0,9607,25,-141,-78.5,0,-0.35,-0.736,0,0
+550,6899,4284,4326,Derived at 19 stations.,"For military purposes. Accuracy 2m, 3m and 3m in X, Y and Z axes.",3246,57.52,59.75,21.74,28.2,1,0,9603,22,-126,-85,,,,,0
+551,1561,4285,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,1346,24.55,26.2,50.69,51.68,1,0,9603,-128,-283,22,,,,,0
+552,1562,4285,4326,"Derived by Brown & Root in 1992 for Qatar General Petroleum Corporation.",Oil exploration.,2406,24.64,27.05,50.55,53.04,1,0,9603,-128.16,-282.42,21.93,,,,,1
+553,1563,4285,4326,"Derived by Qatar Centre for GIS. See Qatar 1974 to WGS 84 (2) (code 1562) for transformation used by QGPC for offshore petroleum industry.",Oil exploration.,1346,24.55,26.2,50.69,51.68,1,0,9603,-128.033,-283.697,21.052,,,,,0
+554,1211,4287,4326,Derived at 2 stations.,"For military purposes. Accuracy 25m, 25m and 32m in X, Y and Z axes.",2407,59.75,72,-55,-40,1,1,9603,164,138,-189,,,,,0
+555,1112,4289,4326,"Replaced by Amersfoort to WGS 84 (2) (code 1672).","?",1275,50.75,53.7,3.2,7.22,1,0,9606,593.16,26.15,478.54,-1.30440,-0.10330,-1.14450,4.0775,0
+556,1672,4289,4326,"Parameter values from Amersfoort to ETRS89 (1) (code 1751) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaces Amersfoort to WGS 84 (1) (code 1112). Replaced by Amersfoort to WGS 84 (3) (code 15934).","Approximation at the +/- 1m level.",1275,50.75,53.7,3.2,7.22,1,0,9607,565.04,49.91,465.84,0.409394,-0.359705,1.86849,4.0772,0
+557,4833,4289,4326,"Parameter values from Amersfoort to ETRS89 (5) (tfm code 4830) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaces Amersfoort to WGS 84 (3) (code 15934).","Approximation at the +/- 1m level.",1275,50.75,53.7,3.2,7.22,1,0,9607,565.4171,50.3319,465.5524,0.398957,-0.343988,1.87740,4.0725,1
+558,15934,4289,4326,"Parameter values from Amersfoort to ETRS89 (3) (tfm code 15739) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaces Amersfoort to WGS 84 (2) (code 1672). Replaced by Amersfoort to WGS 84 (4) (tfm code 4833).","Approximation at the +/- 1m level.",1275,50.75,53.7,3.2,7.22,1,0,9607,565.2369,50.0087,465.658,0.406857,-0.350733,1.87035,4.0812,0
+559,1212,4291,4326,Derived at 84 stations.,"For military purposes only. Accuracy 15m, 6m and 9m in X, Y and Z axes.",1341,-56.15,13,-82,-34,1,1,9603,-57,1,-41,,,,,0
+560,1213,4291,4326,Derived at 10 stations.,For military purposes only. Accuracy 5m in each axis.,1033,-58.41,-21.78,-73.59,-52.63,1,1,9603,-62,-1,-37,,,,,0
+561,1214,4291,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,1049,-22.91,-9.67,-69.66,-57.52,1,1,9603,-61,2,-48,,,,,0
+562,1215,4291,4326,Derived at 22 stations.,"For military purposes only. Accuracy 3m, 5m and 5m in X, Y and Z axes.",1053,-35.71,7.04,-74.01,-25.28,1,1,9603,-60,-2,-41,,,,,0
+563,1216,4291,4326,Derived at 9 stations.,"For military purposes only. Accuracy 15m, 8m and 11m in X, Y and Z axes.",1066,-59.87,-17.5,-113.21,-65.72,1,1,9603,-75,-1,-44,,,,,0
+564,1217,4291,4326,Derived at 7 stations.,"For military purposes only. Accuracy 6m, 6m and 5m in X, Y and Z axes.",1070,-4.23,15.51,-84.77,-66.87,1,1,9603,-44,6,-36,,,,,0
+565,1218,4291,4326,Derived at 11 stations.,For military purposes. Accuracy 3m in each axis.,1085,-5.01,5,-95.35,-75.21,1,1,9603,-48,3,-44,,,,,0
+566,1219,4291,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2356,-1.41,0.18,-91.72,-89.19,1,1,9603,-47,26,-42,,,,,0
+567,1220,4291,4326,Derived at 5 stations.,"For military purposes only. Accuracy 9m, 5m and 5m in X, Y and Z axes.",1114,1.18,10.7,-61.39,-55.77,1,1,9603,-53,3,-47,,,,,0
+568,1221,4291,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,1188,-27.59,-19.29,-62.65,-54.24,1,1,9603,-61,2,-33,,,,,0
+569,1222,4291,4326,Derived at 6 stations.,For military purposes. Accuracy 5m in each axis.,1189,-21.05,-0.03,-84.68,-68.67,1,1,9603,-58,0,-44,,,,,0
+570,1223,4291,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1235,9.83,12.34,-62.09,-57.28,1,1,9603,-45,12,-33,,,,,0
+571,1224,4291,4326,Derived at 5 stations.,"For military purposes only. Accuracy 3m, 6m and 3m in X, Y and Z axes.",1251,0.64,16.75,-73.38,-58.95,1,1,9603,-45,8,-33,,,,,0
+572,1548,4291,4326,"Derived by Brazilean Institute of Geography and Statistics (IGBE) in 1989. Used by ANP.",Medium and small scale mapping.,1053,-35.71,7.04,-74.01,-25.28,1,1,9603,-66.87,4.37,-38.52,,,,,0
+573,1225,4292,4326,Derived at 5 stations.,For military purposes. Accuracy 1m in each axis.,2355,-52.51,-51.16,-59.98,-57.61,1,0,9603,-355,21,72,,,,,1
+574,1226,4293,4326,"Derived at 3 stations. 
 Beware!  Source CRS uses German legal metres, transformation parameter values are in (International) metres. See tfm code 1271 for example.",For military purposes only. Accuracy 20m in each axis.,1169,-30.64,-16.95,8.24,25.27,1,0,9603,616,97,-251,,,,,1
-552,1271,4293,4326,"Beware!  Source CRS uses GLM, tfm param in m. Example: Schwarzeck ?=19°35'46.952""S ?=20°41'50.649""E h=1185.99m; X=5623409.386 Y=2124618.003 Z=-2125847.632 GLM; X=5623485.84m Y=2124646.89m Z=-2125876.54m; WGS 84 X=5624101.48m Y=2124748.97m Z=-2126132.35m.","?",1169,-30.64,-16.95,8.24,25.27,1,0,9603,615.64,102.08,-255.81,,,,,0
-553,1286,4294,4326,Accuracy estimate not available.,For military purposes.,2354,-4.24,4.37,108.79,119.06,1,1,9603,-403,684,41,,,,,0
-554,1834,4294,4326,Accuracy estimate not available.,For military purposes.,2354,-4.24,4.37,108.79,119.06,1,1,9603,-403,684,41,,,,,0
-555,1835,4294,4326,,Oil exploration.,1360,-4.24,4.29,114.55,119.06,1,1,9603,-387.06,636.53,46.29,,,,,0
-556,1836,4294,4326,,Oil exploration.,2770,-0.07,4.29,116.96,119.06,1,1,9603,-403.4,681.12,46.56,,,,,0
-557,1227,4297,4326,Accuracy estimate not available.,For military purposes.,1149,-26.59,-11.69,42.53,51.03,1,0,9603,-189,-242,-91,,,,,1
-558,6873,4297,4326,Derived at 9 points throughout Madagascar. Adopted by OMV.,For applications with an accuracy of 3m.,1149,-26.59,-11.69,42.53,51.03,1,0,9603,-198.383,-240.517,-107.909,,,,,0
-559,1228,4298,4326,Derived at 8 stations.,"For military purposes. Accuracy 10m, 10m and 12m in X, Y and Z axes.",1362,0.85,7.67,109.31,119.61,1,0,9603,-679,669,-48,,,,,1
-560,1592,4298,4326,"Originally used by BSP offshore only, use extended to onshore in 2010.",Oil exploration and production.,1055,4.01,6.31,112.37,115.37,1,0,9603,-678,670,-48,,,,,0
-561,1615,4298,4326,"CARE! Erroneous GPS data was used in the derivation of these parameters. They produce a coordinate difference of 10m horizontally and 50m vertically compared to Timbalai 1948 to WGS 84 (2) (code 1592).",Topographic and engineering survey onshore.,2349,4.01,5.11,114.09,115.37,1,0,9603,-726.282,703.611,-48.999,,,,,0
-562,1852,4298,4326,"Derived by Racal Survey for SSB at 24 coastal stations (including Timbalai fundamental point and 6 other primary triangulation stations) between in Sabah (Kudat southwards) and Sarawak (Sibu northwards).",Oil exploration.,2780,1.56,7.67,109.31,117.31,1,0,9606,-533.4,669.2,-52.5,0,0,4.28,9.4,0
-563,5248,4298,4326,,Oil exploration.,1055,4.01,6.31,112.37,115.37,1,1,9607,-689.5937,623.84046,-65.93566,0.02331,-1.17094,0.80054,5.88536,0
-564,5249,4298,4326,"Parameter values taken from Timbalai 1948 to GDBD2009 (1) (code 5878) assuming that GDBD2009 is equivalent to WGS 84 within the accuracy of the transformation.",Oil exploration.,1055,4.01,6.31,112.37,115.37,1,0,9607,-689.5937,623.84046,-65.93566,0.02331,-1.17094,0.80054,5.88536,0
-565,1229,4299,4326,Derived at 7 stations.,For military purposes only. Accuracy 3m in each axis.,1305,51.39,55.43,-10.56,-5.34,1,1,9603,506,-122,611,,,,,0
-566,1641,4299,4326,"Parameter values from TM75 to ETRS89 (2) (code 1953). Assumes each pair of (i) TM65 and TM75, and (ii) ETRS89 and WGS 84, can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1305,51.39,55.43,-10.56,-5.34,1,0,9606,482.5,-130.6,564.6,-1.042,-0.214,-0.631,8.15,1
-567,1954,4300,4326,"Parameter values taken from TM65 to ETRS89 (2) (code 1953). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1305,51.39,55.43,-10.56,-5.34,1,0,9606,482.5,-130.6,564.6,-1.042,-0.214,-0.631,8.15,1
-568,1956,4300,4326,"Derived at 7 stations. TM75 is based on the geodetic datum of 1965 which should not be confused with the mapping adjustment of 1965 (TM65).",For military purposes only. Accuracy 3m in each axis.,1305,51.39,55.43,-10.56,-5.34,1,0,9603,506,-122,611,,,,,0
-569,1230,4301,4326,Derived at 31 stations.,"For military purposes only. Accuracy 20m, 5m and 20m in X, Y and Z axes.",2409,20.37,45.54,122.83,145.87,1,0,9603,-148,507,685,,,,,0
-570,1231,4301,4326,Derived at 16 stations.,"For military purposes only. Accuracy 8m, 5m and 8m in X, Y and Z axes.",3995,30.18,45.54,128.31,145.87,1,0,9603,-148,507,685,,,,,0
-571,1232,4301,4326,"Derived at 29 stations. Replaced by Tokyo to WGS 84 (5) (code 1305).","For military purposes only. Accuracy 8m, 5m and 8m in X, Y and Z axes.",3266,33.14,38.64,124.53,131.01,1,0,9603,-146,507,687,,,,,0
-572,1233,4301,4326,Derived at 3 stations.,"For military purposes only. Accuracy 20m, 5m and 20m in X, Y and Z axes.",2408,23.98,26.91,122.83,131.38,1,0,9603,-158,507,676,,,,,0
-573,1305,4301,4326,"Derived at 29 stations. Replaces Tokyo to WGS 84 (3) (code 1232).",For military purposes. Accuracy 2m in each axis.,3266,33.14,38.64,124.53,131.01,1,0,9603,-147,506,687,,,,,0
-574,15484,4301,4326,"Parameter values from Tokyo to JGD2000 (1) (code 15483). Assumes JGD2000 and WGS 84 can be considered the same to within the accuracy of the transformation.","Surveying, mapping and civil engineering purposes. Accuracy on main islands 9m.",3957,20.37,45.54,122.83,154.05,1,0,9603,-146.414,507.337,680.507,,,,,1
-575,1296,4302,4326,Derived in 1989 by ONI for Amoco.,Oil exploration.,1339,9.83,11.51,-62.09,-60,1,0,9603,-61.702,284.488,472.052,,,,,1
-576,10085,4302,4326,"Parameter values provided to EOG by Trinidad Ministry of Energy and Energy Industries. Used by EOG offshore Trinidad (including Pelican, Kiskadee and Ibis fields) since 1996.",Oil exploration.,1339,9.83,11.51,-62.09,-60,1,0,9603,-61,285.2,471.6,,,,,0
-577,1932,4644,4326,,"Accuracy better than +/- 1 metre.",2823,-22.37,-22.19,166.35,166.54,1,1,9606,-166.207,-154.777,254.831,-37.5444,7.7011,-10.2025,-30.8598,0
-578,15904,4644,4326,"Parameter values taken from NEA74 Noumea to RGNC91-93 (1) ( code 15886) assuming that RGNC91-93 is equivalent to WGS 84 to within the accuracy of the transformation.",Accuracy 1 metre.,2823,-22.37,-22.19,166.35,166.54,1,0,9603,-10.18,-350.43,291.37,,,,,1
-579,1294,4304,4326,Accuracy estimate not available.,For military purposes.,1365,31.99,37.14,-2.95,9.09,1,0,9603,-73,-247,227,,,,,1
-580,15815,4728,4326,Determined at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3873,27.58,29.3,-18.22,-13.37,1,0,9603,-307,-92,127,,,,,1
-581,1253,4307,4326,Derived at 3 stations.,For military purposes only. Accuracy 25m in each axis.,3213,18.97,37.14,-8.67,11.99,1,0,9603,-186,-93,310,,,,,0
-582,1255,4307,4326,"CAUTION: Source CRS described by DMA as from Voirol 1960. OGP believes that the data used in the derivation of these parameters contains a blunder. We recommend using transformation North Sahara 1959 to WGS84 (1) (code 1253). Derived at 2 stations.",For military purposes only. Accuracy 25m in each axis.,1365,31.99,37.14,-2.95,9.09,1,0,9603,-123,-206,219,,,,,0
-583,1815,4307,4326,Used by BP in District 3 and In Salah Gas.,Oil industry operations.,2598,25,32,1,3.3,1,0,9606,-152.9,43.8,358.3,2.714,1.386,-2.788,-6.743,0
-584,1816,4307,4326,"Derived at astro station central to concession. Significant and varying differences (>100m) at 4 neighbouring astro stations.",Oil industry operations.,2599,27.5,28.3,8.83,9.92,1,0,9603,-95.7,10.2,158.9,,,,,0
-585,1817,4307,4326,Derived at astro station Guerrara.,Oil industry operations.,2600,31.75,32.42,7.16,8,1,0,9603,-165.914,-70.607,305.009,,,,,0
-586,5630,4307,4326,"Derived at 1 station (L38).",Used by Total in Ahnet licence area.,3917,26.06,27.51,1.26,2.92,1,0,9603,-168.52,-72.05,304.3,,,,,0
-587,5660,4307,4326,Derived in 2006 at 45 points in north and central Algeria.,Accuracy at 75 common points better than 1m..,1026,18.97,38.8,-8.67,11.99,1,0,9606,-209.3622,-87.8162,404.6198,0.0046,3.4784,0.5805,-1.4547,1
-588,15874,4307,4326,"Derived at 11 stations throughout blocks 317b, 319b, 321b and 322b. Network based on station P4 (horizontal) and benchmark RN51 (vertical) using EGM96 geoid height. Used by Statoil in Hassi Mouina.",Oil exploration and production. Accuracy 5m.,3402,29.25,31,0,1.25,1,0,9603,-169.559,-72.34,303.102,,,,,0
-589,1234,4309,4326,Accuracy estimate not available.,For military purposes.,3326,-35,-30.09,-58.49,-53.09,1,0,9603,-155,171,37,,,,,1
-590,5386,4309,4326,Derived at 11 stations during 1998 densification of Uruguay control based on SIRGAS 1995.,"Accuracy at stations used for derivation: 0.13 to 1.17m.",3326,-35,-30.09,-58.49,-53.09,1,0,9606,-124.45,183.74,44.64,-0.4384,0.5446,-0.9706,-2.1365,0
-591,15816,4734,4326,Determined at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3184,-40.42,-37,-12.76,-9.8,1,0,9603,-632,438,-609,,,,,1
-592,1235,4311,4326,Derived at 5 stations.,"For military purposes. Accuracy 5m, 5m and 8m in X, Y and Z axes.",1222,1.83,9.35,-58.08,-52.66,1,0,9603,-265,120,-358,,,,,1
-593,1194,4312,4326,May be taken as approximate transformation MGI to ETRS89 assuming ETRS89 is equivalent to WGS 84 within the accuracy of the transformation - see tfm code 1024. Information source gives scale as -2.388739 ppm.,Provincial GIS and other applications to an accuracy of 0.5 metres.,1543,46.64,47.84,13.58,16.17,1,0,9607,601.705,84.263,485.227,-4.7354,-1.3145,-5.393,-2.3887,0
-594,1306,4312,4326,Accuracy estimate not available.,For military purposes only.,2370,40.85,46.88,13.38,23.04,1,1,9603,682,-203,480,,,,,0
-595,1471,4312,4326,,For applications to an accuracy of 1.5 metres.,1037,46.4,49.02,9.53,17.17,1,1,9606,-577.326,-90.129,-463.919,-5.1365988,-1.4742,-5.2970436,-2.4232,0
-596,1618,4312,4326,"Same transformation parameters used for MGI to ETRS89 (1) (code 1619).",For applications to an accuracy of 1.5 metres.,1037,46.4,49.02,9.53,17.17,1,0,9606,577.326,90.129,463.919,5.137,1.474,5.297,2.4232,1
-597,1621,4312,4326,"Parameter values from MGI to ETRS89 (2) (code 1620). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1076,41.62,46.54,13,19.43,1,1,9606,551.7,162.9,467.9,6.04,1.96,-11.38,-4.82,0
-598,1786,4312,4326,"Parameter values from MGI to ETRS89 (3) (code 1785). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1212,45.42,46.88,13.38,16.61,1,1,9606,426.9,142.6,460.1,4.91,4.49,-12.42,17.1,0
-599,1794,4312,4326,"For more accurate transformation see MGI to WGS 84 (7) (code 1795).",Oil industry,3536,41.79,43.56,18.45,20.38,1,1,9603,695.5,-216.6,491.1,,,,,0
-600,15982,4312,4326,"Parameter values from MGI to Slovenia 1996 (1) (code 15981). Assumes Slovenia 1996 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1212,45.42,46.88,13.38,16.61,1,1,9607,409.545,72.164,486.872,-3.085957,-5.46911,11.020289,17.919665,0
-601,1609,4313,4326,"Scale difference is given by information source as 0.999999. Given in this record in ppm to assist application usage. Very similar parameter values (to slightly less precision) used for BD72 to ETRS89: see code 1652.",For applications to an accuracy of 1 metre.,1347,49.5,51.51,2.5,6.4,1,0,9607,-99.059,53.322,-112.486,-0.419,0.83,-1.885,-1,0
-602,1610,4313,4326,,For applications to an accuracy of 5 metres.,1347,49.5,51.51,2.5,6.4,1,0,9603,-125.8,79.9,-100.5,,,,,0
-603,15749,4313,4326,"Parameter values from BD72 to ETRS89 (2) (code 15748). Scale difference is given by information source as 1.0000012747. Given in this record in ppm to assist application usage.",For applications to an accuracy of 0.5 metre.,1044,49.5,51.88,2.23,6.4,1,1,9607,-106.8686,52.2978,-103.7239,-0.3366,0.457,-1.8422,1.2747,0
-604,15929,4313,4326,"Parameter values from BD72 to ETRS89 (2) (code 15928). Scale difference is given by information source as -1.0000012747. Given in this record in ppm to assist application usage.",For applications to an accuracy of 0.5 metre.,1347,49.5,51.51,2.5,6.4,1,0,9607,-106.8686,52.2978,-103.7239,-0.3366,0.457,-1.8422,-1.2747,1
-605,1673,4314,4326,"Parameter values from DHDN to ETRS89 (1) (code 1309) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaced by DHDN to WGS 84 (2) (tfm code 1777).",For applications with an accuracy at 5 m level.,2326,47.27,55.09,5.87,13.84,1,0,9607,582,105,414,-1.04,-0.35,3.08,8.3,0
-606,1777,4314,4326,"Parameter values from DHDN to ETRS89 (2) (code 1776) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaces DHDN to WGS 84 (1) (tfm code 1673).",For applications with an accuracy at 3 m level,2326,47.27,55.09,5.87,13.84,1,0,9606,598.1,73.7,418.2,0.202,0.045,-2.455,6.7,1
-607,15869,4314,4326,"Parameter values taken from RD/83 to ETRS89 (1) (tfm code 15868) assuming that within the accuracy of the transformation ETRS89 is equivalent to WGS 84 and RD/83 is equivalent to DHDN.",For applications with an accuracy at 2m level,1343,50.2,54.74,9.92,15.04,1,0,9606,612.4,77,440.2,-0.054,0.057,-2.797,2.55,0
-608,1517,4315,4326,,"?",3257,7.19,12.68,-15.13,-7.65,1,0,9603,-23,259,-9,,,,,1
-609,1789,4316,4326,"Parameter values taken from Pulkovo 1942 to WGS 84 (9) (code 1293) assuming that","?",1197,43.44,48.27,20.26,31.41,1,1,9603,103.25,-100.4,-307.19,,,,,0
-610,1995,4316,4326,,Oil exploration,3295,43.62,48.27,20.26,29.74,1,0,9603,103.25,-100.4,-307.19,,,,,1
-611,1097,4317,4326,"Parameter values taken from Pulkovo 1942 to WGS 84 (9) (code 1293) assuming that Pulkovo 1942 in Romania is equivalent to Dealul Piscului 1970.","Accuracy 3m, 5m and 3m in X, Y and Z axes.",1197,43.44,48.27,20.26,31.41,1,1,9603,28,-121,-77,,,,,0
-612,1996,4317,4326,,Oil exploration,1197,43.44,48.27,20.26,31.41,1,1,9603,44.107,-116.147,-54.648,,,,,0
-613,1060,4318,4326,,1 metre accuracy.,3267,28.53,30.09,46.54,48.48,1,0,9603,-3.2,-5.7,2.8,,,,,1
-614,1061,4319,4326,,For applications requiring an accuracy of better than 1 metre.,1310,29.17,29.45,47.78,48.16,1,0,9603,-20.8,11.3,2.4,,,,,1
-615,1062,4319,4326,,For applications requiring an accuracy of better than 1 metre.,1310,29.17,29.45,47.78,48.16,1,0,9607,226.702,-193.337,-35.371,2.229,4.391,-9.238,0.9798,0
-616,1237,4322,4326,,For scientific purposes.,1262,-90,90,-180,180,1,0,9606,0,0,4.5,0,0,0.554,0.2263,1
-617,1238,4322,4326,,For scientific purposes.,1262,-90,90,-180,180,1,0,9606,0,0,4.5,0,0,0.554,0.219,0
-618,15821,4731,4326,Derived at 1 satellite station.,"For military and topographic mapping. Accuracy +/-25m in each axis.",3195,-18.32,-17.25,177.19,178.75,1,1,9603,51,391,-36,,,,,0
-619,1240,4324,4326,,Geodesy.,2346,-90,90,-180,180,1,0,9606,0,0,1.9,0,0,0.814,-0.38,1
-620,5521,4646,4326,,For military purposes. Accuracy unknown.,2807,-11.99,-11.31,43.16,43.55,1,0,9603,-963,510,-359,,,,,1
-621,15822,4732,4326,Derived at 10 satellite stations.,"For military and topographic mapping. Accuracy +/-3 m in each axis.",3191,8.66,19.38,162.27,167.82,1,0,9603,102,52,-38,,,,,1
-622,5327,5324,4326,For many purposes ISN2004 can be considered to be coincident with WGS 84.,"Approximation at the +/- 1m level assuming that ISN2004 is equivalent to WGS 84.",1120,59.96,69.59,-30.87,-5.55,1,0,9603,0,0,0,,,,,1
-623,3817,3819,4326,Horizontal coordinates of 66 points of the National Geodetic Network were used to compute this transformation.,GIS and topographic survey.,1119,45.74,48.58,16.11,22.9,1,0,9607,595.48,121.69,515.35,-4.115,2.9383,-0.853,-3.408,1
-624,1920,4645,4326,,"Accuracy +/- 1 metre.",1174,-26.45,-14.83,156.25,174.28,1,1,9603,0,0,0,,,,,0
-625,15823,4733,4326,Derived at 2 satellite stations.,"For military and topographic mapping. Accuracy +/-25m in each axis.",3190,19.22,19.38,166.55,166.72,1,0,9603,276,-57,149,,,,,1
-626,3830,3824,4326,"Approximation at the +/- 1m level assuming that TWD97 is equivalent to WGS 84.","Accuracy +/- 1m.",1228,17.36,26.96,114.32,123.61,1,0,9603,0,0,0,,,,,1
-627,5376,5365,4326,,Accuracy 1m.,1074,2.15,11.77,-90.45,-81.43,1,0,9603,0,0,0,,,,,1
-628,15808,4724,4326,Derived at 2 satellite stations.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3189,-7.49,-7.18,72.3,72.55,1,0,9603,208,-435,-229,,,,,1
-629,5377,5371,4326,,Accuracy 1m.,1186,5,12.51,-84.32,-77.04,1,0,9603,0,0,0,,,,,1
-630,5378,5373,4326,,Accuracy 1m.,1189,-21.05,-0.03,-84.68,-68.67,1,0,9603,0,0,0,,,,,1
-631,15812,4736,4326,,"Scientific mapping. Accuracy +/- 20m in each axis.",3204,-63.08,-62.82,-60.89,-60.35,1,0,9603,260,12,-147,,,,,1
-632,15795,4707,4326,Derived at 1 satellite station. Same transformation parameter values related to same datum area given in original 1987 DMA TR8350.2 edition for Sorol Atoll.,For military purposes only. Accuracy 25m in each axis.,3181,23.69,23.93,-166.36,-166.03,1,0,9603,114,-116,-333,,,,,1
-633,5384,5381,4326,,Accuracy 1m.,1247,-37.77,-30.09,-58.49,-50.01,1,0,9603,0,0,0,,,,,1
-634,15813,4722,4326,Determined from 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3529,-54.95,-53.93,-38.08,-35.74,1,0,9603,-794,119,-298,,,,,1
-635,5227,5228,4326,"Parameter values from S-JTSK/05 to ETRS89 (1) (code 5226). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaces tfm code 1622.",For applications to an accuracy of 1 metre.,1079,48.58,51.06,12.09,18.86,1,0,9607,572.213,85.334,461.94,-4.9732,-1.529,-5.2484,3.5378,1
-636,15771,4692,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from Maupiti 83 to RGPF (1) (tfm code 15759).","Accuracy +/- 1 metre.",3126,-16.57,-16.34,-152.39,-152.14,1,0,9603,217.037,86.959,23.956,,,,,1
-637,15973,4055,4326,"Executes change of sphere/ellipsoid",Web mapping. Accuracy may be no better than 800 metres.,1262,-90,90,-180,180,1,1,9603,0,0,0,,,,,0
-638,5395,5393,4326,,Accuracy 1m.,1087,9.97,14.44,-91.43,-87.65,1,0,9603,0,0,0,,,,,1
-639,15842,4739,4326,"Derived at 2 satellite stations. Care: does not use Hong Kong 1963 (code 4838) as the source CRS.","Military mapping. Accuracy +/- 1m.",1118,22.13,22.58,113.76,114.51,1,0,9603,-156,-271,-189,,,,,1
-640,5261,5252,4326,,"Approximation at the +/- 1m level as both TUREF and WGS 84 are realisations of ITRS.",1237,34.42,43.45,25.62,44.83,1,0,9603,0,0,0,,,,,1
-641,1925,4639,4326,,"Accuracy +/- 10 metres.",2815,-13.41,-13.16,-176.25,-176.07,1,1,9603,252,-132,-125,,,,,0
-642,15847,4639,4326,"Replaces information from 2001 (tfm code 1925).","Accuracy +/- 10 metres.",2815,-13.41,-13.16,-176.25,-176.07,1,0,9603,253,-132,-127,,,,,1
-643,15801,4714,4326,Derived at 3 satellite stations.,"Military and topographic mapping; Accuracy +/- 20 m in each axis",3193,-20.31,-17.37,168.09,169.95,1,0,9603,-127,-769,472,,,,,1
-644,15802,4715,4326,No accuracy estimate available.,Military and scientific mapping.,3205,-77.94,-77.17,165.73,167.43,1,0,9603,-104,-129,239,,,,,1
-645,1994,4657,4326,,Low accuracy applications.,3262,63.34,66.59,-24.66,-13.38,1,0,9603,-28,199,5,,,,,1
-646,5351,5340,4326,,Approximation at the sub meter level.,1033,-58.41,-21.78,-73.59,-52.63,1,0,9603,0,0,0,,,,,1
-647,5078,4743,4326,"Parameter values from Karbala 1979 to IGRS (1) (tfm code 5077) assuming that IGRS is equivalent to WGS 84 within the accuracy of the transformation. Replaces Karbala 1979 to WGS 84 (1) (tfm code 15872).",Accuracy 1m.,3625,29.06,37.39,38.79,48.61,1,0,9603,70.995,-335.916,262.898,,,,,1
-648,15872,4743,4326,"Derived from shifts in UTM rectangular coordinates for one point in Basra area provided by Iraq National Oil Exploration Company. Replaced by Karbala 1979 to WGS 84 (2) (tfm code 5078).",Oil exploration.,3397,29.87,31.09,46.46,48.61,1,0,9603,84.1,-320.1,218.7,,,,,0
-649,1951,4658,4326,Derived at 6 stations.,"Accuracy 3m, 3m and 5m in X, Y and Z axes.",3262,63.34,66.59,-24.66,-13.38,1,0,9603,-73,46,-86,,,,,1
-650,6373,6365,4326,,Accuracy 1m.,1160,12.1,32.72,-122.19,-84.64,1,0,9603,0,0,0,,,,,1
-651,3894,3889,4326,"Approximation at the +/- 1m level assuming that IGRS is equivalent to WGS 84 within the accuracy of the transformation.",Accuracy 1m.,1124,29.06,37.39,38.79,48.75,1,0,9603,0,0,0,,,,,1
-652,1952,4659,4326,For many purposes ISN93 can be considered to be coincident with WGS 84.,"Approximation at the +/- 1m level assuming that ISN93 is equivalent to WGS 84.",1120,59.96,69.59,-30.87,-5.55,1,0,9603,0,0,0,,,,,1
-653,1957,4660,4326,Derived at 3 stations. Residuals under 1m.,For applications to an accuracy of 1 metre.,2869,70.75,71.24,-9.17,-7.87,1,0,9606,982.6087,552.753,-540.873,6.68162662527694,-31.6114924086422,-19.8481610048168,16.805,1
-654,1958,4661,4326,,LKS92 is a realisation of ETRS89 coincident to WGS84 within 1 metre. This transformation has an accuracy equal to the coincidence figure.,1139,55.67,58.09,19.06,28.24,1,0,9603,0,0,0,,,,,1
-655,15849,4213,4326,"Used by Elf / CGG between December 1991 and March 1992. Probably derived from results of concatenated tfm Beduaram to WGS 84 (1) (code 8634).",Oil exploration.,2771,12.8,16.7,7.81,14.9,1,0,9603,-106,-87,188,,,,,1
-656,15803,4716,4326,Derived at 4 satellite stations.,"Military and topographic mapping. Accuracy +/- 15 m in each axis.",3196,-4.76,-2.68,-174.6,-170.66,1,0,9603,298,-304,-375,,,,,1
-657,3915,3906,4326,"Parameter values from MGI 1901 to ETRS89 (3) (code 3914). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1212,45.42,46.88,13.38,16.61,1,0,9606,426.9,142.6,460.1,4.91,4.49,-12.42,17.1,0
-658,3917,3906,4326,"Parameter values from MGI 1901 to Slovenia 1996 (1) (code 3916). Assumes Slovenia 1996 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1212,45.42,46.88,13.38,16.61,1,0,9607,409.545,72.164,486.872,-3.085957,-5.46911,11.020289,17.919665,0
-659,3962,3906,4326,Accuracy estimate not available from information source but established empirically by OGP.,For military purposes only.,2370,40.85,46.88,13.38,23.04,1,0,9603,682,-203,480,,,,,1
-660,3964,3906,4326,"Parameter values from MGI 1901 to ETRS89 (2) (code 3963). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,3234,42.34,46.54,13.43,19.43,1,0,9606,551.7,162.9,467.9,6.04,1.96,-11.38,-4.82,0
-661,3965,3906,4326,,Oil industry,3536,41.79,43.56,18.45,20.38,1,0,9603,695.5,-216.6,491.1,,,,,0
-662,6206,3906,4326,Derived at 13 stations.,"1m accuracy. Residuals generally less than +/- 1m horizontally and vertically.",1148,40.85,42.36,20.45,23.04,1,0,9607,521.748,229.489,590.921,-4.029,-4.488,15.521,-9.78,0
-663,15879,4747,4326,"Approximation at the +/- 1m level assuming that GR96 is equivalent to WGS 84 within the accuracy of the transformation.","For applications with an accuracy of +/- 1m.",1107,56.38,87.03,-75,8.12,1,0,9603,0,0,0,,,,,1
-664,1962,4662,4326,Withdrawn by information source and replaced by improved information from local authority - see tfm code 15903.,"Accuracy +/- 10 metres.",2822,-22.45,-20.03,163.92,167.09,1,0,9603,-13,-348,292,,,,,0
-665,1963,4662,4326,Withdrawn by information source and replaced by improved information - see tfm code 15903.,"Accuracy better than +/- 1 metre.",2822,-22.45,-20.03,163.92,167.09,1,0,9606,97.295,-263.247,310.882,-1.5999,0.8386,3.1409,13.3259,0
-666,15903,4662,4326,"Parameter values taken from IGN72 Grande Terre to RGNC91-93 (1) ( code 15882) assuming that RGNC91-93 is equivalent to WGS 84 to within the accuracy of the transformation.","Accuracy +/- 2 metres.",2822,-22.45,-20.03,163.92,167.09,1,0,9603,-11.64,-348.6,291.98,,,,,1
-667,15878,4748,4326,"Parameter values taken from Viti Levu 1912 to WGS 84 (1) (tfm code 15897). Approximation at the +/- 50m level assuming that CRS 4748 is equivalent to CRS 4752 within the transformation accuracy. Source CRSs 4748 and 4752 are independent but connected.","For applications with an accuracy of +/-50m.",3401,-17.07,-16.1,178.42,-179.77,1,0,9603,51,391,-36,,,,,1
-668,1966,4663,4326,Derived at Forte de Sao Tiago.,For low resolution applications.,2870,32.58,33.15,-17.31,-16.23,1,0,9603,-502.862,-247.438,312.724,,,,,1
-669,1967,4663,4326,,For medium resolution applications.,2870,32.58,33.15,-17.31,-16.23,1,0,9607,-210.502,-66.902,-48.476,-2.094,15.067,5.817,0.485,0
-670,15880,4749,4326,,"Accuracy +/- 1 metre.",1174,-26.45,-14.83,156.25,174.28,1,0,9603,0,0,0,,,,,1
-671,1968,4664,4326,Calculated in 2001.,For low resolution applications.,2871,37.65,37.96,-25.92,-25.08,1,0,9603,-204.633,140.216,55.199,,,,,0
-672,1969,4664,4326,Calculated in 2001.,For medium resolution applications.,2871,37.65,37.96,-25.92,-25.08,1,0,9607,-211.939,137.626,58.3,0.089,-0.251,-0.079,0.384,0
-673,1970,4664,4326,Mean for all islands in group.,For low resolution applications.,1345,36.87,37.96,-25.92,-24.62,1,0,9603,-204.619,140.176,55.226,,,,,1
-674,1971,4664,4326,Mean for all islands in group.,For medium resolution applications.,1345,36.87,37.96,-25.92,-24.62,1,0,9607,-208.719,129.685,52.092,0.195,0.014,-0.327,0.198,0
-675,15881,4750,4326,"Parameter values taken from ST87 Ouvea to RGNC91-93 (1) ( code 15885) assuming that RGNC91-93 is equivalent to WGS 84 to within the accuracy of the transformation.","Accuracy better than +/- 1 metre.",2813,-20.77,-20.34,166.44,166.71,1,0,9603,-56.263,16.136,-22.856,,,,,1
-676,1972,4665,4326,,For low resolution applications.,2872,38.57,38.86,-27.44,-26.97,1,0,9603,-106.301,166.27,-37.916,,,,,0
-677,1973,4665,4326,,For medium resolution applications.,2872,38.57,38.86,-27.44,-26.97,1,0,9607,-105.854,165.589,-38.312,0.003,0.026,-0.024,-0.048,0
-678,1974,4665,4326,,For low resolution applications.,2873,38.46,38.7,-28.9,-28.54,1,0,9603,-106.248,166.244,-37.845,,,,,0
-679,1975,4665,4326,,For medium resolution applications.,2873,38.46,38.7,-28.9,-28.54,1,0,9607,-104,162.924,-38.882,0.075,0.071,-0.051,-0.338,0
-680,1976,4665,4326,,For low resolution applications.,2874,38.32,38.61,-28.61,-27.98,1,0,9603,-106.044,166.655,-37.876,,,,,0
-681,1977,4665,4326,,For medium resolution applications.,2874,38.32,38.61,-28.61,-27.98,1,0,9607,-95.323,166.098,-69.942,0.215,1.031,-0.047,1.922,0
-682,1978,4665,4326,,For low resolution applications.,2875,38.48,38.8,-28.37,-27.71,1,0,9603,-106.253,166.239,-37.854,,,,,0
-683,1979,4665,4326,,For medium resolution applications.,2875,38.48,38.8,-28.37,-27.71,1,0,9607,-100.306,161.246,-48.761,0.192,0.385,-0.076,0.131,0
-684,1980,4665,4326,Mean for all islands in group.,For low resolution applications.,1301,38.32,39.14,-28.9,-26.97,1,0,9603,-106.226,166.366,-37.893,,,,,1
-685,1981,4665,4326,Mean for all islands in group.,For medium resolution applications.,1301,38.32,39.14,-28.9,-26.97,1,0,9607,-103.088,162.481,-28.276,-0.167,-0.082,-0.168,-1.504,0
-686,1986,4666,4326,May be taken as a transformation from Lisbon 1890 to ETRS89 - see tfm code 5039.,For low resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9603,508.088,-191.042,565.223,,,,,1
-687,1990,4666,4326,,For medium resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9607,631.392,-66.551,481.442,-1.09,4.445,4.487,-4.43,0
-688,15804,4717,4326,Derived at 19 satellite stations.,"US space and military operations. Accuracy +/- 3 m in each axis.",3206,20.86,30.83,-82.33,-72.68,1,0,9603,-2,151,181,,,,,1
-689,5267,5264,4326,DRUKREF 03 and WGS 84 are both realisations of ITRS.,For applications to an accuracy of 1 metre.,1048,26.7,28.33,88.75,92.12,1,0,9603,0,0,0,,,,,1
-690,15708,4683,4326,Derived during GPS campaign which established PRS92 coordinates at 330 first order stations.,"Accuracy: 1-10 parts per million.",1190,3,22.18,116.04,129.95,1,0,9607,-127.62,-67.24,-47.04,3.068,-4.903,-1.578,-1.06,1
-691,1993,4667,4326,For all practical purposes this transformation is exact.,Boundary demarcation.,2876,29.06,30.32,46.36,48.61,1,0,9603,0,0,0,,,,,1
-692,15897,4752,4326,Derived at 1 satellite station.,"For military and topographic mapping. Accuracy +/-25m in each axis.",3195,-18.32,-17.25,177.19,178.75,1,0,9603,51,391,-36,,,,,1
-693,15752,4668,4326,Derived at 22 stations.,For military purposes. Accuracy 3m in each axis.,1297,34.88,71.21,-10.56,31.59,1,0,9603,-86,-98,-119,,,,,1
-694,15810,4735,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3192,5.21,5.43,162.85,163.1,1,0,9603,647,1777,-1124,,,,,1
-695,6701,5246,4326,"Approximation at the +/- 1m level assuming that GDBD2009 is equivalent to WGS 84 within the accuracy of the transformation.",Accuracy 1m.,1055,4.01,6.31,112.37,115.37,1,0,9603,0,0,0,,,,,1
-696,4477,4463,4326,"Approximation at the +/- 1m level assuming that RGSPM06 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1220,43.41,47.37,-57.1,-55.9,1,0,9603,0,0,0,,,,,1
-697,5501,5489,4326,"Approximation at the +/- 1m level assuming that RGAF09 is equivalent to WGS 84 within the accuracy of the transformation.","Accuracy +/- 1 metre.",2824,14.08,18.54,-63.66,-57.52,1,0,9603,0,0,0,,,,,1
-698,15912,4755,4326,"Approximation at the +/- 1m level assuming that DGN95 is equivalent to WGS 84 within the accuracy of the transformation.",Accuracy 1 metre.,1122,-13.25,7.79,92.01,141.46,1,0,9603,0,0,0,,,,,1
-699,1555,4158,4326,Derived in 1989 by ONI for Amoco.,Oil exploration.,3143,9.99,10.9,-61.97,-60.86,1,0,9603,-0.465,372.095,171.736,,,,,1
-700,1556,4158,4326,Described by NIMA as Naparima to WGS 84. In Trinidad the source CRS is better known as Naparima 1955. EPSG has duplicated the tfm using the alternative source CRSs. See also tfm code 1307.,For military purposes only. Accuracy given by NIMA 15m in each axis. EPSG believes there is an 8-10m blunder in dX.,3143,9.99,10.9,-61.97,-60.86,1,0,9603,-2,374,172,,,,,0
-701,4476,4470,4326,"Approximation at the +/- 1m level assuming that RGM04 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1159,-14.49,-11.33,43.68,46.7,1,0,9603,0,0,0,,,,,1
-702,5194,4756,4326,Used by Total in Mekong delta.,Academic research not officially adopted.,3770,9.34,11.03,104.25,107.11,1,0,9607,-192.873,-39.382,-111.202,0.00205,0.0005,-0.00335,0.0188,1
-703,1931,4643,4326,,"Accuracy better than +/- 1 metre.",2821,-19.85,-19.5,163.54,163.75,1,0,9606,-480.26,-438.32,-643.429,16.3119,20.1721,-4.0349,-111.7002,1
-704,4290,4475,4326,"Parameter values taken from Cadastre 1997 to RGM04 (1) (transformation code 4478) assuming that RGM04 is coincident with WGS 84 within the accuracy of the transformation.","Accuracy +/- 1 metre.",3340,-13.05,-12.61,44.98,45.35,1,0,9603,-381.788,-57.501,-256.673,,,,,1
-705,5374,5354,4326,,Accuracy 1m.,1049,-22.91,-9.67,-69.66,-57.52,1,0,9603,0,0,0,,,,,1
-706,15787,4701,4326,Derived by Topnav in 1991 at station TSH 85.,Oil exploration. Accuracy 5m.,3171,-6.04,-4.28,12.17,16.28,1,0,9603,-79.9,-158,-168.9,,,,,1
-707,4832,4483,4326,,Accuracy 1m.,1160,12.1,32.72,-122.19,-84.64,1,0,9603,0,0,0,,,,,1
-708,1917,4633,4326,Withdrawn by information source and replaced by improved information from local authority - see tfm code 15902.,"Accuracy +/- 10 metres.",2814,-21.24,-20.62,166.98,167.52,1,0,9603,336,223,-231,,,,,0
-709,1927,4633,4326,Withdrawn by information source and replaced by improved information - see tfm code 15902.,"Accuracy better than +/- 1 metre.",2814,-21.24,-20.62,166.98,167.52,1,0,9606,137.092,131.66,91.475,-1.9436,-11.5993,-4.3321,-7.4824,0
-710,15902,4633,4326,"Parameter values taken from IGN56 Lifou to RGNC91-93 (1) ( code 15883) assuming that RGNC91-93 is equivalent to WGS 84 to within the accuracy of the transformation.",Accuracy 1 metre.,2814,-21.24,-20.62,166.98,167.52,1,0,9603,335.47,222.58,-230.94,,,,,1
-711,15925,4758,4326,,For all practical purposes JAD2001 can be considered to be coincident with WGS 84.,1128,14.08,19.36,-80.6,-74.51,1,0,9603,0,0,0,,,,,1
-712,6711,6706,4326,"Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84. RDN2008 is a regional realisation of ETRS89.","Accuracy +/- 1 metre.",1127,34.76,47.1,5.93,18.99,1,0,9603,0,0,0,,,,,1
-713,15845,4161,4326,Transformation parameter precision given to millimetres in information source but due to accuracy rounded to nearest decimetre for EPSG database.,Geodetic surveying within the oil industry. Accuracy 25 m.,1265,-46.7,-45.19,-69.5,-67.1,1,0,9603,27.5,14,186.4,,,,,1
-714,15931,4759,4326,"Approximation at the +/- 1m level assuming that NAD83(NSRS2007) is equivalent to WGS 84 within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1511,14.92,74.71,167.65,-63.88,1,0,9603,0,0,0,,,,,1
-715,1540,4163,4326,,Accuracy better than 1 metre.,1257,8.95,19,41.08,57.96,1,0,9603,0,0,0,,,,,1
-716,4905,5013,4326,,PTRA08 and WGS 84 are realisations of ITRS coincident to within 1 metre. This transformation has an accuracy equal to the coincidence figure.,3670,29.24,43.07,-35.58,-12.48,1,0,9603,0,0,0,,,,,1
-717,6195,5527,4326,"Parameter values from SAD69(96) to SIRGAS 2000 (2)) (tfm code 5881) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation, based on SAD69 to SIRGAS 2000 (1)) (tfm code 15485). Used by Petrobras and ANP from 1994.","Accuracy generally better than 1m except in Amazon basin where it degenerates to 5m. Should be used only to transform data obtained independently of the classical geodetic network (GPS observations conducted after 1994).", [...]
-718,15806,4719,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis",3188,-27.25,-27.01,-109.51,-109.16,1,0,9603,211,147,111,,,,,1
-719,15860,4702,4326,Mauritania 1999 can be considered to be the same as WGS 84 within the accuracy of this transformation.,Minerals management. Accuracy 1m.,1157,14.72,27.3,-20.04,-4.8,1,0,9603,0,0,0,,,,,1
-720,15971,4762,4326,"Approximation at the +/- 1m level assuming that BDA2000 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1047,28.91,35.73,-68.83,-60.7,1,0,9603,0,0,0,,,,,1
-721,5375,5360,4326,,Accuracy 1m.,1066,-59.87,-17.5,-113.21,-65.72,1,0,9603,0,0,0,,,,,1
-722,15972,4763,4326,"Approximation at the +/- 1m level assuming that Pitcairn 2006 is equivalent to WGS 84.","Accuracy +/- 1 metre.",3208,-25.14,-25,-130.16,-130.01,1,0,9603,0,0,0,,,,,1
-723,1558,4166,4326,Derived at 5 stations.,For military purposes. Accuracy 1m in each axis.,3266,33.14,38.64,124.53,131.01,1,0,9603,0,0,0,,,,,1
-724,4084,4081,4326,"Approximation at the +/- 1m level assuming that REGCAN95 is equivalent to WGS 84.","Accuracy +/- 1m.",3199,24.6,32.76,-21.93,-11.75,1,0,9603,0,0,0,,,,,1
-725,15974,4764,4326,"Approximation at the +/- 1m level assuming that RSRGD2000 is equivalent to WGS 84.","Accuracy +/- 1 metre.",3558,-90,-59.99,144.99,-144.99,1,0,9603,0,0,0,,,,,1
-726,5553,5546,4326,"Exact in 1994 but due to significant and variable tectonic activity in PNG, in 2011 PNG94 and WGS 84 differ generally by 2m but in areas of significant tectonic activity differences can exceed 9m.",Approximation at the 2-10m level.,1187,-14.75,2.58,139.2,162.81,1,0,9603,0,0,0,,,,,1
-727,15870,4679,4326,Derived at 5 points in 2002.,Hydrographic survey,2967,19.37,21.34,-17.08,-15.88,1,0,9603,-80.01,253.26,291.19,,,,,1
-728,15976,4765,4326,"Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1212,45.42,46.88,13.38,16.61,1,0,9603,0,0,0,,,,,1
-729,15820,4730,4326,Derived at 1 satellite station.,For military and topographic mapping. Accuracy 25m in each axis.,3194,-17.32,-14.57,166.47,168.71,1,0,9603,170,42,84,,,,,1
-730,15709,4680,4326,Derived by IGN in 1992 at 7 stations within Nouakchott city.,Oil exploration.,2972,17.89,18.25,-16.11,-15.83,1,0,9603,124.5,-63.5,-281,,,,,1
-731,15908,4754,4326,Derived at 5 stations throughout Libya used to define LGD2006 in May 2006.,For applications to an accuracy of 0.1 metre.,1143,19.5,35.23,9.31,26.21,1,0,9603,-208.4058,-109.8777,-2.5764,,,,,1
-732,5585,4023,4326,"Parameter values from MOLDREF99 to ETRS89 (1) (code 5584). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications with an accuracy of 1m.,1162,45.44,48.47,26.63,30.13,1,0,9603,0,0,0,,,,,1
-733,15831,4737,4326,"Approximation at the +/- 1m level assuming that ITRF2000 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1135,28.6,40.27,122.71,134.28,1,0,9603,0,0,0,,,,,1
-734,5590,5561,4326,"Derived through concatenation of UCS-2000 to S-42 (1) (tfm code 5586 reversed) [an approximation] and S-42 to WGS 84 (16) (tfm code 15865) [derived for whole FSU rather than Ukraine]. Replaced by UCS-2000 to WGS 84 (2) (tfm code 5840).",Accuracy 5 metres.,1242,43.18,52.38,22.15,40.18,1,0,9607,25,-141,-78.5,0,-0.35,-0.736,0,1
-735,5823,5561,4326,"Parameter values taken from Ukraine 2000 to ITRF2005 (1) (code 5822) assuming that ITRS2005 is equivalent to WGS 84 within the accuracy of the transformation.","Approximation at the +/- 1m level assuming that ITRS2005 is equivalent to WGS 84.",1242,43.18,52.38,22.15,40.18,1,1,9603,24,-121,-76,,,,,0
-736,5840,5561,4326,"Parameter values taken from UCS-2000 to ITRF2005 (1) (code 5822) assuming that WGS 84 is equivalent to ITRS2005 within the accuracy of the transformation. Replaces UCS-2000 to WGS 84 (1) (tfm code 5590).","Approximation at the +/- 1m level assuming that WGS 84 is equivalent to ITRS2005.",1242,43.18,52.38,22.15,40.18,1,0,9603,24,-121,-76,,,,,0
-737,15700,4682,4326,Derived at origin station in Dhaka.,Oil exploration.,1041,18.56,26.63,88.04,92.67,1,1,9603,283.8,735.9,261.1,,,,,0
-738,15779,4682,4326,Derived at origin station in Dhaka. Source information given to 3 decimal places but rounded by OGP to be commensurate with stated accuracy.,Oil exploration.,1041,18.56,26.63,88.04,92.67,1,0,9603,283.7,735.9,261.1,,,,,1
-739,1919,4635,4326,,"Accuracy better than +/- 1 metre.",2813,-20.77,-20.34,166.44,166.71,1,1,9606,-122.383,-188.696,103.344,3.5107,-4.9668,-5.7047,4.4798,0
-740,5470,5451,4326,"Parameter values taken from Ocotepeque to CR05 (1) (tfm code 6890) assuming that CR05 is equivalent to WGS 84 within the accuracy of the transformation.",Topographic mapping.,3232,7.98,11.22,-85.97,-82.53,1,0,9603,213.11,9.37,-74.95,,,,,0
-741,5473,5451,4326,"Rotations in original source given in radians are equivalent to Rx = 2.35"", Ry = -0.06"", Rz = 6.39"".",Topographic mapping.,3232,7.98,11.22,-85.97,-82.53,1,1,9607,213.116,9.358,-74.946,2.3514187912169,-0.0614669122616347,6.39420899365999,-5.22,0
-742,5474,5451,4326,,Topographic mapping.,3876,7.98,17.83,-92.29,-82.53,1,1,9603,205.435,-29.099,292.202,,,,,0
-743,6891,5451,4326,"Concatenation (via NAD27) of transformations 6888 and 1171. Accuracy not given, but accuracy of constituent transformations given as 9m and 10m respectively.",For military purposes.,3876,7.98,17.83,-92.29,-82.53,1,0,9603,205,96,-98,,,,,1
-744,15713,4684,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,3274,-0.69,7.08,72.81,73.69,1,0,9603,-133,-321,50,,,,,1
-745,6177,6135,4326,"Approximation at the +/- 1m level assuming that CIGD11 is equivalent to WGS 84.","Accuracy +/- 1m.",1063,17.58,20.68,-83.6,-78.72,1,0,9603,0,0,0,,,,,1
-746,4064,4046,4326,"Approximation at the +/- 1m level assuming that RGRDC 2005 is equivalent to WGS 84 within the accuracy of the transformation.",Accuracy 1m.,3613,-13.46,-3.41,11.79,29.81,1,0,9603,0,0,0,,,,,1
-747,15846,4706,4326,"Sometime referred to as ""Egypt 1907 to WGS 84"". However, application to WGS 84 coordinates of the reverse of this tfm results in Gulf of Suez S-650 TL, not Egypt 1907, position. Gulf of Suez S-650 TL and Egypt 1907 CRSs differ by some 20 metres.",Used for oil exploration by GUPCO.,2341,27.19,30.01,32.34,34.27,1,0,9603,-146.21,112.63,4.05,,,,,1
-748,15918,4214,4326,Provided by BGP to TOTAL in June 2006.,Geophysical exploration in Ordos basin. Accuracy stated as 1m within basin.,3466,35,39,107,110.01,1,0,9603,12.646,-155.176,-80.863,,,,,0
-749,15919,4214,4326,Derived via WGS 72BE. Original transformation derived in 1979 at 4 stations on Yellow Sea coast.,Geophysical exploration in Yellow Sea.,3469,31.23,37.4,119.23,125.06,1,0,9606,15.53,-113.82,-41.38,0,0,0.814,-0.38,0
-750,15920,4214,4326,"Derived via WGS 72BE. Original transformation derived by GSI in 1980-81. The GSI memo incorrectly gave the parameters as from WGS 72 to Beijing 1954, but it has been determined by the OGP that the memo should have stated from Beijing 1954 to WGS 72BE.",Geophysical exploration in South China Sea.,3470,18.31,22.89,110.13,116.76,1,0,9606,31.4,-144.3,-74.8,0,0,0.814,-0.38,0
-751,15921,4214,4326,Provided by BGP to ELF in 1994.,Geophysical exploration in Tarim basin. Accuracy stated as 1m within basin.,3507,37,41.99,77.45,88,1,0,9603,15.8,-154.4,-82.3,,,,,1
-752,15935,4214,4326,Concatenated via WGS 72BE. Recomputation by Shelltech in 1981 of SSB 1980 observation.,Geophysical exploration in Bei Bu basin. Accuracy stated as 1m within basin.,3561,17.81,21.69,107.15,110.17,1,0,9606,18,-136.8,-73.7,0,0,0.814,-0.38,0
-753,15936,4214,4326,Provided by Sinopec to TOTAL in January 2007.,Geophysical exploration in Ordos basin. Accuracy stated as 1m within basin.,3466,35,39,107,110.01,1,0,9603,11.911,-154.833,-80.079,,,,,0
-754,15875,4721,4326,Derived at 20 stations.,"For military purposes. Accuracy 5m, 3m and 2m in X, Y and Z axes.",3398,-19.22,-16.1,176.81,-179.77,1,0,9603,265.025,384.929,-194.046,,,,,1
-755,15876,4720,4326,"Approximation at the +/- 2m level assuming that Fiji 1986 is equivalent to WGS 72. Parameter values taken from WGS 72 to WGS 84 (1) (tfm code 1237).",tbc,1094,-20.81,-12.42,176.81,-178.15,1,0,9606,0,0,4.5,0,0,0.554,0.2263,1
-756,15877,4720,4326,"Suitable for GIS mapping purposes but not rigorous surveying. Very similar results may be obtained through Fiji 1986 to WGS 84 (1) (tfm code 15876).","Horizontal accuracy 2m, vertical accuracy approximately 40 metres..",3398,-19.22,-16.1,176.81,-179.77,1,0,9607,-35.173,136.571,-36.964,1.37,-0.842,-4.718,-1.537,0
-757,5599,5593,4326,,Approximation at the 1m level.,3889,54.33,54.83,10.66,12.01,1,0,9603,0,0,0,,,,,1
-758,15832,4687,4326,"Transformation is to original definition of WGS 84. It is consistent with later WGS 84 realisations G730, G873 and G1150 to no better than 1m.","Accuracy +/- 0.5 metre (to original definition of WGS 84 - see remarks).",1098,-31.24,-4.52,-158.13,-131.97,1,0,9607,0.072,-0.507,-0.245,0.0183,-0.0003,0.007,-0.0093,1
-759,15833,4687,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84.","Accuracy +/- 1 metre.",1098,-31.24,-4.52,-158.13,-131.97,1,0,9603,0,0,0,,,,,0
-760,1921,4636,4326,,"Accuracy +/- 10 metres.",2817,-66.78,-66.1,139.44,141.5,1,0,9603,365,194,166,,,,,1
-761,15772,4688,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from Fatu Iva 72 to RGPF (1) (tfm code 15760).","Accuracy +/- 2 metres.",3133,-10.6,-10.36,-138.75,-138.54,1,0,9607,347.103,1078.125,2623.922,33.8875,-70.6773,9.3943,186.074,1
-762,5236,5233,4326,Derived at 58 stations.,Accuracy 14m.,3310,5.86,9.88,79.64,81.95,1,0,9607,-0.293,766.95,87.713,-0.195704,-1.695068,-3.473016,-0.039338,1
-763,4077,4075,4326,"Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84. SREF98 is a regional realisation of ETRS89.","Accuracy +/- 1 metre.",3534,41.85,46.19,18.81,23.01,1,0,9603,0,0,0,,,,,1
-764,4835,4690,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from Tahiti 79 to RGPF (1) (tfm code 15756).","Accuracy +/- 1 metre.",3124,-17.93,-17.44,-149.7,-149.09,1,0,9607,221.525,152.948,176.768,2.3847,1.3896,0.877,11.4741,1
-765,1922,4637,4326,,"Accuracy +/- 10 metres.",2818,-67.13,-65.61,136,142,1,0,9603,325,154,172,,,,,1
-766,15797,4712,4326,Derived at 2 satellite stations.,For military purposes only. Accuracy 25m in each axis.,3182,-8.03,-7.83,-14.46,-14.24,1,0,9603,-205,107,53,,,,,1
-767,15769,4691,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from Moorea 87 to RGPF (1) (tfm code 15757).","Accuracy +/- 1 metre.",3125,-17.63,-17.41,-150,-149.73,1,0,9607,215.525,149.593,176.229,3.2624,1.692,1.1571,10.4773,1
-768,6142,4723,4326,"Parameter values are taken from GCGD59 to CIGD11 (1) (code 6136) assuming that CIGD11 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1m.,3185,19.21,19.41,-81.46,-81.04,1,0,9607,-179.483,-69.379,-27.584,7.862,-8.163,-6.042,-13.925,1
-769,15830,4723,4326,Determined from 6 satellite stations.,"Topographic survey. Accuracy +/- 1m.",3185,19.21,19.41,-81.46,-81.04,1,0,9603,67.8,106.1,138.8,,,,,0
-770,4066,4695,4326,"Parameter values taken from Katanga 1955 to RGRDC 2005 (1) (code 4065) assuming that RGRDC 2005 is equivalent to WGS 84 within the accuracy of the transformation.",Accuracy 1.5m.,3614,-12.01,-11.13,26.38,27.75,1,0,9603,-103.746,-9.614,-255.95,,,,,1
-771,15746,4693,4326,Derived in Tombak district in March 2005. Used for South Pars phase 11 and Pars LNG plants.,Petroleum Exploration and Production.,3141,27.63,27.81,52.09,52.26,1,0,9603,0,-0.15,0.68,,,,,1
-772,1441,4601,4326,,"?",1273,16.94,17.22,-61.95,-61.61,1,0,9603,-255,-15,71,,,,,1
-773,15811,4601,4326,Determined from 1 satellite station.,"Military mapping. Accuracy +/- 25m in each axis.",1273,16.94,17.22,-61.95,-61.61,1,0,9603,-270,13,62,,,,,0
-774,1442,4602,4326,,"?",3239,15.14,15.69,-61.55,-61.2,1,0,9603,725,685,536,,,,,1
-775,1443,4603,4326,,"?",3118,11.94,12.29,-61.84,-61.54,1,0,9603,72,213.7,93,,,,,1
-776,1444,4604,4326,Derived at 1 satellite station.,Accuracy 25m in each axis.,3279,16.62,16.87,-62.29,-62.08,1,0,9603,174,359,365,,,,,1
-777,1445,4605,4326,,"?",3297,17.06,17.46,-62.92,-62.5,1,0,9603,9,183,236,,,,,1
-778,15750,4605,4326,Derived at 2 stations.,"For military purposes. Accuracy 25m in each of X, Y and Z axes.",3297,17.06,17.46,-62.92,-62.5,1,0,9603,-7,215,225,,,,,0
-779,1446,4606,4326,,"?",3298,13.66,14.16,-61.13,-60.82,1,0,9603,-149,128,296,,,,,1
-780,1959,4607,4326,Derived at 4 points.,1m accuracy.,3300,12.54,13.44,-61.52,-61.07,1,0,9603,195.671,332.517,274.607,,,,,1
+575,1271,4293,4326,"Beware!  Source CRS uses GLM, tfm param in m. Example: Schwarzeck ?=19°35'46.952""S ?=20°41'50.649""E h=1185.99m; X=5623409.386 Y=2124618.003 Z=-2125847.632 GLM; X=5623485.84m Y=2124646.89m Z=-2125876.54m; WGS 84 X=5624101.48m Y=2124748.97m Z=-2126132.35m.","?",1169,-30.64,-16.95,8.24,25.27,1,0,9603,615.64,102.08,-255.81,,,,,0
+576,1286,4294,4326,Accuracy estimate not available.,For military purposes.,2354,-4.24,4.37,108.79,119.06,1,1,9603,-403,684,41,,,,,0
+577,1834,4294,4326,Accuracy estimate not available.,For military purposes.,2354,-4.24,4.37,108.79,119.06,1,1,9603,-403,684,41,,,,,0
+578,1835,4294,4326,,Oil exploration.,1360,-4.24,4.29,114.55,119.06,1,1,9603,-387.06,636.53,46.29,,,,,0
+579,1836,4294,4326,,Oil exploration.,2770,-0.07,4.29,116.96,119.06,1,1,9603,-403.4,681.12,46.56,,,,,0
+580,6900,4129,4326,Derived at 3 stations.,For military purposes. Accuracy 10m in each axis.,1329,-26.87,-19.84,31.29,35.65,1,0,9603,-132,-110,-335,,,,,1
+581,1227,4297,4326,Accuracy estimate not available.,For military purposes.,1149,-26.59,-11.69,42.53,51.03,1,0,9603,-189,-242,-91,,,,,1
+582,6873,4297,4326,Derived at 9 points throughout Madagascar. Adopted by OMV.,For applications with an accuracy of 3m.,1149,-26.59,-11.69,42.53,51.03,1,0,9603,-198.383,-240.517,-107.909,,,,,0
+583,1228,4298,4326,Derived at 8 stations.,"For military purposes. Accuracy 10m, 10m and 12m in X, Y and Z axes.",1362,0.85,7.67,109.31,119.61,1,0,9603,-679,669,-48,,,,,1
+584,1592,4298,4326,"Originally used by BSP offshore only, use extended to onshore in 2010.",Oil exploration and production.,1055,4.01,6.31,112.37,115.37,1,0,9603,-678,670,-48,,,,,0
+585,1615,4298,4326,"CARE! Erroneous GPS data was used in the derivation of these parameters. They produce a coordinate difference of 10m horizontally and 50m vertically compared to Timbalai 1948 to WGS 84 (2) (code 1592).",Topographic and engineering survey onshore.,2349,4.01,5.11,114.09,115.37,1,0,9603,-726.282,703.611,-48.999,,,,,0
+586,1852,4298,4326,"Derived by Racal Survey for SSB at 24 coastal stations (including Timbalai fundamental point and 6 other primary triangulation stations) between in Sabah (Kudat southwards) and Sarawak (Sibu northwards).",Oil exploration.,2780,1.56,7.67,109.31,117.31,1,0,9606,-533.4,669.2,-52.5,0,0,4.28,9.4,0
+587,5248,4298,4326,,Oil exploration.,1055,4.01,6.31,112.37,115.37,1,1,9607,-689.5937,623.84046,-65.93566,0.02331,-1.17094,0.80054,5.88536,0
+588,5249,4298,4326,"Parameter values taken from Timbalai 1948 to GDBD2009 (1) (code 5878) assuming that GDBD2009 is equivalent to WGS 84 within the accuracy of the transformation.",Oil exploration.,1055,4.01,6.31,112.37,115.37,1,0,9607,-689.5937,623.84046,-65.93566,0.02331,-1.17094,0.80054,5.88536,0
+589,6902,4298,4326,Derived at 9 stations.,"For military purposes. Accuracy 1m, 6m and 2m in X, Y and Z axes.",2349,4.01,5.11,114.09,115.37,1,0,9603,-679,667,-49,,,,,0
+590,1229,4299,4326,Derived at 7 stations.,For military purposes only. Accuracy 3m in each axis.,1305,51.39,55.43,-10.56,-5.34,1,1,9603,506,-122,611,,,,,0
+591,1641,4299,4326,"Parameter values from TM75 to ETRS89 (2) (code 1953). Assumes each pair of (i) TM65 and TM75, and (ii) ETRS89 and WGS 84, can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1305,51.39,55.43,-10.56,-5.34,1,0,9606,482.5,-130.6,564.6,-1.042,-0.214,-0.631,8.15,1
+592,1954,4300,4326,"Parameter values taken from TM65 to ETRS89 (2) (code 1953). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1305,51.39,55.43,-10.56,-5.34,1,0,9606,482.5,-130.6,564.6,-1.042,-0.214,-0.631,8.15,1
+593,1956,4300,4326,"Derived at 7 stations. TM75 is based on the geodetic datum of 1965 which should not be confused with the mapping adjustment of 1965 (TM65).",For military purposes only. Accuracy 3m in each axis.,1305,51.39,55.43,-10.56,-5.34,1,0,9603,506,-122,611,,,,,0
+594,1230,4301,4326,Derived at 31 stations.,"For military purposes only. Accuracy 20m, 5m and 20m in X, Y and Z axes.",2409,20.37,45.54,122.83,145.87,1,0,9603,-148,507,685,,,,,0
+595,1231,4301,4326,Derived at 16 stations.,"For military purposes only. Accuracy 8m, 5m and 8m in X, Y and Z axes.",3995,30.18,45.54,128.31,145.87,1,0,9603,-148,507,685,,,,,0
+596,1232,4301,4326,"Derived at 29 stations. Replaced by Tokyo to WGS 84 (5) (code 1305).","For military purposes only. Accuracy 8m, 5m and 8m in X, Y and Z axes.",3266,33.14,38.64,124.53,131.01,1,0,9603,-146,507,687,,,,,0
+597,1233,4301,4326,Derived at 3 stations.,"For military purposes only. Accuracy 20m, 5m and 20m in X, Y and Z axes.",2408,23.98,26.91,122.83,131.38,1,0,9603,-158,507,676,,,,,0
+598,1305,4301,4326,"Derived at 29 stations. Replaces Tokyo to WGS 84 (3) (code 1232).",For military purposes. Accuracy 2m in each axis.,3266,33.14,38.64,124.53,131.01,1,0,9603,-147,506,687,,,,,0
+599,15484,4301,4326,"Parameter values from Tokyo to JGD2000 (1) (code 15483). Assumes JGD2000 and WGS 84 can be considered the same to within the accuracy of the transformation.","Surveying, mapping and civil engineering purposes. Accuracy on main islands 9m.",3957,20.37,45.54,122.83,154.05,1,0,9603,-146.414,507.337,680.507,,,,,1
+600,1296,4302,4326,Derived in 1989 by ONI for Amoco.,Oil exploration.,1339,9.83,11.51,-62.09,-60,1,0,9603,-61.702,284.488,472.052,,,,,1
+601,10085,4302,4326,"Parameter values provided to EOG by Trinidad Ministry of Energy and Energy Industries. Used by EOG offshore Trinidad (including Pelican, Kiskadee and Ibis fields) since 1996.",Oil exploration.,1339,9.83,11.51,-62.09,-60,1,0,9603,-61,285.2,471.6,,,,,0
+602,1932,4644,4326,,"Accuracy better than +/- 1 metre.",2823,-22.37,-22.19,166.35,166.54,1,1,9606,-166.207,-154.777,254.831,-37.5444,7.7011,-10.2025,-30.8598,0
+603,15904,4644,4326,"Parameter values taken from NEA74 Noumea to RGNC91-93 (1) ( code 15886) assuming that RGNC91-93 is equivalent to WGS 84 to within the accuracy of the transformation.",Accuracy 1 metre.,2823,-22.37,-22.19,166.35,166.54,1,0,9603,-10.18,-350.43,291.37,,,,,1
+604,1294,4304,4326,Accuracy estimate not available.,For military purposes.,1365,31.99,37.14,-2.95,9.09,1,0,9603,-73,-247,227,,,,,1
+605,15815,4728,4326,Determined at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3873,27.58,29.3,-18.22,-13.37,1,0,9603,-307,-92,127,,,,,1
+606,1253,4307,4326,Derived at 3 stations.,For military purposes only. Accuracy 25m in each axis.,3213,18.97,37.14,-8.67,11.99,1,0,9603,-186,-93,310,,,,,0
+607,1255,4307,4326,"CAUTION: Source CRS described by DMA as from Voirol 1960. OGP believes that the data used in the derivation of these parameters contains a blunder. We recommend using transformation North Sahara 1959 to WGS84 (1) (code 1253). Derived at 2 stations.",For military purposes only. Accuracy 25m in each axis.,1365,31.99,37.14,-2.95,9.09,1,0,9603,-123,-206,219,,,,,0
+608,1815,4307,4326,Used by BP in District 3 and In Salah Gas.,Oil industry operations.,2598,25,32,1,3.3,1,0,9606,-152.9,43.8,358.3,2.714,1.386,-2.788,-6.743,0
+609,1816,4307,4326,"Derived at astro station central to concession. Significant and varying differences (>100m) at 4 neighbouring astro stations.",Oil industry operations.,2599,27.5,28.3,8.83,9.92,1,0,9603,-95.7,10.2,158.9,,,,,0
+610,1817,4307,4326,Derived at astro station Guerrara.,Oil industry operations.,2600,31.75,32.42,7.16,8,1,0,9603,-165.914,-70.607,305.009,,,,,0
+611,5630,4307,4326,"Derived at 1 station (L38).",Used by Total in Ahnet licence area.,3917,26.06,27.51,1.26,2.92,1,0,9603,-168.52,-72.05,304.3,,,,,0
+612,5660,4307,4326,Derived in 2006 at 45 points in north and central Algeria.,Accuracy at 75 common points better than 1m..,1026,18.97,38.8,-8.67,11.99,1,0,9606,-209.3622,-87.8162,404.6198,0.0046,3.4784,0.5805,-1.4547,1
+613,7442,4307,4326,"Derived at 1 astro station central to concession. Significant and varying differences (>100m) known to exist in neighbouring astro stations.",Oil industry operations.,4382,27.4,28.1,7.66,8.27,1,0,9603,-181.7,64.7,247.2,,,,,0
+614,15874,4307,4326,"Derived at 11 stations throughout blocks 317b, 319b, 321b and 322b. Network based on station P4 (horizontal) and benchmark RN51 (vertical) using EGM96 geoid height. Used by Statoil in Hassi Mouina.",Oil exploration and production. Accuracy 5m.,3402,29.25,31,0,1.25,1,0,9603,-169.559,-72.34,303.102,,,,,0
+615,1234,4309,4326,Accuracy estimate not available.,For military purposes.,3326,-35,-30.09,-58.49,-53.09,1,0,9603,-155,171,37,,,,,1
+616,5386,4309,4326,Derived at 11 stations during 1998 densification of Uruguay control based on SIRGAS 1995.,"Accuracy at stations used for derivation: 0.13 to 1.17m.",3326,-35,-30.09,-58.49,-53.09,1,0,9606,-124.45,183.74,44.64,-0.4384,0.5446,-0.9706,-2.1365,0
+617,6903,4310,4326,Derived at 7 stations.,For military purposes only. Accuracy 3m in each axis.,1207,10.64,16.7,-20.22,-11.36,1,0,9603,-30,190,89,,,,,1
+618,1235,4311,4326,Derived at 5 stations.,"For military purposes. Accuracy 5m, 5m and 8m in X, Y and Z axes.",1222,1.83,9.35,-58.08,-52.66,1,0,9603,-265,120,-358,,,,,1
+619,1194,4312,4326,May be taken as approximate transformation MGI to ETRS89 assuming ETRS89 is equivalent to WGS 84 within the accuracy of the transformation - see tfm code 1024. Information source gives scale as -2.388739 ppm.,Provincial GIS and other applications to an accuracy of 0.5 metres.,1543,46.64,47.84,13.58,16.17,1,0,9607,601.705,84.263,485.227,-4.7354,-1.3145,-5.393,-2.3887,0
+620,1306,4312,4326,Accuracy estimate not available.,For military purposes only.,2370,40.85,46.88,13.38,23.04,1,1,9603,682,-203,480,,,,,0
+621,1471,4312,4326,,For applications to an accuracy of 1.5 metres.,1037,46.4,49.02,9.53,17.17,1,1,9606,-577.326,-90.129,-463.919,-5.136599,-1.474,-5.297044,-2.4232,0
+622,1618,4312,4326,"Same transformation parameters used for MGI to ETRS89 (1) (code 1619).",For applications to an accuracy of 1.5 metres.,1037,46.4,49.02,9.53,17.17,1,0,9606,577.326,90.129,463.919,5.137,1.474,5.297,2.4232,1
+623,1621,4312,4326,"Parameter values from MGI to ETRS89 (2) (code 1620). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1076,41.62,46.54,13,19.43,1,1,9606,551.7,162.9,467.9,6.04,1.96,-11.38,-4.82,0
+624,1786,4312,4326,"Parameter values from MGI to ETRS89 (3) (code 1785). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1212,45.42,46.88,13.38,16.61,1,1,9606,426.9,142.6,460.1,4.91,4.49,-12.42,17.1,0
+625,1794,4312,4326,"For more accurate transformation see MGI to WGS 84 (7) (code 1795).",Oil industry,3536,41.79,43.56,18.45,20.38,1,1,9603,695.5,-216.6,491.1,,,,,0
+626,15982,4312,4326,"Parameter values from MGI to Slovenia 1996 (1) (code 15981). Assumes Slovenia 1996 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1212,45.42,46.88,13.38,16.61,1,1,9607,409.545,72.164,486.872,-3.085957,-5.46911,11.020289,17.919665,0
+627,1609,4313,4326,"Scale difference is given by information source as 0.999999. Given in this record in ppm to assist application usage. Very similar parameter values (to slightly less precision) used for BD72 to ETRS89: see code 1652.",For applications to an accuracy of 1 metre.,1347,49.5,51.51,2.5,6.4,1,0,9607,-99.059,53.322,-112.486,-0.419,0.83,-1.885,-1,0
+628,1610,4313,4326,,For applications to an accuracy of 5 metres.,1347,49.5,51.51,2.5,6.4,1,0,9603,-125.8,79.9,-100.5,,,,,0
+629,15749,4313,4326,"Parameter values from BD72 to ETRS89 (2) (code 15748). Scale difference is given by information source as 1.0000012747. Given in this record in ppm to assist application usage.",For applications to an accuracy of 0.5 metre.,1044,49.5,51.88,2.23,6.4,1,1,9607,-106.8686,52.2978,-103.7239,-0.3366,0.457,-1.8422,1.2747,0
+630,15929,4313,4326,"Parameter values from BD72 to ETRS89 (2) (code 15928). Scale difference is given by information source as -1.0000012747. Given in this record in ppm to assist application usage.",For applications to an accuracy of 0.5 metre.,1347,49.5,51.51,2.5,6.4,1,0,9607,-106.8686,52.2978,-103.7239,-0.3366,0.457,-1.8422,-1.2747,1
+631,1673,4314,4326,"Parameter values from DHDN to ETRS89 (1) (code 1309) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaced by DHDN to WGS 84 (2) (tfm code 1777).",For applications with an accuracy at 5 m level.,2326,47.27,55.09,5.87,13.84,1,0,9607,582,105,414,-1.04,-0.35,3.08,8.3,0
+632,1777,4314,4326,"Parameter values from DHDN to ETRS89 (2) (code 1776) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaces DHDN to WGS 84 (1) (tfm code 1673).",For applications with an accuracy at 3 m level,2326,47.27,55.09,5.87,13.84,1,0,9606,598.1,73.7,418.2,0.202,0.045,-2.455,6.7,1
+633,15869,4314,4326,"Parameter values taken from RD/83 to ETRS89 (1) (tfm code 15868) assuming that within the accuracy of the transformation ETRS89 is equivalent to WGS 84 and RD/83 is equivalent to DHDN.",For applications with an accuracy at 2m level,1343,50.2,54.74,9.92,15.04,1,0,9606,612.4,77,440.2,-0.054,0.057,-2.797,2.55,0
+634,1517,4315,4326,,"?",3257,7.19,12.68,-15.13,-7.65,1,0,9603,-23,259,-9,,,,,1
+635,1789,4316,4326,"Parameter values taken from Pulkovo 1942 to WGS 84 (9) (code 1293) assuming that","?",1197,43.44,48.27,20.26,31.41,1,1,9603,103.25,-100.4,-307.19,,,,,0
+636,1995,4316,4326,,Oil exploration,3295,43.62,48.27,20.26,29.74,1,0,9603,103.25,-100.4,-307.19,,,,,1
+637,1097,4317,4326,"Parameter values taken from Pulkovo 1942 to WGS 84 (9) (code 1293) assuming that Pulkovo 1942 in Romania is equivalent to Dealul Piscului 1970.","Accuracy 3m, 5m and 3m in X, Y and Z axes.",1197,43.44,48.27,20.26,31.41,1,1,9603,28,-121,-77,,,,,0
+638,1996,4317,4326,,Oil exploration,1197,43.44,48.27,20.26,31.41,1,1,9603,44.107,-116.147,-54.648,,,,,0
+639,1060,4318,4326,,1 metre accuracy.,3267,28.53,30.09,46.54,48.48,1,0,9603,-3.2,-5.7,2.8,,,,,1
+640,1061,4319,4326,,For applications requiring an accuracy of better than 1 metre.,1310,29.17,29.45,47.78,48.16,1,0,9603,-20.8,11.3,2.4,,,,,1
+641,1062,4319,4326,,For applications requiring an accuracy of better than 1 metre.,1310,29.17,29.45,47.78,48.16,1,0,9607,226.702,-193.337,-35.371,2.229,4.391,-9.238,0.9798,0
+642,6910,6881,4326,Derivation not given.,For military purposes. Accuracy not specified.,1340,12.54,19,43.37,53.14,1,0,9603,-24,-203,268,,,,,1
+643,1237,4322,4326,,For scientific purposes.,1262,-90,90,-180,180,1,0,9606,0,0,4.5,0,0,0.554,0.2263,1
+644,1238,4322,4326,,For scientific purposes.,1262,-90,90,-180,180,1,0,9606,0,0,4.5,0,0,0.554,0.219,0
+645,6912,6883,4326,Derived at 6 stations.,"For military purposes. Accuracy 5m, 17m and 38m in X, Y and Z axes.",4220,3.14,3.82,8.37,9.02,1,0,9603,-235,-110,393,,,,,1
+646,1240,4324,4326,,Geodesy.,2346,-90,90,-180,180,1,0,9606,0,0,1.9,0,0,0.814,-0.38,1
+647,5521,4646,4326,,For military purposes. Accuracy unknown.,2807,-11.99,-11.31,43.16,43.55,1,0,9603,-963,510,-359,,,,,1
+648,15822,4732,4326,Derived at 10 satellite stations.,"For military and topographic mapping. Accuracy +/-3 m in each axis.",3191,8.66,19.38,162.27,167.82,1,0,9603,102,52,-38,,,,,1
+649,5327,5324,4326,For many purposes ISN2004 can be considered to be coincident with WGS 84.,"Approximation at the +/- 1m level assuming that ISN2004 is equivalent to WGS 84.",1120,59.96,69.59,-30.87,-5.55,1,0,9603,0,0,0,,,,,1
+650,3817,3819,4326,Horizontal coordinates of 66 points of the National Geodetic Network were used to compute this transformation.,GIS and topographic survey.,1119,45.74,48.58,16.11,22.9,1,0,9607,595.48,121.69,515.35,-4.115,2.9383,-0.853,-3.408,1
+651,6914,6892,4326,"Derived by UK DOS at 10 stations in 1998, RMS ±0.314m. Also published by NGA in Standard 0036 v1.0.0 of 2014-07-08 and in GeoTrans v3.4 software with parameter values rounded to integer.",Topographic mapping.,4183,-4.86,-3.66,55.15,56.01,1,0,9603,-43.685,-179.785,-267.721,,,,,1
+652,6926,6892,4326,"Derived by UKHO at 13 stations in 1999, RMS ±0.271m.",Hydrographic survey and charting.,4183,-4.86,-3.66,55.15,56.01,1,0,9606,-76.269,-16.683,68.562,-6.275,10.536,-4.286,-13.686,0
+653,1920,4645,4326,,"Accuracy +/- 1 metre.",1174,-26.45,-14.83,156.25,174.28,1,1,9603,0,0,0,,,,,0
+654,6913,6894,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,3250,13.05,13.83,-16.88,-13.79,1,0,9603,-63,176,185,,,,,1
+655,15823,4733,4326,Derived at 2 satellite stations.,"For military and topographic mapping. Accuracy +/-25m in each axis.",3190,19.22,19.38,166.55,166.72,1,0,9603,276,-57,149,,,,,1
+656,3830,3824,4326,"Approximation at the +/- 1m level assuming that TWD97 is equivalent to WGS 84.","Accuracy +/- 1m.",1228,17.36,26.96,114.32,123.61,1,0,9603,0,0,0,,,,,1
+657,7443,7373,4326,"Approximation at the +/- 1m level assuming that ONG14 is equivalent to WGS 84. See transformation code 7377 for authoritative values.",Geodesy.,1183,14.33,26.74,51.99,63.38,1,0,9603,0,0,0,,,,,1
+658,5376,5365,4326,,Accuracy 1m.,1074,2.15,11.77,-90.45,-81.43,1,0,9603,0,0,0,,,,,1
+659,15808,4724,4326,Derived at 2 satellite stations.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3189,-7.49,-7.18,72.3,72.55,1,0,9603,208,-435,-229,,,,,1
+660,5377,5371,4326,,Accuracy 1m.,1186,5,12.51,-84.32,-77.04,1,0,9603,0,0,0,,,,,1
+661,5378,5373,4326,,Accuracy 1m.,1189,-21.05,-0.03,-84.68,-68.67,1,0,9603,0,0,0,,,,,1
+662,15812,4736,4326,,"Scientific mapping. Accuracy +/- 20m in each axis.",3204,-63.08,-62.82,-60.89,-60.35,1,0,9603,260,12,-147,,,,,1
+663,15821,4731,4326,Derived at 1 satellite station.,"For military and topographic mapping. Accuracy +/-25m in each axis.",3195,-18.32,-17.25,177.19,178.75,1,1,9603,51,391,-36,,,,,0
+664,15795,4707,4326,Derived at 1 satellite station. Same transformation parameter values related to same datum area given in original 1987 DMA TR8350.2 edition for Sorol Atoll.,For military purposes only. Accuracy 25m in each axis.,3181,23.69,23.93,-166.36,-166.03,1,0,9603,114,-116,-333,,,,,1
+665,5384,5381,4326,,Accuracy 1m.,1247,-37.77,-30.09,-58.49,-50.01,1,0,9603,0,0,0,,,,,1
+666,15813,4722,4326,Determined from 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3529,-54.95,-53.93,-38.08,-35.74,1,0,9603,-794,119,-298,,,,,1
+667,5227,5228,4326,"Parameter values from S-JTSK/05 to ETRS89 (1) (code 5226). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaces tfm code 1622.",For applications to an accuracy of 1 metre.,1079,48.58,51.06,12.09,18.86,1,0,9607,572.213,85.334,461.94,-4.9732,-1.529,-5.2484,3.5378,1
+668,15771,4692,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from Maupiti 83 to RGPF (1) (tfm code 15759).","Accuracy +/- 1 metre.",3126,-16.57,-16.34,-152.39,-152.14,1,0,9603,217.037,86.959,23.956,,,,,1
+669,15973,4055,4326,"Executes change of sphere/ellipsoid",Web mapping. Accuracy may be no better than 800 metres.,1262,-90,90,-180,180,1,1,9603,0,0,0,,,,,0
+670,5395,5393,4326,,Accuracy 1m.,1087,9.97,14.44,-91.43,-87.65,1,0,9603,0,0,0,,,,,1
+671,15816,4734,4326,Determined at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3184,-40.42,-37,-12.76,-9.8,1,0,9603,-632,438,-609,,,,,1
+672,1585,4227,4326,,"?",1227,32.31,37.3,34.96,42.38,1,1,9603,-177.5,14.1,237.6,,,,,0
+673,1586,4227,4326,"Derived in 1995 by CGG for Al Furat Petroleum Company. Can be approximated using geocentric translations of dX=-174.3m, dY=+14.1m, dZ=+237.6m.",Oil exploration.,2327,35.33,35.9,39.15,40.41,1,0,9606,-175.09,1.218,238.831,-0.047,0.019,0.808,0.1698,0
+674,1587,4227,4326,Derived at four stations by Topnav in 1997.,Oil exploration.,2328,35.79,36.5,40.5,41.39,1,0,9603,-191.77,15.01,235.07,,,,,0
+675,15741,4227,4326,Derived by Elf in 1991 from tfm code 1584 concatenated with a tfm from WGS72BE to WGS84.,Oil exploration. Accuracy 5m.,2329,34.49,35.9,39.3,40.81,1,0,9603,-187.5,14.1,237.6,,,,,0
+676,15742,4227,4326,Derived for 1998 Omar seismic survey and used in 2000 for El Isba seismic survey.,Oil exploration. Accuracy 5m.,3314,32.31,37.3,35.61,42.38,1,0,9603,-190.421,8.532,238.69,,,,,1
+677,15743,4227,4326,"Derived 2005 at 5 triangulation stations and using (EGM96 geoid model +1.15m). Used by Total/DEZPC for Jafra and Mazraa seismic surveys. Can be approximated using geocentric translations of dX=-190.6m, dY=+8.8m, dZ=+239.6m.",Oil exploration. Accuracy 0.5m.,2329,34.49,35.9,39.3,40.81,1,0,9606,-83.58,-397.54,458.78,-17.595,-2.847,4.256,3.225,0
+678,5261,5252,4326,,"Approximation at the +/- 1m level as both TUREF and WGS 84 are realisations of ITRS.",1237,34.42,43.45,25.62,44.83,1,0,9603,0,0,0,,,,,1
+679,1925,4639,4326,,"Accuracy +/- 10 metres.",2815,-13.41,-13.16,-176.25,-176.07,1,1,9603,252,-132,-125,,,,,0
+680,15847,4639,4326,"Replaces information from 2001 (tfm code 1925).","Accuracy +/- 10 metres.",2815,-13.41,-13.16,-176.25,-176.07,1,0,9603,253,-132,-127,,,,,1
+681,15801,4714,4326,Derived at 3 satellite stations.,"Military and topographic mapping; Accuracy +/- 20 m in each axis",3193,-20.31,-17.37,168.09,169.95,1,0,9603,-127,-769,472,,,,,1
+682,15880,4749,4326,,"Accuracy +/- 1 metre.",1174,-26.45,-14.83,156.25,174.28,1,0,9603,0,0,0,,,,,1
+683,15802,4715,4326,No accuracy estimate available.,Military and scientific mapping.,3205,-77.94,-77.17,165.73,167.43,1,0,9603,-104,-129,239,,,,,1
+684,1994,4657,4326,,Low accuracy applications.,3262,63.34,66.59,-24.66,-13.38,1,0,9603,-28,199,5,,,,,1
+685,5351,5340,4326,,Approximation at the sub meter level.,1033,-58.41,-21.78,-73.59,-52.63,1,0,9603,0,0,0,,,,,1
+686,5078,4743,4326,"Parameter values from Karbala 1979 to IGRS (1) (tfm code 5077) assuming that IGRS is equivalent to WGS 84 within the accuracy of the transformation. Replaces Karbala 1979 to WGS 84 (1) (tfm code 15872).",Accuracy 1m.,3625,29.06,37.39,38.79,48.61,1,0,9603,70.995,-335.916,262.898,,,,,1
+687,15872,4743,4326,"Derived from shifts in UTM rectangular coordinates for one point in Basra area provided by Iraq National Oil Exploration Company. Replaced by Karbala 1979 to WGS 84 (2) (tfm code 5078).",Oil exploration.,3397,29.87,31.09,46.46,48.61,1,0,9603,84.1,-320.1,218.7,,,,,0
+688,1951,4658,4326,"Derived at 6 stations. Replaced by Hjorsey 1955 to WGS 84 (2) (code 6909).","Accuracy 3m, 3m and 5m in X, Y and Z axes.",3262,63.34,66.59,-24.66,-13.38,1,0,9603,-73,46,-86,,,,,0
+689,6909,4658,4326,"Derived at 16 stations. Replaces Hjorsey 1955 to WGS 84 (1) (code 1951).","Accuracy 3m, 3m and 6m in X, Y and Z axes.",3262,63.34,66.59,-24.66,-13.38,1,0,9603,-73,47,-83,,,,,1
+690,6373,6365,4326,,Accuracy 1m.,1160,12.1,32.72,-122.19,-84.64,1,0,9603,0,0,0,,,,,1
+691,3894,3889,4326,"Approximation at the +/- 1m level assuming that IGRS is equivalent to WGS 84 within the accuracy of the transformation.",Accuracy 1m.,1124,29.06,37.39,38.79,48.75,1,0,9603,0,0,0,,,,,1
+692,1952,4659,4326,For many purposes ISN93 can be considered to be coincident with WGS 84.,"Approximation at the +/- 1m level assuming that ISN93 is equivalent to WGS 84.",1120,59.96,69.59,-30.87,-5.55,1,0,9603,0,0,0,,,,,1
+693,1957,4660,4326,Derived at 3 stations. Residuals under 1m.,For applications to an accuracy of 1 metre.,2869,70.75,71.24,-9.17,-7.87,1,0,9606,982.6087,552.753,-540.873,6.6816266,-31.6114924,-19.84816,16.805,1
+694,1958,4661,4326,,LKS92 is a realisation of ETRS89 coincident to WGS84 within 1 metre. This transformation has an accuracy equal to the coincidence figure.,1139,55.67,58.09,19.06,28.24,1,0,9603,0,0,0,,,,,1
+695,15849,4213,4326,"Used by Elf / CGG between December 1991 and March 1992. Probably derived from results of concatenated tfm Beduaram to WGS 84 (1) (code 8634).",Oil exploration.,2771,12.8,16.7,7.81,14.9,1,0,9603,-106,-87,188,,,,,1
+696,15803,4716,4326,Derived at 4 satellite stations.,"Military and topographic mapping. Accuracy +/- 15 m in each axis.",3196,-4.76,-2.68,-174.6,-170.66,1,0,9603,298,-304,-375,,,,,1
+697,3915,3906,4326,"Parameter values from MGI 1901 to ETRS89 (3) (code 3914). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1212,45.42,46.88,13.38,16.61,1,0,9606,426.9,142.6,460.1,4.91,4.49,-12.42,17.1,0
+698,3917,3906,4326,"Parameter values from MGI 1901 to Slovenia 1996 (1) (code 3916). Assumes Slovenia 1996 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1212,45.42,46.88,13.38,16.61,1,0,9607,409.545,72.164,486.872,-3.085957,-5.46911,11.020289,17.919665,0
+699,3962,3906,4326,Accuracy estimate not available from information source but established empirically by OGP.,For military purposes only.,2370,40.85,46.88,13.38,23.04,1,0,9603,682,-203,480,,,,,1
+700,3964,3906,4326,"Parameter values from MGI 1901 to ETRS89 (2) (code 3963). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,3234,42.34,46.54,13.43,19.43,1,0,9606,551.7,162.9,467.9,6.04,1.96,-11.38,-4.82,0
+701,3965,3906,4326,,Oil industry,3536,41.79,43.56,18.45,20.38,1,0,9603,695.5,-216.6,491.1,,,,,0
+702,6206,3906,4326,Derived at 13 stations.,"1m accuracy. Residuals generally less than +/- 1m horizontally and vertically.",1148,40.85,42.36,20.45,23.04,1,0,9607,521.748,229.489,590.921,-4.029,-4.488,15.521,-9.78,0
+703,15879,4747,4326,"Approximation at the +/- 1m level assuming that GR96 is equivalent to WGS 84 within the accuracy of the transformation.","For applications with an accuracy of +/- 1m.",1107,56.38,87.03,-75,8.12,1,0,9603,0,0,0,,,,,1
+704,1962,4662,4326,Withdrawn by information source and replaced by improved information from local authority - see tfm code 15903.,"Accuracy +/- 10 metres.",2822,-22.45,-20.03,163.92,167.09,1,0,9603,-13,-348,292,,,,,0
+705,1963,4662,4326,Withdrawn by information source and replaced by improved information - see tfm code 15903.,"Accuracy better than +/- 1 metre.",2822,-22.45,-20.03,163.92,167.09,1,0,9606,97.295,-263.247,310.882,-1.5999,0.8386,3.1409,13.3259,0
+706,15903,4662,4326,"Parameter values taken from IGN72 Grande Terre to RGNC91-93 (1) ( code 15882) assuming that RGNC91-93 is equivalent to WGS 84 to within the accuracy of the transformation.","Accuracy +/- 2 metres.",2822,-22.45,-20.03,163.92,167.09,1,0,9603,-11.64,-348.6,291.98,,,,,1
+707,15878,4748,4326,"Parameter values taken from Viti Levu 1912 to WGS 84 (1) (tfm code 15897). Approximation at the +/- 50m level assuming that CRS 4748 is equivalent to CRS 4752 within the transformation accuracy. Source CRSs 4748 and 4752 are independent but connected.","For applications with an accuracy of +/-50m.",3401,-17.07,-16.1,178.42,-179.77,1,0,9603,51,391,-36,,,,,1
+708,1966,4663,4326,Derived at Forte de Sao Tiago.,For low resolution applications.,2870,32.58,33.15,-17.31,-16.23,1,0,9603,-502.862,-247.438,312.724,,,,,1
+709,1967,4663,4326,,For medium resolution applications.,2870,32.58,33.15,-17.31,-16.23,1,0,9607,-210.502,-66.902,-48.476,-2.094,15.067,5.817,0.485,0
+710,6911,6882,4326,Derivation not given.,For military purposes. Accuracy not specified.,3269,33.06,34.65,35.04,36.63,1,0,9603,-183,-15,273,,,,,1
+711,15805,4718,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3198,-8.86,-7.52,156.44,158.2,1,0,9603,230,-199,-752,,,,,1
+712,15807,4718,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3197,-9.98,-9.2,159.55,160.88,1,0,9603,252,-209,-751,,,,,0
+713,1968,4664,4326,Calculated in 2001.,For low resolution applications.,2871,37.65,37.96,-25.92,-25.08,1,0,9603,-204.633,140.216,55.199,,,,,0
+714,1969,4664,4326,Calculated in 2001.,For medium resolution applications.,2871,37.65,37.96,-25.92,-25.08,1,0,9607,-211.939,137.626,58.3,0.089,-0.251,-0.079,0.384,0
+715,1970,4664,4326,Mean for all islands in group.,For low resolution applications.,1345,36.87,37.96,-25.92,-24.62,1,0,9603,-204.619,140.176,55.226,,,,,1
+716,1971,4664,4326,Mean for all islands in group.,For medium resolution applications.,1345,36.87,37.96,-25.92,-24.62,1,0,9607,-208.719,129.685,52.092,0.195,0.014,-0.327,0.198,0
+717,15881,4750,4326,"Parameter values taken from ST87 Ouvea to RGNC91-93 (1) ( code 15885) assuming that RGNC91-93 is equivalent to WGS 84 to within the accuracy of the transformation.","Accuracy better than +/- 1 metre.",2813,-20.77,-20.34,166.44,166.71,1,0,9603,-56.263,16.136,-22.856,,,,,1
+718,1972,4665,4326,,For low resolution applications.,2872,38.57,38.86,-27.44,-26.97,1,0,9603,-106.301,166.27,-37.916,,,,,0
+719,1973,4665,4326,,For medium resolution applications.,2872,38.57,38.86,-27.44,-26.97,1,0,9607,-105.854,165.589,-38.312,0.003,0.026,-0.024,-0.048,0
+720,1974,4665,4326,,For low resolution applications.,2873,38.46,38.7,-28.9,-28.54,1,0,9603,-106.248,166.244,-37.845,,,,,0
+721,1975,4665,4326,,For medium resolution applications.,2873,38.46,38.7,-28.9,-28.54,1,0,9607,-104,162.924,-38.882,0.075,0.071,-0.051,-0.338,0
+722,1976,4665,4326,,For low resolution applications.,2874,38.32,38.61,-28.61,-27.98,1,0,9603,-106.044,166.655,-37.876,,,,,0
+723,1977,4665,4326,,For medium resolution applications.,2874,38.32,38.61,-28.61,-27.98,1,0,9607,-95.323,166.098,-69.942,0.215,1.031,-0.047,1.922,0
+724,1978,4665,4326,,For low resolution applications.,2875,38.48,38.8,-28.37,-27.71,1,0,9603,-106.253,166.239,-37.854,,,,,0
+725,1979,4665,4326,,For medium resolution applications.,2875,38.48,38.8,-28.37,-27.71,1,0,9607,-100.306,161.246,-48.761,0.192,0.385,-0.076,0.131,0
+726,1980,4665,4326,Mean for all islands in group.,For low resolution applications.,1301,38.32,39.14,-28.9,-26.97,1,0,9603,-106.226,166.366,-37.893,,,,,1
+727,1981,4665,4326,Mean for all islands in group.,For medium resolution applications.,1301,38.32,39.14,-28.9,-26.97,1,0,9607,-103.088,162.481,-28.276,-0.167,-0.082,-0.168,-1.504,0
+728,1986,4666,4326,May be taken as a transformation from Lisbon 1890 to ETRS89 - see tfm code 5039.,For low resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9603,508.088,-191.042,565.223,,,,,1
+729,1990,4666,4326,,For medium resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9607,631.392,-66.551,481.442,-1.09,4.445,4.487,-4.43,0
+730,15804,4717,4326,Derived at 19 satellite stations.,"US space and military operations. Accuracy +/- 3 m in each axis.",3206,20.86,30.83,-82.33,-72.68,1,0,9603,-2,151,181,,,,,1
+731,5267,5264,4326,DRUKREF 03 and WGS 84 are both realisations of ITRS.,For applications to an accuracy of 1 metre.,1048,26.7,28.33,88.75,92.12,1,0,9603,0,0,0,,,,,1
+732,1993,4667,4326,For all practical purposes this transformation is exact.,Boundary demarcation.,2876,29.06,30.32,46.36,48.61,1,0,9603,0,0,0,,,,,1
+733,6895,4752,4326,"Derived at 9 stations. Replaces Viti Levu 1912 to WGS 84 (1) (code 15897).","For military and topographic mapping. Accuracy +/-3m in each axis.",3195,-18.32,-17.25,177.19,178.75,1,0,9603,98,390,-22,,,,,1
+734,15897,4752,4326,"Derived at 1 satellite station. Replaced by Viti Levu 1912 to WGS 84 (2) (code 6895).","For military and topographic mapping. Accuracy +/-25m in each axis.",3195,-18.32,-17.25,177.19,178.75,1,0,9603,51,391,-36,,,,,0
+735,5470,5451,4326,"Parameter values taken from Ocotepeque to CR05 (1) (tfm code 6890) assuming that CR05 is equivalent to WGS 84 within the accuracy of the transformation.",Topographic mapping.,3232,7.98,11.22,-85.97,-82.53,1,0,9603,213.11,9.37,-74.95,,,,,0
+736,5473,5451,4326,"Rotations in original source given in radians are equivalent to Rx = 2.35"", Ry = -0.06"", Rz = 6.39"".",Topographic mapping.,3232,7.98,11.22,-85.97,-82.53,1,1,9607,213.116,9.358,-74.946,2.351,-0.06147,6.39,-5.22,0
+737,5474,5451,4326,,Topographic mapping.,3876,7.98,17.83,-92.29,-82.53,1,1,9603,205.435,-29.099,292.202,,,,,0
+738,6891,5451,4326,"Concatenation (via NAD27) of transformations 6888 and 1171. Accuracy not given, but accuracy of constituent transformations given as 9m and 10m respectively.",For military purposes.,3876,7.98,17.83,-92.29,-82.53,1,0,9603,205,96,-98,,,,,1
+739,15752,4668,4326,Derived at 22 stations.,For military purposes. Accuracy 3m in each axis.,1297,34.88,71.21,-10.56,31.59,1,0,9603,-86,-98,-119,,,,,1
+740,15810,4735,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3192,5.21,5.43,162.85,163.1,1,0,9603,647,1777,-1124,,,,,1
+741,6701,5246,4326,"Approximation at the +/- 1m level assuming that GDBD2009 is equivalent to WGS 84 within the accuracy of the transformation.",Accuracy 1m.,1055,4.01,6.31,112.37,115.37,1,0,9603,0,0,0,,,,,1
+742,4477,4463,4326,"Approximation at the +/- 1m level assuming that RGSPM06 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1220,43.41,47.37,-57.1,-55.9,1,0,9603,0,0,0,,,,,1
+743,5501,5489,4326,"Approximation at the +/- 1m level assuming that RGAF09 is equivalent to WGS 84 within the accuracy of the transformation.","Accuracy +/- 1 metre.",2824,14.08,18.54,-63.66,-57.52,1,0,9603,0,0,0,,,,,1
+744,15912,4755,4326,"Approximation at the +/- 1m level assuming that DGN95 is equivalent to WGS 84 within the accuracy of the transformation.",Accuracy 1 metre.,1122,-13.25,7.79,92.01,141.46,1,0,9603,0,0,0,,,,,1
+745,1555,4158,4326,Derived in 1989 by ONI for Amoco.,Oil exploration.,3143,9.99,10.9,-61.97,-60.86,1,0,9603,-0.465,372.095,171.736,,,,,1
+746,1556,4158,4326,Described by NIMA as Naparima to WGS 84. In Trinidad the source CRS is better known as Naparima 1955. EPSG has duplicated the tfm using the alternative source CRSs. See also tfm code 1307.,For military purposes only. Accuracy given by NIMA 15m in each axis. EPSG believes there is an 8-10m blunder in dX.,3143,9.99,10.9,-61.97,-60.86,1,0,9603,-2,374,172,,,,,0
+747,4476,4470,4326,"Approximation at the +/- 1m level assuming that RGM04 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1159,-14.49,-11.33,43.68,46.7,1,0,9603,0,0,0,,,,,1
+748,5194,4756,4326,Used by Total in Mekong delta.,Academic research not officially adopted.,3770,9.34,11.03,104.25,107.11,1,0,9607,-192.873,-39.382,-111.202,0.00205,0.0005,-0.00335,0.0188,0
+749,6960,4756,4326,,Academic research not officially adopted.,3328,8.5,23.33,102.14,109.52,1,0,9607,-191.90441429,-39.30318279,-111.45032835,-0.00928836,0.01975479,-0.00427372,0.252906278,1
+750,1931,4643,4326,,"Accuracy better than +/- 1 metre.",2821,-19.85,-19.5,163.54,163.75,1,0,9606,-480.26,-438.32,-643.429,16.3119,20.1721,-4.0349,-111.7002,1
+751,4290,4475,4326,"Parameter values taken from Cadastre 1997 to RGM04 (1) (transformation code 4478) assuming that RGM04 is coincident with WGS 84 within the accuracy of the transformation.","Accuracy +/- 1 metre.",3340,-13.05,-12.61,44.98,45.35,1,0,9603,-381.788,-57.501,-256.673,,,,,1
+752,5374,5354,4326,,Accuracy 1m.,1049,-22.91,-9.67,-69.66,-57.52,1,0,9603,0,0,0,,,,,1
+753,15787,4701,4326,Derived by Topnav in 1991 at station TSH 85.,Oil exploration. Accuracy 5m.,3171,-6.04,-4.28,12.17,16.28,1,0,9603,-79.9,-158,-168.9,,,,,1
+754,4832,4483,4326,,Accuracy 1m.,1160,12.1,32.72,-122.19,-84.64,1,0,9603,0,0,0,,,,,1
+755,1917,4633,4326,Withdrawn by information source and replaced by improved information from local authority - see tfm code 15902.,"Accuracy +/- 10 metres.",2814,-21.24,-20.62,166.98,167.52,1,0,9603,336,223,-231,,,,,0
+756,1927,4633,4326,Withdrawn by information source and replaced by improved information - see tfm code 15902.,"Accuracy better than +/- 1 metre.",2814,-21.24,-20.62,166.98,167.52,1,0,9606,137.092,131.66,91.475,-1.9436,-11.5993,-4.3321,-7.4824,0
+757,15902,4633,4326,"Parameter values taken from IGN56 Lifou to RGNC91-93 (1) ( code 15883) assuming that RGNC91-93 is equivalent to WGS 84 to within the accuracy of the transformation.",Accuracy 1 metre.,2814,-21.24,-20.62,166.98,167.52,1,0,9603,335.47,222.58,-230.94,,,,,1
+758,15925,4758,4326,,For all practical purposes JAD2001 can be considered to be coincident with WGS 84.,1128,14.08,19.36,-80.6,-74.51,1,0,9603,0,0,0,,,,,1
+759,6711,6706,4326,"Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84. RDN2008 is a regional realisation of ETRS89.","Accuracy +/- 1 metre.",1127,34.76,47.1,5.93,18.99,1,0,9603,0,0,0,,,,,1
+760,15845,4161,4326,Transformation parameter precision given to millimetres in information source but due to accuracy rounded to nearest decimetre for EPSG database.,Geodetic surveying within the oil industry. Accuracy 25 m.,1265,-46.7,-45.19,-69.5,-67.1,1,0,9603,27.5,14,186.4,,,,,1
+761,15931,4759,4326,"Approximation at the +/- 1m level assuming that NAD83(NSRS2007) is equivalent to WGS 84 within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1511,14.92,74.71,167.65,-63.88,1,0,9603,0,0,0,,,,,1
+762,1540,4163,4326,,Accuracy better than 1 metre.,1257,8.95,19,41.08,57.96,1,0,9603,0,0,0,,,,,1
+763,4905,5013,4326,,PTRA08 and WGS 84 are realisations of ITRS coincident to within 1 metre. This transformation has an accuracy equal to the coincidence figure.,3670,29.24,43.07,-35.58,-12.48,1,0,9603,0,0,0,,,,,1
+764,6195,5527,4326,"Parameter values from SAD69(96) to SIRGAS 2000 (2)) (tfm code 5881) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation, based on SAD69 to SIRGAS 2000 (1)) (tfm code 15485). Used by Petrobras and ANP from 1994.","Accuracy generally better than 1m except in Amazon basin where it degenerates to 5m. Should be used only to transform data obtained independently of the classical geodetic network (GPS observations conducted after 1994).", [...]
+765,15806,4719,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis",3188,-27.25,-27.01,-109.51,-109.16,1,0,9603,211,147,111,,,,,1
+766,15860,4702,4326,Mauritania 1999 can be considered to be the same as WGS 84 within the accuracy of this transformation.,Minerals management. Accuracy 1m.,1157,14.72,27.3,-20.04,-4.8,1,0,9603,0,0,0,,,,,1
+767,15971,4762,4326,"Approximation at the +/- 1m level assuming that BDA2000 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1047,28.91,35.73,-68.83,-60.7,1,0,9603,0,0,0,,,,,1
+768,5375,5360,4326,,Accuracy 1m.,1066,-59.87,-17.5,-113.21,-65.72,1,0,9603,0,0,0,,,,,1
+769,15972,4763,4326,"Approximation at the +/- 1m level assuming that Pitcairn 2006 is equivalent to WGS 84.","Accuracy +/- 1 metre.",3208,-25.14,-25,-130.16,-130.01,1,0,9603,0,0,0,,,,,1
+770,1558,4166,4326,Derived at 5 stations.,For military purposes. Accuracy 1m in each axis.,3266,33.14,38.64,124.53,131.01,1,0,9603,0,0,0,,,,,1
+771,4084,4081,4326,"Approximation at the +/- 1m level assuming that REGCAN95 is equivalent to WGS 84.","Accuracy +/- 1m.",3199,24.6,32.76,-21.93,-11.75,1,0,9603,0,0,0,,,,,1
+772,15974,4764,4326,"Approximation at the +/- 1m level assuming that RSRGD2000 is equivalent to WGS 84.","Accuracy +/- 1 metre.",3558,-90,-59.99,144.99,-144.99,1,0,9603,0,0,0,,,,,1
+773,5553,5546,4326,"Exact in 1994 but due to significant and variable tectonic activity in PNG, in 2011 PNG94 and WGS 84 differ generally by 2m but in areas of significant tectonic activity differences can exceed 9m.",Approximation at the 2-10m level.,1187,-14.75,2.58,139.2,162.81,1,0,9603,0,0,0,,,,,1
+774,15870,4679,4326,Derived at 5 points in 2002.,Hydrographic survey,2967,19.37,21.34,-17.08,-15.88,1,0,9603,-80.01,253.26,291.19,,,,,1
+775,15976,4765,4326,"Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1212,45.42,46.88,13.38,16.61,1,0,9603,0,0,0,,,,,1
+776,15820,4730,4326,Derived at 1 satellite station.,For military and topographic mapping. Accuracy 25m in each axis.,3194,-17.32,-14.57,166.47,168.71,1,0,9603,170,42,84,,,,,1
+777,15709,4680,4326,Derived by IGN in 1992 at 7 stations within Nouakchott city.,Oil exploration.,2972,17.89,18.25,-16.11,-15.83,1,0,9603,124.5,-63.5,-281,,,,,1
+778,15908,4754,4326,Derived at 5 stations throughout Libya used to define LGD2006 in May 2006.,For applications to an accuracy of 0.1 metre.,1143,19.5,35.23,9.31,26.21,1,0,9603,-208.4058,-109.8777,-2.5764,,,,,1
+779,5585,4023,4326,"Parameter values from MOLDREF99 to ETRS89 (1) (code 5584). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications with an accuracy of 1m.,1162,45.44,48.47,26.63,30.13,1,0,9603,0,0,0,,,,,1
+780,15831,4737,4326,"Approximation at the +/- 1m level assuming that ITRF2000 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1135,28.6,40.27,122.71,134.28,1,0,9603,0,0,0,,,,,1
+781,5590,5561,4326,"Derived through concatenation of UCS-2000 to S-42 (1) (tfm code 5586 reversed) [an approximation] and S-42 to WGS 84 (16) (tfm code 15865) [derived for whole FSU rather than Ukraine]. Replaced by UCS-2000 to WGS 84 (2) (tfm code 5840).",Accuracy 5 metres.,1242,43.18,52.38,22.15,40.18,1,0,9607,25,-141,-78.5,0,-0.35,-0.736,0,1
+782,5823,5561,4326,"Parameter values taken from Ukraine 2000 to ITRF2005 (1) (code 5822) assuming that ITRS2005 is equivalent to WGS 84 within the accuracy of the transformation.","Approximation at the +/- 1m level assuming that ITRS2005 is equivalent to WGS 84.",1242,43.18,52.38,22.15,40.18,1,1,9603,24,-121,-76,,,,,0
+783,5840,5561,4326,"Parameter values taken from UCS-2000 to ITRF2005 (1) (code 5822) assuming that WGS 84 is equivalent to ITRS2005 within the accuracy of the transformation. Replaces UCS-2000 to WGS 84 (1) (tfm code 5590).","Approximation at the +/- 1m level assuming that WGS 84 is equivalent to ITRS2005.",1242,43.18,52.38,22.15,40.18,1,0,9603,24,-121,-76,,,,,0
+784,15700,4682,4326,Derived at origin station in Dhaka.,Oil exploration.,1041,18.56,26.63,88.04,92.67,1,1,9603,283.8,735.9,261.1,,,,,0
+785,15779,4682,4326,Derived at origin station in Dhaka. Source information given to 3 decimal places but rounded by OGP to be commensurate with stated accuracy.,Oil exploration.,1041,18.56,26.63,88.04,92.67,1,0,9603,283.7,735.9,261.1,,,,,1
+786,1919,4635,4326,,"Accuracy better than +/- 1 metre.",2813,-20.77,-20.34,166.44,166.71,1,1,9606,-122.383,-188.696,103.344,3.5107,-4.9668,-5.7047,4.4798,0
+787,15708,4683,4326,Derived during GPS campaign which established PRS92 coordinates at 330 first order stations.,"Accuracy: 1-10 parts per million.",1190,3,22.18,116.04,129.95,1,0,9607,-127.62,-67.24,-47.04,3.068,-4.903,-1.578,-1.06,1
+788,1837,4257,4326,,Oil exploration.,1316,-6.54,-1.88,118.71,120.78,1,0,9603,-587.8,519.75,145.76,,,,,1
+789,15713,4684,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,3274,-0.69,7.08,72.81,73.69,1,0,9603,-133,-321,50,,,,,1
+790,6177,6135,4326,"Approximation at the +/- 1m level assuming that CIGD11 is equivalent to WGS 84.","Accuracy +/- 1m.",1063,17.58,20.68,-83.6,-78.72,1,0,9603,0,0,0,,,,,1
+791,4064,4046,4326,"Approximation at the +/- 1m level assuming that RGRDC 2005 is equivalent to WGS 84 within the accuracy of the transformation.",Accuracy 1m.,3613,-13.46,-3.41,11.79,29.81,1,0,9603,0,0,0,,,,,1
+792,15918,4214,4326,Provided by BGP to TOTAL in June 2006.,Geophysical exploration in Ordos basin. Accuracy stated as 1m within basin.,3466,35,39,107,110.01,1,0,9603,12.646,-155.176,-80.863,,,,,0
+793,15919,4214,4326,Derived via WGS 72BE. Original transformation derived in 1979 at 4 stations on Yellow Sea coast.,Geophysical exploration in Yellow Sea.,3469,31.23,37.4,119.23,125.06,1,0,9606,15.53,-113.82,-41.38,0,0,0.814,-0.38,0
+794,15920,4214,4326,"Derived via WGS 72BE. Original transformation derived by GSI in 1980-81. The GSI memo incorrectly gave the parameters as from WGS 72 to Beijing 1954, but it has been determined by the OGP that the memo should have stated from Beijing 1954 to WGS 72BE.",Geophysical exploration in South China Sea.,3470,18.31,22.89,110.13,116.76,1,0,9606,31.4,-144.3,-74.8,0,0,0.814,-0.38,0
+795,15921,4214,4326,Provided by BGP to ELF in 1994.,Geophysical exploration in Tarim basin. Accuracy stated as 1m within basin.,3507,37,41.99,77.45,88,1,0,9603,15.8,-154.4,-82.3,,,,,1
+796,15935,4214,4326,Concatenated via WGS 72BE. Recomputation by Shelltech in 1981 of SSB 1980 observation.,Geophysical exploration in Bei Bu basin. Accuracy stated as 1m within basin.,3561,17.81,21.69,107.15,110.17,1,0,9606,18,-136.8,-73.7,0,0,0.814,-0.38,0
+797,15936,4214,4326,Provided by Sinopec to TOTAL in January 2007.,Geophysical exploration in Ordos basin. Accuracy stated as 1m within basin.,3466,35,39,107,110.01,1,0,9603,11.911,-154.833,-80.079,,,,,0
+798,15875,4721,4326,Derived at 20 stations. Also published by NGA in GeoTrans v3.4 software with parameter values rounded to integer.,"For military purposes. Accuracy 5m, 3m and 2m in X, Y and Z axes.",3398,-19.22,-16.1,176.81,-179.77,1,0,9603,265.025,384.929,-194.046,,,,,1
+799,7445,6311,4326,"Parameter values from CGRS93 to ETRS89 (1) (code 7444). Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84.",Small scale hydrographic and aviation  mapping.,3236,34.59,35.74,32.2,34.65,1,0,9606,8.846,-4.394,-1.122,0.00237,0.146528,-0.130428,0.783926,1
+800,5599,5593,4326,,Approximation at the 1m level.,3889,54.33,54.83,10.66,12.01,1,0,9603,0,0,0,,,,,1
+801,15832,4687,4326,"Transformation is to original definition of WGS 84. It is consistent with later WGS 84 realisations G730, G873 and G1150 to no better than 1m.","Accuracy +/- 0.5 metre (to original definition of WGS 84 - see remarks).",1098,-31.24,-4.52,-158.13,-131.97,1,0,9607,0.072,-0.507,-0.245,0.0183,-0.0003,0.007,-0.0093,1
+802,15833,4687,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84.","Accuracy +/- 1 metre.",1098,-31.24,-4.52,-158.13,-131.97,1,0,9603,0,0,0,,,,,0
+803,1921,4636,4326,,"Accuracy +/- 10 metres.",2817,-66.78,-66.1,139.44,141.5,1,0,9603,365,194,166,,,,,1
+804,15772,4688,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from Fatu Iva 72 to RGPF (1) (tfm code 15760).","Accuracy +/- 2 metres.",3133,-10.6,-10.36,-138.75,-138.54,1,0,9607,347.103,1078.125,2623.922,33.8875,-70.6773,9.3943,186.074,1
+805,5236,5233,4326,Derived at 58 stations.,Accuracy 14m.,3310,5.86,9.88,79.64,81.95,1,0,9607,-0.293,766.95,87.713,-0.195704,-1.695068,-3.473016,-0.039338,1
+806,4077,4075,4326,"Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84. SREF98 is a regional realisation of ETRS89.","Accuracy +/- 1 metre.",3534,41.85,46.19,18.81,23.01,1,0,9603,0,0,0,,,,,1
+807,4835,4690,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from Tahiti 79 to RGPF (1) (tfm code 15756).","Accuracy +/- 1 metre.",3124,-17.93,-17.44,-149.7,-149.09,1,0,9607,221.525,152.948,176.768,2.3847,1.3896,0.877,11.4741,1
+808,1922,4637,4326,,"Accuracy +/- 10 metres.",2818,-67.13,-65.61,136,142,1,0,9603,325,154,172,,,,,1
+809,15797,4712,4326,Derived at 2 satellite stations.,For military purposes only. Accuracy 25m in each axis.,3182,-8.03,-7.83,-14.46,-14.24,1,0,9603,-205,107,53,,,,,1
+810,15769,4691,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from Moorea 87 to RGPF (1) (tfm code 15757).","Accuracy +/- 1 metre.",3125,-17.63,-17.41,-150,-149.73,1,0,9607,215.525,149.593,176.229,3.2624,1.692,1.1571,10.4773,1
+811,6142,4723,4326,"Parameter values are taken from GCGD59 to CIGD11 (1) (code 6136) assuming that CIGD11 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1m.,3185,19.21,19.41,-81.46,-81.04,1,0,9607,-179.483,-69.379,-27.584,7.862,-8.163,-6.042,-13.925,1
+812,15830,4723,4326,Determined from 6 satellite stations.,"Topographic survey. Accuracy +/- 1m.",3185,19.21,19.41,-81.46,-81.04,1,0,9603,67.8,106.1,138.8,,,,,0
+813,4066,4695,4326,"Parameter values taken from Katanga 1955 to RGRDC 2005 (1) (code 4065) assuming that RGRDC 2005 is equivalent to WGS 84 within the accuracy of the transformation.",Accuracy 1.5m.,3614,-12.01,-11.13,26.38,27.75,1,0,9603,-103.746,-9.614,-255.95,,,,,1
+814,15746,4693,4326,Derived in Tombak district in March 2005. Used for South Pars phase 11 and Pars LNG plants.,Petroleum Exploration and Production.,3141,27.63,27.81,52.09,52.26,1,0,9603,0,-0.15,0.68,,,,,1
+815,1441,4601,4326,,"?",1273,16.94,17.22,-61.95,-61.61,1,0,9603,-255,-15,71,,,,,1
+816,15811,4601,4326,Determined from 1 satellite station.,"Military mapping. Accuracy +/- 25m in each axis.",1273,16.94,17.22,-61.95,-61.61,1,0,9603,-270,13,62,,,,,0
+817,1442,4602,4326,,"?",3239,15.14,15.69,-61.55,-61.2,1,0,9603,725,685,536,,,,,1
+818,1443,4603,4326,,"?",3118,11.94,12.29,-61.84,-61.54,1,0,9603,72,213.7,93,,,,,1
+819,1444,4604,4326,Derived at 1 satellite station.,Accuracy 25m in each axis.,3279,16.62,16.87,-62.29,-62.08,1,0,9603,174,359,365,,,,,1
+820,1445,4605,4326,,"?",3297,17.06,17.46,-62.92,-62.5,1,0,9603,9,183,236,,,,,1
+821,15750,4605,4326,Derived at 2 stations.,"For military purposes. Accuracy 25m in each of X, Y and Z axes.",3297,17.06,17.46,-62.92,-62.5,1,0,9603,-7,215,225,,,,,0
+822,1446,4606,4326,,"?",3298,13.66,14.16,-61.13,-60.82,1,0,9603,-149,128,296,,,,,1
+823,6897,4606,4326,Derived at 3 stations.,For military purposes only. Accuracy 1m in each axis.,3298,13.66,14.16,-61.13,-60.82,1,0,9603,-153,153,307,,,,,0
+824,1959,4607,4326,Derived at 4 points.,1m accuracy.,3300,12.54,13.44,-61.52,-61.07,1,0,9603,195.671,332.517,274.607,,,,,1
diff --git a/data/ellipsoid.csv b/data/ellipsoid.csv
index f5aea43..abf56c6 100644
--- a/data/ellipsoid.csv
+++ b/data/ellipsoid.csv
@@ -26,7 +26,7 @@ ellipsoid_code,ellipsoid_name,semi_major_axis,uom_code,inv_flattening,semi_minor
 7027,Plessis 1817,6376523,9001,308.64,,1,Rescaling of Delambre 1810 figure (a=6376985 m) to make meridional arc from equator to pole equal to 10000000 metres exactly. (Ref: Strasser).,"IGN Paris ""Constants d'Ellipsoides"" February 1972.",OGP,1995/06/02,,0
 7028,Struve 1860,6378298.3,9001,294.73,,1,"Original definition of semi-major axis given as 3272539 toise.  In ""Ellipsoidisch Parameter der Erdfigur (1800-1950)"" , Strasser suggests a conversion factor of 1.94903631 which gives a=6378297.337 metres.","""Geodesia y Cartografia Matematica"" by Fernando Martin Asin; ISBN 84-398-0248-X.",OGP,1998/11/11,1998.070 1998.340,0
 7029,War Office,6378300,9001,296,,1,"In non-metric form, a=20926201 Gold Coast feet. DMA Technical Manual 8358.1 and data derived from this quotes value for semi-major axis as 6378300.58m: OGP recommends use of defined value 6378300m exactly.","Tables for the use of the Gold Coast Survey Department, 1935.",OGP,2009/10/29,2009.075,0
-7030,WGS 84,6378137,9001,298.257223563,,1,"Inverse flattening derived from four defining parameters (semi-major axis; C20 = -484.16685*10e-6; earth's angular velocity w = 7292115e11 rad/sec; gravitational constant GM = 3986005e8 m*m*m/s/s).",DMA Technical Manual 8350.2-B ,OGP,1998/11/11,1998.320,0
+7030,WGS 84,6378137,9001,298.257223563,,1,"1/f derived from four defining parameters semi-major axis; C20 = -484.16685*10e-6; earth's angular velocity ? = 7292115e-11 rad/sec; gravitational constant GM = 3986005e8 m*m*m/s/s. In 1994 new GM = 3986004.418e8 m*m*m/s/s but a and 1/f retained.",DMA Technical Manual 8350.2-B,IOGP,2015/11/25,1998.320 2015.047,0
 7031,GEM 10C,6378137,9001,298.257223563,,1,Used for  GEM 10C Gravity Potential Model.,,OGP,1995/06/02,1998.320,0
 7032,OSU86F,6378136.2,9001,298.257223563,,1,Used for OSU86 gravity potential (geoidal) model.,,OGP,1995/06/02,1998.320,0
 7033,OSU91A,6378136.3,9001,298.257223563,,1,Used for OSU91 gravity potential (geoidal) model.,,OGP,1995/06/02,1998.320,0
diff --git a/data/gcs.csv b/data/gcs.csv
index 77ef80c..e78f240 100644
--- a/data/gcs.csv
+++ b/data/gcs.csv
@@ -58,9 +58,9 @@
 4124,RT90,6124,Rikets koordinatsystem 1990,6124,9122,7004,8901,1,0,6422,1896,1,9607,414.1,41.3,603.1,0.855,-2.141,7.023,0
 4125,Samboja,6125,Samboja,6125,9108,7004,8901,1,1,6402,1282,0,9603,-404.78,685.68,45.47,,,,
 4126,"LKS94 (ETRS89)",6126,"Lithuania 1994 (ETRS89)",6126,9108,7019,8901,1,1,6402,,0,,,,,,,,
-4127,Tete,6127,Tete,6127,9122,7008,8901,1,0,6422,1686,1,9607,-73.472,-51.66,-112.482,-0.953,-4.6,2.368,0.586
+4127,Tete,6127,Tete,6127,9122,7008,8901,1,0,6422,6901,1,9603,-80,-100,-228,,,,
 4128,Madzansua,6128,Madzansua,6128,9122,7008,8901,1,0,6422,,0,,,,,,,,
-4129,Observatario,6129,Observatario,6129,9122,7008,8901,1,0,6422,,0,,,,,,,,
+4129,Observatario,6129,Observatario,6129,9122,7008,8901,1,0,6422,6900,0,9603,-132,-110,-335,,,,
 4130,Moznet,6130,"Moznet (ITRF94)",6130,9122,7030,8901,1,0,6422,1302,0,9607,0,0,0,0,0,0,0
 4131,Indian 1960,6131,Indian 1960,6131,9122,7015,8901,1,0,6422,1542,1,9603,198,881,317,,,,
 4132,FD58,6132,Final Datum 1958,6132,9122,7012,8901,1,0,6422,1513,1,9603,-241.54,-163.64,396.06,,,,
@@ -72,7 +72,7 @@
 4138,St. George Island,6138,St. George Island,6138,9122,7008,8901,1,0,6422,,0,,,,,,,,
 4139,Puerto Rico,6139,Puerto Rico,6139,9122,7008,8901,1,0,6422,1893,0,9603,11,72,-101,,,,
 4140,"NAD83(CSRS98)",6140,NAD83 Canadian Spatial Reference System,6140,9108,7019,8901,1,1,6402,1473,0,9603,0,0,0,,,,
-4141,Israel,6141,Israel,6141,9122,7019,8901,1,0,6422,1073,0,9603,-48,55,52,,,,
+4141,Israel 1993,6141,Israel 1993,6141,9122,7019,8901,1,0,6422,1073,0,9603,-48,55,52,,,,
 4142,Locodjo 1965,6142,Locodjo 1965,6142,9122,7012,8901,1,0,6422,1469,0,9603,-125,53,467,,,,
 4143,Abidjan 1987,6143,Abidjan 1987,6143,9122,7012,8901,1,0,6422,1470,1,9603,-124.76,53,466.79,,,,
 4144,Kalianpur 1937,6144,Kalianpur 1937,6144,9122,7015,8901,1,0,6422,1533,1,9603,214,804,268,,,,
@@ -119,7 +119,7 @@
 4188,OSNI 1952,6188,OSNI 1952,6188,9122,7001,8901,1,0,6422,1955,0,9606,482.5,-130.6,564.6,-1.042,-0.214,-0.631,8.15
 4189,REGVEN,6189,Red Geodesica Venezolana,6189,9122,7019,8901,1,0,6422,1768,0,9603,0,0,0,,,,
 4190,POSGAR 98,6190,Posiciones Geodesicas Argentinas 1998,6190,9122,7019,8901,1,0,6422,1773,1,9603,0,0,0,,,,
-4191,Albanian 1987,6191,Albanian 1987,6191,9122,7024,8901,1,0,6422,,0,,,,,,,,
+4191,Albanian 1987,6191,Albanian 1987,6191,9122,7024,8901,1,0,6422,6964,0,9607,-44.183,-0.58,-38.489,2.3867,2.7072,-3.5196,-8.2703
 4192,Douala 1948,6192,Douala 1948,6192,9122,7022,8901,1,0,6422,15873,0,9603,-206.1,-174.7,-87.7,,,,
 4193,Manoca 1962,6193,Manoca 1962,6193,9122,7011,8901,1,0,6422,1796,0,9603,-70.9,-151.8,-41.4,,,,
 4194,Qornoq 1927,6194,Qornoq 1927,6194,9122,7022,8901,1,0,6422,1797,1,9603,164,138,-189,,,,
@@ -158,8 +158,8 @@
 4228,Douala,6228,Douala,6228,9108,7011,8901,1,1,6402,,0,,,,,,,,
 4229,Egypt 1907,6229,Egypt 1907,6229,9122,7020,8901,1,0,6422,1148,1,9603,-130,110,-13,,,,
 4230,ED50,6230,European Datum 1950,6230,9122,7022,8901,1,0,6422,1133,1,9603,-87,-98,-121,,,,
-4231,ED87,6231,European Datum 1987,6231,9122,7022,8901,1,0,6422,3905,1,9606,-83.11,-97.38,-117.22,0.00569290865241986,-0.0446975835137458,0.0442850539012516,0.1218
-4232,Fahud,6232,Fahud,6232,9122,7012,8901,1,0,6422,1256,1,9603,-346,-1,224,,,,
+4231,ED87,6231,European Datum 1987,6231,9122,7022,8901,1,0,6422,3905,1,9606,-83.11,-97.38,-117.22,0.005693,-0.044698,0.044285,0.1218
+4232,Fahud,6232,Fahud,6232,9122,7012,8901,1,0,6422,1438,1,9606,-333.102,-11.02,230.69,0,0,0.554,0.219
 4233,Gandajika 1970,6233,Gandajika 1970,6233,9122,7022,8901,1,1,6422,1894,0,9603,-133,-321,50,,,,
 4234,Garoua,6234,Garoua,6234,9108,7011,8901,1,1,6402,,0,,,,,,,,
 4235,Guyane Francaise,6235,Guyane Francaise,6235,9108,7022,8901,1,1,6402,,0,,,,,,,,
@@ -197,7 +197,7 @@
 4267,NAD27,6267,North American Datum 1927,6267,9122,7008,8901,1,0,6422,,0,,,,,,,,
 4268,NAD27 Michigan,6268,NAD27 Michigan,6268,9122,7009,8901,1,1,6422,,0,,,,,,,,
 4269,NAD83,6269,North American Datum 1983,6269,9122,7019,8901,1,0,6422,1188,1,9603,0,0,0,,,,
-4270,Nahrwan 1967,6270,Nahrwan 1967,6270,9122,7012,8901,1,0,6422,15871,1,9603,-242.2,-144.9,370.3,,,,
+4270,Nahrwan 1967,6270,Nahrwan 1967,6270,9122,7012,8901,1,0,6422,1191,1,9603,-249,-156,381,,,,
 4271,Naparima 1972,6271,Naparima 1972,6271,9122,7022,8901,1,0,6422,1192,1,9603,-10,375,165,,,,
 4272,NZGD49,6272,New Zealand Geodetic Datum 1949,6272,9122,7022,8901,1,0,6422,1564,1,9607,59.47,-5.04,187.44,-0.47,0.1,-1.024,-4.5993
 4273,NGO 1948,6273,NGO 1948,6273,9122,7005,8901,1,0,6422,1654,0,9606,278.3,93,474.5,7.889,0.05,-6.61,6.21
@@ -216,7 +216,7 @@
 4286,Qatar 1948,6286,Qatar 1948,6286,9122,7020,8901,1,0,6422,,0,,,,,,,,
 4287,Qornoq,6287,Qornoq,6287,9108,7022,8901,1,1,6402,1211,0,9603,164,138,-189,,,,
 4288,Loma Quintana,6288,Loma Quintana,6288,9122,7022,8901,1,0,6422,,0,,,,,,,,
-4289,Amersfoort,6289,Amersfoort,6289,9122,7004,8901,1,0,6422,4833,1,9607,565.4171,50.3319,465.5524,0.398957388243134,-0.343987817378283,1.87740163998045,4.0725
+4289,Amersfoort,6289,Amersfoort,6289,9122,7004,8901,1,0,6422,4833,1,9607,565.4171,50.3319,465.5524,0.398957,-0.343988,1.87740,4.0725
 4291,SAD69,6291,South American Datum 1969,6291,9108,7036,8901,1,1,6402,1212,1,9603,-57,1,-41,,,,
 4292,Sapper Hill 1943,6292,Sapper Hill 1943,6292,9122,7022,8901,1,0,6422,1225,0,9603,-355,21,72,,,,
 4293,Schwarzeck,6293,Schwarzeck,6293,9122,7046,8901,1,0,6422,1226,1,9603,616,97,-251,,,,
@@ -235,7 +235,7 @@
 4307,Nord Sahara 1959,6307,Nord Sahara 1959,6307,9122,7012,8901,1,0,6422,5660,1,9606,-209.3622,-87.8162,404.6198,0.0046,3.4784,0.5805,-1.4547
 4308,RT38,6308,Stockholm 1938,6308,9122,7004,8901,1,0,6422,,0,,,,,,,,
 4309,Yacare,6309,Yacare,6309,9122,7022,8901,1,0,6422,1234,1,9603,-155,171,37,,,,
-4310,Yoff,6310,Yoff,6310,9122,7011,8901,1,0,6422,,0,,,,,,,,
+4310,Yoff,6310,Yoff,6310,9122,7011,8901,1,0,6422,6903,0,9603,-30,190,89,,,,
 4311,Zanderij,6311,Zanderij,6311,9122,7022,8901,1,0,6422,1235,0,9603,-265,120,-358,,,,
 4312,MGI,6312,Militar-Geographische Institut,6312,9122,7004,8901,1,0,6422,1618,1,9606,577.326,90.129,463.919,5.137,1.474,5.297,2.4232
 4313,Belge 1972,6313,Reseau National Belge 1972,6313,9122,7022,8901,1,0,6422,15929,1,9607,-106.8686,52.2978,-103.7239,-0.3366,0.457,-1.8422,-1.2747
@@ -261,7 +261,7 @@
 4603,Grenada 1953,6603,Grenada 1953,6603,9122,7012,8901,1,0,6422,1443,0,9603,72,213.7,93,,,,
 4604,Montserrat 1958,6604,Montserrat 1958,6604,9122,7012,8901,1,0,6422,1444,0,9603,174,359,365,,,,
 4605,St. Kitts 1955,6605,St. Kitts 1955,6605,9122,7012,8901,1,0,6422,1445,1,9603,9,183,236,,,,
-4606,St. Lucia 1955,6606,St. Lucia 1955,6606,9122,7012,8901,1,0,6422,1446,0,9603,-149,128,296,,,,
+4606,St. Lucia 1955,6606,St. Lucia 1955,6606,9122,7012,8901,1,0,6422,1446,1,9603,-149,128,296,,,,
 4607,St. Vincent 1945,6607,St. Vincent 1945,6607,9122,7012,8901,1,0,6422,1959,0,9603,195.671,332.517,274.607,,,,
 4608,"NAD27(76)",6608,"North American Datum 1927 (1976)",6608,9122,7008,8901,1,0,6422,,0,,,,,,,,
 4609,"NAD27(CGQ77)",6609,"North American Datum 1927 (CGQ77)",6609,9122,7008,8901,1,0,6422,,0,,,,,,,,
@@ -303,9 +303,9 @@
 4645,RGNC 1991,6645,Reseau Geodesique Nouvelle Caledonie 1991,6645,9122,7022,8901,1,1,6422,1920,0,9603,0,0,0,,,,
 4646,Grand Comoros,6646,Grand Comoros,6646,9122,7022,8901,1,0,6422,5521,0,9603,-963,510,-359,,,,
 4657,Reykjavik 1900,6657,Reykjavik 1900,6657,9122,7051,8901,1,0,6422,1994,0,9603,-28,199,5,,,,
-4658,Hjorsey 1955,6658,Hjorsey 1955,6658,9122,7022,8901,1,0,6422,1951,0,9603,-73,46,-86,,,,
+4658,Hjorsey 1955,6658,Hjorsey 1955,6658,9122,7022,8901,1,0,6422,6909,1,9603,-73,47,-83,,,,
 4659,ISN93,6659,Islands Net 1993,6659,9122,7019,8901,1,0,6422,1952,0,9603,0,0,0,,,,
-4660,Helle 1954,6660,Helle 1954,6660,9122,7022,8901,1,0,6422,1957,0,9606,982.6087,552.753,-540.873,6.68162662527694,-31.6114924086422,-19.8481610048168,16.805
+4660,Helle 1954,6660,Helle 1954,6660,9122,7022,8901,1,0,6422,1957,0,9606,982.6087,552.753,-540.873,6.6816266,-31.6114924,-19.84816,16.805
 4661,LKS92,6661,Latvia 1992,6661,9122,7019,8901,1,0,6422,1958,0,9603,0,0,0,,,,
 4662,IGN72 Grande Terre,6634,IGN72 Grande Terre,6634,9122,7022,8901,1,0,6422,15903,1,9603,-11.64,-348.6,291.98,,,,
 4663,Porto Santo 1995,6663,Porto Santo 1995,6663,9122,7022,8901,1,0,6422,1966,1,9603,-502.862,-247.438,312.724,,,,
@@ -358,7 +358,7 @@
 4710,St. Helena 1971,6710,St. Helena 1971,6710,9122,7022,8901,1,0,6422,15798,0,9603,-320,550,-494,,,,
 4711,Marcus Island 1952,6711,Marcus Island 1952,6711,9122,7022,8901,1,0,6422,15799,0,9603,124,-234,-25,,,,
 4712,Ascension Island 1958,6712,Ascension Island 1958,6712,9122,7022,8901,1,0,6422,15797,0,9603,-205,107,53,,,,
-4713,Ayabelle Lighthouse,6713,Ayabelle Lighthouse,6713,9122,7012,8901,1,0,6422,15800,0,9603,-79,-129,145,,,,
+4713,Ayabelle Lighthouse,6713,Ayabelle Lighthouse,6713,9122,7012,8901,1,0,6422,6907,1,9603,-77,-128,142,,,,
 4714,Bellevue,6714,Bellevue,6714,9122,7022,8901,1,0,6422,15801,0,9603,-127,-769,472,,,,
 4715,Camp Area Astro,6715,Camp Area Astro,6715,9122,7022,8901,1,0,6422,15802,0,9603,-104,-129,239,,,,
 4716,Phoenix Islands 1966,6716,Phoenix Islands 1966,6716,9122,7022,8901,1,0,6422,15803,0,9603,298,-304,-375,,,,
@@ -389,7 +389,7 @@
 4741,FD54,6741,Faroe Datum 1954,6741,9122,7022,8901,1,0,6422,,0,,,,,,,,
 4742,GDM2000,6742,Geodetic Datum of Malaysia 2000,6742,9122,7019,8901,1,0,6422,,0,,,,,,,,
 4743,Karbala 1979,6743,Karbala 1979,6743,9122,7012,8901,1,0,6422,5078,1,9603,70.995,-335.916,262.898,,,,
-4744,Nahrwan 1934,6744,Nahrwan 1934,6744,9122,7012,8901,1,0,6422,,0,,,,,,,,
+4744,Nahrwan 1934,6744,Nahrwan 1934,6744,9122,7012,8901,1,0,6422,7033,0,9603,-242.2,-144.9,370.3,,,,
 4745,"RD/83",6745,"Rauenberg Datum/83",6745,9122,7004,8901,1,0,6422,,0,,,,,,,,
 4746,"PD/83",6746,"Potsdam Datum/83",6746,9122,7004,8901,1,0,6422,,0,,,,,,,,
 4747,GR96,6747,Greenland 1996,6747,9122,7019,8901,1,0,6422,15879,0,9603,0,0,0,,,,
@@ -397,11 +397,11 @@
 4749,RGNC91-93,6749,Reseau Geodesique de Nouvelle Caledonie 91-93,6749,9122,7019,8901,1,0,6422,15880,0,9603,0,0,0,,,,
 4750,ST87 Ouvea,6750,ST87 Ouvea,6750,9122,7030,8901,1,0,6422,15881,0,9603,-56.263,16.136,-22.856,,,,
 4751,"Kertau (RSO)",6751,"Kertau (RSO)",6751,9122,7056,8901,1,0,6422,,0,,,,,,,,
-4752,Viti Levu 1912,6752,Viti Levu 1912,6752,9122,7055,8901,1,0,6422,15897,0,9603,51,391,-36,,,,
+4752,Viti Levu 1912,6752,Viti Levu 1912,6752,9122,7055,8901,1,0,6422,6895,1,9603,98,390,-22,,,,
 4753,fk89,6753,fk89,6753,9122,7022,8901,1,0,6422,,0,,,,,,,,
 4754,LGD2006,6754,Libyan Geodetic Datum 2006,6754,9122,7022,8901,1,0,6422,15908,0,9603,-208.4058,-109.8777,-2.5764,,,,
 4755,DGN95,6755,Datum Geodesi Nasional 1995,6755,9122,7030,8901,1,0,6422,15912,0,9603,0,0,0,,,,
-4756,VN-2000,6756,Vietnam 2000,6756,9122,7030,8901,1,0,6422,5194,0,9607,-192.873,-39.382,-111.202,0.00205,0.0005,-0.00335,0.0188
+4756,VN-2000,6756,Vietnam 2000,6756,9122,7030,8901,1,0,6422,6960,1,9607,-191.90441429,-39.30318279,-111.45032835,-0.00928836,0.01975479,-0.00427372,0.252906278
 4757,SVY21,6757,SVY21,6757,9122,7030,8901,1,0,6422,,0,,,,,,,,
 4758,JAD2001,6758,Jamaica 2001,6758,9122,7030,8901,1,0,6422,15925,0,9603,0,0,0,,,,
 4759,"NAD83(NSRS2007)",6759,"NAD83 (National Spatial Reference System 2007)",6759,9122,7019,8901,1,0,6422,15931,0,9603,0,0,0,,,,
@@ -467,6 +467,7 @@
 5886,TGD2005,1095,Tonga Geodetic Datum 2005,1095,9122,7019,8901,1,0,6422,,0,,,,,,,,
 6135,CIGD11,1100,Cayman Islands Geodetic Datum 2011,1100,9122,7019,8901,1,0,6422,6177,0,9603,0,0,0,,,,
 6207,Nepal 1981,1111,Nepal 1981,1111,9122,7015,8901,1,0,6422,6208,0,9603,293.17,726.18,245.36,,,,
+6311,CGRS93,1112,Cyprus Geodetic Reference System 1993,1112,9122,7030,8901,1,0,6422,7445,0,9606,8.846,-4.394,-1.122,0.00237,0.146528,-0.130428,0.783926
 6318,"NAD83(2011)",1116,"NAD83 (National Spatial Reference System 2011)",1116,9122,7019,8901,1,0,6422,,0,,,,,,,,
 6322,"NAD83(PA11)",1117,"NAD83 (National Spatial Reference System PA11)",1117,9122,7019,8901,1,0,6422,,0,,,,,,,,
 6325,"NAD83(MA11)",1118,"NAD83 (National Spatial Reference System MA11)",1118,9122,7019,8901,1,0,6422,,0,,,,,,,,
@@ -474,3 +475,24 @@
 6668,JGD2011,1128,Japanese Geodetic Datum 2011,1128,9122,7019,8901,1,0,6422,,0,,,,,,,,
 6706,RDN2008,1132,Rete Dinamica Nazionale 2008,1132,9122,7019,8901,1,0,6422,6711,0,9603,0,0,0,,,,
 6783,"NAD83(CORS96)",1133,"NAD83 (Continuously Operating Reference Station 1996)",1133,9122,7019,8901,1,0,6422,,0,,,,,,,,
+6881,Aden 1925,1135,Aden 1925,1135,9122,7012,8901,1,0,6422,6910,0,9603,-24,-203,268,,,,
+6882,Bekaa Valley 1920,1137,Bekaa Valley 1920,1137,9122,7012,8901,1,0,6422,6911,0,9603,-183,-15,273,,,,
+6883,Bioko,1136,Bioko,1136,9122,7022,8901,1,0,6422,6912,0,9603,-235,-110,393,,,,
+6892,South East Island 1943,1138,South East Island 1943,1138,9122,7012,8901,1,0,6422,6914,1,9603,-43.685,-179.785,-267.721,,,,
+6894,Gambia,1139,Gambia,1139,9122,7012,8901,1,0,6422,6913,0,9603,-63,176,185,,,,
+6980,IGD05,1143,Israeli Geodetic Datum 2005,1143,9122,7019,8901,1,1,6422,,0,,,,,,,,
+6983,IG05 Intermediate CRS,1142,IG05 Intermediate Datum,1142,9122,7019,8901,1,0,6422,,0,,,,,,,,
+6987,"IGD05/12",1145,"Israeli Geodetic Datum 2005(2012)",1145,9122,7019,8901,1,1,6422,,0,,,,,,,,
+6990,"IG05/12 Intermediate CRS",1144,"IG05/12 Intermediate Datum",1144,9122,7019,8901,1,0,6422,,0,,,,,,,,
+7035,"RGSPM06 (lon-lat)",1038,Reseau Geodesique de Saint Pierre et Miquelon 2006,1038,9122,7019,8901,1,0,6424,,0,,,,,,,,
+7037,"RGR92 (lon-lat)",6627,Reseau Geodesique de la Reunion 1992,6627,9122,7019,8901,1,0,6424,,0,,,,,,,,
+7039,"RGM04 (lon-lat)",1036,Reseau Geodesique de Mayotte 2004,1036,9122,7019,8901,1,0,6424,,0,,,,,,,,
+7041,"RGFG95 (lon-lat)",6624,Reseau Geodesique Francais Guyane 1995,6624,9122,7019,8901,1,0,6424,,0,,,,,,,,
+7073,RGTAAF07,1113,Reseau Geodesique des Terres Australes et Antarctiques Francaises 2007,1113,9122,7019,8901,1,0,6422,,0,,,,,,,,
+7084,"RGF93 (lon-lat)",6171,Reseau Geodesique Francais 1993,6171,9122,7019,8901,1,0,6424,,0,,,,,,,,
+7086,"RGAF09 (lon-lat)",1073,Reseau Geodesique des Antilles Francaises 2009,1073,9122,7019,8901,1,0,6424,,0,,,,,,,,
+7088,"RGTAAF07 (lon-lat)",1113,Reseau Geodesique des Terres Australes et Antarctiques Francaises 2007,1113,9122,7019,8901,1,1,6424,,0,,,,,,,,
+7133,"RGTAAF07 (lon-lat)",1113,Reseau Geodesique des Terres Australes et Antarctiques Francaises 2007,1113,9122,7019,8901,1,0,6424,,0,,,,,,,,
+7136,IGD05,1114,Israeli Geodetic Datum 2005,1114,9122,7030,8901,1,0,6422,,0,,,,,,,,
+7139,"IGD05/12",1115,"Israeli Geodetic Datum 2005(2012)",1115,9122,7030,8901,1,0,6422,,0,,,,,,,,
+7373,ONGD14,1147,Oman National Geodetic Datum 2014,1147,9122,7019,8901,1,0,6422,7443,0,9603,0,0,0,,,,
diff --git a/data/gdal_datum.csv b/data/gdal_datum.csv
index 6f58645..0b0310a 100644
--- a/data/gdal_datum.csv
+++ b/data/gdal_datum.csv
@@ -2,7 +2,7 @@
 1024,Hungarian Datum 1909,geodetic,"Fundamental point not given in information source, but presumably Szolohegy which is origin of later HD72.",1909,7004,8901,1119,Topographic mapping.,"Replaced earlier HD1863 adjustment also on Bessel ellipsoid. Both HD1863 and HD1909 were originally on Ferro Prime Meridian but subsequently converted to Greenwich. Replaced by HD72 (datum code 6237).","Timár, Molnár and Márta in Geodezia es Kartografia 55(3) pp16-21. www.fomi.hu/internet/magyar/szaklap/g [...]
 1025,Taiwan Datum 1967,geodetic,"Fundamental point: Hu Tzu Shan. Latitude: 23°58'32.34""N, longitude: 120°58'25.975""E (of Greenwich).",1967,7050,8901,3315,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Adopted in 1980. TWD67 uses the GRS 1967 ellipsoid but with 1/f to exactly 2 decimal places.","National Land Surveying and Mapping Center (NLSC), http://www.nlsc.gov.tw",OGP,"2008/08/11",,0,"D_TWD_1967"
 1026,Taiwan Datum 1997,geodetic,ITRF94 at epoch 1997.0,1997,7019,8901,1228,"Geodetic survey, GIS, topographic mapping, engineering survey.",Adopted in 1998.,"National Land Surveying and Mapping Center (NLSC), http://www.nlsc.gov.tw",OGP,"2008/08/11",,0,"D_TWD_1997"
-1027,EGM2008 geoid,vertical,WGS 84 ellipsoid.,2008,,,1262,Geodesy.,,"http://earth-info.nga.mil/GandG/wgs84/gravitymod/egm2008/egm08_wgs84.html",OGP,"2009/01/30",2008.097,0,
+1027,EGM2008 geoid,vertical,Derived through EGM2008 geoid undulation model consisting of spherical harmonic coefficients to degree 2190 and order 2159 applied to the WGS 84 ellipsoid.,2008,,,1262,Geodesy.,"Replaces EGM96 geoid (datum code 5171). See transformation codes 3858 and 3859 for 2.5x2.5 and 1x1 arc minute geoid undulation grid files derived from the spherical harmonic coefficients.","http://earth-info.nga.mil/GandG/wgs84/gravitymod/egm2008/egm08_wgs84.html",IOGP,"2015/11/25",200 [...]
 1028,Fao 1979,vertical,"Average sea level at Fao during two-year period in mid/late 1970s.",1979,,,3625,"Topographic mapping, geodetic survey.","Levelling network established by Polservice consortium.  Replaces Fao (datum code 5149) in Iraq.","Survey Division, Ministry of Water Resources (MoWR).",OGP,"2010/03/01",2009.003 2010.014,0,
 1029,Iraqi Geospatial Reference System,geodetic,ITRF2000 at epoch 1997.0,2000,7019,8901,1124,Geodetic survey.,,"Survey Division, Ministry of Water Resources (MoWR).",OGP,"2009/02/03",2009.003,0,"D_Iraqi_Geospatial_Reference_System"
 1030,N2000,vertical,"Height at Metsaahovi (latitude 60.21762°N, longitude 24.39517°E) of 54.4233m related to EVRF2000 origin through Baltic Levelling Ring adjustment at epoch 2000.0.",2000,,,3333,"Topographic mapping, geodetic survey.","Realised through the third precise levelling network. Uses normal heights. Replaces N60 (datum code 5116). To account for isostatic land uplift use NKG2005 model.","National Land Survey of Finland;
@@ -37,7 +37,7 @@ http://www.maanmittauslaitos.fi",OGP,"2009/02/21",2008.112,0,
 1058,Bhutan National Geodetic Datum,geodetic,ITRF2000 at epoch 2003.87,2000,7019,8901,1048,Geodetic survey.,,"Department of Survey and Land Records (DSLR), National Land Commission of Bhutan (NLC) via Lantmäteriet Sweden.",OGP,"2010/09/06",2010.086,0,"D_Bhutan_National_Geodetic_Datum"
 1059,Faroe Islands Vertical Reference 2009,vertical,,2009,,,3248,Topographic mapping and engineering survey,Mean Tidal Height System.,"Kort & Matrikelstyrelsen (KMS), Copenhagen.",OGP,"2010/10/27",2010.092,0,
 1060,Islands Net 2004,geodetic,ITRF2000 at epoch 2004.6.,2004,7019,8901,1120,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces ISN93 (datum code 6659).","Landmaelingar Islands (National Land Survey of Iceland). http://www.lmi.is",OGP,"2010/11/12",2010.101,0,"D_Islands_Network_2004"
-1061,International Terrestrial Reference Frame 2008,geodetic,Origin at geocentre. The ITRF2008 origin is defined in such a way that there are null translation parameters at epoch 2005.0 and null translation rates between the ITRF2008 and the ILRS SLR time series.,2008,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) at epoch 2008.0. Replaces ITRF2005 (code 6896).","IGN Paris http://itrf.ensg.ign.fr/itrs_itrf.php",OGP,"2011/01/13",2011.002,0,
+1061,International Terrestrial Reference Frame 2008,geodetic,Origin at geocentre. The ITRF2008 origin is defined in such a way that there are null translation parameters at epoch 2005.0 and null translation rates between the ITRF2008 and the ILRS SLR time series.,2005,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from 2012. Replaces ITRF2005 (code 6896).","International Earth Rotation Service (IERS) Technical Note No. 37, published in 2012. Also at  [...]
 1062,Posiciones Geodesicas Argentinas 2007,geodetic,"A geodetic network of 211 high accuracy surveyed points (178 passive and 33 continuous operating) based on ITRF2005, Epoch 2006.6, that define the National Geodetic System (Sistema Geodésico Nacional) effective 15 May 2009.",2009,7019,8901,1033,"Topographic mapping, geodetic survey.","POSGAR 07 has been adopted by order of the Director of the National Geographic Institute on May 15, 2009, as the new National Geodetic Reference Frame an [...]
 1063,Marco Geodesico Nacional,geodetic,"ITRF94 at epoch 1995.4.  Densification of SIRGAS95 network in Bolivia, consisting of 125 passive geodetic stations and 8 continuous recording GPS stations.",2007,7019,8901,1049,Geodetic survey.,"Densification of SIRGAS 1995 within Bolivia. Replaces PSAD56 (datum code 6248) in Bolivia.","Sistema de Referencia Geocentrico para las Americas (SIRGAS) Boletin Informativo No 12, Aug 2007 and www.sirgas.org/fileadmin/docs/Boletines/Bol12/09_Actividades_SI [...]
 1064,SIRGAS-Chile,geodetic,"ITRF2000 at epoch 2002.0.  Densification of SIRGAS 2000 network in Chile, consisting of 650 monumented stations.",2007,7019,8901,1066,Geodetic survey.,"Densification of SIRGAS 2000 within Chile. Replaces PSAD56 (datum code 6248) in Chile, replaces HITO XVIII (datum code 6254) in Chilean Tierra del Fuego and replaces Easter Island 1967 (datum code 6719)  in Easter Island.","IGM Chile Report: 31_Parra_Baez_Chilean_part_of_SIRGAS.pdf on sirgas.org website (www.si [...]
@@ -83,11 +83,15 @@ http://www.maanmittauslaitos.fi",OGP,"2009/02/21",2008.112,0,
 1104,Horta,vertical,Mean Sea Level during 1935 at Horta.,1935,,,2873,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
 1105,Cais da Madalena,vertical,Mean Sea Level during 1937 at Cais da Madalena.,1937,,,2874,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
 1106,Santa Cruz da Graciosa,vertical,Mean Sea Level during 1938 at Santa Cruz da Graciosa.,1938,,,3681,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
-1107,"Cais da Figueirinha - Angra do Heroísmo",vertical,"Mean Sea Level during 1951 at Cais da Figueirinha - Angra do Heroísmo.",1951,,,2872,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
+1107,Cais da Figueirinha - Angra do Heroismo,vertical,"Mean Sea Level during 1951 at Cais da Figueirinha - Angra do Heroísmo.",1951,,,2872,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2014/09/18",2013.010 2014.064,0,
 1108,Santa Cruz das Flores,vertical,Mean Sea Level during 1965 at Santa Cruz das Flores.,1965,,,1344,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
 1109,Cais da Vila do Porto,vertical,"Mean Sea Level during 1965 at Cais da Vila, Porto.",1965,,,4126,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
 1110,Ponta Delgada,vertical,Mean Sea Level during 1991 at Ponta Delgada.,1991,,,2871,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
 1111,Nepal 1981,geodetic,"Fundamental point: Station 12/157 Nagarkot. Latitude: 27°41'31.04""N, longitude: 85°31'20.23""E (of Greenwich).",1981,7015,8901,1171,"Geodetic survey, topographic mapping.",,Nepal Survey Department www.dos.gov.np and Nepalese Journal on Geoinformatics June 2011.,OGP,"2013/06/26",2013.018,0,
+1112,Cyprus Geodetic Reference System 1993,geodetic,"Station Chionistra (Mount Troodos). Network scale and orientation determined by connection of six stations to ITRF91 in Europe at epoch 1993.1.",1993,7030,8901,3236,Geodetic survey.,Replaces 1913 and 1935 datums.,"Cyprus Department of Lands and Surveys (DLS).",IOGP,"2015/09/28",2014.091,0,
+1113,Reseau Geodesique des Terres Australes et Antarctiques Francaises 2007,geodetic,ITRF2005 at epoch 2007.274,2007,7019,8901,4246,"Geodetic survey, topographic mapping, engineering survey.","Replaces IGN 1963-64 on Amsterdam, Saint-Paul 1969 on St Paul, IGN64 on Crozet, MHM 1954 on Europa, IGN 1962 on Kerguelan, and Petrels 1972 and Perroud 1950 in Adelie Land.",IGN Paris.,IOGP,"2015/04/25",2015.027,0,
+1114,Israeli Geodetic Datum 2005,geodetic,"Defined by coordinates of 13 Active Positioning Network (APN) stations in ITRF2000 at epoch 2004.75. A further five APN stations were added in 2006.",2004,7030,8901,1126,Geodetic Survey.,"Replaces Israel 1993 (datum code 6141). Replaced by IGD05/12 (datum code 1115).",Survey of Israel.,IOGP,"2015/06/20",2015.020,0,
+1115,"Israeli Geodetic Datum 2005(2012)",geodetic,Datum updated in 2012 with four APN stations removed from definition. Coordinate epoch remains ITRF2000 at epoch 2004.75.,2004,7030,8901,1126,Geodetic Survey.,"Replaces IGD05 (datum code 1114).",Survey of Israel.,IOGP,"2015/06/20",2015.020,0,
 1116,"NAD83 (National Spatial Reference System 2011)",geodetic,"Coordinates of a nationwide adjustment of 79,546 NGS ""passive"" control stations in CONUS and Alaska, constrained to 1,171 current CORS station coordinates at epoch 2010.0.",2012,7019,8901,1511,Geodetic survey.,"Replaces NAD83(NSRS2007). ITRF2008 is understood to underlay the latest CORS station coordinates.","U.S. National Geodetic Survey, http://www.ngs.noaa.gov/",OGP,"2013/06/07",2013.022,0,
 1117,"NAD83 (National Spatial Reference System PA11)",geodetic,"Coordinates of a nationwide adjustment including 345 NGS ""passive"" control stations constrained to 24 current Pacific CORS station coordinates at epoch 2010.0.",2012,7019,8901,4162,Geodetic survey.,"Replaces NAD83(HARN) in American Samoa and Hawaii. ITRF2008 is understood to underlay the latest CORS station coordinates.","U.S. National Geodetic Survey, http://www.ngs.noaa.gov/",OGP,"2013/06/07",2013.022,0,
 1118,"NAD83 (National Spatial Reference System MA11)",geodetic,"Coordinates of a nationwide adjustment including 171 NGS ""passive"" control stations constrained to 24 current Pacific CORS station coordinates at epoch 2010.0.",2012,7019,8901,4167,Geodetic survey.,"Replaces NAD83(HARN) (GGN93) code 6152 in Guam. ITRF2008 is understood to underlay the latest CORS station coordinates.","U.S. National Geodetic Survey, http://www.ngs.noaa.gov/",OGP,"2013/06/08",2013.022,0,
@@ -105,7 +109,25 @@ http://www.maanmittauslaitos.fi",OGP,"2009/02/21",2008.112,0,
 1130,"Japanese Geodetic Datum 2000 (vertical)",vertical,24.4140 metres above mean sea level Tokyo Bay.,2002,,,3263,"Topographic mapping, geodetic survey.","Orthometric heights. Replaces JSLD69 and JSLD72 with effect from April 2002. Replaced by JGD2011 (vertical) (datum code 1131) with effect from 21st October 2011.","Geospatial Information Authority of Japan (GSI) bulletin volume 51 of March 2004.",OGP,"2013/12/15",2013.063,0,
 1131,"Japanese Geodetic Datum 2011 (vertical)",vertical,24.3900 metres above mean sea level Tokyo Bay.,2011,,,3263,"Topographic mapping, geodetic survey.","Orthometric heights. Replaces JGD2000 (vertical) (datum code 1130) with effect from 21st October 2011.","Geodetic Department, Geospatial Information Authority of Japan (GSI).",OGP,"2013/12/15",2013.063,0,
 1132,Rete Dinamica Nazionale 2008,geodetic,"Italian densification of ETRS89 realised through network of 99 permanent reference stations in ETRF2000 at 2008.0.",2008,7019,8901,3343,"Geodetic survey, topographic mapping.","Adopted as official Italian reference datum 10/11/2011. Replaces IGM95 (datum code 6670).",IGM Italy,OGP,"2014/01/21",2014.002,0,
+1133,"NAD83 (Continuously Operating Reference Station 1996)",geodetic,"Defined by time-dependent transformations from ITRF. The ITRF realisation and tfm used has been changed periodically; ITRF96 in years 1997 through 1999, ITRF97 in 2000 and 2001 and ITRF2000 from 2002 (see tfm codes 6864-6866 respectively).",1997,7019,8901,1511,Geodetic survey.,"Replaced by NAD83(2011) from 2011-09-06.","US National Geodetic Survey, http://geodesy.noaa.gov/CORS.",OGP,"2014/09/18",2014.029 2014.065,0,
 1134,Christmas Island Datum 1985,engineering,"WGS 72 / UTM zone 48S coordinates 570000mE, 8840000mN; local grid orientated parallel to UTM grid at this point.",1985,,,4169,"GIS, topographic survey, cadastre, engineering survey.",Replaced by GDA94 geodetic datum.,"Landgate (Government of Western Australia), Christmas Island Geographic Information System documentation, www.ga.gov.au/christmas.",OGP,"2014/02/08",2014.005,0,
+1135,Aden 1925,geodetic,,,7012,8901,1340,Engineering and harbour surveys.,,US NGA GeoTrans software v3.4 and other industry sources.,OGP,"2014/07/30",2014.037,0,
+1136,Bioko,geodetic,,,7022,8901,4220,Topographic survey.,,US NGA GeoTrans software v3.4.,OGP,"2014/07/30",2014.037,0,
+1137,Bekaa Valley 1920,geodetic,,,7012,8901,3269,Topographic survey.,,US NGA GeoTrans software v3.4.,OGP,"2014/07/30",2014.037,0,
+1138,South East Island 1943,geodetic,"Fundamental point: Challenger Astro near Port Victoria lighthouse. Latitude: 4°40'39.460""S, longitude: 55°32'00.166""E (of Greenwich).",1975,7012,8901,4183,Topographic survey.,Network readjusted in 1958-59 and extended to Bird and Denis islands in 1975.,UK Hydrographic Office.,OGP,"2014/07/30",2014.037,0,
+1139,Gambia,geodetic,,,7012,8901,3250,Topographic survey.,,US NGA GeoTrans software v3.4.,OGP,"2014/07/30",2014.037,0,
+1140,Singapore Height Datum,vertical,Mean sea level determined at Victoria Dock tide gauge 1935-1937.,2009,,,1210,"Engineering, topographic mapping and GIS.",Orthometric heights. Network readjusted in 2009.,"Singapore Land Authority, Lands Department.",OGP,"2014/09/18",2014.045 2014.065,0,
+1141,IGS08,geodetic,Origin at geocentre. Derived from a subset of 232 stable IGS station coordinates at epoch 2005.0. For all practical purposes coincident with ITRF2008.,2005,7019,8901,1262,"Geodesy. GPS satellite ephemerides produced by US NGS and other International GNSS Service (IGS) analysis centres are expressed in this datum.",Realisation of ITRF2008 at epoch 2005.0.,"http://www.ngs.noaa.gov/CORS/",OGP,"2015/02/06",2014.070,0,
+1142,IG05 Intermediate Datum,geodetic,Defined by transformation from IGD05 at epoch 2004.75.,2004,7019,8901,2603,"Used only as an intermediate stage in conversions between IGD05 and Israeli Grid 05 (IG05).",,Survey of Israel.,OGP,"2014/11/19",2014.041,0,
+1143,Israeli Geodetic Datum 2005,geodetic,ITRF2000 at epoch 2004.75.,2004,7019,8901,1126,Geodetic Survey.,"Replaces Israel 1993 (datum code 6141). Replaced by IGD05/12 (datum code 1145).",Survey of Israel.,OGP,"2014/11/07",2014.041 2015.020,1,
+1144,"IG05/12 Intermediate Datum",geodetic,"Defined by transformation from IGD05/12 at epoch 2012.00.",2012,7019,8901,2603,"Used only as an intermediate stage in conversions between IGD05/12 and Israeli Grid 05/12 (IG05/12).",,Survey of Israel.,OGP,"2014/11/19",2014.041,0,
+1145,"Israeli Geodetic Datum 2005(2012)",geodetic,ITRF2000 at epoch 2012.00,2012,7019,8901,1126,Geodetic Survey.,"Replaces IGD05 (datum code 1143).",Survey of Israel.,OGP,"2014/11/07",2014.041 2015.020,1,
+1146,Ras Ghumays,vertical,Mean Sea Level at Ras Ghumays 1978 and 1979.,1979,,,4225,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,ADCO,OGP,"2015/01/26",2012.056,0,
+1147,Oman National Geodetic Datum 2014,geodetic,20 stations of the Oman primary network tied to ITRF2008 at epoch 2013.15.,2013,7019,8901,1183,Geodetic Survey.,"Replaces WGS 84 (G874).","National Survey Authority, Sultanate of Oman.",IOGP,"2015/08/11",2015.035,0,
+1148,Famagusta 1960,vertical,Mean sea level at Famagusta Harbour.,,,,3236,Topographic mapping and engineering survey.,Orthometric heights.,"Cyprus Department of Lands and Surveys (DLS).",IOGP,"2015/11/03",2014.091,0,
+1149,PNG08,vertical,"Mean sea level at 8 tide gauges around PNG, defined through application of PNG08 geoid model (transformation code 7655) to PNG94 (CRS code 5545).",2011,,,4384,Geodetic survey.,,"Quickclose Geomatics on behalf of Geodetic Section, PNG Office of the Surveyor-General.",IOGP,"2015/11/05",2015.052,0,
+1150,Kumul 34,vertical,"Kumul Platform Station 34. Propagated through bilinear interpolation of EGM96 geoid model (transformation code 10084) reduced to Kumul 34 by offset of -0.87m.",,,,4013,Engineering survey.,,Quickclose Geomatics.,IOGP,"2015/11/05",2015.052,0,
+1151,Kiunga,vertical,"PSM 9465 at Kiunga Airport. Propagated through bilinear interpolation of EGM2008 geoid model (transformation code 3858) reduced to PSM 9465 by offset of -3.0m.",,,,4383,Engineering survey.,,Quickclose Geomatics.,IOGP,"2015/11/05",2015.052,0,
 5100,Mean Sea Level,vertical,"The average height of the surface of the sea at a tide station for all stages of the tide over a 19-year period, usually determined from hourly height readings measured from a fixed predetermined reference level.",,,,1262,Hydrography.,"Approximates geoid. Users are advised to not use this generic vertical datum but to define explicit realisations of MSL by specifying location and epoch, for instance ""MSL at xxx during yyyy-yyyy"".","IHO Dictionary, S-32, 5t [...]
 5101,Ordnance Datum Newlyn,vertical,Mean Sea Level at Newlyn between 1915 and 1921.,,,,2792,"Topographic mapping, geodetic survey.",Orthometric heights.,Ordnance Survey of Great Britain,OGP,"2004/06/16",2004.100,0,"D_Ordnance_Datum_Newlyn"
 5102,National Geodetic Vertical Datum 1929,vertical,26 tide gauges in the US and Canada.,1929,,,1323,"Topographic mapping, geodetic survey.",Normal orthometric heights.,,OGP,"1996/09/12",,0,
@@ -177,7 +199,7 @@ http://www.maanmittauslaitos.fi",OGP,"2010/05/02",2008.112,0,
 5168,Wellington 1953,vertical,MSL at Wellington harbour 1909-1946.,1953,,,3773,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
 5169,"Waitangi (Chatham Island) 1959",vertical,MSL at Waitangi harbour collected in 1959.,1959,,,3894,"Geodetic survey, topographic mapping, engineering survey.",,"Interim Report GEO/T1/19/51 for LINZ by John Hannah, ""An Assessment of New Zealand's Height Systems and Options for a Future Height System"", January 2001.",OGP,"2011/06/20",2008.023 2011.048,0,
 5170,Stewart Island 1977,vertical,MSL at 3-5 high and low tides at two different locations.,1977,,,3338,"Geodetic survey, topographic mapping, engineering survey.",,"Interim Report GEO/T1/19/51 for LINZ by John Hannah, ""An Assessment of New Zealand's Height Systems and Options for a Future Height System"", January 2001.",OGP,"2008/04/04",2008.023,0,
-5171,EGM96 geoid,vertical,WGS 84 ellipsoid.,1996,,,1262,Geodesy.,,"NASA http://cddis.gsfc.nasa.gov/926/egm96/egm96.html",OGP,"2004/04/27",,0,
+5171,EGM96 geoid,vertical,Derived through EGM84 geoid undulation model consisting of spherical harmonic coefficients to degree and order 360 applied to the WGS 84 ellipsoid.,1996,,,1262,Geodesy.,"Replaces EGM84 geoid (datum code 5203). Replaced by EGM2008 geoid (datum code 1027).","NASA http://cddis.gsfc.nasa.gov/926/egm96/egm96.html",IOGP,"2015/11/25",2015.056,0,
 5172,Nivellement General du Luxembourg,vertical,"Reference point Wemperhardt defined as 528.030m above Normaal Amsterdams Peil (NAP). Datum at NAP is mean high tide in 1684. Network adjusted in 1995.",1995,,,1146,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"Administration du Cadastre et de la Topographie. http://www.etat.lu/ACT",OGP,"2004/03/09",,0,
 5173,Antalya,vertical,Mean sea Level at Antalya 1936-71.,,,,3322,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2004/11/26",2004.722,0,
 5174,Norway Normal Null 1954,vertical,MSL defined by regression at 7 gauges with between 17 and 67 years observations.,1974,,,1352,"Geodetic survey, topographic mapping, engineering survey.",Includes initial NN1954 system and NNN1957 system. Former name retained. Normal-orthometric heights. Replaced by NN2000.,Statoil,OGP,"2012/12/17",2012.094,0,
@@ -186,7 +208,7 @@ http://www.maanmittauslaitos.fi",OGP,"2010/05/02",2008.112,0,
 5177,National Vertical Network 1999,vertical,Reference point Ruse defined relative to mean sea level at Trieste in 1875.,1999,,,3307,"Geodetic survey, topographic mapping, engineering survey.",Normal-orthometric heights.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2004/03/09",,0,
 5178,Cascais,vertical,Mean Sea Level at Cascais 1938.,1938,,,1294,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2004/03/09",,0,
 5179,Constanta,vertical,Mean Sea Level at Constanta.,,,,3295,"Geodetic survey, topographic mapping, engineering survey.",Normal-orthometric heights.,"Eurogeographics, http://crs.bkg.bund.de/evrs/Relations.html",OGP,"2004/03/09",,0,
-5180,Alicante,vertical,Mean Sea Level at Alicante between 1870 and 1882.,,,,2366,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2004/03/09",,0,
+5180,Alicante,vertical,Mean Sea Level at Alicante between 1870 and 1882.,,,,4188,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2015/01/28",2014.095,0,
 5181,Deutsches Haupthoehennetz 1992,vertical,"Network adjusted in 1992. Geopotential number at reference point Wallenhorst defined as value from the UELN-73/86 adjustment. Datum at Normaal Amsterdams Peil (NAP) is mean high tide in 1684.",1992,,,3339,"Geodetic survey, topographic mapping, engineering survey.",Replaces DHHN85 in West Germany and SNN76 in East Germany. Uses Normal heights.,"Bundesamt für Kartographie und Geodäsie (BKG), http://crs.bkg.bund.de/crs-eu/",OGP,"2011/08/03",2011.071,0,
 5182,Deutsches Haupthoehennetz 1985,vertical,"Network adjusted in 1985. Height of reference point Wallenhorst defined as value from 1928 adjustment. Datum at Normaal Amsterdams Peil (NAP) is mean high tide in 1684.",1985,,,2326,"Geodetic survey, topographic mapping, engineering survey.",Replaced by DHHN92. Uses Normal-orthometric heights.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2011/08/03",2011.071,0,
 5183,SNN76,vertical,Network adjusted in 1976. Height at reference point Hoppegarten defined as 1957 value from the UPLN adjustment. Datum at Kronstadt is mean sea level of Baltic in 1833.,1976,,,1343,"Geodetic survey, topographic mapping, engineering survey.",Uses Normal heights. Replaced by DHHN92.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2004/03/09",,0,
@@ -209,7 +231,7 @@ http://www.maanmittauslaitos.fi",OGP,"2010/05/02",2008.112,0,
 5200,Huahine SAU 2001,vertical,"Fundamental benchmark: SHOM B3",2001,,,3135,"Geodetic survey, topographic mapping, engineering survey.",Included as part of NGPF - see datum code 5195.,"Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2005/08/12",,0,
 5201,Tahaa SAU 2001,vertical,"Fundamental benchmark: RN16",2001,,,3138,"Geodetic survey, topographic mapping, engineering survey.",Included as part of NGPF - see datum code 5195.,"Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2005/08/12",,0,
 5202,Bora Bora SAU 2001,vertical,"Fundamental benchmark: Vaitape quay SHOM benchmark B.",2001,,,3137,"Geodetic survey, topographic mapping, engineering survey.",Included as part of NGPF - see datum code 5195.,"Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2005/08/12",,0,
-5203,EGM84 geoid,vertical,WGS 84 ellipsoid.,1984,,,1262,Geodesy.,,"US National Geospatial-Intelligence Agency (NGA); http://earth-info.nga.mil/GandG/",OGP,"2005/09/30",,0,
+5203,EGM84 geoid,vertical,Derived through EGM84 geoid undulation model consisting of spherical harmonic coefficients to degree and order 180 applied to the WGS 84 ellipsoid.,1987,,,1262,Geodesy.,"Replaced by EGM96 geoid (datum code 5171).","US National Geospatial-Intelligence Agency (NGA); http://earth-info.nga.mil/GandG/",IOGP,"2015/11/25",2015.056,0,
 5204,International Great Lakes Datum 1955,vertical,"Mean water level 1941-1956 at Pointe-au-Père (Father's Point), Quebec. Benchmark 1248-G = 3.794m.",1955,,,3468,Hydrology.,Dynamic heights. Adopted in 1962. Replaced by IGLD 1985 in January 1992.,Coordinating Committee on Great Lakes Basic Hydraulic and Hydrologic Data,OGP,"2012/08/10",2011.047,0,
 5205,International Great Lakes Datum 1985,vertical,"Mean water level 1970-1983 at Pointe-au-Pierre (Father's Point) and 1984-1988 at Rimouski, Quebec. Benchmark 1250-G = 6.273m.",1985,,,3468,Hydrology.,Dynamic heights. Replaces IGLD 1955 from January 1992.,Coordinating Committee on Great Lakes Basic Hydraulic and Hydrologic Data,OGP,"2012/08/10",2011.047,0,
 5206,Dansk Vertikal Reference 1990,vertical,"Benchmark at Århus cathedral referenced to mean sea level determined during 1990 at 10 tide gauges: Esbjerg, Fredericia, Frederikshavn, Gedser, Hirtshals, Hornbæk, Korsør, København, Slipshavn and Århus.",,,,3237,Topographic mapping and engineering survey,Normal Orthometric heights.,"Kort & Matrikelstyrelsen",OGP,"2006/12/01",,0,
@@ -221,7 +243,7 @@ http://www.maanmittauslaitos.fi",OGP,"2010/05/02",2008.112,0,
 5212,IGN 1992 LD,vertical,"Mean sea level at Pointe-à-Pitre. Origin = marker A with defined height of 0.792m above msl. IGN 1992 LD height 0.00m is 0.629m above sounding datum at Pointe-à-Pitre.",1992,,,2893,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,IGN Paris,OGP,"2008/09/17",,0,
 5213,IGN 1988 SB,vertical,"Mean sea level 1988 at port of Gustavia. Origin = marker A.ef-2 with defined height of 0.621m above msl. IGN 1988 SB height 0.00m deduced to be 0.201m above mean sea level at Pointe-à-Pitre.",1988,,,2891,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,IGN Paris,OGP,"2008/09/17",,0,
 5214,IGN 1988 SM,vertical,"Mean sea level 1949-1950 deduced at Fort Marigot. Origin = marker AS-13 with defined height of 6.990m above msl. IGN 1988 SM height 0.00m deduced to be 0.41m above sounding datum.",1988,,,2890,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,IGN Paris,OGP,"2008/09/17",,0,
-5215,European Vertical Reference Frame 2007,vertical,"13 stations (to be completed)",2007,,,3594,Geodesy.,"Realised by geopotential numbers and Normal heights of the United European Levelling Network. Replaces EVRF2000 (datum code 5129).","European veritical data centre at Bundesamt für Kartographie und Geodäsie (BKG), Leipzig branch. http://crs.bkg.bund.de/evrs/",OGP,"2008/11/21",,0,
+5215,European Vertical Reference Frame 2007,vertical,Least squares fit to 13 stations of the EVRF2000 solution.,2007,,,3594,Geodesy.,"Realised by geopotential numbers and Normal heights of the United European Levelling Network. Replaces EVRF2000 (datum code 5129).","European veritical data centre at Bundesamt für Kartographie und Geodäsie (BKG), Leipzig branch. http://crs.bkg.bund.de/evrs/",OGP,"2015/02/12",2015.005,0,
 6001,"Not specified (based on Airy 1830 ellipsoid)",geodetic,,,7001,8901,1263,Not a valid datum.,Included for coordinate reference systems where datum is unknown.,OGP,OGP,"2000/05/03",1996.080 2000.420,0,"D_Airy_1830"
 6002,"Not specified (based on Airy Modified 1849 ellipsoid)",geodetic,,,7002,8901,1263,Not a valid datum.,Included for coordinate reference systems where datum is unknown.,OGP,OGP,"2000/05/03",1996.080 2000.420,0,"D_Airy_Modified"
 6003,"Not specified (based on Australian National Spheroid)",geodetic,,,7003,8901,1263,Not a valid datum.,Included for coordinate reference systems where datum is unknown.,OGP,OGP,"2000/05/03",1996.080 2000.420,0,"D_Australian"
@@ -273,9 +295,9 @@ http://www.maanmittauslaitos.fi",OGP,"2011/06/30",2006.270 2011.055,0,"D_KKJ"
 6124,Rikets koordinatsystem 1990,geodetic,,1982,7004,8901,1225,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces RT38 adjustment (datum code 6308)",National Land Survey of Sweden,OGP,"1997/11/13",,0,"D_RT_1990"
 6125,Samboja,geodetic,Original origin station P2 Exc now destroyed.  Extensions recomputed using Toran station T9 as origin.,,7004,8901,1328,Topographic mapping.,,Total Indonesia.,OGP,"1997/11/13",,1,"D_Samboja"
 6126,"Lithuania 1994 (ETRS89)",geodetic,Constrained to 4 ETRS89 points in Lithuania from the EUREF Baltic 1992 campaign..,1994,7019,8901,1145,"Topographic mapping, geodetic survey.",Densification of ETRS89 during the 1992 Baltic campaign.,HNIT-Baltic GeoInfoServisas,OGP,"1998/03/12",,0,"D_Lithuania_1994"
-6127,Tete,geodetic,"Fundamental point: Tete.",,7008,8901,3281,Topographic mapping.,,"Mozambique Direcção Nacional de Geografia e Cadastral (DINAGECA).",OGP,"1998/04/16",,0,"D_Tete"
+6127,Tete,geodetic,"Fundamental point: Tete.",1960,7008,8901,3281,Topographic mapping.,,"Mozambique Direcção Nacional de Geografia e Cadastral (DINAGECA).",OGP,"2014/11/19",2014.076,0,"D_Tete"
 6128,Madzansua,geodetic,"Fundamental point: Madzansua.",,7008,8901,1315,Topographic mapping.,"Replaced by transformation to Tete datum (datum code 6127).","Mozambique Direcção Nacional de Geografia e Cadastral (DINAGECA).",OGP,"1998/04/16",,0,"D_Madzansua"
-6129,Observatario,geodetic,"Fundamental point: Maputo observatory.",,7008,8901,1329,Topographic mapping.,"Replaced by transformation to Tete datum (datum code 6127).","Mozambique Direcção Nacional de Geografia e Cadastral (DINAGECA).",OGP,"1998/04/16",,0,"D_Observatario"
+6129,Observatario,geodetic,"Fundamental point: Campos Rodrigues observatory, Maputo.",1907,7008,8901,1329,Topographic mapping.,"Replaced by transformation to Tete datum (datum code 6127).","Mozambique Direcção Nacional de Geografia e Cadastral (DINAGECA).",OGP,"2014/11/19",2014.076,0,"D_Observatario"
 6130,"Moznet (ITRF94)",geodetic,ITRF94 at epoch 1996.9,,7030,8901,1167,Topographic mapping.,,"Mozambique Direcção Nacional de Geografia e Cadastral (DINAGECA).",OGP,"2006/08/18",2006.770,0,"D_Moznet"
 6131,Indian 1960,geodetic,DMA extension over IndoChina of the Indian 1954 network adjusted  to better fit local geoid.,,7015,8901,4007,Topographic mapping.,"Also known as Indian (DMA Reduced).",,OGP,"2012/03/25",2003.361 2012.032,0,"D_Indian_1960"
 6132,Final Datum 1958,geodetic,"Fundamental point: Maniyur.  Latitude: 31°23'59.19""N, longitude: 48°32'31.38""E (of Greenwich).",,7012,8901,1300,Oil industry mapping.,Network included in Nahrwan 1967 adjustment.,IOEPC records,OGP,"2008/06/24",2008.045,0,"D_FD_1958"
@@ -287,7 +309,7 @@ http://www.maanmittauslaitos.fi",OGP,"2011/06/30",2006.270 2011.055,0,"D_KKJ"
 6138,St. George Island,geodetic,"Fundamental point latitude: 56°36'11.31""N, longitude: 169°32'36.00""W (of Greenwich).",,7008,8901,1331,Topographic mapping.,"Many Alaskan islands were never on NAD27 but rather on independent datums.  NADCON conversion program provides transformation from St. George Island Datum to NAD83 (original 1986 realization) - making the transformation appear to user as if from NAD27.","http://www.ngs.noaa.gov/ (NADCON readme file)",OGP,"2008/06/24",2003.362 2008. [...]
 6139,Puerto Rico,geodetic,"Fundamental point: Cardona Island Lighthouse. Latitude:17°57'31.40""N, longitude: 66°38'07.53""W (of Greenwich).",1901,7008,8901,1335,Topographic mapping.,"NADCON conversion program provides transformation from Puerto Rico Datum to NAD83 (original 1986 realization) but making the transformation appear to user as if from NAD27.","Ordnance Survey of Great Britain and http://www.ngs.noaa.gov/ (NADCON readme file).",OGP,"2008/06/24",2003.362 2008.045,0,"D_Puerto_Rico"
 6140,NAD83 Canadian Spatial Reference System,geodetic,,1998,7019,8901,1061,Geodetic survey.,,"Natural Resources of Canada, CSRS website.  http://www.geod.nrcan.gc.ca",OGP,"2007/09/25",2005.880 2006.461 2007.026 2007.092,0,"D_North_American_1983_CSRS"
-6141,Israel,geodetic,"Fundamental point:  Latitude: 31°44'03.817""N, longitude: 35°12'16.261""E (of Greenwich).",,7019,8901,2603,Topographic mapping.,,Survey of Israel.,OGP,"2008/06/24",2002.340 2004.150 2008.045,0,"D_Israel"
+6141,Israel 1993,geodetic,"Fundamental point:  Latitude: 31°44'03.817""N, longitude: 35°12'16.261""E (of Greenwich).",,7019,8901,2603,Topographic mapping.,"Replaces Palestine 1923 (datum code 6281). Replaced by IGD05 (datum code 1143).",Survey of Israel.,OGP,"2014/11/21",2002.340 2004.150 2008.045 2014.041,0,"D_Israel"
 6142,Locodjo 1965,geodetic,"Fundamental point: T5 Banco. Latitude: 5°18'50.5""N, longitude: 4°02'05.1""W (of Greenwich).",1965,7012,8901,1075,Topographic mapping.,,IGN Paris.,OGP,"2008/06/24",2008.045,0,"D_Locodjo_1965"
 6143,Abidjan 1987,geodetic,"Fundamental point: Abidjan I. Latitude: 5°18'51.01""N, longitude: 4°02'06.04""W (of Greenwich).",1987,7012,8901,1075,Topographic mapping.,,IGN Paris.,OGP,"2008/06/24",2008.045,0,"D_Abidjan_1987"
 6144,Kalianpur 1937,geodetic,"Fundamental point: Kalianpur. Latitude: 24° 07'11.260""N, longitude: 77°39'17.570""E (of Greenwich).",1937,7015,8901,1308,Topographic mapping.,Replaces 1880 adjustment except for topographic mapping.  Replaced in Bangladesh and Pakistan by 1962 metrication conversion and in India by 1975 metrication conversion.,"G. Bomford; ""The Re-adjustment of the Indian Triangulation""; Survey of India Professional Paper 28; 1939.",OGP,"2008/06/24",2008.045,0,"D_Kalianpur_1937"
@@ -335,7 +357,7 @@ en el terreno que definen el Sistema Geodésico Nacional.  [A geodetic network o
 6188,OSNI 1952,geodetic,Position fixed to the coordinates from the 19th century Principle Triangulation of station Divis. Scale and orientation controlled by position of Principle Triangulation stations Knocklayd and Trostan.,1952,7001,8901,2530,Geodetic survey and topographic mapping.,"Replaced by Geodetic Datum of 1965 alias 1975 Mapping Adjustment or TM75 (datum code 6300).",Ordnance Survey of Northern Ireland.,OGP,"2001/11/06",,0,"D_OSNI_1952"
 6189,Red Geodesica Venezolana,geodetic,Realised by a frame of 67 stations observed in 1995 as a densification of the SIRGAS campaign and adjusted in the ITRF94.,2000,7019,8901,1251,Geodetic survey.,,Servicio Autonomo de Geografia y Cartografia Nacional.,OGP,"2001/06/11",,0,"D_REGVEN"
 6190,Posiciones Geodesicas Argentinas 1998,geodetic,"A geodetic network of 136 high accuracy surveyed points. Densification of SIRGAS 1995; ITRF94 at epoch 1995.42.",1998,7019,8901,1033,Geodetic survey.,"Technically, but not legally, this datum replaced the 1994 POSGAR adjustment (code 6694) until adoption of the 2007 POSGAR adjustment (code 1062) in May 2009.","Instituto Geográfico Militar de la República Argentina, http://www.igm.gov.ar",OGP,"2011/03/28",2003.361 2005.460 2005.480 2006 [...]
-6191,Albanian 1987,geodetic,,1987,7024,8901,3212,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"EuroGeographics; http://crs.bkg.bund.de/crs-eu/",OGP,"2011/07/20",2011.062,0,"D_Albanian_1987"
+6191,Albanian 1987,geodetic,,1987,7024,8901,3212,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"EuroGeographics; http://crs.bkg.bund.de/crs-eu/",OGP,"2014/11/21",2011.062 2014.078,0,"D_Albanian_1987"
 6192,Douala 1948,geodetic,"South pillar of Douala base; 4°00'40.64""N, 9°42'30.41""E (of Greenwich).",1948,7022,8901,2555,Topographic mapping.,"Replaced  by Manoca 1962 datum (code 6193).",TotalFinaElf,OGP,"2008/06/24",2005.830 2008.045,0,"D_Douala_1948"
 6193,Manoca 1962,geodetic,"Reservoir centre at the  Manoca tower (""tube Suel""), 3°51'49.896""N, 9°36'49.347""E (of Greenwich).",1962,7011,8901,2555,Topographic mapping.,"The intent of the Bukavu 1953 conference was to adopt the Clarke 1880 (RGS) ellipsoid (code 7012) but in practice this datum has used the IGN version.  Replaces Douala 1948 (code 6192).",TotalFinaElf,OGP,"2008/06/24",2008.045,0,"D_Manoca_1962"
 6194,Qornoq 1927,geodetic,"Fundamental point: Station 7008. Latitude: 64°31'06.27""N, longitude: 51°12'24.86""W (of Greenwich).",1927,7022,8901,3362,Topographic mapping.,,"Kort & Matrikelstyrelsen, Copenhagen. Origin coordinates from NIMA http://earth-info.nima.mil/",OGP,"2008/06/24",2003.362 2005.460 2006.220 2008.045,0,"D_Qornoq_1927"
@@ -345,7 +367,7 @@ en el terreno que definen el Sistema Geodésico Nacional.  [A geodetic network o
 6198,Kousseri,geodetic,"IGN astronomical station Dabanga; 11°55'05.9""N  14°38'40.8""E (of Greenwich).",,7012,8901,2591,Topographic mapping.,,TotalFinaElf,OGP,"2008/06/24",2008.045,0,"D_Kousseri"
 6199,Egypt 1930,geodetic,"Fundamental point: Station F1 (Venus). Latitude: 30°01'42.86""N, longitude: 31°16'37.05""E (of Greenwich).",1930,7022,8901,3242,Used for scientific purposes only.,"Note that Egypt 1930 uses the International 1924 ellipsoid, unlike the Egypt 1907 datum (code 6229) which uses the Helmert ellipsoid. Oil industry references to the Egypt 1930 datum name and the Helmert ellipsoid probably mean Egypt 1907 datum.",,OGP,"2008/06/24",2008.045,0,"D_Egypt_1930"
 6200,Pulkovo 1995,geodetic,"Fundamental point: Pulkovo observatory. Latitude: 59°46'15.359""N, longitude: 30°19'28.318""E (of Greenwich).",1995,7024,8901,1198,Scientific adjustment.,,"""Main Terms of Reference for the State Geodetic Network""; Federal Geodetic Service of Russia; 1994",OGP,"2008/06/24",2008.045,0,"D_Pulkovo_1995"
-6201,Adindan,geodetic,"Fundamental point: Station 15; Adindan. Latitude: 22°10'07.110""N, longitude: 31°29'21.608""E (of Greenwich).",,7012,8901,1271,Topographic mapping.,"The 12th parallel traverse of 1966-70 (Point 58 datum, code 6620) is connected to the Adindan network in western Sudan. This has given rise to misconceptions that the Adindan network is used in west Africa.",,OGP,"2008/06/24",2002.431 2003.361 2008.045,0,"D_Adindan"
+6201,Adindan,geodetic,"Fundamental point: Station 15; Adindan. Latitude: 22°10'07.110""N, longitude: 31°29'21.608""E (of Greenwich).",1958,7012,8901,1271,Topographic mapping.,"The 12th parallel traverse of 1966-70 (Point 58 datum, code 6620) is connected to the Blue Nile 1958 network in western Sudan. This has given rise to misconceptions that the Blue Nile network is used in west Africa.","US Coast and Geodetic Survey via Geophysical Reasearch vol 67 #11, October 1962.",IOGP,"2015/04/22 [...]
 6202,Australian Geodetic Datum 1966,geodetic,"Fundamental point: Johnson Memorial Cairn. Latitude: 25°56'54.5515""S, longitude: 133°12'30.0771""E (of Greenwich).",1966,7003,8901,1279,Topographic mapping.,,"Australian Map Grid Technical Manual. National Mapping Council of Australia Technical Publication 7; 1972.",OGP,"2008/06/24",2003.361 2008.045,0,"D_Australian_1966"
 6203,Australian Geodetic Datum 1984,geodetic,"Fundamental point: Johnson Memorial Cairn. Latitude: 25°56'54.5515""S, longitude: 133°12'30.0771""E (of Greenwich).",1984,7003,8901,2576,Topographic mapping.,"Uses all data from 1966 adjustment with additional observations, improved software and a geoid model.","""GDA technical manual v2_2"", Intergovernmental Committee on Surveying and Mapping. www.anzlic.org.au/icsm/gdtm/",OGP,"2008/06/24",2003.290 2003.361 2008.045,0,"D_Australian_1984"
 6204,Ain el Abd 1970,geodetic,"Fundamental point: Ain El Abd.  Latitude: 28°14'06.171""N, longitude: 48°16'20.906""E (of Greenwich).",1970,7022,8901,1272,Topographic mapping.,,,OGP,"2008/06/24",2003.361 2008.045,0,"D_Ain_el_Abd_1970"
@@ -389,7 +411,7 @@ US NGA, http://earth-info.nga.mil/GandG/index.html",OGP,"2008/08/12",2003.362 20
 6242,Jamaica 1969,geodetic,"Fundamental point: Fort Charles Flagstaff. Latitude: 17°55'55.800""N, longitude: 76°56'37.260""W (of Greenwich).",1969,7008,8901,3342,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"Survey Department, Government of Jamaica, 1983.",OGP,"2008/06/24",2004.510 2008.045,0,"D_Jamaica_1969"
 6243,Kalianpur 1880,geodetic,"Fundamental point: Kalianpur. Latitude: 24°07'11.260""N, longitude: 77°39'17.570""E (of Greenwich).",1880,7042,8901,1307,Topographic mapping.,"Includes 1916 extension into Burma (Myanmar).  Replaced by 1937 adjustment.","G. Bomford; ""The Re-adjustment of the Indian Triangulation""; Survey of India Professional Paper 28; 1939.",OGP,"2008/06/24",1997.231 2004.290 2008.045,0,"D_Kalianpur_1880"
 6244,Kandawala,geodetic,"Fundamental point: Kandawala. Latitude: 7°14'06.838""N, longitude: 79°52'36.670""E.",1930,7015,8901,3310,Topographic mapping.,,"Abeyratne, Featherstone and Tantrigoda in Survey Review vol. 42 no. 317 (July 2010).",OGP,"2010/09/24",2010.080,0,"D_Kandawala"
-6245,Kertau 1968,geodetic,"Fundamental point: Kertau. Latitude: 3°27'50.710""N, longitude: 102°37'24.550""E (of Greenwich).",1968,7018,8901,1309,"Geodetic survey, cadastre.","Replaces MRT48 and earlier adjustments. Adopts metric conversion of 39.370113 inches per metre. Not used for 1969 metrication of RSO grid - see Kertau (RSO) (code 6751).",Defence Geographic Centre.,OGP,"2008/06/24",2006.251 2008.045,0,"D_Kertau"
+6245,Kertau 1968,geodetic,"Fundamental point: Kertau. Latitude: 3°27'50.710""N, longitude: 102°37'24.550""E (of Greenwich).",1968,7018,8901,4223,"Geodetic survey, cadastre.","Replaces MRT48 and earlier adjustments. Adopts metric conversion of 39.370113 inches per metre. Not used for 1969 metrication of RSO grid - see Kertau (RSO) (code 6751).",Defence Geographic Centre.,OGP,"2014/11/21",2006.251 2008.045 2014.071,0,"D_Kertau"
 6246,Kuwait Oil Company,geodetic,"Fundamental point: K28.  Latitude: 29°03'42.348""N, longitude: 48°08'42.558""E (of Greenwich).",1952,7012,8901,3267,Oil industry mapping.,,,OGP,"2008/06/24",2004.410 2008.045,0,"D_Kuwait_Oil_Company"
 6247,La Canoa,geodetic,"Fundamental point: La Canoa. Latitude: 8°34'17.170""N, longitude: 63°51'34.880""W (of Greenwich).",,7022,8901,3327,"Geodetic survey, topographic mapping, engineering survey.","Origin and network incorporated within PSAD56 (datum code 6248).",,OGP,"2011/01/25",2008.045 2011.001,0,"D_La_Canoa"
 6248,Provisional South American Datum 1956,geodetic,"Fundamental point: La Canoa. Latitude: 8°34'17.170""N, longitude: 63°51'34.880""W (of Greenwich).",1956,7022,8901,1348,Topographic mapping.,Same origin as La Canoa datum.,,OGP,"2008/06/24",2008.045,0,"D_Provisional_S_American_1956"
@@ -400,7 +422,7 @@ US NGA, http://earth-info.nga.mil/GandG/index.html",OGP,"2008/08/12",2003.362 20
 6253,Luzon 1911,geodetic,"Fundamental point: Balacan. Latitude: 13°33'41.000""N, longitude: 121°52'03.000""E (of Greenwich).",1911,7008,8901,3969,Topographic mapping.,"Replaced by Philippine Reference system of 1992 (datum code 6683).",Coast and Geodetic Survey,OGP,"2012/03/25",2004.730 2008.045 2012.032,0,"D_Luzon_1911"
 6254,Hito XVIII 1963,geodetic,Chile-Argentina boundary survey.,1963,7022,8901,1303,Geodetic survey.,Used in Tierra del Fuego.,Various oil company records.,OGP,"1995/06/02",,0,"D_Hito_XVIII_1963"
 6255,Herat North,geodetic,"Fundamental point: Herat North. Latitude: 34°23'09.08""N, longitude: 64°10'58.94""E (of Greenwich).",,7022,8901,1024,Topographic mapping.,,"NIMA http://earth-info.nima.mil/",OGP,"2008/06/24",2003.362 2005.460 2008.045,0,"D_Herat_North"
-6256,Mahe 1971,geodetic,"Fundamental point: Mahe.",1971,7012,8901,2369,Topographic mapping.,,,OGP,"2012/02/13",2012.025,0,"D_Mahe_1971"
+6256,Mahe 1971,geodetic,"Fundamental point: Station SITE. Latitude: 4°40'14.644""S, longitude: 55°28'44.488""E (of Greenwich).",1971,7012,8901,2369,US military survey.,"South East Island 1943 (datum code 1138) used for topographic mapping, cadastral and hydrographic survey.","Clifford Mugnier's September 2007 PE&RS ""Grids and Datums"" article on Seychelles (www.asprs.org/resources/grids/).",OGP,"2014/09/08",2012.025 2014.037,0,"D_Mahe_1971"
 6257,Makassar,geodetic,"Fundamental point: station P1, Moncongloe. Latitude: 5°08'41.42""S, long 119°24'14.94""E (of Greenwich).",,7004,8901,1316,Topographic mapping.,,"NIMA http://earth-info.nima.mil/",OGP,"2008/06/24",2003.361 2005.460 2008.045,0,"D_Makassar"
 6258,European Terrestrial Reference System 1989,geodetic,Fixed to the stable part of the Eurasian continental plate and consistent with ITRS at the epoch 1989.0.,1989,7019,8901,1298,Geodetic survey.,"The distinction in usage between ETRF89 and ETRS89 is confused: although in principle conceptually different in practice both are used for the realisation.",,OGP,"2003/08/14",1997.110 1997.550 1999.111 2000.720 2003.260,0,"D_ETRS_1989"
 6259,Malongo 1987,geodetic,"Fundamental point: Station Y at Malongo base camp. Latitude: 5°23'30.810""S, longitude: 12°12'01.590""E (of Greenwich).",1987,7022,8901,3180,Oil industry offshore exploration and production from 1987.,"Replaced Mhast (offshore) (code 6705) in 1987. Origin coordinates constrained to those of Mhast (offshore) but other station coordinates differ. References to ""Mhast"" since 1987 often should have stated ""Malongo 1987"".",Chevron Petroleum Technology.,OGP,"200 [...]
@@ -465,8 +487,8 @@ Trinidad 1903 / Trinidad Grid coordinates (Clarke's links): 333604.30 E, 436366.
 6319,Kuwait Utility,geodetic,,,7019,8901,1310,"Cadastre, engineering survey.",,,OGP,"1996/04/12",,0,"D_Kuwait_Utility"
 6322,World Geodetic System 1972,geodetic,Developed from a worldwide distribution of terrestrial and geodetic satellite observations and defined through a set of station coordinates.,1972,7043,8901,1262,Satellite navigation.,Used by GPS before 1987. For Transit satellite positioning see also WGS 72BE.,"NIMA http://earth-info.nima.mil/",OGP,"2006/08/24",1999.030 2003.362 2005.460 2006.820,0,"D_WGS_1972"
 6324,WGS 72 Transit Broadcast Ephemeris,geodetic,,1972,7043,8901,1262,Satellite navigation.,Alleged datum for use with Transit broadcast ephemeris prior to 1989. Relationship to WGS 72 has changed over time.,,OGP,"2006/08/24",1999.030 2006.820,0,"D_WGS_1972_BE"
-6326,World Geodetic System 1984,geodetic,"Defined through a consistent set of station coordinates. These have changed with time: by 0.7m on 29/06/1994 (G730), a further 0.2m on 29/01/1997 (G873) and a further 0.06m on 20/01/2002 (G1150) and on 8/02/2012 (G1674).",1984,7030,8901,1262,Satellite navigation.,"EPSG::6326 has been the then current realisation. No distinction is made between the original and subsequent (G730, G873, G1150 and G1674) WGS 84 frames. Since 1997, WGS 84 has been mai [...]
-http://gis-lab.info/docs/nima-tr8350.2-addendum.pdf",OGP,"2013/06/15",2002.151 2002.890 2003.270 2005.460 2005.550 2006.810 2012.097,0,
+6326,World Geodetic System 1984,geodetic,"Defined through a consistent set of station coordinates. These have changed with time: by 0.7m on 1994-06-29 (G730), a further 0.2m on 1997-01-29 (G873),  0.06m on 2002-01-20 (G1150), 0.2m on 2012-02-08 (G1674) and 0.02m on 2013-10-16 (G1762).",,7030,8901,1262,Satellite navigation.,"EPSG::6326 has been the then current realisation. No distinction is made between the original and subsequent (G730, G873, G1150, G1674 and G1762) WGS 84 frames. Since [...]
+http://gis-lab.info/docs/nima-tr8350.2-addendum.pdf. Also NGA.STND.0036_1.0.0_WGS84 of 2014-07-08.",OGP,"2014/11/21",2002.151 2002.890 2003.270 2005.460 2005.550 2006.810 2012.097 2014.081,0,
 6600,Anguilla 1957,geodetic,"Fundamental point: station A4, Police.",1957,7012,8901,3214,Topographic mapping.,,Ordnance Survey of Great Britain.,OGP,"1999/04/22",,0,"D_Anguilla_1957"
 6601,Antigua 1943,geodetic,"Fundamental point: station A14.",1943,7012,8901,1273,Topographic mapping.,,Ordnance Survey of Great Britain.,OGP,"1999/04/22",,0,"D_Antigua_1943"
 6602,Dominica 1945,geodetic,"Fundamental point: station M12.",1945,7012,8901,3239,Topographic mapping.,,Ordnance Survey of Great Britain.,OGP,"1999/04/22",,0,"D_Dominica_1945"
@@ -486,7 +508,7 @@ http://gis-lab.info/docs/nima-tr8350.2-addendum.pdf",OGP,"2013/06/15",2002.151 2
 6616,Selvagem Grande,geodetic,,,7022,8901,2779,Topographic mapping.,,"Instituto Geografico e Cadastral Lisbon http://www.igeo.pt",OGP,"2003/08/14",2003.232,0,"D_Selvagem_Grande_1938"
 6618,South American Datum 1969,geodetic,"Fundamental point: Chua. Geodetic latitude: 19°45'41.6527""S; geodetic longitude: 48°06'04.0639""W (of Greenwich). (Astronomic coordinates: Latitude 19°45'41.34""S +/- 0.05"", longitude 48°06'07.80""W +/- 0.08"").",1969,7050,8901,1358,Topographic mapping.,"SAD69 uses GRS 1967 ellipsoid but with 1/f to exactly 2 decimal places. In Brazil only, replaced by SAD69(96) (datum code 1075).",DMA 1974.,OGP,"2011/07/27",2003.362 2008.045 2011.053,0,"D_South [...]
 6619,SWEREF99,geodetic,Densification of ETRS89.,1999,7019,8901,1225,"Geodetic survey, cadastre, topographic mapping, engineering survey.","The solution was calculated in ITRF 97 epoch 1999.5, and has subsequently been corrected to ETRS 89 in accordance with guidelines given by EUREF.","National Land Survey of Sweden http://www.lantmateriet.se",OGP,"2010/03/01",2009.024,0,"D_SWEREF99"
-6620,Point 58,geodetic,"Fundamental point: Point 58. Latitude: 12°52'44.045""N, longitude: 3°58'37.040""E (of Greenwich).",1969,7012,8901,2790,Geodetic survey,Used as the basis for computation of the 12th Parallel traverse conducted 1966-70 from Senegal to Chad and connecting to the Adindan triangulation in Sudan.,IGN Paris.,OGP,"2012/01/05",2008.045 2011.090,0,"D_Point_58"
+6620,Point 58,geodetic,"Fundamental point: Point 58. Latitude: 12°52'44.045""N, longitude: 3°58'37.040""E (of Greenwich).",1969,7012,8901,2790,Geodetic survey,"Used as the basis for computation of the 12th Parallel traverse conducted 1966-70 from Senegal to Chad and connecting to the Blue Nile 1958 (Adindan) triangulation in Sudan.",IGN Paris.,IOGP,"2015/04/22",2008.045 2011.090 2015.010,0,"D_Point_58"
 6621,Fort Marigot,geodetic,,,7022,8901,2828,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RRAF 1991 (datum code 1047).",IGN Paris.,OGP,"2009/11/24",2009.073,0,"D_Fort_Marigot"
 6622,Guadeloupe 1948,geodetic,,1948,7022,8901,2829,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RRAF 1991 (datum code 1047).",IGN Paris.,OGP,"2009/11/24",2004.561 2009.073,0,"D_Sainte_Anne"
 6623,Centre Spatial Guyanais 1967,geodetic,"Fundamental point: Kourou-Diane. Latitude: 5°15'53.699""N, longitude: 52°48'09.149""W (of Greenwich).",1967,7022,8901,3105,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RGFG95 (code 6624).",IGN Paris.,OGP,"2008/06/24",2004.562 2008.045,0,"D_CSG_1967"
@@ -514,15 +536,15 @@ http://gis-lab.info/docs/nima-tr8350.2-addendum.pdf",OGP,"2013/06/15",2002.151 2
 6645,Reseau Geodesique Nouvelle Caledonie 1991,geodetic,ITRF90 at epoch 1989.0,1989,7022,8901,1174,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,Service Topographique de la Nouvelle Caledonie.,OGP,"2002/11/29",,1,"D_RGNC_1991"
 6646,Grand Comoros,geodetic,"Fundamental point: M'Tsaoueni.  Latitude: 11°28'32.200""S, longitude: 43°15'42.315""E (of Greenwich).",,7022,8901,2807,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,IGN Paris.,OGP,"2008/06/24",2008.045,0,"D_Grand_Comoros"
 6647,International Terrestrial Reference Frame 1988,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS).",1988,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) at epoch 1988.0. Replaced by ITRF89 (code 6648).","International Earth Rotation Service (IERS) Annual Report for 1988. Also IGN Paris http://lareg.ensg.ign.fr/ITRF",OGP,"2006/10/13",2 [...]
-6648,International Terrestrial Reference Frame 1989,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS).",1989,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) at epoch 1989.0. Replaces ITRF88 (code 6647). Replaced by ITRF90 (code 6649).","International Earth Rotation Service (IERS) Technical Note No. 6. Also IGN Paris http://lareg.ensg.ign. [...]
-6649,International Terrestrial Reference Frame 1990,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS).",1990,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) at epoch 1990.0. Replaces ITRF89 (code 6648). Replaced by ITRF91 (code 6650).","International Earth Rotation Service (IERS) Technical Note No. 9. Also IGN Paris http://lareg.ensg.ign. [...]
-6650,International Terrestrial Reference Frame 1991,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS).",1991,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) at epoch 1991.0. Replaces ITRF90 (code 6649). Replaced by ITRF92 (code 6651).","International Earth Rotation Service (IERS) Technical Note No. 12. Also IGN Paris http://lareg.ensg.ign [...]
-6651,International Terrestrial Reference Frame 1992,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS).",1992,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) at epoch 1992.0. Replaces ITRF91 (code 6650). Replaced by ITRF93 (code 6652).","International Earth Rotation Service (IERS) Technical Note No. 15. Also IGN Paris http://lareg.ensg.ign [...]
-6652,International Terrestrial Reference Frame 1993,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS).",1993,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) at epoch 1993.0. Replaces ITRF92 (code 6651). Replaced by ITRF94 (code 6653).","International Earth Rotation Service (IERS) Technical Note No. 18. Also IGN Paris http://lareg.ensg.ign [...]
-6653,International Terrestrial Reference Frame 1994,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS).",1994,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) at epoch 1994.0. Replaces ITRF93 (code 6652). Replaced by ITRF96 (code 6654).","International Earth Rotation Service (IERS) Technical Note No. 20. Also IGN Paris http://lareg.ensg.ign [...]
-6654,International Terrestrial Reference Frame 1996,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS).",1996,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) at epoch 1996.0. Replaces ITRF94 (code 6653). Replaced by ITRF97 (code 6655).","International Earth Rotation Service (IERS) Technical Note No. 24. Also IGN Paris http://lareg.ensg.ign [...]
-6655,International Terrestrial Reference Frame 1997,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS).",1997,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) at epoch 1997.0. Replaces ITRF96 (code 6654). Replaced by ITRF2000 (code 6656).","International Earth Rotation Service (IERS) Technical Note No. 27. Also IGN Paris http://lareg.ensg.i [...]
-6656,International Terrestrial Reference Frame 2000,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS).",2000,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) at epoch 2000.0. Replaces ITRF97 (code 6655). Replaced by ITRF2005 (code 6896).","IGN Paris http://lareg.ensg.ign.fr/ITRF",OGP,"2011/02/25",2006.770 2006.892 2011.002,0,
+6648,International Terrestrial Reference Frame 1989,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS) for epoch 1988.0.",1988,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from April 1991. Replaces ITRF88 (code 6647). Replaced by ITRF90 (code 6649).","International Earth Rotation Service (IERS) Technical Note No. 6, April 1991. Also IGN [...]
+6649,International Terrestrial Reference Frame 1990,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS) for epoch 1988.0.",1988,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from December 1991. Replaces ITRF89 (code 6648). Replaced by ITRF91 (code 6650).","International Earth Rotation Service (IERS) Technical Note No. 9, December 1991. Al [...]
+6650,International Terrestrial Reference Frame 1991,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS) for epoch 1988.0.",1988,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from October 1992. Replaces ITRF90 (code 6649). Replaced by ITRF92 (code 6651).","International Earth Rotation Service (IERS) Technical Note No. 12, October 1992. Als [...]
+6651,International Terrestrial Reference Frame 1992,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 287 3-dimensional Cartesian station coordinates (SCS) for epoch 1988.0.",1988,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from October 1993. Replaces ITRF91 (code 6650). Replaced by ITRF93 (code 6652).","International Earth Rotation Service (IERS) Technical Note No. 15, October 1993. [...]
+6652,International Terrestrial Reference Frame 1993,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS) for epoch 1993.0.",1993,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from October 1994. Replaces ITRF92 (code 6651). Replaced by ITRF94 (code 6653).","International Earth Rotation Service (IERS) Technical Note No. 18, October 1994. Als [...]
+6653,International Terrestrial Reference Frame 1994,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS) for epoch 1993.0.",1993,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from March 1996. Replaces ITRF93 (code 6652). Replaced by ITRF96 (code 6654).","International Earth Rotation Service (IERS) Technical Note No. 20, March 1996. Also IG [...]
+6654,International Terrestrial Reference Frame 1996,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS) for epoch 1997.0.",1997,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from May 1998. Replaces ITRF94 (code 6653). Replaced by ITRF97 (code 6655).","International Earth Rotation Service (IERS) Technical Note No. 24, May 1998. Also IGN Pa [...]
+6655,International Terrestrial Reference Frame 1997,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS) for epoch 1997.0.",1997,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from May 1999. Replaces ITRF96 (code 6654). Replaced by ITRF2000 (code 6656).","International Earth Rotation Service (IERS) Technical Note No. 27, May 1999. Also IGN  [...]
+6656,International Terrestrial Reference Frame 2000,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS) for epoch 1997.0.",1997,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from 2004. Replaces ITRF97 (code 6655). Replaced by ITRF2005 (code 6896).","International Earth Rotation Service (IERS) Technical Note No. 31, published in 2004. Also [...]
 6657,Reykjavik 1900,geodetic,"Fundamental point:  Latitude: 64°08'31.88""N, longitude: 21°55'51.15""W (of Greenwich).",1900,7051,8901,3262,Medium scale topographic mapping.,,"Landmaelingar Islands (National Survey of Iceland).",OGP,"2008/06/24",2008.045,0,"D_Reykjavik_1900"
 6658,Hjorsey 1955,geodetic,"Fundamental point:  Latitude: 64°31'29.26""N, longitude: 22°22'05.84""W (of Greenwich).",1955,7022,8901,3262,"1/50,000 scale topographic mapping.",,"Landmaelingar Islands (National Survey of Iceland).",OGP,"2008/06/24",2008.045,0,"D_Hjorsey_1955"
 6659,Islands Net 1993,geodetic,ITRF93 at epoch 1993.6.,1996,7019,8901,1120,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by ISN2004 (datum code 1060).","Landmaelingar Islands (National Survey of Iceland).",OGP,"2010/11/12",2006.770 2010.101,0,"D_Islands_Network_1993"
@@ -609,7 +631,7 @@ For Selvagens see Selvagem Grande (datum code 6616).","Instituto Geografico e Ca
 6741,Faroe Datum 1954,geodetic,Astronomical observations at 3 points.,1954,7022,8901,3248,"Geodetic survey, topographic mapping, engineering and cadastral survey.","Replaced by ED50 in late 1970's for all purposes other than cadastre. Replaced by fk89 for cadastre.","Kort & Matrikelstyrelsen (KMS), Copenhagen.",OGP,"2006/08/04",2005.472,0,"D_Faroe_Datum_1954"
 6742,Geodetic Datum of Malaysia 2000,geodetic,"ITRF2000, epoch 2000.0.",2000,7019,8901,1151,"Geodetic survey, topographic mapping, engineering and cadastrral survey.",Replaces all older Malaysian datums.,"GDM2000 Technical Manual; Department of Survey and Mapping Malaysia. www.jupem.gov.my",OGP,"2006/03/16",,0,"D_GDM_2000"
 6743,Karbala 1979,geodetic,"Fundamental point: Karbala. Latitude: 32°34'14.4941""N, longitude: 44°00'49.6379""E.",1979,7012,8901,3625,Geodetic survey.,National geodetic network established by Polservice consortium.,Various industry sources.,OGP,"2011/01/25",2009.003 2011.004,0,"D_Karbala_1979_Polservice"
-6744,Nahrwan 1934,geodetic,"Fundamental point: Nahrwan south base.  Latitude: 33°19'10.87""N, longitude: 44°43'25.54""E (of Greenwich).",1934,7012,8901,3390,Oil exploration and production.,"This adjustment later discovered to have a significant orientation error. In Iran replaced by FD58. In Iraq, replaced by Nahrwan 1967.",Various industry sources.,OGP,"2008/06/24",2008.045,0,"D_Nahrwan_1934"
+6744,Nahrwan 1934,geodetic,"Fundamental point: Nahrwan south base.  Latitude: 33°19'10.87""N, longitude: 44°43'25.54""E (of Greenwich).",1934,7012,8901,4238,Oil exploration and production.,"This adjustment later discovered to have a significant orientation error. In Iran replaced by FD58. In Iraq, replaced by Karbala 1979.",Various industry sources.,OGP,"2015/02/12",2008.045 2014.070,0,"D_Nahrwan_1934"
 6745,"Rauenberg Datum/83",geodetic,"Fundamental point: Rauenberg. Latitude: 52°27'12.021""N, longitude: 13°22'04.928""E (of Greenwich). This station was destroyed in 1910 and the station at Potsdam substituted as the fundamental point.",1990,7004,8901,2545,"Geodetic survey, cadastre, topographic mapping, engineering survey.","RD/83 is the realisation of DHDN in Saxony. It is the resultant of applying a transformation derived at 106 points throughout former East Germany to Pulkovo 1942/83 [...]
 6746,"Potsdam Datum/83",geodetic,"Fundamental point: Rauenberg. Latitude: 52°27'12.021""N, longitude: 13°22'04.928""E (of Greenwich). This station was destroyed in 1910 and the station at Potsdam substituted as the fundamental point.",1990,7004,8901,2544,"Geodetic survey, cadastre, topographic mapping, engineering survey.","PD/83 is the realisation of DHDN in Thuringen. It is the resultant of applying a transformation derived at 13 points on the border between East and West Germany to Pu [...]
 6747,Greenland 1996,geodetic,ITRF94 at epoch 1996.62,1996,7019,8901,1107,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Ammassalik 1958, Qornoq 1927 and Scoresbysund 1952.","Kort & Matrikelstyrelsen (KMS), Copenhagen.",OGP,"2006/08/18",2006.770,0,"D_Greenland_1996"
@@ -651,7 +673,7 @@ For Selvagens see Selvagem Grande (datum code 6616).","Instituto Geografico e Ca
 6819,"Nord Sahara 1959 (Paris)",geodetic,"Coordinates of primary network readjusted on ED50 datum and then transformed conformally to Clarke 1880 (RGS) ellipsoid.",1959,7012,8903,1366,Topographic mapping.,,"""Le System Geodesique Nord-Sahara""; IGN Paris",OGP,"2000/06/23",,1,"D_Nord_Sahara_1959"
 6820,"Gunung Segara (Jakarta)",geodetic,"Station P5 (Gunung Segara) 0°32'12.83""S, 117°08'48.47""E (of Greenwich). Longitude 8°20'20.68""E (of Jakarta).",,7004,8908,1360,Topographic mapping.,,,OGP,"2008/06/24",2008.045,0,"D_Gunung_Segara"
 6821,"Voirol 1879 (Paris)",geodetic,"Fundamental point: Voirol. Latitude: 40.835864 grads N, longitude: 0.788735 grads E (of Paris).",1879,7011,8903,1365,Topographic mapping.,"Replaces Voirol 1875 (Paris) (code 6811).",IGN Paris,OGP,"2004/01/07",,0,"D_Voirol_1879"
-6896,International Terrestrial Reference Frame 2005,geodetic,"Origin at geocentre, originally orientated to the BIH Terrestrial System at epoch 1984.0 then adjusted to ensure zero net rotation to earth's overall tectonic motion. Defined by time series of Cartesian station coordinates and Earth Rotation parameters.",2005,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) at epoch 2005.0. Replaces ITRF2000 (code 6656). Replaced by ITRF2008 (datum code 1061 [...]
+6896,International Terrestrial Reference Frame 2005,geodetic,"Origin at geocentre, originally orientated to the BIH Terrestrial System at epoch 1984.0 then adjusted to ensure zero net rotation to earth's overall tectonic motion. Defined by time series of Cartesian station coordinates for epoch 2000.0.",2000,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from September 2007. Replaces ITRF2000 (code 6656). Replaced by ITRF2008 (datum code 1061).","Jour [...]
 6901,"Ancienne Triangulation Francaise (Paris)",geodetic,,,7027,8914,1326,Topographic mapping.,"Uses the RGS value for the Paris meridian.  In Alsace, data suspected to be transformation of German network into ATF. Replaced by Nouvelle Triangulation Francaise (Paris) (code 6807) which uses the 1936 IGN value for the Paris meridian.",,OGP,"2007/11/01",2007.083,0,"D_ATF"
 6902,"Nord de Guerre (Paris)",geodetic,,,7027,8903,1369,Topographic mapping.,,,OGP,"1995/06/02",,1,"D_Nord_de_Guerre"
 6903,"Madrid 1870 (Madrid)",geodetic,"Fundamental point: Madrid observatory.",1870,7028,8905,2366,Topographic mapping.,,"Institut de Geomatica; Barcelona",OGP,"1998/11/11",,0,"D_Madrid_1870"
diff --git a/data/gdalvrt.xsd b/data/gdalvrt.xsd
index 3dbaa90..b1f7e80 100644
--- a/data/gdalvrt.xsd
+++ b/data/gdalvrt.xsd
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 /******************************************************************************
- * $Id: gdalvrt.xsd 29326 2015-06-10 20:36:31Z rouault $
+ * $Id: gdalvrt.xsd 30648 2015-09-22 15:16:23Z rouault $
  *
  * Project:  GDAL/OGR
  * Purpose:  XML Schema for GDAL VRT files.
@@ -43,6 +43,7 @@
                     <xs:element name="VRTRasterBand" type="VRTRasterBandType"/> <!-- may be repeated -->
                     <xs:element name="MaskBand" type="MaskBandType"/>
                     <xs:element name="GDALWarpOptions" type="GDALWarpOptionsType"/> <!-- only if subClass="VRTWarpedDataset" -->
+                    <xs:element name="PansharpeningOptions" type="PansharpeningOptionsType"/> <!-- only if subClass="VRTPansharpenedDataset" -->
                 </xs:choice>
             </xs:sequence>
             <xs:attribute name="subClass" type="xs:string"/>
@@ -92,6 +93,45 @@
         </xs:sequence>
     </xs:complexType>
 
+    <xs:complexType name="PansharpeningOptionsType">
+        <xs:sequence>
+            <xs:element name="Algorithm" type="xs:string" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="AlgorithmOptions" type="AlgorithmOptionsType" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="Resampling" type="xs:string" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="NumThreads" type="xs:string" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="BitDepth" type="xs:string" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="NoData" type="NoDataOrNoneType" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="SpatialExtentAdjustment" type="xs:string" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="PanchroBand" type="PanchroBandType" minOccurs="1" maxOccurs="1"/>
+            <xs:element name="SpectralBand" type="SpectralBandType" minOccurs="1" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+
+    <xs:simpleType name="NoDataOrNoneType">
+        <xs:union memberTypes="xs:double xs:string" />
+    </xs:simpleType>
+
+    <xs:complexType name="PanchroBandType">
+        <xs:sequence>
+            <xs:element name="SourceFilename" type="SourceFilenameType"/>
+            <xs:element name="SourceBand" type="xs:string"/>  <!-- should be refined into xs:nonNegativeInteger or mask,xs:nonNegativeInteger -->
+        </xs:sequence>
+    </xs:complexType>
+
+    <xs:complexType name="SpectralBandType">
+        <xs:sequence>
+            <xs:element name="SourceFilename" type="SourceFilenameType"/>
+            <xs:element name="SourceBand" type="xs:string"/>  <!-- should be refined into xs:nonNegativeInteger or mask,xs:nonNegativeInteger -->
+        </xs:sequence>
+        <xs:attribute name="dstBand" type="xs:nonNegativeInteger"/>
+    </xs:complexType>
+
+    <xs:complexType name="AlgorithmOptionsType">
+        <xs:sequence>
+            <xs:any processContents="skip" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+
     <xs:complexType name="MDIType">
         <xs:simpleContent>
             <xs:extension base="xs:string">
@@ -156,6 +196,7 @@
             <xs:enumeration value="VRTWarpedRasterBand"/>
             <xs:enumeration value="VRTDerivedRasterBand"/>
             <xs:enumeration value="VRTRawRasterBand"/>
+            <xs:enumeration value="VRTPansharpenedRasterBand"/>
         </xs:restriction>
     </xs:simpleType>
 
@@ -361,6 +402,8 @@
             <xs:enumeration value="FALSE"/>
             <xs:enumeration value="true"/>
             <xs:enumeration value="false"/>
+            <xs:enumeration value="True"/>
+            <xs:enumeration value="False"/>
         </xs:restriction>
     </xs:simpleType>
 
@@ -373,10 +416,16 @@
     </xs:complexType>
 
     <xs:complexType name="RectType">
-        <xs:attribute name="xOff" type="xs:int" />
-        <xs:attribute name="yOff" type="xs:int" />
-        <xs:attribute name="xSize" type="xs:unsignedInt" />
-        <xs:attribute name="ySize" type="xs:unsignedInt" />
+        <xs:attribute name="xOff" type="xs:double" />
+        <xs:attribute name="yOff" type="xs:double" />
+        <xs:attribute name="xSize" type="nonNegativeDouble" />
+        <xs:attribute name="ySize" type="nonNegativeDouble" />
     </xs:complexType>
 
+    <xs:simpleType name="nonNegativeDouble">
+        <xs:restriction base="xs:double">
+            <xs:minExclusive value="0.0"/>
+        </xs:restriction>
+    </xs:simpleType>
+
 </xs:schema>
diff --git a/data/geoccs.csv b/data/geoccs.csv
index 3ad6cb9..2fe9ddd 100644
--- a/data/geoccs.csv
+++ b/data/geoccs.csv
@@ -130,6 +130,7 @@
 5828,"DB_REF",1081,Deutsche Bahn Reference System,1081,9001,7004,8901,1,0,6500
 5884,TGD2005,1095,Tonga Geodetic Datum 2005,1095,9001,7019,8901,1,0,6500
 6133,CIGD11,1100,Cayman Islands Geodetic Datum 2011,1100,9001,7019,8901,1,0,6500
+6309,CGRS93,1112,Cyprus Geodetic Reference System 1993,1112,9001,7030,8901,1,0,6500
 6317,"NAD83(2011)",1116,"NAD83 (National Spatial Reference System 2011)",1116,9001,7019,8901,1,0,6500
 6320,"NAD83(PA11)",1117,"NAD83 (National Spatial Reference System PA11)",1117,9001,7019,8901,1,0,6500
 6323,"NAD83(MA11)",1118,"NAD83 (National Spatial Reference System MA11)",1118,9001,7019,8901,1,0,6500
@@ -137,3 +138,12 @@
 6666,JGD2011,1128,Japanese Geodetic Datum 2011,1128,9001,7019,8901,1,0,6500
 6704,RDN2008,1132,Rete Dinamica Nazionale 2008,1132,9001,7019,8901,1,0,6500
 6781,"NAD83(CORS96)",1133,"NAD83 (Continuously Operating Reference Station 1996)",1133,9001,7019,8901,1,0,6500
+6934,IGS08,1141,IGS08,1141,9001,7019,8901,1,0,6500
+6978,IGD05,1143,Israeli Geodetic Datum 2005,1143,9001,7019,8901,1,1,6500
+6981,IG05 Intermediate CRS,1142,IG05 Intermediate Datum,1142,9001,7019,8901,1,0,6500
+6985,"IGD05/12",1145,"Israeli Geodetic Datum 2005(2012)",1145,9001,7019,8901,1,1,6500
+6988,"IG05/12 Intermediate CRS",1144,"IG05/12 Intermediate Datum",1144,9001,7019,8901,1,0,6500
+7071,RGTAAF07,1113,Reseau Geodesique des Terres Australes et Antarctiques Francaises 2007,1113,9001,7019,8901,1,0,6500
+7134,IGD05,1114,Israeli Geodetic Datum 2005,1114,9001,7030,8901,1,0,6500
+7137,"IGD05/12",1115,"Israeli Geodetic Datum 2005(2012)",1115,9001,7030,8901,1,0,6500
+7371,ONGD14,1147,Oman National Geodetic Datum 2014,1147,9001,7019,8901,1,0,6500
diff --git a/data/netcdf_config.xsd b/data/netcdf_config.xsd
new file mode 100644
index 0000000..2bf1cc8
--- /dev/null
+++ b/data/netcdf_config.xsd
@@ -0,0 +1,143 @@
+<?xml version="1.0"?>
+<!--
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  netCDF driver
+ * Purpose:  Schema of netCDF writer configuration files
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ **********************************************************************
+ * Copyright (c) 2016, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+    <xs:element name="Configuration">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="DatasetCreationOption" type="optionType" minOccurs="0" maxOccurs="unbounded"/>
+                <xs:element name="LayerCreationOption" type="optionType" minOccurs="0" maxOccurs="unbounded">
+                    <xs:annotation><xs:documentation>
+                        Define a layer creation option that applies to all layers.
+                    </xs:documentation></xs:annotation>
+                </xs:element>
+                <xs:element name="Attribute" type="attributeType" minOccurs="0" maxOccurs="unbounded">
+                    <xs:annotation><xs:documentation>
+                        Define a global attribute that must be written (or removed) and applies to all layers.
+                    </xs:documentation></xs:annotation>
+                </xs:element>
+                <xs:element name="Field" type="fieldType" minOccurs="0" maxOccurs="unbounded">
+                    <xs:annotation><xs:documentation>
+                        Define the characteristics of an OGR field / netCDF variable that applies to all layers (that actually uses it)
+                    </xs:documentation></xs:annotation>
+                </xs:element>
+                <xs:element name="Layer" type="layerType" minOccurs="0" maxOccurs="unbounded">
+                    <xs:annotation><xs:documentation>
+                        Define layer specific settings for layer creaetion options, fields and attributes.
+                    </xs:documentation></xs:annotation>
+                </xs:element>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:complexType name="optionType">
+        <xs:attribute name="name" type="xs:string"/>
+        <xs:attribute name="value" type="xs:string"/>
+    </xs:complexType>
+
+    <xs:complexType name="attributeType">
+        <xs:attribute name="name" type="xs:string"/>
+        <xs:attribute name="value" type="xs:string">
+            <xs:annotation><xs:documentation>
+            Value to set as attribute, or empty string
+            to delete an existing attribute
+            </xs:documentation></xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="type" use="optional">
+            <xs:simpleType>
+                <xs:restriction base="xs:string">
+                    <xs:enumeration value="string"/>
+                    <xs:enumeration value="integer"/>
+                    <xs:enumeration value="double"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+    </xs:complexType>
+
+    <xs:complexType name="fieldType">
+        <xs:sequence>
+            <xs:element name="Attribute" type="attributeType" minOccurs="0" maxOccurs="unbounded">
+                <xs:annotation><xs:documentation>
+                    Define an attribute that must be written (or removed) from a OGR field / netCDF variable.
+                </xs:documentation></xs:annotation>
+            </xs:element>
+        </xs:sequence>
+        <xs:attribute name="name" type="xs:string" use="optional">
+            <xs:annotation><xs:documentation>OGR field name.</xs:documentation></xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="netcdf_name" type="xs:string" use="optional">
+            <xs:annotation><xs:documentation>netCDF variable name. When both name
+            and netcdf_name are set, the OGR field {name} will be written as the
+            netCDF {netcdf_name} variable. When netcdf_name is set, but name is none,
+            then the Field definition will match an implictly created netCDF variable,
+            such as x/lon, y/lat, z, ...
+            </xs:documentation></xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="main_dim" type="xs:string" use="optional">
+            <xs:annotation><xs:documentation>
+            Name of the main dimension against which the variable must be indexed.
+            If not set, the record dimension will be used. Only useful when using
+            a layer with FeatureType!=Point.
+            </xs:documentation></xs:annotation>
+        </xs:attribute>
+    </xs:complexType>
+
+    <xs:complexType name="layerType">
+        <xs:sequence>
+            <xs:element name="LayerCreationOption" type="optionType" minOccurs="0" maxOccurs="unbounded">
+            <xs:annotation><xs:documentation>
+                    Define a layer creation option. Overrides or appended to
+                    existing global layer creation options.
+                </xs:documentation></xs:annotation>
+            </xs:element>
+            <xs:element name="Attribute" type="attributeType" minOccurs="0" maxOccurs="unbounded">
+                <xs:annotation><xs:documentation>
+                    Define a global attribute that must be written (or removed).
+                    Overrides or appended to existing global attributes.
+                </xs:documentation></xs:annotation>
+            </xs:element>
+            <xs:element name="Field" type="fieldType" minOccurs="0" maxOccurs="unbounded">
+                <xs:annotation><xs:documentation>
+                    Define the characteristics of an OGR field / netCDF variable
+                    (that must exist as an explicit OGR field, or an implicitly created netCDF variable).
+                    Supersedes global Field definition.
+                </xs:documentation></xs:annotation>
+            </xs:element>
+        </xs:sequence>
+        <xs:attribute name="name" type="xs:string">
+            <xs:annotation><xs:documentation>OGR layer name.</xs:documentation></xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="netcdf_name" type="xs:string" use="optional">
+            <xs:annotation><xs:documentation>netCDF group name.</xs:documentation></xs:annotation>
+        </xs:attribute>
+    </xs:complexType>
+
+</xs:schema>
diff --git a/data/nitf_spec.xml b/data/nitf_spec.xml
index a201c62..a9cb273 100644
--- a/data/nitf_spec.xml
+++ b/data/nitf_spec.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <!--
 /******************************************************************************
- * $Id: nitf_spec.xml 27535 2014-07-16 08:01:05Z rouault $
+ * $Id: nitf_spec.xml 32488 2015-12-27 08:29:13Z rouault $
  *
  * Project:  NITF Library
  * Purpose:  Description of NITF TREs
@@ -168,6 +168,17 @@
         </loop>
     </tre>
 
+    <tre name="CSCCGA" length="60" location="file">
+        <field name="CCG_SOURCE" length="18"/>
+        <field name="REG_SENSOR" length="6"/>
+        <field name="ORIGIN_LINE" length="7"/>
+        <field name="ORIGIN_SAMPLE" length="5"/>
+        <field name="AS_CELL_SIZE" length="7"/>
+        <field name="CS_CELL_SIZE" length="5"/>
+        <field name="CCG_MAX_LINE" length="7"/>
+        <field name="CCG_MAX_SAMPLE" length="5"/>
+    </tre>
+
     <tre name="CSCRNA" length="109" location="image">
         <field name="PREDICT_CORNERS" length="1"/>
         <field name="ULCNR_LAT" length="9"/>
@@ -243,6 +254,46 @@
         </loop>
     </tre>
 
+    <!-- STDI-0002 Appendix N -->
+    <tre name="ENGRDA">
+        <field name="RESRC" length="20" type="string"/>
+        <field name="RECNT" length="3" type="integer" minval="1"/>
+        <loop counter="RECNT" md_prefix="RECORD_%d_" name="RECORDS">
+            <field name="ENGLN" length="2" type="integer" minval="1"/>
+            <field name="ENGLBL" length_var="ENGLN" type="string"/>
+            <field name="ENGMTXC" length="4" type="integer" minval="1"/>
+            <field name="ENGMTXR" length="4" type="integer" minval="1"/>
+            <field name="ENGTYP" length="1" type="string"/>
+            <field name="ENGDTS" length="1" type="integer"/>
+            <field name="ENGDTU" length="2" type="string"/>
+            <field name="ENGDATC" length="8" type="integer" minval="1" maxval="99999932"/>
+            <field name="ENGDATA" length_var="ENGDATC"/>
+        </loop>
+    </tre>
+
+    <!-- STDI-0002 Appendix E (ASDE 2.1/CN1), Table E-12 -->
+    <tre name="EXPLTB" length="101" location="image">
+        <field name="ANGLE_TO_NORTH" length="7" type="real" minval="0.0" maxval="359.999"/>
+        <field name="ANGLE_TO_NORTH_ACCY" length="6" type="real" min="0.0" maxval="44.999"/>
+        <field name="SQUINT_ANGLE" length="7" type="real" min="-60.0" maxval="85.0"/>
+        <field name="SQUINT_ANGLE_ACCY" length="6" type="real" min="0.0" maxval="44.999"/>
+        <field name="MODE" length="3" type="string"/>
+        <field length="16" fixed_value="                "/>
+        <field name="GRAZE_ANG" length="5" type="real" unit="degrees" minval="0.0" maxval="90.00"/>
+        <field name="GRAZE_ANG_ACCY" length="5" type="real" unit="degrees" minval="0.0" maxval="90.00"/>
+        <field name="SLOPE_ANG" length="5" type="real" unit="degrees" minval="0.0" maxval="90.00"/>
+        <field name="POLAR" length="2" type="string"/>
+        <field name="NSAMP" length="5" type="integer" minval="1" maxval="99999"/>
+        <field length="1" fixed_value="0"/>
+        <!-- SEQ_NUM is a string because it is <R>, so it may contain a space -->
+        <field name="SEQ_NUM" length="1" type="string"/>
+        <field name="PRIME_ID" length="12" type="string"/>
+        <field name="PRIME_BE" length="15" type="string"/>
+        <field length="1" fixed_value="0"/>
+        <field name="N_SEC" length="2" type="integer" minval="0" maxval="99"/>
+        <field name="IPR" length="2" type="integer" unit="feet" minval="0" maxval="99"/>
+    </tre>
+
     <tre name="GEOLOB" length="48" location="image">
         <field name="ARV" length="9" type="real"/>
         <field name="BRV" length="9" type="real"/>
@@ -371,6 +422,67 @@
         <field name="PSO" length="15" type="real"/>
     </tre>
 
+    <tre name="MENSRB" location="image">
+        <field name="ACFT_LOC" length="25" type="string"/>
+        <field name="ACFT_LOC_ACCY" length ="6" type="real"/>
+        <field name="ACFT_ALT" length="6" type="integer"/>
+        <field name="RP_LOC" length="25" type="string"/>
+        <field name="RP_LOC_ACCY" length="6" type="real"/>
+        <field name="RP_ELV" length="6" type="integer" minval="-1000" maxval="30000"/>
+        <field name="OF_PC_R" length="7" type="real"/>
+        <field name="OF_PC_A" length="7" type="real"/>
+        <field name="COSGRZ" length="7" type="real" minval="0.0" maxval="1.0"/>
+        <field name="RGCRP" length="7" type="integer" minval="0" maxval="3000000"/>
+        <field name="RLMAP" length="1" type="string"/>
+        <field name="RP_ROW" length="5" type="integer" minval="1" maxval="99999"/>
+        <field name="RP_COL" length="5" type="integer" minval="1" maxval="99999"/>
+        <field name="C_R_NC" length="10" type="real" minval="-1.0" maxval="1.0"/>
+        <field name="C_R_EC" length="10" type="real" minval="-1.0" maxval="1.0"/>
+        <field name="C_R_DC" length="10" type="real" minval="-1.0" maxval="1.0"/>
+        <field name="C_AZ_NC" length="9" type="real" minval="-1.0" maxval="1.0"/>
+        <field name="C_AZ_EC" length="9" type="real" minval="-1.0" maxval="1.0"/>
+        <field name="C_AZ_DC" length="9" type="real" minval="-1.0" maxval="1.0"/>
+        <field name="C_AL_NC" length="9" type="real" minval="-1.0" maxval="1.0"/>
+        <field name="C_AL_EC" length="9" type="real" minval="-1.0" maxval="1.0"/>
+        <field name="C_AL_DC" length="9" type="real" minval="-1.0" maxval="1.0"/>
+        <field name="TOTAL_TILES_COLS" length="3" type="integer" minval="1" maxval="999"/>
+        <field name="TOTAL_TILES_ROWS" length="5" type="integer" minval="1" maxval="99999"/>
+    </tre>
+
+    <!-- STDI-0002 Appendix E (ASDE 2.1/CN1), Table E-21 -->
+    <tre name="PATCHB" size="121" location="image">
+        <field name="PAT_NO" length="4" type="integer" minval="1" maxval="999"/>
+        <!-- LAST_PAT_LEVEL is a string because it is <R>, so it may contain only a space -->
+        <field name="LAST_PAT_FLAG" length="1" type="integer" minval="0" maxval="1"/>
+        <field name="LNSTRT" length="7" type="integer" minval="1" maxval="9999999"/>
+        <field name="LNSTOP" length="7" type="integer" minval="20" maxval="9999999"/>
+        <field name="AZL" length="5" type="integer" units="lines" minval="20" maxval="99999"/>
+        <!-- NVL is a string because it is <R> -->
+        <field name="NVL" length="5" type="string" units="lines"/>
+        <!-- FVL is a string because it is <R> -->
+        <field name="FVL" length="3" type="string" minval="1" maxval="681"/>
+        <field name="NPIXEL" length="5" type="integer" units="pixels" minval="1" maxval="99999"/>
+        <field name="FVPIX" length="5" type="integer" units="pixels" minval="1" maxval="99999"/>
+        <!-- FRAME is a string because it is <R> -->
+        <field name="FRAME" length="3" type="string" minval="1" maxval="512"/>
+        <field name="UTC" length="8" type="real" units="seconds" minval="0.0" maxval="86399.99"/>
+        <field name="SHEAD" length="7" type="real" units="degrees" minval="0.0" maxval="359.999"/>
+        <!-- GRAVITY is a string because it is <R> -->
+        <field name="GRAVITY" length="7" type="string" units="feet/sec^2"/>
+        <field name="INS_V_NC" length="5" type="integer" units="feet/sec" minval="-9999" maxval="9999"/>
+        <field name="INS_V_EC" length="5" type="integer" units="feet/sec" minval="-9999" maxval="9999"/>
+        <field name="INS_V_DC" length="5" type="integer" units="feet/sec" minval="-9999" maxval="9999"/>
+        <!-- OFFLAT and OFFLONG are string because they are <R> -->
+        <field name="OFFLAT" length="8" type="string" units="seconds"/>
+        <field name="OFFLONG" length="8" type="string" units="seconds"/>
+        <field name="TRACK" length="3" type="integer" units="degrees" minval="0" maxval="359"/>
+        <field name="GSWEEP" length="6" type="real" units="degrees" minval="0.0" maxval="120.0"/>
+        <!-- SHEAR is a string because it is <R> -->
+        <field name="SHEAR" length="8" type="string"/>
+        <!-- BATCH_NO is a string because it is <R> -->
+        <field name="BATCH_NO" length="6" type="string"/>
+    </tre>
+
     <tre name="PIAIMB" md_prefix="NITF_PIAIMB_" length="337" location="image">
         <field name="CLOUDCVR" length="3"/>
         <field name="SRP" length="1"/>
@@ -996,6 +1108,362 @@
         <field name="CSSIZ" length="21" type="real"/>
     </tre>
 
+    <tre name="SENSRB" location="image">
+        <field name="GENERAL_DATA" length="1" type="string"/>
+        <if cond="GENERAL_DATA=Y">
+            <field name="SENSOR" length="25" type="string"/>
+            <field name="SENSOR_URI" length="32" type="string"/>
+            <field name="PLATFORM" length="25" type="string"/>
+            <field name="PLATFORM_URI" length="32" type="string"/>
+            <field name="OPERATION_DOMAIN" length="10" type="string"/>
+            <field name="CONTENT_LEVEL" length="1" type="integer" minval="0" maxval="9"/>
+            <field name="GEODETIC_SYSTEM" length="5" type="string"/>
+            <field name="GEODETIC_TYPE" length="1" type="string"/>
+            <field name="ELEVATION_DATUM" length="3" type="string"/>
+            <field name="LENGTH_UNIT" length="2" type="string"/>
+            <field name="ANGULAR_UNIT" length="3" type="string"/>
+            <field name="START_DATE" length="8" type="string"/>
+            <field name="START_TIME" length="14" type="real" minval="0.0" maxval="86399.99999999"/>
+            <field name="END_DATE" length="8" type="string"/>
+            <field name="END_TIME" length="14" type="real" minval="0.0" maxval="86399.99999999"/>
+            <field name="GENERATION_COUNT" length="2" type="integer" minval="0" maxval="99"/>
+            <field name="GENERATION_DATE" length="8" type="string"/>
+            <field name="GENERATION_TIME" length="10" type="string"/>
+        </if>
+        <field name="SENSOR_ARRAY_DATA" length="1" type="string"/>
+        <if cond="SENSOR_ARRAY_DATA=Y">
+            <field name="DETECTION" length="20" type="string"/>
+            <field name="ROW_DETECTORS" length="8" type="integer"/>
+            <field name="COLUMN_DETECTORS" length="8" type="integer"/>
+            <field name="ROW_METRIC" length="8" type="string"/>
+            <field name="COLUMN_METRIC" length="8" type="string"/>
+            <field name="FOCAL_LENGTH" length="8" type="string"/>
+            <field name="ROW_FOV" length="8" type="string"/>
+            <field name="COLUMN_FOV" length="8" type="string"/>
+            <field name="CALIBRATED" length="1" type="string"/>
+        </if>
+        <field name="SENSOR_CALIBRATION_DATA" length="1" type="string"/>
+        <if cond="SENSOR_CALIBRATION_DATA=Y">
+            <field name="CALIBRATION_UNIT" length="2" type="string"/>
+            <field name="PRINCIPAL_POINT_OFFSET_X" length="9" type="string"/>
+            <field name="PRINCIPAL_POINT_OFFSET_Y" length="9" type="string"/>
+            <field name="RADIAL_DISTORT_1" length="12" type="string"/>
+            <field name="RADIAL_DISTORT_2" length="12" type="string"/>
+            <field name="RADIAL_DISTORT_3" length="12" type="string"/>
+            <field name="RADIAL_DISTORT_LIMIT" length="9" type="string"/>
+            <field name="DECENT_DISTORT_1" length="12" type="string"/>
+            <field name="DECENT_DISTORT_2" length="12" type="string"/>
+            <field name="AFFINITY_DISTORT_1" length="12" type="string"/>
+            <field name="AFFINITY_DISTORT_2" length="12" type="string"/>
+            <field name="CALIBRATION_DATE" length="8" type="string"/>
+        </if>
+        <field name="IMAGE_FORMATION_DATA" length="1" type="string"/>
+        <if cond="IMAGE_FORMATION_DATA=Y">
+            <field name="METHOD" length="15" type="string"/>
+            <field name="MODE" length="3" type="string"/>
+            <field name="ROW_COUNT" length="8" type="integer" minval="1" maxval="99999999"/>
+            <field name="COLUMN_COUNT" length="8" type="integer" minval="1" maxval="99999999"/>
+            <field name="ROW_SET" length="8" type="integer"/>
+            <field name="COLUMN_SET" length="8" type="integer"/>
+            <field name="ROW_RATE" length="10" type="real"/>
+            <field name="COLUMN_RATE" length="10" type="real"/>
+            <field name="FIRST_PIXEL_ROW" length="8" type="integer" minval="0" maxval="99999999"/>
+            <field name="FIRST_PIXEL_COLUMN" length="8" type="integer" minval="0" maxval="99999999"/>
+            <field name="TRANSFORM_PARAMS" length="1" type="integer" minval="0" maxval="8"/>
+            <loop counter="TRANSFORM_PARAMS" name="TRANSFORM_PARAM" md_prefix="TRANSFORM_PARAM_%d_">
+                <field name="" longname="TRANSFORM_PARAM" length="12" type="string"/>
+            </loop>
+        </if>
+        <field name="REFERENCE_TIME" length="12" type="string"/>
+        <field name="REFERENCE_ROW" length="8" type="string"/>
+        <field name="REFERENCE_COLUMN" length="8" type="string"/>
+        <field name="LATITUDE_OR_X" length="11" type="string"/>
+        <field name="LONGITUDE_OR_Y" length="12" type="string"/>
+        <field name="ALTITUDE_OR_Z" length="11" type="string"/>
+        <field name="SENSOR_X_OFFSET" length="8" type="integer"/>
+        <field name="SENSOR_Y_OFFSET" length="8" type="integer"/>
+        <field name="SENSOR_Z_OFFSET" length="8" type="integer"/>
+        <field name="ATTITUDE_EULER_ANGLES" length="1" type="string"/>
+        <if cond="ATTITUDE_EULER_ANGLES=Y">
+            <field name="SENSOR_ANGLE_MODEL" length="1" type="integer"/>
+            <field name="SENSOR_ANGLE_1" length="10" type="string"/>
+            <field name="SENSOR_ANGLE_2" length="9" type="string"/>
+            <field name="SENSOR_ANGLE_3" length="10" type="string"/>
+            <field name="PLATFORM_RELATIVE" length="1" type="string"/>
+            <field name="PLATFORM_HEADING" length="9" type="string"/>
+            <field name="PLATFORM_PITCH" length="9" type="string"/>
+            <field name="PLATFORM_ROLL" length="10" type="string"/>
+        </if>
+        <field name="ATTITUDE_UNIT_VECTORS" length="1" type="string"/>
+        <if cond="ATTITUDE_UNIT_VECTORS=Y">
+            <field name="ICX_NORTH_OR_X" length="10" type="real"/>
+            <field name="ICX_EAST_OR_Y" length="10" type="real"/>
+            <field name="ICX_DOWN_OR_Z" length="10" type="real"/>
+            <field name="ICY_NORTH_OR_X" length="10" type="real"/>
+            <field name="ICY_EAST_OR_Y" length="10" type="real"/>
+            <field name="ICY_DOWN_OR_Z" length="10" type="real"/>
+            <field name="ICZ_NORTH_OR_X" length="10" type="real"/>
+            <field name="ICZ_EAST_OR_Y" length="10" type="real"/>
+            <field name="ICZ_DOWN_OR_Z" length="10" type="real"/>
+        </if>
+        <field name="ATTITUDE_QUATERNION" length="1" type="string"/>
+        <if cond="ATTITUDE_QUATERNION=Y">
+            <field name="ATTITUDE_Q1" length="10" type="real"/>
+            <field name="ATTITUDE_Q2" length="10" type="real"/>
+            <field name="ATTITUDE_Q3" length="10" type="real"/>
+            <field name="ATTITUDE_Q4" length="10" type="real"/>
+        </if>
+        <field name="SENSOR_VELOCITY_DATA" length="1" type="string"/>
+        <if cond="SENSOR_VELOCITY_DATA=Y">
+            <field name="VELOCITY_NORTH_OR_X" length="9" type="real"/>
+            <field name="VELOCITY_EAST_OR_Y" length="9" type="real"/>
+            <field name="VELOCITY_DOWN_OR_Z" length="9" type="real"/>
+        </if>
+        <field name="POINT_SET_DATA" length="2" type="integer"/>
+        <loop counter="POINT_SET_DATA" name="POINT_SETS" md_prefix="POINT_SET_%02d_">
+            <field name="POINT_SET_TYPE_MM" length="25" type="string"/>
+            <field name="POINT_COUNT_MM" length="3" type="integer"/>
+            <loop counter="POINT_COUNT_MM" name="POINT" md_prefix="POINT_%03d_">
+                <field name="P_ROW_NNN" length="8" type="integer"/>
+                <field name="P_COLUMN_NNN" length="8" type="integer"/>
+                <field name="P_LATITUDE_NNN" length="10" type="string"/>
+                <field name="P_LONGITUDE_NNN" length="11" type="string"/>
+                <field name="P_ELEVATION_NNN" length="6" type="string"/>
+                <field name="P_RANGE_NNN" length="8" type="string"/>
+            </loop>
+        </loop>
+        <field name="TIME_STAMPED_DATA_SETS" length="2" type="integer"/>
+        <loop counter="TIME_STAMPED_DATA_SETS" name="TIME_STAMPED_SET" md_prefix="TIME_STAMPED_SET_%02d_">
+            <field name="TIME_STAMP_TYPE_MM" length="3" type="string"/>
+            <field name="TIME_STAMP_COUNT_MM" length="4" type="integer"/>
+            <loop counter="TIME_STAMP_COUNT_MM" name="TIME_STAMP_COUNTS" md_prefix="TIME_STAMP_COUNT_%04d_">
+                <field name="TIME_STAMP_TIME_NNNN" length="12" type="real"/>
+                <if cond="TIME_STAMP_TYPE_MM=05a">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="12" type="real"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=05b">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="8" type="integer"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=05c">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="8" type="integer"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=06a">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="11" type="real"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=06b">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="12" type="real"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=06c">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="11" type="real"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=06d">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="8" type="real"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=06e">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="8" type="real"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=06f">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="8" type="real"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=07a">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="1" type="integer"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=07b">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=07c">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="9" type="real"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=07d">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=07e">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="1" type="string"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=07f">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="9" type="real"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=07g">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="9" type="real"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=07h">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=08a">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=08b">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=08c">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=08d">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=08e">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=08f">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=08g">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=08h">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=08i">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=09a">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=09b">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=09c">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=09d">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=10a">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="9" type="real"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=10b">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="9" type="real"/>
+                </if>
+                <if cond="TIME_STAMP_TYPE_MM=10c">
+                    <field name="TIME_STAMP_VALUE_NNNN" length="9" type="real"/>
+                </if>
+            </loop>
+        </loop>
+        <field name="PIXEL_REFERENCED_DATA_SETS" length="2" type="integer"/>
+        <loop counter="PIXEL_REFERENCED_DATA_SETS" name="PIXEL_REFERENCE_DATA_SET" md_prefix="PIXEL_REFERENCE_DATA_SET_%02d_">
+            <field name="PIXEL_REFERENCE_TYPE_MM" length="3" type="string"/>
+            <field name="PIXEL_REFERENCE_COUNT_MM" length="4" type="integer"/>
+            <loop counter="PIXEL_REFERENCE_COUNT_MM" name="PIXEL_REFERENCE_COUNTS" md_prefix="PIXEL_REFERENCE_COUNT_%04d_">
+                <field name="PIXEL_REFERENCE_ROW_NNNN" length="8" type="integer"/>
+                <field name="PIXEL_REFERENCE_COLUMN_NNNN" length="8" type="integer"/>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=05a">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="12" type="real"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=05b">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="8" type="integer"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=05c">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="8" type="integer"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=06a">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="11" type="real"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=06b">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="12" type="real"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=06c">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="11" type="real"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=06d">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="8" type="real"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=06e">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="8" type="real"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=06f">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="8" type="real"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=07a">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="1" type="integer"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=07b">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=07c">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="9" type="real"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=07d">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=07e">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="1" type="string"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=07f">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="9" type="real"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=07g">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="9" type="real"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=07h">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=08a">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=08b">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=08c">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=08d">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=08e">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=08f">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=08g">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=08h">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=08i">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=09a">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=09b">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=09c">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=09d">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="10" type="real"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=10a">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="9" type="real"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=10b">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="9" type="real"/>
+                </if>
+                <if cond="PIXEL_REFERENCE_TYPE_MM=10c">
+                    <field name="PIXEL_REFERENCE_VALUE_NNNN" length="9" type="real"/>
+                </if>
+            </loop>
+        </loop>
+        <field name="UNCERTAINTY_DATA" length="3" type="integer"/>
+        <loop counter="UNCERTAINTY_DATA" name="UNCERTAINTY_DATA_SETS" md_prefix="UNCERTAINTY_DATA_%03d_">
+            <field name="UNCERTAINTY_FIRST_TYPE_NNN" length="11" type="string"/>
+            <field name="UNCERTAINTY_SECOND_TYPE_NNN" length="11" type="string"/>
+            <field name="UNCERTAINTY_VALUE_NNN" length="10" type="string"/>
+        </loop>
+        <field name="ADDITIONAL_PARAMETER_DATA" length="3" type="integer"/>
+        <loop counter="ADDITIONAL_PARAMETER_DATA" name="ADDITIONAL_PARAMETER_DATA_SETS" md_prefix="ADDITIONAL_PARAMETER_DATA_%03d_">
+            <field name="PARAMETER_NAME_MMM" length="25" type="string"/>
+            <field name="PARAMETER_SIZE_MMM" length="3" type="integer"/>
+            <field name="PARAMETER_COUNT_MMM" length="4" type="integer"/>
+            <loop counter="PARAMETER_COUNT_MMM" name="ADDITIONAL_PARAMETER_VALUES" md_prefix="PARAMETER_VALUE_%04d">
+                <field name="PARAMETER_VALUE_NNNN" length_var="PARAMETER_SIZE_MMM" type="string"/>
+            </loop>
+        </loop>
+    </tre>
+
     <tre name="SOURCB" minlength="906" maxlength="99985" location="image">
         <field name="IS_SCA" length="9" type="integer"/>
         <field name="CPATCH" length="10" type="string"/>
@@ -1123,6 +1591,18 @@
         <field length="8"/>
     </tre>
 
+    <tre name="STREOB" length="94" location="image">
+        <field name="ST_ID" length="60" type="string"/>
+        <field name="N_MATES" length="1" type="integer"/>
+        <field name="MATE_INSTANCE" length="1" type="integer"/>
+        <field name="B_CONV" length="5" type="real"/>
+        <field name="E_CONV" length="5" type="real"/>
+        <field name="B_ASYM" length="5" type="real"/>
+        <field name="E_ASYM" length="5" type="real"/>
+        <field name="B_BIE" length="6" type="real"/>
+        <field name="E_BIE" length="6" type="real"/>
+    </tre>
+
     <tre name="USE00A" md_prefix="NITF_USE00A_" length="107" location="image">
         <field name="ANGLE_TO_NORTH" length="3"/>
         <field name="MEAN_GSD" length="5"/>
@@ -1149,4 +1629,5 @@
         <field name="SUN_EL" length="5"/>
         <field name="SUN_AZ" length="5"/>
     </tre>
+
 </tres>
diff --git a/data/ogrvrt.xsd b/data/ogrvrt.xsd
index 0b0ebaa..8e535bc 100644
--- a/data/ogrvrt.xsd
+++ b/data/ogrvrt.xsd
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 /******************************************************************************
- * $Id: ogrvrt.xsd 28950 2015-04-18 23:24:49Z rouault $
+ * $Id: ogrvrt.xsd 33680 2016-03-08 09:59:03Z rouault $
  *
  * Project:  GDAL/OGR
  * Purpose:  XML Schema for OGR VRT files.
@@ -201,6 +201,8 @@
             <xs:enumeration value="wkbCurvePolygon"/> <!-- new in GDAL 2.0 -->
             <xs:enumeration value="wkbMultiCurve"/> <!-- new in GDAL 2.0 -->
             <xs:enumeration value="wkbMultiSurface"/> <!-- new in GDAL 2.0 -->
+            <xs:enumeration value="wkbCurve"/> <!-- new in GDAL 2.1 -->
+            <xs:enumeration value="wkbSurface"/> <!-- new in GDAL 2.1 -->
             <xs:enumeration value="wkbPoint25D"/>
             <xs:enumeration value="wkbLineString25D"/>
             <xs:enumeration value="wkbPolygon25D"/>
@@ -213,6 +215,40 @@
             <xs:enumeration value="wkbCurvePolygonZ"/> <!-- new in GDAL 2.0 -->
             <xs:enumeration value="wkbMultiCurveZ"/> <!-- new in GDAL 2.0 -->
             <xs:enumeration value="wkbMultiSurfaceZ"/> <!-- new in GDAL 2.0 -->
+            <xs:enumeration value="wkbCurveZ"/> <!-- new in GDAL 2.1 -->
+            <xs:enumeration value="wkbSurfaceZ"/> <!-- new in GDAL 2.1 -->
+
+            <!-- below is new in GDAL 2.1 -->
+            <xs:enumeration value="wkbPointM"/>
+            <xs:enumeration value="wkbLineStringM"/>
+            <xs:enumeration value="wkbPolygonM"/>
+            <xs:enumeration value="wkbMultiPointM"/>
+            <xs:enumeration value="wkbMultiLineStringM"/>
+            <xs:enumeration value="wkbMultiPolygonM"/>
+            <xs:enumeration value="wkbGeometryCollectionM"/>
+            <xs:enumeration value="wkbCircularStringM"/>
+            <xs:enumeration value="wkbCompoundCurveM"/>
+            <xs:enumeration value="wkbCurvePolygonM"/>
+            <xs:enumeration value="wkbMultiCurveM"/>
+            <xs:enumeration value="wkbMultiSurfaceM"/>
+            <xs:enumeration value="wkbCurveM"/>
+            <xs:enumeration value="wkbSurfaceM"/>
+
+            <xs:enumeration value="wkbPointZM"/>
+            <xs:enumeration value="wkbLineStringZM"/>
+            <xs:enumeration value="wkbPolygonZM"/>
+            <xs:enumeration value="wkbMultiPointZM"/>
+            <xs:enumeration value="wkbMultiLineStringZM"/>
+            <xs:enumeration value="wkbMultiPolygonZM"/>
+            <xs:enumeration value="wkbGeometryCollectionZM"/>
+            <xs:enumeration value="wkbCircularStringZM"/>
+            <xs:enumeration value="wkbCompoundCurveZM"/>
+            <xs:enumeration value="wkbCurvePolygonZM"/>
+            <xs:enumeration value="wkbMultiCurveZM"/>
+            <xs:enumeration value="wkbMultiSurfaceZM"/>
+            <xs:enumeration value="wkbCurveZM"/>
+            <xs:enumeration value="wkbSurfaceZM"/>
+
         </xs:restriction>
     </xs:simpleType>
 
diff --git a/data/osmconf.ini b/data/osmconf.ini
index 998cb8b..1fabcef 100644
--- a/data/osmconf.ini
+++ b/data/osmconf.ini
@@ -66,7 +66,7 @@ z_order_sql="SELECT (CASE [highway] WHEN 'minor' THEN 3 WHEN 'road' THEN 3 WHEN
 
 [multipolygons]
 # common attributes
-# note: for multipolygons, osm_id=yes instanciates a osm_id field for the id of relations
+# note: for multipolygons, osm_id=yes instantiates a osm_id field for the id of relations
 # and a osm_way_id field for the id of closed ways. Both fields are exclusively set.
 osm_id=yes
 osm_version=no
diff --git a/data/pcs.csv b/data/pcs.csv
index b24a793..6815684 100644
--- a/data/pcs.csv
+++ b/data/pcs.csv
@@ -38,7 +38,7 @@
 2036,"NAD83(CSRS98) / New Brunswick Stereo",9001,4140,19946,9809,1,1,4500,8801,46.3,9110,8802,-66.3,9110,8805,0.999912,9201,8806,2500000,9001,8807,7500000,9001,,,,,,
 2037,"NAD83(CSRS98) / UTM zone 19N",9001,4140,16019,9807,1,1,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 2038,"NAD83(CSRS98) / UTM zone 20N",9001,4140,16020,9807,1,1,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2039,"Israel / Israeli TM Grid",9001,4141,18204,9807,1,0,4400,8801,31.4403817,9110,8802,35.1216261,9110,8805,1.0000067,9201,8806,219529.584,9001,8807,626907.39,9001,,,,,,
+2039,"Israel 1993 / Israeli TM Grid",9001,4141,18204,9807,1,0,4400,8801,31.4403817,9110,8802,35.1216261,9110,8805,1.0000067,9201,8806,219529.584,9001,8807,626907.39,9001,,,,,,
 2040,"Locodjo 1965 / UTM zone 30N",9001,4142,16030,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 2041,"Abidjan 1987 / UTM zone 30N",9001,4143,16030,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 2042,"Locodjo 1965 / UTM zone 29N",9001,4142,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
@@ -55,7 +55,7 @@
 2053,"Hartebeesthoek94 / Lo29",9001,4148,17529,9808,1,0,6503,8801,0,9102,8802,29,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
 2054,"Hartebeesthoek94 / Lo31",9001,4148,17531,9808,1,0,6503,8801,0,9102,8802,31,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
 2055,"Hartebeesthoek94 / Lo33",9001,4148,17533,9808,1,0,6503,8801,0,9102,8802,33,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-2056,"CH1903+ / LV95",9001,4150,19950,9815,1,0,4498,8811,46.570866,9110,8812,7.26225,9110,8813,90,9110,8814,90,9110,8815,1,9201,8816,2600000,9001,8817,1200000,9001
+2056,"CH1903+ / LV95",9001,4150,19950,9815,1,0,4400,8811,46.570866,9110,8812,7.26225,9110,8813,90,9110,8814,90,9110,8815,1,9201,8816,2600000,9001,8817,1200000,9001
 2057,"Rassadiran / Nakhl e Taqi",9001,4153,19951,9815,1,0,4400,8811,27.31077837,9110,8812,52.3612741,9110,8813,0.34179803,9110,8814,0.34179803,9110,8815,0.999895934,9201,8816,658377.437,9001,8817,3044969.194,9001
 2058,"ED50(ED77) / UTM zone 38N",9001,4154,16038,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 2059,"ED50(ED77) / UTM zone 39N",9001,4154,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
@@ -1369,7 +1369,7 @@
 3376,"GDM2000 / East Malaysia BRSO",9001,4742,19894,9812,1,0,4400,8806,0,9001,8807,0,9001,8811,4,9110,8812,115,9110,8813,53.185691582,9110,8814,53.07483685,9110,8815,0.99984,9201
 3377,"GDM2000 / Johor Grid",9001,4742,19893,9806,1,0,4400,8801,2.071804708,9110,8802,103.254057045,9110,8806,-14810.562,9001,8807,8758.32,9001,,,,,,,,,
 3378,"GDM2000 / Sembilan and Melaka Grid",9001,4742,19892,9806,1,0,4400,8801,2.405645149,9110,8802,101.582965815,9110,8806,3673.785,9001,8807,-4240.573,9001,,,,,,,,,
-3379,"GDM2000 / PahangGrid",9001,4742,19891,9806,1,0,4400,8801,3.460979712,9110,8802,102.220587634,9110,8806,-7368.228,9001,8807,6485.858,9001,,,,,,,,,
+3379,"GDM2000 / Pahang Grid",9001,4742,19891,9806,1,0,4400,8801,3.460979712,9110,8802,102.220587634,9110,8806,-7368.228,9001,8807,6485.858,9001,,,,,,,,,
 3380,"GDM2000 / Selangor Grid",9001,4742,19890,9806,1,0,4400,8801,3.410473658,9110,8802,101.232078849,9110,8806,-34836.161,9001,8807,56464.049,9001,,,,,,,,,
 3381,"GDM2000 / Terengganu Grid",9001,4742,19889,9806,1,0,4400,8801,4.583462672,9110,8802,103.041299225,9110,8806,19594.245,9001,8807,3371.895,9001,,,,,,,,,
 3382,"GDM2000 / Pinang Grid",9001,4742,19888,9806,1,0,4400,8801,5.251746315,9110,8802,100.203975707,9110,8806,-23.414,9001,8807,62.283,9001,,,,,,,,,
@@ -1860,9 +1860,9 @@
 3968,"NAD83 / Virginia Lambert",9001,4269,3967,9802,1,0,4499,8821,36,9102,8822,-79.5,9102,8823,37,9102,8824,39.5,9102,8826,0,9001,8827,0,9001,,,
 3969,"NAD83(HARN) / Virginia Lambert",9001,4152,3967,9802,1,0,4499,8821,36,9102,8822,-79.5,9102,8823,37,9102,8824,39.5,9102,8826,0,9001,8827,0,9001,,,
 3970,"NAD83(NSRS2007) / Virginia Lambert",9001,4759,3967,9802,1,0,4499,8821,36,9102,8822,-79.5,9102,8823,37,9102,8824,39.5,9102,8826,0,9001,8827,0,9001,,,
-3973,"WGS 84 / NSIDC EASE-Grid North",9001,4326,3897,1027,1,0,4469,8801,90,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,
-3974,"WGS 84 / NSIDC EASE-Grid South",9001,4326,3898,1027,1,0,4470,8801,-90,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,
-3975,"WGS 84 / NSIDC EASE-Grid Global",9001,4326,19869,9834,1,0,4499,8802,0,9102,8806,0,9001,8807,0,9001,8823,30,9102,,,,,,,,,
+3973,"WGS 84 / NSIDC EASE-Grid North",9001,4326,3897,1027,1,1,4469,8801,90,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,
+3974,"WGS 84 / NSIDC EASE-Grid South",9001,4326,3898,1027,1,1,4470,8801,-90,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,
+3975,"WGS 84 / NSIDC EASE-Grid Global",9001,4326,19869,9834,1,1,4499,8802,0,9102,8806,0,9001,8807,0,9001,8823,30,9102,,,,,,,,,
 3976,"WGS 84 / NSIDC Sea Ice Polar Stereographic South",9001,4326,19866,9829,1,0,4470,8806,0,9001,8807,0,9001,8832,-70,9102,8833,0,9102,,,,,,,,,
 3978,"NAD83 / Canada Atlas Lambert",9001,4269,3977,9802,1,0,4400,8821,49,9102,8822,-95,9102,8823,49,9102,8824,77,9102,8826,0,9001,8827,0,9001,,,
 3979,"NAD83(CSRS) / Canada Atlas Lambert",9001,4617,3977,9802,1,0,4400,8821,49,9102,8822,-95,9102,8823,49,9102,8824,77,9102,8826,0,9001,8827,0,9001,,,
@@ -1903,6 +1903,15 @@
 4095,"ETRS89 / DKTM3",9001,4258,4091,9807,1,0,4400,8801,0,9102,8802,11.75,9102,8805,0.99998,9201,8806,600000,9001,8807,-5000000,9001,,,,,,
 4096,"ETRS89 / DKTM4",9001,4258,4092,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,1,9201,8806,800000,9001,8807,-5000000,9001,,,,,,
 4217,"NAD83 / BLM 59N (ftUS)",9003,4269,4186,9807,1,0,4497,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4390,"Kertau 1968 / Johor Grid",9001,4245,4114,9806,1,0,4400,8801,2.02333,9110,8802,103.334593,9110,8806,0,9001,8807,0,9001,,,,,,,,,
+4391,"Kertau 1968 / Sembilan and Melaka Grid",9001,4245,4115,9806,1,0,4400,8801,2.424422,9110,8802,101.56282,9110,8806,-242.005,9001,8807,-948.547,9001,,,,,,,,,
+4392,"Kertau 1968 / Pahang Grid",9001,4245,4116,9806,1,0,4400,8801,3.42395,9110,8802,102.261024,9110,8806,0,9001,8807,0,9001,,,,,,,,,
+4393,"Kertau 1968 / Selangor Grid",9001,4245,4117,9806,1,0,4400,8801,3.404924,9110,8802,101.302968,9110,8806,-21759.438,9001,8807,55960.906,9001,,,,,,,,,
+4394,"Kertau 1968 / Terengganu Grid",9001,4245,4177,9806,1,0,4400,8801,4.564611,9110,8802,102.534275,9110,8806,0,9001,8807,0,9001,,,,,,,,,
+4395,"Kertau 1968 / Pinang Grid",9001,4245,4305,9806,1,0,4400,8801,5.251677,9110,8802,100.204513,9110,8806,0,9001,8807,0,9001,,,,,,,,,
+4396,"Kertau 1968 / Kedah and Perlis Grid",9001,4245,4320,9806,1,0,4400,8801,5.575453,9110,8802,100.381534,9110,8806,0,9001,8807,0,9001,,,,,,,,,
+4397,"Kertau 1968 / Perak Revised Grid",9001,4245,4321,9806,1,0,4400,8801,4.513377,9110,8802,100.490036,9110,8806,0,9001,8807,133453.669,9001,,,,,,,,,
+4398,"Kertau 1968 / Kelantan Grid",9001,4245,4323,9806,1,0,4400,8801,5.533812,9110,8802,102.103825,9110,8806,0,9001,8807,0,9001,,,,,,,,,
 4399,"NAD27 / BLM 59N (ftUS)",9003,4267,4186,9807,1,0,4497,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
 4400,"NAD27 / BLM 60N (ftUS)",9003,4267,4187,9807,1,0,4497,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
 4401,"NAD27 / BLM 1N (ftUS)",9003,4267,4101,9807,1,0,4497,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
@@ -2256,7 +2265,7 @@
 5479,"RSRGD2000 / MSLC2000",9001,4764,5475,9802,1,0,4500,8821,-78,9110,8822,163,9110,8823,-76.4,9110,8824,-79.2,9110,8826,7000000,9001,8827,5000000,9001,,,
 5480,"RSRGD2000 / BCLC2000",9001,4764,5476,9802,1,0,4500,8821,-74.3,9110,8822,165,9110,8823,-73.4,9110,8824,-75.2,9110,8826,5000000,9001,8827,3000000,9001,,,
 5481,"RSRGD2000 / PCLC2000",9001,4764,5477,9802,1,0,4500,8821,-71.3,9110,8822,166,9110,8823,-70.4,9110,8824,-72.2,9110,8826,3000000,9001,8827,1000000,9001,,,
-5482,"RSRGD2000 / RSPS2000",9001,4764,5478,9810,1,0,4500,8801,-90,9102,8802,180,9102,8805,0.994,9201,8806,5000000,9001,8807,1000000,9001,,,,,,
+5482,"RSRGD2000 / RSPS2000",9001,4764,5478,9810,1,0,1044,8801,-90,9102,8802,180,9102,8805,0.994,9201,8806,5000000,9001,8807,1000000,9001,,,,,,
 5490,"RGAF09 / UTM zone 20N",9001,5489,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 5513,"S-JTSK / Krovak",9001,4156,5509,9819,1,0,6501,1036,30.1717303,9110,8806,0,9001,8807,0,9001,8811,49.3,9110,8818,78.3,9110,8819,0.9999,9201,8833,24.5,9110
 5514,"S-JTSK / Krovak East North",9001,4156,5510,1041,1,0,4499,1036,30.1717303,9110,8806,0,9001,8807,0,9001,8811,49.3,9110,8818,78.3,9110,8819,0.9999,9201,8833,24.5,9110
@@ -2470,10 +2479,10 @@
 6128,Grand Cayman National Grid 1959,9002,4723,6127,9807,1,0,1039,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,1640419.9475,9002,8807,0,9002,,,,,,
 6129,Sister Islands National Grid 1961,9002,4726,6127,9807,1,0,1039,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,1640419.9475,9002,8807,0,9002,,,,,,
 6141,Cayman Islands National Grid 2011,9002,6135,6126,9802,1,1,1039,8821,19.2,9110,8822,80.34,9110,8823,19.2,9110,8824,19.42,9110,8826,2950000,9002,8827,1900000,9002,,,
-6200,"NAD27 / Michigan North",9003,4267,6197,1051,1,0,4497,1038,1.0000382,9201,8821,44.87,9110,8822,-87,9110,8823,45.29,9110,8824,47.05,9110,8826,2000000,9003,8827,0,9003
+6200,"NAD27 / Michigan North",9003,4267,6197,1051,1,1,4497,1038,1.0000382,9201,8821,44.87,9110,8822,-87,9110,8823,45.29,9110,8824,47.05,9110,8826,2000000,9003,8827,0,9003
 6201,"NAD27 / Michigan Central",9003,4267,6198,1051,1,0,4497,1038,1.0000382,9201,8821,43.19,9110,8822,-84.2,9110,8823,44.11,9110,8824,45.42,9110,8826,2000000,9003,8827,0,9003
 6202,"NAD27 / Michigan South",9003,4267,6199,1051,1,0,4497,1038,1.0000382,9201,8821,41.3,9110,8822,-84.2,9110,8823,42.06,9110,8824,43.4,9110,8826,2000000,9003,8827,0,9003
-6204,Macedonian State Coordinate System,9001,3906,6203,9807,1,0,4498,8801,0,9102,8802,21,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
+6204,Macedonia State Coordinate System,9001,3906,6203,9807,1,0,4498,8801,0,9102,8802,21,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
 6210,"SIRGAS 2000 / UTM zone 23N",9001,4674,16023,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 6211,"SIRGAS 2000 / UTM zone 24N",9001,4674,16024,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 6244,"MAGNA-SIRGAS / Arauca urban grid",9001,4686,6212,1052,1,0,4500,1039,100,9001,8801,7.051538301,9110,8802,-70.452991476,9110,8806,1035263.443,9001,8807,1275526.621,9001,,,,,,
@@ -2508,6 +2517,8 @@
 6273,"MAGNA-SIRGAS / Valledupar urban grid",9001,4686,6241,1052,1,0,4500,1039,200,9001,8801,10.265014,9110,8802,-73.1447657,9110,8806,1090979.66,9001,8807,1647208.93,9001,,,,,,
 6274,"MAGNA-SIRGAS / Villavicencio urban grid",9001,4686,6242,1052,1,0,4500,1039,427.19,9001,8801,4.091935036,9110,8802,-73.372814955,9110,8806,1050678.757,9001,8807,950952.124,9001,,,,,,
 6275,"MAGNA-SIRGAS / Yopal urban grid",9001,4686,6243,1052,1,0,4500,1039,300,9001,8801,5.2114138,9110,8802,-72.2512145,9110,8806,851184.177,9001,8807,1083954.137,9001,,,,,,
+6307,"NAD83(CORS96) / Puerto Rico and Virgin Is.",9001,6783,15230,9802,1,0,4499,8821,17.5,9110,8822,-66.26,9110,8823,18.26,9110,8824,18.02,9110,8826,200000,9001,8827,200000,9001,,,
+6312,"CGRS93 / Cyprus Local Transverse Mercator",9001,6311,6308,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.99995,9201,8806,200000,9001,8807,-3500000,9001,,,,,,
 6316,Macedonia State Coordinate System zone 7,9001,3906,18277,9807,1,0,4498,8801,0,9102,8802,21,9102,8805,0.9999,9201,8806,7500000,9001,8807,0,9001,,,,,,
 6328,"NAD83(2011) / UTM zone 59N",9001,6318,16059,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 6329,"NAD83(2011) / UTM zone 60N",9001,6318,16060,9807,1,0,4400,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
@@ -2831,16 +2842,96 @@
 6721,"GDA94 / CIG94",9001,4283,6717,9807,1,0,4400,8801,0,9110,8802,105.373,9110,8805,1.00002514,9201,8806,50000,9001,8807,1300000,9001,,,,,,
 6722,"WGS 84 / CKIG92",9001,4326,6718,9807,1,0,4400,8801,0,9110,8802,96.523,9110,8805,1,9201,8806,50000,9001,8807,1400000,9001,,,,,,
 6723,"GDA94 / CKIG94",9001,4283,6719,9807,1,0,4400,8801,0,9110,8802,96.523,9110,8805,0.99999387,9201,8806,50000,9001,8807,1500000,9001,,,,,,
-6732,"GDA94 / MGA zone 41",9001,4283,6725,9807,1,0,4400,8801,0,9102,8802,63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-6733,"GDA94 / MGA zone 42",9001,4283,6726,9807,1,0,4400,8801,0,9102,8802,69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-6734,"GDA94 / MGA zone 43",9001,4283,6727,9807,1,0,4400,8801,0,9102,8802,75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-6735,"GDA94 / MGA zone 44",9001,4283,6728,9807,1,0,4400,8801,0,9102,8802,81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+6732,"GDA94 / MGA zone 41",9001,4283,6725,9807,1,1,4400,8801,0,9102,8802,63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+6733,"GDA94 / MGA zone 42",9001,4283,6726,9807,1,1,4400,8801,0,9102,8802,69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+6734,"GDA94 / MGA zone 43",9001,4283,6727,9807,1,1,4400,8801,0,9102,8802,75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+6735,"GDA94 / MGA zone 44",9001,4283,6728,9807,1,1,4400,8801,0,9102,8802,81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
 6736,"GDA94 / MGA zone 46",9001,4283,6729,9807,1,0,4400,8801,0,9102,8802,93,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
 6737,"GDA94 / MGA zone 47",9001,4283,6730,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
 6738,"GDA94 / MGA zone 59",9001,4283,6731,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+6784,"NAD83(CORS96) / Oregon Baker zone (m)",9001,6783,6741,9807,1,0,4499,8801,44.3,9110,8802,-117.5,9110,8805,1.00016,9201,8806,40000,9001,8807,0,9001,,,,,,
+6785,"NAD83(CORS96) / Oregon Baker zone (ft)",9002,6783,6742,9807,1,0,4495,8801,44.3,9110,8802,-117.5,9110,8805,1.00016,9201,8806,131233.5958,9002,8807,0,9002,,,,,,
+6786,"NAD83(2011) / Oregon Baker zone (m)",9001,6318,6741,9807,1,0,4499,8801,44.3,9110,8802,-117.5,9110,8805,1.00016,9201,8806,40000,9001,8807,0,9001,,,,,,
+6787,"NAD83(2011) / Oregon Baker zone (ft)",9002,6318,6742,9807,1,0,4495,8801,44.3,9110,8802,-117.5,9110,8805,1.00016,9201,8806,131233.5958,9002,8807,0,9002,,,,,,
+6788,"NAD83(CORS96) / Oregon Bend-Klamath Falls zone (m)",9001,6783,6743,9807,1,0,4499,8801,41.45,9110,8802,-121.45,9110,8805,1.0002,9201,8806,80000,9001,8807,0,9001,,,,,,
+6789,"NAD83(CORS96) / Oregon Bend-Klamath Falls zone (ft)",9002,6783,6744,9807,1,0,4495,8801,41.45,9110,8802,-121.45,9110,8805,1.0002,9201,8806,262467.1916,9002,8807,0,9002,,,,,,
+6790,"NAD83(2011) / Oregon Bend-Klamath Falls zone (m)",9001,6318,6743,9807,1,0,4499,8801,41.45,9110,8802,-121.45,9110,8805,1.0002,9201,8806,80000,9001,8807,0,9001,,,,,,
+6791,"NAD83(2011) / Oregon Bend-Klamath Falls zone (ft)",9002,6318,6744,9807,1,0,4495,8801,41.45,9110,8802,-121.45,9110,8805,1.0002,9201,8806,262467.1916,9002,8807,0,9002,,,,,,
+6792,"NAD83(CORS96) / Oregon Bend-Redmond-Prineville zone (m)",9001,6783,6745,9801,1,0,4499,8801,44.4,9110,8802,-121.15,9110,8805,1.00012,9201,8806,80000,9001,8807,130000,9001,,,,,,
+6793,"NAD83(CORS96) / Oregon Bend-Redmond-Prineville zone (ft)",9002,6783,6746,9801,1,0,4495,8801,44.4,9110,8802,-121.15,9110,8805,1.00012,9201,8806,262467.1916,9002,8807,426509.1864,9002,,,,,,
+6794,"NAD83(2011) / Oregon Bend-Redmond-Prineville zone (m)",9001,6318,6745,9801,1,0,4499,8801,44.4,9110,8802,-121.15,9110,8805,1.00012,9201,8806,80000,9001,8807,130000,9001,,,,,,
+6795,"NAD83(2011) / Oregon Bend-Redmond-Prineville zone (ft)",9002,6318,6746,9801,1,0,4495,8801,44.4,9110,8802,-121.15,9110,8805,1.00012,9201,8806,262467.1916,9002,8807,426509.1864,9002,,,,,,
+6796,"NAD83(CORS96) / Oregon Bend-Burns zone (m)",9001,6783,6747,9801,1,0,4499,8801,43.4,9110,8802,-119.45,9110,8805,1.0002,9201,8806,120000,9001,8807,60000,9001,,,,,,
+6797,"NAD83(CORS96) / Oregon Bend-Burns zone (ft)",9002,6783,6748,9801,1,0,4495,8801,43.4,9110,8802,-119.45,9110,8805,1.0002,9201,8806,393700.7874,9002,8807,196850.3937,9002,,,,,,
+6798,"NAD83(2011) / Oregon Bend-Burns zone (m)",9001,6318,6747,9801,1,0,4499,8801,43.4,9110,8802,-119.45,9110,8805,1.0002,9201,8806,120000,9001,8807,60000,9001,,,,,,
+6799,"NAD83(2011) / Oregon Bend-Burns zone (ft)",9002,6318,6748,9801,1,0,4495,8801,43.4,9110,8802,-119.45,9110,8805,1.0002,9201,8806,393700.7874,9002,8807,196850.3937,9002,,,,,,
+6800,"NAD83(CORS96) / Oregon Canyonville-Grants Pass zone (m)",9001,6783,6749,9807,1,0,4499,8801,42.3,9110,8802,-123.2,9110,8805,1.00007,9201,8806,40000,9001,8807,0,9001,,,,,,
+6801,"NAD83(CORS96) / Oregon Canyonville-Grants Pass zone (ft)",9002,6783,6750,9807,1,0,4495,8801,42.3,9110,8802,-123.2,9110,8805,1.00007,9201,8806,131233.5958,9002,8807,0,9002,,,,,,
+6802,"NAD83(2011) / Oregon Canyonville-Grants Pass zone (m)",9001,6318,6749,9807,1,0,4499,8801,42.3,9110,8802,-123.2,9110,8805,1.00007,9201,8806,40000,9001,8807,0,9001,,,,,,
+6803,"NAD83(2011) / Oregon Canyonville-Grants Pass zone (ft)",9002,6318,6750,9807,1,0,4495,8801,42.3,9110,8802,-123.2,9110,8805,1.00007,9201,8806,131233.5958,9002,8807,0,9002,,,,,,
+6804,"NAD83(CORS96) / Oregon Columbia River East zone (m)",9001,6783,6751,9801,1,0,4499,8801,45.4,9110,8802,-120.3,9110,8805,1.000008,9201,8806,150000,9001,8807,30000,9001,,,,,,
+6805,"NAD83(CORS96) / Oregon Columbia River East zone (ft)",9002,6783,6752,9801,1,0,4495,8801,45.4,9110,8802,-120.3,9110,8805,1.000008,9201,8806,492125.9843,9002,8807,98425.1969,9002,,,,,,
+6806,"NAD83(2011) / Oregon Columbia River East zone (m)",9001,6318,6751,9801,1,0,4499,8801,45.4,9110,8802,-120.3,9110,8805,1.000008,9201,8806,150000,9001,8807,30000,9001,,,,,,
+6807,"NAD83(2011) / Oregon Columbia River East zone (ft)",9002,6318,6752,9801,1,0,4495,8801,45.4,9110,8802,-120.3,9110,8805,1.000008,9201,8806,492125.9843,9002,8807,98425.1969,9002,,,,,,
+6808,"NAD83(CORS96) / Oregon Columbia River West zone (m)",9001,6783,6753,9812,1,0,4499,8806,7000000,9001,8807,-3000000,9001,8811,45.55,9110,8812,-123,9110,8813,295,9102,8814,295,9102,8815,1,9201
+6809,"NAD83(CORS96) / Oregon Columbia River West zone (ft)",9002,6783,6754,9812,1,0,4495,8806,22965879.2651,9002,8807,-9842519.685,9002,8811,45.55,9110,8812,-123,9110,8813,295,9102,8814,295,9102,8815,1,9201
+6810,"NAD83(2011) / Oregon Columbia River West zone (m)",9001,6318,6753,9812,1,0,4499,8806,7000000,9001,8807,-3000000,9001,8811,45.55,9110,8812,-123,9110,8813,295,9102,8814,295,9102,8815,1,9201
+6811,"NAD83(2011) / Oregon Columbia River West zone (ft)",9002,6318,6754,9812,1,0,4495,8806,22965879.2651,9002,8807,-9842519.685,9002,8811,45.55,9110,8812,-123,9110,8813,295,9102,8814,295,9102,8815,1,9201
+6812,"NAD83(CORS96) / Oregon Cottage Grove-Canyonville zone (m)",9001,6783,6755,9807,1,0,4499,8801,42.5,9110,8802,-123.2,9110,8805,1.000023,9201,8806,50000,9001,8807,0,9001,,,,,,
+6813,"NAD83(CORS96) / Oregon Cottage Grove-Canyonville zone (ft)",9002,6783,6756,9807,1,0,4495,8801,42.5,9110,8802,-123.2,9110,8805,1.000023,9201,8806,164041.9948,9002,8807,0,9002,,,,,,
+6814,"NAD83(2011) / Oregon Cottage Grove-Canyonville zone (m)",9001,6318,6755,9807,1,0,4499,8801,42.5,9110,8802,-123.2,9110,8805,1.000023,9201,8806,50000,9001,8807,0,9001,,,,,,
+6815,"NAD83(2011) / Oregon Cottage Grove-Canyonville zone (ft)",9002,6318,6756,9807,1,0,4495,8801,42.5,9110,8802,-123.2,9110,8805,1.000023,9201,8806,164041.9948,9002,8807,0,9002,,,,,,
+6816,"NAD83(CORS96) / Oregon Dufur-Madras zone (m)",9001,6783,6757,9807,1,0,4499,8801,44.3,9110,8802,-121,9110,8805,1.00011,9201,8806,80000,9001,8807,0,9001,,,,,,
+6817,"NAD83(CORS96) / Oregon Dufur-Madras zone (ft)",9002,6783,6758,9807,1,0,4495,8801,44.3,9110,8802,-121,9110,8805,1.00011,9201,8806,262467.1916,9002,8807,0,9002,,,,,,
+6818,"NAD83(2011) / Oregon Dufur-Madras zone (m)",9001,6318,6757,9807,1,0,4499,8801,44.3,9110,8802,-121,9110,8805,1.00011,9201,8806,80000,9001,8807,0,9001,,,,,,
+6819,"NAD83(2011) / Oregon Dufur-Madras zone (ft)",9002,6318,6758,9807,1,0,4495,8801,44.3,9110,8802,-121,9110,8805,1.00011,9201,8806,262467.1916,9002,8807,0,9002,,,,,,
+6820,"NAD83(CORS96) / Oregon Eugene zone (m)",9001,6783,6759,9807,1,0,4499,8801,43.45,9110,8802,-123.1,9110,8805,1.000015,9201,8806,50000,9001,8807,0,9001,,,,,,
+6821,"NAD83(CORS96) / Oregon Eugene zone (ft)",9002,6783,6760,9807,1,0,4495,8801,43.45,9110,8802,-123.1,9110,8805,1.000015,9201,8806,164041.9948,9002,8807,0,9002,,,,,,
+6822,"NAD83(2011) / Oregon Eugene zone (m)",9001,6318,6759,9807,1,0,4499,8801,43.45,9110,8802,-123.1,9110,8805,1.000015,9201,8806,50000,9001,8807,0,9001,,,,,,
+6823,"NAD83(2011) / Oregon Eugene zone (ft)",9002,6318,6760,9807,1,0,4495,8801,43.45,9110,8802,-123.1,9110,8805,1.000015,9201,8806,164041.9948,9002,8807,0,9002,,,,,,
+6824,"NAD83(CORS96) / Oregon Grants Pass-Ashland zone (m)",9001,6783,6761,9807,1,0,4499,8801,41.45,9110,8802,-123.2,9110,8805,1.000043,9201,8806,50000,9001,8807,0,9001,,,,,,
+6825,"NAD83(CORS96) / Oregon Grants Pass-Ashland zone (ft)",9002,6783,6762,9807,1,0,4495,8801,41.45,9110,8802,-123.2,9110,8805,1.000043,9201,8806,164041.9948,9002,8807,0,9002,,,,,,
+6826,"NAD83(2011) / Oregon Grants Pass-Ashland zone (m)",9001,6318,6761,9807,1,0,4499,8801,41.45,9110,8802,-123.2,9110,8805,1.000043,9201,8806,50000,9001,8807,0,9001,,,,,,
+6827,"NAD83(2011) / Oregon Grants Pass-Ashland zone (ft)",9002,6318,6762,9807,1,0,4495,8801,41.45,9110,8802,-123.2,9110,8805,1.000043,9201,8806,164041.9948,9002,8807,0,9002,,,,,,
+6828,"NAD83(CORS96) / Oregon Gresham-Warm Springs zone (m)",9001,6783,6763,9807,1,0,4499,8801,45,9110,8802,-122.2,9110,8805,1.00005,9201,8806,10000,9001,8807,0,9001,,,,,,
+6829,"NAD83(CORS96) / Oregon Gresham-Warm Springs zone (ft)",9002,6783,6764,9807,1,0,4495,8801,45,9110,8802,-122.2,9110,8805,1.00005,9201,8806,32808.399,9002,8807,0,9002,,,,,,
+6830,"NAD83(2011) / Oregon Gresham-Warm Springs zone (m)",9001,6318,6763,9807,1,0,4499,8801,45,9110,8802,-122.2,9110,8805,1.00005,9201,8806,10000,9001,8807,0,9001,,,,,,
+6831,"NAD83(2011) / Oregon Gresham-Warm Springs zone (ft)",9002,6318,6764,9807,1,0,4495,8801,45,9110,8802,-122.2,9110,8805,1.00005,9201,8806,32808.399,9002,8807,0,9002,,,,,,
+6832,"NAD83(CORS96) / Oregon La Grande zone (m)",9001,6783,6765,9807,1,0,4499,8801,45,9102,8802,-118,9102,8805,1.00013,9201,8806,40000,9001,8807,0,9001,,,,,,
+6833,"NAD83(CORS96) / Oregon La Grande zone (ft)",9002,6783,6766,9807,1,0,4495,8801,45,9102,8802,-118,9102,8805,1.00013,9201,8806,131233.5958,9002,8807,0,9002,,,,,,
+6834,"NAD83(2011) / Oregon La Grande zone (m)",9001,6318,6765,9807,1,0,4499,8801,45,9102,8802,-118,9102,8805,1.00013,9201,8806,40000,9001,8807,0,9001,,,,,,
+6835,"NAD83(2011) / Oregon La Grande zone (ft)",9002,6318,6766,9807,1,0,4495,8801,45,9102,8802,-118,9102,8805,1.00013,9201,8806,131233.5958,9002,8807,0,9002,,,,,,
+6836,"NAD83(CORS96) / Oregon Ontario zone (m)",9001,6783,6767,9807,1,0,4499,8801,43.15,9110,8802,-117,9110,8805,1.0001,9201,8806,80000,9001,8807,0,9001,,,,,,
+6837,"NAD83(CORS96) / Oregon Ontario zone (ft)",9002,6783,6768,9807,1,0,4495,8801,43.15,9110,8802,-117,9110,8805,1.0001,9201,8806,262467.1916,9002,8807,0,9002,,,,,,
+6838,"NAD83(2011) / Oregon Ontario zone (m)",9001,6318,6767,9807,1,0,4499,8801,43.15,9110,8802,-117,9110,8805,1.0001,9201,8806,80000,9001,8807,0,9001,,,,,,
+6839,"NAD83(2011) / Oregon Ontario zone (ft)",9002,6318,6768,9807,1,0,4495,8801,43.15,9110,8802,-117,9110,8805,1.0001,9201,8806,262467.1916,9002,8807,0,9002,,,,,,
+6840,"NAD83(CORS96) / Oregon Coast zone (m)",9001,6783,6769,9812,1,0,4499,8806,-300000,9001,8807,-4600000,9001,8811,44.45,9110,8812,-124.03,9110,8813,5,9102,8814,5,9102,8815,1,9201
+6841,"NAD83(CORS96) / Oregon Coast zone (ft)",9002,6783,6770,9812,1,0,4495,8806,-984251.9685,9002,8807,-15091863.5171,9002,8811,44.45,9110,8812,-124.03,9110,8813,5,9102,8814,5,9102,8815,1,9201
+6842,"NAD83(2011) / Oregon Coast zone (m)",9001,6318,6769,9812,1,0,4499,8806,-300000,9001,8807,-4600000,9001,8811,44.45,9110,8812,-124.03,9110,8813,5,9102,8814,5,9102,8815,1,9201
+6843,"NAD83(2011) / Oregon Coast zone (ft)",9002,6318,6770,9812,1,0,4495,8806,-984251.9685,9002,8807,-15091863.5171,9002,8811,44.45,9110,8812,-124.03,9110,8813,5,9102,8814,5,9102,8815,1,9201
+6844,"NAD83(CORS96) / Oregon Pendleton zone (m)",9001,6783,6771,9807,1,0,4499,8801,45.15,9110,8802,-119.1,9110,8805,1.000045,9201,8806,60000,9001,8807,0,9001,,,,,,
+6845,"NAD83(CORS96) / Oregon Pendleton zone (ft)",9002,6783,6772,9807,1,0,4495,8801,45.15,9110,8802,-119.1,9110,8805,1.000045,9201,8806,196850.3937,9002,8807,0,9002,,,,,,
+6846,"NAD83(2011) / Oregon Pendleton zone (m)",9001,6318,6771,9807,1,0,4499,8801,45.15,9110,8802,-119.1,9110,8805,1.000045,9201,8806,60000,9001,8807,0,9001,,,,,,
+6847,"NAD83(2011) / Oregon Pendleton zone (ft)",9002,6318,6772,9807,1,0,4495,8801,45.15,9110,8802,-119.1,9110,8805,1.000045,9201,8806,196850.3937,9002,8807,0,9002,,,,,,
+6848,"NAD83(CORS96) / Oregon Pendleton-La Grande zone (m)",9001,6783,6773,9807,1,0,4499,8801,45.05,9110,8802,-118.2,9110,8805,1.000175,9201,8806,30000,9001,8807,0,9001,,,,,,
+6849,"NAD83(CORS96) / Oregon Pendleton-La Grande zone (ft)",9002,6783,6774,9807,1,0,4495,8801,45.05,9110,8802,-118.2,9110,8805,1.000175,9201,8806,98425.1969,9002,8807,0,9002,,,,,,
+6850,"NAD83(2011) / Oregon Pendleton-La Grande zone (m)",9001,6318,6773,9807,1,0,4499,8801,45.05,9110,8802,-118.2,9110,8805,1.000175,9201,8806,30000,9001,8807,0,9001,,,,,,
+6851,"NAD83(2011) / Oregon Pendleton-La Grande zone (ft)",9002,6318,6774,9807,1,0,4495,8801,45.05,9110,8802,-118.2,9110,8805,1.000175,9201,8806,98425.1969,9002,8807,0,9002,,,,,,
+6852,"NAD83(CORS96) / Oregon Portland zone (m)",9001,6783,6775,9801,1,0,4499,8801,45.3,9110,8802,-122.45,9110,8805,1.000002,9201,8806,100000,9001,8807,50000,9001,,,,,,
+6853,"NAD83(CORS96) / Oregon Portland zone (ft)",9002,6783,6776,9801,1,0,4495,8801,45.3,9110,8802,-122.45,9110,8805,1.000002,9201,8806,328083.9895,9002,8807,164041.9948,9002,,,,,,
+6854,"NAD83(2011) / Oregon Portland zone (m)",9001,6318,6775,9801,1,0,4499,8801,45.3,9110,8802,-122.45,9110,8805,1.000002,9201,8806,100000,9001,8807,50000,9001,,,,,,
+6855,"NAD83(2011) / Oregon Portland zone (ft)",9002,6318,6776,9801,1,0,4495,8801,45.3,9110,8802,-122.45,9110,8805,1.000002,9201,8806,328083.9895,9002,8807,164041.9948,9002,,,,,,
+6856,"NAD83(CORS96) / Oregon Salem zone (m)",9001,6783,6777,9807,1,0,4499,8801,44.2,9110,8802,-123.05,9110,8805,1.00001,9201,8806,50000,9001,8807,0,9001,,,,,,
+6857,"NAD83(CORS96) / Oregon Salem zone (ft)",9002,6783,6778,9807,1,0,4495,8801,44.2,9110,8802,-123.05,9110,8805,1.00001,9201,8806,164041.9948,9002,8807,0,9002,,,,,,
+6858,"NAD83(2011) / Oregon Salem zone (m)",9001,6318,6777,9807,1,0,4499,8801,44.2,9110,8802,-123.05,9110,8805,1.00001,9201,8806,50000,9001,8807,0,9001,,,,,,
+6859,"NAD83(2011) / Oregon Salem zone (ft)",9002,6318,6778,9807,1,0,4495,8801,44.2,9110,8802,-123.05,9110,8805,1.00001,9201,8806,164041.9948,9002,8807,0,9002,,,,,,
+6860,"NAD83(CORS96) / Oregon Santiam Pass zone (m)",9001,6783,6779,9807,1,0,4499,8801,44.05,9110,8802,-122.3,9110,8805,1.000155,9201,8806,0,9001,8807,0,9001,,,,,,
+6861,"NAD83(CORS96) / Oregon Santiam Pass zone (ft)",9002,6783,6780,9807,1,0,4495,8801,44.05,9110,8802,-122.3,9110,8805,1.000155,9201,8806,0,9002,8807,0,9002,,,,,,
+6862,"NAD83(2011) / Oregon Santiam Pass zone (m)",9001,6318,6779,9807,1,0,4499,8801,44.05,9110,8802,-122.3,9110,8805,1.000155,9201,8806,0,9001,8807,0,9001,,,,,,
+6863,"NAD83(2011) / Oregon Santiam Pass (ft)",9002,6318,6780,9807,1,0,4495,8801,44.05,9110,8802,-122.3,9110,8805,1.000155,9201,8806,0,9002,8807,0,9002,,,,,,
 6867,"NAD83(CORS96) / Oregon LCC (m)",9001,6783,13633,9802,1,0,4499,8821,41.45,9110,8822,-120.3,9110,8823,43,9110,8824,45.3,9110,8826,400000,9001,8827,0,9001,,,
 6868,"NAD83(CORS96) / Oregon GIC Lambert (ft)",9002,6783,15374,9802,1,0,4495,8821,41.45,9110,8822,-120.3,9110,8823,43,9110,8824,45.3,9110,8826,1312335.958,9002,8827,0,9002,,,
-6870,"ETRS89 / Albania 2010",9001,4258,6869,9807,1,0,4530,8801,0,9102,8802,20,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
+6870,"ETRS89 / Albania TM 2010",9001,4258,6869,9807,1,0,4530,8801,0,9102,8802,20,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
 6875,"RDN2008 / Italy zone",9001,6706,6877,9807,1,0,4500,8801,0,9102,8802,12,9102,8805,0.9985,9201,8806,7000000,9001,8807,0,9001,,,,,,
 6876,"RDN2008 / Zone 12",9001,6706,6878,9807,1,0,4500,8801,0,9102,8802,12,9102,8805,1,9201,8806,3000000,9001,8807,0,9001,,,,,,
 6879,"NAD83(2011) / Wisconsin Central",9001,6318,14832,9802,1,0,4499,8821,43.5,9110,8822,-90,9110,8823,45.3,9110,8824,44.15,9110,8826,600000,9001,8827,0,9001,,,
@@ -2849,6 +2940,308 @@
 6885,"NAD83(CORS96) / Oregon North (ft)",9002,6783,15351,9802,1,0,4495,8821,43.4,9110,8822,-120.3,9110,8823,46,9110,8824,44.2,9110,8826,8202099.738,9002,8827,0,9002,,,
 6886,"NAD83(CORS96) / Oregon South",9001,6783,13632,9802,1,0,4499,8821,41.4,9110,8822,-120.3,9110,8823,44,9110,8824,42.2,9110,8826,1500000,9001,8827,0,9001,,,
 6887,"NAD83(CORS96) / Oregon South (ft)",9002,6783,15352,9802,1,0,4495,8821,41.4,9110,8822,-120.3,9110,8823,44,9110,8824,42.2,9110,8826,4921259.843,9002,8827,0,9002,,,
+6915,"South East Island 1943 / UTM zone 40N",9001,6892,16040,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+6922,"NAD83 / Kansas LCC",9001,4269,6920,9802,1,0,4499,8821,36,9110,8822,-98.15,9110,8823,39.3,9110,8824,37.3,9110,8826,400000,9001,8827,0,9001,,,
+6923,"NAD83 / Kansas LCC (ftUS)",9003,4269,6921,9802,1,0,4497,8821,36,9110,8822,-98.15,9110,8823,39.3,9110,8824,37.3,9110,8826,1312333.3333,9003,8827,0,9003,,,
+6924,"NAD83(2011) / Kansas LCC",9001,6318,6920,9802,1,0,4499,8821,36,9110,8822,-98.15,9110,8823,39.3,9110,8824,37.3,9110,8826,400000,9001,8827,0,9001,,,
+6925,"NAD83(2011) / Kansas LCC (ftUS)",9003,6318,6921,9802,1,0,4497,8821,36,9110,8822,-98.15,9110,8823,39.3,9110,8824,37.3,9110,8826,1312333.3333,9003,8827,0,9003,,,
+6931,"WGS 84 / NSIDC EASE-Grid 2.0 North",9001,4326,6929,9820,1,0,4469,8801,90,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,
+6932,"WGS 84 / NSIDC EASE-Grid 2.0 South",9001,4326,6930,9820,1,0,4470,8801,-90,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,
+6933,"WGS 84 / NSIDC EASE-Grid 2.0 Global",9001,4326,6928,9835,1,0,4499,8802,0,9102,8806,0,9001,8807,0,9001,8823,30,9102,,,,,,,,,
+6956,"VN-2000 / TM-3 zone 481",9001,4756,6952,9807,1,0,4400,8801,0,9102,8802,102,9102,8805,0.9999,9201,8806,0,9001,8807,500000,9001,,,,,,
+6957,"VN-2000 / TM-3 zone 482",9001,4756,6953,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9999,9201,8806,0,9001,8807,500000,9001,,,,,,
+6958,"VN-2000 / TM-3 zone 491",9001,4756,6954,9807,1,0,4400,8801,0,9102,8802,108,9102,8805,0.9999,9201,8806,0,9001,8807,500000,9001,,,,,,
+6959,"VN-2000 / TM-3 Da Nang zone",9001,4756,6955,9807,1,0,4400,8801,0,9110,8802,107.45,9110,8805,0.9999,9201,8806,0,9001,8807,500000,9001,,,,,,
+6962,"ETRS89 / Albania LCC 2010",9001,4258,6961,9802,1,0,4530,8821,41,9102,8822,20,9102,8823,39,9102,8824,43,9102,8826,0,9001,8827,0,9001,,,
+6966,"NAD27 / Michigan North",9003,4267,6965,1051,1,0,4497,1038,1.0000382,9201,8821,44.47,9110,8822,-87,9110,8823,45.29,9110,8824,47.05,9110,8826,2000000,9003,8827,0,9003
+6984,Israeli Grid 05,9001,6983,18204,9807,1,0,4400,8801,31.4403817,9110,8802,35.1216261,9110,8805,1.0000067,9201,8806,219529.584,9001,8807,626907.39,9001,,,,,,
+6991,"Israeli Grid 05/12",9001,6990,18204,9807,1,0,4400,8801,31.4403817,9110,8802,35.1216261,9110,8805,1.0000067,9201,8806,219529.584,9001,8807,626907.39,9001,,,,,,
+6996,"NAD83(2011) / San Francisco CS13",9001,6318,6994,9807,1,1,4499,8801,37.75,9102,8802,-122.45,9102,8805,1.000007,9202,8806,48000,9001,8807,24000,9001,,,,,,
+6997,"NAD83(2011) / San Francisco CS13 (ftUS)",9003,6318,6995,9807,1,1,4497,8801,37.75,9102,8802,-122.45,9102,8805,1.000007,9202,8806,157480,9003,8807,78740,9003,,,,,,
+7005,"Nahrwan 1934 / UTM zone 37N",9001,4744,16037,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+7006,"Nahrwan 1934 / UTM zone 38N",9001,4744,16038,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+7007,"Nahrwan 1934 / UTM zone 39N",9001,4744,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+7057,"NAD83(2011) / IaRCS zone 1",9003,6318,7043,9801,1,0,4497,8801,43.12,9110,8802,-95.15,9110,8805,1.000052,9201,8806,11500000,9003,8807,9600000,9003,,,,,,
+7058,"NAD83(2011) / IaRCS zone 2",9003,6318,7044,9801,1,0,4497,8801,43.1,9110,8802,-92.45,9110,8805,1.000043,9201,8806,12500000,9003,8807,9800000,9003,,,,,,
+7059,"NAD83(2011) / IaRCS zone 3",9003,6318,7045,9807,1,0,4497,8801,40.15,9110,8802,-91.12,9110,8805,1.000035,9201,8806,13500000,9003,8807,8300000,9003,,,,,,
+7060,"NAD83(2011) / IaRCS zone 4",9003,6318,7046,9801,1,0,4497,8801,42.32,9110,8802,-94.5,9110,8805,1.000045,9201,8806,14500000,9003,8807,8600000,9003,,,,,,
+7061,"NAD83(2011) / IaRCS zone 5",9003,6318,7047,9801,1,0,4497,8801,42.39,9110,8802,-92.15,9110,8805,1.000032,9201,8806,15500000,9003,8807,8900000,9003,,,,,,
+7062,"NAD83(2011) / IaRCS zone 6",9003,6318,7048,9807,1,0,4497,8801,40.15,9110,8802,-95.44,9110,8805,1.000039,9201,8806,16500000,9003,8807,6600000,9003,,,,,,
+7063,"NAD83(2011) / IaRCS zone 7",9003,6318,7049,9807,1,0,4497,8801,40.15,9110,8802,-94.38,9110,8805,1.000045,9201,8806,17500000,9003,8807,6800000,9003,,,,,,
+7064,"NAD83(2011) / IaRCS zone 8",9003,6318,7050,9807,1,0,4497,8801,40.15,9110,8802,-93.43,9110,8805,1.000033,9201,8806,18500000,9003,8807,7000000,9003,,,,,,
+7065,"NAD83(2011) / IaRCS zone 9",9003,6318,7051,9807,1,0,4497,8801,40.15,9110,8802,-92.49,9110,8805,1.000027,9201,8806,19500000,9003,8807,7200000,9003,,,,,,
+7066,"NAD83(2011) / IaRCS zone 10",9003,6318,7052,9801,1,0,4497,8801,41.5,9110,8802,-91.4,9110,8805,1.00002,9201,8806,20500000,9003,8807,8000000,9003,,,,,,
+7067,"NAD83(2011) / IaRCS zone 11",9003,6318,7053,9807,1,0,4497,8801,40.15,9110,8802,-90.32,9110,8805,1.000027,9201,8806,21500000,9003,8807,7600000,9003,,,,,,
+7068,"NAD83(2011) / IaRCS zone 12",9003,6318,7054,9801,1,0,4497,8801,40.55,9110,8802,-93.45,9110,8805,1.000037,9201,8806,22500000,9003,8807,6200000,9003,,,,,,
+7069,"NAD83(2011) / IaRCS zone 13",9003,6318,7055,9807,1,0,4497,8801,40.15,9110,8802,-91.55,9110,8805,1.00002,9201,8806,23500000,9003,8807,6400000,9003,,,,,,
+7070,"NAD83(2011) / IaRCS zone 14",9003,6318,7056,9807,1,0,4497,8801,40.15,9110,8802,-91.15,9110,8805,1.000018,9201,8806,24500000,9003,8807,6200000,9003,,,,,,
+7074,"RGTAAF07 / UTM zone 37S",9001,7073,16137,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+7075,"RGTAAF07 / UTM zone 38S",9001,7073,16138,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+7076,"RGTAAF07 / UTM zone 39S",9001,7073,16139,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+7077,"RGTAAF07 / UTM zone 40S",9001,7073,16140,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+7078,"RGTAAF07 / UTM zone 41S",9001,7073,16141,9807,1,0,4400,8801,0,9102,8802,63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+7079,"RGTAAF07 / UTM zone 42S",9001,7073,16142,9807,1,0,4400,8801,0,9102,8802,69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+7080,"RGTAAF07 / UTM zone 43S",9001,7073,16143,9807,1,0,4400,8801,0,9102,8802,75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+7081,"RGTAAF07 / UTM zone 44S",9001,7073,16144,9807,1,0,4400,8801,0,9102,8802,81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+7082,"RGTAAF07 / Terre Adelie Polar Stereographic",9001,7073,19983,9830,1,0,4400,8826,300000,9001,8827,200000,9001,8832,-67,9102,8833,140,9102,,,,,,,,,
+7109,"NAD83(2011) / RMTCRS St Mary (m)",9001,6318,7089,9807,1,0,4499,8801,48.3,9110,8802,-112.3,9110,8805,1.00016,9201,8806,150000,9001,8807,0,9001,,,,,,
+7110,"NAD83(2011) / RMTCRS Blackfeet (m)",9001,6318,7091,9807,1,0,4499,8801,48,9110,8802,-112.3,9110,8805,1.00019,9201,8806,100000,9001,8807,0,9001,,,,,,
+7111,"NAD83(2011) / RMTCRS Milk River (m)",9001,6318,7093,9801,1,0,4499,8801,48.3,9110,8802,-111,9110,8805,1.000145,9201,8806,150000,9001,8807,200000,9001,,,,,,
+7112,"NAD83(2011) / RMTCRS Fort Belknap (m)",9001,6318,7095,9801,1,0,4499,8801,48.3,9110,8802,-108.3,9110,8805,1.00012,9201,8806,200000,9001,8807,150000,9001,,,,,,
+7113,"NAD83(2011) / RMTCRS Fort Peck Assiniboine (m)",9001,6318,7097,9801,1,0,4499,8801,48.2,9110,8802,-105.3,9110,8805,1.00012,9201,8806,200000,9001,8807,100000,9001,,,,,,
+7114,"NAD83(2011) / RMTCRS Fort Peck Sioux (m)",9001,6318,7099,9801,1,0,4499,8801,48.2,9110,8802,-105.3,9110,8805,1.00009,9201,8806,100000,9001,8807,50000,9001,,,,,,
+7115,"NAD83(2011) / RMTCRS Crow (m)",9001,6318,7101,9807,1,0,4499,8801,44.45,9110,8802,-107.45,9110,8805,1.000148,9201,8806,200000,9001,8807,0,9001,,,,,,
+7116,"NAD83(2011) / RMTCRS Bobcat (m)",9001,6318,7103,9801,1,0,4499,8801,46.15,9110,8802,-111.15,9110,8805,1.000185,9201,8806,100000,9001,8807,100000,9001,,,,,,
+7117,"NAD83(2011) / RMTCRS Billings (m)",9001,6318,7105,9801,1,0,4499,8801,45.47,9110,8802,-108.25,9110,8805,1.0001515,9201,8806,200000,9001,8807,50000,9001,,,,,,
+7118,"NAD83(2011) / RMTCRS Wind River (m)",9001,6318,7107,9807,1,0,4499,8801,42.4,9110,8802,-108.2,9110,8805,1.00024,9201,8806,100000,9001,8807,0,9001,,,,,,
+7119,"NAD83(2011) / RMTCRS St Mary (ft)",9002,6318,7090,9807,1,0,4495,8801,48.3,9110,8802,-112.3,9110,8805,1.00016,9201,8806,492125.9843,9002,8807,0,9002,,,,,,
+7120,"NAD83(2011) / RMTCRS Blackfeet (ft)",9002,6318,7092,9807,1,0,4495,8801,48,9110,8802,-112.3,9110,8805,1.00019,9201,8806,328083.9895,9002,8807,0,9002,,,,,,
+7121,"NAD83(2011) / RMTCRS Milk River (ft)",9002,6318,7094,9801,1,0,4495,8801,48.3,9110,8802,-111,9110,8805,1.000145,9201,8806,492125.9843,9002,8807,656167.979,9002,,,,,,
+7122,"NAD83(2011) / RMTCRS Fort Belknap (ft)",9002,6318,7096,9801,1,0,4495,8801,48.3,9110,8802,-108.3,9110,8805,1.00012,9201,8806,656167.979,9002,8807,492125.9843,9002,,,,,,
+7123,"NAD83(2011) / RMTCRS Fort Peck Assiniboine (ft)",9002,6318,7098,9801,1,0,4495,8801,48.2,9110,8802,-105.3,9110,8805,1.00012,9201,8806,656167.979,9002,8807,328083.9895,9002,,,,,,
+7124,"NAD83(2011) / RMTCRS Fort Peck Sioux (ft)",9002,6318,7100,9801,1,0,4495,8801,48.2,9110,8802,-105.3,9110,8805,1.00009,9201,8806,328083.9895,9002,8807,164041.9938,9002,,,,,,
+7125,"NAD83(2011) / RMTCRS Crow (ft)",9002,6318,7102,9807,1,0,4495,8801,44.45,9110,8802,-107.45,9110,8805,1.000148,9201,8806,656167.979,9002,8807,0,9002,,,,,,
+7126,"NAD83(2011) / RMTCRS Bobcat (ft)",9002,6318,7104,9801,1,0,4495,8801,46.15,9110,8802,-111.15,9110,8805,1.000185,9201,8806,328083.9895,9002,8807,328083.9895,9002,,,,,,
+7127,"NAD83(2011) / RMTCRS Billings (ft)",9002,6318,7106,9801,1,0,4495,8801,45.47,9110,8802,-108.25,9110,8805,1.0001515,9201,8806,656167.979,9002,8807,164041.9948,9002,,,,,,
+7128,"NAD83(2011) / RMTCRS Wind River (ftUS)",9003,6318,7108,9807,1,0,4497,8801,42.4,9110,8802,-108.2,9110,8805,1.00024,9201,8806,328083.3333,9003,8807,0,9003,,,,,,
+7131,"NAD83(2011) / San Francisco CS13",9001,6318,7129,9807,1,0,4499,8801,37.75,9102,8802,-122.45,9102,8805,1.000007,9201,8806,48000,9001,8807,24000,9001,,,,,,
+7132,"NAD83(2011) / San Francisco CS13 (ftUS)",9003,6318,7130,9807,1,0,4497,8801,37.75,9102,8802,-122.45,9102,8805,1.000007,9201,8806,157480,9003,8807,78740,9003,,,,,,
+7142,"Palestine 1923 / Palestine Grid modified",9001,4281,7141,9807,1,0,4400,8801,31.4402749,9110,8802,35.124349,9110,8805,1,9201,8806,170251.555,9001,8807,126867.909,9001,,,,,,
+7257,"NAD83(2011) / InGCS Adams (m)",9001,6318,7143,9807,1,0,4499,8801,40.33,9110,8802,-84.57,9110,8805,1.000034,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7258,"NAD83(2011) / InGCS Adams (ftUS)",9003,6318,7144,9807,1,0,4497,8801,40.33,9110,8802,-84.57,9110,8805,1.000034,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7259,"NAD83(2011) / InGCS Allen (m)",9001,6318,7145,9807,1,0,4499,8801,40.54,9110,8802,-85.03,9110,8805,1.000031,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7260,"NAD83(2011) / InGCS Allen (ftUS)",9003,6318,7146,9807,1,0,4497,8801,40.54,9110,8802,-85.03,9110,8805,1.000031,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7261,"NAD83(2011) / InGCS Bartholomew (m)",9001,6318,7147,9807,1,0,4499,8801,39,9110,8802,-85.51,9110,8805,1.000026,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7262,"NAD83(2011) / InGCS Bartholomew (ftUS)",9003,6318,7148,9807,1,0,4497,8801,39,9110,8802,-85.51,9110,8805,1.000026,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7263,"NAD83(2011) / InGCS Benton (m)",9001,6318,7149,9807,1,0,4499,8801,40.27,9110,8802,-87.18,9110,8805,1.000029,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7264,"NAD83(2011) / InGCS Benton (ftUS)",9003,6318,7150,9807,1,0,4497,8801,40.27,9110,8802,-87.18,9110,8805,1.000029,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7265,"NAD83(2011) / InGCS Blackford-Delaware (m)",9001,6318,7151,9807,1,0,4499,8801,40.03,9110,8802,-85.24,9110,8805,1.000038,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7266,"NAD83(2011) / InGCS Blackford-Delaware (ftUS)",9003,6318,7152,9807,1,0,4497,8801,40.03,9110,8802,-85.24,9110,8805,1.000038,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7267,"NAD83(2011) / InGCS Boone-Hendricks (m)",9001,6318,7153,9807,1,0,4499,8801,39.36,9110,8802,-86.3,9110,8805,1.000036,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7268,"NAD83(2011) / InGCS Boone-Hendricks (ftUS)",9003,6318,7154,9807,1,0,4497,8801,39.36,9110,8802,-86.3,9110,8805,1.000036,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7269,"NAD83(2011) / InGCS Brown (m)",9001,6318,7155,9807,1,0,4499,8801,39,9110,8802,-86.18,9110,8805,1.00003,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7270,"NAD83(2011) / InGCS Brown (ftUS)",9003,6318,7156,9807,1,0,4497,8801,39,9110,8802,-86.18,9110,8805,1.00003,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7271,"NAD83(2011) / InGCS Carroll (m)",9001,6318,7157,9807,1,0,4499,8801,40.24,9110,8802,-86.39,9110,8805,1.000026,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7272,"NAD83(2011) / InGCS Carroll (ftUS)",9003,6318,7158,9807,1,0,4497,8801,40.24,9110,8802,-86.39,9110,8805,1.000026,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7273,"NAD83(2011) / InGCS Cass (m)",9001,6318,7159,9807,1,0,4499,8801,40.33,9110,8802,-86.24,9110,8805,1.000028,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7274,"NAD83(2011) / InGCS Cass (ftUS)",9003,6318,7160,9807,1,0,4497,8801,40.33,9110,8802,-86.24,9110,8805,1.000028,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7275,"NAD83(2011) / InGCS Clark-Floyd-Scott (m)",9001,6318,7161,9807,1,0,4499,8801,38.09,9110,8802,-85.36,9110,8805,1.000021,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7276,"NAD83(2011) / InGCS Clark-Floyd-Scott (ftUS)",9003,6318,7162,9807,1,0,4497,8801,38.09,9110,8802,-85.36,9110,8805,1.000021,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7277,"NAD83(2011) / InGCS Clay (m)",9001,6318,7163,9807,1,0,4499,8801,39.09,9110,8802,-87.09,9110,8805,1.000024,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7278,"NAD83(2011) / InGCS Clay (ftUS)",9003,6318,7164,9807,1,0,4497,8801,39.09,9110,8802,-87.09,9110,8805,1.000024,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7279,"NAD83(2011) / InGCS Clinton (m)",9001,6318,7165,9807,1,0,4499,8801,40.09,9110,8802,-86.36,9110,8805,1.000032,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7280,"NAD83(2011) / InGCS Clinton (ftUS)",9003,6318,7166,9807,1,0,4497,8801,40.09,9110,8802,-86.36,9110,8805,1.000032,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7281,"NAD83(2011) / InGCS Crawford-Lawrence-Orange (m)",9001,6318,7167,9807,1,0,4499,8801,38.06,9110,8802,-86.3,9110,8805,1.000025,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7282,"NAD83(2011) / InGCS Crawford-Lawrence-Orange (ftUS)",9003,6318,7168,9807,1,0,4497,8801,38.06,9110,8802,-86.3,9110,8805,1.000025,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7283,"NAD83(2011) / InGCS Daviess-Greene (m)",9001,6318,7169,9807,1,0,4499,8801,38.27,9110,8802,-87.06,9110,8805,1.000018,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7284,"NAD83(2011) / InGCS Daviess-Greene (ftUS)",9003,6318,7170,9807,1,0,4497,8801,38.27,9110,8802,-87.06,9110,8805,1.000018,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7285,"NAD83(2011) / InGCS Dearborn-Ohio-Switzerland (m)",9001,6318,7171,9807,1,0,4499,8801,38.39,9110,8802,-84.54,9110,8805,1.000029,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7286,"NAD83(2011) / InGCS Dearborn-Ohio-Switzerland (ftUS)",9003,6318,7172,9807,1,0,4497,8801,38.39,9110,8802,-84.54,9110,8805,1.000029,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7287,"NAD83(2011) / InGCS Decatur-Rush (m)",9001,6318,7173,9807,1,0,4499,8801,39.06,9110,8802,-85.39,9110,8805,1.000036,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7288,"NAD83(2011) / InGCS Decatur-Rush (ftUS)",9003,6318,7174,9807,1,0,4497,8801,39.06,9110,8802,-85.39,9110,8805,1.000036,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7289,"NAD83(2011) / InGCS DeKalb (m)",9001,6318,7175,9807,1,0,4499,8801,41.15,9110,8802,-84.57,9110,8805,1.000036,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7290,"NAD83(2011) / InGCS DeKalb (ftUS)",9003,6318,7176,9807,1,0,4497,8801,41.15,9110,8802,-84.57,9110,8805,1.000036,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7291,"NAD83(2011) / InGCS Dubois-Martin (m)",9001,6318,7177,9807,1,0,4499,8801,38.12,9110,8802,-86.57,9110,8805,1.00002,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7292,"NAD83(2011) / InGCS Dubois-Martin (ftUS)",9003,6318,7178,9807,1,0,4497,8801,38.12,9110,8802,-86.57,9110,8805,1.00002,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7293,"NAD83(2011) / InGCS Elkhart-Kosciusko-Wabash (m)",9001,6318,7179,9807,1,0,4499,8801,40.39,9110,8802,-85.51,9110,8805,1.000033,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7294,"NAD83(2011) / InGCS Elkhart-Kosciusko-Wabash (ftUS)",9003,6318,7180,9807,1,0,4497,8801,40.39,9110,8802,-85.51,9110,8805,1.000033,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7295,"NAD83(2011) / InGCS Fayette-Franklin-Union (m)",9001,6318,7181,9807,1,0,4499,8801,39.15,9110,8802,-85.03,9110,8805,1.000038,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7296,"NAD83(2011) / InGCS Fayette-Franklin-Union (ftUS)",9003,6318,7182,9807,1,0,4497,8801,39.15,9110,8802,-85.03,9110,8805,1.000038,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7297,"NAD83(2011) / InGCS Fountain-Warren (m)",9001,6318,7183,9807,1,0,4499,8801,39.57,9110,8802,-87.18,9110,8805,1.000025,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7298,"NAD83(2011) / InGCS Fountain-Warren (ftUS)",9003,6318,7184,9807,1,0,4497,8801,39.57,9110,8802,-87.18,9110,8805,1.000025,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7299,"NAD83(2011) / InGCS Fulton-Marshall-St. Joseph (m)",9001,6318,7185,9807,1,0,4499,8801,40.54,9110,8802,-86.18,9110,8805,1.000031,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7300,"NAD83(2011) / InGCS Fulton-Marshall-St. Joseph (ftUS)",9003,6318,7186,9807,1,0,4497,8801,40.54,9110,8802,-86.18,9110,8805,1.000031,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7301,"NAD83(2011) / InGCS Gibson (m)",9001,6318,7187,9807,1,0,4499,8801,38.09,9110,8802,-87.39,9110,8805,1.000013,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7302,"NAD83(2011) / InGCS Gibson (ftUS)",9003,6318,7188,9807,1,0,4497,8801,38.09,9110,8802,-87.39,9110,8805,1.000013,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7303,"NAD83(2011) / InGCS Grant (m)",9001,6318,7189,9807,1,0,4499,8801,40.21,9110,8802,-85.42,9110,8805,1.000034,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7304,"NAD83(2011) / InGCS Grant (ftUS)",9003,6318,7190,9807,1,0,4497,8801,40.21,9110,8802,-85.42,9110,8805,1.000034,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7305,"NAD83(2011) / InGCS Hamilton-Tipton (m)",9001,6318,7191,9807,1,0,4499,8801,39.54,9110,8802,-86,9110,8805,1.000034,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7306,"NAD83(2011) / InGCS Hamilton-Tipton (ftUS)",9003,6318,7192,9807,1,0,4497,8801,39.54,9110,8802,-86,9110,8805,1.000034,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7307,"NAD83(2011) / InGCS Hancock-Madison (m)",9001,6318,7193,9807,1,0,4499,8801,39.39,9110,8802,-85.48,9110,8805,1.000036,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7308,"NAD83(2011) / InGCS Hancock-Madison (ftUS)",9003,6318,7194,9807,1,0,4497,8801,39.39,9110,8802,-85.48,9110,8805,1.000036,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7309,"NAD83(2011) / InGCS Harrison-Washington (m)",9001,6318,7195,9807,1,0,4499,8801,37.57,9110,8802,-86.09,9110,8805,1.000027,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7310,"NAD83(2011) / InGCS Harrison-Washington (ftUS)",9003,6318,7196,9807,1,0,4497,8801,37.57,9110,8802,-86.09,9110,8805,1.000027,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7311,"NAD83(2011) / InGCS Henry (m)",9001,6318,7197,9807,1,0,4499,8801,39.45,9110,8802,-85.27,9110,8805,1.000043,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7312,"NAD83(2011) / InGCS Henry (ftUS)",9003,6318,7198,9807,1,0,4497,8801,39.45,9110,8802,-85.27,9110,8805,1.000043,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7313,"NAD83(2011) / InGCS Howard-Miami (m)",9001,6318,7199,9807,1,0,4499,8801,40.21,9110,8802,-86.09,9110,8805,1.000031,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7314,"NAD83(2011) / InGCS Howard-Miami (ftUS)",9003,6318,7200,9807,1,0,4497,8801,40.21,9110,8802,-86.09,9110,8805,1.000031,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7315,"NAD83(2011) / InGCS Huntington-Whitley (m)",9001,6318,7201,9807,1,0,4499,8801,40.39,9110,8802,-85.3,9110,8805,1.000034,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7316,"NAD83(2011) / InGCS Huntington-Whitley (ftUS)",9003,6318,7202,9807,1,0,4497,8801,40.39,9110,8802,-85.3,9110,8805,1.000034,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7317,"NAD83(2011) / InGCS Jackson (m)",9001,6318,7203,9807,1,0,4499,8801,38.42,9110,8802,-85.57,9110,8805,1.000022,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7318,"NAD83(2011) / InGCS Jackson (ftUS)",9003,6318,7204,9807,1,0,4497,8801,38.42,9110,8802,-85.57,9110,8805,1.000022,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7319,"NAD83(2011) / InGCS Jasper-Porter (m)",9001,6318,7205,9807,1,0,4499,8801,40.42,9110,8802,-87.06,9110,8805,1.000027,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7320,"NAD83(2011) / InGCS Jasper-Porter (ftUS)",9003,6318,7206,9807,1,0,4497,8801,40.42,9110,8802,-87.06,9110,8805,1.000027,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7321,"NAD83(2011) / InGCS Jay (m)",9001,6318,7207,9807,1,0,4499,8801,40.18,9110,8802,-85,9110,8805,1.000038,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7322,"NAD83(2011) / InGCS Jay (ftUS)",9003,6318,7208,9807,1,0,4497,8801,40.18,9110,8802,-85,9110,8805,1.000038,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7323,"NAD83(2011) / InGCS Jefferson (m)",9001,6318,7209,9807,1,0,4499,8801,38.33,9110,8802,-85.21,9110,8805,1.000028,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7324,"NAD83(2011) / InGCS Jefferson (ftUS)",9003,6318,7210,9807,1,0,4497,8801,38.33,9110,8802,-85.21,9110,8805,1.000028,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7325,"NAD83(2011) / InGCS Jennings (m)",9001,6318,7211,9807,1,0,4499,8801,38.48,9110,8802,-85.48,9110,8805,1.000025,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7326,"NAD83(2011) / InGCS Jennings (ftUS)",9003,6318,7212,9807,1,0,4497,8801,38.48,9110,8802,-85.48,9110,8805,1.000025,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7327,"NAD83(2011) / InGCS Johnson-Marion (m)",9001,6318,7213,9807,1,0,4499,8801,39.18,9110,8802,-86.09,9110,8805,1.000031,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7328,"NAD83(2011) / InGCS Johnson-Marion (ftUS)",9003,6318,7214,9807,1,0,4497,8801,39.18,9110,8802,-86.09,9110,8805,1.000031,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7329,"NAD83(2011) / InGCS Knox (m)",9001,6318,7215,9807,1,0,4499,8801,38.24,9110,8802,-87.27,9110,8805,1.000015,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7330,"NAD83(2011) / InGCS Knox (ftUS)",9003,6318,7216,9807,1,0,4497,8801,38.24,9110,8802,-87.27,9110,8805,1.000015,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7331,"NAD83(2011) / InGCS LaGrange-Noble (m)",9001,6318,7217,9807,1,0,4499,8801,41.15,9110,8802,-85.27,9110,8805,1.000037,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7332,"NAD83(2011) / InGCS LaGrange-Noble (ftUS)",9003,6318,7218,9807,1,0,4497,8801,41.15,9110,8802,-85.27,9110,8805,1.000037,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7333,"NAD83(2011) / InGCS Lake-Newton (m)",9001,6318,7219,9807,1,0,4499,8801,40.42,9110,8802,-87.24,9110,8805,1.000026,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7334,"NAD83(2011) / InGCS Lake-Newton (ftUS)",9003,6318,7220,9807,1,0,4497,8801,40.42,9110,8802,-87.24,9110,8805,1.000026,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7335,"NAD83(2011) / InGCS LaPorte-Pulaski-Starke (m)",9001,6318,7221,9807,1,0,4499,8801,40.54,9110,8802,-86.45,9110,8805,1.000027,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7336,"NAD83(2011) / InGCS LaPorte-Pulaski-Starke (ftUS)",9003,6318,7222,9807,1,0,4497,8801,40.54,9110,8802,-86.45,9110,8805,1.000027,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7337,"NAD83(2011) / InGCS Monroe-Morgan (m)",9001,6318,7223,9807,1,0,4499,8801,38.57,9110,8802,-86.3,9110,8805,1.000028,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7338,"NAD83(2011) / InGCS Monroe-Morgan (ftUS)",9003,6318,7224,9807,1,0,4497,8801,38.57,9110,8802,-86.3,9110,8805,1.000028,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7339,"NAD83(2011) / InGCS Montgomery-Putnam (m)",9001,6318,7225,9807,1,0,4499,8801,39.27,9110,8802,-86.57,9110,8805,1.000031,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7340,"NAD83(2011) / InGCS Montgomery-Putnam (ftUS)",9003,6318,7226,9807,1,0,4497,8801,39.27,9110,8802,-86.57,9110,8805,1.000031,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7341,"NAD83(2011) / InGCS Owen (m)",9001,6318,7227,9807,1,0,4499,8801,39.09,9110,8802,-86.54,9110,8805,1.000026,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7342,"NAD83(2011) / InGCS Owen (ftUS)",9003,6318,7228,9807,1,0,4497,8801,39.09,9110,8802,-86.54,9110,8805,1.000026,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7343,"NAD83(2011) / InGCS Parke-Vermillion (m)",9001,6318,7229,9807,1,0,4499,8801,39.36,9110,8802,-87.21,9110,8805,1.000022,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7344,"NAD83(2011) / InGCS Parke-Vermillion (ftUS)",9003,6318,7230,9807,1,0,4497,8801,39.36,9110,8802,-87.21,9110,8805,1.000022,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7345,"NAD83(2011) / InGCS Perry (m)",9001,6318,7231,9807,1,0,4499,8801,37.48,9110,8802,-86.42,9110,8805,1.00002,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7346,"NAD83(2011) / InGCS Perry (ftUS)",9003,6318,7232,9807,1,0,4497,8801,37.48,9110,8802,-86.42,9110,8805,1.00002,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7347,"NAD83(2011) / InGCS Pike-Warrick (m)",9001,6318,7233,9807,1,0,4499,8801,37.51,9110,8802,-87.18,9110,8805,1.000015,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7348,"NAD83(2011) / InGCS Pike-Warrick (ftUS)",9003,6318,7234,9807,1,0,4497,8801,37.51,9110,8802,-87.18,9110,8805,1.000015,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7349,"NAD83(2011) / InGCS Posey (m)",9001,6318,7235,9807,1,0,4499,8801,37.45,9110,8802,-87.57,9110,8805,1.000013,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7350,"NAD83(2011) / InGCS Posey (ftUS)",9003,6318,7236,9807,1,0,4497,8801,37.45,9110,8802,-87.57,9110,8805,1.000013,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7351,"NAD83(2011) / InGCS Randolph-Wayne (m)",9001,6318,7237,9807,1,0,4499,8801,39.42,9110,8802,-85.03,9110,8805,1.000044,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7352,"NAD83(2011) / InGCS Randolph-Wayne (ftUS)",9003,6318,7238,9807,1,0,4497,8801,39.42,9110,8802,-85.03,9110,8805,1.000044,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7353,"NAD83(2011) / InGCS Ripley (m)",9001,6318,7239,9807,1,0,4499,8801,38.54,9110,8802,-85.18,9110,8805,1.000038,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7354,"NAD83(2011) / InGCS Ripley (ftUS)",9003,6318,7240,9807,1,0,4497,8801,38.54,9110,8802,-85.18,9110,8805,1.000038,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7355,"NAD83(2011) / InGCS Shelby (m)",9001,6318,7241,9807,1,0,4499,8801,39.18,9110,8802,-85.54,9110,8805,1.00003,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7356,"NAD83(2011) / InGCS Shelby (ftUS)",9003,6318,7242,9807,1,0,4497,8801,39.18,9110,8802,-85.54,9110,8805,1.00003,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7357,"NAD83(2011) / InGCS Spencer (m)",9001,6318,7243,9807,1,0,4499,8801,37.45,9110,8802,-87.03,9110,8805,1.000014,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7358,"NAD83(2011) / InGCS Spencer (ftUS)",9003,6318,7244,9807,1,0,4497,8801,37.45,9110,8802,-87.03,9110,8805,1.000014,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7359,"NAD83(2011) / InGCS Steuben (m)",9001,6318,7245,9807,1,0,4499,8801,41.3,9110,8802,-85,9110,8805,1.000041,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7360,"NAD83(2011) / InGCS Steuben (ftUS)",9003,6318,7246,9807,1,0,4497,8801,41.3,9110,8802,-85,9110,8805,1.000041,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7361,"NAD83(2011) / InGCS Sullivan (m)",9001,6318,7247,9807,1,0,4499,8801,38.54,9110,8802,-87.3,9110,8805,1.000017,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7362,"NAD83(2011) / InGCS Sullivan (ftUS)",9003,6318,7248,9807,1,0,4497,8801,38.54,9110,8802,-87.3,9110,8805,1.000017,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7363,"NAD83(2011) / InGCS Tippecanoe-White (m)",9001,6318,7249,9807,1,0,4499,8801,40.12,9110,8802,-86.54,9110,8805,1.000026,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7364,"NAD83(2011) / InGCS Tippecanoe-White (ftUS)",9003,6318,7250,9807,1,0,4497,8801,40.12,9110,8802,-86.54,9110,8805,1.000026,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7365,"NAD83(2011) / InGCS Vanderburgh (m)",9001,6318,7251,9807,1,0,4499,8801,37.48,9110,8802,-87.33,9110,8805,1.000015,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7366,"NAD83(2011) / InGCS Vanderburgh (ftUS)",9003,6318,7252,9807,1,0,4497,8801,37.48,9110,8802,-87.33,9110,8805,1.000015,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7367,"NAD83(2011) / InGCS Vigo (m)",9001,6318,7253,9807,1,0,4499,8801,39.15,9110,8802,-87.27,9110,8805,1.00002,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7368,"NAD83(2011) / InGCS Vigo (ftUS)",9003,6318,7254,9807,1,0,4497,8801,39.15,9110,8802,-87.27,9110,8805,1.00002,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7369,"NAD83(2011) / InGCS Wells (m)",9001,6318,7255,9807,1,0,4499,8801,40.33,9110,8802,-85.15,9110,8805,1.000034,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7370,"NAD83(2011) / InGCS Wells (ftUS)",9003,6318,7256,9807,1,0,4497,8801,40.33,9110,8802,-85.15,9110,8805,1.000034,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7374,"ONGD14 / UTM zone 39N",9001,7373,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+7375,"ONGD14 / UTM zone 40N",9001,7373,16040,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+7376,"ONGD14 / UTM zone 41N",9001,7373,16041,9807,1,0,4400,8801,0,9102,8802,63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+7528,"NAD83(2011) / WISCRS Adams and Juneau (m)",9001,6318,7484,9807,1,0,4499,8801,43.22,9110,8802,-90,9110,8805,1.0000365285,9201,8806,147218.6942,9001,8807,0.0037,9001,,,,,,
+7529,"NAD83(2011) / WISCRS Ashland (m)",9001,6318,7378,9807,1,0,4499,8801,45.4222,9110,8802,-90.372,9110,8805,1.0000495683,9201,8806,172821.9461,9001,8807,0.0017,9001,,,,,,
+7530,"NAD83(2011) / WISCRS Barron (m)",9001,6318,7426,9807,1,0,4499,8801,45.08,9110,8802,-91.51,9110,8805,1.0000486665,9201,8806,93150,9001,8807,0.0029,9001,,,,,,
+7531,"NAD83(2011) / WISCRS Bayfield (m)",9001,6318,7380,9801,1,0,4499,8801,46.4010734158,9110,8802,-91.091,9110,8805,1.0000331195,9201,8806,228600.4575,9001,8807,148551.4837,9001,,,,,,
+7532,"NAD83(2011) / WISCRS Brown (m)",9001,6318,7428,9807,1,0,4499,8801,43,9102,8802,-88,9102,8805,1.00002,9201,8806,31600,9001,8807,4600,9001,,,,,,
+7533,"NAD83(2011) / WISCRS Buffalo (m)",9001,6318,7430,9807,1,0,4499,8801,43.2853,9110,8802,-91.475,9110,8805,1.0000382778,9201,8806,175260.3502,9001,8807,0.0048,9001,,,,,,
+7534,"NAD83(2011) / WISCRS Burnett (m)",9001,6318,7382,9801,1,0,4499,8801,45.5355373517,9110,8802,-92.2728,9110,8805,1.0000383841,9201,8806,64008.1276,9001,8807,59445.9043,9001,,,,,,
+7535,"NAD83(2011) / WISCRS Calumet, Fond du Lac, Outagamie and Winnebago (m)",9001,6318,7486,9807,1,0,4499,8801,42.431,9110,8802,-88.3,9110,8805,1.0000286569,9201,8806,244754.8893,9001,8807,0.0049,9001,,,,,,
+7536,"NAD83(2011) / WISCRS Chippewa (m)",9001,6318,7432,9801,1,0,4499,8801,44.5840284835,9110,8802,-91.174,9110,8805,1.0000391127,9201,8806,60045.72,9001,8807,44091.4346,9001,,,,,,
+7537,"NAD83(2011) / WISCRS Clark (m)",9001,6318,7434,9807,1,0,4499,8801,43.36,9110,8802,-90.423,9110,8805,1.0000463003,9201,8806,199949.1989,9001,8807,0.0086,9001,,,,,,
+7538,"NAD83(2011) / WISCRS Columbia (m)",9001,6318,7488,9801,1,0,4499,8801,43.2745167925,9110,8802,-89.234,9110,8805,1.00003498,9201,8806,169164.3381,9001,8807,111569.6134,9001,,,,,,
+7539,"NAD83(2011) / WISCRS Crawford (m)",9001,6318,7490,9801,1,0,4499,8801,43.1200200178,9110,8802,-90.562,9110,8805,1.0000349151,9201,8806,113690.6274,9001,8807,53703.1201,9001,,,,,,
+7540,"NAD83(2011) / WISCRS Dane (m)",9001,6318,7492,9801,1,0,4499,8801,43.0410257735,9110,8802,-89.252,9110,8805,1.0000384786,9201,8806,247193.2944,9001,8807,146591.9896,9001,,,,,,
+7541,"NAD83(2011) / WISCRS Dodge and Jefferson (m)",9001,6318,7494,9807,1,0,4499,8801,41.282,9110,8802,-88.463,9110,8805,1.0000346418,9201,8806,263347.7263,9001,8807,0.0076,9001,,,,,,
+7542,"NAD83(2011) / WISCRS Door (m)",9001,6318,7436,9807,1,0,4499,8801,44.24,9110,8802,-87.162,9110,8805,1.0000187521,9201,8806,158801.1176,9001,8807,0.0023,9001,,,,,,
+7543,"NAD83(2011) / WISCRS Douglas (m)",9001,6318,7384,9807,1,0,4499,8801,45.53,9110,8802,-91.55,9110,8805,1.0000385418,9201,8806,59131.3183,9001,8807,0.0041,9001,,,,,,
+7544,"NAD83(2011) / WISCRS Dunn (m)",9001,6318,7438,9807,1,0,4499,8801,44.243,9110,8802,-91.534,9110,8805,1.0000410324,9201,8806,51816.104,9001,8807,0.003,9001,,,,,,
+7545,"NAD83(2011) / WISCRS Eau Claire (m)",9001,6318,7440,9801,1,0,4499,8801,44.5220212055,9110,8802,-91.172,9110,8805,1.000035079,9201,8806,120091.4402,9001,8807,91687.9239,9001,,,,,,
+7546,"NAD83(2011) / WISCRS Florence (m)",9001,6318,7386,9807,1,0,4499,8801,45.262,9110,8802,-88.083,9110,8805,1.0000552095,9201,8806,133502.6683,9001,8807,0.0063,9001,,,,,,
+7547,"NAD83(2011) / WISCRS Forest (m)",9001,6318,7388,9807,1,0,4499,8801,44.002,9110,8802,-88.38,9110,8805,1.0000673004,9201,8806,275844.5533,9001,8807,0.0157,9001,,,,,,
+7548,"NAD83(2011) / WISCRS Grant (m)",9001,6318,7496,9807,1,0,4499,8801,41.244,9110,8802,-90.48,9110,8805,1.0000349452,9201,8806,242316.4841,9001,8807,0.01,9001,,,,,,
+7549,"NAD83(2011) / WISCRS Green and Lafayette (m)",9001,6318,7498,9801,1,0,4499,8801,42.3815224197,9110,8802,-89.502,9110,8805,1.0000390487,9201,8806,170078.7403,9001,8807,45830.2947,9001,,,,,,
+7550,"NAD83(2011) / WISCRS Green Lake and Marquette (m)",9001,6318,7500,9801,1,0,4499,8801,43.4825200424,9110,8802,-89.143,9110,8805,1.0000344057,9201,8806,150876.3018,9001,8807,79170.7795,9001,,,,,,
+7551,"NAD83(2011) / WISCRS Iowa (m)",9001,6318,7502,9807,1,0,4499,8801,42.322,9110,8802,-90.094,9110,8805,1.0000394961,9201,8806,113081.0261,9001,8807,0.0045,9001,,,,,,
+7552,"NAD83(2011) / WISCRS Iron (m)",9001,6318,7390,9807,1,0,4499,8801,45.26,9110,8802,-90.152,9110,8805,1.0000677153,9201,8806,220980.4419,9001,8807,0.0085,9001,,,,,,
+7553,"NAD83(2011) / WISCRS Jackson (m)",9001,6318,7450,9807,1,0,4499,8801,44.151200646,9110,8802,-90.503946747,9110,8805,1.0000353,9201,8806,27000,9001,8807,25000,9001,,,,,,
+7554,"NAD83(2011) / WISCRS Kenosha, Milwaukee, Ozaukee and Racine (m)",9001,6318,7504,9807,1,0,4499,8801,42.13,9110,8802,-87.534,9110,8805,1.0000260649,9201,8806,185928.3728,9001,8807,0.0009,9001,,,,,,
+7555,"NAD83(2011) / WISCRS Kewaunee, Manitowoc and Sheboygan (m)",9001,6318,7506,9807,1,0,4499,8801,43.16,9110,8802,-87.33,9110,8805,1.0000233704,9201,8806,79857.7614,9001,8807,0.0012,9001,,,,,,
+7556,"NAD83(2011) / WISCRS La Crosse (m)",9001,6318,7508,9807,1,0,4499,8801,43.2704,9110,8802,-91.19,9110,8805,1.0000319985,9201,8806,130454.6598,9001,8807,0.0033,9001,,,,,,
+7557,"NAD83(2011) / WISCRS Langlade (m)",9001,6318,7452,9801,1,0,4499,8801,45.0915253579,9110,8802,-89.02,9110,8805,1.0000627024,9201,8806,198425.197,9001,8807,105279.7829,9001,,,,,,
+7558,"NAD83(2011) / WISCRS Lincoln (m)",9001,6318,7454,9807,1,0,4499,8801,44.504,9110,8802,-89.44,9110,8805,1.0000599003,9201,8806,116129.0323,9001,8807,0.0058,9001,,,,,,
+7559,"NAD83(2011) / WISCRS Marathon (m)",9001,6318,7456,9801,1,0,4499,8801,44.5403255925,9110,8802,-89.4612,9110,8805,1.000053289,9201,8806,74676.1493,9001,8807,55049.2669,9001,,,,,,
+7560,"NAD83(2011) / WISCRS Marinette (m)",9001,6318,7458,9807,1,0,4499,8801,44.413,9110,8802,-87.424,9110,8805,1.0000234982,9201,8806,238658.8794,9001,8807,0.0032,9001,,,,,,
+7561,"NAD83(2011) / WISCRS Menominee (m)",9001,6318,7460,9807,1,0,4499,8801,44.43,9110,8802,-88.25,9110,8805,1.0000362499,9201,8806,105461.0121,9001,8807,0.0029,9001,,,,,,
+7562,"NAD83(2011) / WISCRS Monroe (m)",9001,6318,7510,9801,1,0,4499,8801,44.0000266143,9110,8802,-90.383,9110,8805,1.0000434122,9201,8806,204521.209,9001,8807,121923.9861,9001,,,,,,
+7563,"NAD83(2011) / WISCRS Oconto (m)",9001,6318,7462,9807,1,0,4499,8801,44.235,9110,8802,-87.543,9110,8805,1.0000236869,9201,8806,182880.3676,9001,8807,0.0033,9001,,,,,,
+7564,"NAD83(2011) / WISCRS Oneida (m)",9001,6318,7392,9801,1,0,4499,8801,45.4215205573,9110,8802,-89.324,9110,8805,1.0000686968,9201,8806,70104.1401,9001,8807,57588.0346,9001,,,,,,
+7565,"NAD83(2011) / WISCRS Pepin and Pierce (m)",9001,6318,7464,9801,1,0,4499,8801,44.3810135939,9110,8802,-92.134,9110,8805,1.0000362977,9201,8806,167640.3354,9001,8807,86033.0876,9001,,,,,,
+7566,"NAD83(2011) / WISCRS Polk (m)",9001,6318,7466,9807,1,0,4499,8801,44.394,9110,8802,-92.38,9110,8805,1.0000433849,9201,8806,141732.2823,9001,8807,0.0059,9001,,,,,,
+7567,"NAD83(2011) / WISCRS Portage (m)",9001,6318,7468,9801,1,0,4499,8801,44.2500566311,9110,8802,-89.3,9110,8805,1.000039936,9201,8806,56388.1128,9001,8807,50022.1874,9001,,,,,,
+7568,"NAD83(2011) / WISCRS Price (m)",9001,6318,7394,9807,1,0,4499,8801,44.332,9110,8802,-90.292,9110,8805,1.0000649554,9201,8806,227990.8546,9001,8807,0.0109,9001,,,,,,
+7569,"NAD83(2011) / WISCRS Richland (m)",9001,6318,7512,9801,1,0,4499,8801,43.1920326539,9110,8802,-90.255,9110,8805,1.0000375653,9201,8806,202387.6048,9001,8807,134255.4253,9001,,,,,,
+7570,"NAD83(2011) / WISCRS Rock (m)",9001,6318,7514,9807,1,0,4499,8801,41.564,9110,8802,-89.042,9110,8805,1.0000337311,9201,8806,146304.2926,9001,8807,0.0068,9001,,,,,,
+7571,"NAD83(2011) / WISCRS Rusk (m)",9001,6318,7470,9807,1,0,4499,8801,43.551,9110,8802,-91.04,9110,8805,1.0000495976,9201,8806,250546.1013,9001,8807,0.0234,9001,,,,,,
+7572,"NAD83(2011) / WISCRS Sauk (m)",9001,6318,7516,9807,1,0,4499,8801,42.491,9110,8802,-89.54,9110,8805,1.0000373868,9201,8806,185623.5716,9001,8807,0.0051,9001,,,,,,
+7573,"NAD83(2011) / WISCRS Sawyer (m)",9001,6318,7396,9801,1,0,4499,8801,45.5400356873,9110,8802,-91.07,9110,8805,1.0000573461,9201,8806,216713.2336,9001,8807,120734.1631,9001,,,,,,
+7574,"NAD83(2011) / WISCRS Shawano (m)",9001,6318,7472,9807,1,0,4499,8801,44.021,9110,8802,-88.362,9110,8805,1.000032144,9201,8806,262433.3253,9001,8807,0.0096,9001,,,,,,
+7575,"NAD83(2011) / WISCRS St. Croix (m)",9001,6318,7474,9807,1,0,4499,8801,44.021,9110,8802,-92.38,9110,8805,1.0000381803,9201,8806,165506.7302,9001,8807,0.0103,9001,,,,,,
+7576,"NAD83(2011) / WISCRS Taylor (m)",9001,6318,7476,9801,1,0,4499,8801,45.1040159509,9110,8802,-90.29,9110,8805,1.0000597566,9201,8806,187147.5744,9001,8807,107746.7522,9001,,,,,,
+7577,"NAD83(2011) / WISCRS Trempealeau (m)",9001,6318,7478,9807,1,0,4499,8801,43.094,9110,8802,-91.22,9110,8805,1.0000361538,9201,8806,256946.9138,9001,8807,0.0041,9001,,,,,,
+7578,"NAD83(2011) / WISCRS Vernon (m)",9001,6318,7518,9801,1,0,4499,8801,43.3430118583,9110,8802,-90.47,9110,8805,1.0000408158,9201,8806,222504.4451,9001,8807,47532.0602,9001,,,,,,
+7579,"NAD83(2011) / WISCRS Vilas (m)",9001,6318,7398,9801,1,0,4499,8801,46.0440238726,9110,8802,-89.292,9110,8805,1.0000730142,9201,8806,134417.0689,9001,8807,50337.1092,9001,,,,,,
+7580,"NAD83(2011) / WISCRS Walworth (m)",9001,6318,7520,9801,1,0,4499,8801,42.4010063549,9110,8802,-88.323,9110,8805,1.0000367192,9201,8806,232562.8651,9001,8807,111088.2224,9001,,,,,,
+7581,"NAD83(2011) / WISCRS Washburn (m)",9001,6318,7424,9801,1,0,4499,8801,45.57403914,9110,8802,-91.47,9110,8805,1.0000475376,9201,8806,234086.8682,9001,8807,188358.6058,9001,,,,,,
+7582,"NAD83(2011) / WISCRS Washington (m)",9001,6318,7522,9807,1,0,4499,8801,42.5505,9110,8802,-88.035,9110,8805,1.00003738,9201,8806,120091.4415,9001,8807,0.003,9001,,,,,,
+7583,"NAD83(2011) / WISCRS Waukesha (m)",9001,6318,7524,9807,1,0,4499,8801,42.341,9110,8802,-88.133,9110,8805,1.0000346179,9201,8806,208788.418,9001,8807,0.0034,9001,,,,,,
+7584,"NAD83(2011) / WISCRS Waupaca (m)",9001,6318,7480,9807,1,0,4499,8801,43.2513,9110,8802,-88.49,9110,8805,1.0000333645,9201,8806,185013.9709,9001,8807,0.007,9001,,,,,,
+7585,"NAD83(2011) / WISCRS Waushara (m)",9001,6318,7526,9801,1,0,4499,8801,44.0650198565,9110,8802,-89.143,9110,8805,1.0000392096,9201,8806,120091.4402,9001,8807,45069.7587,9001,,,,,,
+7586,"NAD83(2011) / WISCRS Wood (m)",9001,6318,7482,9801,1,0,4499,8801,44.214534369,9110,8802,-90,9110,8805,1.0000421209,9201,8806,208483.6173,9001,8807,134589.754,9001,,,,,,
+7587,"NAD83(2011) / WISCRS Adams and Juneau (ftUS)",9003,6318,7485,9807,1,0,4497,8801,43.22,9110,8802,-90,9110,8805,1.0000365285,9201,8806,482999.999,9003,8807,0.012,9003,,,,,,
+7588,"NAD83(2011) / WISCRS Ashland (ftUS)",9003,6318,7379,9807,1,0,4497,8801,45.4222,9110,8802,-90.372,9110,8805,1.0000495683,9201,8806,567000.001,9003,8807,0.006,9003,,,,,,
+7589,"NAD83(2011) / WISCRS Barron (ftUS)",9003,6318,7427,9807,1,0,4497,8801,45.08,9110,8802,-91.51,9110,8805,1.0000486665,9201,8806,305609.625,9003,8807,0.01,9003,,,,,,
+7590,"NAD83(2011) / WISCRS Bayfield (ftUS)",9003,6318,7381,9801,1,0,4497,8801,46.4010734158,9110,8802,-91.091,9110,8805,1.0000331195,9201,8806,750000.001,9003,8807,487372.659,9003,,,,,,
+7591,"NAD83(2011) / WISCRS Brown (ftUS)",9003,6318,7429,9807,1,0,4497,8801,43,9110,8802,-88,9110,8805,1.00002,9201,8806,103674.333,9003,8807,15091.833,9003,,,,,,
+7592,"NAD83(2011) / WISCRS Buffalo (ftUS)",9003,6318,7431,9807,1,0,4497,8801,43.2853,9110,8802,-91.475,9110,8805,1.0000382778,9201,8806,574999.999,9003,8807,0.016,9003,,,,,,
+7593,"NAD83(2011) / WISCRS Burnett (ftUS)",9003,6318,7383,9801,1,0,4497,8801,45.5355373517,9110,8802,-92.2728,9110,8805,1.0000383841,9201,8806,209999.999,9003,8807,195032.104,9003,,,,,,
+7594,"NAD83(2011) / WISCRS Calumet, Fond du Lac, Outagamie and Winnebago (ftUS)",9003,6318,7487,9807,1,0,4497,8801,42.431,9110,8802,-88.3,9110,8805,1.0000286569,9201,8806,802999.999,9003,8807,0.016,9003,,,,,,
+7595,"NAD83(2011) / WISCRS Chippewa (ftUS)",9003,6318,7433,9801,1,0,4497,8801,44.5840284835,9110,8802,-91.174,9110,8805,1.0000391127,9201,8806,197000,9003,8807,144656.648,9003,,,,,,
+7596,"NAD83(2011) / WISCRS Clark (ftUS)",9003,6318,7435,9807,1,0,4497,8801,43.36,9110,8802,-90.423,9110,8805,1.0000463003,9201,8806,655999.997,9003,8807,0.028,9003,,,,,,
+7597,"NAD83(2011) / WISCRS Columbia (ftUS)",9003,6318,7489,9801,1,0,4497,8801,43.2745167925,9110,8802,-89.234,9110,8805,1.00003498,9201,8806,554999.999,9003,8807,366041.307,9003,,,,,,
+7598,"NAD83(2011) / WISCRS Crawford (ftUS)",9003,6318,7491,9801,1,0,4497,8801,43.1200200178,9110,8802,-90.562,9110,8805,1.0000349151,9201,8806,373000,9003,8807,176190.987,9003,,,,,,
+7599,"NAD83(2011) / WISCRS Dane (ftUS)",9003,6318,7493,9801,1,0,4497,8801,43.0410257735,9110,8802,-89.252,9110,8805,1.0000384786,9201,8806,811000,9003,8807,480943.886,9003,,,,,,
+7600,"NAD83(2011) / WISCRS Dodge and Jefferson (ftUS)",9003,6318,7495,9807,1,0,4497,8801,41.282,9110,8802,-88.463,9110,8805,1.0000346418,9201,8806,863999.999,9003,8807,0.025,9003,,,,,,
+7601,"NAD83(2011) / WISCRS Door (ftUS)",9003,6318,7437,9807,1,0,4497,8801,44.24,9110,8802,-87.162,9110,8805,1.0000187521,9201,8806,521000,9003,8807,0.008,9003,,,,,,
+7602,"NAD83(2011) / WISCRS Douglas (ftUS)",9003,6318,7385,9807,1,0,4497,8801,45.53,9110,8802,-91.55,9110,8805,1.0000385418,9201,8806,194000,9003,8807,0.013,9003,,,,,,
+7603,"NAD83(2011) / WISCRS Dunn (ftUS)",9003,6318,7439,9807,1,0,4497,8801,44.243,9110,8802,-91.534,9110,8805,1.0000410324,9201,8806,170000.001,9003,8807,0.01,9003,,,,,,
+7604,"NAD83(2011) / WISCRS Eau Claire (ftUS)",9003,6318,7441,9801,1,0,4497,8801,44.5220212055,9110,8802,-91.172,9110,8805,1.000035079,9201,8806,394000,9003,8807,300812.797,9003,,,,,,
+7605,"NAD83(2011) / WISCRS Florence (ftUS)",9003,6318,7387,9807,1,0,4497,8801,45.262,9110,8802,-88.083,9110,8805,1.0000552095,9201,8806,438000.004,9003,8807,0.021,9003,,,,,,
+7606,"NAD83(2011) / WISCRS Forest (ftUS)",9003,6318,7389,9807,1,0,4497,8801,44.002,9110,8802,-88.38,9110,8805,1.0000673004,9201,8806,905000.005,9003,8807,0.052,9003,,,,,,
+7607,"NAD83(2011) / WISCRS Grant (ftUS)",9003,6318,7497,9807,1,0,4497,8801,41.244,9110,8802,-90.48,9110,8805,1.0000349452,9201,8806,794999.998,9003,8807,0.033,9003,,,,,,
+7608,"NAD83(2011) / WISCRS Green and Lafayette (ftUS)",9003,6318,7499,9801,1,0,4497,8801,42.3815224197,9110,8802,-89.502,9110,8805,1.0000390487,9201,8806,558000,9003,8807,150361.559,9003,,,,,,
+7609,"NAD83(2011) / WISCRS Green Lake and Marquette (ftUS)",9003,6318,7501,9801,1,0,4497,8801,43.4825200424,9110,8802,-89.143,9110,8805,1.0000344057,9201,8806,495000,9003,8807,259746.132,9003,,,,,,
+7610,"NAD83(2011) / WISCRS Iowa (ftUS)",9003,6318,7503,9807,1,0,4497,8801,42.322,9110,8802,-90.094,9110,8805,1.0000394961,9201,8806,371000,9003,8807,0.015,9003,,,,,,
+7611,"NAD83(2011) / WISCRS Iron (ftUS)",9003,6318,7391,9807,1,0,4497,8801,45.26,9110,8802,-90.152,9110,8805,1.0000677153,9201,8806,725000,9003,8807,0.028,9003,,,,,,
+7612,"NAD83(2011) / WISCRS Jackson (ftUS)",9003,6318,7451,9807,1,0,4497,8801,44.151200646,9110,8802,-90.503946747,9110,8805,1.0000353,9201,8806,88582.5,9003,8807,82020.833,9003,,,,,,
+7613,"NAD83(2011) / WISCRS Kenosha, Milwaukee, Ozaukee and Racine (ftUS)",9003,6318,7505,9807,1,0,4497,8801,42.13,9110,8802,-87.534,9110,8805,1.0000260649,9201,8806,610000.003,9003,8807,0.003,9003,,,,,,
+7614,"NAD83(2011) / WISCRS Kewaunee, Manitowoc and Sheboygan (ftUS)",9003,6318,7507,9807,1,0,4497,8801,43.16,9110,8802,-87.33,9110,8805,1.0000233704,9201,8806,262000.006,9003,8807,0.004,9003,,,,,,
+7615,"NAD83(2011) / WISCRS La Crosse (ftUS)",9003,6318,7509,9807,1,0,4497,8801,43.2704,9110,8802,-91.19,9110,8805,1.0000319985,9201,8806,427999.996,9003,8807,0.011,9003,,,,,,
+7616,"NAD83(2011) / WISCRS Langlade (ftUS)",9003,6318,7453,9801,1,0,4497,8801,45.0915253579,9110,8802,-89.02,9110,8805,1.0000627024,9201,8806,651000,9003,8807,345405.421,9003,,,,,,
+7617,"NAD83(2011) / WISCRS Lincoln (ftUS)",9003,6318,7455,9807,1,0,4497,8801,44.504,9110,8802,-89.44,9110,8805,1.0000599003,9201,8806,381000,9003,8807,0.019,9003,,,,,,
+7618,"NAD83(2011) / WISCRS Marathon (ftUS)",9003,6318,7457,9801,1,0,4497,8801,44.5403255925,9110,8802,-89.4612,9110,8805,1.000053289,9201,8806,245000,9003,8807,180607.47,9003,,,,,,
+7619,"NAD83(2011) / WISCRS Marinette (ftUS)",9003,6318,7459,9807,1,0,4497,8801,44.413,9110,8802,-87.424,9110,8805,1.0000234982,9201,8806,783000.007,9003,8807,0.01,9003,,,,,,
+7620,"NAD83(2011) / WISCRS Menominee (ftUS)",9003,6318,7461,9807,1,0,4497,8801,44.43,9110,8802,-88.25,9110,8805,1.0000362499,9201,8806,346000.004,9003,8807,0.01,9003,,,,,,
+7621,"NAD83(2011) / WISCRS Monroe (ftUS)",9003,6318,7511,9801,1,0,4497,8801,44.0000266143,9110,8802,-90.383,9110,8805,1.0000434122,9201,8806,671000,9003,8807,400012.278,9003,,,,,,
+7622,"NAD83(2011) / WISCRS Oconto (ftUS)",9003,6318,7463,9807,1,0,4497,8801,44.235,9110,8802,-87.543,9110,8805,1.0000236869,9201,8806,600000.006,9003,8807,0.011,9003,,,,,,
+7623,"NAD83(2011) / WISCRS Oneida (ftUS)",9003,6318,7393,9801,1,0,4497,8801,45.4215205573,9110,8802,-89.324,9110,8805,1.0000686968,9201,8806,230000,9003,8807,188936.744,9003,,,,,,
+7624,"NAD83(2011) / WISCRS Pepin and Pierce (ftUS)",9003,6318,7465,9801,1,0,4497,8801,44.3810135939,9110,8802,-92.134,9110,8805,1.0000362977,9201,8806,550000,9003,8807,282260.222,9003,,,,,,
+7625,"NAD83(2011) / WISCRS Polk (ftUS)",9003,6318,7467,9807,1,0,4497,8801,44.394,9110,8802,-92.38,9110,8805,1.0000433849,9201,8806,464999.996,9003,8807,0.019,9003,,,,,,
+7626,"NAD83(2011) / WISCRS Portage (ftUS)",9003,6318,7469,9801,1,0,4497,8801,44.2500566311,9110,8802,-89.3,9110,8805,1.000039936,9201,8806,185000,9003,8807,164114.46,9003,,,,,,
+7627,"NAD83(2011) / WISCRS Price (ftUS)",9003,6318,7395,9807,1,0,4497,8801,44.332,9110,8802,-90.292,9110,8805,1.0000649554,9201,8806,747999.995,9003,8807,0.036,9003,,,,,,
+7628,"NAD83(2011) / WISCRS Richland (ftUS)",9003,6318,7513,9801,1,0,4497,8801,43.1920326539,9110,8802,-90.255,9110,8805,1.0000375653,9201,8806,664000,9003,8807,440469.675,9003,,,,,,
+7629,"NAD83(2011) / WISCRS Rock (ftUS)",9003,6318,7515,9807,1,0,4497,8801,41.564,9110,8802,-89.042,9110,8805,1.0000337311,9201,8806,480000,9003,8807,0.022,9003,,,,,,
+7630,"NAD83(2011) / WISCRS Rusk (ftUS)",9003,6318,7471,9807,1,0,4497,8801,43.551,9110,8802,-91.04,9110,8805,1.0000495976,9201,8806,822000.001,9003,8807,0.077,9003,,,,,,
+7631,"NAD83(2011) / WISCRS Sauk (ftUS)",9003,6318,7517,9807,1,0,4497,8801,42.491,9110,8802,-89.54,9110,8805,1.0000373868,9201,8806,609000.001,9003,8807,0.017,9003,,,,,,
+7632,"NAD83(2011) / WISCRS Sawyer (ftUS)",9003,6318,7397,9801,1,0,4497,8801,45.5400356873,9110,8802,-91.07,9110,8805,1.0000573461,9201,8806,711000.001,9003,8807,396108.667,9003,,,,,,
+7633,"NAD83(2011) / WISCRS Shawano (ftUS)",9003,6318,7473,9807,1,0,4497,8801,44.021,9110,8802,-88.362,9110,8805,1.000032144,9201,8806,861000.001,9003,8807,0.031,9003,,,,,,
+7634,"NAD83(2011) / WISCRS St. Croix (ftUS)",9003,6318,7475,9807,1,0,4497,8801,44.021,9110,8802,-92.38,9110,8805,1.0000381803,9201,8806,542999.997,9003,8807,0.034,9003,,,,,,
+7635,"NAD83(2011) / WISCRS Taylor (ftUS)",9003,6318,7477,9801,1,0,4497,8801,45.1040159509,9110,8802,-90.29,9110,8805,1.0000597566,9201,8806,614000,9003,8807,353499.136,9003,,,,,,
+7636,"NAD83(2011) / WISCRS Trempealeau (ftUS)",9003,6318,7479,9807,1,0,4497,8801,43.094,9110,8802,-91.22,9110,8805,1.0000361538,9201,8806,843000,9003,8807,0.013,9003,,,,,,
+7637,"NAD83(2011) / WISCRS Vernon (ftUS)",9003,6318,7519,9801,1,0,4497,8801,43.3430118583,9110,8802,-90.47,9110,8805,1.0000408158,9201,8806,730000,9003,8807,155944.768,9003,,,,,,
+7638,"NAD83(2011) / WISCRS Vilas (ftUS)",9003,6318,7399,9801,1,0,4497,8801,46.0440238726,9110,8802,-89.292,9110,8805,1.0000730142,9201,8806,441000,9003,8807,165147.666,9003,,,,,,
+7639,"NAD83(2011) / WISCRS Walworth (ftUS)",9003,6318,7521,9801,1,0,4497,8801,42.4010063549,9110,8802,-88.323,9110,8805,1.0000367192,9201,8806,763000,9003,8807,364461.943,9003,,,,,,
+7640,"NAD83(2011) / WISCRS Washburn (ftUS)",9003,6318,7425,9801,1,0,4497,8801,45.57403914,9110,8802,-91.47,9110,8805,1.0000475376,9201,8806,768000,9003,8807,617973.193,9003,,,,,,
+7641,"NAD83(2011) / WISCRS Washington (ftUS)",9003,6318,7523,9807,1,0,4497,8801,42.5505,9110,8802,-88.035,9110,8805,1.00003738,9201,8806,394000.004,9003,8807,0.01,9003,,,,,,
+7642,"NAD83(2011) / WISCRS Waukesha (ftUS)",9003,6318,7525,9807,1,0,4497,8801,42.341,9110,8802,-88.133,9110,8805,1.0000346179,9201,8806,685000.001,9003,8807,0.011,9003,,,,,,
+7643,"NAD83(2011) / WISCRS Waupaca (ftUS)",9003,6318,7481,9807,1,0,4497,8801,43.2513,9110,8802,-88.49,9110,8805,1.0000333645,9201,8806,607000.003,9003,8807,0.023,9003,,,,,,
+7644,"NAD83(2011) / WISCRS Waushara (ftUS)",9003,6318,7527,9801,1,0,4497,8801,44.0650198565,9110,8802,-89.143,9110,8805,1.0000392096,9201,8806,394000,9003,8807,147866.367,9003,,,,,,
+7645,"NAD83(2011) / WISCRS Wood (ftUS)",9003,6318,7483,9801,1,0,4497,8801,44.214534369,9110,8802,-90,9110,8805,1.0000421209,9201,8806,684000.001,9003,8807,441566.551,9003,,,,,,
 20004,"Pulkovo 1995 / Gauss-Kruger zone 4",9001,4200,16204,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,
 20005,"Pulkovo 1995 / Gauss-Kruger zone 5",9001,4200,16205,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,
 20006,"Pulkovo 1995 / Gauss-Kruger zone 6",9001,4200,16206,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,
@@ -3459,8 +3852,8 @@
 26996,"NAD83 / Missouri East",9001,4269,12431,9807,1,0,4499,8801,35.5,9110,8802,-90.3,9110,8805,0.999933333,9201,8806,250000,9001,8807,0,9001,,,,,,
 26997,"NAD83 / Missouri Central",9001,4269,12432,9807,1,0,4499,8801,35.5,9110,8802,-92.3,9110,8805,0.999933333,9201,8806,500000,9001,8807,0,9001,,,,,,
 26998,"NAD83 / Missouri West",9001,4269,12433,9807,1,0,4499,8801,36.1,9110,8802,-94.3,9110,8805,0.999941177,9201,8806,850000,9001,8807,0,9001,,,,,,
-27037,"Nahrwan 1967 / UTM zone 37N",9001,4270,16037,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-27038,"Nahrwan 1967 / UTM zone 38N",9001,4270,16038,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+27037,"Nahrwan 1967 / UTM zone 37N",9001,4270,16037,9807,1,1,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+27038,"Nahrwan 1967 / UTM zone 38N",9001,4270,16038,9807,1,1,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 27039,"Nahrwan 1967 / UTM zone 39N",9001,4270,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 27040,"Nahrwan 1967 / UTM zone 40N",9001,4270,16040,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 27120,"Naparima 1972 / UTM zone 20N",9001,4271,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
diff --git a/data/projop_wparm.csv b/data/projop_wparm.csv
index 6d1979e..a687198 100644
--- a/data/projop_wparm.csv
+++ b/data/projop_wparm.csv
@@ -57,10 +57,19 @@
 4111,"BLM zone 11N (US survey feet)",9807,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
 4112,"BLM zone 12N (US survey feet)",9807,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
 4113,"BLM zone 13N (US survey feet)",9807,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4114,Johor Cassini Grid,9806,8801,2.02333,9110,8802,103.334593,9110,8806,0,9001,8807,0,9001,,,,,,,,,
+4115,Sembilan and Melaka Cassini Grid,9806,8801,2.424422,9110,8802,101.56282,9110,8806,-242.005,9001,8807,-948.547,9001,,,,,,,,,
+4116,Pahang Cassini Grid,9806,8801,3.42395,9110,8802,102.261024,9110,8806,0,9001,8807,0,9001,,,,,,,,,
+4117,Selangor Cassini Grid,9806,8801,3.404924,9110,8802,101.302968,9110,8806,-21759.438,9001,8807,55960.906,9001,,,,,,,,,
 4118,"BLM zone 18N (US survey feet)",9807,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
 4119,"BLM zone 19N (US survey feet)",9807,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4177,Terengganu Cassini Grid,9806,8801,4.564611,9110,8802,102.534275,9110,8806,0,9001,8807,0,9001,,,,,,,,,
 4186,"BLM zone 59N (US survey feet)",9807,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
 4187,"BLM zone 60N (US survey feet)",9807,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4305,Pinang Cassini Grid,9806,8801,5.251677,9110,8802,100.204513,9110,8806,0,9001,8807,0,9001,,,,,,,,,
+4320,Kedah and Perlis Cassini Grid,9806,8801,5.575453,9110,8802,100.381534,9110,8806,0,9001,8807,0,9001,,,,,,,,,
+4321,Perak Revised Cassini Grid,9806,8801,4.513377,9110,8802,100.490036,9110,8806,0,9001,8807,133453.669,9001,,,,,,,,,
+4323,Kelantan Cassini Grid,9806,8801,5.533812,9110,8802,102.103825,9110,8806,0,9001,8807,0,9001,,,,,,,,,
 4325,Guam Map Grid,9807,8801,13.3,9110,8802,144.45,9110,8805,1,9201,8806,100000,9001,8807,200000,9001,,,,,,
 4416,Katanga Lambert,9802,8821,-9,9102,8822,26,9102,8823,-6.5,9102,8824,-11.5,9102,8826,500000,9001,8827,500000,9001,,,
 4436,Pennsylvania CS27 South zone,9802,8821,39.2,9110,8822,-77.45,9110,8823,40.58,9110,8824,39.56,9110,8826,2000000,9003,8827,0,9003,,,
@@ -335,6 +344,7 @@
 6241,Valledupar urban grid,1052,1039,200,9001,8801,10.265014,9110,8802,-73.1447657,9110,8806,1090979.66,9001,8807,1647208.93,9001,,,,,,
 6242,Villavicencio urban grid,1052,1039,427.19,9001,8801,4.091935036,9110,8802,-73.372814955,9110,8806,1050678.757,9001,8807,950952.124,9001,,,,,,
 6243,Yopal urban grid,1052,1039,300,9001,8801,5.2114138,9110,8802,-72.2512145,9110,8806,851184.177,9001,8807,1083954.137,9001,,,,,,
+6308,Cyprus Transverse Mercator,9807,8801,0,9102,8802,33,9102,8805,0.99995,9201,8806,200000,9001,8807,-3500000,9001,,,,,,
 6361,Mexico LCC,9802,8821,12,9102,8822,-102,9102,8823,17.5,9102,8824,29.5,9102,8826,2500000,9001,8827,0,9001,,,
 6374,Ukraine TM zone 7,9807,8801,0,9102,8802,21,9102,8805,1,9201,8806,300000,9001,8807,0,9001,,,,,,
 6375,Ukraine TM zone 8,9807,8801,0,9102,8802,24,9102,8805,1,9201,8806,300000,9001,8807,0,9001,,,,,,
@@ -357,9 +367,331 @@
 6729,Map Grid of Australia zone 46,9807,8801,0,9102,8802,93,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
 6730,Map Grid of Australia zone 47,9807,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
 6731,Map Grid of Australia zone 59,9807,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-6869,Albania 2010,9807,8801,0,9102,8802,20,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
+6741,"Oregon Baker zone (meters)",9807,8801,44.3,9110,8802,-117.5,9110,8805,1.00016,9201,8806,40000,9001,8807,0,9001,,,,,,
+6742,"Oregon Baker zone (International feet)",9807,8801,44.3,9110,8802,-117.5,9110,8805,1.00016,9201,8806,131233.5958,9002,8807,0,9002,,,,,,
+6743,"Oregon Bend-Klamath Falls zone (meters)",9807,8801,41.45,9110,8802,-121.45,9110,8805,1.0002,9201,8806,80000,9001,8807,0,9001,,,,,,
+6744,"Oregon Bend-Klamath Falls zone (International feet)",9807,8801,41.45,9110,8802,-121.45,9110,8805,1.0002,9201,8806,262467.1916,9002,8807,0,9002,,,,,,
+6745,"Oregon Bend-Redmond-Prineville zone (meters)",9801,8801,44.4,9110,8802,-121.15,9110,8805,1.00012,9201,8806,80000,9001,8807,130000,9001,,,,,,
+6746,"Oregon Bend-Redmond-Prineville zone (International feet)",9801,8801,44.4,9110,8802,-121.15,9110,8805,1.00012,9201,8806,262467.1916,9002,8807,426509.1864,9002,,,,,,
+6747,"Oregon Bend-Burns zone (meters)",9801,8801,43.4,9110,8802,-119.45,9110,8805,1.0002,9201,8806,120000,9001,8807,60000,9001,,,,,,
+6748,"Oregon Bend-Burns zone (International feet)",9801,8801,43.4,9110,8802,-119.45,9110,8805,1.0002,9201,8806,393700.7874,9002,8807,196850.3937,9002,,,,,,
+6749,"Oregon Canyonville-Grants Pass zone (meters)",9807,8801,42.3,9110,8802,-123.2,9110,8805,1.00007,9201,8806,40000,9001,8807,0,9001,,,,,,
+6750,"Oregon Canyonville-Grants Pass zone (International feet)",9807,8801,42.3,9110,8802,-123.2,9110,8805,1.00007,9201,8806,131233.5958,9002,8807,0,9002,,,,,,
+6751,"Oregon Columbia River East zone (meters)",9801,8801,45.4,9110,8802,-120.3,9110,8805,1.000008,9201,8806,150000,9001,8807,30000,9001,,,,,,
+6752,"Oregon Columbia River East zone (International feet)",9801,8801,45.4,9110,8802,-120.3,9110,8805,1.000008,9201,8806,492125.9843,9002,8807,98425.1969,9002,,,,,,
+6753,"Oregon Columbia River West zone (meters)",9812,8806,7000000,9001,8807,-3000000,9001,8811,45.55,9110,8812,-123,9110,8813,295,9102,8814,295,9102,8815,1,9201
+6754,"Oregon Columbia River West zone (International feet)",9812,8806,22965879.2651,9002,8807,-9842519.685,9002,8811,45.55,9110,8812,-123,9110,8813,295,9102,8814,295,9102,8815,1,9201
+6755,"Oregon Cottage Grove-Canyonville zone (meters)",9807,8801,42.5,9110,8802,-123.2,9110,8805,1.000023,9201,8806,50000,9001,8807,0,9001,,,,,,
+6756,"Oregon Cottage Grove-Canyonville zone (International feet)",9807,8801,42.5,9110,8802,-123.2,9110,8805,1.000023,9201,8806,164041.9948,9002,8807,0,9002,,,,,,
+6757,"Oregon Dufur-Madras zone (meters)",9807,8801,44.3,9110,8802,-121,9110,8805,1.00011,9201,8806,80000,9001,8807,0,9001,,,,,,
+6758,"Oregon Dufur-Madras zone (International feet)",9807,8801,44.3,9110,8802,-121,9110,8805,1.00011,9201,8806,262467.1916,9002,8807,0,9002,,,,,,
+6759,"Oregon Eugene zone (meters)",9807,8801,43.45,9110,8802,-123.1,9110,8805,1.000015,9201,8806,50000,9001,8807,0,9001,,,,,,
+6760,"Oregon Eugene zone (International feet)",9807,8801,43.45,9110,8802,-123.1,9110,8805,1.000015,9201,8806,164041.9948,9002,8807,0,9002,,,,,,
+6761,"Oregon Grants Pass-Ashland zone (meters)",9807,8801,41.45,9110,8802,-123.2,9110,8805,1.000043,9201,8806,50000,9001,8807,0,9001,,,,,,
+6762,"Oregon Grants Pass-Ashland zone (International feet)",9807,8801,41.45,9110,8802,-123.2,9110,8805,1.000043,9201,8806,164041.9948,9002,8807,0,9002,,,,,,
+6763,"Oregon Gresham-Warm Springs zone (meters)",9807,8801,45,9110,8802,-122.2,9110,8805,1.00005,9201,8806,10000,9001,8807,0,9001,,,,,,
+6764,"Oregon Gresham-Warm Springs zone (International feet)",9807,8801,45,9110,8802,-122.2,9110,8805,1.00005,9201,8806,32808.399,9002,8807,0,9002,,,,,,
+6765,"Oregon La Grande zone (meters)",9807,8801,45,9102,8802,-118,9102,8805,1.00013,9201,8806,40000,9001,8807,0,9001,,,,,,
+6766,"Oregon La Grande zone (International feet)",9807,8801,45,9102,8802,-118,9102,8805,1.00013,9201,8806,131233.5958,9002,8807,0,9002,,,,,,
+6767,"Oregon Ontario zone (meters)",9807,8801,43.15,9110,8802,-117,9110,8805,1.0001,9201,8806,80000,9001,8807,0,9001,,,,,,
+6768,"Oregon Ontario zone (International feet)",9807,8801,43.15,9110,8802,-117,9110,8805,1.0001,9201,8806,262467.1916,9002,8807,0,9002,,,,,,
+6769,"Oregon Coast zone (meters)",9812,8806,-300000,9001,8807,-4600000,9001,8811,44.45,9110,8812,-124.03,9110,8813,5,9102,8814,5,9102,8815,1,9201
+6770,"Oregon Coast zone (International feet)",9812,8806,-984251.9685,9002,8807,-15091863.5171,9002,8811,44.45,9110,8812,-124.03,9110,8813,5,9102,8814,5,9102,8815,1,9201
+6771,"Oregon Pendleton zone (meters)",9807,8801,45.15,9110,8802,-119.1,9110,8805,1.000045,9201,8806,60000,9001,8807,0,9001,,,,,,
+6772,"Oregon Pendleton zone (International feet)",9807,8801,45.15,9110,8802,-119.1,9110,8805,1.000045,9201,8806,196850.3937,9002,8807,0,9002,,,,,,
+6773,"Oregon Pendleton-La Grande zone (meters)",9807,8801,45.05,9110,8802,-118.2,9110,8805,1.000175,9201,8806,30000,9001,8807,0,9001,,,,,,
+6774,"Oregon Pendleton-La Grande zone (International feet)",9807,8801,45.05,9110,8802,-118.2,9110,8805,1.000175,9201,8806,98425.1969,9002,8807,0,9002,,,,,,
+6775,"Oregon Portland zone (meters)",9801,8801,45.3,9110,8802,-122.45,9110,8805,1.000002,9201,8806,100000,9001,8807,50000,9001,,,,,,
+6776,"Oregon Portland zone (International feet)",9801,8801,45.3,9110,8802,-122.45,9110,8805,1.000002,9201,8806,328083.9895,9002,8807,164041.9948,9002,,,,,,
+6777,"Oregon Salem zone (meters)",9807,8801,44.2,9110,8802,-123.05,9110,8805,1.00001,9201,8806,50000,9001,8807,0,9001,,,,,,
+6778,"Oregon Salem zone (International feet)",9807,8801,44.2,9110,8802,-123.05,9110,8805,1.00001,9201,8806,164041.9948,9002,8807,0,9002,,,,,,
+6779,"Oregon Santiam Pass zone (meters)",9807,8801,44.05,9110,8802,-122.3,9110,8805,1.000155,9201,8806,0,9001,8807,0,9001,,,,,,
+6780,"Oregon Santiam Pass zone (International feet)",9807,8801,44.05,9110,8802,-122.3,9110,8805,1.000155,9201,8806,0,9002,8807,0,9002,,,,,,
+6869,Albania TM 2010,9807,8801,0,9102,8802,20,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
 6877,Italy zone,9807,8801,0,9102,8802,12,9102,8805,0.9985,9201,8806,7000000,9001,8807,0,9001,,,,,,
 6878,Italy zone 12,9807,8801,0,9102,8802,12,9102,8805,1,9201,8806,3000000,9001,8807,0,9001,,,,,,
+6920,"Kansas DOT Lambert (meters)",9802,8821,36,9110,8822,-98.15,9110,8823,39.3,9110,8824,37.3,9110,8826,400000,9001,8827,0,9001,,,
+6921,"Kansas DOT Lambert (US Survey feet)",9802,8821,36,9110,8822,-98.15,9110,8823,39.3,9110,8824,37.3,9110,8826,1312333.3333,9003,8827,0,9003,,,
+6928,US NSIDC EASE-Grid 2.0 Global,9835,8802,0,9102,8806,0,9001,8807,0,9001,8823,30,9102,,,,,,,,,
+6929,US NSIDC EASE-Grid 2.0 North,9820,8801,90,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,
+6930,US NSIDC EASE-Grid 2.0 South,9820,8801,-90,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,
+6952,Vietnam TM-3 zone 481,9807,8801,0,9102,8802,102,9102,8805,0.9999,9201,8806,0,9001,8807,500000,9001,,,,,,
+6953,Vietnam TM-3 zone 482,9807,8801,0,9102,8802,105,9102,8805,0.9999,9201,8806,0,9001,8807,500000,9001,,,,,,
+6954,Vietnam TM-3 zone 491,9807,8801,0,9102,8802,108,9102,8805,0.9999,9201,8806,0,9001,8807,500000,9001,,,,,,
+6955,Vietnam TM-3 Da Nang zone,9807,8801,0,9110,8802,107.45,9110,8805,0.9999,9201,8806,0,9001,8807,500000,9001,,,,,,
+6961,Albania LCC 2010,9802,8821,41,9102,8822,20,9102,8823,39,9102,8824,43,9102,8826,0,9001,8827,0,9001,,,
+6965,Michigan CS27 North zone,1051,1038,1.0000382,9201,8821,44.47,9110,8822,-87,9110,8823,45.29,9110,8824,47.05,9110,8826,2000000,9003,8827,0,9003
+6994,"City and County of San Francisco CS13 (meters)",9807,8801,37.75,9102,8802,-122.45,9102,8805,1.000007,9202,8806,48000,9001,8807,24000,9001,,,,,,
+6995,"City and County of San Francisco CS13 (US Survey feet)",9807,8801,37.75,9102,8802,-122.45,9102,8805,1.000007,9202,8806,157480,9003,8807,78740,9003,,,,,,
+7043,Iowa regional zone 1 Spencer,9801,8801,43.12,9110,8802,-95.15,9110,8805,1.000052,9201,8806,11500000,9003,8807,9600000,9003,,,,,,
+7044,Iowa regional zone 2 Mason City,9801,8801,43.1,9110,8802,-92.45,9110,8805,1.000043,9201,8806,12500000,9003,8807,9800000,9003,,,,,,
+7045,Iowa regional zone 3 Elkader,9807,8801,40.15,9110,8802,-91.12,9110,8805,1.000035,9201,8806,13500000,9003,8807,8300000,9003,,,,,,
+7046,Iowa regional zone 4 Sioux City-Iowa Falls,9801,8801,42.32,9110,8802,-94.5,9110,8805,1.000045,9201,8806,14500000,9003,8807,8600000,9003,,,,,,
+7047,Iowa regional zone 5 Waterloo,9801,8801,42.39,9110,8802,-92.15,9110,8805,1.000032,9201,8806,15500000,9003,8807,8900000,9003,,,,,,
+7048,Iowa regional zone 6 Council Bluffs,9807,8801,40.15,9110,8802,-95.44,9110,8805,1.000039,9201,8806,16500000,9003,8807,6600000,9003,,,,,,
+7049,Iowa regional zone 7 Carroll-Atlantic,9807,8801,40.15,9110,8802,-94.38,9110,8805,1.000045,9201,8806,17500000,9003,8807,6800000,9003,,,,,,
+7050,Iowa regional zone 8 Ames-Des Moines,9807,8801,40.15,9110,8802,-93.43,9110,8805,1.000033,9201,8806,18500000,9003,8807,7000000,9003,,,,,,
+7051,Iowa regional zone 9 Newton,9807,8801,40.15,9110,8802,-92.49,9110,8805,1.000027,9201,8806,19500000,9003,8807,7200000,9003,,,,,,
+7052,Iowa regional zone 10 Cedar Rapids,9801,8801,41.5,9110,8802,-91.4,9110,8805,1.00002,9201,8806,20500000,9003,8807,8000000,9003,,,,,,
+7053,Iowa regional zone 11 Dubuque-Davenport,9807,8801,40.15,9110,8802,-90.32,9110,8805,1.000027,9201,8806,21500000,9003,8807,7600000,9003,,,,,,
+7054,Iowa regional zone 12 Red Oak-Ottumwa,9801,8801,40.55,9110,8802,-93.45,9110,8805,1.000037,9201,8806,22500000,9003,8807,6200000,9003,,,,,,
+7055,Iowa regional zone 13 Fairfield,9807,8801,40.15,9110,8802,-91.55,9110,8805,1.00002,9201,8806,23500000,9003,8807,6400000,9003,,,,,,
+7056,Iowa regional zone 14 Burlington,9807,8801,40.15,9110,8802,-91.15,9110,8805,1.000018,9201,8806,24500000,9003,8807,6200000,9003,,,,,,
+7089,"Montana Blackfeet St Mary Valley (meters)",9807,8801,48.3,9110,8802,-112.3,9110,8805,1.00016,9201,8806,150000,9001,8807,0,9001,,,,,,
+7090,"Montana Blackfeet St Mary Valley (International feet)",9807,8801,48.3,9110,8802,-112.3,9110,8805,1.00016,9201,8806,492125.9843,9002,8807,0,9002,,,,,,
+7091,"Montana Blackfeet (meters)",9807,8801,48,9110,8802,-112.3,9110,8805,1.00019,9201,8806,100000,9001,8807,0,9001,,,,,,
+7092,"Montana Blackfeet (International feet)",9807,8801,48,9110,8802,-112.3,9110,8805,1.00019,9201,8806,328083.9895,9002,8807,0,9002,,,,,,
+7093,"Montana Milk River (meters)",9801,8801,48.3,9110,8802,-111,9110,8805,1.000145,9201,8806,150000,9001,8807,200000,9001,,,,,,
+7094,"Montana Milk River (International feet)",9801,8801,48.3,9110,8802,-111,9110,8805,1.000145,9201,8806,492125.9843,9002,8807,656167.979,9002,,,,,,
+7095,"Montana Fort Belknap (meters)",9801,8801,48.3,9110,8802,-108.3,9110,8805,1.00012,9201,8806,200000,9001,8807,150000,9001,,,,,,
+7096,"Montana Fort Belknap (International feet)",9801,8801,48.3,9110,8802,-108.3,9110,8805,1.00012,9201,8806,656167.979,9002,8807,492125.9843,9002,,,,,,
+7097,"Montana Fort Peck Assiniboine (meters)",9801,8801,48.2,9110,8802,-105.3,9110,8805,1.00012,9201,8806,200000,9001,8807,100000,9001,,,,,,
+7098,"Montana Fort Peck Assiniboine (International feet)",9801,8801,48.2,9110,8802,-105.3,9110,8805,1.00012,9201,8806,656167.979,9002,8807,328083.9895,9002,,,,,,
+7099,"Montana Fort Peck Sioux (meters)",9801,8801,48.2,9110,8802,-105.3,9110,8805,1.00009,9201,8806,100000,9001,8807,50000,9001,,,,,,
+7100,"Montana Fort Peck Sioux (International feet)",9801,8801,48.2,9110,8802,-105.3,9110,8805,1.00009,9201,8806,328083.9895,9002,8807,164041.9938,9002,,,,,,
+7101,"Montana Crow (meters)",9807,8801,44.45,9110,8802,-107.45,9110,8805,1.000148,9201,8806,200000,9001,8807,0,9001,,,,,,
+7102,"Montana Crow (International feet)",9807,8801,44.45,9110,8802,-107.45,9110,8805,1.000148,9201,8806,656167.979,9002,8807,0,9002,,,,,,
+7103,"Montana Bobcat (meters)",9801,8801,46.15,9110,8802,-111.15,9110,8805,1.000185,9201,8806,100000,9001,8807,100000,9001,,,,,,
+7104,"Montana Bobcat (International feet)",9801,8801,46.15,9110,8802,-111.15,9110,8805,1.000185,9201,8806,328083.9895,9002,8807,328083.9895,9002,,,,,,
+7105,"Montana Billings (meters)",9801,8801,45.47,9110,8802,-108.25,9110,8805,1.0001515,9201,8806,200000,9001,8807,50000,9001,,,,,,
+7106,"Montana Billings (International feet)",9801,8801,45.47,9110,8802,-108.25,9110,8805,1.0001515,9201,8806,656167.979,9002,8807,164041.9948,9002,,,,,,
+7107,"Wyoming Wind River (meters)",9807,8801,42.4,9110,8802,-108.2,9110,8805,1.00024,9201,8806,100000,9001,8807,0,9001,,,,,,
+7108,"Wyoming Wind River (US Survey feet)",9807,8801,42.4,9110,8802,-108.2,9110,8805,1.00024,9201,8806,328083.3333,9003,8807,0,9003,,,,,,
+7129,"City and County of San Francisco CS13 (meters)",9807,8801,37.75,9102,8802,-122.45,9102,8805,1.000007,9201,8806,48000,9001,8807,24000,9001,,,,,,
+7130,"City and County of San Francisco CS13 (US Survey feet)",9807,8801,37.75,9102,8802,-122.45,9102,8805,1.000007,9201,8806,157480,9003,8807,78740,9003,,,,,,
+7141,Palestine Grid modified,9807,8801,31.4402749,9110,8802,35.124349,9110,8805,1,9201,8806,170251.555,9001,8807,126867.909,9001,,,,,,
+7143,"InGCS Adams (m)",9807,8801,40.33,9110,8802,-84.57,9110,8805,1.000034,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7144,"InGCS Adams (ftUS)",9807,8801,40.33,9110,8802,-84.57,9110,8805,1.000034,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7145,"InGCS Allen (m)",9807,8801,40.54,9110,8802,-85.03,9110,8805,1.000031,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7146,"InGCS Allen (ftUS)",9807,8801,40.54,9110,8802,-85.03,9110,8805,1.000031,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7147,"InGCS Bartholomew (m)",9807,8801,39,9110,8802,-85.51,9110,8805,1.000026,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7148,"InGCS Bartholomew (ftUS)",9807,8801,39,9110,8802,-85.51,9110,8805,1.000026,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7149,"InGCS Benton (m)",9807,8801,40.27,9110,8802,-87.18,9110,8805,1.000029,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7150,"InGCS Benton (ftUS)",9807,8801,40.27,9110,8802,-87.18,9110,8805,1.000029,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7151,"InGCS Blackford-Delaware (m)",9807,8801,40.03,9110,8802,-85.24,9110,8805,1.000038,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7152,"InGCS Blackford-Delaware (ftUS)",9807,8801,40.03,9110,8802,-85.24,9110,8805,1.000038,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7153,"InGCS Boone-Hendricks (m)",9807,8801,39.36,9110,8802,-86.3,9110,8805,1.000036,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7154,"InGCS Boone-Hendricks (ftUS)",9807,8801,39.36,9110,8802,-86.3,9110,8805,1.000036,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7155,"InGCS Brown (m)",9807,8801,39,9110,8802,-86.18,9110,8805,1.00003,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7156,"InGCS Brown (ftUS)",9807,8801,39,9110,8802,-86.18,9110,8805,1.00003,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7157,"InGCS Carroll (m)",9807,8801,40.24,9110,8802,-86.39,9110,8805,1.000026,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7158,"InGCS Carroll (ftUS)",9807,8801,40.24,9110,8802,-86.39,9110,8805,1.000026,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7159,"InGCS Cass (m)",9807,8801,40.33,9110,8802,-86.24,9110,8805,1.000028,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7160,"InGCS Cass (ftUS)",9807,8801,40.33,9110,8802,-86.24,9110,8805,1.000028,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7161,"InGCS Clark-Floyd-Scott (m)",9807,8801,38.09,9110,8802,-85.36,9110,8805,1.000021,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7162,"InGCS Clark-Floyd-Scott (ftUS)",9807,8801,38.09,9110,8802,-85.36,9110,8805,1.000021,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7163,"InGCS Clay (m)",9807,8801,39.09,9110,8802,-87.09,9110,8805,1.000024,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7164,"InGCS Clay (ftUS)",9807,8801,39.09,9110,8802,-87.09,9110,8805,1.000024,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7165,"InGCS Clinton (m)",9807,8801,40.09,9110,8802,-86.36,9110,8805,1.000032,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7166,"InGCS Clinton (ftUS)",9807,8801,40.09,9110,8802,-86.36,9110,8805,1.000032,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7167,"InGCS Crawford-Lawrence-Orange (m)",9807,8801,38.06,9110,8802,-86.3,9110,8805,1.000025,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7168,"InGCS Crawford-Lawrence-Orange (ftUS)",9807,8801,38.06,9110,8802,-86.3,9110,8805,1.000025,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7169,"InGCS Daviess-Greene (m)",9807,8801,38.27,9110,8802,-87.06,9110,8805,1.000018,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7170,"InGCS Daviess-Greene (ftUS)",9807,8801,38.27,9110,8802,-87.06,9110,8805,1.000018,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7171,"InGCS Dearborn-Ohio-Switzerland (m)",9807,8801,38.39,9110,8802,-84.54,9110,8805,1.000029,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7172,"InGCS Dearborn-Ohio-Switzerland (ftUS)",9807,8801,38.39,9110,8802,-84.54,9110,8805,1.000029,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7173,"InGCS Decatur-Rush (m)",9807,8801,39.06,9110,8802,-85.39,9110,8805,1.000036,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7174,"InGCS Decatur-Rush (ftUS)",9807,8801,39.06,9110,8802,-85.39,9110,8805,1.000036,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7175,"InGCS DeKalb (m)",9807,8801,41.15,9110,8802,-84.57,9110,8805,1.000036,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7176,"InGCS DeKalb (ftUS)",9807,8801,41.15,9110,8802,-84.57,9110,8805,1.000036,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7177,"InGCS Dubois-Martin (m)",9807,8801,38.12,9110,8802,-86.57,9110,8805,1.00002,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7178,"InGCS Dubois-Martin (ftUS)",9807,8801,38.12,9110,8802,-86.57,9110,8805,1.00002,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7179,"InGCS Elkhart-Kosciusko-Wabash (m)",9807,8801,40.39,9110,8802,-85.51,9110,8805,1.000033,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7180,"InGCS Elkhart-Kosciusko-Wabash (ftUS)",9807,8801,40.39,9110,8802,-85.51,9110,8805,1.000033,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7181,"InGCS Fayette-Franklin-Union (m)",9807,8801,39.15,9110,8802,-85.03,9110,8805,1.000038,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7182,"InGCS Fayette-Franklin-Union (ftUS)",9807,8801,39.15,9110,8802,-85.03,9110,8805,1.000038,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7183,"InGCS Fountain-Warren (m)",9807,8801,39.57,9110,8802,-87.18,9110,8805,1.000025,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7184,"InGCS Fountain-Warren (ftUS)",9807,8801,39.57,9110,8802,-87.18,9110,8805,1.000025,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7185,"InGCS Fulton-Marshall-St. Joseph (m)",9807,8801,40.54,9110,8802,-86.18,9110,8805,1.000031,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7186,"InGCS Fulton-Marshall-St. Joseph (ftUS)",9807,8801,40.54,9110,8802,-86.18,9110,8805,1.000031,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7187,"InGCS Gibson (m)",9807,8801,38.09,9110,8802,-87.39,9110,8805,1.000013,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7188,"InGCS Gibson (ftUS)",9807,8801,38.09,9110,8802,-87.39,9110,8805,1.000013,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7189,"InGCS Grant (m)",9807,8801,40.21,9110,8802,-85.42,9110,8805,1.000034,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7190,"InGCS Grant (ftUS)",9807,8801,40.21,9110,8802,-85.42,9110,8805,1.000034,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7191,"InGCS Hamilton-Tipton (m)",9807,8801,39.54,9110,8802,-86,9110,8805,1.000034,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7192,"InGCS Hamilton-Tipton (ftUS)",9807,8801,39.54,9110,8802,-86,9110,8805,1.000034,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7193,"InGCS Hancock-Madison (m)",9807,8801,39.39,9110,8802,-85.48,9110,8805,1.000036,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7194,"InGCS Hancock-Madison (ftUS)",9807,8801,39.39,9110,8802,-85.48,9110,8805,1.000036,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7195,"InGCS Harrison-Washington (m)",9807,8801,37.57,9110,8802,-86.09,9110,8805,1.000027,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7196,"InGCS Harrison-Washington (ftUS)",9807,8801,37.57,9110,8802,-86.09,9110,8805,1.000027,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7197,"InGCS Henry (m)",9807,8801,39.45,9110,8802,-85.27,9110,8805,1.000043,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7198,"InGCS Henry (ftUS)",9807,8801,39.45,9110,8802,-85.27,9110,8805,1.000043,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7199,"InGCS Howard-Miami (m)",9807,8801,40.21,9110,8802,-86.09,9110,8805,1.000031,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7200,"InGCS Howard-Miami (ftUS)",9807,8801,40.21,9110,8802,-86.09,9110,8805,1.000031,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7201,"InGCS Huntington-Whitley (m)",9807,8801,40.39,9110,8802,-85.3,9110,8805,1.000034,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7202,"InGCS Huntington-Whitley (ftUS)",9807,8801,40.39,9110,8802,-85.3,9110,8805,1.000034,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7203,"InGCS Jackson (m)",9807,8801,38.42,9110,8802,-85.57,9110,8805,1.000022,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7204,"InGCS Jackson (ftUS)",9807,8801,38.42,9110,8802,-85.57,9110,8805,1.000022,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7205,"InGCS Jasper-Porter (m)",9807,8801,40.42,9110,8802,-87.06,9110,8805,1.000027,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7206,"InGCS Jasper-Porter (ftUS)",9807,8801,40.42,9110,8802,-87.06,9110,8805,1.000027,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7207,"InGCS Jay (m)",9807,8801,40.18,9110,8802,-85,9110,8805,1.000038,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7208,"InGCS Jay (ftUS)",9807,8801,40.18,9110,8802,-85,9110,8805,1.000038,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7209,"InGCS Jefferson (m)",9807,8801,38.33,9110,8802,-85.21,9110,8805,1.000028,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7210,"InGCS Jefferson (ftUS)",9807,8801,38.33,9110,8802,-85.21,9110,8805,1.000028,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7211,"InGCS Jennings (m)",9807,8801,38.48,9110,8802,-85.48,9110,8805,1.000025,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7212,"InGCS Jennings (ftUS)",9807,8801,38.48,9110,8802,-85.48,9110,8805,1.000025,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7213,"InGCS Johnson-Marion (m)",9807,8801,39.18,9110,8802,-86.09,9110,8805,1.000031,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7214,"InGCS Johnson-Marion (ftUS)",9807,8801,39.18,9110,8802,-86.09,9110,8805,1.000031,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7215,"InGCS Knox (m)",9807,8801,38.24,9110,8802,-87.27,9110,8805,1.000015,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7216,"InGCS Knox (ftUS)",9807,8801,38.24,9110,8802,-87.27,9110,8805,1.000015,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7217,"InGCS LaGrange-Noble (m)",9807,8801,41.15,9110,8802,-85.27,9110,8805,1.000037,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7218,"InGCS LaGrange-Noble (ftUS)",9807,8801,41.15,9110,8802,-85.27,9110,8805,1.000037,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7219,"InGCS Lake-Newton (m)",9807,8801,40.42,9110,8802,-87.24,9110,8805,1.000026,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7220,"InGCS Lake-Newton (ftUS)",9807,8801,40.42,9110,8802,-87.24,9110,8805,1.000026,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7221,"InGCS LaPorte-Pulaski-Starke (m)",9807,8801,40.54,9110,8802,-86.45,9110,8805,1.000027,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7222,"InGCS LaPorte-Pulaski-Starke (ftUS)",9807,8801,40.54,9110,8802,-86.45,9110,8805,1.000027,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7223,"InGCS Monroe-Morgan (m)",9807,8801,38.57,9110,8802,-86.3,9110,8805,1.000028,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7224,"InGCS Monroe-Morgan (ftUS)",9807,8801,38.57,9110,8802,-86.3,9110,8805,1.000028,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7225,"InGCS Montgomery-Putnam (m)",9807,8801,39.27,9110,8802,-86.57,9110,8805,1.000031,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7226,"InGCS Montgomery-Putnam (ftUS)",9807,8801,39.27,9110,8802,-86.57,9110,8805,1.000031,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7227,"InGCS Owen (m)",9807,8801,39.09,9110,8802,-86.54,9110,8805,1.000026,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7228,"InGCS Owen (ftUS)",9807,8801,39.09,9110,8802,-86.54,9110,8805,1.000026,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7229,"InGCS Parke-Vermillion (m)",9807,8801,39.36,9110,8802,-87.21,9110,8805,1.000022,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7230,"InGCS Parke-Vermillion (ftUS)",9807,8801,39.36,9110,8802,-87.21,9110,8805,1.000022,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7231,"InGCS Perry (m)",9807,8801,37.48,9110,8802,-86.42,9110,8805,1.00002,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7232,"InGCS Perry (ftUS)",9807,8801,37.48,9110,8802,-86.42,9110,8805,1.00002,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7233,"InGCS Pike-Warrick (m)",9807,8801,37.51,9110,8802,-87.18,9110,8805,1.000015,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7234,"InGCS Pike-Warrick (ftUS)",9807,8801,37.51,9110,8802,-87.18,9110,8805,1.000015,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7235,"InGCS Posey (m)",9807,8801,37.45,9110,8802,-87.57,9110,8805,1.000013,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7236,"InGCS Posey (ftUS)",9807,8801,37.45,9110,8802,-87.57,9110,8805,1.000013,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7237,"InGCS Randolph-Wayne (m)",9807,8801,39.42,9110,8802,-85.03,9110,8805,1.000044,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7238,"InGCS Randolph-Wayne (ftUS)",9807,8801,39.42,9110,8802,-85.03,9110,8805,1.000044,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7239,"InGCS Ripley (m)",9807,8801,38.54,9110,8802,-85.18,9110,8805,1.000038,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7240,"InGCS Ripley (ftUS)",9807,8801,38.54,9110,8802,-85.18,9110,8805,1.000038,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7241,"InGCS Shelby (m)",9807,8801,39.18,9110,8802,-85.54,9110,8805,1.00003,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7242,"InGCS Shelby (ftUS)",9807,8801,39.18,9110,8802,-85.54,9110,8805,1.00003,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7243,"InGCS Spencer (m)",9807,8801,37.45,9110,8802,-87.03,9110,8805,1.000014,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7244,"InGCS Spencer (ftUS)",9807,8801,37.45,9110,8802,-87.03,9110,8805,1.000014,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7245,"InGCS Steuben (m)",9807,8801,41.3,9110,8802,-85,9110,8805,1.000041,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7246,"InGCS Steuben (ftUS)",9807,8801,41.3,9110,8802,-85,9110,8805,1.000041,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7247,"InGCS Sullivan (m)",9807,8801,38.54,9110,8802,-87.3,9110,8805,1.000017,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7248,"InGCS Sullivan (ftUS)",9807,8801,38.54,9110,8802,-87.3,9110,8805,1.000017,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7249,"InGCS Tippecanoe-White (m)",9807,8801,40.12,9110,8802,-86.54,9110,8805,1.000026,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7250,"InGCS Tippecanoe-White (ftUS)",9807,8801,40.12,9110,8802,-86.54,9110,8805,1.000026,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7251,"InGCS Vanderburgh (m)",9807,8801,37.48,9110,8802,-87.33,9110,8805,1.000015,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7252,"InGCS Vanderburgh (ftUS)",9807,8801,37.48,9110,8802,-87.33,9110,8805,1.000015,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7253,"InGCS Vigo (m)",9807,8801,39.15,9110,8802,-87.27,9110,8805,1.00002,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7254,"InGCS Vigo (ftUS)",9807,8801,39.15,9110,8802,-87.27,9110,8805,1.00002,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7255,"InGCS Wells (m)",9807,8801,40.33,9110,8802,-85.15,9110,8805,1.000034,9201,8806,240000,9001,8807,36000,9001,,,,,,
+7256,"InGCS Wells (ftUS)",9807,8801,40.33,9110,8802,-85.15,9110,8805,1.000034,9201,8806,787400,9003,8807,118110,9003,,,,,,
+7378,"WISCRS Ashland County (m)",9807,8801,45.4222,9110,8802,-90.372,9110,8805,1.0000495683,9201,8806,172821.9461,9001,8807,0.0017,9001,,,,,,
+7379,"WISCRS Ashland County (ftUS)",9807,8801,45.4222,9110,8802,-90.372,9110,8805,1.0000495683,9201,8806,567000.001,9003,8807,0.006,9003,,,,,,
+7380,"WISCRS Bayfield County (m)",9801,8801,46.4010734158,9110,8802,-91.091,9110,8805,1.0000331195,9201,8806,228600.4575,9001,8807,148551.4837,9001,,,,,,
+7381,"WISCRS Bayfield County (ftUS)",9801,8801,46.4010734158,9110,8802,-91.091,9110,8805,1.0000331195,9201,8806,750000.001,9003,8807,487372.659,9003,,,,,,
+7382,"WISCRS Burnett County (m)",9801,8801,45.5355373517,9110,8802,-92.2728,9110,8805,1.0000383841,9201,8806,64008.1276,9001,8807,59445.9043,9001,,,,,,
+7383,"WISCRS Burnett County (ftUS)",9801,8801,45.5355373517,9110,8802,-92.2728,9110,8805,1.0000383841,9201,8806,209999.999,9003,8807,195032.104,9003,,,,,,
+7384,"WISCRS Douglas County (m)",9807,8801,45.53,9110,8802,-91.55,9110,8805,1.0000385418,9201,8806,59131.3183,9001,8807,0.0041,9001,,,,,,
+7385,"WISCRS Douglas County (ftUS)",9807,8801,45.53,9110,8802,-91.55,9110,8805,1.0000385418,9201,8806,194000,9003,8807,0.013,9003,,,,,,
+7386,"WISCRS Florence County (m)",9807,8801,45.262,9110,8802,-88.083,9110,8805,1.0000552095,9201,8806,133502.6683,9001,8807,0.0063,9001,,,,,,
+7387,"WISCRS Florence County (ftUS)",9807,8801,45.262,9110,8802,-88.083,9110,8805,1.0000552095,9201,8806,438000.004,9003,8807,0.021,9003,,,,,,
+7388,"WISCRS Forest County (m)",9807,8801,44.002,9110,8802,-88.38,9110,8805,1.0000673004,9201,8806,275844.5533,9001,8807,0.0157,9001,,,,,,
+7389,"WISCRS Forest County (ftUS)",9807,8801,44.002,9110,8802,-88.38,9110,8805,1.0000673004,9201,8806,905000.005,9003,8807,0.052,9003,,,,,,
+7390,"WISCRS Iron County (m)",9807,8801,45.26,9110,8802,-90.152,9110,8805,1.0000677153,9201,8806,220980.4419,9001,8807,0.0085,9001,,,,,,
+7391,"WISCRS Iron County (ftUS)",9807,8801,45.26,9110,8802,-90.152,9110,8805,1.0000677153,9201,8806,725000,9003,8807,0.028,9003,,,,,,
+7392,"WISCRS Oneida County (m)",9801,8801,45.4215205573,9110,8802,-89.324,9110,8805,1.0000686968,9201,8806,70104.1401,9001,8807,57588.0346,9001,,,,,,
+7393,"WISCRS Oneida County (ftUS)",9801,8801,45.4215205573,9110,8802,-89.324,9110,8805,1.0000686968,9201,8806,230000,9003,8807,188936.744,9003,,,,,,
+7394,"WISCRS Price County (m)",9807,8801,44.332,9110,8802,-90.292,9110,8805,1.0000649554,9201,8806,227990.8546,9001,8807,0.0109,9001,,,,,,
+7395,"WISCRS Price County (ftUS)",9807,8801,44.332,9110,8802,-90.292,9110,8805,1.0000649554,9201,8806,747999.995,9003,8807,0.036,9003,,,,,,
+7396,"WISCRS Sawyer County (m)",9801,8801,45.5400356873,9110,8802,-91.07,9110,8805,1.0000573461,9201,8806,216713.2336,9001,8807,120734.1631,9001,,,,,,
+7397,"WISCRS Sawyer County (ftUS)",9801,8801,45.5400356873,9110,8802,-91.07,9110,8805,1.0000573461,9201,8806,711000.001,9003,8807,396108.667,9003,,,,,,
+7398,"WISCRS Vilas County (m)",9801,8801,46.0440238726,9110,8802,-89.292,9110,8805,1.0000730142,9201,8806,134417.0689,9001,8807,50337.1092,9001,,,,,,
+7399,"WISCRS Vilas County (ftUS)",9801,8801,46.0440238726,9110,8802,-89.292,9110,8805,1.0000730142,9201,8806,441000,9003,8807,165147.666,9003,,,,,,
+7424,"WISCRS Washburn County (m)",9801,8801,45.57403914,9110,8802,-91.47,9110,8805,1.0000475376,9201,8806,234086.8682,9001,8807,188358.6058,9001,,,,,,
+7425,"WISCRS Washburn County (ftUS)",9801,8801,45.57403914,9110,8802,-91.47,9110,8805,1.0000475376,9201,8806,768000,9003,8807,617973.193,9003,,,,,,
+7426,"WISCRS Barron County (m)",9807,8801,45.08,9110,8802,-91.51,9110,8805,1.0000486665,9201,8806,93150,9001,8807,0.0029,9001,,,,,,
+7427,"WISCRS Barron County (ftUS)",9807,8801,45.08,9110,8802,-91.51,9110,8805,1.0000486665,9201,8806,305609.625,9003,8807,0.01,9003,,,,,,
+7428,"WISCRS Brown County (m)",9807,8801,43,9102,8802,-88,9102,8805,1.00002,9201,8806,31600,9001,8807,4600,9001,,,,,,
+7429,"WISCRS Brown County (ftUS)",9807,8801,43,9110,8802,-88,9110,8805,1.00002,9201,8806,103674.333,9003,8807,15091.833,9003,,,,,,
+7430,"WISCRS Buffalo County (m)",9807,8801,43.2853,9110,8802,-91.475,9110,8805,1.0000382778,9201,8806,175260.3502,9001,8807,0.0048,9001,,,,,,
+7431,"WISCRS Buffalo County (ftUS)",9807,8801,43.2853,9110,8802,-91.475,9110,8805,1.0000382778,9201,8806,574999.999,9003,8807,0.016,9003,,,,,,
+7432,"WISCRS Chippewa County (m)",9801,8801,44.5840284835,9110,8802,-91.174,9110,8805,1.0000391127,9201,8806,60045.72,9001,8807,44091.4346,9001,,,,,,
+7433,"WISCRS Chippewa County (ftUS)",9801,8801,44.5840284835,9110,8802,-91.174,9110,8805,1.0000391127,9201,8806,197000,9003,8807,144656.648,9003,,,,,,
+7434,"WISCRS Clark County (m)",9807,8801,43.36,9110,8802,-90.423,9110,8805,1.0000463003,9201,8806,199949.1989,9001,8807,0.0086,9001,,,,,,
+7435,"WISCRS Clark County (ftUS)",9807,8801,43.36,9110,8802,-90.423,9110,8805,1.0000463003,9201,8806,655999.997,9003,8807,0.028,9003,,,,,,
+7436,"WISCRS Door County (m)",9807,8801,44.24,9110,8802,-87.162,9110,8805,1.0000187521,9201,8806,158801.1176,9001,8807,0.0023,9001,,,,,,
+7437,"WISCRS Door County (ftUS)",9807,8801,44.24,9110,8802,-87.162,9110,8805,1.0000187521,9201,8806,521000,9003,8807,0.008,9003,,,,,,
+7438,"WISCRS Dunn County (m)",9807,8801,44.243,9110,8802,-91.534,9110,8805,1.0000410324,9201,8806,51816.104,9001,8807,0.003,9001,,,,,,
+7439,"WISCRS Dunn County (ftUS)",9807,8801,44.243,9110,8802,-91.534,9110,8805,1.0000410324,9201,8806,170000.001,9003,8807,0.01,9003,,,,,,
+7440,"WISCRS Eau Claire County (m)",9801,8801,44.5220212055,9110,8802,-91.172,9110,8805,1.000035079,9201,8806,120091.4402,9001,8807,91687.9239,9001,,,,,,
+7441,"WISCRS Eau Claire County (ftUS)",9801,8801,44.5220212055,9110,8802,-91.172,9110,8805,1.000035079,9201,8806,394000,9003,8807,300812.797,9003,,,,,,
+7450,"WISCRS Jackson County (m)",9807,8801,44.151200646,9110,8802,-90.503946747,9110,8805,1.0000353,9201,8806,27000,9001,8807,25000,9001,,,,,,
+7451,"WISCRS Jackson County (ftUS)",9807,8801,44.151200646,9110,8802,-90.503946747,9110,8805,1.0000353,9201,8806,88582.5,9003,8807,82020.833,9003,,,,,,
+7452,"WISCRS Langlade County (m)",9801,8801,45.0915253579,9110,8802,-89.02,9110,8805,1.0000627024,9201,8806,198425.197,9001,8807,105279.7829,9001,,,,,,
+7453,"WISCRS Langlade County (ftUS)",9801,8801,45.0915253579,9110,8802,-89.02,9110,8805,1.0000627024,9201,8806,651000,9003,8807,345405.421,9003,,,,,,
+7454,"WISCRS Lincoln County (m)",9807,8801,44.504,9110,8802,-89.44,9110,8805,1.0000599003,9201,8806,116129.0323,9001,8807,0.0058,9001,,,,,,
+7455,"WISCRS Lincoln County (ftUS)",9807,8801,44.504,9110,8802,-89.44,9110,8805,1.0000599003,9201,8806,381000,9003,8807,0.019,9003,,,,,,
+7456,"WISCRS Marathon County (m)",9801,8801,44.5403255925,9110,8802,-89.4612,9110,8805,1.000053289,9201,8806,74676.1493,9001,8807,55049.2669,9001,,,,,,
+7457,"WISCRS Marathon County (ftUS)",9801,8801,44.5403255925,9110,8802,-89.4612,9110,8805,1.000053289,9201,8806,245000,9003,8807,180607.47,9003,,,,,,
+7458,"WISCRS Marinette County (m)",9807,8801,44.413,9110,8802,-87.424,9110,8805,1.0000234982,9201,8806,238658.8794,9001,8807,0.0032,9001,,,,,,
+7459,"WISCRS Marinette County (ftUS)",9807,8801,44.413,9110,8802,-87.424,9110,8805,1.0000234982,9201,8806,783000.007,9003,8807,0.01,9003,,,,,,
+7460,"WISCRS Menominee County (m)",9807,8801,44.43,9110,8802,-88.25,9110,8805,1.0000362499,9201,8806,105461.0121,9001,8807,0.0029,9001,,,,,,
+7461,"WISCRS Menominee County (ftUS)",9807,8801,44.43,9110,8802,-88.25,9110,8805,1.0000362499,9201,8806,346000.004,9003,8807,0.01,9003,,,,,,
+7462,"WISCRS Oconto County (m)",9807,8801,44.235,9110,8802,-87.543,9110,8805,1.0000236869,9201,8806,182880.3676,9001,8807,0.0033,9001,,,,,,
+7463,"WISCRS Oconto County (ftUS)",9807,8801,44.235,9110,8802,-87.543,9110,8805,1.0000236869,9201,8806,600000.006,9003,8807,0.011,9003,,,,,,
+7464,"WISCRS Pepin and Pierce Counties (m)",9801,8801,44.3810135939,9110,8802,-92.134,9110,8805,1.0000362977,9201,8806,167640.3354,9001,8807,86033.0876,9001,,,,,,
+7465,"WISCRS Pepin and Pierce Counties (ftUS)",9801,8801,44.3810135939,9110,8802,-92.134,9110,8805,1.0000362977,9201,8806,550000,9003,8807,282260.222,9003,,,,,,
+7466,"WISCRS Polk County (m)",9807,8801,44.394,9110,8802,-92.38,9110,8805,1.0000433849,9201,8806,141732.2823,9001,8807,0.0059,9001,,,,,,
+7467,"WISCRS Polk County (ftUS)",9807,8801,44.394,9110,8802,-92.38,9110,8805,1.0000433849,9201,8806,464999.996,9003,8807,0.019,9003,,,,,,
+7468,"WISCRS Portage County (m)",9801,8801,44.2500566311,9110,8802,-89.3,9110,8805,1.000039936,9201,8806,56388.1128,9001,8807,50022.1874,9001,,,,,,
+7469,"WISCRS Portage County (ftUS)",9801,8801,44.2500566311,9110,8802,-89.3,9110,8805,1.000039936,9201,8806,185000,9003,8807,164114.46,9003,,,,,,
+7470,"WISCRS Rusk County (m)",9807,8801,43.551,9110,8802,-91.04,9110,8805,1.0000495976,9201,8806,250546.1013,9001,8807,0.0234,9001,,,,,,
+7471,"WISCRS Rusk County (ftUS)",9807,8801,43.551,9110,8802,-91.04,9110,8805,1.0000495976,9201,8806,822000.001,9003,8807,0.077,9003,,,,,,
+7472,"WISCRS Shawano County (m)",9807,8801,44.021,9110,8802,-88.362,9110,8805,1.000032144,9201,8806,262433.3253,9001,8807,0.0096,9001,,,,,,
+7473,"WISCRS Shawano County (ftUS)",9807,8801,44.021,9110,8802,-88.362,9110,8805,1.000032144,9201,8806,861000.001,9003,8807,0.031,9003,,,,,,
+7474,"WISCRS St. Croix County (m)",9807,8801,44.021,9110,8802,-92.38,9110,8805,1.0000381803,9201,8806,165506.7302,9001,8807,0.0103,9001,,,,,,
+7475,"WISCRS St. Croix County (ftUS)",9807,8801,44.021,9110,8802,-92.38,9110,8805,1.0000381803,9201,8806,542999.997,9003,8807,0.034,9003,,,,,,
+7476,"WISCRS Taylor County (m)",9801,8801,45.1040159509,9110,8802,-90.29,9110,8805,1.0000597566,9201,8806,187147.5744,9001,8807,107746.7522,9001,,,,,,
+7477,"WISCRS Taylor County (ftUS)",9801,8801,45.1040159509,9110,8802,-90.29,9110,8805,1.0000597566,9201,8806,614000,9003,8807,353499.136,9003,,,,,,
+7478,"WISCRS Trempealeau County (m)",9807,8801,43.094,9110,8802,-91.22,9110,8805,1.0000361538,9201,8806,256946.9138,9001,8807,0.0041,9001,,,,,,
+7479,"WISCRS Trempealeau County (ftUS)",9807,8801,43.094,9110,8802,-91.22,9110,8805,1.0000361538,9201,8806,843000,9003,8807,0.013,9003,,,,,,
+7480,"WISCRS Waupaca County (m)",9807,8801,43.2513,9110,8802,-88.49,9110,8805,1.0000333645,9201,8806,185013.9709,9001,8807,0.007,9001,,,,,,
+7481,"WISCRS Waupaca County (ftUS)",9807,8801,43.2513,9110,8802,-88.49,9110,8805,1.0000333645,9201,8806,607000.003,9003,8807,0.023,9003,,,,,,
+7482,"WISCRS Wood County (m)",9801,8801,44.214534369,9110,8802,-90,9110,8805,1.0000421209,9201,8806,208483.6173,9001,8807,134589.754,9001,,,,,,
+7483,"WISCRS Wood County (ftUS)",9801,8801,44.214534369,9110,8802,-90,9110,8805,1.0000421209,9201,8806,684000.001,9003,8807,441566.551,9003,,,,,,
+7484,"WISCRS Adams and Juneau Counties (m)",9807,8801,43.22,9110,8802,-90,9110,8805,1.0000365285,9201,8806,147218.6942,9001,8807,0.0037,9001,,,,,,
+7485,"WISCRS Adams and Juneau Counties (ftUS)",9807,8801,43.22,9110,8802,-90,9110,8805,1.0000365285,9201,8806,482999.999,9003,8807,0.012,9003,,,,,,
+7486,"WISCRS Calumet, Fond du Lac, Outagamie and Winnebago Counties (m)",9807,8801,42.431,9110,8802,-88.3,9110,8805,1.0000286569,9201,8806,244754.8893,9001,8807,0.0049,9001,,,,,,
+7487,"WISCRS Calumet, Fond du Lac, Outagamie and Winnebago Counties (ftUS)",9807,8801,42.431,9110,8802,-88.3,9110,8805,1.0000286569,9201,8806,802999.999,9003,8807,0.016,9003,,,,,,
+7488,"WISCRS Columbia County (m)",9801,8801,43.2745167925,9110,8802,-89.234,9110,8805,1.00003498,9201,8806,169164.3381,9001,8807,111569.6134,9001,,,,,,
+7489,"WISCRS Columbia County (ftUS)",9801,8801,43.2745167925,9110,8802,-89.234,9110,8805,1.00003498,9201,8806,554999.999,9003,8807,366041.307,9003,,,,,,
+7490,"WISCRS Crawford County (m)",9801,8801,43.1200200178,9110,8802,-90.562,9110,8805,1.0000349151,9201,8806,113690.6274,9001,8807,53703.1201,9001,,,,,,
+7491,"WISCRS Crawford County (ftUS)",9801,8801,43.1200200178,9110,8802,-90.562,9110,8805,1.0000349151,9201,8806,373000,9003,8807,176190.987,9003,,,,,,
+7492,"WISCRS Dane County (m)",9801,8801,43.0410257735,9110,8802,-89.252,9110,8805,1.0000384786,9201,8806,247193.2944,9001,8807,146591.9896,9001,,,,,,
+7493,"WISCRS Dane County (ftUS)",9801,8801,43.0410257735,9110,8802,-89.252,9110,8805,1.0000384786,9201,8806,811000,9003,8807,480943.886,9003,,,,,,
+7494,"WISCRS Dodge and Jefferson Counties (m)",9807,8801,41.282,9110,8802,-88.463,9110,8805,1.0000346418,9201,8806,263347.7263,9001,8807,0.0076,9001,,,,,,
+7495,"WISCRS Dodge and Jefferson Counties (ftUS)",9807,8801,41.282,9110,8802,-88.463,9110,8805,1.0000346418,9201,8806,863999.999,9003,8807,0.025,9003,,,,,,
+7496,"WISCRS Grant County (m)",9807,8801,41.244,9110,8802,-90.48,9110,8805,1.0000349452,9201,8806,242316.4841,9001,8807,0.01,9001,,,,,,
+7497,"WISCRS Grant County (ftUS)",9807,8801,41.244,9110,8802,-90.48,9110,8805,1.0000349452,9201,8806,794999.998,9003,8807,0.033,9003,,,,,,
+7498,"WISCRS Green and Lafayette Counties (m)",9801,8801,42.3815224197,9110,8802,-89.502,9110,8805,1.0000390487,9201,8806,170078.7403,9001,8807,45830.2947,9001,,,,,,
+7499,"WISCRS Green and Lafayette Counties (ftUS)",9801,8801,42.3815224197,9110,8802,-89.502,9110,8805,1.0000390487,9201,8806,558000,9003,8807,150361.559,9003,,,,,,
+7500,"WISCRS Green Lake and Marquette Counties (m)",9801,8801,43.4825200424,9110,8802,-89.143,9110,8805,1.0000344057,9201,8806,150876.3018,9001,8807,79170.7795,9001,,,,,,
+7501,"WISCRS Green Lake and Marquette Counties (ftUS)",9801,8801,43.4825200424,9110,8802,-89.143,9110,8805,1.0000344057,9201,8806,495000,9003,8807,259746.132,9003,,,,,,
+7502,"WISCRS Iowa County (m)",9807,8801,42.322,9110,8802,-90.094,9110,8805,1.0000394961,9201,8806,113081.0261,9001,8807,0.0045,9001,,,,,,
+7503,"WISCRS Iowa County (ftUS)",9807,8801,42.322,9110,8802,-90.094,9110,8805,1.0000394961,9201,8806,371000,9003,8807,0.015,9003,,,,,,
+7504,"WISCRS Kenosha, Milwaukee, Ozaukee and Racine Counties (m)",9807,8801,42.13,9110,8802,-87.534,9110,8805,1.0000260649,9201,8806,185928.3728,9001,8807,0.0009,9001,,,,,,
+7505,"WISCRS Kenosha, Milwaukee, Ozaukee and Racine Counties (ftUS)",9807,8801,42.13,9110,8802,-87.534,9110,8805,1.0000260649,9201,8806,610000.003,9003,8807,0.003,9003,,,,,,
+7506,"WISCRS Kewaunee, Manitowoc and Sheboygan Counties (m)",9807,8801,43.16,9110,8802,-87.33,9110,8805,1.0000233704,9201,8806,79857.7614,9001,8807,0.0012,9001,,,,,,
+7507,"WISCRS Kewaunee, Manitowoc and Sheboygan Counties (ftUS)",9807,8801,43.16,9110,8802,-87.33,9110,8805,1.0000233704,9201,8806,262000.006,9003,8807,0.004,9003,,,,,,
+7508,"WISCRS La Crosse County (m)",9807,8801,43.2704,9110,8802,-91.19,9110,8805,1.0000319985,9201,8806,130454.6598,9001,8807,0.0033,9001,,,,,,
+7509,"WISCRS La Crosse County (ftUS)",9807,8801,43.2704,9110,8802,-91.19,9110,8805,1.0000319985,9201,8806,427999.996,9003,8807,0.011,9003,,,,,,
+7510,"WISCRS Monroe County (m)",9801,8801,44.0000266143,9110,8802,-90.383,9110,8805,1.0000434122,9201,8806,204521.209,9001,8807,121923.9861,9001,,,,,,
+7511,"WISCRS Monroe County (ftUS)",9801,8801,44.0000266143,9110,8802,-90.383,9110,8805,1.0000434122,9201,8806,671000,9003,8807,400012.278,9003,,,,,,
+7512,"WISCRS Richland County (m)",9801,8801,43.1920326539,9110,8802,-90.255,9110,8805,1.0000375653,9201,8806,202387.6048,9001,8807,134255.4253,9001,,,,,,
+7513,"WISCRS Richland County (ftUS)",9801,8801,43.1920326539,9110,8802,-90.255,9110,8805,1.0000375653,9201,8806,664000,9003,8807,440469.675,9003,,,,,,
+7514,"WISCRS Rock County (m)",9807,8801,41.564,9110,8802,-89.042,9110,8805,1.0000337311,9201,8806,146304.2926,9001,8807,0.0068,9001,,,,,,
+7515,"WISCRS Rock County (ftUS)",9807,8801,41.564,9110,8802,-89.042,9110,8805,1.0000337311,9201,8806,480000,9003,8807,0.022,9003,,,,,,
+7516,"WISCRS Sauk County (m)",9807,8801,42.491,9110,8802,-89.54,9110,8805,1.0000373868,9201,8806,185623.5716,9001,8807,0.0051,9001,,,,,,
+7517,"WISCRS Sauk County (ftUS)",9807,8801,42.491,9110,8802,-89.54,9110,8805,1.0000373868,9201,8806,609000.001,9003,8807,0.017,9003,,,,,,
+7518,"WISCRS Vernon County (m)",9801,8801,43.3430118583,9110,8802,-90.47,9110,8805,1.0000408158,9201,8806,222504.4451,9001,8807,47532.0602,9001,,,,,,
+7519,"WISCRS Vernon County (ftUS)",9801,8801,43.3430118583,9110,8802,-90.47,9110,8805,1.0000408158,9201,8806,730000,9003,8807,155944.768,9003,,,,,,
+7520,"WISCRS Walworth County (m)",9801,8801,42.4010063549,9110,8802,-88.323,9110,8805,1.0000367192,9201,8806,232562.8651,9001,8807,111088.2224,9001,,,,,,
+7521,"WISCRS Walworth County (ftUS)",9801,8801,42.4010063549,9110,8802,-88.323,9110,8805,1.0000367192,9201,8806,763000,9003,8807,364461.943,9003,,,,,,
+7522,"WISCRS Washington County (m)",9807,8801,42.5505,9110,8802,-88.035,9110,8805,1.00003738,9201,8806,120091.4415,9001,8807,0.003,9001,,,,,,
+7523,"WISCRS Washington County (ftUS)",9807,8801,42.5505,9110,8802,-88.035,9110,8805,1.00003738,9201,8806,394000.004,9003,8807,0.01,9003,,,,,,
+7524,"WISCRS Waukesha County (m)",9807,8801,42.341,9110,8802,-88.133,9110,8805,1.0000346179,9201,8806,208788.418,9001,8807,0.0034,9001,,,,,,
+7525,"WISCRS Waukesha County (ftUS)",9807,8801,42.341,9110,8802,-88.133,9110,8805,1.0000346179,9201,8806,685000.001,9003,8807,0.011,9003,,,,,,
+7526,"WISCRS Waushara County (m)",9801,8801,44.0650198565,9110,8802,-89.143,9110,8805,1.0000392096,9201,8806,120091.4402,9001,8807,45069.7587,9001,,,,,,
+7527,"WISCRS Waushara County (ftUS)",9801,8801,44.0650198565,9110,8802,-89.143,9110,8805,1.0000392096,9201,8806,394000,9003,8807,147866.367,9003,,,,,,
 10101,Alabama CS27 East zone,9807,8801,30.3,9110,8802,-85.5,9110,8805,0.99996,9201,8806,500000,9003,8807,0,9003,,,,,,
 10102,Alabama CS27 West zone,9807,8801,30,9110,8802,-87.3,9110,8805,0.999933333,9201,8806,500000,9003,8807,0,9003,,,,,,
 10131,"SPCS83 Alabama East zone (meters)",9807,8801,30.3,9110,8802,-85.5,9110,8805,0.99996,9201,8806,200000,9001,8807,0,9001,,,,,,
@@ -753,8 +1085,8 @@
 15398,Great Lakes and St Lawrence Albers,9822,8821,45.568977,9102,8822,-83.248627,9102,8823,42.122774,9102,8824,49.01518,9102,8826,1000000,9001,8827,1000000,9001,,,
 15399,Yap Islands,9832,8801,9.324815,9110,8802,138.100748,9110,8806,40000,9001,8807,60000,9001,,,,,,,,,
 15400,Guam SPCS,9831,8801,13.282087887,9110,8802,144.445550254,9110,8806,50000,9001,8807,50000,9001,,,,,,,,,
-15498,Geographic 2D axis order reversal,9843,,,,,,,,,,,,,,,,,,,,,
-15499,Geographic 3D horizontal axis order reversal,9844,,,,,,,,,,,,,,,,,,,,,
+15498,"axis order change (2D)",9843,,,,,,,,,,,,,,,,,,,,,
+15499,"axis order change (geographic3D horizontal)",9844,,,,,,,,,,,,,,,,,,,,,
 15500,Australian Antarctic geocentric to geog3D,9602,,,,,,,,,,,,,,,,,,,,,
 15501,Australian Antarctic geog3D to geog2D,9659,,,,,,,,,,,,,,,,,,,,,
 15502,CHTRF95 geocentric to geog3D,9602,,,,,,,,,,,,,,,,,,,,,
diff --git a/data/ruian_vf_ob_v1.gfs b/data/ruian_vf_ob_v1.gfs
index 4b6328e..36f0dba 100644
--- a/data/ruian_vf_ob_v1.gfs
+++ b/data/ruian_vf_ob_v1.gfs
@@ -164,6 +164,13 @@
       <Type>String</Type>
       <Width>12</Width>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- Spravní obvody -->
   <GMLFeatureClass>
@@ -242,6 +249,13 @@
       <Type>Integer</Type>
       <SubType>Integer64</SubType>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- MOP -->
   <GMLFeatureClass>
@@ -314,6 +328,13 @@
       <Type>Integer</Type>
       <SubType>Integer64</SubType>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- MOMC -->
   <GMLFeatureClass>
@@ -455,6 +476,13 @@
       <ElementPath>ZnakObrazek</ElementPath>
       <Type>Complex</Type> <!-- ??? -->
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- CastiObci -->
   <GMLFeatureClass>
@@ -552,6 +580,13 @@
       <Type>String</Type>
       <Width>48</Width>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- Katastralní území -->
   <GMLFeatureClass>
@@ -675,6 +710,13 @@
       <Type>String</Type>
       <Width>48</Width>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- ZSJ -->
   <GMLFeatureClass>
@@ -791,6 +833,13 @@
       <ElementPath>CharakterZsjKod</ElementPath>
       <Type>Integer</Type>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- Ulice -->
   <GMLFeatureClass>
diff --git a/data/ruian_vf_st_v1.gfs b/data/ruian_vf_st_v1.gfs
index 84d7121..05c2daa 100644
--- a/data/ruian_vf_st_v1.gfs
+++ b/data/ruian_vf_st_v1.gfs
@@ -77,6 +77,13 @@
       <Type>String</Type>
       <Width>2</Width>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- Regiony soudržnosti -->
   <GMLFeatureClass>
@@ -162,6 +169,13 @@
       <Type>String</Type>
       <Width>4</Width>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- Kraje -->
   <GMLFeatureClass>
@@ -247,6 +261,13 @@
       <Type>String</Type>
       <Width>4</Width>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- VÚSC -->
   <GMLFeatureClass>
@@ -333,6 +354,13 @@
       <Type>String</Type>
       <Width>5</Width>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- Okresy -->
   <GMLFeatureClass>
@@ -424,6 +452,13 @@
       <Type>String</Type>
       <Width>6</Width>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- ORP -->
   <GMLFeatureClass>
@@ -508,6 +543,13 @@
       <Type>Integer</Type>
       <SubType>Integer64</SubType>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- POU -->
   <GMLFeatureClass>
@@ -594,6 +636,13 @@
       <Type>Integer</Type>
       <SubType>Integer64</SubType>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- Obce -->
   <GMLFeatureClass>
@@ -760,6 +809,13 @@
       <Type>String</Type>
       <Width>12</Width>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- Spravní obvody -->
   <GMLFeatureClass>
@@ -838,6 +894,13 @@
       <Type>Integer</Type>
       <SubType>Integer64</SubType>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- MOP -->
   <GMLFeatureClass>
@@ -910,6 +973,13 @@
       <Type>Integer</Type>
       <SubType>Integer64</SubType>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- MOMC -->
   <GMLFeatureClass>
@@ -1051,6 +1121,13 @@
       <ElementPath>ZnakObrazek</ElementPath>
       <Type>Complex</Type> <!-- ??? -->
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- CastiObci -->
   <GMLFeatureClass>
@@ -1148,6 +1225,13 @@
       <Type>String</Type>
       <Width>48</Width>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- Katastralní území -->
   <GMLFeatureClass>
@@ -1271,6 +1355,13 @@
       <Type>String</Type>
       <Width>48</Width>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- ZSJ -->
   <GMLFeatureClass>
@@ -1387,5 +1478,12 @@
       <ElementPath>CharakterZsjKod</ElementPath>
       <Type>Integer</Type>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
 </GMLFeatureClassList>
diff --git a/data/ruian_vf_v1.gfs b/data/ruian_vf_v1.gfs
index 2371925..c8a6d79 100644
--- a/data/ruian_vf_v1.gfs
+++ b/data/ruian_vf_v1.gfs
@@ -77,6 +77,13 @@
       <Type>String</Type>
       <Width>2</Width>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- Regiony soudržnosti -->
   <GMLFeatureClass>
@@ -162,6 +169,13 @@
       <Type>String</Type>
       <Width>4</Width>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- Kraje -->
   <GMLFeatureClass>
@@ -247,6 +261,13 @@
       <Type>String</Type>
       <Width>4</Width>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- VÚSC -->
   <GMLFeatureClass>
@@ -333,6 +354,13 @@
       <Type>String</Type>
       <Width>5</Width>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- Okresy -->
   <GMLFeatureClass>
@@ -424,6 +452,13 @@
       <Type>String</Type>
       <Width>6</Width>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- ORP -->
   <GMLFeatureClass>
@@ -508,6 +543,13 @@
       <Type>Integer</Type>
       <SubType>Integer64</SubType>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- POU -->
   <GMLFeatureClass>
@@ -594,6 +636,13 @@
       <Type>Integer</Type>
       <SubType>Integer64</SubType>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- Obce -->
   <GMLFeatureClass>
@@ -760,6 +809,13 @@
       <Type>String</Type>
       <Width>12</Width>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- Spravní obvody -->
   <GMLFeatureClass>
@@ -838,6 +894,13 @@
       <Type>Integer</Type>
       <SubType>Integer64</SubType>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- MOP -->
   <GMLFeatureClass>
@@ -910,6 +973,13 @@
       <Type>Integer</Type>
       <SubType>Integer64</SubType>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- MOMC -->
   <GMLFeatureClass>
@@ -1051,6 +1121,13 @@
       <ElementPath>ZnakObrazek</ElementPath>
       <Type>Complex</Type> <!-- ??? -->
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- CastiObci -->
   <GMLFeatureClass>
@@ -1148,6 +1225,13 @@
       <Type>String</Type>
       <Width>48</Width>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- Katastralní území -->
   <GMLFeatureClass>
@@ -1271,6 +1355,13 @@
       <Type>String</Type>
       <Width>48</Width>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- ZSJ -->
   <GMLFeatureClass>
@@ -1387,6 +1478,13 @@
       <ElementPath>CharakterZsjKod</ElementPath>
       <Type>Integer</Type>
     </PropertyDefn>
+    <!-- Datum vzniku -->
+    <PropertyDefn>
+      <Name>DatumVzniku</Name>
+      <ElementPath>DatumVzniku</ElementPath>
+      <Type>String</Type>
+      <Width>19</Width>
+    </PropertyDefn>
   </GMLFeatureClass>
   <!-- Ulice -->
   <GMLFeatureClass>
diff --git a/data/unit_of_measure.csv b/data/unit_of_measure.csv
index 8dbf2cf..951bdc1 100644
--- a/data/unit_of_measure.csv
+++ b/data/unit_of_measure.csv
@@ -1,90 +1,85 @@
 uom_code,unit_of_meas_name,unit_of_meas_type,target_uom_code,factor_b,factor_c,remarks,information_source,data_source,revision_date,change_id,deprecated
 1024,bin,scale,9201,1,1,,OGP,OGP,2012/07/14,2011.106,0
-1025,millimetre,length,9001,1,1000,,ISO 1000.,OGP,2013/05/29,2013.021,0
-1026,metres per second,length,1026,1,1,Length rate.,OGP,OGP,2013/05/29,2013.021,0
+1025,millimetre,length,9001,1,1000,,ISO 1000.,IOGP,2015/11/25,2013.021 2015.062,0
+1026,metres per second,length,1026,1,1,Length rate.,OGP,IOGP,2015/11/25,2013.021 2015.062,0
 1027,millimetres per year,length,1026,1,31556925445,"Year taken to be IUGS definition of 31556925.445 seconds; see UoM code 1029.",ISO 1000.,OGP,2013/09/02,2013.021 2013.042,0
 1028,parts per billion,scale,9201,1,1000000000,"Billion is internationally ambiguous, in different languages being 1E+9 and 1E+12. One billion taken here to be 1E+9.",OGP,OGP,2013/05/29,2013.021,0
-1029,year,time,1040,31556925.445,1,,"International Union of Geological Sciences (IUGS) and International Union of Pure and Applied Chemistry (IUPAC). Pure Appl. Chem., Vol. 83, No. 5, pp. 1159–1162, 2011.",OGP,2013/05/28,2013.021,0
-1030,parts per billion per year,scale,1036,1,3.1556925445e+16,"Year taken to be IUGS definition of 31556925.445 seconds; see UoM code 1029. Billion
-    is internationally ambiguous, in different languages being 1E+9 and 1E+12. One billion taken
-    here to be 1E+9.",ISO 1000.,OGP,2013/12/13,2013.021 2013.042 2013.067,0
-1031,milliarc-second,angle,9101,3.14159265358979,648000000,= ((pi/180) / 3600 / 1000) radians,,OGP,2013/05/29,2013.021,0
-1032,milliarc-seconds per year,angle,1035,3.14159265358979,2.044888768836e+16,"= ((pi/180) / 3600 / 1000) radians per year. Year taken to be IUGS definition of 31556925.445 seconds; see UoM code 1029.",,OGP,2013/09/02,2013.021 2013.042,0
-1033,centimetre,length,9001,1,100,,ISO 1000.,OGP,2013/05/29,2013.021,0
+1031,milliarc-second,angle,9101,3.14159265358979,648000000,= ((pi/180) / 3600 / 1000) radians,,IOGP,2015/11/25,2013.021 2015.062,0
+1033,centimetre,length,9001,1,100,,ISO 1000.,IOGP,2015/11/25,2013.021 2015.062,0
 1034,centimetres per year,length,1026,1,3155692544.5,"Year taken to be IUGS definition of 31556925.445 seconds; see UoM code 1029.",ISO 1000.,OGP,2013/09/02,2013.021 2013.042,0
-1035,radians per second,angle,1035,1,1,Angle rate.,OGP,OGP,2013/05/29,2013.021,0
+1035,radians per second,angle,1035,1,1,Angle rate.,OGP,IOGP,2015/11/25,2013.021 2015.062,0
 1036,unity per second,scale,1036,1,1,Scale rate.,OGP,OGP,2013/05/29,2013.021,0
-1040,second,time,1040,1,1,Not to be confused with the angle unit arc-second.,ISO 1000.,OGP,2013/05/28,2013.021,0
+1040,second,time,1040,1,1,Not to be confused with the angle unit arc-second.,ISO 1000.,IOGP,2015/11/25,2013.021 2015.062,0
 1041,parts per million per year,scale,1036,1,31556925445000,"Year taken to be IUGS definition of 31556925.445 seconds; see UoM code 1029.",,OGP,2013/09/02,2013.021 2013.037 2013.042,0
 1042,metres per year,length,1026,1,31556925.445,"Year taken to be IUGS definition of 31556925.445 seconds; see UoM code 1029.",OGP,OGP,2013/09/02,2013.021 2013.042,0
-1043,arc-seconds per year,angle,1035,3.14159265358979,20448887688360,"=((pi/180) / 3600) radians per year. Year taken to be IUGS definition of 31556925.445 seconds; see UoM code 1029.",,OGP,2013/09/02,2013.021 2013.042,0
-9001,metre,length,9001,1,1,Also known as International metre. SI standard unit.,ISO 1000.,OGP,1995/06/02,,0
-9002,foot,length,9001,0.3048,1,,"ISO 1000; 1958",OGP,1995/06/02,,0
-9003,US survey foot,length,9001,12,39.37,Used in USA.,OGP,OGP,2000/05/07,1999.990,0
-9005,Clarke's foot,length,9001,0.3047972654,1,"Assumes Clarke's 1865 ratio of 1 British foot = 0.3047972654 French legal metres applies to the international metre.   Used in older Australian, southern African & British West Indian mapping.",Australian Land Information Group  www.auslig.gov.au,OGP,2005/09/06,1997.233 1999.990 2000.050 2005.370 2005.460,0
-9014,fathom,length,9001,1.8288,1,= 6 feet.,,OGP,1995/06/02,,0
-9030,nautical mile,length,9001,1852,1,,,OGP,1996/10/18,1996.240,0
-9031,German legal metre,length,9001,1.0000135965,1,Used in Namibia.,"Chief Directorate Surveys and Land Information; Mowbray; South Africa",OGP,1997/06/16,,0
-9033,US survey chain,length,9001,792,39.37,Used in USA primarily for public lands cadastral work.,Bureau of Land Management technical bulletin 6 (1973) and Standard Field Tables 8th edition (1956).,OGP,2000/05/07,1999.990,0
-9034,US survey link,length,9001,7.92,39.37,Used in USA primarily for public lands cadastral work.,Bureau of Land Management technical bulletin 6 (1973) and Standard Field Tables 8th edition (1956).,OGP,2000/05/07,1999.990,0
-9035,US survey mile,length,9001,63360,39.37,Used in USA primarily for public lands cadastral work.,Bureau of Land Management technical bulletin 6 (1973) and Standard Field Tables 8th edition (1956).,OGP,2000/05/07,1999.990,0
-9036,kilometre,length,9001,1000,1,,ISO 1000.,OGP,1998/11/11,,0
-9037,Clarke's yard,length,9001,0.9143917962,1,"=3 Clarke's feet.  Assumes Clarke's 1865 ratio of 1 British foot = 0.3047972654 French legal metres applies to the international metre.   Used in older Australian, southern African & British West Indian mapping.",Australian Land Information Group  www.auslig.gov.au,OGP,2005/09/06,1997.233 1999.990 2005.370 2005.460,0
-9038,Clarke's chain,length,9001,20.1166195164,1,"=22 Clarke's yards.  Assumes Clarke's 1865 ratio of 1 British foot = 0.3047972654 French legal metres applies to the international metre.   Used in older Australian, southern African & British West Indian mapping.",Australian Land Information Group  www.auslig.gov.au,OGP,2005/09/06,1997.233 1999.990 2005.370 2005.460,0
-9039,Clarke's link,length,9001,0.201166195164,1,"=1/100 Clarke's chain. Assumes Clarke's 1865 ratio of 1 British foot = 0.3047972654 French legal metres applies to the international metre.   Used in older Australian, southern African & British West Indian mapping.",Australian Land Information Group  www.auslig.gov.au,OGP,2005/09/06,1997.233 1999.990 2005.370 2005.460,0
-9040,British yard (Sears 1922),length,9001,36,39.370147,Uses Sear's 1922 British yard-metre ratio as given by Bomford as 39.370147 inches per metre.  Used in East Malaysian and older New Zealand mapping.,"G. Bomford ""Geodesy"" 2nd edition 1962; after J.S.Clark ""Remeasurement of the Old Length Standards""; Empire Survey Review no. 90; 1953.",OGP,2000/05/07,1997.233 1999.990,0
-9041,British foot (Sears 1922),length,9001,12,39.370147,Uses Sear's 1922 British yard-metre ratio as given by Bomford as 39.370147 inches per metre.  Used in East Malaysian and older New Zealand mapping.,"G. Bomford ""Geodesy"" 2nd edition 1962; after J.S.Clark ""Remeasurement of the Old Length Standards""; Empire Survey Review no. 90; 1953.",OGP,2000/05/07,1997.233 1999.990,0
-9042,British chain (Sears 1922),length,9001,792,39.370147,Uses Sear's 1922 British yard-metre ratio as given by Bomford as 39.370147 inches per metre.  Used in East Malaysian and older New Zealand mapping.,"G. Bomford ""Geodesy"" 2nd edition 1962; after J.S.Clark ""Remeasurement of the Old Length Standards""; Empire Survey Review no. 90; 1953.",OGP,2000/05/07,1997.233 1999.990,0
-9043,British link (Sears 1922),length,9001,7.92,39.370147,Uses Sear's 1922 British yard-metre ratio as given by Bomford as 39.370147 inches per metre.  Used in East Malaysian and older New Zealand mapping.,"G. Bomford ""Geodesy"" 2nd edition 1962; after J.S.Clark ""Remeasurement of the Old Length Standards""; Empire Survey Review no. 90; 1953.",OGP,2000/05/07,1997.233 1999.990,0
-9050,British yard (Benoit 1895 A),length,9001,0.9143992,1,Uses Benoit's 1895 British yard-metre ratio as given by Clark as 0.9143992 metres per yard.  Used for deriving metric size of ellipsoid in Palestine.,"J.S.Clark; ""Remeasurement of the Old Length Standards""; Empire Survey Review no. 90; 1953.",OGP,2006/03/21,1997.233 1999.990 2006.260,0
-9051,British foot (Benoit 1895 A),length,9001,0.9143992,3,Uses Benoit's 1895 British yard-metre ratio as given by Clark as 0.9143992 metres per yard.  Used for deriving metric size of ellipsoid in Palestine.,"J.S.Clark; ""Remeasurement of the Old Length Standards""; Empire Survey Review no. 90; 1953.",OGP,2006/03/21,1997.233 1999.990 2006.260,0
-9052,British chain (Benoit 1895 A),length,9001,20.1167824,1,Uses Benoit's 1895 British yard-metre ratio as given by Clark as 0.9143992 metres per yard.  Used for deriving metric size of ellipsoid in Palestine.,"J.S.Clark; ""Remeasurement of the Old Length Standards""; Empire Survey Review no. 90; 1953.",OGP,2006/03/21,1997.233 1999.990 2006.260,0
-9053,British link (Benoit 1895 A),length,9001,0.201167824,1,Uses Benoit's 1895 British yard-metre ratio as given by Clark as 0.9143992 metres per yard.  Used for deriving metric size of ellipsoid in Palestine.,"J.S.Clark; ""Remeasurement of the Old Length Standards""; Empire Survey Review no. 90; 1953.",OGP,2006/03/21,1997.233 1999.990 2006.260,0
-9060,British yard (Benoit 1895 B),length,9001,36,39.370113,"G. Bomford ""Geodesy"" 2nd edition 1962; after J.S.Clark ""Remeasurement of the Old Length Standards""; Empire Survey Review no. 90; 1953.","G. Bomford ""Geodesy"" 2nd edition 1962; after J.S.Clark ""Remeasurement of the Old Length Standards""; Empire Survey Review no. 90; 1953.",OGP,2000/05/07,1997.233 1999.990,0
-9061,British foot (Benoit 1895 B),length,9001,12,39.370113,Uses Benoit's 1895 British yard-metre ratio as given by Bomford as 39.370113 inches per metre.  Used in West Malaysian mapping.,"G. Bomford ""Geodesy"" 2nd edition 1962; after J.S.Clark ""Remeasurement of the Old Length Standards""; Empire Survey Review no. 90; 1953.",OGP,2000/05/07,1997.233 1999.990,0
-9062,British chain (Benoit 1895 B),length,9001,792,39.370113,Uses Benoit's 1895 British yard-metre ratio as given by Bomford as 39.370113 inches per metre.  Used in West Malaysian mapping.,"G. Bomford ""Geodesy"" 2nd edition 1962; after J.S.Clark ""Remeasurement of the Old Length Standards""; Empire Survey Review no. 90; 1953.",OGP,2000/05/07,1997.233 1999.990,0
-9063,British link (Benoit 1895 B),length,9001,7.92,39.370113,Uses Benoit's 1895 British yard-metre ratio as given by Bomford as 39.370113 inches per metre.  Used in West Malaysian mapping.,"G. Bomford; ""Geodesy""; 3rd edition 1975",OGP,2000/05/07,1997.233 1999.990,0
-9070,British foot (1865),length,9001,0.9144025,3,Uses Clark's estimate of 1853-1865 British foot-metre ratio of 0.9144025 metres per yard.  Used in 1962 and 1975 estimates of Indian foot.,"J.S.Clark; ""Remeasurement of the Old Length Standards""; Empire Survey Review no. 90; 1953.",OGP,2000/05/07,1997.233 1999.990,0
-9080,Indian foot,length,9001,12,39.370142,Indian Foot = 0.99999566 British feet (A.R.Clarke 1865).  British yard (= 3 British feet) taken to be J.S.Clark's 1865 value of 0.9144025 metres.,"G. Bomford; ""The Re-adjustment of the Indian Triangulation""; Survey of India Professional Paper 28; 1939.",OGP,2000/05/07,1997.231 1999.990,0
-9081,Indian foot (1937),length,9001,0.30479841,1,Indian Foot = 0.99999566 British feet (A.R.Clarke 1865).  British foot taken to be 1895 Benoit value of 12/39.370113m.  Rounded to 8 decimal places as 0.30479841. Used from Bangladesh to Vietnam.  Previously used in India and Pakistan but superseded.,"G. Bomford; ""The Re-adjustment of the Indian Triangulation""; Survey of India Professional Paper 28; 1939.",OGP,2000/05/07,1997.231 1999.990,0
-9082,Indian foot (1962),length,9001,0.3047996,1,Indian Foot = 0.99999566 British feet (A.R.Clarke 1865).  British yard (3 feet) taken to be J.S. Clark's 1865 value of 0.9144025m. Rounded to 7 significant figures with a small error as 1 Ind ft=0.3047996m.  Used in Pakistan since metrication.,"G. Bomford; ""Geodesy""; 2nd edition 1962",OGP,2007/01/25,1997.231 1999.990 2007.011,0
-9083,Indian foot (1975),length,9001,0.3047995,1,Indian Foot = 0.99999566 British feet (A.R.Clarke 1865).  British yard (3 feet) taken to be J.S. Clark's 1865 value of 0.9144025m. Rounded to 7 significant figures as 1 Ind ft=0.3047995m.  Used in India since metrication.,"G. Bomford; ""Geodesy""; 3rd edition 1975",OGP,2007/01/25,1997.231 1999.990 2007.011,0
-9084,Indian yard,length,9001,36,39.370142,Indian Foot = 0.99999566 British feet (A.R.Clarke 1865).  British yard (= 3 British feet) taken to be J.S.Clark's 1865 value of 0.9144025 metres.,"G. Bomford; ""The Re-adjustment of the Indian Triangulation""; Survey of India Professional Paper 28; 1939.",OGP,2000/05/07,1997.231 1999.990,0
-9085,Indian yard (1937),length,9001,0.91439523,1,Indian Foot = 0.99999566 British feet (A.R.Clarke 1865).  British foot taken to be 1895 Benoit value of 12/39.370113m.  Rounded to 8 decimal places as 0.30479841. Used from Bangladesh to Vietnam.  Previously used in India and Pakistan but superseded.,"G. Bomford; ""The Re-adjustment of the Indian Triangulation""; Survey of India Professional Paper 28; 1939.",OGP,2000/05/07,1997.231 1999.990,0
-9086,Indian yard (1962),length,9001,0.9143988,1,Indian Foot = 0.99999566 British feet (A.R.Clarke 1865).  British yard (3 feet) taken to be J.S. Clark's 1865 value of 0.9144025m. Rounded to 7 significant figures with a small error as 1 Ind ft=0.3047996m.  Used in Pakistan since metrication.,"G. Bomford; ""Geodesy""; 2nd edition 1962",OGP,2007/01/25,1997.231 1999.990 2007.011,0
-9087,Indian yard (1975),length,9001,0.9143985,1,Indian Foot = 0.99999566 British feet (A.R.Clarke 1865).  British yard (3 feet) taken to be J.S. Clark's 1865 value of 0.9144025m. Rounded to 7 significant figures as 1 Ind ft=0.3047995m.  Used in India since metrication.,"G. Bomford; ""Geodesy""; 3rd edition 1975",OGP,2007/01/25,1997.231 1999.990 2007.011,0
-9093,Statute mile,length,9001,1609.344,1,=5280 feet,OGP,OGP,2000/03/07,,0
-9094,Gold Coast foot,length,9001,6378300,20926201,"Used in Ghana and some adjacent parts of British west Africa prior to metrication, except for the metrication of projection defining parameters when British foot (Sears 1922) used.",Ordnance Survey International,OGP,2001/01/21,2000.861,0
+1043,arc-seconds per year,angle,1035,3.14159265358979,20448887688360,"=((pi/180) / 3600) radians per year. Year taken to be IUGS definition of 31556925.445 seconds; see UoM code 1029.",,IOGP,2015/03/06,2013.021 2013.042 2015.014,0
+9001,metre,length,9001,1,1,Also known as International metre. SI standard unit.,ISO 1000.,IOGP,2015/11/25,2015.062,0
+9002,foot,length,9001,0.3048,1,,"ISO 1000; 1958",IOGP,2015/11/25,2015.062,0
+9003,US survey foot,length,9001,12,39.37,Used in USA.,OGP,IOGP,2015/11/25,1999.990 2015.062,0
+9005,Clarke's foot,length,9001,0.3047972654,1,"Assumes Clarke's 1865 ratio of 1 British foot = 0.3047972654 French legal metres applies to the international metre.   Used in older Australian, southern African & British West Indian mapping.",Australian Land Information Group  www.auslig.gov.au,IOGP,2015/11/25,1997.233 1999.990 2000.050 2005.370 2005.460 2015.062,0
+9014,fathom,length,9001,1.8288,1,= 6 feet.,,IOGP,2015/11/25,2015.062,0
+9030,nautical mile,length,9001,1852,1,,,IOGP,2015/11/25,1996.240 2015.062,0
+9031,German legal metre,length,9001,1.0000135965,1,Used in Namibia.,"Chief Directorate Surveys and Land Information; Mowbray; South Africa",IOGP,2015/11/25,2015.062,0
+9033,US survey chain,length,9001,792,39.37,Used in USA primarily for public lands cadastral work.,Bureau of Land Management technical bulletin 6 (1973) and Standard Field Tables 8th edition (1956).,IOGP,2015/11/25,1999.990 2015.062,0
+9034,US survey link,length,9001,7.92,39.37,Used in USA primarily for public lands cadastral work.,Bureau of Land Management technical bulletin 6 (1973) and Standard Field Tables 8th edition (1956).,IOGP,2015/11/25,1999.990 2015.062,0
+9035,US survey mile,length,9001,63360,39.37,Used in USA primarily for public lands cadastral work.,Bureau of Land Management technical bulletin 6 (1973) and Standard Field Tables 8th edition (1956).,IOGP,2015/11/25,1999.990 2015.062,0
+9036,kilometre,length,9001,1000,1,,ISO 1000.,IOGP,2015/11/25,2015.062,0
+9037,Clarke's yard,length,9001,0.9143917962,1,"=3 Clarke's feet.  Assumes Clarke's 1865 ratio of 1 British foot = 0.3047972654 French legal metres applies to the international metre.   Used in older Australian, southern African & British West Indian mapping.",Australian Land Information Group  www.auslig.gov.au,IOGP,2015/11/25,1997.233 1999.990 2005.370 2005.460 2015.062,0
+9038,Clarke's chain,length,9001,20.1166195164,1,"=22 Clarke's yards.  Assumes Clarke's 1865 ratio of 1 British foot = 0.3047972654 French legal metres applies to the international metre.   Used in older Australian, southern African & British West Indian mapping.",Australian Land Information Group  www.auslig.gov.au,IOGP,2015/11/25,1997.233 1999.990 2005.370 2005.460 2015.062,0
+9039,Clarke's link,length,9001,0.201166195164,1,"=1/100 Clarke's chain. Assumes Clarke's 1865 ratio of 1 British foot = 0.3047972654 French legal metres applies to the international metre.   Used in older Australian, southern African & British West Indian mapping.",Australian Land Information Group  www.auslig.gov.au,IOGP,2015/11/25,1997.233 1999.990 2005.370 2005.460 2015.062,0
+9040,British yard (Sears 1922),length,9001,36,39.370147,Uses Sear's 1922 British yard-metre ratio as given by Bomford as 39.370147 inches per metre.  Used in East Malaysian and older New Zealand mapping.,"G. Bomford ""Geodesy"" 2nd edition 1962; after J.S.Clark ""Remeasurement of the Old Length Standards""; Empire Survey Review no. 90; 1953.",IOGP,2015/11/25,1997.233 1999.990 2015.062,0
+9041,British foot (Sears 1922),length,9001,12,39.370147,Uses Sear's 1922 British yard-metre ratio as given by Bomford as 39.370147 inches per metre.  Used in East Malaysian and older New Zealand mapping.,"G. Bomford ""Geodesy"" 2nd edition 1962; after J.S.Clark ""Remeasurement of the Old Length Standards""; Empire Survey Review no. 90; 1953.",IOGP,2015/11/25,1997.233 1999.990 2015.062,0
+9042,British chain (Sears 1922),length,9001,792,39.370147,Uses Sear's 1922 British yard-metre ratio as given by Bomford as 39.370147 inches per metre.  Used in East Malaysian and older New Zealand mapping.,"G. Bomford ""Geodesy"" 2nd edition 1962; after J.S.Clark ""Remeasurement of the Old Length Standards""; Empire Survey Review no. 90; 1953.",IOGP,2015/11/25,1997.233 1999.990 2015.062,0
+9043,British link (Sears 1922),length,9001,7.92,39.370147,Uses Sear's 1922 British yard-metre ratio as given by Bomford as 39.370147 inches per metre.  Used in East Malaysian and older New Zealand mapping.,"G. Bomford ""Geodesy"" 2nd edition 1962; after J.S.Clark ""Remeasurement of the Old Length Standards""; Empire Survey Review no. 90; 1953.",IOGP,2015/11/25,1997.233 1999.990 2015.062,0
+9050,British yard (Benoit 1895 A),length,9001,0.9143992,1,Uses Benoit's 1895 British yard-metre ratio as given by Clark as 0.9143992 metres per yard.  Used for deriving metric size of ellipsoid in Palestine.,"J.S.Clark; ""Remeasurement of the Old Length Standards""; Empire Survey Review no. 90; 1953.",IOGP,2015/11/25,1997.233 1999.990 2006.260 2015.062,0
+9051,British foot (Benoit 1895 A),length,9001,0.9143992,3,Uses Benoit's 1895 British yard-metre ratio as given by Clark as 0.9143992 metres per yard.  Used for deriving metric size of ellipsoid in Palestine.,"J.S.Clark; ""Remeasurement of the Old Length Standards""; Empire Survey Review no. 90; 1953.",IOGP,2015/11/25,1997.233 1999.990 2006.260 2015.062,0
+9052,British chain (Benoit 1895 A),length,9001,20.1167824,1,Uses Benoit's 1895 British yard-metre ratio as given by Clark as 0.9143992 metres per yard.  Used for deriving metric size of ellipsoid in Palestine.,"J.S.Clark; ""Remeasurement of the Old Length Standards""; Empire Survey Review no. 90; 1953.",IOGP,2015/11/25,1997.233 1999.990 2006.260 2015.062,0
+9053,British link (Benoit 1895 A),length,9001,0.201167824,1,Uses Benoit's 1895 British yard-metre ratio as given by Clark as 0.9143992 metres per yard.  Used for deriving metric size of ellipsoid in Palestine.,"J.S.Clark; ""Remeasurement of the Old Length Standards""; Empire Survey Review no. 90; 1953.",IOGP,2015/11/25,1997.233 1999.990 2006.260 2015.062,0
+9060,British yard (Benoit 1895 B),length,9001,36,39.370113,"G. Bomford ""Geodesy"" 2nd edition 1962; after J.S.Clark ""Remeasurement of the Old Length Standards""; Empire Survey Review no. 90; 1953.","G. Bomford ""Geodesy"" 2nd edition 1962; after J.S.Clark ""Remeasurement of the Old Length Standards""; Empire Survey Review no. 90; 1953.",IOGP,2015/11/25,1997.233 1999.990 2015.062,0
+9061,British foot (Benoit 1895 B),length,9001,12,39.370113,Uses Benoit's 1895 British yard-metre ratio as given by Bomford as 39.370113 inches per metre.  Used in West Malaysian mapping.,"G. Bomford ""Geodesy"" 2nd edition 1962; after J.S.Clark ""Remeasurement of the Old Length Standards""; Empire Survey Review no. 90; 1953.",IOGP,2015/11/25,1997.233 1999.990 2015.062,0
+9062,British chain (Benoit 1895 B),length,9001,792,39.370113,Uses Benoit's 1895 British yard-metre ratio as given by Bomford as 39.370113 inches per metre.  Used in West Malaysian mapping.,"G. Bomford ""Geodesy"" 2nd edition 1962; after J.S.Clark ""Remeasurement of the Old Length Standards""; Empire Survey Review no. 90; 1953.",IOGP,2015/11/25,1997.233 1999.990 2015.062,0
+9063,British link (Benoit 1895 B),length,9001,7.92,39.370113,Uses Benoit's 1895 British yard-metre ratio as given by Bomford as 39.370113 inches per metre.  Used in West Malaysian mapping.,"G. Bomford; ""Geodesy""; 3rd edition 1975",IOGP,2015/11/25,1997.233 1999.990 2015.062,0
+9070,British foot (1865),length,9001,0.9144025,3,Uses Clark's estimate of 1853-1865 British foot-metre ratio of 0.9144025 metres per yard.  Used in 1962 and 1975 estimates of Indian foot.,"J.S.Clark; ""Remeasurement of the Old Length Standards""; Empire Survey Review no. 90; 1953.",IOGP,2015/11/25,1997.233 1999.990 2015.062,0
+9080,Indian foot,length,9001,12,39.370142,Indian Foot = 0.99999566 British feet (A.R.Clarke 1865).  British yard (= 3 British feet) taken to be J.S.Clark's 1865 value of 0.9144025 metres.,"G. Bomford; ""The Re-adjustment of the Indian Triangulation""; Survey of India Professional Paper 28; 1939.",IOGP,2015/11/25,1997.231 1999.990 2015.062,0
+9081,Indian foot (1937),length,9001,0.30479841,1,Indian Foot = 0.99999566 British feet (A.R.Clarke 1865).  British foot taken to be 1895 Benoit value of 12/39.370113m.  Rounded to 8 decimal places as 0.30479841. Used from Bangladesh to Vietnam.  Previously used in India and Pakistan but superseded.,"G. Bomford; ""The Re-adjustment of the Indian Triangulation""; Survey of India Professional Paper 28; 1939.",IOGP,2015/11/25,1997.231 1999.990 2015.062,0
+9082,Indian foot (1962),length,9001,0.3047996,1,Indian Foot = 0.99999566 British feet (A.R.Clarke 1865).  British yard (3 feet) taken to be J.S. Clark's 1865 value of 0.9144025m. Rounded to 7 significant figures with a small error as 1 Ind ft=0.3047996m.  Used in Pakistan since metrication.,"G. Bomford; ""Geodesy""; 2nd edition 1962",IOGP,2015/11/25,1997.231 1999.990 2007.011 2015.062,0
+9083,Indian foot (1975),length,9001,0.3047995,1,Indian Foot = 0.99999566 British feet (A.R.Clarke 1865).  British yard (3 feet) taken to be J.S. Clark's 1865 value of 0.9144025m. Rounded to 7 significant figures as 1 Ind ft=0.3047995m.  Used in India since metrication.,"G. Bomford; ""Geodesy""; 3rd edition 1975",IOGP,2015/11/25,1997.231 1999.990 2007.011 2015.062,0
+9084,Indian yard,length,9001,36,39.370142,Indian Foot = 0.99999566 British feet (A.R.Clarke 1865).  British yard (= 3 British feet) taken to be J.S.Clark's 1865 value of 0.9144025 metres.,"G. Bomford; ""The Re-adjustment of the Indian Triangulation""; Survey of India Professional Paper 28; 1939.",IOGP,2015/11/25,1997.231 1999.990 2015.062,0
+9085,Indian yard (1937),length,9001,0.91439523,1,Indian Foot = 0.99999566 British feet (A.R.Clarke 1865).  British foot taken to be 1895 Benoit value of 12/39.370113m.  Rounded to 8 decimal places as 0.30479841. Used from Bangladesh to Vietnam.  Previously used in India and Pakistan but superseded.,"G. Bomford; ""The Re-adjustment of the Indian Triangulation""; Survey of India Professional Paper 28; 1939.",IOGP,2015/11/25,1997.231 1999.990 2015.062,0
+9086,Indian yard (1962),length,9001,0.9143988,1,Indian Foot = 0.99999566 British feet (A.R.Clarke 1865).  British yard (3 feet) taken to be J.S. Clark's 1865 value of 0.9144025m. Rounded to 7 significant figures with a small error as 1 Ind ft=0.3047996m.  Used in Pakistan since metrication.,"G. Bomford; ""Geodesy""; 2nd edition 1962",IOGP,2015/11/25,1997.231 1999.990 2007.011 2015.062,0
+9087,Indian yard (1975),length,9001,0.9143985,1,Indian Foot = 0.99999566 British feet (A.R.Clarke 1865).  British yard (3 feet) taken to be J.S. Clark's 1865 value of 0.9144025m. Rounded to 7 significant figures as 1 Ind ft=0.3047995m.  Used in India since metrication.,"G. Bomford; ""Geodesy""; 3rd edition 1975",IOGP,2015/11/25,1997.231 1999.990 2007.011 2015.062,0
+9093,Statute mile,length,9001,1609.344,1,=5280 feet,OGP,IOGP,2015/11/25,2015.062,0
+9094,Gold Coast foot,length,9001,6378300,20926201,"Used in Ghana and some adjacent parts of British west Africa prior to metrication, except for the metrication of projection defining parameters when British foot (Sears 1922) used.",Ordnance Survey International,IOGP,2015/11/25,2000.861 2015.062,0
 9095,British foot (1936),length,9001,0.3048007491,1,For the 1936 retriangulation OSGB defines the relationship of 10 feet of 1796 to the International metre through the logarithmic relationship (10^0.48401603 exactly). 1 ft = 0.3048007491…m. Also used for metric conversions in Ireland.,"1. ""The Retriangulation of Great Britain"", Ordnance Survey of Great Britain.
-2. ""The Irish Grid - A Description of the Co-ordinate Reference System"" published by Ordnance Survey of Ireland, Dublin and Ordnance Survey of Northern Ireland, Belfast.",OGP,2006/11/27,2002.621 2006.932,0
-9096,yard,length,9001,0.9144,1,=3 international feet.,OGP,OGP,2006/07/14,,0
-9097,chain,length,9001,20.1168,1,=22 international yards or 66 international feet.,OGP,OGP,2006/07/14,,0
-9098,link,length,9001,20.1168,100,=1/100 international chain.,OGP,OGP,2006/07/14,,0
-9099,British yard (Sears 1922 truncated),length,9001,0.914398,1,Uses Sear's 1922 British yard-metre ratio (UoM code 9040) truncated to 6 significant figures.,Defence Geographic Centre,OGP,2006/10/23,2006.901,0
-9101,radian,angle,9101,1,1,SI standard unit.,ISO 1000:1992,OGP,1995/06/02,,0
-9102,degree,angle,9101,3.14159265358979,180,= pi/180 radians,,OGP,2002/11/18,1996.220 2002.860,0
-9103,arc-minute,angle,9101,3.14159265358979,10800,1/60th degree = ((pi/180) / 60) radians,,OGP,2002/11/18,1996.220 2002.860,0
-9104,arc-second,angle,9101,3.14159265358979,648000,1/60th arc-minute = ((pi/180) / 3600) radians,,OGP,2002/11/18,1996.220 2002.860,0
-9105,grad,angle,9101,3.14159265358979,200,=pi/200 radians.,,OGP,2002/11/18,1996.220 1999.050 2002.860,0
-9106,gon,angle,9101,3.14159265358979,200,=pi/200 radians,,OGP,2002/11/18,1996.220 2002.860,0
-9107,degree minute second,angle,9102,,,"Degree representation. Format: signed degrees (integer) - arc-minutes (integer) - arc-seconds (real, any precision). Different symbol sets are in use as field separators, for example º ' "". Convert to degrees using algorithm.",OGP,OGP,2002/11/22,1996.190 2002.070 2002.780,0
-9108,degree minute second hemisphere,angle,9102,,,"Degree representation. Format: degrees (integer) - arc-minutes (integer) - arc-seconds (real) - hemisphere abbreviation (single character N S E or W). Different symbol sets are in use as field separators for example º ' "". Convert to deg using algorithm.",OGP,OGP,2002/11/22,1996.190 2002.070 2002.780,0
+2. ""The Irish Grid - A Description of the Co-ordinate Reference System"" published by Ordnance Survey of Ireland, Dublin and Ordnance Survey of Northern Ireland, Belfast.",IOGP,2015/11/25,2002.621 2006.932 2015.062,0
+9096,yard,length,9001,0.9144,1,=3 international feet.,OGP,IOGP,2015/11/25,2015.062,0
+9097,chain,length,9001,20.1168,1,=22 international yards or 66 international feet.,OGP,IOGP,2015/11/25,2015.062,0
+9098,link,length,9001,20.1168,100,=1/100 international chain.,OGP,IOGP,2015/11/25,2015.062,0
+9099,British yard (Sears 1922 truncated),length,9001,0.914398,1,Uses Sear's 1922 British yard-metre ratio (UoM code 9040) truncated to 6 significant figures.,Defence Geographic Centre,IOGP,2015/11/25,2006.901 2015.062,0
+9101,radian,angle,9101,1,1,SI standard unit.,ISO 1000:1992,IOGP,2015/11/25,2015.062,0
+9102,degree,angle,9101,3.14159265358979,180,= pi/180 radians,,IOGP,2015/11/25,1996.220 2002.860 2015.062,0
+9103,arc-minute,angle,9101,3.14159265358979,10800,1/60th degree = ((pi/180) / 60) radians,,IOGP,2015/11/25,1996.220 2002.860 2015.062,0
+9104,arc-second,angle,9101,3.14159265358979,648000,1/60th arc-minute = ((pi/180) / 3600) radians,,IOGP,2015/11/25,1996.220 2002.860 2015.062,0
+9105,grad,angle,9101,3.14159265358979,200,=pi/200 radians.,OGP,IOGP,2015/11/25,1996.220 1999.050 2002.860 2015.062,0
+9106,gon,angle,9101,3.14159265358979,200,=pi/200 radians,,OGP,2002/11/18,1996.220 2002.860 2015.062,1
+9107,degree minute second,angle,9102,,,"Degree representation. Format: signed degrees (integer) - arc-minutes (integer) - arc-seconds (real, any precision). Different symbol sets are in use as field separators, for example º ' "". Convert to degrees using algorithm.",OGP,IOGP,2015/11/25,1996.190 2002.070 2002.780 2015.062,0
+9108,degree minute second hemisphere,angle,9102,,,"Degree representation. Format: degrees (integer) - arc-minutes (integer) - arc-seconds (real) - hemisphere abbreviation (single character N S E or W). Different symbol sets are in use as field separators for example º ' "". Convert to deg using algorithm.",OGP,IOGP,2015/11/25,1996.190 2002.070 2002.780 2015.062,0
 9109,microradian,angle,9101,1,1000000,rad * 10E-6,ISO 1000.,OGP,1996/10/18,1999.050,0
-9110,sexagesimal DMS,angle,9102,,,Pseudo unit. Format: signed degrees - period - minutes (2 digits) - integer seconds (2 digits) - fraction of seconds (any precision). Must include leading zero in minutes and seconds and exclude decimal point for seconds. Convert to degree using formula.,OGP,OGP,2008/03/26,2002.270 2002.780 2008.020,0
-9111,sexagesimal DM,angle,9102,,,Pseudo unit. Format: sign - degrees - decimal point - integer minutes (two digits) - fraction of minutes (any precision).  Must include leading zero in integer minutes.  Must exclude decimal point for minutes.  Convert to deg using algorithm.,OGP,OGP,2002/11/22,2002.070 2002.780,0
-9112,centesimal minute,angle,9101,3.14159265358979,20000,1/100 of a grad and gon = ((pi/200) / 100) radians,http://www.geodesy.matav.hu/,OGP,2005/09/06,1998.480 1999.510 2002.860 2005.460,0
-9113,centesimal second,angle,9101,3.14159265358979,2000000,"1/100 of a centesimal minute or 1/10,000th of a grad and gon = ((pi/200) / 10000) radians",http://www.geodesy.matav.hu/,OGP,2005/09/06,1999.510 2002.860 2005.460,0
-9114,mil_6400,angle,9101,3.14159265358979,3200,Angle subtended by 1/6400 part of a circle.  Approximates to 1/1000th radian.  Note that other approximations (notably 1/6300 circle and 1/6000 circle) also exist.,http://www.geodesy.matav.hu/,OGP,2005/09/06,1999.510 2005.460,0
-9115,degree minute,angle,9102,,,"Degree representation. Format: signed degrees (integer)  - arc-minutes (real, any precision). Different symbol sets are in use as field separators, for example º '. Convert to degrees using algorithm.",OGP,OGP,2002/11/22,2002.780,0
-9116,degree hemisphere,angle,9102,,,"Degree representation. Format: degrees (real, any precision) - hemisphere abbreviation (single character N S E or W). Convert to degrees using algorithm.",OGP,OGP,2002/11/22,,0
-9117,hemisphere degree,angle,9102,,,"Degree representation. Format: hemisphere abbreviation (single character N S E or W) - degrees (real, any precision). Convert to degrees using algorithm.",OGP,OGP,2002/11/22,,0
-9118,degree minute hemisphere,angle,9102,,,"Degree representation. Format: degrees (integer) - arc-minutes (real, any precision) - hemisphere abbreviation (single character N S E or W). Different symbol sets are in use as field separators, for example º '. Convert to degrees using algorithm.",OGP,OGP,2002/11/22,,0
-9119,hemisphere degree minute,angle,9102,,,"Degree representation. Format:  hemisphere abbreviation (single character N S E or W) - degrees (integer) - arc-minutes (real, any precision). Different symbol sets are in use as field separators, for example º '. Convert to degrees using algorithm.",OGP,OGP,2002/11/22,,0
-9120,hemisphere degree minute second,angle,9102,,,"Degree representation. Format: hemisphere abbreviation (single character N S E or W) - degrees (integer) - arc-minutes (integer) - arc-seconds (real). Different symbol sets are in use as field separators for example º ' "". Convert to deg using algorithm.",OGP,OGP,2002/11/22,,0
-9121,sexagesimal DMS.s,angle,9102,,,"Pseudo unit. Format: signed degrees - minutes (two digits) - seconds (real, any precision). Must include leading zero in minutes and seconds where value is under 10 and include decimal separator for seconds. Convert to degree using algorithm.",ISO 6709:1983.,OGP,2002/11/22,,0
-9122,degree (supplier to define representation),angle,9101,3.14159265358979,180,"= pi/180 radians. The degree representation (e.g. decimal, DMSH, etc.) must be clarified by suppliers of data associated with this code.",OGP,OGP,2004/01/05,,0
-9201,unity,scale,9201,1,1,,,OGP,1996/09/12,,0
-9202,parts per million,scale,9201,1,1000000,,,OGP,2013/07/26,2013.021 2013.037,0
+9110,sexagesimal DMS,angle,9102,,,Pseudo unit. Format: signed degrees - period - minutes (2 digits) - integer seconds (2 digits) - fraction of seconds (any precision). Must include leading zero in minutes and seconds and exclude decimal point for seconds. Convert to degree using formula.,OGP,IOGP,2015/11/25,2002.270 2002.780 2008.020 2015.062,0
+9111,sexagesimal DM,angle,9102,,,Pseudo unit. Format: sign - degrees - decimal point - integer minutes (two digits) - fraction of minutes (any precision).  Must include leading zero in integer minutes.  Must exclude decimal point for minutes.  Convert to deg using algorithm.,OGP,IOGP,2015/11/25,2002.070 2002.780 2015.062,0
+9112,centesimal minute,angle,9101,3.14159265358979,20000,1/100 of a grad and gon = ((pi/200) / 100) radians,http://www.geodesy.matav.hu/,IOGP,2015/11/25,1998.480 1999.510 2002.860 2005.460 2015.062,0
+9113,centesimal second,angle,9101,3.14159265358979,2000000,"1/100 of a centesimal minute or 1/10,000th of a grad and gon = ((pi/200) / 10000) radians",http://www.geodesy.matav.hu/,IOGP,2015/11/25,1999.510 2002.860 2005.460 2015.062,0
+9114,mil_6400,angle,9101,3.14159265358979,3200,Angle subtended by 1/6400 part of a circle.  Approximates to 1/1000th radian.  Note that other approximations (notably 1/6300 circle and 1/6000 circle) also exist.,http://www.geodesy.matav.hu/,IOGP,2015/11/25,1999.510 2005.460 2015.062,0
+9115,degree minute,angle,9102,,,"Degree representation. Format: signed degrees (integer)  - arc-minutes (real, any precision). Different symbol sets are in use as field separators, for example º '. Convert to degrees using algorithm.",OGP,IOGP,2015/11/25,2002.780 2015.062,0
+9116,degree hemisphere,angle,9102,,,"Degree representation. Format: degrees (real, any precision) - hemisphere abbreviation (single character N S E or W). Convert to degrees using algorithm.",OGP,IOGP,2015/11/25,2015.062,0
+9117,hemisphere degree,angle,9102,,,"Degree representation. Format: hemisphere abbreviation (single character N S E or W) - degrees (real, any precision). Convert to degrees using algorithm.",OGP,IOGP,2015/11/25,2015.062,0
+9118,degree minute hemisphere,angle,9102,,,"Degree representation. Format: degrees (integer) - arc-minutes (real, any precision) - hemisphere abbreviation (single character N S E or W). Different symbol sets are in use as field separators, for example º '. Convert to degrees using algorithm.",OGP,IOGP,2015/11/25,2015.062,0
+9119,hemisphere degree minute,angle,9102,,,"Degree representation. Format:  hemisphere abbreviation (single character N S E or W) - degrees (integer) - arc-minutes (real, any precision). Different symbol sets are in use as field separators, for example º '. Convert to degrees using algorithm.",OGP,IOGP,2015/11/25,2015.062,0
+9120,hemisphere degree minute second,angle,9102,,,"Degree representation. Format: hemisphere abbreviation (single character N S E or W) - degrees (integer) - arc-minutes (integer) - arc-seconds (real). Different symbol sets are in use as field separators for example º ' "". Convert to deg using algorithm.",OGP,IOGP,2015/11/25,2015.062,0
+9121,sexagesimal DMS.s,angle,9102,,,"Pseudo unit. Format: signed degrees - minutes (two digits) - seconds (real, any precision). Must include leading zero in minutes and seconds where value is under 10 and include decimal separator for seconds. Convert to degree using algorithm.",ISO 6709:1983.,IOGP,2015/11/25,2015.062,0
+9122,degree (supplier to define representation),angle,9101,3.14159265358979,180,"= pi/180 radians. The degree representation (e.g. decimal, DMSH, etc.) must be clarified by suppliers of data associated with this code.",OGP,IOGP,2015/11/25,2015.062,0
+9201,unity,scale,9201,1,1,,,IOGP,2015/11/25,2015.062,0
+9202,parts per million,scale,9201,1,1000000,,,IOGP,2015/11/25,2013.021 2013.037 2015.062,0
 9203,coefficient,scale,9201,1,1,Used when parameters are coefficients.  They inherently take the units which depend upon the term to which the coefficient applies.,OGP,OGP,2004/09/14,2004.530,0
 9204,Bin width 330 US survey feet,length,9001,3960,39.37,,OGP,OGP,2000/10/19,2000.590 2011.106,1
 9205,Bin width 165 US survey feet,length,9001,1980,39.37,,OGP,OGP,2000/10/19,2000.590 2011.106,1
@@ -94,6 +89,6 @@ uom_code,unit_of_meas_name,unit_of_meas_type,target_uom_code,factor_b,factor_c,r
 9209,Bin width 12.5 metres,length,9001,12.5,1,,OGP,OGP,2000/10/19,2000.590 2011.106,1
 9210,Bin width 6.25 metres,length,9001,6.25,1,,OGP,OGP,2000/10/19,2000.590 2011.106,1
 9211,Bin width 3.125 metres,length,9001,3.125,1,,OGP,OGP,2000/10/19,2000.590 2011.106,1
-9300,British foot (Sears 1922 truncated),length,9001,0.914398,3,"Uses Sear's 1922 British yard-metre ratio (UoM code 9040) truncated to 6 significant figures; this truncated ratio (0.914398, UoM code 9099) then converted to other imperial units. 3 ftSe(T) = 1 ydSe(T).",Defence Geographic Centre,OGP,2006/10/23,2006.901,0
-9301,British chain (Sears 1922 truncated),length,9001,20.116756,1,"Uses Sear's 1922 British yard-metre ratio (UoM code 9040) truncated to 6 significant figures; this truncated ratio (0.914398, UoM code 9099) then converted to other imperial units. 1 chSe(T) = 22 ydSe(T). Used in metrication of Malaya RSO grid.",Defence Geographic Centre,OGP,2006/10/23,2006.901,0
-9302,British link (Sears 1922 truncated),length,9001,20.116756,100,"Uses Sear's 1922 British yard-metre ratio (UoM code 9040) truncated to 6 significant figures; this truncated ratio (0.914398, UoM code 9099) then converted to other imperial units. 100 lkSe(T) = 1 chSe(T).",Defence Geographic Centre,OGP,2006/10/23,2006.901,0
+9300,British foot (Sears 1922 truncated),length,9001,0.914398,3,"Uses Sear's 1922 British yard-metre ratio (UoM code 9040) truncated to 6 significant figures; this truncated ratio (0.914398, UoM code 9099) then converted to other imperial units. 3 ftSe(T) = 1 ydSe(T).",Defence Geographic Centre,IOGP,2015/11/25,2006.901 2015.062,0
+9301,British chain (Sears 1922 truncated),length,9001,20.116756,1,"Uses Sear's 1922 British yard-metre ratio (UoM code 9040) truncated to 6 significant figures; this truncated ratio (0.914398, UoM code 9099) then converted to other imperial units. 1 chSe(T) = 22 ydSe(T). Used in metrication of Malaya RSO grid.",Defence Geographic Centre,IOGP,2015/11/25,2006.901 2015.062,0
+9302,British link (Sears 1922 truncated),length,9001,20.116756,100,"Uses Sear's 1922 British yard-metre ratio (UoM code 9040) truncated to 6 significant figures; this truncated ratio (0.914398, UoM code 9099) then converted to other imperial units. 100 lkSe(T) = 1 chSe(T).",Defence Geographic Centre,IOGP,2015/11/25,2006.901 2015.062,0
diff --git a/data/vdv452.xml b/data/vdv452.xml
new file mode 100644
index 0000000..d010fa0
--- /dev/null
+++ b/data/vdv452.xml
@@ -0,0 +1,367 @@
+<?xml version="1.0"?>
+<!--
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL
+ * Purpose:  Description of VDV-452 layers and fields
+ * Author:   Even Rouault, <even.rouault at spatialys.com>
+ *
+ **********************************************************************
+ * Copyright (c) 2015, Even Rouault
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+-->
+<Layers>
+
+    <Layer name_en="BASE_VERSION_VALID" name_de="BASIS_VER_GUELTIGKEIT" num="993">
+        <Field name_en="BASE_VERSION_VALID" name_de="VER_GUELTIGKEIT" type="num" width="8" cond=">0"/>
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+    </Layer>
+
+    <Layer name_en="BASE_VERSION" name_de="MENGE_BASIS_VERSIONEN" num="485">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="BASE_VERSION_DESC" name_de="BASIS_VERSION_TEXT" type="char" width="40"/>
+    </Layer>
+
+    <Layer name_en="PERIOD" name_de="FIRMENKALENDER" num="348">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="OPERATING_DAY" name_de="BETRIEBSTAG" type="num" width="8" cond=">0"/>
+        <Field name_en="OPERATING_DAY_DESC" name_de="BETRIEBSTAG_TEXT" type="char" width="40"/>
+        <Field name_en="DAY_TYPE_NO" name_de="TAGESART_NR" type="num" width="3" cond="1-999"/>
+    </Layer>
+
+    <Layer name_en="DAY_TYPE" name_de="MENGE_TAGESART" num="290">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="DAY_TYPE_NO" name_de="TAGESART_NR" type="num" width="3" cond="1-999"/>
+        <Field name_en="DAY_TYPE_DESC" name_de="TAGESART_TEXT" type="char" width="40"/>
+    </Layer>
+
+    <Layer name_en="POINT_TYPE" name_de="MENGE_ONR_TYP" num="998">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="POINT_TYPE" name_de="ONR_TYP_NR" type="num" width="2" cond="1-7"/>
+        <Field name_en="POINT_TYPE_ABBR" name_de="STR_ONR_TYP" type="char" width="6"/>
+        <Field name_en="POINT_TYPE_DESC" name_de="ONR_TYP_TEXT" type="char" width="40"/>
+    </Layer>
+
+    <Layer name_en="STOP_TYPE" name_de="MENGE_ORT_TYP" num="997">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="STOP_TYPE" name_de="ORT_TYP_NR" type="num" width="2" cond="1-2"/>
+        <Field name_en="STOP_TYPE_DESC" name_de="ORT_TYP_TEXT" type="char" width="40"/>
+    </Layer>
+
+    <Layer name_en="STOP_POINT" name_de="REC_HP" num="229">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="POINT_TYPE" name_de="ONR_TYP_NR" type="num" width="2" cond="1-7"/>
+        <Field name_en="POINT_NO" name_de="ORT_NR" type="num" width="6" cond=">0"/>
+        <Field name_en="STOP_POINT_NO" name_de="HALTEPUNKT_NR" type="num" width="2" cond="0-99"/>
+        <Field name_en="STOP_POINT_DESC" name_de="ZUSATZ_INFO" type="char" width="40"/>
+    </Layer>
+
+    <Layer name_en="ACTIVATION_POINT" name_de="REC_OM" num="295">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="POINT_TYPE" name_de="ONR_TYP_NR" type="num" width="2" cond="3-4"/>
+        <Field name_en="POINT_NO" name_de="ORT_NR" type="num" width="6" cond=">0"/>
+        <Field name_en="ACT_POINT_ABBR" name_de="ORM_KUERZEL" type="char" width="6"/>
+        <Field name_en="ACT_POINT_CODE" name_de="ORMACODE" type="num" width="5" cond="1-32765"/>
+        <Field name_en="ACT_POINT_DESC" name_de="ORM_TEXT" type="char" width="40"/>
+    </Layer>
+
+    <Layer name_en="STOP" name_de="REC_ORT" num="253">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="POINT_TYPE" name_de="ONR_TYP_NR" type="num" width="2" cond="1-7"/>
+        <Field name_en="POINT_NO" name_de="ORT_NR" type="num" width="6" cond=">0"/>
+        <Field name_en="POINT_DESC" name_de="ORT_NAME" type="char" width="40"/>
+        <Field name_en="STOP_NO" name_de="ORT_REF_ORT" type="num" width="6" cond=">0"/>
+        <Field name_en="STOP_TYPE" name_de="ORT_REF_ORT_TYP" type="num" width="2" cond="1-2"/>
+        <Field name_en="STOP_LONG_NO" name_de="ORT_REF_ORT_LANGNR" type="num" width="7" cond=">0,NULL"/>
+        <Field name_en="STOP_ABBR" name_de="ORT_REF_ORT_KUERZEL" type="char" width="8"/>
+        <Field name_en="STOP_DESC" name_de="ORT_REF_ORT_NAME" type="char" width="40"/>
+        <Field name_en="ZONE_CELL_NO" name_de="ZONE_WABE_NR" type="num" width="5" cond=">0,NULL"/>
+        <Field name_en="POINT_LONGITUDE" name_de="ORT_POS_LAENGE" type="num" width="10" cond="+/-1800000000"/>
+        <Field name_en="POINT_LATITUDE" name_de="ORT_POS_BREITE" type="num" width="10" cond="+/-900000000"/>
+        <Field name_en="POINT_ELEVATION" name_de="ORT_POS_HOEHE" type="num" width="10"/>
+        <Field name_en="POINT_HEADING" name_de="ORT_RICHTUNG" type="num" width="3" cond="0-359"/>
+        <Field name_en="STOP_NO_LOCAL" name_de="HAST_NR_LOKAL" type="num" width="9" cond=">0"/>
+        <Field name_en="STOP_NO_NATIONAL" name_de="HST_NR_NATIONAL" type="num" width="9" cond=">0"/>
+        <Field name_en="STOP_NO_INTERNATIONAL" name_de="HST_NR_INTERNATIONAL" type="char" width="30"/>
+    </Layer>
+
+    <Layer name_en="VEHICLE" name_de="FAHRZEUG" num="443">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="VEHICLE_NO" name_de="FZG_NR" type="num" width="4" cond=">0"/>
+        <Field name_en="VEHICLE_TYPE" name_de="FZG_TYP_NR" type="num" width="3" cond="1-252,NULL"/>
+        <Field name_en="VEHICLE_REG" name_de="POLKENN" type="char" width="20"/>
+        <Field name_en="COMPANY" name_de="UNTERNEHMEN" type="num" width="3" cond=">0,NULL"/>
+    </Layer>
+
+    <Layer name_en="TRANSPORT_COMPANY" name_de="ZUL_VERKEHRSBETRIEB" num="992">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="COMPANY" name_de="UNTERNEHMEN" type="num" width="3" cond=">0,NULL"/>
+        <Field name_en="COMPANY_ABBR" name_de="ABK_UNTERNEHMEN" type="char" width="6"/>
+        <Field name_en="BUSINESS_AREA_DESC" name_de="BETRIEBSGEBIET_BEZ" type="char" width="40"/>
+    </Layer>
+
+    <Layer name_en="OPERATING_DEPARTMENT" name_de="MENGE_BEREICH" num="333">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="OP_DEP_NO" name_de="BEREICH_NR" type="num" width="3" cond="0-252"/>
+        <Field name_en="OP_DEP_ABBR" name_de="STR_BEREICH" type="char" width="6"/>
+        <Field name_en="OP_DEP_DESC" name_de="BEREICH_TEXT" type="char" width="40"/>
+    </Layer>
+
+    <Layer name_en="VEHICLE_TYPE" name_de="MENGE_FZG_TYP" num="293">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="VH_TYPE_NO" name_de="FZG_TYP_NR" type="num" width="3" cond="1-252"/>
+        <Field name_en="VH_TYPE_LENGTH" name_de="FZG_LAENGE" type="num" width="2" cond=">=0"/>
+        <Field name_en="VH_TYPE_SEAT" name_de="FZG_TYP_SITZ" type="num" width="3" cond=">=0"/>
+        <Field name_en="VH_TYPE_STAND" name_de="FZG_TYP_STEH" type="num" width="3" cond=">=0"/>
+        <Field name_en="VH_TYPE_DESC" name_de="FZG_TYP_TEXT" type="char" width="40"/>
+        <Field name_en="VH_TYPE_SPEC_SEAT" name_de="SONDER_PLATZ" type="num" width="3" cond=">=0"/>
+        <Field name_en="VH_TYPE_ABBR" name_de="STR_FZG_TYP" type="char" width="6"/>
+    </Layer>
+
+    <Layer name_en="ANNOUNCEMENT" name_de="REC_ANR" num="996">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="ANN_NO" name_de="ANR_NR" type="num" width="4" cond="1-9999"/>
+        <Field name_en="ANN_DESC" name_de="ANR_TEXT" type="char" width="200"/>
+    </Layer>
+
+    <Layer name_en="DESTINATION" name_de="REC_ZNR" num="994">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="DEST_NO" name_de="ZNR_NR" type="num" width="4" cond="0-9999"/>
+        <Field name_en="DEST_BRIEF_TEXT" name_de="FAHRERKURZTEXT" type="char" width="44"/>
+        <Field name_en="DEST_SIDE_TEXT" name_de="SEITENTEXT" type="char" width="160"/>
+        <Field name_en="DEST_FRONT_TEXT" name_de="ZNR_TEXT" type="char" width="160"/>
+        <Field name_en="DEST_CODE" name_de="ZNR_CODE" type="char" width="68"/>
+    </Layer>
+
+    <Layer name_en="LINK" name_de="REC_SEL" num="299">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="OP_DEP_NO" name_de="BEREICH_NR" type="num" width="3" cond="0-252"/>
+        <Field name_en="FROM_POINT_TYPE" name_de="ONR_TYP_NR" type="num" width="2" cond="1-2"/>
+        <Field name_en="FROM_POINT_NO" name_de="ORT_NR" type="num" width="6" cond=">0"/>
+        <Field name_en="TO_POINT_NO" name_de="SEL_ZIEL" type="num" width="6" cond=">0"/>
+        <Field name_en="TO_POINT_TYPE" name_de="SEL_ZIEL_TYP" type="num" width="2" cond="1-2"/>
+        <Field name_en="LINK_DISTANCE" name_de="SEL_LAENGE" type="num" width="5" cond="1-81890"/>
+    </Layer>
+
+    <Layer name_en="POINT_ON_LINK" name_de="REC_SEL_ZP" num="995">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="OP_DEP_NO" name_de="BEREICH_NR" type="num" width="3" cond="0-252"/>
+        <Field name_en="FROM_POINT_TYPE" name_de="ONR_TYP_NR" type="num" width="2" cond="1-2"/>
+        <Field name_en="FROM_POINT_NO" name_de="ORT_NR" type="num" width="6" cond=">0"/>
+        <Field name_en="TO_POINT_NO" name_de="SEL_ZIEL" type="num" width="6" cond=">0"/>
+        <Field name_en="TO_POINT_TYPE" name_de="SEL_ZIEL_TYP" type="num" width="2" cond="1-2"/>
+        <Field name_en="POINT_TO_LINK_NO" name_de="ZP_ONR" type="num" width="6" cond=">0"/>
+        <Field name_en="POINT_TO_LINK_TYPE" name_de="ZP_TYP" type="num" width="2" cond="3-7"/>
+        <Field name_en="POINT_TO_DISTANCE" name_de="SEL_ZP_LAENGE" type="num" width="5" cond="1-81890,NULL"/>
+        <Field name_en="POINT_ON_LINK_SERIAL_NO" name_de="ZP_LFD_NR" type="num" width="3" cond=">0,NULL"/>
+    </Layer>
+
+    <Layer name_en="TIMING_GROUP" name_de="MENGE_FGR" num="222">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="TIMING_GROUP_NO" name_de="FGR_NR" type="num" width="9" cond=">0"/>
+        <Field name_en="TIMING_GROUP_DESC" name_de="FGR_TEXT" type="char" width="40"/>
+    </Layer>
+
+    <Layer name_en="WAIT_TIME" name_de="ORT_HZTF" num="999">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="TIMING_GROUP_NO" name_de="FGR_NR" type="num" width="9" cond=">0"/>
+        <Field name_en="POINT_TYPE" name_de="ONR_TYP_NR" type="num" width="2" cond="1-2"/>
+        <Field name_en="POINT_NO" name_de="ORT_NR" type="num" width="6" cond=">0"/>
+        <Field name_en="WAIT_TIME" name_de="HP_HZT" type="num" width="6" cond="0-65532"/>
+    </Layer>
+
+    <Layer name_en="TRAVEL_TIME" name_de="SEL_FZT_FELD" num="282">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="OP_DEP_NO" name_de="BEREICH_NR" type="num" width="3" cond="0-252"/>
+        <Field name_en="TIMING_GROUP_NO" name_de="FGR_NR" type="num" width="9" cond=">0"/>
+        <Field name_en="FROM_POINT_TYPE" name_de="ONR_TYP_NR" type="num" width="2" cond="1-2"/>
+        <Field name_en="FROM_POINT_NO" name_de="ORT_NR" type="num" width="6" cond=">0"/>
+        <Field name_en="TO_POINT_NO" name_de="SEL_ZIEL" type="num" width="6" cond=">0"/>
+        <Field name_en="TO_POINT_TYPE" name_de="SEL_ZIEL_TYP" type="num" width="2" cond="1-2"/>
+        <Field name_en="TRAVEL_TIME" name_de="SEL_FZT" type="num" width="6" cond="0-65532"/>
+    </Layer>
+
+    <Layer name_en="DEAD_RUN" name_de="REC_UEB" num="225">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="OP_DEP_NO" name_de="BEREICH_NR" type="num" width="3" cond="0-252"/>
+        <Field name_en="FROM_POINT_TYPE" name_de="ONR_TYP_NR" type="num" width="2" cond="1-2"/>
+        <Field name_en="FROM_POINT_NO" name_de="ORT_NR" type="num" width="6" cond=">0"/>
+        <Field name_en="TO_POINT_TYPE" name_de="UEB_ZIEL_TYP" type="num" width="2" cond="1-2"/>
+        <Field name_en="TO_POINT_NO" name_de="UEB_ZIEL" type="num" width="6" cond=">0"/>
+        <Field name_en="DEAD_RUN_DISTANCE" name_de="UEB_LAENGE" type="num" width="6" cond="1-81890"/>
+    </Layer>
+
+    <Layer name_en="DEAD_RUN_TIME" name_de="UEB_FZT" num="247">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="OP_DEP_NO" name_de="BEREICH_NR" type="num" width="3" cond="0-252"/>
+        <Field name_en="TIMING_GROUP_NO" name_de="FGR_NR" type="num" width="9" cond=">0"/>
+        <Field name_en="FROM_POINT_TYPE" name_de="ONR_TYP_NR" type="num" width="2" cond="1-2"/>
+        <Field name_en="FROM_POINT_NO" name_de="ORT_NR" type="num" width="6" cond=">0"/>
+        <Field name_en="TO_POINT_TYPE" name_de="UEB_ZIEL_TYP" type="num" width="2" cond="1-2"/>
+        <Field name_en="TO_POINT_NO" name_de="UEB_ZIEL" type="num" width="6" cond=">0"/>
+        <Field name_en="TRAVEL_TIME" name_de="UEB_FAHRZEIT" type="num" width="6" cond="1-65532"/>
+    </Layer>
+
+    <Layer name_en="JOURNEY_TYPE" name_de="MENGE_FAHRTART" num="332">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="JOURNEY_TYPE_NO" name_de="FAHRTART_NR" type="num" width="2" cond="1-4"/>
+        <Field name_en="JOURNEY_TYPE_DESC" name_de="STR_FAHRTART" type="char" width="6"/>
+    </Layer>
+
+    <Layer name_en="ZONE" name_de="FLAECHEN_ZONE" num="571">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="ZONE_TYPE_NO" name_de="FL_ZONE_TYP_NR" type="num" width="1" cond="1-9"/>
+        <Field name_en="ZONE_NO" name_de="FL_ZONE_NR" type="num" width="6" cond=">0"/>
+        <Field name_en="ZONE_ABBR" name_de="FL_ZONE_KUERZEL" type="char" width="8"/>
+        <Field name_en="ZONE_DESC" name_de="FL_ZONE_NAME" type="char" width="40"/>
+        <Field name_en="ZONE_ADMINISTRATIVE_NO" name_de="FL_AMTLICHE_NR" type="char" width="20"/>
+    </Layer>
+
+    <Layer name_en="ZONE_POINT" name_de="FL_ZONE_ORT" num="539">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="ZONE_TYPE_NO" name_de="FL_ZONE_TYP_NR" type="num" width="1" cond="1-9"/>
+        <Field name_en="ZONE_NO" name_de="FL_ZONE_NR" type="num" width="6" cond=">0"/>
+        <Field name_en="POINT_TYPE" name_de="ONR_TYP_NR" type="num" width="2" cond="1-7"/>
+        <Field name_en="POINT_NO" name_de="ORT_NR" type="num" width="6" cond=">0"/>
+    </Layer>
+
+    <Layer name_en="ZONE_TYPE" name_de="MENGE_FLAECHEN_ZONE_TYP" num="572">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="ZONE_TYPE_NO" name_de="FL_ZONE_TYP_NR" type="num" width="1" cond="1-9"/>
+        <Field name_en="ZONE_TYPE_DESC" name_de="FL_ZONE_TYP_TEXT" type="char" width="40"/>
+    </Layer>
+
+    <Layer name_en="POINT_ON_LINK_TRAVEL_TIME" name_de="SEL_FZT_FELD_ZP" num="540">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="OP_DEP_NO" name_de="BEREICH_NR" type="num" width="3" cond="0-252"/>
+        <Field name_en="TIMING_GROUP_NO" name_de="FGR_NR" type="num" width="9" cond=">0"/>
+        <Field name_en="FROM_POINT_TYPE" name_de="ONR_TYP_NR" type="num" width="2" cond="1-2"/>
+        <Field name_en="FROM_POINT_NO" name_de="ORT_NR" type="num" width="6" cond=">0"/>
+        <Field name_en="TO_POINT_NO" name_de="SEL_ZIEL" type="num" width="6" cond=">0"/>
+        <Field name_en="TO_POINT_TYPE" name_de="SEL_ZIEL_TYP" type="num" width="2" cond="1-2"/>
+        <Field name_en="POINT_TO_LINK_NO" name_de="ZP_ONR" type="num" width="6" cond=">0"/>
+        <Field name_en="POINT_TO_LINK_TYPE" name_de="ZP_TYP" type="num" width="2" cond="7"/>
+        <Field name_en="TRAVEL_TIME" name_de="SEL_FZT_ZP" type="num" width="6" cond="0-65532"/>
+    </Layer>
+
+    <Layer name_en="ROUTE_SEQUENCE" name_de="LID_VERLAUF" num="246">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="SEQUENCE_NO" name_de="LI_LFD_NR" type="num" width="3" cond=">0"/>
+        <Field name_en="LINE_NO" name_de="LI_NR" type="num" width="6" cond="1-99999"/>
+        <Field name_en="ROUTE_ABBR" name_de="STR_LI_VAR" type="char" width="6"/>
+        <Field name_en="POINT_TYPE" name_de="ONR_TYP_NR" type="num" width="2" cond="1-2"/>
+        <Field name_en="POINT_NO" name_de="ORT_NR" type="num" width="6" cond=">0"/>
+        <Field name_en="DEST_NO" name_de="ZNR_NR" type="num" width="4" cond="0-9999"/>
+        <Field name_en="ANN_NO" name_de="ANR_NR" type="num" width="4" cond="1-9999,NULL"/>
+        <Field name_en="LOCKIN_RANGE" name_de="EINFANGBEREICH" type="num" width="3" cond="0-256"/>
+        <Field name_en="LINE_NODE" name_de="LI_KNOTEN" type="boolean" width="1" cond="0-1(1)"/>
+        <Field name_en="PRODUCTIVE" name_de="PRODUKTIV" type="boolean" width="1" cond="0-1(1)"/>
+        <Field name_en="NO_BOARDING" name_de="EINSTEIGEVERBOT" type="boolean" width="1" cond="0-1(0)"/>
+        <Field name_en="NO_ALIGHTING" name_de="AUSSTEIGEVERBOT" type="boolean" width="1" cond="0-1(0)"/>
+        <Field name_en="CITY_BAN" name_de="INNERORTSVERBOT" type="boolean" width="1" cond="0-1(0)"/>
+        <Field name_en="REQUEST_STOP" name_de="BEDARFSHALT" type="boolean" width="1" cond="0-1(0)"/>
+    </Layer>
+
+    <Layer name_en="LINE" name_de="REC_LID" num="226">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="LINE_NO" name_de="LI_NR" type="num" width="6" cond="1-999"/>
+        <Field name_en="ROUTE_ABBR" name_de="STR_LI_VAR" type="char" width="6"/>
+        <Field name_en="ROUTE_NO" name_de="ROUTEN_NR" type="num" width="3" cond="1-999"/>
+        <Field name_en="DIRECTION" name_de="LI_RI_NR" type="num" width="3" cond="1-2"/>
+        <Field name_en="OP_DEP_NO" name_de="BEREICH_NR" type="num" width="3" cond="0-252"/>
+        <Field name_en="LINE_ABBR" name_de="LI_KUERZEL" type="char" width="6"/>
+        <Field name_en="LINE_DESC" name_de="LIDNAME" type="char" width="40"/>
+        <Field name_en="ROUTE_TYPE" name_de="ROUTEN_ART" type="num" width="2" cond="1-4"/>
+        <Field name_en="LINE_CODE" name_de="LINIEN_CODE" type="num" width="2" cond=">0,NULL"/>
+    </Layer>
+
+    <Layer name_en="JOURNEY" name_de="REC_FRT" num="715">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="JOURNEY_NO" name_de="FRT_FID" type="num" width="10" cond=">0"/>
+        <Field name_en="DEPARTURE_TIME" name_de="FRT_START" type="num" width="6" cond="0-129600"/>
+        <Field name_en="LINE_NO" name_de="LI_NR" type="num" width="6" cond="1-9999"/>
+        <Field name_en="DAY_TYPE_NO" name_de="TAGESART_NR" type="num" width="3" cond="1-999"/>
+        <Field name_en="RUN" name_de="LI_KU_NR" type="num" width="6" cond="1-99,NULL"/>
+        <Field name_en="JOURNEY_TYPE" name_de="FAHRTART_NR" type="num" width="2" cond="1-4"/>
+        <Field name_en="TIMING_GROUP_NO" name_de="FGR_NR" type="num" width="9" cond=">0"/>
+        <Field name_en="ROUTE_ABBR" name_de="STR_LI_VAR" type="char" width="6"/>
+        <Field name_en="BLOCK_NO" name_de="UM_UID" type="num" width="8" cond=">0,NULL"/>
+        <Field name_en="TRAIN_NO" name_de="ZUGNR" type="num" width="7" cond=">0"/>
+        <Field name_en="THROUGH_START" name_de="DURCHBI_FRT_START" type="boolean" width="1" cond="0-1(0)"/>
+        <Field name_en="THROUGH_END" name_de="DURCHBI_FRT_ENDE" type="boolean" width="1" cond="0-1(0)"/>
+    </Layer>
+
+    <Layer name_en="JOURNEY_WAIT_TIME" name_de="REC_FRT_HZT" num="308">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="JOURNEY_NO" name_de="FRT_FID" type="num" width="10" cond=">0"/>
+        <Field name_en="POINT_TYPE" name_de="ONR_TYP_NR" type="num" width="2" cond="1-2"/>
+        <Field name_en="POINT_NO" name_de="ORT_NR" type="num" width="6" cond=">0"/>
+        <Field name_en="JOURNEY_WAIT_TIME" name_de="FRT_HZT_ZEIT" type="num" width="6" cond="0-65532"/>
+    </Layer>
+
+    <Layer name_en="BLOCK" name_de="REC_UMLAUF" num="310">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="DAY_TYPE_NO" name_de="TAGESART_NR" type="num" width="3" cond="1-999"/>
+        <Field name_en="BLOCK_NO" name_de="UM_UID" type="num" width="8" cond=">0"/>
+        <Field name_en="FROM_POINT_NO" name_de="ANF_ORT" type="num" width="6" cond=">0"/>
+        <Field name_en="FROM_POINT_TYPE" name_de="ANF_ONR_TYP" type="num" width="2" cond="1-2"/>
+        <Field name_en="TO_POINT_NO" name_de="END_ORT" type="num" width="6" cond=">0"/>
+        <Field name_en="TO_POINT_TYPE" name_de="END_ONR_TYP" type="num" width="2" cond="1-2"/>
+        <Field name_en="VH_TYPE_NO" name_de="FZG_TYP_NR" type="num" width="3" cond="1-252,NULL"/>
+    </Layer>
+
+    <Layer name_en="JOURNEY_CONNECTION" name_de="EINZELANSCHLUSS" num="432">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="CONNECTION_ID" name_de="EINAN_NR" type="num" width="5" cond="1-32764"/>
+        <Field name_en="CONNECTION_NAME" name_de="ANSCHLUSS_NAME" type="char" width="40"/>
+        <Field name_en="PRIORITY" name_de="ANSCHLUSS_GRUPPE" type="char" width="6"/>
+        <Field name_en="CONTROL_CENTRE_CODE" name_de="LEITSTELLENKENNUNG" type="num" width="3" cond="1-255"/>
+        <Field name_en="FEEDER_LINE_NO" name_de="ZUB_LI_NR" type="num" width="3" cond="1-999"/>
+        <Field name_en="FEEDER_DIRECTION" name_de="ZUB_LI_RI_NR" type="num" width="3" cond="1-2(0)"/>
+        <Field name_en="FEEDER_STOP_NO" name_de="ZUB_ORT_REF_ORT" type="num" width="6" cond=">0"/>
+        <Field name_en="FEEDER_POINT_TYPE" name_de="ZUB_ONR_TYP_NR" type="num" width="2" cond=">0,NULL"/>
+        <Field name_en="FEEDER_POINT_NO" name_de="ZUB_ORT_NR" type="num" width="6" cond=">0,NULL"/>
+        <Field name_en="FROM_STOP_NO" name_de="VON_ORT_REF_ORT" type="num" width="6" cond=">0,NULL"/>
+        <Field name_en="LINE_ID" name_de="LINIENID" type="char" width="6"/>
+        <Field name_en="DIRECTION_ID" name_de="RICHTUNGSID" type="char" width="6"/>
+        <Field name_en="CONNECTION_LINK_REF" name_de="ASBID" type="char" width="10"/>
+        <Field name_en="FETCHER_LINE_NO" name_de="ABB_LI_NR" type="num" width="6" cond="1-999"/>
+        <Field name_en="FETCHER_DIRECTION" name_de="ABB_LI_RI_NR" type="num" width="3" cond="1-2(0)"/>
+        <Field name_en="FETCHER_STOP_NO" name_de="ABB_ORT_REF_ORT" type="num" width="6" cond=">0"/>
+        <Field name_en="FETCHER_POINT_TYPE" name_de="ABB_ONR_TYP_NR" type="num" width="2" cond=">0,NULL"/>
+        <Field name_en="FETCHER_POINT_NO" name_de="ABB_ORT_NR" type="num" width="6" cond=">0,NULL"/>
+        <Field name_en="TO_STOP_NO" name_de="NACH_ORT_REF_ORT" type="num" width="6" cond=">0,NULL"/>
+    </Layer>
+
+    <Layer name_en="INTERCHANGE" name_de="REC_UMS" num="232">
+        <Field name_en="BASE_VERSION" name_de="BASIS_VERSION" type="num" width="9" cond=">0"/>
+        <Field name_en="CONNECTION_ID" name_de="EINAN_NR" type="num" width="5" cond="1-32764"/>
+        <Field name_en="DAY_TYPE_NO" name_de="TAGESART_NR" type="num" width="3" cond="1-999"/>
+        <Field name_en="VALIDITY_START_TIME" name_de="UMS_BEGINN" type="num" width="6" cond="0-129599"/>
+        <Field name_en="VALIDITY_END_TIME" name_de="UMS_ENDE" type="num" width="6" cond="0-129599"/>
+        <Field name_en="INTERCHANGE_STANDARD_DURATION" name_de="UMS_MIN" type="num" width="5" cond="0-65532"/>
+        <Field name_en="INTERCHANGE_MAXIMUM_DURATION" name_de="UMS_MAX" type="num" width="5" cond="0-65532"/>
+        <Field name_en="MAXIMUM_WAIT_TIME" name_de="MAX_VERZ_MAN" type="num" width="5" cond="0-65532"/>
+        <Field name_en="MAXIMUM_WAIT_TIME_AUTO" name_de="MAX_VERZ_AUTO" type="num" width="5" cond="0-65532"/>
+    </Layer>
+
+</Layers>
diff --git a/data/vdv452.xsd b/data/vdv452.xsd
new file mode 100644
index 0000000..a42774b
--- /dev/null
+++ b/data/vdv452.xsd
@@ -0,0 +1,63 @@
+<?xml version="1.0"?>
+<!--
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL
+ * Purpose:  Schema of vdv-452.xml
+ * Author:   Even Rouault, <even.rouault at spatialys.com>
+ *
+ **********************************************************************
+ * Copyright (c) 2015, Even Rouault
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+    <xs:element name="Layers">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="Layer" type="LayerType" minOccurs="0" maxOccurs="unbounded"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+    <xs:complexType name="LayerType">
+        <xs:sequence>
+            <xs:element name="Field" type="FieldType" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="name_en" type="xs:string"/>
+        <xs:attribute name="name_de" type="xs:string"/>
+        <xs:attribute name="num" type="xs:integer"  use="optional"/>
+    </xs:complexType>
+    <xs:complexType name="FieldType">
+        <xs:attribute name="name_en" type="xs:string"/>
+        <xs:attribute name="name_de" type="xs:string"/>
+        <xs:attribute name="type">
+          <xs:simpleType>
+                <xs:restriction base="xs:string">
+                    <xs:enumeration value="num"/>
+                    <xs:enumeration value="char"/>
+                    <xs:enumeration value="boolean"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+        <xs:attribute name="width" type="xs:nonNegativeInteger"/>
+        <xs:attribute name="cond" type="xs:string" use="optional"/>
+    </xs:complexType>
+</xs:schema>
diff --git a/data/vertcs.csv b/data/vertcs.csv
index 0c95b96..7af97c8 100644
--- a/data/vertcs.csv
+++ b/data/vertcs.csv
@@ -128,10 +128,11 @@
 5795,Guadeloupe 1951 height,5193,Guadeloupe 1951,9001,1,0,6499,,
 5796,Lagos 1955 height,5194,Lagos 1955,9001,1,0,6499,,
 5797,AIOC95 height,5133,AIOC 1995,9001,1,0,6499,,
-5798,EGM84 geoid height,5203,EGM84 geoid,9001,1,0,6499,,
+5798,EGM84 height,5203,EGM84 geoid,9001,1,0,6499,,
 5799,DVR90 height,5206,Dansk Vertikal Reference 1990,9001,1,0,6499,,
 5829,Instantaneous Water Level height,5113,Instantaneous Water Level,9001,1,0,6499,,
 5831,Instantaneous Water Level depth,5113,Instantaneous Water Level,9001,1,0,6498,,
+5843,Ras Ghumays height,1146,Ras Ghumays,9001,1,0,6499,,
 5861,LAT depth,1080,Lowest Astronomic Tide,9001,1,0,6498,,
 5862,LLWLT depth,1083,Lower Low Water Large Tide,9001,1,0,6498,,
 5863,ISLW depth,1085,Indian Spring Low Water,9001,1,0,6498,,
@@ -156,7 +157,7 @@
 6181,Horta height,1104,Horta,9001,1,0,6499,,
 6182,Cais da Madalena height,1105,Cais da Madalena,9001,1,0,6499,,
 6183,Santa Cruz da Graciosa height,1106,Santa Cruz da Graciosa,9001,1,0,6499,,
-6184,"Cais da Figueirinha - Angra do Heroísmo height",1107,"Cais da Figueirinha - Angra do Heroísmo",9001,1,0,6499,,
+6184,Cais da Figueirinha - Angra do Heroismo height,1107,Cais da Figueirinha - Angra do Heroismo,9001,1,0,6499,,
 6185,Santa Cruz das Flores height,1108,Santa Cruz das Flores,9001,1,0,6499,,
 6186,Cais da Vila do Porto height,1109,Cais da Vila do Porto,9001,1,0,6499,,
 6187,Ponta Delgada height,1110,Ponta Delgada,9001,1,0,6499,,
@@ -175,3 +176,8 @@
 6693,JSLD72 height,1129,Japanese Standard Levelling Datum 1972,9001,1,0,6499,,
 6694,"JGD2000 (vertical) height",1130,"Japanese Geodetic Datum 2000 (vertical)",9001,1,0,6499,,
 6695,"JGD2011 (vertical) height",1131,"Japanese Geodetic Datum 2011 (vertical)",9001,1,0,6499,,
+6916,SHD height,1140,Singapore Height Datum,9001,1,0,6499,,
+7446,Famagusta 1960 height,1148,Famagusta 1960,9001,1,0,6499,,
+7447,PNG08 height,1149,PNG08,9001,1,0,6499,,
+7651,Kumul 34 height,1150,Kumul 34,9001,1,0,6499,,
+7652,Kiunga height,1151,Kiunga,9001,1,0,6499,,
diff --git a/dist_docs/README_UNX_BIN.TXT b/dist_docs/README_UNX_BIN.TXT
deleted file mode 100644
index f6513c1..0000000
--- a/dist_docs/README_UNX_BIN.TXT
+++ /dev/null
@@ -1,71 +0,0 @@
-
-		GDAL/OGR Binary Release
-		=======================
-
-This is a release of GDAL/OGR libraries and related utilities.  Full
-information on GDAL and OGR can be found at:
-
-  http://www.remotesensing.org/gdal                (GDAL)
-  http://gdal.velocet.ca/projects/opengis          (OGR)
-
-Details on the utility programs in this package can be found specifically at:
-
-  http://www.remotesensing.org/gdal/gdal_utilities.html
-  http://gdal.velocet.ca/projets/opengis/ogrhtml/ogr_utilities.html
-
-
-Installing GDAL/OGR
--------------------
-
-The install_unx.sh script can be used to install GDAL into an existing
-file system tree such as /usr/local or /usr.  It assumes that the 
-$PREFIX/bin directory will already be in the user path, and that 
-$PREFIX/lib is already in the LD_LIBRARY_PATH or configured for ldconfig.
-If ldconfig is used it may be necessary to rerun ldconfig as root. 
-
-To install:
-
- ./install_unx.sh /usr/local
-
-Note that html documentation and python files are not installed.  Only the
-shared library, binaries and shared data files are installed into
-$PREFIX/lib, $PREFIX/bin and $PREFIX/share/gdal respectively.
-
-After installation the "gdalinfo --version" command can be used to determine
-if the installation was successful.  Then use "gdal_translate --version"
-to verify that the shared libraries are being found properly.  If not
-add $PREFIX/lib to the LD_LIBRARY_PATH or rerun ldconfig as appropriate
-to local usage and the platform in question. 
-
-
-Using GDAL/OGR Without Installing
----------------------------------
-
-To utilize GDAL/OGR the following steps need to be followed:
-
- 1) Define GDAL_HOME to point to this directory.
- 2) Ensure that $GDAL_HOME/lib is in the LD_LIBRARY_PATH.
- 3) Ensure $GDAL_HOME/bin is in the PATH. 
-
-The following commands in a .cshrc file (for csh or tcsh) should suffice:
-
-  setenv GDAL_HOME ...insert path to this distribution directory...
-  set path = ($path $GDAL_HOME/bin)
-  if ( $?LD_LIBRARY_PATH == 0 ) then
-    setenv LD_LIBRARY_PATH $GDAL_HOME/lib
-  else
-    setenv LD_LIBRARY_PATH $LD_LIBRARY_PATH:$GDAL_HOME/lib
-  endif
-
-The following commands should work for bash, sh, ksh and zsh:
-
-  GDAL_HOME=...insert path to this distribution directory...
-  export GDAL_HOME
-  PATH=$PATH:$GDAL_HOME/bin
-  if test "${LD_LIBRARY_PATH:-EMPTY}" == "EMPTY" ; then
-    LD_LIBRARY_PATH=$GDAL_HOME/lib
-    export LD_LIBRARY_PATH
-  else
-    LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$GDAL_HOME/lib
-  fi
-
diff --git a/dist_docs/README_WIN_BIN.TXT b/dist_docs/README_WIN_BIN.TXT
deleted file mode 100644
index e086fce..0000000
--- a/dist_docs/README_WIN_BIN.TXT
+++ /dev/null
@@ -1,86 +0,0 @@
-	GDAL Binary Distribution for Windows
-	====================================
-
-This distribution contains files necessary to use GDAL utility applications,
-as well as library and include files necessary to compile and link other
-programs against GDAL.  It also include support for using GDAL from Python 2.0.
-
-Local information about GDAL can be found in html\index.html.
-
-eg. 
-  start html\index.html
-
-Central information can be found at:
-
-  http://www.remotesensing.org/gdal
-
-
-Installation
-------------
-
-It is sufficient to unzip this distribution somewhere on your harddrive, and
-add the GDALxxx\BIN directory to your path (where xxx is the version). 
-Alternatively, just copy the contents of the BIN directory to somewhere in
-your path.
-
-For those wanting to develop with GDAL using VC++ commandline tools, a small
-setup script has been written to update the environment appropriately. To 
-use it, edit SETUP_GDAL.BAT, and modify the GDAL_DIR environment to point to
-where GDAL has been put.  Then run SETUP_GDAL.BAT in a DOS window before
-trying to compile against GDAL. 
-
-Utility Programs
-----------------
-
-The following GDAL and OGR utility programs should be available in the bin
-directory.  Visit the GDAL web page for more information on the utility
-programs. 
-
-  gdalinfo.exe: Report summary information about a GDAL supported raster file.
-  gdal_translate.exe: Translate GDAL supported raster files into other formats.
-  gdaladdo: Add overviews to selected GDAL supported formats. 
-  ogrinfo: Dump information about OGR supported vector formats.
-  ogr2ogr: Translate OGR supported vector formats to OGR supported formats.
-
-
-More Detailed Manifest
-----------------------
-
-BIN		All distributed executables, and the DLLs required for them.
-		The GDAL11.DLL is the main GDAL/OGR DLL.  PROJ.DLL is the
-		PROJ.4 DLL used by GDAL for reprojection.
-
-HTML		Web pages, a snapshot of the www.remotesensing.org/gdal web
-		pages at the time the distribution was prepared.
-
-INCLUDE		GDAL and OGR include files.  
-
-LIB		GDAL/OGR libraries.  GDAL.LIB is the omnibus GDAL/OGR static
-		library.  GDAL_I.LIB is the stub (interface) library for the
-		GDAL11.DLL.  Link against GDAL_I.LIB to use the DLL. 
-
-DATA		Data files required by OGRSpatialReference and the GDAL 
-		GeoTIFF driver for looking up EPSG coordinate systems.  Define
-		GEOTIFF_CSV to point to the directory where these files are 
-		found. 
-
-PYMOD		Python extensions for GDAL.  Add this directory to your 
-		PYTHONPATH to use from python.
-
-Supported Formats
------------------
-
-The html\formats_list.html document contains a generic list of supported 
-formats for GDAL, but the following issues should be kept in mind for standard
-builds on Windows:
-
-GDAL:
- o OGDI is omitted.
- o FITS is omitted.
- o GRASS omitted.
- o JPEG, PNG, GeoTIFF are all using internal library code. 
-
-OGR:
- o OGDI omitted.
- o PostgreSQL omitted.
-
diff --git a/dist_docs/SETUP_GDAL.BAT b/dist_docs/SETUP_GDAL.BAT
deleted file mode 100755
index 8cf90be..0000000
--- a/dist_docs/SETUP_GDAL.BAT
+++ /dev/null
@@ -1,24 +0,0 @@
- at echo off
-
-set GDAL_DIR=c:\gdal114
-
-if exist %GDAL_DIR%\SETUP_GDAL.BAT goto DIROK
-
-echo -----------------------------------------------------------------------
-echo It appears that the GDAL_DIR environment variable is not set properly
-echo in SETUP_GDAL.BAT.  Please edit GDAL_SETUP.BAT, and modify the GDAL_DIR
-echo variable to contain the directory containing the SETUP_GDAL.BAT ... the
-echo base directory of the unzipped GDAL tree.
-echo -----------------------------------------------------------------------
-
-goto Done
-
-:DIROK
-
-set PATH=%GDAL_DIR%\bin;%PATH%
-set INCLUDE=%GDAL_DIR%\include;%INCLUDE%
-set LIB=%GDAL_DIR%\include;%LIB%
-set PYTHONPATH=%GDAL_DIR%\pymod;%PYTHONPATH%
-set GEOTIFF_CSV=%GDAL_DIR%\data
-
-:Done
\ No newline at end of file
diff --git a/dist_docs/burnpath.c b/dist_docs/burnpath.c
deleted file mode 100644
index 6fcb61f..0000000
--- a/dist_docs/burnpath.c
+++ /dev/null
@@ -1,113 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-
-const static int block_size = 10000;
-
-/************************************************************************/
-/*                                main()                                */
-/************************************************************************/
-int main( int argc, char ** argv )
-
-{
-    FILE	*fp;
-    int		offset, size, overlap;
-    const char *marker;
-    const char *path;
-    const char *targetfile;
-    char        blockbuf[block_size+1];
-
-/* -------------------------------------------------------------------- */
-/*      Usage message.                                                  */
-/* -------------------------------------------------------------------- */
-    if( argc < 4 )
-    {
-        printf( "\n" );
-        printf( "Usage: burnpath <targetfile> <marker_string> <path>\n" );
-        printf( "\n" );
-        printf( "eg. \n" );
-        printf( "   %% burnpath /opt/lib/libgdal.1.1.so __INST_DATA_TARGET: /opt/share/gdal\n" );
-        exit( 1 );
-    }
-
-    targetfile = argv[1];
-    marker = argv[2];
-    path = argv[3];
-
-    overlap = strlen(marker) + strlen(path) + 1;
-
-/* -------------------------------------------------------------------- */
-/*      Open the target file.                                           */
-/* -------------------------------------------------------------------- */
-    fp = fopen( targetfile, "r+" );
-    if( fp == NULL )
-    {
-        perror( "fopen" );
-        exit( 1 );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Establish the file length.                                      */
-/* -------------------------------------------------------------------- */
-    fseek( fp, 0, SEEK_END );
-    size = ftell( fp );
-    fseek( fp, 0, SEEK_SET );
-
-/* -------------------------------------------------------------------- */
-/*      Read in the file in overlapping chunks.  We assume the          */
-/*      "space" after the marker could be up to 200 bytes.              */
-/* -------------------------------------------------------------------- */
-    for( offset = 0; offset < size; offset += block_size - overlap )
-    {
-        int    block_bytes, block_modified = 0, i;
-
-        if( offset + block_size < size )
-            block_bytes = block_size;
-        else
-            block_bytes = size - offset;
-
-        if( fseek( fp, offset, SEEK_SET ) != 0 )
-        {
-            perror( "fseek" );
-            exit( 1 );
-        }
-
-        if( fread( blockbuf, block_bytes, 1, fp ) != 1 )
-        {
-            perror( "fread" );
-            exit( 1 );
-        }
-        blockbuf[block_bytes] = '\0';
-
-        for( i = 0; i < block_bytes - overlap; i++ )
-        {
-            if( blockbuf[i] == marker[0]
-                && strncmp( blockbuf + i, marker, strlen(marker) ) == 0 )
-            {
-                strcpy( blockbuf+i+strlen(marker), path );
-                block_modified = 1;
-            }
-        }
-
-        if( block_modified )
-        {
-            if( fseek( fp, offset, SEEK_SET ) != 0 )
-            {
-                perror( "fseek" );
-                exit( 1 );
-            }
-
-            if( fwrite( blockbuf, block_bytes, 1, fp ) != 1 )
-            {
-                perror( "fwrite" );
-                exit( 1 );
-            }
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      We are done.                                                    */
-/* -------------------------------------------------------------------- */
-    fclose( fp );
-
-    exit( 0 );
-}
diff --git a/dist_docs/install_unx.sh b/dist_docs/install_unx.sh
deleted file mode 100755
index 06fa6ed..0000000
--- a/dist_docs/install_unx.sh
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/bin/sh
-
-if test $# -eq 0; then
-    echo "Usage: install_unx.sh install-path"
-    echo
-    echo "This script will attempt to install GDAL binaries, and shared"
-    echo "library in the named location."
-    exit 1
-fi
-
-PREFIX=$1
-
-if test ! -d $PREFIX ; then
-  echo "Directory $PREFIX does not exist.  Please create or correct."
-  exit 1
-fi
-
-if test ! -f bin/gdalinfo ; then
-  echo "This script must be run from within the unpacked binary distribution"
-  echo "directory."
-  exit 1
-fi
-
-###############################################################################
-# Ensure required subdirectories exist.
-#
-
-if test ! -d $PREFIX/lib ; then
-  mkdir $PREFIX/lib
-fi
-if test ! -d $PREFIX/bin ; then
-  mkdir $PREFIX/bin
-fi
-if test ! -d $PREFIX/share ; then
-  mkdir $PREFIX/share
-fi
-if test ! -d $PREFIX/share/gdal ; then
-  mkdir $PREFIX/share/gdal
-fi
-
-###############################################################################
-# The following is intended to "burn" an updated INST_DATA location
-# into the given file over the preformatted message embedded in the so.
-# Look at gcore/gdaldrivermanager.cpp for a clue as to what is going on there.
-#
-
-SHARED_LIB=libgdal.1.1.so
-
-for SHARED_LIB in lib/* ; do
-  cp $SHARED_LIB $PREFIX/lib
-  bin/burnpath $PREFIX/$SHARED_LIB __INST_DATA_TARGET: $PREFIX/share/gdal
-done
-
-###############################################################################
-# Copy the rest of the files.
-#
-
-cp share/gdal/* $PREFIX/share/gdal
-
-for EXECUTABLE in bin/* ; do
-  if test "$EXECUTABLE" == "bin/gdal-config" -o "$EXECUTABLE" == "bin/burnpath" ; then
-    /bin/true
-  else
-    cp $EXECUTABLE $PREFIX/bin
-    bin/burnpath $PREFIX/$EXECUTABLE __INST_DATA_TARGET: $PREFIX/share/gdal
-  fi
-done
-
-echo "Installation of GDAL to $PREFIX complete."
-
diff --git a/doc/api.dox b/doc/api.dox
index b06cc44..fd24c34 100644
--- a/doc/api.dox
+++ b/doc/api.dox
@@ -20,7 +20,7 @@ the progress semantics.
 		          void *pProgressArg);
 \endcode
 
- at param dfComplete The ratio of completness of the process from 0.0 for just
+ at param dfComplete The ratio of completeness of the process from 0.0 for just
 started to 1.0 for completed.
 
 @param pszMessage An optional message string to display.  This is usually NULL.
@@ -81,6 +81,6 @@ operation should be terminated.
 
 <li> The ratio of completeness should vary from 0.0 to 1.0.  Please ensure the
 exact value 1.0 is always returned at the end of the algorithm as some 
-gui display mechanisms use this as a clue to popdown the progress monitor. 
+GUI display mechanisms use this as a clue to pop down the progress monitor. 
 
 */
diff --git a/doc/br/gdal_tutorial_br.dox b/doc/br/gdal_tutorial_br.dox
index a78fdfb..e121877 100644
--- a/doc/br/gdal_tutorial_br.dox
+++ b/doc/br/gdal_tutorial_br.dox
@@ -507,7 +507,7 @@ Em Python:
 \section gdal_tutorial_create Usando Create()
 
 Em situações em que não se quer somente exportar um arquivo existente 
-para uma arquivo novo, geralmente usa-se o método GDALDriver::Criar() (embora algumas 
+para uma arquivo novo, geralmente usa-se o método GDALDriver::Create() (embora algumas 
 opções interessantes são possíveis 
 com o uso de arquivos virtuais ou de arquivos da em-memória). 
 O método Create() examina uma lista de opções bem como o CreateCopy(), mas 
diff --git a/doc/br/index_br.dox b/doc/br/index_br.dox
index d93ff7b..3fedf6b 100644
--- a/doc/br/index_br.dox
+++ b/doc/br/index_br.dox
@@ -1,13 +1,13 @@
-#ifndef DOXYGEN_SKIP                                                            
-/* $Id: index_br.dox $ */               
+#ifndef DOXYGEN_SKIP
+/* $Id: index_br.dox $ */
 Translation corresponds to index.dox "11836 2007-08-02 21:24:45Z warmerdam"
-Translator Ivan Lucena <ivan.lucena at pmldnet.com>
-#endif /* DOXYGEN_SKIP */                                                       
+Translator Ivan Lucena <ivan dot lucena at oracle dot com>
+#endif /* DOXYGEN_SKIP */
 
-/*! \page index_br GDAL - Biblioteca de Abstracoes de Dados Geo-Espaciais
+/*! \page index_br GDAL - Biblioteca de Abstrações de Dados Geo-Espaciais
 
 <center>
-<b>Selecione o idioma</b>: 
+<b>Selecione o idioma</b>:
 <a href="index.html">[English] </a>
 <a href="index_ru.html">[Russian] </a>
 [Portuguese]
@@ -15,96 +15,128 @@ Translator Ivan Lucena <ivan.lucena at pmldnet.com>
 </center>
 
 \htmlonly<img src="gdalicon.png" alt="GDAL">\endhtmlonly \latexonly GDAL \endlatexonly
-é uma bibliotéca para tradução de formatos de dados geográficos distribuída pela 
-<a href="http://www.osgeo.org/">Open Source Geospatial Foundation</a> sob a licença 
+é uma bibliotéca para tradução de formatos de dados geográficos distribuída pela
+<a href="http://www.osgeo.org/">Open Source Geospatial Foundation</a> sob a licença
 <a href="http://trac.osgeo.org/gdal/wiki/FAQGeneral#WhatlicensedoesGDALOGRuse">X/MIT</a> estilo
-<a href="http://www.opensource.org/"> Open Source</a>. 
-As aplicações que à utilizam acessam todos os formats 
-supportados pela biblioteca através de 
+<a href="http://www.opensource.org/"> Open Source</a>.
+As aplicações que à utilizam acessam todos os formats
+supportados pela biblioteca através de
 \link gdal_datamodel_br.html um único modelo de dados abstrato\endlink.
-A bilioteca GDAL também conta com uma variadade de programas 
+A bilioteca GDAL também conta com uma variadade de programas
 <a class="el" href="gdal_utilities.html"> utilitários de linha de comando</a>
-para a tradução de formatos bem como uma série de outras funções. 
-A página 
-<a href="http://trac.osgeo.org/gdal/wiki/Release/1.9.0-News">novidades</a> descreve o 
-lançamento em Abril de 2013 da release 1.10.0 da biblioteca GDAL/OGR.
+para a tradução de formatos bem como uma série de outras funções.
+A página
+<a href="http://trac.osgeo.org/gdal/wiki/Release/2.0.0-News">novidades</a> descreve o
+lançamento em Junho de 2015 da release 2.0.0 da biblioteca GDAL/OGR.
+
+Tradicionalmente a bilioteca GDAL referia-se a dados Raster enquanto que OGR 
+referia-se a dados Vetorias (Simple Features). Mas a partir da verção 2.0 as duas partes 
+estão mais integradas. Voce ainda pode se referir a 
+<a href="http://gdal.org/1.11/index.html">documentação da GDAL 1.X</a> se necessário.
 
-A bilioteca <a href="ogr">OGR</a> (cujo código fonte esta incluído na GDAL) possue
-funcionalidades semelhantes às da GDAL para datos vetorias (Simple Features).
 
 Página Principal: http://www.gdal.org<br>
-Download: 
+Download:
  <a href="ftp://ftp.remotesensing.org/gdal">ftp at remotesensing.org</a>,
  <a href="http://download.osgeo.org/gdal">http at download.osgeo.org</a>
 
-\section index_userdocs Documentacao para usuario
+\section index_userdocs Documentação para usuário
 
 <ul>
 <li> <a href="http://trac.osgeo.org/gdal/">Wiki</a> - Documentação e dicas mantidas por vários desenvolvedores e contribuidores
-<li> <a href="http://trac.osgeo.org/gdal/wiki/DownloadingGdalBinaries">Downloads</a> - Programas executáveis prontos para usar
-<li> <a href="formats_list.html">Formatos Suportados</a>
-<li> <a href="gdal_utilities.html">Programs Utilitários</a>
+<li> <a href="http://trac.osgeo.org/gdal/wiki/DownloadingGdalBinaries">Downloads</a> - <Programas executáveis prontos para usar
+<li> <a href="formats_list.html">Formatos raster suportados</a> (142 drivers): <a href="frmt_gtiff.html">GeoTIFF</a>, <a href="frmt_hfa.html">Erdas Imagine</a>, <a href="frmt_ecw.html">ECW</a>, <a href="frmt_mrsid.html">MrSID</a>, <a href="frmt_jp2openjpeg.html">JPEG2000</a>, <a href="frmt_dted.html">DTED</a>, <a href="frmt_nitf.html">NITF</a>, <a href="drv_geopackage_raster.html">GeoPackage</a>, ...
+<li> <a href="ogr_formats.html">Formatos vectorais suportados</a> (84 drivers): <a href="drv_shapefile.html">ESRI Shapefile</a>, <a href="drv_sde.html">ESRI ArcSDE</a>, <a href="drv_openfilegdb.html">ESRI FileGDB</a>, <a href="drv_mitab.html">MapInfo (tab and mid/mif)</a>, <a href="drv_gml.html">GML</a>, <a href="drv_libkml.html">KML</a>, <a href="drv_pg.html">PostGIS</a>, <a href="drv_oci.html">Oracle Spatial</a>, <a href="drv_geopackage.html">GeoPackage</a>, ...
+<li> <a href="gdal_utilities.html">Programas utilitários para raster</a>: <a href="gdalinfo.html">gdalinfo</a>, <a href="gdal_translate.html">gdal_translate</a>, <a href="gdaladdo.html">gdaladdo</a>, <a href="gdalwarp.html">gdalwarp</a>, ...
+<li> <a href="ogr_utilities.html">Programas utilitários para vector</a>: <a href="ogrinfo.html">ogrinfo</a>, <a href="ogr2ogr.html">ogr2ogr</a>, <a href="ogrtindex.html">ogrtindex</a>, ...
 <li> <a href="http://trac.osgeo.org/gdal/wiki/FAQ">Perguntas Mais Frequentes</a>
-<li> <a href="gdal_datamodel_br.html">Modelo de dados</a> <b>(em português)</b>
+<li> <a href="gdal_datamodel_br.html">Modelo de dados raster </a> <b>(em português)</b> e <a href="ogr_arch.html">vectorial</a> em Inglès.
 <li> <a href="http://trac.osgeo.org/gdal/wiki/GovernanceAndCommunity">Governança e participação comunitária</a>
+<li> <a href="http://www.osgeo.org/search_profile?SET=1&MUL_TECH[0]=00013">Lista de provedores de serviço GDAL</a> (lista de provedores não vetados)
 <li> <a href="credits.html">Patrocinadores, Agradecimentos e Créditos</a>
 <li> <a href="http://trac.osgeo.org/gdal/wiki/SoftwareUsingGdal">Software que usam GDAL</a>
 </ul>
 
-\section index_devdocs Documentacao para desenvolvedor
+\section index_devdocs Documentação para desenvolvedor
 
 <ul>
 <li> <a href="http://trac.osgeo.org/gdal/wiki/BuildHints">Como compilar GDAL</a>
 <li> <a href="http://trac.osgeo.org/gdal/wiki/DownloadSource">Downloads</a> - código fonte
+<li> <a href="wince.html">GDAL para Windows CE (sem manutenção)</a>
+</ul>
+
+\section index_devdocs_tutorial Tutoriais
+
+<ul>
+<li> Raster topics:
+  <ul>
+    <li> <a href="gdal_tutorial_br.html">Tutorial da API raster</a>
+    <li> <a href="gdal_drivertut.html">Implementação de driver raster</a>
+    <li> <a href="gdal_vrttut.html">Formato virtual raster (VRT)</a>
+    <li> <a href="warptut.html">Tutorial de Reprojeção em raster
+  </ul>
+</li>
+<li> Vector topics:
+  <ul>
+    <li> <a href="ogr_apitut.html">Tutorial da API vetorial</a>
+    <li> <a href="ogr_drivertut.html">Implementação de driver vetorial</a>
+    <li> <a href="drv_vrt.html">Formato virtual vetorial (VRT)</a>
+    <li> <a href="ogr_feature_style.html">Especificação de estilo vetorial</a>
+   </ul>
+</li>
+<li> <a href="osr_tutorial.html"> Tutorial de Referência Espacial</a> (OSR - OGRSpatialReference)
+</ul>
+
+\subsection index_devdocs_api Documentação da API
+
+<ul>
 <li> <a href="hierarchy.html">Documentação de referencia da API</a>
-<li> <a href="gdal_tutorial_br.html">Tutorial da API do GDAL</a> <b>(em português)</b>
-<li> <a href="gdal_drivertut.html">Tutorial de implementação de drivers</a>
-<li> <a href="warptut.html">Tutorial de transformação geométrica</a>
-<li> <a href="ogr/osr_tutorial.html">Tutorial de Referência Espacial</a>
-<li> <a href="gdal_8h.html">GDAL API para C</a>
-<li> <a href="classGDALDataset.html">GDALDataset</a>
-<li> <a href="classGDALRasterBand.html">GDALRasterBand</a>
-<li> <a href="wince.html">GDAL para Windows CE</a>
+<li> <a href="gdal_8h.html">API raster para C</a>
+<li> <a href="ogr_api_8h.html">API vector para C</a>
+<li> <a href="classGDALDataset.html">GDALDataset para C++</a>
+<li> <a href="classGDALRasterBand.html">GDALRasterBand para C++</a>
+<li> <a href="classOGRLayer.html">OGRLayer para C++</a>
+<li> Dialeto <a href="ogr_sql.html">OGR SQL</a> e dialeto <a href="ogr_sql_sqlite.html">SQLITE SQL</a>
 </ul>
 
-\section index_maillist Lista de discussao por correio eletronico
+<!--
+\subsection index_devdocs_specs Specifications
+
+<ul>
+<li> <a href="http://home.gdal.org/projects/opengis/twohalfdsf.html">Adam's 2.5 D Simple Features Proposal (OGC 99-402r2)</a>
+<li> Adam's SRS WKT Clarification Proposal in <a href="http://home.gdal.org/projects/opengis/wkt_prop.html">html</a>
+or <a href="http://home.gdal.org/projects/opengis/wkt_prop.doc">doc</a> format.
+</ul>
+-->
+
+\section index_maillist Lista de discussão por correio eletrònico
 
 A lista <a href="http://lists.osgeo.org/mailman/listinfo/gdal-announce">gdal-announce</a>
-é uma lista de pequeno volume de mensagens usada somente para anunciar lançamento de 
+é uma lista de pequeno volume de mensagens usada somente para anunciar lançamento de
 versões e desenvolvimentos significativos.
 
 A lista <a href="mailto:gdal-dev at lists.maptools.org">gdal-dev at lists.maptools.org</a>
 pode ser usada para a discussão sobre o desenvolvimento e uso da GDAL e tecnologias relaciadas.
-A inscrição e o acesso aos arquivo da lista podem ser feitos 
-<a href="http://lists.maptools.org/mailman/listinfo/gdal-dev/"> nesta página</a>. 
+A inscrição e o acesso aos arquivo da lista podem ser feitos
+<a href="http://lists.maptools.org/mailman/listinfo/gdal-dev/"> nesta página</a>.
 Os arquivos da lista também estão disponíveis (somente para leitura) através do
 <a href="news://news.gmane.org/gmane.comp.gis.gdal.devel">news://news.gmane.org/gmane.comp.gis.gdal.devel</a>
-ou na página 
+ou na página
 <a href="http://news.gmane.org/gmane.comp.gis.gdal.devel">http://news.gmane.org/gmane.comp.gis.gdal.devel</a>.<p>
 
-Usuários e desenvolvedores da GDAL/OGR podem constantemente ser achados no canal IRC 
+Usuários e desenvolvedores da GDAL/OGR podem constantemente ser achados no canal IRC
 <a href="irc://irc.freenode.net/#gdal">#gdal</a> do irc.freenode.net.<p>
 
 \section index_bugs Como Reportar Problemas (Bugs)
 
-Bugs em GDAL podem ser 
-<a href="http://trac.osgeo.org/gdal/newticket">reportados</a> e também 
+Bugs em GDAL podem ser
+<a href="http://trac.osgeo.org/gdal/newticket">reportados</a> e também
 <a href="http://trac.osgeo.org/gdal/report/1?sort=ticket&asc=0">listados</a> através do software Trac.<p>
 
 \section index_bindings GDAL em outras linguagens
 
 Lista de linguagens de programção supportadas por GDAL:
-
-<ul>
-<li> <a href="http://map.hut.fi/gdal-perl/">Perl</a>
-<li> <a href="http://trac.osgeo.org/gdal/wiki/GdalOgrInPython">Python</a>
-<li> <a href="vb6_tutorial.html">VB6 Bindings</a> (sem o uso de SWIG)
-<li> <a href="http://rgdal.sourceforge.net/">GDAL interface para R</a>
-by Timothy H. Keitt.
-<li> <a href="http://trac.osgeo.org/gdal/wiki/GdalOgrInRuby">Ruby</a>
-<li> <a href="http://trac.osgeo.org/gdal/wiki/GdalOgrInJava">Java</a>
-<li> <a href="http://trac.osgeo.org/gdal/wiki/GdalOgrInCsharp">C# / .Net</a>
-
-</ul>
+<a href="http://trac.osgeo.org/gdal/#GDALOGRInOtherLanguages">GDAL
+wiki</a>.
 
 */
diff --git a/doc/credits.dox b/doc/credits.dox
index 9dc5886..97e12c7 100644
--- a/doc/credits.dox
+++ b/doc/credits.dox
@@ -1,5 +1,5 @@
 #ifndef DOXYGEN_SKIP
-/* $Id: credits.dox 27425 2014-05-30 21:02:09Z rouault $ */
+/* $Id: credits.dox 33134 2016-01-23 23:10:03Z rouault $ */
 #endif /* DOXYGEN_SKIP */
 
 /*!
@@ -171,7 +171,7 @@ CDED / USGS DEM Writer.
 <p>
 
 <li> <b><a href="http://www.waypointinfo.com/">Waypoint</a></b>:
-Panorama(tm) mapping platform delivers powerful online mapping 
+Panorama(TM) mapping platform delivers powerful on-line mapping 
 services for business and government organizations, including spatial 
 analysis, mobile asset tracking, web publishing, and Web Mapping Services. Has
 been a Silver sponsor of GDAL.
@@ -181,7 +181,7 @@ been a Silver sponsor of GDAL.
 
 \htmlonly
 <p>
-$Id: credits.dox 27425 2014-05-30 21:02:09Z rouault $
+$Id: credits.dox 33134 2016-01-23 23:10:03Z rouault $
 </p>
 \endhtmlonly
 
diff --git a/doc/download.dox b/doc/download.dox
index 6713ea7..f7cc59a 100644
--- a/doc/download.dox
+++ b/doc/download.dox
@@ -1,10 +1,10 @@
 #ifndef DOXYGEN_SKIP
-/* $Id: download.dox 11222 2007-04-07 20:25:25Z warmerdam $ */
+/* $Id: download.dox 33134 2016-01-23 23:10:03Z rouault $ */
 #endif /* DOXYGEN_SKIP */
 
 /*!
 \page download GDAL Downloads
 
-This page has been moved to the wiki with a topic on downloading <a href="http://trac.osgeo.org/gdal/wiki/DownloadingGdalBinaries">binaries (pre-built executables</a> and a topic on downloading <a href="http://trac.osgeo.org/gdal/wiki/DownloadSource">source</a>.
+This page has been moved to the Wiki with a topic on downloading <a href="http://trac.osgeo.org/gdal/wiki/DownloadingGdalBinaries">binaries (pre-built executables</a> and a topic on downloading <a href="http://trac.osgeo.org/gdal/wiki/DownloadSource">source</a>.
  
 */
diff --git a/doc/gdal_building.dox b/doc/gdal_building.dox
index 017d576..e2e3280 100644
--- a/doc/gdal_building.dox
+++ b/doc/gdal_building.dox
@@ -1,10 +1,10 @@
 #ifndef DOXYGEN_SKIP
-/* $Id: gdal_building.dox 25410 2012-12-31 11:56:53Z rouault $ */
+/* $Id: gdal_building.dox 33134 2016-01-23 23:10:03Z rouault $ */
 #endif /* DOXYGEN_SKIP */
 
 /*!
 \page gdal_building Building GDAL From Source
 
-This topic now lives in the wiki at: http://trac.osgeo.org/gdal/wiki/BuildHints
+This topic now lives in the Wiki at: http://trac.osgeo.org/gdal/wiki/BuildHints
 
 */
diff --git a/doc/gdal_datamodel.dox b/doc/gdal_datamodel.dox
index 6e6effa..073e207 100644
--- a/doc/gdal_datamodel.dox
+++ b/doc/gdal_datamodel.dox
@@ -1,4 +1,4 @@
-/* $Id: gdal_datamodel.dox 29417 2015-06-22 08:30:54Z rouault $ */
+/* $Id: gdal_datamodel.dox 33134 2016-01-23 23:10:03Z rouault $ */
 
 /*!
 \page gdal_datamodel GDAL Data Model
@@ -31,8 +31,8 @@ strings.  This can contain:
 <li> A datum identifier. 
 <li> An ellipsoid name, semi-major axis, and inverse flattening. 
 <li> A prime meridian name and offset from Greenwich. 
-<li> A projection method type (ie. Transverse Mercator). 
-<li> A list of projection parameters (ie. central_meridian). 
+<li> A projection method type (i.e. Transverse Mercator). 
+<li> A list of projection parameters (i.e. central_meridian). 
 <li> A units name, and conversion factor to meters or radians. 
 <li> Names and ordering for the axes. 
 <li> Codes for most of the above in terms of predefined coordinate systems
@@ -139,7 +139,7 @@ Metadata is split into named groups called domains, with the default
 domain having no name (NULL or "").  Some specific domains exist for 
 special purposes.  Note that currently there is no way to enumerate all
 the domains available for a given object, but applications can "test" for
-any domains they know how to interprete.
+any domains they know how to interpret.
 
 The following metadata items have well defined semantics in the default
 domain:
@@ -200,7 +200,7 @@ string that can be displayed to the user in a selector.
 
 Drivers which support subdatasets advertize the DMD_SUBDATASETS capability. 
 This information is reported when the \-\-format and \-\-formats options are 
-passed to the commandline utilities.
+passed to the command line utilities.
 
 Currently, drivers which support subdatasets are: 
 ADRG, ECRGTOC, GEORASTER, GTiff, HDF4, HDF5, netCDF, NITF, NTv2, OGDI, PDF, 
@@ -253,11 +253,11 @@ items defining the model are:
 <li> SAMP_DEN_COEFF (1-20): Sample Denominator Coefficients. Twenty coefficients for the polynomial in the Denominator of the cn equation. (space separated)
 </ul>
 
-These fields are directly derived from the document prospective GeoTIFF RPC document (http://geotiff.maptools.org/rpc_prop.html) which in turn is closely modelled on the NITF RPC00B definition.
+These fields are directly derived from the document prospective GeoTIFF RPC document (http://geotiff.maptools.org/rpc_prop.html) which in turn is closely modeled on the NITF RPC00B definition.
 
 The line and pixel offset expressed with LINE_OFF and SAMP_OFF are with respect to the center of the pixel.
 
-\subsubsection gdal_datamodel_subdatasets IMAGERY Domain
+\subsubsection gdal_datamodel_imagery IMAGERY Domain (remote sensing)
 
 For satellite or aerial imagery the IMAGERY Domain may be present. It depends on exist special metadata files near the image file. The files at the same directory with image file tested by the set of metadata readers, if files can be processed by the metadata reader, it fill the IMAGERY Domain with the following items:
    
@@ -315,7 +315,7 @@ thematic image).
 <li> An optional minimum and maximum value. 
 
 <li> An optional offset and scale for transforming raster values into meaning
-full values (ie translate height to meters) 
+full values (i.e. translate height to meters).
 
 <li> An optional raster unit name.  For instance, this might indicate linear 
 units for elevation data.
@@ -324,7 +324,7 @@ units for elevation data.
 
   <ul> 
   <li> GCI_Undefined: the default, nothing is known.
-  <li> GCI_GrayIndex: this is an independent grayscale image
+  <li> GCI_GrayIndex: this is an independent gray-scale image
   <li> GCI_PaletteIndex: this raster acts as an index into a color table
   <li> GCI_RedBand: this raster is the red portion of an RGB or RGBA image
   <li> GCI_GreenBand: this raster is the green portion of an RGB or RGBA image
@@ -362,7 +362,7 @@ typedef struct
     /- blue, yellow, or saturation -/
     short      c3;      
 
-    /- alpha or blackband -/
+    /- alpha or black band -/
     short      c4;      
 } GDALColorEntry;
 </pre>
@@ -372,7 +372,7 @@ which is one of the following values, and indicates how the c1/c2/c3/c4 values
 of a color entry should be interpreted. 
 
 <ul>
-<li> GPI_Gray: Use c1 as grayscale value. 
+<li> GPI_Gray: Use c1 as gray scale value. 
 <li> GPI_RGB: Use c1 as red, c2 as green, c3 as blue and c4 as alpha.
 <li> GPI_CMYK: Use c1 as cyan, c2 as magenta, c3 as yellow and c4 as black. 
 <li> GPI_HLS: Use c1 as hue, c2 as lightness, and c3 as saturation. 
@@ -381,7 +381,7 @@ of a color entry should be interpreted.
 To associate a color with a raster pixel, the pixel value is used as a
 subscript into the color table.  That means that the colors are always
 applied starting at zero and ascending.  There is no provision for indicating
-a prescaling mechanism before looking up in the color table. 
+a pre-scaling mechanism before looking up in the color table. 
 
 \section gdal_datamodel_rasterband_overviews Overviews
 
diff --git a/doc/gdal_drivertut.dox b/doc/gdal_drivertut.dox
index 9db3d7f..1611b1b 100644
--- a/doc/gdal_drivertut.dox
+++ b/doc/gdal_drivertut.dox
@@ -1,5 +1,5 @@
 #ifndef DOXYGEN_SKIP
-/* $Id: gdal_drivertut.dox 28785 2015-03-26 20:46:45Z goatbar $ */
+/* $Id: gdal_drivertut.dox 33134 2016-01-23 23:10:03Z rouault $ */
 #endif /* DOXYGEN_SKIP */
 
 /*!
@@ -485,7 +485,7 @@ registering it with the GDALDriverManager().
 <ul>
 <li> The description is the short name for the format.  This is a unique 
 name for this format, often used to identity the driver in scripts and 
-commandline programs.  Normally 3-5 characters in length, and matching the 
+command line programs.  Normally 3-5 characters in length, and matching the 
 prefix of the format classes. (mandatory)
 
 <li> GDAL_DCAP_RASTER: set to YES to indicate that this driver handles
@@ -554,14 +554,14 @@ when writing new drivers is to:
 <li> Add a driver directory under gdal/frmts, with the directory name the same
 as the short name.
 
-<li> Add a GNUmakefile and makefile.vc in that directory modelled on those
-from other similar directories (ie. the jdem directory). 
+<li> Add a GNUmakefile and makefile.vc in that directory modeled on those
+from other similar directories (i.e. the jdem directory). 
 
 <li> Add the module with the dataset, and rasterband implementation.  
 Generally this is called <short_name>dataset.cpp, with all the GDAL specific
 code in one file, though that is not required.
 
-<li> Add the registration entry point declaration (ie. GDALRegister_JDEM()) to
+<li> Add the registration entry point declaration (i.e. GDALRegister_JDEM()) to
 gdal/gcore/gdal_frmts.h.
 
 <li> Add a call to the registration function to frmts/gdalallregister.cpp,
@@ -691,7 +691,7 @@ then the application writes various information by calls to set methods.
 The benefits of the first method are that that all the information is available
 at the point the output file is being created.  This can be especially
 important when implementing file formats using external libraries which 
-require information like colormaps, and georeferencing information at the
+require information like color maps, and georeferencing information at the
 point the file is created.  The other advantage of this method is that the
 CreateCopy() method can read some kinds of information, such as min/max, 
 scaling, description and GCPs for which there are no equivalent set methods.
@@ -719,7 +719,7 @@ return result of the progress function needs always to be checked for
 cancellation, and progress should be reported at reasonable intervals.  The
 JPEGCreateCopy() method demonstrates good handling of the progress function.
 
-<li> Special creation options should be documented in the online help.
+<li> Special creation options should be documented in the on-line help.
 If the options take the format "NAME=VALUE" the papszOptions list can be
 manipulated with CPLFetchNameValue() as demonstrated in the handling of
 the QUALITY and PROGRESSIVE flags for JPEGCreateCopy(). 
@@ -877,7 +877,7 @@ size, number of bands, and pixel data type of the desired file is provided
 but other information (such as georeferencing, and imagery data) would be
 supplied later via other method calls on the resulting GDALDataset.  
 
-The following sample implement PCI .aux labelled raw raster creation.  It
+The following sample implement PCI .aux labeled raw raster creation.  It
 follows a common approach of creating a blank, but valid file using non-GDAL
 calls, and then calling GDALOpen(,GA_Update) at the end to return a writable
 file handle.  This avoids having to duplicate the various setup actions in
@@ -899,7 +899,7 @@ GDALDataset *PAuxDataset::Create( const char * pszFilename,
         && eType != GDT_Int16 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-              "Attempt to create PCI .Aux labelled dataset with an illegal\n"
+              "Attempt to create PCI .Aux labeled dataset with an illegal\n"
               "data type (%s).\n",
               GDALGetDataTypeName(eType) );
 
@@ -1129,7 +1129,7 @@ implement this.
 
 \htmlonly
 <p>
-$Id: gdal_drivertut.dox 28785 2015-03-26 20:46:45Z goatbar $
+$Id: gdal_drivertut.dox 33134 2016-01-23 23:10:03Z rouault $
 </p>
 \endhtmlonly
 
diff --git a/doc/gdal_footer.html b/doc/gdal_footer.html
index 682dedc..fd74b6f 100644
--- a/doc/gdal_footer.html
+++ b/doc/gdal_footer.html
@@ -1,6 +1,6 @@
 <hr>
 
-Generated for GDAL by 
+Generated for GDAL by
 <a href="http://www.doxygen.org/index.html"><img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> $doxygenversion.
 </body>
 </html>
diff --git a/doc/gdal_tutorial.dox b/doc/gdal_tutorial.dox
index 17c7ac4..c0fc37a 100644
--- a/doc/gdal_tutorial.dox
+++ b/doc/gdal_tutorial.dox
@@ -1,4 +1,4 @@
-/* $Id: gdal_tutorial.dox 26639 2013-11-20 12:34:03Z rouault $ */
+/* $Id: gdal_tutorial.dox 33134 2016-01-23 23:10:03Z rouault $ */
 
 /*!
 \page gdal_tutorial GDAL API Tutorial
@@ -170,7 +170,7 @@ In Python:
 \section gdal_tutorial_band Fetching a Raster Band
 
 At this time access to raster data via GDAL is done one band at a time.
-Also, there is metadata, blocksizes, color tables, and various other 
+Also, there is metadata, block sizes, color tables, and various other 
 information available on a band by band basis.  The following codes fetches
 a GDALRasterBand object from the dataset (numbered 1 through GetRasterCount())
 and displays a little information about it.
@@ -481,7 +481,7 @@ In Python:
     src_ds = None
 \endcode
 
-Note that the CreateCopy() method returns a writeable dataset, and that it
+Note that the CreateCopy() method returns a writable dataset, and that it
 must be closed properly to complete writing and flushing the dataset to disk.
 In the Python case this occurs automatically when "dst_ds" goes out of scope. 
 The FALSE (or 0) value used for the bStrict option just after the destination
@@ -651,7 +651,7 @@ In Python:
 
 \htmlonly
 <p>
-$Id: gdal_tutorial.dox 26639 2013-11-20 12:34:03Z rouault $
+$Id: gdal_tutorial.dox 33134 2016-01-23 23:10:03Z rouault $
 </p>
 \endhtmlonly
 
diff --git a/doc/index.dox b/doc/index.dox
index c8bc598..70b51d9 100644
--- a/doc/index.dox
+++ b/doc/index.dox
@@ -1,5 +1,5 @@
 #ifndef DOXYGEN_SKIP                                                            
-/* $Id: index.dox 29079 2015-04-30 14:50:02Z rouault $ */               
+/* $Id: index.dox 33196 2016-01-29 10:56:46Z rouault $ */               
 #endif /* DOXYGEN_SKIP */                                                       
 
 /*! \mainpage GDAL - Geospatial Data Abstraction Library
@@ -15,10 +15,10 @@ Geospatial Foundation</a>.  As a library, it presents a
 \link gdal_datamodel.html single raster abstract data model\endlink and
 \link ogr_arch.html vector abstract data model\endlink  
 to the calling application for all supported formats.  It also comes with a variety
-of useful commandline utilities
+of useful command line utilities
 for data translation and processing.  The 
-<a href="http://trac.osgeo.org/gdal/wiki/Release/1.11.2-News">NEWS</a>
-page describes the February 2015 GDAL/OGR 1.11.2 release.
+<a href="http://trac.osgeo.org/gdal/wiki/Release/2.0.2-News">NEWS</a>
+page describes the January 2016 GDAL/OGR 2.0.2 release.
 
 Traditionally GDAL used to design the raster part of the library, and OGR the
 vector part for Simple Features. Starting with GDAL 2.0, both sides have been
@@ -35,10 +35,11 @@ Download:
 <ul>
 <li> <a href="http://trac.osgeo.org/gdal/">Wiki</a> - Various user and developer contributed documentation and hints
 <li> <a href="http://trac.osgeo.org/gdal/wiki/DownloadingGdalBinaries">Downloads</a> - Ready to use binaries (executables)
-<li> <a href="formats_list.html">Supported raster formats</a> (139 drivers) : <a href="frmt_gtiff.html">GeoTIFF</a>, <a href="frmt_hfa.html">Erdas Imagine</a>, <a href="frmt_ecw.html">ECW</a>, <a href="frmt_mrsid.html">MrSID</a>, <a href="frmt_jp2openjpeg.html">JPEG2000</a>, <a href="frmt_dted.html">DTED</a>, <a href="frmt_nitf.html">NITF</a>, <a href="drv_geopackage_raster.html">GeoPackage</a>, ...
-<li> <a href="ogr_formats.html">Supported vector formats</a> (83 drivers): <a href="drv_shapefile.html">ESRI Shapefile</a>, <a href="drv_sde.html">ESRI ArcSDE</a>, <a href="drv_openfilegdb.html">ESRI FileGDB</a>, <a href="drv_mitab.html">MapInfo (tab and mid/mif)</a>, <a href="drv_gml.html">GML</a>, <a href="drv_libkml.html">KML</a>, <a href="drv_pg.html">PostGIS</a>, <a href="drv_oci.html">Oracle Spatial</a>, <a href="drv_geopackage.html">GeoPackage</a>, ...
+<li> <a href="formats_list.html">Supported raster formats</a> (142 drivers) : <a href="frmt_gtiff.html">GeoTIFF</a>, <a href="frmt_hfa.html">Erdas Imagine</a>, <a href="frmt_ecw.html">ECW</a>, <a href="frmt_mrsid.html">MrSID</a>, <a href="frmt_jp2openjpeg.html">JPEG2000</a>, <a href="frmt_dted.html">DTED</a>, <a href="frmt_nitf.html">NITF</a>, <a href="drv_geopackage_raster.html">GeoPackage</a>, ...
+<li> <a href="ogr_formats.html">Supported vector formats</a> (84 drivers): <a href="drv_shapefile.html">ESRI Shapefile</a>, <a href="drv_sde.html">ESRI ArcSDE</a>, <a href="drv_openfilegdb.html">ESRI FileGDB</a>, <a href="drv_mitab.html">MapInfo (tab and mid/mif)</a>, <a href="drv_gml.html">GML</a>, <a href="drv_libkml.html">KML</a>, <a href="drv_pg.html">PostGIS</a>, <a href="drv_oci.html">Oracle Spatial</a>, <a href="drv_geopackage.html">GeoPackage</a>, ...
 <li> <a href="gdal_utilities.html">Raster utility programs</a> : <a href="gdalinfo.html">gdalinfo</a>, <a href="gdal_translate.html">gdal_translate</a>, <a href="gdaladdo.html">gdaladdo</a>, <a href="gdalwarp.html">gdalwarp</a>, ...
 <li> <a href="ogr_utilities.html">Vector utility programs</a> : <a href="ogrinfo.html">ogrinfo</a>, <a href="ogr2ogr.html">ogr2ogr</a>, <a href="ogrtindex.html">ogrtindex</a>, ...
+<li> <a href="gnm_utilities.html">Geographic Network utility programs</a> : <a href="gnmmanage.html">gnmmanage</a>, <a href="gnmanalyse.html">gnmanalyse</a>, ...
 <li> <a href="http://trac.osgeo.org/gdal/wiki/FAQ">GDAL FAQ</a>
 <li> <a href="gdal_datamodel.html">Raster</a> and <a href="ogr_arch.html">Vector</a> data models and architecture
 <li> <a href="http://trac.osgeo.org/gdal/wiki/GovernanceAndCommunity">GDAL/OGR Governance and Community Participation</a>
@@ -52,19 +53,34 @@ Download:
 <ul>
 <li> <a href="http://trac.osgeo.org/gdal/wiki/BuildHints">Building GDAL From Source</a>
 <li> <a href="http://trac.osgeo.org/gdal/wiki/DownloadSource">Downloads</a> - source code
-<li> <a href="wince.html">GDAL for Windows CE (unmaintained)</a>
 </ul>
 
 \subsection index_devdocs_tutorials Tutorials
 
 <ul>
-<li> <a href="gdal_tutorial.html">Raster API tutorial</a>
-<li> <a href="ogr_apitut.html">Vector API tutorial</a>
-<li> <a href="gdal_drivertut.html">Raster driver implementation</a>
-<li> <a href="ogr_drivertut.html">Vector driver implementation</a>
-<li> <a href="warptut.html">GDAL Warp API tutorial</a> (Reprojection, ...)
+<li> Raster topics:
+  <ul>
+    <li> <a href="gdal_tutorial.html">Raster API tutorial</a>
+    <li> <a href="gdal_drivertut.html">Raster driver implementation</a>
+    <li> <a href="gdal_vrttut.html">Raster Virtual format (VRT)</a>
+    <li> <a href="warptut.html">GDAL Warp API tutorial</a> (Reprojection, ...)
+  </ul>
+</li>
+<li> Vector topics:
+  <ul>
+    <li> <a href="ogr_apitut.html">Vector API tutorial</a>
+    <li> <a href="ogr_drivertut.html">Vector driver implementation</a>
+    <li> <a href="drv_vrt.html">Vector Virtual format (VRT)</a>
+    <li> <a href="ogr_feature_style.html">OGR - Feature Style Specification</a>
+   </ul>
+</li>
+<li> Geographic Network Model topics:
+  <ul>
+    <li> <a href="gnm_arch.html">GNM basics</a>
+    <li> <a href="gnm_tut.html">GNM API tutorial</a>
+   </ul>
+</li>
 <li> <a href="osr_tutorial.html">Projections and Spatial Reference Systems tutorial</a> (OSR - OGRSpatialReference)
-<li> <a href="ogr_feature_style.html">OGR - Feature Style Specification</a>
 </ul>
 
 \subsection index_devdocs_api API documentation
@@ -74,6 +90,7 @@ Download:
 <li> <a href="gdal_8h.html">gdal.h: Raster C API</a>
 <li> <a href="ogr__api_8h.html">ogr_api.h: Vector C API</a>
 <li> <a href="gdal__alg_8h.html">gdal_alg.h: GDAL Algorithms C API</a>
+<li> <a href="gdal__utils_8h.html">gdal_utils.h: GDAL Utilities C API</a>
 <li> <a href="classGDALDataset.html">GDALDataset C++ API</a>
 <li> <a href="classGDALRasterBand.html">GDALRasterBand C++ API</a>
 <li> <a href="classOGRLayer.html">OGRLayer C++ API</a>
@@ -95,16 +112,16 @@ or <a href="http://home.gdal.org/projects/opengis/wkt_prop.doc">doc</a> format.
 \htmlonly 
 <table border="0" cellspacing="4" cellpadding="4"> 
 
-<tr><td><a href="http://2015.foss4g.org/"> 
-<img src="foss4g2015.png" alt="FOSS4G 2015" border="0" width="150" height="75"> 
+<tr><td><a href="http://2016.foss4g.org/"> 
+<img src="http://wiki.osgeo.org/images/f/ff/Foss4g2016_logo_squared.png" alt="FOSS4G 2016" border="0"> 
 </a></td> 
  
-<td><a href="http://2015.foss4g.org">FOSS4G 2015</a> is the leading annual  
+<td><a href="http://2016.foss4g.org">FOSS4G 2016</a> is the leading annual  
 conference for free and open source geospatial software.  It will include  
 presentations related to GDAL/OGR, and some of the GDAL/OGR  
 development community will be attending.  It is <i>the</i> event for those  
 interested in GDAL/OGR, other FOSS geospatial technologies and the community  
-around them. The conference will be held in Seoul, South Korea <strong>September 14th - 19th, 2015</strong>.</td>
+around them. The conference will be held in Bonn, Germany, <strong>August 24th - 26th, 2016</strong>.</td>
 </table> 
 \endhtmlonly
 
@@ -135,17 +152,8 @@ listed</a> using Trac.<p>
 
 \section index_bindings GDAL In Other Languages
 
-The following bindings of GDAL in other languages are available:
-
-<ul>
-<li> <a href="http://trac.osgeo.org/gdal/wiki/GdalOgrInPerl">Perl</a>
-<li> <a href="http://trac.osgeo.org/gdal/wiki/GdalOgrInPython">Python</a>
-<li> <a href="vb6_tutorial.html">VB6 Bindings</a> (not using SWIG)
-<li> <a href="http://trac.osgeo.org/gdal/wiki/GdalOgrInJava">Java</a>
-<li> <a href="http://trac.osgeo.org/gdal/wiki/GdalOgrInCsharp">C# / .Net</a>
-<li> <a href="http://trac.osgeo.org/gdal/wiki/GdalOgrInRuby">Ruby</a>
-<li> <a href="http://trac.osgeo.org/gdal/wiki/GdalOgrInR">R</a>
-
-</ul>
+The list of bindings of GDAL in other languages is maintained on the
+<a href="http://trac.osgeo.org/gdal/#GDALOGRInOtherLanguages">GDAL
+Wiki</a>.
 
 */
diff --git a/doc/ru/Doxyfile b/doc/ru/Doxyfile
index 4153adb..2223f14 100644
--- a/doc/ru/Doxyfile
+++ b/doc/ru/Doxyfile
@@ -962,7 +962,7 @@ SKIP_FUNCTION_MACROS   = YES
 # Adding location for the tag files is done as follows: 
 #   TAGFILES = file1=loc1 "file2 = loc2" ... 
 # where "loc1" and "loc2" can be relative or absolute paths or 
-# URLs. If a location is present for each tag, the installdox tool 
+# URLs. If a location is present for each tag, the installdox tool
 # does not have to be run to correct the links.
 # Note that each tag file must have a unique name
 # (where the name does NOT include the path)
diff --git a/doc/ru/gdal_datamodel_ru.dox b/doc/ru/gdal_datamodel_ru.dox
index 43a4524..08186e7 100644
--- a/doc/ru/gdal_datamodel_ru.dox
+++ b/doc/ru/gdal_datamodel_ru.dox
@@ -1,8 +1,9 @@
 #ifndef DOXYGEN_SKIP
 /*
-$Id: gdal_datamodel_ru.dox 14551 2008-05-28 11:11:20Z dron $
+$Id: gdal_datamodel_ru.dox 30822 2015-10-03 22:38:55Z bishop $
 Translation corresponds to gdal_datamodel.dox 14550 2008-05-28 10:55:15Z
 Translator Andrey Kiselev <dron at remotesensing.org>
+Translator Dmitry Baryshnikov <polimax at mail.ru>
 */
 #endif /* DOXYGEN_SKIP */
 
@@ -21,7 +22,7 @@ Translator Andrey Kiselev <dron at remotesensing.org>
 высоты), общем для всех каналов. Набор данных также отвечает за географическую
 привязку и указание координатной системы, также общими для всех каналов. Сам
 набор данных может иметь ассоциированный комплект метаданных: список пар
-ключ/значение в форме ASCIIZ строк
+ключ/значение в текстовом виде.
 
 Заметим, что набор данных GDAL и модель растровых каналов изначально
 базируется на спецификации регулярных покрытий консорциума OpenGIS. 
@@ -185,13 +186,24 @@ TIFFTAG_DATETIME=1999:05:11 11:29:56
 значений: Covariance_11, Covariance_22, Covariance_33, Covariance_12,
 Covariance_13, Covariance_23 (поскольку сама матрица Эрмитова, то этих данных
 достаточно для её задания).
+<li> METADATATYPE: Если имеется домен IMAGERY, то в данной записи содержится название
+класса при помощи которого были извлечены метаданные. На текущий момент имеются следующие
+классы:
+    <ul>
+    <li>  DG: метаданные ДДЗ DigitalGlobe
+    <li>  GE: метаданные ДДЗ GeoEye
+    <li>  OV: метаданные ДДЗ OrbView
+    <li>  DIMAP: метаданные ДДЗ Астриум (Pleiades, SPOT, ...)
+    <li>  MSP: метаданные ДДЗ с КА Ресурс-ДК1
+    <li>  ODL: метаданные ДДЗ с КА Landsat
+    </ul>
 </ul>
 
 \subsubsection gdal_datamodel_ru_subdatasets Домен вложенных наборов данных (SUBDATASETS)
 
 Домен SUBDATASETS содержит список дочерних наборов данных. Обычно он
 используется для получения указателей на изображения, хранящиеся все вместе в
-едином файле (таком, как HDF или NITF). Например, файл формата NITF с четырьмя
+едином файле (таком, как HDF или NITF). Например, файл формата NITF с двумя
 изображениями может иметь следующий список вложенных наборов данных: 
 
 <pre>
@@ -199,12 +211,6 @@ Covariance_13, Covariance_23 (поскольку сама матрица Эрм
   SUBDATASET_1_DESC=Image 1 of multi_1b.ntf
   SUBDATASET_2_NAME=NITF_IM:1:multi_1b.ntf
   SUBDATASET_2_DESC=Image 2 of multi_1b.ntf
-  SUBDATASET_3_NAME=NITF_IM:2:multi_1b.ntf
-  SUBDATASET_3_DESC=Image 3 of multi_1b.ntf
-  SUBDATASET_4_NAME=NITF_IM:3:multi_1b.ntf
-  SUBDATASET_4_DESC=Image 4 of multi_1b.ntf
-  SUBDATASET_5_NAME=NITF_IM:4:multi_1b.ntf
-  SUBDATASET_5_DESC=Image 5 of multi_1b.ntf
 </pre>
 
 Значение записи _NAME --- строка, которая может быть передана в функцию
@@ -212,6 +218,14 @@ GDALOpen() для получения доступа к изображению. 
 для описания изображения в виде читаемой человеком строки и может быть
 показана пользователю для облегчения выбора.
 
+Драйверы, которые поддерживают дочерние наборы данных сообщают об этом через значение
+DMD_SUBDATASETS. Данные выводятся при передаче ключей \-\-format and \-\-formats  
+в утилиты командной строки.
+
+На текущий момент дочерние наборы поддерживают следующие драйверы: 
+ADRG, ECRGTOC, GEORASTER, GTiff, HDF4, HDF5, netCDF, NITF, NTv2, OGDI, PDF, 
+PostGISRaster, Rasterlite, RPFTOC, RS2, WCS, и WMS.
+
 \subsubsection gdal_datamodel_ru_image_structure Домен структуры изображения (IMAGE_STRUCTURE)
 
 Метаданные в базовом домене содержат информацию, связанную с изображением,
@@ -281,6 +295,20 @@ Coefficient). Эта геометрическая модель может быт
 (http://geotiff.maptools.org/rpc_prop.html), который в свою очередь следует
 определению NITF RPC00B.
 
+\subsubsection gdal_datamodel_ru_imagery Домен метаданных ДДЗ (IMAGERY)
+
+Для материалов воздушной или космической съемки может быть задан домен IMAGERY. 
+Наличие такого домена зависит от специальных файлов метаданных, которые обычно
+размещаются рядом с файлом изображения. Файлы метаданных передаются в классы 
+чтения метаданных, которые, если поддерживают переданные формат, заполняют домен
+следующими величинами:
+   
+<ul>
+<li>  SATELLITEID: Название КА или аппаратуры наблюдения
+<li>  CLOUDCOVER: Облачность. Значение между 0 - 100 или 999 при отсутствии
+<li>  ACQUISITIONDATETIME: Дата и время съемки в UTC
+</ul>  
+
 \subsubsection gdal_datamodel_ru_xml Домены "xml:"
 
 Любой домен, чьё имя имеет префикс "xml:", является не обычной базой
diff --git a/doc/ru/gdal_tutorial_ru.dox b/doc/ru/gdal_tutorial_ru.dox
index b404380..104e02d 100644
--- a/doc/ru/gdal_tutorial_ru.dox
+++ b/doc/ru/gdal_tutorial_ru.dox
@@ -1,7 +1,8 @@
 /*
-$Id: gdal_tutorial_ru.dox 14542 2008-05-27 18:11:25Z dron $
+$Id: gdal_tutorial_ru.dox 30780 2015-10-01 10:42:39Z bishop $
 Translation corresponds to gdal_tutorial.dox 14528 2008-05-26 03:07:21Z
 Translator Andrey Kiselev <dron at remotesensing.org>
+Translator Dmitry Baryshnikov <polimax at mail.ru>
 */
 
 /*!
@@ -25,6 +26,7 @@ GDALOpen() для открытия набора данных. В качеств
 На языке C++:
 \code
 #include "gdal_priv.h"
+#include "cpl_conv.h" // for CPLMalloc()
 
 int main()
 {
@@ -42,6 +44,7 @@ int main()
 На языке C:
 \code
 #include "gdal.h"
+#include "cpl_conv.h" /* for CPLMalloc() */
 
 int main()
 {
@@ -271,6 +274,8 @@ In C:
                           0, 0 );
 \endcode
 
+Буффер pafScanline должен быть освобожден при помощи CPLFree() после его использования.
+
 На языке C:
 \code
 	float *pafScanline;
@@ -282,6 +287,8 @@ In C:
                       0, 0 );
 \endcode
 
+Буффер pafScanline должен быть освобожден при помощи CPLFree() после его использования.
+
 На языке Python:
  
 \code
@@ -342,9 +349,15 @@ pData --- это указатель на буфер в памяти, куда д
 Пожалуйста, постоянно помните, что объекты GDALRasterBand <i>принадлежат</i> к
 своему набору данных и они никогда не должны удаляться с помощью оператора
 delete языка C++. Наборы данных GDALDataset могут быть закрыты либо с помощью
-вызова функции GDALClose(), либо с использованием оператора delete для объекта
-GDALDataset. Любой вариант приведёт к корректному освобождению памяти и сбросу
-на диск всех незаписанных данных.
+вызова функции GDALClose() (настоятельно НЕ рекомендуется использовать оператор
+delete для освобождения GDALDataset для пользователей Windows из-за извесной ошибки
+получения и освобождения памяти через границы модуля. Подробнее см. 
+<a href="http://trac.osgeo.org/gdal/wiki/FAQMiscellaneous#HowshouldIdeallocateresourcesacquaintedfromGDALonWindows">раздел</a> в FAQ).
+Вызов GDALClose приведет к правильной очистке и выполнении всех ожидающих операций
+записи.
+Если забыть выполнить GDALClose для набора данных в режиме редактирования в одном
+из популярных форматов, например, GTiff, может привести к тому, что набор данных
+больше не сможет открываться.
 
 \section gdal_tutorial_ru_creation Способы создания файлов
 
@@ -485,6 +498,8 @@ CreateCopy(), показывает, что CreateCopy() должен завер
     papszOptions = CSLSetNameValue( papszOptions, "COMPRESS", "PACKBITS" );
     poDstDS = poDriver->CreateCopy( pszDstFilename, poSrcDS, FALSE, 
                                     papszOptions, GDALTermProgress, NULL );
+    
+    /* Once we're done, close properly the dataset */
     if( poDstDS != NULL )
         delete poDstDS;
     CSLDestroy( papszOptions );
@@ -500,6 +515,7 @@ CreateCopy(), показывает, что CreateCopy() должен завер
     papszOptions = CSLSetNameValue( papszOptions, "COMPRESS", "PACKBITS" );
     hDstDS = GDALCreateCopy( hDriver, pszDstFilename, hSrcDS, FALSE, 
                              papszOptions, GDALTermProgres, NULL );
+    /* Once we're done, close properly the dataset */                         
     if( hDstDS != NULL )
         GDALClose( hDstDS );
     CSLDestroy( papszOptions );
@@ -511,6 +527,9 @@ CreateCopy(), показывает, что CreateCopy() должен завер
     src_ds = gdal.Open( src_filename )
     dst_ds = driver.CreateCopy( dst_filename, src_ds, 0, 
                                 [ 'TILED=YES', 'COMPRESS=PACKBITS' ] )
+    # Once we're done, close properly the dataset
+    dst_ds = None
+    src_ds = None                                
 \endcode
 
 \section gdal_tutorial_ru_create Использование метода Create()
@@ -568,7 +587,8 @@ CreateCopy(), показывает, что CreateCopy() должен завер
     poBand->RasterIO( GF_Write, 0, 0, 512, 512, 
                       abyRaster, 512, 512, GDT_Byte, 0, 0 );    
 
-    delete poDstDS;
+    /* Once we're done, close properly the dataset */
+    GDALClose( (GDALDatasetH) poDstDS );
 \endcode
 
 На языке C:
@@ -594,13 +614,15 @@ CreateCopy(), показывает, что CreateCopy() должен завер
     GDALRasterIO( hBand, GF_Write, 0, 0, 512, 512, 
                   abyRaster, 512, 512, GDT_Byte, 0, 0 );    
 
+    /* Once we're done, close properly the dataset */
     GDALClose( hDstDS );
 \endcode
 
 На языке Python:
 
 \code
-    import Numeric, osr
+    import osr
+    import numpy
 
     dst_ds.SetGeoTransform( [ 444720, 30, 0, 3751320, 0, -30 ] )
     
@@ -609,13 +631,16 @@ CreateCopy(), показывает, что CreateCopy() должен завер
     srs.SetWellKnownGeogCS( 'NAD27' )
     dst_ds.SetProjection( srs.ExportToWkt() )
 
-    raster = Numeric.zeros( (512, 512) )    
+    raster = numpy.zeros( (512, 512), dtype=numpy.uint8 )    
     dst_ds.GetRasterBand(1).WriteArray( raster )
+
+    # Once we're done, close properly the dataset
+    dst_ds = None
 \endcode
 
 \htmlonly
 <p>
-$Id: gdal_tutorial_ru.dox 14542 2008-05-27 18:11:25Z dron $
+$Id: gdal_tutorial_ru.dox 30780 2015-10-01 10:42:39Z bishop $
 </p>
 \endhtmlonly
 
diff --git a/doc/ru/index_ru.dox b/doc/ru/index_ru.dox
index 597762c..c33cad9 100644
--- a/doc/ru/index_ru.dox
+++ b/doc/ru/index_ru.dox
@@ -1,40 +1,42 @@
-#ifndef DOXYGEN_SKIP                                                            
-/* $Id: index_ru.dox 19610 2010-05-02 11:50:23Z ilucena $ */               
+#ifndef DOXYGEN_SKIP
+/* $Id: index_ru.dox 32998 2016-01-15 14:46:13Z bishop $ */
 Translation corresponds to index.dox 14537 2008-05-27 17:12:02Z
 Translator Andrey Kiselev <dron at ak4719.spb.edu>
-#endif /* DOXYGEN_SKIP */                                                       
+Translator Dmitry Baryshnikov <polimax at mail.ru>
+#endif /* DOXYGEN_SKIP */
 
 /*! \page index_ru GDAL - Geospatial Data Abstraction Library
 
 <center><b>Select language</b>: <a href="index.html">[English]</a>[Russian]<a href="index_br.html">[Portuguese]</a></center>
 
-\htmlonly<img src="gdalicon.png" alt="GDAL">\endhtmlonly \latexonly GDAL \endlatexonly
+\htmlonly<img src="gdalicon.png" alt="GDAL">\endhtmlonly \latexonly GDAL/OGR \endlatexonly
 --- это библиотека для работы с растровыми географическими форматами файлов
 данных. GDAL распространяется
 <a href="http://www.osgeo.org/">Open Source Geospatial Foundation</a>
-на условиях лицензии 
+на условиях лицензии
 <a href="http://trac.osgeo.org/gdal/wiki/FAQGeneral#WhatlicensedoesGDALOGRuse">X/MIT</a>
 , то есть является
 проектом с <a href="http://www.opensource.org/">открытым исходным кодом</a>.
 Как библиотека GDAL предоставляет вызывающему приложению
 \link gdal_datamodel_ru.html единую обобщённую модель данных\endlink для всех
 поддерживаемых форматов файлов данных. Помимо этого в состав GDAL входит
-<a class="el" href="gdal_utilities.html"> 
+<a class="el" href="gdal_utilities.html">
 набор вспомогательных программ</a>, вызываемых
 из командной строки, для преобразования и обработки данных. Описание выпуска
-GDAL/OGR 1.5.1 (март 2008) можно найти на странице
-<a href="http://trac.osgeo.org/gdal/wiki/Release/1.5.1-News">новостей</a>.
+GDAL/OGR 2.0.1 (сентябрь 2015) можно найти на странице
+<a href="http://trac.osgeo.org/gdal/wiki/Release/2.0.1-News">новостей</a>.
 
 Связанная с GDAL библиотека
 <a href="ogr">OGR</a> (исходные тексты которой поставляются вместе с GDAL)
-предоставляет сходные возможности для работы с векторными данными. На странице
-<a href="NEWS.html">обновлений</a> вы сможете найти описание версии 1.3.1,
-выпущенной в октябре 2005 г.<p>
+предоставляет сходные возможности для работы с векторными данными. Начиная с версии 2.0
+обе части бибилиотеки (GDAL и OGR) еще более интегрированы. Документация на GDAL 1.X
+доступна по <a href="http://gdal.org/1.11/index.html"> этой ссылке</a>.
+<p>
 
 Главная страница: http://www.gdal.org<br>
-Загрузить: 
-<a href="ftp://ftp.remotesensing.org/gdal">ftp at remotesensing.org</a>,
-<a href="http://download.osgeo.org/gdal">http at download.osgeo.org</a>.
+Загрузить:
+<a href="ftp://ftp.remotesensing.org/gdal"> по протоколу ftp из remotesensing.org</a>,
+<a href="http://download.osgeo.org/gdal"> по протоколу http из download.osgeo.org</a>.
 
 \section index_userdocs_ru Документация для пользователей
 
@@ -43,51 +45,95 @@ GDAL/OGR 1.5.1 (март 2008) можно найти на странице
 предоставленные пользователями и разработчиками.
 <li> <a href="http://trac.osgeo.org/gdal/wiki/DownloadingGdalBinaries">
 Загрузить</a> --- Готовые исполняемые файлы.
-<li> <a href="formats_list.html">Поддерживаемые форматы</a>.
-<li> <a href="gdal_utilities.html">Вспомогательные программы GDAL</a>.
-<li> <a href="http://trac.osgeo.org/gdal/wiki/FAQ">GDAL FAQ</a>.
-<li> <a href="gdal_datamodel_ru.html">Модель данных GDAL</a>.
-<li> <a href="http://trac.osgeo.org/gdal/wiki/GovernanceAndCommunity">
-Сообщество GDAL/OGR и управление проектом</a>.
-<li> <a href="http://www.osgeo.org/search_profile?SET=1&MUL_TECH[0]=00013">
-Списки компаний, предоставляющих услуги с использованием GDAL</a>.
-<li> <a href="credits.html">Благодарности</a>.
-<li> <a href="http://trac.osgeo.org/gdal/wiki/SoftwareUsingGdal">
-Программное обеспечение, использующее GDAL</a>.
+<li> <a href="formats_list.html">Поддерживаемые растровые форматы</a> (142 драйвера) : <a href="frmt_gtiff.html">GeoTIFF</a>, <a href="frmt_hfa.html">Erdas Imagine</a>, <a href="frmt_ecw.html">ECW</a>, <a href="frmt_mrsid.html">MrSID</a>, <a href="frmt_jp2openjpeg.html">JPEG2000</a>, <a href="frmt_dted.html">DTED</a>, <a href="frmt_nitf.html">NITF</a>, <a href="drv_geopackage_raster.html">GeoPackage</a>, ...
+<li> <a href="ogr_formats.html">Поддерживаемые векторные форматы</a> (84 драйвера): <a href="drv_shapefile.html">ESRI Shapefile</a>, <a href="drv_sde.html">ESRI ArcSDE</a>, <a href="drv_openfilegdb.html">ESRI FileGDB</a>, <a href="drv_mitab.html">MapInfo (tab and mid/mif)</a>, <a href="drv_gml.html">GML</a>, <a href="drv_libkml.html">KML</a>, <a href="drv_pg.html">PostGIS</a>, <a href="drv_oci.html">Oracle Spatial</a>, <a href="drv_geopackage.html">GeoPackage</a>, ...
+<li> <a href="gdal_utilities.html">Вспомогательные программы для растров</a> : <a href="gdalinfo.html">gdalinfo</a>, <a href="gdal_translate.html">gdal_translate</a>, <a href="gdaladdo.html">gdaladdo</a>, <a href="gdalwarp.html">gdalwarp</a>, ...
+<li> <a href="ogr_utilities.html">Вспомогательные программы для векторов</a> : <a href="ogrinfo.html">ogrinfo</a>, <a href="ogr2ogr.html">ogr2ogr</a>, <a href="ogrtindex.html">ogrtindex</a>, ...
+<li> <a href="gnm_utilities.html">Вспомогательные программы для работы с сетевой моделью</a> : <a href="gnmmanage.html">gnmmanage</a>, <a href="gnmanalyse.html">gnmanalyse</a>, ...
+<li> <a href="http://trac.osgeo.org/gdal/wiki/FAQ">GDAL FAQ</a>
+<li> Модели <a href="gdal_datamodel_ru.html">растровых</a> и <a href="ogr_arch.html">векторных</a>  данных и архитектура
+<li> <a href="http://trac.osgeo.org/gdal/wiki/GovernanceAndCommunity">Сообщество GDAL/OGR и управление проектом</a>
+<li> <a href="http://www.osgeo.org/search_profile?SET=1&MUL_TECH[0]=00013">Списки компаний, предоставляющих услуги с использованием GDAL</a> (не проверено)
+<li> <a href="credits.html">Благодарности</a>
+<li> <a href="http://trac.osgeo.org/gdal/wiki/SoftwareUsingGdal">Программное обеспечение, использующее GDAL</a>
 </ul>
 
 \section index_devdocs_ru Документация для разработчиков
 
 <ul>
-<li> <a href="http://trac.osgeo.org/gdal/wiki/BuildHints">
-Сборка GDAL из исходных текстов</a>.
-<li> <a href="http://trac.osgeo.org/gdal/wiki/DownloadSource">Загрузить</a>
-исходные тексты.
-<li> <a href="hierarchy.html">Описание программного интерфейса</a> 
-<li> <a href="gdal_tutorial_ru.html">Руководство по использованию GDAL</a>
-<li> <a href="gdal_drivertut.html">Руководство по написанию драйверов GDAL</a>
-<li> <a href="warptut.html">Руководство по использованию интерфейса трансформации</a>
-<li> <a href="ogr/osr_tutorial.html">Руководство по OGRSpatialReference</a>
-<li> <a href="gdal_8h.html">gdal.h</a> - интерфейс GDAL для языка C.
-<li> <a href="classGDALDataset.html">GDALDataset</a>
-<li> <a href="classGDALRasterBand.html">GDALRasterBand</a>
-<li> <a href="wince.html">GDAL для Windows CE</a>
+<li> <a href="http://trac.osgeo.org/gdal/wiki/BuildHints">Сборка GDAL из исходных текстов</a>.
+<li> <a href="http://trac.osgeo.org/gdal/wiki/DownloadSource">Загрузить</a> исходные тексты.
 </ul>
 
+\subsection index_devdocs_tutorials Tutorials
+
+<ul>
+<li> Разделы по растрам:
+  <ul>
+    <li> <a href="gdal_tutorial_ru.html">Руководство по API работы с растрами</a>
+    <li> <a href="gdal_drivertut.html">Создание драйвера для работы с растром</a>
+    <li> <a href="gdal_vrttut.html">Формат виртуальных растров (VRT)</a>
+    <li> <a href="warptut.html">Руководство по GDAL Warp API</a> (Перепроецирование, ...)
+  </ul>
+</li>
+<li> Разделы по векторам:
+  <ul>
+    <li> <a href="ogr_apitut.html">Руководство по API работы с векторными данными</a>
+    <li> <a href="ogr_drivertut.html">Создание драйвера для работы с векторными данными</a>
+    <li> <a href="drv_vrt.html">Формат виртуальных векторных данных (VRT)</a>
+    <li> <a href="ogr_feature_style.html">OGR - Спецификация языка описания стилей</a>
+   </ul>
+</li>
+<li> Разделы по географической сетевой модели:
+  <ul>
+    <li> <a href="gnm_arch.html">Основы географической сетевой модели</a>
+    <li> <a href="gnm_tut.html">Руководство по API работы с сетевой моделью</a>
+   </ul>
+</li>
+<li> <a href="osr_tutorial.html">Руководство по проекциям и системам координат</a> (OSR - OGRSpatialReference)
+</ul>
+
+\subsection index_devdocs_api Документация по API
+
+
+<ul>
+<li> <a href="hierarchy.html">Документация по API</a>
+<li> <a href="gdal_8h.html">gdal.h: C API растров</a>
+<li> <a href="ogr__api_8h.html">ogr_api.h: C API векторных данных</a>
+<li> <a href="gdal__alg_8h.html">gdal_alg.h: C API алгоритмов GDAL</a>
+<li> <a href="classGDALDataset.html">GDALDataset C++ API</a>
+<li> <a href="classGDALRasterBand.html">GDALRasterBand C++ API</a>
+<li> <a href="classOGRLayer.html">OGRLayer C++ API</a>
+<li> Диалект <a href="ogr_sql.html">OGR SQL</a> и диалект <a href="ogr_sql_sqlite.html">SQLITE SQL</a>
+</ul>
+
+<!--
+\subsection index_devdocs_specs Спецификации
+
+<ul>
+<li> <a href="http://home.gdal.org/projects/opengis/twohalfdsf.html">Adam's 2.5 D Simple Features Proposal (OGC 99-402r2)</a>
+<li> Adam's SRS WKT Clarification Proposal in <a href="http://home.gdal.org/projects/opengis/wkt_prop.html">html</a>
+or <a href="http://home.gdal.org/projects/opengis/wkt_prop.doc">doc</a> format.
+</ul>
+-->
+
 \section foss4g Конференция
 
 \htmlonly
-<a href="http://www.foss4g2008.org/"><center>
-<img src="foss4g08.jpg" alt="" border="0" width="500" height="134">
-</center></a>
+<table border="0" cellspacing="4" cellpadding="4">
+
+<tr><td><a href="http://2016.foss4g.org/"> 
+<img src="http://wiki.osgeo.org/images/f/ff/Foss4g2016_logo_squared.png" alt="FOSS4G 2016" border="0"> 
+</a></td> 
 
-<a href="http://www.foss4g2008.org">FOSS4G 2008</a> основная ежегодная
+<td><a href="http://2016.foss4g.org">FOSS4G 2016</a> основная ежегодная
 конференция разработчиков открытого и свободного географического программного
 обеспечения. Будут представлены доклады и проведены семинары по GDAL/OGR,
 конференцию посетят многие участники сообщества GDAL/OGR. Это <i>важное</i>
 событие для всех, кто интересуется GDAL/OGR и другими свободными технологиями
 в области географии и картографии и хочет познакомиться с участниками этого
-сообщества.
+сообщества. Конференция пройдет в Бонне, Германия, <strong> с 24 по 26 августа 2016</strong>.</td>
+</table>
 \endhtmlonly
 
 \section index_maillist_ru Список рассылки
@@ -108,7 +154,8 @@ href="mailto:gdal-dev at lists.osgeo.org">gdal-dev at lists.osgeo.org</a>.
 news://news.gmane.org/gmane.comp.gis.gdal.devel</a>
 и по HTTP
 <a href="http://news.gmane.org/gmane.comp.gis.gdal.devel">
-http://news.gmane.org/gmane.comp.gis.gdal.devel</a>.<p>
+http://news.gmane.org/gmane.comp.gis.gdal.devel</a>.
+Архив начиная с 2005 года доступен на <a href="http://osgeo-org.1560.n6.nabble.com/GDAL-Dev-f3742093.html">Nabble</a>.<p>
 
 Многих пользователей и разработчиков GDAL/OGR часто можно найти на IRC канале
 <a href="irc:irc.freenode.net/#gdal">#gdal</a> сервера irc.freenode.net.<p>
@@ -122,19 +169,8 @@ http://news.gmane.org/gmane.comp.gis.gdal.devel</a>.<p>
 
 \section index_bindings_ru Интерфейсы для различных языков программирования
 
-Вы можете использовать GDAL/OGR из следующих языков программирования:
-
-<ul>
-<li> <a href="http://map.hut.fi/gdal-perl/">Perl</a>
-<li> <a href="http://trac.osgeo.org/gdal/wiki/GdalOgrInPython">Python</a>
-<li> <a href="vb6_tutorial.html">VB6 Bindings</a> (не использует SWIG)
-<li> <a href="http://rgdal.sourceforge.net/">Интерфейс для R</a>,
-созданный Timothy H. Keitt.
-<li> <a href="http://trac.osgeo.org/gdal/wiki/GdalOgrInRuby">Ruby</a>
-<li> <a href="http://trac.osgeo.org/gdal/wiki/GdalOgrInJava">Java</a>
-<li> <a href="http://trac.osgeo.org/gdal/wiki/GdalOgrInCsharp">C# / .Net</a>
-
-</ul>
+Список интерфейсов для различных языков программирования находится в
+<a href="http://trac.osgeo.org/gdal/#GDALOGRInOtherLanguages">Вики GDAL</a>.
 
 
 */
diff --git a/doc/sponsorship.dox b/doc/sponsorship.dox
index baabe5c..0465ddc 100644
--- a/doc/sponsorship.dox
+++ b/doc/sponsorship.dox
@@ -1,5 +1,5 @@
 #ifndef DOXYGEN_SKIP
-/* $Id: sponsorship.dox 23132 2011-09-29 18:18:54Z warmerdam $ */
+/* $Id: sponsorship.dox 32092 2015-12-08 14:54:56Z goatbar $ */
 #endif /* DOXYGEN_SKIP */
 
 /*!
@@ -76,9 +76,9 @@ of the following class:
 <li> $3000+ USD: Silver Sponsor
 </ol>
 
-Sponsorships last one year, after which they may be continuing with a 
-new payment, or allowed to lapse.  OSGeo is planning to be US 501(c)3 charity 
-and  sponsorships will be eligible as a charitable contribution for US 
+Sponsorships last one year, after which they may be continuing with a
+new payment, or allowed to lapse.  OSGeo is planning to be US 501(c)3 charity
+and sponsorships will be eligible as a charitable contribution for US
 taxpayers.  Appropriate receipts can be issued when needed.
 
 Organizations or individuals interested in sponsoring the GDAL/OGR project
@@ -87,7 +87,7 @@ questions, or to make arrangements.
 
 \htmlonly
 <p>
-$Id: sponsorship.dox 23132 2011-09-29 18:18:54Z warmerdam $
+$Id: sponsorship.dox 32092 2015-12-08 14:54:56Z goatbar $
 </p>
 \endhtmlonly
 
diff --git a/doc/warptut.dox b/doc/warptut.dox
index 5feb38f..04e9e74 100644
--- a/doc/warptut.dox
+++ b/doc/warptut.dox
@@ -1,5 +1,5 @@
 #ifndef DOXYGEN_SKIP
-/* $Id: warptut.dox 21106 2010-11-09 19:19:21Z rouault $ */
+/* $Id: warptut.dox 33134 2016-01-23 23:10:03Z rouault $ */
 #endif /* DOXYGEN_SKIP */
 
 /*!
@@ -133,7 +133,7 @@ caching.
 
 <li> GDALWarpOpations::eResampleAlg - One of GRA_NearestNeighbour (the default,
 and fastest), GRA_Bilinear (2x2 bilinear resampling) or GRA_Cubic.  The
-GRA_NearestNeighbour type should generally be used for thematic or colormapped 
+GRA_NearestNeighbour type should generally be used for thematic or color mapped 
 images.  The other resampling types may give better results for thematic 
 images, especially when substantially changing resolution. 
 
@@ -152,7 +152,7 @@ include:
  destination image to be initialized to the indicated value (for all bands)
  or indicates that it should be initialized to the NO_DATA value in
  padfDstNoDataReal/padfDstNoDataImag.  If this value isn't set the
- destination image will be read and the source warp overlayed on it.
+ destination image will be read and the source warp overlaid on it.
 
 <li> WRITE_FLUSH=YES/NO: This option forces a flush to disk of data after
  each chunk is processed.  In some cases this helps ensure a serial 
@@ -282,12 +282,12 @@ To warp to compressed formats, or CreateCopy() style formats it is necessary
 to produce a full temporary copy of the image in a better behaved format, and
 then CreateCopy() it to the desired final format. 
 
-<li> The Warp API copies only pixels.  All colormaps, georeferencing and
+<li> The Warp API copies only pixels.  All color maps, georeferencing and
 other metadata must be copied to the destination by the application.  
 
 </ul>
 
-\section warptut_perfomance Performance Optimization
+\section warptut_performance Performance Optimization
 
 There are a number of things that can be done to optimize the performance
 of the warp API.
@@ -362,7 +362,7 @@ caution at this time.
 
 \htmlonly
 <p>
-$Id: warptut.dox 21106 2010-11-09 19:19:21Z rouault $
+$Id: warptut.dox 33134 2016-01-23 23:10:03Z rouault $
 </p>
 \endhtmlonly
 
diff --git a/doc/wince_port.dox b/doc/wince_port.dox
deleted file mode 100644
index fa6075c..0000000
--- a/doc/wince_port.dox
+++ /dev/null
@@ -1,340 +0,0 @@
-#ifndef DOXYGEN_SKIP
-/* $Id: wince_port.dox 18465 2010-01-07 20:39:16Z mloskot $ */
-#endif /* DOXYGEN_SKIP */
-
-/*!
-\page wince GDAL for Windows CE
-
-\ref wince_overview<br/>
-\ref wince_features<br/>
-\ref wince_platforms<br/>
-\ref wince_directory<br/>
-\ref wince_building<br/>
-\ref wince_building_proj4<br/>
-\ref wince_building_geos<br/>
-\ref wince_help<br/>
-
-\warning *** Currently, GDAL port for Windows CE platform is not actively maintained. If you are interested in providing patches or taking over this project, please write to <a href="http://lists.osgeo.org/mailman/listinfo/gdal-dev/">gdal-dev at lists.maptools.org</a> mailing list. ***
-
-\section wince_overview Overview
-
-This document is devoted to give some overview of the GDAL port for <a href="http://en.wikipedia.org/wiki/Windows_CE">Windows CE</a> operating system.
-
-\section wince_features Features
-
-Currently, from version <a href="http://www.gdal.org/dl/gdal140.zip">1.4.0</a>, GDAL includes following features for Windows CE platform:
-
-<ul>
-<li>CPL library</li>
-<li>GDAL and OGR core API</li>
-<li>GDAL drivers:
-    <ul>
-        <li><a href="http://www.gdal.org/frmt_various.html#AAIGrid">AAIGrid</a></li>
-        <li><a href="http://www.gdal.org/frmt_dted.html">DTED</a></li>
-        <li><a href="http://www.gdal.org/frmt_gtiff.html">GeoTIFF</a></li>
-    </ul>
-</li>
-<li>OGR drivers:
-    <ul>
-        <li>Generic</li>
-        <li><a href="http://www.gdal.org/ogr/drv_csv.html">CSV</a></li>
-        <li><a href="http://www.gdal.org/ogr/drv_mitab.html">MITAB</a></li>
-        <li><a href="http://www.gdal.org/ogr/drv_shapefile.html">ESRI Shapefile</a></li>
-    </ul>
-</li>
-<li>Unit Test suite (gdalautotest/cpp)</li>
-<li>Optional <a href="http://proj.maptools.org/">PROJ.4</a> support</li>
-<li>Optional <a href="http://geos.refractions.net/">GEOS</a> support</li>
-</ul>
-
-\section wince_platforms Supported Platforms
-
-GDAL for Windows CE has been tested on following versions of Windows CE:
-
-<ul>
-<li>Windows CE 3.x
-    <ul><li>Pocket PC 2002</li></ul>
-</li>
-<li>Windows CE 4.x
-    <ul><li>Windows Mobile 2003</li></ul>
-</li>
-<li>Windows CE 5.x
-    <ul>
-        <li>Windows Mobile 5
-        <li>customized versions of Windows CE 5.0
-    </ul>
-</li>
-</ul>
-
-Supported compilers for Windows CE operating system:
-
-<ul>
-<li>Microsoft Visual C++ 2005 Standard, Professional or Team Suite Edition</li>
-<li>Microsoft eMbedded Visual C++ 4.0
-
-    \note Currently, no project files provided for eVC++ 4.0 IDE
-
-</li>
-</ul>
-
-
-\section wince_directory Content of 'wince' directory
-
-\note Due to problems with removing directories from CVS and missed synchronization of RC branch,
-      the 'wince' directory includes a few deprecated project files (see below).<br />
-      Please <strong>DON'T USE</strong> them, unless you want to fix them yourself.
-
-Active content:
-
-<ul>
-<li><strong>msvc80</strong> - project for Visual C++ 2005 to build GDAL DLL for Windows CE</li>
-<li>README - the file you're currently reading</li>
-<li>TODO   - planned and requested features</li>
-</ul>
-
-
-\deprecated Following directories and projects are deprecated. <strong>DON'T USE THEM!</strong>
-
-<ul>
-<li>evc4_gdalce_dll</li>
-<li>evc4_gdalce_dll_test</li>
-<li>evc4_gdalce_lib</li>
-<li>evc4_gdalce_lib_test</li>
-<li>msvc8_gdalce_lib</li>
-<li>msvc8_gdalce_lib_test</li>
-<li>wce_test_dll</li>
-<li>wce_test_lib</li>
-<li>wcelibcex</li>
-</ul>
-
-
-\section wince_building Building GDAL for Windows CE using Microsoft Visual C++ 2005
-
-<ol>
-
-<li>Requirements
-
-<ul>
-<li>You need to have installed Visual C++ 2005 Standard, Professional or
-Team Suite Edition.</li>
-<li>You also need to have installed at least one SDK for Windows CE platform:
-    <ul>
-    <li>Windows Mobile 2003 Pocket PC SDK</li>
-    <li>Windows Mobile 2003 SmartphoneSDK</li>
-    <li>Windows Mobile 5.0 Pocket PC SDK</li>
-    <li>Windows Mobile 5.0 Smartphone SDK</li>
-    </ul>
-</li>
-<li>Last requirement is the <a href="http://support.microsoft.com/default.aspx?scid=kb;[LN];830482">Run-time Type Information library for the Pocket PC 2003 SDK</a>.</li>
-</ul>
-
-</li>
-
-<li>External dependencies
-
-There is only one external dependency required to build GDAL for Windows CE.
-This dependency is <a href="http://wcelibcex.sourceforge.net">WCELIBCEX</a> library available to download from:
-
-http://sourceforge.net/projects/wcelibcex
-
-You can download latest release - <a href="http://sourceforge.net/project/showfiles.php?group_id=160411&package_id=180452&release_id=476819">wcelibcex-1.0</a> - or checkout sources directly form SVN. In both cases, you will be provided with project file for Visual C++ 2005.
-
-\note WCELIBCEX is built to Static Library. For details, check README.txt file form the package.
-
-</li>
-
-<li>Download GDAL 1.4.0 release or directly from CVS 
-
-Go to http://www.gdal.org/download.html and download ZIP package with GDAL 1.4.0.
-You can also checkout sources directly from SVN.
-
-For this guidelines, I assume following directories structure:
-
-\verbatim
-C:\dev\gdal-1.4.0
-C:\dev\wcelibcex-1.0
-\endverbatim
-
-</li>
-
-<li>Projects configuration
-
-    <ol>
-    <li>Open gdalce_dll.sln project in Visual C++ 2005 IDE
-
-        According to the paths presented in step 3, you should load following file:
-
-        \verbatim C:\dev\gdal-1.4.0\wince\msvc80\gdalce_dll\gdalce_dll.sln \endverbatim
-
-    </li>
-
-    <li>Add WCELIBCEX project to gdalce_dll.sln solution
-
-        Go to File -> Add -> Existing Project, navigage and open following file:
-
-        \verbatim C:\dev\wcelibcex-1.0\msvc80\wcelibcex_lib.vcproj \endverbatim
-
-    </li>
-
-    <a name="gdalce_wcelibcex_configure"></a>
-    <li>Configure path to WCELIBCEX source:
-        <ul>
-        <li>Go to View -> Property Manager to open property manager window</li>
-        <li>Expand tree below gdalce_dll -> Debug -> gdalce_common</li>
-        <li>Right-click on gdalce_common and select Properties</li>
-        <li>In Property Pages dialog, under Common Properties, go to User Macros</li>
-        <li>In macros list, double-click on macro named as WCELIBCEX_DIR</li>
-        <li>According paths assumed in step 3, change the macro value to: \verbatim C:\dev\wcelibcex-1.0\src \endverbatim </li>
-        <li>Click OK to apply changes and close the dialog</li>
-        </ul>
-    </li>
-
-    <a name="gdalce_wcelibcex_dependency"></a>
-    <li>Configure <em>wcelibcex_lib.vcproj</em> as a dependency for <em>gdalce_dll.vcproj</em>
-        <ul>
-        <li>Select gdalce_dll project in Solution Explorer</li>
-        <li>Go to Project -> Project Dependencies</li>
-        <li>In the 'Depends on:' pane, select checkbox next to wcelibcex_lib</li>
-        <li>Click OK to apply and close</li>
-        </ul>
-    </li>
-    </ol>
-</li>
-
-
-<li>Ready to build GDAL for Windows CE
-
-Go to Build and select Build Solution
-
-After a few minutes, you should see GDAL DLL ready to use.
-For example, when Pocket PC 2003 SDK is used and Debug configuration requested,
-all output files are located under this path:
-
-\verbatim
-C:\dev\gdal-1.4.0\wince\msvc80\gdalce_dll\Pocket PC 2003 (ARMV4)\Debug
-\endverbatim
-
-There, you will find following binaries:
-
-<ul>
-<li><strong>gdalce.dll</strong> - dymamic-link library</li>
-<li><strong>gdalce_i.lib</strong> - import library</li>
-</ul>
-
-</li>
-
-</ol>
-
-
-\subsection wince_building_proj4 Enable PROJ.4 support
-
-PROJ.4 support is optional.
-
-In the CVS repository of PROJ.4, there are available project files for Visual C++ 2005 for Windows CE.
-
-It is recommended to read <em>README.txt</em> file from <em>wince\\msvc80</em> directory in PROJ.4 sources tree.
-There, you will find instructions how to build PROJ.4 without attaching its project to gdalce_dll.sln.
-Then you can just add proj.dll and proj_i.lib to linker settings of gdalce_dll.vcproj project.
-
-Below, you can find instructions how to add projce_dll.vcproj project
-directly to gdalce_dll.sln and build everything together.
-
-<ol>
-
-<li>Go to http://proj.maptools.org and learn how to checkout PROJ.4 source from the CVS</li>
-
-<li>Checkout sources to prefered location, for example:
-
-    \verbatim C:\dev\proj \endverbatim
-
-</li>
-
-<li>Add projce_dll.vcproj project to gdalce_dll.sln solution
-
-    Go to File -> Add -> Existing Project, navigage and open following file:
-
-    \verbatim C:\dev\proj\wince\msvc80\projce_dll\projce_dll.vcproj \endverbatim
-
-</li>
-
-<li>Open Property Manager as described <a href="#gdalce_wcelibcex_configure">here</a>, open Property Page for gdalce_common,
-   and edit macro named as PROJ_DIR.
-   
-   Change value of the PROJ_DIR macro to: 
-   \verbatim C:\dev\proj \endverbatim
-
-   Don't close the Property Manager yet.
-
-</li>
-
-<li>Configure path to WCELIBCEX source:
-    <ul>
-    <li>Go to View -> Property Manager to open property manager window</li>
-    <li>Expand tree below projce_dll -> Debug -> projce_common</li>
-    <li>Right-click on projce_common and select Properties</li>
-    <li>In Property Pages dialog, under Common Properties, go to User Macros</li>
-    <li>In macros list, double-click on macro named as WCELIBCEX_DIR</li>
-    <li>According paths assumed in step 3, change the macro value to: \verbatim C:\dev\wcelibcex-1.0\src \endverbatim </li>
-    <li>Click OK to apply changes and close the dialog</li>
-    </ul>
-</li>
-
-<li>Follow instructions explained <a href="#gdalce_wcelibcex_dependency">here</a> and add projce_dll.vcproj as a dependency for gdalce_dll.vcproj</li>
-
-<li>Update proj_config.h file:
-
-    Go to <em>C:\\dev\\proj\\src</em> and rename <em>proj_config.h.wince</em> to <em>proj_config.h</em>.
-
-</li>
-
-<li>Ready to build GDAL for Windows CE
-
-   Go to Build and select Build Solution
-
-   Similarly to explanation above in step 5 for GDAL, binaries for PROJ.4 for Windows CE
-   can be found here:
-
-   \verbatim
-   C:\dev\proj\wince\msvc80\projce_dll\Pocket PC 2003 (ARMV4)\Debug
-   \endverbatim
-
-   There, you can find following binaries:
-
-   <ul>
-   <li><strong>proj.dll</strong> - dymamic-link library</li>
-   <li><strong>proj_i.lib</strong> - import library</li>
-   </ul>
-
-   \note PROJ.4 binaries for Windows CE do not include 'ce' in names.
-         This is due the fact GDAL uses fixed proj.dll name to find and link dynamically with PROJ.4 DLL.
-
-</li>
-
-<li>After all, put proj.dll to the same directory on device where you copied gdalce.dll and your application which uses GDAL.</li>
-
-</ol>
-
-
-\section wince_help How can I help?
-
-I'd like to encourage everyone interested in using GDAL on Windows CE devices to help in its development.
-Here is a list of what you can do as a contribution to the project:
-<ul>
-    <li>You can build GDAL for Windows CE and report problems if you will meet any</li>
-    <li>You can try to build new OGR drivers</li>
-    <li>You can test GDAL/OGR on different Windows CE devices</li>
-    <li>You can write sample applications using GDAL/OGR and announce them on the <a href="http://lists.maptools.org/mailman/listinfo/gdal-dev/">GDAL mailing list</a></li>
-    <li>If you have found a bug or something is not working on the Windows CE, please report it on the <a href="http://bugzilla.remotesensing.org">GDAL's Bugzilla</a>
-</ul>
-
-<p>There is also <em>wince\\TODO</em> file where you can find list of things we are going to do.</p>
-
-<p>If you have any comments or questions, please sent them to <a href="http://lists.osgeo.org/mailman/listinfo/gdal-dev/">gdal-dev at lists.maptools.org</a> mailing list.</p>
-
-\htmlonly
-<p>
-$Id: wince_port.dox 18465 2010-01-07 20:39:16Z mloskot $
-</p>
-\endhtmlonly
-
-*/
diff --git a/doxygen_sqlite3.db b/doxygen_sqlite3.db
index d1c8b4e..e02a5c1 100644
Binary files a/doxygen_sqlite3.db and b/doxygen_sqlite3.db differ
diff --git a/frmts/GNUmakefile b/frmts/GNUmakefile
index a343a4a..3b6b536 100644
--- a/frmts/GNUmakefile
+++ b/frmts/GNUmakefile
@@ -6,6 +6,11 @@ OBJ	=	o/gdalallregister.o
 
 FRMT_FLAGS	=	$(foreach FRMT, $(GDAL_FORMATS), -DFRMT_$(FRMT))
 
+ifeq ($(GNM_ENABLED),yes)
+   GDAL_INCLUDE += -I$(GDAL_ROOT)/gnm -I$(GDAL_ROOT)/gnm/gnm_frmts
+   CXXFLAGS += -DGNM_ENABLED
+endif
+
 %-install-obj:
 	$(MAKE) -C $* install-obj
 
@@ -16,7 +21,7 @@ clean:	$(foreach d,$(GDAL_FORMATS),$(d)-clean)
 	$(RM) o/*.lo
 
 o/gdalallregister.$(OBJ_EXT):	gdalallregister.cpp ../GDALmake.opt
-	$(CXX) -c $(GDAL_INCLUDE) $(CXXFLAGS) $(FRMT_FLAGS) \
+	$(CXX) -c $(GDAL_INCLUDE) $(CPPFLAGS) $(CXXFLAGS) $(FRMT_FLAGS) \
 		-DGDAL_FORMATS="$(GDAL_FORMATS)" \
 		gdalallregister.cpp -o o/gdalallregister.$(OBJ_EXT)
 
diff --git a/frmts/aaigrid/aaigriddataset.cpp b/frmts/aaigrid/aaigriddataset.cpp
index bfe5cfc..7bb8414 100644
--- a/frmts/aaigrid/aaigriddataset.cpp
+++ b/frmts/aaigrid/aaigriddataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: aaigriddataset.cpp 29614 2015-08-06 09:37:29Z rouault $
+ * $Id: aaigriddataset.cpp 33809 2016-03-29 21:41:38Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Implements Arc/Info ASCII Grid Format.
@@ -29,21 +29,22 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
+// We need cpl_port as first include to avoid VSIStatBufL being not
+// defined on i586-mingw32msvc.
+#include "cpl_port.h"
+
 #include <ctype.h>
-#include <limits.h>
+#include <climits>
+
 #include "cpl_string.h"
+#include "gdal_pam.h"
+#include "gdal_frmts.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: aaigriddataset.cpp 29614 2015-08-06 09:37:29Z rouault $");
-
-CPL_C_START
-void    GDALRegister_AAIGrid(void);
-void    GDALRegister_GRASSASCIIGrid(void);
-CPL_C_END
+CPL_CVSID("$Id: aaigriddataset.cpp 33809 2016-03-29 21:41:38Z goatbar $");
 
-static CPLString OSR_GDS( char **papszNV, const char * pszField, 
-                           const char *pszDefaultValue );
+static CPLString OSR_GDS( char **papszNV, const char * pszField,
+                          const char *pszDefaultValue );
 
 typedef enum
 {
@@ -62,14 +63,13 @@ class AAIGRasterBand;
 class CPL_DLL AAIGDataset : public GDALPamDataset
 {
     friend class AAIGRasterBand;
-    
+
     VSILFILE   *fp;
 
     char        **papszPrj;
     CPLString   osPrjFilename;
     char        *pszProjection;
 
-
     unsigned char achReadBuf[256];
     GUIntBig    nBufferOffset;
     int         nOffsetInBuffer;
@@ -83,13 +83,13 @@ class CPL_DLL AAIGDataset : public GDALPamDataset
     double      adfGeoTransform[6];
     int         bNoDataSet;
     double      dfNoDataValue;
-    
+
 
     virtual int ParseHeader(const char* pszHeader, const char* pszDataType);
 
   public:
                 AAIGDataset();
-                ~AAIGDataset();
+       virtual ~AAIGDataset();
 
     virtual char **GetFileList(void);
 
@@ -100,9 +100,11 @@ class CPL_DLL AAIGDataset : public GDALPamDataset
     static int          Identify( GDALOpenInfo * );
     static CPLErr       Delete( const char *pszFilename );
     static CPLErr       Remove( const char *pszFilename, int bRepError );
-    static GDALDataset *CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
-                                int bStrict, char ** papszOptions,
-                                GDALProgressFunc pfnProgress, void * pProgressData );
+    static GDALDataset *CreateCopy( const char * pszFilename,
+                                    GDALDataset *poSrcDS,
+                                    int bStrict, char ** papszOptions,
+                                    GDALProgressFunc pfnProgress,
+                                    void * pProgressData );
 
     virtual CPLErr GetGeoTransform( double * );
     virtual const char *GetProjectionRef(void);
@@ -120,6 +122,7 @@ class GRASSASCIIDataset : public AAIGDataset
 
   public:
                 GRASSASCIIDataset() : AAIGDataset() {}
+       virtual ~GRASSASCIIDataset() {}
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int          Identify( GDALOpenInfo * );
@@ -151,24 +154,22 @@ class AAIGRasterBand : public GDALPamRasterBand
 /*                           AAIGRasterBand()                            */
 /************************************************************************/
 
-AAIGRasterBand::AAIGRasterBand( AAIGDataset *poDS, int nDataStart )
-
+AAIGRasterBand::AAIGRasterBand( AAIGDataset *poDSIn, int nDataStart ) :
+    panLineOffset(NULL)
 {
-    this->poDS = poDS;
+    poDS = poDSIn;
 
     nBand = 1;
-    eDataType = poDS->eDataType;
+    eDataType = poDSIn->eDataType;
 
-    nBlockXSize = poDS->nRasterXSize;
+    nBlockXSize = poDSIn->nRasterXSize;
     nBlockYSize = 1;
 
-    panLineOffset = 
-        (GUIntBig *) VSICalloc( poDS->nRasterYSize, sizeof(GUIntBig) );
+    panLineOffset =
+        static_cast<GUIntBig *>(
+            VSI_CALLOC_VERBOSE( poDSIn->nRasterYSize, sizeof(GUIntBig) ) );
     if (panLineOffset == NULL)
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory,
-                 "AAIGRasterBand::AAIGRasterBand : Out of memory (nRasterYSize = %d)",
-                 poDS->nRasterYSize);
         return;
     }
     panLineOffset[0] = nDataStart;
@@ -192,8 +193,7 @@ CPLErr AAIGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                   void * pImage )
 
 {
-    AAIGDataset *poODS = (AAIGDataset *) poDS;
-    int         iPixel;
+    AAIGDataset *poODS = reinterpret_cast<AAIGDataset *>( poDS );
 
     if( nBlockYOff < 0 || nBlockYOff > poODS->nRasterYSize - 1
         || nBlockXOff != 0 || panLineOffset == NULL || poODS->fp == NULL )
@@ -201,9 +201,7 @@ CPLErr AAIGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
     if( panLineOffset[nBlockYOff] == 0 )
     {
-        int iPrevLine;
-
-        for( iPrevLine = 1; iPrevLine <= nBlockYOff; iPrevLine++ )
+        for( int iPrevLine = 1; iPrevLine <= nBlockYOff; iPrevLine++ )
             if( panLineOffset[iPrevLine] == 0 )
                 IReadBlock( nBlockXOff, iPrevLine-1, NULL );
     }
@@ -211,32 +209,31 @@ CPLErr AAIGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     if( panLineOffset[nBlockYOff] == 0 )
         return CE_Failure;
 
-    
+
     if( poODS->Seek( panLineOffset[nBlockYOff] ) != 0 )
     {
         CPLError( CE_Failure, CPLE_FileIO,
                   "Can't seek to offset %lu in input file to read data.",
-                  (long unsigned int)panLineOffset[nBlockYOff] );
+                  static_cast<long unsigned int>(panLineOffset[nBlockYOff] ) );
         return CE_Failure;
     }
 
-    for( iPixel = 0; iPixel < poODS->nRasterXSize; )
+    for( int iPixel = 0; iPixel < poODS->nRasterXSize; )
     {
-        char szToken[500];
+        // Suck up any pre-white space.
         char chNext;
-        int  iTokenChar = 0;
-
-        /* suck up any pre-white space. */
         do {
             chNext = poODS->Getc();
-        } while( isspace( (unsigned char)chNext ) );
+        } while( isspace( static_cast<unsigned char>(chNext) ) );
 
+        char szToken[500] = { '\0' };
+        int  iTokenChar = 0;
         while( chNext != '\0' && !isspace((unsigned char)chNext)  )
         {
             if( iTokenChar == sizeof(szToken)-2 )
             {
-                CPLError( CE_Failure, CPLE_FileIO, 
-                          "Token too long at scanline %d.", 
+                CPLError( CE_Failure, CPLE_FileIO,
+                          "Token too long at scanline %d.",
                           nBlockYOff );
                 return CE_Failure;
             }
@@ -249,7 +246,7 @@ CPLErr AAIGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             (iPixel != poODS->nRasterXSize - 1 ||
             nBlockYOff != poODS->nRasterYSize - 1) )
         {
-            CPLError( CE_Failure, CPLE_FileIO, 
+            CPLError( CE_Failure, CPLE_FileIO,
                       "File short, can't read line %d.",
                       nBlockYOff );
             return CE_Failure;
@@ -260,16 +257,18 @@ CPLErr AAIGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         if( pImage != NULL )
         {
             if( eDataType == GDT_Float64 )
-                ((double *) pImage)[iPixel] = CPLAtofM(szToken);
+                reinterpret_cast<double *>(pImage)[iPixel] = CPLAtofM(szToken);
             else if( eDataType == GDT_Float32 )
-                ((float *) pImage)[iPixel] = (float) CPLAtofM(szToken);
+                reinterpret_cast<float *>(pImage)[iPixel] =
+                    static_cast<float>( CPLAtofM(szToken) );
             else
-                ((GInt32 *) pImage)[iPixel] = (GInt32) atoi(szToken);
+                reinterpret_cast<GInt32 *>(pImage)[iPixel] =
+                    static_cast<GInt32>( atoi(szToken) );
         }
-        
+
         iPixel++;
     }
-    
+
     if( nBlockYOff < poODS->nRasterYSize - 1 )
         panLineOffset[nBlockYOff + 1] = poODS->Tell();
 
@@ -283,7 +282,7 @@ CPLErr AAIGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 double AAIGRasterBand::GetNoDataValue( int * pbSuccess )
 
 {
-    AAIGDataset *poODS = (AAIGDataset *) poDS;
+    AAIGDataset *poODS = reinterpret_cast<AAIGDataset *>( poDS );
 
     if( pbSuccess )
         *pbSuccess = poODS->bNoDataSet;
@@ -299,7 +298,7 @@ double AAIGRasterBand::GetNoDataValue( int * pbSuccess )
 CPLErr AAIGRasterBand::SetNoDataValue( double dfNoData )
 
 {
-    AAIGDataset *poODS = (AAIGDataset *) poDS;
+    AAIGDataset *poODS = reinterpret_cast<AAIGDataset *>( poDS );
 
     poODS->bNoDataSet = TRUE;
     poODS->dfNoDataValue = dfNoData;
@@ -313,30 +312,26 @@ CPLErr AAIGRasterBand::SetNoDataValue( double dfNoData )
 /* ==================================================================== */
 /************************************************************************/
 
-
 /************************************************************************/
 /*                            AAIGDataset()                            */
 /************************************************************************/
 
-AAIGDataset::AAIGDataset()
-
+AAIGDataset::AAIGDataset() :
+    fp(NULL),
+    papszPrj(NULL),
+    pszProjection(CPLStrdup("")),
+    nBufferOffset(0),
+    nOffsetInBuffer(256),
+    eDataType(GDT_Int32),
+    bNoDataSet(FALSE),
+    dfNoDataValue(-9999.0)
 {
-    papszPrj = NULL;
-    pszProjection = CPLStrdup("");
-    fp = NULL;
-    eDataType = GDT_Int32;
-    bNoDataSet = FALSE;
-    dfNoDataValue = -9999.0;
-
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
-
-    nOffsetInBuffer = 256;
-    nBufferOffset = 0;
 }
 
 /************************************************************************/
@@ -349,7 +344,12 @@ AAIGDataset::~AAIGDataset()
     FlushCache();
 
     if( fp != NULL )
-        VSIFCloseL( fp );
+    {
+        if( VSIFCloseL( fp ) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        }
+    }
 
     CPLFree( pszProjection );
     CSLDestroy( papszPrj );
@@ -390,9 +390,9 @@ char AAIGDataset::Getc()
         return achReadBuf[nOffsetInBuffer++];
 
     nBufferOffset = VSIFTellL( fp );
-    int nRead = VSIFReadL( achReadBuf, 1, sizeof(achReadBuf), fp );
-    unsigned int i;
-    for(i=nRead;i<sizeof(achReadBuf);i++)
+    const int nRead =
+        static_cast<int>(VSIFReadL( achReadBuf, 1, sizeof(achReadBuf), fp ));
+    for( unsigned int i=nRead; i < sizeof(achReadBuf); i++ )
         achReadBuf[i] = '\0';
 
     nOffsetInBuffer = 0;
@@ -426,15 +426,15 @@ int AAIGDataset::Identify( GDALOpenInfo * poOpenInfo )
 /*      Does this look like an AI grid file?                            */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->nHeaderBytes < 40
-        || !( EQUALN((const char *) poOpenInfo->pabyHeader,"ncols",5) ||
-              EQUALN((const char *) poOpenInfo->pabyHeader,"nrows",5) ||
-              EQUALN((const char *) poOpenInfo->pabyHeader,"xllcorner",9)||
-              EQUALN((const char *) poOpenInfo->pabyHeader,"yllcorner",9)||
-              EQUALN((const char *) poOpenInfo->pabyHeader,"xllcenter",9)||
-              EQUALN((const char *) poOpenInfo->pabyHeader,"yllcenter",9)||
-              EQUALN((const char *) poOpenInfo->pabyHeader,"dx",2)||
-              EQUALN((const char *) poOpenInfo->pabyHeader,"dy",2)||
-              EQUALN((const char *) poOpenInfo->pabyHeader,"cellsize",8)) )
+        || !( STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "ncols") ||
+              STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "nrows") ||
+              STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "xllcorner")||
+              STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "yllcorner")||
+              STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "xllcenter")||
+              STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "yllcenter")||
+              STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "dx")||
+              STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "dy")||
+              STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "cellsize")) )
         return FALSE;
 
     return TRUE;
@@ -451,12 +451,12 @@ int GRASSASCIIDataset::Identify( GDALOpenInfo * poOpenInfo )
 /*      Does this look like a GRASS ASCII grid file?                    */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->nHeaderBytes < 40
-        || !( EQUALN((const char *) poOpenInfo->pabyHeader,"north:",6) ||
-              EQUALN((const char *) poOpenInfo->pabyHeader,"south:",6) ||
-              EQUALN((const char *) poOpenInfo->pabyHeader,"east:",5)||
-              EQUALN((const char *) poOpenInfo->pabyHeader,"west:",5)||
-              EQUALN((const char *) poOpenInfo->pabyHeader,"rows:",5)||
-              EQUALN((const char *) poOpenInfo->pabyHeader,"cols:",5) ) )
+        || !( STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "north:") ||
+              STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "south:") ||
+              STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "east:")||
+              STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "west:")||
+              STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "rows:")||
+              STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "cols:") ) )
         return FALSE;
 
     return TRUE;
@@ -480,13 +480,11 @@ GDALDataset *AAIGDataset::Open( GDALOpenInfo * poOpenInfo )
 
 int AAIGDataset::ParseHeader(const char* pszHeader, const char* pszDataType)
 {
-    int i, j;
     char** papszTokens =
         CSLTokenizeString2( pszHeader,  " \n\r\t" , 0 );
-    int nTokens = CSLCount(papszTokens);
-    double dfCellDX = 0;
-    double dfCellDY = 0;
+    const int nTokens = CSLCount(papszTokens);
 
+    int i = 0;
     if ( (i = CSLFindString( papszTokens, "ncols" )) < 0 ||
          i + 1 >= nTokens)
     {
@@ -508,6 +506,8 @@ int AAIGDataset::ParseHeader(const char* pszHeader, const char* pszDataType)
         return FALSE;
     }
 
+    double dfCellDX = 0.0;
+    double dfCellDY = 0.0;
     if ( (i = CSLFindString( papszTokens, "cellsize" )) < 0 )
     {
         int iDX, iDY;
@@ -533,14 +533,16 @@ int AAIGDataset::ParseHeader(const char* pszHeader, const char* pszDataType)
         dfCellDX = dfCellDY = CPLAtofM( papszTokens[i + 1] );
     }
 
+    int j = 0;
     if ((i = CSLFindString( papszTokens, "xllcorner" )) >= 0 &&
         (j = CSLFindString( papszTokens, "yllcorner" )) >= 0 &&
         i + 1 < nTokens && j + 1 < nTokens)
     {
         adfGeoTransform[0] = CPLAtofM( papszTokens[i + 1] );
-       
-        /* Small hack to compensate from insufficient precision in cellsize */
-        /* parameter in datasets of http://ccafs-climate.org/data/A2a_2020s/hccpr_hadcm3 */
+
+        // Small hack to compensate from insufficient precision in cellsize
+        // parameter in datasets of
+        // http://ccafs-climate.org/data/A2a_2020s/hccpr_hadcm3
         if ((nRasterXSize % 360) == 0 &&
             fabs(adfGeoTransform[0] - (-180.0)) < 1e-12 &&
             dfCellDX == dfCellDY &&
@@ -548,7 +550,7 @@ int AAIGDataset::ParseHeader(const char* pszHeader, const char* pszDataType)
         {
             dfCellDX = dfCellDY = 360.0 / nRasterXSize;
         }
-            
+
         adfGeoTransform[1] = dfCellDX;
         adfGeoTransform[2] = 0.0;
         adfGeoTransform[3] = CPLAtofM( papszTokens[j + 1] )
@@ -625,10 +627,10 @@ GDALDataset *GRASSASCIIDataset::Open( GDALOpenInfo * poOpenInfo )
 
 int GRASSASCIIDataset::ParseHeader(const char* pszHeader, const char* pszDataType)
 {
-    int i;
     char** papszTokens =
         CSLTokenizeString2( pszHeader,  " \n\r\t:" , 0 );
-    int nTokens = CSLCount(papszTokens);
+    const int nTokens = CSLCount(papszTokens);
+    int i = 0;
     if ( (i = CSLFindString( papszTokens, "cols" )) < 0 ||
          i + 1 >= nTokens)
     {
@@ -650,10 +652,10 @@ int GRASSASCIIDataset::ParseHeader(const char* pszHeader, const char* pszDataTyp
         return FALSE;
     }
 
-    int iNorth = CSLFindString( papszTokens, "north" );
-    int iSouth = CSLFindString( papszTokens, "south" );
-    int iEast = CSLFindString( papszTokens, "east" );
-    int iWest = CSLFindString( papszTokens, "west" );
+    const int iNorth = CSLFindString( papszTokens, "north" );
+    const int iSouth = CSLFindString( papszTokens, "south" );
+    const int iEast = CSLFindString( papszTokens, "east" );
+    const int iWest = CSLFindString( papszTokens, "west" );
 
     if (iNorth == -1 || iSouth == -1 || iEast == -1 || iWest == -1 ||
         MAX(MAX(iNorth, iSouth), MAX(iEast, iWest)) + 1 >= nTokens)
@@ -662,12 +664,12 @@ int GRASSASCIIDataset::ParseHeader(const char* pszHeader, const char* pszDataTyp
         return FALSE;
     }
 
-    double dfNorth = CPLAtofM( papszTokens[iNorth + 1] );
-    double dfSouth = CPLAtofM( papszTokens[iSouth + 1] );
-    double dfEast = CPLAtofM( papszTokens[iEast + 1] );
-    double dfWest = CPLAtofM( papszTokens[iWest + 1] );
-    double dfPixelXSize = (dfEast - dfWest) / nRasterXSize;
-    double dfPixelYSize = (dfNorth - dfSouth) / nRasterYSize;
+    const double dfNorth = CPLAtofM( papszTokens[iNorth + 1] );
+    const double dfSouth = CPLAtofM( papszTokens[iSouth + 1] );
+    const double dfEast = CPLAtofM( papszTokens[iEast + 1] );
+    const double dfWest = CPLAtofM( papszTokens[iWest + 1] );
+    const double dfPixelXSize = (dfEast - dfWest) / nRasterXSize;
+    const double dfPixelYSize = (dfNorth - dfSouth) / nRasterYSize;
 
     adfGeoTransform[0] = dfWest;
     adfGeoTransform[1] = dfPixelXSize;
@@ -692,7 +694,9 @@ int GRASSASCIIDataset::ParseHeader(const char* pszHeader, const char* pszDataTyp
         }
         if( eDataType == GDT_Float32 )
         {
-            dfNoDataValue = (double) (float) dfNoDataValue;
+            // TODO(schwehr): Is this really what we want?
+            dfNoDataValue =
+                static_cast<double>( static_cast<float>( dfNoDataValue ) );
         }
     }
 
@@ -708,8 +712,8 @@ int GRASSASCIIDataset::ParseHeader(const char* pszHeader, const char* pszDataTyp
             eDataType = GDT_Float64;
         else
         {
-            CPLError(CE_Warning, CPLE_AppDefined,
-                     "Invalid value for type parameter : %s", pszType);
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Invalid value for type parameter : %s", pszType);
         }
     }
 
@@ -725,37 +729,38 @@ int GRASSASCIIDataset::ParseHeader(const char* pszHeader, const char* pszDataTyp
 GDALDataset *AAIGDataset::CommonOpen( GDALOpenInfo * poOpenInfo,
                                             GridFormat eFormat )
 {
-    int i = 0;
-
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    AAIGDataset         *poDS;
+    AAIGDataset *poDS = NULL;
 
     if (eFormat == FORMAT_AAIG)
         poDS = new AAIGDataset();
     else
         poDS = new GRASSASCIIDataset();
 
+    const char* pszDataTypeOption =
+        (eFormat == FORMAT_AAIG) ?
+        "AAIGRID_DATATYPE" : "GRASSASCIIGRID_DATATYPE";
 
-    const char* pszDataTypeOption = (eFormat == FORMAT_AAIG) ? "AAIGRID_DATATYPE":
-                                                               "GRASSASCIIGRID_DATATYPE";
     const char* pszDataType = CPLGetConfigOption(pszDataTypeOption, NULL);
     if( pszDataType == NULL )
-        pszDataType = CSLFetchNameValue( poOpenInfo->papszOpenOptions, "DATATYPE" );
+        pszDataType =
+            CSLFetchNameValue( poOpenInfo->papszOpenOptions, "DATATYPE" );
     if (pszDataType != NULL)
     {
         poDS->eDataType = GDALGetDataTypeByName(pszDataType);
         if (!(poDS->eDataType == GDT_Int32 || poDS->eDataType == GDT_Float32 ||
               poDS->eDataType == GDT_Float64))
         {
-            CPLError(CE_Warning, CPLE_NotSupported,
-                     "Unsupported value for %s : %s", pszDataTypeOption, pszDataType);
+            CPLError( CE_Warning, CPLE_NotSupported,
+                      "Unsupported value for %s : %s",
+                      pszDataTypeOption, pszDataType );
             poDS->eDataType = GDT_Int32;
             pszDataType = NULL;
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Parse the header.                                               */
 /* -------------------------------------------------------------------- */
@@ -772,47 +777,47 @@ GDALDataset *AAIGDataset::CommonOpen( GDALOpenInfo * poOpenInfo,
     poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "r" );
     if( poDS->fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "VSIFOpenL(%s) failed unexpectedly.", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "VSIFOpenL(%s) failed unexpectedly.",
                   poOpenInfo->pszFilename );
         delete poDS;
         return NULL;
-    } 
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Find the start of real data.                                    */
 /* -------------------------------------------------------------------- */
-    int         nStartOfData;
+    int nStartOfData = 0;
 
-    for( i = 2; TRUE ; i++ )
+    for( int i = 2; true ; i++ )
     {
         if( poOpenInfo->pabyHeader[i] == '\0' )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Couldn't find data values in ASCII Grid file.\n" );
             delete poDS;
             return NULL;
         }
-        
-        if( poOpenInfo->pabyHeader[i-1] == '\n' 
-            || poOpenInfo->pabyHeader[i-2] == '\n' 
-            || poOpenInfo->pabyHeader[i-1] == '\r' 
+
+        if( poOpenInfo->pabyHeader[i-1] == '\n'
+            || poOpenInfo->pabyHeader[i-2] == '\n'
+            || poOpenInfo->pabyHeader[i-1] == '\r'
             || poOpenInfo->pabyHeader[i-2] == '\r' )
         {
-            if( !isalpha(poOpenInfo->pabyHeader[i]) 
-                && poOpenInfo->pabyHeader[i] != '\n' 
+            if( !isalpha(poOpenInfo->pabyHeader[i])
+                && poOpenInfo->pabyHeader[i] != '\n'
                 && poOpenInfo->pabyHeader[i] != '\r')
             {
                 nStartOfData = i;
 
-				/* Beginning of real data found. */
+                // Beginning of real data found.
                 break;
             }
         }
     }
 
 /* -------------------------------------------------------------------- */
-/*      Recognize the type of data.										*/
+/*      Recognize the type of data.                                     */
 /* -------------------------------------------------------------------- */
     CPLAssert( NULL != poDS->fp );
 
@@ -820,24 +825,28 @@ GDALDataset *AAIGDataset::CommonOpen( GDALOpenInfo * poOpenInfo,
     {
         /* Allocate 100K chunk + 1 extra byte for NULL character. */
         const size_t nChunkSize = 1024 * 100;
-        GByte* pabyChunk = (GByte *) VSICalloc( nChunkSize + 1, sizeof(GByte) );
+        GByte* pabyChunk = static_cast<GByte *>(
+            VSI_CALLOC_VERBOSE( nChunkSize + 1, sizeof(GByte) ) );
         if (pabyChunk == NULL)
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
             delete poDS;
             return NULL;
         }
         pabyChunk[nChunkSize] = '\0';
 
-        VSIFSeekL( poDS->fp, nStartOfData, SEEK_SET );
+        if( VSIFSeekL( poDS->fp, nStartOfData, SEEK_SET ) < 0 )
+        {
+            delete poDS;
+            VSIFree( pabyChunk );
+            return NULL;
+        }
 
         /* Scan for dot in subsequent chunks of data. */
         while( !VSIFEofL( poDS->fp) )
         {
-            VSIFReadL( pabyChunk, sizeof(GByte), nChunkSize, poDS->fp );
-            CPLAssert( pabyChunk[nChunkSize] == '\0' );
+            CPL_IGNORE_RET_VAL(VSIFReadL( pabyChunk, nChunkSize, 1, poDS->fp ));
 
-            for(i = 0; i < (int)nChunkSize; i++)
+            for( int i = 0; i < static_cast<int>(nChunkSize); i++)
             {
                 GByte ch = pabyChunk[i];
                 if (ch == '.' || ch == ',' || ch == 'e' || ch == 'E')
@@ -866,35 +875,38 @@ GDALDataset *AAIGDataset::CommonOpen( GDALOpenInfo * poOpenInfo,
 /* -------------------------------------------------------------------- */
 /*      Try to read projection file.                                    */
 /* -------------------------------------------------------------------- */
-    char        *pszDirname, *pszBasename;
-    VSIStatBufL   sStatBuf;
 
-    pszDirname = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
-    pszBasename = CPLStrdup(CPLGetBasename(poOpenInfo->pszFilename));
+    char * const pszDirname = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
+    char * const pszBasename =
+        CPLStrdup(CPLGetBasename(poOpenInfo->pszFilename));
 
     poDS->osPrjFilename = CPLFormFilename( pszDirname, pszBasename, "prj" );
-    int nRet = VSIStatL( poDS->osPrjFilename, &sStatBuf );
-
+    int nRet = 0;
+    {
+        VSIStatBufL sStatBuf;
+        nRet = VSIStatL( poDS->osPrjFilename, &sStatBuf );
+    }
     if( nRet != 0 && VSIIsCaseSensitiveFS(poDS->osPrjFilename) )
     {
         poDS->osPrjFilename = CPLFormFilename( pszDirname, pszBasename, "PRJ" );
+
+        VSIStatBufL sStatBuf;
         nRet = VSIStatL( poDS->osPrjFilename, &sStatBuf );
     }
 
     if( nRet == 0 )
     {
-        OGRSpatialReference     oSRS;
-
         poDS->papszPrj = CSLLoad( poDS->osPrjFilename );
 
-        CPLDebug( "AAIGrid", "Loaded SRS from %s", 
+        CPLDebug( "AAIGrid", "Loaded SRS from %s",
                   poDS->osPrjFilename.c_str() );
 
+        OGRSpatialReference oSRS;
         if( oSRS.importFromESRI( poDS->papszPrj ) == OGRERR_NONE )
         {
-            // If geographic values are in seconds, we must transform. 
-            // Is there a code for minutes too? 
-            if( oSRS.IsGeographic() 
+            // If geographic values are in seconds, we must transform.
+            // Is there a code for minutes too?
+            if( oSRS.IsGeographic()
                 && EQUAL(OSR_GDS( poDS->papszPrj, "Units", ""), "DS") )
             {
                 poDS->adfGeoTransform[0] /= 3600.0;
@@ -922,9 +934,10 @@ GDALDataset *AAIGDataset::CommonOpen( GDALOpenInfo * poOpenInfo,
 /* -------------------------------------------------------------------- */
 /*      Check for external overviews.                                   */
 /* -------------------------------------------------------------------- */
-    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles() );
+    poDS->oOvManager.Initialize(
+        poDS, poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles() );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -935,7 +948,7 @@ CPLErr AAIGDataset::GetGeoTransform( double * padfTransform )
 
 {
     memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
-    return( CE_None );
+    return CE_None;
 }
 
 /************************************************************************/
@@ -954,20 +967,20 @@ const char *AAIGDataset::GetProjectionRef()
 
 GDALDataset * AAIGDataset::CreateCopy(
     const char * pszFilename, GDALDataset *poSrcDS,
-    CPL_UNUSED int bStrict,
+    int /* bStrict */,
     char ** papszOptions,
     GDALProgressFunc pfnProgress, void * pProgressData )
 {
-    int  nBands = poSrcDS->GetRasterCount();
-    int  nXSize = poSrcDS->GetRasterXSize();
-    int  nYSize = poSrcDS->GetRasterYSize();
+    const int nBands = poSrcDS->GetRasterCount();
+    const int nXSize = poSrcDS->GetRasterXSize();
+    const int nYSize = poSrcDS->GetRasterYSize();
 
 /* -------------------------------------------------------------------- */
 /*      Some rudimentary checks                                         */
 /* -------------------------------------------------------------------- */
     if( nBands != 1 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "AAIG driver doesn't support %d bands.  Must be 1 band.\n",
                   nBands );
 
@@ -980,13 +993,11 @@ GDALDataset * AAIGDataset::CreateCopy(
 /* -------------------------------------------------------------------- */
 /*      Create the dataset.                                             */
 /* -------------------------------------------------------------------- */
-    VSILFILE        *fpImage;
-
-    fpImage = VSIFOpenL( pszFilename, "wt" );
+    VSILFILE *fpImage = VSIFOpenL( pszFilename, "wt" );
     if( fpImage == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Unable to create file %s.\n", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Unable to create file %s.\n",
                   pszFilename );
         return NULL;
     }
@@ -996,42 +1007,43 @@ GDALDataset * AAIGDataset::CreateCopy(
 /* -------------------------------------------------------------------- */
     double      adfGeoTransform[6];
     char        szHeader[2000];
-    const char *pszForceCellsize = 
+    const char *pszForceCellsize =
         CSLFetchNameValue( papszOptions, "FORCE_CELLSIZE" );
 
     poSrcDS->GetGeoTransform( adfGeoTransform );
 
-    if( ABS(adfGeoTransform[1]+adfGeoTransform[5]) < 0.0000001 
-        || ABS(adfGeoTransform[1]-adfGeoTransform[5]) < 0.0000001 
-        || (pszForceCellsize && CSLTestBoolean(pszForceCellsize)) )
-        CPLsprintf( szHeader, 
-                 "ncols        %d\n" 
+    if( ABS(adfGeoTransform[1]+adfGeoTransform[5]) < 0.0000001
+        || ABS(adfGeoTransform[1]-adfGeoTransform[5]) < 0.0000001
+        || (pszForceCellsize && CPLTestBool(pszForceCellsize)) )
+        CPLsnprintf( szHeader, sizeof(szHeader),
+                 "ncols        %d\n"
                  "nrows        %d\n"
                  "xllcorner    %.12f\n"
                  "yllcorner    %.12f\n"
-                 "cellsize     %.12f\n", 
-                 nXSize, nYSize, 
-                 adfGeoTransform[0], 
+                 "cellsize     %.12f\n",
+                 nXSize, nYSize,
+                 adfGeoTransform[0],
                  adfGeoTransform[3] - nYSize * adfGeoTransform[1],
                  adfGeoTransform[1] );
     else
     {
         if( pszForceCellsize == NULL )
-            CPLError( CE_Warning, CPLE_AppDefined, 
-                      "Producing a Golden Surfer style file with DX and DY instead\n"
-                      "of CELLSIZE since the input pixels are non-square.  Use the\n"
-                      "FORCE_CELLSIZE=TRUE creation option to force use of DX for\n"
-                      "even though this will be distorted.  Most ASCII Grid readers\n"
-                      "(ArcGIS included) do not support the DX and DY parameters.\n" );
-        CPLsprintf( szHeader, 
-                 "ncols        %d\n" 
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Producing a Golden Surfer style file with DX and DY "
+                      "instead of CELLSIZE since the input pixels are "
+                      "non-square.  Use the FORCE_CELLSIZE=TRUE creation "
+                      "option to force use of DX for even though this will "
+                      "be distorted.  Most ASCII Grid readers (ArcGIS "
+                      "included) do not support the DX and DY parameters." );
+        CPLsnprintf( szHeader, sizeof(szHeader),
+                 "ncols        %d\n"
                  "nrows        %d\n"
                  "xllcorner    %.12f\n"
                  "yllcorner    %.12f\n"
                  "dx           %.12f\n"
-                 "dy           %.12f\n", 
-                 nXSize, nYSize, 
-                 adfGeoTransform[0], 
+                 "dy           %.12f\n",
+                 nXSize, nYSize,
+                 adfGeoTransform[0],
                  adfGeoTransform[3] + nYSize * adfGeoTransform[5],
                  adfGeoTransform[1],
                  fabs(adfGeoTransform[5]) );
@@ -1040,32 +1052,34 @@ GDALDataset * AAIGDataset::CreateCopy(
 /* -------------------------------------------------------------------- */
 /*     Builds the format string used for printing float values.         */
 /* -------------------------------------------------------------------- */
-    char szFormatFloat[32];
+    char szFormatFloat[32] = { '\0' };
     strcpy(szFormatFloat, " %.20g");
-    const char *pszDecimalPrecision = 
+    const char *pszDecimalPrecision =
         CSLFetchNameValue( papszOptions, "DECIMAL_PRECISION" );
     const char *pszSignificantDigits =
         CSLFetchNameValue( papszOptions, "SIGNIFICANT_DIGITS" );
-    int bIgnoreSigDigits = FALSE;
+    bool bIgnoreSigDigits = false;
     if( pszDecimalPrecision && pszSignificantDigits )
     {
         CPLError( CE_Warning, CPLE_AppDefined,
                   "Conflicting precision arguments, using DECIMAL_PRECISION" );
-        bIgnoreSigDigits = TRUE;
+        bIgnoreSigDigits = true;
     }
     int nPrecision;
     if ( pszSignificantDigits && !bIgnoreSigDigits )
     {
         nPrecision = atoi( pszSignificantDigits );
         if (nPrecision >= 0)
-            sprintf( szFormatFloat, " %%.%dg", nPrecision );
+            snprintf( szFormatFloat, sizeof(szFormatFloat),
+                      " %%.%dg", nPrecision );
         CPLDebug( "AAIGrid", "Setting precision format: %s", szFormatFloat );
     }
     else if( pszDecimalPrecision )
     {
         nPrecision = atoi( pszDecimalPrecision );
         if ( nPrecision >= 0 )
-            sprintf( szFormatFloat, " %%.%df", nPrecision );
+            snprintf( szFormatFloat, sizeof(szFormatFloat),
+                      " %%.%df", nPrecision );
         CPLDebug( "AAIGrid", "Setting precision format: %s", szFormatFloat );
     }
 
@@ -1073,65 +1087,78 @@ GDALDataset * AAIGDataset::CreateCopy(
 /*      Handle nodata (optionally).                                     */
 /* -------------------------------------------------------------------- */
     GDALRasterBand * poBand = poSrcDS->GetRasterBand( 1 );
-    double dfNoData;
-    int bSuccess;
-    int bReadAsInt;
-    bReadAsInt = ( poBand->GetRasterDataType() == GDT_Byte
-                || poBand->GetRasterDataType() == GDT_Int16
-                || poBand->GetRasterDataType() == GDT_UInt16
-                || poBand->GetRasterDataType() == GDT_Int32 );
+    const bool bReadAsInt =
+        poBand->GetRasterDataType() == GDT_Byte
+        || poBand->GetRasterDataType() == GDT_Int16
+        || poBand->GetRasterDataType() == GDT_UInt16
+        || poBand->GetRasterDataType() == GDT_Int32;
 
     // Write `nodata' value to header if it is exists in source dataset
-    dfNoData = poBand->GetNoDataValue( &bSuccess );
+    int bSuccess = FALSE;
+    const double dfNoData = poBand->GetNoDataValue( &bSuccess );
     if ( bSuccess )
     {
-        sprintf( szHeader+strlen( szHeader ), "NODATA_value " );
+        snprintf( szHeader+strlen( szHeader ),
+                  sizeof(szHeader) - strlen(szHeader), "%s", "NODATA_value " );
         if( bReadAsInt )
-            sprintf( szHeader+strlen( szHeader ), "%d", (int)dfNoData );
+            snprintf( szHeader+strlen( szHeader ),
+                      sizeof(szHeader) - strlen(szHeader), "%d",
+                      static_cast<int>(dfNoData) );
         else
-            CPLsprintf( szHeader+strlen( szHeader ), szFormatFloat, dfNoData );
-        sprintf( szHeader+strlen( szHeader ), "\n" );
+            CPLsnprintf( szHeader+strlen( szHeader ),
+                         sizeof(szHeader) - strlen(szHeader),
+                         szFormatFloat, dfNoData );
+        snprintf( szHeader+strlen( szHeader ),
+                  sizeof(szHeader) - strlen(szHeader), "%s", "\n" );
     }
 
-    VSIFWriteL( szHeader, 1, strlen(szHeader), fpImage );
+    if( VSIFWriteL( szHeader, strlen(szHeader), 1, fpImage ) != 1)
+    {
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpImage));
+        return NULL;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Loop over image, copying image data.                            */
 /* -------------------------------------------------------------------- */
-    int         *panScanline = NULL;
-    double      *padfScanline = NULL;
-    int         iLine, iPixel;
-    CPLErr      eErr = CE_None;
+    int *panScanline = NULL;
+    double *padfScanline = NULL;
 
     // Write scanlines to output file
     if (bReadAsInt)
-        panScanline = (int *) CPLMalloc( nXSize *
-                                GDALGetDataTypeSize(GDT_Int32) / 8 );
+        panScanline = static_cast<int *>(
+            CPLMalloc( nXSize * GDALGetDataTypeSize(GDT_Int32) / 8 ) );
     else
-        padfScanline = (double *) CPLMalloc( nXSize *
-                                    GDALGetDataTypeSize(GDT_Float64) / 8 );
+        padfScanline = static_cast<double *>(
+            CPLMalloc( nXSize * GDALGetDataTypeSize(GDT_Float64) / 8 ) );
 
-    int bHasOuputDecimalDot = FALSE;
-    for( iLine = 0; eErr == CE_None && iLine < nYSize; iLine++ )
+    CPLErr eErr = CE_None;
+
+    bool bHasOutputDecimalDot = false;
+    for( int iLine = 0; eErr == CE_None && iLine < nYSize; iLine++ )
     {
         CPLString osBuf;
-        eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, 
-                                 (bReadAsInt) ? (void*)panScanline : (void*)padfScanline,
-                                 nXSize, 1, (bReadAsInt) ? GDT_Int32 : GDT_Float64,
-                                 0, 0, NULL );
+        eErr = poBand->RasterIO(
+            GF_Read, 0, iLine, nXSize, 1,
+            bReadAsInt ? reinterpret_cast<void *>(panScanline) :
+            reinterpret_cast<void *>(padfScanline),
+            nXSize, 1, bReadAsInt ? GDT_Int32 : GDT_Float64,
+            0, 0, NULL );
 
         if( bReadAsInt )
         {
-            for ( iPixel = 0; iPixel < nXSize; iPixel++ )
+            for ( int iPixel = 0; iPixel < nXSize; iPixel++ )
             {
-                sprintf( szHeader, " %d", panScanline[iPixel] );
+                snprintf( szHeader, sizeof(szHeader),
+                          " %d", panScanline[iPixel] );
                 osBuf += szHeader;
                 if( (iPixel & 1023) == 0 || iPixel == nXSize - 1 )
                 {
-                    if ( VSIFWriteL( osBuf, (int)osBuf.size(), 1, fpImage ) != 1 )
+                    if ( VSIFWriteL( osBuf, static_cast<int>(osBuf.size()), 1,
+                                     fpImage ) != 1 )
                     {
                         eErr = CE_Failure;
-                        CPLError( CE_Failure, CPLE_AppDefined, 
+                        CPLError( CE_Failure, CPLE_AppDefined,
                                   "Write failed, disk full?\n" );
                         break;
                     }
@@ -1141,29 +1168,35 @@ GDALDataset * AAIGDataset::CreateCopy(
         }
         else
         {
-            for ( iPixel = 0; iPixel < nXSize; iPixel++ )
+            for ( int iPixel = 0; iPixel < nXSize; iPixel++ )
             {
-                CPLsprintf( szHeader, szFormatFloat, padfScanline[iPixel] );
+                CPLsnprintf( szHeader, sizeof(szHeader),
+                             szFormatFloat, padfScanline[iPixel] );
 
                 // Make sure that as least one value has a decimal point (#6060)
-                if( !bHasOuputDecimalDot )
+                if( !bHasOutputDecimalDot )
                 {
-                    if( strchr(szHeader, '.') || strchr(szHeader, 'e') || strchr(szHeader, 'E') )
-                        bHasOuputDecimalDot = TRUE;
-                    else if( !CPLIsInf(padfScanline[iPixel]) && !CPLIsNan(padfScanline[iPixel]) )
+                    if( strchr(szHeader, '.') || strchr(szHeader, 'e') ||
+                        strchr(szHeader, 'E') )
+                    {
+                        bHasOutputDecimalDot = true;
+                    }
+                    else if( !CPLIsInf(padfScanline[iPixel]) &&
+                             !CPLIsNan(padfScanline[iPixel]) )
                     {
                         strcat(szHeader, ".0");
-                        bHasOuputDecimalDot = TRUE;
+                        bHasOutputDecimalDot = true;
                     }
                 }
 
                 osBuf += szHeader;
                 if( (iPixel & 1023) == 0 || iPixel == nXSize - 1 )
                 {
-                    if ( VSIFWriteL( osBuf, (int)osBuf.size(), 1, fpImage ) != 1 )
+                    if ( VSIFWriteL( osBuf, (int)osBuf.size(), 1,
+                                     fpImage ) != 1 )
                     {
                         eErr = CE_Failure;
-                        CPLError( CE_Failure, CPLE_AppDefined, 
+                        CPLError( CE_Failure, CPLE_AppDefined,
                                   "Write failed, disk full?\n" );
                         break;
                     }
@@ -1171,20 +1204,23 @@ GDALDataset * AAIGDataset::CreateCopy(
                 }
             }
         }
-        VSIFWriteL( (void *) "\n", 1, 1, fpImage );
+        if( VSIFWriteL( (void *) "\n", 1, 1, fpImage ) != 1 )
+            eErr = CE_Failure;
 
         if( eErr == CE_None &&
-            !pfnProgress((iLine + 1) / ((double) nYSize), NULL, pProgressData) )
+            !pfnProgress( (iLine + 1) / static_cast<double>(nYSize), NULL,
+                          pProgressData) )
         {
             eErr = CE_Failure;
-            CPLError( CE_Failure, CPLE_UserInterrupt, 
+            CPLError( CE_Failure, CPLE_UserInterrupt,
                       "User terminated CreateCopy()" );
         }
     }
 
     CPLFree( panScanline );
     CPLFree( padfScanline );
-    VSIFCloseL( fpImage );
+    if( VSIFCloseL( fpImage ) != 0 )
+        eErr = CE_Failure;
 
     if( eErr != CE_None )
         return NULL;
@@ -1192,50 +1228,47 @@ GDALDataset * AAIGDataset::CreateCopy(
 /* -------------------------------------------------------------------- */
 /*      Try to write projection file.                                   */
 /* -------------------------------------------------------------------- */
-    const char  *pszOriginalProjection;
-
-    pszOriginalProjection = (char *)poSrcDS->GetProjectionRef();
+    const char *pszOriginalProjection = poSrcDS->GetProjectionRef();
     if( !EQUAL( pszOriginalProjection, "" ) )
     {
-        char                    *pszDirname, *pszBasename;
-        char                    *pszPrjFilename;
-        char                    *pszESRIProjection = NULL;
-        VSILFILE                *fp;
-        OGRSpatialReference     oSRS;
-
-        pszDirname = CPLStrdup( CPLGetPath(pszFilename) );
-        pszBasename = CPLStrdup( CPLGetBasename(pszFilename) );
-
-        pszPrjFilename = CPLStrdup( CPLFormFilename( pszDirname, pszBasename, "prj" ) );
-        fp = VSIFOpenL( pszPrjFilename, "wt" );
+        char *pszDirname = CPLStrdup( CPLGetPath(pszFilename) );
+        char *pszBasename = CPLStrdup( CPLGetBasename(pszFilename) );
+        char *pszPrjFilename = CPLStrdup( CPLFormFilename( pszDirname, pszBasename, "prj" ) );
+        VSILFILE *fp = VSIFOpenL( pszPrjFilename, "wt" );
         if (fp != NULL)
         {
-            oSRS.importFromWkt( (char **) &pszOriginalProjection );
+            OGRSpatialReference oSRS;
+            // TODO(schwehr): importFromWkt should be const for the args.
+            oSRS.importFromWkt( const_cast<char **>( &pszOriginalProjection ) );
             oSRS.morphToESRI();
+            char *pszESRIProjection = NULL;
             oSRS.exportToWkt( &pszESRIProjection );
-            VSIFWriteL( pszESRIProjection, 1, strlen(pszESRIProjection), fp );
+            CPL_IGNORE_RET_VAL(
+                VSIFWriteL( pszESRIProjection, 1,
+                            strlen(pszESRIProjection), fp ) );
 
-            VSIFCloseL( fp );
+            CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
             CPLFree( pszESRIProjection );
         }
         else
         {
-            CPLError( CE_Failure, CPLE_FileIO, 
+            CPLError( CE_Failure, CPLE_FileIO,
                       "Unable to create file %s.\n", pszPrjFilename );
         }
         CPLFree( pszDirname );
         CPLFree( pszBasename );
         CPLFree( pszPrjFilename );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Re-open dataset, and copy any auxiliary pam information.         */
 /* -------------------------------------------------------------------- */
 
-    /* If outputing to stdout, we can't reopen it, so we'll return */
+    /* If writing to stdout, we can't reopen it, so return */
     /* a fake dataset to make the caller happy */
     CPLPushErrorHandler(CPLQuietErrorHandler);
-    GDALPamDataset* poDS = (GDALPamDataset*) GDALOpen(pszFilename, GA_ReadOnly);
+    GDALPamDataset* poDS =
+        reinterpret_cast<GDALPamDataset *>( GDALOpen(pszFilename, GA_ReadOnly) );
     CPLPopErrorHandler();
     if (poDS)
     {
@@ -1257,17 +1290,16 @@ GDALDataset * AAIGDataset::CreateCopy(
 /*                              OSR_GDS()                               */
 /************************************************************************/
 
-static CPLString OSR_GDS( char **papszNV, const char * pszField, 
-                           const char *pszDefaultValue )
+static CPLString OSR_GDS( char **papszNV, const char * pszField,
+                          const char *pszDefaultValue )
 
 {
-    int         iLine;
-
     if( papszNV == NULL || papszNV[0] == NULL )
         return pszDefaultValue;
 
-    for( iLine = 0; 
-         papszNV[iLine] != NULL && 
+    int iLine = 0;  // Used after for.
+    for( ;
+         papszNV[iLine] != NULL &&
              !EQUALN(papszNV[iLine],pszField,strlen(pszField));
          iLine++ ) {}
 
@@ -1275,16 +1307,14 @@ static CPLString OSR_GDS( char **papszNV, const char * pszField,
         return pszDefaultValue;
     else
     {
-        CPLString osResult;
-        char    **papszTokens;
-        
-        papszTokens = CSLTokenizeString(papszNV[iLine]);
+        char **papszTokens = CSLTokenizeString(papszNV[iLine]);
 
+        CPLString osResult;
         if( CSLCount(papszTokens) > 1 )
             osResult = papszTokens[1];
         else
             osResult = pszDefaultValue;
-        
+
         CSLDestroy( papszTokens );
         return osResult;
     }
@@ -1297,30 +1327,28 @@ static CPLString OSR_GDS( char **papszNV, const char * pszField,
 void GDALRegister_AAIGrid()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "AAIGrid" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "AAIGrid" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "AAIGrid" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Arc/Info ASCII Grid" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#AAIGrid" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "asc" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte UInt16 Int16 Int32 Float32" );
-
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "AAIGrid" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Arc/Info ASCII Grid" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_various.html#AAIGrid" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "asc" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte UInt16 Int16 Int32 Float32" );
+
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>\n"
 "   <Option name='FORCE_CELLSIZE' type='boolean' description='Force use of CELLSIZE, default is FALSE.'/>\n"
 "   <Option name='DECIMAL_PRECISION' type='int' description='Number of decimal when writing floating-point numbers(%f).'/>\n"
 "   <Option name='SIGNIFICANT_DIGITS' type='int' description='Number of significant digits when writing floating-point numbers(%g).'/>\n"
 "</CreationOptionList>\n" );
-        poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST, 
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
 "<OpenOptionLists>\n"
 "   <Option name='DATATYPE' type='string-select' description='Data type to be used.'>\n"
 "       <Value>Int32</Value>\n"
@@ -1329,12 +1357,11 @@ void GDALRegister_AAIGrid()
 "   </Option>\n"
 "</OpenOptionLists>\n" );
 
-        poDriver->pfnOpen = AAIGDataset::Open;
-        poDriver->pfnIdentify = AAIGDataset::Identify;
-        poDriver->pfnCreateCopy = AAIGDataset::CreateCopy;
-        
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    poDriver->pfnOpen = AAIGDataset::Open;
+    poDriver->pfnIdentify = AAIGDataset::Identify;
+    poDriver->pfnCreateCopy = AAIGDataset::CreateCopy;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
 
 /************************************************************************/
@@ -1344,24 +1371,21 @@ void GDALRegister_AAIGrid()
 void GDALRegister_GRASSASCIIGrid()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "GRASSASCIIGrid" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "GRASSASCIIGrid" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "GRASSASCIIGrid" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "GRASS ASCII Grid" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "frmt_various.html#GRASSASCIIGrid" );
+    poDriver->SetDescription( "GRASSASCIIGrid" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "GRASS ASCII Grid" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_various.html#GRASSASCIIGrid" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = GRASSASCIIDataset::Open;
-        poDriver->pfnIdentify = GRASSASCIIDataset::Identify;
+    poDriver->pfnOpen = GRASSASCIIDataset::Open;
+    poDriver->pfnIdentify = GRASSASCIIDataset::Identify;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/adrg/adrgdataset.cpp b/frmts/adrg/adrgdataset.cpp
index 14d78c6..52148ce 100644
--- a/frmts/adrg/adrgdataset.cpp
+++ b/frmts/adrg/adrgdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: adrgdataset.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: adrgdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Purpose:  ADRG reader
  * Author:   Even Rouault, even.rouault at mines-paris.org
@@ -26,19 +26,20 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
-#include "ogr_spatialref.h"
 #include "cpl_string.h"
+#include "gdal_pam.h"
+#include "gdal_frmts.h"
 #include "iso8211.h"
+#include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: adrgdataset.cpp 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: adrgdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 #define N_ELEMENTS(x)  (sizeof(x)/sizeof(x[0]))
 
 class ADRGDataset : public GDALPamDataset
 {
     friend class ADRGRasterBand;
-    
+
     CPLString    osGENFileName;
     CPLString    osIMGFileName;
 
@@ -53,9 +54,9 @@ class ADRGDataset : public GDALPamDataset
     int          BRV;
 
     char**       papszSubDatasets;
-    
+
     ADRGDataset* poOverviewDS;
-    
+
     /* For creation */
     int          bCreation;
     VSILFILE*        fdGEN;
@@ -64,7 +65,7 @@ class ADRGDataset : public GDALPamDataset
     double       adfGeoTransform[6];
     int          nNextAvailableBlock;
     CPLString    osBaseFileName;
-    
+
     static char** GetGENListFromTHF(const char* pszFileName);
     static char** GetIMGListFromGEN(const char* pszFileName, int* pnRecordIndex = NULL);
     static ADRGDataset* OpenDataset(const char* pszGENFileName, const char* pszIMGFileName, DDFRecord* record = NULL);
@@ -74,14 +75,14 @@ class ADRGDataset : public GDALPamDataset
   public:
                  ADRGDataset();
     virtual     ~ADRGDataset();
-    
+
     virtual const char *GetProjectionRef(void);
     virtual CPLErr GetGeoTransform( double * padfGeoTransform );
     virtual CPLErr SetGeoTransform( double * padfGeoTransform );
 
     virtual char      **GetMetadataDomainList();
     virtual char      **GetMetadata( const char * pszDomain = "" );
-    
+
     virtual char      **GetFileList();
 
     void                AddSubDataset( const char* pszGENFileName, const char* pszIMGFileName );
@@ -89,10 +90,10 @@ class ADRGDataset : public GDALPamDataset
     static GDALDataset *Open( GDALOpenInfo * );
     static GDALDataset *Create(const char* pszFilename, int nXSize, int nYSize,
                                int nBands, GDALDataType eType, char **papszOptions);
-    
+
     static double GetLongitudeFromString(const char* str);
     static double GetLatitudeFromString(const char* str);
-    
+
     void WriteGENFile();
     void WriteTHFFile();
 };
@@ -125,12 +126,12 @@ class ADRGRasterBand : public GDALPamRasterBand
 /*                           ADRGRasterBand()                            */
 /************************************************************************/
 
-ADRGRasterBand::ADRGRasterBand( ADRGDataset *poDS, int nBand )
+ADRGRasterBand::ADRGRasterBand( ADRGDataset *poDSIn, int nBandIn )
 
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
-    
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
+
     eDataType = GDT_Byte;
 
     nBlockXSize = 128;
@@ -153,8 +154,8 @@ int ADRGRasterBand::GetOverviewCount()
     ADRGDataset* poDS = (ADRGDataset*)this->poDS;
     if( poDS->poOverviewDS )
         return 1;
-    else
-        return GDALRasterBand::GetOverviewCount();
+
+    return GDALRasterBand::GetOverviewCount();
 }
 
 /************************************************************************/
@@ -169,11 +170,11 @@ GDALRasterBand *ADRGRasterBand::GetOverview( int i )
     {
         if( i < 0 || i >= 1 )
             return NULL;
-        else
-            return poDS->poOverviewDS->GetRasterBand(nBand);
+
+        return poDS->poOverviewDS->GetRasterBand(nBand);
     }
-    else
-        return GDALRasterBand::GetOverview( i );
+
+    return GDALRasterBand::GetOverview( i );
 }
 #endif
 
@@ -181,12 +182,12 @@ GDALRasterBand *ADRGRasterBand::GetOverview( int i )
 /*                            GetNoDataValue()                          */
 /************************************************************************/
 
-double  ADRGRasterBand::GetNoDataValue( int *pbSuccess )
+double ADRGRasterBand::GetNoDataValue( int *pbSuccess )
 {
     if (pbSuccess)
         *pbSuccess = TRUE;
 
-    return 0;
+    return 0.0;
 }
 
 /************************************************************************/
@@ -202,8 +203,7 @@ GDALColorInterp ADRGRasterBand::GetColorInterpretation()
     else if( nBand == 2 )
         return GCI_GreenBand;
 
-    else 
-        return GCI_BlueBand;
+    return GCI_BlueBand;
 }
 
 /************************************************************************/
@@ -214,40 +214,40 @@ CPLErr ADRGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                   void * pImage )
 
 {
-    ADRGDataset* poDS = (ADRGDataset*)this->poDS;
-    int offset;
-    int nBlock = nBlockYOff * poDS->NFC + nBlockXOff;
-    if (nBlockXOff >= poDS->NFC || nBlockYOff >= poDS->NFL)
+    ADRGDataset* l_poDS = (ADRGDataset*)this->poDS;
+    int nBlock = nBlockYOff * l_poDS->NFC + nBlockXOff;
+    if (nBlockXOff >= l_poDS->NFC || nBlockYOff >= l_poDS->NFL)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "nBlockXOff=%d, NFC=%d, nBlockYOff=%d, NFL=%d",
-                 nBlockXOff, poDS->NFC, nBlockYOff, poDS->NFL);
+                 nBlockXOff, l_poDS->NFC, nBlockYOff, l_poDS->NFL);
         return CE_Failure;
     }
     CPLDebug("ADRG", "(%d,%d) -> nBlock = %d", nBlockXOff, nBlockYOff, nBlock);
 
-    if (poDS->TILEINDEX)
+    int offset;
+    if (l_poDS->TILEINDEX)
     {
-        if (poDS->TILEINDEX[nBlock] == 0)
+        if (l_poDS->TILEINDEX[nBlock] == 0)
         {
             memset(pImage, 0, 128 * 128);
             return CE_None;
         }
-        offset = poDS->offsetInIMG + (poDS->TILEINDEX[nBlock] - 1) * 128 * 128 * 3 + (nBand - 1) * 128 * 128;
+        offset = l_poDS->offsetInIMG + (l_poDS->TILEINDEX[nBlock] - 1) * 128 * 128 * 3 + (nBand - 1) * 128 * 128;
     }
     else
-        offset = poDS->offsetInIMG + nBlock * 128 * 128 * 3 + (nBand - 1) * 128 * 128;
-    
-    if (VSIFSeekL(poDS->fdIMG, offset, SEEK_SET) != 0)
+        offset = l_poDS->offsetInIMG + nBlock * 128 * 128 * 3 + (nBand - 1) * 128 * 128;
+
+    if (VSIFSeekL(l_poDS->fdIMG, offset, SEEK_SET) != 0)
     {
         CPLError(CE_Failure, CPLE_FileIO, "Cannot seek to offset %d", offset);
         return CE_Failure;
     }
-    if (VSIFReadL(pImage, 1, 128 * 128, poDS->fdIMG) != 128 * 128)
+    if (VSIFReadL(pImage, 1, 128 * 128, l_poDS->fdIMG) != 128 * 128)
     {
         CPLError(CE_Failure, CPLE_FileIO, "Cannot read data at offset %d", offset);
         return CE_Failure;
     }
-    
+
     return CE_None;
 }
 
@@ -259,22 +259,21 @@ CPLErr ADRGRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                                   void * pImage )
 
 {
-    ADRGDataset* poDS = (ADRGDataset*)this->poDS;
-    int offset;
-    int nBlock = nBlockYOff * poDS->NFC + nBlockXOff;
-    if (poDS->eAccess != GA_Update)
+    ADRGDataset* l_poDS = (ADRGDataset*)this->poDS;
+    int nBlock = nBlockYOff * l_poDS->NFC + nBlockXOff;
+    if (l_poDS->eAccess != GA_Update)
     {
         return CE_Failure;
     }
-    if (nBlockXOff >= poDS->NFC || nBlockYOff >= poDS->NFL)
+    if (nBlockXOff >= l_poDS->NFC || nBlockYOff >= l_poDS->NFL)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "nBlockXOff=%d, NFC=%d, nBlockYOff=%d, NFL=%d",
-                 nBlockXOff, poDS->NFC, nBlockYOff, poDS->NFL);
+                 nBlockXOff, l_poDS->NFC, nBlockYOff, l_poDS->NFL);
         return CE_Failure;
     }
     CPLDebug("ADRG", "(%d,%d) -> nBlock = %d", nBlockXOff, nBlockYOff, nBlock);
-    
-    if (poDS->TILEINDEX[nBlock] == 0)
+
+    if (l_poDS->TILEINDEX[nBlock] == 0)
     {
         unsigned int i;
         int* pi = (int*)pImage;
@@ -288,17 +287,18 @@ CPLErr ADRGRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
             return CE_None;
         }
 
-        poDS->TILEINDEX[nBlock] = poDS->nNextAvailableBlock ++;
+        l_poDS->TILEINDEX[nBlock] = l_poDS->nNextAvailableBlock ++;
     }
 
-    offset = poDS->offsetInIMG + (poDS->TILEINDEX[nBlock] - 1) * 128 * 128 * 3 + (nBand - 1) * 128 * 128;
+    int offset
+        = l_poDS->offsetInIMG + (l_poDS->TILEINDEX[nBlock] - 1) * 128 * 128 * 3 + (nBand - 1) * 128 * 128;
 
-    if (VSIFSeekL(poDS->fdIMG, offset, SEEK_SET) != 0)
+    if (VSIFSeekL(l_poDS->fdIMG, offset, SEEK_SET) != 0)
     {
         CPLError(CE_Failure, CPLE_FileIO, "Cannot seek to offset %d", offset);
         return CE_Failure;
     }
-    if (VSIFWriteL(pImage, 1, 128 * 128, poDS->fdIMG) != 128 * 128)
+    if (VSIFWriteL(pImage, 1, 128 * 128, l_poDS->fdIMG) != 128 * 128)
     {
         CPLError(CE_Failure, CPLE_FileIO, "Cannot read data at offset %d", offset);
         return CE_Failure;
@@ -328,8 +328,8 @@ static unsigned int WriteSubFieldInt(VSILFILE* fd, int val, unsigned int size)
 {
     char* str = (char*)CPLMalloc(size+1);
     char formatStr[32];
-    sprintf( formatStr, "%%0%dd", size);
-    sprintf( str, formatStr, val);
+    snprintf( formatStr, sizeof(formatStr), "%%0%dd", size);
+    snprintf( str, size+1, formatStr, val);
     VSIFWriteL(str, 1, size, fd);
     CPLFree(str);
     return size;
@@ -357,7 +357,7 @@ static unsigned int WriteLongitude(VSILFILE* fd, double val)
     int ddd = (int)val;
     int mm = (int)((val - ddd) * 60);
     double ssdotss = ((val - ddd) * 60 - mm) * 60;
-    sprintf(str, "%c%03d%02d%05.2f", sign, ddd, mm, ssdotss);
+    snprintf(str, sizeof(str), "%c%03d%02d%05.2f", sign, ddd, mm, ssdotss);
     CPLAssert((int)strlen(str) == 11);
     VSIFWriteL(str, 1, 11, fd);
     return 11;
@@ -371,7 +371,7 @@ static unsigned int WriteLatitude(VSILFILE* fd, double val)
     int dd = (int)val;
     int mm = (int)((val - dd) * 60);
     double ssdotss = ((val - dd) * 60 - mm) * 60;
-    sprintf(str, "%c%02d%02d%05.2f", sign, dd, mm, ssdotss);
+    snprintf(str, sizeof(str), "%c%02d%02d%05.2f", sign, dd, mm, ssdotss);
     CPLAssert((int)strlen(str) == 10);
     VSIFWriteL(str, 1, 10, fd);
     return 10;
@@ -390,24 +390,23 @@ static void FinishWriteLeader(VSILFILE* fd, int beginPos, int sizeFieldLength, i
 {
     int endPos = (int)VSIFTellL(fd);
     VSIFSeekL(fd, beginPos, SEEK_SET);
-    
+
     int nLeaderSize = 24;
     char szLeader[24+1];
     memset(szLeader, ' ', nLeaderSize);
-    
-    int i;
+
     int nDataSize = 0;
     int nFieldOffset = 0;
-    for(i=0;i<nFields;i++)
+    for(int i=0;i<nFields;i++)
         nDataSize += sizeOfFields[i];
     nFieldOffset = (sizeFieldLength + sizeFieldPos + sizeFieldTag) * nFields + 1;
     nDataSize += nFieldOffset;
-    
-    sprintf( szLeader+0, "%05d", (int) (nDataSize + nLeaderSize) );
+
+    snprintf( szLeader+0, sizeof(szLeader)-0, "%05d", (int) (nDataSize + nLeaderSize) );
     szLeader[5] = ' ';
     szLeader[6] = 'D';
-    
-    sprintf( szLeader + 12, "%05d", (int) (nFieldOffset + nLeaderSize) );
+
+    snprintf( szLeader+12, sizeof(szLeader)-12, "%05d", (int) (nFieldOffset + nLeaderSize) );
     szLeader[17] = ' ';
 
     szLeader[20] = (char) ('0' + sizeFieldLength);
@@ -416,9 +415,9 @@ static void FinishWriteLeader(VSILFILE* fd, int beginPos, int sizeFieldLength, i
     szLeader[23] = (char) ('0' + sizeFieldTag);
 
     VSIFWriteL(szLeader, 1, nLeaderSize, fd);
-    
+
     int acc = 0;
-    for(i=0;i<nFields;i++)
+    for(int i=0;i<nFields;i++)
     {
         VSIFWriteL(nameOfFields[i], 1, sizeFieldTag, fd);
         WriteSubFieldInt(fd, sizeOfFields[i], sizeFieldLength);
@@ -426,7 +425,7 @@ static void FinishWriteLeader(VSILFILE* fd, int beginPos, int sizeFieldLength, i
         acc += sizeOfFields[i];
     }
     WriteFieldTerminator(fd);
-    
+
     VSIFSeekL(fd, endPos, SEEK_SET);
 }
 
@@ -444,26 +443,25 @@ static void FinishWriteHeader(VSILFILE* fd, int beginPos, int sizeFieldLength, i
 {
     int endPos = (int)VSIFTellL(fd);
     VSIFSeekL(fd, beginPos, SEEK_SET);
-    
+
     int nLeaderSize = 24;
     char szLeader[24+1];
     memset(szLeader, ' ', nLeaderSize);
-    
-    int i;
+
     int nDataSize = 0;
     int nFieldOffset = 0;
-    for(i=0;i<nFields;i++)
+    for(int i=0;i<nFields;i++)
         nDataSize += sizeOfFields[i];
     nFieldOffset = (sizeFieldLength + sizeFieldPos + sizeFieldTag) * nFields + 1;
     nDataSize += nFieldOffset;
-    
-    sprintf( szLeader+0, "%05d", (int) (nDataSize + nLeaderSize) );
+
+    snprintf( szLeader+0, sizeof(szLeader)-0, "%05d", (int) (nDataSize + nLeaderSize) );
     szLeader[5] = '2';
     szLeader[6] = 'L';
-    
+
     szLeader[10] = '0';
     szLeader[11] = '6';
-    sprintf( szLeader + 12, "%05d", (int) (nFieldOffset + nLeaderSize) );
+    snprintf( szLeader+12, sizeof(szLeader)-12, "%05d", (int) (nFieldOffset + nLeaderSize) );
     szLeader[17] = ' ';
 
     szLeader[20] = (char) ('0' + sizeFieldLength);
@@ -472,9 +470,9 @@ static void FinishWriteHeader(VSILFILE* fd, int beginPos, int sizeFieldLength, i
     szLeader[23] = (char) ('0' + sizeFieldTag);
 
     VSIFWriteL(szLeader, 1, nLeaderSize, fd);
-    
+
     int acc = 0;
-    for(i=0;i<nFields;i++)
+    for(int i=0;i<nFields;i++)
     {
         VSIFWriteL(nameOfFields[i], 1, sizeFieldTag, fd);
         WriteSubFieldInt(fd, sizeOfFields[i], sizeFieldLength);
@@ -482,7 +480,7 @@ static void FinishWriteHeader(VSILFILE* fd, int beginPos, int sizeFieldLength, i
         acc += sizeOfFields[i];
     }
     WriteFieldTerminator(fd);
-    
+
     VSIFSeekL(fd, endPos, SEEK_SET);
 }
 
@@ -501,16 +499,16 @@ static int WriteFieldDecl(VSILFILE* fd, char _data_struct_code , char _data_type
     }
     int len = 6;
     VSIFWriteL(_fieldName, 1, strlen(_fieldName), fd);
-    len += strlen(_fieldName);
+    len += static_cast<int>(strlen(_fieldName));
     if (_arrayDescr[0])
     {
         len += WriteUnitTerminator(fd);
         VSIFWriteL(_arrayDescr, 1, strlen(_arrayDescr), fd);
-        len += strlen(_arrayDescr);
+        len += static_cast<int>(strlen(_arrayDescr));
 
         len += WriteUnitTerminator(fd);
         VSIFWriteL(_formatControls, 1, strlen(_formatControls), fd);
-        len += strlen(_formatControls);
+        len += static_cast<int>(strlen(_formatControls));
     }
     len += WriteFieldTerminator(fd);
     return len;
@@ -521,7 +519,9 @@ static int WriteFieldDecl(VSILFILE* fd, char _data_struct_code , char _data_type
 /*                          ADRGDataset()                               */
 /************************************************************************/
 
-ADRGDataset::ADRGDataset()
+ADRGDataset::ADRGDataset() :
+    offsetInIMG(0), NFC(0), NFL(0), LSO(0.0), PSO(0.0), ARV(0), BRV(0),
+    bGeoTransformValid(0), nNextAvailableBlock(0)
 {
     bCreation = FALSE;
     poOverviewDS = NULL;
@@ -542,22 +542,23 @@ ADRGDataset::~ADRGDataset()
     {
         delete poOverviewDS;
     }
-    
+
     CSLDestroy(papszSubDatasets);
-    
+
     if (bCreation)
     {
         GDALPamDataset::FlushCache();
-        
+
         /* Write header and padding of image */
         VSIFSeekL(fdIMG, 0, SEEK_SET);
         {
             VSILFILE* fd = fdIMG;
+            {
             int nFields = 0;
             int sizeOfFields[] = { 0, 0, 0, 0 };
             const char* nameOfFields[] = { "000", "001", "PAD", "SCN" };
             int pos = BeginHeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
-    
+
             sizeOfFields[nFields++] += WriteFieldDecl(fd, ' ', ' ', "GEO_DATA_FILE", "", ""); /* 000 */
             sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "RECORD_ID_FIELD", /* 001 */
                                                     "RTY!RID",
@@ -568,22 +569,23 @@ ADRGDataset::~ADRGDataset()
             sizeOfFields[nFields++] += WriteFieldDecl(fd, '2', '0', "PIXEL_FIELD", /* SCN */
                                                     "*PIX",
                                                     "(A(1))");
-    
+
             FinishWriteHeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
-            
+            }
+
             /* Write IMAGE_RECORD */
             {
                 int nFields = 0;
                 int sizeOfFields[] = {0, 0, 0};
                 const char* nameOfFields[] = { "001", "PAD", "SCN" };
                 int pos = BeginLeader(fd, 9, 9, 3, N_ELEMENTS(sizeOfFields));
-        
+
                 /* Field 001 */
                 sizeOfFields[nFields] += WriteSubFieldStr(fd, "IMG", 3); /* RTY */
                 sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
                 sizeOfFields[nFields] += WriteFieldTerminator(fd);
                 nFields++;
-        
+
                 /* Field PAD */
                 int endPos = (int)VSIFTellL(fd);
                 char* pad = (char*)CPLMalloc(2047 - endPos);
@@ -593,11 +595,11 @@ ADRGDataset::~ADRGDataset()
                 WriteFieldTerminator(fd);
                 sizeOfFields[nFields] += 2047 - endPos + 1;
                 nFields++;
-                
+
                 /* Field SCN */
                 sizeOfFields[nFields] = (nNextAvailableBlock - 1) * 128 * 128 * 3;
                 nFields++;
-        
+
                 FinishWriteLeader(fd, pos, 9, 9, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
             }
         }
@@ -606,7 +608,7 @@ ADRGDataset::~ADRGDataset()
         int offset = offsetInIMG + (nNextAvailableBlock - 1) * 128 * 128 * 3;
         VSIFSeekL(fdIMG, offset, SEEK_SET);
         WriteFieldTerminator(fdIMG);
-        
+
         WriteGENFile();
         WriteTHFFile();
     }
@@ -615,7 +617,7 @@ ADRGDataset::~ADRGDataset()
     {
         VSIFCloseL(fdIMG);
     }
-    
+
     if (fdGEN)
     {
         VSIFCloseL(fdGEN);
@@ -638,14 +640,13 @@ ADRGDataset::~ADRGDataset()
 char ** ADRGDataset::GetFileList()
 {
     char** papszFileList = GDALPamDataset::GetFileList();
-    
+
     if (osGENFileName.size() > 0 && osIMGFileName.size() > 0)
     {
         CPLString osMainFilename = GetDescription();
-        int bMainFileReal;
         VSIStatBufL  sStat;
 
-        bMainFileReal = VSIStatL( osMainFilename, &sStat ) == 0;
+        const bool bMainFileReal = VSIStatL( osMainFilename, &sStat ) == 0;
         if (bMainFileReal)
         {
             CPLString osShortMainFilename = CPLGetFilename(osMainFilename);
@@ -655,10 +656,10 @@ char ** ADRGDataset::GetFileList()
         }
         else
             papszFileList = CSLAddString(papszFileList, osGENFileName.c_str());
-        
+
         papszFileList = CSLAddString(papszFileList, osIMGFileName.c_str());
     }
-    
+
     return papszFileList;
 }
 
@@ -670,19 +671,19 @@ void ADRGDataset::AddSubDataset( const char* pszGENFileName, const char* pszIMGF
 {
     char	szName[80];
     int		nCount = CSLCount(papszSubDatasets ) / 2;
-    
+
     CPLString osSubDatasetName;
     osSubDatasetName = "ADRG:";
     osSubDatasetName += pszGENFileName;
     osSubDatasetName += ",";
     osSubDatasetName += pszIMGFileName;
 
-    sprintf( szName, "SUBDATASET_%d_NAME", nCount+1 );
-    papszSubDatasets = 
+    snprintf( szName, sizeof(szName), "SUBDATASET_%d_NAME", nCount+1 );
+    papszSubDatasets =
         CSLSetNameValue( papszSubDatasets, szName, osSubDatasetName);
 
-    sprintf( szName, "SUBDATASET_%d_DESC", nCount+1 );
-    papszSubDatasets = 
+    snprintf( szName, sizeof(szName), "SUBDATASET_%d_DESC", nCount+1 );
+    papszSubDatasets =
         CSLSetNameValue( papszSubDatasets, szName, osSubDatasetName);
 }
 
@@ -794,15 +795,11 @@ DDFRecord* ADRGDataset::FindRecordInGENForIMG(DDFModule& module,
     /* Finds the GEN file corresponding to the IMG file */
     if (!module.Open(pszGENFileName, TRUE))
         return NULL;
-        
-        
+
     CPLString osShortIMGFilename = CPLGetFilename(pszIMGFileName);
-        
-    DDFField* field;
-    DDFFieldDefn *fieldDefn;
-    
+
     /* Now finds the record */
-    while (TRUE)
+    while (true)
     {
         CPLPushErrorHandler( CPLQuietErrorHandler );
         DDFRecord* record = module.ReadRecord();
@@ -813,8 +810,8 @@ DDFRecord* ADRGDataset::FindRecordInGENForIMG(DDFModule& module,
 
         if (record->GetFieldCount() >= 5)
         {
-            field = record->GetField(0);
-            fieldDefn = field->GetFieldDefn();
+            DDFField *field = record->GetField(0);
+            DDFFieldDefn *fieldDefn = field->GetFieldDefn();
             if (!(strcmp(fieldDefn->GetName(), "001") == 0 &&
                 fieldDefn->GetSubfieldCount() == 2))
             {
@@ -827,19 +824,19 @@ DDFRecord* ADRGDataset::FindRecordInGENForIMG(DDFModule& module,
             /* Ignore overviews */
             if ( strcmp(RTY, "OVV") == 0 )
                 continue;
-            
+
             if ( strcmp(RTY, "GIN") != 0 )
                 continue;
 
             field = record->GetField(3);
             fieldDefn = field->GetFieldDefn();
-            
+
             if (!(strcmp(fieldDefn->GetName(), "SPR") == 0 &&
                     fieldDefn->GetSubfieldCount() == 15))
             {
                 continue;
             }
-     
+
             const char* pszBAD = record->GetStringSubfield("SPR", 0, "BAD", 0);
             if( pszBAD == NULL || strlen(pszBAD) != 12 )
                 continue;
@@ -849,7 +846,7 @@ DDFRecord* ADRGDataset::FindRecordInGENForIMG(DDFModule& module,
                 if (c)
                     *c = 0;
             }
-            
+
             if (EQUAL(osShortIMGFilename.c_str(), osBAD.c_str()))
             {
                 return record;
@@ -866,7 +863,7 @@ ADRGDataset* ADRGDataset::OpenDataset(
         const char* pszGENFileName, const char* pszIMGFileName, DDFRecord* record)
 {
     DDFModule module;
-    
+
     int SCA = 0;
     int ZNA = 0;
     double PSP;
@@ -879,12 +876,11 @@ ADRGDataset* ADRGDataset::OpenDataset(
     CPLString osBAD;
     int TIF;
     int* TILEINDEX = NULL;
-    int i;
-    
+
     DDFField* field;
     DDFFieldDefn *fieldDefn;
     DDFSubfieldDefn* subfieldDefn;
-    
+
     if (record == NULL)
     {
         record = FindRecordInGENForIMG(module, pszGENFileName, pszIMGFileName);
@@ -902,24 +898,24 @@ ADRGDataset* ADRGDataset::OpenDataset(
     {
         return NULL;
     }
-    
+
     const char* pszPTR = record->GetStringSubfield("DSI", 0, "PRT", 0);
     if( pszPTR == NULL || !EQUAL(pszPTR, "ADRG") )
        return NULL;
-    
+
     const char* pszNAM = record->GetStringSubfield("DSI", 0, "NAM", 0);
     if( pszNAM == NULL || strlen(pszNAM) != 8 )
         return NULL;
     CPLString osNAM = pszNAM;
-    
+
     field = record->GetField(2);
     if( field == NULL )
         return NULL;
     fieldDefn = field->GetFieldDefn();
-    
-    int isGIN = TRUE;
-    
-    if (isGIN)
+
+    // TODO: Support on GIN things.  And what is GIN?
+    // GIN might mean general information and might be a typo of GEN.
+    // if (isGIN)
     {
         if (!(strcmp(fieldDefn->GetName(), "GEN") == 0 &&
                 fieldDefn->GetSubfieldCount() == 21))
@@ -957,6 +953,7 @@ ADRGDataset* ADRGDataset::OpenDataset(
         PSO = GetLatitudeFromString(pszPSO);
         CPLDebug("ADRG", "PSO=%f", PSO);
     }
+#if 0
     else
     {
         if (!(strcmp(fieldDefn->GetName(), "OVI") == 0 &&
@@ -964,16 +961,16 @@ ADRGDataset* ADRGDataset::OpenDataset(
         {
             return NULL;
         }
-        
+
         if( record->GetIntSubfield("OVI", 0, "STR", 0) != 3 )
             return NULL;
-        
+
         ARV = record->GetIntSubfield("OVI", 0, "ARV", 0);
         CPLDebug("ADRG", "ARV=%d", ARV);
-        
+
         BRV = record->GetIntSubfield("OVI", 0, "BRV", 0);
         CPLDebug("ADRG", "BRV=%d", BRV);
-        
+
         const char* pszLSO = record->GetStringSubfield("OVI", 0, "LSO", 0);
         if( pszLSO == NULL || strlen(pszLSO) != 11 )
             return NULL;
@@ -986,12 +983,13 @@ ADRGDataset* ADRGDataset::OpenDataset(
         PSO = GetLatitudeFromString(pszPSO);
         CPLDebug("ADRG", "PSO=%f", PSO);
     }
+#endif
 
     field = record->GetField(3);
     if( field == NULL )
         return NULL;
     fieldDefn = field->GetFieldDefn();
-    
+
     if (!(strcmp(fieldDefn->GetName(), "SPR") == 0 &&
             fieldDefn->GetSubfieldCount() == 15))
     {
@@ -1004,6 +1002,15 @@ ADRGDataset* ADRGDataset::OpenDataset(
     NFC = record->GetIntSubfield("SPR", 0, "NFC", 0);
     CPLDebug("ADRG", "NFC=%d", NFC);
 
+    if( NFL <= 0 || NFC <= 0 ||
+        NFL > INT_MAX / 128 ||
+        NFC > INT_MAX / 128 ||
+        NFL > (INT_MAX - 1) / (NFC * 5) )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,"Invalid NFL / NFC values");
+        return NULL;
+    }
+
     int PNC = record->GetIntSubfield("SPR", 0, "PNC", 0);
     CPLDebug("ADRG", "PNC=%d", PNC);
     if (PNC != 128)
@@ -1041,33 +1048,40 @@ ADRGDataset* ADRGDataset::OpenDataset(
         return NULL;
     TIF = pszTIF[0] == 'Y';
     CPLDebug("ADRG", "TIF=%d", TIF);
-    
+
     if (TIF)
     {
         if (record->GetFieldCount() != 6)
         {
             return NULL;
         }
-        
+
         field = record->GetField(5);
         if( field == NULL )
             return NULL;
         fieldDefn = field->GetFieldDefn();
-    
+
         if (!(strcmp(fieldDefn->GetName(), "TIM") == 0))
         {
             return NULL;
         }
-        
+
         if (field->GetDataSize() != 5 * NFL * NFC + 1)
         {
             return NULL;
         }
-    
-        TILEINDEX = new int [NFL * NFC];
+
+        try
+        {
+            TILEINDEX = new int [NFL * NFC];
+        }
+        catch( const std::bad_alloc& )
+        {
+            return NULL;
+        }
         const char* ptr = field->GetData();
         char offset[5+1]={0};
-        for(i=0;i<NFL*NFC;i++)
+        for(int i=0;i<NFL*NFC;i++)
         {
             strncpy(offset, ptr, 5);
             ptr += 5;
@@ -1083,7 +1097,7 @@ ADRGDataset* ADRGDataset::OpenDataset(
         delete[] TILEINDEX;
         return NULL;
     }
-    
+
     if (ZNA == 9 || ZNA == 18)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Polar cases are not handled by ADRG driver");
@@ -1091,7 +1105,7 @@ ADRGDataset* ADRGDataset::OpenDataset(
         delete[] TILEINDEX;
         return NULL;
     }
-    
+
     /* Skip ISO8211 header of IMG file */
     int offsetInIMG = 0;
     char c;
@@ -1113,7 +1127,7 @@ ADRGDataset* ADRGDataset::OpenDataset(
                 return NULL;
             }
             offsetInIMG += 3;
-            if (strncmp(recordName,"IMG",3) == 0)
+            if (STARTS_WITH(recordName, "IMG"))
             {
                 offsetInIMG += 4;
                 if (VSIFSeekL(fdIMG,3,SEEK_CUR) != 0 ||
@@ -1146,18 +1160,18 @@ ADRGDataset* ADRGDataset::OpenDataset(
             return NULL;
         }
     }
-    
+
     if (VSIFEofL(fdIMG))
     {
         VSIFCloseL(fdIMG);
         delete[] TILEINDEX;
         return NULL;
     }
-    
+
     CPLDebug("ADRG", "Img offset data = %d", offsetInIMG);
-    
+
     ADRGDataset* poDS = new ADRGDataset();
-    
+
     poDS->osGENFileName = pszGENFileName;
     poDS->osIMGFileName = pszIMGFileName;
     poDS->NFC = NFC;
@@ -1180,17 +1194,17 @@ ADRGDataset* ADRGDataset::OpenDataset(
     poDS->adfGeoTransform[4] = 0.0;
     poDS->adfGeoTransform[5] = - 360. / BRV;
 
-    if (isGIN)
+    // if (isGIN)
     {
-        char pszValue[32];
-        sprintf(pszValue, "%d", SCA);
-        poDS->SetMetadataItem( "ADRG_SCA", pszValue );
+        char szValue[32];
+        snprintf( szValue, sizeof(szValue), "%d", SCA);
+        poDS->SetMetadataItem( "ADRG_SCA", szValue );
     }
-    
+
     poDS->SetMetadataItem( "ADRG_NAM", osNAM.c_str() );
-    
+
     poDS->nBands = 3;
-    for( i = 0; i < poDS->nBands; i++ )
+    for( int i = 0; i < poDS->nBands; i++ )
         poDS->SetBand( i+1, new ADRGRasterBand( poDS, i+1 ) );
 
     return poDS;
@@ -1204,16 +1218,13 @@ char** ADRGDataset::GetGENListFromTHF(const char* pszFileName)
 {
     DDFModule module;
     DDFRecord * record;
-    DDFField* field;
-    DDFFieldDefn *fieldDefn;
-    int i;
     int nFilenames = 0;
     char** papszFileNames = NULL;
 
     if (!module.Open(pszFileName, TRUE))
         return papszFileNames;
 
-    while (TRUE)
+    while (true)
     {
         CPLPushErrorHandler( CPLQuietErrorHandler );
         record = module.ReadRecord();
@@ -1224,8 +1235,8 @@ char** ADRGDataset::GetGENListFromTHF(const char* pszFileName)
 
         if (record->GetFieldCount() >= 2)
         {
-            field = record->GetField(0);
-            fieldDefn = field->GetFieldDefn();
+            DDFField *field = record->GetField(0);
+            DDFFieldDefn *fieldDefn = field->GetFieldDefn();
             if (!(strcmp(fieldDefn->GetName(), "001") == 0 &&
                 fieldDefn->GetSubfieldCount() == 2))
             {
@@ -1237,19 +1248,19 @@ char** ADRGDataset::GetGENListFromTHF(const char* pszFileName)
             {
                 continue;
             }
-            
+
             int iVFFFieldInstance = 0;
-            for (i = 1; i < record->GetFieldCount() ; i++)
+            for (int i = 1; i < record->GetFieldCount() ; i++)
             {
                 field = record->GetField(i);
                 fieldDefn = field->GetFieldDefn();
-                
+
                 if (!(strcmp(fieldDefn->GetName(), "VFF") == 0 &&
                       fieldDefn->GetSubfieldCount() == 1))
                 {
                     continue;
                 }
-            
+
                 const char* pszVFF = record->GetStringSubfield("VFF", iVFFFieldInstance++, "VFF", 0);
                 if( pszVFF == NULL )
                     continue;
@@ -1311,8 +1322,6 @@ char** ADRGDataset::GetIMGListFromGEN(const char* pszFileName,
                                       int *pnRecordIndex)
 {
     DDFRecord * record;
-    DDFField* field;
-    DDFFieldDefn *fieldDefn;
     int nFilenames = 0;
     char** papszFileNames = NULL;
     int nRecordIndex = -1;
@@ -1322,12 +1331,12 @@ char** ADRGDataset::GetIMGListFromGEN(const char* pszFileName,
 
     DDFModule module;
     if (!module.Open(pszFileName, TRUE))
-        return NULL;    
+        return NULL;
 
-    while (TRUE)
+    while (true)
     {
         nRecordIndex ++;
-        
+
         CPLPushErrorHandler( CPLQuietErrorHandler );
         record = module.ReadRecord();
         CPLPopErrorHandler();
@@ -1337,8 +1346,8 @@ char** ADRGDataset::GetIMGListFromGEN(const char* pszFileName,
 
         if (record->GetFieldCount() >= 5)
         {
-            field = record->GetField(0);
-            fieldDefn = field->GetFieldDefn();
+            DDFField *field = record->GetField(0);
+            DDFFieldDefn *fieldDefn = field->GetFieldDefn();
             if (!(strcmp(fieldDefn->GetName(), "001") == 0 &&
                 fieldDefn->GetSubfieldCount() == 2))
             {
@@ -1351,7 +1360,8 @@ char** ADRGDataset::GetIMGListFromGEN(const char* pszFileName,
             /* Ignore overviews */
             if ( strcmp(RTY, "OVV") == 0 )
                 continue;
-            
+
+            // TODO: Fix the non-GIN section or remove it.
             if ( strcmp(RTY, "GIN") != 0 )
                 continue;
 
@@ -1359,13 +1369,13 @@ char** ADRGDataset::GetIMGListFromGEN(const char* pszFileName,
             if( field == NULL )
                 continue;
             fieldDefn = field->GetFieldDefn();
-            
+
             if (!(strcmp(fieldDefn->GetName(), "SPR") == 0 &&
                     fieldDefn->GetSubfieldCount() == 15))
             {
                 continue;
             }
-                        
+
             const char* pszBAD = record->GetStringSubfield("SPR", 0, "BAD", 0);
             if( pszBAD == NULL || strlen(pszBAD) != 12 )
                 continue;
@@ -1376,10 +1386,10 @@ char** ADRGDataset::GetIMGListFromGEN(const char* pszFileName,
                     *c = 0;
             }
             CPLDebug("ADRG", "BAD=%s", osBAD.c_str());
-            
+
             /* Build full IMG file name from BAD value */
             CPLString osGENDir(CPLGetDirname(pszFileName));
-            
+
             CPLString osFileName = CPLFormFilename(osGENDir.c_str(), osBAD.c_str(), NULL);
             VSIStatBufL sStatBuf;
             if( VSIStatL( osFileName, &sStatBuf ) == 0 )
@@ -1410,17 +1420,17 @@ char** ADRGDataset::GetIMGListFromGEN(const char* pszFileName,
                 }
                 CSLDestroy(papszDirContent);
             }
-            
+
             if (nFilenames == 0 && pnRecordIndex)
                 *pnRecordIndex = nRecordIndex;
-            
+
             papszFileNames = (char**)CPLRealloc(papszFileNames, sizeof(char*) * (nFilenames + 2));
             papszFileNames[nFilenames] = CPLStrdup(osBAD.c_str());
             papszFileNames[nFilenames + 1] = NULL;
             nFilenames ++;
         }
     }
-    
+
     return papszFileNames;
 }
 
@@ -1433,16 +1443,16 @@ GDALDataset *ADRGDataset::Open( GDALOpenInfo * poOpenInfo )
     int nRecordIndex = -1;
     CPLString osGENFileName;
     CPLString osIMGFileName;
-    int bFromSubdataset = FALSE;
-    
-    if( EQUALN(poOpenInfo->pszFilename, "ADRG:", 5) )
+    bool bFromSubdataset = false;
+
+    if( STARTS_WITH_CI(poOpenInfo->pszFilename, "ADRG:") )
     {
         char** papszTokens = CSLTokenizeString2(poOpenInfo->pszFilename + 5, ",", 0);
         if (CSLCount(papszTokens) == 2)
         {
             osGENFileName = papszTokens[0];
             osIMGFileName = papszTokens[1];
-            bFromSubdataset = TRUE;
+            bFromSubdataset = true;
         }
         CSLDestroy(papszTokens);
     }
@@ -1476,18 +1486,18 @@ GDALDataset *ADRGDataset::Open( GDALOpenInfo * poOpenInfo )
                         papszIMGIter ++;
                     }
                     CSLDestroy(papszIMGFileNames);
-                    
+
                     ptr ++;
                 }
                 CSLDestroy(papszFileNames);
                 return poDS;
             }
         }
-        
+
         if (EQUAL(CPLGetExtension(osFileName.c_str()), "GEN"))
         {
             osGENFileName = osFileName;
-                
+
             char** papszFileNames = GetIMGListFromGEN(osFileName.c_str(), &nRecordIndex);
             if (papszFileNames == NULL)
                 return NULL;
@@ -1510,25 +1520,24 @@ GDALDataset *ADRGDataset::Open( GDALOpenInfo * poOpenInfo )
             }
         }
     }
-    
+
     if (osGENFileName.size() > 0 &&
         osIMGFileName.size() > 0)
     {
         if( poOpenInfo->eAccess == GA_Update )
         {
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                       "The ADRG driver does not support update access to existing"
                       " datasets.\n" );
             return NULL;
         }
-        
+
         DDFModule module;
         DDFRecord* record = NULL;
         if (nRecordIndex >= 0 &&
             module.Open(osGENFileName.c_str(), TRUE))
         {
-            int i;
-            for(i=0;i<=nRecordIndex;i++)
+            for(int i=0;i<=nRecordIndex;i++)
             {
                 CPLPushErrorHandler( CPLQuietErrorHandler );
                 record = module.ReadRecord();
@@ -1538,7 +1547,7 @@ GDALDataset *ADRGDataset::Open( GDALOpenInfo * poOpenInfo )
                   break;
             }
         }
-        
+
         ADRGDataset* poDS = OpenDataset(osGENFileName.c_str(), osIMGFileName.c_str(), record);
 
         if (poDS)
@@ -1560,7 +1569,7 @@ GDALDataset *ADRGDataset::Open( GDALOpenInfo * poOpenInfo )
             return poDS;
         }
     }
-    
+
     return NULL;
 }
 
@@ -1575,8 +1584,6 @@ GDALDataset *ADRGDataset::Create(const char* pszFilename,
                                  GDALDataType eType,
                                  CPL_UNUSED char **papszOptions)
 {
-    int i;
-
     if( eType != GDT_Byte)
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -1601,7 +1608,7 @@ GDALDataset *ADRGDataset::Create(const char* pszFilename,
                 "Specified pixel dimensions (% d x %d) are bad.\n",
                 nXSize, nYSize );
     }
-    
+
     if (!EQUAL(CPLGetExtension(pszFilename), "gen"))
     {
         CPLError( CE_Failure, CPLE_NotSupported,
@@ -1616,8 +1623,8 @@ GDALDataset *ADRGDataset::Create(const char* pszFilename,
                 "Invalid filename. Must be xxxxxx01.GEN where x is between A and Z\n");
         return NULL;
     }
-    
-    for(i=0;i<6;i++)
+
+    for(int i=0;i<6;i++)
     {
         if (!(osBaseFileName[i] >= 'A' && osBaseFileName[i] <= 'Z'))
         {
@@ -1634,7 +1641,7 @@ GDALDataset *ADRGDataset::Create(const char* pszFilename,
                 "Cannot create GEN file : %s.\n", pszFilename);
         return NULL;
     }
-    
+
     CPLString osDirname(CPLGetDirname(pszFilename));
     CPLString osTransh01THF(CPLFormFilename(osDirname.c_str(), "TRANSH01.THF", NULL));
     VSILFILE* fdTHF = VSIFOpenL(osTransh01THF.c_str(), "wb");
@@ -1645,7 +1652,7 @@ GDALDataset *ADRGDataset::Create(const char* pszFilename,
                 "Cannot create THF file : %s.\n", osTransh01THF.c_str());
         return NULL;
     }
-    
+
     CPLString osImgFilename = CPLResetExtension(pszFilename, "IMG");
     VSILFILE* fdIMG = VSIFOpenL(osImgFilename.c_str(), "w+b");
     if (fdIMG == NULL)
@@ -1656,7 +1663,7 @@ GDALDataset *ADRGDataset::Create(const char* pszFilename,
                 "Cannot create image file : %s.\n", osImgFilename.c_str());
         return NULL;
     }
-    
+
     ADRGDataset* poDS = new ADRGDataset();
 
     poDS->eAccess = GA_Update;
@@ -1679,7 +1686,7 @@ GDALDataset *ADRGDataset::Create(const char* pszFilename,
     poDS->poOverviewDS = NULL;
 
     poDS->nBands = 3;
-    for( i = 0; i < poDS->nBands; i++ )
+    for( int i = 0; i < poDS->nBands; i++ )
         poDS->SetBand( i+1, new ADRGRasterBand( poDS, i+1 ) );
 
     return poDS;
@@ -1721,7 +1728,7 @@ static void WriteGENFile_Header(VSILFILE* fd)
     sizeOfFields[nFields++] += WriteFieldDecl(fd, '2', '1', "TILE_INDEX_MAP_FIELD", /* TIM */
                                                 "*TSI",
                                                 "(I(5))");
-    
+
     FinishWriteHeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
 }
 
@@ -1766,7 +1773,7 @@ static void WriteGENFile_OverviewRecord(VSILFILE* fd, CPLString& osBaseFileName,
     int sizeOfFields[] = {0, 0, 0, 0, 0, 0};
     const char* nameOfFields[] = { "001", "DSI", "OVI", "SPR", "BDF", "TIM" };
     int pos = BeginLeader(fd, 9, 9, 3, N_ELEMENTS(sizeOfFields));
-    
+
     /* Field 001 */
     sizeOfFields[nFields] += WriteSubFieldStr(fd, "OVV", 3); /* RTY */
     sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
@@ -1778,7 +1785,7 @@ static void WriteGENFile_OverviewRecord(VSILFILE* fd, CPLString& osBaseFileName,
     sizeOfFields[nFields] += WriteSubFieldStr(fd, osBaseFileName, 8); /* NAM */
     sizeOfFields[nFields] += WriteFieldTerminator(fd);
     nFields++;
-    
+
     /* Field OVI */
     sizeOfFields[nFields] += WriteSubFieldInt(fd, 3, 1); /* STR */
     sizeOfFields[nFields] += WriteSubFieldInt(fd, ARV, 8); /* ARV */   /* FIXME */
@@ -1787,7 +1794,7 @@ static void WriteGENFile_OverviewRecord(VSILFILE* fd, CPLString& osBaseFileName,
     sizeOfFields[nFields] += WriteLatitude(fd, PSO); /* PSO */    /* FIXME */
     sizeOfFields[nFields] += WriteFieldTerminator(fd);
     nFields++;
-    
+
     /* Field SPR */
     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NUL */
     sizeOfFields[nFields] += WriteSubFieldInt(fd, nOvSizeX-1, 6); /* NUS */
@@ -1803,12 +1810,12 @@ static void WriteGENFile_OverviewRecord(VSILFILE* fd, CPLString& osBaseFileName,
     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* PCB */
     sizeOfFields[nFields] += WriteSubFieldInt(fd, 8, 1); /* PVB */
     char tmp[12+1];
-    sprintf(tmp, "%s.IMG", osBaseFileName.c_str()); /* FIXME */
+    snprintf(tmp, sizeof(tmp), "%s.IMG", osBaseFileName.c_str()); /* FIXME */
     sizeOfFields[nFields] += WriteSubFieldStr(fd, tmp, 12); /* BAD */
     sizeOfFields[nFields] += WriteSubFieldStr(fd, "Y", 1); /* TIF */
     sizeOfFields[nFields] += WriteFieldTerminator(fd);
     nFields++;
-    
+
     /* Field BDF */
     sizeOfFields[nFields] += WriteSubFieldStr(fd, "Red", 5); /* BID */
     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
@@ -1821,16 +1828,15 @@ static void WriteGENFile_OverviewRecord(VSILFILE* fd, CPLString& osBaseFileName,
     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
     sizeOfFields[nFields] += WriteFieldTerminator(fd);
     nFields++;
-    
+
     /* Field TIM */
-    int i;
-    for(i=0;i<NFL*NFC;i++)
+    for(int i=0;i<NFL*NFC;i++)
     {
         sizeOfFields[nFields] += WriteSubFieldInt(fd, TILEINDEX[i], 5); /* TSI */
     }
     sizeOfFields[nFields] += WriteFieldTerminator(fd);
     nFields++;
-    
+
     FinishWriteLeader(fd, pos, 9, 9, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
 }
 
@@ -1850,7 +1856,7 @@ static void WriteGENFile_GeneralInformationRecord(VSILFILE* fd, CPLString& osNAM
     int sizeOfFields[] = {0, 0, 0, 0, 0, 0};
     const char* nameOfFields[] = { "001", "DSI", "GEN", "SPR", "BDF", "TIM" };
     int pos = BeginLeader(fd, 9, 9, 3, N_ELEMENTS(sizeOfFields));
-    
+
     /* Field 001 */
     sizeOfFields[nFields] += WriteSubFieldStr(fd, "GIN", 3); /* RTY */
     sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
@@ -1862,7 +1868,7 @@ static void WriteGENFile_GeneralInformationRecord(VSILFILE* fd, CPLString& osNAM
     sizeOfFields[nFields] += WriteSubFieldStr(fd, osNAM.c_str(), 8); /* NAM */
     sizeOfFields[nFields] += WriteFieldTerminator(fd);
     nFields++;
-    
+
     /* Field `GEN */
     sizeOfFields[nFields] += WriteSubFieldInt(fd, 3, 1); /* STR */
     sizeOfFields[nFields] += WriteSubFieldStr(fd, "0099.9", 6); /* LOD */   /* FIXME */
@@ -1906,7 +1912,7 @@ static void WriteGENFile_GeneralInformationRecord(VSILFILE* fd, CPLString& osNAM
     sizeOfFields[nFields] += WriteSubFieldStr(fd, "Y", 1); /* TIF */
     sizeOfFields[nFields] += WriteFieldTerminator(fd);
     nFields++;
-    
+
     /* Field BDF */
     sizeOfFields[nFields] += WriteSubFieldStr(fd, "Red", 5); /* BID */
     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
@@ -1919,10 +1925,9 @@ static void WriteGENFile_GeneralInformationRecord(VSILFILE* fd, CPLString& osNAM
     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
     sizeOfFields[nFields] += WriteFieldTerminator(fd);
     nFields++;
-    
+
     /* Field TIM */
-    int i;
-    for(i=0;i<NFL*NFC;i++)
+    for(int i=0;i<NFL*NFC;i++)
     {
         sizeOfFields[nFields] += WriteSubFieldInt(fd, TILEINDEX[i], 5); /* TSI */
     }
@@ -1951,10 +1956,10 @@ void ADRGDataset::WriteGENFile()
     PSO = adfGeoTransform[3];
     ARV = (int)floor(360. / adfGeoTransform[1] + .5);
     BRV = (int)floor(-360. / adfGeoTransform[5] + .5);
-    
+
     /*ARV = ((ARV + 255) / 512) * 512;
     BRV = ((BRV + 255) / 512) * 512;*/
-    
+
     int SCA = (int)floor(1000000. * 400384 / BRV + 0.5);
 
     int nOvSizeX = nRasterXSize; // FIXME
@@ -1973,18 +1978,18 @@ void ADRGDataset::WriteGENFile()
     /* Write GENERAL_INFORMATION_RECORD */
     CPLString osNAM = osBaseFileName;
     char tmp[12+1];
-    sprintf(tmp, "%s.IMG", osNAM.c_str());
+    snprintf(tmp, sizeof(tmp), "%s.IMG", osNAM.c_str());
     CPLString osBAD = tmp;
     WriteGENFile_GeneralInformationRecord(fdGEN, osNAM, osBAD, ARV, BRV, LSO, PSO,
                                           adfGeoTransform, SCA, nRasterXSize, nRasterYSize, NFL, NFC, TILEINDEX);
-                                          
-    if (CSLTestBoolean(CPLGetConfigOption("ADRG_SIMULATE_MULTI_IMG", "OFF")))
+
+    if (CPLTestBool(CPLGetConfigOption("ADRG_SIMULATE_MULTI_IMG", "OFF")))
     {
         strncpy(tmp, osBaseFileName.c_str(), 6);
         tmp[6] = '\0';
         strcat(tmp, "02");
         osNAM = tmp;
-        sprintf(tmp, "%s.IMG", osNAM.c_str());
+        snprintf(tmp, sizeof(tmp), "%s.IMG", osNAM.c_str());
         osBAD = tmp;
         WriteGENFile_GeneralInformationRecord(fdGEN, osNAM, osBAD, ARV, BRV, LSO, PSO,
                                               adfGeoTransform, SCA, nRasterXSize, nRasterYSize, NFL, NFC, TILEINDEX);
@@ -2186,10 +2191,10 @@ void ADRGDataset::WriteTHFFile()
 
         int nFields = 0;
         int sizeOfFields[] = {0, 0, 0, 0, 0, 0, 0};
-        
+
         /* Debug option to simulate ADRG datasets made of several images */
-        int nTotalFields = (CSLTestBoolean(CPLGetConfigOption("ADRG_SIMULATE_MULTI_IMG", "OFF"))) ? 6 : 5;
-        
+        int nTotalFields = (CPLTestBool(CPLGetConfigOption("ADRG_SIMULATE_MULTI_IMG", "OFF"))) ? 6 : 5;
+
         const char* nameOfFields[] = { "001", "VFF", "VFF", "VFF", "VFF", "VFF", "VFF" };
         int pos = BeginLeader(fd, 9, 9, 3, nTotalFields);
 
@@ -2210,17 +2215,17 @@ void ADRGDataset::WriteTHFFile()
         nFields++;
 
         /* Field VFF */
-        sprintf(tmp, "%s.GEN", osBaseFileName.c_str());
+        snprintf(tmp, sizeof(tmp), "%s.GEN", osBaseFileName.c_str());
         sizeOfFields[nFields] += WriteSubFieldStr(fd, tmp, 51); /* VFF */
         sizeOfFields[nFields] += WriteFieldTerminator(fd);
         nFields++;
 
         /* Field VFF */
-        sprintf(tmp, "%s.IMG", osBaseFileName.c_str());
+        snprintf(tmp, sizeof(tmp), "%s.IMG", osBaseFileName.c_str());
         sizeOfFields[nFields] += WriteSubFieldStr(fd, tmp, 51); /* VFF */
         sizeOfFields[nFields] += WriteFieldTerminator(fd);
         nFields++;
-        
+
         if (nTotalFields == 6)
         {
             /* Field VFF */
@@ -2231,7 +2236,7 @@ void ADRGDataset::WriteTHFFile()
             sizeOfFields[nFields] += WriteFieldTerminator(fd);
             nFields++;
         }
-        
+
         FinishWriteLeader(fd, pos, 9, 9, 3, nTotalFields, sizeOfFields, nameOfFields);
     }
 }
@@ -2243,27 +2248,25 @@ void ADRGDataset::WriteTHFFile()
 void GDALRegister_ADRG()
 
 {
-    GDALDriver  *poDriver;
-
-    if( GDALGetDriverByName( "ADRG" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "ADRG" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "ARC Digitized Raster Graphics" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#ADRG" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gen" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte" );
-        poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = ADRGDataset::Open;
-        poDriver->pfnCreate = ADRGDataset::Create;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    if( GDALGetDriverByName( "ADRG" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "ADRG" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "ARC Digitized Raster Graphics" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_various.html#ADRG" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gen" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte" );
+    poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = ADRGDataset::Open;
+    poDriver->pfnCreate = ADRGDataset::Create;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/adrg/srpdataset.cpp b/frmts/adrg/srpdataset.cpp
index cb6c48f..1a02f3e 100644
--- a/frmts/adrg/srpdataset.cpp
+++ b/frmts/adrg/srpdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: srpdataset.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: srpdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  * Purpose:  ASRP/USRP Reader
  * Author:   Frank Warmerdam (warmerdam at pobox.com)
  *
@@ -28,15 +28,17 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
-#include "ogr_spatialref.h"
 #include "cpl_string.h"
+#include "gdal_pam.h"
+#include "gdal_frmts.h"
 #include "iso8211.h"
+#include "ogr_spatialref.h"
+#include <algorithm>
 
 // Uncomment to recognize also .gen files in addition to .img files
 // #define OPEN_GEN
 
-CPL_CVSID("$Id: srpdataset.cpp 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: srpdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 class SRPDataset : public GDALPamDataset
 {
@@ -79,7 +81,7 @@ class SRPDataset : public GDALPamDataset
 public:
     SRPDataset();
     virtual     ~SRPDataset();
-    
+
     virtual const char *GetProjectionRef(void);
     virtual CPLErr GetGeoTransform( double * padfGeoTransform );
 
@@ -87,7 +89,7 @@ public:
 
     virtual char **GetFileList();
 
-    int                 GetFromRecord( const char* pszFileName, 
+    int                 GetFromRecord( const char* pszFileName,
                                        DDFRecord * record);
     void                AddSubDataset( const char* pszGENFileName, const char* pszIMGFileName );
     void  AddMetadatafromFromTHF(const char* pszFileName);
@@ -121,12 +123,12 @@ class SRPRasterBand : public GDALPamRasterBand
 /*                           SRPRasterBand()                            */
 /************************************************************************/
 
-SRPRasterBand::SRPRasterBand( SRPDataset *poDS, int nBand )
+SRPRasterBand::SRPRasterBand( SRPDataset *poDSIn, int nBandIn )
 
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
-    
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
+
     eDataType = GDT_Byte;
 
     nBlockXSize = 128;
@@ -152,9 +154,9 @@ double  SRPRasterBand::GetNoDataValue( int *pbSuccess )
 GDALColorInterp SRPRasterBand::GetColorInterpretation()
 
 {
-    SRPDataset* poDS = (SRPDataset*)this->poDS;
+    SRPDataset* l_poDS = (SRPDataset*)this->poDS;
 
-    if( poDS->oCT.GetColorEntryCount() > 0 )
+    if( l_poDS->oCT.GetColorEntryCount() > 0 )
         return GCI_PaletteIndex;
     else
         return GCI_GrayIndex;
@@ -167,10 +169,10 @@ GDALColorInterp SRPRasterBand::GetColorInterpretation()
 GDALColorTable *SRPRasterBand::GetColorTable()
 
 {
-    SRPDataset* poDS = (SRPDataset*)this->poDS;
+    SRPDataset* l_poDS = (SRPDataset*)this->poDS;
 
-    if( poDS->oCT.GetColorEntryCount() > 0 )
-        return &(poDS->oCT);
+    if( l_poDS->oCT.GetColorEntryCount() > 0 )
+        return &(l_poDS->oCT);
     else
         return NULL;
 }
@@ -183,20 +185,20 @@ CPLErr SRPRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                    void * pImage )
 
 {
-    SRPDataset* poDS = (SRPDataset*)this->poDS;
+    SRPDataset* l_poDS = (SRPDataset*)this->poDS;
     int offset;
-    int nBlock = nBlockYOff * poDS->NFC + nBlockXOff;
-    if (nBlockXOff >= poDS->NFC || nBlockYOff >= poDS->NFL)
+    int nBlock = nBlockYOff * l_poDS->NFC + nBlockXOff;
+    if (nBlockXOff >= l_poDS->NFC || nBlockYOff >= l_poDS->NFL)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "nBlockXOff=%d, NFC=%d, nBlockYOff=%d, NFL=%d",
-                 nBlockXOff, poDS->NFC, nBlockYOff, poDS->NFL);
+                 nBlockXOff, l_poDS->NFC, nBlockYOff, l_poDS->NFL);
         return CE_Failure;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Is this a null block?                                           */
 /* -------------------------------------------------------------------- */
-    if (poDS->TILEINDEX && poDS->TILEINDEX[nBlock] == 0)
+    if (l_poDS->TILEINDEX && l_poDS->TILEINDEX[nBlock] == 0)
     {
         memset(pImage, 0, 128 * 128);
         return CE_None;
@@ -205,20 +207,20 @@ CPLErr SRPRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
 /*      Compute the offset to the block.                                */
 /* -------------------------------------------------------------------- */
-    if (poDS->TILEINDEX)
+    if (l_poDS->TILEINDEX)
     {
-        if( poDS->PCB == 0 ) // uncompressed 
-            offset = poDS->offsetInIMG + (poDS->TILEINDEX[nBlock] - 1) * 128 * 128;
-        else // compressed 
-            offset = poDS->offsetInIMG + (poDS->TILEINDEX[nBlock] - 1);
+        if( l_poDS->PCB == 0 ) // uncompressed
+            offset = l_poDS->offsetInIMG + (l_poDS->TILEINDEX[nBlock] - 1) * 128 * 128;
+        else // compressed
+            offset = l_poDS->offsetInIMG + (l_poDS->TILEINDEX[nBlock] - 1);
     }
     else
-        offset = poDS->offsetInIMG + nBlock * 128 * 128;
-    
+        offset = l_poDS->offsetInIMG + nBlock * 128 * 128;
+
 /* -------------------------------------------------------------------- */
 /*      Seek to target location.                                        */
 /* -------------------------------------------------------------------- */
-    if (VSIFSeekL(poDS->fdIMG, offset, SEEK_SET) != 0)
+    if (VSIFSeekL(l_poDS->fdIMG, offset, SEEK_SET) != 0)
     {
         CPLError(CE_Failure, CPLE_FileIO, "Cannot seek to offset %d", offset);
         return CE_Failure;
@@ -228,11 +230,11 @@ CPLErr SRPRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /*      For uncompressed case we read the 128x128 and return with no    */
 /*      further processing.                                             */
 /* -------------------------------------------------------------------- */
-    if( poDS->PCB == 0 )
+    if( l_poDS->PCB == 0 )
     {
-        if( VSIFReadL(pImage, 1, 128 * 128, poDS->fdIMG) != 128*128 )
+        if( VSIFReadL(pImage, 1, 128 * 128, l_poDS->fdIMG) != 128*128 )
         {
-            CPLError(CE_Failure, CPLE_FileIO, 
+            CPLError(CE_Failure, CPLE_FileIO,
                      "Cannot read data at offset %d", offset);
             return CE_Failure;
         }
@@ -242,29 +244,29 @@ CPLErr SRPRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /*      If this is compressed data, we read a goodly chunk of data      */
 /*      and then decode it.                                             */
 /* -------------------------------------------------------------------- */
-    else if( poDS->PCB != 0 )
+    else if( l_poDS->PCB != 0 )
     {
         int    nBufSize = 128*128*2;
         int    nBytesRead, iPixel, iSrc, bHalfByteUsed = FALSE;
         GByte *pabyCData = (GByte *) CPLCalloc(nBufSize,1);
 
-        nBytesRead = VSIFReadL(pabyCData, 1, nBufSize, poDS->fdIMG);
+        nBytesRead = static_cast<int>(VSIFReadL(pabyCData, 1, nBufSize, l_poDS->fdIMG));
         if( nBytesRead == 0 )
         {
-            CPLError(CE_Failure, CPLE_FileIO, 
+            CPLError(CE_Failure, CPLE_FileIO,
                      "Cannot read data at offset %d", offset);
             return CE_Failure;
         }
-        
-        CPLAssert( poDS->PVB == 8 );
-        CPLAssert( poDS->PCB == 4 || poDS->PCB == 8 );
+
+        CPLAssert( l_poDS->PVB == 8 );
+        CPLAssert( l_poDS->PCB == 4 || l_poDS->PCB == 8 );
 
         for( iSrc = 0, iPixel = 0; iPixel < 128 * 128; )
         {
             if( iSrc + 2 > nBytesRead )
             {
                 CPLFree( pabyCData );
-                CPLError(CE_Failure, CPLE_AppDefined, 
+                CPLError(CE_Failure, CPLE_AppDefined,
                          "Out of data decoding image block, only %d available.",
                          iSrc );
                 return CE_Failure;
@@ -273,12 +275,12 @@ CPLErr SRPRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             int nCount = 0;
             int nValue = 0;
 
-            if( poDS->PCB == 8 )
+            if( l_poDS->PCB == 8 )
             {
                 nCount = pabyCData[iSrc++];
                 nValue = pabyCData[iSrc++];
             }
-            else if( poDS->PCB == 4 )
+            else if( l_poDS->PCB == 4 )
             {
                 if( (iPixel % 128) == 0 && bHalfByteUsed )
                 {
@@ -305,7 +307,7 @@ CPLErr SRPRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             if( iPixel + nCount > 128 * 128 )
             {
                 CPLFree( pabyCData );
-                CPLError(CE_Failure, CPLE_AppDefined, 
+                CPLError(CE_Failure, CPLE_AppDefined,
                       "Too much data decoding image block, likely corrupt." );
                 return CE_Failure;
             }
@@ -319,7 +321,7 @@ CPLErr SRPRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
         CPLFree( pabyCData );
     }
-    
+
     return CE_None;
 }
 
@@ -327,7 +329,9 @@ CPLErr SRPRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /*                          SRPDataset()                               */
 /************************************************************************/
 
-SRPDataset::SRPDataset()
+SRPDataset::SRPDataset() :
+    NFC(0), NFL(0), ZNA(0), LSO(0.0), PSO(0.0), LOD(0.0), LAD(0.0), ARV(0),
+    BRV(0), PCB(0), PVB(0)
 {
     fdIMG = NULL;
     TILEINDEX = NULL;
@@ -348,7 +352,7 @@ SRPDataset::~SRPDataset()
     {
         VSIFCloseL(fdIMG);
     }
-    
+
     if (TILEINDEX)
     {
         delete [] TILEINDEX;
@@ -447,16 +451,16 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
         CPLDebug( "SRP", "Failed to extract STR, or not 4." );
         return FALSE;
     }
-        
+
     int SCA = record->GetIntSubfield( "GEN", 0, "SCA", 0, &bSuccess );
     CPLDebug("SRP", "SCA=%d", SCA);
-        
+
     ZNA = record->GetIntSubfield( "GEN", 0, "ZNA", 0, &bSuccess );
     CPLDebug("SRP", "ZNA=%d", ZNA);
-        
+
     double PSP = record->GetFloatSubfield( "GEN", 0, "PSP", 0, &bSuccess );
     CPLDebug("SRP", "PSP=%f", PSP);
-        
+
     ARV = record->GetIntSubfield( "GEN", 0, "ARV", 0, &bSuccess );
     CPLDebug("SRP", "ARV=%d", ARV);
 
@@ -478,6 +482,15 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
     NFC = record->GetIntSubfield( "SPR", 0, "NFC", 0, &bSuccess );
     CPLDebug("SRP", "NFC=%d", NFC);
 
+    if( NFL <= 0 || NFC <= 0 ||
+        NFL > INT_MAX / 128 ||
+        NFC > INT_MAX / 128 ||
+        NFL > INT_MAX / NFC )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,"Invalid NFL / NFC values");
+        return FALSE;
+    }
+
     int PNC = record->GetIntSubfield( "SPR", 0, "PNC", 0, &bSuccess );
     CPLDebug("SRP", "PNC=%d", PNC);
 
@@ -509,14 +522,14 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
             *c = 0;
     }
     CPLDebug("SRP", "BAD=%s", osBAD.c_str());
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read the tile map if available.                                 */
 /* -------------------------------------------------------------------- */
     const char* pszTIF = record->GetStringSubfield( "SPR", 0, "TIF", 0 );
     int TIF = pszTIF != NULL && EQUAL(pszTIF,"Y");
     CPLDebug("SRP", "TIF=%d", TIF);
-    
+
     if (TIF)
     {
         field = record->FindField( "TIM" );
@@ -532,12 +545,20 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
 
         /* Should be strict comparison, but apparently a few datasets */
         /* have GetDataSize() greater than the required minimum (#3862) */
-        if (field->GetDataSize() < nIndexValueWidth * NFL * NFC + 1)
+        if (nIndexValueWidth > (INT_MAX - 1) / (NFL * NFC) ||
+            field->GetDataSize() < nIndexValueWidth * NFL * NFC + 1)
+        {
+            return FALSE;
+        }
+
+        try
+        {
+            TILEINDEX = new int [NFL * NFC];
+        }
+        catch( const std::bad_alloc& )
         {
             return FALSE;
         }
-    
-        TILEINDEX = new int [NFL * NFC];
         const char* ptr = field->GetData();
         char offset[30]={0};
         offset[nIndexValueWidth] = '\0';
@@ -550,7 +571,7 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
             //CPLDebug("SRP", "TSI[%d]=%d", i, TILEINDEX[i]);
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Open the .IMG file.  Try to recover gracefully if the case      */
 /*      of the filename is wrong.                                       */
@@ -564,7 +585,7 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
         CPLError( CE_Failure, CPLE_AppDefined, "Cannot find %s", osImgName.c_str());
         return FALSE;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Establish the offset to the first byte of actual image data     */
 /*      in the IMG file, skipping the ISO8211 header.                   */
@@ -586,7 +607,7 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
                 return FALSE;
             }
             offsetInIMG += 3;
-            if (strncmp(recordName,"IMG",3) == 0)
+            if (STARTS_WITH(recordName, "IMG"))
             {
                 offsetInIMG += 4;
                 if (VSIFSeekL(fdIMG,3,SEEK_CUR) != 0)
@@ -616,24 +637,24 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
             return FALSE;
         }
     }
-    
+
     if (VSIFEofL(fdIMG))
     {
         return FALSE;
     }
-    
+
     CPLDebug("SRP", "Img offset data = %d", offsetInIMG);
-    
+
 /* -------------------------------------------------------------------- */
 /*      Establish the SRP Dataset.                                     */
 /* -------------------------------------------------------------------- */
     nRasterXSize = NFC * 128;
     nRasterYSize = NFL * 128;
-    
-    char pszValue[32];
-    sprintf(pszValue, "%d", SCA);
-    SetMetadataItem( "SRP_SCA", pszValue );
-    
+
+    char szValue[32];
+    snprintf(szValue, sizeof(szValue), "%d", SCA);
+    SetMetadataItem( "SRP_SCA", szValue );
+
     nBands = 1;
     for( i = 0; i < nBands; i++ )
         SetBand( i+1, new SRPRasterBand( this, i+1 ) );
@@ -650,21 +671,20 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
     {
         while( (record = oQALModule.ReadRecord()) != NULL)
         {
-            if( record->FindField( "COL" ) != NULL ) 
+            if( record->FindField( "COL" ) != NULL )
             {
                 int            iColor;
-                int            nColorCount = 
-                    record->FindField("COL")->GetRepeatCount();
+                int            nColorCount = std::min(256,
+                    record->FindField("COL")->GetRepeatCount());
 
                 for( iColor = 0; iColor < nColorCount; iColor++ )
                 {
-                    int bSuccess;
                     int nCCD, nNSR, nNSG, nNSB;
                     GDALColorEntry sEntry;
 
                     nCCD = record->GetIntSubfield( "COL", 0, "CCD", iColor,
                         &bSuccess );
-                    if( !bSuccess )
+                    if( !bSuccess || nCCD < 0 || nCCD > 255 )
                         break;
 
                     nNSR = record->GetIntSubfield( "COL", 0, "NSR", iColor );
@@ -682,6 +702,8 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
 
             if (record->FindField( "QUV" ) != NULL )
             {
+                // TODO: Translate to English or state why this should not be in
+                // English.
                 //Date de production du produit : QAL.QUV.DAT1
                 //Num�ro d'�dition  du produit : QAL.QUV.EDN
 
@@ -689,9 +711,8 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
                 if (bSuccess)
                 {
                     CPLDebug("SRP", "EDN=%d", EDN);
-                    char pszValue[5];
-                    sprintf(pszValue, "%d", EDN);
-                    SetMetadataItem( "SRP_EDN", pszValue );
+                    snprintf(szValue, sizeof(szValue), "%d", EDN);
+                    SetMetadataItem( "SRP_EDN", szValue );
                 }
 
 
@@ -768,11 +789,11 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
         }
         else if( ZNA == 61 )
         {
-            oSRS.importFromEPSG( 32661 ); // WGS84 UPS North 
+            oSRS.importFromEPSG( 32661 ); // WGS84 UPS North
         }
         else if( ZNA == -61 )
         {
-            oSRS.importFromEPSG( 32761 ); // WGS84 UPS South 
+            oSRS.importFromEPSG( 32761 ); // WGS84 UPS South
         }
 
         char *pszWKT = NULL;
@@ -781,8 +802,8 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
         CPLFree( pszWKT );
     }
 
-    sprintf(pszValue, "%d", ZNA);
-    SetMetadataItem( "SRP_ZNA", pszValue );
+    snprintf(szValue, sizeof(szValue), "%d", ZNA);
+    SetMetadataItem( "SRP_ZNA", szValue );
 
     return TRUE;
 }
@@ -836,12 +857,12 @@ void SRPDataset::AddSubDataset( const char* pszGENFileName, const char* pszIMGFi
     osSubDatasetName += ",";
     osSubDatasetName += pszIMGFileName;
 
-    sprintf( szName, "SUBDATASET_%d_NAME", nCount+1 );
-    papszSubDatasets = 
+    snprintf(szName, sizeof(szName), "SUBDATASET_%d_NAME", nCount+1 );
+    papszSubDatasets =
         CSLSetNameValue( papszSubDatasets, szName, osSubDatasetName);
 
-    sprintf( szName, "SUBDATASET_%d_DESC", nCount+1 );
-    papszSubDatasets = 
+    snprintf(szName, sizeof(szName), "SUBDATASET_%d_DESC", nCount+1 );
+    papszSubDatasets =
         CSLSetNameValue( papszSubDatasets, szName, osSubDatasetName);
 }
 
@@ -877,7 +898,7 @@ DDFRecord* SRPDataset::FindRecordInGENForIMG(DDFModule& module,
     DDFFieldDefn *fieldDefn;
 
     /* Now finds the record */
-    while (TRUE)
+    while( true )
     {
         CPLPushErrorHandler( CPLQuietErrorHandler );
         DDFRecord* record = module.ReadRecord();
@@ -939,7 +960,7 @@ DDFRecord* SRPDataset::FindRecordInGENForIMG(DDFModule& module,
 SRPDataset* SRPDataset::OpenDataset(
     const char* pszGENFileName, const char* pszIMGFileName, DDFRecord* record)
 {
-    DDFModule module;    
+    DDFModule module;
     DDFField* field;
     DDFFieldDefn *fieldDefn;
 
@@ -962,7 +983,7 @@ SRPDataset* SRPDataset::OpenDataset(
     }
 
     const char* pszPRT = record->GetStringSubfield("DSI", 0, "PRT", 0);
-    if( pszPRT == NULL) 
+    if( pszPRT == NULL)
         return NULL;
 
     CPLString osPRT = pszPRT;
@@ -989,8 +1010,6 @@ SRPDataset* SRPDataset::OpenDataset(
     poDS->osGENFileName = pszGENFileName;
     poDS->osIMGFileName = pszIMGFileName;
 
-
-    
     poDS->SetMetadataItem( "SRP_NAM", osNAM );
     poDS->SetMetadataItem( "SRP_PRODUCT", osPRT );
 
@@ -1002,11 +1021,9 @@ SRPDataset* SRPDataset::OpenDataset(
     }
 
     return poDS;
-
 }
 
 
-
 /************************************************************************/
 /*                          GetGENListFromTHF()                         */
 /************************************************************************/
@@ -1026,7 +1043,7 @@ char** SRPDataset::GetGENListFromTHF(const char* pszFileName)
 
     CPLString osDirName(CPLGetDirname(pszFileName));
 
-    while (TRUE)
+    while( true )
     {
         CPLPushErrorHandler( CPLQuietErrorHandler );
         record = module.ReadRecord();
@@ -1080,9 +1097,9 @@ char** SRPDataset::GetGENListFromTHF(const char* pszFileName)
 
                     CPLString osName = CPLString(pszNAM);
 
-                    /* Define a subdirectory from Dataset but with only 6 caracatere */
+                    /* Define a subdirectory from Dataset but with only 6 characters */
                     CPLString osDirDataset = pszNAM;
-                    osDirDataset.resize(6); 
+                    osDirDataset.resize(6);
                     CPLString osDatasetDir = CPLFormFilename(osDirName.c_str(), osDirDataset.c_str(), NULL);
 
                     CPLString osGENFileName="";
@@ -1168,7 +1185,7 @@ void SRPDataset::AddMetadatafromFromTHF(const char* pszFileName)
 
     CPLString osDirName(CPLGetDirname(pszFileName));
 
-    while (TRUE)
+    while( true )
     {
         CPLPushErrorHandler( CPLQuietErrorHandler );
         record = module.ReadRecord();
@@ -1204,9 +1221,9 @@ void SRPDataset::AddMetadatafromFromTHF(const char* pszFileName)
                 if (bSuccess)
                 {
                     CPLDebug("SRP", "Record EDN %d",EDN);
-                    char pszValue[5];
-                    sprintf(pszValue, "%d", EDN);
-                    SetMetadataItem( "SRP_EDN", pszValue );
+                    char szValue[5];
+                    snprintf(szValue, sizeof(szValue), "%d", EDN);
+                    SetMetadataItem( "SRP_EDN", szValue );
                 }
 
 
@@ -1291,9 +1308,9 @@ char** SRPDataset::GetIMGListFromGEN(const char* pszFileName,
 
     DDFModule module;
     if (!module.Open(pszFileName, TRUE))
-        return NULL;    
+        return NULL;
 
-    while (TRUE)
+    while( true )
     {
         nRecordIndex ++;
 
@@ -1405,7 +1422,7 @@ GDALDataset *SRPDataset::Open( GDALOpenInfo * poOpenInfo )
     int bFromSubdataset = FALSE;
     int bTHFWithSingleGEN = FALSE;
 
-    if( EQUALN(poOpenInfo->pszFilename, "SRP:", 4) )
+    if( STARTS_WITH_CI(poOpenInfo->pszFilename, "SRP:") )
     {
         char** papszTokens = CSLTokenizeString2(poOpenInfo->pszFilename + 4, ",", 0);
         if (CSLCount(papszTokens) == 2)
@@ -1431,7 +1448,7 @@ GDALDataset *SRPDataset::Open( GDALOpenInfo * poOpenInfo )
             if (papszFileNames == NULL)
                 return NULL;
             if (papszFileNames[1] == NULL &&
-                CSLTestBoolean(CPLGetConfigOption("SRP_SINGLE_GEN_IN_THF_AS_DATASET", "TRUE")))
+                CPLTestBool(CPLGetConfigOption("SRP_SINGLE_GEN_IN_THF_AS_DATASET", "TRUE")))
             {
                 osFileName = papszFileNames[0];
                 CSLDestroy(papszFileNames);
@@ -1500,13 +1517,13 @@ GDALDataset *SRPDataset::Open( GDALOpenInfo * poOpenInfo )
 
             for( i = 0; i < (int)nLeaderSize; i++ )
             {
-                if( poOpenInfo->pabyHeader[i] < 32 
+                if( poOpenInfo->pabyHeader[i] < 32
                     || poOpenInfo->pabyHeader[i] > 126 )
                     return NULL;
             }
 
-            if( poOpenInfo->pabyHeader[5] != '1' 
-                && poOpenInfo->pabyHeader[5] != '2' 
+            if( poOpenInfo->pabyHeader[5] != '1'
+                && poOpenInfo->pabyHeader[5] != '2'
                 && poOpenInfo->pabyHeader[5] != '3' )
                 return NULL;
 
@@ -1516,8 +1533,8 @@ GDALDataset *SRPDataset::Open( GDALOpenInfo * poOpenInfo )
                 return NULL;
 
             // --------------------------------------------------------------------
-            //      Find and open the .GEN file.                                   
-            // -------------------------------------------------------------------- 
+            //      Find and open the .GEN file.
+            // --------------------------------------------------------------------
             VSIStatBufL sStatBuf;
 
             CPLString basename = CPLGetBasename( osFileName );
@@ -1527,7 +1544,7 @@ GDALDataset *SRPDataset::Open( GDALOpenInfo * poOpenInfo )
                 return NULL;
             }
 
-            nRecordIndex = CPLScanLong( basename + 6, 2 );
+            nRecordIndex = static_cast<int>(CPLScanLong( basename + 6, 2 ));
 
             CPLString path = CPLGetDirname( osFileName );
             CPLString basename01 = ResetTo01( basename );
@@ -1552,7 +1569,7 @@ GDALDataset *SRPDataset::Open( GDALOpenInfo * poOpenInfo )
 
         if( poOpenInfo->eAccess == GA_Update )
         {
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                 "The SRP driver does not support update access to existing"
                 " datasets.\n" );
             return NULL;
@@ -1606,25 +1623,21 @@ GDALDataset *SRPDataset::Open( GDALOpenInfo * poOpenInfo )
 void GDALRegister_SRP()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "SRP" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "SRP" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "SRP" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Standard Raster Product (ASRP/USRP)" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#SRP" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "img" );
-        poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = SRPDataset::Open;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
-}
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "SRP" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Standard Raster Product (ASRP/USRP)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#SRP" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "img" );
+    poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
+    poDriver->pfnOpen = SRPDataset::Open;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/frmts/aigrid/GNUmakefile b/frmts/aigrid/GNUmakefile
index 4d48b5b..d1026e4 100644
--- a/frmts/aigrid/GNUmakefile
+++ b/frmts/aigrid/GNUmakefile
@@ -4,7 +4,7 @@ include ../../GDALmake.opt
 AIGOBJ  =	gridlib.o aigopen.o aigccitt.o
 OBJ	=	aigdataset.o $(AIGOBJ)
 
-CPPFLAGS	:=	 $(CPPFLAGS) -I../../ogr/ogrsf_frmts/avc
+CPPFLAGS	:=	 $(CPPFLAGS) -I../../ogr/ogrsf_frmts/avc -I../../ogr/ogrsf_frmts/shape
 
 default:	$(OBJ:.o=.$(OBJ_EXT))
 
diff --git a/frmts/aigrid/aigccitt.c b/frmts/aigrid/aigccitt.c
index 431bf45..603accf 100644
--- a/frmts/aigrid/aigccitt.c
+++ b/frmts/aigrid/aigccitt.c
@@ -1,11 +1,11 @@
 /******************************************************************************
- * $Id: aigccitt.c 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: aigccitt.c 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Arc/Info Binary Grid Translator
  * Purpose:  Code for decoding CCITT RLE (G1) compressed data.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *           Code derived from libtiff (tif_fax3), which originally was
- *           derived from code by Frank Cringle in viewfax. 
+ *           derived from code by Frank Cringle in viewfax.
  *
  ******************************************************************************
  * Copyright (c) 2002 Frank Warmerdam <warmerdam at pobox.com>
@@ -13,23 +13,23 @@
  * Copyright (c) 1991-1997 Silicon Graphics, Inc.
  * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
- * Permission to use, copy, modify, distribute, and sell this software and 
+ * Permission to use, copy, modify, distribute, and sell this software and
  * its documentation for any purpose is hereby granted without fee, provided
  * that (i) the above copyright notices and this permission notice appear in
  * all copies of the software and related documentation, and (ii) the names of
  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  * publicity relating to the software without the specific, prior written
  * permission of Sam Leffler and Silicon Graphics.
- * 
- * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
- * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
- * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
- * 
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
- * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  * OF THIS SOFTWARE.
  ****************************************************************************/
 
@@ -50,7 +50,7 @@
 
 /*
  * To override the default routine used to image decoded
- * spans one can use the pseduo tag TIFFTAG_FAXFILLFUNC.
+ * spans one can use the pseudo tag TIFFTAG_FAXFILLFUNC.
  * The routine must have the type signature given below;
  * for example:
  *
@@ -85,7 +85,7 @@ typedef	void (*TIFFFaxFillFunc)(unsigned char*, GUInt32*, GUInt32*, GUInt32);
 typedef struct {		/* state table entry */
 	unsigned char State;	/* see above */
 	unsigned char Width;	/* width of code in bits */
-	GUInt32	Param;		/* unsigned 32-bit run length in bits */
+	GUInt16	Param;		/* unsigned 16-bit run length in bits */
 } TIFFFaxTabEnt;
 
 #if 0  /* Unused */
@@ -1171,38 +1171,38 @@ static const unsigned char aig_TIFFBitRevTable[256] = {
 
 #if 0  /* Unused */
 static const unsigned char aig_TIFFNoBitRevTable[256] = {
-    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
-    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 
-    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 
-    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 
-    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 
-    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 
-    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 
-    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 
-    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 
-    0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 
-    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 
-    0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 
-    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 
-    0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 
-    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 
-    0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 
-    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 
-    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 
-    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 
-    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 
-    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 
-    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 
-    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 
-    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 
-    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 
-    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 
-    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 
-    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 
-    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 
-    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 
-    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 
-    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+    0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+    0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+    0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+    0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
 };
 #endif  /* Unused */
 
@@ -1539,7 +1539,7 @@ typedef struct {
     sp->bit = BitsAvail;						\
     sp->data = BitAcc;							\
     sp->EOLcnt = EOLcnt;						\
-    rawcc -= (unsigned char *) cp - rawcp;				\
+    rawcc -= (int)((unsigned char *) cp - rawcp);			\
     rawcp = (unsigned char *) cp;					\
 } while (0)
 
@@ -1552,7 +1552,7 @@ typedef struct {
 static void
 Fax3Unexpected()
 {
-    CPLError( CE_Failure, CPLE_AppDefined, 
+    CPLError( CE_Failure, CPLE_AppDefined,
               "Bad code word" );
 }
 #define	unexpected(table, a0)	Fax3Unexpected()
@@ -1560,7 +1560,7 @@ Fax3Unexpected()
 static void
 Fax3BadLength(GUInt32 a0, GUInt32 lastx)
 {
-    CPLError( CE_Warning, CPLE_AppDefined, 
+    CPLError( CE_Warning, CPLE_AppDefined,
               "%s (got %lu, expected %lu)",
               a0 < lastx ? "Premature EOL" : "Line length mismatch",
               (unsigned long) a0, (unsigned long) lastx );
@@ -1571,7 +1571,7 @@ Fax3BadLength(GUInt32 a0, GUInt32 lastx)
 static void
 Fax3PrematureEOF()
 {
-    CPLError( CE_Warning, CPLE_AppDefined, 
+    CPLError( CE_Warning, CPLE_AppDefined,
               "Premature EOF" );
 }
 #define	prematureEOF(a0)	Fax3PrematureEOF()
@@ -1584,7 +1584,7 @@ Fax3PrematureEOF()
  * this is <8 bytes.  We optimize the code here to reflect the
  * machine characteristics.
  */
-#if defined(__alpha) || _MIPS_SZLONG == 64 || defined(__LP64__) || defined(__arch64__)
+#if SIZEOF_UNSIGNED_LONG == 8
 #define FILL(n, cp)							    \
     switch (n) {							    \
     case 15:(cp)[14] = 0xff; case 14:(cp)[13] = 0xff; case 13: (cp)[12] = 0xff;\
@@ -1626,7 +1626,7 @@ Fax3PrematureEOF()
 /************************************************************************/
 
 static void
-aig_TIFFFax3fillruns(unsigned char* buf, GUInt32* runs, GUInt32* erun, 
+aig_TIFFFax3fillruns(unsigned char* buf, GUInt32* runs, GUInt32* erun,
                   GUInt32 lastx)
 {
 	static const unsigned char _fillmasks[] =
@@ -1728,6 +1728,11 @@ Fax3DecodeRLE(Fax3BaseState* tif, unsigned char *buf, int occ,
 {
     DECLARE_STATE(tif, sp);
     int mode = sp->b.mode;
+    if( occ % sp->b.rowbytes)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Fractional scanlines cannot be read");
+        return (-1);
+    }
 
     CACHE_STATE(sp);
     thisrun = sp->curruns;
@@ -1757,61 +1762,61 @@ Fax3DecodeRLE(Fax3BaseState* tif, unsigned char *buf, int occ,
 /*      being zero-padded to insure the decoder recognized an EOL       */
 /*      before running out of data.                                     */
 /* -------------------------------------------------------------------- */
-        do {						
-            for (;;) {							 
-                for (;;) {						     
-                    LOOKUP16(12, aig_TIFFFaxWhiteTable, eof1d);		  
-                    switch (TabEnt->State) {				       
-                      case S_EOL:					
-                        EOLcnt = 1;					
-                        goto done1d;					
-                      case S_TermW:					
-                        SETVAL(TabEnt->Param);				
-                        goto doneWhite1d;				
-                      case S_MakeUpW:					
-                      case S_MakeUp:					
-                        a0 += TabEnt->Param;				
-                        RunLength += TabEnt->Param;			
-                        break;						
-                      default:						
-                        unexpected("WhiteTable", a0);			
-                        goto done1d;					
-                    }							
-                }							
-              doneWhite1d:						
-                if (a0 >= lastx)					
-                    goto done1d;					
-                for (;;) {						
-                    LOOKUP16(13, aig_TIFFFaxBlackTable, eof1d);		
-                    switch (TabEnt->State) {				
-                      case S_EOL:					
-                        EOLcnt = 1;					
-                        goto done1d;					
-                      case S_TermB:					
-                        SETVAL(TabEnt->Param);				
-                        goto doneBlack1d;				
-                      case S_MakeUpB:					
-                      case S_MakeUp:					
-                        a0 += TabEnt->Param;				
-                        RunLength += TabEnt->Param;			
-                        break;						
-                      default:						
-                        unexpected("BlackTable", a0);			
-                        goto done1d;					
-                    }							
-                }							
-              doneBlack1d:						
-                if (a0 >= lastx)					
-                    goto done1d;					
-                if( *(pa-1) == 0 && *(pa-2) == 0 )		
-                    pa -= 2;                                                   
-            }								
-          eof1d:							
-            prematureEOF(a0);						
-            CLEANUP_RUNS();						
-            goto EOFRLE;						
-          done1d:							
-            CLEANUP_RUNS();						
+        do {
+            for (;;) {
+                for (;;) {
+                    LOOKUP16(12, aig_TIFFFaxWhiteTable, eof1d);
+                    switch (TabEnt->State) {
+                      case S_EOL:
+                        EOLcnt = 1;
+                        goto done1d;
+                      case S_TermW:
+                        SETVAL(TabEnt->Param);
+                        goto doneWhite1d;
+                      case S_MakeUpW:
+                      case S_MakeUp:
+                        a0 += TabEnt->Param;
+                        RunLength += TabEnt->Param;
+                        break;
+                      default:
+                        unexpected("WhiteTable", a0);
+                        goto done1d;
+                    }
+                }
+              doneWhite1d:
+                if (a0 >= lastx)
+                    goto done1d;
+                for (;;) {
+                    LOOKUP16(13, aig_TIFFFaxBlackTable, eof1d);
+                    switch (TabEnt->State) {
+                      case S_EOL:
+                        EOLcnt = 1;
+                        goto done1d;
+                      case S_TermB:
+                        SETVAL(TabEnt->Param);
+                        goto doneBlack1d;
+                      case S_MakeUpB:
+                      case S_MakeUp:
+                        a0 += TabEnt->Param;
+                        RunLength += TabEnt->Param;
+                        break;
+                      default:
+                        unexpected("BlackTable", a0);
+                        goto done1d;
+                    }
+                }
+              doneBlack1d:
+                if (a0 >= lastx)
+                    goto done1d;
+                if( *(pa-1) == 0 && *(pa-2) == 0 )
+                    pa -= 2;
+            }
+          eof1d:
+            prematureEOF(a0);
+            CLEANUP_RUNS();
+            goto EOFRLE;
+          done1d:
+            CLEANUP_RUNS();
         } while (0);
 
 /* -------------------------------------------------------------------- */
@@ -1884,6 +1889,11 @@ CPLErr DecompressCCITTRLETile( unsigned char *pabySrcData, int nSrcBytes,
      * Calculate the scanline/tile widths.
      */
     rowbytes = nBlockXSize / 8;
+	if( rowbytes == 0 )
+	{
+        CPLError(CE_Failure, CPLE_AppDefined, "rowbytes == 0");
+        return CE_Failure;
+	}
     rowpixels = nBlockXSize;
 
     sp->rowbytes = (GUInt32) rowbytes;
@@ -1914,7 +1924,7 @@ CPLErr DecompressCCITTRLETile( unsigned char *pabySrcData, int nSrcBytes,
         DecoderState(sp)->refruns[1] = 0;
     }
 
-    if( Fax3DecodeRLE( sp, pabyDstData, nDstBytes, 
+    if( Fax3DecodeRLE( sp, pabyDstData, nDstBytes,
                        pabySrcData, nSrcBytes ) == 1 )
         return CE_None;
     else
diff --git a/frmts/aigrid/aigdataset.cpp b/frmts/aigrid/aigdataset.cpp
index 584bd46..4442a54 100644
--- a/frmts/aigrid/aigdataset.cpp
+++ b/frmts/aigrid/aigdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: aigdataset.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: aigdataset.cpp 33757 2016-03-20 20:22:33Z goatbar $
  *
  * Project:  Arc/Info Binary Grid Driver
  * Purpose:  Implements GDAL interface to underlying library.
@@ -28,21 +28,19 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
-#include "cpl_string.h"
-#include "ogr_spatialref.h"
-#include "gdal_rat.h"
 #include "aigrid.h"
 #include "avc.h"
-#include <vector>
+#include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
+#include "gdal_rat.h"
+#include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: aigdataset.cpp 27384 2014-05-24 12:28:12Z rouault $");
+#include <vector>
 
-CPL_C_START
-void	GDALRegister_AIGrid(void);
-CPL_C_END
+CPL_CVSID("$Id: aigdataset.cpp 33757 2016-03-20 20:22:33Z goatbar $");
 
-static CPLString OSR_GDS( char **papszNV, const char * pszField, 
+static CPLString OSR_GDS( char **papszNV, const char * pszField,
                            const char *pszDefaultValue );
 
 
@@ -57,7 +55,7 @@ class AIGRasterBand;
 class CPL_DLL AIGDataset : public GDALPamDataset
 {
     friend class AIGRasterBand;
-    
+
     AIGInfo_t	*psInfo;
 
     char	**papszPrj;
@@ -111,26 +109,26 @@ class AIGRasterBand : public GDALPamRasterBand
 /*                           AIGRasterBand()                            */
 /************************************************************************/
 
-AIGRasterBand::AIGRasterBand( AIGDataset *poDS, int nBand )
+AIGRasterBand::AIGRasterBand( AIGDataset *poDSIn, int nBandIn )
 
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
 
-    nBlockXSize = poDS->psInfo->nBlockXSize;
-    nBlockYSize = poDS->psInfo->nBlockYSize;
+    nBlockXSize = poDSIn->psInfo->nBlockXSize;
+    nBlockYSize = poDSIn->psInfo->nBlockYSize;
 
-    if( poDS->psInfo->nCellType == AIG_CELLTYPE_INT
-        && poDS->psInfo->dfMin >= 0.0 && poDS->psInfo->dfMax <= 254.0 )
+    if( poDSIn->psInfo->nCellType == AIG_CELLTYPE_INT
+        && poDSIn->psInfo->dfMin >= 0.0 && poDSIn->psInfo->dfMax <= 254.0 )
     {
         eDataType = GDT_Byte;
     }
-    else if( poDS->psInfo->nCellType == AIG_CELLTYPE_INT
-        && poDS->psInfo->dfMin >= -32767 && poDS->psInfo->dfMax <= 32767 )
+    else if( poDSIn->psInfo->nCellType == AIG_CELLTYPE_INT
+        && poDSIn->psInfo->dfMin >= -32767 && poDSIn->psInfo->dfMax <= 32767 )
     {
         eDataType = GDT_Int16;
     }
-    else if( poDS->psInfo->nCellType == AIG_CELLTYPE_INT )
+    else if( poDSIn->psInfo->nCellType == AIG_CELLTYPE_INT )
     {
         eDataType = GDT_Int32;
     }
@@ -150,7 +148,6 @@ CPLErr AIGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 {
     AIGDataset	*poODS = (AIGDataset *) poDS;
     GInt32	*panGridRaster;
-    int		i;
 
     if( poODS->psInfo->nCellType == AIG_CELLTYPE_INT )
     {
@@ -165,7 +162,7 @@ CPLErr AIGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
         if( eDataType == GDT_Byte )
         {
-            for( i = 0; i < nBlockXSize * nBlockYSize; i++ )
+            for( int i = 0; i < nBlockXSize * nBlockYSize; i++ )
             {
                 if( panGridRaster[i] == ESRI_GRID_NO_DATA )
                     ((GByte *) pImage)[i] = 255;
@@ -175,7 +172,7 @@ CPLErr AIGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         }
         else if( eDataType == GDT_Int16 )
         {
-            for( i = 0; i < nBlockXSize * nBlockYSize; i++ )
+            for( int i = 0; i < nBlockXSize * nBlockYSize; i++ )
             {
                 if( panGridRaster[i] == ESRI_GRID_NO_DATA )
                     ((GInt16 *) pImage)[i] = -32768;
@@ -185,10 +182,10 @@ CPLErr AIGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         }
         else
         {
-            for( i = 0; i < nBlockXSize * nBlockYSize; i++ )
+            for( int i = 0; i < nBlockXSize * nBlockYSize; i++ )
                 ((GInt32 *) pImage)[i] = panGridRaster[i];
         }
-        
+
         CPLFree( panGridRaster );
 
         return CE_None;
@@ -266,12 +263,14 @@ double AIGRasterBand::GetNoDataValue( int *pbSuccess )
 
     if( eDataType == GDT_Float32 )
         return ESRI_GRID_FLOAT_NO_DATA;
-    else if( eDataType == GDT_Int16 )
+
+    if( eDataType == GDT_Int16 )
         return -32768;
-    else if( eDataType == GDT_Byte )
+
+    if( eDataType == GDT_Byte )
         return 255;
-    else
-        return ESRI_GRID_NO_DATA;
+
+    return ESRI_GRID_NO_DATA;
 }
 
 /************************************************************************/
@@ -285,8 +284,8 @@ GDALColorInterp AIGRasterBand::GetColorInterpretation()
 
     if( poODS->poCT != NULL )
         return GCI_PaletteIndex;
-    else
-        return GDALPamRasterBand::GetColorInterpretation();
+
+    return GDALPamRasterBand::GetColorInterpretation();
 }
 
 /************************************************************************/
@@ -300,8 +299,8 @@ GDALColorTable *AIGRasterBand::GetColorTable()
 
     if( poODS->poCT != NULL )
         return poODS->poCT;
-    else
-        return GDALPamRasterBand::GetColorTable();
+
+    return GDALPamRasterBand::GetColorTable();
 }
 
 /************************************************************************/
@@ -315,15 +314,14 @@ GDALColorTable *AIGRasterBand::GetColorTable()
 /*                            AIGDataset()                            */
 /************************************************************************/
 
-AIGDataset::AIGDataset()
-
+AIGDataset::AIGDataset() :
+    psInfo(NULL),
+    papszPrj(NULL),
+    poCT(NULL),
+    bHasReadRat(FALSE),
+    poRAT(NULL)
 {
-    psInfo = NULL;
-    papszPrj = NULL;
     pszProjection = CPLStrdup("");
-    poCT = NULL;
-    poRAT = NULL;
-    bHasReadRat = FALSE;
 }
 
 /************************************************************************/
@@ -357,22 +355,21 @@ char **AIGDataset::GetFileList()
 
     // Add in all files in the cover directory.
     char **papszCoverFiles = VSIReadDir( GetDescription() );
-    int i;
 
-    for( i = 0; papszCoverFiles != NULL && papszCoverFiles[i] != NULL; i++ )
+    for(int  i = 0; papszCoverFiles != NULL && papszCoverFiles[i] != NULL; i++ )
     {
         if( EQUAL(papszCoverFiles[i],".")
             || EQUAL(papszCoverFiles[i],"..") )
             continue;
 
-        papszFileList = 
-            CSLAddString( papszFileList, 
-                          CPLFormFilename( GetDescription(), 
-                                           papszCoverFiles[i], 
+        papszFileList =
+            CSLAddString( papszFileList,
+                          CPLFormFilename( GetDescription(),
+                                           papszCoverFiles[i],
                                            NULL ) );
     }
     CSLDestroy(papszCoverFiles);
-    
+
     return papszFileList;
 }
 
@@ -384,18 +381,18 @@ class AIGErrorDescription
 {
     public:
         CPLErr eErr;
-        int    no;
+        CPLErrorNum    no;
         CPLString osMsg;
 };
 
-static void CPL_STDCALL AIGErrorHandlerVATOpen(CPLErr eErr, int no, const char* msg)
+static void CPL_STDCALL AIGErrorHandlerVATOpen(CPLErr eErr, CPLErrorNum no, const char* msg)
 {
     std::vector<AIGErrorDescription>* paoErrors =
         (std::vector<AIGErrorDescription>* )CPLGetErrorHandlerUserData();
-    if( EQUALN(msg, "EOF encountered in", strlen("EOF encountered in")) &&
+    if( STARTS_WITH_CI(msg, "EOF encountered in") &&
         strstr(msg, "../info/arc.dir") != NULL )
         return;
-    if( EQUALN(msg, "Failed to open table ", strlen("Failed to open table ")) )
+    if( STARTS_WITH_CI(msg, "Failed to open table ") )
         return;
     AIGErrorDescription oError;
     oError.eErr = eErr;
@@ -411,8 +408,6 @@ static void CPL_STDCALL AIGErrorHandlerVATOpen(CPLErr eErr, int no, const char*
 void AIGDataset::ReadRAT()
 
 {
-#ifndef OGR_ENABLED
-#else
 /* -------------------------------------------------------------------- */
 /*      Check if we have an associated info directory.  If not          */
 /*      return quietly.                                                 */
@@ -422,14 +417,14 @@ void AIGDataset::ReadRAT()
 
     osInfoPath = psInfo->pszCoverName;
     osInfoPath += "/../info";
-    
+
     if( VSIStatL( osInfoPath, &sStatBuf ) != 0 )
     {
         CPLDebug( "AIG", "No associated info directory at: %s, skip RAT.",
                   osInfoPath.c_str() );
         return;
     }
-    
+
     osInfoPath += "/";
 
 /* -------------------------------------------------------------------- */
@@ -443,7 +438,7 @@ void AIGDataset::ReadRAT()
     std::vector<AIGErrorDescription> aoErrors;
     CPLPushErrorHandlerEx(AIGErrorHandlerVATOpen, &aoErrors );
 
-    AVCBinFile *psFile = 
+    AVCBinFile *psFile =
         AVCBinReadOpen( osInfoPath, osTableName,
                         AVCCoverTypeUnknown, AVCFileTABLE, NULL );
     CPLPopErrorHandler();
@@ -465,11 +460,9 @@ void AIGDataset::ReadRAT()
 /* -------------------------------------------------------------------- */
 /*      Setup columns in corresponding RAT.                             */
 /* -------------------------------------------------------------------- */
-    int iField;
-
     poRAT = new GDALDefaultRasterAttributeTable();
 
-    for( iField = 0; iField < psTableDef->numFields; iField++ )
+    for( int iField = 0; iField < psTableDef->numFields; iField++ )
     {
         AVCFieldInfo *psFDef = psTableDef->pasFieldDef + iField;
         GDALRATFieldUsage eFUsage = GFU_Generic;
@@ -482,7 +475,7 @@ void AIGDataset::ReadRAT()
             eFUsage = GFU_MinMax;
         else if( EQUAL(osFName,"COUNT") )
             eFUsage = GFU_PixelCount;
-        
+
         if( psFDef->nType1 * 10 == AVC_FT_BININT )
             eFType = GFT_Integer;
         else if( psFDef->nType1 * 10 == AVC_FT_BINFLOAT )
@@ -501,7 +494,7 @@ void AIGDataset::ReadRAT()
     {
         iRecord++;
 
-        for( iField = 0; iField < psTableDef->numFields; iField++ )
+        for( int iField = 0; iField < psTableDef->numFields; iField++ )
         {
             switch( psTableDef->pasFieldDef[iField].nType1 * 10 )
             {
@@ -519,19 +512,19 @@ void AIGDataset::ReadRAT()
 
               case AVC_FT_BININT:
                 if( psTableDef->pasFieldDef[iField].nSize == 4 )
-                    poRAT->SetValue( iRecord-1, iField, 
+                    poRAT->SetValue( iRecord-1, iField,
                                      pasFields[iField].nInt32 );
                 else
-                    poRAT->SetValue( iRecord-1, iField, 
+                    poRAT->SetValue( iRecord-1, iField,
                                      pasFields[iField].nInt16 );
                 break;
 
               case AVC_FT_BINFLOAT:
                 if( psTableDef->pasFieldDef[iField].nSize == 4 )
-                    poRAT->SetValue( iRecord-1, iField, 
+                    poRAT->SetValue( iRecord-1, iField,
                                      pasFields[iField].fFloat );
                 else
-                    poRAT->SetValue( iRecord-1, iField, 
+                    poRAT->SetValue( iRecord-1, iField,
                                      pasFields[iField].dDouble );
                 break;
             }
@@ -547,8 +540,6 @@ void AIGDataset::ReadRAT()
     /* Workaround against #2447 and #3031, to avoid binding languages */
     /* not being able to open the dataset */
     CPLErrorReset();
-
-#endif /* OGR_ENABLED */
 }
 
 /************************************************************************/
@@ -568,7 +559,7 @@ GDALDataset *AIGDataset::Open( GDALOpenInfo * poOpenInfo )
     CPLString osCoverName;
 
     osCoverName = poOpenInfo->pszFilename;
-    if( osCoverName.size() > 4 
+    if( osCoverName.size() > 4
         && EQUAL(osCoverName.c_str()+osCoverName.size()-4,".adf") )
     {
         osCoverName = CPLGetDirname( poOpenInfo->pszFilename );
@@ -589,10 +580,9 @@ GDALDataset *AIGDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     VSIStatBufL sStatBuf;
     CPLString osTestName;
-    
+
     osTestName.Printf( "%s/hdr.adf", osCoverName.c_str() );
     if( VSIStatL( osTestName, &sStatBuf ) != 0 )
-
     {
         osTestName.Printf( "%s/HDR.ADF", osCoverName.c_str() );
         if( VSIStatL( osTestName, &sStatBuf ) != 0 )
@@ -605,8 +595,7 @@ GDALDataset *AIGDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      there are none this is likely not a grid.                       */
 /* -------------------------------------------------------------------- */
     char **papszFileList = VSIReadDir( osCoverName );
-    int iFile;
-    int bGotOne = FALSE;
+    bool bGotOne = false;
 
     if (papszFileList == NULL)
     {
@@ -618,20 +607,20 @@ GDALDataset *AIGDataset::Open( GDALOpenInfo * poOpenInfo )
             osTestName.Printf( "%s/W001001.ADF", osCoverName.c_str() );
             if( VSIStatL( osTestName, &sStatBuf ) == 0 )
             {
-                bGotOne = TRUE;
+                bGotOne = true;
                 break;
             }
 
             osTestName.Printf( "%s/w001001.adf", osCoverName.c_str() );
             if( VSIStatL( osTestName, &sStatBuf ) == 0 )
             {
-                bGotOne = TRUE;
+                bGotOne = true;
                 break;
             }
         } while(0);
     }
 
-    for( iFile = 0; 
+    for( int iFile = 0;
          papszFileList != NULL && papszFileList[iFile] != NULL && !bGotOne;
          iFile++ )
     {
@@ -645,37 +634,37 @@ GDALDataset *AIGDataset::Open( GDALOpenInfo * poOpenInfo )
             && papszFileList[iFile][0] != 'Z' )
             continue;
 
-        if( strncmp(papszFileList[iFile] + 1, "0010", 4) != 0 )
+        if( !STARTS_WITH(papszFileList[iFile] + 1, "0010") )
             continue;
 
         if( !EQUAL(papszFileList[iFile] + 7, ".adf") )
             continue;
 
-        bGotOne = TRUE;
+        bGotOne = true;
     }
     CSLDestroy( papszFileList );
 
     if( !bGotOne )
         return NULL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Open the file.                                                  */
 /* -------------------------------------------------------------------- */
     psInfo = AIGOpen( osCoverName.c_str(), "r" );
-    
+
     if( psInfo == NULL )
     {
         CPLErrorReset();
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
         AIGClose(psInfo);
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The AIG driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
@@ -683,9 +672,7 @@ GDALDataset *AIGDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    AIGDataset 	*poDS;
-
-    poDS = new AIGDataset();
+    AIGDataset 	*poDS = new AIGDataset();
 
     poDS->psInfo = psInfo;
 
@@ -693,48 +680,47 @@ GDALDataset *AIGDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Try to read a color table (.clr).  It seems it is legal to      */
 /*      have more than one so we just use the first one found.          */
 /* -------------------------------------------------------------------- */
-    char **papszFiles = CPLReadDir( psInfo->pszCoverName );
+    char **papszFiles = VSIReadDir( psInfo->pszCoverName );
     CPLString osClrFilename;
     CPLString osCleanPath = CPLCleanTrailingSlash( psInfo->pszCoverName );
-  
+
     // first check for any .clr in coverage dir.
-    for( iFile = 0; papszFiles != NULL && papszFiles[iFile] != NULL; iFile++ )
+    for( int iFile = 0; papszFiles != NULL && papszFiles[iFile] != NULL; iFile++ )
     {
         if( !EQUAL(CPLGetExtension(papszFiles[iFile]),"clr") && !EQUAL(CPLGetExtension(papszFiles[iFile]),"CLR"))
             continue;
-      
+
         osClrFilename = CPLFormFilename( psInfo->pszCoverName,
                                          papszFiles[iFile], NULL );
         break;
     }
-  
+
     CSLDestroy( papszFiles );
-  
+
     // Look in parent if we don't find a .clr in the coverage dir.
     if( strlen(osClrFilename) == 0 )
     {
         osTestName.Printf( "%s/../%s.clr",
                            psInfo->pszCoverName,
                            CPLGetFilename( osCleanPath ) );
-      
+
         if( VSIStatL( osTestName, &sStatBuf ) != 0 )
 
 	{
             osTestName.Printf( "%s/../%s.CLR",
                                psInfo->pszCoverName,
                                CPLGetFilename( osCleanPath ) );
-      
+
             if( !VSIStatL( osTestName, &sStatBuf ) )
                 osClrFilename = osTestName;
         }
         else
             osClrFilename = osTestName;
     }
-    
-  
+
     if( strlen(osClrFilename) > 0 )
         poDS->TranslateColorTable( osClrFilename );
-  
+
 /* -------------------------------------------------------------------- */
 /*      Establish raster info.                                          */
 /* -------------------------------------------------------------------- */
@@ -750,9 +736,8 @@ GDALDataset *AIGDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*	Try to read projection file.					*/
 /* -------------------------------------------------------------------- */
-    const char	*pszPrjFilename;
-
-    pszPrjFilename = CPLFormCIFilename( psInfo->pszCoverName, "prj", "adf" );
+    const char	*pszPrjFilename
+        = CPLFormCIFilename( psInfo->pszCoverName, "prj", "adf" );
     if( VSIStatL( pszPrjFilename, &sStatBuf ) == 0 )
     {
         OGRSpatialReference	oSRS;
@@ -761,9 +746,9 @@ GDALDataset *AIGDataset::Open( GDALOpenInfo * poOpenInfo )
 
         if( oSRS.importFromESRI( poDS->papszPrj ) == OGRERR_NONE )
         {
-            // If geographic values are in seconds, we must transform. 
-            // Is there a code for minutes too? 
-            if( oSRS.IsGeographic() 
+            // If geographic values are in seconds, we must transform.
+            // Is there a code for minutes too?
+            if( oSRS.IsGeographic()
                 && EQUAL(OSR_GDS( poDS->papszPrj, "Units", ""), "DS") )
             {
                 psInfo->dfLLX /= 3600.0;
@@ -805,7 +790,7 @@ CPLErr AIGDataset::GetGeoTransform( double * padfTransform )
     padfTransform[3] = psInfo->dfURY;
     padfTransform[4] = 0;
     padfTransform[5] = -psInfo->dfCellSizeY;
-    
+
     return( CE_None );
 }
 
@@ -826,16 +811,13 @@ const char *AIGDataset::GetProjectionRef()
 void AIGDataset::TranslateColorTable( const char *pszClrFilename )
 
 {
-    int  iLine;
-    char **papszClrLines;
-
-    papszClrLines = CSLLoad( pszClrFilename );
+    char **papszClrLines = CSLLoad( pszClrFilename );
     if( papszClrLines == NULL )
         return;
 
     poCT = new GDALColorTable();
 
-    for( iLine = 0; papszClrLines[iLine] != NULL; iLine++ )
+    for( int iLine = 0; papszClrLines[iLine] != NULL; iLine++ )
     {
         char **papszTokens = CSLTokenizeString( papszClrLines[iLine] );
 
@@ -850,13 +832,13 @@ void AIGDataset::TranslateColorTable( const char *pszClrFilename )
             sEntry.c3 = (short) atoi(papszTokens[3]);
             sEntry.c4 = 255;
 
-            if( (nIndex < 0 || nIndex > 33000) 
+            if( (nIndex < 0 || nIndex > 33000)
                 || (sEntry.c1 < 0 || sEntry.c1 > 255)
                 || (sEntry.c2 < 0 || sEntry.c2 > 255)
                 || (sEntry.c3 < 0 || sEntry.c3 > 255) )
             {
                 CSLDestroy( papszTokens );
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "Color table entry appears to be corrupt, skipping the rest. " );
                 break;
             }
@@ -874,17 +856,16 @@ void AIGDataset::TranslateColorTable( const char *pszClrFilename )
 /*                              OSR_GDS()                               */
 /************************************************************************/
 
-static CPLString OSR_GDS( char **papszNV, const char * pszField, 
+static CPLString OSR_GDS( char **papszNV, const char * pszField,
                            const char *pszDefaultValue )
 
 {
-    int         iLine;
-
     if( papszNV == NULL || papszNV[0] == NULL )
         return pszDefaultValue;
 
-    for( iLine = 0; 
-         papszNV[iLine] != NULL && 
+    int iLine = 0;
+    for( ;
+         papszNV[iLine] != NULL &&
              !EQUALN(papszNV[iLine],pszField,strlen(pszField));
          iLine++ ) {}
 
@@ -893,15 +874,13 @@ static CPLString OSR_GDS( char **papszNV, const char * pszField,
     else
     {
         CPLString osResult;
-        char    **papszTokens;
-        
-        papszTokens = CSLTokenizeString(papszNV[iLine]);
+        char    **papszTokens = CSLTokenizeString(papszNV[iLine]);
 
         if( CSLCount(papszTokens) > 1 )
             osResult = papszTokens[1];
         else
             osResult = pszDefaultValue;
-        
+
         CSLDestroy( papszTokens );
         return osResult;
     }
@@ -950,9 +929,8 @@ static CPLErr AIGRename( const char *pszNewName, const char *pszOldName )
 /*      Work out the corresponding new names.                           */
 /* -------------------------------------------------------------------- */
     char **papszNewFileList = NULL;
-    int i;
-    
-    for( i = 0; papszFileList[i] != NULL; i++ )
+
+    for( int i = 0; papszFileList[i] != NULL; i++ )
     {
         CPLString osNewFilename;
 
@@ -963,7 +941,7 @@ static CPLErr AIGRename( const char *pszNewName, const char *pszOldName )
         }
 
         osNewFilename = osNewPath + (papszFileList[i] + strlen(osOldPath));
-        
+
         papszNewFileList = CSLAddString( papszNewFileList, osNewFilename );
     }
 
@@ -974,10 +952,11 @@ static CPLErr AIGRename( const char *pszNewName, const char *pszOldName )
     {
         if( VSIMkdir( osNewPath, 0777 ) != 0 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Unable to create directory %s:\n%s",
                       osNewPath.c_str(),
                       VSIStrerror(errno) );
+            CSLDestroy(papszNewFileList);
             return CE_Failure;
         }
     }
@@ -987,26 +966,34 @@ static CPLErr AIGRename( const char *pszNewName, const char *pszOldName )
 /* -------------------------------------------------------------------- */
     VSIStatBufL sStatBuf;
 
-    for( i = 0; papszFileList[i] != NULL; i++ )
+    for( int i = 0; papszFileList[i] != NULL; i++ )
     {
-        if( VSIStatL( papszFileList[i], &sStatBuf ) == 0 
+        if( VSIStatL( papszFileList[i], &sStatBuf ) == 0
             && VSI_ISREG( sStatBuf.st_mode ) )
         {
             if( CPLMoveFile( papszNewFileList[i], papszFileList[i] ) != 0 )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "Unable to move %s to %s:\n%s",
                           papszFileList[i],
-                          papszNewFileList[i], 
+                          papszNewFileList[i],
                           VSIStrerror(errno) );
+                CSLDestroy(papszNewFileList);
                 return CE_Failure;
             }
         }
     }
 
     if( VSIStatL( osOldPath, &sStatBuf ) == 0 )
-        CPLUnlinkTree( osOldPath );
+    {
+        if ( CPLUnlinkTree( osOldPath ) != 0 )
+        {
+          CPLError( CE_Warning, CPLE_AppDefined, "Unable to cleanup old path.");
+        }
+    }
 
+    CSLDestroy(papszFileList);
+    CSLDestroy(papszNewFileList);
     return CE_None;
 }
 
@@ -1035,17 +1022,16 @@ static CPLErr AIGDelete( const char *pszDatasetname )
 /* -------------------------------------------------------------------- */
 /*      Delete all regular files.                                       */
 /* -------------------------------------------------------------------- */
-    int i;
-    for( i = 0; papszFileList[i] != NULL; i++ )
+    for( int i = 0; papszFileList[i] != NULL; i++ )
     {
         VSIStatBufL sStatBuf;
-        if( VSIStatL( papszFileList[i], &sStatBuf ) == 0 
+        if( VSIStatL( papszFileList[i], &sStatBuf ) == 0
             && VSI_ISREG( sStatBuf.st_mode ) )
         {
             if( VSIUnlink( papszFileList[i] ) != 0 )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                          "Unable to delete '%s':\n%s", 
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Unable to delete '%s':\n%s",
                           papszFileList[i], VSIStrerror( errno ) );
                 return CE_Failure;
             }
@@ -1055,10 +1041,10 @@ static CPLErr AIGDelete( const char *pszDatasetname )
 /* -------------------------------------------------------------------- */
 /*      Delete directories.                                             */
 /* -------------------------------------------------------------------- */
-    for( i = 0; papszFileList[i] != NULL; i++ )
+    for( int i = 0; papszFileList[i] != NULL; i++ )
     {
         VSIStatBufL sStatBuf;
-        if( VSIStatL( papszFileList[i], &sStatBuf ) == 0 
+        if( VSIStatL( papszFileList[i], &sStatBuf ) == 0
             && VSI_ISDIR( sStatBuf.st_mode ) )
         {
             if( CPLUnlinkTree( papszFileList[i] ) != 0 )
@@ -1070,31 +1056,29 @@ static CPLErr AIGDelete( const char *pszDatasetname )
 }
 
 /************************************************************************/
-/*                          GDALRegister_AIG()                        */
+/*                          GDALRegister_AIG()                          */
 /************************************************************************/
 
 void GDALRegister_AIGrid()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "AIG" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "AIG" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "AIG" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Arc/Info Binary Grid" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#AIG" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-        
-        poDriver->pfnOpen = AIGDataset::Open;
-
-        poDriver->pfnRename = AIGRename;
-        poDriver->pfnDelete = AIGDelete;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "AIG" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Arc/Info Binary Grid" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_various.html#AIG" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = AIGDataset::Open;
+
+    poDriver->pfnRename = AIGRename;
+    poDriver->pfnDelete = AIGDelete;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/aigrid/aigopen.c b/frmts/aigrid/aigopen.c
index 80e036a..8b3bd8c 100644
--- a/frmts/aigrid/aigopen.c
+++ b/frmts/aigrid/aigopen.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: aigopen.c 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: aigopen.c 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Arc/Info Binary Grid Translator
  * Purpose:  Grid file access cover API for non-GDAL use.
@@ -30,7 +30,9 @@
 
 #include "aigrid.h"
 
-CPL_CVSID("$Id: aigopen.c 27044 2014-03-16 23:41:27Z rouault $");
+CPL_CVSID("$Id: aigopen.c 33720 2016-03-15 00:39:53Z goatbar $");
+
+CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused) {}
 
 /************************************************************************/
 /*                              AIGOpen()                               */
@@ -54,7 +56,7 @@ AIGInfo_t *AIGOpen( const char * pszInputName, const char * pszAccess )
     {
         int      i;
 
-        for( i = strlen(pszCoverName)-1; i > 0; i-- )
+        for( i = (int)strlen(pszCoverName)-1; i > 0; i-- )
         {
             if( pszCoverName[i] == '\\' || pszCoverName[i] == '/' )
             {
@@ -99,7 +101,7 @@ AIGInfo_t *AIGOpen( const char * pszInputName, const char * pszAccess )
 /* -------------------------------------------------------------------- */
     if (psInfo->dfCellSizeX <= 0 || psInfo->dfCellSizeY <= 0)
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Illegal cell size : %f x %f",
                   psInfo->dfCellSizeX, psInfo->dfCellSizeY );
         AIGClose( psInfo );
@@ -107,15 +109,15 @@ AIGInfo_t *AIGOpen( const char * pszInputName, const char * pszAccess )
     }
 
     psInfo->nPixels = (int)
-        ((psInfo->dfURX - psInfo->dfLLX + 0.5 * psInfo->dfCellSizeX) 
+        ((psInfo->dfURX - psInfo->dfLLX + 0.5 * psInfo->dfCellSizeX)
 		/ psInfo->dfCellSizeX);
     psInfo->nLines = (int)
-        ((psInfo->dfURY - psInfo->dfLLY + 0.5 * psInfo->dfCellSizeY) 
+        ((psInfo->dfURY - psInfo->dfLLY + 0.5 * psInfo->dfCellSizeY)
 		/ psInfo->dfCellSizeY);
-    
+
     if (psInfo->nPixels <= 0 || psInfo->nLines <= 0)
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Invalid raster dimensions : %d x %d",
                   psInfo->nPixels, psInfo->nLines );
         AIGClose( psInfo );
@@ -127,7 +129,7 @@ AIGInfo_t *AIGOpen( const char * pszInputName, const char * pszAccess )
         psInfo->nBlockXSize > INT_MAX / psInfo->nBlocksPerRow ||
         psInfo->nBlockYSize > INT_MAX / psInfo->nBlocksPerColumn)
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Invalid block characteristics: nBlockXSize=%d, "
                   "nBlockYSize=%d, nBlocksPerRow=%d, nBlocksPerColumn=%d",
                   psInfo->nBlockXSize, psInfo->nBlockYSize,
@@ -136,6 +138,13 @@ AIGInfo_t *AIGOpen( const char * pszInputName, const char * pszAccess )
         return NULL;
     }
 
+    if (psInfo->nBlocksPerRow > INT_MAX / psInfo->nBlocksPerColumn)
+    {
+        CPLError(CE_Failure, CPLE_OutOfMemory, "Too many blocks");
+        AIGClose( psInfo );
+        return NULL;
+    }
+
     psInfo->nTileXSize = psInfo->nBlockXSize * psInfo->nBlocksPerRow;
     psInfo->nTileYSize = psInfo->nBlockYSize * psInfo->nBlocksPerColumn;
 
@@ -145,6 +154,8 @@ AIGInfo_t *AIGOpen( const char * pszInputName, const char * pszAccess )
     if (psInfo->nTilesPerRow > INT_MAX / psInfo->nTilesPerColumn)
     {
         CPLError(CE_Failure, CPLE_OutOfMemory, "Too many tiles");
+        psInfo->nTilesPerRow = 0; /* to avoid int32 overflow in AIGClose() */
+        psInfo->nTilesPerColumn = 0;
         AIGClose( psInfo );
         return NULL;
     }
@@ -152,12 +163,11 @@ AIGInfo_t *AIGOpen( const char * pszInputName, const char * pszAccess )
 /* -------------------------------------------------------------------- */
 /*      Setup tile infos, but defer reading of tile data.               */
 /* -------------------------------------------------------------------- */
-    psInfo->pasTileInfo = (AIGTileInfo *) 
-        VSICalloc(sizeof(AIGTileInfo),
+    psInfo->pasTileInfo = (AIGTileInfo *)
+        VSI_CALLOC_VERBOSE(sizeof(AIGTileInfo),
                   psInfo->nTilesPerRow * psInfo->nTilesPerColumn);
     if (psInfo->pasTileInfo == NULL)
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate tile info array");
         AIGClose( psInfo );
         return NULL;
     }
@@ -184,6 +194,7 @@ CPLErr AIGAccessTile( AIGInfo_t *psInfo, int iTileX, int iTileY )
     char szBasename[20];
     char *pszFilename;
     AIGTileInfo *psTInfo;
+    const size_t nFilenameLen = strlen(psInfo->pszCoverName)+40;
 
 /* -------------------------------------------------------------------- */
 /*      Identify our tile.                                              */
@@ -204,21 +215,21 @@ CPLErr AIGAccessTile( AIGInfo_t *psInfo, int iTileX, int iTileY )
 /*      Compute the basename.                                           */
 /* -------------------------------------------------------------------- */
     if( iTileY == 0 )
-        sprintf( szBasename, "w%03d001", iTileX + 1 );
+        snprintf( szBasename, sizeof(szBasename), "w%03d001", iTileX + 1 );
     else if( iTileY == 1 )
-        sprintf( szBasename, "w%03d000", iTileX + 1 );
+        snprintf( szBasename, sizeof(szBasename), "w%03d000", iTileX + 1 );
     else
-        sprintf( szBasename, "z%03d%03d", iTileX + 1, iTileY - 1 );
-    
+        snprintf( szBasename, sizeof(szBasename), "z%03d%03d", iTileX + 1, iTileY - 1 );
+
 /* -------------------------------------------------------------------- */
 /*      Open the file w001001.adf file itself.                          */
 /* -------------------------------------------------------------------- */
-    pszFilename = (char *) CPLMalloc(strlen(psInfo->pszCoverName)+40);
-    sprintf( pszFilename, "%s/%s.adf", psInfo->pszCoverName, szBasename );
+    pszFilename = (char *) CPLMalloc(nFilenameLen);
+    snprintf( pszFilename, nFilenameLen, "%s/%s.adf", psInfo->pszCoverName, szBasename );
 
     psTInfo->fpGrid = AIGLLOpen( pszFilename, "rb" );
     psTInfo->bTriedToLoad = TRUE;
-    
+
     if( psTInfo->fpGrid == NULL )
     {
         CPLError( CE_Warning, CPLE_OpenFailed,
@@ -230,7 +241,7 @@ CPLErr AIGAccessTile( AIGInfo_t *psInfo, int iTileX, int iTileY )
 
     CPLFree( pszFilename );
     pszFilename = NULL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read the block index file.                                      */
 /* -------------------------------------------------------------------- */
@@ -251,7 +262,7 @@ CPLErr AIGReadTile( AIGInfo_t * psInfo, int nBlockXOff, int nBlockYOff,
     AIGTileInfo *psTInfo;
 
 /* -------------------------------------------------------------------- */
-/*      Compute our tile, and ensure it is accessable (open).  Then     */
+/*      Compute our tile, and ensure it is accessible (open).  Then     */
 /*      reduce block x/y values to be the block within that tile.       */
 /* -------------------------------------------------------------------- */
     iTileX = nBlockXOff / psInfo->nBlocksPerRow;
@@ -277,15 +288,15 @@ CPLErr AIGReadTile( AIGInfo_t * psInfo, int nBlockXOff, int nBlockYOff,
             panData[i] = ESRI_GRID_NO_DATA;
         return CE_None;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      validate block id.                                              */
 /* -------------------------------------------------------------------- */
     nBlockID = nBlockXOff + nBlockYOff * psInfo->nBlocksPerRow;
-    if( nBlockID < 0 
+    if( nBlockID < 0
         || nBlockID >= psInfo->nBlocksPerRow * psInfo->nBlocksPerColumn )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Illegal block requested." );
         return CE_Failure;
     }
@@ -293,14 +304,14 @@ CPLErr AIGReadTile( AIGInfo_t * psInfo, int nBlockXOff, int nBlockYOff,
     if( nBlockID >= psTInfo->nBlocks )
     {
         int i;
-        CPLDebug( "AIG", 
+        CPLDebug( "AIG",
                   "Request legal block, but from beyond end of block map.\n"
                   "Assuming all nodata." );
         for( i = psInfo->nBlockXSize * psInfo->nBlockYSize - 1; i >= 0; i-- )
             panData[i] = ESRI_GRID_NO_DATA;
         return CE_None;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read block.                                                     */
 /* -------------------------------------------------------------------- */
@@ -341,7 +352,7 @@ CPLErr AIGReadFloatTile( AIGInfo_t * psInfo, int nBlockXOff, int nBlockYOff,
     AIGTileInfo *psTInfo;
 
 /* -------------------------------------------------------------------- */
-/*      Compute our tile, and ensure it is accessable (open).  Then     */
+/*      Compute our tile, and ensure it is accessible (open).  Then     */
 /*      reduce block x/y values to be the block within that tile.       */
 /* -------------------------------------------------------------------- */
     iTileX = nBlockXOff / psInfo->nBlocksPerRow;
@@ -367,15 +378,15 @@ CPLErr AIGReadFloatTile( AIGInfo_t * psInfo, int nBlockXOff, int nBlockYOff,
             pafData[i] = ESRI_GRID_FLOAT_NO_DATA;
         return CE_None;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      validate block id.                                              */
 /* -------------------------------------------------------------------- */
     nBlockID = nBlockXOff + nBlockYOff * psInfo->nBlocksPerRow;
-    if( nBlockID < 0 
+    if( nBlockID < 0
         || nBlockID >= psInfo->nBlocksPerRow * psInfo->nBlocksPerColumn )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Illegal block requested." );
         return CE_Failure;
     }
@@ -383,14 +394,14 @@ CPLErr AIGReadFloatTile( AIGInfo_t * psInfo, int nBlockXOff, int nBlockYOff,
     if( nBlockID >= psTInfo->nBlocks )
     {
         int i;
-        CPLDebug( "AIG", 
+        CPLDebug( "AIG",
                   "Request legal block, but from beyond end of block map.\n"
                   "Assuming all nodata." );
         for( i = psInfo->nBlockXSize * psInfo->nBlockYSize - 1; i >= 0; i-- )
             pafData[i] = ESRI_GRID_FLOAT_NO_DATA;
         return CE_None;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read block.                                                     */
 /* -------------------------------------------------------------------- */
@@ -398,7 +409,7 @@ CPLErr AIGReadFloatTile( AIGInfo_t * psInfo, int nBlockXOff, int nBlockYOff,
                          psTInfo->panBlockOffset[nBlockID],
                          psTInfo->panBlockSize[nBlockID],
                          psInfo->nBlockXSize, psInfo->nBlockYSize,
-                         (GInt32 *) pafData, psInfo->nCellType, 
+                         (GInt32 *) pafData, psInfo->nCellType,
                          psInfo->bCompressed );
 
 /* -------------------------------------------------------------------- */
@@ -425,17 +436,20 @@ CPLErr AIGReadFloatTile( AIGInfo_t * psInfo, int nBlockXOff, int nBlockYOff,
 void AIGClose( AIGInfo_t * psInfo )
 
 {
-    int nTileCount = psInfo->nTilesPerRow * psInfo->nTilesPerColumn;
-    int iTile;
-
-    for( iTile = 0; iTile < nTileCount; iTile++ )
+    if( psInfo->pasTileInfo != NULL )
     {
-        if( psInfo->pasTileInfo[iTile].fpGrid )
+        int nTileCount = psInfo->nTilesPerRow * psInfo->nTilesPerColumn;
+        int iTile;
+
+        for( iTile = 0; iTile < nTileCount; iTile++ )
         {
-            VSIFCloseL( psInfo->pasTileInfo[iTile].fpGrid );
+            if( psInfo->pasTileInfo[iTile].fpGrid )
+            {
+                CPL_IGNORE_RET_VAL_INT(VSIFCloseL( psInfo->pasTileInfo[iTile].fpGrid ));
 
-            CPLFree( psInfo->pasTileInfo[iTile].panBlockOffset );
-            CPLFree( psInfo->pasTileInfo[iTile].panBlockSize );
+                CPLFree( psInfo->pasTileInfo[iTile].panBlockOffset );
+                CPLFree( psInfo->pasTileInfo[iTile].panBlockSize );
+            }
         }
     }
 
@@ -462,13 +476,13 @@ VSILFILE *AIGLLOpen( const char *pszFilename, const char *pszAccess )
         char *pszUCFilename = CPLStrdup(pszFilename);
         int  i;
 
-        for( i = strlen(pszUCFilename)-1; 
+        for( i = (int)strlen(pszUCFilename)-1;
              pszUCFilename[i] != '/' && pszUCFilename[i] != '\\';
              i-- )
         {
             pszUCFilename[i] = (char) toupper(pszUCFilename[i]);
         }
-        
+
         fp = VSIFOpenL( pszUCFilename, pszAccess );
 
         CPLFree( pszUCFilename );
@@ -476,4 +490,3 @@ VSILFILE *AIGLLOpen( const char *pszFilename, const char *pszAccess )
 
     return fp;
 }
-
diff --git a/frmts/aigrid/aigrid.h b/frmts/aigrid/aigrid.h
index db645ba..d131862 100644
--- a/frmts/aigrid/aigrid.h
+++ b/frmts/aigrid/aigrid.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: aigrid.h 22159 2011-04-14 18:18:54Z warmerdam $
+ * $Id: aigrid.h 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Arc/Info Binary Grid Translator
  * Purpose:  Grid file access include file.
@@ -27,14 +27,14 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _AIGRID_H_INCLUDED
-#define _AIGRID_H_INCLUDED
+#ifndef AIGRID_H_INCLUDED
+#define AIGRID_H_INCLUDED
 
 #include "cpl_conv.h"
 
 CPL_C_START
 
-#define ESRI_GRID_NO_DATA -2147483647				       
+#define ESRI_GRID_NO_DATA -2147483647
 /*#define ESRI_GRID_FLOAT_NO_DATA -340282306073709652508363335590014353408.0 */
 #define ESRI_GRID_FLOAT_NO_DATA -340282346638528859811704183484516925440.0
 
@@ -53,9 +53,9 @@ typedef struct {
 
 typedef struct {
     /* Private information */
-    
+
     AIGTileInfo *pasTileInfo;
-    
+
     int		bHasWarned;
 
     /* public information */
@@ -66,11 +66,11 @@ typedef struct {
     GInt32      bCompressed;
 
 #define AIG_CELLTYPE_INT		1
-#define AIG_CELLTYPE_FLOAT		2    
-    
+#define AIG_CELLTYPE_FLOAT		2
+
     GInt32	nBlockXSize;
     GInt32	nBlockYSize;
-    
+
     GInt32	nBlocksPerRow;
     GInt32	nBlocksPerColumn;
 
@@ -108,12 +108,12 @@ CPLErr AIGReadBlock( VSILFILE * fp, GUInt32 nBlockOffset, int nBlockSize,
                      int nCellType, int bCompressed );
 
 CPLErr AIGReadHeader( const char *, AIGInfo_t * );
-CPLErr AIGReadBlockIndex( AIGInfo_t *, AIGTileInfo *, 
+CPLErr AIGReadBlockIndex( AIGInfo_t *, AIGTileInfo *,
                           const char *pszBasename );
 CPLErr AIGReadBounds( const char *, AIGInfo_t * );
 CPLErr AIGReadStatistics( const char *, AIGInfo_t * );
 
-CPLErr DecompressCCITTRLETile( unsigned char *pabySrcData, int nSrcBytes, 
+CPLErr DecompressCCITTRLETile( unsigned char *pabySrcData, int nSrcBytes,
                                unsigned char *pabyDstData, int nDstBytes,
                                int nBlockXSize, int nBlockYSize );
 
@@ -132,4 +132,4 @@ VSILFILE           *AIGLLOpen( const char *, const char * );
 
 CPL_C_END
 
-#endif /* ndef _AIGRID_H_INCLUDED */
+#endif /* ndef AIGRID_H_INCLUDED */
diff --git a/frmts/aigrid/aigrid_format.html b/frmts/aigrid/aigrid_format.html
index 09a8b58..e414e81 100755
--- a/frmts/aigrid/aigrid_format.html
+++ b/frmts/aigrid/aigrid_format.html
@@ -12,20 +12,20 @@
 (<a href="mailto:warmerdam at pobox.com">warmerdam at pobox.com</a>)<p>
 
 The Arc/Info Binary Grid format is the internal working format of the
-Arc/Info Grid product.  It is also usable and creatable within the 
+Arc/Info Grid product.  It is also usable and creatable within the
 spatial analyst component of ArcView.  It is a tiled (blocked) format with run
 length compression capable of holding raster data of up to 4 byte integers
 or 4 byte floating data. <p>
 
-This format should not be confused with the Arc/Info ASCII Grid format 
+This format should not be confused with the Arc/Info ASCII Grid format
 which is the interchange format for grids.  Files can be converted between
 binary and ASCII format with the GRIDASCII and ASCIIGRID commands in
 Arc/Info.  This format is also different than the flat binary raster
 output of the GRIDFLOAT command.  The Arc/Info binary float, and ASCII
-formats are also accessable from within ArcView.<p>
+formats are also accessible from within ArcView.<p>
 
-This format should also not be confused with what I know as ESRI BIL format.  
-This is really a standard ESRI way of creating a header file (.HDR) 
+This format should also not be confused with what I know as ESRI BIL format.
+This is really a standard ESRI way of creating a header file (.HDR)
 describing the data layout a binary raster file containing raster data.<p>
 
 <!--------------------------------------------------------------------------->
@@ -44,10 +44,10 @@ versions.<p>
 <h2>File Set</h2>
 
 A grid coverage actually consists of a number of files.  A grid normally
-lives in it's own directory named after the grid.  For instance, the 
-grid <b>nwgrd1</b> lives in the directory <b>nwgrd1</b>, and has the following 
+lives in it's own directory named after the grid.  For instance, the
+grid <b>nwgrd1</b> lives in the directory <b>nwgrd1</b>, and has the following
 component files:<p>
- 
+
 <pre>
 -rwxr--r--   1 warmerda users          32 Jan 22 16:07 nwgrd1/dblbnd.adf
 -rwxr--r--   1 warmerda users         308 Jan 22 16:07 nwgrd1/hdr.adf
@@ -58,19 +58,19 @@ component files:<p>
 </pre>
 
 Sometimes datasets will also include a prj.adf files containing the projection
-definition in the usual ESRI format. Grids also normally have associated 
-tables in the info directory.  This is beyond the scope of my discussion 
+definition in the usual ESRI format. Grids also normally have associated
+tables in the info directory.  This is beyond the scope of my discussion
 for now.<p>
 
 The files have the following roles:
 
 <ul>
 
-<li> <a href="#dblbnd">dblbnd.adf</a>: Contains the bounds 
+<li> <a href="#dblbnd">dblbnd.adf</a>: Contains the bounds
 (LLX, LLY, URX, URY) of the portion of utilized portion of the grid.<p>
 
-<li> <a href="#hdr.adf">hdr.adf</a>: This is the header, and contains 
-information on the tile sizes, and number of tiles in the dataset.  It also 
+<li> <a href="#hdr.adf">hdr.adf</a>: This is the header, and contains
+information on the tile sizes, and number of tiles in the dataset.  It also
 contains assorted other information I have yet to identify.<p>
 
 <li> <a href="#sta">sta.adf</a>: This contains raster statistics.  In
@@ -81,15 +81,15 @@ the table corresponding integer raster values with a set of attributes.  I
 presume it is really just a pointer into info in a manner similar to the
 pat.adf file in a vector coverage, but I haven't investigated yet. <p>
 
-<li> <a href="#w001001">w001001.adf</a>: 
+<li> <a href="#w001001">w001001.adf</a>:
 This is the file containing the actual raster data.
 <p>
 
-<li> <a href="#w001001x">w001001x.adf</a>: 
-This is an index file containing pointers to 
+<li> <a href="#w001001x">w001001x.adf</a>:
+This is an index file containing pointers to
 each of the tiles in the w001001.adf raster file.<p>
 
-</ul> 
+</ul>
 
 <!--------------------------------------------------------------------------->
 
@@ -111,9 +111,9 @@ Fields:<p>
   </td><td> 8
   </td><td> MSB double
   </td><td> D_LLX
-  </td><td> Lower left X (easting) of the grid.  Generally -0.5 for an 
+  </td><td> Lower left X (easting) of the grid.  Generally -0.5 for an
 ungeoreferenced grid.
-  </td> 
+  </td>
 </tr>
 
 <tr>
@@ -121,9 +121,9 @@ ungeoreferenced grid.
   </td><td> 8
   </td><td> MSB double
   </td><td> D_LLY
-  </td><td> Lower left Y (northing) of the grid. Generally -0.5 for an 
+  </td><td> Lower left Y (northing) of the grid. Generally -0.5 for an
 ungeoreferenced grid.
-  </td> 
+  </td>
 </tr>
 
 <tr>
@@ -131,9 +131,9 @@ ungeoreferenced grid.
   </td><td> 8
   </td><td> MSB double
   </td><td> D_URX
-  </td><td> Upper right X (easting) of the grid. Generally #Pixels-0.5 for an 
+  </td><td> Upper right X (easting) of the grid. Generally #Pixels-0.5 for an
 ungeoreferenced grid.
-  </td> 
+  </td>
 </tr>
 
 <tr>
@@ -141,9 +141,9 @@ ungeoreferenced grid.
   </td><td> 8
   </td><td> MSB double
   </td><td> D_URY
-  </td><td> Upper right Y (northing) of the grid. Generally #Lines-0.5 for an 
+  </td><td> Upper right Y (northing) of the grid. Generally #Lines-0.5 for an
 ungeoreferenced grid.
-  </td> 
+  </td>
 </tr>
 
 </table>
@@ -194,7 +194,7 @@ Fields:<p>
 <tr>
   <td> 0
   </td><td> 8
-  </td><td> 
+  </td><td>
   </td><td> Magic Number (always hex 00 00 27 0A FF FF ** **, usually ending in FC 14, FB F8 or FC 08).
   </td>
 </tr>
@@ -202,7 +202,7 @@ Fields:<p>
 <tr>
   <td> 8
   </td><td> 16
-  </td><td> 
+  </td><td>
   </td><td> zero fill
   </td>
 </tr>
@@ -211,7 +211,7 @@ Fields:<p>
   <td> 24
   </td><td> 4
   </td><td> MSB Int32
-  </td><td> Size of whole file in shorts (multiply by two 
+  </td><td> Size of whole file in shorts (multiply by two
             to get file size in bytes).
   </td>
 </tr>
@@ -219,7 +219,7 @@ Fields:<p>
 <tr>
   <td> 28
   </td><td> 72
-  </td><td> 
+  </td><td>
   </td><td> zero fill
   </td>
 </tr>
@@ -265,7 +265,7 @@ Fields:<p>
   </td><td> MSB double
   </td><td> SMin
   </td><td> Minimum value of a raster cell in this grid.
-  </td> 
+  </td>
 </tr>
 
 <tr>
@@ -274,7 +274,7 @@ Fields:<p>
   </td><td> MSB double
   </td><td> SMax
   </td><td> Maximum value of a raster cell in this grid.
-  </td> 
+  </td>
 </tr>
 
 <tr>
@@ -283,7 +283,7 @@ Fields:<p>
   </td><td> MSB double
   </td><td> SMean
   </td><td> Mean value of a raster cells in this grid.
-  </td> 
+  </td>
 </tr>
 
 <tr>
@@ -292,7 +292,7 @@ Fields:<p>
   </td><td> MSB double
   </td><td> SStdDev
   </td><td> Standard deviation of raster cells in this grid.
-  </td> 
+  </td>
 </tr>
 
 </table>
@@ -343,7 +343,7 @@ Fields:<p>
 <tr>
   <td> 0
   </td><td> 8
-  </td><td> 
+  </td><td>
   </td><td> RMagic
   </td><td> Magic Number (always hex 00 00 27 0A FF FF ** **, usually ending in FC 14, FB F8 or FC 08).
   </td>
@@ -352,8 +352,8 @@ Fields:<p>
 <tr>
   <td> 8
   </td><td> 16
-  </td><td> 
-  </td><td> 
+  </td><td>
+  </td><td>
   </td><td> zero fill
   </td>
 </tr>
@@ -363,7 +363,7 @@ Fields:<p>
   </td><td> 4
   </td><td> MSB Int32
   </td><td> RFileSize
-  </td><td> Size of whole file in shorts (multiply by two 
+  </td><td> Size of whole file in shorts (multiply by two
             to get file size in bytes).
   </td>
 </tr>
@@ -371,8 +371,8 @@ Fields:<p>
 <tr>
   <td> 28
   </td><td> 72
-  </td><td> 
-  </td><td> 
+  </td><td>
+  </td><td>
   </td><td> zero fill
   </td>
 </tr>
@@ -395,7 +395,7 @@ is the value of this field.
   </td><td> byte
   </td><td> RTileType
   </td><td> Tile type code indicating the organization of the following
-data (integer coverages only).  
+data (integer coverages only).
   </td>
 </tr>
 <tr>
@@ -414,10 +414,10 @@ data (integer coverages only).
   </td><td> MSB Int (var size)
   </td><td> RMin
   </td><td> The minimum value pixels for this tile.  This number is added
-to the pixel values for each pixel in this tile (integer coverages only).  
+to the pixel values for each pixel in this tile (integer coverages only).
 I must stress that if RMinSize is less than 4 this is still a signed quantity.
 For instance, if RMinSize is 2, the value is 65536 - byte0*256 - byte1 if
-byte0 is > 127. 
+byte0 is > 127.
   </td>
 </tr>
 
@@ -446,23 +446,23 @@ bytes (zeros) for the RTileSize for that tile.<p>
 <h3>Raster Size</h3>
 
 The size of a the grid isn't as easy to deduce as one might expect.
-The hdr.adf file contains the HTilesPerRow, HTilesPerColumn, 
+The hdr.adf file contains the HTilesPerRow, HTilesPerColumn,
 HTileXSize, and HTileYSize fields which imply a particular raster
-space. However, it seems that this is created much larger than 
+space. However, it seems that this is created much larger than
 necessary to hold the users raster data.  I have created 3x1 rasters
 which resulted in the standard 8x512 tiles of 256x4 pixels each.<p>
 
 It seems that the user portion of the raster has to be computed
 based on the georeferenced bounds in the dblbnd.adf file (assumed
-to be anchored at the top left of the total raster space), and 
+to be anchored at the top left of the total raster space), and
 the HPixelSizeX, and HPixelSizeY fields from hdr.adf.<p>
 
 <b> #Pixels = (D_URX - D_LRX) / HPixelSizeX</b><p>
 <b> #Lines = (D_URY - D_LRY) / HPixelSizeY</b><p>
 
 Based on this number of pixels and lines, it is possible to establish
-what portion out of the top left of the raster is really <i>of 
-interest</i>.  All regions outside this appear to empty tiles, 
+what portion out of the top left of the raster is really <i>of
+interest</i>.  All regions outside this appear to empty tiles,
 or filled with no data markers.<p>
 
 <!------------------------------------------>
@@ -471,7 +471,7 @@ or filled with no data markers.<p>
 
 Each tile contains HBlockXSize * HBlockYSize pixels of data.  For floating
 point and uncompressed integer files the data is just the tile size (in two
-bytes) followed by the pixel data as 4 byte MSB order IEEE floating point 
+bytes) followed by the pixel data as 4 byte MSB order IEEE floating point
 words.  For compressed integer
 tiles it is necessary to interpret the RTileType to establish the details
 of the tile organization:
@@ -489,7 +489,7 @@ One full tile worth of data pixel values follows the RMin field, with
 
 <h4>RTileType = 0x04 (raw 4bit data)</h4>
 
-One full tiles worth of data pixel values follows the RMin field, with 
+One full tiles worth of data pixel values follows the RMin field, with
 4 bits per pixel.  The high order four bits of a byte comes before the low
 order four bits.<p>
 
@@ -500,12 +500,12 @@ RMin field.<p>
 
 <h4>RTileType = 0x10 (raw 16bit data)</h4>
 
-One full tiles worth of data pixel values follows the RMin field, with 
+One full tiles worth of data pixel values follows the RMin field, with
 16 bits per pixel (MSB).<p>
 
 <h4>RTileType = 0x20 (raw 32bit data)</h4>
 
-One full tiles worth of data pixel values follows the RMin field, with 
+One full tiles worth of data pixel values follows the RMin field, with
 32 bits per pixel (MSB).<p>
 
 <h4>RTileType = 0xCF (16 bit literal runs/nodata runs)</h4>
@@ -519,7 +519,7 @@ literal data with two MSB bytes per pixel. <p>
 
 <li> <b>Marker > 127</b>: The marker indicates that <b>256-Marker</b> pixels
 of <i>no data</i> pixels should be put into the output stream.  No data
-(other than the next marker) follows this marker. 
+(other than the next marker) follows this marker.
 
 </ul>
 
@@ -534,7 +534,7 @@ literal data with one byte per pixel. <p>
 
 <li> <b>Marker > 127</b>: The marker indicates that <b>256-Marker</b> pixels
 of <i>no data</i> pixels should be put into the output stream.  No data
-(other than the next marker) follows this marker. 
+(other than the next marker) follows this marker.
 
 </ul>
 
@@ -549,7 +549,7 @@ literal data with one byte per pixel. <p>
 
 <li> <b>Marker > 127</b>: The marker indicates that <b>256-Marker</b> pixels
 of <i>no data</i> pixels should be put into the output stream.  No data
-(other than the next marker) follows this marker. 
+(other than the next marker) follows this marker.
 
 </ul>
 
@@ -580,7 +580,7 @@ which should be interpreted as a <b>count</b>.  The following byte is the
 that <b>count</b> pixels of <b>value</b> should be inserted into the output
 stream.<p>
 
-The intepretation is the same for 0xFC, and 0xF8.  I believe that 0xFC has
+The interpretation is the same for 0xFC, and 0xF8.  I believe that 0xFC has
 a lower dynamic (2 bit) range than 0xF8 (4 or 8 bit).<p>
 
 <h4>RTileType = 0xFF (RMin CCITT RLE 1Bit)</h4>
@@ -620,7 +620,7 @@ file.<p>
      256: 3FF00000 00000000 3FF00000 00000000 ?~~~~~~~?~~~~~~~
      272: C08FFC00 00000000 C0A1BF00 00000000 ~~~~~~~~~~~~~~~~
      288: 00000008 00000200 00000100 00000001 ~~~~~~~~~~~~~~~~
-     304: 00000004                            ~~~~              
+     304: 00000004                            ~~~~
 </pre>
 
 Fields:<p>
@@ -638,7 +638,7 @@ Fields:<p>
   </td><td> Char
   </td><td> HMagic
   </td><td> Magic Number - always "GRID1.2\0"
-  </td> 
+  </td>
 </tr>
 
 <tr>
@@ -646,7 +646,7 @@ Fields:<p>
   </td><td> 8
   </td><td>  
   </td><td>  
-  </td><td> assorted data, I don't know the purpose. 
+  </td><td> assorted data, I don't know the purpose.
   </td>
 </tr>
 
@@ -673,7 +673,7 @@ Fields:<p>
   </td><td> 232
   </td><td>  
   </td><td>  
-  </td><td> assorted data, I don't know the purpose. 
+  </td><td> assorted data, I don't know the purpose.
   </td>
 </tr>
 
@@ -720,8 +720,8 @@ for ungeoreferenced rasters.
   </td><td> 4
   </td><td> MSB Int32
   </td><td> HTilesPerRow
-  </td><td> The width of the file in tiles (often 8 for files of 
-less than 2K in width). 
+  </td><td> The width of the file in tiles (often 8 for files of
+less than 2K in width).
   </td>
 </tr>
 
@@ -747,8 +747,8 @@ less than 2K in width).
   <td> 300
   </td><td> 4
   </td><td> MSB Int32
-  </td><td> 
-  </td><td> Unknown, usually 1. 
+  </td><td>
+  </td><td> Unknown, usually 1.
 </tr>
 
 <tr>
@@ -767,23 +767,23 @@ less than 2K in width).
 
 <h2>Acknowledgements</h2>
 
-I would like to thank <a href="http://www.geosoft.com/">Geosoft Inc.</a> 
+I would like to thank <a href="http://www.geosoft.com/">Geosoft Inc.</a>
 for partial funding of my research into this
 format.  I would also like to thank:<p>
 
 <ul>
 <li> Kenneth R. McVay for providing the statistics file format.
-<li> Noureddine Farah of ThinkSpace who dug up lots of datasets that caused 
+<li> Noureddine Farah of ThinkSpace who dug up lots of datasets that caused
 problems.
-<li> Luciano Fonseca who worked out RTileType 0x01. 
+<li> Luciano Fonseca who worked out RTileType 0x01.
 <li> Martin Manningham of Global Geomatics for additional problem sample files.
 <li> Harry Anderson of EDX Engineering, for showing me that floating point
-tiles don't have RTileType. 
+tiles don't have RTileType.
 <li> Ian Turton for supplying a sample files demonstrating the need to be
 careful with the sign of "short" RMin values.
 <li> Duncan Chaundy at PCI for poking hard till I finally deduced 0xFF tiles.
-<li> Stephen Cheeseman of GeoSoft for yet more problem files. 
-<li> Geoffrey Williams for a files demonstrating tile type 0x20.  
+<li> Stephen Cheeseman of GeoSoft for yet more problem files.
+<li> Geoffrey Williams for a files demonstrating tile type 0x20.
 </ul>
 
 </body>
diff --git a/frmts/aigrid/aitest.c b/frmts/aigrid/aitest.c
index a966ddc..cd26995 100644
--- a/frmts/aigrid/aitest.c
+++ b/frmts/aigrid/aitest.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: aitest.c 28039 2014-11-30 18:24:59Z rouault $
+ * $Id: aitest.c 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Arc/Info Binary Grid Translator
  * Purpose:  Test mainline for examining AIGrid files.
@@ -29,7 +29,7 @@
 
 #include "aigrid.h"
 
-CPL_CVSID("$Id: aitest.c 28039 2014-11-30 18:24:59Z rouault $");
+CPL_CVSID("$Id: aitest.c 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /*                             DumpMagic()                              */
@@ -49,7 +49,7 @@ static void DumpMagic( AIGInfo_t * psInfo, int bVerbose )
         int	bReport = bVerbose;
         unsigned char abyBlockSize[2];
         const char *pszMessage = "";
-        
+
         if( psTInfo->panBlockSize[i] == 0 )
             continue;
 
@@ -61,7 +61,7 @@ static void DumpMagic( AIGInfo_t * psInfo, int bVerbose )
             VSIFReadL( &byMagic, 1, 1, psTInfo->fpGrid );
 
             if( byMagic != 0 && byMagic != 0x43 && byMagic != 0x04
-                && byMagic != 0x08 && byMagic != 0x10 && byMagic != 0xd7 
+                && byMagic != 0x08 && byMagic != 0x10 && byMagic != 0xd7
                 && byMagic != 0xdf && byMagic != 0xe0 && byMagic != 0xfc
                 && byMagic != 0xf8 && byMagic != 0xff && byMagic != 0x41
                 && byMagic != 0x40 && byMagic != 0x42 && byMagic != 0xf0
@@ -77,7 +77,7 @@ static void DumpMagic( AIGInfo_t * psInfo, int bVerbose )
                 bReport = TRUE;
             }
 
-            if( (abyBlockSize[0] * 256 + abyBlockSize[1])*2 != 
+            if( (abyBlockSize[0] * 256 + abyBlockSize[1])*2 !=
                 psTInfo->panBlockSize[i] )
             {
                 pszMessage = "(block size in data doesn't match index)";
@@ -140,7 +140,7 @@ int main( int argc, char ** argv )
         argc--;
         argv++;
     }
-    
+
     if( argc < 2 ) {
         printf( "Usage: aitest [-magic] coverage [block numbers...]\n" );
         exit( 1 );
@@ -179,20 +179,20 @@ int main( int argc, char ** argv )
             psInfo->dfMax,
             psInfo->dfMean,
             psInfo->dfStdDev );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Do we want a dump of all the ``magic'' numbers for              */
-/*      instantated blocks?                                             */
+/*      instantiated blocks?                                            */
 /* -------------------------------------------------------------------- */
     if( !bSuppressMagic )
         DumpMagic( psInfo, bMagic );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read a block, and report it's contents.                         */
 /* -------------------------------------------------------------------- */
     panRaster = (GInt32 *)
         CPLMalloc(psInfo->nBlockXSize * psInfo->nBlockYSize * 4);
-    
+
     while( argc > 2 && (atoi(argv[2]) > 0 || argv[2][0] == '0') )
     {
         int	nBlock = atoi(argv[2]);
@@ -201,7 +201,7 @@ int main( int argc, char ** argv )
 
         argv++;
         argc--;
-        
+
         eErr = AIGReadBlock( psTInfo->fpGrid,
                              psTInfo->panBlockOffset[nBlock],
                              psTInfo->panBlockSize[nBlock],
@@ -215,7 +215,7 @@ int main( int argc, char ** argv )
             printf( "  Error! Skipping block.\n" );
             continue;
         }
-        
+
         for( j = 0; j < psInfo->nBlockYSize; j++ )
         {
             for( i = 0; i < psInfo->nBlockXSize; i++ )
@@ -231,7 +231,7 @@ int main( int argc, char ** argv )
                 else if( psInfo->nCellType == AIG_CELLTYPE_FLOAT )
                     printf( "%f ",
                             ((float *) panRaster)[i+j*psInfo->nBlockXSize] );
-                else 
+                else
                     printf( "%3d ", panRaster[i+j*psInfo->nBlockXSize] );
             }
             printf( "\n" );
diff --git a/frmts/aigrid/gridlib.c b/frmts/aigrid/gridlib.c
index b403dfd..48ad64e 100644
--- a/frmts/aigrid/gridlib.c
+++ b/frmts/aigrid/gridlib.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gridlib.c 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: gridlib.c 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Arc/Info Binary Grid Translator
  * Purpose:  Grid file reading code.
@@ -30,7 +30,9 @@
 
 #include "aigrid.h"
 
-CPL_CVSID("$Id: gridlib.c 27044 2014-03-16 23:41:27Z rouault $");
+CPL_CVSID("$Id: gridlib.c 33720 2016-03-15 00:39:53Z goatbar $");
+
+CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused) {}
 
 /************************************************************************/
 /*                    AIGProcessRaw32bitFloatBlock()                    */
@@ -38,7 +40,7 @@ CPL_CVSID("$Id: gridlib.c 27044 2014-03-16 23:41:27Z rouault $");
 /*      Process a block using ``00'' (32 bit) raw format.               */
 /************************************************************************/
 
-static 
+static
 CPLErr AIGProcessRaw32BitFloatBlock( GByte *pabyCur, int nDataSize, int nMin,
                                      int nBlockXSize, int nBlockYSize,
                                      float * pafData )
@@ -52,7 +54,7 @@ CPLErr AIGProcessRaw32BitFloatBlock( GByte *pabyCur, int nDataSize, int nMin,
         CPLError(CE_Failure, CPLE_AppDefined, "Block too small");
         return CE_Failure;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Collect raw data.                                               */
 /* -------------------------------------------------------------------- */
@@ -71,7 +73,7 @@ CPLErr AIGProcessRaw32BitFloatBlock( GByte *pabyCur, int nDataSize, int nMin,
         ((GByte *) &fWork)[2] = *(pabyCur++);
         ((GByte *) &fWork)[3] = *(pabyCur++);
 #endif
-        
+
         pafData[i] = fWork;
     }
 
@@ -84,7 +86,7 @@ CPLErr AIGProcessRaw32BitFloatBlock( GByte *pabyCur, int nDataSize, int nMin,
 /*      Process a block using ``00'' constant 32bit integer format.     */
 /************************************************************************/
 
-static 
+static
 CPLErr AIGProcessIntConstBlock( GByte *pabyCur, int nDataSize, int nMin,
                                 int nBlockXSize, int nBlockYSize,
                                 GInt32 * panData )
@@ -94,7 +96,7 @@ CPLErr AIGProcessIntConstBlock( GByte *pabyCur, int nDataSize, int nMin,
 
     (void) pabyCur;
     (void) nDataSize;
-    
+
 /* -------------------------------------------------------------------- */
 /*	Apply constant min value.					*/
 /* -------------------------------------------------------------------- */
@@ -104,13 +106,30 @@ CPLErr AIGProcessIntConstBlock( GByte *pabyCur, int nDataSize, int nMin,
     return( CE_None );
 }
 
+/**********************************************************************
+ *                       AIGSaturatedAdd()
+ ***********************************************************************/
+
+static GInt32 AIGSaturatedAdd(GInt32 nVal, GInt32 nAdd)
+{
+    if( nAdd >= 0 && nVal > INT_MAX - nAdd )
+        nVal = INT_MAX;
+    else if( nAdd == INT_MIN && nVal < 0 )
+        nVal = INT_MIN;
+    else if( nAdd != INT_MIN && nAdd < 0 && nVal < INT_MIN - nAdd )
+        nVal = INT_MIN;
+    else
+        nVal += nAdd;
+    return nVal;
+}
+
 /************************************************************************/
 /*                         AIGProcess32bitRawBlock()                    */
 /*                                                                      */
-/*      Process a block using ``20'' (thirtytwo bit) raw format.        */
+/*      Process a block using ``20'' (thirty two bit) raw format.        */
 /************************************************************************/
 
-static 
+static
 CPLErr AIGProcessRaw32BitBlock( GByte *pabyCur, int nDataSize, int nMin,
                                 int nBlockXSize, int nBlockYSize,
                                 GInt32 * panData )
@@ -123,16 +142,15 @@ CPLErr AIGProcessRaw32BitBlock( GByte *pabyCur, int nDataSize, int nMin,
         CPLError(CE_Failure, CPLE_AppDefined, "Block too small");
         return CE_Failure;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Collect raw data.                                               */
 /* -------------------------------------------------------------------- */
     for( i = 0; i < nBlockXSize * nBlockYSize; i++ )
     {
-        panData[i] = pabyCur[0] * 256 * 256 * 256
-            + pabyCur[1] * 256 * 256
-            + pabyCur[2] * 256 
-            + pabyCur[3] + nMin;
+        memcpy(panData + i, pabyCur, 4);
+        panData[i] = CPL_MSBWORD32(panData[i]);
+        panData[i] = AIGSaturatedAdd(panData[i], nMin);
         pabyCur += 4;
     }
 
@@ -145,7 +163,7 @@ CPLErr AIGProcessRaw32BitBlock( GByte *pabyCur, int nDataSize, int nMin,
 /*      Process a block using ``10'' (sixteen bit) raw format.          */
 /************************************************************************/
 
-static 
+static
 CPLErr AIGProcessRaw16BitBlock( GByte *pabyCur, int nDataSize, int nMin,
                                 int nBlockXSize, int nBlockYSize,
                                 GInt32 * panData )
@@ -158,7 +176,7 @@ CPLErr AIGProcessRaw16BitBlock( GByte *pabyCur, int nDataSize, int nMin,
         CPLError(CE_Failure, CPLE_AppDefined, "Block too small");
         return CE_Failure;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Collect raw data.                                               */
 /* -------------------------------------------------------------------- */
@@ -177,7 +195,7 @@ CPLErr AIGProcessRaw16BitBlock( GByte *pabyCur, int nDataSize, int nMin,
 /*      Process a block using ``08'' raw format.                        */
 /************************************************************************/
 
-static 
+static
 CPLErr AIGProcessRaw4BitBlock( GByte *pabyCur, int nDataSize, int nMin,
                                int nBlockXSize, int nBlockYSize,
                                GInt32 * panData )
@@ -189,8 +207,8 @@ CPLErr AIGProcessRaw4BitBlock( GByte *pabyCur, int nDataSize, int nMin,
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Block too small");
         return CE_Failure;
-    } 
-    
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Collect raw data.                                               */
 /* -------------------------------------------------------------------- */
@@ -211,7 +229,7 @@ CPLErr AIGProcessRaw4BitBlock( GByte *pabyCur, int nDataSize, int nMin,
 /*      Process a block using ``0x01'' raw format.                      */
 /************************************************************************/
 
-static 
+static
 CPLErr AIGProcessRaw1BitBlock( GByte *pabyCur, int nDataSize, int nMin,
                                int nBlockXSize, int nBlockYSize,
                                GInt32 * panData )
@@ -224,7 +242,7 @@ CPLErr AIGProcessRaw1BitBlock( GByte *pabyCur, int nDataSize, int nMin,
         CPLError(CE_Failure, CPLE_AppDefined, "Block too small");
         return CE_Failure;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Collect raw data.                                               */
 /* -------------------------------------------------------------------- */
@@ -245,7 +263,7 @@ CPLErr AIGProcessRaw1BitBlock( GByte *pabyCur, int nDataSize, int nMin,
 /*      Process a block using ``08'' raw format.                        */
 /************************************************************************/
 
-static 
+static
 CPLErr AIGProcessRawBlock( GByte *pabyCur, int nDataSize, int nMin,
                         int nBlockXSize, int nBlockYSize, GInt32 * panData )
 
@@ -257,7 +275,7 @@ CPLErr AIGProcessRawBlock( GByte *pabyCur, int nDataSize, int nMin,
         CPLError(CE_Failure, CPLE_AppDefined, "Block too small");
         return CE_Failure;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Collect raw data.                                               */
 /* -------------------------------------------------------------------- */
@@ -275,7 +293,7 @@ CPLErr AIGProcessRawBlock( GByte *pabyCur, int nDataSize, int nMin,
 /*      Process a type 0xFF (CCITT RLE) compressed block.               */
 /************************************************************************/
 
-static 
+static
 CPLErr AIGProcessFFBlock( GByte *pabyCur, int nDataSize, int nMin,
                           int nBlockXSize, int nBlockYSize,
                           GInt32 * panData )
@@ -288,15 +306,13 @@ CPLErr AIGProcessFFBlock( GByte *pabyCur, int nDataSize, int nMin,
     int i, nDstBytes = (nBlockXSize * nBlockYSize + 7) / 8;
     unsigned char *pabyIntermediate;
 
-    pabyIntermediate = (unsigned char *) VSIMalloc(nDstBytes);
+    pabyIntermediate = (unsigned char *) VSI_MALLOC_VERBOSE(nDstBytes);
     if (pabyIntermediate == NULL)
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory,
-                 "Cannot allocate %d bytes", nDstBytes);
         return CE_Failure;
     }
-    
-    eErr = DecompressCCITTRLETile( pabyCur, nDataSize, 
+
+    eErr = DecompressCCITTRLETile( pabyCur, nDataSize,
                                    pabyIntermediate, nDstBytes,
                                    nBlockXSize, nBlockYSize );
     if( eErr != CE_None )
@@ -330,8 +346,8 @@ CPLErr AIGProcessFFBlock( GByte *pabyCur, int nDataSize, int nMin,
 /*      Process a block using ``D7'', ``E0'' or ``DF'' compression.     */
 /************************************************************************/
 
-static 
-CPLErr AIGProcessBlock( GByte *pabyCur, int nDataSize, int nMin, int nMagic, 
+static
+CPLErr AIGProcessBlock( GByte *pabyCur, int nDataSize, int nMin, int nMagic,
                         int nBlockXSize, int nBlockYSize, GInt32 * panData )
 
 {
@@ -349,22 +365,22 @@ CPLErr AIGProcessBlock( GByte *pabyCur, int nDataSize, int nMin, int nMagic,
         int	nMarker = *(pabyCur++);
 
         nDataSize--;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Repeat data - four byte data block (0xE0)                       */
 /* -------------------------------------------------------------------- */
         if( nMagic == 0xE0 )
         {
             GInt32	nValue;
-            
+
             if( nMarker + nPixels > nTotPixels )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                          "Run too long in AIGProcessBlock, needed %d values, got %d.", 
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Run too long in AIGProcessBlock, needed %d values, got %d.",
                           nTotPixels - nPixels, nMarker );
                 return CE_Failure;
             }
-        
+
             if( nDataSize < 4 )
             {
                 CPLError(CE_Failure, CPLE_AppDefined, "Block too small");
@@ -382,18 +398,18 @@ CPLErr AIGProcessBlock( GByte *pabyCur, int nDataSize, int nMin, int nMagic,
             for( i = 0; i < nMarker; i++ )
                 panData[nPixels++] = nValue;
         }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Repeat data - two byte data block (0xF0)                        */
 /* -------------------------------------------------------------------- */
         else if( nMagic == 0xF0 )
         {
             GInt32	nValue;
-            
+
             if( nMarker + nPixels > nTotPixels )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                          "Run too long in AIGProcessBlock, needed %d values, got %d.", 
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Run too long in AIGProcessBlock, needed %d values, got %d.",
                           nTotPixels - nPixels, nMarker );
                 return CE_Failure;
             }
@@ -411,7 +427,7 @@ CPLErr AIGProcessBlock( GByte *pabyCur, int nDataSize, int nMin, int nMagic,
             for( i = 0; i < nMarker; i++ )
                 panData[nPixels++] = nValue;
         }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Repeat data - one byte data block (0xFC)                        */
 /* -------------------------------------------------------------------- */
@@ -421,25 +437,25 @@ CPLErr AIGProcessBlock( GByte *pabyCur, int nDataSize, int nMin, int nMagic,
 
             if( nMarker + nPixels > nTotPixels )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                          "Run too long in AIGProcessBlock, needed %d values, got %d.", 
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Run too long in AIGProcessBlock, needed %d values, got %d.",
                           nTotPixels - nPixels, nMarker );
                 return CE_Failure;
             }
-            
+
             if( nDataSize < 1 )
             {
                 CPLError(CE_Failure, CPLE_AppDefined, "Block too small");
                 return CE_Failure;
             }
-        
+
             nValue = *(pabyCur++) + nMin;
             nDataSize--;
-            
+
             for( i = 0; i < nMarker; i++ )
                 panData[nPixels++] = nValue;
         }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Repeat data - no actual data, just assign minimum (0xDF)        */
 /* -------------------------------------------------------------------- */
@@ -447,16 +463,16 @@ CPLErr AIGProcessBlock( GByte *pabyCur, int nDataSize, int nMin, int nMagic,
         {
             if( nMarker + nPixels > nTotPixels )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                          "Run too long in AIGProcessBlock, needed %d values, got %d.", 
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Run too long in AIGProcessBlock, needed %d values, got %d.",
                           nTotPixels - nPixels, nMarker );
                 return CE_Failure;
             }
-        
+
             for( i = 0; i < nMarker; i++ )
                 panData[nPixels++] = nMin;
         }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Literal data (0xD7): 8bit values.                               */
 /* -------------------------------------------------------------------- */
@@ -464,12 +480,12 @@ CPLErr AIGProcessBlock( GByte *pabyCur, int nDataSize, int nMin, int nMagic,
         {
             if( nMarker + nPixels > nTotPixels )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                          "Run too long in AIGProcessBlock, needed %d values, got %d.", 
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Run too long in AIGProcessBlock, needed %d values, got %d.",
                           nTotPixels - nPixels, nMarker );
                 return CE_Failure;
             }
-        
+
             while( nMarker > 0 && nDataSize > 0 )
             {
                 panData[nPixels++] = *(pabyCur++) + nMin;
@@ -484,15 +500,15 @@ CPLErr AIGProcessBlock( GByte *pabyCur, int nDataSize, int nMin, int nMagic,
         else if( nMagic == 0xCF && nMarker < 128 )
         {
             GInt32	nValue;
-            
+
             if( nMarker + nPixels > nTotPixels )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                          "Run too long in AIGProcessBlock, needed %d values, got %d.", 
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Run too long in AIGProcessBlock, needed %d values, got %d.",
                           nTotPixels - nPixels, nMarker );
                 return CE_Failure;
             }
-        
+
             while( nMarker > 0 && nDataSize >= 2 )
             {
                 nValue = pabyCur[0] * 256 + pabyCur[1] + nMin;
@@ -513,12 +529,12 @@ CPLErr AIGProcessBlock( GByte *pabyCur, int nDataSize, int nMin, int nMagic,
 
             if( nMarker + nPixels > nTotPixels )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                          "Run too long in AIGProcessBlock, needed %d values, got %d.", 
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Run too long in AIGProcessBlock, needed %d values, got %d.",
                           nTotPixels - nPixels, nMarker );
                 return CE_Failure;
             }
-        
+
             while( nMarker > 0 )
             {
                 panData[nPixels++] = ESRI_GRID_NO_DATA;
@@ -535,12 +551,12 @@ CPLErr AIGProcessBlock( GByte *pabyCur, int nDataSize, int nMin, int nMagic,
 
     if( nPixels < nTotPixels || nDataSize < 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Ran out of data processing block with nMagic=%d.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Ran out of data processing block with nMagic=%d.",
                   nMagic );
         return CE_Failure;
     }
-    
+
     return CE_None;
 }
 
@@ -570,7 +586,7 @@ CPLErr AIGReadBlock( VSILFILE * fp, GUInt32 nBlockOffset, int nBlockSize,
 
         return( CE_None );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read the block into memory.                                     */
 /* -------------------------------------------------------------------- */
@@ -587,12 +603,12 @@ CPLErr AIGReadBlock( VSILFILE * fp, GUInt32 nBlockOffset, int nBlockSize,
         return CE_Failure;
     }
 
-    if( VSIFSeekL( fp, nBlockOffset, SEEK_SET ) != 0 
+    if( VSIFSeekL( fp, nBlockOffset, SEEK_SET ) != 0
         || VSIFReadL( pabyRaw, nBlockSize+2, 1, fp ) != 1 )
     {
         memset( panData, 0, nBlockXSize*nBlockYSize*4 );
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Read of %d bytes from offset %d for grid block failed.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Read of %d bytes from offset %d for grid block failed.",
                   nBlockSize+2, nBlockOffset );
         CPLFree( pabyRaw );
         return CE_Failure;
@@ -604,22 +620,22 @@ CPLErr AIGReadBlock( VSILFILE * fp, GUInt32 nBlockOffset, int nBlockSize,
     if( nBlockSize != (pabyRaw[0]*256 + pabyRaw[1])*2 )
     {
         memset( panData, 0, nBlockXSize*nBlockYSize*4 );
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Block is corrupt, block size was %d, but expected to be %d.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Block is corrupt, block size was %d, but expected to be %d.",
                   (pabyRaw[0]*256 + pabyRaw[1])*2, nBlockSize );
         CPLFree( pabyRaw );
         return CE_Failure;
     }
 
     nDataSize = nBlockSize;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Handle float files and uncompressed integer files directly.     */
 /* -------------------------------------------------------------------- */
     if( nCellType == AIG_CELLTYPE_FLOAT )
     {
-        AIGProcessRaw32BitFloatBlock( pabyRaw + 2, nDataSize, 0, 
-                                      nBlockXSize, nBlockYSize, 
+        AIGProcessRaw32BitFloatBlock( pabyRaw + 2, nDataSize, 0,
+                                      nBlockXSize, nBlockYSize,
                                       (float *) panData );
         CPLFree( pabyRaw );
 
@@ -670,8 +686,8 @@ CPLErr AIGReadBlock( VSILFILE * fp, GUInt32 nBlockOffset, int nBlockSize,
     if( nMinSize > 4 )
     {
         memset( panData, 0, nBlockXSize*nBlockYSize*4 );
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Corrupt 'minsize' of %d in block header.  Read aborted.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Corrupt 'minsize' of %d in block header.  Read aborted.",
                   nMinSize );
         CPLFree( pabyRaw );
         return CE_Failure;
@@ -704,13 +720,13 @@ CPLErr AIGReadBlock( VSILFILE * fp, GUInt32 nBlockOffset, int nBlockSize,
                 nMin = nMin - 256*256*256;
         }
     }
-    
+
     nDataSize -= nMinSize;
-    
+
 /* -------------------------------------------------------------------- */
-/*	Call an apppropriate handler depending on magic code.		*/
+/*	Call an appropriate handler depending on magic code.		*/
 /* -------------------------------------------------------------------- */
-
+    eErr = CE_None;
     if( nMagic == 0x08 )
     {
         AIGProcessRawBlock( pabyCur, nDataSize, nMin,
@@ -748,7 +764,7 @@ CPLErr AIGReadBlock( VSILFILE * fp, GUInt32 nBlockOffset, int nBlockSize,
     }
     else if( nMagic == 0xFF )
     {
-        AIGProcessFFBlock( pabyCur, nDataSize, nMin,
+        eErr = AIGProcessFFBlock( pabyCur, nDataSize, nMin,
                            nBlockXSize, nBlockYSize,
                            panData );
     }
@@ -756,11 +772,11 @@ CPLErr AIGReadBlock( VSILFILE * fp, GUInt32 nBlockOffset, int nBlockSize,
     {
         eErr = AIGProcessBlock( pabyCur, nDataSize, nMin, nMagic,
                                 nBlockXSize, nBlockYSize, panData );
-        
+
         if( eErr == CE_Failure )
         {
             static int	bHasWarned = FALSE;
-            
+
             for( i = 0; i < nBlockXSize * nBlockYSize; i++ )
                 panData[i] = ESRI_GRID_NO_DATA;
 
@@ -779,7 +795,7 @@ CPLErr AIGReadBlock( VSILFILE * fp, GUInt32 nBlockOffset, int nBlockSize,
 
     CPLFree( pabyRaw );
 
-    return CE_None;
+    return eErr;
 }
 
 /************************************************************************/
@@ -795,15 +811,16 @@ CPLErr AIGReadHeader( const char * pszCoverName, AIGInfo_t * psInfo )
     char	*pszHDRFilename;
     VSILFILE	*fp;
     GByte	abyData[308];
+    const size_t nHDRFilenameLen = strlen(pszCoverName)+30;
 
 /* -------------------------------------------------------------------- */
 /*      Open the file hdr.adf file.                                     */
 /* -------------------------------------------------------------------- */
-    pszHDRFilename = (char *) CPLMalloc(strlen(pszCoverName)+30);
-    sprintf( pszHDRFilename, "%s/hdr.adf", pszCoverName );
+    pszHDRFilename = (char *) CPLMalloc(nHDRFilenameLen);
+    snprintf( pszHDRFilename, nHDRFilenameLen, "%s/hdr.adf", pszCoverName );
 
     fp = AIGLLOpen( pszHDRFilename, "rb" );
-    
+
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
@@ -820,10 +837,14 @@ CPLErr AIGReadHeader( const char * pszCoverName, AIGInfo_t * psInfo )
 /*      long.                                                           */
 /* -------------------------------------------------------------------- */
 
-    VSIFReadL( abyData, 1, 308, fp );
+    if( VSIFReadL( abyData, 1, 308, fp ) != 308 )
+    {
+        CPL_IGNORE_RET_VAL_INT(VSIFCloseL( fp ));
+        return( CE_Failure );
+    }
+
+    CPL_IGNORE_RET_VAL_INT(VSIFCloseL( fp ));
 
-    VSIFCloseL( fp );
-    
 /* -------------------------------------------------------------------- */
 /*      Read the block size information.                                */
 /* -------------------------------------------------------------------- */
@@ -835,7 +856,7 @@ CPLErr AIGReadHeader( const char * pszCoverName, AIGInfo_t * psInfo )
     memcpy( &(psInfo->nBlockYSize), abyData+304, 4 );
     memcpy( &(psInfo->dfCellSizeX), abyData+256, 8 );
     memcpy( &(psInfo->dfCellSizeY), abyData+264, 8 );
-    
+
 #ifdef CPL_LSB
     psInfo->nCellType = CPL_SWAP32( psInfo->nCellType );
     psInfo->bCompressed = CPL_SWAP32( psInfo->bCompressed );
@@ -859,25 +880,26 @@ CPLErr AIGReadHeader( const char * pszCoverName, AIGInfo_t * psInfo )
 /*      structure with the block offsets, and sizes.                    */
 /************************************************************************/
 
-CPLErr AIGReadBlockIndex( AIGInfo_t * psInfo, AIGTileInfo *psTInfo, 
+CPLErr AIGReadBlockIndex( AIGInfo_t * psInfo, AIGTileInfo *psTInfo,
                           const char *pszBasename )
 
 {
     char	*pszHDRFilename;
     VSILFILE	*fp;
-    int		nLength, i;
-    GInt32	nValue;
+    int		i;
+    GUInt32	nValue, nLength;
     GUInt32	*panIndex;
     GByte       abyHeader[8];
+    const size_t nHDRFilenameLen = strlen(psInfo->pszCoverName)+40;
 
 /* -------------------------------------------------------------------- */
 /*      Open the file hdr.adf file.                                     */
 /* -------------------------------------------------------------------- */
-    pszHDRFilename = (char *) CPLMalloc(strlen(psInfo->pszCoverName)+40);
-    sprintf( pszHDRFilename, "%s/%sx.adf", psInfo->pszCoverName, pszBasename );
+    pszHDRFilename = (char *) CPLMalloc(nHDRFilenameLen);
+    snprintf( pszHDRFilename, nHDRFilenameLen, "%s/%sx.adf", psInfo->pszCoverName, pszBasename );
 
     fp = AIGLLOpen( pszHDRFilename, "rb" );
-    
+
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
@@ -894,74 +916,94 @@ CPLErr AIGReadBlockIndex( AIGInfo_t * psInfo, AIGTileInfo *psTInfo,
 /*      Verify the magic number.  This is often corrupted by CR/LF      */
 /*      translation.                                                    */
 /* -------------------------------------------------------------------- */
-    VSIFReadL( abyHeader, 1, 8, fp );
+    if( VSIFReadL( abyHeader, 1, 8, fp ) != 8 )
+    {
+        CPL_IGNORE_RET_VAL_INT(VSIFCloseL( fp ));
+        return CE_Failure;
+    }
     if( abyHeader[3] == 0x0D && abyHeader[4] == 0x0A )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "w001001x.adf file header has been corrupted by unix to dos text conversion." );
-        VSIFCloseL( fp );
+        CPL_IGNORE_RET_VAL_INT(VSIFCloseL( fp ));
         return CE_Failure;
     }
 
     if( abyHeader[0] != 0x00
-        || abyHeader[1] != 0x00 
+        || abyHeader[1] != 0x00
         || abyHeader[2] != 0x27
         || abyHeader[3] != 0x0A
         || abyHeader[4] != 0xFF
         || abyHeader[5] != 0xFF )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "w001001x.adf file header magic number is corrupt." );
-        VSIFCloseL( fp );
+        CPL_IGNORE_RET_VAL_INT(VSIFCloseL( fp ));
         return CE_Failure;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Get the file length (in 2 byte shorts)                          */
 /* -------------------------------------------------------------------- */
-    VSIFSeekL( fp, 24, SEEK_SET );
-    VSIFReadL( &nValue, 1, 4, fp );
+    if( VSIFSeekL( fp, 24, SEEK_SET ) != 0 ||
+        VSIFReadL( &nValue, 1, 4, fp ) != 4 )
+    {
+        CPL_IGNORE_RET_VAL_INT(VSIFCloseL( fp ));
+        return CE_Failure;
+    }
 
-    // FIXME? : risk of overflow in multiplication
-    nLength = CPL_MSBWORD32(nValue) * 2;
+    nValue = CPL_MSBWORD32(nValue);
+    if( nValue > INT_MAX )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "AIGReadBlockIndex: Bad length");
+        CPL_IGNORE_RET_VAL_INT(VSIFCloseL( fp ));
+        return CE_Failure;
+    }
+    nLength = nValue * 2;
+    if( nLength <= 100 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "AIGReadBlockIndex: Bad length");
+        CPL_IGNORE_RET_VAL_INT(VSIFCloseL( fp ));
+        return CE_Failure;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Allocate buffer, and read the file (from beyond the header)     */
 /*      into the buffer.                                                */
 /* -------------------------------------------------------------------- */
     psTInfo->nBlocks = (nLength-100) / 8;
-    panIndex = (GUInt32 *) VSIMalloc2(psTInfo->nBlocks, 8);
+    panIndex = (GUInt32 *) VSI_MALLOC2_VERBOSE(psTInfo->nBlocks, 8);
     if (panIndex == NULL)
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory,
-                 "AIGReadBlockIndex: Out of memory. Probably due to corrupted w001001x.adf file");
-        VSIFCloseL( fp );
+        CPL_IGNORE_RET_VAL_INT(VSIFCloseL( fp ));
         return CE_Failure;
     }
-    VSIFSeekL( fp, 100, SEEK_SET );
-    if ((int)VSIFReadL( panIndex, 8, psTInfo->nBlocks, fp ) != psTInfo->nBlocks)
+    if( VSIFSeekL( fp, 100, SEEK_SET ) != 0 ||
+        (int)VSIFReadL( panIndex, 8, psTInfo->nBlocks, fp ) != psTInfo->nBlocks)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "AIGReadBlockIndex: Cannot read block info");
-        VSIFCloseL( fp );
+        CPL_IGNORE_RET_VAL_INT(VSIFCloseL( fp ));
         CPLFree( panIndex );
         return CE_Failure;
     }
 
-    VSIFCloseL( fp );
+    CPL_IGNORE_RET_VAL_INT(VSIFCloseL( fp ));
 
 /* -------------------------------------------------------------------- */
 /*	Allocate AIGInfo block info arrays.				*/
 /* -------------------------------------------------------------------- */
-    psTInfo->panBlockOffset = (GUInt32 *) VSIMalloc2(4, psTInfo->nBlocks);
-    psTInfo->panBlockSize = (int *) VSIMalloc2(4, psTInfo->nBlocks);
-    if (psTInfo->panBlockOffset == NULL || 
+    psTInfo->panBlockOffset = (GUInt32 *) VSI_MALLOC2_VERBOSE(4, psTInfo->nBlocks);
+    psTInfo->panBlockSize = (int *) VSI_MALLOC2_VERBOSE(4, psTInfo->nBlocks);
+    if (psTInfo->panBlockOffset == NULL ||
         psTInfo->panBlockSize == NULL)
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory,
-                 "AIGReadBlockIndex: Out of memory. Probably due to corrupted w001001x.adf file");
         CPLFree( psTInfo->panBlockOffset );
         CPLFree( psTInfo->panBlockSize );
+        psTInfo->panBlockOffset = NULL;
+        psTInfo->panBlockSize = NULL;
         CPLFree( panIndex );
         return CE_Failure;
     }
@@ -971,8 +1013,35 @@ CPLErr AIGReadBlockIndex( AIGInfo_t * psInfo, AIGTileInfo *psTInfo,
 /* -------------------------------------------------------------------- */
     for( i = 0; i < psTInfo->nBlocks; i++ )
     {
-        psTInfo->panBlockOffset[i] = CPL_MSBWORD32(panIndex[i*2]) * 2;
-        psTInfo->panBlockSize[i] = CPL_MSBWORD32(panIndex[i*2+1]) * 2;
+        GUInt32 nVal;
+
+        nVal = CPL_MSBWORD32(panIndex[i*2]);
+        if( nVal >= INT_MAX )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "AIGReadBlockIndex: Bad offset for block %d", i);
+            CPLFree( psTInfo->panBlockOffset );
+            CPLFree( psTInfo->panBlockSize );
+            psTInfo->panBlockOffset = NULL;
+            psTInfo->panBlockSize = NULL;
+            CPLFree( panIndex );
+            return CE_Failure;
+        }
+        psTInfo->panBlockOffset[i] = nVal * 2;
+
+        nVal = CPL_MSBWORD32(panIndex[i*2+1]);
+        if( nVal >= INT_MAX / 2 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "AIGReadBlockIndex: Bad size for block %d", i);
+            CPLFree( psTInfo->panBlockOffset );
+            CPLFree( psTInfo->panBlockSize );
+            psTInfo->panBlockOffset = NULL;
+            psTInfo->panBlockSize = NULL;
+            CPLFree( panIndex );
+            return CE_Failure;
+        }
+        psTInfo->panBlockSize[i] = nVal * 2;
     }
 
     CPLFree( panIndex );
@@ -992,15 +1061,16 @@ CPLErr AIGReadBounds( const char * pszCoverName, AIGInfo_t * psInfo )
     char	*pszHDRFilename;
     VSILFILE	*fp;
     double	adfBound[4];
+    const size_t nHDRFilenameLen = strlen(pszCoverName)+40;
 
 /* -------------------------------------------------------------------- */
 /*      Open the file dblbnd.adf file.                                  */
 /* -------------------------------------------------------------------- */
-    pszHDRFilename = (char *) CPLMalloc(strlen(pszCoverName)+40);
-    sprintf( pszHDRFilename, "%s/dblbnd.adf", pszCoverName );
+    pszHDRFilename = (char *) CPLMalloc(nHDRFilenameLen);
+    snprintf( pszHDRFilename, nHDRFilenameLen, "%s/dblbnd.adf", pszCoverName );
 
     fp = AIGLLOpen( pszHDRFilename, "rb" );
-    
+
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
@@ -1016,17 +1086,21 @@ CPLErr AIGReadBounds( const char * pszCoverName, AIGInfo_t * psInfo )
 /* -------------------------------------------------------------------- */
 /*      Get the contents - four doubles.                                */
 /* -------------------------------------------------------------------- */
-    VSIFReadL( adfBound, 1, 32, fp );
+    if( VSIFReadL( adfBound, 1, 32, fp ) != 32 )
+    {
+        CPL_IGNORE_RET_VAL_INT(VSIFCloseL( fp ));
+        return CE_Failure;
+    }
 
-    VSIFCloseL( fp );
+    CPL_IGNORE_RET_VAL_INT(VSIFCloseL( fp ));
 
 #ifdef CPL_LSB
     CPL_SWAPDOUBLE(adfBound+0);
     CPL_SWAPDOUBLE(adfBound+1);
     CPL_SWAPDOUBLE(adfBound+2);
     CPL_SWAPDOUBLE(adfBound+3);
-#endif    
-    
+#endif
+
     psInfo->dfLLX = adfBound[0];
     psInfo->dfLLY = adfBound[1];
     psInfo->dfURX = adfBound[2];
@@ -1047,6 +1121,7 @@ CPLErr AIGReadStatistics( const char * pszCoverName, AIGInfo_t * psInfo )
     char	*pszHDRFilename;
     VSILFILE	*fp;
     double	adfStats[4];
+    const size_t nHDRFilenameLen = strlen(pszCoverName)+40;
 
     psInfo->dfMin = 0.0;
     psInfo->dfMax = 0.0;
@@ -1056,11 +1131,11 @@ CPLErr AIGReadStatistics( const char * pszCoverName, AIGInfo_t * psInfo )
 /* -------------------------------------------------------------------- */
 /*      Open the file sta.adf file.                                     */
 /* -------------------------------------------------------------------- */
-    pszHDRFilename = (char *) CPLMalloc(strlen(pszCoverName)+40);
-    sprintf( pszHDRFilename, "%s/sta.adf", pszCoverName );
+    pszHDRFilename = (char *) CPLMalloc(nHDRFilenameLen);
+    snprintf( pszHDRFilename, nHDRFilenameLen, "%s/sta.adf", pszCoverName );
 
     fp = AIGLLOpen( pszHDRFilename, "rb" );
-    
+
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
@@ -1076,17 +1151,21 @@ CPLErr AIGReadStatistics( const char * pszCoverName, AIGInfo_t * psInfo )
 /* -------------------------------------------------------------------- */
 /*      Get the contents - four doubles.                                */
 /* -------------------------------------------------------------------- */
-    VSIFReadL( adfStats, 1, 32, fp );
+    if( VSIFReadL( adfStats, 1, 32, fp ) != 32 )
+    {
+        CPL_IGNORE_RET_VAL_INT(VSIFCloseL( fp ));
+        return CE_Failure;
+    }
 
-    VSIFCloseL( fp );
+    CPL_IGNORE_RET_VAL_INT(VSIFCloseL( fp ));
 
 #ifdef CPL_LSB
     CPL_SWAPDOUBLE(adfStats+0);
     CPL_SWAPDOUBLE(adfStats+1);
     CPL_SWAPDOUBLE(adfStats+2);
     CPL_SWAPDOUBLE(adfStats+3);
-#endif    
-    
+#endif
+
     psInfo->dfMin = adfStats[0];
     psInfo->dfMax = adfStats[1];
     psInfo->dfMean = adfStats[2];
@@ -1094,4 +1173,3 @@ CPLErr AIGReadStatistics( const char * pszCoverName, AIGInfo_t * psInfo )
 
     return( CE_None );
 }
-
diff --git a/frmts/aigrid/makefile.vc b/frmts/aigrid/makefile.vc
index c1a517a..e372d15 100644
--- a/frmts/aigrid/makefile.vc
+++ b/frmts/aigrid/makefile.vc
@@ -1,7 +1,7 @@
 
 OBJ	=	aigdataset.obj aigopen.obj gridlib.obj aigccitt.obj
 
-EXTRAFLAGS = 	-I../../ogr/ogrsf_frmts/avc
+EXTRAFLAGS = 	-I../../ogr/ogrsf_frmts/avc -I../../ogr/ogrsf_frmts/shape
 
 GDAL_ROOT	=	..\..
 
diff --git a/frmts/airsar/airsardataset.cpp b/frmts/airsar/airsardataset.cpp
index c16a56e..e5136c3 100644
--- a/frmts/airsar/airsardataset.cpp
+++ b/frmts/airsar/airsardataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: airsardataset.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: airsardataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  AirSAR Reader
  * Purpose:  Implements read support for AirSAR Polarimetric data.
@@ -28,16 +28,13 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
-#include "cpl_string.h"
 #include "cpl_conv.h"
+#include "cpl_string.h"
 #include "cpl_vsi.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
 
-CPL_CVSID("$Id: airsardataset.cpp 27745 2014-09-27 16:38:57Z goatbar $");
-
-CPL_C_START
-void	GDALRegister_AirSAR(void);
-CPL_C_END
+CPL_CVSID("$Id: airsardataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -62,13 +59,13 @@ class AirSARDataset : public GDALPamDataset
 
     CPLErr      LoadLine(int iLine);
 
-    static char  **ReadHeader( VSILFILE * fp, int nFileOffset, 
+    static char  **ReadHeader( VSILFILE * fp, int nFileOffset,
                                const char *pszPrefix, int nMaxLines );
 
   public:
                 AirSARDataset();
 		~AirSARDataset();
-    
+
     static GDALDataset *Open( GDALOpenInfo * );
 };
 
@@ -83,34 +80,34 @@ class AirSARRasterBand : public GDALPamRasterBand
   public:
     		AirSARRasterBand( AirSARDataset *, int );
     virtual     ~AirSARRasterBand();
-    
+
     virtual CPLErr IReadBlock( int, int, void * );
 };
 
 /* locations of stokes matrix values within padfMatrix ... same order as they
    are computed in the document. */
 
-#define M11 0
-#define M12 1
-#define M13 2
-#define M14 3
-#define M23 4
-#define M24 5
-#define M33 6
-#define M34 7
-#define M44 8
-#define M22 9
+static const int M11 = 0;
+static const int M12 = 1;
+static const int M13 = 2;
+static const int M14 = 3;
+static const int M23 = 4;
+static const int M24 = 5;
+static const int M33 = 6;
+static const int M34 = 7;
+static const int M44 = 8;
+static const int M22 = 9;
 
 /************************************************************************/
 /*                          AirSARRasterBand()                          */
 /************************************************************************/
 
-AirSARRasterBand::AirSARRasterBand( AirSARDataset *poDS,
-                                    int nBand )
+AirSARRasterBand::AirSARRasterBand( AirSARDataset *poDSIn,
+                                    int nBandIn )
 
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
 
     nBlockXSize = poDS->GetRasterXSize();
     nBlockYSize = 1;
@@ -173,26 +170,22 @@ AirSARRasterBand::~AirSARRasterBand()
 /*                             IReadBlock()                             */
 /************************************************************************/
 
-CPLErr AirSARRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
+CPLErr AirSARRasterBand::IReadBlock( int /* nBlockXOff */,
                                      int nBlockYOff,
                                      void * pImage )
 {
-    CPLErr eErr;
     float *pafLine = (float *) pImage;
-    int iPixel;
-    double *padfMatrix;
+    const double SQRT_2 = 1.4142135623730951;
 
-    eErr = ((AirSARDataset *)poDS)->LoadLine( nBlockYOff );
+    CPLErr eErr = ((AirSARDataset *)poDS)->LoadLine( nBlockYOff );
     if( eErr != CE_None )
         return eErr;
 
-    padfMatrix = ((AirSARDataset *) poDS)->padfMatrix;
-
-#define SQRT_2 1.4142135623730951
+    double *padfMatrix = ((AirSARDataset *) poDS)->padfMatrix;
 
     if( nBand == 1 ) /* C11 */
     {
-        for( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
+        for( int iPixel = 0; iPixel < nRasterXSize; iPixel++ )
         {
             double *m = padfMatrix + 10 * iPixel;
 
@@ -202,10 +195,10 @@ CPLErr AirSARRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     }
     else if( nBand == 2 ) /* C12 */
     {
-        for( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
+        for( int iPixel = 0; iPixel < nRasterXSize; iPixel++ )
         {
             double *m = padfMatrix + 10 * iPixel;
-            
+
             // real
             pafLine[iPixel*2 + 0] = (float)(SQRT_2 * (m[M13] + m[M23]));
 
@@ -215,10 +208,10 @@ CPLErr AirSARRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     }
     else if( nBand == 3 ) /* C13 */
     {
-        for( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
+        for( int iPixel = 0; iPixel < nRasterXSize; iPixel++ )
         {
             double *m = padfMatrix + 10 * iPixel;
-            
+
             // real
             pafLine[iPixel*2 + 0] = (float)(2*m[M33] + m[M22] - m[M11]);
 
@@ -228,20 +221,20 @@ CPLErr AirSARRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     }
     else if( nBand == 4 ) /* C22 */
     {
-        for( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
+        for( int iPixel = 0; iPixel < nRasterXSize; iPixel++ )
         {
             double *m = padfMatrix + 10 * iPixel;
-            
+
             pafLine[iPixel*2+0] = (float)(2 * (m[M11] - m[M22]));
             pafLine[iPixel*2+1] = 0.0;
         }
     }
     else if( nBand == 5 ) /* C23 */
     {
-        for( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
+        for( int iPixel = 0; iPixel < nRasterXSize; iPixel++ )
         {
             double *m = padfMatrix + 10 * iPixel;
-            
+
             // real
             pafLine[iPixel*2 + 0] = (float)(SQRT_2 * (m[M13] - m[M23]));
 
@@ -251,10 +244,10 @@ CPLErr AirSARRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     }
     else if( nBand == 6 ) /* C33 */
     {
-        for( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
+        for( int iPixel = 0; iPixel < nRasterXSize; iPixel++ )
         {
             double *m = padfMatrix + 10 * iPixel;
-            
+
             pafLine[iPixel*2+0] = (float)(m[M11] + m[M22] - 2 * m[M12]);
             pafLine[iPixel*2+1] = 0.0;
         }
@@ -273,15 +266,14 @@ CPLErr AirSARRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /*                           AirSARDataset()                            */
 /************************************************************************/
 
-AirSARDataset::AirSARDataset()
-
-{
-    fp = NULL;
-
-    nLoadedLine = -1;
-    pabyCompressedLine = NULL;
-    padfMatrix = NULL;
-}
+AirSARDataset::AirSARDataset() :
+    fp(NULL),
+    nLoadedLine(-1),
+    pabyCompressedLine(NULL),
+    padfMatrix(NULL),
+    nDataStart(0),
+    nRecordLength(0)
+{ }
 
 /************************************************************************/
 /*                           ~AirSARDataset()                           */
@@ -291,11 +283,8 @@ AirSARDataset::~AirSARDataset()
 
 {
     FlushCache();
-    if( pabyCompressedLine != NULL )
-    {
-        CPLFree( pabyCompressedLine );
-        CPLFree( padfMatrix );
-    }
+    CPLFree( pabyCompressedLine );
+    CPLFree( padfMatrix );
 
     if( fp != NULL )
     {
@@ -319,16 +308,12 @@ CPLErr AirSARDataset::LoadLine( int iLine )
 /* -------------------------------------------------------------------- */
     if( pabyCompressedLine == NULL )
     {
-        pabyCompressedLine = (GByte *) VSIMalloc2(nRasterXSize, 10);
+        pabyCompressedLine = (GByte *) VSI_MALLOC2_VERBOSE(nRasterXSize, 10);
 
-        padfMatrix = (double *) VSIMalloc2(10* sizeof(double), nRasterXSize);
+        padfMatrix = (double *) VSI_MALLOC2_VERBOSE(10* sizeof(double), nRasterXSize);
         if (pabyCompressedLine == NULL ||
             padfMatrix == NULL)
         {
-            CPLError(CE_Failure, CPLE_OutOfMemory,
-                     "AirSARDataset::LoadLine : Out of memory. "
-                     "Probably due to corrupted dataset (nRasterXSize = %d)",
-                     nRasterXSize);
             CPLFree (pabyCompressedLine);
             CPLFree (padfMatrix);
             return CE_Failure;
@@ -340,11 +325,11 @@ CPLErr AirSARDataset::LoadLine( int iLine )
 /* -------------------------------------------------------------------- */
 /*      Load raw compressed data.                                       */
 /* -------------------------------------------------------------------- */
-    if( VSIFSeekL( fp, nDataStart + iLine * nRecordLength, SEEK_SET ) != 0 
+    if( VSIFSeekL( fp, nDataStart + iLine * nRecordLength, SEEK_SET ) != 0
         || ((int) VSIFReadL( pabyCompressedLine, 10, nRasterXSize, fp ))
                  != nRasterXSize )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   "Error reading %d bytes for line %d at offset %d.\n%s",
                   nRasterXSize * 10, iLine, nDataStart + iLine * nRecordLength,
                   VSIStrerror( errno ) );
@@ -358,8 +343,8 @@ CPLErr AirSARDataset::LoadLine( int iLine )
     {
         double *M = padfMatrix + 10 * iPixel;
         signed char *byte = (signed char *) pabyCompressedLine + 10*iPixel - 1;
-        double gen_fac = 1.0; // should we have a general scale factor?
-        
+        const double gen_fac = 1.0; // should we have a general scale factor?
+
         M[M11] = (byte[2] / 254.0 + 1.5) * pow(2.0,byte[1]) * gen_fac;
         M[M12] = byte[3] * M[M11] / 127.0;
         M[M13] = byte[4] * fabs((double) byte[4]) * M[M11] / (127*127);
@@ -378,7 +363,7 @@ CPLErr AirSARDataset::LoadLine( int iLine )
 /************************************************************************/
 /*                             ReadHeader()                             */
 /*                                                                      */
-/*      Read the AirSAR header.  We assume an equal sign seperates      */
+/*      Read the AirSAR header.  We assume an equal sign separates      */
 /*      the keyword name from the value.  If not, assume the last       */
 /*      "blank delimited" word is the value and everything else is a    */
 /*      keyword.                                                        */
@@ -387,20 +372,19 @@ CPLErr AirSARDataset::LoadLine( int iLine )
 /*      blank record or some zero bytes.                                */
 /************************************************************************/
 
-char ** AirSARDataset::ReadHeader( VSILFILE * fp, int nFileOffset, 
+char ** AirSARDataset::ReadHeader( VSILFILE * fp, int nFileOffset,
                                    const char *pszPrefix, int nMaxLines )
 
 {
     char **papszHeadInfo = NULL;
     char szLine[51];
-    int  iLine;
 
     VSIFSeekL( fp, nFileOffset, SEEK_SET );
 
 /* ==================================================================== */
 /*      Loop collecting one line at a time.                             */
 /* ==================================================================== */
-    for( iLine = 0; iLine < nMaxLines; iLine++ )
+    for( int iLine = 0; iLine < nMaxLines; iLine++ )
     {
 /* -------------------------------------------------------------------- */
 /*      Read a 50 byte header record.                                   */
@@ -409,6 +393,7 @@ char ** AirSARDataset::ReadHeader( VSILFILE * fp, int nFileOffset,
         {
             CPLError( CE_Failure, CPLE_FileIO,
                       "Read error collecting AirSAR header." );
+            CSLDestroy( papszHeadInfo );
             return NULL;
         }
 
@@ -417,21 +402,20 @@ char ** AirSARDataset::ReadHeader( VSILFILE * fp, int nFileOffset,
 /* -------------------------------------------------------------------- */
 /*      Is it all spaces, or does it have a zero byte?                  */
 /* -------------------------------------------------------------------- */
-        int bAllSpaces = TRUE;
-        int bHasIllegalChars = FALSE;
-        int i;
+        bool bAllSpaces = true;
+        bool bHasIllegalChars = false;
 
-        for( i = 0; i < 50; i++ )
+        for( int i = 0; i < 50; i++ )
         {
             if( szLine[i] == '\0' )
                 break;
 
             if( szLine[i] != ' ' )
-                bAllSpaces = FALSE;
-            
-            if( ((unsigned char *) szLine)[i] > 127 
+                bAllSpaces = false;
+
+            if( ((unsigned char *) szLine)[i] > 127
                 || ((unsigned char *) szLine)[i] < 10 )
-                bHasIllegalChars = TRUE;
+                bHasIllegalChars = true;
         }
 
         if( bAllSpaces || bHasIllegalChars )
@@ -442,7 +426,7 @@ char ** AirSARDataset::ReadHeader( VSILFILE * fp, int nFileOffset,
 /* -------------------------------------------------------------------- */
         int iPivot = -1;
 
-        for( i = 0; i < 50; i++ )
+        for( int i = 0; i < 50; i++ )
         {
             if( szLine[i] == '=' )
             {
@@ -454,7 +438,7 @@ char ** AirSARDataset::ReadHeader( VSILFILE * fp, int nFileOffset,
         // If no "=" found, split on first double white space
         if( iPivot == -1 )
         {
-            for( i = 48; i >= 0; i-- )
+            for( int i = 48; i >= 0; i-- )
             {
                 if( szLine[i] == ' ' && szLine[i+1] == ' ' )
                 {
@@ -466,7 +450,7 @@ char ** AirSARDataset::ReadHeader( VSILFILE * fp, int nFileOffset,
 
         if( iPivot == -1 ) // Yikes!
         {
-            CPLDebug( "AIRSAR", "No pivot in line `%s'.", 
+            CPLDebug( "AIRSAR", "No pivot in line `%s'.",
                       szLine );
             CPLAssert( iPivot != -1 );
             break;
@@ -484,7 +468,7 @@ char ** AirSARDataset::ReadHeader( VSILFILE * fp, int nFileOffset,
 /*      Strip any white space off the keyword.                          */
 /* -------------------------------------------------------------------- */
         int iKeyEnd = iPivot - 1;
-        
+
         while( iKeyEnd > 0 && szLine[iKeyEnd] == ' ' )
             iKeyEnd--;
 
@@ -493,7 +477,7 @@ char ** AirSARDataset::ReadHeader( VSILFILE * fp, int nFileOffset,
 /* -------------------------------------------------------------------- */
 /*      Convert spaces or colons into underscores in the key name.      */
 /* -------------------------------------------------------------------- */
-        for( i = 0; szLine[i] != '\0'; i++ )
+        for( int i = 0; szLine[i] != '\0'; i++ )
         {
             if( szLine[i] == ' ' || szLine[i] == ':' || szLine[i] == ',' )
                 szLine[i] = '_';
@@ -504,11 +488,11 @@ char ** AirSARDataset::ReadHeader( VSILFILE * fp, int nFileOffset,
 /* -------------------------------------------------------------------- */
         char szPrefixedKeyName[55];
 
-        sprintf( szPrefixedKeyName, "%s_%s", pszPrefix, szLine );
+        snprintf( szPrefixedKeyName, sizeof(szPrefixedKeyName), "%s_%s", pszPrefix, szLine );
 
-        papszHeadInfo = 
+        papszHeadInfo =
             CSLSetNameValue( papszHeadInfo, szPrefixedKeyName, szLine+iValue );
-        
+
     }
 
     return papszHeadInfo;
@@ -528,10 +512,10 @@ GDALDataset *AirSARDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Check for AirSAR/ keyword.                                      */
 /* -------------------------------------------------------------------- */
-    if( !EQUALN((char *) poOpenInfo->pabyHeader, "RECORD LENGTH IN BYTES",22) )
+    if( !STARTS_WITH_CI((char *) poOpenInfo->pabyHeader, "RECORD LENGTH IN BYTES") )
         return NULL;
 
-    if( strstr((char *) poOpenInfo->pabyHeader, "COMPRESSED") == NULL 
+    if( strstr((char *) poOpenInfo->pabyHeader, "COMPRESSED") == NULL
         || strstr((char *) poOpenInfo->pabyHeader, "JPL AIRCRAFT") == NULL )
         return NULL;
 
@@ -541,7 +525,7 @@ GDALDataset *AirSARDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      "well behaved" as metadata keywords.                            */
 /* -------------------------------------------------------------------- */
     char **papszMD = ReadHeader( poOpenInfo->fpL, 0, "MH", 20 );
-    
+
     if( papszMD == NULL )
         return NULL;
 
@@ -550,25 +534,24 @@ GDALDataset *AirSARDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The AIRSAR driver does not support update access to existing"
                   " datasets.\n" );
+        CSLDestroy( papszMD );
         return NULL;
     }
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    AirSARDataset 	*poDS;
-
-    poDS = new AirSARDataset();
+    AirSARDataset *poDS = new AirSARDataset();
 
 /* -------------------------------------------------------------------- */
 /*      Extract some key information.                                   */
 /* -------------------------------------------------------------------- */
 
-    poDS->nRasterXSize = 
+    poDS->nRasterXSize =
         atoi(CSLFetchNameValue(papszMD,"MH_NUMBER_OF_SAMPLES_PER_RECORD"));
-    poDS->nRasterYSize = 
+    poDS->nRasterYSize =
         atoi(CSLFetchNameValue(papszMD,"MH_NUMBER_OF_LINES_IN_IMAGE"));
 
     poDS->nRecordLength = atoi(
@@ -589,10 +572,10 @@ GDALDataset *AirSARDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     int nPHOffset = 0;
 
-    if( CSLFetchNameValue( papszMD, 
+    if( CSLFetchNameValue( papszMD,
                            "MH_BYTE_OFFSET_OF_PARAMETER_HEADER" ) != NULL )
     {
-        nPHOffset = atoi(CSLFetchNameValue( 
+        nPHOffset = atoi(CSLFetchNameValue(
                         papszMD, "MH_BYTE_OFFSET_OF_PARAMETER_HEADER"));
         char **papszPHInfo = ReadHeader( poDS->fp, nPHOffset, "PH", 100 );
 
@@ -607,8 +590,8 @@ GDALDataset *AirSARDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( nPHOffset != 0 )
     {
-        char **papszCHInfo = ReadHeader( poDS->fp, 
-                                         nPHOffset+poDS->nRecordLength, 
+        char **papszCHInfo = ReadHeader( poDS->fp,
+                                         nPHOffset+poDS->nRecordLength,
                                          "CH", 18 );
 
         papszMD = CSLInsertStrings( papszMD, CSLCount(papszMD), papszCHInfo );
@@ -646,28 +629,26 @@ GDALDataset *AirSARDataset::Open( GDALOpenInfo * poOpenInfo )
 }
 
 /************************************************************************/
-/*                        GDALRegister_AirSAR()                            */
+/*                        GDALRegister_AirSAR()                         */
 /************************************************************************/
 
 void GDALRegister_AirSAR()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "AirSAR" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "AirSAR" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "AirSAR" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "AirSAR Polarimetric Image" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_airsar.html" );
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetDescription( "AirSAR" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "AirSAR Polarimetric Image" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_airsar.html" );
 
-        poDriver->pfnOpen = AirSARDataset::Open;
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    poDriver->pfnOpen = AirSARDataset::Open;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/airsar/frmt_airsar.html b/frmts/airsar/frmt_airsar.html
index b363cb8..b590458 100644
--- a/frmts/airsar/frmt_airsar.html
+++ b/frmts/airsar/frmt_airsar.html
@@ -9,16 +9,16 @@
 
 Most variants of the AIRSAR Polarimetric Format produced by the AIRSAR
 Integrated Processor are supported for reading by GDAL. AIRSAR products
-normally include various associated data files, but only the imagery 
+normally include various associated data files, but only the imagery
 data themselves is supported.  Normally these are named <i>mission</i>_l.dat
 (L-Band) or <i>mission</i>_c.dat (C-Band).<p>
 
-AIRSAR format contains a polarimetric image in compressed stokes matrix form. 
+AIRSAR format contains a polarimetric image in compressed stokes matrix form.
 Internally GDAL decompresses the data into a stokes matrix, and then converts
 that form into a covariance matrix.  The returned six bands are the six values
 needed to define the 3x3 Hermitian covariance matrix.  The convention used
 to represent the covariance matrix in terms of the scattering matrix
-elements HH, HV (=VH), and VV is indicated below.  Note that the 
+elements HH, HV (=VH), and VV is indicated below.  Note that the
 non-diagonal elements of the matrix are complex values, while the diagonal
 values are real (though represented as complex bands).<p>
 
@@ -35,16 +35,16 @@ values are real (though represented as complex bands).<p>
 The identities of the bands are also reflected in metadata and in the band
 descriptions.  <p>
 
-The AIRSAR product format includes (potentially) several headers of 
+The AIRSAR product format includes (potentially) several headers of
 information.  This information is captured and represented as metadata on the
-file as a whole.  Information items from the main header are prefixed with 
+file as a whole.  Information items from the main header are prefixed with
 "MH_", items from the parameter header are prefixed with "PH_" and
-information from the calibration header are prefixed with "CH_". 
+information from the calibration header are prefixed with "CH_".
 The metadata item names are derived automatically from the names of the
 fields within the header itself. <p>
 
 No effort is made to read files associated with the AIRSAR product such as
-<i>mission</i>_l.mocomp, <i>mission</i>_meta.airsar or 
+<i>mission</i>_l.mocomp, <i>mission</i>_meta.airsar or
 <i>mission</i>_meta.podaac.<p>
 
 See Also:<p>
diff --git a/frmts/arg/argdataset.cpp b/frmts/arg/argdataset.cpp
index af4a550..b26e943 100644
--- a/frmts/arg/argdataset.cpp
+++ b/frmts/arg/argdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: argdataset.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: argdataset.cpp 32205 2015-12-17 21:57:20Z goatbar $
  *
  * Project:  Azavea Raster Grid format driver.
  * Purpose:  Implements support for reading and writing Azavea Raster Grid
@@ -29,63 +29,48 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "rawdataset.h"
 #include "cpl_string.h"
-#include <json.h>
-#include <ogr_spatialref.h>
-
-CPL_CVSID("$Id: argdataset.cpp 28053 2014-12-04 09:31:07Z rouault $");
-
-#define MAX_FILENAME_LEN 4096
-
-#ifndef NAN
-#  ifdef HUGE_VAL
-#    define NAN (HUGE_VAL * 0.0)
-#  else
+#include "gdal_frmts.h"
+#include "ogr_spatialref.h"
+#include "rawdataset.h"
 
-static float CPLNaN(void)
-{
-    float fNan;
-    int nNan = 0x7FC00000;
-    memcpy(&fNan, &nNan, 4);
-    return fNan;
-}
+#include <json.h>
+#include <limits>
 
-#    define NAN CPLNaN()
-#  endif
-#endif
+CPL_CVSID("$Id: argdataset.cpp 32205 2015-12-17 21:57:20Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
-/*				ARGDataset				                                */
+/*                              ARGDataset                              */
 /* ==================================================================== */
 /************************************************************************/
 
 class ARGDataset : public RawDataset
 {
-        VSILFILE	*fpImage;	// image data file.
-    
-        double	adfGeoTransform[6];
-        char * pszFilename;
+        VSILFILE *fpImage;  // image data file.
+        double adfGeoTransform[6];
+        char *pszFilename;
 
     public:
         ARGDataset();
         ~ARGDataset();
 
-        CPLErr 	GetGeoTransform( double * padfTransform );
-   
+        CPLErr GetGeoTransform( double * padfTransform );
+
         static int Identify( GDALOpenInfo * );
         static GDALDataset *Open( GDALOpenInfo * );
-        static GDALDataset *CreateCopy( const char *, GDALDataset *, int, 
+        static GDALDataset *CreateCopy( const char *, GDALDataset *, int,
             char **, GDALProgressFunc, void *);
-        virtual char ** GetFileList(void);
-}; 
+        virtual char **GetFileList(void);
+};
 
 /************************************************************************/
 /*                            ARGDataset()                              */
 /************************************************************************/
 
-ARGDataset::ARGDataset()
+ARGDataset::ARGDataset() :
+    fpImage(NULL),
+    pszFilename(NULL)
 {
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
@@ -93,7 +78,6 @@ ARGDataset::ARGDataset()
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
-    fpImage = NULL;
 }
 
 /************************************************************************/
@@ -125,7 +109,7 @@ CPLErr ARGDataset::GetGeoTransform( double * padfTransform )
 /************************************************************************/
 /*                         GetJsonFilename()                            */
 /************************************************************************/
-CPLString GetJsonFilename(CPLString pszFilename) 
+static CPLString GetJsonFilename(CPLString pszFilename)
 {
     return CPLSPrintf( "%s/%s.json", CPLGetDirname(pszFilename), CPLGetBasename(pszFilename) );
 }
@@ -133,15 +117,14 @@ CPLString GetJsonFilename(CPLString pszFilename)
 /************************************************************************/
 /*                           GetJsonObject()                            */
 /************************************************************************/
-json_object * GetJsonObject(CPLString pszFilename) 
+static json_object * GetJsonObject(CPLString pszFilename)
 {
-    json_object * pJSONObject = NULL;
     CPLString osJSONFilename = GetJsonFilename(pszFilename);
 
-    pJSONObject = json_object_from_file((char *)osJSONFilename.c_str());
+    json_object *pJSONObject
+        = json_object_from_file(const_cast<char *>(osJSONFilename.c_str()));
     if (pJSONObject == NULL) {
-        CPLDebug("ARGDataset", "GetJsonObject(): "
-            "Could not parse JSON file.");
+        CPLDebug("ARGDataset", "GetJsonObject(): Could not parse JSON file.");
         return NULL;
     }
 
@@ -151,9 +134,9 @@ json_object * GetJsonObject(CPLString pszFilename)
 /************************************************************************/
 /*                          GetJsonValueStr()                           */
 /************************************************************************/
-const char * GetJsonValueStr(json_object * pJSONObject, CPLString pszKey) 
+static const char *GetJsonValueStr(json_object * pJSONObject, CPLString pszKey)
 {
-    json_object * pJSONItem = json_object_object_get(pJSONObject, pszKey.c_str());
+    json_object *pJSONItem = json_object_object_get(pJSONObject, pszKey.c_str());
     if (pJSONItem == NULL) {
         CPLDebug("ARGDataset", "GetJsonValueStr(): "
             "Could not find '%s' in JSON.", pszKey.c_str());
@@ -166,42 +149,40 @@ const char * GetJsonValueStr(json_object * pJSONObject, CPLString pszKey)
 /************************************************************************/
 /*                          GetJsonValueDbl()                           */
 /************************************************************************/
-double GetJsonValueDbl(json_object * pJSONObject, CPLString pszKey) 
+static double GetJsonValueDbl(json_object * pJSONObject, CPLString pszKey)
 {
     const char *pszJSONStr = GetJsonValueStr(pJSONObject, pszKey.c_str());
-    char *pszTmp;
-    double fTmp;
     if (pszJSONStr == NULL) {
-        return NAN;
+        return std::numeric_limits<double>::quiet_NaN();
     }
-    pszTmp = (char *)pszJSONStr;
-    fTmp = CPLStrtod(pszJSONStr, &pszTmp);
+    char *pszTmp = const_cast<char *>(pszJSONStr);
+    double dfTmp = CPLStrtod(pszJSONStr, &pszTmp);
     if (pszTmp == pszJSONStr) {
         CPLDebug("ARGDataset", "GetJsonValueDbl(): "
             "Key value is not a numeric value: %s:%s", pszKey.c_str(), pszTmp);
-        return NAN;
+        return std::numeric_limits<double>::quiet_NaN();
     }
 
-    return fTmp;
+    return dfTmp;
 }
 
 /************************************************************************/
 /*                           GetJsonValueInt()                          */
 /************************************************************************/
-int GetJsonValueInt(json_object * pJSONObject, CPLString pszKey) 
+static int GetJsonValueInt(json_object *pJSONObject, CPLString pszKey)
 {
-    double fTmp = GetJsonValueDbl(pJSONObject, pszKey.c_str());
-    if (CPLIsNan(fTmp)) {
+    double dfTmp = GetJsonValueDbl(pJSONObject, pszKey.c_str());
+    if (CPLIsNan(dfTmp)) {
         return -1;
     }
 
-    return (int)fTmp;
+    return static_cast<int>(dfTmp);
 }
 
 /************************************************************************/
 /*                            GetFileList()                             */
 /************************************************************************/
-char ** ARGDataset::GetFileList()
+char **ARGDataset::GetFileList()
 {
     char **papszFileList = GDALPamDataset::GetFileList();
     CPLString osJSONFilename = GetJsonFilename(pszFilename);
@@ -217,12 +198,11 @@ char ** ARGDataset::GetFileList()
 
 int ARGDataset::Identify( GDALOpenInfo *poOpenInfo )
 {
-    json_object * pJSONObject;
     if (!EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "arg")) {
         return FALSE;
     }
 
-    pJSONObject = GetJsonObject(poOpenInfo->pszFilename);
+    json_object *pJSONObject = GetJsonObject(poOpenInfo->pszFilename);
     if (pJSONObject == NULL) {
         return FALSE;
     }
@@ -236,32 +216,8 @@ int ARGDataset::Identify( GDALOpenInfo *poOpenInfo )
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
-GDALDataset *ARGDataset::Open( GDALOpenInfo * poOpenInfo )
+GDALDataset *ARGDataset::Open( GDALOpenInfo *poOpenInfo )
 {
-    json_object * pJSONObject;
-    const char * pszJSONStr;
-    char * pszLayer;
-    /***** items from the json metadata *****/
-    GDALDataType eType = GDT_Unknown;
-    double fXmin = 0.0;
-    double fYmin = 0.0;
-    double fXmax = 0.0;
-    double fYmax = 0.0;
-    double fCellwidth = 1.0;
-    double fCellheight = 1.0;
-    double fXSkew = 0.0;
-    double fYSkew = 0.0;
-    int nRows = 0;
-    int nCols = 0;
-    int nSrs = 3857;
-    /***** items from the json metadata *****/
-    int nPixelOffset = 0;
-    double fNoDataValue = NAN;
-
-    char * pszWKT = NULL;
-    OGRSpatialReference oSRS;
-    OGRErr nErr = OGRERR_NONE;
-
     if ( !Identify( poOpenInfo ) )
         return NULL;
 
@@ -269,7 +225,7 @@ GDALDataset *ARGDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Check metadata settings in JSON.                                */
 /* -------------------------------------------------------------------- */
 
-    pJSONObject = GetJsonObject(poOpenInfo->pszFilename);
+    json_object *pJSONObject = GetJsonObject(poOpenInfo->pszFilename);
 
     if (pJSONObject == NULL) {
         CPLError(CE_Failure, CPLE_AppDefined, "Error parsing JSON.");
@@ -277,7 +233,7 @@ GDALDataset *ARGDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
     // get the type (always 'arg')
-    pszJSONStr = GetJsonValueStr(pJSONObject, "type");
+    const char *pszJSONStr = GetJsonValueStr(pJSONObject, "type");
     if (pszJSONStr == NULL ) {
         CPLError(CE_Failure, CPLE_AppDefined,
             "The ARG 'type' is missing from the JSON file.");
@@ -293,6 +249,10 @@ GDALDataset *ARGDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
+    double dfNoDataValue;
+    GDALDataType eType;
+    int nPixelOffset;
+
     // get the datatype
     pszJSONStr = GetJsonValueStr(pJSONObject, "datatype");
     if (pszJSONStr == NULL) {
@@ -305,44 +265,44 @@ GDALDataset *ARGDataset::Open( GDALOpenInfo * poOpenInfo )
     else if (EQUAL(pszJSONStr, "int8")) {
         CPLDebug("ARGDataset", "Open(): "
             "int8 data is not supported in GDAL -- mapped to uint8");
-        eType = GDT_Byte; 
+        eType = GDT_Byte;
         nPixelOffset = 1;
-        fNoDataValue = 128;
+        dfNoDataValue = 128;
     }
     else if (EQUAL(pszJSONStr, "int16")) {
         eType = GDT_Int16;
         nPixelOffset = 2;
-        fNoDataValue = -32767;
+        dfNoDataValue = -32767;
     }
     else if (EQUAL(pszJSONStr, "int32")) {
         eType = GDT_Int32;
         nPixelOffset = 4;
-        fNoDataValue = -2e31;
+        dfNoDataValue = -2e31;
     }
     else if (EQUAL(pszJSONStr, "uint8")) {
-        eType = GDT_Byte; 
+        eType = GDT_Byte;
         nPixelOffset = 1;
-        fNoDataValue = 255;
+        dfNoDataValue = 255;
     }
     else if (EQUAL(pszJSONStr, "uint16")) {
         eType = GDT_UInt16;
         nPixelOffset = 2;
-        fNoDataValue = 65535;
+        dfNoDataValue = 65535;
     }
     else if (EQUAL(pszJSONStr, "uint32")) {
         eType = GDT_UInt32;
         nPixelOffset = 4;
-        fNoDataValue = -2e31;
+        dfNoDataValue = -2e31;
     }
     else if (EQUAL(pszJSONStr, "float32")) {
         eType = GDT_Float32;
         nPixelOffset = 4;
-        fNoDataValue = NAN;
+        dfNoDataValue = std::numeric_limits<double>::quiet_NaN();
     }
-    else if (EQUAL(pszJSONStr, "float64")) { 
+    else if (EQUAL(pszJSONStr, "float64")) {
         eType = GDT_Float64;
         nPixelOffset = 8;
-        fNoDataValue = NAN;
+        dfNoDataValue = std::numeric_limits<double>::quiet_NaN();
     }
     else {
         if (EQUAL(pszJSONStr, "int64") ||
@@ -360,18 +320,18 @@ GDALDataset *ARGDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
     // get the xmin of the bounding box
-    fXmin = GetJsonValueDbl(pJSONObject, "xmin");
-    if (CPLIsNan(fXmin)) {
+    const double dfXmin = GetJsonValueDbl(pJSONObject, "xmin");
+    if (CPLIsNan(dfXmin)) {
         CPLError(CE_Failure, CPLE_AppDefined,
             "The ARG 'xmin' is missing or invalid.");
         json_object_put(pJSONObject);
         pJSONObject = NULL;
         return NULL;
     }
-    
+
     // get the ymin of the bounding box
-    fYmin = GetJsonValueDbl(pJSONObject, "ymin");
-    if (CPLIsNan(fYmin)) {
+    const double dfYmin = GetJsonValueDbl(pJSONObject, "ymin");
+    if (CPLIsNan(dfYmin)) {
         CPLError(CE_Failure, CPLE_AppDefined,
             "The ARG 'ymin' is missing or invalid.");
         json_object_put(pJSONObject);
@@ -380,8 +340,8 @@ GDALDataset *ARGDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
     // get the xmax of the bounding box
-    fXmax = GetJsonValueDbl(pJSONObject, "xmax");
-    if (CPLIsNan(fXmax)) {
+    const double dfXmax = GetJsonValueDbl(pJSONObject, "xmax");
+    if (CPLIsNan(dfXmax)) {
         CPLError(CE_Failure, CPLE_AppDefined,
             "The ARG 'xmax' is missing or invalid.");
         json_object_put(pJSONObject);
@@ -390,8 +350,8 @@ GDALDataset *ARGDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
     // get the ymax of the bounding box
-    fYmax = GetJsonValueDbl(pJSONObject, "ymax");
-    if (CPLIsNan(fYmax)) {
+    const double dfYmax = GetJsonValueDbl(pJSONObject, "ymax");
+    if (CPLIsNan(dfYmax)) {
         CPLError(CE_Failure, CPLE_AppDefined,
             "The ARG 'ymax' is missing or invalid.");
         json_object_put(pJSONObject);
@@ -400,8 +360,8 @@ GDALDataset *ARGDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
     // get the cell width
-    fCellwidth = GetJsonValueDbl(pJSONObject, "cellwidth");
-    if (CPLIsNan(fCellwidth)) {
+    const double dfCellwidth = GetJsonValueDbl(pJSONObject, "cellwidth");
+    if (CPLIsNan(dfCellwidth)) {
         CPLError(CE_Failure, CPLE_AppDefined,
             "The ARG 'cellwidth' is missing or invalid.");
         json_object_put(pJSONObject);
@@ -410,8 +370,8 @@ GDALDataset *ARGDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
     // get the cell height
-    fCellheight = GetJsonValueDbl(pJSONObject, "cellheight");
-    if (CPLIsNan(fCellheight)) {
+    const double dfCellheight = GetJsonValueDbl(pJSONObject, "cellheight");
+    if (CPLIsNan(dfCellheight)) {
         CPLError(CE_Failure, CPLE_AppDefined,
             "The ARG 'cellheight' is missing or invalid.");
         json_object_put(pJSONObject);
@@ -419,20 +379,20 @@ GDALDataset *ARGDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    fXSkew = GetJsonValueDbl(pJSONObject, "xskew");
-    if (CPLIsNan(fXSkew)) {
+    double dfXSkew = GetJsonValueDbl(pJSONObject, "xskew");
+    if (CPLIsNan(dfXSkew)) {
         // not an error -- default to 0.0
-        fXSkew = 0.0f;
+        dfXSkew = 0.0f;
     }
 
-    fYSkew = GetJsonValueDbl(pJSONObject, "yskew");
-    if (CPLIsNan(fYSkew)) {
+    double dfYSkew = GetJsonValueDbl(pJSONObject, "yskew");
+    if (CPLIsNan(dfYSkew)) {
         // not an error -- default to 0.0
-        fYSkew = 0.0f;
+        dfYSkew = 0.0f;
     }
 
     // get the rows
-    nRows = GetJsonValueInt(pJSONObject, "rows");
+    const int nRows = GetJsonValueInt(pJSONObject, "rows");
     if (nRows < 0) {
         CPLError(CE_Failure, CPLE_AppDefined,
             "The ARG 'rows' is missing or invalid.");
@@ -442,7 +402,7 @@ GDALDataset *ARGDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
     // get the columns
-    nCols = GetJsonValueInt(pJSONObject, "cols");
+    const int nCols = GetJsonValueInt(pJSONObject, "cols");
     if (nCols < 0) {
         CPLError(CE_Failure, CPLE_AppDefined,
             "The ARG 'cols' is missing or invalid.");
@@ -451,13 +411,14 @@ GDALDataset *ARGDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    nSrs = GetJsonValueInt(pJSONObject, "epsg");
+    int nSrs = GetJsonValueInt(pJSONObject, "epsg");
     if (nSrs < 0) {
         // not an error -- default to web mercator
         nSrs = 3857;
     }
 
-    nErr = oSRS.importFromEPSG(nSrs);
+    OGRSpatialReference oSRS;
+    OGRErr nErr = oSRS.importFromEPSG(nSrs);
     if (nErr != OGRERR_NONE) {
         nErr = oSRS.importFromEPSG(3857);
 
@@ -466,9 +427,10 @@ GDALDataset *ARGDataset::Open( GDALOpenInfo * poOpenInfo )
                 "The EPSG provided did not import cleanly. Defaulting to EPSG:3857");
         }
         else {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                "The 'epsg' value did not transate to a known spatial reference."
-                " Please check the 'epsg' value and try again.");
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "The 'epsg' value did not translate to a known "
+                      "spatial reference. "
+                      "Please check the 'epsg' value and try again.");
 
             json_object_put(pJSONObject);
             pJSONObject = NULL;
@@ -477,6 +439,7 @@ GDALDataset *ARGDataset::Open( GDALOpenInfo * poOpenInfo )
         }
     }
 
+    char *pszWKT = NULL;
     nErr = oSRS.exportToWkt(&pszWKT);
     if (nErr != OGRERR_NONE) {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -496,10 +459,11 @@ GDALDataset *ARGDataset::Open( GDALOpenInfo * poOpenInfo )
             "The ARG 'layer' is missing from the JSON file.");
         json_object_put(pJSONObject);
         pJSONObject = NULL;
+        CPLFree(pszWKT);
         return NULL;
     }
 
-    pszLayer = CPLStrdup(pszJSONStr);
+    char *pszLayer = CPLStrdup(pszJSONStr);
 
     // done with the json object now
     json_object_put(pJSONObject);
@@ -508,9 +472,7 @@ GDALDataset *ARGDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    ARGDataset *poDS;
-
-    poDS = new ARGDataset();
+    ARGDataset *poDS = new ARGDataset();
 
     poDS->pszFilename = CPLStrdup(poOpenInfo->pszFilename);
     poDS->SetMetadataItem("LAYER",pszLayer,NULL);
@@ -534,37 +496,36 @@ GDALDataset *ARGDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    poDS->adfGeoTransform[0] = fXmin;
-    poDS->adfGeoTransform[1] = fCellwidth;
-    poDS->adfGeoTransform[2] = fXSkew;
-    poDS->adfGeoTransform[3] = fYmax;
-    poDS->adfGeoTransform[4] = fYSkew;
-    poDS->adfGeoTransform[5] = -fCellheight;
-    
+    poDS->adfGeoTransform[0] = dfXmin;
+    poDS->adfGeoTransform[1] = dfCellwidth;
+    poDS->adfGeoTransform[2] = dfXSkew;
+    poDS->adfGeoTransform[3] = dfYmax;
+    poDS->adfGeoTransform[4] = dfYSkew;
+    poDS->adfGeoTransform[5] = -dfCellheight;
+
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    RawRasterBand *poBand;
-
 #ifdef CPL_LSB
     int bNative = FALSE;
 #else
     int bNative = TRUE;
 #endif
 
-    poBand = new RawRasterBand( poDS, 1, poDS->fpImage,
-                                0, nPixelOffset, nPixelOffset * nCols,
-                                eType, bNative, TRUE );
+    RawRasterBand *poBand
+        = new RawRasterBand( poDS, 1, poDS->fpImage,
+                             0, nPixelOffset, nPixelOffset * nCols,
+                             eType, bNative, TRUE );
     poDS->SetBand( 1, poBand );
 
-    poBand->SetNoDataValue( fNoDataValue );
+    poBand->SetNoDataValue( dfNoDataValue );
 
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->TryLoadXML();
-    
+
 /* -------------------------------------------------------------------- */
 /*      Check for overviews.                                            */
 /* -------------------------------------------------------------------- */
@@ -576,49 +537,32 @@ GDALDataset *ARGDataset::Open( GDALOpenInfo * poOpenInfo )
 /************************************************************************/
 /*                          CreateCopy()                                */
 /************************************************************************/
-GDALDataset * ARGDataset::CreateCopy( const char * pszFilename,
-                                      GDALDataset * poSrcDS,
-                                      CPL_UNUSED int bStrict,
-                                      CPL_UNUSED char ** papszOptions,
-                                      CPL_UNUSED GDALProgressFunc pfnProgress,
-                                      CPL_UNUSED void * pProgressData )
+GDALDataset *ARGDataset::CreateCopy( const char *pszFilename,
+                                     GDALDataset *poSrcDS,
+                                     int /* bStrict */ ,
+                                     char ** /* papszOptions */ ,
+                                     GDALProgressFunc /* pfnProgress */ ,
+                                     void * /*pProgressData */ )
 {
-    int nBands = poSrcDS->GetRasterCount();
-    int nXSize = poSrcDS->GetRasterXSize();
-    int nYSize = poSrcDS->GetRasterYSize();
-    int nXBlockSize, nYBlockSize, nPixelOffset = 0;
-    GDALDataType eType;
-    CPLString osJSONFilename;
-    CPLString pszDataType;
-    json_object * poJSONObject = NULL;
-    double adfTransform[6];
-    GDALRasterBand * poSrcBand = NULL;
-    RawRasterBand * poDstBand = NULL;
-    VSILFILE * fpImage = NULL;
-    void * pabyData;
-    OGRSpatialReference oSRS;
-    char * pszWKT = NULL;
-    char ** pszTokens = NULL;
-    const char * pszLayer = NULL;
-    int nSrs = 0;
-    OGRErr nErr = OGRERR_NONE;
-    CPLErr eErr;
-
+    const int nBands = poSrcDS->GetRasterCount();
     if( nBands != 1 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
               "ARG driver doesn't support %d bands.  Must be 1 band.", nBands );
         return NULL;
     }
 
-    eType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
-    if( eType == GDT_Unknown || 
-        eType == GDT_CInt16 || 
+    CPLString pszDataType;
+    int nPixelOffset = 0;
+
+    GDALDataType eType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
+    if( eType == GDT_Unknown ||
+        eType == GDT_CInt16 ||
         eType == GDT_CInt32 ||
-        eType == GDT_CFloat32 || 
+        eType == GDT_CFloat32 ||
         eType == GDT_CFloat64 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "ARG driver doesn't support data type %s.",
                   GDALGetDataTypeName(eType) );
         return NULL;
@@ -652,16 +596,19 @@ GDALDataset * ARGDataset::CreateCopy( const char * pszFilename,
         nPixelOffset = 8;
     }
 
+    double adfTransform[6];
     poSrcDS->GetGeoTransform( adfTransform );
 
-    pszWKT = (char *)poSrcDS->GetProjectionRef();
-    nErr = oSRS.importFromWkt(&pszWKT);
+    char *pszWKT = const_cast<char *>(poSrcDS->GetProjectionRef());
+    OGRSpatialReference oSRS;
+    OGRErr nErr = oSRS.importFromWkt(&pszWKT);
     if (nErr != OGRERR_NONE) {
         CPLError( CE_Failure, CPLE_NotSupported,
               "Cannot import spatial reference WKT from source dataset.");
         return NULL;
     }
 
+    int nSrs = 0;
     if (oSRS.GetAuthorityCode("PROJCS") != NULL) {
         nSrs = atoi(oSRS.GetAuthorityCode("PROJCS"));
     }
@@ -677,12 +624,12 @@ GDALDataset * ARGDataset::CreateCopy( const char * pszFilename,
     /********************************************************************/
     /* Create JSON companion file.                                      */
     /********************************************************************/
-    osJSONFilename = GetJsonFilename(pszFilename);
+    const CPLString osJSONFilename = GetJsonFilename(pszFilename);
 
-    poJSONObject = json_object_new_object();
+    json_object *poJSONObject = json_object_new_object();
 
-    pszTokens = poSrcDS->GetMetadata();
-    pszLayer = CSLFetchNameValue(pszTokens, "LAYER");
+    char **pszTokens = poSrcDS->GetMetadata();
+    const char *pszLayer = CSLFetchNameValue(pszTokens, "LAYER");
 
     if ( pszLayer == NULL) {
         // Set the layer
@@ -701,6 +648,10 @@ GDALDataset * ARGDataset::CreateCopy( const char * pszFilename,
     json_object_object_add(poJSONObject, "type", json_object_new_string("arg"));
     // Set the datatype
     json_object_object_add(poJSONObject, "datatype", json_object_new_string(pszDataType));
+
+    const int nXSize = poSrcDS->GetRasterXSize();
+    const int nYSize = poSrcDS->GetRasterYSize();
+
     // Set the number of rows
     json_object_object_add(poJSONObject, "rows", json_object_new_int(nYSize));
     // Set the number of columns
@@ -726,8 +677,8 @@ GDALDataset * ARGDataset::CreateCopy( const char * pszFilename,
         json_object_object_add(poJSONObject, "epsg", json_object_new_int(nSrs));
     }
 
-    if (json_object_to_file((char *)osJSONFilename.c_str(), poJSONObject) < 0) {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+    if (json_object_to_file(const_cast<char *>(osJSONFilename.c_str()), poJSONObject) < 0) {
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "ARG driver can't write companion file.");
 
         json_object_put(poJSONObject);
@@ -739,10 +690,10 @@ GDALDataset * ARGDataset::CreateCopy( const char * pszFilename,
     json_object_put(poJSONObject);
     poJSONObject = NULL;
 
-    fpImage = VSIFOpenL(pszFilename, "wb");
+    VSILFILE *fpImage = VSIFOpenL(pszFilename, "wb");
     if (fpImage == NULL)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
               "ARG driver can't create data file %s.", pszFilename);
 
         // remove JSON file
@@ -752,7 +703,7 @@ GDALDataset * ARGDataset::CreateCopy( const char * pszFilename,
     }
 
     // only 1 raster band
-    poSrcBand = poSrcDS->GetRasterBand( 1 );
+    GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( 1 );
 
 #ifdef CPL_LSB
     int bNative = FALSE;
@@ -760,13 +711,14 @@ GDALDataset * ARGDataset::CreateCopy( const char * pszFilename,
     int bNative = TRUE;
 #endif
 
-    poDstBand = new RawRasterBand( fpImage, 0, nPixelOffset,
-                                   nPixelOffset * nXSize, eType, bNative,
-                                   nXSize, nYSize, TRUE, FALSE);
+    RawRasterBand *poDstBand = new RawRasterBand( fpImage, 0, nPixelOffset,
+                                                  nPixelOffset * nXSize, eType, bNative,
+                                                  nXSize, nYSize, TRUE, FALSE);
 
+    int nXBlockSize, nYBlockSize;
     poSrcBand->GetBlockSize(&nXBlockSize, &nYBlockSize);
 
-    pabyData = CPLMalloc(nXBlockSize * nPixelOffset);
+    void *pabyData = CPLMalloc(nXBlockSize * nPixelOffset);
 
     // convert any blocks into scanlines
     for (int nYBlock = 0; nYBlock * nYBlockSize < nYSize; nYBlock++) {
@@ -783,8 +735,8 @@ GDALDataset * ARGDataset::CreateCopy( const char * pszFilename,
                 else
                     nXValid = nXBlockSize;
 
-                eErr = poSrcBand->RasterIO(GF_Read, nXBlock * nXBlockSize, 
-                    nYBlock * nYBlockSize + nYScanline, nXValid, 1, pabyData, nXBlockSize, 
+                CPLErr eErr = poSrcBand->RasterIO(GF_Read, nXBlock * nXBlockSize,
+                    nYBlock * nYBlockSize + nYScanline, nXValid, 1, pabyData, nXBlockSize,
                     1, eType, 0, 0, NULL);
 
                 if (eErr != CE_None) {
@@ -797,8 +749,8 @@ GDALDataset * ARGDataset::CreateCopy( const char * pszFilename,
                     return NULL;
                 }
 
-                eErr = poDstBand->RasterIO(GF_Write, nXBlock * nXBlockSize, 
-                    nYBlock * nYBlockSize + nYScanline, nXValid, 1, pabyData, nXBlockSize, 
+                eErr = poDstBand->RasterIO(GF_Write, nXBlock * nXBlockSize,
+                    nYBlock * nYBlockSize + nYScanline, nXValid, 1, pabyData, nXBlockSize,
                     1, eType, 0, 0, NULL);
 
                 if (eErr != CE_None) {
@@ -818,7 +770,7 @@ GDALDataset * ARGDataset::CreateCopy( const char * pszFilename,
     delete poDstBand;
     VSIFCloseL( fpImage );
 
-    return (GDALDataset *)GDALOpen( pszFilename, GA_ReadOnly );
+    return reinterpret_cast<GDALDataset *>( GDALOpen( pszFilename, GA_ReadOnly ) );
 }
 
 /************************************************************************/
@@ -827,24 +779,22 @@ GDALDataset * ARGDataset::CreateCopy( const char * pszFilename,
 
 void GDALRegister_ARG()
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "ARG" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "ARG" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "ARG" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Azavea Raster Grid format" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#ARG" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnIdentify = ARGDataset::Identify;
-        poDriver->pfnOpen = ARGDataset::Open;
-        poDriver->pfnCreateCopy = ARGDataset::CreateCopy;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "ARG" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Azavea Raster Grid format" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_various.html#ARG" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnIdentify = ARGDataset::Identify;
+    poDriver->pfnOpen = ARGDataset::Open;
+    poDriver->pfnCreateCopy = ARGDataset::CreateCopy;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/blx/blx.c b/frmts/blx/blx.c
index 8f6b46c..fd7c5d1 100644
--- a/frmts/blx/blx.c
+++ b/frmts/blx/blx.c
@@ -11,10 +11,10 @@
  * copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following
  * conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be
  * included in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -54,70 +54,70 @@ static const int table1[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 			,255,255,255,255,255,255,255,255,255,255};
 
 /* { byte, n of bits when compressed, bit pattern << (13-n of bits) } */
-static const int table2[][3] = {{0,2,0}, {255,3,2048}, {1,3,3072}, {2,4,4096}, 
-			  {3,4,4608}, {254,5,5120}, {4,5,5376}, {5,5,5632}, 
-			  {253,6,5888}, {6,6,6016}, {252,6,6144}, {7,6,6272}, 
-			  {251,6,6400}, {8,6,6528}, {9,7,6656}, {250,7,6720}, 
-			  {10,7,6784}, {249,7,6848}, {11,7,6912}, {248,7,6976}, 
-			  {12,8,7040}, {247,8,7072}, {16,8,7104}, {246,8,7136}, 
-			  {13,8,7168}, {245,8,7200}, {14,8,7232}, {244,8,7264}, 
-			  {15,8,7296}, {243,8,7328}, {242,8,7360}, {241,8,7392}, 
-			  {17,9,7424}, {18,9,7440}, {240,9,7456}, {239,9,7472}, 
-			  {19,9,7488}, {238,9,7504}, {20,9,7520}, {237,9,7536}, 
-			  {21,9,7552}, {236,9,7568}, {22,9,7584}, {235,9,7600}, 
-			  {234,9,7616}, {23,9,7632}, {233,9,7648}, {24,10,7664}, 
-			  {232,10,7672}, {231,10,7680}, {25,10,7688}, {230,10,7696}, 
-			  {229,10,7704}, {26,10,7712}, {228,10,7720}, {27,10,7728}, 
-			  {227,10,7736}, {225,10,7744}, {226,10,7752}, {28,10,7760}, 
-			  {29,10,7768}, {224,10,7776}, {30,10,7784}, {31,10,7792}, 
-			  {223,10,7800}, {32,10,7808}, {222,10,7816}, {33,10,7824}, 
-			  {221,11,7832}, {220,11,7836}, {34,11,7840}, {219,11,7844}, 
-			  {35,11,7848}, {218,11,7852}, {256,11,7856}, {36,11,7860}, 
-			  {217,11,7864}, {216,11,7868}, {37,11,7872}, {215,11,7876}, 
-			  {38,11,7880}, {214,11,7884}, {193,11,7888}, {213,11,7892}, 
-			  {39,11,7896}, {128,11,7900}, {212,11,7904}, {40,11,7908}, 
-			  {194,11,7912}, {211,11,7916}, {210,11,7920}, {41,11,7924}, 
-			  {209,11,7928}, {208,11,7932}, {42,11,7936}, {207,11,7940}, 
-			  {43,11,7944}, {195,11,7948}, {206,11,7952}, {205,11,7956}, 
-			  {204,11,7960}, {44,11,7964}, {203,11,7968}, {192,11,7972}, 
-			  {196,11,7976}, {45,11,7980}, {201,11,7984}, {200,11,7988}, 
-			  {197,11,7992}, {202,11,7996}, {127,11,8000}, {199,11,8004}, 
-			  {198,11,8008}, {46,12,8012}, {47,12,8014}, {48,12,8016}, 
-			  {49,12,8018}, {50,12,8020}, {51,12,8022}, {191,12,8024}, 
-			  {52,12,8026}, {183,12,8028}, {53,12,8030}, {54,12,8032}, 
-			  {55,12,8034}, {190,12,8036}, {56,12,8038}, {57,12,8040}, 
-			  {189,12,8042}, {58,12,8044}, {176,12,8046}, {59,12,8048}, 
-			  {126,12,8050}, {60,12,8052}, {188,12,8054}, {61,12,8056}, 
-			  {63,12,8058}, {62,12,8060}, {64,12,8062}, {129,12,8064}, 
-			  {187,12,8066}, {186,12,8068}, {65,12,8070}, {66,12,8072}, 
-			  {185,12,8074}, {184,12,8076}, {68,12,8078}, {174,12,8080}, 
-			  {67,12,8082}, {182,13,8084}, {69,13,8085}, {180,13,8086}, 
-			  {181,13,8087}, {71,13,8088}, {70,13,8089}, {179,13,8090}, 
-			  {125,13,8091}, {72,13,8092}, {130,13,8093}, {178,13,8094}, 
-			  {177,13,8095}, {73,13,8096}, {74,13,8097}, {124,13,8098}, 
-			  {76,13,8099}, {175,13,8100}, {75,13,8101}, {131,13,8102}, 
-			  {132,13,8103}, {79,13,8104}, {77,13,8105}, {123,13,8106}, 
-			  {80,13,8107}, {172,13,8108}, {171,13,8109}, {78,13,8110}, 
-			  {173,13,8111}, {81,13,8112}, {169,13,8113}, {122,13,8114}, 
-			  {82,13,8115}, {133,13,8116}, {168,13,8117}, {84,13,8118}, 
-			  {164,13,8119}, {167,13,8120}, {85,13,8121}, {170,13,8122}, 
-			  {166,13,8123}, {165,13,8124}, {121,13,8125}, {160,13,8126}, 
-			  {134,13,8127}, {136,13,8128}, {161,13,8129}, {120,13,8130}, 
-			  {88,13,8131}, {83,13,8132}, {119,13,8133}, {163,13,8134}, 
-			  {162,13,8135}, {159,13,8136}, {91,13,8137}, {135,13,8138}, 
-			  {90,13,8139}, {86,13,8140}, {137,13,8141}, {87,13,8142}, 
-			  {89,13,8143}, {158,13,8144}, {152,13,8145}, {138,13,8146}, 
-			  {139,13,8147}, {116,13,8148}, {140,13,8149}, {92,13,8150}, 
-			  {96,13,8151}, {157,13,8152}, {153,13,8153}, {97,13,8154}, 
-			  {94,13,8155}, {93,13,8156}, {117,13,8157}, {156,13,8158}, 
-			  {155,13,8159}, {95,13,8160}, {118,13,8161}, {143,13,8162}, 
-			  {151,13,8163}, {142,13,8164}, {104,13,8165}, {100,13,8166}, 
-			  {148,13,8167}, {144,13,8168}, {154,13,8169}, {115,13,8170}, 
-			  {113,13,8171}, {98,13,8172}, {146,13,8173}, {112,13,8174}, 
-			  {145,13,8175}, {149,13,8176}, {141,13,8177}, {150,13,8178}, 
-			  {103,13,8179}, {147,13,8180}, {99,13,8181}, {108,13,8182}, 
-			  {101,13,8183}, {114,13,8184}, {105,13,8185}, {102,13,8186}, 
-			  {107,13,8187}, {109,13,8188}, {110,13,8189}, {111,13,8190}, 
+static const int table2[][3] = {{0,2,0}, {255,3,2048}, {1,3,3072}, {2,4,4096},
+			  {3,4,4608}, {254,5,5120}, {4,5,5376}, {5,5,5632},
+			  {253,6,5888}, {6,6,6016}, {252,6,6144}, {7,6,6272},
+			  {251,6,6400}, {8,6,6528}, {9,7,6656}, {250,7,6720},
+			  {10,7,6784}, {249,7,6848}, {11,7,6912}, {248,7,6976},
+			  {12,8,7040}, {247,8,7072}, {16,8,7104}, {246,8,7136},
+			  {13,8,7168}, {245,8,7200}, {14,8,7232}, {244,8,7264},
+			  {15,8,7296}, {243,8,7328}, {242,8,7360}, {241,8,7392},
+			  {17,9,7424}, {18,9,7440}, {240,9,7456}, {239,9,7472},
+			  {19,9,7488}, {238,9,7504}, {20,9,7520}, {237,9,7536},
+			  {21,9,7552}, {236,9,7568}, {22,9,7584}, {235,9,7600},
+			  {234,9,7616}, {23,9,7632}, {233,9,7648}, {24,10,7664},
+			  {232,10,7672}, {231,10,7680}, {25,10,7688}, {230,10,7696},
+			  {229,10,7704}, {26,10,7712}, {228,10,7720}, {27,10,7728},
+			  {227,10,7736}, {225,10,7744}, {226,10,7752}, {28,10,7760},
+			  {29,10,7768}, {224,10,7776}, {30,10,7784}, {31,10,7792},
+			  {223,10,7800}, {32,10,7808}, {222,10,7816}, {33,10,7824},
+			  {221,11,7832}, {220,11,7836}, {34,11,7840}, {219,11,7844},
+			  {35,11,7848}, {218,11,7852}, {256,11,7856}, {36,11,7860},
+			  {217,11,7864}, {216,11,7868}, {37,11,7872}, {215,11,7876},
+			  {38,11,7880}, {214,11,7884}, {193,11,7888}, {213,11,7892},
+			  {39,11,7896}, {128,11,7900}, {212,11,7904}, {40,11,7908},
+			  {194,11,7912}, {211,11,7916}, {210,11,7920}, {41,11,7924},
+			  {209,11,7928}, {208,11,7932}, {42,11,7936}, {207,11,7940},
+			  {43,11,7944}, {195,11,7948}, {206,11,7952}, {205,11,7956},
+			  {204,11,7960}, {44,11,7964}, {203,11,7968}, {192,11,7972},
+			  {196,11,7976}, {45,11,7980}, {201,11,7984}, {200,11,7988},
+			  {197,11,7992}, {202,11,7996}, {127,11,8000}, {199,11,8004},
+			  {198,11,8008}, {46,12,8012}, {47,12,8014}, {48,12,8016},
+			  {49,12,8018}, {50,12,8020}, {51,12,8022}, {191,12,8024},
+			  {52,12,8026}, {183,12,8028}, {53,12,8030}, {54,12,8032},
+			  {55,12,8034}, {190,12,8036}, {56,12,8038}, {57,12,8040},
+			  {189,12,8042}, {58,12,8044}, {176,12,8046}, {59,12,8048},
+			  {126,12,8050}, {60,12,8052}, {188,12,8054}, {61,12,8056},
+			  {63,12,8058}, {62,12,8060}, {64,12,8062}, {129,12,8064},
+			  {187,12,8066}, {186,12,8068}, {65,12,8070}, {66,12,8072},
+			  {185,12,8074}, {184,12,8076}, {68,12,8078}, {174,12,8080},
+			  {67,12,8082}, {182,13,8084}, {69,13,8085}, {180,13,8086},
+			  {181,13,8087}, {71,13,8088}, {70,13,8089}, {179,13,8090},
+			  {125,13,8091}, {72,13,8092}, {130,13,8093}, {178,13,8094},
+			  {177,13,8095}, {73,13,8096}, {74,13,8097}, {124,13,8098},
+			  {76,13,8099}, {175,13,8100}, {75,13,8101}, {131,13,8102},
+			  {132,13,8103}, {79,13,8104}, {77,13,8105}, {123,13,8106},
+			  {80,13,8107}, {172,13,8108}, {171,13,8109}, {78,13,8110},
+			  {173,13,8111}, {81,13,8112}, {169,13,8113}, {122,13,8114},
+			  {82,13,8115}, {133,13,8116}, {168,13,8117}, {84,13,8118},
+			  {164,13,8119}, {167,13,8120}, {85,13,8121}, {170,13,8122},
+			  {166,13,8123}, {165,13,8124}, {121,13,8125}, {160,13,8126},
+			  {134,13,8127}, {136,13,8128}, {161,13,8129}, {120,13,8130},
+			  {88,13,8131}, {83,13,8132}, {119,13,8133}, {163,13,8134},
+			  {162,13,8135}, {159,13,8136}, {91,13,8137}, {135,13,8138},
+			  {90,13,8139}, {86,13,8140}, {137,13,8141}, {87,13,8142},
+			  {89,13,8143}, {158,13,8144}, {152,13,8145}, {138,13,8146},
+			  {139,13,8147}, {116,13,8148}, {140,13,8149}, {92,13,8150},
+			  {96,13,8151}, {157,13,8152}, {153,13,8153}, {97,13,8154},
+			  {94,13,8155}, {93,13,8156}, {117,13,8157}, {156,13,8158},
+			  {155,13,8159}, {95,13,8160}, {118,13,8161}, {143,13,8162},
+			  {151,13,8163}, {142,13,8164}, {104,13,8165}, {100,13,8166},
+			  {148,13,8167}, {144,13,8168}, {154,13,8169}, {115,13,8170},
+			  {113,13,8171}, {98,13,8172}, {146,13,8173}, {112,13,8174},
+			  {145,13,8175}, {149,13,8176}, {141,13,8177}, {150,13,8178},
+			  {103,13,8179}, {147,13,8180}, {99,13,8181}, {108,13,8182},
+			  {101,13,8183}, {114,13,8184}, {105,13,8185}, {102,13,8186},
+			  {107,13,8187}, {109,13,8188}, {110,13,8189}, {111,13,8190},
 			  {106,13,8191}, {0,0,8192}};
 
 static const int table3[] = {0x20, 0x2f, 0x44, 0x71, 0x95, 0x101};
@@ -131,17 +131,17 @@ STATIC int compress_chunk(unsigned char *inbuf, int inlen, unsigned char *outbuf
     while(next>=0) {
 	/* Find index of input byte in table2 and put it in j */
 	j=0;
-	while(next != table2[j][0]) j++; 
+	while(next != table2[j][0]) j++;
 
 	if(inlen) {
 	    next = *inbuf++;
 	    inlen--;
-	} else { 
+	} else {
 	    if(next == 0x100)
 		next = -1;
-	    else 
+	    else
 		next = 0x100;
-	}	
+	}
 	reg = (reg << table2[j][1]) | (table2[j][2] >> (13-table2[j][1]));
 	m += table2[j][1];
 
@@ -162,18 +162,18 @@ STATIC int compress_chunk(unsigned char *inbuf, int inlen, unsigned char *outbuf
 STATIC int uncompress_chunk(unsigned char *inbuf, int inlen, unsigned char *outbuf, int outbuflen) {
     int i,j,k,m=0, outlen=0;
     unsigned reg, newdata;
-    
+
     if (inlen < 4)
         return -1;
 
     reg = *(inbuf+3) | (*(inbuf+2)<<8) | (*(inbuf+1)<<16) | (*(inbuf+0)<<24);
     inbuf+=4; inlen-=4;
-    
+
     newdata = (reg>>19)&0x1fff;
 
     while(1) {
 	j = newdata >> 5;
-	
+
 	if(table1[j] == 0xff) {
 	    i=1;
 	    while((int)newdata >= table2[table3[i]][2]) i++;
@@ -181,8 +181,8 @@ STATIC int uncompress_chunk(unsigned char *inbuf, int inlen, unsigned char *outb
 	    j=table3[i-1];
 
             k = j + ((newdata-table2[j][2]) >> (13-table2[j][1]));
-	    
-	    if(table2[k][0] == 0x100) 
+
+	    if(table2[k][0] == 0x100)
 		break;
 	    else {
 		if(outlen>=outbuflen) return -1;
@@ -197,85 +197,82 @@ STATIC int uncompress_chunk(unsigned char *inbuf, int inlen, unsigned char *outb
 	}
 
 	m += table2[j][1];
-	
+
 	if(m>=19) {
-	    if(m>=8) {	
+	    if(m>=8) {
 		for(i=m>>3; i; i--) {
 		    if(inlen) {
 			reg = (reg << 8) | *inbuf++;
 			inlen--;
-		    } else 
+		    } else
 			reg = reg << 8;
 		}
 	    }
 	    m = m&7;
-	}	
+	}
 	newdata = (reg >> (19-m)) & 0x1fff;
     }
     return outlen;
 }
 
 /*
-  Reconstruct a new detail level with double resolution in the horizontal direction 
-  from data from the previous detail level and plus new differential data. 
+  Reconstruct a new detail level with double resolution in the horizontal direction
+  from data from the previous detail level and plus new differential data.
 */
 STATIC blxdata *reconstruct_horiz(blxdata *base, blxdata *diff, unsigned rows, unsigned cols, blxdata *out) {
     unsigned int i,j;
     blxdata tmp;
 
     /* Last column */
-    for(i=0; i<rows; i++)	
+    for(i=0; i<rows; i++)
 	out[2*(cols*i+cols-1)] = diff[cols*i+cols-1] + (((short)(base[cols*i+cols-2]-base[cols*i+cols-1]-1))>>2);
 
     /* Intermediate columns */
-    for(i=0; i<rows; i++)	
+    for(i=0; i<rows; i++)
 	for(j=cols-2; j>0; j--)
 	    out[2*(cols*i+j)] = diff[cols*i+j] + (((short)(base[cols*i+j] + 2*(base[cols*i+j-1]-out[2*(cols*i+j+1)])-3*base[cols*i+j+1]+1))>>3);
-    
+
     /* First column */
-    for(i=0; i<rows; i++)	
+    for(i=0; i<rows; i++)
 	out[2*cols*i] = diff[cols*i] + (((short)(base[cols*i]-base[cols*i+1]+1))>>2);
-	
+
     for(i=0; i<rows; i++)
 	for(j=0; j<cols; j++) {
 	    tmp=base[cols*i+j]+(((short)(out[2*(cols*i+j)]+1))>>1);
 	    out[2*cols*i+2*j+1] = tmp-out[2*(cols*i+j)];
 	    out[2*cols*i+2*j] = tmp;
-	}	
-
+	}
 
     return out;
 }
 
-
-
 /*
-  Reconstruct a new detail level with double resolution in the vertical direction 
-  from data from the previous detail level and plus new differential data. 
+  Reconstruct a new detail level with double resolution in the vertical direction
+  from data from the previous detail level and plus new differential data.
 */
 STATIC blxdata *reconstruct_vert(blxdata *base, blxdata *diff, unsigned rows, unsigned cols, blxdata *out) {
     unsigned int i,j;
     blxdata tmp;
-    
+
     /* Last row */
-    for(i=0; i<cols; i++)	
+    for(i=0; i<cols; i++)
 	out[2*cols*(rows-1)+i] = diff[cols*(rows-1)+i] + (((short)(base[cols*(rows-2)+i]-base[cols*(rows-1)+i]-1))>>2);
 
     /* Intermediate rows */
-    for(i=0; i<cols; i++)	
+    for(i=0; i<cols; i++)
 	for(j=rows-2; j>0; j--)
 	    out[2*cols*j+i] = diff[cols*j+i] + ((short)((base[cols*j+i] + 2*(base[cols*(j-1)+i]-out[2*cols*(j+1)+i])-3*base[cols*(j+1)+i]+1))>>3);
-    
+
     /* First row */
-    for(i=0; i<cols; i++)	
+    for(i=0; i<cols; i++)
 	out[i] = diff[i] + (((short)(base[i]-base[i+cols]+1))>>2);
-	
+
     for(i=0; i<cols; i++)
 	for(j=0; j<rows; j++) {
 	    tmp = base[cols*j+i]+(((short)(out[2*cols*j+i]+1))>>1);
 	    out[cols*(2*j+1)+i] = tmp-out[2*cols*j+i];
 	    out[cols*2*j+i] = tmp;
-	}	
+	}
     return out;
 }
 
@@ -293,20 +290,19 @@ STATIC void decimate_horiz(blxdata *in, unsigned int rows, unsigned int cols, bl
 	    base[i*cols/2+j/2] = in[i*cols+j]-(((short)(tmp+1))>>1);
 	}
     }
-    
-    
+
     /* First column */
     for(i=0; i<rows; i++) {
 	diff[cols/2*i] -= ((short)(base[i*cols/2]-base[i*cols/2+1]+1))>>2;
     }
 
     /* Intermediate columns */
-    for(i=0; i<rows; i++) 
-	for(j=1; j<cols/2-1; j++) 
+    for(i=0; i<rows; i++)
+	for(j=1; j<cols/2-1; j++)
 	    diff[cols/2*i+j] -= ((short)(base[cols/2*i+j] + 2*(base[cols/2*i+j-1]-diff[cols/2*i+j+1])-3*base[cols/2*i+j+1]+1))>>3;
-    
+
     /* Last column */
-    for(i=0; i<rows; i++)	
+    for(i=0; i<rows; i++)
 	diff[cols/2*i+cols/2-1] -= ((short)(base[i*cols/2+cols/2-2]-base[i*cols/2+cols/2-1]-1))>>2;
 }
 
@@ -323,47 +319,58 @@ STATIC void decimate_vert(blxdata *in, unsigned int rows, unsigned int cols, blx
 	    diff[i/2*cols+j] = tmp;
 	    base[i/2*cols+j] = in[i*cols+j]-(((short)(tmp+1))>>1);
 	}
-    
+
     /* First row */
     for(j=0; j<cols; j++)
 	diff[j] -= ((short)(base[j]-base[cols+j]+1))>>2;
 
-    
+
     /* Intermediate rows */
-    for(i=1; i<rows/2-1; i++)	
+    for(i=1; i<rows/2-1; i++)
 	for(j=0; j<cols; j++)
 	    diff[cols*i+j] -= ((short)(base[cols*i+j] + 2*(base[cols*(i-1)+j]-diff[cols*(i+1)+j])-3*base[cols*(i+1)+j]+1))>>3;
-    
+
     /* Last row */
     for(j=0; j<cols; j++)
 	diff[cols*(rows/2-1)+j] -= ((short)(base[cols*(rows/2-2)+j]-base[cols*(rows/2-1)+j]-1))>>2;
-	     
 }
 
-static int get_short_le(unsigned char **data) {
-    int result;
+typedef union
+{
+  short s;
+  unsigned short u;
+} unionshort;
 
-    result = *(*data) | (*((char *)*data+1)<<8);
+static int get_short_le(unsigned char **data) {
+    /* We assume two's complement representation for this to work */
+    unionshort result;
+    result.u = (unsigned short)(*(*data) | (*(*data+1)<<8));
     *data+=2;
-    return result;
+    return result.s;
 }
 
 static int get_short_be(unsigned char **data) {
-    int result;
-
-    result = *(*data+1) | (*((char *)*data)<<8);
+    /* We assume two's complement representation for this to work */
+    unionshort result;
+    result.u = (unsigned short)(*(*data+1) | (*(*data)<<8));
     *data+=2;
-    return result; 
+    return result.s;
 }
 
 static void put_short_le(short data, unsigned char **bufptr) {
-    *(*bufptr)++ = (unsigned char)(data & 0xff);
-    *(*bufptr)++ = (unsigned char)((data>>8) & 0xff);
+    /* We assume two's complement representation for this to work */
+    unionshort us;
+    us.s = data;
+    *(*bufptr)++ = (unsigned char)(us.u & 0xff);
+    *(*bufptr)++ = (unsigned char)((us.u>>8) & 0xff);
 }
 
 static void put_short_be(short data, unsigned char **bufptr) {
-    *(*bufptr)++ = (unsigned char)((data>>8) & 0xff);
-    *(*bufptr)++ = (unsigned char)(data & 0xff);
+    /* We assume two's complement representation for this to work */
+    unionshort us;
+    us.s = data;
+    *(*bufptr)++ = (unsigned char)((us.u>>8) & 0xff);
+    *(*bufptr)++ = (unsigned char)(us.u & 0xff);
 }
 
 
@@ -380,7 +387,7 @@ static int get_unsigned_short_be(unsigned char **data) {
 
     result = *(*data+1) | (*(*data)<<8);
     *data+=2;
-    return result; 
+    return result;
 }
 
 static void put_unsigned_short_le(unsigned short data, unsigned char **bufptr) {
@@ -397,7 +404,7 @@ static int get_short(blxcontext_t *ctx, unsigned char **data) {
 
     if(ctx->endian == LITTLEENDIAN)
 	return get_short_le(data);
-    else 
+    else
 	return get_short_be(data);
 }
 
@@ -405,46 +412,56 @@ static int get_unsigned_short(blxcontext_t *ctx, unsigned char **data) {
 
     if(ctx->endian == LITTLEENDIAN)
 	return get_unsigned_short_le(data);
-    else 
+    else
 	return get_unsigned_short_be(data);
 }
 
 static void put_short(blxcontext_t *ctx, short data, unsigned char **bufptr) {
     if(ctx->endian == LITTLEENDIAN)
 	put_short_le(data, bufptr);
-    else 
+    else
 	put_short_be(data, bufptr);
 }
 
 static void put_unsigned_short(blxcontext_t *ctx, unsigned short data, unsigned char **bufptr) {
     if(ctx->endian == LITTLEENDIAN)
 	put_unsigned_short_le(data, bufptr);
-    else 
+    else
 	put_unsigned_short_be(data, bufptr);
 }
 
+typedef union
+{
+  int i;
+  unsigned int u;
+} unionint;
+
 static int get_int32(blxcontext_t *ctx, unsigned char **data) {
-    int result;
+    /* We assume two's complement representation for this to work */
+    unionint result;
 
     if(ctx->endian == LITTLEENDIAN)
-	result = *(*data) | (*(*data+1)<<8) | (*(*data+2)<<16) | (*((char *)*data+3)<<24);
-    else 
-	result = *(*data+3) | (*(*data+2)<<8) | (*(*data+1)<<16) | (*((char *)*data)<<24);
+	result.u = *(*data) | (*(*data+1)<<8) | (*(*data+2)<<16) | (*(*data+3)<<24);
+    else
+	result.u = *(*data+3) | (*(*data+2)<<8) | (*(*data+1)<<16) | (*(*data)<<24);
     *data+=4;
-    return result;
+    return result.i;
 }
 
 static void put_int32(blxcontext_t *ctx, int data, unsigned char **bufptr) {
+    /* We assume two's complement representation for this to work */
+    unionint ui;
+    ui.i = data;
     if(ctx->endian == LITTLEENDIAN) {
-	*(*bufptr)++ = (unsigned char)(data & 0xff);
-	*(*bufptr)++ = (unsigned char)((data>>8) & 0xff);
-	*(*bufptr)++ = (unsigned char)((data>>16) & 0xff);
-	*(*bufptr)++ = (unsigned char)((data>>24) & 0xff);
+	*(*bufptr)++ = (unsigned char)(ui.u & 0xff);
+	*(*bufptr)++ = (unsigned char)((ui.u>>8) & 0xff);
+	*(*bufptr)++ = (unsigned char)((ui.u>>16) & 0xff);
+	*(*bufptr)++ = (unsigned char)((ui.u>>24) & 0xff);
     } else {
-	*(*bufptr)++ = (unsigned char)((data>>24) & 0xff);
-	*(*bufptr)++ = (unsigned char)((data>>16) & 0xff);
-	*(*bufptr)++ = (unsigned char)((data>>8) & 0xff);
-	*(*bufptr)++ = (unsigned char)(data & 0xff);
+	*(*bufptr)++ = (unsigned char)((ui.u>>24) & 0xff);
+	*(*bufptr)++ = (unsigned char)((ui.u>>16) & 0xff);
+	*(*bufptr)++ = (unsigned char)((ui.u>>8) & 0xff);
+	*(*bufptr)++ = (unsigned char)(ui.u & 0xff);
     }
 }
 
@@ -453,20 +470,20 @@ static int get_unsigned32(blxcontext_t *ctx, unsigned char **data) {
 
     if(ctx->endian == LITTLEENDIAN)
 	result = *(*data) | (*(*data+1)<<8) | (*(*data+2)<<16) | (*(*data+3)<<24);
-    else 
+    else
 	result = *(*data+3) | (*(*data+2)<<8) | (*(*data+1)<<16) | (*(*data)<<24);
     *data+=4;
     return result;
 }
 
 /* Check native endian order */
-int is_big_endian(void)
+static int is_big_endian(void)
 {
 	short int word = 0x0001;
 	char *byte = (char *) &word;
 	return (byte[0] ? 0:1);
 }
-double doubleSWAP(double df)
+static double doubleSWAP(double df)
 {
 	union
 	{
@@ -511,13 +528,13 @@ static void put_cellindex_entry(blxcontext_t *ctx, struct cellindex_s *ci, unsig
     put_unsigned_short(ctx, (unsigned short)ci->datasize, buffer);
     put_unsigned_short(ctx, (unsigned short)ci->compdatasize, buffer);
 }
-     
+
 /* Transpose matrix in-place */
 static void transpose(blxdata *data, int rows, int cols) {
     int i,j;
     blxdata tmp;
 
-    for(i=0; i<rows; i++)	
+    for(i=0; i<rows; i++)
 	for(j=i+1; j<cols; j++) {
 	    tmp=data[i*cols+j];
 	    data[i*cols+j]=data[j*cols+i];
@@ -528,8 +545,9 @@ static void transpose(blxdata *data, int rows, int cols) {
 struct lutentry_s {
     blxdata value;
     int frequency;
-};	
-int lutcmp(const void *aa, const void *bb) {
+};
+
+static int lutcmp(const void *aa, const void *bb) {
     const struct lutentry_s *a=aa, *b=bb;
 
     return b->frequency - a->frequency;
@@ -548,18 +566,20 @@ int blx_encode_celldata(blxcontext_t *ctx,
     struct lutentry_s lut[256];
     int lutsize=0;
 
-    int i,j;
-        
+    int i, j;
+
+    lut[0].value = 0;
+
     *p++ = (unsigned char)(side/32-4); /* Resolution */
-    
+
     /* Allocated memory for buffers */
     indata_scaled = BLXmalloc(sizeof(blxdata)*side*side);
     vdec = BLXmalloc(sizeof(blxdata)*side*side/2);
     vdiff = BLXmalloc(sizeof(blxdata)*side*side/2);
-    for(cn=0; cn<4; cn++) 
+    for(cn=0; cn<4; cn++)
 	c[cn] = BLXmalloc(sizeof(blxdata)*side*side/4);
     tc1 = BLXmalloc(sizeof(blxdata)*side*side/4);
-    tmpdata = BLXmalloc(5*4*side*side/4); 
+    tmpdata = BLXmalloc(5*4*side*side/4);
 
     /* Scale indata and process undefined values*/
     for(i=0; i<side*side; i++) {
@@ -569,7 +589,7 @@ int blx_encode_celldata(blxcontext_t *ctx,
     }
 
     indata = indata_scaled;
-    
+
     cout = tmpdata;
 
     for(level=0; level < 5; level++) {
@@ -579,14 +599,14 @@ int blx_encode_celldata(blxcontext_t *ctx,
 	decimate_vert(indata, side, side, vdec, vdiff);
 	decimate_horiz(vdec, side/2, side, c[0], c[1]);
 	decimate_horiz(vdiff, side/2, side, c[2], c[3]);
-	
+
 	/* For some reason the matrix is transposed if the lut is used for vdec_hdiff */
-	for(i=0; i<side/2; i++)	
+	for(i=0; i<side/2; i++)
 	    for(j=0; j<side/2; j++) {
 		tc1[j*side/2+i] = c[1][i*side/2+j];
 		tc1[i*side/2+j] = c[1][j*side/2+i];
 	    }
-	
+
 	for(cn=1; cn<4; cn++) {
 	    /* Use the possibly transposed version of c when building lut */
 	    if(cn==1)
@@ -599,13 +619,13 @@ int blx_encode_celldata(blxcontext_t *ctx,
 	    for(i=0; i<side*side/4; i++) {
 		/* Find element in lookup table */
 		for(j=0; (j<lutsize) && (lut[j].value != clut[i]); j++);
-		
+
 		if(clut[i] != 0) {
-		    if(j==lutsize) {	
-			lut[lutsize].value=clut[i];	
+		    if(j==lutsize) {
+			lut[lutsize].value=clut[i];
 			lut[lutsize].frequency=1;
 			lutsize++;
-			if(lutsize >= 255) 
+			if(lutsize >= 255)
 			    break;
 		    } else
 			lut[j].frequency++;
@@ -615,13 +635,13 @@ int blx_encode_celldata(blxcontext_t *ctx,
                 /* Since the Huffman table is arranged to let smaller number occupy
 		   less bits after the compression, the lookup table is sorted on frequency */
 		qsort(lut, lutsize, sizeof(struct lutentry_s), lutcmp);
-		
+
 		zeros = 0;
 		for(i=0; i<side*side/4; i++) {
-		    if(clut[i] == 0) 
+		    if(clut[i] == 0)
 			zeros++;
 		    if(((zeros>0) && (clut[i]!=0)) || (zeros >= 0x100-lutsize)) {
-			*cout++ = (unsigned char)(0x100-zeros);	
+			*cout++ = (unsigned char)(0x100-zeros);
 			zeros=0;
 		    }
 		    if(clut[i] != 0) {
@@ -629,23 +649,23 @@ int blx_encode_celldata(blxcontext_t *ctx,
 			*cout++ = (unsigned char)j;
 		    }
 		}
-		if(zeros>0) 
+		if(zeros>0)
 		    *cout++ = (unsigned char)(0x100-zeros);
 	    }
 	    /* Use the lookuptable only when it pays off to do do.
 	       For some reason there cannot be lookup tables in level 4.
                Otherwise Mapsend crashes. */
-	    coutsize = cout-coutstart;
+	    coutsize = (int)(cout-coutstart);
 	    if((lutsize < 255) && (coutsize+2*lutsize+1 < 2*side*side/4) && (level < 4)) {
 		*p++ = (unsigned char)(lutsize+1);
-		for(j=0; j<lutsize; j++) 
+		for(j=0; j<lutsize; j++)
 		    put_short_le(lut[j].value, &p);
 		put_short_le((short)coutsize, &p);
 
 		if(ctx->debug) {
 		    BLXdebug2("n=%d dlen=%d\n", lutsize+1, coutsize);
 		    BLXdebug0("lut={");
-		    for(i=0; i<lutsize; i++) 
+		    for(i=0; i<lutsize; i++)
 			BLXdebug1("%d, ",lut[i].value);
 		    BLXdebug0("}\n");
 		}
@@ -670,18 +690,18 @@ int blx_encode_celldata(blxcontext_t *ctx,
     *p++=0;
 
     BLXfree(indata_scaled);
-    BLXfree(vdec); BLXfree(vdiff); 
-    for(cn=0; cn<4; cn++) 
+    BLXfree(vdec); BLXfree(vdiff);
+    for(cn=0; cn<4; cn++)
 	BLXfree(c[cn]);
     BLXfree(tc1);
     BLXfree(tmpdata);
 
-    return p-outbuf;
+    return (int)(p-outbuf);
 }
 
 STATIC blxdata *decode_celldata(blxcontext_t *ctx, unsigned char *inbuf, int len, int *side, blxdata *outbuf, int outbufsize, int overviewlevel) {
     unsigned char *inptr=inbuf;
-    int resolution,div,level,c,n,i,j,dpos,v,tmp,a,value,index,step,cellsize;
+    int resolution,l_div,level,c,n,i,j,dpos,v,tmp,a,value,l_index,step,cellsize;
     int baseside[12];
     blxdata *base, *diff;
     struct component_s linfo[MAXLEVELS][MAXCOMPONENTS];
@@ -695,8 +715,8 @@ STATIC blxdata *decode_celldata(blxcontext_t *ctx, unsigned char *inbuf, int len
     len --;
 
     tmp = (resolution+4)*32;
-    for(div=1; div<12; div++) 
-	baseside[div-1] = tmp >> div;
+    for(l_div=1; l_div<12; l_div++)
+	baseside[l_div-1] = tmp >> l_div;
 
     if(side != NULL)
 	*side = tmp >> overviewlevel;
@@ -716,7 +736,7 @@ STATIC blxdata *decode_celldata(blxcontext_t *ctx, unsigned char *inbuf, int len
     if(ctx->debug) {
 	BLXdebug0("==============================\n");
     }
-    
+
     base = BLXmalloc(2 * baseside[0] * baseside[0] * sizeof(blxdata));
     diff = BLXmalloc(2 * baseside[0] * baseside[0] * sizeof(blxdata));
     if (base == NULL || diff == NULL)
@@ -741,21 +761,21 @@ STATIC blxdata *decode_celldata(blxcontext_t *ctx, unsigned char *inbuf, int len
             len --;
 	    linfo[level][c].n = n;
 	    if(n>0) {
-		linfo[level][c].lut = BLXmalloc(sizeof(blxdata)*(n-1));	
+		linfo[level][c].lut = BLXmalloc(sizeof(blxdata)*(n-1));
                 if (len < (int)sizeof(short) * n)
                 {
                     BLXerror0("Cell corrupt");
                     outbuf = NULL;
                     goto error;
                 }
-		for(i=0; i<n-1; i++) 
+		for(i=0; i<n-1; i++)
 		    linfo[level][c].lut[i] = (blxdata)get_short_le(&inptr);
 		linfo[level][c].dlen = get_short_le(&inptr);
                 len -= sizeof(short) * n;
 	    } else {
 		linfo[level][c].dlen = 0;
 	    }
-	}		
+	}
     }
 
     for(level=0; level < 5; level++) {
@@ -775,11 +795,11 @@ STATIC blxdata *decode_celldata(blxcontext_t *ctx, unsigned char *inbuf, int len
 	    if(ctx->debug) {
 		BLXdebug2("n=%d dlen=%d\n", linfo[level][c].n, linfo[level][c].dlen);
 		BLXdebug0("lut={");
-		for(i=0; i<linfo[level][c].n-1; i++) 
+		for(i=0; i<linfo[level][c].n-1; i++)
 		    BLXdebug1("%d, ",linfo[level][c].lut[i]);
 		BLXdebug0("}\n");
 	    }
-	    
+
 	    linfo[level][c].data = BLXmalloc(baseside[level]*baseside[level]*sizeof(blxdata));
             if (linfo[level][c].data == NULL)
             {
@@ -794,7 +814,7 @@ STATIC blxdata *decode_celldata(blxcontext_t *ctx, unsigned char *inbuf, int len
                     BLXerror0("Cell corrupt");
                     outbuf = NULL;
                     goto error;
-                }	
+                }
 		for(i=0; i<baseside[level]*baseside[level]; i++)
 		    linfo[level][c].data[i] = (blxdata)get_short(ctx, &inptr);
                 len -= sizeof(short) * baseside[level]*baseside[level];
@@ -827,23 +847,20 @@ STATIC blxdata *decode_celldata(blxcontext_t *ctx, unsigned char *inbuf, int len
 			linfo[level][c].data[dpos++]=linfo[level][c].lut[v];
                     }
 		}
-                len -= linfo[level][c].dlen;	
+                len -= linfo[level][c].dlen;
 		if(c==1)
-		    transpose(linfo[level][c].data, baseside[level], baseside[level]);	
+		    transpose(linfo[level][c].data, baseside[level], baseside[level]);
 	    }
 	    if(0 && ctx->debug) {
 		BLXdebug1("baseside:%d\n",baseside[level]);
 		BLXdebug0("data={");
-		for(i=0; i<baseside[level]*baseside[level]; i++) 
+		for(i=0; i<baseside[level]*baseside[level]; i++)
 		    BLXdebug1("%d, ",linfo[level][c].data[i]);
 		BLXdebug0("}\n");
 	    }
-
-
 	}
-
     }
-    
+
     if (len < (int)sizeof(short) * baseside[4]*baseside[4])
     {
         BLXerror0("Cell corrupt");
@@ -853,41 +870,40 @@ STATIC blxdata *decode_celldata(blxcontext_t *ctx, unsigned char *inbuf, int len
     for(i=0; i<baseside[4]*baseside[4]; i++)
 	linfo[4][0].data[i] = (blxdata)get_short(ctx, &inptr);
     len -=sizeof(short) * baseside[4]*baseside[4];
-    
+
     for(level=4; level >= overviewlevel; level--) {
 	if(ctx->debug) {
 	    BLXdebug1("baseside:%d\n",baseside[level]);
 	    BLXdebug0("inbase={");
-	    for(i=0; i<baseside[level]*baseside[level]; i++) 
+	    for(i=0; i<baseside[level]*baseside[level]; i++)
 		BLXdebug1("%d, ",linfo[level][0].data[i]);
 	    BLXdebug0("}\n");
 	    BLXdebug0("indiff={");
-	    for(i=0; i<baseside[level]*baseside[level]; i++) 
+	    for(i=0; i<baseside[level]*baseside[level]; i++)
 		BLXdebug1("%d, ",linfo[level][1].data[i]);
 	    BLXdebug0("}\n");
 	}
 
-
 	reconstruct_horiz(linfo[level][0].data, linfo[level][1].data, baseside[level], baseside[level], base);
 	if(ctx->debug) {
 	    BLXdebug0("base={");
-	    for(i=0; i<baseside[level]*baseside[level]; i++) 
+	    for(i=0; i<baseside[level]*baseside[level]; i++)
 		BLXdebug1("%d, ",base[i]);
 	    BLXdebug0("}\n");
 	}
 
-	reconstruct_horiz(linfo[level][2].data, linfo[level][3].data, baseside[level], baseside[level], diff);	
+	reconstruct_horiz(linfo[level][2].data, linfo[level][3].data, baseside[level], baseside[level], diff);
 	if(ctx->debug) {
 	    BLXdebug0("diff={");
-	    for(i=0; i<baseside[level]*baseside[level]; i++) 
+	    for(i=0; i<baseside[level]*baseside[level]; i++)
 		BLXdebug1("%d, ",diff[i]);
 	    BLXdebug0("}\n");
 	}
-	if(level>overviewlevel) 
+	if(level>overviewlevel)
 	    reconstruct_vert(base, diff, baseside[level], 2*baseside[level], linfo[level-1][0].data);
-	else	
+	else
 	    reconstruct_vert(base, diff, baseside[level], 2*baseside[level], outbuf);
-    }    
+    }
 
     if(overviewlevel == 0) {
         if (len < 1)
@@ -898,26 +914,26 @@ STATIC blxdata *decode_celldata(blxcontext_t *ctx, unsigned char *inbuf, int len
         }
 	a = *((char *)inptr++);
         len --;
-	index=0;
+	l_index=0;
 	while(len >= 3) {
 	    step = inptr[0] | (inptr[1]<<8); inptr+=2;
 	    value = *((char *)inptr++);
             len -= 3;
 
-	    index += step;
+	    l_index += step;
 
-	    if(value & 1) 
+	    if(value & 1)
 		value = (value-1)/2-a;
-	    else	
+	    else
 		value = value/2+a;
 
-	    if(index>=cellsize) {
+	    if(l_index>=cellsize) {
 		BLXerror0("Cell data corrupt\n");
 		outbuf = NULL;
 		goto error;
 	    }
 
-	    outbuf[index] = outbuf[index] + (blxdata)value;
+	    outbuf[l_index] = outbuf[l_index] + (blxdata)value;
 	}
 
         if (len != 0)
@@ -931,8 +947,15 @@ STATIC blxdata *decode_celldata(blxcontext_t *ctx, unsigned char *inbuf, int len
 
     /* Scale data */
     for(i=0; i<cellsize; i++)
-	outbuf[i] = outbuf[i] * (blxdata)ctx->zscale;
-
+    {
+        int val = outbuf[i] * (blxdata)ctx->zscale;
+        if( val < SHRT_MIN )
+            outbuf[i] = SHRT_MIN;
+        else if( val > SHRT_MAX )
+            outbuf[i] = SHRT_MAX;
+        else
+            outbuf[i] = (blxdata)val;
+    }
 
  error:
     if (base != NULL)
@@ -941,7 +964,7 @@ STATIC blxdata *decode_celldata(blxcontext_t *ctx, unsigned char *inbuf, int len
          BLXfree(diff);
 
     /* Free allocated memory */
-    for(level=4; level >= 0; level--) 
+    for(level=4; level >= 0; level--)
 	for(c=0; c<4; c++) {
 	    if(linfo[level][c].lut)
 		BLXfree(linfo[level][c].lut);
@@ -954,13 +977,13 @@ STATIC blxdata *decode_celldata(blxcontext_t *ctx, unsigned char *inbuf, int len
 
 blxcontext_t *blx_create_context() {
     blxcontext_t *c;
-    
+
     c = BLXmalloc(sizeof(blxcontext_t));
-    
+
     memset(c,0,sizeof(blxcontext_t));
-    
+
     c->cell_ysize = c->cell_xsize = 128;
-    
+
     c->minval = 32767;
     c->maxval = -32768;
 
@@ -968,14 +991,14 @@ blxcontext_t *blx_create_context() {
 
     c->zscale = 1;
 
-    c->fillundef = 1;	
+    c->fillundef = 1;
     c->fillundefval = 0;
 
     return c;
 }
 
 void blx_free_context(blxcontext_t *ctx) {
-    if(ctx->cellindex) 
+    if(ctx->cellindex)
 	BLXfree(ctx->cellindex);
 
     BLXfree(ctx);
@@ -993,16 +1016,16 @@ void blxprintinfo(blxcontext_t *ctx) {
     BLXnotice1("Max chunksize: %d\n", ctx->maxchunksize);
 }
 
-int blx_checkheader(char *header) {
-    short *signature=(short *)header;
+int blx_checkheader(const char *header) {
+    const short *signature=(const short *)header;
 
     return ((signature[0]==0x4) && (signature[1]==0x66)) ||
 	((signature[0]==0x400) && (signature[1]==0x6600));
 }
 
-void blx_generate_header(blxcontext_t *ctx, unsigned char *header) {
+static void blx_generate_header(blxcontext_t *ctx, unsigned char *header) {
     unsigned char *hptr = header;
-    
+
     memset(header, 0, 102);
 
     /* Write signature */
@@ -1021,7 +1044,7 @@ void blx_generate_header(blxcontext_t *ctx, unsigned char *header) {
     put_double(ctx, ctx->lon, &hptr); // 20
     put_double(ctx, -ctx->lat, &hptr); // 28
 
-    put_double(ctx, ctx->pixelsize_lon, &hptr);	// 36 
+    put_double(ctx, ctx->pixelsize_lon, &hptr);	// 36
     put_double(ctx, -ctx->pixelsize_lat, &hptr); // 44
 
     put_short(ctx, (short)ctx->minval, &hptr); // 52
@@ -1046,7 +1069,7 @@ int blx_writecell(blxcontext_t *ctx, blxdata *cell, int cellrow, int cellcol) {
 	    ctx->minval = cell[i];
 	if(cell[i]!=BLX_UNDEF)
 	    allundef=0;
-    }		
+    }
 
     if(allundef)
 	return status;
@@ -1063,11 +1086,11 @@ int blx_writecell(blxcontext_t *ctx, blxdata *cell, int cellrow, int cellcol) {
 	status=-2;
 	goto error;
     }
-    
+
     bufsize = sizeof(blxdata)*ctx->cell_xsize*ctx->cell_ysize+1024;
     uncompbuf = BLXmalloc(bufsize);
     outbuf = BLXmalloc(bufsize);
-    
+
     uncompsize = blx_encode_celldata(ctx, cell, ctx->cell_xsize, uncompbuf, bufsize);
     compsize = compress_chunk(uncompbuf, uncompsize, outbuf, bufsize);
     if (compsize < 0)
@@ -1079,18 +1102,18 @@ int blx_writecell(blxcontext_t *ctx, blxdata *cell, int cellrow, int cellcol) {
 
     if(uncompsize > ctx->maxchunksize)
 	ctx->maxchunksize = uncompsize;
-    
-    ctx->cellindex[cellrow*ctx->cell_cols + cellcol].offset = BLXftell(ctx->fh);
+
+    ctx->cellindex[cellrow*ctx->cell_cols + cellcol].offset = (int)BLXftell(ctx->fh);
     ctx->cellindex[cellrow*ctx->cell_cols + cellcol].datasize = uncompsize;
     ctx->cellindex[cellrow*ctx->cell_cols + cellcol].compdatasize = compsize;
-    
+
     if((int)BLXfwrite(outbuf, 1, compsize, ctx->fh) != compsize) {
 	status=-1;
 	goto error;
     }
-    
+
  error:
-    if(uncompbuf) 
+    if(uncompbuf)
 	BLXfree(uncompbuf);
     if(outbuf)
 	BLXfree(outbuf);
@@ -1118,7 +1141,7 @@ int blxopen(blxcontext_t *ctx, const char *filename, const char *rw) {
     hptr = header;
     if(ctx->write) {
 	blx_generate_header(ctx, header);
-	
+
 	if(BLXfwrite(header, 1, 102, ctx->fh) != 102)
 	    goto error;
 
@@ -1127,7 +1150,7 @@ int blxopen(blxcontext_t *ctx, const char *filename, const char *rw) {
 	    goto error;
 	}
 	memset(ctx->cellindex, 0, sizeof(struct cellindex_s) * ctx->cell_rows * ctx->cell_cols);
-	
+
 	/* Write the empty cell index (this will be overwritten when we have actual data)*/
 	for(i=0;i<ctx->cell_rows;i++)
 	    for(j=0;j<ctx->cell_cols;j++) {
@@ -1141,20 +1164,20 @@ int blxopen(blxcontext_t *ctx, const char *filename, const char *rw) {
 	/* Read header */
 	if(BLXfread(header, 1, 102, ctx->fh) != 102)
 	    goto error;
-    
+
 	signature[0] = get_short_le(&hptr);
 	signature[1] = get_short_le(&hptr);
 
-	/* Determine if the endianess of the BLX file */
-	if((signature[0] == 0x4) && (signature[1] == 0x66)) 
+	/* Determine if the endianness of the BLX file */
+	if((signature[0] == 0x4) && (signature[1] == 0x66))
 	    ctx->endian = LITTLEENDIAN;
-	else {	
+	else {
 	    hptr = header;
 	    signature[0] = get_short_be(&hptr);
 	    signature[1] = get_short_be(&hptr);
-	    if((signature[0] == 0x4) && (signature[1] == 0x66)) 
+	    if((signature[0] == 0x4) && (signature[1] == 0x66))
 		ctx->endian = BIGENDIAN;
-	    else 
+	    else
 		goto error;
 	}
 
@@ -1189,8 +1212,8 @@ int blxopen(blxcontext_t *ctx, const char *filename, const char *rw) {
 
 	ctx->pixelsize_lon = get_double(ctx, &hptr);
 	ctx->pixelsize_lat = -get_double(ctx, &hptr);
-    
-	ctx->minval = get_short(ctx, &hptr); 
+
+	ctx->minval = get_short(ctx, &hptr);
 	ctx->maxval = get_short(ctx, &hptr);
 	ctx->zscale = get_short(ctx, &hptr);
 	ctx->maxchunksize = get_int32(ctx, &hptr);
@@ -1207,7 +1230,7 @@ int blxopen(blxcontext_t *ctx, const char *filename, const char *rw) {
 		    goto error;
 		hptr=header;
 
-		ci = &ctx->cellindex[i*ctx->cell_cols + j];	
+		ci = &ctx->cellindex[i*ctx->cell_cols + j];
 		ci->offset = get_unsigned32(ctx, &hptr);
 		ci->datasize = get_unsigned_short(ctx, &hptr);
 		ci->compdatasize = get_unsigned_short(ctx, &hptr);
@@ -1227,10 +1250,13 @@ int blxclose(blxcontext_t *ctx) {
 
     if(ctx->write) {
 	/* Write updated header and cellindex */
-	BLXfseek(ctx->fh, 0, SEEK_SET);
+        if (BLXfseek(ctx->fh, 0, SEEK_SET) != 0) {
+            status=-1;
+            goto error;
+        }
 
 	blx_generate_header(ctx, header);
-	
+
 	if(BLXfwrite(header, 1, 102, ctx->fh) != 102) {
 	    status=-1;
 	    goto error;
@@ -1240,17 +1266,17 @@ int blxclose(blxcontext_t *ctx) {
 		hptr = header;
 		put_cellindex_entry(ctx, ctx->cellindex+i*ctx->cell_cols+j, &hptr);
 		if((int)BLXfwrite(header, 1, hptr-header, ctx->fh) != (int)(hptr-header)) {
-		    status=-1;	
+		    status=-1;
 		    break;
 		}
 	    }
     }
     ctx->open = 1;
 
- error:	
+ error:
     if(ctx->fh)
 	BLXfclose(ctx->fh);
-    
+
     return status;
 }
 
@@ -1261,7 +1287,7 @@ short *blx_readcell(blxcontext_t *ctx, int row, int col, short *buffer, int bufs
     int tmpbufsize,i;
     short *result=NULL;
     int npoints;
-    
+
     if((ctx==NULL) || (row >= ctx->cell_rows) || (col >= ctx->cell_cols))
 	return NULL;
 
@@ -1275,17 +1301,18 @@ short *blx_readcell(blxcontext_t *ctx, int row, int col, short *buffer, int bufs
 	for(i=0; i<npoints; i++)
 	    buffer[i] = BLX_UNDEF;
     } else {
-	BLXfseek(ctx->fh, ci->offset, SEEK_SET);
+	if(BLXfseek(ctx->fh, ci->offset, SEEK_SET) != 0)
+            goto error;
 
 	chunk = BLXmalloc(ci->datasize);
 	cchunk = BLXmalloc(ci->compdatasize);
 
-	if((chunk == NULL) || (cchunk == NULL)) 
+	if((chunk == NULL) || (cchunk == NULL))
 	    goto error;
-    
+
 	if(BLXfread(cchunk, 1, ci->compdatasize, ctx->fh) != ci->compdatasize)
 	    goto error;
-    
+
         if((unsigned int)uncompress_chunk(cchunk, ci->compdatasize, chunk, ci->datasize) != ci->datasize)
 	    goto error;
 
@@ -1293,10 +1320,10 @@ short *blx_readcell(blxcontext_t *ctx, int row, int col, short *buffer, int bufs
 	tmpbuf = BLXmalloc(tmpbufsize);
         if (tmpbuf == NULL)
             goto error;
-    
+
 	if (decode_celldata(ctx, chunk, ci->datasize, NULL, tmpbuf, tmpbufsize, overviewlevel) == NULL)
             goto error;
-    
+
 	for(i=0; i<npoints; i++)
 	    buffer[i] = tmpbuf[i];
     }
diff --git a/frmts/blx/blx.h b/frmts/blx/blx.h
index 5a88d15..c80d968 100644
--- a/frmts/blx/blx.h
+++ b/frmts/blx/blx.h
@@ -10,10 +10,10 @@
  * copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following
  * conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be
  * included in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -24,11 +24,16 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#ifndef _BLX_H_INCLUDED
-#define _BLX_H_INCLUDED
+#ifndef BLX_H_INCLUDED
+#define BLX_H_INCLUDED
 
 #include <stdio.h>
 
+#ifdef GDALDRIVER
+#include "cpl_conv.h"
+#include "cpl_vsi.h"
+#endif
+
 /* Constants */
 #define BLX_UNDEF -32768
 #define BLX_OVERVIEWLEVELS 4
@@ -42,7 +47,7 @@
 typedef short int blxdata;
 
 struct cellindex_s {
-    int offset;	
+    int offset;
     unsigned int datasize;       /* Uncompressed size */
     unsigned int compdatasize;   /* Compressed data size */
 };
@@ -61,14 +66,18 @@ struct blxcontext_s {
     int endian;
 
     struct cellindex_s *cellindex;
-    
+
     int debug;
 
     int fillundef;     /* If non-zero, fillundefval will be used instead of -32768 for undefined values in non-empty cells when
-			a cell is written */ 
-    int fillundefval; 
+			a cell is written */
+    int fillundefval;
 
+#ifdef GDALDRIVER
+    VSILFILE* fh;
+#else
     FILE *fh;
+#endif
     int write;
     int open;
 };
@@ -91,13 +100,12 @@ struct component_s {
 
 /* Define memory allocation and I/O function macros */
 #ifdef GDALDRIVER
-#include "cpl_conv.h"
-#define BLXfopen VSIFOpen
-#define BLXfclose VSIFClose
-#define BLXfread VSIFRead
-#define BLXfwrite VSIFWrite
-#define BLXfseek VSIFSeek
-#define BLXftell VSIFTell
+#define BLXfopen VSIFOpenL
+#define BLXfclose VSIFCloseL
+#define BLXfread VSIFReadL
+#define BLXfwrite VSIFWriteL
+#define BLXfseek VSIFSeekL
+#define BLXftell VSIFTellL
 #define BLXmalloc VSIMalloc
 #define BLXfree CPLFree
 #define BLXdebug0(text)              CPLDebug("BLX", text)
@@ -141,7 +149,7 @@ int blxclose(blxcontext_t *ctx);
 void blxprintinfo(blxcontext_t *ctx);
 short *blx_readcell(blxcontext_t *ctx, int row, int col, short *buffer, int bufsize, int overviewlevel);
 int blx_encode_celldata(blxcontext_t *ctx, blxdata *indata, int side, unsigned char *outbuf, int outbufsize);
-int blx_checkheader(char *header);
+int blx_checkheader(const char *header);
 int blx_writecell(blxcontext_t *ctx, blxdata *cell, int cellrow, int cellcol);
 
 #endif
diff --git a/frmts/blx/blxdataset.cpp b/frmts/blx/blxdataset.cpp
index 9075c22..a9c0ccd 100644
--- a/frmts/blx/blxdataset.cpp
+++ b/frmts/blx/blxdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: blxdataset.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: blxdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  BLX Driver
  * Purpose:  GDAL BLX support.
@@ -30,18 +30,15 @@
 *
 */
 
-#include "gdal_pam.h"
 #include "cpl_string.h"
-
-CPL_CVSID("$Id: blxdataset.cpp 28053 2014-12-04 09:31:07Z rouault $");
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
 
 CPL_C_START
 #include <blx.h>
 CPL_C_END
 
-CPL_C_START
-void    GDALRegister_BLX(void);
-CPL_C_END
+CPL_CVSID("$Id: blxdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 class BLXDataset : public GDALPamDataset
 {
@@ -66,6 +63,7 @@ class BLXDataset : public GDALPamDataset
 class BLXRasterBand : public GDALPamRasterBand
 {
     int overviewLevel;
+
   public:
     BLXRasterBand( BLXDataset *, int, int overviewLevel=0 );
 
@@ -80,25 +78,23 @@ class BLXRasterBand : public GDALPamRasterBand
 GDALDataset *BLXDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     //      First that the header looks like a BLX header
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     if( poOpenInfo->fpL == NULL || poOpenInfo->nHeaderBytes < 102 )
         return NULL;
 
-    if(!blx_checkheader((char *)poOpenInfo->pabyHeader))
+    if(!blx_checkheader((const char *)poOpenInfo->pabyHeader))
 	return NULL;
-    
-    // -------------------------------------------------------------------- 
-    //      Create a corresponding GDALDataset.                             
-    // -------------------------------------------------------------------- 
-    BLXDataset 	*poDS;
 
-    poDS = new BLXDataset();
+    // --------------------------------------------------------------------
+    //      Create a corresponding GDALDataset.
+    // --------------------------------------------------------------------
+    BLXDataset *poDS = new BLXDataset();
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     //      Open BLX file
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     poDS->blxcontext = blx_create_context();
     if(poDS->blxcontext==NULL)
     {
@@ -122,14 +118,14 @@ GDALDataset *BLXDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->nRasterXSize = poDS->blxcontext->xsize;
     poDS->nRasterYSize = poDS->blxcontext->ysize;
 
-    // -------------------------------------------------------------------- 
-    //      Create band information objects.                                
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
+    //      Create band information objects.
+    // --------------------------------------------------------------------
     poDS->nBands = 1;
     poDS->SetBand( 1, new BLXRasterBand( poDS, 1 ));
 
     // Create overview bands
-    poDS->nOverviewCount = BLX_OVERVIEWLEVELS;	
+    poDS->nOverviewCount = BLX_OVERVIEWLEVELS;
     for(int i=0; i < poDS->nOverviewCount; i++) {
 	poDS->papoOverviewDS[i] = new BLXDataset();
 	poDS->papoOverviewDS[i]->blxcontext = poDS->blxcontext;
@@ -139,14 +135,14 @@ GDALDataset *BLXDataset::Open( GDALOpenInfo * poOpenInfo )
 	poDS->nBands = 1;
 	poDS->papoOverviewDS[i]->SetBand(1, new BLXRasterBand( poDS->papoOverviewDS[i], 1, i+1));
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The BLX driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
@@ -161,12 +157,12 @@ GDALDataset *BLXDataset::Open( GDALOpenInfo * poOpenInfo )
     return( poDS );
 }
 
-BLXDataset::BLXDataset() {
-    blxcontext = NULL;
-    bIsOverview = FALSE;
-    nOverviewCount = 0;
-    
-    for(int i=0; i < nOverviewCount; i++)
+BLXDataset::BLXDataset() :
+    blxcontext(NULL),
+    nOverviewCount(0),
+    bIsOverview(FALSE)
+{
+    for(int i=0; i < BLX_OVERVIEWLEVELS; i++)
 	papoOverviewDS[i]=NULL;
 }
 
@@ -198,18 +194,22 @@ CPLErr BLXDataset::GetGeoTransform( double * padfTransform )
 
 const char *BLXDataset::GetProjectionRef()
 {
-    return( "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433],AUTHORITY[\"EPSG\",\"4326\"]]" );
+    return
+        "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\","
+        "SPHEROID[\"WGS 84\",6378137,298.257223563]],"
+        "PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433],"
+        "AUTHORITY[\"EPSG\",\"4326\"]]";
 }
 
-BLXRasterBand::BLXRasterBand( BLXDataset *poDS, int nBand, int overviewLevel )
+BLXRasterBand::BLXRasterBand( BLXDataset *poDSIn, int nBandIn, int overviewLevelIn )
 
 {
-    BLXDataset *poGDS = (BLXDataset *) poDS;
+    BLXDataset *poGDS = poDSIn;
+
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
+    this->overviewLevel = overviewLevelIn;
 
-    this->poDS = poDS;
-    this->nBand = nBand;
-    this->overviewLevel = overviewLevel;
-    
     eDataType = GDT_Int16;
 
     nBlockXSize = poGDS->blxcontext->cell_xsize >> overviewLevel;
@@ -218,26 +218,26 @@ BLXRasterBand::BLXRasterBand( BLXDataset *poDS, int nBand, int overviewLevel )
 
 int BLXRasterBand::GetOverviewCount()
 {
-    BLXDataset *poGDS = (BLXDataset *) poDS;
-    
+    BLXDataset *poGDS = reinterpret_cast<BLXDataset *>(poDS);
+
     return poGDS->nOverviewCount;
 }
 
 GDALRasterBand *BLXRasterBand::GetOverview( int i )
 {
-    BLXDataset        *poGDS = (BLXDataset *) poDS;
+    BLXDataset *poGDS = reinterpret_cast<BLXDataset *>(poDS);
 
     if( i < 0 || i >= poGDS->nOverviewCount )
 	return NULL;
-    else
-    	return poGDS->papoOverviewDS[i]->GetRasterBand(nBand);
+
+    return poGDS->papoOverviewDS[i]->GetRasterBand(nBand);
 }
 
 CPLErr BLXRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
-                                  void * pImage )
+                                  void *pImage )
 
 {
-    BLXDataset *poGDS = (BLXDataset *) poDS;
+    BLXDataset *poGDS = reinterpret_cast<BLXDataset *>(poDS);
 
     if(blx_readcell(poGDS->blxcontext, nBlockYOff, nBlockXOff, (short *)pImage, nBlockXSize*nBlockYSize*2, overviewLevel) == NULL) {
 	CPLError(CE_Failure, CPLE_AppDefined,
@@ -248,7 +248,7 @@ CPLErr BLXRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     return CE_None;
 }
 
-double BLXRasterBand::GetNoDataValue( int * pbSuccess )
+double BLXRasterBand::GetNoDataValue( int *pbSuccess )
 {
     if (pbSuccess)
         *pbSuccess = TRUE;
@@ -262,25 +262,18 @@ GDALColorInterp BLXRasterBand::GetColorInterpretation(void) {
 /* TODO: check if georeference is the same as for BLX files, WGS84
 */
 static GDALDataset *
-BLXCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
-                int bStrict, char ** papszOptions, 
-                GDALProgressFunc pfnProgress, void * pProgressData )
+BLXCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
+               int bStrict, char ** papszOptions,
+               GDALProgressFunc pfnProgress, void * pProgressData )
 
 {
-    int  nBands = poSrcDS->GetRasterCount();
-    int  nXSize = poSrcDS->GetRasterXSize();
-    int  nYSize = poSrcDS->GetRasterYSize();
-    
-    int zscale = 1;
-    int fillundef = 1, fillundefval = 0;
-    int endian = LITTLEENDIAN;
-
-// -------------------------------------------------------------------- 
-//      Some rudimentary checks                                    
-// -------------------------------------------------------------------- 
+// --------------------------------------------------------------------
+//      Some rudimentary checks
+// --------------------------------------------------------------------
+    const int nBands = poSrcDS->GetRasterCount();
     if( nBands != 1 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "BLX driver doesn't support %d bands.  Must be 1 (grey) ",
                   nBands );
         return NULL;
@@ -288,25 +281,28 @@ BLXCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
     if( poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Int16 && bStrict )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "BLX driver doesn't support data type %s. "
-                  "Only 16 bit byte bands supported.\n", 
-                  GDALGetDataTypeName( 
+                  "Only 16 bit byte bands supported.\n",
+                  GDALGetDataTypeName(
                       poSrcDS->GetRasterBand(1)->GetRasterDataType()) );
 
         return NULL;
     }
 
+    const int nXSize = poSrcDS->GetRasterXSize();
+    const int nYSize = poSrcDS->GetRasterYSize();
     if( (nXSize % 128 != 0) || (nYSize % 128 != 0) ) {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "BLX driver doesn't support dimensions that are not a multiple of 128.\n");
 
         return NULL;
     }
-    
-// -------------------------------------------------------------------- 
-//      What options has the user selected?                             
-// -------------------------------------------------------------------- 
+
+// --------------------------------------------------------------------
+//      What options has the user selected?
+// --------------------------------------------------------------------
+    int zscale = 1;
     if( CSLFetchNameValue(papszOptions,"ZSCALE") != NULL ) {
         zscale = atoi(CSLFetchNameValue(papszOptions,"ZSCALE"));
         if( zscale < 1 ) {
@@ -317,12 +313,12 @@ BLXCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         }
     }
 
-    if( CSLFetchNameValue(papszOptions,"FILLUNDEF") != NULL 
+    int fillundef = 1;
+    if( CSLFetchNameValue(papszOptions,"FILLUNDEF") != NULL
                 && EQUAL(CSLFetchNameValue(papszOptions,"FILLUNDEF"),"NO") )
 	fillundef = 0;
-    else	
-	fillundef = 1;
 
+    int fillundefval = 0;
     if( CSLFetchNameValue(papszOptions,"FILLUNDEFVAL") != NULL ) {
         fillundefval = atoi(CSLFetchNameValue(papszOptions,"FILLUNDEFVAL"));
         if( (fillundefval < -32768) || (fillundefval > 32767) ) {
@@ -332,19 +328,18 @@ BLXCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             return NULL;
         }
     }
-    if( CSLFetchNameValue(papszOptions,"BIGENDIAN") != NULL 
+
+    int endian = LITTLEENDIAN;
+    if( CSLFetchNameValue(papszOptions,"BIGENDIAN") != NULL
 	&& !EQUAL(CSLFetchNameValue(papszOptions,"BIGENDIAN"),"NO") )
 	endian = BIGENDIAN;
-	
-    
 
-// -------------------------------------------------------------------- 
-//      Create the dataset.                                             
-// -------------------------------------------------------------------- 
-    blxcontext_t *ctx;
+// --------------------------------------------------------------------
+//      Create the dataset.
+// --------------------------------------------------------------------
 
     // Create a BLX context
-    ctx = blx_create_context();
+    blxcontext_t *ctx = blx_create_context();
 
     // Setup BLX parameters
     ctx->cell_rows = nYSize / ctx->cell_ysize;
@@ -355,28 +350,27 @@ BLXCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     ctx->endian = endian;
 
     if(blxopen(ctx, pszFilename, "wb")) {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Unable to create blx file %s.\n", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Unable to create blx file %s.\n",
                   pszFilename );
         blx_free_context(ctx);
         return NULL;
     }
 
-// -------------------------------------------------------------------- 
-//      Loop over image, copying image data.                            
-// -------------------------------------------------------------------- 
-    GInt16     *pabyTile;
-    CPLErr      eErr=CE_None;
+// --------------------------------------------------------------------
+//      Loop over image, copying image data.
+// --------------------------------------------------------------------
 
-    pabyTile = (GInt16 *) VSIMalloc( sizeof(GInt16)*ctx->cell_xsize*ctx->cell_ysize );
+    GInt16 *pabyTile
+        = (GInt16 *) VSI_MALLOC_VERBOSE( sizeof(GInt16)*ctx->cell_xsize*ctx->cell_ysize );
     if (pabyTile == NULL)
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
         blxclose(ctx);
         blx_free_context(ctx);
         return NULL;
     }
 
+    CPLErr eErr=CE_None;
     if( !pfnProgress( 0.0, NULL, pProgressData ) )
         eErr = CE_Failure;
 
@@ -384,12 +378,12 @@ BLXCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 	for(int j=0; j < ctx->cell_cols; j++) {
 	    blxdata *celldata;
 	    GDALRasterBand * poBand = poSrcDS->GetRasterBand( 1 );
-	    eErr = poBand->RasterIO( GF_Read, j*ctx->cell_xsize, i*ctx->cell_ysize, 
-				     ctx->cell_xsize, ctx->cell_ysize, 
+	    eErr = poBand->RasterIO( GF_Read, j*ctx->cell_xsize, i*ctx->cell_ysize,
+				     ctx->cell_xsize, ctx->cell_ysize,
 				     pabyTile, ctx->cell_xsize, ctx->cell_ysize, GDT_Int16,
 				     0, 0, NULL );
-	    if(eErr >= CE_Failure) 
-	       break;
+	    if(eErr >= CE_Failure)
+	         break;
 	    celldata = pabyTile;
 	    if (blx_writecell(ctx, celldata, i, j) != 0)
             {
@@ -408,46 +402,45 @@ BLXCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
     CPLFree( pabyTile );
 
-    double        adfGeoTransform[6];
+    double adfGeoTransform[6];
     if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None )
     {
 	ctx->lon = adfGeoTransform[0];
 	ctx->lat = adfGeoTransform[3];
-	ctx->pixelsize_lon = adfGeoTransform[1];	
-	ctx->pixelsize_lat = adfGeoTransform[5];	
+	ctx->pixelsize_lon = adfGeoTransform[1];
+	ctx->pixelsize_lat = adfGeoTransform[5];
     }
 
     blxclose(ctx);
     blx_free_context(ctx);
 
     if (eErr == CE_None)
-        return (GDALDataset *) GDALOpen( pszFilename, GA_ReadOnly );
-    else
-        return NULL;
+        return reinterpret_cast<GDALDataset *>( GDALOpen( pszFilename, GA_ReadOnly ) );
+
+    return NULL;
 }
 
 
 void GDALRegister_BLX()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "BLX" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "BLX" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "BLX" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Magellan topo (.blx)" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#BLX" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "blx" );
-
-        poDriver->pfnOpen = BLXDataset::Open;
-	poDriver->pfnCreateCopy = BLXCreateCopy;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
-}
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "BLX" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Magellan topo (.blx)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_various.html#BLX" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "blx" );
 
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = BLXDataset::Open;
+    poDriver->pfnCreateCopy = BLXCreateCopy;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/frmts/blx/frmt_blx.html b/frmts/blx/frmt_blx.html
index 9394ca5..ec6e4d5 100644
--- a/frmts/blx/frmt_blx.html
+++ b/frmts/blx/frmt_blx.html
@@ -10,7 +10,7 @@
 <p>
 BLX is the format for storing topographic data in Magellan GPS units. This driver
 supports both reading and writing. In addition the 4 overview levels inherent in
-the BLX format can be used with the driver. 
+the BLX format can be used with the driver.
 </p>
 
 <p>
@@ -19,13 +19,13 @@ The BLX format is tile based, for the moment the tile size is fixed to 128x128 s
 
 <p>
 The data type is fixed to Int16 and the value for undefined values is fixed to -32768. In the BLX format undefined values are only really supported on tile level. For
-undefined pixels in non-empty tiles see the FILLUNDEF/FILLUNDEFVAL options. 
+undefined pixels in non-empty tiles see the FILLUNDEF/FILLUNDEFVAL options.
 </p>
 
 <h2>Georeferencing</h2>
 
 <p>
-The BLX projection is fixed to WGS84 and georeferencing from BLX is supported in the form of one tiepoint and 
+The BLX projection is fixed to WGS84 and georeferencing from BLX is supported in the form of one tiepoint and
 pixelsize.
 </p>
 
diff --git a/frmts/bmp/bmpdataset.cpp b/frmts/bmp/bmpdataset.cpp
index ed8be04..a5c358f 100644
--- a/frmts/bmp/bmpdataset.cpp
+++ b/frmts/bmp/bmpdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: bmpdataset.cpp 28234 2014-12-27 14:22:54Z rouault $
+ * $Id: bmpdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Microsoft Windows Bitmap
  * Purpose:  Read/write MS Windows Device Independent Bitmap (DIB) files
@@ -29,17 +29,14 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
 
-CPL_CVSID("$Id: bmpdataset.cpp 28234 2014-12-27 14:22:54Z rouault $");
-
-CPL_C_START
-void    GDALRegister_BMP(void);
-CPL_C_END
+CPL_CVSID("$Id: bmpdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 // Enable if you want to see lots of BMP debugging output.
-// #define BMP_DEBUG    
+// #define BMP_DEBUG
 
 enum BMPType
 {
@@ -53,7 +50,7 @@ enum BMPType
 // BMPInfoHeader structure. An array of BMPColorEntry structures (also called
 // a colour table) follows the bitmap information header structure. The colour
 // table is followed by a second array of indexes into the colour table (the
-// actual bitmap data). Data may be comressed, for 4-bpp and 8-bpp used RLE
+// actual bitmap data). Data may be compressed, for 4-bpp and 8-bpp used RLE
 // compression.
 //
 // +---------------------+
@@ -115,7 +112,7 @@ typedef struct
 } BMPFileHeader;
 
 // File header size in bytes:
-const int       BFH_SIZE = 14;
+static const int       BFH_SIZE = 14;
 
 typedef struct
 {
@@ -130,7 +127,7 @@ typedef struct
                                 // If 0 then the number of bits per pixel is
                                 // specified or is implied by the JPEG or PNG format.
     BMPComprMethod iCompression; // Compression method
-    GUInt32     iSizeImage;     // Size of uncomressed image in bytes. May be 0
+    GUInt32     iSizeImage;     // Size of uncompressed image in bytes. May be 0
                                 // for BMPC_RGB bitmaps. If iCompression is BI_JPEG
                                 // or BI_PNG, iSizeImage indicates the size
                                 // of the JPEG or PNG image buffer.
@@ -182,7 +179,7 @@ typedef struct
 
 /*****************************************************************/
 
-int countonbits(GUInt32 dw)
+static int countonbits(GUInt32 dw)
 {
     int r = 0;
     for(int x = 0; x < 32; x++)
@@ -194,7 +191,7 @@ int countonbits(GUInt32 dw)
 }
 
 
-int findfirstonbit(GUInt32 n)
+static int findfirstonbit(GUInt32 n)
 {
     for(int x = 0; x < 32; x++)
     {
@@ -218,7 +215,7 @@ class BMPDataset : public GDALPamDataset
 
     BMPFileHeader       sFileHeader;
     BMPInfoHeader       sInfoHeader;
-    int                 nColorTableSize, nColorElems;
+    int                 nColorElems;
     GByte               *pabyColorTable;
     GDALColorTable      *poColorTable;
     double              adfGeoTransform[6];
@@ -281,26 +278,27 @@ class BMPRasterBand : public GDALPamRasterBand
 /*                           BMPRasterBand()                            */
 /************************************************************************/
 
-BMPRasterBand::BMPRasterBand( BMPDataset *poDS, int nBand )
+BMPRasterBand::BMPRasterBand( BMPDataset *poDSIn, int nBandIn ) :
+    nScanSize(0)
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
     eDataType = GDT_Byte;
-    iBytesPerPixel = poDS->sInfoHeader.iBitCount / 8;
+    iBytesPerPixel = poDSIn->sInfoHeader.iBitCount / 8;
 
     // We will read one scanline per time. Scanlines in BMP aligned at 4-byte
     // boundary
     nBlockXSize = poDS->GetRasterXSize();
+    nBlockYSize = 1;
 
-    if (nBlockXSize < (INT_MAX - 31) / poDS->sInfoHeader.iBitCount)
+    if (nBlockXSize < (INT_MAX - 31) / poDSIn->sInfoHeader.iBitCount)
         nScanSize =
-            ((poDS->GetRasterXSize() * poDS->sInfoHeader.iBitCount + 31) & ~31) / 8;
+            ((poDS->GetRasterXSize() * poDSIn->sInfoHeader.iBitCount + 31) & ~31) / 8;
     else
     {
         pabyScan = NULL;
         return;
     }
-    nBlockYSize = 1;
 
 #ifdef BMP_DEBUG
     CPLDebug( "BMP",
@@ -330,7 +328,6 @@ CPLErr BMPRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 {
     BMPDataset  *poGDS = (BMPDataset *) poDS;
     GUInt32     iScanOffset;
-    int         i;
 
     if ( poGDS->sInfoHeader.iHeight > 0 )
         iScanOffset = poGDS->sFileHeader.iOffBits +
@@ -366,7 +363,7 @@ CPLErr BMPRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
         else
         {
             CPLError( CE_Failure, CPLE_FileIO,
-                      "Can't read from offset %ld in input file.", 
+                      "Can't read from offset %ld in input file.",
                       (long) iScanOffset );
             return CE_Failure;
         }
@@ -377,11 +374,11 @@ CPLErr BMPRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     {
         GByte *pabyTemp = pabyScan + 3 - nBand;
 
-        for ( i = 0; i < nBlockXSize; i++ )
+        for ( int i = 0; i < nBlockXSize; i++ )
         {
             // Colour triplets in BMP file organized in reverse order:
             // blue, green, red. When we have 32-bit BMP the forth byte
-            // in quadriplet should be discarded as it has no meaning.
+            // in quadruplet should be discarded as it has no meaning.
             // That is why we always use 3 byte count in the following
             // pabyTemp index.
             ((GByte *) pImage)[i] = *pabyTemp;
@@ -428,7 +425,7 @@ CPLErr BMPRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
             return CE_Failure;
         }
 
-        for(i = 0; i < 3; i++)
+        for( int i = 0; i < 3; i++)
         {
             shift[i] = findfirstonbit(mask[i]);
             size[i]  = countonbits(mask[i]);
@@ -442,13 +439,13 @@ CPLErr BMPRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
             fTo8bit[i] = 255.0f / ((1 << size[i])-1);
         }
 
-        for ( i = 0; i < nBlockXSize; i++ )
+        for( int i = 0; i < nBlockXSize; i++ )
         {
             ((GByte *) pImage)[i] = (GByte)
-                (0.5f + fTo8bit[nBand-1] * 
+                (0.5f + fTo8bit[nBand-1] *
                     ((pScan16[i] & mask[nBand-1]) >> shift[nBand-1]));
 #if 0
-        // original code    
+        // original code
             switch ( nBand )
             {
                 case 1: // Red
@@ -456,7 +453,7 @@ CPLErr BMPRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                 break;
 
                 case 2: // Green
-                ((GByte *) pImage)[i] = 
+                ((GByte *) pImage)[i] =
                     ((pabyScan[i] & 0x03) << 3) |
                     ((pabyScan[i + 1] & 0xE0) >> 5);
                 break;
@@ -474,7 +471,7 @@ CPLErr BMPRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     {
         GByte *pabyTemp = pabyScan;
 
-        for ( i = 0; i < nBlockXSize; i++ )
+        for ( int i = 0; i < nBlockXSize; i++ )
         {
             // Most significant part of the byte represents leftmost pixel
             if ( i & 0x01 )
@@ -487,7 +484,7 @@ CPLErr BMPRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     {
         GByte *pabyTemp = pabyScan;
 
-        for ( i = 0; i < nBlockXSize; i++ )
+        for( int i = 0; i < nBlockXSize; i++ )
         {
             switch ( i & 0x7 )
             {
@@ -532,15 +529,13 @@ CPLErr BMPRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                                    void * pImage )
 {
     BMPDataset  *poGDS = (BMPDataset *)poDS;
-    int         iInPixel, iOutPixel;
-    GUInt32     iScanOffset;
 
     CPLAssert( poGDS != NULL
                && nBlockXOff >= 0
                && nBlockYOff >= 0
                && pImage != NULL );
 
-    iScanOffset = poGDS->sFileHeader.iOffBits +
+    GUInt32 iScanOffset = poGDS->sFileHeader.iOffBits +
             ( poGDS->GetRasterYSize() - nBlockYOff - 1 ) * nScanSize;
     if ( VSIFSeekL( poGDS->fp, iScanOffset, SEEK_SET ) < 0 )
     {
@@ -557,7 +552,7 @@ CPLErr BMPRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
         VSIFSeekL( poGDS->fp, iScanOffset, SEEK_SET );
     }
 
-    for ( iInPixel = 0, iOutPixel = iBytesPerPixel - nBand;
+    for ( int iInPixel = 0, iOutPixel = iBytesPerPixel - nBand;
           iInPixel < nBlockXSize; iInPixel++, iOutPixel += poGDS->nBands )
     {
         pabyScan[iOutPixel] = ((GByte *) pImage)[iInPixel];
@@ -596,10 +591,6 @@ CPLErr BMPRasterBand::SetColorTable( GDALColorTable *poColorTable )
 
     if ( poColorTable )
     {
-        GDALColorEntry  oEntry;
-        GUInt32         iULong;
-        unsigned int    i;
-
         poGDS->sInfoHeader.iClrUsed = poColorTable->GetColorEntryCount();
         if ( poGDS->sInfoHeader.iClrUsed < 1 ||
              poGDS->sInfoHeader.iClrUsed > (1U << poGDS->sInfoHeader.iBitCount) )
@@ -607,22 +598,24 @@ CPLErr BMPRasterBand::SetColorTable( GDALColorTable *poColorTable )
 
         VSIFSeekL( poGDS->fp, BFH_SIZE + 32, SEEK_SET );
 
-        iULong = CPL_LSBWORD32( poGDS->sInfoHeader.iClrUsed );
+        GUInt32 iULong = CPL_LSBWORD32( poGDS->sInfoHeader.iClrUsed );
         VSIFWriteL( &iULong, 4, 1, poGDS->fp );
         poGDS->pabyColorTable = (GByte *) CPLRealloc( poGDS->pabyColorTable,
                         poGDS->nColorElems * poGDS->sInfoHeader.iClrUsed );
         if ( !poGDS->pabyColorTable )
             return CE_Failure;
 
-        for( i = 0; i < poGDS->sInfoHeader.iClrUsed; i++ )
+        for( unsigned int i = 0; i < poGDS->sInfoHeader.iClrUsed; i++ )
         {
+            GDALColorEntry  oEntry;
+
             poColorTable->GetColorEntryAsRGB( i, &oEntry );
             poGDS->pabyColorTable[i * poGDS->nColorElems + 3] = 0;
-            poGDS->pabyColorTable[i * poGDS->nColorElems + 2] = 
+            poGDS->pabyColorTable[i * poGDS->nColorElems + 2] =
                 (GByte) oEntry.c1; // Red
-            poGDS->pabyColorTable[i * poGDS->nColorElems + 1] = 
+            poGDS->pabyColorTable[i * poGDS->nColorElems + 1] =
                 (GByte) oEntry.c2; // Green
-            poGDS->pabyColorTable[i * poGDS->nColorElems] = 
+            poGDS->pabyColorTable[i * poGDS->nColorElems] =
                 (GByte) oEntry.c3;     // Blue
         }
 
@@ -693,21 +686,9 @@ class BMPComprRasterBand : public BMPRasterBand
 /*                           BMPComprRasterBand()                       */
 /************************************************************************/
 
-BMPComprRasterBand::BMPComprRasterBand( BMPDataset *poDS, int nBand )
-    : BMPRasterBand( poDS, nBand )
+BMPComprRasterBand::BMPComprRasterBand( BMPDataset *poDSIn, int nBandIn )
+    : BMPRasterBand( poDSIn, nBandIn )
 {
-    unsigned int    i, j, k, iLength = 0;
-    GUInt32         iComprSize, iUncomprSize;
-
-    iComprSize = poDS->sFileHeader.iSize - poDS->sFileHeader.iOffBits;
-    iUncomprSize = poDS->GetRasterXSize() * poDS->GetRasterYSize();
-
-#ifdef DEBUG
-    CPLDebug( "BMP", "RLE compression detected." );
-    CPLDebug ( "BMP", "Size of compressed buffer %ld bytes,"
-               " size of uncompressed buffer %ld bytes.",
-               (long) iComprSize, (long) iUncomprSize );
-#endif
     /* TODO: it might be interesting to avoid uncompressing the whole data */
     /* in a single pass, especially if nXSize * nYSize is big */
     /* We could read incrementally one row at a time */
@@ -719,6 +700,26 @@ BMPComprRasterBand::BMPComprRasterBand( BMPDataset *poDS, int nBand )
         pabyUncomprBuf = NULL;
         return;
     }
+
+    if( poDSIn->sFileHeader.iSize <= poDSIn->sFileHeader.iOffBits ||
+        poDSIn->sFileHeader.iSize - poDSIn->sFileHeader.iOffBits > INT_MAX )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, "Invalid header");
+        pabyComprBuf = NULL;
+        pabyUncomprBuf = NULL;
+        return;
+    }
+
+    GUInt32 iComprSize = poDSIn->sFileHeader.iSize - poDSIn->sFileHeader.iOffBits;
+    GUInt32 iUncomprSize = poDS->GetRasterXSize() * poDS->GetRasterYSize();
+
+#ifdef DEBUG
+    CPLDebug( "BMP", "RLE compression detected." );
+    CPLDebug ( "BMP", "Size of compressed buffer %ld bytes,"
+               " size of uncompressed buffer %ld bytes.",
+               (long) iComprSize, (long) iUncomprSize );
+#endif
+
     pabyComprBuf = (GByte *) VSIMalloc( iComprSize );
     pabyUncomprBuf = (GByte *) VSIMalloc( iUncomprSize );
     if (pabyComprBuf == NULL ||
@@ -731,17 +732,30 @@ BMPComprRasterBand::BMPComprRasterBand( BMPDataset *poDS, int nBand )
         return;
     }
 
-    VSIFSeekL( poDS->fp, poDS->sFileHeader.iOffBits, SEEK_SET );
-    VSIFReadL( pabyComprBuf, 1, iComprSize, poDS->fp );
-    i = 0;
-    j = 0;
-    if ( poDS->sInfoHeader.iBitCount == 8 )         // RLE8
+    if( VSIFSeekL( poDSIn->fp, poDSIn->sFileHeader.iOffBits, SEEK_SET ) != 0 ||
+        VSIFReadL( pabyComprBuf, 1, iComprSize, poDSIn->fp ) < iComprSize )
     {
-        while( j < iUncomprSize && i < iComprSize )
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Can't read from offset %ld in input file.",
+                  (long) poDSIn->sFileHeader.iOffBits );
+        CPLFree(pabyComprBuf);
+        pabyComprBuf = NULL;
+        CPLFree(pabyUncomprBuf);
+        pabyUncomprBuf = NULL;
+        return;
+    }
+    unsigned int k, iLength = 0;
+    unsigned int i = 0;
+    unsigned int j = 0;
+    if ( poDSIn->sInfoHeader.iBitCount == 8 )         // RLE8
+    {
+        while( i < iComprSize )
         {
             if ( pabyComprBuf[i] )
             {
                 iLength = pabyComprBuf[i++];
+                if( j == iUncomprSize )
+                    break;
                 while( iLength > 0 && j < iUncomprSize && i < iComprSize )
                 {
                     pabyUncomprBuf[j++] = pabyComprBuf[i];
@@ -752,6 +766,8 @@ BMPComprRasterBand::BMPComprRasterBand( BMPDataset *poDS, int nBand )
             else
             {
                 i++;
+                if( i == iComprSize )
+                    break;
                 if ( pabyComprBuf[i] == 0 )         // Next scanline
                 {
                     i++;
@@ -762,9 +778,14 @@ BMPComprRasterBand::BMPComprRasterBand( BMPDataset *poDS, int nBand )
                 }
                 else if ( pabyComprBuf[i] == 2 )    // Move to...
                 {
+                    if( j == iUncomprSize )
+                        break;
                     i++;
                     if ( i < iComprSize - 1 )
                     {
+                        if( pabyComprBuf[i+1] > INT_MAX / poDS->GetRasterXSize() ||
+                            static_cast<int>(pabyComprBuf[i+1]) * poDS->GetRasterXSize() > INT_MAX - static_cast<int>(j + pabyComprBuf[i]) )
+                            break;
                         j += pabyComprBuf[i] +
                              pabyComprBuf[i+1] * poDS->GetRasterXSize();
                         i += 2;
@@ -776,6 +797,8 @@ BMPComprRasterBand::BMPComprRasterBand( BMPDataset *poDS, int nBand )
                 {
                     if (i < iComprSize)
                         iLength = pabyComprBuf[i++];
+                    if( j == iUncomprSize )
+                        break;
                     for ( k = 0; k < iLength && j < iUncomprSize && i < iComprSize; k++ )
                         pabyUncomprBuf[j++] = pabyComprBuf[i++];
                     if ( i & 0x01 )
@@ -786,11 +809,13 @@ BMPComprRasterBand::BMPComprRasterBand( BMPDataset *poDS, int nBand )
     }
     else                                            // RLE4
     {
-        while( j < iUncomprSize && i < iComprSize )
+        while( i < iComprSize )
         {
             if ( pabyComprBuf[i] )
             {
                 iLength = pabyComprBuf[i++];
+                if( j == iUncomprSize )
+                    break;
                 while( iLength > 0 && j < iUncomprSize && i < iComprSize )
                 {
                     if ( iLength & 0x01 )
@@ -804,6 +829,8 @@ BMPComprRasterBand::BMPComprRasterBand( BMPDataset *poDS, int nBand )
             else
             {
                 i++;
+                if( i == iComprSize )
+                    break;
                 if ( pabyComprBuf[i] == 0 )         // Next scanline
                 {
                     i++;
@@ -814,9 +841,14 @@ BMPComprRasterBand::BMPComprRasterBand( BMPDataset *poDS, int nBand )
                 }
                 else if ( pabyComprBuf[i] == 2 )    // Move to...
                 {
+                    if( j == iUncomprSize )
+                        break;
                     i++;
                     if ( i < iComprSize - 1 )
                     {
+                        if( pabyComprBuf[i+1] > INT_MAX / poDS->GetRasterXSize() ||
+                            static_cast<int>(pabyComprBuf[i+1]) * poDS->GetRasterXSize() > INT_MAX - static_cast<int>(j + pabyComprBuf[i]) )
+                            break;
                         j += pabyComprBuf[i] +
                              pabyComprBuf[i+1] * poDS->GetRasterXSize();
                         i += 2;
@@ -828,6 +860,8 @@ BMPComprRasterBand::BMPComprRasterBand( BMPDataset *poDS, int nBand )
                 {
                     if (i < iComprSize)
                         iLength = pabyComprBuf[i++];
+                    if( j == iUncomprSize )
+                        break;
                     for ( k = 0; k < iLength && j < iUncomprSize && i < iComprSize; k++ )
                     {
                         if ( k & 0x01 )
@@ -841,9 +875,15 @@ BMPComprRasterBand::BMPComprRasterBand( BMPDataset *poDS, int nBand )
             }
         }
     }
+    /* Validate that we have read all compressed data (we tolerate missing */
+    /* end of image marker) and that we have filled all uncompressed data */
+    if( j < iUncomprSize || (i+1 != iComprSize && i+2 != iComprSize) )
+    {
+        CPLFree(pabyUncomprBuf);
+        pabyUncomprBuf = NULL;
+    }
     // rcg, release compressed buffer here.
-    if ( pabyComprBuf )
-        CPLFree( pabyComprBuf );
+    CPLFree( pabyComprBuf );
     pabyComprBuf = NULL;
 
 }
@@ -854,10 +894,8 @@ BMPComprRasterBand::BMPComprRasterBand( BMPDataset *poDS, int nBand )
 
 BMPComprRasterBand::~BMPComprRasterBand()
 {
-    if ( pabyComprBuf )
-        CPLFree( pabyComprBuf );
-    if ( pabyUncomprBuf )
-        CPLFree( pabyUncomprBuf );
+    CPLFree( pabyComprBuf );
+    CPLFree( pabyUncomprBuf );
 }
 
 /************************************************************************/
@@ -879,22 +917,21 @@ CPLErr BMPComprRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /*                           BMPDataset()                               */
 /************************************************************************/
 
-BMPDataset::BMPDataset()
+BMPDataset::BMPDataset() :
+    nColorElems(0), pabyColorTable(NULL),
+    poColorTable(NULL), bGeoTransformValid(FALSE), pszFilename(NULL), fp(NULL)
 {
-    pszFilename = NULL;
-    fp = NULL;
     nBands = 0;
-    bGeoTransformValid = FALSE;
+
+    memset( &sFileHeader, 0, sizeof(sFileHeader) );
+    memset( &sInfoHeader, 0, sizeof(sInfoHeader) );
+
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
-    pabyColorTable = NULL;
-    poColorTable = NULL;
-    memset( &sFileHeader, 0, sizeof(sFileHeader) );
-    memset( &sInfoHeader, 0, sizeof(sInfoHeader) );
 }
 
 /************************************************************************/
@@ -905,13 +942,12 @@ BMPDataset::~BMPDataset()
 {
     FlushCache();
 
-    if ( pabyColorTable )
-        CPLFree( pabyColorTable );
-    if ( poColorTable != NULL )
+    CPLFree( pabyColorTable );
+    if ( poColorTable )
         delete poColorTable;
-    if( fp != NULL )
-        VSIFCloseL( fp );
     CPLFree( pszFilename );
+    if( fp )
+        VSIFCloseL( fp );
 }
 
 /************************************************************************/
@@ -950,12 +986,11 @@ CPLErr BMPDataset::GetGeoTransform( double * padfTransform )
 
 CPLErr BMPDataset::SetGeoTransform( double * padfTransform )
 {
-    CPLErr              eErr = CE_None;
-
     if ( pszFilename && bGeoTransformValid )
     {
         memcpy( adfGeoTransform, padfTransform, sizeof(double) * 6 );
 
+        CPLErr eErr = CE_None;
         if ( GDALWriteWorldFile( pszFilename, "wld", adfGeoTransform )
              == FALSE )
         {
@@ -964,8 +999,8 @@ CPLErr BMPDataset::SetGeoTransform( double * padfTransform )
         }
         return eErr;
     }
-    else
-        return GDALPamDataset::SetGeoTransform( padfTransform );
+
+    return GDALPamDataset::SetGeoTransform( padfTransform );
 }
 
 /************************************************************************/
@@ -977,26 +1012,26 @@ CPLErr BMPDataset::SetGeoTransform( double * padfTransform )
 /*      for a given block together avoid extra seeks.                   */
 /************************************************************************/
 
-CPLErr BMPDataset::IRasterIO( GDALRWFlag eRWFlag, 
+CPLErr BMPDataset::IRasterIO( GDALRWFlag eRWFlag,
                               int nXOff, int nYOff, int nXSize, int nYSize,
-                              void *pData, int nBufXSize, int nBufYSize, 
+                              void *pData, int nBufXSize, int nBufYSize,
                               GDALDataType eBufType,
-                              int nBandCount, int *panBandMap, 
+                              int nBandCount, int *panBandMap,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
                               GSpacing nBandSpace,
                               GDALRasterIOExtraArg* psExtraArg )
 
 {
     if( nBandCount > 1 )
-        return GDALDataset::BlockBasedRasterIO( 
+        return GDALDataset::BlockBasedRasterIO(
             eRWFlag, nXOff, nYOff, nXSize, nYSize,
-            pData, nBufXSize, nBufYSize, eBufType, 
+            pData, nBufXSize, nBufYSize, eBufType,
             nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace, psExtraArg );
     else
-        return 
+        return
             GDALDataset::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                                    pData, nBufXSize, nBufYSize, eBufType, 
-                                    nBandCount, panBandMap, 
+                                    pData, nBufXSize, nBufYSize, eBufType,
+                                    nBandCount, panBandMap,
                                     nPixelSpace, nLineSpace, nBandSpace, psExtraArg );
 }
 
@@ -1008,11 +1043,11 @@ int BMPDataset::Identify( GDALOpenInfo *poOpenInfo )
 
 {
     if( poOpenInfo->nHeaderBytes < 2
-        || poOpenInfo->pabyHeader[0] != 'B' 
+        || poOpenInfo->pabyHeader[0] != 'B'
         || poOpenInfo->pabyHeader[1] != 'M' )
         return FALSE;
-    else
-        return TRUE;
+
+    return TRUE;
 }
 
 /************************************************************************/
@@ -1027,10 +1062,7 @@ GDALDataset *BMPDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    BMPDataset      *poDS;
-    VSIStatBufL     sStat;
-
-    poDS = new BMPDataset();
+    BMPDataset *poDS = new BMPDataset();
     poDS->eAccess = poOpenInfo->eAccess;
 
     if( poOpenInfo->eAccess == GA_ReadOnly )
@@ -1043,7 +1075,12 @@ GDALDataset *BMPDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    VSIStatL(poOpenInfo->pszFilename, &sStat);
+    VSIStatBufL sStat;
+    if (VSIStatL(poOpenInfo->pszFilename, &sStat) != 0)
+    {
+        delete poDS;
+        return NULL;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Read the BMPFileHeader. We need iOffBits value only             */
@@ -1064,14 +1101,13 @@ GDALDataset *BMPDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Read the BMPInfoHeader.                                         */
 /* -------------------------------------------------------------------- */
-    BMPType         eBMPType;
-
     VSIFSeekL( poDS->fp, BFH_SIZE, SEEK_SET );
     VSIFReadL( &poDS->sInfoHeader.iSize, 1, 4, poDS->fp );
 #ifdef CPL_MSB
     CPL_SWAP32PTR( &poDS->sInfoHeader.iSize );
 #endif
 
+    BMPType eBMPType;
     if ( poDS->sInfoHeader.iSize == BIH_WIN4SIZE )
         eBMPType = BMPT_WIN4;
     else if ( poDS->sInfoHeader.iSize == BIH_OS21SIZE )
@@ -1096,8 +1132,8 @@ GDALDataset *BMPDataset::Open( GDALOpenInfo * poOpenInfo )
         VSIFReadL( &poDS->sInfoHeader.iClrImportant, 1, 4, poDS->fp );
 
         // rcg, read win4/5 fields. If we're reading a
-        // legacy header that ends at iClrImportant, it turns 
-        // out that the three DWORD color table entries used 
+        // legacy header that ends at iClrImportant, it turns
+        // out that the three DWORD color table entries used
         // by the channel masks start here anyway.
         if(poDS->sInfoHeader.iCompression == BMPC_BITFIELDS)
         {
@@ -1123,12 +1159,12 @@ GDALDataset *BMPDataset::Open( GDALOpenInfo * poOpenInfo )
 #endif
         poDS->nColorElems = 4;
     }
-    
+
     if ( eBMPType == BMPT_OS22 )
     {
         poDS->nColorElems = 3; // FIXME: different info in different documents regarding this!
     }
-    
+
     if ( eBMPType == BMPT_OS21 )
     {
         GInt16  iShort;
@@ -1170,15 +1206,21 @@ GDALDataset *BMPDataset::Open( GDALOpenInfo * poOpenInfo )
               poDS->sInfoHeader.iClrUsed, poDS->sInfoHeader.iClrImportant );
 #endif
 
+    if( poDS->sInfoHeader.iHeight == INT_MIN )
+    {
+        delete poDS;
+        return NULL;
+    }
+
     poDS->nRasterXSize = poDS->sInfoHeader.iWidth;
     poDS->nRasterYSize = (poDS->sInfoHeader.iHeight > 0)?
         poDS->sInfoHeader.iHeight:-poDS->sInfoHeader.iHeight;
 
     if  (poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0)
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Invalid dimensions : %d x %d", 
-                  poDS->nRasterXSize, poDS->nRasterYSize); 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Invalid dimensions : %d x %d",
+                  poDS->nRasterXSize, poDS->nRasterYSize);
         delete poDS;
         return NULL;
     }
@@ -1189,30 +1231,44 @@ GDALDataset *BMPDataset::Open( GDALOpenInfo * poOpenInfo )
         case 4:
         case 8:
         {
-            int     i;
-
             poDS->nBands = 1;
+            int nColorTableSize;
+            int nMaxColorTableSize = 1 << poDS->sInfoHeader.iBitCount;
             // Allocate memory for colour table and read it
             if ( poDS->sInfoHeader.iClrUsed )
-                poDS->nColorTableSize = poDS->sInfoHeader.iClrUsed;
+            {
+                if( poDS->sInfoHeader.iClrUsed > (GUInt32)nMaxColorTableSize )
+                {
+                    CPLError(CE_Failure, CPLE_NotSupported,
+                             "Wrong value for iClrUsed: %u",
+                             poDS->sInfoHeader.iClrUsed );
+                    delete poDS;
+                    return NULL;
+                }
+                nColorTableSize = poDS->sInfoHeader.iClrUsed;
+            }
             else
-                poDS->nColorTableSize = 1 << poDS->sInfoHeader.iBitCount;
+                nColorTableSize = nMaxColorTableSize;
+
             poDS->pabyColorTable =
-                (GByte *)VSIMalloc2( poDS->nColorElems, poDS->nColorTableSize );
+                (GByte *)VSI_MALLOC2_VERBOSE( poDS->nColorElems, nColorTableSize );
             if (poDS->pabyColorTable == NULL)
             {
-                CPLError(CE_Failure, CPLE_OutOfMemory, "Color palette will be ignored");
-                poDS->nColorTableSize = 0;
                 break;
             }
 
-            VSIFSeekL( poDS->fp, BFH_SIZE + poDS->sInfoHeader.iSize, SEEK_SET );
-            VSIFReadL( poDS->pabyColorTable, poDS->nColorElems,
-                      poDS->nColorTableSize, poDS->fp );
+            if( VSIFSeekL( poDS->fp, BFH_SIZE + poDS->sInfoHeader.iSize, SEEK_SET ) != 0 ||
+                VSIFReadL( poDS->pabyColorTable, poDS->nColorElems,
+                           nColorTableSize, poDS->fp ) != (size_t)nColorTableSize )
+            {
+                CPLError(CE_Failure, CPLE_FileIO, "Cannot read color table");
+                delete poDS;
+                return NULL;
+            }
 
             GDALColorEntry oEntry;
             poDS->poColorTable = new GDALColorTable();
-            for( i = 0; i < poDS->nColorTableSize; i++ )
+            for( int i = 0; i < nColorTableSize; i++ )
             {
                 oEntry.c1 = poDS->pabyColorTable[i * poDS->nColorElems + 2]; // Red
                 oEntry.c2 = poDS->pabyColorTable[i * poDS->nColorElems + 1]; // Green
@@ -1236,12 +1292,10 @@ GDALDataset *BMPDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    int             iBand;
-
     if ( poDS->sInfoHeader.iCompression == BMPC_RGB
     ||   poDS->sInfoHeader.iCompression == BMPC_BITFIELDS )
     {
-        for( iBand = 1; iBand <= poDS->nBands; iBand++ )
+        for( int iBand = 1; iBand <= poDS->nBands; iBand++ )
         {
             BMPRasterBand* band = new BMPRasterBand( poDS, iBand );
             poDS->SetBand( iBand, band );
@@ -1257,7 +1311,7 @@ GDALDataset *BMPDataset::Open( GDALOpenInfo * poOpenInfo )
     else if ( poDS->sInfoHeader.iCompression == BMPC_RLE8
               || poDS->sInfoHeader.iCompression == BMPC_RLE4 )
     {
-        for( iBand = 1; iBand <= poDS->nBands; iBand++ )
+        for( int iBand = 1; iBand <= poDS->nBands; iBand++ )
         {
             BMPComprRasterBand* band = new BMPComprRasterBand( poDS, iBand );
             poDS->SetBand( iBand, band);
@@ -1333,9 +1387,7 @@ GDALDataset *BMPDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Create the dataset.                                             */
 /* -------------------------------------------------------------------- */
-    BMPDataset      *poDS;
-
-    poDS = new BMPDataset();
+    BMPDataset *poDS = new BMPDataset();
 
     poDS->fp = VSIFOpenL( pszFilename, "wb+" );
     if( poDS->fp == NULL )
@@ -1352,8 +1404,6 @@ GDALDataset *BMPDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Fill the BMPInfoHeader                                          */
 /* -------------------------------------------------------------------- */
-    GUInt32         nScanSize;
-
     poDS->sInfoHeader.iSize = 40;
     poDS->sInfoHeader.iWidth = nXSize;
     poDS->sInfoHeader.iHeight = nYSize;
@@ -1367,11 +1417,11 @@ GDALDataset *BMPDataset::Create( const char * pszFilename,
      *   nScanSize = ((poDS->sInfoHeader.iWidth *
      *            poDS->sInfoHeader.iBitCount + 31) & ~31) / 8
      *
-     * formulae, but we should check for overflow conditions
+     * formula, but we should check for overflow conditions
      * during calculation.
      */
-    nScanSize =
-        (GUInt32)poDS->sInfoHeader.iWidth * poDS->sInfoHeader.iBitCount + 31;
+    GUInt32 nScanSize
+        = (GUInt32)poDS->sInfoHeader.iWidth * poDS->sInfoHeader.iBitCount + 31;
     if ( !poDS->sInfoHeader.iWidth
          || !poDS->sInfoHeader.iBitCount
          || (nScanSize - 31) / poDS->sInfoHeader.iBitCount
@@ -1384,7 +1434,7 @@ GDALDataset *BMPDataset::Create( const char * pszFilename,
 
         return NULL;
     }
-    nScanSize = (nScanSize & ~31) / 8;
+    nScanSize = (nScanSize & ~31U) / 8;
 
     poDS->sInfoHeader.iSizeImage = nScanSize * poDS->sInfoHeader.iHeight;
     poDS->sInfoHeader.iXPelsPerMeter = 0;
@@ -1394,14 +1444,12 @@ GDALDataset *BMPDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Do we need colour table?                                        */
 /* -------------------------------------------------------------------- */
-    unsigned int    i;
-
     if ( nBands == 1 )
     {
         poDS->sInfoHeader.iClrUsed = 1 << poDS->sInfoHeader.iBitCount;
         poDS->pabyColorTable =
             (GByte *) CPLMalloc( poDS->nColorElems * poDS->sInfoHeader.iClrUsed );
-        for ( i = 0; i < poDS->sInfoHeader.iClrUsed; i++ )
+        for ( unsigned int i = 0; i < poDS->sInfoHeader.iClrUsed; i++ )
         {
             poDS->pabyColorTable[i * poDS->nColorElems] =
                 poDS->pabyColorTable[i * poDS->nColorElems + 1] =
@@ -1433,7 +1481,7 @@ GDALDataset *BMPDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
     if( VSIFWriteL( &poDS->sFileHeader.bType, 1, 2, poDS->fp ) != 2 )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   "Write of first 2 bytes to BMP file %s failed.\n"
                   "Is file system full?",
                   pszFilename );
@@ -1481,10 +1529,10 @@ GDALDataset *BMPDataset::Create( const char * pszFilename,
     if ( poDS->sInfoHeader.iClrUsed )
     {
         if( VSIFWriteL( poDS->pabyColorTable, 1,
-                        poDS->nColorElems * poDS->sInfoHeader.iClrUsed, poDS->fp ) 
+                        poDS->nColorElems * poDS->sInfoHeader.iClrUsed, poDS->fp )
             != poDS->nColorElems * poDS->sInfoHeader.iClrUsed )
         {
-            CPLError( CE_Failure, CPLE_FileIO, 
+            CPLError( CE_Failure, CPLE_FileIO,
                       "Error writing color table.  Is disk full?" );
             delete poDS;
 
@@ -1500,9 +1548,7 @@ GDALDataset *BMPDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    int         iBand;
-
-    for( iBand = 1; iBand <= poDS->nBands; iBand++ )
+    for( int iBand = 1; iBand <= poDS->nBands; iBand++ )
     {
         poDS->SetBand( iBand, new BMPRasterBand( poDS, iBand ) );
     }
@@ -1523,31 +1569,29 @@ GDALDataset *BMPDataset::Create( const char * pszFilename,
 void GDALRegister_BMP()
 
 {
-    GDALDriver  *poDriver;
-
-    if( GDALGetDriverByName( "BMP" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-
-        poDriver->SetDescription( "BMP" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "MS Windows Device Independent Bitmap" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "frmt_bmp.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "bmp" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    if( GDALGetDriverByName( "BMP" ) != NULL )
+      return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "BMP" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "MS Windows Device Independent Bitmap" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_bmp.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "bmp" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "   <Option name='WORLDFILE' type='boolean' description='Write out world file'/>"
 "</CreationOptionList>" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = BMPDataset::Open;
-        poDriver->pfnCreate = BMPDataset::Create;
-        poDriver->pfnIdentify = BMPDataset::Identify;
+    poDriver->pfnOpen = BMPDataset::Open;
+    poDriver->pfnCreate = BMPDataset::Create;
+    poDriver->pfnIdentify = BMPDataset::Identify;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/bpg/bpgdataset.cpp b/frmts/bpg/bpgdataset.cpp
index 4aefc49..a0a5aaf 100644
--- a/frmts/bpg/bpgdataset.cpp
+++ b/frmts/bpg/bpgdataset.cpp
@@ -28,8 +28,10 @@
  ****************************************************************************/
 
 #include <stdint.h>
-#include "gdal_pam.h"
+
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
 
 // NOTE: build instructions
 // bpg Makefile needs to be modified to have -fPIC on CFLAGS:= at line 49 and LDFLAGS at line 54 before building bpg
@@ -41,10 +43,6 @@ CPL_C_END
 
 CPL_CVSID("$Id$");
 
-CPL_C_START
-void    GDALRegister_BPG(void);
-CPL_C_END
-
 /************************************************************************/
 /* ==================================================================== */
 /*                               BPGDataset                             */
@@ -221,7 +219,7 @@ CPLErr BPGDataset::Uncompress()
         return CE_Failure;
     }
     BPGDecoderOutputFormat eOutputFormat;
-    
+
     if( GetRasterBand(1)->GetRasterDataType() == GDT_Byte )
         eOutputFormat = (nBands == 1 || nBands == 3) ? BPG_OUTPUT_FORMAT_RGB24 :
                                                        BPG_OUTPUT_FORMAT_RGBA32;
@@ -336,26 +334,24 @@ GDALDataset *BPGDataset::Open( GDALOpenInfo * poOpenInfo )
 void GDALRegister_BPG()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "BPG" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "BPG" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "BPG" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Better Portable Graphics" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "frmt_bpg.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "bpg" );
-        //poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/bpg" );
+    poDriver->SetDescription( "BPG" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Better Portable Graphics" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_bpg.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "bpg" );
+    // poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/bpg" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnIdentify = BPGDataset::Identify;
-        poDriver->pfnOpen = BPGDataset::Open;
+    poDriver->pfnIdentify = BPGDataset::Identify;
+    poDriver->pfnOpen = BPGDataset::Open;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/bsb/bsb2raw.c b/frmts/bsb/bsb2raw.c
index c7a6dcb..2d6ff41 100644
--- a/frmts/bsb/bsb2raw.c
+++ b/frmts/bsb/bsb2raw.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: bsb2raw.c 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: bsb2raw.c 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  BSB Reader
  * Purpose:  Test program for dumping BSB to PPM raster format.
@@ -32,7 +32,7 @@
 #include "cpl_conv.h"
 #include "bsb_read.h"
 
-CPL_CVSID("$Id: bsb2raw.c 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: bsb2raw.c 33717 2016-03-14 06:29:14Z goatbar $");
 
 /************************************************************************/
 /*                                main()                                */
@@ -46,7 +46,7 @@ int main( int nArgc, char **papszArgv )
     GByte	*pabyScanline;
     FILE	*fp;
     int         nError = 0;
-    
+
     if( nArgc < 3 )
     {
         fprintf( stderr, "Usage: bsb2raw src_file dst_file\n" );
@@ -63,7 +63,7 @@ int main( int nArgc, char **papszArgv )
         perror( "open" );
         exit( 1 );
     }
-    
+
     pabyScanline = (GByte *) CPLMalloc(psInfo->nXSize);
     for( iLine = 0; iLine < psInfo->nYSize; iLine++ )
     {
@@ -84,26 +84,23 @@ int main( int nArgc, char **papszArgv )
 /* -------------------------------------------------------------------- */
     fp = VSIFOpen( CPLResetExtension( papszArgv[2], "aux" ), "wt" );
 
-    fprintf( fp, "AuxilaryTarget: %s\n", 
+    fprintf( fp, "AuxilaryTarget: %s\n",
              CPLGetFilename(papszArgv[2]) );
 
-    fprintf( fp, "RawDefinition: %d %d 1\n", 
+    fprintf( fp, "RawDefinition: %d %d 1\n",
              psInfo->nXSize, psInfo->nYSize );
 
-    fprintf( fp, "ChanDefinition-1: 8U 0 1 %d Swapped\n", 
+    fprintf( fp, "ChanDefinition-1: 8U 0 1 %d Swapped\n",
              psInfo->nXSize );
 
     for( i = 0; i < psInfo->nPCTSize; i++ )
         fprintf( fp, "METADATA_IMG_1_Class_%d_Color: (RGB:%d %d %d)\n",
-                 i, 
+                 i,
                  psInfo->pabyPCT[i*3 + 0],
                  psInfo->pabyPCT[i*3 + 1],
                  psInfo->pabyPCT[i*3 + 2] );
-    
+
     VSIFClose( fp );
-    
 
     exit( 0 );
 }
-
-
diff --git a/frmts/bsb/bsb_read.c b/frmts/bsb/bsb_read.c
index 9c3f6be..ff1d2aa 100644
--- a/frmts/bsb/bsb_read.c
+++ b/frmts/bsb/bsb_read.c
@@ -1,13 +1,13 @@
 /******************************************************************************
- * $Id: bsb_read.c 32974 2016-01-13 22:38:54Z rouault $
+ * $Id: bsb_read.c 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  BSB Reader
  * Purpose:  Low level BSB Access API Implementation (non-GDAL).
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
- * NOTE: This code is implemented on the basis of work by Mike Higgins.  The 
- * BSB format is subject to US patent 5,727,090; however, that patent 
- * apparently only covers *writing* BSB files, not reading them, so this code 
+ * NOTE: This code is implemented on the basis of work by Mike Higgins.  The
+ * BSB format is subject to US patent 5,727,090; however, that patent
+ * apparently only covers *writing* BSB files, not reading them, so this code
  * should not be affected.
  *
  ******************************************************************************
@@ -37,7 +37,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: bsb_read.c 32974 2016-01-13 22:38:54Z rouault $");
+CPL_CVSID("$Id: bsb_read.c 33717 2016-03-14 06:29:14Z goatbar $");
 
 static int BSBReadHeaderLine( BSBInfo *psInfo, char* pszLine, int nLineMaxLen, int bNO1 );
 static int BSBSeekAndCheckScanlineNumber ( BSBInfo *psInfo, int nScanline,
@@ -52,59 +52,59 @@ Subject: Re: GISTrans: Maptech / NDI BSB Chart Format
 Mime-Version: 1.0
 Content-Type: text/plain; charset="us-ascii"; format=flowed
 
-         I did it! I just wrote a program that reads NOAA BSB chart files 
-and converts them to BMP files! BMP files are not the final goal of my 
-project, but it served as a proof-of-concept.  Next I will want to write 
-routines to extract pieces of the file at full resolution for printing, and 
-routines to filter pieces of the chart for display at lower resolution on 
-the screen.  (One of the terrible things about most chart display programs 
-is that they all sub-sample the charts instead of filtering it down). How 
+         I did it! I just wrote a program that reads NOAA BSB chart files
+and converts them to BMP files! BMP files are not the final goal of my
+project, but it served as a proof-of-concept.  Next I will want to write
+routines to extract pieces of the file at full resolution for printing, and
+routines to filter pieces of the chart for display at lower resolution on
+the screen.  (One of the terrible things about most chart display programs
+is that they all sub-sample the charts instead of filtering it down). How
 did I figure out how to read the BSB files?
 
-         If you recall, I have been trying to reverse engineer the file 
-formats of those nautical charts. When I am between projects I often do a 
-WEB search for the BSB file format to see if someone else has published a 
-hack for them. Monday I hit a NOAA project status report that mentioned 
-some guy named Marty Yellin who had recently completed writing a program to 
-convert BSB files to other file formats! I searched for him and found him 
-mentioned as a contact person for some NOAA program. I was composing a 
-letter to him in my head, or considering calling the NOAA phone number and 
-asking for his extension number, when I saw another NOAA status report 
-indicating that he had retired in 1998. His name showed up in a few more 
-reports, one of which said that he was the inventor of the BSB file format, 
-that it was patented (#5,727,090), and that the patent had been licensed to 
-Maptech (the evil company that will not allow anyone using their file 
-format to convert them to non-proprietary formats). Patents are readily 
-available on the WEB at the IBM patent server and this one is in the 
-dtabase!  I printed up a copy of the patent and of course it describes very 
-nicely (despite the usual typos and omissions of referenced items in the 
+         If you recall, I have been trying to reverse engineer the file
+formats of those nautical charts. When I am between projects I often do a
+WEB search for the BSB file format to see if someone else has published a
+hack for them. Monday I hit a NOAA project status report that mentioned
+some guy named Marty Yellin who had recently completed writing a program to
+convert BSB files to other file formats! I searched for him and found him
+mentioned as a contact person for some NOAA program. I was composing a
+letter to him in my head, or considering calling the NOAA phone number and
+asking for his extension number, when I saw another NOAA status report
+indicating that he had retired in 1998. His name showed up in a few more
+reports, one of which said that he was the inventor of the BSB file format,
+that it was patented (#5,727,090), and that the patent had been licensed to
+Maptech (the evil company that will not allow anyone using their file
+format to convert them to non-proprietary formats). Patents are readily
+available on the WEB at the IBM patent server and this one is in the
+dtabase!  I printed up a copy of the patent and of course it describes very
+nicely (despite the usual typos and omissions of referenced items in the
 figures) how to write one of these BSB files!
 
-         I was considering talking to a patent lawyer about the legality of 
+         I was considering talking to a patent lawyer about the legality of
 using information in the patent to read files without getting a license,
-when I noticed that the patent is only claiming programs that WRITE the 
-file format. I have noticed this before in RF patents where they describe 
-how to make a receiver and never bother to claim a transmitter. The logic 
-is that the transmitter is no good to anybody unless they license receivers 
-from the patent holder. But I think they did it backwards here! They should 
-have claimed a program that can READ the described file format. Now I can 
-read the files, build programs that read the files, and even sell them 
-without violating the claims in the patent! As long as I never try to write 
+when I noticed that the patent is only claiming programs that WRITE the
+file format. I have noticed this before in RF patents where they describe
+how to make a receiver and never bother to claim a transmitter. The logic
+is that the transmitter is no good to anybody unless they license receivers
+from the patent holder. But I think they did it backwards here! They should
+have claimed a program that can READ the described file format. Now I can
+read the files, build programs that read the files, and even sell them
+without violating the claims in the patent! As long as I never try to write
 one of the evil BSB files, I'm OK!!!
 
-         If you ever need to read these BSB chart programs, drop me a 
+         If you ever need to read these BSB chart programs, drop me a
 note.  I would be happy to send you a copy of this conversion program.
 
 ... later email ...
 
-         Well, here is my little proof of concept program. I hereby give 
+         Well, here is my little proof of concept program. I hereby give
 you permission to distribute it freely, modify for you own use, etc.
-I built it as a "WIN32 Console application" which means it runs in an MS 
-DOS box under Microsoft Windows. But the only Windows specific stuff in it 
-are the include files for the BMP file headers.  If you ripped out the BMP 
+I built it as a "WIN32 Console application" which means it runs in an MS
+DOS box under Microsoft Windows. But the only Windows specific stuff in it
+are the include files for the BMP file headers.  If you ripped out the BMP
 code it should compile under UNIX or anyplace else.
-         I'd be overjoyed to have you announce it to GISTrans or anywhere 
-else.  I'm philosophically opposed to the proprietary treatment of the  BSB 
+         I'd be overjoyed to have you announce it to GISTrans or anywhere
+else.  I'm philosophically opposed to the proprietary treatment of the  BSB
 file format and I want to break it open! Chart data for the People!
 
  ************************************************************************/
@@ -141,8 +141,8 @@ int BSBGetc( BSBInfo *psInfo, int bNO1, int* pbErrorFlag )
     if( psInfo->nBufferOffset >= psInfo->nBufferSize )
     {
         psInfo->nBufferOffset = 0;
-        psInfo->nBufferSize = 
-            VSIFReadL( psInfo->pabyBuffer, 1, psInfo->nBufferAllocation,
+        psInfo->nBufferSize =
+            (int)VSIFReadL( psInfo->pabyBuffer, 1, psInfo->nBufferAllocation,
                        psInfo->fp );
         if( psInfo->nBufferSize <= 0 )
         {
@@ -153,7 +153,7 @@ int BSBGetc( BSBInfo *psInfo, int bNO1, int* pbErrorFlag )
     }
 
     nByte = psInfo->pabyBuffer[psInfo->nBufferOffset++];
-    
+
     if( bNO1 )
     {
         nByte = nByte - 9;
@@ -195,7 +195,7 @@ BSBInfo *BSBOpen( const char *pszFilename )
     fp = VSIFOpenL( pszFilename, "rb" );
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "File %s not found.", pszFilename );
         return NULL;
     }
@@ -204,12 +204,12 @@ BSBInfo *BSBOpen( const char *pszFilename )
 /*	Read the first 1000 bytes, and verify that it contains the	*/
 /*	"BSB/" keyword"							*/
 /* -------------------------------------------------------------------- */
-    if( VSIFReadL( achTestBlock, 1, sizeof(achTestBlock), fp ) 
+    if( VSIFReadL( achTestBlock, 1, sizeof(achTestBlock), fp )
         != sizeof(achTestBlock) )
     {
         VSIFCloseL( fp );
         CPLError( CE_Failure, CPLE_FileIO,
-                  "Could not read first %d bytes for header!", 
+                  "Could not read first %d bytes for header!",
                   (int) sizeof(achTestBlock) );
         return NULL;
     }
@@ -217,7 +217,7 @@ BSBInfo *BSBOpen( const char *pszFilename )
     for( i = 0; (size_t)i < sizeof(achTestBlock) - 4; i++ )
     {
         /* Test for "BSB/" */
-        if( achTestBlock[i+0] == 'B' && achTestBlock[i+1] == 'S' 
+        if( achTestBlock[i+0] == 'B' && achTestBlock[i+1] == 'S'
             && achTestBlock[i+2] == 'B' && achTestBlock[i+3] == '/' )
             break;
 
@@ -238,7 +238,7 @@ BSBInfo *BSBOpen( const char *pszFilename )
     if( i == sizeof(achTestBlock) - 4 )
     {
         VSIFCloseL( fp );
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "This does not appear to be a BSB file, no BSB/ header." );
         return NULL;
     }
@@ -252,7 +252,7 @@ BSBInfo *BSBOpen( const char *pszFilename )
 
     psInfo->nBufferAllocation = 1024;
     psInfo->pabyBuffer = (GByte *) CPLMalloc(psInfo->nBufferAllocation);
-    psInfo->nBufferSize = 0; 
+    psInfo->nBufferSize = 0;
     psInfo->nBufferOffset = 0;
     psInfo->nSavedCharacter = -1000;
 
@@ -269,12 +269,12 @@ BSBInfo *BSBOpen( const char *pszFilename )
         if( szLine[0] != '\0' && szLine[1] != '\0' && szLine[2] != '\0' && szLine[3] == '/' )
         {
             psInfo->papszHeader = CSLAddString( psInfo->papszHeader, szLine );
-            papszTokens = CSLTokenizeStringComplex( szLine+4, ",=", 
+            papszTokens = CSLTokenizeStringComplex( szLine+4, ",=",
                                                     FALSE,FALSE);
             nCount = CSLCount(papszTokens);
         }
 
-        if( EQUALN(szLine,"BSB/",4) )
+        if( STARTS_WITH_CI(szLine, "BSB/") )
         {
             int		nRAIndex;
 
@@ -282,7 +282,7 @@ BSBInfo *BSBOpen( const char *pszFilename )
             if( nRAIndex < 0 || nRAIndex+2 >= nCount )
             {
                 CSLDestroy( papszTokens );
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "Failed to extract RA from BSB/ line." );
                 BSBClose( psInfo );
                 return NULL;
@@ -290,10 +290,10 @@ BSBInfo *BSBOpen( const char *pszFilename )
             psInfo->nXSize = atoi(papszTokens[nRAIndex+1]);
             psInfo->nYSize = atoi(papszTokens[nRAIndex+2]);
         }
-        else if( EQUALN(szLine,"NOS/",4) )
+        else if( STARTS_WITH_CI(szLine, "NOS/") )
         {
             int  nRAIndex;
-            
+
             nRAIndex = CSLFindString(papszTokens, "RA" );
             if( nRAIndex < 0 || nRAIndex+4 >= nCount )
             {
@@ -313,7 +313,7 @@ BSBInfo *BSBOpen( const char *pszFilename )
             if (iPCT < 0 || iPCT > 128)
             {
                 CSLDestroy( papszTokens );
-                CPLError( CE_Failure, CPLE_OutOfMemory, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                             "BSBOpen : Invalid color table index. Probably due to corrupted BSB file (iPCT = %d).",
                             iPCT);
                 BSBClose( psInfo );
@@ -321,19 +321,16 @@ BSBInfo *BSBOpen( const char *pszFilename )
             }
             if( iPCT > psInfo->nPCTSize-1 )
             {
-                unsigned char* pabyNewPCT = (unsigned char *) 
-                    VSIRealloc(psInfo->pabyPCT,(iPCT+1) * 3);
+                unsigned char* pabyNewPCT = (unsigned char *)
+                    VSI_REALLOC_VERBOSE(psInfo->pabyPCT,(iPCT+1) * 3);
                 if (pabyNewPCT == NULL)
                 {
                     CSLDestroy( papszTokens );
-                    CPLError( CE_Failure, CPLE_OutOfMemory, 
-                              "BSBOpen : Out of memory. Probably due to corrupted BSB file (iPCT = %d).",
-                              iPCT);
                     BSBClose( psInfo );
                     return NULL;
                 }
                 psInfo->pabyPCT = pabyNewPCT;
-                memset( psInfo->pabyPCT + psInfo->nPCTSize*3, 0, 
+                memset( psInfo->pabyPCT + psInfo->nPCTSize*3, 0,
                         (iPCT+1-psInfo->nPCTSize) * 3);
                 psInfo->nPCTSize = iPCT+1;
             }
@@ -342,29 +339,29 @@ BSBInfo *BSBOpen( const char *pszFilename )
             psInfo->pabyPCT[iPCT*3+1] = (unsigned char)atoi(papszTokens[2]);
             psInfo->pabyPCT[iPCT*3+2] = (unsigned char)atoi(papszTokens[3]);
         }
-        else if( EQUALN(szLine,"VER/",4) && nCount >= 1 )
+        else if( STARTS_WITH_CI(szLine, "VER/") && nCount >= 1 )
         {
             psInfo->nVersion = (int) (100 * CPLAtof(papszTokens[0]) + 0.5);
         }
 
         CSLDestroy( papszTokens );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Verify we found required keywords.                              */
 /* -------------------------------------------------------------------- */
     if( psInfo->nXSize == 0 || psInfo->nPCTSize == 0 )
     {
         BSBClose( psInfo );
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Failed to find required RGB/ or BSB/ keyword in header." );
-        
+
         return NULL;
     }
 
     if( psInfo->nXSize <= 0 || psInfo->nYSize <= 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Wrong dimensions found in header : %d x %d.",
                   psInfo->nXSize, psInfo->nYSize );
         BSBClose( psInfo );
@@ -384,10 +381,10 @@ BSBInfo *BSBOpen( const char *pszFilename )
 /*                                                                      */
 /*      We actually do some funny stuff here to be able to read past    */
 /*      some garbage to try and find the 0x1a 0x00 sequence since in    */
-/*      at least some files (ie. optech/World.kap) we find a few        */
+/*      at least some files (i.e. optech/World.kap) we find a few       */
 /*      bytes of extra junk in the way.                                 */
 /* -------------------------------------------------------------------- */
-/* from optech/World.kap 
+/* from optech/World.kap
 
    11624: 30333237 34353938 2C302E30 35373836 03274598,0.05786
    11640: 39303232 38332C31 332E3135 39363435 902283,13.159645
@@ -398,9 +395,9 @@ BSBInfo *BSBOpen( const char *pszFilename )
     {
         int    nChar = -1;
 
-        while( nSkipped < 100 
-              && (BSBGetc( psInfo, bNO1, &bErrorFlag ) != 0x1A 
-                  || (nChar = BSBGetc( psInfo, bNO1, &bErrorFlag )) != 0x00) 
+        while( nSkipped < 100
+              && (BSBGetc( psInfo, bNO1, &bErrorFlag ) != 0x1A
+                  || (nChar = BSBGetc( psInfo, bNO1, &bErrorFlag )) != 0x00)
               && !bErrorFlag)
         {
             if( nChar == 0x1A )
@@ -414,7 +411,7 @@ BSBInfo *BSBOpen( const char *pszFilename )
         if( bErrorFlag )
         {
             BSBClose( psInfo );
-            CPLError( CE_Failure, CPLE_FileIO, 
+            CPLError( CE_Failure, CPLE_FileIO,
                         "Truncated BSB file or I/O error." );
             return NULL;
         }
@@ -422,7 +419,7 @@ BSBInfo *BSBOpen( const char *pszFilename )
         if( nSkipped == 100 )
         {
             BSBClose( psInfo );
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Failed to find compressed data segment of BSB file." );
             return NULL;
         }
@@ -435,14 +432,14 @@ BSBInfo *BSBOpen( const char *pszFilename )
 
     /* The USGS files like 83116_1.KAP seem to use the ASCII number instead
        of the binary number for the colorsize value. */
-    
-    if( nSkipped > 0 
+
+    if( nSkipped > 0
         && psInfo->nColorSize >= 0x31 && psInfo->nColorSize <= 0x38 )
         psInfo->nColorSize -= 0x30;
 
     if( ! (psInfo->nColorSize > 0 && psInfo->nColorSize < 9) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "BSBOpen : Bad value for nColorSize (%d). Probably due to corrupted BSB file",
                   psInfo->nColorSize );
         BSBClose( psInfo );
@@ -452,13 +449,10 @@ BSBInfo *BSBOpen( const char *pszFilename )
 /* -------------------------------------------------------------------- */
 /*      Initialize memory for line offset list.                         */
 /* -------------------------------------------------------------------- */
-    psInfo->panLineOffset = (int *) 
-        VSIMalloc2(sizeof(int), psInfo->nYSize);
+    psInfo->panLineOffset = (int *)
+        VSI_MALLOC2_VERBOSE(sizeof(int), psInfo->nYSize);
     if (psInfo->panLineOffset == NULL)
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory, 
-                  "BSBOpen : Out of memory. Probably due to corrupted BSB file (nYSize = %d).",
-                  psInfo->nYSize );
         BSBClose( psInfo );
         return NULL;
     }
@@ -469,7 +463,7 @@ BSBInfo *BSBOpen( const char *pszFilename )
 /* -------------------------------------------------------------------- */
 /*       Read the line offset list                                      */
 /* -------------------------------------------------------------------- */
-    if ( ! CSLTestBoolean(CPLGetConfigOption("BSB_DISABLE_INDEX", "NO")) )
+    if ( !CPLTestBoolean(CPLGetConfigOption("BSB_DISABLE_INDEX", "NO")) )
     {
         /* build the list from file's index table */
         /* To overcome endian compatibility issues individual
@@ -494,7 +488,7 @@ BSBInfo *BSBOpen( const char *pszFilename )
         /* the index table can have one row less than nYSize */
         /* If we look into the file closely, there is no data for */
         /* that last row (the end of line psInfo->nYSize - 1 is the start */
-        /* of the index table), so we can decrement psInfo->nYSize */
+        /* of the index table), so we can decrement psInfo->nYSize. */
         if (nOffsetIndexTable + 4 * (psInfo->nYSize - 1) == nFileLen - 4)
         {
             CPLDebug("BSB", "Index size is one row shorter than declared image height. Correct this");
@@ -508,8 +502,8 @@ BSBInfo *BSBOpen( const char *pszFilename )
         }
         else if (VSIFSeekL( fp, nOffsetIndexTable, SEEK_SET ) != 0 )
         {
-            CPLError( CE_Failure, CPLE_FileIO, 
-                "Seek to offset 0x%08x for first line offset failed.", 
+            CPLError( CE_Failure, CPLE_FileIO,
+                "Seek to offset 0x%08x for first line offset failed.",
                 nOffsetIndexTable);
         }
         else
@@ -652,13 +646,13 @@ static int BSBSeekAndCheckScanlineNumber ( BSBInfo *psInfo, int nScanline,
     {
         if (bVerboseIfError)
         {
-            CPLError( CE_Failure, CPLE_FileIO, 
-                    "Seek to offset %d for scanline %d failed.", 
+            CPLError( CE_Failure, CPLE_FileIO,
+                    "Seek to offset %d for scanline %d failed.",
                     psInfo->panLineOffset[nScanline], nScanline );
         }
         else
         {
-            CPLDebug("BSB", "Seek to offset %d for scanline %d failed.", 
+            CPLDebug("BSB", "Seek to offset %d for scanline %d failed.",
                      psInfo->panLineOffset[nScanline], nScanline );
         }
         return FALSE;
@@ -686,26 +680,26 @@ static int BSBSeekAndCheckScanlineNumber ( BSBInfo *psInfo, int nScanline,
     {
         if (bVerboseIfError)
         {
-            CPLError( CE_Failure, CPLE_FileIO, 
+            CPLError( CE_Failure, CPLE_FileIO,
                     "Truncated BSB file or I/O error." );
         }
         return FALSE;
     }
-    if( nLineMarker != nScanline 
+    if( nLineMarker != nScanline
         && nLineMarker != nScanline + 1 )
     {
-        int bIgnoreLineNumbers = 
-            CSLTestBoolean(CPLGetConfigOption("BSB_IGNORE_LINENUMBERS", "NO"));
+        int bIgnoreLineNumbers =
+            CPLTestBoolean(CPLGetConfigOption("BSB_IGNORE_LINENUMBERS", "NO"));
 
         if (bVerboseIfError && !bIgnoreLineNumbers )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                     "Got scanline id %d when looking for %d @ offset %d.\nSet BSB_IGNORE_LINENUMBERS=TRUE configuration option to try file anyways.", 
+                     "Got scanline id %d when looking for %d @ offset %d.\nSet BSB_IGNORE_LINENUMBERS=TRUE configuration option to try file anyways.",
                      nLineMarker, nScanline+1, psInfo->panLineOffset[nScanline]);
         }
         else
         {
-            CPLDebug("BSB", "Got scanline id %d when looking for %d @ offset %d.", 
+            CPLDebug("BSB", "Got scanline id %d when looking for %d @ offset %d.",
                      nLineMarker, nScanline+1, psInfo->panLineOffset[nScanline]);
         }
 
@@ -721,7 +715,7 @@ static int BSBSeekAndCheckScanlineNumber ( BSBInfo *psInfo, int nScanline,
 /* @param nScanline zero based line number                              */
 /************************************************************************/
 
-int BSBReadScanline( BSBInfo *psInfo, int nScanline, 
+int BSBReadScanline( BSBInfo *psInfo, int nScanline,
                      unsigned char *pabyScanlineBuf )
 
 {
@@ -732,12 +726,12 @@ int BSBReadScanline( BSBInfo *psInfo, int nScanline,
 
 /* -------------------------------------------------------------------- */
 /*      Do we know where the requested line is?  If not, read all       */
-/*      the preceeding ones to "find" our line.                         */
+/*      the preceding ones to "find" our line.                          */
 /* -------------------------------------------------------------------- */
     if( nScanline < 0 || nScanline >= psInfo->nYSize )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
-                  "Scanline %d out of range.", 
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Scanline %d out of range.",
                    nScanline );
         return FALSE;
     }
@@ -771,7 +765,7 @@ int BSBReadScanline( BSBInfo *psInfo, int nScanline,
         ((((1 << psInfo->nColorSize)) - 1) << nValueShift);
     byCountMask = (unsigned char)
         (1 << (7 - psInfo->nColorSize)) - 1;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read and expand runs.                                           */
 /*      If for some reason the buffer is not filled,                    */
@@ -785,7 +779,7 @@ int BSBReadScanline( BSBInfo *psInfo, int nScanline,
                 !bErrorFlag)
         {
             int	    nPixValue;
-            int     nRunCount, i;
+            int     nRunCount;
 
             nPixValue = (byNext & byValueMask) >> nValueShift;
 
@@ -800,7 +794,7 @@ int BSBReadScanline( BSBInfo *psInfo, int nScanline,
             /* Prevent over-run of line data */
             if (nRunCount < 0 || nRunCount > INT_MAX - (iPixel + 1))
             {
-                CPLError( CE_Failure, CPLE_FileIO, 
+                CPLError( CE_Failure, CPLE_FileIO,
                           "Corrupted run count : %d", nRunCount );
                 return FALSE;
             }
@@ -822,7 +816,7 @@ int BSBReadScanline( BSBInfo *psInfo, int nScanline,
         }
         if ( bErrorFlag )
         {
-            CPLError( CE_Failure, CPLE_FileIO, 
+            CPLError( CE_Failure, CPLE_FileIO,
                     "Truncated BSB file or I/O error." );
             return FALSE;
         }
@@ -831,7 +825,7 @@ int BSBReadScanline( BSBInfo *psInfo, int nScanline,
 /*      For reasons that are unclear, some scanlines are exactly one    */
 /*      pixel short (such as in the BSB 3.0 354704.KAP product from     */
 /*      NDI/CHS) but are otherwise OK.  Just add a zero if this         */
-/*      appear to have occured.                                         */
+/*      appear to have occurred.                                         */
 /* -------------------------------------------------------------------- */
         if( iPixel == psInfo->nXSize - 1 )
             pabyScanlineBuf[iPixel++] = 0;
@@ -845,7 +839,7 @@ int BSBReadScanline( BSBInfo *psInfo, int nScanline,
                  nScanline != psInfo->nYSize-1 &&
                  psInfo->panLineOffset[nScanline+1] == -1)
         {
-            int nCurOffset = (int)(VSIFTellL( fp ) - psInfo->nBufferSize) + 
+            int nCurOffset = (int)(VSIFTellL( fp ) - psInfo->nBufferSize) +
                                 psInfo->nBufferOffset;
             psInfo->panLineOffset[nScanline+1] = nCurOffset;
             if (BSBSeekAndCheckScanlineNumber(psInfo, nScanline + 1, FALSE))
@@ -873,7 +867,7 @@ int BSBReadScanline( BSBInfo *psInfo, int nScanline,
 
 /* -------------------------------------------------------------------- */
 /*      If the line buffer is not filled after reading the line in the  */
-/*      file upto the next line offset, just fill it with zeros.        */
+/*      file up to the next line offset, just fill it with zeros.       */
 /*      (The last pixel value from nPixValue could be a better value?)  */
 /* -------------------------------------------------------------------- */
     while( iPixel < psInfo->nXSize )
@@ -929,8 +923,8 @@ BSBInfo *BSBCreate( const char *pszFilename,
     fp = VSIFOpenL( pszFilename, "wb" );
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Failed to open output file %s.", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to open output file %s.",
                   pszFilename );
         return NULL;
     }
@@ -938,18 +932,18 @@ BSBInfo *BSBCreate( const char *pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Write out BSB line.                                             */
 /* -------------------------------------------------------------------- */
-    VSIFPrintfL( fp, 
+    VSIFPrintfL( fp,
                 "!Copyright unknown\n" );
-    VSIFPrintfL( fp, 
+    VSIFPrintfL( fp,
                 "VER/%.1f\n", nVersion / 100.0 );
-    VSIFPrintfL( fp, 
+    VSIFPrintfL( fp,
                 "BSB/NA=UNKNOWN,NU=999502,RA=%d,%d,DU=254\n",
                 nXSize, nYSize );
-    VSIFPrintfL( fp, 
+    VSIFPrintfL( fp,
                 "KNP/SC=25000,GD=WGS84,PR=Mercator\n" );
-    VSIFPrintfL( fp, 
+    VSIFPrintfL( fp,
                 "    PP=31.500000,PI=0.033333,SP=,SK=0.000000,TA=90.000000\n");
-    VSIFPrintfL( fp, 
+    VSIFPrintfL( fp,
                 "     UN=Metres,SD=HHWLT,DX=2.500000,DY=2.500000\n");
 
 
@@ -976,13 +970,13 @@ int BSBWritePCT( BSBInfo *psInfo, int nPCTSize, unsigned char *pabyPCT )
 
 {
     int        i;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Verify the PCT not too large.                                   */
 /* -------------------------------------------------------------------- */
     if( nPCTSize > 128 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Pseudo-color table too large (%d entries), at most 128\n"
                   " entries allowed in BSB format.", nPCTSize );
         return FALSE;
@@ -991,8 +985,8 @@ int BSBWritePCT( BSBInfo *psInfo, int nPCTSize, unsigned char *pabyPCT )
 /* -------------------------------------------------------------------- */
 /*      Compute the number of bits required for the colors.             */
 /* -------------------------------------------------------------------- */
-    for( psInfo->nColorSize = 1; 
-         (1 << psInfo->nColorSize) < nPCTSize; 
+    for( psInfo->nColorSize = 1;
+         (1 << psInfo->nColorSize) < nPCTSize;
          psInfo->nColorSize++ ) {}
 
 /* -------------------------------------------------------------------- */
@@ -1001,8 +995,8 @@ int BSBWritePCT( BSBInfo *psInfo, int nPCTSize, unsigned char *pabyPCT )
 /* -------------------------------------------------------------------- */
     for( i = 1; i < nPCTSize; i++ )
     {
-        VSIFPrintfL( psInfo->fp, 
-                    "RGB/%d,%d,%d,%d\n", 
+        VSIFPrintfL( psInfo->fp,
+                    "RGB/%d,%d,%d,%d\n",
                     i, pabyPCT[i*3+0], pabyPCT[i*3+1], pabyPCT[i*3+2] );
     }
 
@@ -1020,13 +1014,13 @@ int BSBWriteScanline( BSBInfo *psInfo, unsigned char *pabyScanlineBuf )
 
     if( psInfo->nLastLineWritten == psInfo->nYSize - 1 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Attempt to write too many scanlines." );
         return FALSE;
     }
 
 /* -------------------------------------------------------------------- */
-/*      If this is the first scanline writen out the EOF marker, and    */
+/*      If this is the first scanline written out the EOF marker, and   */
 /*      the introductory info in the image segment.                     */
 /* -------------------------------------------------------------------- */
     if( psInfo->nLastLineWritten == -1 )
@@ -1057,7 +1051,7 @@ int BSBWriteScanline( BSBInfo *psInfo, unsigned char *pabyScanlineBuf )
 /* -------------------------------------------------------------------- */
     for( iX = 0; iX < psInfo->nXSize; iX++ )
     {
-        VSIFPutcL( pabyScanlineBuf[iX] << (7-psInfo->nColorSize), 
+        VSIFPutcL( pabyScanlineBuf[iX] << (7-psInfo->nColorSize),
                     psInfo->fp );
     }
 
diff --git a/frmts/bsb/bsb_read.h b/frmts/bsb/bsb_read.h
index 5d288c7..9d1134a 100644
--- a/frmts/bsb/bsb_read.h
+++ b/frmts/bsb/bsb_read.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: bsb_read.h 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: bsb_read.h 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  BSB Reader
  * Purpose:  non-GDAL BSB API Declarations
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _BSBREAD_H_INCLUDED
-#define _BSBREAD_H_INCLUDED
+#ifndef BSBREAD_H_INCLUDED
+#define BSBREAD_H_INCLUDED
 
 #include "cpl_port.h"
 #include "cpl_vsi.h"
@@ -66,18 +66,17 @@ typedef struct {
 } BSBInfo;
 
 BSBInfo CPL_DLL *BSBOpen( const char *pszFilename );
-int CPL_DLL BSBReadScanline( BSBInfo *psInfo, int nScanline, 
+int CPL_DLL BSBReadScanline( BSBInfo *psInfo, int nScanline,
                              unsigned char *pabyScanlineBuf );
 void CPL_DLL BSBClose( BSBInfo *psInfo );
 
-BSBInfo CPL_DLL *BSBCreate( const char *pszFilename, int nCreationFlags, 
+BSBInfo CPL_DLL *BSBCreate( const char *pszFilename, int nCreationFlags,
                             int nVersion, int nXSize, int nYSize );
-int CPL_DLL BSBWritePCT( BSBInfo *psInfo, 
+int CPL_DLL BSBWritePCT( BSBInfo *psInfo,
                          int nPCTSize, unsigned char *pabyPCT );
-int CPL_DLL BSBWriteScanline( BSBInfo *psInfo, 
+int CPL_DLL BSBWriteScanline( BSBInfo *psInfo,
                               unsigned char *pabyScanlineBuf );
-                            
-CPL_C_END
 
+CPL_C_END
 
-#endif /* ndef _BSBREAD_H_INCLUDED */
+#endif /* ndef BSBREAD_H_INCLUDED */
diff --git a/frmts/bsb/bsbdataset.cpp b/frmts/bsb/bsbdataset.cpp
index ddcd566..468e79e 100644
--- a/frmts/bsb/bsbdataset.cpp
+++ b/frmts/bsb/bsbdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: bsbdataset.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: bsbdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  BSB Reader
  * Purpose:  BSBDataset implementation for BSB format.
@@ -28,16 +28,13 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
 #include "bsb_read.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: bsbdataset.cpp 27942 2014-11-11 00:57:41Z rouault $");
-
-CPL_C_START
-void	GDALRegister_BSB(void);
-CPL_C_END
+CPL_CVSID("$Id: bsbdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 //Disabled as people may worry about the BSB patent
 //#define BSB_CREATE
@@ -68,7 +65,7 @@ class BSBDataset : public GDALPamDataset
   public:
                 BSBDataset();
 		~BSBDataset();
-    
+
     BSBInfo     *psInfo;
 
     static GDALDataset *Open( GDALOpenInfo * );
@@ -94,7 +91,7 @@ class BSBRasterBand : public GDALPamRasterBand
 
   public:
     		BSBRasterBand( BSBDataset * );
-    
+
     virtual CPLErr IReadBlock( int, int, void * );
     virtual GDALColorTable *GetColorTable();
     virtual GDALColorInterp GetColorInterpretation();
@@ -105,10 +102,10 @@ class BSBRasterBand : public GDALPamRasterBand
 /*                           BSBRasterBand()                            */
 /************************************************************************/
 
-BSBRasterBand::BSBRasterBand( BSBDataset *poDS )
+BSBRasterBand::BSBRasterBand( BSBDataset *poDSIn )
 
 {
-    this->poDS = poDS;
+    this->poDS = poDSIn;
     this->nBand = 1;
 
     eDataType = GDT_Byte;
@@ -118,13 +115,13 @@ BSBRasterBand::BSBRasterBand( BSBDataset *poDS )
 
     // Note that the first color table entry is dropped, everything is
     // shifted down.
-    for( int i = 0; i < poDS->psInfo->nPCTSize-1; i++ )
+    for( int i = 0; i < poDSIn->psInfo->nPCTSize-1; i++ )
     {
         GDALColorEntry  oColor;
 
-        oColor.c1 = poDS->psInfo->pabyPCT[i*3+0+3];
-        oColor.c2 = poDS->psInfo->pabyPCT[i*3+1+3];
-        oColor.c3 = poDS->psInfo->pabyPCT[i*3+2+3];
+        oColor.c1 = poDSIn->psInfo->pabyPCT[i*3+0+3];
+        oColor.c2 = poDSIn->psInfo->pabyPCT[i*3+1+3];
+        oColor.c3 = poDSIn->psInfo->pabyPCT[i*3+2+3];
         oColor.c4 = 255;
 
         oCT.SetColorEntry( i, &oColor );
@@ -155,8 +152,8 @@ CPLErr BSBRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 
         return CE_None;
     }
-    else
-        return CE_Failure;
+
+    return CE_Failure;
 }
 
 /************************************************************************/
@@ -189,22 +186,22 @@ GDALColorInterp BSBRasterBand::GetColorInterpretation()
 /*                           BSBDataset()                               */
 /************************************************************************/
 
-BSBDataset::BSBDataset()
-
+BSBDataset::BSBDataset() :
+    nGCPCount(0),
+    pasGCPList(NULL),
+    bGeoTransformSet(FALSE)
 {
     psInfo = NULL;
 
-    bGeoTransformSet = FALSE;
 
-    nGCPCount = 0;
-    pasGCPList = NULL;
-    osGCPProjection = "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",7030]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",6326]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",8901]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",9108]],AUTHORITY[\"EPSG\",4326]]";
+    osGCPProjection =
+        "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",7030]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",6326]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",8901]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",9108]],AUTHORITY[\"EPSG\",4326]]";
 
     adfGeoTransform[0] = 0.0;     /* X Origin (top left corner) */
     adfGeoTransform[1] = 1.0;     /* X Pixel size */
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[3] = 0.0;     /* Y Origin (top left corner) */
-    adfGeoTransform[4] = 0.0;     
+    adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;     /* Y Pixel Size */
 
 }
@@ -234,11 +231,11 @@ CPLErr BSBDataset::GetGeoTransform( double * padfTransform )
 
 {
     memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
-    
+
     if( bGeoTransformSet )
         return CE_None;
-    else
-        return CE_Failure;
+
+    return CE_Failure;
 }
 
 /************************************************************************/
@@ -250,23 +247,18 @@ const char *BSBDataset::GetProjectionRef()
 {
     if( bGeoTransformSet )
         return osGCPProjection;
-    else
-        return "";
+
+    return "";
 }
 
 /************************************************************************/
 /*                     GDALHeuristicDatelineWrap()                      */
 /************************************************************************/
 
-static void 
+static void
 GDALHeuristicDatelineWrap( int nPointCount, double *padfX )
 
 {
-    int i;
-    /* Following inits are useless but keep GCC happy */
-    double dfX_PM_Min = 0, dfX_PM_Max = 0, dfX_Dateline_Min = 0, dfX_Dateline_Max = 0;
-    int    bUsePMWrap;
-
     if( nPointCount < 2 )
         return;
 
@@ -275,15 +267,16 @@ GDALHeuristicDatelineWrap( int nPointCount, double *padfX )
 /*      prime meridian (-180 to 180) and centering on the dateline      */
 /*      (0 to 360).                                                     */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < nPointCount; i++ )
-    {
-        double dfX_PM, dfX_Dateline;
+    /* Following inits are useless but keep GCC happy */
+    double dfX_PM_Min = 0, dfX_PM_Max = 0, dfX_Dateline_Min = 0, dfX_Dateline_Max = 0;
 
-        dfX_PM = padfX[i];
+    for( int i = 0; i < nPointCount; i++ )
+    {
+        double dfX_PM = padfX[i];
         if( dfX_PM > 180 )
             dfX_PM -= 360.0;
 
-        dfX_Dateline = padfX[i];
+        double dfX_Dateline = padfX[i];
         if( dfX_Dateline < 0 )
             dfX_Dateline += 360.0;
 
@@ -310,7 +303,7 @@ GDALHeuristicDatelineWrap( int nPointCount, double *padfX )
         return;
 
 /* -------------------------------------------------------------------- */
-/*      Do nothing if both appproach have a wide range - best not to    */
+/*      Do nothing if both approach have a wide range - best not to    */
 /*      fiddle if we aren't sure we are improving things.               */
 /* -------------------------------------------------------------------- */
     if( (dfX_PM_Max - dfX_PM_Min) > 270.0
@@ -320,24 +313,26 @@ GDALHeuristicDatelineWrap( int nPointCount, double *padfX )
 /* -------------------------------------------------------------------- */
 /*      Pick which way to transform things.                             */
 /* -------------------------------------------------------------------- */
+    bool bUsePMWrap;
+
     if( (dfX_PM_Max - dfX_PM_Min) > 270.0
         && (dfX_Dateline_Max - dfX_Dateline_Min) < 270.0 )
-        bUsePMWrap = FALSE;
+        bUsePMWrap = false;
     else
-        bUsePMWrap = TRUE;
+        bUsePMWrap = true;
 
 
 /* -------------------------------------------------------------------- */
 /*      Apply rewrapping.                                               */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < nPointCount; i++ )
+    for( int i = 0; i < nPointCount; i++ )
     {
         if( bUsePMWrap )
         {
             if( padfX[i] > 180 )
                 padfX[i] -= 360.0;
         }
-        else 
+        else
         {
             if( padfX[i] < 0 )
                 padfX[i] += 360.0;
@@ -353,15 +348,14 @@ static void
 GDALHeuristicDatelineWrapGCPs( int nPointCount, GDAL_GCP *pasGCPList )
 {
     std::vector<double> oadfX;
-    int i;
 
     oadfX.resize( nPointCount );
-    for( i = 0; i < nPointCount; i++ )
+    for( int i = 0; i < nPointCount; i++ )
         oadfX[i] = pasGCPList[i].dfGCPX;
 
     GDALHeuristicDatelineWrap( nPointCount, &(oadfX[0]) );
 
-    for( i = 0; i < nPointCount; i++ )
+    for( int i = 0; i < nPointCount; i++ )
         pasGCPList[i].dfGCPX = oadfX[i];
 }
 
@@ -385,7 +379,7 @@ void BSBDataset::ScanForGCPs( bool isNos, const char *pszFilename )
     }
 
 /* -------------------------------------------------------------------- */
-/*      Apply heuristics to re-wrap GCPs to maintain continguity        */
+/*      Apply heuristics to re-wrap GCPs to maintain continuity        */
 /*      over the international dateline.                                */
 /* -------------------------------------------------------------------- */
     if( nGCPCount > 1 )
@@ -394,24 +388,22 @@ void BSBDataset::ScanForGCPs( bool isNos, const char *pszFilename )
 /* -------------------------------------------------------------------- */
 /*      Collect coordinate system related parameters from header.       */
 /* -------------------------------------------------------------------- */
-    int i;
     const char *pszKNP=NULL, *pszKNQ=NULL;
 
-    for( i = 0; psInfo->papszHeader[i] != NULL; i++ )
+    for( int i = 0; psInfo->papszHeader[i] != NULL; i++ )
     {
-        if( EQUALN(psInfo->papszHeader[i],"KNP/",4) )
+        if( STARTS_WITH_CI(psInfo->papszHeader[i], "KNP/") )
         {
             pszKNP = psInfo->papszHeader[i];
             SetMetadataItem( "BSB_KNP", pszKNP + 4 );
         }
-        if( EQUALN(psInfo->papszHeader[i],"KNQ/",4) )
+        if( STARTS_WITH_CI(psInfo->papszHeader[i], "KNQ/") )
         {
-            pszKNQ = psInfo->papszHeader[i]; 
+            pszKNQ = psInfo->papszHeader[i];
             SetMetadataItem( "BSB_KNQ", pszKNQ + 4 );
         }
     }
 
-    
 /* -------------------------------------------------------------------- */
 /*      Can we derive a reasonable coordinate system definition for     */
 /*      this file?  For now we keep it simple, just handling            */
@@ -425,20 +417,20 @@ void BSBDataset::ScanForGCPs( bool isNos, const char *pszFilename )
         const char *pszValue, *pszEnd = NULL;
         const char *pszGEOGCS = "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9108\"]],AUTHORITY[\"EPSG\",\"4326\"]]";
         CPLString osPP;
-        
+
         // Capture the PP string.
         pszValue = strstr(pszKNP,"PP=");
         if( pszValue )
             pszEnd = strstr(pszValue,",");
         if( pszValue && pszEnd )
             osPP.assign(pszValue+3,pszEnd-pszValue-3);
-        
+
         // Look at the datum
         if( pszGD == NULL )
         {
             /* no match. We'll default to EPSG:4326 */
         }
-        else if( EQUALN(pszGD,"GD=European 1950", 16) )
+        else if( STARTS_WITH_CI(pszGD, "GD=European 1950") )
         {
             pszGEOGCS = "GEOGCS[\"ED50\",DATUM[\"European_Datum_1950\",SPHEROID[\"International 1924\",6378388,297,AUTHORITY[\"EPSG\",\"7022\"]],TOWGS84[-87,-98,-121,0,0,0,0],AUTHORITY[\"EPSG\",\"6230\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4230\"]]";
         }
@@ -448,54 +440,54 @@ void BSBDataset::ScanForGCPs( bool isNos, const char *pszFilename )
         {
             /* no match */
         }
-        else if( EQUALN(pszPR,"PR=MERCATOR", 11) )
+        else if( STARTS_WITH_CI(pszPR, "PR=MERCATOR") )
         {
-            // We somewhat arbitrarily select our first GCPX as our 
-            // central meridian.  This is mostly helpful to ensure 
-            // that regions crossing the dateline will be contiguous 
+            // We somewhat arbitrarily select our first GCPX as our
+            // central meridian.  This is mostly helpful to ensure
+            // that regions crossing the dateline will be contiguous
             // in mercator.
             osUnderlyingSRS.Printf( "PROJCS[\"Global Mercator\",%s,PROJECTION[\"Mercator_2SP\"],PARAMETER[\"standard_parallel_1\",0],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",%d],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0],UNIT[\"Meter\",1]]",
                 pszGEOGCS, (int) pasGCPList[0].dfGCPX );
         }
 
-        else if( EQUALN(pszPR,"PR=TRANSVERSE MERCATOR", 22)
+        else if( STARTS_WITH_CI(pszPR, "PR=TRANSVERSE MERCATOR")
                  && osPP.size() > 0 )
         {
-            
-            osUnderlyingSRS.Printf( 
+
+            osUnderlyingSRS.Printf(
                 "PROJCS[\"unnamed\",%s,PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",%s],PARAMETER[\"scale_factor\",1],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0]]",
                 pszGEOGCS, osPP.c_str() );
         }
 
-        else if( EQUALN(pszPR,"PR=UNIVERSAL TRANSVERSE MERCATOR", 32)
+        else if( STARTS_WITH_CI(pszPR, "PR=UNIVERSAL TRANSVERSE MERCATOR")
                  && osPP.size() > 0 )
         {
-            // This is not *really* UTM unless the central meridian 
-            // matches a zone which it does not in some (most?) maps. 
-            osUnderlyingSRS.Printf( 
-                "PROJCS[\"unnamed\",%s,PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",%s],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",0]]", 
+            // This is not *really* UTM unless the central meridian
+            // matches a zone which it does not in some (most?) maps.
+            osUnderlyingSRS.Printf(
+                "PROJCS[\"unnamed\",%s,PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",%s],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",0]]",
                 pszGEOGCS, osPP.c_str() );
         }
 
-        else if( EQUALN(pszPR,"PR=POLYCONIC", 12) && osPP.size() > 0 )
+        else if( STARTS_WITH_CI(pszPR, "PR=POLYCONIC") && osPP.size() > 0 )
         {
-            osUnderlyingSRS.Printf( 
-                "PROJCS[\"unnamed\",%s,PROJECTION[\"Polyconic\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",%s],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0]]", 
+            osUnderlyingSRS.Printf(
+                "PROJCS[\"unnamed\",%s,PROJECTION[\"Polyconic\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",%s],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0]]",
                 pszGEOGCS, osPP.c_str() );
         }
-        
-        else if( EQUALN(pszPR,"PR=LAMBERT CONFORMAL CONIC", 26) 
+
+        else if( STARTS_WITH_CI(pszPR, "PR=LAMBERT CONFORMAL CONIC")
                  && osPP.size() > 0 && pszKNQ != NULL )
         {
             CPLString osP2, osP3;
-        
+
             // Capture the KNQ/P2 string.
             pszValue = strstr(pszKNQ,"P2=");
             if( pszValue )
                 pszEnd = strstr(pszValue,",");
             if( pszValue && pszEnd )
                 osP2.assign(pszValue+3,pszEnd-pszValue-3);
-            
+
             // Capture the KNQ/P3 string.
             pszValue = strstr(pszKNQ,"P3=");
             if( pszValue )
@@ -509,7 +501,7 @@ void BSBDataset::ScanForGCPs( bool isNos, const char *pszFilename )
             }
 
             if( osP2.size() > 0 && osP3.size() > 0 )
-                osUnderlyingSRS.Printf( 
+                osUnderlyingSRS.Printf(
                     "PROJCS[\"unnamed\",%s,PROJECTION[\"Lambert_Conformal_Conic_2SP\"],PARAMETER[\"standard_parallel_1\",%s],PARAMETER[\"standard_parallel_2\",%s],PARAMETER[\"latitude_of_origin\",0.0],PARAMETER[\"central_meridian\",%s],PARAMETER[\"false_easting\",0.0],PARAMETER[\"false_northing\",0.0]]",
                     pszGEOGCS, osP2.c_str(), osP3.c_str(), osPP.c_str() );
 
@@ -523,20 +515,20 @@ void BSBDataset::ScanForGCPs( bool isNos, const char *pszFilename )
     if( osUnderlyingSRS.length() > 0 )
     {
         OGRSpatialReference oGeog_SRS, oProjected_SRS;
-        OGRCoordinateTransformation *poCT;
-        
+
         oProjected_SRS.SetFromUserInput( osUnderlyingSRS );
         oGeog_SRS.CopyGeogCSFrom( &oProjected_SRS );
-        
-        poCT = OGRCreateCoordinateTransformation( &oGeog_SRS, 
-                                                  &oProjected_SRS );
+
+        OGRCoordinateTransformation *poCT
+            = OGRCreateCoordinateTransformation( &oGeog_SRS,
+                                                 &oProjected_SRS );
         if( poCT != NULL )
         {
-            for( i = 0; i < nGCPCount; i++ )
+            for( int i = 0; i < nGCPCount; i++ )
             {
-                poCT->Transform( 1, 
-                                 &(pasGCPList[i].dfGCPX), 
-                                 &(pasGCPList[i].dfGCPY), 
+                poCT->Transform( 1,
+                                 &(pasGCPList[i].dfGCPX),
+                                 &(pasGCPList[i].dfGCPY),
                                  &(pasGCPList[i].dfGCPZ) );
             }
 
@@ -551,7 +543,7 @@ void BSBDataset::ScanForGCPs( bool isNos, const char *pszFilename )
 /* -------------------------------------------------------------------- */
 /*      Attempt to prepare a geotransform from the GCPs.                */
 /* -------------------------------------------------------------------- */
-    if( GDALGCPsToGeoTransform( nGCPCount, pasGCPList, adfGeoTransform, 
+    if( GDALGCPsToGeoTransform( nGCPCount, pasGCPList, adfGeoTransform,
                                 FALSE ) )
     {
         bGeoTransformSet = TRUE;
@@ -571,14 +563,10 @@ void BSBDataset::ScanForGCPs( bool isNos, const char *pszFilename )
 
 void BSBDataset::ScanForGCPsNos( const char *pszFilename )
 {
-    char **Tokens;
-    const char *geofile;
-    const char *extension;
-    int fileGCPCount=0;
-
-    extension = CPLGetExtension(pszFilename);
+    const char *extension = CPLGetExtension(pszFilename);
 
     // pseudointelligently try and guess whether we want a .geo or a .GEO
+    const char *geofile;
     if (extension[1] == 'O')
     {
         geofile = CPLResetExtension( pszFilename, "GEO");
@@ -597,9 +585,10 @@ void BSBDataset::ScanForGCPsNos( const char *pszFilename )
     char *thisLine = (char *) CPLMalloc( 80 ); // FIXME
 
     // Count the GCPs (reference points) and seek the file pointer 'gfp' to the starting point
+    int fileGCPCount=0;
     while (fgets(thisLine, 80, gfp))
     {
-        if( EQUALN(thisLine, "Point", 5) )
+        if( STARTS_WITH_CI(thisLine, "Point") )
             fileGCPCount++;
     }
     VSIRewind( gfp );
@@ -609,10 +598,11 @@ void BSBDataset::ScanForGCPsNos( const char *pszFilename )
 
     while (fgets(thisLine, 80, gfp))
     {
-        if( EQUALN(thisLine, "Point", 5) )
+        if( STARTS_WITH_CI(thisLine, "Point") )
         {
             // got a point line, turn it into a gcp
-            Tokens = CSLTokenizeStringComplex(thisLine, "= ", FALSE, FALSE);
+            char **Tokens
+                = CSLTokenizeStringComplex(thisLine, "= ", FALSE, FALSE);
             if (CSLCount(Tokens) >= 5)
             {
                 GDALInitGCPs( 1, pasGCPList + nGCPCount );
@@ -623,7 +613,7 @@ void BSBDataset::ScanForGCPsNos( const char *pszFilename )
 
                 CPLFree( pasGCPList[nGCPCount].pszId );
                 char	szName[50];
-                sprintf( szName, "GCP_%d", nGCPCount+1 );
+                snprintf( szName, sizeof(szName), "GCP_%d", nGCPCount+1 );
                 pasGCPList[nGCPCount].pszId = CPLStrdup( szName );
 
                 nGCPCount++;
@@ -650,27 +640,24 @@ void BSBDataset::ScanForGCPsBSB()
 /*      REF/n,pixel,line,lat,long                                       */
 /* -------------------------------------------------------------------- */
     int fileGCPCount=0;
-    int i;
 
     // Count the GCPs (reference points) in psInfo->papszHeader
-    for( i = 0; psInfo->papszHeader[i] != NULL; i++ )
-        if( EQUALN(psInfo->papszHeader[i],"REF/",4) )
+    for( int i = 0; psInfo->papszHeader[i] != NULL; i++ )
+        if( STARTS_WITH_CI(psInfo->papszHeader[i], "REF/") )
             fileGCPCount++;
 
     // Memory has not been allocated to fileGCPCount yet
     pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),fileGCPCount+1);
 
-    for( i = 0; psInfo->papszHeader[i] != NULL; i++ )
+    for( int i = 0; psInfo->papszHeader[i] != NULL; i++ )
     {
-        char	**papszTokens;
-        char	szName[50];
 
-        if( !EQUALN(psInfo->papszHeader[i],"REF/",4) )
+        if( !STARTS_WITH_CI(psInfo->papszHeader[i], "REF/") )
             continue;
 
-        papszTokens = 
-            CSLTokenizeStringComplex( psInfo->papszHeader[i]+4, ",", 
-                                      FALSE, FALSE );
+        char	**papszTokens
+            = CSLTokenizeStringComplex( psInfo->papszHeader[i]+4, ",",
+                                        FALSE, FALSE );
 
         if( CSLCount(papszTokens) > 4 )
         {
@@ -688,7 +675,8 @@ void BSBDataset::ScanForGCPsBSB()
             }
             else
             {
-                sprintf( szName, "GCP_%d", nGCPCount+1 );
+                char szName[50];
+                snprintf( szName, sizeof(szName), "GCP_%d", nGCPCount+1 );
                 pasGCPList[nGCPCount].pszId = CPLStrdup( szName );
             }
 
@@ -708,13 +696,13 @@ int BSBDataset::IdentifyInternal( GDALOpenInfo * poOpenInfo, bool& isNosOut )
 /* -------------------------------------------------------------------- */
 /*      Check for BSB/ keyword.                                         */
 /* -------------------------------------------------------------------- */
-    int     i;
     isNosOut = false;
 
     if( poOpenInfo->nHeaderBytes < 1000 )
         return FALSE;
 
-    for( i = 0; i < poOpenInfo->nHeaderBytes - 4; i++ )
+    int i = 0;
+    for( ; i < poOpenInfo->nHeaderBytes - 4; i++ )
     {
         if( poOpenInfo->pabyHeader[i+0] == 'B'
             && poOpenInfo->pabyHeader[i+1] == 'S'
@@ -767,13 +755,13 @@ int BSBDataset::Identify( GDALOpenInfo * poOpenInfo )
 GDALDataset *BSBDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    bool        isNos = false;
+    bool isNos = false;
     if (!IdentifyInternal(poOpenInfo, isNos))
         return NULL;
 
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The BSB driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
@@ -782,9 +770,7 @@ GDALDataset *BSBDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    BSBDataset 	*poDS;
-
-    poDS = new BSBDataset();
+    BSBDataset *poDS = new BSBDataset();
 
 /* -------------------------------------------------------------------- */
 /*      Open the file.                                                  */
@@ -855,7 +841,7 @@ const GDAL_GCP *BSBDataset::GetGCPs()
 
 static int BSBIsSRSOK(const char *pszWKT)
 {
-    int bOK = FALSE;
+    bool bOK = false;
     OGRSpatialReference oSRS, oSRS_WGS84, oSRS_NAD83;
 
     if( pszWKT != NULL && pszWKT[0] != '\0' )
@@ -868,7 +854,7 @@ static int BSBIsSRSOK(const char *pszWKT)
         if ( (oSRS.IsSameGeogCS(&oSRS_WGS84) || oSRS.IsSameGeogCS(&oSRS_NAD83)) &&
               oSRS.IsGeographic() && oSRS.GetPrimeMeridian() == 0.0 )
         {
-            bOK = TRUE;
+            bOK = true;
         }
     }
 
@@ -886,44 +872,42 @@ static int BSBIsSRSOK(const char *pszWKT)
 /************************************************************************/
 
 static GDALDataset *
-BSBCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
-               int bStrict, char ** papszOptions, 
+BSBCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
+               int bStrict, char ** papszOptions,
                GDALProgressFunc pfnProgress, void * pProgressData )
 
 {
-    int  nBands = poSrcDS->GetRasterCount();
-    int  nXSize = poSrcDS->GetRasterXSize();
-    int  nYSize = poSrcDS->GetRasterYSize();
-
 /* -------------------------------------------------------------------- */
 /*      Some some rudimentary checks                                    */
 /* -------------------------------------------------------------------- */
+    const int nBands = poSrcDS->GetRasterCount();
     if( nBands != 1 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "BSB driver only supports one band images.\n" );
 
         return NULL;
     }
 
-    if( poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte 
+    if( poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte
         && bStrict )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "BSB driver doesn't support data type %s. "
-                  "Only eight bit bands supported.\n", 
-                  GDALGetDataTypeName( 
+                  "Only eight bit bands supported.\n",
+                  GDALGetDataTypeName(
                       poSrcDS->GetRasterBand(1)->GetRasterDataType()) );
 
         return NULL;
     }
 
+    const int nXSize = poSrcDS->GetRasterXSize();
+    const int nYSize = poSrcDS->GetRasterYSize();
+
 /* -------------------------------------------------------------------- */
 /*      Open the output file.                                           */
 /* -------------------------------------------------------------------- */
-    BSBInfo *psBSB;
-
-    psBSB = BSBCreate( pszFilename, 0, 200, nXSize, nYSize );
+    BSBInfo *psBSB = BSBCreate( pszFilename, 0, 200, nXSize, nYSize );
     if( psBSB == NULL )
         return NULL;
 
@@ -931,7 +915,6 @@ BSBCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      Prepare initial color table.colortable.                         */
 /* -------------------------------------------------------------------- */
     GDALRasterBand	*poBand = poSrcDS->GetRasterBand(1);
-    int			iColor;
     unsigned char       abyPCT[771];
     int                 nPCTSize;
     int                 anRemap[256];
@@ -943,7 +926,7 @@ BSBCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     if( poBand->GetColorTable() == NULL )
     {
         /* map greyscale down to 63 grey levels. */
-        for( iColor = 0; iColor < 256; iColor++ )
+        for( int iColor = 0; iColor < 256; iColor++ )
         {
             int nOutValue = (int) (iColor / 4.1) + 1;
 
@@ -961,7 +944,7 @@ BSBCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         if (nColorTableSize > 255)
             nColorTableSize = 255;
 
-        for( iColor = 0; iColor < nColorTableSize; iColor++ )
+        for( int iColor = 0; iColor < nColorTableSize; iColor++ )
         {
             GDALColorEntry	sEntry;
 
@@ -983,26 +966,20 @@ BSBCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Boil out all duplicate entries.                                 */
 /* -------------------------------------------------------------------- */
-    int  i;
-
-    for( i = 1; i < nPCTSize-1; i++ )
+    for( int i = 1; i < nPCTSize-1; i++ )
     {
-        int  j;
-
-        for( j = i+1; j < nPCTSize; j++ )
+        for( int j = i+1; j < nPCTSize; j++ )
         {
-            if( abyPCT[i*3+0] == abyPCT[j*3+0] 
-                && abyPCT[i*3+1] == abyPCT[j*3+1] 
+            if( abyPCT[i*3+0] == abyPCT[j*3+0]
+                && abyPCT[i*3+1] == abyPCT[j*3+1]
                 && abyPCT[i*3+2] == abyPCT[j*3+2] )
             {
-                int   k;
-
                 nPCTSize--;
                 abyPCT[j*3+0] = abyPCT[nPCTSize*3+0];
                 abyPCT[j*3+1] = abyPCT[nPCTSize*3+1];
                 abyPCT[j*3+2] = abyPCT[nPCTSize*3+2];
 
-                for( k = 0; k < 256; k++ )
+                for( int k = 0; k < 256; k++ )
                 {
                     // merge matching entries.
                     if( anRemap[k] == j )
@@ -1023,7 +1000,7 @@ BSBCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     {
         CPLError( CE_Warning, CPLE_AppDefined,
                   "Having to merge color table entries to reduce %d real\n"
-                  "color table entries down to 127 values.", 
+                  "color table entries down to 127 values.",
                   nPCTSize );
     }
 
@@ -1034,11 +1011,9 @@ BSBCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
         // Find the closest pair of color table entries.
 
-        for( i = 1; i < nPCTSize-1; i++ )
+        for( int i = 1; i < nPCTSize-1; i++ )
         {
-            int  j;
-            
-            for( j = i+1; j < nPCTSize; j++ )
+            for( int j = i+1; j < nPCTSize; j++ )
             {
                 int nRange = ABS(abyPCT[i*3+0] - abyPCT[j*3+0])
                     + ABS(abyPCT[i*3+1] - abyPCT[j*3+1])
@@ -1053,18 +1028,18 @@ BSBCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             }
         }
 
-        // Merge the second entry into the first. 
+        // Merge the second entry into the first.
         nPCTSize--;
         abyPCT[iBestMatch2*3+0] = abyPCT[nPCTSize*3+0];
         abyPCT[iBestMatch2*3+1] = abyPCT[nPCTSize*3+1];
         abyPCT[iBestMatch2*3+2] = abyPCT[nPCTSize*3+2];
 
-        for( i = 0; i < 256; i++ )
+        for( int i = 0; i < 256; i++ )
         {
             // merge matching entries.
             if( anRemap[i] == iBestMatch2 )
                 anRemap[i] = iBestMatch1;
-            
+
             // shift the last PCT entry into the new hole.
             if( anRemap[i] == nPCTSize )
                 anRemap[i] = iBestMatch2;
@@ -1091,10 +1066,10 @@ BSBCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         if ( BSBIsSRSOK(pszGCPProjection) )
         {
             const GDAL_GCP * pasGCPList = poSrcDS->GetGCPs();
-            for( i = 0; i < nGCPCount; i++ )
+            for( int i = 0; i < nGCPCount; i++ )
             {
-                VSIFPrintfL( psBSB->fp, 
-                            "REF/%d,%f,%f,%f,%f\n", 
+                VSIFPrintfL( psBSB->fp,
+                            "REF/%d,%f,%f,%f,%f\n",
                             i+1,
                             pasGCPList[i].dfGCPPixel, pasGCPList[i].dfGCPLine,
                             pasGCPList[i].dfGCPY, pasGCPList[i].dfGCPX);
@@ -1106,25 +1081,25 @@ BSBCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         const char* pszProjection = poSrcDS->GetProjectionRef();
         if ( BSBIsSRSOK(pszProjection) )
         {
-            VSIFPrintfL( psBSB->fp, 
+            VSIFPrintfL( psBSB->fp,
                         "REF/%d,%d,%d,%f,%f\n",
                         1,
                         0, 0,
                         adfGeoTransform[3] + 0 * adfGeoTransform[4] + 0 * adfGeoTransform[5],
                         adfGeoTransform[0] + 0 * adfGeoTransform[1] + 0 * adfGeoTransform[2]);
-            VSIFPrintfL( psBSB->fp, 
+            VSIFPrintfL( psBSB->fp,
                         "REF/%d,%d,%d,%f,%f\n",
                         2,
                         nXSize, 0,
                         adfGeoTransform[3] + nXSize * adfGeoTransform[4] + 0 * adfGeoTransform[5],
                         adfGeoTransform[0] + nXSize * adfGeoTransform[1] + 0 * adfGeoTransform[2]);
-            VSIFPrintfL( psBSB->fp, 
+            VSIFPrintfL( psBSB->fp,
                         "REF/%d,%d,%d,%f,%f\n",
                         3,
                         nXSize, nYSize,
                         adfGeoTransform[3] + nXSize * adfGeoTransform[4] + nYSize * adfGeoTransform[5],
                         adfGeoTransform[0] + nXSize * adfGeoTransform[1] + nYSize * adfGeoTransform[2]);
-            VSIFPrintfL( psBSB->fp, 
+            VSIFPrintfL( psBSB->fp,
                         "REF/%d,%d,%d,%f,%f\n",
                         4,
                         0, nYSize,
@@ -1136,19 +1111,18 @@ BSBCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Loop over image, copying image data.                            */
 /* -------------------------------------------------------------------- */
-    GByte 	*pabyScanline;
     CPLErr      eErr = CE_None;
 
-    pabyScanline = (GByte *) CPLMalloc( nXSize );
+    GByte *pabyScanline = (GByte *) CPLMalloc( nXSize );
 
     for( int iLine = 0; iLine < nYSize && eErr == CE_None; iLine++ )
     {
-        eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, 
+        eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1,
                                  pabyScanline, nXSize, 1, GDT_Byte,
                                  nBands, nBands * nXSize );
         if( eErr == CE_None )
         {
-            for( i = 0; i < nXSize; i++ )
+            for( int i = 0; i < nXSize; i++ )
                 pabyScanline[i] = (GByte) anRemap[pabyScanline[i]];
 
             if( !BSBWriteScanline( psBSB, pabyScanline ) )
@@ -1168,8 +1142,8 @@ BSBCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         VSIUnlink( pszFilename );
         return NULL;
     }
-    else
-        return (GDALDataset *) GDALOpen( pszFilename, GA_ReadOnly );
+
+    return (GDALDataset *) GDALOpen( pszFilename, GA_ReadOnly );
 }
 #endif
 
@@ -1180,28 +1154,25 @@ BSBCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 void GDALRegister_BSB()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "BSB" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "BSB" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "BSB" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Maptech BSB Nautical Charts" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#BSB" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "BSB" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Maptech BSB Nautical Charts" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#BSB" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 #ifdef BSB_CREATE
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte" );
 #endif
-        poDriver->pfnOpen = BSBDataset::Open;
-        poDriver->pfnIdentify = BSBDataset::Identify;
+    poDriver->pfnOpen = BSBDataset::Open;
+    poDriver->pfnIdentify = BSBDataset::Identify;
 #ifdef BSB_CREATE
-        poDriver->pfnCreateCopy = BSBCreateCopy;
+    poDriver->pfnCreateCopy = BSBCreateCopy;
 #endif
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/cals/GNUmakefile b/frmts/cals/GNUmakefile
new file mode 100644
index 0000000..cf18e10
--- /dev/null
+++ b/frmts/cals/GNUmakefile
@@ -0,0 +1,17 @@
+GDAL_ROOT	=	../..
+
+include $(GDAL_ROOT)/GDALmake.opt
+
+OBJ	=	calsdataset.o
+
+ifeq ($(TIFF_SETTING),internal)
+CPPFLAGS	:=	-I../gtiff/libtiff $(CPPFLAGS)
+endif
+
+default:	$(OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
+
diff --git a/frmts/cals/calsdataset.cpp b/frmts/cals/calsdataset.cpp
new file mode 100644
index 0000000..b4321a6
--- /dev/null
+++ b/frmts/cals/calsdataset.cpp
@@ -0,0 +1,616 @@
+/******************************************************************************
+ * $Id: calsdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
+ *
+ * Project:  CALS driver
+ * Purpose:  CALS driver
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
+#include "gdal_priv.h"
+
+#include "tiff.h"
+
+CPL_CVSID("$Id: calsdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+
+/************************************************************************/
+/* ==================================================================== */
+/*                            CALSDataset                               */
+/* ==================================================================== */
+/************************************************************************/
+
+class CALSDataset : public GDALPamDataset
+{
+    friend class CALSRasterBand;
+
+    CPLString    osTIFFHeaderFilename;
+    CPLString    osSparseFilename;
+    GDALDataset* poUnderlyingDS;
+
+    static void WriteLEInt16(VSILFILE* fp, GInt16 nVal);
+    static void WriteLEInt32(VSILFILE* fp, GInt32 nVal);
+    static void WriteTIFFTAG(VSILFILE* fp, GInt16 nTagName, GInt16 nTagType,
+                             GInt32 nTagValue);
+
+  public:
+                CALSDataset();
+                ~CALSDataset();
+
+    static int          Identify( GDALOpenInfo * poOpenInfo );
+    static GDALDataset *Open( GDALOpenInfo * );
+    static GDALDataset *CreateCopy( const char *pszFilename,
+                                           GDALDataset *poSrcDS,
+                                           int bStrict,
+                                           char **papszOptions,
+                                           GDALProgressFunc pfnProgress,
+                                           void *pProgressData );
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                          CALSRasterBand                              */
+/* ==================================================================== */
+/************************************************************************/
+
+class CALSRasterBand: public GDALPamRasterBand
+{
+    GDALRasterBand* poUnderlyingBand;
+
+  public:
+    CALSRasterBand(CALSDataset* poDSIn)
+    {
+        this->poDS = poDSIn;
+        poUnderlyingBand = poDSIn->poUnderlyingDS->GetRasterBand(1);
+        poUnderlyingBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
+        nBand = 1;
+        eDataType = GDT_Byte;
+    }
+
+    virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void * pData )
+    {
+        return poUnderlyingBand->ReadBlock(nBlockXOff, nBlockYOff, pData);
+    }
+
+    virtual CPLErr IRasterIO( GDALRWFlag eRWFlag,
+                                int nXOff, int nYOff, int nXSize, int nYSize,
+                                void * pData, int nBufXSize, int nBufYSize,
+                                GDALDataType eBufType,
+                                GSpacing nPixelSpace,
+                                GSpacing nLineSpace,
+                                GDALRasterIOExtraArg* psExtraArg )
+    {
+        return poUnderlyingBand->RasterIO(
+                    eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                    pData, nBufXSize, nBufYSize, eBufType,
+                    nPixelSpace, nLineSpace, psExtraArg ) ;
+    }
+
+    virtual GDALColorTable* GetColorTable()
+    {
+        return poUnderlyingBand->GetColorTable();
+    }
+
+    virtual GDALColorInterp GetColorInterpretation()
+    {
+        return GCI_PaletteIndex;
+    }
+
+    virtual char** GetMetadata(const char* pszDomain)
+    {
+        return poUnderlyingBand->GetMetadata(pszDomain);
+    }
+
+    virtual const char* GetMetadataItem(const char* pszKey, const char* pszDomain)
+    {
+        return poUnderlyingBand->GetMetadataItem(pszKey, pszDomain);
+    }
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                          CALSWrapperSrcBand                          */
+/* ==================================================================== */
+/************************************************************************/
+
+class CALSWrapperSrcBand: public GDALPamRasterBand
+{
+        GDALDataset* poSrcDS;
+        int bInvertValues;
+
+    public:
+        CALSWrapperSrcBand(GDALDataset* poSrcDSIn)
+        {
+            this->poSrcDS = poSrcDSIn;
+            SetMetadataItem("NBITS", "1", "IMAGE_STRUCTURE");
+            poSrcDS->GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
+            eDataType = GDT_Byte;
+            bInvertValues = TRUE;
+            GDALColorTable* poCT = poSrcDS->GetRasterBand(1)->GetColorTable();
+            if( poCT != NULL && poCT->GetColorEntryCount() >= 2 )
+            {
+                const GDALColorEntry* psEntry1 = poCT->GetColorEntry(0);
+                const GDALColorEntry* psEntry2 = poCT->GetColorEntry(1);
+                if( psEntry1->c1 == 255 && psEntry1->c2 == 255 && psEntry1->c3 == 255 &&
+                    psEntry2->c1 == 0 && psEntry2->c2 == 0 && psEntry2->c3 == 0 )
+                {
+                    bInvertValues = FALSE;
+                }
+            }
+        }
+
+        virtual CPLErr IReadBlock( CPL_UNUSED int nBlockXOff,
+                                   CPL_UNUSED int nBlockYOff,
+                                   CPL_UNUSED void * pData )
+        {
+            // Should not be called
+            return CE_Failure;
+        }
+
+        virtual CPLErr IRasterIO( GDALRWFlag eRWFlag,
+                                    int nXOff, int nYOff, int nXSize, int nYSize,
+                                    void * pData, int nBufXSize, int nBufYSize,
+                                    GDALDataType eBufType,
+                                    GSpacing nPixelSpace,
+                                    GSpacing nLineSpace,
+                                    GDALRasterIOExtraArg* psExtraArg )
+        {
+            CPLErr eErr = poSrcDS->GetRasterBand(1)->RasterIO(
+                        eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                        pData, nBufXSize, nBufYSize, eBufType,
+                        nPixelSpace, nLineSpace, psExtraArg ) ;
+            if( bInvertValues )
+            {
+                for(int j=0;j<nBufYSize;j++)
+                {
+                    for(int i=0;i<nBufXSize;i++)
+                        ((GByte*)pData)[j * nLineSpace + i * nPixelSpace] =
+                            1 - ((GByte*)pData)[j * nLineSpace + i * nPixelSpace];
+                }
+            }
+            return eErr;
+        }
+
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                          CALSWrapperSrcDataset                       */
+/* ==================================================================== */
+/************************************************************************/
+
+class CALSWrapperSrcDataset: public GDALPamDataset
+{
+    public:
+        CALSWrapperSrcDataset(GDALDataset* poSrcDS, const char* pszPadding)
+        {
+            nRasterXSize = poSrcDS->GetRasterXSize();
+            nRasterYSize = poSrcDS->GetRasterYSize();
+            SetBand(1, new CALSWrapperSrcBand(poSrcDS));
+            SetMetadataItem("TIFFTAG_DOCUMENTNAME", pszPadding);
+        }
+};
+
+
+/************************************************************************/
+/* ==================================================================== */
+/*                            CALSDataset                               */
+/* ==================================================================== */
+/************************************************************************/
+
+/************************************************************************/
+/*                           CALSDataset()                              */
+/************************************************************************/
+
+CALSDataset::CALSDataset()
+{
+    poUnderlyingDS = NULL;
+}
+
+/************************************************************************/
+/*                            ~CALSDataset()                            */
+/************************************************************************/
+
+CALSDataset::~CALSDataset()
+
+{
+    delete poUnderlyingDS;
+    if( osTIFFHeaderFilename.size() )
+        VSIUnlink(osTIFFHeaderFilename);
+    if( osSparseFilename.size() )
+        VSIUnlink(osSparseFilename);
+}
+
+/************************************************************************/
+/*                            Identify()                                */
+/************************************************************************/
+
+int CALSDataset::Identify( GDALOpenInfo * poOpenInfo )
+
+{
+    // If in the ingested bytes we found neither srcdocid: or rtype: 1, give up
+    if( poOpenInfo->nHeaderBytes == 0 ||
+        (strstr( (const char*) poOpenInfo->pabyHeader, "srcdocid:") == NULL &&
+         strstr( (const char*) poOpenInfo->pabyHeader, "rtype: 1") == NULL) )
+        return FALSE;
+
+    // If we found srcdocid: try to ingest up to 2048 bytes
+    if( strstr( (const char*) poOpenInfo->pabyHeader, "srcdocid:") &&
+        !poOpenInfo->TryToIngest(2048) )
+        return FALSE;
+
+    return strstr((const char*) poOpenInfo->pabyHeader, "rtype: 1") != NULL &&
+           strstr((const char*) poOpenInfo->pabyHeader, "rorient:") != NULL &&
+           strstr((const char*) poOpenInfo->pabyHeader, "rpelcnt:") != NULL;
+}
+
+/************************************************************************/
+/*                           WriteLEInt16()                             */
+/************************************************************************/
+
+void CALSDataset::WriteLEInt16(VSILFILE* fp, GInt16 nVal)
+{
+    nVal = CPL_LSBWORD16(nVal);
+    VSIFWriteL(&nVal, 1, 2, fp);
+}
+
+/************************************************************************/
+/*                            WriteLEInt32()                            */
+/************************************************************************/
+
+void CALSDataset::WriteLEInt32(VSILFILE* fp, GInt32 nVal)
+{
+    nVal = CPL_LSBWORD32(nVal);
+    VSIFWriteL(&nVal, 1, 4, fp);
+}
+
+/************************************************************************/
+/*                            WriteTIFFTAG()                            */
+/************************************************************************/
+
+void CALSDataset::WriteTIFFTAG(VSILFILE* fp, GInt16 nTagName, GInt16 nTagType,
+                               GInt32 nTagValue)
+{
+    WriteLEInt16(fp, nTagName);
+    WriteLEInt16(fp, nTagType);
+    WriteLEInt32(fp, 1);
+    WriteLEInt32(fp, nTagValue);
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *CALSDataset::Open( GDALOpenInfo * poOpenInfo )
+
+{
+    if (!Identify(poOpenInfo) || poOpenInfo->fpL == NULL )
+        return NULL;
+
+    const char* pszRPelCnt = strstr((const char*) poOpenInfo->pabyHeader, "rpelcnt:");
+    int nXSize, nYSize;
+    if( sscanf(pszRPelCnt+strlen("rpelcnt:"),"%d,%d",&nXSize,&nYSize) != 2 ||
+        nXSize <= 0 || nYSize <= 0 )
+        return NULL;
+
+    const char* pszOrient = strstr((const char*) poOpenInfo->pabyHeader, "rorient:");
+    int nAngle1, nAngle2;
+    if( sscanf(pszOrient+strlen("rorient:"),"%d,%d",&nAngle1,&nAngle2) != 2 )
+        return NULL;
+
+    const char* pszDensity = strstr((const char*) poOpenInfo->pabyHeader, "rdensty:");
+    int nDensity = 0;
+    if( pszDensity )
+        sscanf(pszDensity+strlen("rdensty:"), "%d", &nDensity);
+
+    VSIFSeekL(poOpenInfo->fpL, 0, SEEK_END);
+    int nFAX4BlobSize = (int)VSIFTellL(poOpenInfo->fpL) - 2048;
+    if( nFAX4BlobSize < 0 )
+        return NULL;
+
+    CALSDataset* poDS = new CALSDataset();
+    poDS->nRasterXSize = nXSize;
+    poDS->nRasterYSize = nYSize;
+
+    // Create a TIFF header for a single-strip CCITTFAX4 file
+    poDS->osTIFFHeaderFilename = CPLSPrintf("/vsimem/cals/header_%p.tiff", poDS);
+    VSILFILE* fp = VSIFOpenL(poDS->osTIFFHeaderFilename, "wb");
+    const int nTagCount = 10;
+    const int nHeaderSize = 4 + 4 + 2 + nTagCount * 12 + 4;
+    WriteLEInt16(fp, TIFF_LITTLEENDIAN); /* TIFF little-endian signature */
+    WriteLEInt16(fp, 42); // TIFF classic
+
+    WriteLEInt32(fp, 8);  /* Offset of IFD0 */
+
+    WriteLEInt16(fp, nTagCount); /* Number of entries */
+
+    WriteTIFFTAG(fp, TIFFTAG_IMAGEWIDTH, TIFF_LONG, nXSize);
+    WriteTIFFTAG(fp, TIFFTAG_IMAGELENGTH, TIFF_LONG, nYSize);
+    WriteTIFFTAG(fp, TIFFTAG_BITSPERSAMPLE, TIFF_SHORT, 1);
+    WriteTIFFTAG(fp, TIFFTAG_COMPRESSION, TIFF_SHORT, COMPRESSION_CCITTFAX4);
+    WriteTIFFTAG(fp, TIFFTAG_PHOTOMETRIC, TIFF_SHORT, PHOTOMETRIC_MINISWHITE);
+    WriteTIFFTAG(fp, TIFFTAG_STRIPOFFSETS, TIFF_LONG, nHeaderSize);
+    WriteTIFFTAG(fp, TIFFTAG_SAMPLESPERPIXEL, TIFF_SHORT, 1);
+    WriteTIFFTAG(fp, TIFFTAG_ROWSPERSTRIP, TIFF_LONG, nYSize);
+    WriteTIFFTAG(fp, TIFFTAG_STRIPBYTECOUNTS, TIFF_LONG, nFAX4BlobSize);
+    WriteTIFFTAG(fp, TIFFTAG_PLANARCONFIG, TIFF_SHORT, PLANARCONFIG_CONTIG);
+
+    WriteLEInt32(fp, 0);  /* Offset of next IFD */
+
+    VSIFCloseL(fp);
+
+    // Create a /vsisparse/ description file assembling the TIFF header
+    // with the FAX4 codestream that starts at offset 2048 of the CALS file
+    poDS->osSparseFilename = CPLSPrintf("/vsimem/cals/sparse_%p.xml", poDS);
+    fp = VSIFOpenL(poDS->osSparseFilename, "wb");
+    CPLAssert(fp);
+    VSIFPrintfL(fp, "<VSISparseFile>"
+                    "<Length>%d</Length>"
+                    "<SubfileRegion>"
+                      "<Filename relative='0'>%s</Filename>"
+                      "<DestinationOffset>0</DestinationOffset>"
+                      "<SourceOffset>0</SourceOffset>"
+                      "<RegionLength>%d</RegionLength>"
+                    "</SubfileRegion>"
+                    "<SubfileRegion>"
+                      "<Filename relative='0'>%s</Filename>"
+                      "<DestinationOffset>%d</DestinationOffset>"
+                      "<SourceOffset>%d</SourceOffset>"
+                      "<RegionLength>%d</RegionLength>"
+                    "</SubfileRegion>"
+                    "</VSISparseFile>",
+                nHeaderSize + nFAX4BlobSize,
+                poDS->osTIFFHeaderFilename.c_str(),
+                nHeaderSize,
+                poOpenInfo->pszFilename,
+                nHeaderSize,
+                2048,
+                nFAX4BlobSize);
+    VSIFCloseL(fp);
+
+    poDS->poUnderlyingDS = (GDALDataset*) GDALOpenEx(
+        CPLSPrintf("/vsisparse/%s", poDS->osSparseFilename.c_str()),
+        GDAL_OF_RASTER | GDAL_OF_INTERNAL, NULL, NULL, NULL);
+    if( poDS->poUnderlyingDS == NULL )
+    {
+        delete poDS;
+        return NULL;
+    }
+
+    if( nAngle1 != 0 || nAngle2 != 270 )
+    {
+        poDS->SetMetadataItem("PIXEL_PATH", CPLSPrintf("%d", nAngle1));
+        poDS->SetMetadataItem("LINE_PROGRESSION", CPLSPrintf("%d", nAngle2));
+    }
+
+    if( nDensity != 0 )
+    {
+        poDS->SetMetadataItem("TIFFTAG_XRESOLUTION", CPLSPrintf("%d", nDensity));
+        poDS->SetMetadataItem("TIFFTAG_YRESOLUTION", CPLSPrintf("%d", nDensity));
+        poDS->SetMetadataItem("TIFFTAG_RESOLUTIONUNIT", "2 (pixels/inch)");
+    }
+
+    poDS->SetBand(1, new CALSRasterBand(poDS));
+
+/* -------------------------------------------------------------------- */
+/*      Initialize any PAM information.                                 */
+/* -------------------------------------------------------------------- */
+    poDS->SetDescription( poOpenInfo->pszFilename );
+    poDS->TryLoadXML( poOpenInfo->GetSiblingFiles() );
+
+/* -------------------------------------------------------------------- */
+/*      Open overviews.                                                 */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename,
+                                 poOpenInfo->GetSiblingFiles() );
+
+    return( poDS );
+}
+
+/************************************************************************/
+/*                             CreateCopy()                             */
+/************************************************************************/
+
+GDALDataset *CALSDataset::CreateCopy( const char *pszFilename,
+                                      GDALDataset *poSrcDS,
+                                      int bStrict,
+                                      char ** /* papszOptionsUnused */,
+                                      GDALProgressFunc pfnProgress,
+                                      void *pProgressData )
+{
+    if( poSrcDS->GetRasterCount() == 0 ||
+        (bStrict && poSrcDS->GetRasterCount() != 1) )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "CALS driver only supports single band raster.");
+        return NULL;
+    }
+    if( poSrcDS->GetRasterBand(1)->GetMetadataItem("NBITS", "IMAGE_STRUCTURE") == NULL ||
+        !EQUAL(poSrcDS->GetRasterBand(1)->GetMetadataItem("NBITS", "IMAGE_STRUCTURE"), "1") )
+    {
+        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
+                  "CALS driver only supports 1-bit.");
+        if( bStrict )
+            return NULL;
+    }
+
+    if( poSrcDS->GetRasterXSize() > 999999 ||
+        poSrcDS->GetRasterYSize() > 999999 )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "CALS driver only supports datasets with dimension <= 999999.");
+        return NULL;
+    }
+
+    GDALDriver* poGTiffDrv = (GDALDriver*)GDALGetDriverByName("GTiff");
+    if( poGTiffDrv == NULL )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "CALS driver needs GTiff driver.");
+        return NULL;
+    }
+
+    /* Write a in-memory TIFF with just the TIFF header to figure out */
+    /* how large it will be */
+    CPLString osTmpFilename(CPLSPrintf("/vsimem/cals/tmp_%p", poSrcDS));
+    char** papszOptions = NULL;
+    papszOptions = CSLSetNameValue(papszOptions, "COMPRESS", "CCITTFAX4");
+    papszOptions = CSLSetNameValue(papszOptions, "NBITS", "1");
+    papszOptions = CSLSetNameValue(papszOptions, "BLOCKYSIZE",
+                                   CPLSPrintf("%d", poSrcDS->GetRasterYSize()));
+    papszOptions = CSLSetNameValue(papszOptions, "SPARSE_OK", "YES");
+    GDALDataset* poDS = poGTiffDrv->Create(osTmpFilename,
+                                           poSrcDS->GetRasterXSize(),
+                                           poSrcDS->GetRasterYSize(),
+                                           1, GDT_Byte,
+                                           papszOptions);
+    if( poDS == NULL )
+    {
+        // Should not happen normally (except if CCITTFAX4 not available)
+        CSLDestroy(papszOptions);
+        return NULL;
+    }
+    const char INITIAL_PADDING[] = "12345";
+    poDS->SetMetadataItem("TIFFTAG_DOCUMENTNAME", INITIAL_PADDING); // to adjust padding
+    GDALClose(poDS);
+    VSIStatBufL sStat;
+    if( VSIStatL(osTmpFilename, &sStat) != 0 )
+    {
+        // Shoudln't happen really... Just to make Coverity happy
+        CSLDestroy(papszOptions);
+        return NULL;
+    }
+    int nTIFFHeaderSize = static_cast<int>(sStat.st_size);
+    VSIUnlink(osTmpFilename);
+
+
+    /* Redo the same thing, but this time write it to the output file */
+    /* and use a variable TIFF tag (TIFFTAG_DOCUMENTNAME) to enlarge the */
+    /* header + the variable TIFF tag so that they are 2048 bytes large */
+    char szBuffer[2048+1];
+    szBuffer[2048] = 0;
+    memset(szBuffer, 'X', 2048 - nTIFFHeaderSize + strlen(INITIAL_PADDING));
+    szBuffer[2048 - nTIFFHeaderSize + strlen(INITIAL_PADDING)] = 0;
+    GDALDataset* poTmpDS = new CALSWrapperSrcDataset(poSrcDS, szBuffer);
+    poDS = poGTiffDrv->CreateCopy(pszFilename, poTmpDS, FALSE, papszOptions,
+                                  pfnProgress, pProgressData );
+    delete poTmpDS;
+    CSLDestroy(papszOptions);
+    if( poDS == NULL )
+        return NULL;
+    delete poDS;
+
+    // Now replace the TIFF header by the CALS header !
+    VSILFILE* fp = VSIFOpenL(pszFilename, "rb+");
+    if( fp == NULL )
+        return NULL; // Shoudln't happen normally
+    memset(szBuffer, ' ', 2048);
+    CPLString osField;
+    osField = "srcdocid: NONE";
+    memcpy(szBuffer, osField, osField.size());
+
+    osField = "dstdocid: NONE";
+    memcpy(szBuffer + 128, osField, osField.size());
+
+    osField = "txtfilid: NONE";
+    memcpy(szBuffer + 128*2, osField, osField.size());
+
+    osField = "figid: NONE";
+    memcpy(szBuffer + 128*3, osField, osField.size());
+
+    osField = "srcgph: NONE";
+    memcpy(szBuffer + 128*4, osField, osField.size());
+
+    osField = "doccls: NONE";
+    memcpy(szBuffer + 128*5, osField, osField.size());
+
+    osField = "rtype: 1";
+    memcpy(szBuffer + 128*6, osField, osField.size());
+
+    int nAngle1 = 0, nAngle2 = 270;
+    const char* pszPixelPath = poSrcDS->GetMetadataItem("PIXEL_PATH");
+    const char* pszLineProgression = poSrcDS->GetMetadataItem("LINE_PROGRESSION");
+    if( pszPixelPath && pszLineProgression )
+    {
+        nAngle1 = atoi(pszPixelPath);
+        nAngle2 = atoi(pszLineProgression);
+    }
+    osField = CPLSPrintf("rorient: %03d,%03d", nAngle1, nAngle2);
+    memcpy(szBuffer + 128*7, osField, osField.size());
+
+    osField = CPLSPrintf("rpelcnt: %06d,%06d",
+                         poSrcDS->GetRasterXSize(),
+                         poSrcDS->GetRasterYSize());
+    memcpy(szBuffer + 128*8, osField, osField.size());
+
+    int nDensity = 200;
+    const char* pszXRes = poSrcDS->GetMetadataItem("TIFFTAG_XRESOLUTION");
+    const char* pszYRes = poSrcDS->GetMetadataItem("TIFFTAG_YRESOLUTION");
+    const char* pszResUnit = poSrcDS->GetMetadataItem("TIFFTAG_RESOLUTIONUNIT");
+    if( pszXRes && pszYRes && pszResUnit && EQUAL(pszXRes, pszYRes) &&
+        atoi(pszResUnit) == 2 )
+    {
+        nDensity = atoi(pszXRes);
+        if( nDensity < 1 || nDensity > 9999 )
+            nDensity = 200;
+    }
+    osField = CPLSPrintf("rdensty: %04d", nDensity);
+    memcpy(szBuffer + 128*9, osField, osField.size());
+
+    osField = "notes: NONE";
+    memcpy(szBuffer + 128*10, osField, osField.size());
+    VSIFWriteL(szBuffer, 1, 2048, fp);
+    VSIFCloseL(fp);
+
+    GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly, NULL);
+    return Open(&oOpenInfo);
+}
+
+/************************************************************************/
+/*                        GDALRegister_CALS()                           */
+/************************************************************************/
+
+void GDALRegister_CALS()
+
+{
+    if( GDALGetDriverByName( "CALS" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "CALS" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "CALS (Type 1)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_cals.html" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, ".cal .ct1");
+
+    poDriver->pfnIdentify = CALSDataset::Identify;
+    poDriver->pfnOpen = CALSDataset::Open;
+    poDriver->pfnCreateCopy = CALSDataset::CreateCopy;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/frmts/cals/frmt_cals.html b/frmts/cals/frmt_cals.html
new file mode 100644
index 0000000..cc67971
--- /dev/null
+++ b/frmts/cals/frmt_cals.html
@@ -0,0 +1,70 @@
+<html>
+<head>
+<title>CALS --- CALS Type 1</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>CALS --- CALS Type 1</h1>
+
+(GDAL >= 2.1)<p>
+
+CALS Type 1 rasters are untiled back and white rasters made of a 2048-byte text header in the
+MIL-STD-1840 standard, followed by a single datastream compressed with CCITT/ITU-T
+Recommendation 6, aka Group 6, aka CCITT FAX 4. CALS Type 1 rasters are one of
+the 4 types of formats described by MIL-PRF-28002C (this standard is now deprecated).
+Other types are not handled by this driver.<p>
+
+This driver supports reading and creation of CALS Type 1 rasters. Update of
+existing rasters is not supported.<p>
+
+A CALS dataset is exposed by the driver as a single-band 1-bit raster with a
+2-entry color table. The first entry (0) is white (RGB=255,255,255) and the second
+entry (1) is black (RGB=0,0,0).<p>
+
+<h2>Metadata</h2>
+
+The following metadata items might be exposed by the driver (or read from the
+input dataset to generate a cor
+
+<ul>
+    <li> <b>PIXEL_PATH</b>: First value of the "rorient" header field, measured
+in degrees counterclockwise from the positive horizontal axis (east).  The pel path
+value represents the number of degrees the image would have to be rotated
+counterclockwise in order to display the image with proper viewing orientation.
+The permissible values for the pixel path direction shall be "0", "90", "180", or "270".
+0 is the typical value. If PIXEL_PATH=0 and LINE_PROGRESSION=270, neither are
+reported.<p>
+
+    <li> <b>LINE_PROGRESSION</b>: Second value of the "rorient" header field.
+The line progression direction is measured in degrees counterclockwise from the
+pel path direction.
+The permissible values for the line progression direction shall be "90" or "270".
+270 is the typical value. If PIXEL_PATH=0 and LINE_PROGRESSION=270, neither are
+reported.<p>
+
+    <li> <b>TIFFTAG_XRESOLUTION</b>: Scan X resolution in dot per inch, from the
+"rdensty" header field. TIFFTAG_XRESOLUTION and TIFFTAG_YRESOLUTION are always equal in CALS.<p>
+
+    <li> <b>TIFFTAG_YRESOLUTION</b>: Scan Y resolution in dot per inch, from the
+"rdensty" header field. TIFFTAG_XRESOLUTION and TIFFTAG_YRESOLUTION are always equal in CALS.<p>
+</ul>
+
+<h2>Creation issues</h2>
+
+Only single band 1-bit rasters are valid input to create a new CALS file. If
+the input raster has no color table, 0 is assumed to be black and 1 to be white.
+If the input raster has a (2 entries) color table, the value for the black and white color
+will be determined from the color table.<p>
+
+<h2>See Also:</h2>
+
+<ul>
+<li> <a href="http://everyspec.com/MIL-PRF/MIL-PRF-010000-29999/MIL-PRF-28002C_4830/">MIL-PRF-28002C</a><p>
+<li> <a href="http://everyspec.com/MIL-STD/MIL-STD-1800-1999/MIL-STD-1840C_4779/">MIL-STD-1840C</a><p>
+
+</ul>
+
+</body>
+</html>
+
diff --git a/frmts/cals/makefile.vc b/frmts/cals/makefile.vc
new file mode 100644
index 0000000..9993c0a
--- /dev/null
+++ b/frmts/cals/makefile.vc
@@ -0,0 +1,15 @@
+GDAL_ROOT = ..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+OBJ	= calsdataset.obj
+
+EXTRAFLAGS = -I..\gtiff\libtiff
+
+default:	$(OBJ)
+	xcopy /D  /Y *.obj ..\o
+	cd ..
+	
+clean:
+	-del *.obj
+	cd ..
diff --git a/frmts/ceos/ceosdataset.cpp b/frmts/ceos/ceosdataset.cpp
index b786c7a..5dffe76 100644
--- a/frmts/ceos/ceosdataset.cpp
+++ b/frmts/ceos/ceosdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ceosdataset.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ceosdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  CEOS Translator
  * Purpose:  GDALDataset driver for CEOS translator.
@@ -29,13 +29,10 @@
  ****************************************************************************/
 
 #include "ceosopen.h"
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: ceosdataset.cpp 27745 2014-09-27 16:38:57Z goatbar $");
-
-CPL_C_START
-void	GDALRegister_CEOS(void);
-CPL_C_END
+CPL_CVSID("$Id: ceosdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -48,7 +45,7 @@ class CEOSRasterBand;
 class CEOSDataset : public GDALPamDataset
 {
     friend class CEOSRasterBand;
-    
+
     CEOSImage	*psCEOS;
 
   public:
@@ -66,11 +63,11 @@ class CEOSDataset : public GDALPamDataset
 class CEOSRasterBand : public GDALPamRasterBand
 {
     friend class CEOSDataset;
-    
+
   public:
 
     		CEOSRasterBand( CEOSDataset *, int );
-    
+
     virtual CPLErr IReadBlock( int, int, void * );
 };
 
@@ -79,12 +76,12 @@ class CEOSRasterBand : public GDALPamRasterBand
 /*                           CEOSRasterBand()                            */
 /************************************************************************/
 
-CEOSRasterBand::CEOSRasterBand( CEOSDataset *poDS, int nBand )
+CEOSRasterBand::CEOSRasterBand( CEOSDataset *poDSIn, int nBandIn )
 
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
-    
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
+
     eDataType = GDT_Byte;
 
     nBlockXSize = poDS->GetRasterXSize();
@@ -141,9 +138,6 @@ CEOSDataset::~CEOSDataset()
 GDALDataset *CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    CEOSImage	*psCEOS;
-    int		i;
-    
 /* -------------------------------------------------------------------- */
 /*      Before trying CEOSOpen() we first verify that the first         */
 /*      record is in fact a CEOS file descriptor record.                */
@@ -160,14 +154,13 @@ GDALDataset *CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Try opening the dataset.                                        */
 /* -------------------------------------------------------------------- */
-    psCEOS = CEOSOpen( poOpenInfo->pszFilename, "rb" );
-    
+    CEOSImage *psCEOS = CEOSOpen( poOpenInfo->pszFilename, "rb" );
     if( psCEOS == NULL )
         return( NULL );
 
     if( psCEOS->nBitsPerPixel != 8 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The CEOS driver cannot handle nBitsPerPixel = %d",
                   psCEOS->nBitsPerPixel );
         CEOSClose(psCEOS);
@@ -187,7 +180,7 @@ GDALDataset *CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->eAccess == GA_Update )
     {
         CEOSClose(psCEOS);
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The CEOS driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
@@ -195,24 +188,22 @@ GDALDataset *CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    CEOSDataset 	*poDS;
-
-    poDS = new CEOSDataset();
+    CEOSDataset *poDS = new CEOSDataset();
 
     poDS->psCEOS = psCEOS;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Capture some information from the file that is of interest.     */
 /* -------------------------------------------------------------------- */
     poDS->nRasterXSize = psCEOS->nPixels;
     poDS->nRasterYSize = psCEOS->nLines;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
     poDS->nBands = psCEOS->nBands;;
 
-    for( i = 0; i < poDS->nBands; i++ )
+    for( int i = 0; i < poDS->nBands; i++ )
         poDS->SetBand( i+1, new CEOSRasterBand( poDS, i+1 ) );
 
 /* -------------------------------------------------------------------- */
@@ -236,22 +227,20 @@ GDALDataset *CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
 void GDALRegister_CEOS()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "CEOS" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "CEOS" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "CEOS" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "CEOS Image" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#CEOS" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-        
-        poDriver->pfnOpen = CEOSDataset::Open;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "CEOS" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "CEOS Image" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_various.html#CEOS" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = CEOSDataset::Open;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/ceos/ceosopen.c b/frmts/ceos/ceosopen.c
index 0c0ae13..e5d4135 100644
--- a/frmts/ceos/ceosopen.c
+++ b/frmts/ceos/ceosopen.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ceosopen.c 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ceosopen.c 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  CEOS Translator
  * Purpose:  Implementation of non-GDAL dependent CEOS support.
@@ -30,7 +30,9 @@
 
 #include "ceosopen.h"
 
-CPL_CVSID("$Id: ceosopen.c 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ceosopen.c 33720 2016-03-15 00:39:53Z goatbar $");
+
+CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused) {}
 
 /************************************************************************/
 /*                            CEOSScanInt()                             */
@@ -39,7 +41,7 @@ CPL_CVSID("$Id: ceosopen.c 27745 2014-09-27 16:38:57Z goatbar $");
 /*      as an integer.                                                  */
 /************************************************************************/
 
-static long CEOSScanInt( const char * pszString, int nMaxChars )
+static int CEOSScanInt( const char * pszString, int nMaxChars )
 
 {
     char	szWorking[33];
@@ -69,6 +71,7 @@ CEOSRecord * CEOSReadRecord( CEOSImage *psImage )
 {
     GByte	abyHeader[12];
     CEOSRecord  *psRecord;
+    GUInt32 nRecordNumUInt32, nLengthUInt32;
 
 /* -------------------------------------------------------------------- */
 /*      Read the standard CEOS header.                                  */
@@ -93,54 +96,53 @@ CEOSRecord * CEOSReadRecord( CEOSImage *psImage )
         CPL_SWAP32PTR( abyHeader + 8 );
     }
 
-    psRecord->nRecordNum = abyHeader[0] * 256 * 256 * 256
-                         + abyHeader[1] * 256 * 256
-                         + abyHeader[2] * 256
+    nRecordNumUInt32 = (abyHeader[0] << 24)
+                         + (abyHeader[1] << 16)
+                         + (abyHeader[2] << 8)
                          + abyHeader[3];
 
-    psRecord->nRecordType = abyHeader[4] * 256 * 256 * 256
-                          + abyHeader[5] * 256 * 256
-                          + abyHeader[6] * 256
-                          + abyHeader[7];
+    psRecord->nRecordType = (abyHeader[4] << 24)
+                         + (abyHeader[5] << 16)
+                         + (abyHeader[6] << 8)
+                         + abyHeader[7];
 
-    psRecord->nLength = abyHeader[8]  * 256 * 256 * 256
-                      + abyHeader[9]  * 256 * 256
-                      + abyHeader[10] * 256
-                      + abyHeader[11];
+    nLengthUInt32 = (abyHeader[8] << 24)
+                         + (abyHeader[9] << 16)
+                         + (abyHeader[10] << 8)
+                         + abyHeader[11];
 
 /* -------------------------------------------------------------------- */
 /*      Does it look reasonable?  We assume there can't be too many     */
 /*      records and that the length must be between 12 and 200000.      */
 /* -------------------------------------------------------------------- */
-    if( psRecord->nRecordNum < 0 || psRecord->nRecordNum > 200000
-        || psRecord->nLength < 12 || psRecord->nLength > 200000 )
+    if( nRecordNumUInt32 > 200000
+        || nLengthUInt32 < 12 || nLengthUInt32 > 200000 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "CEOS record leader appears to be corrupt.\n"
-                  "Record Number = %d, Record Length = %d\n",
-                  psRecord->nRecordNum, psRecord->nLength );
+                  "Record Number = %u, Record Length = %u\n",
+                  nRecordNumUInt32, nLengthUInt32 );
         CPLFree( psRecord );
         return NULL;
     }
 
+    psRecord->nRecordNum = (int)nRecordNumUInt32;
+    psRecord->nLength = (int)nLengthUInt32;
+
 /* -------------------------------------------------------------------- */
 /*      Read the remainder of the record into a buffer.  Ensure that    */
 /*      the first 12 bytes gets moved into this buffer as well.         */
 /* -------------------------------------------------------------------- */
-    psRecord->pachData = (char *) VSIMalloc(psRecord->nLength );
+    psRecord->pachData = (char *) VSI_MALLOC_VERBOSE(psRecord->nLength );
     if( psRecord->pachData == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory,
-                  "Out of memory allocated %d bytes for CEOS record data.\n"
-                  "Are you sure you aren't leaking CEOSRecords?\n",
-                  psRecord->nLength );
         CPLFree( psRecord );
         return NULL;
     }
 
     memcpy( psRecord->pachData, abyHeader, 12 );
 
-    if( (int)VSIFReadL( psRecord->pachData + 12, 1, psRecord->nLength-12, 
+    if( (int)VSIFReadL( psRecord->pachData + 12, 1, psRecord->nLength-12,
                        psImage->fpImage )
         != psRecord->nLength - 12 )
     {
@@ -173,7 +175,7 @@ void CEOSDestroyRecord( CEOSRecord * psRecord )
 /**
  * Open a CEOS transfer.
  *
- * @param pszFilename The name of the CEOS imagery file (ie. imag_01.dat).
+ * @param pszFilename The name of the CEOS imagery file (i.e. imag_01.dat).
  * @param pszAccess An fopen() style access string.  Should be either "rb" for
  * read-only access, or "r+b" for read, and update access.
  *
@@ -216,12 +218,16 @@ CEOSImage * CEOSOpen( const char * pszFilename, const char * pszAccess )
 /*      Preread info on the first record, to establish if it is         */
 /*      little endian.                                                  */
 /* -------------------------------------------------------------------- */
-    VSIFReadL( abyHeader, 16, 1, fp );
-    VSIFSeekL( fp, 0, SEEK_SET );
-    
+    if( VSIFReadL( abyHeader, 16, 1, fp ) != 1 ||
+        VSIFSeekL( fp, 0, SEEK_SET ) < 0 )
+    {
+        CEOSClose( psImage );
+        return NULL;
+    }
+
     if( abyHeader[0] != 0 || abyHeader[1] != 0 )
         psImage->bLittleEndian = TRUE;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Try to read the header record.                                  */
 /* -------------------------------------------------------------------- */
@@ -254,10 +260,10 @@ CEOSImage * CEOSOpen( const char * pszFilename, const char * pszAccess )
         CPLError( CE_Warning, CPLE_AppDefined,
                   "Got a %d file sequence number, instead of the expected\n"
                   "2 indicating imagery on file %s.\n"
-                  "Continuing to access anyways.\n", 
+                  "Continuing to access anyways.\n",
                   nSeqNum, pszFilename );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Extract various information.                                    */
 /* -------------------------------------------------------------------- */
@@ -301,7 +307,7 @@ CEOSImage * CEOSOpen( const char * pszFilename, const char * pszAccess )
             psRecord->nLength + i * psImage->nImageRecLength
 	            + 12 + psImage->nPrefixBytes;
     }
-    
+
     CEOSDestroyRecord( psRecord );
 
     return psImage;
@@ -315,7 +321,7 @@ CEOSImage * CEOSOpen( const char * pszFilename, const char * pszAccess )
  * Read a scanline of image.
  *
  * @param psCEOS The CEOS dataset handle returned by CEOSOpen().
- * @param nBand The band number (ie. 1, 2, 3).
+ * @param nBand The band number (i.e. 1, 2, 3).
  * @param nScanline The scanline requested, one based.
  * @param pData The data buffer to read into.  Must be at least nPixels *
  * nBitesPerPixel bits long.
@@ -328,7 +334,7 @@ CPLErr CEOSReadScanline( CEOSImage * psCEOS, int nBand, int nScanline,
 
 {
     int		nOffset, nBytes;
-    
+
     /*
      * As a short cut, I currently just seek to the data, and read it
      * raw, rather than trying to read ceos records properly.
@@ -374,6 +380,6 @@ void CEOSClose( CEOSImage * psCEOS )
 
 {
     CPLFree( psCEOS->panDataStart );
-    VSIFCloseL( psCEOS->fpImage );
+    CPL_IGNORE_RET_VAL_INT(VSIFCloseL( psCEOS->fpImage ));
     CPLFree( psCEOS );
 }
diff --git a/frmts/ceos/ceosopen.h b/frmts/ceos/ceosopen.h
index b7034d5..0aacce3 100644
--- a/frmts/ceos/ceosopen.h
+++ b/frmts/ceos/ceosopen.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ceosopen.h 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ceosopen.h 31777 2015-11-26 14:14:41Z rouault $
  *
  * Project:  CEOS Translator
  * Purpose:  Public (C callable) interface for CEOS and related formats such
@@ -28,8 +28,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _CEOSOPEN_H_INCLUDED
-#define _CEOSOPEN_H_INCLUDED
+#ifndef CEOSOPEN_H_INCLUDED
+#define CEOSOPEN_H_INCLUDED
 
 /* -------------------------------------------------------------------- */
 /*      Include standard portability stuff.                             */
@@ -102,7 +102,7 @@ void CPL_ODLL	     CEOSDestroyRecord( CEOSRecord * );
 
 CPL_C_END
 
-#endif /* ndef _CEOSOPEN_H_INCLUDED */
+#endif /* ndef CEOSOPEN_H_INCLUDED */
 
 
 
diff --git a/frmts/ceos/ceostest.c b/frmts/ceos/ceostest.c
index 6c8c992..fb0d644 100644
--- a/frmts/ceos/ceostest.c
+++ b/frmts/ceos/ceostest.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ceostest.c 20504 2010-09-02 02:40:49Z warmerdam $
+ * $Id: ceostest.c 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  CEOS Translator
  * Purpose:  Test mainline.
@@ -53,11 +53,11 @@ int main( int nArgc, char ** papszArgv )
         exit( 1 );
     }
 
-    while( !VSIFEofL(fp) 
+    while( !VSIFEofL(fp)
            && (psRecord = CEOSReadRecord( fp )) != NULL )
     {
-        printf( "%9d:%4d:%8x:%d\n", 
-                nPosition, psRecord->nRecordNum, 
+        printf( "%9d:%4d:%8x:%d\n",
+                nPosition, psRecord->nRecordNum,
                 psRecord->nRecordType, psRecord->nLength );
         CEOSDestroyRecord( psRecord );
 
diff --git a/frmts/ceos2/ceos.c b/frmts/ceos2/ceos.c
index f187e4c..a6179c8 100644
--- a/frmts/ceos2/ceos.c
+++ b/frmts/ceos2/ceos.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ceos.c 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ceos.c 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  ASI CEOS Translator
  * Purpose:  Core CEOS functions.
@@ -29,7 +29,7 @@
 
 #include "ceos.h"
 
-CPL_CVSID("$Id: ceos.c 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: ceos.c 33720 2016-03-15 00:39:53Z goatbar $");
 
 /* Function implementations of functions described in ceos.h */
 
@@ -55,9 +55,9 @@ void InitEmptyCeosRecord(CeosRecord_t *record, int32 sequence, CeosTypeCode_t ty
 	record->Length = length;
 
 	/* Now we fill in the buffer portion as well */
-	NativeToCeos( record->Buffer+__SEQUENCE_OFF, &(record->Sequence), sizeof(record->Sequence), sizeof( record->Sequence ) );
-	memcpy(record->Buffer+__TYPE_OFF, &( record->TypeCode.Int32Code ), sizeof( record->TypeCode.Int32Code ) );
-	NativeToCeos( record->Buffer+__LENGTH_OFF, &length,  sizeof( length ), sizeof( length ) );
+	NativeToCeos( record->Buffer+SEQUENCE_OFF, &(record->Sequence), sizeof(record->Sequence), sizeof( record->Sequence ) );
+	memcpy(record->Buffer+TYPE_OFF, &( record->TypeCode.Int32Code ), sizeof( record->TypeCode.Int32Code ) );
+	NativeToCeos( record->Buffer+LENGTH_OFF, &length,  sizeof( length ), sizeof( length ) );
     }
 }
 
@@ -65,7 +65,7 @@ void InitCeosRecord(CeosRecord_t *record, uchar *buffer)
 {
     if(record && buffer)
     {
-	InitCeosRecordWithHeader(record, buffer, buffer+__CEOS_HEADER_LENGTH);
+	InitCeosRecordWithHeader(record, buffer, buffer+CEOS_HEADER_LENGTH);
     }
 }
 
@@ -76,30 +76,32 @@ void InitCeosRecordWithHeader(CeosRecord_t *record, uchar *header, uchar *buffer
         if( record->Length != 0 )
             record->Length = DetermineCeosRecordBodyLength( header );
 
-	if((record->Buffer = HMalloc(record->Length)) == NULL)
+	if(record->Length < CEOS_HEADER_LENGTH ||
+            (record->Buffer = HMalloc(record->Length)) == NULL)
 	{
 	    record->Length = 0;
 	    return;
 	}
 
 	/* First copy the header then the buffer */
-	memcpy(record->Buffer,header,__CEOS_HEADER_LENGTH);
+	memcpy(record->Buffer,header,CEOS_HEADER_LENGTH);
 	/* Now we copy the rest */
-	memcpy(record->Buffer+__CEOS_HEADER_LENGTH,buffer,record->Length-__CEOS_HEADER_LENGTH);
+        if( record->Length > CEOS_HEADER_LENGTH )
+            memcpy(record->Buffer+CEOS_HEADER_LENGTH,buffer,record->Length-CEOS_HEADER_LENGTH);
 
 	/* Now we fill in the rest of the structure! */
-	memcpy(&(record->TypeCode.Int32Code),header+__TYPE_OFF,sizeof(record->TypeCode.Int32Code));
-	CeosToNative(&(record->Sequence),header+__SEQUENCE_OFF,sizeof(record->Sequence), sizeof( record->Sequence ) );
+	memcpy(&(record->TypeCode.Int32Code),header+TYPE_OFF,sizeof(record->TypeCode.Int32Code));
+	CeosToNative(&(record->Sequence),header+SEQUENCE_OFF,sizeof(record->Sequence), sizeof( record->Sequence ) );
     }
 }
 
 int DetermineCeosRecordBodyLength(const uchar *header)
 {
     int i;
-    
+
     if(header)
     {
-	CeosToNative(&i,header+__LENGTH_OFF,sizeof( i ), sizeof( i ) );
+	CeosToNative(&i,header+LENGTH_OFF,sizeof( i ), sizeof( i ) );
 
 	return i;
     }
@@ -214,12 +216,11 @@ void GetCeosField(CeosRecord_t *record, int32 start_byte,
 	break;
 
     default:
-	/* Unknown format */
-	return;
+	/* Unknown format.  Do nothing. */
+        break;
     }
 
     HFree(mod_buf);
-
 }
 
 void SetCeosField(CeosRecord_t *record, int32 start_byte, char *format, void *value)
@@ -258,26 +259,26 @@ void SetCeosField(CeosRecord_t *record, int32 start_byte, char *format, void *va
 	    memcpy(value,temp_buf,field_size);
 	}
 	break;
-	
+
     case 'i':
     case 'I':
 	/* Integer data type */
-	sprintf( printf_format,"%%%s%c",format+1, 'd');
-	sprintf( temp_buf, printf_format, *(int *) value);
+	snprintf( printf_format, sizeof(printf_format), "%%%s%c",format+1, 'd');
+	snprintf( temp_buf, field_size+1, printf_format, *(int *) value);
 	break;
 
     case 'f':
     case 'F':
 	/* Double precision floating point data type */
-	sprintf(printf_format, "%%%s%c", format+1, 'g');
-	sprintf(temp_buf, printf_format, *(double *)value);
+	snprintf( printf_format, sizeof(printf_format), "%%%s%c", format+1, 'g');
+	snprintf( temp_buf, field_size+1, printf_format, *(double *)value);
 	break;
 
     case 'e':
     case 'E':
 	/* Double precision floating point data type (forced exponent) */
-	sprintf(printf_format,"%%%s%c", format+1, 'e');
-	sprintf(temp_buf, printf_format, *(double *)value);
+	snprintf( printf_format, sizeof(printf_format), "%%%s%c", format+1, 'e');
+	snprintf( temp_buf, field_size+1, printf_format, *(double *)value);
 	break;
 
     case 'a':
@@ -288,7 +289,8 @@ void SetCeosField(CeosRecord_t *record, int32 start_byte, char *format, void *va
 
     default:
 	/* Unknown format */
-	return;
+	HFree(temp_buf);
+        return;
     }
 
     memcpy(record->Buffer + start_byte -1, temp_buf, field_size);
@@ -301,7 +303,7 @@ void SetIntCeosField(CeosRecord_t *record, int32 start_byte, int32 length, int32
     int integer_value = value;
     char total_len[12];   /* 12 because 2^32 -> 4294967296 + I + null */
 
-    sprintf(total_len,"I%d",length);
+    snprintf(total_len,sizeof(total_len),"I%d",length);
     SetCeosField(record,start_byte,total_len,&integer_value);
 }
 
@@ -324,6 +326,8 @@ CeosRecord_t *FindCeosRecord(Link_t *record_list, CeosTypeCode_t typecode, int32
     return NULL;
 }
 
+CPL_INLINE static void CPL_IGNORE_RET_VAL_SIZET(CPL_UNUSED size_t unused) {}
+
 void SerializeCeosRecordsToFile(Link_t *record_list, VSILFILE *fp)
 {
     Link_t *list;
@@ -337,8 +341,8 @@ void SerializeCeosRecordsToFile(Link_t *record_list, VSILFILE *fp)
 	memcpy(&crec,list->object,sizeof(CeosRecord_t));
 	Buffer = crec.Buffer;
 	crec.Buffer = NULL;
-	VSIFWriteL(&crec,sizeof(CeosRecord_t),1,fp);
-	VSIFWriteL(Buffer,crec.Length,1,fp);
+	CPL_IGNORE_RET_VAL_SIZET(VSIFWriteL(&crec,sizeof(CeosRecord_t),1,fp));
+	CPL_IGNORE_RET_VAL_SIZET(VSIFWriteL(Buffer,crec.Length,1,fp));
     }
 }
 
@@ -350,9 +354,9 @@ void SerializeCeosRecordsFromFile(Link_t *record_list, VSILFILE *fp)
     while(!VSIFEofL(fp))
     {
 	crec = HMalloc(sizeof(CeosRecord_t));
-	VSIFReadL(crec,sizeof(CeosRecord_t),1,fp);
+	CPL_IGNORE_RET_VAL_SIZET(VSIFReadL(crec,sizeof(CeosRecord_t),1,fp));
 	crec->Buffer = HMalloc(crec->Length * sizeof(char) );
-	VSIFReadL(crec->Buffer,sizeof(char),crec->Length,fp);
+	CPL_IGNORE_RET_VAL_SIZET(VSIFReadL(crec->Buffer,sizeof(char),crec->Length,fp));
 	Link = ceos2CreateLink(crec);
 	AddLink(record_list,Link);
     }
@@ -362,18 +366,20 @@ void CeosUpdateHeaderFromBuffer(CeosRecord_t *record)
 {
     if(record && record->Buffer)
     {
-	CeosToNative( &( record->Length ), record->Buffer+__LENGTH_OFF, sizeof(record->Length ), sizeof( record->Length ) );
-	memcpy(&(record->TypeCode.Int32Code),record->Buffer+__TYPE_OFF,sizeof(record->TypeCode.Int32Code));
-	CeosToNative(&(record->Sequence),record->Buffer+__SEQUENCE_OFF,sizeof(record->Sequence ), sizeof( record->Sequence ) );
+	CeosToNative( &( record->Length ), record->Buffer+LENGTH_OFF, sizeof(record->Length ), sizeof( record->Length ) );
+	memcpy(&(record->TypeCode.Int32Code),record->Buffer+TYPE_OFF,sizeof(record->TypeCode.Int32Code));
+	CeosToNative(&(record->Sequence),record->Buffer+SEQUENCE_OFF,sizeof(record->Sequence ), sizeof( record->Sequence ) );
     }
-    record->Subsequence = 0;
+    if(record)
+        record->Subsequence = 0;
 }
 
 #ifdef CPL_LSB
 
-void swapbyte(void *dst,void *src,int toswap)
+static
+void swapbyte(void *dst,void *src,size_t toswap)
 {
-    int i,e;
+    size_t i,e;
     unsigned char *in = (unsigned char *) src;
     unsigned char *out = (unsigned char *) dst;
 
@@ -385,23 +391,23 @@ void swapbyte(void *dst,void *src,int toswap)
 
 void NativeToCeos( void *dst, const void *src, const size_t len, const size_t swapunit)
 {
-    int i;
-    int remainder;
-    int units;
+    size_t i;
+    size_t l_remainder;
+    size_t units;
 
 
-    remainder = len % swapunit;
+    l_remainder = len % swapunit;
 
-    units = len - remainder;
+    units = len - l_remainder;
 
     for(i = 0;i < units; i += swapunit )
     {
 	swapbyte( ( unsigned char *) dst + i, ( unsigned char * ) src + i, swapunit);
     }
 
-    if(remainder)
+    if(l_remainder)
     {
-	memcpy( ( unsigned char * ) dst + i, ( unsigned char * ) src + i, remainder );
+	memcpy( ( unsigned char * ) dst + i, ( unsigned char * ) src + i, l_remainder );
     }
 }
 
diff --git a/frmts/ceos2/ceos.h b/frmts/ceos2/ceos.h
index 4cfa55c..66f3ec8 100644
--- a/frmts/ceos2/ceos.h
+++ b/frmts/ceos2/ceos.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ceos.h 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ceos.h 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  ASI CEOS Translator
  * Purpose:  CEOS library prototypes
@@ -28,8 +28,8 @@
  ****************************************************************************/
 
 
-#ifndef __CEOS_H
-#define __CEOS_H
+#ifndef CEOS_H
+#define CEOS_H
 
 #include "cpl_conv.h"
 
@@ -39,7 +39,7 @@ CPL_C_START
 #define TBool int
 #define uchar unsigned char
 
-typedef struct Link_t_struct 
+typedef struct Link_t_struct
 {
   struct Link_t_struct	*next;
   void		*object;
@@ -56,91 +56,91 @@ Link_t *AddLink( Link_t *psList, Link_t *psLink );
 
 /* Basic CEOS header defs */
 
-#define __SEQUENCE_OFF 0
-#define __TYPE_OFF 4
-#define __LENGTH_OFF 8
-#define __CEOS_HEADER_LENGTH 12
+#define SEQUENCE_OFF 0
+#define TYPE_OFF 4
+#define LENGTH_OFF 8
+#define CEOS_HEADER_LENGTH 12
 
 /* Defines for CEOS banding type */
 
-#define __CEOS_IL_PIXEL 1
-#define __CEOS_IL_LINE  2
-#define __CEOS_IL_BAND  3
+#define CEOS_IL_PIXEL 1
+#define CEOS_IL_LINE  2
+#define CEOS_IL_BAND  3
 
 /* Defines for CEOS data types */
 
-#define __CEOS_TYP_CHAR 1
-#define __CEOS_TYP_UCHAR 2
-#define __CEOS_TYP_SHORT 3
-#define __CEOS_TYP_USHORT 4
-#define __CEOS_TYP_LONG 5
-#define __CEOS_TYP_ULONG 6
-#define __CEOS_TYP_FLOAT 7
-#define __CEOS_TYP_DOUBLE 8
-#define __CEOS_TYP_COMPLEX_CHAR 9
-#define __CEOS_TYP_COMPLEX_UCHAR 10
-#define __CEOS_TYP_COMPLEX_SHORT 11
-#define __CEOS_TYP_COMPLEX_USHORT 12
-#define __CEOS_TYP_COMPLEX_LONG 13
-#define __CEOS_TYP_COMPLEX_ULONG 14
-#define __CEOS_TYP_COMPLEX_FLOAT 15
-#define __CEOS_TYP_CCP_COMPLEX_FLOAT 16 /* COMPRESSED CROSS PRODUCT */
-#define __CEOS_TYP_PALSAR_COMPLEX_SHORT 17 /* PALSAR - treat as COMPLEX SHORT*/
+#define CEOS_TYP_CHAR 1
+#define CEOS_TYP_UCHAR 2
+#define CEOS_TYP_SHORT 3
+#define CEOS_TYP_USHORT 4
+#define CEOS_TYP_LONG 5
+#define CEOS_TYP_ULONG 6
+#define CEOS_TYP_FLOAT 7
+#define CEOS_TYP_DOUBLE 8
+#define CEOS_TYP_COMPLEX_CHAR 9
+#define CEOS_TYP_COMPLEX_UCHAR 10
+#define CEOS_TYP_COMPLEX_SHORT 11
+#define CEOS_TYP_COMPLEX_USHORT 12
+#define CEOS_TYP_COMPLEX_LONG 13
+#define CEOS_TYP_COMPLEX_ULONG 14
+#define CEOS_TYP_COMPLEX_FLOAT 15
+#define CEOS_TYP_CCP_COMPLEX_FLOAT 16 /* COMPRESSED CROSS PRODUCT */
+#define CEOS_TYP_PALSAR_COMPLEX_SHORT 17 /* PALSAR - treat as COMPLEX SHORT*/
 
 /* Defines for CEOS file names */
 
-#define __CEOS_VOLUME_DIR_FILE 0
-#define __CEOS_LEADER_FILE    1
-#define __CEOS_IMAGRY_OPT_FILE 2
-#define __CEOS_TRAILER_FILE    3
-#define __CEOS_NULL_VOL_FILE   4
-#define __CEOS_ANY_FILE -1
+#define CEOS_VOLUME_DIR_FILE 0
+#define CEOS_LEADER_FILE    1
+#define CEOS_IMAGRY_OPT_FILE 2
+#define CEOS_TRAILER_FILE    3
+#define CEOS_NULL_VOL_FILE   4
+#define CEOS_ANY_FILE -1
 
 /* Defines for Recipe values */
 
-#define __CEOS_REC_NUMCHANS 1
-#define __CEOS_REC_INTERLEAVE 2
-#define __CEOS_REC_DATATYPE 3
-#define __CEOS_REC_BPR 4
-#define __CEOS_REC_LINES 5
-#define __CEOS_REC_TBP 6
-#define __CEOS_REC_BBP 7
-#define __CEOS_REC_PPL 8
-#define __CEOS_REC_LBP 9
-#define __CEOS_REC_RBP 10
-#define __CEOS_REC_BPP 11
-#define __CEOS_REC_RPL 12
-#define __CEOS_REC_PPR 13
-#define __CEOS_REC_IDS 14
-#define __CEOS_REC_FDL 15
-#define __CEOS_REC_PIXORD 16
-#define __CEOS_REC_LINORD 17
-#define __CEOS_REC_PRODTYPE 18
-#define __CEOS_REC_RECORDSIZE 19
-#define __CEOS_REC_SUFFIX_SIZE 20
-#define __CEOS_REC_PDBPR 21
+#define CEOS_REC_NUMCHANS 1
+#define CEOS_REC_INTERLEAVE 2
+#define CEOS_REC_DATATYPE 3
+#define CEOS_REC_BPR 4
+#define CEOS_REC_LINES 5
+#define CEOS_REC_TBP 6
+#define CEOS_REC_BBP 7
+#define CEOS_REC_PPL 8
+#define CEOS_REC_LBP 9
+#define CEOS_REC_RBP 10
+#define CEOS_REC_BPP 11
+#define CEOS_REC_RPL 12
+#define CEOS_REC_PPR 13
+#define CEOS_REC_IDS 14
+#define CEOS_REC_FDL 15
+#define CEOS_REC_PIXORD 16
+#define CEOS_REC_LINORD 17
+#define CEOS_REC_PRODTYPE 18
+#define CEOS_REC_RECORDSIZE 19
+#define CEOS_REC_SUFFIX_SIZE 20
+#define CEOS_REC_PDBPR 21
 
 /* Defines for Recipe Types */
 
-#define __CEOS_REC_TYP_A  1
-#define __CEOS_REC_TYP_B  2
-#define __CEOS_REC_TYP_I  3
+#define CEOS_REC_TYP_A  1
+#define CEOS_REC_TYP_B  2
+#define CEOS_REC_TYP_I  3
 
 /* Defines for SAR Embedded info */
 
-#define __CEOS_SAR_ACQ_YEAR 1
-#define __CEOS_SAR_ACQ_DAY  2
-#define __CEOS_SAR_ACQ_MSEC 4
-#define __CEOS_SAR_TRANS_POL 8
-#define __CEOS_SAR_PULSE_REP 16
-#define __CEOS_SAR_SLANT_FIRST 32
-#define __CEOS_SAR_SLANT_MID 64
-#define __CEOS_SAR_SLANT_LAST 128
+#define CEOS_SAR_ACQ_YEAR 1
+#define CEOS_SAR_ACQ_DAY  2
+#define CEOS_SAR_ACQ_MSEC 4
+#define CEOS_SAR_TRANS_POL 8
+#define CEOS_SAR_PULSE_REP 16
+#define CEOS_SAR_SLANT_FIRST 32
+#define CEOS_SAR_SLANT_MID 64
+#define CEOS_SAR_SLANT_LAST 128
 
 /* Maximum size of LUT for Calibration records */
-#define __CEOS_RADAR_MAX_LUT 512
-#define __CEOS_RADAR_FLIP_DATE 19980101
-#define __CEOS_RADAR_FACILITY "CDPF-RSAT"
+#define CEOS_RADAR_MAX_LUT 512
+#define CEOS_RADAR_FLIP_DATE 19980101
+#define CEOS_RADAR_FACILITY "CDPF-RSAT"
 
 
 typedef union
@@ -207,7 +207,7 @@ typedef struct
     Link_t *       RecordList;
 } CeosSARVolume_t;
 
-typedef struct 
+typedef struct
 {
     int            ImageDescValue;
     int            Override;
@@ -254,7 +254,6 @@ typedef struct
     int NumberOfSamples;
     int Increment;
     TBool PossiblyFlipped;
-    
 } CeosRadarCalibration_t;
 
 
@@ -303,13 +302,13 @@ void GetCeosSAREmbeddedInfo(CeosSARVolume_t *volume, CeosRecord_t *processed_dat
 void DeleteCeosSARVolume(CeosSARVolume_t *volume);
 
 void RegisterRecipes(void);
-void FreeRecipes();
+void FreeRecipes(void);
 
-void AddRecipe( int ( *function )( CeosSARVolume_t *volume, void *token ),
-		void *token, const char *name );
+void AddRecipe( int ( *function )( CeosSARVolume_t *volume, const void *token ),
+		const void *token, const char *name );
 
-int CeosDefaultRecipe( CeosSARVolume_t *volume, void *token );
-int ScanSARRecipeFCN( CeosSARVolume_t *volume, void *token );
+int CeosDefaultRecipe( CeosSARVolume_t *volume, const void *token );
+int ScanSARRecipeFCN( CeosSARVolume_t *volume, const void *token );
 
 /* ceoscalib.c function declarations */
 
diff --git a/frmts/ceos2/ceosrecipe.c b/frmts/ceos2/ceosrecipe.c
index 33e0610..2d49eaa 100644
--- a/frmts/ceos2/ceosrecipe.c
+++ b/frmts/ceos2/ceosrecipe.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ceosrecipe.c 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ceosrecipe.c 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  ASI CEOS Translator
  * Purpose:  CEOS field layout recipes.
@@ -29,38 +29,38 @@
 
 #include "ceos.h"
 
-CPL_CVSID("$Id: ceosrecipe.c 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ceosrecipe.c 33720 2016-03-15 00:39:53Z goatbar $");
 
 /* Array of Datatypes and their names/values */
 
-typedef struct { 
-    char *String;
+typedef struct {
+    const char *String;
     int Type;
 } CeosStringType_t;
 
-typedef struct { 
-    int (*function)(CeosSARVolume_t *volume, void *token);
-    void *token;
+typedef struct {
+    int (*function)(CeosSARVolume_t *volume, const void *token);
+    const void *token;
     const char *name;
 } RecipeFunctionData_t;
 
 
-CeosStringType_t CeosDataType[] = { { "IU1", __CEOS_TYP_UCHAR },
-				    { "IU2", __CEOS_TYP_USHORT },
-				    { "UI1", __CEOS_TYP_UCHAR },
-				    { "UI2", __CEOS_TYP_USHORT },
-				    { "CI*2", __CEOS_TYP_COMPLEX_CHAR },
-				    { "CI*4", __CEOS_TYP_COMPLEX_SHORT },
-				    { "CIS4", __CEOS_TYP_COMPLEX_SHORT },
-				    { "CI*8", __CEOS_TYP_COMPLEX_LONG },
-				    { "C*8", __CEOS_TYP_COMPLEX_FLOAT },
-				    { "R*4", __CEOS_TYP_FLOAT },
+static const CeosStringType_t CeosDataType[] = { { "IU1", CEOS_TYP_UCHAR },
+				    { "IU2", CEOS_TYP_USHORT },
+				    { "UI1", CEOS_TYP_UCHAR },
+				    { "UI2", CEOS_TYP_USHORT },
+				    { "CI*2", CEOS_TYP_COMPLEX_CHAR },
+				    { "CI*4", CEOS_TYP_COMPLEX_SHORT },
+				    { "CIS4", CEOS_TYP_COMPLEX_SHORT },
+				    { "CI*8", CEOS_TYP_COMPLEX_LONG },
+				    { "C*8", CEOS_TYP_COMPLEX_FLOAT },
+				    { "R*4", CEOS_TYP_FLOAT },
 				    { NULL, 0 } };
 
-CeosStringType_t CeosInterleaveType[] = { { "BSQ", __CEOS_IL_BAND },
-					  { " BSQ", __CEOS_IL_BAND },
-					  { "BIL", __CEOS_IL_LINE },
-					  { " BIL", __CEOS_IL_LINE },
+static const CeosStringType_t CeosInterleaveType[] = { { "BSQ", CEOS_IL_BAND },
+					  { " BSQ", CEOS_IL_BAND },
+					  { "BIL", CEOS_IL_LINE },
+					  { " BIL", CEOS_IL_LINE },
 					  { NULL, 0 } };
 
 #define IMAGE_OPT { 63, 192, 18, 18 }
@@ -71,172 +71,172 @@ CeosStringType_t CeosInterleaveType[] = { { "BSQ", __CEOS_IL_BAND },
 #define DATA_SET_SUMMARY { 18, 10, 18, 20 }
 
 /* NOTE: This seems to be the generic recipe used for most things */
-CeosRecipeType_t RadarSatRecipe[] =
+static const CeosRecipeType_t RadarSatRecipe[] =
 {
-    { __CEOS_REC_NUMCHANS, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      233, 4, __CEOS_REC_TYP_I }, /* Number of channels */
-    { __CEOS_REC_INTERLEAVE, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      269, 4, __CEOS_REC_TYP_A }, /* Interleaving type */
-    { __CEOS_REC_DATATYPE, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      429, 4, __CEOS_REC_TYP_A }, /* Data type */
-    { __CEOS_REC_BPR, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      0, 0, __CEOS_REC_TYP_A }, /* For Defeault CEOS, this is done using other vals */
-    { __CEOS_REC_LINES, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      237, 8, __CEOS_REC_TYP_I }, /* How many lines */
-    { __CEOS_REC_TBP, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      261, 4, __CEOS_REC_TYP_I },
-    { __CEOS_REC_BBP, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      265, 4, __CEOS_REC_TYP_I }, /* Bottom border pixels */
-    { __CEOS_REC_PPL, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      249, 8, __CEOS_REC_TYP_I }, /* Pixels per line */
-    { __CEOS_REC_LBP, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      245, 4, __CEOS_REC_TYP_I }, /* Left Border Pixels */
-    { __CEOS_REC_RBP, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      257, 4, __CEOS_REC_TYP_I }, /* Isn't available for RadarSAT */
-    { __CEOS_REC_BPP, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      225, 4, __CEOS_REC_TYP_I }, /* Bytes Per Pixel */
-    { __CEOS_REC_RPL, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      273, 2, __CEOS_REC_TYP_I }, /* Records per line */
-    { __CEOS_REC_PPR, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      0, 0, __CEOS_REC_TYP_I }, /* Pixels Per Record -- need to fill record type */
-    { __CEOS_REC_PDBPR, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      281, 8, __CEOS_REC_TYP_I }, /* pixel data bytes per record */
-    { __CEOS_REC_IDS, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      277, 4, __CEOS_REC_TYP_I }, /* Prefix data per record */
-    { __CEOS_REC_FDL, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      9, 4, __CEOS_REC_TYP_B }, /* Length of Imagry Options Header */
-    { __CEOS_REC_PIXORD, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      0, 0, __CEOS_REC_TYP_I }, /* Must be calculated */
-    { __CEOS_REC_LINORD, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      0, 0, __CEOS_REC_TYP_I }, /* Must be calculated */
-    { __CEOS_REC_PRODTYPE, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      0, 0, __CEOS_REC_TYP_I },
-
-    { __CEOS_REC_RECORDSIZE, 1, __CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC,
-      9, 4, __CEOS_REC_TYP_B }, /* The processed image record size */
+    { CEOS_REC_NUMCHANS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      233, 4, CEOS_REC_TYP_I }, /* Number of channels */
+    { CEOS_REC_INTERLEAVE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      269, 4, CEOS_REC_TYP_A }, /* Interleaving type */
+    { CEOS_REC_DATATYPE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      429, 4, CEOS_REC_TYP_A }, /* Data type */
+    { CEOS_REC_BPR, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      0, 0, CEOS_REC_TYP_A }, /* For Defeault CEOS, this is done using other vals */
+    { CEOS_REC_LINES, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      237, 8, CEOS_REC_TYP_I }, /* How many lines */
+    { CEOS_REC_TBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      261, 4, CEOS_REC_TYP_I },
+    { CEOS_REC_BBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      265, 4, CEOS_REC_TYP_I }, /* Bottom border pixels */
+    { CEOS_REC_PPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      249, 8, CEOS_REC_TYP_I }, /* Pixels per line */
+    { CEOS_REC_LBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      245, 4, CEOS_REC_TYP_I }, /* Left Border Pixels */
+    { CEOS_REC_RBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      257, 4, CEOS_REC_TYP_I }, /* Isn't available for RadarSAT */
+    { CEOS_REC_BPP, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      225, 4, CEOS_REC_TYP_I }, /* Bytes Per Pixel */
+    { CEOS_REC_RPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      273, 2, CEOS_REC_TYP_I }, /* Records per line */
+    { CEOS_REC_PPR, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      0, 0, CEOS_REC_TYP_I }, /* Pixels Per Record -- need to fill record type */
+    { CEOS_REC_PDBPR, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      281, 8, CEOS_REC_TYP_I }, /* pixel data bytes per record */
+    { CEOS_REC_IDS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      277, 4, CEOS_REC_TYP_I }, /* Prefix data per record */
+    { CEOS_REC_FDL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      9, 4, CEOS_REC_TYP_B }, /* Length of Imagry Options Header */
+    { CEOS_REC_PIXORD, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      0, 0, CEOS_REC_TYP_I }, /* Must be calculated */
+    { CEOS_REC_LINORD, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      0, 0, CEOS_REC_TYP_I }, /* Must be calculated */
+    { CEOS_REC_PRODTYPE, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      0, 0, CEOS_REC_TYP_I },
+
+    { CEOS_REC_RECORDSIZE, 1, CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC,
+      9, 4, CEOS_REC_TYP_B }, /* The processed image record size */
 
     /* Some ERS-1 products use an alternate data record subtype2. */
-    { __CEOS_REC_RECORDSIZE, 1, __CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC_ALT,
-      9, 4, __CEOS_REC_TYP_B }, /* The processed image record size */
+    { CEOS_REC_RECORDSIZE, 1, CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC_ALT,
+      9, 4, CEOS_REC_TYP_B }, /* The processed image record size */
 
     /* Yet another ERS-1 and ERS-2 alternate data record subtype2. */
-    { __CEOS_REC_RECORDSIZE, 1, __CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC_ALT2,
-      9, 4, __CEOS_REC_TYP_B }, /* The processed image record size */
+    { CEOS_REC_RECORDSIZE, 1, CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC_ALT2,
+      9, 4, CEOS_REC_TYP_B }, /* The processed image record size */
 
-    { __CEOS_REC_SUFFIX_SIZE, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      289, 4, __CEOS_REC_TYP_I }, /* Suffix data per record */
+    { CEOS_REC_SUFFIX_SIZE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      289, 4, CEOS_REC_TYP_I }, /* Suffix data per record */
     { 0, 0, 0, { 0, 0, 0, 0 }, 0, 0, 0 } /* Last record is Zero */
 } ;
 
 
-CeosRecipeType_t JersRecipe[] =
+static const CeosRecipeType_t JersRecipe[] =
 {
-    { __CEOS_REC_NUMCHANS, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
-      233, 4, __CEOS_REC_TYP_I }, /* Number of channels */
-    { __CEOS_REC_INTERLEAVE, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
-      269, 4, __CEOS_REC_TYP_A }, /* Interleaving type */
-    { __CEOS_REC_DATATYPE, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
-      429, 4, __CEOS_REC_TYP_A }, /* Data type */
-    { __CEOS_REC_BPR, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
-      0, 0, __CEOS_REC_TYP_A }, /* For Defeault CEOS, this is done using other vals */
-    { __CEOS_REC_LINES, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
-      237, 8, __CEOS_REC_TYP_I }, /* How many lines */
-    { __CEOS_REC_TBP, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
-      261, 4, __CEOS_REC_TYP_I },
-    { __CEOS_REC_BBP, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
-      265, 4, __CEOS_REC_TYP_I }, /* Bottom border pixels */
-    { __CEOS_REC_PPL, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
-      249, 8, __CEOS_REC_TYP_I }, /* Pixels per line */
-    { __CEOS_REC_LBP, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
-      245, 4, __CEOS_REC_TYP_I }, /* Left Border Pixels */
-    { __CEOS_REC_RBP, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
-      257, 4, __CEOS_REC_TYP_I }, /* Isn't available for RadarSAT */
-    { __CEOS_REC_BPP, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
-      225, 4, __CEOS_REC_TYP_I }, /* Bytes Per Pixel */
-    { __CEOS_REC_RPL, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
-      273, 2, __CEOS_REC_TYP_I }, /* Records per line */
-    { __CEOS_REC_PPR, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
-      0, 0, __CEOS_REC_TYP_I }, /* Pixels Per Record -- need to fill record type */
-    { __CEOS_REC_PDBPR, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
-      281, 8, __CEOS_REC_TYP_I }, /* pixel data bytes per record */
-    { __CEOS_REC_IDS, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
-      277, 4, __CEOS_REC_TYP_I }, /* Prefix data per record */
-    { __CEOS_REC_FDL, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
-      9, 4, __CEOS_REC_TYP_B }, /* Length of Imagry Options Header */
-    { __CEOS_REC_PIXORD, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
-      0, 0, __CEOS_REC_TYP_I }, /* Must be calculated */
-    { __CEOS_REC_LINORD, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
-      0, 0, __CEOS_REC_TYP_I }, /* Must be calculated */
-    { __CEOS_REC_PRODTYPE, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
-      0, 0, __CEOS_REC_TYP_I },
-
-    { __CEOS_REC_RECORDSIZE, 1, __CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC,
-      9, 4, __CEOS_REC_TYP_B }, /* The processed image record size */
-
-    { __CEOS_REC_SUFFIX_SIZE, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
-      289, 4, __CEOS_REC_TYP_I }, /* Suffix data per record */
+    { CEOS_REC_NUMCHANS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
+      233, 4, CEOS_REC_TYP_I }, /* Number of channels */
+    { CEOS_REC_INTERLEAVE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
+      269, 4, CEOS_REC_TYP_A }, /* Interleaving type */
+    { CEOS_REC_DATATYPE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
+      429, 4, CEOS_REC_TYP_A }, /* Data type */
+    { CEOS_REC_BPR, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
+      0, 0, CEOS_REC_TYP_A }, /* For Defeault CEOS, this is done using other vals */
+    { CEOS_REC_LINES, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
+      237, 8, CEOS_REC_TYP_I }, /* How many lines */
+    { CEOS_REC_TBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
+      261, 4, CEOS_REC_TYP_I },
+    { CEOS_REC_BBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
+      265, 4, CEOS_REC_TYP_I }, /* Bottom border pixels */
+    { CEOS_REC_PPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
+      249, 8, CEOS_REC_TYP_I }, /* Pixels per line */
+    { CEOS_REC_LBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
+      245, 4, CEOS_REC_TYP_I }, /* Left Border Pixels */
+    { CEOS_REC_RBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
+      257, 4, CEOS_REC_TYP_I }, /* Isn't available for RadarSAT */
+    { CEOS_REC_BPP, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
+      225, 4, CEOS_REC_TYP_I }, /* Bytes Per Pixel */
+    { CEOS_REC_RPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
+      273, 2, CEOS_REC_TYP_I }, /* Records per line */
+    { CEOS_REC_PPR, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
+      0, 0, CEOS_REC_TYP_I }, /* Pixels Per Record -- need to fill record type */
+    { CEOS_REC_PDBPR, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
+      281, 8, CEOS_REC_TYP_I }, /* pixel data bytes per record */
+    { CEOS_REC_IDS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
+      277, 4, CEOS_REC_TYP_I }, /* Prefix data per record */
+    { CEOS_REC_FDL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
+      9, 4, CEOS_REC_TYP_B }, /* Length of Imagry Options Header */
+    { CEOS_REC_PIXORD, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
+      0, 0, CEOS_REC_TYP_I }, /* Must be calculated */
+    { CEOS_REC_LINORD, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
+      0, 0, CEOS_REC_TYP_I }, /* Must be calculated */
+    { CEOS_REC_PRODTYPE, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
+      0, 0, CEOS_REC_TYP_I },
+
+    { CEOS_REC_RECORDSIZE, 1, CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC,
+      9, 4, CEOS_REC_TYP_B }, /* The processed image record size */
+
+    { CEOS_REC_SUFFIX_SIZE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
+      289, 4, CEOS_REC_TYP_I }, /* Suffix data per record */
     { 0, 0, 0, { 0, 0, 0, 0 }, 0, 0, 0 } /* Last record is Zero */
 } ;
 
-CeosRecipeType_t ScanSARRecipe[] =
+static const CeosRecipeType_t ScanSARRecipe[] =
 {
-    { __CEOS_REC_NUMCHANS, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      233, 4, __CEOS_REC_TYP_I }, /* Number of channels */
-    { __CEOS_REC_INTERLEAVE, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      269, 4, __CEOS_REC_TYP_A }, /* Interleaving type */
-    { __CEOS_REC_DATATYPE, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      429, 4, __CEOS_REC_TYP_A }, /* Data type */
-    { __CEOS_REC_LINES, 1, __CEOS_ANY_FILE, DATA_SET_SUMMARY,
-      325, 8, __CEOS_REC_TYP_I }, /* How many lines */
-    { __CEOS_REC_PPL, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      249, 8, __CEOS_REC_TYP_I }, /* Pixels per line */
-    { __CEOS_REC_BPP, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      225, 4, __CEOS_REC_TYP_I }, /* Bytes Per Pixel */
-    { __CEOS_REC_RPL, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      273, 2, __CEOS_REC_TYP_I }, /* Records per line */
-    { __CEOS_REC_IDS, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      277, 4, __CEOS_REC_TYP_I }, /* Prefix data per record */
-    { __CEOS_REC_FDL, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      9, 4, __CEOS_REC_TYP_B }, /* Length of Imagry Options Header */
-    { __CEOS_REC_RECORDSIZE, 1, __CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC,
-      9, 4, __CEOS_REC_TYP_B }, /* The processed image record size */
-    { __CEOS_REC_SUFFIX_SIZE, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      289, 4, __CEOS_REC_TYP_I }, /* Suffix data per record */
+    { CEOS_REC_NUMCHANS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      233, 4, CEOS_REC_TYP_I }, /* Number of channels */
+    { CEOS_REC_INTERLEAVE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      269, 4, CEOS_REC_TYP_A }, /* Interleaving type */
+    { CEOS_REC_DATATYPE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      429, 4, CEOS_REC_TYP_A }, /* Data type */
+    { CEOS_REC_LINES, 1, CEOS_ANY_FILE, DATA_SET_SUMMARY,
+      325, 8, CEOS_REC_TYP_I }, /* How many lines */
+    { CEOS_REC_PPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      249, 8, CEOS_REC_TYP_I }, /* Pixels per line */
+    { CEOS_REC_BPP, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      225, 4, CEOS_REC_TYP_I }, /* Bytes Per Pixel */
+    { CEOS_REC_RPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      273, 2, CEOS_REC_TYP_I }, /* Records per line */
+    { CEOS_REC_IDS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      277, 4, CEOS_REC_TYP_I }, /* Prefix data per record */
+    { CEOS_REC_FDL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      9, 4, CEOS_REC_TYP_B }, /* Length of Imagry Options Header */
+    { CEOS_REC_RECORDSIZE, 1, CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC,
+      9, 4, CEOS_REC_TYP_B }, /* The processed image record size */
+    { CEOS_REC_SUFFIX_SIZE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      289, 4, CEOS_REC_TYP_I }, /* Suffix data per record */
     { 0, 0, 0, { 0, 0, 0, 0 }, 0, 0, 0 } /* Last record is Zero */
 } ;
 
-CeosRecipeType_t SIRCRecipe[] =
+static const CeosRecipeType_t SIRCRecipe[] =
 {
-    { __CEOS_REC_NUMCHANS, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      233, 4, __CEOS_REC_TYP_I }, /* Number of channels */
-    { __CEOS_REC_INTERLEAVE, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      269, 4, __CEOS_REC_TYP_A }, /* Interleaving type */
-    { __CEOS_REC_DATATYPE, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      429, 4, __CEOS_REC_TYP_A }, /* Data type */
-    { __CEOS_REC_LINES, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      237, 8, __CEOS_REC_TYP_I }, /* How many lines */
-    { __CEOS_REC_TBP, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      261, 4, __CEOS_REC_TYP_I },
-    { __CEOS_REC_BBP, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      265, 4, __CEOS_REC_TYP_I }, /* Bottom border pixels */
-    { __CEOS_REC_PPL, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      249, 8, __CEOS_REC_TYP_I }, /* Pixels per line */
-    { __CEOS_REC_LBP, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      245, 4, __CEOS_REC_TYP_I }, /* Left Border Pixels */
-    { __CEOS_REC_RBP, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      257, 4, __CEOS_REC_TYP_I }, /* Right Border Pixels */
-    { __CEOS_REC_BPP, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      225, 4, __CEOS_REC_TYP_I }, /* Bytes Per Pixel */
-    { __CEOS_REC_RPL, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      273, 2, __CEOS_REC_TYP_I }, /* Records per line */
-    { __CEOS_REC_IDS, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      277, 4, __CEOS_REC_TYP_I }, /* Prefix data per record */
-    { __CEOS_REC_FDL, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      9, 4, __CEOS_REC_TYP_B }, /* Length of Imagry Options Header */
-    { __CEOS_REC_RECORDSIZE, 1, __CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC,
-      9, 4, __CEOS_REC_TYP_B }, /* The processed image record size */
-    { __CEOS_REC_SUFFIX_SIZE, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
-      289, 4, __CEOS_REC_TYP_I }, /* Suffix data per record */
+    { CEOS_REC_NUMCHANS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      233, 4, CEOS_REC_TYP_I }, /* Number of channels */
+    { CEOS_REC_INTERLEAVE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      269, 4, CEOS_REC_TYP_A }, /* Interleaving type */
+    { CEOS_REC_DATATYPE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      429, 4, CEOS_REC_TYP_A }, /* Data type */
+    { CEOS_REC_LINES, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      237, 8, CEOS_REC_TYP_I }, /* How many lines */
+    { CEOS_REC_TBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      261, 4, CEOS_REC_TYP_I },
+    { CEOS_REC_BBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      265, 4, CEOS_REC_TYP_I }, /* Bottom border pixels */
+    { CEOS_REC_PPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      249, 8, CEOS_REC_TYP_I }, /* Pixels per line */
+    { CEOS_REC_LBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      245, 4, CEOS_REC_TYP_I }, /* Left Border Pixels */
+    { CEOS_REC_RBP, 0, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      257, 4, CEOS_REC_TYP_I }, /* Right Border Pixels */
+    { CEOS_REC_BPP, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      225, 4, CEOS_REC_TYP_I }, /* Bytes Per Pixel */
+    { CEOS_REC_RPL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      273, 2, CEOS_REC_TYP_I }, /* Records per line */
+    { CEOS_REC_IDS, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      277, 4, CEOS_REC_TYP_I }, /* Prefix data per record */
+    { CEOS_REC_FDL, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      9, 4, CEOS_REC_TYP_B }, /* Length of Imagry Options Header */
+    { CEOS_REC_RECORDSIZE, 1, CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC,
+      9, 4, CEOS_REC_TYP_B }, /* The processed image record size */
+    { CEOS_REC_SUFFIX_SIZE, 1, CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
+      289, 4, CEOS_REC_TYP_I }, /* Suffix data per record */
 
     { 0, 0, 0, { 0, 0, 0, 0 }, 0, 0, 0 } /* Last record is Zero */
 } ;
@@ -249,8 +249,8 @@ static char *ExtractString( CeosRecord_t *record, unsigned int offset, unsigned
 
 static int GetCeosStringType(const CeosStringType_t *CeosType, const char *string);
 
-static int SIRCRecipeFCN( CeosSARVolume_t *volume, void *token );
-static int PALSARRecipeFCN( CeosSARVolume_t *volume, void *token );
+static int SIRCRecipeFCN( CeosSARVolume_t *volume, const void *token );
+static int PALSARRecipeFCN( CeosSARVolume_t *volume, const void *token );
 
 Link_t *RecipeFunctions = NULL;
 
@@ -268,18 +268,18 @@ void RegisterRecipes( void )
 void FreeRecipes( void )
 
 {
-    Link_t *link;
+    Link_t *l_link;
 
-    for( link = RecipeFunctions; link != NULL; link = link->next )
-        HFree( link->object );
+    for( l_link = RecipeFunctions; l_link != NULL; l_link = l_link->next )
+        HFree( l_link->object );
 
     DestroyList( RecipeFunctions );
     RecipeFunctions = NULL;
 }
 
 void AddRecipe( int (*function)(CeosSARVolume_t *volume,
-				void *token),
-		void *token,
+				const void *token),
+		const void *token,
                 const char *name )
 {
 
@@ -303,9 +303,9 @@ void AddRecipe( int (*function)(CeosSARVolume_t *volume,
     }
 }
 
-int CeosDefaultRecipe( CeosSARVolume_t *volume, void *token )
+int CeosDefaultRecipe( CeosSARVolume_t *volume, const void *token )
 {
-    CeosRecipeType_t *recipe;
+    const CeosRecipeType_t *recipe;
     CeosRecord_t *record;
     CeosTypeCode_t TypeCode;
     struct CeosSARImageDesc *ImageDesc = &(volume->ImageDesc);
@@ -344,27 +344,27 @@ int CeosDefaultRecipe( CeosSARVolume_t *volume, void *token )
 
 		switch( recipe[i].ImageDescValue )
 		{
-		case __CEOS_REC_NUMCHANS:
+		case CEOS_REC_NUMCHANS:
 		   DoExtractInt( ImageDesc->NumChannels );
 		   break;
-		case __CEOS_REC_LINES:
+		case CEOS_REC_LINES:
 		    DoExtractInt( ImageDesc->Lines );
 		    break;
-		case __CEOS_REC_BPP:
+		case CEOS_REC_BPP:
 		    DoExtractInt( ImageDesc->BytesPerPixel );
 		    break;
-		case __CEOS_REC_RPL:
+		case CEOS_REC_RPL:
 		    DoExtractInt( ImageDesc->RecordsPerLine );
 		    break;
-		case __CEOS_REC_PDBPR:
+		case CEOS_REC_PDBPR:
 		    DoExtractInt( ImageDesc->PixelDataBytesPerRecord );
 		    break;
-		case __CEOS_REC_FDL:
+		case CEOS_REC_FDL:
 		    DoExtractInt( ImageDesc->FileDescriptorLength );
 		    break;
-		case __CEOS_REC_IDS:
+		case CEOS_REC_IDS:
 		    DoExtractInt( ImageDesc->ImageDataStart );
-                    /* 
+                    /*
                     ** This is really reading the quantity of prefix data
                     ** per data record.  We want the offset from the very
                     ** beginning of the record to the data, so we add another
@@ -376,39 +376,38 @@ int CeosDefaultRecipe( CeosSARVolume_t *volume, void *token )
 		    if( ImageDesc->ImageDataStart != 192 )
                         ImageDesc->ImageDataStart += 12;
 		    break;
-		case __CEOS_REC_SUFFIX_SIZE:
+		case CEOS_REC_SUFFIX_SIZE:
 		    DoExtractInt( ImageDesc->ImageSuffixData );
 		    break;
-		case __CEOS_REC_RECORDSIZE:
+		case CEOS_REC_RECORDSIZE:
 		    DoExtractInt( ImageDesc->BytesPerRecord );
 		    break;
-		case __CEOS_REC_PPL:
+		case CEOS_REC_PPL:
 		    DoExtractInt( ImageDesc->PixelsPerLine );
 		    break;
-		case __CEOS_REC_TBP:
+		case CEOS_REC_TBP:
 		    DoExtractInt( ImageDesc->TopBorderPixels );
 		    break;
-		case __CEOS_REC_BBP:
+		case CEOS_REC_BBP:
 		    DoExtractInt( ImageDesc->BottomBorderPixels );
 		    break;
-		case __CEOS_REC_LBP:
+		case CEOS_REC_LBP:
 		    DoExtractInt( ImageDesc->LeftBorderPixels );
 		    break;
-		case __CEOS_REC_RBP:
+		case CEOS_REC_RBP:
 		    DoExtractInt( ImageDesc->RightBorderPixels );
 		    break;
-		case __CEOS_REC_INTERLEAVE:
+		case CEOS_REC_INTERLEAVE:
 		    ExtractString( record, recipe[i].Offset, recipe[i].Length, temp_str );
 
 		    ImageDesc->ChannelInterleaving = GetCeosStringType( CeosInterleaveType, temp_str );
 		    break;
-		case __CEOS_REC_DATATYPE:
+		case CEOS_REC_DATATYPE:
 		    ExtractString( record, recipe[i].Offset, recipe[i].Length, temp_str );
 
 		    ImageDesc->DataType = GetCeosStringType( CeosDataType, temp_str );
 		    break;
 		}
-		
 	    }
 	}
     }
@@ -418,13 +417,13 @@ int CeosDefaultRecipe( CeosSARVolume_t *volume, void *token )
      * bytes of pixel data if necessary.
      */
 
-    if( ImageDesc->PixelsPerLine == 0 
-        && ImageDesc->PixelDataBytesPerRecord != 0 
+    if( ImageDesc->PixelsPerLine == 0
+        && ImageDesc->PixelDataBytesPerRecord != 0
         && ImageDesc->BytesPerPixel != 0 )
     {
-        ImageDesc->PixelsPerLine = 
+        ImageDesc->PixelsPerLine =
             ImageDesc->PixelDataBytesPerRecord / ImageDesc->BytesPerPixel;
-        CPLDebug( "SAR_CEOS", "Guessing PixelPerLine to be %d\n", 
+        CPLDebug( "SAR_CEOS", "Guessing PixelPerLine to be %d\n",
                   ImageDesc->PixelsPerLine );
     }
 
@@ -443,27 +442,27 @@ int CeosDefaultRecipe( CeosSARVolume_t *volume, void *token )
         TypeCode.UCharCode.Type = 0xed;
         TypeCode.UCharCode.Subtype2 = 0x12;
         TypeCode.UCharCode.Subtype3 = 0x12;
-        
-        img_rec = FindCeosRecord( volume->RecordList, TypeCode, 
-                                  __CEOS_IMAGRY_OPT_FILE, -1, -1 );
+
+        img_rec = FindCeosRecord( volume->RecordList, TypeCode,
+                                  CEOS_IMAGRY_OPT_FILE, -1, -1 );
         if( img_rec == NULL )
         {
-            CPLDebug( "SAR_CEOS", 
+            CPLDebug( "SAR_CEOS",
                       "Unable to find imagery rec to check record length." );
             return 0;
         }
 
         if( img_rec->Length != ImageDesc->BytesPerRecord )
         {
-            CPLDebug( "SAR_CEOS", 
+            CPLDebug( "SAR_CEOS",
                       "Guessed record length (%d) did not match\n"
-                      "actual imagery record length (%d), recipe fails.", 
+                      "actual imagery record length (%d), recipe fails.",
                       ImageDesc->BytesPerRecord, img_rec->Length );
             return 0;
         }
     }
-    
-    if( ImageDesc->PixelsPerRecord == 0 && 
+
+    if( ImageDesc->PixelsPerRecord == 0 &&
 	ImageDesc->BytesPerRecord != 0 && ImageDesc->BytesPerPixel != 0 )
     {
 	ImageDesc->PixelsPerRecord = ( ( ImageDesc->BytesPerRecord -
@@ -483,13 +482,13 @@ int CeosDefaultRecipe( CeosSARVolume_t *volume, void *token )
         int  nDataTypeSize = ImageDesc->BytesPerPixel / ImageDesc->NumChannels;
 
         if( nDataTypeSize == 1 )
-            ImageDesc->DataType = __CEOS_TYP_UCHAR;
+            ImageDesc->DataType = CEOS_TYP_UCHAR;
         else if( nDataTypeSize == 2 )
-            ImageDesc->DataType = __CEOS_TYP_USHORT;
+            ImageDesc->DataType = CEOS_TYP_USHORT;
     }
 
     /* Sanity checking */
-    
+
     if( ImageDesc->PixelsPerLine == 0 || ImageDesc->Lines == 0 ||
 	ImageDesc->RecordsPerLine == 0 || ImageDesc->ImageDataStart == 0 ||
 	ImageDesc->FileDescriptorLength == 0 || ImageDesc->DataType == 0 ||
@@ -498,13 +497,13 @@ int CeosDefaultRecipe( CeosSARVolume_t *volume, void *token )
     {
 	return 0;
     } else {
-	
+
 	ImageDesc->ImageDescValid = TRUE;
 	return 1;
     }
 }
 
-int ScanSARRecipeFCN( CeosSARVolume_t *volume, void *token )
+int ScanSARRecipeFCN( CeosSARVolume_t *volume, const void *token )
 {
     struct CeosSARImageDesc *ImageDesc = &(volume->ImageDesc);
 
@@ -517,9 +516,9 @@ int ScanSARRecipeFCN( CeosSARVolume_t *volume, void *token )
     }
 
     return 0;
-}    
+}
 
-static int SIRCRecipeFCN( CeosSARVolume_t *volume, void *token )
+static int SIRCRecipeFCN( CeosSARVolume_t *volume, const void *token )
 {
     struct CeosSARImageDesc *ImageDesc = &(volume->ImageDesc);
     CeosTypeCode_t TypeCode;
@@ -540,13 +539,13 @@ static int SIRCRecipeFCN( CeosSARVolume_t *volume, void *token )
     TypeCode.UCharCode.Subtype2 = 18;
     TypeCode.UCharCode.Subtype3 = 18;
 
-    record = FindCeosRecord( volume->RecordList, TypeCode, 
-                             __CEOS_IMAGRY_OPT_FILE, -1, -1 );
+    record = FindCeosRecord( volume->RecordList, TypeCode,
+                             CEOS_IMAGRY_OPT_FILE, -1, -1 );
     if( record == NULL )
         return 0;
 
     ExtractString( record, 401, 28, szSARDataFormat );
-    if( !EQUALN( szSARDataFormat, "COMPRESSED CROSS-PRODUCTS", 25) )
+    if( !STARTS_WITH_CI(szSARDataFormat, "COMPRESSED CROSS-PRODUCTS") )
         return 0;
 
 /* -------------------------------------------------------------------- */
@@ -564,10 +563,10 @@ static int SIRCRecipeFCN( CeosSARVolume_t *volume, void *token )
 /*      Then fix up a few values.                                       */
 /* -------------------------------------------------------------------- */
     /* It seems the bytes of pixel data per record is just wrong.  Fix. */
-    ImageDesc->PixelDataBytesPerRecord = 
+    ImageDesc->PixelDataBytesPerRecord =
         ImageDesc->BytesPerPixel * ImageDesc->PixelsPerLine;
-    
-    ImageDesc->DataType = __CEOS_TYP_CCP_COMPLEX_FLOAT;
+
+    ImageDesc->DataType = CEOS_TYP_CCP_COMPLEX_FLOAT;
 
 /* -------------------------------------------------------------------- */
 /*      Sanity checking                                                 */
@@ -580,13 +579,13 @@ static int SIRCRecipeFCN( CeosSARVolume_t *volume, void *token )
     {
 	return 0;
     } else {
-	
+
 	ImageDesc->ImageDescValid = TRUE;
 	return 1;
     }
-}    
+}
 
-static int PALSARRecipeFCN( CeosSARVolume_t *volume, void *token )
+static int PALSARRecipeFCN( CeosSARVolume_t *volume, const void *token )
 {
     struct CeosSARImageDesc *ImageDesc = &(volume->ImageDesc);
     CeosTypeCode_t TypeCode;
@@ -607,17 +606,17 @@ static int PALSARRecipeFCN( CeosSARVolume_t *volume, void *token )
     TypeCode.UCharCode.Subtype2 = 18;
     TypeCode.UCharCode.Subtype3 = 18;
 
-    record = FindCeosRecord( volume->RecordList, TypeCode, 
-                             __CEOS_IMAGRY_OPT_FILE, -1, -1 );
+    record = FindCeosRecord( volume->RecordList, TypeCode,
+                             CEOS_IMAGRY_OPT_FILE, -1, -1 );
     if( record == NULL )
         return 0;
 
     ExtractString( record, 401, 28, szSARDataFormat );
-    if( !EQUALN( szSARDataFormat, "INTEGER*18                 ", 25) )
+    if( !STARTS_WITH_CI( szSARDataFormat, "INTEGER*18                 ") )
         return 0;
 
     ExtractString( record, 49, 16, szProduct );
-    if( !EQUALN( szProduct, "ALOS-", 5 ) )
+    if( !STARTS_WITH_CI(szProduct, "ALOS-") )
         return 0;
 
 /* -------------------------------------------------------------------- */
@@ -634,7 +633,7 @@ static int PALSARRecipeFCN( CeosSARVolume_t *volume, void *token )
 /* -------------------------------------------------------------------- */
 /*      Then fix up a few values.                                       */
 /* -------------------------------------------------------------------- */
-    ImageDesc->DataType = __CEOS_TYP_PALSAR_COMPLEX_SHORT;
+    ImageDesc->DataType = CEOS_TYP_PALSAR_COMPLEX_SHORT;
     ImageDesc->NumChannels = 6;
 
 /* -------------------------------------------------------------------- */
@@ -648,17 +647,17 @@ static int PALSARRecipeFCN( CeosSARVolume_t *volume, void *token )
     {
 	return 0;
     } else {
-	
+
 	ImageDesc->ImageDescValid = TRUE;
 	return 1;
     }
-}    
+}
 
 void GetCeosSARImageDesc( CeosSARVolume_t *volume )
 {
-    Link_t *link;
+    Link_t *l_link;
     RecipeFunctionData_t *rec_data;
-    int (*function)(CeosSARVolume_t *volume, void *token);
+    int (*function)(CeosSARVolume_t *volume, const void *token);
 
     if( RecipeFunctions == NULL )
     {
@@ -670,15 +669,15 @@ void GetCeosSARImageDesc( CeosSARVolume_t *volume )
 	return ;
     }
 
-    for(link = RecipeFunctions; link != NULL; link = link->next)
+    for(l_link = RecipeFunctions; l_link != NULL; l_link = l_link->next)
     {
-	if(link->object)
+	if(l_link->object)
 	{
-	    rec_data = link->object;
+	    rec_data = l_link->object;
             function = rec_data->function;
 	    if(( *function )( volume, rec_data->token ) )
             {
-                CPLDebug( "CEOS", "Using recipe '%s'.", 
+                CPLDebug( "CEOS", "Using recipe '%s'.",
                           rec_data->name );
 		return;
             }
@@ -699,13 +698,13 @@ static void ExtractInt(CeosRecord_t *record, int type, unsigned int offset, unsi
 
     switch(type)
     {
-    case __CEOS_REC_TYP_A:
-	sprintf( format, "A%u", length );
+    case CEOS_REC_TYP_A:
+	snprintf( format, sizeof(format), "A%u", length );
 	GetCeosField( record, offset, format,  buffer );
 	*value = atoi( buffer );
 	break;
-    case __CEOS_REC_TYP_B:
-	sprintf( format, "B%u", length );
+    case CEOS_REC_TYP_B:
+	snprintf( format, sizeof(format), "B%u", length );
 #ifdef notdef
 	GetCeosField( record, offset, format, buffer );
 	if( length <= 4 )
@@ -716,8 +715,8 @@ static void ExtractInt(CeosRecord_t *record, int type, unsigned int offset, unsi
 	GetCeosField( record, offset, format, value );
 #endif
 	break;
-    case __CEOS_REC_TYP_I:
-	sprintf( format, "I%u", length );
+    case CEOS_REC_TYP_I:
+	snprintf( format, sizeof(format), "I%u", length );
 	GetCeosField( record, offset, format, value );
 	break;
     }
@@ -735,7 +734,7 @@ static char *ExtractString( CeosRecord_t *record, unsigned int offset, unsigned
 	string = HMalloc( length + 1 );
     }
 
-    sprintf( format, "A%u", length );
+    snprintf( format, sizeof(format), "A%u", length );
 
     GetCeosField( record, offset, format, string );
 
diff --git a/frmts/ceos2/ceossar.c b/frmts/ceos2/ceossar.c
index a11a39a..c6d9529 100644
--- a/frmts/ceos2/ceossar.c
+++ b/frmts/ceos2/ceossar.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ceossar.c 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ceossar.c 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  ASI CEOS Translator
  * Purpose:  Functions related to CeosSARVolume_t.
@@ -29,7 +29,7 @@
 
 #include "ceos.h"
 
-CPL_CVSID("$Id: ceossar.c 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ceossar.c 33720 2016-03-15 00:39:53Z goatbar $");
 
 extern Link_t *RecipeFunctions;
 
@@ -69,17 +69,17 @@ void CalcCeosSARImageFilePosition(CeosSARVolume_t *volume, int channel, int line
 
 	    switch( ImageDesc->ChannelInterleaving )
 	    {
-	    case __CEOS_IL_PIXEL:
+	    case CEOS_IL_PIXEL:
 		TotalRecords = (line - 1) * ImageDesc->RecordsPerLine;
 		TotalBytes = (TotalRecords) * ( ImageDesc->BytesPerRecord );
 		break;
-	    case __CEOS_IL_LINE:
-		TotalRecords = (ImageDesc->NumChannels * (line - 1) + 
+	    case CEOS_IL_LINE:
+		TotalRecords = (ImageDesc->NumChannels * (line - 1) +
 				(channel - 1)) * ImageDesc->RecordsPerLine;
 		TotalBytes = (TotalRecords) * ( ImageDesc->BytesPerRecord ) ;
 		break;
-	    case __CEOS_IL_BAND:
-		TotalRecords = (((channel - 1) * ImageDesc->Lines) * 
+	    case CEOS_IL_BAND:
+		TotalRecords = (((channel - 1) * ImageDesc->Lines) *
 				ImageDesc->RecordsPerLine) +
 				(line - 1) * ImageDesc->RecordsPerLine;
 
@@ -119,7 +119,7 @@ void GetCeosSAREmbeddedInfo(CPL_UNUSED CeosSARVolume_t *volume,
 void DeleteCeosSARVolume(CeosSARVolume_t *volume)
 {
     Link_t *Links;
-    
+
     if( volume )
     {
 	if( volume->RecordList )
diff --git a/frmts/ceos2/sar_ceosdataset.cpp b/frmts/ceos2/sar_ceosdataset.cpp
index 24c76bd..7530496 100644
--- a/frmts/ceos2/sar_ceosdataset.cpp
+++ b/frmts/ceos2/sar_ceosdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sar_ceosdataset.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: sar_ceosdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  ASI CEOS Translator
  * Purpose:  GDALDataset driver for CEOS translator.
@@ -29,35 +29,26 @@
  ****************************************************************************/
 
 #include "ceos.h"
+#include "cpl_string.h"
+#include "gdal_frmts.h"
 #include "gdal_priv.h"
 #include "rawdataset.h"
-#include "cpl_string.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: sar_ceosdataset.cpp 27942 2014-11-11 00:57:41Z rouault $");
-
-CPL_C_START
-void	GDALRegister_SAR_CEOS(void);
-CPL_C_END
-
-static GInt16 CastToGInt16(float val);
+CPL_CVSID("$Id: sar_ceosdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 static GInt16 CastToGInt16(float val)
 {
-    float temp;
-
-    temp = val;
-
-    if ( temp < -32768.0 )
-        temp = -32768.0;
+    if ( val < -32768.0 )
+        val = -32768.0;
 
-    if ( temp > 32767 )
-        temp = 32767.0;
+    if ( val > 32767 )
+        val = 32767.0;
 
-    return (GInt16) temp;    
+    return static_cast<GInt16>(val);
 }
 
-static const char *CeosExtension[][6] = { 
+static const char * const CeosExtension[][6] = {
 { "vol", "led", "img", "trl", "nul", "ext" },
 { "vol", "lea", "img", "trl", "nul", "ext" },
 { "vol", "led", "img", "tra", "nul", "ext" },
@@ -86,10 +77,10 @@ static const char *CeosExtension[][6] = {
 { "vol", "sarl", "sard", "sart", "nvol", "ext" },
 
 /* end marker */
-{ NULL, NULL, NULL, NULL, NULL, NULL } 
+{ NULL, NULL, NULL, NULL, NULL, NULL }
 };
 
-static int 
+static int
 ProcessData( VSILFILE *fp, int fileid, CeosSARVolume_t *sar, int max_records,
              vsi_l_offset max_bytes );
 
@@ -114,6 +105,7 @@ static CeosTypeCode_t QuadToTC( int a, int b, int c, int d )
 #define LEADER_RADIOMETRIC_DATA_RECORD_TC  QuadToTC( 18, 50, 18, 20 )
 #define LEADER_MAP_PROJ_RECORD_TC          QuadToTC( 10, 20, 31, 20 )
 
+// TODO: recond?
 /* JERS from Japan has MAP_PROJ recond with different identifiers */
 /* see CEOS-SAR-CCT Iss/Rev: 2/0 February 10, 1989 */
 #define LEADER_MAP_PROJ_RECORD_JERS_TC         QuadToTC( 18, 20, 18, 20 )
@@ -146,7 +138,7 @@ class SAR_CEOSDataset : public GDALPamDataset
     VSILFILE	*fpImage;
 
     char        **papszTempMD;
-    
+
     int         nGCPCount;
     GDAL_GCP    *pasGCPList;
 
@@ -220,16 +212,16 @@ class SAR_CEOSRasterBand : public GDALPamRasterBand
 /*                         SAR_CEOSRasterBand()                         */
 /************************************************************************/
 
-SAR_CEOSRasterBand::SAR_CEOSRasterBand( SAR_CEOSDataset *poGDS, int nBand,
+SAR_CEOSRasterBand::SAR_CEOSRasterBand( SAR_CEOSDataset *poGDSIn, int nBandIn,
                                         GDALDataType eType )
 
 {
-    this->poDS = poGDS;
-    this->nBand = nBand;
-    
+    this->poDS = poGDSIn;
+    this->nBand = nBandIn;
+
     eDataType = eType;
 
-    nBlockXSize = poGDS->nRasterXSize;
+    nBlockXSize = poGDSIn->nRasterXSize;
     nBlockYSize = 1;
 }
 
@@ -237,17 +229,15 @@ SAR_CEOSRasterBand::SAR_CEOSRasterBand( SAR_CEOSDataset *poGDS, int nBand,
 /*                             IReadBlock()                             */
 /************************************************************************/
 
-CPLErr SAR_CEOSRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
+CPLErr SAR_CEOSRasterBand::IReadBlock( int /* nBlockXOff */,
                                        int nBlockYOff,
                                        void * pImage )
 {
-    struct CeosSARImageDesc *ImageDesc;
-    int	   offset;
-    GByte  *pabyRecord;
     SAR_CEOSDataset *poGDS = (SAR_CEOSDataset *) poDS;
 
-    ImageDesc = &(poGDS->sVolume.ImageDesc);
+    struct CeosSARImageDesc *ImageDesc = &(poGDS->sVolume.ImageDesc);
 
+    int	offset;
     CalcCeosSARImageFilePosition( &(poGDS->sVolume), nBand,
                                   nBlockYOff + 1, NULL, &offset );
 
@@ -257,11 +247,12 @@ CPLErr SAR_CEOSRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /*      Load all the pixel data associated with this scanline.          */
 /*      Ensure we handle multiple record scanlines properly.            */
 /* -------------------------------------------------------------------- */
-    int		iRecord, nPixelsRead = 0;
+    int nPixelsRead = 0;
+
+    GByte *pabyRecord
+        = (GByte *) CPLMalloc( ImageDesc->BytesPerPixel * nBlockXSize );
 
-    pabyRecord = (GByte *) CPLMalloc( ImageDesc->BytesPerPixel * nBlockXSize );
-    
-    for( iRecord = 0; iRecord < ImageDesc->RecordsPerLine; iRecord++ )
+    for( int iRecord = 0; iRecord < ImageDesc->RecordsPerLine; iRecord++ )
     {
         int	nPixelsToRead;
 
@@ -269,44 +260,44 @@ CPLErr SAR_CEOSRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
             nPixelsToRead = nBlockXSize - nPixelsRead;
         else
             nPixelsToRead = ImageDesc->PixelsPerRecord;
-        
-        VSIFSeekL( poGDS->fpImage, offset, SEEK_SET );
-        VSIFReadL( pabyRecord + nPixelsRead * ImageDesc->BytesPerPixel, 
-                   1, nPixelsToRead * ImageDesc->BytesPerPixel, 
-                   poGDS->fpImage );
+
+        CPL_IGNORE_RET_VAL(VSIFSeekL( poGDS->fpImage, offset, SEEK_SET ));
+        CPL_IGNORE_RET_VAL(VSIFReadL( pabyRecord + nPixelsRead * ImageDesc->BytesPerPixel,
+                   1, nPixelsToRead * ImageDesc->BytesPerPixel,
+                   poGDS->fpImage ));
 
         nPixelsRead += nPixelsToRead;
         offset += ImageDesc->BytesPerRecord;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Copy the desired band out based on the size of the type, and    */
 /*      the interleaving mode.                                          */
 /* -------------------------------------------------------------------- */
-    int		nBytesPerSample = GDALGetDataTypeSize( eDataType ) / 8;
+    const int nBytesPerSample = GDALGetDataTypeSize( eDataType ) / 8;
 
-    if( ImageDesc->ChannelInterleaving == __CEOS_IL_PIXEL )
+    if( ImageDesc->ChannelInterleaving == CEOS_IL_PIXEL )
     {
-        GDALCopyWords( pabyRecord + (nBand-1) * nBytesPerSample, 
-                       eDataType, ImageDesc->BytesPerPixel, 
-                       pImage, eDataType, nBytesPerSample, 
+        GDALCopyWords( pabyRecord + (nBand-1) * nBytesPerSample,
+                       eDataType, ImageDesc->BytesPerPixel,
+                       pImage, eDataType, nBytesPerSample,
                        nBlockXSize );
     }
-    else if( ImageDesc->ChannelInterleaving == __CEOS_IL_LINE )
+    else if( ImageDesc->ChannelInterleaving == CEOS_IL_LINE )
     {
-        GDALCopyWords( pabyRecord + (nBand-1) * nBytesPerSample * nBlockXSize, 
-                       eDataType, nBytesPerSample, 
-                       pImage, eDataType, nBytesPerSample, 
+        GDALCopyWords( pabyRecord + (nBand-1) * nBytesPerSample * nBlockXSize,
+                       eDataType, nBytesPerSample,
+                       pImage, eDataType, nBytesPerSample,
                        nBlockXSize );
     }
-    else if( ImageDesc->ChannelInterleaving == __CEOS_IL_BAND )
+    else if( ImageDesc->ChannelInterleaving == CEOS_IL_BAND )
     {
         memcpy( pImage, pabyRecord, nBytesPerSample * nBlockXSize );
     }
 
 #ifdef CPL_LSB
     GDALSwapWords( pImage, nBytesPerSample, nBlockXSize, nBytesPerSample );
-#endif    
+#endif
 
     CPLFree( pabyRecord );
 
@@ -323,16 +314,16 @@ CPLErr SAR_CEOSRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /*                           CCPRasterBand()                            */
 /************************************************************************/
 
-CCPRasterBand::CCPRasterBand( SAR_CEOSDataset *poGDS, int nBand,
+CCPRasterBand::CCPRasterBand( SAR_CEOSDataset *poGDSIn, int nBandIn,
                               GDALDataType eType )
 
 {
-    this->poDS = poGDS;
-    this->nBand = nBand;
+    this->poDS = poGDSIn;
+    this->nBand = nBandIn;
 
     eDataType = eType;
 
-    nBlockXSize = poGDS->nRasterXSize;
+    nBlockXSize = poGDSIn->nRasterXSize;
     nBlockYSize = 1;
 
     if( nBand == 1 )
@@ -375,33 +366,28 @@ CPLErr CCPRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                                   int nBlockYOff,
                                   void * pImage )
 {
-    struct CeosSARImageDesc *ImageDesc;
-    int	   offset;
-    GByte  *pabyRecord;
     SAR_CEOSDataset *poGDS = (SAR_CEOSDataset *) poDS;
-    static float afPowTable[256];
-    static int bPowTableInitialized = FALSE;
 
-    ImageDesc = &(poGDS->sVolume.ImageDesc);
+    struct CeosSARImageDesc *ImageDesc = &(poGDS->sVolume.ImageDesc);
 
-    offset = ImageDesc->FileDescriptorLength
-        + ImageDesc->BytesPerRecord * nBlockYOff 
+    int offset = ImageDesc->FileDescriptorLength
+        + ImageDesc->BytesPerRecord * nBlockYOff
         + ImageDesc->ImageDataStart;
 
 /* -------------------------------------------------------------------- */
 /*      Load all the pixel data associated with this scanline.          */
 /* -------------------------------------------------------------------- */
-    int	        nBytesToRead = ImageDesc->BytesPerPixel * nBlockXSize;
+    const int nBytesToRead = ImageDesc->BytesPerPixel * nBlockXSize;
+
+    GByte *pabyRecord = (GByte *) CPLMalloc( nBytesToRead );
 
-    pabyRecord = (GByte *) CPLMalloc( nBytesToRead );
-    
-    if( VSIFSeekL( poGDS->fpImage, offset, SEEK_SET ) != 0 
-        || (int) VSIFReadL( pabyRecord, 1, nBytesToRead, 
+    if( VSIFSeekL( poGDS->fpImage, offset, SEEK_SET ) != 0
+        || (int) VSIFReadL( pabyRecord, 1, nBytesToRead,
                            poGDS->fpImage ) != nBytesToRead )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   "Error reading %d bytes of CEOS record data at offset %d.\n"
-                  "Reading file %s failed.", 
+                  "Reading file %s failed.",
                   nBytesToRead, offset, poGDS->GetDescription() );
         CPLFree( pabyRecord );
         return CE_Failure;
@@ -410,13 +396,14 @@ CPLErr CCPRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /* -------------------------------------------------------------------- */
 /*      Initialize our power table if this is our first time through.   */
 /* -------------------------------------------------------------------- */
+    static float afPowTable[256];
+    static bool bPowTableInitialized = false;
+
     if( !bPowTableInitialized )
     {
-        int i;
-
-        bPowTableInitialized = TRUE;
+        bPowTableInitialized = true;
 
-        for( i = 0; i < 256; i++ )
+        for( int i = 0; i < 256; i++ )
         {
             afPowTable[i] = (float)pow( 2.0, i-128 );
         }
@@ -426,17 +413,16 @@ CPLErr CCPRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /*      Copy the desired band out based on the size of the type, and    */
 /*      the interleaving mode.                                          */
 /* -------------------------------------------------------------------- */
-    int iX;
-
-    for( iX = 0; iX < nBlockXSize; iX++ )
+    for( int iX = 0; iX < nBlockXSize; iX++ )
     {
         unsigned char *pabyGroup = pabyRecord + iX * ImageDesc->BytesPerPixel;
         signed char *Byte = (signed char*)pabyGroup-1; /* A ones based alias */
-        double dfReSHH, dfImSHH, dfReSHV, dfImSHV, 
-            dfReSVH, dfImSVH, dfReSVV, dfImSVV, dfScale;
+        double dfReSHH, dfImSHH, dfReSHV, dfImSHV,
+            dfReSVH, dfImSVH, dfReSVV, dfImSVV;
+
+        const double dfScale = sqrt( (Byte[2] / 254.0 + 1.5)
+                                     * afPowTable[Byte[1] + 128] );
 
-        dfScale = sqrt( (Byte[2] / 254 + 1.5) * afPowTable[Byte[1] + 128] );
-        
         if( nBand == 1 )
         {
             dfReSHH = Byte[3] * dfScale / 127.0;
@@ -444,7 +430,7 @@ CPLErr CCPRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 
             ((float *) pImage)[iX*2  ] = (float)dfReSHH;
             ((float *) pImage)[iX*2+1] = (float)dfImSHH;
-        }        
+        }
         else if( nBand == 2 )
         {
             dfReSHV = Byte[5] * dfScale / 127.0;
@@ -486,15 +472,15 @@ CPLErr CCPRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /*                           PALSARRasterBand()                         */
 /************************************************************************/
 
-PALSARRasterBand::PALSARRasterBand( SAR_CEOSDataset *poGDS, int nBand )
+PALSARRasterBand::PALSARRasterBand( SAR_CEOSDataset *poGDSIn, int nBandIn )
 
 {
-    this->poDS = poGDS;
-    this->nBand = nBand;
+    this->poDS = poGDSIn;
+    this->nBand = nBandIn;
 
     eDataType = GDT_CInt16;
 
-    nBlockXSize = poGDS->nRasterXSize;
+    nBlockXSize = poGDSIn->nRasterXSize;
     nBlockYSize = 1;
 
     if( nBand == 1 )
@@ -517,35 +503,32 @@ PALSARRasterBand::PALSARRasterBand( SAR_CEOSDataset *poGDS, int nBand )
 /*      Based on ERSDAC-VX-CEOS-004                                     */
 /************************************************************************/
 
-CPLErr PALSARRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
+CPLErr PALSARRasterBand::IReadBlock( int /* nBlockXOff */,
                                      int nBlockYOff,
                                      void * pImage )
 {
-    struct CeosSARImageDesc *ImageDesc;
-    int	   offset;
-    GByte  *pabyRecord;
     SAR_CEOSDataset *poGDS = (SAR_CEOSDataset *) poDS;
 
-    ImageDesc = &(poGDS->sVolume.ImageDesc);
+    struct CeosSARImageDesc *ImageDesc = &(poGDS->sVolume.ImageDesc);
 
-    offset = ImageDesc->FileDescriptorLength
-        + ImageDesc->BytesPerRecord * nBlockYOff 
+    int offset = ImageDesc->FileDescriptorLength
+        + ImageDesc->BytesPerRecord * nBlockYOff
         + ImageDesc->ImageDataStart;
 
 /* -------------------------------------------------------------------- */
 /*      Load all the pixel data associated with this scanline.          */
 /* -------------------------------------------------------------------- */
-    int	        nBytesToRead = ImageDesc->BytesPerPixel * nBlockXSize;
+    const int nBytesToRead = ImageDesc->BytesPerPixel * nBlockXSize;
+
+    GByte  *pabyRecord = (GByte *) CPLMalloc( nBytesToRead );
 
-    pabyRecord = (GByte *) CPLMalloc( nBytesToRead );
-    
-    if( VSIFSeekL( poGDS->fpImage, offset, SEEK_SET ) != 0 
-        || (int) VSIFReadL( pabyRecord, 1, nBytesToRead, 
+    if( VSIFSeekL( poGDS->fpImage, offset, SEEK_SET ) != 0
+        || (int) VSIFReadL( pabyRecord, 1, nBytesToRead,
                            poGDS->fpImage ) != nBytesToRead )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   "Error reading %d bytes of CEOS record data at offset %d.\n"
-                  "Reading file %s failed.", 
+                  "Reading file %s failed.",
                   nBytesToRead, offset, poGDS->GetDescription() );
         CPLFree( pabyRecord );
         return CE_Failure;
@@ -560,21 +543,21 @@ CPLErr PALSARRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
         // we need to pre-initialize things to set the imaginary component to 0
         memset( pImage, 0, nBlockXSize * 4 );
 
-        GDALCopyWords( pabyRecord + 4*(nBand - 1), GDT_Int16, 18, 
-                       pImage, GDT_Int16, 4, 
+        GDALCopyWords( pabyRecord + 4*(nBand - 1), GDT_Int16, 18,
+                       pImage, GDT_Int16, 4,
                        nBlockXSize );
 #ifdef CPL_LSB
         GDALSwapWords( pImage, 2, nBlockXSize, 4 );
-#endif        
+#endif
     }
     else
     {
-        GDALCopyWords( pabyRecord + 6 + 4*(nBand - 4), GDT_CInt16, 18, 
-                       pImage, GDT_CInt16, 4, 
+        GDALCopyWords( pabyRecord + 6 + 4*(nBand - 4), GDT_CInt16, 18,
+                       pImage, GDT_CInt16, 4,
                        nBlockXSize );
 #ifdef CPL_LSB
         GDALSwapWords( pImage, 2, nBlockXSize*2, 2 );
-#endif        
+#endif
     }
     CPLFree( pabyRecord );
 
@@ -582,54 +565,51 @@ CPLErr PALSARRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /*      Convert the values into covariance form as per:                 */
 /* -------------------------------------------------------------------- */
 /*
-** 1) PALSAR- adjust so that it reads bands as a covariance matrix, and 
+** 1) PALSAR- adjust so that it reads bands as a covariance matrix, and
 ** set polarimetric interpretation accordingly:
 **
 ** Covariance_11=HH*conj(HH): already there
 ** Covariance_22=2*HV*conj(HV): need a factor of 2
-** Covariance_33=VV*conj(VV): already there 
+** Covariance_33=VV*conj(VV): already there
 ** Covariance_12=sqrt(2)*HH*conj(HV): need the sqrt(2) factor
 ** Covariance_13=HH*conj(VV): already there
-** Covariance_23=sqrt(2)*HV*conj(VV): need to take the conjugate, then 
+** Covariance_23=sqrt(2)*HV*conj(VV): need to take the conjugate, then
 **               multiply by sqrt(2)
 **
 */
 
     if( nBand == 2 )
     {
-        int i;
         GInt16 *panLine = (GInt16 *) pImage;
-        
-        for( i = 0; i < nBlockXSize * 2; i++ )
+
+        for( int i = 0; i < nBlockXSize * 2; i++ )
         {
           panLine[i] = (GInt16) CastToGInt16((float)2.0 * panLine[i]);
         }
     }
     else if( nBand == 4 )
     {
-        int i;
-        double sqrt_2 = pow(2.0,0.5);
+        const double sqrt_2 = pow(2.0,0.5);
         GInt16 *panLine = (GInt16 *) pImage;
-        
-        for( i = 0; i < nBlockXSize * 2; i++ )
+
+        for( int i = 0; i < nBlockXSize * 2; i++ )
         {
           panLine[i] = (GInt16) CastToGInt16((float)floor(panLine[i] * sqrt_2 + 0.5));
         }
     }
     else if( nBand == 6 )
     {
-        int i;
         GInt16 *panLine = (GInt16 *) pImage;
-        double sqrt_2 = pow(2.0,0.5);
-        
+        const double sqrt_2 = pow(2.0,0.5);
+
         // real portion - just multiple by sqrt(2)
-        for( i = 0; i < nBlockXSize * 2; i += 2 )
+        for( int i = 0; i < nBlockXSize * 2; i += 2 )
         {
           panLine[i] = (GInt16) CastToGInt16((float)floor(panLine[i] * sqrt_2 + 0.5));
         }
 
         // imaginary portion - conjugate and multiply
-        for( i = 1; i < nBlockXSize * 2; i += 2 )
+        for( int i = 1; i < nBlockXSize * 2; i += 2 )
         {
           panLine[i] = (GInt16) CastToGInt16((float)floor(-panLine[i] * sqrt_2 + 0.5));
         }
@@ -648,14 +628,45 @@ CPLErr PALSARRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /*                          SAR_CEOSDataset()                           */
 /************************************************************************/
 
-SAR_CEOSDataset::SAR_CEOSDataset()
-
+SAR_CEOSDataset::SAR_CEOSDataset() :
+    fpImage(NULL),
+    papszTempMD(NULL),
+    nGCPCount(0),
+    pasGCPList(NULL)
 {
-    fpImage = NULL;
-    nGCPCount = 0;
-    pasGCPList = NULL;
-
-    papszTempMD = NULL;
+    sVolume.Flavour = 0;
+    sVolume.Sensor = 0;
+    sVolume.ProductType = 0;
+    sVolume.FileNamingConvention = 0;
+
+    sVolume.VolumeDirectoryFile = 0;
+    sVolume.SARLeaderFile = 0;
+    sVolume.ImagryOptionsFile = 0;
+    sVolume.SARTrailerFile = 0;
+    sVolume.NullVolumeDirectoryFile = 0;
+
+    sVolume.ImageDesc.ImageDescValid = 0;
+    sVolume.ImageDesc.NumChannels = 0;
+    sVolume.ImageDesc.ChannelInterleaving = 0;
+    sVolume.ImageDesc.DataType = 0;
+    sVolume.ImageDesc.BytesPerRecord = 0;
+    sVolume.ImageDesc.Lines = 0;
+    sVolume.ImageDesc.TopBorderPixels = 0;
+    sVolume.ImageDesc.BottomBorderPixels = 0;
+    sVolume.ImageDesc.PixelsPerLine = 0;
+    sVolume.ImageDesc.LeftBorderPixels = 0;
+    sVolume.ImageDesc.RightBorderPixels = 0;
+    sVolume.ImageDesc.BytesPerPixel = 0;
+    sVolume.ImageDesc.RecordsPerLine = 0;
+    sVolume.ImageDesc.PixelsPerRecord = 0;
+    sVolume.ImageDesc.ImageDataStart = 0;
+    sVolume.ImageDesc.ImageSuffixData = 0;
+    sVolume.ImageDesc.FileDescriptorLength = 0;
+    sVolume.ImageDesc.PixelOrder = 0;
+    sVolume.ImageDesc.LineOrder = 0;
+    sVolume.ImageDesc.PixelDataBytesPerRecord = 0;
+
+    sVolume.RecordList = NULL;
 }
 
 /************************************************************************/
@@ -670,7 +681,7 @@ SAR_CEOSDataset::~SAR_CEOSDataset()
     CSLDestroy( papszTempMD );
 
     if( fpImage != NULL )
-        VSIFCloseL( fpImage );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fpImage ));
 
     if( nGCPCount > 0 )
     {
@@ -680,9 +691,9 @@ SAR_CEOSDataset::~SAR_CEOSDataset()
 
     if( sVolume.RecordList )
     {
-        Link_t	*Links;
-
-        for(Links = sVolume.RecordList; Links != NULL; Links = Links->next)
+        for(Link_t *Links = sVolume.RecordList;
+            Links != NULL;
+            Links = Links->next)
         {
             if(Links->object)
             {
@@ -714,8 +725,8 @@ const char *SAR_CEOSDataset::GetGCPProjection()
 {
     if( nGCPCount > 0 )
         return SRS_WKT_WGS84;
-    else
-        return "";
+
+    return "";
 }
 
 /************************************************************************/
@@ -754,40 +765,40 @@ char **SAR_CEOSDataset::GetMetadataDomainList()
 /*        :r - The zero based record number to fetch (optional)         */
 /*                                                                      */
 /*      Note that only records that are pre-loaded will be              */
-/*      accessable, and this normally means that most image records     */
+/*      accessible, and this normally means that most image records     */
 /*      are not available.                                              */
 /************************************************************************/
 
 char **SAR_CEOSDataset::GetMetadata( const char * pszDomain )
 
 {
-    if( pszDomain == NULL || !EQUALN(pszDomain,"ceos-",5) )
+    if( pszDomain == NULL || !STARTS_WITH_CI(pszDomain, "ceos-") )
         return GDALDataset::GetMetadata( pszDomain );
 
 /* -------------------------------------------------------------------- */
 /*      Identify which file to fetch the file from.                     */
 /* -------------------------------------------------------------------- */
-    int	nFileId = -1;
-    
-    if( EQUALN(pszDomain,"ceos-vol",8) )
+    int nFileId = -1;
+
+    if( STARTS_WITH_CI(pszDomain, "ceos-vol") )
     {
-        nFileId = __CEOS_VOLUME_DIR_FILE;
+        nFileId = CEOS_VOLUME_DIR_FILE;
     }
-    else if( EQUALN(pszDomain,"ceos-lea",8) )
+    else if( STARTS_WITH_CI(pszDomain, "ceos-lea") )
     {
-        nFileId = __CEOS_LEADER_FILE;
+        nFileId = CEOS_LEADER_FILE;
     }
-    else if( EQUALN(pszDomain,"ceos-img",8) )
+    else if( STARTS_WITH_CI(pszDomain, "ceos-img") )
     {
-        nFileId = __CEOS_IMAGRY_OPT_FILE;
+        nFileId = CEOS_IMAGRY_OPT_FILE;
     }
-    else if( EQUALN(pszDomain,"ceos-trl",8) )
+    else if( STARTS_WITH_CI(pszDomain, "ceos-trl") )
     {
-        nFileId = __CEOS_TRAILER_FILE;
+        nFileId = CEOS_TRAILER_FILE;
     }
-    else if( EQUALN(pszDomain,"ceos-nul",8) )
+    else if( STARTS_WITH_CI(pszDomain, "ceos-nul") )
     {
-        nFileId = __CEOS_NULL_VOL_FILE;
+        nFileId = CEOS_NULL_VOL_FILE;
     }
     else
         return NULL;
@@ -797,25 +808,24 @@ char **SAR_CEOSDataset::GetMetadata( const char * pszDomain )
 /* -------------------------------------------------------------------- */
 /*      Identify the record type.                                       */
 /* -------------------------------------------------------------------- */
-    CeosTypeCode_t sTypeCode;
     int  a, b, c, d, nRecordIndex = -1;
 
-    if( sscanf( pszDomain, "-%d-%d-%d-%d:%d", 
-                &a, &b, &c, &d, &nRecordIndex ) != 5 
-        && sscanf( pszDomain, "-%d-%d-%d-%d", 
+    if( sscanf( pszDomain, "-%d-%d-%d-%d:%d",
+                &a, &b, &c, &d, &nRecordIndex ) != 5
+        && sscanf( pszDomain, "-%d-%d-%d-%d",
                    &a, &b, &c, &d ) != 4 )
     {
         return NULL;
     }
 
-    sTypeCode = QuadToTC( a, b, c, d );
+    CeosTypeCode_t sTypeCode = QuadToTC( a, b, c, d );
 
 /* -------------------------------------------------------------------- */
 /*      Try to fetch the record.                                        */
 /* -------------------------------------------------------------------- */
     CeosRecord_t *record;
 
-    record = FindCeosRecord( sVolume.RecordList, sTypeCode, nFileId, 
+    record = FindCeosRecord( sVolume.RecordList, sTypeCode, nFileId,
                              -1, nRecordIndex );
 
     if( record == NULL )
@@ -828,15 +838,13 @@ char **SAR_CEOSDataset::GetMetadata( const char * pszDomain )
 /*      chars, double quotes, and backslashes.                          */
 /*      just turn zero bytes into spaces.                               */
 /* -------------------------------------------------------------------- */
-    char *pszSafeCopy;
-    int  i;
 
     CSLDestroy( papszTempMD );
 
     // Escaped version
-    pszSafeCopy = CPLEscapeString( (char *) record->Buffer, 
-                                   record->Length, 
-                                   CPLES_BackslashQuotable );
+    char *pszSafeCopy = CPLEscapeString( (char *) record->Buffer,
+                                         record->Length,
+                                         CPLES_BackslashQuotable );
     papszTempMD = CSLSetNameValue( NULL, "EscapedRecord", pszSafeCopy );
     CPLFree( pszSafeCopy );
 
@@ -845,11 +853,11 @@ char **SAR_CEOSDataset::GetMetadata( const char * pszDomain )
 
     pszSafeCopy = (char *) CPLCalloc(1,record->Length+1);
     memcpy( pszSafeCopy, record->Buffer, record->Length );
-    
-    for( i = 0; i < record->Length; i++ )
+
+    for( int i = 0; i < record->Length; i++ )
         if( pszSafeCopy[i] == '\0' )
             pszSafeCopy[i] = ' ';
-        
+
     papszTempMD = CSLSetNameValue( papszTempMD, "RawRecord", pszSafeCopy );
 
     CPLFree( pszSafeCopy );
@@ -861,18 +869,20 @@ char **SAR_CEOSDataset::GetMetadata( const char * pszDomain )
 /*                          ScanForMetadata()                           */
 /************************************************************************/
 
-void SAR_CEOSDataset::ScanForMetadata() 
+void SAR_CEOSDataset::ScanForMetadata()
 
 {
-    char szField[128], szVolId[128];
-    CeosRecord_t *record;
-
 /* -------------------------------------------------------------------- */
 /*      Get the volume id (with the sensor name)                        */
 /* -------------------------------------------------------------------- */
-    record = FindCeosRecord( sVolume.RecordList, VOLUME_DESCRIPTOR_RECORD_TC,
-                             __CEOS_VOLUME_DIR_FILE, -1, -1 );
+    CeosRecord_t *record
+        = FindCeosRecord( sVolume.RecordList, VOLUME_DESCRIPTOR_RECORD_TC,
+                          CEOS_VOLUME_DIR_FILE, -1, -1 );
+
+    char szVolId[128];
     szVolId[0] = '\0';
+    char szField[128];
+    szField[0] = '\0';
     if( record != NULL )
     {
         szVolId[16] = '\0';
@@ -889,7 +899,7 @@ void SAR_CEOSDataset::ScanForMetadata()
 
         GetCeosField( record, 149, "A12", szField );
 
-        if( !EQUALN(szField,"            ",12) )
+        if( !STARTS_WITH_CI(szField, "            ") )
             SetMetadataItem( "CEOS_PROCESSING_FACILITY", szField );
 
 /* -------------------------------------------------------------------- */
@@ -899,7 +909,7 @@ void SAR_CEOSDataset::ScanForMetadata()
 
         GetCeosField( record, 141, "A8", szField );
 
-        if( !EQUALN(szField,"            ",8) )
+        if( !STARTS_WITH_CI(szField, "            ") )
             SetMetadataItem( "CEOS_PROCESSING_AGENCY", szField );
 
 /* -------------------------------------------------------------------- */
@@ -909,7 +919,7 @@ void SAR_CEOSDataset::ScanForMetadata()
 
         GetCeosField( record, 129, "A12", szField );
 
-        if( !EQUALN(szField,"            ",12) )
+        if( !STARTS_WITH_CI(szField, "            ") )
             SetMetadataItem( "CEOS_PROCESSING_COUNTRY", szField );
 
 /* -------------------------------------------------------------------- */
@@ -919,7 +929,7 @@ void SAR_CEOSDataset::ScanForMetadata()
 
         GetCeosField( record, 33, "A12", szField );
 
-        if( !EQUALN(szField,"            ",12) )
+        if( !STARTS_WITH_CI(szField, "            ") )
             SetMetadataItem( "CEOS_SOFTWARE_ID", szField );
 
 /* -------------------------------------------------------------------- */
@@ -929,9 +939,9 @@ void SAR_CEOSDataset::ScanForMetadata()
 
         GetCeosField( record, 261, "A8", szField );
 
-        if( !EQUALN(szField,"        ",8) )
+        if( !STARTS_WITH_CI(szField, "        ") )
             SetMetadataItem( "CEOS_PRODUCT_ID", szField );
-    
+
 /* -------------------------------------------------------------------- */
 /*      volume identifier.                                                    */
 /* -------------------------------------------------------------------- */
@@ -939,7 +949,7 @@ void SAR_CEOSDataset::ScanForMetadata()
 
         GetCeosField( record, 77, "A16", szField );
 
-        if( !EQUALN(szField,"                ",16) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_VOLSET_ID", szField );
     }
 
@@ -947,16 +957,16 @@ void SAR_CEOSDataset::ScanForMetadata()
 /*      Dataset summary record.                                         */
 /* ==================================================================== */
     record = FindCeosRecord( sVolume.RecordList, LEADER_DATASET_SUMMARY_TC,
-                             __CEOS_LEADER_FILE, -1, -1 );
+                             CEOS_LEADER_FILE, -1, -1 );
 
     if( record == NULL )
         record = FindCeosRecord( sVolume.RecordList, LEADER_DATASET_SUMMARY_TC,
-                                 __CEOS_TRAILER_FILE, -1, -1 );
+                                 CEOS_TRAILER_FILE, -1, -1 );
 
     if( record == NULL )
-        record = FindCeosRecord( sVolume.RecordList, 
+        record = FindCeosRecord( sVolume.RecordList,
                                  LEADER_DATASET_SUMMARY_ERS2_TC,
-                                 __CEOS_LEADER_FILE, -1, -1 );
+                                 CEOS_LEADER_FILE, -1, -1 );
 
     if( record != NULL )
     {
@@ -976,8 +986,8 @@ void SAR_CEOSDataset::ScanForMetadata()
         GetCeosField( record, 101, "A16", szField );
         szField[16] = '\0';
 
-        if( strstr(szVolId,"RSAT") != NULL 
-            && !EQUALN(szField,"                ",16 ) )
+        if( strstr(szVolId,"RSAT") != NULL
+            && !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_ASC_DES", szField );
 
 /* -------------------------------------------------------------------- */
@@ -986,7 +996,7 @@ void SAR_CEOSDataset::ScanForMetadata()
         GetCeosField( record, 149, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ",16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_TRUE_HEADING", szField );
 
 /* -------------------------------------------------------------------- */
@@ -995,7 +1005,7 @@ void SAR_CEOSDataset::ScanForMetadata()
         GetCeosField( record, 165, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ",16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_ELLIPSOID", szField );
 
 /* -------------------------------------------------------------------- */
@@ -1004,13 +1014,13 @@ void SAR_CEOSDataset::ScanForMetadata()
         GetCeosField( record, 181, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ",16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_SEMI_MAJOR", szField );
 
         GetCeosField( record, 197, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ",16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_SEMI_MINOR", szField );
 
 /* -------------------------------------------------------------------- */
@@ -1019,7 +1029,7 @@ void SAR_CEOSDataset::ScanForMetadata()
         GetCeosField( record, 341, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ",16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_SCENE_LENGTH_KM", szField );
 
 /* -------------------------------------------------------------------- */
@@ -1028,7 +1038,7 @@ void SAR_CEOSDataset::ScanForMetadata()
         GetCeosField( record, 357, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ",16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_SCENE_WIDTH_KM", szField );
 
 /* -------------------------------------------------------------------- */
@@ -1037,7 +1047,7 @@ void SAR_CEOSDataset::ScanForMetadata()
         GetCeosField( record, 397, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ",16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_MISSION_ID", szField );
 
 /* -------------------------------------------------------------------- */
@@ -1046,7 +1056,7 @@ void SAR_CEOSDataset::ScanForMetadata()
         GetCeosField( record, 413, "A32", szField );
         szField[32] = '\0';
 
-        if( !EQUALN(szField,"                                ",32 ) )
+        if( !STARTS_WITH_CI(szField, "                                ") )
             SetMetadataItem( "CEOS_SENSOR_ID", szField );
 
 
@@ -1056,7 +1066,7 @@ void SAR_CEOSDataset::ScanForMetadata()
         GetCeosField( record, 445, "A8", szField );
         szField[8] = '\0';
 
-        if( !EQUALN(szField,"        ",8 ) )
+        if( !STARTS_WITH_CI(szField, "        ") )
             SetMetadataItem( "CEOS_ORBIT_NUMBER", szField );
 
 
@@ -1066,7 +1076,7 @@ void SAR_CEOSDataset::ScanForMetadata()
         GetCeosField( record, 453, "A8", szField );
         szField[8] = '\0';
 
-        if( !EQUALN(szField,"        ",8 ) )
+        if( !STARTS_WITH_CI(szField, "        ") )
             SetMetadataItem( "CEOS_PLATFORM_LATITUDE", szField );
 
 /* -------------------------------------------------------------------- */
@@ -1075,7 +1085,7 @@ void SAR_CEOSDataset::ScanForMetadata()
         GetCeosField( record, 461, "A8", szField );
         szField[8] = '\0';
 
-        if( !EQUALN(szField,"        ",8 ) )
+        if( !STARTS_WITH_CI(szField, "        ") )
             SetMetadataItem( "CEOS_PLATFORM_LONGITUDE", szField );
 
 /* -------------------------------------------------------------------- */
@@ -1084,7 +1094,7 @@ void SAR_CEOSDataset::ScanForMetadata()
         GetCeosField( record, 469, "A8", szField );
         szField[8] = '\0';
 
-        if( !EQUALN(szField,"                ",8 ) )
+        if( !STARTS_WITH_CI(szField, "        ") )
             SetMetadataItem( "CEOS_PLATFORM_HEADING", szField );
 
 /* -------------------------------------------------------------------- */
@@ -1093,7 +1103,7 @@ void SAR_CEOSDataset::ScanForMetadata()
         GetCeosField( record, 477, "A8", szField );
         szField[8] = '\0';
 
-        if( !EQUALN(szField,"        ",8 ) )
+        if( !STARTS_WITH_CI(szField, "        ") )
             SetMetadataItem( "CEOS_SENSOR_CLOCK_ANGLE", szField );
 
 /* -------------------------------------------------------------------- */
@@ -1102,7 +1112,7 @@ void SAR_CEOSDataset::ScanForMetadata()
         GetCeosField( record, 485, "A8", szField );
         szField[8] = '\0';
 
-        if( !EQUALN(szField,"        ",8 ) )
+        if( !STARTS_WITH_CI(szField, "        ") )
             SetMetadataItem( "CEOS_INC_ANGLE", szField );
 
 /* -------------------------------------------------------------------- */
@@ -1111,7 +1121,7 @@ void SAR_CEOSDataset::ScanForMetadata()
         GetCeosField( record, 1527, "A8", szField );
         szField[8] = '\0';
 
-        if( !EQUALN(szField,"                ",8 ) )
+        if( !STARTS_WITH_CI(szField, "        ") )
             SetMetadataItem( "CEOS_PIXEL_TIME_DIR", szField );
 
 /* -------------------------------------------------------------------- */
@@ -1120,7 +1130,7 @@ void SAR_CEOSDataset::ScanForMetadata()
         GetCeosField( record, 1687, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ",16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_LINE_SPACING_METERS", szField );
 /* -------------------------------------------------------------------- */
 /*      Pixel spacing                                                    */
@@ -1128,7 +1138,7 @@ void SAR_CEOSDataset::ScanForMetadata()
         GetCeosField( record, 1703, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ",16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_PIXEL_SPACING_METERS", szField );
 
     }
@@ -1136,9 +1146,9 @@ void SAR_CEOSDataset::ScanForMetadata()
 /* -------------------------------------------------------------------- */
 /*      Get the beam mode, for radarsat.                                */
 /* -------------------------------------------------------------------- */
-    record = FindCeosRecord( sVolume.RecordList, 
+    record = FindCeosRecord( sVolume.RecordList,
                              LEADER_RADIOMETRIC_COMPENSATION_TC,
-                             __CEOS_LEADER_FILE, -1, -1 );
+                             CEOS_LEADER_FILE, -1, -1 );
 
     if( strstr(szVolId,"RSAT") != NULL && record != NULL )
     {
@@ -1153,15 +1163,15 @@ void SAR_CEOSDataset::ScanForMetadata()
 /*      ERS calibration and incidence angle info                        */
 /* ==================================================================== */
     record = FindCeosRecord( sVolume.RecordList, ERS_GENERAL_FACILITY_DATA_TC,
-                             __CEOS_LEADER_FILE, -1, -1 );
+                             CEOS_LEADER_FILE, -1, -1 );
 
     if( record == NULL )
-        record = FindCeosRecord( sVolume.RecordList, 
+        record = FindCeosRecord( sVolume.RecordList,
                                  ERS_GENERAL_FACILITY_DATA_ALT_TC,
-                                 __CEOS_LEADER_FILE, -1, -1 );
+                                 CEOS_LEADER_FILE, -1, -1 );
 
     if( record != NULL )
-    {   
+    {
         GetCeosField( record, 13 , "A64", szField );
         szField[64] = '\0';
 
@@ -1175,49 +1185,49 @@ void SAR_CEOSDataset::ScanForMetadata()
         GetCeosField( record, 583 , "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ", 16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_INC_ANGLE_FIRST_RANGE", szField );
 
         GetCeosField( record, 599 , "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ", 16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_INC_ANGLE_CENTRE_RANGE", szField );
 
         GetCeosField( record, 615, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ", 16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_INC_ANGLE_LAST_RANGE", szField );
 
         GetCeosField( record, 663, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ", 16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_CALIBRATION_CONSTANT_K", szField );
 
         GetCeosField( record, 1855, "A20", szField );
         szField[20] = '\0';
 
-        if( !EQUALN(szField,"                    ", 20 ) )
+        if( !STARTS_WITH_CI(szField, "                    ") )
             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C0", szField );
 
         GetCeosField( record, 1875, "A20", szField );
         szField[20] = '\0';
 
-        if( !EQUALN(szField,"                    ", 20 ) )
+        if( !STARTS_WITH_CI(szField, "                    ") )
             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C1", szField );
 
         GetCeosField( record, 1895, "A20", szField );
         szField[20] = '\0';
 
-        if( !EQUALN(szField,"                    ", 20 ) )
+        if( !STARTS_WITH_CI(szField, "                    ") )
             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C2", szField );
 
         GetCeosField( record, 1915, "A20", szField );
         szField[20] = '\0';
 
-        if( !EQUALN(szField,"                    ", 20 ) )
+        if( !STARTS_WITH_CI(szField, "                    ") )
             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C3", szField );
 
     }
@@ -1225,114 +1235,114 @@ void SAR_CEOSDataset::ScanForMetadata()
 /*	Detailed Processing Parameters (Radarsat)                       */
 /* -------------------------------------------------------------------- */
     record = FindCeosRecord( sVolume.RecordList, RSAT_PROC_PARAM_TC,
-                             __CEOS_LEADER_FILE, -1, -1 );
+                             CEOS_LEADER_FILE, -1, -1 );
 
     if( record == NULL )
         record = FindCeosRecord( sVolume.RecordList, RSAT_PROC_PARAM_TC,
-                             __CEOS_TRAILER_FILE, -1, -1 );
+                             CEOS_TRAILER_FILE, -1, -1 );
 
     if( record != NULL )
     {
         GetCeosField( record, 192, "A21", szField );
         szField[21] = '\0';
 
-        if( !EQUALN(szField,"                     ",21 ) )
+        if( !STARTS_WITH_CI(szField, "                     ") )
             SetMetadataItem( "CEOS_PROC_START", szField );
-            
+
         GetCeosField( record, 213, "A21", szField );
         szField[21] = '\0';
 
-        if( !EQUALN(szField,"                     ",21 ) )
+        if( !STARTS_WITH_CI(szField, "                     ") )
             SetMetadataItem( "CEOS_PROC_STOP", szField );
-            
+
         GetCeosField( record, 4649, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ",16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_EPH_ORB_DATA_0", szField );
 
         GetCeosField( record, 4665, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ",16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_EPH_ORB_DATA_1", szField );
 
         GetCeosField( record, 4681, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ",16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_EPH_ORB_DATA_2", szField );
 
         GetCeosField( record, 4697, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ",16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_EPH_ORB_DATA_3", szField );
 
         GetCeosField( record, 4713, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ",16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_EPH_ORB_DATA_4", szField );
 
         GetCeosField( record, 4729, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ",16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_EPH_ORB_DATA_5", szField );
 
         GetCeosField( record, 4745, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ",16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_EPH_ORB_DATA_6", szField );
 
         GetCeosField( record, 4908, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ",16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C0", szField );
 
         GetCeosField( record, 4924, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ",16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C1", szField );
 
         GetCeosField( record, 4940, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ",16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C2", szField );
 
         GetCeosField( record, 4956, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ",16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C3", szField );
 
         GetCeosField( record, 4972, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ",16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C4", szField );
 
         GetCeosField( record, 4988, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ",16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C5", szField );
 
         GetCeosField( record, 7334, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ",16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_INC_ANGLE_FIRST_RANGE", szField );
 
         GetCeosField( record, 7350, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ",16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_INC_ANGLE_LAST_RANGE", szField );
 
     }
@@ -1340,72 +1350,72 @@ void SAR_CEOSDataset::ScanForMetadata()
 /*	Get process-to-raw data coordinate translation values.  These	*/
 /*	are likely specific to Atlantis APP products.			*/
 /* -------------------------------------------------------------------- */
-    record = FindCeosRecord( sVolume.RecordList, 
+    record = FindCeosRecord( sVolume.RecordList,
                              IMAGE_HEADER_RECORD_TC,
-                             __CEOS_IMAGRY_OPT_FILE, -1, -1 );
+                             CEOS_IMAGRY_OPT_FILE, -1, -1 );
 
     if( record != NULL )
     {
         GetCeosField( record, 449, "A4", szField );
         szField[4] = '\0';
 
-        if( !EQUALN(szField,"    ",4 ) )
+        if( !STARTS_WITH_CI(szField, "    ") )
             SetMetadataItem( "CEOS_DM_CORNER", szField );
 
 
         GetCeosField( record, 453, "A4", szField );
         szField[4] = '\0';
 
-        if( !EQUALN(szField,"    ",4 ) )
+        if( !STARTS_WITH_CI(szField, "    ") )
             SetMetadataItem( "CEOS_DM_TRANSPOSE", szField );
 
 
         GetCeosField( record, 457, "A4", szField );
         szField[4] = '\0';
 
-        if( !EQUALN(szField,"    ",4 ) )
+        if( !STARTS_WITH_CI(szField, "    ") )
             SetMetadataItem( "CEOS_DM_START_SAMPLE", szField );
 
 
         GetCeosField( record, 461, "A5", szField );
         szField[5] = '\0';
 
-        if( !EQUALN(szField,"     ",5 ) )
+        if( !STARTS_WITH_CI(szField, "     ") )
             SetMetadataItem( "CEOS_DM_START_PULSE", szField );
 
 
         GetCeosField( record, 466, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ", 16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_DM_FAST_ALPHA", szField );
 
 
         GetCeosField( record, 482, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ", 16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_DM_FAST_BETA", szField );
 
 
         GetCeosField( record, 498, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ", 16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_DM_SLOW_ALPHA", szField );
 
 
         GetCeosField( record, 514, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ", 16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_DM_SLOW_BETA", szField );
 
 
         GetCeosField( record, 530, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ", 16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_DM_FAST_ALPHA_2", szField );
 
     }
@@ -1414,21 +1424,21 @@ void SAR_CEOSDataset::ScanForMetadata()
 /*      Try to find calibration information from Radiometric Data       */
 /*      Record.                                                         */
 /* -------------------------------------------------------------------- */
-    record = FindCeosRecord( sVolume.RecordList, 
+    record = FindCeosRecord( sVolume.RecordList,
                              LEADER_RADIOMETRIC_DATA_RECORD_TC,
-                             __CEOS_LEADER_FILE, -1, -1 );
+                             CEOS_LEADER_FILE, -1, -1 );
 
     if( record == NULL )
-        record = FindCeosRecord( sVolume.RecordList, 
+        record = FindCeosRecord( sVolume.RecordList,
                              LEADER_RADIOMETRIC_DATA_RECORD_TC,
-                             __CEOS_TRAILER_FILE, -1, -1 );
+                             CEOS_TRAILER_FILE, -1, -1 );
 
     if( record != NULL )
     {
         GetCeosField( record, 8317, "A16", szField );
         szField[16] = '\0';
 
-        if( !EQUALN(szField,"                ", 16 ) )
+        if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_CALIBRATION_OFFSET", szField );
     }
 
@@ -1437,21 +1447,21 @@ void SAR_CEOSDataset::ScanForMetadata()
 /*      calibration offset and gain from the Radiometric Ancillary      */
 /*      Record.                                                         */
 /* -------------------------------------------------------------------- */
-    record = FindCeosRecord( sVolume.RecordList, 
+    record = FindCeosRecord( sVolume.RecordList,
                              QuadToTC( 0x3f, 0x24, 0x12, 0x09 ),
-                             __CEOS_LEADER_FILE, -1, -1 );
+                             CEOS_LEADER_FILE, -1, -1 );
     if( record != NULL )
     {
         GetCeosField( record, 29, "A20", szField );
         szField[20] = '\0';
 
-        if( !EQUALN(szField,"                    ", 20 ) )
+        if( !STARTS_WITH_CI(szField, "                    ") )
             SetMetadataItem( "CEOS_OFFSET_A0", szField );
 
         GetCeosField( record, 49, "A20", szField );
         szField[20] = '\0';
 
-        if( !EQUALN(szField,"                    ", 20 ) )
+        if( !STARTS_WITH_CI(szField, "                    ") )
             SetMetadataItem( "CEOS_GAIN_A1", szField );
     }
 
@@ -1459,9 +1469,9 @@ void SAR_CEOSDataset::ScanForMetadata()
 /*      For ERS Standard Format Landsat scenes we pick up the           */
 /*      gain setting from the Scene Header Record.			*/
 /* -------------------------------------------------------------------- */
-    record = FindCeosRecord( sVolume.RecordList, 
+    record = FindCeosRecord( sVolume.RecordList,
                              QuadToTC( 0x12, 0x12, 0x12, 0x09 ),
-                             __CEOS_LEADER_FILE, -1, -1 );
+                             CEOS_LEADER_FILE, -1, -1 );
     if( record != NULL )
     {
         GetCeosField( record, 1486, "A1", szField );
@@ -1482,38 +1492,35 @@ void SAR_CEOSDataset::ScanForMetadata()
 int SAR_CEOSDataset::ScanForMapProjection()
 
 {
-    CeosRecord_t *record;
-    char	 szField[100];
-    int          i;
-
 /* -------------------------------------------------------------------- */
 /*      Find record, and try to determine if it has useful GCPs.        */
 /* -------------------------------------------------------------------- */
 
-    record = FindCeosRecord( sVolume.RecordList, 
-                             LEADER_MAP_PROJ_RECORD_TC,
-                             __CEOS_LEADER_FILE, -1, -1 );
+    CeosRecord_t *record = FindCeosRecord( sVolume.RecordList,
+                                           LEADER_MAP_PROJ_RECORD_TC,
+                                           CEOS_LEADER_FILE, -1, -1 );
 
     /* JERS from Japan */
     if( record == NULL )
-        record = FindCeosRecord( sVolume.RecordList, 
+        record = FindCeosRecord( sVolume.RecordList,
                              LEADER_MAP_PROJ_RECORD_JERS_TC,
-                             __CEOS_LEADER_FILE, -1, -1 );
+                             CEOS_LEADER_FILE, -1, -1 );
 
     if( record == NULL )
         return FALSE;
 
+    char szField[100];
     memset( szField, 0, 17 );
     GetCeosField( record, 29, "A16", szField );
 
-    if( !EQUALN(szField,"Slant Range",11) && !EQUALN(szField,"Ground Range",12) 
-        && !EQUALN(szField,"GEOCODED",8) )
+    if( !STARTS_WITH_CI(szField, "Slant Range") && !STARTS_WITH_CI(szField, "Ground Range")
+        && !STARTS_WITH_CI(szField, "GEOCODED") )
         return FALSE;
 
     GetCeosField( record, 1073, "A16", szField );
-    if( EQUALN(szField,"        ",8) )
+    if( STARTS_WITH_CI(szField, "        ") )
         return FALSE;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read corner points.                                             */
 /* -------------------------------------------------------------------- */
@@ -1522,20 +1529,20 @@ int SAR_CEOSDataset::ScanForMapProjection()
 
     GDALInitGCPs( nGCPCount, pasGCPList );
 
-    for( i = 0; i < nGCPCount; i++ )
+    for( int i = 0; i < nGCPCount; i++ )
     {
         char         szId[32];
 
-        sprintf( szId, "%d", i+1 );
+        snprintf( szId, sizeof(szId), "%d", i+1 );
         pasGCPList[i].pszId = CPLStrdup( szId );
-    
+
         GetCeosField( record, 1073+32*i, "A16", szField );
         pasGCPList[i].dfGCPY = CPLAtof(szField);
         GetCeosField( record, 1089+32*i, "A16", szField );
         pasGCPList[i].dfGCPX = CPLAtof(szField);
         pasGCPList[i].dfGCPZ = 0.0;
     }
-    
+
     pasGCPList[0].dfGCPLine = 0.5;
     pasGCPList[0].dfGCPPixel = 0.5;
 
@@ -1558,8 +1565,6 @@ int SAR_CEOSDataset::ScanForMapProjection()
 void SAR_CEOSDataset::ScanForGCPs()
 
 {
-    int    iScanline, nStep, nGCPMax = 15;
-
 /* -------------------------------------------------------------------- */
 /*      Do we have a standard 180 bytes of prefix data (192 bytes       */
 /*      including the record marker information)?  If not, it is        */
@@ -1578,44 +1583,41 @@ void SAR_CEOSDataset::ScanForGCPs()
 /*      end of each scanline.                                           */
 /* -------------------------------------------------------------------- */
     nGCPCount = 0;
+    int nGCPMax = 15;
     pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),nGCPMax);
 
-    nStep = (GetRasterYSize()-1) / (nGCPMax / 3 - 1);
-    for( iScanline = 0; iScanline < GetRasterYSize(); iScanline += nStep )
+    int nStep = (GetRasterYSize()-1) / (nGCPMax / 3 - 1);
+    for( int iScanline = 0; iScanline < GetRasterYSize(); iScanline += nStep )
     {
-        int   nFileOffset, iGCP;
-        GInt32 anRecord[192/4];
-
         if( nGCPCount > nGCPMax-3 )
             break;
 
-        CalcCeosSARImageFilePosition( &sVolume, 1, iScanline+1, NULL, 
+        int nFileOffset;
+        CalcCeosSARImageFilePosition( &sVolume, 1, iScanline+1, NULL,
                                       &nFileOffset );
 
-        if( VSIFSeekL( fpImage, nFileOffset, SEEK_SET ) != 0 
+        GInt32 anRecord[192/4];
+        if( VSIFSeekL( fpImage, nFileOffset, SEEK_SET ) != 0
             || VSIFReadL( anRecord, 1, 192, fpImage ) != 192 )
             break;
-        
+
         /* loop over first, middle and last pixel gcps */
 
-        for( iGCP = 0; iGCP < 3; iGCP++ )
+        for( int iGCP = 0; iGCP < 3; iGCP++ )
         {
-            int nLat, nLong;
-
-            nLat  = CPL_MSBWORD32( anRecord[132/4 + iGCP] );
-            nLong = CPL_MSBWORD32( anRecord[144/4 + iGCP] );
+            const int nLat  = CPL_MSBWORD32( anRecord[132/4 + iGCP] );
+            const int nLong = CPL_MSBWORD32( anRecord[144/4 + iGCP] );
 
             if( nLat != 0 || nLong != 0 )
             {
-                char      szId[32];
-
                 GDALInitGCPs( 1, pasGCPList + nGCPCount );
 
                 CPLFree( pasGCPList[nGCPCount].pszId );
 
-                sprintf( szId, "%d", nGCPCount+1 );
+                char szId[32];
+                snprintf( szId, sizeof(szId), "%d", nGCPCount+1 );
                 pasGCPList[nGCPCount].pszId = CPLStrdup( szId );
-                
+
                 pasGCPList[nGCPCount].dfGCPX = nLong / 1000000.0;
                 pasGCPList[nGCPCount].dfGCPY = nLat / 1000000.0;
                 pasGCPList[nGCPCount].dfGCPZ = 0.0;
@@ -1625,17 +1627,17 @@ void SAR_CEOSDataset::ScanForGCPs()
                 if( iGCP == 0 )
                     pasGCPList[nGCPCount].dfGCPPixel = 0.5;
                 else if( iGCP == 1 )
-                    pasGCPList[nGCPCount].dfGCPPixel = 
+                    pasGCPList[nGCPCount].dfGCPPixel =
                         GetRasterXSize() / 2.0;
-                else 
-                    pasGCPList[nGCPCount].dfGCPPixel = 
+                else
+                    pasGCPList[nGCPCount].dfGCPPixel =
                         GetRasterXSize() - 0.5;
 
                 nGCPCount++;
             }
         }
     }
-    /* If general GCP's weren't found, look for Map Projection (eg. JERS) */
+    /* If general GCP's were not found, look for Map Projection (e.g. JERS) */
     if( nGCPCount == 0 )
     {
         ScanForMapProjection();
@@ -1650,12 +1652,10 @@ void SAR_CEOSDataset::ScanForGCPs()
 GDALDataset *SAR_CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    int		i, bNative;
-    
 /* -------------------------------------------------------------------- */
 /*      Does this appear to be a valid ceos leader record?              */
 /* -------------------------------------------------------------------- */
-    if( poOpenInfo->nHeaderBytes < __CEOS_HEADER_LENGTH )
+    if( poOpenInfo->nHeaderBytes < CEOS_HEADER_LENGTH )
         return NULL;
 
     if( (poOpenInfo->pabyHeader[4] != 0x3f
@@ -1670,13 +1670,13 @@ GDALDataset *SAR_CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
     // value appears to be little endian.
     if( poOpenInfo->pabyHeader[0] != 0 )
         return NULL;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The SAR_CEOS driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
@@ -1692,62 +1692,54 @@ GDALDataset *SAR_CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    SAR_CEOSDataset 	*poDS;
-    CeosSARVolume_t     *psVolume;
 
-    poDS = new SAR_CEOSDataset();
-
-    psVolume = &(poDS->sVolume);
+    SAR_CEOSDataset *poDS = new SAR_CEOSDataset();
+    CeosSARVolume_t *psVolume = &(poDS->sVolume);
     InitCeosSARVolume( psVolume, 0 );
 
 /* -------------------------------------------------------------------- */
 /*      Try to read the current file as an imagery file.                */
 /* -------------------------------------------------------------------- */
-    
+
     psVolume->ImagryOptionsFile = TRUE;
-    if( ProcessData( fp, __CEOS_IMAGRY_OPT_FILE, psVolume, 4, -1) != CE_None )
+    if( ProcessData( fp, CEOS_IMAGRY_OPT_FILE, psVolume, 4, VSI_L_OFFSET_MAX) != CE_None )
     {
         delete poDS;
-        VSIFCloseL(fp);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
         return NULL;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Try the various filenames.                                      */
 /* -------------------------------------------------------------------- */
-    char *pszPath;
-    char *pszBasename;
-    char *pszExtension;
-    int  nBand, iFile;
+    char *pszPath = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
+    char *pszBasename = CPLStrdup(CPLGetBasename(poOpenInfo->pszFilename));
+    char *pszExtension = CPLStrdup(CPLGetExtension(poOpenInfo->pszFilename));
 
-    pszPath = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
-    pszBasename = CPLStrdup(CPLGetBasename(poOpenInfo->pszFilename));
-    pszExtension = CPLStrdup(CPLGetExtension(poOpenInfo->pszFilename));
+    int nBand;
     if( strlen(pszBasename) > 4 )
         nBand = atoi( pszBasename + 4 );
     else
         nBand = 0;
 
-    for( iFile = 0; iFile < 5;iFile++ )
+    for( int iFile = 0; iFile < 5;iFile++ )
     {
-        int	e;
-
         /* skip image file ... we already did it */
         if( iFile == 2 )
             continue;
 
-        e = 0;
+        int e = 0;
         while( CeosExtension[e][iFile] != NULL )
         {
-            VSILFILE	*process_fp;
             char *pszFilename = NULL;
-            
+
             /* build filename */
             if( EQUAL(CeosExtension[e][5],"base") )
             {
                 char    szMadeBasename[32];
 
-                sprintf( szMadeBasename, CeosExtension[e][iFile], nBand );
+                snprintf( szMadeBasename, sizeof(szMadeBasename),
+                          CeosExtension[e][iFile], nBand );
                 pszFilename = CPLStrdup(
                     CPLFormFilename(pszPath,szMadeBasename, pszExtension));
             }
@@ -1762,18 +1754,18 @@ GDALDataset *SAR_CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
                 pszFilename = CPLStrdup(
                     CPLFormFilename(pszPath,CeosExtension[e][iFile],""));
             }
-            
+
             // This is for SAR SLC as per the SAR Toolbox (from ASF).
             else if( EQUAL(CeosExtension[e][5],"ext2") )
             {
                 char szThisExtension[32];
 
                 if( strlen(pszExtension) > 3 )
-                    sprintf( szThisExtension, "%s%s", 
-                             CeosExtension[e][iFile], 
+                    snprintf( szThisExtension, sizeof(szThisExtension), "%s%s",
+                             CeosExtension[e][iFile],
                              pszExtension+3 );
                 else
-                    sprintf( szThisExtension, "%s", 
+                    snprintf( szThisExtension, sizeof(szThisExtension), "%s",
                              CeosExtension[e][iFile] );
 
                 pszFilename = CPLStrdup(
@@ -1781,16 +1773,16 @@ GDALDataset *SAR_CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
             }
 
             CPLAssert( pszFilename != NULL );
-            if( pszFilename == NULL ) 
+            if( pszFilename == NULL )
                 return NULL;
- 
+
             /* try to open */
-            process_fp = VSIFOpenL( pszFilename, "rb" );
+            VSILFILE *process_fp = VSIFOpenL( pszFilename, "rb" );
 
             /* try upper case */
             if( process_fp == NULL )
             {
-                for( i = strlen(pszFilename)-1; 
+                for( int i = static_cast<int>(strlen(pszFilename))-1;
                      i >= 0 && pszFilename[i] != '/' && pszFilename[i] != '\\';
                      i-- )
                 {
@@ -1805,8 +1797,8 @@ GDALDataset *SAR_CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
             {
                 CPLDebug( "CEOS", "Opened %s.\n", pszFilename );
 
-                VSIFSeekL( process_fp, 0, SEEK_END );
-                if( ProcessData( process_fp, iFile, psVolume, -1, 
+                CPL_IGNORE_RET_VAL(VSIFSeekL( process_fp, 0, SEEK_END ));
+                if( ProcessData( process_fp, iFile, psVolume, -1,
                                  VSIFTellL( process_fp ) ) == 0 )
                 {
                     switch( iFile )
@@ -1821,12 +1813,12 @@ GDALDataset *SAR_CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
                         break;
                     }
 
-                    VSIFCloseL( process_fp );
+                    CPL_IGNORE_RET_VAL(VSIFCloseL( process_fp ));
                     CPLFree( pszFilename );
                     break; /* Exit the while loop, we have this data type*/
                 }
-                    
-                VSIFCloseL( process_fp );
+
+                CPL_IGNORE_RET_VAL(VSIFCloseL( process_fp ));
             }
 
             CPLFree( pszFilename );
@@ -1842,19 +1834,18 @@ GDALDataset *SAR_CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Check that we have an image description.                        */
 /* -------------------------------------------------------------------- */
-    struct CeosSARImageDesc   *psImageDesc;
     GetCeosSARImageDesc( psVolume );
-    psImageDesc = &(psVolume->ImageDesc);
+    struct CeosSARImageDesc *psImageDesc = &(psVolume->ImageDesc);
     if( !psImageDesc->ImageDescValid )
     {
         delete poDS;
 
-        CPLDebug( "CEOS", 
+        CPLDebug( "CEOS",
                   "Unable to extract CEOS image description\n"
-                  "from %s.", 
+                  "from %s.",
                   poOpenInfo->pszFilename );
 
-        VSIFCloseL(fp);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
 
         return NULL;
     }
@@ -1866,73 +1857,75 @@ GDALDataset *SAR_CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
 
     switch( psImageDesc->DataType )
     {
-      case __CEOS_TYP_CHAR:
-      case __CEOS_TYP_UCHAR:
+      case CEOS_TYP_CHAR:
+      case CEOS_TYP_UCHAR:
         eType = GDT_Byte;
         break;
 
-      case __CEOS_TYP_SHORT:
+      case CEOS_TYP_SHORT:
         eType = GDT_Int16;
         break;
 
-      case __CEOS_TYP_COMPLEX_SHORT:
-      case __CEOS_TYP_PALSAR_COMPLEX_SHORT:
+      case CEOS_TYP_COMPLEX_SHORT:
+      case CEOS_TYP_PALSAR_COMPLEX_SHORT:
         eType = GDT_CInt16;
         break;
 
-      case __CEOS_TYP_USHORT:
+      case CEOS_TYP_USHORT:
         eType = GDT_UInt16;
         break;
 
-      case __CEOS_TYP_LONG:
+      case CEOS_TYP_LONG:
         eType = GDT_Int32;
         break;
 
-      case __CEOS_TYP_ULONG:
+      case CEOS_TYP_ULONG:
         eType = GDT_UInt32;
         break;
 
-      case __CEOS_TYP_FLOAT:
+      case CEOS_TYP_FLOAT:
         eType = GDT_Float32;
         break;
 
-      case __CEOS_TYP_DOUBLE:
+      case CEOS_TYP_DOUBLE:
         eType = GDT_Float64;
         break;
 
-      case __CEOS_TYP_COMPLEX_FLOAT:
-      case __CEOS_TYP_CCP_COMPLEX_FLOAT:
+      case CEOS_TYP_COMPLEX_FLOAT:
+      case CEOS_TYP_CCP_COMPLEX_FLOAT:
         eType = GDT_CFloat32;
         break;
 
       default:
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unsupported CEOS image data type %d.\n", 
+                  "Unsupported CEOS image data type %d.\n",
                   psImageDesc->DataType );
         delete poDS;
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Capture some information from the file that is of interest.     */
 /* -------------------------------------------------------------------- */
     poDS->nRasterXSize = psImageDesc->PixelsPerLine;
     poDS->nRasterYSize = psImageDesc->Lines;
 
+    const int bNative =
 #ifdef CPL_LSB
-    bNative = FALSE;
+    FALSE
 #else
-    bNative = TRUE;
+    TRUE
 #endif
+    ;
 
 /* -------------------------------------------------------------------- */
 /*      Special case for compressed cross products.                     */
 /* -------------------------------------------------------------------- */
-    if( psImageDesc->DataType == __CEOS_TYP_CCP_COMPLEX_FLOAT )
+    if( psImageDesc->DataType == CEOS_TYP_CCP_COMPLEX_FLOAT )
     {
         for( int iBand = 0; iBand < psImageDesc->NumChannels; iBand++ )
         {
-            poDS->SetBand( poDS->nBands+1, 
+            poDS->SetBand( poDS->nBands+1,
                            new CCPRasterBand( poDS, poDS->nBands+1, eType ) );
         }
 
@@ -1945,34 +1938,34 @@ GDALDataset *SAR_CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Special case for PALSAR data.                                   */
 /* -------------------------------------------------------------------- */
-    else if( psImageDesc->DataType == __CEOS_TYP_PALSAR_COMPLEX_SHORT )
+    else if( psImageDesc->DataType == CEOS_TYP_PALSAR_COMPLEX_SHORT )
     {
         for( int iBand = 0; iBand < psImageDesc->NumChannels; iBand++ )
         {
-            poDS->SetBand( poDS->nBands+1, 
+            poDS->SetBand( poDS->nBands+1,
                            new PALSARRasterBand( poDS, poDS->nBands+1 ) );
         }
 
         /* mark this as a Symmetrized Covariance product if appropriate */
         if ( poDS->GetRasterCount() == 6 ) {
-            poDS->SetMetadataItem( "MATRIX_REPRESENTATION", 
+            poDS->SetMetadataItem( "MATRIX_REPRESENTATION",
                 "SYMMETRIZED_COVARIANCE" );
-        } 
+        }
     }
 
 /* -------------------------------------------------------------------- */
 /*      Roll our own ...                                                */
 /* -------------------------------------------------------------------- */
     else if( psImageDesc->RecordsPerLine > 1
-             || psImageDesc->DataType == __CEOS_TYP_CHAR
-             || psImageDesc->DataType == __CEOS_TYP_LONG
-             || psImageDesc->DataType == __CEOS_TYP_ULONG
-             || psImageDesc->DataType == __CEOS_TYP_DOUBLE )
+             || psImageDesc->DataType == CEOS_TYP_CHAR
+             || psImageDesc->DataType == CEOS_TYP_LONG
+             || psImageDesc->DataType == CEOS_TYP_ULONG
+             || psImageDesc->DataType == CEOS_TYP_DOUBLE )
     {
         for( int iBand = 0; iBand < psImageDesc->NumChannels; iBand++ )
         {
-            poDS->SetBand( poDS->nBands+1, 
-                           new SAR_CEOSRasterBand( poDS, poDS->nBands+1, 
+            poDS->SetBand( poDS->nBands+1,
+                           new SAR_CEOSRasterBand( poDS, poDS->nBands+1,
                                                    eType ) );
         }
     }
@@ -1982,34 +1975,33 @@ GDALDataset *SAR_CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     else
     {
-        int	StartData;
-        int	nLineSize, nLineSize2;
-
+        int StartData;
         CalcCeosSARImageFilePosition( psVolume, 1, 1, NULL, &StartData );
-        
+
         StartData += psImageDesc->ImageDataStart;
 
+        int nLineSize, nLineSize2;
         CalcCeosSARImageFilePosition( psVolume, 1, 1, NULL, &nLineSize );
         CalcCeosSARImageFilePosition( psVolume, 1, 2, NULL, &nLineSize2 );
 
         nLineSize = nLineSize2 - nLineSize;
-        
+
         for( int iBand = 0; iBand < psImageDesc->NumChannels; iBand++ )
         {
             int           nStartData, nPixelOffset, nLineOffset;
 
-            if( psImageDesc->ChannelInterleaving == __CEOS_IL_PIXEL )
+            if( psImageDesc->ChannelInterleaving == CEOS_IL_PIXEL )
             {
                 CalcCeosSARImageFilePosition(psVolume,1,1,NULL,&nStartData);
 
                 nStartData += psImageDesc->ImageDataStart;
                 nStartData += psImageDesc->BytesPerPixel * iBand;
 
-                nPixelOffset = 
+                nPixelOffset =
                     psImageDesc->BytesPerPixel * psImageDesc->NumChannels;
                 nLineOffset = nLineSize;
             }
-            else if( psImageDesc->ChannelInterleaving == __CEOS_IL_LINE )
+            else if( psImageDesc->ChannelInterleaving == CEOS_IL_LINE )
             {
                 CalcCeosSARImageFilePosition(psVolume, iBand+1, 1, NULL,
                                              &nStartData);
@@ -2018,7 +2010,7 @@ GDALDataset *SAR_CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
                 nPixelOffset = psImageDesc->BytesPerPixel;
                 nLineOffset = nLineSize * psImageDesc->NumChannels;
             }
-            else if( psImageDesc->ChannelInterleaving == __CEOS_IL_BAND )
+            else if( psImageDesc->ChannelInterleaving == CEOS_IL_BAND )
             {
                 CalcCeosSARImageFilePosition(psVolume, iBand+1, 1, NULL,
                                              &nStartData);
@@ -2033,14 +2025,12 @@ GDALDataset *SAR_CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
                 return NULL;
             }
 
-            
-            poDS->SetBand( poDS->nBands+1, 
-                    new RawRasterBand( 
-                        poDS, poDS->nBands+1, fp, 
-                        nStartData, nPixelOffset, nLineOffset, 
+            poDS->SetBand( poDS->nBands+1,
+                    new RawRasterBand(
+                        poDS, poDS->nBands+1, fp,
+                        nStartData, nPixelOffset, nLineOffset,
                         eType, bNative, TRUE ) );
         }
-        
     }
 
 /* -------------------------------------------------------------------- */
@@ -2057,7 +2047,7 @@ GDALDataset *SAR_CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Check for GCPs.                                                 */
 /* -------------------------------------------------------------------- */
     poDS->ScanForGCPs();
-    
+
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
@@ -2075,12 +2065,12 @@ GDALDataset *SAR_CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
 /************************************************************************/
 /*                            ProcessData()                             */
 /************************************************************************/
-static int 
+static int
 ProcessData( VSILFILE *fp, int fileid, CeosSARVolume_t *sar, int max_records,
              vsi_l_offset max_bytes )
 
 {
-    unsigned char      temp_buffer[__CEOS_HEADER_LENGTH];
+    unsigned char      temp_buffer[CEOS_HEADER_LENGTH];
     unsigned char      *temp_body = NULL;
     int                start = 0;
     int                CurrentBodyLength = 0;
@@ -2092,17 +2082,25 @@ ProcessData( VSILFILE *fp, int fileid, CeosSARVolume_t *sar, int max_records,
 
     while(max_records != 0 && max_bytes != 0)
     {
+        iThisRecord++;
+
+        if( VSIFSeekL( fp, start, SEEK_SET ) != 0 ||
+            VSIFReadL( temp_buffer, 1, CEOS_HEADER_LENGTH, fp ) != CEOS_HEADER_LENGTH )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Corrupt CEOS File - cannot read record %d.",
+                      iThisRecord );
+            CPLFree(temp_body);
+            return CE_Failure;
+        }
         record = (CeosRecord_t *) CPLMalloc( sizeof( CeosRecord_t ) );
-        VSIFSeekL( fp, start, SEEK_SET );
-        VSIFReadL( temp_buffer, 1, __CEOS_HEADER_LENGTH, fp );
         record->Length = DetermineCeosRecordBodyLength( temp_buffer );
 
-        iThisRecord++;
         CeosToNative( &(record->Sequence), temp_buffer, 4, 4 );
 
         if( iThisRecord != record->Sequence )
         {
-            if( fileid == __CEOS_IMAGRY_OPT_FILE && iThisRecord == 2 )
+            if( fileid == CEOS_IMAGRY_OPT_FILE && iThisRecord == 2 )
             {
                 CPLDebug( "SAR_CEOS", "Ignoring CEOS file with wrong second record sequence number - likely it has padded records." );
                 CPLFree(record);
@@ -2111,7 +2109,7 @@ ProcessData( VSILFILE *fp, int fileid, CeosSARVolume_t *sar, int max_records,
             }
             else
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "Corrupt CEOS File - got record seq# %d instead of the expected %d.",
                           record->Sequence, iThisRecord );
                 CPLFree(record);
@@ -2119,25 +2117,52 @@ ProcessData( VSILFILE *fp, int fileid, CeosSARVolume_t *sar, int max_records,
                 return CE_Failure;
             }
         }
-        
+
+        if( record->Length <= CEOS_HEADER_LENGTH )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Corrupt CEOS File - cannot read record %d.",
+                      iThisRecord );
+            CPLFree(record);
+            CPLFree(temp_body);
+            return CE_Failure;
+        }
+
         if( record->Length > CurrentBodyLength )
         {
-            if(CurrentBodyLength == 0 )
-            {
-                temp_body = (unsigned char *) CPLMalloc( record->Length );
-                CurrentBodyLength = record->Length;
-            }
-            else
+            unsigned char* temp_body_new = (unsigned char *)
+                    VSI_REALLOC_VERBOSE( temp_body, record->Length );
+            if( temp_body_new == NULL )
             {
-                temp_body = (unsigned char *) 
-                    CPLRealloc( temp_body, record->Length );
-                CurrentBodyLength = record->Length;
+                CPLFree(record);
+                CPLFree(temp_body);
+                return CE_Failure;
             }
+            temp_body = temp_body_new;
+            CurrentBodyLength = record->Length;
         }
 
-        VSIFReadL( temp_body, 1, MAX(0,record->Length-__CEOS_HEADER_LENGTH),fp);
+        int nToRead = record->Length-CEOS_HEADER_LENGTH;
+        if( (int)VSIFReadL( temp_body, 1, nToRead,fp) != nToRead )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Corrupt CEOS File - cannot read record %d.",
+                      iThisRecord );
+            CPLFree(record);
+            CPLFree(temp_body);
+            return CE_Failure;
+        }
 
         InitCeosRecordWithHeader( record, temp_buffer, temp_body );
+        if( record->Length == 0 )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Corrupt CEOS File - invalid record %d.",
+                      iThisRecord );
+            CPLFree(record);
+            CPLFree(temp_body);
+            return CE_Failure;
+        }
 
         if( CurrentType == record->TypeCode.Int32Code )
             record->Subsequence = ++CurrentSequence;
@@ -2183,22 +2208,20 @@ ProcessData( VSILFILE *fp, int fileid, CeosSARVolume_t *sar, int max_records,
 void GDALRegister_SAR_CEOS()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "SAR_CEOS" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "SAR_CEOS" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "SAR_CEOS" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "CEOS SAR Image" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#SAR_CEOS" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = SAR_CEOSDataset::Open;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "SAR_CEOS" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "CEOS SAR Image" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_various.html#SAR_CEOS" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = SAR_CEOSDataset::Open;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/coasp/coasp_dataset.cpp b/frmts/coasp/coasp_dataset.cpp
index fa2db50..8bf342d 100644
--- a/frmts/coasp/coasp_dataset.cpp
+++ b/frmts/coasp/coasp_dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: coasp_dataset.cpp 28831 2015-04-01 16:46:05Z rouault $
+ * $Id: coasp_dataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  DRDC Configurable Airborne SAR Processor (COASP) data reader
  * Purpose:  Support in GDAL for the DRDC COASP format data, both Metadata
@@ -33,22 +33,17 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_priv.h"
-#include "cpl_port.h"
 #include "cpl_conv.h"
-#include "cpl_vsi.h"
+#include "cpl_port.h"
 #include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal_frmts.h"
+#include "gdal_priv.h"
 
-CPL_CVSID("$Id: coasp_dataset.cpp 28831 2015-04-01 16:46:05Z rouault $");
-
-CPL_C_START
-void    GDALRegister_COASP(void);
-CPL_C_END
-
-#define TYPE_GENERIC 0
-#define TYPE_GEOREF  1
-
+CPL_CVSID("$Id: coasp_dataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
+static const int TYPE_GENERIC = 0;
+static const int TYPE_GEOREF = 1;
 
 enum ePolarization {
 	hh = 0,
@@ -57,7 +52,6 @@ enum ePolarization {
 	vv
 };
 
-
 /*******************************************************************
  * Declaration of the COASPMetadata classes                        *
  *******************************************************************/
@@ -72,6 +66,7 @@ class COASPMetadataReader
 	int nCurrentItem;
 public:
 	COASPMetadataReader(char *pszFname);
+        ~COASPMetadataReader();
 	COASPMetadataItem *GetNextItem();
 	COASPMetadataItem *GetItem(int nItem);
 	int GotoMetadataItem(int nItemNumber);
@@ -83,18 +78,21 @@ public:
 class COASPMetadataItem
 {
 protected:
-	char *pszItemName;
-	char *pszItemValue;
+    char *pszItemName;
+    char *pszItemValue;
+
 public:
-	COASPMetadataItem() { }
-	COASPMetadataItem(char *pszItemName, char *pszItemValue);
-	char *GetItemName();
-	char *GetItemValue();
-	int GetType() { return TYPE_GENERIC; }
+    COASPMetadataItem() : pszItemName(NULL), pszItemValue(NULL) { }
+    COASPMetadataItem(char *pszItemName, char *pszItemValue);
+    ~COASPMetadataItem();
+
+    char *GetItemName();
+    char *GetItemValue();
+    int GetType() { return TYPE_GENERIC; }
 };
 
 /* Same as MetadataItem class except parses GCP properly and returns
- * a GDAL_GCP struct 
+ * a GDAL_GCP struct
  */
 class COASPMetadataGeorefGridItem : public COASPMetadataItem
 {
@@ -103,8 +101,9 @@ class COASPMetadataGeorefGridItem : public COASPMetadataItem
 	int nLines;
 	double ndLat;
 	double ndLong;
+
 public:
-	COASPMetadataGeorefGridItem(int nId, int nPixels, int nLines, 
+	COASPMetadataGeorefGridItem(int nId, int nPixels, int nLines,
 		double ndLat, double ndLong);
 	const char *GetItemName() { return "georef_grid"; }
 	GDAL_GCP *GetItemValue();
@@ -117,90 +116,96 @@ public:
  * ================================================================ *
  ********************************************************************/
 
-COASPMetadataItem::COASPMetadataItem(char *pszItemName, char *pszItemValue) 
+COASPMetadataItem::COASPMetadataItem(char *pszItemName_, char *pszItemValue_)
 {
-	this->pszItemName = VSIStrdup(pszItemName);
-	this->pszItemValue = VSIStrdup(pszItemValue);
+    pszItemName = VSIStrdup(pszItemName_);
+    pszItemValue = VSIStrdup(pszItemValue_);
 }
 
-char *COASPMetadataItem::GetItemName() 
+COASPMetadataItem::~COASPMetadataItem()
+{
+    CPLFree(pszItemName);
+    CPLFree(pszItemValue);
+}
+
+char *COASPMetadataItem::GetItemName()
 {
 	return VSIStrdup(pszItemName);
 }
 
-char *COASPMetadataItem::GetItemValue() 
+char *COASPMetadataItem::GetItemValue()
 {
 	return VSIStrdup(pszItemValue);
 }
 
-COASPMetadataGeorefGridItem::COASPMetadataGeorefGridItem(int nId, int nPixels, 
-	int nLines, double ndLat, double ndLong)
+COASPMetadataGeorefGridItem::COASPMetadataGeorefGridItem(int nIdIn, int nPixelsIn,
+	int nLinesIn, double ndLatIn, double ndLongIn)
 {
-	this->nId = nId;
-	this->nPixels = nPixels;
-	this->nLines = nLines;
-	this->ndLat = ndLat;
-	this->ndLong = ndLong;
-	this->pszItemName = VSIStrdup("georef_grid");
-
+	this->nId = nIdIn;
+	this->nPixels = nPixelsIn;
+	this->nLines = nLinesIn;
+	this->ndLat = ndLatIn;
+	this->ndLong = ndLongIn;
+        pszItemName = VSIStrdup("georef_grid");
 }
 
-GDAL_GCP *COASPMetadataGeorefGridItem::GetItemValue() 
+GDAL_GCP *COASPMetadataGeorefGridItem::GetItemValue()
 {
 	return NULL;
 }
 
-
 /********************************************************************
  * ================================================================ *
  * Implementation of the COASPMetadataReader Class                  *
  * ================================================================ *
  ********************************************************************/
 
-COASPMetadataReader::COASPMetadataReader(char *pszFname) 
+COASPMetadataReader::COASPMetadataReader(char *pszFname) :
+    fp(NULL), papszMetadata(NULL), nMetadataCount(0), nCurrentItem(0)
+{
+    papszMetadata = CSLLoad(pszFname);
+    nMetadataCount = CSLCount(papszMetadata);
+}
+
+COASPMetadataReader::~COASPMetadataReader()
 {
-	this->fp = NULL;
-	this->nCurrentItem = 0;
-	this->papszMetadata = CSLLoad(pszFname);
-	this->nMetadataCount = CSLCount(this->papszMetadata);
+    if (fp)
+        VSIFCloseL(fp);
+    CSLDestroy(papszMetadata);
 }
 
-COASPMetadataItem *COASPMetadataReader::GetNextItem() 
+COASPMetadataItem *COASPMetadataReader::GetNextItem()
 {
-	COASPMetadataItem *poMetadata;
-	char **papszMDTokens;
-	char *pszItemName;
-	char *pszItemValue;
 	if (nCurrentItem >= nMetadataCount)
 		return NULL;
 
+        COASPMetadataItem *poMetadata;
 
-	papszMDTokens = CSLTokenizeString2(papszMetadata[nCurrentItem], " ", 
-		CSLT_HONOURSTRINGS );
-	pszItemName = papszMDTokens[0];
-	if (EQUALN(pszItemName, "georef_grid", 11)) {
-		double ndLat, ndLong;
-		int nPixels, nLines;
+        char **papszMDTokens
+            = CSLTokenizeString2(papszMetadata[nCurrentItem], " ",
+                                 CSLT_HONOURSTRINGS );
+        char *pszItemName = papszMDTokens[0];
+	if (STARTS_WITH_CI(pszItemName, "georef_grid")) {
 		// georef_grid ( pixels lines ) ( lat long )
 		// 0           1 2      3     4 5 6   7    8
-		nPixels = atoi(papszMDTokens[2]);
-		nLines = atoi(papszMDTokens[3]);
-		ndLat = CPLAtof(papszMDTokens[6]);
-		ndLong = CPLAtof(papszMDTokens[7]);
-		poMetadata = new COASPMetadataGeorefGridItem(nCurrentItem, nPixels, 
-			nLines, ndLat, ndLong);
+                int nPixels = atoi(papszMDTokens[2]);
+                int nLines = atoi(papszMDTokens[3]);
+                double dfLat = CPLAtof(papszMDTokens[6]);
+                double dfLong = CPLAtof(papszMDTokens[7]);
+                poMetadata = new COASPMetadataGeorefGridItem(
+                    nCurrentItem, nPixels, nLines, dfLat, dfLong);
 	}
 	else {
 		int nCount = CSLCount(papszMDTokens);
-		pszItemValue = CPLStrdup(papszMDTokens[1]); 
+                char *pszItemValue = CPLStrdup(papszMDTokens[1]);
 		for (int i = 2; i < nCount; i++) {
-			int nSize = strlen(papszMDTokens[i]);
-			pszItemValue = (char *)CPLRealloc(pszItemValue, 
-				strlen(pszItemValue) + 1 + nSize);
-			sprintf(pszItemValue,"%s %s",pszItemValue, 
+			const size_t nSize = strlen(pszItemValue) + 1 + strlen(papszMDTokens[i]);
+			pszItemValue = (char *)CPLRealloc(pszItemValue, nSize);
+			snprintf(pszItemValue + strlen(pszItemValue),
+                                 nSize - strlen(pszItemValue), " %s",
 				papszMDTokens[i]);
 		}
-		
+
 		poMetadata = new COASPMetadataItem(pszItemName,
 			pszItemValue);
 
@@ -214,11 +219,11 @@ COASPMetadataItem *COASPMetadataReader::GetNextItem()
 /* Goto a particular metadata item, listed by number */
 int COASPMetadataReader::GotoMetadataItem(int nItemNumber)
 {
-	if (nItemNumber > nMetadataCount || nItemNumber < 0) {
-		nItemNumber = 0;
-		return 0;
+	if (nItemNumber >= nMetadataCount || nItemNumber < 0) {
+            nCurrentItem = 0;
 	}
-	nCurrentItem = nItemNumber;
+	else
+            nCurrentItem = nItemNumber;
 	return nCurrentItem;
 }
 
@@ -238,7 +243,7 @@ class COASPRasterBand;
 
 /* A couple of observations based on the data I have available to me:
  * a) the headers don't really change, beyond indicating data sources
- *    and such. As such, I only read the first header specified by the 
+ *    and such. As such, I only read the first header specified by the
  *    user. Note that this is agnostic: you can specify hh, vv, vh, hv and
  *    all the data needed will be immediately available.
  * b) Lots of GCPs are present in the headers. This is most excellent.
@@ -277,19 +282,19 @@ class COASPRasterBand : public GDALRasterBand {
 	int ePol;
 public:
 	COASPRasterBand( COASPDataset *poDS, GDALDataType eDataType, int ePol, VSILFILE *fp );
-	virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, 
+	virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff,
 		void *pImage);
 };
 
-COASPRasterBand::COASPRasterBand( COASPDataset *poDS, GDALDataType eDataType,
-	int ePol, VSILFILE *fp)
+COASPRasterBand::COASPRasterBand( COASPDataset *poDSIn, GDALDataType eDataTypeIn,
+	int ePolIn, VSILFILE *fpIn)
 {
-	this->fp = fp;
-	this->ePol = ePol;
-	this->poDS = poDS;
-	this->eDataType = eDataType;
-	this->nBlockXSize = poDS->GetRasterXSize();
-	this->nBlockYSize = 1;
+	this->fp = fpIn;
+	this->ePol = ePolIn;
+	this->poDS = poDSIn;
+	this->eDataType = eDataTypeIn;
+        nBlockXSize = poDS->GetRasterXSize();
+        nBlockYSize = 1;
 }
 
 CPLErr COASPRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
@@ -297,7 +302,7 @@ CPLErr COASPRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                                     void *pImage )
 {
 	if (this->fp == NULL) {
-		CPLError(CE_Fatal, 1, "file pointer freed unexpectedly\n");
+		CPLError(CE_Fatal, CPLE_AppDefined, "file pointer freed unexpectedly\n");
 		return CE_Fatal;
 	}
 
@@ -306,16 +311,13 @@ CPLErr COASPRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 
 	VSIFSeekL(this->fp, nByteNum, SEEK_SET);
 	int nReadSize = (GDALGetDataTypeSize(eDataType)/8) * poDS->GetRasterXSize();
-	VSIFReadL((char *)pImage, 1, nReadSize, 
+	VSIFReadL((char *)pImage, 1, nReadSize,
 		this->fp);
 
 #ifdef CPL_LSB
-	GDALSwapWords( pImage, 4, nBlockXSize * 2, 4 ); 
+	GDALSwapWords( pImage, 4, nBlockXSize * 2, 4 );
 #endif
-
-
 	return CE_None;
-	
 }
 
 
@@ -325,7 +327,6 @@ CPLErr COASPRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
  * ================================================================ *
  ********************************************************************/
 
-
 /************************************************************************/
 /*                            GetGCPCount()                             */
 /************************************************************************/
@@ -348,7 +349,7 @@ const GDAL_GCP *COASPDataset::GetGCPs()
 /*                              Identify()                              */
 /************************************************************************/
 
-int COASPDataset::Identify( GDALOpenInfo *poOpenInfo ) 
+int COASPDataset::Identify( GDALOpenInfo *poOpenInfo )
 {
 	if(poOpenInfo->fpL == NULL || poOpenInfo->nHeaderBytes < 256)
 		return 0;
@@ -356,7 +357,7 @@ int COASPDataset::Identify( GDALOpenInfo *poOpenInfo )
 	/* With a COASP .hdr file, the first line or so is:
  	 * time_first_datarec
  	 */
-	if(EQUALN((char *)poOpenInfo->pabyHeader,"time_first_datarec",18))
+	if(STARTS_WITH_CI((char *)poOpenInfo->pabyHeader, "time_first_datarec"))
 		return 1;
 
 	return 0;
@@ -366,46 +367,47 @@ int COASPDataset::Identify( GDALOpenInfo *poOpenInfo )
 /*                                Open()                                */
 /************************************************************************/
 
-GDALDataset *COASPDataset::Open( GDALOpenInfo *poOpenInfo ) 
+GDALDataset *COASPDataset::Open( GDALOpenInfo *poOpenInfo )
 {
 	if (!COASPDataset::Identify(poOpenInfo))
 		return NULL;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The COASP driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
     }
-	/* Create a fresh dataset for us to work with */
-	COASPDataset *poDS;
-	poDS = new COASPDataset();
-	
+
+    /* Create a fresh dataset for us to work with */
+    COASPDataset *poDS = new COASPDataset();
+
 	if (poDS == NULL)
 		return NULL;
 
 	/* Steal the file pointer for the header */
 	poDS->fpHdr = poOpenInfo->fpL;
 	poOpenInfo->fpL = NULL;
-	
+
 	/* Set the binary matrix file pointers to NULL, for now */
 	poDS->fpBinHH = NULL;
 	poDS->fpBinHV = NULL;
 	poDS->fpBinVH = NULL;
 	poDS->fpBinVV = NULL;
+        poDS->nGCPCount = 0;
+        poDS->pasGCP = NULL;
 
 	poDS->pszFileName = VSIStrdup(poOpenInfo->pszFilename);
 
 	/* determine the file name prefix */
-	const char *pszFilename;
 	char *pszBaseName = VSIStrdup(CPLGetBasename(poDS->pszFileName));
 	char *pszDir = VSIStrdup(CPLGetPath(poDS->pszFileName));
 	const char *pszExt = "rc";
-	int nNull = strlen(pszBaseName) - 1;
+	int nNull = static_cast<int>(strlen(pszBaseName)) - 1;
 	char *pszBase = (char *)CPLMalloc(nNull);
 	strncpy(pszBase, pszBaseName, nNull);
 	pszBase[nNull - 1] = '\0';
@@ -423,7 +425,7 @@ GDALDataset *COASPDataset::Open( GDALOpenInfo *poOpenInfo )
 	}
 
 	if (psChan == NULL) {
-		CPLError(CE_Fatal, 1, "unable to recognize file as COASP.\n");
+		CPLError(CE_Fatal, CPLE_AppDefined, "unable to recognize file as COASP.\n");
 		free(poDS->pszFileName);
 		free(pszBase);
 		free(pszDir);
@@ -435,7 +437,6 @@ GDALDataset *COASPDataset::Open( GDALOpenInfo *poOpenInfo )
     COASPMetadataReader *poReader = new COASPMetadataReader(
         poDS->pszFileName);
 
-
     /* Get Image X and Y widths */
     poReader->GotoMetadataItem("number_lines");
     COASPMetadataItem *poItem = poReader->GetNextItem();
@@ -444,6 +445,7 @@ GDALDataset *COASPDataset::Open( GDALOpenInfo *poOpenInfo )
     free(nValue);
 
     poReader->GotoMetadataItem("number_samples");
+    delete poItem;
     poItem = poReader->GetNextItem();
     nValue = poItem->GetItemValue();
     poDS->nRasterXSize = atoi(nValue);
@@ -453,48 +455,48 @@ GDALDataset *COASPDataset::Open( GDALOpenInfo *poOpenInfo )
 	/* Horizontal transmit, horizontal receive */
 	psChan[0] = 'h';
 	psChan[1] = 'h';
-	pszFilename = CPLFormFilename(pszDir, pszBase, pszExt); 
+     const char *pszFilename = CPLFormFilename(pszDir, pszBase, pszExt);
 
 	poDS->fpBinHH = VSIFOpenL(pszFilename, "r");
 
-	if (poDS->fpBinHH != 0) {
+	if (poDS->fpBinHH != NULL) {
 		/* Set raster band */
-		poDS->SetBand(1, new COASPRasterBand(poDS, GDT_CFloat32, 
+		poDS->SetBand(1, new COASPRasterBand(poDS, GDT_CFloat32,
 			hh , poDS->fpBinHH));
 	}
-	
+
 	/* Horizontal transmit, vertical receive */
-    psChan[0] = 'h'; 
-    psChan[1] = 'v'; 
+    psChan[0] = 'h';
+    psChan[1] = 'v';
     pszFilename = CPLFormFilename(pszDir, pszBase, pszExt);
- 
+
 	poDS->fpBinHV = VSIFOpenL(pszFilename, "r");
 
-	if (poDS->fpBinHV != 0) {
+	if (poDS->fpBinHV != NULL) {
 		poDS->SetBand(2, new COASPRasterBand(poDS, GDT_CFloat32,
 			hv, poDS->fpBinHV));
 	}
 
 	/* Vertical transmit, horizontal receive */
-    psChan[0] = 'v'; 
-    psChan[1] = 'h'; 
+    psChan[0] = 'v';
+    psChan[1] = 'h';
     pszFilename = CPLFormFilename(pszDir, pszBase, pszExt);
- 
+
 	poDS->fpBinVH = VSIFOpenL(pszFilename, "r");
 
-	if (poDS->fpBinVH != 0) {
+	if (poDS->fpBinVH != NULL) {
     	poDS->SetBand(3, new COASPRasterBand(poDS, GDT_CFloat32,
 			vh, poDS->fpBinVH));
 	}
 
 	/* Vertical transmit, vertical receive */
-    psChan[0] = 'v'; 
-    psChan[1] = 'v'; 
+    psChan[0] = 'v';
+    psChan[1] = 'v';
     pszFilename = CPLFormFilename(pszDir, pszBase, pszExt);
 
 	poDS->fpBinVV = VSIFOpenL(pszFilename, "r");
 
-	if (poDS->fpBinVV != 0) {
+	if (poDS->fpBinVV != NULL) {
 		poDS->SetBand(4, new COASPRasterBand(poDS, GDT_CFloat32,
 			vv, poDS->fpBinVV));
 	}
@@ -502,14 +504,15 @@ GDALDataset *COASPDataset::Open( GDALOpenInfo *poOpenInfo )
 
 	/* Oops, missing all the data? */
 
-	if (poDS->fpBinHH == NULL && poDS->fpBinHV == NULL 
-		&& poDS->fpBinVH == NULL && poDS->fpBinVV == NULL) 
+	if (poDS->fpBinHH == NULL && poDS->fpBinHV == NULL
+		&& poDS->fpBinVH == NULL && poDS->fpBinVV == NULL)
 	{
-		CPLError(CE_Fatal,1,"Unable to find any data! Aborting.");
+		CPLError(CE_Fatal,CPLE_AppDefined,"Unable to find any data! Aborting.");
 		free(pszBase);
 		free(pszDir);
 		delete poDS;
-
+                delete poItem;
+                delete poReader;
 		return NULL;
 	}
 
@@ -519,37 +522,32 @@ GDALDataset *COASPDataset::Open( GDALOpenInfo *poOpenInfo )
 
 	free(pszBase);
 	free(pszDir);
-	
-	poDS->nGCPCount = 0;
-	poDS->pasGCP = NULL;
 
 	delete poItem;
-	delete poReader; 
+	delete poReader;
 
 	return poDS;
-
 }
 
 /************************************************************************/
 /*                         GDALRegister_COASP()                         */
 /************************************************************************/
 
-void GDALRegister_COASP(void)
+void GDALRegister_COASP()
 {
-	GDALDriver *poDriver;
-	if ( GDALGetDriverByName( "COASP" ) == NULL ) {
-		poDriver = new GDALDriver();
-		poDriver->SetDescription( "COASP" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-		poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-			"DRDC COASP SAR Processor Raster" );
-		poDriver->SetMetadataItem( GDAL_DMD_EXTENSION,
-			"hdr" );
-/*		poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-			"frmt_coasp.html"); */
-		poDriver->pfnIdentify = COASPDataset::Identify;
-		poDriver->pfnOpen = COASPDataset::Open;
-		GetGDALDriverManager()->RegisterDriver( poDriver );
-	}
-
+    if( GDALGetDriverByName( "COASP" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "COASP" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "DRDC COASP SAR Processor Raster" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION,
+                               "hdr" );
+    // poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_coasp.html");
+    poDriver->pfnIdentify = COASPDataset::Identify;
+    poDriver->pfnOpen = COASPDataset::Open;
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/cosar/cosar_dataset.cpp b/frmts/cosar/cosar_dataset.cpp
index 1cfc069..5c58639 100644
--- a/frmts/cosar/cosar_dataset.cpp
+++ b/frmts/cosar/cosar_dataset.cpp
@@ -1,4 +1,4 @@
-/* TerraSAR-X COSAR Format Driver 
+/* TerraSAR-X COSAR Format Driver
  * (C)2007 Philippe P. Vachon <philippe at cowpig.ca>
  * ---------------------------------------------------------------------------
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -20,47 +20,43 @@
  * DEALINGS IN THE SOFTWARE.
  */
 
-
-#include "gdal_priv.h"
-#include "cpl_port.h"
 #include "cpl_conv.h"
-#include "cpl_vsi.h"
+#include "cpl_port.h"
 #include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal_frmts.h"
+#include "gdal_priv.h"
+
 #include <string.h>
 
 /* Various offsets, in bytes */
-#define BIB_OFFSET 	0  /* Bytes in burst, valid only for ScanSAR */
-#define RSRI_OFFSET 	4  /* Range Sample Relative Index */
-#define RS_OFFSET 	8  /* Range Samples, the length of a range line */
-#define AS_OFFSET 	12 /* Azimuth Samples, the length of an azimth column */
-#define BI_OFFSET	16 /* Burst Index, the index number of the burst */
-#define RTNB_OFFSET	20 /* Rangeline total number of bytes, incl. annot. */
-#define TNL_OFFSET	24 /* Total Number of Lines */
-#define MAGIC1_OFFSET	28 /* Magic number 1: 0x43534152 */
-#define MAGIC2_OFFSET	32 /* Magic number 2: Version number */ 
-
-#define COSAR_MAGIC 	0x43534152 /* String CSAR */
-#define FILLER_MAGIC	0x7F7F7F7F /* Filler value, we'll use this for a test */
-
-CPL_C_START
-void GDALRegister_COSAR(void);
-CPL_C_END
+// Commented out the unused defines.
+// #define BIB_OFFSET   0  /* Bytes in burst, valid only for ScanSAR */
+// #define RSRI_OFFSET  4  /* Range Sample Relative Index */
+const static int RS_OFFSET = 8;  /* Range Samples, the length of a range line */
+// #define AS_OFFSET    12 /* Azimuth Samples, the length of an azimuth column */
+// #define BI_OFFSET    16 /* Burst Index, the index number of the burst */
+const static int RTNB_OFFSET = 20;  /* Rangeline total number of bytes, incl. annot. */
+// #define TNL_OFFSET	24 /* Total Number of Lines */
+const static int MAGIC1_OFFSET = 28; /* Magic number 1: 0x43534152 */
+// #define MAGIC2_OFFSET 32 /* Magic number 2: Version number */
+
+// #define COSAR_MAGIC  0x43534152  /* String CSAR */
+// #define FILLER_MAGIC 0x7F7F7F7F  /* Filler value, we'll use this for a test */
 
 class COSARDataset : public GDALDataset
 {
-	long nSize;
 public:
+        COSARDataset() : fp(NULL) { }
 	VSILFILE *fp;
-/*	~COSARDataset(); */
-	
+
 	static GDALDataset *Open( GDALOpenInfo * );
-	long GetSizeInBytes() { return nSize; }
 };
 
 class COSARRasterBand : public GDALRasterBand
 {
-	unsigned long nRTNB;
-	int nBurstNumber;
+    unsigned long nRTNB;
+    // int nBurstNumber;
 public:
 	COSARRasterBand(COSARDataset *, unsigned long nRTNB);
 	virtual CPLErr IReadBlock(int, int, void *);
@@ -70,9 +66,10 @@ public:
  * COSARRasterBand Implementation
  *****************************************************************************/
 
-COSARRasterBand::COSARRasterBand(COSARDataset *pDS, unsigned long nRTNB) {
-	this->nRTNB = nRTNB;
-	nBurstNumber = 1;
+COSARRasterBand::COSARRasterBand(COSARDataset *pDS, unsigned long nRTNBIn)  // :
+    // nBurstNumber(1)
+{
+	this->nRTNB = nRTNBIn;
 	nBlockXSize = pDS->GetRasterXSize();
 	nBlockYSize = 1;
 	eDataType = GDT_CInt16;
@@ -82,8 +79,6 @@ CPLErr COSARRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff,
                                    int nBlockYOff,
                                    void *pImage) {
 
-    unsigned long nRSFV = 0;
-    unsigned long nRSLV = 0;
     COSARDataset *pCDS = (COSARDataset *) poDS;
 
     /* Find the line we want to be at */
@@ -95,8 +90,9 @@ CPLErr COSARRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff,
 
     VSIFSeekL(pCDS->fp,(this->nRTNB * (nBlockYOff + 4)), SEEK_SET);
 
-
     /* Read RSFV and RSLV (TX-GS-DD-3307) */
+    unsigned long nRSFV = 0;
+    unsigned long nRSLV = 0;
     VSIFReadL(&nRSFV,1,4,pCDS->fp);
     VSIFReadL(&nRSLV,1,4,pCDS->fp);
 
@@ -112,18 +108,17 @@ CPLErr COSARRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff,
     {
         /* throw an error */
         CPLError(CE_Failure, CPLE_AppDefined,
-                 "RSLV/RSFV values are not sane... oh dear.\n");	
+                 "RSLV/RSFV values are not sane... oh dear.\n");
         return CE_Failure;
     }
-	
-	
+
     /* zero out the range line */
     for (int i = 0; i < this->nRasterXSize; i++)
     {
         ((GUInt32 *)pImage)[i] = 0;
     }
 
-    /* properly account for validity mask */ 
+    /* properly account for validity mask */
     if (nRSFV > 1)
     {
         VSIFSeekL(pCDS->fp,(this->nRTNB*(nBlockYOff+4)+(nRSFV+1)*4), SEEK_SET);
@@ -137,7 +132,6 @@ CPLErr COSARRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff,
     GDALSwapWords( pImage, 2, nBlockXSize * nBlockYSize * 2, 2 );
 #endif
 
-
     return CE_None;
 }
 
@@ -152,7 +146,7 @@ GDALDataset *COSARDataset::Open( GDALOpenInfo * pOpenInfo ) {
     if( pOpenInfo->nHeaderBytes < 4 )
         return NULL;
 
-    if (!EQUALN((char *)pOpenInfo->pabyHeader+MAGIC1_OFFSET, "CSAR",4)) 
+    if (!STARTS_WITH_CI((char *)pOpenInfo->pabyHeader+MAGIC1_OFFSET, "CSAR"))
         return NULL;
 
 /* -------------------------------------------------------------------- */
@@ -160,31 +154,25 @@ GDALDataset *COSARDataset::Open( GDALOpenInfo * pOpenInfo ) {
 /* -------------------------------------------------------------------- */
     if( pOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The COSAR driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
     }
-    
+
     /* this is a cosar dataset */
-    COSARDataset *pDS;
-    pDS = new COSARDataset();
-	
+    COSARDataset *pDS = new COSARDataset();
+
     /* steal fp */
     pDS->fp = pOpenInfo->fpL;
     pOpenInfo->fpL = NULL;
 
-    /* Calculate the file size */
-    VSIFSeekL(pDS->fp,0,SEEK_END);
-    pDS->nSize = VSIFTellL(pDS->fp);
-
     VSIFSeekL(pDS->fp, RS_OFFSET, SEEK_SET);
-    VSIFReadL(&pDS->nRasterXSize, 1, 4, pDS->fp);  
+    VSIFReadL(&pDS->nRasterXSize, 1, 4, pDS->fp);
 #ifdef CPL_LSB
     pDS->nRasterXSize = CPL_SWAP32(pDS->nRasterXSize);
 #endif
-	
-	
+
     VSIFReadL(&pDS->nRasterYSize, 1, 4, pDS->fp);
 #ifdef CPL_LSB
     pDS->nRasterYSize = CPL_SWAP32(pDS->nRasterYSize);
@@ -198,23 +186,25 @@ GDALDataset *COSARDataset::Open( GDALOpenInfo * pOpenInfo ) {
 
     /* Add raster band */
     pDS->SetBand(1, new COSARRasterBand(pDS, nRTNB));
-    return pDS;	
+    return pDS;
 }
 
 
 /* register the driver with GDAL */
-void GDALRegister_COSAR() {
-	GDALDriver *poDriver;
-	if (GDALGetDriverByName("cosar") == NULL) {
-		poDriver = new GDALDriver();
-		poDriver->SetDescription("COSAR");
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-		poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-			"COSAR Annotated Binary Matrix (TerraSAR-X)");
-		poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-			"frmt_cosar.html");
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-		poDriver->pfnOpen = COSARDataset::Open;
-		GetGDALDriverManager()->RegisterDriver(poDriver);
-	}
+void GDALRegister_COSAR()
+
+{
+    if( GDALGetDriverByName( "cosar" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+    poDriver->SetDescription("COSAR");
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "COSAR Annotated Binary Matrix (TerraSAR-X)");
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_cosar.html");
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->pfnOpen = COSARDataset::Open;
+    GetGDALDriverManager()->RegisterDriver(poDriver);
 }
diff --git a/frmts/cosar/frmt_cosar.html b/frmts/cosar/frmt_cosar.html
index 5d09e2d..ca0bf0e 100644
--- a/frmts/cosar/frmt_cosar.html
+++ b/frmts/cosar/frmt_cosar.html
@@ -8,14 +8,14 @@
 <h1>COSAR -- TerraSAR-X Complex SAR Data Product</h1>
 
 <p>This driver provides the capability to read TerraSAR-X complex data. While
-most users will receive products in GeoTIFF format (representing detected 
+most users will receive products in GeoTIFF format (representing detected
 radiation reflected from the targets, or geocoded data), ScanSAR products will be distributed in COSAR format.</p>
 
 <p>Essentially, COSAR is an annotated binary matrix, with each sample held
 in 4 bytes (16 bytes real, 16 bytes imaginary) stored with the most significant
 byte first (Big Endian). Within a COSAR container there are one or more
 "bursts" which represent individual ScanSAR bursts. Note that if a Stripmap or
-Spotlight product is held in a COSAR container it is stored in a single 
+Spotlight product is held in a COSAR container it is stored in a single
 burst.</p>
 
 <p>Support for ScanSAR data is currently under way, due to the difficulties in fitting
diff --git a/frmts/ctg/ctgdataset.cpp b/frmts/ctg/ctgdataset.cpp
index b13d26f..77f63bf 100644
--- a/frmts/ctg/ctgdataset.cpp
+++ b/frmts/ctg/ctgdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ctgdataset.cpp 28039 2014-11-30 18:24:59Z rouault $
+ * $Id: ctgdataset.cpp 32205 2015-12-17 21:57:20Z goatbar $
  *
  * Project:  CTG driver
  * Purpose:  GDALDataset driver for CTG dataset.
@@ -27,16 +27,13 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: ctgdataset.cpp 28039 2014-11-30 18:24:59Z rouault $");
+CPL_CVSID("$Id: ctgdataset.cpp 32205 2015-12-17 21:57:20Z goatbar $");
 
-CPL_C_START
-void    GDALRegister_CTG(void);
-CPL_C_END
-
-#define HEADER_LINE_COUNT 5
+static const int HEADER_LINE_COUNT = 5;
 
 typedef struct
 {
@@ -94,7 +91,7 @@ static const LULCDescStruct asLULCDesc[] =
     {92, "Glaciers" }
 };
 
-static const char* apszBandDescription[] =
+static const char* const apszBandDescription[] =
 {
     "Land Use and Land Cover",
     "Political units",
@@ -167,18 +164,16 @@ class CTGRasterBand : public GDALPamRasterBand
 /*                           CTGRasterBand()                            */
 /************************************************************************/
 
-CTGRasterBand::CTGRasterBand( CTGDataset *poDS, int nBand )
-
+CTGRasterBand::CTGRasterBand( CTGDataset *poDSIn, int nBandIn ) :
+    papszCategories(NULL)
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
 
     eDataType = GDT_Int32;
 
     nBlockXSize = poDS->GetRasterXSize();
     nBlockYSize = poDS->GetRasterYSize();
-
-    papszCategories = NULL;
 }
 
 /************************************************************************/
@@ -217,7 +212,7 @@ double CTGRasterBand::GetNoDataValue( int *pbSuccess )
     if (pbSuccess)
         *pbSuccess = TRUE;
 
-    return 0.;
+    return 0.0;
 }
 
 /************************************************************************/
@@ -232,15 +227,14 @@ char **CTGRasterBand::GetCategoryNames()
     if (papszCategories != NULL)
         return papszCategories;
 
-    int i;
     int nasLULCDescSize = (int)(sizeof(asLULCDesc) / sizeof(asLULCDesc[0]));
     int nCategoriesSize = asLULCDesc[nasLULCDescSize - 1].nCode;
     papszCategories = (char**)CPLCalloc(nCategoriesSize + 2, sizeof(char*));
-    for(i=0;i<nasLULCDescSize;i++)
+    for(int i=0;i<nasLULCDescSize;i++)
     {
         papszCategories[asLULCDesc[i].nCode] = CPLStrdup(asLULCDesc[i].pszDesc);
     }
-    for(i=0;i<nCategoriesSize;i++)
+    for(int i=0;i<nCategoriesSize;i++)
     {
         if (papszCategories[i] == NULL)
             papszCategories[i] = CPLStrdup("");
@@ -254,13 +248,16 @@ char **CTGRasterBand::GetCategoryNames()
 /*                            ~CTGDataset()                            */
 /************************************************************************/
 
-CTGDataset::CTGDataset()
-{
-    pszProjection = NULL;
-    bHasReadImagery = FALSE;
-    pabyImage = NULL;
-    fp = NULL;
-}
+CTGDataset::CTGDataset() :
+    fp(NULL),
+    nNWEasting(0),
+    nNWNorthing(0),
+    nCellSize(0),
+    nUTMZone(0),
+    pszProjection(NULL),
+    bHasReadImagery(FALSE),
+    pabyImage(NULL)
+{ }
 
 /************************************************************************/
 /*                            ~CTGDataset()                            */
@@ -336,8 +333,7 @@ int CTGDataset::ReadImagery()
                      nLine, szLine);
             return FALSE;
         }
-        int i;
-        for(i=0;i<6;i++)
+        for(int i=0;i<6;i++)
         {
             int nVal = atoi(ExtractField(szField, szLine, 20 + 10*i, 10));
             if (nVal >= 2000000000)
@@ -366,7 +362,7 @@ int CTGDataset::Identify( GDALOpenInfo * poOpenInfo )
     if ((EQUAL(pszFilename, "grid_cell.gz") ||
          EQUAL(pszFilename, "grid_cell1.gz") ||
          EQUAL(pszFilename, "grid_cell2.gz")) &&
-        !EQUALN(poOpenInfo->pszFilename, "/vsigzip/", 9))
+        !STARTS_WITH_CI(poOpenInfo->pszFilename, "/vsigzip/"))
     {
         osFilename = "/vsigzip/";
         osFilename += poOpenInfo->pszFilename;
@@ -385,8 +381,7 @@ int CTGDataset::Identify( GDALOpenInfo * poOpenInfo )
 /*      Chech that it looks roughly as a CTG dataset                    */
 /* -------------------------------------------------------------------- */
     const char* pszData = (const char*)poOpenInfo->pabyHeader;
-    int i;
-    for(i=0;i<4 * 80;i++)
+    for(int i=0;i<4 * 80;i++)
     {
         if (!((pszData[i] >= '0' && pszData[i] <= '9') ||
               pszData[i] == ' ' || pszData[i] == '-'))
@@ -424,8 +419,6 @@ int CTGDataset::Identify( GDALOpenInfo * poOpenInfo )
 GDALDataset *CTGDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    int         i;
-
     if (!Identify(poOpenInfo))
         return NULL;
 
@@ -437,7 +430,7 @@ GDALDataset *CTGDataset::Open( GDALOpenInfo * poOpenInfo )
     if ((EQUAL(pszFilename, "grid_cell.gz") ||
          EQUAL(pszFilename, "grid_cell1.gz") ||
          EQUAL(pszFilename, "grid_cell2.gz")) &&
-        !EQUALN(poOpenInfo->pszFilename, "/vsigzip/", 9))
+        !STARTS_WITH_CI(poOpenInfo->pszFilename, "/vsigzip/"))
     {
         osFilename = "/vsigzip/";
         osFilename += poOpenInfo->pszFilename;
@@ -466,7 +459,7 @@ GDALDataset *CTGDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    for(i=HEADER_LINE_COUNT * 80 - 1;i>=0;i--)
+    for(int i=HEADER_LINE_COUNT * 80 - 1;i>=0;i--)
     {
         if (szHeader[i] == ' ')
             szHeader[i] = 0;
@@ -481,9 +474,7 @@ GDALDataset *CTGDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    CTGDataset         *poDS;
-
-    poDS = new CTGDataset();
+    CTGDataset *poDS = new CTGDataset();
     poDS->fp = fp;
     fp = NULL;
     poDS->nRasterXSize = nCols;
@@ -531,7 +522,7 @@ GDALDataset *CTGDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
     poDS->nBands = 6;
-    for( i = 0; i < poDS->nBands; i++ )
+    for( int i = 0; i < poDS->nBands; i++ )
     {
         poDS->SetBand( i+1, new CTGRasterBand( poDS, i+1 ) );
         poDS->GetRasterBand(i+1)->SetDescription(apszBandDescription[i]);
@@ -548,7 +539,7 @@ GDALDataset *CTGDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -565,7 +556,7 @@ CPLErr CTGDataset::GetGeoTransform( double * padfTransform )
     padfTransform[4] = 0.;
     padfTransform[5] = -nCellSize;
 
-    return( CE_None );
+    return CE_None;
 }
 
 /************************************************************************/
@@ -585,24 +576,22 @@ const char* CTGDataset::GetProjectionRef()
 void GDALRegister_CTG()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "CTG" ) != NULL )
+      return;
 
-    if( GDALGetDriverByName( "CTG" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "CTG" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "USGS LULC Composite Theme Grid" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "frmt_various.html#CTG" );
+    poDriver->SetDescription( "CTG" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "USGS LULC Composite Theme Grid" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_various.html#CTG" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = CTGDataset::Open;
-        poDriver->pfnIdentify = CTGDataset::Identify;
+    poDriver->pfnOpen = CTGDataset::Open;
+    poDriver->pfnIdentify = CTGDataset::Identify;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/dds/ddsdataset.cpp b/frmts/dds/ddsdataset.cpp
index 5ea452b..bae2e4b 100644
--- a/frmts/dds/ddsdataset.cpp
+++ b/frmts/dds/ddsdataset.cpp
@@ -29,19 +29,18 @@
  ******************************************************************************
  *
  * THE CURRENT IMPLEMENTATION IS WRITE ONLY.
- * 
+ *
  */
 
-#include "gdal_pam.h"
+/* stdio.h needed before including crnlib.h, since the later needs NULL to be defined */
+#include <stdio.h>
 #include "crnlib.h"
 #include "dds_defs.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
 
 CPL_CVSID("$Id: $");
 
-CPL_C_START
-void	GDALRegister_DDS(void);
-CPL_C_END
-
 using namespace crnlib;
 
 enum { DDS_COLOR_TYPE_RGB,
@@ -70,34 +69,32 @@ public:
 /************************************************************************/
 
 GDALDataset *
-DDSDataset::CreateCopy(const char * pszFilename, GDALDataset *poSrcDS, 
-                       int bStrict, char ** papszOptions, 
+DDSDataset::CreateCopy(const char * pszFilename, GDALDataset *poSrcDS,
+                       int bStrict, char ** papszOptions,
                        GDALProgressFunc pfnProgress, void * pProgressData)
 
-{  
+{
     int  nBands = poSrcDS->GetRasterCount();
-    int  nXSize = poSrcDS->GetRasterXSize();
-    int  nYSize = poSrcDS->GetRasterYSize();
-    
+
     /* -------------------------------------------------------------------- */
     /*      Some rudimentary checks                                         */
     /* -------------------------------------------------------------------- */
     if (nBands != 3 && nBands != 4)
     {
-        CPLError(CE_Failure, CPLE_NotSupported, 
+        CPLError(CE_Failure, CPLE_NotSupported,
                  "DDS driver doesn't support %d bands. Must be 3 (rgb) \n"
-                 "or 4 (rgba) bands.\n", 
+                 "or 4 (rgba) bands.\n",
                  nBands);
-        
+
         return NULL;
     }
 
     if (poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte)
     {
-        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, 
+        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
                   "DDS driver doesn't support data type %s. "
-                  "Only eight bit (Byte) bands supported. %s\n", 
-                  GDALGetDataTypeName( 
+                  "Only eight bit (Byte) bands supported. %s\n",
+                  GDALGetDataTypeName(
                                       poSrcDS->GetRasterBand(1)->GetRasterDataType()),
                   (bStrict) ? "" : "Defaulting to Byte" );
 
@@ -118,13 +115,11 @@ DDSDataset::CreateCopy(const char * pszFilename, GDALDataset *poSrcDS,
     /* -------------------------------------------------------------------- */
     /*      Create the dataset.                                             */
     /* -------------------------------------------------------------------- */
-    VSILFILE	*fpImage;
-
-    fpImage = VSIFOpenL(pszFilename, "wb");
+    VSILFILE *fpImage = VSIFOpenL(pszFilename, "wb");
     if (fpImage == NULL)
     {
-        CPLError(CE_Failure, CPLE_OpenFailed, 
-                 "Unable to create dds file %s.\n", 
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "Unable to create dds file %s.\n",
                  pszFilename);
         return NULL;
     }
@@ -132,15 +127,15 @@ DDSDataset::CreateCopy(const char * pszFilename, GDALDataset *poSrcDS,
     /* -------------------------------------------------------------------- */
     /*      Create the Crunch compressor                                    */
     /* -------------------------------------------------------------------- */
-    
+
     /* Default values */
-    crn_format fmt = cCRNFmtDXT3; 
-    const uint cDXTBlockSize = 4;    
+    crn_format fmt = cCRNFmtDXT3;
+    const uint cDXTBlockSize = 4;
     crn_dxt_quality dxt_quality = cCRNDXTQualityNormal;
-    bool srgb_colorspace = true;    
+    bool srgb_colorspace = true;
     bool dxt1a_transparency = true;
     //bool generate_mipmaps = true;
-    
+
     /* Check the texture format */
     const char *pszFormat = CSLFetchNameValue( papszOptions, "FORMAT" );
 
@@ -171,7 +166,7 @@ DDSDataset::CreateCopy(const char * pszFilename, GDALDataset *poSrcDS,
     if (pszQuality)
     {
         if (EQUAL(pszQuality, "SUPERFAST"))
-            dxt_quality = cCRNDXTQualitySuperFast;            
+            dxt_quality = cCRNDXTQualitySuperFast;
         else if (EQUAL(pszQuality, "FAST"))
             dxt_quality = cCRNDXTQualityFast;
         else if (EQUAL(pszQuality, "NORMAL"))
@@ -179,7 +174,7 @@ DDSDataset::CreateCopy(const char * pszFilename, GDALDataset *poSrcDS,
         else if (EQUAL(pszQuality, "BETTER"))
             dxt_quality = cCRNDXTQualityBetter;
         else if (EQUAL(pszQuality, "UBER"))
-            dxt_quality = cCRNDXTQualityUber;        
+            dxt_quality = cCRNDXTQualityUber;
         else
         {
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -189,28 +184,31 @@ DDSDataset::CreateCopy(const char * pszFilename, GDALDataset *poSrcDS,
         }
     }
 
+    int nXSize = poSrcDS->GetRasterXSize();
+    int nYSize = poSrcDS->GetRasterYSize();
+
     if ((nXSize%4!=0) || (nYSize%4!=0)) {
-      CPLError(CE_Warning, CPLE_AppDefined,
-               "Raster size is not a multiple of 4: %dx%d. "
-               "Extra rows/colums will be ignored during the compression.",
-               nXSize, nYSize);
+      CPLError( CE_Warning, CPLE_AppDefined,
+                "Raster size is not a multiple of 4: %dx%d. "
+                "Extra rows/columns will be ignored during the compression.",
+                nXSize, nYSize );
     }
-    
+
     crn_comp_params comp_params;
     comp_params.m_format = fmt;
     comp_params.m_dxt_quality = dxt_quality;
     comp_params.set_flag(cCRNCompFlagPerceptual, srgb_colorspace);
     comp_params.set_flag(cCRNCompFlagDXT1AForTransparency, dxt1a_transparency);
-    
+
     crn_block_compressor_context_t pContext = crn_create_block_compressor(comp_params);
-    
+
     /* -------------------------------------------------------------------- */
     /*      Write the DDS header to the file.                               */
     /* -------------------------------------------------------------------- */
 
     VSIFWriteL(&crnlib::cDDSFileSignature, 1,
                sizeof(crnlib::cDDSFileSignature), fpImage);
-    
+
     crnlib::DDSURFACEDESC2 ddsDesc;
     memset(&ddsDesc, 0, sizeof(ddsDesc));
     ddsDesc.dwSize = sizeof(ddsDesc);
@@ -218,7 +216,7 @@ DDSDataset::CreateCopy(const char * pszFilename, GDALDataset *poSrcDS,
     ddsDesc.dwWidth = nXSize;
     ddsDesc.dwHeight = nYSize;
     ddsDesc.dwMipMapCount = 1;
-    
+
     ddsDesc.ddpfPixelFormat.dwSize = sizeof(crnlib::DDPIXELFORMAT);
     ddsDesc.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
     ddsDesc.ddpfPixelFormat.dwFourCC = crn_get_format_fourcc(fmt);
@@ -226,19 +224,19 @@ DDSDataset::CreateCopy(const char * pszFilename, GDALDataset *poSrcDS,
 
     // Set pitch/linearsize field (some DDS readers require this field to be non-zero).
     uint bits_per_pixel = crn_get_format_bits_per_texel(fmt);
-    ddsDesc.lPitch = (((ddsDesc.dwWidth + 3) & ~3) * ((ddsDesc.dwHeight + 3) & ~3) * bits_per_pixel) >> 3;
+    ddsDesc.lPitch = (((ddsDesc.dwWidth + 3) & ~3U) * ((ddsDesc.dwHeight + 3) & ~3U) * bits_per_pixel) >> 3;
     ddsDesc.dwFlags |= DDSD_LINEARSIZE;
 
     /* Endianness problems when serializing structure?? dds on-disk format
        should be verified */
     VSIFWriteL(&ddsDesc, 1, sizeof(ddsDesc), fpImage);
-    
+
     /* -------------------------------------------------------------------- */
     /*      Loop over image, compressing image data.                        */
     /* -------------------------------------------------------------------- */
     const uint bytesPerBlock = crn_get_bytes_per_dxt_block(fmt);
     CPLErr eErr = CE_None;
-    const uint nYNumBlocks = (nYSize + cDXTBlockSize - 1) / cDXTBlockSize;  
+    const uint nYNumBlocks = (nYSize + cDXTBlockSize - 1) / cDXTBlockSize;
     const uint num_blocks_x = (nXSize + cDXTBlockSize - 1) / cDXTBlockSize;
     const uint total_compressed_size = num_blocks_x * bytesPerBlock;
 
@@ -253,16 +251,16 @@ DDSDataset::CreateCopy(const char * pszFilename, GDALDataset *poSrcDS,
     {
         const uint size_y = (iLine*cDXTBlockSize+cDXTBlockSize) < (uint)nYSize ?
                            cDXTBlockSize : (cDXTBlockSize-((iLine*cDXTBlockSize+cDXTBlockSize)-(uint)nYSize));
-        
-        eErr = poSrcDS->RasterIO(GF_Read, 0, iLine*cDXTBlockSize, nXSize, size_y, 
+
+        eErr = poSrcDS->RasterIO(GF_Read, 0, iLine*cDXTBlockSize, nXSize, size_y,
                                  pabyScanlines, nXSize, size_y, GDT_Byte,
                                  nBands, NULL,
-                                 nBands, 
+                                 nBands,
                                  nBands * nXSize, 1, NULL);
 
         if (eErr != CE_None)
             break;
-        
+
         crn_uint32 *pSrc_image = NULL;
         if (nColorType == DDS_COLOR_TYPE_RGB_ALPHA)
             pSrc_image = (crn_uint32*)pabyScanlines;
@@ -273,9 +271,9 @@ DDSDataset::CreateCopy(const char * pszFilename, GDALDataset *poSrcDS,
             {
                 int y = (i*3);
                 src_image[i] = (255<<24) | (pabyScanlines[y+2]<<16) | (pabyScanlines[y+1]<<8) |
-                  pabyScanlines[y];            
+                  pabyScanlines[y];
             }
-            
+
             pSrc_image = &(src_image[0]);
         }
 
@@ -293,7 +291,7 @@ DDSDataset::CreateCopy(const char * pszFilename, GDALDataset *poSrcDS,
                     *pDst_pixels++ = pSrc_image[actual_x + actual_y * nXSize];
                 }
             }
-            
+
             // Compress the DXTn block.
             crn_compress_block(pContext, pixels, static_cast<crn_uint8 *>(pCompressed_data) + block_x * bytesPerBlock);
         }
@@ -318,14 +316,14 @@ DDSDataset::CreateCopy(const char * pszFilename, GDALDataset *poSrcDS,
     CPLFree(pabyScanlines);
     crn_free_block_compressor(pContext);
     pContext = NULL;
-   
+
     VSIFCloseL(fpImage);
 
     if (eErr != CE_None)
         return NULL;
 
     DDSDataset *poDsDummy = new DDSDataset();
-    
+
     return poDsDummy;
 }
 
@@ -335,42 +333,40 @@ DDSDataset::CreateCopy(const char * pszFilename, GDALDataset *poSrcDS,
 
 void GDALRegister_DDS()
 {
-    GDALDriver	*poDriver;
-
-    if (GDALGetDriverByName( "DDS" ) == NULL)
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription("DDS");
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, 
-                                  "DirectDraw Surface");
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#DDS" );        
-        poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "dds");
-        poDriver->SetMetadataItem(GDAL_DMD_MIMETYPE, "image/dds");
-
-        poDriver->SetMetadataItem(GDAL_DMD_CREATIONOPTIONLIST, 
-                                  "<CreationOptionList>\n"
-                                  "   <Option name='FORMAT' type='string-select' description='Texture format' default='DXT3'>\n"
-                                  "     <Value>DXT1</Value>\n"
-                                  "     <Value>DXT1A</Value>\n"
-                                  "     <Value>DXT3</Value>\n"
-                                  "     <Value>DXT5</Value>\n" 
-                                  "     <Value>ETC1</Value>\n"                                                                     
-                                  "   </Option>\n"
-                                  "   <Option name='QUALITY' type='string-select' description='Compression Quality' default='NORMAL'>\n"
-                                  "     <Value>SUPERFAST</Value>\n"
-                                  "     <Value>FAST</Value>\n"
-                                  "     <Value>NORMAL</Value>\n"
-                                  "     <Value>BETTER</Value>\n"
-                                  "     <Value>UBER</Value>\n"                                                                                                      
-                                  "   </Option>\n"                                  
-                                  "</CreationOptionList>\n" );
-
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-        
-        poDriver->pfnCreateCopy = DDSDataset::CreateCopy;
-        
-        GetGDALDriverManager()->RegisterDriver(poDriver);
-    }
+    if( GDALGetDriverByName( "DDS" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription("DDS");
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
+                              "DirectDraw Surface");
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#DDS" );
+    poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "dds");
+    poDriver->SetMetadataItem(GDAL_DMD_MIMETYPE, "image/dds");
+
+    poDriver->SetMetadataItem(
+        GDAL_DMD_CREATIONOPTIONLIST,
+        "<CreationOptionList>\n"
+        "   <Option name='FORMAT' type='string-select' description='Texture format' default='DXT3'>\n"
+        "     <Value>DXT1</Value>\n"
+        "     <Value>DXT1A</Value>\n"
+        "     <Value>DXT3</Value>\n"
+        "     <Value>DXT5</Value>\n"
+        "     <Value>ETC1</Value>\n"
+        "   </Option>\n"
+        "   <Option name='QUALITY' type='string-select' description='Compression Quality' default='NORMAL'>\n"
+        "     <Value>SUPERFAST</Value>\n"
+        "     <Value>FAST</Value>\n"
+        "     <Value>NORMAL</Value>\n"
+        "     <Value>BETTER</Value>\n"
+        "     <Value>UBER</Value>\n"
+        "   </Option>\n"
+        "</CreationOptionList>\n" );
+
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->pfnCreateCopy = DDSDataset::CreateCopy;
+
+    GetGDALDriverManager()->RegisterDriver(poDriver);
 }
diff --git a/frmts/dimap/dimapdataset.cpp b/frmts/dimap/dimapdataset.cpp
index 1c5f936..a923f20 100644
--- a/frmts/dimap/dimapdataset.cpp
+++ b/frmts/dimap/dimapdataset.cpp
@@ -6,7 +6,7 @@
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  * Docs: http://www.spotimage.fr/dimap/spec/documentation/refdoc.htm
- * 
+ *
  ******************************************************************************
  * Copyright (c) 2007, Frank Warmerdam <warmerdam at pobox.com>
  * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
@@ -30,16 +30,13 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
 #include "cpl_minixml.h"
-#include "ogr_spatialref.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
 #include "gdal_proxy.h"
+#include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: dimapdataset.cpp 27942 2014-11-11 00:57:41Z rouault $");
-
-CPL_C_START
-void    GDALRegister_DIMAP(void);
-CPL_C_END
+CPL_CVSID("$Id: dimapdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -69,7 +66,7 @@ class DIMAPDataset : public GDALPamDataset
     CPLString     osImageDSFilename;
     CPLString     osDIMAPFilename;
     int           nProductVersion;
-    
+
     char          **papszXMLDimapMetadata;
 
   protected:
@@ -78,11 +75,11 @@ class DIMAPDataset : public GDALPamDataset
     int ReadImageInformation();
     int ReadImageInformation2(); /* DIMAP 2 */
 
-    void SetMetadataFromXML(CPLXMLNode *psProduct, const char *apszMetadataTranslation[]);
+    void SetMetadataFromXML(CPLXMLNode *psProduct, const char * const apszMetadataTranslation[]);
   public:
             DIMAPDataset();
             ~DIMAPDataset();
-    
+
     virtual const char *GetProjectionRef(void);
     virtual CPLErr GetGeoTransform( double * );
     virtual int    GetGCPCount();
@@ -111,9 +108,9 @@ class DIMAPWrapperRasterBand : public GDALProxyRasterBand
     virtual GDALRasterBand* RefUnderlyingRasterBand() { return poBaseBand; }
 
   public:
-    DIMAPWrapperRasterBand( GDALRasterBand* poBaseBand )
+    DIMAPWrapperRasterBand( GDALRasterBand* poBaseBandIn )
         {
-            this->poBaseBand = poBaseBand;
+            this->poBaseBand = poBaseBandIn;
             eDataType = poBaseBand->GetRasterDataType();
             poBaseBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
         }
@@ -129,23 +126,18 @@ class DIMAPWrapperRasterBand : public GDALProxyRasterBand
 /*                             DIMAPDataset()                            */
 /************************************************************************/
 
-DIMAPDataset::DIMAPDataset()
+DIMAPDataset::DIMAPDataset() :
+    psProduct(NULL),
+    psProductDim(NULL),
+    psProductStrip(NULL),
+    poImageDS(NULL),
+    nGCPCount(0),
+    pasGCPList(NULL),
+    bHaveGeoTransform(FALSE),
+    nProductVersion(1),
+    papszXMLDimapMetadata(NULL)
 {
-    psProduct = NULL;
-
-    psProductDim = NULL;
-    psProductStrip = NULL;
-
-    nGCPCount = 0;
-    pasGCPList = NULL;
     pszGCPProjection = CPLStrdup("");
-
-    poImageDS = NULL;
-    bHaveGeoTransform = FALSE;
-
-    nProductVersion = 1;
-
-    papszXMLDimapMetadata = NULL;
 }
 
 /************************************************************************/
@@ -196,8 +188,7 @@ int DIMAPDataset::CloseDependentDatasets()
 /*      Disconnect the bands so our destructor doesn't try and          */
 /*      delete them since they really belonged to poImageDS.            */
 /* -------------------------------------------------------------------- */
-    int iBand;
-    for( iBand = 0; iBand < nBands; iBand++ )
+    for( int iBand = 0; iBand < nBands; iBand++ )
         delete papoBands[iBand];
     nBands = 0;
 
@@ -234,8 +225,8 @@ char **DIMAPDataset::GetMetadata( const char *pszDomain )
         }
         return papszXMLDimapMetadata;
     }
-    else
-        return GDALPamDataset::GetMetadata( pszDomain );
+
+    return GDALPamDataset::GetMetadata( pszDomain );
 }
 
 /************************************************************************/
@@ -247,8 +238,8 @@ const char *DIMAPDataset::GetProjectionRef()
 {
     if( strlen(osProjection) > 0 )
         return osProjection;
-    else
-        return GDALPamDataset::GetProjectionRef();
+
+    return GDALPamDataset::GetProjectionRef();
 }
 
 /************************************************************************/
@@ -263,8 +254,8 @@ CPLErr DIMAPDataset::GetGeoTransform( double *padfGeoTransform )
         memcpy( padfGeoTransform, adfGeoTransform, sizeof(double)*6 );
         return CE_None;
     }
-    else
-        return GDALPamDataset::GetGeoTransform( padfGeoTransform );
+
+    return GDALPamDataset::GetGeoTransform( padfGeoTransform );
 }
 
 /************************************************************************/
@@ -280,7 +271,7 @@ char **DIMAPDataset::GetFileList()
     papszFileList = CSLInsertStrings( papszFileList, -1, papszImageFiles );
 
     CSLDestroy( papszImageFiles );
-    
+
     return papszFileList;
 }
 
@@ -293,9 +284,9 @@ int DIMAPDataset::Identify( GDALOpenInfo * poOpenInfo )
 {
     if( poOpenInfo->nHeaderBytes >= 100 )
     {
-      if( ( strstr((const char *) poOpenInfo->pabyHeader, 
+      if( ( strstr((const char *) poOpenInfo->pabyHeader,
                    "<Dimap_Document" ) == NULL ) &&
-          ( strstr((const char *) poOpenInfo->pabyHeader, 
+          ( strstr((const char *) poOpenInfo->pabyHeader,
                    "<PHR_DIMAP_Document" ) == NULL ) )
             return FALSE;
         else
@@ -303,35 +294,34 @@ int DIMAPDataset::Identify( GDALOpenInfo * poOpenInfo )
     }
     else if( poOpenInfo->bIsDirectory )
     {
-        VSIStatBufL sStat;
-
         /* DIMAP file */
-        CPLString osMDFilename = 
+        CPLString osMDFilename =
             CPLFormCIFilename( poOpenInfo->pszFilename, "METADATA.DIM", NULL );
-        
+
+        VSIStatBufL sStat;
         if( VSIStatL( osMDFilename, &sStat ) == 0 )
         {
             /* Make sure this is really a Dimap format */
             GDALOpenInfo  oOpenInfo( osMDFilename, GA_ReadOnly, NULL );
             if( oOpenInfo.nHeaderBytes >= 100 )
             {
-                if( strstr((const char *) oOpenInfo.pabyHeader, 
+                if( strstr((const char *) oOpenInfo.pabyHeader,
                            "<Dimap_Document" ) == NULL )
                     return FALSE;
-                else
-                    return TRUE;
+
+                return TRUE;
             }
         }
         else
         {
             /* DIMAP 2 file */
-            osMDFilename = 
+            osMDFilename =
                     CPLFormCIFilename( poOpenInfo->pszFilename, "VOL_PHR.XML", NULL );
-            
+
             if( VSIStatL( osMDFilename, &sStat ) == 0 )
                     return TRUE;
-            else
-                    return FALSE;
+
+            return FALSE;
         }
     }
 
@@ -345,17 +335,15 @@ int DIMAPDataset::Identify( GDALOpenInfo * poOpenInfo )
 GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    int nProductVersion = 1;
-
     if( !Identify( poOpenInfo ) )
         return NULL;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The DIMAP driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
@@ -369,12 +357,12 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
     {
         VSIStatBufL sStat;
 
-        osMDFilename = 
+        osMDFilename =
             CPLFormCIFilename( poOpenInfo->pszFilename, "METADATA.DIM", NULL );
 
         /* DIMAP2 */
         if( VSIStatL( osMDFilename, &sStat ) != 0 )
-        osMDFilename = 
+        osMDFilename =
                 CPLFormCIFilename( poOpenInfo->pszFilename, "VOL_PHR.XML", NULL );
     }
     else
@@ -383,12 +371,9 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Ingest the xml file.                                            */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psProduct, *psImageAttributes;
     CPLXMLNode *psProductDim = NULL, *psProductStrip = NULL;
 
-    float nMetadataFormatVersion;
-
-    psProduct = CPLParseXMLFile( osMDFilename );
+    CPLXMLNode *psProduct = CPLParseXMLFile( osMDFilename );
     if( psProduct == NULL )
         return NULL;
 
@@ -398,20 +383,26 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
 
     /* We check the for the tag Metadata_Identification.METADATA_FORMAT.
     *  The metadata will be set to 2.0 for DIMAP2 */
-    nMetadataFormatVersion = CPLAtof( CPLGetXMLValue(CPLGetXMLNode(psDoc, "Metadata_Identification.METADATA_FORMAT"), 
-                        "version", "1") );
-    if( nMetadataFormatVersion >= 2.0 )
+    int nProductVersion = 1;
+
+    double dfMetadataFormatVersion
+        = CPLAtof( CPLGetXMLValue(
+            CPLGetXMLNode(psDoc, "Metadata_Identification.METADATA_FORMAT"),
+            "version", "1") );
+
+    if( dfMetadataFormatVersion >= 2.0 )
     {
         nProductVersion = 2;
     }
-    
-    /* Check needed information for the DIMAP format */ 
+
+    /* Check needed information for the DIMAP format */
     if (nProductVersion == 1)
     {
-        psImageAttributes = CPLGetXMLNode( psDoc, "Raster_Dimensions" );
+        CPLXMLNode *psImageAttributes
+            = CPLGetXMLNode( psDoc, "Raster_Dimensions" );
         if( psImageAttributes == NULL )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
+            CPLError( CE_Failure, CPLE_OpenFailed,
                 "Failed to find <Raster_Dimensions> in document." );
             CPLDestroyXMLNode(psProduct);
             return NULL;
@@ -424,21 +415,21 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
 
         if( psDatasetComponents == NULL )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
+            CPLError( CE_Failure, CPLE_OpenFailed,
                 "Failed to find <Dataset_Components> in document." );
             CPLDestroyXMLNode(psProduct);
             return NULL;
         }
-        
+
         CPLXMLNode *psDatasetComponent = psDatasetComponents->psChild;
 
-        if( CPLGetXMLNode(psDoc, "Raster_Data") ) 
+        if( CPLGetXMLNode(psDoc, "Raster_Data") )
         {
-            osDIMAPFilename = osMDFilename; 
+            osDIMAPFilename = osMDFilename;
         }
 
         for( ; osDIMAPFilename.size() == 0 && psDatasetComponent != NULL;
-                psDatasetComponent = psDatasetComponent->psNext ) 
+                psDatasetComponent = psDatasetComponent->psNext )
         {
             const char* pszComponentType = CPLGetXMLValue(psDatasetComponent, "COMPONENT_TYPE","");
             if( strcmp(pszComponentType, "DIMAP") == 0 )
@@ -450,24 +441,24 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
                 {
                     if( poOpenInfo->bIsDirectory )
                     {
-                        osDIMAPFilename = 
+                        osDIMAPFilename =
                             CPLFormCIFilename( poOpenInfo->pszFilename, pszHref, NULL );
                     }
                     else
                     {
                         CPLString osPath = CPLGetPath(osMDFilename);
-                        osDIMAPFilename = 
+                        osDIMAPFilename =
                             CPLFormFilename( osPath, pszHref, NULL );
                     }
-                
+
                     /* Data file might be specified there */
                     const char *pszDataFileHref = CPLGetXMLValue(
                         psDatasetComponent, "Data_Files.Data_File.DATA_FILE_PATH.href", "" );
-                    
+
                     if( strlen(pszDataFileHref) > 0 )
                     {
                         CPLString osPath = CPLGetPath(osMDFilename);
-                        osImageDSFilename = 
+                        osImageDSFilename =
                             CPLFormFilename( osPath, pszDataFileHref, NULL );
                     }
 
@@ -493,21 +484,21 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
         {
             CPLString osSTRIPFilename;
             CPLXMLNode *psDatasetSource = psDatasetSources->psChild;
-            
-            for( ; psDatasetSource != NULL; psDatasetSource = psDatasetSource->psNext ) 
+
+            for( ; psDatasetSource != NULL; psDatasetSource = psDatasetSource->psNext )
             {
                 const char* pszSourceType = CPLGetXMLValue(psDatasetSource, "SOURCE_TYPE","");
                 if( strcmp(pszSourceType, "Strip_Source") == 0 )
                 {
                     const char *pszHref = CPLGetXMLValue(
                         psDatasetSource, "Component.COMPONENT_PATH.href", "" );
-                    
+
                     if( strlen(pszHref) > 0 ) /* STRIP product found*/
                     {
                         CPLString osPath = CPLGetPath(osDIMAPFilename);
-                        osSTRIPFilename = 
+                        osSTRIPFilename =
                             CPLFormCIFilename( osPath, pszHref, NULL );
-                        
+
                         break;
                     }
                 }
@@ -528,14 +519,14 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->nProductVersion = nProductVersion;
     poDS->osMDFilename = osMDFilename;
     poDS->osImageDSFilename = osImageDSFilename;
-    poDS->osDIMAPFilename = osDIMAPFilename;    
+    poDS->osDIMAPFilename = osDIMAPFilename;
 
     int res = TRUE;
     if( nProductVersion == 2 )
         res = poDS->ReadImageInformation2();
     else
         res = poDS->ReadImageInformation();
-    
+
     if( res == FALSE )
     {
         delete poDS;
@@ -562,13 +553,13 @@ int DIMAPDataset::ReadImageInformation()
 /*      Get overall image information.                                  */
 /* -------------------------------------------------------------------- */
 #ifdef DEBUG
-    int nBands = 
+    int l_nBands =
         atoi(CPLGetXMLValue( psImageAttributes, "NBANDS", "-1" ));
 #endif
 
-    nRasterXSize = 
+    nRasterXSize =
         atoi(CPLGetXMLValue( psImageAttributes, "NCOLS", "-1" ));
-    nRasterYSize = 
+    nRasterYSize =
         atoi(CPLGetXMLValue( psImageAttributes, "NROWS", "-1" ));
 
 /* -------------------------------------------------------------------- */
@@ -578,9 +569,9 @@ int DIMAPDataset::ReadImageInformation()
     const char *pszHref = CPLGetXMLValue(
         psDoc, "Data_Access.Data_File.DATA_FILE_PATH.href", "" );
     CPLString osPath = CPLGetPath(osMDFilename);
-    CPLString osImageFilename = 
+    CPLString osImageFilename =
         CPLFormFilename( osPath, pszHref, NULL );
-                                   
+
 /* -------------------------------------------------------------------- */
 /*      Try and open the file.                                          */
 /* -------------------------------------------------------------------- */
@@ -594,16 +585,15 @@ int DIMAPDataset::ReadImageInformation()
 /* -------------------------------------------------------------------- */
 /*      Attach the bands.                                               */
 /* -------------------------------------------------------------------- */
-    int iBand;
-    CPLAssert( nBands == poImageDS->GetRasterCount() );
+    CPLAssert( l_nBands == poImageDS->GetRasterCount() );
 
-    for( iBand = 1; iBand <= poImageDS->GetRasterCount(); iBand++ )
+    for( int iBand = 1; iBand <= poImageDS->GetRasterCount(); iBand++ )
         SetBand( iBand, new DIMAPWrapperRasterBand(poImageDS->GetRasterBand( iBand )) );
 
 /* -------------------------------------------------------------------- */
 /*      Try to collect simple insertion point.                          */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psGeoLoc =  
+    CPLXMLNode *psGeoLoc =
         CPLGetXMLNode( psDoc, "Geoposition.Geoposition_Insert" );
 
     if( psGeoLoc != NULL )
@@ -618,9 +608,9 @@ int DIMAPDataset::ReadImageInformation()
     }
     else
     {
-        // Try to get geotransform from underlying raster. 
-        if ( poImageDS->GetGeoTransform(adfGeoTransform) == CE_None ) 
-            bHaveGeoTransform = TRUE; 
+        // Try to get geotransform from underlying raster.
+        if ( poImageDS->GetGeoTransform(adfGeoTransform) == CE_None )
+            bHaveGeoTransform = TRUE;
     }
 
 /* -------------------------------------------------------------------- */
@@ -641,34 +631,34 @@ int DIMAPDataset::ReadImageInformation()
                 nGCPCount++ ;
         }
 
-        pasGCPList = (GDAL_GCP *) 
+        pasGCPList = (GDAL_GCP *)
             CPLCalloc(sizeof(GDAL_GCP),nGCPCount);
-        
+
         nGCPCount = 0;
-        
+
         for( psNode = psGeoLoc->psChild; psNode != NULL;
              psNode = psNode->psNext )
         {
             char    szID[32];
             GDAL_GCP   *psGCP = pasGCPList + nGCPCount;
-            
+
             if( !EQUAL(psNode->pszValue,"Tie_Point") )
                 continue;
 
             nGCPCount++ ;
 
-            sprintf( szID, "%d", nGCPCount );
+            snprintf( szID, sizeof(szID), "%d", nGCPCount );
             psGCP->pszId = CPLStrdup( szID );
             psGCP->pszInfo = CPLStrdup("");
-            psGCP->dfGCPPixel = 
+            psGCP->dfGCPPixel =
                 CPLAtof(CPLGetXMLValue(psNode,"TIE_POINT_DATA_X","0"))-0.5;
-            psGCP->dfGCPLine = 
+            psGCP->dfGCPLine =
                 CPLAtof(CPLGetXMLValue(psNode,"TIE_POINT_DATA_Y","0"))-0.5;
-            psGCP->dfGCPX = 
+            psGCP->dfGCPX =
                 CPLAtof(CPLGetXMLValue(psNode,"TIE_POINT_CRS_X",""));
-            psGCP->dfGCPY = 
+            psGCP->dfGCPY =
                 CPLAtof(CPLGetXMLValue(psNode,"TIE_POINT_CRS_Y",""));
-            psGCP->dfGCPZ = 
+            psGCP->dfGCPZ =
                 CPLAtof(CPLGetXMLValue(psNode,"TIE_POINT_CRS_Z",""));
         }
     }
@@ -676,9 +666,9 @@ int DIMAPDataset::ReadImageInformation()
 /* -------------------------------------------------------------------- */
 /*      Collect the CRS.  For now we look only for EPSG codes.          */
 /* -------------------------------------------------------------------- */
-    const char *pszSRS = CPLGetXMLValue( 
-        psDoc, 
-        "Coordinate_Reference_System.Horizontal_CS.HORIZONTAL_CS_CODE", 
+    const char *pszSRS = CPLGetXMLValue(
+        psDoc,
+        "Coordinate_Reference_System.Horizontal_CS.HORIZONTAL_CS_CODE",
         NULL );
 
     if( pszSRS != NULL )
@@ -700,27 +690,27 @@ int DIMAPDataset::ReadImageInformation()
             }
         }
     }
-    else  
-    { 
-        // Check underlying raster for SRS. We have cases where 
-        // HORIZONTAL_CS_CODE is empty and the underlying raster 
+    else
+    {
+        // Check underlying raster for SRS. We have cases where
+        // HORIZONTAL_CS_CODE is empty and the underlying raster
         // is georeferenced (rprinceley).
-        if ( poImageDS->GetProjectionRef() ) 
-        { 
-            osProjection = poImageDS->GetProjectionRef(); 
-        } 
-    } 
+        if ( poImageDS->GetProjectionRef() )
+        {
+            osProjection = poImageDS->GetProjectionRef();
+        }
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Translate other metadata of interest.                           */
 /* -------------------------------------------------------------------- */
-    static const char *apszMetadataTranslation[] = 
+    static const char * const apszMetadataTranslation[] =
         {
-            "Production", "", 
-            "Production.Facility", "FACILITY_", 
+            "Production", "",
+            "Production.Facility", "FACILITY_",
             "Dataset_Sources.Source_Information.Scene_Source", "",
             "Data_Processing", "",
-            "Image_Interpretation.Spectral_Band_Info", "SPECTRAL_", 
+            "Image_Interpretation.Spectral_Band_Info", "SPECTRAL_",
             NULL, NULL
         };
 
@@ -730,7 +720,7 @@ int DIMAPDataset::ReadImageInformation()
 /*      Set Band metadata from the <Spectral_Band_Info> content         */
 /* -------------------------------------------------------------------- */
 
-    CPLXMLNode *psImageInterpretationNode = 
+    CPLXMLNode *psImageInterpretationNode =
         CPLGetXMLNode( psDoc, "Image_Interpretation" );
     if (psImageInterpretationNode != NULL)
     {
@@ -799,7 +789,7 @@ int DIMAPDataset::ReadImageInformation2()
     CPLXMLNode *psImageAttributes = CPLGetXMLNode( psDoc, "Raster_Data.Raster_Dimensions" );
     if( psImageAttributes == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
             "Failed to find <Raster_Dimensions> in document." );
         return FALSE;
     }
@@ -808,13 +798,13 @@ int DIMAPDataset::ReadImageInformation2()
 /*      Get overall image information.                                  */
 /* -------------------------------------------------------------------- */
 #ifdef DEBUG
-    int nBands = 
+    int l_nBands =
         atoi(CPLGetXMLValue( psImageAttributes, "NBANDS", "-1" ));
 #endif
 
-    nRasterXSize = 
+    nRasterXSize =
         atoi(CPLGetXMLValue( psImageAttributes, "NCOLS", "-1" ));
-    nRasterYSize = 
+    nRasterYSize =
         atoi(CPLGetXMLValue( psImageAttributes, "NROWS", "-1" ));
 
 /* -------------------------------------------------------------------- */
@@ -829,12 +819,12 @@ int DIMAPDataset::ReadImageInformation2()
         if( strlen(pszHref) > 0 )
         {
             CPLString osPath = CPLGetPath( osDIMAPFilename );
-            osImageDSFilename = 
+            osImageDSFilename =
                 CPLFormCIFilename( osPath, pszHref, NULL );
         }
         else
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
+            CPLError( CE_Failure, CPLE_OpenFailed,
                 "Failed to find <DATA_FILE_PATH> in document." );
             return FALSE;
         }
@@ -854,16 +844,15 @@ int DIMAPDataset::ReadImageInformation2()
 /* -------------------------------------------------------------------- */
 /*      Attach the bands.                                               */
 /* -------------------------------------------------------------------- */
-    int iBand;
-    CPLAssert( nBands == poImageDS->GetRasterCount() );
+    CPLAssert( l_nBands == poImageDS->GetRasterCount() );
 
-    for( iBand = 1; iBand <= poImageDS->GetRasterCount(); iBand++ )
+    for( int iBand = 1; iBand <= poImageDS->GetRasterCount(); iBand++ )
         SetBand( iBand, new DIMAPWrapperRasterBand(poImageDS->GetRasterBand( iBand )) );
 
 /* -------------------------------------------------------------------- */
 /*      Try to collect simple insertion point.                          */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psGeoLoc =  
+    CPLXMLNode *psGeoLoc =
         CPLGetXMLNode( psDoc, "Geoposition.Geoposition_Insert" );
 
     if( psGeoLoc != NULL )
@@ -878,22 +867,22 @@ int DIMAPDataset::ReadImageInformation2()
     }
     else
     {
-        // Try to get geotransform from underlying raster. 
-        if ( poImageDS->GetGeoTransform(adfGeoTransform) == CE_None ) 
-            bHaveGeoTransform = TRUE; 
+        // Try to get geotransform from underlying raster.
+        if ( poImageDS->GetGeoTransform(adfGeoTransform) == CE_None )
+            bHaveGeoTransform = TRUE;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Collect the CRS.  For now we look only for EPSG codes.          */
 /* -------------------------------------------------------------------- */
-    const char *pszSRS = CPLGetXMLValue( 
-        psDoc, 
-        "Coordinate_Reference_System.Projected_CRS.PROJECTED_CRS_CODE", 
+    const char *pszSRS = CPLGetXMLValue(
+        psDoc,
+        "Coordinate_Reference_System.Projected_CRS.PROJECTED_CRS_CODE",
         NULL );
     if( pszSRS == NULL )
-        pszSRS = CPLGetXMLValue( 
-            psDoc, 
-            "Coordinate_Reference_System.Geodetic_CRS.GEODETIC_CRS_CODE", 
+        pszSRS = CPLGetXMLValue(
+            psDoc,
+            "Coordinate_Reference_System.Geodetic_CRS.GEODETIC_CRS_CODE",
             NULL );
 
     if( pszSRS != NULL )
@@ -915,25 +904,25 @@ int DIMAPDataset::ReadImageInformation2()
             }
         }
     }
-    else  
-    { 
-        // Check underlying raster for SRS. We have cases where 
-        // HORIZONTAL_CS_CODE is empty and the underlying raster 
+    else
+    {
+        // Check underlying raster for SRS. We have cases where
+        // HORIZONTAL_CS_CODE is empty and the underlying raster
         // is georeferenced (rprinceley).
-        if ( poImageDS->GetProjectionRef() ) 
-        { 
-            osProjection = poImageDS->GetProjectionRef(); 
-        } 
-    } 
+        if ( poImageDS->GetProjectionRef() )
+        {
+            osProjection = poImageDS->GetProjectionRef();
+        }
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Translate other metadata of interest: DIM_<product_name>.XML    */
 /* -------------------------------------------------------------------- */
 
-    static const char *apszMetadataTranslationDim[] = 
+    static const char * const apszMetadataTranslationDim[] =
     {
         "Product_Information.Delivery_Identification", "DATASET_",
-            "Product_Information.Producer_Information", "DATASET_",  
+            "Product_Information.Producer_Information", "DATASET_",
         "Dataset_Sources.Source_Identification.Strip_Source", "",
         "Processing_Information.Production_Facility", "FACILITY_",
         "Processing_Information.Product_Settings", "",
@@ -948,7 +937,7 @@ int DIMAPDataset::ReadImageInformation2()
 /*      Translate other metadata of interest: STRIP_<product_name>.XML    */
 /* -------------------------------------------------------------------- */
 
-    static const char *apszMetadataTranslationStrip[] = 
+    static const char * const apszMetadataTranslationStrip[] =
     {
         "Catalog.Full_Strip.Notations.Cloud_And_Quality_Notation.Data_Strip_Notation", "CLOUDCOVER_",
         "Acquisition_Configuration.Platform_Configuration.Ephemeris_Configuration", "EPHEMERIS_",
@@ -962,9 +951,9 @@ int DIMAPDataset::ReadImageInformation2()
 /*      Set Band metadata from the <Band_Radiance> and                  */
 /*                                <Band_Spectral_Range> content         */
 /* -------------------------------------------------------------------- */
-    
-    CPLXMLNode *psImageInterpretationNode = 
-        CPLGetXMLNode( psDoc, 
+
+    CPLXMLNode *psImageInterpretationNode =
+        CPLGetXMLNode( psDoc,
                     "Radiometric_Data.Radiometric_Calibration.Instrument_Calibration.Band_Measurement_List" );
     if (psImageInterpretationNode != NULL)
     {
@@ -977,7 +966,7 @@ int DIMAPDataset::ReadImageInformation2()
                  EQUAL(psSpectralBandInfoNode->pszValue, "Band_Solar_Irradiance")))
             {
                 CPLString osName;
-            
+
                 if (EQUAL(psSpectralBandInfoNode->pszValue, "Band_Radiance"))
                     osName = "RADIANCE_";
                 else if (EQUAL(psSpectralBandInfoNode->pszValue, "Band_Spectral_Range"))
@@ -995,17 +984,17 @@ int DIMAPDataset::ReadImageInformation2()
                         if (EQUAL(psTag->pszValue, "BAND_ID"))
                         {
                             /* BAND_ID is: B0, B1, .... P */
-                            if (!EQUAL(psTag->psChild->pszValue, "P")) 
+                            if (!EQUAL(psTag->psChild->pszValue, "P"))
                             {
-                                if (strlen(psTag->psChild->pszValue) < 2) /* shouldn't happen */
+                                if (strlen(psTag->psChild->pszValue) < 2) /* should not happen */
                                 {
                                     CPLError(CE_Warning, CPLE_AppDefined,
                                         "Bad BAND_INDEX value : %s", psTag->psChild->pszValue);
                                     nBandIndex = 0;
                                 }
-                                else 
+                                else
                                 {
-                                    nBandIndex = atoi(&psTag->psChild->pszValue[1]) + 1; 
+                                    nBandIndex = atoi(&psTag->psChild->pszValue[1]) + 1;
                                     if (nBandIndex <= 0 ||
                                     nBandIndex > poImageDS->GetRasterCount())
                                     {
@@ -1051,36 +1040,34 @@ int DIMAPDataset::ReadImageInformation2()
 /*                          SetMetadataFromXML()                        */
 /************************************************************************/
 
-void DIMAPDataset::SetMetadataFromXML(CPLXMLNode *psProduct, const char *apszMetadataTranslation[])
+void DIMAPDataset::SetMetadataFromXML(CPLXMLNode *psProductIn, const char * const apszMetadataTranslation[])
 {
-    CPLXMLNode *psDoc = CPLGetXMLNode( psProduct, "=Dimap_Document" );
-    if( psDoc == NULL ) 
+    CPLXMLNode *psDoc = CPLGetXMLNode( psProductIn, "=Dimap_Document" );
+    if( psDoc == NULL )
     {
-      psDoc = CPLGetXMLNode( psProduct, "=PHR_DIMAP_Document" );
+      psDoc = CPLGetXMLNode( psProductIn, "=PHR_DIMAP_Document" );
     }
 
-    int iTrItem;
-    
-    for( iTrItem = 0; apszMetadataTranslation[iTrItem] != NULL; iTrItem += 2 )
+    for( int iTrItem = 0; apszMetadataTranslation[iTrItem] != NULL; iTrItem += 2 )
     {
-        CPLXMLNode *psParent = 
+        CPLXMLNode *psParent =
             CPLGetXMLNode( psDoc, apszMetadataTranslation[iTrItem] );
 
         if( psParent == NULL )
             continue;
 
-        // hackey logic to support directly access a name/value entry
-        // or a parent element with many name/values. 
+        // Hackey logic to support directly access a name/value entry
+        // or a parent element with many name/values.
 
         CPLXMLNode *psTarget;
-        if( psParent->psChild != NULL 
+        if( psParent->psChild != NULL
             && psParent->psChild->eType == CXT_Text )
             psTarget = psParent;
         else
             psTarget = psParent->psChild;
 
-        for( ; psTarget != NULL && psTarget != psParent; 
-             psTarget = psTarget->psNext ) 
+        for( ; psTarget != NULL && psTarget != psParent;
+             psTarget = psTarget->psNext )
         {
             if( psTarget->eType == CXT_Element
                 && psTarget->psChild != NULL)
@@ -1096,7 +1083,7 @@ void DIMAPDataset::SetMetadataFromXML(CPLXMLNode *psProduct, const char *apszMet
                 {
                     /* find the tag value, at the end of the attributes */
                     CPLXMLNode *psNode = psTarget->psChild;
-                    for( ; psNode != NULL;  psNode = psNode->psNext ) 
+                    for( ; psNode != NULL;  psNode = psNode->psNext )
                     {
                         if (psNode->eType == CXT_Attribute)
                             continue;
@@ -1107,7 +1094,7 @@ void DIMAPDataset::SetMetadataFromXML(CPLXMLNode *psProduct, const char *apszMet
                         }
                     }
                 }
-            } 
+            }
         }
     }
 }
@@ -1149,24 +1136,21 @@ const GDAL_GCP *DIMAPDataset::GetGCPs()
 void GDALRegister_DIMAP()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "DIMAP" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "DIMAP" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "DIMAP" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "SPOT DIMAP" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#DIMAP" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = DIMAPDataset::Open;
-        poDriver->pfnIdentify = DIMAPDataset::Identify;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
-}
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "DIMAP" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "SPOT DIMAP" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_various.html#DIMAP" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
+    poDriver->pfnOpen = DIMAPDataset::Open;
+    poDriver->pfnIdentify = DIMAPDataset::Identify;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/frmts/dods/dodsdataset2.cpp b/frmts/dods/dodsdataset2.cpp
index 4100081..f046f70 100644
--- a/frmts/dods/dodsdataset2.cpp
+++ b/frmts/dods/dodsdataset2.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dodsdataset2.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: dodsdataset2.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  OPeNDAP Raster Driver
  * Purpose:  Implements DODSDataset and DODSRasterBand classes.
@@ -65,21 +65,18 @@
 #include <Error.h>
 #include <escaping.h>
 
-#include "gdal_priv.h"		// GDAL
-#include "ogr_spatialref.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "gdal_priv.h"
+#include "ogr_spatialref.h"
 
 using namespace libdap;
 
-CPL_CVSID("$Id: dodsdataset2.cpp 27942 2014-11-11 00:57:41Z rouault $");
-
-CPL_C_START
-void GDALRegister_DODS(void);
-CPL_C_END
+CPL_CVSID("$Id: dodsdataset2.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 /** Attribute names used to encode geo-referencing information. Note that
     these are not C++ objects to avoid problems with static global
-    constructors. 
+    constructors.
 
     @see get_geo_info
 
@@ -149,11 +146,11 @@ static string StripQuotes( string oInput )
 
     oInput = oInput.substr(1,oInput.length()-2);
 
-    pszResult = CPLUnescapeString( oInput.c_str(), NULL, 
+    pszResult = CPLUnescapeString( oInput.c_str(), NULL,
                                    CPLES_BackslashQuotable );
 
     oInput = pszResult;
-    
+
     CPLFree( pszResult );
 
     return oInput;
@@ -186,7 +183,7 @@ static int GetDimension( string oCE, const char *pszDimName,
         if( pszCE[i] == '[' && pszCE[i+1] == pszDimName[0] )
             return iCount;
 
-        else if( pszCE[i] == '[' 
+        else if( pszCE[i] == '['
                  && pszCE[i+1] == '-'
                  && pszCE[i+2] == pszDimName[0] )
         {
@@ -224,8 +221,8 @@ private:
 
     AISConnect *connect_to_server() throw(Error);
 
-    static string      SubConstraint( string raw_constraint, 
-                                      string x_constraint, 
+    static string      SubConstraint( string raw_constraint,
+                                      string x_constraint,
                                       string y_constraint );
 
     char            **CollectBandsFromDDS();
@@ -235,7 +232,7 @@ private:
     void            HarvestDAS();
     static void     HarvestMetadata( GDALMajorObject *, AttrTable * );
     void            HarvestMaps( string oVarName, string oCE );
-    
+
     friend class DODSRasterBand;
 
 public:
@@ -264,10 +261,10 @@ public:
 /* ==================================================================== */
 /************************************************************************/
 
-class DODSRasterBand : public GDALRasterBand 
+class DODSRasterBand : public GDALRasterBand
 {
 private:
-    string oVarName;          
+    string oVarName;
     string oCE;		        // Holds the CE (with [x] and [y] still there
 
     friend class DODSDataset;
@@ -288,7 +285,7 @@ private:
     void            HarvestDAS();
 
 public:
-    DODSRasterBand( DODSDataset *poDS, string oVarName, string oCE, 
+    DODSRasterBand( DODSDataset *poDS, string oVarName, string oCE,
                     int nOverviewFactor );
     virtual ~DODSRasterBand();
 
@@ -361,12 +358,12 @@ DODSDataset::connect_to_server() throw(Error)
 /*      the putenv() if there isn't already a DODS_CONF in the          */
 /*      environment.                                                    */
 /* -------------------------------------------------------------------- */
-    if( CPLGetConfigOption( "DODS_CONF", NULL ) != NULL 
+    if( CPLGetConfigOption( "DODS_CONF", NULL ) != NULL
         && getenv("DODS_CONF") == NULL )
     {
         static char szDODS_CONF[1000];
-            
-        sprintf( szDODS_CONF, "DODS_CONF=%.980s", 
+
+        snprintf( szDODS_CONF, sizeof(szDODS_CONF), "DODS_CONF=%.980s",
                  CPLGetConfigOption( "DODS_CONF", "" ) );
         putenv( szDODS_CONF );
     }
@@ -387,7 +384,7 @@ DODSDataset::connect_to_server() throw(Error)
     string version = poConnection->request_version();
     /*    if (version.empty() || version.find("/3.") == string::npos)
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "I connected to the URL but could not get a DAP 3.x version string\n"
                   "from the server.  I will continue to connect but access may fail.");
     }
@@ -402,8 +399,8 @@ DODSDataset::connect_to_server() throw(Error)
 /*      constraint string for the [x] and [y] parts.                    */
 /************************************************************************/
 
-string DODSDataset::SubConstraint( string raw_constraint, 
-                                   string x_constraint, 
+string DODSDataset::SubConstraint( string raw_constraint,
+                                   string x_constraint,
                                    string y_constraint )
 
 {
@@ -427,14 +424,14 @@ string DODSDataset::SubConstraint( string raw_constraint,
     CPLAssert( x_off != string::npos && y_off != string::npos );
 
     if( x_off < y_off )
-        final_constraint = 
+        final_constraint =
             raw_constraint.substr( 0, x_off )
             + x_constraint
             + raw_constraint.substr( x_off + x_len, y_off - x_off - x_len )
             + y_constraint
             + raw_constraint.substr( y_off + y_len );
     else
-        final_constraint = 
+        final_constraint =
             raw_constraint.substr( 0, y_off )
             + y_constraint
             + raw_constraint.substr( y_off + y_len, x_off - y_off - y_len )
@@ -456,8 +453,8 @@ string DODSDataset::SubConstraint( string raw_constraint,
 /*      candidates.  After the first we only accept additional          */
 /*      objects as bands if they match the size of the original.        */
 /*                                                                      */
-/*      Auto-recognision rules will presumably evolve over time to      */
-/*      recognise different common configurations and to support        */
+/*      Auto-recognition rules will presumably evolve over time to      */
+/*      recognize different common configurations and to support        */
 /*      more variations.                                                */
 /************************************************************************/
 
@@ -470,7 +467,7 @@ char **DODSDataset::CollectBandsFromDDS()
     for( v_i = poDDS->var_begin(); v_i != poDDS->var_end(); v_i++ )
     {
         BaseType *poVar = *v_i;
-        papszResultList = CollectBandsFromDDSVar( poVar->name(), 
+        papszResultList = CollectBandsFromDDSVar( poVar->name(),
                                                   papszResultList );
     }
 
@@ -487,13 +484,13 @@ char **DODSDataset::CollectBandsFromDDS()
 /*      needs a default constraint expression generated.                */
 /************************************************************************/
 
-char **DODSDataset::CollectBandsFromDDSVar( string oVarName, 
+char **DODSDataset::CollectBandsFromDDSVar( string oVarName,
                                             char **papszResultList )
 
 {
     Array *poArray;
     Grid *poGrid = NULL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Is this a grid or array?                                        */
 /* -------------------------------------------------------------------- */
@@ -524,10 +521,10 @@ char **DODSDataset::CollectBandsFromDDSVar( string oVarName,
 /* -------------------------------------------------------------------- */
     Array::Dim_iter dim1 = poArray->dim_begin() + 0;
     Array::Dim_iter dim2 = poArray->dim_begin() + 1;
-    
+
     int nDim1Size = poArray->dimension_size( dim1 );
     int nDim2Size = poArray->dimension_size( dim2 );
-    
+
     if( nDim1Size == 1 || nDim2Size == 1 )
         return papszResultList;
 
@@ -548,19 +545,19 @@ char **DODSDataset::CollectBandsFromDDSVar( string oVarName,
         iXDim = 1;
         iYDim = 0;
     }
-    else if( EQUALN(dim1_name.c_str(),"lat",3) 
-             && EQUALN(dim2_name.c_str(),"lon",3) )
+    else if( STARTS_WITH_CI(dim1_name.c_str(), "lat")
+             && STARTS_WITH_CI(dim2_name.c_str(), "lon") )
     {
         iXDim = 0;
         iYDim = 1;
     }
-    else if( EQUALN(dim1_name.c_str(),"lon",3) 
-             && EQUALN(dim2_name.c_str(),"lat",3) )
+    else if( STARTS_WITH_CI(dim1_name.c_str(), "lon")
+             && STARTS_WITH_CI(dim2_name.c_str(), "lat") )
     {
         iXDim = 1;
         iYDim = 0;
     }
-    else 
+    else
     {
         iYDim = 0;
         iXDim = 1;
@@ -594,9 +591,9 @@ char **DODSDataset::CollectBandsFromDDSVar( string oVarName,
     else
         return papszResultList;
 
-    papszResultList = CSLAddString( papszResultList, 
+    papszResultList = CSLAddString( papszResultList,
                                     poVar->name().c_str() );
-    papszResultList = CSLAddString( papszResultList, 
+    papszResultList = CSLAddString( papszResultList,
                                     oConstraint.c_str() );
 
     return papszResultList;
@@ -630,7 +627,7 @@ char **DODSDataset::ParseBandsFromURL( string oVarList )
         {
             oVarName = papszVars[i];
 
-            papszResultList = 
+            papszResultList =
                 CollectBandsFromDDSVar( oVarName, papszResultList );
         }
         else
@@ -641,11 +638,11 @@ char **DODSDataset::ParseBandsFromURL( string oVarList )
 
             // Eventually we should consider supporting a [band] keyword
             // to select a constraint variable that should be used to
-            // identify a band dimension ... but not for now. 
+            // identify a band dimension ... but not for now.
 
             papszResultList = CSLAddString( papszResultList,
                                             oVarName.c_str() );
-            papszResultList = CSLAddString( papszResultList, 
+            papszResultList = CSLAddString( papszResultList,
                                             oCE.c_str() );
         }
     }
@@ -662,7 +659,7 @@ char **DODSDataset::ParseBandsFromURL( string oVarList )
 /*      metadata to the target object.                                  */
 /************************************************************************/
 
-void DODSDataset::HarvestMetadata( GDALMajorObject *poTarget, 
+void DODSDataset::HarvestMetadata( GDALMajorObject *poTarget,
                                    AttrTable *poSrcTable )
 
 {
@@ -673,7 +670,7 @@ void DODSDataset::HarvestMetadata( GDALMajorObject *poTarget,
 /*      Find Metadata container.                                        */
 /* -------------------------------------------------------------------- */
     AttrTable *poMDTable = poSrcTable->find_container("Metadata");
-    
+
     if( poMDTable == NULL )
         return;
 
@@ -687,8 +684,8 @@ void DODSDataset::HarvestMetadata( GDALMajorObject *poTarget,
         if( poMDTable->get_attr_type( dv_i ) != Attr_string )
             continue;
 
-        poTarget->SetMetadataItem( 
-            poMDTable->get_name( dv_i ).c_str(), 
+        poTarget->SetMetadataItem(
+            poMDTable->get_name( dv_i ).c_str(),
             StripQuotes( poMDTable->get_attr(dv_i) ).c_str() );
     }
 }
@@ -754,12 +751,12 @@ void DODSDataset::HarvestDAS()
     if( oNorth != "" && oSouth != "" && oEast != "" && oWest != "" )
     {
         adfGeoTransform[0] = CPLAtof(oWest.c_str());
-        adfGeoTransform[1] = 
+        adfGeoTransform[1] =
             (CPLAtof(oEast.c_str()) - CPLAtof(oWest.c_str())) / nRasterXSize;
         adfGeoTransform[2] = 0.0;
         adfGeoTransform[3] = CPLAtof(oNorth.c_str());
         adfGeoTransform[4] = 0.0;
-        adfGeoTransform[5] = 
+        adfGeoTransform[5] =
             (CPLAtof(oSouth.c_str()) - CPLAtof(oNorth.c_str())) / nRasterYSize;
 
         bGotGeoTransform = TRUE;
@@ -788,7 +785,7 @@ void DODSDataset::HarvestDAS()
         }
         else
         {
-            CPLError( CE_Warning, CPLE_AppDefined, 
+            CPLError( CE_Warning, CPLE_AppDefined,
                       "Failed to parse GeoTransform DAS value: %s",
                       oValue.c_str() );
         }
@@ -803,17 +800,17 @@ void DODSDataset::HarvestDAS()
     oWKT = StripQuotes(poFileInfo->get_attr( "spatial_ref" ));
     // strip remaining backslashes (2007-04-26, gaffigan at sfos.uaf.edu)
     oWKT.erase(std::remove(oWKT.begin(), oWKT.end(), '\\'), oWKT.end());
-    if( oWKT.length() > 0 
-        && !EQUALN(oWKT.c_str(),"GEOGCS",6)
-        && !EQUALN(oWKT.c_str(),"PROJCS",6)
-        && !EQUALN(oWKT.c_str(),"LOCAL_CS",8) )
+    if( oWKT.length() > 0
+        && !STARTS_WITH_CI(oWKT.c_str(), "GEOGCS")
+        && !STARTS_WITH_CI(oWKT.c_str(), "PROJCS")
+        && !STARTS_WITH_CI(oWKT.c_str(), "LOCAL_CS") )
     {
         OGRSpatialReference oSRS;
 
         if( oSRS.SetFromUserInput( oWKT.c_str() ) != OGRERR_NONE )
         {
-            CPLError( CE_Warning, CPLE_AppDefined, 
-                      "Failed to recognise 'spatial_ref' value of: %s", 
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Failed to recognise 'spatial_ref' value of: %s",
                       oWKT.c_str() );
             oWKT = "";
         }
@@ -857,9 +854,9 @@ void DODSDataset::HarvestMaps( string oVarName, string oCE )
     int iYDim = GetDimension( oCE, "y", NULL );
     int iMap;
     Grid::Map_iter iterMap;
-    
+
     for( iterMap = poGrid->map_begin(), iMap = 0;
-         iterMap != poGrid->map_end(); 
+         iterMap != poGrid->map_end();
          iterMap++, iMap++ )
     {
         if( iMap == iXDim )
@@ -871,11 +868,11 @@ void DODSDataset::HarvestMaps( string oVarName, string oCE )
     if( poXMap == NULL || poYMap == NULL )
         return;
 
-    if( poXMap->var()->type() != dods_float64_c 
+    if( poXMap->var()->type() != dods_float64_c
         || poYMap->var()->type() != dods_float64_c )
     {
         CPLDebug( "DODS", "Ignoring Grid Map - not a supported data type." );
-        return;							       
+        return;
     }
 
 /* -------------------------------------------------------------------- */
@@ -883,11 +880,11 @@ void DODSDataset::HarvestMaps( string oVarName, string oCE )
 /*      expected size.                                                  */
 /* -------------------------------------------------------------------- */
 
-/* -------------------------------------------------------------------- 
- *  Fetch maps.  We need to construct a seperate request like:     
+/* --------------------------------------------------------------------
+ *  Fetch maps.  We need to construct a separate request like:
  *    http://dods.gso.uri.edu/cgi-bin/nph-dods/MCSST/Northwest_Atlantic/5km/raw/1982/9/m82258070000.pvu.Z?dsp_band_1.lat,dsp_band_1.lon
  *
- *  to fetch just the maps, and not the actual dataset. 
+ *  to fetch just the maps, and not the actual dataset.
  * -------------------------------------------------------------------- */
 /* -------------------------------------------------------------------- */
 /*      Build constraint expression.                                    */
@@ -895,16 +892,15 @@ void DODSDataset::HarvestMaps( string oVarName, string oCE )
     string constraint;
     string xdimname = "lon";
     string ydimname = "lat";
-    
 
-    constraint = oVarName + "." + xdimname + "," 
+    constraint = oVarName + "." + xdimname + ","
         + oVarName + "." + ydimname;
 
 /* -------------------------------------------------------------------- */
 /*      Request data from server.                                       */
 /* -------------------------------------------------------------------- */
     DataDDS data( poBaseTypeFactory );
-    
+
     GetConnect()->request_data(data, constraint );
 
 /* -------------------------------------------------------------------- */
@@ -912,8 +908,8 @@ void DODSDataset::HarvestMaps( string oVarName, string oCE )
 /* -------------------------------------------------------------------- */
     BaseType *poBtX = get_variable(data, oVarName + "." + xdimname );
     BaseType *poBtY = get_variable(data, oVarName + "." + ydimname );
-    if (!poBtX || !poBtY 
-        || poBtX->type() != dods_array_c 
+    if (!poBtX || !poBtY
+        || poBtX->type() != dods_array_c
         || poBtY->type() != dods_array_c )
         return;
 
@@ -951,17 +947,17 @@ void DODSDataset::HarvestMaps( string oVarName, string oCE )
 /* -------------------------------------------------------------------- */
     bGotGeoTransform = TRUE;
 
-    // pixel size. 
+    // pixel size.
     adfGeoTransform[1] = (padfXMap[nRasterXSize-1] - padfXMap[0])
         / (nRasterXSize-1);
     adfGeoTransform[5] = (padfYMap[nRasterYSize-1] - padfYMap[0])
         / (nRasterYSize-1);
 
-    // rotational coefficients. 
+    // rotational coefficients.
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[4] = 0.0;
 
-    // origin/ 
+    // origin/
     adfGeoTransform[0] = padfXMap[0] - adfGeoTransform[1] * 0.5;
     adfGeoTransform[3] = padfYMap[0] - adfGeoTransform[5] * 0.5;
 }
@@ -973,11 +969,11 @@ void DODSDataset::HarvestMaps( string oVarName, string oCE )
 GDALDataset *
 DODSDataset::Open(GDALOpenInfo *poOpenInfo)
 {
-    if( !EQUALN(poOpenInfo->pszFilename,"http://",7) 
-        && !EQUALN(poOpenInfo->pszFilename,"https://",8) )
+    if( !STARTS_WITH_CI(poOpenInfo->pszFilename, "http://")
+        && !STARTS_WITH_CI(poOpenInfo->pszFilename, "https://") )
         return NULL;
 
-    
+
     DODSDataset *poDS = new DODSDataset();
     char **papszVarConstraintList = NULL;
 
@@ -1033,23 +1029,23 @@ DODSDataset::Open(GDALOpenInfo *poOpenInfo)
 /* -------------------------------------------------------------------- */
 /*      For now we support only a single band.                          */
 /* -------------------------------------------------------------------- */
-        DODSRasterBand *poBaseBand = 
-            new DODSRasterBand(poDS, 
+        DODSRasterBand *poBaseBand =
+            new DODSRasterBand(poDS,
                                string(papszVarConstraintList[0]),
-                               string(papszVarConstraintList[1]), 
+                               string(papszVarConstraintList[1]),
                                1 );
 
         poDS->nRasterXSize = poBaseBand->GetXSize();
         poDS->nRasterYSize = poBaseBand->GetYSize();
-            
+
 	poDS->SetBand(1, poBaseBand );
 
         for( int iBand = 1; papszVarConstraintList[iBand*2] != NULL; iBand++ )
         {
-            poDS->SetBand( iBand+1, 
-                           new DODSRasterBand(poDS, 
+            poDS->SetBand( iBand+1,
+                           new DODSRasterBand(poDS,
                                    string(papszVarConstraintList[iBand*2+0]),
-                                   string(papszVarConstraintList[iBand*2+1]), 
+                                   string(papszVarConstraintList[iBand*2+1]),
                                               1 ) );
         }
 
@@ -1080,19 +1076,19 @@ DODSDataset::Open(GDALOpenInfo *poOpenInfo)
     }
 
     CSLDestroy(papszVarConstraintList);
-    
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
     if( poDS != NULL && poOpenInfo->eAccess == GA_Update )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The DODS driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
     }
-    
+
     return poDS;
 }
 
@@ -1100,7 +1096,7 @@ DODSDataset::Open(GDALOpenInfo *poOpenInfo)
 /*                          GetGeoTransform()                           */
 /************************************************************************/
 
-CPLErr 
+CPLErr
 DODSDataset::GetGeoTransform( double * padfTransform )
 {
     memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
@@ -1128,7 +1124,7 @@ DODSDataset::GetProjectionRef()
 /*                           DODSRasterBand()                           */
 /************************************************************************/
 
-DODSRasterBand::DODSRasterBand(DODSDataset *poDSIn, string oVarNameIn, 
+DODSRasterBand::DODSRasterBand(DODSDataset *poDSIn, string oVarNameIn,
                                string oCEIn, int nOverviewFactorIn )
 {
     poDS = poDSIn;
@@ -1153,7 +1149,7 @@ DODSRasterBand::DODSRasterBand(DODSDataset *poDSIn, string oVarNameIn,
     if( poDDSDef == NULL )
     {
         throw InternalErr(
-            CPLSPrintf( "Could not find DDS definition for variable %s.", 
+            CPLSPrintf( "Could not find DDS definition for variable %s.",
                         oVarNameIn.c_str() ) );
         return;
     }
@@ -1180,7 +1176,7 @@ DODSRasterBand::DODSRasterBand(DODSDataset *poDSIn, string oVarNameIn,
 /* -------------------------------------------------------------------- */
 /*      Determine the datatype.                                         */
 /* -------------------------------------------------------------------- */
-    
+
     // Now grab the data type of the variable.
     switch (poArray->var()->type()) {
       case dods_byte_c: eDataType = GDT_Byte; break;
@@ -1254,7 +1250,7 @@ DODSRasterBand::DODSRasterBand(DODSDataset *poDSIn, string oVarNameIn,
 
     if( nRasterXSize < nBlockXSize * 2 )
         nBlockXSize = nRasterXSize;
-    
+
     if( nRasterYSize < nBlockYSize * 2 )
         nBlockYSize = nRasterYSize;
 
@@ -1272,19 +1268,19 @@ DODSRasterBand::DODSRasterBand(DODSDataset *poDSIn, string oVarNameIn,
         int iOverview;
 
         nOverviewCount = 0;
-        papoOverviewBand = (DODSRasterBand **) 
+        papoOverviewBand = (DODSRasterBand **)
             CPLCalloc( sizeof(void*), 8 );
 
         for( iOverview = 1; iOverview < 8; iOverview++ )
         {
             int nThisFactor = 1 << iOverview;
-            
+
             if( nRasterXSize / nThisFactor < 128
                 && nRasterYSize / nThisFactor < 128 )
                 break;
 
-            papoOverviewBand[nOverviewCount++] = 
-                new DODSRasterBand( poDSIn, oVarNameIn, oCEIn, 
+            papoOverviewBand[nOverviewCount++] =
+                new DODSRasterBand( poDSIn, oVarNameIn, oCEIn,
                                     nThisFactor );
 
             papoOverviewBand[nOverviewCount-1]->bFlipX = bFlipX;
@@ -1316,7 +1312,7 @@ void DODSRasterBand::HarvestDAS()
 
 {
     DODSDataset *poDODS = dynamic_cast<DODSDataset *>(poDS);
-    
+
 /* -------------------------------------------------------------------- */
 /*      Try and fetch the corresponding DAS subtree if it exists.       */
 /* -------------------------------------------------------------------- */
@@ -1346,11 +1342,11 @@ void DODSRasterBand::HarvestDAS()
     oValue = StripQuotes(poBandInfo->get_attr( "PhotometricInterpretation" ));
     for( iInterp = 0; iInterp < (int) GCI_Max; iInterp++ )
     {
-        if( oValue == GDALGetColorInterpretationName( 
+        if( oValue == GDALGetColorInterpretationName(
                 (GDALColorInterp) iInterp ) )
             eColorInterp = (GDALColorInterp) iInterp;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Get band description.                                           */
 /* -------------------------------------------------------------------- */
@@ -1388,8 +1384,8 @@ void DODSRasterBand::HarvestDAS()
 
         poCT = new GDALColorTable();
 
-        for( dv_i = poCTable->attr_begin(); 
-             dv_i != poCTable->attr_end(); 
+        for( dv_i = poCTable->attr_begin();
+             dv_i != poCTable->attr_end();
              dv_i++ )
         {
             if( !poCTable->is_container( dv_i ) )
@@ -1408,7 +1404,7 @@ void DODSRasterBand::HarvestDAS()
                 sEntry.c4 = 255;
             else
                 sEntry.c4 = atoi(poColor->get_attr( "alpha" ).c_str());
-            
+
             poCT->SetColorEntry( poCT->GetColorEntryCount(), &sEntry );
         }
     }
@@ -1429,7 +1425,7 @@ void DODSRasterBand::HarvestDAS()
 /*                             IReadBlock()                             */
 /************************************************************************/
 
-CPLErr 
+CPLErr
 DODSRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage)
 {
     DODSDataset *poDODS = dynamic_cast<DODSDataset *>(poDS);
@@ -1466,21 +1462,21 @@ DODSRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage)
 /* -------------------------------------------------------------------- */
     string x_constraint, y_constraint, raw_constraint, final_constraint;
 
-    x_constraint = 
-        CPLSPrintf( "[%d:%d:%d]", 
-                    nXOff * nOverviewFactor, 
-                    nOverviewFactor, 
+    x_constraint =
+        CPLSPrintf( "[%d:%d:%d]",
+                    nXOff * nOverviewFactor,
+                    nOverviewFactor,
                     (nXOff + nXSize - 1) * nOverviewFactor );
-    y_constraint = 
-        CPLSPrintf( "[%d:%d:%d]", 
+    y_constraint =
+        CPLSPrintf( "[%d:%d:%d]",
                     nYOff * nOverviewFactor,
                     nOverviewFactor,
                     (nYOff + nYSize - 1) * nOverviewFactor );
 
     raw_constraint = oVarName + oCE;
 
-    final_constraint = poDODS->SubConstraint( raw_constraint, 
-                                              x_constraint, 
+    final_constraint = poDODS->SubConstraint( raw_constraint,
+                                              x_constraint,
                                               y_constraint );
 
     CPLDebug( "DODS", "constraint = %s", final_constraint.c_str() );
@@ -1507,11 +1503,11 @@ DODSRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage)
           case dods_grid_c:
             poA = dynamic_cast<Array*>(dynamic_cast<Grid*>(poBt)->array_var());
             break;
-            
+
           case dods_array_c:
             poA = dynamic_cast<Array *>(poBt);
             break;
-            
+
           default:
             throw InternalErr("Expected an Array or Grid variable!");
         }
@@ -1520,8 +1516,8 @@ DODSRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage)
 /*      Pre-initialize the output buffer to zero.                       */
 /* -------------------------------------------------------------------- */
         if( nXSize < nBlockXSize || nYSize < nBlockYSize )
-            memset( pImage, 0, 
-                    nBlockXSize * nBlockYSize 
+            memset( pImage, 0,
+                    nBlockXSize * nBlockYSize
                     * GDALGetDataTypeSize(eDataType) / 8 );
 
 /* -------------------------------------------------------------------- */
@@ -1538,27 +1534,27 @@ DODSRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage)
         {
             GByte *pabyDataCopy;
             int iY;
-            
+
             CPLDebug( "DODS", "Applying transposition" );
-            
+
             // make a copy of the original
-            pabyDataCopy = (GByte *) 
+            pabyDataCopy = (GByte *)
                 CPLMalloc(nBytesPerPixel * nXSize * nYSize);
             memcpy( pabyDataCopy, pImage, nBytesPerPixel * nXSize * nYSize );
             memset( pImage, 0, nBytesPerPixel * nXSize * nYSize );
-            
+
             for( iY = 0; iY < nYSize; iY++ )
             {
-                GDALCopyWords( pabyDataCopy + iY * nBytesPerPixel, 
+                GDALCopyWords( pabyDataCopy + iY * nBytesPerPixel,
                                eDataType, nBytesPerPixel * nYSize,
-                               ((GByte *) pImage) + iY * nXSize * nBytesPerPixel, 
+                               ((GByte *) pImage) + iY * nXSize * nBytesPerPixel,
                                eDataType, nBytesPerPixel, nXSize );
             }
-            
+
             // cleanup
             CPLFree( pabyDataCopy );
         }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Do we need "x" flipping?                                        */
 /* -------------------------------------------------------------------- */
@@ -1566,23 +1562,23 @@ DODSRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage)
         {
             GByte *pabyDataCopy;
             int iY;
-            
+
             CPLDebug( "DODS", "Applying X flip." );
-            
+
             // make a copy of the original
-            pabyDataCopy = (GByte *) 
+            pabyDataCopy = (GByte *)
                 CPLMalloc(nBytesPerPixel * nXSize * nYSize);
             memcpy( pabyDataCopy, pImage, nBytesPerPixel * nXSize * nYSize );
             memset( pImage, 0, nBytesPerPixel * nXSize * nYSize );
-            
+
             for( iY = 0; iY < nYSize; iY++ )
             {
                 GDALCopyWords( pabyDataCopy + iY*nXSize*nBytesPerPixel,
                                eDataType, nBytesPerPixel,
-                               ((GByte *) pImage) + ((iY+1)*nXSize-1)*nBytesPerPixel, 
+                               ((GByte *) pImage) + ((iY+1)*nXSize-1)*nBytesPerPixel,
                                eDataType, -nBytesPerPixel, nXSize );
             }
-            
+
             // cleanup
             CPLFree( pabyDataCopy );
         }
@@ -1594,14 +1590,14 @@ DODSRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage)
         {
             GByte *pabyDataCopy;
             int iY;
-            
+
             CPLDebug( "DODS", "Applying Y flip." );
-            
+
             // make a copy of the original
-            pabyDataCopy = (GByte *) 
+            pabyDataCopy = (GByte *)
                 CPLMalloc(nBytesPerPixel * nXSize * nYSize);
             memcpy( pabyDataCopy, pImage, nBytesPerPixel * nXSize * nYSize );
-            
+
             for( iY = 0; iY < nYSize; iY++ )
             {
                 GDALCopyWords( pabyDataCopy + iY*nXSize*nBytesPerPixel,
@@ -1610,7 +1606,7 @@ DODSRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage)
                                eDataType, nBytesPerPixel,
                                nXSize );
             }
-            
+
             // cleanup
             CPLFree( pabyDataCopy );
         }
@@ -1628,7 +1624,7 @@ DODSRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage)
                 memmove( ((GByte *) pImage) + iLine*nBlockXSize*nBytesPerPixel,
                          ((GByte *) pImage) + iLine * nXSize * nBytesPerPixel,
                          nBytesPerPixel * nXSize );
-                memset( ((GByte *) pImage) 
+                memset( ((GByte *) pImage)
                         + (iLine*nBlockXSize + nXSize)*nBytesPerPixel,
                         0, nBytesPerPixel * (nBlockXSize - nXSize) );
             }
@@ -1642,7 +1638,7 @@ DODSRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage)
         CPLError(CE_Failure, CPLE_AppDefined, "%s", e.get_error_message().c_str());
         return CE_Failure;
     }
-    
+
     return CE_None;
 }
 
@@ -1719,26 +1715,23 @@ double DODSRasterBand::GetNoDataValue( int * pbSuccess )
 /*                         GDALRegister_DODS()                          */
 /************************************************************************/
 
-void 
-GDALRegister_DODS()
+void GDALRegister_DODS()
+
 {
-    GDALDriver *poDriver;
-    
-    if (! GDAL_CHECK_VERSION("GDAL/DODS driver"))
+    if( !GDAL_CHECK_VERSION("GDAL/DODS driver") )
         return;
 
-    if( GDALGetDriverByName( "DODS" ) == NULL ) {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "DODS" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "DAP 3.x servers" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#DODS" );
+    if( GDALGetDriverByName( "DODS" ) != NULL )
+        return;
 
-        poDriver->pfnOpen = DODSDataset::Open;
+    GDALDriver *poDriver = new GDALDriver();
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
-}
+    poDriver->SetDescription( "DODS" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "DAP 3.x servers" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#DODS" );
+
+    poDriver->pfnOpen = DODSDataset::Open;
 
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/frmts/dods/frmt_dods.html b/frmts/dods/frmt_dods.html
index 4c39f0c..bdd4714 100644
--- a/frmts/dods/frmt_dods.html
+++ b/frmts/dods/frmt_dods.html
@@ -16,14 +16,14 @@ The full dataset name specification consists of the OPeNDAP dataset
 url, the full path to the desired array or grid variable, and an indicator
 of the array indices to be accessed.<p>
 
-For instance, if the url http://maps.gdal.org/daac-bin/nph-hdf/3B42.HDF.dds 
+For instance, if the url http://maps.gdal.org/daac-bin/nph-hdf/3B42.HDF.dds
 returns a DDS definition like this:<p>
 
 <pre>
 Dataset {
   Structure {
     Structure {
-      Float64 percipitate[scan = 5][longitude = 360][latitude = 80];
+      Float64 precipitate[scan = 5][longitude = 360][latitude = 80];
       Float64 relError[scan = 5][longitude = 360][latitude = 80];
     } PlanetaryGrid;
   } DATA_GRANULE;
@@ -31,14 +31,14 @@ Dataset {
 </pre>
 <p>
 
-then the percipitate grid can be accessed using the following GDAL 
+then the precipitate grid can be accessed using the following GDAL
 dataset name:<p>
 
-http://maps.gdal.org/daac-bin/nph-hdf/3B42.HDF?DATA_GRANULE.PlanetaryGrid.percipitate[0][x][y]
+http://maps.gdal.org/daac-bin/nph-hdf/3B42.HDF?DATA_GRANULE.PlanetaryGrid.precipitate[0][x][y]
 <p>
 
 The full path to the grid or array to be accessed needs to be specified (not
-counting the outer Dataset name).  GDAL needs to know which indices of 
+counting the outer Dataset name).  GDAL needs to know which indices of
 the array to treat as x (longitude or easting) and y (latitude or northing).
 Any other dimensions need to be restricted to a single value.<p>
 
@@ -47,7 +47,7 @@ children of the Dataset it may not be necessary to name the grid or array
 variable. <p>
 
 In cases where there are a number of 2D arrays or grids at the dataset
-level, they may be each automatically treated as seperate bands.<p>
+level, they may be each automatically treated as separate bands.<p>
 
 <h2>Specialized AIS/DAS Metadata</h2>
 
@@ -60,14 +60,14 @@ for details of how the AIS mechanism works. <p>
 <pre>
 Attributes {
 
-    GLOBAL { 
+    GLOBAL {
         Float64 Northernmost_Northing 71.1722;
 	Float64 Southernmost_Northing  4.8278;
 	Float64	Easternmost_Easting  -27.8897;
 	Float64	Westernmost_Easting -112.11;
         Float64 GeoTransform "71.1722 0.001 0.0 -112.11 0.0 -0.001";
 	String spatial_ref "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]]";
-        Metadata { 
+        Metadata {
           String TIFFTAG_XRESOLUTION "400";
           String TIFFTAG_YRESOLUTION "400";
           String TIFFTAG_RESOLUTIONUNIT "2 (pixels/inch)";
@@ -76,7 +76,7 @@ Attributes {
 
     band_1 {
         String Description "...";
-        String 
+        String
     }
 }
 </pre>
@@ -97,7 +97,7 @@ It will have the following subitems:<p>
 
 <li> <b>GeoTransform</b>: The six parameters defining the affine transformation
 between pixel/line space and georeferenced space if applicable.  Stored
-as a single string with values seperated by sapces.  Note this 
+as a single string with values separated by spaces.  Note this
 allows for rotated or sheared images. (optional) <p>
 
 <li> <b>SpatialRef</b>: The OpenGIS WKT description of the coordinate system.
@@ -114,10 +114,10 @@ as the attribute name.  Metadata values will always be strings. (optional)
 
 Note that the edge northing and easting values can be computed based
 on the grid size and the geotransform. They are included primarily as
-extra documentation that is easier to interprete by a user than the
+extra documentation that is easier to interpret by a user than the
 GeoTransform.  They will also be used to compute a GeoTransform internally
 if one is note provided, but if both are provided the GeoTransform will
-take precidence.<p>
+take precedence.<p>
 
 <h3>Band</h3>
 
@@ -140,7 +140,7 @@ one of "Undefined", "GrayIndex", "PaletteIndex", "Red", "Green",
 <li> <b>units</b>: name of units (one of "ft" or "m" for elevation data).
 (optional)<p>
 
-<li> <b>add_offset</b>: Offset to be applied to pixel values (after 
+<li> <b>add_offset</b>: Offset to be applied to pixel values (after
 scale_factor) to compute a "real" pixel value.  Defaults to 0.0. (optional)<p>
 
 <li> <b>scale_factor</b>: Scale to be applied to pixel values (before
@@ -153,15 +153,15 @@ add_offset) to compute "real" pixel value.  Defaults to 1.0. (optional)<p>
 <li> <b>Colormap</b>: A container with a subcontainer for each color in
 the color table, looking like the following.  The alpha component is
 optional and assumed to be 255 (opaque) if not provided.<p>
-<pre>									
-    Colormap { 
-      Color_0 { 
+<pre>
+    Colormap {
+      Color_0 {
         Byte red 0;
         Byte green 0;
         Byte blue 0;
         Byte alpha 255;
       }
-      Color_1 { 
+      Color_1 {
         Byte red 255;
         Byte green 255;
         Byte blue 255;
diff --git a/frmts/dted/dted_api.c b/frmts/dted/dted_api.c
index 5573946..09c3f39 100644
--- a/frmts/dted/dted_api.c
+++ b/frmts/dted/dted_api.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dted_api.c 28831 2015-04-01 16:46:05Z rouault $
+ * $Id: dted_api.c 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  DTED Translator
  * Purpose:  Implementation of DTED/CDED access functions.
@@ -31,13 +31,16 @@
 #include "dted_api.h"
 
 #ifndef AVOID_CPL
-CPL_CVSID("$Id: dted_api.c 28831 2015-04-01 16:46:05Z rouault $");
+CPL_CVSID("$Id: dted_api.c 33720 2016-03-15 00:39:53Z goatbar $");
 #endif
 
 static int bWarnedTwoComplement = FALSE;
 
 static void DTEDDetectVariantWithMissingColumns(DTEDInfo* psDInfo);
 
+CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused) {}
+CPL_INLINE static void CPL_IGNORE_RET_VAL_SIZET(CPL_UNUSED size_t unused) {}
+
 /************************************************************************/
 /*                            DTEDGetField()                            */
 /*                                                                      */
@@ -97,7 +100,7 @@ DTEDInfo * DTEDOpen( const char * pszFilename,
         pszAccess = "rb";
     else
         pszAccess = "r+b";
-    
+
     fp = VSIFOpenL( pszFilename, pszAccess );
 
     if( fp == NULL )
@@ -107,7 +110,7 @@ DTEDInfo * DTEDOpen( const char * pszFilename,
 #ifndef AVOID_CPL
             CPLError( CE_Failure, CPLE_OpenFailed,
 #else
-            fprintf( stderr, 
+            fprintf( stderr,
 #endif
                       "Failed to open file %s.",
                       pszFilename );
@@ -153,33 +156,33 @@ DTEDInfo * DTEDOpenEx( VSILFILE   *fp,
 #ifndef AVOID_CPL
                CPLError( CE_Failure, CPLE_OpenFailed,
 #else
-               fprintf( stderr, 
+               fprintf( stderr,
 #endif
                           "Unable to read header, %s is not DTED.",
                           pszFilename );
             }
-            VSIFCloseL( fp );
+            CPL_IGNORE_RET_VAL_INT(VSIFCloseL( fp ));
             return NULL;
         }
 
-    } while( EQUALN(achRecord,"VOL",3) || EQUALN(achRecord,"HDR",3) );
+    } while( STARTS_WITH_CI(achRecord, "VOL") || STARTS_WITH_CI(achRecord, "HDR") );
 
-    if( !EQUALN(achRecord,"UHL",3) )
+    if( !STARTS_WITH_CI(achRecord, "UHL") )
     {
         if( !bTestOpen )
         {
 #ifndef AVOID_CPL
             CPLError( CE_Failure, CPLE_OpenFailed,
 #else
-            fprintf( stderr, 
+            fprintf( stderr,
 #endif
                       "No UHL record.  %s is not a DTED file.",
                       pszFilename );
         }
-        VSIFCloseL( fp );
+        CPL_IGNORE_RET_VAL_INT(VSIFCloseL( fp ));
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create and initialize the DTEDInfo structure.                   */
 /* -------------------------------------------------------------------- */
@@ -196,23 +199,23 @@ DTEDInfo * DTEDOpenEx( VSILFILE   *fp,
 
     psDInfo->nDSIOffset = (int)VSIFTellL( fp );
     psDInfo->pachDSIRecord = (char *) CPLMalloc(DTED_DSI_SIZE);
-    VSIFReadL( psDInfo->pachDSIRecord, 1, DTED_DSI_SIZE, fp );
-    
+    CPL_IGNORE_RET_VAL_SIZET(VSIFReadL( psDInfo->pachDSIRecord, 1, DTED_DSI_SIZE, fp ));
+
     psDInfo->nACCOffset = (int)VSIFTellL( fp );
     psDInfo->pachACCRecord = (char *) CPLMalloc(DTED_ACC_SIZE);
-    VSIFReadL( psDInfo->pachACCRecord, 1, DTED_ACC_SIZE, fp );
+    CPL_IGNORE_RET_VAL_SIZET(VSIFReadL( psDInfo->pachACCRecord, 1, DTED_ACC_SIZE, fp ));
 
-    if( !EQUALN(psDInfo->pachDSIRecord,"DSI",3)
-        || !EQUALN(psDInfo->pachACCRecord,"ACC",3) )
+    if( !STARTS_WITH_CI(psDInfo->pachDSIRecord, "DSI")
+        || !STARTS_WITH_CI(psDInfo->pachACCRecord, "ACC") )
     {
 #ifndef AVOID_CPL
         CPLError( CE_Failure, CPLE_OpenFailed,
 #else
-        fprintf( stderr, 
+        fprintf( stderr,
 #endif
                  "DSI or ACC record missing.  DTED access to\n%s failed.",
                  pszFilename );
-        
+
         DTEDClose(psDInfo);
         return NULL;
     }
@@ -282,10 +285,10 @@ DTEDInfo * DTEDOpenEx( VSILFILE   *fp,
     }
 
     /* NOTE : The first version of MIL-D-89020 was buggy.
-       The latitude and longitude of the LL cornder of the UHF record was inverted.
-       This was fixed in MIL-D-89020 Amendement 1, but some products may be affected.
+       The latitude and longitude of the LL corner of the UHF record was inverted.
+       This was fixed in MIL-D-89020 Amendment 1, but some products may be affected.
        We detect this situation by looking at N/S in the longitude field and
-       E/W in the latitude one
+       E/W in the latitude one.
     */
 
     dfLLOriginX = deg + min / 60.0 + sec / 3600.0;
@@ -352,8 +355,8 @@ static void DTEDDetectVariantWithMissingColumns(DTEDInfo* psDInfo)
     int nSize;
     int nColByteSize = 12 + psDInfo->nYSize*2;
 
-    VSIFSeekL(psDInfo->fp, psDInfo->nDataOffset, SEEK_SET);
-    if (VSIFReadL(pabyRecordHeader, 1, 8, psDInfo->fp) != 8 ||
+    if (VSIFSeekL(psDInfo->fp, psDInfo->nDataOffset, SEEK_SET) < 0 ||
+        VSIFReadL(pabyRecordHeader, 1, 8, psDInfo->fp) != 8 ||
         pabyRecordHeader[0] != 0252)
     {
         CPLDebug("DTED", "Cannot find signature of first column");
@@ -363,7 +366,7 @@ static void DTEDDetectVariantWithMissingColumns(DTEDInfo* psDInfo)
     nFirstDataBlockCount = (pabyRecordHeader[2] << 8) | pabyRecordHeader[3];
     nFirstLongitudeCount = (pabyRecordHeader[4] << 8) | pabyRecordHeader[5];
 
-    VSIFSeekL(psDInfo->fp, 0, SEEK_END);
+    CPL_IGNORE_RET_VAL_SIZET(VSIFSeekL(psDInfo->fp, 0, SEEK_END));
     nSize = (int)VSIFTellL(psDInfo->fp);
     if (nSize < 12 + psDInfo->nYSize*2)
     {
@@ -371,8 +374,8 @@ static void DTEDDetectVariantWithMissingColumns(DTEDInfo* psDInfo)
         return;
     }
 
-    VSIFSeekL(psDInfo->fp, nSize - nColByteSize, SEEK_SET);
-    if (VSIFReadL(pabyRecordHeader, 1, 8, psDInfo->fp) != 8 ||
+    if (VSIFSeekL(psDInfo->fp, nSize - nColByteSize, SEEK_SET) < 0 ||
+        VSIFReadL(pabyRecordHeader, 1, 8, psDInfo->fp) != 8 ||
         pabyRecordHeader[0] != 0252)
     {
         CPLDebug("DTED", "Cannot find signature of last column");
@@ -440,8 +443,8 @@ static void DTEDDetectVariantWithMissingColumns(DTEDInfo* psDInfo)
         {
             int nDataBlockCount, nLongitudeCount;
 
-            VSIFSeekL(psDInfo->fp, psDInfo->nDataOffset + i * nColByteSize, SEEK_SET);
-            if (VSIFReadL(pabyRecordHeader, 1, 8, psDInfo->fp) != 8 ||
+            if (VSIFSeekL(psDInfo->fp, psDInfo->nDataOffset + i * nColByteSize, SEEK_SET) < 0 ||
+                VSIFReadL(pabyRecordHeader, 1, 8, psDInfo->fp) != 8 ||
                 pabyRecordHeader[0] != 0252)
             {
                 CPLDebug("DTED", "Cannot find signature of physical column %d", i);
@@ -475,7 +478,7 @@ static void DTEDDetectVariantWithMissingColumns(DTEDInfo* psDInfo)
 /*                                                                      */
 /*      Read one single sample. The coordinates are given from the      */
 /*      top-left corner of the file (contrary to the internal           */
-/*      organisation or a DTED file)                                    */
+/*      organization or a DTED file)                                    */
 /************************************************************************/
 
 int DTEDReadPoint( DTEDInfo * psDInfo, int nXOff, int nYOff, GInt16* panVal)
@@ -488,7 +491,7 @@ int DTEDReadPoint( DTEDInfo * psDInfo, int nXOff, int nYOff, GInt16* panVal)
 #ifndef AVOID_CPL
         CPLError( CE_Failure, CPLE_AppDefined,
 #else
-        fprintf( stderr, 
+        fprintf( stderr,
 #endif
                   "Invalid raster coordinates (%d,%d) in DTED file.\n", nXOff, nYOff);
         return FALSE;
@@ -513,7 +516,7 @@ int DTEDReadPoint( DTEDInfo * psDInfo, int nXOff, int nYOff, GInt16* panVal)
 #ifndef AVOID_CPL
         CPLError( CE_Failure, CPLE_FileIO,
 #else
-        fprintf( stderr, 
+        fprintf( stderr,
 #endif
                   "Failed to seek to, or read (%d,%d) at offset %d\n"
                   "in DTED file.\n",
@@ -601,7 +604,7 @@ int DTEDReadProfileEx( DTEDInfo * psDInfo, int nColumnOffset,
 #ifndef AVOID_CPL
         CPLError( CE_Failure, CPLE_FileIO,
 #else
-        fprintf( stderr, 
+        fprintf( stderr,
 #endif
                   "Failed to seek to, or read profile %d at offset %d\n"
                   "in DTED file.\n",
@@ -676,7 +679,7 @@ int DTEDReadProfileEx( DTEDInfo * psDInfo, int nColumnOffset,
                         (pabyRecord[8+psDInfo->nYSize*2+2] << 8) |
                         pabyRecord[8+psDInfo->nYSize*2+3];
 
-        if ((GIntBig)fileCheckSum > (GIntBig)(0xff * (8+psDInfo->nYSize*2)))
+        if (fileCheckSum > 0xff * (8+(unsigned int)psDInfo->nYSize*2))
         {
             static int bWarned = FALSE;
             if (! bWarned)
@@ -741,7 +744,7 @@ int DTEDWriteProfile( DTEDInfo * psDInfo, int nColumnOffset,
 /*      Format the data record.                                         */
 /* -------------------------------------------------------------------- */
     pabyRecord = (GByte *) CPLMalloc(12 + psDInfo->nYSize*2);
-    
+
     for( i = 0; i < psDInfo->nYSize; i++ )
     {
         int     nABSVal = ABS(panData[psDInfo->nYSize-i-1]);
@@ -783,7 +786,7 @@ int DTEDWriteProfile( DTEDInfo * psDInfo, int nColumnOffset,
 #ifndef AVOID_CPL
         CPLError( CE_Failure, CPLE_FileIO,
 #else
-        fprintf( stderr, 
+        fprintf( stderr,
 #endif
                   "Failed to seek to, or write profile %d at offset %d\n"
                   "in DTED file.\n",
@@ -795,15 +798,14 @@ int DTEDWriteProfile( DTEDInfo * psDInfo, int nColumnOffset,
     CPLFree( pabyRecord );
 
     return TRUE;
-    
 }
 
 /************************************************************************/
 /*                      DTEDGetMetadataLocation()                       */
 /************************************************************************/
 
-static void DTEDGetMetadataLocation( DTEDInfo *psDInfo, 
-                                     DTEDMetaDataCode eCode, 
+static void DTEDGetMetadataLocation( DTEDInfo *psDInfo,
+                                     DTEDMetaDataCode eCode,
                                      char **ppszLocation, int *pnLength )
 {
     int bIsWeirdDTED = psDInfo->pachUHLRecord[4] == ' ';
@@ -910,9 +912,9 @@ static void DTEDGetMetadataLocation( DTEDInfo *psDInfo,
         if (bIsWeirdDTED)
             *ppszLocation = psDInfo->pachDSIRecord + 270;
         else
-            *ppszLocation = psDInfo->pachDSIRecord + 144; 
-        *pnLength = 5; 
-        break; 
+            *ppszLocation = psDInfo->pachDSIRecord + 144;
+        *pnLength = 5;
+        break;
 
       case DTEDMD_DIGITIZING_SYS:
         if (bIsWeirdDTED)
@@ -1011,7 +1013,7 @@ char *DTEDGetMetadata( DTEDInfo *psDInfo, DTEDMetaDataCode eCode )
 /*                          DTEDSetMetadata()                           */
 /************************************************************************/
 
-int DTEDSetMetadata( DTEDInfo *psDInfo, DTEDMetaDataCode eCode, 
+int DTEDSetMetadata( DTEDInfo *psDInfo, DTEDMetaDataCode eCode,
                      const char *pszNewValue )
 
 {
@@ -1032,7 +1034,7 @@ int DTEDSetMetadata( DTEDInfo *psDInfo, DTEDMetaDataCode eCode,
 /*      Update it, padding with spaces.                                 */
 /* -------------------------------------------------------------------- */
     memset( pszFieldSrc, ' ', nFieldLen );
-    strncpy( pszFieldSrc, pszNewValue, 
+    strncpy( pszFieldSrc, pszNewValue,
              MIN((size_t)nFieldLen,strlen(pszNewValue)) );
 
     /* Turn the flag on, so that the headers are rewritten at file */
@@ -1054,17 +1056,17 @@ void DTEDClose( DTEDInfo * psDInfo )
 /* -------------------------------------------------------------------- */
 /*      Write all headers back to disk.                                 */
 /* -------------------------------------------------------------------- */
-        VSIFSeekL( psDInfo->fp, psDInfo->nUHLOffset, SEEK_SET );
-        VSIFWriteL( psDInfo->pachUHLRecord, 1, DTED_UHL_SIZE, psDInfo->fp );
+        CPL_IGNORE_RET_VAL_INT(VSIFSeekL( psDInfo->fp, psDInfo->nUHLOffset, SEEK_SET ));
+        CPL_IGNORE_RET_VAL_SIZET(VSIFWriteL( psDInfo->pachUHLRecord, 1, DTED_UHL_SIZE, psDInfo->fp ));
 
-        VSIFSeekL( psDInfo->fp, psDInfo->nDSIOffset, SEEK_SET );
-        VSIFWriteL( psDInfo->pachDSIRecord, 1, DTED_DSI_SIZE, psDInfo->fp );
+        CPL_IGNORE_RET_VAL_INT(VSIFSeekL( psDInfo->fp, psDInfo->nDSIOffset, SEEK_SET ));
+        CPL_IGNORE_RET_VAL_SIZET(VSIFWriteL( psDInfo->pachDSIRecord, 1, DTED_DSI_SIZE, psDInfo->fp ));
 
-        VSIFSeekL( psDInfo->fp, psDInfo->nACCOffset, SEEK_SET );
-        VSIFWriteL( psDInfo->pachACCRecord, 1, DTED_ACC_SIZE, psDInfo->fp );
+        CPL_IGNORE_RET_VAL_INT(VSIFSeekL( psDInfo->fp, psDInfo->nACCOffset, SEEK_SET ));
+        CPL_IGNORE_RET_VAL_SIZET(VSIFWriteL( psDInfo->pachACCRecord, 1, DTED_ACC_SIZE, psDInfo->fp ));
     }
 
-    VSIFCloseL( psDInfo->fp );
+    CPL_IGNORE_RET_VAL_INT(VSIFCloseL( psDInfo->fp ));
 
     CPLFree( psDInfo->pachUHLRecord );
     CPLFree( psDInfo->pachDSIRecord );
diff --git a/frmts/dted/dted_api.h b/frmts/dted/dted_api.h
index cb78bc3..328b7fe 100644
--- a/frmts/dted/dted_api.h
+++ b/frmts/dted/dted_api.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dted_api.h 28575 2015-02-28 09:41:10Z rouault $
+ * $Id: dted_api.h 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  DTED Translator
  * Purpose:  Public (C callable) interface for DTED/CDED reading.
@@ -28,8 +28,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _DTED_API_H_INCLUDED
-#define _DTED_API_H_INCLUDED
+#ifndef DTED_API_H_INCLUDED
+#define DTED_API_H_INCLUDED
 
 /* -------------------------------------------------------------------- */
 /*      To avoid dependence on CPL, just define AVOID_CPL when          */
@@ -37,6 +37,7 @@
 /* -------------------------------------------------------------------- */
 #ifndef AVOID_CPL
 #  include "cpl_conv.h"
+#  include "cpl_string.h"
 #else
 
 #include <stdio.h>
@@ -138,7 +139,7 @@ DTEDInfo *DTEDOpenEx( VSILFILE* fp, const char * pszFilename,
 
 /**     Read one single sample. The coordinates are given from the
         top-left corner of the file (contrary to the internal
-        organisation or a DTED file)
+        organization or a DTED file)
 */
 int DTEDReadPoint( DTEDInfo * psDInfo, int nXOff, int nYOff, GInt16* panVal);
 
@@ -161,7 +162,7 @@ int DTEDWriteProfile( DTEDInfo *psDInfo, int nColumnOffset, GInt16 *panData);
 
 void DTEDClose( DTEDInfo * );
 
-const char *DTEDCreate( const char *pszFilename, 
+const char *DTEDCreate( const char *pszFilename,
                         int nLevel, int nLLOriginLat, int nLLOriginLong );
 
 /* -------------------------------------------------------------------- */
@@ -169,11 +170,11 @@ const char *DTEDCreate( const char *pszFilename,
 /* -------------------------------------------------------------------- */
 typedef enum {
     DTEDMD_VERTACCURACY_UHL = 1,            /* UHL 29+4, ACC 8+4 */
-    DTEDMD_VERTACCURACY_ACC = 2,           
+    DTEDMD_VERTACCURACY_ACC = 2,
     DTEDMD_SECURITYCODE_UHL = 3,            /* UHL 33+3, DSI 4+1 */
-    DTEDMD_SECURITYCODE_DSI = 4,           
+    DTEDMD_SECURITYCODE_DSI = 4,
     DTEDMD_UNIQUEREF_UHL = 5,               /* UHL 36+12, DSI 65+15*/
-    DTEDMD_UNIQUEREF_DSI = 6,              
+    DTEDMD_UNIQUEREF_DSI = 6,
     DTEDMD_DATA_EDITION = 7,            /* DSI 88+2 */
     DTEDMD_MATCHMERGE_VERSION = 8,      /* DSI 90+1 */
     DTEDMD_MAINT_DATE = 9,              /* DSI 91+4 */
@@ -186,15 +187,14 @@ typedef enum {
     DTEDMD_HORIZACCURACY = 16,          /* ACC 4+4 */
     DTEDMD_REL_HORIZACCURACY = 17,      /* ACC 12+4 */
     DTEDMD_REL_VERTACCURACY = 18,       /* ACC 16+4 */
-    DTEDMD_HORIZDATUM = 19,             /* DSI 145+5 */ 
+    DTEDMD_HORIZDATUM = 19,             /* DSI 145+5 */
     DTEDMD_ORIGINLONG = 20,             /* UHL 5+7 */
     DTEDMD_ORIGINLAT = 21,              /* UHL 13+7 */
     DTEDMD_NIMA_DESIGNATOR = 22,        /* DSI 60 + 5 */
-    DTEDMD_PARTIALCELL_DSI = 23,        /* DSI 289 + 2 */ 
+    DTEDMD_PARTIALCELL_DSI = 23,        /* DSI 289 + 2 */
     DTEDMD_MAX = 23
 } DTEDMetaDataCode;
 
-    
 char *DTEDGetMetadata( DTEDInfo *, DTEDMetaDataCode );
 int   DTEDSetMetadata( DTEDInfo *, DTEDMetaDataCode, const char *);
 
@@ -210,6 +210,4 @@ void  DTEDPtStreamTrimEdgeOnlyTiles( void *hStream );
 
 CPL_C_END
 
-#endif /* ndef _DTED_API_H_INCLUDED */
-
-
+#endif /* ndef DTED_API_H_INCLUDED */
diff --git a/frmts/dted/dted_create.c b/frmts/dted/dted_create.c
index ab76fbd..72d081e 100644
--- a/frmts/dted/dted_create.c
+++ b/frmts/dted/dted_create.c
@@ -1,9 +1,9 @@
 /******************************************************************************
- * $Id: dted_create.c 28433 2015-02-06 21:18:50Z rouault $
+ * $Id: dted_create.c 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  DTED Translator
  * Purpose:  Implementation of DTEDCreate() portion of DTED API.
- * Author:   Frank Warmerdam, warmerdamm at pobox.com
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
  * Copyright (c) 2001, Frank Warmerdam
@@ -30,7 +30,7 @@
 #include "dted_api.h"
 #include <assert.h>
 
-CPL_CVSID("$Id: dted_create.c 28433 2015-02-06 21:18:50Z rouault $");
+CPL_CVSID("$Id: dted_create.c 33720 2016-03-15 00:39:53Z goatbar $");
 
 #define DTED_ABS_VERT_ACC "NA  "
 #define DTED_SECURITY     "U"
@@ -40,7 +40,7 @@ CPL_CVSID("$Id: dted_create.c 28433 2015-02-06 21:18:50Z rouault $");
 /*                           DTEDFormatDMS()                            */
 /************************************************************************/
 
-static void DTEDFormatDMS( unsigned char *achField, double dfAngle, 
+static void DTEDFormatDMS( unsigned char *achField, double dfAngle,
                            const char *pszLatLong, const char *pszFormat )
 
 {
@@ -48,12 +48,12 @@ static void DTEDFormatDMS( unsigned char *achField, double dfAngle,
     char        szWork[128];
     int         nDegrees, nMinutes, nSeconds;
     double      dfRemainder;
-    
+
     if( pszFormat == NULL )
         pszFormat = "%03d%02d%02d%c";
 
     assert( EQUAL(pszLatLong,"LAT") || EQUAL(pszLatLong,"LONG") );
-    
+
     if( EQUAL(pszLatLong,"LAT") )
     {
         if( dfAngle < 0.0 )
@@ -77,7 +77,7 @@ static void DTEDFormatDMS( unsigned char *achField, double dfAngle,
     dfRemainder = dfRemainder - nMinutes / 60.0;
     nSeconds = (int) floor(dfRemainder * 3600.0 + 0.5);
 
-    sprintf( szWork, pszFormat,
+    snprintf( szWork, sizeof(szWork),pszFormat,
              nDegrees, nMinutes, nSeconds, chHemisphere );
 
     strncpy( (char *) achField, szWork, strlen(szWork) );
@@ -94,9 +94,11 @@ static void DTEDFormat( unsigned char *pszTarget, const char *pszFormat, ... )
 {
     va_list args;
     char    szWork[512];
+    // Quiet coverity by staring off nul terminated.
+    szWork[0] = '\0';
 
     va_start(args, pszFormat);
-    vsprintf( szWork, pszFormat, args );
+    CPLvsnprintf( szWork, sizeof(szWork), pszFormat, args );
     va_end(args);
 
     strncpy( (char *) pszTarget, szWork, strlen(szWork) );
@@ -106,7 +108,7 @@ static void DTEDFormat( unsigned char *pszTarget, const char *pszFormat, ... )
 /*                             DTEDCreate()                             */
 /************************************************************************/
 
-const char *DTEDCreate( const char *pszFilename, int nLevel, 
+const char *DTEDCreate( const char *pszFilename, int nLevel,
                         int nLLOriginLat, int nLLOriginLong )
 
 {
@@ -127,7 +129,7 @@ const char *DTEDCreate( const char *pszFilename, int nLevel,
     {
         nXSize = 1201;
         nYSize = 1201;
-    } 
+    }
     else if( nLevel == 2 )
     {
         nXSize = 3601;
@@ -135,7 +137,7 @@ const char *DTEDCreate( const char *pszFilename, int nLevel,
     }
     else
     {
-        sprintf( szError, "Illegal DTED Level value %d, only 0-2 allowed.",
+        snprintf( szError, sizeof(szError), "Illegal DTED Level value %d, only 0-2 allowed.",
                  nLevel );
         return szError;
     }
@@ -156,7 +158,7 @@ const char *DTEDCreate( const char *pszFilename, int nLevel,
 
     if( fp == NULL )
     {
-        sprintf( szError, "Unable to create file `%s'.", pszFilename );
+        snprintf( szError, sizeof(szError), "Unable to create file `%s'.", pszFilename );
         return szError;
     }
 
@@ -166,7 +168,7 @@ const char *DTEDCreate( const char *pszFilename, int nLevel,
     memset( achRecord, ' ', DTED_UHL_SIZE );
 
     DTEDFormat( achRecord + 0, "UHL1" );
-    
+
     DTEDFormatDMS( achRecord + 4, nLLOriginLong, "LONG", NULL );
     DTEDFormatDMS( achRecord + 12, nLLOriginLat, "LAT", NULL );
 
@@ -204,9 +206,9 @@ const char *DTEDCreate( const char *pszFilename, int nLevel,
     DTEDFormat( achRecord + 144, "WGS84" );
 
     /* origin */
-    DTEDFormatDMS( achRecord + 185, nLLOriginLat, "LAT", 
+    DTEDFormatDMS( achRecord + 185, nLLOriginLat, "LAT",
                    "%02d%02d%02d.0%c" );
-    DTEDFormatDMS( achRecord + 194, nLLOriginLong, "LONG", 
+    DTEDFormatDMS( achRecord + 194, nLLOriginLong, "LONG",
                    "%03d%02d%02d.0%c" );
 
     /* SW */
@@ -251,7 +253,7 @@ const char *DTEDCreate( const char *pszFilename, int nLevel,
     DTEDFormat( achRecord + 15, "NA" );
 
     DTEDFormat( achRecord + 55, "00" );
-    
+
     if( VSIFWriteL( achRecord, DTED_ACC_SIZE, 1, fp ) != 1 )
         return "ACC record write failed.";
 
@@ -262,13 +264,13 @@ const char *DTEDCreate( const char *pszFilename, int nLevel,
     memset( achRecord + 8, 0xff, nYSize*2 );
 
     achRecord[0] = 0252;
-    
+
     for( iProfile = 0; iProfile < nXSize; iProfile++ )
     {
         achRecord[1] = 0;
         achRecord[2] = (GByte) (iProfile / 256);
         achRecord[3] = (GByte) (iProfile % 256);
-        
+
         achRecord[4] = (GByte) (iProfile / 256);
         achRecord[5] = (GByte) (iProfile % 256);
 
@@ -276,7 +278,8 @@ const char *DTEDCreate( const char *pszFilename, int nLevel,
             return "Data record write failed.";
     }
 
-    VSIFCloseL( fp );
+    if( VSIFCloseL( fp ) != 0 )
+        return "I/O error";
 
     return NULL;
 }
diff --git a/frmts/dted/dted_ptstream.c b/frmts/dted/dted_ptstream.c
index 85ced28..ba3961d 100644
--- a/frmts/dted/dted_ptstream.c
+++ b/frmts/dted/dted_ptstream.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dted_ptstream.c 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: dted_ptstream.c 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  DTED Translator
  * Purpose:  DTED Point Stream Writer.
@@ -29,7 +29,7 @@
 
 #include "dted_api.h"
 
-CPL_CVSID("$Id: dted_ptstream.c 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: dted_ptstream.c 33720 2016-03-15 00:39:53Z goatbar $");
 
 typedef struct {
     char     *pszFilename;
@@ -105,7 +105,7 @@ void *DTEDCreatePtStream( const char *pszPath, int nLevel )
         psStream->dfPixelSize = 1.0 / 3600.0;
     else
         psStream->dfPixelSize = 1.0 / 3600.0;
-    
+
     return (void *) psStream;
 }
 
@@ -116,7 +116,7 @@ void *DTEDCreatePtStream( const char *pszPath, int nLevel )
 /*      "current".                                                      */
 /************************************************************************/
 
-static int DTEDPtStreamNewTile( DTEDPtStream *psStream, 
+static int DTEDPtStreamNewTile( DTEDPtStream *psStream,
                                 int nCrLong, int nCrLat )
 
 {
@@ -137,21 +137,21 @@ static int DTEDPtStreamNewTile( DTEDPtStream *psStream,
     else
         chEWHemi = 'e';
 
-    sprintf( szFile, "%c%03d%c%03d.dt%d", 
+    snprintf( szFile, sizeof(szFile), "%c%03d%c%03d.dt%d",
              chEWHemi, ABS(nCrLong), chNSHemi, ABS(nCrLat),
              psStream->nLevel );
 
-    pszFullFilename = 
+    pszFullFilename =
         CPLStrdup(CPLFormFilename( psStream->pszPath, szFile, NULL ));
 
     /* create the dted file */
-    pszError = DTEDCreate( pszFullFilename, psStream->nLevel, 
+    pszError = DTEDCreate( pszFullFilename, psStream->nLevel,
                            nCrLat, nCrLong );
     if( pszError != NULL )
     {
 #ifndef AVOID_CPL
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Failed to create DTED file `%s'.\n%s", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to create DTED file `%s'.\n%s",
                   pszFullFilename, pszError );
 #endif
         return FALSE;
@@ -167,8 +167,8 @@ static int DTEDPtStreamNewTile( DTEDPtStream *psStream,
 
     /* add cached file to stream */
     psStream->nOpenFiles++;
-    psStream->pasCF = 
-        CPLRealloc(psStream->pasCF, 
+    psStream->pasCF =
+        CPLRealloc(psStream->pasCF,
                    sizeof(DTEDCachedFile)*psStream->nOpenFiles);
 
     psStream->pasCF[psStream->nOpenFiles-1].psInfo = psInfo;
@@ -205,7 +205,7 @@ static int DTEDWritePtLL( CPL_UNUSED DTEDPtStream *psStream,
 
     if( psCF->papanProfiles[iProfile] == NULL )
     {
-        psCF->papanProfiles[iProfile] = 
+        psCF->papanProfiles[iProfile] =
             CPLMalloc(sizeof(GInt16) * psInfo->nYSize);
 
         for( i = 0; i < psInfo->nYSize; i++ )
@@ -243,9 +243,9 @@ int DTEDWritePt( void *hStream, double dfLong, double dfLat, double dfElev )
 /*      area of the edge "pixel" that is shared with adjacent           */
 /*      tiles.                                                          */
 /* -------------------------------------------------------------------- */
-    if( (floor(dfLong - 0.5*psStream->dfPixelSize) 
+    if( (floor(dfLong - 0.5*psStream->dfPixelSize)
          != floor(dfLong + 0.5*psStream->dfPixelSize))
-        || (floor(dfLat - 0.5*psStream->dfPixelSize) 
+        || (floor(dfLat - 0.5*psStream->dfPixelSize)
             != floor(dfLat + 0.5*psStream->dfPixelSize)) )
     {
         bOnBoundary = TRUE;
@@ -264,7 +264,7 @@ int DTEDWritePt( void *hStream, double dfLong, double dfLat, double dfElev )
         if( psStream->nLastFile != -1 )
         {
             psInfo = psStream->pasCF[psStream->nLastFile].psInfo;
-            
+
             if( dfLat > psInfo->dfULCornerY
                 || dfLat < psInfo->dfULCornerY - 1.0 - psInfo->dfPixelSizeY
                 || dfLong < psInfo->dfULCornerX
@@ -278,7 +278,7 @@ int DTEDWritePt( void *hStream, double dfLong, double dfLat, double dfElev )
         for( i = 0; i < psStream->nOpenFiles && psStream->nLastFile == -1; i++ )
         {
             psInfo = psStream->pasCF[i].psInfo;
-            
+
             if( !(dfLat > psInfo->dfULCornerY
                   || dfLat < psInfo->dfULCornerY - 1.0 - psInfo->dfPixelSizeY
                   || dfLong < psInfo->dfULCornerX
@@ -294,10 +294,10 @@ int DTEDWritePt( void *hStream, double dfLong, double dfLat, double dfElev )
         if( psStream->nLastFile == -1 )
         {
             int nCrLong, nCrLat;
-            
+
             nCrLong = (int) floor(dfLong);
             nCrLat = (int) floor(dfLat);
-            
+
             if( !DTEDPtStreamNewTile( psStream, nCrLong, nCrLat ) )
                 return FALSE;
         }
@@ -305,7 +305,7 @@ int DTEDWritePt( void *hStream, double dfLong, double dfLat, double dfElev )
 /* -------------------------------------------------------------------- */
 /*      Write data out to selected tile.                                */
 /* -------------------------------------------------------------------- */
-        return DTEDWritePtLL( psStream, psStream->pasCF + psStream->nLastFile, 
+        return DTEDWritePtLL( psStream, psStream->pasCF + psStream->nLastFile,
                               dfLong, dfLat, dfElev );
     }
 
@@ -354,14 +354,14 @@ int DTEDWritePt( void *hStream, double dfLong, double dfLat, double dfElev )
 /* -------------------------------------------------------------------- */
 /*      Write to the tile.                                              */
 /* -------------------------------------------------------------------- */
-                if( !DTEDWritePtLL( psStream, 
-                                    psStream->pasCF + psStream->nLastFile, 
+                if( !DTEDWritePtLL( psStream,
+                                    psStream->pasCF + psStream->nLastFile,
                                     dfLong, dfLat, dfElev ) )
                     return FALSE;
             }
         }
     }
-    
+
     return TRUE;
 }
 
@@ -387,7 +387,7 @@ void DTEDClosePtStream( void *hStream )
         {
             if( psCF->papanProfiles[iProfile] != NULL )
             {
-                DTEDWriteProfile( psCF->psInfo, iProfile, 
+                DTEDWriteProfile( psCF->psInfo, iProfile,
                                   psCF->papanProfiles[iProfile] );
                 CPLFree( psCF->papanProfiles[iProfile] );
             }
@@ -395,10 +395,10 @@ void DTEDClosePtStream( void *hStream )
 
         CPLFree( psCF->papanProfiles );
 
-        for( iMD = 0; iMD < DTEDMD_MAX+1; iMD++ )
+        for( iMD = 0; iMD <= DTEDMD_MAX; iMD++ )
         {
             if( psStream->apszMetadata[iMD] != NULL )
-                DTEDSetMetadata( psCF->psInfo, iMD, 
+                DTEDSetMetadata( psCF->psInfo, (DTEDMetaDataCode)iMD,
                                  psStream->apszMetadata[iMD] );
         }
 
@@ -420,9 +420,9 @@ void DTEDClosePtStream( void *hStream )
 /************************************************************************/
 /*                           DTEDFillPixel()                            */
 /************************************************************************/
-
-void DTEDFillPixel( DTEDInfo *psInfo, GInt16 **papanProfiles, 
-                    GInt16 **papanDstProfiles, int iX, int iY, 
+static
+void DTEDFillPixel( DTEDInfo *psInfo, GInt16 **papanProfiles,
+                    GInt16 **papanDstProfiles, int iX, int iY,
                     int nPixelSearchDist, float *pafKernel )
 
 {
@@ -488,17 +488,17 @@ void DTEDFillPtStream( void *hStream, int nPixelSearchDist )
 /* -------------------------------------------------------------------- */
     nKernelWidth = 2 * nPixelSearchDist + 1;
     pafKernel = (float *) CPLMalloc(nKernelWidth*nKernelWidth*sizeof(float));
-    
+
     for( iX = 0; iX < nKernelWidth; iX++ )
     {
         for( iY = 0; iY < nKernelWidth; iY++ )
         {
-            pafKernel[iX + iY * nKernelWidth] = (float) (1.0 / 
+            pafKernel[iX + iY * nKernelWidth] = (float) (1.0 /
                 sqrt( (nPixelSearchDist-iX) * (nPixelSearchDist-iX)
                       + (nPixelSearchDist-iY) * (nPixelSearchDist-iY) ));
         }
     }
-        
+
 /* ==================================================================== */
 /*      Process each cached file.                                       */
 /* ==================================================================== */
@@ -510,13 +510,13 @@ void DTEDFillPtStream( void *hStream, int nPixelSearchDist )
 
         papanDstProfiles = (GInt16 **)
             CPLCalloc(sizeof(GInt16*),psInfo->nXSize);
-        
+
 /* -------------------------------------------------------------------- */
 /*      Setup output image.                                             */
 /* -------------------------------------------------------------------- */
         for( iX = 0; iX < psInfo->nXSize; iX++ )
         {
-            papanDstProfiles[iX] = (GInt16 *) 
+            papanDstProfiles[iX] = (GInt16 *)
                 CPLMalloc(sizeof(GInt16) * psInfo->nYSize);
         }
 
@@ -530,7 +530,7 @@ void DTEDFillPtStream( void *hStream, int nPixelSearchDist )
                 if( papanProfiles[iX] == NULL
                     || papanProfiles[iX][iY] == DTED_NODATA_VALUE )
                 {
-                    DTEDFillPixel( psInfo, papanProfiles, papanDstProfiles, 
+                    DTEDFillPixel( psInfo, papanProfiles, papanDstProfiles,
                                    iX, iY, nPixelSearchDist, pafKernel );
                 }
                 else
@@ -549,7 +549,7 @@ void DTEDFillPtStream( void *hStream, int nPixelSearchDist )
         }
 
         CPLFree( papanDstProfiles );
-    }    
+    }
 
     CPLFree( pafKernel );
 }
@@ -558,7 +558,7 @@ void DTEDFillPtStream( void *hStream, int nPixelSearchDist )
 /*                      DTEDPtStreamSetMetadata()                       */
 /************************************************************************/
 
-void DTEDPtStreamSetMetadata( void *hStream, DTEDMetaDataCode eCode, 
+void DTEDPtStreamSetMetadata( void *hStream, DTEDMetaDataCode eCode,
                               const char *pszValue )
 
 {
@@ -603,26 +603,26 @@ void DTEDPtStreamTrimEdgeOnlyTiles( void *hStream )
                 }
             }
         }
-        
+
         if( bGotNonEdgeData )
             continue;
 
         /* Remove this tile */
-        
+
         for( iProfile = 0; iProfile < psInfo->nXSize; iProfile++ )
         {
             if( papanProfiles[iProfile] != NULL )
                 CPLFree( papanProfiles[iProfile] );
         }
         CPLFree( papanProfiles );
-        
+
         DTEDClose( psInfo );
 
         VSIUnlink( psStream->pasCF[iFile].pszFilename );
         CPLFree( psStream->pasCF[iFile].pszFilename );
 
-        memmove( psStream->pasCF + iFile, 
-                 psStream->pasCF + iFile + 1, 
+        memmove( psStream->pasCF + iFile,
+                 psStream->pasCF + iFile + 1,
                  sizeof(DTEDCachedFile) * (psStream->nOpenFiles-iFile-1) );
         psStream->nOpenFiles--;
     }
diff --git a/frmts/dted/dted_test.c b/frmts/dted/dted_test.c
index 6830498..43a129f 100644
--- a/frmts/dted/dted_test.c
+++ b/frmts/dted/dted_test.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dted_test.c 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: dted_test.c 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  DTED Translator
  * Purpose:  Test mainline for DTED writer.
@@ -79,7 +79,7 @@ int main( int argc, char ** argv )
                 Usage();
             pszFilename = argv[iArg];
         }
-    }		
+    }
 
     if( pszFilename == NULL )
         Usage();
@@ -116,7 +116,7 @@ int main( int argc, char ** argv )
 
     for( iY = 0; iY < nYSize; iY++ )
     {
-        GDALRasterIO( hSrcBand, GF_Read, 0, iY, nXSize, 1, 
+        GDALRasterIO( hSrcBand, GF_Read, 0, iY, nXSize, 1,
                       panData, nXSize, 1, GDT_Int16, 0, 0 );
 
         if (bHasNoData)
@@ -130,11 +130,11 @@ int main( int argc, char ** argv )
 
         for( iX = 0; iX < nXSize; iX++ )
         {
-            DTEDWritePt( pStream, 
-                         adfGeoTransform[0] 
+            DTEDWritePt( pStream,
+                         adfGeoTransform[0]
                          + adfGeoTransform[1] * (iX + 0.5)
                          + adfGeoTransform[2] * (iY + 0.5),
-                         adfGeoTransform[3] 
+                         adfGeoTransform[3]
                          + adfGeoTransform[4] * (iX + 0.5)
                          + adfGeoTransform[5] * (iY + 0.5),
                          panData[iX] );
diff --git a/frmts/dted/dteddataset.cpp b/frmts/dted/dteddataset.cpp
index f80173c..eac7816 100644
--- a/frmts/dted/dteddataset.cpp
+++ b/frmts/dted/dteddataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dteddataset.cpp 29017 2015-04-25 19:32:11Z rouault $
+ * $Id: dteddataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  DTED Translator
  * Purpose:  GDALDataset driver for DTED translator.
@@ -29,15 +29,13 @@
  ****************************************************************************/
 
 #include "dted_api.h"
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
-#include <algorithm>
 
-CPL_CVSID("$Id: dteddataset.cpp 29017 2015-04-25 19:32:11Z rouault $");
+#include <algorithm>
 
-CPL_C_START
-void    GDALRegister_DTED(void);
-CPL_C_END
+CPL_CVSID("$Id: dteddataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -59,13 +57,13 @@ class DTEDDataset : public GDALPamDataset
   public:
                  DTEDDataset();
     virtual     ~DTEDDataset();
-    
+
     virtual const char *GetProjectionRef(void);
     virtual CPLErr GetGeoTransform( double * );
-    
+
     const char* GetFileName() { return pszFilename; }
     void SetFileName(const char* pszFilename);
-    
+
     static GDALDataset *Open( GDALOpenInfo * );
     static int Identify( GDALOpenInfo * );
 };
@@ -86,7 +84,7 @@ class DTEDRasterBand : public GDALPamRasterBand
   public:
 
                 DTEDRasterBand( DTEDDataset *, int );
-    
+
     virtual CPLErr IReadBlock( int, int, void * );
     virtual CPLErr IWriteBlock( int, int, void * );
 
@@ -100,15 +98,14 @@ class DTEDRasterBand : public GDALPamRasterBand
 /*                           DTEDRasterBand()                            */
 /************************************************************************/
 
-DTEDRasterBand::DTEDRasterBand( DTEDDataset *poDS, int nBand )
-
+DTEDRasterBand::DTEDRasterBand( DTEDDataset *poDSIn, int nBandIn ) :
+    bNoDataSet(TRUE)
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
-    
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
+
     eDataType = GDT_Int16;
 
-    bNoDataSet = TRUE;
     dfNoDataValue = (double) DTED_NODATA_VALUE;
 
     /* For some applications, it may be valuable to consider the whole DTED */
@@ -116,7 +113,7 @@ DTEDRasterBand::DTEDRasterBand( DTEDDataset *poDS, int nBand )
     /* with some scanline oriented algorithms */
     /* Of course you need to have a big enough case size, particularly for DTED 2 */
     /* datasets */
-    nBlockXSize = CSLTestBoolean(CPLGetConfigOption("GDAL_DTED_SINGLE_BLOCK", "NO")) ?
+    nBlockXSize = CPLTestBool(CPLGetConfigOption("GDAL_DTED_SINGLE_BLOCK", "NO")) ?
                             poDS->GetRasterXSize() : 1;
     nBlockYSize = poDS->GetRasterYSize();
 }
@@ -162,7 +159,7 @@ CPLErr DTEDRasterBand::IReadBlock( int nBlockXOff,
         CPLFree(panBuffer);
         return CE_None;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read the data.                                                  */
 /* -------------------------------------------------------------------- */
@@ -247,11 +244,11 @@ double DTEDRasterBand::GetNoDataValue( int * pbSuccess )
 /*                            ~DTEDDataset()                            */
 /************************************************************************/
 
-DTEDDataset::DTEDDataset()
+DTEDDataset::DTEDDataset() : psDTED(NULL)
 {
     pszFilename = CPLStrdup("unknown");
     pszProjection = CPLStrdup("");
-    bVerifyChecksum = CSLTestBoolean(CPLGetConfigOption("DTED_VERIFY_CHECKSUM", "NO"));
+    bVerifyChecksum = CPLTestBool(CPLGetConfigOption("DTED_VERIFY_CHECKSUM", "NO"));
 }
 
 /************************************************************************/
@@ -272,11 +269,11 @@ DTEDDataset::~DTEDDataset()
 /*                            SetFileName()                             */
 /************************************************************************/
 
-void DTEDDataset::SetFileName(const char* pszFilename)
+void DTEDDataset::SetFileName(const char* pszFilenameIn)
 
 {
     CPLFree(this->pszFilename);
-    this->pszFilename = CPLStrdup(pszFilename);
+    this->pszFilename = CPLStrdup(pszFilenameIn);
 }
 
 /************************************************************************/
@@ -286,8 +283,6 @@ void DTEDDataset::SetFileName(const char* pszFilename)
 int DTEDDataset::Identify( GDALOpenInfo * poOpenInfo )
 
 {
-    int         i;
-
 /* -------------------------------------------------------------------- */
 /*      Does the file start with one of the possible DTED header        */
 /*      record types, and do we have a UHL marker?                      */
@@ -295,19 +290,19 @@ int DTEDDataset::Identify( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->nHeaderBytes < 240 )
         return FALSE;
 
-    if( !EQUALN((const char *)poOpenInfo->pabyHeader,"VOL",3)
-        && !EQUALN((const char *)poOpenInfo->pabyHeader,"HDR",3)
-        && !EQUALN((const char *)poOpenInfo->pabyHeader,"UHL",3) )
+    if( !STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "VOL")
+        && !STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "HDR")
+        && !STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "UHL") )
     {
         return FALSE;
     }
 
-    int bFoundUHL = FALSE;
-    for(i=0;i<poOpenInfo->nHeaderBytes-3 && !bFoundUHL ;i += DTED_UHL_SIZE)
+    bool bFoundUHL = false;
+    for(int i=0;i<poOpenInfo->nHeaderBytes-3 && !bFoundUHL ;i += DTED_UHL_SIZE)
     {
-        if( EQUALN((const char *)poOpenInfo->pabyHeader + i,"UHL", 3) )
+        if( STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader + i, "UHL") )
         {
-            bFoundUHL = TRUE;
+            bFoundUHL = true;
         }
     }
     if (!bFoundUHL)
@@ -323,9 +318,6 @@ int DTEDDataset::Identify( GDALOpenInfo * poOpenInfo )
 GDALDataset *DTEDDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    int         i;
-    DTEDInfo    *psDTED;
-
     if (!Identify(poOpenInfo) || poOpenInfo->fpL == NULL )
         return NULL;
 
@@ -334,7 +326,8 @@ GDALDataset *DTEDDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     VSILFILE* fp = poOpenInfo->fpL;
     poOpenInfo->fpL = NULL;
-    psDTED = DTEDOpenEx( fp, poOpenInfo->pszFilename, 
+    DTEDInfo *psDTED
+        = DTEDOpenEx( fp, poOpenInfo->pszFilename,
                          (poOpenInfo->eAccess == GA_Update) ? "rb+" : "rb", TRUE );
 
     if( psDTED == NULL )
@@ -343,9 +336,8 @@ GDALDataset *DTEDDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    DTEDDataset         *poDS;
-
-    poDS = new DTEDDataset();
+    DTEDDataset *poDS
+        = new DTEDDataset();
     poDS->SetFileName(poOpenInfo->pszFilename);
 
     poDS->eAccess = poOpenInfo->eAccess;
@@ -356,18 +348,18 @@ GDALDataset *DTEDDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->nRasterXSize = psDTED->nXSize;
     poDS->nRasterYSize = psDTED->nYSize;
-    
+
     if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
     {
         delete poDS;
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
     poDS->nBands = 1;
-    for( i = 0; i < poDS->nBands; i++ )
+    for( int i = 0; i < poDS->nBands; i++ )
         poDS->SetBand( i+1, new DTEDRasterBand( poDS, i+1 ) );
 
 /* -------------------------------------------------------------------- */
@@ -450,17 +442,17 @@ GDALDataset *DTEDDataset::Open( GDALOpenInfo * poOpenInfo )
     pszValue = DTEDGetMetadata( psDTED, DTEDMD_REL_VERTACCURACY );
     poDS->SetMetadataItem( "DTED_RelVerticalAccuracy", pszValue );
     CPLFree( pszValue );
-    
+
     pszValue = DTEDGetMetadata( psDTED, DTEDMD_ORIGINLAT );
     poDS->SetMetadataItem( "DTED_OriginLatitude", pszValue );
     CPLFree( pszValue );
-    
+
     pszValue = DTEDGetMetadata( psDTED, DTEDMD_ORIGINLONG );
     poDS->SetMetadataItem( "DTED_OriginLongitude", pszValue );
     CPLFree( pszValue );
-    
-    pszValue = DTEDGetMetadata( psDTED, DTEDMD_NIMA_DESIGNATOR ); 
-    poDS->SetMetadataItem( "DTED_NimaDesignator", pszValue ); 
+
+    pszValue = DTEDGetMetadata( psDTED, DTEDMD_NIMA_DESIGNATOR );
+    poDS->SetMetadataItem( "DTED_NimaDesignator", pszValue );
     CPLFree( pszValue );
 
     pszValue = DTEDGetMetadata( psDTED, DTEDMD_PARTIALCELL_DSI );
@@ -548,10 +540,10 @@ const char *DTEDDataset::GetProjectionRef()
     }
     else if (EQUAL(pszPrj, "WGS72"))
     {
-        static int bWarned = FALSE;
+        static bool bWarned = false;
         if (!bWarned)
         {
-            bWarned = TRUE;
+            bWarned = true;
             CPLError( CE_Warning, CPLE_AppDefined,
                       "The DTED file %s indicates WGS72 as horizontal datum. \n"
                       "As this is outdated nowadays, you should contact your data producer to get data georeferenced in WGS84.\n"
@@ -560,14 +552,14 @@ const char *DTEDDataset::GetProjectionRef()
                       "fix the DTED file.\n"
                       "No more warnings will be issued in this session about this operation.", GetFileName() );
         }
-        return "GEOGCS[\"WGS 72\",DATUM[\"WGS_1972\",SPHEROID[\"WGS 72\",6378135,298.26]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433],AUTHORITY[\"EPSG\",\"4322\"]]"; 
+        return "GEOGCS[\"WGS 72\",DATUM[\"WGS_1972\",SPHEROID[\"WGS 72\",6378135,298.26]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433],AUTHORITY[\"EPSG\",\"4322\"]]";
     }
     else
     {
-        static int bWarned = FALSE;
+        static bool bWarned = false;
         if (!bWarned)
         {
-            bWarned = TRUE;
+            bWarned = true;
             CPLError( CE_Warning, CPLE_AppDefined,
                       "The DTED file %s indicates %s as horizontal datum, which is not recognized by the DTED driver. \n"
                       "The DTED driver is going to consider it as WGS84.\n"
@@ -585,31 +577,25 @@ const char *DTEDDataset::GetProjectionRef()
 /************************************************************************/
 
 static GDALDataset *
-DTEDCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
-                int bStrict, char ** papszOptions, 
-                GDALProgressFunc pfnProgress, void * pProgressData )
+DTEDCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
+                int bStrict, char ** /* papszOptions */,
+                GDALProgressFunc pfnProgress, void *pProgressData)
 
 {
-    (void) pProgressData;
-    (void) pfnProgress;
-    (void) papszOptions;
-    (void) bStrict;
-
-
 /* -------------------------------------------------------------------- */
 /*      Some some rudimentary checks                                    */
 /* -------------------------------------------------------------------- */
-    int nBands = poSrcDS->GetRasterCount();
+    const int nBands = poSrcDS->GetRasterCount();
     if (nBands == 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "DTED driver does not support source dataset with zero band.\n");
         return NULL;
     }
-    
+
     if (nBands != 1)
     {
-        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, 
+        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
                   "DTED driver only uses the first band of the dataset.\n");
         if (bStrict)
             return NULL;
@@ -631,7 +617,7 @@ DTEDCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         nLevel = 2;
     else
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                "The source does not appear to be a properly formatted cell." );
         nLevel = 1;
     }
@@ -639,14 +625,14 @@ DTEDCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Checks the input SRS                                            */
 /* -------------------------------------------------------------------- */
-    OGRSpatialReference ogrsr_input;
-    OGRSpatialReference ogrsr_wgs84;
     char* c = (char*)poSrcDS->GetProjectionRef();
+    OGRSpatialReference ogrsr_input;
     ogrsr_input.importFromWkt(&c);
+    OGRSpatialReference ogrsr_wgs84;
     ogrsr_wgs84.SetWellKnownGeogCS( "WGS84" );
     if ( ogrsr_input.IsSameGeogCS(&ogrsr_wgs84) == FALSE)
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "The source projection coordinate system is %s. Only WGS 84 is supported.\n"
                   "The DTED driver will generate a file as if the source was WGS 84 projection coordinate system.",
                   poSrcDS->GetProjectionRef() );
@@ -655,22 +641,21 @@ DTEDCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Work out the LL origin.                                         */
 /* -------------------------------------------------------------------- */
-    int  nLLOriginLat, nLLOriginLong;
     double adfGeoTransform[6];
 
     poSrcDS->GetGeoTransform( adfGeoTransform );
 
-    nLLOriginLat = (int) 
-        floor(adfGeoTransform[3] 
+    int nLLOriginLat = (int)
+        floor(adfGeoTransform[3]
               + poSrcDS->GetRasterYSize() * adfGeoTransform[5] + 0.5);
-    
-    nLLOriginLong = (int) floor(adfGeoTransform[0] + 0.5);
 
-    if (fabs(nLLOriginLat - (adfGeoTransform[3] 
+    int nLLOriginLong = (int) floor(adfGeoTransform[0] + 0.5);
+
+    if (fabs(nLLOriginLat - (adfGeoTransform[3]
               + (poSrcDS->GetRasterYSize() - 0.5) * adfGeoTransform[5])) > 1e-10 ||
         fabs(nLLOriginLong - (adfGeoTransform[0] + 0.5 * adfGeoTransform[1])) > 1e-10)
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                "The corner coordinates of the source are not properly "
                "aligned on plain latitude/longitude boundaries.");
     }
@@ -692,7 +677,7 @@ DTEDCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
     if (poSrcDS->GetRasterXSize() != expectedXSize)
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                "The horizontal source size is not conformant with the one "
                "expected by DTED Level %d at this latitude (%d pixels found instead of %d).", nLevel,
                 poSrcDS->GetRasterXSize(), expectedXSize);
@@ -701,13 +686,12 @@ DTEDCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Create the output dted file.                                    */
 /* -------------------------------------------------------------------- */
-    const char *pszError;
-
-    pszError = DTEDCreate( pszFilename, nLevel, nLLOriginLat, nLLOriginLong );
+    const char *pszError
+        = DTEDCreate( pszFilename, nLevel, nLLOriginLat, nLLOriginLong );
 
     if( pszError != NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", pszError );
         return NULL;
     }
@@ -715,9 +699,8 @@ DTEDCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Open the DTED file so we can output the data to it.             */
 /* -------------------------------------------------------------------- */
-    DTEDInfo *psDTED;
-
-    psDTED = DTEDOpen( pszFilename, "rb+", FALSE );
+    DTEDInfo *psDTED
+        = DTEDOpen( pszFilename, "rb+", FALSE );
     if( psDTED == NULL )
         return NULL;
 
@@ -725,26 +708,28 @@ DTEDCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      Read all the data in a single buffer.                           */
 /* -------------------------------------------------------------------- */
     GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( 1 );
-    GInt16      *panData;
-
-    panData = (GInt16 *) 
-        VSIMalloc(sizeof(GInt16) * psDTED->nXSize * psDTED->nYSize);
+    GInt16 *panData = (GInt16 *)
+        VSI_MALLOC_VERBOSE(sizeof(GInt16) * psDTED->nXSize * psDTED->nYSize);
     if (panData == NULL)
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
         DTEDClose(psDTED);
         return NULL;
     }
 
     for( int iY = 0; iY < psDTED->nYSize; iY++ )
     {
-        poSrcBand->RasterIO( GF_Read, 0, iY, psDTED->nXSize, 1, 
-                            (void *) (panData + iY * psDTED->nXSize), psDTED->nXSize, 1, 
-                            GDT_Int16, 0, 0, NULL );
+        if( poSrcBand->RasterIO( GF_Read, 0, iY, psDTED->nXSize, 1,
+                            (void *) (panData + iY * psDTED->nXSize), psDTED->nXSize, 1,
+                            GDT_Int16, 0, 0, NULL ) != CE_None )
+        {
+            DTEDClose( psDTED );
+            CPLFree( panData );
+            return NULL;
+        }
 
         if( pfnProgress && !pfnProgress(0.5 * (iY+1) / (double) psDTED->nYSize, NULL, pProgressData ) )
         {
-            CPLError( CE_Failure, CPLE_UserInterrupt, 
+            CPLError( CE_Failure, CPLE_UserInterrupt,
                         "User terminated CreateCopy()" );
             DTEDClose( psDTED );
             CPLFree( panData );
@@ -781,7 +766,7 @@ DTEDCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             && !pfnProgress( 0.5 + 0.5 * (iProfile+1) / (double) psDTED->nXSize,
                              NULL, pProgressData ) )
         {
-            CPLError( CE_Failure, CPLE_UserInterrupt, 
+            CPLError( CE_Failure, CPLE_UserInterrupt,
                       "User terminated CreateCopy()" );
             DTEDClose( psDTED );
             CPLFree( panData );
@@ -799,91 +784,91 @@ DTEDCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         iPartialCell = 0;
     else
     {
-      iPartialCell = (GByte)int(floor(100.0 - 
+      iPartialCell = (GByte)int(floor(100.0 -
            (dfNodataCount*100.0/(psDTED->nXSize * psDTED->nYSize))));
         if (iPartialCell < 1)
            iPartialCell=1;
     }
-    sprintf(szPartialCell,"%02d",iPartialCell);
-    DTEDSetMetadata(psDTED, DTEDMD_PARTIALCELL_DSI, szPartialCell); 
+    snprintf( szPartialCell, sizeof(szPartialCell), "%02d",iPartialCell);
+    DTEDSetMetadata(psDTED, DTEDMD_PARTIALCELL_DSI, szPartialCell);
 
 /* -------------------------------------------------------------------- */
 /*      Try to copy any matching available metadata.                    */
 /* -------------------------------------------------------------------- */
     if( poSrcDS->GetMetadataItem( "DTED_VerticalAccuracy_UHL" ) != NULL )
-        DTEDSetMetadata( psDTED, DTEDMD_VERTACCURACY_UHL, 
+        DTEDSetMetadata( psDTED, DTEDMD_VERTACCURACY_UHL,
                      poSrcDS->GetMetadataItem( "DTED_VerticalAccuracy_UHL" ) );
 
     if( poSrcDS->GetMetadataItem( "DTED_VerticalAccuracy_ACC" ) != NULL )
-        DTEDSetMetadata( psDTED, DTEDMD_VERTACCURACY_ACC, 
+        DTEDSetMetadata( psDTED, DTEDMD_VERTACCURACY_ACC,
                     poSrcDS->GetMetadataItem( "DTED_VerticalAccuracy_ACC" ) );
 
     if( poSrcDS->GetMetadataItem( "DTED_SecurityCode_UHL" ) != NULL )
-        DTEDSetMetadata( psDTED, DTEDMD_SECURITYCODE_UHL, 
+        DTEDSetMetadata( psDTED, DTEDMD_SECURITYCODE_UHL,
                     poSrcDS->GetMetadataItem( "DTED_SecurityCode_UHL" ) );
 
     if( poSrcDS->GetMetadataItem( "DTED_SecurityCode_DSI" ) != NULL )
-        DTEDSetMetadata( psDTED, DTEDMD_SECURITYCODE_DSI, 
+        DTEDSetMetadata( psDTED, DTEDMD_SECURITYCODE_DSI,
                     poSrcDS->GetMetadataItem( "DTED_SecurityCode_DSI" ) );
 
     if( poSrcDS->GetMetadataItem( "DTED_UniqueRef_UHL" ) != NULL )
-        DTEDSetMetadata( psDTED, DTEDMD_UNIQUEREF_UHL, 
+        DTEDSetMetadata( psDTED, DTEDMD_UNIQUEREF_UHL,
                          poSrcDS->GetMetadataItem( "DTED_UniqueRef_UHL" ) );
 
     if( poSrcDS->GetMetadataItem( "DTED_UniqueRef_DSI" ) != NULL )
-        DTEDSetMetadata( psDTED, DTEDMD_UNIQUEREF_DSI, 
+        DTEDSetMetadata( psDTED, DTEDMD_UNIQUEREF_DSI,
                          poSrcDS->GetMetadataItem( "DTED_UniqueRef_DSI" ) );
 
     if( poSrcDS->GetMetadataItem( "DTED_DataEdition" ) != NULL )
-        DTEDSetMetadata( psDTED, DTEDMD_DATA_EDITION, 
+        DTEDSetMetadata( psDTED, DTEDMD_DATA_EDITION,
                          poSrcDS->GetMetadataItem( "DTED_DataEdition" ) );
 
     if( poSrcDS->GetMetadataItem( "DTED_MatchMergeVersion" ) != NULL )
-        DTEDSetMetadata( psDTED, DTEDMD_MATCHMERGE_VERSION, 
+        DTEDSetMetadata( psDTED, DTEDMD_MATCHMERGE_VERSION,
                      poSrcDS->GetMetadataItem( "DTED_MatchMergeVersion" ) );
 
     if( poSrcDS->GetMetadataItem( "DTED_MaintenanceDate" ) != NULL )
-        DTEDSetMetadata( psDTED, DTEDMD_MAINT_DATE, 
+        DTEDSetMetadata( psDTED, DTEDMD_MAINT_DATE,
                          poSrcDS->GetMetadataItem( "DTED_MaintenanceDate" ) );
 
     if( poSrcDS->GetMetadataItem( "DTED_MatchMergeDate" ) != NULL )
-        DTEDSetMetadata( psDTED, DTEDMD_MATCHMERGE_DATE, 
+        DTEDSetMetadata( psDTED, DTEDMD_MATCHMERGE_DATE,
                          poSrcDS->GetMetadataItem( "DTED_MatchMergeDate" ) );
 
     if( poSrcDS->GetMetadataItem( "DTED_MaintenanceDescription" ) != NULL )
-        DTEDSetMetadata( psDTED, DTEDMD_MAINT_DESCRIPTION, 
+        DTEDSetMetadata( psDTED, DTEDMD_MAINT_DESCRIPTION,
                  poSrcDS->GetMetadataItem( "DTED_MaintenanceDescription" ) );
 
     if( poSrcDS->GetMetadataItem( "DTED_Producer" ) != NULL )
-        DTEDSetMetadata( psDTED, DTEDMD_PRODUCER, 
+        DTEDSetMetadata( psDTED, DTEDMD_PRODUCER,
                          poSrcDS->GetMetadataItem( "DTED_Producer" ) );
 
     if( poSrcDS->GetMetadataItem( "DTED_VerticalDatum" ) != NULL )
-        DTEDSetMetadata( psDTED, DTEDMD_VERTDATUM, 
+        DTEDSetMetadata( psDTED, DTEDMD_VERTDATUM,
                          poSrcDS->GetMetadataItem( "DTED_VerticalDatum" ) );
 
     if( poSrcDS->GetMetadataItem( "DTED_HorizontalDatum" ) != NULL )
-        DTEDSetMetadata( psDTED, DTEDMD_HORIZDATUM, 
+        DTEDSetMetadata( psDTED, DTEDMD_HORIZDATUM,
                          poSrcDS->GetMetadataItem( "DTED_HorizontalDatum" ) );
 
     if( poSrcDS->GetMetadataItem( "DTED_DigitizingSystem" ) != NULL )
-        DTEDSetMetadata( psDTED, DTEDMD_DIGITIZING_SYS, 
+        DTEDSetMetadata( psDTED, DTEDMD_DIGITIZING_SYS,
                          poSrcDS->GetMetadataItem( "DTED_DigitizingSystem" ) );
 
     if( poSrcDS->GetMetadataItem( "DTED_CompilationDate" ) != NULL )
-        DTEDSetMetadata( psDTED, DTEDMD_COMPILATION_DATE, 
+        DTEDSetMetadata( psDTED, DTEDMD_COMPILATION_DATE,
                          poSrcDS->GetMetadataItem( "DTED_CompilationDate" ) );
 
     if( poSrcDS->GetMetadataItem( "DTED_HorizontalAccuracy" ) != NULL )
-        DTEDSetMetadata( psDTED, DTEDMD_HORIZACCURACY, 
+        DTEDSetMetadata( psDTED, DTEDMD_HORIZACCURACY,
                      poSrcDS->GetMetadataItem( "DTED_HorizontalAccuracy" ) );
 
     if( poSrcDS->GetMetadataItem( "DTED_RelHorizontalAccuracy" ) != NULL )
-        DTEDSetMetadata( psDTED, DTEDMD_REL_HORIZACCURACY, 
+        DTEDSetMetadata( psDTED, DTEDMD_REL_HORIZACCURACY,
                    poSrcDS->GetMetadataItem( "DTED_RelHorizontalAccuracy" ) );
 
     if( poSrcDS->GetMetadataItem( "DTED_RelVerticalAccuracy" ) != NULL )
-        DTEDSetMetadata( psDTED, DTEDMD_REL_VERTACCURACY, 
+        DTEDSetMetadata( psDTED, DTEDMD_REL_VERTACCURACY,
                      poSrcDS->GetMetadataItem( "DTED_RelVerticalAccuracy" ) );
 
 /* -------------------------------------------------------------------- */
@@ -894,7 +879,7 @@ DTEDCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Reopen and copy missing information into a PAM file.            */
 /* -------------------------------------------------------------------- */
-    GDALPamDataset *poDS = (GDALPamDataset *) 
+    GDALPamDataset *poDS = (GDALPamDataset *)
         GDALOpen( pszFilename, GA_ReadOnly );
 
     if( poDS )
@@ -910,28 +895,26 @@ DTEDCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 void GDALRegister_DTED()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "DTED" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "DTED" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "DTED" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "DTED Elevation Raster" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "dt0 dt1 dt2" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#DTED" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte Int16 UInt16" );
-
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = DTEDDataset::Open;
-        poDriver->pfnIdentify = DTEDDataset::Identify;
-        poDriver->pfnCreateCopy = DTEDCreateCopy;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "DTED" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "DTED Elevation Raster" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "dt0 dt1 dt2" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_various.html#DTED" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte Int16 UInt16" );
+
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = DTEDDataset::Open;
+    poDriver->pfnIdentify = DTEDDataset::Identify;
+    poDriver->pfnCreateCopy = DTEDCreateCopy;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/dted/frmt_dted.html b/frmts/dted/frmt_dted.html
index 96e4034..c9a5c6e 100644
--- a/frmts/dted/frmt_dted.html
+++ b/frmts/dted/frmt_dted.html
@@ -7,9 +7,9 @@
 
 <h1>DTED -- Military Elevation Data</h1>
 
-GDAL supports DTED Levels 0, 1, and 2 elevation data for read access.  
-Elevation data is returned as 16 bit signed integer.  Appropriate 
-projection and georeferencing information is also returned.   
+GDAL supports DTED Levels 0, 1, and 2 elevation data for read access.
+Elevation data is returned as 16 bit signed integer.  Appropriate
+projection and georeferencing information is also returned.
 A variety of header fields are returned dataset level metadata.
 <p>
 
diff --git a/frmts/e00grid/e00compr.h b/frmts/e00grid/e00compr.h
index a92bd93..73eba07 100644
--- a/frmts/e00grid/e00compr.h
+++ b/frmts/e00grid/e00compr.h
@@ -54,11 +54,11 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- * 
+ *
  **********************************************************************/
 
-#ifndef _E00COMPR_H_INCLUDED_
-#define _E00COMPR_H_INCLUDED_
+#ifndef E00COMPR_H_INCLUDED_
+#define E00COMPR_H_INCLUDED_
 
 
 #include <stdio.h>
@@ -101,7 +101,7 @@ extern "C" {
 /*---------------------------------------------------------------------
  *                          E00ReadPtr
  *
- * A E00ReadPtr handle is used to hold information about the compressed 
+ * A E00ReadPtr handle is used to hold information about the compressed
  * file currently being read.
  *--------------------------------------------------------------------*/
 struct _E00ReadInfo
@@ -129,7 +129,7 @@ typedef struct _E00ReadInfo *E00ReadPtr;
 /*---------------------------------------------------------------------
  *                          E00WritePtr
  *
- * A E00WritePtr handle is used to hold information about the 
+ * A E00WritePtr handle is used to hold information about the
  * file currently being written.
  *--------------------------------------------------------------------*/
 struct _E00WriteInfo
@@ -178,4 +178,4 @@ int         E00WriteNextLine(E00WritePtr psInfo, const char *pszLine);
 }
 #endif
 
-#endif /* _E00COMPR_H_INCLUDED_ */
+#endif /* E00COMPR_H_INCLUDED_ */
diff --git a/frmts/e00grid/e00griddataset.cpp b/frmts/e00grid/e00griddataset.cpp
index abd9bf7..9a9cd8a 100644
--- a/frmts/e00grid/e00griddataset.cpp
+++ b/frmts/e00grid/e00griddataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: e00griddataset.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: e00griddataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  E00 grid driver
  * Purpose:  GDALDataset driver for E00 grid dataset.
@@ -27,10 +27,11 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_vsi_virtual.h"
 #include "cpl_string.h"
-#include "ogr_spatialref.h"
+#include "cpl_vsi_virtual.h"
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
+#include "ogr_spatialref.h"
 
 /* Private import of e00read.c */
 #define E00ReadOpen         GDALE00GRIDReadOpen
@@ -40,17 +41,13 @@
 #define E00ReadRewind       GDALE00GRIDReadRewind
 #include "e00read.c"
 
-#define E00_INT_SIZE    10
-#define E00_INT14_SIZE  14
-#define E00_FLOAT_SIZE  14
-#define E00_DOUBLE_SIZE 21
-#define VALS_PER_LINE   5
+static const int E00_INT_SIZE = 10;
+// #define E00_INT14_SIZE  14
+static const int E00_FLOAT_SIZE = 14;
+static const int E00_DOUBLE_SIZE = 21;
+static const int VALS_PER_LINE = 5;
 
-CPL_CVSID("$Id: e00griddataset.cpp 27942 2014-11-11 00:57:41Z rouault $");
-
-CPL_C_START
-void    GDALRegister_E00GRID(void);
-CPL_C_END
+CPL_CVSID("$Id: e00griddataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /* g++ -fPIC -Wall -g frmts/e00grid/e00griddataset.cpp -shared -o gdal_E00GRID.so -Iport -Igcore -Iogr -L. -lgdal */
 
@@ -109,10 +106,10 @@ class E00GRIDDataset : public GDALPamDataset
   public:
                  E00GRIDDataset();
     virtual     ~E00GRIDDataset();
-    
+
     virtual CPLErr GetGeoTransform( double * );
     virtual const char* GetProjectionRef();
-    
+
     static GDALDataset *Open( GDALOpenInfo * );
     static int          Identify( GDALOpenInfo * );
 };
@@ -147,12 +144,12 @@ class E00GRIDRasterBand : public GDALPamRasterBand
 /*                         E00GRIDRasterBand()                          */
 /************************************************************************/
 
-E00GRIDRasterBand::E00GRIDRasterBand( E00GRIDDataset *poDS, int nBand,
+E00GRIDRasterBand::E00GRIDRasterBand( E00GRIDDataset *poDSIn, int nBandIn,
                                       GDALDataType eDT )
 
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
 
     eDataType = eDT;
 
@@ -173,10 +170,9 @@ CPLErr E00GRIDRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     char szVal[E00_FLOAT_SIZE+1];
     szVal[E00_FLOAT_SIZE] = 0;
 
-    int i;
     float* pafImage = (float*)pImage;
     int* panImage = (int*)pImage;
-    const float fNoData = (const float)poGDS->dfNoData;
+    const float fNoData = static_cast<float>(poGDS->dfNoData);
 
     /* A new data line begins on a new text line. So if the xsize */
     /* is not a multiple of VALS_PER_LINE, there are padding values */
@@ -189,7 +185,7 @@ CPLErr E00GRIDRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
         if (poGDS->nLastYOff < 0)
         {
             E00ReadRewind(poGDS->e00ReadPtr);
-            for(i=0;i<6;i++)
+            for(int i=0;i<6;i++)
                 E00ReadNextLine(poGDS->e00ReadPtr);
         }
 
@@ -207,7 +203,7 @@ CPLErr E00GRIDRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
         else if (nBlockYOff > poGDS->nLastYOff + 1)
         {
             //CPLDebug("E00GRID", "Forward skip to %d from %d", nBlockYOff, poGDS->nLastYOff);
-            for(i=poGDS->nLastYOff + 1; i < nBlockYOff;i++)
+            for(int i=poGDS->nLastYOff + 1; i < nBlockYOff;i++)
                 IReadBlock(0, i, pImage);
         }
 
@@ -219,7 +215,7 @@ CPLErr E00GRIDRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
         }
 
         const char* pszLine = NULL;
-        for(i=0;i<nBlockXSize;i++)
+        for(int i=0;i<nBlockXSize;i++)
         {
             if ((i % VALS_PER_LINE) == 0)
             {
@@ -251,7 +247,7 @@ CPLErr E00GRIDRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     vsi_l_offset nPos = poGDS->nDataStart + nLinesToSkip * nBytesPerLine;
     VSIFSeekL(poGDS->fp, nPos, SEEK_SET);
 
-    for(i=0;i<nBlockXSize;i++)
+    for(int i=0;i<nBlockXSize;i++)
     {
         if (VSIFReadL(szVal, E00_FLOAT_SIZE, 1, poGDS->fp) != 1)
             return CE_Failure;
@@ -288,8 +284,8 @@ double E00GRIDRasterBand::GetNoDataValue( int *pbSuccess )
 
     if (eDataType == GDT_Float32)
         return (double)(float) poGDS->dfNoData;
-    else
-        return (double)(int)poGDS->dfNoData;
+
+    return (double)(int)poGDS->dfNoData;
 }
 
 /************************************************************************/
@@ -309,7 +305,7 @@ const char * E00GRIDRasterBand::GetUnitType()
     const char* pszRet = "";
     while(*papszIter)
     {
-        if (EQUALN(*papszIter, "Zunits", 6))
+        if (STARTS_WITH_CI(*papszIter, "Zunits"))
         {
             char** papszTokens = CSLTokenizeString(*papszIter);
             if (CSLCount(papszTokens) == 2)
@@ -404,36 +400,30 @@ CPLErr E00GRIDRasterBand::GetStatistics( int bApproxOK, int bForce,
 /*                           E00GRIDDataset()                           */
 /************************************************************************/
 
-E00GRIDDataset::E00GRIDDataset()
+E00GRIDDataset::E00GRIDDataset() :
+    e00ReadPtr(NULL),
+    fp(NULL),
+    nDataStart(0),
+    nBytesEOL(1),
+    nPosBeforeReadLine(0),
+    panOffsets(NULL),
+    nLastYOff(-1),
+    nMaxYOffset(-1),
+    dfNoData(0),
+    papszPrj(NULL),
+    bHasReadMetadata(FALSE),
+    bHasStats(FALSE),
+    dfMin(0),
+    dfMax(0),
+    dfMean(0),
+    dfStddev(0)
 {
-    e00ReadPtr = NULL;
-    fp = NULL;
-    nDataStart = 0;
-    nBytesEOL = 1;
-
-    nPosBeforeReadLine = 0;
-    panOffsets = NULL;
-    nLastYOff = -1;
-    nMaxYOffset = -1;
-
     adfGeoTransform[0] = 0;
     adfGeoTransform[1] = 1;
     adfGeoTransform[2] = 0;
     adfGeoTransform[3] = 0;
     adfGeoTransform[4] = 0;
     adfGeoTransform[5] = 1;
-
-    dfNoData = 0;
-
-    papszPrj = NULL;
-
-    bHasReadMetadata = FALSE;
-
-    bHasStats = FALSE;
-    dfMin = 0;
-    dfMax = 0;
-    dfMean = 0;
-    dfStddev = 0;
 }
 
 /************************************************************************/
@@ -460,8 +450,8 @@ int E00GRIDDataset::Identify( GDALOpenInfo * poOpenInfo )
     if (poOpenInfo->nHeaderBytes == 0)
         return FALSE;
 
-    if (!(EQUALN((const char*)poOpenInfo->pabyHeader, "EXP  0", 6) ||
-          EQUALN((const char*)poOpenInfo->pabyHeader, "EXP  1", 6)))
+    if (!(STARTS_WITH_CI((const char*)poOpenInfo->pabyHeader, "EXP  0") ||
+          STARTS_WITH_CI((const char*)poOpenInfo->pabyHeader, "EXP  1")))
         return FALSE;
 
     /* FIXME: handle GRD  3 if that ever exists ? */
@@ -499,9 +489,6 @@ void E00GRIDDataset::Rewind(void * ptr)
 GDALDataset *E00GRIDDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    int         i;
-    GDALDataType eDT = GDT_Float32;
-
     if (!Identify(poOpenInfo))
         return NULL;
 
@@ -514,7 +501,7 @@ GDALDataset *E00GRIDDataset::Open( GDALOpenInfo * poOpenInfo )
 
     if (poOpenInfo->eAccess == GA_Update)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The E00GRID driver does not support update access to existing"
                   " datasets.\n" );
         VSIFCloseL(fp);
@@ -524,23 +511,20 @@ GDALDataset *E00GRIDDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    E00GRIDDataset         *poDS;
-
-    poDS = new E00GRIDDataset();
+    E00GRIDDataset *poDS = new E00GRIDDataset();
     if (strstr((const char*)poOpenInfo->pabyHeader, "\r\n") != NULL)
         poDS->nBytesEOL = 2;
     poDS->fp = fp;
 
-    const char* pszLine;
     /* read EXP  0 or EXP  1 line */
-    pszLine = CPLReadLine2L(fp, 81, NULL);
+    const char* pszLine = CPLReadLine2L(fp, 81, NULL);
     if (pszLine == NULL)
     {
         CPLDebug("E00GRID", "Bad 1st line");
         delete poDS;
         return NULL;
     }
-    int bCompressed = EQUALN(pszLine, "EXP  1", 6);
+    bool bCompressed = STARTS_WITH_CI(pszLine, "EXP  1");
 
     E00ReadPtr e00ReadPtr = NULL;
     if (bCompressed)
@@ -563,7 +547,7 @@ GDALDataset *E00GRIDDataset::Open( GDALOpenInfo * poOpenInfo )
         pszLine = E00ReadNextLine(e00ReadPtr);
     else
         pszLine = CPLReadLine2L(fp, 81, NULL);
-    if (pszLine == NULL || !EQUALN(pszLine, "GRD  2", 6))
+    if (pszLine == NULL || !STARTS_WITH_CI(pszLine, "GRD  2"))
     {
         CPLDebug("E00GRID", "Bad 2nd line");
         delete poDS;
@@ -583,8 +567,8 @@ GDALDataset *E00GRIDDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    int nRasterXSize = atoi(pszLine);
-    int nRasterYSize = atoi(pszLine + E00_INT_SIZE);
+    const int nRasterXSize = atoi(pszLine);
+    const int nRasterYSize = atoi(pszLine + E00_INT_SIZE);
 
     if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize))
     {
@@ -592,16 +576,18 @@ GDALDataset *E00GRIDDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    if (EQUALN(pszLine + E00_INT_SIZE + E00_INT_SIZE, " 1", 2))
+    GDALDataType eDT = GDT_Float32;
+
+    if (STARTS_WITH_CI(pszLine + E00_INT_SIZE + E00_INT_SIZE, " 1"))
         eDT = GDT_Int32;
-    else if (EQUALN(pszLine + E00_INT_SIZE + E00_INT_SIZE, " 2", 2))
+    else if (STARTS_WITH_CI(pszLine + E00_INT_SIZE + E00_INT_SIZE, " 2"))
         eDT = GDT_Float32;
     else
     {
         CPLDebug("E00GRID", "Unknown data type : %s", pszLine);
     }
 
-    double dfNoData = CPLAtof(pszLine + E00_INT_SIZE + E00_INT_SIZE + 2);
+    const double dfNoData = CPLAtof(pszLine + E00_INT_SIZE + E00_INT_SIZE + 2);
 
     /* read pixel size */
     if (e00ReadPtr)
@@ -630,8 +616,8 @@ GDALDataset *E00GRIDDataset::Open( GDALOpenInfo * poOpenInfo )
         delete poDS;
         return NULL;
     }
-    double dfMinX = CPLAtof(pszLine);
-    double dfMinY = CPLAtof(pszLine + E00_DOUBLE_SIZE);
+    const double dfMinX = CPLAtof(pszLine);
+    const double dfMinY = CPLAtof(pszLine + E00_DOUBLE_SIZE);
 
     /* read xmax, ymax */
     if (e00ReadPtr)
@@ -644,8 +630,8 @@ GDALDataset *E00GRIDDataset::Open( GDALOpenInfo * poOpenInfo )
         delete poDS;
         return NULL;
     }
-    double dfMaxX = CPLAtof(pszLine);
-    double dfMaxY = CPLAtof(pszLine + E00_DOUBLE_SIZE);
+    const double dfMaxX = CPLAtof(pszLine);
+    const double dfMaxY = CPLAtof(pszLine + E00_DOUBLE_SIZE);
 
     poDS->nRasterXSize = nRasterXSize;
     poDS->nRasterYSize = nRasterYSize;
@@ -671,7 +657,7 @@ GDALDataset *E00GRIDDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
     poDS->nBands = 1;
-    for( i = 0; i < poDS->nBands; i++ )
+    for( int i = 0; i < poDS->nBands; i++ )
         poDS->SetBand( i+1, new E00GRIDRasterBand( poDS, i+1, eDT ) );
 
 /* -------------------------------------------------------------------- */
@@ -708,8 +694,8 @@ const char* E00GRIDDataset::ReadLine()
 {
     if (e00ReadPtr)
         return E00ReadNextLine(e00ReadPtr);
-    else
-        return CPLReadLine2L(fp, 81, NULL);
+
+    return CPLReadLine2L(fp, 81, NULL);
 }
 
 /************************************************************************/
@@ -737,13 +723,13 @@ void E00GRIDDataset::ReadMetadata()
 
     if (e00ReadPtr == NULL)
     {
-        int nRoundedBlockXSize = ((nRasterXSize + VALS_PER_LINE - 1) /
+        const int nRoundedBlockXSize = ((nRasterXSize + VALS_PER_LINE - 1) /
                                                 VALS_PER_LINE) * VALS_PER_LINE;
-        vsi_l_offset nValsToSkip =
+        const vsi_l_offset nValsToSkip =
                                (vsi_l_offset)nRasterYSize * nRoundedBlockXSize;
-        vsi_l_offset nLinesToSkip = nValsToSkip / VALS_PER_LINE;
-        int nBytesPerLine = VALS_PER_LINE * E00_FLOAT_SIZE + nBytesEOL;
-        vsi_l_offset nPos = nDataStart + nLinesToSkip * nBytesPerLine;
+        const vsi_l_offset nLinesToSkip = nValsToSkip / VALS_PER_LINE;
+        const int nBytesPerLine = VALS_PER_LINE * E00_FLOAT_SIZE + nBytesEOL;
+        const vsi_l_offset nPos = nDataStart + nLinesToSkip * nBytesPerLine;
         VSIFSeekL(fp, nPos, SEEK_SET);
     }
     else
@@ -774,7 +760,7 @@ void E00GRIDDataset::ReadMetadata()
             i++; \
     } \
 
-        while ((nRead = VSIFReadL(pabyBuffer, 1, nToRead, fp)) != 0)
+        while ((nRead = static_cast<int>(VSIFReadL(pabyBuffer, 1, nToRead, fp))) != 0)
         {
             int i;
             for(i = 0; i < nRead; i++)
@@ -831,13 +817,13 @@ void E00GRIDDataset::ReadMetadata()
     }
 
     const char* pszLine;
-    int bPRJFound = FALSE;
-    int bStatsFound = FALSE;
+    bool bPRJFound = false;
+    bool bStatsFound = false;
     while((pszLine = ReadLine()) != NULL)
     {
-        if (EQUALN(pszLine, "PRJ  2", 6))
+        if (STARTS_WITH_CI(pszLine, "PRJ  2"))
         {
-            bPRJFound = TRUE;
+            bPRJFound = true;
             while((pszLine = ReadLine()) != NULL)
             {
                 if (EQUAL(pszLine, "EOP"))
@@ -865,7 +851,7 @@ void E00GRIDDataset::ReadMetadata()
         }
         else if (strcmp(pszLine, "STDV              8-1  254-1  15 3 60-1  -1  -1-1                   4-") == 0)
         {
-            bStatsFound = TRUE;
+            bStatsFound = true;
             pszLine = ReadLine();
             if (pszLine)
             {
@@ -899,26 +885,23 @@ void E00GRIDDataset::ReadMetadata()
 void GDALRegister_E00GRID()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "E00GRID" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "E00GRID" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "E00GRID" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Arc/Info Export E00 GRID" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#E00GRID" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "e00" );
+    GDALDriver *poDriver = new GDALDriver();
 
+    poDriver->SetDescription( "E00GRID" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Arc/Info Export E00 GRID" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_various.html#E00GRID" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "e00" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = E00GRIDDataset::Open;
-        poDriver->pfnIdentify = E00GRIDDataset::Identify;
+    poDriver->pfnOpen = E00GRIDDataset::Open;
+    poDriver->pfnIdentify = E00GRIDDataset::Identify;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/e00grid/e00read.c b/frmts/e00grid/e00read.c
index 308bf6f..1952b02 100644
--- a/frmts/e00grid/e00read.c
+++ b/frmts/e00grid/e00read.c
@@ -4,7 +4,7 @@
  * Name:     e00read.c
  * Project:  Compressed E00 Read/Write library
  * Language: ANSI C
- * Purpose:  Functions to read Compressed E00 files and return a stream 
+ * Purpose:  Functions to read Compressed E00 files and return a stream
  *           of uncompressed lines.
  * Author:   Daniel Morissette, dmorissette at mapgears.com
  *
@@ -56,7 +56,7 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- * 
+ *
  **********************************************************************/
 
 #include <stdlib.h>
@@ -85,9 +85,9 @@ static E00ReadPtr  _E00ReadTestOpen(E00ReadPtr psInfo)
     /* Check that the file is in E00 format.
      */
     _ReadNextSourceLine(psInfo);
-    if (!psInfo->bEOF && strncmp(psInfo->szInBuf, "EXP ", 4) == 0)
+    if (!psInfo->bEOF && STARTS_WITH(psInfo->szInBuf, "EXP "))
     {
-        /* We should be in presence of a valid E00 file... 
+        /* We should be in presence of a valid E00 file...
          * Is the file compressed or not?
          *
          * Note: we cannot really rely on the number that follows the EXP to
@@ -95,16 +95,16 @@ static E00ReadPtr  _E00ReadTestOpen(E00ReadPtr psInfo)
          * uncompressed files that start with a "EXP 1" line!!!
          *
          * The best test is to read the first non-empty line: if the file is
-         * compressed, the first line of data should be 79 or 80 characters 
+         * compressed, the first line of data should be 79 or 80 characters
          * long and contain several '~' characters.
          */
         do
         {
             _ReadNextSourceLine(psInfo);
-        }while(!psInfo->bEOF && 
+        }while(!psInfo->bEOF &&
                (psInfo->szInBuf[0] == '\0' || isspace(psInfo->szInBuf[0])) );
 
-         if (!psInfo->bEOF && 
+         if (!psInfo->bEOF &&
              (strlen(psInfo->szInBuf)==79 || strlen(psInfo->szInBuf)==80) &&
              strchr(psInfo->szInBuf, '~') != NULL )
              psInfo->bIsCompressed = 1;
@@ -127,7 +127,7 @@ static E00ReadPtr  _E00ReadTestOpen(E00ReadPtr psInfo)
  *
  * Try to open a E00 file given its filename and return a E00ReadPtr handle.
  *
- * Returns NULL if the file could not be opened or if it does not 
+ * Returns NULL if the file could not be opened or if it does not
  * appear to be a valid E00 file.
  **********************************************************************/
 E00ReadPtr  E00ReadOpen(const char *pszFname)
@@ -137,7 +137,7 @@ E00ReadPtr  E00ReadOpen(const char *pszFname)
 
     CPLErrorReset();
 
-    /* Open the file 
+    /* Open the file
      */
     fp = VSIFOpen(pszFname, "rt");
     if (fp == NULL)
@@ -147,7 +147,7 @@ E00ReadPtr  E00ReadOpen(const char *pszFname)
         return NULL;
     }
 
-    /* File was succesfully opened, allocate and initialize a 
+    /* File was successfully opened, allocate and initialize a
      * E00ReadPtr handle and check that the file is valid.
      */
     psInfo = (E00ReadPtr)CPLCalloc(1, sizeof(struct _E00ReadInfo));
@@ -180,7 +180,7 @@ E00ReadPtr  E00ReadOpen(const char *pszFname)
  *   const char *myReadNextLine(void *pRefData);
  *   void        myReadRewind(void *pRefData);
  *
- *   myReadNextLine() should return a reference to its own internal 
+ *   myReadNextLine() should return a reference to its own internal
  *   buffer, or NULL if an error happens or EOF is reached.
  *
  * E00ReadCallbackOpen() returns a E00ReadPtr handle or NULL if the file
@@ -203,7 +203,7 @@ E00ReadPtr  E00ReadCallbackOpen(void *pRefData,
         return NULL;
     }
 
-    /* Allocate and initialize a 
+    /* Allocate and initialize a
      * E00ReadPtr handle and check that the file is valid.
      */
     psInfo = (E00ReadPtr)CPLCalloc(1, sizeof(struct _E00ReadInfo));
@@ -243,7 +243,7 @@ void    E00ReadClose(E00ReadPtr psInfo)
 /**********************************************************************
  *                          E00ReadRewind()
  *
- * Rewind the E00ReadPtr.  Allows starting another read pass on the 
+ * Rewind the E00ReadPtr.  Allows starting another read pass on the
  * input file.
  **********************************************************************/
 void    E00ReadRewind(E00ReadPtr psInfo)
@@ -282,14 +282,14 @@ const char *E00ReadNextLine(E00ReadPtr psInfo)
     {
         if (!psInfo->bIsCompressed)
         {
-            /* Uncompressed file... return line directly. 
+            /* Uncompressed file... return line directly.
              */
             _ReadNextSourceLine(psInfo);
             pszLine = psInfo->szInBuf;
         }
         else if (psInfo->bIsCompressed && psInfo->nInputLineNo == 0)
         {
-            /* Header line in a compressed file... return line 
+            /* Header line in a compressed file... return line
              * after replacing "EXP  1" with "EXP  0".  E00ReadOpen()
              * has already verified that this line starts with "EXP "
              */
@@ -307,13 +307,13 @@ const char *E00ReadNextLine(E00ReadPtr psInfo)
                 _ReadNextSourceLine(psInfo);
             }
 
-            /* Uncompress the next line of input and return it 
+            /* Uncompress the next line of input and return it
              */
             pszLine = _UncompressNextLine(psInfo);
         }
 
         /* If we just reached EOF then make sure we don't add an extra
-         * empty line at the end of the uncompressed oputput.
+         * empty line at the end of the uncompressed output.
          */
         if (psInfo->bEOF && strlen(pszLine) == 0)
             pszLine = NULL;
@@ -336,7 +336,7 @@ static void _ReadNextSourceLine(E00ReadPtr psInfo)
         psInfo->iInBufPtr = 0;
         psInfo->szInBuf[0] = '\0';
 
-        /* Read either using fgets() or psInfo->pfnReadNextLine() 
+        /* Read either using fgets() or psInfo->pfnReadNextLine()
          * depending on the way the file was opened...
          */
         if (psInfo->pfnReadNextLine == NULL)
@@ -366,11 +366,11 @@ static void _ReadNextSourceLine(E00ReadPtr psInfo)
 
         if (!psInfo->bEOF)
         {
-            /* A new line was succesfully read.  Remove trailing '\n' if any.
+            /* A new line was successfully read.  Remove trailing '\n' if any.
              * (Note: For Unix systems, we also have to check for '\r')
              */
             int nLen;
-            nLen = strlen(psInfo->szInBuf);
+            nLen = (int)strlen(psInfo->szInBuf);
             while(nLen > 0 && (psInfo->szInBuf[nLen-1] == '\n' ||
                                psInfo->szInBuf[nLen-1] == '\r'   ) )
             {
@@ -387,7 +387,7 @@ static void _ReadNextSourceLine(E00ReadPtr psInfo)
 /**********************************************************************
  *                          _GetNextSourceChar()
  *
- * Returns the next char from the source file input buffer... and 
+ * Returns the next char from the source file input buffer... and
  * reload the input buffer when necessary... this function makes the
  * whole input file appear as one huge null-terminated string with
  * no line delimiters.
@@ -518,7 +518,7 @@ static const char *_UncompressNextLine(E00ReadPtr psInfo)
              *  ~             marks the beginning of a new code sequence
              *
              *  c0            is a single character code defining the format
-             *                of the number (decimal position, exponent, 
+             *                of the number (decimal position, exponent,
              *                and even or odd number of digits)
              *
              *  c1 c2 ... cn  each of these characters represent a pair of
@@ -558,7 +558,7 @@ static const char *_UncompressNextLine(E00ReadPtr psInfo)
                     if (n == 92 && (c=_GetNextSourceChar(psInfo)) != '\0')
                         n += c - '!';
 
-                    psInfo->szOutBuf[iOutBufPtr++] = '0' + n/10;
+                    psInfo->szOutBuf[iOutBufPtr++] = (char)('0' + n/10);
 
                     if (++iCurDigit == iDecimalPoint)
                         psInfo->szOutBuf[iOutBufPtr++] = '.';
@@ -611,8 +611,8 @@ static const char *_UncompressNextLine(E00ReadPtr psInfo)
                 CPLError(CE_Failure, CPLE_NotSupported,
                          "Unexpected code \"~%c\" encountered in line %d.",
                           c, psInfo->nInputLineNo);
-    
-                /* Force the program to abort by simulating a EOF 
+
+                /* Force the program to abort by simulating a EOF
                  */
                 psInfo->bEOF = 1;
                 bEOL = 1;
@@ -629,7 +629,7 @@ static const char *_UncompressNextLine(E00ReadPtr psInfo)
                       "Uncompressed line longer than 80 chars. "
                       "Input file possibly corrupt around line %d.",
                       psInfo->nInputLineNo);
-            /* Force the program to abort by simulating a EOF 
+            /* Force the program to abort by simulating a EOF
              */
             psInfo->bEOF = 1;
             bEOL = 1;
diff --git a/frmts/ecw/GNUmakefile b/frmts/ecw/GNUmakefile
index 0a723d7..78d9ef1 100644
--- a/frmts/ecw/GNUmakefile
+++ b/frmts/ecw/GNUmakefile
@@ -4,7 +4,7 @@ include ../../GDALmake.opt
 OBJ	=	ecwdataset.o ecwcreatecopy.o jp2userbox.o ecwasyncreader.o
 
 CPPFLAGS	:=	 -DFRMT_ecw $(CPPFLAGS) \
-	$(ECW_FLAGS) $(ECW_INCLUDE) $(EXTRA_CFLAGS)
+	$(ECW_FLAGS) $(ECW_INCLUDE) $(EXTRA_CFLAGS) -DDO_NOT_USE_DEBUG_BOOL
 PLUGIN_SO =	gdal_ECW_JP2ECW.so
 
 default:	$(OBJ:.o=.$(OBJ_EXT))
diff --git a/frmts/ecw/ecwcreatecopy.cpp b/frmts/ecw/ecwcreatecopy.cpp
index 0c62adf..7dbda11 100644
--- a/frmts/ecw/ecwcreatecopy.cpp
+++ b/frmts/ecw/ecwcreatecopy.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ecwcreatecopy.cpp 29054 2015-04-29 19:31:41Z rouault $
+ * $Id: ecwcreatecopy.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  GDAL ECW Driver
  * Purpose:  ECW CreateCopy method implementation.
@@ -32,7 +32,12 @@
 #include "gdaljp2metadata.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: ecwcreatecopy.cpp 29054 2015-04-29 19:31:41Z rouault $");
+#if ECWSDK_VERSION<50
+/* For NCSStrDup */
+#include "NCSUtil.h"
+#endif
+
+CPL_CVSID("$Id: ecwcreatecopy.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 #if defined(FRMT_ecw) && defined(HAVE_COMPRESS)
 
@@ -45,7 +50,7 @@ CPLString GetCompressionSoftwareName(){
     char szProcessName[2048];
 
     /* For privacy reason, allow the user to not write the software name in the ECW */
-    if( !CSLTestBoolean(CPLGetConfigOption("GDAL_ECW_WRITE_COMPRESSION_SOFTWARE", "YES")) )
+    if( !CPLTestBool(CPLGetConfigOption("GDAL_ECW_WRITE_COMPRESSION_SOFTWARE", "YES")) )
         return osRet;
 
     if( CPLGetExecPath( szProcessName, sizeof(szProcessName) - 1 ) )
@@ -62,7 +67,7 @@ CPLString GetCompressionSoftwareName(){
     else
         strcpy(szProcessName, "Unknown");
 
-    osRet.Printf("%s/GDAL v%d.%d.%d.%d/ECWJP2 SDK v%s", 
+    osRet.Printf("%s/GDAL v%d.%d.%d.%d/ECWJP2 SDK v%s",
                  szProcessName,
                  GDAL_VERSION_MAJOR,
                  GDAL_VERSION_MINOR,
@@ -81,15 +86,15 @@ public:
     virtual CNCSError WriteReadLine(UINT32 nNextLine, void **ppInputArray);
 #if ECWSDK_VERSION>=50
     virtual void WriteStatus(IEEE4 fPercentComplete, const NCS::CString &sStatusText, const CompressionCounters &Counters);
-#else 
+#else
     virtual void WriteStatus(UINT32 nCurrentLine);
 #endif
 
     virtual bool WriteCancel();
 
-    CPLErr  Initialize( const char *pszFilename, char **papszOptions, 
+    CPLErr  Initialize( const char *pszFilename, char **papszOptions,
                         int nXSize, int nYSize, int nBands, const char * const * papszBandDescriptions, int bRGBColorSpace,
-                        GDALDataType eType, 
+                        GDALDataType eType,
                         const char *pszWKT, double *padfGeoTransform,
                         int nGCPCount, const GDAL_GCP *pasGCPList,
                         int bIsJPEG2000, int bPixelIsPoint, char** papszRPCMD,
@@ -99,7 +104,7 @@ public:
     CPLErr  PrepareCoverageBox( const char *pszWKT, double *padfGeoTransform );
     CPLErr  WriteJP2Box( GDALJP2Box * );
     void    WriteXMLBoxes();
-    CPLErr  WriteLineBIL(UINT16 nBands, void **ppOutputLine, UINT32 *pLineSteps = NULL);
+    CPLErr  ourWriteLineBIL(UINT16 nBands, void **ppOutputLine, UINT32 *pLineSteps = NULL);
     virtual NCSEcwCellType WriteReadLineGetCellType() {
         return sFileInfo.eCellType;
     }
@@ -119,22 +124,27 @@ public:
     GDALProgressFunc  pfnProgress;
     void             *pProgressData;
 
-    
     GDALDataType eWorkDT;
 
     JP2UserBox** papoJP2UserBox;
     int          nJP2UserBox;
-    
-private : 
+
+private:
     NCSFileViewFileInfoEx sFileInfo;
+
+    /* To fix 'warning: ‘virtual NCS::CView& NCS::CView::operator=(const NCS::CView&)’ was hidden ' with SDK 5 */
+#if ECWSDK_VERSION>=50
+    using CNCSFile::operator=;
+#endif
+    CPL_DISALLOW_COPY_ASSIGN(GDALECWCompressor)
 };
 
 /************************************************************************/
 /*                         GDALECWCompressor()                          */
 /************************************************************************/
 
-GDALECWCompressor::GDALECWCompressor()
-
+GDALECWCompressor::GDALECWCompressor() :
+    eWorkDT(GDT_Unknown)
 {
     m_poSrcDS = NULL;
     m_nPercentComplete = -1;
@@ -161,6 +171,12 @@ GDALECWCompressor::~GDALECWCompressor()
     for(i=0;i<nJP2UserBox;i++)
         delete papoJP2UserBox[i];
     CPLFree(papoJP2UserBox);
+
+#if ECWSDK_VERSION>=50
+    NCSFreeFileInfo(&sFileInfo);
+#else
+    NCSFreeFileInfoEx(&sFileInfo);
+#endif
 }
 
 /************************************************************************/
@@ -170,16 +186,6 @@ GDALECWCompressor::~GDALECWCompressor()
 CPLErr GDALECWCompressor::CloseDown()
 
 {
-#if ECWSDK_VERSION>=50
-    NCSFreeFileInfo(&sFileInfo);
-#else
-    for( int i = 0; i < sFileInfo.nBands; i++ ) 
-    { 
-        CPLFree( sFileInfo.pBands[i].szDesc ); 
-    } 
-    CPLFree( sFileInfo.pBands ); 
-#endif
-
     Close( true );
     m_OStream.Close();
 
@@ -190,7 +196,7 @@ CPLErr GDALECWCompressor::CloseDown()
 /*                           WriteReadLine()                            */
 /************************************************************************/
 
-CNCSError GDALECWCompressor::WriteReadLine( UINT32 nNextLine, 
+CNCSError GDALECWCompressor::WriteReadLine( UINT32 nNextLine,
                                             void **ppInputArray )
 
 {
@@ -210,16 +216,16 @@ CNCSError GDALECWCompressor::WriteReadLine( UINT32 nNextLine,
     pabyLineBuf = (GByte *) CPLMalloc( sFileInfo.nSizeX * sFileInfo.nBands
                                        * nWordSize );
 
-    eErr = m_poSrcDS->RasterIO( GF_Read, 0, nNextLine, sFileInfo.nSizeX, 1, 
-                                pabyLineBuf, sFileInfo.nSizeX, 1, 
-                                eWorkDT, 
+    eErr = m_poSrcDS->RasterIO( GF_Read, 0, nNextLine, sFileInfo.nSizeX, 1,
+                                pabyLineBuf, sFileInfo.nSizeX, 1,
+                                eWorkDT,
                                 sFileInfo.nBands, panBandMap,
                                 nWordSize, 0, nWordSize * sFileInfo.nSizeX, NULL );
 
     for( iBand = 0; iBand < (int) sFileInfo.nBands; iBand++ )
     {
         memcpy( ppInputArray[iBand],
-                pabyLineBuf + nWordSize * sFileInfo.nSizeX * iBand, 
+                pabyLineBuf + nWordSize * sFileInfo.nSizeX * iBand,
                 nWordSize * sFileInfo.nSizeX );
     }
 
@@ -227,23 +233,23 @@ CNCSError GDALECWCompressor::WriteReadLine( UINT32 nNextLine,
     CPLFree( panBandMap );
 
     if( eErr == CE_None )
-        return NCS_SUCCESS;
+        return GetCNCSError(NCS_SUCCESS);
     else
-        return NCS_FILEIO_ERROR;
+        return GetCNCSError(NCS_FILEIO_ERROR);
 }
 
 /************************************************************************/
 /*                            WriteStatus()                             */
 /************************************************************************/
 #if ECWSDK_VERSION>=50
-void GDALECWCompressor::WriteStatus(IEEE4 fPercentComplete, const NCS::CString &sStatusText, const CompressionCounters &Counters) 
+void GDALECWCompressor::WriteStatus(IEEE4 fPercentComplete, const NCS::CString &sStatusText, const CompressionCounters &Counters)
 {
     std::string sStatusUTF8;
     sStatusText.utf8_str(sStatusUTF8);
 
-    m_bCancelled = !pfnProgress( 
-                    fPercentComplete/100.0, 
-                    sStatusUTF8.c_str(), 
+    m_bCancelled = !pfnProgress(
+                    fPercentComplete/100.0,
+                    sStatusUTF8.c_str(),
                     pProgressData );
 }
 #else
@@ -251,11 +257,11 @@ void GDALECWCompressor::WriteStatus(IEEE4 fPercentComplete, const NCS::CString &
 void GDALECWCompressor::WriteStatus( UINT32 nCurrentLine )
 
 {
-    m_bCancelled = 
-        !pfnProgress( nCurrentLine / (float) sFileInfo.nSizeY, 
+    m_bCancelled =
+        !pfnProgress( nCurrentLine / (float) sFileInfo.nSizeY,
                       NULL, pProgressData );
 }
-#endif 
+#endif
 /************************************************************************/
 /*                            WriteCancel()                             */
 /************************************************************************/
@@ -315,9 +321,9 @@ CPLErr  GDALECWCompressor::PrepareCoverageBox(
     }
 
     if( nEPSGCode != 0 )
-        sprintf( szSRSName, "urn:ogc:def:crs:EPSG::%d", nEPSGCode );
+        snprintf( szSRSName, sizeof(szSRSName), "urn:ogc:def:crs:EPSG::%d", nEPSGCode );
     else
-        strcpy( szSRSName, 
+        strcpy( szSRSName,
                 "gmljp2://xml/CRSDictionary.gml#ogrcrs1" );
 
 /* -------------------------------------------------------------------- */
@@ -325,7 +331,7 @@ CPLErr  GDALECWCompressor::PrepareCoverageBox(
 /* -------------------------------------------------------------------- */
     char szDoc[4000];
 
-    CPLsprintf( szDoc, 
+    CPLsnprintf( szDoc, sizeof(szDoc),
 "<gml:FeatureCollection\n"
 "   xmlns:gml=\"http://www.opengis.net/gml\"\n"
 "   xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
@@ -367,13 +373,13 @@ CPLErr  GDALECWCompressor::PrepareCoverageBox(
 "    </gml:FeatureCollection>\n"
 "  </gml:featureMember>\n"
 "</gml:FeatureCollection>\n",
-             sFileInfo.nSizeX-1, sFileInfo.nSizeY-1, 
+             sFileInfo.nSizeX-1, sFileInfo.nSizeY-1,
              szSRSName,
              padfGeoTransform[0] + padfGeoTransform[1] * 0.5
-                                 + padfGeoTransform[4] * 0.5, 
+                                 + padfGeoTransform[4] * 0.5,
              padfGeoTransform[3] + padfGeoTransform[2] * 0.5
                                  + padfGeoTransform[5] * 0.5,
-             szSRSName, 
+             szSRSName,
              padfGeoTransform[1], padfGeoTransform[2],
              szSRSName,
              padfGeoTransform[4], padfGeoTransform[5] );
@@ -391,8 +397,8 @@ CPLErr  GDALECWCompressor::PrepareCoverageBox(
         if( oSRS.exportToXML( &pszGMLDef, NULL ) == OGRERR_NONE )
         {
             pszDictBox = (char *) CPLMalloc(strlen(pszGMLDef) + 4000);
-            
-            sprintf( pszDictBox, 
+
+            snprintf( pszDictBox, strlen(pszGMLDef) + 4000,
 "<gml:Dictionary gml:id=\"CRSU1\" \n"
 "        xmlns:gml=\"http://www.opengis.net/gml\"\n"
 "        xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
@@ -418,7 +424,7 @@ CPLErr  GDALECWCompressor::PrepareCoverageBox(
     poLabel->m_bValid = true;
     m_oGMLAssoc.m_OtherBoxes.push_back( poLabel );
     m_oGMLAssoc.m_OwnedBoxes.push_back( poLabel );
-    
+
     poAssoc = new CNCSJP2File::CNCSJPXAssocBox();
     m_oGMLAssoc.m_OtherBoxes.push_back( poAssoc );
     m_oGMLAssoc.m_OwnedBoxes.push_back( poAssoc );
@@ -442,7 +448,7 @@ CPLErr  GDALECWCompressor::PrepareCoverageBox(
         m_oGMLAssoc.m_OtherBoxes.push_back( poAssoc );
         m_oGMLAssoc.m_OwnedBoxes.push_back( poAssoc );
         poAssoc->m_bValid = true;
-        
+
         poLabel = new CNCSJP2File::CNCSJPXLabelBox();
         poLabel->SetLabel( "CRSDictionary.gml" );
         poLabel->m_bValid = true;
@@ -451,7 +457,7 @@ CPLErr  GDALECWCompressor::PrepareCoverageBox(
 
         poGMLData = new JP2UserBox();
         poGMLData->m_nTBox = 'xml '; /* Is it correct on a big-endian host ? Does ECW work on big-endian hosts ;-) */
-        poGMLData->SetData( strlen(pszDictBox), 
+        poGMLData->SetData( strlen(pszDictBox),
                             (unsigned char *) pszDictBox );
         poAssoc->m_OtherBoxes.push_back( poGMLData );
         poAssoc->m_OwnedBoxes.push_back( poGMLData );
@@ -482,7 +488,7 @@ CPLErr GDALECWCompressor::WriteJP2Box( GDALJP2Box * poBox )
     memcpy( &(poECWBox->m_nTBox), poBox->GetType(), 4 );
     CPL_MSBPTR32( &(poECWBox->m_nTBox) );
 
-    poECWBox->SetData( (int) poBox->GetDataLength(), 
+    poECWBox->SetData( (int) poBox->GetDataLength(),
                        poBox->GetWritableData() );
 
     AddBox( poECWBox );
@@ -513,10 +519,10 @@ void GDALECWCompressor::WriteXMLBoxes()
 }
 
 /************************************************************************/
-/*                            WriteLineBIL()                            */
+/*                          ourWriteLineBIL()                           */
 /************************************************************************/
 
-CPLErr  GDALECWCompressor::WriteLineBIL(UINT16 nBands, void **ppOutputLine, UINT32 *pLineSteps){
+CPLErr  GDALECWCompressor::ourWriteLineBIL(UINT16 nBands, void **ppOutputLine, UINT32 *pLineSteps){
 
     CNCSError oError = CNCSFile::WriteLineBIL(sFileInfo.eCellType,nBands, ppOutputLine, pLineSteps);
 
@@ -533,10 +539,10 @@ CPLErr  GDALECWCompressor::WriteLineBIL(UINT16 nBands, void **ppOutputLine, UINT
 /*      Initialize compressor output.                                   */
 /************************************************************************/
 
-CPLErr GDALECWCompressor::Initialize( 
-    const char *pszFilename, char **papszOptions, 
+CPLErr GDALECWCompressor::Initialize(
+    const char *pszFilename, char **papszOptions,
     int nXSize, int nYSize, int nBands, const char * const * papszBandDescriptions, int bRGBColorSpace,
-    GDALDataType eType, 
+    GDALDataType eType,
     const char *pszWKT, double *padfGeoTransform,
     int nGCPCount, const GDAL_GCP *pasGCPList,
     int bIsJPEG2000, int bPixelIsPoint, char** papszRPCMD,
@@ -548,16 +554,16 @@ CPLErr GDALECWCompressor::Initialize(
 /*      For 4.x and beyond you need a license key to compress data.     */
 /*      Check for it as a configuration option or a creation option.    */
 /* -------------------------------------------------------------------- */
-#if ECWSDK_VERSION >= 40 
+#if ECWSDK_VERSION >= 40
     const char* pszECWKey = CSLFetchNameValue( papszOptions, "ECW_ENCODE_KEY");
     if( pszECWKey == NULL )
         pszECWKey = CPLGetConfigOption( "ECW_ENCODE_KEY", NULL );
-    
-    const char* pszECWCompany = 
+
+    const char* pszECWCompany =
         CSLFetchNameValue( papszOptions, "ECW_ENCODE_COMPANY");
     if( pszECWCompany == NULL )
         pszECWCompany = CPLGetConfigOption( "ECW_ENCODE_COMPANY", NULL );
-    
+
     if( pszECWKey && pszECWCompany)
     {
         CPLDebug( "ECW", "SetOEMKey(%s,%s)", pszECWCompany, pszECWKey );
@@ -581,7 +587,7 @@ CPLErr GDALECWCompressor::Initialize(
 /* -------------------------------------------------------------------- */
     if( nBands == 0 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "ECW driver requires at least one band." );
         return CE_Failure;
     }
@@ -592,14 +598,14 @@ CPLErr GDALECWCompressor::Initialize(
     float      fTargetCompression;
 
     // Default compression based on image type per request from Paul Beaty.
-    if( nBands > 1 ) 
+    if( nBands > 1 )
         fTargetCompression = 95.0;
     else
         fTargetCompression = 90.0;
 
     if( CSLFetchNameValue(papszOptions, "TARGET") != NULL )
     {
-        fTargetCompression = (float) 
+        fTargetCompression = (float)
             CPLAtof(CSLFetchNameValue(papszOptions, "TARGET"));
 
         /* The max allowed value should be 100 - 100 / 65535 = 99.9984740978 */
@@ -608,14 +614,14 @@ CPLErr GDALECWCompressor::Initialize(
         /* (compression rate = 10 000) */
         if( fTargetCompression < 0.0 || fTargetCompression > 99.99 )
         {
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                       "TARGET compression of %.3f invalid, should be a\n"
                       "value between 0 and 99.99 percent.\n",
                       (double) fTargetCompression );
             return CE_Failure;
         }
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Create and initialize compressor.                               */
 /* -------------------------------------------------------------------- */
@@ -670,7 +676,7 @@ CPLErr GDALECWCompressor::Initialize(
             nBits = 8;
             bSigned = FALSE;
             break;
-            
+
         case GDT_UInt16:
 #if ECWSDK_VERSION >=50
             psClient->nCellBitDepth = 16;
@@ -679,7 +685,7 @@ CPLErr GDALECWCompressor::Initialize(
             nBits = 16;
             bSigned = FALSE;
             break;
-            
+
         case GDT_UInt32:
 #if ECWSDK_VERSION >=50
             psClient->nCellBitDepth = 32;
@@ -688,7 +694,7 @@ CPLErr GDALECWCompressor::Initialize(
             nBits = 32;
             bSigned = FALSE;
             break;
-            
+
         case GDT_Int16:
 #if ECWSDK_VERSION >=50
             psClient->nCellBitDepth = 16;
@@ -697,7 +703,7 @@ CPLErr GDALECWCompressor::Initialize(
             nBits = 16;
             bSigned = TRUE;
             break;
-            
+
         case GDT_Int32:
 #if ECWSDK_VERSION >=50
             psClient->nCellBitDepth = 32;
@@ -706,13 +712,13 @@ CPLErr GDALECWCompressor::Initialize(
             nBits = 32;
             bSigned = TRUE;
             break;
-            
+
         case GDT_Float32:
             psClient->eCellType = NCSCT_IEEE4;
             nBits = 32;
             bSigned = TRUE;
             break;
-            
+
         case GDT_Float64:
             psClient->eCellType = NCSCT_IEEE8;
             nBits = 64;
@@ -720,7 +726,7 @@ CPLErr GDALECWCompressor::Initialize(
             break;
 
         default:
-            // We treat complex types as float.  
+            // We treat complex types as float.
             psClient->eCellType = NCSCT_IEEE4;
             nBits = 32;
             bSigned = TRUE;
@@ -733,21 +739,16 @@ CPLErr GDALECWCompressor::Initialize(
 /* -------------------------------------------------------------------- */
     int iBand;
 
-#if ECWSDK_VERSION>=50
-    psClient->pBands = (NCSFileBandInfo *) 
+    psClient->pBands = (NCSFileBandInfo *)
         NCSMalloc( sizeof(NCSFileBandInfo) * nBands, true );
-#else
-    psClient->pBands = (NCSFileBandInfo *) 
-        CPLMalloc( sizeof(NCSFileBandInfo) * nBands );
-#endif
     for( iBand = 0; iBand < nBands; iBand++ )
     {
         psClient->pBands[iBand].nBits = (UINT8) nBits;
         psClient->pBands[iBand].bSigned = (BOOLEAN)bSigned;
-#if ECWSDK_VERSION>=50
+#if ECWSDK_VERSION >=50
         psClient->pBands[iBand].szDesc = NCSStrDup(papszBandDescriptions[iBand]);
 #else
-        psClient->pBands[iBand].szDesc = CPLStrdup(papszBandDescriptions[iBand]);
+        psClient->pBands[iBand].szDesc = NCSStrDup((char*)papszBandDescriptions[iBand]);
 #endif
     }
 
@@ -758,36 +759,36 @@ CPLErr GDALECWCompressor::Initialize(
     if( bIsJPEG2000 )
     {
         pszOption = CSLFetchNameValue(papszOptions, "PROFILE");
-        if( pszOption != NULL && EQUAL(pszOption,"BASELINE_0") ) 
-            SetParameter( 
+        if( pszOption != NULL && EQUAL(pszOption,"BASELINE_0") )
+            SetParameter(
                 CNCSJP2FileView::JP2_COMPRESS_PROFILE_BASELINE_0 );
-        else if( pszOption != NULL && EQUAL(pszOption,"BASELINE_1") ) 
-            SetParameter( 
+        else if( pszOption != NULL && EQUAL(pszOption,"BASELINE_1") )
+            SetParameter(
                 CNCSJP2FileView::JP2_COMPRESS_PROFILE_BASELINE_1 );
         else if( pszOption != NULL && EQUAL(pszOption,"BASELINE_2") )
-            SetParameter( 
+            SetParameter(
                 CNCSJP2FileView::JP2_COMPRESS_PROFILE_BASELINE_2 );
-        else if( pszOption != NULL && EQUAL(pszOption,"NPJE") ) 
-            SetParameter( 
+        else if( pszOption != NULL && EQUAL(pszOption,"NPJE") )
+            SetParameter(
                 CNCSJP2FileView::JP2_COMPRESS_PROFILE_NITF_BIIF_NPJE );
-        else if( pszOption != NULL && EQUAL(pszOption,"EPJE") ) 
-            SetParameter( 
+        else if( pszOption != NULL && EQUAL(pszOption,"EPJE") )
+            SetParameter(
                 CNCSJP2FileView::JP2_COMPRESS_PROFILE_NITF_BIIF_EPJE );
-        
+
         pszOption = CSLFetchNameValue(papszOptions, "CODESTREAM_ONLY" );
-        if( pszOption != NULL ) 
+        if( pszOption != NULL )
             SetParameter(
-                CNCSJP2FileView::JP2_COMPRESS_CODESTREAM_ONLY, 
-                (bool) CSLTestBoolean( pszOption ) );
-        
+                CNCSJP2FileView::JP2_COMPRESS_CODESTREAM_ONLY,
+                CPLTestBool( pszOption ) );
+
         pszOption = CSLFetchNameValue(papszOptions, "LEVELS");
         if( pszOption != NULL )
-            SetParameter( CNCSJP2FileView::JP2_COMPRESS_LEVELS, 
+            SetParameter( CNCSJP2FileView::JP2_COMPRESS_LEVELS,
                                       (UINT32) atoi(pszOption) );
-        
+
         pszOption = CSLFetchNameValue(papszOptions, "LAYERS");
         if( pszOption != NULL )
-            SetParameter( CNCSJP2FileView::JP2_COMPRESS_LAYERS, 
+            SetParameter( CNCSJP2FileView::JP2_COMPRESS_LAYERS,
                                       (UINT32) atoi(pszOption) );
 
         pszOption = CSLFetchNameValue(papszOptions, "PRECINCT_WIDTH");
@@ -797,40 +798,40 @@ CPLErr GDALECWCompressor::Initialize(
 
         pszOption = CSLFetchNameValue(papszOptions, "PRECINCT_HEIGHT");
         if( pszOption != NULL )
-            SetParameter(CNCSJP2FileView::JP2_COMPRESS_PRECINCT_HEIGHT, 
+            SetParameter(CNCSJP2FileView::JP2_COMPRESS_PRECINCT_HEIGHT,
                                      (UINT32) atoi(pszOption) );
 
         pszOption = CSLFetchNameValue(papszOptions, "TILE_WIDTH");
         if( pszOption != NULL )
-            SetParameter( CNCSJP2FileView::JP2_COMPRESS_TILE_WIDTH, 
+            SetParameter( CNCSJP2FileView::JP2_COMPRESS_TILE_WIDTH,
                                       (UINT32) atoi(pszOption) );
 
         pszOption = CSLFetchNameValue(papszOptions, "TILE_HEIGHT");
         if( pszOption != NULL )
-            SetParameter( CNCSJP2FileView::JP2_COMPRESS_TILE_HEIGHT, 
+            SetParameter( CNCSJP2FileView::JP2_COMPRESS_TILE_HEIGHT,
                                       (UINT32) atoi(pszOption) );
 
         pszOption = CSLFetchNameValue(papszOptions, "INCLUDE_SOP");
         if( pszOption != NULL )
-            SetParameter( CNCSJP2FileView::JP2_COMPRESS_INCLUDE_SOP, 
-                                      (bool) CSLTestBoolean( pszOption ) );
-    
+            SetParameter( CNCSJP2FileView::JP2_COMPRESS_INCLUDE_SOP,
+                                      CPLTestBool( pszOption ) );
+
         pszOption = CSLFetchNameValue(papszOptions, "INCLUDE_EPH");
         if( pszOption != NULL )
-            SetParameter( CNCSJP2FileView::JP2_COMPRESS_INCLUDE_EPH, 
-                                      (bool) CSLTestBoolean( pszOption ) );
-    
+            SetParameter( CNCSJP2FileView::JP2_COMPRESS_INCLUDE_EPH,
+                                      CPLTestBool( pszOption ) );
+
         pszOption = CSLFetchNameValue(papszOptions, "PROGRESSION");
         if( pszOption != NULL && EQUAL(pszOption,"LRCP") )
-            SetParameter( 
+            SetParameter(
                 CNCSJP2FileView::JP2_COMPRESS_PROGRESSION_LRCP );
-                                  
+
         else if( pszOption != NULL && EQUAL(pszOption,"RLCP") )
-            SetParameter( 
+            SetParameter(
                 CNCSJP2FileView::JP2_COMPRESS_PROGRESSION_RLCP );
 
         else if( pszOption != NULL && EQUAL(pszOption,"RPCL") )
-            SetParameter( 
+            SetParameter(
                 CNCSJP2FileView::JP2_COMPRESS_PROGRESSION_RPCL );
 
         pszOption = CSLFetchNameValue(papszOptions, "GEODATA_USAGE");
@@ -852,18 +853,18 @@ CPLErr GDALECWCompressor::Initialize(
 
         pszOption = CSLFetchNameValue(papszOptions, "DECOMPRESS_LAYERS");
         if( pszOption != NULL )
-            SetParameter( 
-                CNCSJP2FileView::JP2_DECOMPRESS_LAYERS, 
+            SetParameter(
+                CNCSJP2FileView::JP2_DECOMPRESS_LAYERS,
                 (UINT32) atoi(pszOption) );
 
-        pszOption = CSLFetchNameValue(papszOptions, 
+        pszOption = CSLFetchNameValue(papszOptions,
                                       "DECOMPRESS_RECONSTRUCTION_PARAMETER");
         if( pszOption != NULL )
-            SetParameter( 
-                CNCSJP2FileView::JPC_DECOMPRESS_RECONSTRUCTION_PARAMETER, 
+            SetParameter(
+                CNCSJP2FileView::JPC_DECOMPRESS_RECONSTRUCTION_PARAMETER,
                 (IEEE4) CPLAtof(pszOption) );
     }
-                                  
+
 /* -------------------------------------------------------------------- */
 /*      Georeferencing.                                                 */
 /* -------------------------------------------------------------------- */
@@ -873,9 +874,9 @@ CPLErr GDALECWCompressor::Initialize(
     psClient->fCellIncrementX = 1.0;
     psClient->fCellIncrementY = -1.0;
     psClient->fCWRotationDegrees = 0.0;
-    
+
     if( padfGeoTransform[2] != 0.0 || padfGeoTransform[4] != 0.0 )
-        CPLError( CE_Warning, CPLE_NotSupported, 
+        CPLError( CE_Warning, CPLE_NotSupported,
                   "Rotational coefficients ignored, georeferencing of\n"
                   "output ECW file will be incorrect.\n" );
     else
@@ -895,10 +896,10 @@ CPLErr GDALECWCompressor::Initialize(
 
     strcpy( szProjection, "RAW" );
     strcpy( szDatum, "RAW" );
-    
+
     if( CSLFetchNameValue(papszOptions, "PROJ") != NULL )
     {
-        strncpy( szProjection, 
+        strncpy( szProjection,
                 CSLFetchNameValue(papszOptions, "PROJ"), sizeof(szProjection) );
         szProjection[sizeof(szProjection)-1] = 0;
     }
@@ -923,17 +924,12 @@ CPLErr GDALECWCompressor::Initialize(
         psClient->eCellSizeUnits = ECWTranslateToCellSizeUnits(szUnits);
     }
 
-#if ECWSDK_VERSION>=50
     NCSFree(psClient->szDatum);
     psClient->szDatum = NCSStrDup(szDatum);
     NCSFree(psClient->szProjection);
     psClient->szProjection = NCSStrDup(szProjection);
-#else
-    psClient->szDatum = szDatum;
-    psClient->szProjection = szProjection;
-#endif
 
-    CPLDebug( "ECW", "Writing with PROJ=%s, DATUM=%s, UNITS=%s", 
+    CPLDebug( "ECW", "Writing with PROJ=%s, DATUM=%s, UNITS=%s",
               szProjection, szDatum, ECWTranslateFromCellSizeUnits(psClient->eCellSizeUnits) );
 
 /* -------------------------------------------------------------------- */
@@ -992,20 +988,38 @@ CPLErr GDALECWCompressor::Initialize(
     if( bIsJPEG2000 )
     {
         int bSeekable = !
-          ( strncmp(pszFilename, "/vsistdout/", strlen("/vsistdout/")) == 0 ||
-            strncmp(pszFilename, "/vsizip/", strlen("/vsizip/")) == 0 ||
-            strncmp(pszFilename, "/vsigzip/", strlen("/vsigzip/")) == 0 );
+          ( STARTS_WITH(pszFilename, "/vsistdout/") ||
+            STARTS_WITH(pszFilename, "/vsizip/") ||
+            STARTS_WITH(pszFilename, "/vsigzip/") );
         fpVSIL = VSIFOpenL( pszFilename, (bSeekable) ? "wb+": "wb" );
         if( fpVSIL == NULL )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
-                      "Failed to open %s.", pszFilename );
+            CPLError( CE_Failure, CPLE_OpenFailed,
+                      "Failed to open/create %s.", pszFilename );
             return CE_Failure;
         }
 
-        m_OStream.Access( fpVSIL, TRUE, (BOOLEAN) bSeekable, pszFilename, 
+        m_OStream.Access( fpVSIL, TRUE, (BOOLEAN) bSeekable, pszFilename,
 			  0, -1 );
-    }    
+    }
+    else
+    {
+        if( !STARTS_WITH(pszFilename, "/vsi") )
+        {
+            // Try now to create the file to avoid memory leaks if it is
+            // the SDK that fails to do it.
+            fpVSIL = VSIFOpenL( pszFilename, "wb" );
+            if( fpVSIL == NULL )
+            {
+                CPLError( CE_Failure, CPLE_OpenFailed,
+                        "Failed to open/create %s.", pszFilename );
+                return CE_Failure;
+            }
+            VSIFCloseL(fpVSIL);
+            VSIUnlink(pszFilename);
+            fpVSIL = NULL;
+        }
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Check if we can enable large files.  This option should only    */
@@ -1021,7 +1035,7 @@ CPLErr GDALECWCompressor::Initialize(
 
     pszLargeOK = CPLGetConfigOption( "ECW_LARGE_OK", pszLargeOK );
 
-    if( CSLTestBoolean(pszLargeOK) )
+    if( CPLTestBool(pszLargeOK) )
     {
         CNCSFile::SetKeySize();
         CPLDebug( "ECW", "Large file generation enabled." );
@@ -1051,7 +1065,7 @@ CPLErr GDALECWCompressor::Initialize(
         if (m_poSrcDS && m_poSrcDS->GetMetadataItem("FILE_METADATA_CLASSIFICATION")!=NULL){
             psClient->pFileMetaData->sClassification =  NCSStrDupT(NCS::CString(m_poSrcDS->GetMetadataItem("FILE_METADATA_CLASSIFICATION")).c_str());
         }
-        if ( pszECWCompany != NULL && CSLTestBoolean(CPLGetConfigOption("GDAL_ECW_WRITE_COMPANY", "YES"))  ){
+        if ( pszECWCompany != NULL && CPLTestBool(CPLGetConfigOption("GDAL_ECW_WRITE_COMPANY", "YES"))  ){
             psClient->pFileMetaData->sCompany = NCSStrDupT(NCS::CString(pszECWCompany).c_str());
         }
         CPLString osCompressionSoftware = GetCompressionSoftwareName();
@@ -1072,14 +1086,25 @@ CPLErr GDALECWCompressor::Initialize(
 /* -------------------------------------------------------------------- */
 /*      Set the file info.                                              */
 /* -------------------------------------------------------------------- */
-    CNCSError oError;
-
-    oError = SetFileInfo( sFileInfo );
+    CNCSError oError = SetFileInfo( sFileInfo );
 
     if( oError.GetErrorNumber() == NCS_SUCCESS )
     {
         if( fpVSIL == NULL )
-            oError = Open( (char *) pszFilename, false, true );
+        {
+#if ECWSDK_VERSION>=40 && defined(WIN32)
+            if( CPLTestBool( CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
+            {
+                wchar_t *pwszFilename = CPLRecodeToWChar( pszFilename, CPL_ENC_UTF8, CPL_ENC_UCS2 );
+                oError = GetCNCSError(Open( pwszFilename, false, true ));
+                CPLFree( pwszFilename );
+            }
+            else
+#endif
+            {
+                oError = GetCNCSError(Open( (char *) pszFilename, false, true ));
+            }
+        }
         else
             oError = CNCSJP2FileView::Open( &(m_OStream) );
     }
@@ -1114,11 +1139,11 @@ static int ECWIsInputRGBColorSpace(GDALDataset* poSrcDS)
     int bRGBColorSpace = FALSE;
     int bRGB = FALSE;
     if ( nBands>=3 ) {
-        bRGB = (poSrcDS->GetRasterBand(1)->GetColorInterpretation() 
+        bRGB = (poSrcDS->GetRasterBand(1)->GetColorInterpretation()
                  == GCI_RedBand);
-        bRGB &= (poSrcDS->GetRasterBand(2)->GetColorInterpretation() 
+        bRGB &= (poSrcDS->GetRasterBand(2)->GetColorInterpretation()
                  == GCI_GreenBand);
-        bRGB &= (poSrcDS->GetRasterBand(3)->GetColorInterpretation() 
+        bRGB &= (poSrcDS->GetRasterBand(3)->GetColorInterpretation()
                  == GCI_BlueBand);
     }
     if( nBands == 3 )
@@ -1127,7 +1152,7 @@ static int ECWIsInputRGBColorSpace(GDALDataset* poSrcDS)
     }
     else if( nBands == 4 && bRGB )
     {
-        bRGBColorSpace = (poSrcDS->GetRasterBand(4)->GetColorInterpretation() 
+        bRGBColorSpace = (poSrcDS->GetRasterBand(4)->GetColorInterpretation()
                  == GCI_AlphaBand);
     }
 
@@ -1139,8 +1164,8 @@ static int ECWIsInputRGBColorSpace(GDALDataset* poSrcDS)
 /************************************************************************/
 
 static GDALDataset *
-ECWCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
-               int bStrict, char ** papszOptions, 
+ECWCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
+               int bStrict, char ** papszOptions,
                GDALProgressFunc pfnProgress, void * pProgressData,
                int bIsJPEG2000 )
 
@@ -1156,7 +1181,7 @@ ECWCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
     if (nBands == 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "ECW driver does not support source dataset with zero band.\n");
         return NULL;
     }
@@ -1174,9 +1199,8 @@ ECWCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      For ECW, confirm the datatype is 8bit (or uint16 for ECW v3)    */
 /* -------------------------------------------------------------------- */
-    bool bECWV3 = false;
-
     #if ECWSDK_VERSION >= 50
+    bool bECWV3 = false;
     if (bIsJPEG2000 == FALSE){
         const char* pszOption = CSLFetchNameValue(papszOptions, "ECW_FORMAT_VERSION");
         if( pszOption != NULL )
@@ -1185,7 +1209,11 @@ ECWCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         }
     }
     #endif
-    if( !(eType == GDT_Byte  || (bECWV3 && eType == GDT_UInt16 ) || bIsJPEG2000 ) )
+    if( !(eType == GDT_Byte  ||
+#if ECWSDK_VERSION >= 50
+        (bECWV3 && eType == GDT_UInt16 ) ||
+#endif
+        bIsJPEG2000 ) )
     {
         if( bStrict )
         {
@@ -1195,7 +1223,7 @@ ECWCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 #if ECWSDK_VERSION >= 50
                       " ECW version 3 files supports UInt16 as well."
                       " Specify ECW_FORMAT_VERSION=3 creation option to write version 3 file. \n"
-#else 
+#else
                       ". \n"
 #endif
                       , GDALGetDataTypeName( eType ) );
@@ -1205,7 +1233,7 @@ ECWCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 #if ECWSDK_VERSION>=50
             if (eType == GDT_UInt16)
             {
-                CPLError( CE_Warning, CPLE_AppDefined, 
+                CPLError( CE_Warning, CPLE_AppDefined,
                           "ECW version 2 does not support UInt16 data type, truncating to Byte."
                           " Consider specifying ECW_FORMAT_VERSION=3 for full UInt16 support available in ECW version 3. \n");
             }
@@ -1228,7 +1256,6 @@ ECWCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      Setup the compressor.                                           */
 /* -------------------------------------------------------------------- */
     GDALECWCompressor         oCompressor;
-    CNCSError oErr;
 
     oCompressor.pfnProgress = pfnProgress;
     oCompressor.pProgressData = pProgressData;
@@ -1238,8 +1265,7 @@ ECWCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         return NULL;
 
     char** papszBandDescriptions = (char**) CPLMalloc(nBands * sizeof(char*));
-    int i;
-    for (i=0;i<nBands;i++){
+    for (int i=0;i<nBands;i++){
         /* Make a copy since ECWGetColorInterpretationName() can return a string generated */
         /* by CPLSPrintf(), which has just a few rotating entries. */
         papszBandDescriptions[i] = CPLStrdup(ECWGetColorInterpretationName(poSrcDS->GetRasterBand(i+1)->GetColorInterpretation(), i));
@@ -1248,17 +1274,17 @@ ECWCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     const char* pszAreaOrPoint = poSrcDS->GetMetadataItem(GDALMD_AREA_OR_POINT);
     int bPixelIsPoint = pszAreaOrPoint != NULL && EQUAL(pszAreaOrPoint, GDALMD_AOP_POINT);
 
-    if( oCompressor.Initialize( pszFilename, papszOptions, 
+    if( oCompressor.Initialize( pszFilename, papszOptions,
                                 nXSize, nYSize, nBands, papszBandDescriptions, bRGBColorSpace,
-                                eType, pszWKT, adfGeoTransform, 
-                                poSrcDS->GetGCPCount(), 
+                                eType, pszWKT, adfGeoTransform,
+                                poSrcDS->GetGCPCount(),
                                 poSrcDS->GetGCPs(),
                                 bIsJPEG2000, bPixelIsPoint,
                                 poSrcDS->GetMetadata("RPC"),
                                 poSrcDS )
         != CE_None )
     {
-        for (i=0;i<nBands;i++)
+        for (int i=0;i<nBands;i++)
             CPLFree(papszBandDescriptions[i]);
         CPLFree(papszBandDescriptions);
         return NULL;
@@ -1267,11 +1293,14 @@ ECWCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Start the compression.                                          */
 /* -------------------------------------------------------------------- */
-    oErr = oCompressor.Write();
+    CNCSError oErr = oCompressor.Write();
 
     if( oErr.GetErrorNumber() != NCS_SUCCESS )
     {
         ECWReportError(oErr);
+        for (int i=0;i<nBands;i++)
+            CPLFree(papszBandDescriptions[i]);
+        CPLFree(papszBandDescriptions);
         return NULL;
     }
 
@@ -1279,7 +1308,7 @@ ECWCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      Cleanup, and return read-only handle.                           */
 /* -------------------------------------------------------------------- */
     oCompressor.CloseDown();
-    for (i=0;i<nBands;i++)
+    for (int i=0;i<nBands;i++)
         CPLFree(papszBandDescriptions[i]);
     CPLFree(papszBandDescriptions);
     pfnProgress( 1.001, NULL, pProgressData );
@@ -1289,7 +1318,7 @@ ECWCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
     GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly);
     GDALPamDataset *poDS;
-    
+
     if (bIsJPEG2000)
         poDS = (GDALPamDataset*) ECWDatasetOpenJPEG2000(&oOpenInfo);
     else
@@ -1330,30 +1359,29 @@ ECWCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /************************************************************************/
 
 GDALDataset *
-ECWCreateCopyECW( const char * pszFilename, GDALDataset *poSrcDS, 
-                  int bStrict, char ** papszOptions, 
+ECWCreateCopyECW( const char * pszFilename, GDALDataset *poSrcDS,
+                  int bStrict, char ** papszOptions,
                   GDALProgressFunc pfnProgress, void * pProgressData )
 
 {
     int nBands = poSrcDS->GetRasterCount();
     if (nBands == 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "ECW driver does not support source dataset with zero band.\n");
         return NULL;
     }
 
     if( !EQUAL(CPLGetExtension(pszFilename),"ecw") )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "ECW driver does not support creating ECW files\n"
                   "with an extension other than .ecw" );
         return NULL;
     }
-    bool bECWV3 = false;
 
 #if ECWSDK_VERSION >= 50
-
+    bool bECWV3 = false;
     const char* pszOption = CSLFetchNameValue(papszOptions, "ECW_FORMAT_VERSION");
     if( pszOption != NULL )
     {
@@ -1363,13 +1391,15 @@ ECWCreateCopyECW( const char * pszFilename, GDALDataset *poSrcDS,
 #endif
 
     GDALDataType eDataType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
-    if( eDataType != GDT_Byte 
-        && !(bECWV3 && (eDataType == GDT_UInt16))  
+    if( eDataType != GDT_Byte
+#if ECWSDK_VERSION >= 50
+        && !(bECWV3 && (eDataType == GDT_UInt16))
+#endif
         && bStrict )
     {
 #if ECWSDK_VERSION >= 50
         if (eDataType == GDT_UInt16){
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                 "ECW v2 does not support UInt16 data type. Consider "
                 " specifying ECW_FORMAT_VERSION=3 for full UInt16 support available in ECW v3. \n"
                 );
@@ -1377,13 +1407,13 @@ ECWCreateCopyECW( const char * pszFilename, GDALDataset *poSrcDS,
         else
 #endif
         {
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                   "ECW driver doesn't support data type %s. "
                   "Only unsigned eight "
 #if ECWSDK_VERSION >= 50
                   "or sixteen "
 #endif
-                  "bit bands supported. \n", 
+                  "bit bands supported. \n",
                   GDALGetDataTypeName(eDataType) );
         }
 
@@ -1392,18 +1422,18 @@ ECWCreateCopyECW( const char * pszFilename, GDALDataset *poSrcDS,
 
     if( poSrcDS->GetRasterXSize() < 128 || poSrcDS->GetRasterYSize() < 128 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "ECW driver requires image to be at least 128x128,\n"
-                  "the source image is %dx%d.\n", 
+                  "the source image is %dx%d.\n",
                   poSrcDS->GetRasterXSize(),
                   poSrcDS->GetRasterYSize() );
-                  
+
         return NULL;
     }
 
     if (poSrcDS->GetRasterBand(1)->GetColorTable() != NULL)
     {
-        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, 
+        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
                   "ECW driver ignores color table. "
                   "The source raster band will be considered as grey level.\n"
                   "Consider using color table expansion (-expand option in gdal_translate)\n");
@@ -1411,7 +1441,7 @@ ECWCreateCopyECW( const char * pszFilename, GDALDataset *poSrcDS,
             return NULL;
     }
 
-    return ECWCreateCopy( pszFilename, poSrcDS, bStrict, papszOptions, 
+    return ECWCreateCopy( pszFilename, poSrcDS, bStrict, papszOptions,
                           pfnProgress, pProgressData, FALSE );
 }
 
@@ -1420,30 +1450,29 @@ ECWCreateCopyECW( const char * pszFilename, GDALDataset *poSrcDS,
 /************************************************************************/
 
 GDALDataset *
-ECWCreateCopyJPEG2000( const char * pszFilename, GDALDataset *poSrcDS, 
-                       int bStrict, char ** papszOptions, 
+ECWCreateCopyJPEG2000( const char * pszFilename, GDALDataset *poSrcDS,
+                       int bStrict, char ** papszOptions,
                        GDALProgressFunc pfnProgress, void * pProgressData )
 
 {
     int nBands = poSrcDS->GetRasterCount();
     if (nBands == 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "JP2ECW driver does not support source dataset with zero band.\n");
         return NULL;
     }
 
     if( EQUAL(CPLGetExtension(pszFilename),"ecw") )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "JP2ECW driver does not support creating JPEG2000 files\n"
                   "with a .ecw extension.  Please use anything else." );
         return NULL;
     }
 
     GDALDataType eDataType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
-    if( eDataType != GDT_Byte 
-        && eDataType != GDT_Byte 
+    if( eDataType != GDT_Byte
         && eDataType != GDT_Int16
         && eDataType != GDT_UInt16
         && eDataType != GDT_Int32
@@ -1452,7 +1481,7 @@ ECWCreateCopyJPEG2000( const char * pszFilename, GDALDataset *poSrcDS,
         && eDataType != GDT_Float64
         && bStrict )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "JP2ECW driver doesn't support data type %s. ",
                   GDALGetDataTypeName(eDataType) );
 
@@ -1461,7 +1490,7 @@ ECWCreateCopyJPEG2000( const char * pszFilename, GDALDataset *poSrcDS,
 
     if (poSrcDS->GetRasterBand(1)->GetColorTable() != NULL)
     {
-        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, 
+        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
                   "JP2ECW driver ignores color table. "
                   "The source raster band will be considered as grey level.\n"
                   "Consider using color table expansion (-expand option in gdal_translate)\n");
@@ -1469,26 +1498,26 @@ ECWCreateCopyJPEG2000( const char * pszFilename, GDALDataset *poSrcDS,
             return NULL;
     }
 
-    return ECWCreateCopy( pszFilename, poSrcDS, bStrict, papszOptions, 
+    return ECWCreateCopy( pszFilename, poSrcDS, bStrict, papszOptions,
                           pfnProgress, pProgressData, TRUE );
 }
 
 /************************************************************************/
 /************************************************************************
- 
+
                ECW/JPEG200 Create() Support
                ----------------------------
 
-  The remainder of the file is code to implement the Create() method. 
+  The remainder of the file is code to implement the Create() method.
   New dataset and raster band classes are defined specifically for the
   purpose of being write-only.  In particular, you cannot read back data
   from these datasets, and writing must occur in a pretty specific order.
-  
+
   That is, you need to write all metadata (projection, georef, etc) first
   and then write the image data.  All bands data for the first scanline
   should be written followed by all bands for the second scanline and so on.
 
-  Creation supports the same virtual subfile names as CreateCopy() supports. 
+  Creation supports the same virtual subfile names as CreateCopy() supports.
 
  ************************************************************************/
 /************************************************************************/
@@ -1514,19 +1543,19 @@ class IRasterIORequest
         int nBufXSize;
         int nBufYSize;
 
-        IRasterIORequest( GDALRasterBand* poBand,
-                          int nXOff, int nYOff, int nXSize, int nYSize,
-                          void * pData, int nBufXSize, int nBufYSize,
-                          GDALDataType eBufType, 
+        IRasterIORequest( GDALRasterBand* poBandIn,
+                          int nXOffIn, int nYOffIn, int nXSizeIn, int nYSizeIn,
+                          void * pData, int nBufXSizeIn, int nBufYSizeIn,
+                          GDALDataType eBufType,
                           GSpacing nPixelSpace, GSpacing nLineSpace ) :
-                            poBand(poBand),
-                            nXOff(nXOff),
-                            nYOff(nYOff),
-                            nXSize(nXSize),
-                            nYSize(nYSize),
+                            poBand(poBandIn),
+                            nXOff(nXOffIn),
+                            nYOff(nYOffIn),
+                            nXSize(nXSizeIn),
+                            nYSize(nYSizeIn),
                             pabyData(NULL),
-                            nBufXSize(nBufXSize),
-                            nBufYSize(nBufYSize)
+                            nBufXSize(nBufXSizeIn),
+                            nBufYSize(nBufYSizeIn)
         {
             GDALDataType eDataType = poBand->GetRasterDataType();
             int nDataTypeSize = GDALGetDataTypeSize(eDataType) / 8;
@@ -1534,7 +1563,7 @@ class IRasterIORequest
             for(int iY = 0; iY < nBufYSize; iY ++)
             {
                 GDALCopyWords((GByte*)pData + iY * nLineSpace,
-                              eBufType, nPixelSpace,
+                              eBufType, static_cast<int>(nPixelSpace),
                               pabyData + iY * nBufXSize * nDataTypeSize,
                               eDataType, nDataTypeSize,
                               nBufXSize);
@@ -1544,7 +1573,7 @@ class IRasterIORequest
 };
 #endif
 
-class CPL_DLL ECWWriteDataset : public GDALDataset
+class ECWWriteDataset : public GDALDataset
 {
     friend class ECWWriteRasterBand;
 
@@ -1553,26 +1582,26 @@ class CPL_DLL ECWWriteDataset : public GDALDataset
     int       bIsJPEG2000;
     GDALDataType eDataType;
     char    **papszOptions;
-  
+
     char     *pszProjection;
     double    adfGeoTransform[6];
 
     GDALECWCompressor oCompressor;
-    int       bCrystalized;
-    
+    int       bCrystalized;  // TODO: Spelling.
+
     int       nLoadedLine;
     GByte     *pabyBILBuffer;
 
-    int       bOutOfOrderWriteOccured;
+    int       bOutOfOrderWriteOccurred;
 #ifdef OPTIMIZED_FOR_GDALWARP
     int       nPrevIRasterIOBand;
 #endif
 
-    CPLErr    Crystalize();
+  CPLErr    Crystalize();  // TODO: Spelling.
     CPLErr    FlushLine();
 
   public:
-            ECWWriteDataset( const char *, int, int, int, 
+            ECWWriteDataset( const char *, int, int, int,
                                  GDALDataType, char **papszOptions,
                                  int );
             ~ECWWriteDataset();
@@ -1588,7 +1617,7 @@ class CPL_DLL ECWWriteDataset : public GDALDataset
     virtual CPLErr IRasterIO( GDALRWFlag eRWFlag,
                               int nXOff, int nYOff, int nXSize, int nYSize,
                               void * pData, int nBufXSize, int nBufYSize,
-                              GDALDataType eBufType, 
+                              GDALDataType eBufType,
                               int nBandCount, int *panBandMap,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
                               GSpacing nBandSpace,
@@ -1601,11 +1630,11 @@ class CPL_DLL ECWWriteDataset : public GDALDataset
 /*                         ECWWriteRasterBand                           */
 /* ==================================================================== */
 /************************************************************************/
- 
+
 class ECWWriteRasterBand : public GDALRasterBand
 {
     friend class ECWWriteDataset;
-    
+
     // NOTE: poDS may be altered for NITF/JPEG2000 files!
     ECWWriteDataset     *poGDS;
 
@@ -1620,13 +1649,13 @@ class ECWWriteRasterBand : public GDALRasterBand
                    ECWWriteRasterBand( ECWWriteDataset *, int );
                   ~ECWWriteRasterBand();
 
-    virtual CPLErr SetColorInterpretation( GDALColorInterp eInterpIn ) 
+    virtual CPLErr SetColorInterpretation( GDALColorInterp eInterpIn )
         { eInterp = eInterpIn;
           if( strlen(GetDescription()) == 0 )
               SetDescription(ECWGetColorInterpretationName(eInterp, nBand-1));
           return CE_None;
         }
-    virtual GDALColorInterp GetColorInterpretation() 
+    virtual GDALColorInterp GetColorInterpretation()
         { return eInterp; }
 
     virtual CPLErr IReadBlock( int, int, void * );
@@ -1636,7 +1665,7 @@ class ECWWriteRasterBand : public GDALRasterBand
     virtual CPLErr IRasterIO( GDALRWFlag eRWFlag,
                               int nXOff, int nYOff, int nXSize, int nYSize,
                               void * pData, int nBufXSize, int nBufYSize,
-                              GDALDataType eBufType, 
+                              GDALDataType eBufType,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
                               GDALRasterIOExtraArg* psExtraArg);
 #endif
@@ -1646,10 +1675,10 @@ class ECWWriteRasterBand : public GDALRasterBand
 /*                          ECWWriteDataset()                           */
 /************************************************************************/
 
-ECWWriteDataset::ECWWriteDataset( const char *pszFilename, 
-                                  int nXSize, int nYSize, int nBandCount, 
+ECWWriteDataset::ECWWriteDataset( const char *pszFilenameIn,
+                                  int nXSize, int nYSize, int nBandCount,
                                   GDALDataType eType,
-                                  char **papszOptions, int bIsJPEG2000 )
+                                  char **papszOptionsIn, int bIsJPEG2000In )
 
 {
     bCrystalized = FALSE;
@@ -1658,10 +1687,10 @@ ECWWriteDataset::ECWWriteDataset( const char *pszFilename,
 
     eAccess = GA_Update;
 
-    this->bIsJPEG2000 = bIsJPEG2000;
+    this->bIsJPEG2000 = bIsJPEG2000In;
     this->eDataType = eType;
-    this->papszOptions = CSLDuplicate( papszOptions );
-    this->pszFilename = CPLStrdup( pszFilename );
+    this->papszOptions = CSLDuplicate( papszOptionsIn );
+    this->pszFilename = CPLStrdup( pszFilenameIn );
 
     nRasterXSize = nXSize;
     nRasterYSize = nYSize;
@@ -1680,7 +1709,7 @@ ECWWriteDataset::ECWWriteDataset( const char *pszFilename,
         SetBand( iBand, new ECWWriteRasterBand( this, iBand ) );
     }
 
-    bOutOfOrderWriteOccured = FALSE;
+    bOutOfOrderWriteOccurred = FALSE;
 #ifdef OPTIMIZED_FOR_GDALWARP
     nPrevIRasterIOBand = -1;
 #endif
@@ -1697,7 +1726,7 @@ ECWWriteDataset::~ECWWriteDataset()
 
     if( bCrystalized )
     {
-        if( bOutOfOrderWriteOccured )
+        if( bOutOfOrderWriteOccurred )
         {
             /* Otherwise there's a hang-up in the destruction of the oCompressor object */
             while( nLoadedLine < nRasterYSize - 1 )
@@ -1779,11 +1808,10 @@ CPLErr ECWWriteDataset::Crystalize()
     int nWordSize = GDALGetDataTypeSize( eDataType ) / 8;
 
     CPLErr eErr;
-    CNCSError oError;
 
     if( bCrystalized )
         return CE_None;
-    
+
     const char **paszBandDescriptions = (const char **) CPLMalloc(nBands * sizeof(char *));
     for (int i = 0; i < nBands; i++ ){
         paszBandDescriptions[i] = GetRasterBand(i+1)->GetDescription();
@@ -1791,10 +1819,10 @@ CPLErr ECWWriteDataset::Crystalize()
 
     int bRGBColorSpace = ECWIsInputRGBColorSpace(this);
 
-    eErr = oCompressor.Initialize( pszFilename, papszOptions, 
+    eErr = oCompressor.Initialize( pszFilename, papszOptions,
                                    nRasterXSize, nRasterYSize, nBands,paszBandDescriptions, bRGBColorSpace,
-                                   eDataType, 
-                                   pszProjection, adfGeoTransform, 
+                                   eDataType,
+                                   pszProjection, adfGeoTransform,
                                    0, NULL,
                                    bIsJPEG2000, FALSE, NULL );
 
@@ -1803,9 +1831,9 @@ CPLErr ECWWriteDataset::Crystalize()
 
     nLoadedLine = -1;
     pabyBILBuffer = (GByte *) CPLMalloc( nWordSize * nBands * nRasterXSize );
-    
+
     CPLFree(paszBandDescriptions);
-    
+
     return eErr;
 }
 
@@ -1820,7 +1848,7 @@ CPLErr ECWWriteDataset::FlushLine()
     CPLErr eErr;
 
 /* -------------------------------------------------------------------- */
-/*      Crystalize if not already done.                                 */
+/*      Crystallize if not already done.                                */
 /* -------------------------------------------------------------------- */
     if( !bCrystalized )
     {
@@ -1835,16 +1863,16 @@ CPLErr ECWWriteDataset::FlushLine()
 /* -------------------------------------------------------------------- */
     if( nLoadedLine != -1 )
     {
-        
+
         void **papOutputLine;
 
         papOutputLine = (void **) CPLMalloc(sizeof(void*) * nBands);
         for( int i = 0; i < nBands; i++ )
-            papOutputLine[i] = 
+            papOutputLine[i] =
                 (void *) (pabyBILBuffer + i * nWordSize * nRasterXSize);
-        
 
-        eErr =  oCompressor.WriteLineBIL( (UINT16) nBands, papOutputLine );
+
+        eErr =  oCompressor.ourWriteLineBIL( (UINT16) nBands, papOutputLine );
         CPLFree( papOutputLine );
         if (eErr!=CE_None){
            return eErr;
@@ -1868,7 +1896,7 @@ CPLErr ECWWriteDataset::FlushLine()
 CPLErr ECWWriteDataset::IRasterIO( GDALRWFlag eRWFlag,
                               int nXOff, int nYOff, int nXSize, int nYSize,
                               void * pData, int nBufXSize, int nBufYSize,
-                              GDALDataType eBufType, 
+                              GDALDataType eBufType,
                               int nBandCount, int *panBandMap,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
                               GSpacing nBandSpace,
@@ -1877,7 +1905,7 @@ CPLErr ECWWriteDataset::IRasterIO( GDALRWFlag eRWFlag,
     ECWWriteRasterBand* po4thBand = NULL;
     IRasterIORequest* poIORequest = NULL;
 
-    if( bOutOfOrderWriteOccured )
+    if( bOutOfOrderWriteOccurred )
         return CE_Failure;
 
     if( eRWFlag == GF_Write && nBandCount == 3 && nBands == 4 )
@@ -1894,7 +1922,7 @@ CPLErr ECWWriteDataset::IRasterIO( GDALRWFlag eRWFlag,
                 nBufYSize != poIORequest->nBufYSize )
             {
                 CPLError(CE_Failure, CPLE_AppDefined, "Out of order write");
-                bOutOfOrderWriteOccured = TRUE;
+                bOutOfOrderWriteOccurred = TRUE;
                 return CE_Failure;
             }
         }
@@ -1906,18 +1934,19 @@ CPLErr ECWWriteDataset::IRasterIO( GDALRWFlag eRWFlag,
         (nBandCount == nBands || ( nBandCount == 3 && poIORequest != NULL && nBands == 4) ) &&
         nPixelSpace == nDataTypeSize && nLineSpace == nPixelSpace * nRasterXSize )
     {
+        CPLErr eErr = CE_None;
         GByte* pabyData = (GByte*)pData;
         for(int iY = 0; iY < nYSize; iY ++)
         {
-            for(int iBand = 0; iBand < nBandCount; iBand ++)
+            for(int iBand = 0; iBand < nBandCount && eErr == CE_None; iBand ++)
             {
-                GetRasterBand(panBandMap[iBand])->WriteBlock(0, iY + nYOff,
+                eErr = GetRasterBand(panBandMap[iBand])->WriteBlock(0, iY + nYOff,
                     pabyData + iY * nLineSpace + iBand * nBandSpace);
             }
 
-            if( poIORequest != NULL )
+            if( poIORequest != NULL && eErr == CE_None )
             {
-                po4thBand->WriteBlock(0, iY + nYOff,
+                eErr = po4thBand->WriteBlock(0, iY + nYOff,
                     poIORequest->pabyData + iY * nDataTypeSize * nXSize);
             }
         }
@@ -1928,13 +1957,13 @@ CPLErr ECWWriteDataset::IRasterIO( GDALRWFlag eRWFlag,
             po4thBand->poIORequest = NULL;
         }
 
-        return CE_None;
+        return eErr;
     }
     else
         return GDALDataset::IRasterIO(eRWFlag,
                               nXOff, nYOff, nXSize, nYSize,
                               pData, nBufXSize, nBufYSize,
-                              eBufType, 
+                              eBufType,
                               nBandCount, panBandMap,
                               nPixelSpace, nLineSpace, nBandSpace, psExtraArg);
 }
@@ -2004,7 +2033,7 @@ CPLErr ECWWriteRasterBand::IReadBlock( CPL_UNUSED int nBlockX,
 CPLErr ECWWriteRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                               int nXOff, int nYOff, int nXSize, int nYSize,
                               void * pData, int nBufXSize, int nBufYSize,
-                              GDALDataType eBufType, 
+                              GDALDataType eBufType,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
                               GDALRasterIOExtraArg* psExtraArg)
 {
@@ -2015,10 +2044,10 @@ CPLErr ECWWriteRasterBand::IRasterIO( GDALRWFlag eRWFlag,
         /* It is called before GDALDatasetRasterIO() on the 3 first bands */
         if( poIORequest != NULL )
             return CE_Failure;
-        poIORequest = new IRasterIORequest( this, 
+        poIORequest = new IRasterIORequest( this,
                               nXOff, nYOff, nXSize, nYSize,
                               pData, nBufXSize, nBufYSize,
-                              eBufType, 
+                              eBufType,
                               nPixelSpace, nLineSpace );
         return CE_None;
     }
@@ -2027,7 +2056,7 @@ CPLErr ECWWriteRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     return GDALRasterBand::IRasterIO( eRWFlag,
                               nXOff, nYOff, nXSize, nYSize,
                               pData, nBufXSize, nBufYSize,
-                              eBufType, 
+                              eBufType,
                               nPixelSpace, nLineSpace, psExtraArg );
 }
 #endif
@@ -2043,7 +2072,7 @@ CPLErr ECWWriteRasterBand::IWriteBlock( CPL_UNUSED int nBlockX,
     int nWordSize = GDALGetDataTypeSize( eDataType ) / 8;
     CPLErr eErr;
 
-    if( poGDS->bOutOfOrderWriteOccured )
+    if( poGDS->bOutOfOrderWriteOccurred )
         return CE_Failure;
 
 /* -------------------------------------------------------------------- */
@@ -2062,19 +2091,19 @@ CPLErr ECWWriteRasterBand::IWriteBlock( CPL_UNUSED int nBlockX,
 /* -------------------------------------------------------------------- */
     if( nBlockY != poGDS->nLoadedLine )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Apparent attempt to write to ECW non-sequentially.\n"
                   "Loaded line is %d, but %d of band %d was written to.",
                   poGDS->nLoadedLine, nBlockY, nBand );
-        poGDS->bOutOfOrderWriteOccured = TRUE;
+        poGDS->bOutOfOrderWriteOccurred = TRUE;
         return CE_Failure;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Copy passed data into current line buffer.                      */
 /* -------------------------------------------------------------------- */
-    memcpy( poGDS->pabyBILBuffer + (nBand-1) * nWordSize * nRasterXSize, 
-            pBuffer, 
+    memcpy( poGDS->pabyBILBuffer + (nBand-1) * nWordSize * nRasterXSize,
+            pBuffer,
             nWordSize * nRasterXSize );
 
     return CE_None;
@@ -2085,13 +2114,18 @@ CPLErr ECWWriteRasterBand::IWriteBlock( CPL_UNUSED int nBlockX,
 /************************************************************************/
 
 GDALDataset *
-ECWCreateJPEG2000(const char *pszFilename, int nXSize, int nYSize, int nBands, 
+ECWCreateJPEG2000(const char *pszFilename, int nXSize, int nYSize, int nBands,
                   GDALDataType eType, char **papszOptions )
 
 {
+    if( nBands == 0 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, "0 band not supported");
+        return NULL;
+    }
     ECWInitialize();
 
-    return new ECWWriteDataset( pszFilename, nXSize, nYSize, nBands, 
+    return new ECWWriteDataset( pszFilename, nXSize, nYSize, nBands,
                                 eType, papszOptions, TRUE );
 }
 
@@ -2100,13 +2134,18 @@ ECWCreateJPEG2000(const char *pszFilename, int nXSize, int nYSize, int nBands,
 /************************************************************************/
 
 GDALDataset *
-ECWCreateECW( const char *pszFilename, int nXSize, int nYSize, int nBands, 
+ECWCreateECW( const char *pszFilename, int nXSize, int nYSize, int nBands,
               GDALDataType eType, char **papszOptions )
 
 {
+    if( nBands == 0 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, "0 band not supported");
+        return NULL;
+    }
     ECWInitialize();
 
-    return new ECWWriteDataset( pszFilename, nXSize, nYSize, nBands, 
+    return new ECWWriteDataset( pszFilename, nXSize, nYSize, nBands,
                                 eType, papszOptions, FALSE );
 }
 
diff --git a/frmts/ecw/ecwdataset.cpp b/frmts/ecw/ecwdataset.cpp
index 149d2bd..6d9383a 100644
--- a/frmts/ecw/ecwdataset.cpp
+++ b/frmts/ecw/ecwdataset.cpp
@@ -1,7 +1,7 @@
 /******************************************************************************
- * $Id: ecwdataset.cpp 29507 2015-07-08 21:59:03Z rouault $
+ * $Id: ecwdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
- * Project:  GDAL 
+ * Project:  GDAL
  * Purpose:  ECW (ERDAS Wavelet Compression Format) Driver
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -28,22 +28,23 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_ecw.h"
 #include "cpl_minixml.h"
+#include "gdal_ecw.h"
+#include "gdal_frmts.h"
 #include "ogr_spatialref.h"
 #include "ogr_api.h"
 #include "ogr_geometry.h"
 
 #include "../mem/memdataset.h"
 
-CPL_CVSID("$Id: ecwdataset.cpp 29507 2015-07-08 21:59:03Z rouault $");
+CPL_CVSID("$Id: ecwdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 #undef NOISY_DEBUG
 
 #ifdef FRMT_ecw
 
 static const unsigned char jpc_header[] = {0xff,0x4f};
-static const unsigned char jp2_header[] = 
+static const unsigned char jp2_header[] =
     {0x00,0x00,0x00,0x0c,0x6a,0x50,0x20,0x20,0x0d,0x0a,0x87,0x0a};
 
 static CPLMutex *hECWDatasetMutex = NULL;
@@ -65,11 +66,11 @@ void ECWReportError(CNCSError& oErr, const char* pszMsg)
 {
 #if ECWSDK_VERSION<50
     char* pszErrorMessage = oErr.GetErrorMessage();
-    CPLError( CE_Failure, CPLE_AppDefined, 
+    CPLError( CE_Failure, CPLE_AppDefined,
               "%s%s", pszMsg, pszErrorMessage );
     NCSFree(pszErrorMessage);
-#else 
-    CPLError( CE_Failure, CPLE_AppDefined, 
+#else
+    CPLError( CE_Failure, CPLE_AppDefined,
              "%s%s", pszMsg, NCSGetLastErrorText(oErr) );
 #endif
 }
@@ -78,16 +79,16 @@ void ECWReportError(CNCSError& oErr, const char* pszMsg)
 /*                           ECWRasterBand()                            */
 /************************************************************************/
 
-ECWRasterBand::ECWRasterBand( ECWDataset *poDS, int nBand, int iOverview,
+ECWRasterBand::ECWRasterBand( ECWDataset *poDSIn, int nBandIn, int iOverviewIn,
                               char** papszOpenOptions )
 
 {
-    this->poDS = poDS;
-    poGDS = poDS;
+    this->poDS = poDSIn;
+    poGDS = poDSIn;
 
-    this->iOverview = iOverview;
-    this->nBand = nBand;
-    eDataType = poDS->eRasterDataType;
+    this->iOverview = iOverviewIn;
+    this->nBand = nBandIn;
+    eDataType = poDSIn->eRasterDataType;
 
     nRasterXSize = poDS->GetRasterXSize() / ( 1 << (iOverview+1));
     nRasterYSize = poDS->GetRasterYSize() / ( 1 << (iOverview+1));
@@ -98,20 +99,20 @@ ECWRasterBand::ECWRasterBand( ECWDataset *poDS, int nBand, int iOverview,
 /* -------------------------------------------------------------------- */
 /*      Work out band color interpretation.                             */
 /* -------------------------------------------------------------------- */
-    if( poDS->psFileInfo->eColorSpace == NCSCS_NONE )
+    if( poDSIn->psFileInfo->eColorSpace == NCSCS_NONE )
         eBandInterp = GCI_Undefined;
-    else if( poDS->psFileInfo->eColorSpace == NCSCS_GREYSCALE )
+    else if( poDSIn->psFileInfo->eColorSpace == NCSCS_GREYSCALE )
     {
         eBandInterp = GCI_GrayIndex;
-        //we could also have alpha band. 
-        if ( strcmp(poDS->psFileInfo->pBands[nBand-1].szDesc, NCS_BANDDESC_AllOpacity) == 0 ||
-             strcmp(poDS->psFileInfo->pBands[nBand-1].szDesc, NCS_BANDDESC_GreyscaleOpacity) ==0 ){
+        //we could also have alpha band.
+        if ( strcmp(poDSIn->psFileInfo->pBands[nBand-1].szDesc, NCS_BANDDESC_AllOpacity) == 0 ||
+             strcmp(poDSIn->psFileInfo->pBands[nBand-1].szDesc, NCS_BANDDESC_GreyscaleOpacity) ==0 ){
             eBandInterp = GCI_AlphaBand;
         }
-    }else if (poDS->psFileInfo->eColorSpace == NCSCS_MULTIBAND ){
-        eBandInterp = ECWGetColorInterpretationByName(poDS->psFileInfo->pBands[nBand-1].szDesc);
-    }else if (poDS->psFileInfo->eColorSpace == NCSCS_sRGB){
-        eBandInterp = ECWGetColorInterpretationByName(poDS->psFileInfo->pBands[nBand-1].szDesc);
+    }else if (poDSIn->psFileInfo->eColorSpace == NCSCS_MULTIBAND ){
+        eBandInterp = ECWGetColorInterpretationByName(poDSIn->psFileInfo->pBands[nBand-1].szDesc);
+    }else if (poDSIn->psFileInfo->eColorSpace == NCSCS_sRGB){
+        eBandInterp = ECWGetColorInterpretationByName(poDSIn->psFileInfo->pBands[nBand-1].szDesc);
         if( eBandInterp == GCI_Undefined )
         {
             if( nBand == 1 )
@@ -122,7 +123,7 @@ ECWRasterBand::ECWRasterBand( ECWDataset *poDS, int nBand, int iOverview,
                 eBandInterp = GCI_BlueBand;
             else if (nBand == 4 )
             {
-                if (strcmp(poDS->psFileInfo->pBands[nBand-1].szDesc, NCS_BANDDESC_AllOpacity) == 0)
+                if (strcmp(poDSIn->psFileInfo->pBands[nBand-1].szDesc, NCS_BANDDESC_AllOpacity) == 0)
                     eBandInterp = GCI_AlphaBand;
                 else
                     eBandInterp = GCI_Undefined;
@@ -133,9 +134,9 @@ ECWRasterBand::ECWRasterBand( ECWDataset *poDS, int nBand, int iOverview,
             }
         }
     }
-    else if( poDS->psFileInfo->eColorSpace == NCSCS_YCbCr )
+    else if( poDSIn->psFileInfo->eColorSpace == NCSCS_YCbCr )
     {
-        if( CSLTestBoolean( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB","YES") ))
+        if( CPLTestBool( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB","YES") ))
         {
             if( nBand == 1 )
                 eBandInterp = GCI_RedBand;
@@ -167,33 +168,33 @@ ECWRasterBand::ECWRasterBand( ECWDataset *poDS, int nBand, int iOverview,
     if( iOverview == -1 )
     {
         int i;
-        for( i = 0; 
-             nRasterXSize / (1 << (i+1)) > 128 
+        for( i = 0;
+             nRasterXSize / (1 << (i+1)) > 128
                  && nRasterYSize / (1 << (i+1)) > 128;
              i++ )
         {
-            apoOverviews.push_back( new ECWRasterBand( poDS, nBand, i, papszOpenOptions ) );
+            apoOverviews.push_back( new ECWRasterBand( poDSIn, nBandIn, i, papszOpenOptions ) );
         }
     }
 
-    bPromoteTo8Bit = 
-        poDS->psFileInfo->nBands == 4 && nBand == 4 &&
-        poDS->psFileInfo->pBands[0].nBits == 8 &&
-        poDS->psFileInfo->pBands[1].nBits == 8 &&
-        poDS->psFileInfo->pBands[2].nBits == 8 &&
-        poDS->psFileInfo->pBands[3].nBits == 1 &&
-        eBandInterp == GCI_AlphaBand && 
+    bPromoteTo8Bit =
+        poDSIn->psFileInfo->nBands == 4 && nBand == 4 &&
+        poDSIn->psFileInfo->pBands[0].nBits == 8 &&
+        poDSIn->psFileInfo->pBands[1].nBits == 8 &&
+        poDSIn->psFileInfo->pBands[2].nBits == 8 &&
+        poDSIn->psFileInfo->pBands[3].nBits == 1 &&
+        eBandInterp == GCI_AlphaBand &&
         CSLFetchBoolean(papszOpenOptions, "1BIT_ALPHA_PROMOTION",
-            CSLTestBoolean(CPLGetConfigOption("GDAL_ECW_PROMOTE_1BIT_ALPHA_AS_8BIT", "YES")));
+            CPLTestBool(CPLGetConfigOption("GDAL_ECW_PROMOTE_1BIT_ALPHA_AS_8BIT", "YES")));
     if( bPromoteTo8Bit )
         CPLDebug("ECW", "Fourth (alpha) band is promoted from 1 bit to 8 bit");
 
-    if( (poDS->psFileInfo->pBands[nBand-1].nBits % 8) != 0 && !bPromoteTo8Bit )
+    if( (poDSIn->psFileInfo->pBands[nBand-1].nBits % 8) != 0 && !bPromoteTo8Bit )
         SetMetadataItem("NBITS",
-                        CPLString().Printf("%d",poDS->psFileInfo->pBands[nBand-1].nBits),
+                        CPLString().Printf("%d",poDSIn->psFileInfo->pBands[nBand-1].nBits),
                         "IMAGE_STRUCTURE" );
 
-    SetDescription(poDS->psFileInfo->pBands[nBand-1].szDesc);
+    SetDescription(poDSIn->psFileInfo->pBands[nBand-1].szDesc);
 }
 
 /************************************************************************/
@@ -216,11 +217,11 @@ ECWRasterBand::~ECWRasterBand()
 /*                            GetOverview()                             */
 /************************************************************************/
 
-GDALRasterBand *ECWRasterBand::GetOverview( int iOverview )
+GDALRasterBand *ECWRasterBand::GetOverview( int iOverviewIn )
 
 {
-    if( iOverview >= 0 && iOverview < (int) apoOverviews.size() )
-        return apoOverviews[iOverview];
+    if( iOverviewIn >= 0 && iOverviewIn < (int) apoOverviews.size() )
+        return apoOverviews[iOverviewIn];
     else
         return NULL;
 }
@@ -257,21 +258,21 @@ CPLErr ECWRasterBand::SetColorInterpretation( GDALColorInterp eNewInterp )
 /************************************************************************/
 
 CPLErr ECWRasterBand::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
-                                  int nBufXSize, int nBufYSize, 
-                                  GDALDataType eDT, 
+                                  int nBufXSize, int nBufYSize,
+                                  GDALDataType eDT,
                                   char **papszOptions )
 {
     int nResFactor = 1 << (iOverview+1);
-    
-    return poGDS->AdviseRead( nXOff * nResFactor, 
-                              nYOff * nResFactor, 
-                              nXSize * nResFactor, 
-                              nYSize * nResFactor, 
-                              nBufXSize, nBufYSize, eDT, 
+
+    return poGDS->AdviseRead( nXOff * nResFactor,
+                              nYOff * nResFactor,
+                              nXSize * nResFactor,
+                              nYSize * nResFactor,
+                              nBufXSize, nBufYSize, eDT,
                               1, &nBand, papszOptions );
 }
 
-//statistics support: 
+//statistics support:
 #if ECWSDK_VERSION >= 50
 
 /************************************************************************/
@@ -285,11 +286,11 @@ CPLErr ECWRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
 {
     int bForceCoalesced = bForce;
     // If file version is smaller than 3, there will be no statistics in the file. But if it is version 3 or higher we don't want underlying implementation to compute histogram
-    // so we set bForceCoalesced to FALSE. 
+    // so we set bForceCoalesced to FALSE.
     if (poGDS->psFileInfo->nFormatVersion >= 3){
         bForceCoalesced = FALSE;
     }
-    // We check if we have PAM histogram. If we have them we return them. This will allow to override statistics stored in the file. 
+    // We check if we have PAM histogram. If we have them we return them. This will allow to override statistics stored in the file.
     CPLErr pamError =  GDALPamRasterBand::GetDefaultHistogram(pdfMin, pdfMax, pnBuckets, ppanHistogram, bForceCoalesced, f, pProgressData);
     if ( pamError == CE_None || poGDS->psFileInfo->nFormatVersion<3 || eBandInterp == GCI_AlphaBand){
         return pamError;
@@ -311,8 +312,8 @@ CPLErr ECWRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
             for (size_t i = 0; i < bandStats.nHistBucketCount; i++){
                 (*ppanHistogram)[i] = (GUIntBig) bandStats.Histogram[i];
             }
-            //JTO: this is not perfect as You can't tell who wrote the histogram !!! 
-            //It will offset it unnecesarilly for files with hists not modified by GDAL. 
+            //JTO: this is not perfect as You can't tell who wrote the histogram !!!
+            //It will offset it unnecessarily for files with hists not modified by GDAL.
             double dfHalfBucket = (bandStats.fMaxHist -  bandStats.fMinHist) / (2 * (*pnBuckets - 1));
             if ( pdfMin != NULL ){
                 *pdfMin = bandStats.fMinHist - dfHalfBucket;
@@ -333,23 +334,23 @@ CPLErr ECWRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
             //compute. Save.
             pamError = GDALPamRasterBand::GetDefaultHistogram(pdfMin, pdfMax, pnBuckets, ppanHistogram, TRUE, f,pProgressData);
             if (pamError == CE_None){
-                CPLErr error = SetDefaultHistogram(*pdfMin, *pdfMax, *pnBuckets, *ppanHistogram);
-                if (error != CE_None){
-                    //Histogram is there but we failed to save it back to file. 
+                CPLErr error2 = SetDefaultHistogram(*pdfMin, *pdfMax, *pnBuckets, *ppanHistogram);
+                if (error2 != CE_None){
+                    //Histogram is there but we failed to save it back to file.
                     CPLError (CE_Warning, CPLE_AppDefined,
                         "SetDefaultHistogram failed in ECWRasterBand::GetDefaultHistogram. Histogram might not be saved in .ecw file." );
                 }
                 return CE_None;
             }else{
-                //Something went wrong during histogram computation. 
+                //Something went wrong during histogram computation.
                 return pamError;
             }
         }else{
-            //No histogram, no forced computation. 
+            //No histogram, no forced computation.
             return CE_Warning;
         }
     }else {
-        //Statistics were already there and were used. 
+        //Statistics were already there and were used.
         return CE_None;
     }
 }
@@ -361,12 +362,12 @@ CPLErr ECWRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
 CPLErr ECWRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
                                            int nBuckets, GUIntBig *panHistogram )
 {
-    //Only version 3 supports saving statistics. 
+    //Only version 3 supports saving statistics.
     if (poGDS->psFileInfo->nFormatVersion < 3 || eBandInterp == GCI_AlphaBand){
         return GDALPamRasterBand::SetDefaultHistogram(dfMin, dfMax, nBuckets, panHistogram);
     }
-    
-    //determine if there are statistics in PAM file. 
+
+    //determine if there are statistics in PAM file.
     double dummy;
     int dummy_i;
     GUIntBig *dummy_histogram;
@@ -387,7 +388,7 @@ CPLErr ECWRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
             "ECWRDataset::StatisticsEnsureInitialized failed in ECWRasterBand::SetDefaultHistogram. Default histogram will be written to PAM. " );
         return GDALPamRasterBand::SetDefaultHistogram(dfMin, dfMax, nBuckets, panHistogram);
     }
-    
+
     NCSFileStatistics *pStatistics = poGDS->pStatistics;
 
     if (pStatistics == NULL){
@@ -399,12 +400,12 @@ CPLErr ECWRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
                         "NCSEcwInitStatistics failed in ECWRasterBand::SetDefaultHistogram." );
             return GDALPamRasterBand::SetDefaultHistogram(dfMin, dfMax, nBuckets, panHistogram);
         }
-        //no error statistics properly initialized but there were no statistics previously. 
+        //no error statistics properly initialized but there were no statistics previously.
     }else{
-        //is there a room for our band already? 
-        //This should account for following cases: 
-        //1. Existing histogram (for this or different band) has smaller bucket count. 
-        //2. There is no existing histogram but statistics are set for one or more bands (pStatistics->nHistBucketCounts is zero). 
+        //is there a room for our band already?
+        //This should account for following cases:
+        //1. Existing histogram (for this or different band) has smaller bucket count.
+        //2. There is no existing histogram but statistics are set for one or more bands (pStatistics->nHistBucketCounts is zero).
         if ((int)pStatistics->BandsStats[nStatsBandIndex].nHistBucketCount != nBuckets){
             //no. There is no room. We need more!
             NCSFileStatistics *pNewStatistics = NULL;
@@ -418,7 +419,8 @@ CPLErr ECWRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
             error = NCSEcwInitStatistics(&pNewStatistics, nStatsBandCount, bucketCounts);
             if (!error.Success()){
                 CPLError( CE_Warning, CPLE_AppDefined,
-                            "NCSEcwInitStatistics failed in ECWRasterBand::SetDefaultHistogram (realocate)." );
+                          "NCSEcwInitStatistics failed in "
+                          "ECWRasterBand::SetDefaultHistogram (reallocate)." );
                 return GDALPamRasterBand::SetDefaultHistogram(dfMin, dfMax, nBuckets, panHistogram);
             }
             //we need to copy existing statistics.
@@ -444,7 +446,7 @@ CPLErr ECWRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
     for (int i=0;i<nBuckets;i++){
         pStatistics->BandsStats[nStatsBandIndex].Histogram[i] = (UINT64)panHistogram[i];
     }
-    
+
     if (hasPAMDefaultHistogram){
         CPLError( CE_Debug, CPLE_AppDefined,
                     "PAM default histogram will be overwritten." );
@@ -467,7 +469,6 @@ void ECWRasterBand::GetBandIndexAndCountForStatistics(int &bandIndex, int &bandC
                 bandIndex--;
             }
         }
-        
     }
 }
 
@@ -529,16 +530,16 @@ double ECWRasterBand::GetMaximum(int* pbSuccess)
 /************************************************************************/
 
 CPLErr ECWRasterBand::GetStatistics( int bApproxOK, int bForce,
-                                  double *pdfMin, double *pdfMax, 
+                                  double *pdfMin, double *pdfMax,
                                   double *pdfMean, double *padfStdDev )
 {
     int bForceCoalesced = bForce;
     // If file version is smaller than 3, there will be no statistics in the file. But if it is version 3 or higher we don't want underlying implementation to compute histogram
-    // so we set bForceCoalesced to FALSE. 
+    // so we set bForceCoalesced to FALSE.
     if (poGDS->psFileInfo->nFormatVersion >= 3){
         bForceCoalesced = FALSE;
     }
-    // We check if we have PAM histogram. If we have them we return them. This will allow to override statistics stored in the file. 
+    // We check if we have PAM histogram. If we have them we return them. This will allow to override statistics stored in the file.
     CPLErr pamError =  GDALPamRasterBand::GetStatistics(bApproxOK, bForceCoalesced, pdfMin, pdfMax, pdfMean, padfStdDev);
     if ( pamError == CE_None || poGDS->psFileInfo->nFormatVersion<3 || eBandInterp == GCI_AlphaBand){
         return pamError;
@@ -579,13 +580,13 @@ CPLErr ECWRasterBand::GetStatistics( int bApproxOK, int bForce,
         }
         if (bStatisticsFromFile) return CE_None;
     }
-    //no required statistics. 
+    //no required statistics.
     if (!bStatisticsFromFile && bForce == TRUE){
         double dfMin, dfMax, dfMean,dfStdDev;
-        pamError = GDALPamRasterBand::GetStatistics(bApproxOK, TRUE, 
+        pamError = GDALPamRasterBand::GetStatistics(bApproxOK, TRUE,
             &dfMin,
             &dfMax,
-            &dfMean, 
+            &dfMean,
             &dfStdDev);
         if (pdfMin!=NULL) {
             *pdfMin = dfMin;
@@ -607,11 +608,11 @@ CPLErr ECWRasterBand::GetStatistics( int bApproxOK, int bForce,
             }
             return CE_None;
         }else{
-            //whatever happened we return. 
+            //whatever happened we return.
             return pamError;
         }
     }else{
-        //no statistics and we are not forced to return. 
+        //no statistics and we are not forced to return.
         return CE_Warning;
     }
 }
@@ -620,14 +621,14 @@ CPLErr ECWRasterBand::GetStatistics( int bApproxOK, int bForce,
 /*                          SetStatistics()                             */
 /************************************************************************/
 
-CPLErr ECWRasterBand::SetStatistics( double dfMin, double dfMax, 
+CPLErr ECWRasterBand::SetStatistics( double dfMin, double dfMax,
                                   double dfMean, double dfStdDev ){
     if (poGDS->psFileInfo->nFormatVersion < 3 || eBandInterp == GCI_AlphaBand){
         return GDALPamRasterBand::SetStatistics(dfMin, dfMax, dfMean, dfStdDev);
     }
     double dummy;
     bool hasPAMStatistics = GDALPamRasterBand::GetStatistics(TRUE, FALSE, &dummy, &dummy, &dummy, &dummy) == CE_None;
-    
+
     NCS::CError error = poGDS->StatisticsEnsureInitialized();
     if (!error.Success()){
             CPLError( CE_Warning, CPLE_AppDefined,
@@ -643,20 +644,20 @@ CPLErr ECWRasterBand::SetStatistics( double dfMin, double dfMax,
             return GDALPamRasterBand::SetStatistics(dfMin, dfMax, dfMean, dfStdDev);
         }
     }
-    
+
     poGDS->pStatistics->BandsStats[nStatsBandIndex].fMinVal = (IEEE4) dfMin;
     poGDS->pStatistics->BandsStats[nStatsBandIndex].fMaxVal = (IEEE4)dfMax;
     poGDS->pStatistics->BandsStats[nStatsBandIndex].fMeanVal = (IEEE4)dfMean;
     poGDS->pStatistics->BandsStats[nStatsBandIndex].fStandardDev = (IEEE4)dfStdDev;
     poGDS->bStatisticsDirty = TRUE;
-    //if we have PAM statistics we need to save them as well. Better option would be to remove them from PAM file but I don't know how to do that without messing in PAM internals. 
+    //if we have PAM statistics we need to save them as well. Better option would be to remove them from PAM file but I don't know how to do that without messing in PAM internals.
     if ( hasPAMStatistics ){
         CPLError( CE_Debug, CPLE_AppDefined,
                         "PAM statistics will be overwritten." );
         return  GDALPamRasterBand::SetStatistics(dfMin, dfMax, dfMean, dfStdDev);
     }
+
     return CE_None;
-    
 }
 #endif
 
@@ -676,7 +677,7 @@ CPLErr ECWRasterBand::OldIRasterIO( GDALRWFlag eRWFlag,
                                  GDALDataType eBufType,
                                  GSpacing nPixelSpace, GSpacing nLineSpace,
                                  GDALRasterIOExtraArg* psExtraArg )
-    
+
 {
     int          iBand, bDirect;
     GByte        *pabyWorkBuffer = NULL;
@@ -690,11 +691,11 @@ CPLErr ECWRasterBand::OldIRasterIO( GDALRWFlag eRWFlag,
 /* -------------------------------------------------------------------- */
 /*      Try to do it based on existing "advised" access.                */
 /* -------------------------------------------------------------------- */
-    int nRet = poGDS->TryWinRasterIO( eRWFlag, 
-                               nXOff, nYOff, 
-                               nXSize, nYSize, 
-                               (GByte *) pData, nBufXSize, nBufYSize, 
-                               eBufType, 1, &nBand, 
+    int nRet = poGDS->TryWinRasterIO( eRWFlag,
+                               nXOff, nYOff,
+                               nXSize, nYSize,
+                               (GByte *) pData, nBufXSize, nBufYSize,
+                               eBufType, 1, &nBand,
                                nPixelSpace, nLineSpace, 0 , psExtraArg);
     if( nRet == TRUE )
         return CE_None;
@@ -768,7 +769,7 @@ CPLErr ECWRasterBand::OldIRasterIO( GDALRWFlag eRWFlag,
 
         if ( nNewYSize == nBufYSize || iSrcLine == (int)(iDstLine * dfSrcYInc) )
         {
-            eRStatus = poGDS->poFileView->ReadLineBIL( 
+            eRStatus = poGDS->poFileView->ReadLineBIL(
                 poGDS->eNCSRequestDataType, 1, (void **) &pabySrcBuf );
 
             if( eRStatus != NCSECW_READ_OK )
@@ -792,9 +793,9 @@ CPLErr ECWRasterBand::OldIRasterIO( GDALRWFlag eRWFlag,
             {
                 if ( nNewXSize == nBufXSize )
                 {
-                    GDALCopyWords( pabyWorkBuffer, poGDS->eRasterDataType, 
-                                nRawPixelSize, 
-                                ((GByte *)pData) + iDstLine * nLineSpace, 
+                    GDALCopyWords( pabyWorkBuffer, poGDS->eRasterDataType,
+                                nRawPixelSize,
+                                ((GByte *)pData) + iDstLine * nLineSpace,
                                 eBufType, (int)nPixelSpace, nBufXSize );
                 }
                 else
@@ -803,7 +804,7 @@ CPLErr ECWRasterBand::OldIRasterIO( GDALRWFlag eRWFlag,
 
                     for ( iPixel = 0; iPixel < nBufXSize; iPixel++ )
                     {
-                        GDALCopyWords( pabyWorkBuffer 
+                        GDALCopyWords( pabyWorkBuffer
                                     + nRawPixelSize*((int)(iPixel*dfSrcXInc)),
                                     poGDS->eRasterDataType, nRawPixelSize,
                                     (GByte *)pData + iDstLineOff
@@ -862,8 +863,8 @@ CPLErr ECWRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     if ( nLineSpace == 0 )
         nLineSpace = nPixelSpace * nBufXSize;
 
-    CPLDebug( "ECWRasterBand", 
-            "RasterIO(nBand=%d,iOverview=%d,nXOff=%d,nYOff=%d,nXSize=%d,nYSize=%d -> %dx%d)", 
+    CPLDebug( "ECWRasterBand",
+            "RasterIO(nBand=%d,iOverview=%d,nXOff=%d,nYOff=%d,nXSize=%d,nYSize=%d -> %dx%d)",
             nBand, iOverview, nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize );
 
 #if !defined(SDK_CAN_DO_SUPERSAMPLING)
@@ -929,10 +930,10 @@ CPLErr ECWRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage
 /*                            ECWDataset()                              */
 /************************************************************************/
 
-ECWDataset::ECWDataset(int bIsJPEG2000)
+ECWDataset::ECWDataset(int bIsJPEG2000In)
 
 {
-    this->bIsJPEG2000 = bIsJPEG2000;
+    this->bIsJPEG2000 = bIsJPEG2000In;
     bUsingCustomStream = FALSE;
     poFileView = NULL;
     bWinActive = FALSE;
@@ -946,7 +947,7 @@ ECWDataset::ECWDataset(int bIsJPEG2000)
     bProjCodeChanged = FALSE;
     bDatumCodeChanged = FALSE;
     bUnitsCodeChanged = FALSE;
-    
+
     bUseOldBandRasterIOImplementation = FALSE;
 #if ECWSDK_VERSION>=50
 
@@ -955,8 +956,8 @@ ECWDataset::ECWDataset(int bIsJPEG2000)
     bStatisticsInitialized = FALSE;
     bFileMetaDataDirty = FALSE;
 
-#endif 
-    
+#endif
+
     sCachedMultiBandIO.bEnabled = FALSE;
     sCachedMultiBandIO.nBandsTried = 0;
     sCachedMultiBandIO.nXOff = 0;
@@ -967,12 +968,24 @@ ECWDataset::ECWDataset(int bIsJPEG2000)
     sCachedMultiBandIO.nBufYSize = 0;
     sCachedMultiBandIO.eBufType = GDT_Unknown;
     sCachedMultiBandIO.pabyData = NULL;
-    
+
     bPreventCopyingSomeMetadata = FALSE;
 
     nBandIndexToPromoteTo8Bit = -1;
-    
+
     poDriver = (GDALDriver*) GDALGetDriverByName( bIsJPEG2000 ? "JP2ECW" : "ECW" );
+
+    psFileInfo =  NULL;
+    eNCSRequestDataType = NCSCT_UINT8;
+    nWinXOff = 0;
+    nWinYOff = 0;
+    nWinXSize = 0;
+    nWinYSize = 0;
+    nWinBufXSize = 0;
+    nWinBufYSize = 0;
+    nWinBandCount = 0;
+    nWinBufLoaded = FALSE;
+    papCurLineBuf = NULL;
 }
 
 /************************************************************************/
@@ -996,11 +1009,11 @@ ECWDataset::~ECWDataset()
 /* -------------------------------------------------------------------- */
 /*      Release / dereference iostream.                                 */
 /* -------------------------------------------------------------------- */
-    // The underlying iostream of the CNCSJP2FileView (poFileView) object may 
-    // also be the underlying iostream of other CNCSJP2FileView (poFileView) 
-    // objects.  Consequently, when we delete the CNCSJP2FileView (poFileView) 
+    // The underlying iostream of the CNCSJP2FileView (poFileView) object may
+    // also be the underlying iostream of other CNCSJP2FileView (poFileView)
+    // objects.  Consequently, when we delete the CNCSJP2FileView (poFileView)
     // object, we must decrement the nFileViewCount attribute of the underlying
-    // VSIIOStream object, and only delete the VSIIOStream object when 
+    // VSIIOStream object, and only delete the VSIIOStream object when
     // nFileViewCount is equal to zero.
 
     CPLMutexHolder oHolder( &hECWDatasetMutex );
@@ -1029,14 +1042,18 @@ ECWDataset::~ECWDataset()
         #13 0x00007fffb7551c61 in GDALDestroy () at gdaldllmain.cpp:80
         #14 0x00007ffff7de990e in _dl_fini () at dl-fini.c:254
     */
-    // Not replicable with similar test in C++, but this might be just a matter of luck related
-    // to the order in which the libraries are unloaded, so just don't try
-    // to delete poFileView from the GDAL destructor.
+    // Not reproducible with similar test in C++, but this might be
+    // just a matter of luck related to the order in which the
+    // libraries are unloaded, so just don't try to delete poFileView
+    // from the GDAL destructor.
     if( poFileView != NULL && !GDALIsInGlobalDestructor() )
     {
         VSIIOStream *poUnderlyingIOStream = (VSIIOStream *)NULL;
 
-        poUnderlyingIOStream = ((VSIIOStream *)(poFileView->GetStream()));
+        if( bUsingCustomStream )
+        {
+            poUnderlyingIOStream = ((VSIIOStream *)(poFileView->GetStream()));
+        }
         delete poFileView;
 
         if( bUsingCustomStream )
@@ -1061,7 +1078,7 @@ ECWDataset::~ECWDataset()
         WriteFileMetaData(pFileMetaDataCopy);
         NCSFreeMetaData(pFileMetaDataCopy);
     }
-#endif 
+#endif
 
     CSLDestroy( papszGMLMetadata );
 
@@ -1078,7 +1095,7 @@ NCS::CError ECWDataset::StatisticsEnsureInitialized(){
     if (bStatisticsInitialized == TRUE){
         return NCS_SUCCESS;
     }
-    
+
     NCS::CError error = poFileView->GetClientStatistics(&pStatistics);
     if (error.Success()){
         bStatisticsInitialized = TRUE;
@@ -1103,12 +1120,12 @@ NCS::CError ECWDataset::StatisticsWrite()
                 error = NCSEcwEditClose(view);
             }
         }
-    }	
-    
+    }
+
     bStatisticsDirty = FALSE;
-    
+
     return error;
-    
+
 }
 
 /************************************************************************/
@@ -1201,7 +1218,7 @@ CPLErr ECWDataset::SetMetadataItem( const char * pszName,
             m_osDatumCode = osNewVal;
             bHdrDirty |= bDatumCodeChanged;
         }
-        else 
+        else
         {
             bUnitsCodeChanged |= (osNewVal != m_osUnitsCode)?TRUE:FALSE;
             m_osUnitsCode = osNewVal;
@@ -1215,7 +1232,7 @@ CPLErr ECWDataset::SetMetadataItem( const char * pszName,
               eAccess == GA_Update &&
               (pszDomain == NULL || EQUAL(pszDomain, "")) &&
               pszName != NULL &&
-              strncmp(pszName, "FILE_METADATA_", strlen("FILE_METADATA_")) == 0 )
+              STARTS_WITH(pszName, "FILE_METADATA_") )
     {
         bFileMetaDataDirty = TRUE;
 
@@ -1318,7 +1335,7 @@ CPLErr ECWDataset::SetMetadata( char ** papszMetadata,
                     EQUAL(pszKey, "CLOCKWISE_ROTATION_DEG") ||
                     EQUAL(pszKey, "COLORSPACE") ||
                     EQUAL(pszKey, "COMPRESSION_DATE") ||
-                    EQUALN(pszKey, "FILE_METADATA_", strlen("FILE_METADATA_")) ) )
+                    STARTS_WITH_CI(pszKey, "FILE_METADATA_") ) )
             {
                 /* do nothing */
             }
@@ -1355,7 +1372,7 @@ CPLErr ECWDataset::SetMetadata( char ** papszMetadata,
             CSLFetchNameValue(papszMetadata, "FILE_METADATA_COMPANY") != NULL ||
             CSLFetchNameValue(papszMetadata, "FILE_METADATA_EMAIL") != NULL ||
             CSLFetchNameValue(papszMetadata, "FILE_METADATA_ADDRESS") != NULL ||
-            CSLFetchNameValue(papszMetadata, "FILE_METADATA_TELEPHONE") != NULL)) 
+            CSLFetchNameValue(papszMetadata, "FILE_METADATA_TELEPHONE") != NULL))
 #endif
         )
     {
@@ -1363,10 +1380,10 @@ CPLErr ECWDataset::SetMetadata( char ** papszMetadata,
         char** papszIter = papszMetadata;
         while(*papszIter)
         {
-            if (strncmp(*papszIter, "PROJ=", 5) == 0 ||
-                strncmp(*papszIter, "DATUM=", 6) == 0 ||
-                strncmp(*papszIter, "UNITS=", 6) == 0 ||
-                (strncmp(*papszIter, "FILE_METADATA_", strlen("FILE_METADATA_")) == 0 && strchr(*papszIter, '=') != NULL) )
+            if (STARTS_WITH(*papszIter, "PROJ=") ||
+                STARTS_WITH(*papszIter, "DATUM=") ||
+                STARTS_WITH(*papszIter, "UNITS=") ||
+                (STARTS_WITH(*papszIter, "FILE_METADATA_") && strchr(*papszIter, '=') != NULL) )
             {
                 char* pszKey = NULL;
                 const char* pszValue = CPLParseNameValue(*papszIter, &pszKey );
@@ -1406,7 +1423,7 @@ void ECWDataset::WriteHeader()
     /* Load original header info */
 #if ECWSDK_VERSION<50
     eErr = NCSEcwEditReadInfo((char*) GetDescription(), &psEditInfo);
-#else 
+#else
     eErr = NCSEcwEditReadInfo(  NCS::CString::Utf8Decode(GetDescription()).c_str(), &psEditInfo);
 #endif
     if (eErr != NCS_SUCCESS)
@@ -1515,11 +1532,11 @@ CPLErr ECWDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
     int bStopProcessing = FALSE;
     eErr = ValidateRasterIOOrAdviseReadParameters( "AdviseRead()", &bStopProcessing,
                                                     nXOff, nYOff, nXSize, nYSize,
-                                                    nBufXSize, nBufYSize, 
+                                                    nBufXSize, nBufYSize,
                                                     nBandCount, panBandList);
     if( eErr != CE_None || bStopProcessing )
         return eErr;
-    
+
     if( nBandCount > 100 )
     {
         ReportError( CE_Failure, CPLE_IllegalArg,
@@ -1530,7 +1547,7 @@ CPLErr ECWDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
 /* -------------------------------------------------------------------- */
 /*      Adjust band numbers to be zero based.                           */
 /* -------------------------------------------------------------------- */
-    panAdjustedBandList = (int *) 
+    panAdjustedBandList = (int *)
         CPLMalloc(sizeof(int) * nBandCount );
     nBandIndexToPromoteTo8Bit = -1;
     for( int ii= 0; ii < nBandCount; ii++ )
@@ -1548,10 +1565,8 @@ CPLErr ECWDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
 /* -------------------------------------------------------------------- */
 /*      Set the new requested window.                                   */
 /* -------------------------------------------------------------------- */
-    CNCSError oErr;
-    
-    oErr = poFileView->SetView( nBandCount, (UINT32 *) panAdjustedBandList, 
-                                nXOff, nYOff, 
+    CNCSError oErr = poFileView->SetView( nBandCount, (UINT32 *) panAdjustedBandList,
+                                nXOff, nYOff,
                                 nXOff + nXSize-1, nYOff + nYSize-1,
                                 nBufXSize, nBufYSize );
 
@@ -1595,9 +1610,9 @@ CPLErr ECWDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
 /* -------------------------------------------------------------------- */
     papCurLineBuf = (void **) CPLMalloc(sizeof(void*) * nWinBandCount );
     for( int iBand = 0; iBand < nWinBandCount; iBand++ )
-        papCurLineBuf[iBand] = 
+        papCurLineBuf[iBand] =
             CPLMalloc(nBufXSize * (GDALGetDataTypeSize(eRasterDataType)/8) );
-        
+
     return CE_None;
 }
 
@@ -1636,13 +1651,13 @@ int ECWDataset::TryWinRasterIO( CPL_UNUSED GDALRWFlag eFlag,
 /*      satisfy our requirement.                                        */
 /* -------------------------------------------------------------------- */
 #ifdef NOISY_DEBUG
-    CPLDebug( "ECW", "TryWinRasterIO(%d,%d,%d,%d,%d,%d)", 
+    CPLDebug( "ECW", "TryWinRasterIO(%d,%d,%d,%d,%d,%d)",
               nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize );
 #endif
 
     if( !bWinActive )
         return FALSE;
-    
+
     if( nXOff != nWinXOff || nXSize != nWinXSize )
         return FALSE;
 
@@ -1671,13 +1686,13 @@ int ECWDataset::TryWinRasterIO( CPL_UNUSED GDALRWFlag eFlag,
         static int nDebugCount = 0;
 
         if( nDebugCount < 30 )
-            CPLDebug( "ECW", 
-                      "TryWinRasterIO(%d,%d,%d,%d -> %dx%d) - doing advised read.", 
+            CPLDebug( "ECW",
+                      "TryWinRasterIO(%d,%d,%d,%d -> %dx%d) - doing advised read.",
                       nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize );
 
         if( nDebugCount == 29 )
             CPLDebug( "ECW", "No more TryWinRasterIO messages will be reported" );
-        
+
         nDebugCount++;
     }
 
@@ -1689,9 +1704,9 @@ int ECWDataset::TryWinRasterIO( CPL_UNUSED GDALRWFlag eFlag,
     for( iBufLine = 0; iBufLine < nBufYSize; iBufLine++ )
     {
         double fFileLine = ((iBufLine+0.5) / nBufYSize) * nYSize + nYOff;
-        int iWinLine = 
+        int iWinLine =
             (int) (((fFileLine - nWinYOff) / nWinYSize) * nWinBufYSize);
-        
+
         if( iWinLine == nWinBufLoaded + 1 )
             LoadNextLine();
 
@@ -1711,8 +1726,8 @@ int ECWDataset::TryWinRasterIO( CPL_UNUSED GDALRWFlag eFlag,
             }
 
             GDALCopyWords( papCurLineBuf[iWinBand], eRasterDataType,
-                           GDALGetDataTypeSize( eRasterDataType ) / 8, 
-                           pabyData + nBandSpace * iBand 
+                           GDALGetDataTypeSize( eRasterDataType ) / 8,
+                           pabyData + nBandSpace * iBand
                            + iBufLine * nLineSpace, eDT, (int)nPixelSpace,
                            nBufXSize );
         }
@@ -1745,7 +1760,7 @@ CPLErr ECWDataset::LoadNextLine()
     }
 
     NCSEcwReadStatus  eRStatus;
-    eRStatus = poFileView->ReadLineBIL( eNCSRequestDataType, 
+    eRStatus = poFileView->ReadLineBIL( eNCSRequestDataType,
                                         (UINT16) nWinBandCount,
                                         papCurLineBuf );
     if( eRStatus != NCSECW_READ_OK )
@@ -1791,12 +1806,12 @@ void ECWDataset::CleanupWindow()
 CPLErr ECWDataset::IRasterIO( GDALRWFlag eRWFlag,
                               int nXOff, int nYOff, int nXSize, int nYSize,
                               void * pData, int nBufXSize, int nBufYSize,
-                              GDALDataType eBufType, 
+                              GDALDataType eBufType,
                               int nBandCount, int *panBandMap,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
                               GSpacing nBandSpace,
                               GDALRasterIOExtraArg* psExtraArg)
-    
+
 {
     if( eRWFlag == GF_Write )
         return CE_Failure;
@@ -1805,35 +1820,32 @@ CPLErr ECWDataset::IRasterIO( GDALRWFlag eRWFlag,
         return CE_Failure;
 
     if( bUseOldBandRasterIOImplementation )
-        /* Sanity check. Shouldn't happen */
+        /* Sanity check. Should not happen */
         return CE_Failure;
     int nDataTypeSize = (GDALGetDataTypeSize(eRasterDataType) / 8);
 
     if ( nPixelSpace == 0 ){
         nPixelSpace = nDataTypeSize;
     }
-     
+
     if (nLineSpace == 0 ) {
         nLineSpace = nPixelSpace*nBufXSize;
     }
     if ( nBandSpace == 0 ){
-        nBandSpace = nDataTypeSize*nBufXSize*nBufYSize;
+        nBandSpace = static_cast<GSpacing>(nDataTypeSize)*nBufXSize*nBufYSize;
     }
-    
+
     // Use GDAL upsampling if non nearest
     if( (nBufXSize > nXSize || nBufYSize > nYSize) &&
         psExtraArg->eResampleAlg != GRIORA_NearestNeighbour )
     {
         int nBufDataTypeSize = (GDALGetDataTypeSize(eBufType) / 8);
-        GByte* pabyTemp = (GByte*)VSIMalloc3(nXSize, nYSize, nBufDataTypeSize * nBandCount);
+        GByte* pabyTemp = (GByte*)VSI_MALLOC3_VERBOSE(nXSize, nYSize, nBufDataTypeSize * nBandCount);
         if( pabyTemp == NULL )
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory, 
-                          "Failed to allocate %d byte intermediate decompression buffer for jpeg2000.", 
-                          nXSize * nYSize * nBufDataTypeSize * nBandCount );
             return CE_Failure;
         }
-        
+
         CPLErr eErr = IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
                                 pabyTemp, nXSize, nYSize,
                                 eBufType, nBandCount, panBandMap,
@@ -1841,7 +1853,7 @@ CPLErr ECWDataset::IRasterIO( GDALRWFlag eRWFlag,
                                 (GIntBig)nBufDataTypeSize* nXSize,
                                 (GIntBig)nBufDataTypeSize*nXSize*nYSize,
                                 psExtraArg);
-        
+
         if( eErr == CE_None )
         {
             /* Create a MEM dataset that wraps the input buffer */
@@ -1874,21 +1886,21 @@ CPLErr ECWDataset::IRasterIO( GDALRWFlag eRWFlag,
             INIT_RASTERIO_EXTRA_ARG(sExtraArgTmp);
             sExtraArgTmp.eResampleAlg = psExtraArg->eResampleAlg;
 
-            poMEMDS->RasterIO(GF_Read, 0, 0, nXSize, nYSize,
+            CPL_IGNORE_RET_VAL(poMEMDS->RasterIO(GF_Read, 0, 0, nXSize, nYSize,
                                 pData, nBufXSize, nBufYSize,
                                 eBufType,
                                 nBandCount, NULL,
                                 nPixelSpace, nLineSpace, nBandSpace,
-                                &sExtraArgTmp);
+                                &sExtraArgTmp));
 
             GDALClose(poMEMDS);
         }
 
         VSIFree(pabyTemp);
-        
+
         return eErr;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      ECW SDK 3.3 has a bug with the ECW format when we query the     */
 /*      number of bands of the dataset, but not in the "natural order". */
@@ -1911,7 +1923,7 @@ CPLErr ECWDataset::IRasterIO( GDALRWFlag eRWFlag,
             return GDALDataset::IRasterIO(
                                     eRWFlag, nXOff, nYOff, nXSize, nYSize,
                                     pData, nBufXSize, nBufYSize,
-                                    eBufType, 
+                                    eBufType,
                                     nBandCount, panBandMap,
                                     nPixelSpace, nLineSpace, nBandSpace, psExtraArg);
         }
@@ -1937,13 +1949,13 @@ CPLErr ECWDataset::IRasterIO( GDALRWFlag eRWFlag,
             sCachedMultiBandIO.pabyData != NULL )
         {
             int j;
-            int nDataTypeSize = GDALGetDataTypeSize(eBufType) / 8;
+            int nBufTypeSize = GDALGetDataTypeSize(eBufType) / 8;
             for(j = 0; j < nBufYSize; j++)
             {
                 GDALCopyWords(sCachedMultiBandIO.pabyData +
-                                    (*panBandMap - 1) * nBufXSize * nBufYSize * nDataTypeSize +
-                                    j * nBufXSize * nDataTypeSize,
-                            eBufType, nDataTypeSize,
+                                    (*panBandMap - 1) * nBufXSize * nBufYSize * nBufTypeSize +
+                                    j * nBufXSize * nBufTypeSize,
+                            eBufType, nBufTypeSize,
                             ((GByte*)pData) + j * nLineSpace, eBufType, (int)nPixelSpace,
                             nBufXSize);
             }
@@ -1952,7 +1964,7 @@ CPLErr ECWDataset::IRasterIO( GDALRWFlag eRWFlag,
 
         if( !(sCachedMultiBandIO.bEnabled) &&
             sCachedMultiBandIO.nBandsTried == nBands &&
-            CSLTestBoolean(CPLGetConfigOption("ECW_CLEVER", "YES")) )
+            CPLTestBool(CPLGetConfigOption("ECW_CLEVER", "YES")) )
         {
             sCachedMultiBandIO.bEnabled = TRUE;
             CPLDebug("ECW", "Detecting successive band reading pattern (for next time)");
@@ -1962,8 +1974,8 @@ CPLErr ECWDataset::IRasterIO( GDALRWFlag eRWFlag,
 /* -------------------------------------------------------------------- */
 /*      Try to do it based on existing "advised" access.                */
 /* -------------------------------------------------------------------- */
-    int nRet = TryWinRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, 
-                        (GByte *) pData, nBufXSize, nBufYSize, 
+    int nRet = TryWinRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                        (GByte *) pData, nBufXSize, nBufYSize,
                         eBufType, nBandCount, panBandMap,
                         nPixelSpace, nLineSpace, nBandSpace, psExtraArg );
     if( nRet == TRUE )
@@ -1991,10 +2003,10 @@ CPLErr ECWDataset::IRasterIO( GDALRWFlag eRWFlag,
     else if( nXSize < nBufXSize || nYSize < nBufYSize )
     {
         bUseOldBandRasterIOImplementation = TRUE;
-        CPLErr eErr = 
+        CPLErr eErr =
             GDALDataset::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
                                     pData, nBufXSize, nBufYSize,
-                                    eBufType, 
+                                    eBufType,
                                     nBandCount, panBandMap,
                                     nPixelSpace, nLineSpace, nBandSpace, psExtraArg);
         bUseOldBandRasterIOImplementation = FALSE;
@@ -2004,25 +2016,27 @@ CPLErr ECWDataset::IRasterIO( GDALRWFlag eRWFlag,
 
     else if( nBufYSize == 1 )
     {
-        //JTO: this is tricky, because it expects the rest of the image with this bufer width to be 
-        //read. The prefered way to achieve this behaviour would be to call AdviseRead before call IRasterIO.
-        //ERO; indeed, the logic could be improved to detect successive pattern of single line reading
-        //before doing an AdviseRead.
+        // This is tricky, because it expects the rest of the image
+        // with this buffer width to be read. The preferred way to
+        // achieve this behaviour would be to call AdviseRead before
+        // call IRasterIO.  The logic could be improved to detect
+        // successive pattern of single line reading before doing an
+        // AdviseRead.
         CPLErr eErr;
 
         eErr = AdviseRead( nXOff, nYOff, nXSize, GetRasterYSize() - nYOff,
-                           nBufXSize, (nRasterYSize - nYOff) / nYSize, eBufType, 
+                           nBufXSize, (nRasterYSize - nYOff) / nYSize, eBufType,
                            nBandCount, panBandMap, NULL );
-        if( eErr == CE_None 
-            && TryWinRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, 
-                               (GByte *) pData, nBufXSize, nBufYSize, 
+        if( eErr == CE_None
+            && TryWinRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                               (GByte *) pData, nBufXSize, nBufYSize,
                                eBufType, nBandCount, panBandMap,
                                nPixelSpace, nLineSpace, nBandSpace, psExtraArg ) )
             return CE_None;
     }
 
-    CPLDebug( "ECW", 
-              "RasterIO(%d,%d,%d,%d -> %dx%d) - doing interleaved read.", 
+    CPLDebug( "ECW",
+              "RasterIO(%d,%d,%d,%d -> %dx%d) - doing interleaved read.",
               nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize );
 
 /* -------------------------------------------------------------------- */
@@ -2031,8 +2045,8 @@ CPLErr ECWDataset::IRasterIO( GDALRWFlag eRWFlag,
     UINT32 anBandIndices[100];
     int    i;
     NCSError     eNCSErr;
-    CNCSError    oErr;
-    
+    CNCSError    oErr(GetCNCSError(NCS_SUCCESS));
+
     for( i = 0; i < nBandCount; i++ )
         anBandIndices[i] = panBandMap[i] - 1;
 
@@ -2058,13 +2072,13 @@ CPLErr ECWDataset::IRasterIO( GDALRWFlag eRWFlag,
         sCachedMultiBandIO.eBufType = eBufType;
         sCachedMultiBandIO.nBandsTried = 1;
 
-        int nDataTypeSize = GDALGetDataTypeSize(eBufType) / 8;
+        int nBufTypeSize = GDALGetDataTypeSize(eBufType) / 8;
 
         if( sCachedMultiBandIO.bEnabled )
         {
             GByte* pNew = (GByte*)VSIRealloc(
                 sCachedMultiBandIO.pabyData,
-                    nBufXSize * nBufYSize * nBands * nDataTypeSize);
+                    nBufXSize * nBufYSize * nBands * nBufTypeSize);
             if( pNew == NULL )
                 CPLFree(sCachedMultiBandIO.pabyData);
             sCachedMultiBandIO.pabyData = pNew;
@@ -2082,15 +2096,15 @@ CPLErr ECWDataset::IRasterIO( GDALRWFlag eRWFlag,
             }
 
             oErr = poFileView->SetView( nBands, anBandIndices,
-                                        nXOff, nYOff, 
-                                        nXOff + nXSize - 1, 
+                                        nXOff, nYOff,
+                                        nXOff + nXSize - 1,
                                         nYOff + nYSize - 1,
                                         nBufXSize, nBufYSize );
             eNCSErr = oErr.GetErrorNumber();
 
             if( eNCSErr != NCS_SUCCESS )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                         "%s", NCSGetErrorText(eNCSErr) );
 
                 return CE_Failure;
@@ -2099,9 +2113,9 @@ CPLErr ECWDataset::IRasterIO( GDALRWFlag eRWFlag,
             CPLErr eErr = ReadBands(sCachedMultiBandIO.pabyData,
                                     nBufXSize, nBufYSize, eBufType,
                                     nBands,
-                                    nDataTypeSize,
-                                    nBufXSize * nDataTypeSize,
-                                    nBufXSize * nBufYSize * nDataTypeSize,
+                                    nBufTypeSize,
+                                    nBufXSize * nBufTypeSize,
+                                    nBufXSize * nBufYSize * nBufTypeSize,
                                     psExtraArg);
             if( eErr != CE_None )
                 return eErr;
@@ -2110,8 +2124,8 @@ CPLErr ECWDataset::IRasterIO( GDALRWFlag eRWFlag,
             for(j = 0; j < nBufYSize; j++)
             {
                 GDALCopyWords(sCachedMultiBandIO.pabyData +
-                                    j * nBufXSize * nDataTypeSize,
-                              eBufType, nDataTypeSize,
+                                    j * nBufXSize * nBufTypeSize,
+                              eBufType, nBufTypeSize,
                               ((GByte*)pData) + j * nLineSpace, eBufType, (int)nPixelSpace,
                               nBufXSize);
             }
@@ -2126,17 +2140,17 @@ CPLErr ECWDataset::IRasterIO( GDALRWFlag eRWFlag,
             nBandIndexToPromoteTo8Bit = i;
     }
     oErr = poFileView->SetView( nBandCount, anBandIndices,
-                                nXOff, nYOff, 
-                                nXOff + nXSize - 1, 
+                                nXOff, nYOff,
+                                nXOff + nXSize - 1,
                                 nYOff + nYSize - 1,
                                 nBufXSize, nBufYSize );
     eNCSErr = oErr.GetErrorNumber();
-    
+
     if( eNCSErr != NCS_SUCCESS )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", NCSGetErrorText(eNCSErr) );
-        
+
         return CE_Failure;
     }
 
@@ -2169,14 +2183,14 @@ CPLErr ECWDataset::ReadBandsDirectly(void * pData, int nBufXSize, int nBufYSize,
     }
 
     CPLErr eErr = CE_None;
-    for(int nR = 0; nR < nBufYSize; nR++) 
+    for(int nR = 0; nR < nBufYSize; nR++)
     {
         if (poFileView->ReadLineBIL(eNCSRequestDataType,(UINT16) nBandCount, (void**)pBIL) != NCSECW_READ_OK)
         {
             eErr = CE_Failure;
             break;
         }
-        for(int nB = 0; nB < nBandCount; nB++) 
+        for(int nB = 0; nB < nBandCount; nB++)
         {
             if( nB == nBandIndexToPromoteTo8Bit )
             {
@@ -2208,8 +2222,8 @@ CPLErr ECWDataset::ReadBandsDirectly(void * pData, int nBufXSize, int nBufYSize,
 /************************************************************************/
 
 CPLErr ECWDataset::ReadBands(void * pData, int nBufXSize, int nBufYSize,
-                             GDALDataType eBufType, 
-                             int nBandCount, 
+                             GDALDataType eBufType,
+                             int nBandCount,
                              GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace,
                              GDALRasterIOExtraArg* psExtraArg)
 {
@@ -2218,15 +2232,15 @@ CPLErr ECWDataset::ReadBands(void * pData, int nBufXSize, int nBufYSize,
 /*      Setup working scanline, and the pointers into it.               */
 /* -------------------------------------------------------------------- */
     int nDataTypeSize = (GDALGetDataTypeSize(eRasterDataType) / 8);
-    bool bDirect = (eBufType == eRasterDataType) && nDataTypeSize == nPixelSpace && 
-        nLineSpace == (nPixelSpace*nBufXSize) && nBandSpace == (nDataTypeSize*nBufXSize*nBufYSize) ;
+    bool bDirect = (eBufType == eRasterDataType) && nDataTypeSize == nPixelSpace &&
+        nLineSpace == (nPixelSpace*nBufXSize) && nBandSpace == (static_cast<GSpacing>(nDataTypeSize)*nBufXSize*nBufYSize) ;
     if (bDirect)
     {
-        return ReadBandsDirectly(pData, nBufXSize, nBufYSize,eBufType, 
+        return ReadBandsDirectly(pData, nBufXSize, nBufYSize,eBufType,
             nBandCount, nPixelSpace, nLineSpace, nBandSpace, psExtraArg);
     }
-     CPLDebug( "ECW", 
-              "ReadBands(-> %dx%d) - reading lines using GDALCopyWords.", 
+     CPLDebug( "ECW",
+              "ReadBands(-> %dx%d) - reading lines using GDALCopyWords.",
               nBufXSize, nBufYSize);
     CPLErr eErr = CE_None;
     GByte *pabyBILScanline = (GByte *) CPLMalloc(nBufXSize * nDataTypeSize *
@@ -2243,7 +2257,7 @@ CPLErr ECWDataset::ReadBands(void * pData, int nBufXSize, int nBufYSize,
     {
         NCSEcwReadStatus  eRStatus;
 
-        eRStatus = poFileView->ReadLineBIL( eNCSRequestDataType, 
+        eRStatus = poFileView->ReadLineBIL( eNCSRequestDataType,
                                             (UINT16) nBandCount,
                                             (void **) papabyBIL );
         if( eRStatus != NCSECW_READ_OK )
@@ -2264,11 +2278,11 @@ CPLErr ECWDataset::ReadBands(void * pData, int nBufXSize, int nBufYSize,
                 }
             }
 
-            GDALCopyWords( 
+            GDALCopyWords(
                 pabyBILScanline + i * nDataTypeSize * nBufXSize,
-                eRasterDataType, nDataTypeSize, 
-                ((GByte *) pData) + nLineSpace * iScanline + nBandSpace * i, 
-                eBufType, (int)nPixelSpace, 
+                eRasterDataType, nDataTypeSize,
+                ((GByte *) pData) + nLineSpace * iScanline + nBandSpace * i,
+                eBufType, (int)nPixelSpace,
                 nBufXSize );
         }
 
@@ -2290,22 +2304,22 @@ CPLErr ECWDataset::ReadBands(void * pData, int nBufXSize, int nBufYSize,
 /************************************************************************/
 /*                        IdentifyJPEG2000()                            */
 /*                                                                      */
-/*          Open method that only supports JPEG2000 files.              */
+/*          Identify method that only supports JPEG2000 files.          */
 /************************************************************************/
 
 int ECWDataset::IdentifyJPEG2000( GDALOpenInfo * poOpenInfo )
 
 {
-    if( EQUALN(poOpenInfo->pszFilename,"J2K_SUBFILE:",12) )
+    if( STARTS_WITH_CI(poOpenInfo->pszFilename, "J2K_SUBFILE:") )
         return TRUE;
 
-    else if( poOpenInfo->nHeaderBytes >= 16 
-        && (memcmp( poOpenInfo->pabyHeader, jpc_header, 
+    else if( poOpenInfo->nHeaderBytes >= 16
+        && (memcmp( poOpenInfo->pabyHeader, jpc_header,
                     sizeof(jpc_header) ) == 0
-            || memcmp( poOpenInfo->pabyHeader, jp2_header, 
+            || memcmp( poOpenInfo->pabyHeader, jp2_header,
                     sizeof(jp2_header) ) == 0) )
         return TRUE;
-    
+
     else
         return FALSE;
 }
@@ -2324,7 +2338,7 @@ GDALDataset *ECWDataset::OpenJPEG2000( GDALOpenInfo * poOpenInfo )
 
     return Open( poOpenInfo, TRUE );
 }
-    
+
 /************************************************************************/
 /*                           IdentifyECW()                              */
 /*                                                                      */
@@ -2340,8 +2354,8 @@ int ECWDataset::IdentifyECW( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( (!EQUAL(CPLGetExtension(poOpenInfo->pszFilename),"ecw")
          || poOpenInfo->nHeaderBytes == 0)
-        && !EQUALN(poOpenInfo->pszFilename,"ecwp:",5)
-        && !EQUALN(poOpenInfo->pszFilename,"ecwps:",5) )
+        && !STARTS_WITH_CI(poOpenInfo->pszFilename, "ecwp:")
+        && !STARTS_WITH_CI(poOpenInfo->pszFilename,"ecwps:") )
         return FALSE;
 
     return TRUE;
@@ -2378,18 +2392,30 @@ CNCSJP2FileView *ECWDataset::OpenFileView( const char *pszDatasetName,
 /* -------------------------------------------------------------------- */
     CNCSJP2FileView *poFileView = NULL;
     NCSError         eErr;
-    CNCSError        oErr;
+    CNCSError        oErr(GetCNCSError(NCS_SUCCESS));
 
     bUsingCustomStream = FALSE;
     poFileView = new CNCSFile();
     //we always open in read only mode. This should be improved in the future.
     try
     {
-        oErr = poFileView->Open( (char *) pszDatasetName, bProgressive, false );
+#ifdef WIN32
+        if( CPLTestBool( CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
+        {
+            wchar_t *pwszDatasetName = CPLRecodeToWChar( pszDatasetName, CPL_ENC_UTF8, CPL_ENC_UCS2 );
+            oErr = poFileView->Open( pwszDatasetName, bProgressive, false );
+            CPLFree( pwszDatasetName );
+        }
+        else
+#endif
+        {
+            oErr = poFileView->Open( (char *) pszDatasetName, bProgressive, false );
+        }
     }
     catch(...)
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "Unexpected exception occured in ECW SDK");
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Unexpected exception occurred in ECW SDK");
         delete poFileView;
         return NULL;
     }
@@ -2400,8 +2426,8 @@ CNCSJP2FileView *ECWDataset::OpenFileView( const char *pszDatasetName,
 /* -------------------------------------------------------------------- */
     if( eErr != NCS_SUCCESS )
     {
-        CPLDebug( "ECW", 
-                  "NCScbmOpenFileView(%s): eErr=%d, will try VSIL stream.", 
+        CPLDebug( "ECW",
+                  "NCScbmOpenFileView(%s): eErr=%d, will try VSIL stream.",
                   pszDatasetName, (int) eErr );
 
         delete poFileView;
@@ -2409,7 +2435,7 @@ CNCSJP2FileView *ECWDataset::OpenFileView( const char *pszDatasetName,
         VSILFILE *fpVSIL = VSIFOpenL( pszDatasetName, "rb" );
         if( fpVSIL == NULL )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
+            CPLError( CE_Failure, CPLE_OpenFailed,
                       "Failed to open %s.", pszDatasetName );
             return NULL;
         }
@@ -2432,27 +2458,27 @@ CNCSJP2FileView *ECWDataset::OpenFileView( const char *pszDatasetName,
         poFileView = new CNCSJP2FileView();
         oErr = poFileView->Open( poIOStream, bProgressive );
 
-        // The CNCSJP2FileView (poFileView) object may not use the iostream 
-        // (poIOStream) passed to the CNCSJP2FileView::Open() method if an 
+        // The CNCSJP2FileView (poFileView) object may not use the iostream
+        // (poIOStream) passed to the CNCSJP2FileView::Open() method if an
         // iostream is already available to the ECW JPEG 2000 SDK for a given
-        // file.  Consequently, if the iostream passed to 
-        // CNCSJP2FileView::Open() does not become the underlying iostream 
+        // file.  Consequently, if the iostream passed to
+        // CNCSJP2FileView::Open() does not become the underlying iostream
         // of the CNCSJP2FileView object, then it should be deleted.
         //
         // In addition, the underlying iostream of the CNCSJP2FileView object
-        // should not be deleted until all CNCSJP2FileView objects using the 
-        // underlying iostream are deleted. Consequently, each time a 
-        // CNCSJP2FileView object is created, the nFileViewCount attribute 
-        // of the underlying VSIIOStream object must be incremented for use 
+        // should not be deleted until all CNCSJP2FileView objects using the
+        // underlying iostream are deleted. Consequently, each time a
+        // CNCSJP2FileView object is created, the nFileViewCount attribute
+        // of the underlying VSIIOStream object must be incremented for use
         // in the ECWDataset destructor.
-          
-        VSIIOStream * poUnderlyingIOStream = 
+
+        VSIIOStream * poUnderlyingIOStream =
             ((VSIIOStream *)(poFileView->GetStream()));
 
         if ( poUnderlyingIOStream )
             poUnderlyingIOStream->nFileViewCount++;
 
-        if ( poIOStream != poUnderlyingIOStream ) 
+        if ( poIOStream != poUnderlyingIOStream )
         {
             delete poIOStream;
         }
@@ -2465,14 +2491,13 @@ CNCSJP2FileView *ECWDataset::OpenFileView( const char *pszDatasetName,
 
         if( oErr.GetErrorNumber() != NCS_SUCCESS )
         {
-            if (poFileView)
-                delete poFileView;
+            delete poFileView;
             ECWReportError(oErr);
 
             return NULL;
         }
     }
-    
+
     return poFileView;
 }
 
@@ -2501,7 +2526,7 @@ GDALDataset *ECWDataset::Open( GDALOpenInfo * poOpenInfo, int bIsJPEG2000 )
 /*      From: J2K_SUBFILE:offset,size,filename                           */
 /*      To: /vsisubfile/offset_size,filename                            */
 /* -------------------------------------------------------------------- */
-    if (EQUALN(osFilename,"J2K_SUBFILE:",12))
+    if (STARTS_WITH_CI(osFilename, "J2K_SUBFILE:"))
     {
         char** papszTokens = CSLTokenizeString2(osFilename.c_str()+12, ",", 0);
         if (CSLCount(papszTokens) >= 3)
@@ -2511,7 +2536,7 @@ GDALDataset *ECWDataset::Open( GDALOpenInfo * poOpenInfo, int bIsJPEG2000 )
         }
         else
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
+            CPLError( CE_Failure, CPLE_OpenFailed,
                       "Failed to parse J2K_SUBFILE specification." );
             CSLDestroy(papszTokens);
             return NULL;
@@ -2529,7 +2554,7 @@ GDALDataset *ECWDataset::Open( GDALOpenInfo * poOpenInfo, int bIsJPEG2000 )
         /* Detect what is apparently the ECW v3 file format signature */
         if( EQUAL(CPLGetExtension(osFilename), "ECW") &&
             poOpenInfo->nHeaderBytes > 0x30 &&
-            EQUALN((const char*)(poOpenInfo->pabyHeader + 0x20), "ecw ECW3", 8) )
+            STARTS_WITH_CI((const char*)(poOpenInfo->pabyHeader + 0x20), "ecw ECW3") )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
                      "Cannot open %s which looks like a ECW format v3 file, that requires ECW SDK 5.0 or later",
@@ -2549,8 +2574,8 @@ GDALDataset *ECWDataset::Open( GDALOpenInfo * poOpenInfo, int bIsJPEG2000 )
     poDS->eAccess = poOpenInfo->eAccess;
 
     // Disable .aux.xml writing for subfiles and such.  Unfortunately
-    // this will also disable it in some cases where it might be 
-    // applicable. 
+    // this will also disable it in some cases where it might be
+    // applicable.
     if( bUsingCustomStream )
         poDS->nPamFlags |= GPF_DISABLED;
 
@@ -2563,7 +2588,7 @@ GDALDataset *ECWDataset::Open( GDALOpenInfo * poOpenInfo, int bIsJPEG2000 )
 
     CPLDebug( "ECW", "FileInfo: SizeXY=%d,%d Bands=%d\n"
               "       OriginXY=%g,%g  CellIncrementXY=%g,%g\n"
-              "       ColorSpace=%d, eCellType=%d\n", 
+              "       ColorSpace=%d, eCellType=%d\n",
               poDS->psFileInfo->nSizeX,
               poDS->psFileInfo->nSizeY,
               poDS->psFileInfo->nBands,
@@ -2577,7 +2602,7 @@ GDALDataset *ECWDataset::Open( GDALOpenInfo * poOpenInfo, int bIsJPEG2000 )
 /* -------------------------------------------------------------------- */
 /*      Establish raster info.                                          */
 /* -------------------------------------------------------------------- */
-    poDS->nRasterXSize = poDS->psFileInfo->nSizeX; 
+    poDS->nRasterXSize = poDS->psFileInfo->nSizeX;
     poDS->nRasterYSize = poDS->psFileInfo->nSizeY;
 
 /* -------------------------------------------------------------------- */
@@ -2650,7 +2675,7 @@ GDALDataset *ECWDataset::Open( GDALOpenInfo * poOpenInfo, int bIsJPEG2000 )
     /* -------------------------------------------------------------------- */
         if( !poDS->bGeoTransformValid )
         {
-            poDS->bGeoTransformValid |= 
+            poDS->bGeoTransformValid |=
                 GDALReadWorldFile2( osFilename, NULL,
                                     poDS->adfGeoTransform,
                                     poOpenInfo->GetSiblingFiles(), NULL )
@@ -2754,7 +2779,7 @@ GDALDataset *ECWDataset::Open( GDALOpenInfo * poOpenInfo, int bIsJPEG2000 )
 
         // Progression Order
         char *csOrder = NULL;
-        poDS->poFileView->GetParameter((char*)"JPC:DECOMPRESS:PROGRESSION:ORDER", &csOrder);	
+        poDS->poFileView->GetParameter((char*)"JPC:DECOMPRESS:PROGRESSION:ORDER", &csOrder);
         if (csOrder) {
             poDS->SetMetadataItem("PROGRESSION_ORDER", csOrder, JPEG2000_DOMAIN_NAME);
             NCSFree(csOrder);
@@ -2790,10 +2815,10 @@ GDALDataset *ECWDataset::Open( GDALOpenInfo * poOpenInfo, int bIsJPEG2000 )
         poDS->SetMetadataItem("COMPRESSION_RATE_ACTUAL", CPLString().Printf("%f", poDS->psFileInfo->fActualCompressionRate));
         poDS->SetMetadataItem("CLOCKWISE_ROTATION_DEG", CPLString().Printf("%f", poDS->psFileInfo->fCWRotationDegrees));
         poDS->SetMetadataItem("COMPRESSION_DATE", poDS->psFileInfo->sCompressionDate);
-        //Get file metadata. 
+        //Get file metadata.
         poDS->ReadFileMetaDataFromFile();
     }
-#else 
+#else
     poDS->SetMetadataItem("VERSION", CPLString().Printf("%d",bIsJPEG2000?1:2));
 #endif
 
@@ -2906,7 +2931,7 @@ void ECWDataset::ReadFileMetaDataFromFile()
     if (psFileInfo->pFileMetaData->sAddress != NULL )
         GDALDataset::SetMetadataItem("FILE_METADATA_ADDRESS", NCS::CString(psFileInfo->pFileMetaData->sAddress));
     if (psFileInfo->pFileMetaData->sTelephone != NULL )
-        GDALDataset::SetMetadataItem("FILE_METADATA_TELEPHONE", NCS::CString(psFileInfo->pFileMetaData->sTelephone));		
+        GDALDataset::SetMetadataItem("FILE_METADATA_TELEPHONE", NCS::CString(psFileInfo->pFileMetaData->sTelephone));
 }
 
 /************************************************************************/
@@ -2946,7 +2971,7 @@ void ECWDataset::WriteFileMetaData(NCSFileMetaData* pFileMetaDataCopy)
     NCSEditClose(psFileView);
 }
 
-#endif 
+#endif
 /************************************************************************/
 /*                         ECW2WKTProjection()                          */
 /*                                                                      */
@@ -2973,19 +2998,19 @@ void ECWDataset::ECW2WKTProjection()
 /*      origin (0,0) and pixel size (1,1).  I think sometimes I have    */
 /*      also seen pixel increments of 0 on invalid datasets.            */
 /* -------------------------------------------------------------------- */
-    if( psFileInfo->fOriginX != 0.0 
-        || psFileInfo->fOriginY != 0.0 
-        || (psFileInfo->fCellIncrementX != 0.0 
+    if( psFileInfo->fOriginX != 0.0
+        || psFileInfo->fOriginY != 0.0
+        || (psFileInfo->fCellIncrementX != 0.0
             && psFileInfo->fCellIncrementX != 1.0)
-        || (psFileInfo->fCellIncrementY != 0.0 
+        || (psFileInfo->fCellIncrementY != 0.0
             && psFileInfo->fCellIncrementY != 1.0) )
     {
         bGeoTransformValid = TRUE;
-        
+
         adfGeoTransform[0] = psFileInfo->fOriginX;
         adfGeoTransform[1] = psFileInfo->fCellIncrementX;
         adfGeoTransform[2] = 0.0;
-        
+
         adfGeoTransform[3] = psFileInfo->fOriginY;
         adfGeoTransform[4] = 0.0;
         adfGeoTransform[5] = -fabs(psFileInfo->fCellIncrementY);
@@ -3017,8 +3042,8 @@ void ECWDataset::ECW2WKTProjection()
     m_osDatumCode = psFileInfo->szDatum;
     m_osProjCode = psFileInfo->szProjection;
     m_osUnitsCode = osUnits;
-    if( oSRS.importFromERM( psFileInfo->szProjection, 
-                            psFileInfo->szDatum, 
+    if( oSRS.importFromERM( psFileInfo->szProjection,
+                            psFileInfo->szDatum,
                             osUnits ) == OGRERR_NONE )
     {
         oSRS.exportToWkt( &pszProjection );
@@ -3048,9 +3073,9 @@ int ECWTranslateFromWKT( const char *pszWKT,
 
     if( pszWKT == NULL || strlen(pszWKT) == 0 )
         return FALSE;
-    
+
     oSRS.importFromWkt( &pszWKTIn );
-    
+
     if( oSRS.IsLocal() )
         return TRUE;
 
@@ -3072,20 +3097,18 @@ int ECWTranslateFromWKT( const char *pszWKT,
         pszAuthorityName =  oSRS.GetAuthorityName( "GEOGCS" );
     }
 
-    if( pszAuthorityName != NULL && EQUAL(pszAuthorityName,"EPSG") 
+    if( pszAuthorityName != NULL && EQUAL(pszAuthorityName,"EPSG")
         && pszAuthorityCode != NULL && atoi(pszAuthorityCode) > 0 )
         nEPSGCode = (UINT32) atoi(pszAuthorityCode);
 
     if( nEPSGCode != 0 )
     {
         char *pszEPSGProj = NULL, *pszEPSGDatum = NULL;
-        CNCSError oErr;
-
-        oErr = 
-            CNCSJP2FileView::GetProjectionAndDatum( atoi(pszAuthorityCode), 
+        CNCSError oErr =
+            CNCSJP2FileView::GetProjectionAndDatum( atoi(pszAuthorityCode),
                                                  &pszEPSGProj, &pszEPSGDatum );
 
-        CPLDebug( "ECW", "GetGDTProjDat(%d) = %s/%s", 
+        CPLDebug( "ECW", "GetGDTProjDat(%d) = %s/%s",
                   atoi(pszAuthorityCode),
                   pszEPSGProj ? pszEPSGProj : "(null)",
                   pszEPSGDatum ? pszEPSGDatum : "(null)");
@@ -3144,7 +3167,7 @@ CellSizeUnits ECWTranslateToCellSizeUnits(const char* pszUnits)
 
 GDALColorInterp ECWGetColorInterpretationByName(const char *pszName)
 {
-    if (EQUAL(pszName, NCS_BANDDESC_AllOpacity)) 
+    if (EQUAL(pszName, NCS_BANDDESC_AllOpacity))
         return GCI_AlphaBand;
     else if (EQUAL(pszName, NCS_BANDDESC_Blue))
         return GCI_BlueBand;
@@ -3165,35 +3188,37 @@ GDALColorInterp ECWGetColorInterpretationByName(const char *pszName)
 
 const char* ECWGetColorInterpretationName(GDALColorInterp eColorInterpretation, int nBandNumber)
 {
-    const char *result;
+    const char *pszResult;
     switch (eColorInterpretation){
-    case GCI_AlphaBand: 
-        result = NCS_BANDDESC_AllOpacity;
+    case GCI_AlphaBand:
+        pszResult = NCS_BANDDESC_AllOpacity;
         break;
-    case GCI_GrayIndex: 
-        result = NCS_BANDDESC_Greyscale;
+    case GCI_GrayIndex:
+        pszResult = NCS_BANDDESC_Greyscale;
         break;
     case GCI_RedBand:
     case GCI_GreenBand:
-    case GCI_BlueBand: 
-        result = GDALGetColorInterpretationName(eColorInterpretation);
+    case GCI_BlueBand:
+        pszResult = GDALGetColorInterpretationName(eColorInterpretation);
         break;
     case GCI_Undefined:
-        if (nBandNumber <=3){
-            if (nBandNumber == 0 ) {
-                result = "Red";
-            }else if (nBandNumber == 1) {
-                result = "Green";
-            }else if (nBandNumber == 2) {
-                result = "Blue";
-            }
+        if (nBandNumber == 0 ) {
+            pszResult = "Red";
+        }else if (nBandNumber == 1) {
+            pszResult = "Green";
+        }else if (nBandNumber == 2) {
+            pszResult = "Blue";
         }
-        result = CPLSPrintf(NCS_BANDDESC_Band,nBandNumber + 1);
+        else
+        {
+            pszResult = CPLSPrintf(NCS_BANDDESC_Band,nBandNumber + 1);
+        }
+        break;
+    default:
+        pszResult = CPLSPrintf(NCS_BANDDESC_Band,nBandNumber + 1);
         break;
-    default: 
-        result = CPLSPrintf(NCS_BANDDESC_Band,nBandNumber + 1);
     }
-    return result;
+    return pszResult;
 }
 
 /************************************************************************/
@@ -3213,11 +3238,11 @@ const char* ECWGetColorSpaceName(NCSFileColorSpace colorSpace)
         case NCSCS_MULTIBAND:
             return "MULTIBAND"; break;
         case NCSCS_sRGB:
-            return  "RGB"; break;
+            return "RGB"; break;
         case NCSCS_YCbCr:
             return "YCbCr"; break;
         default:
-            return  "unrecognised";
+            return "unrecognized";
     }
 }
 /************************************************************************/
@@ -3265,15 +3290,15 @@ void ECWInitialize()
 /*      This will disable automatic conversion of YCbCr to RGB by       */
 /*      the toolkit.                                                    */
 /* -------------------------------------------------------------------- */
-    if( !CSLTestBoolean( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB","YES") ) )
+    if( !CPLTestBool( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB","YES") ) )
         NCSecwSetConfig(NCSCFG_JP2_MANAGE_ICC, FALSE);
 #if ECWSDK_VERSION>= 50
 	NCSecwSetConfig(NCSCFG_ECWP_CLIENT_HTTP_USER_AGENT, "ECW GDAL Driver/" NCS_ECWJP2_FULL_VERSION_STRING_DOT_DEL);
-#endif 
+#endif
 /* -------------------------------------------------------------------- */
 /*      Initialize cache memory limit.  Default is apparently 1/4 RAM.  */
 /* -------------------------------------------------------------------- */
-    const char *pszEcwCacheSize = 
+    const char *pszEcwCacheSize =
         CPLGetConfigOption("GDAL_ECW_CACHE_MAXMEM",NULL);
     if( pszEcwCacheSize == NULL )
         pszEcwCacheSize = CPLGetConfigOption("ECW_CACHE_MAXMEM",NULL);
@@ -3288,7 +3313,7 @@ void ECWInitialize()
     /*		behaviour.														*/
     /* -------------------------------------------------------------------- */
     #if ECWSDK_VERSION >= 50
-    if( CSLTestBoolean( CPLGetConfigOption("ECW_DO_NOT_RESOLVE_DATUM_PROJECTION","NO") ) == TRUE) 
+    if( CPLTestBool( CPLGetConfigOption("ECW_DO_NOT_RESOLVE_DATUM_PROJECTION","NO") ) == TRUE)
         NCSecwSetConfig(NCSCFG_PROJECTION_FORMAT, NCS_PROJECTION_ERMAPPER_FORMAT);
     #endif
 /* -------------------------------------------------------------------- */
@@ -3315,26 +3340,26 @@ void ECWInitialize()
 /* -------------------------------------------------------------------- */
     pszOpt = CPLGetConfigOption( "ECWP_BLOCKING_TIME_MS", NULL );
     if( pszOpt )
-        NCSecwSetConfig( NCSCFG_BLOCKING_TIME_MS, 
+        NCSecwSetConfig( NCSCFG_BLOCKING_TIME_MS,
                          (NCSTimeStampMs) atoi(pszOpt) );
 
     // I believe 10s means we wait for complete data back from
     // ECWP almost all the time which is good for our blocking model.
     pszOpt = CPLGetConfigOption( "ECWP_REFRESH_TIME_MS", "10000" );
     if( pszOpt )
-        NCSecwSetConfig( NCSCFG_REFRESH_TIME_MS, 
+        NCSecwSetConfig( NCSCFG_REFRESH_TIME_MS,
                          (NCSTimeStampMs) atoi(pszOpt) );
 
     pszOpt = CPLGetConfigOption( "ECW_TEXTURE_DITHER", NULL );
     if( pszOpt )
-        NCSecwSetConfig( NCSCFG_TEXTURE_DITHER, 
-                         (BOOLEAN) CSLTestBoolean( pszOpt ) );
+        NCSecwSetConfig( NCSCFG_TEXTURE_DITHER,
+                         (BOOLEAN) CPLTestBool( pszOpt ) );
 
 
     pszOpt = CPLGetConfigOption( "ECW_FORCE_FILE_REOPEN", NULL );
     if( pszOpt )
-        NCSecwSetConfig( NCSCFG_FORCE_FILE_REOPEN, 
-                         (BOOLEAN) CSLTestBoolean( pszOpt ) );
+        NCSecwSetConfig( NCSCFG_FORCE_FILE_REOPEN,
+                         (BOOLEAN) CPLTestBool( pszOpt ) );
 
     pszOpt = CPLGetConfigOption( "ECW_CACHE_MAXOPEN", NULL );
     if( pszOpt )
@@ -3343,19 +3368,19 @@ void ECWInitialize()
 #if ECWSDK_VERSION >= 40
     pszOpt = CPLGetConfigOption( "ECW_AUTOGEN_J2I", NULL );
     if( pszOpt )
-        NCSecwSetConfig( NCSCFG_JP2_AUTOGEN_J2I, 
-                         (BOOLEAN) CSLTestBoolean( pszOpt ) );
+        NCSecwSetConfig( NCSCFG_JP2_AUTOGEN_J2I,
+                         (BOOLEAN) CPLTestBool( pszOpt ) );
 
     pszOpt = CPLGetConfigOption( "ECW_OPTIMIZE_USE_NEAREST_NEIGHBOUR", NULL );
     if( pszOpt )
-        NCSecwSetConfig( NCSCFG_OPTIMIZE_USE_NEAREST_NEIGHBOUR, 
-                         (BOOLEAN) CSLTestBoolean( pszOpt ) );
+        NCSecwSetConfig( NCSCFG_OPTIMIZE_USE_NEAREST_NEIGHBOUR,
+                         (BOOLEAN) CPLTestBool( pszOpt ) );
 
 
     pszOpt = CPLGetConfigOption( "ECW_RESILIENT_DECODING", NULL );
     if( pszOpt )
-        NCSecwSetConfig( NCSCFG_RESILIENT_DECODING, 
-                         (BOOLEAN) CSLTestBoolean( pszOpt ) );
+        NCSecwSetConfig( NCSCFG_RESILIENT_DECODING,
+                         (BOOLEAN) CPLTestBool( pszOpt ) );
 #endif
 }
 
@@ -3363,7 +3388,7 @@ void ECWInitialize()
 /*                         GDALDeregister_ECW()                         */
 /************************************************************************/
 
-void GDALDeregister_ECW( GDALDriver * )
+static void GDALDeregister_ECW( GDALDriver * )
 
 {
     /* For unknown reason, this cleanup can take up to 3 seconds (see #3134) for SDK 3.3. */
@@ -3389,7 +3414,7 @@ void GDALDeregister_ECW( GDALDriver * )
 }
 
 /************************************************************************/
-/*                          GDALRegister_ECW()                        */
+/*                          GDALRegister_ECW()                          */
 /************************************************************************/
 
 /* Needed for v4.3 and v5.0 */
@@ -3400,50 +3425,49 @@ void GDALDeregister_ECW( GDALDriver * )
 void GDALRegister_ECW()
 
 {
-#ifdef FRMT_ecw 
-    GDALDriver	*poDriver;
+#ifdef FRMT_ecw
+    GDALDriver *poDriver;
 
-    if (! GDAL_CHECK_VERSION("ECW driver"))
+    if( !GDAL_CHECK_VERSION( "ECW driver" ) )
         return;
 
-    if( GDALGetDriverByName( "ECW" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "ECW" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    if( GDALGetDriverByName( "ECW" ) != NULL )
+        return;
 
-        CPLString osLongName = "ERDAS Compressed Wavelets (SDK ";
+    poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "ECW" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+
+    CPLString osLongName = "ERDAS Compressed Wavelets (SDK ";
 
 #ifdef NCS_ECWSDK_VERSION_STRING
-        osLongName += NCS_ECWSDK_VERSION_STRING;
+    osLongName += NCS_ECWSDK_VERSION_STRING;
 #else
-        osLongName += "3.x";
-#endif        
-        osLongName += ")";
-
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, osLongName );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_ecw.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "ecw" );
-        
-        poDriver->pfnIdentify = ECWDataset::IdentifyECW;
-        poDriver->pfnOpen = ECWDataset::OpenECW;
-        poDriver->pfnUnloadDriver = GDALDeregister_ECW;
+    osLongName += "3.x";
+#endif
+    osLongName += ")";
+
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, osLongName );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_ecw.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "ecw" );
+
+    poDriver->pfnIdentify = ECWDataset::IdentifyECW;
+    poDriver->pfnOpen = ECWDataset::OpenECW;
+    poDriver->pfnUnloadDriver = GDALDeregister_ECW;
 #ifdef HAVE_COMPRESS
-// The create method does not work with SDK 3.3 ( crash in CNCSJP2FileView::WriteLineBIL() due to m_pFile being NULL )
+    // The create method does not work with SDK 3.3 ( crash in
+    // CNCSJP2FileView::WriteLineBIL() due to m_pFile being NULL ).
 #if ECWSDK_VERSION >= 50
-        poDriver->pfnCreate = ECWCreateECW;  
+    poDriver->pfnCreate = ECWCreateECW;
 #endif
-        poDriver->pfnCreateCopy = ECWCreateCopyECW;
+    poDriver->pfnCreateCopy = ECWCreateCopyECW;
 #if ECWSDK_VERSION >= 50
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte UInt16" );
-#else 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte UInt16" );
+#else
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,  "Byte" );
 #endif
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "   <Option name='TARGET' type='float' description='Compression Percentage' />"
 "   <Option name='PROJ' type='string' description='ECW Projection Name'/>"
@@ -3462,13 +3486,12 @@ void GDALRegister_ECW()
 
 "</CreationOptionList>" );
 #else
-        /* In read-only mode, we support VirtualIO. This is not the case */
-        /* for ECWCreateCopyECW() */
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    // In read-only mode, we support VirtualIO. This is not the case
+    // for ECWCreateCopyECW().
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 #endif
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 #endif /* def FRMT_ecw */
 }
 
@@ -3500,50 +3523,49 @@ GDALDataset* ECWDatasetOpenJPEG2000(GDALOpenInfo* poOpenInfo)
 void GDALRegister_JP2ECW()
 
 {
-#ifdef FRMT_ecw 
-    GDALDriver	*poDriver;
+#ifdef FRMT_ecw
+    if( !GDAL_CHECK_VERSION( "JP2ECW driver" ) )
+        return;
 
-    if (! GDAL_CHECK_VERSION("JP2ECW driver"))
+    if( GDALGetDriverByName( "JP2ECW" ) != NULL )
         return;
 
-    if( GDALGetDriverByName( "JP2ECW" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "JP2ECW" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "JP2ECW" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
 
-        CPLString osLongName = "ERDAS JPEG2000 (SDK ";
+    CPLString osLongName = "ERDAS JPEG2000 (SDK ";
 
 #ifdef NCS_ECWSDK_VERSION_STRING
-        osLongName += NCS_ECWSDK_VERSION_STRING;
+    osLongName += NCS_ECWSDK_VERSION_STRING;
 #else
-        osLongName += "3.x";
-#endif        
-        osLongName += ")";
-
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, osLongName );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_jp2ecw.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jp2" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-        
-        poDriver->pfnIdentify = ECWDataset::IdentifyJPEG2000;
-        poDriver->pfnOpen = ECWDataset::OpenJPEG2000;
-
-        poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST, 
+    osLongName += "3.x";
+#endif
+    osLongName += ")";
+
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, osLongName );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_jp2ecw.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jp2" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnIdentify = ECWDataset::IdentifyJPEG2000;
+    poDriver->pfnOpen = ECWDataset::OpenJPEG2000;
+
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
 "<OpenOptionList>"
 "   <Option name='1BIT_ALPHA_PROMOTION' type='boolean' description='Whether a 1-bit alpha channel should be promoted to 8-bit' default='YES'/>"
 "   <Option name='OPEN_REMOTE_GML' type='boolean' description='Whether to load remote vector layers referenced by a link in a GMLJP2 v2 box' default='NO'/>"
 "</OpenOptionList>" );
 
 #ifdef HAVE_COMPRESS
-        poDriver->pfnCreate = ECWCreateJPEG2000;
-        poDriver->pfnCreateCopy = ECWCreateCopyJPEG2000;
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte UInt16 Int16 UInt32 Int32 Float32 Float64" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
+    poDriver->pfnCreate = ECWCreateJPEG2000;
+    poDriver->pfnCreateCopy = ECWCreateCopyJPEG2000;
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte UInt16 Int16 UInt32 Int32 "
+                               "Float32 Float64" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "   <Option name='TARGET' type='float' description='Compression Percentage' />"
 "   <Option name='PROJ' type='string' description='ECW Projection Name'/>"
@@ -3591,7 +3613,6 @@ void GDALRegister_JP2ECW()
 "</CreationOptionList>" );
 #endif
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 #endif /* def FRMT_ecw */
 }
diff --git a/frmts/ecw/ecwsdk_headers.h b/frmts/ecw/ecwsdk_headers.h
new file mode 100644
index 0000000..c8c4a13
--- /dev/null
+++ b/frmts/ecw/ecwsdk_headers.h
@@ -0,0 +1,102 @@
+/******************************************************************************
+ *
+ * Project:  GDAL
+ * Purpose:  Includes ECW SDK headers
+ * Author:   Even Rouault <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+#ifndef ECWSDK_HEADERS_H
+#define ECWSDK_HEADERS_H
+
+#include "cpl_port.h"
+
+#ifdef HAVE_GCC_SYSTEM_HEADER
+#pragma GCC system_header
+#endif
+
+
+// The following is needed on 4.x+ to enable rw support.
+#if defined(HAVE_COMPRESS)
+# ifndef ECW_COMPRESS_RW_SDK_VERSION
+#  define ECW_COMPRESS_RW_SDK_VERSION
+# endif
+#endif
+
+#if defined(_MSC_VER)
+#  pragma warning(disable:4800)
+#endif
+
+#include <NCSECWClient.h>
+#include <NCSECWCompressClient.h>
+#include <NCSErrors.h>
+#include <NCSFile.h>
+#include <NCSJP2FileView.h>
+
+#ifdef HAVE_ECW_BUILDNUMBER_H
+#  include <ECWJP2BuildNumber.h>
+#  if !defined(ECW_VERSION)
+#    define ECWSDK_VERSION (NCS_ECWJP2_VER_MAJOR*10+NCS_ECWJP2_VER_MINOR)
+#  endif
+#else
+/* By default, assume 3.3 SDK Version. */
+#  if !defined(ECWSDK_VERSION)
+#    define ECWSDK_VERSION 33
+#  endif
+#endif
+
+#if ECWSDK_VERSION < 40
+
+#if !defined(NO_COMPRESS) && !defined(HAVE_COMPRESS)
+#  define HAVE_COMPRESS
+#endif
+
+#else
+    #if ECWSDK_VERSION>=50
+                #if ECWSDK_VERSION>=51
+                        #define JPEG2000_DOMAIN_NAME "JPEG2000"
+                #endif
+        #include <NCSECWHeaderEditor.h>
+        #include "NCSEcw/SDK/Box.h"
+    #else
+        #include <HeaderEditor.h>
+    #endif
+#  define NCS_FASTCALL
+#endif
+
+#if ECWSDK_VERSION >= 40
+#define SDK_CAN_DO_SUPERSAMPLING 1
+#endif
+
+#ifndef NCSFILEBASE_H
+#  include <NCSJP2FileView.h>
+#else
+#  undef  CNCSJP2FileView
+#  define CNCSJP2FileView         CNCSFile
+#endif
+
+/* Trick to avoid warnings with SDK 3.3 when assigning a NCSError code */
+/* to a CNCSError object */
+static inline CNCSError GetCNCSError(NCSError nCode) { return CNCSError(nCode); }
+
+#endif
diff --git a/frmts/ecw/frmt_ecw.html b/frmts/ecw/frmt_ecw.html
index cc7ffd8..a330738 100644
--- a/frmts/ecw/frmt_ecw.html
+++ b/frmts/ecw/frmt_ecw.html
@@ -7,14 +7,14 @@
 
 <h1>ECW -- Enhanced Compressed Wavelets (.ecw)</h1>
 
-GDAL supports reading and writing ECW files using the ERDAS ECW/JP2 SDK developed by 
-Hexagon Geospatial (formerly Intergraph, ERDAS, ERMapper). Support is optional and 
+GDAL supports reading and writing ECW files using the ERDAS ECW/JP2 SDK developed by
+Hexagon Geospatial (formerly Intergraph, ERDAS, ERMapper). Support is optional and
 requires linking in the libraries available from the ECW/JP2 SDK Download page.<p>
 
 <h3>Licensing</h3>
 
 The ERDAS ECW/JP2 SDK v5.x is available under multiple license types. For Desktop usage, decoding
-any sized ECW/JP2 image is made available free of charge. To compress, deploy on a Server platform, or decode 
+any sized ECW/JP2 image is made available free of charge. To compress, deploy on a Server platform, or decode
 unlimited sized files on Mobile platforms a license must be purchased from Hexagon Geospatial.<p>
 
 
@@ -27,96 +27,96 @@ unlimited sized files on Mobile platforms a license must be purchased from Hexag
 
 <h2>Creation Options</h2>
 
-The ERDAS ECW/JP2 v4.x and v5.x SDK is only free for image decompression.  To 
-compress images it is necessary to build with the read/write SDK and to 
+The ERDAS ECW/JP2 v4.x and v5.x SDK is only free for image decompression.  To
+compress images it is necessary to build with the read/write SDK and to
 provide an OEM licensing key at runtime which may be purchased from ERDAS.<p>
 
-For those still using the ECW 3.3 SDK, images less than 500MB may be 
+For those still using the ECW 3.3 SDK, images less than 500MB may be
 compressed for free, while larger images require licensing from ERDAS.  See
 the licensing agreement and the LARGE_OK option.<p>
 
 Files to be compressed into ECW format must also
-be at least 128x128.  ECW currently only supports 8 bits per channel for 
-ECW Version 2 files. ECW Version 3 files supports 16 bits per channel 
+be at least 128x128.  ECW currently only supports 8 bits per channel for
+ECW Version 2 files. ECW Version 3 files supports 16 bits per channel
 (as Uint16 data type). Please see Creation options to enable ECW V3 files writing <p>
 
 When writing coordinate system information to ECW files, many less
-common coordinate systems are not mapped properly.  If you know the 
+common coordinate systems are not mapped properly.  If you know the
 ECW name for the coordinate system you can force it to be set at
 creation time with the PROJ and DATUM creation options. <p>
 
-ECW format does not support creation of overviews since the ECW format 
+ECW format does not support creation of overviews since the ECW format
 is already considered to be optimized for "arbitrary overviews". <P>
 
 <h2>Creation Options:</h2>
 
 <ul>
 
-<li> <b>LARGE_OK=YES</b>: <i>(v3.x SDK only)</i> Allow compressing files larger than 500MB in accordance with EULA terms. Deprecated since v4.x and 
+<li> <b>LARGE_OK=YES</b>: <i>(v3.x SDK only)</i> Allow compressing files larger than 500MB in accordance with EULA terms. Deprecated since v4.x and
 replaced by ECW_ENCODE_KEY & ECW_ENCODE_COMPANY.<p>
 
 <li> <b>ECW_ENCODE_KEY=key</b>: <i>(v4.x SDK or higher)</i> Provide the OEM encoding key to unlock encoding capability
-up to the licensed gigapixel limit.  The key is is approximately 129 hex digits long. The Company and Key must match and must be re-generated with each minor release of the SDK.  It may also be provided globally as a configuration option.<p>
+up to the licensed gigapixel limit.  The key is approximately 129 hex digits long. The Company and Key must match and must be re-generated with each minor release of the SDK.  It may also be provided globally as a configuration option.<p>
 
 <li> <b>ECW_ENCODE_COMPANY=name</b>: <i>(v4.x SDK or higher)</i> Provide the name of the company in the issued
-OEM key (see ECW_ENCODE_KEY).  The Company and Key must match and must be re-generated with each minor release of the SDK.  It may also be provided 
+OEM key (see ECW_ENCODE_KEY).  The Company and Key must match and must be re-generated with each minor release of the SDK.  It may also be provided
 globally as a configuration option.<p>
 
-<li> <b>TARGET=percent</b>: Set the target size reduction as a percentage of 
+<li> <b>TARGET=percent</b>: Set the target size reduction as a percentage of
 the original.  If not provided defaults to 90% for greyscale images, and 95%
 for RGB images.<p>
 
-<li> <b>PROJ=name</b>: Name of the ECW projection string to use. 
+<li> <b>PROJ=name</b>: Name of the ECW projection string to use.
 Common examples are NUTM11, or GEODETIC.<p>
 
-<li> <b>DATUM=name</b>: Name of the ECW datum string to use. 
+<li> <b>DATUM=name</b>: Name of the ECW datum string to use.
 Common examples are WGS84 or NAD83.<p>
 
 <li> <b>UNITS=name</b>: (GDAL >= 1.9.0) Name of the ECW projection units to use :
 METERS (default) or FEET (us-foot).<p>
 
-<li> <b>ECW_FORMAT_VERSION=2/3</b>: (GDAL >= 1.10.0) When build with the ECW 5.x SDK this option can be set to  
+<li> <b>ECW_FORMAT_VERSION=2/3</b>: (GDAL >= 1.10.0) When build with the ECW 5.x SDK this option can be set to
 allow ECW Version 3 files to be created. Default, 2 to retain widest compatibility.<p>
 
 </ul>
 
 <h2> Configuration Options </h2>
 
-The ERDAS ECW SDK supports a variety of 
-<a href="http://trac.osgeo.org/gdal/wiki/ConfigOptions">runtime configuration 
-options</a> to control various features.  Most of these are exposed as GDAL 
+The ERDAS ECW SDK supports a variety of
+<a href="http://trac.osgeo.org/gdal/wiki/ConfigOptions">runtime configuration
+options</a> to control various features.  Most of these are exposed as GDAL
 configuration options.  See the ECW SDK documentation for full details on the
-meaning of these options. 
+meaning of these options.
 
 <ul>
-<li> <b>ECW_CACHE_MAXMEM=bytes</b>: maximum bytes of RAM used for in-memory 
-caching.  If not set, up to one quarter of physical RAM will be used by the 
+<li> <b>ECW_CACHE_MAXMEM=bytes</b>: maximum bytes of RAM used for in-memory
+caching.  If not set, up to one quarter of physical RAM will be used by the
 SDK for in-memory caching.<p>
 
 <li> <b>ECWP_CACHE_LOCATION=path</b>: Path to a directory to use for caching
 ECWP results.  If unset ECWP caching will not be enabled.<p>
 
-<li> <b>ECWP_CACHE_SIZE_MB=number_of_megabytes</b>: The maximum 
-number of megabytes of space in the ECWP_CACHE_LOCATION to be used for 
+<li> <b>ECWP_CACHE_SIZE_MB=number_of_megabytes</b>: The maximum
+number of megabytes of space in the ECWP_CACHE_LOCATION to be used for
 caching ECWP results.<p>
 
 <li> <b>ECWP_BLOCKING_TIME_MS</b>: time an ecwp:// blocking read will wait
 before returning - default 10000 ms.<p>
 
-<li> <b>ECWP_REFRESH_TIME_MS</b>: time delay between blocks arriving and the 
+<li> <b>ECWP_REFRESH_TIME_MS</b>: time delay between blocks arriving and the
 next refresh callback - default 10000 ms.  For the purposes of GDAL this is
-the amount of time the driver will wait for more data on an ecwp connection 
-for which the final result has not yet been returned.  If set small then 
+the amount of time the driver will wait for more data on an ecwp connection
+for which the final result has not yet been returned.  If set small then
 RasterIO() requests will often produce low resolution results.<p>
 
 <li> <b>ECW_TEXTURE_DITHER=TRUE/FALSE</b>: This may be set to FALSE to disable
 dithering when decompressing ECW files.  Defaults to TRUE.<p>
 
-<li> <b>ECW_FORCE_FILE_REOPEN=TRUE/FALSE</b>: This may be set to TRUE to 
-force open a file handle for each file for each connection made.  Defaults to 
+<li> <b>ECW_FORCE_FILE_REOPEN=TRUE/FALSE</b>: This may be set to TRUE to
+force open a file handle for each file for each connection made.  Defaults to
 FALSE.<p>
 
-<li> <b>ECW_CACHE_MAXOPEN=number</b>: The maximum number of files to keep 
+<li> <b>ECW_CACHE_MAXOPEN=number</b>: The maximum number of files to keep
 open for ECW file handle caching.  Defaults to unlimited.<p>
 
 <li> <b>ECW_RESILIENT_DECODING=TRUE/FALSE</b>: Controls whether the reader
@@ -143,7 +143,7 @@ Note: This version is not backward compatible and will fail to decode in v3.x or
 In addition to local files, this driver also supports access to streaming network
 imagery services using the proprietary "ECWP" protocol from the ERDAS APOLLO product.  Use the full ecwp:// prefixed dataset url
 as input.  When built with ECW/JP2 SDK v4.1 or newer it
-is also possible to take advantage of 
+is also possible to take advantage of
 <a href="http://trac.osgeo.org/gdal/wiki/rfc24_progressive_data_support">
 RFC 24</a> for asynchronous / progressive streaming access to ECWP services.<p>
 
@@ -175,11 +175,11 @@ built from the projection string.<p>
 <li>FILE_METADATA_EMAIL
 <li>FILE_METADATA_TELEPHONE
 <li>CLOCKWISE_ROTATION_DEG
-<li>COLORSPACE 
+<li>COLORSPACE
 <li>COMPRESSION_DATE
 <li>COMPRESSION_RATE_ACTUAL
 <li>COMPRESSION_RATE_TARGET
-<li>VERSION 
+<li>VERSION
 </ul>
 
 <h2>See Also</h2>
diff --git a/frmts/ecw/frmt_jp2ecw.html b/frmts/ecw/frmt_jp2ecw.html
index c4bd5a0..4f08342 100644
--- a/frmts/ecw/frmt_jp2ecw.html
+++ b/frmts/ecw/frmt_jp2ecw.html
@@ -7,19 +7,19 @@
 
 <h1>JP2ECW -- ERDAS JPEG2000 (.jp2)</h1>
 
-GDAL supports reading and writing JPEG2000 files using the ERDAS ECW/JP2 SDK developed by 
-Hexagon Geospatial (formerly Intergraph, ERDAS, ERMapper). Support is optional and 
+GDAL supports reading and writing JPEG2000 files using the ERDAS ECW/JP2 SDK developed by
+Hexagon Geospatial (formerly Intergraph, ERDAS, ERMapper). Support is optional and
 requires linking in the libraries available from the ECW/JP2 SDK Download page.<p>
 
-Coordinate system and georeferencing transformations are read, and 
-some degree of support is included for GeoJP2 (tm) (GeoTIFF-in-JPEG2000), 
+Coordinate system and georeferencing transformations are read, and
+some degree of support is included for GeoJP2 (tm) (GeoTIFF-in-JPEG2000),
 ERDAS GML-in-JPEG2000, and the new GML-in-JPEG2000 specification developed
 at OGC. <p>
 
 <h3>Licensing</h3>
 
 The ERDAS ECW/JP2 SDK v5.x is available under multiple license types. For Desktop usage, decoding
-any sized ECW/JP2 image is made available free of charge. To compress, deploy on a Server platform, or decode 
+any sized ECW/JP2 image is made available free of charge. To compress, deploy on a Server platform, or decode
 unlimited sized files on Mobile platforms a license must be purchased from Hexagon Geospatial.<p>
 
 
@@ -47,24 +47,24 @@ Changing other options can <i>substantially</i> impact decoding speed and compat
 
 <ul>
 
-<li> <b>LARGE_OK=YES</b>: <i>(v3.x SDK only)</i> Allow compressing files larger than 500MB in accordance with EULA terms. Deprecated since v4.x and 
+<li> <b>LARGE_OK=YES</b>: <i>(v3.x SDK only)</i> Allow compressing files larger than 500MB in accordance with EULA terms. Deprecated since v4.x and
 replaced by ECW_ENCODE_KEY & ECW_ENCODE_COMPANY.<p>
 
 <li> <b>ECW_ENCODE_KEY=key</b>: <i>(v4.x SDK or higher)</i> Provide the OEM encoding key to unlock encoding capability
-up to the licensed gigapixel limit.  The key is is approximately 129 hex digits long. The Company and Key must match and must be re-generated with each minor release of the SDK.  It may also be provided globally as a configuration option.<p>
+up to the licensed gigapixel limit.  The key is approximately 129 hex digits long. The Company and Key must match and must be re-generated with each minor release of the SDK.  It may also be provided globally as a configuration option.<p>
 
 <li> <b>ECW_ENCODE_COMPANY=name</b>: <i>(v4.x SDK or higher)</i> Provide the name of the company in the issued
-OEM key (see ECW_ENCODE_KEY).  The Company and Key must match and must be re-generated with each minor release of the SDK.  It may also be provided 
+OEM key (see ECW_ENCODE_KEY).  The Company and Key must match and must be re-generated with each minor release of the SDK.  It may also be provided
 globally as a configuration option.<p>
 
-<li> <b>TARGET=percent</b>: Set the target size reduction as a percentage of 
-the original.  If not provided defaults to 75 for an 75% reduction.  TARGET=0 
+<li> <b>TARGET=percent</b>: Set the target size reduction as a percentage of
+the original.  If not provided defaults to 75 for an 75% reduction.  TARGET=0
 uses lossless compression.<p>
 
-<li> <b>PROJ=name</b>: Name of the ECW projection string to use. 
+<li> <b>PROJ=name</b>: Name of the ECW projection string to use.
 Common examples are NUTM11, or GEODETIC.<p>
 
-<li> <b>DATUM=name</b>: Name of the ECW datum string to use. 
+<li> <b>DATUM=name</b>: Name of the ECW datum string to use.
 Common examples are WGS84 or NAD83.<p>
 
 <li> <b>GMLJP2=YES/NO</b>: Indicates whether a GML box
@@ -84,8 +84,8 @@ If filename is just set to YES, a minimal instance will be built.<p>
 
 <li> <b>GeoJP2=YES/NO</b>: Indicates whether a UUID/GeoTIFF box conforming to the GeoJP2 (GeoTIFF in JPEG2000) specification should be included in the file.  Defaults to YES.<p>
 
-<li> <b>PROFILE=profile</b>: One of BASELINE_0, BASELINE_1, BASELINE_2, 
-NPJE or EPJE.  Review the ECW SDK documentation for details on profile 
+<li> <b>PROFILE=profile</b>: One of BASELINE_0, BASELINE_1, BASELINE_2,
+NPJE or EPJE.  Review the ECW SDK documentation for details on profile
 meanings.<p>
 
 <li> <b>PROGRESSION=LRCP/RLCP/RPCL</b>: Set the progression order with
@@ -96,7 +96,7 @@ imagery code stream will be written.  If NO a JP2 package
 will be written around the code stream including a variety of meta
 information. (Default, NO)<p>
 
-    
+
 <li> <b>LEVELS=n</b>: Resolution levels in pyramid (by default so many that the size of the smallest thumbnail image is 64x64 pixels at maximum)<p>
 <li> <b>LAYERS=n</b>: Quality layers (default, 1)<p>
 <li> <b>PRECINCT_WIDTH=n</b>: Precinct Width (default, 64)<p>
@@ -138,36 +138,36 @@ be written. Defaults to NO.
 
 </ul>
 
-"JPEG2000 format does not support creation of GDAL overviews since the format 
-is already considered to be optimized for "arbitrary overviews". 
-JP2ECW driver also arranges JP2 codestream to allow optimal access to power of two overviews. 
-This is controlled with the creation option LEVELS." 
+"JPEG2000 format does not support creation of GDAL overviews since the format
+is already considered to be optimized for "arbitrary overviews".
+JP2ECW driver also arranges JP2 codestream to allow optimal access to power of two overviews.
+This is controlled with the creation option LEVELS."
 <P>
 
 <h2> Configuration Options </h2>
 
-The ERDAS ECW/JP2 SDK supports a variety of 
-<a href="http://trac.osgeo.org/gdal/wiki/ConfigOptions">runtime configuration 
-options</a> to control various features.  Most of these are exposed as GDAL 
+The ERDAS ECW/JP2 SDK supports a variety of
+<a href="http://trac.osgeo.org/gdal/wiki/ConfigOptions">runtime configuration
+options</a> to control various features.  Most of these are exposed as GDAL
 configuration options.  See the ECW/JP2 SDK documentation for full details on the
-meaning of these options. 
+meaning of these options.
 
 <ul>
-<li> <b>ECW_CACHE_MAXMEM=bytes</b>: maximum bytes of RAM used for in-memory 
-caching.  If not set, up to one quarter of physical RAM will be used by the 
+<li> <b>ECW_CACHE_MAXMEM=bytes</b>: maximum bytes of RAM used for in-memory
+caching.  If not set, up to one quarter of physical RAM will be used by the
 SDK for in-memory caching.<p>
 
 <li> <b>ECW_TEXTURE_DITHER=TRUE/FALSE</b>: This may be set to FALSE to disable
 dithering when decompressing ECW files.  Defaults to TRUE.<p>
 
-<li> <b>ECW_FORCE_FILE_REOPEN=TRUE/FALSE</b>: This may be set to TRUE to 
-force open a file handle for each file for each connection made.  Defaults to 
+<li> <b>ECW_FORCE_FILE_REOPEN=TRUE/FALSE</b>: This may be set to TRUE to
+force open a file handle for each file for each connection made.  Defaults to
 FALSE.<p>
 
-<li> <b>ECW_CACHE_MAXOPEN=number</b>: The maximum number of files to keep 
+<li> <b>ECW_CACHE_MAXOPEN=number</b>: The maximum number of files to keep
 open for ECW file handle caching.  Defaults to unlimited.<p>
 
-<li> <b>ECW_AUTOGEN_J2I=TRUE/FALSE</b>: Controls whether .j2i index files 
+<li> <b>ECW_AUTOGEN_J2I=TRUE/FALSE</b>: Controls whether .j2i index files
 should be created when opening jpeg2000 files.  Defaults to TRUE.<p>
 
 <li> <b>ECW_RESILIENT_DECODING=TRUE/FALSE</b>: Controls whether the reader
diff --git a/frmts/ecw/gdal_ecw.h b/frmts/ecw/gdal_ecw.h
index 99c3b18..697a94c 100644
--- a/frmts/ecw/gdal_ecw.h
+++ b/frmts/ecw/gdal_ecw.h
@@ -1,7 +1,7 @@
 /******************************************************************************
  * $Id: ecwdataset.cpp 21486 2011-01-13 17:38:17Z warmerdam $
  *
- * Project:  GDAL 
+ * Project:  GDAL
  * Purpose:  ECW (ERDAS Wavelet Compression Format) Driver Definitions
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -42,64 +42,7 @@
 
 #ifdef FRMT_ecw
 
-// The following is needed on 4.x+ to enable rw support.
-#if defined(HAVE_COMPRESS)
-# ifndef ECW_COMPRESS_RW_SDK_VERSION
-#  define ECW_COMPRESS_RW_SDK_VERSION
-# endif
-#endif
-
-#if defined(_MSC_VER)
-#  pragma warning(disable:4800)
-#endif
-
-#include <NCSECWClient.h>
-#include <NCSECWCompressClient.h>
-#include <NCSErrors.h>
-#include <NCSFile.h>
-#include <NCSJP2FileView.h>
-
-#ifdef HAVE_ECW_BUILDNUMBER_H
-#  include <ECWJP2BuildNumber.h>
-#  if !defined(ECW_VERSION)
-#    define ECWSDK_VERSION (NCS_ECWJP2_VER_MAJOR*10+NCS_ECWJP2_VER_MINOR)
-#  endif
-#else
-/* By default, assume 3.3 SDK Version. */
-#  if !defined(ECWSDK_VERSION)
-#    define ECWSDK_VERSION 33
-#  endif
-#endif
-
-#if ECWSDK_VERSION < 40
-
-#if !defined(NO_COMPRESS) && !defined(HAVE_COMPRESS)
-#  define HAVE_COMPRESS
-#endif
-
-#else
-    #if ECWSDK_VERSION>=50
-		#if ECWSDK_VERSION>=51
-			#define JPEG2000_DOMAIN_NAME "JPEG2000"
-		#endif
-        #include <NCSECWHeaderEditor.h>
-        #include "NCSEcw/SDK/Box.h"
-    #else 
-        #include <HeaderEditor.h>
-    #endif
-#  define NCS_FASTCALL
-#endif
-
-#if ECWSDK_VERSION >= 40
-#define SDK_CAN_DO_SUPERSAMPLING 1
-#endif
-
-#ifndef NCSFILEBASE_H
-#  include <NCSJP2FileView.h>
-#else
-#  undef  CNCSJP2FileView
-#  define CNCSJP2FileView	  CNCSFile
-#endif
+#include "ecwsdk_headers.h"
 
 void ECWInitialize( void );
 GDALDataset* ECWDatasetOpenJPEG2000(GDALOpenInfo* poOpenInfo);
@@ -108,19 +51,19 @@ GDALColorInterp ECWGetColorInterpretationByName(const char *pszName);
 const char* ECWGetColorSpaceName(NCSFileColorSpace colorSpace);
 #ifdef HAVE_COMPRESS
 GDALDataset *
-ECWCreateCopyECW( const char * pszFilename, GDALDataset *poSrcDS, 
-                 int bStrict, char ** papszOptions, 
+ECWCreateCopyECW( const char * pszFilename, GDALDataset *poSrcDS,
+                 int bStrict, char ** papszOptions,
                  GDALProgressFunc pfnProgress, void * pProgressData );
 GDALDataset *
-ECWCreateCopyJPEG2000( const char * pszFilename, GDALDataset *poSrcDS, 
-                 int bStrict, char ** papszOptions, 
+ECWCreateCopyJPEG2000( const char * pszFilename, GDALDataset *poSrcDS,
+                 int bStrict, char ** papszOptions,
                  GDALProgressFunc pfnProgress, void * pProgressData );
 
 GDALDataset *
-ECWCreateECW( const char * pszFilename, int nXSize, int nYSize, int nBands, 
+ECWCreateECW( const char * pszFilename, int nXSize, int nYSize, int nBands,
               GDALDataType eType, char **papszOptions );
 GDALDataset *
-ECWCreateJPEG2000(const char *pszFilename, int nXSize, int nYSize, int nBands, 
+ECWCreateJPEG2000(const char *pszFilename, int nXSize, int nYSize, int nBands,
                   GDALDataType eType, char **papszOptions );
 #endif
 
@@ -134,7 +77,7 @@ void ECWReportError(CNCSError& oErr, const char* pszMsg = "");
 #ifdef HAVE_COMPRESS
 #if ECWSDK_VERSION>=50
 class JP2UserBox : public CNCSSDKBox {
-#else 
+#else
 class JP2UserBox : public CNCSJP2Box {
 #endif
 private:
@@ -147,20 +90,20 @@ public:
     virtual ~JP2UserBox();
 
 #if ECWSDK_VERSION >= 40
-    virtual CNCSError Parse(NCS::SDK::CFileBase &JP2File, 
+    virtual CNCSError Parse(NCS::SDK::CFileBase &JP2File,
                              NCS::CIOStream &Stream);
-    virtual CNCSError UnParse(NCS::SDK::CFileBase &JP2File, 
+    virtual CNCSError UnParse(NCS::SDK::CFileBase &JP2File,
                                 NCS::CIOStream &Stream);
-#else        
-    virtual CNCSError Parse(class CNCSJP2File &JP2File, 
+#else
+    virtual CNCSError Parse(class CNCSJP2File &JP2File,
                             CNCSJPCIOStream &Stream);
-    virtual CNCSError UnParse(class CNCSJP2File &JP2File, 
+    virtual CNCSError UnParse(class CNCSJP2File &JP2File,
                               CNCSJPCIOStream &Stream);
 #endif
     virtual void UpdateXLBox(void);
 
     void    SetData( int nDataLength, const unsigned char *pabyDataIn );
-    
+
     int     GetDataLength() { return nDataLength; }
     unsigned char *GetData() { return pabyData; }
 };
@@ -175,21 +118,24 @@ public:
 class VSIIOStream : public CNCSJPCIOStream
 
 {
-  private: 
+  private:
     char     *m_Filename;
   public:
-    
+
     INT64    startOfJPData;
     INT64    lengthOfJPData;
     VSILFILE    *fpVSIL;
     BOOLEAN      bWritable;
     BOOLEAN      bSeekable;
     int      nFileViewCount;
-    
+
     int      nCOMState;
     int      nCOMLength;
     GByte    abyCOMType[2];
 
+    /* To fix ‘virtual bool NCS::CIOStream::Read(INT64, void*, UINT32)’ was hidden' with SDK 5 */
+    using CNCSJPCIOStream::Read;
+
     VSIIOStream() : m_Filename(NULL){
         nFileViewCount = 0;
         startOfJPData = 0;
@@ -220,13 +166,13 @@ class VSIIOStream : public CNCSJPCIOStream
             fpVSIL = NULL;
         }
         return oErr;
-    }        
-        
+    }
+
 #if ECWSDK_VERSION >= 40
     virtual VSIIOStream *Clone() {
-        
+
         VSILFILE *fpNewVSIL = VSIFOpenL( m_Filename, "rb" );
-        if (fpNewVSIL == NULL) 
+        if (fpNewVSIL == NULL)
         {
             return NULL;
         }else
@@ -239,7 +185,7 @@ class VSIIOStream : public CNCSJPCIOStream
 #endif /* ECWSDK_VERSION >= 4 */
 
     CNCSError Access( VSILFILE *fpVSILIn, BOOLEAN bWrite, BOOLEAN bSeekableIn,
-                              const char *pszFilename, 
+                              const char *pszFilename,
                               INT64 start, INT64 size = -1) {
 
         fpVSIL = fpVSILIn;
@@ -250,8 +196,8 @@ class VSIIOStream : public CNCSJPCIOStream
         VSIFSeekL(fpVSIL, startOfJPData, SEEK_SET);
         m_Filename = CPLStrdup(pszFilename);
         // the filename is used to establish where to put temporary files.
-        // if it does not have a path to a real directory, we will 
-        // substitute something. 
+        // if it does not have a path to a real directory, we will
+        // substitute something.
         CPLString osFilenameUsed = pszFilename;
         CPLString osPath = CPLGetPath( pszFilename );
         struct stat sStatBuf;
@@ -266,14 +212,27 @@ class VSIIOStream : public CNCSJPCIOStream
             }
             CPLDebug( "ECW", "Using filename '%s' for temporary directory determination purposes.", osFilenameUsed.c_str() );
         }
-        return(CNCSJPCIOStream::Open((char *)osFilenameUsed.c_str(), 
-                                     (bool) bWrite));
+#ifdef WIN32
+        if( CSLTestBoolean( CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
+        {
+            wchar_t       *pwszFilename = CPLRecodeToWChar( osFilenameUsed.c_str(), CPL_ENC_UTF8, CPL_ENC_UCS2 );
+            CNCSError oError;
+            oError = CNCSJPCIOStream::Open( pwszFilename, (bool) bWrite );
+            CPLFree( pwszFilename );
+            return oError;
+        }
+        else
+#endif
+        {
+            return(CNCSJPCIOStream::Open((char *)osFilenameUsed.c_str(),
+                                        (bool) bWrite));
+        }
     }
 
     virtual bool NCS_FASTCALL Seek() {
         return bSeekable;
     }
-    
+
     virtual bool NCS_FASTCALL Seek(INT64 offset, Origin origin = CURRENT) {
         bool success = false;
         switch(origin) {
@@ -284,13 +243,13 @@ class VSIIOStream : public CNCSJPCIOStream
             case CURRENT:
               success = (0 == VSIFSeekL(fpVSIL, offset, SEEK_CUR));
               break;
-                
+
             case END:
               success = (0 == VSIFSeekL(fpVSIL, offset, SEEK_END));
               break;
         }
         if( !success )
-            CPLDebug( "ECW", "VSIIOStream::Seek(%d,%d) failed.", 
+            CPLDebug( "ECW", "VSIIOStream::Seek(%d,%d) failed.",
                       (int) offset, (int) origin );
         return(success);
     }
@@ -320,14 +279,14 @@ class VSIIOStream : public CNCSJPCIOStream
 
 //        return(1 == VSIFReadL( buffer, count, 1, fpVSIL ) );
 
-        // The following is a hack 
+        // The following is a hack
         if( VSIFReadL( buffer, count, 1, fpVSIL ) != 1 )
         {
             CPLDebug( "VSIIOSTREAM",
                       "Read(%d) failed @ " CPL_FRMT_GIB ", ignoring failure.",
                       count, (VSIFTellL( fpVSIL ) - startOfJPData) );
         }
-        
+
         return true;
     }
 
@@ -370,7 +329,7 @@ class VSIIOStream : public CNCSJPCIOStream
             }
             else
             {
-                GByte prevBuffer[] = 
+                GByte prevBuffer[] =
 		  { (GByte)(nCOMLength >> 8), (GByte) (nCOMLength & 0xff) };
                 VSIFWriteL(prevBuffer, 2, 1, fpVSIL);
                 nCOMState = 0;
@@ -389,14 +348,14 @@ class VSIIOStream : public CNCSJPCIOStream
                 nCOMState = 0;
             }
         }
-        
+
         if( 1 != VSIFWriteL(buffer, count, 1, fpVSIL) )
         {
-            CPLDebug( "ECW", "VSIIOStream::Write(%d) failed.", 
+            CPLDebug( "ECW", "VSIIOStream::Write(%d) failed.",
                       (int) count );
             return false;
         }
-        else 
+        else
             return true;
     }
 };
@@ -422,7 +381,7 @@ private:
 
     static NCSEcwReadStatus RefreshCB( NCSFileView * );
     NCSEcwReadStatus ReadToBuffer();
-    
+
 public:
     ECWAsyncReader();
     virtual ~ECWAsyncReader();
@@ -474,7 +433,7 @@ class CPL_DLL ECWDataset : public GDALJP2AbstractDataset
 
     int         bUsingCustomStream;
 
-    // Current view window. 
+    // Current view window.
     int         bWinActive;
     int         nWinXOff, nWinYOff, nWinXSize, nWinYSize;
     int         nWinBufXSize, nWinBufYSize;
@@ -510,12 +469,12 @@ class CPL_DLL ECWDataset : public GDALJP2AbstractDataset
 
     int bFileMetaDataDirty;
     void WriteFileMetaData(NCSFileMetaData* pFileMetaDataCopy);
-	
+
 #endif
 
     static CNCSJP2FileView    *OpenFileView( const char *pszDatasetName,
                                              bool bProgressive,
-                                             int &bUsingCustomStream, 
+                                             int &bUsingCustomStream,
                                              bool bWrite=false);
 
     int         bHdrDirty;
@@ -528,28 +487,28 @@ class CPL_DLL ECWDataset : public GDALJP2AbstractDataset
     int         bDatumCodeChanged;
     int         bUnitsCodeChanged;
     void        WriteHeader();
-    
+
     int         bUseOldBandRasterIOImplementation;
-    
+
     int         bPreventCopyingSomeMetadata;
 
     int         nBandIndexToPromoteTo8Bit;
 
     CPLStringList oECWMetadataList;
     CPLErr ReadBands(void * pData, int nBufXSize, int nBufYSize,
-                    GDALDataType eBufType, 
+                    GDALDataType eBufType,
                     int nBandCount,
                     GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace,
                     GDALRasterIOExtraArg* psExtraArg);
     CPLErr ReadBandsDirectly(void * pData, int nBufXSize, int nBufYSize,
-                    GDALDataType eBufType, 
+                    GDALDataType eBufType,
                     int nBandCount,
                     GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace,
                     GDALRasterIOExtraArg* psExtraArg);
   public:
         ECWDataset(int bIsJPEG2000);
         ~ECWDataset();
-                
+
     static GDALDataset *Open( GDALOpenInfo *, int bIsJPEG2000 );
     static int          IdentifyJPEG2000( GDALOpenInfo * poOpenInfo );
     static GDALDataset *OpenJPEG2000( GDALOpenInfo * );
@@ -579,15 +538,15 @@ class CPL_DLL ECWDataset : public GDALJP2AbstractDataset
                              const char * pszDomain = "" );
 
     virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
-                               int nBufXSize, int nBufYSize, 
-                               GDALDataType eDT, 
+                               int nBufXSize, int nBufYSize,
+                               GDALDataType eDT,
                                int nBandCount, int *panBandList,
                                char **papszOptions );
 
     // progressive methods
 #if ECWSDK_VERSION >= 40
     virtual GDALAsyncReader* BeginAsyncReader( int nXOff, int nYOff,
-                                               int nXSize, int nYSize, 
+                                               int nXSize, int nYSize,
                                                void *pBuf,
                                                int nBufXSize, int nBufYSize,
                                                GDALDataType eBufType,
@@ -614,13 +573,13 @@ class CPL_DLL ECWDataset : public GDALJP2AbstractDataset
 class ECWRasterBand : public GDALPamRasterBand
 {
     friend class ECWDataset;
-    
+
     // NOTE: poDS may be altered for NITF/JPEG2000 files!
     ECWDataset     *poGDS;
 
     GDALColorInterp         eBandInterp;
 
-    int                          iOverview; // -1 for base. 
+    int                          iOverview; // -1 for base.
 
     std::vector<ECWRasterBand*>  apoOverviews;
 
@@ -659,7 +618,7 @@ class ECWRasterBand : public GDALPamRasterBand
     virtual CPLErr SetColorInterpretation( GDALColorInterp );
 
     virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
-                               int nBufXSize, int nBufYSize, 
+                               int nBufXSize, int nBufYSize,
                                GDALDataType eDT, char **papszOptions );
 #if ECWSDK_VERSION >= 50
     void GetBandIndexAndCountForStatistics(int &bandIndex, int &bandCount);
@@ -672,9 +631,9 @@ class ECWRasterBand : public GDALPamRasterBand
     virtual double GetMinimum( int* pbSuccess );
     virtual double GetMaximum( int* pbSuccess );
     virtual CPLErr GetStatistics( int bApproxOK, int bForce,
-                                  double *pdfMin, double *pdfMax, 
+                                  double *pdfMin, double *pdfMax,
                                   double *pdfMean, double *padfStdDev );
-    virtual CPLErr SetStatistics( double dfMin, double dfMax, 
+    virtual CPLErr SetStatistics( double dfMin, double dfMax,
                                   double dfMean, double dfStdDev );
 #endif
 
diff --git a/frmts/ecw/jp2userbox.cpp b/frmts/ecw/jp2userbox.cpp
index 913164b..cfe9e95 100644
--- a/frmts/ecw/jp2userbox.cpp
+++ b/frmts/ecw/jp2userbox.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: jp2userbox.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: jp2userbox.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  GDAL ECW Driver
  * Purpose:  JP2UserBox implementation - arbitrary box read/write.
@@ -29,7 +29,7 @@
 
 #include "gdal_ecw.h"
 
-CPL_CVSID("$Id: jp2userbox.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: jp2userbox.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 #if defined(HAVE_COMPRESS)
 
@@ -101,7 +101,7 @@ CNCSError JP2UserBox::Parse( CPL_UNUSED class CNCSJP2File &JP2File,
                              CPL_UNUSED CNCSJPCIOStream &Stream )
 #endif
 {
-    CNCSError Error = NCS_SUCCESS;
+    CNCSError Error(GetCNCSError(NCS_SUCCESS));
 
     return Error;
 }
@@ -113,25 +113,25 @@ CNCSError JP2UserBox::Parse( CPL_UNUSED class CNCSJP2File &JP2File,
 /************************************************************************/
 
 #if ECWSDK_VERSION >= 40
-CNCSError JP2UserBox::UnParse( NCS::SDK::CFileBase &JP2File, 
+CNCSError JP2UserBox::UnParse( NCS::SDK::CFileBase &JP2File,
                                NCS::CIOStream &Stream )
 #else
-CNCSError JP2UserBox::UnParse( class CNCSJP2File &JP2File, 
+CNCSError JP2UserBox::UnParse( class CNCSJP2File &JP2File,
                                CNCSJPCIOStream &Stream )
 #endif
 {
-    CNCSError Error = NCS_SUCCESS;
+    CNCSError Error(GetCNCSError(NCS_SUCCESS));
 
     if( m_nTBox == 0 )
     {
-        Error = NCS_UNKNOWN_ERROR;
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        Error = GetCNCSError(NCS_UNKNOWN_ERROR);
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "No box type set in JP2UserBox::UnParse()" );
         return Error;
     }
 #if ECWSDK_VERSION<50
     Error = CNCSJP2Box::UnParse(JP2File, Stream);
-#else 
+#else
     Error = CNCSSDKBox::UnParse(JP2File, Stream);
 #endif
 //    NCSJP2_CHECKIO_BEGIN(Error, Stream);
diff --git a/frmts/elas/elasdataset.cpp b/frmts/elas/elasdataset.cpp
index 38a10ec..0df1720 100644
--- a/frmts/elas/elasdataset.cpp
+++ b/frmts/elas/elasdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: elasdataset.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: elasdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  ELAS Translator
  * Purpose:  Complete implementation of ELAS translator module for GDAL.
@@ -28,20 +28,23 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: elasdataset.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+#include <algorithm>
 
-CPL_C_START
-void	GDALRegister_ELAS(void);
-CPL_C_END
+using std::fill;
 
-typedef struct {
-    GInt32	NBIH;	/* bytes in header, normaly 1024 */
+CPL_CVSID("$Id: elasdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+
+typedef struct ELASHeader {
+    ELASHeader();
+
+    GInt32      NBIH;   /* bytes in header, normally 1024 */
     GInt32      NBPR;	/* bytes per data record (all bands of scanline) */
     GInt32	IL;	/* initial line - normally 1 */
     GInt32	LL;	/* last line */
-    GInt32	IE;	/* initial element (pixel), normally 1 */
+    GInt32      IE;     /* initial element (pixel), normally 1 */
     GInt32	LE;	/* last element (pixel) */
     GInt32	NC;	/* number of channels (bands) */
     GInt32	H4321;	/* header record identifier - always 4321. */
@@ -67,8 +70,39 @@ typedef struct {
     char	Comment6[64];
     GUInt16	ColorTable[256];  /* RGB packed with 4 bits each */
     char	unused2[32];
-} ELASHeader;
-
+} _ELASHeader;
+
+ELASHeader::ELASHeader() :
+    NBIH(0),
+    NBPR(0),
+    IL(0),
+    LL(0),
+    IE(0),
+    LE(0),
+    NC(0),
+    H4321(0),
+    YOffset(0),
+    XOffset(0),
+    YPixSize(0.0),
+    XPixSize(0.0),
+    IH20(0),
+    LABL(0),
+    HEAD(0)
+{
+    fill( YLabel, YLabel + CPL_ARRAYSIZE(YLabel), 0 );
+    fill( XLabel, XLabel + CPL_ARRAYSIZE(XLabel), 0 );
+    fill( Matrix, Matrix + CPL_ARRAYSIZE(Matrix), 0.f );
+    fill( IH19, IH19 + CPL_ARRAYSIZE(IH19), 0 );
+    fill( unused1, unused1 + CPL_ARRAYSIZE(unused1), 0 );
+    fill( Comment1, Comment1 + CPL_ARRAYSIZE(Comment1), 0 );
+    fill( Comment2, Comment2 + CPL_ARRAYSIZE(Comment2), 0 );
+    fill( Comment3, Comment3 + CPL_ARRAYSIZE(Comment3), 0 );
+    fill( Comment4, Comment4 + CPL_ARRAYSIZE(Comment4), 0 );
+    fill( Comment5, Comment5 + CPL_ARRAYSIZE(Comment5), 0 );
+    fill( Comment6, Comment6 + CPL_ARRAYSIZE(Comment6), 0 );
+    fill( ColorTable, ColorTable + CPL_ARRAYSIZE(ColorTable), 0 );
+    fill( unused2, unused2 + CPL_ARRAYSIZE(unused2), 0 );
+}
 
 /************************************************************************/
 /* ==================================================================== */
@@ -91,7 +125,7 @@ class ELASDataset : public GDALPamDataset
 
     int		nLineOffset;
     int		nBandOffset;     // within a line.
-    
+
     double	adfGeoTransform[6];
 
   public:
@@ -125,9 +159,9 @@ class ELASRasterBand : public GDALPamRasterBand
                    ELASRasterBand( ELASDataset *, int );
 
     // should override RasterIO eventually.
-    
+
     virtual CPLErr IReadBlock( int, int, void * );
-    virtual CPLErr IWriteBlock( int, int, void * ); 
+    virtual CPLErr IWriteBlock( int, int, void * );
 };
 
 
@@ -135,15 +169,15 @@ class ELASRasterBand : public GDALPamRasterBand
 /*                           ELASRasterBand()                            */
 /************************************************************************/
 
-ELASRasterBand::ELASRasterBand( ELASDataset *poDS, int nBand )
+ELASRasterBand::ELASRasterBand( ELASDataset *poDSIn, int nBandIn )
 
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
 
-    this->eAccess = poDS->eAccess;
+    this->eAccess = poDSIn->eAccess;
 
-    eDataType = poDS->eRasterDataType;
+    eDataType = poDSIn->eRasterDataType;
 
     nBlockXSize = poDS->GetRasterXSize();
     nBlockYSize = 1;
@@ -157,16 +191,13 @@ CPLErr ELASRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                                    int nBlockYOff,
                                    void * pImage )
 {
+    CPLAssert( nBlockXOff == 0 );
+
     ELASDataset	*poGDS = (ELASDataset *) poDS;
-    CPLErr		eErr = CE_None;
-    long		nOffset;
-    int			nDataSize;
 
-    CPLAssert( nBlockXOff == 0 );
+    int nDataSize = GDALGetDataTypeSize(eDataType) * poGDS->GetRasterXSize() / 8;
+    long nOffset = poGDS->nLineOffset * nBlockYOff + 1024 + (nBand-1) * nDataSize;
 
-    nDataSize = GDALGetDataTypeSize(eDataType) * poGDS->GetRasterXSize() / 8;
-    nOffset = poGDS->nLineOffset * nBlockYOff + 1024 + (nBand-1) * nDataSize;
-    
 /* -------------------------------------------------------------------- */
 /*      If we can't seek to the data, we will assume this is a newly    */
 /*      created file, and that the file hasn't been extended yet.       */
@@ -178,10 +209,10 @@ CPLErr ELASRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
         CPLError( CE_Failure, CPLE_FileIO,
                   "Seek or read of %d bytes at %ld failed.\n",
                   nDataSize, nOffset );
-        eErr = CE_Failure;
+        return CE_Failure;
     }
 
-    return eErr;
+    return CE_None;
 }
 
 /************************************************************************/
@@ -192,27 +223,24 @@ CPLErr ELASRasterBand::IWriteBlock( CPL_UNUSED int nBlockXOff,
                                     int nBlockYOff,
                                     void * pImage )
 {
-    ELASDataset	*poGDS = (ELASDataset *) poDS;
-    CPLErr		eErr = CE_None;
-    long		nOffset;
-    int			nDataSize;
-
     CPLAssert( nBlockXOff == 0 );
     CPLAssert( eAccess == GA_Update );
 
-    nDataSize = GDALGetDataTypeSize(eDataType) * poGDS->GetRasterXSize() / 8;
-    nOffset = poGDS->nLineOffset * nBlockYOff + 1024 + (nBand-1) * nDataSize;
-    
+    ELASDataset	*poGDS = (ELASDataset *) poDS;
+
+    int nDataSize = GDALGetDataTypeSize(eDataType) * poGDS->GetRasterXSize() / 8;
+    long nOffset = poGDS->nLineOffset * nBlockYOff + 1024 + (nBand-1) * nDataSize;
+
     if( VSIFSeekL( poGDS->fp, nOffset, SEEK_SET ) != 0
         || VSIFWriteL( pImage, 1, nDataSize, poGDS->fp ) != (size_t) nDataSize )
     {
         CPLError( CE_Failure, CPLE_FileIO,
                   "Seek or write of %d bytes at %ld failed.\n",
                   nDataSize, nOffset );
-        eErr = CE_Failure;
+        return CE_Failure;
     }
 
-    return eErr;
+    return CE_None;
 }
 
 /************************************************************************/
@@ -226,11 +254,13 @@ CPLErr ELASRasterBand::IWriteBlock( CPL_UNUSED int nBlockXOff,
 /*                            ELASDataset()                             */
 /************************************************************************/
 
-ELASDataset::ELASDataset()
-
+ELASDataset::ELASDataset() :
+    fp(NULL),
+    bHeaderModified(0),
+    eRasterDataType(GDT_Unknown),
+    nLineOffset(0),
+    nBandOffset(0)
 {
-    fp = NULL;
-
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
@@ -250,8 +280,7 @@ ELASDataset::~ELASDataset()
 
     if( fp != NULL )
     {
-        VSIFCloseL( fp );
-        fp = NULL;
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
     }
 }
 
@@ -268,8 +297,8 @@ void ELASDataset::FlushCache()
 
     if( bHeaderModified )
     {
-        VSIFSeekL( fp, 0, SEEK_SET );
-        VSIFWriteL( &sHeader, 1024, 1, fp );
+        CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 0, SEEK_SET ));
+        CPL_IGNORE_RET_VAL(VSIFWriteL( &sHeader, 1024, 1, fp ));
         bHeaderModified = FALSE;
     }
 }
@@ -310,21 +339,20 @@ GDALDataset *ELASDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    ELASDataset 	*poDS;
-    const char	 	*pszAccess;
+    const char *pszAccess;
 
     if( poOpenInfo->eAccess == GA_Update )
         pszAccess = "r+b";
     else
         pszAccess = "rb";
 
-    poDS = new ELASDataset();
+    ELASDataset *poDS = new ELASDataset();
 
     poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, pszAccess );
     if( poDS->fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Attempt to open `%s' with acces `%s' failed.\n",
+                  "Attempt to open `%s' with access `%s' failed.\n",
                   poOpenInfo->pszFilename, pszAccess );
         delete poDS;
         return NULL;
@@ -341,18 +369,17 @@ GDALDataset *ELASDataset::Open( GDALOpenInfo * poOpenInfo )
         CPLError( CE_Failure, CPLE_FileIO,
                   "Attempt to read 1024 byte header filed on file %s\n",
                   poOpenInfo->pszFilename );
+        delete poDS;
         return NULL;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Extract information of interest from the header.                */
 /* -------------------------------------------------------------------- */
-    int		nStart, nEnd, nELASDataType, nBytesPerSample;
-    
     poDS->nLineOffset = CPL_MSBWORD32( poDS->sHeader.NBPR );
 
-    nStart = CPL_MSBWORD32( poDS->sHeader.IL );
-    nEnd = CPL_MSBWORD32( poDS->sHeader.LL );
+    int nStart = CPL_MSBWORD32( poDS->sHeader.IL );
+    int nEnd = CPL_MSBWORD32( poDS->sHeader.LL );
     poDS->nRasterYSize = nEnd - nStart + 1;
 
     nStart = CPL_MSBWORD32( poDS->sHeader.IE );
@@ -368,9 +395,9 @@ GDALDataset *ELASDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    nELASDataType = (poDS->sHeader.IH19[2] & 0x7e) >> 2;
-    nBytesPerSample = poDS->sHeader.IH19[3];
-    
+    const int nELASDataType = (poDS->sHeader.IH19[2] & 0x7e) >> 2;
+    const int nBytesPerSample = poDS->sHeader.IH19[3];
+
     if( nELASDataType == 0 && nBytesPerSample == 1 )
         poDS->eRasterDataType = GDT_Byte;
     else if( nELASDataType == 1 && nBytesPerSample == 1 )
@@ -383,11 +410,11 @@ GDALDataset *ELASDataset::Open( GDALOpenInfo * poOpenInfo )
     {
         delete poDS;
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unrecognised image data type %d, with BytesPerSample=%d.\n",
+                  "Unrecognized image data type %d, with BytesPerSample=%d.\n",
                   nELASDataType, nBytesPerSample );
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*	Band offsets are always multiples of 256 within a multi-band	*/
 /*	scanline of data.						*/
@@ -404,9 +431,8 @@ GDALDataset *ELASDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    int		iBand;
-
-    for( iBand = 0; iBand < poDS->nBands; iBand++ )
+    /* coverity[tainted_data] */
+    for( int iBand = 0; iBand < poDS->nBands; iBand++ )
     {
         poDS->SetBand( iBand+1, new ELASRasterBand( poDS, iBand+1 ) );
     }
@@ -443,7 +469,7 @@ GDALDataset *ELASDataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->adfGeoTransform[4] = 0.0;
         poDS->adfGeoTransform[5] = 1.0;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
@@ -470,14 +496,12 @@ GDALDataset *ELASDataset::Create( const char * pszFilename,
                                   char ** /* notdef: papszParmList */ )
 
 {
-    int		nBandOffset;
-    
 /* -------------------------------------------------------------------- */
 /*      Verify input options.                                           */
 /* -------------------------------------------------------------------- */
     if (nBands <= 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "ELAS driver does not support %d bands.\n", nBands);
         return NULL;
     }
@@ -495,9 +519,7 @@ GDALDataset *ELASDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Try to create the file.                                         */
 /* -------------------------------------------------------------------- */
-    FILE	*fp;
-
-    fp = VSIFOpen( pszFilename, "w" );
+    FILE *fp = VSIFOpen( pszFilename, "w" );
 
     if( fp == NULL )
     {
@@ -506,11 +528,11 @@ GDALDataset *ELASDataset::Create( const char * pszFilename,
                   pszFilename );
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*	How long will each band of a scanline be?			*/
 /* -------------------------------------------------------------------- */
-    nBandOffset = nXSize * GDALGetDataTypeSize(eType)/8;
+    int nBandOffset = nXSize * GDALGetDataTypeSize(eType)/8;
 
     if( nBandOffset % 256 != 0 )
     {
@@ -530,7 +552,7 @@ GDALDataset *ELASDataset::Create( const char * pszFilename,
     sHeader.NBIH = CPL_MSBWORD32(1024);
 
     sHeader.NBPR = CPL_MSBWORD32(nBands * nBandOffset);
-    
+
     sHeader.IL = CPL_MSBWORD32(1);
     sHeader.LL = CPL_MSBWORD32(nYSize);
 
@@ -555,15 +577,13 @@ GDALDataset *ELASDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Write the header data.                                          */
 /* -------------------------------------------------------------------- */
-    VSIFWrite( &sHeader, 1024, 1, fp );
+    CPL_IGNORE_RET_VAL(VSIFWrite( &sHeader, 1024, 1, fp ));
 
 /* -------------------------------------------------------------------- */
 /*      Now write out zero data for all the imagery.  This is           */
 /*      inefficient, but simplies the IReadBlock() / IWriteBlock() logic.*/
 /* -------------------------------------------------------------------- */
-    GByte	*pabyLine;
-
-    pabyLine = (GByte *) CPLCalloc(nBandOffset,nBands);
+    GByte *pabyLine = (GByte *) CPLCalloc(nBandOffset,nBands);
     for( int iLine = 0; iLine < nYSize; iLine++ )
     {
         if( VSIFWrite( pabyLine, 1, nBandOffset, fp ) != (size_t) nBandOffset )
@@ -578,7 +598,7 @@ GDALDataset *ELASDataset::Create( const char * pszFilename,
     }
 
     CPLFree( pabyLine );
-    
+
     VSIFClose( fp );
 
 /* -------------------------------------------------------------------- */
@@ -619,18 +639,16 @@ CPLErr ELASDataset::SetGeoTransform( double * padfTransform )
 
         return CE_Failure;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Remember the new transform, and update the header.              */
 /* -------------------------------------------------------------------- */
-    int		nXOff, nYOff;
-    
     memcpy( adfGeoTransform, padfTransform, sizeof(double)*6 );
 
     bHeaderModified = TRUE;
 
-    nXOff = (int) (adfGeoTransform[0] + adfGeoTransform[1]*0.5);
-    nYOff = (int) (adfGeoTransform[3] + adfGeoTransform[5]*0.5);
+    const int nXOff = (int) (adfGeoTransform[0] + adfGeoTransform[1]*0.5);
+    const int nYOff = (int) (adfGeoTransform[3] + adfGeoTransform[5]*0.5);
 
     sHeader.XOffset = CPL_MSBWORD32(nXOff);
     sHeader.YOffset = CPL_MSBWORD32(nYOff);
@@ -641,49 +659,47 @@ CPLErr ELASDataset::SetGeoTransform( double * padfTransform )
     CPL_MSBPTR32(&(sHeader.XPixSize));
     CPL_MSBPTR32(&(sHeader.YPixSize));
 
-    strncpy( sHeader.YLabel, "NOR ", 4 );
-    strncpy( sHeader.XLabel, "EAS ", 4 );
+    memcpy( sHeader.YLabel, "NOR ", 4 );
+    memcpy( sHeader.XLabel, "EAS ", 4 );
 
     sHeader.Matrix[0] = 1.0;
     sHeader.Matrix[1] = 0.0;
     sHeader.Matrix[2] = 0.0;
     sHeader.Matrix[3] = -1.0;
-    
+
     CPL_MSBPTR32(&(sHeader.Matrix[0]));
     CPL_MSBPTR32(&(sHeader.Matrix[1]));
     CPL_MSBPTR32(&(sHeader.Matrix[2]));
     CPL_MSBPTR32(&(sHeader.Matrix[3]));
-    
+
     return( CE_None );
 }
 
 
 /************************************************************************/
-/*                          GDALRegister_ELAS()                        */
+/*                          GDALRegister_ELAS()                         */
 /************************************************************************/
 
 void GDALRegister_ELAS()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "ELAS" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "ELAS" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "ELAS" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "ELAS" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte Float32 Float64" );
-
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = ELASDataset::Open;
-        poDriver->pfnIdentify = ELASDataset::Identify;
-        poDriver->pfnCreate = ELASDataset::Create;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "ELAS" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "ELAS" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte Float32 Float64" );
+
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = ELASDataset::Open;
+    poDriver->pfnIdentify = ELASDataset::Identify;
+    poDriver->pfnCreate = ELASDataset::Create;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/elas/frmt_elas.html b/frmts/elas/frmt_elas.html
index aeeba31..ff82e4a 100644
--- a/frmts/elas/frmt_elas.html
+++ b/frmts/elas/frmt_elas.html
@@ -7,7 +7,7 @@
 
 <h1>ELAS - Earth Resources Laboratory Applications Software</h1>
 
-<p>ELAS is an old remote sensing system still used for a variety of research projects within NASA. 
+<p>ELAS is an old remote sensing system still used for a variety of research projects within NASA.
 The ELAS format support can be found in gdal/frmts/elas.</p>
 
 <p>See Also:</p>
diff --git a/frmts/envisat/EnvisatFile.c b/frmts/envisat/EnvisatFile.c
index c5fa90d..0232ef5 100644
--- a/frmts/envisat/EnvisatFile.c
+++ b/frmts/envisat/EnvisatFile.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: EnvisatFile.c 29670 2015-08-19 17:00:51Z kyle $
+ * $Id: EnvisatFile.c 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  APP ENVISAT Support
  * Purpose:  Low Level Envisat file access (read/write) API.
@@ -35,14 +35,17 @@
 #  include "cpl_conv.h"
 #  include "EnvisatFile.h"
 
-CPL_CVSID("$Id: EnvisatFile.c 29670 2015-08-19 17:00:51Z kyle $");
+CPL_CVSID("$Id: EnvisatFile.c 33720 2016-03-15 00:39:53Z goatbar $");
 
 #else
 #  include "APP/app.h"
 #  include "util/Files/EnvisatFile.h"
 #endif
 
-typedef struct 
+CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused) {}
+CPL_INLINE static void CPL_IGNORE_RET_VAL_SIZET(CPL_UNUSED size_t unused) {}
+
+typedef struct
 {
     char	*ds_name;
     char	*ds_type;
@@ -57,6 +60,7 @@ typedef struct
 {
     char	*key;
     char	*value;
+    size_t      value_len;
     char	*units;
     char	*literal_line;
     int         value_offset;
@@ -91,20 +95,20 @@ struct EnvisatFile_tag
 /*
  * API For handling name/value lists.
  */
-int S_NameValueList_Parse( const char *text, int text_offset, 
-                           int *entry_count, 
+int S_NameValueList_Parse( const char *text, int text_offset,
+                           int *entry_count,
                            EnvisatNameValue ***entries );
-void S_NameValueList_Destroy( int *entry_count, 
+void S_NameValueList_Destroy( int *entry_count,
                              EnvisatNameValue ***entries );
 int S_NameValueList_FindKey( const char *key,
-                             int entry_count, 
+                             int entry_count,
                              EnvisatNameValue **entries );
 const char *S_NameValueList_FindValue( const char *key,
-                                       int entry_count, 
+                                       int entry_count,
                                        EnvisatNameValue **entries,
                                        const char * default_value );
 
-int S_NameValueList_Rewrite( VSILFILE *fp, int entry_count, 
+int S_NameValueList_Rewrite( VSILFILE *fp, int entry_count,
                              EnvisatNameValue **entries );
 
 EnvisatNameValue *
@@ -121,7 +125,7 @@ Name:
     Envisat_SetupLevel0
 
 Purpose:
-    Patch up missing information about SPH, and datasets for incomplete 
+    Patch up missing information about SPH, and datasets for incomplete
     level 0 signal datasets.
 
 Description:
@@ -145,24 +149,24 @@ static int EnvisatFile_SetupLevel0( EnvisatFile *self )
 
     self->dsd_offset = 0;
     self->ds_count = 1;
-    self->ds_info = (EnvisatDatasetInfo **) 
+    self->ds_info = (EnvisatDatasetInfo **)
         CPLCalloc(sizeof(EnvisatDatasetInfo*),self->ds_count);
 
     if( self->ds_info == NULL )
         return FAILURE;
 
     /*
-     * Figure out how long the file is. 
+     * Figure out how long the file is.
      */
 
-    VSIFSeekL( self->fp, 0, SEEK_END );
+    CPL_IGNORE_RET_VAL_INT(VSIFSeekL( self->fp, 0, SEEK_END ));
     file_length = (int) VSIFTellL( self->fp );
-    
-    /* 
+
+    /*
      * Read the first record header, and verify the well known values.
      */
-    VSIFSeekL( self->fp, 3203, SEEK_SET );
-    VSIFReadL( header, 68, 1, self->fp );
+    CPL_IGNORE_RET_VAL_INT(VSIFSeekL( self->fp, 3203, SEEK_SET ));
+    CPL_IGNORE_RET_VAL_SIZET(VSIFReadL( header, 68, 1, self->fp ));
 
     if( header[38] != 0 || header[39] != 0x1d
         || header[40] != 0 || header[41] != 0x54 )
@@ -172,11 +176,11 @@ static int EnvisatFile_SetupLevel0( EnvisatFile *self )
         return FAILURE;
     }
 
-    /* 
-     * Then build the dataset into structure from that. 
+    /*
+     * Then build the dataset into structure from that.
      */
     ds_info = (EnvisatDatasetInfo *) CPLCalloc(sizeof(EnvisatDatasetInfo),1);
-    
+
     ds_info->ds_name = CPLStrdup( "ASAR SOURCE PACKETS         " );
     ds_info->ds_type = CPLStrdup("M");
     ds_info->filename = CPLStrdup("                                                              ");
@@ -184,7 +188,7 @@ static int EnvisatFile_SetupLevel0( EnvisatFile *self )
     ds_info->dsr_size = -1;
     ds_info->num_dsr = 0;
     ds_info->ds_size = file_length - ds_info->ds_offset;
-    
+
     self->ds_info[0] = ds_info;
 
     return SUCCESS;
@@ -212,8 +216,8 @@ Returns:
 
 -----------------------------------------------------------------------------*/
 
-int EnvisatFile_Open( EnvisatFile **self_ptr, 
-                      const char *filename, 
+int EnvisatFile_Open( EnvisatFile **self_ptr,
+                      const char *filename,
                       const char *mode )
 
 {
@@ -241,7 +245,7 @@ int EnvisatFile_Open( EnvisatFile **self_ptr,
     }
 
     /*
-     * Try to open the file, and report failure. 
+     * Try to open the file, and report failure.
      */
 
     fp = VSIFOpenL( filename, mode );
@@ -250,8 +254,8 @@ int EnvisatFile_Open( EnvisatFile **self_ptr,
     {
         char	error_buf[2048];
 
-        sprintf( error_buf, 
-                 "Unable to open file \"%s\" in EnvisatFile_Open().", 
+        snprintf( error_buf, sizeof(error_buf),
+                 "Unable to open file \"%s\" in EnvisatFile_Open().",
                  filename );
 
         SendError( error_buf );
@@ -259,7 +263,7 @@ int EnvisatFile_Open( EnvisatFile **self_ptr,
     }
 
     /*
-     * Create, and initialize the EnvisatFile structure. 
+     * Create, and initialize the EnvisatFile structure.
      */
     self = (EnvisatFile *) CPLCalloc(sizeof(EnvisatFile),1);
     if( self == NULL )
@@ -271,7 +275,7 @@ int EnvisatFile_Open( EnvisatFile **self_ptr,
     self->updatable = (strcmp(mode,"rb+") == 0);
 
     /*
-     * Read the MPH, and process it as a group of name/value pairs. 
+     * Read the MPH, and process it as a group of name/value pairs.
      */
 
     if( VSIFReadL( mph_data, 1, MPH_SIZE, fp ) != MPH_SIZE )
@@ -282,17 +286,19 @@ int EnvisatFile_Open( EnvisatFile **self_ptr,
     }
 
     mph_data[MPH_SIZE] = '\0';
-    if( S_NameValueList_Parse( mph_data, 0, 
-                               &(self->mph_count), 
+    if( S_NameValueList_Parse( mph_data, 0,
+                               &(self->mph_count),
                                &(self->mph_entries) ) == FAILURE )
+    {
+        CPLFree( self );
         return FAILURE;
+    }
 
     /*
      * Is this an incomplete level 0 file?
      */
-    if( EnvisatFile_GetKeyValueAsInt( self, MPH, "SPH_SIZE", -1 ) == 0 
-        && strncmp(EnvisatFile_GetKeyValueAsString( self, MPH, "PRODUCT", ""),
-                   "ASA_IM__0P", 10) == 0 )
+    if( EnvisatFile_GetKeyValueAsInt( self, MPH, "SPH_SIZE", -1 ) == 0
+        && STARTS_WITH(EnvisatFile_GetKeyValueAsString( self, MPH, "PRODUCT", ""), "ASA_IM__0P") )
     {
 
         if( EnvisatFile_SetupLevel0( self ) == FAILURE )
@@ -308,14 +314,15 @@ int EnvisatFile_Open( EnvisatFile **self_ptr,
     }
 
     /*
-     * Read the SPH, and process it as a group of name/value pairs.  
+     * Read the SPH, and process it as a group of name/value pairs.
      */
     sph_size = EnvisatFile_GetKeyValueAsInt( self, MPH, "SPH_SIZE", 0 );
 
-    if( sph_size == 0 )							
+    if( sph_size == 0 )
     {
         SendError( "File does not appear to have SPH,"
                    " SPH_SIZE not set, or zero." );
+        CPLFree( self );
         return FAILURE;
     }
 
@@ -339,26 +346,33 @@ int EnvisatFile_Open( EnvisatFile **self_ptr,
     }
 
     if( S_NameValueList_Parse( sph_data, MPH_SIZE,
-                               &(self->sph_count), 
+                               &(self->sph_count),
                                &(self->sph_entries) ) == FAILURE )
+    {
+        CPLFree( self );
         return FAILURE;
+    }
 
     /*
      * Parse the Dataset Definitions.
      */
     num_dsd = EnvisatFile_GetKeyValueAsInt( self, MPH, "NUM_DSD", 0 );
     dsd_size = EnvisatFile_GetKeyValueAsInt( self, MPH, "DSD_SIZE", 0 );
-    
+
     if( num_dsd > 0 && ds_data == NULL )
     {
         SendError( "DSDs indicated in MPH, but not found in SPH." );
+        CPLFree( self );
         return FAILURE;
     }
 
-    self->ds_info = (EnvisatDatasetInfo **) 
+    self->ds_info = (EnvisatDatasetInfo **)
         CPLCalloc(sizeof(EnvisatDatasetInfo*),num_dsd);
     if( self->ds_info == NULL )
+    {
+        CPLFree( self );
         return FAILURE;
+    }
 
     for( i = 0; i < num_dsd; i++ )
     {
@@ -368,40 +382,43 @@ int EnvisatFile_Open( EnvisatFile **self_ptr,
         EnvisatDatasetInfo *ds_info;
 
         /*
-         * We parse each DSD grouping into a name/value list. 
+         * We parse each DSD grouping into a name/value list.
          */
         dsd_data = ds_data + i * dsd_size;
         dsd_data[dsd_size-1] = '\0';
-        
-        if( S_NameValueList_Parse( dsd_data, 0, 
+
+        if( S_NameValueList_Parse( dsd_data, 0,
                                    &dsdh_count, &dsdh_entries ) == FAILURE )
+        {
+            CPLFree( self );
             return FAILURE;
+        }
 
-        /* 
-         * Then build the dataset into structure from that. 
+        /*
+         * Then build the dataset into structure from that.
          */
         ds_info = (EnvisatDatasetInfo *) CPLCalloc(sizeof(EnvisatDatasetInfo),1);
 
         ds_info->ds_name = CPLStrdup(
-            S_NameValueList_FindValue( "DS_NAME", 
+            S_NameValueList_FindValue( "DS_NAME",
                                        dsdh_count, dsdh_entries, "" ));
         ds_info->ds_type = CPLStrdup(
-            S_NameValueList_FindValue( "DS_TYPE", 
+            S_NameValueList_FindValue( "DS_TYPE",
                                        dsdh_count, dsdh_entries, "" ));
         ds_info->filename = CPLStrdup(
-            S_NameValueList_FindValue( "FILENAME", 
+            S_NameValueList_FindValue( "FILENAME",
                                        dsdh_count, dsdh_entries, "" ));
         ds_info->ds_offset = atoi(
-            S_NameValueList_FindValue( "DS_OFFSET", 
+            S_NameValueList_FindValue( "DS_OFFSET",
                                        dsdh_count, dsdh_entries, "0" ));
         ds_info->ds_size = atoi(
-            S_NameValueList_FindValue( "DS_SIZE", 
+            S_NameValueList_FindValue( "DS_SIZE",
                                        dsdh_count, dsdh_entries, "0" ));
         ds_info->num_dsr = atoi(
-            S_NameValueList_FindValue( "NUM_DSR", 
+            S_NameValueList_FindValue( "NUM_DSR",
                                        dsdh_count, dsdh_entries, "0" ));
         ds_info->dsr_size = atoi(
-            S_NameValueList_FindValue( "DSR_SIZE", 
+            S_NameValueList_FindValue( "DSR_SIZE",
                                        dsdh_count, dsdh_entries, "0" ));
 
         S_NameValueList_Destroy( &dsdh_count, &dsdh_entries );
@@ -409,7 +426,7 @@ int EnvisatFile_Open( EnvisatFile **self_ptr,
         self->ds_info[i] = ds_info;
         self->ds_count++;
     }
-    
+
     CPLFree( sph_data );
 
     /*
@@ -432,7 +449,7 @@ Description:
 
 Inputs:
     filename -- name of Envisat file.
-    template_file -- name of envisat file header to utilize as template. 
+    template_file -- name of envisat file header to utilize as template.
 
 Outputs:
     self -- file handle, NULL on FAILURE.
@@ -442,8 +459,8 @@ Returns:
 
 -----------------------------------------------------------------------------*/
 
-int EnvisatFile_Create( EnvisatFile **self_ptr, 
-                        const char *filename, 
+int EnvisatFile_Create( EnvisatFile **self_ptr,
+                        const char *filename,
                         const char *template_file )
 
 {
@@ -461,49 +478,49 @@ int EnvisatFile_Create( EnvisatFile **self_ptr,
     {
         char	error_buf[2048];
 
-        sprintf( error_buf, 
-                 "Unable to open file \"%s\" in EnvisatFile_Create().", 
+        snprintf( error_buf, sizeof(error_buf),
+                 "Unable to open file \"%s\" in EnvisatFile_Create().",
                  template_file );
 
         SendError( error_buf );
         return FAILURE;
     }
 
-    VSIFSeekL( fp, 0, SEEK_END );
+    CPL_IGNORE_RET_VAL_INT(VSIFSeekL( fp, 0, SEEK_END ));
     template_size = (int) VSIFTellL( fp );
 
     template_data = (char *) CPLMalloc(template_size);
-    
-    VSIFSeekL( fp, 0, SEEK_SET );
-    VSIFReadL( template_data, template_size, 1, fp );
-    VSIFCloseL( fp );
+
+    CPL_IGNORE_RET_VAL_INT(VSIFSeekL( fp, 0, SEEK_SET ));
+    CPL_IGNORE_RET_VAL_SIZET(VSIFReadL( template_data, template_size, 1, fp ));
+    CPL_IGNORE_RET_VAL_INT(VSIFCloseL( fp ));
 
     /*
-     * Try to write the template out to the new filename. 
+     * Try to write the template out to the new filename.
      */
-    
+
     fp = VSIFOpenL( filename, "wb" );
     if( fp == NULL )
     {
         char	error_buf[2048];
 
-        sprintf( error_buf, 
-                 "Unable to open file \"%s\" in EnvisatFile_Create().", 
+        snprintf( error_buf, sizeof(error_buf),
+                 "Unable to open file \"%s\" in EnvisatFile_Create().",
                  filename );
 
         SendError( error_buf );
         return FAILURE;
     }
 
-    VSIFWriteL( template_data, template_size, 1, fp );
-    VSIFCloseL( fp );
+    CPL_IGNORE_RET_VAL_SIZET(VSIFWriteL( template_data, template_size, 1, fp ));
+    CPL_IGNORE_RET_VAL_INT(VSIFCloseL( fp ));
 
     CPLFree( template_data );
 
     /*
-     * Now just open the file normally. 
+     * Now just open the file normally.
      */
-    
+
     return EnvisatFile_Open( self_ptr, filename, "r+" );
 }
 
@@ -517,10 +534,10 @@ Purpose:
 
 Description:
     The length is computed by scanning the dataset definitions, not the
-    physical file length.  
+    physical file length.
 
 Inputs:
-    self -- the file to operate on. 
+    self -- the file to operate on.
 
 Outputs:
 
@@ -537,13 +554,13 @@ int EnvisatFile_GetCurrentLength( EnvisatFile *self )
     int		ds_offset;
     int         ds_size;
 
-    length = MPH_SIZE 
+    length = MPH_SIZE
         + EnvisatFile_GetKeyValueAsInt( self, MPH, "SPH_SIZE", 0 );
 
-    for( ds = 0; 
-         EnvisatFile_GetDatasetInfo( self, ds, NULL, NULL, NULL, 
+    for( ds = 0;
+         EnvisatFile_GetDatasetInfo( self, ds, NULL, NULL, NULL,
                                      &ds_offset, &ds_size, NULL, NULL )
-             != FAILURE; 
+             != FAILURE;
          ds++ )
     {
         if( ds_offset != 0 && (ds_offset+ds_size) > length )
@@ -578,14 +595,14 @@ static int EnvisatFile_RewriteHeader( EnvisatFile *self )
 {
     int		dsd, dsd_size;
 
-    /* 
+    /*
      * Rewrite MPH and SPH headers.
      */
-    if( S_NameValueList_Rewrite( self->fp, 
+    if( S_NameValueList_Rewrite( self->fp,
                         self->mph_count, self->mph_entries ) == FAILURE )
         return FAILURE;
 
-    if( S_NameValueList_Rewrite( self->fp, 
+    if( S_NameValueList_Rewrite( self->fp,
                         self->sph_count, self->sph_entries ) == FAILURE )
         return FAILURE;
 
@@ -604,46 +621,51 @@ static int EnvisatFile_RewriteHeader( EnvisatFile *self )
         EnvisatNameValue **dsdh_entries = NULL;
 
         dsd_text = (char *) CPLCalloc(1,dsd_size+1);
-        if( VSIFSeekL( self->fp, self->dsd_offset + dsd * dsd_size, 
+        if( VSIFSeekL( self->fp, self->dsd_offset + dsd * dsd_size,
                    SEEK_SET ) != 0 )
         {
             SendError( "VSIFSeekL() failed in EnvisatFile_RewriteHeader()" );
+            CPLFree(dsd_text);
             return FAILURE;
         }
-        
+
         if( (int) VSIFReadL( dsd_text, 1, dsd_size, self->fp ) != dsd_size )
         {
             SendError( "VSIFReadL() failed in EnvisatFile_RewriteHeader()" );
             return FAILURE;
         }
 
-        if( S_NameValueList_Parse( dsd_text, self->dsd_offset + dsd*dsd_size, 
+        if( S_NameValueList_Parse( dsd_text, self->dsd_offset + dsd*dsd_size,
                                    &dsdh_count, &dsdh_entries ) == FAILURE )
             return FAILURE;
 
         CPLFree( dsd_text );
 
-        key_index = S_NameValueList_FindKey( "DS_OFFSET", 
+        key_index = S_NameValueList_FindKey( "DS_OFFSET",
                                              dsdh_count, dsdh_entries );
         if( key_index == -1 )
             continue;
 
-        sprintf( dsdh_entries[key_index]->value, "%+021d", 
+        snprintf( dsdh_entries[key_index]->value,
+                  dsdh_entries[key_index]->value_len, "%+021d",
                  self->ds_info[dsd]->ds_offset );
 
-        key_index = S_NameValueList_FindKey( "DS_SIZE", 
+        key_index = S_NameValueList_FindKey( "DS_SIZE",
                                              dsdh_count, dsdh_entries );
-        sprintf( dsdh_entries[key_index]->value, "%+021d", 
+        snprintf( dsdh_entries[key_index]->value,
+                  dsdh_entries[key_index]->value_len, "%+021d",
                  self->ds_info[dsd]->ds_size );
 
-        key_index = S_NameValueList_FindKey( "NUM_DSR", 
+        key_index = S_NameValueList_FindKey( "NUM_DSR",
                                              dsdh_count, dsdh_entries );
-        sprintf( dsdh_entries[key_index]->value, "%+011d", 
+        snprintf( dsdh_entries[key_index]->value,
+                  dsdh_entries[key_index]->value_len, "%+011d",
                  self->ds_info[dsd]->num_dsr );
 
-        key_index = S_NameValueList_FindKey( "DSR_SIZE", 
+        key_index = S_NameValueList_FindKey( "DSR_SIZE",
                                              dsdh_count, dsdh_entries );
-        sprintf( dsdh_entries[key_index]->value, "%+011d", 
+        snprintf( dsdh_entries[key_index]->value,
+                  dsdh_entries[key_index]->value_len, "%+011d",
                  self->ds_info[dsd]->dsr_size );
 
         if( S_NameValueList_Rewrite( self->fp, dsdh_count, dsdh_entries )
@@ -690,13 +712,13 @@ void EnvisatFile_Close( EnvisatFile *self )
         EnvisatFile_RewriteHeader( self );
 
     /*
-     * Close file. 
+     * Close file.
      */
     if( self->fp != NULL )
-        VSIFCloseL( self->fp );
+        CPL_IGNORE_RET_VAL_INT(VSIFCloseL( self->fp ));
 
     /*
-     * Clean up data structures. 
+     * Clean up data structures.
      */
     S_NameValueList_Destroy( &(self->mph_count), &(self->mph_entries) );
     S_NameValueList_Destroy( &(self->sph_count), &(self->sph_entries) );
@@ -771,7 +793,7 @@ Returns:
 
 -----------------------------------------------------------------------------*/
 
-const char *EnvisatFile_GetKeyByIndex( EnvisatFile *self, 
+const char *EnvisatFile_GetKeyByIndex( EnvisatFile *self,
                                        EnvisatFile_HeaderFlag mph_or_sph,
                                        int key_index )
 
@@ -780,7 +802,7 @@ const char *EnvisatFile_GetKeyByIndex( EnvisatFile *self,
     EnvisatNameValue **entries;
 
     /*
-     * Select source list. 
+     * Select source list.
      */
     if( mph_or_sph == MPH )
     {
@@ -822,7 +844,7 @@ Returns:
 
 -----------------------------------------------------------------------------*/
 
-const char *EnvisatFile_GetKeyValueAsString( EnvisatFile *self, 
+const char *EnvisatFile_GetKeyValueAsString( EnvisatFile *self,
                                              EnvisatFile_HeaderFlag mph_or_sph,
                                              const char *key,
                                              const char *default_value )
@@ -832,7 +854,7 @@ const char *EnvisatFile_GetKeyValueAsString( EnvisatFile *self,
     EnvisatNameValue **entries;
 
     /*
-     * Select source list. 
+     * Select source list.
      */
     if( mph_or_sph == MPH )
     {
@@ -878,7 +900,7 @@ Returns:
 
 -----------------------------------------------------------------------------*/
 
-int EnvisatFile_SetKeyValueAsString( EnvisatFile *self, 
+int EnvisatFile_SetKeyValueAsString( EnvisatFile *self,
                                      EnvisatFile_HeaderFlag mph_or_sph,
                                      const char *key,
                                      const char *value )
@@ -894,7 +916,7 @@ int EnvisatFile_SetKeyValueAsString( EnvisatFile *self,
     }
 
     /*
-     * Select source list. 
+     * Select source list.
      */
     if( mph_or_sph == MPH )
     {
@@ -915,8 +937,8 @@ int EnvisatFile_SetKeyValueAsString( EnvisatFile *self,
     {
         char	error_buf[2048];
 
-        sprintf( error_buf, 
-                 "Unable to set header field \"%s\", field not found.", 
+        snprintf( error_buf, sizeof(error_buf),
+                 "Unable to set header field \"%s\", field not found.",
                  key );
 
         SendError( error_buf );
@@ -926,12 +948,12 @@ int EnvisatFile_SetKeyValueAsString( EnvisatFile *self,
     self->header_dirty = 1;
     if( strlen(value) > strlen(entries[key_index]->value) )
     {
-        strncpy( entries[key_index]->value, value, 
+        strncpy( entries[key_index]->value, value,
                  strlen(entries[key_index]->value) );
     }
     else
     {
-        memset( entries[key_index]->value, ' ', 
+        memset( entries[key_index]->value, ' ',
                 strlen(entries[key_index]->value) );
         strncpy( entries[key_index]->value, value, strlen(value) );
     }
@@ -962,7 +984,7 @@ Returns:
 
 -----------------------------------------------------------------------------*/
 
-int EnvisatFile_GetKeyValueAsInt( EnvisatFile *self, 
+int EnvisatFile_GetKeyValueAsInt( EnvisatFile *self,
                                   EnvisatFile_HeaderFlag mph_or_sph,
                                   const char *key,
                                   int default_value )
@@ -972,7 +994,7 @@ int EnvisatFile_GetKeyValueAsInt( EnvisatFile *self,
     EnvisatNameValue **entries;
 
     /*
-     * Select source list. 
+     * Select source list.
      */
     if( mph_or_sph == MPH )
     {
@@ -1018,7 +1040,7 @@ Returns:
 
 -----------------------------------------------------------------------------*/
 
-int EnvisatFile_SetKeyValueAsInt( EnvisatFile *self, 
+int EnvisatFile_SetKeyValueAsInt( EnvisatFile *self,
                                   EnvisatFile_HeaderFlag mph_or_sph,
                                   const char *key,
                                   int value )
@@ -1033,16 +1055,16 @@ int EnvisatFile_SetKeyValueAsInt( EnvisatFile *self,
     {
         char	error_buf[2048];
 
-        sprintf( error_buf, 
-                 "Unable to set header field \"%s\", field not found.", 
+        snprintf( error_buf, sizeof(error_buf),
+                 "Unable to set header field \"%s\", field not found.",
                  key );
 
         SendError( error_buf );
         return FAILURE;
     }
 
-    sprintf( format, "%%+0%dd", (int) strlen(prototype_value) );
-    sprintf( string_value, format, value );
+    snprintf( format, sizeof(format), "%%+0%dd", (int) strlen(prototype_value) );
+    snprintf( string_value, sizeof(string_value), format, value );
 
     return EnvisatFile_SetKeyValueAsString( self, mph_or_sph, key, string_value );
 }
@@ -1070,7 +1092,7 @@ Returns:
 
 -----------------------------------------------------------------------------*/
 
-double EnvisatFile_GetKeyValueAsDouble( EnvisatFile *self, 
+double EnvisatFile_GetKeyValueAsDouble( EnvisatFile *self,
                                         EnvisatFile_HeaderFlag mph_or_sph,
                                         const char *key,
                                         double default_value )
@@ -1080,7 +1102,7 @@ double EnvisatFile_GetKeyValueAsDouble( EnvisatFile *self,
     EnvisatNameValue **entries;
 
     /*
-     * Select source list. 
+     * Select source list.
      */
     if( mph_or_sph == MPH )
     {
@@ -1113,7 +1135,7 @@ Purpose:
 
 Description:
     Note that this function attempts to format the new value similarly to
-    the previous value.  In some cases (expecially exponential values) this 
+    the previous value.  In some cases (especially exponential values) this
     may not work out well.  In case of problems the caller is encourage to
     format the value themselves, and use the EnvisatFile_SetKeyValueAsString
     function, but taking extreme care about the string length.
@@ -1131,7 +1153,7 @@ Returns:
 
 -----------------------------------------------------------------------------*/
 
-int EnvisatFile_SetKeyValueAsDouble( EnvisatFile *self, 
+int EnvisatFile_SetKeyValueAsDouble( EnvisatFile *self,
                                      EnvisatFile_HeaderFlag mph_or_sph,
                                      const char *key,
                                      double value )
@@ -1146,19 +1168,19 @@ int EnvisatFile_SetKeyValueAsDouble( EnvisatFile *self,
     {
         char	error_buf[2048];
 
-        sprintf( error_buf, 
-                 "Unable to set header field \"%s\", field not found.", 
+        snprintf( error_buf, sizeof(error_buf),
+                 "Unable to set header field \"%s\", field not found.",
                  key );
 
         SendError( error_buf );
         return FAILURE;
     }
 
-    length = strlen(prototype_value);
+    length = (int)strlen(prototype_value);
     if( prototype_value[length-4] == 'E' )
     {
-        sprintf( format, "%%+%dE", length-4 );
-        sprintf( string_value, format, value );
+        snprintf( format, sizeof(format), "%%+%dE", length-4 );
+        snprintf( string_value, sizeof(string_value), format, value );
     }
     else
     {
@@ -1167,12 +1189,12 @@ int EnvisatFile_SetKeyValueAsDouble( EnvisatFile *self,
         {
             if( prototype_value[i] == '.' )
                 break;
-            
+
             decimals++;
         }
 
-        sprintf( format, "%%+0%d.%df", length, decimals );
-        CPLsprintf( string_value, format, value );
+        snprintf( format, sizeof(format), "%%+0%d.%df", length, decimals );
+        CPLsnprintf( string_value, sizeof(string_value), format, value );
 
         if( (int)strlen(string_value) > length )
             string_value[length] = '\0';
@@ -1187,7 +1209,7 @@ Name:
     EnvisatFile_GetDatasetIndex()
 
 Purpose:
-    Fetch the datasat index give a dataset name.
+    Fetch the dataset index given a dataset name.
 
 Description:
     The provided name is extended with spaces, so it isn't necessary for the
@@ -1217,7 +1239,7 @@ int EnvisatFile_GetDatasetIndex( EnvisatFile *self, const char *ds_name )
      */
     strncpy( padded_ds_name, ds_name, sizeof(padded_ds_name) );
     padded_ds_name[sizeof(padded_ds_name)-1] = 0;
-    for( i = strlen(padded_ds_name); (size_t)i < sizeof(padded_ds_name)-1; i++ )
+    for( i = (int)strlen(padded_ds_name); (size_t)i < sizeof(padded_ds_name)-1; i++ )
     {
         padded_ds_name[i] = ' ';
     }
@@ -1228,9 +1250,8 @@ int EnvisatFile_GetDatasetIndex( EnvisatFile *self, const char *ds_name )
      */
     for( i = 0; i < self->ds_count; i++ )
     {
-        if( strncmp( padded_ds_name, self->ds_info[i]->ds_name, 
-                     strlen(self->ds_info[i]->ds_name) ) == 0 )
-        {
+        if( strncmp( padded_ds_name, self->ds_info[i]->ds_name,
+                     strlen(self->ds_info[i]->ds_name) ) == 0 )        {
             return i;
         }
     }
@@ -1256,10 +1277,10 @@ Inputs:
     ds_index -- the dataset index to fetch
 
 Outputs:
-    ds_name -- the dataset symbolic name, ie 'MDS1 SQ ADS              '.
-    ds_type -- the dataset type, ie. 'A', not sure of valid values.
+    ds_name -- the dataset symbolic name, i.e 'MDS1 SQ ADS              '.
+    ds_type -- the dataset type, i.e. 'A', not sure of valid values.
     filename -- dataset filename, normally spaces, or 'NOT USED          '.
-    ds_offset -- the byte offset in the whole file to the first byte of 
+    ds_offset -- the byte offset in the whole file to the first byte of
                  dataset data.  This is 0 for unused datasets.
     ds_size -- the size, in bytes, of the whole dataset.
     num_dsr -- the number of records in the dataset.
@@ -1271,9 +1292,9 @@ Returns:
 
 -----------------------------------------------------------------------------*/
 
-int EnvisatFile_GetDatasetInfo( EnvisatFile *self, 
-                                int ds_index, 
-                                char **ds_name, 
+int EnvisatFile_GetDatasetInfo( EnvisatFile *self,
+                                int ds_index,
+                                char **ds_name,
                                 char **ds_type,
                                 char **filename,
                                 int  *ds_offset,
@@ -1316,7 +1337,7 @@ Description:
 Inputs:
     self -- the file to be searched.
     ds_index -- the dataset index to fetch
-    ds_offset -- the byte offset in the whole file to the first byte of 
+    ds_offset -- the byte offset in the whole file to the first byte of
                  dataset data.  This is 0 for unused datasets.
     ds_size -- the size, in bytes, of the whole dataset.
     num_dsr -- the number of records in the dataset.
@@ -1330,8 +1351,8 @@ Returns:
 
 -----------------------------------------------------------------------------*/
 
-int EnvisatFile_SetDatasetInfo( EnvisatFile *self, 
-                                int ds_index, 
+int EnvisatFile_SetDatasetInfo( EnvisatFile *self,
+                                int ds_index,
                                 int ds_offset,
                                 int ds_size,
                                 int num_dsr,
@@ -1378,7 +1399,7 @@ Returns:
 
 -----------------------------------------------------------------------------*/
 
-int EnvisatFile_ReadDatasetChunk( EnvisatFile *self, 
+int EnvisatFile_ReadDatasetChunk( EnvisatFile *self,
                                   int ds_index,
                                   int offset,
                                   int size,
@@ -1392,7 +1413,7 @@ int EnvisatFile_ReadDatasetChunk( EnvisatFile *self,
         return FAILURE;
     }
 
-    if( offset < 0 
+    if( offset < 0
         || offset + size > self->ds_info[ds_index]->ds_size )
     {
         SendError( "Attempt to read beyond end of dataset in "
@@ -1441,7 +1462,7 @@ Returns:
 
 -----------------------------------------------------------------------------*/
 
-int EnvisatFile_WriteDatasetRecord( EnvisatFile *self, 
+int EnvisatFile_WriteDatasetRecord( EnvisatFile *self,
                                     int ds_index,
                                     int record_index,
                                     void *buffer )
@@ -1474,7 +1495,7 @@ int EnvisatFile_WriteDatasetRecord( EnvisatFile *self,
         return FAILURE;
     }
 
-    result = VSIFWriteL( buffer, 1, self->ds_info[ds_index]->dsr_size, self->fp );
+    result = (int)VSIFWriteL( buffer, 1, self->ds_info[ds_index]->dsr_size, self->fp );
     if( result != self->ds_info[ds_index]->dsr_size )
     {
         SendError( "write failed in EnvisatFile_WriteDatasetRecord()" );
@@ -1511,14 +1532,14 @@ Returns:
 
 int EnvisatFile_ReadDatasetRecordChunk(EnvisatFile*,int,int,void*,int,int);
 
-int EnvisatFile_ReadDatasetRecord( EnvisatFile *self, 
+int EnvisatFile_ReadDatasetRecord( EnvisatFile *self,
                                     int ds_index,
                                     int record_index,
                                     void *buffer )
 {
-    return EnvisatFile_ReadDatasetRecordChunk( self, 
-                ds_index, record_index, buffer, 0 , -1 ) ; 
-} 
+    return EnvisatFile_ReadDatasetRecordChunk( self,
+                ds_index, record_index, buffer, 0 , -1 ) ;
+}
 
 /*-----------------------------------------------------------------------------
 
@@ -1529,7 +1550,7 @@ Purpose:
     Read a part of an arbitrary dataset record.
 
 Description:
-    Note that no range checking is made on dataset's offset and size, 
+    Note that no range checking is made on dataset's offset and size,
     and data may be read from outside the dataset if they are inappropriate.
 
 Inputs:
@@ -1538,7 +1559,7 @@ Inputs:
     record_index -- the record to write.
     record_buffer -- buffer to load data into
     offset -- chunk offset relative to the record start (zerro offset)
-    size -- chunk size (set -1 to read from offset to the records' end)  
+    size -- chunk size (set -1 to read from offset to the records' end)
 
 Outputs:
 
@@ -1547,25 +1568,25 @@ Returns:
 
 -----------------------------------------------------------------------------*/
 
-int EnvisatFile_ReadDatasetRecordChunk( EnvisatFile *self, 
+int EnvisatFile_ReadDatasetRecordChunk( EnvisatFile *self,
                                     int ds_index,
                                     int record_index,
-                                    void *buffer, 
+                                    void *buffer,
                                     int offset, int size )
 {
     int		absolute_offset;
     int         result;
-    int     dsr_size = self->ds_info[ds_index]->dsr_size ; 
+    int     dsr_size = self->ds_info[ds_index]->dsr_size ;
 
     if (( offset < 0 )||(offset > dsr_size))
     {
         SendError( "Invalid chunk offset in "
                    "EnvisatFile_ReadDatasetRecordChunk()" );
         return FAILURE;
-    } 
+    }
 
-    if ( size < 0 ) 
-        size = dsr_size - offset ; 
+    if ( size < 0 )
+        size = dsr_size - offset ;
 
     if( ds_index < 0 || ds_index >= self->ds_count )
     {
@@ -1598,7 +1619,7 @@ int EnvisatFile_ReadDatasetRecordChunk( EnvisatFile *self,
         return FAILURE;
     }
 
-    result = VSIFReadL( buffer, 1, size, self->fp );
+    result = (int)VSIFReadL( buffer, 1, size, self->fp );
     if( result != size )
     {
         SendError( "read failed in EnvisatFile_ReadDatasetRecord()" );
@@ -1614,26 +1635,26 @@ Name:
     S_NameValueList_FindKey()
 
 Purpose:
-    Search for given key in list of name/value pairs. 
+    Search for given key in list of name/value pairs.
 
 Description:
     Scans list looking for index of EnvisatNameValue where the key matches
-    (case sensitive) the passed in name. 
+    (case sensitive) the passed in name.
 
 Inputs:
-    key -- the key, such as "SLICE_POSITION" being searched for. 
+    key -- the key, such as "SLICE_POSITION" being searched for.
     entry_count -- the number of items in the entries array.
-    entries -- array of name/value structures to search. 
+    entries -- array of name/value structures to search.
 
 Outputs:
 
 Returns:
-    array index into entries, or -1 on failure. 
+    array index into entries, or -1 on failure.
 
 -----------------------------------------------------------------------------*/
 
-int S_NameValueList_FindKey( const char *key, 
-                             int entry_count, 
+int S_NameValueList_FindKey( const char *key,
+                             int entry_count,
                              EnvisatNameValue **entries )
 
 {
@@ -1644,7 +1665,7 @@ int S_NameValueList_FindKey( const char *key,
         if( strcmp(entries[i]->key,key) == 0 )
             return i;
     }
-    
+
     return -1;
 }
 
@@ -1660,9 +1681,9 @@ Description:
     Returns value string or default if key not found.
 
 Inputs:
-    key -- the key, such as "SLICE_POSITION" being searched for. 
+    key -- the key, such as "SLICE_POSITION" being searched for.
     entry_count -- the number of items in the entries array.
-    entries -- array of name/value structures to search. 
+    entries -- array of name/value structures to search.
     default_value -- value to use if key not found.
 
 Outputs:
@@ -1672,8 +1693,8 @@ Returns:
 
 -----------------------------------------------------------------------------*/
 
-const char *S_NameValueList_FindValue( const char *key, 
-                                       int entry_count, 
+const char *S_NameValueList_FindValue( const char *key,
+                                       int entry_count,
                                        EnvisatNameValue **entries,
                                        const char *default_value )
 
@@ -1694,10 +1715,10 @@ Name:
 
 Purpose:
     Parse a block of envisat style name/value pairs into an
-    EnvisatNameValue structure list. 
+    EnvisatNameValue structure list.
 
 Description:
-    The passed in text block should be zero terminated.  The entry_count, 
+    The passed in text block should be zero terminated.  The entry_count,
     and entries should be pre-initialized (normally to 0 and NULL).
 
 Inputs:
@@ -1706,15 +1727,15 @@ Inputs:
 Outputs:
     entry_count -- returns with the updated number of entries in the
                    entries array.
-    entries -- returns with updated array info structures. 
+    entries -- returns with updated array info structures.
 
 Returns:
     SUCCESS or FAILURE
 
 -----------------------------------------------------------------------------*/
 
-int S_NameValueList_Parse( const char *text, int text_offset, 
-                           int *entry_count, 
+int S_NameValueList_Parse( const char *text, int text_offset,
+                           int *entry_count,
                            EnvisatNameValue ***entries )
 
 {
@@ -1726,21 +1747,24 @@ int S_NameValueList_Parse( const char *text, int text_offset,
     while( *next_text != '\0' )
     {
         char	line[1024];
-        int     line_len = 0, equal_index, src_char, line_offset;
-        EnvisatNameValue *entry;
+        int     line_len = 0;
+        int     equal_index = 0;
+        int     src_char = 0;
+        int     line_offset = 0;
+        EnvisatNameValue *entry = NULL;
 
         /*
          * Extract one line of text into the "line" buffer, and remove the
          * newline character.  Eat leading spaces.
          */
-        while( *next_text == ' ' ) 
+        while( *next_text == ' ' )
         {
             next_text++;
         }
         line_offset = (int) (next_text - text) + text_offset;
         while( *next_text != '\0' && *next_text != '\n' )
         {
-          if( line_len > ((int)sizeof(line) - 1) )
+          if( line_len > ((int)sizeof(line) - 2) )
             {
                 SendError( "S_NameValueList_Parse(): "
                            "Corrupt line, longer than 1024 characters." );
@@ -1763,17 +1787,17 @@ int S_NameValueList_Parse( const char *text, int text_offset,
             continue;
 
         /*
-         * Create the name/value info structure. 
+         * Create the name/value info structure.
          */
         entry = (EnvisatNameValue *) CPLCalloc(sizeof(EnvisatNameValue),1);
         entry->literal_line = CPLStrdup(line);
 
         /*
          * Capture the key.  We take everything up to the equal sign.  There
-         * shouldn't be any white space, but if so, we take it as part of the
+         * should not be any white space, but if so, we take it as part of the
          * key.
          */
-        equal_index = strstr(line, "=") - line;
+        equal_index = (int)(strstr(line, "=") - line);
         entry->key = (char *) CPLMalloc(equal_index+1);
         strncpy( entry->key, line, equal_index );
         entry->key[equal_index] = '\0';
@@ -1791,6 +1815,7 @@ int S_NameValueList_Parse( const char *text, int text_offset,
 
             line[src_char] = '\0';
             entry->value = CPLStrdup(line + equal_index + 2);
+            entry->value_len = strlen(entry->value)+1;
             entry->value_offset += 1;
         }
 
@@ -1799,8 +1824,8 @@ int S_NameValueList_Parse( const char *text, int text_offset,
          */
         else
         {
-            for( src_char = equal_index + 1; 
-                 line[src_char] != '\0' && line[src_char] != '<' 
+            for( src_char = equal_index + 1;
+                 line[src_char] != '\0' && line[src_char] != '<'
                      && line[src_char] != ' ';
                  src_char++ ) {}
 
@@ -1809,7 +1834,7 @@ int S_NameValueList_Parse( const char *text, int text_offset,
             {
                 int dst_char;
 
-                for( dst_char = src_char+1; 
+                for( dst_char = src_char+1;
                      line[dst_char] != '>' && line[dst_char] != '\0';
                      dst_char++ ) {}
 
@@ -1819,10 +1844,11 @@ int S_NameValueList_Parse( const char *text, int text_offset,
 
             line[src_char] = '\0';
             entry->value = CPLStrdup( line + equal_index + 1 );
+            entry->value_len = strlen(entry->value)+1;
         }
 
         /*
-         * Add the entry to the name/value list. 
+         * Add the entry to the name/value list.
          */
         (*entry_count)++;
         *entries = (EnvisatNameValue **)
@@ -1831,12 +1857,13 @@ int S_NameValueList_Parse( const char *text, int text_offset,
         if( *entries == NULL )
         {
             *entry_count = 0;
+            CPLFree(entry);
             return FAILURE;
         }
 
         (*entries)[*entry_count-1] = entry;
     }
-    
+
     return SUCCESS;
 }
 
@@ -1861,8 +1888,8 @@ Returns:
 
 -----------------------------------------------------------------------------*/
 
-int S_NameValueList_Rewrite( VSILFILE * fp, int entry_count, 
-                              EnvisatNameValue **entries )	      
+int S_NameValueList_Rewrite( VSILFILE * fp, int entry_count,
+                              EnvisatNameValue **entries )
 
 {
     int		i;
@@ -1877,7 +1904,7 @@ int S_NameValueList_Rewrite( VSILFILE * fp, int entry_count,
             return FAILURE;
         }
 
-        if( VSIFWriteL( entry->value, 1, strlen(entry->value), fp ) != 
+        if( VSIFWriteL( entry->value, 1, strlen(entry->value), fp ) !=
             strlen(entry->value) )
         {
             SendError( "VSIFWriteL() failed writing name/value list." );
@@ -1903,7 +1930,7 @@ Description:
 Inputs:
     entry_count -- returns with the updated number of entries in the
                    entries array.
-    entries -- returns with updated array info structures. 
+    entries -- returns with updated array info structures.
 
 Outputs:
     entry_count -- Set to zero.
@@ -1914,8 +1941,8 @@ Returns:
 
 -----------------------------------------------------------------------------*/
 
-void S_NameValueList_Destroy( int *entry_count, 
-                              EnvisatNameValue ***entries )	      
+void S_NameValueList_Destroy( int *entry_count,
+                              EnvisatNameValue ***entries )
 
 {
     int		i;
@@ -1930,7 +1957,7 @@ void S_NameValueList_Destroy( int *entry_count,
     }
 
     CPLFree( *entries );
-    
+
     *entry_count = 0;
     *entries = NULL;
 }
diff --git a/frmts/envisat/EnvisatFile.h b/frmts/envisat/EnvisatFile.h
index 72c3810..b808727 100644
--- a/frmts/envisat/EnvisatFile.h
+++ b/frmts/envisat/EnvisatFile.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: EnvisatFile.h 27098 2014-03-27 00:16:11Z rouault $
+ * $Id: EnvisatFile.h 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  APP ENVISAT Support
  * Purpose:  Low Level Envisat file access (read/write) API.
@@ -27,110 +27,106 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef __ENVISAT_FILE_H__
-#define __ENVISAT_FILE_H__
+#ifndef ENVISAT_FILE_H_
+#define ENVISAT_FILE_H_
 
 typedef struct EnvisatFile_tag EnvisatFile;
 
-typedef enum 
+typedef enum
 {
     MPH = 0,
     SPH = 1
 } EnvisatFile_HeaderFlag;
 
-int EnvisatFile_Open( EnvisatFile **self, const char *filename, 
+int EnvisatFile_Open( EnvisatFile **self, const char *filename,
                       const char *mode );
 void EnvisatFile_Close( EnvisatFile *self );
 const char *EnvisatFile_GetFilename( EnvisatFile *self );
-int EnvisatFile_Create( EnvisatFile **self, const char *filename, 
+int EnvisatFile_Create( EnvisatFile **self, const char *filename,
                         const char *template_file );
 int EnvisatFile_GetCurrentLength( EnvisatFile *self );
 
-const char* EnvisatFile_GetKeyByIndex(  EnvisatFile *self, 
+const char* EnvisatFile_GetKeyByIndex(  EnvisatFile *self,
                                         EnvisatFile_HeaderFlag mph_or_sph,
                                         int key_index );
 
-int EnvisatFile_TestKey(  EnvisatFile *self, 
+int EnvisatFile_TestKey(  EnvisatFile *self,
                           EnvisatFile_HeaderFlag mph_or_sph,
                           const char *key );
 
-const char *EnvisatFile_GetKeyValueAsString( EnvisatFile *self, 
+const char *EnvisatFile_GetKeyValueAsString( EnvisatFile *self,
                                              EnvisatFile_HeaderFlag mph_or_sph,
                                              const char *key,
                                              const char *default_value );
 
-int EnvisatFile_SetKeyValueAsString( EnvisatFile *self, 
+int EnvisatFile_SetKeyValueAsString( EnvisatFile *self,
                                      EnvisatFile_HeaderFlag mph_or_sph,
                                      const char *key,
                                      const char *value );
 
-int EnvisatFile_GetKeyValueAsInt( EnvisatFile *self, 
+int EnvisatFile_GetKeyValueAsInt( EnvisatFile *self,
                                   EnvisatFile_HeaderFlag mph_or_sph,
-                                  const char *key, 
+                                  const char *key,
                                   int default_value );
 
-int EnvisatFile_SetKeyValueAsInt( EnvisatFile *self, 
+int EnvisatFile_SetKeyValueAsInt( EnvisatFile *self,
                                   EnvisatFile_HeaderFlag mph_or_sph,
-                                  const char *key, 
+                                  const char *key,
                                   int value );
 
-double EnvisatFile_GetKeyValueAsDouble( EnvisatFile *self, 
+double EnvisatFile_GetKeyValueAsDouble( EnvisatFile *self,
                                         EnvisatFile_HeaderFlag mph_or_sph,
-                                        const char *key, 
+                                        const char *key,
                                         double default_value );
-int EnvisatFile_SetKeyValueAsDouble( EnvisatFile *self, 
+int EnvisatFile_SetKeyValueAsDouble( EnvisatFile *self,
                                      EnvisatFile_HeaderFlag mph_or_sph,
-                                     const char *key, 
+                                     const char *key,
                                      double value );
 
 int EnvisatFile_GetDatasetIndex( EnvisatFile *self, const char *ds_name );
 
-int EnvisatFile_GetDatasetInfo( EnvisatFile *self, 
+int EnvisatFile_GetDatasetInfo( EnvisatFile *self,
                                 int ds_index,
-                                char **ds_name, 
+                                char **ds_name,
                                 char **ds_type,
                                 char **filename,
                                 int  *ds_offset,
                                 int  *ds_size,
                                 int  *num_dsr,
                                 int  *dsr_size );
-int EnvisatFile_SetDatasetInfo( EnvisatFile *self, 
+int EnvisatFile_SetDatasetInfo( EnvisatFile *self,
                                 int ds_index,
                                 int ds_offset,
                                 int ds_size,
                                 int num_dsr,
                                 int dsr_size );
-                              
-int EnvisatFile_ReadDatasetRecordChunk( EnvisatFile *self, 
+
+int EnvisatFile_ReadDatasetRecordChunk( EnvisatFile *self,
                                     int ds_index,
                                     int record_index,
-                                    void *buffer, 
+                                    void *buffer,
                                     int offset, int size ) ;
-int EnvisatFile_ReadDatasetRecord( EnvisatFile *self, 
+int EnvisatFile_ReadDatasetRecord( EnvisatFile *self,
                                    int ds_index,
-                                   int record_index, 
+                                   int record_index,
                                    void *record_buffer );
-int EnvisatFile_WriteDatasetRecord( EnvisatFile *self, 
+int EnvisatFile_WriteDatasetRecord( EnvisatFile *self,
                                     int ds_index,
-                                    int record_index, 
+                                    int record_index,
                                     void *record_buffer );
-int EnvisatFile_ReadDatasetChunk( EnvisatFile *self, 
+int EnvisatFile_ReadDatasetChunk( EnvisatFile *self,
                                   int ds_index,
-                                  int offset, 
+                                  int offset,
                                   int size,
                                   void *buffer );
-                                
 
 #ifndef FAILURE
 #  define FAILURE 1
 #endif
-#ifndef SUCCESS 
+#ifndef SUCCESS
 #  define SUCCESS 0
 #endif
 
-#endif /* __ENVISAT_FILE_H__ */
+#endif /* ENVISAT_FILE_H_ */
 
 /* EOF */
-
-
-
diff --git a/frmts/envisat/adsrange.cpp b/frmts/envisat/adsrange.cpp
index d5d4889..20cac71 100644
--- a/frmts/envisat/adsrange.cpp
+++ b/frmts/envisat/adsrange.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: adsrange.cpp 27099 2014-03-27 00:49:30Z rouault $
+ * $Id: adsrange.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  APP ENVISAT Support
  * Purpose:  Detect range of ADS records matching the MDS records.
- * Author:   Martin Paces, martin.paces at eox.at 
+ * Author:   Martin Paces, martin.paces at eox.at
  *
  ******************************************************************************
- * Copyright (c) 2013, EOX IT Services, GmbH 
+ * Copyright (c) 2013, EOX IT Services, GmbH
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -40,114 +40,110 @@ CPL_C_END
 #include <cmath>
 
 /* -------------------------------------------------------------------- */
-/* 
- * data-set descriptor (private helper class) 
+/*
+ * data-set descriptor (private helper class)
  */
 
 class DataSet
-{ 
+{
   public:
 
     EnvisatFile & envfile ;
     int index ;
-    int nrec ; 
+    int nrec ;
 
-    DataSet( EnvisatFile & envfile , int index ) : 
-        envfile(envfile), index(index), nrec(0)
-    { 
-        EnvisatFile_GetDatasetInfo( &envfile, index, NULL, NULL, NULL,
+    DataSet( EnvisatFile & envfileIn , int indexIn ) :
+        envfile(envfileIn), index(indexIn), nrec(0)
+    {
+        EnvisatFile_GetDatasetInfo( &envfileIn, indexIn, NULL, NULL, NULL,
                 NULL , NULL, &nrec, NULL ) ;
-    } 
+    }
 
-    TimeDelta getMJD( int ridx ) 
-    { 
-        GUInt32 mjd[3] ; 
+    TimeDelta getMJD( int ridx )
+    {
+        if ( ridx < 0 ) ridx += nrec ;
 
-        if ( ridx < 0 ) ridx += nrec ; 
-    
+        GUInt32 mjd[3];
         EnvisatFile_ReadDatasetRecordChunk(&envfile,index,ridx,mjd,0,12) ;
 
-        #define INT32(x)    ((GInt32)CPL_MSBWORD32(x)) 
+        #define INT32(x)    ((GInt32)CPL_MSBWORD32(x))
 
         return TimeDelta( INT32(mjd[0]), INT32(mjd[1]), INT32(mjd[2]) ) ;
 
-        #undef INT32 
-    } 
+        #undef INT32
+    }
 
-} ; 
+  private:
+    CPL_DISALLOW_COPY_ASSIGN(DataSet);
+} ;
 
 /* -------------------------------------------------------------------- */
-/* 
- * constructor of the ADSRangeLastAfter object 
+/*
+ * constructor of the ADSRangeLastAfter object
  *
- */ 
+ */
 
-ADSRangeLastAfter::ADSRangeLastAfter( EnvisatFile & envfile, 
+ADSRangeLastAfter::ADSRangeLastAfter( EnvisatFile & envfile,
     int  ads_idx , int mds_idx, const TimeDelta & line_interval )
-{ 
-    int idx ; 
-    TimeDelta t_mds , t_ads , t_ads_prev ; 
-
-    /* abs.time tolerance */ 
-    TimeDelta atol = line_interval * 0.5 ; 
+{
+    /* abs.time tolerance */
+    TimeDelta atol = line_interval * 0.5 ;
 
     /* MDS and ADS descriptor classes */
-    DataSet mds( envfile, mds_idx ) ; 
-    DataSet ads( envfile, ads_idx ) ; 
+    DataSet mds( envfile, mds_idx ) ;
+    DataSet ads( envfile, ads_idx ) ;
 
-    /* read the times of the first and last measurements */ 
+    /* read the times of the first and last measurements */
     mjd_m_first = mds.getMJD(0) ;  /* MDJ time of the first MDS record */
     mjd_m_last  = mds.getMJD(-1) ;   /* MDJ time of the last MDS record */
 
-    /* look-up the the first applicable ADSR */ 
+    /* look-up the first applicable ADSR */
 
-    idx   = 0 ; 
-    t_mds = mjd_m_first + atol ; /*time of the first MDSR + tolerance */ 
-    t_ads  = ads.getMJD(0) ;     /*time of the first ADSR */
-    t_ads_prev = t_ads ;         /* holds previous ADSR */
+    int idx = 0;
+    TimeDelta t_mds = mjd_m_first + atol ; /*time of the first MDSR + tolerance */
+    TimeDelta t_ads  = ads.getMJD(0) ;     /*time of the first ADSR */
+    TimeDelta t_ads_prev = t_ads ;         /* holds previous ADSR */
 
-    if ( t_ads < t_mds ) 
-    { 
+    if ( t_ads < t_mds )
+    {
         for( idx = 1 ; idx < ads.nrec ; ++idx )
-        { 
-            t_ads = ads.getMJD(idx) ; 
-        
-            if ( t_ads >= t_mds ) break ; 
-
-            t_ads_prev = t_ads ; 
-        } 
-    } 
-    
+        {
+            t_ads = ads.getMJD(idx) ;
+
+            if ( t_ads >= t_mds ) break ;
+
+            t_ads_prev = t_ads ;
+        }
+    }
+
     /* store the first applicable ASDR */
     idx_first = idx - 1 ; /* sets -1 if no match */
     mjd_first = t_ads_prev ; /* set time of the first rec. if no match */
 
-    /* look-up the the last applicable ADSR */ 
+    /* look-up the last applicable ADSR */
 
-    idx   = ads.nrec-2 ; 
-    t_mds = mjd_m_last - atol ;  /* time of the last MDSR - tolerance */ 
+    idx   = ads.nrec-2 ;
+    t_mds = mjd_m_last - atol ;  /* time of the last MDSR - tolerance */
     t_ads  = ads.getMJD(-1) ;    /* time of the first ADSR */
     t_ads_prev = t_ads ;         /* holds previous ADSR */
 
-    if ( t_ads > t_mds ) 
-    { 
+    if ( t_ads > t_mds )
+    {
         for( idx = ads.nrec-2 ; idx >= 0 ; --idx )
-        { 
-            t_ads = ads.getMJD(idx) ; 
-        
-            if ( t_ads <= t_mds ) break ; 
-
-            t_ads_prev = t_ads ; 
-        } 
-    } 
-   
+        {
+            t_ads = ads.getMJD(idx) ;
+
+            if ( t_ads <= t_mds ) break ;
+
+            t_ads_prev = t_ads ;
+        }
+    }
+
     /* store the last applicable ASDR */
     idx_last = idx + 1 ; /* sets ads.nrec if no match */
     mjd_last = t_ads_prev ; /* set time of the last rec. if no match */
 
     /* valuate the line offsets */
-    off_first = (int)floor( 0.5 + ( mjd_m_first - mjd_first ) / line_interval ) ; 
-    off_last  = (int)floor( 0.5 + ( mjd_last  - mjd_m_last  ) / line_interval ) ; 
-
-} ;
-
+    off_first = (int)floor( 0.5 + ( mjd_m_first - mjd_first ) / line_interval ) ;
+    off_last  = (int)floor( 0.5 + ( mjd_last  - mjd_m_last  ) / line_interval ) ;
+}
diff --git a/frmts/envisat/adsrange.hpp b/frmts/envisat/adsrange.hpp
index de4ca0d..e0849b6 100644
--- a/frmts/envisat/adsrange.hpp
+++ b/frmts/envisat/adsrange.hpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: adsrange.hpp 27098 2014-03-27 00:16:11Z rouault $
+ * $Id: adsrange.hpp 31977 2015-12-03 11:42:22Z rouault $
  *
  * Project:  APP ENVISAT Support
  * Purpose:  Detect range of ADS records matching the MDS records
@@ -34,15 +34,15 @@
 
 CPL_C_START
 #include "EnvisatFile.h"
-#include "records.h"
 CPL_C_END
+#include "records.h"
 
 #include "timedelta.hpp"
 
 /* -------------------------------------------------------------------- */
 /*
  * class ADSRange 
- * 
+ *
  * Range of ADS record matching the range of the MDS records. 
  *
  */
@@ -71,16 +71,16 @@ class ADSRange
     { 
     } 
 
-    ADSRange( const int idx_first, const int idx_last, 
-        const int off_first, const int off_last, 
-        const TimeDelta &mjd_first, const TimeDelta &mjd_last, 
-        const TimeDelta &mjd_m_first, const TimeDelta &mjd_m_last ) :
-        idx_first(idx_first), idx_last(idx_last), off_first(off_first),
-        off_last(off_last), mjd_first(mjd_first), mjd_last(mjd_last),
-        mjd_m_first(mjd_m_first), mjd_m_last(mjd_m_last) 
+    ADSRange( const int idx_firstIn, const int idx_lastIn, 
+        const int off_firstIn, const int off_lastIn, 
+        const TimeDelta &mjd_firstIn, const TimeDelta &mjd_lastIn, 
+        const TimeDelta &mjd_m_firstIn, const TimeDelta &mjd_m_lastIn ) :
+        idx_first(idx_firstIn), idx_last(idx_lastIn), off_first(off_firstIn),
+        off_last(off_lastIn), mjd_first(mjd_firstIn), mjd_last(mjd_lastIn),
+        mjd_m_first(mjd_m_firstIn), mjd_m_last(mjd_m_lastIn) 
     { 
     } 
-    
+
     /* get count of matched records */
     inline int getDSRCount( void ) const 
     { 
@@ -136,38 +136,35 @@ class ADSRange
     { 
         return this->mjd_m_last ; 
     } 
-
-} ;  
+};
 
 
 /* -------------------------------------------------------------------- */
-/* 
- * NOTE: There are two kinds of ADS records: 
+/*
+ * NOTE: There are two kinds of ADS records:
  *
- *  1) One ADS record appliable to all consequent MDS records until replaced 
- *     by another ADS record, i.e., last MDS records does no need to be 
+ *  1) One ADS record applicable to all consequent MDS records until replaced
+ *     by another ADS record, i.e., last MDS records does no need to be
  *     followed by an ADS record.
  *
- *  2) Two ADS records applicable to all MDS records between them 
- *     (e.g., tiepoints ADS), i.e., last MDS record should be followed 
- *     by an ADS rescord having the same or later time-stamp.  
- *  
- *  The type of the ADS afects the way how the ADS records corresponding 
- *  to a set of MDS records should be selected. 
+ *  2) Two ADS records applicable to all MDS records between them
+ *     (e.g., tiepoints ADS), i.e., last MDS record should be followed
+ *     by an ADS record having the same or later time-stamp.
+ *
+ *  The type of the ADS affects the way how the ADS records corresponding
+ *  to a set of MDS records should be selected.
  */
 
 
 class ADSRangeLastAfter: public ADSRange
-{ 
+{
 
-  public: 
+  public:
 
     /* CONSTRUCTOR */ 
     ADSRangeLastAfter( EnvisatFile & envfile, int  ads_idx , int mds_idx,
             const TimeDelta & line_interval ) ; 
-
-} ;  
+};
 
 
 #endif /*tiepointrange_hpp*/
-
diff --git a/frmts/envisat/dumpgeo.c b/frmts/envisat/dumpgeo.c
index 4c2cc0e..fb1265f 100644
--- a/frmts/envisat/dumpgeo.c
+++ b/frmts/envisat/dumpgeo.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dumpgeo.c 9484 2006-04-04 02:44:16Z fwarmerdam $
+ * $Id: dumpgeo.c 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  APP ENVISAT Support
  * Purpose:  Test mainline for dumping ENVISAT format files.
@@ -43,7 +43,6 @@ int main( int argc, char ** argv )
         exit( 1 );
     }
 
-    
     if( EnvisatFile_Open( &es_file, argv[1], "r" ) != 0 )
     {
         printf( "EnvisatFile_Open(%s) failed.\n", argv[1] );
@@ -55,9 +54,9 @@ int main( int argc, char ** argv )
     {
         printf( "Can't find geolocation grid ads.\n" );
         exit( 3 );
-    }        
+    }
 
-    EnvisatFile_GetDatasetInfo( es_file, 
+    EnvisatFile_GetDatasetInfo( es_file,
                                 ds_index, NULL, NULL, NULL,
                                 &ds_offset, &ds_size,
                                 &num_dsr, &dsr_size );
@@ -76,10 +75,10 @@ int main( int argc, char ** argv )
         float   fValue;
         int	sample;
 
-        EnvisatFile_ReadDatasetRecord( es_file, ds_index, i_record, 
+        EnvisatFile_ReadDatasetRecord( es_file, ds_index, i_record,
                                        abyRecord );
 
-        printf( "<====================== Record %d ==================>\n", 
+        printf( "<====================== Record %d ==================>\n",
                 i_record );
 
         /* field 1 */
@@ -87,7 +86,7 @@ int main( int argc, char ** argv )
         CPL_SWAP32PTR( abyRecord + 4 );
         CPL_SWAP32PTR( abyRecord + 8 );
 
-        printf( "start line: mjd_days = %d, sec = %d, msec = %d\n", 
+        printf( "start line: mjd_days = %d, sec = %d, msec = %d\n",
                 ((int *) abyRecord)[0],
                 ((unsigned int *) abyRecord)[1],
                 ((unsigned int *) abyRecord)[2] );
@@ -97,7 +96,7 @@ int main( int argc, char ** argv )
 
         /* field 3 */
         memcpy( &unValue, abyRecord + 13, 4 );
-        printf( "range line (first in granule) = %d\n", 
+        printf( "range line (first in granule) = %d\n",
                 CPL_SWAP32( unValue ) );
 
         /* field 4 */
@@ -137,7 +136,7 @@ int main( int argc, char ** argv )
         CPL_SWAP32PTR( abyRecord + 271 );
         CPL_SWAP32PTR( abyRecord + 275 );
 
-        printf( "end line: mjd_days = %d, sec = %d, msec = %d\n", 
+        printf( "end line: mjd_days = %d, sec = %d, msec = %d\n",
                 ((int *) (abyRecord + 267))[0],
                 ((unsigned int *) (abyRecord + 267))[1],
                 ((unsigned int *) (abyRecord + 267))[2] );
diff --git a/frmts/envisat/envisat_dump.c b/frmts/envisat/envisat_dump.c
index 18bd5ac..795000e 100644
--- a/frmts/envisat/envisat_dump.c
+++ b/frmts/envisat/envisat_dump.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: envisat_dump.c 9484 2006-04-04 02:44:16Z fwarmerdam $
+ * $Id: envisat_dump.c 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  APP ENVISAT Support
  * Purpose:  Test mainline for dumping ENVISAT format files.
@@ -43,44 +43,43 @@ int main( int argc, char ** argv )
         exit( 1 );
     }
 
-    
     if( EnvisatFile_Open( &es_file, argv[1], "r" ) != 0 )
     {
         printf( "EnvisatFile_Open(%s) failed.\n", argv[1] );
         exit( 2 );
     }
-    
+
     printf( "MPH\n" );
     printf( "===\n" );
 
-    for( i = 0; 
+    for( i = 0;
          (key = EnvisatFile_GetKeyByIndex( es_file, MPH, i )) != NULL;
          i++ )
     {
-        const char	*value = EnvisatFile_GetKeyValueAsString( es_file, 
-                                                                  MPH, 
+        const char	*value = EnvisatFile_GetKeyValueAsString( es_file,
+                                                                  MPH,
                                                                   key,
                                                                   "" );
 
         printf( "%s = [%s]\n", key, value );
     }
-    
+
     printf( "\n" );
     printf( "SPH\n" );
     printf( "===\n" );
 
-    for( i = 0; 
+    for( i = 0;
          (key = EnvisatFile_GetKeyByIndex( es_file, SPH, i )) != NULL;
          i++ )
     {
-        const char	*value = EnvisatFile_GetKeyValueAsString( es_file, 
-                                                                  SPH, 
+        const char	*value = EnvisatFile_GetKeyValueAsString( es_file,
+                                                                  SPH,
                                                                   key,
                                                                   "" );
 
         printf( "%s = [%s]\n", key, value );
     }
-    
+
     printf( "\n" );
     printf( "Datasets\n" );
     printf( "========\n" );
@@ -90,12 +89,12 @@ int main( int argc, char ** argv )
         char	*ds_name, *ds_type, *filename;
         int	ds_offset, ds_size, num_dsr, dsr_size;
 
-        if( EnvisatFile_GetDatasetInfo( es_file, 
-                                        i, 
-                                        &ds_name, 
-                                        &ds_type, 
-                                        &filename, 
-                                        &ds_offset, 
+        if( EnvisatFile_GetDatasetInfo( es_file,
+                                        i,
+                                        &ds_name,
+                                        &ds_type,
+                                        &filename,
+                                        &ds_offset,
                                         &ds_size,
                                         &num_dsr,
                                         &dsr_size ) == 1 )
diff --git a/frmts/envisat/envisatdataset.cpp b/frmts/envisat/envisatdataset.cpp
index d9caec6..d3d6d6a 100644
--- a/frmts/envisat/envisatdataset.cpp
+++ b/frmts/envisat/envisatdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: envisatdataset.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: envisatdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  APP ENVISAT Support
  * Purpose:  Reader for ENVISAT format image data.
@@ -28,23 +28,20 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "timedelta.hpp"
 #include "adsrange.hpp"
 #include "rawdataset.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
 #include "ogr_srs_api.h"
+#include "timedelta.hpp"
 
-CPL_CVSID("$Id: envisatdataset.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: envisatdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 CPL_C_START
 #include "EnvisatFile.h"
 #include "records.h"
 CPL_C_END
 
-CPL_C_START
-void	GDALRegister_Envisat(void);
-CPL_C_END
-
 /************************************************************************/
 /* ==================================================================== */
 /*                        MerisL2FlagBand                         */
@@ -53,13 +50,13 @@ CPL_C_END
 class MerisL2FlagBand : public GDALPamRasterBand
 {
   public:
-    MerisL2FlagBand( GDALDataset *, int, VSILFILE*, off_t, off_t );
+    MerisL2FlagBand( GDALDataset *, int, VSILFILE*, vsi_l_offset, int );
     virtual ~MerisL2FlagBand();
     virtual CPLErr IReadBlock( int, int, void * );
 
   private:
-    off_t nImgOffset;
-    off_t nPrefixBytes;
+    vsi_l_offset nImgOffset;
+    int nPrefixBytes;
     size_t nBytePerPixel;
     size_t nRecordSize;
     size_t nDataSize;
@@ -70,22 +67,22 @@ class MerisL2FlagBand : public GDALPamRasterBand
 /************************************************************************/
 /*                        MerisL2FlagBand()                       */
 /************************************************************************/
-MerisL2FlagBand::MerisL2FlagBand( GDALDataset *poDS, int nBand,
-                                  VSILFILE* fpImage, off_t nImgOffset,
-                                  off_t nPrefixBytes )
+MerisL2FlagBand::MerisL2FlagBand( GDALDataset *poDSIn, int nBandIn,
+                                  VSILFILE* fpImageIn, vsi_l_offset nImgOffsetIn,
+                                  int nPrefixBytesIn ) :
+    nBytePerPixel(3)
 {
-    this->poDS = (GDALDataset *) poDS;
-    this->nBand = nBand;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
 
-    this->fpImage = fpImage;
-    this->nImgOffset = nImgOffset;
-    this->nPrefixBytes = nPrefixBytes;
+    this->fpImage = fpImageIn;
+    this->nImgOffset = nImgOffsetIn;
+    this->nPrefixBytes = nPrefixBytesIn;
 
     eDataType = GDT_UInt32;
 
     nBlockXSize = poDS->GetRasterXSize();
     nBlockYSize = 1;
-    nBytePerPixel = 3;
 
     nDataSize = nBlockXSize * nBytePerPixel;
     nRecordSize = nPrefixBytes + nDataSize;
@@ -112,7 +109,7 @@ CPLErr MerisL2FlagBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     CPLAssert( nBlockXOff == 0 );
     CPLAssert( pReadBuf != NULL );
 
-    off_t nOffset = nImgOffset + nPrefixBytes +
+    vsi_l_offset nOffset = nImgOffset + nPrefixBytes +
                     nBlockYOff * nBlockYSize * nRecordSize;
 
     if ( VSIFSeekL( fpImage, nOffset, SEEK_SET ) != 0 )
@@ -131,10 +128,9 @@ CPLErr MerisL2FlagBand::IReadBlock( CPL_UNUSED int nBlockXOff,
         return CE_Failure;
     }
 
-    unsigned iImg, iBuf;
-    for( iImg = 0, iBuf = 0;
-         iImg < nBlockXSize * sizeof(GDT_UInt32);
-         iImg += sizeof(GDT_UInt32), iBuf += nBytePerPixel )
+    for( unsigned iImg = 0, iBuf = 0;
+         iImg < nBlockXSize * (unsigned)sizeof(GDT_UInt32);
+         iImg += (unsigned)sizeof(GDT_UInt32), iBuf += (unsigned)nBytePerPixel )
     {
 #ifdef CPL_LSB
         ((GByte*) pImage)[iImg] = pReadBuf[iBuf + 2];
@@ -172,7 +168,7 @@ class EnvisatDataset : public RawDataset
     void        ScanForGCPs_ASAR();
     void        ScanForGCPs_MERIS();
 
-    void        UnwrapGCPs(); 
+    void        UnwrapGCPs();
 
     void	CollectMetadata( EnvisatFile_HeaderFlag );
     void        CollectDSDMetadata();
@@ -202,13 +198,13 @@ class EnvisatDataset : public RawDataset
 /*                            EnvisatDataset()                             */
 /************************************************************************/
 
-EnvisatDataset::EnvisatDataset()
+EnvisatDataset::EnvisatDataset() :
+    hEnvisatFile(NULL),
+    fpImage(NULL),
+    nGCPCount(0),
+    pasGCPList(NULL),
+    papszTempMD(NULL)
 {
-    hEnvisatFile = NULL;
-    fpImage = NULL;
-    nGCPCount = 0;
-    pasGCPList = NULL;
-    papszTempMD = NULL;
 }
 
 /************************************************************************/
@@ -224,7 +220,7 @@ EnvisatDataset::~EnvisatDataset()
         EnvisatFile_Close( hEnvisatFile );
 
     if( fpImage != NULL )
-        VSIFCloseL( fpImage );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fpImage ));
 
     if( nGCPCount > 0 )
     {
@@ -254,8 +250,8 @@ const char *EnvisatDataset::GetGCPProjection()
 {
     if( nGCPCount > 0 )
         return SRS_WKT_WGS84;
-    else
-        return "";
+
+    return "";
 }
 
 /************************************************************************/
@@ -276,9 +272,9 @@ const GDAL_GCP *EnvisatDataset::GetGCPs()
 void EnvisatUnwrapGCPs( int nGCPCount, GDAL_GCP *pasGCPList ) ;
 
 void  EnvisatDataset::UnwrapGCPs()
-{ 
+{
     EnvisatUnwrapGCPs( nGCPCount, pasGCPList ) ;
-} 
+}
 
 /************************************************************************/
 /*                          ScanForGCPs_ASAR()                          */
@@ -287,16 +283,15 @@ void  EnvisatDataset::UnwrapGCPs()
 void EnvisatDataset::ScanForGCPs_ASAR()
 
 {
-    int		nDatasetIndex, nNumDSR, nDSRSize, iRecord;
-
 /* -------------------------------------------------------------------- */
 /*      Do we have a meaningful geolocation grid?                       */
 /* -------------------------------------------------------------------- */
-    nDatasetIndex = EnvisatFile_GetDatasetIndex( hEnvisatFile,
-                                                 "GEOLOCATION GRID ADS" );
+    int nDatasetIndex = EnvisatFile_GetDatasetIndex( hEnvisatFile,
+                                                     "GEOLOCATION GRID ADS" );
     if( nDatasetIndex == -1 )
         return;
 
+    int nNumDSR, nDSRSize;
     if( EnvisatFile_GetDatasetInfo( hEnvisatFile, nDatasetIndex,
                                     NULL, NULL, NULL, NULL, NULL,
                                     &nNumDSR, &nDSRSize ) != SUCCESS )
@@ -309,13 +304,13 @@ void EnvisatDataset::ScanForGCPs_ASAR()
 /*      Collect the first GCP set from each record.			*/
 /* -------------------------------------------------------------------- */
     GByte	abyRecord[521];
-    int  	nRange=0, nSample, iGCP, nRangeOffset=0;
+    int  	nRange=0, nRangeOffset=0;
     GUInt32 	unValue;
 
     nGCPCount = 0;
     pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),(nNumDSR+1) * 11);
 
-    for( iRecord = 0; iRecord < nNumDSR; iRecord++ )
+    for( int iRecord = 0; iRecord < nNumDSR; iRecord++ )
     {
         if( EnvisatFile_ReadDatasetRecord( hEnvisatFile, nDatasetIndex,
                                            iRecord, abyRecord ) != SUCCESS )
@@ -332,19 +327,18 @@ void EnvisatDataset::ScanForGCPs_ASAR()
             nRangeOffset = nRange-1;
         }
 
-        for( iGCP = 0; iGCP < 11; iGCP++ )
+        for( int iGCP = 0; iGCP < 11; iGCP++ )
         {
-            char	szId[128];
-
             GDALInitGCPs( 1, pasGCPList + nGCPCount );
 
             CPLFree( pasGCPList[nGCPCount].pszId );
 
-            sprintf( szId, "%d", nGCPCount+1 );
+            char szId[128];
+            snprintf( szId, sizeof(szId), "%d", nGCPCount+1 );
             pasGCPList[nGCPCount].pszId = CPLStrdup( szId );
 
             memcpy( &unValue, abyRecord + 25 + iGCP*4, 4 );
-            nSample = CPL_MSBWORD32(unValue);
+            int nSample = CPL_MSBWORD32(unValue);
 
             memcpy( &unValue, abyRecord + 25 + 176 + iGCP*4, 4 );
             pasGCPList[nGCPCount].dfGCPX = ((int)CPL_MSBWORD32(unValue))*0.000001;
@@ -367,19 +361,18 @@ void EnvisatDataset::ScanForGCPs_ASAR()
     memcpy( &unValue, abyRecord + 17, 4 );
     nRange = nRange + CPL_MSBWORD32( unValue ) - 1;
 
-    for( iGCP = 0; iGCP < 11; iGCP++ )
+    for( int iGCP = 0; iGCP < 11; iGCP++ )
     {
-        char	szId[128];
-
         GDALInitGCPs( 1, pasGCPList + nGCPCount );
 
         CPLFree( pasGCPList[nGCPCount].pszId );
 
-        sprintf( szId, "%d", nGCPCount+1 );
+        char szId[128];
+        snprintf( szId, sizeof(szId), "%d", nGCPCount+1 );
         pasGCPList[nGCPCount].pszId = CPLStrdup( szId );
 
         memcpy( &unValue, abyRecord + 279 + iGCP*4, 4 );
-        nSample = CPL_MSBWORD32(unValue);
+        int nSample = CPL_MSBWORD32(unValue);
 
         memcpy( &unValue, abyRecord + 279 + 176 + iGCP*4, 4 );
         pasGCPList[nGCPCount].dfGCPX = ((int)CPL_MSBWORD32(unValue))*0.000001;
@@ -403,19 +396,17 @@ void EnvisatDataset::ScanForGCPs_ASAR()
 void EnvisatDataset::ScanForGCPs_MERIS()
 
 {
-    int		nDatasetIndex, nNumDSR, nDSRSize;
-    bool    isBrowseProduct ; 
-
 /* -------------------------------------------------------------------- */
-/*      Do we have a meaningful geolocation grid?  Seach for a          */
+/*      Do we have a meaningful geolocation grid?  Search for a         */
 /*      DS_TYPE=A and a name containing "geolocation" or "tie           */
 /*      points".                                                        */
 /* -------------------------------------------------------------------- */
-    nDatasetIndex = EnvisatFile_GetDatasetIndex( hEnvisatFile,
-                                                 "Tie points ADS" );
+    int nDatasetIndex = EnvisatFile_GetDatasetIndex( hEnvisatFile,
+                                                     "Tie points ADS" );
     if( nDatasetIndex == -1 )
         return;
 
+    int nNumDSR, nDSRSize;
     if( EnvisatFile_GetDatasetInfo( hEnvisatFile, nDatasetIndex,
                                     NULL, NULL, NULL, NULL, NULL,
                                     &nNumDSR, &nDSRSize ) != SUCCESS )
@@ -427,33 +418,28 @@ void EnvisatDataset::ScanForGCPs_MERIS()
 /* -------------------------------------------------------------------- */
 /*      Figure out the tiepoint space, and how many we have.            */
 /* -------------------------------------------------------------------- */
-    int  nLinesPerTiePoint, nSamplesPerTiePoint;
-    int  nTPPerLine, nTPPerColumn = nNumDSR;
-
-    if( nNumDSR == 0 )
-        return;
-
-    nLinesPerTiePoint =
+    int nLinesPerTiePoint =
         EnvisatFile_GetKeyValueAsInt( hEnvisatFile, SPH,
                                       "LINES_PER_TIE_PT", 0 );
-    nSamplesPerTiePoint =
+    int nSamplesPerTiePoint =
         EnvisatFile_GetKeyValueAsInt( hEnvisatFile, SPH,
                                       "SAMPLES_PER_TIE_PT", 0 );
 
     if( nLinesPerTiePoint == 0 || nSamplesPerTiePoint == 0 )
         return;
 
-    nTPPerLine = (GetRasterXSize() + nSamplesPerTiePoint - 1)
+    int nTPPerColumn = nNumDSR;
+    int nTPPerLine = (GetRasterXSize() + nSamplesPerTiePoint - 1)
         / nSamplesPerTiePoint;
 
 /* -------------------------------------------------------------------- */
-/*      Find a Mesurement type dataset to use as a reference raster     */
+/*      Find a measurement type dataset to use as a reference raster    */
 /*      band.                                                           */
 /* -------------------------------------------------------------------- */
 
-    int		nMDSIndex;
+    int nMDSIndex = 0;
 
-    for( nMDSIndex = 0; TRUE; nMDSIndex++ )
+    for( ; true; nMDSIndex++ )
     {
         char *pszDSType;
         if( EnvisatFile_GetDatasetInfo( hEnvisatFile, nMDSIndex,
@@ -471,21 +457,21 @@ void EnvisatDataset::ScanForGCPs_MERIS()
 /* -------------------------------------------------------------------- */
 
     /* get the MDS line sampling time interval */
-    TimeDelta tdMDSSamplingInterval( 0 , 0 ,  
+    TimeDelta tdMDSSamplingInterval( 0 , 0 ,
         EnvisatFile_GetKeyValueAsInt( hEnvisatFile, SPH,
                                       "LINE_TIME_INTERVAL", 0  ) );
 
     /* get range of TiePoint ADS records matching the measurements */
-    ADSRangeLastAfter arTP( *hEnvisatFile , nDatasetIndex, 
-        nMDSIndex , tdMDSSamplingInterval ) ; 
-    
-    /* check if there are any TPs to be used */ 
+    ADSRangeLastAfter arTP( *hEnvisatFile , nDatasetIndex,
+        nMDSIndex , tdMDSSamplingInterval ) ;
+
+    /* check if there are any TPs to be used */
     if ( arTP.getDSRCount() <= 0 )
     {
         CPLDebug( "EnvisatDataset" , "No tiepoint covering "
             "the measurement records." ) ;
         return; /* No TPs - no extraction. */
-    } 
+    }
 
     /* check if TPs cover the whole range of MDSRs */
     if(( arTP.getFirstOffset() < 0 )||( arTP.getLastOffset() < 0 ))
@@ -495,27 +481,28 @@ void EnvisatDataset::ScanForGCPs_MERIS()
         /* Not good but we can still extract some of the TPS, can we? */
     }
 
-    /* check TP records spacing */
-    if ((1+(arTP.getFirstOffset()+arTP.getLastOffset()+GetRasterYSize()-1) 
+    /* Check TP record spacing */
+    if ((1+(arTP.getFirstOffset()+arTP.getLastOffset()+GetRasterYSize()-1)
            / nLinesPerTiePoint ) != arTP.getDSRCount() )
     {
-        CPLDebug( "EnvisatDataset", "Not enough tieponts per column! "
-            "received=%d expected=%d", nTPPerColumn , 
-                1 + (arTP.getFirstOffset()+arTP.getLastOffset()+
-                      GetRasterYSize()-1) / nLinesPerTiePoint ) ; 
-        return; /* That is far more serious - we risk missplaces TPs. */
+        CPLDebug( "EnvisatDataset", "Not enough tiepoints per column! "
+                  "received=%d expected=%d", nTPPerColumn ,
+                  1 + (arTP.getFirstOffset()+arTP.getLastOffset()+
+                       GetRasterYSize()-1) / nLinesPerTiePoint ) ;
+        return;  // That is far more serious - we risk misplacing TPs.
     }
 
+    bool isBrowseProduct;
     if ( 50*nTPPerLine + 13 == nDSRSize ) /* regular product */
     {
-        isBrowseProduct = false ; 
-    } 
+        isBrowseProduct = false ;
+    }
     else if ( 8*nTPPerLine + 13 == nDSRSize ) /* browse product */
-    { 
+    {
         /* although BPs are rare there is no reason not to support them */
-        isBrowseProduct = true ; 
-    } 
-    else 
+        isBrowseProduct = true ;
+    }
+    else
     {
         CPLDebug( "EnvisatDataset", "Unexpectd size of 'Tie points ADS' !"
                 " received=%d expected=%d or %d" , nDSRSize ,
@@ -528,54 +515,52 @@ void EnvisatDataset::ScanForGCPs_MERIS()
 /* -------------------------------------------------------------------- */
 
     GByte	*pabyRecord = (GByte *) CPLMalloc(nDSRSize-13);
-    int  	iGCP;
 
-    GUInt32 *tpLat = ((GUInt32*)pabyRecord) + nTPPerLine*0 ; /* latitude */  
-    GUInt32 *tpLon = ((GUInt32*)pabyRecord) + nTPPerLine*1 ; /* longitude */  
+    GUInt32 *tpLat = ((GUInt32*)pabyRecord) + nTPPerLine*0 ; /* latitude */
+    GUInt32 *tpLon = ((GUInt32*)pabyRecord) + nTPPerLine*1 ; /* longitude */
     GUInt32 *tpLtc = ((GUInt32*)pabyRecord) + nTPPerLine*4 ; /* lat. DEM correction */
-    GUInt32 *tpLnc = ((GUInt32*)pabyRecord) + nTPPerLine*5 ; /* lon. DEM correction */ 
+    GUInt32 *tpLnc = ((GUInt32*)pabyRecord) + nTPPerLine*5 ; /* lon. DEM correction */
 
     nGCPCount = 0;
-    pasGCPList = (GDAL_GCP *) CPLCalloc( sizeof(GDAL_GCP), 
+    pasGCPList = (GDAL_GCP *) CPLCalloc( sizeof(GDAL_GCP),
                                         arTP.getDSRCount() * nTPPerLine );
 
     for( int ir = 0 ; ir < arTP.getDSRCount() ; ir++ )
     {
-        int iRecord = ir + arTP.getFirstIndex() ; 
+        int iRecord = ir + arTP.getFirstIndex() ;
 
-        double dfGCPLine = 0.5 + 
-            ( iRecord*nLinesPerTiePoint - arTP.getFirstOffset() ) ; 
+        double dfGCPLine = 0.5 +
+            ( iRecord*nLinesPerTiePoint - arTP.getFirstOffset() ) ;
 
         if( EnvisatFile_ReadDatasetRecordChunk( hEnvisatFile, nDatasetIndex,
                     iRecord , pabyRecord, 13 , -1 ) != SUCCESS )
             continue;
 
-        for( iGCP = 0; iGCP < nTPPerLine; iGCP++ )
+        for( int iGCP = 0; iGCP < nTPPerLine; iGCP++ )
         {
-            char	szId[128];
-
             GDALInitGCPs( 1, pasGCPList + nGCPCount );
 
             CPLFree( pasGCPList[nGCPCount].pszId );
 
-            sprintf( szId, "%d", nGCPCount+1 );
+            char szId[128];
+            snprintf( szId, sizeof(szId), "%d", nGCPCount+1 );
             pasGCPList[nGCPCount].pszId = CPLStrdup( szId );
 
-            #define INT32(x)    ((GInt32)CPL_MSBWORD32(x)) 
+            #define INT32(x)    ((GInt32)CPL_MSBWORD32(x))
 
-            pasGCPList[nGCPCount].dfGCPX = 1e-6*INT32(tpLon[iGCP]) ; 
-            pasGCPList[nGCPCount].dfGCPY = 1e-6*INT32(tpLat[iGCP]) ; 
+            pasGCPList[nGCPCount].dfGCPX = 1e-6*INT32(tpLon[iGCP]) ;
+            pasGCPList[nGCPCount].dfGCPY = 1e-6*INT32(tpLat[iGCP]) ;
             pasGCPList[nGCPCount].dfGCPZ = 0.0;
 
             if( !isBrowseProduct ) /* add DEM corrections */
-            { 
-                pasGCPList[nGCPCount].dfGCPX += 1e-6*INT32(tpLnc[iGCP]) ; 
-                pasGCPList[nGCPCount].dfGCPY += 1e-6*INT32(tpLtc[iGCP]) ; 
-            } 
+            {
+                pasGCPList[nGCPCount].dfGCPX += 1e-6*INT32(tpLnc[iGCP]) ;
+                pasGCPList[nGCPCount].dfGCPY += 1e-6*INT32(tpLtc[iGCP]) ;
+            }
 
             #undef INT32
 
-            pasGCPList[nGCPCount].dfGCPLine = dfGCPLine ; 
+            pasGCPList[nGCPCount].dfGCPLine = dfGCPLine ;
             pasGCPList[nGCPCount].dfGCPPixel = iGCP*nSamplesPerTiePoint + 0.5;
 
             nGCPCount++;
@@ -600,18 +585,18 @@ char **EnvisatDataset::GetMetadataDomainList()
 char **EnvisatDataset::GetMetadata( const char * pszDomain )
 
 {
-    if( pszDomain == NULL || !EQUALN(pszDomain,"envisat-ds-",11) )
+    if( pszDomain == NULL || !STARTS_WITH_CI(pszDomain, "envisat-ds-") )
         return GDALDataset::GetMetadata( pszDomain );
 
 /* -------------------------------------------------------------------- */
 /*      Get the dataset name and record number.                         */
 /* -------------------------------------------------------------------- */
-    char	szDSName[128];
-    int         i, nRecord = -1;
-
+    char szDSName[128];
     strncpy( szDSName, pszDomain+11, sizeof(szDSName) );
     szDSName[sizeof(szDSName)-1] = 0;
-    for( i = 0; i < (int) sizeof(szDSName)-1; i++ )
+
+    int nRecord = -1;
+    for( int i = 0; i < (int) sizeof(szDSName)-1; i++ )
     {
         if( szDSName[i] == '-' )
         {
@@ -628,11 +613,10 @@ char **EnvisatDataset::GetMetadata( const char * pszDomain )
 /*      Get the dataset index and info.                                 */
 /* -------------------------------------------------------------------- */
     int nDSIndex = EnvisatFile_GetDatasetIndex( hEnvisatFile, szDSName );
-    int nDSRSize, nNumDSR;
-
     if( nDSIndex == -1 )
         return NULL;
 
+    int nDSRSize, nNumDSR;
     EnvisatFile_GetDatasetInfo( hEnvisatFile, nDSIndex, NULL, NULL, NULL,
                                 NULL, NULL, &nNumDSR, &nDSRSize );
 
@@ -642,9 +626,7 @@ char **EnvisatDataset::GetMetadata( const char * pszDomain )
 /* -------------------------------------------------------------------- */
 /*      Read the requested record.                                      */
 /* -------------------------------------------------------------------- */
-    char  *pszRecord;
-
-    pszRecord = (char *) CPLMalloc(nDSRSize+1);
+    char  *pszRecord = (char *) CPLMalloc(nDSRSize+1);
 
     if( EnvisatFile_ReadDatasetRecord( hEnvisatFile, nDSIndex, nRecord,
                                        pszRecord ) == FAILURE )
@@ -657,16 +639,14 @@ char **EnvisatDataset::GetMetadata( const char * pszDomain )
 /*      Massage the data into a safe textual format.  For now we        */
 /*      just turn zero bytes into spaces.                               */
 /* -------------------------------------------------------------------- */
-    char *pszEscapedRecord;
-
     CSLDestroy( papszTempMD );
 
-    pszEscapedRecord = CPLEscapeString( pszRecord, nDSRSize,
-                                        CPLES_BackslashQuotable );
+    char *pszEscapedRecord
+        = CPLEscapeString( pszRecord, nDSRSize, CPLES_BackslashQuotable );
     papszTempMD = CSLSetNameValue( NULL, "EscapedRecord", pszEscapedRecord );
     CPLFree( pszEscapedRecord );
 
-    for( i = 0; i < nDSRSize; i++ )
+    for( int i = 0; i < nDSRSize; i++ )
         if( pszRecord[i] == '\0' )
             pszRecord[i] = ' ';
 
@@ -688,31 +668,30 @@ void EnvisatDataset::CollectDSDMetadata()
 
 {
     char	*pszDSName, *pszFilename;
-    int		iDSD;
 
-    for( iDSD = 0;
+    for( int iDSD = 0;
          EnvisatFile_GetDatasetInfo( hEnvisatFile, iDSD, &pszDSName, NULL,
                              &pszFilename, NULL, NULL, NULL, NULL ) == SUCCESS;
          iDSD++ )
     {
         if( pszFilename == NULL
             || strlen(pszFilename) == 0
-            || EQUALN(pszFilename,"NOT USED",8)
-            || EQUALN(pszFilename,"        ",8))
+            || STARTS_WITH_CI(pszFilename, "NOT USED")
+            || STARTS_WITH_CI(pszFilename, "        "))
             continue;
 
-        char	szKey[128], szTrimmedName[128];
-        int	i;
+        const int max_len = 128;
+        char szKey[max_len];
 
-        strcpy( szKey, "DS_" );
-        strcat( szKey, pszDSName );
+        strcpy( szKey, "DS_");
+        strncat( szKey, pszDSName, max_len - strlen(szKey) - 1 );
 
         // strip trailing spaces.
-        for( i = strlen(szKey)-1; i && szKey[i] == ' '; i-- )
+        for( int i = static_cast<int>(strlen(szKey))-1; i && szKey[i] == ' '; i-- )
             szKey[i] = '\0';
 
         // convert spaces into underscores.
-        for( i = 0; szKey[i] != '\0'; i++ )
+        for( int i = 0; szKey[i] != '\0'; i++ )
         {
             if( szKey[i] == ' ' )
                 szKey[i] = '_';
@@ -720,8 +699,9 @@ void EnvisatDataset::CollectDSDMetadata()
 
         strcat( szKey, "_NAME" );
 
+        char szTrimmedName[max_len];
         strcpy( szTrimmedName, pszFilename );
-        for( i = strlen(szTrimmedName)-1; i && szTrimmedName[i] == ' '; i--)
+        for( int i = static_cast<int>(strlen(szTrimmedName))-1; i && szTrimmedName[i] == ' '; i--)
             szTrimmedName[i] = '\0';
 
         SetMetadataItem( szKey, szTrimmedName );
@@ -736,21 +716,14 @@ void EnvisatDataset::CollectDSDMetadata()
 
 void EnvisatDataset::CollectADSMetadata()
 {
-    int nDSIndex, nNumDsr, nDSRSize;
-    int nRecord;
+    int nNumDsr, nDSRSize;
     const char *pszDSName, *pszDSType, *pszDSFilename;
-    const char *pszProduct;
-    char *pszRecord;
-    char szPrefix[128], szKey[128], szValue[1024];
-    int i;
-    CPLErr ret;
-    const EnvisatRecordDescr *pRecordDescr = NULL;
-    const EnvisatFieldDescr *pField;
-
-    pszProduct = EnvisatFile_GetKeyValueAsString( hEnvisatFile, MPH,
-                                                  "PRODUCT", "" );
-
-    for( nDSIndex = 0;
+
+    const char *pszProduct
+        = EnvisatFile_GetKeyValueAsString( hEnvisatFile, MPH,
+                                           "PRODUCT", "" );
+
+    for( int nDSIndex = 0;
          EnvisatFile_GetDatasetInfo( hEnvisatFile, nDSIndex,
                                      (char **) &pszDSName,
                                      (char **) &pszDSType,
@@ -759,28 +732,29 @@ void EnvisatDataset::CollectADSMetadata()
                                      &nNumDsr, &nDSRSize ) == SUCCESS;
          ++nDSIndex )
     {
-        if( EQUALN(pszDSFilename,"NOT USED",8) || (nNumDsr <= 0) )
+        if( STARTS_WITH_CI(pszDSFilename, "NOT USED") || (nNumDsr <= 0) )
             continue;
         if( !EQUAL(pszDSType,"A") && !EQUAL(pszDSType,"G") )
             continue;
 
-        for ( nRecord = 0; nRecord < nNumDsr; ++nRecord )
+        for ( int nRecord = 0; nRecord < nNumDsr; ++nRecord )
         {
+            char szPrefix[128];
             strncpy( szPrefix, pszDSName, sizeof(szPrefix) - 1);
             szPrefix[sizeof(szPrefix) - 1] = '\0';
 
             // strip trailing spaces
-            for( i = strlen(szPrefix)-1; i && szPrefix[i] == ' '; --i )
+            for( int i = static_cast<int>(strlen(szPrefix))-1; i && szPrefix[i] == ' '; --i )
                 szPrefix[i] = '\0';
 
             // convert spaces into underscores
-            for( i = 0; szPrefix[i] != '\0'; i++ )
+            for( int i = 0; szPrefix[i] != '\0'; i++ )
             {
                 if( szPrefix[i] == ' ' )
                     szPrefix[i] = '_';
             }
 
-            pszRecord = (char *) CPLMalloc(nDSRSize+1);
+            char *pszRecord = (char *) CPLMalloc(nDSRSize+1);
 
             if( EnvisatFile_ReadDatasetRecord( hEnvisatFile, nDSIndex, nRecord,
                                                pszRecord ) == FAILURE )
@@ -789,21 +763,23 @@ void EnvisatDataset::CollectADSMetadata()
                 return;
             }
 
-            pRecordDescr = EnvisatFile_GetRecordDescriptor(pszProduct, pszDSName);
+            const EnvisatRecordDescr *pRecordDescr
+                = EnvisatFile_GetRecordDescriptor(pszProduct, pszDSName);
             if (pRecordDescr)
             {
-                pField = pRecordDescr->pFields;
+                const EnvisatFieldDescr *pField = pRecordDescr->pFields;
                 while ( pField && pField->szName )
                 {
-                    ret = EnvisatFile_GetFieldAsString(pszRecord, nDSRSize,
-                                           pField, szValue);
-                    if ( ret == CE_None )
+                    char szValue[1024];
+                    if ( CE_None == EnvisatFile_GetFieldAsString(pszRecord, nDSRSize,
+                                                                 pField, szValue, sizeof(szValue)) )
                     {
+                        char szKey[128];
                         if (nNumDsr == 1)
-                            sprintf(szKey, "%s_%s", szPrefix, pField->szName);
+                            snprintf( szKey, sizeof(szKey), "%s_%s", szPrefix, pField->szName);
                         else
                             // sprintf(szKey, "%s_%02d_%s", szPrefix, nRecord,
-                            sprintf(szKey, "%s_%d_%s", szPrefix, nRecord,
+                            snprintf( szKey, sizeof(szKey), "%s_%d_%s", szPrefix, nRecord,
                                     pField->szName);
                         SetMetadataItem(szKey, szValue, "RECORDS");
                     }
@@ -826,19 +802,16 @@ void EnvisatDataset::CollectADSMetadata()
 void EnvisatDataset::CollectMetadata( EnvisatFile_HeaderFlag  eMPHOrSPH )
 
 {
-    int		iKey;
-
-    for( iKey = 0; TRUE; iKey++ )
+    for( int iKey = 0; true; iKey++ )
     {
-        const char *pszValue, *pszKey;
-        char  szHeaderKey[128];
-
-        pszKey = EnvisatFile_GetKeyByIndex(hEnvisatFile, eMPHOrSPH, iKey);
+        const char *pszKey
+            = EnvisatFile_GetKeyByIndex(hEnvisatFile, eMPHOrSPH, iKey);
         if( pszKey == NULL )
             break;
 
-        pszValue = EnvisatFile_GetKeyValueAsString( hEnvisatFile, eMPHOrSPH,
-                                                    pszKey, NULL );
+        const char *pszValue
+            = EnvisatFile_GetKeyValueAsString( hEnvisatFile, eMPHOrSPH,
+                                               pszKey, NULL );
 
         if( pszValue == NULL )
             continue;
@@ -851,10 +824,11 @@ void EnvisatDataset::CollectMetadata( EnvisatFile_HeaderFlag  eMPHOrSPH )
             || EQUAL(pszKey,"NUM_DATA_SETS") )
             continue;
 
+        char szHeaderKey[128];
         if( eMPHOrSPH == MPH )
-            sprintf( szHeaderKey, "MPH_%s", pszKey );
+            snprintf( szHeaderKey, sizeof(szHeaderKey), "MPH_%s", pszKey );
         else
-            sprintf( szHeaderKey, "SPH_%s", pszKey );
+            snprintf( szHeaderKey, sizeof(szHeaderKey), "SPH_%s", pszKey );
 
         SetMetadataItem( szHeaderKey, pszValue );
     }
@@ -867,34 +841,32 @@ void EnvisatDataset::CollectMetadata( EnvisatFile_HeaderFlag  eMPHOrSPH )
 GDALDataset *EnvisatDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    EnvisatFile	*hEnvisatFile;
-
 /* -------------------------------------------------------------------- */
 /*      Check the header.                                               */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->nHeaderBytes < 8 )
         return NULL;
 
-    if( !EQUALN((const char *) poOpenInfo->pabyHeader, "PRODUCT=",8) )
+    if( !STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "PRODUCT=") )
         return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Try opening the dataset.                                        */
 /* -------------------------------------------------------------------- */
-    int		ds_index;
-
+    EnvisatFile	*hEnvisatFile;
     if( EnvisatFile_Open( &hEnvisatFile, poOpenInfo->pszFilename, "r" )
         == FAILURE )
         return NULL;
 
 /* -------------------------------------------------------------------- */
-/*      Find a Mesurement type dataset to use as our reference          */
+/*      Find a measurement type dataset to use as our reference          */
 /*      raster band.                                                    */
 /* -------------------------------------------------------------------- */
-    int		dsr_size, num_dsr, ds_offset, bNative;
+    int         dsr_size, num_dsr, ds_offset;
     char        *pszDSType;
 
-    for( ds_index = 0; TRUE; ds_index++ )
+    int ds_index = 0;
+    for( ; true; ds_index++ )
     {
         if( EnvisatFile_GetDatasetInfo( hEnvisatFile, ds_index,
                                         NULL, &pszDSType, NULL,
@@ -902,7 +874,8 @@ GDALDataset *EnvisatDataset::Open( GDALOpenInfo * poOpenInfo )
                                         &num_dsr, &dsr_size ) == FAILURE )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "Unable to find \"MDS1\" measurement datatset in Envisat file." );
+                      "Unable to find \"MDS1\" measurement dataset in "
+                      "Envisat file." );
             EnvisatFile_Close( hEnvisatFile );
             return NULL;
         }
@@ -926,19 +899,13 @@ GDALDataset *EnvisatDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    EnvisatDataset 	*poDS;
-
-    poDS = new EnvisatDataset();
+    EnvisatDataset *poDS = new EnvisatDataset();
 
     poDS->hEnvisatFile = hEnvisatFile;
 
 /* -------------------------------------------------------------------- */
 /*      Setup image definition.                                         */
 /* -------------------------------------------------------------------- */
-    const char  *pszDataType, *pszSampleType, *pszProduct;
-    GDALDataType eDataType;
-    int          nPrefixBytes;
-
     EnvisatFile_GetDatasetInfo( hEnvisatFile, ds_index,
                                 NULL, NULL, NULL, &ds_offset, NULL,
                                 &num_dsr, &dsr_size );
@@ -948,23 +915,27 @@ GDALDataset *EnvisatDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->nRasterYSize = num_dsr;
     poDS->eAccess = GA_ReadOnly;
 
-    pszProduct = EnvisatFile_GetKeyValueAsString( hEnvisatFile, MPH,
-                                                  "PRODUCT", "" );
-    pszDataType = EnvisatFile_GetKeyValueAsString( hEnvisatFile, SPH,
-                                                   "DATA_TYPE", "" );
-    pszSampleType = EnvisatFile_GetKeyValueAsString( hEnvisatFile, SPH,
-                                                     "SAMPLE_TYPE", "" );
-    if( EQUAL(pszDataType,"FLT32") && EQUALN(pszSampleType,"COMPLEX",7))
+    const char *pszProduct
+        = EnvisatFile_GetKeyValueAsString( hEnvisatFile, MPH, "PRODUCT", "" );
+    const char *pszDataType
+        = EnvisatFile_GetKeyValueAsString( hEnvisatFile, SPH, "DATA_TYPE",
+                                           "" );
+    const char *pszSampleType
+        = EnvisatFile_GetKeyValueAsString( hEnvisatFile, SPH, "SAMPLE_TYPE",
+                                           "" );
+
+    GDALDataType eDataType;
+    if( EQUAL(pszDataType,"FLT32") && STARTS_WITH_CI(pszSampleType, "COMPLEX"))
         eDataType = GDT_CFloat32;
     else if( EQUAL(pszDataType,"FLT32") )
         eDataType = GDT_Float32;
     else if( EQUAL(pszDataType,"UWORD") )
         eDataType = GDT_UInt16;
-    else if( EQUAL(pszDataType,"SWORD") && EQUALN(pszSampleType,"COMPLEX",7) )
+    else if( EQUAL(pszDataType,"SWORD") && STARTS_WITH_CI(pszSampleType, "COMPLEX") )
         eDataType = GDT_CInt16;
     else if( EQUAL(pszDataType,"SWORD") )
         eDataType = GDT_Int16;
-    else if( EQUALN(pszProduct,"ATS_TOA_1",8) )
+    else if( STARTS_WITH_CI(pszProduct,"ATS_TOA_1") )
     {
         /* all 16bit data, no line length provided */
         eDataType = GDT_Int16;
@@ -986,13 +957,15 @@ GDALDataset *EnvisatDataset::Open( GDALOpenInfo * poOpenInfo )
             eDataType = GDT_Byte;
     }
 
+    const int bNative =
 #ifdef CPL_LSB
-    bNative = FALSE;
+    FALSE
 #else
-    bNative = TRUE;
+    TRUE
 #endif
+        ;
 
-    nPrefixBytes = dsr_size -
+    int nPrefixBytes = dsr_size -
         ((GDALGetDataTypeSize(eDataType) / 8) * poDS->nRasterXSize);
 
 /* -------------------------------------------------------------------- */
@@ -1037,7 +1010,7 @@ GDALDataset *EnvisatDataset::Open( GDALOpenInfo * poOpenInfo )
         if( !EQUAL(pszDSType,"M") || num_dsr2 != num_dsr )
             continue;
 
-        if( EQUALN(pszProduct,"MER",3) && (pszProduct[8] == '2') &&
+        if( STARTS_WITH_CI(pszProduct, "MER") && (pszProduct[8] == '2') &&
             ( (strstr(pszDSName, "MDS(16)") != NULL) ||
               (strstr(pszDSName, "MDS(19)") != NULL)) )
             bMiltiChannel = true;
@@ -1060,7 +1033,7 @@ GDALDataset *EnvisatDataset::Open( GDALOpenInfo * poOpenInfo )
 /*       Handle MERIS Level 2 datasets with data type different from    */
 /*       the one declared in the SPH                                    */
 /* -------------------------------------------------------------------- */
-        else if( EQUALN(pszProduct,"MER",3) &&
+        else if( STARTS_WITH_CI(pszProduct, "MER") &&
                  (strstr(pszDSName, "Flags") != NULL) )
         {
             if (pszProduct[8] == '1')
@@ -1084,9 +1057,9 @@ GDALDataset *EnvisatDataset::Open( GDALOpenInfo * poOpenInfo )
 
                 const char *pszSuffix = strstr( pszDSName, "MDS" );
                 if ( pszSuffix != NULL)
-                    sprintf( szBandName, "Detector index %s", pszSuffix );
+                    snprintf( szBandName, sizeof(szBandName), "Detector index %s", pszSuffix );
                 else
-                    sprintf( szBandName, "Detector index" );
+                    snprintf( szBandName, sizeof(szBandName), "%s", "Detector index" );
                 poDS->GetRasterBand(iBand)->SetDescription( szBandName );
             }
             else if ( (pszProduct[8] == '2') &&
@@ -1102,7 +1075,7 @@ GDALDataset *EnvisatDataset::Open( GDALOpenInfo * poOpenInfo )
                 poDS->GetRasterBand(iBand)->SetDescription( pszDSName );
             }
         }
-        else if( EQUALN(pszProduct,"MER",3) && (pszProduct[8] == '2') )
+        else if( STARTS_WITH_CI(pszProduct, "MER") && (pszProduct[8] == '2') )
         {
             int nPrefixBytes2, nSubBands, nSubBandIdx, nSubBandOffset;
 
@@ -1129,7 +1102,7 @@ GDALDataset *EnvisatDataset::Open( GDALOpenInfo * poOpenInfo )
 
                 if (nSubBands > 1)
                 {
-                    sprintf( szBandName, "%s (%d)", pszDSName, nSubBandIdx );
+                    snprintf( szBandName, sizeof(szBandName), "%s (%d)", pszDSName, nSubBandIdx );
                     poDS->GetRasterBand(iBand)->SetDescription( szBandName );
                 }
                 else
@@ -1146,7 +1119,7 @@ GDALDataset *EnvisatDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->CollectDSDMetadata();
     poDS->CollectADSMetadata();
 
-    if( EQUALN(pszProduct,"MER",3) )
+    if( STARTS_WITH_CI(pszProduct, "MER") )
         poDS->ScanForGCPs_MERIS();
     else
         poDS->ScanForGCPs_ASAR();
@@ -1175,24 +1148,20 @@ GDALDataset *EnvisatDataset::Open( GDALOpenInfo * poOpenInfo )
 void GDALRegister_Envisat()
 
 {
-    GDALDriver	*poDriver;
-
-    if( GDALGetDriverByName( "ESAT" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    if( GDALGetDriverByName( "ESAT" ) != NULL )
+        return;
 
-        poDriver->SetDescription( "ESAT" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Envisat Image Format" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "frmt_various.html#Envisat" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "n1" );
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetDescription( "ESAT" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Envisat Image Format" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_various.html#Envisat" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "n1" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = EnvisatDataset::Open;
+    poDriver->pfnOpen = EnvisatDataset::Open;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/envisat/records.c b/frmts/envisat/records.c
index f8a9263..43a0c45 100644
--- a/frmts/envisat/records.c
+++ b/frmts/envisat/records.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: records.c 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: records.c 32100 2015-12-09 07:07:26Z goatbar $
  *
  * Project:  APP ENVISAT Support
  * Purpose:  Low Level Envisat file access (read/write) API.
@@ -30,7 +30,7 @@
 #include "cpl_string.h"
 #include "records.h"
 
-CPL_CVSID("$Id: records.c 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: records.c 32100 2015-12-09 07:07:26Z goatbar $");
 
 /* --- ASAR record descriptors --------------------------------------------- */
 static const EnvisatFieldDescr ASAR_ANTENNA_ELEV_PATT_ADSR[] = {
@@ -1207,29 +1207,29 @@ const EnvisatRecordDescr* EnvisatFile_GetRecordDescriptor(
     const EnvisatRecordDescr *pRecordDescr = NULL;
     int nLen;
 
-    if( EQUALN(pszProduct,"ASA",3) )
+    if( STARTS_WITH_CI(pszProduct, "ASA") )
         paRecords = aASAR_Records;
-    else if( EQUALN(pszProduct,"MER",3) )
+    else if( STARTS_WITH_CI(pszProduct, "MER") )
     {
-        if ( EQUALN(pszProduct + 6,"C_2P",4) )
+        if ( STARTS_WITH_CI(pszProduct + 6, "C_2P") )
             paRecords = aMERIS_2P_C_Records;
-        else if ( EQUALN(pszProduct + 6,"V_2P",4) )
+        else if ( STARTS_WITH_CI(pszProduct + 6, "V_2P") )
             paRecords = aMERIS_2P_V_Records;
-        else if ( EQUALN(pszProduct + 8,"1P",2) )
+        else if ( STARTS_WITH_CI(pszProduct + 8, "1P") )
             paRecords = aMERIS_1P_Records;
-        else if ( EQUALN(pszProduct + 8,"2P",2) )
+        else if ( STARTS_WITH_CI(pszProduct + 8, "2P") )
             paRecords = aMERIS_2P_Records;
         else
             return NULL;
     }
-    else if( EQUALN(pszProduct,"SAR",3) )
+    else if( STARTS_WITH_CI(pszProduct, "SAR") )
         /* ERS products in ENVISAT format have the same records of ASAR ones */
         paRecords = aASAR_Records;
     else
         return NULL;
 
     /* strip trailing spaces */
-    for( nLen = strlen(pszDataset); nLen && pszDataset[nLen-1] == ' '; --nLen );
+    for( nLen = (int)strlen(pszDataset); nLen && pszDataset[nLen-1] == ' '; --nLen );
 
     pRecordDescr = paRecords;
     while ( pRecordDescr->szName != NULL )
@@ -1244,7 +1244,7 @@ const EnvisatRecordDescr* EnvisatFile_GetRecordDescriptor(
 }
 
 CPLErr EnvisatFile_GetFieldAsString(const void *pRecord, int nRecLen,
-                        const EnvisatFieldDescr* pField, char *szBuf)
+                        const EnvisatFieldDescr* pField, char *szBuf, size_t nBufLen)
 {
     int i, nOffset = 0;
     const void *pData;
@@ -1274,7 +1274,7 @@ CPLErr EnvisatFile_GetFieldAsString(const void *pRecord, int nRecLen,
             {
                 if (i > 0)
                     szBuf[nOffset++] = ' ';
-                nOffset += sprintf(szBuf + nOffset, "%d",
+                nOffset += snprintf(szBuf + nOffset, nBufLen -nOffset, "%d",
                                    ((const char*)pData)[i]);
             }
             break;
@@ -1283,7 +1283,7 @@ CPLErr EnvisatFile_GetFieldAsString(const void *pRecord, int nRecLen,
             {
                 if (i > 0)
                     szBuf[nOffset++] = ' ';
-                nOffset += sprintf(szBuf + nOffset, "%d",
+                nOffset += snprintf(szBuf + nOffset, nBufLen -nOffset, "%d",
                                    CPL_MSBWORD16(((const GInt16*)pData)[i]));
             }
             break;
@@ -1292,7 +1292,7 @@ CPLErr EnvisatFile_GetFieldAsString(const void *pRecord, int nRecLen,
             {
                 if (i > 0)
                     szBuf[nOffset++] = ' ';
-                nOffset += sprintf(szBuf + nOffset, "%d",
+                nOffset += snprintf(szBuf + nOffset, nBufLen -nOffset,"%d",
                                    CPL_MSBWORD16(((const GUInt16*)pData)[i]));
             }
             break;
@@ -1301,7 +1301,7 @@ CPLErr EnvisatFile_GetFieldAsString(const void *pRecord, int nRecLen,
             {
                 if (i > 0)
                     szBuf[nOffset++] = ' ';
-                nOffset += sprintf(szBuf + nOffset, "%d",
+                nOffset += snprintf(szBuf + nOffset, nBufLen -nOffset,"%d",
                                    CPL_MSBWORD32(((const GInt32*)pData)[i]));
             }
             break;
@@ -1310,7 +1310,7 @@ CPLErr EnvisatFile_GetFieldAsString(const void *pRecord, int nRecLen,
             {
                 if (i > 0)
                     szBuf[nOffset++] = ' ';
-                nOffset += sprintf(szBuf + nOffset, "%d",
+                nOffset += snprintf(szBuf + nOffset, nBufLen -nOffset,"%d",
                                    CPL_MSBWORD32(((const GUInt32*)pData)[i]));
             }
             break;
@@ -1324,7 +1324,7 @@ CPLErr EnvisatFile_GetFieldAsString(const void *pRecord, int nRecLen,
 
                 if (i > 0)
                     szBuf[nOffset++] = ' ';
-                nOffset += CPLsprintf(szBuf + nOffset, "%f", fValue);
+                nOffset += CPLsnprintf(szBuf + nOffset, nBufLen -nOffset,"%f", fValue);
             }
             break;
         case EDT_Float64:
@@ -1336,7 +1336,7 @@ CPLErr EnvisatFile_GetFieldAsString(const void *pRecord, int nRecLen,
 #endif
                 if (i > 0)
                     szBuf[nOffset++] = ' ';
-                nOffset += CPLsprintf(szBuf + nOffset, "%f", dfValue);
+                nOffset += CPLsnprintf(szBuf + nOffset, nBufLen -nOffset,"%f", dfValue);
             }
             break;
 /*
@@ -1399,13 +1399,13 @@ CPLErr EnvisatFile_GetFieldAsString(const void *pRecord, int nRecLen,
                 seconds = CPL_MSBWORD32(((const GUInt32*)pData)[1]);
                 microseconds = CPL_MSBWORD32(((const GUInt32*)pData)[2]);
 
-                sprintf(szBuf, "%d, %d, %d", days, seconds, microseconds);
+                snprintf(szBuf, nBufLen, "%d, %d, %d", days, seconds, microseconds);
             }
             break;
         default:
             CPLDebug( "EnvisatDataset",
                       "Unabe to convert '%s' field to string: "
-                      "unsecpected data type '%d'.",
+                      "unexpected data type '%d'.",
                       pField->szName, pField->eType );
             return CE_Failure;
     }
diff --git a/frmts/envisat/records.h b/frmts/envisat/records.h
index 4eb8ae2..c5242e2 100644
--- a/frmts/envisat/records.h
+++ b/frmts/envisat/records.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: records.h 22488 2011-06-02 17:04:47Z rouault $
+ * $Id: records.h 32078 2015-12-08 09:09:45Z rouault $
  *
  * Project:  APP ENVISAT Support
  * Purpose:  Low Level Envisat file access (read/write) API.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef __RECORDS_H__
-#define __RECORDS_H__
+#ifndef RECORDS_H_
+#define RECORDS_H_
 
 #include "gdal.h"
 
@@ -62,9 +62,9 @@ typedef enum {
 
 typedef struct {
     const char* szName;
-    const int nOffset;
-    const EnvisatDataType eType;
-    const int nCount;
+    int nOffset;
+    EnvisatDataType eType;
+    int nCount;
 } EnvisatFieldDescr;
 
 typedef struct {
@@ -75,11 +75,11 @@ typedef struct {
 const EnvisatRecordDescr* EnvisatFile_GetRecordDescriptor(const char* pszProduct,
                                               const char* pszDataset);
 
-CPLErr EnvisatFile_GetFieldAsString(const void*, int, const EnvisatFieldDescr*, char*);
+CPLErr EnvisatFile_GetFieldAsString(const void*, int, const EnvisatFieldDescr*, char*, size_t);
 
 
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
 
-#endif /* __RECORDS_H__ */
+#endif /* RECORDS_H_ */
diff --git a/frmts/envisat/timedelta.hpp b/frmts/envisat/timedelta.hpp
index e142a00..312e576 100644
--- a/frmts/envisat/timedelta.hpp
+++ b/frmts/envisat/timedelta.hpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: timedelta.hpp 27098 2014-03-27 00:16:11Z rouault $
+ * $Id: timedelta.hpp 33123 2016-01-23 18:59:28Z rouault $
  *
  * Project:  APP ENVISAT Support
  * Purpose:  time difference class for handling of Envisat MJD time
@@ -29,16 +29,16 @@
 
 #ifndef timedelta_hpp
 #define timedelta_hpp
-/* 
+/*
  * TimeDelta class represents the time difference. It is used to 
  * hold the Envisat MJD (Modified Julian Date - which is time 
  * since 2000-01-01T00:00:00.000000Z) 
  */
 
 class TimeDelta  
-{ 
+{
 
-  private: 
+  private:
 
     int days ;     /* number of days */
     int secs ;     /* number of seconds since day start */ 
@@ -47,45 +47,45 @@ class TimeDelta
     /* SETTERS */
 
     /* set object using number of days, seconds and micro-seconds */
-    inline void set( int days , int secs , int usecs ) 
+    inline void set( int daysIn , int secsIn , int usecsIn ) 
     { 
         int tmp0 , tmp1 ; 
         /* overflow check with proper handling of negative values */ 
         /* note that division and modulo for negative values is impl.dependent */ 
 
-        secs += ( tmp0 = usecs>=0 ? usecs/1000000 : -1-((-usecs)/1000000) ) ;  
-        days += ( tmp1 = secs>=0 ? secs/86400 : -1-((-secs)/86400) ) ;
+        secsIn += ( tmp0 = usecsIn>=0 ? usecsIn/1000000 : -1-((-usecsIn)/1000000) ) ;  
+        daysIn += ( tmp1 = secsIn>=0 ? secsIn/86400 : -1-((-secsIn)/86400) ) ;
 
-        this->usecs = usecs - 1000000*tmp0 ;
-        this->secs  = secs - 86400*tmp1 ; 
-        this->days  = days ;
+        this->usecs = usecsIn - 1000000*tmp0 ;
+        this->secs  = secsIn - 86400*tmp1 ; 
+        this->days  = daysIn ;
     } 
 
     /* set object from floating point number of seconds */
-    inline void fromSeconds( double secs ) 
+    inline void fromSeconds( double secsIn ) 
     { 
-        int _days = (int)( secs / 86400 ) ;
-        int _secs = (int)( secs - 86400*_days ) ;
-        int _uscs = (int)(( secs - ((int)secs) )*1e6) ; 
+        int _days = (int)( secsIn / 86400 ) ;
+        int _secs = (int)( secsIn - 86400*_days ) ;
+        int _uscs = (int)(( secsIn - ((int)secsIn) )*1e6) ; 
 
         this->set( _days , _secs , _uscs ) ;
     } 
 
-  public: 
+  public:
 
     /* CONSTRUCTORS */
     TimeDelta( void ) : days(0), secs(0), usecs(0) {} 
 
     /* construct object using number of days, seconds and micro-seconds */
-    TimeDelta( int days , int secs , int usecs ) 
+    TimeDelta( int daysIn , int secsIn , int usecsIn ) 
     { 
-        this->set( days, secs, usecs ) ;
+        this->set( daysIn, secsIn, usecsIn ) ;
     } 
 
     /* construct object from floating point number of seconds */
-    TimeDelta( double secs ) 
+    TimeDelta( double secsIn ) 
     { 
-        this->fromSeconds( secs ) ;
+        this->fromSeconds( secsIn ) ;
     }
 
     /* GETTERS */
@@ -106,15 +106,14 @@ class TimeDelta
     } 
 
     /* convert to seconds - can handle safely at least 250 years dif. */
-    /*  ... before loosing the microsecond precision */
+    /*  ... before losing the microsecond precision */
     inline operator double( void ) const  
     { 
         return (this->days*86400.0) + this->secs + (this->usecs*1e-6) ;
     } 
 
-
     /* OPERATORS */
-    
+
     /* difference */
     inline TimeDelta operator -( const TimeDelta & that ) const 
     { 
@@ -186,7 +185,6 @@ class TimeDelta
                 ) ;
     } 
 
-
     inline bool operator !=( const TimeDelta & that ) const 
     { 
         return !( *this == that ) ;
@@ -202,7 +200,7 @@ class TimeDelta
         return !( *this > that ) ;
     } 
 
-} ;  
+};
 
 /*
 #include <iostream>
@@ -215,7 +213,7 @@ std::ostream & operator<<( std::ostream & out, const TimeDelta & td )
         << "," << td.getMicroseconds() << ")" ; 
 
     return out ;
-} 
+}
 */
 
 #endif /*timedelta_hpp*/
diff --git a/frmts/envisat/unwrapgcps.cpp b/frmts/envisat/unwrapgcps.cpp
index 7cceb81..397a36f 100644
--- a/frmts/envisat/unwrapgcps.cpp
+++ b/frmts/envisat/unwrapgcps.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: unwrapgcps.cpp 27098 2014-03-27 00:16:11Z rouault $
+ * $Id: unwrapgcps.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  APP ENVISAT Support
- * Purpose:  GCPs Unwrapping for products crossing the WGS84 date-line  
- * Author:   Martin Paces martin.paces at eox.at 
+ * Purpose:  GCPs Unwrapping for products crossing the WGS84 date-line
+ * Author:   Martin Paces martin.paces at eox.at
  *
  ******************************************************************************
- * Copyright (c) 2013, EOX IT Services, GmbH 
+ * Copyright (c) 2013, EOX IT Services, GmbH
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,151 +32,153 @@
 #include <cstdio>
 
 // number of histogram bins (36 a 10dg)
-#define NBIN  36  
+static const int NBIN = 36;
 // number of empty bins to guess the flip-point
-#define NEMPY 7 
+static const int NEMPY = 7;
 
-// WGS84 bounds 
-#define XMIN  (-180.0)
-#define XMAX  (+180.0)
-#define XDIF  (+360.0)
-#define XCNT     (0.0)
+// WGS84 bounds
+static const double XMIN = -180.0;
+// static const double XMAX = 180.0;
+static const double XDIF = 360.0;
+static const double XCNT = 0.0;
 
-// max. allowed longitude extent of the GCP set 
-#define XLIM  (XDIF*(1.0-NEMPY*(1.0/NBIN)))
+// max. allowed longitude extent of the GCP set
+static const double XLIM = XDIF*(1.0-NEMPY*(1.0/NBIN));
 
+/* used by envisatdataset.cpp */
+extern void EnvisatUnwrapGCPs( int cnt, GDAL_GCP *gcp );
 
-// The algoright is based on assumption that the unwrapped 
+// The algorithm is based on assumption that the unwrapped
 // GCPs ('flipped' values) have smaller extent along the longitude.
-// We further assume that the lenght of the striplines is limitted 
-// to one orbit and does not exceeded given limit along the longitude, 
-// e.i., the wrapped-arround coordinates have significantly larger 
-// extent the unwrapped. If the smaller extend exceedes the limit
-// the original tiepoints are returned. 
-
-static double _suggest_flip_point( const int cnt, GDAL_GCP *gcp ) 
-{ 
+// We further assume that the length of the striplines is limited
+// to one orbit and does not exceeded given limit along the longitude,
+// e.i., the wrapped-around coordinates have significantly larger
+// extent the unwrapped. If the smaller extend exceeds the limit
+// the original tiepoints are returned.
+
+static double _suggest_flip_point( const int cnt, GDAL_GCP *gcp )
+{
     // the histogram array - it is expected to fit the stack
-    int hist[NBIN] ; 
-    
+    int hist[NBIN] ;
+
     // reset the histogram counters
-    for( int i = 0 ; i < NBIN ; i++ ) hist[i] = 0 ; 
+    for( int i = 0 ; i < NBIN ; i++ ) hist[i] = 0 ;
 
-    // accumulate the histogram 
-    for( int i = 0 ; i < cnt ; i++ ) 
-    { 
-        double x = (gcp[i].dfGCPX-XMIN)/XDIF ;
-        int idx = (int)(NBIN*(x-floor(x))) ; 
+    // accumulate the histogram
+    for( int i = 0 ; i < cnt ; i++ )
+    {
+        double x = (gcp[i].dfGCPX-XMIN)/XDIF;
+        int idx = (int)(NBIN*(x-floor(x)));
 
-        // the lattitudes should lay in the +/-180 bounds 
+        // The latitudes should lay in the +/-180 bounds
         // although it should never happen we check the outliers
-        if (idx < 0) idx = 0 ; 
-        if (idx >= NBIN ) idx = NBIN-1; 
+        if (idx < 0) idx = 0 ;
+        if (idx >= NBIN ) idx = NBIN-1;
 
-        hist[idx] += 1 ; 
-    } 
+        hist[idx] += 1 ;
+    }
 
     // find a middle of at least NEMPTY consecutive empty bins and get its middle
-    int i0 = -1 , i1 = -1 , last_is_empty = 0 ; 
-    for( int i = 0 ; i < (2*NBIN-1) ; i++ ) 
-    { 
-        if ( 0 == hist[i%NBIN] ) // empty 
-        { 
-            if ( !last_is_empty ) // re-start counter 
-            { 
+    int i0 = -1 , i1 = -1 , last_is_empty = 0 ;
+    for( int i = 0 ; i < (2*NBIN-1) ; i++ )
+    {
+        if ( 0 == hist[i%NBIN] ) // empty
+        {
+            if ( !last_is_empty ) // re-start counter
+            {
                 i0 = i ;
-                last_is_empty = 1 ; 
+                last_is_empty = 1 ;
             }
-        } 
-        else // non-empty 
+        }
+        else // non-empty
         {
-            if ( last_is_empty ) 
-            { 
+            if ( last_is_empty )
+            {
                 i1 = i ;
-                last_is_empty = 0 ; 
+                last_is_empty = 0 ;
 
-                // if the segment is long enough -> terminate 
-                if (( i1 - i0 )>=NEMPY) break ; 
-            } 
+                // if the segment is long enough -> terminate
+                if (( i1 - i0 )>=NEMPY) break ;
+            }
         }
-    } 
+    }
 
-    // if all full or all empty the returning default value 
+    // if all full or all empty the returning default value
     if ( i1 < 0 ) return XCNT ;
 
     // return the flip-centre
 
-    double tmp = ((i1-i0)*0.5+i0)/((float)NBIN) ; 
+    double tmp = ((i1-i0)*0.5+i0)/((float)NBIN) ;
 
     return (tmp-floor(tmp))*XDIF + XMIN ;
 }
-    
 
-void EnvisatUnwrapGCPs( int cnt, GDAL_GCP *gcp ) 
-{ 
-    if ( cnt < 1 ) return ; 
-    
-    // suggest right flip-point 
-    double x_flip = _suggest_flip_point( cnt, gcp ); 
 
-    // find the limits allong the longitude (x) for flipped and unflipped values
-    
+void EnvisatUnwrapGCPs( int cnt, GDAL_GCP *gcp )
+{
+    if ( cnt < 1 ) return ;
+
+    // suggest right flip-point
+    double x_flip = _suggest_flip_point( cnt, gcp );
+
+    // Find the limits along the longitude (x) for flipped and unflipped values.
+
     int cnt_flip = 0 ; // flipped values' counter
-    double x0_dif , x1_dif ; 
+    double x0_dif , x1_dif ;
 
-    { 
+    {
         double x0_min, x0_max, x1_min, x1_max ;
 
-        { 
+        {
             double x0 = gcp[0].dfGCPX ;
             int  flip = (x0>x_flip) ;
-            x0_min = x0_max = x0 ; 
-            x1_min = x1_max = x0 - flip*XDIF ; 
-            cnt_flip += flip ; // count the flipped values 
-        } 
+            x0_min = x0_max = x0 ;
+            x1_min = x1_max = x0 - flip*XDIF ;
+            cnt_flip += flip ; // count the flipped values
+        }
 
-        for ( int i = 1 ; i < cnt ; ++i ) 
-        { 
+        for ( int i = 1 ; i < cnt ; ++i )
+        {
             double x0 = gcp[i].dfGCPX ;
             int  flip = (x0>x_flip) ;
             double x1 = x0 - flip*XDIF ; // flipped value
-            cnt_flip += flip ; // count the flipped values 
-
-            if ( x0 > x0_max ) x0_max = x0 ; 
-            if ( x0 < x0_min ) x0_min = x0 ; 
-            if ( x1 > x1_max ) x1_max = x1 ; 
-            if ( x1 < x1_min ) x1_min = x1 ; 
-        } 
-
-        x0_dif = x0_max - x0_min ; 
-        x1_dif = x1_max - x1_min ; 
-    } 
-
-    // in case all values either flipped or non-flipped 
-    // nothing is to be done 
-    if (( cnt_flip == 0 ) || ( cnt_flip == cnt )) return ; 
-
-    // check whether we need to split the segment 
-    // i.e., segment is too long decide the best option 
-    
-    if (( x0_dif > XLIM ) && ( x1_dif > XLIM )) 
-    { 
-        // this should not happen 
-        // we give-up and return the original tie-point set 
+            cnt_flip += flip ; // count the flipped values
+
+            if ( x0 > x0_max ) x0_max = x0 ;
+            if ( x0 < x0_min ) x0_min = x0 ;
+            if ( x1 > x1_max ) x1_max = x1 ;
+            if ( x1 < x1_min ) x1_min = x1 ;
+        }
+
+        x0_dif = x0_max - x0_min ;
+        x1_dif = x1_max - x1_min ;
+    }
+
+    // in case all values either flipped or non-flipped
+    // nothing is to be done
+    if (( cnt_flip == 0 ) || ( cnt_flip == cnt )) return ;
+
+    // check whether we need to split the segment
+    // i.e., segment is too long decide the best option
+
+    if (( x0_dif > XLIM ) && ( x1_dif > XLIM ))
+    {
+        // this should not happen
+        // we give-up and return the original tie-point set
 
         CPLError(CE_Warning,CPLE_AppDefined,"GCPs' set is too large"
-            " to perform the unwrapping! The unwrapping is not performed!"); 
+            " to perform the unwrapping! The unwrapping is not performed!");
 
-        return ; 
-    } 
-    else if ( x1_dif < x0_dif ) 
-    { 
+        return ;
+    }
+    else if ( x1_dif < x0_dif )
+    {
         // flipped GCPs' set has smaller extent -> unwrapping is performed
-        for ( int i = 1 ; i < cnt ; ++i ) 
-        { 
+        for ( int i = 1 ; i < cnt ; ++i )
+        {
             double x0 = gcp[i].dfGCPX ;
 
-            gcp[i].dfGCPX = x0 - (x0>XCNT)*XDIF ; 
-        } 
-    } 
-} 
+            gcp[i].dfGCPX = x0 - (x0>XCNT)*XDIF ;
+        }
+    }
+}
diff --git a/frmts/epsilon/epsilondataset.cpp b/frmts/epsilon/epsilondataset.cpp
index 4e58529..51ca9c0 100644
--- a/frmts/epsilon/epsilondataset.cpp
+++ b/frmts/epsilon/epsilondataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: epsilondataset.cpp 28738 2015-03-16 17:20:21Z rouault $
+ * $Id: epsilondataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  GDAL Epsilon driver
  * Purpose:  Implement GDAL Epsilon support using Epsilon library
@@ -27,10 +27,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "epsilon.h"
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: epsilondataset.cpp 28738 2015-03-16 17:20:21Z rouault $");
+#include "epsilon.h"
+
+CPL_CVSID("$Id: epsilondataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 #define RASTERLITE_WAVELET_HEADER "StartWaveletsImage$$"
 #define RASTERLITE_WAVELET_FOOTER "$$EndWaveletsImage"
@@ -68,26 +70,26 @@ class EpsilonDataset : public GDALPamDataset
 
     VSILFILE*    fp;
     vsi_l_offset nFileOff;
-    
+
     GByte*   pabyFileBuf;
     int      nFileBufMaxSize;
     int      nFileBufCurSize;
     int      nFileBufOffset;
     int      bEOF;
     int      bError;
-    
+
     GByte*   pabyBlockData;
     int      nBlockDataSize;
     vsi_l_offset nStartBlockFileOff;
-    
+
     int      bRegularTiling;
-    
+
     int        nBlocks;
     BlockDesc* pasBlocks;
-    
+
     int      nBufferedBlock;
     GByte*   pabyRGBData;
-    
+
     void     Seek(vsi_l_offset nPos);
     int      GetNextByte();
     int      GetNextBlockData();
@@ -96,7 +98,7 @@ class EpsilonDataset : public GDALPamDataset
   public:
                  EpsilonDataset();
     virtual     ~EpsilonDataset();
-    
+
     static GDALDataset *Open( GDALOpenInfo * );
     static int          Identify( GDALOpenInfo * );
 };
@@ -111,7 +113,7 @@ class EpsilonRasterBand : public GDALPamRasterBand
 {
   public:
                             EpsilonRasterBand(EpsilonDataset* poDS, int nBand);
-                 
+
     virtual CPLErr          IReadBlock( int, int, void * );
     virtual GDALColorInterp GetColorInterpretation();
 };
@@ -124,23 +126,23 @@ EpsilonDataset::EpsilonDataset()
 {
     fp = NULL;
     nFileOff = 0;
-    
+
     pabyFileBuf = NULL;
     nFileBufMaxSize = 0;
     nFileBufCurSize = 0;
     nFileBufOffset = 0;
     bEOF = FALSE;
     bError = FALSE;
-    
+
     pabyBlockData = NULL;
     nBlockDataSize = 0;
     nStartBlockFileOff = 0;
-    
+
     bRegularTiling = FALSE;
-    
+
     nBlocks = 0;
     pasBlocks = NULL;
-    
+
     nBufferedBlock = -1;
     pabyRGBData = NULL;
 }
@@ -162,13 +164,13 @@ EpsilonDataset::~EpsilonDataset()
 /*                       EpsilonRasterBand()                            */
 /************************************************************************/
 
-EpsilonRasterBand::EpsilonRasterBand(EpsilonDataset* poDS, int nBand)
+EpsilonRasterBand::EpsilonRasterBand(EpsilonDataset* poDSIn, int nBandIn)
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
     this->eDataType = GDT_Byte;
-    this->nBlockXSize = poDS->pasBlocks[0].w;
-    this->nBlockYSize = poDS->pasBlocks[0].h;
+    this->nBlockXSize = poDSIn->pasBlocks[0].w;
+    this->nBlockYSize = poDSIn->pasBlocks[0].h;
 }
 
 /************************************************************************/
@@ -201,32 +203,32 @@ CPLErr EpsilonRasterBand::IReadBlock( int nBlockXOff,
                                       int nBlockYOff, void * pImage)
 {
     EpsilonDataset* poGDS = (EpsilonDataset*) poDS;
-    
+
     //CPLDebug("EPSILON", "IReadBlock(nBand=%d,nBlockXOff=%d,nBlockYOff=%d)",
     //         nBand, nBlockXOff, nBlockYOff);
 
-    int nBlocksPerRow = (poGDS->nRasterXSize + nBlockXSize - 1) / nBlockXSize;
-    int nBlock = nBlockXOff + nBlockYOff * nBlocksPerRow;
-    
+    int l_nBlocksPerRow = (poGDS->nRasterXSize + nBlockXSize - 1) / nBlockXSize;
+    int nBlock = nBlockXOff + nBlockYOff * l_nBlocksPerRow;
+
     BlockDesc* psDesc = &poGDS->pasBlocks[nBlock];
 #ifdef DEBUG
-    int nBlocksPerColumn = (poGDS->nRasterYSize + nBlockYSize - 1) / nBlockYSize;
+    int l_nBlocksPerColumn = (poGDS->nRasterYSize + nBlockYSize - 1) / nBlockYSize;
     CPLAssert(psDesc->x == nBlockXOff * nBlockXSize);
     CPLAssert(psDesc->y == nBlockYOff * nBlockYSize);
-    CPLAssert(psDesc->w == (nBlockXOff < nBlocksPerRow - 1) ?
+    CPLAssert(psDesc->w == (nBlockXOff < l_nBlocksPerRow - 1) ?
                                 nBlockXSize : poGDS->nRasterXSize - psDesc->x);
-    CPLAssert(psDesc->h == (nBlockYOff < nBlocksPerColumn - 1) ?
+    CPLAssert(psDesc->h == (nBlockYOff < l_nBlocksPerColumn - 1) ?
                                 nBlockYSize : poGDS->nRasterYSize - psDesc->y);
 #endif
 
     poGDS->Seek(psDesc->offset);
-        
+
     if (!poGDS->GetNextBlockData())
     {
         memset(pImage, 0, nBlockXSize * nBlockYSize);
         return CE_Failure;
     }
-    
+
     eps_block_header hdr;
     if (eps_read_block_header (poGDS->pabyBlockData,
                                poGDS->nBlockDataSize, &hdr) != EPS_OK)
@@ -243,7 +245,7 @@ CPLErr EpsilonRasterBand::IReadBlock( int nBlockXOff,
         memset(pImage, 0, nBlockXSize * nBlockYSize);
         return CE_Failure;
     }
-    
+
     int w = GET_FIELD(hdr, w);
     int h = GET_FIELD(hdr, h);
     int i;
@@ -251,7 +253,7 @@ CPLErr EpsilonRasterBand::IReadBlock( int nBlockXOff,
     if (poGDS->nBands == 1)
     {
         unsigned char ** pTempData =
-            (unsigned char **) CPLMalloc(h * sizeof(unsigned char*));        
+            (unsigned char **) CPLMalloc(h * sizeof(unsigned char*));
         for(i=0;i<h;i++)
             pTempData[i] = ((GByte*)pImage) + i * nBlockXSize;
 
@@ -279,7 +281,7 @@ CPLErr EpsilonRasterBand::IReadBlock( int nBlockXOff,
                 return CE_Failure;
             }
         }
-            
+
         if (poGDS->nBufferedBlock == nBlock)
         {
             memcpy(pImage,
@@ -287,7 +289,7 @@ CPLErr EpsilonRasterBand::IReadBlock( int nBlockXOff,
                    nBlockXSize * nBlockYSize);
             return CE_None;
         }
-    
+
         unsigned char ** pTempData[3];
         int iBand;
         for(iBand=0;iBand<3;iBand++)
@@ -298,31 +300,31 @@ CPLErr EpsilonRasterBand::IReadBlock( int nBlockXOff,
                 pTempData[iBand][i] = poGDS->pabyRGBData +
                     iBand * nBlockXSize * nBlockYSize + i * nBlockXSize;
         }
-    
+
         if (w != nBlockXSize || h != nBlockYSize)
             memset(poGDS->pabyRGBData, 0, 3 * nBlockXSize * nBlockYSize);
-            
+
         if (eps_decode_truecolor_block (pTempData[0], pTempData[1], pTempData[2],
                                         poGDS->pabyBlockData, &hdr) != EPS_OK)
         {
-            for(iBand=0;iBand<poGDS->nBands;iBand++)
+            for(iBand=0;iBand<3;iBand++)
                 CPLFree(pTempData[iBand]);
             memset(pImage, 0, nBlockXSize * nBlockYSize);
             return CE_Failure;
         }
-        
-        for(iBand=0;iBand<poGDS->nBands;iBand++)
+
+        for(iBand=0;iBand<3;iBand++)
             CPLFree(pTempData[iBand]);
-            
+
         poGDS->nBufferedBlock = nBlock;
         memcpy(pImage,
                poGDS->pabyRGBData + (nBand - 1) * nBlockXSize * nBlockYSize,
                nBlockXSize * nBlockYSize);
-                   
+
         if (nBand == 1)
         {
             int iOtherBand;
-            for(iOtherBand=2;iOtherBand<=poGDS->nBands;iOtherBand++)
+            for(iOtherBand=2;iOtherBand<=3;iOtherBand++)
             {
                 GDALRasterBlock *poBlock;
 
@@ -330,7 +332,7 @@ CPLErr EpsilonRasterBand::IReadBlock( int nBlockXOff,
                     GetLockedBlockRef(nBlockXOff,nBlockYOff, TRUE);
                 if (poBlock == NULL)
                     break;
-                    
+
                 GByte* pabySrcBlock = (GByte *) poBlock->GetDataRef();
                 if( pabySrcBlock == NULL )
                 {
@@ -346,7 +348,7 @@ CPLErr EpsilonRasterBand::IReadBlock( int nBlockXOff,
             }
         }
     }
-    
+
     return CE_None;
 }
 
@@ -376,7 +378,7 @@ int EpsilonDataset::GetNextByte()
         nFileOff ++;
         return pabyFileBuf[nFileBufOffset ++];
     }
-        
+
     if (bError || bEOF)
         return -1;
 
@@ -399,7 +401,7 @@ int EpsilonDataset::GetNextByte()
         bEOF = TRUE;
     if (nBytesRead == 0)
         return -1;
-    
+
     nFileOff ++;
     return pabyFileBuf[nFileBufOffset ++];
 }
@@ -415,13 +417,13 @@ int EpsilonDataset::GetNextBlockData()
     int nStartBlockBufOffset = 0;
     pabyBlockData = NULL;
     nBlockDataSize = 0;
-    
+
     while (nFileBufOffset < MAX_SIZE_BEFORE_BLOCK_MARKER)
     {
         int chNextByte = GetNextByte();
         if (chNextByte < 0)
             return FALSE;
-        
+
         if (chNextByte != EPS_MARKER)
         {
             nStartBlockFileOff = nFileOff - 1;
@@ -432,7 +434,7 @@ int EpsilonDataset::GetNextBlockData()
     }
     if (nFileBufOffset == MAX_SIZE_BEFORE_BLOCK_MARKER)
         return FALSE;
-        
+
     while (nFileBufOffset < BLOCK_DATA_MAX_SIZE)
     {
         int chNextByte = GetNextByte();
@@ -444,10 +446,10 @@ int EpsilonDataset::GetNextBlockData()
             pabyBlockData = pabyFileBuf + nStartBlockBufOffset;
             return TRUE;
         }
-            
+
         nBlockDataSize ++;
     }
-    
+
     pabyBlockData = pabyFileBuf + nStartBlockBufOffset;
     return TRUE;
 }
@@ -465,21 +467,21 @@ int EpsilonDataset::ScanBlocks(int* pnBands)
 
     int nTileW = -1;
     int nTileH = -1;
-    
+
     *pnBands = 0;
 
     bRegularTiling = TRUE;
-    
+
     eps_block_header hdr;
-    while(TRUE)
+    while( true )
     {
         Seek(nStartBlockFileOff + nBlockDataSize);
-        
+
         if (!GetNextBlockData())
         {
             break;
         }
-        
+
         /* Ignore rasterlite wavelet header */
         int nRasterliteWaveletHeaderLen = strlen(RASTERLITE_WAVELET_HEADER);
         if (nBlockDataSize >= nRasterliteWaveletHeaderLen &&
@@ -488,7 +490,7 @@ int EpsilonDataset::ScanBlocks(int* pnBands)
         {
             continue;
         }
-        
+
         /* Stop at rasterlite wavelet footer */
         int nRasterlineWaveletFooterLen = strlen(RASTERLITE_WAVELET_FOOTER);
         if (nBlockDataSize >= nRasterlineWaveletFooterLen &&
@@ -497,7 +499,7 @@ int EpsilonDataset::ScanBlocks(int* pnBands)
         {
             break;
         }
-        
+
         if (eps_read_block_header (pabyBlockData,
                                    nBlockDataSize, &hdr) != EPS_OK)
         {
@@ -511,7 +513,7 @@ int EpsilonDataset::ScanBlocks(int* pnBands)
             CPLError(CE_Warning, CPLE_AppDefined, "bad CRC");
             continue;
         }
-        
+
         int W = GET_FIELD(hdr, W);
         int H = GET_FIELD(hdr, H);
         int x = GET_FIELD(hdr, x);
@@ -521,7 +523,7 @@ int EpsilonDataset::ScanBlocks(int* pnBands)
 
         //CPLDebug("EPSILON", "W=%d,H=%d,x=%d,y=%d,w=%d,h=%d,offset=" CPL_FRMT_GUIB,
         //                    W, H, x, y, w, h, nStartBlockFileOff);
-        
+
         int nNewBands = (hdr.block_type == EPS_GRAYSCALE_BLOCK) ? 1 : 3;
         if (nRasterXSize == 0)
         {
@@ -529,13 +531,13 @@ int EpsilonDataset::ScanBlocks(int* pnBands)
             {
                 break;
             }
-            
+
             bRet = TRUE;
             nRasterXSize = W;
             nRasterYSize = H;
             *pnBands = nNewBands;
         }
-        
+
         if (nRasterXSize != W || nRasterYSize != H || *pnBands != nNewBands ||
             x < 0 || y < 0 || x + w > W || y + h > H)
         {
@@ -543,15 +545,21 @@ int EpsilonDataset::ScanBlocks(int* pnBands)
             bRet = FALSE;
             break;
         }
-        
+
+        BlockDesc* pasNewBlocks = (BlockDesc*)VSI_REALLOC_VERBOSE(pasBlocks, sizeof(BlockDesc) * (nBlocks+1));
+        if( pasNewBlocks == NULL )
+        {
+            bRet = FALSE;
+            break;
+        }
+        pasBlocks = pasNewBlocks;
         nBlocks++;
-        pasBlocks = (BlockDesc*)VSIRealloc(pasBlocks, sizeof(BlockDesc) * nBlocks);
         pasBlocks[nBlocks-1].x = x;
         pasBlocks[nBlocks-1].y = y;
         pasBlocks[nBlocks-1].w = w;
         pasBlocks[nBlocks-1].h = h;
         pasBlocks[nBlocks-1].offset = nStartBlockFileOff;
-        
+
         if (bRegularTiling)
         {
             if (nTileW < 0)
@@ -559,10 +567,10 @@ int EpsilonDataset::ScanBlocks(int* pnBands)
                 nTileW = w;
                 nTileH = h;
             }
-            
+
             if (w > nTileW || h > nTileH)
                 bRegularTiling = FALSE;
-            
+
             if (x != nExpectedX)
                 bRegularTiling = FALSE;
 
@@ -571,7 +579,7 @@ int EpsilonDataset::ScanBlocks(int* pnBands)
                 if (y + h != H)
                     bRegularTiling = FALSE;
             }
-            
+
             if (nTileW != w)
             {
                 if (x + w != W)
@@ -584,11 +592,11 @@ int EpsilonDataset::ScanBlocks(int* pnBands)
             }
             else
                 nExpectedX += nTileW;
-            
+
             //if (!bRegularTiling)
             //    CPLDebug("EPSILON", "not regular tiling!");
         }
-    } 
+    }
 
     return bRet;
 }
@@ -606,14 +614,14 @@ int EpsilonDataset::Identify(GDALOpenInfo* poOpenInfo)
     {
         return TRUE;
     }
-    
+
     if (poOpenInfo->nHeaderBytes > EPS_MIN_GRAYSCALE_BUF &&
-        (EQUALN((const char*)poOpenInfo->pabyHeader, "type=gs", 7) ||
-         EQUALN((const char*)poOpenInfo->pabyHeader, "type=tc", 7)))
+        (STARTS_WITH_CI((const char*)poOpenInfo->pabyHeader, "type=gs") ||
+         STARTS_WITH_CI((const char*)poOpenInfo->pabyHeader, "type=tc")))
     {
         return TRUE;
     }
-    
+
     return FALSE;
 }
 
@@ -628,7 +636,7 @@ GDALDataset* EpsilonDataset::Open(GDALOpenInfo* poOpenInfo)
 
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The EPSILON driver does not support update access to existing"
                   " files.\n" );
         return NULL;
@@ -637,20 +645,20 @@ GDALDataset* EpsilonDataset::Open(GDALOpenInfo* poOpenInfo)
     VSILFILE* fp = VSIFOpenL(poOpenInfo->pszFilename, "rb");
     if (fp == NULL)
         return NULL;
-    
+
     EpsilonDataset* poDS = new EpsilonDataset();
     poDS->fp = fp;
-    
+
     poDS->nRasterXSize = 0;
     poDS->nRasterYSize = 0;
-    
+
     int nBandsToAdd = 0;
     if (!poDS->ScanBlocks(&nBandsToAdd))
     {
         delete poDS;
         return NULL;
     }
-    
+
     if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) ||
         !GDALCheckBandCount(nBandsToAdd, FALSE))
     {
@@ -659,20 +667,20 @@ GDALDataset* EpsilonDataset::Open(GDALOpenInfo* poOpenInfo)
     }
     if (!poDS->bRegularTiling)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The EPSILON driver does not support reading "
                   "not regularly blocked files.\n" );
         delete poDS;
         return NULL;
     }
-    
+
     int i;
     for(i=1;i<=nBandsToAdd;i++)
         poDS->SetBand(i, new EpsilonRasterBand(poDS, i));
-        
+
     if (nBandsToAdd > 1)
         poDS->SetMetadataItem("INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE");
-    
+
     return poDS;
 }
 
@@ -681,9 +689,9 @@ GDALDataset* EpsilonDataset::Open(GDALOpenInfo* poOpenInfo)
 /*                  EpsilonDatasetCreateCopy ()                         */
 /************************************************************************/
 
-GDALDataset *
-EpsilonDatasetCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
-                       CPL_UNUSED int bStrict, char ** papszOptions, 
+static GDALDataset *
+EpsilonDatasetCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
+                       CPL_UNUSED int bStrict, char ** papszOptions,
                        GDALProgressFunc pfnProgress, void * pProgressData )
 {
     int nBands = poSrcDS->GetRasterCount();
@@ -695,7 +703,7 @@ EpsilonDatasetCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                  "or 3 band (RGB) data");
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Fetch and check creation options                                */
 /* -------------------------------------------------------------------- */
@@ -712,8 +720,8 @@ EpsilonDatasetCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         CPLError(CE_Failure, CPLE_NotSupported,
                 "Block size must be a power of 2 between 32 et 1024");
         return NULL;
-    }         
-    
+    }
+
     const char* pszFilter =
         CSLFetchNameValueDef(papszOptions, "FILTER", "daub97lift");
     char** papszFBID = eps_get_fb_info(EPS_FB_ID);
@@ -735,7 +743,7 @@ EpsilonDatasetCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                  pszFilter);
         return NULL;
     }
-    
+
     int eMode = EPS_MODE_OTLPF;
     const char* pszMode = CSLFetchNameValueDef(papszOptions, "MODE", "OTLPF");
     if (EQUAL(pszMode, "NORMAL"))
@@ -748,41 +756,41 @@ EpsilonDatasetCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                  pszMode);
         return NULL;
     }
-    
+
     char** papszFBType = eps_get_fb_info(EPS_FB_TYPE);
     int bIsBiOrthogonal = EQUAL(papszFBType[nIndexFB], "biorthogonal");
     eps_free_fb_info(papszFBType);
-    
+
     if (eMode == EPS_MODE_OTLPF && !bIsBiOrthogonal)
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "MODE=OTLPF can only be used with biorthogonal filters. "
                  "Use MODE=NORMAL instead");
         return NULL;
-    }    
-    
+    }
+
     int bRasterliteOutput =
-        CSLTestBoolean(CSLFetchNameValueDef(papszOptions,
+        CPLTestBool(CSLFetchNameValueDef(papszOptions,
                                             "RASTERLITE_OUTPUT", "NO"));
-             
+
     int nYRatio = EPS_Y_RT;
     int nCbRatio = EPS_Cb_RT;
     int nCrRatio = EPS_Cr_RT;
-    
+
     int eResample;
-    if (CSLTestBoolean(CSLFetchNameValueDef(papszOptions,
+    if (CPLTestBool(CSLFetchNameValueDef(papszOptions,
                                             "RGB_RESAMPLE", "YES")))
         eResample = EPS_RESAMPLE_420;
     else
         eResample = EPS_RESAMPLE_444;
-    
+
     const char* pszTarget = CSLFetchNameValueDef(papszOptions, "TARGET", "96");
     double dfReductionFactor = 1 - CPLAtof(pszTarget) / 100;
     if (dfReductionFactor > 1)
         dfReductionFactor = 1;
     else if (dfReductionFactor < 0)
         dfReductionFactor = 0;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Open file                                                       */
 /* -------------------------------------------------------------------- */
@@ -826,7 +834,7 @@ EpsilonDatasetCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         VSIFCloseL(fp);
         return NULL;
     }
-    
+
     GByte* pabyOutBuf = (GByte*)VSIMalloc(nTargetBlockSize);
     if (pabyOutBuf == NULL)
     {
@@ -834,7 +842,7 @@ EpsilonDatasetCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         VSIFCloseL(fp);
         return NULL;
     }
-    
+
     GByte** apapbyRawBuffer[3];
     int i, j;
     for(i=0;i<nBands;i++)
@@ -846,7 +854,7 @@ EpsilonDatasetCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                             pabyBuffer + (i * nBlockXSize + j) * nBlockYSize;
         }
     }
-    
+
     if (bRasterliteOutput)
     {
         const char* pszHeader = RASTERLITE_WAVELET_HEADER;
@@ -879,7 +887,7 @@ EpsilonDatasetCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             }
             if (bMustMemset)
                 memset(pabyBuffer, 0, nBands * nBlockXSize * nBlockYSize);
-            
+
             eErr = poSrcDS->RasterIO(GF_Read,
                               nBlockXOff * nBlockXSize,
                               nBlockYOff * nBlockYSize,
@@ -890,7 +898,7 @@ EpsilonDatasetCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                               1,
                               nBlockXSize,
                               nBlockXSize * nBlockYSize, NULL);
-            
+
             int nOutBufSize = nTargetBlockSize;
             if (eErr == CE_None && nBands == 1)
             {
@@ -902,8 +910,8 @@ EpsilonDatasetCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                                            pabyOutBuf, &nOutBufSize,
                                            (char*) pszFilter, eMode))
                 {
-                    CPLError(CE_Failure, CPLE_AppDefined,
-                             "Error occured when encoding block (%d, %d)",
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                              "Error occurred when encoding block (%d, %d)",
                              nBlockXOff, nBlockYOff);
                     eErr = CE_Failure;
                 }
@@ -924,12 +932,12 @@ EpsilonDatasetCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                                            (char*) pszFilter, eMode))
                 {
                     CPLError(CE_Failure, CPLE_AppDefined,
-                             "Error occured when encoding block (%d, %d)",
+                             "Error occurred when encoding block (%d, %d)",
                              nBlockXOff, nBlockYOff);
                     eErr = CE_Failure;
                 }
             }
-            
+
             if (eErr == CE_None)
             {
                 if ((int)VSIFWriteL(pabyOutBuf, 1, nOutBufSize, fp) !=
@@ -938,7 +946,7 @@ EpsilonDatasetCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
                 char chEPSMarker = EPS_MARKER;
                 VSIFWriteL(&chEPSMarker, 1, 1, fp);
-                
+
                 if (pfnProgress && !pfnProgress(
                       1.0 * (nBlockYOff * nXBlocks + nBlockXOff + 1) / nBlocks,
                       NULL, pProgressData))
@@ -948,7 +956,7 @@ EpsilonDatasetCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             }
         }
     }
-    
+
     if (bRasterliteOutput)
     {
         const char* pszFooter = RASTERLITE_WAVELET_FOOTER;
@@ -958,17 +966,17 @@ EpsilonDatasetCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Cleanup work buffers                                            */
 /* -------------------------------------------------------------------- */
-    
+
     for(i=0;i<nBands;i++)
     {
         VSIFree(apapbyRawBuffer[i]);
     }
-    
+
     VSIFree(pabyOutBuf);
     VSIFree(pabyBuffer);
-        
+
     VSIFCloseL(fp);
-    
+
     if (eErr != CE_None)
         return NULL;
 
@@ -985,39 +993,35 @@ EpsilonDatasetCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 void GDALRegister_EPSILON()
 
 {
-    GDALDriver  *poDriver;
-    
-    if (! GDAL_CHECK_VERSION("EPSILON driver"))
+    if( !GDAL_CHECK_VERSION( "EPSILON driver" ) )
         return;
 
-    if( GDALGetDriverByName( "EPSILON" ) == NULL )
+    if( GDALGetDriverByName( "EPSILON" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "EPSILON" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Epsilon wavelets" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_epsilon.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte" );
+
+    CPLString osMethods;
+    char** papszFBID = eps_get_fb_info(EPS_FB_ID);
+    char** papszFBIDIter = papszFBID;
+    while(papszFBIDIter && *papszFBIDIter)
     {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "EPSILON" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Epsilon wavelets" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "frmt_epsilon.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
-                                   "Byte" );
-
-        CPLString osMethods;
-        char** papszFBID = eps_get_fb_info(EPS_FB_ID);
-        char** papszFBIDIter = papszFBID;
-        while(papszFBIDIter && *papszFBIDIter)
-        {
-            osMethods += "       <Value>";
-            osMethods += *papszFBIDIter;
-            osMethods += "</Value>\n";
-            papszFBIDIter ++;
-        }
-        eps_free_fb_info(papszFBID);
-        
-        CPLString osOptionList;
-        osOptionList.Printf(
+        osMethods += "       <Value>";
+        osMethods += *papszFBIDIter;
+        osMethods += "</Value>\n";
+        papszFBIDIter ++;
+    }
+    eps_free_fb_info(papszFBID);
+
+    CPLString osOptionList;
+    osOptionList.Printf(
 "<CreationOptionList>"
 "   <Option name='TARGET' type='int' description='target size reduction as a percentage of the original (0-100)' default='75'/>"
 "   <Option name='FILTER' type='string-select' description='Filter ID' default='daub97lift'>"
@@ -1033,15 +1037,14 @@ void GDALRegister_EPSILON()
 "   <Option name='RASTERLITE_OUTPUT' type='boolean' description='if Rasterlite header and footers must be inserted' default='FALSE'/>"
 "</CreationOptionList>", osMethods.c_str()  );
 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
-                                   osOptionList.c_str() );
-                            
-        poDriver->pfnOpen = EpsilonDataset::Open;
-        poDriver->pfnIdentify = EpsilonDataset::Identify;
-        poDriver->pfnCreateCopy = EpsilonDatasetCreateCopy;
-        
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+                               osOptionList.c_str() );
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    poDriver->pfnOpen = EpsilonDataset::Open;
+    poDriver->pfnIdentify = EpsilonDataset::Identify;
+    poDriver->pfnCreateCopy = EpsilonDatasetCreateCopy;
+
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/epsilon/frmt_epsilon.html b/frmts/epsilon/frmt_epsilon.html
index d8dd6ce..3b7735f 100644
--- a/frmts/epsilon/frmt_epsilon.html
+++ b/frmts/epsilon/frmt_epsilon.html
@@ -1,41 +1,41 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<title>Epsilon - Wavelet compressed images</title>
-</head>
-
-<body>
-
-<h1>Epsilon - Wavelet compressed images</h1>
-
-<p>Starting with GDAL 1.7.0, GDAL can read and write wavelet-compressed images through the Epsilon library.
-Starting with GDAL 1.9.0, epsilon 0.9.1 is required.</p>
-
-<p>The driver rely on the Open Source EPSILON library (dual LGPL/GPL licence v3). In its current state, the
-   driver will only be able to read images with regular internal tiling.</p>
-
-<p>The EPSILON driver only supports 1 band (grayscale) and 3 bands (RGB) images</p>
-   
-<p>This is mainly intented to be used by the <a href="frmt_rasterlite.html">Rasterlite</a> driver.</p>
-
-<h2>Creation options</h2>
-
-<ul>
-<li><p><b>TARGET</b> Target size reduction as a percentage of the original (0-100). Defaults to 96</p></li>
-<li><p><b>FILTER</b>. See EPSILON documentation or 'gdalinfo --format EPSILON' for full list of filter IDs. Defaults to 'daub97lift'</p></li>
-<li><p><b>BLOCKXSIZE</b>=n: Sets tile width, defaults to 256. Power of 2 between 32 and 1024</p></li>
-<li><p><b>BLOCKYSIZE</b>=n: Sets tile height, defaults to 256. Power of 2 between 32 and 1024</p></li>
-<li><p><b>MODE</b>=[NORMAL/OTLPF] : OTLPF is some kind of hack to reduce boundary artefacts  when image is broken into several tiles.
-                                 Due to mathematical constrains this method can be applied to biorthogonal filters only. Defaults to OTLPF</p></li>
-<li><p><b>RGB_RESAMPLE</b>=[YES/NO] : Whether RGB buffer must be resampled to 4:2:0. Defaults to YES</p></li>
-</ul>
-
-<p>See Also:</p>
-
-<ul>
-<li><a href="http://sourceforge.net/projects/epsilon-project">EPSILON home page</a></li>
-</ul>
-
-</body>
-</html>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Epsilon - Wavelet compressed images</title>
+</head>
+
+<body>
+
+<h1>Epsilon - Wavelet compressed images</h1>
+
+<p>Starting with GDAL 1.7.0, GDAL can read and write wavelet-compressed images through the Epsilon library.
+Starting with GDAL 1.9.0, epsilon 0.9.1 is required.</p>
+
+<p>The driver rely on the Open Source EPSILON library (dual LGPL/GPL licence v3). In its current state, the
+   driver will only be able to read images with regular internal tiling.</p>
+
+<p>The EPSILON driver only supports 1 band (grayscale) and 3 bands (RGB) images</p>
+
+<p>This is mainly intended to be used by the <a href="frmt_rasterlite.html">Rasterlite</a> driver.</p>
+
+<h2>Creation options</h2>
+
+<ul>
+<li><p><b>TARGET</b> Target size reduction as a percentage of the original (0-100). Defaults to 96</p></li>
+<li><p><b>FILTER</b>. See EPSILON documentation or 'gdalinfo --format EPSILON' for full list of filter IDs. Defaults to 'daub97lift'</p></li>
+<li><p><b>BLOCKXSIZE</b>=n: Sets tile width, defaults to 256. Power of 2 between 32 and 1024</p></li>
+<li><p><b>BLOCKYSIZE</b>=n: Sets tile height, defaults to 256. Power of 2 between 32 and 1024</p></li>
+<li><p><b>MODE</b>=[NORMAL/OTLPF] : OTLPF is some kind of hack to reduce boundary artifacts  when image is broken into several tiles.
+                                 Due to mathematical constrains this method can be applied to biorthogonal filters only. Defaults to OTLPF</p></li>
+<li><p><b>RGB_RESAMPLE</b>=[YES/NO] : Whether RGB buffer must be resampled to 4:2:0. Defaults to YES</p></li>
+</ul>
+
+<p>See Also:</p>
+
+<ul>
+<li><a href="http://sourceforge.net/projects/epsilon-project">EPSILON home page</a></li>
+</ul>
+
+</body>
+</html>
diff --git a/frmts/ers/ersdataset.cpp b/frmts/ers/ersdataset.cpp
index 1da4234..dbcc251 100644
--- a/frmts/ers/ersdataset.cpp
+++ b/frmts/ers/ersdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ersdataset.cpp 28474 2015-02-13 11:42:37Z rouault $
+ * $Id: ersdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  ERMapper .ers Driver
  * Purpose:  Implementation of .ers driver.
@@ -28,12 +28,13 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "rawdataset.h"
-#include "ogr_spatialref.h"
 #include "cpl_string.h"
 #include "ershdrnode.h"
+#include "gdal_frmts.h"
+#include "ogr_spatialref.h"
+#include "rawdataset.h"
 
-CPL_CVSID("$Id: ersdataset.cpp 28474 2015-02-13 11:42:37Z rouault $");
+CPL_CVSID("$Id: ersdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -85,14 +86,14 @@ class ERSDataset : public RawDataset
   public:
     		ERSDataset();
 	       ~ERSDataset();
-    
+
     virtual void FlushCache(void);
     virtual CPLErr GetGeoTransform( double * padfTransform );
     virtual CPLErr SetGeoTransform( double *padfTransform );
     virtual const char *GetProjectionRef(void);
     virtual CPLErr SetProjection( const char * );
     virtual char **GetFileList(void);
-    
+
     virtual int    GetGCPCount();
     virtual const char *GetGCPProjection();
     virtual const GDAL_GCP *GetGCPs();
@@ -115,27 +116,26 @@ class ERSDataset : public RawDataset
 /*                            ERSDataset()                             */
 /************************************************************************/
 
-ERSDataset::ERSDataset()
+ERSDataset::ERSDataset() :
+    fpImage(NULL),
+    poDepFile(NULL),
+    bGotTransform(FALSE),
+    bHDRDirty(FALSE),
+    poHeader(NULL),
+    nGCPCount(0),
+    pasGCPList(NULL),
+    bHasNoDataValue(FALSE),
+    dfNoDataValue(0.0)
 {
-    fpImage = NULL;
-    poDepFile = NULL;
     pszProjection = CPLStrdup("");
-    bGotTransform = FALSE;
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
-    poHeader = NULL;
-    bHDRDirty = FALSE;
 
-    nGCPCount = 0;
-    pasGCPList = NULL;
     pszGCPProjection = CPLStrdup("");
-
-    bHasNoDataValue = FALSE;
-    dfNoDataValue = 0.0;
 }
 
 /************************************************************************/
@@ -177,11 +177,9 @@ int ERSDataset::CloseDependentDatasets()
 
     if( poDepFile != NULL )
     {
-        int iBand;
-
         bHasDroppedRef = TRUE;
 
-        for( iBand = 0; iBand < nBands; iBand++ )
+        for( int iBand = 0; iBand < nBands; iBand++ )
             papoBands[iBand] = NULL;
         nBands = 0;
 
@@ -204,7 +202,7 @@ void ERSDataset::FlushCache()
         VSILFILE * fpERS = VSIFOpenL( GetDescription(), "w" );
         if( fpERS == NULL )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
+            CPLError( CE_Failure, CPLE_OpenFailed,
                       "Unable to rewrite %s header.",
                       GetDescription() );
         }
@@ -268,8 +266,8 @@ char **ERSDataset::GetMetadata( const char *pszDomain )
             oERSMetadataList.AddString(CPLSPrintf("%s=%s", "UNITS", osUnits.c_str()));
         return oERSMetadataList.List();
     }
-    else
-        return GDALPamDataset::GetMetadata( pszDomain );
+
+    return GDALPamDataset::GetMetadata( pszDomain );
 }
 
 /************************************************************************/
@@ -352,30 +350,29 @@ CPLErr ERSDataset::SetGCPs( int nGCPCountIn, const GDAL_GCP *pasGCPListIn,
 
     oSRS.exportToERM( szERSProj, szERSDatum, szERSUnits );
 
-    /* Write the above computed values, unless they have been overriden by */
+    /* Write the above computed values, unless they have been overridden by */
     /* the creation options PROJ, DATUM or UNITS */
 
-    poHeader->Set( "RasterInfo.WarpControl.CoordinateSpace.Datum", 
+    poHeader->Set( "RasterInfo.WarpControl.CoordinateSpace.Datum",
                    CPLString().Printf( "\"%s\"",
                         (osDatum.size()) ? osDatum.c_str() : szERSDatum ) );
-    poHeader->Set( "RasterInfo.WarpControl.CoordinateSpace.Projection", 
+    poHeader->Set( "RasterInfo.WarpControl.CoordinateSpace.Projection",
                    CPLString().Printf( "\"%s\"",
                         (osProj.size()) ? osProj.c_str() : szERSProj ) );
-    poHeader->Set( "RasterInfo.WarpControl.CoordinateSpace.CoordinateType", 
+    poHeader->Set( "RasterInfo.WarpControl.CoordinateSpace.CoordinateType",
                    CPLString().Printf( "EN" ) );
-    poHeader->Set( "RasterInfo.WarpControl.CoordinateSpace.Units", 
+    poHeader->Set( "RasterInfo.WarpControl.CoordinateSpace.Units",
                    CPLString().Printf( "\"%s\"",
                         (osUnits.size()) ? osUnits.c_str() : szERSUnits ) );
-    poHeader->Set( "RasterInfo.WarpControl.CoordinateSpace.Rotation", 
+    poHeader->Set( "RasterInfo.WarpControl.CoordinateSpace.Rotation",
                    "0:0:0.0" );
 
 /* -------------------------------------------------------------------- */
 /*      Translate the GCPs.                                             */
 /* -------------------------------------------------------------------- */
     CPLString osControlPoints = "{\n";
-    int iGCP;
-    
-    for( iGCP = 0; iGCP < nGCPCount; iGCP++ )
+
+    for( int iGCP = 0; iGCP < nGCPCount; iGCP++ )
     {
         CPLString osLine;
 
@@ -393,7 +390,7 @@ CPLErr ERSDataset::SetGCPs( int nGCPCountIn, const GDAL_GCP *pasGCPListIn,
         osControlPoints += osLine;
     }
     osControlPoints += "\t\t}";
-    
+
     poHeader->Set( "RasterInfo.WarpControl.ControlPoints", osControlPoints );
 
     return CE_None;
@@ -435,7 +432,7 @@ CPLErr ERSDataset::SetProjection( const char *pszSRS )
 
     oSRS.exportToERM( szERSProj, szERSDatum, szERSUnits );
 
-    /* Write the above computed values, unless they have been overriden by */
+    /* Write the above computed values, unless they have been overridden by */
     /* the creation options PROJ, DATUM or UNITS */
     if( osProjForced.size() )
         osProj = osProjForced;
@@ -464,15 +461,15 @@ void ERSDataset::WriteProjectionInfo(const char* pszProj,
                                      const char* pszUnits)
 {
     bHDRDirty = TRUE;
-    poHeader->Set( "CoordinateSpace.Datum", 
+    poHeader->Set( "CoordinateSpace.Datum",
                    CPLString().Printf( "\"%s\"", pszDatum ) );
-    poHeader->Set( "CoordinateSpace.Projection", 
+    poHeader->Set( "CoordinateSpace.Projection",
                    CPLString().Printf( "\"%s\"", pszProj ) );
-    poHeader->Set( "CoordinateSpace.CoordinateType", 
+    poHeader->Set( "CoordinateSpace.CoordinateType",
                    CPLString().Printf( "EN" ) );
-    poHeader->Set( "CoordinateSpace.Units", 
+    poHeader->Set( "CoordinateSpace.Units",
                    CPLString().Printf( "\"%s\"", pszUnits ) );
-    poHeader->Set( "CoordinateSpace.Rotation", 
+    poHeader->Set( "CoordinateSpace.Rotation",
                    "0:0:0.0" );
 
 /* -------------------------------------------------------------------- */
@@ -481,9 +478,8 @@ void ERSDataset::WriteProjectionInfo(const char* pszProj,
 /* -------------------------------------------------------------------- */
     int iRasterInfo = -1;
     int iCoordSpace = -1;
-    int i;
 
-    for( i = 0; i < poHeader->nItemCount; i++ )
+    for( int i = 0; i < poHeader->nItemCount; i++ )
     {
         if( EQUAL(poHeader->papszItemName[i],"RasterInfo") )
             iRasterInfo = i;
@@ -497,15 +493,14 @@ void ERSDataset::WriteProjectionInfo(const char* pszProj,
 
     if( iCoordSpace > iRasterInfo && iRasterInfo != -1 )
     {
-        for( i = iCoordSpace; i > 0 && i != iRasterInfo; i-- )
+        for( int i = iCoordSpace; i > 0 && i != iRasterInfo; i-- )
         {
-            char *pszTemp;
 
             ERSHdrNode *poTemp = poHeader->papoItemChild[i];
             poHeader->papoItemChild[i] = poHeader->papoItemChild[i-1];
             poHeader->papoItemChild[i-1] = poTemp;
 
-            pszTemp = poHeader->papszItemName[i];
+            char *pszTemp = poHeader->papszItemName[i];
             poHeader->papszItemName[i] = poHeader->papszItemName[i-1];
             poHeader->papszItemName[i-1] = pszTemp;
 
@@ -528,10 +523,8 @@ CPLErr ERSDataset::GetGeoTransform( double * padfTransform )
         memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
         return CE_None;
     }
-    else
-    {
-        return GDALPamDataset::GetGeoTransform( padfTransform );
-    }
+
+    return GDALPamDataset::GetGeoTransform( padfTransform );
 }
 
 /************************************************************************/
@@ -546,7 +539,7 @@ CPLErr ERSDataset::SetGeoTransform( double *padfTransform )
 
     if( adfGeoTransform[2] != 0 || adfGeoTransform[4] != 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Rotated and skewed geotransforms not currently supported for ERS driver." );
         return CE_Failure;
     }
@@ -556,17 +549,17 @@ CPLErr ERSDataset::SetGeoTransform( double *padfTransform )
 
     bHDRDirty = TRUE;
 
-    poHeader->Set( "RasterInfo.CellInfo.Xdimension", 
+    poHeader->Set( "RasterInfo.CellInfo.Xdimension",
                    CPLString().Printf( "%.15g", fabs(adfGeoTransform[1]) ) );
-    poHeader->Set( "RasterInfo.CellInfo.Ydimension", 
+    poHeader->Set( "RasterInfo.CellInfo.Ydimension",
                    CPLString().Printf( "%.15g", fabs(adfGeoTransform[5]) ) );
-    poHeader->Set( "RasterInfo.RegistrationCoord.Eastings", 
+    poHeader->Set( "RasterInfo.RegistrationCoord.Eastings",
                    CPLString().Printf( "%.15g", adfGeoTransform[0] ) );
-    poHeader->Set( "RasterInfo.RegistrationCoord.Northings", 
+    poHeader->Set( "RasterInfo.RegistrationCoord.Northings",
                    CPLString().Printf( "%.15g", adfGeoTransform[3] ) );
 
     if( CPLAtof(poHeader->Find("RasterInfo.RegistrationCellX", "0")) != 0.0 ||
-        CPLAtof(poHeader->Find("RasterInfo.RegistrationCellY", "0")) != 0.0 ) 
+        CPLAtof(poHeader->Find("RasterInfo.RegistrationCellY", "0")) != 0.0 )
     {
         // Reset RegistrationCellX/Y to 0 if the header gets rewritten (#5493)
         poHeader->Set("RasterInfo.RegistrationCellX", "0");
@@ -593,18 +586,16 @@ static double ERSDMS2Dec( const char *pszDMS )
         CSLDestroy(papszTokens);
         return CPLAtof( pszDMS );
     }
-    else
-    {
-        double dfResult = fabs(CPLAtof(papszTokens[0]))
-            + CPLAtof(papszTokens[1]) / 60.0
-            + CPLAtof(papszTokens[2]) / 3600.0;
 
-        if( CPLAtof(papszTokens[0]) < 0 )
-            dfResult *= -1;
+    double dfResult = fabs(CPLAtof(papszTokens[0]))
+        + CPLAtof(papszTokens[1]) / 60.0
+        + CPLAtof(papszTokens[2]) / 3600.0;
 
-        CSLDestroy( papszTokens );
-        return dfResult;
-    }
+    if( CPLAtof(papszTokens[0]) < 0 )
+        dfResult *= -1;
+
+    CSLDestroy( papszTokens );
+    return dfResult;
 }
 
 /************************************************************************/
@@ -614,20 +605,19 @@ static double ERSDMS2Dec( const char *pszDMS )
 char **ERSDataset::GetFileList()
 
 {
-    char **papszFileList = NULL;
 
-    // Main data file, etc. 
-    papszFileList = GDALPamDataset::GetFileList();
+    // Main data file, etc.
+    char **papszFileList = GDALPamDataset::GetFileList();
 
-    // Add raw data file if we have one. 
+    // Add raw data file if we have one.
     if( strlen(osRawFilename) > 0 )
         papszFileList = CSLAddString( papszFileList, osRawFilename );
 
-    // If we have a dependent file, merge it's list of files in. 
+    // If we have a dependent file, merge it's list of files in.
     if( poDepFile )
     {
         char **papszDepFiles = poDepFile->GetFileList();
-        papszFileList = 
+        papszFileList =
             CSLInsertStrings( papszFileList, -1, papszDepFiles );
         CSLDestroy( papszDepFiles );
     }
@@ -644,7 +634,7 @@ char **ERSDataset::GetFileList()
 void ERSDataset::ReadGCPs()
 
 {
-    const char *pszCP = 
+    const char *pszCP =
         poHeader->Find( "RasterInfo.WarpControl.ControlPoints", NULL );
 
     if( pszCP == NULL )
@@ -656,12 +646,13 @@ void ERSDataset::ReadGCPs()
 /*   "1035" Yes No 2344.650885 3546.419458 483270.73 3620906.21 3.105   */
 /* -------------------------------------------------------------------- */
     char **papszTokens = CSLTokenizeStringComplex( pszCP, "{ \t}", TRUE,FALSE);
-    int nItemsPerLine;
     int nItemCount = CSLCount(papszTokens);
 
 /* -------------------------------------------------------------------- */
 /*      Work out if we have elevation values or not.                    */
 /* -------------------------------------------------------------------- */
+    int nItemsPerLine;
+
     if( nItemCount == 7 )
         nItemsPerLine = 7;
     else if( nItemCount == 8 )
@@ -686,15 +677,13 @@ void ERSDataset::ReadGCPs()
 /* -------------------------------------------------------------------- */
 /*      Setup GCPs.                                                     */
 /* -------------------------------------------------------------------- */
-    int iGCP;
-
     CPLAssert( nGCPCount == 0 );
 
     nGCPCount = nItemCount / nItemsPerLine;
     pasGCPList = (GDAL_GCP *) CPLCalloc(nGCPCount,sizeof(GDAL_GCP));
     GDALInitGCPs( nGCPCount, pasGCPList );
 
-    for( iGCP = 0; iGCP < nGCPCount; iGCP++ )
+    for( int iGCP = 0; iGCP < nGCPCount; iGCP++ )
     {
         GDAL_GCP *psGCP = pasGCPList + iGCP;
 
@@ -707,9 +696,9 @@ void ERSDataset::ReadGCPs()
         if( nItemsPerLine == 8 )
             psGCP->dfGCPZ = CPLAtof(papszTokens[iGCP*nItemsPerLine+7]);
     }
-    
+
     CSLDestroy( papszTokens );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Parse the GCP projection.                                       */
 /* -------------------------------------------------------------------- */
@@ -751,13 +740,13 @@ class ERSRasterBand : public RawRasterBand
 /*                           ERSRasterBand()                            */
 /************************************************************************/
 
-ERSRasterBand::ERSRasterBand( GDALDataset *poDS, int nBand, void * fpRaw,
-                                vsi_l_offset nImgOffset, int nPixelOffset,
-                                int nLineOffset,
-                                GDALDataType eDataType, int bNativeOrder,
-                                int bIsVSIL, int bOwnsFP ) :
-    RawRasterBand(poDS, nBand, fpRaw, nImgOffset, nPixelOffset,
-                  nLineOffset, eDataType, bNativeOrder, bIsVSIL, bOwnsFP)
+ERSRasterBand::ERSRasterBand( GDALDataset *poDSIn, int nBandIn, void * fpRawIn,
+                                vsi_l_offset nImgOffsetIn, int nPixelOffsetIn,
+                                int nLineOffsetIn,
+                                GDALDataType eDataTypeIn, int bNativeOrderIn,
+                                int bIsVSILIn, int bOwnsFPIn ) :
+    RawRasterBand(poDSIn, nBandIn, fpRawIn, nImgOffsetIn, nPixelOffsetIn,
+                  nLineOffsetIn, eDataTypeIn, bNativeOrderIn, bIsVSILIn, bOwnsFPIn)
 {
 }
 
@@ -808,7 +797,7 @@ int ERSDataset::Identify( GDALOpenInfo * poOpenInfo )
 /*      We assume the user selects the .ers file.                       */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->nHeaderBytes > 15
-        && EQUALN((const char *) poOpenInfo->pabyHeader,"Algorithm Begin",15) )
+        && STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "Algorithm Begin") )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
                   "%s appears to be an algorithm ERS file, which is not currently supported.",
@@ -820,7 +809,7 @@ int ERSDataset::Identify( GDALOpenInfo * poOpenInfo )
 /*      We assume the user selects the .ers file.                       */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->nHeaderBytes < 15
-        || !EQUALN((const char *) poOpenInfo->pabyHeader,"DatasetHeader ",14) )
+        || !STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "DatasetHeader ") )
         return FALSE;
 
     return TRUE;
@@ -840,7 +829,7 @@ GDALDataset *ERSDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Open the .ers file, and read the first line.                    */
 /* -------------------------------------------------------------------- */
     VSILFILE *fpERS = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
-    
+
     if( fpERS == NULL )
         return NULL;
 
@@ -863,14 +852,14 @@ GDALDataset *ERSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Do we have the minimum required information from this header?   */
 /* -------------------------------------------------------------------- */
-    if( poHeader->Find( "RasterInfo.NrOfLines" ) == NULL 
-        || poHeader->Find( "RasterInfo.NrOfCellsPerLine" ) == NULL 
+    if( poHeader->Find( "RasterInfo.NrOfLines" ) == NULL
+        || poHeader->Find( "RasterInfo.NrOfCellsPerLine" ) == NULL
         || poHeader->Find( "RasterInfo.NrOfBands" ) == NULL )
     {
         if( poHeader->FindNode( "Algorithm" ) != NULL )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
-                      "%s appears to be an algorithm ERS file, which is not currently supported.", 
+            CPLError( CE_Failure, CPLE_OpenFailed,
+                      "%s appears to be an algorithm ERS file, which is not currently supported.",
                       poOpenInfo->pszFilename );
         }
         delete poHeader;
@@ -880,9 +869,7 @@ GDALDataset *ERSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    ERSDataset     *poDS;
-
-    poDS = new ERSDataset();
+    ERSDataset *poDS = new ERSDataset();
     poDS->poHeader = poHeader;
     poDS->eAccess = poOpenInfo->eAccess;
 
@@ -892,7 +879,7 @@ GDALDataset *ERSDataset::Open( GDALOpenInfo * poOpenInfo )
     int nBands = atoi(poHeader->Find( "RasterInfo.NrOfBands" ));
     poDS->nRasterXSize = atoi(poHeader->Find( "RasterInfo.NrOfCellsPerLine" ));
     poDS->nRasterYSize = atoi(poHeader->Find( "RasterInfo.NrOfLines" ));
-    
+
     if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) ||
         !GDALCheckBandCount(nBands, FALSE))
     {
@@ -912,9 +899,9 @@ GDALDataset *ERSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Establish the data type.                                        */
 /* -------------------------------------------------------------------- */
-    GDALDataType eType;
-    CPLString osCellType = poHeader->Find( "RasterInfo.CellType", 
+    CPLString osCellType = poHeader->Find( "RasterInfo.CellType",
                                            "Unsigned8BitInteger" );
+    GDALDataType eType;
     if( EQUAL(osCellType,"Unsigned8BitInteger") )
         eType = GDT_Byte;
     else if( EQUAL(osCellType,"Signed8BitInteger") )
@@ -940,30 +927,26 @@ GDALDataset *ERSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Pick up the word order.                                         */
 /* -------------------------------------------------------------------- */
-    int bNative;
-
+    const int bNative =
 #ifdef CPL_LSB
-    bNative = EQUAL(poHeader->Find( "ByteOrder", "LSBFirst" ),
-                    "LSBFirst");
+    EQUAL(poHeader->Find( "ByteOrder", "LSBFirst" ), "LSBFirst")
 #else
-    bNative = EQUAL(poHeader->Find( "ByteOrder", "MSBFirst" ),
-                    "MSBFirst");
+    EQUAL(poHeader->Find( "ByteOrder", "MSBFirst" ), "MSBFirst")
 #endif
-
+    ;
 /* -------------------------------------------------------------------- */
 /*      Figure out the name of the target file.                         */
 /* -------------------------------------------------------------------- */
     CPLString osPath = CPLGetPath( poOpenInfo->pszFilename );
     CPLString osDataFile = poHeader->Find( "DataFile", "" );
-    CPLString osDataFilePath;
 
     if( osDataFile.length() == 0 ) // just strip off extension.
     {
         osDataFile = CPLGetFilename( poOpenInfo->pszFilename );
         osDataFile = osDataFile.substr( 0, osDataFile.find_last_of('.') );
     }
-        
-    osDataFilePath = CPLFormFilename( osPath, osDataFile, NULL );
+
+    CPLString osDataFilePath = CPLFormFilename( osPath, osDataFile, NULL );
 
 /* -------------------------------------------------------------------- */
 /*      DataSetType = Translated files are links to things like ecw     */
@@ -971,18 +954,16 @@ GDALDataset *ERSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( EQUAL(poHeader->Find("DataSetType",""),"Translated") )
     {
-        poDS->poDepFile = (GDALDataset *) 
+        poDS->poDepFile = (GDALDataset *)
             GDALOpenShared( osDataFilePath, poOpenInfo->eAccess );
 
-        if( poDS->poDepFile != NULL 
+        if( poDS->poDepFile != NULL
             && poDS->poDepFile->GetRasterCount() >= nBands )
         {
-            int iBand;
-
-            for( iBand = 0; iBand < nBands; iBand++ )
+            for( int iBand = 0; iBand < nBands; iBand++ )
             {
                 // Assume pixel interleaved.
-                poDS->SetBand( iBand+1, 
+                poDS->SetBand( iBand+1,
                                poDS->poDepFile->GetRasterBand( iBand+1 ) );
             }
         }
@@ -1004,22 +985,21 @@ GDALDataset *ERSDataset::Open( GDALOpenInfo * poOpenInfo )
         if( poDS->fpImage != NULL )
         {
             int iWordSize = GDALGetDataTypeSize(eType) / 8;
-            int iBand;
 
-            for( iBand = 0; iBand < nBands; iBand++ )
+            for( int iBand = 0; iBand < nBands; iBand++ )
             {
                 // Assume pixel interleaved.
-                poDS->SetBand( 
-                    iBand+1, 
+                poDS->SetBand(
+                    iBand+1,
                     new ERSRasterBand( poDS, iBand+1, poDS->fpImage,
-                                       nHeaderOffset 
+                                       nHeaderOffset
                                        + iWordSize * iBand * poDS->nRasterXSize,
                                        iWordSize,
                                        iWordSize * nBands * poDS->nRasterXSize,
                                        eType, bNative, TRUE ));
                 if( EQUAL(osCellType,"Signed8BitInteger") )
                     poDS->GetRasterBand(iBand+1)->
-                        SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", 
+                        SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE",
                                          "IMAGE_STRUCTURE" );
             }
         }
@@ -1037,17 +1017,16 @@ GDALDataset *ERSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Look for band descriptions.                                     */
 /* -------------------------------------------------------------------- */
-    int iChild, iBand = 0;
     ERSHdrNode *poRI = poHeader->FindNode( "RasterInfo" );
 
-    for( iChild = 0; 
-         poRI != NULL && iChild < poRI->nItemCount && iBand < poDS->nBands; 
+    for( int iChild = 0, iBand = 0;
+         poRI != NULL && iChild < poRI->nItemCount && iBand < poDS->nBands;
          iChild++ )
     {
         if( poRI->papoItemChild[iChild] != NULL
             && EQUAL(poRI->papszItemName[iChild],"BandId") )
         {
-            const char *pszValue = 
+            const char *pszValue =
                 poRI->papoItemChild[iChild]->Find( "Value", NULL );
 
             iBand++;
@@ -1090,30 +1069,30 @@ GDALDataset *ERSDataset::Open( GDALOpenInfo * poOpenInfo )
     if( poHeader->Find( "RasterInfo.RegistrationCoord.Eastings", NULL ) )
     {
         poDS->bGotTransform = TRUE;
-        poDS->adfGeoTransform[0] = CPLAtof( 
+        poDS->adfGeoTransform[0] = CPLAtof(
             poHeader->Find( "RasterInfo.RegistrationCoord.Eastings", "" ));
-        poDS->adfGeoTransform[1] = CPLAtof( 
+        poDS->adfGeoTransform[1] = CPLAtof(
             poHeader->Find( "RasterInfo.CellInfo.Xdimension", "1.0" ));
         poDS->adfGeoTransform[2] = 0.0;
-        poDS->adfGeoTransform[3] = CPLAtof( 
+        poDS->adfGeoTransform[3] = CPLAtof(
             poHeader->Find( "RasterInfo.RegistrationCoord.Northings", "" ));
         poDS->adfGeoTransform[4] = 0.0;
-        poDS->adfGeoTransform[5] = -CPLAtof( 
+        poDS->adfGeoTransform[5] = -CPLAtof(
             poHeader->Find( "RasterInfo.CellInfo.Ydimension", "1.0" ));
     }
     else if( poHeader->Find( "RasterInfo.RegistrationCoord.Latitude", NULL )
              && poHeader->Find( "RasterInfo.CellInfo.Xdimension", NULL ) )
     {
         poDS->bGotTransform = TRUE;
-        poDS->adfGeoTransform[0] = ERSDMS2Dec( 
+        poDS->adfGeoTransform[0] = ERSDMS2Dec(
             poHeader->Find( "RasterInfo.RegistrationCoord.Longitude", "" ));
-        poDS->adfGeoTransform[1] = CPLAtof( 
+        poDS->adfGeoTransform[1] = CPLAtof(
             poHeader->Find( "RasterInfo.CellInfo.Xdimension", "" ));
         poDS->adfGeoTransform[2] = 0.0;
-        poDS->adfGeoTransform[3] = ERSDMS2Dec( 
+        poDS->adfGeoTransform[3] = ERSDMS2Dec(
             poHeader->Find( "RasterInfo.RegistrationCoord.Latitude", "" ));
         poDS->adfGeoTransform[4] = 0.0;
-        poDS->adfGeoTransform[5] = -CPLAtof( 
+        poDS->adfGeoTransform[5] = -CPLAtof(
             poHeader->Find( "RasterInfo.CellInfo.Ydimension", "" ));
     }
 
@@ -1139,7 +1118,7 @@ GDALDataset *ERSDataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->adfGeoTransform[0] -=
             dfCellX * poDS->adfGeoTransform[1]
             + dfCellY * poDS->adfGeoTransform[2];
-        poDS->adfGeoTransform[3] -= 
+        poDS->adfGeoTransform[3] -=
             dfCellX * poDS->adfGeoTransform[4]
             + dfCellY * poDS->adfGeoTransform[5];
     }
@@ -1156,7 +1135,7 @@ GDALDataset *ERSDataset::Open( GDALOpenInfo * poOpenInfo )
         {
             CPLPushErrorHandler( CPLQuietErrorHandler );
 
-            for( iBand = 1; iBand <= poDS->nBands; iBand++ )
+            for( int iBand = 1; iBand <= poDS->nBands; iBand++ )
                 poDS->GetRasterBand(iBand)->SetNoDataValue(poDS->dfNoDataValue);
 
             CPLPopErrorHandler();
@@ -1168,14 +1147,14 @@ GDALDataset *ERSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     ERSHdrNode *poAll = NULL;
 
-    for( iChild = 0; 
-         poRI != NULL && iChild < poRI->nItemCount; 
+    for( int iChild = 0;
+         poRI != NULL && iChild < poRI->nItemCount;
          iChild++ )
     {
         if( poRI->papoItemChild[iChild] != NULL
             && EQUAL(poRI->papszItemName[iChild],"RegionInfo") )
         {
-            if( EQUAL(poRI->papoItemChild[iChild]->Find("RegionName",""), 
+            if( EQUAL(poRI->papoItemChild[iChild]->Find("RegionName",""),
                       "All") )
                 poAll = poRI->papoItemChild[iChild];
         }
@@ -1188,9 +1167,9 @@ GDALDataset *ERSDataset::Open( GDALOpenInfo * poOpenInfo )
     {
         CPLPushErrorHandler( CPLQuietErrorHandler );
 
-        for( iBand = 1; iBand <= poDS->nBands; iBand++ )
+        for( int iBand = 1; iBand <= poDS->nBands; iBand++ )
         {
-            const char *pszValue = 
+            const char *pszValue =
                 poAll->FindElem( "Stats.MinimumValue", iBand-1 );
 
             if( pszValue )
@@ -1215,9 +1194,9 @@ GDALDataset *ERSDataset::Open( GDALOpenInfo * poOpenInfo )
                 poDS->GetRasterBand(iBand)->SetMetadataItem(
                     "STATISTICS_MEDIAN", pszValue );
         }
-        
+
         CPLPopErrorHandler();
-        
+
     }
 
 /* -------------------------------------------------------------------- */
@@ -1231,7 +1210,7 @@ GDALDataset *ERSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->TryLoadXML();
-    
+
     // if no SR in xml, try aux
     const char* pszPrj = poDS->GDALPamDataset::GetProjectionRef();
     if( !pszPrj || strlen(pszPrj) == 0 )
@@ -1272,7 +1251,7 @@ GDALDataset *ERSDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
     if (nBands <= 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "ERS driver does not support %d bands.\n", nBands);
         return NULL;
     }
@@ -1281,8 +1260,8 @@ GDALDataset *ERSDataset::Create( const char * pszFilename,
         && eType != GDT_Int32 && eType != GDT_UInt32
         && eType != GDT_Float32 && eType != GDT_Float64 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "The ERS driver does not supporting creating files of types %s.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "The ERS driver does not supporting creating files of types %s.",
                   GDALGetDataTypeName( eType ) );
         return NULL;
     }
@@ -1332,34 +1311,32 @@ GDALDataset *ERSDataset::Create( const char * pszFilename,
 /*      Handling for signed eight bit data.                             */
 /* -------------------------------------------------------------------- */
     const char *pszPixelType = CSLFetchNameValue( papszOptions, "PIXELTYPE" );
-    if( pszPixelType 
-        && EQUAL(pszPixelType,"SIGNEDBYTE") 
+    if( pszPixelType
+        && EQUAL(pszPixelType,"SIGNEDBYTE")
         && eType == GDT_Byte )
         pszCellType = "Signed8BitInteger";
 
 /* -------------------------------------------------------------------- */
 /*      Write binary file.                                              */
 /* -------------------------------------------------------------------- */
-    GUIntBig nSize;
-    GByte byZero = 0;
-
     VSILFILE *fpBin = VSIFOpenL( osBinFile, "w" );
 
     if( fpBin == NULL )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
-                  "Failed to create %s:\n%s", 
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Failed to create %s:\n%s",
                   osBinFile.c_str(), VSIStrerror( errno ) );
         return NULL;
     }
 
-    nSize = nXSize * (GUIntBig) nYSize 
+    GUIntBig nSize = nXSize * (GUIntBig) nYSize
         * nBands * (GDALGetDataTypeSize(eType) / 8);
+    GByte byZero = 0;
     if( VSIFSeekL( fpBin, nSize-1, SEEK_SET ) != 0
         || VSIFWriteL( &byZero, 1, 1, fpBin ) != 1 )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
-                  "Failed to write %s:\n%s", 
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Failed to write %s:\n%s",
                   osBinFile.c_str(), VSIStrerror( errno ) );
         VSIFCloseL( fpBin );
         return NULL;
@@ -1371,11 +1348,11 @@ GDALDataset *ERSDataset::Create( const char * pszFilename,
 /*      Try writing header file.                                        */
 /* -------------------------------------------------------------------- */
     VSILFILE *fpERS = VSIFOpenL( osErsFile, "w" );
-    
+
     if( fpERS == NULL )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
-                  "Failed to create %s:\n%s", 
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Failed to create %s:\n%s",
                   osErsFile.c_str(), VSIStrerror( errno ) );
         return NULL;
     }
@@ -1386,7 +1363,7 @@ GDALDataset *ERSDataset::Create( const char * pszFilename,
 
 // Last updated requires timezone info which we don't necessarily get
 // get from VSICTime() so perhaps it is better to omit this.
-//    VSIFPrintfL( fpERS, "\tLastUpdated\t= %s", 
+//    VSIFPrintfL( fpERS, "\tLastUpdated\t= %s",
 //                 VSICTime( VSITime( NULL ) ) );
 
     VSIFPrintfL( fpERS, "\tDataSetType\t= ERStorage\n" );
@@ -1400,8 +1377,8 @@ GDALDataset *ERSDataset::Create( const char * pszFilename,
     VSIFPrintfL( fpERS, "\tRasterInfo End\n" );
     if( VSIFPrintfL( fpERS, "DatasetHeader End\n" ) < 17 )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
-                  "Failed to write %s:\n%s", 
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Failed to write %s:\n%s",
                   osErsFile.c_str(), VSIStrerror( errno ) );
         return NULL;
     }
@@ -1435,7 +1412,7 @@ GDALDataset *ERSDataset::Create( const char * pszFilename,
                                   pszDatum ? pszDatum : "RAW",
                                   pszUnits ? pszUnits : "METERS");
     }
-    
+
     return poDS;
 }
 
@@ -1446,22 +1423,20 @@ GDALDataset *ERSDataset::Create( const char * pszFilename,
 void GDALRegister_ERS()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "ERS" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "ERS" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "ERS" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "ERMapper .ers Labelled" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_ers.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte Int16 UInt16 Int32 UInt32 Float32 Float64" );
-
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "ERS" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "ERMapper .ers Labelled" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_ers.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte Int16 UInt16 Int32 UInt32 "
+                               "Float32 Float64" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "   <Option name='PIXELTYPE' type='string' description='By setting this to SIGNEDBYTE, a new Byte file can be forced to be written as signed byte'/>"
 "   <Option name='PROJ' type='string' description='ERS Projection Name'/>"
@@ -1472,12 +1447,11 @@ void GDALRegister_ERS()
 "   </Option>"
 "</CreationOptionList>" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = ERSDataset::Open;
-        poDriver->pfnIdentify = ERSDataset::Identify;
-        poDriver->pfnCreate = ERSDataset::Create;
+    poDriver->pfnOpen = ERSDataset::Open;
+    poDriver->pfnIdentify = ERSDataset::Identify;
+    poDriver->pfnCreate = ERSDataset::Create;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/ers/ershdrnode.cpp b/frmts/ers/ershdrnode.cpp
index 5aab4d1..09ab448 100644
--- a/frmts/ers/ershdrnode.cpp
+++ b/frmts/ers/ershdrnode.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ershdrnode.cpp 21814 2011-02-23 22:55:14Z warmerdam $
+ * $Id: ershdrnode.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  ERMapper .ers Driver
  * Purpose:  Implementation of ERSHdrNode class for parsing/accessing .ers hdr.
@@ -31,22 +31,20 @@
 #include "cpl_string.h"
 #include "ershdrnode.h"
 
-CPL_CVSID("$Id: ershdrnode.cpp 21814 2011-02-23 22:55:14Z warmerdam $");
+CPL_CVSID("$Id: ershdrnode.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 
 /************************************************************************/
 /*                             ERSHdrNode()                             */
 /************************************************************************/
 
-ERSHdrNode::ERSHdrNode()
-
-{
-    nItemMax = 0;
-    nItemCount = 0;
-    papszItemName = NULL;
-    papszItemValue = NULL;
-    papoItemChild = NULL;
-}
+ERSHdrNode::ERSHdrNode() :
+    nItemMax(0),
+    nItemCount(0),
+    papszItemName(NULL),
+    papszItemValue(NULL),
+    papoItemChild(NULL)
+{ }
 
 /************************************************************************/
 /*                            ~ERSHdrNode()                             */
@@ -55,9 +53,7 @@ ERSHdrNode::ERSHdrNode()
 ERSHdrNode::~ERSHdrNode()
 
 {
-    int i;
-
-    for( i = 0; i < nItemCount; i++ )
+    for( int i = 0; i < nItemCount; i++ )
     {
         if( papoItemChild[i] != NULL )
             delete papoItemChild[i];
@@ -84,11 +80,11 @@ void ERSHdrNode::MakeSpace()
     if( nItemCount == nItemMax )
     {
         nItemMax = (int) (nItemMax * 1.3) + 10;
-        papszItemName = (char **) 
+        papszItemName = (char **)
             CPLRealloc(papszItemName,sizeof(char *) * nItemMax);
-        papszItemValue = (char **) 
+        papszItemValue = (char **)
             CPLRealloc(papszItemValue,sizeof(char *) * nItemMax);
-        papoItemChild = (ERSHdrNode **) 
+        papoItemChild = (ERSHdrNode **)
             CPLRealloc(papoItemChild,sizeof(void *) * nItemMax);
     }
 }
@@ -110,18 +106,17 @@ int ERSHdrNode::ReadLine( VSILFILE * fp, CPLString &osLine )
     do
     {
         const char *pszNewLine = CPLReadLineL( fp );
-        
+
         if( pszNewLine == NULL )
             return FALSE;
 
         osLine += pszNewLine;
 
-        int  bInQuote = FALSE;
-        size_t  i;
+        bool bInQuote = false;
 
         nBracketLevel = 0;
 
-        for( i = 0; i < osLine.length(); i++ )
+        for( size_t i = 0; i < osLine.length(); i++ )
         {
             if( osLine[i] == '"' )
                 bInQuote = !bInQuote;
@@ -156,20 +151,21 @@ int ERSHdrNode::ReadLine( VSILFILE * fp, CPLString &osLine )
 int ERSHdrNode::ParseChildren( VSILFILE * fp )
 
 {
-    while( TRUE )
-    { 
-        size_t iOff;
-        CPLString osLine;
-
+    while( true )
+    {
 /* -------------------------------------------------------------------- */
 /*      Read the next line (or multi-line for bracketed value).         */
 /* -------------------------------------------------------------------- */
+        CPLString osLine;
+
         if( !ReadLine( fp, osLine ) )
             return FALSE;
 
 /* -------------------------------------------------------------------- */
 /*      Got a Name=Value.                                               */
 /* -------------------------------------------------------------------- */
+        size_t iOff;
+
         if( (iOff = osLine.find_first_of( '=' )) != std::string::npos )
         {
             CPLString osName = osLine.substr(0,iOff-1);
@@ -193,14 +189,14 @@ int ERSHdrNode::ParseChildren( VSILFILE * fp )
         {
             CPLString osName = osLine.substr(0,iOff);
             osName.Trim();
-            
+
             MakeSpace();
             papszItemName[nItemCount] = CPLStrdup(osName);
             papszItemValue[nItemCount] = NULL;
             papoItemChild[nItemCount] = new ERSHdrNode();
 
             nItemCount++;
-            
+
             if( !papoItemChild[nItemCount-1]->ParseChildren( fp ) )
                 return FALSE;
         }
@@ -219,8 +215,8 @@ int ERSHdrNode::ParseChildren( VSILFILE * fp )
 /* -------------------------------------------------------------------- */
         else if( osLine.Trim().length() > 0 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Unexpected line parsing .ecw:\n%s", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Unexpected line parsing .ecw:\n%s",
                       osLine.c_str() );
             return FALSE;
         }
@@ -237,27 +233,26 @@ int ERSHdrNode::WriteSelf( VSILFILE * fp, int nIndent )
 
 {
     CPLString oIndent;
-    int i;
 
     oIndent.assign( nIndent, '\t' );
 
-    for( i = 0; i < nItemCount; i++ )
+    for( int i = 0; i < nItemCount; i++ )
     {
         if( papszItemValue[i] != NULL )
         {
-            if( VSIFPrintfL( fp, "%s%s\t= %s\n", 
-                             oIndent.c_str(), 
-                             papszItemName[i], 
+            if( VSIFPrintfL( fp, "%s%s\t= %s\n",
+                             oIndent.c_str(),
+                             papszItemName[i],
                              papszItemValue[i] ) < 1 )
                 return FALSE;
         }
         else
         {
-            VSIFPrintfL( fp, "%s%s Begin\n", 
+            VSIFPrintfL( fp, "%s%s Begin\n",
                          oIndent.c_str(), papszItemName[i] );
             if( !papoItemChild[i]->WriteSelf( fp, nIndent+1 ) )
                 return FALSE;
-            if( VSIFPrintfL( fp, "%s%s End\n", 
+            if( VSIFPrintfL( fp, "%s%s End\n",
                              oIndent.c_str(), papszItemName[i] ) < 1 )
                 return FALSE;
         }
@@ -270,21 +265,19 @@ int ERSHdrNode::WriteSelf( VSILFILE * fp, int nIndent )
 /*                                Find()                                */
 /*                                                                      */
 /*      Find the desired entry value.  The input is a path with         */
-/*      components seperated by dots, relative to the current node.     */
+/*      components separated by dots, relative to the current node.     */
 /************************************************************************/
 
 const char *ERSHdrNode::Find( const char *pszPath, const char *pszDefault )
 
 {
-    int i;
-
 /* -------------------------------------------------------------------- */
 /*      If this is the final component of the path, search for a        */
 /*      matching child and return the value.                            */
 /* -------------------------------------------------------------------- */
     if( strchr(pszPath,'.') == NULL )
     {
-        for( i = 0; i < nItemCount; i++ )
+        for( int i = 0; i < nItemCount; i++ )
         {
             if( EQUAL(pszPath,papszItemName[i]) )
             {
@@ -292,9 +285,9 @@ const char *ERSHdrNode::Find( const char *pszPath, const char *pszDefault )
                 {
                     if( papszItemValue[i][0] == '"' )
                     {
-                        // strip off quotes. 
+                        // strip off quotes.
                         osTempReturn = papszItemValue[i];
-                        osTempReturn = 
+                        osTempReturn =
                             osTempReturn.substr( 1, osTempReturn.length()-2 );
                         return osTempReturn;
                     }
@@ -313,20 +306,19 @@ const char *ERSHdrNode::Find( const char *pszPath, const char *pszDefault )
 /*      and recurse.                                                    */
 /* -------------------------------------------------------------------- */
     CPLString osPathFirst, osPathRest, osPath = pszPath;
-    int iDot;
-    
-    iDot = osPath.find_first_of('.');
+
+    size_t iDot = osPath.find_first_of('.');
     osPathFirst = osPath.substr(0,iDot);
     osPathRest = osPath.substr(iDot+1);
 
-    for( i = 0; i < nItemCount; i++ )
+    for( int i = 0; i < nItemCount; i++ )
     {
         if( EQUAL(osPathFirst,papszItemName[i]) )
         {
             if( papoItemChild[i] != NULL )
                 return papoItemChild[i]->Find( osPathRest, pszDefault );
-            else
-                return pszDefault;
+
+            return pszDefault;
         }
     }
 
@@ -339,30 +331,30 @@ const char *ERSHdrNode::Find( const char *pszPath, const char *pszDefault )
 /*      Find a particular element from an array valued item.            */
 /************************************************************************/
 
-const char *ERSHdrNode::FindElem( const char *pszPath, int iElem, 
+const char *ERSHdrNode::FindElem( const char *pszPath, int iElem,
                                   const char *pszDefault )
 
 {
     const char *pszArray = Find( pszPath, NULL );
-    char **papszTokens;
-    int  bDefault = TRUE;
 
     if( pszArray == NULL )
         return pszDefault;
 
-    papszTokens = CSLTokenizeStringComplex( pszArray, "{ \t}", TRUE, FALSE );
+    bool bDefault = true;
+    char **papszTokens
+        = CSLTokenizeStringComplex( pszArray, "{ \t}", TRUE, FALSE );
     if( iElem >= 0 && iElem < CSLCount(papszTokens) )
     {
         osTempReturn = papszTokens[iElem];
-        bDefault = FALSE;
+        bDefault = false;
     }
-    
+
     CSLDestroy( papszTokens );
 
     if( bDefault )
         return pszDefault;
-    else
-        return osTempReturn;
+
+    return osTempReturn;
 }
 
 /************************************************************************/
@@ -374,12 +366,9 @@ const char *ERSHdrNode::FindElem( const char *pszPath, int iElem,
 ERSHdrNode *ERSHdrNode::FindNode( const char *pszPath )
 
 {
-    int i;
     CPLString osPathFirst, osPathRest, osPath = pszPath;
-    int iDot;
-    
-    iDot = osPath.find_first_of('.');
-    if( iDot == -1 )
+    size_t iDot = osPath.find_first_of('.');
+    if( iDot == std::string::npos )
     {
         osPathFirst = osPath;
     }
@@ -389,7 +378,7 @@ ERSHdrNode *ERSHdrNode::FindNode( const char *pszPath )
         osPathRest = osPath.substr(iDot+1);
     }
 
-    for( i = 0; i < nItemCount; i++ )
+    for( int i = 0; i < nItemCount; i++ )
     {
         if( EQUAL(osPathFirst,papszItemName[i]) )
         {
@@ -418,24 +407,22 @@ void ERSHdrNode::Set( const char *pszPath, const char *pszValue )
 
 {
     CPLString  osPath = pszPath;
-    int iDot;
-    
-    iDot = osPath.find_first_of('.');
+    size_t iDot = osPath.find_first_of('.');
 
 /* -------------------------------------------------------------------- */
 /*      We have an intermediate node, find or create it and             */
 /*      recurse.                                                        */
 /* -------------------------------------------------------------------- */
-    if( iDot != -1 )
+    if( iDot != std::string::npos )
     {
         CPLString osPathFirst = osPath.substr(0,iDot);
         CPLString osPathRest = osPath.substr(iDot+1);
         ERSHdrNode *poFirst = FindNode( osPathFirst );
-        
+
         if( poFirst == NULL )
         {
             poFirst = new ERSHdrNode();
-            
+
             MakeSpace();
             papszItemName[nItemCount] = CPLStrdup(osPathFirst);
             papszItemValue[nItemCount] = NULL;
@@ -450,11 +437,9 @@ void ERSHdrNode::Set( const char *pszPath, const char *pszValue )
 /* -------------------------------------------------------------------- */
 /*      This is the final item name.  Find or create it.                */
 /* -------------------------------------------------------------------- */
-    int i;
-
-    for( i = 0; i < nItemCount; i++ )
+    for( int i = 0; i < nItemCount; i++ )
     {
-        if( EQUAL(osPath,papszItemName[i]) 
+        if( EQUAL(osPath,papszItemName[i])
             && papszItemValue[i] != NULL )
         {
             CPLFree( papszItemValue[i] );
diff --git a/frmts/ers/ershdrnode.h b/frmts/ers/ershdrnode.h
index 1fbf371..8bd31f8 100644
--- a/frmts/ers/ershdrnode.h
+++ b/frmts/ers/ershdrnode.h
@@ -1,7 +1,7 @@
 
 class ERSHdrNode;
 
-class ERSHdrNode 
+class ERSHdrNode
 {
     CPLString osTempReturn;
 
@@ -21,7 +21,7 @@ public:
     int    WriteSelf( VSILFILE *fp, int nIndent );
 
     const char *Find( const char *pszPath, const char *pszDefault = NULL );
-    const char *FindElem( const char *pszPath, int iElem, 
+    const char *FindElem( const char *pszPath, int iElem,
                           const char *pszDefault = NULL );
     ERSHdrNode *FindNode( const char *pszPath );
 
diff --git a/frmts/ers/frmt_ers.html b/frmts/ers/frmt_ers.html
index 3100f6b..8e80479 100644
--- a/frmts/ers/frmt_ers.html
+++ b/frmts/ers/frmt_ers.html
@@ -8,8 +8,8 @@
 <h1>ERS -- ERMapper .ERS</h1>
 
 GDAL supports reading and writing raster files with .ers header files, with some
-limitations.  The .ers ascii format is used by ERMapper for labelling raw 
-data files, as well as for providing extended metadata, and georeferencing 
+limitations.  The .ers ascii format is used by ERMapper for labeling raw
+data files, as well as for providing extended metadata, and georeferencing
 for some other file formats.  The .ERS format, or variants are also used to
 hold descriptions of ERMapper algorithms, but these are not supported by GDAL.<p>
 
diff --git a/frmts/fit/fit.cpp b/frmts/fit/fit.cpp
index 9a0d561..c5ef483 100644
--- a/frmts/fit/fit.cpp
+++ b/frmts/fit/fit.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: fit.cpp 14048 2008-03-20 18:47:21Z rouault $
+ * $Id: fit.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  FIT Driver
  * Purpose:  Implement FIT Support - not using the SGI iflFIT library.
@@ -30,18 +30,18 @@
 #include <limits.h>
 #include "fit.h"
 
-CPL_CVSID("$Id: fit.cpp 14048 2008-03-20 18:47:21Z rouault $");
+CPL_CVSID("$Id: fit.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 GDALDataType fitDataType(int dtype) {
     switch (dtype) {
     case 1: // iflBit   /* single-bit */
-        fprintf(stderr, 
+        fprintf(stderr,
                 "GDAL unsupported data type (single-bit) in fitDataType\n");
         return GDT_Unknown;
     case 2: // iflUChar    /* unsigned character (byte) */
         return GDT_Byte;
     case 4: // iflChar     /* signed character (byte) */
-        fprintf(stderr, 
+        fprintf(stderr,
                 "GDAL unsupported data type (signed char) in fitDataType\n");
         return GDT_Unknown;
 //         return Byte;
@@ -61,7 +61,7 @@ GDALDataType fitDataType(int dtype) {
     case 256: // iflDouble /* double precision floating point */
         return GDT_Float64;
     default:
-        CPLError(CE_Failure, CPLE_NotSupported, 
+        CPLError(CE_Failure, CPLE_NotSupported,
                  "FIT - unknown data type %i in fitDataType", dtype);
         return GDT_Unknown;
     } // switch
@@ -84,7 +84,7 @@ int fitGetDataType(GDALDataType eDataType) {
     case GDT_Float64:
         return 256; // iflDouble - double precision floating point
     default:
-        CPLError(CE_Failure, CPLE_NotSupported, 
+        CPLError(CE_Failure, CPLE_NotSupported,
                  "FIT - unsupported GDALDataType %i in fitGetDataType",
                  eDataType);
         return 0;
@@ -100,7 +100,7 @@ int fitGetDataType(GDALDataType eDataType) {
 
 
 int fitGetColorModel(GDALColorInterp colorInterp, int nBands) {
-    // XXX - shoould check colorInterp for all bands, not just first one
+    // XXX - Should check colorInterp for all bands, not just first one.
 
     switch(colorInterp) {
     case GCI_GrayIndex:
@@ -114,7 +114,7 @@ int fitGetColorModel(GDALColorInterp colorInterp, int nBands) {
         } // switch
 
     case GCI_PaletteIndex:
-        CPLError(CE_Failure, CPLE_NotSupported, 
+        CPLError(CE_Failure, CPLE_NotSupported,
                  "FIT write - unsupported ColorInterp PaletteIndex\n");
         return 0;
 
@@ -161,14 +161,14 @@ int fitGetColorModel(GDALColorInterp colorInterp, int nBands) {
         default:
             UNSUPPORTED_COMBO();
         } // switch
-        
+
     case GCI_GreenBand:
     case GCI_SaturationBand:
     case GCI_LightnessBand:
     case GCI_MagentaBand:
     case GCI_YellowBand:
     case GCI_BlackBand:
-        CPLError(CE_Failure, CPLE_NotSupported, 
+        CPLError(CE_Failure, CPLE_NotSupported,
                  "FIT write - unsupported combination (band 1 = %s) "
                  "- ignoring color model",
                  GDALGetColorInterpretationName(colorInterp));
@@ -188,7 +188,7 @@ int fitGetColorModel(GDALColorInterp colorInterp, int nBands) {
             return 5; // iflRGBA - full color with transparency (alpha channel)
         } // switch
 
-        CPLError(CE_Failure, CPLE_NotSupported, 
+        CPLError(CE_Failure, CPLE_NotSupported,
                  "FIT write - unrecognized colorInterp %i and "
                  "unrecognized number of bands (%i)", colorInterp, nBands);
 
diff --git a/frmts/fit/fit.h b/frmts/fit/fit.h
index 1315784..1675c0c 100644
--- a/frmts/fit/fit.h
+++ b/frmts/fit/fit.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: fit.h 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: fit.h 31777 2015-11-26 14:14:41Z rouault $
  *
  * Project:  FIT Driver
  * Purpose:  Implement FIT Support - not using the SGI iflFIT library.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef __FIT_H__
-#define __FIT_H__
+#ifndef FIT_H_
+#define FIT_H_
 
 #include "gdal.h"
 
@@ -112,4 +112,4 @@ int fitGetColorModel(GDALColorInterp colorInterp, int nBands);
 }
 #endif
 
-#endif // __FIT_H__
+#endif // FIT_H_
diff --git a/frmts/fit/fitdataset.cpp b/frmts/fit/fitdataset.cpp
index 9d9f4b6..91d9564 100644
--- a/frmts/fit/fitdataset.cpp
+++ b/frmts/fit/fitdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: fitdataset.cpp 28785 2015-03-26 20:46:45Z goatbar $
+ * $Id: fitdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  FIT Driver
  * Purpose:  Implement FIT Support - not using the SGI iflFIT library.
@@ -28,17 +28,13 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_string.h"
 #include "fit.h"
-#include "gstEndian.h"
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
-#include "cpl_string.h"
-
-CPL_CVSID("$Id: fitdataset.cpp 28785 2015-03-26 20:46:45Z goatbar $");
+#include "gstEndian.h"
 
-CPL_C_START
- 
-void	GDALRegister_FIT(void);
-CPL_C_END
+CPL_CVSID("$Id: fitdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 #define FIT_WRITE
 
@@ -57,11 +53,11 @@ class FITRasterBand;
 class FITDataset : public GDALPamDataset
 {
     friend class FITRasterBand;
-    
+
     VSILFILE	*fp;
     FITinfo	*info;
     double      adfGeoTransform[6];
-    
+
   public:
     FITDataset();
     ~FITDataset();
@@ -71,8 +67,8 @@ class FITDataset : public GDALPamDataset
 
 #ifdef FIT_WRITE
 static GDALDataset *FITCreateCopy(const char * pszFilename,
-                                  GDALDataset *poSrcDS, 
-                                  int bStrict, char ** papszOptions, 
+                                  GDALDataset *poSrcDS,
+                                  int bStrict, char ** papszOptions,
                                   GDALProgressFunc pfnProgress,
                                   void * pProgressData );
 #endif // FIT_WRITE
@@ -86,7 +82,7 @@ static GDALDataset *FITCreateCopy(const char * pszFilename,
 class FITRasterBand : public GDALPamRasterBand
 {
     friend class FITDataset;
-    
+
     unsigned long recordSize; // number of bytes of a single page/block/record
     unsigned long numXBlocks; // number of pages in the X direction
     unsigned long numYBlocks; // number of pages in the Y direction
@@ -96,13 +92,13 @@ class FITRasterBand : public GDALPamRasterBand
 
 public:
 
-    FITRasterBand( FITDataset *, int );
+    FITRasterBand( FITDataset *, int nBandIn, int nBandsIn );
     ~FITRasterBand();
-    
+
     // should override RasterIO eventually.
-    
+
     virtual CPLErr IReadBlock( int, int, void * );
-//     virtual CPLErr WriteBlock( int, int, void * ); 
+//     virtual CPLErr WriteBlock( int, int, void * );
     virtual double GetMinimum( int *pbSuccess );
     virtual double GetMaximum( int *pbSuccess );
     virtual GDALColorInterp GetColorInterpretation();
@@ -113,39 +109,47 @@ public:
 /*                           FITRasterBand()                            */
 /************************************************************************/
 
-FITRasterBand::FITRasterBand( FITDataset *poDS, int nBand ) : tmpImage( NULL )
+FITRasterBand::FITRasterBand( FITDataset *poDSIn, int nBandIn, int nBandsIn ) :
+        recordSize(0),
+        numXBlocks(0),
+        numYBlocks(0),
+        bytesPerComponent(0),
+        bytesPerPixel(0),
+        tmpImage( NULL )
 
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
-    
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
+
 /* -------------------------------------------------------------------- */
 /*      Get the GDAL data type.                                         */
 /* -------------------------------------------------------------------- */
-    eDataType = fitDataType(poDS->info->dtype);
+    eDataType = fitDataType(poDSIn->info->dtype);
 
 /* -------------------------------------------------------------------- */
 /*      Get the page sizes.                                             */
 /* -------------------------------------------------------------------- */
-    nBlockXSize = poDS->info->xPageSize;
-    nBlockYSize = poDS->info->yPageSize;
+    nBlockXSize = poDSIn->info->xPageSize;
+    nBlockYSize = poDSIn->info->yPageSize;
 
 /* -------------------------------------------------------------------- */
 /*      Caculate the values for record offset calculations.             */
 /* -------------------------------------------------------------------- */
     bytesPerComponent = (GDALGetDataTypeSize(eDataType) / 8);
-    bytesPerPixel = poDS->nBands * bytesPerComponent;
+    if( bytesPerComponent == 0 )
+        return;
+    bytesPerPixel = nBandsIn * bytesPerComponent;
+    if( nBlockXSize <= 0 || nBlockYSize <= 0 ||
+        nBlockXSize > INT_MAX / (int)bytesPerPixel ||
+        nBlockYSize > INT_MAX / (nBlockXSize * (int)bytesPerPixel) )
+        return;
     recordSize = bytesPerPixel * nBlockXSize * nBlockYSize;
     numXBlocks =
-        (unsigned long) ceil((double) poDS->info->xSize / nBlockXSize);
+        (unsigned long) ceil((double) poDSIn->info->xSize / nBlockXSize);
     numYBlocks =
-        (unsigned long) ceil((double) poDS->info->ySize / nBlockYSize);
-
-    tmpImage = (char *) malloc(recordSize);
-    if (! tmpImage)
-        CPLError(CE_Fatal, CPLE_NotSupported, 
-                 "FITRasterBand couldn't allocate %lu bytes", recordSize);
+        (unsigned long) ceil((double) poDSIn->info->ySize / nBlockYSize);
 
+    tmpImage = (char *) VSI_MALLOC_VERBOSE(recordSize);
 /* -------------------------------------------------------------------- */
 /*      Set the access flag.  For now we set it the same as the         */
 /*      whole dataset, but eventually this should take account of       */
@@ -157,8 +161,7 @@ FITRasterBand::FITRasterBand( FITDataset *poDS, int nBand ) : tmpImage( NULL )
 
 FITRasterBand::~FITRasterBand()
 {
-    if ( tmpImage )
-        free ( tmpImage );
+    VSIFree ( tmpImage );
 }
 
 
@@ -170,10 +173,10 @@ FITRasterBand::~FITRasterBand()
                 t *dstp = (t *) pImage; \
                 t *srcp = (t *) tmpImage; \
                 srcp += nBand-1; \
-                long i = 0; \
+                long imacro = 0; \
                 for(long y=ystart; y != ystop; y+= yinc) \
-                    for(long x=xstart; x != xstop; x+= xinc, i++) { \
-                        dstp[i] = srcp[(y * nBlockXSize + x) * \
+                    for(long x=xstart; x != xstop; x+= xinc, imacro++) { \
+                        dstp[imacro] = srcp[(y * nBlockXSize + x) * \
                                        poFIT_DS->nBands]; \
                     } \
     }
@@ -183,10 +186,10 @@ FITRasterBand::~FITRasterBand()
                 t *dstp = (t *) pImage; \
                 t *srcp = (t *) tmpImage; \
                 srcp += nBand-1; \
-                long i = 0; \
-                for(long x=xstart; x != xstop; x+= xinc, i++) \
+                long imacro = 0; \
+                for(long x=xstart; x != xstop; x+= xinc, imacro++) \
                     for(long y=ystart; y != ystop; y+= yinc) { \
-                        dstp[i] = srcp[(x * nBlockYSize + y) * \
+                        dstp[imacro] = srcp[(x * nBlockYSize + y) * \
                                        poFIT_DS->nBands]; \
                     } \
     }
@@ -246,7 +249,7 @@ CPLErr FITRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         CPLError(CE_Failure, CPLE_NotSupported,
                  "FIT - unrecognized image space %i",
                  poFIT_DS->info->space);
-        tilenum = 0;
+        return CE_Failure;
     } // switch
 
     uint64 offset = poFIT_DS->info->dataOffset + recordSize * tilenum;
@@ -268,15 +271,21 @@ CPLErr FITRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     if ((poFIT_DS->nBands == 1) && (poFIT_DS->info->space == 1)) // upper left
         fastpath = TRUE;
 
+    size_t nRead;
     if (! fastpath) {
-        VSIFReadL( tmpImage, recordSize, 1, poFIT_DS->fp );
+        nRead = VSIFReadL( tmpImage, recordSize, 1, poFIT_DS->fp );
         // offset to correct component to swap
         p = (char *) tmpImage + nBand-1;
     }
     else {
-        VSIFReadL( pImage, recordSize, 1, poFIT_DS->fp );
+        nRead = VSIFReadL( pImage, recordSize, 1, poFIT_DS->fp );
         p = (char *) pImage;
     }
+    if( nRead != 1 )
+    {
+        CPLError(CE_Failure, CPLE_FileIO, "Cannot read record");
+        return CE_Failure;
+    }
 
 
 #ifdef swapping
@@ -299,7 +308,7 @@ CPLErr FITRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             gst_swap64(p + i);
         break;
     default:
-        CPLError(CE_Failure, CPLE_NotSupported, 
+        CPLError(CE_Failure, CPLE_NotSupported,
                  "FITRasterBand::IReadBlock unsupported bytesPerPixel %lu",
                  bytesPerComponent);
     } // switch
@@ -382,7 +391,7 @@ CPLErr FITRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                 COPY_XFIRST(uint64);
                 break;
             default:
-                CPLError(CE_Failure, CPLE_NotSupported, 
+                CPLError(CE_Failure, CPLE_NotSupported,
                          "FITRasterBand::IReadBlock unsupported "
                          "bytesPerComponent %lu", bytesPerComponent);
             } // switch
@@ -460,7 +469,7 @@ CPLErr FITRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                 COPY_YFIRST(uint64);
                 break;
             default:
-                CPLError(CE_Failure, CPLE_NotSupported, 
+                CPLError(CE_Failure, CPLE_NotSupported,
                          "FITRasterBand::IReadBlock unsupported "
                          "bytesPerComponent %lu", bytesPerComponent);
             } // switch
@@ -482,8 +491,6 @@ CPLErr FITRasterBand::ReadBlock( int nBlockXOff, int nBlockYOff,
 {
     FITDataset	*poFIT_DS = (FITDataset *) poDS;
 
-    
-
     return CE_None;
 }
 
@@ -497,8 +504,6 @@ CPLErr FITRasterBand::WriteBlock( int nBlockXOff, int nBlockYOff,
 {
     FITDataset	*poFIT_DS = (FITDataset *) poDS;
 
-    
-
     return CE_None;
 }
 #endif
@@ -518,12 +523,11 @@ double FITRasterBand::GetMinimum( int *pbSuccess )
         *pbSuccess = TRUE;
 
     if (poFIT_DS->info->version &&
-        EQUALN((const char *) &(poFIT_DS->info->version), "02", 2)) {
+        STARTS_WITH_CI((const char *) &(poFIT_DS->info->version), "02")) {
         return poFIT_DS->info->minValue;
     }
-    else {
-        return GDALRasterBand::GetMinimum( pbSuccess );
-    }
+
+    return GDALRasterBand::GetMinimum( pbSuccess );
 }
 
 /************************************************************************/
@@ -540,12 +544,11 @@ double FITRasterBand::GetMaximum( int *pbSuccess )
     if (pbSuccess)
         *pbSuccess = TRUE;
 
-    if (EQUALN((const char *) &poFIT_DS->info->version, "02", 2)) {
+    if (STARTS_WITH_CI((const char *) &poFIT_DS->info->version, "02")) {
         return poFIT_DS->info->maxValue;
     }
-    else {
-        return GDALRasterBand::GetMaximum( pbSuccess );
-    }
+
+    return GDALRasterBand::GetMaximum( pbSuccess );
 }
 
 /************************************************************************/
@@ -561,13 +564,13 @@ GDALColorInterp FITRasterBand::GetColorInterpretation()
 
     switch(poFIT_DS->info->cm) {
     case 1: // iflNegative - inverted luminance (min value is white)
-        CPLError( CE_Warning, CPLE_NotSupported, 
+        CPLError( CE_Warning, CPLE_NotSupported,
                   "FIT - color model Negative not supported - ignoring model");
             return GCI_Undefined;
 
     case 2: // iflLuminance - luminance
         if (poFIT_DS->nBands != 1) {
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                       "FIT - color model Luminance mismatch with %i bands",
                       poFIT_DS->nBands);
             return GCI_Undefined;
@@ -576,14 +579,14 @@ GDALColorInterp FITRasterBand::GetColorInterpretation()
         case 1:
             return GCI_GrayIndex;
         default:
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                       "FIT - color model Luminance unknown band %i", nBand);
             return GCI_Undefined;
         } // switch nBand
 
     case 3: // iflRGB - full color (Red, Green, Blue triplets)
         if (poFIT_DS->nBands != 3) {
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                       "FIT - color model RGB mismatch with %i bands",
                       poFIT_DS->nBands);
             return GCI_Undefined;
@@ -596,20 +599,20 @@ GDALColorInterp FITRasterBand::GetColorInterpretation()
         case 3:
             return GCI_BlueBand;
         default:
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                       "FIT - color model RGB unknown band %i", nBand);
             return GCI_Undefined;
         } // switch nBand
 
     case 4: // iflRGBPalette - color mapped values
-        CPLError( CE_Warning, CPLE_NotSupported, 
+        CPLError( CE_Warning, CPLE_NotSupported,
                   "FIT - color model  RGBPalette not supported - "
                   "ignoring model");
             return GCI_Undefined;
 
     case 5: // iflRGBA - full color with transparency (alpha channel)
         if (poFIT_DS->nBands != 4) {
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                       "FIT - color model RGBA mismatch with %i bands",
                       poFIT_DS->nBands);
             return GCI_Undefined;
@@ -624,14 +627,14 @@ GDALColorInterp FITRasterBand::GetColorInterpretation()
         case 4:
             return GCI_AlphaBand;
         default:
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                       "FIT - color model RGBA unknown band %i", nBand);
             return GCI_Undefined;
         } // switch nBand
 
     case 6: // iflHSV - Hue, Saturation, Value
         if (poFIT_DS->nBands != 3) {
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                       "FIT - color model HSV mismatch with %i bands",
                       poFIT_DS->nBands);
             return GCI_Undefined;
@@ -644,14 +647,14 @@ GDALColorInterp FITRasterBand::GetColorInterpretation()
         case 3:
             return GCI_LightnessBand;
         default:
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                       "FIT - color model HSV unknown band %i", nBand);
             return GCI_Undefined;
         } // switch nBand
 
     case 7: // iflCMY - Cyan, Magenta, Yellow
         if (poFIT_DS->nBands != 3) {
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                       "FIT - color model CMY mismatch with %i bands",
                       poFIT_DS->nBands);
             return GCI_Undefined;
@@ -664,14 +667,14 @@ GDALColorInterp FITRasterBand::GetColorInterpretation()
         case 3:
             return GCI_YellowBand;
         default:
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                       "FIT - color model CMY unknown band %i", nBand);
             return GCI_Undefined;
         } // switch nBand
 
     case 8: // iflCMYK - Cyan, Magenta, Yellow, Black
         if (poFIT_DS->nBands != 4) {
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                       "FIT - color model CMYK mismatch with %i bands",
                       poFIT_DS->nBands);
             return GCI_Undefined;
@@ -686,14 +689,14 @@ GDALColorInterp FITRasterBand::GetColorInterpretation()
         case 4:
             return GCI_BlackBand;
         default:
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                       "FIT - color model CMYK unknown band %i", nBand);
             return GCI_Undefined;
         } // switch nBand
 
     case 9: // iflBGR - full color (ordered Blue, Green, Red)
         if (poFIT_DS->nBands != 3) {
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                       "FIT - color model BGR mismatch with %i bands",
                       poFIT_DS->nBands);
             return GCI_Undefined;
@@ -706,14 +709,14 @@ GDALColorInterp FITRasterBand::GetColorInterpretation()
         case 3:
             return GCI_RedBand;
         default:
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                       "FIT - color model BGR unknown band %i", nBand);
             return GCI_Undefined;
         } // switch nBand
 
     case 10: // iflABGR - Alpha, Blue, Green, Red (SGI frame buffers)
         if (poFIT_DS->nBands != 4) {
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                       "FIT - color model ABGR mismatch with %i bands",
                       poFIT_DS->nBands);
             return GCI_Undefined;
@@ -728,7 +731,7 @@ GDALColorInterp FITRasterBand::GetColorInterpretation()
         case 4:
             return GCI_RedBand;
         default:
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                       "FIT - color model ABGR unknown band %i", nBand);
             return GCI_Undefined;
         } // switch nBand
@@ -738,13 +741,13 @@ GDALColorInterp FITRasterBand::GetColorInterpretation()
         return GCI_Undefined;
 
     case 12: // iflYCC PhotoCD color model (Luminance, Chrominance)
-        CPLError( CE_Warning, CPLE_NotSupported, 
+        CPLError( CE_Warning, CPLE_NotSupported,
                   "FIT - color model YCC not supported - ignoring model");
             return GCI_Undefined;
 
     case 13: // iflLuminanceAlpha - Luminance plus alpha
         if (poFIT_DS->nBands != 2) {
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                       "FIT - color model LuminanceAlpha mismatch with "
                       "%i bands",
                       poFIT_DS->nBands);
@@ -756,14 +759,14 @@ GDALColorInterp FITRasterBand::GetColorInterpretation()
         case 2:
             return GCI_AlphaBand;
         default:
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                       "FIT - color model LuminanceAlpha unknown band %i",
                       nBand);
             return GCI_Undefined;
         } // switch nBand
 
     default:
-        CPLError( CE_Warning, CPLE_NotSupported, 
+        CPLError( CE_Warning, CPLE_NotSupported,
                   "FIT - unrecognized color model %i - ignoring model",
                   poFIT_DS->info->cm);
         return GCI_Undefined;
@@ -776,7 +779,6 @@ GDALColorInterp FITRasterBand::GetColorInterpretation()
 
 FITDataset::FITDataset() : fp( NULL ), info( NULL )
 {
-
     adfGeoTransform[0] = 0.0; // x origin (top left corner)
     adfGeoTransform[1] = 1.0; // x pixel size
     adfGeoTransform[2] = 0.0;
@@ -796,10 +798,15 @@ FITDataset::~FITDataset()
     if (info)
         delete(info);
     if(fp)
-        VSIFCloseL(fp);
+    {
+        if( VSIFCloseL(fp) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        }
+    }
 }
 
-// simple guard object to delete memory 
+// simple guard object to delete memory
 // when the guard goes out of scope
 template< class T >
 class DeleteGuard
@@ -814,18 +821,18 @@ public:
     T *take()
     {
         T *tmp = _ptr;
-	    _ptr = 0;
+	    _ptr = NULL;
 	    return tmp;
     }
 
 private:
     T *_ptr;
 	// prevent default copy constructor and assignment operator
-    DeleteGuard( const DeleteGuard & );  
+    DeleteGuard( const DeleteGuard & );
     DeleteGuard &operator=( const DeleteGuard & );
 };
 
-// simple guard object to free memory 
+// simple guard object to free memory
 // when the guard goes out of scope
 template< class T >
 class FreeGuard
@@ -841,14 +848,14 @@ public:
     T *take()
     {
         T *tmp = _ptr;
-	    _ptr = 0;
+	    _ptr = NULL;
 	    return tmp;
     }
 
 private:
     T *_ptr;
 	// prevent default copy constructor and assignment operator
-    FreeGuard( const FreeGuard & );  
+    FreeGuard( const FreeGuard & );
     FreeGuard &operator=( const FreeGuard & );
 };
 
@@ -860,20 +867,20 @@ GDALDataset *FITDataset::Open( GDALOpenInfo * poOpenInfo )
 {
 /* -------------------------------------------------------------------- */
 /*	First we check to see if the file has the expected header	*/
-/*	bytes.								*/    
+/*	bytes.								*/
 /* -------------------------------------------------------------------- */
 
     if( poOpenInfo->nHeaderBytes < 5 )
         return NULL;
 
 
-    if( !EQUALN((const char *) poOpenInfo->pabyHeader, "IT01", 4) &&
-        !EQUALN((const char *) poOpenInfo->pabyHeader, "IT02", 4) )
+    if( !STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "IT01") &&
+        !STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "IT02") )
         return NULL;
 
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The FIT driver does not support update access to existing"
                   " files.\n" );
         return NULL;
@@ -882,9 +889,7 @@ GDALDataset *FITDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    FITDataset 	*poDS;
-
-    poDS = new FITDataset();
+    FITDataset 	*poDS = new FITDataset();
     DeleteGuard<FITDataset> guard( poDS );
 
 	// re-open file for large file (64bit) access
@@ -911,7 +916,7 @@ GDALDataset *FITDataset::Open( GDALOpenInfo * poOpenInfo )
     FIThead02 *head = (FIThead02 *) poOpenInfo->pabyHeader;
 
     // extract the image attributes from the file header
-    if (EQUALN((const char *) &head->version, "02", 2)) {
+    if (STARTS_WITH_CI((const char *) &head->version, "02")) {
         // incomplete header
         if( poOpenInfo->nHeaderBytes < (signed) sizeof(FIThead02) )
             return NULL;
@@ -927,7 +932,7 @@ GDALDataset *FITDataset::Open( GDALOpenInfo * poOpenInfo )
 
         info->userOffset = sizeof(FIThead02);
     }
-    else if (EQUALN((const char *) &head->version, "01", 2)) {
+    else if (STARTS_WITH_CI((const char *) &head->version, "01")) {
         // incomplete header
         if( poOpenInfo->nHeaderBytes < (signed) sizeof(FIThead01) )
             return NULL;
@@ -943,7 +948,7 @@ GDALDataset *FITDataset::Open( GDALOpenInfo * poOpenInfo )
     }
     else {
         // unrecognized header version
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "FIT - unsupported header version %.2s\n",
                   (const char*) &head->version);
         return NULL;
@@ -981,7 +986,7 @@ GDALDataset *FITDataset::Open( GDALOpenInfo * poOpenInfo )
     info->cPageSize = head->cPageSize;
 
     CPLDebug("FIT", "size %i %i %i %i, pageSize %i %i %i %i",
-             info->xSize, info->ySize, info->zSize, info->cSize, 
+             info->xSize, info->ySize, info->zSize, info->cSize,
              info->xPageSize, info->yPageSize, info->zPageSize,
              info->cPageSize);
 
@@ -992,7 +997,12 @@ GDALDataset *FITDataset::Open( GDALOpenInfo * poOpenInfo )
 
     poDS->nRasterXSize = head->xSize;
     poDS->nRasterYSize = head->ySize;
-    poDS->nBands = head->cSize;
+
+    if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) ||
+        !GDALCheckBandCount(head->cSize, FALSE))
+    {
+        return NULL;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Check if 64 bit seek is needed.                                 */
@@ -1015,7 +1025,7 @@ GDALDataset *FITDataset::Open( GDALOpenInfo * poOpenInfo )
 #ifdef VSI_LARGE_API_SUPPORTED
         CPLDebug("FIT", "Using 64 bit version of fseek");
 #else
-        CPLError(CE_Fatal, CPLE_NotSupported, 
+        CPLError(CE_Fatal, CPLE_NotSupported,
                  "FIT - need 64 bit version of fseek");
 #endif
 
@@ -1025,28 +1035,28 @@ GDALDataset *FITDataset::Open( GDALOpenInfo * poOpenInfo )
 
     if( info->zSize != 1 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "FIT driver - unsupported zSize %i\n", info->zSize);
         return NULL;
     }
 
     if( info->order != 1 ) // interleaved - RGBRGB
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "FIT driver - unsupported order %i\n", info->order);
         return NULL;
     }
 
     if( info->zPageSize != 1 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "FIT driver - unsupported zPageSize %i\n", info->zPageSize);
         return NULL;
     }
 
     if( info->cPageSize != info->cSize )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "FIT driver - unsupported cPageSize %i (!= %i)\n",
                   info->cPageSize, info->cSize);
         return NULL;
@@ -1055,9 +1065,12 @@ GDALDataset *FITDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    for( int i = 0; i < poDS->nBands; i++ )
+    for( int i = 0; i < (int)head->cSize; i++ )
     {
-        poDS->SetBand( i+1,  new FITRasterBand( poDS, i+1 ) ) ;
+        FITRasterBand* poBand = new FITRasterBand( poDS, i+1, (int)head->cSize );
+        poDS->SetBand( i+1,  poBand);
+        if( poBand->tmpImage == NULL )
+            return NULL;
     }
 
 /* -------------------------------------------------------------------- */
@@ -1080,8 +1093,8 @@ GDALDataset *FITDataset::Open( GDALOpenInfo * poOpenInfo )
 
 #ifdef FIT_WRITE
 static GDALDataset *FITCreateCopy(const char * pszFilename,
-                                  GDALDataset *poSrcDS, 
-                                  int bStrict, char ** papszOptions, 
+                                  GDALDataset *poSrcDS,
+                                  int bStrict, char ** papszOptions,
                                   GDALProgressFunc pfnProgress,
                                   void * pProgressData )
 {
@@ -1090,7 +1103,7 @@ static GDALDataset *FITCreateCopy(const char * pszFilename,
     int nBands = poSrcDS->GetRasterCount();
     if (nBands == 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "FIT driver does not support source dataset with zero band.\n");
         return NULL;
     }
@@ -1098,19 +1111,17 @@ static GDALDataset *FITCreateCopy(const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Create the dataset.                                             */
 /* -------------------------------------------------------------------- */
-    VSILFILE	*fpImage;
-
     if( !pfnProgress( 0.0, NULL, pProgressData ) )
     {
         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
         return NULL;
     }
 
-    fpImage = VSIFOpenL( pszFilename, "wb" );
+    VSILFILE *fpImage = VSIFOpenL( pszFilename, "wb" );
     if( fpImage == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "FIT - unable to create file %s.\n", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "FIT - unable to create file %s.\n",
                   pszFilename );
         return NULL;
     }
@@ -1126,8 +1137,8 @@ static GDALDataset *FITCreateCopy(const char * pszFilename,
     // clean header so padding (past real header) is all zeros
     memset( head, 0, size );
 
-    strncpy((char *) &head->magic, "IT", 2);
-    strncpy((char *) &head->version, "02", 2);
+    memcpy((char *) &head->magic, "IT", 2);
+    memcpy((char *) &head->version, "02", 2);
 
     head->xSize = poSrcDS->GetRasterXSize();
     gst_swapb(head->xSize);
@@ -1141,13 +1152,13 @@ static GDALDataset *FITCreateCopy(const char * pszFilename,
 
     GDALRasterBand *firstBand = poSrcDS->GetRasterBand(1);
     if (! firstBand) {
-        VSIFCloseL(fpImage);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpImage));
         return NULL;
     }
 
     head->dtype = fitGetDataType(firstBand->GetRasterDataType());
     if (! head->dtype) {
-        VSIFCloseL(fpImage);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpImage));
         return NULL;
     }
     gst_swapb(head->dtype);
@@ -1174,7 +1185,7 @@ static GDALDataset *FITCreateCopy(const char * pszFilename,
             blockY = newBlockY;
         }
         else {
-            CPLError(CE_Failure, CPLE_OpenFailed, 
+            CPLError(CE_Failure, CPLE_OpenFailed,
                      "FIT - Unable to parse option PAGESIZE values [%s]", str);
         }
     }
@@ -1186,7 +1197,7 @@ static GDALDataset *FITCreateCopy(const char * pszFilename,
     // * handle block size bigger than image size
     // * undesirable block size (non power of 2, others?)
     // * mismatched block sizes for different bands
-    // * image that isn't even pages (ie. partially empty pages at edge)
+    // * image that isn't even pages (i.e. partially empty pages at edge)
     CPLDebug("FIT write", "using block size %ix%i", blockX, blockY);
 
     head->xPageSize = blockX;
@@ -1207,7 +1218,7 @@ static GDALDataset *FITCreateCopy(const char * pszFilename,
     head->dataOffset = size;
     gst_swapb(head->dataOffset);
 
-    VSIFWriteL(head, size, 1, fpImage);
+    CPL_IGNORE_RET_VAL(VSIFWriteL(head, size, 1, fpImage));
 
 /* -------------------------------------------------------------------- */
 /*      Loop over image, copying image data.                            */
@@ -1219,7 +1230,7 @@ static GDALDataset *FITCreateCopy(const char * pszFilename,
     unsigned long pageBytes = blockX * blockY * bytesPerPixel;
     char *output = (char *) malloc(pageBytes);
     if (! output)
-        CPLError(CE_Fatal, CPLE_NotSupported, 
+        CPLError(CE_Fatal, CPLE_NotSupported,
                  "FITRasterBand couldn't allocate %lu bytes", pageBytes);
     FreeGuard<char> guardOutput( output );
 
@@ -1255,10 +1266,10 @@ static GDALDataset *FITCreateCopy(const char * pszFilename,
                 GDALRasterBand * poBand = poSrcDS->GetRasterBand( iBand+1 );
                 CPLErr eErr =
                     poBand->RasterIO( GF_Read, // eRWFlag
-                                      x * blockX, // nXOff
-                                      y * blockY, // nYOff
-                                      readX, // nXSize
-                                      readY, // nYSize
+                                      static_cast<int>(x * blockX), // nXOff
+                                      static_cast<int>(y * blockY), // nYOff
+                                      static_cast<int>(readX), // nXSize
+                                      static_cast<int>(readY), // nYSize
                                       output + iBand * bytesPerComponent,
                                       // pData
                                       blockX, // nBufXSize
@@ -1268,7 +1279,7 @@ static GDALDataset *FITCreateCopy(const char * pszFilename,
                                       bytesPerPixel, // nPixelSpace
                                       bytesPerPixel * blockX, NULL); // nLineSpace
                 if (eErr != CE_None)
-                    CPLError(CE_Failure, CPLE_FileIO, 
+                    CPLError(CE_Failure, CPLE_FileIO,
                              "FIT write - CreateCopy got read error %i", eErr);
             } // for iBand
 
@@ -1292,13 +1303,13 @@ static GDALDataset *FITCreateCopy(const char * pszFilename,
                     gst_swap64(p + i);
                 break;
             default:
-                CPLError(CE_Failure, CPLE_NotSupported, 
+                CPLError(CE_Failure, CPLE_NotSupported,
                          "FIT write - unsupported bytesPerPixel %lu",
                          bytesPerComponent);
             } // switch
 #endif // swapping
-            
-            VSIFWriteL(output, pageBytes, 1, fpImage);
+
+            CPL_IGNORE_RET_VAL(VSIFWriteL(output, pageBytes, 1, fpImage));
 
             double perc = ((double) (y * maxx + x)) / (maxx * maxy);
 //             printf("progress %f\n", perc);
@@ -1306,7 +1317,7 @@ static GDALDataset *FITCreateCopy(const char * pszFilename,
             {
                 CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
                 //free(output);
-                VSIFCloseL( fpImage );
+                CPL_IGNORE_RET_VAL(VSIFCloseL( fpImage ));
                 VSIUnlink( pszFilename );
                 return NULL;
             }
@@ -1314,7 +1325,7 @@ static GDALDataset *FITCreateCopy(const char * pszFilename,
 
     //free(output);
 
-    VSIFCloseL( fpImage );
+    CPL_IGNORE_RET_VAL(VSIFCloseL( fpImage ));
 
     pfnProgress( 1.0, NULL, pProgressData );
 
@@ -1349,28 +1360,25 @@ static GDALDataset *FITCreateCopy(const char * pszFilename,
 void GDALRegister_FIT()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "FIT" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "FIT" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "FIT" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "FIT Image" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = FITDataset::Open;
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "FIT" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "FIT Image" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = FITDataset::Open;
 #ifdef FIT_WRITE
-        poDriver->pfnCreateCopy = FITCreateCopy;
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte UInt16 Int16 UInt32 Int32 Float32 Float64" );
+    poDriver->pfnCreateCopy = FITCreateCopy;
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte UInt16 Int16 UInt32 Int32 "
+                               "Float32 Float64" );
 #endif // FIT_WRITE
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/fit/gstEndian.h b/frmts/fit/gstEndian.h
index a91763c..866666f 100644
--- a/frmts/fit/gstEndian.h
+++ b/frmts/fit/gstEndian.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gstEndian.h 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: gstEndian.h 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  FIT Driver
  * Purpose:  Implement FIT Support - not using the SGI iflFIT library.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _gstEndian_h_
-#define _gstEndian_h_
+#ifndef gstEndian_h_
+#define gstEndian_h_
 
 // endian swapping tools
 
@@ -78,7 +78,7 @@ static inline void gst_swap32(void * value)
 
 static inline void gst_swap16(void * value)
 {
-    *(uint16 *)(value) = 
+    *(uint16 *)(value) =
 		   ( ((*(uint16 *)(value) & 0x00ff) << 8) |
              ((*(uint16 *)(value) >> 8) & 0x00ff) );
 }
@@ -114,9 +114,9 @@ static inline void gst_swapbytes(void * value, int size)
 #define swapped_fwrite(ptr, size, nitems, stream) \
 	fwrite(ptr, size, nitems, stream)
 
-#define gst_swap64( vlaue )
-#define gst_swap32( vlaue )
-#define gst_swap16( vlaue )
+#define gst_swap64( value )
+#define gst_swap32( value )
+#define gst_swap16( value )
 #define gst_swapbytes( value, size )
 #define gst_swapb( value )
 
@@ -124,4 +124,4 @@ static inline void gst_swapbytes(void * value, int size)
 
 } // gstEndian namespace
 
-#endif // ! _gstEndian_h_
+#endif // ! gstEndian_h_
diff --git a/frmts/fit/gstTypes.h b/frmts/fit/gstTypes.h
index bd34a73..ec1bfb2 100644
--- a/frmts/fit/gstTypes.h
+++ b/frmts/fit/gstTypes.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gstTypes.h 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: gstTypes.h 31777 2015-11-26 14:14:41Z rouault $
  *
  * Project:  FIT Driver
  * Purpose:  Implement FIT Support - not using the SGI iflFIT library.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _gstTypes_h_
-#define _gstTypes_h_
+#ifndef gstTypes_h_
+#define gstTypes_h_
 
 #include <stdarg.h>
 #include "cpl_conv.h"
@@ -44,4 +44,4 @@ typedef GIntBig				int64;
 
 typedef unsigned char                   uchar;
 
-#endif // !_gstTypes_h_
+#endif // !gstTypes_h_
diff --git a/frmts/fits/fitsdataset.cpp b/frmts/fits/fitsdataset.cpp
index 124e519..35857b1 100644
--- a/frmts/fits/fitsdataset.cpp
+++ b/frmts/fits/fitsdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: fitsdataset.cpp 28831 2015-04-01 16:46:05Z rouault $
+ * $Id: fitsdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  FITS Driver
  * Purpose:  Implement FITS raster read/write support
@@ -30,16 +30,13 @@
 
 
 
-#include "gdal_pam.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
 #include <string.h>
-
-CPL_CVSID("$Id: fitsdataset.cpp 28831 2015-04-01 16:46:05Z rouault $");
-
-CPL_C_START
 #include <fitsio.h>
-void	GDALRegister_FITS(void);
-CPL_C_END
+
+CPL_CVSID("$Id: fitsdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -52,7 +49,7 @@ class FITSRasterBand;
 class FITSDataset : public GDALPamDataset {
 
   friend class FITSRasterBand;
-  
+
   fitsfile* hFITS;
 
   GDALDataType gdalDataType;   // GDAL code for the image type
@@ -61,7 +58,7 @@ class FITSDataset : public GDALPamDataset {
   bool isExistingFile;
   long highestOffsetWritten;  // How much of image has been written
 
-  FITSDataset();     // Others shouldn't call this constructor explicitly
+  FITSDataset();     // Others should not call this constructor explicitly
 
   CPLErr Init(fitsfile* hFITS_, bool isExistingFile_);
 
@@ -73,7 +70,7 @@ public:
 			     int nXSize, int nYSize, int nBands,
 			     GDALDataType eType,
 			     char** papszParmList);
-  
+
 };
 
 /************************************************************************/
@@ -85,14 +82,14 @@ public:
 class FITSRasterBand : public GDALPamRasterBand {
 
   friend class	FITSDataset;
-  
+
 public:
 
   FITSRasterBand(FITSDataset*, int);
   ~FITSRasterBand();
 
   virtual CPLErr IReadBlock( int, int, void * );
-  virtual CPLErr IWriteBlock( int, int, void * ); 
+  virtual CPLErr IWriteBlock( int, int, void * );
 };
 
 
@@ -100,12 +97,12 @@ public:
 /*                          FITSRasterBand()                           */
 /************************************************************************/
 
-FITSRasterBand::FITSRasterBand(FITSDataset *poDS, int nBand) {
+FITSRasterBand::FITSRasterBand(FITSDataset *poDSIn, int nBandIn) {
 
-  this->poDS = poDS;
-  this->nBand = nBand;
-  eDataType = poDS->gdalDataType;
-  nBlockXSize = poDS->nRasterXSize;;
+  this->poDS = poDSIn;
+  this->nBand = nBandIn;
+  eDataType = poDSIn->gdalDataType;
+  nBlockXSize = poDSIn->nRasterXSize;;
   nBlockYSize = 1;
 }
 
@@ -150,13 +147,13 @@ CPLErr FITSRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff, int nBlockYOff,
 
   // Otherwise read in the image data
   fits_read_img(hFITS, dataset->fitsDataType, offset, nElements,
-		0, pImage, 0, &status);
+		NULL, pImage, NULL, &status);
   if (status) {
     CPLError(CE_Failure, CPLE_AppDefined,
 	     "Couldn't read image data from FITS file (%d).", status);
     return CE_Failure;
   }
-  
+
   return CE_None;
 }
 
@@ -215,7 +212,7 @@ CPLErr FITSRasterBand::IWriteBlock(CPL_UNUSED int nBlockXOff, int nBlockYOff,
 // Simple static function to determine if FITS header keyword should
 // be saved in meta data.
 static const int ignorableHeaderCount = 15;
-static const char* ignorableFITSHeaders[ignorableHeaderCount] = {
+static const char* const ignorableFITSHeaders[ignorableHeaderCount] = {
   "SIMPLE", "BITPIX", "NAXIS", "NAXIS1", "NAXIS2", "NAXIS3", "END",
   "XTENSION", "PCOUNT", "GCOUNT", "EXTEND", "CONTINUE",
   "COMMENT", "", "LONGSTRN"
@@ -234,7 +231,7 @@ static bool isIgnorableFITSHeader(const char* name) {
 /************************************************************************/
 
 FITSDataset::FITSDataset() {
-  hFITS = 0;
+  hFITS = NULL;
 }
 
 /************************************************************************/
@@ -248,11 +245,11 @@ FITSDataset::~FITSDataset() {
     if(eAccess == GA_Update) {   // Only do this if we've successfully opened the file and  update capability
       // Write any meta data to the file that's compatible with FITS
       status = 0;
-      fits_movabs_hdu(hFITS, 1, 0, &status);
+      fits_movabs_hdu(hFITS, 1, NULL, &status);
       fits_write_key_longwarn(hFITS, &status);
       if (status) {
         CPLError(CE_Warning, CPLE_AppDefined,
-	         "Couldn't move to first HDU in FITS file %s (%d).\n", 
+	         "Couldn't move to first HDU in FITS file %s (%d).\n",
 	         GetDescription(), status);
       }
       char** metaData = GetMetadata();
@@ -282,13 +279,13 @@ FITSDataset::~FITSDataset() {
 	    // handle. Note: to avoid a compiler warning we copy the
 	    // const value string to a non const one...
             char* valueCpy = CPLStrdup(value);
-	    fits_update_key_longstr(hFITS, key, valueCpy, 0, &status);
+	    fits_update_key_longstr(hFITS, key, valueCpy, NULL, &status);
 	    CPLFree(valueCpy);
 
 	    // Check for errors
 	    if (status) {
 	      CPLError(CE_Warning, CPLE_AppDefined,
-		       "Couldn't update key %s in FITS file %s (%d).", 
+		       "Couldn't update key %s in FITS file %s (%d).",
 		       key, GetDescription(), status);
 	      return;
 	    }
@@ -322,10 +319,10 @@ CPLErr FITSDataset::Init(fitsfile* hFITS_, bool isExistingFile_) {
   int status = 0;
 
   // Move to the primary HDU
-  fits_movabs_hdu(hFITS, 1, 0, &status);
+  fits_movabs_hdu(hFITS, 1, NULL, &status);
   if (status) {
     CPLError(CE_Failure, CPLE_AppDefined,
-	     "Couldn't move to first HDU in FITS file %s (%d).\n", 
+	     "Couldn't move to first HDU in FITS file %s (%d).\n",
 	     GetDescription(), status);
     return CE_Failure;
   }
@@ -345,7 +342,7 @@ CPLErr FITSDataset::Init(fitsfile* hFITS_, bool isExistingFile_) {
   fits_get_img_param(hFITS, maxdim, &bitpix, &naxis, naxes, &status);
   if (status) {
     CPLError(CE_Failure, CPLE_AppDefined,
-	     "Couldn't determine image parameters of FITS file %s (%d).", 
+	     "Couldn't determine image parameters of FITS file %s (%d).",
 	     GetDescription(), status);
     return CE_Failure;
   }
@@ -373,29 +370,29 @@ CPLErr FITSDataset::Init(fitsfile* hFITS_, bool isExistingFile_) {
   }
   else {
     CPLError(CE_Failure, CPLE_AppDefined,
-	     "FITS file %s has unknown data type: %d.", GetDescription(), 
+	     "FITS file %s has unknown data type: %d.", GetDescription(),
 	     bitpix);
     return CE_Failure;
   }
 
   // Determine image dimensions - we assume BSQ ordering
   if (naxis == 2) {
-    nRasterXSize = naxes[0];
-    nRasterYSize = naxes[1];
+    nRasterXSize = static_cast<int>(naxes[0]);
+    nRasterYSize = static_cast<int>(naxes[1]);
     nBands = 1;
   }
   else if (naxis == 3) {
-    nRasterXSize = naxes[0];
-    nRasterYSize = naxes[1];
-    nBands = naxes[2];
+    nRasterXSize = static_cast<int>(naxes[0]);
+    nRasterYSize = static_cast<int>(naxes[1]);
+    nBands = static_cast<int>(naxes[2]);
   }
   else {
     CPLError(CE_Failure, CPLE_AppDefined,
-	     "FITS file %s does not have 2 or 3 dimensions.", 
+	     "FITS file %s does not have 2 or 3 dimensions.",
 	     GetDescription());
     return CE_Failure;
   }
-  
+
   // Create the bands
   for (int i = 0; i < nBands; ++i)
     SetBand(i+1, new FITSRasterBand(this, i+1));
@@ -412,18 +409,18 @@ CPLErr FITSDataset::Init(fitsfile* hFITS_, bool isExistingFile_) {
   fits_get_hdrspace(hFITS, &nKeys, &nMoreKeys, &status);
   for(keyNum = 1; keyNum <= nKeys; keyNum++)
   {
-    fits_read_keyn(hFITS, keyNum, key, value, 0, &status);
+    fits_read_keyn(hFITS, keyNum, key, value, NULL, &status);
     if (status) {
       CPLError(CE_Failure, CPLE_AppDefined,
-	       "Error while reading key %d from FITS file %s (%d)", 
+	       "Error while reading key %d from FITS file %s (%d)",
 	       keyNum, GetDescription(), status);
       return CE_Failure;
     }
     if (strcmp(key, "END") == 0) {
-        /* we shouldn't get here in principle since the END */
-        /* keyword shouldn't be counted in nKeys, but who knows... */
+        // We should not get here in principle since the END
+        // keyword shouldn't be counted in nKeys, but who knows.
         break;
-    } 
+    }
     else if (isIgnorableFITSHeader(key)) {
       // Ignore it!
     }
@@ -437,9 +434,9 @@ CPLErr FITSDataset::Init(fitsfile* hFITS_, bool isExistingFile_) {
       // Check for long string
       if (strrchr(newValue, '&') == newValue + strlen(newValue) - 1) {
 	// Value string ends in "&", so use long string conventions
-	char* longString = 0;
-	fits_read_key_longstr(hFITS, key, &longString, 0, &status);
-	// Note that read_key_longst already strips quotes
+	char* longString = NULL;
+	fits_read_key_longstr(hFITS, key, &longString, NULL, &status);
+        // Note that read_key_longstr already strips quotes
 	if (status) {
 	  CPLError(CE_Failure, CPLE_AppDefined,
 		   "Error while reading long string for key %s from "
@@ -454,7 +451,7 @@ CPLErr FITSDataset::Init(fitsfile* hFITS_, bool isExistingFile_) {
       }
     }
   }
-  
+
   return CE_None;
 }
 
@@ -473,17 +470,17 @@ GDALDataset* FITSDataset::Open(GDALOpenInfo* poOpenInfo) {
     return NULL;
   if (memcmp(poOpenInfo->pabyHeader, fitsID, fitsIDLen))
     return NULL;
-  
+
   // Get access mode and attempt to open the file
   int status = 0;
-  fitsfile* hFITS = 0;
-  if (poOpenInfo->eAccess == GA_ReadOnly) 
+  fitsfile* hFITS = NULL;
+  if (poOpenInfo->eAccess == GA_ReadOnly)
     fits_open_file(&hFITS, poOpenInfo->pszFilename, READONLY, &status);
   else
     fits_open_file(&hFITS, poOpenInfo->pszFilename, READWRITE, &status);
   if (status) {
     CPLError(CE_Failure, CPLE_AppDefined,
-	     "Error while opening FITS file %s (%d).\n", 
+	     "Error while opening FITS file %s (%d).\n",
 	     poOpenInfo->pszFilename, status);
     fits_close_file(hFITS, &status);
     return NULL;
@@ -538,7 +535,7 @@ GDALDataset *FITSDataset::Create(const char* pszFilename,
 
   // Create the file - to force creation, we prepend the name with '!'
   char* extFilename = new char[strlen(pszFilename) + 10];  // 10 for margin!
-  sprintf(extFilename, "!%s", pszFilename);
+  snprintf(extFilename, strlen(pszFilename) + 10, "!%s", pszFilename);
   fits_create_file(&hFITS, extFilename, &status);
   delete[] extFilename;
   if (status) {
@@ -574,7 +571,7 @@ GDALDataset *FITSDataset::Create(const char* pszFilename,
   // Check the status
   if (status) {
     CPLError(CE_Failure, CPLE_AppDefined,
-	     "Couldn't create image within FITS file %s (%d).", 
+	     "Couldn't create image within FITS file %s (%d).",
 	     pszFilename, status);
     fits_close_file(hFITS, &status);
     return NULL;
@@ -587,7 +584,7 @@ GDALDataset *FITSDataset::Create(const char* pszFilename,
   dataset->SetDescription(pszFilename);
 
   // Init recalculates a lot of stuff we already know, but...
-  if (dataset->Init(hFITS, false) != CE_None) { 
+  if (dataset->Init(hFITS, false) != CE_None) {
     delete dataset;
     return NULL;
   }
@@ -598,29 +595,29 @@ GDALDataset *FITSDataset::Create(const char* pszFilename,
 
 
 /************************************************************************/
-/*                          GDALRegister_FITS()                        */
+/*                          GDALRegister_FITS()                         */
 /************************************************************************/
 
-void GDALRegister_FITS() {
-
-    GDALDriver* poDriver;
-
-    if( GDALGetDriverByName( "FITS" ) == NULL) {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "FITS" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Flexible Image Transport System" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#FITS" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte Int16 Int32 Float32 Float64" );
-        
-        poDriver->pfnOpen = FITSDataset::Open;
-        poDriver->pfnCreate = FITSDataset::Create;
-        poDriver->pfnCreateCopy = NULL;
-
-        GetGDALDriverManager()->RegisterDriver(poDriver);
-    }
+void GDALRegister_FITS()
+
+{
+    if( GDALGetDriverByName( "FITS" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "FITS" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Flexible Image Transport System" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_various.html#FITS" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte Int16 Int32 Float32 Float64" );
+
+    poDriver->pfnOpen = FITSDataset::Open;
+    poDriver->pfnCreate = FITSDataset::Create;
+    poDriver->pfnCreateCopy = NULL;
+
+    GetGDALDriverManager()->RegisterDriver(poDriver);
 }
diff --git a/frmts/formats_list.html b/frmts/formats_list.html
index ac88c98..cff415c 100644
--- a/frmts/formats_list.html
+++ b/frmts/formats_list.html
@@ -115,6 +115,14 @@
 </td><td> Yes
 </td></tr>
 
+<tr><td> <a href="frmt_cals.html">CALS Type I</a>
+</td><td> CALS
+</td><td> Yes
+</td><td> No
+</td><td> --
+</td><td> Yes
+</td></tr>
+
 <tr><td> <a href="frmt_various.html#CEOS">CEOS (Spot for instance)</a>
 </td><td> CEOS
 </td><td> No
@@ -155,12 +163,20 @@
 </td><td> Yes
 </td></tr>
 
+<tr><td> <a href="drv_db2_raster.html">DB2</a>
+</td><td> DB2
+</td><td> Yes
+</td><td> Yes
+</td><td> No limits
+</td><td> No, needs ODBC (and any or all of PNG, JPEG, WEBP drivers)
+</td></tr>
+
 <tr><td> <a href="frmt_various.html#DDS">DirectDraw Surface</a>
 </td><td> DDS
 </td><td> Yes
 </td><td> No
-</td><td> 
-</td><td> No
+</td><td>
+</td><td> No, needs Crunch Lib
 </td></tr>
 
 <tr><td> <a href="frmt_various.html#DIMAP">Spot DIMAP (metadata.dim)</a>
@@ -279,7 +295,7 @@
 </td><td> ERS
 </td><td> Yes
 </td><td> Yes
-</td><td> 
+</td><td>
 </td><td> Yes
 </td></tr>
 
@@ -447,7 +463,7 @@
 </td><td> GTX
 </td><td> Yes
 </td><td> Yes
-</td><td> 
+</td><td>
 </td><td> Yes
 </td></tr>
 
@@ -523,6 +539,14 @@
 </td><td> Yes
 </td></tr>
 
+<tr><td> <a href="frmt_isce.html">ISCE raster</a>
+</td><td> ISCE
+</td><td> Yes
+</td><td> No
+</td><td> --
+</td><td> Yes
+</td></tr>
+
 <tr><td> <a href="frmt_isis2.html">USGS Astrogeology ISIS cube (Version 2)</a>
 </td><td> ISIS2
 </td><td> Yes
@@ -559,7 +583,7 @@
 </td><td> JPEG
 </td><td> Yes
 </td><td> Yes
-</td><td> 4GiB (max dimentions 65500x65500)
+</td><td> 4GiB (max dimensions 65500x65500)
 </td><td> Yes (internal libjpeg provided)
 </td></tr>
 
@@ -599,7 +623,7 @@
 </td><td> JP2MrSID
 </td><td> Yes
 </td><td> Yes
-</td><td> 
+</td><td>
 </td><td> No, needs MrSID SDK
 </td></tr>
 
@@ -667,7 +691,7 @@
 </td><td> Yes
 </td></tr>
 
-<tr><td> <a href="frmt_leveller.html">Daylon Leveller Heightfield</a> 
+<tr><td> <a href="frmt_leveller.html">Daylon Leveller Heightfield</a>
 </td><td> Leveller
 </td><td> No
 </td><td> Yes
@@ -685,7 +709,7 @@
 
 <tr><td> <a href="frmt_mbtiles.html">MBTiles</a>
 </td><td> MBTiles
-</td><td> No
+</td><td> Yes
 </td><td> Yes
 </td><td> --
 </td><td> No (needs OGR SQLite driver)
@@ -703,7 +727,7 @@
 </td><td> MEM
 </td><td> Yes
 </td><td> Yes
-</td><td> 
+</td><td>
 </td><td> Yes
 </td></tr>
 
@@ -731,6 +755,14 @@
 </td><td> No, needs LIDAR SDK
 </td></tr>
 
+<tr><td> <a href="frmt_marfa.html">Meta Raster Format</a>
+</td><td> MRF
+</td><td> Yes
+</td><td> Yes
+</td><td> --
+</td><td> Yes
+</td></tr>
+
 <tr><td> <a href="frmt_mrsid.html">Multi-resolution Seamless Image Database</a>
 </td><td> MrSID
 </td><td> No
@@ -743,7 +775,7 @@
 </td><td> MSG
 </td><td> No
 </td><td> Yes
-</td><td> 
+</td><td>
 </td><td> No, needs msg library
 </td></tr>
 
@@ -751,7 +783,7 @@
 </td><td> MSGN
 </td><td> No
 </td><td> Yes
-</td><td> 
+</td><td>
 </td><td> Yes
 </td></tr>
 
@@ -856,7 +888,7 @@
 </td><td> Yes
 </td><td> Yes
 </td><td> --
-</td><td> Yes (but needs libpoppler or libpodofo for read support)
+</td><td> Yes (but needs libpoppler, libpodofo or PDFium for read support)
 </td></tr>
 
 <tr><td> <a href="frmt_pds.html">NASA Planetary Data System</a>
@@ -971,6 +1003,22 @@
 </td><td> Yes
 </td></tr>
 
+<tr><td> <a href="frmt_safe.html">Sentinel 1 SAR SAFE (manifest.safe)</a>
+</td><td> SAFE
+</td><td> No
+</td><td> Yes
+</td><td> No limits
+</td><td> Yes
+</td></tr>
+
+<tr><td> <a href="frmt_sentinel2.html">Sentinel 2</a>
+</td><td> SENTINEL2
+</td><td> No
+</td><td> Yes
+</td><td> No limits
+</td><td> Yes
+</td></tr>
+
 <tr><td> <a href="frmt_various.html#SAGA">SAGA GIS Binary format</a>
 </td><td> SAGA
 </td><td> Yes
@@ -1099,7 +1147,7 @@
 </td><td> No, needs libwebp
 </td></tr>
 
-<tr><td> <a href="frmt_wms.html">OGC Web Map Service</a>
+<tr><td> <a href="frmt_wms.html">OGC Web Map Service, and TMS, WorldWind, On Earth tiled, VirtualEarth, ArcGIS REST, IIP)</a>
 </td><td> WMS
 </td><td> No
 </td><td> Yes
@@ -1107,6 +1155,14 @@
 </td><td> No, needs libcurl
 </td></tr>
 
+<tr><td> <a href="frmt_wmts.html">OGC Web Map Tile Service</a>
+</td><td> WMTS
+</td><td> No
+</td><td> Yes
+</td><td> --
+</td><td> No, needs libcurl
+</td></tr>
+
 <tr><td> <a href="frmt_various.html#XPM">X11 Pixmap (.xpm)</a>
 </td><td> XPM
 </td><td> Yes
@@ -1127,7 +1183,7 @@
 </td><td> ZMap
 </td><td> Yes
 </td><td> Yes
-</td><td> 
+</td><td>
 </td><td> Yes
 </td></tr>
 
@@ -1147,7 +1203,7 @@
 </p>
 
 <p>
-$Id: formats_list.html 28859 2015-04-07 08:40:10Z rouault $
+$Id: formats_list.html 33822 2016-03-31 12:35:35Z rouault $
 </p>
 
 </body>
diff --git a/frmts/frmt_various.html b/frmts/frmt_various.html
index 23c4cd9..4b84816 100644
--- a/frmts/frmt_various.html
+++ b/frmts/frmt_various.html
@@ -15,8 +15,8 @@
 
 <p>
 Supported for read and write access, including reading of an affine
-georeferencing transform and some projections.  
-This format is the ASCII interchange format for Arc/Info Grid, 
+georeferencing transform and some projections.
+This format is the ASCII interchange format for Arc/Info Grid,
 and takes the form of an ASCII file, plus sometimes an associated .prj file.
 It is normally produced with the Arc/Info ASCIIGRID command.</p>
 
@@ -31,7 +31,7 @@ same format as the band data.
 <p>By default, the datatype returned for AAIGRID datasets by GDAL is autodetected,
 and set to Float32 for grid with floating point values or Int32 otherwise. This is
 done by analysing the format of the NODATA value and, if needed, the data of the
-grid. From GDAL 1.8.0, you can explictely specify the datatype by setting the
+grid. From GDAL 1.8.0, you can explicitly specify the datatype by setting the
 AAIGRID_DATATYPE configuration option (Int32, Float32 and Float64 values are
 supported currently)</p>
 
@@ -39,7 +39,7 @@ supported currently)</p>
 georeferenced units differ) then DX and DY parameters will be output instead
 of CELLSIZE.  Such files can be used in Golden Surfer, but not most other
 ascii grid reading programs.  For force the X pixel size to be used as CELLSIZE
-use the FORCE_CELLSIZE=YES creation option or resample the input to have 
+use the FORCE_CELLSIZE=YES creation option or resample the input to have
 square pixels.</p>
 
 <p>When writing floating-point values, the driver uses the "%.20g" format
@@ -61,9 +61,10 @@ for Arc/Info Binary Grid format.</p>
 
 <p>(GDAL >= 1.9.0)</p>
 
-<p>This is a conveniency driver to read ACE2 DEMs. Those files contain raw binary data. The
-georeferencing is entirely determined by the filename. Quality, source and confidence
-layers are of Int16 type, whereas elevation data is returned as Float32.</p>
+<p>This is a convenience driver to read ACE2 DEMs. Those files contain
+raw binary data. The georeferencing is entirely determined by the
+filename. Quality, source and confidence layers are of Int16 type,
+whereas elevation data is returned as Float32.</p>
 
 <p><a href="http://tethys.eaprs.cse.dmu.ac.uk/ACE2/shared/overview">ACE2 product overview</a></p>
 
@@ -89,19 +90,19 @@ GDAL will report the images it is composed of as subdatasets. If the THF referen
 
 <h2><a name="AIG">AIG -- Arc/Info Binary Grid</a></h2>
 
-<p>Supported by GDAL for read access.  
-This format is the internal binary format for Arc/Info Grid, 
-and takes the form of a coverage level directory in an Arc/Info database. 
+<p>Supported by GDAL for read access.
+This format is the internal binary format for Arc/Info Grid,
+and takes the form of a coverage level directory in an Arc/Info database.
 To open the coverage select the coverage directory, or an .adf file (such as
 hdr.adf) from within it.  If the directory does not contain file(s) with names
 like w001001.adf then it is not a grid coverage.</p>
 
-<p>Support includes reading of an affine 
+<p>Support includes reading of an affine
 georeferencing transform, some projections, and a color
 table (.clr) if available.</p>
 
 <p>This driver is implemented based on a reverse engineering of the format.  See
-the <a href="http://home.gdal.org/projects/aigrid/index.html">format 
+the <a href="http://home.gdal.org/projects/aigrid/index.html">format
 description</a> for more details.</p>
 
 <p>The projections support (read if a prj.adf file is available) is quite
@@ -114,9 +115,9 @@ limited.  Additional sample prj.adf files may be sent to the maintainer,
 
 <h2><a name="ARG">ARG -- Azavea Raster Grid</a></h2>
 
-<p>Driver implementation for a raw format that is used in 
-<a href="http://geotrellis.io/">GeoTrellis</a> and called ARG. 
-<a href="http://geotrellis.io/documentation/0.9.0/geotrellis/io/arg/">ARG format 
+<p>Driver implementation for a raw format that is used in
+<a href="http://geotrellis.io/">GeoTrellis</a> and called ARG.
+<a href="http://geotrellis.io/documentation/0.9.0/geotrellis/io/arg/">ARG format
 specification</a>. Format is essentially a raw format, with a companion .JSON file.</p>
 
 <p>NOTE: Implemented as <tt>gdal/frmts/arg/argdataset.cpp</tt>.</p>
@@ -125,8 +126,8 @@ specification</a>. Format is essentially a raw format, with a companion .JSON fi
 
 <h2><a name="BSB">BSB -- Maptech/NOAA BSB Nautical Chart Format</a></h2>
 
-<p>BSB Nautical Chart format is supported for read access, including reading 
-the colour table and the reference points (as GCPs).  Note that the .BSB 
+<p>BSB Nautical Chart format is supported for read access, including reading
+the colour table and the reference points (as GCPs).  Note that the .BSB
 files cannot be selected directly.  Instead select the .KAP files.  Versions
 1.1, 2.0 and 3.0 have been tested successfully.</p>
 
@@ -152,7 +153,7 @@ driver includes support for reading and writing .bt 1.3 format including
 support for Int16, Int32 and Float32 pixel data types.</p>
 
 <p>The driver does
-<b>not</b> support reading or writting gzipped (.bt.gz) .bt files even
+<b>not</b> support reading or writing gzipped (.bt.gz) .bt files even
 though this is supported by the VTP software.  Please unpack the files
 before using with GDAL using the "gzip -d file.bt.gz".</p>
 
@@ -181,7 +182,7 @@ not capture any metadata, or georeferencing.</p>
 will have problems with many other data sources.  In particular, it will
 only work with eight bit unsigned data.</p>
 
-<p>See the separate <a href="#SAR_CEOS">SAR_CEOS</a> driver for access to 
+<p>See the separate <a href="#SAR_CEOS">SAR_CEOS</a> driver for access to
 SAR CEOS data products.</p>
 
 <p>NOTE: Implemented as <tt>gdal/frmts/ceos/ceosdataset.cpp</tt>.</p>
@@ -235,7 +236,7 @@ Land Use and Land Cover Digital Data (Data Users Guide 4)</a> - HTML version con
 Supported for writing and creation.  The DirectDraw Surface file format (uses
 the filename extension DDS), from Microsoft, is a standard for storing data
 compressed with the lossy S3 Texture Compression (S3TC) algorithm. The DDS
-format and compression are provided by the crunch library. 
+format and compression are provided by the crunch library.
 </p>
 
 <p>
@@ -258,11 +259,11 @@ creation option QUALITY.
 <h2><a name="DIMAP">DIMAP -- Spot DIMAP</a></h2>
 
 <p>This is a read-only read for Spot DIMAP described images.  To use, select
-the METADATA.DIM file in a product directory, or the product directory 
+the METADATA.DIM file in a product directory, or the product directory
 itself.</p>
 
-<p>The imagery is in a distinct imagery file, often a TIFF file, but the 
-DIMAP dataset handles accessing that file, and attaches geolocation and 
+<p>The imagery is in a distinct imagery file, often a TIFF file, but the
+DIMAP dataset handles accessing that file, and attaches geolocation and
 other metadata to the dataset from the metadata xml file.</p>
 
 <p>From GDAL 1.6.0, the content of the <Spectral_Band_Info> node is reported as metadata
@@ -287,7 +288,7 @@ for more detailed information.</p>
 
 <h2><a name="DOQ1">DOQ1 -- First Generation USGS DOQ</a></h2>
 
-<p>Support for read access, including reading of an affine georeferencing 
+<p>Support for read access, including reading of an affine georeferencing
 transform, and capture of the projection string.   This format is the old,
 unlabelled DOQ (Digital Ortho Quad) format from the USGS.</p>
 
@@ -297,7 +298,7 @@ unlabelled DOQ (Digital Ortho Quad) format from the USGS.</p>
 
 <h2><a name="DOQ2">DOQ2 -- New Labelled USGS DOQ</a></h2>
 
-<p>Support for read access, including reading of an affine georeferencing 
+<p>Support for read access, including reading of an affine georeferencing
 transform, capture of the projection string and reading of other auxiliary
 fields as metadata.   This format is the new,
 labelled DOQ (Digital Ortho Quad) format from the USGS.</p>
@@ -330,13 +331,13 @@ USGS DOQ Standards</a></p>
 often referred to as ESRI BIL format.  Eight, sixteen
 and thirty-two bit integer raster data types are supported as well as 32
 bit floating point.  Coordinate systems (from a .prj file), and georeferencing
-are supported.  Unrecognised options in the .hdr file are ignored.  To 
+are supported.  Unrecognized options in the .hdr file are ignored.  To
 open a dataset select the file with the image file (often with the extension
 .bil).  If present .clr color table files are read, but not written. If present,
 image.rep file will be read to extract the projection system of SpatioCarte Defense 1.0 raster products.</p>
 
 <p>This driver does not always do well differentiating between floating point and
-integer data.  The GDAL extension to the .hdr format to differentiate is to add 
+integer data.  The GDAL extension to the .hdr format to differentiate is to add
 a field named PIXELTYPE with values of either FLOAT, SIGNEDINT or UNSIGNEDINT.
 In combination with the NBITS field it is possible to described all variations
 of pixel types.</p>
@@ -418,16 +419,16 @@ contains the actual raw data may have the extension .bl.</p>
 
 <p>GDAL supports some variations of raw raster files with associated ENVI
 style .hdr files describing the format.  To select an existing ENVI raster
-file select the binary file containing the data (as opposed to the .hdr 
+file select the binary file containing the data (as opposed to the .hdr
 file), and GDAL will find the .hdr file by replacing the dataset extension
 with .hdr.</p>
 
 <p>GDAL should support reading bil, bip and bsq interleaved formats, and
-most pixel types are supported, including 8bit unsigned, 16 and 32bit 
-signed and unsigned integers, 32bit and 64 bit floating point, and 
-32bit and 64bit complex floating point.  There is limited support for 
-recognising map_info keywords with the 
-coordinate system and georeferencing.  In particular, UTM and State Plane 
+most pixel types are supported, including 8bit unsigned, 16 and 32bit
+signed and unsigned integers, 32bit and 64 bit floating point, and
+32bit and 64bit complex floating point.  There is limited support for
+recognising map_info keywords with the
+coordinate system and georeferencing.  In particular, UTM and State Plane
 should work.</p>
 
 <p>Starting with GDAL 1.10, all ENVI header fields will be stored in the
@@ -438,10 +439,10 @@ ENVI metadata domain, and all of these can then be written out to the header fil
 <ul>
 
 	<li> <b>INTERLEAVE=BSQ/BIP/BIL</b>: Force the generation specified
-	type of interleaving. <b>BSQ</b> --- band sequental (default),
+	type of interleaving. <b>BSQ</b> --- band sequential (default),
 	<b>BIP</b> --- data interleaved by pixel,
 	<b>BIL</b> --- data interleaved by line.</li>
-	
+
 	<li> <b>SUFFIX=REPLACE/ADD</b>: Force adding ".hdr" suffix to supplied
 	filename, e.g. if user selects "file.bin" name for output dataset,
 	"file.bin.hdr" header file will be created. By default header file
@@ -526,7 +527,7 @@ COLS:    9340
 </pre>
 
 <p>
-Pixel data types of U8, U16, S16, F32, F64, and U1 (bit) are supported.  
+Pixel data types of U8, U16, S16, F32, F64, and U1 (bit) are supported.
 Georeferencing and coordinate system information should be supported
 when provided. </p>
 
@@ -543,7 +544,7 @@ when provided. </p>
 <p>By default, the datatype returned for GRASS ASCII grid datasets by GDAL is autodetected,
 and set to Float32 for grid with floating point values or Int32 otherwise. This is
 done by analysing the format of the null value and the first 100k bytes of data of the
-grid. You can also explictely specify the datatype by setting the
+grid. You can also explicitly specify the datatype by setting the
 GRASSASCIIGRID_DATATYPE configuration option (Int32, Float32 and Float64 values are
 supported currently)</p>
 
@@ -590,7 +591,7 @@ binary grid format), it is more complicated and flexible.</p>
 <h2><a name="GXF">GXF -- Grid eXchange File</a></h2>
 
 <p>This is a raster exchange format propagated by Geosoft, and made a standard
-in the gravity/magnetics field.  GDAL supports reading (but not writing) 
+in the gravity/magnetics field.  GDAL supports reading (but not writing)
 GXF-3 files, including support for georeferencing information, and projections.
 </p>
 
@@ -607,18 +608,18 @@ configuration option (Float64 supported currently)</p>
 
 <h2><a name="IDA">IDA -- Image Display and Analysis</a></h2>
 
-<p>GDAL supports reading and writing IDA images with some limitations.  IDA 
+<p>GDAL supports reading and writing IDA images with some limitations.  IDA
 images are the image format of WinDisp 4.  The files are always one band only
 of 8bit data.  IDA files often have the extension .img though that is not
 required.</p>
 
 <p>Projection and georeferencing information is read though some projections
-(ie. Meteosat, and Hammer-Aitoff) are not supported.  When writing IDA files
-the projection must have a false easting and false northing of zero. The 
+(i.e. Meteosat, and Hammer-Aitoff) are not supported.  When writing IDA files
+the projection must have a false easting and false northing of zero. The
 support coordinate systems in IDA are Geographic, Lambert Conformal Conic,
 Lambert Azimuth Equal Area, Albers Equal-Area Conic and Goodes Homolosine.</p>
 
-<p>IDA files typically contain values scaled to 8bit via a slope and offset.  
+<p>IDA files typically contain values scaled to 8bit via a slope and offset.
 These are returned as the slope and offset values of the bands and they must
 be used if the data is to be rescaled to original raw values for analysis. </p>
 
@@ -668,10 +669,32 @@ Most of the metadata is read.
 
 <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
 
+<h2><a name="ISCE">ISCE</a></h2>
+
+<p>Driver for the image formats used in the JPL's Interferometric synthetic
+aperture radar Scientific Computing Environment (ISCE). Only images with
+data types mappable to GDAL data types are supported.</p>
+
+<p>Image properties are stored under the ISCE metadata domain, but there is
+currently no support to access underlying components elements and their
+properties. Likewise, ISCE domain metadata will be saved as properties
+in the image XML file.</p>
+
+<p>Georeferencing is not yet implemented.</p>
+
+<p>The ACCESS_MODE property is not currently honored.</p>
+
+<p>The only creation option currently is SCHEME, which value (BIL, BIP, BSQ)
+determine the interleaving (default is BIP).</p>
+
+<p>NOTE: Implemented as <tt>gdal/frmts/raw/iscedataset.cpp</tt>.<p>
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
 <h2><a name="JDEM">JDEM -- Japanese DEM (.mem)</a></h2>
 
 <p>GDAL includes read support for Japanese DEM files, normally having the
-extension .mem.  These files are a product of the Japanese Geographic Survey 
+extension .mem.  These files are a product of the Japanese Geographic Survey
 Institute.</p>
 
 <p>These files are represented as having one 32bit floating band with elevation
@@ -682,7 +705,7 @@ system (always lat/long on the Tokyo datum). </p>
 
 <p>NOTE: Implemented as <tt>gdal/frmts/jdem/jdemdataset.cpp</tt>.</p>
 
-<p>See Also: <a href="http://www.gsi.go.jp/ENGLISH/">Geographic Survey 
+<p>See Also: <a href="http://www.gsi.go.jp/ENGLISH/">Geographic Survey
 Institute (GSI) Web Site.</a></p>
 
 <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
@@ -706,12 +729,12 @@ except the limitation of the file system.</p>
 <h2><a name="LAN">LAN -- Erdas 7.x .LAN and .GIS</a></h2>
 
 <p>GDAL supports reading and writing
-Erdas 7.x .LAN and .GIS raster files.  Currently 
+Erdas 7.x .LAN and .GIS raster files.  Currently
 4bit, 8bit and 16bit pixel data types are supported for reading
 and 8bit and 16bit for writing.  </p>
 
-<p>GDAL does read the map extents (geotransform) from LAN/GIS files, and 
-attempts to read the coordinate system informaton.  However, this format
+<p>GDAL does read the map extents (geotransform) from LAN/GIS files, and
+attempts to read the coordinate system information.  However, this format
 of file does not include complete coordinate system information, so for
 state plane and UTM coordinate systems a LOCAL_CS definition is returned
 with valid linear units but no other meaningful information.</p>
@@ -735,9 +758,9 @@ and so on.   To open a dataset select the .hdr file.</p>
 <p>Reading lat/long GCPs (TOP_LEFT_CORNER, ...) is supported but there is no
 support for reading affine georeferencing or projection information.</p>
 
-<p>Unrecognised keywords from the .hdr file are preserved as metadata. </p>
+<p>Unrecognized keywords from the .hdr file are preserved as metadata.</p>
 
-<p>All data types with GDAL equivelents are supported, including 8, 16, 32 and
+<p>All data types with GDAL equivalents are supported, including 8, 16, 32 and
 64 bit data precisions in integer, real and complex data types.  In addition
 tile organized files (as produced by the Vexcel SAR Processor - APP) are
 supported for reading. </p>
@@ -758,7 +781,7 @@ be manually added to the .hdr file if required.</p>
 <h2><a name="NDF">NDF -- NLAPS Data Format</a></h2>
 
 <p>GDAL has limited support for reading NLAPS Data Format files.  This is a
-format primarily used by the Eros Data Center for distribution of Landsat 
+format primarily used by the Eros Data Center for distribution of Landsat
 data.  NDF datasets consist of a header file (often with the extension .H1)
 and one or more associated raw data files (often .I1, .I2, ...).  To open
 a dataset select the header file, often with the extension .H1, .H2 or
@@ -777,11 +800,11 @@ Data Format Specification</a>.</p>
 
 <h2><a name="GMT">GMT -- GMT Compatible netCDF</a></h2>
 
-<p>GDAL has limited support for reading and writing netCDF <i>grid</i> files. 
+<p>GDAL has limited support for reading and writing netCDF <i>grid</i> files.
 NetCDF files that are not recognised as grids (they lack variables called
 dimension, and z) will be silently ignored by this driver.  This driver is
-primarily intended to provide a mechanism for grid interchange with the 
-<a href="http://gmt.soest.hawaii.edu/">GMT</a> package.  The 
+primarily intended to provide a mechanism for grid interchange with the
+<a href="http://gmt.soest.hawaii.edu/">GMT</a> package.  The
 netCDF driver should be used for more general netCDF datasets.</p>
 
 <p>The units information in the file will be ignored, but x_range, and
@@ -789,9 +812,9 @@ y_range information will be read to get georeferenced extents of the raster.
 All netCDF data types should be supported for reading.</p>
 
 <p>Newly created files (with a type of <tt>GMT</tt>) will always have
-units of "meters" for x, y and z but the x_range, y_range and z_range should 
-be correct.  Note that netCDF does not have an unsigned byte data type, so 
-8bit rasters will generally need to be converted to Int16 for export to 
+units of "meters" for x, y and z but the x_range, y_range and z_range should
+be correct.  Note that netCDF does not have an unsigned byte data type, so
+8bit rasters will generally need to be converted to Int16 for export to
 GMT.</p>
 
 <p>NetCDF support in GDAL is optional, and not compiled in by default.  </p>
@@ -804,13 +827,13 @@ GMT.</p>
 
 <h2><a name="PAux">PAux -- PCI .aux Labelled Raw Format</a></h2>
 
-<p>GDAL includes a partial implementation of the PCI .aux labelled raw raster 
+<p>GDAL includes a partial implementation of the PCI .aux labelled raw raster
 file for read, write and creation.  To open a PCI labelled file, select the
 raw data file itself.  The .aux file (which must have a common base name) will
 be checked for automatically. </p>
 
 <p>The format type for creating new files is <tt>PAux</tt>.  All PCI data types
-(8U, 16U, 16S, and 32R) are supported.  Currently georeferencing, projections, 
+(8U, 16U, 16S, and 32R) are supported.  Currently georeferencing, projections,
 and other metadata is ignored.</p>
 
 <p>Creation Options:</p>
@@ -827,7 +850,7 @@ Description</a></p>
 <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
 
 <h2><a name="PCRaster">PCRaster raster file format</a></h2>
-<p>GDAL includes support for reading and writing PCRaster raster files. PCRaster is a dynamic modelling system for distributed simulation models. The main applications of PCRaster are found in environmental modelling: geography, hydrology, ecology to name a few. Examples include models for research on global hydrology, vegetation competition models, slope stability models and land use change models.</p>
+<p>GDAL includes support for reading and writing PCRaster raster files. PCRaster is a dynamic modeling system for distributed simulation models. The main applications of PCRaster are found in environmental modeling: geography, hydrology, ecology to name a few. Examples include models for research on global hydrology, vegetation competition models, slope stability models and land use change models.</p>
 
 <p>The driver reads all types of PCRaster maps: booleans, nominal, ordinals, scalar, directional and ldd. The same cell representation used to store values in the file is used to store the values in memory.</p>
 
@@ -868,7 +891,7 @@ Description</a></p>
   </tbody>
 </table>
 
-<p>For rasters from other sources than a PCRaster raster file a value scale and cell representation is determined according to the folowing rules:</p>
+<p>For rasters from other sources than a PCRaster raster file a value scale and cell representation is determined according to the following rules:</p>
 
 <table>
   <thead>
@@ -932,8 +955,8 @@ Description</a></p>
 
 <h2><a name="PNG">PNG -- Portable Network Graphics</a></h2>
 
-<p>GDAL includes support for reading, and creating .png files.  Greyscale, 
-pseudo-colored, Paletted, RGB and RGBA PNG files are supported as well as 
+<p>GDAL includes support for reading, and creating .png files.  Greyscale,
+pseudo-colored, Paletted, RGB and RGBA PNG files are supported as well as
 precisions of eight and sixteen bits per sample.</p>
 
 <p>PNG files are linearly compressed, so random reading of large PNG files can
@@ -946,10 +969,10 @@ will be read.  Single transparency values in greyscale files will be
 recognised as a nodata value in GDAL.  Transparent index in paletted images
 are preserved when the color table is read. </p>
 
-<p>PNG files can be created with a type of PNG, using the CreateCopy() method, 
+<p>PNG files can be created with a type of PNG, using the CreateCopy() method,
 requiring a prototype to read from.  Writing includes support for the
-various image types, and will preserve transparency/nodata values.  
-Georeferencing .wld files are written if option WORLDFILE setted.  All
+various image types, and will preserve transparency/nodata values.
+Georeferencing .wld files are written if option WORLDFILE is set.  All
 pixel types other than 16bit unsigned will be written as eight bit.</p>
 
 <p>Starting with GDAL 1.9.0, XMP metadata can be extracted from the file, and will be
@@ -989,12 +1012,13 @@ of 9 is slow but does the best compression.</li>
 <li> <b>COPYRIGHT=value</b>: Copyright, written in a TEXT or iTXt chunk (GDAL >= 2.0 )</li>
 <li> <b>COMMENT=value</b>: Comment, written in a TEXT or iTXt chunk (GDAL >= 2.0 )</li>
 <li> <b>WRITE_METADATA_AS_TEXT=YES/NO</b>: Whether to write source dataset metadata in TEXT chunks (GDAL >= 2.0 )</li>
+<li> <b>NBITS=1/2/4</b>: Force number of output bits (GDAL >= 2.1 )</li>
 
 </ul>
 
-<p>NOTE: Implemented as <tt>gdal/frmts/png/pngdataset.cpp</tt>.</p> 
+<p>NOTE: Implemented as <tt>gdal/frmts/png/pngdataset.cpp</tt>.</p>
 
-<p>PNG support is implemented based on the libpng reference library.  
+<p>PNG support is implemented based on the libpng reference library.
 More information is available at <a href="http://www.libpng.org/pub/png">
 http://www.libpng.org/pub/png</a>.</p>
 
@@ -1013,7 +1037,7 @@ http://www.libpng.org/pub/png</a>.</p>
 <ul>
 
 <li> <b>MAXVAL=n</b>: Force setting the maximum color value to <b>n</b>
-in the output PNM file. May be useful if you plannig use the output files with
+in the output PNM file. May be useful if you planning to use the output files with
 software which is not liberal to this value.</li>
 </ul>
 
@@ -1023,13 +1047,13 @@ software which is not liberal to this value.</li>
 
 <h2><a name="ROI_PAC">ROI_PAC</a></h2>
 
-<p>Driver for the image formats used in the JPL's ROI_PAC 
+<p>Driver for the image formats used in the JPL's ROI_PAC
 project (<a href="https://aws.roipac.org/">https://aws.roipac.org/</a>).
 All image type are supported excepted .raw images.</p>
 
 <p>Metadata are stored in the ROI_PAC domain.</p>
 
-<p>Georeferencing is supported, but expect problems when using the UTM 
+<p>Georeferencing is supported, but expect problems when using the UTM
 projection, as ROI_PAC format do not store any hemisphere field.</p>
 
 <p>When creating files, you have to be able to specify the right data type
@@ -1064,12 +1088,13 @@ Subdatasets:
 </pre>
 
 
-<p>In some situations, <a href="frmt_nitf.html">NITF</a> tiles inside a subdataset don't share the same palettes.
-The RPFTOC driver will do its best to remap palettes to the reported palette by gdalinfo (which
-is the palette of the first tile of the subdataset).
-In situations where it wouldn't give a good result, you can try to set the RPFTOC_FORCE_RGBA
-environment variable to TRUE before opening the subdataset. This will cause the driver to expose
-the subdataset as a RGBA dataset, instead of a paletted one.</p>
+<p>In some situations, <a href="frmt_nitf.html">NITF</a> tiles inside a
+subdataset don't share the same palettes.  The RPFTOC driver will do its best
+to remap palettes to the reported palette by gdalinfo (which is the palette of
+the first tile of the subdataset).  In situations where it would not give a
+good result, you can try to set the RPFTOC_FORCE_RGBA environment variable to
+TRUE before opening the subdataset. This will cause the driver to expose the
+subdataset as a RGBA dataset, instead of a paletted one.</p>
 
 <p>It is possible to build external overviews for a subdataset. The overview for the first subdataset
 will be named A.TOC.1.ovr for example, for the second dataset it will be A.TOC.2.ovr, etc.
@@ -1084,7 +1109,7 @@ as the list of the NITF tiles of the subdataset.</p>
 
 <ul>
 <li> <a href="frmt_ogdi.html">OGDI Bridge</a> : the RPFTOC driver gives an equivalent
-     functionnality (without external dependency) to the RPF driver from the OGDI library. </li>
+     functionality (without external dependency) to the RPF driver from the OGDI library. </li>
 <li> <a href="http://www.everyspec.com/MIL-PRF/MIL-PRF+%28080000+-+99999%29/MIL-PRF-89038_25371/">MIL-PRF-89038</a> : specification of RPF, CADRG, CIB products</li>
 </ul>
 
@@ -1107,33 +1132,33 @@ CEOS superstructure information.  It also captures various pieces of metadata
 from various header files, including:</p>
 
 <pre>
-  CEOS_LOGICAL_VOLUME_ID=EERS-1-SAR-MLD  
-  CEOS_PROCESSING_FACILITY=APP         
-  CEOS_PROCESSING_AGENCY=CCRS    
-  CEOS_PROCESSING_COUNTRY=CANADA      
-  CEOS_SOFTWARE_ID=APP 1.62    
-  CEOS_ACQUISITION_TIME=19911029162818919               
+  CEOS_LOGICAL_VOLUME_ID=EERS-1-SAR-MLD
+  CEOS_PROCESSING_FACILITY=APP
+  CEOS_PROCESSING_AGENCY=CCRS
+  CEOS_PROCESSING_COUNTRY=CANADA
+  CEOS_SOFTWARE_ID=APP 1.62
+  CEOS_ACQUISITION_TIME=19911029162818919
   CEOS_SENSOR_CLOCK_ANGLE=  90.000
-  CEOS_ELLIPSOID=IUGG_75         
+  CEOS_ELLIPSOID=IUGG_75
   CEOS_SEMI_MAJOR=    6378.1400000
   CEOS_SEMI_MINOR=    6356.7550000
 </pre>
 
-<p>The SAR_CEOS driver also includes some support for SIR-C and PALSAR 
+<p>The SAR_CEOS driver also includes some support for SIR-C and PALSAR
 polarimetric data.  The SIR-C format contains an image in compressed
-scattering matrix form, described 
-<a href="http://southport.jpl.nasa.gov/software/dcomp/dcomp.html">here</a>.  
+scattering matrix form, described
+<a href="http://southport.jpl.nasa.gov/software/dcomp/dcomp.html">here</a>.
 GDAL decompresses the data as it is read in.  The PALSAR format
 contains bands that correspond almost exactly to elements of the 3x3
 Hermitian covariance matrix-
 see the <a href="http://www.ersdac.or.jp/palsar/palsar_E.html">
-ERSDAC-VX-CEOS-004A.pdf</a> document for a complete description (pixel 
+ERSDAC-VX-CEOS-004A.pdf</a> document for a complete description (pixel
 storage is described on page 193). GDAL converts these to complex floating
 point covariance matrix bands as they are read in.  The convention used
 to represent the covariance matrix in terms of the scattering matrix
-elements HH, HV (=VH), and VV is indicated below. Note that the 
+elements HH, HV (=VH), and VV is indicated below. Note that the
 non-diagonal elements of the matrix are complex values, while the diagonal
-values are real (though represented as complex bands).</p> 
+values are real (though represented as complex bands).</p>
 
 <ul>
 <li> Band 1: Covariance_11 (Float32) = HH*conj(HH)</li>
@@ -1155,23 +1180,23 @@ values are real (though represented as complex bands).</p>
 
 <p>(starting with GDAL 1.7.0)</p>
 
-<p>The driver supports both reading and writing (including create, delete, 
-and copy) SAGA GIS binary grids. SAGA binary grid datasets are made of 
-an ASCII header (.SGRD) and a binary data (.SDAT) file with a common 
+<p>The driver supports both reading and writing (including create, delete,
+and copy) SAGA GIS binary grids. SAGA binary grid datasets are made of
+an ASCII header (.SGRD) and a binary data (.SDAT) file with a common
 basename.  The .SDAT file should be selected to access the dataset.</p>
 
-<p>The driver supports reading the following SAGA datatypes 
+<p>The driver supports reading the following SAGA datatypes
 (in brackets the corresponding GDAL types): BIT (GDT_Byte),
-BYTE_UNSIGNED (GDT_Byte), BYTE (GDT_Byte), SHORTINT_UNSIGNED (GDT_UInt16), 
-SHORTINT (GDT_Int16), INTEGER_UNSIGNED (GDT_UInt32), INTEGER (GDT_Int32), 
+BYTE_UNSIGNED (GDT_Byte), BYTE (GDT_Byte), SHORTINT_UNSIGNED (GDT_UInt16),
+SHORTINT (GDT_Int16), INTEGER_UNSIGNED (GDT_UInt32), INTEGER (GDT_Int32),
 FLOAT (GDT_Float32) and DOUBLE (GDT_Float64).</p>
 
-<p>The driver supports writing the following SAGA datatypes: BYTE_UNSIGNED 
-(GDT_Byte), SHORTINT_UNSIGNED (GDT_UInt16), SHORTINT (GDT_Int16), 
-INTEGER_UNSIGNED (GDT_UInt32), INTEGER (GDT_Int32), FLOAT (GDT_Float32) 
+<p>The driver supports writing the following SAGA datatypes: BYTE_UNSIGNED
+(GDT_Byte), SHORTINT_UNSIGNED (GDT_UInt16), SHORTINT (GDT_Int16),
+INTEGER_UNSIGNED (GDT_UInt32), INTEGER (GDT_Int32), FLOAT (GDT_Float32)
 and DOUBLE (GDT_Float64).</p>
 
-<p>Currently the driver does not support zFactors other than 1 and reading 
+<p>Currently the driver does not support zFactors other than 1 and reading
 SAGA grids which are written TOPTOBOTTOM.</p>
 
 <p>NOTE: Implemented as <tt>gdal/frmts/saga/sagadataset.cpp</tt>.</p>
@@ -1189,7 +1214,7 @@ Projection and georeferencing information is also returned.</p>
 with a name like XXXCATD.DDF.  This should be selected to open
 the dataset.</p>
 
-<p>The elevation units of DEMs may be feet or meters.  The GetType() method on a 
+<p>The elevation units of DEMs may be feet or meters.  The GetType() method on a
 band will attempt to return if the units are Feet ("ft") or Meters ("m").</p>
 
 <p>NOTE: Implemented as <tt>gdal/frmts/sdts/sdtsdataset.cpp</tt>.</p>
@@ -1200,9 +1225,9 @@ band will attempt to return if the units are Feet ("ft") or Meters ("m").</p>
 
 <p>The SGI driver currently supports the reading and writing of SGI Image files.</p>
 
-<p>The driver currently supports 1, 2, 3, and 4 band images. The driver 
-currently supports "8 bit per channel value" images. The driver supports 
-both uncompressed and run-length encoded (RLE) images for reading, but 
+<p>The driver currently supports 1, 2, 3, and 4 band images. The driver
+currently supports "8 bit per channel value" images. The driver supports
+both uncompressed and run-length encoded (RLE) images for reading, but
 created files are always RLE compressed..</p>
 
 <p>The GDAL SGI Driver was based on Paul Bourke's SGI image read code.</p>
@@ -1222,8 +1247,9 @@ created files are always RLE compressed..</p>
 
 <p>(GDAL >= 1.9.0)</p>
 
-<p>This is a conveniency driver to read Snow Data Assimilation System data.
-Those files contain Int16 raw binary data. The file to provide to GDAL is the .Hdr file.</p>
+<p>This is a convenience driver to read Snow Data Assimilation System
+data.  Those files contain Int16 raw binary data. The file to provide
+to GDAL is the .Hdr file.</p>
 
 <p><a href="http://nsidc.org/data/docs/noaa/g02158_snodas_snow_cover_model/index.html">Snow Data Assimilation System (SNODAS) Data Products at NSIDC</a></p>
 
@@ -1238,7 +1264,7 @@ Those files contain Int16 raw binary data. The file to provide to GDAL is the .H
 
 <p>The ASRP and USRP raster products (as defined by DGIWG) are variations on a
 common standard product format and are supported for reading by GDAL.  ASRP and
-USRP datasets are made of several files - typically a .GEN, .IMG, .SOU and .QAL 
+USRP datasets are made of several files - typically a .GEN, .IMG, .SOU and .QAL
 file with a common basename.  The .IMG file should be selected to access the dataset.</p>
 
 <p>ASRP (in a geographic coordinate system) and USRP (in a UTM/UPS coordinate
@@ -1306,10 +1332,10 @@ or other suffixes depending on the image file it comes with.</p>
 
 <h2><a name="XPM">XPM - X11 Pixmap</a></h2>
 
-<p>GDAL includes support for reading and writing XPM (X11 Pixmap Format) 
-image files.  These are colormapped one band images primarily used for 
+<p>GDAL includes support for reading and writing XPM (X11 Pixmap Format)
+image files.  These are colormapped one band images primarily used for
 simple graphics purposes in X11 applications.  It has been incorporated in
-GDAL primarily to ease translation of GDAL images into a form useable with
+GDAL primarily to ease translation of GDAL images into a form usable with
 the GTK toolkit.</p>
 
 <p>The XPM support does not support georeferencing (not available from XPM files)
@@ -1345,12 +1371,15 @@ This format is an ASCII interchange format for gridded data
 in an ASCII line format for transport and storage. It is commonly used
 in applications in the Oil and Gas Exploration field.</p>
 
-<p>By default, files are interpreted and written according to the PIXEL_IS_AREA convention.
-If you define the ZMAP_PIXEL_IS_POINT configuration option to TRUE, the PIXEL_IS_POINT
-convention will be followed to interprete/write the file (the georeferenced values in the header
-of the file will then be considered as the coordinate of the center of the pixels). Note that in that case,
-GDAL will report the extent with its usual PIXEL_IS_AREA convention (the coordinates of the topleft corner
-as reported by GDAL will be a half-pixel at the top and left of the values that appear in the file).</p>
+<p>By default, files are interpreted and written according to the
+PIXEL_IS_AREA convention.  If you define the ZMAP_PIXEL_IS_POINT
+configuration option to TRUE, the PIXEL_IS_POINT convention will be
+followed to interpret/write the file (the georeferenced values in the
+header of the file will then be considered as the coordinate of the
+center of the pixels). Note that in that case, GDAL will report the
+extent with its usual PIXEL_IS_AREA convention (the coordinates of the
+topleft corner as reported by GDAL will be a half-pixel at the top and
+left of the values that appear in the file).</p>
 
 <p>Informal specification given in this <a href="http://lists.osgeo.org/pipermail/gdal-dev/2011-June/029173.html">GDAL-dev mailing list thread</a></p>
 
@@ -1362,7 +1391,7 @@ as reported by GDAL will be a half-pixel at the top and left of the values that
 </p>
 
 <p>
-$Id: frmt_various.html 29778 2015-08-25 09:02:53Z rouault $
+$Id: frmt_various.html 33795 2016-03-27 03:34:36Z goatbar $
 </p>
 
 </body>
diff --git a/frmts/gdalallregister.cpp b/frmts/gdalallregister.cpp
index e03cad0..848a53d 100644
--- a/frmts/gdalallregister.cpp
+++ b/frmts/gdalallregister.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalallregister.cpp 28859 2015-04-07 08:40:10Z rouault $
+ * $Id: gdalallregister.cpp 33546 2016-02-24 21:02:52Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALAllRegister(), primary format registration.
@@ -32,7 +32,11 @@
 #include "gdal_frmts.h"
 #include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: gdalallregister.cpp 28859 2015-04-07 08:40:10Z rouault $");
+#ifdef GNM_ENABLED
+   #include "gnm_frmts.h"
+#endif
+
+CPL_CVSID("$Id: gdalallregister.cpp 33546 2016-02-24 21:02:52Z goatbar $");
 
 #ifdef notdef
 // we may have a use for this some day
@@ -50,27 +54,25 @@ static char *szConfiguredFormats = "GDAL_FORMATS";
  *
  * This function will drive any of the following that are configured into
  * GDAL.  See <a href="http://gdal.org/formats_list.html">raster list</a> and
- * <a href="http://gdal.org/ogr/ogr_formats.html">vector full list</a>
+ * <a href="http://gdal.org/ogr_formats.html">vector full list</a>
  *
- * This function should generally be called once at the beginning of the application.
+ * This function should generally be called once at the beginning of the
+ * application.
  */
 
 void CPL_STDCALL GDALAllRegister()
 
 {
+    // AutoLoadDrivers is a no-op if compiled with GDAL_NO_AUTOLOAD defined.
     GetGDALDriverManager()->AutoLoadDrivers();
 
 #ifdef FRMT_vrt
     GDALRegister_VRT();
-#endif    
-
-#ifdef FRMT_gdb    
-    GDALRegister_GDB();
-#endif    
+#endif
 
-#ifdef FRMT_gtiff    
+#ifdef FRMT_gtiff
     GDALRegister_GTiff();
-#endif    
+#endif
 
 #ifdef FRMT_nitf
     GDALRegister_NITF();
@@ -81,19 +83,19 @@ void CPL_STDCALL GDALAllRegister()
 #ifdef FRMT_hfa
     GDALRegister_HFA();
 #endif
-    
+
 #ifdef FRMT_ceos2
     GDALRegister_SAR_CEOS();
 #endif
-    
+
 #ifdef FRMT_ceos
     GDALRegister_CEOS();
 #endif
-    
+
 #ifdef FRMT_jaxapalsar
     GDALRegister_PALSARJaxa();
 #endif
-    
+
 #ifdef FRMT_gff
     GDALRegister_GFF();
 #endif
@@ -101,7 +103,7 @@ void CPL_STDCALL GDALAllRegister()
 #ifdef FRMT_elas
     GDALRegister_ELAS();
 #endif
-    
+
 #ifdef FRMT_aigrid
 //    GDALRegister_AIGrid2();
     GDALRegister_AIGrid();
@@ -131,7 +133,7 @@ void CPL_STDCALL GDALAllRegister()
 #ifdef FRMT_dds
     GDALRegister_DDS();
 #endif
-    
+
 #ifdef FRMT_gta
     GDALRegister_GTA();
 #endif
@@ -189,6 +191,10 @@ void CPL_STDCALL GDALAllRegister()
     GDALRegister_RS2();
 #endif
 
+#ifdef FRMT_safe
+    GDALRegister_SAFE();
+#endif
+
 #ifdef FRMT_pcidsk
     GDALRegister_PCIDSK();
 #endif
@@ -351,6 +357,46 @@ void CPL_STDCALL GDALAllRegister()
     GDALRegister_MAP();
 #endif
 
+#ifdef FRMT_kmlsuperoverlay
+    GDALRegister_KMLSUPEROVERLAY();
+#endif
+
+#ifdef FRMT_webp
+    GDALRegister_WEBP();
+#endif
+
+#ifdef FRMT_pdf
+    GDALRegister_PDF();
+#endif
+
+#ifdef FRMT_rasterlite
+    GDALRegister_Rasterlite();
+#endif
+
+#ifdef FRMT_mbtiles
+    GDALRegister_MBTiles();
+#endif
+
+#ifdef FRMT_plmosaic
+    GDALRegister_PLMOSAIC();
+#endif
+
+#ifdef FRMT_cals
+    GDALRegister_CALS();
+#endif
+
+#ifdef FRMT_wmts
+    GDALRegister_WMTS();
+#endif
+
+#ifdef FRMT_sentinel2
+    GDALRegister_SENTINEL2();
+#endif
+
+#ifdef FRMT_mrf
+    GDALRegister_mrf();
+#endif
+
 /* -------------------------------------------------------------------- */
 /*      Put raw formats at the end of the list. These drivers support   */
 /*      various ASCII-header labeled formats, so the driver could be    */
@@ -362,8 +408,6 @@ void CPL_STDCALL GDALAllRegister()
     GDALRegister_PNM();
     GDALRegister_DOQ1();
     GDALRegister_DOQ2();
-    GDALRegister_ENVI();
-    GDALRegister_EHdr();
     GDALRegister_GenBin();
     GDALRegister_PAux();
     GDALRegister_MFF();
@@ -387,6 +431,11 @@ void CPL_STDCALL GDALAllRegister()
     GDALRegister_SNODAS();
     GDALRegister_KRO();
     GDALRegister_ROIPAC();
+
+    // Those ones need to look for side car files so put them at end
+    GDALRegister_ENVI();
+    GDALRegister_EHdr();
+    GDALRegister_ISCE();
 #endif
 
 #ifdef FRMT_arg
@@ -408,7 +457,7 @@ void CPL_STDCALL GDALAllRegister()
 
 #ifdef FRMT_gxf
     GDALRegister_GXF();
-#endif    
+#endif
 
 #ifdef FRMT_grass
     GDALRegister_GRASS();
@@ -443,18 +492,10 @@ void CPL_STDCALL GDALAllRegister()
     GDALRegister_BLX();
 #endif
 
-#ifdef FRMT_pgchip
-    GDALRegister_PGCHIP();
-#endif
-
 #ifdef FRMT_georaster
     GDALRegister_GEOR();
 #endif
 
-#ifdef FRMT_rasterlite
-    GDALRegister_Rasterlite();
-#endif
-
 #ifdef FRMT_epsilon
     GDALRegister_EPSILON();
 #endif
@@ -467,10 +508,6 @@ void CPL_STDCALL GDALAllRegister()
     GDALRegister_SAGA();
 #endif
 
-#ifdef FRMT_kmlsuperoverlay
-    GDALRegister_KMLSUPEROVERLAY();
-#endif
-
 #ifdef FRMT_xyz
     GDALRegister_XYZ();
 #endif
@@ -479,10 +516,6 @@ void CPL_STDCALL GDALAllRegister()
     GDALRegister_HF2();
 #endif
 
-#ifdef FRMT_pdf
-    GDALRegister_PDF();
-#endif
-
 #ifdef FRMT_jpegls
     GDALRegister_JPEGLS();
 #endif
@@ -499,10 +532,6 @@ void CPL_STDCALL GDALAllRegister()
     GDALRegister_E00GRID();
 #endif
 
-#ifdef FRMT_webp
-    GDALRegister_WEBP();
-#endif
-
 #ifdef FRMT_zmap
     GDALRegister_ZMap();
 #endif
@@ -511,16 +540,12 @@ void CPL_STDCALL GDALAllRegister()
     GDALRegister_NGSGEOID();
 #endif
 
-#ifdef FRMT_mbtiles
-    GDALRegister_MBTiles();
-#endif
-
 #ifdef FRMT_iris
     GDALRegister_IRIS();
 #endif
 
-#ifdef FRMT_plmosaic
-    GDALRegister_PLMOSAIC();
+#ifdef GNM_ENABLED
+    GNMRegisterAllInternal();
 #endif
 
     OGRRegisterAllInternal();
@@ -528,7 +553,7 @@ void CPL_STDCALL GDALAllRegister()
 #ifdef FRMT_wcs
     GDALRegister_HTTP();
 #endif
-    
+
 /* -------------------------------------------------------------------- */
 /*      Deregister any drivers explicitly marked as suppressed by the   */
 /*      GDAL_SKIP environment variable.                                 */
diff --git a/frmts/georaster/frmt_georaster.html b/frmts/georaster/frmt_georaster.html
index 6f95498..f227a9a 100644
--- a/frmts/georaster/frmt_georaster.html
+++ b/frmts/georaster/frmt_georaster.html
@@ -1,281 +1,281 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html><head>
-  <title>GeoRaster --- Oracle Spatial GeoRaster</title>
-  <meta http-equiv="CONTENT-TYPE" content="text/html; charset=UTF-8">
-  <meta name="GENERATOR" content="OpenOffice.org 2.4  (Linux)">
-  <style type="text/css">
-	<!--
-		@page { size: 8.5in 11in; margin: 0.79in }
-		P { margin-bottom: 0.08in }
-	--></style>
-</head>
-<body bgcolor="#ffffff">
-<h1>Oracle Spatial GeoRaster</h1>
-<p>
-This driver supports reading and writing raster data in Oracle Spatial
-GeoRaster format (10g or later). The Oracle Spatial GeoRaster driver is
-optionally built as a GDAL plugin, but it requires Oracle client
-libraries.
-</p>
-<p>
-When opening a GeoRaster, it's name should be specified in the form:
-</p>
-<p style="font-family: Courier New,Courier,monospace; margin-left: 40px;">
-georaster:<user>{,/}<pwd>{,@}[db],[schema.][table],[column],[where]<br>
-georaster:<user>{,/}<pwd>{,@}[db],<rdt>,<rid></p>
-<p>Where:</p>
-<p style="font-family: Courier New,Courier,monospace; margin-left: 40px;">
-user   = Oracle server user's name login<br>
-pwd    = user password<br>
-db     = Oracle server identification (database name)<br>
-schema = name of a schema                      <br>
-table  = name of a GeoRaster table (table that
-contains GeoRaster columns)<br>
-column = name of a column data type MDSYS.SDO_GEORASTER<br>
-where  = a simple where clause to identify one or multiples
-GeoRaster(s)<br>
-rdt    = name of a raster data table<br>
-rid    = numeric identification of one GeoRaster</p>
-<p>Examples:</p>
-<p style="font-family: Courier New,Courier,monospace; margin-left: 40px;">geor:scott,tiger,demodb,table,column,id=1<br>
-geor:scott,tiger,demodb,table,column,"id = 1"<br>
-"georaster:scott/tiger at demodb,table,column,gain>10"<br>
-"georaster:scott/tiger at demodb,table,column,city='Brasilia'"<br>
-georaster:scott,tiger,,rdt_10$,10<br>
-geor:scott/tiger,,rdt_10$,10</p>
-<p>Note: do note use space around the field values and the commas.</p>
-<p>Note: like in the last two examples, the database name field could
-be left empty (",,") and the TNSNAME will be used.</p>
-<p>Note: If  the query results in more than one GeoRaster it will
-be treated as a GDAL metadata's list of sub-datasets (see bellow)</p>
-<h3>Browsing the database for GeoRasters
-<br>
-</h3>
-<p>By providing some basic information the
-GeoRaster driver is capable of listing the existing rasters stored on
-the server:</p>
-To list all the GeoRaster table
-on the server that belongs to that user name and database:
-<p style="margin-left: 40px;"><font face="Courier, monospace">%
-gdalinfo georaster:scott/tiger at db1</font></p>
-To list all the GeoRaster type columns that exist in that
-table:<br>
-<div style="margin-left: 40px;"><font face="Courier, monospace">%
-gdalinfo georaster:scott/tiger at db1,table_name</font></div>
-<p>That will list all the GeoRaster objects stored in that table.
-</p>
-<div style="margin-left: 40px;"><font face="Courier, monospace">%
-gdalinfo georaster:scott/tiger at db1,table_name,georaster_column</font></div>
-<p>That will list all the GeoRaster existing on that table according to
-a Where clause.
-</p>
-<div style="margin-left: 40px;"><font face="Courier, monospace">%
-gdalinfo
-georaster:scott/tiger at db1,table_name,georaster_column,city='Brasilia'</font></div>
-<br>
-Note that the result of those queries
-are returned as GDAL metadata sub-datasets, e.g.:
-<p style="margin-left: 40px;"><font face="Courier, monospace">%
-gdalinfo georaster:scott/tiger<br>
-Driver:
-GeoRaster/Oracle Spatial GeoRaster<br>
-Subdatasets:</font><br>
-<span style="background: transparent none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"><font face="Courier, monospace">
-SUBDATASET_1_NAME=georaster:scott,tiger,,LANDSAT<br>
-SUBDATASET_1_DESC=Table:LANDSAT<br>
-SUBDATASET_2_NAME=georaster:scott,tiger,,GDAL_IMPORT<br>
-SUBDATASET_2_DESC=Table:GDAL_IMPORT</font></span></p>
-<h3>Creation Options</h3>
-<ul>
-  <li><strong>BLOCKXSIZE</strong>: The number of pixel columns
-on raster block. </li>
-  <li> <strong>BLOCKYSIZE</strong>: The number of pixel rows
-on raster block. </li>
-  <li> <strong>BLOCKBSIZE</strong>: The number of
-bands on raster block.</li>
-  <li> <strong>BLOCKING</strong>: Decline the use of blocking (NO) or request an automatic blocking size (OPTIMUM).</li>
-  <li><span style="font-weight: bold;">SRID</span>: Assign a specific
-EPSG projection/reference system identification to the GeoRaster.</li>
-  <li><strong>INTERLEAVE</strong>: Band interleaving mode, BAND, LINE,
-PIXEL (or BSQ, BIL, BIP) for band sequential, Line or Pixel
-interleaving. </li>
-  <li><strong>DESCRIPTION</strong>: A simple description of a newly
-created table in SQL syntax. If the table already exist, this create
-option will be ignored, e.g.:</li>
-</ul>
-<span style="font-family: Courier New,Courier,monospace;">%
-gdal_translate -of georaster landsat_823.tif
-geor:scott/tiger at orcl,landsat,raster \<br>
-  -co DESCRIPTION="(ID NUMBER, NAME VARCHAR2(40), RASTER
-MDSYS.SDO_GEORASTER)" \<br>
-  -co INSERT="VALUES (1,'Scene 823',</span><span style="font-family: Courier New,Courier,monospace;"></span><span style="font-family: Courier New,Courier,monospace;">SDO_GEOR.INIT()</span><span style="font-family: Courier New,Courier,monospace;"></span><span style="font-family: Courier New,Courier,monospace;">)"</span>
-<ul>
-  <li><strong>INSERT</strong>: A simple SQL insert/values clause to
-inform the driver what values to fill up when inserting a new row on
-the table, e.g.:</li>
-</ul>
-<span style="font-family: Courier New,Courier,monospace;">%
-gdal_translate -of georaster landsat_825.tif
-geor:scott/tiger at orcl,landsat,raster \<br>
-  -co INSERT="(ID, RASTER) VALUES (2,</span><span style="font-family: Courier New,Courier,monospace;"></span><span style="font-family: Courier New,Courier,monospace;">SDO_GEOR.INIT()</span><span style="font-family: Courier New,Courier,monospace;"></span><span style="font-family: Courier New,Courier,monospace;">)"</span><br>
-<ul>
-  <li><strong>COMPRESS</strong>: Compression options, JPEG-F,
-DEFLATE or NONE. The two JPEG options are lossy, meaning that the
-original pixel values are changed.</li>
-  <li><strong>GENPYRAMID</strong>: Generate pyramid after a GeoRaster object have been loaded to the database. 
-The content of that parameter must be the resampling method of 
-choice NN (nearest neighbor) , BILINEAR, BIQUADRATIC, CUBIC, AVERAGE4 or AVERAGE16. If GENPYRLEVELS is not 
-informed the PL/SQL function sdo_geor.generatePyramid will calculate the number of levels to generate.</li>
-  <li><strong>GENPYRLEVELS</strong>: Define the number of pyramid levels to be generated.
-If GENPYRAMID is not informed the resample method NN (nearest neighbor) will apply.</li>
-  <li><strong>QUALITY</strong>: Quality compression option for JPEG 
-ranging from 0 to 100. The default is 75.</li>
-  <li><strong>NBITS</strong>: Sub byte data type, options: 1, 2 or 4.</li>
-  <li><strong>SPATIALEXTENT</strong>: Generate Spatial Extents. The default for that options is 
-TRUE, that means that this option only need to be informed to force the Spatial Extent to 
-remain as NULL. If EXTENTSRID is not informed the Spatial Extent geometry will be generated with 
-the same SRID as the GeoGeoraster object.</li>
-  <li><strong>EXTENTSRID</strong>: SRID code to be used on the Spatial Extent geometry. 
-If the table/column has already a spatial extent, the value informed should be the same as the 
-SRID on the Spatial Extent of the other existing GeoRaster.</li>
-  <li><strong>OBJECTTABLE</strong>: To create RDT as SDO_RASTER object inform TRUE otherwise, the default 
-  is FALSE and the RDT will be created as regular relational tables. That does not apply for Oracle version older than 11.</li>
-</ul>
-<strong></strong>
-<h3>Importing GeoRaster</h3>
-<p style="margin-bottom: 0in;">During the process of importing raster
-into a GeoRaster object it is possible to give the driver a simple SQL
-table
-definition and also a SQL insert/values clause to inform the driver
-about the table to be created and the values to be added to the newly
-created row. The following example does that:</p>
-<p style="margin-bottom: 0in;"><font face="Courier, monospace">%
-gdal_translate -of georaster Newpor.tif georaster:scott/tiger,,landsat,scene
-\<br>
-  -co
-"DESCRIPTION=(ID NUMBER, SITE VARCHAR2(45), SCENE
-MDSYS.SDO_GEORASTER)" \<br>
-</font><font face="Courier, monospace">
-  -co "INSERT=VALUES(1,'West fields', </font><span style="font-family: Courier New,Courier,monospace;">SDO_GEOR.INIT()</span><font face="Courier, monospace">)" \<br>
-</font><font face="Courier, monospace">  -co "BLOCKXSIZE=512</font><span style="font-family: Courier New,Courier,monospace;"></span><font face="Courier, monospace">" -co "BLOCKYSIZE=512" -co "BLOCKBSIZE=3" \<br>
-  -co "INTERLEAVE=PIXEL</font><span style="font-family: Courier New,Courier,monospace;"></span><font face="Courier, monospace">" -co "COMPRESS=JPEG-F"</font></p>
-<p style="margin-bottom: 0in;">Note that the create option DESCRIPTION
-requires to inform table name (in bold). And column name
-(underlined) should match the description:</p>
-<p style="margin-bottom: 0in;"><font face="Courier, monospace">%
-gdal_translate -of georaster landsat_1.tif georaster:scott/tiger,,<span style="font-weight: bold;">landsat</span>,<span style="text-decoration: underline;">scene</span>
-\<br>
-  -co
-"DESCRIPTION=(ID NUMBER, SITE VARCHAR2(45), <span style="text-decoration: underline;">SCENE</span>
-MDSYS.SDO_GEORASTER)" \<br>
-  -co "INSERT=VALUES(1,'West fields', </font><span style="font-family: Courier New,Courier,monospace;">SDO_GEOR.INIT()</span><font face="Courier, monospace">)"</font></p>
-<p style="margin-bottom: 0in;">If the table "landsat" exist, the option
-"DESCRIPTION" is ignored. The driver can only
-update one GeoRaster column per run of gdal_translate. Oracle create
-default names and values for RDT and RID during the initialization of
-the SDO_GEORASTER object but user are also able to specify a name and
-value of their choice.</p>
-<p style="margin-bottom: 0in;"><font face="Courier, monospace">%
-gdal_translate -of georaster
-landsat_1.tif georaster:scott/tiger,,landsat,scene
-\<br>
-  -co "INSERT=VALUES(10,'Main building', </font><span style="font-family: Courier New,Courier,monospace;">SDO_GEOR.INIT('RDT',
-10)</span><font face="Courier, monospace">)"</font></p>
-<p style="margin-bottom: 0in;">If no information is given about where
-to store the raster the driver will create (if doesn't exist already)
-a default table named GDAL_IMPORT with just one GeoRaster column
-named RASTER and a table GDAL_RDT as the RDT, the RID will be given automatically by the server, example:</p>
-<p style="margin-bottom: 0in;"><font face="Courier, monospace">%
-gdal_translate -of georaster input.tif
-“geor:scott/tiger at dbdemo”</font><br>
-</p>
-<h3>Exporting GeoRaster</h3>
-A GeoRaster can be identified by a Where clause or by a pair of RDT
-& RID:<br>
-<br>
-<span style="font-family: Courier New,Courier,monospace;">%
-gdal_translate -of gtiff geor:scott/tiger at dbdemo,landsat,scene,id=54
-output.tif<br>
-</span><span style="font-family: Courier New,Courier,monospace;">%
-gdal_translate -of gtiff geor:scott/tiger at dbdemo,st_rdt_1,130 output.tif<br>
-</span>
-<h3>Cross schema access</h3>
-As long as the user was granted full access the GeoRaster table and the
-Raster Data Table, e.g.:<br>
-<br>
-<span style="font-family: Courier New,Courier,monospace;">% sqlplus
-scott/tiger<br>
-SQL> grant select,insert,update,delete on gdal_import to spock;<br>
-</span><span style="font-family: Courier New,Courier,monospace;">SQL>
-grant select,insert,update,delete on gdal_rdt to spock;<br>
-</span><br>
-It is possible to an user access to extract and load GeoRaster from
-another user/schema by informing the schema name as showed here:<br>
-<br>
-Browsing:<br>
-<br>
-<span style="font-family: Courier New,Courier,monospace;">% gdalinfo
-geor:spock/lion at orcl,scott.<br>
-% </span><span style="font-family: Courier New,Courier,monospace;">gdalinfo
-geor:spock/lion at orcl,</span><span style="font-family: Courier New,Courier,monospace;">scott</span><span style="font-family: Courier New,Courier,monospace;">.gdal_import,raster,"t.raster.rasterid >
-100"</span><br>
-<span style="font-family: Courier New,Courier,monospace;">% </span><span style="font-family: Courier New,Courier,monospace;">gdalinfo
-geor:spock/lion at orcl,</span><span style="font-family: Courier New,Courier,monospace;">scott</span><span style="font-family: Courier New,Courier,monospace;">.gdal_import,raster,</span><span style="font-family: Courier New,Courier,monospace;">t.raster.rasterid=101<br>
-<br>
-</span>Extracting:<br>
-<br>
-<span style="font-family: Courier New,Courier,monospace;">%
-gdal_translate </span><span style="font-family: Courier New,Courier,monospace;">geor:spock/lion at orcl,</span><span style="font-family: Courier New,Courier,monospace;">scott</span><span style="font-family: Courier New,Courier,monospace;">.</span><span style="font-family: Courier New,Courier,monospace;">gdal_import,raster,</span><span style="font-family: Courier New,Courier,monospace;">t.raster.rasterid=101</span><span style="font-family: Courier New,Courier,monospace;"> out.tif</span> [...]
-</span><span style="font-family: Courier New,Courier,monospace;">%
-gdal_translate </span><span style="font-family: Courier New,Courier,monospace;">geor:spock/lion at orcl,gdal_rdt,101
-out.tif<br>
-<br>
-</span>Note: On the above example that acessing by RDT/RID doesn't
-need schame name as long as the users is granted full acess to both
-tables.<br>
-<br>
-Loading:<br>
-<br>
-<span style="font-family: Courier New,Courier,monospace;">%
-gdal_translate -of georaster input.tif </span><span style="font-family: Courier New,Courier,monospace;">geor:spock/lion at orcl,</span><span style="font-family: Courier New,Courier,monospace;">scott</span><span style="font-family: Courier New,Courier,monospace;">.</span><span style="font-family: Courier New,Courier,monospace;"></span><span style="font-family: Courier New,Courier,monospace;"></span><span style="font-family: Courier New,Courier,monospace;"><br>
-</span><span style="font-family: Courier New,Courier,monospace;">%
-gdal_translate </span><span style="font-family: Courier New,Courier,monospace;">-of georaster
-input.tif geor:spock/lion at orcl,</span><span style="font-family: Courier New,Courier,monospace;">scott</span><span style="font-family: Courier New,Courier,monospace;">.</span><span style="font-family: Courier New,Courier,monospace;">cities,image \<br>
-  -co INSERT="(1,'Rio de Janeiro',sdo_geor.init('cities_rdt'))"</span><span style="font-family: Courier New,Courier,monospace;"></span><br>
-<h3>General use of GeoRaster</h3>
-GeoRaster can be used in any GDAL command line tool with all the
-available options. Like a image subset extraction or re-project:<br>
-<br>
-<span style="font-family: Courier New,Courier,monospace;">%
-gdal_translate -of gtiff geor:scott/tiger at dbdemo,landsat,scene,id=54
-output.tif \<br>
-  -srcwin 0 0 800 600<br>
-<br>
-</span><span style="font-family: Courier New,Courier,monospace;">%
-gdalwarp -of png geor:scott/tiger at dbdemo,st_rdt_1,130 output.png -t_srs
-EPSG:9000913<br>
-<br>
-</span>Two different GeoRaster can be used as input and output on the
-same operation:<br>
-<br>
-<span style="font-family: Courier New,Courier,monospace;">%
-gdal_translate -of georaster
-geor:scott/tiger at dbdemo,landsat,scene,id=54
-geor:scott/tiger at proj1,projview,image -co INSERT="VALUES (102, </span><span style="font-family: Courier New,Courier,monospace;">SDO_GEOR.INIT()</span><span style="font-family: Courier New,Courier,monospace;">)"<br>
-<br>
-</span>
-Applications that use GDAL can theoretically read and write from
-GeoRaster just like any other format but most of then are more inclined
-to try to access files on the file system so one alternative is to
-create VRT to represent the GeoRaster description, e.g.:<br>
-<br>
-<span style="font-family: Courier New,Courier,monospace;">%
-gdal_translate -of VRT
-geor:scott/tiger at dbdemo,landsat,scene,id=54 view_54.vrt<br>
-% openenv view_54.vrt<br>
-<br>
-</span><span style="font-family: Courier New,Courier,monospace;"></span><br>
-<h3></h3>
-
-
-</body></html>
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head>
+  <title>GeoRaster --- Oracle Spatial GeoRaster</title>
+  <meta http-equiv="CONTENT-TYPE" content="text/html; charset=UTF-8">
+  <meta name="GENERATOR" content="OpenOffice.org 2.4  (Linux)">
+  <style type="text/css">
+	<!--
+		@page { size: 8.5in 11in; margin: 0.79in }
+		P { margin-bottom: 0.08in }
+	--></style>
+</head>
+<body bgcolor="#ffffff">
+<h1>Oracle Spatial GeoRaster</h1>
+<p>
+This driver supports reading and writing raster data in Oracle Spatial
+GeoRaster format (10g or later). The Oracle Spatial GeoRaster driver is
+optionally built as a GDAL plugin, but it requires Oracle client
+libraries.
+</p>
+<p>
+When opening a GeoRaster, it's name should be specified in the form:
+</p>
+<p style="font-family: Courier New,Courier,monospace; margin-left: 40px;">
+georaster:<user>{,/}<pwd>{,@}[db],[schema.][table],[column],[where]<br>
+georaster:<user>{,/}<pwd>{,@}[db],<rdt>,<rid></p>
+<p>Where:</p>
+<p style="font-family: Courier New,Courier,monospace; margin-left: 40px;">
+user   = Oracle server user's name login<br>
+pwd    = user password<br>
+db     = Oracle server identification (database name)<br>
+schema = name of a schema                      <br>
+table  = name of a GeoRaster table (table that
+contains GeoRaster columns)<br>
+column = name of a column data type MDSYS.SDO_GEORASTER<br>
+where  = a simple where clause to identify one or multiples
+GeoRaster(s)<br>
+rdt    = name of a raster data table<br>
+rid    = numeric identification of one GeoRaster</p>
+<p>Examples:</p>
+<p style="font-family: Courier New,Courier,monospace; margin-left: 40px;">geor:scott,tiger,demodb,table,column,id=1<br>
+geor:scott,tiger,demodb,table,column,"id = 1"<br>
+"georaster:scott/tiger at demodb,table,column,gain>10"<br>
+"georaster:scott/tiger at demodb,table,column,city='Brasilia'"<br>
+georaster:scott,tiger,,rdt_10$,10<br>
+geor:scott/tiger,,rdt_10$,10</p>
+<p>Note: do note use space around the field values and the commas.</p>
+<p>Note: like in the last two examples, the database name field could
+be left empty (",,") and the TNSNAME will be used.</p>
+<p>Note: If  the query results in more than one GeoRaster it will
+be treated as a GDAL metadata's list of sub-datasets (see below)</p>
+<h3>Browsing the database for GeoRasters
+<br>
+</h3>
+<p>By providing some basic information the
+GeoRaster driver is capable of listing the existing rasters stored on
+the server:</p>
+To list all the GeoRaster table
+on the server that belongs to that user name and database:
+<p style="margin-left: 40px;"><font face="Courier, monospace">%
+gdalinfo georaster:scott/tiger at db1</font></p>
+To list all the GeoRaster type columns that exist in that
+table:<br>
+<div style="margin-left: 40px;"><font face="Courier, monospace">%
+gdalinfo georaster:scott/tiger at db1,table_name</font></div>
+<p>That will list all the GeoRaster objects stored in that table.
+</p>
+<div style="margin-left: 40px;"><font face="Courier, monospace">%
+gdalinfo georaster:scott/tiger at db1,table_name,georaster_column</font></div>
+<p>That will list all the GeoRaster existing on that table according to
+a Where clause.
+</p>
+<div style="margin-left: 40px;"><font face="Courier, monospace">%
+gdalinfo
+georaster:scott/tiger at db1,table_name,georaster_column,city='Brasilia'</font></div>
+<br>
+Note that the result of those queries
+are returned as GDAL metadata sub-datasets, e.g.:
+<p style="margin-left: 40px;"><font face="Courier, monospace">%
+gdalinfo georaster:scott/tiger<br>
+Driver:
+GeoRaster/Oracle Spatial GeoRaster<br>
+Subdatasets:</font><br>
+<span style="background: transparent none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"><font face="Courier, monospace">
+SUBDATASET_1_NAME=georaster:scott,tiger,,LANDSAT<br>
+SUBDATASET_1_DESC=Table:LANDSAT<br>
+SUBDATASET_2_NAME=georaster:scott,tiger,,GDAL_IMPORT<br>
+SUBDATASET_2_DESC=Table:GDAL_IMPORT</font></span></p>
+<h3>Creation Options</h3>
+<ul>
+  <li><strong>BLOCKXSIZE</strong>: The number of pixel columns
+on raster block. </li>
+  <li> <strong>BLOCKYSIZE</strong>: The number of pixel rows
+on raster block. </li>
+  <li> <strong>BLOCKBSIZE</strong>: The number of
+bands on raster block.</li>
+  <li> <strong>BLOCKING</strong>: Decline the use of blocking (NO) or request an automatic blocking size (OPTIMUM).</li>
+  <li><span style="font-weight: bold;">SRID</span>: Assign a specific
+EPSG projection/reference system identification to the GeoRaster.</li>
+  <li><strong>INTERLEAVE</strong>: Band interleaving mode, BAND, LINE,
+PIXEL (or BSQ, BIL, BIP) for band sequential, Line or Pixel
+interleaving. </li>
+  <li><strong>DESCRIPTION</strong>: A simple description of a newly
+created table in SQL syntax. If the table already exist, this create
+option will be ignored, e.g.:</li>
+</ul>
+<span style="font-family: Courier New,Courier,monospace;">%
+gdal_translate -of georaster landsat_823.tif
+geor:scott/tiger at orcl,landsat,raster \<br>
+  -co DESCRIPTION="(ID NUMBER, NAME VARCHAR2(40), RASTER
+MDSYS.SDO_GEORASTER)" \<br>
+  -co INSERT="VALUES (1,'Scene 823',</span><span style="font-family: Courier New,Courier,monospace;"></span><span style="font-family: Courier New,Courier,monospace;">SDO_GEOR.INIT()</span><span style="font-family: Courier New,Courier,monospace;"></span><span style="font-family: Courier New,Courier,monospace;">)"</span>
+<ul>
+  <li><strong>INSERT</strong>: A simple SQL insert/values clause to
+inform the driver what values to fill up when inserting a new row on
+the table, e.g.:</li>
+</ul>
+<span style="font-family: Courier New,Courier,monospace;">%
+gdal_translate -of georaster landsat_825.tif
+geor:scott/tiger at orcl,landsat,raster \<br>
+  -co INSERT="(ID, RASTER) VALUES (2,</span><span style="font-family: Courier New,Courier,monospace;"></span><span style="font-family: Courier New,Courier,monospace;">SDO_GEOR.INIT()</span><span style="font-family: Courier New,Courier,monospace;"></span><span style="font-family: Courier New,Courier,monospace;">)"</span><br>
+<ul>
+  <li><strong>COMPRESS</strong>: Compression options, JPEG-F,
+DEFLATE or NONE. The two JPEG options are lossy, meaning that the
+original pixel values are changed.</li>
+  <li><strong>GENPYRAMID</strong>: Generate pyramid after a GeoRaster object have been loaded to the database.
+The content of that parameter must be the resampling method of
+choice NN (nearest neighbor) , BILINEAR, BIQUADRATIC, CUBIC, AVERAGE4 or AVERAGE16. If GENPYRLEVELS is not
+informed the PL/SQL function sdo_geor.generatePyramid will calculate the number of levels to generate.</li>
+  <li><strong>GENPYRLEVELS</strong>: Define the number of pyramid levels to be generated.
+If GENPYRAMID is not informed the resample method NN (nearest neighbor) will apply.</li>
+  <li><strong>QUALITY</strong>: Quality compression option for JPEG
+ranging from 0 to 100. The default is 75.</li>
+  <li><strong>NBITS</strong>: Sub byte data type, options: 1, 2 or 4.</li>
+  <li><strong>SPATIALEXTENT</strong>: Generate Spatial Extents. The default for that options is
+TRUE, that means that this option only need to be informed to force the Spatial Extent to
+remain as NULL. If EXTENTSRID is not informed the Spatial Extent geometry will be generated with
+the same SRID as the GeoGeoraster object.</li>
+  <li><strong>EXTENTSRID</strong>: SRID code to be used on the Spatial Extent geometry.
+If the table/column has already a spatial extent, the value informed should be the same as the
+SRID on the Spatial Extent of the other existing GeoRaster.</li>
+  <li><strong>OBJECTTABLE</strong>: To create RDT as SDO_RASTER object inform TRUE otherwise, the default
+  is FALSE and the RDT will be created as regular relational tables. That does not apply for Oracle version older than 11.</li>
+</ul>
+<strong></strong>
+<h3>Importing GeoRaster</h3>
+<p style="margin-bottom: 0in;">During the process of importing raster
+into a GeoRaster object it is possible to give the driver a simple SQL
+table
+definition and also a SQL insert/values clause to inform the driver
+about the table to be created and the values to be added to the newly
+created row. The following example does that:</p>
+<p style="margin-bottom: 0in;"><font face="Courier, monospace">%
+gdal_translate -of georaster Newpor.tif georaster:scott/tiger,,landsat,scene
+\<br>
+  -co
+"DESCRIPTION=(ID NUMBER, SITE VARCHAR2(45), SCENE
+MDSYS.SDO_GEORASTER)" \<br>
+</font><font face="Courier, monospace">
+  -co "INSERT=VALUES(1,'West fields', </font><span style="font-family: Courier New,Courier,monospace;">SDO_GEOR.INIT()</span><font face="Courier, monospace">)" \<br>
+</font><font face="Courier, monospace">  -co "BLOCKXSIZE=512</font><span style="font-family: Courier New,Courier,monospace;"></span><font face="Courier, monospace">" -co "BLOCKYSIZE=512" -co "BLOCKBSIZE=3" \<br>
+  -co "INTERLEAVE=PIXEL</font><span style="font-family: Courier New,Courier,monospace;"></span><font face="Courier, monospace">" -co "COMPRESS=JPEG-F"</font></p>
+<p style="margin-bottom: 0in;">Note that the create option DESCRIPTION
+requires to inform table name (in bold). And column name
+(underlined) should match the description:</p>
+<p style="margin-bottom: 0in;"><font face="Courier, monospace">%
+gdal_translate -of georaster landsat_1.tif georaster:scott/tiger,,<span style="font-weight: bold;">landsat</span>,<span style="text-decoration: underline;">scene</span>
+\<br>
+  -co
+"DESCRIPTION=(ID NUMBER, SITE VARCHAR2(45), <span style="text-decoration: underline;">SCENE</span>
+MDSYS.SDO_GEORASTER)" \<br>
+  -co "INSERT=VALUES(1,'West fields', </font><span style="font-family: Courier New,Courier,monospace;">SDO_GEOR.INIT()</span><font face="Courier, monospace">)"</font></p>
+<p style="margin-bottom: 0in;">If the table "landsat" exist, the option
+"DESCRIPTION" is ignored. The driver can only
+update one GeoRaster column per run of gdal_translate. Oracle create
+default names and values for RDT and RID during the initialization of
+the SDO_GEORASTER object but user are also able to specify a name and
+value of their choice.</p>
+<p style="margin-bottom: 0in;"><font face="Courier, monospace">%
+gdal_translate -of georaster
+landsat_1.tif georaster:scott/tiger,,landsat,scene
+\<br>
+  -co "INSERT=VALUES(10,'Main building', </font><span style="font-family: Courier New,Courier,monospace;">SDO_GEOR.INIT('RDT',
+10)</span><font face="Courier, monospace">)"</font></p>
+<p style="margin-bottom: 0in;">If no information is given about where
+to store the raster the driver will create (if doesn't exist already)
+a default table named GDAL_IMPORT with just one GeoRaster column
+named RASTER and a table GDAL_RDT as the RDT, the RID will be given automatically by the server, example:</p>
+<p style="margin-bottom: 0in;"><font face="Courier, monospace">%
+gdal_translate -of georaster input.tif
+“geor:scott/tiger at dbdemo”</font><br>
+</p>
+<h3>Exporting GeoRaster</h3>
+A GeoRaster can be identified by a Where clause or by a pair of RDT
+& RID:<br>
+<br>
+<span style="font-family: Courier New,Courier,monospace;">%
+gdal_translate -of gtiff geor:scott/tiger at dbdemo,landsat,scene,id=54
+output.tif<br>
+</span><span style="font-family: Courier New,Courier,monospace;">%
+gdal_translate -of gtiff geor:scott/tiger at dbdemo,st_rdt_1,130 output.tif<br>
+</span>
+<h3>Cross schema access</h3>
+As long as the user was granted full access the GeoRaster table and the
+Raster Data Table, e.g.:<br>
+<br>
+<span style="font-family: Courier New,Courier,monospace;">% sqlplus
+scott/tiger<br>
+SQL> grant select,insert,update,delete on gdal_import to spock;<br>
+</span><span style="font-family: Courier New,Courier,monospace;">SQL>
+grant select,insert,update,delete on gdal_rdt to spock;<br>
+</span><br>
+It is possible to an user access to extract and load GeoRaster from
+another user/schema by informing the schema name as showed here:<br>
+<br>
+Browsing:<br>
+<br>
+<span style="font-family: Courier New,Courier,monospace;">% gdalinfo
+geor:spock/lion at orcl,scott.<br>
+% </span><span style="font-family: Courier New,Courier,monospace;">gdalinfo
+geor:spock/lion at orcl,</span><span style="font-family: Courier New,Courier,monospace;">scott</span><span style="font-family: Courier New,Courier,monospace;">.gdal_import,raster,"t.raster.rasterid >
+100"</span><br>
+<span style="font-family: Courier New,Courier,monospace;">% </span><span style="font-family: Courier New,Courier,monospace;">gdalinfo
+geor:spock/lion at orcl,</span><span style="font-family: Courier New,Courier,monospace;">scott</span><span style="font-family: Courier New,Courier,monospace;">.gdal_import,raster,</span><span style="font-family: Courier New,Courier,monospace;">t.raster.rasterid=101<br>
+<br>
+</span>Extracting:<br>
+<br>
+<span style="font-family: Courier New,Courier,monospace;">%
+gdal_translate </span><span style="font-family: Courier New,Courier,monospace;">geor:spock/lion at orcl,</span><span style="font-family: Courier New,Courier,monospace;">scott</span><span style="font-family: Courier New,Courier,monospace;">.</span><span style="font-family: Courier New,Courier,monospace;">gdal_import,raster,</span><span style="font-family: Courier New,Courier,monospace;">t.raster.rasterid=101</span><span style="font-family: Courier New,Courier,monospace;"> out.tif</span> [...]
+</span><span style="font-family: Courier New,Courier,monospace;">%
+gdal_translate </span><span style="font-family: Courier New,Courier,monospace;">geor:spock/lion at orcl,gdal_rdt,101
+out.tif<br>
+<br>
+</span>Note: On the above example that accessing by RDT/RID doesn't
+need schame name as long as the users is granted full access to both
+tables.<br>
+<br>
+Loading:<br>
+<br>
+<span style="font-family: Courier New,Courier,monospace;">%
+gdal_translate -of georaster input.tif </span><span style="font-family: Courier New,Courier,monospace;">geor:spock/lion at orcl,</span><span style="font-family: Courier New,Courier,monospace;">scott</span><span style="font-family: Courier New,Courier,monospace;">.</span><span style="font-family: Courier New,Courier,monospace;"></span><span style="font-family: Courier New,Courier,monospace;"></span><span style="font-family: Courier New,Courier,monospace;"><br>
+</span><span style="font-family: Courier New,Courier,monospace;">%
+gdal_translate </span><span style="font-family: Courier New,Courier,monospace;">-of georaster
+input.tif geor:spock/lion at orcl,</span><span style="font-family: Courier New,Courier,monospace;">scott</span><span style="font-family: Courier New,Courier,monospace;">.</span><span style="font-family: Courier New,Courier,monospace;">cities,image \<br>
+  -co INSERT="(1,'Rio de Janeiro',sdo_geor.init('cities_rdt'))"</span><span style="font-family: Courier New,Courier,monospace;"></span><br>
+<h3>General use of GeoRaster</h3>
+GeoRaster can be used in any GDAL command line tool with all the
+available options. Like a image subset extraction or re-project:<br>
+<br>
+<span style="font-family: Courier New,Courier,monospace;">%
+gdal_translate -of gtiff geor:scott/tiger at dbdemo,landsat,scene,id=54
+output.tif \<br>
+  -srcwin 0 0 800 600<br>
+<br>
+</span><span style="font-family: Courier New,Courier,monospace;">%
+gdalwarp -of png geor:scott/tiger at dbdemo,st_rdt_1,130 output.png -t_srs
+EPSG:9000913<br>
+<br>
+</span>Two different GeoRaster can be used as input and output on the
+same operation:<br>
+<br>
+<span style="font-family: Courier New,Courier,monospace;">%
+gdal_translate -of georaster
+geor:scott/tiger at dbdemo,landsat,scene,id=54
+geor:scott/tiger at proj1,projview,image -co INSERT="VALUES (102, </span><span style="font-family: Courier New,Courier,monospace;">SDO_GEOR.INIT()</span><span style="font-family: Courier New,Courier,monospace;">)"<br>
+<br>
+</span>
+Applications that use GDAL can theoretically read and write from
+GeoRaster just like any other format but most of then are more inclined
+to try to access files on the file system so one alternative is to
+create VRT to represent the GeoRaster description, e.g.:<br>
+<br>
+<span style="font-family: Courier New,Courier,monospace;">%
+gdal_translate -of VRT
+geor:scott/tiger at dbdemo,landsat,scene,id=54 view_54.vrt<br>
+% openenv view_54.vrt<br>
+<br>
+</span><span style="font-family: Courier New,Courier,monospace;"></span><br>
+<h3></h3>
+
+
+</body></html>
diff --git a/frmts/georaster/georaster_dataset.cpp b/frmts/georaster/georaster_dataset.cpp
index 21ca864..bec6437 100644
--- a/frmts/georaster/georaster_dataset.cpp
+++ b/frmts/georaster/georaster_dataset.cpp
@@ -31,15 +31,12 @@
 
 #include "cpl_error.h"
 
-#include "ogr_spatialref.h"
-
 #include "gdal.h"
+#include "gdal_frmts.h"
 #include "gdal_priv.h"
-#include "georaster_priv.h"
+#include "ogr_spatialref.h"
 
-CPL_C_START
-void CPL_DLL GDALRegister_GEOR(void);
-CPL_C_END
+#include "georaster_priv.h"
 
 //  ---------------------------------------------------------------------------
 //                                                           GeoRasterDataset()
@@ -84,7 +81,7 @@ GeoRasterDataset::~GeoRasterDataset()
     {
         delete poMaskBand;
     }
-    
+
     CPLFree( pszProjection );
     CSLDestroy( papszSubdatasets );
 }
@@ -101,8 +98,8 @@ int GeoRasterDataset::Identify( GDALOpenInfo* poOpenInfo )
 
     char* pszFilename = poOpenInfo->pszFilename;
 
-    if( EQUALN( pszFilename, "georaster:", 10 ) == false &&
-        EQUALN( pszFilename, "geor:", 5 )       == false )
+    if( STARTS_WITH_CI(pszFilename, "georaster:") == false &&
+        STARTS_WITH_CI(pszFilename, "geor:")       == false )
     {
         return false;
     }
@@ -117,7 +114,7 @@ int GeoRasterDataset::Identify( GDALOpenInfo* poOpenInfo )
 GDALDataset* GeoRasterDataset::Open( GDALOpenInfo* poOpenInfo )
 {
     //  -------------------------------------------------------------------
-    //  It shouldn't have an open file pointer
+    //  It should not have an open file pointer.
     //  -------------------------------------------------------------------
 
     if( poOpenInfo->fpL != NULL )
@@ -215,10 +212,10 @@ GDALDataset* GeoRasterDataset::Open( GDALOpenInfo* poOpenInfo )
 
         for( i = 0; i < n; i++ )
         {
-            if ( EQUALN( papszRPC_MD[i], "MIN_LAT", 7 )  ||
-                 EQUALN( papszRPC_MD[i], "MIN_LONG", 8 ) ||
-                 EQUALN( papszRPC_MD[i], "MAX_LAT", 7 )  ||
-                 EQUALN( papszRPC_MD[i], "MAX_LONG", 8 ) )
+            if ( STARTS_WITH_CI(papszRPC_MD[i], "MIN_LAT")  ||
+                 STARTS_WITH_CI(papszRPC_MD[i], "MIN_LONG") ||
+                 STARTS_WITH_CI(papszRPC_MD[i], "MAX_LAT")  ||
+                 STARTS_WITH_CI(papszRPC_MD[i], "MAX_LONG") )
             {
                 continue;
             }
@@ -242,7 +239,7 @@ GDALDataset* GeoRasterDataset::Open( GDALOpenInfo* poOpenInfo )
     {
         poGRD->poMaskBand = new GeoRasterRasterBand( poGRD, 0, DEFAULT_BMP_MASK );
     }
-    
+
     //  -------------------------------------------------------------------
     //  Check for filter Nodata environment variable, default is YES
     //  -------------------------------------------------------------------
@@ -294,7 +291,7 @@ GDALDataset* GeoRasterDataset::Open( GDALOpenInfo* poOpenInfo )
     poGRD->SetMetadataItem( "COMPRESSION", CPLGetXMLValue( poGRW->phMetadata,
         "rasterInfo.compression.type", "NONE" ), "IMAGE_STRUCTURE" );
 
-    if( EQUALN( poGRW->sCompressionType.c_str(), "JPEG", 4 ) )
+    if( STARTS_WITH_CI(poGRW->sCompressionType.c_str(), "JPEG") )
     {
         poGRD->SetMetadataItem( "COMPRESS_QUALITY",
             CPLGetXMLValue( poGRW->phMetadata,
@@ -358,7 +355,7 @@ GDALDataset* GeoRasterDataset::Open( GDALOpenInfo* poOpenInfo )
 GDALDataset *GeoRasterDataset::Create( const char *pszFilename,
                                        int nXSize,
                                        int nYSize,
-                                       int nBands, 
+                                       int nBands,
                                        GDALDataType eType,
                                        char **papszOptions )
 {
@@ -479,7 +476,7 @@ GDALDataset *GeoRasterDataset::Create( const char *pszFilename,
     pszFetched = CSLFetchNameValue( papszOptions, "COMPRESS" );
 
     if( pszFetched != NULL &&
-        ( EQUALN( pszFetched, "JPEG", 4 ) ||
+        ( STARTS_WITH_CI(pszFetched, "JPEG") ||
           EQUAL( pszFetched, "DEFLATE" ) ) )
     {
         poGRW->sCompressionType = pszFetched;
@@ -541,17 +538,17 @@ GDALDataset *GeoRasterDataset::Create( const char *pszFilename,
         }
     }
 
-    if( bInterleve_ind == false && 
-      ( poGRW->nBandBlockSize == 3 || poGRW->nBandBlockSize == 4 ) ) 
+    if( bInterleve_ind == false &&
+      ( poGRW->nBandBlockSize == 3 || poGRW->nBandBlockSize == 4 ) )
     {
       poGRW->sInterleaving = "BIP";
     }
 
-    if( EQUALN( poGRW->sCompressionType.c_str(), "JPEG", 4 ) )
+    if( STARTS_WITH_CI(poGRW->sCompressionType.c_str(), "JPEG") )
     {
         if( ! EQUAL( poGRW->sInterleaving.c_str(), "BIP" ) )
         {
-            CPLError( CE_Warning, CPLE_IllegalArg, 
+            CPLError( CE_Warning, CPLE_IllegalArg,
                 "compress=JPEG assumes interleave=BIP" );
             poGRW->sInterleaving = "BIP";
         }
@@ -570,7 +567,7 @@ GDALDataset *GeoRasterDataset::Create( const char *pszFilename,
         {
             if( poGRW->poConnection->GetVersion() < 11 )
             {
-                CPLError( CE_Warning, CPLE_IllegalArg, 
+                CPLError( CE_Warning, CPLE_IllegalArg,
                     "BLOCKING=OPTIMALPADDING not supported on Oracle older than 11g" );
             }
             else
@@ -587,7 +584,7 @@ GDALDataset *GeoRasterDataset::Create( const char *pszFilename,
 
     if( pszDescription && poGRW->bUniqueFound )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg, 
+        CPLError( CE_Failure, CPLE_IllegalArg,
             "Option (DESCRIPTION) cannot be used on a existing GeoRaster." );
         delete poGRD;
         return NULL;
@@ -595,7 +592,7 @@ GDALDataset *GeoRasterDataset::Create( const char *pszFilename,
 
     if( pszInsert && poGRW->bUniqueFound )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg, 
+        CPLError( CE_Failure, CPLE_IllegalArg,
             "Option (INSERT) cannot be used on a existing GeoRaster." );
         delete poGRD;
         return NULL;
@@ -621,7 +618,7 @@ GDALDataset *GeoRasterDataset::Create( const char *pszFilename,
          */
         if( eType != GDT_Byte )
         {
-            CPLError( CE_Failure, CPLE_IllegalArg, 
+            CPLError( CE_Failure, CPLE_IllegalArg,
                 "Option (COMPRESS=%s) can only be used with Byte data type.",
                 poGRW->sCompressionType.c_str() );
             delete poGRD;
@@ -645,14 +642,13 @@ GDALDataset *GeoRasterDataset::Create( const char *pszFilename,
             return NULL;
         }
 
-        /* There is a limite on how big a compressed block can be.
-         */
-        if( ( poGRW->nColumnBlockSize * 
+        // There is a limit on how big a compressed block can be.
+        if( ( poGRW->nColumnBlockSize *
               poGRW->nRowBlockSize *
               poGRW->nBandBlockSize *
               ( GDALGetDataTypeSize( eType ) / 8 ) ) > ( 50 * 1024 * 1024 ) )
         {
-            CPLError( CE_Failure, CPLE_IllegalArg, 
+            CPLError( CE_Failure, CPLE_IllegalArg,
                 "Option (COMPRESS=%s) each data block must not exceed 50Mb. "
                 "Consider reducing BLOCK{X,Y,B}XSIZE.",
                 poGRW->sCompressionType.c_str() );
@@ -663,12 +659,12 @@ GDALDataset *GeoRasterDataset::Create( const char *pszFilename,
 
     if( EQUAL( poGRW->sCompressionType.c_str(), "DEFLATE" ) )
     {
-        if( ( poGRW->nColumnBlockSize * 
+        if( ( poGRW->nColumnBlockSize *
               poGRW->nRowBlockSize *
               poGRW->nBandBlockSize *
               ( GDALGetDataTypeSize( eType ) / 8 ) ) > ( 1024 * 1024 * 1024 ) )
         {
-            CPLError( CE_Failure, CPLE_IllegalArg, 
+            CPLError( CE_Failure, CPLE_IllegalArg,
                 "For (COMPRESS=%s) each data block must not exceed 1Gb. "
                 "Consider reducing BLOCK{X,Y,B}XSIZE.",
                 poGRW->sCompressionType.c_str() );
@@ -684,7 +680,7 @@ GDALDataset *GeoRasterDataset::Create( const char *pszFilename,
         int nVersion = poGRW->poConnection->GetVersion();
         if( nVersion <= 11 )
         {
-            CPLError( CE_Failure, CPLE_IllegalArg, 
+            CPLError( CE_Failure, CPLE_IllegalArg,
                 "Driver create-option OBJECTTABLE not "
                 "supported on Oracle %d", nVersion );
             delete poGRD;
@@ -692,8 +688,8 @@ GDALDataset *GeoRasterDataset::Create( const char *pszFilename,
         }
     }
 
-    poGRD->poGeoRaster->bCreateObjectTable = (bool)
-        CSLFetchBoolean( papszOptions, "OBJECTTABLE", FALSE );
+    poGRD->poGeoRaster->bCreateObjectTable = CPL_TO_BOOL(
+        CSLFetchBoolean( papszOptions, "OBJECTTABLE", FALSE ));
 
     //  -------------------------------------------------------------------
     //  Create a SDO_GEORASTER object on the server
@@ -709,7 +705,7 @@ GDALDataset *GeoRasterDataset::Create( const char *pszFilename,
         delete poGRD;
         return NULL;
     }
-    
+
     //  -------------------------------------------------------------------
     //  Prepare an identification string
     //  -------------------------------------------------------------------
@@ -733,7 +729,7 @@ GDALDataset *GeoRasterDataset::Create( const char *pszFilename,
     }
 
     //  -------------------------------------------------------------------
-    //  Load aditional options
+    //  Load additional options
     //  -------------------------------------------------------------------
 
     pszFetched = CSLFetchNameValue( papszOptions, "VATNAME" );
@@ -751,8 +747,8 @@ GDALDataset *GeoRasterDataset::Create( const char *pszFilename,
         poGRD->poGeoRaster->SetGeoReference( atoi( pszFetched ) );
     }
 
-    poGRD->poGeoRaster->bGenSpatialIndex = (bool)
-        CSLFetchBoolean( papszOptions, "SPATIALEXTENT", TRUE );
+    poGRD->poGeoRaster->bGenSpatialIndex = CPL_TO_BOOL(
+        CSLFetchBoolean( papszOptions, "SPATIALEXTENT", TRUE ));
 
     pszFetched = CSLFetchNameValue( papszOptions, "EXTENTSRID" );
 
@@ -773,9 +769,9 @@ GDALDataset *GeoRasterDataset::Create( const char *pszFilename,
         {
             poGRD->poGeoRaster->eModelCoordLocation = MCL_UPPERLEFT;
         }
-        else 
+        else
         {
-            CPLError( CE_Warning, CPLE_IllegalArg, 
+            CPLError( CE_Warning, CPLE_IllegalArg,
                 "Incorrect COORDLOCATION (%s)", pszFetched );
         }
     }
@@ -834,7 +830,7 @@ GDALDataset *GeoRasterDataset::CreateCopy( const char* pszFilename,
     int nBands = poSrcDS->GetRasterCount();
     if (nBands == 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
         "GeoRaster driver does not support source dataset with zero band.\n");
         return NULL;
     }
@@ -867,12 +863,12 @@ GDALDataset *GeoRasterDataset::CreateCopy( const char* pszFilename,
 
     if ( poSrcDS->GetGeoTransform( adfTransform ) == CE_None )
     {
-        if ( ! ( adfTransform[0] == 0.0 && 
+        if ( ! ( adfTransform[0] == 0.0 &&
                  adfTransform[1] == 1.0 &&
                  adfTransform[2] == 0.0 &&
                  adfTransform[3] == 0.0 &&
                  adfTransform[4] == 0.0 &&
-                 adfTransform[5] == 1.0 ) ) 
+                 adfTransform[5] == 1.0 ) )
         {
             poDstDS->SetGeoTransform( adfTransform );
         }
@@ -884,7 +880,7 @@ GDALDataset *GeoRasterDataset::CreateCopy( const char* pszFilename,
     }
 
     // --------------------------------------------------------------------
-    //      Copy RPC 
+    //      Copy RPC
     // --------------------------------------------------------------------
 
     char **papszRPCMetadata = GDALGetMetadata( poSrcDS, "RPC" );
@@ -908,14 +904,14 @@ GDALDataset *GeoRasterDataset::CreateCopy( const char* pszFilename,
     for( iBand = 1; iBand <= poSrcDS->GetRasterCount(); iBand++ )
     {
         GDALRasterBand*      poSrcBand = poSrcDS->GetRasterBand( iBand );
-        GeoRasterRasterBand* poDstBand = (GeoRasterRasterBand*) 
+        GeoRasterRasterBand* poDstBand = (GeoRasterRasterBand*)
                                          poDstDS->GetRasterBand( iBand );
 
         // ----------------------------------------------------------------
         //  Copy Color Table
         // ----------------------------------------------------------------
 
-        GDALColorTable* poColorTable = poSrcBand->GetColorTable(); 
+        GDALColorTable* poColorTable = poSrcBand->GetColorTable();
 
         if( poColorTable )
         {
@@ -923,7 +919,7 @@ GDALDataset *GeoRasterDataset::CreateCopy( const char* pszFilename,
         }
 
         // ----------------------------------------------------------------
-        //  Copy statitics information, without median and mode
+        //  Copy statistics information, without median and mode.
         // ----------------------------------------------------------------
 
         if( poSrcBand->GetStatistics( false, false, &dfMin, &dfMax,
@@ -938,7 +934,7 @@ GDALDataset *GeoRasterDataset::CreateCopy( const char* pszFilename,
         }
 
         // ----------------------------------------------------------------
-        //  Copy statitics metadata information, including median and mode
+        //  Copy statistics metadata information, including median and mode.
         // ----------------------------------------------------------------
 
         const char *pszMin     = poSrcBand->GetMetadataItem( "STATISTICS_MINIMUM" );
@@ -970,7 +966,7 @@ GDALDataset *GeoRasterDataset::CreateCopy( const char* pszFilename,
                 }
 
                 poDstBand->poGeoRaster->SetStatistics( iBand,
-                                                       pszMin, pszMax, pszMean, 
+                                                       pszMin, pszMax, pszMean,
                                                        pszMedian, pszMode,
                                                        pszStdDev, pszSkipFX );
             }
@@ -1011,13 +1007,11 @@ GDALDataset *GeoRasterDataset::CreateCopy( const char* pszFilename,
 
     poDstDS->GetRasterBand( 1 )->GetBlockSize( &nBlockXSize, &nBlockYSize );
 
-    void *pData = VSIMalloc( nBlockXSize * nBlockYSize *
+    void *pData = VSI_MALLOC_VERBOSE( nBlockXSize * nBlockYSize *
         GDALGetDataTypeSize( eType ) / 8 );
 
     if( pData == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory,
-            "GeoRaster::CreateCopy : Out of memory " );
         delete poDstDS;
         return NULL;
     }
@@ -1030,7 +1024,7 @@ GDALDataset *GeoRasterDataset::CreateCopy( const char* pszFilename,
     int nBlockRows = 0;
     CPLErr eErr = CE_None;
 
-    int nPixelSize = GDALGetDataTypeSize( 
+    int nPixelSize = GDALGetDataTypeSize(
         poSrcDS->GetRasterBand(1)->GetRasterDataType() ) / 8;
 
     if( poDstDS->poGeoRaster->nBandBlockSize == 1)
@@ -1160,7 +1154,7 @@ GDALDataset *GeoRasterDataset::CreateCopy( const char* pszFilename,
 
     if( pfnProgress )
     {
-        printf( "Ouput dataset: (georaster:%s/%s@%s,%s,%d) on %s%s,%s\n",
+        printf( "Output dataset: (georaster:%s/%s@%s,%s,%d) on %s%s,%s\n",
             poDstDS->poGeoRaster->poConnection->GetUser(),
             poDstDS->poGeoRaster->poConnection->GetPassword(),
             poDstDS->poGeoRaster->poConnection->GetServer(),
@@ -1230,7 +1224,7 @@ CPLErr GeoRasterDataset::GetGeoTransform( double *padfTransform )
     {
         return CE_Failure;
     }
-    
+
     memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
 
     bGeoTransform = true;
@@ -1277,7 +1271,7 @@ const char* GeoRasterDataset::GetProjectionRef( void )
         /*
          * Ignores the WKT from Oracle and use the one from GDAL's
          * EPSG tables. That would ensure that other drivers/software
-         * will recognizize the parameters.
+         * will recognize the parameters.
          */
 
         if( oSRS.exportToWkt( &pszProjection ) == OGRERR_NONE )
@@ -1474,7 +1468,7 @@ CPLErr GeoRasterDataset::SetProjection( const char *pszProjString )
 
     if( pszAuthName != NULL && pszAuthCode != NULL )
     {
-        if( EQUAL( pszAuthName, "ORACLE" ) || 
+        if( EQUAL( pszAuthName, "ORACLE" ) ||
             EQUAL( pszAuthName, "EPSG" ) )
         {
             poGeoRaster->SetGeoReference( atoi( pszAuthCode ) );
@@ -1487,11 +1481,11 @@ CPLErr GeoRasterDataset::SetProjection( const char *pszProjString )
     // ----------------------------------------------------------------
 
     OGRSpatialReference *poSRS2 = oSRS.Clone();
-    
+
     poSRS2->StripCTParms();
 
     double dfAngularUnits = poSRS2->GetAngularUnits( NULL );
-    
+
     if( fabs(dfAngularUnits - 0.0174532925199433) < 0.0000000000000010 )
     {
         /* match the precision used on Oracle for that particular value */
@@ -1506,7 +1500,7 @@ CPLErr GeoRasterDataset::SetProjection( const char *pszProjString )
         delete poSRS2;
         return CE_Failure;
     }
-    
+
     const char *pszProjName = poSRS2->GetAttrValue( "PROJECTION" );
 
     if( pszProjName )
@@ -1580,95 +1574,95 @@ CPLErr GeoRasterDataset::SetProjection( const char *pszProjString )
         {
             poSRS2->SetProjection( "Interrupted Goode Homolosine" );
         }
-        
+
         // ----------------------------------------------------------------
         // Translate projection's parameters to Oracle's standards
         // ----------------------------------------------------------------
 
         char* pszStart = NULL;
-        
-        CPLFree( pszCloneWKT );       
+
+        CPLFree( pszCloneWKT );
 
         if( poSRS2->exportToWkt( &pszCloneWKT ) != OGRERR_NONE )
         {
             delete poSRS2;
             return CE_Failure;
         }
-        
-        if( ( pszStart = strstr(pszCloneWKT, SRS_PP_AZIMUTH) ) )
+
+        if( ( pszStart = strstr(pszCloneWKT, SRS_PP_AZIMUTH) ) != NULL )
         {
             strncpy( pszStart, "Azimuth", strlen(SRS_PP_AZIMUTH) );
         }
 
-        if( ( pszStart = strstr(pszCloneWKT, SRS_PP_CENTRAL_MERIDIAN) ) )
+        if( ( pszStart = strstr(pszCloneWKT, SRS_PP_CENTRAL_MERIDIAN) ) != NULL )
         {
-            strncpy( pszStart, "Central_Meridian", 
+            strncpy( pszStart, "Central_Meridian",
                                         strlen(SRS_PP_CENTRAL_MERIDIAN) );
         }
 
-        if( ( pszStart = strstr(pszCloneWKT, SRS_PP_FALSE_EASTING) ) )
+        if( ( pszStart = strstr(pszCloneWKT, SRS_PP_FALSE_EASTING) ) != NULL )
         {
             strncpy( pszStart, "False_Easting", strlen(SRS_PP_FALSE_EASTING) );
         }
 
-        if( ( pszStart = strstr(pszCloneWKT, SRS_PP_FALSE_NORTHING) ) )
+        if( ( pszStart = strstr(pszCloneWKT, SRS_PP_FALSE_NORTHING) ) != NULL )
         {
-            strncpy( pszStart, "False_Northing", 
+            strncpy( pszStart, "False_Northing",
                                         strlen(SRS_PP_FALSE_NORTHING) );
         }
 
-        if( ( pszStart = strstr(pszCloneWKT, SRS_PP_LATITUDE_OF_CENTER) ) )
+        if( ( pszStart = strstr(pszCloneWKT, SRS_PP_LATITUDE_OF_CENTER) ) != NULL )
         {
-            strncpy( pszStart, "Latitude_Of_Center", 
+            strncpy( pszStart, "Latitude_Of_Center",
                                         strlen(SRS_PP_LATITUDE_OF_CENTER) );
         }
-                
-        if( ( pszStart = strstr(pszCloneWKT, SRS_PP_LATITUDE_OF_ORIGIN) ) )
+
+        if( ( pszStart = strstr(pszCloneWKT, SRS_PP_LATITUDE_OF_ORIGIN) ) != NULL )
         {
-            strncpy( pszStart, "Latitude_Of_Origin", 
+            strncpy( pszStart, "Latitude_Of_Origin",
                                         strlen(SRS_PP_LATITUDE_OF_ORIGIN) );
         }
-                
-        if( ( pszStart = strstr(pszCloneWKT, SRS_PP_LONGITUDE_OF_CENTER) ) )
+
+        if( ( pszStart = strstr(pszCloneWKT, SRS_PP_LONGITUDE_OF_CENTER) ) != NULL )
         {
-            strncpy( pszStart, "Longitude_Of_Center", 
+            strncpy( pszStart, "Longitude_Of_Center",
                                         strlen(SRS_PP_LONGITUDE_OF_CENTER) );
         }
-                
-        if( ( pszStart = strstr(pszCloneWKT, SRS_PP_PSEUDO_STD_PARALLEL_1) ) )
+
+        if( ( pszStart = strstr(pszCloneWKT, SRS_PP_PSEUDO_STD_PARALLEL_1) ) != NULL )
         {
-            strncpy( pszStart, "Pseudo_Standard_Parallel_1", 
+            strncpy( pszStart, "Pseudo_Standard_Parallel_1",
                                         strlen(SRS_PP_PSEUDO_STD_PARALLEL_1) );
         }
-                
-        if( ( pszStart = strstr(pszCloneWKT, SRS_PP_SCALE_FACTOR) ) )
+
+        if( ( pszStart = strstr(pszCloneWKT, SRS_PP_SCALE_FACTOR) ) != NULL )
         {
             strncpy( pszStart, "Scale_Factor", strlen(SRS_PP_SCALE_FACTOR) );
         }
-                
-        if( ( pszStart = strstr(pszCloneWKT, SRS_PP_STANDARD_PARALLEL_1) ) )
+
+        if( ( pszStart = strstr(pszCloneWKT, SRS_PP_STANDARD_PARALLEL_1) ) != NULL )
         {
-            strncpy( pszStart, "Standard_Parallel_1", 
+            strncpy( pszStart, "Standard_Parallel_1",
                                         strlen(SRS_PP_STANDARD_PARALLEL_1) );
         }
-                
-        if( ( pszStart = strstr(pszCloneWKT, SRS_PP_STANDARD_PARALLEL_2) ) )
+
+        if( ( pszStart = strstr(pszCloneWKT, SRS_PP_STANDARD_PARALLEL_2) ) != NULL )
         {
-            strncpy( pszStart, "Standard_Parallel_2", 
+            strncpy( pszStart, "Standard_Parallel_2",
                                         strlen(SRS_PP_STANDARD_PARALLEL_2) );
-        }                
-                
-        if( ( pszStart = strstr(pszCloneWKT, SRS_PP_STANDARD_PARALLEL_2) ) )
+        }
+
+        if( ( pszStart = strstr(pszCloneWKT, SRS_PP_STANDARD_PARALLEL_2) ) != NULL )
         {
-            strncpy( pszStart, "Standard_Parallel_2", 
+            strncpy( pszStart, "Standard_Parallel_2",
                                         strlen(SRS_PP_STANDARD_PARALLEL_2) );
-        }                
-        
+        }
+
         // ----------------------------------------------------------------
         // Fix Unit name
         // ----------------------------------------------------------------
-        
-        if( ( pszStart = strstr(pszCloneWKT, "metre") ) )
+
+        if( ( pszStart = strstr(pszCloneWKT, "metre") ) != NULL )
         {
             strncpy( pszStart, SRS_UL_METER, strlen(SRS_UL_METER) );
         }
@@ -1680,16 +1674,16 @@ CPLErr GeoRasterDataset::SetProjection( const char *pszProjString )
 
     OWConnection* poConnection  = poGeoRaster->poConnection;
     OWStatement* poStmt = NULL;
-    
-    int nNewSRID = 0;    
-   
-    char *pszFuncName = "FIND_GEOG_CRS";
-  
+
+    int nNewSRID = 0;
+
+    const char *pszFuncName = "FIND_GEOG_CRS";
+
     if( poSRS2->IsProjected() )
     {
         pszFuncName = "FIND_PROJ_CRS";
     }
-    
+
     poStmt = poConnection->CreateStatement( CPLSPrintf(
         "DECLARE\n"
         "  LIST SDO_SRID_LIST;"
@@ -1703,7 +1697,7 @@ CPLErr GeoRasterDataset::SetProjection( const char *pszProjString )
         "END;",
             pszFuncName,
             pszCloneWKT ) );
-        
+
     poStmt->BindName( ":out", &nNewSRID );
 
     CPLPushErrorHandler( CPLQuietErrorHandler );
@@ -1715,26 +1709,26 @@ CPLErr GeoRasterDataset::SetProjection( const char *pszProjString )
         if ( nNewSRID > 0 )
         {
             poGeoRaster->SetGeoReference( nNewSRID );
-            CPLFree( pszCloneWKT );       
+            CPLFree( pszCloneWKT );
             return CE_None;
         }
-    }   
+    }
 
     // --------------------------------------------------------------------
     // Search by simplified WKT or insert it as a user defined SRS
     // --------------------------------------------------------------------
-    
+
     int nCounter = 0;
 
     poStmt = poConnection->CreateStatement( CPLSPrintf(
         "SELECT COUNT(*) FROM MDSYS.CS_SRS WHERE WKTEXT = '%s'", pszCloneWKT));
-    
+
     poStmt->Define( &nCounter );
-            
+
     CPLPushErrorHandler( CPLQuietErrorHandler );
 
     if( poStmt->Execute() && nCounter > 0 )
-    {    
+    {
         poStmt = poConnection->CreateStatement( CPLSPrintf(
             "SELECT SRID FROM MDSYS.CS_SRS WHERE WKTEXT = '%s'", pszCloneWKT));
 
@@ -1743,15 +1737,15 @@ CPLErr GeoRasterDataset::SetProjection( const char *pszProjString )
         if( poStmt->Execute() )
         {
             CPLPopErrorHandler();
-            
+
             poGeoRaster->SetGeoReference( nNewSRID );
             CPLFree( pszCloneWKT );
             return CE_None;
-        }    
+        }
     }
 
     CPLPopErrorHandler();
-    
+
     poStmt = poConnection->CreateStatement( CPLSPrintf(
         "DECLARE\n"
         "  MAX_SRID NUMBER := 0;\n"
@@ -1774,24 +1768,24 @@ CPLErr GeoRasterDataset::SetProjection( const char *pszProjString )
     if( poStmt->Execute() )
     {
         CPLPopErrorHandler();
-            
+
         poGeoRaster->SetGeoReference( nNewSRID );
     }
     else
     {
         CPLPopErrorHandler();
-            
+
         poGeoRaster->SetGeoReference( UNKNOWN_CRS );
 
         CPLError( CE_Warning, CPLE_UserInterrupt,
             "Insufficient privileges to insert reference system to "
             "table MDSYS.CS_SRS." );
-        
+
         eError = CE_Warning;
     }
 
     CPLFree( pszCloneWKT );
-    
+
     return eError;
 }
 
@@ -1812,7 +1806,7 @@ char **GeoRasterDataset::GetMetadataDomainList()
 
 char **GeoRasterDataset::GetMetadata( const char *pszDomain )
 {
-    if( pszDomain != NULL && EQUALN( pszDomain, "SUBDATASETS", 11 ) )
+    if( pszDomain != NULL && STARTS_WITH_CI(pszDomain, "SUBDATASETS") )
         return papszSubdatasets;
     else
         return GDALDataset::GetMetadata( pszDomain );
@@ -1859,10 +1853,10 @@ void GeoRasterDataset::SetSubdatasets( GeoRasterWrapper* poGRW )
     if( poGRW->sTable.empty() &&
         poGRW->sColumn.empty() )
     {
-        poStmt = poConnection->CreateStatement( 
+        poStmt = poConnection->CreateStatement(
             "SELECT   DISTINCT TABLE_NAME, OWNER FROM ALL_SDO_GEOR_SYSDATA\n"
             "  ORDER  BY TABLE_NAME ASC" );
-        
+
         char szTable[OWNAME];
         char szOwner[OWNAME];
 
@@ -1911,7 +1905,7 @@ void GeoRasterDataset::SetSubdatasets( GeoRasterWrapper* poGRW )
 
         poStmt->Define( szColumn );
         poStmt->Define( szOwner );
-        
+
         if( poStmt->Execute() )
         {
             int nCount = 1;
@@ -1934,7 +1928,7 @@ void GeoRasterDataset::SetSubdatasets( GeoRasterWrapper* poGRW )
             }
             while( poStmt->Fetch() );
         }
-        
+
         return;
     }
 
@@ -2083,7 +2077,7 @@ CPLErr GeoRasterDataset::IBuildOverviews( const char* pszResampling,
     {
         bInternal = false;
     }
-        
+
     //  -----------------------------------------------------------
     //  Pyramids applies to the whole dataset not to a specific band
     //  -----------------------------------------------------------
@@ -2132,14 +2126,14 @@ CPLErr GeoRasterDataset::IBuildOverviews( const char* pszResampling,
               ( panOverviewList[i] != panOverviewList[i-1] * 2 ) )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
-                    "Invalid GeoRaster Pyramids levels." );        
+                    "Invalid GeoRaster Pyramids levels." );
                 return CE_Failure;
             }
         }
     }
 
     //  -----------------------------------------------------------
-    //  Re-sampling method: 
+    //  Re-sampling method:
     //    NN, BILINEAR, AVERAGE4, AVERAGE16 and CUBIC
     //  -----------------------------------------------------------
 
@@ -2149,7 +2143,7 @@ CPLErr GeoRasterDataset::IBuildOverviews( const char* pszResampling,
     {
         strcpy( szMethod, "NN" );
     }
-    else if( EQUALN( pszResampling, "AVERAGE", 7 ) )
+    else if( STARTS_WITH_CI(pszResampling, "AVERAGE") )
     {
         strcpy( szMethod, "AVERAGE4" );
     }
@@ -2172,7 +2166,7 @@ CPLErr GeoRasterDataset::IBuildOverviews( const char* pszResampling,
     //  -----------------------------------------------------------
     //  If Pyramid was done internally on the server exit here
     //  -----------------------------------------------------------
-    
+
     if( bInternal )
     {
         pfnProgress( 1 , NULL, pProgressData );
@@ -2229,8 +2223,8 @@ CPLErr GeoRasterDataset::IBuildOverviews( const char* pszResampling,
     {
         GeoRasterRasterBand* poBand = (GeoRasterRasterBand*) papoBands[i];
 
-        void *pScaledProgressData = GDALCreateScaledProgress( 
-            i / (double) nBands, ( i + 1) / (double) nBands, 
+        void *pScaledProgressData = GDALCreateScaledProgress(
+            i / (double) nBands, ( i + 1) / (double) nBands,
             pfnProgress, pProgressData );
 
         eErr = GDALRegenerateOverviews(
@@ -2251,10 +2245,8 @@ CPLErr GeoRasterDataset::IBuildOverviews( const char* pszResampling,
 //                                                             CreateMaskBand()
 //  ---------------------------------------------------------------------------
 
-CPLErr GeoRasterDataset::CreateMaskBand( int nFlags )
+CPLErr GeoRasterDataset::CreateMaskBand( int /*nFlags*/ )
 {
-    (void) nFlags;
-
     if( ! poGeoRaster->InitializeMask( DEFAULT_BMP_MASK,
             poGeoRaster->nRowBlockSize,
             poGeoRaster->nColumnBlockSize,
@@ -2264,7 +2256,7 @@ CPLErr GeoRasterDataset::CreateMaskBand( int nFlags )
     {
         return CE_Failure;
     }
-    
+
     poGeoRaster->bHasBitmapMask = true;
 
     return CE_None;
@@ -2275,26 +2267,25 @@ CPLErr GeoRasterDataset::CreateMaskBand( int nFlags )
 /*****************************************************************************/
 
 void CPL_DLL GDALRegister_GEOR()
-{
-    GDALDriver* poDriver;
 
-    if (! GDAL_CHECK_VERSION("GeoRaster driver"))
+{
+    if( !GDAL_CHECK_VERSION( "GeoRaster driver" ) )
         return;
 
-    if( GDALGetDriverByName( "GeoRaster" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    if( GDALGetDriverByName( "GeoRaster" ) != NULL )
+        return;
 
-        poDriver->SetDescription(  "GeoRaster" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Oracle Spatial GeoRaster" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_georaster.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
-                                   "Byte UInt16 Int16 UInt32 Int32 Float32 "
-                                   "Float64 CFloat32 CFloat64" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription(  "GeoRaster" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Oracle Spatial GeoRaster" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_georaster.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte UInt16 Int16 UInt32 Int32 Float32 "
+                               "Float64 CFloat32 CFloat64" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "  <Option name='DESCRIPTION' type='string' description='Table Description'/>"
 "  <Option name='INSERT'      type='string' description='Column Values'/>"
@@ -2347,12 +2338,11 @@ void CPL_DLL GDALRegister_GEOR()
                                            "default='75'/>"
 "</CreationOptionList>" );
 
-        poDriver->pfnOpen       = GeoRasterDataset::Open;
-        poDriver->pfnCreate     = GeoRasterDataset::Create;
-        poDriver->pfnCreateCopy = GeoRasterDataset::CreateCopy;
-        poDriver->pfnIdentify   = GeoRasterDataset::Identify;
-        poDriver->pfnDelete     = GeoRasterDataset::Delete;
+    poDriver->pfnOpen       = GeoRasterDataset::Open;
+    poDriver->pfnCreate     = GeoRasterDataset::Create;
+    poDriver->pfnCreateCopy = GeoRasterDataset::CreateCopy;
+    poDriver->pfnIdentify   = GeoRasterDataset::Identify;
+    poDriver->pfnDelete     = GeoRasterDataset::Delete;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/georaster/georaster_priv.h b/frmts/georaster/georaster_priv.h
index c74a64d..3b50606 100644
--- a/frmts/georaster/georaster_priv.h
+++ b/frmts/georaster/georaster_priv.h
@@ -28,8 +28,8 @@
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
 
-#ifndef _GEORASTER_PRIV_H_INCLUDED
-#define _GEORASTER_PRIV_H_INCLUDED
+#ifndef GEORASTER_PRIV_H_INCLUDED
+#define GEORASTER_PRIV_H_INCLUDED
 
 #include "gdal.h"
 #include "gdal_priv.h"
@@ -111,7 +111,7 @@ struct hNoDataItem {
 };
 
 //  ---------------------------------------------------------------------------
-//  GeoRaster wrapper classe definitions
+//  GeoRaster wrapper class definitions
 //  ---------------------------------------------------------------------------
 
 #include "oci_wrapper.h"
@@ -159,11 +159,11 @@ public:
                             int nBands,
                             GDALDataType eType,
                             char** papszOptions );
-    static GDALDataset* CreateCopy( const char* pszFilename, 
+    static GDALDataset* CreateCopy( const char* pszFilename,
                             GDALDataset* poSrcDS,
                             int bStrict,
                             char** papszOptions,
-                            GDALProgressFunc pfnProgress, 
+                            GDALProgressFunc pfnProgress,
                             void* pProgressData );
     virtual CPLErr      GetGeoTransform( double* padfTransform );
     virtual CPLErr      SetGeoTransform( double* padfTransform );
@@ -172,11 +172,11 @@ public:
     virtual char      **GetMetadataDomainList();
     virtual char**      GetMetadata( const char* pszDomain );
     virtual void        FlushCache( void );
-    virtual CPLErr      IRasterIO( GDALRWFlag eRWFlag, 
+    virtual CPLErr      IRasterIO( GDALRWFlag eRWFlag,
                             int nXOff, int nYOff, int nXSize, int nYSize,
-                            void *pData, int nBufXSize, int nBufYSize, 
+                            void *pData, int nBufXSize, int nBufYSize,
                             GDALDataType eBufType,
-                            int nBandCount, int *panBandMap, 
+                            int nBandCount, int *panBandMap,
                             GSpacing nPixelSpace, GSpacing nLineSpace,
                             GSpacing nBandSpace,
                             GDALRasterIOExtraArg* psExtraArg );
@@ -197,10 +197,10 @@ public:
                             GDALProgressFunc pfnProgress,
                             void* pProgresoversData );
     virtual CPLErr      CreateMaskBand( int nFlags );
-    virtual OGRErr      StartTransaction(int bForce=FALSE) {return CE_None;};
+    virtual OGRErr      StartTransaction(int /* bForce */ =FALSE) {return CE_None;};
     virtual OGRErr      CommitTransaction() {return CE_None;};
     virtual OGRErr      RollbackTransaction() {return CE_None;};
-    
+
     void                AssignGeoRaster( GeoRasterWrapper* poGRW );
 };
 
@@ -213,7 +213,7 @@ class GeoRasterRasterBand : public GDALRasterBand
     friend class GeoRasterDataset;
 
 public:
-                        GeoRasterRasterBand( GeoRasterDataset* poGDS, 
+                        GeoRasterRasterBand( GeoRasterDataset* poGDS,
                             int nBand,
                             int nLevel );
     virtual            ~GeoRasterRasterBand();
@@ -239,7 +239,7 @@ private:
     hNoDataItem*        pahNoDataArray;
     int                 nNoDataArraySz;
     bool                bHasNoDataArray;
-    
+
     void                ApplyNoDataArry( void* pBuffer );
 
 public:
@@ -248,19 +248,19 @@ public:
     virtual CPLErr      SetNoDataValue( double dfNoDataValue );
     virtual double      GetMinimum( int* pbSuccess = NULL );
     virtual double      GetMaximum( int* pbSuccess = NULL );
-    virtual GDALColorTable* 
+    virtual GDALColorTable*
                         GetColorTable();
-    virtual CPLErr      SetColorTable( GDALColorTable *poInColorTable ); 
-    virtual GDALColorInterp   
+    virtual CPLErr      SetColorTable( GDALColorTable *poInColorTable );
+    virtual GDALColorInterp
                         GetColorInterpretation();
-    virtual CPLErr      IReadBlock( int nBlockXOff, int nBlockYOff, 
+    virtual CPLErr      IReadBlock( int nBlockXOff, int nBlockYOff,
                             void *pImage );
-    virtual CPLErr      IWriteBlock( int nBlockXOff, int nBlockYOff, 
+    virtual CPLErr      IWriteBlock( int nBlockXOff, int nBlockYOff,
                             void *pImage );
-    virtual CPLErr      SetStatistics( double dfMin, double dfMax, 
+    virtual CPLErr      SetStatistics( double dfMin, double dfMax,
                             double dfMean, double dfStdDev );
     virtual CPLErr      GetStatistics( int bApproxOK, int bForce,
-                            double* pdfMin, double* pdfMax, 
+                            double* pdfMin, double* pdfMax,
                             double* pdfMean, double* pdfStdDev );
     virtual             GDALRasterAttributeTable *GetDefaultRAT();
     virtual CPLErr      SetDefaultRAT( const GDALRasterAttributeTable *poRAT );
@@ -294,7 +294,6 @@ private:
     GByte*              pabyBlockBuf;
     GByte*              pabyCompressBuf;
     OWStatement*        poBlockStmt;
-    OWStatement*        poStmtWrite;
 
     int                 nCurrentLevel;
     long                nLevelOffset;
@@ -336,7 +335,7 @@ public:
 
     static char**       ParseIdentificator( const char* pszStringID );
     static GeoRasterWrapper*
-                        Open( 
+                        Open(
                             const char* pszStringID,
                             bool bUpdate );
     bool                Create(
@@ -467,11 +466,11 @@ public:
 
     bool                bHasBitmapMask;
     bool                bUniqueFound;
-    
+
     int                 eModelCoordLocation;
     unsigned int        anULTCoordinate[3];
 
     GDALRPCInfo*        phRPC;
 };
 
-#endif /* ifndef _GEORASTER_PRIV_H_INCLUDED */
+#endif /* ifndef GEORASTER_PRIV_H_INCLUDED */
diff --git a/frmts/georaster/georaster_rasterband.cpp b/frmts/georaster/georaster_rasterband.cpp
index 498d07f..4a921db 100644
--- a/frmts/georaster/georaster_rasterband.cpp
+++ b/frmts/georaster/georaster_rasterband.cpp
@@ -41,12 +41,12 @@
 //  ---------------------------------------------------------------------------
 
 GeoRasterRasterBand::GeoRasterRasterBand( GeoRasterDataset *poGDS,
-                                          int nBand,
+                                          int nBandIn,
                                           int nLevel )
 {
     poDS                = (GDALDataset*) poGDS;
     poGeoRaster         = poGDS->poGeoRaster;
-    this->nBand         = nBand;
+    this->nBand         = nBandIn;
     this->eDataType     = OWGetDataType( poGeoRaster->sCellDepth.c_str() );
     poColorTable        = new GDALColorTable();
     poDefaultRAT        = NULL;
@@ -63,7 +63,7 @@ GeoRasterRasterBand::GeoRasterRasterBand( GeoRasterDataset *poGDS,
     pahNoDataArray      = NULL;
     nNoDataArraySz      = 0;
     bHasNoDataArray     = false;
-    
+
     //  -----------------------------------------------------------------------
     //  Initialize overview list
     //  -----------------------------------------------------------------------
@@ -165,7 +165,6 @@ GeoRasterRasterBand::GeoRasterRasterBand( GeoRasterDataset *poGDS,
                      * Use the first value to assigned pixel values
                      * on method ApplyNoDataArray()
                      */
-                    
                     dfNoData = phItem->dfLower;
                 }
             }
@@ -183,7 +182,7 @@ GeoRasterRasterBand::~GeoRasterRasterBand()
 {
     delete poColorTable;
     delete poDefaultRAT;
-    
+
     CPLFree( pszVATName );
     CPLFree( pahNoDataArray );
 
@@ -221,10 +220,10 @@ CPLErr GeoRasterRasterBand::IReadBlock( int nBlockXOff,
     }
     else
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-            "Error reading GeoRaster ofsett X (%d) offset Y (%d) band (%d)",
-            nBlockXOff, nBlockYOff, nBand );
-
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Error reading GeoRaster offset X (%d) offset Y (%d) "
+                  "band (%d)",
+                  nBlockXOff, nBlockYOff, nBand );
         return CE_Failure;
     }
 }
@@ -247,10 +246,10 @@ CPLErr GeoRasterRasterBand::IWriteBlock( int nBlockXOff,
     }
     else
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-            "Error writing GeoRaster ofsett X (%d) offset Y (%d) band (%d)",
-            nBlockXOff, nBlockYOff, nBand );
-
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Error writing GeoRaster offset X (%d) offset Y (%d) "
+                  "band (%d)",
+                  nBlockXOff, nBlockYOff, nBand );
         return CE_Failure;
     }
 }
@@ -409,7 +408,7 @@ CPLErr GeoRasterRasterBand::GetStatistics( int bApproxOK, int bForce,
         SetMetadataItem( "STATISTICS_MODE",        szMode );
         SetMetadataItem( "STATISTICS_STDDEV",      szStdDev );
         SetMetadataItem( "STATISTICS_SKIPFACTORX", szSampling );
-        SetMetadataItem( "STATISTICS_SKIPFACTORY", szSampling ); 
+        SetMetadataItem( "STATISTICS_SKIPFACTORY", szSampling );
 
         *pdfMin     = dfMin;
         *pdfMax     = dfMax;
@@ -426,13 +425,13 @@ CPLErr GeoRasterRasterBand::GetStatistics( int bApproxOK, int bForce,
 //                                                              SetStatistics()
 //  ---------------------------------------------------------------------------
 
-CPLErr GeoRasterRasterBand::SetStatistics( double dfMin, double dfMax,
-                                           double dfMean, double dfStdDev )
+CPLErr GeoRasterRasterBand::SetStatistics( double dfMinIn, double dfMaxIn,
+                                           double dfMeanIn, double dfStdDevIn )
 {
-    this->dfMin       = dfMin;
-    this->dfMax       = dfMax;
-    this->dfMean      = dfMean;
-    this->dfStdDev    = dfStdDev;
+    this->dfMin       = dfMinIn;
+    this->dfMax       = dfMaxIn;
+    this->dfMean      = dfMeanIn;
+    this->dfStdDev    = dfStdDevIn;
 
     return CE_None;
 }
@@ -464,7 +463,7 @@ double GeoRasterRasterBand::GetNoDataValue( int *pbSuccess )
 
 CPLErr GeoRasterRasterBand::SetNoDataValue( double dfNoDataValue )
 {
-    const char* pszFormat = 
+    const char* pszFormat =
         (eDataType == GDT_Float32 || eDataType == GDT_Float64) ? "%f" : "%.0f";
 
     poGeoRaster->SetNoData( (poDS->GetRasterCount() == 1) ? 0 : nBand,
@@ -570,7 +569,7 @@ CPLErr GeoRasterRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT
     if( ! pszVATName )
     {
         pszVATName = CPLStrdup( CPLSPrintf(
-            "RAT_%s_%d_%d", 
+            "RAT_%s_%d_%d",
             poGeoRaster->sDataTable.c_str(),
             poGeoRaster->nRasterId,
             nBand ) );
@@ -621,7 +620,7 @@ CPLErr GeoRasterRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT
 
     void** papWriteFields = (void**) VSIMalloc2(sizeof(void*), nColunsCount + 1);
 
-    papWriteFields[0] = 
+    papWriteFields[0] =
         (void*) VSIMalloc3(sizeof(int), sizeof(int), nEntryCount ); // ID field
 
     for(iCol = 0; iCol < nColunsCount; iCol++)
@@ -642,7 +641,7 @@ CPLErr GeoRasterRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT
                  (void*) VSIMalloc3(sizeof(double), sizeof(double), nEntryCount );
         }
     }
-    
+
     // ---------------------------
     // Load data to buffers
     // ---------------------------
@@ -659,7 +658,7 @@ CPLErr GeoRasterRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT
                 int nOffset = iEntry * nVATStrSize;
                 char* pszTarget = ((char*)papWriteFields[iCol + 1]) + nOffset;
                 const char *pszStrValue = poRAT->GetValueAsString(iEntry, iCol);
-                int nLen = strlen( pszStrValue );
+                int nLen = static_cast<int>(strlen( pszStrValue ));
                 nLen = nLen > ( nVATStrSize - 1 ) ? nVATStrSize : ( nVATStrSize - 1 );
                 strncpy( pszTarget, pszStrValue, nLen );
                 pszTarget[nLen] = '\0';
@@ -682,7 +681,7 @@ CPLErr GeoRasterRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT
     // ---------------------------
 
     CPLString osInsert = CPLSPrintf( "INSERT INTO %s VALUES (", pszVATName );
-    
+
     for( iCol = 0; iCol < ( nColunsCount + 1); iCol++ )
     {
         if( iCol > 0 )
@@ -700,7 +699,7 @@ CPLErr GeoRasterRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT
     // ---------------------------
 
     poStmt->Bind((int*) papWriteFields[0]); // ID field
-    
+
     for(iCol = 0; iCol < nColunsCount; iCol++)
     {
         if( poRAT->GetTypeOfCol( iCol ) == GFT_String )
@@ -734,7 +733,7 @@ CPLErr GeoRasterRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT
     {
         CPLFree( papWriteFields[iCol] );
     }
-    
+
     CPLFree( papWriteFields );
 
     delete poStmt;
@@ -763,16 +762,16 @@ GDALRasterAttributeTable *GeoRasterRasterBand::GetDefaultRAT()
     // Get the name of the VAT Table
     // ----------------------------------------------------------
 
-    char* pszVATName = poGDS->poGeoRaster->GetVAT( nBand );
+    char* l_pszVATName = poGDS->poGeoRaster->GetVAT( nBand );
 
-    if( pszVATName == NULL )
+    if( l_pszVATName == NULL )
     {
         return NULL;
     }
 
     OCIParam* phDesc = NULL;
 
-    phDesc = poGDS->poGeoRaster->poConnection->GetDescription( pszVATName );
+    phDesc = poGDS->poGeoRaster->poConnection->GetDescription( l_pszVATName );
 
     if( phDesc == NULL )
     {
@@ -780,7 +779,7 @@ GDALRasterAttributeTable *GeoRasterRasterBand::GetDefaultRAT()
     }
 
     // ----------------------------------------------------------
-    // Create the RAT and the SELECT statemet based on fields description
+    // Create the RAT and the SELECT statement based on fields description.
     // ----------------------------------------------------------
 
     int   iCol = 0;
@@ -822,12 +821,12 @@ GDALRasterAttributeTable *GeoRasterRasterBand::GetDefaultRAT()
             case SQLT_TIMESTAMP_LTZ:
             case SQLT_TIME:
             case SQLT_TIME_TZ:
-                    poDefaultRAT->CreateColumn( szField, GFT_String, 
+                    poDefaultRAT->CreateColumn( szField, GFT_String,
                         GFU_Generic );
                 break;
             default:
                 CPLDebug("GEORASTER", "VAT (%s) Column (%s) type (%d) not supported"
-                    "as GDAL RAT", pszVATName, szField, hType );
+                    "as GDAL RAT", l_pszVATName, szField, hType );
                 continue;
         }
         strcpy( szColumnList, CPLSPrintf( "%s substr(%s,1,%d),",
@@ -845,7 +844,7 @@ GDALRasterAttributeTable *GeoRasterRasterBand::GetDefaultRAT()
     OWStatement* poStmt = NULL;
 
     poStmt = poGeoRaster->poConnection->CreateStatement( CPLSPrintf (
-        "SELECT %s FROM %s", szColumnList, pszVATName ) );
+        "SELECT %s FROM %s", szColumnList, l_pszVATName ) );
 
     char** papszValue = (char**) CPLMalloc( sizeof(char**) * iCol );
 
@@ -860,7 +859,7 @@ GDALRasterAttributeTable *GeoRasterRasterBand::GetDefaultRAT()
     if( ! poStmt->Execute() )
     {
         CPLError( CE_Failure, CPLE_AppDefined, "Error reading VAT %s",
-            pszVATName );
+            l_pszVATName );
         return NULL;
     }
 
@@ -883,7 +882,7 @@ GDALRasterAttributeTable *GeoRasterRasterBand::GetDefaultRAT()
 
     delete poStmt;
 
-    CPLFree( pszVATName );
+    CPLFree( l_pszVATName );
 
     return poDefaultRAT;
 }
@@ -914,10 +913,8 @@ GDALRasterBand* GeoRasterRasterBand::GetOverview( int nLevel )
 //                                                             CreateMaskBand()
 //  ---------------------------------------------------------------------------
 
-CPLErr GeoRasterRasterBand::CreateMaskBand( int nFlags )
+CPLErr GeoRasterRasterBand::CreateMaskBand( int /*nFlags*/ )
 {
-    (void) nFlags;
-
     if( ! poGeoRaster->bHasBitmapMask )
     {
         return CE_Failure;
diff --git a/frmts/georaster/georaster_wrapper.cpp b/frmts/georaster/georaster_wrapper.cpp
index 9669f96..aa2a366 100644
--- a/frmts/georaster/georaster_wrapper.cpp
+++ b/frmts/georaster/georaster_wrapper.cpp
@@ -111,23 +111,23 @@ GeoRasterWrapper::~GeoRasterWrapper()
 
     if( pahLocator && nBlockCount )
     {
-        OWStatement::Free( pahLocator, nBlockCount );
+        OWStatement::Free( pahLocator, static_cast<int>(nBlockCount) );
     }
 
     CPLFree( pahLocator );
     CPLFree( pabyBlockBuf );
     CPLFree( pabyCompressBuf );
     CPLFree( pahLevels );
-    
+
     if( CPLListCount( psNoDataList ) )
     {
         CPLList* psList = NULL;
-        
+
         for( psList = psNoDataList; psList ; psList = psList->psNext )
         {
             CPLFree( psList->pData );
         }
-        
+
         CPLListDestroy( psNoDataList );
     }
 
@@ -137,7 +137,7 @@ GeoRasterWrapper::~GeoRasterWrapper()
     }
 
     CPLDestroyXMLNode( phMetadata );
-    
+
     if( sDInfo.global_state )
     {
         jpeg_destroy_decompress( &sDInfo );
@@ -229,7 +229,7 @@ GeoRasterWrapper* GeoRasterWrapper::Open( const char* pszStringId, bool bUpdate
     }
 
     poGRW->bUpdate = bUpdate;
-    
+
     //  ---------------------------------------------------------------
     //  Get a connection with Oracle server
     //  ---------------------------------------------------------------
@@ -273,7 +273,7 @@ GeoRasterWrapper* GeoRasterWrapper::Open( const char* pszStringId, bool bUpdate
             poGRW->sSchema = "";
             poGRW->sOwner  = poGRW->poConnection->GetUser();
         }
-        
+
         CSLDestroy( papszSchema );
     }
     else
@@ -523,7 +523,7 @@ GeoRasterWrapper* GeoRasterWrapper::Open( const char* pszStringId, bool bUpdate
     else
     {
         poGRW->bUniqueFound = false;
-        
+
         delete poStmt;
         return poGRW;
     }
@@ -538,7 +538,7 @@ GeoRasterWrapper* GeoRasterWrapper::Open( const char* pszStringId, bool bUpdate
         poGRW->sDataTable.c_str(),
         poGRW->sColumn.c_str(),
         poGRW->nRasterId );
-    
+
     //  -------------------------------------------------------------------
     //  Read Metadata XML in text
     //  -------------------------------------------------------------------
@@ -603,10 +603,10 @@ GeoRasterWrapper* GeoRasterWrapper::Open( const char* pszStringId, bool bUpdate
     //  Apply ULTCoordinate
     //  -------------------------------------------------------------------
 
-    poGRW->dfXCoefficient[2] += 
+    poGRW->dfXCoefficient[2] +=
                 ( poGRW->anULTCoordinate[0] * poGRW->dfXCoefficient[0] );
 
-    poGRW->dfYCoefficient[2] += 
+    poGRW->dfYCoefficient[2] +=
                 ( poGRW->anULTCoordinate[1] * poGRW->dfYCoefficient[1] );
 
     //  -------------------------------------------------------------------
@@ -616,7 +616,7 @@ GeoRasterWrapper* GeoRasterWrapper::Open( const char* pszStringId, bool bUpdate
     OCIDescriptorFree( phLocator, OCI_DTYPE_LOB );
     CPLFree( pszXML );
     delete poStmt;
-    
+
     //  -------------------------------------------------------------------
     //  Return a GeoRasterWrapper object
     //  -------------------------------------------------------------------
@@ -630,7 +630,7 @@ GeoRasterWrapper* GeoRasterWrapper::Open( const char* pszStringId, bool bUpdate
 
 bool GeoRasterWrapper::Create( char* pszDescription,
                                char* pszInsert,
-                               bool bUpdate )
+                               bool bUpdateIn )
 {
     CPLString sValues;
     CPLString sFormat;
@@ -677,7 +677,7 @@ bool GeoRasterWrapper::Create( char* pszDescription,
 
     char szDescription[OWTEXT];
 
-    if( bUpdate == false )
+    if( bUpdateIn == false )
     {
 
         if ( pszDescription  )
@@ -765,17 +765,17 @@ bool GeoRasterWrapper::Create( char* pszDescription,
 
         if( nRasterBands == 1 )
         {
-            sBlocking = CPLSPrintf( 
-                "blockSize=(%d, %d)", 
-                nRowBlockSize, 
+            sBlocking = CPLSPrintf(
+                "blockSize=(%d, %d)",
+                nRowBlockSize,
                 nColumnBlockSize );
         }
         else
         {
-            sBlocking = CPLSPrintf( 
-                "blockSize=(%d, %d, %d)", 
-                nRowBlockSize, 
-                nColumnBlockSize, 
+            sBlocking = CPLSPrintf(
+                "blockSize=(%d, %d, %d)",
+                nRowBlockSize,
+                nColumnBlockSize,
                 nBandBlockSize );
         }
     }
@@ -796,22 +796,22 @@ bool GeoRasterWrapper::Create( char* pszDescription,
     {
         if( nRasterBands == 1 )
         {
-            sFormat = CPLSPrintf( 
+            sFormat = CPLSPrintf(
                 "20001, '"
-                "dimSize=(%d,%d) ", 
+                "dimSize=(%d,%d) ",
                 nRasterRows, nRasterColumns );
         }
         else
         {
-            sFormat = CPLSPrintf( 
+            sFormat = CPLSPrintf(
                 "21001, '"
-                "dimSize=(%d,%d,%d) ", 
+                "dimSize=(%d,%d,%d) ",
                 nRasterRows, nRasterColumns, nRasterBands );
         }
 
-        if( EQUALN( sCompressionType.c_str(), "JPEG", 4 ) )
+        if( STARTS_WITH_CI(sCompressionType.c_str(), "JPEG") )
         {
-            sFormat.append( CPLSPrintf( 
+            sFormat.append( CPLSPrintf(
                     "%s "
                     "cellDepth=%s "
                     "interleaving=%s "
@@ -825,7 +825,7 @@ bool GeoRasterWrapper::Create( char* pszDescription,
         }
         else
         {
-            sFormat.append( CPLSPrintf( 
+            sFormat.append( CPLSPrintf(
                     "%s "
                     "cellDepth=%s "
                     "interleaving=%s "
@@ -868,7 +868,7 @@ bool GeoRasterWrapper::Create( char* pszDescription,
 
     OWStatement* poStmt;
 
-    if( ! bUpdate )
+    if( ! bUpdateIn )
     {
         poStmt = poConnection->CreateStatement( CPLSPrintf(
             "DECLARE\n"
@@ -903,12 +903,12 @@ bool GeoRasterWrapper::Create( char* pszDescription,
     }
 
     //  -----------------------------------------------------------
-    //  Prepare UPDATE or INSERT comand
+    //  Prepare UPDATE or INSERT command
     //  -----------------------------------------------------------
 
     CPLString sCommand;
 
-    if( bUpdate )
+    if( bUpdateIn )
     {
         sCommand = CPLSPrintf(
             "SELECT %s INTO GR1 FROM %s%s T WHERE %s FOR UPDATE;",
@@ -1059,7 +1059,7 @@ bool GeoRasterWrapper::Create( char* pszDescription,
 
         OCIDescriptorFree( phLocator, OCI_DTYPE_LOB );
 
-        
+
         delete poStmt;
 
         return true;
@@ -1163,7 +1163,7 @@ bool GeoRasterWrapper::Create( char* pszDescription,
             sColumn.c_str(), sSchema.c_str(), sTable.c_str(),
             sColumn.c_str(), sColumn.c_str(),
             szCreateBlank,
-            sFormat.c_str(), 
+            sFormat.c_str(),
             sSchema.c_str(), sTable.c_str(),
             sColumn.c_str(), sColumn.c_str(), sColumn.c_str(),
             sSchema.c_str(), sSchema.c_str(), sSchema.c_str(),
@@ -1176,7 +1176,7 @@ bool GeoRasterWrapper::Create( char* pszDescription,
     poStmt->Bind( &nTotalBandBlocks );
     poStmt->Bind( &nTotalRowBlocks );
     poStmt->Bind( &nTotalColumnBlocks );
-    
+
     poStmt->BindName( ":rdt", szBindRDT );
     poStmt->BindName( ":rid", &nBindRID );
 
@@ -1260,7 +1260,7 @@ bool GeoRasterWrapper::Delete( void )
     {
         return false;
     }
-    
+
     OWStatement* poStmt = poConnection->CreateStatement( CPLSPrintf(
       "UPDATE %s%s T SET %s = NULL WHERE %s\n",
             sSchema.c_str(),
@@ -1337,7 +1337,7 @@ void GeoRasterWrapper::GetRasterInfo( void )
     }
 
     //  -------------------------------------------------------------------
-    //  Load NoData Values 
+    //  Load NoData Values
     //  -------------------------------------------------------------------
 
     LoadNoDataValues();
@@ -1346,13 +1346,13 @@ void GeoRasterWrapper::GetRasterInfo( void )
     //  Get ULTCoordinate values
     //  -------------------------------------------------------------------
 
-    anULTCoordinate[0] = atoi(CPLGetXMLValue( 
+    anULTCoordinate[0] = atoi(CPLGetXMLValue(
             phMetadata, "rasterInfo.ULTCoordinate.column", "0"));
 
-    anULTCoordinate[1] = atoi(CPLGetXMLValue( 
+    anULTCoordinate[1] = atoi(CPLGetXMLValue(
             phMetadata, "rasterInfo.ULTCoordinate.row", "0"));
 
-    anULTCoordinate[2] = atoi(CPLGetXMLValue( 
+    anULTCoordinate[2] = atoi(CPLGetXMLValue(
             phMetadata, "rasterInfo.ULTCoordinate.band", "0"));
 
     //  -------------------------------------------------------------------
@@ -1411,13 +1411,13 @@ void GeoRasterWrapper::GetRasterInfo( void )
     sCompressionType  = CPLGetXMLValue( phMetadata,
         "rasterInfo.compression.type", "NONE" );
 
-    if( EQUALN( sCompressionType.c_str(), "JPEG", 4 ) )
+    if( STARTS_WITH_CI(sCompressionType.c_str(), "JPEG") )
     {
         nCompressQuality = atoi( CPLGetXMLValue( phMetadata,
                             "rasterInfo.compression.quality", "75" ) );
     }
 
-    if( EQUALN( sCompressionType.c_str(), "JPEG", 4 ) )
+    if( STARTS_WITH_CI(sCompressionType.c_str(), "JPEG") )
     {
         sInterleaving = "BIP";
     }
@@ -1494,9 +1494,9 @@ bool GeoRasterWrapper::GetStatistics( int nBand,
     {
         if( n == nBand && CPLGetXMLNode( phSubLayer, "statisticDataset" ) )
         {
-            strncpy( pszSampling, CPLGetXMLValue( phSubLayer, 
+            strncpy( pszSampling, CPLGetXMLValue( phSubLayer,
                 "statisticDataset.samplingFactor",  "0.0" ), MAX_DOUBLE_STR_REP );
-            strncpy( pszMin, CPLGetXMLValue( phSubLayer, 
+            strncpy( pszMin, CPLGetXMLValue( phSubLayer,
                 "statisticDataset.MIN",  "0.0" ), MAX_DOUBLE_STR_REP );
             strncpy( pszMax, CPLGetXMLValue( phSubLayer,
                 "statisticDataset.MAX",  "0.0" ), MAX_DOUBLE_STR_REP );
@@ -1747,7 +1747,7 @@ void GeoRasterWrapper::SetColorMap( int nBand, GDALColorTable* poCT )
 bool GeoRasterWrapper::InitializeIO( void )
 {
     bInitializeIO = true;
-    
+
     // --------------------------------------------------------------------
     // Initialize Pyramid level details
     // --------------------------------------------------------------------
@@ -1778,13 +1778,13 @@ bool GeoRasterWrapper::InitializeIO( void )
     // --------------------------------------------------------------------
 
     int iLevel = 1;
-    
+
     for( iLevel = 1; iLevel <= nPyramidMaxLevel; iLevel++ )
     {
         int nRBS = nRowBlockSize;
         int nCBS = nColumnBlockSize;
-        int nTCB = nTotalColumnBlocks;
-        int nTRB = nTotalRowBlocks;
+        int nTCB;
+        int nTRB;
 
         // --------------------------------------------------------------------
         // Calculate the actual size of a lower resolution block
@@ -1832,13 +1832,13 @@ bool GeoRasterWrapper::InitializeIO( void )
         pahLevels[iLevel].nGDALBlockBytes    = (unsigned long ) ( nCBS * nRBS * nGDALCellBytes );
         pahLevels[iLevel].nOffset            = 0L;
     }
-    
+
     // --------------------------------------------------------------------
     // Calculate total row count and level's offsets
     // --------------------------------------------------------------------
 
     nBlockCount = 0L;
-    
+
     for( iLevel = 0; iLevel <= nPyramidMaxLevel; iLevel++ )
     {
         pahLevels[iLevel].nOffset = nBlockCount;
@@ -1851,15 +1851,10 @@ bool GeoRasterWrapper::InitializeIO( void )
 
     long nMaxBufferSize = MAX( nBlockBytes, nGDALBlockBytes );
 
-    pabyBlockBuf = (GByte*) VSIMalloc( sizeof(GByte) * nMaxBufferSize );
+    pabyBlockBuf = (GByte*) VSI_MALLOC_VERBOSE( nMaxBufferSize );
 
     if ( pabyBlockBuf == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory, 
-            "InitializeIO - Block Buffer error\n"
-            "Cannot allocate memory buffer of (%ld) bytes "
-            "Consider the use of *smaller* block size",
-            nMaxBufferSize );
         return false;
     }
 
@@ -1869,15 +1864,10 @@ bool GeoRasterWrapper::InitializeIO( void )
 
     if( bUpdate && ! EQUAL( sCompressionType.c_str(), "NONE") )
     {
-        pabyCompressBuf = (GByte*) VSIMalloc( sizeof(GByte) * nMaxBufferSize );
+        pabyCompressBuf = (GByte*) VSI_MALLOC_VERBOSE( nMaxBufferSize );
 
         if ( pabyCompressBuf == NULL )
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory,
-                "InitializeIO - Compression Buffer error\n"
-                "Cannot allocate memory buffer of (%ld) bytes "
-                "Consider the use of *smaller* block size",
-                nMaxBufferSize );
             return false;
         }
     }
@@ -1886,15 +1876,10 @@ bool GeoRasterWrapper::InitializeIO( void )
     // Allocate array of LOB Locators
     // --------------------------------------------------------------------
 
-    pahLocator = (OCILobLocator**) VSIMalloc( sizeof(void*) * nBlockCount );
+    pahLocator = (OCILobLocator**) VSI_MALLOC_VERBOSE( sizeof(void*) * nBlockCount );
 
     if ( pahLocator == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory,
-                "InitializeIO - LobLocator Array error\n"
-                "Cannot allocate memory buffer of (%ld) bytes "
-                "Consider the use of *bigger* block size",
-                (sizeof(void*) * nBlockCount) );
         return false;
     }
 
@@ -1925,7 +1910,7 @@ bool GeoRasterWrapper::InitializeIO( void )
     poBlockStmt->Bind( &nRasterId );
     poBlockStmt->Define( pahLocator, nBlockCount );
 
-    if( ! poBlockStmt->Execute( nBlockCount ) )
+    if( ! poBlockStmt->Execute( static_cast<int>(nBlockCount) ) )
     {
         return false;
     }
@@ -1971,16 +1956,16 @@ bool GeoRasterWrapper::GetDataBlock( int nBand,
     {
         InitializeLevel( nLevel );
     }
-    
+
     long nBlock = GetBlockNumber( nBand, nXOffset, nYOffset );
 
-    CPLDebug( "Read  ", 
-              "Block = %4ld Size = %7ld Band = %d Level = %d X = %d Y = %d", 
+    CPLDebug( "Read  ",
+              "Block = %4ld Size = %7ld Band = %d Level = %d X = %d Y = %d",
               nBlock, nBlockBytes, nBand, nLevel, nXOffset, nYOffset );
 
     if( nCacheBlockId != nBlock )
     {
-        if ( bFlushBlock )       
+        if ( bFlushBlock )
         {
             if( ! FlushBlock( nCacheBlockId ) )
             {
@@ -1994,7 +1979,7 @@ bool GeoRasterWrapper::GetDataBlock( int nBand,
 
         nBytesRead = poBlockStmt->ReadBlob( pahLocator[nBlock],
                                             pabyBlockBuf,
-                                            nBlockBytes );
+                                            static_cast<int>(nBlockBytes) );
 
         CPLDebug( "Load  ", "Block = %4ld Size = %7ld", nBlock, nBlockBytes );
 
@@ -2004,11 +1989,11 @@ bool GeoRasterWrapper::GetDataBlock( int nBand,
             return true;
         }
 
-        if( nBytesRead < nBlockBytes && 
+        if( nBytesRead < nBlockBytes &&
             EQUAL( sCompressionType.c_str(), "NONE") )
         {
-            CPLError( CE_Warning, CPLE_AppDefined, 
-                "BLOB size (%ld) is smaller than expected (%ld) !", 
+            CPLError( CE_Warning, CPLE_AppDefined,
+                "BLOB size (%ld) is smaller than expected (%ld) !",
                 nBytesRead,  nBlockBytes );
             memset( pData, 0, nGDALBlockBytes );
             return true;
@@ -2016,15 +2001,20 @@ bool GeoRasterWrapper::GetDataBlock( int nBand,
 
         if( nBytesRead > nBlockBytes )
         {
-            CPLError( CE_Warning, CPLE_AppDefined, 
+            CPLError( CE_Warning, CPLE_AppDefined,
                 "BLOB size (%ld) is bigger than expected (%ld) !",
                 nBytesRead,  nBlockBytes );
             memset( pData, 0, nGDALBlockBytes );
             return true;
         }
 
+        //  ----------------------------------------------------------------
+        //  GeoRaster BLOB is always Big endian
+        //  ----------------------------------------------------------------
+
 #ifndef CPL_MSB
-        if( nCellSizeBits > 8 )
+        if( nCellSizeBits > 8 && 
+            EQUAL( sCompressionType.c_str(), "DEFLATE") == false )
         {
             int nWordSize  = nCellSizeBits / 8;
             int nWordCount = nColumnBlockSize * nRowBlockSize * nBandBlockSize;
@@ -2036,13 +2026,21 @@ bool GeoRasterWrapper::GetDataBlock( int nBand,
         //  Uncompress
         //  ----------------------------------------------------------------
 
-        if( EQUALN( sCompressionType.c_str(), "JPEG", 4 ) )
+        if( STARTS_WITH_CI(sCompressionType.c_str(), "JPEG") )
         {
             UncompressJpeg( nBytesRead );
         }
         else if ( EQUAL( sCompressionType.c_str(), "DEFLATE" ) )
         {
             UncompressDeflate( nBytesRead );
+#ifndef CPL_MSB
+            if( nCellSizeBits > 8 )
+            {
+                int nWordSize  = nCellSizeBits / 8;
+                int nWordCount = nColumnBlockSize * nRowBlockSize * nBandBlockSize;
+                GDALSwapWords( pabyBlockBuf, nWordSize, nWordCount, nWordSize );
+            }
+#endif
         }
 
         //  ----------------------------------------------------------------
@@ -2127,8 +2125,8 @@ bool GeoRasterWrapper::SetDataBlock( int nBand,
 
     long nBlock = GetBlockNumber( nBand, nXOffset, nYOffset );
 
-    CPLDebug( "Write ", 
-              "Block = %4ld Size = %7ld Band = %d Level = %d X = %d Y = %d", 
+    CPLDebug( "Write ",
+              "Block = %4ld Size = %7ld Band = %d Level = %d X = %d Y = %d",
               nBlock, nBlockBytes, nBand, nLevel, nXOffset, nYOffset );
 
     //  --------------------------------------------------------------------
@@ -2155,7 +2153,7 @@ bool GeoRasterWrapper::SetDataBlock( int nBand,
 
         nBytesRead = poBlockStmt->ReadBlob( pahLocator[nBlock],
                                             pabyBlockBuf,
-                                            nBlockBytes );
+                                            static_cast<int>(nBlockBytes) );
 
         CPLDebug( "Reload", "Block = %4ld Size = %7ld", nBlock, nBlockBytes );
 
@@ -2169,7 +2167,7 @@ bool GeoRasterWrapper::SetDataBlock( int nBand,
             //  Uncompress
             //  ------------------------------------------------------------
 
-            if( EQUALN( sCompressionType.c_str(), "JPEG", 4 ) )
+            if( STARTS_WITH_CI(sCompressionType.c_str(), "JPEG") )
             {
                 UncompressJpeg( nBytesRead );
             }
@@ -2177,7 +2175,7 @@ bool GeoRasterWrapper::SetDataBlock( int nBand,
             {
                 UncompressDeflate( nBytesRead );
             }
-            
+
             //  ------------------------------------------------------------
             //  Unpack NBits
             //  ------------------------------------------------------------
@@ -2258,7 +2256,7 @@ bool GeoRasterWrapper::FlushBlock( long nCacheBlock )
 
     if( ! EQUAL( sCompressionType.c_str(), "NONE" ) )
     {
-        if( EQUALN( sCompressionType.c_str(), "JPEG", 4 ) )
+        if( STARTS_WITH_CI(sCompressionType.c_str(), "JPEG") )
         {
             nFlushBlockSize = CompressJpeg();
         }
@@ -2274,12 +2272,12 @@ bool GeoRasterWrapper::FlushBlock( long nCacheBlock )
     //  Write BLOB
     //  --------------------------------------------------------------------
 
-    CPLDebug( "Flush ", "Block = %4ld Size = %7ld", nCacheBlock, 
+    CPLDebug( "Flush ", "Block = %4ld Size = %7ld", nCacheBlock,
               nFlushBlockSize );
 
     if( ! poBlockStmt->WriteBlob( pahLocator[nCacheBlock],
                                   pabyFlushBuffer,
-                                  nFlushBlockSize ) )
+                                  static_cast<int>(nFlushBlockSize) ) )
     {
         return false;
     }
@@ -2294,7 +2292,7 @@ bool GeoRasterWrapper::FlushBlock( long nCacheBlock )
 //  ---------------------------------------------------------------------------
 //                                                           LoadNoDataValues()
 //  ---------------------------------------------------------------------------
-
+static
 CPLList* AddToNoDataList( CPLXMLNode* phNode, int nNumber, CPLList* poList )
 {
     CPLXMLNode* psChild = phNode->psChild;
@@ -2372,9 +2370,9 @@ void GeoRasterWrapper::LoadNoDataValues( void )
 //                                                                     GetRPC()
 //  ---------------------------------------------------------------------------
 
-/* This is the order for storing 20 coeffients in GeoRaster Metadata */
+/* This is the order for storing 20 coefficients in GeoRaster Metadata */
 
-static const int anOrder[] = { 
+static const int anOrder[] = {
     1, 2, 8, 12, 3, 5, 15, 9, 13, 16, 4, 6, 18, 7, 11, 19, 10, 14, 17, 20
 };
 
@@ -2382,7 +2380,7 @@ void GeoRasterWrapper::GetRPC()
 {
     int i;
 
-    CPLXMLNode* phSRSInfo = CPLGetXMLNode( phMetadata, 
+    CPLXMLNode* phSRSInfo = CPLGetXMLNode( phMetadata,
                                            "spatialReferenceInfo" );
 
     if( phSRSInfo == NULL )
@@ -2436,7 +2434,7 @@ void GeoRasterWrapper::GetRPC()
     }
 
     phRPC = (GDALRPCInfo*) VSIMalloc( sizeof(GDALRPCInfo) );
-    
+
     phRPC->dfLINE_OFF     = CPLAtof( CPLGetXMLValue( phPolyModel, "rowOff", "0" ) );
     phRPC->dfSAMP_OFF     = CPLAtof( CPLGetXMLValue( phPolyModel, "columnOff", "0" ) );
     phRPC->dfLONG_OFF     = CPLAtof( CPLGetXMLValue( phPolyModel, "xOff", "0" ) );
@@ -2584,12 +2582,12 @@ void GeoRasterWrapper::SetRPC()
     CPLString osField, osMultiField;
     CPLXMLNode* phPolynomial = NULL;
 
-    CPLXMLNode* phSRSInfo = CPLGetXMLNode( phMetadata, 
+    CPLXMLNode* phSRSInfo = CPLGetXMLNode( phMetadata,
                                            "spatialReferenceInfo" );
 
     if( ! phSRSInfo )
     {
-        phSRSInfo = CPLCreateXMLNode( phMetadata, CXT_Element, 
+        phSRSInfo = CPLCreateXMLNode( phMetadata, CXT_Element,
                                       "spatialReferenceInfo" );
     }
     else
@@ -2629,28 +2627,28 @@ void GeoRasterWrapper::SetRPC()
 
     CPLCreateXMLElementAndValue( phSRSInfo, "isReferenced", "true" );
     CPLCreateXMLElementAndValue( phSRSInfo, "SRID", "4327" );
-    CPLCreateXMLElementAndValue( phSRSInfo, "modelCoordinateLocation", 
+    CPLCreateXMLElementAndValue( phSRSInfo, "modelCoordinateLocation",
                                             "CENTER" );
     CPLCreateXMLElementAndValue( phSRSInfo, "modelType", "FunctionalFitting" );
-    CPLSetXMLValue( phSRSInfo, "polynomialModel.#rowOff",      
+    CPLSetXMLValue( phSRSInfo, "polynomialModel.#rowOff",
                                     CPLSPrintf( "%.15g", phRPC->dfLINE_OFF ) );
-    CPLSetXMLValue( phSRSInfo, "polynomialModel.#columnOff",   
+    CPLSetXMLValue( phSRSInfo, "polynomialModel.#columnOff",
                                     CPLSPrintf( "%.15g", phRPC->dfSAMP_OFF ) );
-    CPLSetXMLValue( phSRSInfo, "polynomialModel.#xOff",        
+    CPLSetXMLValue( phSRSInfo, "polynomialModel.#xOff",
                                     CPLSPrintf( "%.15g", phRPC->dfLONG_OFF ) );
-    CPLSetXMLValue( phSRSInfo, "polynomialModel.#yOff",        
+    CPLSetXMLValue( phSRSInfo, "polynomialModel.#yOff",
                                     CPLSPrintf( "%.15g", phRPC->dfLAT_OFF ) );
-    CPLSetXMLValue( phSRSInfo, "polynomialModel.#zOff",        
+    CPLSetXMLValue( phSRSInfo, "polynomialModel.#zOff",
                                     CPLSPrintf( "%.15g", phRPC->dfHEIGHT_OFF ) );
-    CPLSetXMLValue( phSRSInfo, "polynomialModel.#rowScale",    
+    CPLSetXMLValue( phSRSInfo, "polynomialModel.#rowScale",
                                     CPLSPrintf( "%.15g", phRPC->dfLINE_SCALE ) );
-    CPLSetXMLValue( phSRSInfo, "polynomialModel.#columnScale", 
+    CPLSetXMLValue( phSRSInfo, "polynomialModel.#columnScale",
                                     CPLSPrintf( "%.15g", phRPC->dfSAMP_SCALE ) );
-    CPLSetXMLValue( phSRSInfo, "polynomialModel.#xScale",      
+    CPLSetXMLValue( phSRSInfo, "polynomialModel.#xScale",
                                     CPLSPrintf( "%.15g", phRPC->dfLONG_SCALE ) );
-    CPLSetXMLValue( phSRSInfo, "polynomialModel.#yScale",      
+    CPLSetXMLValue( phSRSInfo, "polynomialModel.#yScale",
                                     CPLSPrintf( "%.15g", phRPC->dfLAT_SCALE ) );
-    CPLSetXMLValue( phSRSInfo, "polynomialModel.#zScale",      
+    CPLSetXMLValue( phSRSInfo, "polynomialModel.#zScale",
                                     CPLSPrintf( "%.15g", phRPC->dfHEIGHT_SCALE ) );
     CPLXMLNode*     phPloyModel = CPLGetXMLNode( phSRSInfo, "polynomialModel" );
 
@@ -2670,7 +2668,7 @@ void GeoRasterWrapper::SetRPC()
         osMultiField += osField;
     }
     phPolynomial = CPLGetXMLNode( phPloyModel, "pPolynomial" );
-    CPLCreateXMLElementAndValue( phPolynomial, "polynomialCoefficients", 
+    CPLCreateXMLElementAndValue( phPolynomial, "polynomialCoefficients",
                                  osMultiField );
 
     // qPolynomial refers to LINE_DEN
@@ -2689,7 +2687,7 @@ void GeoRasterWrapper::SetRPC()
         osMultiField += osField;
     }
     phPolynomial = CPLGetXMLNode( phPloyModel, "qPolynomial" );
-    CPLCreateXMLElementAndValue( phPolynomial, "polynomialCoefficients", 
+    CPLCreateXMLElementAndValue( phPolynomial, "polynomialCoefficients",
                                  osMultiField );
 
     // rPolynomial refers to SAMP_NUM
@@ -2708,7 +2706,7 @@ void GeoRasterWrapper::SetRPC()
         osMultiField += osField;
     }
     phPolynomial = CPLGetXMLNode( phPloyModel, "rPolynomial" );
-    CPLCreateXMLElementAndValue( phPolynomial, "polynomialCoefficients", 
+    CPLCreateXMLElementAndValue( phPolynomial, "polynomialCoefficients",
                                  osMultiField );
 
     // sPolynomial refers to SAMP_DEN
@@ -2727,7 +2725,7 @@ void GeoRasterWrapper::SetRPC()
         osMultiField += osField;
     }
     phPolynomial = CPLGetXMLNode( phPloyModel, "sPolynomial" );
-    CPLCreateXMLElementAndValue( phPolynomial, "polynomialCoefficients", 
+    CPLCreateXMLElementAndValue( phPolynomial, "polynomialCoefficients",
                                  osMultiField );
 
     //  -------------------------------------------------------------------
@@ -2780,7 +2778,7 @@ bool GeoRasterWrapper::GetNoData( int nLayer, double* pdfNoDataValue )
     }
 
     //  -------------------------------------------------------------------
-    //  Values from the Object Layer override values from the layers 
+    //  Values from the Object Layer override values from the layers
     //  -------------------------------------------------------------------
 
     if( nCount == 1 )
@@ -2857,14 +2855,14 @@ bool GeoRasterWrapper::SetNoData( int nLayer, const char* pszValue )
 
     char szRDT[OWCODE];
     char szNoData[OWTEXT];
-    
+
     strcpy( szRDT, sDataTable.c_str() );
     strcpy( szNoData, pszValue );
 
     int nRID = nRasterId;
 
     // ------------------------------------------------------------
-    //  Write the in memory XML metada to avoid lossing other changes
+    //  Write the in memory XML metadata to avoid losing other changes.
     // ------------------------------------------------------------
 
     char* pszMetadata = CPLSerializeXMLTree( phMetadata );
@@ -2876,7 +2874,7 @@ bool GeoRasterWrapper::SetNoData( int nLayer, const char* pszValue )
 
     OCILobLocator* phLocatorR = NULL;
     OCILobLocator* phLocatorW = NULL;
-    
+
     OWStatement* poStmt = poConnection->CreateStatement( CPLSPrintf(
         "DECLARE\n"
         "  GR1 sdo_georaster;\n"
@@ -2912,7 +2910,7 @@ bool GeoRasterWrapper::SetNoData( int nLayer, const char* pszValue )
     poStmt->BindName( ":rdt", szRDT );
     poStmt->BindName( ":rid", &nRID );
 
-    CPLFree( pszMetadata );    
+    CPLFree( pszMetadata );
 
     if( ! poStmt->Execute() )
     {
@@ -3108,7 +3106,7 @@ bool GeoRasterWrapper::FlushMetadata()
     {
         CPLSetXMLValue( psNode, "type", sCompressionType.c_str() );
 
-        if( EQUALN( sCompressionType.c_str(), "JPEG", 4 ) )
+        if( STARTS_WITH_CI(sCompressionType.c_str(), "JPEG") )
         {
             CPLSetXMLValue( psNode, "quality",
                 CPLSPrintf( "%d", nCompressQuality ) );
@@ -3248,7 +3246,7 @@ bool GeoRasterWrapper::FlushMetadata()
             sWhere.c_str() ) );
 
     poStmt->WriteCLob( &phLocator, pszMetadata );
-    
+
     poStmt->Bind( &nSRID );
     poStmt->Bind( &nExtentSRID );
     poStmt->Bind( &phLocator );
@@ -3276,11 +3274,11 @@ bool GeoRasterWrapper::FlushMetadata()
 
     if( nException )
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
             "Cannot generate spatialExtent! (ORA-%d) ", nException );
     }
 
-    if (bGenPyramid) 
+    if (bGenPyramid)
     {
         if (GeneratePyramid( nPyramidLevels, sPyramidResampling.c_str(), true ))
         {
@@ -3452,7 +3450,7 @@ bool GeoRasterWrapper::DeletePyramid()
             sTable.c_str(),
             sColumn.c_str(),
             sWhere.c_str() ) );
-    
+
     poStmt->Execute();
 
     delete poStmt;
@@ -3509,7 +3507,7 @@ bool GeoRasterWrapper::InitializeMask( int nLevel,
         "END;" );
 
     char pszDataTable[OWNAME];
-    
+
     poStmt->Bind( &nBlockColumns );
     poStmt->Bind( &nBlockRows );
     poStmt->Bind( &nBandBlocks );
@@ -3576,11 +3574,10 @@ void GeoRasterWrapper::PackNBits( GByte* pabyData )
 {
     int nPixCount = nBandBlockSize * nRowBlockSize * nColumnBlockSize;
 
-    GByte* pabyBuffer = (GByte*) VSIMalloc( nPixCount * sizeof(GByte*) );
+    GByte* pabyBuffer = (GByte*) VSI_MALLOC_VERBOSE( nPixCount * sizeof(GByte*) );
 
     if( pabyBuffer == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory, "PackNBits" );
         return;
     }
 
@@ -3687,7 +3684,7 @@ static const int DC_HUFFVAL[256] =
  * JPEGHuffmanTable.StdDCChrominance
  *
  ***/
-
+static
 void JPEG_LoadTables( JQUANT_TBL* hquant_tbl_ptr,
                       JHUFF_TBL* huff_ac_ptr,
                       JHUFF_TBL* huff_dc_ptr,
@@ -3787,7 +3784,7 @@ void GeoRasterWrapper::UncompressJpeg( unsigned long nInSize )
                 jpeg_alloc_huff_table( (j_common_ptr) &sDInfo );
             sDInfo.dc_huff_tbl_ptrs[n] =
                 jpeg_alloc_huff_table( (j_common_ptr) &sDInfo );
-            
+
             JPEG_LoadTables( sDInfo.quant_tbl_ptrs[n],
                              sDInfo.ac_huff_tbl_ptrs[n],
                              sDInfo.dc_huff_tbl_ptrs[n],
@@ -3850,7 +3847,7 @@ unsigned long GeoRasterWrapper::CompressJpeg( void )
         jpeg_create_compress( &sCInfo );
 
         jpeg_vsiio_dest( &sCInfo, fpImage );
-        
+
         sCInfo.image_width = nColumnBlockSize;
         sCInfo.image_height = nRowBlockSize;
         sCInfo.input_components = nBandBlockSize;
@@ -3890,10 +3887,10 @@ unsigned long GeoRasterWrapper::CompressJpeg( void )
     {
         jpeg_vsiio_dest( &sCInfo, fpImage );
     }
-    
+
     jpeg_suppress_tables( &sCInfo, ! write_all_tables );
     jpeg_start_compress( &sCInfo, write_all_tables );
-    
+
     GByte* pabyScanline = pabyBlockBuf;
 
     for( int iLine = 0; iLine < nRowBlockSize; iLine++ )
@@ -3922,11 +3919,10 @@ unsigned long GeoRasterWrapper::CompressJpeg( void )
 
 bool GeoRasterWrapper::UncompressDeflate( unsigned long nBufferSize )
 {
-    GByte* pabyBuf = (GByte*) VSIMalloc( nBufferSize );
+    GByte* pabyBuf = (GByte*) VSI_MALLOC_VERBOSE( nBufferSize );
 
     if( pabyBuf == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory, "UncompressDeflate" );
         return false;
     }
 
@@ -3964,11 +3960,10 @@ unsigned long GeoRasterWrapper::CompressDeflate( void )
 {
     unsigned long nLen = ((unsigned long)(nBlockBytes * 1.1)) + 12;
 
-    GByte* pabyBuf = (GByte*) VSIMalloc( nBlockBytes );
+    GByte* pabyBuf = (GByte*) VSI_MALLOC_VERBOSE( nBlockBytes );
 
     if( pabyBuf == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory, "CompressDeflate" );
         return 0;
     }
 
diff --git a/frmts/georaster/oci_wrapper.cpp b/frmts/georaster/oci_wrapper.cpp
index 2c2f3cc..aaf7312 100644
--- a/frmts/georaster/oci_wrapper.cpp
+++ b/frmts/georaster/oci_wrapper.cpp
@@ -640,8 +640,8 @@ void OWStatement::Bind( int* pnData )
         (void*) NULL,
         (ub2*) NULL,
         (ub2*) NULL,
-        (ub4) NULL,
-        (ub4) NULL,
+        (ub4) 0,
+        (ub4*) NULL,
         (ub4) OCI_DEFAULT ),
         hError );
 }
@@ -663,8 +663,8 @@ void OWStatement::Bind( long* pnData )
         (void*) NULL,
         (ub2*) NULL,
         (ub2*) NULL,
-        (ub4) NULL,
-        (ub4) NULL,
+        (ub4) 0,
+        (ub4*) NULL,
         (ub4) OCI_DEFAULT ),
         hError );
 }
@@ -686,8 +686,8 @@ void OWStatement::Bind( double* pnData )
         (void*) NULL,
         (ub2*) NULL,
         (ub2*) NULL,
-        (ub4) NULL,
-        (ub4) NULL,
+        (ub4) 0,
+        (ub4*) NULL,
         (ub4) OCI_DEFAULT ),
         hError );
 }
@@ -709,8 +709,8 @@ void OWStatement::Bind( char* pData, long nData )
         (void*) NULL,
         (ub2*) NULL,
         (ub2*) NULL,
-        (ub4) NULL,
-        (ub4) NULL,
+        (ub4) 0,
+        (ub4*) NULL,
         (ub4) OCI_DEFAULT ),
         hError );
 }
@@ -733,7 +733,7 @@ void OWStatement::Bind( sdo_geometry** pphData )
         (ub2*) NULL,
         (ub2*) NULL,
         (ub4) 0,
-        (ub4) 0,
+        (ub4*) NULL,
         (ub4) OCI_DEFAULT ),
         hError );
 
@@ -766,8 +766,8 @@ void OWStatement::Bind( OCILobLocator** pphLocator )
         (void*) NULL,
         (ub2*) NULL,
         (ub2*) NULL,
-        (ub4) NULL,
-        (ub4) NULL,
+        (ub4) 0,
+        (ub4*) NULL,
         (ub4) OCI_DEFAULT ),
         hError );
 }
@@ -789,8 +789,8 @@ void OWStatement::Bind( OCIArray** pphData, OCIType* type )
         (void*) NULL,
         (ub2*) NULL,
         (ub2*) NULL,
-        (ub4) NULL,
-        (ub4) NULL,
+        (ub4) 0,
+        (ub4*) NULL,
         (ub4) OCI_DEFAULT ),
         hError );
 
@@ -823,8 +823,8 @@ void OWStatement::Bind( char* pszData, int nSize )
         (void*) NULL,
         (ub2*) NULL,
         (ub2*) NULL,
-        (ub4) NULL,
-        (ub4) NULL,
+        (ub4) 0,
+        (ub4*) NULL,
         (ub4) OCI_DEFAULT ),
         hError );
 }
@@ -948,7 +948,7 @@ void OWStatement::WriteCLob( OCILobLocator** pphLocator, char* pszData )
         (dvoid **) 0),
         hError );
 
-    CheckError( OCILobCreateTemporary( 
+    CheckError( OCILobCreateTemporary(
         poConnection->hSvcCtx,
         poConnection->hError,
         (OCILobLocator*) *pphLocator,
@@ -1483,8 +1483,8 @@ void OWStatement::BindArray( void* pData, long nSize )
         (void*) NULL,
         (ub2*) NULL,
         (ub2*) NULL,
-        (ub4) NULL,
-        (ub4) NULL,
+        (ub4) 0,
+        (ub4*) NULL,
         (ub4) OCI_DEFAULT ), hError );
 
     CheckError( OCIBindArrayOfStruct(
@@ -1523,7 +1523,7 @@ bool OWIsNumeric( const char *pszText )
 /*****************************************************************************/
 /*                     Parse Value after a Hint on a string                  */
 /*****************************************************************************/
-
+static
 const char *OWParseValue( const char* pszText,
                           const char* pszSeparators,
                           const char* pszHint,
@@ -1594,7 +1594,7 @@ const char* OWParseSDO_GEOR_INIT( const char* pszInsert, int nField )
 
     pszEnd++;
 
-    int nLength = pszEnd - pszStart + 1;
+    int nLength = static_cast<int>(pszEnd - pszStart + 1);
 
     char szBuffer[OWTEXT];
 
@@ -1646,7 +1646,7 @@ int OWParseEPSG( const char* pszText )
 /*                            Convert Data type description                  */
 /*****************************************************************************/
 
-const GDALDataType OWGetDataType( const char* pszCellDepth )
+GDALDataType OWGetDataType( const char* pszCellDepth )
 {
     unsigned int i;
 
diff --git a/frmts/georaster/oci_wrapper.h b/frmts/georaster/oci_wrapper.h
index 3b01732..5f4b4fc 100644
--- a/frmts/georaster/oci_wrapper.h
+++ b/frmts/georaster/oci_wrapper.h
@@ -28,8 +28,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OCI_WRAPPER_H_INCLUDED
-#define _OCI_WRAPPER_H_INCLUDED
+#ifndef OCI_WRAPPER_H_INCLUDED
+#define OCI_WRAPPER_H_INCLUDED
 
 // GDAL supporting types
 
@@ -56,10 +56,10 @@ struct OW_CellDepth {
 bool CheckError( sword nStatus, OCIError* hError );
 
 /***************************************************************************/
-/*                            Auxiliar functions                           */
+/*                            Auxiliary functions                          */
 /***************************************************************************/
 
-const GDALDataType  OWGetDataType( const char* pszCellDepth );
+GDALDataType        OWGetDataType( const char* pszCellDepth );
 const char*         OWSetDataType( const GDALDataType eType );
 int                 OWParseServerVersion( const char* pszText );
 int                 OWParseEPSG( const char* pszText );
@@ -89,7 +89,7 @@ const char*         OWParseSDO_GEOR_INIT( const char* pszInsert, int nField );
 #define OW_XMLNS        "xmlns=\"http://xmlns.oracle.com/spatial/georaster\""
 
 /***************************************************************************/
-/*                   USER DEFINED (actualy Oracle's) types                 */
+/*                   USER DEFINED (actually Oracle's) types                 */
 /***************************************************************************/
 
 typedef OCIRef SDO_GEORASTER_ref;
@@ -341,7 +341,7 @@ class OWStatement
 
 public:
 
-                        OWStatement( OWConnection* poConnect, 
+                        OWStatement( OWConnection* poConnect,
                             const char* pszStatement );
     virtual            ~OWStatement();
 
diff --git a/frmts/gff/gff_dataset.cpp b/frmts/gff/gff_dataset.cpp
index da0a520..acfd800 100644
--- a/frmts/gff/gff_dataset.cpp
+++ b/frmts/gff/gff_dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gff_dataset.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: gff_dataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Ground-based SAR Applitcations Testbed File Format driver
  * Purpose:  Support in GDAL for Sandia National Laboratory's GFF format
@@ -29,14 +29,15 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_priv.h"
-#include "gdal_pam.h"
-#include "cpl_port.h"
 #include "cpl_conv.h"
-#include "cpl_vsi.h"
+#include "cpl_port.h"
 #include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
+#include "gdal_priv.h"
 
-CPL_CVSID("$Id: gff_dataset.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: gff_dataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /*******************************************************************
  * Declaration of the GFFDataset class                             *
@@ -44,18 +45,19 @@ CPL_CVSID("$Id: gff_dataset.cpp 27745 2014-09-27 16:38:57Z goatbar $");
 
 class GFFRasterBand;
 
-class GFFDataset : public GDALPamDataset 
+class GFFDataset : public GDALPamDataset
 {
     friend class GFFRasterBand;
     VSILFILE *fp;
     GDALDataType eDataType;
-    unsigned int nEndianess;
+    unsigned int nEndianness;
     /* Some relevant headers */
     unsigned short nVersionMajor;
     unsigned short nVersionMinor;
     unsigned int nLength;
     //char *pszCreator;
-    /* I am taking this at face value (are they freakin' insane?) */
+    // TODO: Needs a better explanation.
+    /* I am taking this at face value (are they insane?) */
     //float fBPP;
     unsigned int nBPP;
 
@@ -77,9 +79,11 @@ public:
     static int Identify( GDALOpenInfo * poOpenInfo );
 };
 
-GFFDataset::GFFDataset()
+GFFDataset::GFFDataset() :
+    fp(NULL), eDataType(GDT_Unknown), nEndianness(0), nVersionMajor(0),
+    nVersionMinor(0), nLength(0), nBPP(0), nFrameCnt(0), nImageType(0),
+    nRowMajor(0), nRgCnt(0), nAzCnt(0)
 {
-    fp = NULL;
 }
 
 GFFDataset::~GFFDataset()
@@ -103,19 +107,19 @@ public:
 /************************************************************************/
 /*                           GFFRasterBand()                            */
 /************************************************************************/
-GFFRasterBand::GFFRasterBand( GFFDataset *poDS, int nBand,
-	GDALDataType eDataType ) 
+GFFRasterBand::GFFRasterBand( GFFDataset *poDSIn, int nBandIn,
+	GDALDataType eDataTypeIn )
 {
-    unsigned long nBytes;
-    this->poDS = poDS;
-    this->nBand = nBand;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
 
-    this->eDataType = eDataType;
+    this->eDataType = eDataTypeIn;
 
     nBlockXSize = poDS->GetRasterXSize();
     nBlockYSize = 1;
 
     /* Determine the number of bytes per sample */
+    unsigned long nBytes;
     switch (eDataType) {
       case GDT_CInt16:
         nBytes = 4;
@@ -129,15 +133,14 @@ GFFRasterBand::GFFRasterBand( GFFDataset *poDS, int nBand,
     }
 
     nRasterBandMemory = nBytes * poDS->GetRasterXSize();
-    nSampleSize = nBytes;
-
+    nSampleSize = static_cast<int>(nBytes);
 }
 
 /************************************************************************/
 /*                             IReadBlock()                             */
 /************************************************************************/
 
-CPLErr GFFRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
+CPLErr GFFRasterBand::IReadBlock( int /* nBlockXOff */ ,
                                   int nBlockYOff,
                                   void *pImage )
 {
@@ -153,17 +156,14 @@ CPLErr GFFRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 #if defined(CPL_MSB)
     if( GDALDataTypeIsComplex( eDataType ) )
     {
-        int nWordSize;
-
-        nWordSize = GDALGetDataTypeSize(eDataType)/16;
+        int nWordSize = GDALGetDataTypeSize(eDataType)/16;
         GDALSwapWords( pImage, nWordSize, nBlockXSize, 2*nWordSize );
-        GDALSwapWords( ((GByte *) pImage)+nWordSize, 
+        GDALSwapWords( ((GByte *) pImage)+nWordSize,
                         nWordSize, nBlockXSize, 2*nWordSize );
     }
 #endif
 
     return CE_None;
-	
 }
 
 /********************************************************************
@@ -177,10 +177,10 @@ CPLErr GFFRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /************************************************************************/
 int GFFDataset::Identify( GDALOpenInfo *poOpenInfo )
 {
-    if(poOpenInfo->nHeaderBytes < 7) 
+    if(poOpenInfo->nHeaderBytes < 7)
         return 0;
 
-    if (EQUALN((char *)poOpenInfo->pabyHeader,"GSATIMG",7)) 
+    if (STARTS_WITH_CI((char *)poOpenInfo->pabyHeader, "GSATIMG"))
         return 1;
 
     return 0;
@@ -190,12 +190,10 @@ int GFFDataset::Identify( GDALOpenInfo *poOpenInfo )
 /*                                Open()                                */
 /************************************************************************/
 
-GDALDataset *GFFDataset::Open( GDALOpenInfo *poOpenInfo ) 
+GDALDataset *GFFDataset::Open( GDALOpenInfo *poOpenInfo )
 {
-    unsigned short nCreatorLength = 0;
-
     /* Check that the dataset is indeed a GSAT File Format (GFF) file */
-    if (!GFFDataset::Identify(poOpenInfo)) 
+    if (!GFFDataset::Identify(poOpenInfo))
         return NULL;
 
 /* -------------------------------------------------------------------- */
@@ -203,14 +201,13 @@ GDALDataset *GFFDataset::Open( GDALOpenInfo *poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The GFF driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
     }
-    
-    GFFDataset *poDS;
-    poDS = new GFFDataset();
+
+    GFFDataset *poDS = new GFFDataset();
 
     poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "r" );
     if( poDS->fp == NULL )
@@ -219,15 +216,17 @@ GDALDataset *GFFDataset::Open( GDALOpenInfo *poOpenInfo )
         return NULL;
     }
 
-    /* Check the endianess of the file */
+    /* Check the endianness of the file */
     VSIFSeekL(poDS->fp,54,SEEK_SET);
-    VSIFReadL(&(poDS->nEndianess),2,1,poDS->fp);
+    VSIFReadL(&(poDS->nEndianness),2,1,poDS->fp);
 
+    const bool bSwap =
 #if defined(CPL_LSB)
-    int bSwap = 0;
+    false
 #else
-    int bSwap = 1;
+    true
 #endif
+        ;
 
     VSIFSeekL(poDS->fp,8,SEEK_SET);
     VSIFReadL(&poDS->nVersionMinor,2,1,poDS->fp);
@@ -236,6 +235,8 @@ GDALDataset *GFFDataset::Open( GDALOpenInfo *poOpenInfo )
     if (bSwap) CPL_SWAP16PTR(&poDS->nVersionMajor);
     VSIFReadL(&poDS->nLength,4,1,poDS->fp);
     if (bSwap) CPL_SWAP32PTR(&poDS->nLength);
+
+    unsigned short nCreatorLength = 0;
     VSIFReadL(&nCreatorLength,2,1,poDS->fp);
     if (bSwap) CPL_SWAP16PTR(&nCreatorLength);
     /* Hack for now... I should properly load the date metadata, for
@@ -290,9 +291,9 @@ GDALDataset *GFFDataset::Open( GDALOpenInfo *poOpenInfo )
         return NULL;
     }
 
-    /* Set raster width/height 
+    /* Set raster width/height
      * Note that the images that are complex are listed as having twice the
-     * number of X-direction values than there are actual pixels. This is 
+     * number of X-direction values than there are actual pixels. This is
      * because whoever came up with the format was crazy (actually, my
      * hunch is that they designed it very much for Matlab)
      * */
@@ -333,19 +334,21 @@ GDALDataset *GFFDataset::Open( GDALOpenInfo *poOpenInfo )
 /*                          GDALRegister_GFF()                          */
 /************************************************************************/
 
-void GDALRegister_GFF(void) 
+void GDALRegister_GFF()
 {
-    GDALDriver *poDriver;
-    if ( GDALGetDriverByName("GFF") == NULL ) {
-        poDriver = new GDALDriver();
-        poDriver->SetDescription("GFF");
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, 
-                                  "Ground-based SAR Applications Testbed File Format (.gff)");
-        poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "frmt_various.html#GFF");
-        poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "gff");
-        poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
-        poDriver->pfnOpen = GFFDataset::Open;
-        GetGDALDriverManager()->RegisterDriver(poDriver);
-    }
+    if( GDALGetDriverByName( "GFF" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription("GFF");
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem(
+        GDAL_DMD_LONGNAME,
+        "Ground-based SAR Applications Testbed File Format (.gff)");
+    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "frmt_various.html#GFF");
+    poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "gff");
+    poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
+    poDriver->pfnOpen = GFFDataset::Open;
+    GetGDALDriverManager()->RegisterDriver(poDriver);
 }
diff --git a/frmts/gif/GNUmakefile b/frmts/gif/GNUmakefile
index d625298..beffb1c 100644
--- a/frmts/gif/GNUmakefile
+++ b/frmts/gif/GNUmakefile
@@ -20,7 +20,7 @@ clean:
 	rm -f *.o $(O_OBJ)
 
 ../o/%.$(OBJ_EXT):	giflib/%.c
-	$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@
+	$(CC) -c $(CPPFLAGS) $(CFLAGS) $(NO_UNUSED_PARAMETER_FLAG) $(NO_SIGN_COMPARE) $< -o $@
 
 
 all:	$(OBJ:.o=.$(OBJ_EXT))
diff --git a/frmts/gif/biggifdataset.cpp b/frmts/gif/biggifdataset.cpp
index 7f95a80..11a1207 100644
--- a/frmts/gif/biggifdataset.cpp
+++ b/frmts/gif/biggifdataset.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: biggifdataset.cpp 28279 2015-01-03 14:37:52Z rouault $
+ * $Id: biggifdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  BIGGIF Driver
- * Purpose:  Implement GDAL support for reading large GIF files in a 
+ * Purpose:  Implement GDAL support for reading large GIF files in a
  *           streaming fashion rather than the slurp-into-memory approach
  *           of the normal GIF driver.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
@@ -30,15 +30,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
 #include "gifabstractdataset.h"
 
-CPL_CVSID("$Id: biggifdataset.cpp 28279 2015-01-03 14:37:52Z rouault $");
-
-CPL_C_START
-void	GDALRegister_BIGGIF(void);
-CPL_C_END
+CPL_CVSID("$Id: biggifdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -89,8 +86,8 @@ class BIGGifRasterBand : public GIFAbstractRasterBand
 /*                          BIGGifRasterBand()                          */
 /************************************************************************/
 
-BIGGifRasterBand::BIGGifRasterBand( BIGGIFDataset *poDS, int nBackground ) :
-    GIFAbstractRasterBand(poDS, 1, poDS->hGifFile->SavedImages, nBackground, TRUE)
+BIGGifRasterBand::BIGGifRasterBand( BIGGIFDataset *poDSIn, int nBackground ) :
+    GIFAbstractRasterBand(poDSIn, 1, poDSIn->hGifFile->SavedImages, nBackground, TRUE)
 
 {
 }
@@ -116,8 +113,8 @@ CPLErr BIGGifRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     if( poGDS->poWorkDS != NULL && nBlockYOff <= poGDS->nLastLineRead )
     {
         return poGDS->poWorkDS->
-            RasterIO( GF_Read, 0, nBlockYOff, nBlockXSize, 1, 
-                      pImage, nBlockXSize, 1, GDT_Byte, 
+            RasterIO( GF_Read, 0, nBlockYOff, nBlockXSize, 1,
+                      pImage, nBlockXSize, 1, GDT_Byte,
                       1, NULL, 0, 0, 0, NULL );
     }
 
@@ -133,9 +130,10 @@ CPLErr BIGGifRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /* -------------------------------------------------------------------- */
 /*      Read till we get our target line.                               */
 /* -------------------------------------------------------------------- */
-    while( poGDS->nLastLineRead < nBlockYOff )
+    CPLErr eErr = CE_None;
+    while( poGDS->nLastLineRead < nBlockYOff && eErr == CE_None )
     {
-        if( DGifGetLine( poGDS->hGifFile, (GifPixelType*)pImage, 
+        if( DGifGetLine( poGDS->hGifFile, (GifPixelType*)pImage,
                          nBlockXSize ) == GIF_ERROR )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -147,14 +145,14 @@ CPLErr BIGGifRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 
         if( poGDS->poWorkDS != NULL )
         {
-            poGDS->poWorkDS->RasterIO( GF_Write, 
-                                       0, poGDS->nLastLineRead, nBlockXSize, 1, 
-                                       pImage, nBlockXSize, 1, GDT_Byte, 
+            eErr = poGDS->poWorkDS->RasterIO( GF_Write,
+                                       0, poGDS->nLastLineRead, nBlockXSize, 1,
+                                       pImage, nBlockXSize, 1, GDT_Byte,
                                        1, NULL, 0, 0, 0, NULL );
         }
     }
 
-    return CE_None;
+    return eErr;
 }
 
 /************************************************************************/
@@ -168,11 +166,10 @@ CPLErr BIGGifRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /*                            BIGGIFDataset()                            */
 /************************************************************************/
 
-BIGGIFDataset::BIGGIFDataset()
-
+BIGGIFDataset::BIGGIFDataset() :
+    nLastLineRead(-1),
+    poWorkDS(NULL)
 {
-    nLastLineRead = -1;
-    poWorkDS = NULL;
 }
 
 /************************************************************************/
@@ -240,7 +237,7 @@ CPLErr BIGGIFDataset::ReOpen()
     if( hGifFile != NULL )
     {
         GDALDriver *poGTiffDriver = (GDALDriver*) GDALGetDriverByName("GTiff");
-        
+
         if( poGTiffDriver != NULL )
         {
             /* Create as a sparse file to avoid filling up the whole file */
@@ -250,8 +247,8 @@ CPLErr BIGGIFDataset::ReOpen()
 
             osTempFilename += ".tif";
 
-            poWorkDS = poGTiffDriver->Create( osTempFilename, 
-                                              nRasterXSize, nRasterYSize, 1, 
+            poWorkDS = poGTiffDriver->Create( osTempFilename,
+                                              nRasterXSize, nRasterYSize, 1,
                                               GDT_Byte, const_cast<char**>(apszOptions));
         }
     }
@@ -265,7 +262,7 @@ CPLErr BIGGIFDataset::ReOpen()
     hGifFile = GIFAbstractDataset::myDGifOpen( fp, GIFAbstractDataset::ReadFunc );
     if( hGifFile == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "DGifOpen() failed.  Perhaps the gif file is corrupt?\n" );
 
         return CE_Failure;
@@ -274,47 +271,27 @@ CPLErr BIGGIFDataset::ReOpen()
 /* -------------------------------------------------------------------- */
 /*      Find the first image record.                                    */
 /* -------------------------------------------------------------------- */
-    GifRecordType RecordType = TERMINATE_RECORD_TYPE;
-
-    while( DGifGetRecordType(hGifFile, &RecordType) != GIF_ERROR
-           && RecordType != TERMINATE_RECORD_TYPE
-           && RecordType != IMAGE_DESC_RECORD_TYPE )
-    {
-        /* Skip extension records found before IMAGE_DESC_RECORD_TYPE */
-        if (RecordType == EXTENSION_RECORD_TYPE)
-        {
-            int nFunction;
-            GifByteType *pExtData;
-            if (DGifGetExtension(hGifFile, &nFunction, &pExtData) == GIF_ERROR)
-                break;
-            while (pExtData != NULL)
-            {
-                if (DGifGetExtensionNext(hGifFile, &pExtData) == GIF_ERROR)
-                    break;
-            }
-        }
-    }
-
+    GifRecordType RecordType = FindFirstImage(hGifFile);
     if( RecordType != IMAGE_DESC_RECORD_TYPE )
     {
         GIFAbstractDataset::myDGifCloseFile( hGifFile );
         hGifFile = NULL;
 
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "Failed to find image description record in GIF file." );
         return CE_Failure;
     }
-    
+
     if (DGifGetImageDesc(hGifFile) == GIF_ERROR)
     {
         GIFAbstractDataset::myDGifCloseFile( hGifFile );
         hGifFile = NULL;
 
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "Image description reading failed in GIF file." );
         return CE_Failure;
     }
-    
+
     return CE_None;
 }
 
@@ -331,7 +308,7 @@ GDALDataset *BIGGIFDataset::Open( GDALOpenInfo * poOpenInfo )
 
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The GIF driver does not support update access to existing"
                   " files.\n" );
         return NULL;
@@ -340,9 +317,7 @@ GDALDataset *BIGGIFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    BIGGIFDataset 	*poDS;
-
-    poDS = new BIGGIFDataset();
+    BIGGIFDataset *poDS = new BIGGIFDataset();
 
     poDS->fp = poOpenInfo->fpL;
     poOpenInfo->fpL = NULL;
@@ -356,7 +331,7 @@ GDALDataset *BIGGIFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Capture some information from the file that is of interest.     */
 /* -------------------------------------------------------------------- */
-    
+
     poDS->nRasterXSize = poDS->hGifFile->SavedImages[0].ImageDesc.Width;
     poDS->nRasterYSize = poDS->hGifFile->SavedImages[0].ImageDesc.Height;
     if( poDS->hGifFile->SavedImages[0].ImageDesc.ColorMap == NULL &&
@@ -370,8 +345,8 @@ GDALDataset *BIGGIFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    poDS->SetBand( 1, 
-                   new BIGGifRasterBand( poDS, 
+    poDS->SetBand( 1,
+                   new BIGGifRasterBand( poDS,
                                          poDS->hGifFile->SBackGroundColor ));
 
 /* -------------------------------------------------------------------- */
@@ -401,25 +376,23 @@ GDALDataset *BIGGIFDataset::Open( GDALOpenInfo * poOpenInfo )
 void GDALRegister_BIGGIF()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "BIGGIF" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "BIGGIF" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "BIGGIF" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Graphics Interchange Format (.gif)" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_gif.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gif" );
-        poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/gif" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = BIGGIFDataset::Open;
-        poDriver->pfnIdentify = GIFAbstractDataset::Identify;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+     GDALDriver *poDriver = new GDALDriver();
+
+     poDriver->SetDescription( "BIGGIF" );
+     poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+     poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                                "Graphics Interchange Format (.gif)" );
+     poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                                "frmt_gif.html" );
+     poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gif" );
+     poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/gif" );
+     poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+     poDriver->pfnOpen = BIGGIFDataset::Open;
+     poDriver->pfnIdentify = GIFAbstractDataset::Identify;
+
+     GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/gif/frmt_gif.html b/frmts/gif/frmt_gif.html
index fdb0e30..86aced4 100644
--- a/frmts/gif/frmt_gif.html
+++ b/frmts/gif/frmt_gif.html
@@ -25,12 +25,12 @@ stored as XML raw content in the xml:XMP metadata domain.<p>
 
 GIF files can only be created as 1 8bit band using the "CreateCopy" mechanism.
 If written from a file that is not colormapped, a default greyscale colormap
-is generated.  Tranparent GIFs are not currently supported on creation.<p>
+is generated.  Transparent GIFs are not currently supported on creation.<p>
 
 <b>WORLDFILE=ON</b>: Force the generation of an associated ESRI world
 file (.wld).<p>
 
-Interlaced (progressive) GIF files can be generated by supplying the 
+Interlaced (progressive) GIF files can be generated by supplying the
 <b>INTERLACING=ON</b> option on creation. <p>
 
 Starting with GDAL 1.7.0, GDAL's internal GIF support is implemented based
@@ -38,7 +38,7 @@ on source from the giflib 4.1.6 library (written by Gershon Elbor, Eric Raymond
 and Toshio Kuratomi), hence generating LZW compressed GIF.<p>
 
 The driver was written with the financial support of the <a href="http://www.dmsolutions.ca/">DM
-Solutions Group</a>, and <a href="http://www.ciet.org/">CIET 
+Solutions Group</a>, and <a href="http://www.ciet.org/">CIET
 International</a>.<p>
 
 See Also:<p>
diff --git a/frmts/gif/gifabstractdataset.cpp b/frmts/gif/gifabstractdataset.cpp
index c9d2b3b..e37cad4 100644
--- a/frmts/gif/gifabstractdataset.cpp
+++ b/frmts/gif/gifabstractdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gifabstractdataset.cpp 29222 2015-05-21 15:06:39Z rouault $
+ * $Id: gifabstractdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  GIF Driver
  * Purpose:  GIF Abstract Dataset
@@ -29,10 +29,10 @@
 
 #include "gifabstractdataset.h"
 
-CPL_CVSID("$Id: gifabstractdataset.cpp 29222 2015-05-21 15:06:39Z rouault $");
+CPL_CVSID("$Id: gifabstractdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
-static const int InterlacedOffset[] = { 0, 4, 2, 1 }; 
-static const int InterlacedJumps[] = { 8, 8, 4, 2 };  
+static const int InterlacedOffset[] = { 0, 4, 2, 1 };
+static const int InterlacedJumps[] = { 8, 8, 4, 2 };
 
 /************************************************************************/
 /* ==================================================================== */
@@ -45,25 +45,21 @@ static const int InterlacedJumps[] = { 8, 8, 4, 2 };
 /*                         GIFAbstractDataset()                         */
 /************************************************************************/
 
-GIFAbstractDataset::GIFAbstractDataset()
-
+GIFAbstractDataset::GIFAbstractDataset() :
+    fp(NULL),
+    hGifFile(NULL),
+    pszProjection(NULL),
+    bGeoTransformValid(FALSE),
+    nGCPCount(0),
+    pasGCPList(NULL),
+    bHasReadXMPMetadata(FALSE)
 {
-    hGifFile = NULL;
-    fp = NULL;
-
-    pszProjection = NULL;
-    bGeoTransformValid = FALSE;
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
-
-    nGCPCount = 0;
-    pasGCPList = NULL;
-
-    bHasReadXMPMetadata = FALSE;
 }
 
 /************************************************************************/
@@ -91,7 +87,6 @@ GIFAbstractDataset::~GIFAbstractDataset()
         VSIFCloseL( fp );
 }
 
-
 /************************************************************************/
 /*                       GIFCollectXMPMetadata()                        */
 /************************************************************************/
@@ -113,16 +108,15 @@ static CPLString GIFCollectXMPMetadata(VSILFILE* fp)
     /* Loop over file */
 
     int iStartSearchOffset = 1024;
-    while(TRUE)
+    while(true)
     {
-        int nRead = VSIFReadL( abyBuffer + 1024, 1, 1024, fp );
+        int nRead = static_cast<int>(VSIFReadL( abyBuffer + 1024, 1, 1024, fp ));
         if (nRead <= 0)
             break;
         abyBuffer[1024 + nRead] = 0;
 
-        int i;
         int iFoundOffset = -1;
-        for(i=iStartSearchOffset;i<1024+nRead - 14;i++)
+        for(int i=iStartSearchOffset;i<1024+nRead - 14;i++)
         {
             if (memcmp(abyBuffer + i, "\x21\xff\x0bXMP DataXMP", 14) == 0)
             {
@@ -152,7 +146,7 @@ static CPLString GIFCollectXMPMetadata(VSILFILE* fp)
                     break;
                 pszXMP = pszNewXMP;
 
-                nRead = VSIFReadL( pszXMP + nSize, 1, 1024, fp );
+                nRead = static_cast<int>(VSIFReadL( pszXMP + nSize, 1, 1024, fp ));
                 if (nRead <= 0)
                     break;
 
@@ -247,8 +241,8 @@ const char *GIFAbstractDataset::GetProjectionRef()
 {
     if ( pszProjection && bGeoTransformValid )
         return pszProjection;
-    else
-        return GDALPamDataset::GetProjectionRef();
+
+    return GDALPamDataset::GetProjectionRef();
 }
 
 /************************************************************************/
@@ -263,8 +257,8 @@ CPLErr GIFAbstractDataset::GetGeoTransform( double * padfTransform )
         memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
         return CE_None;
     }
-    else
-        return GDALPamDataset::GetGeoTransform( padfTransform );
+
+    return GDALPamDataset::GetGeoTransform( padfTransform );
 }
 
 /************************************************************************/
@@ -276,8 +270,8 @@ int GIFAbstractDataset::GetGCPCount()
 {
     if (nGCPCount > 0)
         return nGCPCount;
-    else
-        return GDALPamDataset::GetGCPCount();
+
+    return GDALPamDataset::GetGCPCount();
 }
 
 /************************************************************************/
@@ -289,8 +283,8 @@ const char *GIFAbstractDataset::GetGCPProjection()
 {
     if ( pszProjection && nGCPCount > 0 )
         return pszProjection;
-    else
-        return GDALPamDataset::GetGCPProjection();
+
+    return GDALPamDataset::GetGCPProjection();
 }
 
 /************************************************************************/
@@ -302,8 +296,8 @@ const GDAL_GCP *GIFAbstractDataset::GetGCPs()
 {
     if (nGCPCount > 0)
         return pasGCPList;
-    else
-        return GDALPamDataset::GetGCPs();
+
+    return GDALPamDataset::GetGCPs();
 }
 
 /************************************************************************/
@@ -316,8 +310,8 @@ int GIFAbstractDataset::Identify( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->nHeaderBytes < 8 )
         return FALSE;
 
-    if( strncmp((const char *) poOpenInfo->pabyHeader, "GIF87a",5) != 0
-        && strncmp((const char *) poOpenInfo->pabyHeader, "GIF89a",5) != 0 )
+    if( !STARTS_WITH((const char *) poOpenInfo->pabyHeader, "GIF87a")
+        && !STARTS_WITH((const char *) poOpenInfo->pabyHeader, "GIF89a") )
         return FALSE;
 
     return TRUE;
@@ -351,7 +345,7 @@ void GIFAbstractDataset::DetectGeoreferencing( GDALOpenInfo * poOpenInfo )
 
     bGeoTransformValid =
         GDALReadWorldFile2( poOpenInfo->pszFilename, NULL,
-                            adfGeoTransform, poOpenInfo->GetSiblingFiles(), 
+                            adfGeoTransform, poOpenInfo->GetSiblingFiles(),
                             &pszWldFilename );
     if ( !bGeoTransformValid )
     {
@@ -416,12 +410,42 @@ int GIFAbstractDataset::myEGifCloseFile( GifFileType *hGifFile )
 /*      Proxy function for reading from GIF file.                       */
 /************************************************************************/
 
-int GIFAbstractDataset::ReadFunc( GifFileType *psGFile, GifByteType *pabyBuffer, 
+int GIFAbstractDataset::ReadFunc( GifFileType *psGFile, GifByteType *pabyBuffer,
                                         int nBytesToRead )
 
 {
-    return VSIFReadL( pabyBuffer, 1, nBytesToRead, 
-                      (VSILFILE *) psGFile->UserData );
+    return static_cast<int>(VSIFReadL( pabyBuffer, 1, nBytesToRead,
+                      (VSILFILE *) psGFile->UserData ));
+}
+
+/************************************************************************/
+/*                          FindFirstImage()                            */
+/************************************************************************/
+
+GifRecordType GIFAbstractDataset::FindFirstImage( GifFileType* hGifFile )
+{
+    GifRecordType RecordType = TERMINATE_RECORD_TYPE;
+
+    while( DGifGetRecordType(hGifFile, &RecordType) != GIF_ERROR
+           && RecordType != TERMINATE_RECORD_TYPE
+           && RecordType != IMAGE_DESC_RECORD_TYPE )
+    {
+        /* Skip extension records found before IMAGE_DESC_RECORD_TYPE */
+        if (RecordType == EXTENSION_RECORD_TYPE)
+        {
+            int nFunction;
+            GifByteType *pExtData;
+            if (DGifGetExtension(hGifFile, &nFunction, &pExtData) == GIF_ERROR)
+                break;
+            while (pExtData != NULL)
+            {
+                if (DGifGetExtensionNext(hGifFile, &pExtData) == GIF_ERROR)
+                    break;
+            }
+        }
+    }
+
+    return RecordType;
 }
 
 /************************************************************************/
@@ -429,13 +453,15 @@ int GIFAbstractDataset::ReadFunc( GifFileType *psGFile, GifByteType *pabyBuffer,
 /************************************************************************/
 
 GIFAbstractRasterBand::GIFAbstractRasterBand(
-                              GIFAbstractDataset *poDS, int nBand, 
+                              GIFAbstractDataset *poDSIn, int nBandIn,
                               SavedImage *psSavedImage, int nBackground,
-                              int bAdvertizeInterlacedMDI )
-
+                              int bAdvertizeInterlacedMDI ) :
+    panInterlaceMap(NULL),
+    poColorTable(NULL),
+    nTransparentColor(0)
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
 
     eDataType = GDT_Byte;
 
@@ -444,10 +470,6 @@ GIFAbstractRasterBand::GIFAbstractRasterBand(
 
     psImage = psSavedImage;
 
-    poColorTable = NULL;
-    panInterlaceMap = NULL;
-    nTransparentColor = 0;
-
     if (psImage == NULL)
         return;
 
@@ -457,18 +479,18 @@ GIFAbstractRasterBand::GIFAbstractRasterBand(
     panInterlaceMap = NULL;
     if( psImage->ImageDesc.Interlace )
     {
-        int     i, j, iLine = 0;
-        
+        int iLine = 0;
+
         if( bAdvertizeInterlacedMDI )
             poDS->SetMetadataItem( "INTERLACED", "YES", "IMAGE_STRUCTURE" );
 
-        panInterlaceMap = (int *) CPLCalloc(poDS->nRasterYSize,sizeof(int));
+        panInterlaceMap = (int *) CPLCalloc(poDSIn->nRasterYSize,sizeof(int));
 
-        for (i = 0; i < 4; i++)
+        for (int i = 0; i < 4; i++)
         {
-            for (j = InterlacedOffset[i]; 
-                 j < poDS->nRasterYSize;
-                 j += InterlacedJumps[i]) 
+            for (int j = InterlacedOffset[i];
+                 j < poDSIn->nRasterYSize;
+                 j += InterlacedJumps[i])
                 panInterlaceMap[j] = iLine++;
         }
     }
@@ -479,10 +501,8 @@ GIFAbstractRasterBand::GIFAbstractRasterBand(
 /*      Check for transparency.  We just take the first graphic         */
 /*      control extension block we find, if any.                        */
 /* -------------------------------------------------------------------- */
-    int iExtBlock;
-
     nTransparentColor = -1;
-    for( iExtBlock = 0; iExtBlock < psImage->ExtensionBlockCount; iExtBlock++ )
+    for( int iExtBlock = 0; iExtBlock < psImage->ExtensionBlockCount; iExtBlock++ )
     {
         unsigned char *pExtData;
 
@@ -504,7 +524,7 @@ GIFAbstractRasterBand::GIFAbstractRasterBand(
 /* -------------------------------------------------------------------- */
     ColorMapObject      *psGifCT = psImage->ImageDesc.ColorMap;
     if( psGifCT == NULL )
-        psGifCT = poDS->hGifFile->SColorMap;
+        psGifCT = poDSIn->hGifFile->SColorMap;
 
     poColorTable = new GDALColorTable();
     for( int iColor = 0; iColor < psGifCT->ColorCount; iColor++ )
@@ -532,8 +552,8 @@ GIFAbstractRasterBand::GIFAbstractRasterBand(
     if( nBackground != 255 )
     {
         char szBackground[10];
-        
-        sprintf( szBackground, "%d", nBackground );
+
+        snprintf( szBackground, sizeof(szBackground), "%d", nBackground );
         SetMetadataItem( "GIF_BACKGROUND", szBackground );
     }
 }
diff --git a/frmts/gif/gifabstractdataset.h b/frmts/gif/gifabstractdataset.h
index 66c9ddf..fd2cf88 100644
--- a/frmts/gif/gifabstractdataset.h
+++ b/frmts/gif/gifabstractdataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gifabstractdataset.h 29222 2015-05-21 15:06:39Z rouault $
+ * $Id: gifabstractdataset.h 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  GIF Driver
  * Purpose:  GIF Abstract Dataset
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _GIFABSTRACTDATASET_H_INCLUDED
-#define _GIFABSTRACTDATASET_H_INCLUDED
+#ifndef GIFABSTRACTDATASET_H_INCLUDED
+#define GIFABSTRACTDATASET_H_INCLUDED
 
 #include "gdal_pam.h"
 
@@ -85,8 +85,9 @@ class GIFAbstractDataset : public GDALPamDataset
     static GifFileType* myDGifOpen( void *userPtr, InputFunc readFunc );
     static int          myDGifCloseFile( GifFileType *hGifFile );
     static int          myEGifCloseFile( GifFileType *hGifFile );
-    static int          ReadFunc( GifFileType *psGFile, GifByteType *pabyBuffer, 
+    static int          ReadFunc( GifFileType *psGFile, GifByteType *pabyBuffer,
                                   int nBytesToRead );
+    static GifRecordType FindFirstImage( GifFileType* hGifFile );
 };
 
 /************************************************************************/
@@ -101,14 +102,14 @@ class GIFAbstractRasterBand : public GDALPamRasterBand
     SavedImage  *psImage;
 
     int         *panInterlaceMap;
-    
+
     GDALColorTable *poColorTable;
 
     int         nTransparentColor;
 
   public:
 
-                   GIFAbstractRasterBand(GIFAbstractDataset *poDS, int nBand, 
+                   GIFAbstractRasterBand(GIFAbstractDataset *poDS, int nBand,
                                          SavedImage *psSavedImage, int nBackground,
                                          int bAdvertizeInterlacedMDI );
     virtual       ~GIFAbstractRasterBand();
diff --git a/frmts/gif/gifdataset.cpp b/frmts/gif/gifdataset.cpp
index 1483b2f..79668da 100644
--- a/frmts/gif/gifdataset.cpp
+++ b/frmts/gif/gifdataset.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: gifdataset.cpp 28785 2015-03-26 20:46:45Z goatbar $
+ * $Id: gifdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  GIF Driver
- * Purpose:  Implement GDAL GIF Support using libungif code.  
+ * Purpose:  Implement GDAL GIF Support using libungif code.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -28,15 +28,14 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
 #include "gifabstractdataset.h"
 
-CPL_CVSID("$Id: gifdataset.cpp 28785 2015-03-26 20:46:45Z goatbar $");
+CPL_CVSID("$Id: gifdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 CPL_C_START
-void	GDALRegister_GIF(void);
-
 #if !(defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5)
 
 // This prototype seems to have been messed up!
@@ -50,8 +49,8 @@ GifFileType * EGifOpen(void* userData, OutputFunc writeFunc);
 
 CPL_C_END
 
-static const int InterlacedOffset[] = { 0, 4, 2, 1 }; 
-static const int InterlacedJumps[] = { 8, 8, 4, 2 };  
+static const int InterlacedOffset[] = { 0, 4, 2, 1 };
+static const int InterlacedJumps[] = { 8, 8, 4, 2 };
 
 static int VSIGIFWriteFunc( GifFileType *, const GifByteType *, int );
 
@@ -77,7 +76,6 @@ class GIFDataset : public GIFAbstractDataset
                                     int bStrict, char ** papszOptions,
                                     GDALProgressFunc pfnProgress,
                                     void * pProgressData );
-
 };
 
 /************************************************************************/
@@ -98,9 +96,9 @@ class GIFRasterBand : public GIFAbstractRasterBand
 /*                           GIFRasterBand()                            */
 /************************************************************************/
 
-GIFRasterBand::GIFRasterBand( GIFDataset *poDS, int nBand, 
+GIFRasterBand::GIFRasterBand( GIFDataset *poDSIn, int nBandIn,
                               SavedImage *psSavedImage, int nBackground ) :
-                GIFAbstractRasterBand(poDS, nBand, psSavedImage, nBackground, FALSE)
+                GIFAbstractRasterBand(poDSIn, nBandIn, psSavedImage, nBackground, FALSE)
 
 {
 }
@@ -124,7 +122,7 @@ CPLErr GIFRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     if( panInterlaceMap != NULL )
         nBlockYOff = panInterlaceMap[nBlockYOff];
 
-    memcpy( pImage, psImage->RasterBits + nBlockYOff * nBlockXSize, 
+    memcpy( pImage, psImage->RasterBits + nBlockYOff * nBlockXSize,
             nBlockXSize );
 
     return CE_None;
@@ -157,7 +155,7 @@ GDALDataset *GIFDataset::Open( GDALOpenInfo * poOpenInfo )
 
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The GIF driver does not support update access to existing"
                   " files.\n" );
         return NULL;
@@ -166,18 +164,15 @@ GDALDataset *GIFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Ingest.                                                         */
 /* -------------------------------------------------------------------- */
-    GifFileType 	*hGifFile;
-    VSILFILE                *fp;
-    int                  nGifErr;
-
-    fp = poOpenInfo->fpL;
+    VSILFILE *fp = poOpenInfo->fpL;
     poOpenInfo->fpL = NULL;
 
-    hGifFile = GIFAbstractDataset::myDGifOpen( fp, GIFAbstractDataset::ReadFunc );
+    GifFileType *hGifFile
+        = GIFAbstractDataset::myDGifOpen( fp, GIFAbstractDataset::ReadFunc );
     if( hGifFile == NULL )
     {
         VSIFCloseL( fp );
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "DGifOpen() failed for %s.\n"
                   "Perhaps the gif file is corrupt?\n",
                   poOpenInfo->pszFilename );
@@ -191,27 +186,7 @@ GDALDataset *GIFDataset::Open( GDALOpenInfo * poOpenInfo )
     /* -------------------------------------------------------------------- */
     /*      Find the first image record.                                    */
     /* -------------------------------------------------------------------- */
-    GifRecordType RecordType = TERMINATE_RECORD_TYPE;
-
-    while( DGifGetRecordType(hGifFile, &RecordType) != GIF_ERROR
-        && RecordType != TERMINATE_RECORD_TYPE
-        && RecordType != IMAGE_DESC_RECORD_TYPE )
-    {
-        /* Skip extension records found before IMAGE_DESC_RECORD_TYPE */
-        if (RecordType == EXTENSION_RECORD_TYPE)
-        {
-            int nFunction;
-            GifByteType *pExtData;
-            if (DGifGetExtension(hGifFile, &nFunction, &pExtData) == GIF_ERROR)
-                break;
-            while (pExtData != NULL)
-            {
-                if (DGifGetExtensionNext(hGifFile, &pExtData) == GIF_ERROR)
-                    break;
-            }
-        }
-    }
-
+    GifRecordType RecordType = FindFirstImage(hGifFile);
     if( RecordType == IMAGE_DESC_RECORD_TYPE  &&
         DGifGetImageDesc(hGifFile) != GIF_ERROR)
     {
@@ -238,7 +213,7 @@ GDALDataset *GIFDataset::Open( GDALOpenInfo * poOpenInfo )
     if( hGifFile == NULL )
     {
         VSIFCloseL( fp );
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "DGifOpen() failed for %s.\n"
                   "Perhaps the gif file is corrupt?\n",
                   poOpenInfo->pszFilename );
@@ -246,7 +221,7 @@ GDALDataset *GIFDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    nGifErr = DGifSlurp( hGifFile );
+    int nGifErr = DGifSlurp( hGifFile );
 
     if( nGifErr != GIF_OK || hGifFile->SavedImages == NULL )
     {
@@ -263,7 +238,7 @@ GDALDataset *GIFDataset::Open( GDALOpenInfo * poOpenInfo )
             return NULL;
          }
          else
-            CPLError( CE_Failure, CPLE_OpenFailed, 
+            CPLError( CE_Failure, CPLE_OpenFailed,
                         "DGifSlurp() failed for %s.\n"
                         "Perhaps the gif file is corrupt?\n",
                         poOpenInfo->pszFilename );
@@ -274,9 +249,7 @@ GDALDataset *GIFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    GIFDataset 	*poDS;
-
-    poDS = new GIFDataset();
+    GIFDataset *poDS = new GIFDataset();
 
     poDS->fp = fp;
     poDS->eAccess = GA_ReadOnly;
@@ -309,7 +282,7 @@ GDALDataset *GIFDataset::Open( GDALOpenInfo * poOpenInfo )
         /* Since giflib 5, de-interlacing is done by DGifSlurp() */
         psImage->ImageDesc.Interlace = 0;
 #endif
-        poDS->SetBand( poDS->nBands+1, 
+        poDS->SetBand( poDS->nBands+1,
                        new GIFRasterBand( poDS, poDS->nBands+1, psImage,
                                           hGifFile->SBackGroundColor ));
     }
@@ -371,47 +344,45 @@ static void GDALPrintGifError(CPL_UNUSED GifFileType *hGifFile, const char* pszM
 /************************************************************************/
 
 GDALDataset *
-GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
-               int bStrict, char ** papszOptions, 
+GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
+               int bStrict, char ** papszOptions,
                GDALProgressFunc pfnProgress, void * pProgressData )
 
 {
-    int  nBands = poSrcDS->GetRasterCount();
-    int  nXSize = poSrcDS->GetRasterXSize();
-    int  nYSize = poSrcDS->GetRasterYSize();
-    int	 bInterlace = FALSE;
-
 /* -------------------------------------------------------------------- */
 /*      Check for interlaced option.                                    */
 /* -------------------------------------------------------------------- */
-    bInterlace = CSLFetchBoolean(papszOptions, "INTERLACING", FALSE);
+    int bInterlace = CSLFetchBoolean(papszOptions, "INTERLACING", FALSE);
 
 /* -------------------------------------------------------------------- */
 /*      Some some rudimentary checks                                    */
 /* -------------------------------------------------------------------- */
+    const int nBands = poSrcDS->GetRasterCount();
     if( nBands != 1 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "GIF driver only supports one band images.\n" );
 
         return NULL;
     }
 
+    const int nXSize = poSrcDS->GetRasterXSize();
+    const int nYSize = poSrcDS->GetRasterYSize();
     if (nXSize > 65535 || nYSize > 65535)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "GIF driver only supports datasets up to 65535x65535 size.\n" );
 
         return NULL;
     }
 
-    if( poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte 
+    if( poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte
         && bStrict )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "GIF driver doesn't support data type %s. "
-                  "Only eight bit bands supported.\n", 
-                  GDALGetDataTypeName( 
+                  "Only eight bit bands supported.\n",
+                  GDALGetDataTypeName(
                       poSrcDS->GetRasterBand(1)->GetRasterDataType()) );
 
         return NULL;
@@ -420,18 +391,16 @@ GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Open the output file.                                           */
 /* -------------------------------------------------------------------- */
-    GifFileType *hGifFile;
-    VSILFILE *fp;
-
-    fp = VSIFOpenL( pszFilename, "wb" );
+    VSILFILE *fp  = VSIFOpenL( pszFilename, "wb" );
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Failed to create %s:\n%s", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to create %s:\n%s",
                   pszFilename, VSIStrerror( errno ) );
         return NULL;
     }
 
+    GifFileType *hGifFile;
 #if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5
     int nError;
     hGifFile = EGifOpen( fp, VSIGIFWriteFunc, &nError );
@@ -441,7 +410,7 @@ GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     if( hGifFile == NULL )
     {
         VSIFCloseL( fp );
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "EGifOpenFilename(%s) failed.  Does file already exist?",
                   pszFilename );
 
@@ -453,12 +422,19 @@ GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
     GDALRasterBand	*poBand = poSrcDS->GetRasterBand(1);
     ColorMapObject	*psGifCT;
-    int			iColor;
 
     if( poBand->GetColorTable() == NULL )
     {
         psGifCT = GifMakeMapObject( 256, NULL );
-        for( iColor = 0; iColor < 256; iColor++ )
+        if( psGifCT == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Cannot allocate color table");
+            GIFAbstractDataset::myEGifCloseFile(hGifFile);
+            VSIFCloseL( fp );
+            return NULL;
+        }
+        for( int iColor = 0; iColor < 256; iColor++ )
         {
             psGifCT->Colors[iColor].Red = (GifByteType) iColor;
             psGifCT->Colors[iColor].Green = (GifByteType) iColor;
@@ -468,13 +444,22 @@ GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     else
     {
         GDALColorTable	*poCT = poBand->GetColorTable();
-        int nFullCount = 1;
+        int nFullCount = 2;
 
         while( nFullCount < poCT->GetColorEntryCount() )
             nFullCount = nFullCount * 2;
 
         psGifCT = GifMakeMapObject( nFullCount, NULL );
-        for( iColor = 0; iColor < poCT->GetColorEntryCount(); iColor++ )
+        if( psGifCT == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Cannot allocate color table");
+            GIFAbstractDataset::myEGifCloseFile(hGifFile);
+            VSIFCloseL( fp );
+            return NULL;
+        }
+        int iColor = 0;
+        for( ; iColor < poCT->GetColorEntryCount(); iColor++ )
         {
             GDALColorEntry	sEntry;
 
@@ -494,7 +479,7 @@ GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Setup parameters.                                               */
 /* -------------------------------------------------------------------- */
-    if (EGifPutScreenDesc(hGifFile, nXSize, nYSize, 
+    if (EGifPutScreenDesc(hGifFile, nXSize, nYSize,
                           8, /* ColorRes */
                           255, /* Background */
                           psGifCT) == GIF_ERROR)
@@ -505,7 +490,7 @@ GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         VSIFCloseL( fp );
         return NULL;
     }
-    
+
     GifFreeMapObject(psGifCT);
     psGifCT = NULL;
 
@@ -533,26 +518,26 @@ GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Loop over image, copying image data.                            */
 /* -------------------------------------------------------------------- */
-    CPLErr      eErr;
-    GDALPamDataset *poDS;
-    GByte      *pabyScanline;
-
-    pabyScanline = (GByte *) CPLMalloc( nXSize );
+    GDALPamDataset *poDS = NULL;
+    GByte *pabyScanline = (GByte *) CPLMalloc( nXSize );
 
     if( !pfnProgress( 0.0, NULL, pProgressData ) )
-        eErr = CE_Failure;
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Unable to setup progress." );
+    }
 
     if( !bInterlace )
     {
         for( int iLine = 0; iLine < nYSize; iLine++ )
         {
-            eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, 
-                                     pabyScanline, nXSize, 1, GDT_Byte,
-                                     nBands, nBands * nXSize, NULL );
+            const CPLErr eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1,
+                                                  pabyScanline, nXSize, 1, GDT_Byte,
+                                                  nBands, nBands * nXSize, NULL );
 
             if( eErr != CE_None || EGifPutLine( hGifFile, pabyScanline, nXSize ) == GIF_ERROR )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "Error writing gif file." );
                 goto error;
             }
@@ -566,29 +551,28 @@ GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     }
     else
     {
-        int 	i, j;
-        int nLinesRead = 0;
         int nLinesToRead = 0;
-        for ( i = 0; i < 4; i++)
+        for ( int i = 0; i < 4; i++)
         {
-            for (j = InterlacedOffset[i]; j < nYSize; j += InterlacedJumps[i]) 
+            for ( int j = InterlacedOffset[i]; j < nYSize; j += InterlacedJumps[i] )
             {
                 nLinesToRead ++;
             }
         }
 
+        int nLinesRead = 0;
         /* Need to perform 4 passes on the images: */
-        for ( i = 0; i < 4; i++)
+        for ( int i = 0; i < 4; i++)
         {
-            for (j = InterlacedOffset[i]; j < nYSize; j += InterlacedJumps[i]) 
+            for ( int j = InterlacedOffset[i]; j < nYSize; j += InterlacedJumps[i] )
             {
-                eErr= poBand->RasterIO( GF_Read, 0, j, nXSize, 1, 
+                const CPLErr eErr= poBand->RasterIO( GF_Read, 0, j, nXSize, 1,
                                         pabyScanline, nXSize, 1, GDT_Byte,
                                         1, nXSize, NULL );
 
                 if (eErr != CE_None || EGifPutLine(hGifFile, pabyScanline, nXSize) == GIF_ERROR)
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined, 
+                    CPLError( CE_Failure, CPLE_AppDefined,
                             "Error writing gif file." );
                     goto error;
                 }
@@ -610,7 +594,7 @@ GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
     if (GIFAbstractDataset::myEGifCloseFile(hGifFile) == GIF_ERROR)
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "EGifCloseFile() failed.\n" );
         hGifFile = NULL;
         goto error;
@@ -625,9 +609,9 @@ GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
     if( CSLFetchBoolean( papszOptions, "WORLDFILE", FALSE ) )
     {
-    	double      adfGeoTransform[6];
-	
-	if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None )
+        double      adfGeoTransform[6];
+
+        if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None )
             GDALWriteWorldFile( pszFilename, "wld", adfGeoTransform );
     }
 
@@ -635,7 +619,7 @@ GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      Re-open dataset, and copy any auxiliary pam information.         */
 /* -------------------------------------------------------------------- */
 
-    /* If outputing to stdout, we can't reopen it, so we'll return */
+    /* If writing to stdout, we can't reopen it, so return */
     /* a fake dataset to make the caller happy */
     CPLPushErrorHandler(CPLQuietErrorHandler);
     poDS = (GDALPamDataset*) GDALOpen(pszFilename, GA_ReadOnly);
@@ -673,7 +657,7 @@ error:
 /*      Proxy write function.                                           */
 /************************************************************************/
 
-static int VSIGIFWriteFunc( GifFileType *psGFile, 
+static int VSIGIFWriteFunc( GifFileType *psGFile,
                             const GifByteType *pabyBuffer, int nBytesToWrite )
 
 {
@@ -690,50 +674,46 @@ static int VSIGIFWriteFunc( GifFileType *psGFile,
         /* Most readers don't even care if it is GIF87a or GIF89a, but it is */
         /* better to write the right version */
 
-        int nRet = VSIFWriteL("GIF89a", 1, 6, fp);
+        size_t nRet = VSIFWriteL("GIF89a", 1, 6, fp);
         nRet += VSIFWriteL( (char *) pabyBuffer + 6, 1, nBytesToWrite - 6, fp );
-        return nRet;
+        return static_cast<int>(nRet);
     }
     else
-        return VSIFWriteL( (void *) pabyBuffer, 1, nBytesToWrite, fp );
+        return static_cast<int>(VSIFWriteL( (void *) pabyBuffer, 1, nBytesToWrite, fp ));
 }
 
 /************************************************************************/
-/*                          GDALRegister_GIF()                        */
+/*                          GDALRegister_GIF()                          */
 /************************************************************************/
 
 void GDALRegister_GIF()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "GIF" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "GIF" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "GIF" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Graphics Interchange Format (.gif)" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_gif.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gif" );
-        poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/gif" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte" );
-
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "GIF" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Graphics Interchange Format (.gif)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_gif.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gif" );
+    poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/gif" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>\n"
 "   <Option name='INTERLACING' type='boolean'/>\n"
 "   <Option name='WORLDFILE' type='boolean'/>\n"
 "</CreationOptionList>\n" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = GIFDataset::Open;
-        poDriver->pfnCreateCopy = GIFDataset::CreateCopy;
-        poDriver->pfnIdentify = GIFAbstractDataset::Identify;
+    poDriver->pfnOpen = GIFDataset::Open;
+    poDriver->pfnCreateCopy = GIFDataset::CreateCopy;
+    poDriver->pfnIdentify = GIFAbstractDataset::Identify;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/gif/giflib/README b/frmts/gif/giflib/README
index 6e0bb14..e0a4d0f 100644
--- a/frmts/gif/giflib/README
+++ b/frmts/gif/giflib/README
@@ -1,14 +1,15 @@
-This code is from giflib 4.1.6
+This code is (mostly) from giflib 4.1.6
 
 This seems to be the new location of the giflib project:
 http://sourceforge.net/projects/giflib
 
 Changes:
  o Select only lib files needed.
- o Hacked in O_BINARY support whereever O_BINARY is defined.
+ o Hacked in O_BINARY support wherever O_BINARY is defined.
  o Modify include section of c files
  o Apply patch for http://trac.osgeo.org/gdal/ticket/2542
  o Apply Debian 01-cve.dpatch to fix CVE-2005-2974 and CVE-2005-3350
+ o Partial resync with gilib master (~5.1.1) to fix various Coverity warnings
 
 History:
 
diff --git a/frmts/gif/giflib/dgif_lib.c b/frmts/gif/giflib/dgif_lib.c
index 9b791f4..7e591b9 100644
--- a/frmts/gif/giflib/dgif_lib.c
+++ b/frmts/gif/giflib/dgif_lib.c
@@ -58,7 +58,7 @@ static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf,
 /******************************************************************************
  * Open a new gif file for read, given by its name.
  * Returns GifFileType pointer dynamically allocated which serves as the gif
- * info record. _GifError is cleared if succesfull.
+ * info record. _GifError is cleared if successfully.
  *****************************************************************************/
 GifFileType *
 DGifOpenFileName(const char *FileName) {
@@ -81,7 +81,7 @@ DGifOpenFileName(const char *FileName) {
 /******************************************************************************
  * Update a new gif file, given its file handle.
  * Returns GifFileType pointer dynamically allocated which serves as the gif
- * info record. _GifError is cleared if succesfull.
+ * info record. _GifError is cleared if successfully.
  *****************************************************************************/
 GifFileType *
 DGifOpenFileHandle(int FileHandle) {
@@ -126,6 +126,7 @@ DGifOpenFileHandle(int FileHandle) {
     GifFile->UserData = 0;    /* TVT */
 
     /* Lets see if this is a GIF file: */
+    /* coverity[check_return] */
     if (READ(GifFile, Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
         _GifError = D_GIF_ERR_READ_FAILED;
         fclose(f);
@@ -137,7 +138,7 @@ DGifOpenFileHandle(int FileHandle) {
     /* The GIF Version number is ignored at this time. Maybe we should do
      * something more useful with it.  */
     Buf[GIF_STAMP_LEN] = 0;
-    if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
+    if (strncmp(GIF_STAMP, (const char*)Buf, GIF_VERSION_POS) != 0) {
         _GifError = D_GIF_ERR_NOT_GIF_FILE;
         fclose(f);
         free((char *)Private);
@@ -194,6 +195,7 @@ DGifOpen(void *userData,
     GifFile->UserData = userData;    /* TVT */
 
     /* Lets see if this is a GIF file: */
+    /* coverity[check_return] */
     if (READ(GifFile, Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
         _GifError = D_GIF_ERR_READ_FAILED;
         free((char *)Private);
@@ -204,7 +206,7 @@ DGifOpen(void *userData,
     /* The GIF Version number is ignored at this time. Maybe we should do
      * something more useful with it. */
     Buf[GIF_STAMP_LEN] = 0;
-    if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
+    if (strncmp(GIF_STAMP, (const char*)Buf, GIF_VERSION_POS) != 0) {
         _GifError = D_GIF_ERR_NOT_GIF_FILE;
         free((char *)Private);
         free((char *)GifFile);
@@ -244,6 +246,7 @@ DGifGetScreenDesc(GifFileType * GifFile) {
         DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR)
         return GIF_ERROR;
 
+    /* coverity[check_return] */
     if (READ(GifFile, Buf, 3) != 3) {
         _GifError = D_GIF_ERR_READ_FAILED;
 		FreeMapObject(GifFile->SColorMap);
@@ -263,6 +266,7 @@ DGifGetScreenDesc(GifFileType * GifFile) {
 
         /* Get the global color map: */
         for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
+            /* coverity[check_return] */
             if (READ(GifFile, Buf, 3) != 3) {
                 FreeMapObject(GifFile->SColorMap);
                 GifFile->SColorMap = NULL;
@@ -296,6 +300,7 @@ DGifGetRecordType(GifFileType * GifFile,
         return GIF_ERROR;
     }
 
+    /* coverity[check_return] */
     if (READ(GifFile, &Buf, 1) != 1) {
         _GifError = D_GIF_ERR_READ_FAILED;
         return GIF_ERROR;
@@ -343,6 +348,7 @@ DGifGetImageDesc(GifFileType * GifFile) {
         DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR ||
         DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR)
         return GIF_ERROR;
+    /* coverity[check_return] */
     if (READ(GifFile, Buf, 1) != 1) {
         _GifError = D_GIF_ERR_READ_FAILED;
 		FreeMapObject(GifFile->Image.ColorMap);
@@ -366,6 +372,7 @@ DGifGetImageDesc(GifFileType * GifFile) {
 
         /* Get the image local color map: */
         for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) {
+            /* coverity[check_return] */
             if (READ(GifFile, Buf, 3) != 3) {
                 FreeMapObject(GifFile->Image.ColorMap);
                 _GifError = D_GIF_ERR_READ_FAILED;
@@ -382,12 +389,14 @@ DGifGetImageDesc(GifFileType * GifFile) {
     }
 
     if (GifFile->SavedImages) {
-        if ((GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages,
+        SavedImage* new_saved_images = (SavedImage *)realloc(GifFile->SavedImages,
                                       sizeof(SavedImage) *
-                                      (GifFile->ImageCount + 1))) == NULL) {
+                                      (GifFile->ImageCount + 1));
+        if (new_saved_images == NULL) {
             _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
             return GIF_ERROR;
         }
+        GifFile->SavedImages = new_saved_images;
     } else {
         if ((GifFile->SavedImages =
              (SavedImage *) malloc(sizeof(SavedImage))) == NULL) {
@@ -526,6 +535,7 @@ DGifGetExtension(GifFileType * GifFile,
         return GIF_ERROR;
     }
 
+    /* coverity[check_return] */
     if (READ(GifFile, &Buf, 1) != 1) {
         _GifError = D_GIF_ERR_READ_FAILED;
         return GIF_ERROR;
@@ -547,6 +557,7 @@ DGifGetExtensionNext(GifFileType * GifFile,
     GifByteType Buf;
     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
 
+    /* coverity[check_return] */
     if (READ(GifFile, &Buf, 1) != 1) {
         _GifError = D_GIF_ERR_READ_FAILED;
         return GIF_ERROR;
@@ -554,6 +565,8 @@ DGifGetExtensionNext(GifFileType * GifFile,
     if (Buf > 0) {
         *Extension = Private->Buf;    /* Use private unused buffer. */
         (*Extension)[0] = Buf;  /* Pascal strings notation (pos. 0 is len.). */
+        /* coverity[check_return] */
+        /* coverity[tainted_data] */
         if (READ(GifFile, &((*Extension)[1]), Buf) != Buf) {
             _GifError = D_GIF_ERR_READ_FAILED;
             return GIF_ERROR;
@@ -573,7 +586,7 @@ DGifCloseFile(GifFileType * GifFile) {
     GifFilePrivateType *Private;
     FILE *File;
 
-    if (GifFile == NULL)
+    if (GifFile == NULL || GifFile->Private == NULL)
         return GIF_ERROR;
 
     Private = (GifFilePrivateType *) GifFile->Private;
@@ -596,22 +609,21 @@ DGifCloseFile(GifFileType * GifFile) {
         GifFile->SColorMap = NULL;
     }
 
-    if (Private) {
-        free((char *)Private);
-        Private = NULL;
-    }
-
     if (GifFile->SavedImages) {
         FreeSavedImages(GifFile);
         GifFile->SavedImages = NULL;
     }
 
-    free(GifFile);
-
     if (File && (fclose(File) != 0)) {
         _GifError = D_GIF_ERR_CLOSE_FAILED;
+        free((char *)Private);
+        free(GifFile);
         return GIF_ERROR;
     }
+
+    free((char *)Private);
+    free(GifFile);
+
     return GIF_OK;
 }
 
@@ -624,6 +636,7 @@ DGifGetWord(GifFileType * GifFile,
 
     unsigned char c[2];
 
+    /* coverity[check_return] */
     if (READ(GifFile, c, 2) != 2) {
         _GifError = D_GIF_ERR_READ_FAILED;
         return GIF_ERROR;
@@ -670,14 +683,19 @@ DGifGetCodeNext(GifFileType * GifFile,
     GifByteType Buf;
     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
 
+    /* coverity[tainted_data_argument] */
+    /* coverity[check_return] */
     if (READ(GifFile, &Buf, 1) != 1) {
         _GifError = D_GIF_ERR_READ_FAILED;
         return GIF_ERROR;
     }
 
+    /* coverity[lower_bounds] */
     if (Buf > 0) {
         *CodeBlock = Private->Buf;    /* Use private unused buffer. */
         (*CodeBlock)[0] = Buf;  /* Pascal strings notation (pos. 0 is len.). */
+        /* coverity[tainted_data] */
+        /* coverity[check_return] */
         if (READ(GifFile, &((*CodeBlock)[1]), Buf) != Buf) {
             _GifError = D_GIF_ERR_READ_FAILED;
             return GIF_ERROR;
@@ -702,7 +720,10 @@ DGifSetupDecompress(GifFileType * GifFile) {
     GifPrefixType *Prefix;
     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
 
-    READ(GifFile, &CodeSize, 1);    /* Read Code size from file. */
+    /* coverity[check_return] */
+    if (READ(GifFile, &CodeSize, 1) < 1) {    /* Read Code size from file. */
+        return GIF_ERROR;    /* Failed to read Code size. */
+    }
     BitsPerPixel = CodeSize;
 
     Private->Buf[0] = 0;    /* Input Buffer empty. */
@@ -754,7 +775,7 @@ DGifDecompressLine(GifFileType * GifFile,
     }
 
     if (StackPtr != 0) {
-        /* Let pop the stack off before continueing to read the gif file: */
+        /* Let pop the stack off before continuing to read the GIF file: */
         while (StackPtr != 0 && i < LineLen)
             Line[i++] = Stack[--StackPtr];
     }
@@ -767,11 +788,7 @@ DGifDecompressLine(GifFileType * GifFile,
             /* Note however that usually we will not be here as we will stop
              * decoding as soon as we got all the pixel, or EOF code will
              * not be read at all, and DGifGetLine/Pixel clean everything.  */
-            if (i != LineLen - 1 || Private->PixelCount != 0) {
-                _GifError = D_GIF_ERR_EOF_TOO_SOON;
                 return GIF_ERROR;
-            }
-            i++;
         } else if (CrntCode == ClearCode) {
             /* We need to start over again: */
             for (j = 0; j <= LZ_MAX_CODE; j++)
@@ -788,40 +805,41 @@ DGifDecompressLine(GifFileType * GifFile,
                 /* This is simple - its pixel scalar, so add it to output: */
                 Line[i++] = CrntCode;
             } else {
-                /* Its a code to needed to be traced: trace the linked list
+                /* It is a code to that needs to be traced: trace the linked list
                  * until the prefix is a pixel, while pushing the suffix
-                 * pixels on our stack. If we done, pop the stack in reverse
-                 * (thats what stack is good for!) order to output.  */
+                 * pixels on our stack. If we are done, pop the stack in reverse
+                 * (that is what stacks are good for!) order to output. */
                 if (Prefix[CrntCode] == NO_SUCH_CODE) {
+                    CrntPrefix = LastCode;
+
                     /* Only allowed if CrntCode is exactly the running code:
                      * In that case CrntCode = XXXCode, CrntCode or the
                      * prefix code is last code and the suffix char is
                      * exactly the prefix of last code! */
                     if (CrntCode == Private->RunningCode - 2) {
-                        CrntPrefix = LastCode;
                         Suffix[Private->RunningCode - 2] =
                            Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
                                                                  LastCode,
                                                                  ClearCode);
                     } else {
-                        _GifError = D_GIF_ERR_IMAGE_DEFECT;
-                        return GIF_ERROR;
+                        Suffix[Private->RunningCode - 2] =
+                           Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
+                                                                 CrntCode,
+                                                                 ClearCode);
                     }
                 } else
                     CrntPrefix = CrntCode;
 
-                /* Now (if image is O.K.) we should not get an NO_SUCH_CODE
-                 * During the trace. As we might loop forever, in case of
-                 * defective image, we count the number of loops we trace
-                 * and stop if we got LZ_MAX_CODE. obviously we can not
-                 * loop more than that.  */
-                j = 0;
-                while (j++ <= LZ_MAX_CODE &&
+                /* Now (if image is O.K.) we should not get a NO_SUCH_CODE
+                 * during the trace. As we might loop forever, in case of
+                 * defective image, we use StackPtr as loop counter and stop
+                 * before overflowing Stack[]. */
+                while (StackPtr < LZ_MAX_CODE &&
                        CrntPrefix > ClearCode && CrntPrefix <= LZ_MAX_CODE) {
                     Stack[StackPtr++] = Suffix[CrntPrefix];
                     CrntPrefix = Prefix[CrntPrefix];
                 }
-                if (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
+                if (StackPtr >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
                     _GifError = D_GIF_ERR_IMAGE_DEFECT;
                     return GIF_ERROR;
                 }
@@ -832,7 +850,7 @@ DGifDecompressLine(GifFileType * GifFile,
                 while (StackPtr != 0 && i < LineLen)
                     Line[i++] = Stack[--StackPtr];
             }
-            if (LastCode != NO_SUCH_CODE) {
+            if (LastCode != NO_SUCH_CODE && Prefix[Private->RunningCode - 2] == NO_SUCH_CODE) {
                 Prefix[Private->RunningCode - 2] = LastCode;
 
                 if (CrntCode == Private->RunningCode - 2) {
@@ -919,18 +937,18 @@ DGifGetLZCodes(GifFileType * GifFile,
 
 /******************************************************************************
  * The LZ decompression input routine:
- * This routine is responsable for the decompression of the bit stream from
+ * This routine is responsible for the decompression of the bit stream from
  * 8 bits (bytes) packets, into the real codes.
- * Returns GIF_OK if read succesfully.
+ * Returns GIF_OK if read successfully.
  *****************************************************************************/
 static int
 DGifDecompressInput(GifFileType * GifFile,
                     int *Code) {
-    
+
     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
 
     GifByteType NextByte;
-    static unsigned short CodeMasks[] = {
+    static const unsigned short CodeMasks[] = {
         0x0000, 0x0001, 0x0003, 0x0007,
         0x000f, 0x001f, 0x003f, 0x007f,
         0x00ff, 0x01ff, 0x03ff, 0x07ff,
@@ -974,7 +992,7 @@ DGifDecompressInput(GifFileType * GifFile,
  * This routines read one gif data block at a time and buffers it internally
  * so that the decompression routine could access it.
  * The routine returns the next byte from its internal buffer (or read next
- * block in if buffer empty) and returns GIF_OK if succesful.
+ * block in if buffer empty) and returns GIF_OK if successful.
  *****************************************************************************/
 static int
 DGifBufferedInput(GifFileType * GifFile,
@@ -983,6 +1001,7 @@ DGifBufferedInput(GifFileType * GifFile,
 
     if (Buf[0] == 0) {
         /* Needs to read the next buffer - this one is empty: */
+        /* coverity[check_return] */
         if (READ(GifFile, Buf, 1) != 1) {
             _GifError = D_GIF_ERR_READ_FAILED;
             return GIF_ERROR;
@@ -995,14 +1014,8 @@ DGifBufferedInput(GifFileType * GifFile,
             _GifError = D_GIF_ERR_IMAGE_DEFECT;
             return GIF_ERROR;
         }
-        /* There shouldn't be any empty data blocks here as the LZW spec
-         * says the LZW termination code should come first.  Therefore we
-         * shouldn't be inside this routine at that point.
-         */
-        if (Buf[0] == 0) {
-            _GifError = D_GIF_ERR_IMAGE_DEFECT;
-            return GIF_ERROR;
-        }
+
+        /* coverity[check_return] */
         if (READ(GifFile, &Buf[1], Buf[0]) != Buf[0]) {
             _GifError = D_GIF_ERR_READ_FAILED;
             return GIF_ERROR;
diff --git a/frmts/gif/giflib/egif_lib.c b/frmts/gif/giflib/egif_lib.c
index 4107973..f2b79c9 100644
--- a/frmts/gif/giflib/egif_lib.c
+++ b/frmts/gif/giflib/egif_lib.c
@@ -52,7 +52,7 @@ static char GifVersionPrefix[GIF_STAMP_LEN + 1] = GIF87_STAMP;
 
 #define WRITE(_gif,_buf,_len)   \
   (((GifFilePrivateType*)_gif->Private)->Write ?    \
-   ((GifFilePrivateType*)_gif->Private)->Write(_gif,_buf,_len) :    \
+   ((GifFilePrivateType*)_gif->Private)->Write(_gif,_buf,(int)(_len)) :    \
    fwrite(_buf, 1, _len, ((GifFilePrivateType*)_gif->Private)->File))
 
 static int EGifPutWord(int Word, GifFileType * GifFile);
@@ -64,19 +64,19 @@ static int EGifBufferedOutput(GifFileType * GifFile, GifByteType * Buf,
                               int c);
 
 /******************************************************************************
- * Open a new gif file for write, given by its name. If TestExistance then
+ * Open a new gif file for write, given by its name. If TestExistence then
  * if the file exists this routines fails (returns NULL).
  * Returns GifFileType pointer dynamically allocated which serves as the gif
- * info record. _GifError is cleared if succesfull.
+ * info record. _GifError is cleared if successfully.
  *****************************************************************************/
 GifFileType *
 EGifOpenFileName(const char *FileName,
-                 int TestExistance) {
+                 int TestExistence) {
 
     int FileHandle;
     GifFileType *GifFile;
 
-    if (TestExistance)
+    if (TestExistence)
         FileHandle = open(FileName, O_WRONLY | O_CREAT | O_EXCL
 #if defined(O_BINARY)
                           | O_BINARY
@@ -103,7 +103,7 @@ EGifOpenFileName(const char *FileName,
  * Update a new gif file, given its file handle, which must be opened for
  * write in binary mode.
  * Returns GifFileType pointer dynamically allocated which serves as the gif
- * info record. _GifError is cleared if succesfull.
+ * info record. _GifError is cleared if successfully.
  *****************************************************************************/
 GifFileType *
 EGifOpenFileHandle(int FileHandle) {
@@ -216,7 +216,7 @@ EGifSetGifVersion(const char *Version) {
 
 /******************************************************************************
  * This routine should be called before any other EGif calls, immediately
- * follows the GIF file openning.
+ * follows the GIF file opening.
  *****************************************************************************/
 int
 EGifPutScreenDesc(GifFileType * GifFile,
@@ -244,7 +244,7 @@ EGifPutScreenDesc(GifFileType * GifFile,
 /* First write the version prefix into the file. */
 #ifndef DEBUG_NO_PREFIX
     if (WRITE(GifFile, (unsigned char *)GifVersionPrefix,
-              strlen(GifVersionPrefix)) != strlen(GifVersionPrefix)) {
+              (int)strlen(GifVersionPrefix)) != strlen(GifVersionPrefix)) {
         _GifError = E_GIF_ERR_WRITE_FAILED;
         return GIF_ERROR;
     }
@@ -356,7 +356,7 @@ EGifPutImageDesc(GifFileType * GifFile,
     }
 
     /* Put the image descriptor into the file: */
-    Buf[0] = ',';    /* Image seperator character. */
+    Buf[0] = ',';    /* Image separator character. */
 #ifndef DEBUG_NO_PREFIX
     WRITE(GifFile, Buf, 1);
 #endif /* DEBUG_NO_PREFIX */
@@ -469,10 +469,10 @@ int
 EGifPutComment(GifFileType * GifFile,
                const char *Comment) {
   
-    unsigned int length = strlen(Comment);
+    unsigned int length;
     char *buf;
 
-    length = strlen(Comment);
+    length = (unsigned int)strlen(Comment);
     if (length <= 255) {
         return EGifPutExtension(GifFile, COMMENT_EXT_FUNC_CODE,
                                 length, Comment);
@@ -494,14 +494,8 @@ EGifPutComment(GifFileType * GifFile,
             length -= 255;
         }
         /* Output any partial block and the clear code. */
-        if (length > 0) {
-            if (EGifPutExtensionLast(GifFile, 0, length, buf) == GIF_ERROR) {
-                return GIF_ERROR;
-            }
-        } else {
-            if (EGifPutExtensionLast(GifFile, 0, 0, NULL) == GIF_ERROR) {
-                return GIF_ERROR;
-            }
+        if (EGifPutExtensionLast(GifFile, 0, length, buf) == GIF_ERROR) {
+            return GIF_ERROR;
         }
     }
     return GIF_OK;
@@ -706,13 +700,14 @@ EGifCloseFile(GifFileType * GifFile) {
     GifFilePrivateType *Private;
     FILE *File;
 
-    if (GifFile == NULL)
+    if (GifFile == NULL || GifFile->Private == NULL)
         return GIF_ERROR;
 
     Private = (GifFilePrivateType *) GifFile->Private;
     if (!IS_WRITEABLE(Private)) {
         /* This file was NOT open for writing: */
         _GifError = E_GIF_ERR_NOT_WRITEABLE;
+        free(GifFile);
         return GIF_ERROR;
     }
 
@@ -729,18 +724,21 @@ EGifCloseFile(GifFileType * GifFile) {
         FreeMapObject(GifFile->SColorMap);
         GifFile->SColorMap = NULL;
     }
-    if (Private) {
-        if (Private->HashTable) {
-            free((char *) Private->HashTable);
-        }
-	    free((char *) Private);
+
+    if (Private->HashTable) {
+        free((char *) Private->HashTable);
     }
-    free(GifFile);
 
     if (File && fclose(File) != 0) {
         _GifError = E_GIF_ERR_CLOSE_FAILED;
+        free((char *) Private);
+        free(GifFile);
         return GIF_ERROR;
     }
+
+    free((char *) Private);
+    free(GifFile);
+
     return GIF_OK;
 }
 
@@ -839,7 +837,7 @@ EGifCompressLine(GifFileType * GifFile,
          * CrntCode as Prefix string with Pixel as postfix char.
          */
         NewKey = (((UINT32) CrntCode) << 8) + Pixel;
-        if ((NewCode = _ExistsHashTable(HashTable, NewKey)) >= 0) {
+        if ((NewCode = _ExistsHashTable(HashTable, (UINT32)NewKey)) >= 0) {
             /* This Key is already there, or the string is old one, so
              * simple take new code as our CrntCode:
              */
@@ -870,7 +868,7 @@ EGifCompressLine(GifFileType * GifFile,
                 _ClearHashTable(HashTable);
             } else {
                 /* Put this unique key with its relative Code in hash table: */
-                _InsertHashTable(HashTable, NewKey, Private->RunningCode++);
+                _InsertHashTable(HashTable, (UINT32)NewKey, Private->RunningCode++);
             }
         }
 
@@ -902,7 +900,7 @@ EGifCompressLine(GifFileType * GifFile,
  * The LZ compression output routine:
  * This routine is responsible for the compression of the bit stream into
  * 8 bits (bytes) packets.
- * Returns GIF_OK if written succesfully.
+ * Returns GIF_OK if written successfully.
  *****************************************************************************/
 static int
 EGifCompressOutput(GifFileType * GifFile,
@@ -937,7 +935,7 @@ EGifCompressOutput(GifFileType * GifFile,
         }
     }
 
-    /* If code cannt fit into RunningBits bits, must raise its size. Note */
+    /* If code cannot fit into RunningBits bits, must raise its size. Note */
     /* however that codes above 4095 are used for special signaling.      */
     if (Private->RunningCode >= Private->MaxCode1 && Code <= 4095) {
        Private->MaxCode1 = 1 << ++Private->RunningBits;
@@ -950,7 +948,7 @@ EGifCompressOutput(GifFileType * GifFile,
  * This routines buffers the given characters until 255 characters are ready
  * to be output. If Code is equal to -1 the buffer is flushed (EOF).
  * The buffer is Dumped with first byte as its size, as GIF format requires.
- * Returns GIF_OK if written succesfully.
+ * Returns GIF_OK if written successfully.
  *****************************************************************************/
 static int
 EGifBufferedOutput(GifFileType * GifFile,
@@ -1009,11 +1007,11 @@ EGifSpew(GifFileType * GifFileOut) {
         }
     }
 
-    strncpy(SavedStamp, GifVersionPrefix, GIF_STAMP_LEN);
+    memcpy(SavedStamp, GifVersionPrefix, GIF_STAMP_LEN);
     if (gif89) {
-        strncpy(GifVersionPrefix, GIF89_STAMP, GIF_STAMP_LEN);
+        memcpy(GifVersionPrefix, GIF89_STAMP, GIF_STAMP_LEN);
     } else {
-        strncpy(GifVersionPrefix, GIF87_STAMP, GIF_STAMP_LEN);
+        memcpy(GifVersionPrefix, GIF87_STAMP, GIF_STAMP_LEN);
     }
     if (EGifPutScreenDesc(GifFileOut,
                           GifFileOut->SWidth,
@@ -1021,10 +1019,10 @@ EGifSpew(GifFileType * GifFileOut) {
                           GifFileOut->SColorResolution,
                           GifFileOut->SBackGroundColor,
                           GifFileOut->SColorMap) == GIF_ERROR) {
-        strncpy(GifVersionPrefix, SavedStamp, GIF_STAMP_LEN);
+        memcpy(GifVersionPrefix, SavedStamp, GIF_STAMP_LEN);
         return (GIF_ERROR);
     }
-    strncpy(GifVersionPrefix, SavedStamp, GIF_STAMP_LEN);
+    memcpy(GifVersionPrefix, SavedStamp, GIF_STAMP_LEN);
 
     for (i = 0; i < GifFileOut->ImageCount; i++) {
         SavedImage *sp = &GifFileOut->SavedImages[i];
diff --git a/frmts/gif/giflib/gif_hash.h b/frmts/gif/giflib/gif_hash.h
index a82595f..545146c 100644
--- a/frmts/gif/giflib/gif_hash.h
+++ b/frmts/gif/giflib/gif_hash.h
@@ -7,8 +7,8 @@
 * 14 Jun 89 - Version 1.0 by Gershon Elber.				      *
 ******************************************************************************/
 
-#ifndef _GIF_HASH_H_
-#define _GIF_HASH_H_
+#ifndef GIF_HASH_H_
+#define GIF_HASH_H_
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -59,4 +59,4 @@ void _ClearHashTable(GifHashTableType *HashTable);
 void _InsertHashTable(GifHashTableType *HashTable, UINT32 Key, int Code);
 int _ExistsHashTable(GifHashTableType *HashTable, UINT32 Key);
 
-#endif /* _GIF_HASH_H_ */
+#endif /* GIF_HASH_H_ */
diff --git a/frmts/gif/giflib/gif_lib.h b/frmts/gif/giflib/gif_lib.h
index 54acd91..26565ec 100644
--- a/frmts/gif/giflib/gif_lib.h
+++ b/frmts/gif/giflib/gif_lib.h
@@ -8,7 +8,7 @@
  * History:                                                                    
  * 14 Jun 89 - Version 1.0 by Gershon Elber.                                   
  *  3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, Unique names)  
- * 15 Sep 90 - Version 2.0 by Eric S. Raymond (Changes to suoport GIF slurp)   
+ * 15 Sep 90 - Version 2.0 by Eric S. Raymond (Changes to support GIF slurp)
  * 26 Jun 96 - Version 3.0 by Eric S. Raymond (Full GIF89 support)
  * 17 Dec 98 - Version 4.0 by Toshio Kuratomi (Fix extension writing code)     
  *****************************************************************************/
@@ -134,7 +134,7 @@ typedef int (*OutputFunc) (GifFileType *, const GifByteType *, int);
 ******************************************************************************/
 
 GifFileType *EGifOpenFileName(const char *GifFileName,
-                              int GifTestExistance);
+                              int GifTestExistence);
 GifFileType *EGifOpenFileHandle(int GifFileHandle);
 GifFileType *EGifOpen(void *userPtr, OutputFunc writeFunc);
 
@@ -174,7 +174,7 @@ int EGifCloseFile(GifFileType * GifFile);
 #define E_GIF_ERR_NOT_ENOUGH_MEM 7
 #define E_GIF_ERR_DISK_IS_FULL   8
 #define E_GIF_ERR_CLOSE_FAILED   9
-#define E_GIF_ERR_NOT_WRITEABLE  10
+#define E_GIF_ERR_NOT_WRITEABLE  10  /* TODO: Spelling.  Fix upstream and deprecate. */
 
 /******************************************************************************
  * O.K., here are the routines one can access in order to decode GIF file:     
diff --git a/frmts/gif/giflib/gif_lib_private.h b/frmts/gif/giflib/gif_lib_private.h
index b31c9c5..3592cbb 100644
--- a/frmts/gif/giflib/gif_lib_private.h
+++ b/frmts/gif/giflib/gif_lib_private.h
@@ -1,5 +1,5 @@
-#ifndef _GIF_LIB_PRIVATE_H
-#define _GIF_LIB_PRIVATE_H
+#ifndef GIF_LIB_PRIVATE_H
+#define GIF_LIB_PRIVATE_H
 
 #include "gif_lib.h"
 #include "gif_hash.h"
@@ -28,6 +28,7 @@
 #define FILE_STATE_READ     0x08
 
 #define IS_READABLE(Private)    (Private->FileState & FILE_STATE_READ)
+/* TODO: Spelling.  Fix upstream and deprecate. */
 #define IS_WRITEABLE(Private)   (Private->FileState & FILE_STATE_WRITE)
 
 typedef struct GifFilePrivateType {
@@ -56,4 +57,4 @@ typedef struct GifFilePrivateType {
 
 extern int _GifError;
 
-#endif /* _GIF_LIB_PRIVATE_H */
+#endif /* GIF_LIB_PRIVATE_H */
diff --git a/frmts/gif/giflib/gifalloc.c b/frmts/gif/giflib/gifalloc.c
index 79d2332..d68809a 100644
--- a/frmts/gif/giflib/gifalloc.c
+++ b/frmts/gif/giflib/gifalloc.c
@@ -64,6 +64,7 @@ MakeMapObject(int ColorCount,
 
     Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType));
     if (Object->Colors == (GifColorType *) NULL) {
+        free(Object);
         return ((ColorMapObject *) NULL);
     }
 
@@ -99,6 +100,10 @@ FreeMapObject(ColorMapObject * Object) {
 #ifdef DEBUG
 void
 DumpColorMap(ColorMapObject * Object,
+             FILE * fp);
+
+void
+DumpColorMap(ColorMapObject * Object,
              FILE * fp) {
 
     if (Object) {
@@ -189,7 +194,7 @@ UnionColorMap(const ColorMapObject * ColorIn1,
     NewBitSize = BitSize(CrntSlot);
     RoundUpTo = (1 << NewBitSize);
 
-    if (RoundUpTo != ColorUnion->ColorCount) {
+    if (RoundUpTo > 0 && RoundUpTo != ColorUnion->ColorCount) {
         register GifColorType *Map = ColorUnion->Colors;
 
         /* 
@@ -201,9 +206,15 @@ UnionColorMap(const ColorMapObject * ColorIn1,
             Map[j].Red = Map[j].Green = Map[j].Blue = 0;
 
         /* perhaps we can shrink the map? */
-        if (RoundUpTo < ColorUnion->ColorCount)
-            ColorUnion->Colors = (GifColorType *)realloc(Map,
-                                 sizeof(GifColorType) * RoundUpTo);
+        if (RoundUpTo < ColorUnion->ColorCount) {
+            GifColorType *new_map = (GifColorType *)realloc(Map,
+                                 RoundUpTo * sizeof(GifColorType));
+            if( new_map == NULL ) {
+                FreeMapObject(ColorUnion);
+                return ((ColorMapObject *) NULL);
+            }
+            ColorUnion->Colors = new_map;
+        }
     }
 
     ColorUnion->ColorCount = RoundUpTo;
@@ -256,10 +267,14 @@ AddExtensionBlock(SavedImage * New,
 
     if (New->ExtensionBlocks == NULL)
         New->ExtensionBlocks=(ExtensionBlock *)malloc(sizeof(ExtensionBlock));
-    else
-        New->ExtensionBlocks = (ExtensionBlock *)realloc(New->ExtensionBlocks,
+    else {
+        ExtensionBlock* ep_new = (ExtensionBlock *)realloc(New->ExtensionBlocks,
                                       sizeof(ExtensionBlock) *
                                       (New->ExtensionBlockCount + 1));
+        if( ep_new == NULL )
+            return (GIF_ERROR);
+        New->ExtensionBlocks = ep_new;
+    }
 
     if (New->ExtensionBlocks == NULL)
         return (GIF_ERROR);
@@ -301,7 +316,7 @@ FreeExtension(SavedImage * Image)
 /* Private Function:
  * Frees the last image in the GifFile->SavedImages array
  */
-void
+static void
 FreeLastSavedImage(GifFileType *GifFile) {
 
     SavedImage *sp;
@@ -366,7 +381,7 @@ MakeSavedImage(GifFileType * GifFile,
              */
 
             /* first, the local color map */
-            if (sp->ImageDesc.ColorMap) {
+            if (CopyFrom->ImageDesc.ColorMap) {
                 sp->ImageDesc.ColorMap = MakeMapObject(
                                          CopyFrom->ImageDesc.ColorMap->ColorCount,
                                          CopyFrom->ImageDesc.ColorMap->Colors);
@@ -389,7 +404,7 @@ MakeSavedImage(GifFileType * GifFile,
                    CopyFrom->ImageDesc.Width);
 
             /* finally, the extension blocks */
-            if (sp->ExtensionBlocks) {
+            if (CopyFrom->ExtensionBlocks) {
                 sp->ExtensionBlocks = (ExtensionBlock *)malloc(
                                       sizeof(ExtensionBlock) *
                                       CopyFrom->ExtensionBlockCount);
diff --git a/frmts/grass/frmt_grass.html b/frmts/grass/frmt_grass.html
index 6cffa8a..ff045cf 100644
--- a/frmts/grass/frmt_grass.html
+++ b/frmts/grass/frmt_grass.html
@@ -56,7 +56,7 @@ in the GRASS setup file.
 The following features are supported by the GDAL/GRASS link.
 
 <ul>
-<li> Up to 256 entries from raster colormaps are read (0-255).  
+<li> Up to 256 entries from raster colormaps are read (0-255).
 <li> Compressed and uncompressed integer (CELL), floating point
 (FCELL) and double precision (DCELL) raster maps are all
 supported. Integer raster maps are classified with a band type of
diff --git a/frmts/grass/grass57dataset.cpp b/frmts/grass/grass57dataset.cpp
index 0b97887..fac8a1f 100644
--- a/frmts/grass/grass57dataset.cpp
+++ b/frmts/grass/grass57dataset.cpp
@@ -1,10 +1,10 @@
 /******************************************************************************
- * $Id: grass57dataset.cpp 28534 2015-02-21 14:34:39Z rouault $
+ * $Id: grass57dataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  GRASS Driver
  * Purpose:  Implement GRASS raster read/write support
  *           This version is for GRASS 5.7+ and uses GRASS libraries
- *           directly instead of using libgrass. 
+ *           directly instead of using libgrass.
  * Author:   Frank Warmerdam <warmerdam at pobox.com>
  *           Radim Blazek <blazek at itc.it>
  *
@@ -41,7 +41,12 @@ extern "C" {
 #ifdef __cplusplus
 #undef class
 #endif
-    
+
+#include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "gdal_priv.h"
+#include "ogr_spatialref.h"
+
 #include <grass/version.h>
 #include <grass/gprojects.h>
 #include <grass/gis.h>
@@ -57,17 +62,9 @@ char *GPJ_grass_to_wkt(struct Key_Value *,
 #endif
 }
 
-#include "gdal_priv.h"
-#include "cpl_string.h"
-#include "ogr_spatialref.h"
-
 #define GRASS_MAX_COLORS 100000  // what is the right value
 
-CPL_CVSID("$Id: grass57dataset.cpp 28534 2015-02-21 14:34:39Z rouault $");
-
-CPL_C_START
-void	GDALRegister_GRASS(void);
-CPL_C_END
+CPL_CVSID("$Id: grass57dataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 #if GRASS_VERSION_MAJOR  >= 7
 #define G_get_cellhd             Rast_get_cellhd
@@ -123,12 +120,12 @@ class GRASSDataset : public GDALDataset
 {
     friend class GRASSRasterBand;
 
-    char	*pszGisdbase;  
+    char	*pszGisdbase;
     char	*pszLocation;  /* LOCATION_NAME */
     char	*pszElement;   /* cellhd or group */
 
-    struct Cell_head sCellInfo; /* raster region */ 
-    
+    struct Cell_head sCellInfo; /* raster region */
+
     char	*pszProjection;
 
     double	adfGeoTransform[6];
@@ -165,7 +162,7 @@ class GRASSRasterBand : public GDALRasterBand
     struct Colors sGrassColors;
     GDALColorTable *poCT;
 
-    struct Cell_head sOpenWindow; /* the region when the raster was opened */ 
+    struct Cell_head sOpenWindow; /* the region when the raster was opened */
 
     int		bHaveMinMax;
     double	dfCellMin;
@@ -177,7 +174,7 @@ class GRASSRasterBand : public GDALRasterBand
 
   public:
 
-                   GRASSRasterBand( GRASSDataset *, int, 
+                   GRASSRasterBand( GRASSDataset *, int,
                                     const char *, const char * );
     virtual        ~GRASSRasterBand();
 
@@ -194,7 +191,7 @@ class GRASSRasterBand : public GDALRasterBand
 
   private:
     CPLErr ResetReading( struct Cell_head * );
-    
+
 };
 
 
@@ -226,7 +223,7 @@ GRASSRasterBand::GRASSRasterBand( GRASSDataset *poDS, int nBand,
 /* -------------------------------------------------------------------- */
     struct FPRange sRange;
 
-    if( G_read_fp_range( (char *) pszCellName, (char *) pszMapset, 
+    if( G_read_fp_range( (char *) pszCellName, (char *) pszMapset,
                          &sRange ) == -1 )
     {
         bHaveMinMax = FALSE;
@@ -240,12 +237,12 @@ GRASSRasterBand::GRASSRasterBand( GRASSDataset *poDS, int nBand,
 /* -------------------------------------------------------------------- */
 /*      Setup band type, and preferred nodata value.                    */
 /* -------------------------------------------------------------------- */
-    // Negative values are also (?) stored as 4 bytes (format = 3) 
+    // Negative values are also (?) stored as 4 bytes (format = 3)
     //       => raster with format < 3 has only positive values
 
-    // GRASS modules usually do not waste space and only the format necessary to keep 
+    // GRASS modules usually do not waste space and only the format necessary to keep
     // full raster values range is used -> no checks if shorter type could be used
-    
+
     if( nGRSType == CELL_TYPE ) {
 	if ( sCellInfo.format == 0 ) {  // 1 byte / cell -> possible range 0,255
 	    if ( bHaveMinMax && dfCellMin > 0 ) {
@@ -268,20 +265,20 @@ GRASSRasterBand::GRASSRasterBand( GRASSDataset *poDS, int nBand,
 		dfNoData = 65535;
 	    } else { // maximum is not known or full range is used
 		CELL cval;
-		this->eDataType = GDT_Int32; 
+		this->eDataType = GDT_Int32;
 		G_set_c_null_value ( &cval, 1);
 		dfNoData = (double) cval;
 		nativeNulls = true;
 	    }
 	    nativeNulls = false;
-	} else {  // 3-4 bytes 
+	} else {  // 3-4 bytes
 	    CELL cval;
 	    this->eDataType = GDT_Int32;
 	    G_set_c_null_value ( &cval, 1);
 	    dfNoData = (double) cval;
 	    nativeNulls = true;
 	}
-    } 
+    }
     else if( nGRSType == FCELL_TYPE ) {
 	FCELL fval;
         this->eDataType = GDT_Float32;
@@ -314,7 +311,7 @@ GRASSRasterBand::GRASSRasterBand( GRASSDataset *poDS, int nBand,
     poCT = NULL;
     if( G_read_colors( (char *) pszCellName, (char *) pszMapset, &sGrassColors ) == 1 )
     {
-	int maxcolor; 
+	int maxcolor;
 	CELL min, max;
 
 	G_get_color_range ( &min, &max, &sGrassColors);
@@ -325,7 +322,7 @@ GRASSRasterBand::GRASSRasterBand( GRASSDataset *poDS, int nBand,
             } else {
 	       maxcolor = (int) ceil ( dfCellMax );
 	    }
-	    if ( maxcolor > GRASS_MAX_COLORS ) { 
+	    if ( maxcolor > GRASS_MAX_COLORS ) {
 		maxcolor = GRASS_MAX_COLORS;
                 CPLDebug( "GRASS", "Too many values, color table cut to %d entries.", maxcolor );
 	    }
@@ -337,7 +334,7 @@ GRASSRasterBand::GRASSRasterBand( GRASSDataset *poDS, int nBand,
                CPLDebug( "GRASS", "Too many values, color table set to %d entries.", maxcolor );
 	    }
         }
-	    
+
         poCT = new GDALColorTable();
         for( int iColor = 0; iColor <= maxcolor; iColor++ )
         {
@@ -367,30 +364,29 @@ GRASSRasterBand::GRASSRasterBand( GRASSDataset *poDS, int nBand,
                 poCT->SetColorEntry( iColor, &sColor );
             }
         }
-	    
-	/* Create metadata enries for color table rules */
-	char key[200], value[200];
-	int rcount = G_colors_count ( &sGrassColors );
 
-	sprintf ( value, "%d", rcount );
-	this->SetMetadataItem( "COLOR_TABLE_RULES_COUNT", value );
+        /* Create metadata entries for color table rules */
+        char key[200], value[200];
+        int rcount = G_colors_count ( &sGrassColors );
 
-	/* Add the rules in reverse order */
-	for ( int i = rcount-1; i >= 0; i-- ) {
-	    DCELL val1, val2;
-	    unsigned char r1, g1, b1, r2, g2, b2;
+        snprintf ( value, sizeof(value), "%d", rcount );
+        this->SetMetadataItem( "COLOR_TABLE_RULES_COUNT", value );
 
-	     G_get_f_color_rule ( &val1, &r1, &g1, &b1, &val2, &r2, &g2, &b2, &sGrassColors, i );
-		
+        /* Add the rules in reverse order */
+        for ( int i = rcount-1; i >= 0; i-- ) {
+            DCELL val1, val2;
+            unsigned char r1, g1, b1, r2, g2, b2;
 
-	     sprintf ( key, "COLOR_TABLE_RULE_RGB_%d", rcount-i-1 );
-	     sprintf ( value, "%e %e %d %d %d %d %d %d", val1, val2, r1, g1, b1, r2, g2, b2 );
-	     this->SetMetadataItem( key, value );
-	}
+            G_get_f_color_rule ( &val1, &r1, &g1, &b1, &val2, &r2, &g2, &b2, &sGrassColors, i );
+
+            snprintf ( key, sizeof(key), "COLOR_TABLE_RULE_RGB_%d", rcount-i-1 );
+            snprintf ( value, sizeof(value), "%e %e %d %d %d %d %d %d", val1, val2, r1, g1, b1, r2, g2, b2 );
+            this->SetMetadataItem( key, value );
+        }
     } else {
-	this->SetMetadataItem( "COLOR_TABLE_RULES_COUNT", "0" );
+        this->SetMetadataItem( "COLOR_TABLE_RULES_COUNT", "0" );
     }
-    
+
     this->valid = true;
 }
 
@@ -407,7 +403,7 @@ GRASSRasterBand::~GRASSRasterBand()
 
     if( hCell >= 0 )
         G_close_cell( hCell );
-    
+
     if ( pszCellName )
         G_free ( pszCellName );
 
@@ -443,10 +439,10 @@ CPLErr GRASSRasterBand::ResetReading ( struct Cell_head *sNewWindow )
 	/* Open raster */
 	G__setenv( "GISDBASE", ((GRASSDataset *)poDS)->pszGisdbase );
 	G__setenv( "LOCATION_NAME", ((GRASSDataset *)poDS)->pszLocation );
-	G__setenv( "MAPSET", pszMapset); 
+	G__setenv( "MAPSET", pszMapset);
 	G_reset_mapsets();
 	G_add_mapset_to_search_path ( pszMapset );
-	
+
 	if ( (hCell = G_open_cell_old( pszCellName, pszMapset)) < 0 ) {
 	    CPLError( CE_Warning, CPLE_AppDefined, "GRASS: Cannot open raster '%s'", pszCellName );
             this->valid = false;
@@ -454,7 +450,7 @@ CPLErr GRASSRasterBand::ResetReading ( struct Cell_head *sNewWindow )
 	}
 
 	G_copy((void *) &sOpenWindow, (void *) sNewWindow, sizeof(struct Cell_head));
-	
+
     }
     else
     {
@@ -483,21 +479,22 @@ CPLErr GRASSRasterBand::ResetReading ( struct Cell_head *sNewWindow )
 /*                                                                      */
 /************************************************************************/
 
-CPLErr GRASSRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage )
+CPLErr GRASSRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
+                                    void *pImage )
 
 {
     if ( ! this->valid ) return CE_Failure;
 
-    // Reset window because IRasterIO could be previosly called
+    // Reset window because IRasterIO could be previously called.
     if ( ResetReading ( &(((GRASSDataset *)poDS)->sCellInfo) ) != CE_None ) {
        return CE_Failure;
-    }       
-    
+    }
+
     if ( eDataType == GDT_Byte || eDataType == GDT_UInt16 ) {
         CELL  *cbuf;
 
 	cbuf = G_allocate_c_raster_buf();
-	G_get_c_raster_row ( hCell, cbuf, nBlockYOff );	
+	G_get_c_raster_row ( hCell, cbuf, nBlockYOff );
 
 	/* Reset NULLs */
 	for ( int col = 0; col < nBlockXSize; col++ ) {
@@ -505,9 +502,9 @@ CPLErr GRASSRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImag
 		cbuf[col] = (CELL) dfNoData;
 	}
 
-	GDALCopyWords ( (void *) cbuf, GDT_Int32, sizeof(CELL), 
+	GDALCopyWords ( (void *) cbuf, GDT_Int32, sizeof(CELL),
 	                pImage, eDataType, GDALGetDataTypeSize(eDataType)/8,
-			nBlockXSize );    
+			nBlockXSize );
 
 	G_free ( cbuf );
 
@@ -518,7 +515,7 @@ CPLErr GRASSRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImag
     } else if ( eDataType == GDT_Float64 ) {
 	G_get_d_raster_row ( hCell, (DCELL *) pImage, nBlockYOff );
     }
-	
+
     return CE_None;
 }
 
@@ -537,25 +534,25 @@ CPLErr GRASSRasterBand::IRasterIO ( GDALRWFlag eRWFlag,
 {
     /* GRASS library does that, we have only calculate and reset the region in map units
      * and if the region has changed, reopen the raster */
-    
+
     /* Calculate the region */
     struct Cell_head sWindow;
     struct Cell_head *psDsWindow;
-    
+
     if ( ! this->valid ) return CE_Failure;
 
     psDsWindow = &(((GRASSDataset *)poDS)->sCellInfo);
-    
-    sWindow.north = psDsWindow->north - nYOff * psDsWindow->ns_res; 
-    sWindow.south = sWindow.north - nYSize * psDsWindow->ns_res; 
-    sWindow.west = psDsWindow->west + nXOff * psDsWindow->ew_res; 
-    sWindow.east = sWindow.west + nXSize * psDsWindow->ew_res; 
+
+    sWindow.north = psDsWindow->north - nYOff * psDsWindow->ns_res;
+    sWindow.south = sWindow.north - nYSize * psDsWindow->ns_res;
+    sWindow.west = psDsWindow->west + nXOff * psDsWindow->ew_res;
+    sWindow.east = sWindow.west + nXSize * psDsWindow->ew_res;
     sWindow.proj = psDsWindow->proj;
     sWindow.zone = psDsWindow->zone;
 
     sWindow.cols = nBufXSize;
     sWindow.rows = nBufYSize;
-     
+
     /* Reset resolution */
     G_adjust_Cell_head ( &sWindow, 1, 1);
 
@@ -563,7 +560,7 @@ CPLErr GRASSRasterBand::IRasterIO ( GDALRWFlag eRWFlag,
     {
         return CE_Failure;
     }
-    
+
     /* Read Data */
     CELL  *cbuf = NULL;
     FCELL *fbuf = NULL;
@@ -578,7 +575,7 @@ CPLErr GRASSRasterBand::IRasterIO ( GDALRWFlag eRWFlag,
 	nLineSpace = nBufXSize * nPixelSpace;
 
     if ( nGRSType == CELL_TYPE && ( !nativeNulls || eBufType != GDT_Int32 || sizeof(CELL) != 4 ||
-		                    nPixelSpace != sizeof(CELL) )  ) 
+		                    nPixelSpace != sizeof(CELL) )  )
     {
 	cbuf = G_allocate_c_raster_buf();
     } else if( nGRSType == FCELL_TYPE && ( eBufType != GDT_Float32 || nPixelSpace != sizeof(FCELL) ) ) {
@@ -591,42 +588,42 @@ CPLErr GRASSRasterBand::IRasterIO ( GDALRWFlag eRWFlag,
 
     for ( int row = 0; row < nBufYSize; row++ ) {
         char *pnt = (char *)pData + row * nLineSpace;
-	
+
 	if ( nGRSType == CELL_TYPE ) {
 	    if ( direct ) {
 		G_get_c_raster_row ( hCell, (CELL *) pnt, row );
 	    } else {
 		G_get_c_raster_row ( hCell, cbuf, row );
-		
+
 		/* Reset NULLs */
 		for ( int col = 0; col < nBufXSize; col++ ) {
-		    if ( G_is_c_null_value(&(cbuf[col])) ) 
+		    if ( G_is_c_null_value(&(cbuf[col])) )
 			cbuf[col] = (CELL) dfNoData;
 		}
 
-		GDALCopyWords ( (void *) cbuf, GDT_Int32, sizeof(CELL), 
+		GDALCopyWords ( (void *) cbuf, GDT_Int32, sizeof(CELL),
 			        (void *)  pnt,  eBufType, nPixelSpace,
-				nBufXSize ); 
+				nBufXSize );
 	    }
 	} else if( nGRSType == FCELL_TYPE ) {
 	    if ( direct ) {
 		G_get_f_raster_row ( hCell, (FCELL *) pnt, row );
 	    } else {
 		G_get_f_raster_row ( hCell, fbuf, row );
-		
-		GDALCopyWords ( (void *) fbuf, GDT_Float32, sizeof(FCELL), 
+
+		GDALCopyWords ( (void *) fbuf, GDT_Float32, sizeof(FCELL),
 			        (void *)  pnt,  eBufType, nPixelSpace,
-				nBufXSize ); 
+				nBufXSize );
 	    }
 	} else if( nGRSType == DCELL_TYPE ) {
 	    if ( direct ) {
 		G_get_d_raster_row ( hCell, (DCELL *) pnt, row );
 	    } else {
 		G_get_d_raster_row ( hCell, dbuf, row );
-		
-		GDALCopyWords ( (void *) dbuf, GDT_Float64, sizeof(DCELL), 
+
+		GDALCopyWords ( (void *) dbuf, GDT_Float64, sizeof(DCELL),
 			        (void *)  pnt,  eBufType, nPixelSpace,
-				nBufXSize ); 
+				nBufXSize );
 	    }
 	}
     }
@@ -634,7 +631,7 @@ CPLErr GRASSRasterBand::IRasterIO ( GDALRWFlag eRWFlag,
     if ( cbuf ) G_free ( cbuf );
     if ( fbuf ) G_free ( fbuf );
     if ( dbuf ) G_free ( dbuf );
-    
+
     return CE_None;
 }
 
@@ -699,7 +696,7 @@ double GRASSRasterBand::GetMaximum( int *pbSuccess )
         return 4294967295.0;
     else if( eDataType == GDT_UInt16 )
         return 65535;
-    else 
+    else
         return 255;
 }
 
@@ -745,13 +742,13 @@ GRASSDataset::GRASSDataset()
 
 GRASSDataset::~GRASSDataset()
 {
-    
+
     if ( pszGisdbase )
 	G_free ( pszGisdbase );
-    
+
     if ( pszLocation )
         G_free ( pszLocation );
-    
+
     if ( pszElement )
 	G_free ( pszElement );
 
@@ -762,7 +759,7 @@ GRASSDataset::~GRASSDataset()
 /*                          GetProjectionRef()                          */
 /************************************************************************/
 
-const char *GRASSDataset::GetProjectionRef() 
+const char *GRASSDataset::GetProjectionRef()
 {
     if( pszProjection == NULL )
         return "";
@@ -774,10 +771,10 @@ const char *GRASSDataset::GetProjectionRef()
 /*                          GetGeoTransform()                           */
 /************************************************************************/
 
-CPLErr GRASSDataset::GetGeoTransform( double * padfGeoTransform ) 
+CPLErr GRASSDataset::GetGeoTransform( double * padfGeoTransform )
 {
     memcpy( padfGeoTransform, adfGeoTransform, sizeof(double) * 6 );
-    
+
     return CE_None;
 }
 
@@ -790,22 +787,22 @@ CPLErr GRASSDataset::GetGeoTransform( double * padfGeoTransform )
 /* Returns: true - OK                                                   */
 /*          false - failed                                              */
 /************************************************************************/
-bool GRASSDataset::SplitPath( char *path, char **gisdbase, char **location, 
+bool GRASSDataset::SplitPath( char *path, char **gisdbase, char **location,
 	                      char **mapset, char **element, char **name )
 {
     char *p, *ptr[5], *tmp;
     int  i = 0;
-    
+
     *gisdbase = *location = *mapset = *element = *name = NULL;
-    
-    if ( !path || strlen(path) == 0 ) 
+
+    if ( !path || strlen(path) == 0 )
 	return false;
 
     tmp = G_store ( path );
 
     while ( (p = strrchr(tmp,'/')) != NULL  && i < 4 ) {
 	*p = '\0';
-	
+
 	if ( strlen(p+1) == 0 ) /* repeated '/' */
 	    continue;
 
@@ -853,7 +850,7 @@ GDALDataset *GRASSDataset::Open( GDALOpenInfo * poOpenInfo )
         && strstr(poOpenInfo->pszFilename,"/group/") == NULL )
         return NULL;
 
-    /* Always init, if no rasters are opened G_no_gisinit resets the projection and 
+    /* Always init, if no rasters are opened G_no_gisinit resets the projection and
      * rasters in different projection may be then opened */
 
     // Don't use GISRC file and read/write GRASS variables (from location G_VAR_GISRC) to memory only.
@@ -864,7 +861,7 @@ GDALDataset *GRASSDataset::Open( GDALOpenInfo * poOpenInfo )
 
     // Set error function
     G_set_error_routine ( (GrassErrorHandler) Grass2CPLErrorHook );
-    
+
 
     // GISBASE is path to the directory where GRASS is installed,
     if ( !getenv( "GISBASE" ) ) {
@@ -889,22 +886,22 @@ GDALDataset *GRASSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Check element name                                              */
 /* -------------------------------------------------------------------- */
-    if ( strcmp(pszElem,"cellhd") != 0 && strcmp(pszElem,"group") != 0 ) { 
-	G_free(pszGisdb); 
-        G_free(pszLoc); 
-        G_free(pszMapset); 
-        G_free(pszElem); 
+    if ( strcmp(pszElem,"cellhd") != 0 && strcmp(pszElem,"group") != 0 ) {
+	G_free(pszGisdb);
+        G_free(pszLoc);
+        G_free(pszMapset);
+        G_free(pszElem);
         G_free(pszName);
 	return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Set GRASS variables                                             */
 /* -------------------------------------------------------------------- */
 
     G__setenv( "GISDBASE", pszGisdb );
     G__setenv( "LOCATION_NAME", pszLoc );
-    G__setenv( "MAPSET", pszMapset); // group is searched only in current mapset 
+    G__setenv( "MAPSET", pszMapset); // group is searched only in current mapset
     G_reset_mapsets();
     G_add_mapset_to_search_path ( pszMapset );
 
@@ -912,7 +909,7 @@ GDALDataset *GRASSDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Check if this is a valid grass cell.                            */
 /* -------------------------------------------------------------------- */
     if ( strcmp(pszElem,"cellhd") == 0 ) {
-	
+
         if ( G_find_file2("cell", pszName, pszMapset) == NULL ) {
 	    G_free(pszGisdb); G_free(pszLoc); G_free(pszMapset); G_free(pszElem); G_free(pszName);
 	    return NULL;
@@ -932,8 +929,8 @@ GDALDataset *GRASSDataset::Open( GDALOpenInfo * poOpenInfo )
 	    G_free(pszGisdb); G_free(pszLoc); G_free(pszMapset); G_free(pszElem); G_free(pszName);
 	    return NULL;
 	}
-        
-        for( int iRef = 0; iRef < ref.nfiles; iRef++ ) 
+
+        for( int iRef = 0; iRef < ref.nfiles; iRef++ )
 	{
             papszCells = CSLAddString( papszCells, ref.file[iRef].name );
             papszMapsets = CSLAddString( papszMapsets, ref.file[iRef].mapset );
@@ -942,7 +939,7 @@ GDALDataset *GRASSDataset::Open( GDALOpenInfo * poOpenInfo )
 
         I_free_group_ref( &ref );
     }
-    
+
     G_free( pszMapset );
     G_free( pszName );
 
@@ -959,7 +956,7 @@ GDALDataset *GRASSDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->pszGisdbase = pszGisdb;
     poDS->pszLocation = pszLoc;
     poDS->pszElement = pszElem;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Capture some information from the file that is of interest.     */
 /* -------------------------------------------------------------------- */
@@ -983,7 +980,7 @@ GDALDataset *GRASSDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->adfGeoTransform[3] = poDS->sCellInfo.north;
     poDS->adfGeoTransform[4] = 0.0;
     poDS->adfGeoTransform[5] = -1 * poDS->sCellInfo.ns_res;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Try to get a projection definition.                             */
 /* -------------------------------------------------------------------- */
@@ -1000,7 +997,7 @@ GDALDataset *GRASSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     for( int iBand = 0; papszCells[iBand] != NULL; iBand++ )
     {
-	GRASSRasterBand *rb = new GRASSRasterBand( poDS, iBand+1, papszMapsets[iBand], 
+	GRASSRasterBand *rb = new GRASSRasterBand( poDS, iBand+1, papszMapsets[iBand],
                                                                   papszCells[iBand] );
 
 	if ( !rb->valid ) {
@@ -1008,26 +1005,26 @@ GDALDataset *GRASSDataset::Open( GDALOpenInfo * poOpenInfo )
 	    delete rb;
 	    delete poDS;
 	    return NULL;
-	}
+        }
 
         poDS->SetBand( iBand+1, rb );
     }
 
     CSLDestroy(papszCells);
     CSLDestroy(papszMapsets);
-    
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The GRASS driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
     }
-    
+
     return poDS;
 }
 
@@ -1037,25 +1034,20 @@ GDALDataset *GRASSDataset::Open( GDALOpenInfo * poOpenInfo )
 
 void GDALRegister_GRASS()
 {
-    GDALDriver	*poDriver;
-    
-    if (! GDAL_CHECK_VERSION("GDAL/GRASS57 driver"))
+    if( !GDAL_CHECK_VERSION( "GDAL/GRASS57 driver" ) )
         return;
 
-    if( GDALGetDriverByName( "GRASS" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "GRASS" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "GRASS Rasters (5.7+)" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_grass.html" );
-        
-        poDriver->pfnOpen = GRASSDataset::Open;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
-}
+    if( GDALGetDriverByName( "GRASS" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
 
+    poDriver->SetDescription( "GRASS" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "GRASS Rasters (5.7+)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_grass.html" );
+
+    poDriver->pfnOpen = GRASSDataset::Open;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/frmts/grass/grassdataset.cpp b/frmts/grass/grassdataset.cpp
index f413298..6503f3e 100644
--- a/frmts/grass/grassdataset.cpp
+++ b/frmts/grass/grassdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: grassdataset.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: grassdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  GRASS Driver
  * Purpose:  Implement GRASS raster read/write support
@@ -30,15 +30,12 @@
 
 #include <libgrass.h>
 
-#include "gdal_priv.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "gdal_priv.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: grassdataset.cpp 27384 2014-05-24 12:28:12Z rouault $");
-
-CPL_C_START
-void	GDALRegister_GRASS(void);
-CPL_C_END
+CPL_CVSID("$Id: grassdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 /************************************************************************/
 /*                         Grass2CPLErrorHook()                         */
@@ -104,7 +101,7 @@ class GRASSRasterBand : public GDALRasterBand
 
   public:
 
-                   GRASSRasterBand( GRASSDataset *, int, 
+                   GRASSRasterBand( GRASSDataset *, int,
                                     const char *, const char * );
     virtual        ~GRASSRasterBand();
 
@@ -139,7 +136,7 @@ GRASSRasterBand::GRASSRasterBand( GRASSDataset *poDS, int nBand,
 /* -------------------------------------------------------------------- */
     struct FPRange sRange;
 
-    if( G_read_fp_range( (char *) pszCellName, (char *) pszMapset, 
+    if( G_read_fp_range( (char *) pszCellName, (char *) pszMapset,
                          &sRange ) == -1 )
     {
         bHaveMinMax = FALSE;
@@ -190,7 +187,7 @@ GRASSRasterBand::GRASSRasterBand( GRASSDataset *poDS, int nBand,
         this->eDataType = GDT_Float64;
         dfNoData = -12345.0;
     }
-    
+
     nBlockXSize = poDS->nRasterXSize;;
     nBlockYSize = 1;
 
@@ -202,7 +199,7 @@ GRASSRasterBand::GRASSRasterBand( GRASSDataset *poDS, int nBand,
     struct Colors sGrassColors;
 
     poCT = NULL;
-    if( G_read_colors( (char *) pszCellName, (char *) pszMapset, 
+    if( G_read_colors( (char *) pszCellName, (char *) pszMapset,
                        &sGrassColors ) == 1 )
     {
         poCT = new GDALColorTable();
@@ -263,11 +260,11 @@ CPLErr GRASSRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
 {
     char *pachNullBuf;
-    
+
     pachNullBuf = (char *) CPLMalloc(nBlockXSize);
     G_get_null_value_row( hCell, pachNullBuf, nBlockYOff );
-            
-    if( eDataType == GDT_Float32 || eDataType == GDT_Float64 
+
+    if( eDataType == GDT_Float32 || eDataType == GDT_Float64
         || eDataType == GDT_UInt32 )
     {
         G_get_raster_row( hCell, pImage, nBlockYOff, nGRSType  );
@@ -280,16 +277,15 @@ CPLErr GRASSRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                     ((GUInt32 *) pImage)[i] = (GUInt32) dfNoData;
                 else if( eDataType == GDT_Float32 )
                     ((float *) pImage)[i] = dfNoData;
-                else 
+                else
                     ((double *) pImage)[i] = dfNoData;
             }
         }
-        
     }
     else
     {
         GUInt32 *panRow = (GUInt32 *) CPLMalloc(4 * nBlockXSize);
-        
+
         G_get_raster_row( hCell, panRow, nBlockYOff, nGRSType  );
 
         for( int i = 0; i < nBlockXSize; i++ )
@@ -298,7 +294,7 @@ CPLErr GRASSRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                 panRow[i] = (GUInt32) dfNoData;
         }
 
-        GDALCopyWords( panRow, GDT_UInt32, 4, 
+        GDALCopyWords( panRow, GDT_UInt32, 4,
                        pImage, eDataType, GDALGetDataTypeSize(eDataType)/8,
                        nBlockXSize );
 
@@ -371,7 +367,7 @@ double GRASSRasterBand::GetMaximum( int *pbSuccess )
         return 4294967295.0;
     else if( eDataType == GDT_UInt16 )
         return 65535;
-    else 
+    else
         return 255;
 }
 
@@ -426,7 +422,7 @@ GRASSDataset::~GRASSDataset()
 /*                          GetProjectionRef()                          */
 /************************************************************************/
 
-const char *GRASSDataset::GetProjectionRef() 
+const char *GRASSDataset::GetProjectionRef()
 {
     if( pszProjection == NULL )
         return "";
@@ -438,10 +434,10 @@ const char *GRASSDataset::GetProjectionRef()
 /*                          GetGeoTransform()                           */
 /************************************************************************/
 
-CPLErr GRASSDataset::GetGeoTransform( double * padfGeoTransform ) 
+CPLErr GRASSDataset::GetGeoTransform( double * padfGeoTransform )
 {
     memcpy( padfGeoTransform, adfGeoTransform, sizeof(double) * 6 );
-    
+
     return CE_None;
 }
 
@@ -476,7 +472,7 @@ GDALDataset *GRASSDataset::Open( GDALOpenInfo * poOpenInfo )
         G_free( pszMapset );
         G_free( pszCell );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Check if this is a valid GRASS imagery group.                   */
 /* -------------------------------------------------------------------- */
@@ -486,7 +482,7 @@ GDALDataset *GRASSDataset::Open( GDALOpenInfo * poOpenInfo )
 
         I_init_group_ref( &ref );
         I_get_group_ref( pszCell, &ref );
-        
+
         for( int iRef = 0; iRef < ref.nfiles; iRef++ )
         {
             papszCells = CSLAddString( papszCells, ref.file[iRef].name );
@@ -511,12 +507,12 @@ GDALDataset *GRASSDataset::Open( GDALOpenInfo * poOpenInfo )
 
     /* notdef: should only allow read access to an existing cell, right? */
     poDS->eAccess = poOpenInfo->eAccess;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Capture some information from the file that is of interest.     */
 /* -------------------------------------------------------------------- */
     struct Cell_head	sCellInfo;
-    
+
     if( G_get_cellhd( papszCells[0], papszMapsets[0], &sCellInfo ) != 0 )
     {
         /* notdef: report failure. */
@@ -558,24 +554,24 @@ GDALDataset *GRASSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     for( int iBand = 0; papszCells[iBand] != NULL; iBand++ )
     {
-        poDS->SetBand( iBand+1, 
-                       new GRASSRasterBand( poDS, iBand+1, 
-                                            papszMapsets[iBand], 
+        poDS->SetBand( iBand+1,
+                       new GRASSRasterBand( poDS, iBand+1,
+                                            papszMapsets[iBand],
                                             papszCells[iBand] ) );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The GRASS driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
     }
-    
+
     return poDS;
 }
 
@@ -586,25 +582,20 @@ GDALDataset *GRASSDataset::Open( GDALOpenInfo * poOpenInfo )
 void GDALRegister_GRASS()
 
 {
-    GDALDriver	*poDriver;
-    
-    if (! GDAL_CHECK_VERSION("GDAL/GRASS driver"))
+    if( !GDAL_CHECK_VERSION( "GDAL/GRASS driver" ) )
         return;
 
-    if( GDALGetDriverByName( "GRASS" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "GRASS" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "GRASS Database Rasters" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_grass.html" );
-        
-        poDriver->pfnOpen = GRASSDataset::Open;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
-}
+    if( GDALGetDriverByName( "GRASS" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "GRASS" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "GRASS Database Rasters" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_grass.html" );
 
+    poDriver->pfnOpen = GRASSDataset::Open;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/frmts/grass/pkg/Makefile.in b/frmts/grass/pkg/Makefile.in
index 007df6d..9bac96a 100644
--- a/frmts/grass/pkg/Makefile.in
+++ b/frmts/grass/pkg/Makefile.in
@@ -4,9 +4,9 @@ LD	=	@CXX@
 
 CPPFLAGS = -DUSE_CPL -DGRASS_GISBASE=\"@GRASS_GISBASE@\" \
 	  @GDAL_INC@ @GRASS_INCLUDE@ @PQ_INCLUDE@ @CPPFLAGS@
-CXXFLAGS = @CXX_WFLAGS@ @CXX_PIC@ 
-CFLAGS   = @CFLAGS@ 
-LDFLAGS  = @LDFLAGS@ 
+CXXFLAGS = @CXX_WFLAGS@ @CXX_PIC@
+CFLAGS   = @CFLAGS@
+LDFLAGS  = @LDFLAGS@
 
 RANLIB		=	@RANLIB@
 SO_EXT		=	@SO_EXT@
@@ -40,7 +40,7 @@ install:	default
 	cp -r @GRASS_GISBASE@/driver/db/* ${GRASSTABLES_DIR}/driver/db/
 
 clean:
-	rm -f $(OLIBNAME) $(GLIBNAME) *.o 
+	rm -f $(OLIBNAME) $(GLIBNAME) *.o
 
 distclean: clean
 	rm -fr Makefile config.status config.log autom*.cache
@@ -49,7 +49,7 @@ distclean: clean
 $(GLIBNAME):	grass57dataset.o
 	$(LD_SHARED) $(LDFLAGS) grass57dataset.o $(LIBS) -o $(GLIBNAME)
 
-$(OLIBNAME):	ogrgrassdriver.o ogrgrassdatasource.o ogrgrasslayer.o 
+$(OLIBNAME):	ogrgrassdriver.o ogrgrassdatasource.o ogrgrasslayer.o
 	$(LD_SHARED) $(LDFLAGS) ogrgrassdriver.o ogrgrassdatasource.o ogrgrasslayer.o $(LIBS) -o $(OLIBNAME)
 
 %.o:	%.cpp
diff --git a/frmts/grass/pkg/configure.in b/frmts/grass/pkg/configure.in
index 0ac90cb..a0cfa9c 100644
--- a/frmts/grass/pkg/configure.in
+++ b/frmts/grass/pkg/configure.in
@@ -1,5 +1,5 @@
 dnl ***************************************************************************
-dnl $Id: configure.in 28598 2015-03-03 07:34:28Z martinl $
+dnl $Id: configure.in 33717 2016-03-14 06:29:14Z goatbar $
 dnl
 dnl Project:  GDAL GRASS Plugin
 dnl Purpose:  Configure source file.
@@ -127,9 +127,9 @@ if test "$with_grass" != "yes" ; then
   if test "$GRASS_SETTING" = "no" ; then
     AC_CHECK_LIB(grass_gis,G_asprintf,GRASS_SETTING=grass57+,GRASS_SETTING=no,-L$with_grass/lib -lgrass_datetime)
   fi
-   
-  if test "$GRASS_SETTING" != "no" ; then   
-    if test "$GRASS_SETTING" = "grass70+" ; then   
+
+  if test "$GRASS_SETTING" != "no" ; then
+    if test "$GRASS_SETTING" = "grass70+" ; then
       G_RASTLIBS="-lgrass_raster -lgrass_imagery"
       G_VECTLIBS="-lgrass_vector -lgrass_dig2 -lgrass_dgl -lgrass_rtree -lgrass_linkm -lgrass_dbmiclient -lgrass_dbmibase"
       LIBS="-L$with_grass/lib $G_VECTLIBS $G_RASTLIBS -lgrass_gproj -lgrass_gmath -lgrass_gis -lgrass_datetime $LIBS"
diff --git a/frmts/grib/degrib18/degrib/clock.c b/frmts/grib/degrib18/degrib/clock.c
index 4d43056..880348d 100644
--- a/frmts/grib/degrib18/degrib/clock.c
+++ b/frmts/grib/degrib18/degrib/clock.c
@@ -409,13 +409,13 @@ int Clock_MonthNum (int day, sInt4 year)
  *
  * PURPOSE
  *   Returns either the number of days in the month or the number of days
- * since the begining of the year.
+ * since the beginning of the year.
  *
  * ARGUMENTS
  * month = Month in question. (Input)
  *   day = Day of month in question (Input)
  *  year = years since the epoch (Input)
- * f_tot = 1 if we want total days from begining of year,
+ * f_tot = 1 if we want total days from beginning of year,
  *         0 if we want total days in the month. (Input)
  *
  * RETURNS: int
@@ -465,7 +465,7 @@ int Clock_NumDay (int month, int day, sInt4 year, char f_tot)
  * Arthur Taylor / MDL
  *
  * PURPOSE
- *   To format part of the output clock string.
+ *   To format part of the output l_clock string.
  *
  * ARGUMENTS
  *    buffer = The output string to write to. (Output)
@@ -486,15 +486,16 @@ int Clock_NumDay (int month, int day, sInt4 year, char f_tot)
  * NOTES
  *****************************************************************************
  */
-static void Clock_FormatParse (char buffer[100], sInt4 sec, float floatSec,
+#define SIZEOF_BUFFER   100
+static void Clock_FormatParse (char buffer[SIZEOF_BUFFER], sInt4 sec, float floatSec,
                                sInt4 totDay, sInt4 year, int month, int day,
                                char format)
 {
-   static char *MonthName[] = {
+   static const char * const MonthName[] = {
       "January", "February", "March", "April", "May", "June", "July",
       "August", "September", "October", "November", "December"
    };
-   static char *DayName[] = {
+   static const char * const DayName[] = {
       "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
       "Saturday"
    };
@@ -510,57 +511,57 @@ static void Clock_FormatParse (char buffer[100], sInt4 sec, float floatSec,
    switch (format) {
       case 'd':
          dy = (Clock_NumDay (month, 1, year, 1) - 1);
-         sprintf (buffer, "%02d", day - dy);
+         snprintf(buffer, SIZEOF_BUFFER, "%02d", day - dy);
          return;
       case 'm':
-         sprintf (buffer, "%02d", month);
+         snprintf(buffer, SIZEOF_BUFFER, "%02d", month);
          return;
       case 'E':
-         sprintf (buffer, "%2d", month);
+         snprintf(buffer, SIZEOF_BUFFER, "%2d", month);
          return;
       case 'Y':
-         sprintf (buffer, "%04d", year);
+         snprintf(buffer, SIZEOF_BUFFER, "%04d", year);
          return;
       case 'H':
-         sprintf (buffer, "%02d", (int) ((sec % 86400L) / 3600));
+         snprintf(buffer, SIZEOF_BUFFER, "%02d", (int) ((sec % 86400L) / 3600));
          return;
       case 'G':
-         sprintf (buffer, "%2d", (int) ((sec % 86400L) / 3600));
+         snprintf(buffer, SIZEOF_BUFFER, "%2d", (int) ((sec % 86400L) / 3600));
          return;
       case 'M':
-         sprintf (buffer, "%02d", (int) ((sec % 3600) / 60));
+         snprintf(buffer, SIZEOF_BUFFER, "%02d", (int) ((sec % 3600) / 60));
          return;
       case 'S':
-         sprintf (buffer, "%02d", (int) (sec % 60));
+         snprintf(buffer, SIZEOF_BUFFER, "%02d", (int) (sec % 60));
          return;
       case 'f':
-         sprintf (buffer, "%05.2f", ((int) (sec % 60)) + floatSec);
+         snprintf(buffer, SIZEOF_BUFFER, "%05.2f", ((int) (sec % 60)) + floatSec);
          return;
       case 'n':
-         sprintf (buffer, "\n");
+         snprintf(buffer, SIZEOF_BUFFER, "\n");
          return;
       case '%':
-         sprintf (buffer, "%%");
+         snprintf(buffer, SIZEOF_BUFFER, "%%");
          return;
       case 't':
-         sprintf (buffer, "\t");
+         snprintf(buffer, SIZEOF_BUFFER, "\t");
          return;
       case 'y':
-         sprintf (buffer, "%02d", (int) (year % 100));
+         snprintf(buffer, SIZEOF_BUFFER, "%02d", (int) (year % 100));
          return;
       case 'I':
          i = ((sec % 43200L) / 3600);
          if (i == 0) {
-            sprintf (buffer, "12");
+            snprintf(buffer, SIZEOF_BUFFER, "12");
          } else {
-            sprintf (buffer, "%02d", i);
+            snprintf(buffer, SIZEOF_BUFFER, "%02d", i);
          }
          return;
       case 'p':
          if (((sec % 86400L) / 3600) >= 12) {
-            sprintf (buffer, "PM");
+            snprintf(buffer, SIZEOF_BUFFER, "PM");
          } else {
-            sprintf (buffer, "AM");
+            snprintf(buffer, SIZEOF_BUFFER, "AM");
          }
          return;
       case 'B':
@@ -579,28 +580,28 @@ static void Clock_FormatParse (char buffer[100], sInt4 sec, float floatSec,
          buffer[3] = '\0';
          return;
       case 'w':
-         sprintf (buffer, "%d", (int) ((4 + totDay) % 7));
+         snprintf(buffer, SIZEOF_BUFFER, "%d", (int) ((4 + totDay) % 7));
          return;
       case 'j':
-         sprintf (buffer, "%03d", day + 1);
+         snprintf(buffer, SIZEOF_BUFFER, "%03d", day + 1);
          return;
       case 'e':
          dy = (Clock_NumDay (month, 1, year, 1) - 1);
-         sprintf (buffer, "%d", (int) (day - dy));
+         snprintf(buffer, SIZEOF_BUFFER, "%d", (int) (day - dy));
          return;
       case 'W':
          i = (1 - ((4 + totDay - day) % 7)) % 7;
          if (day < i)
-            sprintf (buffer, "00");
+            snprintf(buffer, SIZEOF_BUFFER, "00");
          else
-            sprintf (buffer, "%02d", ((day - i) / 7) + 1);
+            snprintf(buffer, SIZEOF_BUFFER, "%02d", ((day - i) / 7) + 1);
          return;
       case 'U':
          i = (-((4 + totDay - day) % 7)) % 7;
          if (day < i)
-            sprintf (buffer, "00");
+            snprintf(buffer, SIZEOF_BUFFER, "00");
          else
-            sprintf (buffer, "%02d", ((day - i) / 7) + 1);
+            snprintf(buffer, SIZEOF_BUFFER, "%02d", ((day - i) / 7) + 1);
          return;
       case 'D':
          Clock_FormatParse (buffer, sec, floatSec, totDay, year, month,
@@ -678,7 +679,7 @@ static void Clock_FormatParse (char buffer[100], sInt4 sec, float floatSec,
          }
          return;
       default:
-         sprintf (buffer, "unknown %c", format);
+         snprintf(buffer, SIZEOF_BUFFER, "unknown %c", format);
          return;
    }
 }
@@ -708,17 +709,17 @@ static void Clock_FormatParse (char buffer[100], sInt4 sec, float floatSec,
  */
 sChar Clock_GetTimeZone ()
 {
-   struct tm time;
+   struct tm l_time;
    time_t ansTime;
    struct tm *gmTime;
    static int timeZone = 9999;
 
    if (timeZone == 9999) {
       /* Cheap method of getting global time_zone variable. */
-      memset (&time, 0, sizeof (struct tm));
-      time.tm_year = 70;
-      time.tm_mday = 2;
-      ansTime = mktime (&time);
+      memset (&l_time, 0, sizeof (struct tm));
+      l_time.tm_year = 70;
+      l_time.tm_mday = 2;
+      ansTime = mktime (&l_time);
       gmTime = gmtime (&ansTime);
       timeZone = gmTime->tm_hour;
       if (gmTime->tm_mday != 2) {
@@ -740,7 +741,7 @@ sChar Clock_GetTimeZone ()
  * At 2 AM DT (or 1 AM ST) in October -> 1 AM ST (and we return 0)
  *
  * ARGUMENTS
- *    clock = The time stored as a double. (Input)
+ *    l_clock = The time stored as a double. (Input)
  * TimeZone = hours to add to local time to get UTC. (Input)
  *
  * RETURNS: int
@@ -754,20 +755,20 @@ sChar Clock_GetTimeZone ()
  * NOTES
  *****************************************************************************
  */
-int Clock_IsDaylightSaving2 (double clock, sChar TimeZone)
+int Clock_IsDaylightSaving2 (double l_clock, sChar TimeZone)
 {
    sInt4 totDay, year;
    int day, first;
    double secs;
 
-   clock = clock - TimeZone * 3600.;
+   l_clock = l_clock - TimeZone * 3600.;
    /* Clock should now be in Standard Time, so comparisons later have to be
     * based on Standard Time. */
 
-   totDay = (sInt4) floor (clock / SEC_DAY);
+   totDay = (sInt4) floor (l_clock / SEC_DAY);
    Clock_Epoch2YearDay (totDay, &day, &year);
    /* Figure out number of seconds since beginning of year. */
-   secs = clock - (totDay - day) * SEC_DAY;
+   secs = l_clock - (totDay - day) * SEC_DAY;
 
    /* figure out if 1/1/year is mon/tue/.../sun */
    first = ((4 + (totDay - day)) % 7); /* -day should get 1/1 but may need
@@ -863,7 +864,7 @@ int Clock_IsDaylightSaving2 (double clock, sChar TimeZone)
  * PURPOSE
  *
  * ARGUMENTS
- * clock = The time stored as a double. (Input)
+ * l_clock = The time stored as a double. (Input)
  *  year = The year. (Output)
  * month = The month. (Output)
  *   day = The day. (Output)
@@ -879,17 +880,17 @@ int Clock_IsDaylightSaving2 (double clock, sChar TimeZone)
  * NOTES
  *****************************************************************************
  */
-void Clock_PrintDate (double clock, sInt4 *year, int *month, int *day,
+void Clock_PrintDate (double l_clock, sInt4 *year, int *month, int *day,
                       int *hour, int *min, double *sec)
 {
    sInt4 totDay;
    sInt4 intSec;
 
-   totDay = (sInt4) floor (clock / SEC_DAY);
+   totDay = (sInt4) floor (l_clock / SEC_DAY);
    Clock_Epoch2YearDay (totDay, day, year);
    *month = Clock_MonthNum (*day, *year);
    *day = *day - Clock_NumDay (*month, 1, *year, 1) + 1;
-   *sec = clock - ((double) totDay) * SEC_DAY;
+   *sec = l_clock - ((double) totDay) * SEC_DAY;
    intSec = (sInt4) (*sec);
    *hour = (int) ((intSec % 86400L) / 3600);
    *min = (int) ((intSec % 3600) / 60);
@@ -902,13 +903,13 @@ void Clock_PrintDate (double clock, sInt4 *year, int *month, int *day,
  * Arthur Taylor / MDL
  *
  * PURPOSE
- *   To create formated output from a time structure that is stored as a
+ *   To create formatted output from a time structure that is stored as a
  * double.
  *
  * ARGUMENTS
  * buffer = Destination to write the format to. (Output)
  *      n = The number of characters in buffer. (Input)
- *  clock = The time stored as a double. (Input)
+ *  l_clock = The time stored as a double. (Input)
  * format = The desired output format. (Input)
  *  f_gmt = 0 output GMT, 1 output LDT, 2 output LST. (Input)
  *
@@ -921,7 +922,7 @@ void Clock_PrintDate (double clock, sInt4 *year, int *month, int *day,
  * NOTES
  *****************************************************************************
  */
-void Clock_Print (char *buffer, int n, double clock, const char *format,
+void Clock_Print (char *buffer, int n, double l_clock, const char *format,
                   char f_gmt)
 {
    sInt4 totDay, year;
@@ -937,19 +938,19 @@ void Clock_Print (char *buffer, int n, double clock, const char *format,
    /* Handle gmt problems. */
    if (f_gmt != 0) {
       timeZone = Clock_GetTimeZone ();
-      /* clock is currently in UTC */
-      clock -= timeZone * 3600;
-      /* clock is now in local standard time Note: A 0 is passed to
+      /* l_clock is currently in UTC */
+      l_clock -= timeZone * 3600;
+      /* l_clock is now in local standard time Note: A 0 is passed to
        * DaylightSavings so it converts from local to local standard time. */
-      if ((f_gmt == 1) && (Clock_IsDaylightSaving2 (clock, 0) == 1)) {
-         clock = clock + 3600;
+      if ((f_gmt == 1) && (Clock_IsDaylightSaving2 (l_clock, 0) == 1)) {
+         l_clock = l_clock + 3600;
       }
    }
    /* Convert from seconds to days and seconds. */
-   totDay = (sInt4) floor (clock / SEC_DAY);
+   totDay = (sInt4) floor (l_clock / SEC_DAY);
    Clock_Epoch2YearDay (totDay, &day, &year);
    month = Clock_MonthNum (day, year);
-   floatSec = clock - ((double) totDay) * SEC_DAY;
+   floatSec = l_clock - ((double) totDay) * SEC_DAY;
    sec = (sInt4) floatSec;
    floatSec = floatSec - sec;
 
@@ -970,7 +971,7 @@ void Clock_Print (char *buffer, int n, double clock, const char *format,
                                day, format[i]);
             buffer[j] = '\0';
             strncat (buffer, locBuff, n - j);
-            j += strlen (locBuff);
+            j += (int)strlen (locBuff);
             f_perc = 0;
          }
       }
@@ -983,7 +984,7 @@ void Clock_Print (char *buffer, int n, double clock, const char *format,
  * Arthur Taylor / MDL
  *
  * PURPOSE
- *   To create formated output from a time structure that is stored as a
+ *   To create formatted output from a time structure that is stored as a
  * double.  This is similar to Clock_Print, except it bases the timezone
  * shift on what the user supplies rather than the system timezone, and
  * accepts a flag that indicates whether to inquire about daylight savings.
@@ -994,7 +995,7 @@ void Clock_Print (char *buffer, int n, double clock, const char *format,
  * ARGUMENTS
  *     buffer = Destination to write the format to. (Output)
  *          n = The number of characters in buffer. (Input)
- *      clock = The time stored as a double (asumed in UTC). (Input)
+ *      l_clock = The time stored as a double (asumed in UTC). (Input)
  *     format = The desired output format. (Input)
  *   timeZone = Hours to add to local time to get UTC. (Input)
  * f_dayCheck = True if we should check if daylight savings is in effect,
@@ -1008,7 +1009,7 @@ void Clock_Print (char *buffer, int n, double clock, const char *format,
  * NOTES
  *****************************************************************************
  */
-void Clock_Print2 (char *buffer, int n, double clock, char *format,
+void Clock_Print2 (char *buffer, int n, double l_clock, char *format,
                    sChar timeZone, sChar f_dayCheck)
 {
    sInt4 totDay, year;
@@ -1020,22 +1021,22 @@ void Clock_Print2 (char *buffer, int n, double clock, char *format,
    char f_perc;
    char locBuff[100];
 
-   /* clock is currently in UTC */
-   clock -= timeZone * 3600;
-   /* clock is now in local standard time */
+   /* l_clock is currently in UTC */
+   l_clock -= timeZone * 3600;
+   /* l_clock is now in local standard time */
    if (f_dayCheck) {
       /* Note: A 0 is passed to DaylightSavings so it converts from local to
        * local standard time. */
-      if (Clock_IsDaylightSaving2 (clock, 0) == 1) {
-         clock += 3600;
+      if (Clock_IsDaylightSaving2 (l_clock, 0) == 1) {
+         l_clock += 3600;
       }
    }
 
    /* Convert from seconds to days and seconds. */
-   totDay = (sInt4) floor (clock / SEC_DAY);
+   totDay = (sInt4) floor (l_clock / SEC_DAY);
    Clock_Epoch2YearDay (totDay, &day, &year);
    month = Clock_MonthNum (day, year);
-   floatSec = clock - ((double) totDay) * SEC_DAY;
+   floatSec = l_clock - ((double) totDay) * SEC_DAY;
    sec = (sInt4) floatSec;
    floatSec = floatSec - sec;
 
@@ -1056,7 +1057,7 @@ void Clock_Print2 (char *buffer, int n, double clock, char *format,
                                day, format[i]);
             buffer[j] = '\0';
             strncat (buffer, locBuff, n - j);
-            j += strlen (locBuff);
+            j += (int)strlen (locBuff);
             f_perc = 0;
          }
       }
@@ -1110,16 +1111,16 @@ double Clock_Clicks (void)
  * NOTES
  *****************************************************************************
  */
-int Clock_SetSeconds (double *time, sChar f_set)
+int Clock_SetSeconds (double *ptime, sChar f_set)
 {
    static double ans = 0;
    static int f_ansSet = 0;
 
    if (f_set) {
-      ans = *time;
+      ans = *ptime;
       f_ansSet = 1;
    } else if (f_ansSet) {
-      *time = ans;
+      *ptime = ans;
    }
    return f_ansSet;
 }
@@ -1161,41 +1162,41 @@ double Clock_Seconds (void)
 int Clock_PrintZone2 (char *ptr, sChar TimeZone, char f_day)
 {
    if (TimeZone == 0) {
-      sprintf (ptr, "UTC");
+      strcpy (ptr, "UTC");
       return 0;
    } else if (TimeZone == 5) {
       if (f_day) {
-         sprintf (ptr, "EDT");
+         strcpy (ptr, "EDT");
       } else {
-         sprintf (ptr, "EST");
+         strcpy (ptr, "EST");
       }
       return 0;
    } else if (TimeZone == 6) {
       if (f_day) {
-         sprintf (ptr, "CDT");
+         strcpy (ptr, "CDT");
       } else {
-         sprintf (ptr, "CST");
+         strcpy (ptr, "CST");
       }
       return 0;
    } else if (TimeZone == 7) {
       if (f_day) {
-         sprintf (ptr, "MDT");
+         strcpy (ptr, "MDT");
       } else {
-         sprintf (ptr, "MST");
+         strcpy (ptr, "MST");
       }
       return 0;
    } else if (TimeZone == 8) {
       if (f_day) {
-         sprintf (ptr, "PDT");
+         strcpy (ptr, "PDT");
       } else {
-         sprintf (ptr, "PST");
+         strcpy (ptr, "PST");
       }
       return 0;
    } else if (TimeZone == 9) {
       if (f_day) {
-         sprintf (ptr, "YDT");
+         strcpy (ptr, "YDT");
       } else {
-         sprintf (ptr, "YST");
+         strcpy (ptr, "YST");
       }
       return 0;
    }
@@ -1396,7 +1397,7 @@ int Clock_ScanMonth (char *ptr)
  */
 void Clock_PrintMonth3 (int mon, char *buffer, CPL_UNUSED int buffLen)
 {
-   static char *MonthName[] = {
+   static const char * const MonthName[] = {
       "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT",
       "NOV", "DEC"
    };
@@ -1424,7 +1425,7 @@ void Clock_PrintMonth3 (int mon, char *buffer, CPL_UNUSED int buffLen)
  */
 void Clock_PrintMonth (int mon, char *buffer, CPL_UNUSED int buffLen)
 {
-   static char *MonthName[] = {
+   static const char * const MonthName[] = {
       "January", "February", "March", "April", "May", "June", "July",
       "August", "September", "October", "November", "December"
    };
@@ -1612,7 +1613,7 @@ Example:
 1994-11-05T13:15:30Z corresponds to the same instant.
 */
 static int Clock_ScanDash (char *word, int *mon, int *day, sInt4 *year,
-                           double *time, char *f_time)
+                           double *ptime, char *f_time)
 {
    char *ptr3;
    char *ptr = word;
@@ -1707,7 +1708,7 @@ static int Clock_ScanDash (char *word, int *mon, int *day, sInt4 *year,
       }
    }
    *f_time = 1;
-   *time = sec + min * 60 + hour * 3600 - offset;
+   *ptime = sec + min * 60 + hour * 3600 - offset;
    return 0;
 }
 
@@ -1728,17 +1729,15 @@ static int Clock_ScanDash (char *word, int *mon, int *day, sInt4 *year,
  * NOTES
  *****************************************************************************
  */
-/* prj::slosh prj::stm2trk and prj::degrib use this with clock zero'ed
-   out, so I have now made sure clock is zero'ed. */
-void Clock_ScanDate (double *clock, sInt4 year, int mon, int day)
+/* prj::slosh prj::stm2trk and prj::degrib use this with l_clock zero'ed
+   out, so I have now made sure l_clock is zero'ed. */
+void Clock_ScanDate (double *l_clock, sInt4 year, int mon, int day)
 {
    int i;
    sInt4 delt, temp, totDay;
 
-   myAssert ((mon >= 1) && (mon <= 12));
-
-   /* Makes sure clock is zero'ed out. */
-   *clock = 0;
+   /* Makes sure l_clock is zero'ed out. */
+   *l_clock = 0;
 
    if ((mon < 1) || (mon > 12) || (day < 0) || (day > 31))
       return;
@@ -1797,12 +1796,12 @@ void Clock_ScanDate (double *clock, sInt4 year, int mon, int day)
          }
       }
    }
-   *clock = *clock + ((double) (totDay)) * 24 * 3600;
+   *l_clock = *l_clock + ((double) (totDay)) * 24 * 3600;
 }
 
-int Clock_ScanDateNumber (double *clock, char *buffer)
+int Clock_ScanDateNumber (double *l_clock, char *buffer)
 {
-   int buffLen = strlen (buffer);
+   int buffLen = (int)strlen (buffer);
    sInt4 year;
    int mon = 1;
    int day = 1;
@@ -1811,7 +1810,7 @@ int Clock_ScanDateNumber (double *clock, char *buffer)
    int sec = 0;
    char c_temp;
 
-   *clock = 0;
+   *l_clock = 0;
    if ((buffLen != 4) && (buffLen != 6) && (buffLen != 8) &&
        (buffLen != 10) && (buffLen != 12) && (buffLen != 14)) {
       return 1;
@@ -1850,20 +1849,20 @@ int Clock_ScanDateNumber (double *clock, char *buffer)
       sec = atoi (buffer + 12);
       buffer[14] = c_temp;
    }
-   Clock_ScanDate (clock, year, mon, day);
-   *clock = *clock + sec + min * 60 + hour * 3600;
+   Clock_ScanDate (l_clock, year, mon, day);
+   *l_clock = *l_clock + sec + min * 60 + hour * 3600;
    return 0;
 }
 
-void Clock_PrintDateNumber (double clock, char buffer[15])
+void Clock_PrintDateNumber (double l_clock, char buffer[15])
 {
    sInt4 year;
    int month, day, hour, min, sec;
    double d_sec;
 
-   Clock_PrintDate (clock, &year, &month, &day, &hour, &min, &d_sec);
+   Clock_PrintDate (l_clock, &year, &month, &day, &hour, &min, &d_sec);
    sec = (int) d_sec;
-   sprintf (buffer, "%04d%02d%02d%02d%02d%02d", year, month, day, hour, min,
+   snprintf(buffer, 15, "%04d%02d%02d%02d%02d%02d", year, month, day, hour, min,
             sec);
 }
 
@@ -1897,7 +1896,7 @@ enum {
  */
 /* Start at *Start.  Advance Start until it is at first non-space,
  * non-',' non-'.' character.  Move End to first space, ',' or '.' after
- * new Start location.  Copy upto 30 characters (in caps) into word. */
+ * new Start location.  Copy up to 30 characters (in caps) into word. */
 /* return -1 if no next word, 0 otherwise */
 static int Clock_GetWord (char **Start, char **End, char word[30],
                           int *wordType)
@@ -1988,13 +1987,13 @@ typedef struct {
  * NOTES
  * * f_gmt == 0 no adjust, 1 adjust as LDT, 2 adjust as LST *
  *  Adjusted from:
- * if ((f_gmt == 2) && (Clock_IsDaylightSaving2 (*clock, 0) == 1)) {
+ * if ((f_gmt == 2) && (Clock_IsDaylightSaving2 (*l_clock, 0) == 1)) {
  * to:
- * if ((f_gmt == 1) && (Clock_IsDaylightSaving2 (*clock, 0) == 1)) {
+ * if ((f_gmt == 1) && (Clock_IsDaylightSaving2 (*l_clock, 0) == 1)) {
 
  *****************************************************************************
  */
-int Clock_Scan (double *clock, char *buffer, char f_gmt)
+int Clock_Scan (double *l_clock, char *buffer, char f_gmt)
 {
    char *ptr, *ptr2;
    char *ptr3;
@@ -2008,7 +2007,7 @@ int Clock_Scan (double *clock, char *buffer, char f_gmt)
    int day;
    sInt4 year;
    char f_year = 0;
-   int index;
+   int l_index;
    int ans;
    stackType *Stack = NULL;
    relType *Rel = NULL;
@@ -2073,7 +2072,7 @@ int Clock_Scan (double *clock, char *buffer, char f_gmt)
          Stack = (stackType *) realloc ((void *) Stack,
                                         lenStack * sizeof (stackType));
          Stack[lenStack - 1].val = atoi (word);
-         Stack[lenStack - 1].len = strlen (word);
+         Stack[lenStack - 1].len = (int)strlen (word);
       } else if (strcmp (word, "AM") == 0) {
          if (f_ampm != -1) {
             printf ("Detected multiple am/pm\n");
@@ -2100,12 +2099,12 @@ int Clock_Scan (double *clock, char *buffer, char f_gmt)
          }
          f_timeZone = 1;
          wordType = WT_TIMEZONE;
-      } else if ((index = Clock_ScanMonth (word)) != -1) {
+      } else if ((l_index = Clock_ScanMonth (word)) != -1) {
          if ((f_slashWord) || (f_monthWord)) {
             printf ("Detected multiple months or already defined month.\n");
             goto errorReturn;
          }
-         month = index;
+         month = l_index;
          /* Get the next word? First preserve the pointer */
          ptr3 = ptr2;
          ptr = ptr2;
@@ -2150,7 +2149,7 @@ int Clock_Scan (double *clock, char *buffer, char f_gmt)
          f_dateWord = 1;
 
          /* Ignore the day of the week info? */
-      } else if ((index = Clock_ScanWeekday (word)) != -1) {
+      } else if ((l_index = Clock_ScanWeekday (word)) != -1) {
          if ((f_slashWord) || (f_dayWord)) {
             printf ("Detected multiple day of week or already defined "
                     "day.\n");
@@ -2159,7 +2158,7 @@ int Clock_Scan (double *clock, char *buffer, char f_gmt)
          wordType = WT_DAY;
          f_dayWord = 1;
          f_dateWord = 1;
-      } else if (GetIndexFromStr (word, PreRel, &index) != -1) {
+      } else if (GetIndexFromStr (word, PreRel, &l_index) != -1) {
          wordType = WT_PRE_RELATIVE;
          /* Next word must be a unit word. */
          ptr = ptr2;
@@ -2172,32 +2171,32 @@ int Clock_Scan (double *clock, char *buffer, char f_gmt)
             printf ("Couldn't get the Relative unit\n");
             goto errorReturn;
          }
-         if (index != 1) {
+         if (l_index != 1) {
             lenRel++;
             Rel = (relType *) realloc ((void *) Rel,
                                        lenRel * sizeof (relType));
             Rel[lenRel - 1].relUnit = ans;
             Rel[lenRel - 1].amount = 1;
-            if (index == 0) {
+            if (l_index == 0) {
                Rel[lenRel - 1].f_negate = 1;
             } else {
                Rel[lenRel - 1].f_negate = 0;
             }
          }
-         printf ("Pre Relative Word: %s %d\n", word, index);
+         printf ("Pre Relative Word: %s %d\n", word, l_index);
 
       } else if (strcmp (word, "AGO") == 0) {
-         if ((lastWordType != WT_PRE_RELATIVE) ||
+         if ((lastWordType != WT_PRE_RELATIVE) &&
              (lastWordType != WT_RELATIVE_UNIT)) {
             printf ("Ago did not follow relative words\n");
             goto errorReturn;
          }
          Rel[lenRel - 1].f_negate = 1;
          wordType = WT_POST_RELATIVE;
-      } else if (GetIndexFromStr (word, RelUnit, &index) != -1) {
+      } else if (GetIndexFromStr (word, RelUnit, &l_index) != -1) {
          lenRel++;
          Rel = (relType *) realloc ((void *) Rel, lenRel * sizeof (relType));
-         Rel[lenRel - 1].relUnit = index;
+         Rel[lenRel - 1].relUnit = l_index;
          Rel[lenRel - 1].amount = 1;
          Rel[lenRel - 1].f_negate = 0;
          if (lastWordType == WT_INTEGER) {
@@ -2205,14 +2204,14 @@ int Clock_Scan (double *clock, char *buffer, char f_gmt)
             Rel[lenRel - 1].amount = Stack[lenStack].val;
          }
          wordType = WT_RELATIVE_UNIT;
-      } else if (GetIndexFromStr (word, AdjDay, &index) != -1) {
-         if (index != 1) {
+      } else if (GetIndexFromStr (word, AdjDay, &l_index) != -1) {
+         if (l_index != 1) {
             lenRel++;
             Rel = (relType *) realloc ((void *) Rel,
                                        lenRel * sizeof (relType));
             Rel[lenRel - 1].relUnit = 13; /* DAY in RelUnit list */
             Rel[lenRel - 1].amount = 1;
-            if (index == 0) {
+            if (l_index == 0) {
                Rel[lenRel - 1].f_negate = 1;
             } else {
                Rel[lenRel - 1].f_negate = 0;
@@ -2279,7 +2278,7 @@ int Clock_Scan (double *clock, char *buffer, char f_gmt)
             goto errorReturn;
          }
       }
-      lenStack = 0;
+      /*lenStack = 0;*/
    }
    if (!f_time) {
       if (f_ampm != -1) {
@@ -2311,8 +2310,8 @@ int Clock_Scan (double *clock, char *buffer, char f_gmt)
    if (f_dateWord || f_slashWord) {
       /* Check if we don't have the year. */
       if (!f_year) {
-         *clock = Clock_Seconds ();
-         Clock_Epoch2YearDay ((sInt4) (floor (*clock / SEC_DAY)), &i, &year);
+         *l_clock = Clock_Seconds ();
+         Clock_Epoch2YearDay ((sInt4) (floor (*l_clock / SEC_DAY)), &i, &year);
       }
       /* Deal with relative adjust by year and month. */
       for (i = 0; i < lenRel; i++) {
@@ -2330,14 +2329,14 @@ int Clock_Scan (double *clock, char *buffer, char f_gmt)
          year++;
          month -= 12;
       }
-      *clock = 0;
-      Clock_ScanDate (clock, year, month, day);
+      *l_clock = 0;
+      Clock_ScanDate (l_clock, year, month, day);
 
    } else {
       /* Pure Time words. */
-      *clock = Clock_Seconds ();
+      *l_clock = Clock_Seconds ();
       /* round off to start of day */
-      *clock = (floor (*clock / SEC_DAY)) * SEC_DAY;
+      *l_clock = (floor (*l_clock / SEC_DAY)) * SEC_DAY;
       /* Deal with relative adjust by year and month. */
       monthAdj = 0;
       yearAdj = 0;
@@ -2357,8 +2356,8 @@ int Clock_Scan (double *clock, char *buffer, char f_gmt)
          }
       }
       if ((monthAdj != 0) || (yearAdj != 0)) {
-         /* Break clock into mon/day/year */
-         Clock_Epoch2YearDay ((sInt4) (floor (*clock / SEC_DAY)),
+         /* Break l_clock into mon/day/year */
+         Clock_Epoch2YearDay ((sInt4) (floor (*l_clock / SEC_DAY)),
                               &day, &year);
          month = Clock_MonthNum (day, year);
          day -= (Clock_NumDay (month, 1, year, 1) - 1);
@@ -2372,58 +2371,58 @@ int Clock_Scan (double *clock, char *buffer, char f_gmt)
             year++;
             month -= 12;
          }
-         *clock = 0;
-         Clock_ScanDate (clock, year, month, day);
+         *l_clock = 0;
+         Clock_ScanDate (l_clock, year, month, day);
       }
    }
 
    /* Join the date and the time. */
-   *clock += curTime;
+   *l_clock += curTime;
 
    /* Finish the relative adjustments. */
    for (i = 0; i < lenRel; i++) {
       switch (Rel[i].relUnit) {
          case 3:       /* Fortnight. */
          case 4:
-            *clock += (Rel[i].amount * 14 * 24 * 3600.);
+            *l_clock += (Rel[i].amount * 14 * 24 * 3600.);
             break;
          case 5:       /* Week. */
          case 6:
-            *clock += (Rel[i].amount * 7 * 24 * 3600.);
+            *l_clock += (Rel[i].amount * 7 * 24 * 3600.);
             break;
          case 7:       /* Day. */
          case 8:
-            *clock += (Rel[i].amount * 24 * 3600.);
+            *l_clock += (Rel[i].amount * 24 * 3600.);
             break;
          case 9:       /* Hour. */
          case 10:
-            *clock += (Rel[i].amount * 3600.);
+            *l_clock += (Rel[i].amount * 3600.);
             break;
          case 11:      /* Minute. */
          case 12:
          case 13:
          case 14:
-            *clock += (Rel[i].amount * 60.);
+            *l_clock += (Rel[i].amount * 60.);
             break;
          case 15:      /* Second. */
          case 16:
          case 17:
          case 18:
-            *clock += Rel[i].amount;
+            *l_clock += Rel[i].amount;
             break;
       }
    }
 
    if (f_gmt != 0) {
-      /* IsDaylightSaving takes clock in GMT, and Timezone. */
+      /* IsDaylightSaving takes l_clock in GMT, and Timezone. */
       /* Note: A 0 is passed to DaylightSavings so it converts from LST to
        * LST. */
-      if ((f_gmt == 1) && (Clock_IsDaylightSaving2 (*clock, 0) == 1)) {
-         *clock = *clock - 3600;
+      if ((f_gmt == 1) && (Clock_IsDaylightSaving2 (*l_clock, 0) == 1)) {
+         *l_clock = *l_clock - 3600;
       }
       /* Handle gmt problems. We are going from Local time to GMT so we add
        * the TimeZone here. */
-      *clock = *clock + TimeZone * 3600;
+      *l_clock = *l_clock + TimeZone * 3600;
    }
 
    free (Stack);
@@ -2437,5 +2436,5 @@ int Clock_Scan (double *clock, char *buffer, char f_gmt)
 }
 
 #ifdef CLOCK_PROGRAM
-/* See clockstart.c */
+/* See l_clockstart.c */
 #endif
diff --git a/frmts/grib/degrib18/degrib/clock.h b/frmts/grib/degrib18/degrib/clock.h
index 0268701..3b4f15b 100644
--- a/frmts/grib/degrib18/degrib/clock.h
+++ b/frmts/grib/degrib18/degrib/clock.h
@@ -14,7 +14,7 @@ extern "C" {
 void Clock_Epoch2YearDay (sInt4 totDay, int *Day, sInt4 * Yr);
 int Clock_MonthNum (int day, sInt4 year);
 int Clock_NumDay (int month, int day, sInt4 year, char f_tot);
-sChar Clock_GetTimeZone ();
+sChar Clock_GetTimeZone (void);
 int Clock_IsDaylightSaving2 (double clock, sChar TimeZone);
 void Clock_PrintDate (double clock, sInt4 *year, int *month, int *day,
                       int *hour, int *min, double *sec);
diff --git a/frmts/grib/degrib18/degrib/degrib1.cpp b/frmts/grib/degrib18/degrib/degrib1.cpp
index 195344c..2c2138d 100644
--- a/frmts/grib/degrib18/degrib/degrib1.cpp
+++ b/frmts/grib/degrib18/degrib/degrib1.cpp
@@ -56,47 +56,6 @@
 #define DEF_NCEP_TABLE rean_nowarn
 enum Def_NCEP_Table { rean, opn, rean_nowarn, opn_nowarn };
 
-extern GRIB1ParmTable parm_table_ncep_opn[256];
-extern GRIB1ParmTable parm_table_ncep_reanal[256];
-extern GRIB1ParmTable parm_table_ncep_tdl[256];
-extern GRIB1ParmTable parm_table_ncep_mdl[256];
-extern GRIB1ParmTable parm_table_omb[256];
-extern GRIB1ParmTable parm_table_nceptab_129[256];
-extern GRIB1ParmTable parm_table_nceptab_130[256];
-extern GRIB1ParmTable parm_table_nceptab_131[256];
-
-extern GRIB1ParmTable parm_table_nohrsc[256];
-
-extern GRIB1ParmTable parm_table_cptec_254[256];
-
-extern GRIB1ParmTable parm_table_afwa_000[256];
-extern GRIB1ParmTable parm_table_afwa_001[256];
-extern GRIB1ParmTable parm_table_afwa_002[256];
-extern GRIB1ParmTable parm_table_afwa_003[256];
-extern GRIB1ParmTable parm_table_afwa_010[256];
-extern GRIB1ParmTable parm_table_afwa_011[256];
-
-extern GRIB1ParmTable parm_table_dwd_002[256];
-extern GRIB1ParmTable parm_table_dwd_201[256];
-extern GRIB1ParmTable parm_table_dwd_202[256];
-extern GRIB1ParmTable parm_table_dwd_203[256];
-
-extern GRIB1ParmTable parm_table_ecmwf_128[256];
-extern GRIB1ParmTable parm_table_ecmwf_129[256];
-extern GRIB1ParmTable parm_table_ecmwf_130[256];
-extern GRIB1ParmTable parm_table_ecmwf_131[256];
-extern GRIB1ParmTable parm_table_ecmwf_140[256];
-extern GRIB1ParmTable parm_table_ecmwf_150[256];
-extern GRIB1ParmTable parm_table_ecmwf_160[256];
-extern GRIB1ParmTable parm_table_ecmwf_170[256];
-extern GRIB1ParmTable parm_table_ecmwf_180[256];
-
-extern GRIB1ParmTable parm_table_athens[256];
-
-extern GRIB1ParmTable parm_table_cmc[256];
-
-extern GRIB1ParmTable parm_table_undefined[256];
-
 /*****************************************************************************
  * Choose_ParmTable() --
  *
@@ -123,7 +82,7 @@ extern GRIB1ParmTable parm_table_undefined[256];
  * NOTES
  *****************************************************************************
  */
-static GRIB1ParmTable *Choose_ParmTable (pdsG1Type *pdsMeta,
+static const GRIB1ParmTable *Choose_ParmTable (pdsG1Type *pdsMeta,
                                          unsigned short int center,
                                          unsigned short int subcenter)
 {
@@ -285,7 +244,7 @@ static void GRIB1_Table2LookUp (pdsG1Type *pdsMeta, const char **name,
                                 unsigned short int center,
                                 unsigned short int subcenter)
 {
-   GRIB1ParmTable *table; /* The parameter table choosen by the pdsMeta data */
+   const GRIB1ParmTable *table; /* The parameter table chosen by the pdsMeta data */
 
    table = Choose_ParmTable (pdsMeta, center, subcenter);
    if ((center == NMC) && (pdsMeta->mstrVersion == 129)
@@ -305,8 +264,6 @@ static void GRIB1_Table2LookUp (pdsG1Type *pdsMeta, const char **name,
 /*   printf ("%s %s %s\n", *name, *comment, *unit);*/
 }
 
-extern GRIB1SurfTable GRIB1Surface[256];
-
 /* Similar to metaname.c :: ParseLevelName() */
 static void GRIB1_Table3LookUp (pdsG1Type *pdsMeta, char **shortLevelName,
                                 char **longLevelName)
@@ -698,7 +655,17 @@ int GRIB1_Inventory (DataSource &fp, uInt4 gribLen, inventoryType *inv)
       errSprintf ("Ran out of data in PDS (GRIB1_Inventory)\n");
       return -1;
    }
+   if( sectLen < 3 )
+   {
+       errSprintf ("Invalid sectLen.\n");
+       return -1;
+   }
    pds = (uChar *) malloc (sectLen * sizeof (uChar));
+   if( pds == NULL )
+   {
+       errSprintf ("Ran out of memory.\n");
+       return -1;
+   }
    *pds = *temp;
    pds[1] = temp[1];
    pds[2] = temp[2];
@@ -724,11 +691,15 @@ int GRIB1_Inventory (DataSource &fp, uInt4 gribLen, inventoryType *inv)
    strcpy (inv->element, varName);
    inv->unitName = (char *) malloc ((1 + 2 + strlen (varUnit)) *
                                     sizeof (char));
-   sprintf (inv->unitName, "[%s]", varUnit);
+   snprintf (inv->unitName, (1 + 2 + strlen (varUnit)) *
+                                    sizeof (char), "[%s]", varUnit);
    inv->comment = (char *) malloc ((1 + strlen (varComment) +
                                     strlen (varUnit) + 2 + 1) *
                                    sizeof (char));
-   sprintf (inv->comment, "%s [%s]", varComment, varUnit);
+   snprintf (inv->comment, (1 + strlen (varComment) +
+                                    strlen (varUnit) + 2 + 1) *
+                                   sizeof (char),
+             "%s [%s]", varComment, varUnit);
 
    GRIB1_Table3LookUp (&(pdsMeta), &(inv->shortFstLevel),
                        &(inv->longFstLevel));
@@ -816,7 +787,7 @@ int GRIB1_RefTime (DataSource &fp, uInt4 gribLen, double *refTime)
  *  12/2003 AAT: adas data encoder seems to have # of vertical data = 1, but
  *        parameters of vertical data = 255, which doesn't make sense.
  *        Changed the error from "fatal" to a warning in debug mode.
- *   6/2004 AAT: Modified to allow "extended" lat/lon grids (ie stretched or
+ *   6/2004 AAT: Modified to allow "extended" lat/lon grids (i.e. stretched or
  *        stretched and rotated).
  *
  * NOTES
@@ -1383,7 +1354,7 @@ static int ReadGrib1Sect4 (uChar *bds, uInt4 gribLen, uInt4 *curLoc,
    uInt4 sectLen;       /* Length in bytes of the current section. */
    short int ESF;       /* Power of 2 scaling factor. */
    uInt4 uli_temp;      /* Used to store sInt4s (temporarily) */
-   double refVal;       /* The refrence value for the grid, also the minimum
+   double refVal;       /* The reference value for the grid, also the minimum
                          * value. */
    uChar numBits;       /* # of bits for a single element of data. */
    uChar numUnusedBit;  /* # of extra bits at end of record. */
@@ -1751,7 +1722,7 @@ int ReadGrib1Record (DataSource &fp, sChar f_unit, double **Grib_Data,
       return -1;
    }
 
-   /* Preceeding was in degrib2, next part is specific to GRIB1. */
+   /* Preceding was in degrib2, next part is specific to GRIB1. */
    curLoc = 8;
    if (ReadGrib1Sect1 (c_ipack + curLoc, gribLen, &curLoc, &(meta->pds1),
                        &f_gds, &gridID, &f_bms, &DSF, &(meta->center),
@@ -1830,16 +1801,23 @@ int ReadGrib1Record (DataSource &fp, sChar f_unit, double **Grib_Data,
    meta->unitName = (char *) realloc ((void *) (meta->unitName),
                                       (1 + 2 + strlen (varUnit)) *
                                       sizeof (char));
-   sprintf (meta->unitName, "[%s]", varUnit);
+   snprintf (meta->unitName,
+            (1 + 2 + strlen (varUnit)) *
+                                      sizeof (char),
+            "[%s]", varUnit);
    meta->comment = (char *) realloc ((void *) (meta->comment),
                                      (1 + strlen (varComment) +
                                       strlen (varUnit)
                                       + 2 + 1) * sizeof (char));
-   sprintf (meta->comment, "%s [%s]", varComment, varUnit);
+   snprintf (meta->comment,
+            (1 + strlen (varComment) +
+                                      strlen (varUnit)
+                                      + 2 + 1) * sizeof (char),
+            "%s [%s]", varComment, varUnit);
 
    if (ComputeUnit (meta->convert, meta->unitName, f_unit, &unitM, &unitB,
                     unitName) == 0) {
-      unitLen = strlen (unitName);
+      unitLen = static_cast<int>(strlen (unitName));
       meta->unitName = (char *) realloc ((void *) (meta->unitName),
                                          1 + unitLen * sizeof (char));
       strncpy (meta->unitName, unitName, unitLen);
@@ -1881,11 +1859,10 @@ int ReadGrib1Record (DataSource &fp, sChar f_unit, double **Grib_Data,
               "section 5 is missing\n");
       return 0;
    }
-   if (curLoc + 4 > gribLen) {
-      errSprintf ("Ran out of bytes looking for the end of the message.\n");
+   if (curLoc + 4 != gribLen) {
+      errSprintf ("Invalid number of bytes for the end of the message.\n");
       return -5;
    }
-   myAssert (curLoc + 4 == gribLen);
    memcpy (&li_temp, c_ipack + curLoc, 4);
    if (li_temp != 926365495L) {
       errSprintf ("Did not find the end of the message.\n");
diff --git a/frmts/grib/degrib18/degrib/degrib1.h b/frmts/grib/degrib18/degrib/degrib1.h
index c504f41..62be482 100644
--- a/frmts/grib/degrib18/degrib/degrib1.h
+++ b/frmts/grib/degrib18/degrib/degrib1.h
@@ -17,6 +17,49 @@ typedef struct {
    char f_twoPart;
 } GRIB1SurfTable;
 
+extern const GRIB1ParmTable parm_table_ncep_opn[256];
+extern const GRIB1ParmTable parm_table_ncep_reanal[256];
+extern const GRIB1ParmTable parm_table_ncep_tdl[256];
+extern const GRIB1ParmTable parm_table_ncep_mdl[256];
+extern const GRIB1ParmTable parm_table_omb[256];
+extern const GRIB1ParmTable parm_table_nceptab_129[256];
+extern const GRIB1ParmTable parm_table_nceptab_130[256];
+extern const GRIB1ParmTable parm_table_nceptab_131[256];
+
+extern const GRIB1ParmTable parm_table_nohrsc[256];
+
+extern const GRIB1ParmTable parm_table_cptec_254[256];
+
+extern const GRIB1ParmTable parm_table_afwa_000[256];
+extern const GRIB1ParmTable parm_table_afwa_001[256];
+extern const GRIB1ParmTable parm_table_afwa_002[256];
+extern const GRIB1ParmTable parm_table_afwa_003[256];
+extern const GRIB1ParmTable parm_table_afwa_010[256];
+extern const GRIB1ParmTable parm_table_afwa_011[256];
+
+extern const GRIB1ParmTable parm_table_dwd_002[256];
+extern const GRIB1ParmTable parm_table_dwd_201[256];
+extern const GRIB1ParmTable parm_table_dwd_202[256];
+extern const GRIB1ParmTable parm_table_dwd_203[256];
+
+extern const GRIB1ParmTable parm_table_ecmwf_128[256];
+extern const GRIB1ParmTable parm_table_ecmwf_129[256];
+extern const GRIB1ParmTable parm_table_ecmwf_130[256];
+extern const GRIB1ParmTable parm_table_ecmwf_131[256];
+extern const GRIB1ParmTable parm_table_ecmwf_140[256];
+extern const GRIB1ParmTable parm_table_ecmwf_150[256];
+extern const GRIB1ParmTable parm_table_ecmwf_160[256];
+extern const GRIB1ParmTable parm_table_ecmwf_170[256];
+extern const GRIB1ParmTable parm_table_ecmwf_180[256];
+
+extern const GRIB1ParmTable parm_table_athens[256];
+
+extern const GRIB1ParmTable parm_table_cmc[256];
+
+extern const GRIB1ParmTable parm_table_undefined[256];
+
+extern const GRIB1SurfTable GRIB1Surface[256];
+
 
 int GRIB1_Inventory (DataSource &fp, uInt4 gribLen, inventoryType * inv);
 
diff --git a/frmts/grib/degrib18/degrib/degrib2.cpp b/frmts/grib/degrib18/degrib/degrib2.cpp
index 2caf42a..faa643b 100644
--- a/frmts/grib/degrib18/degrib/degrib2.cpp
+++ b/frmts/grib/degrib18/degrib/degrib2.cpp
@@ -44,7 +44,7 @@
  * message in "expect2" bytes or 0 bytes from the start.  Returns -1 if it
  * can't find "GRIB", 1 if "GRIB" is not 0, "expect", or "expect2" bytes from
  * the start.
- *   It stores the bytes it reads (a max of "expect") upto but not including
+ *   It stores the bytes it reads (a max of "expect") up to but not including
  * the 'G' in "GRIB" in wmo.
  *
  *   After it finds section 0, it then parses the 16 bytes that make up
@@ -613,7 +613,7 @@ static int FindSectLen (char *c_ipack, sInt4 gribLen, sInt4 ns[8],
  *  12/2002 (TK,AC,TB,&MS): Code Review.
  *
  * NOTES
- * 1) Numbers not found in document were discused with Bob Glahn on 8/29/2002
+ * 1) Numbers not found in document were discussed with Bob Glahn on 8/29/2002
  * 2) Possible exceptions:
  *    template 3.120 could need ns[3] = 1600
  *    template 4.30 could need a different ns4.
@@ -761,7 +761,7 @@ void IS_Free (IS_dataType *is)
  *   9/2002 Arthur Taylor (MDL/RSIS): Created.
  *  11/2002 AAT: Updated.
  *  12/2002 (TK,AC,TB,&MS): Code Review.
- *   1/2003 AAT: It wasn't error coded 208, but rather 202 to look for.
+ *   1/2003 AAT: It was not error coded 208, but rather 202 to look for.
  *   3/2003 AAT: Modified handling of section 2 stuff (no loop)
  *   3/2003 AAT: Added ability to handle multiple grids in same message.
  *   4/2003 AAT: Added ability to call GRIB1 decoder for GRIB1 messages.
@@ -798,7 +798,7 @@ void IS_Free (IS_dataType *is)
  *    xmissp, and xmisss.  We don't embed because we don't know what to set
  *    xmissp or xmisss to.  Instead after we know the range, we choose a value
  *    and walk through the bitmap setting grib_Data appropriately.
- * 5a) iclean = 0;  This is because we do want the missing values embeded.
+ * 5a) iclean = 0;  This is because we do want the missing values embedded.
  *    that is we want the missing values to be place holders.
  * 6) f_endMsg is true if in the past we either completed reading a message,
  *    or we haven't read any messages.  In either case we need to read the
@@ -843,10 +843,10 @@ int ReadGrib2Record (DataSource &fp, sChar f_unit, double **Grib_Data,
                          * unless library is compiled a particular way. */
    sInt4 ibitmap;       /* 0 means no bitmap returned, otherwise 1. */
    float xmissp;        /* The primary missing value.  If iclean = 0, this
-                         * value is embeded in grid, otherwise it is the
+                         * value is embedded in grid, otherwise it is the
                          * value returned from the GRIB message. */
    float xmisss;        /* The secondary missing value.  If iclean = 0, this
-                         * value is embeded in grid, otherwise it is the
+                         * value is embedded in grid, otherwise it is the
                          * value returned from the GRIB message. */
    sInt4 jer[UNPK_NUM_ERRORS * 2]; /* Any Error codes along with their *
                                     * severity levels generated using the *
@@ -996,7 +996,7 @@ int ReadGrib2Record (DataSource &fp, sChar f_unit, double **Grib_Data,
             }
             /* Don't need to do the following, but we do in case code
              * changes. */
-            c_ipack = (char *) IS->ipack;
+            /*c_ipack = (char *) IS->ipack;*/
          }
       }
       IS->nd5 = nd5;
@@ -1066,15 +1066,15 @@ int ReadGrib2Record (DataSource &fp, sChar f_unit, double **Grib_Data,
                   IS->is[5], IS->ns[5], gribLen, xmissp, xmisss, simpVer)
        != 0) {
 #ifdef DEBUG
-      FILE *fp;
-      if ((fp = fopen ("dump.is0", "wt")) != NULL) {
+      FILE *l_fp;
+      if ((l_fp = fopen ("dump.is0", "wt")) != NULL) {
          for (i = 0; i < 8; i++) {
-            fprintf (fp, "---Section %d---\n", (int) i);
+            fprintf (l_fp, "---Section %d---\n", (int) i);
             for (j = 1; j <= IS->ns[i]; j++) {
-               fprintf (fp, "IS%d Item %d = %d\n", (int) i, (int) j, IS->is[i][j - 1]);
+               fprintf (l_fp, "IS%d Item %d = %d\n", (int) i, (int) j, IS->is[i][j - 1]);
             }
          }
-         fclose (fp);
+         fclose (l_fp);
       }
 #endif
       preErrSprintf ("Inside ReadGrib2Record.. Problems in MetaParse\n");
@@ -1102,7 +1102,7 @@ int ReadGrib2Record (DataSource &fp, sChar f_unit, double **Grib_Data,
 */
    if (ComputeUnit (meta->convert, meta->unitName, f_unit, &unitM, &unitB,
                     unitName) == 0) {
-      unitLen = strlen (unitName);
+      unitLen = static_cast<int>(strlen (unitName));
       meta->unitName = (char *) realloc ((void *) (meta->unitName),
                                          1 + unitLen * sizeof (char));
       strncpy (meta->unitName, unitName, unitLen);
diff --git a/frmts/grib/degrib18/degrib/engribapi.c b/frmts/grib/degrib18/degrib/engribapi.c
index a115a40..6576d21 100644
--- a/frmts/grib/degrib18/degrib/engribapi.c
+++ b/frmts/grib/degrib18/degrib/engribapi.c
@@ -297,10 +297,10 @@ void fillSect2 (enGribMeta *en, uChar *sec2, sInt4 lenSec2)
  * shapeEarth = [Code:3.2] shape of the Earth defined by GRIB2 (Output)
  *    factRad = Scale factor of radius of spherical Earth. (Output)
  *     valRad = Value of radius of spherical Earth (Output)
- *    factMaj = Scale factor of major axis of eliptical Earth. (Output)
- *     valMaj = Value of major axis of eliptical Earth (Output)
- *    factMin = Scale factor of minor axis of eliptical Earth. (Output)
- *     valMin = Value of minor axis of eliptical Earth (Output)
+ *    factMaj = Scale factor of major axis of elliptical Earth. (Output)
+ *     valMaj = Value of major axis of elliptical Earth (Output)
+ *    factMin = Scale factor of minor axis of elliptical Earth. (Output)
+ *     valMin = Value of minor axis of elliptical Earth (Output)
  *
  * RETURNS: void
  *
@@ -387,7 +387,7 @@ static void getShpEarth (double majEarth, double minEarth, sInt4 * shapeEarth,
  * [tmplNum=0]
  *      angle = rule 92.1.6 may not hold, in which case, angle != 0, and
  *              unit = angle/subdivision. Typically 0 (Input)
- *   subDivis = 0 or see angle explaination. (Input)
+ *   subDivis = 0 or see angle explanation. (Input)
  * [tmplNum=10,20,30]
  *    meshLat = Latitude where Dx and Dy are specified (Input)
  *  orientLon = Orientation of the grid (Input)
@@ -580,7 +580,7 @@ int fillSect3 (enGribMeta *en, uShort2 tmplNum, double majEarth,
 static int getCodedTime (uChar timeCode, double time, sInt4 *ans)
 {
    /* Following is a lookup table for unit conversion (see code table 4.4). */
-   static sInt4 unit2sec[] = {
+   static const sInt4 unit2sec[] = {
       60, 3600, 86400L, 0, 0,
       0, 0, 0, 0, 0,
       10800, 21600L, 43200L, 1
@@ -724,7 +724,7 @@ int fillSect4_0 (enGribMeta *en, uShort2 tmplNum, uChar cat, uChar subCat,
  *
  * RETURNS: int
  *    > 0 (length of section 4).
- *    -1 if not template 4.1, or fillSect4_0 wasn't already called.
+ *    -1 if not template 4.1, or fillSect4_0 was not already called.
  *
  *  4/2006 Arthur Taylor (MDL): Created.
  *
@@ -734,7 +734,7 @@ int fillSect4_0 (enGribMeta *en, uShort2 tmplNum, uChar cat, uChar subCat,
 int fillSect4_1 (enGribMeta *en, uShort2 tmplNum, uChar typeEnsemble,
                  uChar perturbNum, uChar numFcsts)
 {
-   /* ensemble tempate (1) */
+   /* Ensemble template (1) */
    if (tmplNum != 1) {
       /* This is specifically for template 4.1 */
       return -1;
@@ -763,7 +763,7 @@ int fillSect4_1 (enGribMeta *en, uShort2 tmplNum, uChar typeEnsemble,
  *
  * RETURNS: int
  *    > 0 (length of section 4).
- *    -1 if not template 4.2, or fillSect4_0 wasn't already called.
+ *    -1 if not template 4.2, or fillSect4_0 was not already called.
  *
  *  4/2006 Arthur Taylor (MDL): Created.
  *
@@ -811,7 +811,7 @@ int fillSect4_2 (enGribMeta *en, uShort2 tmplNum, uChar numFcsts,
  *
  * RETURNS: int
  *    > 0 (length of section 4).
- *    -1 if not template 4.5, or fillSect4_0 wasn't already called.
+ *    -1 if not template 4.5, or fillSect4_0 was not already called.
  *
  *  4/2006 Arthur Taylor (MDL): Created.
  *
@@ -872,7 +872,7 @@ int fillSect4_5 (enGribMeta *en, uShort2 tmplNum, uChar numFcsts,
  *
  * RETURNS: int
  *    > 0 (length of section 4).
- *    -1 if not template 4.8, or fillSect4_0 wasn't already called.
+ *    -1 if not template 4.8, or fillSect4_0 was not already called.
  *    -4 can only handle 1 and only 1 time interval
  *
  *  4/2006 Arthur Taylor (MDL): Created.
@@ -952,7 +952,7 @@ int fillSect4_8 (enGribMeta *en, uShort2 tmplNum, sInt4 endYear, int endMonth,
  *
  * RETURNS: int
  *    > 0 (length of section 4).
- *    -1 if not template 4.9, or fillSect4_0 wasn't already called.
+ *    -1 if not template 4.9, or fillSect4_0 was not already called.
  *    -4 can only handle 1 and only 1 time interval
  *
  *  4/2006 Arthur Taylor (MDL): Created.
@@ -1040,7 +1040,7 @@ int fillSect4_9 (enGribMeta *en, uShort2 tmplNum, uChar numFcsts,
  *
  * RETURNS: int
  *    > 0 (length of section 4).
- *    -1 if not template 4.9, or fillSect4_0 wasn't already called.
+ *    -1 if not template 4.9, or fillSect4_0 was not already called.
  *    -4 can only handle 1 and only 1 time interval
  *
  *  5/2006 Arthur Taylor (MDL): Created.
@@ -1111,7 +1111,7 @@ int fillSect4_10 (enGribMeta *en, uShort2 tmplNum, int percentile,
  *
  * RETURNS: int
  *    > 0 (length of section 4).
- *    -1 if not template 4.12, or fillSect4_0 wasn't already called.
+ *    -1 if not template 4.12, or fillSect4_0 was not already called.
  *    -4 can only handle 1 and only 1 time interval
  *
  *  4/2006 Arthur Taylor (MDL): Created.
diff --git a/frmts/grib/degrib18/degrib/filedatasource.cpp b/frmts/grib/degrib18/degrib/filedatasource.cpp
index a45f4fb..e06b0be 100644
--- a/frmts/grib/degrib18/degrib/filedatasource.cpp
+++ b/frmts/grib/degrib18/degrib/filedatasource.cpp
@@ -7,10 +7,10 @@ FileDataSource::FileDataSource(const char * fileName)
     fp = VSIFOpenL(fileName, "rb");
 }
 
-FileDataSource::FileDataSource(VSILFILE* fp)
+FileDataSource::FileDataSource(VSILFILE* fpIn)
 : closeFile(false)
 {
-    this->fp = fp;
+    this->fp = fpIn;
 }
 
 FileDataSource::~FileDataSource()
@@ -56,5 +56,5 @@ int FileDataSource::DataSourceFeof()
 
 long FileDataSource::DataSourceFtell()
 {
-    return VSIFTellL( fp );
+    return static_cast<long>(VSIFTellL( fp ));
 }
diff --git a/frmts/grib/degrib18/degrib/fileendian.cpp b/frmts/grib/degrib18/degrib/fileendian.cpp
index dfc4fdd..ec7cc71 100644
--- a/frmts/grib/degrib18/degrib/fileendian.cpp
+++ b/frmts/grib/degrib18/degrib/fileendian.cpp
@@ -330,7 +330,7 @@ int fileBitRead (void *Dst, size_t dstLen, uShort2 num_bits, FILE * fp,
                  uChar * gbuf, sChar * gbufLoc)
 {
    static uChar BitRay[] = { 0, 1, 3, 7, 15, 31, 63, 127, 255 };
-   register uChar buf_loc, buf, *ptr;
+   uChar buf_loc, buf, *ptr;
    uChar *dst = (uChar*)Dst;
    size_t num_bytes;
    uChar dst_loc;
diff --git a/frmts/grib/degrib18/degrib/grib1tab.cpp b/frmts/grib/degrib18/degrib/grib1tab.cpp
index 3b092d5..eaad4e6 100644
--- a/frmts/grib/degrib18/degrib/grib1tab.cpp
+++ b/frmts/grib/degrib18/degrib/grib1tab.cpp
@@ -21,7 +21,7 @@
  *****************************************************************************
  */
 /* *INDENT-OFF* */
-GRIB1SurfTable GRIB1Surface[256] = {
+const GRIB1SurfTable GRIB1Surface[256] = {
    /* 0 */ {"var0", "reserved", "-", 0},
    /* 1 */ {"SFC", "Ground or water surface", "-", 0},
    /* 2 */ {"CBL", "Cloud base level", "-", 0},
@@ -228,7 +228,7 @@ GRIB1SurfTable GRIB1Surface[256] = {
    /* 197 */ {"var197", "reserved", "-", 0},
    /* 198 */ {"var198", "reserved", "-", 0},
    /* 199 */ {"var199", "reserved", "-", 0},
-   /* 200 */ {"EATM", "entire atmosphere (considerd as a single layer)", "-",
+   /* 200 */ {"EATM", "entire atmosphere (considered as a single layer)", "-",
               0},
    /* 201 */ {"EOCN", "entire ocean (considered as a single layer)", "-", 0},
    /* 202 */ {"var202", "reserved", "-", 0},
@@ -305,7 +305,7 @@ GRIB1SurfTable GRIB1Surface[256] = {
 /* http://www.nco.ncep.noaa.gov/pmb/docs/on388/table2.html */
 /* Updated last on 5/24/2003 */
 /* *INDENT-OFF* */
-GRIB1ParmTable parm_table_ncep_opn[256] = {
+const GRIB1ParmTable parm_table_ncep_opn[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"PRES", "Pressure", "Pa", UC_NONE},
    /* 2 */ {"PRMSL", "Pressure reduced to MSL", "Pa", UC_NONE},
@@ -596,7 +596,7 @@ GRIB1ParmTable parm_table_ncep_opn[256] = {
 
 /* http://www.nco.ncep.noaa.gov/pmb/docs/on388/table2.html */
 /* Updated last on 5/24/2003 */
-GRIB1ParmTable parm_table_nceptab_129[256] = {
+const GRIB1ParmTable parm_table_nceptab_129[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"PRES", "Pressure", "Pa", UC_NONE},
    /* 2 */ {"PRMSL", "Pressure reduced to MSL", "Pa", UC_NONE},
@@ -870,7 +870,7 @@ GRIB1ParmTable parm_table_nceptab_129[256] = {
 
 /* http://www.nco.ncep.noaa.gov/pmb/docs/on388/table2.html */
 /* Updated last on 5/24/2003 */
-GRIB1ParmTable parm_table_nceptab_130[256] = {
+const GRIB1ParmTable parm_table_nceptab_130[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"PRES", "Pressure", "Pa", UC_NONE},
    /* 2 */ {"PRMSL", "Pressure reduced to MSL", "Pa", UC_NONE},
@@ -1162,7 +1162,7 @@ GRIB1ParmTable parm_table_nceptab_130[256] = {
 };
 
 /* Updated last on 9/8/2005 */
-GRIB1ParmTable parm_table_nceptab_131[256] = {
+const GRIB1ParmTable parm_table_nceptab_131[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"PRES", "Pressure", "Pa", UC_NONE},
    /* 2 */ {"PRMSL", "Pressure reduced to MSL", "Pa", UC_NONE},
@@ -1371,8 +1371,8 @@ GRIB1ParmTable parm_table_nceptab_131[256] = {
    /* 188 */ {"DRIP", "Rate of water dropping from canopy to gnd", "kg/m^2", UC_NONE},
    /* 189 */ {"LANDN", "Land-sea coverage (nearest neighbor)", "land=1,sea=0", UC_NONE},
    /* 190 */ {"HLCY", "Storm relative helicity", "m^2/s^2", UC_NONE},
-   /* 191 */ {"NLATN", "Latitude (nearest neigbhbor) (-90 to +90)", "deg", UC_NONE},
-   /* 192 */ {"ELONN", "East longitude (nearest neigbhbor) (0-360)", "deg", UC_NONE},
+   /* 191 */ {"NLATN", "Latitude (nearest neighbor) (-90 to +90)", "deg", UC_NONE},
+   /* 192 */ {"ELONN", "East longitude (nearest neighbor) (0-360)", "deg", UC_NONE},
    /* 193 */ {"var193", "undefined", "-", UC_NONE},
    /* 194 */ {"CPOFP", "Probability of frozen precipitation", "%", UC_NONE},
    /* 195 */ {"var195", "undefined", "-", UC_NONE},
@@ -1413,7 +1413,7 @@ GRIB1ParmTable parm_table_nceptab_131[256] = {
    /* 230 */ {"SMREF", "Transpiration stress-onset (soil moisture)", "fraction", UC_NONE},
    /* 231 */ {"SMDRY", "Direct evaporation cease (soil moisture)", "fraction", UC_NONE},
    /* 232 */ {"WVINC", "water vapor added by precip assimilation", "kg/m^2", UC_NONE},
-   /* 233 */ {"WCINC", "water condensate added by precip assimilaition", "kg/m^2", UC_NONE},
+   /* 233 */ {"WCINC", "water condensate added by precip assimilation", "kg/m^2", UC_NONE},
    /* 234 */ {"BGRUN", "Baseflow-groundwater runoff", "kg/m^2", UC_NONE},
    /* 235 */ {"SSRUN", "Storm surface runoff", "kg/m^2", UC_NONE},
    /* 236 */ {"var236", "undefined", "-", UC_NONE},
@@ -1443,7 +1443,7 @@ GRIB1ParmTable parm_table_nceptab_131[256] = {
 /* See: http://www.nohrsc.noaa.gov/technology/pdf/nohrsc_product_identifier.pdf */
 /* Updated last on 10/17/2005 */
 /* *INDENT-OFF* */
-GRIB1ParmTable parm_table_nohrsc[256] = {
+const GRIB1ParmTable parm_table_nohrsc[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"PRES", "Pressure", "Pa", UC_NONE},
    /* 2 */ {"PRMSL", "Pressure reduced to MSL", "Pa", UC_NONE},
@@ -1730,7 +1730,7 @@ GRIB1ParmTable parm_table_nohrsc[256] = {
  * Original subcenter=0 Reanalysis files had
  * 2.5x2.5 (144x73) lat-long grid or 192x94 Gaussian grid (PDS grid=255?)
  */
-GRIB1ParmTable parm_table_ncep_reanal[256] = {
+const GRIB1ParmTable parm_table_ncep_reanal[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"PRES", "Pressure", "Pa", UC_NONE},
    /* 2 */ {"PRMSL", "Pressure reduced to MSL", "Pa", UC_NONE},
@@ -1994,7 +1994,7 @@ GRIB1ParmTable parm_table_ncep_reanal[256] = {
    /* 255 */ {"var255", "undefined", "-", UC_NONE},
 };
 
-GRIB1ParmTable parm_table_ncep_tdl[256] = {
+const GRIB1ParmTable parm_table_ncep_tdl[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"PRES", "Pressure", "Pa", UC_NONE},
    /* 2 */ {"PRMSL", "Pressure reduced to MSL", "Pa", UC_NONE},
@@ -2262,7 +2262,7 @@ GRIB1ParmTable parm_table_ncep_tdl[256] = {
    /* 255 */ {"var255", "undefined", "-", UC_NONE}
 };
 
-GRIB1ParmTable parm_table_ncep_mdl[256] = {
+const GRIB1ParmTable parm_table_ncep_mdl[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"PRES", "Pressure", "Pa", UC_NONE},
    /* 2 */ {"PRMSL", "Pressure reduced to MSL", "Pa", UC_NONE},
@@ -2533,7 +2533,7 @@ GRIB1ParmTable parm_table_ncep_mdl[256] = {
  * 12/31/2001 added REV
  */
 
-GRIB1ParmTable parm_table_omb[256] = {
+const GRIB1ParmTable parm_table_omb[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"var1", "undefined", "-", UC_NONE},
    /* 2 */ {"GHz6", "6.6 GHz", "K", UC_NONE},
@@ -2804,7 +2804,7 @@ GRIB1ParmTable parm_table_omb[256] = {
  *****************************************************************************
  */
 
-GRIB1ParmTable parm_table_ecmwf_128[256] = {
+const GRIB1ParmTable parm_table_ecmwf_128[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"STRM", "Stream function", "m^2/s", UC_NONE},
    /* 2 */ {"VPOT", "Velocity potential", "m^2/s", UC_NONE},
@@ -3099,7 +3099,7 @@ GRIB1ParmTable parm_table_ecmwf_128[256] = {
    /* 255 */ {"-", "Indicates a missing value", "-", UC_NONE},
 };
 
-GRIB1ParmTable parm_table_ecmwf_129[256] = {
+const GRIB1ParmTable parm_table_ecmwf_129[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"var1", "undefined", "-", UC_NONE},
    /* 2 */ {"var2", "undefined", "-", UC_NONE},
@@ -3377,7 +3377,7 @@ GRIB1ParmTable parm_table_ecmwf_129[256] = {
    /* 255 */ {"var255", "undefined", "-", UC_NONE},
 };
 
-GRIB1ParmTable parm_table_ecmwf_130[256] = {
+const GRIB1ParmTable parm_table_ecmwf_130[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"var1", "undefined", "-", UC_NONE},
    /* 2 */ {"var2", "undefined", "-", UC_NONE},
@@ -3648,7 +3648,7 @@ GRIB1ParmTable parm_table_ecmwf_130[256] = {
    /* 255 */ {"var255", "undefined", "-", UC_NONE},
 };
 
-GRIB1ParmTable parm_table_ecmwf_131[256] = {
+const GRIB1ParmTable parm_table_ecmwf_131[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"var1", "undefined", "-", UC_NONE},
    /* 2 */ {"var2", "undefined", "-", UC_NONE},
@@ -3907,7 +3907,7 @@ GRIB1ParmTable parm_table_ecmwf_131[256] = {
    /* 255 */ {"var255", "undefined", "-", UC_NONE},
 };
 
-GRIB1ParmTable parm_table_ecmwf_140[256] = {
+const GRIB1ParmTable parm_table_ecmwf_140[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"var1", "undefined", "-", UC_NONE},
    /* 2 */ {"var2", "undefined", "-", UC_NONE},
@@ -4167,7 +4167,7 @@ GRIB1ParmTable parm_table_ecmwf_140[256] = {
    /* 255 */ {"var255", "undefined", "-", UC_NONE},
 };
 
-GRIB1ParmTable parm_table_ecmwf_150[256] = {
+const GRIB1ParmTable parm_table_ecmwf_150[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"var1", "undefined", "-", UC_NONE},
    /* 2 */ {"var2", "undefined", "-", UC_NONE},
@@ -4351,7 +4351,7 @@ GRIB1ParmTable parm_table_ecmwf_150[256] = {
    /* 177 */ {"var177", "undefined", "-", UC_NONE},
    /* 178 */ {"var178", "undefined", "-", UC_NONE},
    /* 179 */ {"var179", "undefined", "-", UC_NONE},
-   /* 180 */ {"var180", "Diagnosed SST eror", "C", UC_NONE},
+   /* 180 */ {"var180", "Diagnosed SST error", "C", UC_NONE},
    /* 181 */ {"var181", "Heat flux correction", "W/m^2", UC_NONE},
    /* 182 */ {"var182", "Observed SST", "C", UC_NONE},
    /* 183 */ {"var183", "Observed heat flux", "W/m^2", UC_NONE},
@@ -4429,7 +4429,7 @@ GRIB1ParmTable parm_table_ecmwf_150[256] = {
    /* 255 */ {"var255", "undefined", "-", UC_NONE},
 };
 
-GRIB1ParmTable parm_table_ecmwf_160[256] = {
+const GRIB1ParmTable parm_table_ecmwf_160[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"var1", "undefined", "-", UC_NONE},
    /* 2 */ {"var2", "undefined", "-", UC_NONE},
@@ -4697,7 +4697,7 @@ GRIB1ParmTable parm_table_ecmwf_160[256] = {
    /* 255 */ {"var255", "undefined", "-", UC_NONE},
 };
 
-GRIB1ParmTable parm_table_ecmwf_170[256] = {
+const GRIB1ParmTable parm_table_ecmwf_170[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"var1", "undefined", "-", UC_NONE},
    /* 2 */ {"var2", "undefined", "-", UC_NONE},
@@ -4958,7 +4958,7 @@ GRIB1ParmTable parm_table_ecmwf_170[256] = {
    /* 255 */ {"var255", "undefined", "-", UC_NONE},
 };
 
-GRIB1ParmTable parm_table_ecmwf_180[256] = {
+const GRIB1ParmTable parm_table_ecmwf_180[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"var1", "undefined", "-", UC_NONE},
    /* 2 */ {"var2", "undefined", "-", UC_NONE},
@@ -5229,7 +5229,7 @@ GRIB1ParmTable parm_table_ecmwf_180[256] = {
  * Helmut P. Frank, 30.08.2001
  */
 
-GRIB1ParmTable parm_table_dwd_002[256] = {
+const GRIB1ParmTable parm_table_dwd_002[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"PS", "pressure", "Pa", UC_NONE},
    /* 2 */ {"PS_msl", "pressure reduced to MSL", "Pa", UC_NONE},
@@ -5266,7 +5266,7 @@ GRIB1ParmTable parm_table_dwd_002[256] = {
    /* 31 */ {"WDIR", "Wind direction", "degree true", UC_NONE},
    /* 32 */ {"WIND", "Wind speed", "m/s", UC_NONE},
    /* 33 */ {"U", "u-component (zonal) of wind", "m/s", UC_NONE},
-   /* 34 */ {"V", "v-component (merdional) of wind", "m/s", UC_NONE},
+   /* 34 */ {"V", "v-component (meridional) of wind", "m/s", UC_NONE},
    /* 35 */ {"STRM", "Stream function", "m^2/s", UC_NONE},
    /* 36 */ {"VPOT", "Velocity potential", "m^2/s", UC_NONE},
    /* 37 */ {"MNTSF", "Montgomery stream function", "m^2/s^2", UC_NONE},
@@ -5505,7 +5505,7 @@ GRIB1ParmTable parm_table_dwd_002[256] = {
  * Helmut P. Frank, 30.08.2001
  */
 
-GRIB1ParmTable parm_table_dwd_201[256] = {
+const GRIB1ParmTable parm_table_dwd_201[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"DSWRF", "Downward shortwave radiation flux", "W/m^2", UC_NONE},
    /* 2 */ {"USWRF", "Upward short wave radiation flux", "W/m^2", UC_NONE},
@@ -5867,13 +5867,13 @@ GRIB1ParmTable parm_table_dwd_201[256] = {
  * Helmut P. Frank, 30.08.2001
  */
 
-GRIB1ParmTable parm_table_dwd_202[256] = {
+const GRIB1ParmTable parm_table_dwd_202[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"Seeg_peak", "jonswap parameter fm", "1/s", UC_NONE},
    /* 2 */ {"Seeg_alpha", "jonswap parameter alpha", "1", UC_NONE},
    /* 3 */ {"Seeg_gamma", "jonswap parameter gamma", "1", UC_NONE},
    /* 4 */ {"Seeg_dir", "Seegang direction", "degree true", UC_NONE},
-   /* 5 */ {"Seeg_energ", "Seegang energy densitiy", "(m^2)(s^2)", UC_NONE},
+   /* 5 */ {"Seeg_energ", "Seegang energy density", "(m^2)(s^2)", UC_NONE},
    /* 6 */ {"Seeg_icemk", "Seegang ice mask", "1", UC_NONE},
    /* 7 */ {"peak_p_sw", "peak period of swell", "s", UC_NONE},
    /* 8 */ {"peak_p_ww", "peak period of wind waves", "s", UC_NONE},
@@ -6173,7 +6173,7 @@ GRIB1ParmTable parm_table_dwd_202[256] = {
  * Helmut P. Frank, 30.08.2001
  */
 
-GRIB1ParmTable parm_table_dwd_203[256] = {
+const GRIB1ParmTable parm_table_dwd_203[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"pressure", "pressure", "hPa", UC_NONE},
    /* 2 */ {"geopot_h", "geopotential height", "10 * gpm", UC_NONE},
@@ -6240,7 +6240,7 @@ GRIB1ParmTable parm_table_dwd_203[256] = {
    /* 56 */ {"min_temp", "minimum temperature", "C", UC_NONE},
    /* 57 */ {"var57", "undefined", "-", UC_NONE},
    /* 58 */ {"clo", "value of isolation of clothes", "1", UC_NONE},
-   /* 59 */ {"pmva", "predected mean vote (angepasst)", "1", UC_NONE},
+   /* 59 */ {"pmva", "predicted mean vote (angepasst)", "1", UC_NONE},
    /* 60 */ {"feeled_t", "feeled temperature", "C", UC_NONE},
    /* 61 */ {"sea_temper", "sea temperature", "C", UC_NONE},
    /* 62 */ {"var62", "undefined", "-", UC_NONE},
@@ -6499,7 +6499,7 @@ GRIB1ParmTable parm_table_dwd_203[256] = {
  *****************************************************************************
  */
 
-GRIB1ParmTable parm_table_cptec_254[256] = {
+const GRIB1ParmTable parm_table_cptec_254[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"PRES", "Pressure", "hPa", UC_NONE},
    /* 2 */ {"psnm", "Pressure reduced to MSL", "hPa", UC_NONE},
@@ -6776,7 +6776,7 @@ GRIB1ParmTable parm_table_cptec_254[256] = {
 /* AFWA center = 57, subcenter = 0 */
 /* Updated last on 7/22/2004 */
 /* *INDENT-OFF* */
-GRIB1ParmTable parm_table_afwa_000[256] = {
+const GRIB1ParmTable parm_table_afwa_000[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"PRES", "Pressure", "Pa", UC_NONE},
    /* 2 */ {"PRMSL", "Pressure reduced to MSL", "Pa", UC_NONE},
@@ -7075,7 +7075,7 @@ GRIB1ParmTable parm_table_afwa_000[256] = {
 /* AFWA center = 57, subcenter = 1 */
 /* Updated last on 7/22/2004 */
 /* *INDENT-OFF* */
-GRIB1ParmTable parm_table_afwa_001[256] = {
+const GRIB1ParmTable parm_table_afwa_001[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"PRES", "Pressure", "Pa", UC_NONE},
    /* 2 */ {"PRMSL", "Pressure reduced to MSL", "Pa", UC_NONE},
@@ -7369,7 +7369,7 @@ GRIB1ParmTable parm_table_afwa_001[256] = {
 /* AFWA center = 57, subcenter = 2 */
 /* Updated last on 7/22/2004 */
 /* *INDENT-OFF* */
-GRIB1ParmTable parm_table_afwa_002[256] = {
+const GRIB1ParmTable parm_table_afwa_002[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"PRES", "Pressure", "Pa", UC_NONE},
    /* 2 */ {"PRMSL", "Pressure reduced to MSL", "Pa", UC_NONE},
@@ -7677,7 +7677,7 @@ GRIB1ParmTable parm_table_afwa_002[256] = {
 /* AFWA center = 57, subcenter = 3 */
 /* Updated last on 7/22/2004 */
 /* *INDENT-OFF* */
-GRIB1ParmTable parm_table_afwa_003[256] = {
+const GRIB1ParmTable parm_table_afwa_003[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"PRES", "Pressure", "Pa", UC_NONE},
    /* 2 */ {"PRMSL", "Pressure reduced to MSL", "Pa", UC_NONE},
@@ -7952,7 +7952,7 @@ GRIB1ParmTable parm_table_afwa_003[256] = {
 /* AFWA center = 57, subcenter = 10 */
 /* Updated last on 7/30/2004 */
 /* *INDENT-OFF* */
-GRIB1ParmTable parm_table_afwa_010[256] = {
+const GRIB1ParmTable parm_table_afwa_010[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"PRES", "Pressure", "Pa", UC_NONE},
    /* 2 */ {"PRMSL", "Pressure reduced to MSL", "Pa", UC_NONE},
@@ -8114,14 +8114,15 @@ GRIB1ParmTable parm_table_afwa_010[256] = {
    /* 147 */ {"MXABH", "Max Absolute Humidity", "g/m^3", UC_NONE},
    /* 148 */ {"MNABH", "Min Absolute Humidity", "g/m^3", UC_NONE},
    /* 149 */ {"MNPREC", "Min Precipitation", "mm", UC_NONE},
-   /* 150 */ {"NEWND", "NE Wind Direction Occurance", "%", UC_NONE},
-   /* 151 */ {"EWND", "E Wind Direction Occurance", "%", UC_NONE},
-   /* 152 */ {"SEWND", "SE Wind Direction Occurance", "%", UC_NONE},
-   /* 153 */ {"SWND", "S Wind Direction Occurance", "%", UC_NONE},
-   /* 154 */ {"SWWND", "SW Wind Direction Occurance", "%", UC_NONE},
-   /* 155 */ {"WWND", "W Wind Direction Occurance", "%", UC_NONE},
-   /* 156 */ {"NWWND", "NW Wind Direction Occurance", "%", UC_NONE},
-   /* 157 */ {"NWND", "N Wind Direction Occurance", "%", UC_NONE},
+   /* TODO: Spelling. */
+   /* 150 */ {"NEWND", "NE Wind Direction Occurrence", "%", UC_NONE},
+   /* 151 */ {"EWND", "E Wind Direction Occurrence", "%", UC_NONE},
+   /* 152 */ {"SEWND", "SE Wind Direction Occurrence", "%", UC_NONE},
+   /* 153 */ {"SWND", "S Wind Direction Occurrence", "%", UC_NONE},
+   /* 154 */ {"SWWND", "SW Wind Direction Occurrence", "%", UC_NONE},
+   /* 155 */ {"WWND", "W Wind Direction Occurrence", "%", UC_NONE},
+   /* 156 */ {"NWWND", "NW Wind Direction Occurrence", "%", UC_NONE},
+   /* 157 */ {"NWND", "N Wind Direction Occurrence", "%", UC_NONE},
    /* 158 */ {"NEWSP", "NE Wind Speed", "m/s", UC_NONE},
    /* 159 */ {"EWSP", "E Wind Speed", "m/s", UC_NONE},
    /* 160 */ {"SEWSP", "SE Wind Speed", "m/s", UC_NONE},
@@ -8236,7 +8237,7 @@ GRIB1ParmTable parm_table_afwa_010[256] = {
 /* AFWA center = 57, subcenter = 11 */
 /* Updated last on 7/30/2004 */
 /* *INDENT-OFF* */
-GRIB1ParmTable parm_table_afwa_011[256] = {
+const GRIB1ParmTable parm_table_afwa_011[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"PRES", "Pressure", "Pa", UC_NONE},
    /* 2 */ {"PRMSL", "Pressure reduced to MSL", "Pa", UC_NONE},
@@ -8513,7 +8514,7 @@ GRIB1ParmTable parm_table_afwa_011[256] = {
 /* athens grid */
 /* Updated last on 3/13/2006 */
 /* *INDENT-OFF* */
-GRIB1ParmTable parm_table_athens[256] = {
+const GRIB1ParmTable parm_table_athens[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"PRES", "Pressure", "Pa", UC_NONE},
    /* 2 */ {"PRMSL", "Pressure reduced to MSL", "Pa", UC_NONE},
@@ -8790,7 +8791,7 @@ GRIB1ParmTable parm_table_athens[256] = {
  */
 /* Updated last on 11/13/2006 */
 /* *INDENT-OFF* */
-GRIB1ParmTable parm_table_cmc[256] = {
+const GRIB1ParmTable parm_table_cmc[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"PRES", "Pressure", "Pa", UC_NONE},
    /* 2 */ {"PRMSL", "Pressure reduced to MSL", "Pa", UC_NONE},
@@ -9064,7 +9065,7 @@ GRIB1ParmTable parm_table_cmc[256] = {
 /* UNDEFINED GRID */
 /* Updated last on 7/30/2004 */
 /* *INDENT-OFF* */
-GRIB1ParmTable parm_table_undefined[256] = {
+const GRIB1ParmTable parm_table_undefined[256] = {
    /* 0 */ {"var0", "undefined", "-", UC_NONE},
    /* 1 */ {"PRES", "Pressure", "Pa", UC_NONE},
    /* 2 */ {"PRMSL", "Pressure reduced to MSL", "Pa", UC_NONE},
diff --git a/frmts/grib/degrib18/degrib/grib2api.c b/frmts/grib/degrib18/degrib/grib2api.c
index 48a69c4..7c53dd9 100644
--- a/frmts/grib/degrib18/degrib/grib2api.c
+++ b/frmts/grib/degrib18/degrib/grib2api.c
@@ -63,7 +63,7 @@
  *
  * PURPOSE
  *   Unpack the local use data assuming that it was packed using the MDL
- * encoder.  This assumes "local" starts at octet 6 (ie skipping over the
+ * encoder.  This assumes "local" starts at octet 6 (i.e. skipping over the
  * length and section ID octets)
  *
  *   In Section 2, GRIB2 provides for local use data.  The MDL encoder packs
@@ -185,7 +185,7 @@ static int mdl_LocalUnpack (unsigned char *local, sInt4 locallen,
             memBitRead (&uli_temp, sizeof (sInt4), local, numBits,
                         &bufLoc, &numUsed);
             local += numUsed;
-            BytesUsed += numUsed;
+            BytesUsed += (int) numUsed;
             rdat[curIndex] = (refVal + uli_temp) * recScale10;
             curIndex++;
          }
@@ -206,7 +206,7 @@ static int mdl_LocalUnpack (unsigned char *local, sInt4 locallen,
             memBitRead (&uli_temp, sizeof (sInt4), local, numBits,
                         &bufLoc, &numUsed);
             local += numUsed;
-            BytesUsed += numUsed;
+            BytesUsed += (int) numUsed;
             idat[curIndex] = (refVal + uli_temp) * recScale10;
             curIndex++;
          }
@@ -335,7 +335,7 @@ static int fillOutSectLen (unsigned char *c_ipack, int lenCpack,
  *         bmap = bitmap from NCEPs routines. (Input)
  * f_ignoreScan = Flag to ignore the attempt at changing the scan (Input)
  *         scan = The scan orientation of fld/bmap/iain/ib (Input/Output)
- *       nx, ny = The dimmensions of the grid. (Input)
+ *       nx, ny = The dimensions of the grid. (Input)
  *       iclean = 1 means the user wants the unpacked data returned without
  *                missing values in it. 0 means embed the missing values. (In)
  *       xmissp = The primary missing value to use if iclean = 0. (Input).
@@ -440,7 +440,7 @@ static int TransferInt (float * fld, sInt4 ngrdpts, sInt4 ibitmap,
  *         bmap = bitmap from NCEPs routines. (Input)
  *         scan = The scan orientation of fld/bmap/iain/ib (Input/Output)
  * f_ignoreScan = Flag to ignore the attempt at changing the scan (Input)
- *       nx, ny = The dimmensions of the grid. (Input)
+ *       nx, ny = The dimensions of the grid. (Input)
  *       iclean = 1 means the user wants the unpacked data returned without
  *                missing values in it. 0 means embed the missing values. (In)
  *       xmissp = The primary missing value to use if iclean = 0. (Input).
@@ -610,7 +610,7 @@ Routine g2_addlocal can be used to add a Local Use Section ( Section 2 ).
 Note that this section is optional and need not appear in a GRIB2 message.
 
 Function g2_addgrid is used to encode a grid definition into Section 3.
-This grid definition defines the geometry of the the data values in the
+This grid definition defines the geometry of the data values in the
 fields that follow it.  g2_addgrid can be called again to change the grid
 definition describing subsequent data fields.
 
@@ -696,14 +696,14 @@ is required for each GRIB2 message.
  *                                 Request for an invalid subgrid
  *                                 Problems unpacking the data.
  *                                 problems expanding the data.
- *                                 Calling dimmensions were too small.
+ *                                 Calling dimensions were too small.
  * ker=2 jer[1,0]=100  jer[1,1]=2: Error unpacking section 1.
  * ker=3 jer[2,0]=200  jer[2,1]=2: Error unpacking section 2.
  * ker=4 jer[3,0]=300  jer[3,1]=2: Error unpacking section 3.
  * ker=5 jer[4,0]=400  jer[4,1]=2: Error unpacking section 4.
  * ker=6 jer[5,0]=500  jer[5,1]=2: Error unpacking section 5.
  *                                 Data Template not implemented.
- *                                 Durring Transfer, nx * ny != ngrdpts.
+ *                                 During Transfer, nx * ny != ngrdpts.
  * ker=7 jer[6,0]=600  jer[6,1]=2: Error unpacking section 6.
  * ker=8 jer[7,0]=700  jer[7,1]=2: Error unpacking section 7.
  * ker=9 jer[8,0]=2001 jer[8,1]=2: nd2x3 is not large enough.
@@ -740,6 +740,7 @@ is required for each GRIB2 message.
  * gfld->num_coord = number of values in array gfld->coord_list[].
  *****************************************************************************
  */
+static
 void unpk_g2ncep (CPL_UNUSED sInt4 * kfildo, float * ain, sInt4 * iain, sInt4 * nd2x3,
                   sInt4 * idat, sInt4 * nidat, float * rdat, sInt4 * nrdat,
                   sInt4 * is0, CPL_UNUSED sInt4 * ns0, sInt4 * is1, CPL_UNUSED sInt4 * ns1,
@@ -870,7 +871,7 @@ void unpk_g2ncep (CPL_UNUSED sInt4 * kfildo, float * ain, sInt4 * iain, sInt4 *
       g2_free (gfld);
       return;
    }
-   /* Check if data wasn't unpacked. */
+   /* Check if data was not unpacked. */
    if (!gfld->unpacked) {
       jer[0 + *ndjer] = 2;
       *kjer = 1;
@@ -1355,7 +1356,7 @@ static void clear (float * ain, sInt4 * iain, sInt4 * nd2x3, sInt4 * idat,
  * Arthur Taylor / MDL
  *
  * PURPOSE
- *   This is so we can copy upto 4 bytes from a big endian 4 byte int data
+ *   This is so we can copy up to 4 bytes from a big endian 4 byte int data
  * stream.
  *
  *   The reason this is needed is because the GRIB2 API required the GRIB2
@@ -1746,6 +1747,7 @@ void unpk_grib2 (sInt4 * kfildo, float * ain, sInt4 * iain, sInt4 * nd2x3,
 /* Not sure I need this... It is intended to provide a way to call it from
  * FORTRAN, but I'm not sure it is needed. */
 /* gcc has two __ if there is one _ in the procedure name. */
+#ifndef GDAL_COMPILATION
 void unpk_grib2__ (sInt4 * kfildo, float * ain, sInt4 * iain,
                    sInt4 * nd2x3, sInt4 * idat, sInt4 * nidat, float * rdat,
                    sInt4 * nrdat, sInt4 * is0, sInt4 * ns0, sInt4 * is1,
@@ -1762,6 +1764,7 @@ void unpk_grib2__ (sInt4 * kfildo, float * ain, sInt4 * iain,
                is7, ns7, ib, ibitmap, ipack, nd5, xmissp, xmisss, inew,
                iclean, l3264b, iendpk, jer, ndjer, kjer);
 }
+#endif
 
 /*****************************************************************************
  * C_pkGrib2() --
diff --git a/frmts/grib/degrib18/degrib/inventory.cpp b/frmts/grib/degrib18/degrib/inventory.cpp
index 950c639..841ee36 100644
--- a/frmts/grib/degrib18/degrib/inventory.cpp
+++ b/frmts/grib/degrib18/degrib/inventory.cpp
@@ -83,7 +83,7 @@ void GRIB2InventoryFree (inventoryType *inv)
  *
  * PURPOSE
  *   Prints to standard out, an inventory of the file, assuming one has an
- * array of invenories of single grib messages.
+ * array of inventories of single GRIB messages.
  *
  * ARGUMENTS
  *    Inv = Pointer to an Array of inventories to print. (Input)
@@ -257,9 +257,20 @@ static int GRIB2SectToBuffer (DataSource &fp,
       }
       return -1;
    }
+   if( *secLen < sizeof(sInt4) )
+   {
+       errSprintf ("ERROR: Wrong secLen in GRIB2SectToBuffer\n");
+       return -1;
+   }
    if (*buffLen < *secLen) {
+      char* buffnew = (char *) realloc ((void *) *buff, *secLen * sizeof (char));
+      if( buffnew == NULL )
+      {
+           errSprintf ("ERROR: Ran out of memory in GRIB2SectToBuffer\n");
+           return -1;
+      }
       *buffLen = *secLen;
-      *buff = (char *) realloc ((void *) *buff, *buffLen * sizeof (char));
+      *buff = buffnew;
       buffer = *buff;
    }
 
@@ -275,7 +286,7 @@ static int GRIB2SectToBuffer (DataSource &fp,
    if (*sect == -1) {
       *sect = buffer[5 - 5];
    } else if (buffer[5 - 5] != *sect) {
-      errSprintf ("ERROR: Section %d misslabeled\n", *sect);
+      errSprintf ("ERROR: Section %d mislabeled\n", *sect);
       return -2;
    }
    return 0;
@@ -341,17 +352,17 @@ static int GRIB2SectJump (DataSource &fp,
    if (*sect == -1) {
       *sect = sectNum;
    } else if (sectNum != *sect) {
-      errSprintf ("ERROR: Section %d misslabeled\n", *sect);
-      return -2;
+       errSprintf ("ERROR: Section %d mislabeled\n", *sect);
+       return -2;
    }
-   /* Since fseek does not give an error if we jump outside the file, we test 
+   /* Since fseek does not give an error if we jump outside the file, we test
     * it by using fgetc / ungetc. */
    fp.DataSourceFseek (*secLen - 5, SEEK_CUR);
    if ((c = fp.DataSourceFgetc()) == EOF) {
-      errSprintf ("ERROR: Ran out of file in Section %d\n", *sect);
-      return -1;
+       errSprintf ("ERROR: Ran out of file in Section %d\n", *sect);
+       return -1;
    } else {
-		 fp.DataSourceUngetc(c);
+       fp.DataSourceUngetc(c);
    }
    return 0;
 }
@@ -420,12 +431,12 @@ static int GRIB2Inventory2to7 (sChar sectNum, DataSource &fp, sInt4 gribLen,
    double fstSurfValue; /* Value of first fixed surface. */
    sInt4 value;         /* The scaled value from GRIB2 file. */
    sChar factor;        /* The scaled factor from GRIB2 file */
-   sChar scale;         /* Surface scale as opposed to probility factor. */
+   sChar scale;         /* Surface scale as opposed to probability factor. */
    uChar sndSurfType;   /* Type of the second fixed surface. */
    double sndSurfValue; /* Value of second fixed surface. */
    sChar f_sndValue;    /* flag if SndValue is valid. */
    uChar timeRangeUnit;
-   sInt4 lenTime;       /* Used by parseTime to tell difference betweeen 8hr
+   sInt4 lenTime;       /* Used by parseTime to tell difference between 8hr
                          * average and 1hr average ozone. */
    uChar genID;         /* The Generating process ID (used for GFS MOS) */
    uChar probType;      /* The probability type */
@@ -444,7 +455,7 @@ static int GRIB2Inventory2to7 (sChar sectNum, DataSource &fp, sInt4 gribLen,
          return -6;
       }
       if ((sectNum != 2) && (sectNum != 3)) {
-         errSprintf ("ERROR: Section 2 or 3 misslabeled\n");
+         errSprintf ("ERROR: Section 2 or 3 mislabeled\n");
          return -5;
       } else if (sectNum == 2) {
          /* Jump past section 3. */
@@ -628,26 +639,27 @@ enum { GS4_ANALYSIS, GS4_ENSEMBLE, GS4_DERIVED, GS4_PROBABIL_PNT = 5,
    /* Try to convert lenTime to hourly. */
    if (timeRangeUnit == 0) {
       lenTime = (sInt4) (lenTime / 60.);
-      timeRangeUnit = 1;
+      /*timeRangeUnit = 1;*/
    } else if (timeRangeUnit == 1) {
    } else if (timeRangeUnit == 2) {
       lenTime = lenTime * 24;
-      timeRangeUnit = 1;
+      /*timeRangeUnit = 1;*/
    } else if (timeRangeUnit == 10) {
       lenTime = lenTime * 3;
-      timeRangeUnit = 1;
+      /*timeRangeUnit = 1;*/
    } else if (timeRangeUnit == 11) {
       lenTime = lenTime * 6;
-      timeRangeUnit = 1;
+      /*timeRangeUnit = 1;*/
    } else if (timeRangeUnit == 12) {
       lenTime = lenTime * 12;
-      timeRangeUnit = 1;
+      /*timeRangeUnit = 1;*/
    } else if (timeRangeUnit == 13) {
       lenTime = (sInt4) (lenTime / 3600.);
-      timeRangeUnit = 1;
+      /*timeRangeUnit = 1;*/
    } else {
       printf ("Can't handle this timeRangeUnit\n");
-      myAssert (timeRangeUnit == 1);
+      //myAssert (timeRangeUnit == 1);
+      return -8;
    }
    if (lenTime == GRIB2MISSING_s4) {
       lenTime = 0;
@@ -789,7 +801,7 @@ enum { GS4_ANALYSIS, GS4_ENSEMBLE, GS4_DERIVED, GS4_PROBABIL_PNT = 5,
  *   9/2002 Arthur Taylor (MDL/RSIS): Created.
  *  11/2002 AAT: Revised.
  *  12/2002 (TK,AC,TB,&MS): Code Review.
- *   3/2003 AAT: Corrected some satelite type mistakes.
+ *   3/2003 AAT: Corrected some satellite type mistakes.
  *   3/2003 AAT: Implemented multiple grid inventories in the same GRIB2
  *          message.
  *   4/2003 AAT: Started adding GRIB1 support
@@ -801,7 +813,7 @@ enum { GS4_ANALYSIS, GS4_ENSEMBLE, GS4_DERIVED, GS4_PROBABIL_PNT = 5,
  *          after we know we have a GRIB file, we don't want "trailing" bytes
  *          to break the program.
  *   8/2003 AAT: switched fileLen to only be computed for an error message.
- *   8/2003 AAT: curTot no longer serves a purpse.
+ *   8/2003 AAT: curTot no longer serves a purpose.
  *   5/2004 AAT: Added a check for section number 2..8 for the repeated
  *          section (otherwise error)
  *  10/2004 AAT: Added ability to inventory TDLP records.
@@ -901,7 +913,7 @@ int GRIB2Inventory (DataSource &fp, inventoryType **Inv, uInt4 *LenInv,
             free (msg);
             /* find out how big the file is. */
             fp.DataSourceFseek (0L, SEEK_END);
-            fileLen = fp.DataSourceFtell();
+            fileLen = static_cast<int>(fp.DataSourceFtell());
             /* fseek (fp, 0L, SEEK_SET); */
             printf ("There were %d trailing bytes in the file.\n",
                     fileLen - offset);
@@ -1133,7 +1145,7 @@ int GRIB2RefTime (char *filename, double *refTime)
             free (msg);
             /* find out how big the file is. */
             fp.DataSourceFseek (0L, SEEK_END);
-            fileLen = fp.DataSourceFtell();
+            fileLen = static_cast<int>(fp.DataSourceFtell());
             /* fseek (fp, 0L, SEEK_SET); */
             printf ("There were %d trailing bytes in the file.\n",
                     fileLen - offset);
diff --git a/frmts/grib/degrib18/degrib/memendian.c b/frmts/grib/degrib18/degrib/memendian.c
index 1fe0ba8..b1f4602 100644
--- a/frmts/grib/degrib18/degrib/memendian.c
+++ b/frmts/grib/degrib18/degrib/memendian.c
@@ -194,7 +194,7 @@ void *revmemcpyRay (void *Dst, void *Src, const size_t elem_size,
  *
  * NOTES
  * 1) Assumes binary bit stream is "big endian". Resulting in no byte
- *    boundaries ie 00100110101101 => 001001 | 10101101
+ *    boundaries i.e. 00100110101101 => 001001 | 10101101
  *****************************************************************************
  */
 char memBitRead (void *Dst, size_t dstLen, void *Src, size_t numBits,
@@ -329,7 +329,7 @@ char memBitRead (void *Dst, size_t dstLen, void *Src, size_t numBits,
  *
  * NOTES
  * 1) Assumes binary bit stream should be "big endian". Resulting in no byte
- *    boundaries ie 00100110101101 => 001001 | 1010110
+ *    boundaries i.e. 00100110101101 => 001001 | 1010110
  * 2) Assumes that Dst is already zero'ed out.
  *****************************************************************************
  */
diff --git a/frmts/grib/degrib18/degrib/memorydatasource.cpp b/frmts/grib/degrib18/degrib/memorydatasource.cpp
index 7b21bca..b3f5668 100644
--- a/frmts/grib/degrib18/degrib/memorydatasource.cpp
+++ b/frmts/grib/degrib18/degrib/memorydatasource.cpp
@@ -25,7 +25,7 @@ size_t MemoryDataSource::DataSourceFread(void* lpBuf, size_t size, size_t count)
 		eof = false; // feof also "resets" after a good read
 
 	memcpy(lpBuf, memoryBlock + seekPos, size * count);
-	seekPos += size * count;
+	seekPos += static_cast<long>(size * count);
 
 	return count;
 
diff --git a/frmts/grib/degrib18/degrib/meta.h b/frmts/grib/degrib18/degrib/meta.h
index d9a3f6e..d49cb7b 100644
--- a/frmts/grib/degrib18/degrib/meta.h
+++ b/frmts/grib/degrib18/degrib/meta.h
@@ -89,7 +89,7 @@ typedef struct {
    uChar intens[NUM_UGLY_WORD]; /* (see WxIntens) */
    uChar vis[NUM_UGLY_WORD]; /* 255 no vis, otherwise in units of 1/32 SM
                             * so 6SM -> 192. P6SM -> 224 */
-   uChar f_or[NUM_UGLY_WORD]; /* true if OR, or MX was a hazzard. */
+   uChar f_or[NUM_UGLY_WORD]; /* true if OR, or MX was a hazard. */
    uChar f_priority[NUM_UGLY_WORD]; /* 0 if normal,
                             * 1 if 'include unconditional'
                             * 2 if 'high priority' */
@@ -101,7 +101,7 @@ typedef struct {
                             * temporarily 3 (invalid and used). */
    sInt4 validIndex;    /* Which index this is, counting only used
                             * valid indexes.  If it is not used it is -1 */
-   char *english[NUM_UGLY_WORD]; /* The english translation of ugly string. */
+   char *english[NUM_UGLY_WORD]; /* The English translation of ugly string. */
    uChar wx_inten[NUM_UGLY_WORD]; /* A code to represent the wx and
                               intensity for an "ugly word". */
    sInt4 HazCode[NUM_UGLY_WORD]; /* A code to represent all the attributes. */
@@ -116,7 +116,7 @@ typedef struct {
    int maxLen;               /* Max Length of all of the "ugly strings"
                               * It includes 1 for the \0 character. */
    UglyStringType *ugly;     /* The parsed Ugly string. */
-   int maxEng[NUM_UGLY_WORD]; /* Max length of english phrases for all ugly
+   int maxEng[NUM_UGLY_WORD]; /* Max length of English phrases for all ugly
                                * word number X. */
 } sect2_WxType;
 
@@ -409,7 +409,7 @@ typedef struct {
    uChar center;             /* For lambert and polar stereographic, answers:
                                 (south/north?) and (bi-polar?) */
    uChar scan;               /* describes how the grid was traversed when it
-                                was stored. (ie top/down left/right etc.)
+                                was stored. (i.e. top/down left/right etc.)
                                 Internally we use 0100. (start lower left) */
    double lat2, lon2;        /* lat,lon position of last grid point.
                                 (0 if unused) */
@@ -442,7 +442,7 @@ enum { GS5_SIMPLE = 0, GS5_CMPLX = 2, GS5_CMPLXSEC = 3, GS5_JPEG2000 = 40,
 };
 typedef struct {
    sInt4 packType;           /* What kind of packing was used. */
-   float refVal;             /* The refrence value for the grid, also the
+   float refVal;             /* The reference value for the grid, also the
                               * minimum value? */
    short int ESF;            /* Power of 2 scaling factor. */
    short int DSF;            /* Decimal Scale Factor */
diff --git a/frmts/grib/degrib18/degrib/metaname.cpp b/frmts/grib/degrib18/degrib/metaname.cpp
index 3586383..2b7ce0f 100644
--- a/frmts/grib/degrib18/degrib/metaname.cpp
+++ b/frmts/grib/degrib18/degrib/metaname.cpp
@@ -32,7 +32,7 @@ const char *centerLookup (unsigned short int center)
     * http://www.nco.ncep.noaa.gov/pmb/docs/on388/table0.html 
     * I typed this in on 11/2/2006 */
 /* *INDENT-OFF* */
-   static struct {
+   static const struct {
       unsigned short int num;
       const char *name;
    } Center[] = {
@@ -350,7 +350,7 @@ const char *subCenterLookup(unsigned short int center,
  * http://www.ecmwf.int/publications/manuals/libraries/gribex/
  *        localGRIBUsage.html as of 4/5/2006
  */
-   static struct {
+   static const struct {
       unsigned short int center, subcenter;
       const char *name;
    } SubCenter[] = {
@@ -424,7 +424,7 @@ const char *processLookup (unsigned short int center, unsigned char process)
    /* see: http://www.nco.ncep.noaa.gov/pmb/docs/on388/tablea.html I typed
     * this in on 10/12/2005 */
 /* *INDENT-OFF* */
-   static struct {
+   static const struct {
       unsigned short int center;
       unsigned char process;
       const char *name;
@@ -554,7 +554,7 @@ typedef struct {
  * 1/3/2006
  */
 /* GRIB2 Code table 4.2 : 0.0 */
-GRIB2ParmTable MeteoTemp[] = {
+static const GRIB2ParmTable MeteoTemp[] = {
    /* 0 */ {"TMP", "Temperature", "K", UC_K2F},  /* Need NDFD override. T */
    /* 1 */ {"VTMP", "Virtual temperature", "K", UC_K2F},
    /* 2 */ {"POT", "Potential temperature", "K", UC_K2F},
@@ -578,7 +578,7 @@ GRIB2ParmTable MeteoTemp[] = {
 
 /* GRIB2 Code table 4.2 : 0.1 */
 /* NCEP added "Water" to items 22, 24, 25 */
-GRIB2ParmTable MeteoMoist[] = {
+static const GRIB2ParmTable MeteoMoist[] = {
    /* 0 */ {"SPFH", "Specific humidity", "kg/kg", UC_NONE},
    /* 1 */ {"RH", "Relative Humidity", "%", UC_NONE},
    /* 2 */ {"MIXR", "Humidity mixing ratio", "kg/kg", UC_NONE},
@@ -633,7 +633,7 @@ GRIB2ParmTable MeteoMoist[] = {
 };
 
 /* GRIB2 Code table 4.2 : 0.2 */
-GRIB2ParmTable MeteoMoment[] = {
+static const GRIB2ParmTable MeteoMoment[] = {
    /* 0 */ {"WDIR", "Wind direction (from which blowing)", "deg true",
             UC_NONE}, /* Need NDFD override WindDir */
    /* 1 */ {"WIND", "Wind speed", "m/s", UC_MS2Knots}, /* Need NDFD override WindSpd */
@@ -669,7 +669,7 @@ GRIB2ParmTable MeteoMoment[] = {
 };
 
 /* GRIB2 Code table 4.2 : 0.3 */
-GRIB2ParmTable MeteoMass[] = {
+static const GRIB2ParmTable MeteoMass[] = {
    /* 0 */ {"PRES", "Pressure", "Pa", UC_NONE},
    /* 1 */ {"PRMSL", "Pressure reduced to MSL", "Pa", UC_NONE},
    /* 2 */ {"PTEND", "Pressure tendency", "Pa/s", UC_NONE},
@@ -679,7 +679,7 @@ GRIB2ParmTable MeteoMass[] = {
    /* 6 */ {"DIST", "Geometric Height", "m", UC_NONE},
    /* 7 */ {"HSTDV", "Standard deviation of height", "m", UC_NONE},
    /* 8 */ {"PRESA", "Pressure anomaly", "Pa", UC_NONE},
-   /* 9 */ {"GPA", "Geopotential height anomally", "gpm", UC_NONE},
+   /* 9 */ {"GPA", "Geopotential height anomaly", "gpm", UC_NONE},
    /* 10 */ {"DEN", "Density", "kg/(m^3)", UC_NONE},
    /* 11 */ {"", "Altimeter setting", "Pa", UC_NONE},
    /* 12 */ {"", "Thickness", "m", UC_NONE},
@@ -693,7 +693,7 @@ GRIB2ParmTable MeteoMass[] = {
 };
 
 /* GRIB2 Code table 4.2 : 0.4 */
-GRIB2ParmTable MeteoShortRadiate[] = {
+static const GRIB2ParmTable MeteoShortRadiate[] = {
    /* 0 */ {"NSWRS", "Net short-wave radiation flux (surface)", "W/(m^2)", UC_NONE},
    /* 1 */ {"NSWRT", "Net short-wave radiation flux (top of atmosphere)",
             "W/(m^2)", UC_NONE},
@@ -707,7 +707,7 @@ GRIB2ParmTable MeteoShortRadiate[] = {
 };
 
 /* GRIB2 Code table 4.2 : 0.5 */
-GRIB2ParmTable MeteoLongRadiate[] = {
+static const GRIB2ParmTable MeteoLongRadiate[] = {
    /* 0 */ {"NLWRS", "Net long wave radiation flux (surface)", "W/(m^2)", UC_NONE},
    /* 1 */ {"NLWRT", "Net long wave radiation flux (top of atmosphere)",
             "W/(m^2)", UC_NONE},
@@ -717,7 +717,7 @@ GRIB2ParmTable MeteoLongRadiate[] = {
 };
 
 /* GRIB2 Code table 4.2 : 0.6 */
-GRIB2ParmTable MeteoCloud[] = {
+static const GRIB2ParmTable MeteoCloud[] = {
    /* 0 */ {"CICE", "Cloud Ice", "kg/(m^2)", UC_NONE},
    /* 1 */ {"TCDC", "Total cloud cover", "%", UC_NONE}, /* Need NDFD override Sky */
    /* 2 */ {"CDCON", "Convective cloud cover", "%", UC_NONE},
@@ -753,7 +753,7 @@ GRIB2ParmTable MeteoCloud[] = {
 
 /* GRIB2 Code table 4.2 : 0.7 */
 /* NCEP capitalized items 6, 7, 8 */
-GRIB2ParmTable MeteoStability[] = {
+static const GRIB2ParmTable MeteoStability[] = {
    /* 0 */ {"PLI", "Parcel lifted index (to 500 hPa)", "K", UC_NONE},
    /* 1 */ {"BLI", "Best lifted index (to 500 hPa)", "K", UC_NONE},
    /* 2 */ {"KX", "K index", "K", UC_NONE},
@@ -764,25 +764,26 @@ GRIB2ParmTable MeteoStability[] = {
    /* 7 */ {"CIN", "Convective inhibition", "J/kg", UC_NONE},
    /* 8 */ {"HLCY", "Storm relative helicity", "J/kg", UC_NONE},
    /* 9 */ {"", "Energy helicity index", "numeric", UC_NONE},
+// TODO: Spelling fifted.
 /* 10 */   {"LFTX", "Surface fifted index", "K", UC_NONE},
 /* 11 */   {"4LFTX", "Best (4-layer) lifted index", "K", UC_NONE},
 /* 12 */   {"RI", "Richardson number", "-", UC_NONE},
 };
 
 /* GRIB2 Code table 4.2 : 0.13 */
-GRIB2ParmTable MeteoAerosols[] = {
+static const GRIB2ParmTable MeteoAerosols[] = {
    /* 0 */ {"", "Aerosol type", "(0 Aerosol not present, 1 Aerosol present, "
             "255 missing)", UC_NONE},
 };
 
 /* GRIB2 Code table 4.2 : 0.14 */
-GRIB2ParmTable MeteoGases[] = {
+static const GRIB2ParmTable MeteoGases[] = {
    /* 0 */ {"TOZNE", "Total ozone", "Dobson", UC_NONE},
 /* 1 */    {"O3MR", "Ozone Mixing Ratio", "kg/kg", UC_NONE},
 };
 
 /* GRIB2 Code table 4.2 : 0.15 */
-GRIB2ParmTable MeteoRadar[] = {
+static const GRIB2ParmTable MeteoRadar[] = {
    /* 0 */ {"", "Base spectrum width", "m/s", UC_NONE},
    /* 1 */ {"", "Base reflectivity", "dB", UC_NONE},
    /* 2 */ {"", "Base radial velocity", "m/s", UC_NONE},
@@ -795,7 +796,7 @@ GRIB2ParmTable MeteoRadar[] = {
 };
 
 /* GRIB2 Code table 4.2 : 0.18 */
-GRIB2ParmTable MeteoNuclear[] = {
+static const GRIB2ParmTable MeteoNuclear[] = {
    /* 0 */ {"", "Air concentration of Caesium 137", "Bq/(m^3)", UC_NONE},
    /* 1 */ {"", "Air concentration of Iodine 131", "Bq/(m^3)", UC_NONE},
    /* 2 */ {"", "Air concentration of radioactive pollutant", "Bq/(m^3)", UC_NONE},
@@ -812,7 +813,7 @@ GRIB2ParmTable MeteoNuclear[] = {
 
 /* GRIB2 Code table 4.2 : 0.19 */
 /* NCEP capitalized items 11 */
-GRIB2ParmTable MeteoAtmos[] = {
+static const GRIB2ParmTable MeteoAtmos[] = {
    /* 0 */ {"VIS", "Visibility", "m", UC_NONE},
    /* 1 */ {"ALBDO", "Albedo", "%", UC_NONE},
    /* 2 */ {"TSTM", "Thunderstorm probability", "%", UC_NONE},
@@ -841,17 +842,17 @@ GRIB2ParmTable MeteoAtmos[] = {
 };
 
 /* GRIB2 Code table 4.2 : 0.253 or 0.190 (Document is inconsistent.) */
-GRIB2ParmTable MeteoText[] = {
+static const GRIB2ParmTable MeteoText[] = {
    /* 0 */ {"", "Arbitrary text string", "CCITTIA5", UC_NONE},
 };
 
-GRIB2ParmTable MeteoMisc[] = {
+static const GRIB2ParmTable MeteoMisc[] = {
    /* 0 */ {"TSEC", "Seconds prior to initial reference time (defined in Section"
             " 1)", "s", UC_NONE},
 };
 
 /* GRIB2 Code table 4.2 : 1.0 */
-GRIB2ParmTable HydroBasic[] = {
+static const GRIB2ParmTable HydroBasic[] = {
    /* 0 */ {"", "Flash flood guidance", "kg/(m^2)", UC_NONE},
    /* 1 */ {"", "Flash flood runoff", "kg/(m^2)", UC_NONE},
    /* 2 */ {"", "Remotely sensed snow cover", "(50 no-snow/no-cloud, "
@@ -864,7 +865,7 @@ GRIB2ParmTable HydroBasic[] = {
 };
 
 /* GRIB2 Code table 4.2 : 1.1 */
-GRIB2ParmTable HydroProb[] = {
+static const GRIB2ParmTable HydroProb[] = {
    /* 0 */ {"", "Conditional percent precipitation amount fractile for an "
             "overall period", "kg/(m^2)", UC_NONE},
    /* 1 */ {"", "Percent precipitation in a sub-period of an overall period",
@@ -873,7 +874,7 @@ GRIB2ParmTable HydroProb[] = {
 };
 
 /* GRIB2 Code table 4.2 : 2.0 */
-GRIB2ParmTable LandVeg[] = {
+static const GRIB2ParmTable LandVeg[] = {
    /* 0 */ {"LAND", "Land cover (1=land; 2=sea)", "Proportion", UC_NONE},
    /* 1 */ {"SFCR", "Surface roughness", "m", UC_NONE}, /*NCEP override SFRC? */
    /* 2 */ {"TSOIL", "Soil temperature", "K", UC_NONE},
@@ -903,7 +904,7 @@ GRIB2ParmTable LandVeg[] = {
 
 /* GRIB2 Code table 4.2 : 2.3 */
 /* NCEP changed 0 to be "Soil type (as in Zobler)" I ignored them */
-GRIB2ParmTable LandSoil[] = {
+static const GRIB2ParmTable LandSoil[] = {
    /* 0 */ {"SOTYP", "Soil type", "(1 Sand, 2 Loamy sand, 3 Sandy loam, "
             "4 Silt loam, 5 Organic (redefined), 6 Sandy clay loam, "
             "7 Silt clay loam, 8 Clay loam, 9 Sandy clay, 10 Silty clay, "
@@ -920,7 +921,7 @@ GRIB2ParmTable LandSoil[] = {
 };
 
 /* GRIB2 Code table 4.2 : 3.0 */
-GRIB2ParmTable SpaceImage[] = {
+static const GRIB2ParmTable SpaceImage[] = {
    /* 0 */ {"", "Scaled radiance", "numeric", UC_NONE},
    /* 1 */ {"", "Scaled albedo", "numeric", UC_NONE},
    /* 2 */ {"", "Scaled brightness temperature", "numeric", UC_NONE},
@@ -942,7 +943,7 @@ GRIB2ParmTable SpaceImage[] = {
 };
 
 /* GRIB2 Code table 4.2 : 3.1 */
-GRIB2ParmTable SpaceQuantitative[] = {
+static const GRIB2ParmTable SpaceQuantitative[] = {
    /* 0 */ {"", "Estimated precipitation", "kg/(m^2)", UC_NONE},
 /* 1 */ {"", "Instantaneous rain rate", "kg/(m^2*s)", UC_NONE},
 /* 2 */ {"", "Cloud top height", "kg/(m^2*s)", UC_NONE},
@@ -954,7 +955,7 @@ GRIB2ParmTable SpaceQuantitative[] = {
 };
 
 /* GRIB2 Code table 4.2 : 10.0 */
-GRIB2ParmTable OceanWaves[] = {
+static const GRIB2ParmTable OceanWaves[] = {
    /* 0 */ {"WVSP1", "Wave spectra (1)", "-", UC_NONE},
    /* 1 */ {"WVSP2", "Wave spectra (2)", "-", UC_NONE},
    /* 2 */ {"WVSP3", "Wave spectra (3)", "-", UC_NONE},
@@ -972,7 +973,7 @@ GRIB2ParmTable OceanWaves[] = {
 };
 
 /* GRIB2 Code table 4.2 : 10.1 */
-GRIB2ParmTable OceanCurrents[] = {
+static const GRIB2ParmTable OceanCurrents[] = {
    /* 0 */ {"DIRC", "Current direction", "Degree true", UC_NONE},
    /* 1 */ {"SPC", "Current speed", "m/s", UC_NONE},
    /* 2 */ {"UOGRD", "u-component of current", "m/s", UC_NONE},
@@ -980,7 +981,7 @@ GRIB2ParmTable OceanCurrents[] = {
 };
 
 /* GRIB2 Code table 4.2 : 10.2 */
-GRIB2ParmTable OceanIce[] = {
+static const GRIB2ParmTable OceanIce[] = {
    /* 0 */ {"ICEC", "Ice cover", "Proportion", UC_NONE},
    /* 1 */ {"ICETK", "Ice thinkness", "m", UC_NONE},
    /* 2 */ {"DICED", "Direction of ice drift", "Degree true", UC_NONE},
@@ -992,18 +993,20 @@ GRIB2ParmTable OceanIce[] = {
 };
 
 /* GRIB2 Code table 4.2 : 10.3 */
-GRIB2ParmTable OceanSurface[] = {
+static const GRIB2ParmTable OceanSurface[] = {
    /* 0 */ {"WTMP", "Water temperature", "K", UC_NONE},
    /* 1 */ {"DSLM", "Deviation of sea level from mean", "m", UC_NONE},
 };
 
+#ifdef unused
 /* GRIB2 Code table 4.2 : 10.4 */
-GRIB2ParmTable OceanSubSurface[] = {
+static const GRIB2ParmTable OceanSubSurface[] = {
    /* 0 */ {"MTHD", "Main thermocline depth", "m", UC_NONE},
    /* 1 */ {"MTHA", "Main thermocline anomaly", "m", UC_NONE},
    /* 2 */ {"TTHDP", "Transient thermocline depth", "m", UC_NONE},
    /* 3 */ {"SALTY", "Salinity", "kg/kg", UC_NONE},
 };
+#endif
 
 /* *INDENT-ON* */
 
@@ -1031,7 +1034,7 @@ GRIB2ParmTable OceanSubSurface[] = {
  * NOTES
  *****************************************************************************
  */
-static GRIB2ParmTable *Choose_GRIB2ParmTable (int prodType, int cat,
+static const GRIB2ParmTable *Choose_GRIB2ParmTable (int prodType, int cat,
                                               size_t *tableLen)
 {
    enum { METEO_TEMP = 0, METEO_MOIST = 1, METEO_MOMENT = 2, METEO_MASS = 3,
@@ -1178,7 +1181,7 @@ static GRIB2ParmTable *Choose_GRIB2ParmTable (int prodType, int cat,
 }
 
 /* *INDENT-OFF* */
-NDFD_AbrevOverideTable NDFD_Overide[] = {
+static const NDFD_AbrevOverideTable NDFD_Overide[] = {
    /*  0 */ {"TMP", "T"},
    /*  1 */ {"TMAX", "MaxT"},
    /*  2 */ {"TMIN", "MinT"},
@@ -1194,7 +1197,7 @@ NDFD_AbrevOverideTable NDFD_Overide[] = {
    /* 11 */ {"GUST", "WindGust"},
 };
 
-GRIB2LocalTable NDFD_LclTable[] = {
+static const GRIB2LocalTable NDFD_LclTable[] = {
    /* 0 */ {0, 1, 192, "Wx", "Weather string", "-", UC_NONE},
    /* 1 */ {0, 0, 193, "ApparentT", "Apparent Temperature", "K", UC_K2F},
    /* 2 */ {0, 14, 192, "O3MR", "Ozone Mixing Ratio", "kg/kg", UC_NONE},
@@ -1210,7 +1213,7 @@ GRIB2LocalTable NDFD_LclTable[] = {
            {10, 3, 193, "ETSurge", "Extra Tropical Storm Surge", "m", UC_M2Feet},
 };
 
-GRIB2LocalTable HPC_LclTable[] = {
+static const GRIB2LocalTable HPC_LclTable[] = {
    /* 0 */ {0, 1, 192, "HPC-Wx", "HPC Code", "-", UC_NONE},
 };
 
@@ -1226,7 +1229,7 @@ http://www.nco.ncep.noaa.gov/pmb/docs/on388/table2.html
 Updated again on 2/14/2006
 Updated again on 3/15/2006
 */
-GRIB2LocalTable NCEP_LclTable[] = {
+static const GRIB2LocalTable NCEP_LclTable[] = {
    /*  0 */ {0, 0, 192, "SNOHF", "Snow Phase Change Heat Flux", "W/(m^2)", UC_NONE},
             {0, 0, 193, "TTRAD", "Temperature tendency by all radiation", "K/s", UC_NONE},
 
@@ -1403,7 +1406,7 @@ int IsData_MOS (unsigned short int center, unsigned short int subcenter)
  * NOTES
  *****************************************************************************
  */
-static GRIB2LocalTable *Choose_LocalParmTable (unsigned short int center,
+static const GRIB2LocalTable *Choose_LocalParmTable (unsigned short int center,
                                                unsigned short int subcenter,
                                                size_t *tableLen)
 {
@@ -1449,7 +1452,7 @@ static GRIB2LocalTable *Choose_LocalParmTable (unsigned short int center,
  *
  * PURPOSE
  *   Converts a prodType, template, category and subcategory quadruple to the
- * ASCII string abreviation of that variable.
+ * ASCII string abbreviation of that variable.
  *   For example: 0, 0, 0, 0, = "T" for temperature.
  *
  * ARGUMENTS
@@ -1493,8 +1496,8 @@ static void ElemNameProb (uShort2 center, uShort2 subcenter, int prodType,
                           double lowerProb, double upperProb, char **name,
                           char **comment, char **unit, int *convert)
 {
-   GRIB2ParmTable *table;
-   GRIB2LocalTable *local;
+   const GRIB2ParmTable *table;
+   const GRIB2LocalTable *local;
    size_t tableLen;
    size_t i;
    char f_isNdfd = IsData_NDFD (center, subcenter);
@@ -1668,8 +1671,8 @@ static void ElemNamePerc (uShort2 center, uShort2 subcenter, int prodType,
                           sChar percentile, char **name, char **comment,
                           char **unit, int *convert)
 {
-   GRIB2ParmTable *table;
-   GRIB2LocalTable *local;
+   const GRIB2ParmTable *table;
+   const GRIB2LocalTable *local;
    size_t tableLen;
    size_t i;
 
@@ -1760,8 +1763,8 @@ static void ElemNameNorm (uShort2 center, uShort2 subcenter, int prodType,
                           char **name,
                           char **comment, char **unit, int *convert)
 {
-   GRIB2ParmTable *table;
-   GRIB2LocalTable *local;
+   const GRIB2ParmTable *table;
+   const GRIB2LocalTable *local;
    size_t tableLen;
    size_t i;
    sChar f_accum;
@@ -1901,7 +1904,7 @@ void ParseElemName (uShort2 center, uShort2 subcenter, int prodType,
  *
  * PURPOSE
  *   Converts a prodType, template, category and subcategory quadruple to the
- * ASCII string abreviation of that variable.
+ * ASCII string abbreviation of that variable.
  *   For example: 0, 0, 0, 0, = "T" for temperature.
  *
  * ARGUMENTS
@@ -1919,7 +1922,7 @@ void ParseElemName (uShort2 center, uShort2 subcenter, int prodType,
  * FILES/DATABASES: None
  *
  * RETURNS: char *
- *   Same as 'strcpy', ie it returns name.
+ *   Same as 'strcpy', i.e. it returns name.
  *
  * HISTORY
  *   9/2002 Arthur Taylor (MDL/RSIS): Created.
@@ -2069,7 +2072,7 @@ static void ParseElemName2 (int prodType, int templat, int cat, int subcat,
  * is m = 1, b = 0.
  *
  * Currently:
- *   For f_unit = 1 (english) we return Fahrenheit, knots, and inches for
+ *   For f_unit = 1 (English) we return Fahrenheit, knots, and inches for
  * temperature, wind speed, and amount of snow or rain.  The original units
  * are Kelvin, m/s, kg/m**2.
  *   For f_unit = 2 (metric) we return Celsius instead of Kelvin.
@@ -2160,7 +2163,7 @@ int ComputeUnit (int convert, char *origName, sChar f_unit, double *unitM,
             origName[strlen (origName) - 2] = '\0';
             if (strlen (origName) > 21)
                origName[21] = '\0';
-            sprintf (name, "[%s]", origName + 7);
+            snprintf (name, 15, "[%s]", origName + 7);
             *unitM = -10; /* M = -10 => take 10^(x) */
             *unitB = 0;
             return 0;
@@ -2185,7 +2188,7 @@ int ComputeUnit (int convert, char *origName, sChar f_unit, double *unitM,
  * is m = 1, b = 0.
  *
  * Currently:
- *   For f_unit = 1 (english) we return Fahrenheit, knots, and inches for
+ *   For f_unit = 1 (English) we return Fahrenheit, knots, and inches for
  * temperature, wind speed, and amount of snow or rain.  The original units
  * are Kelvin, m/s, kg/m**2.
  *   For f_unit = 2 (metric) we return Celsius instead of Kelvin.
@@ -2295,7 +2298,7 @@ static int ComputeUnit2 (int prodType, int templat, int cat, int subcat,
 
 /* GRIB2 Code Table 4.5 */
 /* *INDENT-OFF* */
-GRIB2SurfTable Surface[] = {
+static const GRIB2SurfTable Surface[] = {
    /* 0 */ {"RESERVED", "Reserved", "-"},
    /* 1 */ {"SFC", "Ground or water surface", "-"},
    /* 2 */ {"CBL", "Cloud base level", "-"},
@@ -2337,8 +2340,8 @@ typedef struct {
 
 /* based on http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_table4-5.shtml
  * updated last on 3/14/2006 */
-GRIB2LocalSurface NCEP_Surface[] = {
-   {200, {"EATM", "Entire atmosphere (considerd as a single layer)", "-"}},
+static const GRIB2LocalSurface NCEP_Surface[] = {
+   {200, {"EATM", "Entire atmosphere (considered as a single layer)", "-"}},
    {201, {"EOCN", "Entire ocean (considered as a single layer)", "-"}},
    {204, {"HTFL", "Highest tropospheric freezing level", "-"}},
    {206, {"GCBL", "Grid scale cloud bottom level", "-"}},
@@ -2481,13 +2484,13 @@ void ParseLevelName (unsigned short int center, unsigned short int subcenter,
    *shortLevelName = NULL;
    free (*longLevelName);
    *longLevelName = NULL;
-   sprintf (valBuff, "%f", value);
+   snprintf (valBuff, sizeof(valBuff), "%f", value);
    strTrimRight (valBuff, '0');
    if (valBuff[strlen (valBuff) - 1] == '.') {
       valBuff[strlen (valBuff) - 1] = '\0';
    }
    if (f_sndValue) {
-      sprintf (sndBuff, "%f", sndValue);
+      snprintf (sndBuff, sizeof(sndBuff), "%f", sndValue);
       strTrimRight (sndBuff, '0');
       if (sndBuff[strlen (sndBuff) - 1] == '.') {
          sndBuff[strlen (sndBuff) - 1] = '\0';
diff --git a/frmts/grib/degrib18/degrib/metaparse.cpp b/frmts/grib/degrib18/degrib/metaparse.cpp
index 4b3adee..c420696 100644
--- a/frmts/grib/degrib18/degrib/metaparse.cpp
+++ b/frmts/grib/degrib18/degrib/metaparse.cpp
@@ -397,7 +397,7 @@ static int ParseSect2_Wx (float *rdat, sInt4 nrdat, sInt4 *idat,
    size_t j;            /* Counter over the length of the current group. */
    char *buffer;        /* Used to store the current "ugly" string. */
    int buffLen;         /* Length of current "ugly" string. */
-   int len;             /* length of current english phrases during creation
+   int len;             /* length of current English phrases during creation
                          * of the maxEng[] data. */
    int i;               /* assists in traversing the maxEng[] array. */
 
@@ -476,7 +476,7 @@ static int ParseSect2_Wx (float *rdat, sInt4 nrdat, sInt4 *idat,
       Wx->data = (char **) realloc ((void *) Wx->data,
                                     Wx->dataLen * sizeof (char *));
       /* Assert: buffLen is 1 more than strlen(buffer). -- FALSE -- */
-      buffLen = strlen (buffer) + 1;
+      buffLen = static_cast<int>(strlen (buffer)) + 1;
 
       Wx->data[Wx->dataLen - 1] = (char *) malloc (buffLen * sizeof (char));
       if (Wx->maxLen < buffLen) {
@@ -490,13 +490,13 @@ static int ParseSect2_Wx (float *rdat, sInt4 nrdat, sInt4 *idat,
    for (j = 0; j < Wx->dataLen; j++) {
       ParseUglyString (&(Wx->ugly[j]), Wx->data[j], simpVer);
    }
-   /* We want to know how many bytes we need for each english phrase column,
+   /* We want to know how many bytes we need for each English phrase column,
     * so we walk through each column calculating that value. */
    for (i = 0; i < NUM_UGLY_WORD; i++) {
       /* Assert: Already initialized Wx->maxEng[i]. */
       for (j = 0; j < Wx->dataLen; j++) {
          if (Wx->ugly[j].english[i] != NULL) {
-            len = strlen (Wx->ugly[j].english[i]);
+            len = static_cast<int>(strlen (Wx->ugly[j].english[i]));
             if (len > Wx->maxEng[i]) {
                Wx->maxEng[i] = len;
             }
@@ -659,7 +659,7 @@ static int ParseSect3 (sInt4 *is3, sInt4 ns3, grib_MetaData *meta)
                          * lat/lon. See GRIB2 Regulation 92.1.6 */
    sInt4 angle;         /* For Lat/Lon, 92.1.6 may not hold, in which case,
                          * angle != 0, and unit = angle/subdivision. */
-   sInt4 subdivision;   /* see angle explaination. */
+   sInt4 subdivision;   /* see angle explanation. */
 
    if (ns3 < 14) {
       return -1;
@@ -682,8 +682,9 @@ static int ParseSect3 (sInt4 *is3, sInt4 ns3, grib_MetaData *meta)
    }
    meta->gds.projType = (uChar) is3[12];
 
-	 // Don't refuse to convert the GRIB file if only the projection is unknown to us
-	 /*
+   // Do not refuse to convert the GRIB file if only the projection is unknown.
+
+   /*
    if ((is3[12] != GS3_LATLON) && (is3[12] != GS3_MERCATOR) &&
        (is3[12] != GS3_POLAR) && (is3[12] != GS3_LAMBERT)) {
       errSprintf ("Un-supported Map Projection %ld\n", is3[12]);
@@ -725,7 +726,7 @@ static int ParseSect3 (sInt4 *is3, sInt4 ns3, grib_MetaData *meta)
             errSprintf ("Missing info on radius of Earth.\n");
             return -2;
          }
-         /* Check if our m assumption was valid. If it wasn't, they give us
+         /* Check if our m assumption was valid. If it was not, they give us
           * 6371 km, which we convert to 6.371 < 6.4 */
          if (meta->gds.majEarth < 6.4) {
             meta->gds.majEarth = meta->gds.majEarth * 1000.;
@@ -763,7 +764,7 @@ static int ParseSect3 (sInt4 *is3, sInt4 ns3, grib_MetaData *meta)
             errSprintf ("Missing info on major / minor axis of Earth.\n");
             return -2;
          }
-         /* Check if our km assumption was valid. If it wasn't, they give us
+         /* Check if our km assumption was valid. If it was not, they give us
           * 6371000 m, which is > 6400. */
          if (meta->gds.majEarth > 6400) {
             meta->gds.majEarth = meta->gds.majEarth / 1000.;
@@ -788,7 +789,7 @@ static int ParseSect3 (sInt4 *is3, sInt4 ns3, grib_MetaData *meta)
             errSprintf ("Missing info on major / minor axis of Earth.\n");
             return -2;
          }
-         /* Check if our m assumption was valid. If it wasn't, they give us
+         /* Check if our m assumption was valid. If it was not, they give us
           * 6371 km, which we convert to 6.371 < 6.4 */
          if (meta->gds.majEarth < 6.4) {
             meta->gds.majEarth = meta->gds.majEarth * 1000.;
@@ -988,14 +989,14 @@ static int ParseSect3 (sInt4 *is3, sInt4 ns3, grib_MetaData *meta)
    }
    if (meta->gds.scan != GRIB2BIT_2) {
 #ifdef DEBUG
-      printf ("Scan mode is expected to be 0100 (ie %d) not %d\n",
+      printf ("Scan mode is expected to be 0100 (i.e. %d) not %d\n",
               GRIB2BIT_2, meta->gds.scan);
       printf ("The merged GRIB2 Library should return it in 0100\n");
       printf ("The merged library swaps both NCEP and MDL data to scan "
               "mode 0100\n");
 #endif
 /*
-      errSprintf ("Scan mode is expected to be 0100 (ie %d) not %d",
+      errSprintf ("Scan mode is expected to be 0100 (i.e. %d) not %d",
                   GRIB2BIT_2, meta->gds.scan);
       return -2;
 */
@@ -1034,14 +1035,14 @@ static int ParseSect3 (sInt4 *is3, sInt4 ns3, grib_MetaData *meta)
 int ParseSect4Time2secV1 (sInt4 time, int unit, double *ans)
 {
    /* Following is a lookup table for unit conversion (see code table 4.4). */
-   static sInt4 unit2sec[] = {
+   static const sInt4 unit2sec[] = {
       60, 3600, 86400L, 0, 0,
       0, 0, 0, 0, 0,
       10800, 21600L, 43200L
    };
    if ((unit >= 0) && (unit < 13)) {
       if (unit2sec[unit] != 0) {
-         *ans = (double) (time * unit2sec[unit]);
+         *ans = (double) (time) * unit2sec[unit];
          return 0;
       }
    } else if (unit == 254) {
@@ -1083,14 +1084,14 @@ int ParseSect4Time2secV1 (sInt4 time, int unit, double *ans)
 int ParseSect4Time2sec (sInt4 time, int unit, double *ans)
 {
    /* Following is a lookup table for unit conversion (see code table 4.4). */
-   static sInt4 unit2sec[] = {
+   static const sInt4 unit2sec[] = {
       60, 3600, 86400L, 0, 0,
       0, 0, 0, 0, 0,
       10800, 21600L, 43200L, 1
    };
    if ((unit >= 0) && (unit < 14)) {
       if (unit2sec[unit] != 0) {
-         *ans = (double) (time * unit2sec[unit]);
+         *ans = (double) (time) * unit2sec[unit];
          return 0;
       }
    }
@@ -1957,8 +1958,8 @@ int MetaParse (grib_MetaData *meta, sInt4 *is0, sInt4 ns0,
  *    WxType = table to look up values in. (Input)
  *    startX = The start of the X values. (Input)
  *    startY = The start of the Y values. (Input)
- *     subNx = The Nx dimmension of the subgrid (Input)
- *     subNy = The Ny dimmension of the subgrid (Input)
+ *     subNx = The Nx dimension of the subgrid (Input)
+ *     subNy = The Ny dimension of the subgrid (Input)
  *
  * FILES/DATABASES: None
  *
@@ -2078,8 +2079,8 @@ static void ParseGridNoMiss (gridAttribType *attrib, double *grib_Data,
  *    WxType = table to look up values in. (Input)
  *    startX = The start of the X values. (Input)
  *    startY = The start of the Y values. (Input)
- *     subNx = The Nx dimmension of the subgrid (Input)
- *     subNy = The Ny dimmension of the subgrid (Input)
+ *     subNx = The Nx dimension of the subgrid (Input)
+ *     subNy = The Ny dimension of the subgrid (Input)
  *
  * FILES/DATABASES: None
  *
@@ -2206,8 +2207,8 @@ static void ParseGridPrimMiss (gridAttribType *attrib, double *grib_Data,
  *    WxType = table to look up values in. (Input)
  *    startX = The start of the X values. (Input)
  *    startY = The start of the Y values. (Input)
- *     subNx = The Nx dimmension of the subgrid (Input)
- *     subNy = The Ny dimmension of the subgrid (Input)
+ *     subNx = The Nx dimension of the subgrid (Input)
+ *     subNy = The Ny dimension of the subgrid (Input)
  *
  * FILES/DATABASES: None
  *
@@ -2386,8 +2387,8 @@ void ParseGrid (gridAttribType *attrib, double **Grib_Data,
    sInt4 missCnt = 0;   /* Number of detected missing values. */
    uInt4 index;         /* Current index into Wx table. */
    float *ain = (float *) iain;
-   uInt4 subNx;         /* The Nx dimmension of the subgrid. */
-   uInt4 subNy;         /* The Ny dimmension of the subgrid. */
+   uInt4 subNx;         /* The Nx dimension of the subgrid. */
+   uInt4 subNy;         /* The Ny dimension of the subgrid. */
 
    subNx = stopX - startX + 1;
    subNy = stopY - startY + 1;
@@ -2584,7 +2585,7 @@ typedef struct {
    int cnt;
 } freqType;
 
-int freqCompare (const void *A, const void *B)
+static int freqCompare (const void *A, const void *B)
 {
    const freqType *a = (freqType *) A;
    const freqType *b = (freqType *) B;
@@ -2634,10 +2635,11 @@ void FreqPrint (char **ans, double *Data, sInt4 DataLen, sInt4 Nx,
       }
    }
 
-   qsort (freq, numFreq, sizeof (freq[0]), freqCompare);
+   if( freq )
+     qsort (freq, numFreq, sizeof (freq[0]), freqCompare);
 
    mallocSprintf (ans, "%s | count\n", comment);
-   sprintf (format, "%%.%df | %%d\n", decimal);
+   snprintf (format, sizeof(format), "%%.%df | %%d\n", decimal);
    for (i = 0; i < numFreq; i++) {
       reallocSprintf (ans, format, myRound (freq[i].value, decimal),
                       freq[i].cnt);
diff --git a/frmts/grib/degrib18/degrib/metaprint.cpp b/frmts/grib/degrib18/degrib/metaprint.cpp
index dc6d770..89ebd25 100644
--- a/frmts/grib/degrib18/degrib/metaprint.cpp
+++ b/frmts/grib/degrib18/degrib/metaprint.cpp
@@ -18,6 +18,10 @@
 #include <stdlib.h>
 #include <stdarg.h>
 #include <math.h>
+#ifndef DONT_DEPRECATE_SPRINTF
+#define DONT_DEPRECATE_SPRINTF
+#endif
+#include "cpl_port.h"
 #include "meta.h"
 #include "metaname.h"
 #include "myerror.h"
@@ -53,9 +57,9 @@
  * Instead do sizeof(table) in calling procedure.
  *****************************************************************************
  */
-static const char *Lookup(const char **table, size_t n, size_t index)
+static const char *Lookup(const char * const *table, size_t n, size_t index)
 {
-   static const char *def[] =
+   static const char * const def[] =
     { "Reserved", "Reserved for local use", "Missing" };
    if (index < (n / sizeof (char *))) {
       return table[index];
@@ -83,7 +87,7 @@ static const char *Lookup(const char **table, size_t n, size_t index)
  * a fmt == NULL.  This last call will return the constructed message to the
  * caller, and reset the message to NULL.  It is caller's responsibility to
  * free the message, and to make sure that last call to Print has fmt = NULL,
- * so that the routine doesn't accidently keep memory.
+ * so that the routine doesn't accidentally keep memory.
  *
  * ARGUMENTS
  *   label = A label for this set of data. (Input)
@@ -97,8 +101,8 @@ static const char *Lookup(const char **table, size_t n, size_t index)
  * FILES/DATABASES: None
  *
  * RETURNS: char *
- *   NULL if (fmt != NULL) (ie we added to message)
- *   message if (fmt == NULL) (ie return the message).
+ *   NULL if (fmt != NULL) (i.e. we added to message)
+ *   message if (fmt == NULL) (i.e. return the message).
  *       It is caller's responsibility to free the message, and to make sure
  *       that last call to Print has fmt = NULL.
  *
@@ -223,18 +227,18 @@ static void PrintSect1 (pdsG2Type * pds2, unsigned short int center,
                         unsigned short int subcenter)
 {
    /* Based on Grib2 Code Table 1.2 */
-   static const char *table12[] = { "Analysis", "Start of Forecast",
+   static const char * const table12[] = { "Analysis", "Start of Forecast",
       "Verifying time of forecast", "Observation time"
    };
 
    /* Based on Grib2 Code Table 1.3 */
-   static const char *table13[] = { "Operational products",
+   static const char * const table13[] = { "Operational products",
       "Operational test products", "Research products",
       "Re-analysis products"
    };
 
    /* Based on Grib2 Code Table 1.4 */
-   static const char *table14[] = { "Analysis products",
+   static const char * const table14[] = { "Analysis products",
       "Forecast products", "Analysis and forecast products",
       "Control forecast products", "Perturbed forecast products",
       "Control and perturbed forecast products",
@@ -354,30 +358,30 @@ static void PrintSect4_Category (grib_MetaData *meta)
    sect4_type *sect4 = &(meta->pds2.sect4);
 
    /* Based on Grib2 Code Table 4.1 discipline 0 */
-   static const char *tbl41_0[] = {
+   static const char * const tbl41_0[] = {
       "Temperature", "Moisture", "Momentum", "Mass", "Short-wave Radiation",
-      "Long-wave Radiation", "Cloud", "Thermodynamic Stability indicies",
-      "Kinematic Stability indicies", "Temperature Probabilities",
+      "Long-wave Radiation", "Cloud", "Thermodynamic Stability indices",
+      "Kinematic Stability indices", "Temperature Probabilities",
       "Moisture Probabilities", "Momentum Probabilities",
       "Mass Probabilities", "Aerosols", "Trace gases (e.g. ozone, C02)",
       "Radar", "Forecast Radar Imagery", "Electro-dynamics",
       "Nuclear/radiology", "Physical atmospheric properties"
    };
    /* Based on Grib2 Code Table 4.1 discipline 1 */
-   static const char *tbl41_1[] = {
+   static const char * const tbl41_1[] = {
       "Hydrology basic products", "Hydrology probabilities"
    };
    /* Based on Grib2 Code Table 4.1 discipline 2 */
-   static const char *tbl41_2[] = {
+   static const char * const tbl41_2[] = {
       "Vegetation/Biomass", "Agri-/aquacultural Special Products",
       "Transportation-related Products", "Soil Products"
    };
    /* Based on Grib2 Code Table 4.1 discipline 3 */
-   static const char *tbl41_3[] = {
+   static const char * const tbl41_3[] = {
       "Image format products", "Quantitative products"
    };
    /* Based on Grib2 Code Table 4.1 discipline 10 */
-   static const char *tbl41_10[] = {
+   static const char * const tbl41_10[] = {
       "Waves", "Currents", "Ice", "Surface Properties",
       "Sub-surface Properties"
    };
@@ -440,7 +444,7 @@ static void PrintSect4_Category (grib_MetaData *meta)
  *
  * HISTORY
  *   9/2002 Arthur Taylor (MDL/RSIS): Created.
- *   2/2003 AAT: Adjusted the interpretation of the scale vactor and value.
+ *   2/2003 AAT: Adjusted the interpretation of the scale vector and value.
  *          to be consistent with what Matt found from email conversations
  *          with WMO GRIB2 experts.
  *   2/2003 AAT: Switched from: value / pow (10, factor)
@@ -462,7 +466,7 @@ static int PrintSect4 (grib_MetaData *meta, sChar f_unit)
 {
    sect4_type *sect4 = &(meta->pds2.sect4);
    /* Based on Grib2 Code Table 4.0 */
-   static const char *tbl40[] = {
+   static const char * const tbl40[] = {
       "Analysis at a horizontal layer at a point in time",
       "Individual ensemble forecast at a horizontal layer at a point in time",
       "Derived forecast based on ensemble members at a horizontal layer at a"
@@ -483,14 +487,14 @@ static int PrintSect4 (grib_MetaData *meta, sChar f_unit)
    };
 
    /* Based on Grib2 Code Table 4.3 */
-   static const char *tbl43[] = {
+   static const char * const tbl43[] = {
       "Analysis", "Initialization", "Forecast", "Bias corrected forecast",
       "Ensemble forecast", "Probability forecast", "Forecast error",
       "Analysis error", "Observation"
    };
 
    /* Based on Grib2 Code Table 4.4 */
-   static const char *tbl44[] = {
+   static const char * const tbl44[] = {
       "Minute", "Hour", "Day", "Month", "Year", "Decade",
       "Normal (30 years)", "Century", "Reserved", "Reserved",
       "3 hours", "6 hours", "12 hours", "Second"
@@ -500,24 +504,24 @@ static int PrintSect4 (grib_MetaData *meta, sChar f_unit)
    /* See "metaname.c :: Surface[]" */
 
    /* Based on Grib2 Code Table 4.6 */
-   static const char *tbl46[] = {
+   static const char * const tbl46[] = {
       "Unperturbed high-resolution control forecast",
-      "Unperturbed low-reosulution control foreacst",
+      "Unperturbed low-resolution control forecast",
       "Negatively perturbed forecast", "Positively perturbed forecast"
    };
 
    /* Based on Grib2 Code Table 4.7 */
-   static const char *tbl47[] = {
+   static const char * const tbl47[] = {
       "Unweighted mean of all members", "Weighted mean of all members",
       "Standard deviation with respect to cluster mean",
       "Standard deviation with respect to cluster mean, normalized",
       "Spread of all members",
-      "Large anomally index of all memebers",
+      "Large anomaly index of all members",
       "Unweighted mean of the cluster members"
    };
 
    /* Based on Grib2 Code Table 4.9 */
-   static const char *tbl49[] = {
+   static const char * const tbl49[] = {
       "Probability of event below lower limit",
       "Probability of event above upper limit",
       "Probability of event between limits (include lower, exclude upper)",
@@ -526,7 +530,7 @@ static int PrintSect4 (grib_MetaData *meta, sChar f_unit)
    };
 
    /* Based on Grib2 Code Table 4.10 */
-   static const char *tbl410[] = {
+   static const char * const tbl410[] = {
       "Average", "Accumulation", "Maximum", "Minimum",
       "Difference (Value at end of time minus beginning)",
       "Root mean square", "Standard deviation",
@@ -535,7 +539,7 @@ static int PrintSect4 (grib_MetaData *meta, sChar f_unit)
    };
 
    /* Based on Grib2 Code Table 4.11 */
-   static const char *tbl411[] = {
+   static const char * const tbl411[] = {
       "Reserved",
       "Successive times; same forecast time, start time incremented",
       "Successive times; same start time, forecast time incremented",
@@ -824,6 +828,7 @@ static int PrintSect4 (grib_MetaData *meta, sChar f_unit)
                 sect4->upperLimit.value *
                 pow (10.0, -1 * sect4->upperLimit.factor), buffer);
          /* Intentionally fall through. */
+         // CPL_FALLTHROUGH
       case GS4_STATISTIC:
 /*         strftime (buffer, 100, "%m/%d/%Y %H:%M:%S UTC",
                    gmtime (&(sect4->validTime)));*/
@@ -893,7 +898,7 @@ static int PrintPDS2 (grib_MetaData *meta, sChar f_unit)
 {
    pdsG2Type *pds2 = &(meta->pds2);
    /* Based on Grib2 Code Table 0.0 */
-   static const char *table0[] = {
+   static const char * const table0[] = {
       "Meteorological products", "Hydrological products",
       "Land surface products", "Space products", "Oceanographic products"
    };
@@ -946,7 +951,7 @@ static int PrintPDS2 (grib_MetaData *meta, sChar f_unit)
  *   4/2003 Arthur Taylor (MDL/RSIS): Created.
  *  10/2005 AAT: Adjusted to take center, subcenter as we moved that out of
  *               the pdsG1 type.
- *  11/2005 AAT: Added f_utit variable.
+ *  11/2005 AAT: Added f_unit variable.
  *
  * NOTES
  *****************************************************************************
@@ -1082,7 +1087,7 @@ static void PrintPDS1 (pdsG1Type *pds1, char *comment,
 static int PrintGDS (gdsType *gds, int version)
 {
    /* Based on Grib2 Code Table 3.1 */
-   static const char *table31[] = { "Latitude/Longitude", "Mercator",
+   static const char * const table31[] = { "Latitude/Longitude", "Mercator",
       "Polar Stereographic", "Lambert Conformal",
       "Space view perspective orthographic",
       "Equatorial azimuthal equidistant projection",
@@ -1186,9 +1191,9 @@ static int PrintGDS (gdsType *gds, int version)
       Print ("GDS", "Dx", Prt_FS, gds->Dx, "m");
       Print ("GDS", "Dy", Prt_FS, gds->Dy, "m");
    }
-   /* For scan mode... The user of this data doesn't necesarily care how it
-    * was stored in the Grib2 grid (ie gds->scan), they just care about how
-    * the data they are accessing is scanned (ie scan=0000) */
+   /* For scan mode... The user of this data doesn't necessarily care how it
+    * was stored in the Grib2 grid (i.e. gds->scan), they just care about how
+    * the data they are accessing is scanned (i.e. scan=0000) */
    sprintf (buffer, "%d%d%d%d", ((gds->scan & GRIB2BIT_1) / GRIB2BIT_1),
             ((gds->scan & GRIB2BIT_2) / GRIB2BIT_2),
             ((gds->scan & GRIB2BIT_3) / GRIB2BIT_3),
@@ -1259,17 +1264,17 @@ static int PrintGDS (gdsType *gds, int version)
 static void PrintGridAttrib (gridAttribType *attrib, sChar decimal)
 {
    /* Based on Grib2 Code Table 5.0 */
-   static const char *table50[] = {
+   static const char * const table50[] = {
       "Grid point data - simple packing", "Matrix value - simple packing",
       "Grid point data - complex packing",
       "Grid point data - complex packing and spatial differencing"
    };
 
    /* Based on Grib2 Code Table 5.1 */
-   static const char *table51[] = { "Floating point", "Integer" };
+   static const char * const table51[] = { "Floating point", "Integer" };
 
    /* Based on Grib2 Code Table 5.5 */
-   static const char *table55[] = {
+   static const char * const table55[] = {
       "No explicit missing value included with data",
       "Primary missing value included with data",
       "Primary and Secondary missing values included with data"
diff --git a/frmts/grib/degrib18/degrib/myassert.c b/frmts/grib/degrib18/degrib/myassert.c
index 5c16c1f..da19cf1 100644
--- a/frmts/grib/degrib18/degrib/myassert.c
+++ b/frmts/grib/degrib18/degrib/myassert.c
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * myasert.c
+ * myassert.c
  *
  * DESCRIPTION
  *    This file contains the code to handle assert statements.  There is no
diff --git a/frmts/grib/degrib18/degrib/myassert.h b/frmts/grib/degrib18/degrib/myassert.h
index f23d752..5157b49 100644
--- a/frmts/grib/degrib18/degrib/myassert.h
+++ b/frmts/grib/degrib18/degrib/myassert.h
@@ -25,8 +25,16 @@
 #endif
 
 #ifdef DEBUG
+
+#if defined(__GNUC__) && __GNUC__ >= 3
+#define DEGRIB_NO_RETURN                                __attribute__((noreturn))
+#else
+#define DEGRIB_NO_RETURN
+#endif
+
+
 CPL_C_START
-   void _myAssert (const char *file, int lineNum);
+   void _myAssert (const char *file, int lineNum) DEGRIB_NO_RETURN;
 CPL_C_END
 
    #define myAssert(f) \
diff --git a/frmts/grib/degrib18/degrib/myerror.c b/frmts/grib/degrib18/degrib/myerror.c
index 02d2941..02af990 100644
--- a/frmts/grib/degrib18/degrib/myerror.c
+++ b/frmts/grib/degrib18/degrib/myerror.c
@@ -86,7 +86,7 @@ static void AllocSprintf (char **Ptr, size_t *LenBuff, const char *fmt,
    size_t lenBuff = *LenBuff; /* Local copy of LenBuff. */
    const char *p;       /* Points to % char in % option. */
    const char *p1;      /* Points to end of % option. */
-   char bufpart[330];   /* Used for formating the int / float options. */
+   char bufpart[330];   /* Used for formatting the int / float options. */
    char format[20];     /* Used to store the % option. */
    char *sval;          /* For pulling strings off va_list. */
    char **Sval;         /* For pulling lists of strings off va_list. */
@@ -560,7 +560,7 @@ static void _myWarn (uChar f_errCode, const char *fmt, va_list ap)
  *   This does the transformation of the "..." parameters, and calls _myWarn.
  * This was broken out when we started to implement myWarnRet, so we had two
  * ways to call _myWarn.  A complicated way (myWarnRet), and a simpler way
- * (myWarn).  After creating the myWarnW# #defines, thought to depricate use
+ * (myWarn).  After creating the myWarnW# #defines, thought to deprecate use
  * of myWarn by making it static.  Still need it, because myWarnRet uses it.
  *
  * ARGUMENTS
@@ -716,9 +716,9 @@ void myWarnSet (uChar f_outType, uChar f_detail, uChar f_fileDetail,
  *
  * RETURNS: sChar
  *   -1 means no messages in msg (msg should be null)
- *    0 means upto notation msg in msg, but msg should not be null.
- *    1 means upto warning messages in msg, msg should not be null.
- *    2 means upto error messages in msg, msg should not be null.
+ *    0 means up to notation msg in msg, but msg should not be null.
+ *    1 means up to warning messages in msg, msg should not be null.
+ *    2 means up to error messages in msg, msg should not be null.
  *
  * 12/2005 Arthur Taylor (MDL): Created.
  *
@@ -771,9 +771,9 @@ uChar myWarnNotEmpty ()
  *
  * RETURNS: sChar
  *   -1 means no messages in msg (msg should be null)
- *    0 means upto notation msg in msg, but msg should not be null.
- *    1 means upto warning messages in msg, msg should not be null.
- *    2 means upto error messages in msg, msg should not be null.
+ *    0 means up to notation msg in msg, but msg should not be null.
+ *    1 means up to warning messages in msg, msg should not be null.
+ *    2 means up to error messages in msg, msg should not be null.
  *
  * 12/2005 Arthur Taylor (MDL): Created.
  *
diff --git a/frmts/grib/degrib18/degrib/myerror.h b/frmts/grib/degrib18/degrib/myerror.h
index 9c4380a..db57b7c 100644
--- a/frmts/grib/degrib18/degrib/myerror.h
+++ b/frmts/grib/degrib18/degrib/myerror.h
@@ -45,9 +45,9 @@ void myWarnSet (uChar f_outType, uChar f_detail, uChar f_fileDetail,
 /* You are responsible for free'ing the result of myWarnClear. */
 sChar myWarnClear (char **msg, uChar f_closeFile);
 
-uChar myWarnNotEmpty ();
+uChar myWarnNotEmpty (void);
 
-sChar myWarnLevel ();
+sChar myWarnLevel (void);
 
 /* Use myWarnQ# for (quiet file/line) notes. */
 /* Use myWarnN# for notes. */
diff --git a/frmts/grib/degrib18/degrib/myutil.c b/frmts/grib/degrib18/degrib/myutil.c
index ec2290d..17d9a1a 100644
--- a/frmts/grib/degrib18/degrib/myutil.c
+++ b/frmts/grib/degrib18/degrib/myutil.c
@@ -188,13 +188,13 @@ void mySplit (const char *data, char symbol, size_t *Argc, char ***Argv,
 
 int myAtoI (const char *ptr, sInt4 *value)
 {
-   char *extra;         /* The data after the end of the double. */
+   char *extra = NULL;         /* The data after the end of the double. */
 
    myAssert (ptr != NULL);
    *value = 0;
    while (*ptr != '\0') {
       if (isdigit (*ptr) || (*ptr == '+') || (*ptr == '-')) {
-         *value = strtol (ptr, &extra, 10);
+         *value = (int)strtol (ptr, &extra, 10);
          myAssert (extra != NULL);
          if (*extra == '\0') {
             return 1;
@@ -256,7 +256,7 @@ int myAtoI (const char *ptr, sInt4 *value)
  */
 int myAtoF (const char *ptr, double *value)
 {
-   char *extra;         /* The data after the end of the double. */
+   char *extra = NULL;         /* The data after the end of the double. */
 
    myAssert (ptr != NULL);
    *value = 0;
@@ -388,7 +388,7 @@ int myStat (char *filename, char *perm, sInt4 *size, double *mtime)
    if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
       /* Is a directory */
       if (size)
-         *size = stbuf.st_size;
+         *size = (sInt4)stbuf.st_size;
       if (mtime)
          *mtime = stbuf.st_mtime;
       if (perm) {
@@ -402,7 +402,7 @@ int myStat (char *filename, char *perm, sInt4 *size, double *mtime)
    } else if ((stbuf.st_mode & S_IFMT) == S_IFREG) {
       /* Is a file */
       if (size)
-         *size = stbuf.st_size;
+         *size = (sInt4)stbuf.st_size;
       if (mtime)
          *mtime = stbuf.st_mtime;
       if (perm) {
@@ -505,7 +505,7 @@ return 0; // TODO: reimplement for Win32
  *
  * ARGUMENTS
  *  fileIn = source file to read from. (Input)
- * fileOut = destation file to write to. (Input)
+ *  fileOut = destination file to write to. (Input)
  *
  * RETURNS: int
  *   0 = success.
@@ -614,7 +614,7 @@ void FileTail (const char *fileName, char **tail)
  *     primarily as an example, but it can be used for some rounding.
  *****************************************************************************
  */
-double POWERS_ONE[] = {
+static const double POWERS_ONE[] = {
    1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
    1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17
 };
@@ -1020,17 +1020,17 @@ int GetIndexFromStr (const char *str, char **Opt, int *Index)
  */
 static sChar Clock_GetTimeZone ()
 {
-   struct tm time;
+   struct tm l_time;
    time_t ansTime;
    struct tm *gmTime;
    static sChar timeZone = 127;
 
    if (timeZone == 127) {
       /* Cheap method of getting global time_zone variable. */
-      memset (&time, 0, sizeof (struct tm));
-      time.tm_year = 70;
-      time.tm_mday = 2;
-      ansTime = mktime (&time);
+      memset (&l_time, 0, sizeof (struct tm));
+      l_time.tm_year = 70;
+      l_time.tm_mday = 2;
+      ansTime = mktime (&l_time);
       gmTime = gmtime (&ansTime);
       timeZone = gmTime->tm_hour;
       if (gmTime->tm_mday != 2) {
@@ -1076,12 +1076,12 @@ int myParseTime3 (const char *is, time_t * AnsTime)
    uChar hour;          /* The hour. */
    uChar min;           /* The minute. */
    uChar sec;           /* The second. */
-   struct tm time;      /* A temporary variable to put the time info into. */
+   struct tm l_time;      /* A temporary variable to put the time info into. */
 
-   memset (&time, 0, sizeof (struct tm));
+   memset (&l_time, 0, sizeof (struct tm));
    myAssert (strlen (is) == 14);
    if (strlen (is) != 14) {
-      printf ("%s is not formated correctly\n", is);
+      printf ("%s is not formatted correctly\n", is);
       return 1;
    }
    strncpy (buffer, is, 4);
@@ -1104,13 +1104,13 @@ int myParseTime3 (const char *is, time_t * AnsTime)
       printf ("%d %d %d %d %d %d\n", year, mon, day, hour, min, sec);
       return 1;
    }
-   time.tm_year = year - 1900;
-   time.tm_mon = mon - 1;
-   time.tm_mday = day;
-   time.tm_hour = hour;
-   time.tm_min = min;
-   time.tm_sec = sec;
-   *AnsTime = mktime (&time) - (Clock_GetTimeZone () * 3600);
+   l_time.tm_year = year - 1900;
+   l_time.tm_mon = mon - 1;
+   l_time.tm_mday = day;
+   l_time.tm_hour = hour;
+   l_time.tm_min = min;
+   l_time.tm_sec = sec;
+   *AnsTime = mktime (&l_time) - (Clock_GetTimeZone () * 3600);
    return 0;
 }
 
diff --git a/frmts/grib/degrib18/degrib/scan.c b/frmts/grib/degrib18/degrib/scan.c
index 7f905d4..e94e1d6 100644
--- a/frmts/grib/degrib18/degrib/scan.c
+++ b/frmts/grib/degrib18/degrib/scan.c
@@ -22,7 +22,7 @@
  *   To convert from the index of the GRIB2 message which is defined by the
  * scan parameter, to one that seemed reasonable.  The choice for internal
  * array orientation boiled down to either (scan = 0000) (start from upper
- * left and accross similar to a CRT screen) or (scan = 0100) (start at lower
+ * left and across similar to a CRT screen) or (scan = 0100) (start at lower
  * left and go up ).
  *   It was decided that (scan 0100) was what people expected.  The only catch
  * is that Spatial Analyst requires (scan = 0000), so when writing to that
@@ -30,7 +30,7 @@
  *   For more info on scan flags: see Grib2 "Flag" Table 3.4
  *
  * ARGUMENTS
- *    row = The index in the scaned in data. (Input)
+ *    row = The index in the scanned in data. (Input)
  *   X, Y = The x,y position in a scan == 0100 world. (Output)
  *   scan = The orientation of the GRIB2 grid. (Input)
  * Nx, Ny = The Dimensions of the grid (Input).
@@ -98,7 +98,7 @@ void ScanIndex2XY (sInt4 row, sInt4 * X, sInt4 * Y, uChar scan, sInt4 Nx,
  * testing purposes, and in case it is useful.
  *
  * ARGUMENTS
- *    Row = The index in the scaned in data. (Output)
+ *    Row = The index in the scanned in data. (Output)
  *   x, y = The x,y position in a (scan = 0100) world. (Input)
  *   scan = The orientation of the GRIB2 grid. (Input)
  * Nx, Ny = The Dimensions of the grid (Input).
diff --git a/frmts/grib/degrib18/degrib/tdlpack.cpp b/frmts/grib/degrib18/degrib/tdlpack.cpp
index ba6a43c..3a81930 100644
--- a/frmts/grib/degrib18/degrib/tdlpack.cpp
+++ b/frmts/grib/degrib18/degrib/tdlpack.cpp
@@ -20,7 +20,7 @@
 #define GRIB_SIGN_INT2(a,b) ((1-(int) ((unsigned) (a & 0x80) >> 6)) * (int) (((a & 0x7f) << 8) + b))
 
 /* *INDENT-OFF* */
-TDLP_TableType TDLP_B_Table[5] = {
+static const TDLP_TableType TDLP_B_Table[5] = {
    /* 0 */ {0, "Continuous field"},
    /* 1 */ {1, "Point Binary - cumulative from above"},
    /* 2 */ {2, "Point Binary - cumulative from below"},
@@ -28,7 +28,7 @@ TDLP_TableType TDLP_B_Table[5] = {
    /* 4 */ {5, "Grid Binary - "},
 };
 
-TDLP_TableType TDLP_DD_Table[9] = {
+static const TDLP_TableType TDLP_DD_Table[9] = {
    /* 0 */ {0, "Independent of model"},
    /* 1 */ {6, "NGM model"},
    /* 2 */ {7, "Eta model"},
@@ -40,20 +40,20 @@ TDLP_TableType TDLP_DD_Table[9] = {
    /* 8 */ {82, "Obs matching AEV Forecasts"},
 };
 
-TDLP_TableType TDLP_V_Table[4] = {
+static const TDLP_TableType TDLP_V_Table[4] = {
    /* 0 */ {0, "No vertical processing"},
    /* 1 */ {1, "Difference Levels (UUUU - LLLL)"},
    /* 2 */ {2, "Sum Levels (UUUU + LLLL)"},
    /* 3 */ {3, "Mean Levels (UUUU + LLLL) / 2."},
 };
 
-TDLP_TableType TDLP_T_Table[3] = {
-   /* 0 */ {0, "No nolinear tranform"},
+static const TDLP_TableType TDLP_T_Table[3] = {
+   /* 0 */ {0, "No nolinear transform"},  // TODO: "No no"?
    /* 1 */ {1, "Square transform"},
-   /* 2 */ {2, "Square root tranform"},
+   /* 2 */ {2, "Square root transform"},
 };
 
-TDLP_TableType TDLP_Oper_Table[9] = {
+static const TDLP_TableType TDLP_Oper_Table[9] = {
    /* 0 */ {0, "No time operator"},
    /* 1 */ {1, "Mean (Var 1, Var 2)"},
    /* 2 */ {2, "Difference (Var 1 - Var 2)"},
@@ -65,14 +65,14 @@ TDLP_TableType TDLP_Oper_Table[9] = {
    /* 8 */ {8, "Minimum (Var 1, Var 2)"},
 };
 
-TDLP_TableType TDLP_I_Table[4] = {
+static const TDLP_TableType TDLP_I_Table[4] = {
    /* 0 */ {0, "No interpolation"},
    /* 1 */ {1, "Bi-quadratic interpolation"},
    /* 2 */ {2, "Bi-linear interpolation"},
    /* 3 */ {3, "Special interpolation for QPF"},
 };
 
-TDLP_TableType TDLP_S_Table[6] = {
+static const TDLP_TableType TDLP_S_Table[6] = {
    /* 0 */ {0, "No smoothing"},
    /* 1 */ {1, "5-point smoothing"},
    /* 2 */ {2, "9-point smoothing"},
@@ -151,7 +151,10 @@ static int ReadTDLPSect1 (uChar *pds, sInt4 tdlpLen, sInt4 *curLoc,
       errSprintf ("Ran out of data in PDS (TDLP Section 1)\n");
       return -1;
    }
-   myAssert (sectLen <= 71);
+   if( sectLen > 71 ) {
+      errSprintf ("TDLP Section 1 is too big.\n");
+      return -1;
+   }
    if (sectLen < 39) {
       errSprintf ("TDLP Section 1 is too small.\n");
       return -1;
@@ -167,10 +170,10 @@ static int ReadTDLPSect1 (uChar *pds, sInt4 tdlpLen, sInt4 *curLoc,
    min = *(pds++);
    MEMCPY_BIG (&li_temp, pds, sizeof (sInt4));
    pds += 4;
-   t_year = li_temp / 1000000L;
-   li_temp -= t_year * 1000000L;
-   t_month = li_temp / 10000L;
-   li_temp -= t_month * 10000L;
+   t_year = li_temp / 1000000;
+   li_temp -= t_year * 1000000;
+   t_month = li_temp / 10000;
+   li_temp -= t_month * 10000;
    t_day = li_temp / 100;
    t_hour = li_temp - t_day * 100;
    if ((t_year != year) || (t_month != month) || (t_day != day) ||
@@ -185,8 +188,8 @@ static int ReadTDLPSect1 (uChar *pds, sInt4 tdlpLen, sInt4 *curLoc,
    MEMCPY_BIG (&(li_temp), pds, sizeof (sInt4));
    pds += 4;
    pdsMeta->ID1 = li_temp;
-   pdsMeta->CCC = li_temp / 1000000L;
-   li_temp -= pdsMeta->CCC * 1000000L;
+   pdsMeta->CCC = li_temp / 1000000;
+   li_temp -= pdsMeta->CCC * 1000000;
    pdsMeta->FFF = li_temp / 1000;
    li_temp -= pdsMeta->FFF * 1000;
    pdsMeta->B = li_temp / 100;
@@ -194,39 +197,39 @@ static int ReadTDLPSect1 (uChar *pds, sInt4 tdlpLen, sInt4 *curLoc,
    MEMCPY_BIG (&(li_temp), pds, sizeof (sInt4));
    pds += 4;
    pdsMeta->ID2 = li_temp;
-   pdsMeta->V = li_temp / 100000000L;
-   li_temp -= pdsMeta->V * 100000000L;
+   pdsMeta->V = li_temp / 100000000;
+   li_temp -= pdsMeta->V * 100000000;
    pdsMeta->LLLL = li_temp / 10000;
    pdsMeta->UUUU = li_temp - pdsMeta->LLLL * 10000;
    MEMCPY_BIG (&(li_temp), pds, sizeof (sInt4));
    pds += 4;
    pdsMeta->ID3 = li_temp;
-   pdsMeta->T = li_temp / 100000000L;
-   li_temp -= pdsMeta->T * 100000000L;
-   pdsMeta->RR = li_temp / 1000000L;
-   li_temp -= pdsMeta->RR * 1000000L;
-   pdsMeta->Oper = li_temp / 100000L;
-   li_temp -= pdsMeta->Oper * 100000L;
+   pdsMeta->T = li_temp / 100000000;
+   li_temp -= pdsMeta->T * 100000000;
+   pdsMeta->RR = li_temp / 1000000;
+   li_temp -= pdsMeta->RR * 1000000;
+   pdsMeta->Oper = li_temp / 100000;
+   li_temp -= pdsMeta->Oper * 100000;
    pdsMeta->HH = li_temp / 1000;
    pdsMeta->ttt = li_temp - pdsMeta->HH * 1000;
    MEMCPY_BIG (&(li_temp), pds, sizeof (sInt4));
    pds += 4;
    pdsMeta->ID4 = li_temp;
-   W = li_temp / 1000000000L;
-   li_temp -= W * 1000000000L;
-   XXXX = li_temp / 100000L;
-   li_temp -= XXXX * 100000L;
+   W = li_temp / 1000000000;
+   li_temp -= W * 1000000000;
+   XXXX = li_temp / 100000;
+   li_temp -= XXXX * 100000;
    if (W) {
       XXXX = -1 * XXXX;
    }
-   YY = li_temp / 1000L;
-   li_temp -= YY * 1000L;
+   YY = li_temp / 1000;
+   li_temp -= YY * 1000;
    if (YY >= 50) {
       YY = -1 * (YY - 50);
    }
    pdsMeta->thresh = (XXXX / 10000.) * pow (10.0, YY);
    pdsMeta->I = li_temp / 100;
-   li_temp -= pdsMeta->I * 100L;
+   li_temp -= pdsMeta->I * 100;
    pdsMeta->S = li_temp / 10;
    pdsMeta->G = li_temp - pdsMeta->S * 10;
    project_hr = GRIB_UNSIGN_INT2 (*pds, pds[1]);
@@ -291,7 +294,7 @@ static int ReadTDLPSect1 (uChar *pds, sInt4 tdlpLen, sInt4 *curLoc,
  * NOTES
  *****************************************************************************
  */
-static const char *TDLP_TableLookUp(TDLP_TableType * table, int tableLen,
+static const char *TDLP_TableLookUp(const TDLP_TableType * table, int tableLen,
                                     int index)
 {
    int i;               /* Loop counter. */
@@ -336,43 +339,43 @@ void PrintPDS_TDLP (pdsTDLPType * pds)
 
    Print ("PDS-TDLP", "Reference Time", Prt_S, buffer);
    Print ("PDS-TDLP", "Plain Language", Prt_S, pds->Descriptor);
-   sprintf (buffer, "%09d", pds->ID1);
+   snprintf(buffer, sizeof(buffer), "%09d", pds->ID1);
    Print ("PDS-TDLP", "ID 1", Prt_S, buffer);
-   sprintf (buffer, "%09d", pds->ID2);
+   snprintf(buffer, sizeof(buffer), "%09d", pds->ID2);
    Print ("PDS-TDLP", "ID 2", Prt_S, buffer);
-   sprintf (buffer, "%09d", pds->ID3);
+   snprintf(buffer, sizeof(buffer), "%09d", pds->ID3);
    Print ("PDS-TDLP", "ID 3", Prt_S, buffer);
    Print ("PDS-TDLP", "ID 4", Prt_D, pds->ID4);
    Print ("PDS-TDLP", "Model or Process Number", Prt_D, pds->procNum);
    Print ("PDS-TDLP", "Sequence Number", Prt_D, pds->seqNum);
 
-   sprintf (buffer, "%03d", pds->CCC);
+   snprintf(buffer, sizeof(buffer), "%03d", pds->CCC);
    Print ("PDS-TDLP", "ID1-CCC", Prt_S, buffer);
-   sprintf (buffer, "%03d", pds->FFF);
+   snprintf(buffer, sizeof(buffer), "%03d", pds->FFF);
    Print ("PDS-TDLP", "ID1-FFF", Prt_S, buffer);
    Print ("PDS-TDLP", "ID1-B", Prt_DS, pds->B,
           TDLP_TableLookUp (TDLP_B_Table, sizeof (TDLP_B_Table), pds->B));
-   sprintf (buffer, "%02d", pds->DD);
+   snprintf(buffer, sizeof(buffer), "%02d", pds->DD);
    Print ("PDS-TDLP", "ID1-DD", Prt_SS, buffer,
           TDLP_TableLookUp (TDLP_DD_Table, sizeof (TDLP_DD_Table), pds->DD));
 
    Print ("PDS-TDLP", "ID2-V", Prt_DS, pds->V,
           TDLP_TableLookUp (TDLP_V_Table, sizeof (TDLP_V_Table), pds->V));
-   sprintf (buffer, "%04d", pds->LLLL);
+   snprintf(buffer, sizeof(buffer), "%04d", pds->LLLL);
    Print ("PDS-TDLP", "ID2-LLLL", Prt_S, buffer);
-   sprintf (buffer, "%04d", pds->UUUU);
+   snprintf(buffer, sizeof(buffer), "%04d", pds->UUUU);
    Print ("PDS-TDLP", "ID2-UUUU", Prt_S, buffer);
 
    if (pds->Oper != 0) {
       Print ("PDS-TDLP", "ID3-T", Prt_DS, pds->T,
              TDLP_TableLookUp (TDLP_T_Table, sizeof (TDLP_T_Table), pds->T));
-      sprintf (buffer, "%02d", pds->RR);
+      snprintf(buffer, sizeof(buffer), "%02d", pds->RR);
       Print ("PDS-TDLP", "ID3-RR", Prt_SS, buffer,
              "Run time offset in hours");
       Print ("PDS-TDLP", "ID3-Oper", Prt_DS, pds->Oper,
              TDLP_TableLookUp (TDLP_Oper_Table, sizeof (TDLP_Oper_Table),
                                pds->Oper));
-      sprintf (buffer, "%02d", pds->HH);
+      snprintf(buffer, sizeof(buffer), "%02d", pds->HH);
       Print ("PDS-TDLP", "ID3-HH", Prt_SS, buffer,
              "Number of hours between variables");
    } else {
@@ -380,7 +383,7 @@ void PrintPDS_TDLP (pdsTDLPType * pds)
              TDLP_TableLookUp (TDLP_Oper_Table, sizeof (TDLP_Oper_Table),
                                pds->Oper));
    }
-   sprintf (buffer, "%03d", pds->ttt);
+   snprintf(buffer, sizeof(buffer), "%03d", pds->ttt);
    Print ("PDS-TDLP", "ID3-ttt", Prt_SS, buffer, "Forecast Projection");
 
    Print ("PDS-TDLP", "ID4-thresh", Prt_F, pds->thresh);
@@ -493,7 +496,7 @@ static void TDLP_ElemSurfUnit (pdsTDLPType * pds, char **element,
  *
  * NOTES
  *   Speed improvements...
- * 1) pds doen't need to be allocated each time.
+ * 1) pds does not need to be allocated each time.
  * 2) Not all data is needed, do something like TDLP_RefTime
  * 3) TDLP_ElemSurfUnit may be slow?
  *****************************************************************************
@@ -521,7 +524,16 @@ int TDLP_Inventory (DataSource &fp, sInt4 tdlpLen, inventoryType *inv)
       errSprintf ("Ran out of data in PDS (TDLP_Inventory)\n");
       return -1;
    }
+   if( sectLen < 1 ) {
+       errSprintf ("Wrong sectLen (TDLP_Inventory)\n");
+       return -1;
+   }
    pds = (uChar *) malloc (sectLen * sizeof (uChar));
+   if( pds == NULL ) 
+   {
+      errSprintf ("Ran out of memory in PDS (TDLP_Inventory)\n");
+      return -1;
+   }
    *pds = sectLen;
    if (fp.DataSourceFread (pds + 1, sizeof (char), sectLen - 1) + 1 != sectLen) {
       errSprintf ("Ran out of file.\n");
@@ -599,7 +611,10 @@ int TDLP_RefTime (DataSource &fp, sInt4 tdlpLen, double *refTime)
       errSprintf ("Ran out of data in PDS (TDLP_RefTime)\n");
       return -1;
    }
-   myAssert (sectLen <= 71);
+   if( sectLen > 71 ) {
+      errSprintf ("TDLP Section 1 is too big.\n");
+      return -1;
+   }
    if (sectLen < 39) {
       errSprintf ("TDLP Section 1 is too small.\n");
       return -1;
@@ -625,10 +640,10 @@ int TDLP_RefTime (DataSource &fp, sInt4 tdlpLen, double *refTime)
 
    if (FREAD_BIG (&li_temp, sizeof (sInt4), 1, fp) != 1)
       goto error;
-   t_year = li_temp / 1000000L;
-   li_temp -= t_year * 1000000L;
-   t_month = li_temp / 10000L;
-   li_temp -= t_month * 10000L;
+   t_year = li_temp / 1000000;
+   li_temp -= t_year * 1000000;
+   t_month = li_temp / 10000;
+   li_temp -= t_month * 10000;
    t_day = li_temp / 100;
    t_hour = li_temp - t_day * 100;
 
@@ -692,7 +707,10 @@ static int ReadTDLPSect2 (uChar *gds, sInt4 tdlpLen, sInt4 *curLoc,
       errSprintf ("Ran out of data in GDS (TDLP Section 2)\n");
       return -1;
    }
-   myAssert (sectLen == 28);
+   if( sectLen != 28 ) {
+      errSprintf ("Wrong sectLen (TDLP Section 2)\n");
+      return -1;
+   }
 
    gridType = *(gds++);
    gdsMeta->Nx = GRIB_UNSIGN_INT2 (*gds, gds[1]);
@@ -880,13 +898,13 @@ static int ReadTDLPSect4 (uChar *bds, sInt4 tdlpLen, sInt4 *curLoc,
    uChar kbit;          /* # of bits for # values in a group. */
    TDLGroupType *grp;   /* Holds the info about each group. */
    size_t i, j;         /* Loop counters. */
-   uInt4 t_numPack;     /* Used to total number of values in a group to check 
+   uInt4 t_numPack;     /* Used to total number of values in a group to check
                          * the numPack value. */
    uInt4 t_numBits;     /* Used to total number of bits used in the groups. */
    uInt4 t_numBytes;    /* Used to total number of bytes used to compare to
                          * sectLen. */
    sInt4 maxVal;        /* The max value in a group. */
-   uInt4 dataCnt;       /* How many values (miss or othewise) we have read. */
+   uInt4 dataCnt;       /* How many values (miss or otherwise) we have read. */
    uInt4 lastData;      /* Index to last actual data. */
    uInt4 numVal;        /* # of actual (non-missing values) we have. */
    double scale;        /* Amount to scale values by. */
@@ -971,8 +989,8 @@ static int ReadTDLPSect4 (uChar *bds, sInt4 tdlpLen, sInt4 *curLoc,
       memBitRead (&uli_temp, sizeof (sInt4), bds, 31, &bufLoc, &numUsed);
       myAssert (numUsed == 4);
       bds += numUsed;
-      t_numBytes += numUsed;
-      origVal = (f_negative) ? -1 * uli_temp : uli_temp;
+      t_numBytes += static_cast<uInt4>(numUsed);
+      origVal = (f_negative) ? -1 * (sInt4)uli_temp : uli_temp;
       memBitRead (&mbit, sizeof (mbit), bds, 5, &bufLoc, &numUsed);
       memBitRead (&f_negative, sizeof (f_negative), bds, 1, &bufLoc,
                   &numUsed);
@@ -980,36 +998,36 @@ static int ReadTDLPSect4 (uChar *bds, sInt4 tdlpLen, sInt4 *curLoc,
       myAssert ((mbit > 0) && (mbit < 32));
       memBitRead (&uli_temp, sizeof (sInt4), bds, mbit, &bufLoc, &numUsed);
       bds += numUsed;
-      t_numBytes += numUsed;
-      fstDiff = (f_negative) ? -1 * uli_temp : uli_temp;
+      t_numBytes += static_cast<uInt4>(numUsed);
+      fstDiff = (f_negative) ? -1 * (sInt4)uli_temp : uli_temp;
    }
    memBitRead (&nbit, sizeof (nbit), bds, 5, &bufLoc, &numUsed);
    bds += numUsed;
-   t_numBytes += numUsed;
+   t_numBytes += static_cast<uInt4>(numUsed);
    memBitRead (&f_negative, sizeof (f_negative), bds, 1, &bufLoc, &numUsed);
    bds += numUsed;
-   t_numBytes += numUsed;
+   t_numBytes += static_cast<uInt4>(numUsed);
    myAssert ((nbit > 0) && (nbit < 32));
    memBitRead (&uli_temp, sizeof (sInt4), bds, nbit, &bufLoc, &numUsed);
    bds += numUsed;
-   t_numBytes += numUsed;
-   minVal = (f_negative) ? -1 * uli_temp : uli_temp;
+   t_numBytes += static_cast<uInt4>(numUsed);
+   minVal = (f_negative) ? -1 * (sInt4)uli_temp : uli_temp;
    memBitRead (&LX, sizeof (LX), bds, 16, &bufLoc, &numUsed);
    bds += numUsed;
-   t_numBytes += numUsed;
+   t_numBytes += static_cast<uInt4>(numUsed);
    grp = (TDLGroupType *) malloc (LX * sizeof (TDLGroupType));
    memBitRead (&ibit, sizeof (ibit), bds, 5, &bufLoc, &numUsed);
    bds += numUsed;
-   t_numBytes += numUsed;
+   t_numBytes += static_cast<uInt4>(numUsed);
    memBitRead (&jbit, sizeof (jbit), bds, 5, &bufLoc, &numUsed);
    /* Following assert is because it is the # of bits of # of bits.  Which
     * means that # of bits of value that has a max of 64. */
    myAssert (jbit < 6);
    bds += numUsed;
-   t_numBytes += numUsed;
+   t_numBytes += static_cast<uInt4>(numUsed);
    memBitRead (&kbit, sizeof (kbit), bds, 5, &bufLoc, &numUsed);
    bds += numUsed;
-   t_numBytes += numUsed;
+   t_numBytes += static_cast<uInt4>(numUsed);
    myAssert (ibit < 33);
    for (i = 0; i < LX; i++) {
       if (ibit == 0) {
@@ -1018,7 +1036,7 @@ static int ReadTDLPSect4 (uChar *bds, sInt4 tdlpLen, sInt4 *curLoc,
          memBitRead (&(grp[i].min), sizeof (sInt4), bds, ibit, &bufLoc,
                      &numUsed);
          bds += numUsed;
-         t_numBytes += numUsed;
+         t_numBytes += static_cast<uInt4>(numUsed);
       }
    }
    myAssert (jbit < 8);
@@ -1030,7 +1048,7 @@ static int ReadTDLPSect4 (uChar *bds, sInt4 tdlpLen, sInt4 *curLoc,
          memBitRead (&(grp[i].bit), sizeof (uChar), bds, jbit, &bufLoc,
                      &numUsed);
          bds += numUsed;
-         t_numBytes += numUsed;
+         t_numBytes += static_cast<uInt4>(numUsed);
       }
       myAssert (grp[i].bit < 32);
    }
@@ -1044,7 +1062,7 @@ static int ReadTDLPSect4 (uChar *bds, sInt4 tdlpLen, sInt4 *curLoc,
          memBitRead (&(grp[i].num), sizeof (sInt4), bds, kbit, &bufLoc,
                      &numUsed);
          bds += numUsed;
-         t_numBytes += numUsed;
+         t_numBytes += static_cast<uInt4>(numUsed);
       }
       t_numPack += grp[i].num;
       t_numBits += grp[i].num * grp[i].bit;
@@ -1521,7 +1539,7 @@ int ReadTDLPRecord (DataSource &fp, double **TDLP_Data, uInt4 *tdlp_DataLen,
       return -1;
    }
 
-   /* Preceeding was in degrib2, next part is specific to TDLP. */
+   /* Preceding was in degrib2, next part is specific to TDLP. */
    curLoc = 8;
    if (ReadTDLPSect1 (c_ipack + curLoc, tdlpLen, &curLoc, &(meta->pdsTdlp),
                       &f_gds, &f_bms, &DSF, &BSF) != 0) {
@@ -1670,7 +1688,7 @@ int ReadTDLPRecord (DataSource &fp, double **TDLP_Data, uInt4 *tdlp_DataLen,
  * NOTES
  *****************************************************************************
  */
-#define SCALE_MISSING 10000L
+#define SCALE_MISSING 10000
 static void TDL_ScaleData (double *Src, sInt4 *Dst, sInt4 numData,
                            int DSF, int BSF, char *f_primMiss,
                            double *primMiss, char *f_secMiss,
@@ -1696,7 +1714,7 @@ static void TDL_ScaleData (double *Src, sInt4 *Dst, sInt4 numData,
          src++;
          f_actualSec = 1;
       } else {
-         *(dst) = (long int) (floor ((*(src++) / scale) + .5));
+         *(dst) = (sInt4) (floor ((*(src++) / scale) + .5));
          /* Check if scaled value == primary missing value. */
          if (((*f_primMiss) || (*f_secMiss)) && (*dst == li_primMiss)) {
             *dst = *dst - 1;
@@ -1886,8 +1904,8 @@ static int TDL_GetSecDiff (sInt4 *Data, int numData, sInt4 *SecDiff,
  *
  * PURPOSE
  *   Checks if the average range of 2nd order differences < average range of
- * 0 order differnces, to determine if we should use second order differences
- *   This deals with the case when we have primary missing values.
+ *   0 order differences, to determine if we should use second order
+ *   differences. This deals with the case when we have primary missing values.
  *
  * ARGUMENTS
  *        Data = The data. (Input)
@@ -2001,7 +2019,8 @@ static int TDL_UseSecDiff_Prim (sInt4 *Data, sInt4 numData,
  *
  * PURPOSE
  *   Checks if the average range of 2nd order differences < average range of
- * 0 order differnces, to determine if we should use second order differences
+ *   0 order differences, to determine if we should use second order
+ *   differences.
  *
  * ARGUMENTS
  *        Data = The data. (Input)
@@ -2140,7 +2159,7 @@ static int power (uInt4 val, int extra)
  * ARGUMENTS
  *        Data = The data. (Input)
  *       start = The starting index in data (Input)
- *        stop = The stoping index in data (Input)
+ *        stop = The stopping index in data (Input)
  * li_primMiss = scaled primary missing value (Input)
  *  li_secMiss = scaled secondary missing value (Input)
  *         min = The min value found (Output)
@@ -2195,7 +2214,7 @@ static char findMaxMin2 (sInt4 *Data, int start, int stop,
  * ARGUMENTS
  *        Data = The data. (Input)
  *       start = The starting index in data (Input)
- *        stop = The stoping index in data (Input)
+ *        stop = The stopping index in data (Input)
  * li_primMiss = scaled primary missing value (Input)
  *         min = The min value found (Output)
  *         max = The max value found (Output)
@@ -2248,7 +2267,7 @@ static char findMaxMin1 (sInt4 *Data, int start, int stop,
  * ARGUMENTS
  *  Data = The data. (Input)
  * start = The starting index in data (Input)
- *  stop = The stoping index in data (Input)
+ *  stop = The stopping index in data (Input)
  *   min = The min value found (Output)
  *   max = The max value found (Output)
  *
@@ -2290,7 +2309,7 @@ static void findMaxMin0 (sInt4 *Data, int start, int stop, sInt4 *min,
  * ARGUMENTS
  *        Data = The data. (Input)
  *       start = The starting index in data (Input)
- *        stop = The stoping index in data (Input)
+ *        stop = The stopping index in data (Input)
  * li_primMiss = scaled primary missing value (Input)
  *  li_secMiss = scaled secondary missing value (Input)
  *       range = The range to use (Input)
@@ -2354,7 +2373,7 @@ static void findGroup2 (sInt4 *Data, int start, int stop,
  * ARGUMENTS
  *        Data = The data. (Input)
  *       start = The starting index in data (Input)
- *        stop = The stoping index in data (Input)
+ *        stop = The stopping index in data (Input)
  * li_primMiss = scaled primary missing value (Input)
  *       range = The range to use (Input)
  *       split = The first index that is out of the range (Output)
@@ -2417,7 +2436,7 @@ static void findGroup1 (sInt4 *Data, int start, int stop,
  * ARGUMENTS
  *        Data = The data. (Input)
  *       start = The starting index in data (Input)
- *        stop = The stoping index in data (Input)
+ *        stop = The stopping index in data (Input)
  *       range = The range to use (Input)
  *       split = The first index that is out of the range (Output)
  *         min = The min value for the group. (Output)
@@ -2470,7 +2489,7 @@ static void findGroup0 (sInt4 *Data, int start, int stop,
  * ARGUMENTS
  *        Data = The data. (Input)
  *       start = The starting index in data (Input)
- *        stop = The stoping index in data (Input)
+ *        stop = The stopping index in data (Input)
  * li_primMiss = scaled primary missing value (Input)
  *  li_secMiss = scaled secondary missing value (Input)
  *       range = The range to use (Input)
@@ -2534,7 +2553,7 @@ static void findGroupRev2 (sInt4 *Data, int start, int stop,
  * ARGUMENTS
  *        Data = The data. (Input)
  *       start = The starting index in data (Input)
- *        stop = The stoping index in data (Input)
+ *        stop = The stopping index in data (Input)
  * li_primMiss = scaled primary missing value (Input)
  *       range = The range to use (Input)
  *       split = The first index that is still in the range (Output)
@@ -2597,7 +2616,7 @@ static void findGroupRev1 (sInt4 *Data, int start, int stop,
  * ARGUMENTS
  *        Data = The data. (Input)
  *       start = The starting index in data (Input)
- *        stop = The stoping index in data (Input)
+ *        stop = The stopping index in data (Input)
  * li_primMiss = scaled primary missing value (Input)
  *       range = The range to use (Input)
  *       split = The first index that is still in the range (Output)
@@ -2656,8 +2675,8 @@ static void findGroupRev0 (sInt4 *Data, int start, int stop,
  * ARGUMENTS
  *        Data = The data. (Input)
  *      start1 = The starting index in data (Input)
- *      start2 = The starting index of the earlier group (ie don't go to any
- *               earlier indicies than this. (Input)
+ *      start2 = The starting index of the earlier group (i.e. don't go to any
+ *               earlier indices than this. (Input)
  * li_primMiss = scaled primary missing value (Input)
  *  li_secMiss = scaled secondary missing value (Input)
  *         bit = The range we are allowed to store this in. (Input)
@@ -2724,8 +2743,8 @@ static void shiftGroup2 (sInt4 *Data, int start1, int start2,
  * ARGUMENTS
  *        Data = The data. (Input)
  *      start1 = The starting index in data (Input)
- *      start2 = The starting index of the earlier group (ie don't go to any
- *               earlier indicies than this. (Input)
+ *      start2 = The starting index of the earlier group (i.e. don't go to any
+ *               earlier indices than this. (Input)
  * li_primMiss = scaled primary missing value (Input)
  *         bit = The range we are allowed to store this in. (Input)
  *         min = The min value for the group. (Input/Output)
@@ -2791,8 +2810,8 @@ static void shiftGroup1 (sInt4 *Data, int start1, int start2,
  * ARGUMENTS
  *        Data = The data. (Input)
  *      start1 = The starting index in data (Input)
- *      start2 = The starting index of the earlier group (ie don't go to any
- *               earlier indicies than this. (Input)
+ *      start2 = The starting index of the earlier group (i.e. don't go to any
+ *               earlier indices than this. (Input)
  *         bit = The range we are allowed to store this in. (Input)
  *         min = The min value for the group. (Input/Output)
  *         max = The max value for the group. (Input/Output)
@@ -3130,7 +3149,7 @@ static sInt4 ComputeGroupSize (TDLGroupType * group, int numGroup,
    }
    /* Allow 0 bits for min.  Assumes that decoder allows 0 bits */
    *kbit = i;
-   ans += ((*ibit) + (*jbit) + (*kbit)) * numGroup;
+   ans += (sInt4) (((*ibit) + (*jbit) + (*kbit)) * numGroup);
    return ans;
 }
 
@@ -3219,12 +3238,12 @@ static int splitGroup (sInt4 *Data, int numData, TDLGroupType * group,
           (group[i].bit > minBit)) {
          f_keep = 0;
          doSplit (Data, numData, &(group[i]), &subGroup, &numSubGroup,
-                  f_primMiss, li_primMiss, f_secMiss, li_secMiss, xFactor);
+                  f_primMiss, li_primMiss, f_secMiss, li_secMiss, static_cast<int>(xFactor));
          if (numSubGroup != 1) {
-            scoreA = group[i].bit * group[i].num + xFactor;
+            scoreA = static_cast<sInt4>(group[i].bit * group[i].num + xFactor);
             scoreB = 0;
             for (sub = 0; sub < numSubGroup; sub++) {
-               scoreB += subGroup[sub].bit * subGroup[sub].num + xFactor;
+               scoreB += (sInt4) (subGroup[sub].bit * subGroup[sub].num + xFactor);
             }
             if (scoreB < scoreA) {
                f_keep = 1;
@@ -3253,8 +3272,8 @@ static int splitGroup (sInt4 *Data, int numData, TDLGroupType * group,
                subGroup[1].f_trySplit = 1;
                subGroup[1].f_tryShift = 1;
                numSubGroup = 2;
-               scoreB = subGroup[0].bit * subGroup[0].num + xFactor;
-               scoreB += subGroup[1].bit * subGroup[1].num + xFactor;
+               scoreB = static_cast<sInt4>(subGroup[0].bit * subGroup[0].num + xFactor);
+               scoreB += static_cast<sInt4>(subGroup[1].bit * subGroup[1].num + xFactor);
                if (scoreB < scoreA) {
                   f_keep = 1;
                }
@@ -3270,9 +3289,9 @@ static int splitGroup (sInt4 *Data, int numData, TDLGroupType * group,
             doSplitRight (Data, numData, &(group[i]), &(subGroup[1]),
                           &(subGroup[0]), f_primMiss, li_primMiss, f_secMiss,
                           li_secMiss);
-            scoreA = group[i].bit * group[i].num + xFactor;
-            scoreB = subGroup[0].bit * subGroup[0].num + xFactor;
-            scoreB += subGroup[1].bit * subGroup[1].num + xFactor;
+            scoreA = static_cast<sInt4>(group[i].bit * group[i].num + xFactor);
+            scoreB = static_cast<sInt4>(subGroup[0].bit * subGroup[0].num + xFactor);
+            scoreB += static_cast<sInt4>(subGroup[1].bit * subGroup[1].num + xFactor);
             if (scoreB < scoreA) {
                f_keep = 1;
             }
@@ -3371,7 +3390,7 @@ static void shiftGroup (sInt4 *Data,
                         char f_secMiss, sInt4 li_secMiss, int xFactor)
 {
    TDLGroupType *group = (*Group); /* Local pointer to Group. */
-   int numGroup = (*NumGroup); /* # elements in group. */
+   int numGroup = static_cast<int>(*NumGroup); /* # elements in group. */
    int i, j;            /* loop counters. */
    sInt4 A_max;         /* Max value of a given group. */
    sInt4 A_min;         /* Min value of a given group. */
@@ -3407,7 +3426,7 @@ static void shiftGroup (sInt4 *Data,
          /* See if that affects any of the previous groups. */
          for (j = i + 1; j < numGroup; j++) {
             if (group[j].num != 0) {
-               G1.start = G1.start;
+               /*G1.start = G1. start;*/ /* self-assignment... */
                G1.num = group[i - 1].num + group[j].num;
                G1.min = (group[i - 1].min < group[j].min) ?
                      group[i - 1].min : group[j].min;
@@ -3457,7 +3476,7 @@ static void shiftGroup (sInt4 *Data,
                G2 = group[i];
                G2.min = A_min;
                G2.max = A_max;
-               G1.num -= (group[i].start - begin);
+               G1.num -= static_cast<uInt4>(group[i].start - begin);
                if (f_secMiss) {
                   findMaxMin2 (Data, G1.start, G1.start + G1.num,
                                li_primMiss, li_secMiss, &A_min, &A_max);
@@ -3476,8 +3495,8 @@ static void shiftGroup (sInt4 *Data,
                   G1.f_trySplit = 1;
                   G1.f_tryShift = 1;
                }
-               G2.num += (group[i].start - begin);
-               G2.start = begin;
+               G2.num += static_cast<uInt4>(group[i].start - begin);
+               G2.start = static_cast<uInt4>(begin);
                G2.f_trySplit = 1;
                G2.f_tryShift = 1;
                scoreA = group[i].bit * group[i].num + xFactor;
@@ -3533,7 +3552,7 @@ static void shiftGroup (sInt4 *Data,
  *   Attempts to find groups for packing the data.  It starts by preparing
  * the data, by removing the overall min value.
  *
- *   Next it Creates any 0 bit groups (primary missing: missings are all 0
+ *   Next it Creates any 0 bit groups (primary missing: missing are all 0
  * bit groups, const values are 0 bit groups.  No missing: const values are
  * 0 bit groups.)
  *
@@ -3600,8 +3619,7 @@ static void GroupIt (sInt4 OverallMin, sInt4 *Data, size_t numData,
          for (i = 0; i < numData; i++) {
             if ((Data[i] != li_secMiss) && (Data[i] != li_primMiss)) {
                Data[i] -= OverallMin;
-               /* Check if we accidently adjusted to prim or sec, if so add
-                * 1. */
+               // Check if we accidentally adjusted to prim or sec, if so add 1.
                if ((Data[i] == li_secMiss) || (Data[i] == li_primMiss)) {
                   myAssert (1 == 2);
                   Data[i]++;
@@ -3616,8 +3634,7 @@ static void GroupIt (sInt4 OverallMin, sInt4 *Data, size_t numData,
          for (i = 0; i < numData; i++) {
             if (Data[i] != li_primMiss) {
                Data[i] -= OverallMin;
-               /* Check if we accidently adjusted to prim or sec, if so add
-                * 1. */
+               // Check if we accidentally adjusted to prim or sec, if so add 1.
                if (Data[i] == li_primMiss) {
                   myAssert (1 == 2);
                   Data[i]++;
@@ -3663,7 +3680,7 @@ static void GroupIt (sInt4 OverallMin, sInt4 *Data, size_t numData,
                   G.min = Data[i];
                   G.max = Data[i];
                   G.num = 1;
-                  G.start = i;
+                  G.start = static_cast<uInt4>(i);
                }
             } else {
                /* Close a missing group */
@@ -3681,7 +3698,7 @@ static void GroupIt (sInt4 OverallMin, sInt4 *Data, size_t numData,
                G.min = Data[i];
                G.max = Data[i];
                G.num = 1;
-               G.start = i;
+               G.start = static_cast<uInt4>(i);
             }
          } else {
             if (Data[i] == li_primMiss) {
@@ -3705,7 +3722,7 @@ static void GroupIt (sInt4 OverallMin, sInt4 *Data, size_t numData,
                G.min = Data[i];
                G.max = Data[i];
                G.num = 1;
-               G.start = i;
+               G.start = static_cast<uInt4>(i);
             } else {
                if (G.min > Data[i]) {
                   G.min = Data[i];
@@ -3749,13 +3766,13 @@ static void GroupIt (sInt4 OverallMin, sInt4 *Data, size_t numData,
    } else {
       /* Already handled the f_primMiss case */
       if (f_secMiss) {
-         findMaxMin2 (Data, 0, numData, li_primMiss, li_secMiss, &A_min,
+         findMaxMin2 (Data, 0, static_cast<int>(numData), li_primMiss, li_secMiss, &A_min,
                       &A_max);
       } else {
-         findMaxMin0 (Data, 0, numData, &A_min, &A_max);
+         findMaxMin0 (Data, 0, static_cast<int>(numData), &A_min, &A_max);
       }
       G.start = 0;
-      G.num = numData;
+      G.num = static_cast<uInt4>(numData);
       G.min = A_min;
       G.max = A_max;
       G.bit = (char) power ((uInt4) (A_max - A_min), f_secMiss + f_primMiss);
@@ -3768,7 +3785,7 @@ static void GroupIt (sInt4 OverallMin, sInt4 *Data, size_t numData,
 
    lclGroup = NULL;
    numLclGroup = 0;
-   *groupSize = ComputeGroupSize (*group, *numGroup, ibit, jbit, kbit);
+   *groupSize = ComputeGroupSize (*group, static_cast<int>(*numGroup), ibit, jbit, kbit);
    xFactor = *ibit + *jbit + *kbit;
 #ifdef DEBUG
 /*
@@ -3779,7 +3796,7 @@ static void GroupIt (sInt4 OverallMin, sInt4 *Data, size_t numData,
 
    f_adjust = 1;
    while (f_adjust) {
-      f_adjust = splitGroup (Data, numData, *group, *numGroup, &lclGroup,
+      f_adjust = splitGroup (Data, static_cast<int>(numData), *group, static_cast<int>(*numGroup), &lclGroup,
                              &numLclGroup, f_primMiss, li_primMiss,
                              f_secMiss, li_secMiss, xFactor);
       free (*group);
@@ -3787,9 +3804,9 @@ static void GroupIt (sInt4 OverallMin, sInt4 *Data, size_t numData,
       *numGroup = numLclGroup;
 
       if (f_adjust) {
-         shiftGroup (Data, numData, group, numGroup, f_primMiss,
-                     li_primMiss, f_secMiss, li_secMiss, xFactor);
-         *groupSize = ComputeGroupSize (*group, *numGroup, ibit, jbit, kbit);
+         shiftGroup (Data, static_cast<int>(numData), group, numGroup, f_primMiss,
+                     li_primMiss, f_secMiss, li_secMiss, static_cast<int>(xFactor));
+         *groupSize = ComputeGroupSize (*group, static_cast<int>(*numGroup), ibit, jbit, kbit);
          if (xFactor != *ibit + *jbit + *kbit) {
             for (i = 0; i < *numGroup; i++) {
                if (((*group)[i].num > *ibit + *jbit + *kbit) &&
@@ -3832,7 +3849,7 @@ static void GroupIt (sInt4 OverallMin, sInt4 *Data, size_t numData,
  *     f_grid = Flag if this is grid data (or vector) (Input)
  *         NX = The number of X values. (Input)
  *         NY = The number of Y values. (Input)
- * f_sndOrder = Flag if we should do second order diffencing (Output)
+ * f_sndOrder = Flag if we should do second order differencing (Output)
  *      group = Resulting groups. (Output)
  *   numGroup = Number of groups. (Output)
  *        Min = Overall minimum. (Output)
@@ -3914,7 +3931,7 @@ static int GroupPack (double *Src, sInt4 **Dst, sInt4 numData,
       li_secMiss = (sInt4) (*secMiss * SCALE_MISSING + .5);
    }
 
-   /* Reason this is after TDL_ScaleData is we don't want to reoder the
+   /* Reason this is after TDL_ScaleData is we don't want to reorder the
     * caller's copy of the data. */
    if (f_grid) {
       TDL_ReorderGrid (Data, NX, NY);
@@ -4072,10 +4089,10 @@ int WriteTDLPRecord (FILE * fp, double *Data, sInt4 DataLen, int DSF,
    short int si_temp;   /* Temporary variable (short int). */
    double d_temp;       /* Temporary variable (double). */
    char buffer[6];      /* Used to write reserved values */
-   uChar pbuf;          /* A buffer of bits that weren't written to disk */
+   uChar pbuf;          /* A buffer of bits that were not written to disk */
    sChar pbufLoc;       /* Where in pbuf to add more bits. */
 
-   commentLen = strlen (comment);
+   commentLen = static_cast<int>(strlen (comment));
    if (commentLen > 32) {
       errSprintf ("Error: '%s' is > 32 bytes long\n", comment);
       return -1;
@@ -4213,7 +4230,7 @@ int WriteTDLPRecord (FILE * fp, double *Data, sInt4 DataLen, int DSF,
    if (f_bitmap) {
       i |= 2;
    }
-   fputc (i, fp);
+   fputc (static_cast<int>(i), fp);
 /*   tempTime = gmtime (&(refTime));*/
    Clock_PrintDate (refTime, &year, &month, &day, &hour, &min, &sec);
 /* year = tempTime->tm_year + 1900;
@@ -4228,7 +4245,7 @@ int WriteTDLPRecord (FILE * fp, double *Data, sInt4 DataLen, int DSF,
    fputc (day, fp);
    fputc (hour, fp);
    fputc (min, fp);
-   li_temp = (year * 1000000L + month * 10000L + day * 100 + hour);
+   li_temp = (year * 1000000 + month * 10000 + day * 100 + hour);
    FWRITE_BIG (&li_temp, sizeof (sInt4), 1, fp);
    FWRITE_BIG (&ID1, sizeof (sInt4), 1, fp);
    FWRITE_BIG (&ID2, sizeof (sInt4), 1, fp);
@@ -4239,9 +4256,9 @@ int WriteTDLPRecord (FILE * fp, double *Data, sInt4 DataLen, int DSF,
    fputc (processNum, fp);
    fputc (seqNum, fp);
    i = (DSF < 0) ? 128 - DSF : DSF;
-   fputc (i, fp);
+   fputc (static_cast<int>(i), fp);
    i = (BSF < 0) ? 128 - BSF : BSF;
-   fputc (i, fp);
+   fputc (static_cast<int>(i), fp);
    /* Reserved: 3 bytes of 0. */
    li_temp = 0;
    fwrite (&li_temp, sizeof (char), 3, fp);
@@ -4327,7 +4344,7 @@ int WriteTDLPRecord (FILE * fp, double *Data, sInt4 DataLen, int DSF,
       i |= 8;
    if (!f_grid)
       i |= 16;
-   fputc (i, fp);
+   fputc (static_cast<int>(i), fp);
    li_temp = DataLen;
    FWRITE_BIG (&li_temp, sizeof (sInt4), 1, fp);
    if (f_primMiss) {
diff --git a/frmts/grib/degrib18/degrib/weather.c b/frmts/grib/degrib18/degrib/weather.c
index 7d9c93c..b8f8555 100644
--- a/frmts/grib/degrib18/degrib/weather.c
+++ b/frmts/grib/degrib18/degrib/weather.c
@@ -40,7 +40,7 @@
 #endif
 
 typedef struct {
-   char *abrev, *name;
+   const char *abrev, *name;
    uChar number;
 } WxTable;
 
@@ -60,7 +60,7 @@ enum {
 /* SA -> Snowfall aob freezing */
 /* LC -> Caution Advised on area Lakes */
 /*   {"WG", "Frequent Gusts", WX_WG},*/
-WxTable WxCode[] = {
+static const WxTable WxCode[] = {
    /* 0 */ {"<NoWx>", "No Weather", WX_NOWX},
    /* Dry Obstruction to visibility. */
    /* 14 */ {"K", "Smoke", WX_K},
@@ -109,7 +109,7 @@ enum {
    COV_INTER, COV_BRIEF, COV_UNKNOWN
 };
 
-WxTable WxCover[] = {
+static const WxTable WxCover[] = {
    /* 0 */ {"<NoCov>", "No Coverage/Probability", COV_NOCOV},
    /* 1 */ {"Iso", "Isolated", COV_ISO},
    /* 2 */ {"Sct", "Scattered", COV_SCT},
@@ -133,7 +133,7 @@ WxTable WxCover[] = {
 
 enum { INT_NOINT, INT_DD, INT_D, INT_M, INT_P, INT_UNKNOWN };
 
-WxTable WxIntens[] = {
+static const WxTable WxIntens[] = {
    /* 0 */ {"<NoInten>", "No Intensity", INT_NOINT},
    /* 1 */ {"--", "Very Light", INT_DD},
    /* 2 */ {"-", "Light", INT_D},
@@ -147,7 +147,7 @@ enum {
    VIS_96, VIS_128, VIS_160, VIS_192, VIS_224, VIS_UNKNOWN = 255
 };
 
-WxTable WxVisib[] = {
+static const WxTable WxVisib[] = {
    /* 0 */ {"<NoVis>", "255", VIS_NOVIS},
    /* 1 */ {"0SM", "0", VIS_0},
    /* 2 */ {"1/4SM", "8", VIS_8},
@@ -172,9 +172,9 @@ enum {
    HAZ_PRI2 = 254, HAZ_OR = 255
 };
 
-/* Note: HazCode currently can handle upto (21 + 4) different WxAttrib
+/* Note: HazCode currently can handle up to (21 + 4) different WxAttrib
  * numbers because it is stored in a "sInt4" (2^31 = 21,47,48,36,48) */
-WxTable WxAttrib[] = {
+static const WxTable WxAttrib[] = {
    /* 0 */ {"", "None", HAZ_NOHAZ},
    /* 1 */ {"FL", "Frequent Lightning", HAZ_FL},
    /* 2 */ {"GW", "Gusty Winds", HAZ_GW},
@@ -206,7 +206,7 @@ WxTable WxAttrib[] = {
  *   To use the same weather table scheme used by Marc Saccucci in
  * makeWxImageCodes() in the NDFD source tree.  The purpose of both
  * procedures is to simplify the weather string (aka ugly string) to a single
- * integral code number, which contains the most releavent weather.  The
+ * integral code number, which contains the most relevant weather.  The
  * intent is to create a simpler field which can more readily be viewed as
  * an image.
  *
@@ -1760,7 +1760,7 @@ static int NDFD_CodeIntens4 (int inten1, int inten2)
  *   To use the same weather table scheme used by Mark Armstrong in
  * makeWxImageCodes().  The purpose of both procedures is to simplify the
  * weather string (aka ugly string) to a single integral code number, which
- * contains the most releavent weather.  The intent is to create a simpler
+ * contains the most relevant weather.  The intent is to create a simpler
  * field which can more readily be viewed as an image.
  *
  * ARGUMENTS
@@ -1948,7 +1948,7 @@ static int NDFD_WxTable4 (UglyStringType * ugly)
  */
 void FreeUglyString (UglyStringType * ugly)
 {
-   int j;               /* Used to free all the english words. */
+   int j;               /* Used to free all the English words. */
 
    for (j = 0; j < NUM_UGLY_ATTRIB; j++) {
       free (ugly->english[j]);
@@ -2033,7 +2033,7 @@ static void InitUglyString (UglyStringType * ugly)
  * NOTES
  *****************************************************************************
  */
-static int FindInTable (WxTable * table, int tableLen, char *data, uChar *ans)
+static int FindInTable (const WxTable * table, int tableLen, char *data, uChar *ans)
 {
    int i;               /* Index used to walk through the table. */
 
@@ -2065,8 +2065,8 @@ static int FindInTable (WxTable * table, int tableLen, char *data, uChar *ans)
  *   ugly = The ugly string structure to modify. (Output)
  *   data = The string (or phrase) to look for. (Input)
  *   word = Which word we are currently working on. (Input)
- *  place = What part of the word (ie # of :'s) (Input)
- * attNum = What part of attribute piece (ie # of ,'s) (Input)
+ *  place = What part of the word (i.e. # of :'s) (Input)
+ * attNum = What part of attribute piece (i.e. # of ,'s) (Input)
  *
  * FILES/DATABASES: None
  *
@@ -2231,7 +2231,7 @@ static int UglyLookUp (UglyStringType * ugly, char *data, uChar word,
  *   5/2003 Arthur Taylor (MDL/RSIS): Created.
  *
  * NOTES
- * 1) buffer size is choosen so each of the 8 parts has 50 bytes for the
+ * 1) buffer size is chosen so each of the 8 parts has 50 bytes for the
  *    table entry and the ' ' and ', ' and ' with '.  If NUM_UGLY_ATTRIB
  *    increases (from 5), we may need more.
  * 2) Instead of static buffer, we could use myerror.c :: AllocSprintf.
@@ -2265,7 +2265,7 @@ static void Ugly2English (UglyStringType * ugly)
       f_first = 1;
       for (j = 0; j < NUM_UGLY_ATTRIB; j++) {
          if (ugly->attrib[i][j] != 0) {
-            if (ugly->f_priority == 0) {
+            if (ugly->f_priority[i] == 0) {
                if (f_first) {
                   strcat (buffer, " with ");
                   f_first = 0;
@@ -2331,7 +2331,7 @@ static void Ugly2English (UglyStringType * ugly)
  *
  * RETURNS: int
  *  0 = No problems
- * -1 = Had difficulties parseing the Ugly string.
+ * -1 = Had difficulties parsing the ugly string.
  *
  * HISTORY
  *   5/2003 Arthur Taylor (MDL/RSIS): Created.
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/README b/frmts/grib/degrib18/g2clib-1.0.4/README
index d17845b..86fdf92 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/README
+++ b/frmts/grib/degrib18/g2clib-1.0.4/README
@@ -7,7 +7,7 @@ This library contains "C" decoder/encoder
 routines for GRIB edition 2.  The user API for the GRIB2 routines
 is described in file "grib2c.doc".
 
-This "C" source code conatins many uses of the C++
+This "C" source code contains many uses of the C++
 comment style "//".  Please make sure you include the
 appropriate compiler option in the CFLAGS variable in the
 makefile to allow the use of "//" comment indicators.
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/cmplxpack.c b/frmts/grib/degrib18/g2clib-1.0.4/cmplxpack.c
index 4d9908c..bed4d8f 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/cmplxpack.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/cmplxpack.c
@@ -8,7 +8,7 @@ void cmplxpack(g2float *fld,g2int ndpts, g2int idrsnum,g2int *idrstmpl,
 //   PRGMMR: Gilbert          ORG: W/NP11    DATE: 2004-08-27
 //
 // ABSTRACT: This subroutine packs up a data field using a complex
-//   packing algorithm as defined in the GRIB2 documention.  It
+//   packing algorithm as defined in the GRIB2 documentation.  It
 //   supports GRIB2 complex packing templates with or without
 //   spatial differences (i.e. DRTs 5.2 and 5.3).
 //   It also fills in GRIB2 Data Representation Template 5.2 or 5.3 
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/compack.c b/frmts/grib/degrib18/g2clib-1.0.4/compack.c
index 4f9bd2c..bdd0340 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/compack.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/compack.c
@@ -11,7 +11,7 @@ void compack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
 //   PRGMMR: Gilbert          ORG: W/NP11    DATE: 2002-11-07
 //
 // ABSTRACT: This subroutine packs up a data field using a complex
-//   packing algorithm as defined in the GRIB2 documention.  It
+//   packing algorithm as defined in the GRIB2 documentation.  It
 //   supports GRIB2 complex packing templates with or without
 //   spatial differences (i.e. DRTs 5.2 and 5.3).
 //   It also fills in GRIB2 Data Representation Template 5.2 or 5.3 
@@ -64,7 +64,7 @@ void compack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
 //$$$
 {
 
-      static g2int zero=0;
+      const g2int zero=0;
       g2int  *ifld,*gref,*glen,*gwidth;
       g2int  *jmin, *jmax, *lbit;
       g2int  i,j,n, /* nbits, */ imin,imax,left;
@@ -76,9 +76,9 @@ void compack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
       g2int  kfildo, minpk, inc, maxgrps, ibit, jbit, kbit, novref, lbitref;
       g2int  missopt, miss1, miss2, ier;
       g2float  bscale,dscale,rmax,rmin,temp;
-      static g2int simple_alg = 0;
-      static g2float alog2=0.69314718;       //  ln(2.0)
-      static g2int one=1;
+      const g2int simple_alg = 0;
+      const g2float alog2=0.69314718;       //  ln(2.0)
+      const g2int one=1;
 
       bscale=int_power(2.0,-idrstmpl[1]);
       dscale=int_power(10.0,idrstmpl[2]);
@@ -121,7 +121,7 @@ void compack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
              ifld[j]=(g2int)RINT(((fld[j]*dscale)-rmin)*bscale);
         }
         //
-        //  Calculate Spatial differences, if using DRS Template 5.3
+        //  Calculate spatial differences, if using DRS Template 5.3.
         //
         if (idrsnum == 3) {        // spatial differences
            if (idrstmpl[16]!=1 && idrstmpl[16]!=2) idrstmpl[16]=1;
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/comunpack.c b/frmts/grib/degrib18/g2clib-1.0.4/comunpack.c
index ee650ef..40f5321 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/comunpack.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/comunpack.c
@@ -10,7 +10,7 @@ int comunpack(unsigned char *cpack,g2int lensec,g2int idrsnum,g2int *idrstmpl,g2
 //   PRGMMR: Gilbert          ORG: W/NP11    DATE: 2002-10-29
 //
 // ABSTRACT: This subroutine unpacks a data field that was packed using a
-//   complex packing algorithm as defined in the GRIB2 documention,
+//   complex packing algorithm as defined in the GRIB2 documentation,
 //   using info from the GRIB2 Data Representation Template 5.2 or 5.3.
 //   Supports GRIB2 complex packing templates with or without
 //   spatial differences (i.e. DRTs 5.2 and 5.3).
@@ -104,7 +104,7 @@ int comunpack(unsigned char *cpack,g2int lensec,g2int idrsnum,g2int *idrstmpl,g2
       
       //printf("RMISSs: %f %f %f \n",rmiss1,rmiss2,ref);
 // 
-//  Extract Spatial differencing values, if using DRS Template 5.3
+//  Extract spatial differencing values, if using DRS Template 5.3
 //
       if (idrsnum == 3) {
          if (nbitsd != 0) {
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/dec_jpeg2000.cpp b/frmts/grib/degrib18/g2clib-1.0.4/dec_jpeg2000.cpp
index 67e13f5..0f32c59 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/dec_jpeg2000.cpp
+++ b/frmts/grib/degrib18/g2clib-1.0.4/dec_jpeg2000.cpp
@@ -23,7 +23,7 @@
 #endif
 
 CPL_C_START
-// Cripes ... shouldn't this go in an include files!
+// Should this go in an include file?  Otherwise it should be static, correct?
 int dec_jpeg2000(char *injpc,g2int bufsize,g2int *outfld);
 CPL_C_END
 
@@ -34,7 +34,7 @@ int dec_jpeg2000(char *injpc,g2int bufsize,g2int *outfld)
 *   PRGMMR: Gilbert          ORG: W/NP11     DATE: 2002-12-02
 *
 * ABSTRACT: This Function decodes a JPEG2000 code stream specified in the
-*   JPEG2000 Part-1 standard (i.e., ISO/IEC 15444-1) using JasPer 
+*   JPEG2000 Part-1 standard (i.e., ISO/IEC 15444-1) using JasPer
 *   Software version 1.500.4 (or 1.700.2) written by the University of British
 *   Columbia and Image Power Inc, and others.
 *   JasPer is available at http://www.ece.uvic.ca/~mdadams/jasper/.
@@ -70,7 +70,7 @@ int dec_jpeg2000(char *injpc,g2int bufsize,g2int *outfld)
 {
 #ifndef HAVE_JASPER
     // J2K_SUBFILE method
-    
+
     // create "memory file" from buffer
     int fileNumber = 0;
     VSIStatBufL   sStatBuf;
@@ -81,14 +81,14 @@ int dec_jpeg2000(char *injpc,g2int bufsize,g2int *outfld)
         osFileName.Printf( "/vsimem/work%d.jpc", ++fileNumber );
     }
 
-    VSIFCloseL( VSIFileFromMemBuffer( 
-                    osFileName, (unsigned char*)injpc, bufsize, 
+    VSIFCloseL( VSIFileFromMemBuffer(
+                    osFileName, (unsigned char*)injpc, bufsize,
                     FALSE ) ); // TRUE to let vsi delete the buffer when done
 
-    // Open memory buffer for reading 
+    // Open memory buffer for reading
     GDALDataset* poJ2KDataset = (GDALDataset *)
         GDALOpen( osFileName, GA_ReadOnly );
- 
+
     if( poJ2KDataset == NULL )
     {
         printf("dec_jpeg2000: Unable to open JPEG2000 image within GRIB file.\n"
@@ -103,8 +103,8 @@ int dec_jpeg2000(char *injpc,g2int bufsize,g2int *outfld)
     }
 
     // Fulfill administration: initialize parameters required for RasterIO
-    int nXSize = poJ2KDataset->GetRasterXSize();
-    int nYSize = poJ2KDataset->GetRasterYSize();
+    const int nXSize = poJ2KDataset->GetRasterXSize();
+    const int nYSize = poJ2KDataset->GetRasterYSize();
     int nXOff = 0;
     int nYOff = 0;
     int nBufXSize = nXSize;
@@ -117,48 +117,46 @@ int dec_jpeg2000(char *injpc,g2int bufsize,g2int *outfld)
     int nBandSpace = 0;
 
     //    Decompress the JPEG2000 into the output integer array.
-    poJ2KDataset->RasterIO( GF_Read, nXOff, nYOff, nXSize, nYSize,
+    const CPLErr eErr = poJ2KDataset->RasterIO( GF_Read, nXOff, nYOff, nXSize, nYSize,
                             outfld, nBufXSize, nBufYSize, eBufType,
-                            nBandCount, panBandMap, 
+                            nBandCount, panBandMap,
                             nPixelSpace, nLineSpace, nBandSpace, NULL );
 
     // close source file, and "unlink" it.
     GDALClose( poJ2KDataset );
     VSIUnlink( osFileName );
 
-    return 0;
+    return (eErr == CE_None) ? 0 : -3;
 
-#else 
+#else
 
     // JasPer method
-    
-    int ier;
+
     g2int i,j,k;
-    jas_image_t *image=0;
+    jas_image_t *image=NULL;
     jas_stream_t *jpcstream;
     jas_image_cmpt_t *pcmpt;
-    char *opts=0;
+    char *opts=NULL;
     jas_matrix_t *data;
 
 //    jas_init();
 
-    ier=0;
-//   
+//
 //     Create jas_stream_t containing input JPEG200 codestream in memory.
-//       
+//
 
     jpcstream=jas_stream_memopen(injpc,bufsize);
 
-//   
+//
 //     Decode JPEG200 codestream into jas_image_t structure.
-//       
+//
 
     image=jpc_decode(jpcstream,opts);
-    if ( image == 0 ) {
-       printf(" jpc_decode return = %d \n",ier);
+    if ( image == NULL ) {
+       printf(" jpc_decode failed\n");
        return -3;
     }
-    
+
     pcmpt=image->cmpts_[0];
 
 //   Expecting jpeg2000 image to be grayscale only.
@@ -169,25 +167,25 @@ int dec_jpeg2000(char *injpc,g2int bufsize,g2int *outfld)
        return (-5);
     }
 
-// 
+//
 //    Create a data matrix of grayscale image values decoded from
 //    the jpeg2000 codestream.
 //
-    data=jas_matrix_create(jas_image_height(image), jas_image_width(image));
+    data=jas_matrix_create(static_cast<int>(jas_image_height(image)), static_cast<int>(jas_image_width(image)));
     jas_image_readcmpt(image,0,0,0,jas_image_width(image),
                        jas_image_height(image),data);
 //
 //    Copy data matrix to output integer array.
 //
     k=0;
-    for (i=0;i<pcmpt->height_;i++) 
-      for (j=0;j<pcmpt->width_;j++) 
-        outfld[k++]=data->rows_[i][j];
+    for (i=0;i<pcmpt->height_;i++)
+      for (j=0;j<pcmpt->width_;j++)
+        outfld[k++]=static_cast<g2int>(data->rows_[i][j]);
 //
 //     Clean up JasPer work structures.
 //
     jas_matrix_destroy(data);
-    ier=jas_stream_close(jpcstream);
+    jas_stream_close(jpcstream);
     jas_image_destroy(image);
 
     return 0;
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/dec_png.c b/frmts/grib/degrib18/g2clib-1.0.4/dec_png.c
index 4ae027c..86d476a 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/dec_png.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/dec_png.c
@@ -38,7 +38,7 @@ void user_read_data(png_structp png_ptr,png_bytep data, png_uint_32 length)
 
 int dec_png(unsigned char *pngbuf,g2int *width,g2int *height,char *cout)
 {
-    int interlace,color,compres,filter,bit_depth;
+    int interlace,color,compress,filter,bit_depth;
     g2int j,k,n,bytes,clen;
     png_structp png_ptr;
     png_infop info_ptr,end_info;
@@ -101,7 +101,7 @@ int dec_png(unsigned char *pngbuf,g2int *width,g2int *height,char *cout)
 
     /*printf("SAGT:png %d %d %d\n",info_ptr->width,info_ptr->height,info_ptr->bit_depth);*/
     (void)png_get_IHDR(png_ptr, info_ptr, (png_uint_32 *)width, (png_uint_32 *)height,
-               &bit_depth, &color, &interlace, &compres, &filter);
+               &bit_depth, &color, &interlace, &compress, &filter);
 
 /*     Check if image was grayscale      */
 
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/drstemplates.c b/frmts/grib/degrib18/g2clib-1.0.4/drstemplates.c
index 138c266..34f2bb5 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/drstemplates.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/drstemplates.c
@@ -60,16 +60,16 @@ g2int getdrsindex(g2int number)
 !
 !$$$*/
 {
-           g2int j,getdrsindex=-1;
+           g2int j,l_getdrsindex=-1;
 
            for (j=0;j<MAXDRSTEMP;j++) {
               if (number == templatesdrs[j].template_num) {
-                 getdrsindex=j;
-                 return(getdrsindex);
+                 l_getdrsindex=j;
+                 return(l_getdrsindex);
               }
            }
 
-           return(getdrsindex);
+           return(l_getdrsindex);
 }
 
 
@@ -105,18 +105,18 @@ xxtemplate *getdrstemplate(g2int number)
 !
 !$$$*/
 {
-           g2int index;
+           g2int l_index;
            xxtemplate *new;
 
-           index=getdrsindex(number);
+           l_index=getdrsindex(number);
 
-           if (index != -1) {
+           if (l_index != -1) {
               new=(xxtemplate *)malloc(sizeof(xxtemplate));
               new->type=5;
-              new->num=templatesdrs[index].template_num;
-              new->maplen=templatesdrs[index].mapdrslen;
-              new->needext=templatesdrs[index].needext;
-              new->map=(g2int *)templatesdrs[index].mapdrs;
+              new->num=templatesdrs[l_index].template_num;
+              new->maplen=templatesdrs[l_index].mapdrslen;
+              new->needext=templatesdrs[l_index].needext;
+              new->map=(g2int *)templatesdrs[l_index].mapdrs;
               new->extlen=0;
               new->ext=0;        //NULL
               return(new);
@@ -162,12 +162,13 @@ xxtemplate *extdrstemplate(g2int number,g2int *list)
 !$$$*/
 {
            xxtemplate *new;
-           g2int index,i;
+           g2int l_index,i;
 
-           index=getdrsindex(number);
-           if (index == -1) return(0);
+           l_index=getdrsindex(number);
+           if (l_index == -1) return(0);
 
            new=getdrstemplate(number);
+           if (new == NULL) return NULL;
 
            if ( ! new->needext ) return(new);
 
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/drstemplates.h b/frmts/grib/degrib18/g2clib-1.0.4/drstemplates.h
index 845586a..f35de99 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/drstemplates.h
+++ b/frmts/grib/degrib18/g2clib-1.0.4/drstemplates.h
@@ -1,12 +1,12 @@
-#ifndef _drstemplates_H
-#define _drstemplates_H
+#ifndef drstemplates_H
+#define drstemplates_H
 #include "grib2.h"
 
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-26
 //
 // ABSTRACT: This Fortran Module contains info on all the available 
 //   GRIB2 Data Representation Templates used in Section 5 (DRS).
-//   The information decribing each template is stored in the
+//   The information describing each template is stored in the
 //   drstemplate structure defined below.
 //
 //   Each Template has three parts: The number of entries in the template
@@ -42,7 +42,7 @@
           g2int mapdrs[MAXDRSMAPLEN];
       };
 
-const struct drstemplate *get_templatesdrs();
+const struct drstemplate *get_templatesdrs(void);
 g2int getdrsindex(g2int number);
 
-#endif  /*  _drstemplates_H  */
+#endif  /*  drstemplates_H  */
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/g2_addfield.c b/frmts/grib/degrib18/g2clib-1.0.4/g2_addfield.c
index 632bf48..b02dfbe 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/g2_addfield.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/g2_addfield.c
@@ -56,8 +56,8 @@ g2int g2_addfield(unsigned char *cgrib,g2int ipdsnum,g2int *ipdstmpl,
 //     ipdstmpl - Contains the data values for the specified Product Definition
 //                Template ( N=ipdsnum ).  Each element of this integer 
 //                array contains an entry (in the order specified) of Product
-//                Defintion Template 4.N
-//     coordlist- Array containg floating point values intended to document
+//                Definition Template 4.N
+//     coordlist- Array containing floating point values intended to document
 //                the vertical discretisation associated to model data
 //                on hybrid coordinate vertical levels.
 //     numcoord - number of values in array coordlist.
@@ -112,15 +112,14 @@ g2int g2_addfield(unsigned char *cgrib,g2int ipdsnum,g2int *ipdstmpl,
 //
 //$$$
 {
-      g2int ierr;
-      static unsigned char G=0x47;       // 'G'
-      static unsigned char R=0x52;       // 'R'
-      static unsigned char I=0x49;       // 'I'
-      static unsigned char B=0x42;       // 'B'
-      static unsigned char s7=0x37;   // '7'
+      const unsigned char G=0x47;       // 'G'
+      const unsigned char R=0x52;       // 'R'
+      const unsigned char I=0x49;       // 'I'
+      const unsigned char B=0x42;       // 'B'
+      const unsigned char s7=0x37;   // '7'
 
       unsigned char *cpack;
-      static g2int  zero=0,one=1,four=4,five=5,six=6,seven=7;
+      const g2int  zero=0,one=1,four=4,five=5,six=6,seven=7;
       const g2int  minsize=50000;
       g2int   iofst,ibeg,lencurr,len,nsize;
       g2int   ilen,isecnum,i,nbits,temp,left;
@@ -131,17 +130,15 @@ g2int g2_addfield(unsigned char *cgrib,g2int ipdsnum,g2int *ipdstmpl,
       g2int   width,height,iscan,itemp;
       g2float *pfld;
       xxtemplate  *mappds,*mapdrs;
-      unsigned int allones=4294967295u;
+      const unsigned int allones=4294967295u;
  
-      ierr=0;
 //
 //  Check to see if beginning of GRIB message exists
 //
       if ( cgrib[0]!=G || cgrib[1]!=R || cgrib[2]!=I || cgrib[3]!=B ) {
         printf("g2_addfield: GRIB not found in given message.\n");
-        printf("g2_addfield: Call to routine g2_create required to initialize GRIB messge.\n");
-        ierr=-1;
-        return(ierr);
+        printf("g2_addfield: Call to routine g2_create required to initialize GRIB message.\n");
+        return(-1);
       }
 //
 //  Get current length of GRIB message
@@ -153,8 +150,7 @@ g2int g2_addfield(unsigned char *cgrib,g2int ipdsnum,g2int *ipdstmpl,
       if ( cgrib[lencurr-4]==s7 && cgrib[lencurr-3]==s7 &&
            cgrib[lencurr-2]==s7 && cgrib[lencurr-1]==s7 ) {
         printf("g2_addfield: GRIB message already complete.  Cannot add new section.\n");
-        ierr=-2;
-        return(ierr);
+        return(-2);
       }
 //
 //  Loop through all current sections of the GRIB message to
@@ -178,7 +174,7 @@ g2int g2_addfield(unsigned char *cgrib,g2int ipdsnum,g2int *ipdstmpl,
       //  Check if a previous defined bitmap exists
         if (isecnum == 6) {
           gbit(cgrib,&ibmprev,iofst,8);
-          iofst=iofst+8;
+          /*iofst=iofst+8;*/
           if ((ibmprev >= 0) && (ibmprev <= 253)) isprevbmap=1;
         }
         len=len+ilen;
@@ -190,8 +186,7 @@ g2int g2_addfield(unsigned char *cgrib,g2int ipdsnum,g2int *ipdstmpl,
           printf("g2_addfield: Section byte counts don''t add to total.\n");
           printf("g2_addfield: Sum of section byte counts = %d\n",len);
           printf("g2_addfield: Total byte count in Section 0 = %d\n",lencurr);
-          ierr=-3;
-          return(ierr);
+          return(-3);
         }
       }
 //
@@ -200,8 +195,7 @@ g2int g2_addfield(unsigned char *cgrib,g2int ipdsnum,g2int *ipdstmpl,
       if ( (isecnum != 3) && (isecnum != 7) ) {
         printf("g2_addfield: Sections 4-7 can only be added after Section 3 or 7.\n");
         printf("g2_addfield: Section ',isecnum,' was the last found in given GRIB message.\n");
-        ierr=-4;
-        return(ierr);
+        return(-4);
 //
 //  Sections 4 through 7 can only be added if section 3 was previously defined.
 //
@@ -210,8 +204,7 @@ g2int g2_addfield(unsigned char *cgrib,g2int ipdsnum,g2int *ipdstmpl,
         printf("g2_addfield: Sections 4-7 can only be added if Section 3 was previously included.\n");
         printf("g2_addfield: Section 3 was not found in given GRIB message.\n");
         printf("g2_addfield: Call to routine addgrid required to specify Grid definition.\n");
-        ierr=-6;
-        return(ierr);
+        return(-6);
       }
 //
 //  Add Section 4  - Product Definition Section
@@ -229,8 +222,7 @@ g2int g2_addfield(unsigned char *cgrib,g2int ipdsnum,g2int *ipdstmpl,
       //
       mappds=getpdstemplate(ipdsnum);
       if (mappds == 0) {          // undefined template
-        ierr=-5;
-        return(ierr);
+        return(-5);
       }
       //
       //   Extend the Product Definition Template, if necessary.
@@ -300,8 +292,7 @@ g2int g2_addfield(unsigned char *cgrib,g2int ipdsnum,g2int *ipdstmpl,
       //
       mapdrs=getdrstemplate(idrsnum);
       if (mapdrs == 0) {
-        ierr=-5;
-        return(ierr);
+        return(-5);
       }
       //
       //  contract data field, removing data at invalid grid points,
@@ -370,7 +361,7 @@ g2int g2_addfield(unsigned char *cgrib,g2int ipdsnum,g2int *ipdstmpl,
               width=ndpts;
               height=1;
            }
-           else if ( width==allones || height==allones ) {
+           else if ( (unsigned int)width==allones || (unsigned int)height==allones ) {
               width=ndpts;
               height=1;
            }
@@ -389,16 +380,14 @@ g2int g2_addfield(unsigned char *cgrib,g2int ipdsnum,g2int *ipdstmpl,
 #endif  /* USE_PNG */
       else {
         printf("g2_addfield: Data Representation Template 5.%d not yet implemented.\n",idrsnum);
-        ierr=-7;
-        return(ierr);
+        return(-7);
       }
       if ( ibmap == 0 || ibmap==254 ) {      // free temp space
          if (fld != pfld) free(pfld);
       }
       if ( lcpack < 0 ) {
         if( cpack != 0 ) free(cpack);
-        ierr=-10;
-        return(ierr);
+        return(-10);
       }
 
 //
@@ -459,12 +448,11 @@ g2int g2_addfield(unsigned char *cgrib,g2int ipdsnum,g2int *ipdstmpl,
       if ((ibmap==254) && ( ! isprevbmap)) {
         printf("g2_addfield: Requested previously defined bitmap,");
         printf(" but one does not exist in the current GRIB message.\n");
-        ierr=-8;
-        return(ierr);
+        return(-8);
       }
       //
       //   Calculate length of section 6 and store it in octets
-      //   1-4 of section 6.  Pad to end of octect, if necessary.
+      //   1-4 of section 6.  Pad to end of octet, if necessary.
       //
       left=8-(iofst%8);
       if (left != 8) {
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/g2_addgrid.c b/frmts/grib/degrib18/g2clib-1.0.4/g2_addgrid.c
index 220d14d..7fdb274 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/g2_addgrid.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/g2_addgrid.c
@@ -39,7 +39,7 @@ g2int g2_addgrid(unsigned char *cgrib,g2int *igds,g2int *igdstmpl,g2int *ideflis
 //     igdstmpl - Contains the data values for the specified Grid Definition
 //                Template ( NN=igds[4] ).  Each element of this integer 
 //                array contains an entry (in the order specified) of Grid
-//                Defintion Template 3.NN
+//                Definition Template 3.NN
 //     ideflist - (Used if igds[2] != 0)  This array contains the
 //                number of grid points contained in each row ( or column )
 //      idefnum - (Used if igds[2] != 0)  The number of entries
@@ -71,27 +71,24 @@ g2int g2_addgrid(unsigned char *cgrib,g2int *igds,g2int *igdstmpl,g2int *ideflis
 //$$$
 {
 
-      g2int ierr;
-      static unsigned char G=0x47;       // 'G'
-      static unsigned char R=0x52;       // 'R'
-      static unsigned char I=0x49;       // 'I'
-      static unsigned char B=0x42;       // 'B'
-      static unsigned char seven=0x37;   // '7'
+      const unsigned char G=0x47;       // 'G'
+      const unsigned char R=0x52;       // 'R'
+      const unsigned char I=0x49;       // 'I'
+      const unsigned char B=0x42;       // 'B'
+      const unsigned char seven=0x37;   // '7'
 
-      static g2int one=1,three=3,miss=65535;
+      const g2int one=1,three=3,miss=65535;
       g2int   lensec3,iofst,ibeg,lencurr,len;
       g2int   i,j,temp,ilen,isecnum,nbits;
       xxtemplate *mapgrid=0;
  
-      ierr=0;
 //
 //  Check to see if beginning of GRIB message exists
 //
       if ( cgrib[0]!=G || cgrib[1]!=R || cgrib[2]!=I || cgrib[3]!=B ) {
         printf("g2_addgrid: GRIB not found in given message.\n");
-        printf("g2_addgrid: Call to routine gribcreate required to initialize GRIB messge.\n");
-        ierr=-1;
-        return(ierr);
+        printf("g2_addgrid: Call to routine gribcreate required to initialize GRIB message.\n");
+        return(-1);
       }
 //
 //  Get current length of GRIB message
@@ -103,8 +100,7 @@ g2int g2_addgrid(unsigned char *cgrib,g2int *igds,g2int *igdstmpl,g2int *ideflis
       if ( cgrib[lencurr-4]==seven && cgrib[lencurr-3]==seven &&
            cgrib[lencurr-2]==seven && cgrib[lencurr-1]==seven ) {
         printf("g2_addgrid: GRIB message already complete.  Cannot add new section.\n");
-        ierr=-2;
-        return(ierr);
+        return(-2);
       }
 //
 //  Loop through all current sections of the GRIB message to
@@ -126,8 +122,7 @@ g2int g2_addgrid(unsigned char *cgrib,g2int *igds,g2int *igdstmpl,g2int *ideflis
           printf("g2_addgrid: Section byte counts don''t add to total.\n");
           printf("g2_addgrid: Sum of section byte counts = %d\n",len);
           printf("g2_addgrid: Total byte count in Section 0 = %d\n",lencurr);
-          ierr=-3;
-          return(ierr);
+          return(-3);
         }
       }
 //
@@ -136,8 +131,7 @@ g2int g2_addgrid(unsigned char *cgrib,g2int *igds,g2int *igdstmpl,g2int *ideflis
       if ( (isecnum!=1) && (isecnum!=2) && (isecnum!=7) ) {
         printf("g2_addgrid: Section 3 can only be added after Section 1, 2 or 7.\n");
         printf("g2_addgrid: Section ',isecnum,' was the last found in given GRIB message.\n");
-        ierr=-4;
-        return(ierr);
+        return(-4);
       }
 //
 //  Add Section 3  - Grid Definition Section
@@ -167,8 +161,7 @@ g2int g2_addgrid(unsigned char *cgrib,g2int *igds,g2int *igdstmpl,g2int *ideflis
       if (igds[0] == 0) {
         mapgrid=getgridtemplate(igds[4]);
         if (mapgrid == 0) {       // undefined template
-          ierr=-5;
-          return(ierr);
+          return(-5);
         }
         //
         //   Extend the Grid Definition Template, if necessary.
@@ -181,6 +174,12 @@ g2int g2_addgrid(unsigned char *cgrib,g2int *igds,g2int *igdstmpl,g2int *ideflis
           mapgrid=extgridtemplate(igds[4],igdstmpl);
         }
       }
+
+      /* Added by GDAL to avoid 'potential null pointer dereference [-Wnull-dereference]' on below mapgrid->maplen */
+      if (mapgrid == 0) {       // undefined template
+        return(-5);
+      }
+
       //
       //   Pack up each input value in array igdstmpl into the
       //   the appropriate number of octets, which are specified in
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/g2_addlocal.c b/frmts/grib/degrib18/g2clib-1.0.4/g2_addlocal.c
index 7e0a15e..cf44c00 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/g2_addlocal.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/g2_addlocal.c
@@ -50,26 +50,23 @@ g2int g2_addlocal(unsigned char *cgrib,unsigned char *csec2,g2int lcsec2)
 //$$$
 {
 
-      g2int ierr; 
-      static unsigned char G=0x47;       // 'G'
-      static unsigned char R=0x52;       // 'R'
-      static unsigned char I=0x49;       // 'I'
-      static unsigned char B=0x42;       // 'B'
-      static unsigned char seven=0x37;   // '7'
+      const unsigned char G=0x47;       // 'G'
+      const unsigned char R=0x52;       // 'R'
+      const unsigned char I=0x49;       // 'I'
+      const unsigned char B=0x42;       // 'B'
+      const unsigned char seven=0x37;   // '7'
 
-      static g2int two=2;
+      const g2int two=2;
       g2int   j,k,lensec2,iofst,ibeg,lencurr,ilen,len,istart;
       g2int   isecnum;
- 
-      ierr=0;
+
 //
 //  Check to see if beginning of GRIB message exists
 //
       if ( cgrib[0]!=G || cgrib[1]!=R || cgrib[2]!=I || cgrib[3]!=B ) {
         printf("g2_addlocal: GRIB not found in given message.\n");
-        printf("g2_addlocal: Call to routine g2_create required to initialize GRIB messge.\n");
-        ierr=-1;
-        return(ierr);
+        printf("g2_addlocal: Call to routine g2_create required to initialize GRIB message.\n");
+        return(-1);
       }
 //
 //  Get current length of GRIB message
@@ -81,8 +78,7 @@ g2int g2_addlocal(unsigned char *cgrib,unsigned char *csec2,g2int lcsec2)
       if ( cgrib[lencurr-4]==seven && cgrib[lencurr-3]==seven && 
            cgrib[lencurr-2]==seven && cgrib[lencurr-1]==seven ) {
         printf("g2_addlocal: GRIB message already complete.  Cannot add new section.\n");
-        ierr=-2;
-        return(ierr);
+        return(-2);
       }
 //
 //  Loop through all current sections of the GRIB message to
@@ -104,8 +100,7 @@ g2int g2_addlocal(unsigned char *cgrib,unsigned char *csec2,g2int lcsec2)
           printf("g2_addlocal: Section byte counts don't add to total.\n");
           printf("g2_addlocal: Sum of section byte counts = %d\n",len);
           printf("g2_addlocal: Total byte count in Section 0 = %d\n",lencurr);
-          ierr=-3;
-          return(ierr);
+          return(-3);
         }
       }
 //
@@ -114,8 +109,7 @@ g2int g2_addlocal(unsigned char *cgrib,unsigned char *csec2,g2int lcsec2)
       if ( (isecnum!=1) && (isecnum!=7) ) {
         printf("g2_addlocal: Section 2 can only be added after Section 1 or Section 7.\n");
         printf("g2_addlocal: Section %d was the last found in given GRIB message.\n",isecnum);
-        ierr=-4;
-        return(ierr);
+        return(-4);
       }
 //
 //  Add Section 2  - Local Use Section
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/g2_create.c b/frmts/grib/degrib18/g2clib-1.0.4/g2_create.c
index 5791485..9944284 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/g2_create.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/g2_create.c
@@ -30,8 +30,8 @@ g2int g2_create(unsigned char *cgrib,g2int *listsec0,g2int *listsec1)
 //                listsec0[1]=GRIB Edition Number (currently 2)
 //     listsec1 - Contains information needed for GRIB Identification Section 1.
 //                Must be dimensioned >= 13.
-//                listsec1[0]=Id of orginating centre (Common Code Table C-1)
-//                listsec1[1]=Id of orginating sub-centre (local table)
+//                listsec1[0]=Id of originating centre (Common Code Table C-1)
+//                listsec1[1]=Id of originating sub-centre (local table)
 //                listsec1[2]=GRIB Master Tables Version Number (Code Table 1.0)
 //                listsec1[3]=GRIB Local Tables Version Number (Code Table 1.1)
 //                listsec1[4]=Significance of Reference Time (Code Table 1.2)
@@ -65,20 +65,17 @@ g2int g2_create(unsigned char *cgrib,g2int *listsec0,g2int *listsec1)
 //$$$
 {
 
-      g2int  ierr;
       g2int   zero=0,one=1;
       g2int   mapsec1len=MAPSEC1LEN;
       g2int   mapsec1[MAPSEC1LEN]={ 2,2,1,1,1,2,1,1,1,1,1,1,1 };
       g2int   i,lensec0,lensec1,iofst,ibeg,nbits,len;
 
-      ierr=0;
 //
 //  Currently handles only GRIB Edition 2.
 //  
       if (listsec0[1] != 2) {
         printf("g2_create: can only code GRIB edition 2.");
-        ierr=-1;
-        return (ierr);
+        return (-1);
       }
 //
 //  Pack Section 0 - Indicator Section 
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/g2_getfld.c b/frmts/grib/degrib18/g2clib-1.0.4/g2_getfld.c
index 9a68f19..2c1e81e 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/g2_getfld.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/g2_getfld.c
@@ -123,11 +123,11 @@ g2int g2_getfld(unsigned char *cgrib,g2int ifldnum,g2int unpack,g2int expand,
 //        gfld->igdtmpl  = Contains the data values for the specified Grid
 //                         Definition Template ( NN=gfld->igdtnum ).  Each
 //                         element of this integer array contains an entry (in
-//                         the order specified) of Grid Defintion Template 3.NN
+//                         the order specified) of Grid Definition Template 3.NN
 //                         This element is a pointer to an array
 //                         that holds the data.
 //        gfld->igdtlen = Number of elements in gfld->igdtmpl[].  i.e. number of
-//                       entries in Grid Defintion Template 3.NN
+//                       entries in Grid Definition Template 3.NN
 //                       ( NN=gfld->igdtnum ).
 //        gfld->list_opt  = (Used if gfld->numoct_opt .ne. 0)  This array
 //                          contains the number of grid points contained in
@@ -144,11 +144,11 @@ g2int g2_getfld(unsigned char *cgrib,g2int ifldnum,g2int unpack,g2int expand,
 //        gfld->ipdtmpl  = Contains the data values for the specified Product
 //                         Definition Template ( N=gfdl->ipdtnum ). Each element
 //                         of this integer array contains an entry (in the
-//                         order specified) of Product Defintion Template 4.N.
+//                         order specified) of Product Definition Template 4.N.
 //                         This element is a pointer to an array
 //                         that holds the data.
 //        gfld->ipdtlen = Number of elements in gfld->ipdtmpl[].  i.e. number of
-//                       entries in Product Defintion Template 4.N
+//                       entries in Product Definition Template 4.N
 //                       ( N=gfdl->ipdtnum ).
 //        gfld->coord_list  = Real array containing floating point values
 //                            intended to document the vertical discretisation
@@ -163,7 +163,7 @@ g2int g2_getfld(unsigned char *cgrib,g2int ifldnum,g2int unpack,g2int expand,
 //        gfld->idrtmpl  = Contains the data values for the specified Data
 //                         Representation Template ( N=gfld->idrtnum ).  Each
 //                         element of this integer array contains an entry
-//                         (in the order specified) of Product Defintion
+//                         (in the order specified) of Product Definition
 //                         Template 5.N.
 //                         This element is a pointer to an array
 //                         that holds the data.
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/g2_gribend.c b/frmts/grib/degrib18/g2clib-1.0.4/g2_gribend.c
index 4674beb..c6d838a 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/g2_gribend.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/g2_gribend.c
@@ -48,21 +48,19 @@ g2int g2_gribend(unsigned char *cgrib)
 {
 
       g2int iofst,lencurr,len,ilen,isecnum;
-      g2int   ierr,lengrib;
-      static unsigned char G=0x47;       // 'G'
-      static unsigned char R=0x52;       // 'R'
-      static unsigned char I=0x49;       // 'I'
-      static unsigned char B=0x42;       // 'B'
-      static unsigned char seven=0x37;   // '7'
+      g2int   lengrib;
+      const unsigned char G=0x47;       // 'G'
+      const unsigned char R=0x52;       // 'R'
+      const unsigned char I=0x49;       // 'I'
+      const unsigned char B=0x42;       // 'B'
+      const unsigned char seven=0x37;   // '7'
  
-      ierr=0;
 //
 //  Check to see if beginning of GRIB message exists
 //
       if ( cgrib[0]!=G || cgrib[1]!=R || cgrib[2]!=I || cgrib[3]!=B ) {
         printf("g2_gribend: GRIB not found in given message.\n");
-        ierr=-1;
-        return (ierr);
+        return (-1);
       }
 //
 //  Get current length of GRIB message
@@ -88,8 +86,7 @@ g2int g2_gribend(unsigned char *cgrib)
           printf("g2_gribend: Section byte counts don''t add to total.\n");
           printf("g2_gribend: Sum of section byte counts = %d\n",(int)len);
           printf("g2_gribend: Total byte count in Section 0 = %d\n",(int)lencurr);
-          ierr=-3;
-          return (ierr);
+          return (-3);
         }
       }
 //
@@ -98,8 +95,7 @@ g2int g2_gribend(unsigned char *cgrib)
       if ( isecnum != 7 ) {
         printf("g2_gribend: Section 8 can only be added after Section 7.\n");
         printf("g2_gribend: Section %d was the last found in given GRIB message.\n",isecnum);
-        ierr=-4;
-        return (ierr);
+        return (-4);
       }
 //
 //  Add Section 8  - End Section
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/g2_info.c b/frmts/grib/degrib18/g2clib-1.0.4/g2_info.c
index 738afe3..06bc156 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/g2_info.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/g2_info.c
@@ -34,8 +34,8 @@ g2int g2_info(unsigned char *cgrib,g2int *listsec0,g2int *listsec1,
 //     listsec1 - pointer to an array containing information read from GRIB 
 //                Identification Section 1.
 //                Must be allocated with >= 13 elements.
-//                listsec1[0]=Id of orginating centre (Common Code Table C-1)
-//                listsec1[1]=Id of orginating sub-centre (local table)
+//                listsec1[0]=Id of originating centre (Common Code Table C-1)
+//                listsec1[1]=Id of originating sub-centre (local table)
 //                listsec1[2]=GRIB Master Tables Version Number (Code Table 1.0)
 //                listsec1[3]=GRIB Local Tables Version Number 
 //                listsec1[4]=Significance of Reference Time (Code Table 1.1)
@@ -48,7 +48,7 @@ g2int g2_info(unsigned char *cgrib,g2int *listsec0,g2int *listsec1,
 //                listsec1[11]=Production status of data (Code Table 1.2)
 //                listsec1[12]=Type of processed data (Code Table 1.3)
 //     numfields- The number of gridded fields found in the GRIB message.
-//                That is, the number of occurences of Sections 4 - 7.
+//                That is, the number of occurrences of Sections 4 - 7.
 //     numlocal - The number of Local Use Sections ( Section 2 ) found in 
 //                the GRIB message.
 //
@@ -71,12 +71,11 @@ g2int g2_info(unsigned char *cgrib,g2int *listsec0,g2int *listsec1,
 //$$$
 {
  
-      g2int ierr,mapsec1len=13;
+      g2int mapsec1len=13;
       g2int mapsec1[13]={2,2,1,1,1,2,1,1,1,1,1,1,1};
       g2int  i,j,istart,iofst,lengrib,lensec0,lensec1;
       g2int ipos,isecnum,nbits,lensec;
 
-      ierr=0;
       *numlocal=0;
       *numfields=0;
 //
@@ -92,8 +91,7 @@ g2int g2_info(unsigned char *cgrib,g2int *listsec0,g2int *listsec1,
       }
       if (istart == -1) {
         printf("g2_info:  Beginning characters GRIB not found.");
-        ierr=1;
-        return(ierr);
+        return(1);
       }
 //
 //  Unpack Section 0 - Indicator Section 
@@ -114,8 +112,7 @@ g2int g2_info(unsigned char *cgrib,g2int *listsec0,g2int *listsec1,
 //  
       if (listsec0[1] != 2) {
         printf("g2_info: can only decode GRIB edition 2.");
-        ierr=2;
-        return(ierr);
+        return(2);
       }
 //
 //  Unpack Section 1 - Identification Section
@@ -126,8 +123,7 @@ g2int g2_info(unsigned char *cgrib,g2int *listsec0,g2int *listsec1,
       iofst=iofst+8;
       if (isecnum != 1) {
         printf("g2_info: Could not find section 1.");
-        ierr=3;
-        return(ierr);
+        return(3);
       }
       //
       //   Unpack each input value in array listsec1 into the
@@ -151,8 +147,7 @@ g2int g2_info(unsigned char *cgrib,g2int *listsec0,g2int *listsec1,
           ipos=ipos+4;
           if (ipos != (istart+lengrib)) {
             printf("g2_info: '7777' found, but not where expected.\n");
-            ierr=4;
-            return(ierr);
+            return(4);
           }
           break;
         }
@@ -161,12 +156,11 @@ g2int g2_info(unsigned char *cgrib,g2int *listsec0,g2int *listsec1,
         gbit(cgrib,&lensec,iofst,32);        // Get Length of Section
         iofst=iofst+32;
         gbit(cgrib,&isecnum,iofst,8);         // Get Section number
-        iofst=iofst+8;
+        /*iofst=iofst+8;*/
         ipos=ipos+lensec;                 // Update beginning of section pointer
         if (ipos > (istart+lengrib)) {
           printf("g2_info: '7777'  not found at end of GRIB message.\n");
-          ierr=5;
-          return(ierr);
+          return(5);
         }
         if ( isecnum>=2 && isecnum<=7 ) {
            if (isecnum == 2)      // Local Section 2
@@ -179,8 +173,7 @@ g2int g2_info(unsigned char *cgrib,g2int *listsec0,g2int *listsec1,
         }
         else {
            printf("g2_info: Invalid section number found in GRIB message: %d\n"                   ,isecnum);
-           ierr=6;
-           return(ierr);
+           return(6);
         }
         
       }
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/g2_miss.c b/frmts/grib/degrib18/g2clib-1.0.4/g2_miss.c
index 3dab744..dc10716 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/g2_miss.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/g2_miss.c
@@ -35,7 +35,7 @@ void g2_miss( gribfield *gfld, float *rmiss, int *nmiss )
     g2int     itype;    
 
     /*
-     *  Missing value management currnetly only used in
+     *  Missing value management currently only used in
      *  DRT's 5.2 and 5.3.
      */
     if ( gfld->idrtnum != 2  &&  gfld->idrtnum != 3 ) {
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack3.c b/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack3.c
index 911fc80..f9462aa 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack3.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack3.c
@@ -20,7 +20,7 @@ g2int g2_unpack3(unsigned char *cgrib,g2int *iofst,g2int **igds,g2int **igdstmpl
 //                          g2int **igdstmpl,g2int *mapgridlen,
 //                          g2int **ideflist,g2int *idefnum)
 //   INPUT ARGUMENTS:
-//     cgrib    - Char array ontaining Section 3 of the GRIB2 message
+//     cgrib    - Char array containing Section 3 of the GRIB2 message.
 //     iofst    - Bit offset for the beginning of Section 3 in cgrib.
 //
 //   OUTPUT ARGUMENTS:      
@@ -42,9 +42,9 @@ g2int g2_unpack3(unsigned char *cgrib,g2int *iofst,g2int **igds,g2int **igdstmpl
 //                the specified Grid Definition
 //                Template ( NN=igds[4] ).  Each element of this integer 
 //                array contains an entry (in the order specified) of Grid
-//                Defintion Template 3.NN
+//                Definition Template 3.NN
 //     mapgridlen- Number of elements in igdstmpl[].  i.e. number of entries
-//                in Grid Defintion Template 3.NN  ( NN=igds[4] ).
+//                in Grid Definition Template 3.NN  ( NN=igds[4] ).
 //     ideflist - (Used if igds[2] .ne. 0)  Pointer to integer array containing
 //                the number of grid points contained in each row ( or column ).
 //                (part of Section 3)
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack4.c b/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack4.c
index 8af7576..d0b6e9f 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack4.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack4.c
@@ -30,9 +30,9 @@ g2int g2_unpack4(unsigned char *cgrib,g2int *iofst,g2int *ipdsnum,g2int **ipdstm
 //                the specified Product Definition
 //                Template ( N=ipdsnum ).  Each element of this integer
 //                array contains an entry (in the order specified) of Product
-//                Defintion Template 4.N
+//                Definition Template 4.N
 //     mappdslen- Number of elements in ipdstmpl[].  i.e. number of entries
-//                in Product Defintion Template 4.N  ( N=ipdsnum ).
+//                in Product Definition Template 4.N  ( N=ipdsnum ).
 //     coordlist- Pointer to real array containing floating point values 
 //                intended to document
 //                the vertical discretisation associated to model data
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack7.c b/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack7.c
index f963653..c1125b6 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack7.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack7.c
@@ -4,11 +4,6 @@
 #include <string.h>
 #include "grib2.h"
 
-g2int simunpack(unsigned char *,g2int *, g2int,g2float *);
-int comunpack(unsigned char *,g2int,g2int,g2int *,g2int,g2float *);
-g2int specunpack(unsigned char *,g2int *,g2int,g2int,g2int, g2int, g2float *);
-g2int jpcunpack(unsigned char *,g2int,g2int *,g2int, g2float *);
-
 #ifdef USE_PNG
   g2int pngunpack(unsigned char *,g2int,g2int *,g2int, g2float *);
 #endif  /* USE_PNG */
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/gbits.c b/frmts/grib/degrib18/g2clib-1.0.4/gbits.c
index 34709da..ccee324 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/gbits.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/gbits.c
@@ -5,7 +5,7 @@ void gbit(unsigned char *in,g2int *iout,g2int iskip,g2int nbyte)
       gbits(in,iout,iskip,nbyte,(g2int)0,(g2int)1);
 }
 
-void sbit(unsigned char *out,g2int *in,g2int iskip,g2int nbyte)
+void sbit(unsigned char *out,const g2int *in,g2int iskip,g2int nbyte)
 {
       sbits(out,in,iskip,nbyte,(g2int)0,(g2int)1);
 }
@@ -26,34 +26,34 @@ void gbits(unsigned char *in,g2int *iout,g2int iskip,g2int nbyte,g2int nskip,
 */
 {
       g2int i,tbit,bitcnt,ibit,itmp;
-      g2int nbit,index;
-      static g2int ones[]={1,3,7,15,31,63,127,255};
+      g2int nbit,l_index;
+      static const g2int ones[]={1,3,7,15,31,63,127,255};
 
 //     nbit is the start position of the field in bits
       nbit = iskip;
       for (i=0;i<n;i++) {
          bitcnt = nbyte;
-         index=nbit/8;
+         l_index=nbit/8;
          ibit=nbit%8;
          nbit = nbit + nbyte + nskip;
 
 //        first byte
          tbit= ( bitcnt < (8-ibit) ) ? bitcnt : 8-ibit;  // find min
-         itmp = (int)*(in+index) & ones[7-ibit];
+         itmp = (int)*(in+l_index) & ones[7-ibit];
          if (tbit != 8-ibit) itmp >>= (8-ibit-tbit);
-         index++;
+         l_index++;
          bitcnt = bitcnt - tbit;
 
 //        now transfer whole bytes
          while (bitcnt >= 8) {
-             itmp = itmp<<8 | (int)*(in+index);
+             itmp = itmp<<8 | (int)*(in+l_index);
              bitcnt = bitcnt - 8;
-             index++;
+             l_index++;
          }
 
 //        get data from last byte
          if (bitcnt > 0) {
-             itmp = ( itmp << bitcnt ) | ( ((int)*(in+index) >> (8-bitcnt)) & ones[bitcnt-1] );
+             itmp = ( itmp << bitcnt ) | ( ((int)*(in+l_index) >> (8-bitcnt)) & ones[bitcnt-1] );
          }
 
          *(iout+i) = itmp;
@@ -61,7 +61,7 @@ void gbits(unsigned char *in,g2int *iout,g2int iskip,g2int nbyte,g2int nskip,
 }
 
 
-void sbits(unsigned char *out,g2int *in,g2int iskip,g2int nbyte,g2int nskip,
+void sbits(unsigned char *out,const g2int *in,g2int iskip,g2int nbyte,g2int nskip,
            g2int n)
 /*C          Store bits - pack bits:  Put arbitrary size values into a
 /          packed bit string, taking the low order bits from each value
@@ -76,8 +76,8 @@ void sbits(unsigned char *out,g2int *in,g2int iskip,g2int nbyte,g2int nskip,
 */
 {
       g2int i,bitcnt,tbit,ibit,itmp,imask,itmp2,itmp3;
-      g2int nbit,index;
-      static g2int ones[]={1,3,7,15,31,63,127,255};
+      g2int nbit,l_index;
+      static const g2int ones[]={1,3,7,15,31,63,127,255};
 
 //     number bits from zero to ...
 //     nbit is the last bit of the field to be filled
@@ -86,7 +86,7 @@ void sbits(unsigned char *out,g2int *in,g2int iskip,g2int nbyte,g2int nskip,
       for (i=0;i<n;i++) {
          itmp = *(in+i);
          bitcnt = nbyte;
-         index=nbit/8;
+         l_index=nbit/8;
          ibit=nbit%8;
          nbit = nbit + nbyte + nskip;
 
@@ -95,29 +95,29 @@ void sbits(unsigned char *out,g2int *in,g2int iskip,g2int nbyte,g2int nskip,
              tbit= ( bitcnt < (ibit+1) ) ? bitcnt : ibit+1;  // find min
              imask = ones[tbit-1] << (7-ibit);
              itmp2 = (itmp << (7-ibit)) & imask;
-             itmp3 = (int)*(out+index) & (255-imask);
-             out[index] = (unsigned char)(itmp2 | itmp3);
+             itmp3 = (int)*(out+l_index) & (255-imask);
+             out[l_index] = (unsigned char)(itmp2 | itmp3);
              bitcnt = bitcnt - tbit;
              itmp = itmp >> tbit;
-             index--;
+             l_index--;
          }
 
 //        now byte aligned
 
 //        do by bytes
          while (bitcnt >= 8) {
-             out[index] = (unsigned char)(itmp & 255);
+             out[l_index] = (unsigned char)(itmp & 255);
              itmp = itmp >> 8;
              bitcnt = bitcnt - 8;
-             index--;
+             l_index--;
          }
 
 //        do last byte
 
          if (bitcnt > 0) {
              itmp2 = itmp & ones[bitcnt-1];
-             itmp3 = (int)*(out+index) & (255-ones[bitcnt-1]);
-             out[index] = (unsigned char)(itmp2 | itmp3);
+             itmp3 = (int)*(out+l_index) & (255-ones[bitcnt-1]);
+             out[l_index] = (unsigned char)(itmp2 | itmp3);
          }
       }
 
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/getdim.c b/frmts/grib/degrib18/g2clib-1.0.4/getdim.c
index c86228f..318184e 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/getdim.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/getdim.c
@@ -2,9 +2,6 @@
 #include <stdlib.h>
 #include "grib2.h"
 
-g2int g2_unpack3(unsigned char *,g2int *,g2int **,g2int **,
-                         g2int *,g2int **,g2int *);
-
 g2int getdim(unsigned char *csec3,g2int *width,g2int *height,g2int *iscan)
 //$$$  SUBPROGRAM DOCUMENTATION BLOCK
 //                .      .    .                                       .
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/getpoly.c b/frmts/grib/degrib18/g2clib-1.0.4/getpoly.c
index 9e2a5a6..e60d05c 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/getpoly.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/getpoly.c
@@ -2,9 +2,6 @@
 #include <stdlib.h>
 #include "grib2.h"
 
-g2int g2_unpack3(unsigned char *,g2int *,g2int **,g2int **,
-                         g2int *,g2int **,g2int *);
-
 g2int getpoly(unsigned char *csec3,g2int *jj,g2int *kk,g2int *mm)
 //$$$  SUBPROGRAM DOCUMENTATION BLOCK
 //                .      .    .                                       .
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/grib2.h b/frmts/grib/degrib18/g2clib-1.0.4/grib2.h
index 810e7d6..e5fe610 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/grib2.h
+++ b/frmts/grib/degrib18/g2clib-1.0.4/grib2.h
@@ -1,5 +1,5 @@
-#ifndef _grib2_H
-#define _grib2_H
+#ifndef grib2_H
+#define grib2_H
 #include<stdio.h>
 
 #define G2_VERSION "g2clib-1.0.4"
@@ -75,11 +75,11 @@
 //        gfld->igdtmpl  = Contains the data values for the specified Grid
 //                         Definition Template ( NN=gfld->igdtnum ).  Each
 //                         element of this integer array contains an entry (in
-//                         the order specified) of Grid Defintion Template 3.NN
+//                         the order specified) of Grid Definition Template 3.NN
 //                         This element is a pointer to an array
 //                         that holds the data.
 //        gfld->igdtlen = Number of elements in gfld->igdtmpl[].  i.e. number of
-//                       entries in Grid Defintion Template 3.NN
+//                       entries in Grid Definition Template 3.NN
 //                       ( NN=gfld->igdtnum ).
 //        gfld->list_opt  = (Used if gfld->numoct_opt .ne. 0)  This array
 //                          contains the number of grid points contained in
@@ -95,11 +95,11 @@
 //        gfld->ipdtmpl  = Contains the data values for the specified Product
 //                         Definition Template ( N=gfdl->ipdtnum ).  Each element
 //                         of this integer array contains an entry (in the
-//                         order specified) of Product Defintion Template 4.N.
+//                         order specified) of Product Definition Template 4.N.
 //                         This element is a pointer to an array
 //                         that holds the data.
 //        gfld->ipdtlen = Number of elements in gfld->ipdtmpl[].  i.e. number of
-//                       entries in Product Defintion Template 4.N
+//                       entries in Product Definition Template 4.N
 //                       ( N=gfdl->ipdtnum ).
 //        gfld->coord_list  = Real array containing floating point values
 //                            intended to document the vertical discretisation
@@ -114,7 +114,7 @@
 //        gfld->idrtmpl  = Contains the data values for the specified Data
 //                         Representation Template ( N=gfld->idrtnum ).  Each
 //                         element of this integer array contains an entry
-//                         (in the order specified) of Product Defintion
+//                         (in the order specified) of Product Definition
 //                         Template 5.N.
 //                         This element is a pointer to an array
 //                         that holds the data.
@@ -152,8 +152,8 @@ typedef unsigned int g2intu;
 typedef float g2float;
 
 typedef struct {
-   g2int type;           /* 3=Grid Defintion Template.                       */
-                         /* 4=Product Defintion Template.                    */
+   g2int type;           /* 3=Grid Definition Template.                       */
+                         /* 4=Product Definition Template.                    */
                          /* 5=Data Representation Template.                  */
    g2int num;            /* template number.                                 */
    g2int maplen;         /* number of entries in the static part             */
@@ -227,9 +227,9 @@ extern void simpack(g2float *,g2int,g2int *,unsigned char *,g2int *);
 extern void compack(g2float *,g2int,g2int,g2int *,unsigned char *,g2int *);
 void misspack(g2float *,g2int ,g2int ,g2int *, unsigned char *, g2int *);
 void gbit(unsigned char *,g2int *,g2int ,g2int );
-void sbit(unsigned char *,g2int *,g2int ,g2int );
+void sbit(unsigned char *,const g2int *,g2int ,g2int );
 void gbits(unsigned char *,g2int *,g2int ,g2int ,g2int ,g2int );
-void sbits(unsigned char *,g2int *,g2int ,g2int ,g2int ,g2int );
+void sbits(unsigned char *,const g2int *,g2int ,g2int ,g2int ,g2int );
 
 int pack_gp(g2int *, g2int *, g2int *,
             g2int *, g2int *, g2int *, g2int *, g2int *,
@@ -237,5 +237,41 @@ int pack_gp(g2int *, g2int *, g2int *,
             g2int *, g2int *, g2int *, g2int *, g2int *,
             g2int *, g2int *, g2int *);
 
-#endif  /*  _grib2_H  */
+g2int g2_unpack1(unsigned char *cgrib,g2int *iofst,g2int **ids,g2int *idslen);
+g2int g2_unpack2(unsigned char *cgrib,g2int *iofst,g2int *lencsec2,unsigned char **csec2);
+g2int g2_unpack3(unsigned char *cgrib,g2int *iofst,g2int **igds,g2int **igdstmpl,
+                         g2int *mapgridlen,g2int **ideflist,g2int *idefnum);
+g2int g2_unpack4(unsigned char *cgrib,g2int *iofst,g2int *ipdsnum,g2int **ipdstmpl,
+               g2int *mappdslen,g2float **coordlist,g2int *numcoord);
+g2int g2_unpack5(unsigned char *cgrib,g2int *iofst,g2int *ndpts,g2int *idrsnum,
+               g2int **idrstmpl,g2int *mapdrslen);
+g2int g2_unpack6(unsigned char *cgrib,g2int *iofst,g2int ngpts,g2int *ibmap,
+               g2int **bmap);
+g2int g2_unpack7(unsigned char *cgrib,g2int *iofst,g2int igdsnum,g2int *igdstmpl,
+               g2int idrsnum,g2int *idrstmpl,g2int ndpts,g2float **fld);
+g2int simunpack(unsigned char *,g2int *, g2int,g2float *);
+int comunpack(unsigned char *,g2int,g2int,g2int *,g2int,g2float *);
+g2int specunpack(unsigned char *,g2int *,g2int,g2int,g2int, g2int, g2float *);
+g2int jpcunpack(unsigned char *,g2int,g2int *,g2int, g2float *);
+void specpack(g2float *fld,g2int ndpts,g2int JJ,g2int KK,g2int MM,
+              g2int *idrstmpl,unsigned char *cpack,g2int *lcpack);
+
+typedef g2int integer;
+typedef g2float real;
+int reduce(integer *kfildo, integer *jmin, integer *jmax,
+        integer *lbit, integer *nov, integer *lx, integer *ndg, integer *ibit,
+         integer *jbit, integer *kbit, integer *novref, integer *ibxx2,
+        integer *ier);
+void cmplxpack(g2float *fld,g2int ndpts, g2int idrsnum,g2int *idrstmpl,
+               unsigned char *cpack, g2int *lcpack);
+g2int getdim(unsigned char *csec3,g2int *width,g2int *height,g2int *iscan);
+void g2_miss( gribfield *gfld, float *rmiss, int *nmiss );
+g2int getpoly(unsigned char *csec3,g2int *jj,g2int *kk,g2int *mm);
+void jpcpack(g2float *fld,g2int width,g2int height,g2int *idrstmpl,
+             unsigned char *cpack,g2int *lcpack);
+int enc_jpeg2000(unsigned char *cin,g2int width,g2int height,g2int nbits,
+                 g2int ltype, g2int ratio, g2int retry, char *outjpc, 
+                 g2int jpclen);
+
+#endif  /*  grib2_H  */
 
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/grib2c.doc b/frmts/grib/degrib18/g2clib-1.0.4/grib2c.doc
index 4ad7c34..104375e 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/grib2c.doc
+++ b/frmts/grib/degrib18/g2clib-1.0.4/grib2c.doc
@@ -66,7 +66,7 @@ Routine g2_addlocal can be used to add a Local Use Section ( Section 2 ).
 Note that this section is optional and need not appear in a GRIB2 message.
 
 Function g2_addgrid is used to encode a grid definition into Section 3.
-This grid definition defines the geometry of the the data values in the
+This grid definition defines the geometry of the data values in the
 fields that follow it.  g2_addgrid can be called again to change the grid 
 definition describing subsequent data fields.
 
@@ -230,11 +230,11 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //        gfld->igdtmpl  = Contains the data values for the specified Grid
 //                         Definition Template ( NN=gfld->igdtnum ).  Each
 //                         element of this integer array contains an entry (in
-//                         the order specified) of Grid Defintion Template 3.NN
+//                         the order specified) of Grid Definition Template 3.NN
 //                         This element is a pointer to an array
 //                         that holds the data.
 //        gfld->igdtlen = Number of elements in gfld->igdtmpl[].  i.e. number of
-//                       entries in Grid Defintion Template 3.NN
+//                       entries in Grid Definition Template 3.NN
 //                       ( NN=gfld->igdtnum ).
 //        gfld->list_opt  = (Used if gfld->numoct_opt .ne. 0)  This array
 //                          contains the number of grid points contained in
@@ -251,11 +251,11 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //        gfld->ipdtmpl  = Contains the data values for the specified Product
 //                         Definition Template ( N=gfdl->ipdtnum ). Each element
 //                         of this integer array contains an entry (in the
-//                         order specified) of Product Defintion Template 4.N.
+//                         order specified) of Product Definition Template 4.N.
 //                         This element is a pointer to an array
 //                         that holds the data.
 //        gfld->ipdtlen = Number of elements in gfld->ipdtmpl[].  i.e. number of
-//                       entries in Product Defintion Template 4.N
+//                       entries in Product Definition Template 4.N
 //                       ( N=gfdl->ipdtnum ).
 //        gfld->coord_list  = Real array containing floating point values
 //                            intended to document the vertical discretisation
@@ -270,7 +270,7 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //        gfld->idrtmpl  = Contains the data values for the specified Data
 //                         Representation Template ( N=gfld->idrtnum ).  Each
 //                         element of this integer array contains an entry
-//                         (in the order specified) of Product Defintion
+//                         (in the order specified) of Product Definition
 //                         Template 5.N.
 //                         This element is a pointer to an array
 //                         that holds the data.
@@ -328,7 +328,7 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //     iseek      - number of bytes in the file to skip before search
 //     mseek      - number of bytes to search at a time
 //   OUTPUT ARGUMENTS:
-//     lskip      - number of bytes to skip from the beggining of the file
+//     lskip      - number of bytes to skip from the beginning of the file
 //                  to where the GRIB message starts
 //     lgrib      - number of bytes in message (set to 0, if no message found)
 //
@@ -369,8 +369,8 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //     listsec1 - pointer to an array containing information read from GRIB 
 //                Identification Section 1.
 //                Must be allocated with >= 13 elements.
-//                listsec1[0]=Id of orginating centre (Common Code Table C-1)
-//                listsec1[1]=Id of orginating sub-centre (local table)
+//                listsec1[0]=Id of originating centre (Common Code Table C-1)
+//                listsec1[1]=Id of originating sub-centre (local table)
 //                listsec1[2]=GRIB Master Tables Version Number (Code Table 1.0)
 //                listsec1[3]=GRIB Local Tables Version Number 
 //                listsec1[4]=Significance of Reference Time (Code Table 1.1)
@@ -383,7 +383,7 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //                listsec1[11]=Production status of data (Code Table 1.2)
 //                listsec1[12]=Type of processed data (Code Table 1.3)
 //     numfields- The number of gridded fields found in the GRIB message.
-//                That is, the number of occurences of Sections 4 - 7.
+//                That is, the number of occurrences of Sections 4 - 7.
 //     numlocal - The number of Local Use Sections ( Section 2 ) found in 
 //                the GRIB message.
 //
@@ -515,11 +515,11 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //        gfld->igdtmpl  = Contains the data values for the specified Grid
 //                         Definition Template ( NN=gfld->igdtnum ).  Each
 //                         element of this integer array contains an entry (in
-//                         the order specified) of Grid Defintion Template 3.NN
+//                         the order specified) of Grid Definition Template 3.NN
 //                         This element is a pointer to an array
 //                         that holds the data.
 //        gfld->igdtlen = Number of elements in gfld->igdtmpl[].  i.e. number of
-//                       entries in Grid Defintion Template 3.NN
+//                       entries in Grid Definition Template 3.NN
 //                       ( NN=gfld->igdtnum ).
 //        gfld->list_opt  = (Used if gfld->numoct_opt .ne. 0)  This array
 //                          contains the number of grid points contained in
@@ -536,11 +536,11 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //        gfld->ipdtmpl  = Contains the data values for the specified Product
 //                         Definition Template ( N=gfdl->ipdtnum ). Each element
 //                         of this integer array contains an entry (in the
-//                         order specified) of Product Defintion Template 4.N.
+//                         order specified) of Product Definition Template 4.N.
 //                         This element is a pointer to an array
 //                         that holds the data.
 //        gfld->ipdtlen = Number of elements in gfld->ipdtmpl[].  i.e. number of
-//                       entries in Product Defintion Template 4.N
+//                       entries in Product Definition Template 4.N
 //                       ( N=gfdl->ipdtnum ).
 //        gfld->coord_list  = Real array containing floating point values
 //                            intended to document the vertical discretisation
@@ -555,7 +555,7 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //        gfld->idrtmpl  = Contains the data values for the specified Data
 //                         Representation Template ( N=gfld->idrtnum ).  Each
 //                         element of this integer array contains an entry
-//                         (in the order specified) of Product Defintion
+//                         (in the order specified) of Product Definition
 //                         Template 5.N.
 //                         This element is a pointer to an array
 //                         that holds the data.
@@ -783,7 +783,7 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //     igdstmpl - Contains the data values for the specified Grid Definition
 //                Template ( NN=igds[4] ).  Each element of this integer 
 //                array contains an entry (in the order specified) of Grid
-//                Defintion Template 3.NN
+//                Definition Template 3.NN
 //     ideflist - (Used if igds[2] != 0)  This array contains the
 //                number of grid points contained in each row ( or column )
 //      idefnum - (Used if igds[2] != 0)  The number of entries
@@ -846,8 +846,8 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //     ipdstmpl - Contains the data values for the specified Product Definition
 //                Template ( N=ipdsnum ).  Each element of this integer 
 //                array contains an entry (in the order specified) of Product
-//                Defintion Template 4.N
-//     coordlist- Array containg floating point values intended to document
+//                Definition Template 4.N
+//     coordlist- Array containing floating point values intended to document
 //                the vertical discretisation associated to model data
 //                on hybrid coordinate vertical levels.
 //     numcoord - number of values in array coordlist.
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/gridtemplates.c b/frmts/grib/degrib18/g2clib-1.0.4/gridtemplates.c
index 9bf4261..3940f94 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/gridtemplates.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/gridtemplates.c
@@ -23,7 +23,7 @@ static const struct gridtemplate templatesgrid[MAXGRIDTEMP] = {
          {30, 22, 0, {1,1,4,1,4,1,4,4,4,-4,-4,1,-4,-4,4,4,1,1,-4,-4,-4,-4} },
              // 3.31: Albers equal area
          {31, 22, 0, {1,1,4,1,4,1,4,4,4,-4,4,1,-4,4,4,4,1,1,-4,-4,-4,4} },
-             // 3.40: Guassian Lat/Lon
+             // 3.40: Gaussian Lat/Lon
          {40, 19, 0, {1,1,4,1,4,1,4,4,4,4,4,-4,4,1,-4,4,4,4,1} },
              // 3.41: Rotated Gaussian Lat/Lon
          {41, 22, 0, {1,1,4,1,4,1,4,4,4,4,4,-4,4,1,-4,4,4,4,1,-4,4,4} },
@@ -90,16 +90,16 @@ g2int getgridindex(g2int number)
 !
 !$$$*/
 {
-           g2int j,getgridindex=-1;
+           g2int j,l_getgridindex=-1;
 
            for (j=0;j<MAXGRIDTEMP;j++) {
               if (number == templatesgrid[j].template_num) {
-                 getgridindex=j;
-                 return(getgridindex);
+                 l_getgridindex=j;
+                 return(l_getgridindex);
               }
            }
 
-           return(getgridindex);
+           return(l_getgridindex);
 }
 
 xxtemplate *getgridtemplate(g2int number)
@@ -134,18 +134,18 @@ xxtemplate *getgridtemplate(g2int number)
 !
 !$$$*/
 {
-           g2int index;
+           g2int l_index;
            xxtemplate *new;
 
-           index=getgridindex(number);
+           l_index=getgridindex(number);
 
-           if (index != -1) {
+           if (l_index != -1) {
               new=(xxtemplate *)malloc(sizeof(xxtemplate));
               new->type=3;
-              new->num=templatesgrid[index].template_num;
-              new->maplen=templatesgrid[index].mapgridlen;
-              new->needext=templatesgrid[index].needext;
-              new->map=(g2int *)templatesgrid[index].mapgrid;
+              new->num=templatesgrid[l_index].template_num;
+              new->maplen=templatesgrid[l_index].mapgridlen;
+              new->needext=templatesgrid[l_index].needext;
+              new->map=(g2int *)templatesgrid[l_index].mapgrid;
               new->extlen=0;
               new->ext=0;        //NULL
               return(new);
@@ -192,12 +192,13 @@ xxtemplate *extgridtemplate(g2int number,g2int *list)
 !$$$*/
 {
            xxtemplate *new;
-           g2int index,i;
+           g2int l_index,i;
 
-           index=getgridindex(number);
-           if (index == -1) return(0);
+           l_index=getgridindex(number);
+           if (l_index == -1) return(0);
 
            new=getgridtemplate(number);
+           if( new == NULL ) return(NULL);
 
            if ( ! new->needext ) return(new);
 
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/gridtemplates.h b/frmts/grib/degrib18/g2clib-1.0.4/gridtemplates.h
index 8cd8cac..ba4ebef 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/gridtemplates.h
+++ b/frmts/grib/degrib18/g2clib-1.0.4/gridtemplates.h
@@ -1,12 +1,12 @@
-#ifndef _gridtemplates_H
-#define _gridtemplates_H
+#ifndef gridtemplates_H
+#define gridtemplates_H
 #include "grib2.h"
 
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2001-10-26
 //
 // ABSTRACT: This Fortran Module contains info on all the available 
 //   GRIB2 Grid Definition Templates used in Section 3 (GDS).
-//   The information decribing each template is stored in the
+//   The information describing each template is stored in the
 //   gridtemplate structure defined below.
 //
 //   Each Template has three parts: The number of entries in the template
@@ -43,7 +43,7 @@
       };
 
 
-const struct gridtemplate *get_templatesgrid();
+const struct gridtemplate *get_templatesgrid(void);
 g2int getgridindex(g2int number);
 
-#endif  /*  _gridtemplates_H  */
+#endif  /*  gridtemplates_H  */
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/jpcpack.c b/frmts/grib/degrib18/g2clib-1.0.4/jpcpack.c
index 272358d..b55e3af 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/jpcpack.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/jpcpack.c
@@ -2,9 +2,6 @@
 #include <math.h>
 #include "grib2.h"
 
-int enc_jpeg2000(unsigned char *,g2int ,g2int ,g2int ,
-                 g2int , g2int, g2int , char *, g2int );
-
 void jpcpack(g2float *fld,g2int width,g2int height,g2int *idrstmpl,
              unsigned char *cpack,g2int *lcpack)
 //$$$  SUBPROGRAM DOCUMENTATION BLOCK
@@ -72,7 +69,7 @@ void jpcpack(g2float *fld,g2int width,g2int height,g2int *idrstmpl,
 //$$$
 {
       g2int  *ifld;
-      static g2float alog2=0.69314718;       //  ln(2.0)
+      const g2float alog2=0.69314718;       //  ln(2.0)
       g2int  j,nbits,imin,imax,maxdif;
       g2int  ndpts,nbytes,nsize,retry;
       g2float  bscale,dscale,rmax,rmin,temp;
@@ -109,7 +106,7 @@ void jpcpack(g2float *fld,g2int width,g2int height,g2int *idrstmpl,
         //
         if (idrstmpl[1] == 0) {
            //
-           //  No binary scaling and calculate minumum number of 
+           //  No binary scaling and calculate minimum number of
            //  bits in which the data will fit.
            //
            imin=(g2int)RINT(rmin*dscale);
@@ -124,7 +121,7 @@ void jpcpack(g2float *fld,g2int width,g2int height,g2int *idrstmpl,
         }
         else {
            //
-           //  Use binary scaling factor and calculate minumum number of 
+           //  Use binary scaling factor and calculate minimum number of 
            //  bits in which the data will fit.
            //
            rmin=rmin*dscale;
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/jpcunpack.c b/frmts/grib/degrib18/g2clib-1.0.4/jpcunpack.c
index 6fbecbf..006652f 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/jpcunpack.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/jpcunpack.c
@@ -55,7 +55,8 @@ g2int jpcunpack(unsigned char *cpack,g2int len,g2int *idrstmpl,g2int ndpts,
 
          ifld=(g2int *)calloc(ndpts,sizeof(g2int));
          if ( ifld == 0 ) {
-            fprintf(stderr,"Could not allocate space in jpcunpack.\n  Data field NOT upacked.\n");
+            fprintf(stderr, "Could not allocate space in jpcunpack.\n"
+                    "Data field NOT unpacked.\n");
             return(1);
          }
          /* iret= (g2int) */ dec_jpeg2000((char *) cpack,len,ifld);
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/misspack.c b/frmts/grib/degrib18/g2clib-1.0.4/misspack.c
index d79a5f3..1b5b754 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/misspack.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/misspack.c
@@ -10,7 +10,7 @@ void misspack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
 //   PRGMMR: Gilbert          ORG: W/NP11    DATE: 2000-06-21
 //
 // ABSTRACT: This subroutine packs up a data field using a complex
-//   packing algorithm as defined in the GRIB2 documention.  It
+//   packing algorithm as defined in the GRIB2 documentation.  It
 //   supports GRIB2 complex packing templates with or without
 //   spatial differences (i.e. DRTs 5.2 and 5.3).
 //   It also fills in GRIB2 Data Representation Template 5.2 or 5.3 
@@ -66,7 +66,7 @@ void misspack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
 
       g2int  *ifld, *ifldmiss, *jfld;
       g2int  *jmin, *jmax, *lbit;
-      static g2int zero=0;
+      const g2int zero=0;
       g2int  *gref, *gwidth, *glen;
       g2int  glength, grpwidth;
       g2int  i, n, iofst, imin, ival1, ival2, isd, minsd, nbitsd = 0;
@@ -77,9 +77,9 @@ void misspack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
       g2int  imax, lg, mtemp, ier, igmax;
       g2int  kfildo, minpk, inc, maxgrps, ibit, jbit, kbit, novref, lbitref;
       g2float  rmissp, rmisss, bscale, dscale, rmin, temp;
-      static g2int simple_alg = 0;
-      static g2float alog2=0.69314718;       //  ln(2.0)
-      static g2int one=1;
+      const g2int simple_alg = 0;
+      const g2float alog2=0.69314718;       //  ln(2.0)
+      const g2int one=1;
 
       bscale=int_power(2.0,-idrstmpl[1]);
       dscale=int_power(10.0,idrstmpl[2]);
@@ -128,7 +128,7 @@ void misspack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
 //  Allocate work arrays:
 //  Note: -ifldmiss[j],j=0,ndpts-1 is a map of original field indicating 
 //         which of the original data values
-//         are primary missing (1), sencondary missing (2) or non-missing (0).
+//         are primary missing (1), secondary missing (2) or non-missing (0).
 //        -jfld[j],j=0,nonmiss-1 is a subarray of just the non-missing values 
 //         from the original field.
 //
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/pack_gp.c b/frmts/grib/degrib18/g2clib-1.0.4/pack_gp.c
index 2eaa00e..969de58 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/pack_gp.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/pack_gp.c
@@ -13,7 +13,6 @@
 /*#include "f2c.h"*/
 #include <stdlib.h>
 #include "grib2.h"
-typedef g2int integer;
 typedef g2int logical;
 #define TRUE_ (1)
 #define FALSE_ (0)
@@ -282,13 +281,13 @@ typedef g2int logical;
 /*                       AND A MINIMUM THAT HAS BEEN SET TO ZERO WHEN */
 /*                       ALL VALUES ARE MISSING.  0 OTHERWISE. */
 /*                       NOTE THAT THIS DOES NOT DISTINGUISH BETWEEN */
-/*                       PRIMARY AND SECONDARY MISSINGS WHEN SECONDARY */
-/*                       MISSINGS ARE PRESENT.  THIS MEANS THAT */
+/*                       PRIMARY AND SECONDARY MISSING WHEN SECONDARY */
+/*                       MISSING ARE PRESENT.  THIS MEANS THAT */
 /*                       LBIT( ) WILL NOT BE ZERO WITH THE RESULTING */
-/*                       COMPRESSION EFFICIENCY WHEN SECONDARY MISSINGS */
+/*                       COMPRESSION EFFICIENCY WHEN SECONDARY MISSING */
 /*                       ARE PRESENT.  ALSO NOTE THAT A CHECK HAS BEEN */
 /*                       MADE EARLIER TO DETERMINE THAT SECONDARY */
-/*                       MISSINGS ARE REALLY THERE. */
+/*                       MISSING ARE REALLY THERE. */
 /*              MISLLB = SET TO 1 WHEN ALL VALUES IN GROUP B ARE MISSING. */
 /*                       THIS IS USED TO DISTINGUISH BETWEEN A REAL */
 /*                       MINIMUM WHEN ALL VALUES ARE NOT MISSING */
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/pdstemplates.c b/frmts/grib/degrib18/g2clib-1.0.4/pdstemplates.c
index ec9651f..e0ce6af 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/pdstemplates.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/pdstemplates.c
@@ -106,16 +106,16 @@ g2int getpdsindex(g2int number)
 //
 //$$$/
 {
-           g2int j,getpdsindex=-1;
+           g2int j,l_getpdsindex=-1;
 
            for (j=0;j<MAXPDSTEMP;j++) {
               if (number == templatespds[j].template_num) {
-                 getpdsindex=j;
-                 return(getpdsindex);
+                 l_getpdsindex=j;
+                 return(l_getpdsindex);
               }
            }
 
-           return(getpdsindex);
+           return(l_getpdsindex);
 }
 
 
@@ -151,18 +151,18 @@ xxtemplate *getpdstemplate(g2int number)
 //
 //$$$/
 {
-           g2int index;
+           g2int l_index;
            xxtemplate *new;
 
-           index=getpdsindex(number);
+           l_index=getpdsindex(number);
 
-           if (index != -1) {
+           if (l_index != -1) {
               new=(xxtemplate *)malloc(sizeof(xxtemplate));
               new->type=4;
-              new->num=templatespds[index].template_num;
-              new->maplen=templatespds[index].mappdslen;
-              new->needext=templatespds[index].needext;
-              new->map=(g2int *)templatespds[index].mappds;
+              new->num=templatespds[l_index].template_num;
+              new->maplen=templatespds[l_index].mappdslen;
+              new->needext=templatespds[l_index].needext;
+              new->map=(g2int *)templatespds[l_index].mappds;
               new->extlen=0;
               new->ext=0;        //NULL
               return(new);
@@ -209,12 +209,13 @@ xxtemplate *extpdstemplate(g2int number,g2int *list)
 //$$$
 {
            xxtemplate *new;
-           g2int index,i,j,k,l;
+           g2int l_index,i,j,k,l;
 
-           index=getpdsindex(number);
-           if (index == -1) return(0);
+           l_index=getpdsindex(number);
+           if (l_index == -1) return(0);
 
            new=getpdstemplate(number);
+           if (new == NULL) return NULL;
 
            if ( ! new->needext ) return(new);
 
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/pdstemplates.h b/frmts/grib/degrib18/g2clib-1.0.4/pdstemplates.h
index e268230..3819fb2 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/pdstemplates.h
+++ b/frmts/grib/degrib18/g2clib-1.0.4/pdstemplates.h
@@ -1,12 +1,12 @@
-#ifndef _pdstemplates_H
-#define _pdstemplates_H
+#ifndef pdstemplates_H
+#define pdstemplates_H
 #include "grib2.h"
 
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-26
 //
-// ABSTRACT: This inculde file contains info on all the available 
+// ABSTRACT: This include file contains info on all the available 
 //   GRIB2 Product Definition Templates used in Section 4 (PDS).
-//   The information decribing each template is stored in the
+//   The information describing each template is stored in the
 //   pdstemplate structure defined below.
 //
 //   Each Template has three parts: The number of entries in the template
@@ -44,7 +44,7 @@
           g2int mappds[MAXPDSMAPLEN];
       };
 
-const struct pdstemplate *get_templatespds();
+const struct pdstemplate *get_templatespds(void);
 g2int getpdsindex(g2int number);
 
-#endif  /*  _pdstemplates_H  */
+#endif  /*  pdstemplates_H  */
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/pngpack.c b/frmts/grib/degrib18/g2clib-1.0.4/pngpack.c
index a5a47b7..55d158f 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/pngpack.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/pngpack.c
@@ -90,7 +90,7 @@ void pngpack(g2float *fld,g2int width,g2int height,g2int *idrstmpl,
         //
         if (idrstmpl[1] == 0) {
            //
-           //  No binary scaling and calculate minumum number of 
+           //  No binary scaling and calculate minimum number of 
            //  bits in which the data will fit.
            //
            imin=(g2int)RINT(rmin*dscale);
@@ -105,7 +105,7 @@ void pngpack(g2float *fld,g2int width,g2int height,g2int *idrstmpl,
         }
         else {
            //
-           //  Use binary scaling factor and calculate minumum number of 
+           //  Use binary scaling factor and calculate minimum number of 
            //  bits in which the data will fit.
            //
            rmin=rmin*dscale;
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/pngunpack.c b/frmts/grib/degrib18/g2clib-1.0.4/pngunpack.c
index 407a358..373d854 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/pngunpack.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/pngunpack.c
@@ -57,7 +57,8 @@ g2int pngunpack(unsigned char *cpack,g2int len,g2int *idrstmpl,g2int ndpts,
          ifld=(g2int *)calloc(ndpts,sizeof(g2int));
          ctemp=(unsigned char *)calloc(ndpts*4,1);
          if ( ifld == 0 || ctemp == 0) {
-            fprintf(stderr,"Could not allocate space in jpcunpack.\n  Data field NOT upacked.\n");
+            fprintf(stderr, "Could not allocate space in jpcunpack.\n"
+                    "Data field NOT unpacked.\n");
             return(1);
          }
          iret=(g2int)dec_png(cpack,&width,&height,ctemp);
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/reduce.c b/frmts/grib/degrib18/g2clib-1.0.4/reduce.c
index 044138b..b1b18b4 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/reduce.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/reduce.c
@@ -16,9 +16,6 @@
 
 #include "cpl_port.h"
 
-typedef g2int integer;
-typedef g2float real;
-
 /* Subroutine */ int reduce(CPL_UNUSED integer *kfildo, integer *jmin, integer *jmax,
 	integer *lbit, integer *nov, integer *lx, integer *ndg, integer *ibit,
 	 integer *jbit, integer *kbit, integer *novref, integer *ibxx2,
@@ -158,12 +155,12 @@ typedef g2float real;
     ntotbt[*kbit - 1] = iorigb;
 /*           THIS IS THE VALUE OF TOTAL BITS FOR THE ORIGINAL LX */
 /*           GROUPS, WHICH REQUIRES KBITS TO PACK THE GROUP */
-/*           LENGHTS.  SETTING THIS HERE MAKES ONE LESS LOOPS */
+/*           LENGTHS.  SETTING THIS HERE MAKES ONE LESS LOOPS */
 /*           NECESSARY BELOW. */
 
 /*        COMPUTE BITS NOW USED FOR THE PARAMETERS DEFINED. */
 
-/*        DETERMINE OTHER POSSIBILITES BY INCREASING LX AND DECREASING */
+/*        DETERMINE OTHER POSSIBILITIES BY INCREASING LX AND DECREASING */
 /*        NOV( ) WITH VALUES GREATER THAN THRESHOLDS.  ASSUME A GROUP IS */
 /*        SPLIT INTO 2 OR MORE GROUPS SO THAT KBIT IS REDUCED WITHOUT */
 /*        CHANGING IBIT OR JBIT. */
@@ -387,7 +384,7 @@ L288:
 /*           LX IS NOW THE NEW NUMBER OF GROUPS. */
 	*kbit = jj;
 /*           KBIT IS NOW THE NEW NUMBER OF BITS REQUIRED FOR PACKING */
-/*           GROUP LENGHTS. */
+/*           GROUP LENGTHS. */
     }
 
 /*     WRITE(KFILDO,406)CFEED,LX */
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/seekgb.c b/frmts/grib/degrib18/g2clib-1.0.4/seekgb.c
index 8bff0c5..424197f 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/seekgb.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/seekgb.c
@@ -25,7 +25,7 @@ void seekgb(FILE *lugb,g2int iseek,g2int mseek,g2int *lskip,g2int *lgrib)
 //     iseek      - number of bytes in the file to skip before search
 //     mseek      - number of bytes to search at a time
 //   OUTPUT ARGUMENTS:
-//     lskip      - number of bytes to skip from the beggining of the file
+//     lskip      - number of bytes to skip from the beginning of the file
 //                  to where the GRIB message starts
 //     lgrib      - number of bytes in message (set to 0, if no message found)
 //
@@ -52,7 +52,7 @@ void seekgb(FILE *lugb,g2int iseek,g2int mseek,g2int *lskip,g2int *lgrib)
 //  READ PARTIAL SECTION
 
         /* ret= */ fseek(lugb,ipos,SEEK_SET);
-        nread=fread(cbuf,sizeof(unsigned char),mseek,lugb);
+        nread=(int)fread(cbuf,sizeof(unsigned char),mseek,lugb);
         lim=nread-8;
 
 //  LOOK FOR 'GRIB...' IN PARTIAL SECTION
@@ -65,7 +65,7 @@ void seekgb(FILE *lugb,g2int iseek,g2int mseek,g2int *lskip,g2int *lgrib)
             if (vers == 1) gbit(cbuf,&lengrib,(k+4)*8,3*8);
             if (vers == 2) gbit(cbuf,&lengrib,(k+12)*8,4*8);
             /* ret= */ fseek(lugb,ipos+k+lengrib-4,SEEK_SET);
-            k4=fread(&end,sizeof(g2int),1,lugb);
+            k4=(int)fread(&end,sizeof(g2int),1,lugb);
             if (k4 == 1 && end == 926365495) {      //GRIB message found
                 *lskip=ipos+k;
                 *lgrib=lengrib;
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/simpack.c b/frmts/grib/degrib18/g2clib-1.0.4/simpack.c
index 1e19af9..15940b8 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/simpack.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/simpack.c
@@ -10,7 +10,7 @@ void simpack(g2float *fld,g2int ndpts,g2int *idrstmpl,unsigned char *cpack,g2int
 //   PRGMMR: Gilbert          ORG: W/NP11    DATE: 2002-11-06
 //
 // ABSTRACT: This subroutine packs up a data field using the simple
-//   packing algorithm as defined in the GRIB2 documention.  It
+//   packing algorithm as defined in the GRIB2 documentation.  It
 //   also fills in GRIB2 Data Representation Template 5.0 with the
 //   appropriate values.
 //
@@ -59,12 +59,12 @@ void simpack(g2float *fld,g2int ndpts,g2int *idrstmpl,unsigned char *cpack,g2int
 //$$$
 {
 
-      static g2int zero=0;
+      const g2int zero=0;
       g2int  *ifld;
       g2int  j,nbits,imin,imax,maxdif,nbittot,left;
       g2float  bscale,dscale,rmax,rmin,temp;
       double maxnum;
-      static g2float alog2=0.69314718;       //  ln(2.0)
+      const g2float alog2=0.69314718;       //  ln(2.0)
       
       bscale=int_power(2.0,-idrstmpl[1]);
       dscale=int_power(10.0,idrstmpl[2]);
@@ -96,7 +96,7 @@ void simpack(g2float *fld,g2int ndpts,g2int *idrstmpl,unsigned char *cpack,g2int
         //
         if (nbits==0 && idrstmpl[1]==0) {
            //
-           //  No binary scaling and calculate minumum number of 
+           //  No binary scaling and calculate minimum number of 
            //  bits in which the data will fit.
            //
            imin=(g2int)RINT(rmin*dscale);
@@ -126,7 +126,7 @@ void simpack(g2float *fld,g2int ndpts,g2int *idrstmpl,unsigned char *cpack,g2int
         }
         else if (nbits==0 && idrstmpl[1]!=0) {
            //
-           //  Use binary scaling factor and calculate minumum number of 
+           //  Use binary scaling factor and calculate minimum number of 
            //  bits in which the data will fit.
            //
            rmin=rmin*dscale;
@@ -140,7 +140,7 @@ void simpack(g2float *fld,g2int ndpts,g2int *idrstmpl,unsigned char *cpack,g2int
         }
         else if (nbits!=0 && idrstmpl[1]!=0) {
            //
-           //  Use binary scaling factor and use minumum number of 
+           //  Use binary scaling factor and use minimum number of 
            //  bits specified by user.   Dangerous - may loose
            //  information if binary scale factor and nbits not set
            //  properly by user.
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/simunpack.c b/frmts/grib/degrib18/g2clib-1.0.4/simunpack.c
index cca0d1e..3826b9a 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/simunpack.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/simunpack.c
@@ -2,6 +2,7 @@
 #include <stdlib.h>
 #include "grib2.h"
 
+g2int simunpack(unsigned char *cpack,g2int *idrstmpl,g2int ndpts,g2float *fld);
 
 g2int simunpack(unsigned char *cpack,g2int *idrstmpl,g2int ndpts,g2float *fld)
 ////$$$  SUBPROGRAM DOCUMENTATION BLOCK
@@ -10,7 +11,7 @@ g2int simunpack(unsigned char *cpack,g2int *idrstmpl,g2int ndpts,g2float *fld)
 //   PRGMMR: Gilbert          ORG: W/NP11    DATE: 2002-10-29
 //
 // ABSTRACT: This subroutine unpacks a data field that was packed using a 
-//   simple packing algorithm as defined in the GRIB2 documention,
+//   simple packing algorithm as defined in the GRIB2 documentation,
 //   using info from the GRIB2 Data Representation Template 5.0.
 //
 // PROGRAM HISTORY LOG:
@@ -50,7 +51,8 @@ g2int simunpack(unsigned char *cpack,g2int *idrstmpl,g2int ndpts,g2float *fld)
 
       ifld=(g2int *)calloc(ndpts,sizeof(g2int));
       if ( ifld == 0 ) {
-         fprintf(stderr,"Could not allocate space in simunpack.\n  Data field NOT upacked.\n");
+         fprintf(stderr,"Could not allocate space in simunpack.\n"
+                 "Data field NOT unpacked.\n");
          return(1);
       }
 
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/specunpack.c b/frmts/grib/degrib18/g2clib-1.0.4/specunpack.c
index 5b35459..bc47b4c 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/specunpack.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/specunpack.c
@@ -13,7 +13,7 @@ g2int specunpack(unsigned char *cpack,g2int *idrstmpl,g2int ndpts,g2int JJ,
 //
 // ABSTRACT: This subroutine unpacks a spectral data field that was packed 
 //   using the complex packing algorithm for spherical harmonic data as 
-//   defined in the GRIB2 documention,
+//   defined in the GRIB2 documentation,
 //   using info from the GRIB2 Data Representation Template 5.51.
 //
 // PROGRAM HISTORY LOG:
diff --git a/frmts/grib/frmt_grib.html b/frmts/grib/frmt_grib.html
index 773d5b4..c54a181 100644
--- a/frmts/grib/frmt_grib.html
+++ b/frmts/grib/frmt_grib.html
@@ -7,7 +7,7 @@
 
 <h1>GRIB -- WMO General Regularly-distributed Information in Binary form</h1>
 
-GDAL supports reading of GRIB1 and GRIB2 format raster data, with some degree 
+GDAL supports reading of GRIB1 and GRIB2 format raster data, with some degree
 of support for coordinate system, georeferencing and other metadata.  GRIB
 format is commonly used for distribution of Meteorological information, and
 is propagated by the World Meteorological Organization.<p>
@@ -15,7 +15,7 @@ is propagated by the World Meteorological Organization.<p>
 The GDAL GRIB driver is based on a modified version of the degrib application
 which is written primarily by Arthur Taylor of NOAA NWS NDFD (MDL).  The
 degrib application (and the GDAL GRIB driver) are built on the g2clib
-grib decoding library written primarily by John Huddleston of NOAA NWS NCEP. 
+grib decoding library written primarily by John Huddleston of NOAA NWS NCEP.
 <p>
 
 There are several encoding schemes for raster data in GRIB format.  Most
@@ -24,12 +24,12 @@ GRIB files will generally be supported if GDAL is also built with JPEG2000
 support via one of the GDAL JPEG2000 drivers.  The JasPer library generally
 provides the best jpeg2000 support for the GRIB driver.<p>
 
-GRIB files may a be represented in GDAL as having many bands, with some sets 
-of bands representing a time sequence.  GRIB bands are represented as Float64 
-(double precision floating point) regardless of the actual values. GRIB 
-metadata is captured as per-band metadata and used to set band descriptions, 
+GRIB files may a be represented in GDAL as having many bands, with some sets
+of bands representing a time sequence.  GRIB bands are represented as Float64
+(double precision floating point) regardless of the actual values. GRIB
+metadata is captured as per-band metadata and used to set band descriptions,
 similar to this:
-<pre>    
+<pre>
   Description = 100000[Pa] ISBL="Isobaric surface"
     GRIB_UNIT=[gpm]
     GRIB_COMMENT=Geopotential height [gpm]
@@ -40,7 +40,7 @@ similar to this:
     GRIB_FORECAST_SECONDS=3600 sec
 </pre>
 
-GRIB2 files may also include an extract of the product definition template 
+GRIB2 files may also include an extract of the product definition template
 number (octet 8-9), and the product definition template values (octet 10+)
 as metadata like this:
 
diff --git a/frmts/grib/gribdataset.cpp b/frmts/grib/gribdataset.cpp
index 7384922..90b024e 100644
--- a/frmts/grib/gribdataset.cpp
+++ b/frmts/grib/gribdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gribdataset.cpp 28459 2015-02-12 13:48:21Z rouault $
+ * $Id: gribdataset.cpp 33813 2016-03-29 23:48:36Z goatbar $
  *
  * Project:  GRIB Driver
  * Purpose:  GDALDataset driver for GRIB translator for read support
@@ -27,11 +27,13 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ******************************************************************************
- * 
+ *
  */
 
-#include "gdal_pam.h"
 #include "cpl_multiproc.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
+#include "ogr_spatialref.h"
 
 #include "degrib18/degrib/degrib2.h"
 #include "degrib18/degrib/inventory.h"
@@ -39,19 +41,13 @@
 #include "degrib18/degrib/filedatasource.h"
 #include "degrib18/degrib/memorydatasource.h"
 
-#include "ogr_spatialref.h"
-
-CPL_CVSID("$Id: gribdataset.cpp 28459 2015-02-12 13:48:21Z rouault $");
-
-CPL_C_START
-void	GDALRegister_GRIB(void);
-CPL_C_END
+CPL_CVSID("$Id: gribdataset.cpp 33813 2016-03-29 23:48:36Z goatbar $");
 
 static CPLMutex *hGRIBMutex = NULL;
 
 /************************************************************************/
 /* ==================================================================== */
-/*				GRIBDataset				*/
+/*                              GRIBDataset                             */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -62,21 +58,21 @@ class GRIBDataset : public GDALPamDataset
     friend class GRIBRasterBand;
 
   public:
-		GRIBDataset();
-		~GRIBDataset();
-    
+                GRIBDataset();
+                ~GRIBDataset();
+
     static GDALDataset *Open( GDALOpenInfo * );
     static int          Identify( GDALOpenInfo * );
 
-    CPLErr 	GetGeoTransform( double * padfTransform );
+    CPLErr      GetGeoTransform( double * padfTransform );
     const char *GetProjectionRef();
-    
-	private:
-		void SetGribMetaData(grib_MetaData* meta);
-    VSILFILE	*fp;
+
+  private:
+    void SetGribMetaData(grib_MetaData* meta);
+    VSILFILE    *fp;
     char  *pszProjection;
-    OGRCoordinateTransformation *poTransform;
-    double adfGeoTransform[6]; // Calculate and store once as GetGeoTransform may be called multiple times
+    // Calculate and store once as GetGeoTransform may be called multiple times.
+    double adfGeoTransform[6];
 
     GIntBig  nCachedBytes;
     GIntBig  nCachedBytesThreshold;
@@ -93,7 +89,7 @@ class GRIBDataset : public GDALPamDataset
 class GRIBRasterBand : public GDALPamRasterBand
 {
     friend class GRIBDataset;
-    
+
 public:
     GRIBRasterBand( GRIBDataset*, int, inventoryType* );
     virtual ~GRIBRasterBand();
@@ -110,7 +106,8 @@ private:
 
     CPLErr       LoadData();
 
-    static void ReadGribData( DataSource &, sInt4, int, double**, grib_MetaData**);
+    static void ReadGribData( DataSource &, sInt4, int, double**,
+                              grib_MetaData** );
     sInt4 start;
     int subgNum;
     char *longFstLevel;
@@ -126,7 +123,7 @@ private:
 /*                         ConvertUnitInText()                          */
 /************************************************************************/
 
-static CPLString ConvertUnitInText(int bMetricUnits, const char* pszTxt)
+static CPLString ConvertUnitInText( bool bMetricUnits, const char* pszTxt )
 {
     if( !bMetricUnits )
         return pszTxt;
@@ -142,36 +139,41 @@ static CPLString ConvertUnitInText(int bMetricUnits, const char* pszTxt)
 /*                           GRIBRasterBand()                            */
 /************************************************************************/
 
-GRIBRasterBand::GRIBRasterBand( GRIBDataset *poDS, int nBand, 
-                                inventoryType *psInv )
-  : m_Grib_Data(NULL), m_Grib_MetaData(NULL)
+GRIBRasterBand::GRIBRasterBand( GRIBDataset *poDSIn, int nBandIn,
+                                inventoryType *psInv ) :
+    start(psInv->start),
+    subgNum(psInv->subgNum),
+    longFstLevel(CPLStrdup(psInv->longFstLevel)),
+    m_Grib_Data(NULL),
+    m_Grib_MetaData(NULL),
+    nGribDataXSize(poDSIn->nRasterXSize),
+    nGribDataYSize(poDSIn->nRasterYSize)
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
-    this->start = psInv->start;
-    this->subgNum = psInv->subgNum;
-    this->longFstLevel = CPLStrdup(psInv->longFstLevel);
+    poDS = poDSIn;
+    nBand = nBandIn;
 
-    eDataType = GDT_Float64; // let user do -ot Float32 if needed for saving space, GRIB contains Float64 (though not fully utilized most of the time)
+    // Let user do -ot Float32 if needed for saving space, GRIB contains
+    // Float64 (though not fully utilized most of the time).
+    eDataType = GDT_Float64;
 
-    nBlockXSize = poDS->nRasterXSize;
+    nBlockXSize = poDSIn->nRasterXSize;
     nBlockYSize = 1;
 
-    nGribDataXSize = poDS->nRasterXSize;
-    nGribDataYSize = poDS->nRasterYSize;
-
-    const char* pszGribNormalizeUnits = CPLGetConfigOption("GRIB_NORMALIZE_UNITS", "YES");
-    int bMetricUnits = CSLTestBoolean(pszGribNormalizeUnits);
+    const char* pszGribNormalizeUnits =
+        CPLGetConfigOption("GRIB_NORMALIZE_UNITS", "YES");
+    bool bMetricUnits = CPLTestBool(pszGribNormalizeUnits);
 
-    SetMetadataItem( "GRIB_UNIT", ConvertUnitInText(bMetricUnits, psInv->unitName) );
-    SetMetadataItem( "GRIB_COMMENT", ConvertUnitInText(bMetricUnits, psInv->comment) );
+    SetMetadataItem( "GRIB_UNIT",
+                     ConvertUnitInText(bMetricUnits, psInv->unitName) );
+    SetMetadataItem( "GRIB_COMMENT",
+                     ConvertUnitInText(bMetricUnits, psInv->comment) );
     SetMetadataItem( "GRIB_ELEMENT", psInv->element );
     SetMetadataItem( "GRIB_SHORT_NAME", psInv->shortFstLevel );
-    SetMetadataItem( "GRIB_REF_TIME", 
+    SetMetadataItem( "GRIB_REF_TIME",
                      CPLString().Printf("%12.0f sec UTC", psInv->refTime ) );
-    SetMetadataItem( "GRIB_VALID_TIME", 
+    SetMetadataItem( "GRIB_VALID_TIME",
                      CPLString().Printf("%12.0f sec UTC", psInv->validTime ) );
-    SetMetadataItem( "GRIB_FORECAST_SECONDS", 
+    SetMetadataItem( "GRIB_FORECAST_SECONDS",
                      CPLString().Printf("%.0f sec", psInv->foreSec ) );
 }
 
@@ -185,7 +187,7 @@ GRIBRasterBand::GRIBRasterBand( GRIBDataset *poDS, int nBand,
 void GRIBRasterBand::FindPDSTemplate()
 
 {
-    GRIBDataset *poGDS = (GRIBDataset *) poDS;
+    GRIBDataset *poGDS = reinterpret_cast<GRIBDataset *>( poDS );
 
 /* -------------------------------------------------------------------- */
 /*      Collect section 4 octet information ... we read the file        */
@@ -193,12 +195,13 @@ void GRIBRasterBand::FindPDSTemplate()
 /*      this for us.                                                    */
 /* -------------------------------------------------------------------- */
     GIntBig nOffset = VSIFTellL( poGDS->fp );
-    GByte abyHead[5];
-    GUInt32 nSectSize;
 
     VSIFSeekL( poGDS->fp, start+16, SEEK_SET );
+
+    GByte abyHead[5] = { 0 };
     VSIFReadL( abyHead, 5, 1, poGDS->fp );
 
+    GUInt32 nSectSize = 0;
     while( abyHead[4] != 4 )
     {
         memcpy( &nSectSize, abyHead, 4 );
@@ -208,41 +211,38 @@ void GRIBRasterBand::FindPDSTemplate()
             || VSIFReadL( abyHead, 5, 1, poGDS->fp ) != 1 )
             break;
     }
-        
+
     if( abyHead[4] == 4 )
     {
-        GUInt16 nCoordCount;
-        GUInt16 nPDTN;
-        CPLString osOctet;
-        int i;
-        GByte *pabyBody;
-
         memcpy( &nSectSize, abyHead, 4 );
         CPL_MSBPTR32( &nSectSize );
 
-        pabyBody = (GByte *) CPLMalloc(nSectSize-5);
+        GByte *pabyBody = static_cast<GByte *>( CPLMalloc(nSectSize - 5) );
         VSIFReadL( pabyBody, 1, nSectSize-5, poGDS->fp );
 
+        GUInt16 nCoordCount = 0;
         memcpy( &nCoordCount, pabyBody + 5 - 5, 2 );
         CPL_MSBPTR16( &nCoordCount );
 
+        GUInt16 nPDTN = 0;
         memcpy( &nPDTN, pabyBody + 7 - 5, 2 );
         CPL_MSBPTR16( &nPDTN );
 
         SetMetadataItem( "GRIB_PDS_PDTN",
                          CPLString().Printf( "%d", nPDTN ) );
 
-        for( i = 9; i < (int) nSectSize; i++ )
+        CPLString osOctet;
+        for( int i = 9; i < static_cast<int>( nSectSize ); i++ )
         {
-            char szByte[10];
+            char szByte[10] = { '\0' };
 
             if( i == 9 )
-                sprintf( szByte, "%d", pabyBody[i-5] );
+                snprintf( szByte, sizeof(szByte), "%d", pabyBody[i-5] );
             else
-                sprintf( szByte, " %d", pabyBody[i-5] );
+                snprintf( szByte, sizeof(szByte), " %d", pabyBody[i-5] );
             osOctet += szByte;
         }
-        
+
         SetMetadataItem( "GRIB_PDS_TEMPLATE_NUMBERS", osOctet );
 
         CPLFree( pabyBody );
@@ -259,10 +259,10 @@ const char * GRIBRasterBand::GetDescription() const
 {
     if( longFstLevel == NULL )
         return GDALPamRasterBand::GetDescription();
-    else
-        return longFstLevel;
+
+    return longFstLevel;
 }
- 
+
 /************************************************************************/
 /*                             LoadData()                               */
 /************************************************************************/
@@ -272,28 +272,30 @@ CPLErr GRIBRasterBand::LoadData()
 {
     if( !m_Grib_Data )
     {
-        GRIBDataset *poGDS = (GRIBDataset *) poDS;
+        GRIBDataset *poGDS = reinterpret_cast<GRIBDataset *>( poDS );
 
         if (poGDS->bCacheOnlyOneBand)
         {
-            /* In "one-band-at-a-time" strategy, if the last recently used */
-            /* band is not that one, uncache it. We could use a smarter strategy */
-            /* based on a LRU, but that's a bit overkill for now. */
+            // In "one-band-at-a-time" strategy, if the last recently used
+            // band is not that one, uncache it. We could use a smarter strategy
+            // based on a LRU, but that's a bit overkill for now.
             poGDS->poLastUsedBand->UncacheData();
             poGDS->nCachedBytes = 0;
         }
         else
         {
-            /* Once we have cached more than nCachedBytesThreshold bytes, we will switch */
-            /* to "one-band-at-a-time" strategy, instead of caching all bands that have */
-            /* been accessed */
+            // Once we have cached more than nCachedBytesThreshold bytes, we
+            // will switch to "one-band-at-a-time" strategy, instead of caching
+            // all bands that have been accessed.
             if (poGDS->nCachedBytes > poGDS->nCachedBytesThreshold)
             {
-                CPLDebug("GRIB", "Maximum band cache size reached for this dataset. "
-                         "Caching only one band at a time from now");
+                CPLDebug( "GRIB",
+                          "Maximum band cache size reached for this dataset. "
+                          "Caching only one band at a time from now");
                 for(int i=0;i<poGDS->nBands;i++)
                 {
-                    ((GRIBRasterBand*) poGDS->GetRasterBand(i+1))->UncacheData();
+                    reinterpret_cast<GRIBRasterBand*>(
+                        poGDS->GetRasterBand(i+1))->UncacheData();
                 }
                 poGDS->nCachedBytes = 0;
                 poGDS->bCacheOnlyOneBand = TRUE;
@@ -320,14 +322,16 @@ CPLErr GRIBRasterBand::LoadData()
         poGDS->nCachedBytes += nGribDataXSize * nGribDataYSize * sizeof(double);
         poGDS->poLastUsedBand = this;
 
-        if( nGribDataXSize != nRasterXSize 
+        if( nGribDataXSize != nRasterXSize
             || nGribDataYSize != nRasterYSize )
         {
             CPLError( CE_Warning, CPLE_AppDefined,
-                      "Band %d of GRIB dataset is %dx%d, while the first band and dataset is %dx%d.  Georeferencing of band %d may be incorrect, and data access may be incomplete.", 
-                      nBand, 
-                      nGribDataXSize, nGribDataYSize, 
-                      nRasterXSize, nRasterYSize, 
+                      "Band %d of GRIB dataset is %dx%d, while the first band "
+                      "and dataset is %dx%d.  Georeferencing of band %d may "
+                      "be incorrect, and data access may be incomplete.",
+                      nBand,
+                      nGribDataXSize, nGribDataYSize,
+                      nRasterXSize, nRasterYSize,
                       nBand );
         }
     }
@@ -339,7 +343,7 @@ CPLErr GRIBRasterBand::LoadData()
 /*                             IReadBlock()                             */
 /************************************************************************/
 
-CPLErr GRIBRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
+CPLErr GRIBRasterBand::IReadBlock( int /* nBlockXOff */,
                                    int nBlockYOff,
                                    void * pImage )
 
@@ -358,27 +362,25 @@ CPLErr GRIBRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
         && nGribDataYSize == nRasterYSize )
     {
         // Simple 1:1 case.
-        memcpy(pImage, 
-               m_Grib_Data + nRasterXSize * (nRasterYSize - nBlockYOff - 1), 
+        memcpy(pImage,
+               m_Grib_Data + nRasterXSize * (nRasterYSize - nBlockYOff - 1),
                nRasterXSize * sizeof(double));
-        
+
         return CE_None;
     }
-    else
-    {
-        memset( pImage, 0, sizeof(double)*nRasterXSize );
 
-        if( nBlockYOff >= nGribDataYSize ) // off image?
-            return CE_None;
+    memset( pImage, 0, sizeof(double) * nRasterXSize );
 
-        int nCopyWords = MIN(nRasterXSize,nGribDataXSize);
-
-        memcpy( pImage, 
-                m_Grib_Data + nGribDataXSize*(nGribDataYSize-nBlockYOff-1),
-                nCopyWords * sizeof(double) );
-        
+    if( nBlockYOff >= nGribDataYSize ) // off image?
         return CE_None;
-    }
+
+    const int nCopyWords = MIN(nRasterXSize,nGribDataXSize);
+
+    memcpy( pImage,
+            m_Grib_Data + nGribDataXSize*(nGribDataYSize-nBlockYOff-1),
+            nCopyWords * sizeof(double) );
+
+    return CE_None;
 }
 
 /************************************************************************/
@@ -413,30 +415,37 @@ double GRIBRasterBand::GetNoDataValue( int *pbSuccess )
 /*                            ReadGribData()                            */
 /************************************************************************/
 
-void GRIBRasterBand::ReadGribData( DataSource & fp, sInt4 start, int subgNum, double** data, grib_MetaData** metaData)
+void GRIBRasterBand::ReadGribData( DataSource & fp, sInt4 start, int subgNum,
+                                   double** data, grib_MetaData** metaData)
 {
-    /* Initialisation, for calling the ReadGrib2Record function */
-    sInt4 f_endMsg = 1;  /* 1 if we read the last grid in a GRIB message, or we haven't read any messages. */
-    // int subgNum = 0;     /* The subgrid in the message that we are interested in. */
-    sChar f_unit = 2;        /* None = 0, English = 1, Metric = 2 */
-    double majEarth = 0;     /* -radEarth if < 6000 ignore, otherwise use this to
-                              * override the radEarth in the GRIB1 or GRIB2
-                              * message.  Needed because NCEP uses 6371.2 but GRIB1 could only state 6367.47. */
-    double minEarth = 0;     /* -minEarth if < 6000 ignore, otherwise use this to
-                              * override the minEarth in the GRIB1 or GRIB2 message. */
-    sChar f_SimpleVer = 4;   /* Which version of the simple NDFD Weather table to
-                              * use. (1 is 6/2003) (2 is 1/2004) (3 is 2/2004)
-                              * (4 is 11/2004) (default 4) */
-    LatLon lwlf;         /* lower left corner (cookie slicing) -lwlf */
-    LatLon uprt;         /* upper right corner (cookie slicing) -uprt */
-    IS_dataType is;      /* Un-parsed meta data for this GRIB2 message. As well as some memory used by the unpacker. */
-
-    lwlf.lat = -100; // lat == -100 instructs the GRIB decoder that we don't want a subgrid
+    // Initialization, for calling the ReadGrib2Record function.
+    sInt4 f_endMsg = 1;  // 1 if we read the last grid in a GRIB message, or we
+                         // haven't read any messages.
+    // int subgNum = 0; // The subgrid in the message that we are interested in.
+    sChar f_unit = 2;        // None = 0, English = 1, Metric = 2
+    double majEarth = 0.0;   // -radEarth if < 6000 ignore, otherwise use this
+                             // to override the radEarth in the GRIB1 or GRIB2
+                             // message.  Needed because NCEP uses 6371.2 but
+                             // GRIB1 could only state 6367.47.
+    double minEarth = 0.0;   // -minEarth if < 6000 ignore, otherwise use this
+                             // to override the minEarth in the GRIB1 or GRIB2
+                             // message.
+    sChar f_SimpleVer = 4;   // Which version of the simple NDFD Weather table
+                             // to use. (1 is 6/2003) (2 is 1/2004) (3 is
+                             // 2/2004) (4 is 11/2004) (default 4)
+    LatLon lwlf;         // lower left corner (cookie slicing) -lwlf
+    LatLon uprt;         // upper right corner (cookie slicing) -uprt
+    IS_dataType is;      // Un-parsed meta data for this GRIB2 message. As well
+                         // as some memory used by the unpacker.
+
+    lwlf.lat = -100; // lat == -100 instructs the GRIB decoder that we don't
+                     // want a subgrid
 
     IS_Init (&is);
 
-    const char* pszGribNormalizeUnits = CPLGetConfigOption("GRIB_NORMALIZE_UNITS", "YES");
-    if ( !CSLTestBoolean(pszGribNormalizeUnits) )
+    const char* pszGribNormalizeUnits =
+        CPLGetConfigOption("GRIB_NORMALIZE_UNITS", "YES");
+    if ( !CPLTestBool(pszGribNormalizeUnits) )
         f_unit = 0; /* do not normalize units to metric */
 
     /* Read GRIB message from file position "start". */
@@ -447,7 +456,8 @@ void GRIBRasterBand::ReadGribData( DataSource & fp, sInt4 start, int subgNum, do
     ReadGrib2Record (fp, f_unit, data, &grib_DataLen, *metaData, &is, subgNum,
                      majEarth, minEarth, f_SimpleVer, &f_endMsg, &lwlf, &uprt);
 
-    char * errMsg = errSprintf(NULL); // no intention to show errors, just swallow it and free the memory
+    // no intention to show errors, just swallow it and free the memory.
+    char * errMsg = errSprintf(NULL);
     if( errMsg != NULL )
         CPLDebug( "GRIB", "%s", errMsg );
     free(errMsg);
@@ -483,15 +493,17 @@ GRIBRasterBand::~GRIBRasterBand()
 
 /************************************************************************/
 /* ==================================================================== */
-/*				GRIBDataset				*/
+/*                              GRIBDataset                             */
 /* ==================================================================== */
 /************************************************************************/
 
-GRIBDataset::GRIBDataset()
-
+GRIBDataset::GRIBDataset() :
+    fp(NULL),
+    pszProjection(CPLStrdup("")),
+    nCachedBytes(0),
+    bCacheOnlyOneBand(FALSE),
+    poLastUsedBand(NULL)
 {
-  poTransform = NULL;
-  pszProjection = CPLStrdup("");
   adfGeoTransform[0] = 0.0;
   adfGeoTransform[1] = 1.0;
   adfGeoTransform[2] = 0.0;
@@ -499,12 +511,11 @@ GRIBDataset::GRIBDataset()
   adfGeoTransform[4] = 0.0;
   adfGeoTransform[5] = 1.0;
 
-  nCachedBytes = 0;
   /* Switch caching strategy once 100 MB threshold is reached */
   /* Why 100 MB ? --> why not ! */
-  nCachedBytesThreshold = ((GIntBig)atoi(CPLGetConfigOption("GRIB_CACHEMAX", "100"))) * 1024 * 1024;
-  bCacheOnlyOneBand = FALSE;
-  poLastUsedBand = NULL;
+  nCachedBytesThreshold =
+      static_cast<GIntBig>(atoi(CPLGetConfigOption("GRIB_CACHEMAX", "100")))
+      * 1024 * 1024;
 }
 
 /************************************************************************/
@@ -517,7 +528,7 @@ GRIBDataset::~GRIBDataset()
     FlushCache();
     if( fp != NULL )
         VSIFCloseL( fp );
-		
+
     CPLFree( pszProjection );
 }
 
@@ -550,18 +561,17 @@ int GRIBDataset::Identify( GDALOpenInfo * poOpenInfo )
 {
     if (poOpenInfo->nHeaderBytes < 8)
         return FALSE;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Does a part of what ReadSECT0() but in a thread-safe way.       */
 /* -------------------------------------------------------------------- */
-    int i;
-    for(i=0;i<poOpenInfo->nHeaderBytes-3;i++)
+    for(int i=0;i<poOpenInfo->nHeaderBytes-3;i++)
     {
-        if (EQUALN((const char*)poOpenInfo->pabyHeader + i, "GRIB", 4) ||
-            EQUALN((const char*)poOpenInfo->pabyHeader + i, "TDLP", 4))
+        if (STARTS_WITH_CI((const char*)poOpenInfo->pabyHeader + i, "GRIB") ||
+            STARTS_WITH_CI((const char*)poOpenInfo->pabyHeader + i, "TDLP"))
             return TRUE;
     }
-    
+
     return FALSE;
 }
 
@@ -574,15 +584,15 @@ GDALDataset *GRIBDataset::Open( GDALOpenInfo * poOpenInfo )
 {
     if( !Identify(poOpenInfo) )
         return NULL;
-        
+
 /* -------------------------------------------------------------------- */
 /*      A fast "probe" on the header that is partially read in memory.  */
 /* -------------------------------------------------------------------- */
     char *buff = NULL;
     uInt4 buffLen = 0;
-    sInt4 sect0[SECT0LEN_WORD];
-    uInt4 gribLen;
-    int version;
+    sInt4 sect0[SECT0LEN_WORD] = { 0 };
+    uInt4 gribLen = 0;
+    int version = 0;
 // grib is not thread safe, make sure not to cause problems
 // for other thread safe formats
 
@@ -597,13 +607,13 @@ GDALDataset *GRIBDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
     free(buff);
-    
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The GRIB driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
@@ -611,27 +621,28 @@ GDALDataset *GRIBDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    GRIBDataset 	*poDS;
-
-    poDS = new GRIBDataset();
+    GRIBDataset *poDS = new GRIBDataset();
 
     poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "r" );
 
-	/* Check the return values */    
-	if (!poDS->fp) {
+    /* Check the return values */
+    if (!poDS->fp) {
         // we have no FP, so we don't have anywhere to read from
         char * errMsg = errSprintf(NULL);
         if( errMsg != NULL )
             CPLDebug( "GRIB", "%s", errMsg );
         free(errMsg);
-		
-		CPLError( CE_Failure, CPLE_OpenFailed, "Error (%d) opening file %s", errno, poOpenInfo->pszFilename);
-        CPLReleaseMutex(hGRIBMutex); // Release hGRIBMutex otherwise we'll deadlock with GDALDataset own hGRIBMutex
+
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Error (%d) opening file %s", errno, poOpenInfo->pszFilename);
+        // Release hGRIBMutex otherwise we'll deadlock with GDALDataset own
+        // hGRIBMutex.
+        CPLReleaseMutex(hGRIBMutex);
         delete poDS;
         CPLAcquireMutex(hGRIBMutex, 1000.0);
         return NULL;
-	}
-    
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Read the header.                                                */
 /* -------------------------------------------------------------------- */
@@ -644,26 +655,30 @@ GDALDataset *GRIBDataset::Open( GDALOpenInfo * poOpenInfo )
 /* The band-data that is read is stored into the first RasterBand,      */
 /* simply so that the same portion of the file is not read twice.       */
 /* -------------------------------------------------------------------- */
-    
+
     VSIFSeekL( poDS->fp, 0, SEEK_SET );
 
-    FileDataSource grib_fp (poDS->fp);
+    FileDataSource grib_fp(poDS->fp);
 
-    inventoryType *Inv = NULL;  /* Contains an GRIB2 message inventory of the file */
-    uInt4 LenInv = 0;        /* size of Inv (also # of GRIB2 messages) */
-    int msgNum =0;          /* The messageNumber during the inventory. */
+    // Contains an GRIB2 message inventory of the file.
+    inventoryType *Inv = NULL;
+    uInt4 LenInv = 0;        // Size of Inv (also # of GRIB2 messages).
+    int msgNum = 0;          // The messageNumber during the inventory.
 
-    if (GRIB2Inventory (grib_fp, &Inv, &LenInv, 0, &msgNum) <= 0 )
+    if( GRIB2Inventory (grib_fp, &Inv, &LenInv, 0, &msgNum) <= 0 )
     {
         char * errMsg = errSprintf(NULL);
         if( errMsg != NULL )
             CPLDebug( "GRIB", "%s", errMsg );
         free(errMsg);
 
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "%s is a grib file, but no raster dataset was successfully identified.",
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "%s is a grib file, "
+                  "but no raster dataset was successfully identified.",
                   poOpenInfo->pszFilename );
-        CPLReleaseMutex(hGRIBMutex); // Release hGRIBMutex otherwise we'll deadlock with GDALDataset own hGRIBMutex
+        // Release hGRIBMutex otherwise we'll deadlock with GDALDataset own
+        // hGRIBMutex.
+        CPLReleaseMutex(hGRIBMutex);
         delete poDS;
         CPLAcquireMutex(hGRIBMutex, 1000.0);
         return NULL;
@@ -672,28 +687,44 @@ GDALDataset *GRIBDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create band objects.                                            */
 /* -------------------------------------------------------------------- */
-    GRIBRasterBand *gribBand;
     for (uInt4 i = 0; i < LenInv; ++i)
     {
+        GRIBRasterBand *gribBand = NULL;
         uInt4 bandNr = i+1;
         if (bandNr == 1)
         {
-            // important: set DataSet extents before creating first RasterBand in it
-            double * data = NULL;
-            grib_MetaData* metaData;
-            GRIBRasterBand::ReadGribData(grib_fp, 0, Inv[i].subgNum, &data, &metaData);
-            if (data == 0 || metaData->gds.Nx < 1 || metaData->gds.Ny < 1)
+            // Important: set DataSet extents before creating first RasterBand
+            // in it.
+            double *data = NULL;
+            grib_MetaData *metaData = NULL;
+            GRIBRasterBand::ReadGribData( grib_fp, 0, Inv[i].subgNum,
+                                          &data, &metaData );
+            if( data == NULL || metaData == NULL || metaData->gds.Nx < 1 ||
+                 metaData->gds.Ny < 1 )
             {
-                CPLError( CE_Failure, CPLE_OpenFailed, 
-                          "%s is a grib file, but no raster dataset was successfully identified.",
+                CPLError( CE_Failure, CPLE_OpenFailed,
+                          "%s is a grib file, "
+                          "but no raster dataset was successfully identified.",
                           poOpenInfo->pszFilename );
-                CPLReleaseMutex(hGRIBMutex); // Release hGRIBMutex otherwise we'll deadlock with GDALDataset own hGRIBMutex
+                // Release hGRIBMutex otherwise we'll deadlock with GDALDataset
+                // own hGRIBMutex.
+                CPLReleaseMutex(hGRIBMutex);
                 delete poDS;
                 CPLAcquireMutex(hGRIBMutex, 1000.0);
+                if (metaData != NULL)
+                {
+                    delete metaData;
+                }
+                if (data != NULL)
+                {
+                    free(data);
+                }
                 return NULL;
             }
 
-            poDS->SetGribMetaData(metaData); // set the DataSet's x,y size, georeference and projection from the first GRIB band
+             // Set the DataSet's x,y size, georeference and projection from
+             // the first GRIB band.
+            poDS->SetGribMetaData(metaData);
             gribBand = new GRIBRasterBand( poDS, bandNr, Inv+i);
 
             if( Inv->GribVersion == 2 )
@@ -705,7 +736,8 @@ GDALDataset *GRIBDataset::Open( GDALOpenInfo * poOpenInfo )
         else
         {
             gribBand = new GRIBRasterBand( poDS, bandNr, Inv+i );
-            if( CSLTestBoolean( CPLGetConfigOption( "GRIB_PDS_ALL_BANDS", "ON" ) ) )
+            if( CPLTestBool(
+                   CPLGetConfigOption( "GRIB_PDS_ALL_BANDS", "ON" ) ) )
             {
                 if( Inv->GribVersion == 2 )
                     gribBand->FindPDSTemplate();
@@ -720,14 +752,17 @@ GDALDataset *GRIBDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
     poDS->SetDescription( poOpenInfo->pszFilename );
-    
-    CPLReleaseMutex(hGRIBMutex); // Release hGRIBMutex otherwise we'll deadlock with GDALDataset own hGRIBMutex
+
+    // Release hGRIBMutex otherwise we'll deadlock with GDALDataset own
+    // hGRIBMutex.
+    CPLReleaseMutex(hGRIBMutex);
     poDS->TryLoadXML();
 
 /* -------------------------------------------------------------------- */
 /*      Check for external overviews.                                   */
 /* -------------------------------------------------------------------- */
-    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles() );
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename,
+                                 poOpenInfo->GetSiblingFiles() );
     CPLAcquireMutex(hGRIBMutex, 1000.0);
 
     return( poDS );
@@ -767,14 +802,17 @@ void GRIBDataset::SetGribMetaData(grib_MetaData* meta)
                     meta->gds.meshLat, meta->gds.orientLon,
                     0.0, 0.0); // set projection
         break;
-			
 
       case GS3_ORTHOGRAPHIC:
 
-        //oSRS.SetOrthographic(0.0, meta->gds.orientLon,
-        //											meta->gds.lon2, meta->gds.lat2);
-        //oSRS.SetGEOS(meta->gds.orientLon, meta->gds.stretchFactor, meta->gds.lon2, meta->gds.lat2);
-        oSRS.SetGEOS(  0, 35785831, 0, 0 ); // hardcoded for now, I don't know yet how to parse the meta->gds section
+        // oSRS.SetOrthographic( 0.0, meta->gds.orientLon,
+        //                       meta->gds.lon2, meta->gds.lat2);
+
+        // oSRS.SetGEOS( meta->gds.orientLon, meta->gds.stretchFactor,
+        //               meta->gds.lon2, meta->gds.lat2);
+
+        // TODO: Hardcoded for now. How to parse the meta->gds section?
+        oSRS.SetGEOS(  0, 35785831, 0, 0 );
         break;
       case GS3_EQUATOR_EQUIDIST:
         break;
@@ -802,7 +840,7 @@ void GRIBDataset::SetGribMetaData(grib_MetaData* meta)
     }
     else
     {
-        double fInv = a/(a-b);
+        const double fInv = a / (a - b);
         oSRS.SetGeogCS( "Coordinate System imported from GRIB file",
                         NULL,
                         "Spheroid imported from GRIB file",
@@ -812,15 +850,18 @@ void GRIBDataset::SetGribMetaData(grib_MetaData* meta)
     OGRSpatialReference oLL; // construct the "geographic" part of oSRS
     oLL.CopyGeogCSFrom( &oSRS );
 
-    double rMinX;
-    double rMaxY;
-    double rPixelSizeX;
-    double rPixelSizeY;
+    double rMinX = 0.0;
+    double rMaxY = 0.0;
+    double rPixelSizeX = 0.0;
+    double rPixelSizeY = 0.0;
     if (meta->gds.projType == GS3_ORTHOGRAPHIC)
     {
-        //rMinX = -meta->gds.Dx * (meta->gds.Nx / 2); // This is what should work, but it doesn't .. Dx seems to have an inverse relation with pixel size
-        //rMaxY = meta->gds.Dy * (meta->gds.Ny / 2);
-        const double geosExtentInMeters = 11137496.552; // hardcoded for now, assumption: GEOS projection, full disc (like MSG)
+        // This is what should work, but it doesn't .. Dx seems to have an
+        // inverse relation with pixel size.
+        // rMinX = -meta->gds.Dx * (meta->gds.Nx / 2);
+        // rMaxY = meta->gds.Dy * (meta->gds.Ny / 2);
+        // Hardcoded for now, assumption: GEOS projection, full disc (like MSG).
+        const double geosExtentInMeters = 11137496.552;
         rMinX = -(geosExtentInMeters / 2);
         rMaxY = geosExtentInMeters / 2;
         rPixelSizeX = geosExtentInMeters / meta->gds.Nx;
@@ -828,13 +869,23 @@ void GRIBDataset::SetGribMetaData(grib_MetaData* meta)
     }
     else if( oSRS.IsProjected() )
     {
-        rMinX = meta->gds.lon1; // longitude in degrees, to be transformed to meters (or degrees in case of latlon)
-        rMaxY = meta->gds.lat1; // latitude in degrees, to be transformed to meters 
-        OGRCoordinateTransformation *poTransformLLtoSRS = OGRCreateCoordinateTransformation( &(oLL), &(oSRS) );
-        if ((poTransformLLtoSRS != NULL) && poTransformLLtoSRS->Transform( 1, &rMinX, &rMaxY )) // transform it to meters
+        // Longitude in degrees, to be transformed to meters (or degrees in
+        // case of latlon).
+        rMinX = meta->gds.lon1;
+        // Latitude in degrees, to be transformed to meters.
+        rMaxY = meta->gds.lat1;
+        OGRCoordinateTransformation *poTransformLLtoSRS =
+            OGRCreateCoordinateTransformation( &(oLL), &(oSRS) );
+        // Transform it to meters.
+        if( (poTransformLLtoSRS != NULL) &&
+            poTransformLLtoSRS->Transform( 1, &rMinX, &rMaxY ))
         {
             if (meta->gds.scan == GRIB2BIT_2) // Y is minY, GDAL wants maxY
-                rMaxY += (meta->gds.Ny - 1) * meta->gds.Dy; // -1 because we GDAL needs the coordinates of the centre of the pixel
+            {
+                // -1 because we GDAL needs the coordinates of the centre of
+                // the pixel.
+                rMaxY += (meta->gds.Ny - 1) * meta->gds.Dy;
+            }
             rPixelSizeX = meta->gds.Dx;
             rPixelSizeY = meta->gds.Dy;
         }
@@ -842,23 +893,27 @@ void GRIBDataset::SetGribMetaData(grib_MetaData* meta)
         {
             rMinX = 0.0;
             rMaxY = 0.0;
-            
+
             rPixelSizeX = 1.0;
             rPixelSizeY = -1.0;
-            
+
             oSRS.Clear();
 
             CPLError( CE_Warning, CPLE_AppDefined,
-                      "Unable to perform coordinate transformations, so the correct\n"
-                      "projected geotransform could not be deduced from the lat/long\n"
-                      "control points.  Defaulting to ungeoreferenced." );
+                      "Unable to perform coordinate transformations, so the "
+                      "correct projected geotransform could not be deduced "
+                      "from the lat/long control points.  "
+                      "Defaulting to ungeoreferenced." );
         }
         delete poTransformLLtoSRS;
     }
     else
     {
-        rMinX = meta->gds.lon1; // longitude in degrees, to be transformed to meters (or degrees in case of latlon)
-        rMaxY = meta->gds.lat1; // latitude in degrees, to be transformed to meters 
+        // Longitude in degrees, to be transformed to meters (or degrees in
+        // case of latlon).
+        rMinX = meta->gds.lon1;
+        // Latitude in degrees, to be transformed to meters.
+        rMaxY = meta->gds.lat1;
 
         double rMinY = meta->gds.lat2;
         if (meta->gds.lat2 > rMaxY)
@@ -870,7 +925,8 @@ void GRIBDataset::SetGribMetaData(grib_MetaData* meta)
         if( meta->gds.Nx == 1 )
           rPixelSizeX = meta->gds.Dx;
         else if (meta->gds.lon1 > meta->gds.lon2)
-          rPixelSizeX = (360.0 - (meta->gds.lon1 - meta->gds.lon2)) / (meta->gds.Nx - 1);
+          rPixelSizeX =
+              (360.0 - (meta->gds.lon1 - meta->gds.lon2)) / (meta->gds.Nx - 1);
         else
           rPixelSizeX = (meta->gds.lon2 - meta->gds.lon1) / (meta->gds.Nx - 1);
 
@@ -925,25 +981,21 @@ static void GDALDeregister_GRIB(GDALDriver* )
 void GDALRegister_GRIB()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "GRIB" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "GRIB" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "GRIB" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "GRIdded Binary (.grb)" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_grib.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "grb" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = GRIBDataset::Open;
-        poDriver->pfnIdentify = GRIBDataset::Identify;
-        poDriver->pfnUnloadDriver = GDALDeregister_GRIB;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "GRIB" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "GRIdded Binary (.grb)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_grib.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "grb" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = GRIBDataset::Open;
+    poDriver->pfnIdentify = GRIBDataset::Identify;
+    poDriver->pfnUnloadDriver = GDALDeregister_GRIB;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/gsg/gs7bgdataset.cpp b/frmts/gsg/gs7bgdataset.cpp
index ee8d8d2..6ab7e64 100644
--- a/frmts/gsg/gs7bgdataset.cpp
+++ b/frmts/gsg/gs7bgdataset.cpp
@@ -1,5 +1,5 @@
 /****************************************************************************
- * $Id: gs7bgdataset.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: gs7bgdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Implements the Golden Software Surfer 7 Binary Grid Format.
@@ -30,11 +30,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include <float.h>
-#include <limits.h>
-#include <math.h>
-#include <assert.h>
+#include <cassert>
+#include <cfloat>
+#include <climits>
+#include <cmath>
 
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 
 #ifndef DBL_MAX
@@ -61,11 +62,7 @@
 # define SHRT_MAX 32767
 #endif /* SHRT_MAX */
 
-CPL_CVSID("$Id: gs7bgdataset.cpp 28053 2014-12-04 09:31:07Z rouault $");
-
-CPL_C_START
-void    GDALRegister_GS7BG(void);
-CPL_C_END
+CPL_CVSID("$Id: gs7bgdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -75,13 +72,15 @@ CPL_C_END
 
 class GS7BGRasterBand;
 
+static const double dfDefaultNoDataValue = 1.701410009187828e+38f;
+
 class GS7BGDataset : public GDALPamDataset
 {
     friend class GS7BGRasterBand;
 
-    static double dfNoData_Value;
+    double dfNoData_Value;
     static const size_t nHEADER_SIZE;
-    static size_t nData_Position;
+    size_t nData_Position;
 
     static CPLErr WriteHeader( VSILFILE *fp, GInt32 nXSize, GInt32 nYSize,
                    double dfMinX, double dfMaxX,
@@ -91,6 +90,12 @@ class GS7BGDataset : public GDALPamDataset
     VSILFILE    *fp;
 
   public:
+    GS7BGDataset() :
+    /* NOTE:  This is not mentioned in the spec, but Surfer 8 uses this value */
+    /* 0x7effffee (Little Endian: eeffff7e) */
+        dfNoData_Value(dfDefaultNoDataValue),
+        nData_Position(0),
+        fp(NULL) { }
     ~GS7BGDataset();
 
     static int          Identify( GDALOpenInfo * );
@@ -109,17 +114,12 @@ class GS7BGDataset : public GDALPamDataset
     CPLErr SetGeoTransform( double *padfGeoTransform );
 };
 
-/* NOTE:  This is not mentioned in the spec, but Surfer 8 uses this value */
-/* 0x7effffee (Little Endian: eeffff7e) */
-double GS7BGDataset::dfNoData_Value = 1.701410009187828e+38f;
 
 const size_t GS7BGDataset::nHEADER_SIZE = 100;
 
-size_t GS7BGDataset::nData_Position = 0;
-
-const long  nHEADER_TAG = 0x42525344;
-const long  nGRID_TAG = 0x44495247;
-const long  nDATA_TAG = 0x41544144;
+static const long  nHEADER_TAG = 0x42525344;
+static const long  nGRID_TAG = 0x44495247;
+static const long  nDATA_TAG = 0x41544144;
 #if 0 /* Unused */
 const long  nFAULT_TAG = 0x49544c46;
 #endif
@@ -165,15 +165,17 @@ class GS7BGRasterBand : public GDALPamRasterBand
 /*                           GS7BGRasterBand()                          */
 /************************************************************************/
 
-GS7BGRasterBand::GS7BGRasterBand( GS7BGDataset *poDS, int nBand ) :
+GS7BGRasterBand::GS7BGRasterBand( GS7BGDataset *poDSIn, int nBandIn ) :
+    dfMinX(0.0), dfMaxX(0.0), dfMinY(0.0), dfMaxY(0.0), dfMinZ(0.0),
+    dfMaxZ(0.0),
     pafRowMinZ(NULL),
     pafRowMaxZ(NULL),
     nMinZRow(-1),
     nMaxZRow(-1)
 
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
 
     eDataType = GDT_Float64;
 
@@ -188,10 +190,8 @@ GS7BGRasterBand::GS7BGRasterBand( GS7BGDataset *poDS, int nBand ) :
 GS7BGRasterBand::~GS7BGRasterBand( )
 
 {
-    if( pafRowMinZ != NULL )
-        CPLFree( pafRowMinZ );
-    if( pafRowMaxZ != NULL )
-        CPLFree( pafRowMaxZ );
+    CPLFree( pafRowMinZ );
+    CPLFree( pafRowMaxZ );
 }
 
 /************************************************************************/
@@ -201,12 +201,11 @@ GS7BGRasterBand::~GS7BGRasterBand( )
 CPLErr GS7BGRasterBand::ScanForMinMaxZ()
 
 {
-    double *pafRowVals = (double *)VSIMalloc2( nRasterXSize, sizeof(double));
+    GS7BGDataset* poGDS = reinterpret_cast<GS7BGDataset*>(poDS);
+    double *pafRowVals = (double *)VSI_MALLOC2_VERBOSE( nRasterXSize, sizeof(double));
 
     if( pafRowVals == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory,
-          "Unable to allocate row buffer to scan grid file.\n" );
         return CE_Failure;
     }
 
@@ -232,7 +231,7 @@ CPLErr GS7BGRasterBand::ScanForMinMaxZ()
         pafRowMaxZ[iRow] = -FLT_MAX;
         for( int iCol=0; iCol<nRasterXSize; iCol++ )
         {
-            if( pafRowVals[iCol] == GS7BGDataset::dfNoData_Value )
+            if( pafRowVals[iCol] == poGDS->dfNoData_Value )
                 continue;
 
             if( pafRowVals[iCol] < pafRowMinZ[iRow] )
@@ -296,8 +295,8 @@ CPLErr GS7BGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     GS7BGDataset *poGDS = (GS7BGDataset *) ( poDS );
 
     if( VSIFSeekL( poGDS->fp,
-        ( GS7BGDataset::nData_Position +
-            sizeof(double) * nRasterXSize * (nRasterYSize - nBlockYOff - 1) ),
+        ( poGDS->nData_Position +
+            sizeof(double) * static_cast<vsi_l_offset>(nRasterXSize) * (nRasterYSize - nBlockYOff - 1) ),
         SEEK_SET ) != 0 )
     {
         CPLError( CE_Failure, CPLE_FileIO,
@@ -345,21 +344,17 @@ CPLErr GS7BGRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     if( pafRowMinZ == NULL || pafRowMaxZ == NULL
         || nMinZRow < 0 || nMaxZRow < 0 )
     {
-        pafRowMinZ = (double *)VSIMalloc2( nRasterYSize,sizeof(double) );
+        pafRowMinZ = (double *)VSI_MALLOC2_VERBOSE( nRasterYSize,sizeof(double) );
         if( pafRowMinZ == NULL )
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory,
-              "Unable to allocate space for row minimums array.\n" );
             return CE_Failure;
         }
 
-        pafRowMaxZ = (double *)VSIMalloc2( nRasterYSize,sizeof(double) );
+        pafRowMaxZ = (double *)VSI_MALLOC2_VERBOSE( nRasterYSize,sizeof(double) );
         if( pafRowMaxZ == NULL )
         {
             VSIFree( pafRowMinZ );
             pafRowMinZ = NULL;
-            CPLError( CE_Failure, CPLE_OutOfMemory,
-              "Unable to allocate space for row maximums array.\n" );
             return CE_Failure;
         }
 
@@ -383,7 +378,7 @@ CPLErr GS7BGRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     pafRowMaxZ[nBlockYOff] = -DBL_MAX;
     for( int iPixel=0; iPixel<nBlockXSize; iPixel++ )
     {
-        if( pdfImage[iPixel] != GS7BGDataset::dfNoData_Value )
+        if( pdfImage[iPixel] != poGDS->dfNoData_Value )
         {
             if( pdfImage[iPixel] < pafRowMinZ[nBlockYOff] )
                 pafRowMinZ[nBlockYOff] = pdfImage[iPixel];
@@ -479,10 +474,11 @@ CPLErr GS7BGRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
 
 double GS7BGRasterBand::GetNoDataValue( int * pbSuccess )
 {
+    GS7BGDataset* poGDS = reinterpret_cast<GS7BGDataset*>(poDS);
     if( pbSuccess )
         *pbSuccess = TRUE;
 
-    return GS7BGDataset::dfNoData_Value;
+    return poGDS->dfNoData_Value;
 }
 
 /************************************************************************/
@@ -533,7 +529,7 @@ int GS7BGDataset::Identify( GDALOpenInfo * poOpenInfo )
     /* Check for signature - for GS7BG the signature is the */
     /* nHEADER_TAG with reverse byte order.                 */
     if( poOpenInfo->nHeaderBytes < 4
-        || !EQUALN((const char *) poOpenInfo->pabyHeader,"DSRB",4) )
+        || !STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "DSRB") )
     {
         return FALSE;
     }
@@ -589,9 +585,6 @@ GDALDataset *GS7BGDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
     GInt32 nTag;
-    GInt32 nSize;
-    GInt32 nVersion;
-
     if( VSIFReadL( (void *)&nTag, sizeof(GInt32), 1, poDS->fp ) != 1 )
     {
         delete poDS;
@@ -608,7 +601,8 @@ GDALDataset *GS7BGDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    if( VSIFReadL( (void *)&nSize, sizeof(GInt32), 1, poDS->fp ) != 1 )
+    GUInt32 nSize;
+    if( VSIFReadL( (void *)&nSize, sizeof(GUInt32), 1, poDS->fp ) != 1 )
     {
         delete poDS;
         CPLError( CE_Failure, CPLE_FileIO,
@@ -618,6 +612,7 @@ GDALDataset *GS7BGDataset::Open( GDALOpenInfo * poOpenInfo )
 
     CPL_LSBPTR32( &nSize );
 
+    GInt32 nVersion;
     if( VSIFReadL( (void *)&nVersion, sizeof(GInt32), 1, poDS->fp ) != 1 )
     {
         delete poDS;
@@ -631,7 +626,7 @@ GDALDataset *GS7BGDataset::Open( GDALOpenInfo * poOpenInfo )
     if(nVersion != 1 && nVersion != 2)
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   "Incorrect file version (%d).", nVersion );
         return NULL;
     }
@@ -648,7 +643,7 @@ GDALDataset *GS7BGDataset::Open( GDALOpenInfo * poOpenInfo )
 
         CPL_LSBPTR32( &nTag );
 
-        if( VSIFReadL( (void *)&nSize, sizeof(GInt32), 1, poDS->fp ) != 1 )
+        if( VSIFReadL( (void *)&nSize, sizeof(GUInt32), 1, poDS->fp ) != 1 )
         {
             delete poDS;
             CPLError( CE_Failure, CPLE_FileIO,
@@ -660,7 +655,7 @@ GDALDataset *GS7BGDataset::Open( GDALOpenInfo * poOpenInfo )
 
         if(nTag != nGRID_TAG)
         {
-            if( VSIFSeekL( poDS->fp, nSize, SEEK_SET ) != 0 )
+            if( VSIFSeekL( poDS->fp, nSize, SEEK_CUR ) != 0 )
             {
                 delete poDS;
                 CPLError( CE_Failure, CPLE_FileIO,
@@ -707,6 +702,7 @@ GDALDataset *GS7BGDataset::Open( GDALOpenInfo * poOpenInfo )
     /*      Create band information objects.                               */
     /* --------------------------------------------------------------------*/
     GS7BGRasterBand *poBand = new GS7BGRasterBand( poDS, 1 );
+    poDS->SetBand( 1, poBand );
 
     // find the min X Value of the grid
     double dfTemp;
@@ -776,7 +772,6 @@ GDALDataset *GS7BGDataset::Open( GDALOpenInfo * poOpenInfo )
     }
     CPL_LSBPTR64( &dfTemp );
     poBand->dfMaxZ = dfTemp;
-    poDS->SetBand( 1, poBand );
 
     // read and ignore the rotation value
     //(This is not used in the current version).
@@ -905,7 +900,6 @@ CPLErr GS7BGDataset::SetGeoTransform( double *padfGeoTransform )
         return CE_Failure;
 
     /* non-zero transform 2 or 4 or negative 1 or 5 not supported natively */
-    CPLErr eErr = CE_None;
     /*if( padfGeoTransform[2] != 0.0 || padfGeoTransform[4] != 0.0
     || padfGeoTransform[1] < 0.0 || padfGeoTransform[5] < 0.0 )
     eErr = GDALPamDataset::SetGeoTransform( padfGeoTransform );
@@ -918,7 +912,7 @@ CPLErr GS7BGDataset::SetGeoTransform( double *padfGeoTransform )
     double dfMinY = padfGeoTransform[5] * (nRasterYSize - 0.5) + padfGeoTransform[3];
     double dfMaxY = padfGeoTransform[3] + padfGeoTransform[5] / 2;
 
-    eErr = WriteHeader( fp, poGRB->nRasterXSize, poGRB->nRasterYSize,
+    CPLErr eErr = WriteHeader( fp, poGRB->nRasterXSize, poGRB->nRasterYSize,
             dfMinX, dfMaxX, dfMinY, dfMaxY,
             poGRB->dfMinZ, poGRB->dfMaxZ );
 
@@ -1071,7 +1065,7 @@ CPLErr GS7BGDataset::WriteHeader( VSILFILE *fp, GInt32 nXSize, GInt32 nYSize,
         return CE_Failure;
     }
 
-    dfTemp = dfNoData_Value;  
+    dfTemp = dfDefaultNoDataValue;
     CPL_LSBPTR64( &dfTemp );
     if( VSIFWriteL( (void *)&dfTemp, sizeof(double), 1, fp ) != 1 )
     {
@@ -1089,7 +1083,7 @@ CPLErr GS7BGDataset::WriteHeader( VSILFILE *fp, GInt32 nXSize, GInt32 nYSize,
         return CE_Failure;
     }
 
-    int nSize = nXSize * nYSize * sizeof(double);
+    int nSize = nXSize * nYSize * (int)sizeof(double);
     nTemp = CPL_LSBWORD32(nSize); // Mark size of data
     if( VSIFWriteL( (void *)&nTemp, sizeof(GInt32), 1, fp ) != 1 )
     {
@@ -1160,7 +1154,7 @@ GDALDataset *GS7BGDataset::Create( const char * pszFilename,
         return NULL;
     }
 
-    double dfVal = dfNoData_Value;
+    double dfVal = dfDefaultNoDataValue;
     CPL_LSBPTR64( &dfVal );
     for( int iRow = 0; iRow < nYSize; iRow++ )
     {
@@ -1198,7 +1192,7 @@ GDALDataset *GS7BGDataset::CreateCopy( const char *pszFilename,
     int nBands = poSrcDS->GetRasterCount();
     if (nBands == 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "Driver does not support source dataset with zero band.\n");
         return NULL;
     }
@@ -1218,7 +1212,7 @@ GDALDataset *GS7BGDataset::CreateCopy( const char *pszFilename,
     }
 
     GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( 1 );
-    
+
     if( !pfnProgress( 0.0, NULL, pProgressData ) )
     {
         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated\n" );
@@ -1257,12 +1251,10 @@ GDALDataset *GS7BGDataset::CreateCopy( const char *pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Copy band data.                                                 */
 /* -------------------------------------------------------------------- */
-    double *pfData = (double *)VSIMalloc2( nXSize, sizeof( double ) );
+    double *pfData = (double *)VSI_MALLOC2_VERBOSE( nXSize, sizeof( double ) );
     if( pfData == NULL )
     {
         VSIFCloseL( fp );
-        CPLError( CE_Failure, CPLE_OutOfMemory,
-              "Unable to create copy, unable to allocate line buffer.\n" );
         return NULL;
     }
 
@@ -1287,7 +1279,7 @@ GDALDataset *GS7BGDataset::CreateCopy( const char *pszFilename,
         {
             if( bSrcHasNDValue && pfData[iCol] == dfSrcNoDataValue )
             {
-                pfData[iCol] = dfNoData_Value;
+                pfData[iCol] = dfDefaultNoDataValue;
             }
             else
             {
@@ -1298,7 +1290,7 @@ GDALDataset *GS7BGDataset::CreateCopy( const char *pszFilename,
                     dfMinZ = pfData[iCol];
             }
 
-            CPL_LSBPTR32( pfData+iCol );
+            CPL_LSBPTR64( pfData+iCol );
         }
 
         if( VSIFWriteL( (void *)pfData, sizeof( double ), nXSize,
@@ -1351,28 +1343,25 @@ GDALDataset *GS7BGDataset::CreateCopy( const char *pszFilename,
 void GDALRegister_GS7BG()
 
 {
-    GDALDriver    *poDriver;
-
-    if( GDALGetDriverByName( "GS7BG" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-
-        poDriver->SetDescription( "GS7BG" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Golden Software 7 Binary Grid (.grd)" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "frmt_various.html#GS7BG" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "grd" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
-            "Byte Int16 UInt16 Float32 Float64" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnIdentify = GS7BGDataset::Identify;
-        poDriver->pfnOpen = GS7BGDataset::Open;
-        poDriver->pfnCreate = GS7BGDataset::Create;
-        poDriver->pfnCreateCopy = GS7BGDataset::CreateCopy;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    if( GDALGetDriverByName( "GS7BG" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "GS7BG" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Golden Software 7 Binary Grid (.grd)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#GS7BG" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "grd" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte Int16 UInt16 Float32 Float64" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnIdentify = GS7BGDataset::Identify;
+    poDriver->pfnOpen = GS7BGDataset::Open;
+    poDriver->pfnCreate = GS7BGDataset::Create;
+    poDriver->pfnCreateCopy = GS7BGDataset::CreateCopy;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/gsg/gsagdataset.cpp b/frmts/gsg/gsagdataset.cpp
index 1790276..f011b65 100644
--- a/frmts/gsg/gsagdataset.cpp
+++ b/frmts/gsg/gsagdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gsagdataset.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: gsagdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Implements the Golden Software ASCII Grid Format.
@@ -36,6 +36,7 @@
 #include <limits.h>
 #include <assert.h>
 
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 
 #ifndef DBL_MAX
@@ -50,11 +51,7 @@
 # define INT_MAX 2147483647
 #endif /* INT_MAX */
 
-CPL_CVSID("$Id: gsagdataset.cpp 28053 2014-12-04 09:31:07Z rouault $");
-
-CPL_C_START
-void	GDALRegister_GSAG(void);
-CPL_C_END
+CPL_CVSID("$Id: gsagdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -120,7 +117,8 @@ class GSAGRasterBand : public GDALPamRasterBand
     double dfMaxZ;
 
     vsi_l_offset *panLineOffset;
-	int nLastReadLine;
+    int nLastReadLine;
+    size_t nMaxLineSize;
 
     double *padfRowMinZ;
     double *padfRowMaxZ;
@@ -133,7 +131,7 @@ class GSAGRasterBand : public GDALPamRasterBand
 
     		GSAGRasterBand( GSAGDataset *, int, vsi_l_offset );
     		~GSAGRasterBand();
-    
+
     CPLErr IReadBlock( int, int, void * );
     CPLErr IWriteBlock( int, int, void * );
 
@@ -150,7 +148,7 @@ class GSAGRasterBand : public GDALPamRasterBand
 /* explanation.								*/
 /************************************************************************/
 
-bool AlmostEqual( double dfVal1, double dfVal2 )
+static bool AlmostEqual( double dfVal1, double dfVal2 )
 
 {
     const double dfTOLERANCE = 0.0000000001;
@@ -163,34 +161,38 @@ bool AlmostEqual( double dfVal1, double dfVal2 )
 /*                           GSAGRasterBand()                           */
 /************************************************************************/
 
-GSAGRasterBand::GSAGRasterBand( GSAGDataset *poDS, int nBand,
+GSAGRasterBand::GSAGRasterBand( GSAGDataset *poDSIn, int nBandIn,
 				vsi_l_offset nDataStart ) :
+    dfMinX(0.0),
+    dfMaxX(0.0),
+    dfMinY(0.0),
+    dfMaxY(0.0),
+    dfMinZ(0.0),
+    dfMaxZ(0.0),
+    nLastReadLine(0),
+    nMaxLineSize(128),
     padfRowMinZ(NULL),
     padfRowMaxZ(NULL),
     nMinZRow(-1),
     nMaxZRow(-1)
-
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
-    
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
+
     eDataType = GDT_Float64;
 
     nBlockXSize = poDS->GetRasterXSize();
     nBlockYSize = 1;
 
     panLineOffset =
-	(vsi_l_offset *)VSICalloc( poDS->nRasterYSize+1, sizeof(vsi_l_offset) );
+	(vsi_l_offset *)VSI_CALLOC_VERBOSE( poDSIn->nRasterYSize+1, sizeof(vsi_l_offset) );
     if( panLineOffset == NULL )
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory,
-                 "GSAGRasterBand::GSAGRasterBand : Out of memory allocating %d * %d bytes",
-                 (int) poDS->nRasterYSize+1, (int) sizeof(vsi_l_offset) );
 	return;
     }
 
-	panLineOffset[poDS->nRasterYSize-1] = nDataStart;
-	nLastReadLine = poDS->nRasterYSize;
+    panLineOffset[poDSIn->nRasterYSize-1] = nDataStart;
+    nLastReadLine = poDSIn->nRasterYSize;
 }
 
 /************************************************************************/
@@ -200,10 +202,8 @@ GSAGRasterBand::GSAGRasterBand( GSAGDataset *poDS, int nBand,
 GSAGRasterBand::~GSAGRasterBand()
 {
     CPLFree( panLineOffset );
-    if( padfRowMinZ != NULL )
-	CPLFree( padfRowMinZ );
-    if( padfRowMaxZ != NULL )
-	CPLFree( padfRowMaxZ );
+    CPLFree( padfRowMinZ );
+    CPLFree( padfRowMaxZ );
 }
 
 /************************************************************************/
@@ -213,11 +213,9 @@ GSAGRasterBand::~GSAGRasterBand()
 CPLErr GSAGRasterBand::ScanForMinMaxZ()
 
 {
-    double *padfRowValues = (double *)VSIMalloc2( nBlockXSize, sizeof(double) );
+    double *padfRowValues = (double *)VSI_MALLOC2_VERBOSE( nBlockXSize, sizeof(double) );
     if( padfRowValues == NULL )
     {
-	CPLError( CE_Failure, CPLE_OutOfMemory,
-		  "Unable to allocate memory for grid row values.\n" );
 	return CE_Failure;
     }
 
@@ -300,12 +298,11 @@ CPLErr GSAGRasterBand::ScanForMinMaxZ()
 CPLErr GSAGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 				   void * pImage )
 {
-    static size_t nMaxLineSize = 128;
-    double *pdfImage = (double *)pImage;
     GSAGDataset *poGDS = (GSAGDataset *)poDS;
-
     assert( poGDS != NULL );
 
+    double *pdfImage = (double *)pImage;
+
     if( nBlockYOff < 0 || nBlockYOff > nRasterYSize - 1 || nBlockXOff != 0 )
         return CE_Failure;
 
@@ -329,10 +326,7 @@ CPLErr GSAGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         return CE_Failure;
     }
 
-    size_t nLineBufSize;
-    char *szLineBuf = NULL;
-    size_t nCharsRead;
-    size_t nCharsExamined = 0;
+    size_t nLineBufSize = nMaxLineSize;
     /* If we know the offsets, we can just read line directly */
     if( (nBlockYOff > 0) && ( panLineOffset[nBlockYOff-1] != 0 ) )
     {
@@ -340,20 +334,14 @@ CPLErr GSAGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 	nLineBufSize = (size_t) (panLineOffset[nBlockYOff-1]
                                  - panLineOffset[nBlockYOff] + 1);
     }
-    else
-    {
-	nLineBufSize = nMaxLineSize;
-    }
 
-    szLineBuf = (char *)VSIMalloc( nLineBufSize );
+    char *szLineBuf = (char *)VSI_MALLOC_VERBOSE( nLineBufSize );
     if( szLineBuf == NULL )
     {
-	CPLError( CE_Failure, CPLE_OutOfMemory,
-		  "Unable to read block, unable to allocate line buffer.\n" );
 	return CE_Failure;
     }
 
-    nCharsRead = VSIFReadL( szLineBuf, 1, nLineBufSize - 1, poGDS->fp );
+    size_t nCharsRead = VSIFReadL( szLineBuf, 1, nLineBufSize - 1, poGDS->fp );
     if( nCharsRead == 0 )
     {
 	VSIFree( szLineBuf );
@@ -364,6 +352,7 @@ CPLErr GSAGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     }
     szLineBuf[nCharsRead] = '\0';
 
+    size_t nCharsExamined = 0;
     char *szStart = szLineBuf;
     char *szEnd = szStart;
     for( int iCell=0; iCell<nBlockXSize; szStart = szEnd )
@@ -372,28 +361,38 @@ CPLErr GSAGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 	if( szStart == szEnd )
 	{
 	    /* No number found */
+            if( *szStart == '.' )
+            {
+                CPLError( CE_Warning, CPLE_FileIO,
+                          "Unexpected value in grid row %d (expected floating "
+                          "point value, found \"%s\").\n",
+                          nBlockYOff, szStart );
+                return CE_Failure;
+            }
 
 	    /* Check if this was an expected failure */
 	    while( isspace( (unsigned char)*szStart ) )
 		szStart++;
 
 	    /* Found sign at end of input, seek back to re-read it */
+            bool bOnlySign = false;
 	    if ( (*szStart == '-' || *szStart == '+') && *(szStart+1) == '\0' )
 	    {
-	    	if( VSIFSeekL( poGDS->fp, 
-                               VSIFTellL( poGDS->fp)-1, 
+	    	if( VSIFSeekL( poGDS->fp,
+                               VSIFTellL( poGDS->fp)-1,
                                SEEK_SET ) != 0 )
 	    	{
 		    VSIFree( szLineBuf );
 		    CPLError( CE_Failure, CPLE_FileIO,
 			      "Unable to seek in grid row %d "
 			      "(offset %ld, seek %d).\n",
-			      nBlockYOff, 
+			      nBlockYOff,
                               (long) VSIFTellL(poGDS->fp),
 			      -1 );
 
 		    return CE_Failure;
 		}
+		bOnlySign = true;
 	    }
 	    else if( *szStart != '\0' )
 	    {
@@ -420,8 +419,8 @@ CPLErr GSAGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 	    {
 		CPLError( CE_Warning, CPLE_FileIO,
 			  "Unexpected ASCII null-character in grid row %d at "
-			  "offset %ld.\n", 
-                          nBlockYOff, 
+			  "offset %ld.\n",
+                          nBlockYOff,
                           (long) (szStart - szLineBuf) );
 
 		while( *szStart == '\0' &&
@@ -434,7 +433,7 @@ CPLErr GSAGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
 	    nCharsExamined += szStart - szLineBuf;
 	    nCharsRead = VSIFReadL( szLineBuf, 1, nLineBufSize - 1, poGDS->fp );
-	    if( nCharsRead == 0 )
+	    if( nCharsRead == 0 || (bOnlySign && nCharsRead == 1) )
 	    {
 		VSIFree( szLineBuf );
 		CPLError( CE_Failure, CPLE_FileIO,
@@ -443,7 +442,7 @@ CPLErr GSAGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 		return CE_Failure;
 	    }
 	    szLineBuf[nCharsRead] = '\0';
-	    szStart = szEnd = szLineBuf;
+	    szEnd = szLineBuf;
 	    continue;
 	}
 	else if( *szEnd == '\0'
@@ -465,24 +464,24 @@ CPLErr GSAGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 	    {
 		CPLError( CE_Warning, CPLE_FileIO,
 			  "Unexpected ASCII null-character in grid row %d at "
-			  "offset %ld.\n", 
-                          nBlockYOff, 
+			  "offset %ld.\n",
+                          nBlockYOff,
                           (long) (szStart - szLineBuf) );
 
 		while( *szEnd == '\0' &&
-		       static_cast<size_t>(szStart - szLineBuf) < nCharsRead )
+		       static_cast<size_t>(szEnd - szLineBuf) < nCharsRead )
 		    szEnd++;
 
 		continue;
 	    }
 
 	    /* End of buffer, could be interrupting a number */
-	    if( VSIFSeekL( poGDS->fp, szStart - szEnd, SEEK_CUR ) != 0 )
+	    if( VSIFSeekL( poGDS->fp, VSIFTellL(poGDS->fp) + szStart - szEnd, SEEK_SET ) != 0 )
 	    {
 		VSIFree( szLineBuf );
 		CPLError( CE_Failure, CPLE_FileIO,
 			  "Unable to seek in grid row %d (offset %ld, seek %d)"
-			  ".\n", nBlockYOff, 
+			  ".\n", nBlockYOff,
                           (long) VSIFTellL(poGDS->fp),
 			  (int) (szStart - szEnd) );
 
@@ -508,7 +507,6 @@ CPLErr GSAGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 	    }
 
 	    /* This is really the last value and has no tailing newline */
-	    szStart = szLineBuf;
 	    szEnd = szLineBuf + nCharsRead;
 	}
 
@@ -536,7 +534,7 @@ CPLErr GSAGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 	nMaxLineSize = nCharsExamined + 1;
 
     if( nBlockYOff > 0 )
-        panLineOffset[nBlockYOff - 1] = 
+        panLineOffset[nBlockYOff - 1] =
             panLineOffset[nBlockYOff] + nCharsExamined;
 
     nLastReadLine = nBlockYOff;
@@ -570,21 +568,17 @@ CPLErr GSAGRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     if( padfRowMinZ == NULL || padfRowMaxZ == NULL
 	|| nMinZRow < 0 || nMaxZRow < 0 )
     {
-	padfRowMinZ = (double *)VSIMalloc2( nRasterYSize,sizeof(double) );
+	padfRowMinZ = (double *)VSI_MALLOC2_VERBOSE( nRasterYSize,sizeof(double) );
 	if( padfRowMinZ == NULL )
 	{
-	    CPLError( CE_Failure, CPLE_OutOfMemory,
-		      "Unable to allocate space for row minimums array.\n" );
 	    return CE_Failure;
 	}
 
-	padfRowMaxZ = (double *)VSIMalloc2( nRasterYSize,sizeof(double) );
+	padfRowMaxZ = (double *)VSI_MALLOC2_VERBOSE( nRasterYSize,sizeof(double) );
 	if( padfRowMaxZ == NULL )
 	{
 	    VSIFree( padfRowMinZ );
 	    padfRowMinZ = NULL;
-	    CPLError( CE_Failure, CPLE_OutOfMemory,
-		      "Unable to allocate space for row maximums array.\n" );
 	    return CE_Failure;
 	}
 
@@ -773,21 +767,21 @@ double GSAGRasterBand::GetMaximum( int *pbSuccess )
 /*                             GSAGDataset()                            */
 /************************************************************************/
 
-GSAGDataset::GSAGDataset( const char *pszEOL )
-
+GSAGDataset::GSAGDataset( const char *pszEOL ) :
+    fp(NULL),
+    nMinMaxZOffset(0)
 {
     if( pszEOL == NULL || EQUAL(pszEOL, "") )
     {
 	CPLDebug( "GSAG", "GSAGDataset() created with invalid EOL string.\n" );
-	this->szEOL[0] = '\x0D';
-	this->szEOL[1] = '\x0A';
-	this->szEOL[2] = '\0';
-    }
-    else
-    {
-        strncpy(this->szEOL, pszEOL, sizeof(this->szEOL));
-	this->szEOL[sizeof(this->szEOL) - 1] = '\0';
+	szEOL[0] = '\x0D';
+	szEOL[1] = '\x0A';
+	szEOL[2] = '\0';
+        return;
     }
+
+    strncpy(szEOL, pszEOL, sizeof(szEOL));
+    szEOL[sizeof(this->szEOL) - 1] = '\0';
 }
 
 /************************************************************************/
@@ -811,7 +805,7 @@ int GSAGDataset::Identify( GDALOpenInfo * poOpenInfo )
 {
     /* Check for signature */
     if( poOpenInfo->nHeaderBytes < 5
-        || !EQUALN((const char *) poOpenInfo->pabyHeader,"DSAA",4)
+        || !STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "DSAA")
         || ( poOpenInfo->pabyHeader[4] != '\x0D'
             && poOpenInfo->pabyHeader[4] != '\x0A' ))
     {
@@ -858,13 +852,13 @@ GDALDataset *GSAGDataset::Open( GDALOpenInfo * poOpenInfo )
 
     if( poDS->fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "VSIFOpenL(%s) failed unexpectedly.", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "VSIFOpenL(%s) failed unexpectedly.",
                   poOpenInfo->pszFilename );
 	delete poDS;
         return NULL;
     }
- 
+
 /* -------------------------------------------------------------------- */
 /*      Read the header.                                                */
 /* -------------------------------------------------------------------- */
@@ -877,11 +871,10 @@ GDALDataset *GSAGDataset::Open( GDALOpenInfo * poOpenInfo )
     else
     {
 	bMustFreeHeader = true;
-	pabyHeader = (char *)VSIMalloc( nMAX_HEADER_SIZE );
+	pabyHeader = (char *)VSI_MALLOC_VERBOSE( nMAX_HEADER_SIZE );
 	if( pabyHeader == NULL )
 	{
-	    CPLError( CE_Failure, CPLE_OutOfMemory,
-		      "Unable to open dataset, unable to header buffer.\n" );
+            delete poDS;
 	    return NULL;
 	}
 
@@ -893,12 +886,6 @@ GDALDataset *GSAGDataset::Open( GDALOpenInfo * poOpenInfo )
     const char *szStart = pabyHeader + 5;
     char *szEnd;
     double dfTemp;
-    double dfMinX;
-    double dfMaxX;
-    double dfMinY;
-    double dfMaxY;
-    double dfMinZ;
-    double dfMaxZ;
 
     /* Parse number of X axis grid rows */
     long nTemp = strtol( szStart, &szEnd, 10 );
@@ -931,11 +918,11 @@ GDALDataset *GSAGDataset::Open( GDALOpenInfo * poOpenInfo )
 	szErrorMsg = "Unable to parse the number of Y axis grid rows.\n";
 	goto error;
     }
-    else if( nTemp > INT_MAX )
+    else if( nTemp > INT_MAX - 1 )
     {
 	CPLError( CE_Warning, CPLE_AppDefined,
 		  "Number of Y axis grid rows not representable.\n" );
-	poDS->nRasterYSize = INT_MAX;
+	poDS->nRasterYSize = INT_MAX - 1;
     }
     else if ( nTemp == 0)
     {
@@ -949,6 +936,7 @@ GDALDataset *GSAGDataset::Open( GDALOpenInfo * poOpenInfo )
     szStart = szEnd;
 
     /* Parse the minimum X value of the grid */
+    double dfMinX;
     dfTemp = CPLStrtod( szStart, &szEnd );
     if( szStart == szEnd )
     {
@@ -962,6 +950,7 @@ GDALDataset *GSAGDataset::Open( GDALOpenInfo * poOpenInfo )
     szStart = szEnd;
 
     /* Parse the maximum X value of the grid */
+    double dfMaxX;
     dfTemp = CPLStrtod( szStart, &szEnd );
     if( szStart == szEnd )
     {
@@ -975,6 +964,7 @@ GDALDataset *GSAGDataset::Open( GDALOpenInfo * poOpenInfo )
     szStart = szEnd;
 
     /* Parse the minimum Y value of the grid */
+    double dfMinY;
     dfTemp = CPLStrtod( szStart, &szEnd );
     if( szStart == szEnd )
     {
@@ -988,6 +978,7 @@ GDALDataset *GSAGDataset::Open( GDALOpenInfo * poOpenInfo )
     szStart = szEnd;
 
     /* Parse the maximum Y value of the grid */
+    double dfMaxY;
     dfTemp = CPLStrtod( szStart, &szEnd );
     if( szStart == szEnd )
     {
@@ -1005,6 +996,7 @@ GDALDataset *GSAGDataset::Open( GDALOpenInfo * poOpenInfo )
 	szStart++;
     poDS->nMinMaxZOffset = szStart - pabyHeader;
 
+    double dfMinZ;
     dfTemp = CPLStrtod( szStart, &szEnd );
     if( szStart == szEnd )
     {
@@ -1018,6 +1010,7 @@ GDALDataset *GSAGDataset::Open( GDALOpenInfo * poOpenInfo )
     szStart = szEnd;
 
     /* Parse the maximum Z value of the grid */
+    double dfMaxZ;
     dfTemp = CPLStrtod( szStart, &szEnd );
     if( szStart == szEnd )
     {
@@ -1152,14 +1145,13 @@ CPLErr GSAGDataset::SetGeoTransform( double *padfGeoTransform )
     /*if( padfGeoTransform[2] != 0.0 || padfGeoTransform[4] != 0.0
 	|| padfGeoTransform[1] < 0.0 || padfGeoTransform[5] < 0.0 )
 	eErr = GDALPamDataset::SetGeoTransform( padfGeoTransform );*/
+    // if( eErr != CE_None )
+    //     return eErr;
 
-    if( eErr != CE_None )
-	return eErr;
-
-    double dfOldMinX = poGRB->dfMinX;
-    double dfOldMaxX = poGRB->dfMaxX;
-    double dfOldMinY = poGRB->dfMinY;
-    double dfOldMaxY = poGRB->dfMaxY;
+    const double dfOldMinX = poGRB->dfMinX;
+    const double dfOldMaxX = poGRB->dfMaxX;
+    const double dfOldMinY = poGRB->dfMinY;
+    const double dfOldMaxY = poGRB->dfMaxY;
 
     poGRB->dfMinX = padfGeoTransform[0] + padfGeoTransform[1] / 2;
     poGRB->dfMaxX =
@@ -1196,7 +1188,7 @@ CPLErr GSAGDataset::ShiftFileContents( VSILFILE *fp, vsi_l_offset nShiftStart,
     if( /* nShiftStart < 0
            || */ (nShiftSize < 0
 	    && nShiftStart < static_cast<vsi_l_offset>(-nShiftSize)) )
-	nShiftStart = (nShiftSize > 0) ? 0 : -nShiftSize;
+	nShiftStart = /*(nShiftSize > 0) ? 0 :*/  -nShiftSize;
 
     /* get offset at end of file */
     if( VSIFSeekL( fp, 0, SEEK_END ) != 0 )
@@ -1257,11 +1249,9 @@ CPLErr GSAGDataset::ShiftFileContents( VSILFILE *fp, vsi_l_offset nShiftStart,
 
     /* prepare buffer for real shifting */
     size_t nBufferSize = (1024 >= abs(nShiftSize)*2) ? 1024 : abs(nShiftSize)*2;
-    char *pabyBuffer = (char *)VSIMalloc( nBufferSize );
+    char *pabyBuffer = (char *)VSI_MALLOC_VERBOSE( nBufferSize );
     if( pabyBuffer == NULL)
     {
-	CPLError( CE_Failure, CPLE_OutOfMemory,
-		  "Unable to allocate space for shift buffer.\n" );
 	return CE_Failure;
     }
 
@@ -1333,7 +1323,7 @@ CPLErr GSAGDataset::ShiftFileContents( VSILFILE *fp, vsi_l_offset nShiftStart,
 
         if( VSIFEofL( fp ) )
             bEOF = true;
-        else 
+        else
             bEOF = false;
 
 	if( nRead == 0 && !bEOF )
@@ -1516,7 +1506,7 @@ GDALDataset *GSAGDataset::CreateCopy( const char *pszFilename,
     int nBands = poSrcDS->GetRasterCount();
     if (nBands == 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "GSAG driver does not support source dataset with zero band.\n");
         return NULL;
     }
@@ -1551,8 +1541,8 @@ GDALDataset *GSAGDataset::CreateCopy( const char *pszFilename,
         return NULL;
     }
 
-    int          nXSize = poSrcDS->GetRasterXSize();
-    int          nYSize = poSrcDS->GetRasterYSize();
+    const int nXSize = poSrcDS->GetRasterXSize();
+    const int nYSize = poSrcDS->GetRasterYSize();
     double	 adfGeoTransform[6];
 
     poSrcDS->GetGeoTransform( adfGeoTransform );
@@ -1598,12 +1588,10 @@ GDALDataset *GSAGDataset::CreateCopy( const char *pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Copy band data.							*/
 /* -------------------------------------------------------------------- */
-    double *pdfData = (double *)VSIMalloc2( nXSize, sizeof( double ) );
+    double *pdfData = (double *)VSI_MALLOC2_VERBOSE( nXSize, sizeof( double ) );
     if( pdfData == NULL )
     {
 	VSIFCloseL( fp );
-	CPLError( CE_Failure, CPLE_OutOfMemory,
-		  "Unable to create copy, unable to allocate line buffer.\n" );
 	return NULL;
     }
 
@@ -1701,7 +1689,7 @@ GDALDataset *GSAGDataset::CreateCopy( const char *pszFilename,
     ssRange << dfMin << " " << dfMax << "\x0D\x0A";
     if( ssRange.str().length() != nDummyRangeLen )
     {
-	int nShiftSize = ssRange.str().length() - nDummyRangeLen;
+	int nShiftSize = static_cast<int>(ssRange.str().length() - nDummyRangeLen);
 	if( ShiftFileContents( fp, nRangeStart + nDummyRangeLen,
 			       nShiftSize, "\x0D\x0A" ) != CE_None )
 	{
@@ -1741,34 +1729,31 @@ GDALDataset *GSAGDataset::CreateCopy( const char *pszFilename,
 }
 
 /************************************************************************/
-/*                          GDALRegister_GSAG()                          */
+/*                          GDALRegister_GSAG()                         */
 /************************************************************************/
 
 void GDALRegister_GSAG()
 
 {
-    GDALDriver	*poDriver;
-
-    if( GDALGetDriverByName( "GSAG" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "GSAG" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Golden Software ASCII Grid (.grd)" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#GSAG" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "grd" );
-	poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
-				   "Byte Int16 UInt16 Int32 UInt32 "
-				   "Float32 Float64" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnIdentify = GSAGDataset::Identify;
-        poDriver->pfnOpen = GSAGDataset::Open;
-        poDriver->pfnCreateCopy = GSAGDataset::CreateCopy;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    if( GDALGetDriverByName( "GSAG" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "GSAG" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Golden Software ASCII Grid (.grd)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#GSAG" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "grd" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte Int16 UInt16 Int32 UInt32 "
+                               "Float32 Float64" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnIdentify = GSAGDataset::Identify;
+    poDriver->pfnOpen = GSAGDataset::Open;
+    poDriver->pfnCreateCopy = GSAGDataset::CreateCopy;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/gsg/gsbgdataset.cpp b/frmts/gsg/gsbgdataset.cpp
index fc30544..1b1df5e 100644
--- a/frmts/gsg/gsbgdataset.cpp
+++ b/frmts/gsg/gsbgdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gsbgdataset.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: gsbgdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Implements the Golden Software Binary Grid Format.
@@ -35,6 +35,7 @@
 #include <limits.h>
 #include <assert.h>
 
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 
 #ifndef DBL_MAX
@@ -61,11 +62,7 @@
 # define SHRT_MAX 32767
 #endif /* SHRT_MAX */
 
-CPL_CVSID("$Id: gsbgdataset.cpp 28053 2014-12-04 09:31:07Z rouault $");
-
-CPL_C_START
-void	GDALRegister_GSBG(void);
-CPL_C_END
+CPL_CVSID("$Id: gsbgdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -90,6 +87,7 @@ class GSBGDataset : public GDALPamDataset
     VSILFILE	*fp;
 
   public:
+                 GSBGDataset() : fp(NULL) {}
 		~GSBGDataset();
 
     static int          Identify( GDALOpenInfo * );
@@ -142,7 +140,7 @@ class GSBGRasterBand : public GDALPamRasterBand
 
     		GSBGRasterBand( GSBGDataset *, int );
 		~GSBGRasterBand();
-    
+
     CPLErr IReadBlock( int, int, void * );
     CPLErr IWriteBlock( int, int, void * );
 
@@ -155,16 +153,21 @@ class GSBGRasterBand : public GDALPamRasterBand
 /*                           GSBGRasterBand()                           */
 /************************************************************************/
 
-GSBGRasterBand::GSBGRasterBand( GSBGDataset *poDS, int nBand ) :
+GSBGRasterBand::GSBGRasterBand( GSBGDataset *poDSIn, int nBandIn ) :
+    dfMinX(0.0),
+    dfMaxX(0.0),
+    dfMinY(0.0),
+    dfMaxY(0.0),
+    dfMinZ(0.0),
+    dfMaxZ(0.0),
     pafRowMinZ(NULL),
     pafRowMaxZ(NULL),
     nMinZRow(-1),
     nMaxZRow(-1)
-
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
-    
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
+
     eDataType = GDT_Float32;
 
     nBlockXSize = poDS->GetRasterXSize();
@@ -191,12 +194,10 @@ GSBGRasterBand::~GSBGRasterBand( )
 CPLErr GSBGRasterBand::ScanForMinMaxZ()
 
 {
-    float *pafRowVals = (float *)VSIMalloc2( nRasterXSize, 4 );
+    float *pafRowVals = (float *)VSI_MALLOC2_VERBOSE( nRasterXSize, 4 );
 
     if( pafRowVals == NULL )
     {
-	CPLError( CE_Failure, CPLE_OutOfMemory,
-		  "Unable to allocate row buffer to scan grid file.\n" );
 	return CE_Failure;
     }
 
@@ -283,10 +284,10 @@ CPLErr GSBGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     if( nBlockYOff < 0 || nBlockYOff > nRasterYSize - 1 || nBlockXOff != 0 )
 	return CE_Failure;
 
-    GSBGDataset *poGDS = dynamic_cast<GSBGDataset *>(poDS);
+    GSBGDataset *poGDS = reinterpret_cast<GSBGDataset *>(poDS);
     if( VSIFSeekL( poGDS->fp,
 		   GSBGDataset::nHEADER_SIZE +
-                        4 * nRasterXSize * (nRasterYSize - nBlockYOff - 1),
+                        4 * static_cast<vsi_l_offset>(nRasterXSize) * (nRasterYSize - nBlockYOff - 1),
 		   SEEK_SET ) != 0 )
     {
 	CPLError( CE_Failure, CPLE_FileIO,
@@ -336,21 +337,17 @@ CPLErr GSBGRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     if( pafRowMinZ == NULL || pafRowMaxZ == NULL
 	|| nMinZRow < 0 || nMaxZRow < 0 )
     {
-	pafRowMinZ = (float *)VSIMalloc2( nRasterYSize,sizeof(float) );
+	pafRowMinZ = (float *)VSI_MALLOC2_VERBOSE( nRasterYSize,sizeof(float) );
 	if( pafRowMinZ == NULL )
 	{
-	    CPLError( CE_Failure, CPLE_OutOfMemory,
-		      "Unable to allocate space for row minimums array.\n" );
 	    return CE_Failure;
 	}
 
-	pafRowMaxZ = (float *)VSIMalloc2( nRasterYSize,sizeof(float) );
+	pafRowMaxZ = (float *)VSI_MALLOC2_VERBOSE( nRasterYSize,sizeof(float) );
 	if( pafRowMaxZ == NULL )
 	{
 	    VSIFree( pafRowMinZ );
 	    pafRowMinZ = NULL;
-	    CPLError( CE_Failure, CPLE_OutOfMemory,
-		      "Unable to allocate space for row maximums array.\n" );
 	    return CE_Failure;
 	}
 
@@ -454,7 +451,7 @@ CPLErr GSBGRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     if( bHeaderNeedsUpdate && dfMaxZ > dfMinZ )
     {
 	CPLErr eErr = poGDS->WriteHeader( poGDS->fp,
-					  (GInt16) nRasterXSize, 
+					  (GInt16) nRasterXSize,
                                           (GInt16) nRasterYSize,
 					  dfMinX, dfMaxX,
 					  dfMinY, dfMaxY,
@@ -524,7 +521,7 @@ int GSBGDataset::Identify( GDALOpenInfo * poOpenInfo )
 {
     /* Check for signature */
     if( poOpenInfo->nHeaderBytes < 4
-        || !EQUALN((const char *) poOpenInfo->pabyHeader,"DSBB",4) )
+        || !STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "DSBB") )
     {
         return FALSE;
     }
@@ -561,12 +558,12 @@ GDALDataset *GSBGDataset::Open( GDALOpenInfo * poOpenInfo )
     if( poDS->fp == NULL )
     {
 	delete poDS;
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "VSIFOpenL(%s) failed unexpectedly.", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "VSIFOpenL(%s) failed unexpectedly.",
                   poOpenInfo->pszFilename );
         return NULL;
     }
- 
+
 /* -------------------------------------------------------------------- */
 /*      Read the header.                                                */
 /* -------------------------------------------------------------------- */
@@ -611,6 +608,7 @@ GDALDataset *GSBGDataset::Open( GDALOpenInfo * poOpenInfo )
     if( VSIFReadL( (void *)&dfTemp, 8, 1, poDS->fp ) != 1 )
     {
 	delete poDS;
+        delete poBand;
 	CPLError( CE_Failure, CPLE_FileIO,
 		  "Unable to read minimum X value.\n" );
 	return NULL;
@@ -621,6 +619,7 @@ GDALDataset *GSBGDataset::Open( GDALOpenInfo * poOpenInfo )
     if( VSIFReadL( (void *)&dfTemp, 8, 1, poDS->fp ) != 1 )
     {
 	delete poDS;
+        delete poBand;
 	CPLError( CE_Failure, CPLE_FileIO,
 		  "Unable to read maximum X value.\n" );
 	return NULL;
@@ -631,6 +630,7 @@ GDALDataset *GSBGDataset::Open( GDALOpenInfo * poOpenInfo )
     if( VSIFReadL( (void *)&dfTemp, 8, 1, poDS->fp ) != 1 )
     {
 	delete poDS;
+        delete poBand;
 	CPLError( CE_Failure, CPLE_FileIO,
 		  "Unable to read minimum Y value.\n" );
 	return NULL;
@@ -641,6 +641,7 @@ GDALDataset *GSBGDataset::Open( GDALOpenInfo * poOpenInfo )
     if( VSIFReadL( (void *)&dfTemp, 8, 1, poDS->fp ) != 1 )
     {
 	delete poDS;
+        delete poBand;
 	CPLError( CE_Failure, CPLE_FileIO,
 		  "Unable to read maximum Y value.\n" );
 	return NULL;
@@ -651,6 +652,7 @@ GDALDataset *GSBGDataset::Open( GDALOpenInfo * poOpenInfo )
     if( VSIFReadL( (void *)&dfTemp, 8, 1, poDS->fp ) != 1 )
     {
 	delete poDS;
+        delete poBand;
 	CPLError( CE_Failure, CPLE_FileIO,
 		  "Unable to read minimum Z value.\n" );
 	return NULL;
@@ -661,6 +663,7 @@ GDALDataset *GSBGDataset::Open( GDALOpenInfo * poOpenInfo )
     if( VSIFReadL( (void *)&dfTemp, 8, 1, poDS->fp ) != 1 )
     {
 	delete poDS;
+        delete poBand;
 	CPLError( CE_Failure, CPLE_FileIO,
 		  "Unable to read maximum Z value.\n" );
 	return NULL;
@@ -763,8 +766,8 @@ CPLErr GSBGDataset::SetGeoTransform( double *padfGeoTransform )
         padfGeoTransform[5] * (nRasterYSize - 0.5) + padfGeoTransform[3];
     double dfMaxY = padfGeoTransform[3] + padfGeoTransform[5] / 2;
 
-    eErr = WriteHeader( fp, 
-                        (GInt16) poGRB->nRasterXSize, 
+    eErr = WriteHeader( fp,
+                        (GInt16) poGRB->nRasterXSize,
                         (GInt16) poGRB->nRasterYSize,
 			dfMinX, dfMaxX, dfMinY, dfMaxY,
 			poGRB->dfMinZ, poGRB->dfMaxZ );
@@ -927,7 +930,7 @@ GDALDataset *GSBGDataset::Create( const char * pszFilename,
                   pszFilename );
         return NULL;
     }
-    
+
     CPLErr eErr = WriteHeader( fp, (GInt16) nXSize, (GInt16) nYSize,
 			       0.0, nXSize, 0.0, nYSize, 0.0, 0.0 );
     if( eErr != CE_None )
@@ -974,7 +977,7 @@ GDALDataset *GSBGDataset::CreateCopy( const char *pszFilename,
     int nBands = poSrcDS->GetRasterCount();
     if (nBands == 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "GSBG driver does not support source dataset with zero band.\n");
         return NULL;
     }
@@ -1044,12 +1047,10 @@ GDALDataset *GSBGDataset::CreateCopy( const char *pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Copy band data.							*/
 /* -------------------------------------------------------------------- */
-    float *pfData = (float *)VSIMalloc2( nXSize, sizeof( float ) );
+    float *pfData = (float *)VSI_MALLOC2_VERBOSE( nXSize, sizeof( float ) );
     if( pfData == NULL )
     {
 	VSIFCloseL( fp );
-	CPLError( CE_Failure, CPLE_OutOfMemory,
-		  "Unable to create copy, unable to allocate line buffer.\n" );
 	return NULL;
     }
 
@@ -1132,34 +1133,31 @@ GDALDataset *GSBGDataset::CreateCopy( const char *pszFilename,
 }
 
 /************************************************************************/
-/*                          GDALRegister_GSBG()                          */
+/*                          GDALRegister_GSBG()                         */
 /************************************************************************/
 
 void GDALRegister_GSBG()
 
 {
-    GDALDriver	*poDriver;
-
-    if( GDALGetDriverByName( "GSBG" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "GSBG" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Golden Software Binary Grid (.grd)" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#GSBG" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "grd" );
-	poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
-				   "Byte Int16 UInt16 Float32" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnIdentify = GSBGDataset::Identify;
-        poDriver->pfnOpen = GSBGDataset::Open;
-	poDriver->pfnCreate = GSBGDataset::Create;
-	poDriver->pfnCreateCopy = GSBGDataset::CreateCopy;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    if( GDALGetDriverByName( "GSBG" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "GSBG" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Golden Software Binary Grid (.grd)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#GSBG" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "grd" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte Int16 UInt16 Float32" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnIdentify = GSBGDataset::Identify;
+    poDriver->pfnOpen = GSBGDataset::Open;
+    poDriver->pfnCreate = GSBGDataset::Create;
+    poDriver->pfnCreateCopy = GSBGDataset::CreateCopy;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/gta/GNUmakefile b/frmts/gta/GNUmakefile
index 148615b..68c0faa 100644
--- a/frmts/gta/GNUmakefile
+++ b/frmts/gta/GNUmakefile
@@ -3,7 +3,7 @@ include ../../GDALmake.opt
 
 OBJ	=	gtadataset.o
 
-
+CPPFLAGS := $(CPPFLAGS) $(NO_NON_VIRTUAL_DTOR_FLAG)
 
 default:	$(OBJ:.o=.$(OBJ_EXT))
 
diff --git a/frmts/gta/gta_headers.h b/frmts/gta/gta_headers.h
new file mode 100644
index 0000000..6e63f92
--- /dev/null
+++ b/frmts/gta/gta_headers.h
@@ -0,0 +1,40 @@
+/******************************************************************************
+ *
+ * Project:  GDAL
+ * Purpose:  Import GTA headers
+ * Author:   Even Rouault <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+#ifndef GTA_HEADERS_H
+#define GTA_HEADERS_H
+
+#include "cpl_port.h"
+
+#ifdef HAVE_GCC_SYSTEM_HEADER
+#pragma GCC system_header
+#endif
+
+#include <gta/gta.hpp>
+
+#endif
diff --git a/frmts/gta/gtadataset.cpp b/frmts/gta/gtadataset.cpp
index f9df795..ea45dfe 100644
--- a/frmts/gta/gtadataset.cpp
+++ b/frmts/gta/gtadataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gtadataset.cpp 28785 2015-03-26 20:46:45Z goatbar $
+ * $Id: gtadataset.cpp 33005 2016-01-15 17:28:49Z rouault $
  *
  * Project:  GTA read/write Driver
  * Purpose:  GDAL bindings over GTA library.
@@ -48,7 +48,7 @@
  * - GDAL metadata is assumed to be in UTF-8 encoding, so that no conversion is
  *   necessary to store it in GTA tags. I'm not sure that this is correct, but
  *   since some metadata might not be representable in the local encoding (e.g.
- *   a chinese description in latin1), using UTF-8 seems reasonable.
+ *   a Chinese description in latin1), using UTF-8 seems reasonable.
  *
  * The following could be implemented, but currently is not:
  * - Allow metadata updates by using a special GDAL/METADATA_BUFFER tag that
@@ -88,15 +88,11 @@
 
 #include <limits.h>
 #include "cpl_port.h" // for snprintf for MSVC
-#include <gta/gta.hpp>
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
+#include "gta_headers.h"
 
-CPL_CVSID("$Id: gtadataset.cpp 28785 2015-03-26 20:46:45Z goatbar $");
-
-CPL_C_START
-void    GDALRegister_GTA(void);
-CPL_C_END
-
+CPL_CVSID("$Id: gtadataset.cpp 33005 2016-01-15 17:28:49Z rouault $");
 
 /************************************************************************/
 /* Helper functions                                                     */
@@ -144,6 +140,7 @@ class GTAIO : public gta::custom_io
         : fp( NULL )
     {
     }
+
     ~GTAIO( )
     {
         close( );
@@ -309,14 +306,14 @@ class GTARasterBand : public GDALPamRasterBand
 /*                           GTARasterBand()                            */
 /************************************************************************/
 
-GTARasterBand::GTARasterBand( GTADataset *poDS, int nBand )
+GTARasterBand::GTARasterBand( GTADataset *poDSIn, int nBandIn )
 
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
 
     // Data type
-    switch( poDS->oHeader.component_type( nBand-1 ) )
+    switch( poDSIn->oHeader.component_type( nBand-1 ) )
     {
     case gta::int8:
         eDataType = GDT_Byte;
@@ -359,24 +356,24 @@ GTARasterBand::GTARasterBand( GTADataset *poDS, int nBand )
     nBlockYSize = 1;
 
     // Component information
-    sComponentSize = poDS->oHeader.component_size( nBand-1 );
+    sComponentSize = static_cast<size_t>(poDSIn->oHeader.component_size( nBand-1 ));
     sComponentOffset = 0;
     for( int i = 0; i < nBand-1; i++ )
     {
-        sComponentOffset += poDS->oHeader.component_size( i );
+        sComponentOffset += poDSIn->oHeader.component_size( i );
     }
 
     // Metadata
     papszCategoryNames = NULL;
     papszMetaData = NULL;
-    if( poDS->oHeader.component_taglist( nBand-1 ).get( "DESCRIPTION" ) )
+    if( poDSIn->oHeader.component_taglist( nBand-1 ).get( "DESCRIPTION" ) )
     {
-        SetDescription( poDS->oHeader.component_taglist( nBand-1 ).get( "DESCRIPTION" ) );
+        SetDescription( poDSIn->oHeader.component_taglist( nBand-1 ).get( "DESCRIPTION" ) );
     }
-    for( uintmax_t i = 0; i < poDS->oHeader.component_taglist( nBand-1 ).tags(); i++)
+    for( uintmax_t i = 0; i < poDSIn->oHeader.component_taglist( nBand-1 ).tags(); i++)
     {
-        const char *pszTagName = poDS->oHeader.component_taglist( nBand-1 ).name( i );
-        if( strncmp( pszTagName, "GDAL/META/", 10 ) == 0 )
+        const char *pszTagName = poDSIn->oHeader.component_taglist( nBand-1 ).name( i );
+        if( STARTS_WITH(pszTagName, "GDAL/META/") )
         {
             const char *pDomainEnd = strchr( pszTagName + 10, '/' );
             if( pDomainEnd && pDomainEnd - (pszTagName + 10) > 0 )
@@ -393,7 +390,7 @@ GTARasterBand::GTARasterBand( GTADataset *poDS, int nBand )
                 }
                 pszDomain[j] = '\0';
                 const char *pszName = pszTagName + 10 + j + 1;
-                const char *pszValue = poDS->oHeader.component_taglist( nBand-1 ).value( i );
+                const char *pszValue = poDSIn->oHeader.component_taglist( nBand-1 ).value( i );
                 SetMetadataItem( pszName, pszValue,
                         strcmp( pszDomain, "DEFAULT" ) == 0 ? NULL : pszDomain );
                 VSIFree( pszDomain );
@@ -746,7 +743,7 @@ CPLErr GTARasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
         memcpy( (void *) pDst, (void *) pSrc, sComponentSize );
     }
 
-    // Write the block that conatins all bands at once
+    // Write the block that contains all bands at once
     if( poGDS->WriteBlock( ) != CE_None )
     {
         return CE_Failure;
@@ -777,6 +774,7 @@ GTADataset::GTADataset()
     nLastBlockXOff = -1;
     nLastBlockYOff = -1;
     pBlock = NULL;
+    DataOffset = 0;
 }
 
 /************************************************************************/
@@ -812,7 +810,7 @@ CPLErr GTADataset::ReadBlock( int nBlockXOff, int nBlockYOff )
         if( pBlock == NULL )
         {
             if( oHeader.data_size() > (size_t)(-1)
-                    || ( pBlock = VSIMalloc( oHeader.data_size() ) ) == NULL )
+                    || ( pBlock = VSI_MALLOC_VERBOSE( static_cast<size_t>(oHeader.data_size()) ) ) == NULL )
             {
                 CPLError( CE_Failure, CPLE_OutOfMemory,
                         "Cannot allocate buffer for the complete data set.\n"
@@ -843,11 +841,9 @@ CPLErr GTADataset::ReadBlock( int nBlockXOff, int nBlockYOff )
 
         if( pBlock == NULL )
         {
-            pBlock = VSIMalloc2( oHeader.element_size(), nBlockXSize );
+            pBlock = VSI_MALLOC2_VERBOSE( static_cast<size_t>(oHeader.element_size()), nBlockXSize );
             if( pBlock == NULL )
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory,
-                        "Cannot allocate scanline buffer" );
                 return CE_Failure;
             }
         }
@@ -1002,7 +998,7 @@ GDALDataset *GTADataset::Open( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->nHeaderBytes < 5 )
         return NULL;
 
-    if( !EQUALN((char *)poOpenInfo->pabyHeader,"GTA",3) )
+    if( !STARTS_WITH_CI((char *)poOpenInfo->pabyHeader, "GTA") )
         return NULL;
 
 /* -------------------------------------------------------------------- */
@@ -1067,8 +1063,8 @@ GDALDataset *GTADataset::Open( GDALOpenInfo * poOpenInfo )
         delete poDS;
         return NULL;
     }
-    poDS->nRasterXSize = poDS->oHeader.dimension_size(0);
-    poDS->nRasterYSize = poDS->oHeader.dimension_size(1);
+    poDS->nRasterXSize = static_cast<int>(poDS->oHeader.dimension_size(0));
+    poDS->nRasterYSize = static_cast<int>(poDS->oHeader.dimension_size(1));
 
     // Check the number of bands (called components in GTA)
     if( poDS->oHeader.components() > INT_MAX-1
@@ -1080,7 +1076,7 @@ GDALDataset *GTADataset::Open( GDALOpenInfo * poOpenInfo )
         delete poDS;
         return NULL;
     }
-    poDS->nBands = poDS->oHeader.components();
+    poDS->nBands = static_cast<int>(poDS->oHeader.components());
 
     // Check the data types (called component types in GTA)
     for( int iBand = 0; iBand < poDS->nBands; iBand++ )
@@ -1132,10 +1128,9 @@ GDALDataset *GTADataset::Open( GDALOpenInfo * poOpenInfo )
         }
         else
         {
-            poDS->pasGCPs = (GDAL_GCP *)VSIMalloc2( poDS->nGCPs, sizeof(GDAL_GCP) );
+            poDS->pasGCPs = (GDAL_GCP *)VSI_MALLOC2_VERBOSE( poDS->nGCPs, sizeof(GDAL_GCP) );
             if( poDS->pasGCPs == NULL )
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory, "Cannot allocate GCP list" );
                 delete poDS;
                 return NULL;
             }
@@ -1150,8 +1145,8 @@ GDALDataset *GTADataset::Open( GDALOpenInfo * poOpenInfo )
                 poDS->pasGCPs[i].pszId = VSIStrdup( CPLSPrintf( "%d", i ) );
                 char pszGCPTagName[64];
                 char pszGCPInfoTagName[64];
-                strcpy( pszGCPTagName, CPLSPrintf( "GDAL/GCP%d", i ) );
-                strcpy( pszGCPInfoTagName, CPLSPrintf( "GDAL/GCP%d_INFO", i ) );
+                snprintf( pszGCPTagName, sizeof(pszGCPTagName), "GDAL/GCP%d", i );
+                snprintf( pszGCPInfoTagName, sizeof(pszGCPTagName), "GDAL/GCP%d_INFO", i );
                 if( poDS->oHeader.global_taglist().get(pszGCPInfoTagName) )
                 {
                     poDS->pasGCPs[i].pszInfo = VSIStrdup( poDS->oHeader.global_taglist().get(pszGCPInfoTagName) );
@@ -1181,15 +1176,14 @@ GDALDataset *GTADataset::Open( GDALOpenInfo * poOpenInfo )
     for( uintmax_t i = 0; i < poDS->oHeader.global_taglist().tags(); i++)
     {
         const char *pszTagName = poDS->oHeader.global_taglist().name( i );
-        if( strncmp( pszTagName, "GDAL/META/", 10 ) == 0 )
+        if( STARTS_WITH(pszTagName, "GDAL/META/") )
         {
             const char *pDomainEnd = strchr( pszTagName + 10, '/' );
             if( pDomainEnd && pDomainEnd - (pszTagName + 10) > 0 )
             {
-                char *pszDomain = (char *)VSIMalloc( pDomainEnd - (pszTagName + 10) + 1 );
+                char *pszDomain = (char *)VSI_MALLOC_VERBOSE( pDomainEnd - (pszTagName + 10) + 1 );
                 if( !pszDomain )
                 {
-                    CPLError( CE_Failure, CPLE_OutOfMemory, "Cannot allocate metadata buffer" );
                     delete poDS;
                     return NULL;
                 }
@@ -1313,10 +1307,9 @@ GTACreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                       pszCompressionValue );
     }
 
-    gta::type *peGTATypes = (gta::type *)VSIMalloc2( poSrcDS->GetRasterCount(), sizeof(gta::type) );
+    gta::type *peGTATypes = (gta::type *)VSI_MALLOC2_VERBOSE( poSrcDS->GetRasterCount(), sizeof(gta::type) );
     if( peGTATypes == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory, "Cannot allocate GTA type list" );
         return NULL;
     }
     for( int i = 0; i < poSrcDS->GetRasterCount(); i++ )
@@ -1457,8 +1450,8 @@ GTACreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             {
                 char pszGCPTagName[64];
                 char pszGCPInfoTagName[64];
-                strcpy( pszGCPTagName, CPLSPrintf( "GDAL/GCP%d", i ) );
-                strcpy( pszGCPInfoTagName, CPLSPrintf( "GDAL/GCP%d_INFO", i ) );
+                snprintf( pszGCPTagName, sizeof(pszGCPTagName), "GDAL/GCP%d", i );
+                snprintf( pszGCPInfoTagName, sizeof(pszGCPInfoTagName), "GDAL/GCP%d_INFO", i );
                 if( pasGCPs[i].pszInfo && pasGCPs[i].pszInfo[0] != '\0' )
                 {
                     oHeader.global_taglist().set( pszGCPInfoTagName, pasGCPs[i].pszInfo );
@@ -1608,10 +1601,9 @@ GTACreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         return NULL;
     }
 
-    void *pLine = VSIMalloc2( oHeader.element_size(), oHeader.dimension_size(0) );
+    void *pLine = VSI_MALLOC2_VERBOSE( static_cast<size_t>(oHeader.element_size()), static_cast<size_t>(oHeader.dimension_size(0)) );
     if( pLine == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory, "Cannot allocate scanline buffer.\n" );
         VSIFree( pLine );
         return NULL;
     }
@@ -1690,46 +1682,44 @@ GTACreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 void GDALRegister_GTA()
 
 {
-    GDALDriver  *poDriver;
-
-    if( GDALGetDriverByName( "GTA" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-
-        poDriver->SetDescription( "GTA" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                "Generic Tagged Arrays (.gta)" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                "frmt_gta.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gta" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
-                "Byte UInt16 Int16 UInt32 Int32 Float32 Float64 "
-                "CInt16 CInt32 CFloat32 CFloat64" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
-                "<CreationOptionList>"
-                "  <Option name='COMPRESS' type='string-select'>"
-                "    <Value>NONE</Value>"
-                "    <Value>BZIP2</Value>"
-                "    <Value>XZ</Value>"
-                "    <Value>ZLIB</Value>"
-                "    <Value>ZLIB1</Value>"
-                "    <Value>ZLIB2</Value>"
-                "    <Value>ZLIB3</Value>"
-                "    <Value>ZLIB4</Value>"
-                "    <Value>ZLIB5</Value>"
-                "    <Value>ZLIB6</Value>"
-                "    <Value>ZLIB7</Value>"
-                "    <Value>ZLIB8</Value>"
-                "    <Value>ZLIB9</Value>"
-                "  </Option>"
-                "</CreationOptionList>" );
-
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = GTADataset::Open;
-        poDriver->pfnCreateCopy = GTACreateCopy;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    if( GDALGetDriverByName( "GTA" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "GTA" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Generic Tagged Arrays (.gta)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_gta.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gta" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte UInt16 Int16 UInt32 Int32 Float32 Float64 "
+                               "CInt16 CInt32 CFloat32 CFloat64" );
+    poDriver->SetMetadataItem(
+        GDAL_DMD_CREATIONOPTIONLIST,
+        "<CreationOptionList>"
+        "  <Option name='COMPRESS' type='string-select'>"
+        "    <Value>NONE</Value>"
+        "    <Value>BZIP2</Value>"
+        "    <Value>XZ</Value>"
+        "    <Value>ZLIB</Value>"
+        "    <Value>ZLIB1</Value>"
+        "    <Value>ZLIB2</Value>"
+        "    <Value>ZLIB3</Value>"
+        "    <Value>ZLIB4</Value>"
+        "    <Value>ZLIB5</Value>"
+        "    <Value>ZLIB6</Value>"
+        "    <Value>ZLIB7</Value>"
+        "    <Value>ZLIB8</Value>"
+        "    <Value>ZLIB9</Value>"
+        "  </Option>"
+        "</CreationOptionList>" );
+
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = GTADataset::Open;
+    poDriver->pfnCreateCopy = GTACreateCopy;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/gtiff/frmt_gtiff.html b/frmts/gtiff/frmt_gtiff.html
index 16eb6b5..29224a5 100644
--- a/frmts/gtiff/frmt_gtiff.html
+++ b/frmts/gtiff/frmt_gtiff.html
@@ -16,9 +16,9 @@ somewhat less varieties can be written.</p>
 reading and writing BigTIFF files (evolution of the TIFF format to support files
 larger than 4 GB).</p>
 
-<p>Currently band types of Byte, UInt16, Int16, UInt32, Int32, Float32, Float64, 
+<p>Currently band types of Byte, UInt16, Int16, UInt32, Int32, Float32, Float64,
 CInt16, CInt32, CFloat32 and CFloat64 are supported for
-reading and writing.  
+reading and writing.
 Paletted images will return palette information associated with
 the band.  The compression formats listed below should be supported for
 reading as well. </p>
@@ -30,7 +30,7 @@ such as YCbCr color model files, are automatically translated into RGBA
 <h2>Georeferencing</h2>
 
 <p>Most GeoTIFF projections should be supported, with the caveat that in order
-to translate uncommon Projected, and Geographic coordinate systems into 
+to translate uncommon Projected, and Geographic coordinate systems into
 OGC WKT it is necessary to have the EPSG .csv files available.  They must
 be found at the location pointed to by the GEOTIFF_CSV environment variable.
 </p>
@@ -149,7 +149,7 @@ stored the EXIF metadata domain.</p>
 
 <p>Note that these metadata properties can only be used on the original raw pixel data. If automatic conversion to RGB has been done, the color profile information cannot be used.</p>
 
-<p>All these metadata tags can be overriden and/or used as creation options.</p>
+<p>All these metadata tags can be overridden and/or used as creation options.</p>
 
 <h2>Nodata value</h2>
 
@@ -157,15 +157,26 @@ stored the EXIF metadata domain.</p>
 files created with the default profile GDALGeoTIFF. Note that all bands must use the same nodata value.
 When BASELINE or GeoTIFF profile are used, the nodata value is stored into a PAM .aux.xml file.</p>
 
+<h2>Open options</h2>
+
+<ul>
+
+<li><p><b>NUM_THREADS=number_of_threads/ALL_CPUS</b>: (From GDAL 2.1)
+Enable multi-threaded compression by specifying the number of worker threads.
+Worth it for slow compression algorithms such as DEFLATE or LZMA. Will be
+ignored for JPEG.  Default is compression in the main thread.</p></li>
+
+</ul>
+
 <h2>Creation Issues</h2>
 
 <p>GeoTIFF files can be created with any GDAL defined band type, including
-the complex types.  Created files may have any number of bands.  Files 
+the complex types.  Created files may have any number of bands.  Files
 with exactly 3 bands will be
 given a photometric interpretation of RGB, files with exactly four bands
-will have a photometric interpretation of RGBA, while all other combinations 
+will have a photometric interpretation of RGBA, while all other combinations
 will have a photometric interpretation of MIN_IS_WHITE.  Files with
-pseudo-color tables, or GCPs can currently only be created when creating from 
+pseudo-color tables, or GCPs can currently only be created when creating from
 an existing GDAL dataset with those objects (GDALDriver::CreateCopy()).</p>
 
 <p>Note that the GeoTIFF format does not support parametric description of datums,
@@ -190,7 +201,7 @@ if RPC information is available.</p></li>
 
 <li><p><b>INTERLEAVE=[BAND,PIXEL]</b>: By default TIFF files with pixel
 interleaving (PLANARCONFIG_CONTIG in TIFF terminology) are created.  These
-are slightly less efficient than BAND interleaving for some purposes, but 
+are slightly less efficient than BAND interleaving for some purposes, but
 some applications only support pixel interleaved TIFF files.</p></li>
 
 <li><p><b>TILED=YES</b>: By default stripped TIFF files are created.  This
@@ -203,7 +214,7 @@ option can be used to force creation of tiled TIFF files.</p></li>
 
 <li><p><b>NBITS=n</b>: Create a file with less than 8 bits per sample by passing a value from 1 to 7.  The apparent pixel type should be Byte. From GDAL 1.6.0, values of n=9...15 (UInt16 type) and n=17...31 (UInt32 type) are also accepted. </p></li>
 
-<li><p><b>COMPRESS=[JPEG/LZW/PACKBITS/DEFLATE/CCITTRLE/CCITTFAX3/CCITTFAX4/NONE]</b>: 
+<li><p><b>COMPRESS=[JPEG/LZW/PACKBITS/DEFLATE/CCITTRLE/CCITTFAX3/CCITTFAX4/LZMA/NONE]</b>:
 Set the compression to use.  JPEG should generally only be used with Byte data (8 bit per channel).
 But starting with GDAL 1.7.0 and provided that GDAL is built with internal libtiff and libjpeg,
 it is possible to read and write TIFF files with 12bit JPEG compressed TIFF files (seen as UInt16 bands with NBITS=12).
@@ -212,6 +223,11 @@ The CCITT compression should only be used with 1bit (NBITS=1) data.
 LZW and DEFLATE compressions can be used with the PREDICTOR creation option.
 None is the default.</p></li>
 
+<li><p><b>NUM_THREADS=number_of_threads/ALL_CPUS</b>: (From GDAL 2.1)
+Enable multi-threaded compression by specifying the number of worker threads.
+Worth for slow compressions such as DEFLATE or LZMA. Will be ignored for JPEG.
+Default is compression in the main thread.</p></li>
+
 <li><p><b>PREDICTOR=[1/2/3]</b>: Set the predictor for LZW or DEFLATE compression. The default is 1 (no predictor), 2 is horizontal differencing and 3 is floating point prediction.</p></li>
 
 <li><p><b>DISCARD_LSB=nbits or nbits_band1,nbits_band2,...nbits_bandN</b>: (GDAL >= 2.0)
@@ -236,7 +252,7 @@ This is generally the optimal choice for smallest file size, and consequently is
 
 <li><p><b>ZLEVEL=[1-9]</b>:  Set the level of compression when using DEFLATE compression. A value of 9 is best, and 1 is least compression. The default is 6.</p></li>
 
-<li><p><b>PHOTOMETRIC=[MINISBLACK/MINISWHITE/RGB/CMYK/YCBCR/CIELAB/ICCLAB/ITULAB]</b>: 
+<li><p><b>PHOTOMETRIC=[MINISBLACK/MINISWHITE/RGB/CMYK/YCBCR/CIELAB/ICCLAB/ITULAB]</b>:
 Set the photometric interpretation tag. Default is MINISBLACK, but if the
 input image has 3 or 4 bands of Byte type, then RGB will be selected. You can
 override default photometric using this option.</p></li>
@@ -255,7 +271,7 @@ tags are emitted by GDAL.</p>
 <li>With <tt>GDALGeoTIFF</tt> (the default) various GDAL custom tags may be written.</li>
 <li>With <tt>GeoTIFF</tt> only GeoTIFF tags will be added to the baseline.</li>
 <li>With <tt>BASELINE</tt> no GDAL or GeoTIFF tags will be written.  BASELINE is occasionally useful when writing files to
-be read by applications intolerant of unrecognised tags.</li>
+be read by applications intolerant of unrecognized tags.</li>
 </ul>
 </li>
 
@@ -263,8 +279,8 @@ be read by applications intolerant of unrecognised tags.</li>
 <ul>
 <li>YES forces BigTIFF.</li>
 <li>NO forces classic TIFF.</li>
-<li>IF_NEEDED will only create a BigTIFF if it is clearly needed (uncompressed, and image larger than 4GB).</li>
-<li>IF_SAFER will create BigTIFF if the resulting file *might* exceed 4GB.</li>
+<li>IF_NEEDED will only create a BigTIFF if it is clearly needed (in the uncompressed case, and image larger than 4GB. So no effect when using a compression).</li>
+<li>IF_SAFER will create BigTIFF if the resulting file *might* exceed 4GB. Note: this is only a heuristics that might not always work depending on compression ratios.</li>
 </ul>
 <p>BigTIFF is a TIFF variant which can contain more than 4GiB of data (size of classic TIFF is limited by that value). This option is available if GDAL is built with libtiff library version 4.0 or higher (which is the case of the internal libtiff version from GDAL >= 1.5.0).  The default is IF_NEEDED. (IF_NEEDED and IF_SAFER are available from GDAL 1.6.0).</p>
 <p>When creating a new GeoTIFF with no compression, GDAL computes in advance the
@@ -276,7 +292,7 @@ if the final file is anticipated to be too big for classical TIFF format.
 If BigTIFF creation is not explicitly asked or guessed and the resulting file is too big for classical TIFF,
 libtiff will fail with an error message like "TIFFAppendToStrip:Maximum TIFF file size exceeded".</p></li>
 
-<li><p><b>PIXELTYPE=[DEFAULT/SIGNEDBYTE]</b>: By setting this to SIGNEDBYTE, a 
+<li><p><b>PIXELTYPE=[DEFAULT/SIGNEDBYTE]</b>: By setting this to SIGNEDBYTE, a
 new Byte file can be forced to be written as signed byte.</p></li>
 
 <!-- Commented for the moment. Not sure we want to advertize that
@@ -291,6 +307,15 @@ also exist, provided that the GDAL_TIFF_INTERNAL_MASK configuration option is se
 Note that this creation option will have <a href="http://trac.osgeo.org/gdal/ticket/3917">no effect</a> if general options
 (i.e. options which are not creation options) of gdal_translate are used.</p></li>
 
+<li><p><b>GEOTIFF_KEYS_FLAVOR=[STANDARD/ESRI_PE]</b>: (GDAL >= 2.1.0) Determine
+which "flavor" of GeoTIFF keys must be used to write the SRS information. The STANDARD
+way (default choice) will use the general accepted formulations of GeoTIFF keys, including
+extensions of the values accepted for ProjectedCSTypeGeoKey to new EPSG codes.
+The ESRI_PE flavor will write formulations that are (more) compatible of ArcGIS. At the time
+of writing, the ESRI_PE choice has mostly an effect when writing the EPSG:3857 (Web Mercator)
+SRS. For other SRS, the standard way will be used, with the addition of a ESRI_PE WKT
+string as the value of PCSCitationGeoKey.</p></li>
+
 </ul>
 
 <h3>About JPEG compression of RGB images </h3>
@@ -338,7 +363,7 @@ will generate a file with the above defined constraints (related to position of
 block order), and this
 is only supported for a uncompressed file. The Create() method also supports creating streamable
 compatible files, but the writer must be careful to set the projection, geotransform
-or metadata before writting image blocks (so that the IFD is written at the beginning
+or metadata before writing image blocks (so that the IFD is written at the beginning
 of the file). And when writing image blocks, the order
 of blocks must be the one of the above paragraph, otherwise errors will be reported.
 
@@ -357,7 +382,7 @@ gdal_translate my_fifo out.png -of PNG
 <p>
 Note: not all utilities are compatible with such input or output streaming operations,
 and even those which may deal with such files may not manage to deal with them in
-all circumstances, for example if the reading driver drived by the output file is
+all circumstances, for example if the reading driver driven by the output file is
 not compatible with the block order of the streamed input.
 
 <h3>Configuration options</h3>
@@ -377,7 +402,7 @@ Can help reading partially corrupted TIFF files</li>
 <li>USE_RRD: Can be set to TRUE to force external overviews in the RRD format. Default value : FALSE</li>
 <li>TIFF_USE_OVR: Can be set to TRUE to force external overviews in the GeoTIFF (.ovr) format. Default value : FALSE</li>
 <li>GTIFF_POINT_GEO_IGNORE: Can be set to TRUE to revert back to the behaviour of GDAL < 1.8.0
-regarding how PixelIsPoint is interprated w.r.t geotransform. See <a href="http://trac.osgeo.org/gdal/wiki/rfc33_gtiff_pixelispoint">
+regarding how PixelIsPoint is interpreted w.r.t geotransform. See <a href="http://trac.osgeo.org/gdal/wiki/rfc33_gtiff_pixelispoint">
 RFC 33: GTiff - Fixing PixelIsPoint Interpretation</a> for more details. Default value : FALSE</li>
 <li>GTIFF_REPORT_COMPD_CS: (GDAL >= 1.9.0). Can be set to TRUE to avoid stripping the vertical CS of compound CS. Default value : FALSE</li>
 <li>GDAL_ENABLE_TIFF_SPLIT : Can be set to FALSE to avoid all-in-one-strip files being presented as having. Default value : TRUE</li>
@@ -385,19 +410,21 @@ RFC 33: GTiff - Fixing PixelIsPoint Interpretation</a> for more details. Default
 <!-- not sure it is wise to advertize this one. I doubt it works correctly if set to NO. CONVERT_YCBCR_TO_RGB -->
 <!-- debug/autotest option : GTIFF_DELETE_ON_ERROR -->
 <li>GDAL_TIFF_OVR_BLOCKSIZE : See <a href="#overviews"><i>Overviews</i> section</a>.
-<li>GTIFF_LINEAR_UNITS: Can be set to BROKEN to read GeoTIFF files that 
+<li>GTIFF_LINEAR_UNITS: Can be set to BROKEN to read GeoTIFF files that
 have false easting/northing improperly set in meters when it ought to be in
-coordinate system linear units.  (<a href="http://trac.osgeo.org/gdal/ticket/3901">Ticket #3901</a>). 
+coordinate system linear units.  (<a href="http://trac.osgeo.org/gdal/ticket/3901">Ticket #3901</a>).
 <li>TAB_APPROX_GEOTRANSFORM=YES/NO: (GDAL >= 2.0) To decide if an approximate geotransform is acceptable when reading a .tab file. Default value: NO
 <li>GTIFF_DIRECT_IO=YES/NO: (GDAL >= 2.0) Can be set to YES to use specialized
-RasterIO() implementations when reading un-tiled un-compressed TIFF files to
+RasterIO() implementations when reading un-compressed TIFF files (un-tiled only
+in GDAL 2.0, both un-tiled and tiled in GDAL 2.1) to
 avoid using the block cache. Setting it to YES even when the optimized cases do
 not apply should be safe (generic implementation will be used). Default value:NO
 <li>GTIFF_VIRTUAL_MEM_IO=YES/NO/IF_ENOUGH_RAM: (GDAL >= 2.0) Can be set to YES
 to use specialized RasterIO() implementations when reading un-compressed TIFF
 files to avoid using the block cache.
 This implementation relies on memory-mapped file I/O,
-and is currently only supported on Linux (64-bit build strongly recommended).
+and is currently only supported on Linux (64-bit build strongly recommended) or,
+starting with GDAL 2.1, on other POSIX-like systems.
 Setting it to YES even when the optimized cases do not apply should be safe
 (generic implementation will be used), but if the file exceeds RAM, disk swapping
 might occur if the whole file is read. Setting it to IF_ENOUGH_RAM will first
@@ -415,7 +442,7 @@ in priority, and if not possible, the later is tried.
 <li> <a href="http://www.remotesensing.org/geotiff/geotiff.html">GeoTIFF Information Page</a></li>
 <li> <a href="http://www.remotesensing.org/libtiff/">libtiff Page</a></li>
 <li> <a href="http://www.awaresystems.be/imaging/tiff/bigtiff.html">
-	Details on BigTIFF file format</a></li>
+        Details on BigTIFF file format</a></li>
 
 </ul>
 
diff --git a/frmts/gtiff/geotiff.cpp b/frmts/gtiff/geotiff.cpp
index 39b54f5..92508f9 100644
--- a/frmts/gtiff/geotiff.cpp
+++ b/frmts/gtiff/geotiff.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: geotiff.cpp 33053 2016-01-20 10:53:18Z rouault $
+ * $Id: geotiff.cpp 33843 2016-04-01 08:37:57Z rouault $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  GDAL GeoTIFF support.
@@ -36,38 +36,41 @@
 #define _GNU_SOURCE
 #endif
 
-#include "gdal_pam.h"
-#define CPL_SERV_H_INCLUDED
+#include "cpl_port.h"  // Must be first.
+
+#include <set>
 
-#include "xtiffio.h"
-#include "geovalues.h"
-#include "cpl_string.h"
 #include "cpl_csv.h"
+#include "cplkeywordparser.h"
 #include "cpl_minixml.h"
-#include "gt_overview.h"
-#include "ogr_spatialref.h"
-#include "tif_float.h"
-#include "gtiff.h"
-#include "gdal_csv.h"
-#include "gt_wkt_srs.h"
-#include "gt_wkt_srs_priv.h"
-#include "tifvsi.h"
 #include "cpl_multiproc.h"
-#include "cplkeywordparser.h"
-#include "gt_jpeg_copy.h"
+#include "cpl_string.h"
 #include "cpl_vsi_virtual.h"
-#include <set>
+#include "cpl_worker_thread_pool.h"
+#include "gdal_csv.h"
+#include "gdal_frmts.h"
 #include "gdal_mdreader.h"
-
+#include "gdal_pam.h"
+#include "geovalues.h"
+#include "gt_jpeg_copy.h"
+#include "gt_overview.h"
+#include "gt_wkt_srs.h"
+#include "gt_wkt_srs_priv.h"
+#include "gtiff.h"
+#include "ogr_spatialref.h"
+#include "tif_float.h"
 #ifdef INTERNAL_LIBTIFF
-#include "tiffiop.h"
+#  include "tiffiop.h"
 #endif
+#include "tifvsi.h"
+#include "xtiffio.h"
 
-CPL_CVSID("$Id: geotiff.cpp 33053 2016-01-20 10:53:18Z rouault $");
+CPL_CVSID("$Id: geotiff.cpp 33843 2016-04-01 08:37:57Z rouault $");
 
 #if SIZEOF_VOIDP == 4
 static int bGlobalStripIntegerOverflow = FALSE;
 #endif
+static bool bGlobalInExternalOvr = false;
 
 typedef enum
 {
@@ -103,7 +106,7 @@ static const GTIFFTags asTIFFTags[] =
 /*                            IsPowerOfTwo()                            */
 /************************************************************************/
 
-static int IsPowerOfTwo(unsigned int i)
+static bool IsPowerOfTwo(unsigned int i)
 {
     int nBitSet = 0;
     while(i != 0)
@@ -116,12 +119,21 @@ static int IsPowerOfTwo(unsigned int i)
 }
 
 /************************************************************************/
+/*                          GTIFFSetInExternalOvr()                     */
+/************************************************************************/
+
+void GTIFFSetInExternalOvr(bool b)
+{
+    bGlobalInExternalOvr = b;
+}
+
+/************************************************************************/
 /*                     GTIFFGetOverviewBlockSize()                      */
 /************************************************************************/
 
 void GTIFFGetOverviewBlockSize(int* pnBlockXSize, int* pnBlockYSize)
 {
-    static int bHasWarned = FALSE;
+    static bool bHasWarned = false;
     const char* pszVal = CPLGetConfigOption("GDAL_TIFF_OVR_BLOCKSIZE", "128");
     int nOvrBlockSize = atoi(pszVal);
     if (nOvrBlockSize < 64 || nOvrBlockSize > 4096 ||
@@ -133,7 +145,7 @@ void GTIFFGetOverviewBlockSize(int* pnBlockXSize, int* pnBlockYSize)
                     "Wrong value for GDAL_TIFF_OVR_BLOCKSIZE : %s. "
                     "Should be a power of 2 between 64 and 4096. Defaulting to 128",
                     pszVal);
-            bHasWarned = TRUE;
+            bHasWarned = true;
         }
         nOvrBlockSize = 128;
     }
@@ -151,7 +163,7 @@ enum
 
 /************************************************************************/
 /* ==================================================================== */
-/*				GTiffDataset				*/
+/*                          GTiffDataset                                */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -168,7 +180,24 @@ typedef enum
     VIRTUAL_MEM_IO_IF_ENOUGH_RAM
 } VirtualMemIOEnum;
 
-class GTiffDataset : public GDALPamDataset
+class GTiffDataset;
+typedef struct
+{
+    GTiffDataset *poDS;
+    int           bTIFFIsBigEndian;
+    char         *pszTmpFilename;
+    int           nHeight;
+    uint16        nPredictor;
+    GByte        *pabyBuffer;
+    int           nBufferSize;
+    int           nStripOrTile;
+
+    GByte        *pabyCompressedBuffer; /* owned by pszTmpFilename */
+    int           nCompressedBufferSize;
+    int           bReady;
+} GTiffCompressionJob;
+
+class GTiffDataset CPL_FINAL : public GDALPamDataset
 {
     friend class GTiffRasterBand;
     friend class GTiffSplitBand;
@@ -180,9 +209,9 @@ class GTiffDataset : public GDALPamDataset
     friend class GTiffJPEGOverviewBand;
 
     friend void    GTIFFSetJpegQuality(GDALDatasetH hGTIFFDS, int nJpegQuality);
-    
-    TIFF	*hTIFF;
-    VSILFILE *fpL;
+
+    TIFF       *hTIFF;
+    VSILFILE   *fpL;
     int         bStreamingIn;
 
     int         bStreamingOut;
@@ -197,31 +226,31 @@ class GTiffDataset : public GDALPamDataset
     void        ScanDirectories();
 
     toff_t      nDirOffset;
-    int		bBase;
+    int         bBase;
     int         bCloseTIFFHandle; /* useful for closing TIFF handle opened by GTIFF_DIR: */
 
-    uint16	nPlanarConfig;
-    uint16	nSamplesPerPixel;
-    uint16	nBitsPerSample;
-    uint32	nRowsPerStrip;
-    uint16	nPhotometric;
+    uint16      nPlanarConfig;
+    uint16      nSamplesPerPixel;
+    uint16      nBitsPerSample;
+    uint32      nRowsPerStrip;
+    uint16      nPhotometric;
     uint16      nSampleFormat;
     uint16      nCompression;
-    
-    int		nBlocksPerBand;
+
+    int         nBlocksPerBand;
 
     uint32      nBlockXSize;
-    uint32	nBlockYSize;
+    uint32      nBlockYSize;
 
-    int		nLoadedBlock;		/* or tile */
-    int         bLoadedBlockDirty;  
-    GByte	*pabyBlockBuf;
+    int         nLoadedBlock;  /* or tile */
+    int         bLoadedBlockDirty;
+    GByte       *pabyBlockBuf;
 
     CPLErr      LoadBlockBuf( int nBlockId, int bReadFromDisk = TRUE );
     CPLErr      FlushBlockBuf();
     int         bWriteErrorInFlushBlockBuf;
 
-    char	*pszProjection;
+    char        *pszProjection;
     int         bLookedForProjection;
     int         bLookedForMDAreaOrPoint;
 
@@ -231,20 +260,21 @@ class GTiffDataset : public GDALPamDataset
     void        AdjustLinearUnit( short UOMLength );
 #endif
 
-    double	adfGeoTransform[6];
-    int		bGeoTransformValid;
+    double      adfGeoTransform[6];
+    int         bGeoTransformValid;
 
     int         bTreatAsRGBA;
     int         bCrystalized;
+    bool        bCheckIfColorInterpMustGoToPamAtCrystalization;
 
-    void	Crystalize();
+    void        Crystalize();  // TODO: Spelling.
 
     GDALColorTable *poColorTable;
 
-    void	WriteGeoTIFFInfo();
-    int		SetDirectory( toff_t nDirOffset = 0 );
+    void        WriteGeoTIFFInfo();
+    int         SetDirectory( toff_t nDirOffset = 0 );
 
-    int		nOverviewCount;
+    int         nOverviewCount;
     GTiffDataset **papoOverviewDS;
 
     int         nJPEGOverviewVisibilityFlag; /* if > 0, the implicit JPEG overviews are visible through GetOverviewCount() */
@@ -253,8 +283,8 @@ class GTiffDataset : public GDALPamDataset
     GTiffJPEGOverviewDS **papoJPEGOverviewDS;
     int         GetJPEGOverviewCount();
 
-    int		nGCPCount;
-    GDAL_GCP	*pasGCPList;
+    int         nGCPCount;
+    GDAL_GCP    *pasGCPList;
 
     int         IsBlockAvailable( int nBlockId );
 
@@ -266,7 +296,7 @@ class GTiffDataset : public GDALPamDataset
     int         bNoDataSet;
     double      dfNoDataValue;
 
-    int	        bMetadataChanged;
+    int         bMetadataChanged;
     int         bColorProfileMetadataChanged;
 
     int         bNeedsRewrite;
@@ -283,8 +313,8 @@ class GTiffDataset : public GDALPamDataset
 
     void*        pabyTempWriteBuffer;
     int          nTempWriteBufferSize;
-    int          WriteEncodedTile(uint32 tile, GByte* pabyData, int bPreserveDataBuffer);
-    int          WriteEncodedStrip(uint32 strip, GByte* pabyData, int bPreserveDataBuffer);
+    bool         WriteEncodedTile(uint32 tile, GByte* pabyData, int bPreserveDataBuffer);
+    bool         WriteEncodedStrip(uint32 strip, GByte* pabyData, int bPreserveDataBuffer);
 
     GTiffDataset* poMaskDS;
     GTiffDataset* poBaseDS;
@@ -323,7 +353,7 @@ class GTiffDataset : public GDALPamDataset
     int           nLZMAPreset;
     int           nJpegQuality;
     int           nJpegTablesMode;
-    
+
     int           bPromoteTo8Bits;
 
     int           bDebugDontWriteBlocks;
@@ -345,23 +375,36 @@ class GTiffDataset : public GDALPamDataset
     VirtualMemIOEnum eVirtualMemIOUsage;
     CPLVirtualMem* psVirtualMemIOMapping;
 
-    int           nSetPhotometricFromBandColorInterp;
+    GTIFFKeysFlavorEnum eGeoTIFFKeysFlavor;
 
     CPLVirtualMem *pBaseMapping;
     int            nRefBaseMapping;
-    
+
     int            bHasDiscardedLsb;
     std::vector<int> anMaskLsb, anOffsetLsb;
     void           DiscardLsb(GByte* pabyBuffer, int nBytes, int iBand);
     void           GetDiscardLsbOption(char** papszOptions);
 
+    CPLWorkerThreadPool *poCompressThreadPool;
+    std::vector<GTiffCompressionJob> asCompressionJobs;
+    CPLMutex      *hCompressThreadPoolMutex;
+    void           InitCompressionThreads(char** papszOptions);
+    void           InitCreationOrOpenOptions(char** papszOptions);
+    static void    ThreadCompressionFunc(void* pData);
+    void           WaitCompletionForBlock(int nBlockId);
+    void           WriteRawStripOrTile(int nStripOrTile,
+                                 GByte* pabyCompressedBuffer,
+                                 int nCompressedBufferSize);
+    int            SubmitCompressionJob(int nStripOrTile, GByte* pabyData,
+                                        int cc, int nHeight);
+
     int            GuessJPEGQuality(int& bOutHasQuantizationTable,
                                     int& bOutHasHuffmanTable);
 
-    CPLErr         DirectIO( GDALRWFlag eRWFlag,
+    int            DirectIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
                                void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType, 
+                               GDALDataType eBufType,
                                int nBandCount, int *panBandMap,
                                GSpacing nPixelSpace, GSpacing nLineSpace,
                                GSpacing nBandSpace,
@@ -370,11 +413,30 @@ class GTiffDataset : public GDALPamDataset
     int            VirtualMemIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
                                void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType, 
+                               GDALDataType eBufType,
                                int nBandCount, int *panBandMap,
                                GSpacing nPixelSpace, GSpacing nLineSpace,
                                GSpacing nBandSpace,
                                GDALRasterIOExtraArg* psExtraArg );
+
+    GByte          *m_pTempBufferForCommonDirectIO;
+    size_t          m_nTempBufferForCommonDirectIOSize;
+    template<class FetchBuffer> CPLErr CommonDirectIO(
+                               FetchBuffer& oFetcher,
+                               int nXOff, int nYOff, int nXSize, int nYSize,
+                               void * pData, int nBufXSize, int nBufYSize,
+                               GDALDataType eBufType,
+                               int nBandCount, int *panBandMap,
+                               GSpacing nPixelSpace, GSpacing nLineSpace,
+                               GSpacing nBandSpace );
+
+    bool        m_bReadGeoTransform;
+    bool        m_bLoadPam;
+    void        LoadGeoreferencingAndPamIfNeeded();
+
+    bool        m_bHasGotSiblingFiles;
+    char      **GetSiblingFiles();
+
   protected:
     virtual int         CloseDependentDatasets();
 
@@ -395,20 +457,19 @@ class GTiffDataset : public GDALPamDataset
     virtual CPLErr IRasterIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
                                void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType, 
+                               GDALDataType eBufType,
                                int nBandCount, int *panBandMap,
                                GSpacing nPixelSpace, GSpacing nLineSpace,
                                GSpacing nBandSpace,
                                GDALRasterIOExtraArg* psExtraArg);
     virtual char **GetFileList(void);
 
-    virtual CPLErr IBuildOverviews( const char *, int, int *, int, int *, 
+    virtual CPLErr IBuildOverviews( const char *, int, int *, int, int *,
                                     GDALProgressFunc, void * );
 
-    CPLErr	   OpenOffset( TIFF *, GTiffDataset **ppoActiveDSRef, 
-                               toff_t nDirOffset, int bBaseIn, GDALAccess, 
-                               int bAllowRGBAInterface = TRUE, int bReadGeoTransform = FALSE,
-                               char** papszSiblingFiles = NULL);
+    CPLErr         OpenOffset( TIFF *, GTiffDataset **ppoActiveDSRef,
+                               toff_t nDirOffset, int bBaseIn, GDALAccess,
+                               int bAllowRGBAInterface = TRUE, bool bReadGeoTransform = false);
 
     static GDALDataset *OpenDir( GDALOpenInfo * );
     static GDALDataset *Open( GDALOpenInfo * );
@@ -416,17 +477,17 @@ class GTiffDataset : public GDALPamDataset
     static GDALDataset *Create( const char * pszFilename,
                                 int nXSize, int nYSize, int nBands,
                                 GDALDataType eType, char ** papszParmList );
-    static GDALDataset *CreateCopy( const char * pszFilename, 
-                                    GDALDataset *poSrcDS, 
-                                    int bStrict, char ** papszOptions, 
-                                    GDALProgressFunc pfnProgress, 
+    static GDALDataset *CreateCopy( const char * pszFilename,
+                                    GDALDataset *poSrcDS,
+                                    int bStrict, char ** papszOptions,
+                                    GDALProgressFunc pfnProgress,
                                     void * pProgressData );
     virtual void    FlushCache( void );
 
     virtual char      **GetMetadataDomainList();
     virtual CPLErr  SetMetadata( char **, const char * = "" );
     virtual char  **GetMetadata( const char * pszDomain = "" );
-    virtual CPLErr  SetMetadataItem( const char*, const char*, 
+    virtual CPLErr  SetMetadataItem( const char*, const char*,
                                      const char* = "" );
     virtual const char *GetMetadataItem( const char * pszName,
                                          const char * pszDomain = "" );
@@ -437,9 +498,10 @@ class GTiffDataset : public GDALPamDataset
     // only needed by createcopy and close code.
     static void     WriteRPC( GDALDataset *, TIFF *, int, const char *,
                                    const char *, char **, int bWriteOnlyInPAMIfNeeded = FALSE );
-    static int	    WriteMetadata( GDALDataset *, TIFF *, int, const char *,
+    static int      WriteMetadata( GDALDataset *, TIFF *, int, const char *,
                                    const char *, char **, int bExcludeRPBandIMGFileWriting = FALSE );
-    static void	    WriteNoDataValue( TIFF *, double );
+    static void     WriteNoDataValue( TIFF *, double );
+    static void     UnsetNoDataValue( TIFF * );
 
     static TIFF *   CreateLL( const char * pszFilename,
                               int nXSize, int nYSize, int nBands,
@@ -461,7 +523,7 @@ class GTiffDataset : public GDALPamDataset
 /* ==================================================================== */
 /************************************************************************/
 
-class GTiffJPEGOverviewDS : public GDALDataset
+class GTiffJPEGOverviewDS CPL_FINAL : public GDALDataset
 {
         friend class GTiffJPEGOverviewBand;
         GTiffDataset* poParentDS;
@@ -483,14 +545,14 @@ class GTiffJPEGOverviewDS : public GDALDataset
        virtual CPLErr IRasterIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
                                void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType, 
+                               GDALDataType eBufType,
                                int nBandCount, int *panBandMap,
                                GSpacing nPixelSpace, GSpacing nLineSpace,
                                GSpacing nBandSpace,
                                GDALRasterIOExtraArg* psExtraArg);
 };
 
-class GTiffJPEGOverviewBand : public GDALRasterBand
+class GTiffJPEGOverviewBand CPL_FINAL : public GDALRasterBand
 {
     public:
         GTiffJPEGOverviewBand(GTiffJPEGOverviewDS* poDS, int nBand);
@@ -502,22 +564,22 @@ class GTiffJPEGOverviewBand : public GDALRasterBand
 /*                        GTiffJPEGOverviewDS()                         */
 /************************************************************************/
 
-GTiffJPEGOverviewDS::GTiffJPEGOverviewDS(GTiffDataset* poParentDS, int nOverviewLevel,
-                                         const void* pJPEGTable, int nJPEGTableSizeIn)
+GTiffJPEGOverviewDS::GTiffJPEGOverviewDS(GTiffDataset* poParentDSIn, int nOverviewLevelIn,
+                                         const void* pJPEGTable, int nJPEGTableSizeIn) :
+    nJPEGTableSize(nJPEGTableSizeIn),
+    poJPEGDS(NULL),
+    nBlockId(-1)
 {
-    this->poParentDS = poParentDS;
-    this->nOverviewLevel = nOverviewLevel;
-    poJPEGDS = NULL;
-    nBlockId = -1;
+    poParentDS = poParentDSIn;
+    nOverviewLevel = nOverviewLevelIn;
 
     osTmpFilenameJPEGTable.Printf("/vsimem/jpegtable_%p", this);
-    nJPEGTableSize = nJPEGTableSizeIn;
 
     const GByte abyAdobeAPP14RGB[] = {
         0xFF, 0xEE, 0x00, 0x0E, 0x41, 0x64, 0x6F, 0x62, 0x65, 0x00,
         0x64, 0x00, 0x00, 0x00, 0x00, 0x00 };
-    int bAddAdobe = ( poParentDS->nPlanarConfig == PLANARCONFIG_CONTIG &&
-                      poParentDS->nPhotometric != PHOTOMETRIC_YCBCR && poParentDS->nBands == 3 );
+    bool bAddAdobe = ( poParentDS->nPlanarConfig == PLANARCONFIG_CONTIG &&
+                       poParentDS->nPhotometric != PHOTOMETRIC_YCBCR && poParentDS->nBands == 3 );
     pabyJPEGTable = (GByte*) CPLMalloc(nJPEGTableSize + ((bAddAdobe) ? sizeof(abyAdobeAPP14RGB) : 0));
     memcpy(pabyJPEGTable, pJPEGTable, nJPEGTableSize);
     if( bAddAdobe )
@@ -525,14 +587,13 @@ GTiffJPEGOverviewDS::GTiffJPEGOverviewDS(GTiffDataset* poParentDS, int nOverview
         memcpy(pabyJPEGTable + nJPEGTableSize, abyAdobeAPP14RGB, sizeof(abyAdobeAPP14RGB));
         nJPEGTableSize += sizeof(abyAdobeAPP14RGB);
     }
-    VSIFCloseL(VSIFileFromMemBuffer( osTmpFilenameJPEGTable, pabyJPEGTable, nJPEGTableSize, TRUE ));
+    CPL_IGNORE_RET_VAL(VSIFCloseL(VSIFileFromMemBuffer( osTmpFilenameJPEGTable, pabyJPEGTable, nJPEGTableSize, TRUE )));
 
     int nScaleFactor = 1 << nOverviewLevel;
-    nRasterXSize = (poParentDS->nRasterXSize + nScaleFactor - 1) / nScaleFactor; 
-    nRasterYSize = (poParentDS->nRasterYSize + nScaleFactor - 1) / nScaleFactor; 
+    nRasterXSize = (poParentDS->nRasterXSize + nScaleFactor - 1) / nScaleFactor;
+    nRasterYSize = (poParentDS->nRasterYSize + nScaleFactor - 1) / nScaleFactor;
 
-    int i;
-    for(i=1;i<=poParentDS->nBands;i++)
+    for(int i=1;i<=poParentDS->nBands;i++)
         SetBand(i, new GTiffJPEGOverviewBand(this, i));
 
     SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
@@ -562,7 +623,7 @@ GTiffJPEGOverviewDS::~GTiffJPEGOverviewDS()
 CPLErr GTiffJPEGOverviewDS::IRasterIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
                                void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType, 
+                               GDALDataType eBufType,
                                int nBandCount, int *panBandMap,
                                GSpacing nPixelSpace, GSpacing nLineSpace,
                                GSpacing nBandSpace,
@@ -576,7 +637,7 @@ CPLErr GTiffJPEGOverviewDS::IRasterIO( GDALRWFlag eRWFlag,
         ((int)poParentDS->nBlockXSize < poParentDS->nRasterXSize ||
         poParentDS->nBlockYSize > 1) )
     {
-        return BlockBasedRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, 
+        return BlockBasedRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
                                    pData, nBufXSize, nBufYSize,
                                    eBufType, nBandCount, panBandMap,
                                    nPixelSpace, nLineSpace, nBandSpace, psExtraArg );
@@ -595,18 +656,15 @@ CPLErr GTiffJPEGOverviewDS::IRasterIO( GDALRWFlag eRWFlag,
 /*                        GTiffJPEGOverviewBand()                       */
 /************************************************************************/
 
-GTiffJPEGOverviewBand::GTiffJPEGOverviewBand(GTiffJPEGOverviewDS* poDS, int nBand)
+GTiffJPEGOverviewBand::GTiffJPEGOverviewBand(GTiffJPEGOverviewDS* poDSIn, int nBandIn)
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
-    eDataType = poDS->poParentDS->GetRasterBand(nBand)->GetRasterDataType();
-    poDS->poParentDS->GetRasterBand(nBand)->GetBlockSize(&nBlockXSize, &nBlockYSize);
-    int nScaleFactor = 1 << poDS->nOverviewLevel;
-    nBlockXSize = (nBlockXSize + nScaleFactor - 1) / nScaleFactor; 
-    if( nBlockYSize == 1 )
-        nBlockYSize = 1;
-    else
-        nBlockYSize = (nBlockYSize + nScaleFactor - 1) / nScaleFactor; 
+    poDS = poDSIn;
+    nBand = nBandIn;
+    eDataType = poDSIn->poParentDS->GetRasterBand(nBandIn)->GetRasterDataType();
+    poDSIn->poParentDS->GetRasterBand(nBandIn)->GetBlockSize(&nBlockXSize, &nBlockYSize);
+    const int nScaleFactor = 1 << poDSIn->nOverviewLevel;
+    nBlockXSize = (nBlockXSize + nScaleFactor - 1) / nScaleFactor;
+    nBlockYSize = (nBlockYSize + nScaleFactor - 1) / nScaleFactor;
 }
 
 /************************************************************************/
@@ -625,7 +683,8 @@ CPLErr GTiffJPEGOverviewBand::IReadBlock( int nBlockXOff, int nBlockYOff, void *
     }
     else
     {
-        int nBlocksPerRow = DIV_ROUND_UP(poGDS->poParentDS->nRasterXSize, poGDS->poParentDS->nBlockXSize);
+        nBlocksPerRow = DIV_ROUND_UP(poGDS->poParentDS->nRasterXSize,
+                                               poGDS->poParentDS->nBlockXSize);
         nBlockId = nBlockYOff * nBlocksPerRow + nBlockXOff;
     }
     if( poGDS->poParentDS->nPlanarConfig == PLANARCONFIG_SEPARATE )
@@ -637,7 +696,7 @@ CPLErr GTiffJPEGOverviewBand::IReadBlock( int nBlockXOff, int nBlockYOff, void *
         return CE_Failure;
 
     /* Make sure it is available */
-    int nDataTypeSize = GDALGetDataTypeSize(eDataType)/8;
+    const int nDataTypeSize = GDALGetDataTypeSize(eDataType)/8;
     if( !poGDS->poParentDS->IsBlockAvailable(nBlockId) )
     {
         memset(pImage, 0, nBlockXSize * nBlockYSize * nDataTypeSize );
@@ -654,10 +713,10 @@ CPLErr GTiffJPEGOverviewBand::IReadBlock( int nBlockXOff, int nBlockYOff, void *
 
         /* Find offset and size of the JPEG tile/strip */
         TIFF* hTIFF = poGDS->poParentDS->hTIFF;
-        if( (( TIFFIsTiled( hTIFF ) 
+        if( (( TIFFIsTiled( hTIFF )
             && TIFFGetField( hTIFF, TIFFTAG_TILEBYTECOUNTS, &panByteCounts )
             && TIFFGetField( hTIFF, TIFFTAG_TILEOFFSETS, &panOffsets ) )
-            || ( !TIFFIsTiled( hTIFF ) 
+            || ( !TIFFIsTiled( hTIFF )
             && TIFFGetField( hTIFF, TIFFTAG_STRIPBYTECOUNTS, &panByteCounts )
             && TIFFGetField( hTIFF, TIFFTAG_STRIPOFFSETS, &panOffsets ) )) &&
             panByteCounts != NULL && panOffsets != NULL )
@@ -690,26 +749,36 @@ CPLErr GTiffJPEGOverviewBand::IReadBlock( int nBlockXOff, int nBlockYOff, void *
         /* If the size of the JPEG strip/tile is small enough, we will */
         /* read it from the TIFF file and forge a in-memory JPEG file with */
         /* the JPEG table followed by the JPEG data. */
-        int bInMemoryJPEGFile = ( nByteCount < 256 * 256 );
+        bool bInMemoryJPEGFile = ( nByteCount < 256 * 256 );
         if( bInMemoryJPEGFile )
         {
             /* If the previous file was opened as a /vsisparse/, we have to re-open */
             if( poGDS->poJPEGDS != NULL &&
-                strncmp(poGDS->poJPEGDS->GetDescription(), "/vsisparse/", strlen("/vsisparse/")) == 0 )
+                STARTS_WITH(poGDS->poJPEGDS->GetDescription(), "/vsisparse/") )
             {
                 GDALClose( (GDALDatasetH) poGDS->poJPEGDS );
                 poGDS->poJPEGDS = NULL;
             }
             osFileToOpen = poGDS->osTmpFilename;
 
-            VSIFSeekL(fp, poGDS->nJPEGTableSize + nByteCount - 1, SEEK_SET);
+            bool bError = FALSE;
+            if( VSIFSeekL(fp, poGDS->nJPEGTableSize + nByteCount - 1, SEEK_SET) != 0 )
+                bError = true;
             char ch = 0;
-            VSIFWriteL(&ch, 1, 1, fp);
+            if( !bError && VSIFWriteL(&ch, 1, 1, fp) != 1 )
+                bError = true;
             GByte* pabyBuffer = VSIGetMemFileBuffer( poGDS->osTmpFilename, NULL, FALSE);
             memcpy(pabyBuffer, poGDS->pabyJPEGTable, poGDS->nJPEGTableSize);
             VSILFILE* fpTIF = VSI_TIFFGetVSILFile(TIFFClientdata( hTIFF ));
-            VSIFSeekL(fpTIF, nOffset, SEEK_SET);
-            VSIFReadL(pabyBuffer + poGDS->nJPEGTableSize, 1, (size_t)nByteCount, fpTIF);
+            if( !bError && VSIFSeekL(fpTIF, nOffset, SEEK_SET) != 0 )
+                bError = true;
+            if( VSIFReadL(pabyBuffer + poGDS->nJPEGTableSize, (size_t)nByteCount, 1, fpTIF) != 1 )
+                bError = true;
+            if( bError )
+            {
+                CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
+                return CE_Failure;
+            }
         }
         else
         {
@@ -722,7 +791,7 @@ CPLErr GTiffJPEGOverviewBand::IReadBlock( int nBlockXOff, int nBlockYOff, void *
 
             osFileToOpen = CPLSPrintf("/vsisparse/%s", poGDS->osTmpFilename.c_str());
 
-            VSIFPrintfL(fp, "<VSISparseFile><SubfileRegion><Filename relative='0'>%s</Filename>"
+            if( VSIFPrintfL(fp, "<VSISparseFile><SubfileRegion><Filename relative='0'>%s</Filename>"
                         "<DestinationOffset>0</DestinationOffset>"
                         "<SourceOffset>0</SourceOffset>"
                         "<RegionLength>%d</RegionLength>"
@@ -738,9 +807,13 @@ CPLErr GTiffJPEGOverviewBand::IReadBlock( int nBlockXOff, int nBlockYOff, void *
                         poGDS->poParentDS->GetDescription(),
                         (int)poGDS->nJPEGTableSize,
                         nOffset,
-                        nByteCount);
+                        nByteCount) < 0 )
+            {
+                CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
+                return CE_Failure;
+            }
         }
-        VSIFCloseL(fp);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
 
         if( poGDS->poJPEGDS == NULL )
         {
@@ -778,13 +851,13 @@ CPLErr GTiffJPEGOverviewBand::IReadBlock( int nBlockXOff, int nBlockYOff, void *
     CPLErr eErr = CE_Failure;
     if( poGDS->poJPEGDS )
     {
-        GDALDataset* poDS = poGDS->poJPEGDS;
+        GDALDataset* l_poDS = poGDS->poJPEGDS;
 
         int nReqXOff = 0, nReqYOff, nReqXSize, nReqYSize;
         if( nBlockYSize == 1 )
         {
             nReqYOff = nBlockYOff * nScaleFactor;
-            nReqXSize = poDS->GetRasterXSize();
+            nReqXSize = l_poDS->GetRasterXSize();
             nReqYSize = nScaleFactor;
         }
         else
@@ -795,23 +868,23 @@ CPLErr GTiffJPEGOverviewBand::IReadBlock( int nBlockXOff, int nBlockYOff, void *
         }
         int nBufXSize = nBlockXSize;
         int nBufYSize = nBlockYSize;
-        if( nReqXOff + nReqXSize > poDS->GetRasterXSize() )
+        if( nReqXOff + nReqXSize > l_poDS->GetRasterXSize() )
         {
-            nReqXSize = poDS->GetRasterXSize() - nReqXOff;
+            nReqXSize = l_poDS->GetRasterXSize() - nReqXOff;
             nBufXSize = nReqXSize / nScaleFactor;
             if( nBufXSize == 0 ) nBufXSize = 1;
         }
-        if( nReqYOff + nReqYSize > poDS->GetRasterYSize() )
+        if( nReqYOff + nReqYSize > l_poDS->GetRasterYSize() )
         {
-            nReqYSize = poDS->GetRasterYSize() - nReqYOff;
+            nReqYSize = l_poDS->GetRasterYSize() - nReqYOff;
             nBufYSize = nReqYSize / nScaleFactor;
             if( nBufYSize == 0 ) nBufYSize = 1;
         }
 
         int nSrcBand = ( poGDS->poParentDS->nPlanarConfig == PLANARCONFIG_SEPARATE ) ? 1 : nBand;
-        if( nSrcBand <= poDS->GetRasterCount() )
+        if( nSrcBand <= l_poDS->GetRasterCount() )
         {
-            eErr = poDS->GetRasterBand(nSrcBand)->RasterIO(GF_Read,
+            eErr = l_poDS->GetRasterBand(nSrcBand)->RasterIO(GF_Read,
                                  nReqXOff, nReqYOff, nReqXSize, nReqYSize,
                                  pImage,
                                  nBufXSize, nBufYSize, eDataType,
@@ -828,7 +901,7 @@ CPLErr GTiffJPEGOverviewBand::IReadBlock( int nBlockXOff, int nBlockYOff, void *
 /* of the .ovr file                                                     */
 /************************************************************************/
 
-void    GTIFFSetJpegQuality(GDALDatasetH hGTIFFDS, int nJpegQuality)
+void GTIFFSetJpegQuality(GDALDatasetH hGTIFFDS, int nJpegQuality)
 {
     CPLAssert(EQUAL(GDALGetDriverShortName(GDALGetDatasetDriver(hGTIFFDS)), "GTIFF"));
 
@@ -837,8 +910,7 @@ void    GTIFFSetJpegQuality(GDALDatasetH hGTIFFDS, int nJpegQuality)
 
     poDS->ScanDirectories();
 
-    int i;
-    for(i=0;i<poDS->nOverviewCount;i++)
+    for(int i=0;i<poDS->nOverviewCount;i++)
         poDS->papoOverviewDS[i]->nJpegQuality = nJpegQuality;
 }
 
@@ -860,7 +932,7 @@ class GTiffRasterBand : public GDALPamRasterBand
     CPLString          osUnitType;
     CPLString          osDescription;
 
-    CPLErr DirectIO( GDALRWFlag eRWFlag,
+    int                DirectIO( GDALRWFlag eRWFlag,
                                   int nXOff, int nYOff, int nXSize, int nYSize,
                                   void * pData, int nBufXSize, int nBufYSize,
                                   GDALDataType eBufType,
@@ -895,83 +967,93 @@ public:
                                   void * pData, int nBufXSize, int nBufYSize,
                                   GDALDataType eBufType,
                                   GSpacing nPixelSpace, GSpacing nLineSpace,
-                                  GDALRasterIOExtraArg* psExtraArg );
-
-    virtual const char *GetDescription() const;
-    virtual void        SetDescription( const char * );
-
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual GDALColorTable *GetColorTable();
-    virtual CPLErr          SetColorTable( GDALColorTable * );
-    virtual double	    GetNoDataValue( int * );
-    virtual CPLErr	    SetNoDataValue( double );
-
-    virtual double GetOffset( int *pbSuccess = NULL );
-    virtual CPLErr SetOffset( double dfNewValue );
-    virtual double GetScale( int *pbSuccess = NULL );
-    virtual CPLErr SetScale( double dfNewValue );
-    virtual const char* GetUnitType();
-    virtual CPLErr SetUnitType( const char *pszNewValue );
-    virtual CPLErr SetColorInterpretation( GDALColorInterp );
-
-    virtual char      **GetMetadataDomainList();
-    virtual CPLErr  SetMetadata( char **, const char * = "" );
-    virtual char  **GetMetadata( const char * pszDomain = "" );
-    virtual CPLErr  SetMetadataItem( const char*, const char*, 
-                                     const char* = "" );
+                                  GDALRasterIOExtraArg* psExtraArg ) CPL_FINAL;
+
+    virtual const char *GetDescription() const CPL_FINAL;
+    virtual void        SetDescription( const char * ) CPL_FINAL;
+
+    virtual GDALColorInterp GetColorInterpretation() /*CPL_FINAL*/;
+    virtual GDALColorTable *GetColorTable() /*CPL_FINAL*/;
+    virtual CPLErr          SetColorTable( GDALColorTable * ) CPL_FINAL;
+    virtual double          GetNoDataValue( int * ) CPL_FINAL;
+    virtual CPLErr          SetNoDataValue( double ) CPL_FINAL;
+    virtual CPLErr DeleteNoDataValue() CPL_FINAL;
+
+    virtual double GetOffset( int *pbSuccess = NULL ) CPL_FINAL;
+    virtual CPLErr SetOffset( double dfNewValue ) CPL_FINAL;
+    virtual double GetScale( int *pbSuccess = NULL ) CPL_FINAL;
+    virtual CPLErr SetScale( double dfNewValue ) CPL_FINAL;
+    virtual const char* GetUnitType() CPL_FINAL;
+    virtual CPLErr SetUnitType( const char *pszNewValue ) CPL_FINAL;
+    virtual CPLErr SetColorInterpretation( GDALColorInterp ) CPL_FINAL;
+
+    virtual char      **GetMetadataDomainList() CPL_FINAL;
+    virtual CPLErr  SetMetadata( char **, const char * = "" ) CPL_FINAL;
+    virtual char  **GetMetadata( const char * pszDomain = "" ) CPL_FINAL;
+    virtual CPLErr  SetMetadataItem( const char*, const char*,
+                                     const char* = "" ) CPL_FINAL;
     virtual const char *GetMetadataItem( const char * pszName,
-                                         const char * pszDomain = "" );
-    virtual int    GetOverviewCount();
-    virtual GDALRasterBand *GetOverview( int );
+                                         const char * pszDomain = "" ) CPL_FINAL;
+    virtual int    GetOverviewCount() CPL_FINAL;
+    virtual GDALRasterBand *GetOverview( int ) CPL_FINAL;
 
-    virtual GDALRasterBand *GetMaskBand();
-    virtual int             GetMaskFlags();
-    virtual CPLErr          CreateMaskBand( int nFlags );
+    virtual GDALRasterBand *GetMaskBand() CPL_FINAL;
+    virtual int             GetMaskFlags() CPL_FINAL;
+    virtual CPLErr          CreateMaskBand( int nFlags ) CPL_FINAL;
 
     virtual CPLVirtualMem  *GetVirtualMemAuto( GDALRWFlag eRWFlag,
                                                int *pnPixelSpace,
                                                GIntBig *pnLineSpace,
-                                               char **papszOptions );
+                                               char **papszOptions ) CPL_FINAL;
+
+    virtual CPLErr  GetHistogram( double dfMin, double dfMax,
+                          int nBuckets, GUIntBig * panHistogram,
+                          int bIncludeOutOfRange, int bApproxOK,
+                          GDALProgressFunc, void *pProgressData ) CPL_FINAL;
+
+    virtual CPLErr GetDefaultHistogram( double *pdfMin, double *pdfMax,
+                                        int *pnBuckets, GUIntBig ** ppanHistogram,
+                                        int bForce,
+                                        GDALProgressFunc, void *pProgressData) CPL_FINAL;
 };
 
 /************************************************************************/
 /*                           GTiffRasterBand()                          */
 /************************************************************************/
 
-GTiffRasterBand::GTiffRasterBand( GTiffDataset *poDS, int nBand )
-
+GTiffRasterBand::GTiffRasterBand( GTiffDataset *poDSIn, int nBandIn) :
+    bHaveOffsetScale(FALSE),
+    dfOffset(0.0),
+    dfScale(1.0),
+    poGDS(poDSIn),
+    bNoDataSet(FALSE),
+    dfNoDataValue(-9999.0)
 {
-    poGDS = poDS;
-
-    this->poDS = poDS;
-    this->nBand = nBand;
-
-    bHaveOffsetScale = FALSE;
-    dfOffset = 0.0;
-    dfScale = 1.0;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
 /* -------------------------------------------------------------------- */
 /*      Get the GDAL data type.                                         */
 /* -------------------------------------------------------------------- */
-    uint16		nSampleFormat = poDS->nSampleFormat;
+    const uint16 nBitsPerSample = poGDS->nBitsPerSample;
+    const uint16 nSampleFormat = poGDS->nSampleFormat;
 
     eDataType = GDT_Unknown;
 
-    if( poDS->nBitsPerSample <= 8 )
+    if( nBitsPerSample <= 8 )
     {
         eDataType = GDT_Byte;
         if( nSampleFormat == SAMPLEFORMAT_INT )
-            SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" );
-            
+            oGTiffMDMD.SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" );
     }
-    else if( poDS->nBitsPerSample <= 16 )
+    else if( nBitsPerSample <= 16 )
     {
         if( nSampleFormat == SAMPLEFORMAT_INT )
             eDataType = GDT_Int16;
         else
             eDataType = GDT_UInt16;
     }
-    else if( poDS->nBitsPerSample == 32 )
+    else if( nBitsPerSample == 32 )
     {
         if( nSampleFormat == SAMPLEFORMAT_COMPLEXINT )
             eDataType = GDT_CInt16;
@@ -982,7 +1064,7 @@ GTiffRasterBand::GTiffRasterBand( GTiffDataset *poDS, int nBand )
         else
             eDataType = GDT_UInt32;
     }
-    else if( poDS->nBitsPerSample == 64 )
+    else if( nBitsPerSample == 64 )
     {
         if( nSampleFormat == SAMPLEFORMAT_IEEEFP )
             eDataType = GDT_Float64;
@@ -991,7 +1073,7 @@ GTiffRasterBand::GTiffRasterBand( GTiffDataset *poDS, int nBand )
         else if( nSampleFormat == SAMPLEFORMAT_COMPLEXINT )
             eDataType = GDT_CInt32;
     }
-    else if( poDS->nBitsPerSample == 128 )
+    else if( nBitsPerSample == 128 )
     {
         if( nSampleFormat == SAMPLEFORMAT_COMPLEXIEEEFP )
             eDataType = GDT_CFloat64;
@@ -1000,14 +1082,14 @@ GTiffRasterBand::GTiffRasterBand( GTiffDataset *poDS, int nBand )
 /* -------------------------------------------------------------------- */
 /*      Try to work out band color interpretation.                      */
 /* -------------------------------------------------------------------- */
-    int bLookForExtraSamples = FALSE;
+    bool bLookForExtraSamples = false;
 
-    if( poDS->poColorTable != NULL && nBand == 1 ) 
+    if( poGDS->poColorTable != NULL && nBand == 1 )
         eBandInterp = GCI_PaletteIndex;
-    else if( poDS->nPhotometric == PHOTOMETRIC_RGB 
-             || (poDS->nPhotometric == PHOTOMETRIC_YCBCR 
-                 && poDS->nCompression == COMPRESSION_JPEG 
-                 && CSLTestBoolean( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB",
+    else if( poGDS->nPhotometric == PHOTOMETRIC_RGB
+             || (poGDS->nPhotometric == PHOTOMETRIC_YCBCR
+                 && poGDS->nCompression == COMPRESSION_JPEG
+                 && CPLTestBool( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB",
                                                        "YES") )) )
     {
         if( nBand == 1 )
@@ -1017,9 +1099,9 @@ GTiffRasterBand::GTiffRasterBand( GTiffDataset *poDS, int nBand )
         else if( nBand == 3 )
             eBandInterp = GCI_BlueBand;
         else
-            bLookForExtraSamples = TRUE;
+            bLookForExtraSamples = true;
     }
-    else if( poDS->nPhotometric == PHOTOMETRIC_YCBCR )
+    else if( poGDS->nPhotometric == PHOTOMETRIC_YCBCR )
     {
         if( nBand == 1 )
             eBandInterp = GCI_YCbCr_YBand;
@@ -1028,9 +1110,9 @@ GTiffRasterBand::GTiffRasterBand( GTiffDataset *poDS, int nBand )
         else if( nBand == 3 )
             eBandInterp = GCI_YCbCr_CrBand;
         else
-            bLookForExtraSamples = TRUE;
+            bLookForExtraSamples = true;
     }
-    else if( poDS->nPhotometric == PHOTOMETRIC_SEPARATED )
+    else if( poGDS->nPhotometric == PHOTOMETRIC_SEPARATED )
     {
         if( nBand == 1 )
             eBandInterp = GCI_CyanBand;
@@ -1041,22 +1123,36 @@ GTiffRasterBand::GTiffRasterBand( GTiffDataset *poDS, int nBand )
         else if( nBand == 4 )
             eBandInterp = GCI_BlackBand;
         else
-            bLookForExtraSamples = TRUE;
+            bLookForExtraSamples = true;
     }
-    else if( poDS->nPhotometric == PHOTOMETRIC_MINISBLACK && nBand == 1 )
+    else if( poGDS->nPhotometric == PHOTOMETRIC_MINISBLACK && nBand == 1 )
         eBandInterp = GCI_GrayIndex;
     else
-        bLookForExtraSamples = TRUE;
-        
+        bLookForExtraSamples = true;
+
     if( bLookForExtraSamples )
     {
         uint16 *v;
         uint16 count = 0;
 
-        if( TIFFGetField( poDS->hTIFF, TIFFTAG_EXTRASAMPLES, &count, &v ) )
+        if( TIFFGetField( poGDS->hTIFF, TIFFTAG_EXTRASAMPLES, &count, &v ) )
         {
-            int nBaseSamples;
-            nBaseSamples = poDS->nSamplesPerPixel - count;
+            const int nBaseSamples = poGDS->nSamplesPerPixel - count;
+            const int nExpectedBaseSamples =
+                (poGDS->nPhotometric == PHOTOMETRIC_MINISBLACK) ? 1 :
+                (poGDS->nPhotometric == PHOTOMETRIC_MINISWHITE) ? 1 :
+                (poGDS->nPhotometric == PHOTOMETRIC_RGB) ? 3 :
+                (poGDS->nPhotometric == PHOTOMETRIC_YCBCR) ? 3 :
+                (poGDS->nPhotometric == PHOTOMETRIC_SEPARATED) ? 4 : 0;
+
+            if( nExpectedBaseSamples > 0 &&
+                nBand == nExpectedBaseSamples + 1 &&
+                nBaseSamples != nExpectedBaseSamples )
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "Wrong number of ExtraSamples : %d. %d were expected",
+                         count, poGDS->nSamplesPerPixel - nExpectedBaseSamples);
+            }
 
             if( nBand > nBaseSamples
                 && nBand-nBaseSamples-1 < count
@@ -1071,13 +1167,10 @@ GTiffRasterBand::GTiffRasterBand( GTiffDataset *poDS, int nBand )
     }
 
 /* -------------------------------------------------------------------- */
-/*	Establish block size for strip or tiles.			*/
+/*      Establish block size for strip or tiles.                        */
 /* -------------------------------------------------------------------- */
-    nBlockXSize = poDS->nBlockXSize;
-    nBlockYSize = poDS->nBlockYSize;
-
-    bNoDataSet = FALSE;
-    dfNoDataValue = -9999.0;
+    nBlockXSize = poGDS->nBlockXSize;
+    nBlockYSize = poGDS->nBlockYSize;
 }
 
 /************************************************************************/
@@ -1086,8 +1179,8 @@ GTiffRasterBand::GTiffRasterBand( GTiffDataset *poDS, int nBand )
 
 GTiffRasterBand::~GTiffRasterBand()
 {
-    /* So that any future DropReferenceVirtualMem() will not try to access the */
-    /* raster band object, but this wouldn't conform the advertized contract */
+    // So that any future DropReferenceVirtualMem() will not try to access the
+    // raster band object, but this would not conform the advertised contract.
     if( aSetPSelf.size() != 0 )
     {
         CPLError(CE_Warning, CPLE_AppDefined,
@@ -1099,33 +1192,112 @@ GTiffRasterBand::~GTiffRasterBand()
 }
 
 /************************************************************************/
+/*                        FetchBufferDirectIO                           */
+/************************************************************************/
+
+class FetchBufferDirectIO CPL_FINAL
+{
+    VSILFILE*    fp;
+    GByte       *pTempBuffer;
+    size_t       nTempBufferSize;
+
+public:
+            FetchBufferDirectIO(VSILFILE* fpIn, GByte* pTempBufferIn, size_t nTempBufferSizeIn) :
+                    fp(fpIn),
+                    pTempBuffer(pTempBufferIn),
+                    nTempBufferSize(nTempBufferSizeIn) {}
+
+    const GByte* FetchBytes(vsi_l_offset nOffset,
+                            int nPixels, int nDTSize,
+                            bool bIsByteSwapped, bool bIsComplex,
+                            int nBlockId)
+    {
+        if( !FetchBytes(pTempBuffer, nOffset, nPixels, nDTSize, bIsByteSwapped,
+                        bIsComplex, nBlockId) )
+        {
+            return NULL;
+        }
+        return pTempBuffer;
+    }
+
+    bool  FetchBytes(GByte* pabyDstBuffer,
+                     vsi_l_offset nOffset,
+                     int nPixels, int nDTSize,
+                     bool bIsByteSwapped, bool bIsComplex,
+                     int nBlockId)
+    {
+        vsi_l_offset nSeekForward = 0;
+        if( nOffset <= VSIFTellL(fp) ||
+            (nSeekForward = nOffset - VSIFTellL(fp)) > nTempBufferSize )
+        {
+            if( VSIFSeekL(fp, nOffset, SEEK_SET) != 0 )
+            {
+                CPLError(CE_Failure, CPLE_FileIO,
+                         "Cannot seek to block %d", nBlockId);
+                return false;
+            }
+        }
+        else
+        {
+            while( nSeekForward > 0 )
+            {
+                size_t nToRead = (size_t) MIN( nTempBufferSize, nSeekForward );
+                if( VSIFReadL(pTempBuffer, nToRead, 1, fp) != 1 )
+                {
+                    CPLError(CE_Failure, CPLE_FileIO,
+                             "Cannot seek to block %d", nBlockId);
+                    return false;
+                }
+                nSeekForward -= nToRead;
+            }
+        }
+        if( VSIFReadL(pabyDstBuffer, nPixels * nDTSize, 1, fp) != 1 )
+        {
+            CPLError(CE_Failure, CPLE_FileIO,
+                    "Missing data for block %d", nBlockId);
+            return false;
+        }
+
+        if( bIsByteSwapped )
+        {
+            if( bIsComplex )
+                GDALSwapWords( pabyDstBuffer, nDTSize / 2, 2 * nPixels, nDTSize / 2);
+            else
+                GDALSwapWords( pabyDstBuffer, nDTSize, nPixels, nDTSize);
+        }
+        return true;
+    }
+
+    static const EMULATED_BOOL bMinimizeIO = true;
+};
+
+/************************************************************************/
 /*                           DirectIO()                                 */
 /************************************************************************/
 
 /* Reads directly bytes from the file using ReadMultiRange(), and by-pass */
-/* block reading. Restricted to simple TIFF configurations (un-tiled, */
-/* uncompressed data, standard data types). Particularly useful to extract */
+/* block reading. Restricted to simple TIFF configurations */
+/* (uncompressed data, standard data types). Particularly useful to extract */
 /* sub-windows of data on a large /vsicurl dataset). */
+/* Returns -1 if DirectIO() can't be supported on that file */
 
-CPLErr GTiffRasterBand::DirectIO( GDALRWFlag eRWFlag,
+int GTiffRasterBand::DirectIO( GDALRWFlag eRWFlag,
                                   int nXOff, int nYOff, int nXSize, int nYSize,
                                   void * pData, int nBufXSize, int nBufYSize,
                                   GDALDataType eBufType,
                                   GSpacing nPixelSpace, GSpacing nLineSpace,
                                   GDALRasterIOExtraArg* psExtraArg )
 {
+    const int nDTSizeBits = GDALGetDataTypeSize(eDataType);
     if( !(eRWFlag == GF_Read &&
           poGDS->nCompression == COMPRESSION_NONE &&
           (poGDS->nPhotometric == PHOTOMETRIC_MINISBLACK ||
            poGDS->nPhotometric == PHOTOMETRIC_RGB ||
            poGDS->nPhotometric == PHOTOMETRIC_PALETTE) &&
-          (poGDS->nBitsPerSample == 8 || (poGDS->nBitsPerSample == 16) ||
-           poGDS->nBitsPerSample == 32 || poGDS->nBitsPerSample == 64) &&
-          poGDS->nBitsPerSample == GDALGetDataTypeSize(eDataType) &&
-          poGDS->SetDirectory() && /* very important to make hTIFF uptodate! */
-          !TIFFIsTiled( poGDS->hTIFF )) )
+          poGDS->nBitsPerSample == nDTSizeBits &&
+          poGDS->SetDirectory() /* very important to make hTIFF uptodate! */) )
     {
-        return CE_Failure;
+        return -1;
     }
 
     /* we only know how to deal with nearest neighbour in this optimized routine */
@@ -1133,7 +1305,7 @@ CPLErr GTiffRasterBand::DirectIO( GDALRWFlag eRWFlag,
         psExtraArg != NULL &&
         psExtraArg->eResampleAlg != GRIORA_NearestNeighbour )
     {
-        return CE_Failure;
+        return -1;
     }
 
     /*CPLDebug("GTiff", "DirectIO(%d,%d,%d,%d -> %dx%d)",
@@ -1147,6 +1319,33 @@ CPLErr GTiffRasterBand::DirectIO( GDALRWFlag eRWFlag,
         VSI_TIFFFlushBufferedWrite( TIFFClientdata( poGDS->hTIFF ) );
     }
 
+    if( TIFFIsTiled( poGDS->hTIFF ) )
+    {
+        if( poGDS->m_pTempBufferForCommonDirectIO == NULL )
+        {
+            const int nDTSize = nDTSizeBits / 8;
+            poGDS->m_nTempBufferForCommonDirectIOSize =
+                (size_t)(nBlockXSize * nBlockYSize * nDTSize *
+                ((poGDS->nPlanarConfig == PLANARCONFIG_CONTIG) ? poGDS->nBands : 1));
+
+            poGDS->m_pTempBufferForCommonDirectIO = (GByte*)VSI_MALLOC_VERBOSE(poGDS->m_nTempBufferForCommonDirectIOSize);
+            if( poGDS->m_pTempBufferForCommonDirectIO == NULL )
+                return CE_Failure;
+        }
+
+        VSILFILE* fp = VSI_TIFFGetVSILFile(TIFFClientdata( poGDS->hTIFF ));
+        FetchBufferDirectIO oFetcher(fp, poGDS->m_pTempBufferForCommonDirectIO,
+                                     poGDS->m_nTempBufferForCommonDirectIOSize);
+
+        return poGDS->CommonDirectIO( oFetcher,
+                            nXOff, nYOff, nXSize, nYSize,
+                            pData, nBufXSize, nBufYSize,
+                            eBufType,
+                            1, &nBand,
+                            nPixelSpace, nLineSpace,
+                            0 );
+    }
+
     /* Get strip offsets */
     toff_t *panTIFFOffsets = NULL;
     if ( !TIFFGetField( poGDS->hTIFF, TIFFTAG_STRIPOFFSETS, &panTIFFOffsets ) ||
@@ -1155,18 +1354,17 @@ CPLErr GTiffRasterBand::DirectIO( GDALRWFlag eRWFlag,
         return CE_Failure;
     }
 
-    int iLine;
     int nReqXSize = nXSize; /* sub-sampling or over-sampling can only be done at last stage */
     int nReqYSize = MIN(nBufYSize, nYSize); /* we can do sub-sampling at the extraction stage */
-    void** ppData = (void**) VSIMalloc(nReqYSize * sizeof(void*));
+    void** ppData = (void**) VSI_MALLOC_VERBOSE(nReqYSize * sizeof(void*));
     vsi_l_offset* panOffsets = (vsi_l_offset*)
-                            VSIMalloc(nReqYSize * sizeof(vsi_l_offset));
-    size_t* panSizes = (size_t*) VSIMalloc(nReqYSize * sizeof(size_t));
+                            VSI_MALLOC_VERBOSE(nReqYSize * sizeof(vsi_l_offset));
+    size_t* panSizes = (size_t*) VSI_MALLOC_VERBOSE(nReqYSize * sizeof(size_t));
     int nDTSize = GDALGetDataTypeSize(eDataType) / 8;
     void* pTmpBuffer = NULL;
-    CPLErr eErr = CE_None;
+    int eErr = CE_None;
     int nContigBands = ((poGDS->nPlanarConfig == PLANARCONFIG_CONTIG) ? poGDS->nBands : 1);
-    int ePixelSize = nDTSize * nContigBands;
+    int nSrcPixelSize = nDTSize * nContigBands;
 
     if (ppData == NULL || panOffsets == NULL || panSizes == NULL)
         eErr = CE_Failure;
@@ -1177,28 +1375,31 @@ CPLErr GTiffRasterBand::DirectIO( GDALRWFlag eRWFlag,
     {
         /* We need a temporary buffer for over-sampling/sub-sampling */
         /* and/or data type conversion */
-        pTmpBuffer = VSIMalloc(nReqXSize * nReqYSize * ePixelSize);
+        pTmpBuffer = VSI_MALLOC_VERBOSE(nReqXSize * nReqYSize * nSrcPixelSize);
         if (pTmpBuffer == NULL)
             eErr = CE_Failure;
     }
 
     /* Prepare data extraction */
+    const double dfSrcYInc = nYSize / (double) nBufYSize;
+
+    int iLine;
     for(iLine=0;eErr == CE_None && iLine<nReqYSize;iLine++)
     {
         if (pTmpBuffer == NULL)
             ppData[iLine] = ((GByte*)pData) + iLine * nLineSpace;
         else
-            ppData[iLine] = ((GByte*)pTmpBuffer) + iLine * nReqXSize * ePixelSize;
+            ppData[iLine] = ((GByte*)pTmpBuffer) + iLine * nReqXSize * nSrcPixelSize;
         int nSrcLine;
         if (nBufYSize < nYSize) /* Sub-sampling in y */
-            nSrcLine = nYOff + (int)((iLine + 0.5) * nYSize / nBufYSize);
+            nSrcLine = nYOff + (int)((iLine + 0.5) * dfSrcYInc);
         else
             nSrcLine = nYOff + iLine;
 
         int nBlockXOff = 0;
         int nBlockYOff = nSrcLine / nBlockYSize;
         int nYOffsetInBlock = nSrcLine % nBlockYSize;
-        int nBlocksPerRow = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
+        nBlocksPerRow = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
         int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
         if( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE )
         {
@@ -1207,10 +1408,10 @@ CPLErr GTiffRasterBand::DirectIO( GDALRWFlag eRWFlag,
 
         panOffsets[iLine] = panTIFFOffsets[nBlockId];
         if (panOffsets[iLine] == 0) /* We don't support sparse files */
-            eErr = CE_Failure;
+            eErr = -1;
 
-        panOffsets[iLine] += (nXOff + nYOffsetInBlock * nBlockXSize) * ePixelSize;
-        panSizes[iLine] = nReqXSize * ePixelSize;
+        panOffsets[iLine] += (nXOff + nYOffsetInBlock * nBlockXSize) * nSrcPixelSize;
+        panSizes[iLine] = nReqXSize * nSrcPixelSize;
     }
 
     /* Extract data from the file */
@@ -1235,38 +1436,42 @@ CPLErr GTiffRasterBand::DirectIO( GDALRWFlag eRWFlag,
     }
 
     /* Over-sampling/sub-sampling and/or data type conversion */
+    const double dfSrcXInc = nXSize / (double) nBufXSize;
     if (eErr == CE_None && pTmpBuffer != NULL)
     {
         for(int iY=0;iY<nBufYSize;iY++)
         {
             int iSrcY = (nBufYSize <= nYSize) ? iY :
-                            (int)((iY + 0.5) * nYSize / nBufYSize);
-            if (nBufXSize == nXSize && nContigBands == 1)
+                            (int)((iY + 0.5) * dfSrcYInc);
+
+            GByte* pabySrcData = ((GByte*)ppData[iSrcY]) +
+                        ((nContigBands > 1) ? (nBand-1) : 0) * nDTSize;
+            GByte* pabyDstData = ((GByte*)pData) + iY * nLineSpace;
+            if( nBufXSize == nXSize )
             {
-                GDALCopyWords( ppData[iSrcY], eDataType, nDTSize,
-                                ((GByte*)pData) + iY * nLineSpace,
-                                eBufType, nPixelSpace,
-                                nReqXSize);
+                GDALCopyWords( pabySrcData,
+                                eDataType, nSrcPixelSize,
+                                pabyDstData,
+                                eBufType, static_cast<int>(nPixelSpace), nBufXSize);
             }
             else
             {
-                GByte* pabySrcData = ((GByte*)ppData[iSrcY]) +
-                            ((nContigBands > 1) ? (nBand-1) : 0) * nDTSize;
-                GByte* pabyDstData = ((GByte*)pData) + iY * nLineSpace;
-                if( nBufXSize == nXSize && nDTSize == 1 && eBufType == GDT_Byte )
+                if( eDataType == GDT_Byte && eBufType == GDT_Byte )
                 {
-                    for(int iX=0;iX<nBufXSize;iX++)
+                    double dfSrcX = 0.5 * dfSrcXInc;
+                    for(int iX=0;iX<nBufXSize;iX++, dfSrcX += dfSrcXInc)
                     {
-                        pabyDstData[iX * nPixelSpace] = pabySrcData[iX * ePixelSize];
+                        int iSrcX = (int)dfSrcX;
+                        pabyDstData[iX * nPixelSpace] = pabySrcData[iSrcX * nSrcPixelSize];
                     }
                 }
                 else
                 {
-                    for(int iX=0;iX<nBufXSize;iX++)
+                    double dfSrcX = 0.5 * dfSrcXInc;
+                    for(int iX=0;iX<nBufXSize;iX++, dfSrcX += dfSrcXInc)
                     {
-                        int iSrcX = (nBufXSize == nXSize) ? iX :
-                                        (int)((iX+0.5) * nXSize / nBufXSize);
-                        GDALCopyWords( pabySrcData + iSrcX * ePixelSize,
+                        int iSrcX = (int)dfSrcX;
+                        GDALCopyWords( pabySrcData + iSrcX * nSrcPixelSize,
                                     eDataType, 0,
                                     pabyDstData + iX * nPixelSpace,
                                     eBufType, 0, 1);
@@ -1294,11 +1499,10 @@ CPLVirtualMem* GTiffRasterBand::GetVirtualMemAuto( GDALRWFlag eRWFlag,
                                                   GIntBig *pnLineSpace,
                                                   char **papszOptions )
 {
-    CPLVirtualMem* psRet;
-
-    if( !CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "USE_DEFAULT_IMPLEMENTATION", "NO")) )
+    if( !CPLTestBool(CSLFetchNameValueDef(papszOptions, "USE_DEFAULT_IMPLEMENTATION", "NO")) )
     {
-        psRet = GetVirtualMemAutoInternal(eRWFlag, pnPixelSpace, pnLineSpace,
+        CPLVirtualMem *psRet
+            = GetVirtualMemAutoInternal(eRWFlag, pnPixelSpace, pnLineSpace,
                                         papszOptions);
         if( psRet != NULL )
         {
@@ -1313,6 +1517,39 @@ CPLVirtualMem* GTiffRasterBand::GetVirtualMemAuto( GDALRWFlag eRWFlag,
 }
 
 /************************************************************************/
+/*                           GetHistogram()                             */
+/************************************************************************/
+
+CPLErr  GTiffRasterBand::GetHistogram( double dfMin, double dfMax,
+                          int nBuckets, GUIntBig * panHistogram,
+                          int bIncludeOutOfRange, int bApproxOK,
+                          GDALProgressFunc pfnProgress, void *pProgressData )
+{
+    poGDS->LoadGeoreferencingAndPamIfNeeded();
+    return GDALPamRasterBand::GetHistogram(dfMin, dfMax, nBuckets, panHistogram,
+                                           bIncludeOutOfRange, bApproxOK,
+                                           pfnProgress, pProgressData);
+}
+
+/************************************************************************/
+/*                       GetDefaultHistogram()                          */
+/************************************************************************/
+
+CPLErr GTiffRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
+                                             int *pnBuckets,
+                                             GUIntBig ** ppanHistogram,
+                                             int bForce,
+                                             GDALProgressFunc pfnProgress,
+                                             void *pProgressData )
+{
+    poGDS->LoadGeoreferencingAndPamIfNeeded();
+    return GDALPamRasterBand::GetDefaultHistogram(pdfMin, pdfMax,
+                                                  pnBuckets, ppanHistogram,
+                                                  bForce,
+                                                  pfnProgress, pProgressData);
+}
+
+/************************************************************************/
 /*                     DropReferenceVirtualMem()                        */
 /************************************************************************/
 
@@ -1325,6 +1562,7 @@ void GTiffRasterBand::DropReferenceVirtualMem(void* pUserData)
 
     GTiffRasterBand** ppoSelf = (GTiffRasterBand**) pUserData;
     GTiffRasterBand* poSelf = *ppoSelf;
+
     if( poSelf != NULL )
     {
         if( --(poSelf->poGDS->nRefBaseMapping) == 0 )
@@ -1393,13 +1631,13 @@ CPLVirtualMem* GTiffRasterBand::GetVirtualMemAutoInternal( GDALRWFlag eRWFlag,
 
     if( !(CPLIsVirtualMemFileMapAvailable() &&
           VSIFGetNativeFileDescriptorL(fp) != NULL &&
+#if SIZEOF_VOIDP == 4
           nLength == (size_t)nLength &&
+#endif
           poGDS->nCompression == COMPRESSION_NONE &&
           (poGDS->nPhotometric == PHOTOMETRIC_MINISBLACK ||
            poGDS->nPhotometric == PHOTOMETRIC_RGB ||
            poGDS->nPhotometric == PHOTOMETRIC_PALETTE) &&
-          (poGDS->nBitsPerSample == 8 || poGDS->nBitsPerSample == 16 ||
-           poGDS->nBitsPerSample == 32 || poGDS->nBitsPerSample == 64) &&
           poGDS->nBitsPerSample == GDALGetDataTypeSize(eDataType) &&
           !TIFFIsTiled( poGDS->hTIFF ) && !TIFFIsByteSwapped(poGDS->hTIFF)) )
     {
@@ -1449,16 +1687,17 @@ CPLVirtualMem* GTiffRasterBand::GetVirtualMemAutoInternal( GDALRWFlag eRWFlag,
             {
                 return NULL;
             }
-            VSIFSeekL(fp, 0, SEEK_END);
+            if( VSIFSeekL(fp, 0, SEEK_END) != 0 )
+                return NULL;
             vsi_l_offset nBaseOffset = VSIFTellL(fp);
 
             /* Just write one tile with libtiff to put it in appropriate state */
-            GByte* pabyData = (GByte*)VSICalloc(1, nBlockSize);
+            GByte* pabyData = (GByte*)VSI_CALLOC_VERBOSE(1, nBlockSize);
             if( pabyData == NULL )
             {
                 return NULL;
             }
-            int ret = TIFFWriteEncodedStrip(poGDS->hTIFF, 0, pabyData, nBlockSize);
+            int ret = static_cast<int>(TIFFWriteEncodedStrip(poGDS->hTIFF, 0, pabyData, nBlockSize));
             VSI_TIFFFlushBufferedWrite( TIFFClientdata( poGDS->hTIFF ) );
             VSIFree(pabyData);
             if( ret != nBlockSize )
@@ -1470,7 +1709,8 @@ CPLVirtualMem* GTiffRasterBand::GetVirtualMemAutoInternal( GDALRWFlag eRWFlag,
 
             /* Now simulate the writing of other blocks */
             vsi_l_offset nDataSize = (vsi_l_offset)nBlockSize * nBlocks;
-            VSIFSeekL(fp, nBaseOffset + nDataSize - 1, SEEK_SET);
+            if( VSIFSeekL(fp, nBaseOffset + nDataSize - 1, SEEK_SET) != 0 )
+                return NULL;
             char ch = 0;
             if( VSIFWriteL(&ch, 1, 1, fp) != 1 )
             {
@@ -1491,7 +1731,7 @@ CPLVirtualMem* GTiffRasterBand::GetVirtualMemAutoInternal( GDALRWFlag eRWFlag,
     }
 
     GIntBig nBlockSpacing = 0;
-    int bCompatibleSpacing = TRUE;
+    bool bCompatibleSpacing = true;
     toff_t nPrevOffset = 0;
     for(i = 0; i < poGDS->nBlocksPerBand; i ++)
     {
@@ -1502,7 +1742,7 @@ CPLVirtualMem* GTiffRasterBand::GetVirtualMemAutoInternal( GDALRWFlag eRWFlag,
             nCurOffset = panTIFFOffsets[i];
         if( nCurOffset == 0 )
         {
-            bCompatibleSpacing = FALSE;
+            bCompatibleSpacing = false;
             break;
         }
         if( i > 0 )
@@ -1512,14 +1752,14 @@ CPLVirtualMem* GTiffRasterBand::GetVirtualMemAutoInternal( GDALRWFlag eRWFlag,
             {
                 if( nCurSpacing != (GIntBig)nBlockYSize * nLineSize )
                 {
-                    bCompatibleSpacing = FALSE;
+                    bCompatibleSpacing = false;
                     break;
                 }
                 nBlockSpacing = nCurSpacing;
             }
             else if( nBlockSpacing != nCurSpacing )
             {
-                bCompatibleSpacing = FALSE;
+                bCompatibleSpacing = false;
                 break;
             }
         }
@@ -1581,7 +1821,7 @@ CPLVirtualMem* GTiffRasterBand::GetVirtualMemAutoInternal( GDALRWFlag eRWFlag,
 CPLErr GTiffDataset::IRasterIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
                                void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType, 
+                               GDALDataType eBufType,
                                int nBandCount, int *panBandMap,
                                GSpacing nPixelSpace, GSpacing nLineSpace,
                                GSpacing nBandSpace,
@@ -1592,30 +1832,20 @@ CPLErr GTiffDataset::IRasterIO( GDALRWFlag eRWFlag,
     /* Try to pass the request to the most appropriate overview dataset */
     if( nBufXSize < nXSize && nBufYSize < nYSize )
     {
-        int nXOffMod = nXOff, nYOffMod = nYOff, nXSizeMod = nXSize, nYSizeMod = nYSize;
-        GDALRasterIOExtraArg sExtraArg;
-    
-        GDALCopyRasterIOExtraArg(&sExtraArg, psExtraArg);
-        
+        int bTried;
         nJPEGOverviewVisibilityFlag ++;
-        int iOvrLevel = GDALBandGetBestOverviewLevel2(papoBands[0],
-                                                     nXOffMod, nYOffMod,
-                                                     nXSizeMod, nYSizeMod,
-                                                     nBufXSize, nBufYSize,
-                                                     &sExtraArg);
+        eErr = TryOverviewRasterIO( eRWFlag,
+                                    nXOff, nYOff, nXSize, nYSize,
+                                    pData, nBufXSize, nBufYSize,
+                                    eBufType,
+                                    nBandCount, panBandMap,
+                                    nPixelSpace, nLineSpace,
+                                    nBandSpace,
+                                    psExtraArg,
+                                    &bTried );
         nJPEGOverviewVisibilityFlag --;
-
-        if( iOvrLevel >= 0 && papoBands[0]->GetOverview(iOvrLevel) != NULL &&
-            papoBands[0]->GetOverview(iOvrLevel)->GetDataset() != NULL )
-        {
-            nJPEGOverviewVisibilityFlag ++;
-            eErr = papoBands[0]->GetOverview(iOvrLevel)->GetDataset()->RasterIO(
-                eRWFlag, nXOffMod, nYOffMod, nXSizeMod, nYSizeMod,
-                pData, nBufXSize, nBufYSize, eBufType,
-                nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace, &sExtraArg);
-            nJPEGOverviewVisibilityFlag --;
+        if( bTried )
             return eErr;
-        }
     }
 
     if( eVirtualMemIOUsage != VIRTUAL_MEM_IO_NO )
@@ -1629,12 +1859,12 @@ CPLErr GTiffDataset::IRasterIO( GDALRWFlag eRWFlag,
     }
     if (bDirectIO)
     {
-        eErr = DirectIO(
+        int nErr = DirectIO(
                 eRWFlag, nXOff, nYOff, nXSize, nYSize,
                 pData, nBufXSize, nBufYSize, eBufType,
                 nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace, psExtraArg);
-        if (eErr == CE_None)
-            return eErr;
+        if (nErr >= 0)
+            return (CPLErr)nErr;
     }
 
     nJPEGOverviewVisibilityFlag ++;
@@ -1647,27 +1877,83 @@ CPLErr GTiffDataset::IRasterIO( GDALRWFlag eRWFlag,
 }
 
 /************************************************************************/
-/*                         VirtualMemIO()                               */
+/*                        FetchBufferVirtualMemIO                       */
 /************************************************************************/
 
-//#define DEBUG_REACHED_VIRTUAL_MEM_IO
-#ifdef DEBUG_REACHED_VIRTUAL_MEM_IO
-static int anReachedVirtualMemIO[32] = { 0 };
-#define REACHED(x)  anReachedVirtualMemIO[x] = 1
-#else
-#define REACHED(x)
-#endif
+class FetchBufferVirtualMemIO CPL_FINAL
+{
+    const GByte* pabySrcData;
+    size_t       nMappingSize;
+    GByte       *pTempBuffer;
+
+public:
+            FetchBufferVirtualMemIO(const GByte* pabySrcDataIn,
+                                    size_t nMappingSizeIn,
+                                    GByte* pTempBufferIn) :
+                    pabySrcData(pabySrcDataIn),
+                    nMappingSize(nMappingSizeIn),
+                    pTempBuffer(pTempBufferIn) {}
+
+    const GByte* FetchBytes(vsi_l_offset nOffset,
+                            int nPixels, int nDTSize,
+                            bool bIsByteSwapped, bool bIsComplex,
+                            int nBlockId)
+    {
+        if( nOffset + nPixels * nDTSize > nMappingSize )
+        {
+            CPLError(CE_Failure, CPLE_FileIO,
+                    "Missing data for block %d", nBlockId);
+            return NULL;
+        }
+        if( !bIsByteSwapped )
+            return pabySrcData + nOffset;
+        memcpy(pTempBuffer, pabySrcData + nOffset, nPixels * nDTSize);
+        if( bIsComplex )
+            GDALSwapWords( pTempBuffer, nDTSize / 2, 2 * nPixels, nDTSize / 2);
+        else
+            GDALSwapWords( pTempBuffer, nDTSize, nPixels, nDTSize);
+        return pTempBuffer;
+    }
+
+    bool  FetchBytes(GByte* pabyDstBuffer,
+                     vsi_l_offset nOffset,
+                     int nPixels, int nDTSize,
+                     bool bIsByteSwapped, bool bIsComplex,
+                     int nBlockId)
+    {
+        if( nOffset + nPixels * nDTSize > nMappingSize )
+        {
+            CPLError(CE_Failure, CPLE_FileIO,
+                    "Missing data for block %d", nBlockId);
+            return false;
+        }
+        memcpy(pabyDstBuffer, pabySrcData + nOffset, nPixels * nDTSize);
+        if( bIsByteSwapped )
+        {
+            if( bIsComplex )
+                GDALSwapWords( pabyDstBuffer, nDTSize / 2, 2 * nPixels, nDTSize / 2);
+            else
+                GDALSwapWords( pabyDstBuffer, nDTSize, nPixels, nDTSize);
+        }
+        return true;
+    }
+
+    static const EMULATED_BOOL bMinimizeIO = false;
+};
+
+/************************************************************************/
+/*                         VirtualMemIO()                               */
+/************************************************************************/
 
 int GTiffDataset::VirtualMemIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
                                void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType, 
+                               GDALDataType eBufType,
                                int nBandCount, int *panBandMap,
                                GSpacing nPixelSpace, GSpacing nLineSpace,
                                GSpacing nBandSpace,
                                GDALRasterIOExtraArg* psExtraArg )
 {
-    GDALDataType eDataType = GetRasterBand(1)->GetRasterDataType();
     if( eAccess == GA_Update || eRWFlag == GF_Write || bStreamingIn )
         return -1;
 
@@ -1682,14 +1968,13 @@ int GTiffDataset::VirtualMemIO( GDALRWFlag eRWFlag,
     if( !SetDirectory() )
         return CE_Failure;
 
+    const GDALDataType eDataType = GetRasterBand(1)->GetRasterDataType();
+    const int nDTSizeBits = GDALGetDataTypeSize(eDataType);
     if( !(nCompression == COMPRESSION_NONE &&
         (nPhotometric == PHOTOMETRIC_MINISBLACK ||
         nPhotometric == PHOTOMETRIC_RGB ||
         nPhotometric == PHOTOMETRIC_PALETTE) &&
-        (nBitsPerSample == 8 || (nBitsPerSample == 16) ||
-        nBitsPerSample == 32 || nBitsPerSample == 64) &&
-        nBitsPerSample == GDALGetDataTypeSize(eDataType) &&
-        !TIFFIsByteSwapped(hTIFF) ) )
+        nBitsPerSample == nDTSizeBits) )
     {
         eVirtualMemIOUsage = VIRTUAL_MEM_IO_NO;
         return -1;
@@ -1697,7 +1982,7 @@ int GTiffDataset::VirtualMemIO( GDALRWFlag eRWFlag,
 
     size_t nMappingSize = 0;
     GByte* pabySrcData = NULL;
-    if( strncmp(GetDescription(), "/vsimem/", strlen("/vsimem/")) == 0 )
+    if( STARTS_WITH(GetDescription(), "/vsimem/") )
     {
         vsi_l_offset nDataLength = 0;
         pabySrcData = VSIGetMemFileBuffer(GetDescription(), &nDataLength, FALSE);
@@ -1714,7 +1999,11 @@ int GTiffDataset::VirtualMemIO( GDALRWFlag eRWFlag,
             eVirtualMemIOUsage = VIRTUAL_MEM_IO_NO;
             return -1;
         }
-        VSIFSeekL(fp, 0, SEEK_END);
+        if( VSIFSeekL(fp, 0, SEEK_END) != 0 )
+        {
+            eVirtualMemIOUsage = VIRTUAL_MEM_IO_NO;
+            return -1;
+        }
         vsi_l_offset nLength = VSIFTellL(fp);
         if( (size_t)nLength != nLength )
         {
@@ -1741,437 +2030,1160 @@ int GTiffDataset::VirtualMemIO( GDALRWFlag eRWFlag,
         eVirtualMemIOUsage = VIRTUAL_MEM_IO_YES;
     }
 
-    /* Get strip offsets */
-    toff_t *panOffsets = NULL;
-    if ( !TIFFGetField( hTIFF, (TIFFIsTiled( hTIFF )) ? TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS, &panOffsets ) ||
-         panOffsets == NULL )
+    if( psVirtualMemIOMapping )
     {
-        eVirtualMemIOUsage = VIRTUAL_MEM_IO_NO;
-        return CE_Failure;
+#ifdef DEBUG
+        CPLDebug("GTiff", "Using VirtualMemIO");
+#endif
+        nMappingSize = CPLVirtualMemGetSize(psVirtualMemIOMapping);
+        pabySrcData = (GByte*)CPLVirtualMemGetAddr(psVirtualMemIOMapping);
     }
 
-    int nDTSize = GDALGetDataTypeSize(eDataType) / 8;
-    int nBufDTSize = GDALGetDataTypeSize(eBufType) / 8;
-
-    int iBand;
-    int bUseContigImplementation =
-        ( nPlanarConfig == PLANARCONFIG_CONTIG ) && (nBandCount > 1) && (nBandSpace == nBufDTSize);
-    for(iBand = 0; iBand < nBandCount; iBand ++ )
+    if( TIFFIsByteSwapped(hTIFF) && m_pTempBufferForCommonDirectIO == NULL )
     {
-        int nBand = panBandMap[iBand];
-        if( nBand != iBand + 1 )
+        const int nDTSize = nDTSizeBits / 8;
+        m_nTempBufferForCommonDirectIOSize =
+            (size_t)(nBlockXSize * nDTSize * ((nPlanarConfig == PLANARCONFIG_CONTIG) ? nBands : 1));
+        if( TIFFIsTiled(hTIFF) )
+            m_nTempBufferForCommonDirectIOSize *= nBlockYSize;
+
+        m_pTempBufferForCommonDirectIO = (GByte*)VSI_MALLOC_VERBOSE(m_nTempBufferForCommonDirectIOSize);
+        if( m_pTempBufferForCommonDirectIO == NULL )
+            return CE_Failure;
+    }
+    FetchBufferVirtualMemIO oFetcher(pabySrcData, nMappingSize, m_pTempBufferForCommonDirectIO);
+
+    return CommonDirectIO( oFetcher,
+                           nXOff, nYOff, nXSize, nYSize,
+                           pData, nBufXSize, nBufYSize,
+                           eBufType,
+                           nBandCount, panBandMap,
+                           nPixelSpace, nLineSpace,
+                           nBandSpace );
+}
+
+/************************************************************************/
+/*                   CopyContigByteMultiBand()                          */
+/************************************************************************/
+
+static inline void CopyContigByteMultiBand(
+                            const GByte* CPL_RESTRICT pabySrc, int nSrcStride,
+                            GByte* CPL_RESTRICT pabyDest, int nDestStride,
+                            int nIters, int nBandCount)
+{
+    if( nBandCount == 3 )
+    {
+        if( nSrcStride == 3 && nDestStride == 4 )
+        {
+            while( nIters >= 8 )
+            {
+                pabyDest[4*0+0] = pabySrc[3*0+0];
+                pabyDest[4*0+1] = pabySrc[3*0+1];
+                pabyDest[4*0+2] = pabySrc[3*0+2];
+                pabyDest[4*1+0] = pabySrc[3*1+0];
+                pabyDest[4*1+1] = pabySrc[3*1+1];
+                pabyDest[4*1+2] = pabySrc[3*1+2];
+                pabyDest[4*2+0] = pabySrc[3*2+0];
+                pabyDest[4*2+1] = pabySrc[3*2+1];
+                pabyDest[4*2+2] = pabySrc[3*2+2];
+                pabyDest[4*3+0] = pabySrc[3*3+0];
+                pabyDest[4*3+1] = pabySrc[3*3+1];
+                pabyDest[4*3+2] = pabySrc[3*3+2];
+                pabyDest[4*4+0] = pabySrc[3*4+0];
+                pabyDest[4*4+1] = pabySrc[3*4+1];
+                pabyDest[4*4+2] = pabySrc[3*4+2];
+                pabyDest[4*5+0] = pabySrc[3*5+0];
+                pabyDest[4*5+1] = pabySrc[3*5+1];
+                pabyDest[4*5+2] = pabySrc[3*5+2];
+                pabyDest[4*6+0] = pabySrc[3*6+0];
+                pabyDest[4*6+1] = pabySrc[3*6+1];
+                pabyDest[4*6+2] = pabySrc[3*6+2];
+                pabyDest[4*7+0] = pabySrc[3*7+0];
+                pabyDest[4*7+1] = pabySrc[3*7+1];
+                pabyDest[4*7+2] = pabySrc[3*7+2];
+                pabySrc += 3 * 8;
+                pabyDest += 4 * 8;
+                nIters -= 8;
+            }
+            while( nIters-- > 0 )
+            {
+                pabyDest[0] = pabySrc[0];
+                pabyDest[1] = pabySrc[1];
+                pabyDest[2] = pabySrc[2];
+                pabySrc += 3;
+                pabyDest += 4;
+            }
+        }
+        else
         {
-            bUseContigImplementation = FALSE;
-            break;
+            while( nIters-- > 0 )
+            {
+                pabyDest[0] = pabySrc[0];
+                pabyDest[1] = pabySrc[1];
+                pabyDest[2] = pabySrc[2];
+                pabySrc += nSrcStride;
+                pabyDest += nDestStride;
+            }
         }
     }
-
-    if( psVirtualMemIOMapping )
+    else
     {
-        nMappingSize = CPLVirtualMemGetSize(psVirtualMemIOMapping);
-        pabySrcData = (GByte*)CPLVirtualMemGetAddr(psVirtualMemIOMapping);
+        while( nIters-- > 0 )
+        {
+            for(int iBand=0;iBand<nBandCount;iBand++)
+                pabyDest[iBand] = pabySrc[iBand];
+            pabySrc += nSrcStride;
+            pabyDest += nDestStride;
+        }
     }
-    const int nBandsPerBlock = ( nPlanarConfig == PLANARCONFIG_SEPARATE ) ? 1 : nBands;
-    const int nBandsPerBlockDTSize = nBandsPerBlock * nDTSize;
-    const int nBlocksPerRow = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
-    const int bByteOnly = (eDataType == eBufType && nDTSize == 1 );
-    const int bByteNoXResampling = ( bByteOnly && nXSize == nBufXSize );
-    const int nBlockSize = nBlockXSize * nBlockYSize * nBandsPerBlockDTSize;
+}
 
-    int bNoDataSet;
-    double dfNoData = GetRasterBand(1)->GetNoDataValue( &bNoDataSet );
-    GByte abyNoData = 0;
-    if( !bNoDataSet )
-        dfNoData = 0;
-    else if( dfNoData >= 0 && dfNoData <= 255 )
-        abyNoData = (GByte) (dfNoData + 0.5);
+/************************************************************************/
+/*                         CommonDirectIO()                             */
+/************************************************************************/
 
-    if( bUseContigImplementation )
-    {
-        if( TIFFIsTiled( hTIFF ) )
-        {
+//#define DEBUG_REACHED_VIRTUAL_MEM_IO
+#ifdef DEBUG_REACHED_VIRTUAL_MEM_IO
+static int anReachedVirtualMemIO[52] = { 0 };
+#define REACHED(x)  anReachedVirtualMemIO[x] = 1
+#else
+#define REACHED(x)
+#endif
+
+template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
+                               FetchBuffer& oFetcher,
+                               int nXOff, int nYOff, int nXSize, int nYSize,
+                               void * pData, int nBufXSize, int nBufYSize,
+                               GDALDataType eBufType,
+                               int nBandCount, int *panBandMap,
+                               GSpacing nPixelSpace, GSpacing nLineSpace,
+                               GSpacing nBandSpace )
+{
+    const GDALDataType eDataType = GetRasterBand(1)->GetRasterDataType();
+    const int nDTSize = GDALGetDataTypeSize(eDataType) / 8;
+    const bool bIsComplex = CPL_TO_BOOL(GDALDataTypeIsComplex(eDataType));
+    const int nBufDTSize = GDALGetDataTypeSize(eBufType) / 8;
+
+    /* Get strip offsets */
+    toff_t *panOffsets = NULL;
+    if ( !TIFFGetField( hTIFF, (TIFFIsTiled( hTIFF )) ? TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS, &panOffsets ) ||
+         panOffsets == NULL )
+    {
+        return CE_Failure;
+    }
+
+    bool bUseContigImplementation =
+        ( nPlanarConfig == PLANARCONFIG_CONTIG ) && (nBandCount > 1) && (nBandSpace == nBufDTSize);
+    if( bUseContigImplementation )
+    {
+        for(int iBand = 0; iBand < nBandCount; iBand ++ )
+        {
+            int nBand = panBandMap[iBand];
+            if( nBand != iBand + 1 )
+            {
+                bUseContigImplementation = false;
+                break;
+            }
+        }
+    }
+
+    const int nBandsPerBlock = ( nPlanarConfig == PLANARCONFIG_SEPARATE ) ? 1 : nBands;
+    const int nBandsPerBlockDTSize = nBandsPerBlock * nDTSize;
+    const int nBlocksPerRow = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
+    const bool bNoTypeChange = (eDataType == eBufType);
+    const bool bNoXResampling = (nXSize == nBufXSize );
+    const bool bNoXResamplingNoTypeChange = (bNoTypeChange && bNoXResampling);
+    const bool bByteOnly = (bNoTypeChange && nDTSize == 1 );
+    const bool bByteNoXResampling = ( bByteOnly && bNoXResamplingNoTypeChange );
+    const bool bIsByteSwapped = CPL_TO_BOOL(TIFFIsByteSwapped(hTIFF));
+    const double dfSrcXInc = nXSize / (double) nBufXSize;
+    const double dfSrcYInc = nYSize / (double) nBufYSize;
+
+    int bNoDataSetIn;
+    double dfNoData = GetRasterBand(1)->GetNoDataValue( &bNoDataSetIn );
+    GByte abyNoData = 0;
+    if( !bNoDataSetIn )
+        dfNoData = 0;
+    else if( dfNoData >= 0 && dfNoData <= 255 )
+        abyNoData = (GByte) (dfNoData + 0.5);
+
+    if( FetchBuffer::bMinimizeIO &&
+             TIFFIsTiled( hTIFF ) && bNoXResampling && (nYSize == nBufYSize ) &&
+             nPlanarConfig == PLANARCONFIG_CONTIG && nBandCount > 1 )
+    {
+        GByte* pabyData = (GByte*)pData;
+        for(int y=0;y<nBufYSize;)
+        {
+            const int nSrcLine = nYOff + y;
+            const int nBlockYOff = nSrcLine / nBlockYSize;
+            const int nYOffsetInBlock = nSrcLine % nBlockYSize;
+            const int nUsedBlockHeight = MIN(nBufYSize - y, (int)nBlockYSize - nYOffsetInBlock);
+
+            int nBlockXOff = nXOff / nBlockXSize;
+            int nXOffsetInBlock = nXOff % nBlockXSize;
+            int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
+
+            int x = 0;
+            while( x < nBufXSize )
+            {
+                const toff_t nCurOffset = panOffsets[nBlockId];
+                const int nUsedBlockWidth = MIN((int)nBlockXSize - nXOffsetInBlock, nBufXSize - x);
+
+                if( nCurOffset == 0 )
+                {
+                    REACHED(30);
+                    for( int k=0;k<nUsedBlockHeight;k++)
+                    {
+                        GByte* pabyLocalData = pabyData + (y+k) * nLineSpace + x * nPixelSpace;
+                        for(int iBand=0;iBand<nBandCount;iBand++)
+                        {
+                            GByte* pabyLocalDataBand = pabyLocalData + iBand * nBandSpace;
+
+                            GDALCopyWords(&dfNoData, GDT_Float64, 0,
+                                    pabyLocalDataBand, eBufType, static_cast<int>(nPixelSpace),
+                                    nUsedBlockWidth);
+                        }
+                    }
+                }
+                else
+                {
+                    const int nByteOffsetInBlock =
+                        nYOffsetInBlock * nBlockXSize * nBandsPerBlockDTSize;
+                    const GByte* pabyLocalSrcDataK0 = oFetcher.FetchBytes(
+                            nCurOffset + nByteOffsetInBlock,
+                            (int)nBlockXSize * nUsedBlockHeight * nBandsPerBlock,
+                            nDTSize, bIsByteSwapped, bIsComplex, nBlockId);
+                    if( pabyLocalSrcDataK0 == NULL )
+                        return CE_Failure;
+
+                    for( int k=0;k<nUsedBlockHeight;k++)
+                    {
+                        GByte* pabyLocalData = pabyData + (y+k) * nLineSpace + x * nPixelSpace;
+                        const GByte* pabyLocalSrcData =
+                            pabyLocalSrcDataK0 + (k * nBlockXSize + nXOffsetInBlock) * nBandsPerBlockDTSize;
+
+                        if( bUseContigImplementation && nBands == nBandCount &&
+                            nPixelSpace == nBandsPerBlockDTSize )
+                        {
+                            REACHED(31);
+                            GDALCopyWords(pabyLocalSrcData,
+                                            eDataType, nDTSize,
+                                            pabyLocalData,
+                                            eBufType, nBufDTSize,
+                                            nUsedBlockWidth * nBands);
+                        }
+                        else
+                        {
+                            REACHED(32);
+                            for(int iBand=0;iBand<nBandCount;iBand++)
+                            {
+                                GByte* pabyLocalDataBand = pabyLocalData + iBand * nBandSpace;
+                                const GByte* pabyLocalSrcDataBand = pabyLocalSrcData + (panBandMap[iBand]-1) * nDTSize;
+
+                                GDALCopyWords(pabyLocalSrcDataBand,
+                                                eDataType, nBandsPerBlockDTSize,
+                                                pabyLocalDataBand,
+                                                eBufType, static_cast<int>(nPixelSpace),
+                                                nUsedBlockWidth);
+                            }
+                        }
+                    }
+                }
+
+                nXOffsetInBlock = 0;
+                nBlockXOff ++;
+                nBlockId ++;
+                x += nUsedBlockWidth;
+            }
+
+            y += nUsedBlockHeight;
+        }
+    }
+    else if( FetchBuffer::bMinimizeIO &&
+             TIFFIsTiled( hTIFF ) && bNoXResampling && (nYSize == nBufYSize ) /*&&
+             (nPlanarConfig == PLANARCONFIG_SEPARATE || nBandCount == 1)*/ )
+    {
+        for(int iBand=0;iBand<nBandCount;iBand++)
+        {
+            GByte* pabyData = (GByte*)pData + iBand * nBandSpace;
+            const int nBand = panBandMap[iBand];
+            for(int y=0;y<nBufYSize;)
+            {
+                const int nSrcLine = nYOff + y;
+                const int nBlockYOff = nSrcLine / nBlockYSize;
+                const int nYOffsetInBlock = nSrcLine % nBlockYSize;
+                const int nUsedBlockHeight = MIN(nBufYSize - y, (int)nBlockYSize - nYOffsetInBlock);
+
+                int nBlockXOff = nXOff / nBlockXSize;
+                int nXOffsetInBlock = nXOff % nBlockXSize;
+                int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
+                if ( nPlanarConfig == PLANARCONFIG_SEPARATE )
+                {
+                    REACHED(33);
+                    nBlockId += nBlocksPerBand * (nBand - 1);
+                }
+                else
+                {
+                    REACHED(34);
+                }
+
+                int x = 0;
+                while( x < nBufXSize )
+                {
+                    const toff_t nCurOffset = panOffsets[nBlockId];
+                    const int nUsedBlockWidth = MIN((int)nBlockXSize - nXOffsetInBlock, nBufXSize - x);
+
+                    if( nCurOffset == 0 )
+                    {
+                        REACHED(35);
+                        for( int k=0;k<nUsedBlockHeight;k++)
+                        {
+                            GByte* pabyLocalData = pabyData + (y+k) * nLineSpace + x * nPixelSpace;
+
+                            GDALCopyWords(&dfNoData, GDT_Float64, 0,
+                                    pabyLocalData, eBufType, static_cast<int>(nPixelSpace),
+                                    nUsedBlockWidth);
+                        }
+                    }
+                    else
+                    {
+                        const int nByteOffsetInBlock =
+                            nYOffsetInBlock * nBlockXSize * nBandsPerBlockDTSize;
+                        const GByte* pabyLocalSrcDataK0 = oFetcher.FetchBytes(
+                                nCurOffset + nByteOffsetInBlock,
+                                (int)nBlockXSize * nUsedBlockHeight * nBandsPerBlock,
+                                nDTSize, bIsByteSwapped, bIsComplex, nBlockId);
+                        if( pabyLocalSrcDataK0 == NULL )
+                            return CE_Failure;
+
+                        if ( nPlanarConfig == PLANARCONFIG_CONTIG )
+                        {
+                            REACHED(36);
+                            pabyLocalSrcDataK0 += (nBand - 1) * nDTSize;
+                        }
+                        else
+                        {
+                            REACHED(37);
+                        }
+
+                        for( int k=0;k<nUsedBlockHeight;k++)
+                        {
+                            GByte* pabyLocalData = pabyData + (y+k) * nLineSpace + x * nPixelSpace;
+                            const GByte* pabyLocalSrcData =
+                                pabyLocalSrcDataK0 + (k * nBlockXSize + nXOffsetInBlock) * nBandsPerBlockDTSize;
+
+                            GDALCopyWords(pabyLocalSrcData,
+                                            eDataType, nBandsPerBlockDTSize,
+                                            pabyLocalData,
+                                            eBufType, static_cast<int>(nPixelSpace),
+                                            nUsedBlockWidth);
+                        }
+                    }
+
+                    nXOffsetInBlock = 0;
+                    nBlockXOff ++;
+                    nBlockId ++;
+                    x += nUsedBlockWidth;
+                }
+
+                y += nUsedBlockHeight;
+            }
+        }
+    }
+    else if( FetchBuffer::bMinimizeIO &&
+             TIFFIsTiled( hTIFF ) &&
+             nPlanarConfig == PLANARCONFIG_CONTIG && nBandCount > 1 )
+    {
+        GByte* pabyData = (GByte*)pData;
+        int anSrcYOffset[256];
+        for(int y=0;y<nBufYSize;)
+        {
+            const double dfYOffStart = nYOff + (y + 0.5) * dfSrcYInc;
+            const int nSrcLine = (int)dfYOffStart;
+            const int nYOffsetInBlock = nSrcLine % nBlockYSize;
+            const int nBlockYOff = nSrcLine / nBlockYSize;
+            const int nBaseByteOffsetInBlock = nYOffsetInBlock * nBlockXSize * nBandsPerBlockDTSize;
+            int ychunk = 1;
+            int nLastSrcLineK = nSrcLine;
+            anSrcYOffset[0] = 0;
+            for(int k=1;k<nBufYSize-y;k++)
+            {
+                int nSrcLineK = nYOff + (int)((y + k + 0.5) * dfSrcYInc);
+                const int nBlockYOffK = nSrcLineK / nBlockYSize;
+                if( k < 256)
+                    anSrcYOffset[k] = ((nSrcLineK % nBlockYSize) - nYOffsetInBlock) * nBlockXSize * nBandsPerBlockDTSize;
+                if( nBlockYOffK != nBlockYOff )
+                {
+                    break;
+                }
+                ychunk ++;
+                nLastSrcLineK = nSrcLineK;
+            }
+            const int nUsedBlockHeight = nLastSrcLineK - nSrcLine + 1;
+            //CPLAssert(nUsedBlockHeight <= nBlockYSize);
+
+            double dfSrcX = nXOff + 0.5 * dfSrcXInc;
+            int nCurBlockXOff = 0;
+            int nNextBlockXOff = 0;
+            toff_t nCurOffset = 0;
+            const GByte* pabyLocalSrcDataStartLine = NULL;
+            for(int x=0;x<nBufXSize;x++, dfSrcX += dfSrcXInc)
+            {
+                int nSrcPixel = (int)dfSrcX;
+                if( nSrcPixel >= nNextBlockXOff )
+                {
+                    const int nBlockXOff = nSrcPixel / nBlockXSize;
+                    nCurBlockXOff = nBlockXOff * nBlockXSize;
+                    nNextBlockXOff = nCurBlockXOff + nBlockXSize;
+                    int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
+                    nCurOffset = panOffsets[nBlockId];
+                    if( nCurOffset != 0 )
+                    {
+                        pabyLocalSrcDataStartLine = oFetcher.FetchBytes(
+                                nCurOffset + nBaseByteOffsetInBlock,
+                                (int)nBlockXSize * nBandsPerBlock * nUsedBlockHeight, nDTSize,
+                                bIsByteSwapped, bIsComplex, nBlockId);
+                        if( pabyLocalSrcDataStartLine == NULL )
+                            return CE_Failure;
+                    }
+                }
+
+                if( nCurOffset == 0 )
+                {
+                    REACHED(38);
+
+                    for( int k = 0; k < ychunk; k ++ )
+                    {
+                        GByte* const pabyLocalData = pabyData + (y+k) * nLineSpace + x * nPixelSpace;
+                        for(int iBand=0;iBand<nBandCount;iBand++)
+                        {
+                            GDALCopyWords(&dfNoData, GDT_Float64, 0,
+                                          pabyLocalData + nBandSpace * iBand, eBufType, 0,
+                                          1);
+                        }
+                    }
+                }
+
+                else
+                {
+                    const int nXOffsetInBlock = nSrcPixel - nCurBlockXOff;
+                    double dfYOff = dfYOffStart;
+                    const GByte* const pabyLocalSrcDataK0 =
+                        pabyLocalSrcDataStartLine + nXOffsetInBlock * nBandsPerBlockDTSize;
+                    GByte* pabyLocalData = pabyData + y * nLineSpace + x * nPixelSpace;
+                    for( int k = 0; k < ychunk; k ++, pabyLocalData += nLineSpace )
+                    {
+                        const GByte* pabyLocalSrcData;
+                        if( ychunk <= 256 )
+                        {
+                            REACHED(39);
+                            pabyLocalSrcData = pabyLocalSrcDataK0 + anSrcYOffset[k];
+                        }
+                        else
+                        {
+                            REACHED(40);
+                            const int nYOffsetInBlockK = ((int)dfYOff) % nBlockYSize;
+                            //CPLAssert(nYOffsetInBlockK - nYOffsetInBlock <= nUsedBlockHeight);
+                            pabyLocalSrcData = pabyLocalSrcDataK0 +
+                                (nYOffsetInBlockK - nYOffsetInBlock) * nBlockXSize * nBandsPerBlockDTSize;
+                            dfYOff += dfSrcYInc;
+                        }
+
+                        if( bByteOnly )
+                        {
+                            REACHED(41);
+                            for(int iBand=0;iBand<nBandCount;iBand++)
+                            {
+                                GByte* pabyLocalDataBand = pabyLocalData + iBand * nBandSpace;
+                                const GByte* pabyLocalSrcDataBand = pabyLocalSrcData + (panBandMap[iBand]-1) /* * nDTSize*/;
+                                *pabyLocalDataBand = *pabyLocalSrcDataBand;
+                            }
+                        }
+                        else
+                        {
+                            REACHED(42);
+                            for(int iBand=0;iBand<nBandCount;iBand++)
+                            {
+                                GByte* pabyLocalDataBand = pabyLocalData + iBand * nBandSpace;
+                                const GByte* pabyLocalSrcDataBand = pabyLocalSrcData + (panBandMap[iBand]-1) * nDTSize;
+
+                                GDALCopyWords(pabyLocalSrcDataBand,
+                                                eDataType, 0,
+                                                pabyLocalDataBand,
+                                                eBufType, 0,
+                                                1);
+                            }
+                        }
+                    }
+                }
+            }
+
+            y += ychunk;
+        }
+    }
+    else if( FetchBuffer::bMinimizeIO &&
+             TIFFIsTiled( hTIFF ) /* &&
+             (nPlanarConfig == PLANARCONFIG_SEPARATE || nBandCount == 1) */ )
+    {
+        for(int iBand=0;iBand<nBandCount;iBand++)
+        {
+            GByte* pabyData = (GByte*)pData + iBand * nBandSpace;
+            const int nBand = panBandMap[iBand];
+            int anSrcYOffset[256];
+            for(int y=0;y<nBufYSize;)
+            {
+                const double dfYOffStart = nYOff + (y + 0.5) * dfSrcYInc;
+                const int nSrcLine = (int)dfYOffStart;
+                const int nYOffsetInBlock = nSrcLine % nBlockYSize;
+                const int nBlockYOff = nSrcLine / nBlockYSize;
+                const int nBaseByteOffsetInBlock = nYOffsetInBlock * nBlockXSize * nBandsPerBlockDTSize;
+                int ychunk = 1;
+                int nLastSrcLineK = nSrcLine;
+                anSrcYOffset[0] = 0;
+                for(int k=1;k<nBufYSize-y;k++)
+                {
+                    int nSrcLineK = nYOff + (int)((y + k + 0.5) * dfSrcYInc);
+                    const int nBlockYOffK = nSrcLineK / nBlockYSize;
+                    if( k < 256)
+                        anSrcYOffset[k] = ((nSrcLineK % nBlockYSize) - nYOffsetInBlock) * nBlockXSize * nBandsPerBlockDTSize;
+                    if( nBlockYOffK != nBlockYOff )
+                    {
+                        break;
+                    }
+                    ychunk ++;
+                    nLastSrcLineK = nSrcLineK;
+                }
+                const int nUsedBlockHeight = nLastSrcLineK - nSrcLine + 1;
+                //CPLAssert(nUsedBlockHeight <= nBlockYSize);
+
+                double dfSrcX = nXOff + 0.5 * dfSrcXInc;
+                int nCurBlockXOff = 0;
+                int nNextBlockXOff = 0;
+                toff_t nCurOffset = 0;
+                const GByte* pabyLocalSrcDataStartLine = NULL;
+                for(int x=0;x<nBufXSize;x++, dfSrcX += dfSrcXInc)
+                {
+                    int nSrcPixel = (int)dfSrcX;
+                    if( nSrcPixel >= nNextBlockXOff )
+                    {
+                        const int nBlockXOff = nSrcPixel / nBlockXSize;
+                        nCurBlockXOff = nBlockXOff * nBlockXSize;
+                        nNextBlockXOff = nCurBlockXOff + nBlockXSize;
+                        int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
+                        if ( nPlanarConfig == PLANARCONFIG_SEPARATE )
+                        {
+                            REACHED(43);
+                            nBlockId += nBlocksPerBand * (nBand - 1);
+                        }
+                        else
+                        {
+                            REACHED(44);
+                        }
+                        nCurOffset = panOffsets[nBlockId];
+                        if( nCurOffset != 0 )
+                        {
+                            pabyLocalSrcDataStartLine = oFetcher.FetchBytes(
+                                    nCurOffset + nBaseByteOffsetInBlock,
+                                    (int)nBlockXSize * nBandsPerBlock * nUsedBlockHeight, nDTSize,
+                                    bIsByteSwapped, bIsComplex, nBlockId);
+                            if( pabyLocalSrcDataStartLine == NULL )
+                                return CE_Failure;
+
+                            if ( nPlanarConfig == PLANARCONFIG_CONTIG )
+                            {
+                                REACHED(45);
+                                pabyLocalSrcDataStartLine += (nBand - 1) * nDTSize;
+                            }
+                            else
+                            {
+                                REACHED(46);
+                            }
+
+                        }
+                    }
+
+                    if( nCurOffset == 0 )
+                    {
+                        REACHED(47);
+
+                        for( int k = 0; k < ychunk; k ++ )
+                        {
+                            GByte* const pabyLocalData = pabyData + (y+k) * nLineSpace + x * nPixelSpace;
+
+                            GDALCopyWords(&dfNoData, GDT_Float64, 0,
+                                            pabyLocalData, eBufType, 0,
+                                            1);
+                        }
+                    }
+
+                    else
+                    {
+                        const int nXOffsetInBlock = nSrcPixel - nCurBlockXOff;
+                        double dfYOff = dfYOffStart;
+                        const GByte* const pabyLocalSrcDataK0 =
+                            pabyLocalSrcDataStartLine + nXOffsetInBlock * nBandsPerBlockDTSize;
+                        GByte* pabyLocalData = pabyData + y * nLineSpace + x * nPixelSpace;
+                        for( int k = 0; k < ychunk; k ++, pabyLocalData += nLineSpace )
+                        {
+                            const GByte* pabyLocalSrcData;
+                            if( ychunk <= 256 )
+                            {
+                                REACHED(48);
+                                pabyLocalSrcData = pabyLocalSrcDataK0 + anSrcYOffset[k];
+                            }
+                            else
+                            {
+                                REACHED(49);
+                                const int nYOffsetInBlockK = ((int)dfYOff) % nBlockYSize;
+                                //CPLAssert(nYOffsetInBlockK - nYOffsetInBlock <= nUsedBlockHeight);
+                                pabyLocalSrcData = pabyLocalSrcDataK0 +
+                                    (nYOffsetInBlockK - nYOffsetInBlock) * nBlockXSize * nBandsPerBlockDTSize;
+                                dfYOff += dfSrcYInc;
+                            }
+
+                            if( bByteOnly )
+                            {
+                                REACHED(50);
+
+                                *pabyLocalData = *pabyLocalSrcData;
+                            }
+                            else
+                            {
+                                REACHED(51);
+
+                                GDALCopyWords(pabyLocalSrcData,
+                                                eDataType, 0,
+                                                pabyLocalData,
+                                                eBufType, 0,
+                                                1);
+                            }
+                        }
+                    }
+                }
+
+                y += ychunk;
+            }
+        }
+    }
+    else if( bUseContigImplementation )
+    {
+        if( !FetchBuffer::bMinimizeIO && TIFFIsTiled( hTIFF ) )
+        {
             GByte* pabyData = (GByte*)pData;
             for(int y=0;y<nBufYSize;y++)
             {
-                int nSrcLine = nYOff + (int)((y + 0.5) * nYSize / nBufYSize);
-                int nBlockYOff = nSrcLine / nBlockYSize;
-                int nYOffsetInBlock = nSrcLine % nBlockYSize;
-                int nBaseByteOffsetInBlock = nYOffsetInBlock * nBlockXSize * nBandsPerBlockDTSize;
+                const int nSrcLine = nYOff + (int)((y + 0.5) * dfSrcYInc);
+                const int nBlockYOff = nSrcLine / nBlockYSize;
+                const int nYOffsetInBlock = nSrcLine % nBlockYSize;
+                const int nBaseByteOffsetInBlock = nYOffsetInBlock * nBlockXSize * nBandsPerBlockDTSize;
 
-                if( bByteNoXResampling )
+                if( bNoXResampling )
                 {
-                    GByte* pabyLocalSrcData = NULL;
                     GByte* pabyLocalData = pabyData + y * nLineSpace;
-                    int nLastPixelBlock = 0;
                     int nBlockXOff = nXOff / nBlockXSize;
                     int nXOffsetInBlock = nXOff % nBlockXSize;
                     int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
-                    int nByteOffsetInBlock = nBaseByteOffsetInBlock + nXOffsetInBlock * nBandsPerBlockDTSize;
 
-                    for(int x=0;x<nBufXSize;x++)
+                    int x = 0;
+                    while( x < nBufXSize )
                     {
-                        int nSrcPixel = nXOff + x;
-                        if( nSrcPixel >= nLastPixelBlock )
+                        const int nByteOffsetInBlock = nBaseByteOffsetInBlock +
+                                        nXOffsetInBlock * nBandsPerBlockDTSize;
+                        const toff_t nCurOffset = panOffsets[nBlockId];
+                        const int nUsedBlockWidth = MIN((int)nBlockXSize - nXOffsetInBlock, nBufXSize - x);
+
+                        int nIters = nUsedBlockWidth;
+                        if( nCurOffset == 0 )
                         {
-                            REACHED(0);
-                            nLastPixelBlock = (nBlockXOff + 1) * nBlockXSize;
-                            toff_t nCurOffset = panOffsets[nBlockId];
-                            if( nCurOffset )
+                            if( bByteNoXResampling )
                             {
-                                if( nCurOffset + nBlockSize > nMappingSize )
+                                REACHED(0);
+                                while( nIters-- > 0 )
                                 {
-                                    REACHED(24);
-                                    CPLError(CE_Failure, CPLE_FileIO,
-                                            "Missing data for block %d", nBlockId);
-                                    return CE_Failure;
+                                    for(int iBand=0;iBand<nBandCount;iBand++)
+                                        pabyLocalData[iBand] = abyNoData;
+                                    pabyLocalData += nPixelSpace;
                                 }
-                                pabyLocalSrcData = pabySrcData + nCurOffset + nByteOffsetInBlock;
                             }
                             else
-                                pabyLocalSrcData = NULL;
-                            nByteOffsetInBlock = nBaseByteOffsetInBlock;
-                            nBlockXOff ++;
-                            nBlockId ++; 
+                            {
+                                REACHED(1);
+                                while( nIters-- > 0 )
+                                {
+                                    GDALCopyWords(&dfNoData, GDT_Float64, 0,
+                                          pabyLocalData, eBufType, static_cast<int>(nBandSpace),
+                                          nBandCount);
+                                    pabyLocalData += nPixelSpace;
+                                }
+                            }
                         }
                         else
                         {
-                            REACHED(1);
+                            if( bNoTypeChange && nBands == nBandCount &&
+                                nPixelSpace == nBandsPerBlockDTSize )
+                            {
+                                REACHED(2);
+                                if( !oFetcher.FetchBytes(
+                                        pabyLocalData,
+                                        nCurOffset + nByteOffsetInBlock,
+                                        nIters * nBandsPerBlock, nDTSize,
+                                        bIsByteSwapped, bIsComplex, nBlockId) )
+                                {
+                                    return CE_Failure;
+                                }
+                                pabyLocalData += nIters * nBandsPerBlock * nDTSize;
+                            }
+                            else
+                            {
+                                const GByte* pabyLocalSrcData = oFetcher.FetchBytes(
+                                        nCurOffset + nByteOffsetInBlock,
+                                        nIters * nBandsPerBlock, nDTSize,
+                                        bIsByteSwapped, bIsComplex, nBlockId);
+                                if( pabyLocalSrcData == NULL )
+                                    return CE_Failure;
+                                if( bByteNoXResampling )
+                                {
+                                    REACHED(3);
+                                    CopyContigByteMultiBand(pabyLocalSrcData,
+                                                        nBandsPerBlockDTSize,
+                                                        pabyLocalData,
+                                                        static_cast<int>(nPixelSpace),
+                                                        nIters,
+                                                        nBandCount);
+                                    pabyLocalData += nIters * nPixelSpace;
+                                }
+                                else
+                                {
+                                    REACHED(4);
+                                    while( nIters-- > 0 )
+                                    {
+                                        GDALCopyWords(pabyLocalSrcData,
+                                                      eDataType, nDTSize,
+                                                      pabyLocalData,
+                                                      eBufType, static_cast<int>(nBandSpace),
+                                                      nBandCount);
+                                        pabyLocalSrcData += nBandsPerBlockDTSize;
+                                        pabyLocalData += nPixelSpace;
+                                    }
+                                }
+                            }
                         }
 
-                        if( pabyLocalSrcData == NULL )
-                        {
-                            REACHED(2);
-                            for(int iBand=0;iBand<nBandCount;iBand++)
-                                pabyLocalData[iBand] = abyNoData;
-                        }
-                        else
-                        {
-                            REACHED(3);
-                            for(int iBand=0;iBand<nBandCount;iBand++)
-                                pabyLocalData[iBand] = pabyLocalSrcData[iBand];
-                            pabyLocalSrcData += nBandsPerBlockDTSize;
-                        }
-                        pabyLocalData += nPixelSpace;
+                        nXOffsetInBlock = 0;
+                        nBlockXOff ++;
+                        nBlockId ++;
+                        x += nUsedBlockWidth;
                     }
                 }
-                else
+                else /* contig, tiled, potential resampling and data type change */
                 {
-                    for(int x=0;x<nBufXSize;x++)
+                    const GByte* pabyLocalSrcDataStartLine = NULL;
+                    GByte* pabyLocalData = pabyData + y * nLineSpace;
+                    double dfSrcX = nXOff + 0.5 * dfSrcXInc;
+                    int nCurBlockXOff = 0;
+                    int nNextBlockXOff = 0;
+                    toff_t nCurOffset = 0;
+                    for(int x=0;x<nBufXSize;x++, dfSrcX += dfSrcXInc)
                     {
-                        int nSrcPixel = nXOff + (int)((x + 0.5) * nXSize / nBufXSize);
-                        int nBlockXOff = nSrcPixel / nBlockXSize;
-                        int nXOffsetInBlock = nSrcPixel % nBlockXSize;
-                        int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
-                        int nByteOffsetInBlock = nBaseByteOffsetInBlock + nXOffsetInBlock * nBandsPerBlockDTSize;
-                        toff_t nCurOffset = panOffsets[nBlockId];
+                        int nSrcPixel = (int)dfSrcX;
+                        if( nSrcPixel >= nNextBlockXOff )
+                        {
+                            const int nBlockXOff = nSrcPixel / nBlockXSize;
+                            nCurBlockXOff = nBlockXOff * nBlockXSize;
+                            nNextBlockXOff = nCurBlockXOff + nBlockXSize;
+                            int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
+                            nCurOffset = panOffsets[nBlockId];
+                            if( nCurOffset != 0 )
+                            {
+                                pabyLocalSrcDataStartLine = oFetcher.FetchBytes(
+                                        nCurOffset + nBaseByteOffsetInBlock,
+                                        (int)nBlockXSize * nBandsPerBlock, nDTSize,
+                                        bIsByteSwapped, bIsComplex, nBlockId);
+                                if( pabyLocalSrcDataStartLine == NULL )
+                                    return CE_Failure;
+                            }
+                        }
+                        const int nXOffsetInBlock = nSrcPixel - nCurBlockXOff;
+
                         if( nCurOffset == 0 )
                         {
-                            REACHED(4);
+                            REACHED(5);
                             GDALCopyWords(&dfNoData, GDT_Float64, 0,
-                                          pabyData + y * nLineSpace + x * nPixelSpace,
-                                          eBufType, nBandSpace,
+                                          pabyLocalData,
+                                          eBufType, static_cast<int>(nBandSpace),
                                           nBandCount);
+                            pabyLocalData += nPixelSpace;
                         }
                         else
                         {
-                            if( nCurOffset + nBlockSize > nMappingSize )
+                            const GByte* pabyLocalSrcData = pabyLocalSrcDataStartLine +
+                                    nXOffsetInBlock * nBandsPerBlockDTSize;
+
+                            REACHED(6);
+                            if( bByteOnly )
                             {
-                                REACHED(25);
-                                CPLError(CE_Failure, CPLE_FileIO,
-                                            "Missing data for block %d", nBlockId);
-                                return CE_Failure;
+                                for(int iBand = 0; iBand < nBands; iBand ++ )
+                                    pabyLocalData[iBand] = pabyLocalSrcData[iBand];
                             }
-                            REACHED(5);
-                            GDALCopyWords(pabySrcData + nCurOffset + nByteOffsetInBlock,
+                            else
+                            {
+                                GDALCopyWords(pabyLocalSrcData,
                                             eDataType, nDTSize,
-                                            pabyData + y * nLineSpace + x * nPixelSpace,
-                                            eBufType, nBandSpace,
+                                            pabyLocalData,
+                                            eBufType, static_cast<int>(nBandSpace),
                                             nBandCount);
+                            }
+                            pabyLocalData += nPixelSpace;
                         }
                     }
                 }
             }
         }
-        else
+        else /* contig, stripped organized */
         {
             GByte* pabyData = (GByte*)pData;
             for(int y=0;y<nBufYSize;y++)
             {
-                int nSrcLine = nYOff + (int)((y + 0.5) * nYSize / nBufYSize);
-                int nBlockYOff = nSrcLine / nBlockYSize;
-                int nYOffsetInBlock = nSrcLine % nBlockYSize;
-                int nBlockId = nBlockYOff;
-                toff_t nCurOffset = panOffsets[nBlockId];
+                const int nSrcLine = nYOff + (int)((y + 0.5) * dfSrcYInc);
+                const int nBlockYOff = nSrcLine / nBlockYSize;
+                const int nYOffsetInBlock = nSrcLine % nBlockYSize;
+                const int nBlockId = nBlockYOff;
+                const toff_t nCurOffset = panOffsets[nBlockId];
                 if( nCurOffset == 0 )
                 {
-                    REACHED(6);
+                    REACHED(7);
                     for(int x=0;x<nBufXSize;x++)
                     {
                         GDALCopyWords(&dfNoData, GDT_Float64, 0,
                                       pabyData + y * nLineSpace + x * nPixelSpace,
-                                      eBufType, nBandSpace,
+                                      eBufType, static_cast<int>(nBandSpace),
                                       nBandCount);
                     }
                 }
                 else
                 {
-                    if( nCurOffset + (nYOffsetInBlock + 1) * nBlockXSize * nBandsPerBlockDTSize > nMappingSize )
+                    GByte* pabyLocalData = pabyData + y * nLineSpace;
+                    const int nBaseByteOffsetInBlock = (nYOffsetInBlock * nBlockXSize + nXOff) * nBandsPerBlockDTSize;
+
+                    if( bNoXResamplingNoTypeChange && nBands == nBandCount &&
+                        nPixelSpace == nBandsPerBlockDTSize )
                     {
-                        REACHED(26);
-                        CPLError(CE_Failure, CPLE_FileIO,
-                                    "Missing data for block %d", nBlockId);
-                        return CE_Failure;
+                        REACHED(8);
+                        if( !oFetcher.FetchBytes(
+                            pabyLocalData,
+                            nCurOffset + nBaseByteOffsetInBlock,
+                            nXSize * nBandsPerBlock, nDTSize, bIsByteSwapped, bIsComplex, nBlockId) )
+                        {
+                            return CE_Failure;
+                        }
                     }
-                    int nBaseByteOffsetInBlock = (nYOffsetInBlock * nBlockXSize + nXOff) * nBandsPerBlockDTSize;
-                    GByte* pabyLocalData = pabyData + y * nLineSpace;
-                    GByte* pabyLocalSrcData = pabySrcData + nCurOffset + nBaseByteOffsetInBlock;
-                    if( bByteNoXResampling )
+                    else
                     {
-                        if( nPixelSpace == nBandCount && nBandsPerBlockDTSize == nBandCount )
+                        const GByte* pabyLocalSrcData = oFetcher.FetchBytes(
+                            nCurOffset + nBaseByteOffsetInBlock,
+                            nXSize * nBandsPerBlock, nDTSize, bIsByteSwapped, bIsComplex, nBlockId);
+                        if( pabyLocalSrcData == NULL )
+                            return CE_Failure;
+
+                        if( bByteNoXResampling )
                         {
-                            REACHED(7);
-                            memcpy(pabyLocalData, pabyLocalSrcData, nBufXSize * nBandCount);
+                            REACHED(9);
+                            CopyContigByteMultiBand(pabyLocalSrcData,
+                                                nBandsPerBlockDTSize,
+                                                pabyLocalData,
+                                                static_cast<int>(nPixelSpace),
+                                                nBufXSize,
+                                                nBandCount);
                         }
-                        else
+                        else if( bByteOnly )
                         {
-                            REACHED(23);
-                            for(int x=0;x<nBufXSize;x++)
+                            REACHED(10);
+                            double dfSrcX = 0.5 * dfSrcXInc;
+                            for(int x=0;x<nBufXSize;x++, dfSrcX += dfSrcXInc)
                             {
+                                int nSrcPixelMinusXOff = (int)dfSrcX;
                                 for(int iBand=0;iBand<nBandCount;iBand++)
-                                    pabyLocalData[iBand] = pabyLocalSrcData[iBand];
-                                pabyLocalSrcData += nBandsPerBlockDTSize;
-                                pabyLocalData += nPixelSpace;
+                                {
+                                    pabyLocalData[x * nPixelSpace + iBand /* * nBandSpace*/] =
+                                        pabyLocalSrcData[nSrcPixelMinusXOff * nBandsPerBlockDTSize + iBand];
+                                }
                             }
                         }
-                    }
-                    else if( bByteOnly )
-                    {
-                        REACHED(31);
-                        for(int x=0;x<nBufXSize;x++)
-                        {
-                            int nSrcPixelMinusXOff = (int)((x + 0.5) * nXSize / nBufXSize);
-                            for(int iBand=0;iBand<nBandCount;iBand++)
-                                pabyLocalData[x * nPixelSpace + iBand /* * nBandSpace*/] = pabyLocalSrcData[nSrcPixelMinusXOff * nBandsPerBlockDTSize + iBand];
-                        }
-                    }
-                    else
-                    {
-                        REACHED(8);
-                        for(int x=0;x<nBufXSize;x++)
+                        else
                         {
-                            int nSrcPixelMinusXOff = (int)((x + 0.5) * nXSize / nBufXSize);
-                            GDALCopyWords(pabyLocalSrcData + nSrcPixelMinusXOff * nBandsPerBlockDTSize,
-                                          eDataType, nDTSize,
-                                          pabyLocalData + x * nPixelSpace,
-                                          eBufType, nBandSpace,
-                                          nBandCount);
+                            REACHED(11);
+                            double dfSrcX = 0.5 * dfSrcXInc;
+                            for(int x=0;x<nBufXSize;x++, dfSrcX += dfSrcXInc)
+                            {
+                                int nSrcPixelMinusXOff = (int)dfSrcX;
+                                GDALCopyWords(pabyLocalSrcData + nSrcPixelMinusXOff * nBandsPerBlockDTSize,
+                                            eDataType, nDTSize,
+                                            pabyLocalData + x * nPixelSpace,
+                                            eBufType, static_cast<int>(nBandSpace),
+                                            nBandCount);
+                            }
                         }
                     }
                 }
             }
         }
     }
-    else
+    else /* non contig reading case */
     {
-        if( TIFFIsTiled( hTIFF ) )
+        if( !FetchBuffer::bMinimizeIO && TIFFIsTiled( hTIFF ) )
         {
-            for(iBand = 0; iBand < nBandCount; iBand ++ )
+            for(int iBand = 0; iBand < nBandCount; iBand ++ )
             {
-                int nBand = panBandMap[iBand];
-                GByte* pabyData = (GByte*)pData + iBand * nBandSpace;
+                const int nBand = panBandMap[iBand];
+                GByte* const pabyData = (GByte*)pData + iBand * nBandSpace;
                 for(int y=0;y<nBufYSize;y++)
                 {
-                    int nSrcLine = nYOff + (int)((y + 0.5) * nYSize / nBufYSize);
-                    int nBlockYOff = nSrcLine / nBlockYSize;
-                    int nYOffsetInBlock = nSrcLine % nBlockYSize;
+                    const int nSrcLine = nYOff + (int)((y + 0.5) * dfSrcYInc);
+                    const int nBlockYOff = nSrcLine / nBlockYSize;
+                    const int nYOffsetInBlock = nSrcLine % nBlockYSize;
 
                     int nBaseByteOffsetInBlock = nYOffsetInBlock * nBlockXSize * nBandsPerBlockDTSize;
                     if ( nPlanarConfig == PLANARCONFIG_CONTIG )
                     {
-                        REACHED(9);
+                        REACHED(12);
                         nBaseByteOffsetInBlock += (nBand-1) * nDTSize;
                     }
                     else
                     {
-                        REACHED(10);
+                        REACHED(13);
                     }
 
-                    if( bByteNoXResampling )
+                    if( bNoXResampling )
                     {
                         GByte* pabyLocalData = pabyData + y * nLineSpace;
-                        int nLastPixelBlock = 0;
-                        int nByteOffsetInBlock = 0;
-                        toff_t nCurOffset = 0;
                         int nBlockXOff = nXOff / nBlockXSize;
                         int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
                         if ( nPlanarConfig == PLANARCONFIG_SEPARATE )
+                        {
+                            REACHED(14);
                             nBlockId += nBlocksPerBand * (nBand - 1);
+                        }
+                        else
+                        {
+                            REACHED(15);
+                        }
                         int nXOffsetInBlock = nXOff % nBlockXSize;
-                        for(int x=0;x<nBufXSize;x++)
+
+                        int x = 0;
+                        while( x < nBufXSize )
                         {
-                            int nSrcPixel = nXOff + x;
-                            if( nSrcPixel >= nLastPixelBlock )
-                            {
-                                REACHED(11);
-                                nLastPixelBlock = (nBlockXOff + 1) * nBlockXSize;
-                                nByteOffsetInBlock = nBaseByteOffsetInBlock + nXOffsetInBlock * nBandsPerBlockDTSize;
-                                nCurOffset = panOffsets[nBlockId];
-                                if( nCurOffset != 0 &&
-                                    nCurOffset + nBlockSize > nMappingSize )
-                                {
-                                    REACHED(27);
-                                    CPLError(CE_Failure, CPLE_FileIO,
-                                                "Missing data for block %d", nBlockId);
-                                    return CE_Failure;
-                                }
-                                nXOffsetInBlock = 0;
-                                nBlockXOff ++;
-                                nBlockId ++; 
-                            }
-                            else
-                            {
-                                REACHED(12);
-                                nByteOffsetInBlock += nBandsPerBlockDTSize;
-                            }
+                            const int nByteOffsetInBlock = nBaseByteOffsetInBlock +
+                                    nXOffsetInBlock * nBandsPerBlockDTSize;
+                            const toff_t nCurOffset = panOffsets[nBlockId];
+                            const int nUsedBlockWidth = MIN((int)nBlockXSize - nXOffsetInBlock, nBufXSize - x);
+                            int nIters = nUsedBlockWidth;
 
                             if( nCurOffset == 0 )
                             {
-                                REACHED(13);
-                                *pabyLocalData = abyNoData;
+                                REACHED(16);
+                                GDALCopyWords(&dfNoData, GDT_Float64, 0,
+                                              pabyLocalData, eBufType, static_cast<int>(nPixelSpace),
+                                              nIters);
+                                pabyLocalData += nIters * nPixelSpace;
                             }
                             else
                             {
-                                REACHED(14);
-                                *pabyLocalData = pabySrcData[nCurOffset + nByteOffsetInBlock];
+                                if( bNoTypeChange && nPixelSpace == nBandsPerBlockDTSize )
+                                {
+                                    REACHED(17);
+                                    if( !oFetcher.FetchBytes( pabyLocalData,
+                                            nCurOffset + nByteOffsetInBlock,
+                                            (nIters - 1) * nBandsPerBlock + 1, nDTSize,
+                                            bIsByteSwapped, bIsComplex, nBlockId) )
+                                    {
+                                        return CE_Failure;
+                                    }
+                                    pabyLocalData += nIters * nPixelSpace;
+                                }
+                                else
+                                {
+                                    const GByte* pabyLocalSrcData = oFetcher.FetchBytes(
+                                        nCurOffset + nByteOffsetInBlock,
+                                        (nIters - 1) * nBandsPerBlock + 1, nDTSize,
+                                        bIsByteSwapped, bIsComplex, nBlockId);
+                                    if( pabyLocalSrcData == NULL )
+                                        return CE_Failure;
+
+                                    REACHED(18);
+                                    GDALCopyWords(pabyLocalSrcData, eDataType, nBandsPerBlockDTSize,
+                                                    pabyLocalData, eBufType, static_cast<int>(nPixelSpace),
+                                                    nIters);
+                                    pabyLocalData += nIters * nPixelSpace;
+                                }
                             }
-                            pabyLocalData += nPixelSpace;
+
+                            nXOffsetInBlock = 0;
+                            nBlockXOff ++;
+                            nBlockId ++;
+                            x += nUsedBlockWidth;
                         }
                     }
-                    else
+                    else /* non contig reading, tiled, potential resampling and data type change */
                     {
-                        for(int x=0;x<nBufXSize;x++)
+                        const GByte* pabyLocalSrcDataStartLine = NULL;
+                        GByte* pabyLocalData = pabyData + y * nLineSpace;
+                        double dfSrcX = nXOff + 0.5 * dfSrcXInc;
+                        int nCurBlockXOff = 0;
+                        int nNextBlockXOff = 0;
+                        toff_t nCurOffset = 0;
+                        for(int x=0;x<nBufXSize;x++, dfSrcX += dfSrcXInc)
                         {
-                            int nSrcPixel = nXOff + (int)((x + 0.5) * nXSize / nBufXSize);
-                            int nBlockXOff = nSrcPixel / nBlockXSize;
-                            int nXOffsetInBlock = nSrcPixel % nBlockXSize;
-                            int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
-                            if ( nPlanarConfig == PLANARCONFIG_SEPARATE )
-                                nBlockId += nBlocksPerBand * (nBand - 1);
-                            int nByteOffsetInBlock = nBaseByteOffsetInBlock + nXOffsetInBlock * nBandsPerBlockDTSize;
-                            toff_t nCurOffset = panOffsets[nBlockId];
+                            int nSrcPixel = (int)dfSrcX;
+                            if( nSrcPixel >= nNextBlockXOff )
+                            {
+                                const int nBlockXOff = nSrcPixel / nBlockXSize;
+                                nCurBlockXOff = nBlockXOff * nBlockXSize;
+                                nNextBlockXOff = nCurBlockXOff + nBlockXSize;
+                                int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
+                                if ( nPlanarConfig == PLANARCONFIG_SEPARATE )
+                                {
+                                    REACHED(19);
+                                    nBlockId += nBlocksPerBand * (nBand - 1);
+                                }
+                                else
+                                {
+                                    REACHED(20);
+                                }
+                                nCurOffset = panOffsets[nBlockId];
+                                if( nCurOffset != 0 )
+                                {
+                                    pabyLocalSrcDataStartLine = oFetcher.FetchBytes(
+                                            nCurOffset + nBaseByteOffsetInBlock,
+                                            (int)nBlockXSize * nBandsPerBlock, nDTSize,
+                                            bIsByteSwapped, bIsComplex, nBlockId);
+                                    if( pabyLocalSrcDataStartLine == NULL )
+                                        return CE_Failure;
+                                }
+                            }
+                            const int nXOffsetInBlock = nSrcPixel - nCurBlockXOff;
+
                             if( nCurOffset == 0 )
                             {
-                                REACHED(15);
+                                REACHED(21);
                                 GDALCopyWords(&dfNoData, GDT_Float64, 0,
-                                              pabyData + y * nLineSpace + x * nPixelSpace,
-                                              eBufType, nPixelSpace,
+                                              pabyLocalData,
+                                              eBufType, 0,
                                               1);
+                                pabyLocalData += nPixelSpace;
                             }
                             else
                             {
-                                if( nCurOffset + nBlockSize > nMappingSize)
+                                const GByte* pabyLocalSrcData = pabyLocalSrcDataStartLine +
+                                        nXOffsetInBlock * nBandsPerBlockDTSize;
+
+                                REACHED(22);
+                                if( bByteOnly )
+                                    *pabyLocalData = *pabyLocalSrcData;
+                                else
                                 {
-                                    REACHED(28);
-                                    CPLError(CE_Failure, CPLE_FileIO,
-                                                "Missing data for block %d", nBlockId);
-                                    return CE_Failure;
+                                    GDALCopyWords(pabyLocalSrcData,
+                                                eDataType, 0,
+                                                pabyLocalData,
+                                                eBufType, 0,
+                                                1);
                                 }
-                                REACHED(16);
-                                GDALCopyWords(pabySrcData + nCurOffset + nByteOffsetInBlock,
-                                            eDataType, nDTSize,
-                                            pabyData + y * nLineSpace + x * nPixelSpace,
-                                            eBufType, nPixelSpace,
-                                            1);
+                                pabyLocalData += nPixelSpace;
                             }
                         }
                     }
                 }
             }
         }
-        else
+        else /* non contig reading, stripped */
         {
-            for(iBand = 0; iBand < nBandCount; iBand ++ )
+            for(int iBand = 0; iBand < nBandCount; iBand ++ )
             {
-                int nBand = panBandMap[iBand];
+                const int nBand = panBandMap[iBand];
                 GByte* pabyData = (GByte*)pData + iBand * nBandSpace;
                 for(int y=0;y<nBufYSize;y++)
                 {
-                    int nSrcLine = nYOff + (int)((y + 0.5) * nYSize / nBufYSize);
-                    int nBlockYOff = nSrcLine / nBlockYSize;
-                    int nYOffsetInBlock = nSrcLine % nBlockYSize;
+                    const int nSrcLine = nYOff + (int)((y + 0.5) * dfSrcYInc);
+                    const int nBlockYOff = nSrcLine / nBlockYSize;
+                    const int nYOffsetInBlock = nSrcLine % nBlockYSize;
                     int nBlockId = nBlockYOff;
                     if ( nPlanarConfig == PLANARCONFIG_SEPARATE )
                     {
-                        REACHED(17);
+                        REACHED(23);
                         nBlockId += nBlocksPerBand * (nBand - 1);
                     }
                     else
                     {
-                        REACHED(18);
+                        REACHED(24);
                     }
-                    toff_t nCurOffset = panOffsets[nBlockId];
+                    const toff_t nCurOffset = panOffsets[nBlockId];
                     if( nCurOffset == 0 )
                     {
-                        REACHED(19);
+                        REACHED(25);
                         GDALCopyWords(&dfNoData, GDT_Float64, 0,
-                                      pabyData + y * nLineSpace, eBufType, nPixelSpace,
+                                      pabyData + y * nLineSpace, eBufType, static_cast<int>(nPixelSpace),
                                       nBufXSize);
                     }
                     else
                     {
-                        if( nCurOffset + (nYOffsetInBlock + 1) * nBlockXSize * nBandsPerBlockDTSize > nMappingSize )
-                        {
-                            REACHED(29);
-                            CPLError(CE_Failure, CPLE_FileIO,
-                                     "Missing data for block %d", nBlockId);
-                            return CE_Failure;
-                        }
-                        int nBaseByteOffsetInBlock = (nYOffsetInBlock * nBlockXSize + nXOff) * nBandsPerBlockDTSize;
+                        int nBaseByteOffsetInBlock =
+                            (nYOffsetInBlock * nBlockXSize + nXOff) * nBandsPerBlockDTSize;
                         if ( nPlanarConfig == PLANARCONFIG_CONTIG )
                             nBaseByteOffsetInBlock += (nBand-1) * nDTSize;
 
-                        if( bByteNoXResampling )
+                        GByte* pabyLocalData = pabyData + y * nLineSpace;
+                        if( bNoXResamplingNoTypeChange && nPixelSpace == nBandsPerBlockDTSize )
                         {
-                            GByte* pabyLocalData = pabyData + y * nLineSpace;
-                            GByte* pabyLocalSrcData = pabySrcData + nCurOffset + nBaseByteOffsetInBlock;
-                            if( nPixelSpace == 1 && nBandsPerBlockDTSize == 1 )
-                            {
-                                REACHED(20);
-                                memcpy(pabyLocalData, pabyLocalSrcData, nBufXSize);
-                            }
-                            else
+                            REACHED(26);
+                            if( !oFetcher.FetchBytes(pabyLocalData,
+                                        nCurOffset + nBaseByteOffsetInBlock,
+                                        (nXSize-1) * nBandsPerBlock + 1, nDTSize,
+                                        bIsByteSwapped, bIsComplex, nBlockId) )
                             {
-                                REACHED(21);
-                                for(int x=0;x<nBufXSize;x++)
-                                {
-                                    *pabyLocalData = *pabyLocalSrcData,
-                                    pabyLocalData += nPixelSpace;
-                                    pabyLocalSrcData += nBandsPerBlockDTSize;
-                                }
+                                return CE_Failure;
                             }
                         }
-                        else if( bByteOnly )
+                        else
                         {
-                            REACHED(30);
-                            GByte* pabyLocalData = pabyData + y * nLineSpace;
-                            GByte* pabyLocalSrcData = pabySrcData + nCurOffset + nBaseByteOffsetInBlock;
-                            for(int x=0;x<nBufXSize;x++)
+                            const GByte* pabyLocalSrcData = oFetcher.FetchBytes(
+                                nCurOffset + nBaseByteOffsetInBlock,
+                                (nXSize-1) * nBandsPerBlock + 1, nDTSize,
+                                bIsByteSwapped, bIsComplex, nBlockId);
+                            if( pabyLocalSrcData == NULL )
+                                return CE_Failure;
+
+                            if( bNoXResamplingNoTypeChange )
                             {
-                                int nSrcPixelMinusXOff = (int)((x + 0.5) * nXSize / nBufXSize);
-                                pabyLocalData[x * nPixelSpace] = pabyLocalSrcData[nSrcPixelMinusXOff * nBandsPerBlockDTSize];
+                                REACHED(27);
+                                GDALCopyWords(pabyLocalSrcData,
+                                              eDataType, nBandsPerBlockDTSize,
+                                              pabyLocalData, eBufType, static_cast<int>(nPixelSpace),
+                                              nBufXSize);
                             }
-                        }
-                        else
-                        {
-                            REACHED(22);
-                            for(int x=0;x<nBufXSize;x++)
+                            else if( bByteOnly )
+                            {
+                                REACHED(28);
+                                double dfSrcX = 0.5 * dfSrcXInc;
+                                for(int x=0;x<nBufXSize;x++, dfSrcX += dfSrcXInc)
+                                {
+                                    int nSrcPixelMinusXOff = (int)dfSrcX;
+                                    pabyLocalData[x * nPixelSpace] =
+                                        pabyLocalSrcData[nSrcPixelMinusXOff * nBandsPerBlockDTSize];
+                                }
+                            }
+                            else
                             {
-                                int nSrcPixelMinusXOff = (int)((x + 0.5) * nXSize / nBufXSize);
-                                int nByteOffsetInBlock = nBaseByteOffsetInBlock + nSrcPixelMinusXOff * nBandsPerBlockDTSize;
-                                GDALCopyWords(pabySrcData + nCurOffset + nByteOffsetInBlock,
-                                            eDataType, nDTSize,
-                                            pabyData + y * nLineSpace + x * nPixelSpace, eBufType, nPixelSpace,
-                                            1);
+                                REACHED(29);
+                                double dfSrcX = 0.5 * dfSrcXInc;
+                                for(int x=0;x<nBufXSize;x++, dfSrcX += dfSrcXInc)
+                                {
+                                    int nSrcPixelMinusXOff = (int)dfSrcX;
+                                    GDALCopyWords(pabyLocalSrcData +
+                                                    nSrcPixelMinusXOff * nBandsPerBlockDTSize,
+                                                eDataType, 0,
+                                                pabyLocalData + x * nPixelSpace,
+                                                eBufType, 0,
+                                                1);
+                                }
                             }
                         }
                     }
@@ -2188,32 +3200,31 @@ int GTiffDataset::VirtualMemIO( GDALRWFlag eRWFlag,
 /************************************************************************/
 
 /* Reads directly bytes from the file using ReadMultiRange(), and by-pass */
-/* block reading. Restricted to simple TIFF configurations (un-tiled, */
-/* uncompressed data, standard data types). Particularly useful to extract */
+/* block reading. Restricted to simple TIFF configurations */
+/* (uncompressed data, standard data types). Particularly useful to extract */
 /* sub-windows of data on a large /vsicurl dataset). */
+/* Returns -1 if DirectIO() can't be supported on that file */
 
-CPLErr GTiffDataset::DirectIO( GDALRWFlag eRWFlag,
+int GTiffDataset::DirectIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
                                void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType, 
+                               GDALDataType eBufType,
                                int nBandCount, int *panBandMap,
                                GSpacing nPixelSpace, GSpacing nLineSpace,
                                GSpacing nBandSpace,
                                GDALRasterIOExtraArg* psExtraArg )
 {
-    GDALDataType eDataType = GetRasterBand(1)->GetRasterDataType();
+    const GDALDataType eDataType = GetRasterBand(1)->GetRasterDataType();
+    const int nDTSizeBits = GDALGetDataTypeSize(eDataType);
     if( !(eRWFlag == GF_Read &&
           nCompression == COMPRESSION_NONE &&
           (nPhotometric == PHOTOMETRIC_MINISBLACK ||
            nPhotometric == PHOTOMETRIC_RGB ||
            nPhotometric == PHOTOMETRIC_PALETTE) &&
-          (nBitsPerSample == 8 || (nBitsPerSample == 16) ||
-           nBitsPerSample == 32 || nBitsPerSample == 64) &&
-          nBitsPerSample == GDALGetDataTypeSize(eDataType) &&
-          SetDirectory() && /* very important to make hTIFF uptodate! */
-          !TIFFIsTiled( hTIFF )) )
+          nBitsPerSample == nDTSizeBits &&
+          SetDirectory() /* very important to make hTIFF uptodate! */) )
     {
-        return CE_Failure;
+        return -1;
     }
 
     /* we only know how to deal with nearest neighbour in this optimized routine */
@@ -2221,15 +3232,15 @@ CPLErr GTiffDataset::DirectIO( GDALRWFlag eRWFlag,
         psExtraArg != NULL &&
         psExtraArg->eResampleAlg != GRIORA_NearestNeighbour )
     {
-        return CE_Failure;
+        return -1;
     }
 
     /* if the file is band interleave or only one band is requested, then */
     /* fallback to band DirectIO */
-    int bUseBandRasterIO = FALSE;
+    bool bUseBandRasterIO = false;
     if( nPlanarConfig == PLANARCONFIG_SEPARATE || nBandCount == 1 )
     {
-        bUseBandRasterIO = TRUE;
+        bUseBandRasterIO = true;
     }
     else
     {
@@ -2238,7 +3249,7 @@ CPLErr GTiffDataset::DirectIO( GDALRWFlag eRWFlag,
         {
             if( panBandMap[iBand] != iBand + 1)
             {
-                bUseBandRasterIO = TRUE;
+                bUseBandRasterIO = true;
                 break;
             }
         }
@@ -2268,7 +3279,37 @@ CPLErr GTiffDataset::DirectIO( GDALRWFlag eRWFlag,
 
     /* Make sure that TIFFTAG_STRIPOFFSETS is up-to-date */
     if (GetAccess() == GA_Update)
+    {
         FlushCache();
+        VSI_TIFFFlushBufferedWrite( TIFFClientdata( hTIFF ) );
+    }
+
+    if( TIFFIsTiled( hTIFF ) )
+    {
+        if( m_pTempBufferForCommonDirectIO == NULL )
+        {
+            const int nDTSize = nDTSizeBits / 8;
+            m_nTempBufferForCommonDirectIOSize =
+                (size_t)(nBlockXSize * nBlockYSize * nDTSize *
+                ((nPlanarConfig == PLANARCONFIG_CONTIG) ? nBands : 1));
+
+            m_pTempBufferForCommonDirectIO = (GByte*)VSI_MALLOC_VERBOSE(m_nTempBufferForCommonDirectIOSize);
+            if( m_pTempBufferForCommonDirectIO == NULL )
+                return CE_Failure;
+        }
+
+        VSILFILE* fp = VSI_TIFFGetVSILFile(TIFFClientdata( hTIFF ));
+        FetchBufferDirectIO oFetcher(fp, m_pTempBufferForCommonDirectIO,
+                                     m_nTempBufferForCommonDirectIOSize);
+
+        return CommonDirectIO( oFetcher,
+                            nXOff, nYOff, nXSize, nYSize,
+                            pData, nBufXSize, nBufYSize,
+                            eBufType,
+                            nBandCount, panBandMap,
+                            nPixelSpace, nLineSpace,
+                            nBandSpace );
+    }
 
     /* Get strip offsets */
     toff_t *panTIFFOffsets = NULL;
@@ -2278,18 +3319,17 @@ CPLErr GTiffDataset::DirectIO( GDALRWFlag eRWFlag,
         return CE_Failure;
     }
 
-    int iLine;
     int nReqXSize = nXSize; /* sub-sampling or over-sampling can only be done at last stage */
     int nReqYSize = MIN(nBufYSize, nYSize); /* we can do sub-sampling at the extraction stage */
-    void** ppData = (void**) VSIMalloc(nReqYSize * sizeof(void*));
+    void** ppData = (void**) VSI_MALLOC_VERBOSE(nReqYSize * sizeof(void*));
     vsi_l_offset* panOffsets = (vsi_l_offset*)
-                            VSIMalloc(nReqYSize * sizeof(vsi_l_offset));
-    size_t* panSizes = (size_t*) VSIMalloc(nReqYSize * sizeof(size_t));
+                            VSI_MALLOC_VERBOSE(nReqYSize * sizeof(vsi_l_offset));
+    size_t* panSizes = (size_t*) VSI_MALLOC_VERBOSE(nReqYSize * sizeof(size_t));
     int nDTSize = GDALGetDataTypeSize(eDataType) / 8;
     void* pTmpBuffer = NULL;
-    CPLErr eErr = CE_None;
+    int eErr = CE_None;
     int nContigBands = nBands;
-    int ePixelSize = nDTSize * nContigBands;
+    int nSrcPixelSize = nDTSize * nContigBands;
 
     if (ppData == NULL || panOffsets == NULL || panSizes == NULL)
         eErr = CE_Failure;
@@ -2301,21 +3341,24 @@ CPLErr GTiffDataset::DirectIO( GDALRWFlag eRWFlag,
     {
         /* We need a temporary buffer for over-sampling/sub-sampling */
         /* and/or data type conversion */
-        pTmpBuffer = VSIMalloc(nReqXSize * nReqYSize * ePixelSize);
+        pTmpBuffer = VSI_MALLOC_VERBOSE(nReqXSize * nReqYSize * nSrcPixelSize);
         if (pTmpBuffer == NULL)
             eErr = CE_Failure;
     }
 
     /* Prepare data extraction */
+    const double dfSrcYInc = nYSize / (double) nBufYSize;
+
+    int iLine;
     for(iLine=0;eErr == CE_None && iLine<nReqYSize;iLine++)
     {
         /*if (pTmpBuffer == NULL)
             ppData[iLine] = ((GByte*)pData) + iLine * nLineSpace;
         else*/
-            ppData[iLine] = ((GByte*)pTmpBuffer) + iLine * nReqXSize * ePixelSize;
+            ppData[iLine] = ((GByte*)pTmpBuffer) + iLine * nReqXSize * nSrcPixelSize;
         int nSrcLine;
         if (nBufYSize < nYSize) /* Sub-sampling in y */
-            nSrcLine = nYOff + (int)((iLine + 0.5) * nYSize / nBufYSize);
+            nSrcLine = nYOff + (int)((iLine + 0.5) * dfSrcYInc);
         else
             nSrcLine = nYOff + iLine;
 
@@ -2327,10 +3370,10 @@ CPLErr GTiffDataset::DirectIO( GDALRWFlag eRWFlag,
 
         panOffsets[iLine] = panTIFFOffsets[nBlockId];
         if (panOffsets[iLine] == 0) /* We don't support sparse files */
-            eErr = CE_Failure;
+            eErr = -1;
 
-        panOffsets[iLine] += (nXOff + nYOffsetInBlock * nBlockXSize) * ePixelSize;
-        panSizes[iLine] = nReqXSize * ePixelSize;
+        panOffsets[iLine] += (nXOff + nYOffsetInBlock * nBlockXSize) * nSrcPixelSize;
+        panSizes[iLine] = nReqXSize * nSrcPixelSize;
     }
 
     /* Extract data from the file */
@@ -2355,12 +3398,13 @@ CPLErr GTiffDataset::DirectIO( GDALRWFlag eRWFlag,
     }
 
     /* Over-sampling/sub-sampling and/or data type conversion */
+    const double dfSrcXInc = nXSize / (double) nBufXSize;
     if (eErr == CE_None && pTmpBuffer != NULL)
     {
         for(int iY=0;iY<nBufYSize;iY++)
         {
             int iSrcY = (nBufYSize <= nYSize) ? iY :
-                            (int)((iY + 0.5) * nYSize / nBufYSize);
+                            (int)((iY + 0.5) * dfSrcYInc);
             /* Optimization: no resampling, no data type change, number of bands requested == number of bands */
             /* and buffer is packed pixel-interleaved */
             if (nBufXSize == nXSize && nContigBands == nBandCount &&
@@ -2368,21 +3412,29 @@ CPLErr GTiffDataset::DirectIO( GDALRWFlag eRWFlag,
                 nBandSpace == nDTSize && nPixelSpace == nBandCount * nBandSpace )
             {
                 memcpy( ((GByte*)pData) + iY * nLineSpace, ppData[iSrcY],
-                        nReqXSize * nPixelSpace );
+                        static_cast<size_t>(nReqXSize * nPixelSpace) );
             }
             /* Other optimization: no resampling, no data type change, */
-            /* data type is Byte and buffer is pixel-interleaved (with some stridding between pixels) */
+            /* data type is Byte */
             else if (nBufXSize == nXSize &&
-                     eDataType == eBufType && eDataType == GDT_Byte &&
-                     nBandSpace == 1 && nPixelSpace > nBandCount )
+                     eDataType == eBufType && eDataType == GDT_Byte )
             {
                 GByte* pabySrcData = ((GByte*)ppData[iSrcY]);
                 GByte* pabyDstData = ((GByte*)pData) + iY * nLineSpace;
-                for(int iX=0;iX<nBufXSize;iX++)
+                if( nBandSpace == 1 && nPixelSpace > nBandCount )
+                {
+                    /* buffer is pixel-interleaved (with some stridding between pixels) */
+                    CopyContigByteMultiBand(pabySrcData, nSrcPixelSize,
+                                            pabyDstData, static_cast<int>(nPixelSpace),
+                                            nBufXSize, nBandCount);
+                }
+                else
                 {
                     for(int iBand = 0; iBand < nBandCount; iBand ++ )
                     {
-                        pabyDstData[iX * nPixelSpace + iBand] = pabySrcData[iX * ePixelSize + iBand];
+                        GDALCopyWords(pabySrcData + iBand, GDT_Byte, nSrcPixelSize,
+                                      pabyDstData + iBand * nBandSpace, GDT_Byte, static_cast<int>(nPixelSpace),
+                                      nBufXSize);
                     }
                 }
             }
@@ -2393,14 +3445,26 @@ CPLErr GTiffDataset::DirectIO( GDALRWFlag eRWFlag,
                 {
                     GByte* pabySrcData = ((GByte*)ppData[iSrcY]) + iBand * nDTSize;
                     GByte* pabyDstData = ((GByte*)pData) + iBand * nBandSpace + iY * nLineSpace;
-                    for(int iX=0;iX<nBufXSize;iX++)
+                    if( eDataType == GDT_Byte && eBufType == GDT_Byte )
                     {
-                        int iSrcX = (nBufXSize == nXSize) ? iX :
-                                        (int)((iX+0.5) * nXSize / nBufXSize);
-                        GDALCopyWords( pabySrcData + iSrcX * ePixelSize,
-                                    eDataType, 0,
-                                    pabyDstData + iX * nPixelSpace,
-                                    eBufType, 0, 1);
+                        double dfSrcX = 0.5 * dfSrcXInc;
+                        for(int iX=0;iX<nBufXSize;iX++, dfSrcX += dfSrcXInc)
+                        {
+                            int iSrcX = (int)dfSrcX;
+                            pabyDstData[iX * nPixelSpace] = pabySrcData[iSrcX * nSrcPixelSize];
+                        }
+                    }
+                    else
+                    {
+                        double dfSrcX = 0.5 * dfSrcXInc;
+                        for(int iX=0;iX<nBufXSize;iX++, dfSrcX += dfSrcXInc)
+                        {
+                            int iSrcX = (int)dfSrcX;
+                            GDALCopyWords( pabySrcData + iSrcX * nSrcPixelSize,
+                                        eDataType, 0,
+                                        pabyDstData + iX * nPixelSpace,
+                                        eBufType, 0, 1);
+                        }
                     }
                 }
             }
@@ -2436,30 +3500,18 @@ CPLErr GTiffRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     /* Try to pass the request to the most appropriate overview dataset */
     if( nBufXSize < nXSize && nBufYSize < nYSize )
     {
-        int nXOffMod = nXOff, nYOffMod = nYOff, nXSizeMod = nXSize, nYSizeMod = nYSize;
-        GDALRasterIOExtraArg sExtraArg;
-    
-        GDALCopyRasterIOExtraArg(&sExtraArg, psExtraArg);
-        
+        int bTried;
         poGDS->nJPEGOverviewVisibilityFlag ++;
-        int iOvrLevel = GDALBandGetBestOverviewLevel2(this,
-                                                     nXOffMod, nYOffMod,
-                                                     nXSizeMod, nYSizeMod,
-                                                     nBufXSize, nBufYSize,
-                                                     &sExtraArg);
+        eErr = TryOverviewRasterIO( eRWFlag,
+                                    nXOff, nYOff, nXSize, nYSize,
+                                    pData, nBufXSize, nBufYSize,
+                                    eBufType,
+                                    nPixelSpace, nLineSpace,
+                                    psExtraArg,
+                                    &bTried );
         poGDS->nJPEGOverviewVisibilityFlag --;
-
-        if( iOvrLevel >= 0 && GetOverview(iOvrLevel) != NULL &&
-            GetOverview(iOvrLevel)->GetDataset() != NULL )
-        {
-            poGDS->nJPEGOverviewVisibilityFlag ++;
-            eErr = GetOverview(iOvrLevel)->RasterIO(
-                eRWFlag, nXOffMod, nYOffMod, nXSizeMod, nYSizeMod,
-                pData, nBufXSize, nBufYSize, eBufType,
-                nPixelSpace, nLineSpace, &sExtraArg);
-            poGDS->nJPEGOverviewVisibilityFlag --;
+        if( bTried )
             return eErr;
-        }
     }
 
 
@@ -2474,11 +3526,11 @@ CPLErr GTiffRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     }
     if (poGDS->bDirectIO)
     {
-        eErr = DirectIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
+        int nErr = DirectIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
                         pData, nBufXSize, nBufYSize, eBufType,
                         nPixelSpace, nLineSpace, psExtraArg);
-        if (eErr == CE_None)
-            return eErr;
+        if (nErr >= 0)
+            return (CPLErr)nErr;
     }
 
     if (poGDS->nBands != 1 &&
@@ -2526,18 +3578,18 @@ CPLErr GTiffRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                     void * pImage )
 
 {
-    int			nBlockBufSize, nBlockId, nBlockIdBand0;
-    CPLErr		eErr = CE_None;
+    int nBlockBufSize, nBlockId, nBlockIdBand0;
+    CPLErr eErr = CE_None;
 
     if (!poGDS->SetDirectory())
         return CE_Failure;
 
     if( TIFFIsTiled(poGDS->hTIFF) )
-        nBlockBufSize = TIFFTileSize( poGDS->hTIFF );
+        nBlockBufSize = static_cast<int>(TIFFTileSize( poGDS->hTIFF ));
     else
     {
         CPLAssert( nBlockXOff == 0 );
-        nBlockBufSize = TIFFStripSize( poGDS->hTIFF );
+        nBlockBufSize = static_cast<int>(TIFFStripSize( poGDS->hTIFF ));
     }
 
     CPLAssert(nBlocksPerRow != 0);
@@ -2546,7 +3598,7 @@ CPLErr GTiffRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         nBlockId = nBlockIdBand0 + (nBand-1) * poGDS->nBlocksPerBand;
     else
         nBlockId = nBlockIdBand0;
-        
+
 /* -------------------------------------------------------------------- */
 /*      The bottom most partial tiles and strips are sometimes only     */
 /*      partially encoded.  This code reduces the requested data so     */
@@ -2556,10 +3608,12 @@ CPLErr GTiffRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
     if( (nBlockYOff+1) * nBlockYSize > nRasterYSize )
     {
-        nBlockReqSize = (nBlockBufSize / nBlockYSize) 
+        nBlockReqSize = (nBlockBufSize / nBlockYSize)
             * (nBlockYSize - (((nBlockYOff+1) * nBlockYSize) % nRasterYSize));
     }
 
+    poGDS->WaitCompletionForBlock(nBlockId);
+
 /* -------------------------------------------------------------------- */
 /*      Handle the case of a strip or tile that doesn't exist yet.      */
 /*      Just set to zeros and return.                                   */
@@ -2569,7 +3623,7 @@ CPLErr GTiffRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         NullBlock( pImage );
         return CE_None;
     }
-    
+
     if( poGDS->bStreamingIn &&
         !(poGDS->nBands > 1 && poGDS->nPlanarConfig == PLANARCONFIG_CONTIG && nBlockId == poGDS->nLoadedBlock) )
     {
@@ -2589,7 +3643,7 @@ CPLErr GTiffRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     }
 
 /* -------------------------------------------------------------------- */
-/*      Handle simple case (separate, onesampleperpixel)		*/
+/*      Handle simple case (separate, onesampleperpixel)                */
 /* -------------------------------------------------------------------- */
     if( poGDS->nBands == 1
         || poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE )
@@ -2606,7 +3660,7 @@ CPLErr GTiffRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                 memset( pImage, 0, nBlockBufSize );
                 CPLError( CE_Failure, CPLE_AppDefined,
                           "TIFFReadEncodedTile() failed.\n" );
-                
+
                 eErr = CE_Failure;
             }
         }
@@ -2643,33 +3697,33 @@ CPLErr GTiffRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /*      Special case for YCbCr subsampled data.                         */
 /* -------------------------------------------------------------------- */
 #ifdef notdef
-    if( (eBandInterp == GCI_YCbCr_YBand 
+    if( (eBandInterp == GCI_YCbCr_YBand
          || eBandInterp == GCI_YCbCr_CbBand
          ||  eBandInterp == GCI_YCbCr_CrBand)
         && poGDS->nBitsPerSample == 8 )
     {
-	uint16 hs, vs;
+        uint16 hs, vs;
         int iX, iY;
 
-	TIFFGetFieldDefaulted( poGDS->hTIFF, TIFFTAG_YCBCRSUBSAMPLING, 
+        TIFFGetFieldDefaulted( poGDS->hTIFF, TIFFTAG_YCBCRSUBSAMPLING,
                                &hs, &vs);
-        
+
         for( iY = 0; iY < nBlockYSize; iY++ )
         {
             for( iX = 0; iX < nBlockXSize; iX++ )
             {
                 int iBlock = (iY / vs) * (nBlockXSize/hs) + (iX / hs);
-                GByte *pabySrcBlock = poGDS->pabyBlockBuf + 
+                GByte *pabySrcBlock = poGDS->pabyBlockBuf +
                     (vs * hs + 2) * iBlock;
-                
+
                 if( eBandInterp == GCI_YCbCr_YBand )
-                    ((GByte *)pImage)[iY*nBlockXSize + iX] = 
+                    ((GByte *)pImage)[iY*nBlockXSize + iX] =
                         pabySrcBlock[(iX % hs) + (iY % vs) * hs];
                 else if( eBandInterp == GCI_YCbCr_CbBand )
-                    ((GByte *)pImage)[iY*nBlockXSize + iX] = 
+                    ((GByte *)pImage)[iY*nBlockXSize + iX] =
                         pabySrcBlock[vs * hs + 0];
                 else if( eBandInterp == GCI_YCbCr_CrBand )
-                    ((GByte *)pImage)[iY*nBlockXSize + iX] = 
+                    ((GByte *)pImage)[iY*nBlockXSize + iX] =
                         pabySrcBlock[vs * hs + 1];
             }
         }
@@ -2677,91 +3731,13 @@ CPLErr GTiffRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         return CE_None;
     }
 #endif
-        
-/* -------------------------------------------------------------------- */
-/*      Handle simple case of eight bit data, and pixel interleaving.   */
-/* -------------------------------------------------------------------- */
-    if( poGDS->nBitsPerSample == 8 )
-    {
-        int	i, nBlockPixels;
-        GByte	*pabyImage;
-        GByte   *pabyImageDest = (GByte*)pImage;
-        int      nBands = poGDS->nBands;
-
-        pabyImage = poGDS->pabyBlockBuf + nBand - 1;
-
-        nBlockPixels = nBlockXSize * nBlockYSize;
 
-/* ==================================================================== */
-/*     Optimization for high number of words to transfer and some       */
-/*     typical band numbers : we unroll the loop.                       */
-/* ==================================================================== */
-#define COPY_TO_DST_BUFFER(nBands) \
-        if (nBlockPixels > 100) \
-        { \
-            for ( i = nBlockPixels / 16; i != 0; i -- ) \
-            { \
-                pabyImageDest[0] = pabyImage[0*nBands]; \
-                pabyImageDest[1] = pabyImage[1*nBands]; \
-                pabyImageDest[2] = pabyImage[2*nBands]; \
-                pabyImageDest[3] = pabyImage[3*nBands]; \
-                pabyImageDest[4] = pabyImage[4*nBands]; \
-                pabyImageDest[5] = pabyImage[5*nBands]; \
-                pabyImageDest[6] = pabyImage[6*nBands]; \
-                pabyImageDest[7] = pabyImage[7*nBands]; \
-                pabyImageDest[8] = pabyImage[8*nBands]; \
-                pabyImageDest[9] = pabyImage[9*nBands]; \
-                pabyImageDest[10] = pabyImage[10*nBands]; \
-                pabyImageDest[11] = pabyImage[11*nBands]; \
-                pabyImageDest[12] = pabyImage[12*nBands]; \
-                pabyImageDest[13] = pabyImage[13*nBands]; \
-                pabyImageDest[14] = pabyImage[14*nBands]; \
-                pabyImageDest[15] = pabyImage[15*nBands]; \
-                pabyImageDest += 16; \
-                pabyImage += 16*nBands; \
-            } \
-            nBlockPixels = nBlockPixels % 16; \
-        } \
-        for( i = 0; i < nBlockPixels; i++ ) \
-        { \
-            pabyImageDest[i] = *pabyImage; \
-            pabyImage += nBands; \
-        }
-
-        switch (nBands)
-        {
-            case 3:  COPY_TO_DST_BUFFER(3); break;
-            case 4:  COPY_TO_DST_BUFFER(4); break;
-            default:
-            {
-                for( i = 0; i < nBlockPixels; i++ )
-                {
-                    pabyImageDest[i] = *pabyImage;
-                    pabyImage += nBands;
-                }
-            }
-        }
-#undef COPY_TO_DST_BUFFER
-    }
-
-    else
-    {
-        int	i, nBlockPixels, nWordBytes;
-        GByte	*pabyImage;
-
-        nWordBytes = poGDS->nBitsPerSample / 8;
-        pabyImage = poGDS->pabyBlockBuf + (nBand - 1) * nWordBytes;
+    int nWordBytes = poGDS->nBitsPerSample / 8;
+    GByte* pabyImage = poGDS->pabyBlockBuf + (nBand - 1) * nWordBytes;
 
-        nBlockPixels = nBlockXSize * nBlockYSize;
-        for( i = 0; i < nBlockPixels; i++ )
-        {
-            for( int j = 0; j < nWordBytes; j++ )
-            {
-                ((GByte *) pImage)[i*nWordBytes + j] = pabyImage[j];
-            }
-            pabyImage += poGDS->nBands * nWordBytes;
-        }
-    }
+    GDALCopyWords(pabyImage, eDataType, poGDS->nBands * nWordBytes,
+                  pImage, eDataType, nWordBytes,
+                  nBlockXSize * nBlockYSize);
 
     if (eErr == CE_None)
         eErr = FillCacheForOtherBands(nBlockXOff, nBlockYOff);
@@ -2832,7 +3808,7 @@ CPLErr GTiffRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                                      void * pImage )
 
 {
-    int		nBlockId;
+    int nBlockId;
     CPLErr      eErr = CE_None;
 
     if (poGDS->bDebugDontWriteBlocks)
@@ -2873,7 +3849,7 @@ CPLErr GTiffRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
 /*      Handle case of pixel interleaved (PLANARCONFIG_CONTIG) images.  */
 /* -------------------------------------------------------------------- */
     nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
-        
+
     eErr = poGDS->LoadBlockBuf( nBlockId );
     if( eErr != CE_None )
         return eErr;
@@ -2883,7 +3859,7 @@ CPLErr GTiffRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
 /*      out any other bands that are dirty in our cache.  This is       */
 /*      especially helpful when writing compressed blocks.              */
 /* -------------------------------------------------------------------- */
-    int iBand; 
+    int iBand;
     int nWordBytes = poGDS->nBitsPerSample / 8;
     int nBands = poGDS->nBands;
 
@@ -2911,74 +3887,12 @@ CPLErr GTiffRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
             pabyThisImage = (GByte *) poBlock->GetDataRef();
         }
 
-        int i, nBlockPixels = nBlockXSize * nBlockYSize;
         GByte *pabyOut = poGDS->pabyBlockBuf + iBand*nWordBytes;
 
-        if (nWordBytes == 1)
-        {
-
-/* ==================================================================== */
-/*     Optimization for high number of words to transfer and some       */
-/*     typical band numbers : we unroll the loop.                       */
-/* ==================================================================== */
-#define COPY_TO_DST_BUFFER(nBands) \
-            if (nBlockPixels > 100) \
-            { \
-                for ( i = nBlockPixels / 16; i != 0; i -- ) \
-                { \
-                    pabyOut[0*nBands] = pabyThisImage[0]; \
-                    pabyOut[1*nBands] = pabyThisImage[1]; \
-                    pabyOut[2*nBands] = pabyThisImage[2]; \
-                    pabyOut[3*nBands] = pabyThisImage[3]; \
-                    pabyOut[4*nBands] = pabyThisImage[4]; \
-                    pabyOut[5*nBands] = pabyThisImage[5]; \
-                    pabyOut[6*nBands] = pabyThisImage[6]; \
-                    pabyOut[7*nBands] = pabyThisImage[7]; \
-                    pabyOut[8*nBands] = pabyThisImage[8]; \
-                    pabyOut[9*nBands] = pabyThisImage[9]; \
-                    pabyOut[10*nBands] = pabyThisImage[10]; \
-                    pabyOut[11*nBands] = pabyThisImage[11]; \
-                    pabyOut[12*nBands] = pabyThisImage[12]; \
-                    pabyOut[13*nBands] = pabyThisImage[13]; \
-                    pabyOut[14*nBands] = pabyThisImage[14]; \
-                    pabyOut[15*nBands] = pabyThisImage[15]; \
-                    pabyThisImage += 16; \
-                    pabyOut += 16*nBands; \
-                } \
-                nBlockPixels = nBlockPixels % 16; \
-            } \
-            for( i = 0; i < nBlockPixels; i++ ) \
-            { \
-                *pabyOut = pabyThisImage[i]; \
-                pabyOut += nBands; \
-            }
-
-            switch (nBands)
-            {
-                case 3:  COPY_TO_DST_BUFFER(3); break;
-                case 4:  COPY_TO_DST_BUFFER(4); break;
-                default:
-                {
-                    for( i = 0; i < nBlockPixels; i++ )
-                    {
-                        *pabyOut = pabyThisImage[i];
-                        pabyOut += nBands;
-                    }
-                }
-            }
-#undef COPY_TO_DST_BUFFER
-        }
-        else
-        {
-            for( i = 0; i < nBlockPixels; i++ )
-            {
-                memcpy( pabyOut, pabyThisImage, nWordBytes );
+        GDALCopyWords(pabyThisImage, eDataType, nWordBytes,
+                      pabyOut, eDataType, nWordBytes * nBands,
+                      nBlockXSize * nBlockYSize);
 
-                pabyOut += nWordBytes * nBands;
-                pabyThisImage += nWordBytes;
-            }
-        }
-        
         if( poBlock != NULL )
         {
             poBlock->MarkClean();
@@ -2998,6 +3912,8 @@ CPLErr GTiffRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
 void GTiffRasterBand::SetDescription( const char *pszDescription )
 
 {
+    poGDS->LoadGeoreferencingAndPamIfNeeded();
+
     if( pszDescription == NULL )
         pszDescription = "";
 
@@ -3010,6 +3926,8 @@ void GTiffRasterBand::SetDescription( const char *pszDescription )
 
 const char *GTiffRasterBand::GetDescription() const
 {
+    poGDS->LoadGeoreferencingAndPamIfNeeded();
+
     return osDescription;
 }
 
@@ -3020,6 +3938,8 @@ const char *GTiffRasterBand::GetDescription() const
 double GTiffRasterBand::GetOffset( int *pbSuccess )
 
 {
+    poGDS->LoadGeoreferencingAndPamIfNeeded();
+
     if( pbSuccess )
         *pbSuccess = bHaveOffsetScale;
     return dfOffset;
@@ -3032,6 +3952,8 @@ double GTiffRasterBand::GetOffset( int *pbSuccess )
 CPLErr GTiffRasterBand::SetOffset( double dfNewValue )
 
 {
+    poGDS->LoadGeoreferencingAndPamIfNeeded();
+
     if( !bHaveOffsetScale || dfNewValue != dfOffset )
         poGDS->bMetadataChanged = TRUE;
 
@@ -3047,6 +3969,8 @@ CPLErr GTiffRasterBand::SetOffset( double dfNewValue )
 double GTiffRasterBand::GetScale( int *pbSuccess )
 
 {
+    poGDS->LoadGeoreferencingAndPamIfNeeded();
+
     if( pbSuccess )
         *pbSuccess = bHaveOffsetScale;
     return dfScale;
@@ -3059,6 +3983,8 @@ double GTiffRasterBand::GetScale( int *pbSuccess )
 CPLErr GTiffRasterBand::SetScale( double dfNewValue )
 
 {
+    poGDS->LoadGeoreferencingAndPamIfNeeded();
+
     if( !bHaveOffsetScale || dfNewValue != dfScale )
         poGDS->bMetadataChanged = TRUE;
 
@@ -3074,6 +4000,8 @@ CPLErr GTiffRasterBand::SetScale( double dfNewValue )
 const char* GTiffRasterBand::GetUnitType()
 
 {
+    poGDS->LoadGeoreferencingAndPamIfNeeded();
+
     return osUnitType.c_str();
 }
 
@@ -3084,6 +4012,8 @@ const char* GTiffRasterBand::GetUnitType()
 CPLErr GTiffRasterBand::SetUnitType( const char* pszNewValue )
 
 {
+    poGDS->LoadGeoreferencingAndPamIfNeeded();
+
     CPLString osNewValue(pszNewValue ? pszNewValue : "");
     if( osNewValue.compare(osUnitType) != 0 )
         poGDS->bMetadataChanged = TRUE;
@@ -3098,6 +4028,8 @@ CPLErr GTiffRasterBand::SetUnitType( const char* pszNewValue )
 
 char **GTiffRasterBand::GetMetadataDomainList()
 {
+    poGDS->LoadGeoreferencingAndPamIfNeeded();
+
     return CSLDuplicate(oGTiffMDMD.GetDomainList());
 }
 
@@ -3108,6 +4040,11 @@ char **GTiffRasterBand::GetMetadataDomainList()
 char **GTiffRasterBand::GetMetadata( const char * pszDomain )
 
 {
+    if( pszDomain == NULL || !EQUAL(pszDomain, "IMAGE_STRUCTURE") )
+    {
+        poGDS->LoadGeoreferencingAndPamIfNeeded();
+    }
+
     return oGTiffMDMD.GetMetadata( pszDomain );
 }
 
@@ -3118,6 +4055,8 @@ char **GTiffRasterBand::GetMetadata( const char * pszDomain )
 CPLErr GTiffRasterBand::SetMetadata( char ** papszMD, const char *pszDomain )
 
 {
+    poGDS->LoadGeoreferencingAndPamIfNeeded();
+
     if( poGDS->bStreamingOut && poGDS->bCrystalized )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
@@ -3144,10 +4083,15 @@ CPLErr GTiffRasterBand::SetMetadata( char ** papszMD, const char *pszDomain )
 /*                          GetMetadataItem()                           */
 /************************************************************************/
 
-const char *GTiffRasterBand::GetMetadataItem( const char * pszName, 
+const char *GTiffRasterBand::GetMetadataItem( const char * pszName,
                                               const char * pszDomain )
 
 {
+    if( pszDomain == NULL || !EQUAL(pszDomain, "IMAGE_STRUCTURE") )
+    {
+        poGDS->LoadGeoreferencingAndPamIfNeeded();
+    }
+
     if( pszName != NULL && pszDomain != NULL && EQUAL(pszDomain, "TIFF") )
     {
         int nBlockXOff, nBlockYOff;
@@ -3174,8 +4118,8 @@ const char *GTiffRasterBand::GetMetadataItem( const char * pszName,
             if( !poGDS->SetDirectory() )
                 return NULL;
 
-            int nBlocksPerRow = DIV_ROUND_UP(poGDS->nRasterXSize, poGDS->nBlockXSize);
-            int nBlocksPerColumn = DIV_ROUND_UP(poGDS->nRasterYSize, poGDS->nBlockYSize);
+            nBlocksPerRow = DIV_ROUND_UP(poGDS->nRasterXSize, poGDS->nBlockXSize);
+            nBlocksPerColumn = DIV_ROUND_UP(poGDS->nRasterYSize, poGDS->nBlockYSize);
             if( nBlockXOff < 0 || nBlockXOff >= nBlocksPerRow ||
                 nBlockYOff < 0 || nBlockYOff >= nBlocksPerColumn )
                 return NULL;
@@ -3193,9 +4137,9 @@ const char *GTiffRasterBand::GetMetadataItem( const char * pszName,
 
             toff_t *panOffsets = NULL;
             TIFF* hTIFF = poGDS->hTIFF;
-            if( (( TIFFIsTiled( hTIFF ) 
+            if( (( TIFFIsTiled( hTIFF )
                 && TIFFGetField( hTIFF, TIFFTAG_TILEOFFSETS, &panOffsets ) )
-                || ( !TIFFIsTiled( hTIFF ) 
+                || ( !TIFFIsTiled( hTIFF )
                 && TIFFGetField( hTIFF, TIFFTAG_STRIPOFFSETS, &panOffsets ) )) &&
                 panOffsets != NULL )
             {
@@ -3211,8 +4155,8 @@ const char *GTiffRasterBand::GetMetadataItem( const char * pszName,
             if( !poGDS->SetDirectory() )
                 return NULL;
 
-            int nBlocksPerRow = DIV_ROUND_UP(poGDS->nRasterXSize, poGDS->nBlockXSize);
-            int nBlocksPerColumn = DIV_ROUND_UP(poGDS->nRasterYSize, poGDS->nBlockYSize);
+            nBlocksPerRow = DIV_ROUND_UP(poGDS->nRasterXSize, poGDS->nBlockXSize);
+            nBlocksPerColumn = DIV_ROUND_UP(poGDS->nRasterYSize, poGDS->nBlockYSize);
             if( nBlockXOff < 0 || nBlockXOff >= nBlocksPerRow ||
                 nBlockYOff < 0 || nBlockYOff >= nBlocksPerColumn )
                 return NULL;
@@ -3230,9 +4174,9 @@ const char *GTiffRasterBand::GetMetadataItem( const char * pszName,
 
             toff_t *panByteCounts = NULL;
             TIFF* hTIFF = poGDS->hTIFF;
-            if( (( TIFFIsTiled( hTIFF ) 
+            if( (( TIFFIsTiled( hTIFF )
                 && TIFFGetField( hTIFF, TIFFTAG_TILEBYTECOUNTS, &panByteCounts ) )
-                || ( !TIFFIsTiled( hTIFF ) 
+                || ( !TIFFIsTiled( hTIFF )
                 && TIFFGetField( hTIFF, TIFFTAG_STRIPBYTECOUNTS, &panByteCounts ) )) &&
                 panByteCounts != NULL )
             {
@@ -3251,11 +4195,13 @@ const char *GTiffRasterBand::GetMetadataItem( const char * pszName,
 /*                          SetMetadataItem()                           */
 /************************************************************************/
 
-CPLErr GTiffRasterBand::SetMetadataItem( const char *pszName, 
+CPLErr GTiffRasterBand::SetMetadataItem( const char *pszName,
                                          const char *pszValue,
                                          const char *pszDomain )
 
 {
+    poGDS->LoadGeoreferencingAndPamIfNeeded();
+
     if( poGDS->bStreamingOut && poGDS->bCrystalized )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
@@ -3282,6 +4228,8 @@ CPLErr GTiffRasterBand::SetMetadataItem( const char *pszName,
 GDALColorInterp GTiffRasterBand::GetColorInterpretation()
 
 {
+    poGDS->LoadGeoreferencingAndPamIfNeeded();
+
     return eBandInterp;
 }
 
@@ -3316,6 +4264,8 @@ static uint16 GTiffGetAlphaValue(const char* pszValue, uint16 nDefault)
 CPLErr GTiffRasterBand::SetColorInterpretation( GDALColorInterp eInterp )
 
 {
+    poGDS->LoadGeoreferencingAndPamIfNeeded();
+
     if( eInterp == eBandInterp )
         return CE_None;
 
@@ -3329,9 +4279,9 @@ CPLErr GTiffRasterBand::SetColorInterpretation( GDALColorInterp eInterp )
     }
 
     /* greyscale + alpha */
-    else if( eInterp == GCI_AlphaBand 
-        && nBand == 2 
-        && poGDS->nSamplesPerPixel == 2 
+    if( eInterp == GCI_AlphaBand
+        && nBand == 2
+        && poGDS->nSamplesPerPixel == 2
         && poGDS->nPhotometric == PHOTOMETRIC_MINISBLACK )
     {
         uint16 v[1];
@@ -3342,75 +4292,147 @@ CPLErr GTiffRasterBand::SetColorInterpretation( GDALColorInterp eInterp )
         return CE_None;
     }
 
-    /* RGB + alpha */
-    else if( eInterp == GCI_AlphaBand 
-             && nBand == 4 
-             && poGDS->nSamplesPerPixel == 4
-             && poGDS->nPhotometric == PHOTOMETRIC_RGB )
+    /* Try to autoset TIFFTAG_PHOTOMETRIC = PHOTOMETRIC_RGB if possible */
+    if( poGDS->nBands >= 3 &&
+        poGDS->nCompression != COMPRESSION_JPEG &&
+        poGDS->nPhotometric != PHOTOMETRIC_RGB &&
+        CSLFetchNameValue( poGDS->papszCreationOptions, "PHOTOMETRIC") == NULL &&
+        ((nBand == 1 && eInterp == GCI_RedBand) ||
+         (nBand == 2 && eInterp == GCI_GreenBand) ||
+         (nBand == 3 && eInterp == GCI_BlueBand)) )
     {
-        uint16 v[1];
-        v[0] = GTiffGetAlphaValue(CPLGetConfigOption("GTIFF_ALPHA", NULL),
-                                  DEFAULT_ALPHA_TYPE);
+        if( poGDS->GetRasterBand(1)->GetColorInterpretation() == GCI_RedBand &&
+            poGDS->GetRasterBand(2)->GetColorInterpretation() == GCI_GreenBand &&
+            poGDS->GetRasterBand(3)->GetColorInterpretation() == GCI_BlueBand )
+        {
+            poGDS->nPhotometric = PHOTOMETRIC_RGB;
+            TIFFSetField(poGDS->hTIFF, TIFFTAG_PHOTOMETRIC, poGDS->nPhotometric);
 
-        TIFFSetField(poGDS->hTIFF, TIFFTAG_EXTRASAMPLES, 1, v);
+            /* We need to update the number of extra samples */
+            uint16 *v;
+            uint16 count = 0;
+            uint16 nNewExtraSamplesCount = static_cast<uint16>(poGDS->nBands - 3);
+            if( poGDS->nBands >= 4 &&
+                TIFFGetField( poGDS->hTIFF, TIFFTAG_EXTRASAMPLES, &count, &v ) &&
+                count > nNewExtraSamplesCount )
+            {
+                uint16* pasNewExtraSamples =
+                    (uint16*)CPLMalloc( nNewExtraSamplesCount * sizeof(uint16) );
+                memcpy( pasNewExtraSamples, v + count - nNewExtraSamplesCount,
+                        nNewExtraSamplesCount * sizeof(uint16) );
+
+                TIFFSetField(poGDS->hTIFF, TIFFTAG_EXTRASAMPLES, nNewExtraSamplesCount, pasNewExtraSamples);
+
+                CPLFree(pasNewExtraSamples);
+            }
+        }
+        poGDS->bCheckIfColorInterpMustGoToPamAtCrystalization = true;
         return CE_None;
     }
-    
-    else
+
+    // On the contrary, cancel the above if needed
+    if( poGDS->nCompression != COMPRESSION_JPEG &&
+        poGDS->nPhotometric == PHOTOMETRIC_RGB &&
+        CSLFetchNameValue( poGDS->papszCreationOptions, "PHOTOMETRIC") == NULL &&
+        ((nBand == 1 && eInterp != GCI_RedBand) ||
+         (nBand == 2 && eInterp != GCI_GreenBand) ||
+         (nBand == 3 && eInterp != GCI_BlueBand)) )
     {
-        /* Try to autoset TIFFTAG_PHOTOMETRIC = PHOTOMETRIC_RGB if possible */
-        if( poGDS->nCompression != COMPRESSION_JPEG &&
-            poGDS->nSetPhotometricFromBandColorInterp >= 0 &&
-            CSLFetchNameValue( poGDS->papszCreationOptions, "PHOTOMETRIC") == NULL &&
-            (poGDS->nBands == 3 || poGDS->nBands == 4) &&
-            ((nBand == 1 && eInterp == GCI_RedBand) ||
-             (nBand == 2 && eInterp == GCI_GreenBand) ||
-             (nBand == 3 && eInterp == GCI_BlueBand) ||
-             (nBand == 4 && eInterp == GCI_AlphaBand)) )
-        {
-            poGDS->nSetPhotometricFromBandColorInterp ++;
-            if( poGDS->nSetPhotometricFromBandColorInterp == poGDS->nBands )
-            {
-                poGDS->nPhotometric = PHOTOMETRIC_RGB;
-                TIFFSetField(poGDS->hTIFF, TIFFTAG_PHOTOMETRIC, poGDS->nPhotometric);
-                if( poGDS->nSetPhotometricFromBandColorInterp == 4 )
-                {
-                    uint16 v[1];
-                    v[0] = GTiffGetAlphaValue(CPLGetConfigOption("GTIFF_ALPHA", NULL),
-                                            DEFAULT_ALPHA_TYPE);
+        poGDS->nPhotometric = PHOTOMETRIC_MINISBLACK;
+        TIFFSetField(poGDS->hTIFF, TIFFTAG_PHOTOMETRIC, poGDS->nPhotometric);
 
-                    TIFFSetField(poGDS->hTIFF, TIFFTAG_EXTRASAMPLES, 1, v);
+        /* We need to update the number of extra samples */
+        uint16 *v;
+        uint16 count = 0;
+        uint16 nNewExtraSamplesCount = static_cast<uint16>(poGDS->nBands - 1);
+        if( poGDS->nBands >= 2 )
+        {
+            TIFFGetField( poGDS->hTIFF, TIFFTAG_EXTRASAMPLES, &count, &v );
+            if( nNewExtraSamplesCount > count )
+            {
+                uint16* pasNewExtraSamples =
+                    (uint16*)CPLMalloc( nNewExtraSamplesCount * sizeof(uint16) );
+                for(int i=0; i < (int)(nNewExtraSamplesCount - count); i++)
+                    pasNewExtraSamples[i] = EXTRASAMPLE_UNSPECIFIED;
+                if (count > 0 )
+                {
+                    memcpy( pasNewExtraSamples + nNewExtraSamplesCount - count, v,
+                            count * sizeof(uint16) );
                 }
+
+                TIFFSetField(poGDS->hTIFF, TIFFTAG_EXTRASAMPLES, nNewExtraSamplesCount, pasNewExtraSamples);
+
+                CPLFree(pasNewExtraSamples);
             }
-            return CE_None;
         }
-        else
+
+        poGDS->bCheckIfColorInterpMustGoToPamAtCrystalization = true;
+    }
+
+    /* Mark alpha band in extrasamples */
+    if( eInterp == GCI_AlphaBand )
+    {
+        uint16 *v;
+        uint16 count = 0;
+        if( TIFFGetField( poGDS->hTIFF, TIFFTAG_EXTRASAMPLES, &count, &v ) )
         {
-            if( poGDS->nPhotometric != PHOTOMETRIC_MINISBLACK &&
-                CSLFetchNameValue( poGDS->papszCreationOptions, "PHOTOMETRIC") == NULL )
-            {
-                poGDS->nPhotometric = PHOTOMETRIC_MINISBLACK;
-                TIFFSetField(poGDS->hTIFF, TIFFTAG_PHOTOMETRIC, poGDS->nPhotometric);
-            }
-            if( poGDS->nSetPhotometricFromBandColorInterp > 0 )
+            int nBaseSamples = poGDS->nSamplesPerPixel - count;
+
+            for(int i=1;i<=poGDS->nBands;i++)
             {
-                for(int i=1;i<=poGDS->nBands;i++)
+                if( i != nBand &&
+                    poGDS->GetRasterBand(i)->GetColorInterpretation()  == GCI_AlphaBand )
                 {
-                    if( i != nBand )
+                    if( i == nBaseSamples + 1 &&
+                        CSLFetchNameValue(poGDS->papszCreationOptions, "ALPHA") != NULL )
+                    {
+                        CPLError(CE_Warning, CPLE_AppDefined,
+                                "Band %d was already identified as alpha band, "
+                                "and band %d is now marked as alpha too. "
+                                "Presumably ALPHA creation option is not needed",
+                                i, nBand);
+                    }
+                    else
                     {
-                        ((GDALPamRasterBand*)poGDS->GetRasterBand(i))->GDALPamRasterBand::SetColorInterpretation(
-                            poGDS->GetRasterBand(i)->GetColorInterpretation() );
-                        CPLDebug("GTIFF", "ColorInterpretation %s for band %d goes to PAM instead of TIFF tag",
-                                 GDALGetColorInterpretationName(poGDS->GetRasterBand(i)->GetColorInterpretation()), i);
+                        CPLError(CE_Warning, CPLE_AppDefined,
+                                "Band %d was already identified as alpha band, "
+                                "and band %d is now marked as alpha too",
+                                i, nBand);
                     }
                 }
             }
-            poGDS->nSetPhotometricFromBandColorInterp = -1;
-            CPLDebug("GTIFF", "ColorInterpretation %s for band %d goes to PAM instead of TIFF tag",
-                     GDALGetColorInterpretationName(eInterp), nBand);
-            return GDALPamRasterBand::SetColorInterpretation( eInterp );
+
+            if( nBand > nBaseSamples && nBand - nBaseSamples - 1 < count )
+            {
+                // We need to allocate a new array as (current) libtiff
+                // versions will not like that we reuse the array we got from
+                // TIFFGetField().
+
+                uint16* pasNewExtraSamples =
+                    (uint16*)CPLMalloc( count * sizeof(uint16) );
+                memcpy( pasNewExtraSamples, v, count * sizeof(uint16) );
+                pasNewExtraSamples[nBand - nBaseSamples - 1] =
+                    GTiffGetAlphaValue(CPLGetConfigOption("GTIFF_ALPHA", NULL),
+                                            DEFAULT_ALPHA_TYPE);
+
+                TIFFSetField(poGDS->hTIFF, TIFFTAG_EXTRASAMPLES, count, pasNewExtraSamples);
+
+                CPLFree(pasNewExtraSamples);
+
+                return CE_None;
+            }
         }
     }
+
+    if( poGDS->nPhotometric != PHOTOMETRIC_MINISBLACK &&
+        CSLFetchNameValue( poGDS->papszCreationOptions, "PHOTOMETRIC") == NULL )
+    {
+        poGDS->nPhotometric = PHOTOMETRIC_MINISBLACK;
+        TIFFSetField(poGDS->hTIFF, TIFFTAG_PHOTOMETRIC, poGDS->nPhotometric);
+    }
+
+    poGDS->bCheckIfColorInterpMustGoToPamAtCrystalization = true;
+    return CE_None;
 }
 
 /************************************************************************/
@@ -3420,6 +4442,8 @@ CPLErr GTiffRasterBand::SetColorInterpretation( GDALColorInterp eInterp )
 GDALColorTable *GTiffRasterBand::GetColorTable()
 
 {
+    poGDS->LoadGeoreferencingAndPamIfNeeded();
+
     if( nBand == 1 )
         return poGDS->poColorTable;
     else
@@ -3433,33 +4457,36 @@ GDALColorTable *GTiffRasterBand::GetColorTable()
 CPLErr GTiffRasterBand::SetColorTable( GDALColorTable * poCT )
 
 {
+    poGDS->LoadGeoreferencingAndPamIfNeeded();
+
 /* -------------------------------------------------------------------- */
 /*      Check if this is even a candidate for applying a PCT.           */
 /* -------------------------------------------------------------------- */
     if( nBand != 1)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "SetColorTable() can only be called on band 1." );
         return CE_Failure;
     }
 
     if( poGDS->nSamplesPerPixel != 1 && poGDS->nSamplesPerPixel != 2)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "SetColorTable() not supported for multi-sample TIFF files." );
         return CE_Failure;
     }
-        
+
     if( eDataType != GDT_Byte && eDataType != GDT_UInt16 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
-                  "SetColorTable() only supported for Byte or UInt16 bands in TIFF format." );
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "SetColorTable() only supported for Byte or UInt16 bands "
+                  "in TIFF format." );
         return CE_Failure;
     }
 
 /* -------------------------------------------------------------------- */
 /*      We are careful about calling SetDirectory() to avoid            */
-/*      prematurely crystalizing the directory.  (#2820)                */
+/*      prematurely crystallizing the directory.  (#2820)               */
 /* -------------------------------------------------------------------- */
     if( poGDS->bCrystalized )
     {
@@ -3472,16 +4499,16 @@ CPLErr GTiffRasterBand::SetColorTable( GDALColorTable * poCT )
 /* -------------------------------------------------------------------- */
     if( poCT == NULL || poCT->GetColorEntryCount() == 0 )
     {
-        TIFFSetField( poGDS->hTIFF, TIFFTAG_PHOTOMETRIC, 
+        TIFFSetField( poGDS->hTIFF, TIFFTAG_PHOTOMETRIC,
                       PHOTOMETRIC_MINISBLACK );
 
 #ifdef HAVE_UNSETFIELD
         TIFFUnsetField( poGDS->hTIFF, TIFFTAG_COLORMAP );
 #else
-        CPLDebug( "GTiff", 
+        CPLDebug( "GTiff",
                   "TIFFUnsetField() not supported, colormap may not be cleared." );
 #endif
-        
+
         if( poGDS->poColorTable )
         {
             delete poGDS->poColorTable;
@@ -3512,9 +4539,9 @@ CPLErr GTiffRasterBand::SetColorTable( GDALColorTable * poCT )
         if( iColor < poCT->GetColorEntryCount() )
         {
             GDALColorEntry  sRGB;
-            
+
             poCT->GetColorEntryAsRGB( iColor, &sRGB );
-            
+
             panTRed[iColor] = (unsigned short) (257 * sRGB.c1);
             panTGreen[iColor] = (unsigned short) (257 * sRGB.c2);
             panTBlue[iColor] = (unsigned short) (257 * sRGB.c3);
@@ -3557,6 +4584,8 @@ CPLErr GTiffRasterBand::SetColorTable( GDALColorTable * poCT )
 double GTiffRasterBand::GetNoDataValue( int * pbSuccess )
 
 {
+    poGDS->LoadGeoreferencingAndPamIfNeeded();
+
     if( bNoDataSet )
     {
         if( pbSuccess )
@@ -3564,7 +4593,7 @@ double GTiffRasterBand::GetNoDataValue( int * pbSuccess )
 
         return dfNoDataValue;
     }
-   
+
     if( poGDS->bNoDataSet )
     {
         if( pbSuccess )
@@ -3583,6 +4612,8 @@ double GTiffRasterBand::GetNoDataValue( int * pbSuccess )
 CPLErr GTiffRasterBand::SetNoDataValue( double dfNoData )
 
 {
+    poGDS->LoadGeoreferencingAndPamIfNeeded();
+
     if( poGDS->bNoDataSet && poGDS->dfNoDataValue == dfNoData )
         return CE_None;
     if( poGDS->bStreamingOut && poGDS->bCrystalized )
@@ -3603,6 +4634,34 @@ CPLErr GTiffRasterBand::SetNoDataValue( double dfNoData )
 }
 
 /************************************************************************/
+/*                        DeleteNoDataValue()                           */
+/************************************************************************/
+
+CPLErr GTiffRasterBand::DeleteNoDataValue()
+
+{
+    poGDS->LoadGeoreferencingAndPamIfNeeded();
+
+    if( !poGDS->bNoDataSet )
+        return CE_None;
+    if( poGDS->bStreamingOut && poGDS->bCrystalized )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Cannot modify nodata at that point in a streamed output file");
+        return CE_Failure;
+    }
+
+    poGDS->bNoDataSet = FALSE;
+    poGDS->dfNoDataValue = -9999.0;
+
+    poGDS->bNoDataChanged = TRUE;
+
+    bNoDataSet = FALSE;
+    dfNoDataValue = -9999.0;;
+    return CE_None;
+}
+
+/************************************************************************/
 /*                             NullBlock()                              */
 /*                                                                      */
 /*      Set the block data to the null value if it is set, or zero      */
@@ -3615,9 +4674,9 @@ void GTiffRasterBand::NullBlock( void *pData )
     int nWords = nBlockXSize * nBlockYSize;
     int nChunkSize = MAX(1,GDALGetDataTypeSize(eDataType)/8);
 
-    int bNoDataSet;
-    double dfNoData = GetNoDataValue( &bNoDataSet );
-    if( !bNoDataSet )
+    int bNoDataSetIn;
+    double dfNoData = GetNoDataValue( &bNoDataSetIn );
+    if( !bNoDataSetIn )
     {
 #ifdef ESRI_BUILD
         if ( poGDS->nBitsPerSample >= 2 )
@@ -3655,8 +4714,8 @@ int GTiffRasterBand::GetOverviewCount()
         if( nOverviewCount > 0 )
             return nOverviewCount;
 
-        /* Implict JPEG overviews are normally hidden, except when doing */
-        /* IRasterIO() operations */
+        /* Implicit JPEG overviews are normally hidden, except when doing */
+        /* IRasterIO() operations. */
         if( poGDS->nJPEGOverviewVisibilityFlag )
             return poGDS->GetJPEGOverviewCount();
         else
@@ -3745,7 +4804,7 @@ GDALRasterBand *GTiffRasterBand::GetMaskBand()
 /* ==================================================================== */
 /************************************************************************/
 
-class GTiffSplitBand : public GTiffRasterBand
+class GTiffSplitBand CPL_FINAL : public GTiffRasterBand
 {
     friend class GTiffDataset;
 
@@ -3762,8 +4821,8 @@ class GTiffSplitBand : public GTiffRasterBand
 /*                           GTiffSplitBand()                           */
 /************************************************************************/
 
-GTiffSplitBand::GTiffSplitBand( GTiffDataset *poDS, int nBand )
-        : GTiffRasterBand( poDS, nBand )
+GTiffSplitBand::GTiffSplitBand( GTiffDataset *poDSIn, int nBandIn )
+        : GTiffRasterBand( poDSIn, nBandIn )
 
 {
     nBlockXSize = poDS->GetRasterXSize();
@@ -3787,7 +4846,7 @@ CPLErr GTiffSplitBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
 {
     (void) nBlockXOff;
-    
+
     /* Optimization when reading the same line in a contig multi-band TIFF */
     if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG && poGDS->nBands > 1 &&
         poGDS->nLastLineRead == nBlockYOff )
@@ -3797,17 +4856,15 @@ CPLErr GTiffSplitBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
     if (!poGDS->SetDirectory())
         return CE_Failure;
-        
+
     if (poGDS->nPlanarConfig == PLANARCONFIG_CONTIG &&
         poGDS->nBands > 1)
     {
         if (poGDS->pabyBlockBuf == NULL)
         {
-            poGDS->pabyBlockBuf = (GByte *) VSIMalloc(TIFFScanlineSize(poGDS->hTIFF));
+            poGDS->pabyBlockBuf = (GByte *) VSI_MALLOC_VERBOSE(TIFFScanlineSize(poGDS->hTIFF));
             if( poGDS->pabyBlockBuf == NULL )
             {
-                CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate " CPL_FRMT_GUIB " bytes.",
-                         (GUIntBig)TIFFScanlineSize(poGDS->hTIFF));
                 return CE_Failure;
             }
         }
@@ -3816,7 +4873,7 @@ CPLErr GTiffSplitBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     {
         CPLAssert(TIFFScanlineSize(poGDS->hTIFF) == nBlockXSize);
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read through to target scanline.                                */
 /* -------------------------------------------------------------------- */
@@ -3831,28 +4888,30 @@ CPLErr GTiffSplitBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             poGDS->nLastLineRead = -1;
         poGDS->nLastBandRead = nBand;
     }
-    
+
     while( poGDS->nLastLineRead < nBlockYOff )
     {
+        ++poGDS->nLastLineRead;
         if( TIFFReadScanline( poGDS->hTIFF,
                               poGDS->pabyBlockBuf ? poGDS->pabyBlockBuf : pImage,
-                              ++poGDS->nLastLineRead,
+                              poGDS->nLastLineRead,
                               (poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE) ? (uint16) (nBand-1) : 0 ) == -1
             && !poGDS->bIgnoreReadErrors )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "TIFFReadScanline() failed." );
+            poGDS->nLastLineRead = -1;
             return CE_Failure;
         }
     }
-    
+
 extract_band_data:
 /* -------------------------------------------------------------------- */
 /*      Extract band data from contig buffer.                           */
 /* -------------------------------------------------------------------- */
     if ( poGDS->pabyBlockBuf != NULL )
     {
-        int	  iPixel, iSrcOffset= nBand - 1, iDstOffset=0;
+        int iPixel, iSrcOffset= nBand - 1, iDstOffset=0;
 
         for( iPixel = 0; iPixel < nBlockXSize; iPixel++, iSrcOffset+=poGDS->nBands, iDstOffset++ )
         {
@@ -3875,7 +4934,7 @@ CPLErr GTiffSplitBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     (void) nBlockYOff;
     (void) pImage;
 
-    CPLError( CE_Failure, CPLE_AppDefined, 
+    CPLError( CE_Failure, CPLE_AppDefined,
               "Split bands are read-only." );
     return CE_Failure;
 }
@@ -3886,7 +4945,7 @@ CPLErr GTiffSplitBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
 /* ==================================================================== */
 /************************************************************************/
 
-class GTiffRGBABand : public GTiffRasterBand
+class GTiffRGBABand CPL_FINAL : public GTiffRasterBand
 {
     friend class GTiffDataset;
 
@@ -3905,8 +4964,8 @@ class GTiffRGBABand : public GTiffRasterBand
 /*                           GTiffRGBABand()                            */
 /************************************************************************/
 
-GTiffRGBABand::GTiffRGBABand( GTiffDataset *poDS, int nBand )
-        : GTiffRasterBand( poDS, nBand )
+GTiffRGBABand::GTiffRGBABand( GTiffDataset *poDSIn, int nBandIn )
+        : GTiffRasterBand( poDSIn, nBandIn )
 
 {
     eDataType = GDT_Byte;
@@ -3919,7 +4978,7 @@ GTiffRGBABand::GTiffRGBABand( GTiffDataset *poDS, int nBand )
 CPLErr GTiffRGBABand::IWriteBlock( int, int, void * )
 
 {
-    CPLError( CE_Failure, CPLE_AppDefined, 
+    CPLError( CE_Failure, CPLE_AppDefined,
               "RGBA interpreted raster bands are read-only." );
     return CE_Failure;
 }
@@ -3932,8 +4991,8 @@ CPLErr GTiffRGBABand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                     void * pImage )
 
 {
-    int			nBlockBufSize, nBlockId;
-    CPLErr		eErr = CE_None;
+    int nBlockBufSize, nBlockId;
+    CPLErr eErr = CE_None;
 
     if (!poGDS->SetDirectory())
         return CE_Failure;
@@ -3947,11 +5006,11 @@ CPLErr GTiffRGBABand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
     if( poGDS->pabyBlockBuf == NULL )
     {
-        poGDS->pabyBlockBuf = (GByte *) VSIMalloc3( 4, nBlockXSize, nBlockYSize );
+        poGDS->pabyBlockBuf = (GByte *) VSI_MALLOC3_VERBOSE( 4, nBlockXSize, nBlockYSize );
         if( poGDS->pabyBlockBuf == NULL )
             return( CE_Failure );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read the strip                                                  */
 /* -------------------------------------------------------------------- */
@@ -3959,8 +5018,8 @@ CPLErr GTiffRGBABand::IReadBlock( int nBlockXOff, int nBlockYOff,
     {
         if( TIFFIsTiled( poGDS->hTIFF ) )
         {
-            if( TIFFReadRGBATile(poGDS->hTIFF, 
-                                 nBlockXOff * nBlockXSize, 
+            if( TIFFReadRGBATile(poGDS->hTIFF,
+                                 nBlockXOff * nBlockXSize,
                                  nBlockYOff * nBlockYSize,
                                  (uint32 *) poGDS->pabyBlockBuf) == -1
                 && !poGDS->bIgnoreReadErrors )
@@ -3968,15 +5027,15 @@ CPLErr GTiffRGBABand::IReadBlock( int nBlockXOff, int nBlockYOff,
                 /* Once TIFFError() is properly hooked, this can go away */
                 CPLError( CE_Failure, CPLE_AppDefined,
                           "TIFFReadRGBATile() failed." );
-                
+
                 memset( poGDS->pabyBlockBuf, 0, nBlockBufSize );
-                
+
                 eErr = CE_Failure;
             }
         }
         else
         {
-            if( TIFFReadRGBAStrip(poGDS->hTIFF, 
+            if( TIFFReadRGBAStrip(poGDS->hTIFF,
                                   nBlockId * nBlockYSize,
                                   (uint32 *) poGDS->pabyBlockBuf) == -1
                 && !poGDS->bIgnoreReadErrors )
@@ -3984,16 +5043,16 @@ CPLErr GTiffRGBABand::IReadBlock( int nBlockXOff, int nBlockYOff,
                 /* Once TIFFError() is properly hooked, this can go away */
                 CPLError( CE_Failure, CPLE_AppDefined,
                           "TIFFReadRGBAStrip() failed." );
-                
+
                 memset( poGDS->pabyBlockBuf, 0, nBlockBufSize );
-                
+
                 eErr = CE_Failure;
             }
         }
     }
 
     poGDS->nLoadedBlock = nBlockId;
-                              
+
 /* -------------------------------------------------------------------- */
 /*      Handle simple case of eight bit data, and pixel interleaving.   */
 /* -------------------------------------------------------------------- */
@@ -4014,12 +5073,12 @@ CPLErr GTiffRGBABand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
     for( iDestLine = 0; iDestLine < nThisBlockYSize; iDestLine++ )
     {
-        int	nSrcOffset;
+        int nSrcOffset;
 
         nSrcOffset = (nThisBlockYSize - iDestLine - 1) * nBlockXSize * 4;
 
         GDALCopyWords( poGDS->pabyBlockBuf + nBO + nSrcOffset, GDT_Byte, 4,
-                       ((GByte *) pImage)+iDestLine*nBlockXSize, GDT_Byte, 1, 
+                       ((GByte *) pImage)+iDestLine*nBlockXSize, GDT_Byte, 1,
                        nBlockXSize );
     }
 
@@ -4069,8 +5128,8 @@ class GTiffOddBitsBand : public GTiffRasterBand
 /*                           GTiffOddBitsBand()                         */
 /************************************************************************/
 
-GTiffOddBitsBand::GTiffOddBitsBand( GTiffDataset *poGDS, int nBand )
-        : GTiffRasterBand( poGDS, nBand )
+GTiffOddBitsBand::GTiffOddBitsBand( GTiffDataset *poGDSIn, int nBandIn )
+        : GTiffRasterBand( poGDSIn, nBandIn )
 
 {
     eDataType = GDT_Byte;
@@ -4095,11 +5154,11 @@ GTiffOddBitsBand::~GTiffOddBitsBand()
 /*                            IWriteBlock()                             */
 /************************************************************************/
 
-CPLErr GTiffOddBitsBand::IWriteBlock( int nBlockXOff, int nBlockYOff, 
+CPLErr GTiffOddBitsBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                                       void *pImage )
 
 {
-    int		nBlockId;
+    int nBlockId;
     CPLErr      eErr = CE_None;
 
     if (poGDS->bWriteErrorInFlushBlockBuf)
@@ -4118,7 +5177,7 @@ CPLErr GTiffOddBitsBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                && nBlockYOff >= 0
                && pImage != NULL );
 
-    if( eDataType == GDT_Float32 && poGDS->nBitsPerSample < 32 )
+    if( eDataType == GDT_Float32 )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "Writing float data with nBitsPerSample < 32 is unsupported");
@@ -4135,7 +5194,7 @@ CPLErr GTiffOddBitsBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
         nBlockId += (nBand-1) * poGDS->nBlocksPerBand;
 
     /* Only read content from disk in the CONTIG case */
-    eErr = poGDS->LoadBlockBuf( nBlockId, 
+    eErr = poGDS->LoadBlockBuf( nBlockId,
                                 poGDS->nPlanarConfig == PLANARCONFIG_CONTIG && poGDS->nBands > 1 );
     if( eErr != CE_None )
         return eErr;
@@ -4149,7 +5208,7 @@ CPLErr GTiffOddBitsBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     if( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE
         || poGDS->nBands == 1 )
     {
-        int	iBit, iPixel, iBitOffset = 0;
+        int iBit, iPixel, iBitOffset = 0;
         int     iX, iY, nBitsPerLine;
 
         // bits per line rounds up to next byte boundary.
@@ -4179,6 +5238,40 @@ CPLErr GTiffOddBitsBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                 continue;
             }
 
+            if (poGDS->nBitsPerSample == 12 )
+            {
+                for( iX = 0; iX < nBlockXSize; iX++ )
+                {
+                    GUInt32 nInWord = ((GUInt16 *) pImage)[iPixel++];
+                    if (nInWord > nMaxVal)
+                    {
+                        nInWord = nMaxVal;
+                        if( !poGDS->bClipWarn )
+                        {
+                            poGDS->bClipWarn = TRUE;
+                            CPLError( CE_Warning, CPLE_AppDefined,
+                                      "One or more pixels clipped to fit %d bit domain.", poGDS->nBitsPerSample );
+                        }
+                    }
+
+                    if( (iBitOffset % 8) == 0 )
+                    {
+                        poGDS->pabyBlockBuf[iBitOffset>>3] = (GByte) (nInWord >> 4);
+                        /* let 4 lower bits to zero as they're going to be overridden by the next word */
+                        poGDS->pabyBlockBuf[(iBitOffset>>3)+1] = (GByte) ((nInWord & 0xf) << 4);
+                    }
+                    else
+                    {
+                        /* we must or to preserve the 4 upper bits written for the previous word */
+                        poGDS->pabyBlockBuf[iBitOffset>>3] |= (GByte) (nInWord >> 8);
+                        poGDS->pabyBlockBuf[(iBitOffset>>3)+1] = (GByte) (nInWord & 0xff);
+                    }
+
+                    iBitOffset += poGDS->nBitsPerSample;
+                }
+                continue;
+            }
+
             for( iX = 0; iX < nBlockXSize; iX++ )
             {
                 GUInt32  nInWord = 0;
@@ -4207,21 +5300,21 @@ CPLErr GTiffOddBitsBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                 {
 /* -------------------------------------------------------------------- */
 /*      Special case for 24bit data which is pre-byteswapped since      */
-/*      the size falls on a byte boundary ... ugg (#2361).              */
+/*      the size falls on a byte boundary ... ugh (#2361).              */
 /* -------------------------------------------------------------------- */
 #ifdef CPL_MSB
-                    poGDS->pabyBlockBuf[(iBitOffset>>3) + 0] = 
+                    poGDS->pabyBlockBuf[(iBitOffset>>3) + 0] =
                         (GByte) nInWord;
-                    poGDS->pabyBlockBuf[(iBitOffset>>3) + 1] = 
+                    poGDS->pabyBlockBuf[(iBitOffset>>3) + 1] =
                         (GByte) (nInWord >> 8);
-                    poGDS->pabyBlockBuf[(iBitOffset>>3) + 2] = 
+                    poGDS->pabyBlockBuf[(iBitOffset>>3) + 2] =
                         (GByte) (nInWord >> 16);
 #else
-                    poGDS->pabyBlockBuf[(iBitOffset>>3) + 0] = 
+                    poGDS->pabyBlockBuf[(iBitOffset>>3) + 0] =
                         (GByte) (nInWord >> 16);
-                    poGDS->pabyBlockBuf[(iBitOffset>>3) + 1] = 
+                    poGDS->pabyBlockBuf[(iBitOffset>>3) + 1] =
                         (GByte) (nInWord >> 8);
-                    poGDS->pabyBlockBuf[(iBitOffset>>3) + 2] = 
+                    poGDS->pabyBlockBuf[(iBitOffset>>3) + 2] =
                         (GByte) nInWord;
 #endif
                     iBitOffset += 24;
@@ -4234,7 +5327,7 @@ CPLErr GTiffOddBitsBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                             poGDS->pabyBlockBuf[iBitOffset>>3] |= (0x80 >>(iBitOffset & 7));
                         iBitOffset++;
                     }
-                } 
+                }
             }
         }
 
@@ -4252,13 +5345,13 @@ CPLErr GTiffOddBitsBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
 /*      out any other bands that are dirty in our cache.  This is       */
 /*      especially helpful when writing compressed blocks.              */
 /* -------------------------------------------------------------------- */
-    int iBand; 
+    int iBand;
 
     for( iBand = 0; iBand < poGDS->nBands; iBand++ )
     {
         const GByte *pabyThisImage = NULL;
         GDALRasterBlock *poBlock = NULL;
-        int	iBit, iPixel, iBitOffset = 0;
+        int iBit, iPixel, iBitOffset = 0;
         int     iPixelBitSkip, iBandBitOffset, iX, iY, nBitsPerLine;
 
         if( iBand+1 == nBand )
@@ -4288,10 +5381,45 @@ CPLErr GTiffOddBitsBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
         if( (nBitsPerLine & 7) != 0 )
             nBitsPerLine = (nBitsPerLine + 7) & (~7);
 
-        iPixel = 0;
-        for( iY = 0; iY < nBlockYSize; iY++ )
-        {
-            iBitOffset = iBandBitOffset + iY * nBitsPerLine;
+        iPixel = 0;
+        for( iY = 0; iY < nBlockYSize; iY++ )
+        {
+            iBitOffset = iBandBitOffset + iY * nBitsPerLine;
+
+            if (poGDS->nBitsPerSample == 12 )
+            {
+                for( iX = 0; iX < nBlockXSize; iX++ )
+                {
+                    GUInt32 nInWord = ((GUInt16 *) pabyThisImage)[iPixel++];
+                    if (nInWord > nMaxVal)
+                    {
+                        nInWord = nMaxVal;
+                        if( !poGDS->bClipWarn )
+                        {
+                            poGDS->bClipWarn = TRUE;
+                            CPLError( CE_Warning, CPLE_AppDefined,
+                                      "One or more pixels clipped to fit %d bit domain.", poGDS->nBitsPerSample );
+                        }
+                    }
+
+                    if( (iBitOffset % 8) == 0 )
+                    {
+                        poGDS->pabyBlockBuf[iBitOffset>>3] = (GByte) (nInWord >> 4);
+                        poGDS->pabyBlockBuf[(iBitOffset>>3)+1] =
+                            (GByte) (((nInWord & 0xf) << 4) | (poGDS->pabyBlockBuf[(iBitOffset>>3)+1] & 0xf));
+                    }
+                    else
+                    {
+                        poGDS->pabyBlockBuf[iBitOffset>>3] =
+                            (GByte) ((poGDS->pabyBlockBuf[iBitOffset>>3] & 0xf0) |
+                                     (nInWord >> 8));
+                        poGDS->pabyBlockBuf[(iBitOffset>>3)+1] = (GByte) (nInWord & 0xff);
+                    }
+
+                    iBitOffset += iPixelBitSkip;
+                }
+                continue;
+            }
 
             for( iX = 0; iX < nBlockXSize; iX++ )
             {
@@ -4321,21 +5449,21 @@ CPLErr GTiffOddBitsBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                 {
 /* -------------------------------------------------------------------- */
 /*      Special case for 24bit data which is pre-byteswapped since      */
-/*      the size falls on a byte boundary ... ugg (#2361).              */
+/*      the size falls on a byte boundary ... ugh (#2361).              */
 /* -------------------------------------------------------------------- */
 #ifdef CPL_MSB
-                    poGDS->pabyBlockBuf[(iBitOffset>>3) + 0] = 
+                    poGDS->pabyBlockBuf[(iBitOffset>>3) + 0] =
                         (GByte) nInWord;
-                    poGDS->pabyBlockBuf[(iBitOffset>>3) + 1] = 
+                    poGDS->pabyBlockBuf[(iBitOffset>>3) + 1] =
                         (GByte) (nInWord >> 8);
-                    poGDS->pabyBlockBuf[(iBitOffset>>3) + 2] = 
+                    poGDS->pabyBlockBuf[(iBitOffset>>3) + 2] =
                         (GByte) (nInWord >> 16);
 #else
-                    poGDS->pabyBlockBuf[(iBitOffset>>3) + 0] = 
+                    poGDS->pabyBlockBuf[(iBitOffset>>3) + 0] =
                         (GByte) (nInWord >> 16);
-                    poGDS->pabyBlockBuf[(iBitOffset>>3) + 1] = 
+                    poGDS->pabyBlockBuf[(iBitOffset>>3) + 1] =
                         (GByte) (nInWord >> 8);
-                    poGDS->pabyBlockBuf[(iBitOffset>>3) + 2] = 
+                    poGDS->pabyBlockBuf[(iBitOffset>>3) + 2] =
                         (GByte) nInWord;
 #endif
                     iBitOffset += 24;
@@ -4348,13 +5476,14 @@ CPLErr GTiffOddBitsBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                             poGDS->pabyBlockBuf[iBitOffset>>3] |= (0x80 >>(iBitOffset & 7));
                         else
                         {
-                            /* We must explictly unset the bit as we may update an existing block */
+                            // We must explicitly unset the bit as we
+                            // may update an existing block.
                             poGDS->pabyBlockBuf[iBitOffset>>3] &= ~(0x80 >>(iBitOffset & 7));
                         }
 
                         iBitOffset++;
                     }
-                } 
+                }
 
                 iBitOffset= iBitOffset + iPixelBitSkip - poGDS->nBitsPerSample;
             }
@@ -4380,8 +5509,8 @@ CPLErr GTiffOddBitsBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                     void * pImage )
 
 {
-    int			nBlockId;
-    CPLErr		eErr = CE_None;
+    int nBlockId;
+    CPLErr eErr = CE_None;
 
     if (!poGDS->SetDirectory())
         return CE_Failure;
@@ -4393,9 +5522,9 @@ CPLErr GTiffOddBitsBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         nBlockId += (nBand-1) * poGDS->nBlocksPerBand;
 
 /* -------------------------------------------------------------------- */
-/*	Handle the case of a strip in a writable file that doesn't	*/
-/*	exist yet, but that we want to read.  Just set to zeros and	*/
-/*	return.								*/
+/*      Handle the case of a strip in a writable file that doesn't      */
+/*      exist yet, but that we want to read.  Just set to zeros and     */
+/*      return.                                                         */
 /* -------------------------------------------------------------------- */
     if( nBlockId != poGDS->nLoadedBlock && !poGDS->IsBlockAvailable(nBlockId) )
     {
@@ -4415,15 +5544,15 @@ CPLErr GTiffOddBitsBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
 /*      Translate 1bit data to eight bit.                               */
 /* -------------------------------------------------------------------- */
-        int	  iDstOffset=0, iLine;
-        register GByte *pabyBlockBuf = poGDS->pabyBlockBuf;
+        int iDstOffset=0, iLine;
+        const GByte * const pabyBlockBuf = poGDS->pabyBlockBuf;
 
         for( iLine = 0; iLine < nBlockYSize; iLine++ )
         {
             int iSrcOffset, iPixel;
 
             iSrcOffset = ((nBlockXSize+7) >> 3) * 8 * iLine;
-            
+
             GByte bSetVal = (poGDS->bPromoteTo8Bits) ? 255 : 1;
 
             for( iPixel = 0; iPixel < nBlockXSize; iPixel++, iSrcOffset++ )
@@ -4439,10 +5568,10 @@ CPLErr GTiffOddBitsBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /*      Handle the case of 16- and 24-bit floating point data as per    */
 /*      TIFF Technical Note 3.                                          */
 /* -------------------------------------------------------------------- */
-    else if( eDataType == GDT_Float32 && poGDS->nBitsPerSample < 32 )
+    else if( eDataType == GDT_Float32 )
     {
-        int	i, nBlockPixels, nWordBytes, iSkipBytes;
-        GByte	*pabyImage;
+        int i, nBlockPixels, nWordBytes, iSkipBytes;
+        GByte *pabyImage;
 
         nWordBytes = poGDS->nBitsPerSample / 8;
         pabyImage = poGDS->pabyBlockBuf + (nBand - 1) * nWordBytes;
@@ -4484,8 +5613,8 @@ CPLErr GTiffOddBitsBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
     else if( poGDS->nBitsPerSample == 12 )
     {
-        int	iPixel, iBitOffset = 0;
-        int     iPixelBitSkip, iBandBitOffset, iX, iY, nBitsPerLine;
+        int iPixel, iBitOffset = 0;
+        int iPixelBitSkip, iBandBitOffset, iX, iY, nBitsPerLine;
 
         if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG )
         {
@@ -4515,16 +5644,16 @@ CPLErr GTiffOddBitsBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                 if( (iBitOffset & 0x7) == 0 )
                 {
                     /* starting on byte boundary */
-                    
-                    ((GUInt16 *) pImage)[iPixel++] = 
+
+                    ((GUInt16 *) pImage)[iPixel++] =
                         (poGDS->pabyBlockBuf[iByte] << 4)
                         | (poGDS->pabyBlockBuf[iByte+1] >> 4);
                 }
                 else
                 {
                     /* starting off byte boundary */
-                    
-                    ((GUInt16 *) pImage)[iPixel++] = 
+
+                    ((GUInt16 *) pImage)[iPixel++] =
                         ((poGDS->pabyBlockBuf[iByte] & 0xf) << 8)
                         | (poGDS->pabyBlockBuf[iByte+1]);
                 }
@@ -4535,11 +5664,11 @@ CPLErr GTiffOddBitsBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
 /* -------------------------------------------------------------------- */
 /*      Special case for 24bit data which is pre-byteswapped since      */
-/*      the size falls on a byte boundary ... ugg (#2361).              */
+/*      the size falls on a byte boundary ... ugh (#2361).              */
 /* -------------------------------------------------------------------- */
     else if( poGDS->nBitsPerSample == 24 )
     {
-        int	iPixel;
+        int iPixel;
         int     iPixelByteSkip, iBandByteOffset, iX, iY, nBytesPerLine;
 
         if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG )
@@ -4558,18 +5687,18 @@ CPLErr GTiffOddBitsBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         iPixel = 0;
         for( iY = 0; iY < nBlockYSize; iY++ )
         {
-            GByte *pabyImage = 
+            GByte *pabyImage =
                 poGDS->pabyBlockBuf + iBandByteOffset + iY * nBytesPerLine;
 
             for( iX = 0; iX < nBlockXSize; iX++ )
             {
 #ifdef CPL_MSB
-                ((GUInt32 *) pImage)[iPixel++] = 
+                ((GUInt32 *) pImage)[iPixel++] =
                     ((GUInt32)*(pabyImage + 2) << 16)
                     | ((GUInt32)*(pabyImage + 1) << 8)
                     | (GUInt32)*(pabyImage + 0);
 #else
-                ((GUInt32 *) pImage)[iPixel++] = 
+                ((GUInt32 *) pImage)[iPixel++] =
                     ((GUInt32)*(pabyImage + 0) << 16)
                     | ((GUInt32)*(pabyImage + 1) << 8)
                     | (GUInt32)*(pabyImage + 2);
@@ -4584,7 +5713,7 @@ CPLErr GTiffOddBitsBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
     else
     {
-        int	iBit, iPixel, iBitOffset = 0;
+        int iBit, iPixel, iBitOffset = 0;
         int     iPixelBitSkip, iBandBitOffset, iX, iY, nBitsPerLine;
 
         if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG )
@@ -4603,7 +5732,8 @@ CPLErr GTiffOddBitsBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         if( (nBitsPerLine & 7) != 0 )
             nBitsPerLine = (nBitsPerLine + 7) & (~7);
 
-        register GByte *pabyBlockBuf = poGDS->pabyBlockBuf;
+        const GByte * const pabyBlockBuf = poGDS->pabyBlockBuf;
+        const int nBitsPerSample = poGDS->nBitsPerSample;
         iPixel = 0;
 
         for( iY = 0; iY < nBlockYSize; iY++ )
@@ -4614,15 +5744,15 @@ CPLErr GTiffOddBitsBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             {
                 int  nOutWord = 0;
 
-                for( iBit = 0; iBit < poGDS->nBitsPerSample; iBit++ )
+                for( iBit = 0; iBit < nBitsPerSample; iBit++ )
                 {
                     if( pabyBlockBuf[iBitOffset>>3]
                         & (0x80 >>(iBitOffset & 7)) )
-                        nOutWord |= (1 << (poGDS->nBitsPerSample - 1 - iBit));
+                        nOutWord |= (1 << (nBitsPerSample - 1 - iBit));
                     iBitOffset++;
                 }
 
-                iBitOffset= iBitOffset + iPixelBitSkip - poGDS->nBitsPerSample;
+                iBitOffset= iBitOffset + iPixelBitSkip - nBitsPerSample;
 
                 if( eDataType == GDT_Byte )
                     ((GByte *) pImage)[iPixel++] = (GByte) nOutWord;
@@ -4667,20 +5797,20 @@ class GTiffBitmapBand : public GTiffOddBitsBand
 /*                           GTiffBitmapBand()                          */
 /************************************************************************/
 
-GTiffBitmapBand::GTiffBitmapBand( GTiffDataset *poDS, int nBand )
-        : GTiffOddBitsBand( poDS, nBand )
+GTiffBitmapBand::GTiffBitmapBand( GTiffDataset *poDSIn, int nBandIn )
+        : GTiffOddBitsBand( poDSIn, nBandIn )
 
 {
     eDataType = GDT_Byte;
 
-    if( poDS->poColorTable != NULL )
-        poColorTable = poDS->poColorTable->Clone();
+    if( poDSIn->poColorTable != NULL )
+        poColorTable = poDSIn->poColorTable->Clone();
     else
     {
 #ifdef ESRI_BUILD
         poColorTable = NULL;
 #else
-        GDALColorEntry	oWhite, oBlack;
+        GDALColorEntry oWhite, oBlack;
 
         oWhite.c1 = 255;
         oWhite.c2 = 255;
@@ -4693,8 +5823,8 @@ GTiffBitmapBand::GTiffBitmapBand( GTiffDataset *poDS, int nBand )
         oBlack.c4 = 255;
 
         poColorTable = new GDALColorTable();
-        
-        if( poDS->nPhotometric == PHOTOMETRIC_MINISWHITE )
+
+        if( poDSIn->nPhotometric == PHOTOMETRIC_MINISWHITE )
         {
             poColorTable->SetColorEntry( 0, &oWhite );
             poColorTable->SetColorEntry( 1, &oBlack );
@@ -4750,7 +5880,7 @@ GDALColorTable *GTiffBitmapBand::GetColorTable()
 /* ==================================================================== */
 /************************************************************************/
 
-class GTiffSplitBitmapBand : public GTiffBitmapBand
+class GTiffSplitBitmapBand CPL_FINAL : public GTiffBitmapBand
 {
     friend class GTiffDataset;
 
@@ -4768,8 +5898,8 @@ class GTiffSplitBitmapBand : public GTiffBitmapBand
 /*                       GTiffSplitBitmapBand()                         */
 /************************************************************************/
 
-GTiffSplitBitmapBand::GTiffSplitBitmapBand( GTiffDataset *poDS, int nBand )
-        : GTiffBitmapBand( poDS, nBand )
+GTiffSplitBitmapBand::GTiffSplitBitmapBand( GTiffDataset *poDSIn, int nBandIn )
+        : GTiffBitmapBand( poDSIn, nBandIn )
 
 {
     nBlockXSize = poDS->GetRasterXSize();
@@ -4798,14 +5928,12 @@ CPLErr GTiffSplitBitmapBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
     if (!poGDS->SetDirectory())
         return CE_Failure;
-        
+
     if (poGDS->pabyBlockBuf == NULL)
     {
-        poGDS->pabyBlockBuf = (GByte *) VSIMalloc(TIFFScanlineSize(poGDS->hTIFF));
+        poGDS->pabyBlockBuf = (GByte *) VSI_MALLOC_VERBOSE(TIFFScanlineSize(poGDS->hTIFF));
         if( poGDS->pabyBlockBuf == NULL )
         {
-            CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate " CPL_FRMT_GUIB " bytes.",
-                         (GUIntBig)TIFFScanlineSize(poGDS->hTIFF));
             return CE_Failure;
         }
     }
@@ -4818,19 +5946,21 @@ CPLErr GTiffSplitBitmapBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
     while( poGDS->nLastLineRead < nBlockYOff )
     {
-        if( TIFFReadScanline( poGDS->hTIFF, poGDS->pabyBlockBuf, ++poGDS->nLastLineRead, 0 ) == -1
+        ++poGDS->nLastLineRead;
+        if( TIFFReadScanline( poGDS->hTIFF, poGDS->pabyBlockBuf, poGDS->nLastLineRead, 0 ) == -1
             && !poGDS->bIgnoreReadErrors )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "TIFFReadScanline() failed." );
+            poGDS->nLastLineRead = -1;
             return CE_Failure;
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Translate 1bit data to eight bit.                               */
 /* -------------------------------------------------------------------- */
-    int	  iPixel, iSrcOffset=0, iDstOffset=0;
+    int iPixel, iSrcOffset=0, iDstOffset=0;
 
     for( iPixel = 0; iPixel < nBlockXSize; iPixel++, iSrcOffset++ )
     {
@@ -4855,7 +5985,7 @@ CPLErr GTiffSplitBitmapBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     (void) nBlockYOff;
     (void) pImage;
 
-    CPLError( CE_Failure, CPLE_AppDefined, 
+    CPLError( CE_Failure, CPLE_AppDefined,
               "Split bitmap bands are read-only." );
     return CE_Failure;
 }
@@ -4871,8 +6001,10 @@ CPLErr GTiffSplitBitmapBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
 /*                            GTiffDataset()                            */
 /************************************************************************/
 
-GTiffDataset::GTiffDataset()
-
+GTiffDataset::GTiffDataset() :
+    nPlanarConfig(0), nSamplesPerPixel(0), nBitsPerSample(0), nRowsPerStrip(0),
+    nPhotometric(0), nSampleFormat(0), nCompression(0), nBlocksPerBand(0),
+    nBlockXSize(0), nBlockYSize(0)
 {
     nLoadedBlock = -1;
     bLoadedBlockDirty = FALSE;
@@ -4891,6 +6023,7 @@ GTiffDataset::GTiffDataset()
     bForceUnsetGTOrGCPs = FALSE;
     bForceUnsetProjection = FALSE;
     bCrystalized = TRUE;
+    bCheckIfColorInterpMustGoToPamAtCrystalization = false;
     poColorTable = NULL;
     bNoDataChanged = FALSE;
     bNoDataSet = FALSE;
@@ -4948,38 +6081,47 @@ GTiffDataset::GTiffDataset()
     nLZMAPreset = -1;
     nJpegQuality = -1;
     nJpegTablesMode = -1;
-    
+
     bPromoteTo8Bits = FALSE;
 
-    bDebugDontWriteBlocks = CSLTestBoolean(CPLGetConfigOption("GTIFF_DONT_WRITE_BLOCKS", "NO"));
+    bDebugDontWriteBlocks = CPLTestBool(CPLGetConfigOption("GTIFF_DONT_WRITE_BLOCKS", "NO"));
 
     bIsFinalized = FALSE;
-    bIgnoreReadErrors = CSLTestBoolean(CPLGetConfigOption("GTIFF_IGNORE_READ_ERRORS", "NO"));
+    bIgnoreReadErrors = CPLTestBool(CPLGetConfigOption("GTIFF_IGNORE_READ_ERRORS", "NO"));
 
     bEXIFMetadataLoaded = FALSE;
     bICCMetadataLoaded = FALSE;
 
     bScanDeferred = TRUE;
 
-    bDirectIO = CSLTestBoolean(CPLGetConfigOption("GTIFF_DIRECT_IO", "NO"));
+    bDirectIO = CPLTestBool(CPLGetConfigOption("GTIFF_DIRECT_IO", "NO"));
     const char* pszVirtualMemIO = CPLGetConfigOption("GTIFF_VIRTUAL_MEM_IO", "NO");
     if( EQUAL(pszVirtualMemIO, "IF_ENOUGH_RAM") )
         eVirtualMemIOUsage = VIRTUAL_MEM_IO_IF_ENOUGH_RAM;
-    else if( CSLTestBoolean(pszVirtualMemIO) )
+    else if( CPLTestBool(pszVirtualMemIO) )
         eVirtualMemIOUsage = VIRTUAL_MEM_IO_YES;
     else
         eVirtualMemIOUsage = VIRTUAL_MEM_IO_NO;
     psVirtualMemIOMapping = NULL;
-    
-    nSetPhotometricFromBandColorInterp = 0;
+
+    eGeoTIFFKeysFlavor = GEOTIFF_KEYS_STANDARD;
 
     pBaseMapping = NULL;
     nRefBaseMapping = 0;
-    
+
     bHasDiscardedLsb = FALSE;
 
     bIMDRPCMetadataLoaded = FALSE;
     papszMetadataFiles = NULL;
+    poCompressThreadPool = NULL;
+    hCompressThreadPoolMutex = NULL;
+
+    m_pTempBufferForCommonDirectIO = NULL;
+    m_nTempBufferForCommonDirectIOSize = 0;
+
+    m_bReadGeoTransform = false;
+    m_bLoadPam = false;
+    m_bHasGotSiblingFiles = false;
 }
 
 /************************************************************************/
@@ -5001,7 +6143,7 @@ int GTiffDataset::Finalize()
     if (bIsFinalized)
         return FALSE;
 
-    int bHasDroppedRef = FALSE;
+    bool bHasDroppedRef = false;
 
     Crystalize();
 
@@ -5014,7 +6156,7 @@ int GTiffDataset::Finalize()
 /* -------------------------------------------------------------------- */
 /*      Handle forcing xml:ESRI data to be written to PAM.              */
 /* -------------------------------------------------------------------- */
-    if( CSLTestBoolean(CPLGetConfigOption( "ESRI_XML_PAM", "NO" )) )
+    if( CPLTestBool(CPLGetConfigOption( "ESRI_XML_PAM", "NO" )) )
     {
         char **papszESRIMD = GetMetadata("xml:ESRI");
         if( papszESRIMD )
@@ -5047,6 +6189,34 @@ int GTiffDataset::Finalize()
 /* -------------------------------------------------------------------- */
     FlushCache();
 
+    // Finish compression
+    if( poCompressThreadPool )
+    {
+        poCompressThreadPool->WaitCompletion();
+        delete poCompressThreadPool;
+
+        // Flush remaining data
+        for(int i=0;i<(int)asCompressionJobs.size();i++)
+        {
+            if( asCompressionJobs[i].bReady )
+            {
+                if( asCompressionJobs[i].nCompressedBufferSize )
+                {
+                    WriteRawStripOrTile( asCompressionJobs[i].nStripOrTile,
+                                   asCompressionJobs[i].pabyCompressedBuffer,
+                                   asCompressionJobs[i].nCompressedBufferSize );
+                }
+            }
+            CPLFree(asCompressionJobs[i].pabyBuffer);
+            if( asCompressionJobs[i].pszTmpFilename )
+            {
+                VSIUnlink(asCompressionJobs[i].pszTmpFilename);
+                CPLFree(asCompressionJobs[i].pszTmpFilename);
+            }
+        }
+        CPLDestroyMutex(hCompressThreadPoolMutex);
+    }
+
 /* -------------------------------------------------------------------- */
 /*      If there is still changed metadata, then presumably we want     */
 /*      to push it into PAM.                                            */
@@ -5066,14 +6236,14 @@ int GTiffDataset::Finalize()
         for( int i = 0; i < nOverviewCount; i++ )
         {
             delete papoOverviewDS[i];
-            bHasDroppedRef = TRUE;
+            bHasDroppedRef = true;
         }
         nOverviewCount = 0;
 
         for( int i = 0; i < nJPEGOverviewCountOri; i++ )
         {
             delete papoJPEGOverviewDS[i];
-            bHasDroppedRef = TRUE;
+            bHasDroppedRef = true;
         }
         nJPEGOverviewCount = 0;
         nJPEGOverviewCountOri = 0;
@@ -5093,7 +6263,7 @@ int GTiffDataset::Finalize()
     {
         delete poMaskDS;
         poMaskDS = NULL;
-        bHasDroppedRef = TRUE;
+        bHasDroppedRef = true;
     }
 
     if( poColorTable != NULL )
@@ -5106,14 +6276,20 @@ int GTiffDataset::Finalize()
         hTIFF = NULL;
         if( fpL != NULL )
         {
-            VSIFCloseL( fpL );
+            if( VSIFCloseL( fpL ) != 0 )
+            {
+                CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+            }
             fpL = NULL;
         }
     }
-    
+
     if( fpToWrite != NULL )
     {
-        VSIFCloseL( fpToWrite );
+        if( VSIFCloseL( fpToWrite ) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        }
         fpToWrite = NULL;
     }
 
@@ -5142,6 +6318,9 @@ int GTiffDataset::Finalize()
     CSLDestroy(papszMetadataFiles);
     papszMetadataFiles = NULL;
 
+    VSIFree(m_pTempBufferForCommonDirectIO);
+    m_pTempBufferForCommonDirectIO = NULL;
+
     bIsFinalized = TRUE;
 
     return bHasDroppedRef;
@@ -5175,16 +6354,15 @@ int GTiffDataset::GetJPEGOverviewCount()
     nJPEGOverviewCount = 0;
     if( !bBase || eAccess != GA_ReadOnly || nCompression != COMPRESSION_JPEG ||
         (nRasterXSize < 256 && nRasterYSize < 256) ||
-        !CSLTestBoolean(CPLGetConfigOption("GTIFF_IMPLICIT_JPEG_OVR", "YES")) ||
+        !CPLTestBool(CPLGetConfigOption("GTIFF_IMPLICIT_JPEG_OVR", "YES")) ||
         GDALGetDriverByName("JPEG") == NULL )
     {
         return 0;
     }
 
-    /* libjpeg-6b only suppports 2, 4 and 8 scale denominators */
+    /* libjpeg-6b only supports 2, 4 and 8 scale denominators */
     /* TODO: Later versions support more */
-    int i;
-    for(i = 2; i >= 0; i--)
+    for(int i = 2; i >= 0; i--)
     {
         if( nRasterXSize >= (256 << i) || nRasterYSize >= (256 << i) )
         {
@@ -5194,7 +6372,7 @@ int GTiffDataset::GetJPEGOverviewCount()
     }
     if( nJPEGOverviewCount == 0 )
         return 0;
-    
+
     if( !SetDirectory() )
         return 0;
 
@@ -5219,7 +6397,7 @@ int GTiffDataset::GetJPEGOverviewCount()
 
     papoJPEGOverviewDS = (GTiffJPEGOverviewDS**) CPLMalloc(
                         sizeof(GTiffJPEGOverviewDS*) * nJPEGOverviewCount );
-    for(i = 0; i < nJPEGOverviewCount; i++)
+    for(int i = 0; i < nJPEGOverviewCount; i++)
     {
         papoJPEGOverviewDS[i] = new GTiffJPEGOverviewDS(this, i+1,
                                             pJPEGTable, (int)nJPEGTableSize);
@@ -5237,15 +6415,14 @@ int GTiffDataset::GetJPEGOverviewCount()
 void GTiffDataset::FillEmptyTiles()
 
 {
-    toff_t *panByteCounts = NULL;
-    int    nBlockCount, iBlock;
-
     if (!SetDirectory())
         return;
 
 /* -------------------------------------------------------------------- */
 /*      How many blocks are there in this file?                         */
 /* -------------------------------------------------------------------- */
+    int nBlockCount;
+
     if( nPlanarConfig == PLANARCONFIG_SEPARATE )
         nBlockCount = nBlocksPerBand * nBands;
     else
@@ -5254,6 +6431,8 @@ void GTiffDataset::FillEmptyTiles()
 /* -------------------------------------------------------------------- */
 /*      Fetch block maps.                                               */
 /* -------------------------------------------------------------------- */
+    toff_t *panByteCounts = NULL;
+
     if( TIFFIsTiled( hTIFF ) )
         TIFFGetField( hTIFF, TIFFTAG_TILEBYTECOUNTS, &panByteCounts );
     else
@@ -5272,22 +6451,20 @@ void GTiffDataset::FillEmptyTiles()
     int nBlockBytes;
 
     if( TIFFIsTiled( hTIFF ) )
-        nBlockBytes = TIFFTileSize(hTIFF);
+        nBlockBytes = static_cast<int>(TIFFTileSize(hTIFF));
     else
-        nBlockBytes = TIFFStripSize(hTIFF);
+        nBlockBytes = static_cast<int>(TIFFStripSize(hTIFF));
 
-    GByte *pabyData = (GByte *) VSICalloc(nBlockBytes,1);
+    GByte *pabyData = (GByte *) VSI_CALLOC_VERBOSE(nBlockBytes,1);
     if (pabyData == NULL)
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory,
-                 "Cannot allocate %d bytes", nBlockBytes);
         return;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Check all blocks, writing out data for uninitialized blocks.    */
 /* -------------------------------------------------------------------- */
-    for( iBlock = 0; iBlock < nBlockCount; iBlock++ )
+    for( int iBlock = 0; iBlock < nBlockCount; iBlock++ )
     {
         if( panByteCounts[iBlock] == 0 )
         {
@@ -5303,17 +6480,17 @@ void GTiffDataset::FillEmptyTiles()
 /*                        WriteEncodedTile()                            */
 /************************************************************************/
 
-int GTiffDataset::WriteEncodedTile(uint32 tile, GByte *pabyData,
-                                   int bPreserveDataBuffer)
+bool GTiffDataset::WriteEncodedTile(uint32 tile, GByte *pabyData,
+                                    int bPreserveDataBuffer)
 {
-    int cc = TIFFTileSize( hTIFF );
-    int bNeedTileFill = FALSE;
+    int cc = static_cast<int>(TIFFTileSize( hTIFF ));
+    bool bNeedTileFill = false;
     int iRow=0, iColumn=0;
     int nBlocksPerRow=1, nBlocksPerColumn=1;
 
-    /* 
-    ** Do we need to spread edge values right or down for a partial 
-    ** JPEG encoded tile?  We do this to avoid edge artifacts. 
+    /*
+    ** Do we need to spread edge values right or down for a partial
+    ** JPEG encoded tile?  We do this to avoid edge artifacts.
     */
     if( nCompression == COMPRESSION_JPEG )
     {
@@ -5326,21 +6503,21 @@ int GTiffDataset::WriteEncodedTile(uint32 tile, GByte *pabyData,
         // Is this a partial right edge tile?
         if( iRow == nBlocksPerRow - 1
             && nRasterXSize % nBlockXSize != 0 )
-            bNeedTileFill = TRUE;
+            bNeedTileFill = true;
 
         // Is this a partial bottom edge tile?
         if( iColumn == nBlocksPerColumn - 1
             && nRasterYSize % nBlockYSize != 0 )
-            bNeedTileFill = TRUE;
+            bNeedTileFill = true;
     }
 
-    /* 
+    /*
     ** If we need to fill out the tile, or if we want to prevent
     ** TIFFWriteEncodedTile from altering the buffer as part of
     ** byte swapping the data on write then we will need a temporary
-    ** working buffer.  If not, we can just do a direct write. 
+    ** working buffer.  If not, we can just do a direct write.
     */
-    if (bPreserveDataBuffer 
+    if (bPreserveDataBuffer
         && (TIFFIsByteSwapped(hTIFF) || bNeedTileFill || bHasDiscardedLsb) )
     {
         if (cc != nTempWriteBufferSize)
@@ -5374,15 +6551,15 @@ int GTiffDataset::WriteEncodedTile(uint32 tile, GByte *pabyData,
         if( iRow == nBlocksPerColumn - 1 )
             nBottomPixelsToFill = nBlockYSize * (iRow+1) - nRasterYSize;
 
-        // Fill out to the right. 
+        // Fill out to the right.
         iSrcX = nBlockXSize - nRightPixelsToFill - 1;
 
         for( iX = iSrcX+1; iX < nBlockXSize; iX++ )
         {
             for( iY = 0; iY < nBlockYSize; iY++ )
             {
-                memcpy( pabyData + (nBlockXSize * iY + iX) * nComponents, 
-                        pabyData + (nBlockXSize * iY + iSrcX) * nComponents, 
+                memcpy( pabyData + (nBlockXSize * iY + iX) * nComponents,
+                        pabyData + (nBlockXSize * iY + iSrcX) * nComponents,
                         nComponents );
             }
         }
@@ -5391,15 +6568,15 @@ int GTiffDataset::WriteEncodedTile(uint32 tile, GByte *pabyData,
         iSrcY = nBlockYSize - nBottomPixelsToFill - 1;
         for( iY = iSrcY+1; iY < nBlockYSize; iY++ )
         {
-            memcpy( pabyData + nBlockXSize * nComponents * iY, 
-                    pabyData + nBlockXSize * nComponents * iSrcY, 
+            memcpy( pabyData + nBlockXSize * nComponents * iY,
+                    pabyData + nBlockXSize * nComponents * iSrcY,
                     nBlockXSize * nComponents );
         }
     }
 
     if( bHasDiscardedLsb != 0 )
     {
-        int iBand = (nPlanarConfig == PLANARCONFIG_SEPARATE ) ? tile / nBlocksPerBand : -1;
+        int iBand = (nPlanarConfig == PLANARCONFIG_SEPARATE ) ? (int)tile / nBlocksPerBand : -1;
         DiscardLsb(pabyData, cc, iBand);
     }
 
@@ -5410,42 +6587,58 @@ int GTiffDataset::WriteEncodedTile(uint32 tile, GByte *pabyData,
             CPLError(CE_Failure, CPLE_NotSupported,
                      "Attempt to write block %d whereas %d was expected",
                      tile,  nLastWrittenBlockId + 1);
-            return -1;
+            return false;
         }
         if( (int)VSIFWriteL(pabyData, 1, cc, fpToWrite) != cc )
         {
             CPLError(CE_Failure, CPLE_FileIO, "Could not write %d bytes",
                      cc);
-            return -1;
+            return false;
         }
         nLastWrittenBlockId = tile;
-        return 0;
+        return true;
     }
 
-    return TIFFWriteEncodedTile(hTIFF, tile, pabyData, cc);
+/* -------------------------------------------------------------------- */
+/*      Should we do compression in a worker thread ?                   */
+/* -------------------------------------------------------------------- */
+    if( SubmitCompressionJob(tile, pabyData, cc, nBlockYSize) )
+        return true;
+
+    // libtiff 4.0.6 or older do not always properly report write errors
+#if !defined(INTERNAL_LIBTIFF) && (!defined(TIFFLIB_VERSION) || (TIFFLIB_VERSION <= 20150912))
+    CPLErr eBefore = CPLGetLastErrorType();
+#endif
+    bool bRet = static_cast<int>(TIFFWriteEncodedTile(hTIFF, tile, pabyData, cc)) == cc;
+#if !defined(INTERNAL_LIBTIFF) && (!defined(TIFFLIB_VERSION) || (TIFFLIB_VERSION <= 20150912))
+    if( eBefore == CE_None && CPLGetLastErrorType() == CE_Failure )
+        bRet = FALSE;
+#endif
+    return bRet;
 }
 
 /************************************************************************/
 /*                        WriteEncodedStrip()                           */
 /************************************************************************/
 
-int  GTiffDataset::WriteEncodedStrip(uint32 strip, GByte* pabyData,
+bool GTiffDataset::WriteEncodedStrip(uint32 strip, GByte* pabyData,
                                      int bPreserveDataBuffer)
 {
-    int cc = TIFFStripSize( hTIFF );
-    
+    int cc = static_cast<int>(TIFFStripSize( hTIFF ));
+
 /* -------------------------------------------------------------------- */
 /*      If this is the last strip in the image, and is partial, then    */
 /*      we need to trim the number of scanlines written to the          */
 /*      amount of valid data we have. (#2748)                           */
 /* -------------------------------------------------------------------- */
     int nStripWithinBand = strip % nBlocksPerBand;
+    int nStripHeight = nRowsPerStrip;
 
     if( (int) ((nStripWithinBand+1) * nRowsPerStrip) > GetRasterYSize() )
     {
-        cc = (cc / nRowsPerStrip)
-            * (GetRasterYSize() - nStripWithinBand * nRowsPerStrip);
-        CPLDebug( "GTiff", "Adjusted bytes to write from %d to %d.", 
+        nStripHeight = GetRasterYSize() - nStripWithinBand * nRowsPerStrip;
+        cc = (cc / nRowsPerStrip) * nStripHeight;
+        CPLDebug( "GTiff", "Adjusted bytes to write from %d to %d.",
                   (int) TIFFStripSize(hTIFF), cc );
     }
 
@@ -5467,7 +6660,7 @@ int  GTiffDataset::WriteEncodedStrip(uint32 strip, GByte* pabyData,
 
     if( bHasDiscardedLsb != 0 )
     {
-        int iBand = (nPlanarConfig == PLANARCONFIG_SEPARATE ) ? strip / nBlocksPerBand : -1;
+        int iBand = (nPlanarConfig == PLANARCONFIG_SEPARATE ) ? (int)strip / nBlocksPerBand : -1;
         DiscardLsb(pabyData, cc, iBand);
     }
 
@@ -5478,19 +6671,341 @@ int  GTiffDataset::WriteEncodedStrip(uint32 strip, GByte* pabyData,
             CPLError(CE_Failure, CPLE_NotSupported,
                      "Attempt to write block %d whereas %d was expected",
                      strip,  nLastWrittenBlockId + 1);
-            return -1;
+            return false;
         }
         if( (int)VSIFWriteL(pabyData, 1, cc, fpToWrite) != cc )
         {
             CPLError(CE_Failure, CPLE_FileIO, "Could not write %d bytes",
                      cc);
-            return -1;
+            return false;
         }
         nLastWrittenBlockId = strip;
-        return 0;
+        return true;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Should we do compression in a worker thread ?                   */
+/* -------------------------------------------------------------------- */
+    if( SubmitCompressionJob(strip, pabyData, cc, nStripHeight) )
+        return true;
+
+    // libtiff 4.0.6 or older do not always properly report write errors
+#if !defined(INTERNAL_LIBTIFF) && (!defined(TIFFLIB_VERSION) || (TIFFLIB_VERSION <= 20150912))
+    CPLErr eBefore = CPLGetLastErrorType();
+#endif
+    bool bRet = static_cast<int>(TIFFWriteEncodedStrip(hTIFF, strip, pabyData, cc)) == cc;
+#if !defined(INTERNAL_LIBTIFF) && (!defined(TIFFLIB_VERSION) || (TIFFLIB_VERSION <= 20150912))
+    if( eBefore == CE_None && CPLGetLastErrorType() == CE_Failure )
+        bRet = FALSE;
+#endif
+    return bRet;
+}
+
+/************************************************************************/
+/*                        InitCompressionThreads()                      */
+/************************************************************************/
+
+void GTiffDataset::InitCompressionThreads(char** papszOptions)
+{
+    const char* pszValue = CSLFetchNameValue( papszOptions, "NUM_THREADS" );
+    if (pszValue == NULL)
+        pszValue = CPLGetConfigOption("GDAL_NUM_THREADS", NULL);
+    if( pszValue )
+    {
+        int nThreads;
+        if (EQUAL(pszValue, "ALL_CPUS"))
+            nThreads = CPLGetNumCPUs();
+        else
+            nThreads = atoi(pszValue);
+        if( nThreads > 1 )
+        {
+            if( nCompression == COMPRESSION_NONE ||
+                nCompression == COMPRESSION_JPEG )
+            {
+                CPLDebug("GTiff", "NUM_THREADS ignored with uncompressed or JPEG");
+            }
+            else
+            {
+                CPLDebug("GTiff", "Using %d threads for compression", nThreads);
+                poCompressThreadPool = new CPLWorkerThreadPool();
+                if( !poCompressThreadPool->Setup(nThreads, NULL, NULL) )
+                {
+                    delete poCompressThreadPool;
+                    poCompressThreadPool = NULL;
+                }
+                else
+                {
+                    // Add a margin of an extra job w.r.t thread number
+                    // so as to optimize compression time (enables the main
+                    // thread to do boring I/O while all CPUs are working)
+                    asCompressionJobs.resize(nThreads + 1);
+                    memset(&asCompressionJobs[0], 0,
+                           asCompressionJobs.size() * sizeof(GTiffCompressionJob));
+                    for(int i=0;i<(int)asCompressionJobs.size();i++)
+                    {
+                        asCompressionJobs[i].pszTmpFilename =
+                            CPLStrdup(CPLSPrintf("/vsimem/gtiff/thread/job/%p",
+                                                 &asCompressionJobs[i]));
+                        asCompressionJobs[i].nStripOrTile = -1;
+                    }
+                    hCompressThreadPoolMutex = CPLCreateMutex();
+                    CPLReleaseMutex(hCompressThreadPoolMutex);
+
+                    // This is kind of a hack, but basically using
+                    // TIFFWriteRawStrip/Tile and then TIFFReadEncodedStrip/Tile
+                    // does not work on a newly created file, because TIFF_MYBUFFER
+                    // is not set in tif_flags
+                    // (if using TIFFWriteEncodedStrip/Tile first, TIFFWriteBufferSetup()
+                    // is automatically called)
+                    // This should likely rather fixed in libtiff itself...
+                    TIFFWriteBufferSetup(hTIFF, NULL, -1);
+                }
+            }
+        }
+        else if (nThreads < 0 || (!EQUAL(pszValue, "0") && !EQUAL(pszValue, "1") && !EQUAL(pszValue, "ALL_CPUS")) )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Invalid value for NUM_THREADS: %s", pszValue);
+        }
+    }
+}
+
+/************************************************************************/
+/*                       GetGTIFFKeysFlavor()                           */
+/************************************************************************/
+
+static GTIFFKeysFlavorEnum GetGTIFFKeysFlavor(char** papszOptions)
+{
+    const char* pszGeoTIFFKeysFlavor = CSLFetchNameValueDef(papszOptions,
+                                                            "GEOTIFF_KEYS_FLAVOR",
+                                                            "STANDARD");
+    if( EQUAL(pszGeoTIFFKeysFlavor, "ESRI_PE") )
+        return GEOTIFF_KEYS_ESRI_PE;
+    return GEOTIFF_KEYS_STANDARD;
+}
+
+/************************************************************************/
+/*                      InitCreationOrOpenOptions()                     */
+/************************************************************************/
+
+void GTiffDataset::InitCreationOrOpenOptions(char** papszOptions)
+{
+    InitCompressionThreads(papszOptions);
+
+    eGeoTIFFKeysFlavor = GetGTIFFKeysFlavor(papszOptions);
+}
+
+/************************************************************************/
+/*                      ThreadCompressionFunc()                         */
+/************************************************************************/
+
+void GTiffDataset::ThreadCompressionFunc(void* pData)
+{
+    GTiffCompressionJob* psJob = (GTiffCompressionJob*)pData;
+    GTiffDataset* poDS = psJob->poDS;
+
+    VSILFILE* fpTmp = VSIFOpenL(psJob->pszTmpFilename, "wb+");
+    TIFF* hTIFFTmp = VSI_TIFFOpen(psJob->pszTmpFilename,
+        (psJob->bTIFFIsBigEndian) ? "wb+" : "wl+", fpTmp);
+    CPLAssert( hTIFFTmp != NULL );
+    int nBlockXSize, nBlockYSize;
+    poDS->GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
+    TIFFSetField(hTIFFTmp, TIFFTAG_IMAGEWIDTH, nBlockXSize);
+    TIFFSetField(hTIFFTmp, TIFFTAG_IMAGELENGTH, psJob->nHeight);
+    TIFFSetField(hTIFFTmp, TIFFTAG_BITSPERSAMPLE, poDS->nBitsPerSample);
+    TIFFSetField(hTIFFTmp, TIFFTAG_COMPRESSION, poDS->nCompression);
+    if( psJob->nPredictor != PREDICTOR_NONE )
+        TIFFSetField(hTIFFTmp, TIFFTAG_PREDICTOR, psJob->nPredictor);
+    if( poDS->nZLevel >= 0 )
+        TIFFSetField(hTIFFTmp, TIFFTAG_ZIPQUALITY, poDS->nZLevel);
+    if( poDS->nLZMAPreset > 0 && poDS->nCompression == COMPRESSION_LZMA)
+        TIFFSetField(hTIFFTmp, TIFFTAG_LZMAPRESET, poDS->nLZMAPreset);
+    TIFFSetField(hTIFFTmp, TIFFTAG_PHOTOMETRIC, poDS->nPhotometric);
+    TIFFSetField(hTIFFTmp, TIFFTAG_SAMPLEFORMAT, poDS->nSampleFormat);
+    TIFFSetField(hTIFFTmp, TIFFTAG_SAMPLESPERPIXEL, poDS->nSamplesPerPixel);
+    TIFFSetField(hTIFFTmp, TIFFTAG_ROWSPERSTRIP, poDS->nBlockYSize);
+    TIFFSetField(hTIFFTmp, TIFFTAG_PLANARCONFIG, poDS->nPlanarConfig);
+
+    bool bOK
+        = (TIFFWriteEncodedStrip(hTIFFTmp, 0, psJob->pabyBuffer,
+                                 psJob->nBufferSize) == psJob->nBufferSize);
+
+    int nOffset = 0;
+    if( bOK )
+    {
+        toff_t* panOffsets = NULL;
+        toff_t* panByteCounts = NULL;
+        TIFFGetField(hTIFFTmp, TIFFTAG_STRIPOFFSETS, &panOffsets);
+        TIFFGetField(hTIFFTmp, TIFFTAG_STRIPBYTECOUNTS, &panByteCounts);
+
+        nOffset = (int) panOffsets[0];
+        psJob->nCompressedBufferSize = (int) panByteCounts[0];
+    }
+    else
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Error when compressing strip/tile %d",
+                 psJob->nStripOrTile);
+    }
+
+    XTIFFClose(hTIFFTmp);
+    if( VSIFCloseL(fpTmp) != 0 )
+    {
+        if( bOK )
+        {
+            bOK = false;
+            CPLError(CE_Failure, CPLE_AppDefined, "Error when compressing strip/tile %d",
+                    psJob->nStripOrTile);
+        }
+    }
+
+    if( bOK )
+    {
+        vsi_l_offset nFileSize = 0;
+        GByte* pabyCompressedBuffer = VSIGetMemFileBuffer(psJob->pszTmpFilename,
+                                                                &nFileSize,
+                                                                FALSE);
+        CPLAssert(nOffset + psJob->nCompressedBufferSize <= (int)nFileSize);
+        psJob->pabyCompressedBuffer = pabyCompressedBuffer + nOffset;
+    }
+    else
+    {
+        psJob->pabyCompressedBuffer = NULL;
+        psJob->nCompressedBufferSize = 0;
+    }
+
+    CPLAcquireMutex(poDS->hCompressThreadPoolMutex, 1000.0);
+    psJob->bReady = TRUE;
+    CPLReleaseMutex(poDS->hCompressThreadPoolMutex);
+}
+
+/************************************************************************/
+/*                        WriteRawStripOrTile()                         */
+/************************************************************************/
+
+void GTiffDataset::WriteRawStripOrTile(int nStripOrTile,
+                                       GByte* pabyCompressedBuffer,
+                                       int nCompressedBufferSize)
+{
+    //CPLDebug("GTIFF", "Writing raw strip/tile %d, size %d",
+    //         nStripOrTile, nCompressedBufferSize);
+    toff_t *panOffsets = NULL;
+    if( TIFFGetField( hTIFF,
+        TIFFIsTiled( hTIFF ) ? TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS, &panOffsets ) &&
+        panOffsets[nStripOrTile] != 0 )
+    {
+        // Make sure that if the tile/strip already exists, we write at end of file
+        TIFFSetWriteOffset(hTIFF, 0);
+    }
+    if( TIFFIsTiled( hTIFF ) )
+        TIFFWriteRawTile(hTIFF, nStripOrTile, pabyCompressedBuffer, nCompressedBufferSize);
+    else
+        TIFFWriteRawStrip(hTIFF, nStripOrTile, pabyCompressedBuffer, nCompressedBufferSize);
+}
+
+/************************************************************************/
+/*                        WaitCompletionForBlock()                      */
+/************************************************************************/
+
+void GTiffDataset::WaitCompletionForBlock(int nBlockId)
+{
+    if( poCompressThreadPool != NULL )
+    {
+        for(int i=0;i<(int)asCompressionJobs.size();i++)
+        {
+            if( asCompressionJobs[i].nStripOrTile == nBlockId )
+            {
+                CPLDebug("GTIFF",
+                         "Waiting for worker job to finish handling block %d",
+                         nBlockId);
+
+                CPLAcquireMutex(hCompressThreadPoolMutex, 1000.0);
+                int bReady = asCompressionJobs[i].bReady;
+                CPLReleaseMutex(hCompressThreadPoolMutex);
+                if( !bReady )
+                {
+                    poCompressThreadPool->WaitCompletion(0);
+                    CPLAssert( asCompressionJobs[i].bReady == TRUE );
+                }
+
+                if( asCompressionJobs[i].nCompressedBufferSize )
+                {
+                    WriteRawStripOrTile(asCompressionJobs[i].nStripOrTile,
+                                  asCompressionJobs[i].pabyCompressedBuffer,
+                                  asCompressionJobs[i].nCompressedBufferSize);
+                }
+                asCompressionJobs[i].pabyCompressedBuffer = NULL;
+                asCompressionJobs[i].nBufferSize = 0;
+                asCompressionJobs[i].bReady = FALSE;
+                asCompressionJobs[i].nStripOrTile = -1;
+                return;
+            }
+        }
+    }
+}
+
+/************************************************************************/
+/*                      SubmitCompressionJob()                          */
+/************************************************************************/
+
+int GTiffDataset::SubmitCompressionJob(int nStripOrTile, GByte* pabyData,
+                                       int cc, int nHeight)
+{
+/* -------------------------------------------------------------------- */
+/*      Should we do compression in a worker thread ?                   */
+/* -------------------------------------------------------------------- */
+    if( !( poCompressThreadPool != NULL &&
+           (nCompression == COMPRESSION_ADOBE_DEFLATE ||
+            nCompression == COMPRESSION_LZW ||
+            nCompression == COMPRESSION_PACKBITS ||
+            nCompression == COMPRESSION_LZMA) ) )
+        return FALSE;
+
+    int nNextCompressionJobAvail = -1;
+    // Wait that at least one job is finished
+    poCompressThreadPool->WaitCompletion(static_cast<int>(asCompressionJobs.size() - 1));
+    for(int i=0;i<(int)asCompressionJobs.size();i++)
+    {
+        CPLAcquireMutex(hCompressThreadPoolMutex, 1000.0);
+        int bReady = asCompressionJobs[i].bReady;
+        CPLReleaseMutex(hCompressThreadPoolMutex);
+        if( bReady )
+        {
+            if( asCompressionJobs[i].nCompressedBufferSize )
+            {
+                WriteRawStripOrTile( asCompressionJobs[i].nStripOrTile,
+                                asCompressionJobs[i].pabyCompressedBuffer,
+                                asCompressionJobs[i].nCompressedBufferSize );
+            }
+            asCompressionJobs[i].pabyCompressedBuffer = NULL;
+            asCompressionJobs[i].nBufferSize = 0;
+            asCompressionJobs[i].bReady = FALSE;
+            asCompressionJobs[i].nStripOrTile = -1;
+        }
+        if( asCompressionJobs[i].nBufferSize == 0 )
+        {
+            if( nNextCompressionJobAvail < 0 )
+                nNextCompressionJobAvail = i;
+        }
+    }
+    CPLAssert(nNextCompressionJobAvail >= 0);
+
+    GTiffCompressionJob* psJob = &asCompressionJobs[nNextCompressionJobAvail];
+    psJob->poDS = this;
+    psJob->bTIFFIsBigEndian = TIFFIsBigEndian(hTIFF);
+    psJob->pabyBuffer = (GByte*)CPLRealloc(psJob->pabyBuffer, cc);
+    memcpy(psJob->pabyBuffer, pabyData, cc);
+    psJob->nBufferSize = cc;
+    psJob->nHeight = nHeight;
+    psJob->nStripOrTile = nStripOrTile;
+    psJob->nPredictor = PREDICTOR_NONE;
+    if ( nCompression == COMPRESSION_LZW ||
+         nCompression == COMPRESSION_ADOBE_DEFLATE )
+    {
+        TIFFGetField( hTIFF, TIFFTAG_PREDICTOR, &psJob->nPredictor );
     }
 
-    return TIFFWriteEncodedStrip(hTIFF, strip, pabyData, cc);
+    poCompressThreadPool->SubmitJob(ThreadCompressionFunc, psJob);
+    return TRUE;
 }
 
 /************************************************************************/
@@ -5503,12 +7018,12 @@ void GTiffDataset::DiscardLsb(GByte* pabyBuffer, int nBytes, int iBand)
     {
         if( nPlanarConfig == PLANARCONFIG_SEPARATE )
         {
-            int nMask = anMaskLsb[iBand];
-            int nOffset = anOffsetLsb[iBand];
+            const int nMask = anMaskLsb[iBand];
+            const int nOffset = anOffsetLsb[iBand];
             for( int i = 0; i < nBytes; i ++ )
             {
                 if( pabyBuffer[i] != 255 ) /* we want to keep 255 in case it is alpha */
-                    pabyBuffer[i] = (pabyBuffer[i] & nMask) | nOffset;
+                    pabyBuffer[i] = static_cast<GByte>((pabyBuffer[i] & nMask) | nOffset);
             }
         }
         else
@@ -5518,8 +7033,8 @@ void GTiffDataset::DiscardLsb(GByte* pabyBuffer, int nBytes, int iBand)
                 for( int j = 0; j < nBands; j ++ )
                 {
                     if( pabyBuffer[i + j] != 255 ) /* we want to keep 255 in case it is alpha */
-                        pabyBuffer[i + j] = (pabyBuffer[i + j] &
-                                    anMaskLsb[j]) | anOffsetLsb[j];
+                        pabyBuffer[i + j] = static_cast<GByte>((pabyBuffer[i + j] &
+                                    anMaskLsb[j]) | anOffsetLsb[j]);
                 }
             }
         }
@@ -5528,11 +7043,11 @@ void GTiffDataset::DiscardLsb(GByte* pabyBuffer, int nBytes, int iBand)
     {
         if( nPlanarConfig == PLANARCONFIG_SEPARATE )
         {
-            int nMask = anMaskLsb[iBand];
-            int nOffset = anOffsetLsb[iBand];
+            const int nMask = anMaskLsb[iBand];
+            const int nOffset = anOffsetLsb[iBand];
             for( int i = 0; i < nBytes/2; i ++ )
             {
-                ((GUInt16*)pabyBuffer)[i] = (((GUInt16*)pabyBuffer)[i] & nMask) | nOffset;
+                ((GUInt16*)pabyBuffer)[i] = static_cast<GUInt16>((((GUInt16*)pabyBuffer)[i] & nMask) | nOffset);
             }
         }
         else
@@ -5541,8 +7056,8 @@ void GTiffDataset::DiscardLsb(GByte* pabyBuffer, int nBytes, int iBand)
             {
                 for( int j = 0; j < nBands; j ++ )
                 {
-                    ((GUInt16*)pabyBuffer)[i + j] = (((GUInt16*)pabyBuffer)[i + j] &
-                                    anMaskLsb[j]) | anOffsetLsb[j];
+                    ((GUInt16*)pabyBuffer)[i + j] = static_cast<GUInt16>((((GUInt16*)pabyBuffer)[i + j] &
+                                    anMaskLsb[j]) | anOffsetLsb[j]);
                 }
             }
         }
@@ -5551,8 +7066,8 @@ void GTiffDataset::DiscardLsb(GByte* pabyBuffer, int nBytes, int iBand)
     {
         if( nPlanarConfig == PLANARCONFIG_SEPARATE )
         {
-            int nMask = anMaskLsb[iBand];
-            int nOffset = anOffsetLsb[iBand];
+            const int nMask = anMaskLsb[iBand];
+            const int nOffset = anOffsetLsb[iBand];
             for( int i = 0; i < nBytes/4; i ++ )
             {
                 ((GUInt32*)pabyBuffer)[i] = (((GUInt32*)pabyBuffer)[i] & nMask) | nOffset;
@@ -5583,16 +7098,16 @@ CPLErr  GTiffDataset::WriteEncodedTileOrStrip(uint32 tile_or_strip, void* data,
 
     if( TIFFIsTiled( hTIFF ) )
     {
-        if( WriteEncodedTile(tile_or_strip, (GByte*) data, 
-                             bPreserveDataBuffer) == -1 )
+        if( !(WriteEncodedTile(tile_or_strip, (GByte*) data,
+                               bPreserveDataBuffer)) )
         {
             eErr = CE_Failure;
         }
     }
     else
     {
-        if( WriteEncodedStrip(tile_or_strip, (GByte *) data, 
-                              bPreserveDataBuffer) == -1 )
+        if( !(WriteEncodedStrip(tile_or_strip, (GByte *) data,
+                                bPreserveDataBuffer)) )
         {
             eErr = CE_Failure;
         }
@@ -5608,8 +7123,6 @@ CPLErr  GTiffDataset::WriteEncodedTileOrStrip(uint32 tile_or_strip, void* data,
 CPLErr GTiffDataset::FlushBlockBuf()
 
 {
-    CPLErr      eErr = CE_None;
-
     if( nLoadedBlock < 0 || !bLoadedBlockDirty )
         return CE_None;
 
@@ -5618,7 +7131,7 @@ CPLErr GTiffDataset::FlushBlockBuf()
     if (!SetDirectory())
         return CE_Failure;
 
-    eErr = WriteEncodedTileOrStrip(nLoadedBlock, pabyBlockBuf, TRUE);
+    CPLErr eErr = WriteEncodedTileOrStrip(nLoadedBlock, pabyBlockBuf, TRUE);
     if (eErr != CE_None)
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -5638,15 +7151,13 @@ CPLErr GTiffDataset::FlushBlockBuf()
 CPLErr GTiffDataset::LoadBlockBuf( int nBlockId, int bReadFromDisk )
 
 {
-    int	nBlockBufSize;
-    CPLErr	eErr = CE_None;
-
     if( nLoadedBlock == nBlockId )
         return CE_None;
 
 /* -------------------------------------------------------------------- */
 /*      If we have a dirty loaded block, flush it out first.            */
 /* -------------------------------------------------------------------- */
+    CPLErr eErr = CE_None;
     if( nLoadedBlock != -1 && bLoadedBlockDirty )
     {
         eErr = FlushBlockBuf();
@@ -5657,10 +7168,11 @@ CPLErr GTiffDataset::LoadBlockBuf( int nBlockId, int bReadFromDisk )
 /* -------------------------------------------------------------------- */
 /*      Get block size.                                                 */
 /* -------------------------------------------------------------------- */
+    int nBlockBufSize;
     if( TIFFIsTiled(hTIFF) )
-        nBlockBufSize = TIFFTileSize( hTIFF );
+        nBlockBufSize = static_cast<int>(TIFFTileSize( hTIFF ));
     else
-        nBlockBufSize = TIFFStripSize( hTIFF );
+        nBlockBufSize = static_cast<int>(TIFFStripSize( hTIFF ));
 
     if ( !nBlockBufSize )
     {
@@ -5674,14 +7186,9 @@ CPLErr GTiffDataset::LoadBlockBuf( int nBlockId, int bReadFromDisk )
 /* -------------------------------------------------------------------- */
     if( pabyBlockBuf == NULL )
     {
-        pabyBlockBuf = (GByte *) VSICalloc( 1, nBlockBufSize );
+        pabyBlockBuf = (GByte *) VSI_CALLOC_VERBOSE( 1, nBlockBufSize );
         if( pabyBlockBuf == NULL )
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory,
-                      "Unable to allocate %d bytes for a temporary strip "
-                      "buffer in GTIFF driver.",
-                      nBlockBufSize );
-            
             return( CE_Failure );
         }
     }
@@ -5719,11 +7226,13 @@ CPLErr GTiffDataset::LoadBlockBuf( int nBlockId, int bReadFromDisk )
 
     if( (int)((nBlockYOff+1) * nBlockYSize) > nRasterYSize )
     {
-        nBlockReqSize = (nBlockBufSize / nBlockYSize) 
+        nBlockReqSize = (nBlockBufSize / nBlockYSize)
             * (nBlockYSize - (((nBlockYOff+1) * nBlockYSize) % nRasterYSize));
         memset( pabyBlockBuf, 0, nBlockBufSize );
     }
 
+    WaitCompletionForBlock(nBlockId);
+
 /* -------------------------------------------------------------------- */
 /*      If we don't have this block already loaded, and we know it      */
 /*      doesn't yet exist on disk, just zero the memory buffer and      */
@@ -5748,9 +7257,9 @@ CPLErr GTiffDataset::LoadBlockBuf( int nBlockId, int bReadFromDisk )
             /* Once TIFFError() is properly hooked, this can go away */
             CPLError( CE_Failure, CPLE_AppDefined,
                       "TIFFReadEncodedTile() failed." );
-                
+
             memset( pabyBlockBuf, 0, nBlockBufSize );
-                
+
             eErr = CE_Failure;
         }
     }
@@ -5763,9 +7272,9 @@ CPLErr GTiffDataset::LoadBlockBuf( int nBlockId, int bReadFromDisk )
             /* Once TIFFError() is properly hooked, this can go away */
             CPLError( CE_Failure, CPLE_AppDefined,
                       "TIFFReadEncodedStrip() failed." );
-                
+
             memset( pabyBlockBuf, 0, nBlockBufSize );
-                
+
             eErr = CE_Failure;
         }
     }
@@ -5793,13 +7302,14 @@ static void GTiffFillStreamableOffsetAndCount(TIFF* hTIFF, int nSize)
     TIFFGetField( hTIFF, TIFFTAG_IMAGEWIDTH, &nXSize );
     TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &nYSize );
     toff_t* panOffset = NULL, *panSize = NULL;
-    int nBlockCount = ( TIFFIsTiled(hTIFF) ) ? TIFFNumberOfTiles(hTIFF) : TIFFNumberOfStrips(hTIFF);
-    TIFFGetField( hTIFF, TIFFIsTiled(hTIFF) ? TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS, &panOffset );
-    TIFFGetField( hTIFF, TIFFIsTiled(hTIFF) ? TIFFTAG_TILEBYTECOUNTS : TIFFTAG_STRIPBYTECOUNTS, &panSize );
+    const bool bIsTiled = CPL_TO_BOOL( TIFFIsTiled(hTIFF) );
+    int nBlockCount = ( bIsTiled ) ? TIFFNumberOfTiles(hTIFF) : TIFFNumberOfStrips(hTIFF);
+    TIFFGetField( hTIFF, bIsTiled ? TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS, &panOffset );
+    TIFFGetField( hTIFF, bIsTiled ? TIFFTAG_TILEBYTECOUNTS : TIFFTAG_STRIPBYTECOUNTS, &panSize );
     toff_t nOffset = nSize;
-    int nBlocksPerBand = 0;
+    int nBlocksPerBand = 1; /* trick to avoid clang static analyzer raising false positive about divide by zero later */
     uint32 nRowsPerStrip = 0;
-    if( !TIFFIsTiled(hTIFF)  )
+    if( !bIsTiled  )
     {
         TIFFGetField( hTIFF, TIFFTAG_ROWSPERSTRIP, &nRowsPerStrip);
         if( nRowsPerStrip > (uint32)nYSize )
@@ -5808,8 +7318,9 @@ static void GTiffFillStreamableOffsetAndCount(TIFF* hTIFF, int nSize)
     }
     for(int i=0;i<nBlockCount;i++)
     {
-        int cc = TIFFIsTiled(hTIFF) ? TIFFTileSize(hTIFF) : TIFFStripSize(hTIFF);
-        if( !TIFFIsTiled(hTIFF)  )
+        int cc = bIsTiled ? static_cast<int>(TIFFTileSize(hTIFF)) :
+                            static_cast<int>(TIFFStripSize(hTIFF));
+        if( !bIsTiled  )
         {
 /* -------------------------------------------------------------------- */
 /*      If this is the last strip in the image, and is partial, then    */
@@ -5841,6 +7352,54 @@ void GTiffDataset::Crystalize()
 {
     if( !bCrystalized )
     {
+        if( bCheckIfColorInterpMustGoToPamAtCrystalization )
+        {
+            bool bColorInterpToPam = false;
+            if( nPhotometric == PHOTOMETRIC_MINISBLACK )
+            {
+                for( int i=0;i<nBands;i++)
+                {
+                    GDALColorInterp eInterp = GetRasterBand(i+1)->GetColorInterpretation();
+                    if( !(eInterp == GCI_GrayIndex || eInterp == GCI_Undefined ||
+                          (i > 0 && eInterp == GCI_AlphaBand)) )
+                    {
+                        bColorInterpToPam = true;
+                        break;
+                    }
+                }
+            }
+            else if( nPhotometric == PHOTOMETRIC_RGB )
+            {
+                for( int i=0;i<nBands;i++)
+                {
+                    GDALColorInterp eInterp = GetRasterBand(i+1)->GetColorInterpretation();
+                    if( !((i == 0 && eInterp == GCI_RedBand) ||
+                          (i == 1 && eInterp == GCI_GreenBand) ||
+                          (i == 2 && eInterp == GCI_BlueBand) ||
+                          (i >= 3 && (eInterp == GCI_Undefined || eInterp == GCI_AlphaBand))) )
+                    {
+                        bColorInterpToPam = true;
+                        break;
+                    }
+                }
+            }
+            else
+            {
+                bColorInterpToPam = true;
+            }
+            if( bColorInterpToPam )
+            {
+                CPLDebug("GTiff", "Color interpretations have to go to PAM");
+                for( int i=0;i<nBands;i++)
+                {
+                    static_cast<GDALPamRasterBand*>(GetRasterBand(i+1))->
+                        GDALPamRasterBand::SetColorInterpretation(
+                            GetRasterBand(i+1)->GetColorInterpretation() );
+                }
+            }
+            bCheckIfColorInterpMustGoToPamAtCrystalization = false;
+        }
+
         // FIXME? libtiff writes extended tags in the order they are specified
         // and not in increasing order
         WriteMetadata( this, hTIFF, TRUE, osProfile, osFilename,
@@ -5858,13 +7417,13 @@ void GTiffDataset::Crystalize()
 
         TIFFWriteCheck( hTIFF, TIFFIsTiled(hTIFF), "GTiffDataset::Crystalize");
 
-        // Keep zip and tiff quality, and jpegcolormode which get reset when we call 
-        // TIFFWriteDirectory 
-        int jquality = -1, zquality = -1, nColorMode = -1, nJpegTablesMode = -1; 
-        TIFFGetField(hTIFF, TIFFTAG_JPEGQUALITY, &jquality); 
-        TIFFGetField(hTIFF, TIFFTAG_ZIPQUALITY, &zquality); 
+        // Keep zip and tiff quality, and jpegcolormode which get reset when we call
+        // TIFFWriteDirectory
+        int jquality = -1, zquality = -1, nColorMode = -1, nJpegTablesModeIn = -1;
+        TIFFGetField(hTIFF, TIFFTAG_JPEGQUALITY, &jquality);
+        TIFFGetField(hTIFF, TIFFTAG_ZIPQUALITY, &zquality);
         TIFFGetField( hTIFF, TIFFTAG_JPEGCOLORMODE, &nColorMode );
-        TIFFGetField( hTIFF, TIFFTAG_JPEGTABLESMODE, &nJpegTablesMode );
+        TIFFGetField( hTIFF, TIFFTAG_JPEGTABLESMODE, &nJpegTablesModeIn );
 
         TIFFWriteDirectory( hTIFF );
         if( bStreamingOut )
@@ -5875,7 +7434,10 @@ void GTiffDataset::Crystalize()
             TIFFSetDirectory( hTIFF, 0 );
             TIFFWriteDirectory( hTIFF );
 
-            VSIFSeekL( fpL, 0, SEEK_END );
+            if( VSIFSeekL( fpL, 0, SEEK_END ) != 0 )
+            {
+                CPLError(CE_Failure, CPLE_FileIO, "Could not seek");
+            }
             int nSize = (int) VSIFTellL(fpL);
 
             TIFFSetDirectory( hTIFF, 0 );
@@ -5899,15 +7461,15 @@ void GTiffDataset::Crystalize()
             TIFFSetDirectory( hTIFF, 0 );
 
 
-        // Now, reset zip and tiff quality and jpegcolormode. 
-        if(jquality > 0) 
-            TIFFSetField(hTIFF, TIFFTAG_JPEGQUALITY, jquality); 
-        if(zquality > 0) 
+        // Now, reset zip and tiff quality and jpegcolormode.
+        if(jquality > 0)
+            TIFFSetField(hTIFF, TIFFTAG_JPEGQUALITY, jquality);
+        if(zquality > 0)
             TIFFSetField(hTIFF, TIFFTAG_ZIPQUALITY, zquality);
         if (nColorMode >= 0)
             TIFFSetField(hTIFF, TIFFTAG_JPEGCOLORMODE, nColorMode);
-        if (nJpegTablesMode >= 0 )
-            TIFFSetField(hTIFF, TIFFTAG_JPEGTABLESMODE, nJpegTablesMode);
+        if (nJpegTablesModeIn >= 0 )
+            TIFFSetField(hTIFF, TIFFTAG_JPEGTABLESMODE, nJpegTablesModeIn);
 
         nDirOffset = TIFFCurrentDirOffset( hTIFF );
     }
@@ -5940,12 +7502,16 @@ void GTiffCacheOffsetOrCount(VSILFILE* fp,
         nOffsetEndPage  = nLastStripOffset;
     if( nOffsetStartPage >= nOffsetEndPage )
     {
-        CPLError(CE_Failure, CPLE_AppDefined, 
+        CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot read offset/size for strile %d", nBlockId);
         panVals[nBlockId] = 0;
         return;
     }
-    VSIFSeekL(fp, nOffsetStartPage, SEEK_SET);
+    if( VSIFSeekL(fp, nOffsetStartPage, SEEK_SET) != 0 )
+    {
+        panVals[nBlockId] = 0;
+        return;
+    }
     size_t nToRead = (size_t)(nOffsetEndPage - nOffsetStartPage);
     size_t nRead = VSIFReadL(buffer, 1, nToRead, fp);
     if( nRead < nToRead )
@@ -5993,7 +7559,7 @@ int GTiffDataset::IsBlockAvailable( int nBlockId )
 
 {
 #ifdef INTERNAL_LIBTIFF
-
+#ifdef DEFER_STRILE_LOAD
     /* Optimization to avoid fetching the whole Strip/TileCounts and Strip/TileOffsets arrays */
     if( eAccess == GA_ReadOnly &&
         !(hTIFF->tif_flags & TIFF_SWAB) &&
@@ -6034,16 +7600,16 @@ int GTiffDataset::IsBlockAvailable( int nBlockId )
             vsi_l_offset nCurOffset = VSIFTellL(fp);
             if( ~(hTIFF->tif_dir.td_stripoffset[nBlockId]) == 0 )
             {
-                vsi_l_offset nDirOffset;
+                vsi_l_offset l_nDirOffset;
                 if( hTIFF->tif_flags&TIFF_BIGTIFF )
-                    nDirOffset = hTIFF->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8;
+                    l_nDirOffset = hTIFF->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8;
                 else
-                    nDirOffset = hTIFF->tif_dir.td_stripoffset_entry.tdir_offset.toff_long;
+                    l_nDirOffset = hTIFF->tif_dir.td_stripoffset_entry.tdir_offset.toff_long;
 
                 if( hTIFF->tif_dir.td_stripoffset_entry.tdir_type == TIFF_LONG )
                 {
                     GTiffCacheOffsetOrCount(fp,
-                                            nDirOffset,
+                                            l_nDirOffset,
                                             nBlockId,
                                             hTIFF->tif_dir.td_nstrips,
                                             hTIFF->tif_dir.td_stripoffset,
@@ -6052,7 +7618,7 @@ int GTiffDataset::IsBlockAvailable( int nBlockId )
                 else
                 {
                     GTiffCacheOffsetOrCount(fp,
-                                            nDirOffset,
+                                            l_nDirOffset,
                                             nBlockId,
                                             hTIFF->tif_dir.td_nstrips,
                                             hTIFF->tif_dir.td_stripoffset,
@@ -6062,16 +7628,16 @@ int GTiffDataset::IsBlockAvailable( int nBlockId )
 
             if( ~(hTIFF->tif_dir.td_stripbytecount[nBlockId]) == 0 )
             {
-                vsi_l_offset nDirOffset;
+                vsi_l_offset l_nDirOffset;
                 if( hTIFF->tif_flags&TIFF_BIGTIFF )
-                    nDirOffset = hTIFF->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8;
+                    l_nDirOffset = hTIFF->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8;
                 else
-                    nDirOffset = hTIFF->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long;
+                    l_nDirOffset = hTIFF->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long;
 
                 if( hTIFF->tif_dir.td_stripbytecount_entry.tdir_type == TIFF_LONG )
                 {
                     GTiffCacheOffsetOrCount(fp,
-                                            nDirOffset,
+                                            l_nDirOffset,
                                             nBlockId,
                                             hTIFF->tif_dir.td_nstrips,
                                             hTIFF->tif_dir.td_stripbytecount,
@@ -6080,23 +7646,30 @@ int GTiffDataset::IsBlockAvailable( int nBlockId )
                 else
                 {
                     GTiffCacheOffsetOrCount(fp,
-                                            nDirOffset,
+                                            l_nDirOffset,
                                             nBlockId,
                                             hTIFF->tif_dir.td_nstrips,
                                             hTIFF->tif_dir.td_stripbytecount,
                                             sizeof(uint64));
                 }
             }
-            VSIFSeekL(fp, nCurOffset, SEEK_SET);
+            if( VSIFSeekL(fp, nCurOffset, SEEK_SET) != 0 )
+            {
+                /* For some reason Coverity tells: */
+                /* Value of non-local "this->hTIFF->tif_dir.td_stripoffset" that was verified to be "NULL" is not restored as it was along other paths. */
+                /* coverity[end_of_path] */
+                return FALSE;
+            }
         }
         return hTIFF->tif_dir.td_stripbytecount[nBlockId] != 0;
     }
+#endif /* DEFER_STRILE_LOAD */
 #endif /* INTERNAL_LIBTIFF */
     toff_t *panByteCounts = NULL;
 
-    if( ( TIFFIsTiled( hTIFF ) 
+    if( ( TIFFIsTiled( hTIFF )
           && TIFFGetField( hTIFF, TIFFTAG_TILEBYTECOUNTS, &panByteCounts ) )
-        || ( !TIFFIsTiled( hTIFF ) 
+        || ( !TIFFIsTiled( hTIFF )
           && TIFFGetField( hTIFF, TIFFTAG_STRIPBYTECOUNTS, &panByteCounts ) ) )
     {
         if( panByteCounts == NULL )
@@ -6149,19 +7722,19 @@ void GTiffDataset::FlushDirectory()
         {
             if (!SetDirectory())
                 return;
-            bNeedsRewrite = 
+            bNeedsRewrite =
                 WriteMetadata( this, hTIFF, TRUE, osProfile, osFilename,
                                papszCreationOptions );
             bMetadataChanged = FALSE;
         }
-        
+
         if( bGeoTIFFInfoChanged )
         {
             if (!SetDirectory())
                 return;
             WriteGeoTIFFInfo();
         }
-        
+
         if( bNoDataChanged )
         {
             if (!SetDirectory())
@@ -6169,9 +7742,13 @@ void GTiffDataset::FlushDirectory()
             if( bNoDataSet )
             {
                 WriteNoDataValue( hTIFF, dfNoDataValue );
-                bNeedsRewrite = TRUE;
-                bNoDataChanged = FALSE;
             }
+            else
+            {
+                UnsetNoDataValue( hTIFF );
+            }
+            bNeedsRewrite = TRUE;
+            bNoDataChanged = FALSE;
         }
 
         if( bNeedsRewrite )
@@ -6203,7 +7780,7 @@ void GTiffDataset::FlushDirectory()
 
     // there are some circumstances in which we can reach this point
     // without having made this our directory (SetDirectory()) in which
-    // case we should not risk a flush. 
+    // case we should not risk a flush.
     if( GetAccess() == GA_Update && TIFFCurrentDirOffset(hTIFF) == nDirOffset )
     {
 #if defined(BIGTIFF_SUPPORT)
@@ -6218,7 +7795,7 @@ void GTiffDataset::FlushDirectory()
         if( nDirOffset != TIFFCurrentDirOffset( hTIFF ) )
         {
             nDirOffset = nNewDirOffset;
-            CPLDebug( "GTiff", 
+            CPLDebug( "GTiff",
                       "directory moved during flush in FlushDirectory()" );
         }
 #else
@@ -6264,25 +7841,25 @@ CPLErr GTiffDataset::CleanOverviews()
     int iThisOffset = 1;
 
     TIFFSetDirectory( hTIFF, 0 );
-    
-    for( ; TRUE; ) 
+
+    while( true )
     {
         for( i = 0; i < nOverviewCount; i++ )
         {
             if( anOvDirOffsets[i] == TIFFCurrentDirOffset( hTIFF ) )
             {
-                CPLDebug( "GTiff", "%d -> %d", 
+                CPLDebug( "GTiff", "%d -> %d",
                           (int) anOvDirOffsets[i], iThisOffset );
                 anOvDirIndexes.push_back( (uint16) iThisOffset );
             }
         }
-        
+
         if( TIFFLastDirectory( hTIFF ) )
             break;
 
         TIFFReadDirectory( hTIFF );
         iThisOffset++;
-    } 
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Actually unlink the target directories.  Note that we do        */
@@ -6504,7 +8081,7 @@ CPLErr GTiffDataset::CreateInternalMaskOverviews(int nOvrBlockXSize,
     const char* pszInternalMask = CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK", NULL);
     if (poMaskDS != NULL &&
         poMaskDS->GetRasterCount() == 1 &&
-        (pszInternalMask == NULL || CSLTestBoolean(pszInternalMask)))
+        (pszInternalMask == NULL || CPLTestBool(pszInternalMask)))
     {
         int nMaskOvrCompression;
         if( strstr(GDALGetMetadataItem(GDALGetDriverByName( "GTiff" ),
@@ -6546,7 +8123,7 @@ CPLErr GTiffDataset::CreateInternalMaskOverviews(int nOvrBlockXSize,
                 }
                 else
                 {
-                    poODS->bPromoteTo8Bits = CSLTestBoolean(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK_TO_8BIT", "YES"));
+                    poODS->bPromoteTo8Bits = CPLTestBool(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK_TO_8BIT", "YES"));
                     poODS->poBaseDS = this;
                     papoOverviewDS[i]->poMaskDS = poODS;
                     poMaskDS->nOverviewCount++;
@@ -6566,10 +8143,10 @@ CPLErr GTiffDataset::CreateInternalMaskOverviews(int nOvrBlockXSize,
 /*                          IBuildOverviews()                           */
 /************************************************************************/
 
-CPLErr GTiffDataset::IBuildOverviews( 
-    const char * pszResampling, 
+CPLErr GTiffDataset::IBuildOverviews(
+    const char * pszResampling,
     int nOverviews, int * panOverviewList,
-    int nBands, int * panBandList,
+    int nBandsIn, int * panBandList,
     GDALProgressFunc pfnProgress, void * pProgressData )
 
 {
@@ -6589,8 +8166,8 @@ CPLErr GTiffDataset::IBuildOverviews(
 /*      If RRD or external OVR overviews requested, then invoke         */
 /*      generic handling.                                               */
 /* -------------------------------------------------------------------- */
-    if( CSLTestBoolean(CPLGetConfigOption( "USE_RRD", "NO" )) 
-        || CSLTestBoolean(CPLGetConfigOption( "TIFF_USE_OVR", "NO" )) )
+    if( CPLTestBool(CPLGetConfigOption( "USE_RRD", "NO" ))
+        || CPLTestBool(CPLGetConfigOption( "TIFF_USE_OVR", "NO" )) )
     {
         bUseGenericHandling = TRUE;
     }
@@ -6619,18 +8196,18 @@ CPLErr GTiffDataset::IBuildOverviews(
 
         return GDALDataset::IBuildOverviews(
             pszResampling, nOverviews, panOverviewList,
-            nBands, panBandList, pfnProgress, pProgressData );
+            nBandsIn, panBandList, pfnProgress, pProgressData );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Our TIFF overview support currently only works safely if all    */
 /*      bands are handled at the same time.                             */
 /* -------------------------------------------------------------------- */
-    if( nBands != GetRasterCount() )
+    if( nBandsIn != GetRasterCount() )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
                   "Generation of overviews in TIFF currently only"
-                  " supported when operating on all bands.\n" 
+                  " supported when operating on all bands.\n"
                   "Operation failed.\n" );
         return CE_Failure;
     }
@@ -6642,9 +8219,9 @@ CPLErr GTiffDataset::IBuildOverviews(
     if( nOverviews == 0 )
     {
         if( nOverviewCount == 0 )
-            return GDALDataset::IBuildOverviews( 
-                pszResampling, nOverviews, panOverviewList, 
-                nBands, panBandList, pfnProgress, pProgressData );
+            return GDALDataset::IBuildOverviews(
+                pszResampling, nOverviews, panOverviewList,
+                nBandsIn, panBandList, pfnProgress, pProgressData );
         else
             return CleanOverviews();
     }
@@ -6675,15 +8252,15 @@ CPLErr GTiffDataset::IBuildOverviews(
         for( i = 0; i < nOverviews && eErr == CE_None; i++ )
         {
             void *pScaledProgressData;
-            pScaledProgressData = 
-                GDALCreateScaledProgress( dfAcc / dfTotal, 
+            pScaledProgressData =
+                GDALCreateScaledProgress( dfAcc / dfTotal,
                                           (dfAcc + padfOvrRasterFactor[i]) / dfTotal,
                                          pfnProgress, pProgressData );
             dfAcc += padfOvrRasterFactor[i];
 
-            eErr = IBuildOverviews( 
-                    pszResampling, 1, &panOverviewList[i], 
-                    nBands, panBandList, GDALScaledProgress, pScaledProgressData );
+            eErr = IBuildOverviews(
+                    pszResampling, 1, &panOverviewList[i],
+                    nBandsIn, panBandList, GDALScaledProgress, pScaledProgressData );
 
             GDALDestroyScaledProgress(pScaledProgressData);
         }
@@ -6716,7 +8293,7 @@ CPLErr GTiffDataset::IBuildOverviews(
 /* -------------------------------------------------------------------- */
     int nOvBitsPerSample = nBitsPerSample;
 
-    if( EQUALN(pszResampling,"AVERAGE_BIT2",12) )
+    if( STARTS_WITH_CI(pszResampling, "AVERAGE_BIT2") )
         nOvBitsPerSample = 8;
 
 /* -------------------------------------------------------------------- */
@@ -6735,11 +8312,11 @@ CPLErr GTiffDataset::IBuildOverviews(
             nColors = 1 << nOvBitsPerSample;
         else
             nColors = 65536;
-        
+
         anTRed.resize(nColors,0);
         anTGreen.resize(nColors,0);
         anTBlue.resize(nColors,0);
-        
+
         for( int iColor = 0; iColor < nColors; iColor++ )
         {
             if( iColor < poColorTable->GetColorEntryCount() )
@@ -6762,7 +8339,7 @@ CPLErr GTiffDataset::IBuildOverviews(
         panGreen = &(anTGreen[0]);
         panBlue = &(anTBlue[0]);
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Do we need some metadata for the overviews?                     */
 /* -------------------------------------------------------------------- */
@@ -6818,7 +8395,7 @@ CPLErr GTiffDataset::IBuildOverviews(
                                              poODS->GetRasterYSize(),
                                              GetRasterYSize());
 
-            if( nOvFactor == panOverviewList[i] 
+            if( nOvFactor == panOverviewList[i]
                 || nOvFactor == GDALOvLevelAdjust2( panOverviewList[i],
                                                     GetRasterXSize(),
                                                     GetRasterYSize() ) )
@@ -6827,20 +8404,20 @@ CPLErr GTiffDataset::IBuildOverviews(
 
         if( panOverviewList[i] > 0 )
         {
-            toff_t	nOverviewOffset;
+            toff_t nOverviewOffset;
             int         nOXSize, nOYSize;
 
-            nOXSize = (GetRasterXSize() + panOverviewList[i] - 1) 
+            nOXSize = (GetRasterXSize() + panOverviewList[i] - 1)
                 / panOverviewList[i];
             nOYSize = (GetRasterYSize() + panOverviewList[i] - 1)
                 / panOverviewList[i];
 
-            nOverviewOffset = 
+            nOverviewOffset =
                 GTIFFWriteDirectory(hTIFF, FILETYPE_REDUCEDIMAGE,
-                                    nOXSize, nOYSize, 
+                                    nOXSize, nOYSize,
                                     nOvBitsPerSample, nPlanarConfig,
                                     nSamplesPerPixel, nOvrBlockXSize, nOvrBlockYSize, TRUE,
-                                    nCompression, nPhotometric, nSampleFormat, 
+                                    nCompression, nPhotometric, nSampleFormat,
                                     nPredictor,
                                     panRed, panGreen, panBlue,
                                     nExtraSamples, panExtraSampleValues,
@@ -6885,9 +8462,9 @@ CPLErr GTiffDataset::IBuildOverviews(
                         papoOverviewDS[i]->poMaskDS->GetRasterBand(1);
             }
         }
-        eErr = GDALRegenerateOverviews( (GDALRasterBandH) 
+        eErr = GDALRegenerateOverviews( (GDALRasterBandH)
                                         poMaskDS->GetRasterBand(1),
-                                        nMaskOverviews, 
+                                        nMaskOverviews,
                                         (GDALRasterBandH *) papoOverviewBands,
                                         pszResampling, GDALDummyProgress, NULL);
         CPLFree(papoOverviewBands);
@@ -6900,7 +8477,7 @@ CPLErr GTiffDataset::IBuildOverviews(
     if (nPlanarConfig == PLANARCONFIG_CONTIG &&
         GDALDataTypeIsComplex(GetRasterBand( panBandList[0] )->GetRasterDataType()) == FALSE &&
         GetRasterBand( panBandList[0] )->GetColorTable() == NULL &&
-        (EQUALN(pszResampling, "NEAR", 4) || EQUAL(pszResampling, "AVERAGE") ||
+        (STARTS_WITH_CI(pszResampling, "NEAR") || EQUAL(pszResampling, "AVERAGE") ||
          EQUAL(pszResampling, "GAUSS") || EQUAL(pszResampling, "CUBIC") ||
          EQUAL(pszResampling, "CUBICSPLINE") || EQUAL(pszResampling, "LANCZOS") ||
          EQUAL(pszResampling, "BILINEAR")))
@@ -6918,9 +8495,9 @@ CPLErr GTiffDataset::IBuildOverviews(
         int nNewOverviews = 0;
         int iBand;
 
-        papapoOverviewBands = (GDALRasterBand ***) CPLCalloc(sizeof(void*),nBands);
-        papoBandList = (GDALRasterBand **) CPLCalloc(sizeof(void*),nBands);
-        for( iBand = 0; iBand < nBands; iBand++ )
+        papapoOverviewBands = (GDALRasterBand ***) CPLCalloc(sizeof(void*),nBandsIn);
+        papoBandList = (GDALRasterBand **) CPLCalloc(sizeof(void*),nBandsIn);
+        for( iBand = 0; iBand < nBandsIn; iBand++ )
         {
             GDALRasterBand* poBand = GetRasterBand( panBandList[iBand] );
 
@@ -6948,7 +8525,7 @@ CPLErr GTiffDataset::IBuildOverviews(
                     if (bHasNoData)
                         poOverview->SetNoDataValue(noDataValue);
 
-                    if( nOvFactor == panOverviewList[i] 
+                    if( nOvFactor == panOverviewList[i]
                         || nOvFactor == GDALOvLevelAdjust2( panOverviewList[i],
                                                             poBand->GetXSize(),
                                                             poBand->GetYSize() ) )
@@ -6969,11 +8546,11 @@ CPLErr GTiffDataset::IBuildOverviews(
             }
         }
 
-        GDALRegenerateOverviewsMultiBand(nBands, papoBandList,
+        GDALRegenerateOverviewsMultiBand(nBandsIn, papoBandList,
                                          nNewOverviews, papapoOverviewBands,
                                          pszResampling, pfnProgress, pProgressData );
 
-        for( iBand = 0; iBand < nBands; iBand++ )
+        for( iBand = 0; iBand < nBandsIn; iBand++ )
         {
             CPLFree(papapoOverviewBands[iBand]);
         }
@@ -6984,10 +8561,10 @@ CPLErr GTiffDataset::IBuildOverviews(
     {
         GDALRasterBand **papoOverviewBands;
 
-        papoOverviewBands = (GDALRasterBand **) 
+        papoOverviewBands = (GDALRasterBand **)
             CPLCalloc(sizeof(void*),nOverviews);
 
-        for( int iBand = 0; iBand < nBands && eErr == CE_None; iBand++ )
+        for( int iBand = 0; iBand < nBandsIn && eErr == CE_None; iBand++ )
         {
             GDALRasterBand *poBand;
             int            nNewOverviews;
@@ -7015,7 +8592,7 @@ CPLErr GTiffDataset::IBuildOverviews(
                                                      poOverview->GetYSize(),
                                                      poBand->GetYSize());
 
-                    if( nOvFactor == panOverviewList[i] 
+                    if( nOvFactor == panOverviewList[i]
                         || nOvFactor == GDALOvLevelAdjust2( panOverviewList[i],
                                                             poBand->GetXSize(),
                                                             poBand->GetYSize() ) )
@@ -7028,16 +8605,16 @@ CPLErr GTiffDataset::IBuildOverviews(
 
             void         *pScaledProgressData;
 
-            pScaledProgressData = 
-                GDALCreateScaledProgress( iBand / (double) nBands, 
-                                        (iBand+1) / (double) nBands,
+            pScaledProgressData =
+                GDALCreateScaledProgress( iBand / (double) nBandsIn,
+                                        (iBand+1) / (double) nBandsIn,
                                         pfnProgress, pProgressData );
 
             eErr = GDALRegenerateOverviews( (GDALRasterBandH) poBand,
-                                            nNewOverviews, 
+                                            nNewOverviews,
                                             (GDALRasterBandH *) papoOverviewBands,
-                                            pszResampling, 
-                                            GDALScaledProgress, 
+                                            pszResampling,
+                                            GDALScaledProgress,
                                             pScaledProgressData);
 
             GDALDestroyScaledProgress( pScaledProgressData );
@@ -7066,14 +8643,14 @@ static void GTiffWriteDummyGeokeyDirectory(TIFF* hTIFF)
     uint16 *panVI = NULL;
     uint16 nKeyCount;
 
-    if( TIFFGetField( hTIFF, TIFFTAG_GEOKEYDIRECTORY, 
+    if( TIFFGetField( hTIFF, TIFFTAG_GEOKEYDIRECTORY,
                         &nKeyCount, &panVI ) )
     {
         GUInt16 anGKVersionInfo[4] = { 1, 1, 0, 0 };
         double  adfDummyDoubleParams[1] = { 0.0 };
-        TIFFSetField( hTIFF, TIFFTAG_GEOKEYDIRECTORY, 
+        TIFFSetField( hTIFF, TIFFTAG_GEOKEYDIRECTORY,
                         4, anGKVersionInfo );
-        TIFFSetField( hTIFF, TIFFTAG_GEODOUBLEPARAMS, 
+        TIFFSetField( hTIFF, TIFFTAG_GEODOUBLEPARAMS,
                         1, adfDummyDoubleParams );
         TIFFSetField( hTIFF, TIFFTAG_GEOASCIIPARAMS, "" );
     }
@@ -7087,16 +8664,16 @@ void GTiffDataset::WriteGeoTIFFInfo()
 
 {
     bool bPixelIsPoint = false;
-    int  bPointGeoIgnore = FALSE;
+    bool bPointGeoIgnore = false;
 
-    if( GetMetadataItem( GDALMD_AREA_OR_POINT ) 
+    if( GetMetadataItem( GDALMD_AREA_OR_POINT )
         && EQUAL(GetMetadataItem(GDALMD_AREA_OR_POINT),
                  GDALMD_AOP_POINT) )
     {
         bPixelIsPoint = true;
-        bPointGeoIgnore = 
-            CSLTestBoolean( CPLGetConfigOption("GTIFF_POINT_GEO_IGNORE",
-                                               "FALSE") );
+        bPointGeoIgnore =
+            CPLTestBool( CPLGetConfigOption( "GTIFF_POINT_GEO_IGNORE",
+                                             "FALSE") );
     }
 
     if( bForceUnsetGTOrGCPs )
@@ -7151,7 +8728,7 @@ void GTiffDataset::WriteGeoTIFFInfo()
         if( adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0
                 && adfGeoTransform[5] < 0.0 )
         {
-            double	adfPixelScale[3], adfTiePoints[6];
+            double adfPixelScale[3], adfTiePoints[6];
 
             adfPixelScale[0] = adfGeoTransform[1];
             adfPixelScale[1] = fabs(adfGeoTransform[5]);
@@ -7178,7 +8755,7 @@ void GTiffDataset::WriteGeoTIFFInfo()
         }
         else
         {
-            double	adfMatrix[16];
+            double adfMatrix[16];
 
             memset(adfMatrix,0,sizeof(double) * 16);
 
@@ -7208,8 +8785,8 @@ void GTiffDataset::WriteGeoTIFFInfo()
     }
     else if( GetGCPCount() > 0 )
     {
-        double	*padfTiePoints;
-        int		iGCP;
+        double *padfTiePoints;
+        int iGCP;
 
         bNeedsRewrite = TRUE;
 
@@ -7234,19 +8811,19 @@ void GTiffDataset::WriteGeoTIFFInfo()
         }
 
         if( !EQUAL(osProfile,"BASELINE") )
-            TIFFSetField( hTIFF, TIFFTAG_GEOTIEPOINTS, 
+            TIFFSetField( hTIFF, TIFFTAG_GEOTIEPOINTS,
                           6 * GetGCPCount(), padfTiePoints );
         CPLFree( padfTiePoints );
     }
 
 /* -------------------------------------------------------------------- */
-/*	Write out projection definition.				*/
+/*      Write out projection definition.                                */
 /* -------------------------------------------------------------------- */
     const bool bHasProjection = (pszProjection != NULL && strlen(pszProjection) > 0);
     if( (bHasProjection || bPixelIsPoint)
         && !EQUAL(osProfile,"BASELINE") )
     {
-        GTIF	*psGTIF;
+        GTIF *psGTIF;
 
         bNeedsRewrite = TRUE;
 
@@ -7254,12 +8831,12 @@ void GTiffDataset::WriteGeoTIFFInfo()
         // by writing a dummy geokey directory. (#2546)
         GTiffWriteDummyGeokeyDirectory(hTIFF);
 
-        psGTIF = GTIFNew( hTIFF );  
+        psGTIF = GTIFNew( hTIFF );
 
         // set according to coordinate system.
         if( bHasProjection )
         {
-            GTIFSetFromOGISDefn( psGTIF, pszProjection );
+            GTIFSetFromOGISDefnEx( psGTIF, pszProjection, eGeoTIFFKeysFlavor );
         }
 
         if( bPixelIsPoint )
@@ -7279,7 +8856,7 @@ void GTiffDataset::WriteGeoTIFFInfo()
 
 static void AppendMetadataItem( CPLXMLNode **ppsRoot, CPLXMLNode **ppsTail,
                                 const char *pszKey, const char *pszValue,
-                                int nBand, const char *pszRole, 
+                                int nBand, const char *pszRole,
                                 const char *pszDomain )
 
 {
@@ -7295,7 +8872,7 @@ static void AppendMetadataItem( CPLXMLNode **ppsRoot, CPLXMLNode **ppsTail,
 
     if( nBand > 0 )
     {
-        sprintf( szBandId, "%d", nBand - 1 );
+        snprintf( szBandId, sizeof(szBandId), "%d", nBand - 1 );
         CPLCreateXMLNode( CPLCreateXMLNode( psItem,CXT_Attribute,"sample"),
                           CXT_Text, szBandId );
     }
@@ -7326,7 +8903,7 @@ static void AppendMetadataItem( CPLXMLNode **ppsRoot, CPLXMLNode **ppsTail,
         CPLAddXMLChild( *ppsRoot, psItem );
     else
         CPLAddXMLSibling( *ppsTail, psItem );
-    
+
     *ppsTail = psItem;
 }
 
@@ -7335,7 +8912,7 @@ static void AppendMetadataItem( CPLXMLNode **ppsRoot, CPLXMLNode **ppsTail,
 /************************************************************************/
 
 static void WriteMDMetadata( GDALMultiDomainMetadata *poMDMD, TIFF *hTIFF,
-                             CPLXMLNode **ppsRoot, CPLXMLNode **ppsTail, 
+                             CPLXMLNode **ppsRoot, CPLXMLNode **ppsTail,
                              int nBand, const char *pszProfile )
 
 {
@@ -7352,7 +8929,7 @@ static void WriteMDMetadata( GDALMultiDomainMetadata *poMDMD, TIFF *hTIFF,
     {
         char **papszMD = poMDMD->GetMetadata( papszDomainList[iDomain] );
         int iItem;
-        int bIsXML = FALSE;
+        bool bIsXML = false;
 
         if( EQUAL(papszDomainList[iDomain], "IMAGE_STRUCTURE") )
             continue; // ignored
@@ -7360,11 +8937,11 @@ static void WriteMDMetadata( GDALMultiDomainMetadata *poMDMD, TIFF *hTIFF,
             continue; // ignored
         if( EQUAL(papszDomainList[iDomain], MD_DOMAIN_RPC) )
             continue; // handled elsewhere
-        if( EQUAL(papszDomainList[iDomain], "xml:ESRI") 
-            && CSLTestBoolean(CPLGetConfigOption( "ESRI_XML_PAM", "NO" )) )
+        if( EQUAL(papszDomainList[iDomain], "xml:ESRI")
+            && CPLTestBool(CPLGetConfigOption( "ESRI_XML_PAM", "NO" )) )
             continue; // handled elsewhere
 
-        if( EQUALN(papszDomainList[iDomain], "xml:",4 ) )
+        if( STARTS_WITH_CI(papszDomainList[iDomain], "xml:") )
             bIsXML = TRUE;
 
 /* -------------------------------------------------------------------- */
@@ -7389,12 +8966,12 @@ static void WriteMDMetadata( GDALMultiDomainMetadata *poMDMD, TIFF *hTIFF,
                     continue;
                 }
             }
-            
+
 /* -------------------------------------------------------------------- */
 /*      Convert into XML item or handle as a special TIFF tag.          */
 /* -------------------------------------------------------------------- */
             if( strlen(papszDomainList[iDomain]) == 0
-                && nBand == 0 && EQUALN(pszItemName,"TIFFTAG_",8) )
+                && nBand == 0 && STARTS_WITH_CI(pszItemName, "TIFFTAG_") )
             {
                 if( EQUAL(pszItemName,"TIFFTAG_RESOLUTIONUNIT") ) {
                     /* ResolutionUnit can't be 0, which is the default if atoi() fails.
@@ -7431,8 +9008,8 @@ static void WriteMDMetadata( GDALMultiDomainMetadata *poMDMD, TIFF *hTIFF,
             else if( nBand == 0 && EQUAL(pszItemName,GDALMD_AREA_OR_POINT) )
                 /* do nothing, handled elsewhere */;
             else
-                AppendMetadataItem( ppsRoot, ppsTail, 
-                                    pszItemName, pszItemValue, 
+                AppendMetadataItem( ppsRoot, ppsTail,
+                                    pszItemName, pszItemValue,
                                     nBand, NULL, papszDomainList[iDomain] );
 
             CPLFree( pszItemName );
@@ -7502,7 +9079,7 @@ void GTiffDataset::WriteRPC( GDALDataset *poSrcDS, TIFF *hTIFF,
         /* profile is selected and RPCTXT is not asked */
         int bRPBExplicitlyAsked = CSLFetchBoolean( papszCreationOptions, "RPB", FALSE );
         int bRPBExplicitlyDenied = !CSLFetchBoolean( papszCreationOptions, "RPB", TRUE );
-        if( (!EQUAL(pszProfile,"GDALGeoTIFF") && 
+        if( (!EQUAL(pszProfile,"GDALGeoTIFF") &&
              !CSLFetchBoolean( papszCreationOptions, "RPCTXT", FALSE ) &&
              !bRPBExplicitlyDenied )
             || bRPBExplicitlyAsked )
@@ -7544,7 +9121,7 @@ int  GTiffDataset::WriteMetadata( GDALDataset *poSrcDS, TIFF *hTIFF,
 
     if( bSrcIsGeoTIFF )
     {
-        WriteMDMetadata( &(((GTiffDataset *)poSrcDS)->oGTiffMDMD), 
+        WriteMDMetadata( &(((GTiffDataset *)poSrcDS)->oGTiffMDMD),
                          hTIFF, &psRoot, &psTail, 0, pszProfile );
     }
     else
@@ -7586,18 +9163,18 @@ int  GTiffDataset::WriteMetadata( GDALDataset *poSrcDS, TIFF *hTIFF,
 
         if( bSrcIsGeoTIFF )
         {
-            WriteMDMetadata( &(((GTiffRasterBand *)poBand)->oGTiffMDMD), 
+            WriteMDMetadata( &(((GTiffRasterBand *)poBand)->oGTiffMDMD),
                              hTIFF, &psRoot, &psTail, nBand, pszProfile );
         }
         else
         {
             char **papszMD = poBand->GetMetadata();
-            
+
             if( CSLCount(papszMD) > 0 )
             {
                 GDALMultiDomainMetadata oMDMD;
                 oMDMD.SetMetadata( papszMD );
-                
+
                 WriteMDMetadata( &oMDMD, hTIFF, &psRoot, &psTail, nBand,
                                  pszProfile );
             }
@@ -7610,24 +9187,24 @@ int  GTiffDataset::WriteMetadata( GDALDataset *poSrcDS, TIFF *hTIFF,
         {
             char szValue[128];
 
-            CPLsprintf( szValue, "%.18g", dfOffset );
-            AppendMetadataItem( &psRoot, &psTail, "OFFSET", szValue, nBand, 
+            CPLsnprintf( szValue, sizeof(szValue), "%.18g", dfOffset );
+            AppendMetadataItem( &psRoot, &psTail, "OFFSET", szValue, nBand,
                                 "offset", "" );
-            CPLsprintf( szValue, "%.18g", dfScale );
-            AppendMetadataItem( &psRoot, &psTail, "SCALE", szValue, nBand, 
+            CPLsnprintf( szValue, sizeof(szValue), "%.18g", dfScale );
+            AppendMetadataItem( &psRoot, &psTail, "SCALE", szValue, nBand,
                                 "scale", "" );
         }
 
         const char* pszUnitType = poBand->GetUnitType();
         if (pszUnitType != NULL && pszUnitType[0] != '\0')
-            AppendMetadataItem( &psRoot, &psTail, "UNITTYPE", pszUnitType, nBand, 
+            AppendMetadataItem( &psRoot, &psTail, "UNITTYPE", pszUnitType, nBand,
                                 "unittype", "" );
 
 
-        if (strlen(poBand->GetDescription()) > 0) 
+        if (strlen(poBand->GetDescription()) > 0)
         {
-            AppendMetadataItem( &psRoot, &psTail, "DESCRIPTION", 
-                                poBand->GetDescription(), nBand, 
+            AppendMetadataItem( &psRoot, &psTail, "DESCRIPTION",
+                                poBand->GetDescription(), nBand,
                                 "description", "" );
         }
     }
@@ -7645,11 +9222,23 @@ int  GTiffDataset::WriteMetadata( GDALDataset *poSrcDS, TIFF *hTIFF,
             if( strlen(pszXML_MD) > 32000 )
             {
                 if( bSrcIsGeoTIFF )
-                    ((GTiffDataset *) poSrcDS)->PushMetadataToPam();
+                {
+                    if( ((GTiffDataset *) poSrcDS)->GetPamFlags() & GPF_DISABLED )
+                    {
+                        CPLError( CE_Warning, CPLE_AppDefined,
+                            "Metadata exceeding 32000 bytes cannot be written into GeoTIFF." );
+                    }
+                    else
+                    {
+                        ((GTiffDataset *) poSrcDS)->PushMetadataToPam();
+                        CPLError( CE_Warning, CPLE_AppDefined,
+                            "Metadata exceeding 32000 bytes cannot be written into GeoTIFF. Transferred to PAM instead." );
+                    }
+                }
                 else
+                {
                     bRet = FALSE;
-                CPLError( CE_Warning, CPLE_AppDefined, 
-                          "Lost metadata writing to GeoTIFF ... too large to fit in tag." );
+                }
             }
             else
             {
@@ -7724,8 +9313,8 @@ void GTiffDataset::PushMetadataToPam()
         char **papszDomainList;
 
         papszDomainList = poSrcMDMD->GetDomainList();
-        for( iDomain = 0; 
-             papszDomainList && papszDomainList[iDomain]; 
+        for( iDomain = 0;
+             papszDomainList && papszDomainList[iDomain];
              iDomain++ )
         {
             char **papszMD = poSrcMDMD->GetMetadata( papszDomainList[iDomain] );
@@ -7741,11 +9330,9 @@ void GTiffDataset::PushMetadataToPam()
 
             for( i = CSLCount(papszMD)-1; i >= 0; i-- )
             {
-                if( EQUALN(papszMD[i],"TIFFTAG_",8)
+                if( STARTS_WITH_CI(papszMD[i], "TIFFTAG_")
                     || EQUALN(papszMD[i],GDALMD_AREA_OR_POINT,
-                              strlen(GDALMD_AREA_OR_POINT)) )
-                    papszMD = CSLRemoveStrings( papszMD, i, 1, NULL );
-            }
+                              strlen(GDALMD_AREA_OR_POINT)) )                    papszMD = CSLRemoveStrings( papszMD, i, 1, NULL );            }
 
             if( nBand == 0 )
                 GDALPamDataset::SetMetadata( papszMD, papszDomainList[iDomain]);
@@ -7754,7 +9341,7 @@ void GTiffDataset::PushMetadataToPam()
 
             CSLDestroy( papszMD );
         }
-            
+
 /* -------------------------------------------------------------------- */
 /*      Handle some "special domain" stuff.                             */
 /* -------------------------------------------------------------------- */
@@ -7785,7 +9372,7 @@ void GTiffDatasetWriteRPCTag( TIFF *hTIFF, char **papszRPCMD )
     if( !GDALExtractRPCInfo( papszRPCMD, &sRPC ) )
         return;
 
-    adfRPCTag[0] = -1.0;  // Error Bias 
+    adfRPCTag[0] = -1.0;  // Error Bias
     adfRPCTag[1] = -1.0;  // Error Random
 
     adfRPCTag[2] = sRPC.dfLINE_OFF;
@@ -7825,7 +9412,7 @@ char** GTiffDatasetReadRPCTag(TIFF* hTIFF)
     int i;
     uint16 nCount;
 
-    if( !TIFFGetField( hTIFF, TIFFTAG_RPCCOEFFICIENT, &nCount, &padfRPCTag ) 
+    if( !TIFFGetField( hTIFF, TIFFTAG_RPCCOEFFICIENT, &nCount, &padfRPCTag )
         || nCount != 92 )
         return NULL;
 
@@ -7897,12 +9484,26 @@ void GTiffDataset::WriteNoDataValue( TIFF *hTIFF, double dfNoData )
     char szVal[400];
     if (CPLIsNan(dfNoData))
         strcpy(szVal, "nan");
-	else
+    else
         CPLsnprintf(szVal, sizeof(szVal), "%.18g", dfNoData);
     TIFFSetField( hTIFF, TIFFTAG_GDAL_NODATA, szVal );
 }
 
 /************************************************************************/
+/*                         UnsetNoDataValue()                           */
+/************************************************************************/
+
+void GTiffDataset::UnsetNoDataValue( TIFF *hTIFF )
+
+{
+#ifdef HAVE_UNSETFIELD
+    TIFFUnsetField( hTIFF, TIFFTAG_GDAL_NODATA );
+#else
+    TIFFSetField( hTIFF, TIFFTAG_GDAL_NODATA, "" );
+#endif
+}
+
+/************************************************************************/
 /*                            SetDirectory()                            */
 /************************************************************************/
 
@@ -7926,7 +9527,7 @@ int GTiffDataset::SetDirectory( toff_t nNewOffset )
         if( *ppoActiveDSRef != NULL )
             (*ppoActiveDSRef)->FlushDirectory();
     }
-    
+
     if( nNewOffset == 0)
         return TRUE;
 
@@ -7946,10 +9547,10 @@ int GTiffDataset::SetDirectory( toff_t nNewOffset )
 
     if( !TIFFGetField( hTIFF, TIFFTAG_PHOTOMETRIC, &(nPhotometric) ) )
         nPhotometric = PHOTOMETRIC_MINISBLACK;
-    
-    if( nCompression == COMPRESSION_JPEG 
-        && nPhotometric == PHOTOMETRIC_YCBCR 
-        && CSLTestBoolean( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB",
+
+    if( nCompression == COMPRESSION_JPEG
+        && nPhotometric == PHOTOMETRIC_YCBCR
+        && CPLTestBool( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB",
                                               "YES") ) )
     {
         int nColorMode;
@@ -7960,7 +9561,7 @@ int GTiffDataset::SetDirectory( toff_t nNewOffset )
     }
 
 /* -------------------------------------------------------------------- */
-/*      Propogate any quality settings.                                 */
+/*      Propagate any quality settings.                                 */
 /* -------------------------------------------------------------------- */
     if( GetAccess() == GA_Update )
     {
@@ -7969,10 +9570,10 @@ int GTiffDataset::SetDirectory( toff_t nNewOffset )
         {
             CPLDebug( "GTiff", "Propagate JPEG_QUALITY(%d) in SetDirectory()",
                       nJpegQuality );
-            TIFFSetField(hTIFF, TIFFTAG_JPEGQUALITY, nJpegQuality); 
+            TIFFSetField(hTIFF, TIFFTAG_JPEGQUALITY, nJpegQuality);
         }
         if(nJpegTablesMode >= 0 && nCompression == COMPRESSION_JPEG)
-            TIFFSetField(hTIFF, TIFFTAG_JPEGTABLESMODE, nJpegTablesMode); 
+            TIFFSetField(hTIFF, TIFFTAG_JPEGTABLESMODE, nJpegTablesMode);
         if(nZLevel > 0 && nCompression == COMPRESSION_ADOBE_DEFLATE)
             TIFFSetField(hTIFF, TIFFTAG_ZIPQUALITY, nZLevel);
         if(nLZMAPreset > 0 && nCompression == COMPRESSION_LZMA)
@@ -7990,7 +9591,7 @@ int GTiffDataset::Identify( GDALOpenInfo * poOpenInfo )
 
 {
     const char  *pszFilename = poOpenInfo->pszFilename;
-    if( EQUALN(pszFilename,"GTIFF_RAW:", strlen("GTIFF_RAW:")) )
+    if( STARTS_WITH_CI(pszFilename, "GTIFF_RAW:") )
     {
         pszFilename += strlen("GTIFF_RAW:");
         GDALOpenInfo oOpenInfo( pszFilename, poOpenInfo->eAccess );
@@ -8001,12 +9602,12 @@ int GTiffDataset::Identify( GDALOpenInfo * poOpenInfo )
 /*      We have a special hook for handling opening a specific          */
 /*      directory of a TIFF file.                                       */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszFilename,"GTIFF_DIR:",strlen("GTIFF_DIR:")) )
+    if( STARTS_WITH_CI(pszFilename, "GTIFF_DIR:") )
         return TRUE;
 
 /* -------------------------------------------------------------------- */
-/*	First we check to see if the file has the expected header	*/
-/*	bytes.								*/    
+/*      First we check to see if the file has the expected header       */
+/*      bytes.                                                          */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->fpL == NULL || poOpenInfo->nHeaderBytes < 2 )
         return FALSE;
@@ -8039,19 +9640,19 @@ int GTiffDataset::Identify( GDALOpenInfo * poOpenInfo )
 /*                            GTIFFErrorHandler()                       */
 /************************************************************************/
 
-class GTIFFErrorStruct
+class GTIFFErrorStruct CPL_FINAL
 {
 public:
     CPLErr type;
-    int    no;
+    CPLErrorNum no;
     CPLString msg;
-    
-        GTIFFErrorStruct() {}
-        GTIFFErrorStruct(CPLErr eErr, int no, const char* msg) :
-            type(eErr), no(no), msg(msg) {}
+
+        GTIFFErrorStruct() : type(CE_None), no(CPLE_None) {}
+        GTIFFErrorStruct(CPLErr eErrIn, CPLErrorNum noIn, const char* msgIn) :
+            type(eErrIn), no(noIn), msg(msgIn) {}
 };
 
-static void CPL_STDCALL GTIFFErrorHandler(CPLErr eErr, int no, const char* msg)
+static void CPL_STDCALL GTIFFErrorHandler(CPLErr eErr, CPLErrorNum no, const char* msg)
 {
     std::vector<GTIFFErrorStruct>* paoErrors =
         (std::vector<GTIFFErrorStruct>*) CPLGetErrorHandlerUserData();
@@ -8071,10 +9672,12 @@ static int GTIFFExtendMemoryFile(const CPLString& osTmpFilename,
 {
     if( nNewLength <= (int)nDataLength )
         return TRUE;
-    VSIFSeekL(fpTemp, nNewLength - 1, SEEK_SET);
+    if( VSIFSeekL(fpTemp, nNewLength - 1, SEEK_SET) != 0 )
+        return FALSE;
     char ch = 0;
-    VSIFWriteL(&ch, 1, 1, fpTemp);
-    int nOldDataLength = nDataLength;
+    if( VSIFWriteL(&ch, 1, 1, fpTemp) != 1 )
+        return FALSE;
+    int nOldDataLength = static_cast<int>(nDataLength);
     pabyBuffer = (GByte*)VSIGetMemFileBuffer( osTmpFilename, &nDataLength, FALSE);
     int nToRead = nNewLength - nOldDataLength;
     int nRead = (int)VSIFReadL( pabyBuffer + nOldDataLength, 1, nToRead, fpL);
@@ -8100,9 +9703,17 @@ static int GTIFFMakeBufferedStream(GDALOpenInfo* poOpenInfo)
     if( fpTemp == NULL )
         return FALSE;
     /* The seek is needed for /vsistdin/ that has some rewind capabilities */
-    VSIFSeekL(poOpenInfo->fpL, poOpenInfo->nHeaderBytes, SEEK_SET);
+    if( VSIFSeekL(poOpenInfo->fpL, poOpenInfo->nHeaderBytes, SEEK_SET) != 0 )
+    {
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpTemp));
+        return FALSE;
+    }
     CPLAssert( (int)VSIFTellL(poOpenInfo->fpL) == poOpenInfo->nHeaderBytes );
-    VSIFWriteL(poOpenInfo->pabyHeader, 1, poOpenInfo->nHeaderBytes, fpTemp);
+    if( VSIFWriteL(poOpenInfo->pabyHeader, poOpenInfo->nHeaderBytes, 1, fpTemp) != 1 )
+    {
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpTemp));
+        return FALSE;
+    }
     vsi_l_offset nDataLength;
     GByte* pabyBuffer = (GByte*)VSIGetMemFileBuffer( osTmpFilename, &nDataLength, FALSE);
     int bLittleEndian = (pabyBuffer[0] == 'I');
@@ -8118,7 +9729,7 @@ static int GTIFFMakeBufferedStream(GDALOpenInfo* poOpenInfo)
         {
             CPLError(CE_Failure, CPLE_NotSupported,
                      "IFD start should be at offset 16 for a streamed BigTIFF");
-            VSIFCloseL(fpTemp);
+            CPL_IGNORE_RET_VAL(VSIFCloseL(fpTemp));
             VSIUnlink(osTmpFilename);
             return FALSE;
         }
@@ -8128,17 +9739,17 @@ static int GTIFFMakeBufferedStream(GDALOpenInfo* poOpenInfo)
         {
             CPLError(CE_Failure, CPLE_NotSupported,
                      "Too many tags : " CPL_FRMT_GIB, nTmp);
-            VSIFCloseL(fpTemp);
+            CPL_IGNORE_RET_VAL(VSIFCloseL(fpTemp));
             VSIUnlink(osTmpFilename);
             return FALSE;
         }
-        int nTags = nTmp;
+        int nTags = static_cast<int>(nTmp);
         int nSpaceForTags = nTags * 20;
         if( !GTIFFExtendMemoryFile(osTmpFilename, fpTemp, poOpenInfo->fpL,
                                     24 + nSpaceForTags,
                                     pabyBuffer, nDataLength) )
         {
-            VSIFCloseL(fpTemp);
+            CPL_IGNORE_RET_VAL(VSIFCloseL(fpTemp));
             VSIUnlink(osTmpFilename);
             return FALSE;
         }
@@ -8158,7 +9769,7 @@ static int GTIFFMakeBufferedStream(GDALOpenInfo* poOpenInfo)
             {
                 CPLError(CE_Failure, CPLE_NotSupported,
                          "Too many elements for tag %d : " CPL_FRMT_GUIB, nTag, nTmp);
-                VSIFCloseL(fpTemp);
+                CPL_IGNORE_RET_VAL(VSIFCloseL(fpTemp));
                 VSIUnlink(osTmpFilename);
                 return FALSE;
             }
@@ -8172,7 +9783,7 @@ static int GTIFFMakeBufferedStream(GDALOpenInfo* poOpenInfo)
                 {
                     CPLError(CE_Failure, CPLE_NotSupported,
                              "Overflow with tag %d", nTag);
-                    VSIFCloseL(fpTemp);
+                    CPL_IGNORE_RET_VAL(VSIFCloseL(fpTemp));
                     VSIUnlink(osTmpFilename);
                     return FALSE;
                 }
@@ -8190,7 +9801,7 @@ static int GTIFFMakeBufferedStream(GDALOpenInfo* poOpenInfo)
         {
             CPLError(CE_Failure, CPLE_NotSupported,
                      "IFD start should be at offset 8 for a streamed TIFF");
-            VSIFCloseL(fpTemp);
+            CPL_IGNORE_RET_VAL(VSIFCloseL(fpTemp));
             VSIUnlink(osTmpFilename);
             return FALSE;
         }
@@ -8201,7 +9812,7 @@ static int GTIFFMakeBufferedStream(GDALOpenInfo* poOpenInfo)
         {
             CPLError(CE_Failure, CPLE_NotSupported,
                      "Too many tags : %d", nTmp16);
-            VSIFCloseL(fpTemp);
+            CPL_IGNORE_RET_VAL(VSIFCloseL(fpTemp));
             VSIUnlink(osTmpFilename);
             return FALSE;
         }
@@ -8211,7 +9822,7 @@ static int GTIFFMakeBufferedStream(GDALOpenInfo* poOpenInfo)
                                     10 + nSpaceForTags,
                                     pabyBuffer, nDataLength) )
         {
-            VSIFCloseL(fpTemp);
+            CPL_IGNORE_RET_VAL(VSIFCloseL(fpTemp));
             VSIUnlink(osTmpFilename);
             return FALSE;
         }
@@ -8230,7 +9841,7 @@ static int GTIFFMakeBufferedStream(GDALOpenInfo* poOpenInfo)
             {
                 CPLError(CE_Failure, CPLE_NotSupported,
                          "Too many elements for tag %d : %u", nTag, nTmp);
-                VSIFCloseL(fpTemp);
+                CPL_IGNORE_RET_VAL(VSIFCloseL(fpTemp));
                 VSIUnlink(osTmpFilename);
                 return FALSE;
             }
@@ -8244,7 +9855,7 @@ static int GTIFFMakeBufferedStream(GDALOpenInfo* poOpenInfo)
                 {
                     CPLError(CE_Failure, CPLE_NotSupported,
                              "Overflow with tag %d", nTag);
-                    VSIFCloseL(fpTemp);
+                    CPL_IGNORE_RET_VAL(VSIFCloseL(fpTemp));
                     VSIUnlink(osTmpFilename);
                     return FALSE;
                 }
@@ -8255,21 +9866,22 @@ static int GTIFFMakeBufferedStream(GDALOpenInfo* poOpenInfo)
     }
     if( nMaxOffset > 10 * 1024 * 1024 )
     {
-        VSIFCloseL(fpTemp);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpTemp));
         VSIUnlink(osTmpFilename);
         return FALSE;
     }
     if( !GTIFFExtendMemoryFile(osTmpFilename, fpTemp, poOpenInfo->fpL,
-                                nMaxOffset, pabyBuffer, nDataLength) )
+                               static_cast<int>(nMaxOffset), pabyBuffer, nDataLength) )
     {
-        VSIFCloseL(fpTemp);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpTemp));
         VSIUnlink(osTmpFilename);
         return FALSE;
     }
     CPLAssert(nDataLength == VSIFTellL(poOpenInfo->fpL));
     poOpenInfo->fpL = (VSILFILE*)VSICreateBufferedReaderHandle(
         (VSIVirtualHandle*)poOpenInfo->fpL, pabyBuffer, ((vsi_l_offset)INT_MAX) << 32 );
-    VSIFCloseL(fpTemp);
+    if( VSIFCloseL(fpTemp) != 0 )
+        return FALSE;
     VSIUnlink(osTmpFilename);
 
     return TRUE;
@@ -8282,7 +9894,7 @@ static int GTIFFMakeBufferedStream(GDALOpenInfo* poOpenInfo)
 GDALDataset *GTiffDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    TIFF	*hTIFF;
+    TIFF *hTIFF;
     int          bAllowRGBAInterface = TRUE;
     const char  *pszFilename = poOpenInfo->pszFilename;
 
@@ -8292,7 +9904,7 @@ GDALDataset *GTiffDataset::Open( GDALOpenInfo * poOpenInfo )
     if (!Identify(poOpenInfo))
         return NULL;
 
-    if( EQUALN(pszFilename,"GTIFF_RAW:", strlen("GTIFF_RAW:")) )
+    if( STARTS_WITH_CI(pszFilename, "GTIFF_RAW:") )
     {
         bAllowRGBAInterface = FALSE;
         pszFilename +=  strlen("GTIFF_RAW:");
@@ -8302,7 +9914,7 @@ GDALDataset *GTiffDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      We have a special hook for handling opening a specific          */
 /*      directory of a TIFF file.                                       */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszFilename,"GTIFF_DIR:",strlen("GTIFF_DIR:")) )
+    if( STARTS_WITH_CI(pszFilename, "GTIFF_DIR:") )
         return OpenDir( poOpenInfo );
 
     if (!GTiffOneTimeInit())
@@ -8321,12 +9933,12 @@ GDALDataset *GTiffDataset::Open( GDALOpenInfo * poOpenInfo )
         if( poOpenInfo->fpL == NULL )
             return NULL;
     }
-    else if( !(pszReadStreaming && !CSLTestBoolean(pszReadStreaming)) &&
+    else if( !(pszReadStreaming && !CPLTestBool(pszReadStreaming)) &&
              poOpenInfo->nHeaderBytes >= 24 &&
              ((int)VSIFTellL(poOpenInfo->fpL) == poOpenInfo->nHeaderBytes || /* A pipe has no seeking capability, so its position is 0 despite having read bytes */
               strcmp(pszFilename, "/vsistdin/") == 0 ||
-              //strncmp(pszFilename, "/vsicurl_streaming/", strlen("/vsicurl_streaming/")) == 0 ||
-              (pszReadStreaming && CSLTestBoolean(pszReadStreaming))) )
+              //STARTS_WITH(pszFilename, "/vsicurl_streaming/") ||
+              (pszReadStreaming && CPLTestBool(pszReadStreaming))) )
     {
         bStreaming = TRUE;
         if( !GTIFFMakeBufferedStream(poOpenInfo) )
@@ -8336,6 +9948,7 @@ GDALDataset *GTiffDataset::Open( GDALOpenInfo * poOpenInfo )
     /* Store errors/warnings and emit them later */
     std::vector<GTIFFErrorStruct> aoErrors;
     CPLPushErrorHandlerEx(GTIFFErrorHandler, &aoErrors);
+    CPLSetCurrentErrorHandlerCatchDebug( FALSE );
     hTIFF = VSI_TIFFOpen( pszFilename, ( poOpenInfo->eAccess == GA_ReadOnly ) ? "rc" : "r+c",
                           poOpenInfo->fpL );
     CPLPopErrorHandler();
@@ -8420,7 +10033,7 @@ GDALDataset *GTiffDataset::Open( GDALOpenInfo * poOpenInfo )
             /* There is a risk of DoS due to huge amount of memory allocated in ChopUpSingleUncompressedStrip() */
             /* in libtiff */
             if (nStrips > 128 * 1024 * 1024 &&
-                !CSLTestBoolean(CPLGetConfigOption("GTIFF_FORCE_STRIP_CHOP", "NO")))
+                !CPLTestBool(CPLGetConfigOption("GTIFF_FORCE_STRIP_CHOP", "NO")))
             {
                 CPLError(CE_Warning, CPLE_AppDefined,
                         "Potential denial of service detected. Avoid using strip chop. "
@@ -8443,7 +10056,7 @@ GDALDataset *GTiffDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    GTiffDataset 	*poDS;
+    GTiffDataset *poDS;
 
     poDS = new GTiffDataset();
     poDS->SetDescription( pszFilename );
@@ -8452,17 +10065,22 @@ GDALDataset *GTiffDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->fpL = poOpenInfo->fpL;
     poOpenInfo->fpL = NULL;
     poDS->bStreamingIn = bStreaming;
+    poDS->nCompression = nCompression;
 
     if( poDS->OpenOffset( hTIFF, &(poDS->poActiveDS),
                           TIFFCurrentDirOffset(hTIFF), TRUE,
-                          poOpenInfo->eAccess, 
-                          bAllowRGBAInterface, TRUE,
-                          poOpenInfo->GetSiblingFiles()) != CE_None )
+                          poOpenInfo->eAccess,
+                          bAllowRGBAInterface, true) != CE_None )
     {
         delete poDS;
         return NULL;
     }
 
+    if( poOpenInfo->eAccess == GA_Update )
+    {
+        poDS->InitCreationOrOpenOptions(poOpenInfo->papszOpenOptions);
+    }
+
     if( nCompression == COMPRESSION_JPEG && poOpenInfo->eAccess == GA_Update )
     {
         int bHasQuantizationTable = FALSE, bHasHuffmanTable = FALSE;
@@ -8550,35 +10168,7 @@ GDALDataset *GTiffDataset::Open( GDALOpenInfo * poOpenInfo )
             TIFFSetField( hTIFF, TIFFTAG_JPEGTABLESMODE, poDS->nJpegTablesMode);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Initialize any PAM information.                                 */
-/* -------------------------------------------------------------------- */
-    poDS->TryLoadXML( poOpenInfo->GetSiblingFiles() );
-    poDS->ApplyPamInfo();
-
-    int i;
-    for(i=1;i<=poDS->nBands;i++)
-    {
-        GTiffRasterBand* poBand = (GTiffRasterBand*) poDS->GetRasterBand(i);
-
-        /* Load scale, offset and unittype from PAM if available */
-        if (!poBand->bHaveOffsetScale)
-        {
-            poBand->dfScale = poBand->GDALPamRasterBand::GetScale(&poBand->bHaveOffsetScale);
-            poBand->dfOffset = poBand->GDALPamRasterBand::GetOffset();
-        }
-        if (poBand->osUnitType.size() == 0)
-        {
-            const char* pszUnitType = poBand->GDALPamRasterBand::GetUnitType();
-            if (pszUnitType)
-                poBand->osUnitType = pszUnitType;
-        }
-
-        GDALColorInterp ePAMColorInterp = poBand->GDALPamRasterBand::GetColorInterpretation();
-        if( ePAMColorInterp != GCI_Undefined )
-            poBand->eBandInterp = ePAMColorInterp;
-    }
-
+    poDS->m_bLoadPam = true;
     poDS->bColorProfileMetadataChanged = FALSE;
     poDS->bMetadataChanged = FALSE;
     poDS->bGeoTIFFInfoChanged = FALSE;
@@ -8587,10 +10177,19 @@ GDALDataset *GTiffDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->bForceUnsetProjection = FALSE;
 
 /* -------------------------------------------------------------------- */
-/*      Check for external overviews.                                   */
+/*      Initialize info for external overviews.                         */
 /* -------------------------------------------------------------------- */
-    poDS->oOvManager.Initialize( poDS, pszFilename, poOpenInfo->GetSiblingFiles() );
-    
+    poDS->oOvManager.Initialize( poDS, pszFilename );
+    if( poOpenInfo->AreSiblingFilesLoaded() )
+        poDS->oOvManager.TransferSiblingFiles( poOpenInfo->StealSiblingFiles() );
+
+    /* For backward compatibility, in case GTIFF_POINT_GEO_IGNORE is defined */
+    /* load georeferencing right now */
+    if( CPLGetConfigOption("GTIFF_POINT_GEO_IGNORE", NULL) != NULL )
+    {
+        poDS->LoadGeoreferencingAndPamIfNeeded();
+    }
+
     return poDS;
 }
 
@@ -8665,11 +10264,11 @@ void GTiffDataset::LookForProjection()
 /* -------------------------------------------------------------------- */
 /*      Capture the GeoTIFF projection, if available.                   */
 /* -------------------------------------------------------------------- */
-    GTIF 	*hGTIF;
+    GTIF *hGTIF;
 
     CPLFree( pszProjection );
     pszProjection = NULL;
-    
+
     hGTIF = GTIFNew(hTIFF);
 
     if ( !hGTIF )
@@ -8685,15 +10284,15 @@ void GTiffDataset::LookForProjection()
         psGTIFDefn = GTIFAllocDefn();
 #else
         psGTIFDefn = (GTIFDefn *) CPLCalloc(1,sizeof(GTIFDefn));
-#endif    
+#endif
 
         if( GTIFGetDefn( hGTIF, psGTIFDefn ) )
         {
             pszProjection = GTIFGetOGISDefn( hGTIF, psGTIFDefn );
-            
+
             // Should we simplify away vertical CS stuff?
-            if( EQUALN(pszProjection,"COMPD_CS",8)
-                && !CSLTestBoolean( CPLGetConfigOption("GTIFF_REPORT_COMPD_CS",
+            if( STARTS_WITH_CI(pszProjection, "COMPD_CS")
+                && !CPLTestBool( CPLGetConfigOption("GTIFF_REPORT_COMPD_CS",
                                                        "NO") ) )
             {
                 OGRSpatialReference oSRS;
@@ -8708,9 +10307,9 @@ void GTiffDataset::LookForProjection()
             }
         }
 
-        // check the tif linear unit and the CS linear unit 
+        // check the tif linear unit and the CS linear unit
 #ifdef ESRI_BUILD
-        AdjustLinearUnit(psGTIFDefn.UOMLength); 
+        AdjustLinearUnit(psGTIFDefn.UOMLength);
 #endif
 
 #if LIBGEOTIFF_VERSION >= 1410
@@ -8788,7 +10387,7 @@ void GTiffDataset::ApplyPamInfo()
 {
     double adfPamGeoTransform[6];
 
-    if( GDALPamDataset::GetGeoTransform( adfPamGeoTransform ) == CE_None 
+    if( GDALPamDataset::GetGeoTransform( adfPamGeoTransform ) == CE_None
         && (adfPamGeoTransform[0] != 0.0 || adfPamGeoTransform[1] != 1.0
             || adfPamGeoTransform[2] != 0.0 || adfPamGeoTransform[3] != 0.0
             || adfPamGeoTransform[4] != 0.0 || adfPamGeoTransform[5] != 1.0 ))
@@ -8877,23 +10476,23 @@ GDALDataset *GTiffDataset::OpenDir( GDALOpenInfo * poOpenInfo )
 {
     int bAllowRGBAInterface = TRUE;
     const char* pszFilename = poOpenInfo->pszFilename;
-    if( EQUALN(pszFilename,"GTIFF_RAW:", strlen("GTIFF_RAW:")) )
+    if( STARTS_WITH_CI(pszFilename, "GTIFF_RAW:") )
     {
         bAllowRGBAInterface = FALSE;
         pszFilename += strlen("GTIFF_RAW:");
     }
 
-    if( !EQUALN(pszFilename,"GTIFF_DIR:",strlen("GTIFF_DIR:")) )
+    if( !STARTS_WITH_CI(pszFilename, "GTIFF_DIR:") )
         return NULL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Split out filename, and dir#/offset.                            */
 /* -------------------------------------------------------------------- */
     pszFilename += strlen("GTIFF_DIR:");
     int        bAbsolute = FALSE;
     toff_t     nOffset;
-    
-    if( EQUALN(pszFilename,"off:",4) )
+
+    if( STARTS_WITH_CI(pszFilename, "off:") )
     {
         bAbsolute = TRUE;
         pszFilename += 4;
@@ -8916,7 +10515,7 @@ GDALDataset *GTiffDataset::OpenDir( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Try opening the dataset.                                        */
 /* -------------------------------------------------------------------- */
-    TIFF	*hTIFF;
+    TIFF *hTIFF;
 
     if (!GTiffOneTimeInit())
         return NULL;
@@ -8927,7 +10526,7 @@ GDALDataset *GTiffDataset::OpenDir( GDALOpenInfo * poOpenInfo )
     hTIFF = VSI_TIFFOpen( pszFilename, "r", fpL );
     if( hTIFF == NULL )
     {
-        VSIFCloseL(fpL);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpL));
         return( NULL );
     }
 
@@ -8942,9 +10541,9 @@ GDALDataset *GTiffDataset::OpenDir( GDALOpenInfo * poOpenInfo )
             if( TIFFReadDirectory( hTIFF ) == 0 )
             {
                 XTIFFClose( hTIFF );
-                CPLError( CE_Failure, CPLE_OpenFailed, 
+                CPLError( CE_Failure, CPLE_OpenFailed,
                           "Requested directory %lu not found.", (long unsigned int)nOffsetRequested );
-                VSIFCloseL(fpL);
+                CPL_IGNORE_RET_VAL(VSIFCloseL(fpL));
                 return NULL;
             }
             nOffset--;
@@ -8956,7 +10555,7 @@ GDALDataset *GTiffDataset::OpenDir( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    GTiffDataset 	*poDS;
+    GTiffDataset *poDS;
 
     poDS = new GTiffDataset();
     poDS->SetDescription( poOpenInfo->pszFilename );
@@ -8964,8 +10563,8 @@ GDALDataset *GTiffDataset::OpenDir( GDALOpenInfo * poOpenInfo )
     poDS->poActiveDS = poDS;
     poDS->fpL = fpL;
 
-    if( !EQUAL(pszFilename,poOpenInfo->pszFilename) 
-        && !EQUALN(poOpenInfo->pszFilename,"GTIFF_RAW:",10) )
+    if( !EQUAL(pszFilename,poOpenInfo->pszFilename)
+        && !STARTS_WITH_CI(poOpenInfo->pszFilename, "GTIFF_RAW:") )
     {
         poDS->SetPhysicalFilename( pszFilename );
         poDS->SetSubdatasetName( poOpenInfo->pszFilename );
@@ -8978,10 +10577,12 @@ GDALDataset *GTiffDataset::OpenDir( GDALOpenInfo * poOpenInfo )
                   "Opening a specific TIFF directory is not supported in update mode. Switching to read-only" );
     }
 
+    if( poOpenInfo->AreSiblingFilesLoaded() )
+        poDS->oOvManager.TransferSiblingFiles( poOpenInfo->StealSiblingFiles() );
+
     if( poDS->OpenOffset( hTIFF, &(poDS->poActiveDS),
                           nOffset, FALSE, GA_ReadOnly,
-                          bAllowRGBAInterface, TRUE,
-                          poOpenInfo->GetSiblingFiles() ) != CE_None )
+                          bAllowRGBAInterface, true ) != CE_None )
     {
         delete poDS;
         return NULL;
@@ -9037,7 +10638,7 @@ void GTiffDataset::LoadICCProfile()
     if (!SetDirectory())
         return;
 
-    if (TIFFGetField(hTIFF, TIFFTAG_ICCPROFILE, &nEmbedLen, &pEmbedBuffer)) 
+    if (TIFFGetField(hTIFF, TIFFTAG_ICCPROFILE, &nEmbedLen, &pEmbedBuffer))
     {
         char *pszBase64Profile = CPLBase64Encode(nEmbedLen, (const GByte*)pEmbedBuffer);
 
@@ -9049,9 +10650,9 @@ void GTiffDataset::LoadICCProfile()
     }
 
     /* Check for colorimetric tiff */
-    if (TIFFGetField(hTIFF, TIFFTAG_PRIMARYCHROMATICITIES, &pCHR)) 
+    if (TIFFGetField(hTIFF, TIFFTAG_PRIMARYCHROMATICITIES, &pCHR))
     {
-        if (TIFFGetField(hTIFF, TIFFTAG_WHITEPOINT, &pWP)) 
+        if (TIFFGetField(hTIFF, TIFFTAG_WHITEPOINT, &pWP))
         {
             if (!TIFFGetFieldDefaulted(hTIFF, TIFFTAG_TRANSFERFUNCTION, &pTFR, &pTFG, &pTFB))
                 return;
@@ -9059,14 +10660,14 @@ void GTiffDataset::LoadICCProfile()
             TIFFGetFieldDefaulted(hTIFF, TIFFTAG_TRANSFERRANGE, &pTransferRange);
 
             // Set all the colorimetric metadata.
-            oGTiffMDMD.SetMetadataItem( "SOURCE_PRIMARIES_RED", 
+            oGTiffMDMD.SetMetadataItem( "SOURCE_PRIMARIES_RED",
                 CPLString().Printf( "%.9f, %.9f, 1.0", (double)pCHR[0], (double)pCHR[1] ) , "COLOR_PROFILE" );
-            oGTiffMDMD.SetMetadataItem( "SOURCE_PRIMARIES_GREEN", 
+            oGTiffMDMD.SetMetadataItem( "SOURCE_PRIMARIES_GREEN",
                 CPLString().Printf( "%.9f, %.9f, 1.0", (double)pCHR[2], (double)pCHR[3] ) , "COLOR_PROFILE" );
-            oGTiffMDMD.SetMetadataItem( "SOURCE_PRIMARIES_BLUE", 
+            oGTiffMDMD.SetMetadataItem( "SOURCE_PRIMARIES_BLUE",
                 CPLString().Printf( "%.9f, %.9f, 1.0", (double)pCHR[4], (double)pCHR[5] ) , "COLOR_PROFILE" );
 
-            oGTiffMDMD.SetMetadataItem( "SOURCE_WHITEPOINT", 
+            oGTiffMDMD.SetMetadataItem( "SOURCE_WHITEPOINT",
                 CPLString().Printf( "%.9f, %.9f, 1.0", (double)pWP[0], (double)pWP[1] ) , "COLOR_PROFILE" );
 
             /* Set transfer function metadata */
@@ -9074,23 +10675,23 @@ void GTiffDataset::LoadICCProfile()
             /* Get length of table. */
             const uint32 nTransferFunctionLength = 1 << nBitsPerSample;
 
-            oGTiffMDMD.SetMetadataItem( "TIFFTAG_TRANSFERFUNCTION_RED", 
+            oGTiffMDMD.SetMetadataItem( "TIFFTAG_TRANSFERFUNCTION_RED",
                 ConvertTransferFunctionToString( pTFR, nTransferFunctionLength), "COLOR_PROFILE" );
 
-            oGTiffMDMD.SetMetadataItem( "TIFFTAG_TRANSFERFUNCTION_GREEN", 
+            oGTiffMDMD.SetMetadataItem( "TIFFTAG_TRANSFERFUNCTION_GREEN",
                 ConvertTransferFunctionToString( pTFG, nTransferFunctionLength), "COLOR_PROFILE" );
 
-            oGTiffMDMD.SetMetadataItem( "TIFFTAG_TRANSFERFUNCTION_BLUE", 
+            oGTiffMDMD.SetMetadataItem( "TIFFTAG_TRANSFERFUNCTION_BLUE",
                 ConvertTransferFunctionToString( pTFB, nTransferFunctionLength), "COLOR_PROFILE" );
 
             /* Set transfer range */
             if (pTransferRange)
             {
                 oGTiffMDMD.SetMetadataItem( "TIFFTAG_TRANSFERRANGE_BLACK",
-                    CPLString().Printf( "%d, %d, %d", 
+                    CPLString().Printf( "%d, %d, %d",
                         (int)pTransferRange[0], (int)pTransferRange[2], (int)pTransferRange[4]), "COLOR_PROFILE" );
                 oGTiffMDMD.SetMetadataItem( "TIFFTAG_TRANSFERRANGE_WHITE",
-                    CPLString().Printf( "%d, %d, %d", 
+                    CPLString().Printf( "%d, %d, %d",
                         (int)pTransferRange[1], (int)pTransferRange[3], (int)pTransferRange[5]), "COLOR_PROFILE" );
             }
         }
@@ -9102,7 +10703,7 @@ void GTiffDataset::LoadICCProfile()
 /*                                                                      */
 /*      Save ICC Profile or colorimetric data into file                 */
 /* pDS:                                                                 */
-/*      Dataset that contains the metadata with the ICC or colorimetric */ 
+/*      Dataset that contains the metadata with the ICC or colorimetric */
 /*      data. If this argument is specified, all other arguments are    */
 /*      ignored. Set them to NULL or 0.                                 */
 /* hTIFF:                                                               */
@@ -9146,7 +10747,7 @@ void GTiffDataset::SaveICCProfile(GTiffDataset *pDS, TIFF *hTIFF, char **papszPa
 
         TIFFSetField(hTIFF, TIFFTAG_ICCPROFILE, nEmbedLen, pEmbedBuffer);
 
-        CPLFree(pEmbedBuffer);        
+        CPLFree(pEmbedBuffer);
     }
     else
     {
@@ -9180,7 +10781,7 @@ void GTiffDataset::SaveICCProfile(GTiffDataset *pDS, TIFF *hTIFF, char **papszPa
                 break;
             }
 
-            char** papszTokens = CSLTokenizeString2( pszValue, ",", 
+            char** papszTokens = CSLTokenizeString2( pszValue, ",",
                 CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
 
             if (CSLCount( papszTokens ) != 3)
@@ -9212,7 +10813,7 @@ void GTiffDataset::SaveICCProfile(GTiffDataset *pDS, TIFF *hTIFF, char **papszPa
 
             CSLDestroy( papszTokens );
         }
-        
+
         if (bOutputCHR)
         {
             TIFFSetField(hTIFF, TIFFTAG_PRIMARYCHROMATICITIES, pCHR);
@@ -9226,7 +10827,7 @@ void GTiffDataset::SaveICCProfile(GTiffDataset *pDS, TIFF *hTIFF, char **papszPa
             pszValue = CSLFetchNameValue(papszParmList, "SOURCE_WHITEPOINT");
         if (pszValue != NULL)
         {
-            char** papszTokens = CSLTokenizeString2( pszValue, ",", 
+            char** papszTokens = CSLTokenizeString2( pszValue, ",",
                 CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
 
             if (CSLCount( papszTokens ) != 3)
@@ -9262,7 +10863,7 @@ void GTiffDataset::SaveICCProfile(GTiffDataset *pDS, TIFF *hTIFF, char **papszPa
                 TIFFSetField(hTIFF, TIFFTAG_WHITEPOINT, pWP);
             }
         }
-        
+
         /* Set transfer function metadata */
         char const *pszTFRed = NULL;
         char const *pszTFGreen = NULL;
@@ -9287,11 +10888,11 @@ void GTiffDataset::SaveICCProfile(GTiffDataset *pDS, TIFF *hTIFF, char **papszPa
             /* Get length of table. */
             const int nTransferFunctionLength = 1 << ((pDS!=NULL)?pDS->nBitsPerSample:nBitsPerSample);
 
-            char** papszTokensRed = CSLTokenizeString2( pszTFRed, ",", 
+            char** papszTokensRed = CSLTokenizeString2( pszTFRed, ",",
                 CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
-            char** papszTokensGreen = CSLTokenizeString2( pszTFGreen, ",", 
+            char** papszTokensGreen = CSLTokenizeString2( pszTFGreen, ",",
                 CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
-            char** papszTokensBlue = CSLTokenizeString2( pszTFBlue, ",", 
+            char** papszTokensBlue = CSLTokenizeString2( pszTFBlue, ",",
                 CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
 
             if ((CSLCount( papszTokensRed ) == nTransferFunctionLength) &&
@@ -9311,7 +10912,7 @@ void GTiffDataset::SaveICCProfile(GTiffDataset *pDS, TIFF *hTIFF, char **papszPa
                     pTransferFuncBlue[i] = (uint16)atoi(papszTokensBlue[i]);
                 }
 
-                TIFFSetField(hTIFF, TIFFTAG_TRANSFERFUNCTION, 
+                TIFFSetField(hTIFF, TIFFTAG_TRANSFERFUNCTION,
                     pTransferFuncRed, pTransferFuncGreen, pTransferFuncBlue);
 
                 CPLFree(pTransferFuncRed);
@@ -9338,7 +10939,7 @@ void GTiffDataset::SaveICCProfile(GTiffDataset *pDS, TIFF *hTIFF, char **papszPa
                 break;
             }
 
-            char** papszTokens = CSLTokenizeString2( pszValue, ",", 
+            char** papszTokens = CSLTokenizeString2( pszValue, ",",
                 CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
 
             if (CSLCount( papszTokens ) != 3)
@@ -9347,7 +10948,7 @@ void GTiffDataset::SaveICCProfile(GTiffDataset *pDS, TIFF *hTIFF, char **papszPa
                 CSLDestroy( papszTokens );
                 break;
             }
-            
+
             int j;
             for( j = 0; j < 3; j++ )
             {
@@ -9356,7 +10957,7 @@ void GTiffDataset::SaveICCProfile(GTiffDataset *pDS, TIFF *hTIFF, char **papszPa
 
             CSLDestroy( papszTokens );
         }
-        
+
         if (bOutputTransferRange)
         {
             TIFFSetField(hTIFF, TIFFTAG_TRANSFERRANGE, pTXR);
@@ -9372,23 +10973,21 @@ void GTiffDataset::SaveICCProfile(GTiffDataset *pDS, TIFF *hTIFF, char **papszPa
 /*      full res, and overview pages.                                   */
 /************************************************************************/
 
-CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn, 
-                                 GTiffDataset **ppoActiveDSRef,
-                                 toff_t nDirOffsetIn, 
-				 int bBaseIn, GDALAccess eAccess,
+CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
+                                 GTiffDataset **ppoActiveDSRefIn,
+                                 toff_t nDirOffsetIn,
+                                 int bBaseIn, GDALAccess eAccessIn,
                                  int bAllowRGBAInterface,
-                                 int bReadGeoTransform,
-                                 char** papszSiblingFiles )
+                                 bool bReadGeoTransform )
 
 {
-    uint32	nXSize, nYSize;
-    int		bTreatAsBitmap = FALSE;
-    int         bTreatAsOdd = FALSE;
+    bool bTreatAsBitmap = false;
+    bool bTreatAsOdd = false;
 
-    this->eAccess = eAccess;
+    eAccess = eAccessIn;
 
     hTIFF = hTIFFIn;
-    this->ppoActiveDSRef = ppoActiveDSRef;
+    ppoActiveDSRef = ppoActiveDSRefIn;
 
     nDirOffset = nDirOffsetIn;
 
@@ -9397,11 +10996,10 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
 
     bBase = bBaseIn;
 
-    this->eAccess = eAccess;
-
 /* -------------------------------------------------------------------- */
 /*      Capture some information from the file that is of interest.     */
 /* -------------------------------------------------------------------- */
+    uint32 nXSize, nYSize;
     TIFFGetField( hTIFF, TIFFTAG_IMAGEWIDTH, &nXSize );
     TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &nYSize );
     nRasterXSize = nXSize;
@@ -9411,22 +11009,22 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
         nBands = 1;
     else
         nBands = nSamplesPerPixel;
-    
+
     if( !TIFFGetField(hTIFF, TIFFTAG_BITSPERSAMPLE, &(nBitsPerSample)) )
         nBitsPerSample = 1;
-    
+
     if( !TIFFGetField( hTIFF, TIFFTAG_PLANARCONFIG, &(nPlanarConfig) ) )
         nPlanarConfig = PLANARCONFIG_CONTIG;
-    
+
     if( !TIFFGetField( hTIFF, TIFFTAG_PHOTOMETRIC, &(nPhotometric) ) )
         nPhotometric = PHOTOMETRIC_MINISBLACK;
-    
+
     if( !TIFFGetField( hTIFF, TIFFTAG_SAMPLEFORMAT, &(nSampleFormat) ) )
         nSampleFormat = SAMPLEFORMAT_UINT;
-    
+
     if( !TIFFGetField( hTIFF, TIFFTAG_COMPRESSION, &(nCompression) ) )
         nCompression = COMPRESSION_NONE;
-    
+
 #if defined(TIFFLIB_VERSION) && TIFFLIB_VERSION > 20031007 /* 3.6.0 */
     if (nCompression != COMPRESSION_NONE &&
         !TIFFIsCODECConfigured(nCompression))
@@ -9442,14 +11040,14 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
 /*      to RGB by libtiff/libjpeg unless specifically requested         */
 /*      otherwise.                                                      */
 /* -------------------------------------------------------------------- */
-    if( nCompression == COMPRESSION_JPEG 
-        && nPhotometric == PHOTOMETRIC_YCBCR 
-        && CSLTestBoolean( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB",
+    if( nCompression == COMPRESSION_JPEG
+        && nPhotometric == PHOTOMETRIC_YCBCR
+        && CPLTestBool( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB",
                                               "YES") ) )
     {
         int nColorMode;
 
-        SetMetadataItem( "SOURCE_COLOR_SPACE", "YCbCr", "IMAGE_STRUCTURE" );
+        oGTiffMDMD.SetMetadataItem( "SOURCE_COLOR_SPACE", "YCbCr", "IMAGE_STRUCTURE" );
         if ( !TIFFGetField( hTIFF, TIFFTAG_JPEGCOLORMODE, &nColorMode ) ||
               nColorMode != JPEGCOLORMODE_RGB )
             TIFFSetField(hTIFF, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
@@ -9468,7 +11066,7 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
         if( !TIFFGetField( hTIFF, TIFFTAG_ROWSPERSTRIP,
                            &(nRowsPerStrip) ) )
         {
-            CPLError( CE_Warning, CPLE_AppDefined, 
+            CPLError( CE_Warning, CPLE_AppDefined,
                       "RowsPerStrip not defined ... assuming all one strip." );
             nRowsPerStrip = nYSize; /* dummy value */
         }
@@ -9482,7 +11080,7 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
         nBlockXSize = nRasterXSize;
         nBlockYSize = nRowsPerStrip;
     }
-        
+
     nBlocksPerBand =
         DIV_ROUND_UP(nYSize, nBlockYSize) * DIV_ROUND_UP(nXSize, nBlockXSize);
 
@@ -9491,11 +11089,11 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
 /* -------------------------------------------------------------------- */
     if( nBitsPerSample == 1 && nBands == 1 )
     {
-        bTreatAsBitmap = TRUE;
+        bTreatAsBitmap = true;
 
         // Lets treat large "one row" bitmaps using the scanline api.
-        if( !TIFFIsTiled(hTIFF) 
-            && nBlockYSize == nYSize 
+        if( !TIFFIsTiled(hTIFF)
+            && nBlockYSize == nYSize
             && nYSize > 2000
             /* libtiff does not support reading JBIG files with TIFFReadScanline() */
             && nCompression != COMPRESSION_JBIG )
@@ -9507,16 +11105,20 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
 /* -------------------------------------------------------------------- */
 /*      Should we treat this via the RGBA interface?                    */
 /* -------------------------------------------------------------------- */
-    if( bAllowRGBAInterface &&
-        !bTreatAsBitmap && !(nBitsPerSample > 8) 
+    if(
+#ifdef DEBUG
+        CPLTestBool(CPLGetConfigOption("GTIFF_FORCE_RGBA", "NO")) ||
+#endif
+        (bAllowRGBAInterface &&
+        !bTreatAsBitmap && !(nBitsPerSample > 8)
         && (nPhotometric == PHOTOMETRIC_CIELAB ||
             nPhotometric == PHOTOMETRIC_LOGL ||
             nPhotometric == PHOTOMETRIC_LOGLUV ||
             nPhotometric == PHOTOMETRIC_SEPARATED ||
-            ( nPhotometric == PHOTOMETRIC_YCBCR 
-              && nCompression != COMPRESSION_JPEG )) )
+            ( nPhotometric == PHOTOMETRIC_YCBCR
+              && nCompression != COMPRESSION_JPEG ))) )
     {
-        char	szMessage[1024];
+        char szMessage[1024];
 
         if( TIFFRGBAImageOK( hTIFF, szMessage ) == 1 )
         {
@@ -9540,7 +11142,7 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
                     break;
             }
             if (pszSourceColorSpace)
-                SetMetadataItem( "SOURCE_COLOR_SPACE", pszSourceColorSpace, "IMAGE_STRUCTURE" );
+                oGTiffMDMD.SetMetadataItem( "SOURCE_COLOR_SPACE", pszSourceColorSpace, "IMAGE_STRUCTURE" );
             bTreatAsRGBA = TRUE;
             nBands = 4;
         }
@@ -9549,16 +11151,28 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
             CPLDebug( "GTiff", "TIFFRGBAImageOK says:\n%s", szMessage );
         }
     }
-    
+
+    // libtiff has various issues with OJPEG compression and chunky-strip support
+    // with the "classic" scanline/strip/tile interfaces, and that wouldn't
+    // work either, so better bail out
+    if( nCompression == COMPRESSION_OJPEG &&
+        !bTreatAsRGBA )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Old-JPEG compression only supported through RGBA interface, "
+                 "which cannot be used probably because the file is corrupted");
+        return CE_Failure;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Should we treat this via the split interface?                   */
 /* -------------------------------------------------------------------- */
-    if( !TIFFIsTiled(hTIFF) 
+    if( !TIFFIsTiled(hTIFF)
         && nBitsPerSample == 8
-        && nBlockYSize == nYSize 
+        && nBlockYSize == nYSize
         && nYSize > 2000
-        && !bTreatAsRGBA 
-        && CSLTestBoolean(CPLGetConfigOption("GDAL_ENABLE_TIFF_SPLIT", "YES")))
+        && !bTreatAsRGBA
+        && CPLTestBool(CPLGetConfigOption("GDAL_ENABLE_TIFF_SPLIT", "YES")))
     {
         /* libtiff 3.9.2 (20091104) and older, libtiff 4.0.0beta5 (also 20091104) */
         /* and older will crash when trying to open a all-in-one-strip */
@@ -9575,22 +11189,23 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
 #endif
             bTreatAsSplit = TRUE;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Should we treat this via the odd bits interface?                */
 /* -------------------------------------------------------------------- */
     if ( nSampleFormat == SAMPLEFORMAT_IEEEFP )
     {
         if ( nBitsPerSample == 16 || nBitsPerSample == 24 )
-            bTreatAsOdd = TRUE;
+            bTreatAsOdd = true;
     }
     else if ( !bTreatAsRGBA && !bTreatAsBitmap
               && nBitsPerSample != 8
               && nBitsPerSample != 16
               && nBitsPerSample != 32
-              && nBitsPerSample != 64 
+              && nBitsPerSample != 64
               && nBitsPerSample != 128 )
-        bTreatAsOdd = TRUE;
+        bTreatAsOdd = true;
+
 
 /* -------------------------------------------------------------------- */
 /*      We don't support 'chunks' bigger than 2GB although libtiff v4   */
@@ -9598,7 +11213,11 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
 /* -------------------------------------------------------------------- */
 #if defined(BIGTIFF_SUPPORT)
     tmsize_t nChunkSize;
-    if( bTreatAsSplit || bTreatAsSplitBitmap )
+    if( bTreatAsRGBA )
+    {
+        nChunkSize = 4 * static_cast<tmsize_t>(nBlockXSize) * nBlockYSize;
+    }
+    else if( bTreatAsSplit || bTreatAsSplitBitmap )
     {
         nChunkSize = TIFFScanlineSize( hTIFF );
     }
@@ -9612,12 +11231,12 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
     if( nChunkSize > INT_MAX )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
-                  "Scanline/tile/strip size bigger than 2GB." );
+                "Scanline/tile/strip size bigger than 2GB." );
         return CE_Failure;
     }
 #endif
 
-    int bMinIsWhite = nPhotometric == PHOTOMETRIC_MINISWHITE;
+    bool bMinIsWhite = nPhotometric == PHOTOMETRIC_MINISWHITE;
 
 /* -------------------------------------------------------------------- */
 /*      Check for NODATA                                                */
@@ -9633,10 +11252,10 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
 /* -------------------------------------------------------------------- */
 /*      Capture the color table if there is one.                        */
 /* -------------------------------------------------------------------- */
-    unsigned short	*panRed, *panGreen, *panBlue;
+    unsigned short *panRed, *panGreen, *panBlue;
 
-    if( bTreatAsRGBA 
-        || TIFFGetField( hTIFF, TIFFTAG_COLORMAP, 
+    if( bTreatAsRGBA || nBitsPerSample > 16
+        || TIFFGetField( hTIFF, TIFFTAG_COLORMAP,
                          &panRed, &panGreen, &panBlue) == 0 )
     {
         // Build inverted palette if we have inverted photometric.
@@ -9645,14 +11264,13 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
         if( nBitsPerSample <= 16 && nPhotometric == PHOTOMETRIC_MINISWHITE )
         {
             GDALColorEntry  oEntry;
-            int		    iColor, nColorCount;
-            
+
             poColorTable = new GDALColorTable();
-            nColorCount = 1 << nBitsPerSample;
+            const int nColorCount = 1 << nBitsPerSample;
 
-            for ( iColor = 0; iColor < nColorCount; iColor++ )
+            for ( int iColor = 0; iColor < nColorCount; iColor++ )
             {
-            oEntry.c1 = oEntry.c2 = oEntry.c3 = (short) 
+            oEntry.c1 = oEntry.c2 = oEntry.c3 = (short)
                         ((255 * (nColorCount - 1 - iColor)) / (nColorCount-1));
             oEntry.c4 = 255;
             poColorTable->SetColorEntry( iColor, &oEntry );
@@ -9665,12 +11283,12 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
     }
     else
     {
-        int	nColorCount, nMaxColor = 0;
+        int nMaxColor = 0;
         GDALColorEntry oEntry;
 
         poColorTable = new GDALColorTable();
 
-        nColorCount = 1 << nBitsPerSample;
+        const int nColorCount = 1 << nBitsPerSample;
 
         for( int iColor = nColorCount - 1; iColor >= 0; iColor-- )
         {
@@ -9689,225 +11307,54 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
         // Bug 1384 - Some TIFF files are generated with color map entry
         // values in range 0-255 instead of 0-65535 - try to handle these
         // gracefully.
-        if( nMaxColor > 0 && nMaxColor < 256 )
-        {
-            CPLDebug( "GTiff", "TIFF ColorTable seems to be improperly scaled, fixing up." );
-            
-            for( int iColor = nColorCount - 1; iColor >= 0; iColor-- )
-            {
-                oEntry.c1 = panRed[iColor];
-                oEntry.c2 = panGreen[iColor];
-                oEntry.c3 = panBlue[iColor];
-                oEntry.c4 = (bNoDataSet && (int)dfNoDataValue == iColor) ? 0 : 255;
-                
-                poColorTable->SetColorEntry( iColor, &oEntry );
-            }
-        }
-    }
-    
-/* -------------------------------------------------------------------- */
-/*      Create band information objects.                                */
-/* -------------------------------------------------------------------- */
-    for( int iBand = 0; iBand < nBands; iBand++ )
-    {
-        if( bTreatAsRGBA )
-            SetBand( iBand+1, new GTiffRGBABand( this, iBand+1 ) );
-        else if( bTreatAsSplitBitmap )
-            SetBand( iBand+1, new GTiffSplitBitmapBand( this, iBand+1 ) );
-        else if( bTreatAsSplit )
-            SetBand( iBand+1, new GTiffSplitBand( this, iBand+1 ) );
-        else if( bTreatAsBitmap )
-            SetBand( iBand+1, new GTiffBitmapBand( this, iBand+1 ) );
-        else if( bTreatAsOdd )
-            SetBand( iBand+1, new GTiffOddBitsBand( this, iBand+1 ) );
-        else
-            SetBand( iBand+1, new GTiffRasterBand( this, iBand+1 ) );
-    }
-
-    if( GetRasterBand(1)->GetRasterDataType() == GDT_Unknown )
-    {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "Unsupported TIFF configuration." );
-        return CE_Failure;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Get the transform or gcps from the GeoTIFF file.                */
-/* -------------------------------------------------------------------- */
-    if( bReadGeoTransform )
-    {
-        char    *pszTabWKT = NULL;
-        double	*padfTiePoints, *padfScale, *padfMatrix;
-        uint16	nCount;
-        bool    bPixelIsPoint = false;
-        short nRasterType;
-        GTIF	*psGTIF;
-        int     bPointGeoIgnore = FALSE;
-
-        psGTIF = GTIFNew( hTIFF ); // I wonder how expensive this is?
-
-        if( psGTIF )
-        {
-            if( GDALGTIFKeyGetSHORT(psGTIF, GTRasterTypeGeoKey, &nRasterType,
-                        0, 1 ) == 1
-                && nRasterType == (short) RasterPixelIsPoint )
-            {
-                bPixelIsPoint = true;
-                bPointGeoIgnore =
-                    CSLTestBoolean( CPLGetConfigOption("GTIFF_POINT_GEO_IGNORE",
-                                                    "FALSE") );
-            }
-
-            GTIFFree( psGTIF );
-        }
-
-        adfGeoTransform[0] = 0.0;
-        adfGeoTransform[1] = 1.0;
-        adfGeoTransform[2] = 0.0;
-        adfGeoTransform[3] = 0.0;
-        adfGeoTransform[4] = 0.0;
-        adfGeoTransform[5] = 1.0;
-    
-        if( TIFFGetField(hTIFF,TIFFTAG_GEOPIXELSCALE,&nCount,&padfScale )
-            && nCount >= 2 
-            && padfScale[0] != 0.0 && padfScale[1] != 0.0 )
-        {
-            adfGeoTransform[1] = padfScale[0];
-            adfGeoTransform[5] = - ABS(padfScale[1]);
-
-            if( TIFFGetField(hTIFF,TIFFTAG_GEOTIEPOINTS,&nCount,&padfTiePoints )
-                && nCount >= 6 )
-            {
-                adfGeoTransform[0] =
-                    padfTiePoints[3] - padfTiePoints[0] * adfGeoTransform[1];
-                adfGeoTransform[3] =
-                    padfTiePoints[4] - padfTiePoints[1] * adfGeoTransform[5];
-
-                if( bPixelIsPoint && !bPointGeoIgnore )
-                {
-                    adfGeoTransform[0] -= (adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5);
-                    adfGeoTransform[3] -= (adfGeoTransform[4] * 0.5 + adfGeoTransform[5] * 0.5);
-                }
-
-                bGeoTransformValid = TRUE;
-            }
-        }
-
-        else if( TIFFGetField(hTIFF,TIFFTAG_GEOTRANSMATRIX,&nCount,&padfMatrix ) 
-                 && nCount == 16 )
-        {
-            adfGeoTransform[0] = padfMatrix[3];
-            adfGeoTransform[1] = padfMatrix[0];
-            adfGeoTransform[2] = padfMatrix[1];
-            adfGeoTransform[3] = padfMatrix[7];
-            adfGeoTransform[4] = padfMatrix[4];
-            adfGeoTransform[5] = padfMatrix[5];
-
-            if( bPixelIsPoint && !bPointGeoIgnore )
-            {
-                adfGeoTransform[0] -= (adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5);
-                adfGeoTransform[3] -= (adfGeoTransform[4] * 0.5 + adfGeoTransform[5] * 0.5);
-            }
-
-            bGeoTransformValid = TRUE;
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Otherwise try looking for a .tab, .tfw, .tifw or .wld file.     */
-/* -------------------------------------------------------------------- */
-        else
-        {
-            char* pszGeorefFilename = NULL;
-
-            /* Begin with .tab since it can also have projection info */
-            int bTabFileOK =
-                GDALReadTabFile2( osFilename, adfGeoTransform,
-                                    &pszTabWKT, &nGCPCount, &pasGCPList,
-                                    papszSiblingFiles, &pszGeorefFilename );
-
-            if( bTabFileOK )
-            {
-                if( nGCPCount == 0 )
-                    bGeoTransformValid = TRUE;
-            }
-            else
-            {
-                if( !bGeoTransformValid )
-                {
-                    bGeoTransformValid =
-                        GDALReadWorldFile2( osFilename, NULL, adfGeoTransform,
-                                            papszSiblingFiles, &pszGeorefFilename);
-                }
-
-                if( !bGeoTransformValid )
-                {
-                    bGeoTransformValid =
-                        GDALReadWorldFile2( osFilename, "wld", adfGeoTransform,
-                                            papszSiblingFiles, &pszGeorefFilename);
-                }
-            }
-
-            if (pszGeorefFilename)
-            {
-                osGeorefFilename = pszGeorefFilename;
-                CPLFree(pszGeorefFilename);
-            }
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Check for GCPs.  Note, we will allow there to be GCPs and a     */
-/*      transform in some circumstances.                                */
-/* -------------------------------------------------------------------- */
-        if( TIFFGetField(hTIFF,TIFFTAG_GEOTIEPOINTS,&nCount,&padfTiePoints )
-            && !bGeoTransformValid )
-        {
-            nGCPCount = nCount / 6;
-            pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),nGCPCount);
-        
-            for( int iGCP = 0; iGCP < nGCPCount; iGCP++ )
-            {
-                char	szID[32];
+        if( nMaxColor > 0 && nMaxColor < 256 )
+        {
+            CPLDebug( "GTiff", "TIFF ColorTable seems to be improperly scaled, fixing up." );
 
-                sprintf( szID, "%d", iGCP+1 );
-                pasGCPList[iGCP].pszId = CPLStrdup( szID );
-                pasGCPList[iGCP].pszInfo = CPLStrdup("");
-                pasGCPList[iGCP].dfGCPPixel = padfTiePoints[iGCP*6+0];
-                pasGCPList[iGCP].dfGCPLine = padfTiePoints[iGCP*6+1];
-                pasGCPList[iGCP].dfGCPX = padfTiePoints[iGCP*6+3];
-                pasGCPList[iGCP].dfGCPY = padfTiePoints[iGCP*6+4];
-                pasGCPList[iGCP].dfGCPZ = padfTiePoints[iGCP*6+5];
+            for( int iColor = nColorCount - 1; iColor >= 0; iColor-- )
+            {
+                oEntry.c1 = panRed[iColor];
+                oEntry.c2 = panGreen[iColor];
+                oEntry.c3 = panBlue[iColor];
+                oEntry.c4 = (bNoDataSet && (int)dfNoDataValue == iColor) ? 0 : 255;
 
-                if( bPixelIsPoint && !bPointGeoIgnore )
-                {
-                    pasGCPList[iGCP].dfGCPPixel -= 0.5;
-                    pasGCPList[iGCP].dfGCPLine -= 0.5;
-                }
+                poColorTable->SetColorEntry( iColor, &oEntry );
             }
         }
+    }
 
 /* -------------------------------------------------------------------- */
-/*      Did we find a tab file?  If so we will use it's coordinate      */
-/*      system and give it precidence.                                  */
+/*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-        if( pszTabWKT != NULL 
-            && (pszProjection == NULL || pszProjection[0] == '\0') )
-        {
-            CPLFree( pszProjection );
-            pszProjection = pszTabWKT;
-            pszTabWKT = NULL;
-            bLookedForProjection = TRUE;
-        }
-        
-        CPLFree( pszTabWKT );
-        bGeoTIFFInfoChanged = FALSE;
-        bForceUnsetGTOrGCPs = FALSE;
-        bForceUnsetProjection = FALSE;
+    for( int iBand = 0; iBand < nBands; iBand++ )
+    {
+        if( bTreatAsRGBA )
+            SetBand( iBand+1, new GTiffRGBABand( this, iBand+1 ) );
+        else if( bTreatAsSplitBitmap )
+            SetBand( iBand+1, new GTiffSplitBitmapBand( this, iBand+1 ) );
+        else if( bTreatAsSplit )
+            SetBand( iBand+1, new GTiffSplitBand( this, iBand+1 ) );
+        else if( bTreatAsBitmap )
+            SetBand( iBand+1, new GTiffBitmapBand( this, iBand+1 ) );
+        else if( bTreatAsOdd )
+            SetBand( iBand+1, new GTiffOddBitsBand( this, iBand+1 ) );
+        else
+            SetBand( iBand+1, new GTiffRasterBand( this, iBand+1 ) );
+    }
+
+    if( GetRasterBand(1)->GetRasterDataType() == GDT_Unknown )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Unsupported TIFF configuration." );
+        return CE_Failure;
     }
 
+    m_bReadGeoTransform = bReadGeoTransform;
+
 /* -------------------------------------------------------------------- */
 /*      Capture some other potentially interesting information.         */
 /* -------------------------------------------------------------------- */
-    char	szWorkMDI[200];
+    char szWorkMDI[200];
     uint16  nShort;
 
     size_t iTag;
@@ -9916,15 +11363,15 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
         if( asTIFFTags[iTag].eType == GTIFFTAGTYPE_STRING )
         {
             if( TIFFGetField( hTIFF, asTIFFTags[iTag].nTagVal, &pszText ) )
-                SetMetadataItem( asTIFFTags[iTag].pszTagName,  pszText );
+                oGTiffMDMD.SetMetadataItem( asTIFFTags[iTag].pszTagName,  pszText );
         }
         else if( asTIFFTags[iTag].eType == GTIFFTAGTYPE_FLOAT )
         {
             float   fVal;
             if( TIFFGetField( hTIFF, asTIFFTags[iTag].nTagVal, &fVal ) )
             {
-                CPLsprintf( szWorkMDI, "%.8g", fVal );
-                SetMetadataItem( asTIFFTags[iTag].pszTagName, szWorkMDI );
+                CPLsnprintf( szWorkMDI, sizeof(szWorkMDI), "%.8g", fVal );
+                oGTiffMDMD.SetMetadataItem( asTIFFTags[iTag].pszTagName, szWorkMDI );
             }
         }
         else if( asTIFFTags[iTag].eType == GTIFFTAGTYPE_SHORT &&
@@ -9932,8 +11379,8 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
         {
             if( TIFFGetField( hTIFF, asTIFFTags[iTag].nTagVal, &nShort ) )
             {
-                sprintf( szWorkMDI, "%d", nShort );
-                SetMetadataItem( asTIFFTags[iTag].pszTagName, szWorkMDI );
+                snprintf( szWorkMDI, sizeof(szWorkMDI), "%d", nShort );
+                oGTiffMDMD.SetMetadataItem( asTIFFTags[iTag].pszTagName, szWorkMDI );
             }
         }
     }
@@ -9941,21 +11388,21 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
     if( TIFFGetField( hTIFF, TIFFTAG_RESOLUTIONUNIT, &nShort ) )
     {
         if( nShort == RESUNIT_NONE )
-            sprintf( szWorkMDI, "%d (unitless)", nShort );
+            snprintf( szWorkMDI, sizeof(szWorkMDI), "%d (unitless)", nShort );
         else if( nShort == RESUNIT_INCH )
-            sprintf( szWorkMDI, "%d (pixels/inch)", nShort );
+            snprintf( szWorkMDI, sizeof(szWorkMDI), "%d (pixels/inch)", nShort );
         else if( nShort == RESUNIT_CENTIMETER )
-            sprintf( szWorkMDI, "%d (pixels/cm)", nShort );
+            snprintf( szWorkMDI, sizeof(szWorkMDI), "%d (pixels/cm)", nShort );
         else
-            sprintf( szWorkMDI, "%d", nShort );
-        SetMetadataItem( "TIFFTAG_RESOLUTIONUNIT", szWorkMDI );
+            snprintf( szWorkMDI, sizeof(szWorkMDI), "%d", nShort );
+        oGTiffMDMD.SetMetadataItem( "TIFFTAG_RESOLUTIONUNIT", szWorkMDI );
     }
 
     int nTagSize;
     void* pData;
     if( TIFFGetField( hTIFF, TIFFTAG_XMLPACKET, &nTagSize, &pData ) )
     {
-        char* pszXMP = (char*)VSIMalloc(nTagSize + 1);
+        char* pszXMP = (char*)VSI_MALLOC_VERBOSE(nTagSize + 1);
         if (pszXMP)
         {
             memcpy(pszXMP, pData, nTagSize);
@@ -9964,7 +11411,7 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
             char *apszMDList[2];
             apszMDList[0] = pszXMP;
             apszMDList[1] = NULL;
-            SetMetadata(apszMDList, "xml:XMP");
+            oGTiffMDMD.SetMetadata(apszMDList, "xml:XMP");
 
             CPLFree(pszXMP);
         }
@@ -9973,75 +11420,75 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
     if( nCompression == COMPRESSION_NONE )
         /* no compression tag */;
     else if( nCompression == COMPRESSION_CCITTRLE )
-        SetMetadataItem( "COMPRESSION", "CCITTRLE", "IMAGE_STRUCTURE" );
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "CCITTRLE", "IMAGE_STRUCTURE" );
     else if( nCompression == COMPRESSION_CCITTFAX3 )
-        SetMetadataItem( "COMPRESSION", "CCITTFAX3", "IMAGE_STRUCTURE" );
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "CCITTFAX3", "IMAGE_STRUCTURE" );
     else if( nCompression == COMPRESSION_CCITTFAX4 )
-        SetMetadataItem( "COMPRESSION", "CCITTFAX4", "IMAGE_STRUCTURE" );
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "CCITTFAX4", "IMAGE_STRUCTURE" );
     else if( nCompression == COMPRESSION_LZW )
-        SetMetadataItem( "COMPRESSION", "LZW", "IMAGE_STRUCTURE" );
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "LZW", "IMAGE_STRUCTURE" );
     else if( nCompression == COMPRESSION_OJPEG )
-        SetMetadataItem( "COMPRESSION", "OJPEG", "IMAGE_STRUCTURE" );
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "OJPEG", "IMAGE_STRUCTURE" );
     else if( nCompression == COMPRESSION_JPEG )
-    {  
+    {
         if ( nPhotometric == PHOTOMETRIC_YCBCR )
-            SetMetadataItem( "COMPRESSION", "YCbCr JPEG", "IMAGE_STRUCTURE" );
+            oGTiffMDMD.SetMetadataItem( "COMPRESSION", "YCbCr JPEG", "IMAGE_STRUCTURE" );
         else
-            SetMetadataItem( "COMPRESSION", "JPEG", "IMAGE_STRUCTURE" );
+            oGTiffMDMD.SetMetadataItem( "COMPRESSION", "JPEG", "IMAGE_STRUCTURE" );
     }
     else if( nCompression == COMPRESSION_NEXT )
-        SetMetadataItem( "COMPRESSION", "NEXT", "IMAGE_STRUCTURE" );
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "NEXT", "IMAGE_STRUCTURE" );
     else if( nCompression == COMPRESSION_CCITTRLEW )
-        SetMetadataItem( "COMPRESSION", "CCITTRLEW", "IMAGE_STRUCTURE" );
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "CCITTRLEW", "IMAGE_STRUCTURE" );
     else if( nCompression == COMPRESSION_PACKBITS )
-        SetMetadataItem( "COMPRESSION", "PACKBITS", "IMAGE_STRUCTURE" );
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "PACKBITS", "IMAGE_STRUCTURE" );
     else if( nCompression == COMPRESSION_THUNDERSCAN )
-        SetMetadataItem( "COMPRESSION", "THUNDERSCAN", "IMAGE_STRUCTURE" );
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "THUNDERSCAN", "IMAGE_STRUCTURE" );
     else if( nCompression == COMPRESSION_PIXARFILM )
-        SetMetadataItem( "COMPRESSION", "PIXARFILM", "IMAGE_STRUCTURE" );
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "PIXARFILM", "IMAGE_STRUCTURE" );
     else if( nCompression == COMPRESSION_PIXARLOG )
-        SetMetadataItem( "COMPRESSION", "PIXARLOG", "IMAGE_STRUCTURE" );
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "PIXARLOG", "IMAGE_STRUCTURE" );
     else if( nCompression == COMPRESSION_DEFLATE )
-        SetMetadataItem( "COMPRESSION", "DEFLATE", "IMAGE_STRUCTURE" );
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "DEFLATE", "IMAGE_STRUCTURE" );
     else if( nCompression == COMPRESSION_ADOBE_DEFLATE )
-        SetMetadataItem( "COMPRESSION", "DEFLATE", "IMAGE_STRUCTURE" );
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "DEFLATE", "IMAGE_STRUCTURE" );
     else if( nCompression == COMPRESSION_DCS )
-        SetMetadataItem( "COMPRESSION", "DCS", "IMAGE_STRUCTURE" );
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "DCS", "IMAGE_STRUCTURE" );
     else if( nCompression == COMPRESSION_JBIG )
-        SetMetadataItem( "COMPRESSION", "JBIG", "IMAGE_STRUCTURE" );
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "JBIG", "IMAGE_STRUCTURE" );
     else if( nCompression == COMPRESSION_SGILOG )
-        SetMetadataItem( "COMPRESSION", "SGILOG", "IMAGE_STRUCTURE" );
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "SGILOG", "IMAGE_STRUCTURE" );
     else if( nCompression == COMPRESSION_SGILOG24 )
-        SetMetadataItem( "COMPRESSION", "SGILOG24", "IMAGE_STRUCTURE" );
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "SGILOG24", "IMAGE_STRUCTURE" );
     else if( nCompression == COMPRESSION_JP2000 )
-        SetMetadataItem( "COMPRESSION", "JP2000", "IMAGE_STRUCTURE" );
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "JP2000", "IMAGE_STRUCTURE" );
     else if( nCompression == COMPRESSION_LZMA )
-        SetMetadataItem( "COMPRESSION", "LZMA", "IMAGE_STRUCTURE" );
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "LZMA", "IMAGE_STRUCTURE" );
 
     else
     {
         CPLString oComp;
-        SetMetadataItem( "COMPRESSION", 
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION",
                          (const char *) oComp.Printf( "%d", nCompression));
     }
 
     if( nPlanarConfig == PLANARCONFIG_CONTIG && nBands != 1 )
-        SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
+        oGTiffMDMD.SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
     else
-        SetMetadataItem( "INTERLEAVE", "BAND", "IMAGE_STRUCTURE" );
+        oGTiffMDMD.SetMetadataItem( "INTERLEAVE", "BAND", "IMAGE_STRUCTURE" );
 
     if(  (GetRasterBand(1)->GetRasterDataType() == GDT_Byte   && nBitsPerSample != 8 ) ||
          (GetRasterBand(1)->GetRasterDataType() == GDT_UInt16 && nBitsPerSample != 16) ||
          (GetRasterBand(1)->GetRasterDataType() == GDT_UInt32 && nBitsPerSample != 32) )
     {
         for (int i = 0; i < nBands; ++i)
-            GetRasterBand(i+1)->SetMetadataItem( "NBITS", 
+            static_cast<GTiffRasterBand*>(GetRasterBand(i+1))->oGTiffMDMD.SetMetadataItem( "NBITS",
                                                  CPLString().Printf( "%d", (int)nBitsPerSample ),
                                                  "IMAGE_STRUCTURE" );
     }
-        
+
     if( bMinIsWhite )
-        SetMetadataItem( "MINISWHITE", "YES", "IMAGE_STRUCTURE" );
+        oGTiffMDMD.SetMetadataItem( "MINISWHITE", "YES", "IMAGE_STRUCTURE" );
 
     if( TIFFGetField( hTIFF, TIFFTAG_GDAL_METADATA, &pszText ) )
     {
@@ -10054,103 +11501,357 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
 
         for( ; psItem != NULL; psItem = psItem->psNext )
         {
-            const char *pszKey, *pszValue, *pszRole, *pszDomain; 
-            char *pszUnescapedValue;
-            int nBand, bIsXML = FALSE;
 
             if( psItem->eType != CXT_Element
                 || !EQUAL(psItem->pszValue,"Item") )
                 continue;
 
-            pszKey = CPLGetXMLValue( psItem, "name", NULL );
-            pszValue = CPLGetXMLValue( psItem, NULL, NULL );
-            nBand = atoi(CPLGetXMLValue( psItem, "sample", "-1" )) + 1;
-            pszRole = CPLGetXMLValue( psItem, "role", "" );
-            pszDomain = CPLGetXMLValue( psItem, "domain", "" );
-                
+            const char *pszKey = CPLGetXMLValue( psItem, "name", NULL );
+            const char *pszValue = CPLGetXMLValue( psItem, NULL, NULL );
+            const int nBand = atoi(CPLGetXMLValue( psItem, "sample", "-1" )) + 1;
+            const char *pszRole = CPLGetXMLValue( psItem, "role", "" );
+            const char *pszDomain = CPLGetXMLValue( psItem, "domain", "" );
+
             if( pszKey == NULL || pszValue == NULL )
                 continue;
 
-            if( EQUALN(pszDomain,"xml:",4) )
+            bool bIsXML = false;
+
+            if( STARTS_WITH_CI(pszDomain, "xml:") )
                 bIsXML = TRUE;
 
-            pszUnescapedValue = CPLUnescapeString( pszValue, NULL, 
-                                                   CPLES_XML );
+            char *pszUnescapedValue
+                = CPLUnescapeString( pszValue, NULL, CPLES_XML );
             if( nBand == 0 )
             {
                 if( bIsXML )
                 {
                     char *apszMD[2] = { pszUnescapedValue, NULL };
-                    SetMetadata( apszMD, pszDomain );
+                    oGTiffMDMD.SetMetadata( apszMD, pszDomain );
                 }
                 else
-                    SetMetadataItem( pszKey, pszUnescapedValue, pszDomain );
+                    oGTiffMDMD.SetMetadataItem( pszKey, pszUnescapedValue, pszDomain );
             }
             else
             {
-                GDALRasterBand *poBand = GetRasterBand(nBand);
+                GTiffRasterBand *poBand = static_cast<GTiffRasterBand*>(GetRasterBand(nBand));
                 if( poBand != NULL )
                 {
                     if( EQUAL(pszRole,"scale") )
-                        poBand->SetScale( CPLAtofM(pszUnescapedValue) );
+                    {
+                        poBand->bHaveOffsetScale = TRUE;
+                        poBand->dfScale = CPLAtofM(pszUnescapedValue);
+                    }
                     else if( EQUAL(pszRole,"offset") )
-                        poBand->SetOffset( CPLAtofM(pszUnescapedValue) );
+                    {
+                        poBand->bHaveOffsetScale = TRUE;
+                        poBand->dfOffset = CPLAtofM(pszUnescapedValue);
+                    }
                     else if( EQUAL(pszRole,"unittype") )
-                        poBand->SetUnitType( pszUnescapedValue );
+                        poBand->osUnitType = pszUnescapedValue;
                     else if( EQUAL(pszRole,"description") )
-                        poBand->SetDescription( pszUnescapedValue );
+                        poBand->osDescription = pszUnescapedValue;
                     else
                     {
                         if( bIsXML )
                         {
                             char *apszMD[2] = { pszUnescapedValue, NULL };
-                            poBand->SetMetadata( apszMD, pszDomain );
+                            poBand->oGTiffMDMD.SetMetadata( apszMD, pszDomain );
                         }
                         else
-                            poBand->SetMetadataItem(pszKey,pszUnescapedValue,
+                            poBand->oGTiffMDMD.SetMetadataItem(pszKey,pszUnescapedValue,
                                                     pszDomain );
                     }
                 }
             }
-            CPLFree( pszUnescapedValue );
+            CPLFree( pszUnescapedValue );
+        }
+
+        CPLDestroyXMLNode( psRoot );
+    }
+
+    if( bStreamingIn )
+    {
+        toff_t* panOffsets = NULL;
+        TIFFGetField( hTIFF, (TIFFIsTiled( hTIFF )) ? TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS , &panOffsets );
+        if( panOffsets )
+        {
+            int nBlockCount = ( TIFFIsTiled(hTIFF) ) ? TIFFNumberOfTiles(hTIFF) : TIFFNumberOfStrips(hTIFF);
+            for(int i=1;i<nBlockCount;i++)
+            {
+                if( panOffsets[i] < panOffsets[i-1] )
+                {
+                    oGTiffMDMD.SetMetadataItem("UNORDERED_BLOCKS", "YES", "TIFF");
+                    CPLDebug("GTIFF",
+                             "Offset of block %d is lower than previous block. Reader must be careful",
+                             i);
+                    break;
+                }
+            }
+        }
+    }
+
+    CPLAssert(m_bReadGeoTransform == bReadGeoTransform);
+    CPLAssert(!bMetadataChanged);
+    bMetadataChanged = FALSE;
+
+    return( CE_None );
+}
+
+/************************************************************************/
+/*                         GetSiblingFiles()                            */
+/************************************************************************/
+
+char** GTiffDataset::GetSiblingFiles()
+{
+    char** papszSiblingFiles;
+    if( m_bHasGotSiblingFiles )
+        papszSiblingFiles = oOvManager.GetSiblingFiles();
+    else
+    {
+        m_bHasGotSiblingFiles = true;
+        const int nMaxFiles = atoi(CPLGetConfigOption("GDAL_READDIR_LIMIT_ON_OPEN", "1000"));
+        papszSiblingFiles = VSIReadDirEx(CPLGetDirname(osFilename), nMaxFiles);
+        if( nMaxFiles > 0 && CSLCount(papszSiblingFiles) > nMaxFiles )
+        {
+            CPLDebug("GTiff", "GDAL_READDIR_LIMIT_ON_OPEN reached on %s",
+                     CPLGetDirname(osFilename));
+            CSLDestroy(papszSiblingFiles);
+            papszSiblingFiles = NULL;
+        }
+        oOvManager.TransferSiblingFiles( papszSiblingFiles );
+    }
+    return papszSiblingFiles;
+}
+
+/************************************************************************/
+/*                     LoadGeoreferencingAndPamIfNeeded()               */
+/************************************************************************/
+
+void GTiffDataset::LoadGeoreferencingAndPamIfNeeded()
+
+{
+/* -------------------------------------------------------------------- */
+/*      Get the transform or gcps from the GeoTIFF file.                */
+/* -------------------------------------------------------------------- */
+    if( m_bReadGeoTransform )
+    {
+        char    *pszTabWKT = NULL;
+        double  *padfTiePoints, *padfScale, *padfMatrix;
+        uint16  nCount;
+        bool    bPixelIsPoint = false;
+        short nRasterType;
+        bool bPointGeoIgnore = false;
+
+        m_bReadGeoTransform = false;
+
+        if( !SetDirectory() )
+            return;
+
+        GTIF    *psGTIF = GTIFNew( hTIFF ); // I wonder how expensive this is?
+
+        if( psGTIF )
+        {
+            if( GDALGTIFKeyGetSHORT(psGTIF, GTRasterTypeGeoKey, &nRasterType,
+                        0, 1 ) == 1
+                && nRasterType == (short) RasterPixelIsPoint )
+            {
+                bPixelIsPoint = true;
+                bPointGeoIgnore =
+                    CPLTestBool( CPLGetConfigOption("GTIFF_POINT_GEO_IGNORE",
+                                                    "FALSE") );
+            }
+
+            GTIFFree( psGTIF );
+        }
+
+        adfGeoTransform[0] = 0.0;
+        adfGeoTransform[1] = 1.0;
+        adfGeoTransform[2] = 0.0;
+        adfGeoTransform[3] = 0.0;
+        adfGeoTransform[4] = 0.0;
+        adfGeoTransform[5] = 1.0;
+
+        if( TIFFGetField(hTIFF,TIFFTAG_GEOPIXELSCALE,&nCount,&padfScale )
+            && nCount >= 2
+            && padfScale[0] != 0.0 && padfScale[1] != 0.0 )
+        {
+            adfGeoTransform[1] = padfScale[0];
+            adfGeoTransform[5] = - ABS(padfScale[1]);
+
+            if( TIFFGetField(hTIFF,TIFFTAG_GEOTIEPOINTS,&nCount,&padfTiePoints )
+                && nCount >= 6 )
+            {
+                adfGeoTransform[0] =
+                    padfTiePoints[3] - padfTiePoints[0] * adfGeoTransform[1];
+                adfGeoTransform[3] =
+                    padfTiePoints[4] - padfTiePoints[1] * adfGeoTransform[5];
+
+                if( bPixelIsPoint && !bPointGeoIgnore )
+                {
+                    adfGeoTransform[0] -= (adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5);
+                    adfGeoTransform[3] -= (adfGeoTransform[4] * 0.5 + adfGeoTransform[5] * 0.5);
+                }
+
+                bGeoTransformValid = TRUE;
+            }
+        }
+
+        else if( TIFFGetField(hTIFF,TIFFTAG_GEOTRANSMATRIX,&nCount,&padfMatrix )
+                 && nCount == 16 )
+        {
+            adfGeoTransform[0] = padfMatrix[3];
+            adfGeoTransform[1] = padfMatrix[0];
+            adfGeoTransform[2] = padfMatrix[1];
+            adfGeoTransform[3] = padfMatrix[7];
+            adfGeoTransform[4] = padfMatrix[4];
+            adfGeoTransform[5] = padfMatrix[5];
+
+            if( bPixelIsPoint && !bPointGeoIgnore )
+            {
+                adfGeoTransform[0] -= (adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5);
+                adfGeoTransform[3] -= (adfGeoTransform[4] * 0.5 + adfGeoTransform[5] * 0.5);
+            }
+
+            bGeoTransformValid = TRUE;
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Otherwise try looking for a .tab, .tfw, .tifw or .wld file.     */
+/* -------------------------------------------------------------------- */
+        else
+        {
+            char* pszGeorefFilename = NULL;
+
+            char** papszSiblingFiles = GetSiblingFiles();
+
+            /* Begin with .tab since it can also have projection info */
+            int bTabFileOK =
+                GDALReadTabFile2( osFilename, adfGeoTransform,
+                                    &pszTabWKT, &nGCPCount, &pasGCPList,
+                                    papszSiblingFiles, &pszGeorefFilename );
+
+            if( bTabFileOK )
+            {
+                if( nGCPCount == 0 )
+                    bGeoTransformValid = TRUE;
+            }
+            else
+            {
+                if( !bGeoTransformValid )
+                {
+                    bGeoTransformValid =
+                        GDALReadWorldFile2( osFilename, NULL, adfGeoTransform,
+                                            papszSiblingFiles, &pszGeorefFilename);
+                }
+
+                if( !bGeoTransformValid )
+                {
+                    bGeoTransformValid =
+                        GDALReadWorldFile2( osFilename, "wld", adfGeoTransform,
+                                            papszSiblingFiles, &pszGeorefFilename);
+                }
+            }
+
+            if (pszGeorefFilename)
+            {
+                osGeorefFilename = pszGeorefFilename;
+                CPLFree(pszGeorefFilename);
+            }
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Check for GCPs.  Note, we will allow there to be GCPs and a     */
+/*      transform in some circumstances.                                */
+/* -------------------------------------------------------------------- */
+        if( TIFFGetField(hTIFF,TIFFTAG_GEOTIEPOINTS,&nCount,&padfTiePoints )
+            && !bGeoTransformValid )
+        {
+            nGCPCount = nCount / 6;
+            pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),nGCPCount);
+
+            for( int iGCP = 0; iGCP < nGCPCount; iGCP++ )
+            {
+                char    szID[32];
+
+                snprintf( szID, sizeof(szID), "%d", iGCP+1 );
+                pasGCPList[iGCP].pszId = CPLStrdup( szID );
+                pasGCPList[iGCP].pszInfo = CPLStrdup("");
+                pasGCPList[iGCP].dfGCPPixel = padfTiePoints[iGCP*6+0];
+                pasGCPList[iGCP].dfGCPLine = padfTiePoints[iGCP*6+1];
+                pasGCPList[iGCP].dfGCPX = padfTiePoints[iGCP*6+3];
+                pasGCPList[iGCP].dfGCPY = padfTiePoints[iGCP*6+4];
+                pasGCPList[iGCP].dfGCPZ = padfTiePoints[iGCP*6+5];
+
+                if( bPixelIsPoint && !bPointGeoIgnore )
+                {
+                    pasGCPList[iGCP].dfGCPPixel -= 0.5;
+                    pasGCPList[iGCP].dfGCPLine -= 0.5;
+                }
+            }
         }
 
-        CPLDestroyXMLNode( psRoot );
-    }
-    
-    if( bStreamingIn )
-    {
-        toff_t* panOffsets = NULL;
-        TIFFGetField( hTIFF, (TIFFIsTiled( hTIFF )) ? TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS , &panOffsets );
-        if( panOffsets )
+/* -------------------------------------------------------------------- */
+/*      Did we find a tab file?  If so we will use it's coordinate      */
+/*      system and give it precedence.                                  */
+/* -------------------------------------------------------------------- */
+        if( pszTabWKT != NULL
+            && (pszProjection == NULL || pszProjection[0] == '\0') )
         {
-            int nBlockCount = ( TIFFIsTiled(hTIFF) ) ? TIFFNumberOfTiles(hTIFF) : TIFFNumberOfStrips(hTIFF);
-            for(int i=1;i<nBlockCount;i++)
-            {
-                if( panOffsets[i] < panOffsets[i-1] )
-                {
-                    SetMetadataItem("UNORDERED_BLOCKS", "YES", "TIFF");
-                    CPLDebug("GTIFF",
-                             "Offset of block %d is lower than previous block. Reader must be careful",
-                             i);
-                    break;
-                }
-            }
+            CPLFree( pszProjection );
+            pszProjection = pszTabWKT;
+            pszTabWKT = NULL;
+            bLookedForProjection = TRUE;
         }
+
+        CPLFree( pszTabWKT );
     }
 
-    bMetadataChanged = FALSE;
+
+
+    if( m_bLoadPam )
+    {
+        m_bLoadPam = false;
 
 /* -------------------------------------------------------------------- */
-/*      If this is a "base" raster, we should scan for any              */
-/*      associated overviews, internal mask bands and subdatasets.      */
+/*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
-    if( bBase )
-    {
-        //ScanDirectories();
-    }
+        CPLAssert(!bColorProfileMetadataChanged);
+        CPLAssert(!bMetadataChanged);
+        CPLAssert(!bGeoTIFFInfoChanged);
+        CPLAssert(!bNoDataChanged);
 
-    return( CE_None );
+        TryLoadXML( GetSiblingFiles() );
+        ApplyPamInfo();
+
+        bColorProfileMetadataChanged = FALSE;
+        bMetadataChanged = FALSE;
+        bGeoTIFFInfoChanged = FALSE;
+        bNoDataChanged = FALSE;
+
+        int i;
+        for(i=1;i<=nBands;i++)
+        {
+            GTiffRasterBand* poBand = (GTiffRasterBand*) GetRasterBand(i);
+
+            /* Load scale, offset and unittype from PAM if available */
+            if (!poBand->bHaveOffsetScale)
+            {
+                poBand->dfScale = poBand->GDALPamRasterBand::GetScale(&poBand->bHaveOffsetScale);
+                poBand->dfOffset = poBand->GDALPamRasterBand::GetOffset();
+            }
+            if (poBand->osUnitType.size() == 0)
+            {
+                const char* pszUnitType = poBand->GDALPamRasterBand::GetUnitType();
+                if (pszUnitType)
+                    poBand->osUnitType = pszUnitType;
+            }
+
+            GDALColorInterp ePAMColorInterp = poBand->GDALPamRasterBand::GetColorInterpretation();
+            if( ePAMColorInterp != GCI_Undefined )
+                poBand->eBandInterp = ePAMColorInterp;
+        }
+    }
 }
 
 /************************************************************************/
@@ -10185,8 +11886,8 @@ void GTiffDataset::ScanDirectories()
     CPLStringList aosSubdatasets;
     int  iDirIndex = 0;
 
-    FlushDirectory();  
-    while( !TIFFLastDirectory( hTIFF ) 
+    FlushDirectory();
+    while( !TIFFLastDirectory( hTIFF )
            && (iDirIndex == 0 || TIFFReadDirectory( hTIFF ) != 0) )
     {
         /* Only libtiff 4.0.4 can handle between 32768 and 65535 directories */
@@ -10194,11 +11895,11 @@ void GTiffDataset::ScanDirectories()
         if( iDirIndex == 32768 )
             break;
 #endif
-        toff_t	nThisDir = TIFFCurrentDirOffset(hTIFF);
-        uint32	nSubType = 0;
+        toff_t nThisDir = TIFFCurrentDirOffset(hTIFF);
+        uint32 nSubType = 0;
 
         *ppoActiveDSRef = NULL; // our directory no longer matches this ds
-            
+
         iDirIndex++;
 
         if( !TIFFGetField(hTIFF, TIFFTAG_SUBFILETYPE, &nSubType) )
@@ -10210,28 +11911,26 @@ void GTiffDataset::ScanDirectories()
             iDirIndex != 1 &&
             nOverviewCount < 30 /* to avoid DoS */ )
         {
-            GTiffDataset	*poODS;
-                
-            poODS = new GTiffDataset();
-            if( poODS->OpenOffset( hTIFF, ppoActiveDSRef, nThisDir, FALSE, 
-                                   eAccess ) != CE_None 
+            GTiffDataset *poODS = new GTiffDataset();
+            if( poODS->OpenOffset( hTIFF, ppoActiveDSRef, nThisDir, FALSE,
+                                   eAccess ) != CE_None
                 || poODS->GetRasterCount() != GetRasterCount() )
             {
                 delete poODS;
             }
             else
             {
-                CPLDebug( "GTiff", "Opened %dx%d overview.\n", 
+                CPLDebug( "GTiff", "Opened %dx%d overview.\n",
                           poODS->GetRasterXSize(), poODS->GetRasterYSize());
                 nOverviewCount++;
                 papoOverviewDS = (GTiffDataset **)
-                    CPLRealloc(papoOverviewDS, 
+                    CPLRealloc(papoOverviewDS,
                                nOverviewCount * (sizeof(void*)));
                 papoOverviewDS[nOverviewCount-1] = poODS;
                 poODS->poBaseDS = this;
             }
         }
-            
+
         /* Embedded mask of the main image */
         else if ((nSubType & FILETYPE_MASK) != 0 &&
                  (nSubType & FILETYPE_REDUCEDIMAGE) == 0 &&
@@ -10239,7 +11938,7 @@ void GTiffDataset::ScanDirectories()
                  poMaskDS == NULL )
         {
             poMaskDS = new GTiffDataset();
-                
+
             /* The TIFF6 specification - page 37 - only allows 1 SamplesPerPixel and 1 BitsPerSample
                Here we support either 1 or 8 bit per sample
                and we support either 1 sample per pixel or as many samples as in the main image
@@ -10249,8 +11948,8 @@ void GTiffDataset::ScanDirectories()
                the main image, what we don't support here
             */
 
-            if( poMaskDS->OpenOffset( hTIFF, ppoActiveDSRef, nThisDir, 
-                                      FALSE, eAccess ) != CE_None 
+            if( poMaskDS->OpenOffset( hTIFF, ppoActiveDSRef, nThisDir,
+                                      FALSE, eAccess ) != CE_None
                 || poMaskDS->GetRasterCount() == 0
                 || !(poMaskDS->GetRasterCount() == 1 || poMaskDS->GetRasterCount() == GetRasterCount())
                 || poMaskDS->GetRasterXSize() != GetRasterXSize()
@@ -10264,11 +11963,11 @@ void GTiffDataset::ScanDirectories()
             {
                 CPLDebug( "GTiff", "Opened band mask.\n");
                 poMaskDS->poBaseDS = this;
-                    
-                poMaskDS->bPromoteTo8Bits = CSLTestBoolean(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK_TO_8BIT", "YES"));
+
+                poMaskDS->bPromoteTo8Bits = CPLTestBool(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK_TO_8BIT", "YES"));
             }
         }
-            
+
         /* Embedded mask of an overview */
         /* The TIFF6 specification allows the combination of the FILETYPE_xxxx masks */
         else if ((nSubType & FILETYPE_REDUCEDIMAGE) != 0 &&
@@ -10276,7 +11975,7 @@ void GTiffDataset::ScanDirectories()
                  iDirIndex != 1)
         {
             GTiffDataset* poDS = new GTiffDataset();
-            if( poDS->OpenOffset( hTIFF, ppoActiveDSRef, nThisDir, FALSE, 
+            if( poDS->OpenOffset( hTIFF, ppoActiveDSRef, nThisDir, FALSE,
                                   eAccess ) != CE_None
                 || poDS->GetRasterCount() == 0
                 || poDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte)
@@ -10296,7 +11995,7 @@ void GTiffDataset::ScanDirectories()
                         CPLDebug( "GTiff", "Opened band mask for %dx%d overview.\n",
                                   poDS->GetRasterXSize(), poDS->GetRasterYSize());
                         ((GTiffDataset*)papoOverviewDS[i])->poMaskDS = poDS;
-                        poDS->bPromoteTo8Bits = CSLTestBoolean(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK_TO_8BIT", "YES"));
+                        poDS->bPromoteTo8Bits = CPLTestBool(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK_TO_8BIT", "YES"));
                         poDS->poBaseDS = this;
                         break;
                     }
@@ -10308,19 +12007,19 @@ void GTiffDataset::ScanDirectories()
             }
         }
         else if( nSubType == 0 || nSubType == FILETYPE_PAGE ) {
-            CPLString osName, osDesc;
-            uint32	nXSize, nYSize;
-            uint16  nSPP;
+            uint32 nXSize, nYSize;
+            uint16 nSPP;
 
             TIFFGetField( hTIFF, TIFFTAG_IMAGEWIDTH, &nXSize );
             TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &nYSize );
             if( !TIFFGetField(hTIFF, TIFFTAG_SAMPLESPERPIXEL, &nSPP ) )
                 nSPP = 1;
 
-            osName.Printf( "SUBDATASET_%d_NAME=GTIFF_DIR:%d:%s", 
+            CPLString osName, osDesc;
+            osName.Printf( "SUBDATASET_%d_NAME=GTIFF_DIR:%d:%s",
                            iDirIndex, iDirIndex, osFilename.c_str() );
-            osDesc.Printf( "SUBDATASET_%d_DESC=Page %d (%dP x %dL x %dB)", 
-                           iDirIndex, iDirIndex, 
+            osDesc.Printf( "SUBDATASET_%d_DESC=Page %d (%dP x %dL x %dB)",
+                           iDirIndex, iDirIndex,
                            (int)nXSize, (int)nYSize, nSPP );
 
             aosSubdatasets.AddString(osName);
@@ -10338,14 +12037,13 @@ void GTiffDataset::ScanDirectories()
     /* have a mask, let's set this mask as an overview of the main mask... */
     if (poMaskDS != NULL)
     {
-        int i;
-        for(i=0;i<nOverviewCount;i++)
+        for(int i=0;i<nOverviewCount;i++)
         {
             if (((GTiffDataset*)papoOverviewDS[i])->poMaskDS != NULL)
             {
                 poMaskDS->nOverviewCount++;
                 poMaskDS->papoOverviewDS = (GTiffDataset **)
-                    CPLRealloc(poMaskDS->papoOverviewDS, 
+                    CPLRealloc(poMaskDS->papoOverviewDS,
                                poMaskDS->nOverviewCount * (sizeof(void*)));
                 poMaskDS->papoOverviewDS[poMaskDS->nOverviewCount-1] =
                     ((GTiffDataset*)papoOverviewDS[i])->poMaskDS;
@@ -10359,7 +12057,7 @@ void GTiffDataset::ScanDirectories()
 /* -------------------------------------------------------------------- */
     if( aosSubdatasets.size() > 2 )
     {
-        oGTiffMDMD.SetMetadata( aosSubdatasets.StealList(), "SUBDATASETS" );
+        oGTiffMDMD.SetMetadata( aosSubdatasets.List(), "SUBDATASETS" );
     }
 }
 
@@ -10392,7 +12090,7 @@ static int GTiffGetZLevel(char** papszOptions)
         nZLevel =  atoi( pszValue );
         if (!(nZLevel >= 1 && nZLevel <= 9))
         {
-            CPLError( CE_Warning, CPLE_IllegalArg, 
+            CPLError( CE_Warning, CPLE_IllegalArg,
                     "ZLEVEL=%s value not recognised, ignoring.",
                     pszValue );
             nZLevel = -1;
@@ -10410,7 +12108,7 @@ static int GTiffGetJpegQuality(char** papszOptions)
         nJpegQuality = atoi( pszValue );
         if (!(nJpegQuality >= 1 && nJpegQuality <= 100))
         {
-            CPLError( CE_Warning, CPLE_IllegalArg, 
+            CPLError( CE_Warning, CPLE_IllegalArg,
                     "JPEG_QUALITY=%s value not recognised, ignoring.",
                     pszValue );
             nJpegQuality = -1;
@@ -10434,7 +12132,7 @@ void GTiffDataset::GetDiscardLsbOption(char** papszOptions)
     const char* pszBits = CSLFetchNameValue( papszOptions, "DISCARD_LSB" );
     if( pszBits == NULL)
         return;
-    
+
     if( nPhotometric == PHOTOMETRIC_PALETTE )
     {
         CPLError(CE_Warning, CPLE_AppDefined,
@@ -10500,29 +12198,28 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
                               CPLString& osTmpFilename )
 
 {
-    TIFF		*hTIFF;
+    if (!GTiffOneTimeInit())
+        return NULL;
+
+    TIFF *hTIFF;
     int                 nBlockXSize = 0, nBlockYSize = 0;
     int                 bTiled = FALSE;
     int                 nCompression = COMPRESSION_NONE;
-    int                 nPredictor = PREDICTOR_NONE, nJpegQuality = -1, nZLevel = -1,
-                        nLZMAPreset = -1, nJpegTablesMode = -1;
+    int                 nPredictor = PREDICTOR_NONE;
     uint16              nSampleFormat;
-    int			nPlanar;
+    int nPlanar;
     const char          *pszValue;
     const char          *pszProfile;
     int                 bCreateBigTIFF = FALSE;
 
-    if (!GTiffOneTimeInit())
-        return NULL;
-
 /* -------------------------------------------------------------------- */
 /*      Blow on a few errors.                                           */
 /* -------------------------------------------------------------------- */
     if( nXSize < 1 || nYSize < 1 || nBands < 1 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Attempt to create %dx%dx%d TIFF file, but width, height and bands\n"
-                  "must be positive.", 
+                  "must be positive.",
                   nXSize, nYSize, nBands );
 
         return NULL;
@@ -10530,16 +12227,16 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
 
     if (nBands > 65535)
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Attempt to create %dx%dx%d TIFF file, but bands\n"
-                  "must be lesser or equal to 65535.", 
+                  "must be lesser or equal to 65535.",
                   nXSize, nYSize, nBands );
 
         return NULL;
     }
 
 /* -------------------------------------------------------------------- */
-/*	Setup values based on options.					*/
+/*      Setup values based on options.                                  */
 /* -------------------------------------------------------------------- */
     pszProfile = CSLFetchNameValue(papszParmList,"PROFILE");
     if( pszProfile == NULL )
@@ -10565,13 +12262,13 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
             nPlanar = PLANARCONFIG_SEPARATE;
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "INTERLEAVE=%s unsupported, value must be PIXEL or BAND.",
                       pszValue );
             return NULL;
         }
     }
-    else 
+    else
     {
         nPlanar = PLANARCONFIG_CONTIG;
     }
@@ -10588,10 +12285,10 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
     if( pszValue  != NULL )
         nPredictor =  atoi( pszValue );
 
-    nZLevel = GTiffGetZLevel(papszParmList);
-    nLZMAPreset = GTiffGetLZMAPreset(papszParmList);
-    nJpegQuality = GTiffGetJpegQuality(papszParmList);
-    nJpegTablesMode = GTiffGetJpegTablesMode(papszParmList);
+    int nZLevel = GTiffGetZLevel(papszParmList);
+    int nLZMAPreset = GTiffGetLZMAPreset(papszParmList);
+    int nJpegQuality = GTiffGetJpegQuality(papszParmList);
+    int nJpegTablesMode = GTiffGetJpegTablesMode(papszParmList);
 
 /* -------------------------------------------------------------------- */
 /*      Streaming related code                                          */
@@ -10637,17 +12334,15 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Compute the uncompressed size.                                  */
 /* -------------------------------------------------------------------- */
-    double  dfUncompressedImageSize;
-
-    dfUncompressedImageSize = 
-        nXSize * ((double)nYSize) * nBands * (GDALGetDataTypeSize(eType)/8);
+    double  dfUncompressedImageSize
+        = nXSize * ((double)nYSize) * nBands * (GDALGetDataTypeSize(eType)/8);
     dfUncompressedImageSize += dfExtraSpaceForOverviews;
 
-    if( nCompression == COMPRESSION_NONE 
+    if( nCompression == COMPRESSION_NONE
         && dfUncompressedImageSize > 4200000000.0 )
     {
 #ifndef BIGTIFF_SUPPORT
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "A %d pixels x %d lines x %d bands %s image would be larger than 4GB\n"
                   "but this is the largest size a TIFF can be, and BigTIFF is unavailable.\n"
                   "Creation failed.",
@@ -10657,6 +12352,27 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
     }
 
 /* -------------------------------------------------------------------- */
+/*      Check free space (only for big, non sparse, uncompressed)       */
+/* -------------------------------------------------------------------- */
+    if( nCompression == COMPRESSION_NONE &&
+        dfUncompressedImageSize >= 1e9 &&
+        !CSLFetchBoolean(papszParmList, "SPARSE_OK", FALSE) &&
+        CPLTestBool(CPLGetConfigOption("CHECK_DISK_FREE_SPACE", "TRUE")) )
+    {
+        GIntBig nFreeDiskSpace = VSIGetDiskFreeSpace(CPLGetDirname(pszFilename));
+        if( nFreeDiskSpace >= 0 &&
+            nFreeDiskSpace < dfUncompressedImageSize )
+        {
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Free disk space available is " CPL_FRMT_GIB " bytes, "
+                      "whereas " CPL_FRMT_GIB " are at least necessary.",
+                      nFreeDiskSpace,
+                      static_cast<GIntBig>(dfUncompressedImageSize) );
+            return NULL;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Should the file be created as a bigtiff file?                   */
 /* -------------------------------------------------------------------- */
     const char *pszBIGTIFF = CSLFetchNameValue(papszParmList, "BIGTIFF");
@@ -10666,7 +12382,7 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
 
     if( EQUAL(pszBIGTIFF,"IF_NEEDED") )
     {
-        if( nCompression == COMPRESSION_NONE 
+        if( nCompression == COMPRESSION_NONE
             && dfUncompressedImageSize > 4200000000.0 )
             bCreateBigTIFF = TRUE;
     }
@@ -10678,11 +12394,11 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
 
     else
     {
-        bCreateBigTIFF = CSLTestBoolean( pszBIGTIFF );
+        bCreateBigTIFF = CPLTestBool( pszBIGTIFF );
         if (!bCreateBigTIFF && nCompression == COMPRESSION_NONE &&
              dfUncompressedImageSize > 4200000000.0 )
         {
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                 "The TIFF file will be larger than 4GB, so BigTIFF is necessary.\n"
                 "Creation failed.");
             return NULL;
@@ -10701,7 +12417,7 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
 
     if( bCreateBigTIFF )
         CPLDebug( "GTiff", "File being created as a BigTIFF." );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Check if the user wishes a particular endianness                */
 /* -------------------------------------------------------------------- */
@@ -10760,7 +12476,7 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
                       "Attempt to create new tiff file `%s'\n"
                       "failed in XTIFFOpen().\n",
                       pszFilename );
-        VSIFCloseL(fpL);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpL));
         return NULL;
     }
 
@@ -10894,7 +12610,7 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
                 CPLError(CE_Failure, CPLE_NotSupported,
                          "Currently, PHOTOMETRIC=YCBCR requires COMPRESS=JPEG");
                 XTIFFClose(hTIFF);
-                VSIFCloseL(fpL);
+                CPL_IGNORE_RET_VAL(VSIFCloseL(fpL));
                 return NULL;
             }
 
@@ -10903,7 +12619,7 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
                 CPLError(CE_Failure, CPLE_NotSupported,
                          "PHOTOMETRIC=YCBCR requires INTERLEAVE=PIXEL");
                 XTIFFClose(hTIFF);
-                VSIFCloseL(fpL);
+                CPL_IGNORE_RET_VAL(VSIFCloseL(fpL));
                 return NULL;
             }
 
@@ -10915,7 +12631,7 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
                 CPLError(CE_Failure, CPLE_NotSupported,
                          "PHOTOMETRIC=YCBCR requires a source raster with only 3 bands (RGB)");
                 XTIFFClose(hTIFF);
-                VSIFCloseL(fpL);
+                CPL_IGNORE_RET_VAL(VSIFCloseL(fpL));
                 return NULL;
             }
 
@@ -10939,26 +12655,26 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
         }
         else
         {
-            CPLError( CE_Warning, CPLE_IllegalArg, 
+            CPLError( CE_Warning, CPLE_IllegalArg,
                       "PHOTOMETRIC=%s value not recognised, ignoring.\n"
-                      "Set the Photometric Interpretation as MINISBLACK.", 
+                      "Set the Photometric Interpretation as MINISBLACK.",
                       pszValue );
             TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK );
         }
 
         if ( nBands < nSamplesAccountedFor )
         {
-            CPLError( CE_Warning, CPLE_IllegalArg, 
+            CPLError( CE_Warning, CPLE_IllegalArg,
                       "PHOTOMETRIC=%s value does not correspond to number "
                       "of bands (%d), ignoring.\n"
-                      "Set the Photometric Interpretation as MINISBLACK.", 
+                      "Set the Photometric Interpretation as MINISBLACK.",
                       pszValue, nBands );
             TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK );
         }
     }
     else
     {
-        /* 
+        /*
          * If image contains 3 or 4 bands and datatype is Byte then we will
          * assume it is RGB. In all other cases assume it is MINISBLACK.
          */
@@ -10991,23 +12707,21 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
 /* -------------------------------------------------------------------- */
     if( nBands > nSamplesAccountedFor )
     {
-        uint16 *v;
-        int i;
         int nExtraSamples = nBands - nSamplesAccountedFor;
 
-        v = (uint16 *) CPLMalloc( sizeof(uint16) * nExtraSamples );
+        uint16 *v = (uint16 *) CPLMalloc( sizeof(uint16) * nExtraSamples );
 
         v[0] = GTiffGetAlphaValue(CSLFetchNameValue(papszParmList, "ALPHA"),
                                   EXTRASAMPLE_UNSPECIFIED);
 
-        for( i = 1; i < nExtraSamples; i++ )
+        for( int i = 1; i < nExtraSamples; i++ )
             v[i] = EXTRASAMPLE_UNSPECIFIED;
 
         TIFFSetField(hTIFF, TIFFTAG_EXTRASAMPLES, nExtraSamples, v );
-        
+
         CPLFree(v);
     }
-    
+
     /* Set the ICC color profile. */
     if (!EQUAL(pszProfile,"BASELINE"))
     {
@@ -11026,7 +12740,7 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
     {
         if( nBlockXSize == 0 )
             nBlockXSize = 256;
-        
+
         if( nBlockYSize == 0 )
             nBlockYSize = 256;
 
@@ -11034,7 +12748,7 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
             !TIFFSetField( hTIFF, TIFFTAG_TILELENGTH, nBlockYSize ))
         {
             XTIFFClose(hTIFF);
-            VSIFCloseL(fpL);
+            CPL_IGNORE_RET_VAL(VSIFCloseL(fpL));
             return NULL;
         }
     }
@@ -11046,10 +12760,10 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
             nRowsPerStrip = MIN(nYSize, (int)TIFFDefaultStripSize(hTIFF,0));
         else
             nRowsPerStrip = nBlockYSize;
-        
+
         TIFFSetField( hTIFF, TIFFTAG_ROWSPERSTRIP, nRowsPerStrip );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Set compression related tags.                                   */
 /* -------------------------------------------------------------------- */
@@ -11059,7 +12773,7 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
     if (nCompression == COMPRESSION_ADOBE_DEFLATE
         && nZLevel != -1)
         TIFFSetField( hTIFF, TIFFTAG_ZIPQUALITY, nZLevel );
-    else if( nCompression == COMPRESSION_JPEG 
+    else if( nCompression == COMPRESSION_JPEG
         && nJpegQuality != -1 )
         TIFFSetField( hTIFF, TIFFTAG_JPEGQUALITY, nJpegQuality );
     else if( nCompression == COMPRESSION_LZMA && nLZMAPreset != -1)
@@ -11075,12 +12789,12 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
     if( bForceColorTable )
     {
         int nColors;
-        
+
         if( eType == GDT_Byte )
             nColors = 256;
         else
             nColors = 65536;
-        
+
         unsigned short *panTRed, *panTGreen, *panTBlue;
 
         panTRed = (unsigned short *) CPLMalloc(sizeof(unsigned short)*nColors);
@@ -11090,7 +12804,7 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
         for( int iColor = 0; iColor < nColors; iColor++ )
         {
             if( eType == GDT_Byte )
-            {                
+            {
                 panTRed[iColor] = (unsigned short) (257 * iColor);
                 panTGreen[iColor] = (unsigned short) (257 * iColor);
                 panTBlue[iColor] = (unsigned short) (257 * iColor);
@@ -11102,10 +12816,10 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
                 panTBlue[iColor] = (unsigned short) iColor;
             }
         }
-        
+
         TIFFSetField( hTIFF, TIFFTAG_COLORMAP,
                       panTRed, panTGreen, panTBlue );
-        
+
         CPLFree( panTRed );
         CPLFree( panTGreen );
         CPLFree( panTBlue );
@@ -11118,12 +12832,11 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
     /* crystalized the directory. This way we avoid a directory rewriting */
 #if defined(BIGTIFF_SUPPORT)
     if( nCompression == COMPRESSION_JPEG &&
-        strncmp(pszFilename, "/vsimem/gtiffdataset_jpg_tmp_",
-                strlen("/vsimem/gtiffdataset_jpg_tmp_")) != 0 &&
-        CSLTestBoolean(CSLFetchNameValueDef(papszParmList, "WRITE_JPEGTABLE_TAG", "YES")) )
+        !STARTS_WITH(pszFilename, "/vsimem/gtiffdataset_jpg_tmp_") &&
+        CPLTestBool(CSLFetchNameValueDef(papszParmList, "WRITE_JPEGTABLE_TAG", "YES")) )
     {
-        CPLString osTmpFilename;
-        osTmpFilename.Printf("/vsimem/gtiffdataset_jpg_tmp_%p", hTIFF);
+        CPLString osTmpFilenameIn;
+        osTmpFilenameIn.Printf("/vsimem/gtiffdataset_jpg_tmp_%p", hTIFF);
         VSILFILE* fpTmp = NULL;
         CPLString osTmp;
         char** papszLocalParameters = NULL;
@@ -11139,29 +12852,29 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
                 "NBITS", CSLFetchNameValue(papszParmList, "NBITS"));
         papszLocalParameters = CSLSetNameValue(papszLocalParameters,
                 "JPEGTABLESMODE", CSLFetchNameValue(papszParmList, "JPEGTABLESMODE"));
-        TIFF* hTIFFTmp = CreateLL( osTmpFilename, 16, 16, (nBands <= 4) ? nBands : 1,
+        TIFF* hTIFFTmp = CreateLL( osTmpFilenameIn, 16, 16, (nBands <= 4) ? nBands : 1,
                                    eType, 0.0, papszLocalParameters, &fpTmp, osTmp );
         CSLDestroy(papszLocalParameters);
         if( hTIFFTmp )
         {
             uint16 nPhotometric;
-            int nJpegTablesMode;
+            int nJpegTablesModeIn;
             TIFFGetField( hTIFFTmp, TIFFTAG_PHOTOMETRIC, &(nPhotometric) );
-            TIFFGetField( hTIFFTmp, TIFFTAG_JPEGTABLESMODE, &nJpegTablesMode );
+            TIFFGetField( hTIFFTmp, TIFFTAG_JPEGTABLESMODE, &nJpegTablesModeIn );
             TIFFWriteCheck( hTIFFTmp, FALSE, "CreateLL" );
             TIFFWriteDirectory( hTIFFTmp );
             TIFFSetDirectory( hTIFFTmp, 0 );
-            // Now, reset quality and jpegcolormode. 
-            if(nJpegQuality > 0) 
-                TIFFSetField(hTIFFTmp, TIFFTAG_JPEGQUALITY, nJpegQuality); 
-            if( nPhotometric == PHOTOMETRIC_YCBCR 
-                && CSLTestBoolean( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB",
+            // Now, reset quality and jpegcolormode.
+            if(nJpegQuality > 0)
+                TIFFSetField(hTIFFTmp, TIFFTAG_JPEGQUALITY, nJpegQuality);
+            if( nPhotometric == PHOTOMETRIC_YCBCR
+                && CPLTestBool( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB",
                                                     "YES") ) )
             {
                 TIFFSetField(hTIFFTmp, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
             }
-            if (nJpegTablesMode >= 0 )
-                TIFFSetField(hTIFFTmp, TIFFTAG_JPEGTABLESMODE, nJpegTablesMode);
+            if (nJpegTablesModeIn >= 0 )
+                TIFFSetField(hTIFFTmp, TIFFTAG_JPEGTABLESMODE, nJpegTablesModeIn);
 
             GByte abyZeroData[(16*16*4*3)/2];
             memset(abyZeroData, 0, (16*16*4*3)/2);
@@ -11180,9 +12893,9 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
                 TIFFSetField(hTIFF, TIFFTAG_REFERENCEBLACKWHITE, ref);
 
             XTIFFClose(hTIFFTmp);
-            VSIFCloseL(fpTmp);
+            CPL_IGNORE_RET_VAL(VSIFCloseL(fpTmp));
         }
-        VSIUnlink(osTmpFilename);
+        VSIUnlink(osTmpFilenameIn);
     }
 #endif
 
@@ -11232,7 +12945,7 @@ static int GTIFFQuantizationTablesEqual(const GByte* paby1, int nLen1,
                                         const GByte* paby2, int nLen2)
 {
     int bFound = FALSE;
-    while(TRUE)
+    while(true)
     {
         int nLenTable1 = 0;
         int nLenTable2 = 0;
@@ -11250,8 +12963,8 @@ static int GTIFFQuantizationTablesEqual(const GByte* paby1, int nLen1,
             return FALSE;
         paby1New += nLenTable1;
         paby2New += nLenTable2;
-        nLen1 -= (paby1New - paby1);
-        nLen2 -= (paby2New - paby2);
+        nLen1 -= static_cast<int>(paby1New - paby1);
+        nLen2 -= static_cast<int>(paby2New - paby2);
         paby1 = paby1New;
         paby2 = paby2New;
         bFound = TRUE;
@@ -11264,10 +12977,12 @@ int GTiffDataset::GuessJPEGQuality(int& bOutHasQuantizationTable,
     CPLAssert( nCompression == COMPRESSION_JPEG );
     uint32 nJPEGTableSize = 0;
     void* pJPEGTable = NULL;
-    bOutHasQuantizationTable = FALSE;
-    bOutHasHuffmanTable = FALSE;
     if( !TIFFGetField(hTIFF, TIFFTAG_JPEGTABLES, &nJPEGTableSize, &pJPEGTable) )
+    {
+        bOutHasQuantizationTable = FALSE;
+        bOutHasHuffmanTable = FALSE;
         return -1;
+    }
 
     bOutHasQuantizationTable = GTIFFFindNextTable((const GByte*)pJPEGTable, 0xDB, nJPEGTableSize, NULL) != NULL;
     bOutHasHuffmanTable = GTIFFFindNextTable((const GByte*)pJPEGTable, 0xC4, nJPEGTableSize, NULL) != NULL;
@@ -11289,8 +13004,8 @@ int GTiffDataset::GuessJPEGQuality(int& bOutHasQuantizationTable,
         papszLocalParameters = CSLSetNameValue(papszLocalParameters,
                                                 "NBITS", "12");
 
-    CPLString osTmpFilename;
-    osTmpFilename.Printf("/vsimem/gtiffdataset_guess_jpeg_quality_tmp_%p", this);
+    CPLString osTmpFilenameIn;
+    osTmpFilenameIn.Printf("/vsimem/gtiffdataset_guess_jpeg_quality_tmp_%p", this);
 
     int nRet = -1;
     for(int nQuality=0;nQuality<=100 && nRet < 0;nQuality++)
@@ -11305,7 +13020,7 @@ int GTiffDataset::GuessJPEGQuality(int& bOutHasQuantizationTable,
 
         CPLPushErrorHandler(CPLQuietErrorHandler);
         CPLString osTmp;
-        TIFF* hTIFFTmp = CreateLL( osTmpFilename, 16, 16, (nBands <= 4) ? nBands : 1,
+        TIFF* hTIFFTmp = CreateLL( osTmpFilenameIn, 16, 16, (nBands <= 4) ? nBands : 1,
                                    GetRasterBand(1)->GetRasterDataType(), 0.0,
                                    papszLocalParameters, &fpTmp, osTmp );
         CPLPopErrorHandler();
@@ -11317,9 +13032,9 @@ int GTiffDataset::GuessJPEGQuality(int& bOutHasQuantizationTable,
         TIFFWriteCheck( hTIFFTmp, FALSE, "CreateLL" );
         TIFFWriteDirectory( hTIFFTmp );
         TIFFSetDirectory( hTIFFTmp, 0 );
-        // Now reset jpegcolormode. 
-        if( nPhotometric == PHOTOMETRIC_YCBCR 
-            && CSLTestBoolean( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB",
+        // Now reset jpegcolormode.
+        if( nPhotometric == PHOTOMETRIC_YCBCR
+            && CPLTestBool( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB",
                                                 "YES") ) )
         {
             TIFFSetField(hTIFFTmp, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
@@ -11343,11 +13058,11 @@ int GTiffDataset::GuessJPEGQuality(int& bOutHasQuantizationTable,
         }
 
         XTIFFClose(hTIFFTmp);
-        VSIFCloseL(fpTmp);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpTmp));
     }
 
     CSLDestroy(papszLocalParameters);
-    VSIUnlink(osTmpFilename);
+    VSIUnlink(osTmpFilenameIn);
 
     return nRet;
 }
@@ -11364,8 +13079,8 @@ GDALDataset *GTiffDataset::Create( const char * pszFilename,
                                    char **papszParmList )
 
 {
-    GTiffDataset *	poDS;
-    TIFF		*hTIFF;
+    GTiffDataset *poDS;
+    TIFF *hTIFF;
     VSILFILE* fpL = NULL;
     CPLString           osTmpFilename;
 
@@ -11373,7 +13088,7 @@ GDALDataset *GTiffDataset::Create( const char * pszFilename,
 /*      Create the underlying TIFF file.                                */
 /* -------------------------------------------------------------------- */
     hTIFF = CreateLL( pszFilename,
-                      nXSize, nYSize, nBands, 
+                      nXSize, nYSize, nBands,
                       eType, 0, papszParmList, &fpL, osTmpFilename );
     int bStreaming = (osTmpFilename.size() != 0);
 
@@ -11408,7 +13123,7 @@ GDALDataset *GTiffDataset::Create( const char * pszFilename,
     poDS->nSamplesPerPixel = (uint16) nBands;
     poDS->osFilename = pszFilename;
 
-    /* Avoid premature crystalization that will cause directory re-writting */
+    /* Avoid premature crystalization that will cause directory re-writing */
     /* if GetProjectionRef() or GetGeoTransform() are called on the newly created GeoTIFF */
     poDS->bLookedForProjection = TRUE;
 
@@ -11447,9 +13162,9 @@ GDALDataset *GTiffDataset::Create( const char * pszFilename,
 /*      to RGB by libtiff/libjpeg unless specifically requested         */
 /*      otherwise.                                                      */
 /* -------------------------------------------------------------------- */
-    if( poDS->nCompression == COMPRESSION_JPEG 
-        && poDS->nPhotometric == PHOTOMETRIC_YCBCR 
-        && CSLTestBoolean( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB",
+    if( poDS->nCompression == COMPRESSION_JPEG
+        && poDS->nPhotometric == PHOTOMETRIC_YCBCR
+        && CPLTestBool( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB",
                                               "YES") ) )
     {
         int nColorMode;
@@ -11463,13 +13178,13 @@ GDALDataset *GTiffDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Read palette back as a color table if it has one.               */
 /* -------------------------------------------------------------------- */
-    unsigned short	*panRed, *panGreen, *panBlue;
-    
+    unsigned short *panRed, *panGreen, *panBlue;
+
     if( poDS->nPhotometric == PHOTOMETRIC_PALETTE
-        && TIFFGetField( hTIFF, TIFFTAG_COLORMAP, 
+        && TIFFGetField( hTIFF, TIFFTAG_COLORMAP,
                          &panRed, &panGreen, &panBlue) )
     {
-        int	nColorCount;
+        int nColorCount;
         GDALColorEntry oEntry;
 
         poDS->poColorTable = new GDALColorTable();
@@ -11493,7 +13208,7 @@ GDALDataset *GTiffDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
     if( !CSLFetchBoolean( papszParmList, "SPARSE_OK", FALSE ) )
         poDS->bFillEmptyTiles = TRUE;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Preserve creation options for consulting later (for instance    */
 /*      to decide if a TFW file should be written).                     */
@@ -11504,6 +13219,7 @@ GDALDataset *GTiffDataset::Create( const char * pszFilename,
     poDS->nLZMAPreset = GTiffGetLZMAPreset(papszParmList);
     poDS->nJpegQuality = GTiffGetJpegQuality(papszParmList);
     poDS->nJpegTablesMode = GTiffGetJpegTablesMode(papszParmList);
+    poDS->InitCreationOrOpenOptions(papszParmList);
 
 #if !defined(BIGTIFF_SUPPORT)
 /* -------------------------------------------------------------------- */
@@ -11537,7 +13253,7 @@ GDALDataset *GTiffDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    int		iBand;
+    int iBand;
 
     for( iBand = 0; iBand < nBands; iBand++ )
     {
@@ -11551,7 +13267,7 @@ GDALDataset *GTiffDataset::Create( const char * pszFilename,
         {
             poDS->SetBand( iBand+1, new GTiffOddBitsBand( poDS, iBand+1 ) );
             poDS->GetRasterBand( iBand+1 )->
-                SetMetadataItem( "NBITS", 
+                SetMetadataItem( "NBITS",
                                  CPLString().Printf("%d",poDS->nBitsPerSample),
                                  "IMAGE_STRUCTURE" );
         }
@@ -11574,19 +13290,18 @@ GDALDataset *GTiffDataset::Create( const char * pszFilename,
 /************************************************************************/
 
 GDALDataset *
-GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
-                          int bStrict, char ** papszOptions, 
+GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
+                          int bStrict, char ** papszOptions,
                           GDALProgressFunc pfnProgress, void * pProgressData )
 
 {
-    TIFF	*hTIFF;
-    int		nXSize = poSrcDS->GetRasterXSize();
-    int		nYSize = poSrcDS->GetRasterYSize();
-    int		nBands = poSrcDS->GetRasterCount();
-    int         iBand;
+    TIFF *hTIFF;
+    int nXSize = poSrcDS->GetRasterXSize();
+    int nYSize = poSrcDS->GetRasterYSize();
+    int nBands = poSrcDS->GetRasterCount();
     CPLErr      eErr = CE_None;
-    uint16	nPlanarConfig;
-    uint16	nBitsPerSample;
+    uint16 nPlanarConfig;
+    uint16 nBitsPerSample;
     GDALRasterBand *poPBand;
 
     if( poSrcDS->GetRasterCount() == 0 )
@@ -11595,14 +13310,14 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                   "Unable to export GeoTIFF files with zero bands." );
         return NULL;
     }
-        
+
     poPBand = poSrcDS->GetRasterBand(1);
     GDALDataType eType = poPBand->GetRasterDataType();
 
 /* -------------------------------------------------------------------- */
 /*      Check, whether all bands in input dataset has the same type.    */
 /* -------------------------------------------------------------------- */
-    for ( iBand = 2; iBand <= nBands; iBand++ )
+    for ( int iBand = 2; iBand <= nBands; iBand++ )
     {
         if ( eType != poSrcDS->GetRasterBand(iBand)->GetRasterDataType() )
         {
@@ -11635,16 +13350,16 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     if( pszProfile == NULL )
         pszProfile = "GDALGeoTIFF";
 
-    if( !EQUAL(pszProfile,"BASELINE") 
-        && !EQUAL(pszProfile,"GeoTIFF") 
+    if( !EQUAL(pszProfile,"BASELINE")
+        && !EQUAL(pszProfile,"GeoTIFF")
         && !EQUAL(pszProfile,"GDALGeoTIFF") )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "PROFILE=%s not supported in GTIFF driver.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "PROFILE=%s not supported in GTIFF driver.",
                   pszProfile );
         return NULL;
     }
-    
+
     if( EQUAL(pszProfile,"BASELINE") )
         bGeoTIFF = FALSE;
     else
@@ -11655,13 +13370,13 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
     char     **papszCreateOptions = CSLDuplicate( papszOptions );
 
-    if( poPBand->GetMetadataItem( "NBITS", "IMAGE_STRUCTURE" ) != NULL 
+    if( poPBand->GetMetadataItem( "NBITS", "IMAGE_STRUCTURE" ) != NULL
         && atoi(poPBand->GetMetadataItem( "NBITS", "IMAGE_STRUCTURE" )) > 0
         && CSLFetchNameValue( papszCreateOptions, "NBITS") == NULL )
     {
-        papszCreateOptions = 
+        papszCreateOptions =
             CSLSetNameValue( papszCreateOptions, "NBITS",
-                             poPBand->GetMetadataItem( "NBITS", 
+                             poPBand->GetMetadataItem( "NBITS",
                                                        "IMAGE_STRUCTURE" ) );
     }
 
@@ -11669,12 +13384,12 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         && eType == GDT_Byte
         && poPBand->GetMetadataItem( "PIXELTYPE", "IMAGE_STRUCTURE" ) )
     {
-        papszCreateOptions = 
-            CSLSetNameValue( papszCreateOptions, "PIXELTYPE", 
-                             poPBand->GetMetadataItem( 
+        papszCreateOptions =
+            CSLSetNameValue( papszCreateOptions, "PIXELTYPE",
+                             poPBand->GetMetadataItem(
                                  "PIXELTYPE", "IMAGE_STRUCTURE" ) );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Color profile.  Copy from band metadata if found.              */
 /* -------------------------------------------------------------------- */
@@ -11704,7 +13419,7 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
             if ((pszMD != NULL) && !EQUAL(pszMD, "") )
             {
-                papszCreateOptions = 
+                papszCreateOptions =
                     CSLSetNameValue( papszCreateOptions, pszOptionsMD[i], pszMD );
 
                 /* If an ICC profile exists, other tags are not needed */
@@ -11725,7 +13440,7 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         {
             if( poSrcDS->GetRasterBand(j)->GetOverviewCount() != nSrcOverviews )
             {
-                CPLError( CE_Failure, CPLE_NotSupported, 
+                CPLError( CE_Failure, CPLE_NotSupported,
                   "COPY_SRC_OVERVIEWS cannot be used when the bands have not the same number of overview levels." );
                 CSLDestroy(papszCreateOptions);
                 return NULL;
@@ -11735,7 +13450,7 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                 GDALRasterBand* poOvrBand = poSrcDS->GetRasterBand(j)->GetOverview(i);
                 if( poOvrBand == NULL )
                 {
-                    CPLError( CE_Failure, CPLE_NotSupported, 
+                    CPLError( CE_Failure, CPLE_NotSupported,
                         "COPY_SRC_OVERVIEWS cannot be used when one overview band is NULL." );
                     CSLDestroy(papszCreateOptions);
                     return NULL;
@@ -11744,7 +13459,7 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                 if( poOvrBand->GetXSize() != poOvrFirstBand->GetXSize() ||
                     poOvrBand->GetYSize() != poOvrFirstBand->GetYSize() )
                 {
-                    CPLError( CE_Failure, CPLE_NotSupported, 
+                    CPLError( CE_Failure, CPLE_NotSupported,
                     "COPY_SRC_OVERVIEWS cannot be used when the overview bands have not the same dimensions among bands." );
                     CSLDestroy(papszCreateOptions);
                     return NULL;
@@ -11787,7 +13502,7 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     /* when CreateCopy'ing() from a JPEG dataset, and asking for COMPRESS=JPEG, */
     /* use DCT coefficients (unless other options are incompatible, like strip/tile dimensions, */
     /* specifying JPEG_QUALITY option, incompatible PHOTOMETRIC with the source colorspace, etc...) */
-    /* to avoid the lossy steps involved by uncompression/recompression */
+    /* to avoid the lossy steps involved by decompression/recompression */
     if (!bDirectCopyFromJPEG && GTIFF_CanCopyFromJPEG(poSrcDS, papszCreateOptions))
     {
         CPLDebug("GTiff", "Using special copy mode from a JPEG dataset");
@@ -11823,62 +13538,67 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     if( !TIFFGetField( hTIFF, TIFFTAG_COMPRESSION, &(nCompression) ) )
         nCompression = COMPRESSION_NONE;
 
-    int bForcePhotometric = 
+    bool bForcePhotometric =
         CSLFetchNameValue(papszOptions,"PHOTOMETRIC") != NULL;
 
 /* -------------------------------------------------------------------- */
 /*      If the source is RGB, then set the PHOTOMETRIC_RGB value        */
 /* -------------------------------------------------------------------- */
-    if( nBands == 3 && !bForcePhotometric &&
+    if( nBands >= 3 && !bForcePhotometric &&
         nCompression != COMPRESSION_JPEG &&
         poSrcDS->GetRasterBand(1)->GetColorInterpretation() == GCI_RedBand &&
         poSrcDS->GetRasterBand(2)->GetColorInterpretation() == GCI_GreenBand &&
         poSrcDS->GetRasterBand(3)->GetColorInterpretation() == GCI_BlueBand )
     {
         TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
-    }
 
-/* -------------------------------------------------------------------- */
-/*      Are we really producing a Grey+Alpha image?  If so, set the     */
-/*      associated alpha information.                                   */
-/* -------------------------------------------------------------------- */
-    else if( nBands == 2 && !bForcePhotometric &&
-             nCompression != COMPRESSION_JPEG &&
-             poSrcDS->GetRasterBand(1)->GetColorInterpretation()==GCI_GrayIndex &&
-             poSrcDS->GetRasterBand(2)->GetColorInterpretation()==GCI_AlphaBand)
-    {
-        uint16 v[1];
+        /* We need to update the number of extra samples */
+        uint16 *v;
+        uint16 count = 0;
+        uint16 nNewExtraSamplesCount = static_cast<uint16>(nBands - 3);
+        if( nBands >= 4 &&
+            TIFFGetField( hTIFF, TIFFTAG_EXTRASAMPLES, &count, &v ) &&
+            count > nNewExtraSamplesCount )
+        {
+            uint16* pasNewExtraSamples =
+                (uint16*)CPLMalloc( nNewExtraSamplesCount * sizeof(uint16) );
+            memcpy( pasNewExtraSamples, v + count - nNewExtraSamplesCount,
+                    nNewExtraSamplesCount * sizeof(uint16) );
 
-        v[0] = GTiffGetAlphaValue(CSLFetchNameValue(papszOptions, "ALPHA"),
-                                  DEFAULT_ALPHA_TYPE);
+            TIFFSetField(hTIFF, TIFFTAG_EXTRASAMPLES, nNewExtraSamplesCount, pasNewExtraSamples);
 
-        TIFFSetField(hTIFF, TIFFTAG_EXTRASAMPLES, 1, v);
-        TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK );
+            CPLFree(pasNewExtraSamples);
+        }
     }
+
 /* -------------------------------------------------------------------- */
-/*      Are we really producing an RGBA image?  If so, set the          */
-/*      associated alpha information.                                   */
+/*      Set the alpha channel if it is the last one.                    */
 /* -------------------------------------------------------------------- */
-    else if( nBands == 4 && !bForcePhotometric &&
-             nCompression != COMPRESSION_JPEG &&
-             poSrcDS->GetRasterBand(4)->GetColorInterpretation()==GCI_AlphaBand)
+    if( poSrcDS->GetRasterBand(nBands)->GetColorInterpretation()==GCI_AlphaBand )
     {
-        uint16 v[1];
+        uint16 *v;
+        uint16 count = 0;
+        if( TIFFGetField( hTIFF, TIFFTAG_EXTRASAMPLES, &count, &v ) )
+        {
+            int nBaseSamples = nBands - count;
+            if( nBands > nBaseSamples && nBands - nBaseSamples - 1 < count )
+            {
+                // We need to allocate a new array as (current) libtiff
+                // versions will not like that we reuse the array we got from
+                // TIFFGetField().
 
-        v[0] = GTiffGetAlphaValue(CSLFetchNameValue(papszOptions, "ALPHA"),
-                                  DEFAULT_ALPHA_TYPE);
+                uint16* pasNewExtraSamples =
+                    (uint16*)CPLMalloc( count * sizeof(uint16) );
+                memcpy( pasNewExtraSamples, v, count * sizeof(uint16) );
+                pasNewExtraSamples[nBands - nBaseSamples - 1] =
+                    GTiffGetAlphaValue(CPLGetConfigOption("GTIFF_ALPHA", CSLFetchNameValue(papszOptions,"ALPHA")),
+                                            DEFAULT_ALPHA_TYPE);
 
-        TIFFSetField(hTIFF, TIFFTAG_EXTRASAMPLES, 1, v);
-        TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
-    }
+                TIFFSetField(hTIFF, TIFFTAG_EXTRASAMPLES, count, pasNewExtraSamples);
 
-    else if( !bForcePhotometric && nBands == 3 &&
-             nCompression != COMPRESSION_JPEG &&
-             (poSrcDS->GetRasterBand(1)->GetColorInterpretation() != GCI_Undefined ||
-              poSrcDS->GetRasterBand(2)->GetColorInterpretation() != GCI_Undefined ||
-              poSrcDS->GetRasterBand(3)->GetColorInterpretation() != GCI_Undefined) )
-    {
-        TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK );
+                CPLFree(pasNewExtraSamples);
+            }
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -11888,12 +13608,12 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
     if( nCompression == COMPRESSION_JPEG )
     {
-        if( nBands >= 3 
-            && (poSrcDS->GetRasterBand(1)->GetColorInterpretation() 
+        if( nBands >= 3
+            && (poSrcDS->GetRasterBand(1)->GetColorInterpretation()
                 == GCI_YCbCr_YBand)
-            && (poSrcDS->GetRasterBand(2)->GetColorInterpretation() 
+            && (poSrcDS->GetRasterBand(2)->GetColorInterpretation()
                 == GCI_YCbCr_CbBand)
-            && (poSrcDS->GetRasterBand(3)->GetColorInterpretation() 
+            && (poSrcDS->GetRasterBand(3)->GetColorInterpretation()
                 == GCI_YCbCr_CrBand) )
         {
             /* do nothing ... */
@@ -11905,19 +13625,19 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             TIFFSetField( hTIFF, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB );
         }
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Does the source image consist of one band, with a palette?      */
 /*      If so, copy over.                                               */
 /* -------------------------------------------------------------------- */
-    if( (nBands == 1 || nBands == 2) && poSrcDS->GetRasterBand(1)->GetColorTable() != NULL 
+    if( (nBands == 1 || nBands == 2) && poSrcDS->GetRasterBand(1)->GetColorTable() != NULL
         && eType == GDT_Byte )
     {
-        unsigned short	anTRed[256], anTGreen[256], anTBlue[256];
+        unsigned short anTRed[256], anTGreen[256], anTBlue[256];
         GDALColorTable *poCT;
 
         poCT = poSrcDS->GetRasterBand(1)->GetColorTable();
-        
+
         for( int iColor = 0; iColor < 256; iColor++ )
         {
             if( iColor < poCT->GetColorEntryCount() )
@@ -11940,11 +13660,11 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE );
         TIFFSetField( hTIFF, TIFFTAG_COLORMAP, anTRed, anTGreen, anTBlue );
     }
-    else if( (nBands == 1 || nBands == 2) 
-             && poSrcDS->GetRasterBand(1)->GetColorTable() != NULL 
+    else if( (nBands == 1 || nBands == 2)
+             && poSrcDS->GetRasterBand(1)->GetColorTable() != NULL
              && eType == GDT_UInt16 )
     {
-        unsigned short	*panTRed, *panTGreen, *panTBlue;
+        unsigned short *panTRed, *panTGreen, *panTBlue;
         GDALColorTable *poCT;
 
         panTRed   = (unsigned short *) CPLMalloc(65536*sizeof(unsigned short));
@@ -11952,7 +13672,7 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         panTBlue  = (unsigned short *) CPLMalloc(65536*sizeof(unsigned short));
 
         poCT = poSrcDS->GetRasterBand(1)->GetColorTable();
-        
+
         for( int iColor = 0; iColor < 65536; iColor++ )
         {
             if( iColor < poCT->GetColorEntryCount() )
@@ -11985,7 +13705,7 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                   "can only be written to 1 band or 2 bands Byte or UInt16 GeoTIFF files." );
 
     if( nBands == 2
-        && poSrcDS->GetRasterBand(1)->GetColorTable() != NULL 
+        && poSrcDS->GetRasterBand(1)->GetColorTable() != NULL
         && (eType == GDT_Byte || eType == GDT_UInt16) )
     {
         uint16 v[1] = { EXTRASAMPLE_UNASSALPHA };
@@ -12007,13 +13727,13 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                                  pszFilename, papszOptions );
 
 /* -------------------------------------------------------------------- */
-/* 	Write NoData value, if exist.                                   */
+/*      Write NoData value, if exist.                                   */
 /* -------------------------------------------------------------------- */
     if( EQUAL(pszProfile,"GDALGeoTIFF") )
     {
-        int		bSuccess;
-        double	dfNoData;
-    
+        int bSuccess;
+        double dfNoData;
+
         dfNoData = poSrcDS->GetRasterBand(1)->GetNoDataValue( &bSuccess );
         if ( bSuccess )
             GTiffDataset::WriteNoDataValue( hTIFF, dfNoData );
@@ -12023,16 +13743,16 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      Are we addressing PixelIsPoint mode?                            */
 /* -------------------------------------------------------------------- */
     bool bPixelIsPoint = false;
-    int  bPointGeoIgnore = FALSE;
+    bool bPointGeoIgnore = false;
 
-    if( poSrcDS->GetMetadataItem( GDALMD_AREA_OR_POINT ) 
+    if( poSrcDS->GetMetadataItem( GDALMD_AREA_OR_POINT )
         && EQUAL(poSrcDS->GetMetadataItem(GDALMD_AREA_OR_POINT),
                  GDALMD_AOP_POINT) )
     {
         bPixelIsPoint = true;
-        bPointGeoIgnore = 
-            CSLTestBoolean( CPLGetConfigOption("GTIFF_POINT_GEO_IGNORE",
-                                               "FALSE") );
+        bPointGeoIgnore =
+            CPLTestBool( CPLGetConfigOption( "GTIFF_POINT_GEO_IGNORE",
+                                                "FALSE") );
     }
 
 /* -------------------------------------------------------------------- */
@@ -12040,7 +13760,7 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
     const char *pszProjection = NULL;
     double      adfGeoTransform[6];
-    
+
     if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None
         && (adfGeoTransform[0] != 0.0 || adfGeoTransform[1] != 1.0
             || adfGeoTransform[2] != 0.0 || adfGeoTransform[3] != 0.0
@@ -12048,36 +13768,36 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     {
         if( bGeoTIFF )
         {
-            if( adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0 
+            if( adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0
                 && adfGeoTransform[5] < 0.0 )
             {
 
-                double	adfPixelScale[3], adfTiePoints[6];
+                double adfPixelScale[3], adfTiePoints[6];
 
                 adfPixelScale[0] = adfGeoTransform[1];
                 adfPixelScale[1] = fabs(adfGeoTransform[5]);
                 adfPixelScale[2] = 0.0;
 
                 TIFFSetField( hTIFF, TIFFTAG_GEOPIXELSCALE, 3, adfPixelScale );
-            
+
                 adfTiePoints[0] = 0.0;
                 adfTiePoints[1] = 0.0;
                 adfTiePoints[2] = 0.0;
                 adfTiePoints[3] = adfGeoTransform[0];
                 adfTiePoints[4] = adfGeoTransform[3];
                 adfTiePoints[5] = 0.0;
-                
+
                 if( bPixelIsPoint && !bPointGeoIgnore )
                 {
                     adfTiePoints[3] += adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5;
                     adfTiePoints[4] += adfGeoTransform[4] * 0.5 + adfGeoTransform[5] * 0.5;
                 }
-	    
+
                 TIFFSetField( hTIFF, TIFFTAG_GEOTIEPOINTS, 6, adfTiePoints );
             }
             else
             {
-                double	adfMatrix[16];
+                double adfMatrix[16];
 
                 memset(adfMatrix,0,sizeof(double) * 16);
 
@@ -12088,7 +13808,7 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                 adfMatrix[5] = adfGeoTransform[5];
                 adfMatrix[7] = adfGeoTransform[3];
                 adfMatrix[15] = 1.0;
-                
+
                 if( bPixelIsPoint && !bPointGeoIgnore )
                 {
                     adfMatrix[3] += adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5;
@@ -12097,7 +13817,7 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
                 TIFFSetField( hTIFF, TIFFTAG_GEOTRANSMATRIX, 16, adfMatrix );
             }
-            
+
             pszProjection = poSrcDS->GetProjectionRef();
         }
 
@@ -12116,9 +13836,9 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     else if( poSrcDS->GetGCPCount() > 0 && bGeoTIFF )
     {
         const GDAL_GCP *pasGCPs = poSrcDS->GetGCPs();
-        double	*padfTiePoints;
+        double *padfTiePoints;
 
-        padfTiePoints = (double *) 
+        padfTiePoints = (double *)
             CPLMalloc(6*sizeof(double)*poSrcDS->GetGCPCount());
 
         for( int iGCP = 0; iGCP < poSrcDS->GetGCPCount(); iGCP++ )
@@ -12138,13 +13858,13 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             }
         }
 
-        TIFFSetField( hTIFF, TIFFTAG_GEOTIEPOINTS, 
+        TIFFSetField( hTIFF, TIFFTAG_GEOTIEPOINTS,
                       6*poSrcDS->GetGCPCount(), padfTiePoints );
         CPLFree( padfTiePoints );
-        
+
         pszProjection = poSrcDS->GetGCPProjection();
-        
-        if( CSLFetchBoolean( papszOptions, "TFW", FALSE ) 
+
+        if( CSLFetchBoolean( papszOptions, "TFW", FALSE )
             || CSLFetchBoolean( papszOptions, "WORLDFILE", FALSE ) )
         {
             CPLError(CE_Warning, CPLE_AppDefined,
@@ -12161,13 +13881,13 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     const bool bHasProjection = (pszProjection != NULL && strlen(pszProjection) > 0);
     if( (bHasProjection || bPixelIsPoint) && bGeoTIFF )
     {
-        GTIF	*psGTIF;
+        GTIF *psGTIF;
 
         psGTIF = GTIFNew( hTIFF );
 
         if( bHasProjection )
         {
-            GTIFSetFromOGISDefn( psGTIF, pszProjection );
+            GTIFSetFromOGISDefnEx( psGTIF, pszProjection, GetGTIFFKeysFlavor(papszOptions) );
         }
 
         if( bPixelIsPoint )
@@ -12226,7 +13946,7 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Cleanup                                                         */
 /* -------------------------------------------------------------------- */
-    
+
     TIFFWriteCheck( hTIFF, TIFFIsTiled(hTIFF), "GTiffCreateCopy()");
     TIFFWriteDirectory( hTIFF );
     if( bStreaming )
@@ -12237,7 +13957,8 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         TIFFSetDirectory( hTIFF, 0 );
         TIFFWriteDirectory( hTIFF );
 
-        VSIFSeekL( fpL, 0, SEEK_END );
+        if( VSIFSeekL( fpL, 0, SEEK_END ) != 0 )
+            CPLError(CE_Failure, CPLE_FileIO, "Cannot seek");
         int nSize = (int) VSIFTellL(fpL);
 
         vsi_l_offset nDataLength;
@@ -12249,7 +13970,8 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     TIFFFlush( hTIFF );
     XTIFFClose( hTIFF );
     hTIFF = NULL;
-    VSIFCloseL(fpL);
+    if( VSIFCloseL(fpL) != 0 )
+        eErr = CE_Failure;
     fpL = NULL;
 
     if( eErr != CE_None )
@@ -12272,7 +13994,7 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         {
             CPLError(CE_Failure, CPLE_FileIO, "Could not write %d bytes",
                      (int)nDataLength);
-            VSIFCloseL( fpL );
+            CPL_IGNORE_RET_VAL(VSIFCloseL( fpL ));
             VSIUnlink(osTmpFilename);
             return NULL;
         }
@@ -12315,7 +14037,18 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         poDS->fpToWrite = fpL;
     }
     poDS->osProfile = pszProfile;
-    poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT & ~GCIF_MASK );
+
+    int nCloneInfoFlags = GCIF_PAM_DEFAULT & ~GCIF_MASK;
+
+    // If we explicitly asked not to tag the alpha band as such, don't
+    // reintroduce this alpha color interpretation in PAM.
+    if( poSrcDS->GetRasterBand(nBands)->GetColorInterpretation()==GCI_AlphaBand &&
+        GTiffGetAlphaValue(CPLGetConfigOption("GTIFF_ALPHA", CSLFetchNameValue(papszOptions,"ALPHA")), DEFAULT_ALPHA_TYPE) == EXTRASAMPLE_UNSPECIFIED )
+    {
+        nCloneInfoFlags = nCloneInfoFlags & ~GCIF_COLORINTERP;
+    }
+
+    poDS->CloneInfo( poSrcDS, nCloneInfoFlags );
     poDS->papszCreationOptions = CSLDuplicate( papszOptions );
     poDS->bDontReloadFirstBlock = bDontReloadFirstBlock;
 
@@ -12340,8 +14073,8 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     {
         GDALRasterBand* poSrcBand = poSrcDS->GetRasterBand(nBand);
         GDALRasterBand* poDstBand = poDS->GetRasterBand(nBand);
-        char **papszSRC_MD = poSrcBand->GetMetadata();
-        char **papszDST_MD = CSLDuplicate(poDstBand->GetMetadata());
+        papszSRC_MD = poSrcBand->GetMetadata();
+        papszDST_MD = CSLDuplicate(poDstBand->GetMetadata());
 
         papszDST_MD = CSLMerge( papszDST_MD, papszSRC_MD );
 
@@ -12359,7 +14092,7 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Handle forcing xml:ESRI data to be written to PAM.              */
 /* -------------------------------------------------------------------- */
-    if( CSLTestBoolean(CPLGetConfigOption( "ESRI_XML_PAM", "NO" )) )
+    if( CPLTestBool(CPLGetConfigOption( "ESRI_XML_PAM", "NO" )) )
     {
         char **papszESRIMD = poSrcDS->GetMetadata("xml:ESRI");
         if( papszESRIMD )
@@ -12369,8 +14102,8 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     }
 
 /* -------------------------------------------------------------------- */
-/*      Second chance : now that we have a PAM dataset, it is possible  */
-/*      to write metadata that we couldn't be writen as TIFF tag        */
+/*      Second chance: now that we have a PAM dataset, it is possible   */
+/*      to write metadata that we could not write as a TIFF tag.        */
 /* -------------------------------------------------------------------- */
     if (!bHasWrittenMDInGeotiffTAG && !bStreaming)
         GTiffDataset::WriteMetadata( poDS, hTIFF, TRUE, pszProfile,
@@ -12398,6 +14131,7 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     poDS->nJpegQuality = GTiffGetJpegQuality(papszOptions);
     poDS->nJpegTablesMode = GTiffGetJpegTablesMode(papszOptions);
     poDS->GetDiscardLsbOption(papszOptions);
+    poDS->InitCreationOrOpenOptions(papszOptions);
 
     if (nCompression == COMPRESSION_ADOBE_DEFLATE)
     {
@@ -12452,8 +14186,9 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
         if (poDS->nOverviewCount != nSrcOverviews)
         {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "Did only manage to instanciate %d overview levels, whereas source contains %d",
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Did only manage to instantiate %d overview levels, "
+                      "whereas source contains %d",
                      poDS->nOverviewCount, nSrcOverviews);
             eErr = CE_Failure;
         }
@@ -12474,11 +14209,11 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         {
             /* Begin with the smallest overview */
             int iOvrLevel = nSrcOverviews-1-i;
-            
+
             /* Create a fake dataset with the source overview level so that */
             /* GDALDatasetCopyWholeRaster can cope with it */
             GDALDataset* poSrcOvrDS = GDALCreateOverviewDataset(poSrcDS, iOvrLevel, TRUE, FALSE);
-            
+
             GDALRasterBand* poOvrBand =
                     poSrcDS->GetRasterBand(1)->GetOverview(iOvrLevel);
             double dfNextCurPixels = dfCurPixels +
@@ -12487,12 +14222,12 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             void* pScaledData = GDALCreateScaledProgress( dfCurPixels / dfTotalPixels,
                                       dfNextCurPixels / dfTotalPixels,
                                       pfnProgress, pProgressData);
-                                
+
             eErr = GDALDatasetCopyWholeRaster( (GDALDatasetH) poSrcOvrDS,
                                                 (GDALDatasetH) poDS->papoOverviewDS[iOvrLevel],
                                                 papszCopyWholeRasterOptions,
                                                 GDALScaledProgress, pScaledData );
-                                                
+
             dfCurPixels = dfNextCurPixels;
             GDALDestroyScaledProgress(pScaledData);
 
@@ -12550,11 +14285,13 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     {
         /* For split bands, we use TIFFWriteScanline() interface */
         CPLAssert(poDS->nBitsPerSample == 8 || poDS->nBitsPerSample == 1);
-        
+
         if (poDS->nPlanarConfig == PLANARCONFIG_CONTIG && poDS->nBands > 1)
         {
             int j;
-            GByte* pabyScanline = (GByte *) CPLMalloc(TIFFScanlineSize(hTIFF));
+            GByte* pabyScanline = (GByte *) VSI_MALLOC_VERBOSE(TIFFScanlineSize(hTIFF));
+            if( pabyScanline == NULL )
+                eErr = CE_Failure;
             for(j=0;j<nYSize && eErr == CE_None;j++)
             {
                 eErr = poSrcDS->RasterIO(GF_Read, 0, j, nXSize, 1,
@@ -12575,10 +14312,13 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         }
         else
         {
-            int iBand, j;
-            GByte* pabyScanline = (GByte *) CPLMalloc(nXSize);
-            eErr = CE_None;
-            for(iBand=1;iBand<=nBands && eErr == CE_None;iBand++)
+            int j;
+            GByte* pabyScanline = (GByte *) VSI_MALLOC_VERBOSE(nXSize);
+            if( pabyScanline == NULL )
+                eErr = CE_Failure;
+            else
+                eErr = CE_None;
+            for(int iBand=1;iBand<=nBands && eErr == CE_None;iBand++)
             {
                 for(j=0;j<nYSize && eErr == CE_None;j++)
                 {
@@ -12611,7 +14351,7 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             }
             CPLFree(pabyScanline);
         }
-        
+
         /* Necessary to be able to read the file without re-opening */
 #if defined(HAVE_TIFFGETSIZEPROC)
         TIFFSizeProc pfnSizeProc = TIFFGetSizeProc( hTIFF );
@@ -12647,18 +14387,18 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                                             papszCopyWholeRasterOptions,
                                             GDALScaledProgress, pScaledData );
     }
-    
+
     GDALDestroyScaledProgress(pScaledData);
 
     if (eErr == CE_None && !bStreaming)
     {
         if (poDS->poMaskDS)
         {
-            const char* papszOptions[2] = { "COMPRESSED=YES", NULL };
+            const char* l_papszOptions[2] = { "COMPRESSED=YES", NULL };
             eErr = GDALRasterBandCopyWholeRaster(
                                     poSrcDS->GetRasterBand(1)->GetMaskBand(),
                                     poDS->GetRasterBand(1)->GetMaskBand(),
-                                    (char**)papszOptions,
+                                    (char**)l_papszOptions,
                                     GDALDummyProgress, NULL);
         }
         else
@@ -12670,7 +14410,7 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         delete poDS;
         poDS = NULL;
 
-        if (CSLTestBoolean(CPLGetConfigOption("GTIFF_DELETE_ON_ERROR", "YES")))
+        if (CPLTestBool(CPLGetConfigOption("GTIFF_DELETE_ON_ERROR", "YES")))
         {
             if( !bStreaming )
                 VSIUnlink( pszFilename ); // should really delete more carefully.
@@ -12689,6 +14429,7 @@ const char *GTiffDataset::GetProjectionRef()
 {
     if( nGCPCount == 0 )
     {
+        LoadGeoreferencingAndPamIfNeeded();
         LookForProjection();
 
         if( EQUAL(pszProjection,"") )
@@ -12713,21 +14454,22 @@ CPLErr GTiffDataset::SetProjection( const char * pszNewProjection )
                  "Cannot modify projection at that point in a streamed output file");
         return CE_Failure;
     }
-    
+
+    LoadGeoreferencingAndPamIfNeeded();
     LookForProjection();
 
-    if( !EQUALN(pszNewProjection,"GEOGCS",6)
-        && !EQUALN(pszNewProjection,"PROJCS",6)
-        && !EQUALN(pszNewProjection,"LOCAL_CS",8)
-        && !EQUALN(pszNewProjection,"COMPD_CS",8)
-        && !EQUALN(pszNewProjection,"GEOCCS",6)
+    if( !STARTS_WITH_CI(pszNewProjection, "GEOGCS")
+        && !STARTS_WITH_CI(pszNewProjection, "PROJCS")
+        && !STARTS_WITH_CI(pszNewProjection, "LOCAL_CS")
+        && !STARTS_WITH_CI(pszNewProjection, "COMPD_CS")
+        && !STARTS_WITH_CI(pszNewProjection, "GEOCCS")
         && !EQUAL(pszNewProjection,"") )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                 "Only OGC WKT Projections supported for writing to GeoTIFF.\n"
                 "%s not supported.",
                   pszNewProjection );
-        
+
         return CE_Failure;
     }
 
@@ -12753,8 +14495,10 @@ CPLErr GTiffDataset::SetProjection( const char * pszNewProjection )
 CPLErr GTiffDataset::GetGeoTransform( double * padfTransform )
 
 {
+    LoadGeoreferencingAndPamIfNeeded();
+
     memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
-    
+
     if( !bGeoTransformValid )
         return CE_Failure;
     else
@@ -12775,6 +14519,8 @@ CPLErr GTiffDataset::SetGeoTransform( double * padfTransform )
         return CE_Failure;
     }
 
+    LoadGeoreferencingAndPamIfNeeded();
+
     if( GetAccess() == GA_Update )
     {
         if (
@@ -12815,6 +14561,8 @@ CPLErr GTiffDataset::SetGeoTransform( double * padfTransform )
 int GTiffDataset::GetGCPCount()
 
 {
+    LoadGeoreferencingAndPamIfNeeded();
+
     return nGCPCount;
 }
 
@@ -12825,6 +14573,8 @@ int GTiffDataset::GetGCPCount()
 const char *GTiffDataset::GetGCPProjection()
 
 {
+    LoadGeoreferencingAndPamIfNeeded();
+
     if( nGCPCount > 0 )
     {
         LookForProjection();
@@ -12842,6 +14592,8 @@ const char *GTiffDataset::GetGCPProjection()
 const GDAL_GCP *GTiffDataset::GetGCPs()
 
 {
+    LoadGeoreferencingAndPamIfNeeded();
+
     return pasGCPList;
 }
 
@@ -12849,31 +14601,33 @@ const GDAL_GCP *GTiffDataset::GetGCPs()
 /*                               SetGCPs()                              */
 /************************************************************************/
 
-CPLErr GTiffDataset::SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
+CPLErr GTiffDataset::SetGCPs( int nGCPCountIn, const GDAL_GCP *pasGCPListIn,
                               const char *pszGCPProjection )
 {
+    LoadGeoreferencingAndPamIfNeeded();
+
     if( GetAccess() == GA_Update )
     {
         LookForProjection();
 
-        if (this->nGCPCount > 0 && nGCPCount == 0)
+        if (nGCPCount > 0 && nGCPCountIn == 0)
             bForceUnsetGTOrGCPs = TRUE;
-        if( !EQUAL(this->pszProjection, "") &&
+        if( !EQUAL(pszProjection, "") &&
                    (pszGCPProjection == NULL ||
                    pszGCPProjection[0] == '\0') )
             bForceUnsetProjection = TRUE;
 
-        if( this->nGCPCount > 0 )
+        if( nGCPCount > 0 )
         {
-            GDALDeinitGCPs( this->nGCPCount, this->pasGCPList );
-            CPLFree( this->pasGCPList );
+            GDALDeinitGCPs( nGCPCount, pasGCPList );
+            CPLFree( pasGCPList );
         }
 
-        this->nGCPCount = nGCPCount;
-        this->pasGCPList = GDALDuplicateGCPs(nGCPCount, pasGCPList);
+        nGCPCount = nGCPCountIn;
+        pasGCPList = GDALDuplicateGCPs(nGCPCount, pasGCPListIn);
 
-        CPLFree( this->pszProjection );
-        this->pszProjection = CPLStrdup( pszGCPProjection );
+        CPLFree( pszProjection );
+        pszProjection = CPLStrdup( pszGCPProjection );
         bGeoTIFFInfoChanged = TRUE;
 
         return CE_None;
@@ -12892,6 +14646,8 @@ CPLErr GTiffDataset::SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
 
 char **GTiffDataset::GetMetadataDomainList()
 {
+    LoadGeoreferencingAndPamIfNeeded();
+
     return BuildMetadataDomainList(CSLDuplicate(oGTiffMDMD.GetDomainList()),
                                    TRUE,
                                    "", "ProxyOverviewRequest", MD_DOMAIN_RPC, MD_DOMAIN_IMD, "SUBDATASETS", "EXIF",
@@ -12905,6 +14661,11 @@ char **GTiffDataset::GetMetadataDomainList()
 char **GTiffDataset::GetMetadata( const char * pszDomain )
 
 {
+    if( pszDomain == NULL || !EQUAL(pszDomain, "IMAGE_STRUCTURE") )
+    {
+        LoadGeoreferencingAndPamIfNeeded();
+    }
+
     if( pszDomain != NULL && EQUAL(pszDomain,"ProxyOverviewRequest") )
         return GDALPamDataset::GetMetadata( pszDomain );
 
@@ -12912,7 +14673,7 @@ char **GTiffDataset::GetMetadata( const char * pszDomain )
                                    EQUAL(pszDomain, MD_DOMAIN_IMD) ||
                                    EQUAL(pszDomain, MD_DOMAIN_IMAGERY)) )
         LoadMetadata();
-    
+
     else if( pszDomain != NULL && EQUAL(pszDomain,"SUBDATASETS") )
         ScanDirectories();
 
@@ -12934,6 +14695,8 @@ char **GTiffDataset::GetMetadata( const char * pszDomain )
 CPLErr GTiffDataset::SetMetadata( char ** papszMD, const char *pszDomain )
 
 {
+    LoadGeoreferencingAndPamIfNeeded();
+
     if( bStreamingOut && bCrystalized )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
@@ -12955,9 +14718,9 @@ CPLErr GTiffDataset::SetMetadata( char ** papszMD, const char *pszDomain )
     if( (pszDomain == NULL || EQUAL(pszDomain, "")) &&
         CSLFetchNameValue(papszMD, GDALMD_AREA_OR_POINT) != NULL )
     {
-        const char* pszPrevValue = 
+        const char* pszPrevValue =
                 GetMetadataItem(GDALMD_AREA_OR_POINT);
-        const char* pszNewValue = 
+        const char* pszNewValue =
                 CSLFetchNameValue(papszMD, GDALMD_AREA_OR_POINT);
         if (pszPrevValue == NULL || pszNewValue == NULL ||
             !EQUAL(pszPrevValue, pszNewValue))
@@ -12974,10 +14737,15 @@ CPLErr GTiffDataset::SetMetadata( char ** papszMD, const char *pszDomain )
 /*                          GetMetadataItem()                           */
 /************************************************************************/
 
-const char *GTiffDataset::GetMetadataItem( const char * pszName, 
+const char *GTiffDataset::GetMetadataItem( const char * pszName,
                                            const char * pszDomain )
 
 {
+    if( pszDomain == NULL || !EQUAL(pszDomain, "IMAGE_STRUCTURE") )
+    {
+        LoadGeoreferencingAndPamIfNeeded();
+    }
+
     if( pszDomain != NULL && EQUAL(pszDomain,"ProxyOverviewRequest") )
         return GDALPamDataset::GetMetadataItem( pszName, pszDomain );
 
@@ -13017,6 +14785,28 @@ const char *GTiffDataset::GetMetadataItem( const char * pszName,
         return (osMissing.size()) ? CPLSPrintf("%s", osMissing.c_str()) : NULL;
     }
 #endif
+    else if( pszDomain != NULL && EQUAL(pszDomain, "_DEBUG_") &&
+             pszName != NULL && EQUAL(pszName, "TIFFTAG_EXTRASAMPLES") )
+    {
+        CPLString osRet;
+        uint16 *v;
+        uint16 count = 0;
+
+        if( TIFFGetField( hTIFF, TIFFTAG_EXTRASAMPLES, &count, &v ) )
+        {
+            for(int i=0; i < (int)count; i++)
+            {
+                if( i > 0 ) osRet += ",";
+                osRet += CPLSPrintf("%d", v[i]);
+            }
+        }
+        return (osRet.size()) ? CPLSPrintf("%s", osRet.c_str()) : NULL;
+    }
+    else if( pszDomain != NULL && EQUAL(pszDomain, "_DEBUG_") &&
+             pszName != NULL && EQUAL(pszName, "TIFFTAG_PHOTOMETRIC") )
+    {
+        return CPLSPrintf("%d", nPhotometric);
+    }
 
     return oGTiffMDMD.GetMetadataItem( pszName, pszDomain );
 }
@@ -13025,11 +14815,13 @@ const char *GTiffDataset::GetMetadataItem( const char * pszName,
 /*                          SetMetadataItem()                           */
 /************************************************************************/
 
-CPLErr GTiffDataset::SetMetadataItem( const char *pszName, 
+CPLErr GTiffDataset::SetMetadataItem( const char *pszName,
                                       const char *pszValue,
                                       const char *pszDomain )
 
 {
+    LoadGeoreferencingAndPamIfNeeded();
+
     if( bStreamingOut && bCrystalized )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
@@ -13084,8 +14876,9 @@ void GTiffDataset::LoadEXIFMetadata()
     VSILFILE* fp = VSI_TIFFGetVSILFile(TIFFClientdata( hTIFF ));
 
     GByte          abyHeader[2];
-    VSIFSeekL(fp, 0, SEEK_SET);
-    VSIFReadL(abyHeader, 1, 2, fp);
+    if( VSIFSeekL(fp, 0, SEEK_SET) != 0 ||
+        VSIFReadL(abyHeader, 1, 2, fp) != 2 )
+        return;
 
     int bLittleEndian = abyHeader[0] == 'I' && abyHeader[1] == 'I';
     int bSwabflag = bLittleEndian ^ CPL_IS_LSB;
@@ -13162,6 +14955,8 @@ void GTiffDataset::LoadMetadata()
 char **GTiffDataset::GetFileList()
 
 {
+    LoadGeoreferencingAndPamIfNeeded();
+
     char **papszFileList = GDALPamDataset::GetFileList();
 
     LoadMetadata();
@@ -13186,7 +14981,7 @@ char **GTiffDataset::GetFileList()
 /*                         CreateMaskBand()                             */
 /************************************************************************/
 
-CPLErr GTiffDataset::CreateMaskBand(int nFlags)
+CPLErr GTiffDataset::CreateMaskBand(int nFlagsIn)
 {
     ScanDirectories();
 
@@ -13196,15 +14991,15 @@ CPLErr GTiffDataset::CreateMaskBand(int nFlags)
                  "This TIFF dataset has already an internal mask band");
         return CE_Failure;
     }
-    else if (CSLTestBoolean(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK", "NO")))
+    else if (CPLTestBool(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK", "NO")))
     {
         toff_t  nOffset;
         int     bIsTiled;
         int     bIsOverview = FALSE;
-        uint32	nSubType;
-        int     nCompression;
+        uint32 nSubType;
+        int     l_nCompression;
 
-        if (nFlags != GMF_PER_DATASET)
+        if (nFlagsIn != GMF_PER_DATASET)
         {
             CPLError(CE_Failure, CPLE_AppDefined,
                      "The only flag value supported for internal mask is GMF_PER_DATASET");
@@ -13214,9 +15009,9 @@ CPLErr GTiffDataset::CreateMaskBand(int nFlags)
         if( strstr(GDALGetMetadataItem(GDALGetDriverByName( "GTiff" ),
                                        GDAL_DMD_CREATIONOPTIONLIST, NULL ),
                    "<Value>DEFLATE</Value>") != NULL )
-            nCompression = COMPRESSION_ADOBE_DEFLATE;
+            l_nCompression = COMPRESSION_ADOBE_DEFLATE;
         else
-            nCompression = COMPRESSION_PACKBITS;
+            l_nCompression = COMPRESSION_PACKBITS;
 
     /* -------------------------------------------------------------------- */
     /*      If we don't have read access, then create the mask externally.  */
@@ -13227,7 +15022,7 @@ CPLErr GTiffDataset::CreateMaskBand(int nFlags)
                     "File open for read-only accessing, "
                     "creating mask externally." );
 
-            return GDALPamDataset::CreateMaskBand(nFlags);
+            return GDALPamDataset::CreateMaskBand(nFlagsIn);
         }
 
         if (poBaseDS)
@@ -13251,23 +15046,23 @@ CPLErr GTiffDataset::CreateMaskBand(int nFlags)
         }
 
         bIsTiled = TIFFIsTiled(hTIFF);
-        
+
         FlushDirectory();
-        
+
         nOffset = GTIFFWriteDirectory(hTIFF,
                                       (bIsOverview) ? FILETYPE_REDUCEDIMAGE | FILETYPE_MASK : FILETYPE_MASK,
                                       nRasterXSize, nRasterYSize,
                                       1, PLANARCONFIG_CONTIG, 1,
                                       nBlockXSize, nBlockYSize,
-                                      bIsTiled, nCompression, 
+                                      bIsTiled, l_nCompression,
                                       PHOTOMETRIC_MASK, PREDICTOR_NONE,
                                       SAMPLEFORMAT_UINT, NULL, NULL, NULL, 0, NULL, "");
         if (nOffset == 0)
             return CE_Failure;
 
         poMaskDS = new GTiffDataset();
-        poMaskDS->bPromoteTo8Bits = CSLTestBoolean(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK_TO_8BIT", "YES"));
-        if( poMaskDS->OpenOffset( hTIFF, ppoActiveDSRef, nOffset, 
+        poMaskDS->bPromoteTo8Bits = CPLTestBool(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK_TO_8BIT", "YES"));
+        if( poMaskDS->OpenOffset( hTIFF, ppoActiveDSRef, nOffset,
                                   FALSE, GA_Update ) != CE_None)
         {
             delete poMaskDS;
@@ -13279,7 +15074,7 @@ CPLErr GTiffDataset::CreateMaskBand(int nFlags)
     }
     else
     {
-        return GDALPamDataset::CreateMaskBand(nFlags);
+        return GDALPamDataset::CreateMaskBand(nFlagsIn);
     }
 }
 
@@ -13287,7 +15082,7 @@ CPLErr GTiffDataset::CreateMaskBand(int nFlags)
 /*                         CreateMaskBand()                             */
 /************************************************************************/
 
-CPLErr GTiffRasterBand::CreateMaskBand(int nFlags)
+CPLErr GTiffRasterBand::CreateMaskBand(int nFlagsIn)
 {
     poGDS->ScanDirectories();
 
@@ -13297,13 +15092,13 @@ CPLErr GTiffRasterBand::CreateMaskBand(int nFlags)
                  "This TIFF dataset has already an internal mask band");
         return CE_Failure;
     }
-    else if (CSLTestBoolean(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK", "NO")))
+    else if (CPLTestBool(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK", "NO")))
     {
-        return poGDS->CreateMaskBand(nFlags);
+        return poGDS->CreateMaskBand(nFlagsIn);
     }
     else
     {
-        return GDALPamRasterBand::CreateMaskBand(nFlags);
+        return GDALPamRasterBand::CreateMaskBand(nFlagsIn);
     }
 }
 
@@ -13342,10 +15137,10 @@ static char *PrepareTIFFErrorFormat( const char *module, const char *fmt )
 /************************************************************************/
 /*                        GTiffWarningHandler()                         */
 /************************************************************************/
-void
+static void
 GTiffWarningHandler(const char* module, const char* fmt, va_list ap )
 {
-    char	*pszModFmt;
+    char *pszModFmt;
 
     if( strstr(fmt,"nknown field") != NULL )
         return;
@@ -13365,7 +15160,7 @@ GTiffWarningHandler(const char* module, const char* fmt, va_list ap )
 /************************************************************************/
 /*                         GTiffErrorHandler()                          */
 /************************************************************************/
-void
+static void
 GTiffErrorHandler(const char* module, const char* fmt, va_list ap )
 {
     char *pszModFmt;
@@ -13388,7 +15183,14 @@ GTiffErrorHandler(const char* module, const char* fmt, va_list ap )
 #ifdef BIGTIFF_SUPPORT
     if( strcmp(fmt, "Maximum TIFF file size exceeded") == 0 )
     {
-        fmt = "Maximum TIFF file size exceeded. Use BIGTIFF=YES creation option.";
+        // Ideally there would be a thread-safe way of setting this flag,
+        // but we cannot really use the extended error handler, since the
+        // handler is for all TIFF handles, and not necessarily the ones of
+        // this driver.
+        if( bGlobalInExternalOvr )
+            fmt = "Maximum TIFF file size exceeded. Use --config BIGTIFF_OVERVIEW YES configuration option.";
+        else
+            fmt = "Maximum TIFF file size exceeded. Use BIGTIFF=YES creation option.";
     }
 #endif
 
@@ -13409,19 +15211,19 @@ static void GTiffTagExtender(TIFF *tif)
 
 {
     static const TIFFFieldInfo xtiffFieldInfo[] = {
-        { TIFFTAG_GDAL_METADATA,    -1,-1, TIFF_ASCII,	FIELD_CUSTOM,
-          TRUE,	FALSE,	(char*) "GDALMetadata" },
-        { TIFFTAG_GDAL_NODATA,	    -1,-1, TIFF_ASCII,	FIELD_CUSTOM,
-          TRUE,	FALSE,	(char*) "GDALNoDataValue" },
-        { TIFFTAG_RPCCOEFFICIENT,   -1,-1, TIFF_DOUBLE,	FIELD_CUSTOM,
-          TRUE,	TRUE,	(char*) "RPCCoefficient" }
+        { TIFFTAG_GDAL_METADATA,    -1,-1, TIFF_ASCII, FIELD_CUSTOM,
+          TRUE, FALSE, (char*) "GDALMetadata" },
+        { TIFFTAG_GDAL_NODATA, -1,-1, TIFF_ASCII, FIELD_CUSTOM,
+          TRUE, FALSE, (char*) "GDALNoDataValue" },
+        { TIFFTAG_RPCCOEFFICIENT,   -1,-1, TIFF_DOUBLE, FIELD_CUSTOM,
+          TRUE, TRUE, (char*) "RPCCoefficient" }
     };
 
-    if (_ParentExtender) 
+    if (_ParentExtender)
         (*_ParentExtender)(tif);
 
     TIFFMergeFieldInfo( tif, xtiffFieldInfo,
-		        sizeof(xtiffFieldInfo) / sizeof(xtiffFieldInfo[0]) );
+                        sizeof(xtiffFieldInfo) / sizeof(xtiffFieldInfo[0]) );
 }
 
 /************************************************************************/
@@ -13550,6 +15352,7 @@ int GTIFFGetCompressionMethod(const char* pszValue, const char* pszVariableName)
 
     return nCompression;
 }
+
 /************************************************************************/
 /*                          GDALRegister_GTiff()                        */
 /************************************************************************/
@@ -13557,105 +15360,109 @@ int GTIFFGetCompressionMethod(const char* pszValue, const char* pszVariableName)
 void GDALRegister_GTiff()
 
 {
-    if( GDALGetDriverByName( "GTiff" ) == NULL )
-    {
-        GDALDriver	*poDriver;
-        char szCreateOptions[5000];
-        char szOptionalCompressItems[500];
-        int bHasJPEG = FALSE, bHasLZW = FALSE, bHasDEFLATE = FALSE, bHasLZMA = FALSE;
+    if( GDALGetDriverByName( "GTiff" ) != NULL )
+        return;
+
+    char szCreateOptions[5000];
+    char szOptionalCompressItems[500];
+    bool bHasJPEG = false;
+    bool bHasLZW = false;
+    bool bHasDEFLATE = false;
+    bool bHasLZMA = false;
+
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver = new GDALDriver();
-        
 /* -------------------------------------------------------------------- */
 /*      Determine which compression codecs are available that we        */
 /*      want to advertise.  If we are using an old libtiff we won't     */
 /*      be able to find out so we just assume all are available.        */
 /* -------------------------------------------------------------------- */
-        strcpy( szOptionalCompressItems, 
-                "       <Value>NONE</Value>" );
+    strcpy( szOptionalCompressItems, "       <Value>NONE</Value>" );
 
 #if TIFFLIB_VERSION <= 20040919
-        strcat( szOptionalCompressItems, 
-                "       <Value>PACKBITS</Value>"
-                "       <Value>JPEG</Value>"
-                "       <Value>LZW</Value>"
-                "       <Value>DEFLATE</Value>" );
-        bHasLZW = bHasDEFLATE = TRUE;
+    strcat( szOptionalCompressItems,
+            "       <Value>PACKBITS</Value>"
+            "       <Value>JPEG</Value>"
+            "       <Value>LZW</Value>"
+            "       <Value>DEFLATE</Value>" );
+    bHasLZW = bHasDEFLATE = true;
 #else
-        TIFFCodec	*c, *codecs = TIFFGetConfiguredCODECs();
+    TIFFCodec *c;
+    TIFFCodec *codecs = TIFFGetConfiguredCODECs();
 
-        for( c = codecs; c->name; c++ )
+    for( c = codecs; c->name; c++ )
+    {
+        if( c->scheme == COMPRESSION_PACKBITS )
+            strcat( szOptionalCompressItems,
+                    "       <Value>PACKBITS</Value>" );
+        else if( c->scheme == COMPRESSION_JPEG )
         {
-            if( c->scheme == COMPRESSION_PACKBITS )
-                strcat( szOptionalCompressItems,
-                        "       <Value>PACKBITS</Value>" );
-            else if( c->scheme == COMPRESSION_JPEG )
-            {
-                bHasJPEG = TRUE;
-                strcat( szOptionalCompressItems,
-                        "       <Value>JPEG</Value>" );
-            }
-            else if( c->scheme == COMPRESSION_LZW )
-            {
-                bHasLZW = TRUE;
-                strcat( szOptionalCompressItems,
-                        "       <Value>LZW</Value>" );
-            }
-            else if( c->scheme == COMPRESSION_ADOBE_DEFLATE )
-            {
-                bHasDEFLATE = TRUE;
-                strcat( szOptionalCompressItems,
-                        "       <Value>DEFLATE</Value>" );
-            }
-            else if( c->scheme == COMPRESSION_CCITTRLE )
-                strcat( szOptionalCompressItems,
-                        "       <Value>CCITTRLE</Value>" );
-            else if( c->scheme == COMPRESSION_CCITTFAX3 )
-                strcat( szOptionalCompressItems,
-                        "       <Value>CCITTFAX3</Value>" );
-            else if( c->scheme == COMPRESSION_CCITTFAX4 )
-                strcat( szOptionalCompressItems,
-                        "       <Value>CCITTFAX4</Value>" );
-            else if( c->scheme == COMPRESSION_LZMA )
-            {
-                bHasLZMA = TRUE;
-                strcat( szOptionalCompressItems,
-                        "       <Value>LZMA</Value>" );
-            }
+            bHasJPEG = true;
+            strcat( szOptionalCompressItems,
+                    "       <Value>JPEG</Value>" );
+        }
+        else if( c->scheme == COMPRESSION_LZW )
+        {
+            bHasLZW = TRUE;
+            strcat( szOptionalCompressItems,
+                    "       <Value>LZW</Value>" );
+        }
+        else if( c->scheme == COMPRESSION_ADOBE_DEFLATE )
+        {
+            bHasDEFLATE = TRUE;
+            strcat( szOptionalCompressItems,
+                    "       <Value>DEFLATE</Value>" );
+        }
+        else if( c->scheme == COMPRESSION_CCITTRLE )
+            strcat( szOptionalCompressItems,
+                    "       <Value>CCITTRLE</Value>" );
+        else if( c->scheme == COMPRESSION_CCITTFAX3 )
+            strcat( szOptionalCompressItems,
+                    "       <Value>CCITTFAX3</Value>" );
+        else if( c->scheme == COMPRESSION_CCITTFAX4 )
+            strcat( szOptionalCompressItems,
+                    "       <Value>CCITTFAX4</Value>" );
+        else if( c->scheme == COMPRESSION_LZMA )
+        {
+            bHasLZMA = true;
+            strcat( szOptionalCompressItems,
+                    "       <Value>LZMA</Value>" );
         }
-        _TIFFfree( codecs );
-#endif        
+    }
+    _TIFFfree( codecs );
+#endif
 
 /* -------------------------------------------------------------------- */
 /*      Build full creation option list.                                */
 /* -------------------------------------------------------------------- */
-        sprintf( szCreateOptions, "%s%s%s", 
-"<CreationOptionList>"
-"   <Option name='COMPRESS' type='string-select'>",
-                 szOptionalCompressItems,
-"   </Option>");
-        if (bHasLZW || bHasDEFLATE)
-            strcat( szCreateOptions, ""        
-"   <Option name='PREDICTOR' type='int' description='Predictor Type (1=default, 2=horizontal differencing, 3=floating point prediction)'/>");
+    snprintf( szCreateOptions, sizeof(szCreateOptions), "%s%s%s",
+              "<CreationOptionList>"
+              "   <Option name='COMPRESS' type='string-select'>",
+              szOptionalCompressItems,
+              "   </Option>");
+    if (bHasLZW || bHasDEFLATE)
         strcat( szCreateOptions, ""
+"   <Option name='PREDICTOR' type='int' description='Predictor Type (1=default, 2=horizontal differencing, 3=floating point prediction)'/>");
+    strcat( szCreateOptions, ""
 "   <Option name='DISCARD_LSB' type='string' description='Number of least-significant bits to set to clear as a single value or comma-separated list of values for per-band values'/>" );
-        if (bHasJPEG)
-        {
-            strcat( szCreateOptions, ""
+    if (bHasJPEG)
+    {
+        strcat( szCreateOptions, ""
 "   <Option name='JPEG_QUALITY' type='int' description='JPEG quality 1-100' default='75'/>"
 "   <Option name='JPEGTABLESMODE' type='int' description='Content of JPEGTABLES tag. 0=no JPEGTABLES tag, 1=Quantization tables only, 2=Huffman tables only, 3=Both' default='1'/>" );
 #ifdef JPEG_DIRECT_COPY
-            strcat( szCreateOptions, ""
+        strcat( szCreateOptions, ""
 "   <Option name='JPEG_DIRECT_COPY' type='boolean' description='To copy without any decompression/recompression a JPEG source file' default='NO'/>");
 #endif
-        }
-        if (bHasDEFLATE)
-            strcat( szCreateOptions, ""
+    }
+    if (bHasDEFLATE)
+        strcat( szCreateOptions, ""
 "   <Option name='ZLEVEL' type='int' description='DEFLATE compression level 1-9' default='6'/>");
-        if (bHasLZMA)
-            strcat( szCreateOptions, ""
-"   <Option name='LZMA_PRESET' type='int' description='LZMA compression level 0(fast)-9(slow)' default='6'/>");
+    if (bHasLZMA)
         strcat( szCreateOptions, ""
+"   <Option name='LZMA_PRESET' type='int' description='LZMA compression level 0(fast)-9(slow)' default='6'/>");
+    strcat( szCreateOptions, ""
+"   <Option name='NUM_THREADS' type='string' description='Number of worker threads for compression. Can be set to ALL_CPUS' default='1'/>"
 "   <Option name='NBITS' type='int' description='BITS for sub-byte files (1-7), sub-uint16 (9-15), sub-uint32 (17-31)'/>"
 "   <Option name='INTERLEAVE' type='string-select' default='PIXEL'>"
 "       <Value>BAND</Value>"
@@ -13721,38 +15528,48 @@ void GDALRegister_GTiff()
 "   <Option name='TIFFTAG_TRANSFERRANGE_BLACK' type='string' description='Transfer range for black'/>"
 "   <Option name='TIFFTAG_TRANSFERRANGE_WHITE' type='string' description='Transfer range for white'/>"
 "   <Option name='STREAMABLE_OUTPUT' type='boolean' default='NO' description='Enforce a mode compatible with a streamable file'/>"
+"   <Option name='GEOTIFF_KEYS_FLAVOR' type='string-select' default='STANDARD' description='Which flavor of GeoTIFF keys must be used'>"
+"       <Value>STANDARD</Value>"
+"       <Value>ESRI_PE</Value>"
+"   </Option>"
 "</CreationOptionList>" );
-                 
+
 /* -------------------------------------------------------------------- */
 /*      Set the driver details.                                         */
 /* -------------------------------------------------------------------- */
-        poDriver->SetDescription( "GTiff" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "GeoTIFF" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_gtiff.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/tiff" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "tif" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "tif tiff" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte UInt16 Int16 UInt32 Int32 Float32 "
-                                   "Float64 CInt16 CInt32 CFloat32 CFloat64" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
-                                   szCreateOptions );
-        poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetDescription( "GTiff" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "GeoTIFF" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_gtiff.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/tiff" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "tif" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "tif tiff" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte UInt16 Int16 UInt32 Int32 Float32 "
+                               "Float64 CInt16 CInt32 CFloat32 CFloat64" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, szCreateOptions );
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+"<OpenOptionList>"
+"   <Option name='NUM_THREADS' type='string' description='Number of worker threads for compression. Can be set to ALL_CPUS' default='1'/>"
+"   <Option name='GEOTIFF_KEYS_FLAVOR' type='string-select' default='STANDARD' description='Which flavor of GeoTIFF keys must be used (for writing)'>"
+"       <Value>STANDARD</Value>"
+"       <Value>ESRI_PE</Value>"
+"   </Option>"
+"</OpenOptionList>" );
+    poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
 #ifdef INTERNAL_LIBTIFF
-        poDriver->SetMetadataItem( "LIBTIFF", "INTERNAL" );
+    poDriver->SetMetadataItem( "LIBTIFF", "INTERNAL" );
 #else
-        poDriver->SetMetadataItem( "LIBTIFF", TIFFLIB_VERSION_STR );
+    poDriver->SetMetadataItem( "LIBTIFF", TIFFLIB_VERSION_STR );
 #endif
 
-        poDriver->pfnOpen = GTiffDataset::Open;
-        poDriver->pfnCreate = GTiffDataset::Create;
-        poDriver->pfnCreateCopy = GTiffDataset::CreateCopy;
-        poDriver->pfnUnloadDriver = GDALDeregister_GTiff;
-        poDriver->pfnIdentify = GTiffDataset::Identify;
+    poDriver->pfnOpen = GTiffDataset::Open;
+    poDriver->pfnCreate = GTiffDataset::Create;
+    poDriver->pfnCreateCopy = GTiffDataset::CreateCopy;
+    poDriver->pfnUnloadDriver = GDALDeregister_GTiff;
+    poDriver->pfnIdentify = GTiffDataset::Identify;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/gtiff/gt_citation.cpp b/frmts/gtiff/gt_citation.cpp
index 80470cf..c09b400 100644
--- a/frmts/gtiff/gt_citation.cpp
+++ b/frmts/gtiff/gt_citation.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gt_citation.cpp 28263 2014-12-29 22:00:08Z rouault $
+ * $Id: gt_citation.cpp 33796 2016-03-27 13:21:07Z goatbar $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Implements special parsing of Imagine citation strings, and
@@ -36,15 +36,15 @@
 #include "gt_citation.h"
 #include "gt_wkt_srs_priv.h"
 
-CPL_CVSID("$Id: gt_citation.cpp 28263 2014-12-29 22:00:08Z rouault $");
+CPL_CVSID("$Id: gt_citation.cpp 33796 2016-03-27 13:21:07Z goatbar $");
 
-static const char *apszUnitMap[] = {
+static const char * const apszUnitMap[] = {
     "meters", "1.0",
     "meter", "1.0",
     "m", "1.0",
     "centimeters", "0.01",
     "centimeter", "0.01",
-    "cm", "0.01", 
+    "cm", "0.01",
     "millimeters", "0.001",
     "millimeter", "0.001",
     "mm", "0.001",
@@ -53,7 +53,7 @@ static const char *apszUnitMap[] = {
     "km", "1000.0",
     "us_survey_feet", "0.3048006096012192",
     "us_survey_foot", "0.3048006096012192",
-    "feet", "0.3048006096012192", 
+    "feet", "0.3048006096012192",
     "foot", "0.3048006096012192",
     "ft", "0.3048006096012192",
     "international_feet", "0.3048",
@@ -73,13 +73,13 @@ static const char *apszUnitMap[] = {
     "clarke_foot", "0.3047972651",
     "indian_feet", "0.3047995142",
     "indian_foot", "0.3047995142",
-    "Yard_Indian", "0.9143985307444408", 
+    "Yard_Indian", "0.9143985307444408",
     "Foot_Clarke", "0.30479726540",
     "Foot_Gold_Coast", "0.3047997101815088",
-    "Link_Clarke", "0.2011661951640", 
-    "Yard_Sears", "0.9143984146160287", 
-    "50_Kilometers", "50000.0", 
-    "150_Kilometers", "150000.0", 
+    "Link_Clarke", "0.2011661951640",
+    "Yard_Sears", "0.9143984146160287",
+    "50_Kilometers", "50000.0",
+    "150_Kilometers", "150000.0",
     NULL, NULL
 };
 
@@ -90,7 +90,7 @@ static const char *apszUnitMap[] = {
 /************************************************************************/
 char* ImagineCitationTranslation(char* psCitation, geokey_t keyID)
 {
-    static const char *keyNames[] = {
+    static const char * const keyNames[] = {
         "NAD = ", "Datum = ", "Ellipsoid = ", "Units = ", NULL
     };
 
@@ -98,7 +98,7 @@ char* ImagineCitationTranslation(char* psCitation, geokey_t keyID)
     int i;
     if(!psCitation)
         return ret;
-    if(EQUALN(psCitation, "IMAGINE GeoTIFF Support", strlen("IMAGINE GeoTIFF Support")))
+    if(STARTS_WITH_CI(psCitation, "IMAGINE GeoTIFF Support"))
     {
         // this is a handle IMAGING style citation
         char name[256];
@@ -150,14 +150,14 @@ char* ImagineCitationTranslation(char* psCitation, geokey_t keyID)
             if(strlen(name)>0)
             {
                 char* p2;
-                if((p2 = strstr(psCitation, "Projection Name = ")) != 0)
+                if((p2 = strstr(psCitation, "Projection Name = ")) != NULL)
                     p = p2 + strlen("Projection Name = ");
-                if((p2 = strstr(psCitation, "Projection = ")) != 0)
+                if((p2 = strstr(psCitation, "Projection = ")) != NULL)
                     p = p2 + strlen("Projection = ");
                 if(p1[0] == '\0' || p1[0] == '\n' || p1[0] == ' ')
                     p1 --;
                 p2 = p1 - 1;
-                while( p2 != 0 && (p2[0] == ' ' || p2[0] == '\0' || p2[0] == '\n') )
+                while( p2 != NULL && (p2[0] == ' ' || p2[0] == '\0' || p2[0] == '\n') )
                     p2--;
                 if(p2 != p1 - 1)
                     p1 = p2;
@@ -200,7 +200,7 @@ char* ImagineCitationTranslation(char* psCitation, geokey_t keyID)
                 if(p1[0] == '\0' || p1[0] == '\n' || p1[0] == ' ')
                     p1 --;
                 char* p2 = p1 - 1;
-                while( p2 != 0 && (p2[0] == ' ' || p2[0] == '\0' || p2[0] == '\n') )
+                while( p2 != NULL && (p2[0] == ' ' || p2[0] == '\0' || p2[0] == '\n') )
                     p2--;
                 if(p2 != p1 - 1)
                     p1 = p2;
@@ -231,12 +231,12 @@ char** CitationStringParse(char* psCitation, geokey_t keyID)
     if(!psCitation)
         return ret;
 
-    ret = (char **) CPLCalloc(sizeof(char*), nCitationNameTypes); 
+    ret = (char **) CPLCalloc(sizeof(char*), nCitationNameTypes);
     char* pDelimit = NULL;
     char* pStr = psCitation;
     char name[512];
     int nameSet = FALSE;
-    int nameLen = strlen(psCitation);
+    int nameLen = static_cast<int>(strlen(psCitation));
     OGRBoolean nameFound = FALSE;
     while((pStr-psCitation+1)< nameLen)
     {
@@ -285,7 +285,7 @@ char** CitationStringParse(char* psCitation, geokey_t keyID)
         }
         if(strstr(name, "Primem = "))
         {
-            ret[CitPrimemName] = CPLStrdup(name+strlen("Primem = "));    
+            ret[CitPrimemName] = CPLStrdup(name+strlen("Primem = "));
             nameFound = TRUE;
         }
         if(strstr(name, "AUnits = "))
@@ -319,7 +319,7 @@ void SetLinearUnitCitation(GTIF* psGTIF, char* pszLinearUOMName)
     CPLString osCitation;
     int n = 0;
     if( GDALGTIFKeyGetASCII( psGTIF, PCSCitationGeoKey, szName, 0, sizeof(szName) ) )
-        n = strlen(szName);
+        n = static_cast<int>(strlen(szName));
     if(n>0)
     {
         osCitation = szName;
@@ -354,7 +354,7 @@ void SetGeogCSCitation(GTIF * psGTIF, OGRSpatialReference *poSRS, char* angUnitN
     if (n == 0)
         return;
 
-    if(!EQUALN(szName, "GCS Name = ", strlen("GCS Name = ")))
+    if(!STARTS_WITH_CI(szName, "GCS Name = "))
     {
         osCitation = "GCS Name = ";
         osCitation += szName;
@@ -398,9 +398,9 @@ void SetGeogCSCitation(GTIF * psGTIF, OGRSpatialReference *poSRS, char* angUnitN
             double aUnit = poSRS->GetAngularUnits(NULL);
             primemValue *= aUnit;
         }
-        GTIFKeySet( psGTIF, GeogPrimeMeridianLongGeoKey, TYPE_DOUBLE, 1, 
+        GTIFKeySet( psGTIF, GeogPrimeMeridianLongGeoKey, TYPE_DOUBLE, 1,
                     primemValue );
-    } 
+    }
     if(angUnitName && strlen(angUnitName) > 0 && !EQUAL(angUnitName, "Degree"))
     {
         osCitation += "|AUnits = ";
@@ -423,11 +423,11 @@ void SetGeogCSCitation(GTIF * psGTIF, OGRSpatialReference *poSRS, char* angUnitN
 /*      Parse and set Citation string to SRS                            */
 /************************************************************************/
 OGRBoolean SetCitationToSRS(GTIF* hGTIF, char* szCTString, int nCTStringLen,
-                            geokey_t geoKey,  OGRSpatialReference*	poSRS, OGRBoolean* linearUnitIsSet)
+                            geokey_t geoKey,  OGRSpatialReference *poSRS, OGRBoolean* linearUnitIsSet)
 {
     OGRBoolean ret = FALSE;
     char* lUnitName = NULL;
-    
+
     poSRS->GetLinearUnits( &lUnitName );
     if(!lUnitName || strlen(lUnitName) == 0  || EQUAL(lUnitName, "unknown"))
         *linearUnitIsSet = FALSE;
@@ -457,7 +457,7 @@ OGRBoolean SetCitationToSRS(GTIF* hGTIF, char* szCTString, int nCTStringLen,
         if(ctNames[CitLUnitsName])
         {
             double unitSize = 0.0;
-            int size = strlen(ctNames[CitLUnitsName]);
+            int size = static_cast<int>(strlen(ctNames[CitLUnitsName]));
             if(strchr(ctNames[CitLUnitsName], '\0'))
                 size -= 1;
             for( int i = 0; apszUnitMap[i] != NULL; i += 2 )
@@ -473,7 +473,7 @@ OGRBoolean SetCitationToSRS(GTIF* hGTIF, char* szCTString, int nCTStringLen,
             poSRS->SetLinearUnits( ctNames[CitLUnitsName], unitSize);
             *linearUnitIsSet = TRUE;
         }
-        for(int i= 0; i<nCitationNameTypes; i++) 
+        for(int i= 0; i<nCitationNameTypes; i++)
             CPLFree( ctNames[i] );
         CPLFree( ctNames );
     }
@@ -500,14 +500,14 @@ OGRBoolean SetCitationToSRS(GTIF* hGTIF, char* szCTString, int nCTStringLen,
 /*      Parse and get geogcs names from a Citation string               */
 /************************************************************************/
 void GetGeogCSFromCitation(char* szGCSName, int nGCSName,
-                           geokey_t geoKey, 
-                           char	**ppszGeogName,
-                           char	**ppszDatumName,
-                           char	**ppszPMName,
-                           char	**ppszSpheroidName,
-                           char	**ppszAngularUnits)
+                           geokey_t geoKey,
+                           char **ppszGeogName,
+                           char **ppszDatumName,
+                           char **ppszPMName,
+                           char **ppszSpheroidName,
+                           char **ppszAngularUnits)
 {
-    *ppszGeogName = *ppszDatumName = *ppszPMName = 
+    *ppszGeogName = *ppszDatumName = *ppszPMName =
         *ppszSpheroidName = *ppszAngularUnits = NULL;
 
     char* imgCTName = ImagineCitationTranslation(szGCSName, geoKey);
@@ -555,7 +555,7 @@ OGRBoolean CheckCitationKeyForStatePlaneUTM(GTIF* hGTIF, GTIFDefn* psDefn, OGRSp
 
 /* -------------------------------------------------------------------- */
 /*      For ESRI builds we are interested in maximizing PE              */
-/*      compatability, but generally we prefer to use EPSG              */
+/*      compatibility, but generally we prefer to use EPSG              */
 /*      definitions of the coordinate system if PCS is defined.         */
 /* -------------------------------------------------------------------- */
 #if !defined(ESRI_BUILD)
@@ -580,8 +580,8 @@ OGRBoolean CheckCitationKeyForStatePlaneUTM(GTIF* hGTIF, GTIFDefn* psDefn, OGRSp
         if( strstr(osLCCT,"us") && strstr(osLCCT,"survey")
             && (strstr(osLCCT,"feet") || strstr(osLCCT,"foot")) )
             strcpy(units, "us_survey_feet");
-        else if(strstr(osLCCT, "linear_feet")  
-                || strstr(osLCCT, "linear_foot") 
+        else if(strstr(osLCCT, "linear_feet")
+                || strstr(osLCCT, "linear_foot")
                 || strstr(osLCCT, "international"))
             strcpy(units, "international_feet");
         else if( strstr(osLCCT,"meter") )
@@ -604,14 +604,14 @@ OGRBoolean CheckCitationKeyForStatePlaneUTM(GTIF* hGTIF, GTIFDefn* psDefn, OGRSp
                 if (hasUnits)
                 {
                     OGR_SRSNode *poUnit = poSRS->GetAttrNode( "PROJCS|UNIT" );
-      
+
                     if( poUnit != NULL && poUnit->GetChildCount() >= 2 )
                     {
                         CPLString unitName = poUnit->GetChild(0)->GetValue();
                         unitName.tolower();
 
                         if (strstr(units, "us_survey_feet"))
-                        {              
+                        {
                             if (strstr(unitName, "us_survey_feet") || strstr(unitName, "foot_us") )
                                 done = TRUE;
                         }
@@ -634,9 +634,9 @@ OGRBoolean CheckCitationKeyForStatePlaneUTM(GTIF* hGTIF, GTIFDefn* psDefn, OGRSp
     }
     if( !hasUnits )
     {
-        char	*pszUnitsName = NULL;
+        char *pszUnitsName = NULL;
         GTIFGetUOMLengthInfo( psDefn->UOMLength, &pszUnitsName, NULL );
-        if( pszUnitsName && strlen(pszUnitsName) > 0 )
+        if( pszUnitsName )
         {
             CPLString osLCCT = pszUnitsName;
             GTIFFreeMemory( pszUnitsName );
@@ -649,7 +649,7 @@ OGRBoolean CheckCitationKeyForStatePlaneUTM(GTIF* hGTIF, GTIFDefn* psDefn, OGRSp
                 strcpy(units, "international_feet");
             else if(strstr(osLCCT, "meter"))
                 strcpy(units, "meters");
-            hasUnits = TRUE;
+            /*hasUnits = TRUE;*/
         }
     }
 
@@ -658,11 +658,11 @@ OGRBoolean CheckCitationKeyForStatePlaneUTM(GTIF* hGTIF, GTIFDefn* psDefn, OGRSp
 
     /* check PCSCitationGeoKey if it exists */
     szCTString[0] = '\0';
-    if( hGTIF && GDALGTIFKeyGetASCII( hGTIF, PCSCitationGeoKey, szCTString, 0, sizeof(szCTString)) )  
+    if( hGTIF && GDALGTIFKeyGetASCII( hGTIF, PCSCitationGeoKey, szCTString, 0, sizeof(szCTString)) )
     {
         /* For tif created by LEICA(ERDAS), ESRI state plane pe string was used and */
         /* the state plane zone is given in PCSCitation. Therefore try Esri pe string first. */
-        SetCitationToSRS(hGTIF, szCTString, strlen(szCTString), PCSCitationGeoKey, poSRS, pLinearUnitIsSet);
+        SetCitationToSRS(hGTIF, szCTString, static_cast<int>(strlen(szCTString)), PCSCitationGeoKey, poSRS, pLinearUnitIsSet);
         const char *pcsName = poSRS->GetAttrValue("PROJCS");
         const char *pStr = NULL;
         if( (pcsName && (pStr = strstr(pcsName, "State Plane Zone ")) != NULL)
@@ -703,7 +703,7 @@ void CheckUTM( GTIFDefn * psDefn, const char * pszCtString )
     if(!psDefn || !pszCtString)
         return;
 
-    static const char *apszUtmProjCode[] = {
+    static const char * const apszUtmProjCode[] = {
         "PSAD56", "17N", "16017",
         "PSAD56", "18N", "16018",
         "PSAD56", "19N", "16019",
diff --git a/frmts/gtiff/gt_citation.h b/frmts/gtiff/gt_citation.h
index 8a43c9a..661efc2 100644
--- a/frmts/gtiff/gt_citation.h
+++ b/frmts/gtiff/gt_citation.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gt_citation.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: gt_citation.h 33796 2016-03-27 13:21:07Z goatbar $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Implements special parsing of Imagine citation strings, and
@@ -40,7 +40,7 @@ char* ImagineCitationTranslation(char* psCitation, geokey_t keyID);
 char** CitationStringParse(char* psCitation, geokey_t keyID);
 
 #define nCitationNameTypes 9
-typedef enum 
+typedef enum
 {
   CitCsName = 0,
   CitPcsName = 1,
@@ -61,12 +61,12 @@ void SetGeogCSCitation(GTIF * psGTIF, OGRSpatialReference *poSRS, char* angUnitN
 OGRBoolean SetCitationToSRS(GTIF* hGTIF, char* szCTString, int nCTStringLen,
                             geokey_t geoKey, OGRSpatialReference* poSRS, OGRBoolean* linearUnitIsSet);
 void GetGeogCSFromCitation(char* szGCSName, int nGCSName,
-                           geokey_t geoKey, 
-                          char	**ppszGeogName,
-                          char	**ppszDatumName,
-                          char	**ppszPMName,
-                          char	**ppszSpheroidName,
-                          char	**ppszAngularUnits);
+                           geokey_t geoKey,
+                          char **ppszGeogName,
+                          char **ppszDatumName,
+                          char **ppszPMName,
+                          char **ppszSpheroidName,
+                          char **ppszAngularUnits);
 void CheckUTM( GTIFDefn * psDefn, const char * pszCtString );
 
 
diff --git a/frmts/gtiff/gt_jpeg_copy.cpp b/frmts/gtiff/gt_jpeg_copy.cpp
index 97b98dc..4d897d3 100644
--- a/frmts/gtiff/gt_jpeg_copy.cpp
+++ b/frmts/gtiff/gt_jpeg_copy.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gt_jpeg_copy.cpp 28213 2014-12-25 00:42:13Z rouault $
+ * $Id: gt_jpeg_copy.cpp 33806 2016-03-28 22:26:19Z goatbar $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Specialized copy of JPEG content into TIFF.
@@ -29,16 +29,21 @@
 
 #include "cpl_vsi.h"
 #include "gt_jpeg_copy.h"
+#if defined(JPEG_DIRECT_COPY) || defined(HAVE_LIBJPEG)
+#  include "vrt/vrtdataset.h"
+#endif
+
+#ifndef BIGTIFF_SUPPORT
+#define tmsize_t tsize_t
+#endif
 
 /* Note: JPEG_DIRECT_COPY is not defined by default, because it is mainly */
 /* useful for debugging purposes */
 
-CPL_CVSID("$Id: gt_jpeg_copy.cpp 28213 2014-12-25 00:42:13Z rouault $");
+CPL_CVSID("$Id: gt_jpeg_copy.cpp 33806 2016-03-28 22:26:19Z goatbar $");
 
 #if defined(JPEG_DIRECT_COPY) || defined(HAVE_LIBJPEG)
 
-#include "vrt/vrtdataset.h"
-
 /************************************************************************/
 /*                      GetUnderlyingDataset()                          */
 /************************************************************************/
@@ -79,7 +84,7 @@ static int IsBaselineDCTJPEG(VSILFILE* fp)
     }
 
     int nOffset = 2;
-    while(TRUE)
+    while( true )
     {
         VSIFSeekL(fp, nOffset, SEEK_SET);
         if (VSIFReadL(abyBuf, 1, 4, fp) != 4 ||
@@ -162,7 +167,7 @@ int GTIFF_CanDirectCopyFromJPEG(GDALDataset* poSrcDS, char** &papszCreateOptions
         papszCreateOptions = CSLSetNameValue(papszCreateOptions, "JPEG_QUALITY", NULL);
     }
     if (fpJPEG)
-        VSIFCloseL(fpJPEG);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpJPEG));
 
     return bJPEGDirectCopy;
 }
@@ -194,7 +199,7 @@ CPLErr GTIFF_DirectCopyFromJPEG(GDALDataset* poDS, GDALDataset* poSrcDS,
     void* pabyJPEGData = VSIMalloc(nSize);
     if (pabyJPEGData == NULL)
     {
-        VSIFCloseL(fpJPEG);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpJPEG));
         return CE_Failure;
     }
 
@@ -216,7 +221,8 @@ CPLErr GTIFF_DirectCopyFromJPEG(GDALDataset* poDS, GDALDataset* poSrcDS,
     }
 
     VSIFree(pabyJPEGData);
-    VSIFCloseL(fpJPEG);
+    if VSIFCloseL(fpJPEG) != 0 )
+        eErr = CE_Failure;
 
     return eErr;
 }
@@ -345,9 +351,9 @@ void GTIFF_Set_TIFFTAG_JPEGTABLES(TIFF* hTIFF,
                                   jpeg_compress_struct& sCInfo)
 {
     char szTmpFilename[128];
-    sprintf(szTmpFilename, "/vsimem/tables_%p", &sDInfo);
+    snprintf(szTmpFilename, sizeof(szTmpFilename), "/vsimem/tables_%p", &sDInfo);
     VSILFILE* fpTABLES = VSIFOpenL(szTmpFilename, "wb+");
-    
+
     uint16  nPhotometric;
     TIFFGetField( hTIFF, TIFFTAG_PHOTOMETRIC, &nPhotometric );
 
@@ -370,7 +376,7 @@ void GTIFF_Set_TIFFTAG_JPEGTABLES(TIFF* hTIFF,
     }
     jpeg_write_tables( &sCInfo );
 
-    VSIFCloseL(fpTABLES);
+    CPL_IGNORE_RET_VAL(VSIFCloseL(fpTABLES));
 
     vsi_l_offset nSizeTables = 0;
     GByte* pabyJPEGTablesData = VSIGetMemFileBuffer(szTmpFilename, &nSizeTables, FALSE);
@@ -403,7 +409,7 @@ CPLErr GTIFF_CopyFromJPEG_WriteAdditionalTags(TIFF* hTIFF,
     jmp_buf setjmp_buffer;
     if (setjmp(setjmp_buffer))
     {
-        VSIFCloseL(fpJPEG);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpJPEG));
         return CE_Failure;
     }
 
@@ -494,7 +500,8 @@ CPLErr GTIFF_CopyFromJPEG_WriteAdditionalTags(TIFF* hTIFF,
     jpeg_abort_decompress( &sDInfo );
     jpeg_destroy_decompress( &sDInfo );
 
-    VSIFCloseL(fpJPEG);
+    if( VSIFCloseL(fpJPEG) != 0 )
+        return CE_Failure;
 
     return CE_None;
 }
@@ -503,39 +510,60 @@ CPLErr GTIFF_CopyFromJPEG_WriteAdditionalTags(TIFF* hTIFF,
 /*                    GTIFF_CopyBlockFromJPEG()                         */
 /************************************************************************/
 
-static CPLErr GTIFF_CopyBlockFromJPEG(TIFF* hTIFF,
-                                      jpeg_decompress_struct& sDInfo,
-                                      int iX, int iY,
-                                      int nXBlocks,
-                                      CPL_UNUSED int nYBlocks,
-                                      int nXSize, int nYSize,
-                                      int nBlockXSize, int nBlockYSize,
-                                      int iMCU_sample_width, int iMCU_sample_height,
-                                      jvirt_barray_ptr *pSrcCoeffs)
+typedef struct
 {
-    CPLString osTmpFilename(CPLSPrintf("/vsimem/%p", &sDInfo));
+    TIFF* hTIFF;
+    jpeg_decompress_struct* psDInfo;
+    int iX;
+    int iY;
+    int nXBlocks;
+    int nXSize;
+    int nYSize;
+    int nBlockXSize;
+    int nBlockYSize;
+    int iMCU_sample_width;
+    int iMCU_sample_height;
+    jvirt_barray_ptr *pSrcCoeffs;
+} GTIFF_CopyBlockFromJPEGArgs;
+
+static CPLErr GTIFF_CopyBlockFromJPEG(GTIFF_CopyBlockFromJPEGArgs* psArgs)
+{
+    CPLString osTmpFilename(CPLSPrintf("/vsimem/%p", psArgs->psDInfo));
     VSILFILE* fpMEM = VSIFOpenL(osTmpFilename, "wb+");
 
 /* -------------------------------------------------------------------- */
 /*      Initialization of the compressor                                */
 /* -------------------------------------------------------------------- */
-    struct jpeg_error_mgr sJErr;
-    struct jpeg_compress_struct sCInfo;
     jmp_buf setjmp_buffer;
     if (setjmp(setjmp_buffer))
     {
-        VSIFCloseL(fpMEM);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpMEM));
         VSIUnlink(osTmpFilename);
         return CE_Failure;
     }
 
+    TIFF* hTIFF = psArgs->hTIFF;
+    jpeg_decompress_struct* psDInfo = psArgs->psDInfo;
+    const int iX = psArgs->iX;
+    const int iY = psArgs->iY;
+    const int nXBlocks = psArgs->nXBlocks;
+    const int nXSize = psArgs->nXSize;
+    const int nYSize = psArgs->nYSize;
+    const int nBlockXSize = psArgs->nBlockXSize;
+    const int nBlockYSize = psArgs->nBlockYSize;
+    const int iMCU_sample_width = psArgs->iMCU_sample_width;
+    const int iMCU_sample_height = psArgs->iMCU_sample_height;
+    jvirt_barray_ptr *pSrcCoeffs = psArgs->pSrcCoeffs;
+
+    struct jpeg_error_mgr sJErr;
+    struct jpeg_compress_struct sCInfo;
     sCInfo.err = jpeg_std_error( &sJErr );
     sJErr.error_exit = GTIFF_ErrorExitJPEG;
     sCInfo.client_data = (void *) &setjmp_buffer;
 
     /* Initialize destination compression parameters from source values */
     jpeg_create_compress(&sCInfo);
-    jpeg_copy_critical_parameters(&sDInfo, &sCInfo);
+    jpeg_copy_critical_parameters(psDInfo, &sCInfo);
 
     /* ensure libjpeg won't write any extraneous markers */
     sCInfo.write_JFIF_header = FALSE;
@@ -618,8 +646,8 @@ static CPLErr GTIFF_CopyBlockFromJPEG(TIFF* hTIFF,
         jpeg_component_info *compptr = sCInfo.comp_info + ci;
         int x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
         int y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
-        JDIMENSION nSrcWidthInBlocks = sDInfo.comp_info[ci].width_in_blocks;
-        JDIMENSION nSrcHeightInBlocks = sDInfo.comp_info[ci].height_in_blocks;
+        JDIMENSION nSrcWidthInBlocks = psDInfo->comp_info[ci].width_in_blocks;
+        JDIMENSION nSrcHeightInBlocks = psDInfo->comp_info[ci].height_in_blocks;
 
         JDIMENSION nXBlocksToCopy = compptr->width_in_blocks;
         if (x_crop_blocks + compptr->width_in_blocks > nSrcWidthInBlocks)
@@ -629,22 +657,21 @@ static CPLErr GTIFF_CopyBlockFromJPEG(TIFF* hTIFF,
                         dst_blk_y < compptr->height_in_blocks;
                         dst_blk_y += compptr->v_samp_factor)
         {
-            JBLOCKARRAY dst_buffer = (*sDInfo.mem->access_virt_barray)
-                            ((j_common_ptr) &sDInfo, pDstCoeffs[ci],
+            JBLOCKARRAY dst_buffer = (*psDInfo->mem->access_virt_barray)
+                            ((j_common_ptr) psDInfo, pDstCoeffs[ci],
                                 dst_blk_y,
                                 (JDIMENSION) compptr->v_samp_factor, TRUE);
 
             int offset_y = 0;
-            int nYBlocks = compptr->v_samp_factor;
             if( bIsTiled &&
                 dst_blk_y + y_crop_blocks + compptr->v_samp_factor >
                                                         nSrcHeightInBlocks)
             {
-                nYBlocks = nSrcHeightInBlocks - (dst_blk_y + y_crop_blocks);
+                int nYBlocks = nSrcHeightInBlocks - (dst_blk_y + y_crop_blocks);
                 if (nYBlocks > 0)
                 {
-                    JBLOCKARRAY src_buffer = (*sDInfo.mem->access_virt_barray)
-                                ((j_common_ptr) &sDInfo, pSrcCoeffs[ci],
+                    JBLOCKARRAY src_buffer = (*psDInfo->mem->access_virt_barray)
+                                ((j_common_ptr) psDInfo, pSrcCoeffs[ci],
                                 dst_blk_y + y_crop_blocks,
                                     (JDIMENSION) 1, FALSE);
                     for (; offset_y < nYBlocks; offset_y++)
@@ -669,8 +696,8 @@ static CPLErr GTIFF_CopyBlockFromJPEG(TIFF* hTIFF,
             }
             else
             {
-                JBLOCKARRAY src_buffer = (*sDInfo.mem->access_virt_barray)
-                                ((j_common_ptr) &sDInfo, pSrcCoeffs[ci],
+                JBLOCKARRAY src_buffer = (*psDInfo->mem->access_virt_barray)
+                                ((j_common_ptr) psDInfo, pSrcCoeffs[ci],
                                 dst_blk_y + y_crop_blocks,
                                 (JDIMENSION) compptr->v_samp_factor, FALSE);
                 for (; offset_y < compptr->v_samp_factor; offset_y++)
@@ -692,7 +719,7 @@ static CPLErr GTIFF_CopyBlockFromJPEG(TIFF* hTIFF,
     jpeg_finish_compress(&sCInfo);
     jpeg_destroy_compress(&sCInfo);
 
-    VSIFCloseL(fpMEM);
+    CPL_IGNORE_RET_VAL( VSIFCloseL(fpMEM) );
 
 /* -------------------------------------------------------------------- */
 /*      Write the JPEG content with libtiff raw API                     */
@@ -705,13 +732,13 @@ static CPLErr GTIFF_CopyBlockFromJPEG(TIFF* hTIFF,
     if ( bIsTiled )
     {
         if ((vsi_l_offset)TIFFWriteRawTile(hTIFF, iX + iY * nXBlocks,
-                                           pabyJPEGData, nSize) != nSize)
+                                           pabyJPEGData, static_cast<tmsize_t>(nSize)) != nSize)
             eErr = CE_Failure;
     }
     else
     {
         if ((vsi_l_offset)TIFFWriteRawStrip(hTIFF, iX + iY * nXBlocks,
-                                            pabyJPEGData, nSize) != nSize)
+                                            pabyJPEGData, static_cast<tmsize_t>(nSize)) != nSize)
             eErr = CE_Failure;
     }
 
@@ -749,7 +776,7 @@ CPLErr GTIFF_CopyFromJPEG(GDALDataset* poDS, GDALDataset* poSrcDS,
     jmp_buf setjmp_buffer;
     if (setjmp(setjmp_buffer))
     {
-        VSIFCloseL(fpJPEG);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpJPEG));
         jpeg_destroy_decompress(&sDInfo);
         return CE_Failure;
     }
@@ -843,15 +870,21 @@ CPLErr GTIFF_CopyFromJPEG(GDALDataset* poDS, GDALDataset* poSrcDS,
     {
         for(int iX=0;iX<nXBlocks && eErr == CE_None;iX++)
         {
-            eErr = GTIFF_CopyBlockFromJPEG( hTIFF,
-                                            sDInfo,
-                                            iX, iY,
-                                            nXBlocks, nYBlocks,
-                                            nXSize, nYSize,
-                                            nBlockXSize, nBlockYSize,
-                                            iMCU_sample_width,
-                                            iMCU_sample_height,
-                                            pSrcCoeffs );
+            GTIFF_CopyBlockFromJPEGArgs sArgs;
+            sArgs.hTIFF = hTIFF;
+            sArgs.psDInfo = &sDInfo;
+            sArgs.iX = iX;
+            sArgs.iY = iY;
+            sArgs.nXBlocks = nXBlocks;
+            sArgs.nXSize = nXSize;
+            sArgs.nYSize = nYSize;
+            sArgs.nBlockXSize = nBlockXSize;
+            sArgs.nBlockYSize = nBlockYSize;
+            sArgs.iMCU_sample_width = iMCU_sample_width;
+            sArgs.iMCU_sample_height = iMCU_sample_height;
+            sArgs.pSrcCoeffs = pSrcCoeffs;
+
+            eErr = GTIFF_CopyBlockFromJPEG( &sArgs );
 
             if (!pfnProgress((iY * nXBlocks + iX + 1) * 1.0 /
                                 (nXBlocks * nYBlocks),
@@ -867,7 +900,8 @@ CPLErr GTIFF_CopyFromJPEG(GDALDataset* poDS, GDALDataset* poSrcDS,
     jpeg_finish_decompress( &sDInfo );
     jpeg_destroy_decompress( &sDInfo );
 
-    VSIFCloseL(fpJPEG);
+    if( VSIFCloseL(fpJPEG) != 0 )
+        eErr = CE_Failure;
 
     return eErr;
 }
diff --git a/frmts/gtiff/gt_jpeg_copy.h b/frmts/gtiff/gt_jpeg_copy.h
index 053dd0f..513f101 100644
--- a/frmts/gtiff/gt_jpeg_copy.h
+++ b/frmts/gtiff/gt_jpeg_copy.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gt_jpeg_copy.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: gt_jpeg_copy.h 33806 2016-03-28 22:26:19Z goatbar $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Specialized copy of JPEG content into TIFF.
@@ -30,10 +30,11 @@
 #ifndef GT_JPEG_COPY_H_INCLUDED
 #define GT_JPEG_COPY_H_INCLUDED
 
-#ifdef JPEG_DIRECT_COPY
-
-#include "gdal_priv.h"
+#include "cpl_error.h"
 #include "cpl_vsi.h"
+#include "gdal_priv.h"
+
+#ifdef JPEG_DIRECT_COPY
 
 int GTIFF_CanDirectCopyFromJPEG(GDALDataset* poSrcDS, char** &papszCreateOptions);
 
@@ -45,8 +46,6 @@ CPLErr GTIFF_DirectCopyFromJPEG(GDALDataset* poDS, GDALDataset* poSrcDS,
 
 #ifdef HAVE_LIBJPEG
 
-#include "gdal_priv.h"
-#include "cpl_error.h"
 #include "tiffio.h"
 
 int GTIFF_CanCopyFromJPEG(GDALDataset* poSrcDS, char** &papszCreateOptions);
diff --git a/frmts/gtiff/gt_overview.cpp b/frmts/gtiff/gt_overview.cpp
index fc845bf..576b5a8 100644
--- a/frmts/gtiff/gt_overview.cpp
+++ b/frmts/gtiff/gt_overview.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: gt_overview.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: gt_overview.cpp 33806 2016-03-28 22:26:19Z goatbar $
  *
  * Project:  GeoTIFF Driver
- * Purpose:  Code to build overviews of external databases as a TIFF file. 
+ * Purpose:  Code to build overviews of external databases as a TIFF file.
  *           Only used by the GDALDefaultOverviews::BuildOverviews() method.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -30,14 +30,12 @@
  ****************************************************************************/
 
 #include "gdal_priv.h"
-#define CPL_SERV_H_INCLUDED
-
-#include "tifvsi.h"
-#include "xtiffio.h"
 #include "gt_overview.h"
 #include "gtiff.h"
+#include "tifvsi.h"
+#include "xtiffio.h"
 
-CPL_CVSID("$Id: gt_overview.cpp 28053 2014-12-04 09:31:07Z rouault $");
+CPL_CVSID("$Id: gt_overview.cpp 33806 2016-03-28 22:26:19Z goatbar $");
 
 /************************************************************************/
 /*                         GTIFFWriteDirectory()                        */
@@ -50,10 +48,10 @@ CPL_CVSID("$Id: gt_overview.cpp 28053 2014-12-04 09:31:07Z rouault $");
 /************************************************************************/
 
 toff_t GTIFFWriteDirectory(TIFF *hTIFF, int nSubfileType, int nXSize, int nYSize,
-                           int nBitsPerPixel, int nPlanarConfig, int nSamples, 
+                           int nBitsPerPixel, int nPlanarConfig, int nSamples,
                            int nBlockXSize, int nBlockYSize,
                            int bTiled, int nCompressFlag, int nPhotometric,
-                           int nSampleFormat, 
+                           int nSampleFormat,
                            int nPredictor,
                            unsigned short *panRed,
                            unsigned short *panGreen,
@@ -63,17 +61,21 @@ toff_t GTIFFWriteDirectory(TIFF *hTIFF, int nSubfileType, int nXSize, int nYSize
                            const char *pszMetadata )
 
 {
-    toff_t	nBaseDirOffset;
-    toff_t	nOffset;
+    toff_t nBaseDirOffset;
+    toff_t nOffset;
 
     nBaseDirOffset = TIFFCurrentDirOffset( hTIFF );
 
+    /* This is a bit of a hack to cause (*tif->tif_cleanup)(tif); to be called */
+    /* See https://trac.osgeo.org/gdal/ticket/2055 */
+    TIFFSetField( hTIFF, TIFFTAG_COMPRESSION, COMPRESSION_NONE );
+
 #if defined(TIFFLIB_VERSION) && TIFFLIB_VERSION >= 20051201 /* 3.8.0 */
     TIFFFreeDirectory( hTIFF );
 #endif
 
     TIFFCreateDirectory( hTIFF );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Setup TIFF fields.                                              */
 /* -------------------------------------------------------------------- */
@@ -110,7 +112,7 @@ toff_t GTIFFWriteDirectory(TIFF *hTIFF, int nSubfileType, int nXSize, int nYSize
         TIFFSetField( hTIFF, TIFFTAG_PREDICTOR, nPredictor );
 
 /* -------------------------------------------------------------------- */
-/*	Write color table if one is present.				*/
+/*      Write color table if one is present.                            */
 /* -------------------------------------------------------------------- */
     if( panRed != NULL )
     {
@@ -147,13 +149,13 @@ toff_t GTIFFWriteDirectory(TIFF *hTIFF, int nSubfileType, int nXSize, int nYSize
 /************************************************************************/
 
 void GTIFFBuildOverviewMetadata( const char *pszResampling,
-                                 GDALDataset *poBaseDS, 
+                                 GDALDataset *poBaseDS,
                                  CPLString &osMetadata )
 
 {
     osMetadata = "<GDALMetadata>";
 
-    if( pszResampling && EQUALN(pszResampling,"AVERAGE_BIT2",12) )
+    if( pszResampling && STARTS_WITH_CI(pszResampling, "AVERAGE_BIT2") )
         osMetadata += "<Item name=\"RESAMPLING\" sample=\"0\">AVERAGE_BIT2GRAYSCALE</Item>";
 
     if( poBaseDS->GetMetadataItem( "INTERNAL_MASK_FLAGS_1" ) )
@@ -168,8 +170,8 @@ void GTIFFBuildOverviewMetadata( const char *pszResampling,
             osName.Printf( "INTERNAL_MASK_FLAGS_%d", iBand+1 );
             if( poBaseDS->GetMetadataItem( osName ) )
             {
-                osItem.Printf( "<Item name=\"%s\">%s</Item>", 
-                               osName.c_str(), 
+                osItem.Printf( "<Item name=\"%s\">%s</Item>",
+                               osName.c_str(),
                                poBaseDS->GetMetadataItem( osName ) );
                 osMetadata += osItem;
             }
@@ -194,11 +196,11 @@ void GTIFFBuildOverviewMetadata( const char *pszResampling,
 /*                        GTIFFBuildOverviews()                         */
 /************************************************************************/
 
-CPLErr 
+CPLErr
 GTIFFBuildOverviews( const char * pszFilename,
-                     int nBands, GDALRasterBand **papoBandList, 
+                     int nBands, GDALRasterBand **papoBandList,
                      int nOverviews, int * panOverviewList,
-                     const char * pszResampling, 
+                     const char * pszResampling,
                      GDALProgressFunc pfnProgress, void * pProgressData )
 
 {
@@ -286,11 +288,11 @@ GTIFFBuildOverviews( const char * pszFilename,
 
         if( hBand->GetMetadataItem( "NBITS", "IMAGE_STRUCTURE" ) )
         {
-            nBandBits = 
+            nBandBits =
                 atoi(hBand->GetMetadataItem("NBITS","IMAGE_STRUCTURE"));
 
-            if( nBandBits == 1 
-                && EQUALN(pszResampling,"AVERAGE_BIT2",12) )
+            if( nBandBits == 1
+                && STARTS_WITH_CI(pszResampling, "AVERAGE_BIT2") )
                 nBandBits = 8;
         }
 
@@ -303,22 +305,22 @@ GTIFFBuildOverviews( const char * pszFilename,
         }
         else if( nBitsPerPixel != nBandBits || nSampleFormat != nBandFormat )
         {
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                       "GTIFFBuildOverviews() doesn't support a mixture of band"
                       " data types." );
             return CE_Failure;
         }
         else if( hBand->GetColorTable() != NULL )
         {
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                       "GTIFFBuildOverviews() doesn't support building"
                       " overviews of multiple colormapped bands." );
             return CE_Failure;
         }
-        else if( hBand->GetXSize() != nXSize 
+        else if( hBand->GetXSize() != nXSize
                  || hBand->GetYSize() != nYSize )
         {
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                       "GTIFFBuildOverviews() doesn't support building"
                       " overviews of different sized bands." );
             return CE_Failure;
@@ -336,12 +338,12 @@ GTIFFBuildOverviews( const char * pszFilename,
         if (nCompression < 0)
             return CE_Failure;
     }
-    
+
     if( nCompression == COMPRESSION_JPEG && nBitsPerPixel > 8 )
-    {  
+    {
         if( nBitsPerPixel > 16 )
         {
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                       "GTIFFBuildOverviews() doesn't support building"
                       " JPEG compressed overviews of nBitsPerPixel > 16." );
             return CE_Failure;
@@ -367,7 +369,7 @@ GTIFFBuildOverviews( const char * pszFilename,
             nPlanarConfig = PLANARCONFIG_SEPARATE;
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "INTERLEAVE_OVERVIEW=%s unsupported, value must be PIXEL or BAND. ignoring",
                       pszInterleave );
         }
@@ -378,8 +380,8 @@ GTIFFBuildOverviews( const char * pszFilename,
 /* -------------------------------------------------------------------- */
     if( nBands == 3 )
         nPhotometric = PHOTOMETRIC_RGB;
-    else if( papoBandList[0]->GetColorTable() != NULL 
-             && !EQUALN(pszResampling,"AVERAGE_BIT2",12) )
+    else if( papoBandList[0]->GetColorTable() != NULL
+             && !STARTS_WITH_CI(pszResampling, "AVERAGE_BIT2") )
     {
         nPhotometric = PHOTOMETRIC_PALETTE;
         /* should set the colormap up at this point too! */
@@ -452,7 +454,7 @@ GTIFFBuildOverviews( const char * pszFilename,
         }
         else
         {
-            CPLError( CE_Warning, CPLE_IllegalArg, 
+            CPLError( CE_Warning, CPLE_IllegalArg,
                       "PHOTOMETRIC_OVERVIEW=%s value not recognised, ignoring.\n",
                       pszPhotometric );
         }
@@ -490,20 +492,20 @@ GTIFFBuildOverviews( const char * pszFilename,
         {
             int    nOXSize, nOYSize;
 
-            nOXSize = (nXSize + panOverviewList[iOverview] - 1) 
+            nOXSize = (nXSize + panOverviewList[iOverview] - 1)
                 / panOverviewList[iOverview];
-            nOYSize = (nYSize + panOverviewList[iOverview] - 1) 
+            nOYSize = (nYSize + panOverviewList[iOverview] - 1)
                 / panOverviewList[iOverview];
 
-            dfUncompressedOverviewSize += 
+            dfUncompressedOverviewSize +=
                 nOXSize * ((double)nOYSize) * nBands * nDataTypeSize;
         }
 
-        if( nCompression == COMPRESSION_NONE 
+        if( nCompression == COMPRESSION_NONE
             && dfUncompressedOverviewSize > 4200000000.0 )
         {
     #ifndef BIGTIFF_SUPPORT
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                     "The overview file would be larger than 4GB\n"
                     "but this is the largest size a TIFF can be, and BigTIFF is unavailable.\n"
                     "Creation failed." );
@@ -521,7 +523,7 @@ GTIFFBuildOverviews( const char * pszFilename,
         int bCreateBigTIFF = FALSE;
         if( EQUAL(pszBIGTIFF,"IF_NEEDED") )
         {
-            if( nCompression == COMPRESSION_NONE 
+            if( nCompression == COMPRESSION_NONE
                 && dfUncompressedOverviewSize > 4200000000.0 )
                 bCreateBigTIFF = TRUE;
         }
@@ -539,11 +541,11 @@ GTIFFBuildOverviews( const char * pszFilename,
         }
         else
         {
-            bCreateBigTIFF = CSLTestBoolean( pszBIGTIFF );
-            if (!bCreateBigTIFF && nCompression == COMPRESSION_NONE 
+            bCreateBigTIFF = CPLTestBool( pszBIGTIFF );
+            if (!bCreateBigTIFF && nCompression == COMPRESSION_NONE
                 && dfUncompressedOverviewSize > 4200000000.0 )
             {
-                CPLError( CE_Failure, CPLE_NotSupported, 
+                CPLError( CE_Failure, CPLE_NotSupported,
                     "The overview file will be larger than 4GB, so BigTIFF is necessary.\n"
                     "Creation failed.");
                 return CE_Failure;
@@ -576,14 +578,14 @@ GTIFFBuildOverviews( const char * pszFilename,
                           "failed in VSI_TIFFOpen().\n",
                           pszFilename );
             if( fpL != NULL )
-                VSIFCloseL(fpL);
+                CPL_IGNORE_RET_VAL(VSIFCloseL(fpL));
             return CE_Failure;
         }
     }
 /* -------------------------------------------------------------------- */
 /*      Otherwise just open it for update access.                       */
 /* -------------------------------------------------------------------- */
-    else 
+    else
     {
         fpL = VSIFOpenL( pszFilename, "r+" );
         if( fpL == NULL )
@@ -598,7 +600,7 @@ GTIFFBuildOverviews( const char * pszFilename,
                           "failed in VSI_TIFFOpen().\n",
                           pszFilename );
             if( fpL != NULL )
-                VSIFCloseL(fpL);
+                CPL_IGNORE_RET_VAL(VSIFCloseL(fpL));
             return CE_Failure;
         }
     }
@@ -618,11 +620,11 @@ GTIFFBuildOverviews( const char * pszFilename,
         else
             nColorCount = 65536;
 
-        panRed   = (unsigned short *) 
+        panRed   = (unsigned short *)
             CPLCalloc(nColorCount,sizeof(unsigned short));
-        panGreen = (unsigned short *) 
+        panGreen = (unsigned short *)
             CPLCalloc(nColorCount,sizeof(unsigned short));
-        panBlue  = (unsigned short *) 
+        panBlue  = (unsigned short *)
             CPLCalloc(nColorCount,sizeof(unsigned short));
 
         for( int iColor = 0; iColor < nColorCount; iColor++ )
@@ -655,13 +657,13 @@ GTIFFBuildOverviews( const char * pszFilename,
     {
         int    nOXSize, nOYSize;
 
-        nOXSize = (nXSize + panOverviewList[iOverview] - 1) 
+        nOXSize = (nXSize + panOverviewList[iOverview] - 1)
             / panOverviewList[iOverview];
-        nOYSize = (nYSize + panOverviewList[iOverview] - 1) 
+        nOYSize = (nYSize + panOverviewList[iOverview] - 1)
             / panOverviewList[iOverview];
 
         GTIFFWriteDirectory(hOTIFF, FILETYPE_REDUCEDIMAGE,
-                            nOXSize, nOYSize, nBitsPerPixel, 
+                            nOXSize, nOYSize, nBitsPerPixel,
                             nPlanarConfig, nBands,
                             nOvrBlockXSize, nOvrBlockYSize, TRUE, nCompression,
                             nPhotometric, nSampleFormat, nPredictor,
@@ -679,7 +681,8 @@ GTIFFBuildOverviews( const char * pszFilename,
     }
 
     XTIFFClose( hOTIFF );
-    VSIFCloseL(fpL);
+    if (VSIFCloseL(fpL) != 0 )
+        return CE_Failure;
     fpL = NULL;
 
 /* -------------------------------------------------------------------- */
@@ -692,17 +695,17 @@ GTIFFBuildOverviews( const char * pszFilename,
     hODS = (GDALDataset *) GDALOpen( pszFilename, GA_Update );
     if( hODS == NULL )
         return CE_Failure;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Do we need to set the jpeg quality?                             */
 /* -------------------------------------------------------------------- */
     TIFF *hTIFF = (TIFF*) hODS->GetInternalHandle(NULL);
 
-    if( nCompression == COMPRESSION_JPEG 
+    if( nCompression == COMPRESSION_JPEG
         && CPLGetConfigOption( "JPEG_QUALITY_OVERVIEW", NULL ) != NULL )
     {
         int nJpegQuality = atoi(CPLGetConfigOption("JPEG_QUALITY_OVERVIEW","75"));
-        TIFFSetField( hTIFF, TIFFTAG_JPEGQUALITY, 
+        TIFFSetField( hTIFF, TIFFTAG_JPEGQUALITY,
                       nJpegQuality );
         GTIFFSetJpegQuality((GDALDatasetH)hODS, nJpegQuality);
     }
@@ -711,11 +714,13 @@ GTIFFBuildOverviews( const char * pszFilename,
 /*      Loop writing overview data.                                     */
 /* -------------------------------------------------------------------- */
 
+    GTIFFSetInExternalOvr(true);
+
     if (nCompression != COMPRESSION_NONE &&
         nPlanarConfig == PLANARCONFIG_CONTIG &&
         GDALDataTypeIsComplex(papoBandList[0]->GetRasterDataType()) == FALSE &&
         papoBandList[0]->GetColorTable() == NULL &&
-        (EQUALN(pszResampling, "NEAR", 4) || EQUAL(pszResampling, "AVERAGE") ||
+        (STARTS_WITH_CI(pszResampling, "NEAR") || EQUAL(pszResampling, "AVERAGE") ||
          EQUAL(pszResampling, "GAUSS") || EQUAL(pszResampling, "CUBIC") ||
          EQUAL(pszResampling, "CUBICSPLINE") || EQUAL(pszResampling, "LANCZOS") ||
          EQUAL(pszResampling, "BILINEAR")))
@@ -800,18 +805,18 @@ GTIFFBuildOverviews( const char * pszFilename,
 
             void         *pScaledProgressData;
 
-            pScaledProgressData = 
-                GDALCreateScaledProgress( iBand / (double) nBands, 
+            pScaledProgressData =
+                GDALCreateScaledProgress( iBand / (double) nBands,
                                         (iBand+1) / (double) nBands,
                                         pfnProgress, pProgressData );
 
             if (eErr == CE_None)
-                eErr = 
-                    GDALRegenerateOverviews( (GDALRasterBandH) hSrcBand, 
-                                        nDstOverviews, 
-                                        (GDALRasterBandH *) papoOverviews, 
+                eErr =
+                    GDALRegenerateOverviews( (GDALRasterBandH) hSrcBand,
+                                        nDstOverviews,
+                                        (GDALRasterBandH *) papoOverviews,
                                         pszResampling,
-                                        GDALScaledProgress, 
+                                        GDALScaledProgress,
                                         pScaledProgressData);
 
             GDALDestroyScaledProgress( pScaledProgressData );
@@ -827,8 +832,9 @@ GTIFFBuildOverviews( const char * pszFilename,
         hODS->FlushCache();
     delete hODS;
 
+    GTIFFSetInExternalOvr(false);
+
     pfnProgress( 1.0, NULL, pProgressData );
 
     return eErr;
 }
-    
diff --git a/frmts/gtiff/gt_overview.h b/frmts/gtiff/gt_overview.h
index 1843162..ffa62a0 100644
--- a/frmts/gtiff/gt_overview.h
+++ b/frmts/gtiff/gt_overview.h
@@ -2,7 +2,7 @@
  * $Id: gt_overview.h 13297 2007-12-09 19:03:50Z rouault $
  *
  * Project:  GeoTIFF Driver
- * Purpose:  Code to build overviews of external databases as a TIFF file. 
+ * Purpose:  Code to build overviews of external databases as a TIFF file.
  *           Only used by the GDALDefaultOverviews::BuildOverviews() method.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -36,10 +36,10 @@
 #include "tiffio.h"
 
 toff_t GTIFFWriteDirectory(TIFF *hTIFF, int nSubfileType, int nXSize, int nYSize,
-                           int nBitsPerPixel, int nPlanarConfig, int nSamples, 
+                           int nBitsPerPixel, int nPlanarConfig, int nSamples,
                            int nBlockXSize, int nBlockYSize,
                            int bTiled, int nCompressFlag, int nPhotometric,
-                           int nSampleFormat, 
+                           int nSampleFormat,
                            int nPredictor,
                            unsigned short *panRed,
                            unsigned short *panGreen,
@@ -49,7 +49,7 @@ toff_t GTIFFWriteDirectory(TIFF *hTIFF, int nSubfileType, int nXSize, int nYSize
                            const char *pszMetadata );
 
 void GTIFFBuildOverviewMetadata( const char *pszResampling,
-                                 GDALDataset *poBaseDS, 
+                                 GDALDataset *poBaseDS,
                                  CPLString &osMetadata );
 
 #endif
diff --git a/frmts/gtiff/gt_wkt_srs.cpp b/frmts/gtiff/gt_wkt_srs.cpp
index 8d6feee..5d1081d 100644
--- a/frmts/gtiff/gt_wkt_srs.cpp
+++ b/frmts/gtiff/gt_wkt_srs.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gt_wkt_srs.cpp 31128 2015-10-25 18:07:26Z rouault $
+ * $Id: gt_wkt_srs.cpp 33806 2016-03-28 22:26:19Z goatbar $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Implements translation between GeoTIFF normalized projection
@@ -32,21 +32,20 @@
 #include "cpl_error.h"
 #include "cpl_conv.h"
 #include "cpl_csv.h"
+#include "cpl_multiproc.h"
+#include "gdal.h"
 #include "gdal_csv.h"
-
 #include "geovalues.h"
-#include "ogr_spatialref.h"
-#include "gdal.h"
-#include "xtiffio.h"
-#include "cpl_multiproc.h"
-#include "tifvsi.h"
+#include "gt_citation.h"
 #include "gt_wkt_srs.h"
 #include "gt_wkt_srs_for_gdal.h"
-#include "gt_citation.h"
 #include "gt_wkt_srs_priv.h"
 #include "gtiff.h"
+#include "ogr_spatialref.h"
+#include "tifvsi.h"
+#include "xtiffio.h"
 
-CPL_CVSID("$Id: gt_wkt_srs.cpp 31128 2015-10-25 18:07:26Z rouault $")
+CPL_CVSID("$Id: gt_wkt_srs.cpp 33806 2016-03-28 22:26:19Z goatbar $")
 
 #define ProjLinearUnitsInterpCorrectGeoKey   3059
 
@@ -68,7 +67,7 @@ CPL_C_END
 // To remind myself not to use CPLString in this file!
 #define CPLString Please_do_not_use_CPLString_in_this_file
 
-static const char *papszDatumEquiv[] =
+static const char * const papszDatumEquiv[] =
 {
     "Militar_Geographische_Institut",
     "Militar_Geographische_Institute",
@@ -94,7 +93,7 @@ static const char *papszDatumEquiv[] =
 
 static CPLMutex* hMutex = NULL;
 
-void LibgeotiffOneTimeInit() 
+void LibgeotiffOneTimeInit()
 {
     static int bOneTimeInitDone = FALSE;
     CPLMutexHolder oHolder( &hMutex);
@@ -116,7 +115,7 @@ void LibgeotiffOneTimeInit()
 /*                   LibgeotiffOneTimeCleanupMutex()                    */
 /************************************************************************/
 
-void LibgeotiffOneTimeCleanupMutex() 
+void LibgeotiffOneTimeCleanupMutex()
 {
     if( hMutex != NULL )
     {
@@ -153,8 +152,8 @@ static void GTIFToCPLRecycleString( char **ppszTarget )
 static void WKTMassageDatum( char ** ppszDatum )
 
 {
-    int		i, j;
-    char	*pszDatum;
+    int i, j;
+    char *pszDatum;
 
     pszDatum = *ppszDatum;
     if (pszDatum[0] == '\0')
@@ -188,9 +187,9 @@ static void WKTMassageDatum( char ** ppszDatum )
         pszDatum[j] = '\0';
     else
         pszDatum[j+1] = '\0';
-    
+
 /* -------------------------------------------------------------------- */
-/*      Search for datum equivelences.  Specific massaged names get     */
+/*      Search for datum equivalences.  Specific massaged names get     */
 /*      mapped to OpenGIS specified names.                              */
 /* -------------------------------------------------------------------- */
     for( i = 0; papszDatumEquiv[i] != NULL; i += 2 )
@@ -214,12 +213,11 @@ static void WKTMassageDatum( char ** ppszDatum )
 /************************************************************************/
 
 /* For example:
-   GTCitationGeoKey (Ascii,215): "IMAGINE GeoTIFF Support\nCopyright 1991 - 2001 by ERDAS, Inc. All Rights Reserved\n@(#)$RCSfile$ $Revision: 31128 $ $Date: 2015-10-25 11:07:26 -0700 (Sun, 25 Oct 2015) $\nProjection Name = UTM\nUnits = meters\nGeoTIFF Units = meters"
+   GTCitationGeoKey (Ascii,215): "IMAGINE GeoTIFF Support\nCopyright 1991 - 2001 by ERDAS, Inc. All Rights Reserved\n@(#)$RCSfile$ $Revision: 33806 $ $Date: 2016-03-28 15:26:19 -0700 (Mon, 28 Mar 2016) $\nProjection Name = UTM\nUnits = meters\nGeoTIFF Units = meters"
 
-   GeogCitationGeoKey (Ascii,267): "IMAGINE GeoTIFF Support\nCopyright 1991 - 2001 by ERDAS, Inc. All Rights Reserved\n@(#)$RCSfile$ $Revision: 31128 $ $Date: 2015-10-25 11:07:26 -0700 (Sun, 25 Oct 2015) $\nUnable to match Ellipsoid (Datum) to a GeographicTypeGeoKey value\nEllipsoid = Clarke 1866\nDatum = NAD27 (CONUS)"
+   GeogCitationGeoKey (Ascii,267): "IMAGINE GeoTIFF Support\nCopyright 1991 - 2001 by ERDAS, Inc. All Rights Reserved\n@(#)$RCSfile$ $Revision: 33806 $ $Date: 2016-03-28 15:26:19 -0700 (Mon, 28 Mar 2016) $\nUnable to match Ellipsoid (Datum) to a GeographicTypeGeoKey value\nEllipsoid = Clarke 1866\nDatum = NAD27 (CONUS)"
 
-   PCSCitationGeoKey (Ascii,214): "IMAGINE GeoTIFF Support\nCopyright 1991 - 2001 by ERDAS, Inc. All Rights Reserved\n@(#)$RCSfile$ $Revision: 31128 $ $Date: 2015-10-25 11:07:26 -0700 (Sun, 25 Oct 2015) $\nUTM Zone 10N\nEllipsoid = Clarke 1866\nDatum = NAD27 (CONUS)"
- 
+   PCSCitationGeoKey (Ascii,214): "IMAGINE GeoTIFF Support\nCopyright 1991 - 2001 by ERDAS, Inc. All Rights Reserved\n@(#)$RCSfile$ $Revision: 33806 $ $Date: 2016-03-28 15:26:19 -0700 (Mon, 28 Mar 2016) $\nUTM Zone 10N\nEllipsoid = Clarke 1866\nDatum = NAD27 (CONUS)"
 */
 
 static void GTIFCleanupImagineNames( char *pszCitation )
@@ -233,9 +231,9 @@ static void GTIFCleanupImagineNames( char *pszCitation )
 /*      assume that this will have a "$" at the end of it all.          */
 /* -------------------------------------------------------------------- */
     char *pszSkip;
-    
+
     for( pszSkip = pszCitation + strlen(pszCitation) - 1;
-         pszSkip != pszCitation && *pszSkip != '$'; 
+         pszSkip != pszCitation && *pszSkip != '$';
          pszSkip-- ) {}
 
     if( *pszSkip == '$' )
@@ -323,7 +321,7 @@ int GDALGTIFKeyGetDOUBLE( GTIF *hGTIF, geokey_t key,
 char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
 
 {
-    OGRSpatialReference	oSRS;
+    OGRSpatialReference oSRS;
 
 /* -------------------------------------------------------------------- */
 /*      Make sure we have hooked CSVFilename().                         */
@@ -342,11 +340,11 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
 /* -------------------------------------------------------------------- */
 /*      Handle non-standard coordinate systems as LOCAL_CS.             */
 /* -------------------------------------------------------------------- */
-    if( psDefn->Model != ModelTypeProjected 
-        && psDefn->Model != ModelTypeGeographic 
+    if( psDefn->Model != ModelTypeProjected
+        && psDefn->Model != ModelTypeGeographic
         && psDefn->Model != ModelTypeGeocentric )
     {
-        char	*pszWKT;
+        char *pszWKT;
         char    szPeStr[2400];
 
         /** check if there is a pe string citation key **/
@@ -358,8 +356,8 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
             if( strstr(pszWKT, "PROJCS[\"WGS_1984_Web_Mercator_Auxiliary_Sphere\"") )
             {
                 oSRS.SetFromUserInput(pszWKT);
-                oSRS.SetExtension( "PROJCS", "PROJ4",  
-                                   "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext  +no_defs" ); 
+                oSRS.SetExtension( "PROJCS", "PROJ4",
+                                   "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext  +no_defs" );
                 oSRS.FixupOrdering();
                 CPLFree(pszWKT);
                 pszWKT = NULL;
@@ -370,7 +368,7 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
         }
         else
         {
-            char	*pszUnitsName = NULL;
+            char *pszUnitsName = NULL;
             char    szPCSName[300];
             int     nKeyCount = 0;
             int     anVersion[3];
@@ -382,9 +380,9 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
             {
                 // Handle citation.
                 strcpy( szPCSName, "unnamed" );
-                if( !GDALGTIFKeyGetASCII( hGTIF, GTCitationGeoKey, szPCSName, 
+                if( !GDALGTIFKeyGetASCII( hGTIF, GTCitationGeoKey, szPCSName,
                                  0, sizeof(szPCSName) ) )
-                    GDALGTIFKeyGetASCII( hGTIF, GeogCitationGeoKey, szPCSName, 
+                    GDALGTIFKeyGetASCII( hGTIF, GeogCitationGeoKey, szPCSName,
                                 0, sizeof(szPCSName) );
 
                 GTIFCleanupImagineNames( szPCSName );
@@ -392,7 +390,7 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
 
                 // Handle units
                 GTIFGetUOMLengthInfo( psDefn->UOMLength, &pszUnitsName, NULL );
-              
+
                 if( pszUnitsName != NULL && psDefn->UOMLength != KvUserDefined )
                 {
                     oSRS.SetLinearUnits( pszUnitsName, psDefn->UOMLengthInMeters );
@@ -417,17 +415,17 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
         char    szName[300];
 
         strcpy( szName, "unnamed" );
-        if( !GDALGTIFKeyGetASCII( hGTIF, GTCitationGeoKey, szName, 
+        if( !GDALGTIFKeyGetASCII( hGTIF, GTCitationGeoKey, szName,
                          0, sizeof(szName) ) )
-            GDALGTIFKeyGetASCII( hGTIF, GeogCitationGeoKey, szName, 
+            GDALGTIFKeyGetASCII( hGTIF, GeogCitationGeoKey, szName,
                         0, sizeof(szName) );
 
         oSRS.SetGeocCS( szName );
 
-        char	*pszUnitsName = NULL;
-          
+        char *pszUnitsName = NULL;
+
         GTIFGetUOMLengthInfo( psDefn->UOMLength, &pszUnitsName, NULL );
-        
+
         if( pszUnitsName != NULL && psDefn->UOMLength != KvUserDefined )
         {
             oSRS.SetLinearUnits( pszUnitsName, psDefn->UOMLengthInMeters );
@@ -438,7 +436,7 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
 
         GTIFFreeMemory( pszUnitsName );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      #3901: In libgeotiff 1.3.0 and earlier we incorrectly           */
 /*      interpreted linear projection parameter geokeys (false          */
@@ -448,7 +446,7 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
 /*      with an older version of libgeotiff.                            */
 /* -------------------------------------------------------------------- */
     int iParm;
-    const char *pszLinearUnits = 
+    const char *pszLinearUnits =
         CPLGetConfigOption( "GTIFF_LINEAR_UNITS", "DEFAULT" );
 
 #if LIBGEOTIFF_VERSION <= 1300
@@ -464,7 +462,7 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
               case ProjFalseOriginNorthingGeoKey:
               case ProjCenterEastingGeoKey:
               case ProjCenterNorthingGeoKey:
-                if( psDefn->UOMLengthInMeters != 0 
+                if( psDefn->UOMLengthInMeters != 0
                     && psDefn->UOMLengthInMeters != 1.0 )
                 {
                     psDefn->ProjParm[iParm] *= psDefn->UOMLengthInMeters;
@@ -488,12 +486,12 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
 /*      behavior.                                                       */
 /* -------------------------------------------------------------------- */
     short bLinearUnitsMarkedCorrect = FALSE;
-    
-    GDALGTIFKeyGetSHORT(hGTIF, (geokey_t) ProjLinearUnitsInterpCorrectGeoKey, 
+
+    GDALGTIFKeyGetSHORT(hGTIF, (geokey_t) ProjLinearUnitsInterpCorrectGeoKey,
                &bLinearUnitsMarkedCorrect, 0, 1);
 
-    if( EQUAL(pszLinearUnits,"BROKEN") 
-        && psDefn->Projection == KvUserDefined 
+    if( EQUAL(pszLinearUnits,"BROKEN")
+        && psDefn->Projection == KvUserDefined
         && !bLinearUnitsMarkedCorrect )
     {
         for( iParm = 0; iParm < psDefn->nParms; iParm++ )
@@ -506,7 +504,7 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
               case ProjFalseOriginNorthingGeoKey:
               case ProjCenterEastingGeoKey:
               case ProjCenterNorthingGeoKey:
-                if( psDefn->UOMLengthInMeters != 0 
+                if( psDefn->UOMLengthInMeters != 0
                     && psDefn->UOMLengthInMeters != 1.0 )
                 {
                     psDefn->ProjParm[iParm] /= psDefn->UOMLengthInMeters;
@@ -534,15 +532,15 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
             char    *pszPCSName = NULL;
 
             GTIFGetPCSInfo( psDefn->PCS, &pszPCSName, NULL, NULL, NULL );
-            
+
             oSRS.SetNode( "PROJCS", pszPCSName ? pszPCSName : "unnamed" );
             if ( pszPCSName )
                 GTIFFreeMemory( pszPCSName );
 
             oSRS.SetAuthority( "PROJCS", "EPSG", psDefn->PCS );
         }
-        else if(hGTIF && GDALGTIFKeyGetASCII( hGTIF, PCSCitationGeoKey, szCTString, 0, 
-                                     sizeof(szCTString)) )  
+        else if(hGTIF && GDALGTIFKeyGetASCII( hGTIF, PCSCitationGeoKey, szCTString, 0,
+                                     sizeof(szCTString)) )
         {
             if (!SetCitationToSRS(hGTIF, szCTString, sizeof(szCTString),
                                   PCSCitationGeoKey, &oSRS, &linearUnitIsSet))
@@ -564,7 +562,7 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
         /* Handle ESRI/Erdas style state plane and UTM in citation key */
         if( CheckCitationKeyForStatePlaneUTM(hGTIF, psDefn, &oSRS, &linearUnitIsSet) )
         {
-            char	*pszWKT;
+            char *pszWKT;
             oSRS.morphFromESRI();
             oSRS.FixupOrdering();
             if( oSRS.exportToWkt( &pszWKT ) == OGRERR_NONE )
@@ -576,33 +574,33 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
         if( hGTIF && GDALGTIFKeyGetASCII( hGTIF, GTCitationGeoKey, szCTString, 0, sizeof(szCTString) ) )
             SetCitationToSRS(hGTIF, szCTString, sizeof(szCTString), GTCitationGeoKey, &oSRS, &linearUnitIsSet);
     }
-    
+
 /* ==================================================================== */
 /*      Setup the GeogCS                                                */
 /* ==================================================================== */
-    char	*pszGeogName = NULL;
-    char	*pszDatumName = NULL;
-    char	*pszPMName = NULL;
-    char	*pszSpheroidName = NULL;
-    char	*pszAngularUnits = NULL;
-    double	dfInvFlattening=0.0, dfSemiMajor=0.0;
+    char *pszGeogName = NULL;
+    char *pszDatumName = NULL;
+    char *pszPMName = NULL;
+    char *pszSpheroidName = NULL;
+    char *pszAngularUnits = NULL;
+    double dfInvFlattening=0.0, dfSemiMajor=0.0;
     char  szGCSName[512];
     OGRBoolean aUnitGot = FALSE;
-    
+
     if( !GTIFGetGCSInfo( psDefn->GCS, &pszGeogName, NULL, NULL, NULL )
-        && hGTIF != NULL 
-        && GDALGTIFKeyGetASCII( hGTIF, GeogCitationGeoKey, szGCSName, 0, 
+        && hGTIF != NULL
+        && GDALGTIFKeyGetASCII( hGTIF, GeogCitationGeoKey, szGCSName, 0,
                        sizeof(szGCSName)) )
     {
         GetGeogCSFromCitation(szGCSName, sizeof(szGCSName),
-                              GeogCitationGeoKey, 
+                              GeogCitationGeoKey,
                               &pszGeogName, &pszDatumName,
                               &pszPMName, &pszSpheroidName,
                               &pszAngularUnits);
     }
     else
         GTIFToCPLRecycleString( &pszGeogName );
-        
+
     if( !pszDatumName )
     {
         GTIFGetDatumInfo( psDefn->Datum, &pszDatumName, NULL );
@@ -625,7 +623,7 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
     }
     else
         GDALGTIFKeyGetDOUBLE(hGTIF, GeogPrimeMeridianLongGeoKey, &(psDefn->PMLongToGreenwich), 0, 1 );
-    
+
     if( !pszAngularUnits )
     {
         GTIFGetUOMAngleInfo( psDefn->UOMAngle, &pszAngularUnits, NULL );
@@ -671,7 +669,7 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
         pszGeogName = CPLStrdup( pszDatumName ? pszDatumName : "unknown" );
     }
 
-    oSRS.SetGeogCS( pszGeogName, pszDatumName, 
+    oSRS.SetGeogCS( pszGeogName, pszDatumName,
                     pszSpheroidName, dfSemiMajor, dfInvFlattening,
                     pszPMName,
                     psDefn->PMLongToGreenwich / psDefn->UOMAngleInDegrees,
@@ -703,7 +701,27 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
                          psDefn->TOWGS84[5],
                          psDefn->TOWGS84[6] );
 #endif
-        
+
+/* -------------------------------------------------------------------- */
+/*      Set projection units if not yet done                            */
+/* -------------------------------------------------------------------- */
+    if( psDefn->Model == ModelTypeProjected && !linearUnitIsSet )
+    {
+        char        *pszUnitsName = NULL;
+
+        GTIFGetUOMLengthInfo( psDefn->UOMLength, &pszUnitsName, NULL );
+
+        if( pszUnitsName != NULL && psDefn->UOMLength != KvUserDefined )
+        {
+            oSRS.SetLinearUnits( pszUnitsName, psDefn->UOMLengthInMeters );
+            oSRS.SetAuthority( "PROJCS|UNIT", "EPSG", psDefn->UOMLength );
+        }
+        else
+            oSRS.SetLinearUnits( "unknown", psDefn->UOMLengthInMeters );
+
+        GTIFFreeMemory( pszUnitsName );
+    }
+
 /* ==================================================================== */
 /*      Try to import PROJCS from ProjectedCSTypeGeoKey if we           */
 /*      have essentially only it. We could relax a bit the constraints  */
@@ -719,22 +737,49 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
         GDALGTIFKeyGetSHORT(hGTIF, GeographicTypeGeoKey, &tmp, 0, 1  ) == 0 &&
         GDALGTIFKeyGetSHORT(hGTIF, GeogGeodeticDatumGeoKey, &tmp, 0, 1  ) == 0 &&
         GDALGTIFKeyGetSHORT(hGTIF, GeogEllipsoidGeoKey, &tmp, 0, 1  ) == 0 &&
-        CSLTestBoolean(CPLGetConfigOption("GTIFF_IMPORT_FROM_EPSG", "YES")) )
+        CPLTestBool(CPLGetConfigOption("GTIFF_IMPORT_FROM_EPSG", "YES")) )
     {
         // Save error state as importFromEPSGA() will call CPLReset()
-        int errNo = CPLGetLastErrorNo();
+        CPLErrorNum errNo = CPLGetLastErrorNo();
         CPLErr eErr = CPLGetLastErrorType();
         const char* pszTmp = CPLGetLastErrorMsg();
         char* pszLastErrorMsg = CPLStrdup(pszTmp ? pszTmp : "");
         CPLPushErrorHandler(CPLQuietErrorHandler);
-        OGRErr eImportErr = oSRS.importFromEPSG(psDefn->PCS);
+        OGRSpatialReference oSRSTmp;
+        OGRErr eImportErr = oSRSTmp.importFromEPSG(psDefn->PCS);
         CPLPopErrorHandler();
         // Restore error state
         CPLErrorSetState( eErr, errNo, pszLastErrorMsg);
         CPLFree(pszLastErrorMsg);
         bGotFromEPSG = (eImportErr == OGRERR_NONE);
+
+        if( bGotFromEPSG )
+        {
+            // See #6210. In case there's an overridden linear units, take it
+            // into account
+            char* pszUnitsName = NULL;
+            double dfUOMLengthInMeters = oSRS.GetLinearUnits( &pszUnitsName );
+            if( dfUOMLengthInMeters != oSRSTmp.GetLinearUnits(NULL) )
+            {
+                CPLDebug("GTiff", "Modify EPSG:%d to have %s linear units...",
+                            psDefn->PCS, pszUnitsName ? pszUnitsName : "unknown");
+
+                if( pszUnitsName )
+                    oSRSTmp.SetLinearUnitsAndUpdateParameters( pszUnitsName, dfUOMLengthInMeters );
+
+                const char* pszAuthorityCode = oSRS.GetAuthorityCode( "PROJCS|UNIT" );
+                const char* pszAuthorityName = oSRS.GetAuthorityName( "PROJCS|UNIT" );
+                if( pszAuthorityCode && pszAuthorityName )
+                    oSRSTmp.SetAuthority( "PROJCS|UNIT",pszAuthorityName, atoi(pszAuthorityCode) );
+
+                if( oSRSTmp.GetRoot()->FindChild( "AUTHORITY" ) != -1 )
+                    oSRSTmp.GetRoot()->DestroyChild( oSRSTmp.GetRoot()->FindChild( "AUTHORITY" ) );
+            }
+
+            oSRS = oSRSTmp;
+        }
     }
-        
+
 /* ==================================================================== */
 /*      Handle projection parameters.                                   */
 /* ==================================================================== */
@@ -745,8 +790,8 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
 /*      angular units of the GEOGCS and the linear units of the         */
 /*      projection.                                                     */
 /* -------------------------------------------------------------------- */
-        double		adfParm[10];
-        int		i;
+        double adfParm[10];
+        int i;
 
         for( i = 0; i < MIN(10,psDefn->nParms); i++ )
             adfParm[i] = psDefn->ProjParm[i];
@@ -759,16 +804,9 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
             adfParm[0] *= psDefn->UOMAngleInDegrees;
             adfParm[1] *= psDefn->UOMAngleInDegrees;
             adfParm[2] *= psDefn->UOMAngleInDegrees;
-            adfParm[3] *= psDefn->UOMAngleInDegrees; 
+            adfParm[3] *= psDefn->UOMAngleInDegrees;
         }
-        short unitCode = 0;
-        GDALGTIFKeyGetSHORT(hGTIF, ProjLinearUnitsGeoKey, &unitCode, 0, 1  );
-        if(unitCode != KvUserDefined)
-        {
-            adfParm[5] /= psDefn->UOMLengthInMeters;
-            adfParm[6] /= psDefn->UOMLengthInMeters;
-        }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Translation the fundamental projection.                         */
 /* -------------------------------------------------------------------- */
@@ -803,10 +841,10 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
                                   adfParm[4],
                                   adfParm[5], adfParm[6] );
 
-            if (psDefn->Projection == 1024 || psDefn->Projection == 9841) // override hack for google mercator. 
+            if (psDefn->Projection == 1024 || psDefn->Projection == 9841) // override hack for google mercator.
             {
-                oSRS.SetExtension( "PROJCS", "PROJ4",  
-                                   "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext  +no_defs" ); 
+                oSRS.SetExtension( "PROJCS", "PROJ4",
+                                   "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext  +no_defs" );
             }
             break;
 
@@ -828,25 +866,25 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
                          adfParm[4],
                          adfParm[5], adfParm[6] );
             break;
-        
+
           case CT_HotineObliqueMercatorAzimuthCenter:
             oSRS.SetHOMAC( adfParm[0], adfParm[1],
                            adfParm[2], adfParm[3],
                            adfParm[4],
                            adfParm[5], adfParm[6] );
             break;
-        
-          case CT_EquidistantConic: 
+
+          case CT_EquidistantConic:
             oSRS.SetEC( adfParm[0], adfParm[1],
                         adfParm[2], adfParm[3],
                         adfParm[5], adfParm[6] );
             break;
-        
+
           case CT_CassiniSoldner:
             oSRS.SetCS( adfParm[0], adfParm[1],
                         adfParm[5], adfParm[6] );
             break;
-        
+
           case CT_Polyconic:
             oSRS.SetPolyconic( adfParm[0], adfParm[1],
                                adfParm[5], adfParm[6] );
@@ -856,43 +894,43 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
             oSRS.SetAE( adfParm[0], adfParm[1],
                         adfParm[5], adfParm[6] );
             break;
-        
+
           case CT_MillerCylindrical:
             oSRS.SetMC( adfParm[0], adfParm[1],
                         adfParm[5], adfParm[6] );
             break;
-        
+
           case CT_Equirectangular:
             oSRS.SetEquirectangular2( adfParm[0], adfParm[1],
                                       adfParm[2],
                                       adfParm[5], adfParm[6] );
             break;
-        
+
           case CT_Gnomonic:
             oSRS.SetGnomonic( adfParm[0], adfParm[1],
                               adfParm[5], adfParm[6] );
             break;
-        
+
           case CT_LambertAzimEqualArea:
             oSRS.SetLAEA( adfParm[0], adfParm[1],
                           adfParm[5], adfParm[6] );
             break;
-        
+
           case CT_Orthographic:
             oSRS.SetOrthographic( adfParm[0], adfParm[1],
                                   adfParm[5], adfParm[6] );
             break;
-        
+
           case CT_Robinson:
             oSRS.SetRobinson( adfParm[1],
                               adfParm[5], adfParm[6] );
             break;
-        
+
           case CT_Sinusoidal:
             oSRS.SetSinusoidal( adfParm[1],
                                 adfParm[5], adfParm[6] );
             break;
-        
+
           case CT_VanDerGrinten:
             oSRS.SetVDG( adfParm[1],
                          adfParm[5], adfParm[6] );
@@ -903,7 +941,7 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
                         adfParm[4],
                         adfParm[5], adfParm[6] );
             break;
-        
+
           case CT_LambertConfConic_2SP:
             oSRS.SetLCC( adfParm[2], adfParm[3],
                          adfParm[0], adfParm[1],
@@ -915,7 +953,7 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
                             adfParm[4],
                             adfParm[5], adfParm[6] );
             break;
-        
+
           case CT_AlbersEqualArea:
             oSRS.SetACEA( adfParm[0], adfParm[1],
                           adfParm[2], adfParm[3],
@@ -936,28 +974,8 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
                 oSRS.GetRoot()->SetValue( "LOCAL_CS" );
             break;
         }
-
-/* -------------------------------------------------------------------- */
-/*      Set projection units.                                           */
-/* -------------------------------------------------------------------- */
-        if(!linearUnitIsSet)
-        {
-            char	*pszUnitsName = NULL;
-          
-            GTIFGetUOMLengthInfo( psDefn->UOMLength, &pszUnitsName, NULL );
-
-            if( pszUnitsName != NULL && psDefn->UOMLength != KvUserDefined )
-            {
-                oSRS.SetLinearUnits( pszUnitsName, psDefn->UOMLengthInMeters );
-                oSRS.SetAuthority( "PROJCS|UNIT", "EPSG", psDefn->UOMLength );
-            }
-            else
-                oSRS.SetLinearUnits( "unknown", psDefn->UOMLengthInMeters );
-
-            GTIFFreeMemory( pszUnitsName );
-        }
     }
-    
+
     if( oSRS.IsProjected())
     {
         // Hack to be able to read properly what we have written for EPSG:102113 (ESRI ancient WebMercator)
@@ -988,7 +1006,7 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
     if( (verticalCSType != -1 || verticalDatum != -1 || verticalUnits != -1)
         && (oSRS.IsGeographic() || oSRS.IsProjected() || oSRS.IsLocal()) )
     {
-        if( !GDALGTIFKeyGetASCII( hGTIF, VerticalCitationGeoKey, citation, 
+        if( !GDALGTIFKeyGetASCII( hGTIF, VerticalCitationGeoKey, citation,
                          0, sizeof(citation) ) )
             strcpy( citation, "unknown" );
 
@@ -1010,20 +1028,20 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
 
 /* -------------------------------------------------------------------- */
 /*      This addresses another case where the EGM96 Vertical Datum code */
-/*      is mis-used as a Vertical CS code (#4922)                       */
+/*      is misused as a Vertical CS code (#4922).                       */
 /* -------------------------------------------------------------------- */
         if( verticalCSType == 5171 )
         {
             verticalDatum = 5171;
             verticalCSType = 5773;
         }
- 
+
 /* -------------------------------------------------------------------- */
 /*      Somewhat similarly, codes 5001 to 5033 were treated as          */
 /*      vertical coordinate systems based on ellipsoidal heights.       */
 /*      We use the corresponding 2d geodetic datum as the vertical      */
 /*      datum and clear the vertical coordinate system code since       */
-/*      there isn't one in epsg.                                        */
+/*      there isn't one in EPSG.                                        */
 /* -------------------------------------------------------------------- */
         if( (verticalCSType >= 5001 && verticalCSType <= 5033)
             && verticalDatum == -1 )
@@ -1067,13 +1085,13 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
         if( verticalCSType > 0 && verticalCSType != KvUserDefined )
         {
             pszFilename = CSVFilename( "coordinate_reference_system.csv" );
-            sprintf( szSearchKey, "%d", verticalCSType );
+            snprintf( szSearchKey, sizeof(szSearchKey), "%d", verticalCSType );
 
             if( verticalDatum < 1 || verticalDatum == KvUserDefined )
             {
-                pszValue = CSVGetField( pszFilename, 
-                                        "coord_ref_sys_code", 
-                                        szSearchKey, CC_Integer, 
+                pszValue = CSVGetField( pszFilename,
+                                        "coord_ref_sys_code",
+                                        szSearchKey, CC_Integer,
                                         "datum_code" );
                 if( pszValue != NULL )
                     verticalDatum = (short) atoi(pszValue);
@@ -1081,9 +1099,9 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
 
             if( EQUAL(citation,"unknown") )
             {
-                pszValue = CSVGetField( pszFilename, 
-                                        "coord_ref_sys_code", 
-                                        szSearchKey, CC_Integer, 
+                pszValue = CSVGetField( pszFilename,
+                                        "coord_ref_sys_code",
+                                        szSearchKey, CC_Integer,
                                         "coord_ref_sys_name" );
                 if( pszValue != NULL && *pszValue != '\0' )
                     strncpy( citation, pszValue, sizeof(citation) );
@@ -1091,20 +1109,20 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
 
             if( verticalUnits < 1 || verticalUnits == KvUserDefined )
             {
-                pszValue = CSVGetField( pszFilename, 
-                                        "coord_ref_sys_code", 
-                                        szSearchKey, CC_Integer, 
+                pszValue = CSVGetField( pszFilename,
+                                        "coord_ref_sys_code",
+                                        szSearchKey, CC_Integer,
                                         "coord_sys_code" );
                 if( pszValue != NULL )
                 {
                     pszFilename = CSVFilename( "coordinate_axis.csv" );
-                    pszValue = CSVGetField( pszFilename, 
-                                            "coord_sys_code", 
-                                            pszValue, CC_Integer, 
+                    pszValue = CSVGetField( pszFilename,
+                                            "coord_sys_code",
+                                            pszValue, CC_Integer,
                                             "uom_code" );
                     if( pszValue != NULL )
                         verticalUnits = (short) atoi(pszValue);
-                }                
+                }
             }
         }
 
@@ -1125,7 +1143,7 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
             if( EQUAL(pszFilename,"datum.csv") )
                 pszFilename = CSVFilename( "gdal_datum.csv" );
 
-            sprintf( szSearchKey, "%d", verticalDatum );
+            snprintf( szSearchKey, sizeof(szSearchKey), "%d", verticalDatum );
 
             pszValue = CSVGetField( pszFilename,
                                     "DATUM_CODE", szSearchKey, CC_Integer,
@@ -1136,32 +1154,32 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
             pszValue = CSVGetField( pszFilename,
                                     "DATUM_CODE", szSearchKey, CC_Integer,
                                     "DATUM_TYPE" );
-            if( pszValue != NULL && EQUALN(pszValue,"geodetic",8) )
+            if( pszValue != NULL && STARTS_WITH_CI(pszValue, "geodetic") )
                 pszVDatumType = "2002"; // CS_VD_Ellipsoidal
 
-            // We unfortunately don't know how to identify other 
-            // vertical datum types, particularly orthometric (2001). 
+            // We unfortunately don't know how to identify other
+            // vertical datum types, particularly orthometric (2001).
         }
 
         oSRS.SetNode( "COMPD_CS|VERT_CS|VERT_DATUM", pszVDatumName );
         oSRS.GetAttrNode( "COMPD_CS|VERT_CS|VERT_DATUM" )
             ->AddChild( new OGR_SRSNode( pszVDatumType ) );
         if( verticalDatum > 0 && verticalDatum != KvUserDefined )
-            oSRS.SetAuthority( "COMPD_CS|VERT_CS|VERT_DATUM", "EPSG", 
+            oSRS.SetAuthority( "COMPD_CS|VERT_CS|VERT_DATUM", "EPSG",
                                verticalDatum );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Set the vertical units.                                         */
 /* -------------------------------------------------------------------- */
-        if( verticalUnits > 0 && verticalUnits != KvUserDefined 
+        if( verticalUnits > 0 && verticalUnits != KvUserDefined
             && verticalUnits != 9001 )
         {
             char szInMeters[128];
 
             pszFilename = CSVFilename("unit_of_measure.csv");
-            
+
             // Name
-            sprintf( szSearchKey, "%d", verticalUnits );
+            snprintf( szSearchKey, sizeof(szSearchKey), "%d", verticalUnits );
             pszValue = CSVGetField( pszFilename,
                                     "uom_code", szSearchKey, CC_Integer,
                                     "unit_of_meas_name" );
@@ -1173,15 +1191,15 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
             // Value
             double dfFactorB, dfFactorC;
             dfFactorB = GTIFAtof(
-                CSVGetField( pszFilename, 
+                CSVGetField( pszFilename,
                              "uom_code", szSearchKey, CC_Integer,
                              "factor_b" ));
             dfFactorC = GTIFAtof(
-                CSVGetField( pszFilename, 
+                CSVGetField( pszFilename,
                              "uom_code", szSearchKey, CC_Integer,
                              "factor_c" ));
             if( dfFactorB != 0.0 && dfFactorC != 0.0 )
-                CPLsprintf( szInMeters, "%.16g", dfFactorB / dfFactorC );
+                CPLsnprintf( szInMeters, sizeof(szInMeters), "%.16g", dfFactorB / dfFactorC );
             else
                 strcpy( szInMeters, "1" );
 
@@ -1205,15 +1223,15 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
         oSRS.SetNode( "COMPD_CS|VERT_CS|AXIS", "Up" );
         oSRS.GetAttrNode( "COMPD_CS|VERT_CS|AXIS" )
             ->AddChild( new OGR_SRSNode( "UP" ) );
-        
+
         if( verticalCSType > 0 && verticalCSType != KvUserDefined )
             oSRS.SetAuthority( "COMPD_CS|VERT_CS", "EPSG", verticalCSType );
     }
-    
+
 /* ==================================================================== */
 /*      Return the WKT serialization of the object.                     */
 /* ==================================================================== */
-    char	*pszWKT;
+    char *pszWKT;
 
     oSRS.FixupOrdering();
 
@@ -1230,18 +1248,16 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
 static int OGCDatumName2EPSGDatumCode( const char * pszOGCName )
 
 {
-    FILE	*fp;
-    char	**papszTokens;
-    int		nReturn = KvUserDefined;
-
+    char **papszTokens;
+    int nReturn = KvUserDefined;
 
 /* -------------------------------------------------------------------- */
 /*      Do we know it as a built in?                                    */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszOGCName,"NAD27") 
+    if( EQUAL(pszOGCName,"NAD27")
         || EQUAL(pszOGCName,"North_American_Datum_1927") )
         return Datum_North_American_Datum_1927;
-    else if( EQUAL(pszOGCName,"NAD83") 
+    else if( EQUAL(pszOGCName,"NAD83")
              || EQUAL(pszOGCName,"North_American_Datum_1983") )
         return Datum_North_American_Datum_1983;
     else if( EQUAL(pszOGCName,"WGS84") || EQUAL(pszOGCName,"WGS_1984")
@@ -1253,24 +1269,24 @@ static int OGCDatumName2EPSGDatumCode( const char * pszOGCName )
 /* -------------------------------------------------------------------- */
 /*      Open the table if possible.                                     */
 /* -------------------------------------------------------------------- */
-    fp = VSIFOpen( CSVFilename("gdal_datum.csv"), "r" );
+    VSILFILE *fp = VSIFOpenL( CSVFilename("gdal_datum.csv"), "r" );
     if( fp == NULL )
-        fp = VSIFOpen( CSVFilename("datum.csv"), "r" );
+        fp = VSIFOpenL( CSVFilename("datum.csv"), "r" );
 
     if( fp == NULL )
         return nReturn;
 
 /* -------------------------------------------------------------------- */
-/*	Discard the first line with field names.			*/
+/*      Discard the first line with field names.                        */
 /* -------------------------------------------------------------------- */
-    CSLDestroy( CSVReadParseLine( fp ) );
+    CSLDestroy( CSVReadParseLineL( fp ) );
 
 /* -------------------------------------------------------------------- */
 /*      Read lines looking for our datum.                               */
 /* -------------------------------------------------------------------- */
-    for( papszTokens = CSVReadParseLine( fp );
+    for( papszTokens = CSVReadParseLineL( fp );
          CSLCount(papszTokens) > 2 && nReturn == KvUserDefined;
-         papszTokens = CSVReadParseLine( fp ) )
+         papszTokens = CSVReadParseLineL( fp ) )
     {
         WKTMassageDatum( papszTokens + 1 );
 
@@ -1281,7 +1297,7 @@ static int OGCDatumName2EPSGDatumCode( const char * pszOGCName )
     }
 
     CSLDestroy( papszTokens );
-    VSIFClose( fp );
+    VSIFCloseL( fp );
 
     return nReturn;
 }
@@ -1295,10 +1311,16 @@ static int OGCDatumName2EPSGDatumCode( const char * pszOGCName )
 int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 
 {
+    return GTIFSetFromOGISDefnEx(psGTIF, pszOGCWKT, GEOTIFF_KEYS_STANDARD);
+}
+
+int GTIFSetFromOGISDefnEx( GTIF * psGTIF, const char *pszOGCWKT,
+                           GTIFFKeysFlavorEnum eFlavor )
+{
     OGRSpatialReference *poSRS;
-    int		nPCS = KvUserDefined;
+    int nPCS = KvUserDefined;
     OGRErr      eErr;
-    OGRBoolean peStrStored = FALSE;    
+    OGRBoolean peStrStored = FALSE;
 
     GTIFKeySet(psGTIF, GTRasterTypeGeoKey, TYPE_SHORT, 1,
                RasterPixelIsArea);
@@ -1322,18 +1344,18 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 
     if( poSRS->GetAuthorityName("PROJCS|GEOGCS|DATUM|SPHEROID") != NULL
         && EQUAL(poSRS->GetAuthorityName("PROJCS|GEOGCS|DATUM|SPHEROID"),
-                 "EPSG")) 
+                 "EPSG"))
     {
         nSpheroid = (short)
             atoi(poSRS->GetAuthorityCode("PROJCS|GEOGCS|DATUM|SPHEROID"));
     }
     else if( poSRS->GetAuthorityName("GEOGCS|DATUM|SPHEROID") != NULL
-             && EQUAL(poSRS->GetAuthorityName("GEOGCS|DATUM|SPHEROID"),"EPSG")) 
+             && EQUAL(poSRS->GetAuthorityName("GEOGCS|DATUM|SPHEROID"),"EPSG"))
     {
         nSpheroid = (short)
             atoi(poSRS->GetAuthorityCode("GEOGCS|DATUM|SPHEROID"));
     }
-    
+
     dfSemiMajor = poSRS->GetSemiMajor( &eErr );
     dfInvFlattening = poSRS->GetInvFlattening( &eErr );
     if( eErr != OGRERR_NONE )
@@ -1341,16 +1363,16 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         dfSemiMajor = 0.0;
         dfInvFlattening = 0.0;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Get the Datum so we can special case a few PCS codes.           */
 /* -------------------------------------------------------------------- */
-    int		nDatum = KvUserDefined;
+    int nDatum = KvUserDefined;
 
-    if( poSRS->GetAuthorityName("PROJCS|GEOGCS|DATUM") != NULL 
+    if( poSRS->GetAuthorityName("PROJCS|GEOGCS|DATUM") != NULL
         && EQUAL(poSRS->GetAuthorityName("PROJCS|GEOGCS|DATUM"),"EPSG") )
         nDatum = atoi(poSRS->GetAuthorityCode("PROJCS|GEOGCS|DATUM"));
-    else if( poSRS->GetAuthorityName("GEOGCS|DATUM") != NULL 
+    else if( poSRS->GetAuthorityName("GEOGCS|DATUM") != NULL
              && EQUAL(poSRS->GetAuthorityName("GEOGCS|DATUM"),"EPSG") )
         nDatum = atoi(poSRS->GetAuthorityCode("GEOGCS|DATUM"));
     else if( poSRS->GetAttrValue("DATUM") != NULL )
@@ -1361,10 +1383,10 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 /* -------------------------------------------------------------------- */
     int         nGCS = KvUserDefined;
 
-    if( poSRS->GetAuthorityName("PROJCS|GEOGCS") != NULL 
+    if( poSRS->GetAuthorityName("PROJCS|GEOGCS") != NULL
         && EQUAL(poSRS->GetAuthorityName("PROJCS|GEOGCS"),"EPSG") )
         nGCS = atoi(poSRS->GetAuthorityCode("PROJCS|GEOGCS"));
-    else if( poSRS->GetAuthorityName("GEOGCS") != NULL 
+    else if( poSRS->GetAuthorityName("GEOGCS") != NULL
              && EQUAL(poSRS->GetAuthorityName("GEOGCS"),"EPSG") )
         nGCS = atoi(poSRS->GetAuthorityCode("GEOGCS"));
 
@@ -1375,10 +1397,10 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 /*      Get the linear units.                                           */
 /* -------------------------------------------------------------------- */
     char        *pszLinearUOMName = NULL;
-    double	dfLinearUOM = poSRS->GetLinearUnits( &pszLinearUOMName );
+    double dfLinearUOM = poSRS->GetLinearUnits( &pszLinearUOMName );
     int         nUOMLengthCode = 9001; /* meters */
 
-    if( poSRS->GetAuthorityName("PROJCS|UNIT") != NULL 
+    if( poSRS->GetAuthorityName("PROJCS|UNIT") != NULL
         && EQUAL(poSRS->GetAuthorityName("PROJCS|UNIT"),"EPSG")
         && poSRS->GetAttrNode( "PROJCS|UNIT" ) != poSRS->GetAttrNode("GEOGCS|UNIT") )
         nUOMLengthCode = atoi(poSRS->GetAuthorityCode("PROJCS|UNIT"));
@@ -1396,7 +1418,7 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 /* -------------------------------------------------------------------- */
 /*      Get some authority values.                                      */
 /* -------------------------------------------------------------------- */
-    if( poSRS->GetAuthorityName("PROJCS") != NULL 
+    if( poSRS->GetAuthorityName("PROJCS") != NULL
         && EQUAL(poSRS->GetAuthorityName("PROJCS"),"EPSG") )
     {
         nPCS = atoi(poSRS->GetAuthorityCode("PROJCS"));
@@ -1408,17 +1430,27 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 /*      Handle the projection transformation.                           */
 /* -------------------------------------------------------------------- */
     const char *pszProjection = poSRS->GetAttrValue( "PROJECTION" );
-    int bWritePEString = FALSE;
-    
+    bool bWritePEString = false;
+
     if( nPCS != KvUserDefined )
     {
-        GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
-                   ModelTypeProjected);
-        GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, nPCS );
+        // If ESRI_PE flavor is explicitly required, then for EPSG:3857
+        // we will have to write a completely non-standard definition
+        // that requires not setting GTModelTypeGeoKey to ProjectedCSTypeGeoKey
+        if( eFlavor == GEOTIFF_KEYS_ESRI_PE && nPCS == 3857 )
+        {
+            bWritePEString = true;
+        }
+        else
+        {
+            GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
+                    ModelTypeProjected);
+            GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, nPCS );
+        }
     }
     else if( poSRS->IsGeocentric() )
     {
-        GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeGeocentric );
     }
     else if( pszProjection == NULL )
@@ -1437,7 +1469,7 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
                    CT_AlbersEqualArea );
 
         GTIFKeySet(psGTIF, ProjStdParallelGeoKey, TYPE_DOUBLE, 1,
@@ -1451,17 +1483,17 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 
         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
     }
 
     else if( poSRS->GetUTMZone() != 0 )
     {
-        int		bNorth, nZone, nProjection;
+        int bNorth, nZone, nProjection;
 
         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
@@ -1498,10 +1530,10 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
             else
                 nProjection = 16100 + nZone;
 
-        
+
             GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
                        KvUserDefined );
-            
+
             GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1, nProjection );
         }
     }
@@ -1515,7 +1547,7 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
                    CT_TransverseMercator );
 
         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
@@ -1523,17 +1555,17 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 
         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
     }
-    
+
     else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED) )
     {
         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
@@ -1543,7 +1575,7 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
                    CT_TransvMercator_SouthOriented );
 
         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
@@ -1551,18 +1583,18 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 
         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
     }
-    
-    else if( EQUAL(pszProjection,SRS_PT_MERCATOR_2SP) 
+
+    else if( EQUAL(pszProjection,SRS_PT_MERCATOR_2SP)
              || EQUAL(pszProjection,SRS_PT_MERCATOR_1SP) )
 
     {
@@ -1573,7 +1605,7 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
                    CT_Mercator );
 
         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
@@ -1591,11 +1623,11 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 
         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
     }
-    
+
     else if( EQUAL(pszProjection,SRS_PT_OBLIQUE_STEREOGRAPHIC) )
     {
         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
@@ -1605,7 +1637,7 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
                    CT_ObliqueStereographic );
 
         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
@@ -1613,17 +1645,17 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 
         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
     }
-    
+
     else if( EQUAL(pszProjection,SRS_PT_STEREOGRAPHIC) )
     {
         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
@@ -1633,7 +1665,7 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
                    CT_Stereographic );
 
         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
@@ -1641,17 +1673,17 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 
         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
     }
-    
+
     else if( EQUAL(pszProjection,SRS_PT_POLAR_STEREOGRAPHIC) )
     {
         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
@@ -1661,7 +1693,7 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
                    CT_PolarStereographic );
 
         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
@@ -1669,17 +1701,17 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 
         GTIFKeySet(psGTIF, ProjStraightVertPoleLongGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
     }
-    
+
     else if( EQUAL(pszProjection,SRS_PT_HOTINE_OBLIQUE_MERCATOR) )
     {
         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
@@ -1689,7 +1721,7 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
                    CT_ObliqueMercator );
 
         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
@@ -1697,23 +1729,23 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 
         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjAzimuthAngleGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_AZIMUTH, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjRectifiedGridAngleGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_RECTIFIED_GRID_ANGLE, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjScaleAtCenterGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
     }
-    
+
     else if( EQUAL(pszProjection,SRS_PT_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER) )
     {
         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
@@ -1723,7 +1755,7 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
                    CT_HotineObliqueMercatorAzimuthCenter );
 
         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
@@ -1731,23 +1763,23 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 
         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjAzimuthAngleGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_AZIMUTH, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjRectifiedGridAngleGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_RECTIFIED_GRID_ANGLE, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjScaleAtCenterGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
     }
-    
+
     else if( EQUAL(pszProjection,SRS_PT_CASSINI_SOLDNER) )
     {
         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
@@ -1757,7 +1789,7 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
                    CT_CassiniSoldner );
 
         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
@@ -1765,14 +1797,14 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 
         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
     }
-    
+
     else if( EQUAL(pszProjection,SRS_PT_EQUIDISTANT_CONIC) )
     {
         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
@@ -1782,7 +1814,7 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
                    CT_EquidistantConic );
 
         GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1,
@@ -1796,14 +1828,14 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 
         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
     }
-    
+
     else if( EQUAL(pszProjection,SRS_PT_POLYCONIC) )
     {
         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
@@ -1813,7 +1845,7 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
                    CT_Polyconic );
 
         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
@@ -1821,17 +1853,17 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 
         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
     }
-    
+
     else if( EQUAL(pszProjection,SRS_PT_AZIMUTHAL_EQUIDISTANT) )
     {
         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
@@ -1841,7 +1873,7 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
                    CT_AzimuthalEquidistant );
 
         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
@@ -1849,14 +1881,14 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 
         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
     }
-    
+
     else if( EQUAL(pszProjection,SRS_PT_MILLER_CYLINDRICAL) )
     {
         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
@@ -1866,7 +1898,7 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
                    CT_MillerCylindrical );
 
         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
@@ -1874,14 +1906,14 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 
         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
     }
-    
+
     else if( EQUAL(pszProjection,SRS_PT_EQUIRECTANGULAR) )
     {
         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
@@ -1891,7 +1923,7 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
                    CT_Equirectangular );
 
         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
@@ -1899,17 +1931,17 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 
         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
     }
-    
+
     else if( EQUAL(pszProjection,SRS_PT_GNOMONIC) )
     {
         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
@@ -1919,7 +1951,7 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
                    CT_Gnomonic );
 
         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
@@ -1927,14 +1959,14 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 
         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
     }
-    
+
     else if( EQUAL(pszProjection,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
     {
         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
@@ -1944,7 +1976,7 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
                    CT_LambertAzimEqualArea );
 
         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
@@ -1952,14 +1984,14 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 
         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
     }
-    
+
     else if( EQUAL(pszProjection,SRS_PT_ORTHOGRAPHIC) )
     {
         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
@@ -1969,7 +2001,7 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
                    CT_Orthographic );
 
         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
@@ -1977,14 +2009,14 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 
         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
     }
-    
+
     else if( EQUAL(pszProjection,SRS_PT_NEW_ZEALAND_MAP_GRID) )
     {
         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
@@ -1994,7 +2026,7 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
                    CT_NewZealandMapGrid );
 
         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
@@ -2002,14 +2034,14 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 
         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
     }
-    
+
     else if( EQUAL(pszProjection,SRS_PT_ROBINSON) )
     {
         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
@@ -2019,19 +2051,19 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
                    CT_Robinson );
 
         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
     }
-    
+
     else if( EQUAL(pszProjection,SRS_PT_SINUSOIDAL) )
     {
         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
@@ -2041,19 +2073,19 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
                    CT_Sinusoidal );
 
         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
     }
-    
+
     else if( EQUAL(pszProjection,SRS_PT_VANDERGRINTEN) )
     {
         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
@@ -2063,19 +2095,19 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
                    CT_VanDerGrinten );
 
         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
     }
-    
+
     else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP) )
     {
         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
@@ -2085,7 +2117,7 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
                    CT_LambertConfConic_2SP );
 
         GTIFKeySet(psGTIF, ProjFalseOriginLatGeoKey, TYPE_DOUBLE, 1,
@@ -2093,20 +2125,20 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 
         GTIFKeySet(psGTIF, ProjFalseOriginLongGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjStdParallel2GeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_2, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseOriginEastingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseOriginNorthingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
     }
-    
+
     else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP) )
     {
         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
@@ -2116,7 +2148,7 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
                    CT_LambertConfConic_1SP );
 
         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
@@ -2124,13 +2156,13 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 
         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
     }
@@ -2144,55 +2176,69 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1,
                    CT_CylindricalEqualArea );
 
         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
-        
+
         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
     }
 
     else
     {
-        bWritePEString = TRUE;
+        bWritePEString = true;
     }
 
     // Note that VERTCS is an ESRI "spelling" of VERT_CS so we assume if
     // we find it that we should try to treat this as a PE string.
     bWritePEString |= (poSRS->GetAttrValue("VERTCS") != NULL);
 
-    if( bWritePEString 
-        && CSLTestBoolean( CPLGetConfigOption("GTIFF_ESRI_CITATION",
-                                              "YES") ) )
+    bWritePEString |= (eFlavor == GEOTIFF_KEYS_ESRI_PE);
+
+    bWritePEString &=
+        CPLTestBool( CPLGetConfigOption("GTIFF_ESRI_CITATION", "YES") );
+
+    if( bWritePEString )
     {
         /* Anyhing we can't map, we store as an ESRI PE string with a citation key */
         char *pszPEString = NULL;
         poSRS->morphToESRI();
         poSRS->exportToWkt( &pszPEString );
-        int peStrLen = strlen(pszPEString);
+        int peStrLen = static_cast<int>(strlen(pszPEString));
         if(peStrLen > 0)
         {
             char *outPeStr = (char *) CPLMalloc( peStrLen + strlen("ESRI PE String = ")+1 );
-            strcpy(outPeStr, "ESRI PE String = "); 
-            strcat(outPeStr, pszPEString); 
-            GTIFKeySet( psGTIF, PCSCitationGeoKey, TYPE_ASCII, 0, outPeStr ); 
+            strcpy(outPeStr, "ESRI PE String = ");
+            strcat(outPeStr, pszPEString);
+            GTIFKeySet( psGTIF, PCSCitationGeoKey, TYPE_ASCII, 0, outPeStr );
             peStrStored = TRUE;
             CPLFree( outPeStr );
         }
-        if(pszPEString)
-            CPLFree( pszPEString );
+        CPLFree( pszPEString );
         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
+
+        /* Not completely sure we really need to imitate ArcGIS to that point */
+        /* but that cannot hurt */
+        if( nPCS == 3857 )
+        {
+            GTIFKeySet(psGTIF, GTCitationGeoKey, TYPE_ASCII, 0,
+                       "PCS Name = WGS_1984_Web_Mercator_Auxiliary_Sphere");
+            GTIFKeySet( psGTIF, GeographicTypeGeoKey, TYPE_SHORT,
+                        1, GCS_WGS_84 );
+            GTIFKeySet( psGTIF, GeogSemiMajorAxisGeoKey, TYPE_DOUBLE, 1, 6378137.0);
+            GTIFKeySet( psGTIF, GeogInvFlatteningGeoKey, TYPE_DOUBLE, 1, 298.257223563);
+        }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Is there a false easting/northing set?  If so, write out a      */
 /*      special geokey tag to indicate that GDAL has written these      */
@@ -2204,10 +2250,10 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
          || GDALGTIFKeyGetDOUBLE(psGTIF, ProjFalseNorthingGeoKey, &dfFN, 0, 1)
          || GDALGTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginEastingGeoKey, &dfFE, 0, 1)
          || GDALGTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginNorthingGeoKey, &dfFN, 0, 1))
-        && (dfFE != 0.0 || dfFN != 0.0) 
+        && (dfFE != 0.0 || dfFN != 0.0)
         && nUOMLengthCode != 9001 )
     {
-        GTIFKeySet(psGTIF, (geokey_t) ProjLinearUnitsInterpCorrectGeoKey, 
+        GTIFKeySet(psGTIF, (geokey_t) ProjLinearUnitsInterpCorrectGeoKey,
                    TYPE_SHORT, 1, (short) 1 );
     }
 
@@ -2216,41 +2262,40 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 /* -------------------------------------------------------------------- */
     if( poSRS->IsGeocentric() )
     {
-        GTIFKeySet(psGTIF, GeogLinearUnitsGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet(psGTIF, GeogLinearUnitsGeoKey, TYPE_SHORT, 1,
                    nUOMLengthCode );
         if( nUOMLengthCode == KvUserDefined )
-            GTIFKeySet( psGTIF, GeogLinearUnitSizeGeoKey, TYPE_DOUBLE, 1, 
+            GTIFKeySet( psGTIF, GeogLinearUnitSizeGeoKey, TYPE_DOUBLE, 1,
                         dfLinearUOM);
     }
     else if( !poSRS->IsGeographic() )
     {
-        GTIFKeySet(psGTIF, ProjLinearUnitsGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet(psGTIF, ProjLinearUnitsGeoKey, TYPE_SHORT, 1,
                    nUOMLengthCode );
         if( nUOMLengthCode == KvUserDefined )
-            GTIFKeySet( psGTIF, ProjLinearUnitSizeGeoKey, TYPE_DOUBLE, 1, 
+            GTIFKeySet( psGTIF, ProjLinearUnitSizeGeoKey, TYPE_DOUBLE, 1,
                         dfLinearUOM);
 
         /* if linear units name is available and user defined, store it as citation */
-        if(!peStrStored 
-           && nUOMLengthCode == KvUserDefined 
-           && pszLinearUOMName 
+        if(!peStrStored
+           && nUOMLengthCode == KvUserDefined
+           && pszLinearUOMName
            && strlen(pszLinearUOMName)>0
-           && CSLTestBoolean( CPLGetConfigOption("GTIFF_ESRI_CITATION",
+           && CPLTestBool( CPLGetConfigOption("GTIFF_ESRI_CITATION",
                                                  "YES") ) )
         {
             SetLinearUnitCitation(psGTIF, pszLinearUOMName);
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
-/*      Write angular units.  Always Degrees for now.                   */
-/*   Changed to support different angular units                         */
+/*      Write angular units.                                            */
 /* -------------------------------------------------------------------- */
 
     char* angUnitName = NULL;
     double angUnitValue = poSRS->GetAngularUnits(&angUnitName);
     if(EQUAL(angUnitName, "Degree"))
-        GTIFKeySet(psGTIF, GeogAngularUnitsGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet(psGTIF, GeogAngularUnitsGeoKey, TYPE_SHORT, 1,
                    Angular_Degree );
     else if (EQUAL(angUnitName, "arc-second"))
         GTIFKeySet(psGTIF, GeogAngularUnitsGeoKey, TYPE_SHORT, 1,
@@ -2270,11 +2315,11 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
     /*else if (EQUAL(angUnitName, "microradian"))
         GTIFKeySet(psGTIF, GeogAngularUnitsGeoKey, TYPE_SHORT, 1,
                    9109);*/
-    else if(angUnitName)
+    else
     {
-        GTIFKeySet(psGTIF, GeogCitationGeoKey, TYPE_ASCII, 0, 
-                   angUnitName ); // it may be rewritten if the gcs is userdefined 
-        GTIFKeySet(psGTIF, GeogAngularUnitSizeGeoKey, TYPE_DOUBLE, 1, 
+        GTIFKeySet(psGTIF, GeogCitationGeoKey, TYPE_ASCII, 0,
+                   angUnitName ); // it may be rewritten if the gcs is userdefined
+        GTIFKeySet(psGTIF, GeogAngularUnitSizeGeoKey, TYPE_DOUBLE, 1,
                    angUnitValue );
     }
 
@@ -2283,11 +2328,14 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 /*      name.                                                           */
 /* -------------------------------------------------------------------- */
     if( poSRS->GetRoot() != NULL
-        && poSRS->GetRoot()->GetChild(0) != NULL 
+        && poSRS->GetRoot()->GetChild(0) != NULL
         && (poSRS->IsProjected() || poSRS->IsLocal() || poSRS->IsGeocentric()) )
     {
-        GTIFKeySet( psGTIF, GTCitationGeoKey, TYPE_ASCII, 0, 
-                    poSRS->GetRoot()->GetChild(0)->GetValue() );
+        if( !(bWritePEString && nPCS == 3857) )
+        {
+            GTIFKeySet( psGTIF, GTCitationGeoKey, TYPE_ASCII, 0,
+                        poSRS->GetRoot()->GetChild(0)->GetValue() );
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -2297,7 +2345,7 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 
     if( poGCS != NULL && poGCS->GetChild(0) != NULL )
     {
-        GTIFKeySet( psGTIF, GeogCitationGeoKey, TYPE_ASCII, 0, 
+        GTIFKeySet( psGTIF, GeogCitationGeoKey, TYPE_ASCII, 0,
                     poGCS->GetChild(0)->GetValue() );
     }
 
@@ -2316,7 +2364,7 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
             else if( nDatum == Datum_WGS84 || nDatum == DatumE_WGS84 )
                 nGCS = GCS_WGS_84;
         }
-            
+
         if( nGCS != KvUserDefined )
         {
             GTIFKeySet( psGTIF, GeographicTypeGeoKey, TYPE_SHORT,
@@ -2324,27 +2372,27 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         }
         else if( nDatum != KvUserDefined )
         {
-            GTIFKeySet( psGTIF, GeographicTypeGeoKey, TYPE_SHORT, 1, 
+            GTIFKeySet( psGTIF, GeographicTypeGeoKey, TYPE_SHORT, 1,
                         KvUserDefined );
             GTIFKeySet( psGTIF, GeogGeodeticDatumGeoKey, TYPE_SHORT,
                         1, nDatum );
         }
         else if( nSpheroid != KvUserDefined )
         {
-            GTIFKeySet( psGTIF, GeographicTypeGeoKey, TYPE_SHORT, 1, 
+            GTIFKeySet( psGTIF, GeographicTypeGeoKey, TYPE_SHORT, 1,
                         KvUserDefined );
             GTIFKeySet( psGTIF, GeogGeodeticDatumGeoKey, TYPE_SHORT,
                         1, KvUserDefined );
-            GTIFKeySet( psGTIF, GeogEllipsoidGeoKey, TYPE_SHORT, 1, 
+            GTIFKeySet( psGTIF, GeogEllipsoidGeoKey, TYPE_SHORT, 1,
                         nSpheroid );
         }
         else if( dfSemiMajor != 0.0 )
         {
-            GTIFKeySet( psGTIF, GeographicTypeGeoKey, TYPE_SHORT, 1, 
+            GTIFKeySet( psGTIF, GeographicTypeGeoKey, TYPE_SHORT, 1,
                         KvUserDefined );
             GTIFKeySet( psGTIF, GeogGeodeticDatumGeoKey, TYPE_SHORT,
                         1, KvUserDefined );
-            GTIFKeySet( psGTIF, GeogEllipsoidGeoKey, TYPE_SHORT, 1, 
+            GTIFKeySet( psGTIF, GeogEllipsoidGeoKey, TYPE_SHORT, 1,
                         KvUserDefined );
             GTIFKeySet( psGTIF, GeogSemiMajorAxisGeoKey, TYPE_DOUBLE, 1,
                         dfSemiMajor );
@@ -2358,15 +2406,15 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         else if( poSRS->GetAttrValue("DATUM") != NULL
                  && strstr(poSRS->GetAttrValue("DATUM"),"unknown") == NULL
                  && strstr(poSRS->GetAttrValue("DATUM"),"unnamed") == NULL )
-                 
+
         {
             CPLError( CE_Warning, CPLE_AppDefined,
                       "Couldn't translate `%s' to a GeoTIFF datum.\n",
                       poSRS->GetAttrValue("DATUM") );
         }
 
-        /* Always set InvFlattening if it is avaliable.  */
-        /* So that it doesn'tneed to calculate from SemiMinor */
+        /* Always set InvFlattening if it is available.  */
+        /* So that it doesn't need to calculate from SemiMinor */
         if( dfInvFlattening != 0.0 )
             GTIFKeySet( psGTIF, GeogInvFlatteningGeoKey, TYPE_DOUBLE, 1,
                         dfInvFlattening );
@@ -2375,8 +2423,8 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
             GTIFKeySet( psGTIF, GeogSemiMajorAxisGeoKey, TYPE_DOUBLE, 1,
                         dfSemiMajor );
 
-        if( nGCS == KvUserDefined 
-            && CSLTestBoolean( CPLGetConfigOption("GTIFF_ESRI_CITATION",
+        if( nGCS == KvUserDefined
+            && CPLTestBool( CPLGetConfigOption("GTIFF_ESRI_CITATION",
                                                   "YES") ) )
             SetGeogCSCitation(psGTIF, poSRS, angUnitName, nDatum, nSpheroid);
     }
@@ -2403,7 +2451,7 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
                             adfTOWGS84 );
         }
         else
-            GTIFKeySet( psGTIF, GeogTOWGS84GeoKey, TYPE_DOUBLE, 7, 
+            GTIFKeySet( psGTIF, GeogTOWGS84GeoKey, TYPE_DOUBLE, 7,
                         adfTOWGS84 );
     }
 #endif
@@ -2415,19 +2463,19 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
     {
         const char *pszValue;
 
-        GTIFKeySet( psGTIF, VerticalCitationGeoKey, TYPE_ASCII, 0, 
+        GTIFKeySet( psGTIF, VerticalCitationGeoKey, TYPE_ASCII, 0,
                     poSRS->GetAttrValue( "COMPD_CS|VERT_CS" ) );
 
         pszValue = poSRS->GetAuthorityCode( "COMPD_CS|VERT_CS" );
         if( pszValue && atoi(pszValue) )
             GTIFKeySet( psGTIF, VerticalCSTypeGeoKey, TYPE_SHORT, 1,
                         atoi(pszValue) );
-        
+
         pszValue = poSRS->GetAuthorityCode( "COMPD_CS|VERT_CS|VERT_DATUM" );
         if( pszValue && atoi(pszValue) )
             GTIFKeySet( psGTIF, VerticalDatumGeoKey, TYPE_SHORT, 1,
                         atoi(pszValue) );
-        
+
         pszValue = poSRS->GetAuthorityCode( "COMPD_CS|VERT_CS|UNIT" );
         if( pszValue && atoi(pszValue) )
             GTIFKeySet( psGTIF, VerticalUnitsGeoKey, TYPE_SHORT, 1,
@@ -2445,7 +2493,7 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 /*                         GTIFWktFromMemBuf()                          */
 /************************************************************************/
 
-CPLErr GTIFWktFromMemBuf( int nSize, unsigned char *pabyBuffer, 
+CPLErr GTIFWktFromMemBuf( int nSize, unsigned char *pabyBuffer,
                           char **ppszWKT, double *padfGeoTransform,
                           int *pnGCPCount, GDAL_GCP **ppasGCPList )
 {
@@ -2453,7 +2501,7 @@ CPLErr GTIFWktFromMemBuf( int nSize, unsigned char *pabyBuffer,
                                pnGCPCount, ppasGCPList, NULL, NULL);
 }
 
-CPLErr GTIFWktFromMemBufEx( int nSize, unsigned char *pabyBuffer, 
+CPLErr GTIFWktFromMemBufEx( int nSize, unsigned char *pabyBuffer,
                             char **ppszWKT, double *padfGeoTransform,
                             int *pnGCPCount, GDAL_GCP **ppasGCPList,
                             int *pbPixelIsPoint, char*** ppapszRPCMD )
@@ -2464,7 +2512,7 @@ CPLErr GTIFWktFromMemBufEx( int nSize, unsigned char *pabyBuffer,
     short nRasterType;
     char szFilename[100];
 
-    sprintf( szFilename, "/vsimem/wkt_from_mem_buf_%ld.tif",
+    snprintf( szFilename, sizeof(szFilename), "/vsimem/wkt_from_mem_buf_%ld.tif",
              (long) CPLGetPID() );
 
 /* -------------------------------------------------------------------- */
@@ -2492,14 +2540,14 @@ CPLErr GTIFWktFromMemBufEx( int nSize, unsigned char *pabyBuffer,
         CPLError( CE_Failure, CPLE_AppDefined,
                   "TIFF/GeoTIFF structure is corrupt." );
         VSIUnlink( szFilename );
-        VSIFCloseL( fp );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
         return CE_Failure;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Get the projection definition.                                  */
 /* -------------------------------------------------------------------- */
-    GTIF 	*hGTIF;
+    GTIF *hGTIF;
     GTIFDefn    *psGTIFDefn;
 
     hGTIF = GTIFNew(hTIFF);
@@ -2510,7 +2558,7 @@ CPLErr GTIFWktFromMemBufEx( int nSize, unsigned char *pabyBuffer,
     {
         bPixelIsPoint = true;
         bPointGeoIgnore =
-            CSLTestBoolean( CPLGetConfigOption("GTIFF_POINT_GEO_IGNORE",
+            CPLTestBool( CPLGetConfigOption("GTIFF_POINT_GEO_IGNORE",
                                             "FALSE") );
     }
     if( pbPixelIsPoint )
@@ -2522,28 +2570,28 @@ CPLErr GTIFWktFromMemBufEx( int nSize, unsigned char *pabyBuffer,
     psGTIFDefn = GTIFAllocDefn();
 #else
     psGTIFDefn = (GTIFDefn *) CPLCalloc(1,sizeof(GTIFDefn));
-#endif    
+#endif
+
 
-                
     if( hGTIF != NULL && GTIFGetDefn( hGTIF, psGTIFDefn ) )
         *ppszWKT = GTIFGetOGISDefn( hGTIF, psGTIFDefn );
     else
         *ppszWKT = NULL;
-    
+
     if( hGTIF )
         GTIFFree( hGTIF );
-    
+
 #if LIBGEOTIFF_VERSION >= 1410
     GTIFFreeDefn(psGTIFDefn);
 #else
     CPLFree(psGTIFDefn);
-#endif    
+#endif
 
 /* -------------------------------------------------------------------- */
 /*      Get geotransform or tiepoints.                                  */
 /* -------------------------------------------------------------------- */
-    double	*padfTiePoints, *padfScale, *padfMatrix;
-    int16	nCount;
+    double *padfTiePoints, *padfScale, *padfMatrix;
+    int16 nCount;
 
     padfGeoTransform[0] = 0.0;
     padfGeoTransform[1] = 1.0;
@@ -2554,7 +2602,7 @@ CPLErr GTIFWktFromMemBufEx( int nSize, unsigned char *pabyBuffer,
 
     *pnGCPCount = 0;
     *ppasGCPList = NULL;
-    
+
     if( TIFFGetField(hTIFF,TIFFTAG_GEOPIXELSCALE,&nCount,&padfScale )
         && nCount >= 2 )
     {
@@ -2568,7 +2616,7 @@ CPLErr GTIFWktFromMemBufEx( int nSize, unsigned char *pabyBuffer,
                 padfTiePoints[3] - padfTiePoints[0] * padfGeoTransform[1];
             padfGeoTransform[3] =
                 padfTiePoints[4] - padfTiePoints[1] * padfGeoTransform[5];
-        
+
             // adjust for pixel is point in transform
             if( bPixelIsPoint && !bPointGeoIgnore )
             {
@@ -2583,13 +2631,13 @@ CPLErr GTIFWktFromMemBufEx( int nSize, unsigned char *pabyBuffer,
     {
         *pnGCPCount = nCount / 6;
         *ppasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),*pnGCPCount);
-        
+
         for( int iGCP = 0; iGCP < *pnGCPCount; iGCP++ )
         {
-            char	szID[32];
-            GDAL_GCP	*psGCP = *ppasGCPList + iGCP;
+            char szID[32];
+            GDAL_GCP *psGCP = *ppasGCPList + iGCP;
 
-            sprintf( szID, "%d", iGCP+1 );
+            snprintf( szID, sizeof(szID), "%d", iGCP+1 );
             psGCP->pszId = CPLStrdup( szID );
             psGCP->pszInfo = CPLStrdup("");
             psGCP->dfGCPPixel = padfTiePoints[iGCP*6+0];
@@ -2600,7 +2648,7 @@ CPLErr GTIFWktFromMemBufEx( int nSize, unsigned char *pabyBuffer,
         }
     }
 
-    else if( TIFFGetField(hTIFF,TIFFTAG_GEOTRANSMATRIX,&nCount,&padfMatrix ) 
+    else if( TIFFGetField(hTIFF,TIFFTAG_GEOTRANSMATRIX,&nCount,&padfMatrix )
              && nCount == 16 )
     {
         padfGeoTransform[0] = padfMatrix[3];
@@ -2623,7 +2671,7 @@ CPLErr GTIFWktFromMemBufEx( int nSize, unsigned char *pabyBuffer,
 /*      Cleanup.                                                        */
 /* -------------------------------------------------------------------- */
     XTIFFClose( hTIFF );
-    VSIFCloseL( fp );
+    CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
 
     VSIUnlink( szFilename );
 
@@ -2653,10 +2701,10 @@ CPLErr GTIFMemBufFromWktEx( const char *pszWKT, const double *padfGeoTransform,
 
 {
     TIFF        *hTIFF;
-    GTIF 	*hGTIF;
+    GTIF *hGTIF;
     char        szFilename[100];
 
-    sprintf( szFilename, "/vsimem/wkt_from_mem_buf_%ld.tif", 
+    snprintf( szFilename, sizeof(szFilename), "/vsimem/wkt_from_mem_buf_%ld.tif",
              (long) CPLGetPID() );
 
 /* -------------------------------------------------------------------- */
@@ -2678,7 +2726,7 @@ CPLErr GTIFMemBufFromWktEx( const char *pszWKT, const double *padfGeoTransform,
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "TIFF/GeoTIFF structure is corrupt." );
-        VSIFCloseL(fpL);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpL));
         return CE_Failure;
     }
 
@@ -2692,17 +2740,17 @@ CPLErr GTIFMemBufFromWktEx( const char *pszWKT, const double *padfGeoTransform,
     TIFFSetField( hTIFF, TIFFTAG_ROWSPERSTRIP, 1 );
     TIFFSetField( hTIFF, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG );
     TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Get the projection definition.                                  */
 /* -------------------------------------------------------------------- */
 
-    int  bPointGeoIgnore = FALSE;
+    int bPointGeoIgnore = FALSE;
     if( bPixelIsPoint )
     {
-        bPointGeoIgnore = 
-            CSLTestBoolean( CPLGetConfigOption("GTIFF_POINT_GEO_IGNORE",
-                                               "FALSE") );
+        bPointGeoIgnore =
+            CPLTestBool( CPLGetConfigOption( "GTIFF_POINT_GEO_IGNORE",
+                                             "FALSE") );
     }
 
     if( pszWKT != NULL || bPixelIsPoint )
@@ -2732,14 +2780,14 @@ CPLErr GTIFMemBufFromWktEx( const char *pszWKT, const double *padfGeoTransform,
 
         if( padfGeoTransform[2] == 0.0 && padfGeoTransform[4] == 0.0 )
         {
-            double	adfPixelScale[3], adfTiePoints[6];
+            double adfPixelScale[3], adfTiePoints[6];
 
             adfPixelScale[0] = padfGeoTransform[1];
             adfPixelScale[1] = fabs(padfGeoTransform[5]);
             adfPixelScale[2] = 0.0;
 
             TIFFSetField( hTIFF, TIFFTAG_GEOPIXELSCALE, 3, adfPixelScale );
-            
+
             adfTiePoints[0] = 0.0;
             adfTiePoints[1] = 0.0;
             adfTiePoints[2] = 0.0;
@@ -2757,7 +2805,7 @@ CPLErr GTIFMemBufFromWktEx( const char *pszWKT, const double *padfGeoTransform,
         }
         else
         {
-            double	adfMatrix[16];
+            double adfMatrix[16];
 
             memset(adfMatrix,0,sizeof(double) * 16);
 
@@ -2784,7 +2832,7 @@ CPLErr GTIFMemBufFromWktEx( const char *pszWKT, const double *padfGeoTransform,
 /* -------------------------------------------------------------------- */
     else if( nGCPCount > 0 )
     {
-        double	*padfTiePoints;
+        double *padfTiePoints;
 
         padfTiePoints = (double *) CPLMalloc(6*sizeof(double)*nGCPCount);
 
@@ -2801,7 +2849,7 @@ CPLErr GTIFMemBufFromWktEx( const char *pszWKT, const double *padfGeoTransform,
 
         TIFFSetField( hTIFF, TIFFTAG_GEOTIEPOINTS, 6*nGCPCount, padfTiePoints);
         CPLFree( padfTiePoints );
-    } 
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Write RPC                                                       */
@@ -2821,10 +2869,10 @@ CPLErr GTIFMemBufFromWktEx( const char *pszWKT, const double *padfGeoTransform,
     TIFFWriteDirectory( hTIFF );
 
     XTIFFClose( hTIFF );
-    VSIFCloseL(fpL);
+    CPL_IGNORE_RET_VAL(VSIFCloseL(fpL));
 
 /* -------------------------------------------------------------------- */
-/*      Read back from the memory buffer.  It would be preferrable      */
+/*      Read back from the memory buffer.  It would be preferable       */
 /*      to be able to "steal" the memory buffer, but there isn't        */
 /*      currently any support for this.                                 */
 /* -------------------------------------------------------------------- */
diff --git a/frmts/gtiff/gt_wkt_srs.h b/frmts/gtiff/gt_wkt_srs.h
index e1791c2..bb7c95e 100644
--- a/frmts/gtiff/gt_wkt_srs.h
+++ b/frmts/gtiff/gt_wkt_srs.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gt_wkt_srs.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: gt_wkt_srs.h 33806 2016-03-28 22:26:19Z goatbar $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Implements translation between GeoTIFF normalized projection
@@ -35,12 +35,21 @@
 
 #include "cpl_port.h"
 
-#include "geotiff.h"
 #include "geo_normalize.h"
+#include "geotiff.h"
 
 CPL_C_START
 char CPL_DLL *  GTIFGetOGISDefn( GTIF *, GTIFDefn * );
 int  CPL_DLL   GTIFSetFromOGISDefn( GTIF *, const char * );
+
+typedef enum
+{
+    GEOTIFF_KEYS_STANDARD,
+    GEOTIFF_KEYS_ESRI_PE
+} GTIFFKeysFlavorEnum;
+
+int GTIFSetFromOGISDefnEx( GTIF *, const char *, GTIFFKeysFlavorEnum );
+
 CPL_C_END
 
 #endif // GT_WKT_SRS_H_INCLUDED
diff --git a/frmts/gtiff/gt_wkt_srs_for_gdal.h b/frmts/gtiff/gt_wkt_srs_for_gdal.h
index 8f69103..0e864a4 100644
--- a/frmts/gtiff/gt_wkt_srs_for_gdal.h
+++ b/frmts/gtiff/gt_wkt_srs_for_gdal.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gt_wkt_srs_for_gdal.h 29049 2015-04-29 15:54:12Z rouault $
+ * $Id: gt_wkt_srs_for_gdal.h 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Read/Write in-memory GeoTIFF file
@@ -50,7 +50,7 @@ CPLErr CPL_DLL GTIFWktFromMemBuf( int nSize, unsigned char *pabyBuffer,
                           char **ppszWKT, double *padfGeoTransform,
                           int *pnGCPCount, GDAL_GCP **ppasGCPList );
 
-CPLErr GTIFWktFromMemBufEx( int nSize, unsigned char *pabyBuffer, 
+CPLErr GTIFWktFromMemBufEx( int nSize, unsigned char *pabyBuffer,
                             char **ppszWKT, double *padfGeoTransform,
                             int *pnGCPCount, GDAL_GCP **ppasGCPList,
                             int *pbPixelIsPoint, char*** ppapszRPCMD );
diff --git a/frmts/gtiff/gtiff.h b/frmts/gtiff/gtiff.h
index 4347bc4..1d21254 100644
--- a/frmts/gtiff/gtiff.h
+++ b/frmts/gtiff/gtiff.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gtiff.h 29049 2015-04-29 15:54:12Z rouault $
+ * $Id: gtiff.h 33806 2016-03-28 22:26:19Z goatbar $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  GDAL GeoTIFF support.
@@ -33,8 +33,8 @@
 
 #include "cpl_port.h"
 
-#include "tiffio.h"
 #include "gdal.h"
+#include "tiffio.h"
 
 CPL_C_START
 int    GTiffOneTimeInit();
@@ -42,6 +42,7 @@ void CPL_DLL LibgeotiffOneTimeInit();
 void   LibgeotiffOneTimeCleanupMutex();
 CPL_C_END
 
+void    GTIFFSetInExternalOvr(bool b);
 void    GTIFFGetOverviewBlockSize(int* pnBlockXSize, int* pnBlockYSize);
 void    GTIFFSetJpegQuality(GDALDatasetH hGTIFFDS, int nJpegQuality);
 int     GTIFFGetCompressionMethod(const char* pszValue, const char* pszVariableName);
diff --git a/frmts/gtiff/libgeotiff/GNUmakefile b/frmts/gtiff/libgeotiff/GNUmakefile
index d10dbb9..b267f05 100644
--- a/frmts/gtiff/libgeotiff/GNUmakefile
+++ b/frmts/gtiff/libgeotiff/GNUmakefile
@@ -15,11 +15,11 @@ OBJ	= \
 	geotiff_proj4.o \
 	geo_extra.o \
 	geo_trans.o \
-	geo_simpletags.o 
+	geo_simpletags.o
 
 O_OBJ	=	$(foreach file,$(OBJ),../../o/$(file))
 
-ALL_C_FLAGS	=	$(CPPFLAGS) $(CFLAGS) 
+ALL_C_FLAGS	=	$(CPPFLAGS) $(CFLAGS) -DDONT_DEPRECATE_SPRINTF
 
 ifeq ($(TIFF_SETTING),internal)
 ALL_C_FLAGS	:=	-I../libtiff $(ALL_C_FLAGS)
diff --git a/frmts/gtiff/libgeotiff/epsg_datum.inc b/frmts/gtiff/libgeotiff/epsg_datum.inc
index 198e78f..916ec7d 100644
--- a/frmts/gtiff/libgeotiff/epsg_datum.inc
+++ b/frmts/gtiff/libgeotiff/epsg_datum.inc
@@ -1,7 +1,7 @@
 /*
  *  EPSG/POSC Datum database -- GeoTIFF Rev. 0.2
  */
- 
+
 /* C database for Geotiff include files.   */
 /* the macro ValuePair() must be defined   */
 /* by the enclosing include file           */
diff --git a/frmts/gtiff/libgeotiff/epsg_units.inc b/frmts/gtiff/libgeotiff/epsg_units.inc
index fe1b5db..50110f5 100644
--- a/frmts/gtiff/libgeotiff/epsg_units.inc
+++ b/frmts/gtiff/libgeotiff/epsg_units.inc
@@ -1,7 +1,7 @@
 /*
  * Rev. 0.2 EPSG/POSC Units Database.
  */
- 
+
 #ifdef INCLUDE_OLD_CODES
 #include geo_units.inc
 #endif /* OLD Codes */
diff --git a/frmts/gtiff/libgeotiff/geo_config.h b/frmts/gtiff/libgeotiff/geo_config.h
index d773b71..394b348 100644
--- a/frmts/gtiff/libgeotiff/geo_config.h
+++ b/frmts/gtiff/libgeotiff/geo_config.h
@@ -3,11 +3,14 @@
 #define GEO_CONFIG_H
 
 #include "cpl_config.h"
+
+#ifndef COVERITY_SCAN
 #include "cpl_string.h"
 #ifdef sprintf
 #undef sprintf
 #endif
 #define sprintf CPLsprintf
+#endif
 
 #ifdef RENAME_INTERNAL_LIBTIFF_SYMBOLS
 #include "gdal_libtiff_symbol_rename.h"
diff --git a/frmts/gtiff/libgeotiff/geo_ctrans.inc b/frmts/gtiff/libgeotiff/geo_ctrans.inc
index 9bad7c1..ce3cb89 100644
--- a/frmts/gtiff/libgeotiff/geo_ctrans.inc
+++ b/frmts/gtiff/libgeotiff/geo_ctrans.inc
@@ -2,7 +2,7 @@
  * $Id: geo_ctrans.inc 2209 2012-05-09 01:34:58Z warmerdam $
  *
  * Project:  libgeotiff
- * Purpose:  GeoTIFF Projection Method codes. 
+ * Purpose:  GeoTIFF Projection Method codes.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -38,8 +38,8 @@
 /* by the enclosing include file           */
 
 /*
- *  Revised 12 Jul 1995   NDR -- changed South Oriented to a code 
- *  Revised 28 Sep 1995   NDR -- Added Rev. 1.0 aliases. 
+ *  Revised 12 Jul 1995   NDR -- changed South Oriented to a code
+ *  Revised 28 Sep 1995   NDR -- Added Rev. 1.0 aliases.
  */
 
 ValuePair(CT_TransverseMercator,	1)
diff --git a/frmts/gtiff/libgeotiff/geo_extra.c b/frmts/gtiff/libgeotiff/geo_extra.c
index b31aa7d..a2ee182 100644
--- a/frmts/gtiff/libgeotiff/geo_extra.c
+++ b/frmts/gtiff/libgeotiff/geo_extra.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: geo_extra.c 1568 2009-04-22 21:10:55Z warmerdam $
+ * $Id: geo_extra.c 2691 2015-12-06 21:54:31Z rouault $
  *
  * Project:  libgeotiff
  * Purpose:  Code to normalize a few common PCS values without use of CSV
@@ -37,7 +37,7 @@
 #include "geo_normalize.h"
 #include "geovalues.h"
 
-static int StatePlaneTable[] = 
+static const int StatePlaneTable[] =
 {
     PCS_NAD83_Alabama_East,		Proj_Alabama_CS83_East,
     PCS_NAD83_Alabama_West,		Proj_Alabama_CS83_West,
@@ -209,7 +209,7 @@ static int StatePlaneTable[] =
     PCS_NAD83_Wyoming_E_Cen,		Proj_Wyoming_CS83_East_Central,
     PCS_NAD83_Wyoming_W_Cen,		Proj_Wyoming_CS83_West_Central,
     PCS_NAD83_Wyoming_West,		Proj_Wyoming_CS83_West,
-    
+
     PCS_NAD83_Puerto_Rico_Virgin_Is,	Proj_Puerto_Rico_Virgin_Is,
 
     PCS_NAD27_Alabama_East,		Proj_Alabama_CS27_East,
@@ -387,7 +387,7 @@ static int StatePlaneTable[] =
     PCS_NAD27_Wyoming_E_Cen,		Proj_Wyoming_CS27_East_Central,
     PCS_NAD27_Wyoming_W_Cen,		Proj_Wyoming_CS27_West_Central,
     PCS_NAD27_Wyoming_West,		Proj_Wyoming_CS27_West,
-    
+
     PCS_NAD27_Puerto_Rico,		Proj_Puerto_Rico_CS27,
 
     KvUserDefined
@@ -459,7 +459,7 @@ int	GTIFMapSysToPCS( int MapSys, int Datum, int nZone )
             PCSCode = 2205;
     }
 
-    return( PCSCode );
+    return PCSCode;
 }
 
 /************************************************************************/
@@ -499,7 +499,7 @@ int	GTIFMapSysToProj( int MapSys, int nZone )
             ProjCode = 15303;
     }
 
-    return( ProjCode );
+    return ProjCode;
 }
 
 /************************************************************************/
@@ -534,7 +534,7 @@ int	GTIFMapSysToProj( int MapSys, int nZone )
  * This function is useful to recognise (most) UTM and State Plane coordinate
  * systems, even if CSV files aren't available to translate them automatically.
  * It is used as a fallback mechanism by GTIFGetDefn() for normalization when
- * CSV files aren't found. 
+ * CSV files aren't found.
  */
 
 int GTIFPCSToMapSys( int PCSCode, int * pDatum, int * pZone )
@@ -553,7 +553,7 @@ int GTIFPCSToMapSys( int PCSCode, int * pDatum, int * pZone )
 	Proj = MapSys_UTM_North;
 	nZone = PCSCode - PCS_NAD27_UTM_zone_3N + 3;
     }
-    else if( PCSCode >= PCS_NAD83_UTM_zone_3N 
+    else if( PCSCode >= PCS_NAD83_UTM_zone_3N
 	     && PCSCode <= PCS_NAD83_UTM_zone_23N )
     {
 	Datum = GCS_NAD83;
@@ -605,7 +605,7 @@ int GTIFPCSToMapSys( int PCSCode, int * pDatum, int * pZone )
 	Proj = MapSys_UTM_South;
 	nZone = PCSCode - PCS_WGS84_UTM_zone_1S + 1;
     }
-    else if( PCSCode >= PCS_SAD69_UTM_zone_18N 
+    else if( PCSCode >= PCS_SAD69_UTM_zone_18N
 	     && PCSCode <= PCS_SAD69_UTM_zone_22N )
     {
 	Datum = KvUserDefined;
@@ -642,7 +642,7 @@ int GTIFPCSToMapSys( int PCSCode, int * pDatum, int * pZone )
             Proj = MapSys_State_Plane_27;
 	    Datum = GCS_NAD27;
         }
-	
+
 	nZone = PCSCode - 10000;
 	if( Datum == GCS_NAD83 )
 	    nZone -= 30;
@@ -654,7 +654,7 @@ int GTIFPCSToMapSys( int PCSCode, int * pDatum, int * pZone )
     if( pZone != NULL )
         *pZone = nZone;
 
-    return( Proj );
+    return Proj;
 }
 
 /************************************************************************/
@@ -707,7 +707,7 @@ int GTIFProjToMapSys( int ProjCode, int * pZone )
     }
 
 /* -------------------------------------------------------------------- */
-/*      Handle State Plane.  I think there are some anomolies in        */
+/*      Handle State Plane.  I think there are some anomalies in        */
 /*      here, so this is a bit risky.                                   */
 /* -------------------------------------------------------------------- */
     else if( ProjCode >= 10101 && ProjCode <= 15299 )
@@ -723,10 +723,9 @@ int GTIFProjToMapSys( int ProjCode, int * pZone )
             nZone = ProjCode - 10000;
         }
     }
-    
+
     if( pZone != NULL )
         *pZone = nZone;
 
-    return( MapSys );
+    return MapSys;
 }
-
diff --git a/frmts/gtiff/libgeotiff/geo_free.c b/frmts/gtiff/libgeotiff/geo_free.c
index a43fcad..9810c5d 100644
--- a/frmts/gtiff/libgeotiff/geo_free.c
+++ b/frmts/gtiff/libgeotiff/geo_free.c
@@ -23,10 +23,10 @@
  **********************************************************************/
 
 /**
-  
+
 This function deallocates an existing GeoTIFF access handle previously
 created with GTIFNew().  If the handle was
-used to write GeoTIFF keys to the TIFF file, the 
+used to write GeoTIFF keys to the TIFF file, the
 GTIFWriteKeys() function should be used
 to flush results to the file before calling GTIFFree().  GTIFFree()
 should be called before XTIFFClose() is
@@ -37,13 +37,13 @@ called on the corresponding TIFF file handle.<p>
 void GTIFFree(GTIF* gtif)
 {
     int     i;
-	
+
     if (!gtif) return;
-	
+
     /* Free parameter arrays */
     if (gtif->gt_double) _GTIFFree (gtif->gt_double);
     if (gtif->gt_short) _GTIFFree (gtif->gt_short);
-	
+
     /* Free GeoKey arrays */
     if (gtif->gt_keys)
     {
@@ -57,6 +57,6 @@ void GTIFFree(GTIF* gtif)
         _GTIFFree (gtif->gt_keys);
     }
     if (gtif->gt_keyindex) _GTIFFree (gtif->gt_keyindex);
-	
+
     _GTIFFree (gtif);
 }
diff --git a/frmts/gtiff/libgeotiff/geo_get.c b/frmts/gtiff/libgeotiff/geo_get.c
index f027bd3..801c70d 100644
--- a/frmts/gtiff/libgeotiff/geo_get.c
+++ b/frmts/gtiff/libgeotiff/geo_get.c
@@ -37,19 +37,19 @@ void GTIFDirectoryInfo(GTIF *gtif, int version[3], int *keycount)
 
 int GTIFKeyInfo(GTIF *gtif, geokey_t key, int *size, tagtype_t* type)
 {
-        int index = gtif->gt_keyindex[ key ];
+        int nIndex = gtif->gt_keyindex[ key ];
         GeoKey *keyptr;
 
-        if (!index) return 0;
+        if (!nIndex) return 0;
 
-        keyptr = gtif->gt_keys + index;
+        keyptr = gtif->gt_keys + nIndex;
         if (size) *size = (int) keyptr->gk_size;
         if (type) *type = keyptr->gk_type;
 
-        return keyptr->gk_count;
+        return (int)keyptr->gk_count;
 }
 
-/** 
+/**
 
 This function reads the value of a single GeoKey from a GeoTIFF file.
 
@@ -138,8 +138,8 @@ ValuePair(  ProjScaleAtCenterGeoKey,	3093)     -- ratio   --
 ValuePair(  ProjAzimuthAngleGeoKey,	3094)     -- GeogAzimuthUnit --
 ValuePair(  ProjStraightVertPoleLongGeoKey,	3095)     -- GeogAngularUnit --
 
- 6.2.4 Vertical CS Keys 
-   
+ 6.2.4 Vertical CS Keys
+
 ValuePair(  VerticalCSTypeGeoKey,	4096)  -- Section 6.3.4.1 codes   --
 ValuePair(  VerticalCitationGeoKey,	4097)  -- documentation --
 ValuePair(  VerticalDatumGeoKey,	4098)  -- Section 6.3.4.2 codes   --
@@ -147,7 +147,7 @@ ValuePair(  VerticalUnitsGeoKey,	4099)  -- Section 6.3.1 (.x) codes   --
 </pre>
 */
 
-int GTIFKeyGet(GTIF *gtif, geokey_t thekey, void *val, int index, int count)
+int GTIFKeyGet(GTIF *gtif, geokey_t thekey, void *val, int nIndex, int count)
 {
         int kindex = gtif->gt_keyindex[ thekey ];
         GeoKey *key;
@@ -158,16 +158,16 @@ int GTIFKeyGet(GTIF *gtif, geokey_t thekey, void *val, int index, int count)
         if (!kindex) return 0;
 
         key = gtif->gt_keys+kindex;
-        if (!count) count = key->gk_count - index;
+        if (!count) count = (int) (key->gk_count - nIndex);
         if (count <=0) return 0;
-        if (count > key->gk_count) count = key->gk_count;
+        if (count > key->gk_count) count = (int) key->gk_count;
         size = key->gk_size;
         type = key->gk_type;
 
         if (count==1 && type==TYPE_SHORT) data = (char *)&key->gk_data;
         else data = key->gk_data;
 
-        _GTIFmemcpy( val, data + index*size, count*size );
+        _GTIFmemcpy( val, data + nIndex*size, count*size );
 
         if (type==TYPE_ASCII)
            ((char *)val)[count-1] = '\0'; /* replace last char with NULL */
diff --git a/frmts/gtiff/libgeotiff/geo_keyp.h b/frmts/gtiff/libgeotiff/geo_keyp.h
index 01091de..02a1882 100644
--- a/frmts/gtiff/libgeotiff/geo_keyp.h
+++ b/frmts/gtiff/libgeotiff/geo_keyp.h
@@ -10,8 +10,8 @@
  *  notice accompanies any products derived therefrom.
  **********************************************************************/
 
-#ifndef __geo_keyp_h_
-#define __geo_keyp_h_
+#ifndef LIBGEOTIFF_GEO_KEYP_H_
+#define LIBGEOTIFF_GEO_KEYP_H_
 
 #include <stdlib.h> /* for size_t */
 
@@ -72,22 +72,22 @@ struct gtiff {
    tiff_t*    gt_tif;      /* TIFF file descriptor  */
    struct _TIFFMethod gt_methods;  /* TIFF i/o methods      */
    int        gt_flags;    /* file flags            */
-   
+
    pinfo_t    gt_version;  /* GeoTIFF Version       */
    pinfo_t    gt_rev_major;/* GeoKey Key Revision   */
    pinfo_t    gt_rev_minor;/* GeoKey Code Revision  */
-   
+
    int        gt_num_keys; /* number of keys        */
    GeoKey*    gt_keys;     /* array of keys         */
    int*       gt_keyindex; /* index of a key, if set*/
    int        gt_keymin;   /* smallest key set      */
    int        gt_keymax;   /* largest key set       */
-   
+
    pinfo_t*   gt_short;    /* array of SHORT vals   */
    double*    gt_double;   /* array of DOUBLE vals  */
    int        gt_nshorts;  /* number of SHORT vals  */
    int        gt_ndoubles; /* number of DOUBLE vals */
-};  
+};
 
 typedef enum {
 	FLAG_FILE_OPEN=1,
@@ -98,5 +98,4 @@ typedef enum {
 #define MAX_KEYS 100         /* maximum keys in a file  */
 #define MAX_VALUES 1000      /* maximum values in a tag */
 
-#endif /* __geo_keyp_h_ */
-
+#endif /* LIBGEOTIFF_GEO_KEYP_H_ */
diff --git a/frmts/gtiff/libgeotiff/geo_names.c b/frmts/gtiff/libgeotiff/geo_names.c
index 4c73f49..f44b51a 100644
--- a/frmts/gtiff/libgeotiff/geo_names.c
+++ b/frmts/gtiff/libgeotiff/geo_names.c
@@ -1,8 +1,8 @@
 /*
  * geo_names.c
  *
- *  This encapsulates all of the value-naming mechanism of 
- *  libgeotiff. 
+ *  This encapsulates all of the value-naming mechanism of
+ *  libgeotiff.
  *
  *  Written By: Niles Ritter
  *
@@ -17,7 +17,7 @@
 #include "geonames.h"
 #include "geo_tiffp.h" /* for tag names */
 
-static KeyInfo _formatInfo[] =  {
+static const KeyInfo _formatInfo[] =  {
    {TYPE_BYTE,    "Byte"},
    {TYPE_SHORT,   "Short"},
    {TYPE_LONG,    "Long"},
@@ -32,7 +32,7 @@ static KeyInfo _formatInfo[] =  {
     END_LIST
 };
 
-static KeyInfo _tagInfo[] =  {
+static const KeyInfo _tagInfo[] =  {
     {GTIFF_PIXELSCALE,  "ModelPixelScaleTag"},
     {GTIFF_TRANSMATRIX, "ModelTransformationTag"},
     {GTIFF_TIEPOINTS,   "ModelTiepointTag"},
@@ -41,10 +41,10 @@ static KeyInfo _tagInfo[] =  {
     END_LIST
 };
 
-static char *FindName(KeyInfo *info,int key)
+static char *FindName(const KeyInfo *info,int key)
 {
    static char errmsg[80];
-   
+
    while (info->ki_key>=0 && info->ki_key != key) info++;
 
    if (info->ki_key<0)
@@ -72,15 +72,15 @@ char *GTIFTagName(int tag)
 
 char *GTIFValueName(geokey_t key, int value)
 {
-   KeyInfo *info;
-   
+   const KeyInfo *info;
+
    switch (key)
    {
 	/* All codes using linear/angular/whatever units */
-	case GeogLinearUnitsGeoKey: 
-	case ProjLinearUnitsGeoKey: 
-	case GeogAngularUnitsGeoKey: 
-	case GeogAzimuthUnitsGeoKey: 
+	case GeogLinearUnitsGeoKey:
+	case ProjLinearUnitsGeoKey:
+	case GeogAngularUnitsGeoKey:
+	case GeogAzimuthUnitsGeoKey:
     case VerticalUnitsGeoKey:
 		                      info=_geounitsValue; break;
 
@@ -100,16 +100,16 @@ char *GTIFValueName(geokey_t key, int value)
 	/* And if all else fails... */
    	default:                      info = _csdefaultValue;break;
    }
-   
+
    return FindName( info,value);
 }
 
-/* 
- * Inverse Utilities (name->code) 
+/*
+ * Inverse Utilities (name->code)
  */
 
 
-static int FindCode(KeyInfo *info,char *key)
+static int FindCode(const KeyInfo *info,char *key)
 {
    while (info->ki_key>=0 && strcmp(info->ki_name,key) ) info++;
 
@@ -149,16 +149,16 @@ int GTIFTagCode(char *tag)
  */
 int GTIFValueCode(geokey_t key, char *name)
 {
-   KeyInfo *info;
-   
+   const KeyInfo *info;
+
    switch (key)
    {
 	/* All codes using linear/angular/whatever units */
-	case GeogLinearUnitsGeoKey: 
-	case ProjLinearUnitsGeoKey: 
-	case GeogAngularUnitsGeoKey: 
+	case GeogLinearUnitsGeoKey:
+	case ProjLinearUnitsGeoKey:
+	case GeogAngularUnitsGeoKey:
 	case GeogAzimuthUnitsGeoKey:
-    case VerticalUnitsGeoKey: 
+    case VerticalUnitsGeoKey:
 		                      info=_geounitsValue; break;
 
    	/* put other key-dependent lists here */
@@ -177,7 +177,6 @@ int GTIFValueCode(geokey_t key, char *name)
 	/* And if all else fails... */
    	default:                      info = _csdefaultValue;break;
    }
-   
+
    return FindCode( info,name);
 }
-
diff --git a/frmts/gtiff/libgeotiff/geo_new.c b/frmts/gtiff/libgeotiff/geo_new.c
index af02bee..9a4608e 100644
--- a/frmts/gtiff/libgeotiff/geo_new.c
+++ b/frmts/gtiff/libgeotiff/geo_new.c
@@ -17,7 +17,7 @@
 #include "geotiffio.h"   /* public interface        */
 #include "geo_tiffp.h" /* external TIFF interface */
 #include "geo_keyp.h"  /* private interface       */
-#include "geo_simpletags.h" 
+#include "geo_simpletags.h"
 
 /* private local routines */
 static int ReadKey(GTIF* gt, TempKeyData* tempData,
@@ -32,16 +32,16 @@ static int ReadKey(GTIF* gt, TempKeyData* tempData,
 
 
 /**
- * Given an open TIFF file, look for GTIF keys and 
+ * Given an open TIFF file, look for GTIF keys and
  *  values and return GTIF structure.
 
 This function creates a GeoTIFF information interpretation handle
-(GTIF *) based on a passed in TIFF handle originally from 
-XTIFFOpen().  Even though the argument 
+(GTIF *) based on a passed in TIFF handle originally from
+XTIFFOpen().  Even though the argument
 (<b>tif</b>) is shown as type <tt>void *</tt>, it is really normally
 of type <tt>TIFF *</tt>.<p>
 
-The returned GTIF handle can be used to read or write GeoTIFF tags 
+The returned GTIF handle can be used to read or write GeoTIFF tags
 using the various GTIF functions.  The handle should be destroyed using
 GTIFFree() before the file is closed with TIFFClose().<p>
 
@@ -80,7 +80,7 @@ GTIF *GTIFNewSimpleTags( void *tif )
 GTIF* GTIFNewWithMethods(void *tif, TIFFMethod* methods)
 {
     GTIF* gt=(GTIF*)0;
-    int count,bufcount,index;
+    int count,bufcount,nIndex;
     GeoKey *keyptr;
     pinfo_t *data;
     KeyEntry *entptr;
@@ -89,19 +89,19 @@ GTIF* GTIFNewWithMethods(void *tif, TIFFMethod* methods)
 
     memset( &tempData, 0, sizeof(tempData) );
     gt = (GTIF*)_GTIFcalloc( sizeof(GTIF));
-    if (!gt) goto failure;	
-	
+    if (!gt) goto failure;
+
     /* install TIFF file and I/O methods */
     gt->gt_tif = (tiff_t *)tif;
     memcpy( &gt->gt_methods, methods, sizeof(TIFFMethod) );
 
     /* since this is an array, GTIF will allocate the memory */
-    if ( tif == NULL 
+    if ( tif == NULL
          || !(gt->gt_methods.get)(tif, GTIFF_GEOKEYDIRECTORY, &gt->gt_nshorts, &data ))
     {
         /* No ProjectionInfo, create a blank one */
         data=(pinfo_t*)_GTIFcalloc((4+MAX_VALUES)*sizeof(pinfo_t));
-        if (!data) goto failure;	
+        if (!data) goto failure;
         header = (KeyHeader *)data;
         header->hdr_version = GvCurrentVersion;
         header->hdr_rev_major = GvCurrentRevision;
@@ -115,18 +115,18 @@ GTIF* GTIFNewWithMethods(void *tif, TIFFMethod* methods)
     }
     gt->gt_short = data;
     header = (KeyHeader *)data;
-	
+
     if (header->hdr_version > GvCurrentVersion) goto failure;
     if (header->hdr_rev_major > GvCurrentRevision)
     {
         /* issue warning */
     }
-	
+
     /* If we got here, then the geokey can be parsed */
     count = header->hdr_num_keys;
 
-    if (count * sizeof(KeyEntry) >= (4 + MAX_VALUES) * sizeof(pinfo_t)) 
-        goto failure; 
+    if (count * sizeof(KeyEntry) >= (4 + MAX_VALUES) * sizeof(pinfo_t))
+        goto failure;
 
     gt->gt_num_keys = count;
     gt->gt_version  = header->hdr_version;
@@ -141,7 +141,7 @@ GTIF* GTIFNewWithMethods(void *tif, TIFFMethod* methods)
                                  &gt->gt_ndoubles, &gt->gt_double ))
     {
         gt->gt_double=(double*)_GTIFcalloc(MAX_VALUES*sizeof(double));
-        if (!gt->gt_double) goto failure;	
+        if (!gt->gt_double) goto failure;
     }
     else
     {
@@ -160,7 +160,7 @@ GTIF* GTIFNewWithMethods(void *tif, TIFFMethod* methods)
     else
     {
         /* last NULL doesn't count; "|" used for delimiter */
-        if( tempData.tk_asciiParamsLength > 0 
+        if( tempData.tk_asciiParamsLength > 0
             && tempData.tk_asciiParams[tempData.tk_asciiParamsLength-1] == '\0')
         {
             --tempData.tk_asciiParamsLength;
@@ -172,30 +172,30 @@ GTIF* GTIFNewWithMethods(void *tif, TIFFMethod* methods)
     if (!gt->gt_keys) goto failure;
     gt->gt_keyindex = (int *)_GTIFcalloc( sizeof(int)*(MAX_KEYINDEX+1));
     if (!gt->gt_keyindex) goto failure;
-	
+
     /*  Loop to get all GeoKeys */
     entptr = ((KeyEntry *)data) + 1;
     keyptr = gt->gt_keys;
     gt->gt_keymin = MAX_KEYINDEX;
     gt->gt_keymax = 0;
-    for (index=1; index<=count; index++,entptr++)
+    for (nIndex=1; nIndex<=count; nIndex++,entptr++)
     {
         if (!ReadKey(gt, &tempData, entptr, ++keyptr))
             goto failure;
-			
+
         /* Set up the index (start at 1, since 0=unset) */
-        gt->gt_keyindex[entptr->ent_key] = index;		
+        gt->gt_keyindex[entptr->ent_key] = nIndex;
     }
 
     if( tempData.tk_asciiParams != NULL )
         _GTIFFree( tempData.tk_asciiParams );
-	
+
     return gt;
-	
+
   failure:
     /* Notify of error */
     if( tempData.tk_asciiParams != NULL )
-        _GTIFFree( tempData.tk_asciiParams );    
+        _GTIFFree( tempData.tk_asciiParams );
     GTIFFree (gt);
     return (GTIF *)0;
 }
@@ -237,20 +237,22 @@ static int ReadKey(GTIF* gt, TempKeyData* tempData,
         case GTIFF_GEOKEYDIRECTORY:
             keyptr->gk_data = (char *)(gt->gt_short+offset);
             if (gt->gt_nshorts < offset+count)
-                gt->gt_nshorts = offset+count;
+                return 0;
             break;
         case GTIFF_DOUBLEPARAMS:
             keyptr->gk_data = (char *)(gt->gt_double+offset);
             if (gt->gt_ndoubles < offset+count)
-                gt->gt_ndoubles = offset+count;
+                return 0;
             break;
         case GTIFF_ASCIIPARAMS:
-            if( offset + count == tempData->tk_asciiParamsLength + 1 
+            if( tempData->tk_asciiParams == NULL )
+                return 0;
+            if( offset + count == tempData->tk_asciiParamsLength + 1
                 && count > 0 )
             {
-                /* some vendors seem to feel they should not use the 
+                /* some vendors seem to feel they should not use the
                    terminating '|' char, but do include a terminating '\0'
-                   which we lose in the low level reading code.  
+                   which we lose in the low level reading code.
                    If this is the case, drop the extra character */
                 count--;
             }
@@ -261,7 +263,7 @@ static int ReadKey(GTIF* gt, TempKeyData* tempData,
                 /* issue warning... if we could */
             }
             else if (offset + count > tempData->tk_asciiParamsLength)
-                return (0);
+                return 0;
 
             keyptr->gk_count = MAX(1,count+1);
             keyptr->gk_data = (char *) _GTIFcalloc (keyptr->gk_count);
@@ -280,6 +282,6 @@ static int ReadKey(GTIF* gt, TempKeyData* tempData,
             return 0; /* failure */
     }
     keyptr->gk_size = _gtiff_size[keyptr->gk_type];
-	
+
     return 1; /* success */
 }
diff --git a/frmts/gtiff/libgeotiff/geo_normalize.c b/frmts/gtiff/libgeotiff/geo_normalize.c
index f88b5af..c3f954d 100644
--- a/frmts/gtiff/libgeotiff/geo_normalize.c
+++ b/frmts/gtiff/libgeotiff/geo_normalize.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: geo_normalize.c 2595 2014-12-27 22:59:32Z rouault $
+ * $Id: geo_normalize.c 2712 2016-01-11 11:36:59Z rouault $
  *
  * Project:  libgeotiff
  * Purpose:  Code to normalize PCS and other composite codes in a GeoTIFF file.
@@ -26,7 +26,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
- 
+
 #include "cpl_serv.h"
 #include "geo_tiffp.h"
 #include "geovalues.h"
@@ -36,8 +36,8 @@
 #  define KvUserDefined 32767
 #endif
 
-#ifndef PI
-#  define PI 3.14159265358979323846
+#ifndef M_PI
+#  define M_PI 3.14159265358979323846
 #endif
 
 /* EPSG Codes for projection parameters.  Unfortunately, these bear no
@@ -75,12 +75,35 @@
 
 #define CT_Ext_Mercator_2SP     -CT_Mercator
 
+#ifndef CPL_INLINE
+#  if (defined(__GNUC__) && !defined(__NO_INLINE__)) || defined(_MSC_VER)
+#    define HAS_CPL_INLINE  1
+#    define CPL_INLINE __inline
+#  elif defined(__SUNPRO_CC)
+#    define HAS_CPL_INLINE  1
+#    define CPL_INLINE inline
+#  else
+#    define CPL_INLINE
+#  endif
+#endif
+
+#ifndef CPL_UNUSED
+#if defined(__GNUC__) && __GNUC__ >= 4
+#  define CPL_UNUSED __attribute((__unused__))
+#else
+/* TODO: add cases for other compilers */
+#  define CPL_UNUSED
+#endif
+#endif
+
+CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused) {}
+
 /************************************************************************/
 /*                           GTIFGetPCSInfo()                           */
 /************************************************************************/
 
-int GTIFGetPCSInfo( int nPCSCode, char **ppszEPSGName, 
-                    short *pnProjOp, short *pnUOMLengthCode, 
+int GTIFGetPCSInfo( int nPCSCode, char **ppszEPSGName,
+                    short *pnProjOp, short *pnUOMLengthCode,
                     short *pnGeogCS )
 
 {
@@ -142,7 +165,7 @@ int GTIFGetPCSInfo( int nPCSCode, char **ppszEPSGName,
     if( papszRecord == NULL )
     {
         pszFilename = CSVFilename( "pcs.csv" );
-        
+
         sprintf( szSearchKey, "%d", nPCSCode );
         papszRecord = CSVScanFileByName( pszFilename, "COORD_REF_SYS_CODE",
                                          szSearchKey, CC_Integer );
@@ -203,7 +226,7 @@ int GTIFGetPCSInfo( int nPCSCode, char **ppszEPSGName,
         if( atoi(pszValue) > 0 )
             *pnProjOp = (short) atoi(pszValue);
         else
-            *pnUOMLengthCode = KvUserDefined;
+            *pnProjOp = KvUserDefined;
     }
 
 /* -------------------------------------------------------------------- */
@@ -228,7 +251,7 @@ int GTIFGetPCSInfo( int nPCSCode, char **ppszEPSGName,
 /************************************************************************/
 /*                           GTIFAngleToDD()                            */
 /*                                                                      */
-/*      Convert a numeric angle to decimal degress.                     */
+/*      Convert a numeric angle to decimal degrees.                     */
 /************************************************************************/
 
 double GTIFAngleToDD( double dfAngle, int nUOMAngle )
@@ -244,12 +267,12 @@ double GTIFAngleToDD( double dfAngle, int nUOMAngle )
     else if ( nUOMAngle != KvUserDefined )
     {
         double		dfInDegrees = 1.0;
-        
+
         GTIFGetUOMAngleInfo( nUOMAngle, NULL, &dfInDegrees );
         dfAngle = dfAngle * dfInDegrees;
     }
 
-    return( dfAngle );
+    return dfAngle;
 }
 
 /************************************************************************/
@@ -262,11 +285,11 @@ double GTIFAngleStringToDD( const char * pszAngle, int nUOMAngle )
 
 {
     double	dfAngle;
-    
+
     if( nUOMAngle == 9110 )		/* DDD.MMSSsss */
     {
         char	*pszDecimal;
-        
+
         dfAngle = ABS(atoi(pszAngle));
         pszDecimal = strchr(pszAngle,'.');
         if( pszDecimal != NULL && strlen(pszDecimal) > 1 )
@@ -279,7 +302,7 @@ double GTIFAngleStringToDD( const char * pszAngle, int nUOMAngle )
                 szMinutes[1] = pszDecimal[2];
             else
                 szMinutes[1] = '0';
-            
+
             szMinutes[2] = '\0';
             dfAngle += atoi(szMinutes) / 60.0;
 
@@ -311,7 +334,7 @@ double GTIFAngleStringToDD( const char * pszAngle, int nUOMAngle )
     }
     else if( nUOMAngle == 9101 )			/* radians */
     {
-        dfAngle = 180 * (GTIFAtof(pszAngle ) / PI);
+        dfAngle = 180 * (GTIFAtof(pszAngle ) / M_PI);
     }
     else if( nUOMAngle == 9103 )			/* arc-minute */
     {
@@ -321,15 +344,15 @@ double GTIFAngleStringToDD( const char * pszAngle, int nUOMAngle )
     {
         dfAngle = GTIFAtof(pszAngle) / 3600;
     }
-    else /* decimal degrees ... some cases missing but seeminly never used */
+    else /* decimal degrees ... some cases missing but seemingly never used */
     {
         CPLAssert( nUOMAngle == 9102 || nUOMAngle == KvUserDefined
                    || nUOMAngle == 0 );
-        
+
         dfAngle = GTIFAtof(pszAngle );
     }
 
-    return( dfAngle );
+    return dfAngle;
 }
 
 /************************************************************************/
@@ -352,7 +375,7 @@ int GTIFGetGCSInfo( int nGCSCode, char ** ppszName,
 /* -------------------------------------------------------------------- */
     const char * pszName = NULL;
     nPM = PM_Greenwich;
-    nUOMAngle = Angular_DMS_Hemisphere; 
+    nUOMAngle = Angular_DMS_Hemisphere;
     if( nGCSCode == GCS_NAD27 )
     {
         nDatum = Datum_North_American_Datum_1927;
@@ -398,7 +421,7 @@ int GTIFGetGCSInfo( int nGCSCode, char ** ppszName,
     pszFilename = CSVFilename("gcs.override.csv");
     sprintf( szSearchKey, "%d", nGCSCode );
     nDatum = atoi(CSVGetField( pszFilename,
-                               "COORD_REF_SYS_CODE", szSearchKey, 
+                               "COORD_REF_SYS_CODE", szSearchKey,
                                CC_Integer, "DATUM_CODE" ) );
 
     if( nDatum < 1 )
@@ -406,7 +429,7 @@ int GTIFGetGCSInfo( int nGCSCode, char ** ppszName,
         pszFilename = CSVFilename("gcs.csv");
         sprintf( szSearchKey, "%d", nGCSCode );
         nDatum = atoi(CSVGetField( pszFilename,
-                                   "COORD_REF_SYS_CODE", szSearchKey, 
+                                   "COORD_REF_SYS_CODE", szSearchKey,
                                    CC_Integer, "DATUM_CODE" ) );
     }
 
@@ -427,7 +450,7 @@ int GTIFGetGCSInfo( int nGCSCode, char ** ppszName,
 
     if( pnDatum != NULL )
         *pnDatum = (short) nDatum;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Get the PM.                                                     */
 /* -------------------------------------------------------------------- */
@@ -464,8 +487,8 @@ int GTIFGetGCSInfo( int nGCSCode, char ** ppszName,
             CPLStrdup(CSVGetField( pszFilename,
                                    "COORD_REF_SYS_CODE",szSearchKey,CC_Integer,
                                    "COORD_REF_SYS_NAME" ));
-    
-    return( TRUE );
+
+    return TRUE;
 }
 
 /************************************************************************/
@@ -489,7 +512,7 @@ int GTIFGetEllipsoidInfo( int nEllipseCode, char ** ppszName,
 /* -------------------------------------------------------------------- */
     double     dfInvFlattening=0.0, dfSemiMinor=0.0;
     const char *pszName = NULL;
-    
+
     if( nEllipseCode == Ellipse_Clarke_1866 )
     {
         pszName = "Clarke 1866";
@@ -567,10 +590,10 @@ int GTIFGetEllipsoidInfo( int nEllipseCode, char ** ppszName,
     GTIFGetUOMLengthInfo( nUOMLength, NULL, &dfToMeters );
 
     dfSemiMajor *= dfToMeters;
-    
+
     if( pdfSemiMajor != NULL )
         *pdfSemiMajor = dfSemiMajor;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Get the semi-minor if requested.  If the Semi-minor axis        */
 /*      isn't available, compute it based on the inverse flattening.    */
@@ -584,9 +607,7 @@ int GTIFGetEllipsoidInfo( int nEllipseCode, char ** ppszName,
 
         if( *pdfSemiMinor == 0.0 )
         {
-            double	dfInvFlattening;
-            
-            dfInvFlattening = 
+            dfInvFlattening =
                 GTIFAtof(CSVGetField( CSVFilename("ellipsoid.csv"),
                                   "ELLIPSOID_CODE", szSearchKey, CC_Integer,
                                   "INV_FLATTENING" ));
@@ -602,8 +623,8 @@ int GTIFGetEllipsoidInfo( int nEllipseCode, char ** ppszName,
             CPLStrdup(CSVGetField( CSVFilename("ellipsoid.csv"),
                                    "ELLIPSOID_CODE", szSearchKey, CC_Integer,
                                    "ELLIPSOID_NAME" ));
-    
-    return( TRUE );
+
+    return TRUE;
 }
 
 /************************************************************************/
@@ -639,7 +660,7 @@ int GTIFGetPMInfo( int nPMCode, char ** ppszName, double *pdfOffset )
     sprintf( szSearchKey, "%d", nPMCode );
 
     nUOMAngle =
-        atoi(CSVGetField( pszFilename, 
+        atoi(CSVGetField( pszFilename,
                           "PRIME_MERIDIAN_CODE", szSearchKey, CC_Integer,
                           "UOM_CODE" ) );
     if( nUOMAngle < 1 )
@@ -664,23 +685,23 @@ int GTIFGetPMInfo( int nPMCode, char ** ppszName, double *pdfOffset )
     {
         *pdfOffset =
             GTIFAngleStringToDD(
-                CSVGetField( pszFilename, 
+                CSVGetField( pszFilename,
                              "PRIME_MERIDIAN_CODE", szSearchKey, CC_Integer,
                              "GREENWICH_LONGITUDE" ),
                 nUOMAngle );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Get the name, if requested.                                     */
 /* -------------------------------------------------------------------- */
     if( ppszName != NULL )
         *ppszName =
             CPLStrdup(
-                CSVGetField( pszFilename, 
+                CSVGetField( pszFilename,
                              "PRIME_MERIDIAN_CODE", szSearchKey, CC_Integer,
                              "PRIME_MERIDIAN_NAME" ));
-    
-    return( TRUE );
+
+    return TRUE;
 }
 
 /************************************************************************/
@@ -744,7 +765,7 @@ int GTIFGetDatumInfo( int nDatumCode, char ** ppszName, short * pnEllipsoid )
         {
             pszFilename = CSVFilename( "gdal_datum.csv" );
             VSIFClose( fp );
-        }        
+        }
     }
     else
         VSIFClose( fp );
@@ -786,8 +807,8 @@ int GTIFGetDatumInfo( int nDatumCode, char ** ppszName, short * pnEllipsoid )
             CPLStrdup(CSVGetField( pszFilename,
                                    "DATUM_CODE", szSearchKey, CC_Integer,
                                    "DATUM_NAME" ));
-    
-    return( TRUE );
+
+    return TRUE;
 }
 
 
@@ -865,7 +886,7 @@ int GTIFGetUOMLengthInfo( int nUOMLengthCode,
                                         "UNIT_OF_MEAS_NAME" );
         *ppszUOMName = CPLStrdup( CSLGetField(papszUnitsRecord, iNameField) );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Get the A and B factor fields, and create the multiplicative    */
 /*      factor.                                                         */
@@ -873,7 +894,7 @@ int GTIFGetUOMLengthInfo( int nUOMLengthCode,
     if( pdfInMeters != NULL )
     {
         int	iBFactorField, iCFactorField;
-        
+
         iBFactorField = CSVGetFileFieldId( pszFilename, "FACTOR_B" );
         iCFactorField = CSVGetFileFieldId( pszFilename, "FACTOR_C" );
 
@@ -883,8 +904,8 @@ int GTIFGetUOMLengthInfo( int nUOMLengthCode,
         else
             *pdfInMeters = 0.0;
     }
-    
-    return( TRUE );
+
+    return TRUE;
 }
 
 /************************************************************************/
@@ -905,7 +926,7 @@ int GTIFGetUOMAngleInfo( int nUOMAngleCode,
     {
       case 9101:
         pszUOMName = "radian";
-        dfInDegrees = 180.0 / PI;
+        dfInDegrees = 180.0 / M_PI;
         break;
 
       case 9102:
@@ -939,21 +960,18 @@ int GTIFGetUOMAngleInfo( int nUOMAngleCode,
 
       case 9109:
         pszUOMName = "microradian";
-        dfInDegrees = 180.0 / (PI * 1000000.0);
+        dfInDegrees = 180.0 / (M_PI * 1000000.0);
         break;
 
       default:
         break;
     }
-    
+
     if (pszUOMName)
     {
         if( ppszUOMName != NULL )
         {
-            if( pszUOMName != NULL )
-                *ppszUOMName = CPLStrdup( pszUOMName );
-            else
-                *ppszUOMName = NULL;
+            *ppszUOMName = CPLStrdup( pszUOMName );
         }
 
         if( pdfInDegrees != NULL )
@@ -977,13 +995,13 @@ int GTIFGetUOMAngleInfo( int nUOMAngleCode,
     if( pszUOMName != NULL )
     {
         double dfFactorB, dfFactorC, dfInRadians;
-        
-        dfFactorB = 
+
+        dfFactorB =
             GTIFAtof(CSVGetField( pszFilename,
                               "UOM_CODE", szSearchKey, CC_Integer,
                               "FACTOR_B" ));
-        
-        dfFactorC = 
+
+        dfFactorC =
             GTIFAtof(CSVGetField( pszFilename,
                               "UOM_CODE", szSearchKey, CC_Integer,
                               "FACTOR_C" ));
@@ -991,8 +1009,11 @@ int GTIFGetUOMAngleInfo( int nUOMAngleCode,
         if( dfFactorC != 0.0 )
         {
             dfInRadians = (dfFactorB / dfFactorC);
-            dfInDegrees = dfInRadians * 180.0 / PI;
+            dfInDegrees = dfInRadians * 180.0 / M_PI;
         }
+
+        if( ppszUOMName != NULL )
+            *ppszUOMName = CPLStrdup( pszUOMName );
     }
     else
     {
@@ -1002,18 +1023,11 @@ int GTIFGetUOMAngleInfo( int nUOMAngleCode,
 /* -------------------------------------------------------------------- */
 /*      Return to caller.                                               */
 /* -------------------------------------------------------------------- */
-    if( ppszUOMName != NULL )
-    {
-        if( pszUOMName != NULL )
-            *ppszUOMName = CPLStrdup( pszUOMName );
-        else
-            *ppszUOMName = NULL;
-    }
 
     if( pdfInDegrees != NULL )
         *pdfInDegrees = dfInDegrees;
 
-    return( TRUE );
+    return TRUE;
 }
 
 /************************************************************************/
@@ -1027,106 +1041,104 @@ static int EPSGProjMethodToCTProjMethod( int nEPSG, int bReturnExtendedCTCode )
 
 {
     /* see trf_method.csv for list of EPSG codes */
-    
+
     switch( nEPSG )
     {
       case 9801:
-        return( CT_LambertConfConic_1SP );
+        return CT_LambertConfConic_1SP;
 
       case 9802:
-        return( CT_LambertConfConic_2SP );
+        return CT_LambertConfConic_2SP;
 
       case 9803:
-        return( CT_LambertConfConic_2SP ); /* Belgian variant not supported */
+        return CT_LambertConfConic_2SP; /* Belgian variant not supported */
 
       case 9804:
-        return( CT_Mercator );  /* 1SP and 2SP not differentiated */
+        return CT_Mercator;  /* 1SP and 2SP not differentiated */
 
       case 9805:
         if( bReturnExtendedCTCode )
-            return( CT_Ext_Mercator_2SP );
+            return CT_Ext_Mercator_2SP;
         else
-            return( CT_Mercator );  /* 1SP and 2SP not differentiated */
-        
+            return CT_Mercator;  /* 1SP and 2SP not differentiated */
+
       /* Mercator 1SP (Spherical) For EPSG:3785 */
       case 9841:
-        return( CT_Mercator );  /* 1SP and 2SP not differentiated */
-        
+        return CT_Mercator;  /* 1SP and 2SP not differentiated */
+
       /* Google Mercator For EPSG:3857 */
       case 1024:
-        return( CT_Mercator );  /* 1SP and 2SP not differentiated */
+        return CT_Mercator;  /* 1SP and 2SP not differentiated */
 
       case 9806:
-        return( CT_CassiniSoldner );
+        return CT_CassiniSoldner;
 
       case 9807:
-        return( CT_TransverseMercator );
+        return CT_TransverseMercator;
 
       case 9808:
-        return( CT_TransvMercator_SouthOriented );
+        return CT_TransvMercator_SouthOriented;
 
       case 9809:
-        return( CT_ObliqueStereographic );
+        return CT_ObliqueStereographic;
 
       case 9810:
-      case 9829: /* variant B not quite the same - not sure how to handle */ 
-        return( CT_PolarStereographic );
+      case 9829: /* variant B not quite the same - not sure how to handle */
+        return CT_PolarStereographic;
 
       case 9811:
-        return( CT_NewZealandMapGrid );
+        return CT_NewZealandMapGrid;
 
       case 9812:
-        return( CT_ObliqueMercator ); /* is hotine actually different? */
+        return CT_ObliqueMercator; /* is hotine actually different? */
 
       case 9813:
-        return( CT_ObliqueMercator_Laborde );
+        return CT_ObliqueMercator_Laborde;
 
       case 9814:
-        return( CT_ObliqueMercator_Rosenmund ); /* swiss  */
+        return CT_ObliqueMercator_Rosenmund; /* swiss  */
 
       case 9815:
-        return( CT_HotineObliqueMercatorAzimuthCenter );
+        return CT_HotineObliqueMercatorAzimuthCenter;
 
       case 9816: /* tunesia mining grid has no counterpart */
-        return( KvUserDefined );
+        return KvUserDefined;
 
       case 9818:
-        return( CT_Polyconic );
+        return CT_Polyconic;
 
       case 9820:
       case 1027:
-        return( CT_LambertAzimEqualArea );
+        return CT_LambertAzimEqualArea;
 
       case 9822:
-        return( CT_AlbersEqualArea );
+        return CT_AlbersEqualArea;
 
       case 9834:
-        return( CT_CylindricalEqualArea );
-        
+        return CT_CylindricalEqualArea;
+
       case 1028:
       case 1029:
       case 9823: /* spherical */
       case 9842: /* elliptical */
-        return( CT_Equirectangular );
+        return CT_Equirectangular;
 
       default: /* use the EPSG code for other methods */
         return nEPSG;
     }
-
-    return( KvUserDefined );
 }
 
 /************************************************************************/
 /*                            SetGTParmIds()                            */
 /*                                                                      */
-/*      This is hardcoded logic to set the GeoTIFF parmaeter            */
+/*      This is hardcoded logic to set the GeoTIFF parameter            */
 /*      identifiers for all the EPSG supported projections.  As the     */
 /*      trf_method.csv table grows with new projections, this code      */
 /*      will need to be updated.                                        */
 /************************************************************************/
 
-static int SetGTParmIds( int nCTProjection, 
-                         int *panProjParmId, 
+static int SetGTParmIds( int nCTProjection,
+                         int *panProjParmId,
                          int *panEPSGCodes )
 
 {
@@ -1140,7 +1152,7 @@ static int SetGTParmIds( int nCTProjection,
     memset( panEPSGCodes, 0, sizeof(int) * 7 );
 
     /* psDefn->nParms = 7; */
-    
+
     switch( nCTProjection )
     {
       case CT_CassiniSoldner:
@@ -1191,7 +1203,7 @@ static int SetGTParmIds( int nCTProjection,
         panEPSGCodes[5] = EPSGProjCenterEasting;
         panEPSGCodes[6] = EPSGProjCenterNorthing;
         return TRUE;
-        
+
       case CT_LambertConfConic_1SP:
       case CT_Mercator:
       case CT_ObliqueStereographic:
@@ -1305,7 +1317,7 @@ static int SetGTParmIds( int nCTProjection,
         return TRUE;
 
       default:
-        return( FALSE );
+        return FALSE;
     }
 }
 
@@ -1319,7 +1331,7 @@ static int SetGTParmIds( int nCTProjection,
 /************************************************************************/
 
 int GTIFGetProjTRFInfo( /* COORD_OP_CODE from coordinate_operation.csv */
-                        int nProjTRFCode, 
+                        int nProjTRFCode,
                         char **ppszProjTRFName,
                         short * pnProjMethod,
                         double * padfProjParms )
@@ -1330,7 +1342,7 @@ int GTIFGetProjTRFInfo( /* COORD_OP_CODE from coordinate_operation.csv */
     char	szTRFCode[16];
     int         nCTProjMethod;
     char       *pszFilename;
-    
+
     if ((nProjTRFCode >= Proj_UTM_zone_1N && nProjTRFCode <= Proj_UTM_zone_60N) ||
         (nProjTRFCode >= Proj_UTM_zone_1S && nProjTRFCode <= Proj_UTM_zone_60S))
     {
@@ -1431,7 +1443,7 @@ int GTIFGetProjTRFInfo( /* COORD_OP_CODE from coordinate_operation.csv */
             sprintf( szParamCodeID, "PARAMETER_CODE_%d", iEPSG+1 );
 
             if( atoi(CSVGetField( pszFilename,
-                                  "COORD_OP_CODE", szTRFCode, CC_Integer, 
+                                  "COORD_OP_CODE", szTRFCode, CC_Integer,
                                   szParamCodeID )) == nEPSGCode )
                 break;
         }
@@ -1454,17 +1466,17 @@ int GTIFGetProjTRFInfo( /* COORD_OP_CODE from coordinate_operation.csv */
                 nEPSGCode = EPSGOriginLong;
             else
                 continue;
-                
+
             for( iEPSG = 0; iEPSG < 7; iEPSG++ )
             {
                 sprintf( szParamCodeID, "PARAMETER_CODE_%d", iEPSG+1 );
 
                 if( atoi(CSVGetField( pszFilename,
-                                      "COORD_OP_CODE", szTRFCode, CC_Integer, 
+                                      "COORD_OP_CODE", szTRFCode, CC_Integer,
                                       szParamCodeID )) == nEPSGCode )
                     break;
             }
-            
+
             if( iEPSG == 7 )
                 continue;
         }
@@ -1474,10 +1486,10 @@ int GTIFGetProjTRFInfo( /* COORD_OP_CODE from coordinate_operation.csv */
         sprintf( szParamValueID, "PARAMETER_VALUE_%d", iEPSG+1 );
 
         nUOM = atoi(CSVGetField( pszFilename,
-                                 "COORD_OP_CODE", szTRFCode, CC_Integer, 
+                                 "COORD_OP_CODE", szTRFCode, CC_Integer,
                                  szParamUOMID ));
         pszValue = CSVGetField( pszFilename,
-                                "COORD_OP_CODE", szTRFCode, CC_Integer, 
+                                "COORD_OP_CODE", szTRFCode, CC_Integer,
                                 szParamValueID );
 
         /* Transform according to the UOM */
@@ -1505,7 +1517,7 @@ int GTIFGetProjTRFInfo( /* COORD_OP_CODE from coordinate_operation.csv */
                                    "COORD_OP_CODE", szTRFCode, CC_Integer,
                                    "COORD_OP_NAME" ));
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Transfer requested data into passed variables.                  */
 /* -------------------------------------------------------------------- */
@@ -1597,43 +1609,43 @@ static void GTIFFetchProjParms( GTIF * psGTIF, GTIFDefn * psDefn )
 /* -------------------------------------------------------------------- */
     if( !GTIFKeyGetDOUBLE(psGTIF, ProjFalseEastingGeoKey, &dfFalseEasting, 0, 1)
         && !GTIFKeyGetDOUBLE(psGTIF, ProjCenterEastingGeoKey,
-                       &dfFalseEasting, 0, 1) 
+                       &dfFalseEasting, 0, 1)
         && !GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginEastingGeoKey,
                        &dfFalseEasting, 0, 1) )
         dfFalseEasting = 0.0;
-        
+
     if( !GTIFKeyGetDOUBLE(psGTIF, ProjFalseNorthingGeoKey, &dfFalseNorthing,0,1)
         && !GTIFKeyGetDOUBLE(psGTIF, ProjCenterNorthingGeoKey,
                        &dfFalseNorthing, 0, 1)
         && !GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginNorthingGeoKey,
                        &dfFalseNorthing, 0, 1) )
         dfFalseNorthing = 0.0;
-        
+
     switch( psDefn->CTProjection )
     {
 /* -------------------------------------------------------------------- */
       case CT_Stereographic:
 /* -------------------------------------------------------------------- */
-        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLongGeoKey, 
+        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLongGeoKey,
                        &dfNatOriginLong, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLongGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLongGeoKey,
                           &dfNatOriginLong, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLongGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLongGeoKey,
                           &dfNatOriginLong, 0, 1 ) == 0 )
             dfNatOriginLong = 0.0;
 
-        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLatGeoKey, 
+        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLatGeoKey,
                        &dfNatOriginLat, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLatGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLatGeoKey,
                           &dfNatOriginLat, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLatGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLatGeoKey,
                           &dfNatOriginLat, 0, 1 ) == 0 )
             dfNatOriginLat = 0.0;
 
         if( GTIFKeyGetDOUBLE(psGTIF, ProjScaleAtNatOriginGeoKey,
                        &dfNatOriginScale, 0, 1 ) == 0 )
             dfNatOriginScale = 1.0;
-            
+
         /* notdef: should transform to decimal degrees at this point */
 
         psDefn->ProjParm[0] = dfNatOriginLat;
@@ -1713,26 +1725,26 @@ static void GTIFFetchProjParms( GTIF * psGTIF, GTIFDefn * psDefn )
       case CT_TransverseMercator:
       case CT_TransvMercator_SouthOriented:
 /* -------------------------------------------------------------------- */
-        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLongGeoKey, 
+        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLongGeoKey,
                        &dfNatOriginLong, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLongGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLongGeoKey,
                           &dfNatOriginLong, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLongGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLongGeoKey,
                           &dfNatOriginLong, 0, 1 ) == 0 )
             dfNatOriginLong = 0.0;
 
-        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLatGeoKey, 
+        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLatGeoKey,
                        &dfNatOriginLat, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLatGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLatGeoKey,
                           &dfNatOriginLat, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLatGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLatGeoKey,
                           &dfNatOriginLat, 0, 1 ) == 0 )
             dfNatOriginLat = 0.0;
 
         if( GTIFKeyGetDOUBLE(psGTIF, ProjScaleAtNatOriginGeoKey,
                        &dfNatOriginScale, 0, 1 ) == 0 )
             dfNatOriginScale = 1.0;
-            
+
         /* notdef: should transform to decimal degrees at this point */
 
         psDefn->ProjParm[0] = dfNatOriginLat;
@@ -1751,25 +1763,25 @@ static void GTIFFetchProjParms( GTIF * psGTIF, GTIFDefn * psDefn )
 
 /* -------------------------------------------------------------------- */
       case CT_ObliqueMercator: /* hotine */
-      case CT_HotineObliqueMercatorAzimuthCenter: 
+      case CT_HotineObliqueMercatorAzimuthCenter:
 /* -------------------------------------------------------------------- */
-        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLongGeoKey, 
+        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLongGeoKey,
                        &dfNatOriginLong, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLongGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLongGeoKey,
                           &dfNatOriginLong, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLongGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLongGeoKey,
                           &dfNatOriginLong, 0, 1 ) == 0 )
             dfNatOriginLong = 0.0;
 
-        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLatGeoKey, 
+        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLatGeoKey,
                        &dfNatOriginLat, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLatGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLatGeoKey,
                           &dfNatOriginLat, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLatGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLatGeoKey,
                           &dfNatOriginLat, 0, 1 ) == 0 )
             dfNatOriginLat = 0.0;
 
-        if( GTIFKeyGetDOUBLE(psGTIF, ProjAzimuthAngleGeoKey, 
+        if( GTIFKeyGetDOUBLE(psGTIF, ProjAzimuthAngleGeoKey,
                        &dfAzimuth, 0, 1 ) == 0 )
             dfAzimuth = 0.0;
 
@@ -1782,7 +1794,7 @@ static void GTIFFetchProjParms( GTIF * psGTIF, GTIFDefn * psDefn )
             && GTIFKeyGetDOUBLE(psGTIF, ProjScaleAtCenterGeoKey,
                           &dfNatOriginScale, 0, 1 ) == 0 )
             dfNatOriginScale = 1.0;
-            
+
         /* notdef: should transform to decimal degrees at this point */
 
         psDefn->ProjParm[0] = dfNatOriginLat;
@@ -1807,19 +1819,19 @@ static void GTIFFetchProjParms( GTIF * psGTIF, GTIFDefn * psDefn )
       case CT_CassiniSoldner:
       case CT_Polyconic:
 /* -------------------------------------------------------------------- */
-        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLongGeoKey, 
+        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLongGeoKey,
                        &dfNatOriginLong, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLongGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLongGeoKey,
                           &dfNatOriginLong, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLongGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLongGeoKey,
                           &dfNatOriginLong, 0, 1 ) == 0 )
             dfNatOriginLong = 0.0;
 
-        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLatGeoKey, 
+        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLatGeoKey,
                        &dfNatOriginLat, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLatGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLatGeoKey,
                           &dfNatOriginLat, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLatGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLatGeoKey,
                           &dfNatOriginLat, 0, 1 ) == 0 )
             dfNatOriginLat = 0.0;
 
@@ -1828,7 +1840,7 @@ static void GTIFFetchProjParms( GTIF * psGTIF, GTIFDefn * psDefn )
             && GTIFKeyGetDOUBLE(psGTIF, ProjScaleAtCenterGeoKey,
                           &dfNatOriginScale, 0, 1 ) == 0 )
             dfNatOriginScale = 1.0;
-            
+
         /* notdef: should transform to decimal degrees at this point */
 
         psDefn->ProjParm[0] = dfNatOriginLat;
@@ -1853,19 +1865,19 @@ static void GTIFFetchProjParms( GTIF * psGTIF, GTIFDefn * psDefn )
       case CT_Orthographic:
       case CT_NewZealandMapGrid:
 /* -------------------------------------------------------------------- */
-        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLongGeoKey, 
+        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLongGeoKey,
                        &dfNatOriginLong, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLongGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLongGeoKey,
                           &dfNatOriginLong, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLongGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLongGeoKey,
                           &dfNatOriginLong, 0, 1 ) == 0 )
             dfNatOriginLong = 0.0;
 
-        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLatGeoKey, 
+        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLatGeoKey,
                        &dfNatOriginLat, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLatGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLatGeoKey,
                           &dfNatOriginLat, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLatGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLatGeoKey,
                           &dfNatOriginLat, 0, 1 ) == 0 )
             dfNatOriginLat = 0.0;
 
@@ -1886,23 +1898,23 @@ static void GTIFFetchProjParms( GTIF * psGTIF, GTIFDefn * psDefn )
 /* -------------------------------------------------------------------- */
       case CT_Equirectangular:
 /* -------------------------------------------------------------------- */
-        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLongGeoKey, 
+        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLongGeoKey,
                        &dfNatOriginLong, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLongGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLongGeoKey,
                           &dfNatOriginLong, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLongGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLongGeoKey,
                           &dfNatOriginLong, 0, 1 ) == 0 )
             dfNatOriginLong = 0.0;
 
-        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLatGeoKey, 
+        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLatGeoKey,
                        &dfNatOriginLat, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLatGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLatGeoKey,
                           &dfNatOriginLat, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLatGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLatGeoKey,
                           &dfNatOriginLat, 0, 1 ) == 0 )
             dfNatOriginLat = 0.0;
 
-        if( GTIFKeyGetDOUBLE(psGTIF, ProjStdParallel1GeoKey, 
+        if( GTIFKeyGetDOUBLE(psGTIF, ProjStdParallel1GeoKey,
                        &dfStdParallel1, 0, 1 ) == 0 )
             dfStdParallel1 = 0.0;
 
@@ -1927,11 +1939,11 @@ static void GTIFFetchProjParms( GTIF * psGTIF, GTIFDefn * psDefn )
       case CT_Sinusoidal:
       case CT_VanDerGrinten:
 /* -------------------------------------------------------------------- */
-        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLongGeoKey, 
+        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLongGeoKey,
                        &dfNatOriginLong, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLongGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLongGeoKey,
                           &dfNatOriginLong, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLongGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLongGeoKey,
                           &dfNatOriginLong, 0, 1 ) == 0 )
             dfNatOriginLong = 0.0;
 
@@ -1950,21 +1962,21 @@ static void GTIFFetchProjParms( GTIF * psGTIF, GTIFDefn * psDefn )
 /* -------------------------------------------------------------------- */
       case CT_PolarStereographic:
 /* -------------------------------------------------------------------- */
-        if( GTIFKeyGetDOUBLE(psGTIF, ProjStraightVertPoleLongGeoKey, 
+        if( GTIFKeyGetDOUBLE(psGTIF, ProjStraightVertPoleLongGeoKey,
                        &dfNatOriginLong, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLongGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLongGeoKey,
                           &dfNatOriginLong, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLongGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLongGeoKey,
                           &dfNatOriginLong, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLongGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLongGeoKey,
                           &dfNatOriginLong, 0, 1 ) == 0 )
             dfNatOriginLong = 0.0;
 
-        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLatGeoKey, 
+        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLatGeoKey,
                        &dfNatOriginLat, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLatGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLatGeoKey,
                           &dfNatOriginLat, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLatGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLatGeoKey,
                           &dfNatOriginLat, 0, 1 ) == 0 )
             dfNatOriginLat = 0.0;
 
@@ -1973,7 +1985,7 @@ static void GTIFFetchProjParms( GTIF * psGTIF, GTIFDefn * psDefn )
             && GTIFKeyGetDOUBLE(psGTIF, ProjScaleAtCenterGeoKey,
                           &dfNatOriginScale, 0, 1 ) == 0 )
             dfNatOriginScale = 1.0;
-            
+
         /* notdef: should transform to decimal degrees at this point */
 
         psDefn->ProjParm[0] = dfNatOriginLat;
@@ -1993,27 +2005,27 @@ static void GTIFFetchProjParms( GTIF * psGTIF, GTIFDefn * psDefn )
 /* -------------------------------------------------------------------- */
       case CT_LambertConfConic_2SP:
 /* -------------------------------------------------------------------- */
-        if( GTIFKeyGetDOUBLE(psGTIF, ProjStdParallel1GeoKey, 
+        if( GTIFKeyGetDOUBLE(psGTIF, ProjStdParallel1GeoKey,
                        &dfStdParallel1, 0, 1 ) == 0 )
             dfStdParallel1 = 0.0;
 
-        if( GTIFKeyGetDOUBLE(psGTIF, ProjStdParallel2GeoKey, 
+        if( GTIFKeyGetDOUBLE(psGTIF, ProjStdParallel2GeoKey,
                        &dfStdParallel2, 0, 1 ) == 0 )
             dfStdParallel1 = 0.0;
 
-        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLongGeoKey, 
+        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLongGeoKey,
                        &dfNatOriginLong, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLongGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLongGeoKey,
                           &dfNatOriginLong, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLongGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLongGeoKey,
                           &dfNatOriginLong, 0, 1 ) == 0 )
             dfNatOriginLong = 0.0;
 
-        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLatGeoKey, 
+        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLatGeoKey,
                        &dfNatOriginLat, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLatGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLatGeoKey,
                           &dfNatOriginLat, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLatGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLatGeoKey,
                           &dfNatOriginLat, 0, 1 ) == 0 )
             dfNatOriginLat = 0.0;
 
@@ -2039,27 +2051,27 @@ static void GTIFFetchProjParms( GTIF * psGTIF, GTIFDefn * psDefn )
       case CT_AlbersEqualArea:
       case CT_EquidistantConic:
 /* -------------------------------------------------------------------- */
-        if( GTIFKeyGetDOUBLE(psGTIF, ProjStdParallel1GeoKey, 
+        if( GTIFKeyGetDOUBLE(psGTIF, ProjStdParallel1GeoKey,
                        &dfStdParallel1, 0, 1 ) == 0 )
             dfStdParallel1 = 0.0;
 
-        if( GTIFKeyGetDOUBLE(psGTIF, ProjStdParallel2GeoKey, 
+        if( GTIFKeyGetDOUBLE(psGTIF, ProjStdParallel2GeoKey,
                        &dfStdParallel2, 0, 1 ) == 0 )
             dfStdParallel2 = 0.0;
 
-        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLongGeoKey, 
+        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLongGeoKey,
                        &dfNatOriginLong, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLongGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLongGeoKey,
                           &dfNatOriginLong, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLongGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLongGeoKey,
                           &dfNatOriginLong, 0, 1 ) == 0 )
             dfNatOriginLong = 0.0;
 
-        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLatGeoKey, 
+        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLatGeoKey,
                        &dfNatOriginLat, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLatGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLatGeoKey,
                           &dfNatOriginLat, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLatGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLatGeoKey,
                           &dfNatOriginLat, 0, 1 ) == 0 )
             dfNatOriginLat = 0.0;
 
@@ -2084,15 +2096,15 @@ static void GTIFFetchProjParms( GTIF * psGTIF, GTIFDefn * psDefn )
 /* -------------------------------------------------------------------- */
       case CT_CylindricalEqualArea:
 /* -------------------------------------------------------------------- */
-        if( GTIFKeyGetDOUBLE(psGTIF, ProjStdParallel1GeoKey, 
+        if( GTIFKeyGetDOUBLE(psGTIF, ProjStdParallel1GeoKey,
                        &dfStdParallel1, 0, 1 ) == 0 )
             dfStdParallel1 = 0.0;
 
-        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLongGeoKey, 
+        if( GTIFKeyGetDOUBLE(psGTIF, ProjNatOriginLongGeoKey,
                        &dfNatOriginLong, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLongGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginLongGeoKey,
                           &dfNatOriginLong, 0, 1 ) == 0
-            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLongGeoKey, 
+            && GTIFKeyGetDOUBLE(psGTIF, ProjCenterLongGeoKey,
                           &dfNatOriginLong, 0, 1 ) == 0 )
             dfNatOriginLong = 0.0;
 
@@ -2126,7 +2138,7 @@ static void GTIFFetchProjParms( GTIF * psGTIF, GTIFDefn * psDefn )
           case ProjFalseOriginNorthingGeoKey:
           case ProjCenterEastingGeoKey:
           case ProjCenterNorthingGeoKey:
-            if( psDefn->UOMLengthInMeters != 0 
+            if( psDefn->UOMLengthInMeters != 0
                 && psDefn->UOMLengthInMeters != 1.0 )
             {
                 psDefn->ProjParm[iParm] *= psDefn->UOMLengthInMeters;
@@ -2150,32 +2162,32 @@ static void GTIFFetchProjParms( GTIF * psGTIF, GTIFDefn * psDefn )
 @return TRUE if the function has been successful, otherwise FALSE.
 
 This function reads the coordinate system definition from a GeoTIFF file,
-and <i>normalizes</i> it into a set of component information using 
-definitions from CSV (Comma Seperated Value ASCII) files derived from 
+and <i>normalizes</i> it into a set of component information using
+definitions from CSV (Comma Separated Value ASCII) files derived from
 EPSG tables.  This function is intended to simplify correct support for
 reading files with defined PCS (Projected Coordinate System) codes that
 wouldn't otherwise be directly known by application software by reducing
-it to the underlying projection method, parameters, datum, ellipsoid, 
+it to the underlying projection method, parameters, datum, ellipsoid,
 prime meridian and units.<p>
 
-The application should pass a pointer to an existing uninitialized 
-GTIFDefn structure, and GTIFGetDefn() will fill it in.  The fuction 
-currently always returns TRUE but in the future will return FALSE if 
+The application should pass a pointer to an existing uninitialized
+GTIFDefn structure, and GTIFGetDefn() will fill it in.  The function
+currently always returns TRUE but in the future will return FALSE if
 CSV files are not found.  In any event, all geokeys actually found in the
 file will be copied into the GTIFDefn.  However, if the CSV files aren't
 found codes implied by other codes will not be set properly.<p>
 
 GTIFGetDefn() will not generally work if the EPSG derived CSV files cannot
-be found.  By default a modest attempt will be made to find them, but 
+be found.  By default a modest attempt will be made to find them, but
 in general it is necessary for the calling application to override the
-logic to find them.  This can be done by calling the 
+logic to find them.  This can be done by calling the
 SetCSVFilenameHook() function to
 override the search method based on application knowledge of where they are
 found.<p>
 
 The normalization methodology operates by fetching tags from the GeoTIFF
 file, and then setting all other tags implied by them in the structure.  The
-implied relationships are worked out by reading definitions from the 
+implied relationships are worked out by reading definitions from the
 various EPSG derived CSV tables.<p>
 
 For instance, if a PCS (ProjectedCSTypeGeoKey) is found in the GeoTIFF file
@@ -2183,9 +2195,9 @@ this code is used to lookup a record in the <tt>horiz_cs.csv</tt> CSV
 file.  For example given the PCS 26746 we can find the name
 (NAD27 / California zone VI), the GCS 4257 (NAD27), and the ProjectionCode
 10406 (California CS27 zone VI).  The GCS, and ProjectionCode can in turn
-be looked up in other tables until all the details of units, ellipsoid, 
+be looked up in other tables until all the details of units, ellipsoid,
 prime meridian, datum, projection (LambertConfConic_2SP) and projection
-parameters are established.  A full listgeo dump of a file 
+parameters are established.  A full listgeo dump of a file
 for this result might look like the following, all based on a single PCS
 value:<p>
 
@@ -2196,10 +2208,10 @@ Geotiff_Information:
    Key_Revision: 1.0
    Tagged_Information:
       ModelTiepointTag (2,3):
-         0                0                0                
-         1577139.71       634349.176       0                
+         0                0                0
+         1577139.71       634349.176       0
       ModelPixelScaleTag (1,3):
-         195.509321       198.32184        0                
+         195.509321       198.32184        0
       End_Of_Tags.
    Keyed_Information:
       GTModelTypeGeoKey (Short,1): ModelTypeProjected
@@ -2225,15 +2237,15 @@ Projection Linear Units: 9003/US survey foot (0.304801m)
 </pre>
 
 Note that GTIFGetDefn() does not inspect or return the tiepoints and scale.
-This must be handled seperately as it normally would.  It is intended to
-simplify capture and normalization of the coordinate system definition.  
+This must be handled separately as it normally would.  It is intended to
+simplify capture and normalization of the coordinate system definition.
 Note that GTIFGetDefn() also does the following things:
 
 <ol>
 <li> Convert all angular values to decimal degrees.
-<li> Convert all linear values to meters. 
+<li> Convert all linear values to meters.
 <li> Return the linear units and conversion to meters for the tiepoints and
-scale (though the tiepoints and scale remain in their native units). 
+scale (though the tiepoints and scale remain in their native units).
 <li> When reading projection parameters a variety of differences between
 different GeoTIFF generators are handled, and a normalized set of parameters
 for each projection are always returned.
@@ -2249,8 +2261,8 @@ GTIFDefn::ProjParmId[] will
 be zero.  This is done to retain correspondence to the EPSG parameter
 numbering scheme.<p>
 
-The 
-<a href="http://www.remotesensing.org/cgi-bin/cvsweb.cgi/~checkout~/osrs/geotiff/libgeotiff/geotiff_proj4.c">geotiff_proj4.c</a> module distributed with libgeotiff can 
+The
+<a href="http://www.remotesensing.org/cgi-bin/cvsweb.cgi/~checkout~/osrs/geotiff/libgeotiff/geotiff_proj4.c">geotiff_proj4.c</a> module distributed with libgeotiff can
 be used as an example of code that converts a GTIFDefn into another projection
 system.<p>
 
@@ -2264,7 +2276,7 @@ int GTIFGetDefn( GTIF * psGTIF, GTIFDefn * psDefn )
     int		i;
     short	nGeogUOMLinear;
     double	dfInvFlattening;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Initially we default all the information we can.                */
 /* -------------------------------------------------------------------- */
@@ -2363,7 +2375,7 @@ int GTIFGetDefn( GTIF * psGTIF, GTIFDefn * psDefn )
 /* -------------------------------------------------------------------- */
     if( psDefn->ProjCode == KvUserDefined )
         GTIFKeyGetSHORT(psGTIF, ProjectionGeoKey, &(psDefn->ProjCode), 0, 1 );
-    
+
     if( psDefn->ProjCode != KvUserDefined )
     {
         /*
@@ -2375,11 +2387,11 @@ int GTIFGetDefn( GTIF * psGTIF, GTIFDefn * psDefn )
          */
         GTIFGetProjTRFInfo( psDefn->ProjCode, NULL, &(psDefn->Projection),
                             psDefn->ProjParm );
-        
+
         /*
          * Set the GeoTIFF identity of the parameters.
          */
-        psDefn->CTProjection = (short) 
+        psDefn->CTProjection = (short)
             EPSGProjMethodToCTProjMethod( psDefn->Projection, FALSE );
 
         SetGTParmIds( EPSGProjMethodToCTProjMethod(psDefn->Projection, TRUE),
@@ -2403,7 +2415,7 @@ int GTIFGetDefn( GTIF * psGTIF, GTIFDefn * psDefn )
         GTIFGetGCSInfo( psDefn->GCS, NULL, &(psDefn->Datum), &(psDefn->PM),
                         &(psDefn->UOMAngle) );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Handle the GCS angular units.  GeogAngularUnitsGeoKey           */
 /*      overrides the GCS or PCS setting.                               */
@@ -2443,19 +2455,19 @@ int GTIFGetDefn( GTIF * psGTIF, GTIFDefn * psDefn )
 /*      to warn if they conflict with provided information, but for     */
 /*      now we just override.                                           */
 /* -------------------------------------------------------------------- */
-    GTIFKeyGetDOUBLE(psGTIF, GeogSemiMajorAxisGeoKey, &(psDefn->SemiMajor), 0, 1 );
-    GTIFKeyGetDOUBLE(psGTIF, GeogSemiMinorAxisGeoKey, &(psDefn->SemiMinor), 0, 1 );
-    
-    if( GTIFKeyGetDOUBLE(psGTIF, GeogInvFlatteningGeoKey, &dfInvFlattening, 
+    CPL_IGNORE_RET_VAL_INT(GTIFKeyGetDOUBLE(psGTIF, GeogSemiMajorAxisGeoKey, &(psDefn->SemiMajor), 0, 1 ));
+    CPL_IGNORE_RET_VAL_INT(GTIFKeyGetDOUBLE(psGTIF, GeogSemiMinorAxisGeoKey, &(psDefn->SemiMinor), 0, 1 ));
+
+    if( GTIFKeyGetDOUBLE(psGTIF, GeogInvFlatteningGeoKey, &dfInvFlattening,
                    0, 1 ) == 1 )
     {
         if( dfInvFlattening != 0.0 )
-            psDefn->SemiMinor = 
+            psDefn->SemiMinor =
                 psDefn->SemiMajor * (1 - 1.0/dfInvFlattening);
         else
             psDefn->SemiMinor = psDefn->SemiMajor;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Get the prime meridian info.                                    */
 /* -------------------------------------------------------------------- */
@@ -2467,8 +2479,8 @@ int GTIFGetDefn( GTIF * psGTIF, GTIFDefn * psDefn )
     }
     else
     {
-        GTIFKeyGetDOUBLE(psGTIF, GeogPrimeMeridianLongGeoKey,
-                   &(psDefn->PMLongToGreenwich), 0, 1 );
+        CPL_IGNORE_RET_VAL_INT(GTIFKeyGetDOUBLE(psGTIF, GeogPrimeMeridianLongGeoKey,
+                   &(psDefn->PMLongToGreenwich), 0, 1 ));
 
         psDefn->PMLongToGreenwich =
             GTIFAngleToDD( psDefn->PMLongToGreenwich,
@@ -2479,8 +2491,8 @@ int GTIFGetDefn( GTIF * psGTIF, GTIFDefn * psDefn )
 /*      Get the TOWGS84 parameters.                                     */
 /* -------------------------------------------------------------------- */
 #if !defined(GEO_NORMALIZE_DISABLE_TOWGS84)
-    psDefn->TOWGS84Count = 
-        GTIFKeyGetDOUBLE(psGTIF, GeogTOWGS84GeoKey, psDefn->TOWGS84, 0, 7 );
+    psDefn->TOWGS84Count =
+        (short)GTIFKeyGetDOUBLE(psGTIF, GeogTOWGS84GeoKey, psDefn->TOWGS84, 0, 7 );
 #endif
 
 /* -------------------------------------------------------------------- */
@@ -2498,7 +2510,7 @@ int GTIFGetDefn( GTIF * psGTIF, GTIFDefn * psDefn )
     }
     else
     {
-        GTIFKeyGetDOUBLE(psGTIF,ProjLinearUnitSizeGeoKey,&(psDefn->UOMLengthInMeters),0,1);
+        CPL_IGNORE_RET_VAL_INT(GTIFKeyGetDOUBLE(psGTIF,ProjLinearUnitSizeGeoKey,&(psDefn->UOMLengthInMeters),0,1));
     }
 
 /* -------------------------------------------------------------------- */
@@ -2528,16 +2540,16 @@ int GTIFGetDefn( GTIF * psGTIF, GTIFDefn * psDefn )
         psDefn->nParms = 7;
         psDefn->ProjParmId[0] = ProjNatOriginLatGeoKey;
         psDefn->ProjParm[0] = 0.0;
-            
+
         psDefn->ProjParmId[1] = ProjNatOriginLongGeoKey;
         psDefn->ProjParm[1] = psDefn->Zone*6 - 183.0;
-        
+
         psDefn->ProjParmId[4] = ProjScaleAtNatOriginGeoKey;
         psDefn->ProjParm[4] = 0.9996;
-        
+
         psDefn->ProjParmId[5] = ProjFalseEastingGeoKey;
         psDefn->ProjParm[5] = 500000.0;
-        
+
         psDefn->ProjParmId[6] = ProjFalseNorthingGeoKey;
 
         if( psDefn->MapSys == MapSys_UTM_North )
@@ -2589,7 +2601,7 @@ const char *GTIFDecToDMS( double dfAngle, const char * pszAxis,
              nPrecision+3, nPrecision, pszHemisphere );
     sprintf( szBuffer, szFormat, nDegrees, nMinutes, dfSeconds );
 
-    return( szBuffer );
+    return szBuffer;
 }
 
 /************************************************************************/
@@ -2617,11 +2629,11 @@ void GTIFPrintDefn( GTIFDefn * psDefn, FILE * fp )
     if( psDefn->PCS != KvUserDefined )
     {
         char	*pszPCSName = NULL;
-    
+
         GTIFGetPCSInfo( psDefn->PCS, &pszPCSName, NULL, NULL, NULL );
         if( pszPCSName == NULL )
             pszPCSName = CPLStrdup("name unknown");
-        
+
         fprintf( fp, "PCS = %d (%s)\n", psDefn->PCS, pszPCSName );
         CPLFree( pszPCSName );
     }
@@ -2636,7 +2648,7 @@ void GTIFPrintDefn( GTIFDefn * psDefn, FILE * fp )
         GTIFGetProjTRFInfo( psDefn->ProjCode, &pszTRFName, NULL, NULL );
         if( pszTRFName == NULL )
             pszTRFName = CPLStrdup("");
-                
+
         fprintf( fp, "Projection = %d (%s)\n",
                  psDefn->ProjCode, pszTRFName );
 
@@ -2654,7 +2666,7 @@ void GTIFPrintDefn( GTIFDefn * psDefn, FILE * fp )
 
         if( pszName == NULL )
             pszName = "(unknown)";
-            
+
         fprintf( fp, "Projection Method: %s\n", pszName );
 
         for( i = 0; i < psDefn->nParms; i++ )
@@ -2669,14 +2681,14 @@ void GTIFPrintDefn( GTIFDefn * psDefn, FILE * fp )
             if( i < 4 )
             {
                 char	*pszAxisName;
-                
+
                 if( strstr(pszName,"Long") != NULL )
                     pszAxisName = "Long";
                 else if( strstr(pszName,"Lat") != NULL )
                     pszAxisName = "Lat";
                 else
                     pszAxisName = "?";
-                
+
                 fprintf( fp, "   %s: %f (%s)\n",
                          pszName, psDefn->ProjParm[i],
                          GTIFDecToDMS( psDefn->ProjParm[i], pszAxisName, 2 ) );
@@ -2698,7 +2710,7 @@ void GTIFPrintDefn( GTIFDefn * psDefn, FILE * fp )
         GTIFGetGCSInfo( psDefn->GCS, &pszName, NULL, NULL, NULL );
         if( pszName == NULL )
             pszName = CPLStrdup("(unknown)");
-        
+
         fprintf( fp, "GCS: %d/%s\n", psDefn->GCS, pszName );
         CPLFree( pszName );
     }
@@ -2713,7 +2725,7 @@ void GTIFPrintDefn( GTIFDefn * psDefn, FILE * fp )
         GTIFGetDatumInfo( psDefn->Datum, &pszName, NULL );
         if( pszName == NULL )
             pszName = CPLStrdup("(unknown)");
-        
+
         fprintf( fp, "Datum: %d/%s\n", psDefn->Datum, pszName );
         CPLFree( pszName );
     }
@@ -2728,13 +2740,13 @@ void GTIFPrintDefn( GTIFDefn * psDefn, FILE * fp )
         GTIFGetEllipsoidInfo( psDefn->Ellipsoid, &pszName, NULL, NULL );
         if( pszName == NULL )
             pszName = CPLStrdup("(unknown)");
-        
+
         fprintf( fp, "Ellipsoid: %d/%s (%.2f,%.2f)\n",
                  psDefn->Ellipsoid, pszName,
                  psDefn->SemiMajor, psDefn->SemiMinor );
         CPLFree( pszName );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Report the prime meridian.                                      */
 /* -------------------------------------------------------------------- */
@@ -2746,7 +2758,7 @@ void GTIFPrintDefn( GTIFDefn * psDefn, FILE * fp )
 
         if( pszName == NULL )
             pszName = CPLStrdup("(unknown)");
-        
+
         fprintf( fp, "Prime Meridian: %d/%s (%f/%s)\n",
                  psDefn->PM, pszName,
                  psDefn->PMLongToGreenwich,
@@ -2763,7 +2775,7 @@ void GTIFPrintDefn( GTIFDefn * psDefn, FILE * fp )
         int i;
 
         fprintf( fp, "TOWGS84: " );
-        
+
         for( i = 0; i < psDefn->TOWGS84Count; i++ )
         {
             if( i > 0 )
@@ -2786,7 +2798,7 @@ void GTIFPrintDefn( GTIFDefn * psDefn, FILE * fp )
         GTIFGetUOMLengthInfo( psDefn->UOMLength, &pszName, NULL );
         if( pszName == NULL )
             pszName = CPLStrdup( "(unknown)" );
-        
+
         fprintf( fp, "Projection Linear Units: %d/%s (%fm)\n",
                  psDefn->UOMLength, pszName, psDefn->UOMLengthInMeters );
         CPLFree( pszName );
@@ -2843,7 +2855,7 @@ GTIFDefn *GTIFAllocDefn()
 /*      Free a GTIF structure allocated by GTIFAllocDefn().             */
 /************************************************************************/
 
-void GTIFFreeDefn( GTIFDefn *defn ) 
+void GTIFFreeDefn( GTIFDefn *defn )
 {
     VSIFree( defn );
 }
diff --git a/frmts/gtiff/libgeotiff/geo_normalize.h b/frmts/gtiff/libgeotiff/geo_normalize.h
index 60a4095..d466831 100644
--- a/frmts/gtiff/libgeotiff/geo_normalize.h
+++ b/frmts/gtiff/libgeotiff/geo_normalize.h
@@ -43,7 +43,7 @@ extern "C" {
  *
  * Include file for extended projection definition normalization api.
  */
-    
+
 #define MAX_GTIF_PROJPARMS 	10
 
 /**
@@ -60,7 +60,7 @@ typedef struct {
 
     /** From GeographicTypeGeoKey tag.  For example GCS_WGS_84 or
         GCS_Voirol_1875_Paris.  Includes datum and prime meridian value. */
-    short	GCS;	      
+    short	GCS;
 
     /** From ProjLinearUnitsGeoKey.  For example Linear_Meter. */
     short	UOMLength;
@@ -73,7 +73,7 @@ typedef struct {
 
     /** One UOMAngle = UOMLengthInDegrees degrees. */
     double      UOMAngleInDegrees;
-    
+
     /** Datum from GeogGeodeticDatumGeoKey tag. For example Datum_WGS84 */
     short	Datum;
 
@@ -95,8 +95,8 @@ typedef struct {
     /** The length of the semi minor ellipse axis in meters. */
     double	SemiMinor;
 
-  /* this #if is primary intended to maintain binary compatability with older
-     versions of libgeotiff for MrSID binaries (for example) */
+  /* This #if is primary intended to maintain binary compatibility with older
+     versions of libgeotiff for MrSID binaries (for example). */
 #if !defined(GEO_NORMALIZE_DISABLE_TOWGS84)
     /** TOWGS84 transformation values (0/3/7) */
     short       TOWGS84Count;
@@ -113,9 +113,9 @@ typedef struct {
     short	Projection;
 
     /** GeoTIFF identifier for underlying projection method.  While some of
-      these values have corresponding vlaues in EPSG (Projection field),
+      these values have corresponding values in EPSG (Projection field),
       others do not.  For example CT_TransverseMercator. */
-    short	CTProjection;   
+    short	CTProjection;
 
     /** Number of projection parameters in ProjParm and ProjParmId. */
     int		nParms;
@@ -144,7 +144,7 @@ typedef struct {
 } GTIFDefn;
 
 int CPL_DLL GTIFGetPCSInfo( int nPCSCode, char **ppszEPSGName,
-                            short *pnProjOp, 
+                            short *pnProjOp,
                             short *pnUOMLengthCode, short *pnGeogCS );
 int CPL_DLL GTIFGetProjTRFInfo( int nProjTRFCode,
                                 char ** ppszProjTRFName,
@@ -168,7 +168,7 @@ int CPL_DLL GTIFGetUOMAngleInfo( int nUOMAngleCode,
                                  char **ppszUOMName,
                                  double * pdfInDegrees );
 double CPL_DLL GTIFAngleToDD( double dfAngle, int nUOMAngle );
-    
+
 
 /* this should be used to free strings returned by GTIFGet... funcs */
 void CPL_DLL GTIFFreeMemory( char * );
@@ -215,5 +215,5 @@ int  CPL_DLL  GTIFSetFromProj4( GTIF *gtif, const char *proj4 );
 #ifdef __cplusplus
 }
 #endif
-    
+
 #endif /* ndef GEO_NORMALIZE_H_INCLUDED */
diff --git a/frmts/gtiff/libgeotiff/geo_print.c b/frmts/gtiff/libgeotiff/geo_print.c
index bc9d164..babcb83 100644
--- a/frmts/gtiff/libgeotiff/geo_print.c
+++ b/frmts/gtiff/libgeotiff/geo_print.c
@@ -40,7 +40,7 @@
 static void DefaultPrint(char *string, void *aux);
 static void PrintKey(GeoKey *key, GTIFPrintMethod print,void *aux);
 static void PrintGeoTags(GTIF *gtif,GTIFReadMethod scan,void *aux);
-static void PrintTag(int tag, int nrows, double *data, int ncols, 
+static void PrintTag(int tag, int nrows, double *data, int ncols,
 					GTIFPrintMethod print,void *aux);
 static void DefaultRead(char *string, void *aux);
 static int  ReadKey(GTIF *gt, GTIFReadMethod scan, void *aux);
@@ -54,24 +54,24 @@ static int  ReadTag(GTIF *gt,GTIFReadMethod scan,void *aux);
  * The output format is a "GeoTIFF meta-data" file, which may be
  * used to import information with the GTIFFImport() routine.
  */
- 
+
 void GTIFPrint(GTIF *gtif, GTIFPrintMethod print,void *aux)
 {
     int i;
     int numkeys = gtif->gt_num_keys;
     GeoKey *key = gtif->gt_keys;
     char message[1024];
-	
+
     if (!print) print = (GTIFPrintMethod) &DefaultPrint;
-    if (!aux) aux=stdout;	
+    if (!aux) aux=stdout;
 
-    sprintf(message,FMT_GEOTIFF "\n"); 
+    sprintf(message,FMT_GEOTIFF "\n");
     print(message,aux);
     sprintf(message, "Version: %hd" ,gtif->gt_version);
     sprintf(message, FMT_VERSION,gtif->gt_version);
     print("   ",aux); print(message,aux); print("\n",aux);
     sprintf(message, FMT_REV,gtif->gt_rev_major,
-            gtif->gt_rev_minor); 
+            gtif->gt_rev_minor);
     print("   ",aux); print(message,aux); print("\n",aux);
 
     sprintf(message,"   %s\n",FMT_TAGS); print(message,aux);
@@ -103,7 +103,7 @@ static void PrintGeoTags(GTIF *gt, GTIFPrintMethod print,void *aux)
 		PrintTag(GTIFF_TRANSMATRIX,count/4, data, 4, print, aux);
 }
 
-static void PrintTag(int tag, int nrows, double *dptr, int ncols, 
+static void PrintTag(int tag, int nrows, double *dptr, int ncols,
 					GTIFPrintMethod print,void *aux)
 {
 	int i,j;
@@ -135,7 +135,7 @@ static void PrintKey(GeoKey *key, GTIFPrintMethod print, void *aux)
 {
     char *data;
     geokey_t keyid = (geokey_t) key->gk_key;
-    int count = key->gk_count;
+    int count = (int) key->gk_count;
     int vals_now,i;
     pinfo_t *sptr;
     double *dptr;
@@ -143,18 +143,18 @@ static void PrintKey(GeoKey *key, GTIFPrintMethod print, void *aux)
 
     print("      ",aux);
     print(GTIFKeyName(keyid),aux);
-	
+
     sprintf(message," (%s,%d): ",GTIFTypeName(key->gk_type),count);
     print(message,aux);
-	
+
     if (key->gk_type==TYPE_SHORT && count==1)
         data = (char *)&key->gk_data;
     else
         data = key->gk_data;
-		
+
     switch (key->gk_type)
     {
-      case TYPE_ASCII: 
+      case TYPE_ASCII:
       {
           int  in_char, out_char;
 
@@ -194,8 +194,8 @@ static void PrintKey(GeoKey *key, GTIFPrintMethod print, void *aux)
           print("\"\n",aux);
       }
       break;
-        
-      case TYPE_DOUBLE: 
+
+      case TYPE_DOUBLE:
         for (dptr = (double *)data; count > 0; count-= vals_now)
         {
             vals_now = count > 3? 3: count;
@@ -207,8 +207,8 @@ static void PrintKey(GeoKey *key, GTIFPrintMethod print, void *aux)
             print("\n",aux);
         }
         break;
-        
-      case TYPE_SHORT: 
+
+      case TYPE_SHORT:
         sptr = (pinfo_t *)data;
         if (count==1)
         {
@@ -231,8 +231,8 @@ static void PrintKey(GeoKey *key, GTIFPrintMethod print, void *aux)
             }
         }
         break;
-        
-      default: 
+
+      default:
         sprintf(message, "Unknown Type (%d)\n",key->gk_type);
         print(message,aux);
         break;
@@ -258,17 +258,17 @@ static void DefaultPrint(char *string, void *aux)
  * The input format is a "GeoTIFF meta-data" file, which may be
  * generated by the GTIFFPrint() routine.
  */
- 
+
 int GTIFImport(GTIF *gtif, GTIFReadMethod scan,void *aux)
 {
     int status;
     char message[1024];
-	
+
     if (!scan) scan = (GTIFReadMethod) &DefaultRead;
-    if (!aux) aux=stdin;	
-	
+    if (!aux) aux=stdin;
+
     scan(message,aux);
-    if (strncmp(message,FMT_GEOTIFF,8)) return 0; 
+    if (strncmp(message,FMT_GEOTIFF,8)) return 0;
     scan(message,aux);
     if (!sscanf(message,FMT_VERSION,(short int*)&gtif->gt_version)) return 0;
     scan(message,aux);
@@ -283,7 +283,7 @@ int GTIFImport(GTIF *gtif, GTIFReadMethod scan,void *aux)
     scan(message,aux);
     if (strncmp(message,FMT_KEYS,8)) return 0;
     while ((status=ReadKey(gtif,scan,aux))>0);
-	
+
     return (status==0); /* success */
 }
 
@@ -312,7 +312,7 @@ static int ReadTag(GTIF *gt,GTIFReadMethod scan,void *aux)
 
     num=sscanf(message,"%[^( ] (%d,%d):\n",tagname,&nrows,&ncols);
     if (num!=3) return StringError(message);
-	
+
     tag = GTIFTagCode(tagname);
     if (tag < 0) return StringError(tagname);
 
@@ -320,7 +320,7 @@ static int ReadTag(GTIF *gt,GTIFReadMethod scan,void *aux)
 
     data = (double *) _GTIFcalloc(count * sizeof(double));
     dptr = data;
-	
+
     for (i=0;i<nrows;i++)
     {
         scan(message,aux);
@@ -328,12 +328,15 @@ static int ReadTag(GTIF *gt,GTIFReadMethod scan,void *aux)
         for (j=0;j<ncols;j++)
         {
             if (!sscanf(vptr,"%lg",dptr++))
+            {
+                _GTIFFree( data );
                 return StringError(vptr);
+            }
             FINDCHAR(vptr,' ');
             SKIPWHITE(vptr);
         }
-    }	
-    (gt->gt_methods.set)(gt->gt_tif, (pinfo_t) tag, count, data );	
+    }
+    (gt->gt_methods.set)(gt->gt_tif, (pinfo_t) tag, count, data );
 
     _GTIFFree( data );
 
@@ -352,40 +355,43 @@ static int ReadKey(GTIF *gt, GTIFReadMethod scan, void *aux)
     short  *sptr;
     char name[1000];
     char type[20];
-    double data[100];
     double *dptr;
     char *vptr;
     int num;
     char message[2048];
+    int keycode;
+    int typecode;
 
-    scan(message,aux); 
+    scan(message,aux);
     if (!strncmp(message,FMT_KEYEND,8)) return 0;
 
     num=sscanf(message,"%[^( ] (%[^,],%d):\n",name,type,&count);
     if (num!=3) return StringError(message);
 
     vptr = message;
-    FINDCHAR(vptr,':'); 
+    FINDCHAR(vptr,':');
     if (!*vptr) return StringError(message);
     vptr+=2;
 
-    if( GTIFKeyCode(name) < 0 )
+    keycode = GTIFKeyCode(name);
+    if( keycode < 0 )
         return StringError(name);
     else
-        key = (geokey_t) GTIFKeyCode(name);
+        key = (geokey_t) keycode;
 
-    if( GTIFTypeCode(type) < 0 )
+    typecode = GTIFTypeCode(type);
+    if( typecode < 0 )
         return StringError(type);
     else
-        ktype = (tagtype_t) GTIFTypeCode(type);
+        ktype = (tagtype_t) typecode;
 
     /* skip white space */
     SKIPWHITE(vptr);
     if (!*vptr) return StringError(message);
-			
+
     switch (ktype)
     {
-      case TYPE_ASCII: 
+      case TYPE_ASCII:
       {
           char *cdata;
           int out_char = 0;
@@ -415,8 +421,11 @@ static int ReadKey(GTIF *gt, GTIFReadMethod scan, void *aux)
                   cdata[out_char++] = *(vptr++);
           }
 
-          if( out_char < count-1 ) return StringError(message);
-          if( *vptr != '"' ) return StringError(message);
+          if( out_char < count-1 ||  *vptr != '"' )
+          {
+              _GTIFFree( cdata );
+              return StringError(message);
+          }
 
           cdata[count-1] = '\0';
           GTIFKeySet(gt,key,ktype,count,cdata);
@@ -424,8 +433,10 @@ static int ReadKey(GTIF *gt, GTIFReadMethod scan, void *aux)
           _GTIFFree( cdata );
       }
       break;
-        
-      case TYPE_DOUBLE: 
+
+      case TYPE_DOUBLE:
+      {
+        double data[100];
         outcount = count;
         for (dptr = data; count > 0; count-= vals_now)
         {
@@ -448,8 +459,9 @@ static int ReadKey(GTIF *gt, GTIFReadMethod scan, void *aux)
         else
             GTIFKeySet(gt,key,ktype,outcount,data);
         break;
-        
-      case TYPE_SHORT: 
+      }
+
+      case TYPE_SHORT:
         if (count==1)
         {
             icode = GTIFValueCode(key,vptr);
@@ -459,11 +471,9 @@ static int ReadKey(GTIF *gt, GTIFReadMethod scan, void *aux)
         }
         else  /* multi-valued short - no such thing yet */
         {
-            char* cdata;
-            memcpy(&cdata, &data, sizeof(void*));
-            sptr = (short *)cdata;
+            short data[100];
             outcount = count;
-            for (; count > 0; count-= vals_now)
+            for (sptr = data; count > 0; count-= vals_now)
             {
                 vals_now = count > 3? 3: count;
                 for (i=0; i<vals_now; i++,sptr++)
@@ -478,7 +488,8 @@ static int ReadKey(GTIF *gt, GTIFReadMethod scan, void *aux)
                 if (vals_now<count)
                 {
                     scan(message,aux);
-                    vptr = message;
+                    /* FIXME: the following is dead assignment */
+                    /*vptr = message;*/
                 }
             }
             GTIFKeySet(gt,key,ktype,outcount,sptr);
diff --git a/frmts/gtiff/libgeotiff/geo_set.c b/frmts/gtiff/libgeotiff/geo_set.c
index 19adf71..7831dcc 100644
--- a/frmts/gtiff/libgeotiff/geo_set.c
+++ b/frmts/gtiff/libgeotiff/geo_set.c
@@ -43,7 +43,7 @@ to read.  At this time all keys except for strings have only one value,
 so <b>index</b> should be zero, and <b>count</b> should be one.<p>
 
 The <b>key</b> indicates the key name to be written to the
-file and should from the geokey_t enumeration 
+file and should from the geokey_t enumeration
 (eg. <tt>ProjectedCSTypeGeoKey</tt>).  The full list of possible geokey_t
 values can be found in geokeys.inc, or in the online documentation for
 GTIFKeyGet().<p>
@@ -61,15 +61,15 @@ are passed by value rather than as pointers when count is 1, but as pointers
 if count is larger than 1.<p>
 
 Note that key values aren't actually flushed to the file until
-GTIFWriteKeys() is called.  Till then 
+GTIFWriteKeys() is called.  Till then
 the new values are just kept with the GTIF structure.<p>
 
 <b>Example:</b><p>
 
 <pre>
-    GTIFKeySet(gtif, GTRasterTypeGeoKey, TYPE_SHORT, 1, 
+    GTIFKeySet(gtif, GTRasterTypeGeoKey, TYPE_SHORT, 1,
                RasterPixelIsArea);
-    GTIFKeySet(gtif, GTCitationGeoKey, TYPE_ASCII, 0, 
+    GTIFKeySet(gtif, GTCitationGeoKey, TYPE_ASCII, 0,
                "UTM 11 North / NAD27" );
 </pre>
 
@@ -78,7 +78,7 @@ the new values are just kept with the GTIF structure.<p>
 int GTIFKeySet(GTIF *gtif, geokey_t keyID, tagtype_t type, int count,...)
 {
     va_list ap;
-    int index = gtif->gt_keyindex[ keyID ];
+    int nIndex = gtif->gt_keyindex[ keyID ];
     int newvalues = 0;
     GeoKey *key;
     char *data = NULL;
@@ -88,7 +88,7 @@ int GTIFKeySet(GTIF *gtif, geokey_t keyID, tagtype_t type, int count,...)
 
     va_start(ap, count);
     /* pass singleton keys by value */
-    if (count>1 && type!=TYPE_ASCII) 
+    if (count>1 && type!=TYPE_ASCII)
     {
         val = va_arg(ap, char*);
     }
@@ -97,21 +97,21 @@ int GTIFKeySet(GTIF *gtif, geokey_t keyID, tagtype_t type, int count,...)
         /* delete the indicated tag */
         va_end(ap);
 
-        if( index < 1 )
+        if( nIndex < 1 )
             return 0;
 
-        if (gtif->gt_keys[index].gk_type == TYPE_ASCII)
+        if (gtif->gt_keys[nIndex].gk_type == TYPE_ASCII)
         {
-            _GTIFFree (gtif->gt_keys[index].gk_data);
+            _GTIFFree (gtif->gt_keys[nIndex].gk_data);
         }
 
-        while( index < gtif->gt_num_keys )
+        while( nIndex < gtif->gt_num_keys )
         {
-            _GTIFmemcpy( gtif->gt_keys + index, 
-                         gtif->gt_keys + index + 1, 
+            _GTIFmemcpy( gtif->gt_keys + nIndex,
+                         gtif->gt_keys + nIndex + 1,
                          sizeof(GeoKey) );
-            gtif->gt_keyindex[gtif->gt_keys[index].gk_key] = index;
-            index++;
+            gtif->gt_keyindex[gtif->gt_keys[nIndex].gk_key] = nIndex;
+            nIndex++;
         }
 
         gtif->gt_num_keys--;
@@ -125,21 +125,21 @@ int GTIFKeySet(GTIF *gtif, geokey_t keyID, tagtype_t type, int count,...)
     {
       case TYPE_SHORT:  sval=(pinfo_t) va_arg(ap, int); val=(char *)&sval;     break;
       case TYPE_DOUBLE: dval=va_arg(ap, dblparam_t); val=(char *)&dval;  break;
-      case TYPE_ASCII: 
+      case TYPE_ASCII:
         val=va_arg(ap, char*);
-        count = strlen(val) + 1; /* force = string length */
+        count = (int)strlen(val) + 1; /* force = string length */
         break;
       default:
         assert( FALSE );
         break;
     }
     va_end(ap);
-    
+
     /* We assume here that there are no multi-valued SHORTS ! */
-    if (index)
+    if (nIndex)
     {
         /* Key already exists */
-        key = gtif->gt_keys+index;
+        key = gtif->gt_keys+nIndex;
         if (type!=key->gk_type || count > key->gk_count)
         {
             /* need to reset data pointer */
@@ -154,8 +154,8 @@ int GTIFKeySet(GTIF *gtif, geokey_t keyID, tagtype_t type, int count,...)
         /* We need to create the key */
         if (gtif->gt_num_keys == MAX_KEYS) return 0;
         key = gtif->gt_keys + ++gtif->gt_num_keys;
-        index = gtif->gt_num_keys;
-        gtif->gt_keyindex[ keyID ] = index;
+        nIndex = gtif->gt_num_keys;
+        gtif->gt_keyindex[ keyID ] = nIndex;
         key->gk_key = keyID;
         key->gk_type = type;
         key->gk_count = count;
@@ -169,7 +169,7 @@ int GTIFKeySet(GTIF *gtif, geokey_t keyID, tagtype_t type, int count,...)
     {
         switch (type)
         {
-          case TYPE_SHORT:  
+          case TYPE_SHORT:
             if (count > 1) return 0;
             data = (char *)&key->gk_data; /* store value *in* data */
             break;
@@ -190,12 +190,12 @@ int GTIFKeySet(GTIF *gtif, geokey_t keyID, tagtype_t type, int count,...)
     /* this fixes a bug where if a request is made to write a duplicate
        key, we must initialize the data to a valid value.
        Bryan Wells (bryan at athena.bangor.autometric.com) */
-        
+
     else /* no new values, but still have something to write */
     {
         switch (type)
         {
-          case TYPE_SHORT:  
+          case TYPE_SHORT:
             if (count > 1) return 0;
             data = (char *)&key->gk_data; /* store value *in* data */
             break;
@@ -208,7 +208,7 @@ int GTIFKeySet(GTIF *gtif, geokey_t keyID, tagtype_t type, int count,...)
             return 0;
         }
     }
-        
+
     switch (type)
     {
       case TYPE_ASCII:
@@ -226,7 +226,7 @@ int GTIFKeySet(GTIF *gtif, geokey_t keyID, tagtype_t type, int count,...)
     }
 
     _GTIFmemcpy(data, val, count*key->gk_size);
-    
+
     gtif->gt_flags |= FLAG_FILE_MODIFIED;
     return 1;
 }
diff --git a/frmts/gtiff/libgeotiff/geo_simpletags.c b/frmts/gtiff/libgeotiff/geo_simpletags.c
index e001782..9db79d8 100644
--- a/frmts/gtiff/libgeotiff/geo_simpletags.c
+++ b/frmts/gtiff/libgeotiff/geo_simpletags.c
@@ -24,7 +24,7 @@
  *                    tags in memory, without depending on libtiff.
  *
  *****************************************************************************/
- 
+
 #include "geotiff.h"    /* public GTIFF interface */
 #include "geo_simpletags.h"
 
@@ -38,12 +38,12 @@ static int        _GTIFSetField (tiff_t *tif, pinfo_t tag, int  count, void *val
 static tagtype_t  _GTIFTagType  (tiff_t *tif, pinfo_t tag);
 
 /*
- * Set up default TIFF handlers. 
+ * Set up default TIFF handlers.
  */
 void GTIFSetSimpleTagsMethods(TIFFMethod *method)
 {
 	if (!method) return;
-	
+
 	method->get = _GTIFGetField;
 	method->set = _GTIFSetField;
 	method->type = _GTIFTagType;
@@ -59,7 +59,7 @@ static int _GTIFGetField (tiff_t *tif, pinfo_t tag, int *count, void *val )
     int item_size, data_type;
     void *internal_value, *ret_value;
 
-    if( !ST_GetKey( (ST_TIFF*) tif, (int) tag, count, &data_type, 
+    if( !ST_GetKey( (ST_TIFF*) tif, (int) tag, count, &data_type,
                     &internal_value ) )
         return 0;
 
@@ -72,12 +72,12 @@ static int _GTIFGetField (tiff_t *tif, pinfo_t tag, int *count, void *val )
     if (!ret_value) return 0;
 
     _TIFFmemcpy( ret_value, internal_value,  item_size * *count );
-	
+
     *(void **)val = ret_value;
     return 1;
 }
 
-/* 
+/*
  * Set a GeoTIFF TIFF field.
  */
 static int _GTIFSetField (tiff_t *tif, pinfo_t tag, int count, void *value )
@@ -101,7 +101,7 @@ static tagtype_t  _GTIFTagType  (tiff_t *tif, pinfo_t tag)
 	tagtype_t ttype;
 
 	(void) tif; /* dummy reference */
-	
+
 	switch (tag)
 	{
 		case GTIFF_ASCIIPARAMS:    ttype=TYPE_ASCII; break;
@@ -112,7 +112,7 @@ static tagtype_t  _GTIFTagType  (tiff_t *tif, pinfo_t tag)
 		case GTIFF_GEOKEYDIRECTORY: ttype=TYPE_SHORT; break;
 		default: ttype = TYPE_UNKNOWN;
 	}
-	
+
 	return ttype;
 }
 
@@ -124,19 +124,19 @@ int ST_TagType( int tag )
 {
     switch (tag)
     {
-      case GTIFF_ASCIIPARAMS:    
+      case GTIFF_ASCIIPARAMS:
         return STT_ASCII;
 
       case GTIFF_PIXELSCALE:
       case GTIFF_TRANSMATRIX:
       case GTIFF_TIEPOINTS:
-      case GTIFF_DOUBLEPARAMS:   
+      case GTIFF_DOUBLEPARAMS:
         return STT_DOUBLE;
 
       case GTIFF_GEOKEYDIRECTORY:
         return STT_SHORT;
     }
-    
+
     return -1;
 }
 
@@ -197,9 +197,9 @@ int ST_SetKey( ST_TIFF *st, int tag, int count, int st_type, void *data )
 /* -------------------------------------------------------------------- */
 /*      We should compute the length if we were not given a count       */
 /* -------------------------------------------------------------------- */
-    if (count == 0 && st_type == STT_ASCII ) 
+    if (count == 0 && st_type == STT_ASCII )
     {
-        count = strlen((char*)data)+1;
+        count = (int)strlen((char*)data)+1;
     }
 
 /* -------------------------------------------------------------------- */
@@ -212,7 +212,8 @@ int ST_SetKey( ST_TIFF *st, int tag, int count, int st_type, void *data )
             free( st->key_list[i].data );
             st->key_list[i].count = count;
             st->key_list[i].type = st_type;
-            st->key_list[i].data = malloc(item_size*count);
+            /* +1 to make clang static analyzer not warn about potential malloc(0) */
+            st->key_list[i].data = malloc(item_size*count+1);
             memcpy( st->key_list[i].data, data, count * item_size );
             return 1;
         }
@@ -227,9 +228,10 @@ int ST_SetKey( ST_TIFF *st, int tag, int count, int st_type, void *data )
     st->key_list[st->key_count-1].tag = tag;
     st->key_list[st->key_count-1].count = count;
     st->key_list[st->key_count-1].type = st_type;
-    st->key_list[st->key_count-1].data = malloc(item_size * count);
+    /* +1 to make clang static analyzer not warn about potential malloc(0) */
+    st->key_list[st->key_count-1].data = malloc(item_size * count+1);
     memcpy( st->key_list[st->key_count-1].data, data, item_size * count );
-    
+
     return 1;
 }
 
@@ -237,7 +239,7 @@ int ST_SetKey( ST_TIFF *st, int tag, int count, int st_type, void *data )
 /*                             ST_GetKey()                              */
 /************************************************************************/
 
-int ST_GetKey( ST_TIFF *st, int tag, int *count, 
+int ST_GetKey( ST_TIFF *st, int tag, int *count,
                int *st_type, void **data_ptr )
 
 {
@@ -259,4 +261,3 @@ int ST_GetKey( ST_TIFF *st, int tag, int *count,
 
     return 0;
 }
-
diff --git a/frmts/gtiff/libgeotiff/geo_simpletags.h b/frmts/gtiff/libgeotiff/geo_simpletags.h
index 666578e..721b4de 100644
--- a/frmts/gtiff/libgeotiff/geo_simpletags.h
+++ b/frmts/gtiff/libgeotiff/geo_simpletags.h
@@ -20,15 +20,15 @@
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************
  *
- *  geo_simpletags.h 
+ *  geo_simpletags.h
  *
  * Provides interface for a "simple tags io in memory" mechanism
  * as an alternative to accessing a real tiff file using libtiff.
  *
  ****************************************************************************/
 
-#ifndef __geo_simpletags_h_
-#define __geo_simpletags_h_
+#ifndef LIBGEOTIFF_GEO_SIMPLETAGS_H_
+#define LIBGEOTIFF_GEO_SIMPLETAGS_H_
 
 #include "geotiff.h"
 
@@ -56,18 +56,18 @@ typedef void *STIFF;
 
 void CPL_DLL GTIFSetSimpleTagsMethods(TIFFMethod *method);
 
-int CPL_DLL ST_SetKey( ST_TIFF *, int tag, int count, 
+int CPL_DLL ST_SetKey( ST_TIFF *, int tag, int count,
                        int st_type, void *data );
-int CPL_DLL ST_GetKey( ST_TIFF *, int tag, int *count, 
+int CPL_DLL ST_GetKey( ST_TIFF *, int tag, int *count,
                        int *st_type, void **data_ptr );
 
-ST_TIFF CPL_DLL *ST_Create();
+ST_TIFF CPL_DLL *ST_Create( void );
 void CPL_DLL ST_Destroy( ST_TIFF * );
 
 int CPL_DLL ST_TagType( int tag );
 
 #if defined(__cplusplus)
-} 
+}
 #endif
 
-#endif /* __geo_simpletags_h_ */
+#endif /* LIBGEOTIFF_GEO_SIMPLETAGS_H_ */
diff --git a/frmts/gtiff/libgeotiff/geo_tiffp.c b/frmts/gtiff/libgeotiff/geo_tiffp.c
index 63ba284..3f253e7 100644
--- a/frmts/gtiff/libgeotiff/geo_tiffp.c
+++ b/frmts/gtiff/libgeotiff/geo_tiffp.c
@@ -15,7 +15,7 @@
  * notice accompanies any products derived therefrom.
  *
  **********************************************************************/
- 
+
 #include "geotiff.h"    /* public GTIFF interface */
 
 #include "geo_tiffp.h"  /* Private TIFF interface */
@@ -29,12 +29,12 @@ static int        _GTIFSetField (tiff_t *tif, pinfo_t tag, int  count, void *val
 static tagtype_t  _GTIFTagType  (tiff_t *tif, pinfo_t tag);
 
 /*
- * Set up default TIFF handlers. 
+ * Set up default TIFF handlers.
  */
 void _GTIFSetDefaultTIFF(TIFFMethod *method)
 {
 	if (!method) return;
-	
+
 	method->get = _GTIFGetField;
 	method->set = _GTIFSetField;
 	method->type = _GTIFTagType;
@@ -49,7 +49,7 @@ gdata_t _GTIFcalloc(gsize_t size)
 
 gdata_t _GTIFrealloc(gdata_t ptr, gsize_t size)
 {
-    return( _TIFFrealloc((tdata_t)ptr, (tsize_t) size) );
+    return _TIFFrealloc((tdata_t)ptr, (tsize_t) size);
 }
 
 void _GTIFmemcpy(gdata_t out,gdata_t in,gsize_t size)
@@ -76,7 +76,7 @@ static int _GTIFGetField (tiff_t *tif, pinfo_t tag, int *count, void *val )
 	char *tmp;
 	char *value;
 	gsize_t size = _gtiff_size[_GTIFTagType (tif,tag)];
-	
+
 	if (_GTIFTagType(tif,  tag) == TYPE_ASCII)
 	{
 		status = TIFFGetField((TIFF *)tif,tag,&tmp);
@@ -85,19 +85,19 @@ static int _GTIFGetField (tiff_t *tif, pinfo_t tag, int *count, void *val )
 	}
 	else status = TIFFGetField((TIFF *)tif,tag,&scount,&tmp);
 	if (!status) return status;
-	
+
 	*count = scount;
 
 	value = (char *)_GTIFcalloc( (scount+MAX_VALUES)*size);
 	if (!value) return 0;
-	
+
 	_TIFFmemcpy( value, tmp,  size * scount);
-	
+
 	*(char **)val = value;
 	return status;
 }
 
-/* 
+/*
  * Set a GeoTIFF TIFF field.
  */
 static int _GTIFSetField (tiff_t *tif, pinfo_t tag, int count, void *value )
@@ -108,7 +108,7 @@ static int _GTIFSetField (tiff_t *tif, pinfo_t tag, int count, void *value )
 	/* libtiff ASCII uses null-delimiter */
 	if (_GTIFTagType(tif,  tag) == TYPE_ASCII)
 		status = TIFFSetField((TIFF *)tif,tag,value);
-	else 
+	else
 		status = TIFFSetField((TIFF *)tif,tag,scount,value);
 	return status;
 }
@@ -128,7 +128,7 @@ static tagtype_t  _GTIFTagType  (tiff_t *tif, pinfo_t tag)
 	tagtype_t ttype;
 
 	(void) tif; /* dummy reference */
-	
+
 	switch (tag)
 	{
 		case GTIFF_ASCIIPARAMS:    ttype=TYPE_ASCII; break;
@@ -139,7 +139,6 @@ static tagtype_t  _GTIFTagType  (tiff_t *tif, pinfo_t tag)
 		case GTIFF_GEOKEYDIRECTORY: ttype=TYPE_SHORT; break;
 		default: ttype = TYPE_UNKNOWN;
 	}
-	
+
 	return ttype;
 }
-
diff --git a/frmts/gtiff/libgeotiff/geo_tiffp.h b/frmts/gtiff/libgeotiff/geo_tiffp.h
index 0e56cde..f9186c5 100644
--- a/frmts/gtiff/libgeotiff/geo_tiffp.h
+++ b/frmts/gtiff/libgeotiff/geo_tiffp.h
@@ -17,8 +17,8 @@
  *  notice accompanies any products derived therefrom.
  **********************************************************************/
 
-#ifndef __geo_tiffp_h_
-#define __geo_tiffp_h_
+#ifndef LIBGEOTIFF_GEO_TIFFP_H_
+#define LIBGEOTIFF_GEO_TIFFP_H_
 
 /**********************************************************************
  *
@@ -28,7 +28,7 @@
  *    with the appropriate one for your own TIFF parsing routines.
  *
  *   Revision History
- * 
+ *
  *      19 September 1995   ndr    Demoted Intergraph trans matrix.
  *
  **********************************************************************/
@@ -58,12 +58,12 @@ typedef double dblparam_t;
  *   with the appropriate definitions to access the geo-tags
  *
  **********************************************************************/
- 
+
 typedef unsigned short pinfo_t;    /* SHORT ProjectionInfo tag type */
 typedef TIFF    tiff_t;            /* TIFF file descriptor          */
 typedef tdata_t  gdata_t;          /* pointer to data */
 typedef tsize_t  gsize_t;          /* data allocation size */
- 
+
 #define GTIFF_GEOKEYDIRECTORY   TIFFTAG_GEOKEYDIRECTORY /* from xtiffio.h */
 #define GTIFF_DOUBLEPARAMS      TIFFTAG_GEODOUBLEPARAMS
 #define GTIFF_ASCIIPARAMS       TIFFTAG_GEOASCIIPARAMS
@@ -91,7 +91,7 @@ typedef struct     _TIFFMethod {
 
 /**********************************************************************
  *
- *               Protected Function Declarations  
+ *               Protected Function Declarations
  *
  *   These routines are exposed implementations, and should not
  *   be used by external GEOTIFF client programs.
@@ -106,8 +106,8 @@ extern void CPL_DLL _GTIFFree(gdata_t data);
 extern void CPL_DLL _GTIFmemcpy(gdata_t out,gdata_t in,gsize_t size);
 
 #if defined(__cplusplus)
-} 
+}
 #endif
 
 
-#endif /* __geo_tiffp_h_ */
+#endif /* LIBGEOTIFF_GEO_TIFFP_H_ */
diff --git a/frmts/gtiff/libgeotiff/geo_trans.c b/frmts/gtiff/libgeotiff/geo_trans.c
index 0ea9107..8f5460f 100644
--- a/frmts/gtiff/libgeotiff/geo_trans.c
+++ b/frmts/gtiff/libgeotiff/geo_trans.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: geo_trans.c 1568 2009-04-22 21:10:55Z warmerdam $
+ * $Id: geo_trans.c 2678 2015-10-28 19:06:57Z rouault $
  *
  * Project:  libgeotiff
  * Purpose:  Code to abstract translation between pixel/line and PCS
@@ -27,7 +27,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
- 
+
 #include "geotiff.h"
 #include "geo_tiffp.h" /* external TIFF interface */
 #include "geo_keyp.h"  /* private interface       */
@@ -55,7 +55,7 @@ static int inv_geotransform( double *gt_in, double *gt_out )
 
     inv_det = 1.0 / det;
 
-    /* compute adjoint, and devide by determinate */
+    /* compute adjoint, and divide by determinate */
 
     gt_out[0] =  gt_in[4] * inv_det;
     gt_out[3] = -gt_in[3] * inv_det;
@@ -73,6 +73,7 @@ static int inv_geotransform( double *gt_in, double *gt_out )
 /*                       GTIFTiepointTranslate()                        */
 /************************************************************************/
 
+static
 int GTIFTiepointTranslate( int gcp_count, double * gcps_in, double * gcps_out,
                            double x_in, double y_in,
                            double *x_out, double *y_out )
@@ -85,7 +86,7 @@ int GTIFTiepointTranslate( int gcp_count, double * gcps_in, double * gcps_out,
     (void) y_in;
     (void) x_out;
     (void) y_out;
-    
+
     /* I would appreciate a _brief_ block of code for doing second order
        polynomial regression here! */
     return FALSE;
@@ -140,7 +141,7 @@ int GTIFImageToPCS( GTIF *gtif, double *x, double *y )
 /*      If the pixelscale count is zero, but we have tiepoints use      */
 /*      the tiepoint based approach.                                    */
 /* -------------------------------------------------------------------- */
-    if( tiepoint_count > 6 && count == 0 ) 
+    if( tiepoint_count > 6 && count == 0 )
     {
         res = GTIFTiepointTranslate( tiepoint_count / 6,
                                      tiepoints, tiepoints + 3,
@@ -150,25 +151,25 @@ int GTIFImageToPCS( GTIF *gtif, double *x, double *y )
 /* -------------------------------------------------------------------- */
 /*	If we have a transformation matrix, use it. 			*/
 /* -------------------------------------------------------------------- */
-    else if( transform_count == 16 ) 
+    else if( transform_count == 16 )
     {
         double x_in = *x, y_in = *y;
 
         *x = x_in * transform[0] + y_in * transform[1] + transform[3];
         *y = x_in * transform[4] + y_in * transform[5] + transform[7];
-        
+
         res = TRUE;
-    } 
+    }
 
 /* -------------------------------------------------------------------- */
 /*      For now we require one tie point, and a valid pixel scale.      */
 /* -------------------------------------------------------------------- */
-    else if( count < 3 || tiepoint_count < 6 ) 
+    else if( count < 3 || tiepoint_count < 6 )
     {
         res = FALSE;
-    } 
+    }
 
-    else 
+    else
     {
         *x = (*x - tiepoints[0]) * pixel_scale[0] + tiepoints[3];
         *y = (*y - tiepoints[1]) * (-1 * pixel_scale[1]) + tiepoints[4];
@@ -179,11 +180,11 @@ int GTIFImageToPCS( GTIF *gtif, double *x, double *y )
 /* -------------------------------------------------------------------- */
 /*      Cleanup                                                         */
 /* -------------------------------------------------------------------- */
-    if(tiepoints)   
+    if(tiepoints)
         _GTIFFree(tiepoints);
     if(pixel_scale)
         _GTIFFree(pixel_scale);
-    if(transform)  
+    if(transform)
         _GTIFFree(transform);
 
     return res;
@@ -197,7 +198,7 @@ int GTIFImageToPCS( GTIF *gtif, double *x, double *y )
  * Translate a projection coordinate to pixel/line coordinates.
  *
  * At this time this function does not support PCS to image translations for
- * tiepoints-only based definitions, only matrix and pixelscale/tiepoints 
+ * tiepoints-only based definitions, only matrix and pixelscale/tiepoints
  * formulations are supposed.
  *
  * @param gtif The handle from GTIFNew() indicating the target file.
@@ -254,7 +255,7 @@ int GTIFPCSToImage( GTIF *gtif, double *x, double *y )
     {
         double  x_in = *x, y_in = *y;
         double	gt_in[6], gt_out[6];
-        
+
         gt_in[0] = transform[0];
         gt_in[1] = transform[1];
         gt_in[2] = transform[3];
@@ -268,7 +269,7 @@ int GTIFPCSToImage( GTIF *gtif, double *x, double *y )
         {
             *x = x_in * gt_out[0] + y_in * gt_out[1] + gt_out[2];
             *y = x_in * gt_out[3] + y_in * gt_out[4] + gt_out[5];
-            
+
             result = TRUE;
         }
     }
@@ -287,13 +288,12 @@ int GTIFPCSToImage( GTIF *gtif, double *x, double *y )
 /* -------------------------------------------------------------------- */
 /*      Cleanup.                                                        */
 /* -------------------------------------------------------------------- */
-    if(tiepoints)   
+    if(tiepoints)
         _GTIFFree(tiepoints);
     if(pixel_scale)
         _GTIFFree(pixel_scale);
-    if(transform)  
+    if(transform)
         _GTIFFree(transform);
 
     return result;
 }
-
diff --git a/frmts/gtiff/libgeotiff/geo_write.c b/frmts/gtiff/libgeotiff/geo_write.c
index 344d4bd..777d15e 100644
--- a/frmts/gtiff/libgeotiff/geo_write.c
+++ b/frmts/gtiff/libgeotiff/geo_write.c
@@ -21,13 +21,13 @@ static int SortKeys(GTIF* gt,int *sortkeys);
 
 
 /**
-This function flushes all the GeoTIFF keys that have been set with the 
-GTIFKeySet() function into the associated 
+This function flushes all the GeoTIFF keys that have been set with the
+GTIFKeySet() function into the associated
 TIFF file.
 
 @param gt The GeoTIFF handle returned by GTIFNew.
 
-GTIFWriteKeys() should be called before 
+GTIFWriteKeys() should be called before
 GTIFFree() is used to deallocate a GeoTIFF access handle.
  */
 
@@ -39,12 +39,12 @@ int GTIFWriteKeys(GTIF *gt)
     KeyHeader *header;
     TempKeyData tempData;
     int sortkeys[MAX_KEYS];
-	
+
     if (!(gt->gt_flags & FLAG_FILE_MODIFIED)) return 1;
 
     if( gt->gt_tif == NULL )
         return 0;
-	
+
     tempData.tk_asciiParams = 0;
     tempData.tk_asciiParamsLength = 0;
     tempData.tk_asciiParamsOffset = 0;
@@ -54,14 +54,14 @@ int GTIFWriteKeys(GTIF *gt)
     {
         /* XXX error: a key was not recognized */
     }
-	
+
     /* Set up header of ProjectionInfo tag */
     header = (KeyHeader *)gt->gt_short;
     header->hdr_num_keys = (pinfo_t) gt->gt_num_keys;
     header->hdr_version  = GvCurrentVersion;
     header->hdr_rev_major  = GvCurrentRevision;
     header->hdr_rev_minor  = GvCurrentMinorRev;
-	
+
     /* Sum up the ASCII tag lengths */
     for (i = 0; i < gt->gt_num_keys; i++)
     {
@@ -75,6 +75,8 @@ int GTIFWriteKeys(GTIF *gt)
     {
         tempData.tk_asciiParams =
             (char *)_GTIFcalloc(tempData.tk_asciiParamsLength + 1);
+        if( tempData.tk_asciiParams == NULL )
+            return 0;
         tempData.tk_asciiParams[tempData.tk_asciiParamsLength] = '\0';
     }
 
@@ -83,12 +85,19 @@ int GTIFWriteKeys(GTIF *gt)
     entptr = (KeyEntry*)(gt->gt_short + 4);
     for (i=0; i< gt->gt_num_keys; i++,entptr++)
     {
-        if (!WriteKey(gt,&tempData,entptr,keyptr+sortkeys[i])) return 0;
-    }	
-	
+        if (!WriteKey(gt,&tempData,entptr,keyptr+sortkeys[i]))
+        {
+            if (tempData.tk_asciiParamsLength > 0)
+            {
+                _GTIFFree (tempData.tk_asciiParams);
+            }
+            return 0;
+        }
+    }
+
     /* Write out the Key Directory */
-    (gt->gt_methods.set)(gt->gt_tif, GTIFF_GEOKEYDIRECTORY, gt->gt_nshorts, gt->gt_short );	
-	
+    (gt->gt_methods.set)(gt->gt_tif, GTIFF_GEOKEYDIRECTORY, gt->gt_nshorts, gt->gt_short );
+
     /* Write out the params directories */
     if (gt->gt_ndoubles)
         (gt->gt_methods.set)(gt->gt_tif, GTIFF_DOUBLEPARAMS, gt->gt_ndoubles, gt->gt_double );
@@ -99,7 +108,7 @@ int GTIFWriteKeys(GTIF *gt)
         (gt->gt_methods.set)(gt->gt_tif,
                              GTIFF_ASCIIPARAMS, 0, tempData.tk_asciiParams);
     }
-	
+
     gt->gt_flags &= ~FLAG_FILE_MODIFIED;
 
     if (tempData.tk_asciiParamsLength > 0)
@@ -114,7 +123,7 @@ int GTIFWriteKeys(GTIF *gt)
  *                        Private Routines
  *
  **********************************************************************/
- 
+
 /*
  * Given GeoKey, write out the KeyEntry entries, returning 0 if failure.
  *  This is the exact complement of ReadKey().
@@ -124,18 +133,18 @@ static int WriteKey(GTIF* gt, TempKeyData* tempData,
                     KeyEntry* entptr, GeoKey* keyptr)
 {
     int count;
-	
+
     entptr->ent_key = (pinfo_t) keyptr->gk_key;
     entptr->ent_count = (pinfo_t) keyptr->gk_count;
     count = entptr->ent_count;
-	
+
     if (count==1 && keyptr->gk_type==TYPE_SHORT)
     {
         entptr->ent_location = GTIFF_LOCAL;
         memcpy(&(entptr->ent_val_offset), &keyptr->gk_data, sizeof(pinfo_t));
         return 1;
     }
-		  
+
     switch (keyptr->gk_type)
     {
       case TYPE_SHORT:
@@ -145,10 +154,12 @@ static int WriteKey(GTIF* gt, TempKeyData* tempData,
         break;
       case TYPE_DOUBLE:
         entptr->ent_location = GTIFF_DOUBLEPARAMS;
-        entptr->ent_val_offset = (pinfo_t) 
+        entptr->ent_val_offset = (pinfo_t)
             ((double*)keyptr->gk_data - gt->gt_double);
         break;
       case TYPE_ASCII:
+        if( tempData->tk_asciiParams == NULL )
+            return 0;
         entptr->ent_location = GTIFF_ASCIIPARAMS;
         entptr->ent_val_offset = (pinfo_t) tempData->tk_asciiParamsOffset;
         _GTIFmemcpy (tempData->tk_asciiParams + tempData->tk_asciiParamsOffset
@@ -159,12 +170,12 @@ static int WriteKey(GTIF* gt, TempKeyData* tempData,
       default:
         return 0; /* failure */
     }
-	
+
     return 1; /* success */
 }
 
 
-/* 
+/*
  * Numerically sort the GeoKeys.
  * We just do a linear search through
  * the list and pull out the keys that were set.
@@ -174,21 +185,26 @@ static int SortKeys(GTIF* gt,int *sortkeys)
 {
     int i, did_work;
 
-    for( i = 0; i < gt->gt_num_keys; i++ )
+    /* A bit convoluted to make Clang Static Analyzer happy */
+    if( gt->gt_num_keys <= 0 )
+        return 1;
+
+    sortkeys[0] = 1;
+    for( i = 1; i < gt->gt_num_keys; i++ )
         sortkeys[i] = i+1;
 
     do {  /* simple bubble sort */
         did_work = 0;
         for( i = 0; i < gt->gt_num_keys-1; i++ )
         {
-            if( gt->gt_keys[sortkeys[i]].gk_key 
+            if( gt->gt_keys[sortkeys[i]].gk_key
                 > gt->gt_keys[sortkeys[i+1]].gk_key )
             {
                 /* swap keys in sort list */
                 int j = sortkeys[i];
                 sortkeys[i] = sortkeys[i+1];
                 sortkeys[i+1] = j;
-                
+
                 did_work = 1;
             }
         }
@@ -196,4 +212,3 @@ static int SortKeys(GTIF* gt,int *sortkeys)
 
     return 1;
 }
-
diff --git a/frmts/gtiff/libgeotiff/geokeys.h b/frmts/gtiff/libgeotiff/geokeys.h
index b3a14c8..8b2d2f2 100644
--- a/frmts/gtiff/libgeotiff/geokeys.h
+++ b/frmts/gtiff/libgeotiff/geokeys.h
@@ -10,14 +10,14 @@
  *  notice accompanies any products derived therefrom.
  **********************************************************************/
 
-#ifndef __geokeys_h_
-#define __geokeys_h_
+#ifndef LIBGEOTIFF_GEOKEYS_H_
+#define LIBGEOTIFF_GEOKEYS_H_
 
-/* The GvCurrentRevision number should be incremented whenever a 
- * new set of Keys are defined or modified in "geokeys.inc", and comments 
+/* The GvCurrentRevision number should be incremented whenever a
+ * new set of Keys are defined or modified in "geokeys.inc", and comments
  * added to the "Revision History" section above. If only code
  * _values_ are augmented, the "GvCurrentMinorRev" number should
- * be incremented instead (see "geovalues.h"). Whenever the 
+ * be incremented instead (see "geovalues.h"). Whenever the
  * GvCurrentRevision is incremented, the GvCurrentMinorRev should
  * be reset to zero.
  *
@@ -39,13 +39,13 @@ typedef enum {
 #  include "geokeys.inc"         /* geokey database */
 
    ReservedEndGeoKey  =  32767,
-   
+
    /* Key space available for Private or internal use */
    PrivateBaseGeoKey = 32768,    /* Consistent with TIFF Private tags */
-   PrivateEndGeoKey  = 65535,    
-   
+   PrivateEndGeoKey  = 65535,
+
    EndGeoKey = 65535             /* Largest Possible GeoKey ID */
 } geokey_t;
 
 
-#endif /* __geokeys_h_ */
+#endif /* LIBGEOTIFF_GEOKEYS_H_ */
diff --git a/frmts/gtiff/libgeotiff/geokeys.inc b/frmts/gtiff/libgeotiff/geokeys.inc
index 03be6e0..21263e2 100644
--- a/frmts/gtiff/libgeotiff/geokeys.inc
+++ b/frmts/gtiff/libgeotiff/geokeys.inc
@@ -68,7 +68,7 @@ ValuePair(  ProjStraightVertPoleLongGeoKey, 3095) /* GeogAngularUnit */
 ValuePair(  ProjRectifiedGridAngleGeoKey, 3096)   /* GeogAngularUnit */
 
 /* 6.2.4 Vertical CS Keys */
-   
+
 ValuePair(  VerticalCSTypeGeoKey,	4096)  /* Section 6.3.4.1 codes   */
 ValuePair(  VerticalCitationGeoKey,	4097)  /* documentation */
 ValuePair(  VerticalDatumGeoKey,	4098)  /* Section 6.3.4.2 codes   */
diff --git a/frmts/gtiff/libgeotiff/geonames.h b/frmts/gtiff/libgeotiff/geonames.h
index 37670c4..851cc5f 100644
--- a/frmts/gtiff/libgeotiff/geonames.h
+++ b/frmts/gtiff/libgeotiff/geonames.h
@@ -1,8 +1,8 @@
 /*
  * geonames.h
  *
- *  This encapsulates all of the value-naming mechanism of 
- *  libgeotiff. 
+ *  This encapsulates all of the value-naming mechanism of
+ *  libgeotiff.
  *
  *  Written By: Niles Ritter
  *
@@ -12,8 +12,8 @@
  *  notice accompanies any products derived therefrom.
  */
 
-#ifndef __geonames_h
-#define __geonames_h
+#ifndef LIBGEOTIFF_GEONAMES_H_
+#define LIBGEOTIFF_GEONAMES_H_
 
 struct _KeyInfo {
 	int ki_key;
@@ -21,8 +21,8 @@ struct _KeyInfo {
 };
 typedef struct _KeyInfo KeyInfo;
 
-/* If memory is a premium, then omitting the 
- * long name lists may save some space; simply 
+/* If memory is a premium, then omitting the
+ * long name lists may save some space; simply
  * #define OMIT_GEOTIFF_NAMES in the compile statement
  * to remove all key->string translation.
  */
@@ -42,7 +42,7 @@ typedef struct _KeyInfo KeyInfo;
  *         6.2.x GeoTIFF Keys
  ************************************************************/
 
-static KeyInfo _keyInfo[] =  {
+static const KeyInfo _keyInfo[] =  {
 #   include "geokeys.inc"   /* geokey database */
     END_LIST
 };
@@ -51,18 +51,18 @@ static KeyInfo _keyInfo[] =  {
    {KvUndefined, "Undefined"}, \
    {KvUserDefined,"User-Defined"}, \
    ValuePair(KvUndefined,KvUndefined) \
-   ValuePair(KvUserDefined,KvUserDefined) 
+   ValuePair(KvUserDefined,KvUserDefined)
 
-static KeyInfo _csdefaultValue[] = {
+static const KeyInfo _csdefaultValue[] = {
    COMMON_VALUES
-   END_LIST  
+   END_LIST
 };
 
 /************************************************************
  *         6.3.x GeoTIFF Key Values
  ************************************************************/
 
-static KeyInfo _modeltypeValue[] = {
+static const KeyInfo _modeltypeValue[] = {
    COMMON_VALUES
     ValuePair(ModelTypeProjected,1)
     ValuePair(ModelTypeGeographic,2)
@@ -70,75 +70,74 @@ static KeyInfo _modeltypeValue[] = {
     ValuePair(ModelProjected,1)     /* aliases */
     ValuePair(ModelGeographic,2)    /* aliases */
     ValuePair(ModelGeocentric,3)    /* aliases */
-   END_LIST  
+   END_LIST
 };
 
-static KeyInfo _rastertypeValue[] = {
+static const KeyInfo _rastertypeValue[] = {
    COMMON_VALUES
     ValuePair(RasterPixelIsArea,1)
     ValuePair(RasterPixelIsPoint,2)
-   END_LIST  
+   END_LIST
 };
 
-static KeyInfo _geounitsValue[] = {
+static const KeyInfo _geounitsValue[] = {
    COMMON_VALUES
 #  include "epsg_units.inc"
-   END_LIST  
+   END_LIST
 };
 
-static KeyInfo _geographicValue[] = {
+static const KeyInfo _geographicValue[] = {
    COMMON_VALUES
 #  include "epsg_gcs.inc"
-   END_LIST  
+   END_LIST
 };
 
-static KeyInfo _geodeticdatumValue[] = {
+static const KeyInfo _geodeticdatumValue[] = {
    COMMON_VALUES
 #  include "epsg_datum.inc"
-   END_LIST  
+   END_LIST
 };
 
-static KeyInfo _ellipsoidValue[] = {
+static const KeyInfo _ellipsoidValue[] = {
    COMMON_VALUES
 #  include "epsg_ellipse.inc"
-   END_LIST  
+   END_LIST
 };
 
-static KeyInfo _primemeridianValue[] = {
+static const KeyInfo _primemeridianValue[] = {
    COMMON_VALUES
 #  include "epsg_pm.inc"
-   END_LIST  
+   END_LIST
 };
 
-static KeyInfo _pcstypeValue[] = {
+static const KeyInfo _pcstypeValue[] = {
    COMMON_VALUES
 #  include "epsg_pcs.inc"
-   END_LIST  
+   END_LIST
 };
 
-static KeyInfo _projectionValue[] = {
+static const KeyInfo _projectionValue[] = {
    COMMON_VALUES
 #  include "epsg_proj.inc"
-   END_LIST  
+   END_LIST
 };
 
-static KeyInfo _coordtransValue[] = {
+static const KeyInfo _coordtransValue[] = {
    COMMON_VALUES
 #  include "geo_ctrans.inc"
-   END_LIST  
+   END_LIST
 };
 
-static KeyInfo _vertcstypeValue[] = {
+static const KeyInfo _vertcstypeValue[] = {
    COMMON_VALUES
 #  include "epsg_vertcs.inc"
-   END_LIST  
+   END_LIST
 };
 
-static KeyInfo _vdatumValue[] = {
+static const KeyInfo _vdatumValue[] = {
    COMMON_VALUES
     ValuePair(VDatumBase,1)
-   END_LIST  
+   END_LIST
 };
 
-#endif /* __geonames_h */
-
+#endif /* LIBGEOTIFF_GEONAMES_H_ */
diff --git a/frmts/gtiff/libgeotiff/geotiff.h b/frmts/gtiff/libgeotiff/geotiff.h
index 6bf9ba2..2cab1bb 100644
--- a/frmts/gtiff/libgeotiff/geotiff.h
+++ b/frmts/gtiff/libgeotiff/geotiff.h
@@ -10,15 +10,15 @@
  *  notice accompanies any products derived therefrom.
  **********************************************************************/
 
-#ifndef __geotiff_h_
-#define __geotiff_h_
+#ifndef LIBGEOTIFF_GEOTIFF_H_
+#define LIBGEOTIFF_GEOTIFF_H_
 
 /**
  * \file geotiff.h
  *
  * Primary libgeotiff include file.
  *
- * This is the defacto registry for valid GEOTIFF GeoKeys
+ * This is the de facto registry for valid GeoTIFF GeoKeys
  * and their associated symbolic values. This is also the only file
  * of the GeoTIFF library which needs to be included in client source
  * code.
@@ -120,4 +120,4 @@ int CPL_DLL    GTIFPCSToImage( GTIF *gtif, double *x, double *y );
 }
 #endif
 
-#endif /* __geotiff_h_ */
+#endif /* LIBGEOTIFF_GEOTIFF_H_ */
diff --git a/frmts/gtiff/libgeotiff/geotiff_proj4.c b/frmts/gtiff/libgeotiff/geotiff_proj4.c
index 129f687..6c0e2c5 100644
--- a/frmts/gtiff/libgeotiff/geotiff_proj4.c
+++ b/frmts/gtiff/libgeotiff/geotiff_proj4.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: geotiff_proj4.c 2594 2014-12-27 16:46:35Z rouault $
+ * $Id: geotiff_proj4.c 2653 2015-05-02 12:07:17Z rouault $
  *
  * Project:  libgeotiff
  * Purpose:  Code to convert a normalized GeoTIFF definition into a PROJ.4
@@ -33,6 +33,7 @@
 #include "geotiff.h"
 #include "geo_normalize.h"
 #include "geovalues.h"
+#include "geo_tiffp.h"
 
 /************************************************************************/
 /*                          OSRProj4Tokenize()                          */
@@ -117,7 +118,7 @@ static const char *OSR_GSV( char **papszNV, const char * pszField )
 {
     size_t field_len = strlen(pszField);
     int i;
-    
+
     if( !papszNV )
         return NULL;
 
@@ -144,7 +145,7 @@ static const char *OSR_GSV( char **papszNV, const char * pszField )
 /*      helper function for importFromProj4().                          */
 /************************************************************************/
 
-static double OSR_GDV( char **papszNV, const char * pszField, 
+static double OSR_GDV( char **papszNV, const char * pszField,
                        double dfDefaultValue )
 
 {
@@ -186,7 +187,7 @@ int GTIFSetFromProj4( GTIF *gtif, const char *proj4 )
     short nSpheroid = KvUserDefined;
     double dfSemiMajor=0.0, dfSemiMinor=0.0, dfInvFlattening=0.0;
     int	   nDatum = KvUserDefined;
-    int    nGCS = KvUserDefined;    
+    int    nGCS = KvUserDefined;
     const char  *value;
 
 /* -------------------------------------------------------------------- */
@@ -215,13 +216,13 @@ int GTIFSetFromProj4( GTIF *gtif, const char *proj4 )
         if( dfSemiMinor != 0.0 && dfInvFlattening == 0.0 )
             dfInvFlattening = -1.0 / (dfSemiMinor/dfSemiMajor - 1.0);
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Get the GCS/Datum code.                                         */
 /* -------------------------------------------------------------------- */
     value = OSR_GSV( papszNV, "datum" );
 
-    if( value == NULL ) 
+    if( value == NULL )
     {
     }
     else if( EQUAL(value,"WGS84") )
@@ -254,7 +255,7 @@ int GTIFSetFromProj4( GTIF *gtif, const char *proj4 )
     else if( EQUAL(value,"longlat") || EQUAL(value,"latlong") )
     {
     }
-    
+
     else if( EQUAL(value,"tmerc") )
     {
 	GTIFKeySet(gtif, GTModelTypeGeoKey, TYPE_SHORT, 1,
@@ -264,7 +265,7 @@ int GTIFSetFromProj4( GTIF *gtif, const char *proj4 )
 	GTIFKeySet(gtif, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-	GTIFKeySet(gtif, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+	GTIFKeySet(gtif, ProjCoordTransGeoKey, TYPE_SHORT, 1,
 		   CT_TransverseMercator );
 
         GTIFKeySet(gtif, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
@@ -272,13 +273,13 @@ int GTIFSetFromProj4( GTIF *gtif, const char *proj4 )
 
         GTIFKeySet(gtif, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
                    OSR_GDV( papszNV, "lon_0", 0.0 ) );
-        
+
         GTIFKeySet(gtif, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
                    OSR_GDV( papszNV, "k", 1.0 ) );
-        
+
         GTIFKeySet(gtif, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
                    OSR_GDV( papszNV, "x_0", 0.0 ) );
-        
+
         GTIFKeySet(gtif, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
@@ -287,7 +288,7 @@ int GTIFSetFromProj4( GTIF *gtif, const char *proj4 )
     {
         int nZone = (int) OSR_GDV(papszNV,"zone",0);
         const char *south = OSR_GSV(papszNV,"south");
-                         
+
 	GTIFKeySet(gtif, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
 	GTIFKeySet(gtif, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
@@ -295,18 +296,18 @@ int GTIFSetFromProj4( GTIF *gtif, const char *proj4 )
 	GTIFKeySet(gtif, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-	GTIFKeySet(gtif, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+	GTIFKeySet(gtif, ProjCoordTransGeoKey, TYPE_SHORT, 1,
 		   CT_TransverseMercator );
 
-        GTIFKeySet(gtif, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, 
+        GTIFKeySet(gtif, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
                    0.0 );
 
         GTIFKeySet(gtif, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
                    nZone * 6 - 183.0 );
-        
+
         GTIFKeySet(gtif, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
                    0.9996 );
-        
+
         GTIFKeySet(gtif, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
                    500000.0 );
 
@@ -318,8 +319,8 @@ int GTIFSetFromProj4( GTIF *gtif, const char *proj4 )
                        0.0 );
     }
 
-    else if( EQUAL(value,"lcc") 
-             && OSR_GDV(papszNV, "lat_0", 0.0 ) 
+    else if( EQUAL(value,"lcc")
+             && OSR_GDV(papszNV, "lat_0", 0.0 )
              == OSR_GDV(papszNV, "lat_1", 0.0 ) )
     {
 	GTIFKeySet(gtif, GTModelTypeGeoKey, TYPE_SHORT, 1,
@@ -329,7 +330,7 @@ int GTIFSetFromProj4( GTIF *gtif, const char *proj4 )
 	GTIFKeySet(gtif, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-	GTIFKeySet(gtif, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+	GTIFKeySet(gtif, ProjCoordTransGeoKey, TYPE_SHORT, 1,
 		   CT_LambertConfConic_1SP );
 
         GTIFKeySet(gtif, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
@@ -337,13 +338,13 @@ int GTIFSetFromProj4( GTIF *gtif, const char *proj4 )
 
         GTIFKeySet(gtif, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
                    OSR_GDV( papszNV, "lon_0", 0.0 ) );
-        
+
         GTIFKeySet(gtif, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
                    OSR_GDV( papszNV, "k", 1.0 ) );
-        
+
         GTIFKeySet(gtif, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
                    OSR_GDV( papszNV, "x_0", 0.0 ) );
-        
+
         GTIFKeySet(gtif, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
@@ -357,7 +358,7 @@ int GTIFSetFromProj4( GTIF *gtif, const char *proj4 )
 	GTIFKeySet(gtif, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-	GTIFKeySet(gtif, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+	GTIFKeySet(gtif, ProjCoordTransGeoKey, TYPE_SHORT, 1,
 		   CT_LambertConfConic_2SP );
 
         GTIFKeySet(gtif, ProjFalseOriginLatGeoKey, TYPE_DOUBLE, 1,
@@ -365,16 +366,16 @@ int GTIFSetFromProj4( GTIF *gtif, const char *proj4 )
 
         GTIFKeySet(gtif, ProjFalseOriginLongGeoKey, TYPE_DOUBLE, 1,
                    OSR_GDV( papszNV, "lon_0", 0.0 ) );
-        
+
         GTIFKeySet(gtif, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1,
                    OSR_GDV( papszNV, "lat_1", 0.0 ) );
-        
+
         GTIFKeySet(gtif, ProjStdParallel2GeoKey, TYPE_DOUBLE, 1,
                    OSR_GDV( papszNV, "lat_2", 0.0 ) );
-        
+
         GTIFKeySet(gtif, ProjFalseOriginEastingGeoKey, TYPE_DOUBLE, 1,
                    OSR_GDV( papszNV, "x_0", 0.0 ) );
-        
+
         GTIFKeySet(gtif, ProjFalseOriginNorthingGeoKey, TYPE_DOUBLE, 1,
                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
@@ -382,91 +383,91 @@ int GTIFSetFromProj4( GTIF *gtif, const char *proj4 )
 #ifdef notdef
     else if( EQUAL(value,"bonne") )
     {
-        SetBonne( OSR_GDV( papszNV, "lat_1", 0.0 ), 
-                  OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                  OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetBonne( OSR_GDV( papszNV, "lat_1", 0.0 ),
+                  OSR_GDV( papszNV, "lon_0", 0.0 ),
+                  OSR_GDV( papszNV, "x_0", 0.0 ),
                   OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value,"cass") )
     {
-        SetCS( OSR_GDV( papszNV, "lat_0", 0.0 ), 
-               OSR_GDV( papszNV, "lon_0", 0.0 ), 
-               OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetCS( OSR_GDV( papszNV, "lat_0", 0.0 ),
+               OSR_GDV( papszNV, "lon_0", 0.0 ),
+               OSR_GDV( papszNV, "x_0", 0.0 ),
                OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value,"nzmg") )
     {
-        SetNZMG( OSR_GDV( papszNV, "lat_0", -41.0 ), 
-                 OSR_GDV( papszNV, "lon_0", 173.0 ), 
-                 OSR_GDV( papszNV, "x_0", 2510000.0 ), 
+        SetNZMG( OSR_GDV( papszNV, "lat_0", -41.0 ),
+                 OSR_GDV( papszNV, "lon_0", 173.0 ),
+                 OSR_GDV( papszNV, "x_0", 2510000.0 ),
                  OSR_GDV( papszNV, "y_0", 6023150.0 ) );
     }
 
     else if( EQUAL(value,"cea") )
     {
-        SetCEA( OSR_GDV( papszNV, "lat_ts", 0.0 ), 
-                OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetCEA( OSR_GDV( papszNV, "lat_ts", 0.0 ),
+                OSR_GDV( papszNV, "lon_0", 0.0 ),
+                OSR_GDV( papszNV, "x_0", 0.0 ),
                 OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value,"merc") /* 2SP form */
              && OSR_GDV(papszNV, "lat_ts", 1000.0) < 999.0 )
     {
-        SetMercator2SP( OSR_GDV( papszNV, "lat_ts", 0.0 ), 
+        SetMercator2SP( OSR_GDV( papszNV, "lat_ts", 0.0 ),
                         0.0,
-                        OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                        OSR_GDV( papszNV, "x_0", 0.0 ), 
+                        OSR_GDV( papszNV, "lon_0", 0.0 ),
+                        OSR_GDV( papszNV, "x_0", 0.0 ),
                         OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value,"merc") ) /* 1SP form */
     {
         SetMercator( 0.0,
-                     OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                     OSR_GDV( papszNV, "k", 1.0 ), 
-                     OSR_GDV( papszNV, "x_0", 0.0 ), 
+                     OSR_GDV( papszNV, "lon_0", 0.0 ),
+                     OSR_GDV( papszNV, "k", 1.0 ),
+                     OSR_GDV( papszNV, "x_0", 0.0 ),
                      OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
-    else if( EQUAL(value,"stere") 
+    else if( EQUAL(value,"stere")
              && ABS(OSR_GDV( papszNV, "lat_0", 0.0 ) - 90) < 0.001 )
     {
-        SetPS( OSR_GDV( papszNV, "lat_ts", 90.0 ), 
-               OSR_GDV( papszNV, "lon_0", 0.0 ), 
-               OSR_GDV( papszNV, "k", 1.0 ), 
-               OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetPS( OSR_GDV( papszNV, "lat_ts", 90.0 ),
+               OSR_GDV( papszNV, "lon_0", 0.0 ),
+               OSR_GDV( papszNV, "k", 1.0 ),
+               OSR_GDV( papszNV, "x_0", 0.0 ),
                OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
-    else if( EQUAL(value,"stere") 
+    else if( EQUAL(value,"stere")
              && ABS(OSR_GDV( papszNV, "lat_0", 0.0 ) + 90) < 0.001 )
     {
-        SetPS( OSR_GDV( papszNV, "lat_ts", -90.0 ), 
-               OSR_GDV( papszNV, "lon_0", 0.0 ), 
-               OSR_GDV( papszNV, "k", 1.0 ), 
-               OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetPS( OSR_GDV( papszNV, "lat_ts", -90.0 ),
+               OSR_GDV( papszNV, "lon_0", 0.0 ),
+               OSR_GDV( papszNV, "k", 1.0 ),
+               OSR_GDV( papszNV, "x_0", 0.0 ),
                OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUALN(value,"stere",5) /* mostly sterea */
              && CSLFetchNameValue(papszNV,"k") != NULL )
     {
-        SetOS( OSR_GDV( papszNV, "lat_0", 0.0 ), 
-               OSR_GDV( papszNV, "lon_0", 0.0 ), 
-               OSR_GDV( papszNV, "k", 1.0 ), 
-               OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetOS( OSR_GDV( papszNV, "lat_0", 0.0 ),
+               OSR_GDV( papszNV, "lon_0", 0.0 ),
+               OSR_GDV( papszNV, "k", 1.0 ),
+               OSR_GDV( papszNV, "x_0", 0.0 ),
                OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value,"stere") )
     {
-        SetStereographic( OSR_GDV( papszNV, "lat_0", 0.0 ), 
-                          OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                          1.0, 
-                          OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetStereographic( OSR_GDV( papszNV, "lat_0", 0.0 ),
+                          OSR_GDV( papszNV, "lon_0", 0.0 ),
+                          1.0,
+                          OSR_GDV( papszNV, "x_0", 0.0 ),
                           OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
@@ -496,212 +497,212 @@ int GTIFSetFromProj4( GTIF *gtif, const char *proj4 )
 
     else if( EQUAL(value,"gnom") )
     {
-        SetGnomonic( OSR_GDV( papszNV, "lat_0", 0.0 ), 
-                     OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                     OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetGnomonic( OSR_GDV( papszNV, "lat_0", 0.0 ),
+                     OSR_GDV( papszNV, "lon_0", 0.0 ),
+                     OSR_GDV( papszNV, "x_0", 0.0 ),
                      OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value,"ortho") )
     {
-        SetOrthographic( OSR_GDV( papszNV, "lat_0", 0.0 ), 
-                         OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                         OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetOrthographic( OSR_GDV( papszNV, "lat_0", 0.0 ),
+                         OSR_GDV( papszNV, "lon_0", 0.0 ),
+                         OSR_GDV( papszNV, "x_0", 0.0 ),
                          OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value,"laea") )
     {
-        SetLAEA( OSR_GDV( papszNV, "lat_0", 0.0 ), 
-                 OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                 OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetLAEA( OSR_GDV( papszNV, "lat_0", 0.0 ),
+                 OSR_GDV( papszNV, "lon_0", 0.0 ),
+                 OSR_GDV( papszNV, "x_0", 0.0 ),
                  OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value,"aeqd") )
     {
-        SetAE( OSR_GDV( papszNV, "lat_0", 0.0 ), 
-               OSR_GDV( papszNV, "lon_0", 0.0 ), 
-               OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetAE( OSR_GDV( papszNV, "lat_0", 0.0 ),
+               OSR_GDV( papszNV, "lon_0", 0.0 ),
+               OSR_GDV( papszNV, "x_0", 0.0 ),
                OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value,"eqdc") )
     {
-        SetEC( OSR_GDV( papszNV, "lat_1", 0.0 ), 
-               OSR_GDV( papszNV, "lat_2", 0.0 ), 
-               OSR_GDV( papszNV, "lat_0", 0.0 ), 
-               OSR_GDV( papszNV, "lon_0", 0.0 ), 
-               OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetEC( OSR_GDV( papszNV, "lat_1", 0.0 ),
+               OSR_GDV( papszNV, "lat_2", 0.0 ),
+               OSR_GDV( papszNV, "lat_0", 0.0 ),
+               OSR_GDV( papszNV, "lon_0", 0.0 ),
+               OSR_GDV( papszNV, "x_0", 0.0 ),
                OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value,"mill") )
     {
-        SetMC( OSR_GDV( papszNV, "lat_0", 0.0 ), 
-               OSR_GDV( papszNV, "lon_0", 0.0 ), 
-               OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetMC( OSR_GDV( papszNV, "lat_0", 0.0 ),
+               OSR_GDV( papszNV, "lon_0", 0.0 ),
+               OSR_GDV( papszNV, "x_0", 0.0 ),
                OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value,"moll") )
     {
-        SetMollweide( OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                      OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetMollweide( OSR_GDV( papszNV, "lon_0", 0.0 ),
+                      OSR_GDV( papszNV, "x_0", 0.0 ),
                       OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value,"eck4") )
     {
-        SetEckertIV( OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                     OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetEckertIV( OSR_GDV( papszNV, "lon_0", 0.0 ),
+                     OSR_GDV( papszNV, "x_0", 0.0 ),
                      OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value,"eck6") )
     {
-        SetEckertVI( OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                     OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetEckertVI( OSR_GDV( papszNV, "lon_0", 0.0 ),
+                     OSR_GDV( papszNV, "x_0", 0.0 ),
                      OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value,"poly") )
     {
-        SetPolyconic( OSR_GDV( papszNV, "lat_0", 0.0 ), 
-                      OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                      OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetPolyconic( OSR_GDV( papszNV, "lat_0", 0.0 ),
+                      OSR_GDV( papszNV, "lon_0", 0.0 ),
+                      OSR_GDV( papszNV, "x_0", 0.0 ),
                       OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value,"aea") )
     {
-        SetACEA( OSR_GDV( papszNV, "lat_1", 0.0 ), 
-                 OSR_GDV( papszNV, "lat_2", 0.0 ), 
-                 OSR_GDV( papszNV, "lat_0", 0.0 ), 
-                 OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                 OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetACEA( OSR_GDV( papszNV, "lat_1", 0.0 ),
+                 OSR_GDV( papszNV, "lat_2", 0.0 ),
+                 OSR_GDV( papszNV, "lat_0", 0.0 ),
+                 OSR_GDV( papszNV, "lon_0", 0.0 ),
+                 OSR_GDV( papszNV, "x_0", 0.0 ),
                  OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value,"robin") )
     {
-        SetRobinson( OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                     OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetRobinson( OSR_GDV( papszNV, "lon_0", 0.0 ),
+                     OSR_GDV( papszNV, "x_0", 0.0 ),
                      OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value,"vandg") )
     {
-        SetVDG( OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetVDG( OSR_GDV( papszNV, "lon_0", 0.0 ),
+                OSR_GDV( papszNV, "x_0", 0.0 ),
                 OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value,"sinu") )
     {
-        SetSinusoidal( OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                       OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetSinusoidal( OSR_GDV( papszNV, "lon_0", 0.0 ),
+                       OSR_GDV( papszNV, "x_0", 0.0 ),
                        OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value,"gall") )
     {
-        SetGS( OSR_GDV( papszNV, "lon_0", 0.0 ), 
-               OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetGS( OSR_GDV( papszNV, "lon_0", 0.0 ),
+               OSR_GDV( papszNV, "x_0", 0.0 ),
                OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value,"goode") )
     {
-        SetGH( OSR_GDV( papszNV, "lon_0", 0.0 ), 
-               OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetGH( OSR_GDV( papszNV, "lon_0", 0.0 ),
+               OSR_GDV( papszNV, "x_0", 0.0 ),
                OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value,"geos") )
     {
-        SetGEOS( OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                 OSR_GDV( papszNV, "h", 35785831.0 ), 
-                 OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetGEOS( OSR_GDV( papszNV, "lon_0", 0.0 ),
+                 OSR_GDV( papszNV, "h", 35785831.0 ),
+                 OSR_GDV( papszNV, "x_0", 0.0 ),
                  OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
-    else if( EQUAL(value,"lcc") ) 
+    else if( EQUAL(value,"lcc") )
     {
-        if( OSR_GDV(papszNV, "lat_0", 0.0 ) 
+        if( OSR_GDV(papszNV, "lat_0", 0.0 )
             == OSR_GDV(papszNV, "lat_1", 0.0 ) )
         {
             /* 1SP form */
-            SetLCC1SP( OSR_GDV( papszNV, "lat_0", 0.0 ), 
-                       OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                       OSR_GDV( papszNV, "k_0", 1.0 ), 
-                       OSR_GDV( papszNV, "x_0", 0.0 ), 
+            SetLCC1SP( OSR_GDV( papszNV, "lat_0", 0.0 ),
+                       OSR_GDV( papszNV, "lon_0", 0.0 ),
+                       OSR_GDV( papszNV, "k_0", 1.0 ),
+                       OSR_GDV( papszNV, "x_0", 0.0 ),
                        OSR_GDV( papszNV, "y_0", 0.0 ) );
         }
         else
         {
             /* 2SP form */
-            SetLCC( OSR_GDV( papszNV, "lat_1", 0.0 ), 
-                    OSR_GDV( papszNV, "lat_2", 0.0 ), 
-                    OSR_GDV( papszNV, "lat_0", 0.0 ), 
-                    OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                    OSR_GDV( papszNV, "x_0", 0.0 ), 
+            SetLCC( OSR_GDV( papszNV, "lat_1", 0.0 ),
+                    OSR_GDV( papszNV, "lat_2", 0.0 ),
+                    OSR_GDV( papszNV, "lat_0", 0.0 ),
+                    OSR_GDV( papszNV, "lon_0", 0.0 ),
+                    OSR_GDV( papszNV, "x_0", 0.0 ),
                     OSR_GDV( papszNV, "y_0", 0.0 ) );
         }
     }
 
     else if( EQUAL(value,"omerc") )
     {
-        SetHOM( OSR_GDV( papszNV, "lat_0", 0.0 ), 
-                OSR_GDV( papszNV, "lonc", 0.0 ), 
-                OSR_GDV( papszNV, "alpha", 0.0 ), 
+        SetHOM( OSR_GDV( papszNV, "lat_0", 0.0 ),
+                OSR_GDV( papszNV, "lonc", 0.0 ),
+                OSR_GDV( papszNV, "alpha", 0.0 ),
                 0.0, /* ??? */
-                OSR_GDV( papszNV, "k", 1.0 ), 
-                OSR_GDV( papszNV, "x_0", 0.0 ), 
+                OSR_GDV( papszNV, "k", 1.0 ),
+                OSR_GDV( papszNV, "x_0", 0.0 ),
                 OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value,"somerc") )
     {
-        SetHOM( OSR_GDV( papszNV, "lat_0", 0.0 ), 
-                OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                90.0,  90.0, 
-                OSR_GDV( papszNV, "k", 1.0 ), 
-                OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetHOM( OSR_GDV( papszNV, "lat_0", 0.0 ),
+                OSR_GDV( papszNV, "lon_0", 0.0 ),
+                90.0,  90.0,
+                OSR_GDV( papszNV, "k", 1.0 ),
+                OSR_GDV( papszNV, "x_0", 0.0 ),
                 OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value,"krovak") )
     {
-        SetKrovak( OSR_GDV( papszNV, "lat_0", 0.0 ), 
-                   OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                   OSR_GDV( papszNV, "alpha", 0.0 ), 
+        SetKrovak( OSR_GDV( papszNV, "lat_0", 0.0 ),
+                   OSR_GDV( papszNV, "lon_0", 0.0 ),
+                   OSR_GDV( papszNV, "alpha", 0.0 ),
                    0.0, /* pseudo_standard_parallel_1 */
-                   OSR_GDV( papszNV, "k", 1.0 ), 
-                   OSR_GDV( papszNV, "x_0", 0.0 ), 
+                   OSR_GDV( papszNV, "k", 1.0 ),
+                   OSR_GDV( papszNV, "x_0", 0.0 ),
                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value, "iwm_p") )
     {
-        SetIWMPolyconic( OSR_GDV( papszNV, "lat_1", 0.0 ), 
+        SetIWMPolyconic( OSR_GDV( papszNV, "lat_1", 0.0 ),
                          OSR_GDV( papszNV, "lat_2", 0.0 ),
-                         OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                         OSR_GDV( papszNV, "x_0", 0.0 ), 
+                         OSR_GDV( papszNV, "lon_0", 0.0 ),
+                         OSR_GDV( papszNV, "x_0", 0.0 ),
                          OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value, "wag1") )
     {
         SetWagner( 1, 0.0,
-                   OSR_GDV( papszNV, "x_0", 0.0 ), 
+                   OSR_GDV( papszNV, "x_0", 0.0 ),
                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value, "wag2") )
     {
         SetWagner( 2, 0.0,
-                   OSR_GDV( papszNV, "x_0", 0.0 ), 
+                   OSR_GDV( papszNV, "x_0", 0.0 ),
                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
@@ -709,45 +710,45 @@ int GTIFSetFromProj4( GTIF *gtif, const char *proj4 )
     {
         SetWagner( 3,
                    OSR_GDV( papszNV, "lat_ts", 0.0 ),
-                   OSR_GDV( papszNV, "x_0", 0.0 ), 
+                   OSR_GDV( papszNV, "x_0", 0.0 ),
                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value, "wag1") )
     {
         SetWagner( 4, 0.0,
-                   OSR_GDV( papszNV, "x_0", 0.0 ), 
+                   OSR_GDV( papszNV, "x_0", 0.0 ),
                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value, "wag1") )
     {
         SetWagner( 5, 0.0,
-                   OSR_GDV( papszNV, "x_0", 0.0 ), 
+                   OSR_GDV( papszNV, "x_0", 0.0 ),
                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value, "wag1") )
     {
         SetWagner( 6, 0.0,
-                   OSR_GDV( papszNV, "x_0", 0.0 ), 
+                   OSR_GDV( papszNV, "x_0", 0.0 ),
                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value, "wag1") )
     {
         SetWagner( 7, 0.0,
-                   OSR_GDV( papszNV, "x_0", 0.0 ), 
+                   OSR_GDV( papszNV, "x_0", 0.0 ),
                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(value,"tpeqd") )
     {
-        SetTPED( OSR_GDV( papszNV, "lat_1", 0.0 ), 
-                 OSR_GDV( papszNV, "lon_1", 0.0 ), 
-                 OSR_GDV( papszNV, "lat_2", 0.0 ), 
-                 OSR_GDV( papszNV, "lon_2", 0.0 ), 
-                 OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetTPED( OSR_GDV( papszNV, "lat_1", 0.0 ),
+                 OSR_GDV( papszNV, "lon_1", 0.0 ),
+                 OSR_GDV( papszNV, "lat_2", 0.0 ),
+                 OSR_GDV( papszNV, "lon_2", 0.0 ),
+                 OSR_GDV( papszNV, "x_0", 0.0 ),
                  OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 #endif
@@ -768,7 +769,7 @@ int GTIFSetFromProj4( GTIF *gtif, const char *proj4 )
     }
     else
     {
-        GTIFKeySet( gtif, GeographicTypeGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet( gtif, GeographicTypeGeoKey, TYPE_SHORT, 1,
                     KvUserDefined );
         GTIFKeySet( gtif, GeogGeodeticDatumGeoKey, TYPE_SHORT,
                     1, nDatum );
@@ -780,11 +781,11 @@ int GTIFSetFromProj4( GTIF *gtif, const char *proj4 )
     if( nGCS == KvUserDefined )
     {
         if( nSpheroid != KvUserDefined )
-            GTIFKeySet( gtif, GeogEllipsoidGeoKey, TYPE_SHORT, 1, 
+            GTIFKeySet( gtif, GeogEllipsoidGeoKey, TYPE_SHORT, 1,
                         nSpheroid );
         else
         {
-            GTIFKeySet( gtif, GeogEllipsoidGeoKey, TYPE_SHORT, 1, 
+            GTIFKeySet( gtif, GeogEllipsoidGeoKey, TYPE_SHORT, 1,
                         KvUserDefined );
             GTIFKeySet( gtif, GeogSemiMajorAxisGeoKey, TYPE_DOUBLE, 1,
                         dfSemiMajor );
@@ -795,7 +796,6 @@ int GTIFSetFromProj4( GTIF *gtif, const char *proj4 )
                 GTIFKeySet( gtif, GeogInvFlatteningGeoKey, TYPE_DOUBLE, 1,
                             dfInvFlattening );
         }
-        
     }
 
 /* -------------------------------------------------------------------- */
@@ -808,31 +808,31 @@ int GTIFSetFromProj4( GTIF *gtif, const char *proj4 )
         value = OSR_GSV( papszNV, "to_meter" );
         if( value )
         {
-            GTIFKeySet( gtif, ProjLinearUnitsGeoKey, TYPE_SHORT, 1, 
+            GTIFKeySet( gtif, ProjLinearUnitsGeoKey, TYPE_SHORT, 1,
                         KvUserDefined );
-            GTIFKeySet( gtif, ProjLinearUnitSizeGeoKey, TYPE_DOUBLE, 1, 
+            GTIFKeySet( gtif, ProjLinearUnitSizeGeoKey, TYPE_DOUBLE, 1,
                         GTIFAtof(value) );
         }
     }
     else if( EQUAL(value,"meter") || EQUAL(value,"m") )
     {
-        GTIFKeySet( gtif, ProjLinearUnitsGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet( gtif, ProjLinearUnitsGeoKey, TYPE_SHORT, 1,
                     Linear_Meter );
-    } 
+    }
     else if( EQUAL(value,"us-ft") )
     {
-        GTIFKeySet( gtif, ProjLinearUnitsGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet( gtif, ProjLinearUnitsGeoKey, TYPE_SHORT, 1,
                     Linear_Foot_US_Survey );
-    } 
+    }
     else if( EQUAL(value,"ft") )
     {
-        GTIFKeySet( gtif, ProjLinearUnitsGeoKey, TYPE_SHORT, 1, 
+        GTIFKeySet( gtif, ProjLinearUnitsGeoKey, TYPE_SHORT, 1,
                     Linear_Foot );
-    } 
+    }
 
 
     OSRFreeStringList( papszNV );
-    
+
     return TRUE;
 }
 
@@ -851,7 +851,7 @@ char * GTIFGetProj4Defn( GTIFDefn * psDefn )
         return CPLStrdup("");
 
     szProjection[0] = '\0';
-    
+
 /* ==================================================================== */
 /*      Translate the units of measure.                                 */
 /*                                                                      */
@@ -861,7 +861,7 @@ char * GTIFGetProj4Defn( GTIFDefn * psDefn )
 /* ==================================================================== */
     if( psDefn->UOMLength == Linear_Meter )
     {
-        strcpy( szUnits, "+units=m " ); 
+        strcpy( szUnits, "+units=m " );
     }
     else if( psDefn->UOMLength == Linear_Foot )
     {
@@ -902,20 +902,19 @@ char * GTIFGetProj4Defn( GTIFDefn * psDefn )
 /* -------------------------------------------------------------------- */
     dfFalseEasting = psDefn->ProjParm[5];
     dfFalseNorthing = psDefn->ProjParm[6];
-    
+
 /* ==================================================================== */
 /*      Handle general projection methods.                              */
 /* ==================================================================== */
- 
+
 /* -------------------------------------------------------------------- */
 /*      Geographic.                                                     */
 /* -------------------------------------------------------------------- */
     if(psDefn->Model==ModelTypeGeographic)
     {
         sprintf(szProjection+strlen(szProjection),"+proj=latlong ");
-        
     }
- 
+
 /* -------------------------------------------------------------------- */
 /*      UTM - special case override on transverse mercator so things    */
 /*      will be more meaningful to the user.                            */
@@ -926,7 +925,7 @@ char * GTIFGetProj4Defn( GTIFDefn * psDefn )
                  "+proj=utm +zone=%d ",
                  psDefn->Zone );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Transverse Mercator                                             */
 /* -------------------------------------------------------------------- */
@@ -1136,7 +1135,7 @@ char * GTIFGetProj4Defn( GTIFDefn * psDefn )
                  dfFalseEasting,
                  dfFalseNorthing );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      EquidistantConic                                                */
 /* -------------------------------------------------------------------- */
@@ -1152,7 +1151,7 @@ char * GTIFGetProj4Defn( GTIFDefn * psDefn )
                  dfFalseEasting,
                  dfFalseNorthing );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Robinson                                                        */
 /* -------------------------------------------------------------------- */
@@ -1164,7 +1163,7 @@ char * GTIFGetProj4Defn( GTIFDefn * psDefn )
                  dfFalseEasting,
                  dfFalseNorthing );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      VanDerGrinten                                                   */
 /* -------------------------------------------------------------------- */
@@ -1176,7 +1175,7 @@ char * GTIFGetProj4Defn( GTIFDefn * psDefn )
                  dfFalseEasting,
                  dfFalseNorthing );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Sinusoidal                                                      */
 /* -------------------------------------------------------------------- */
@@ -1188,7 +1187,7 @@ char * GTIFGetProj4Defn( GTIFDefn * psDefn )
                  dfFalseEasting,
                  dfFalseNorthing );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      LambertConfConic_2SP                                            */
 /* -------------------------------------------------------------------- */
@@ -1204,7 +1203,7 @@ char * GTIFGetProj4Defn( GTIFDefn * psDefn )
                  dfFalseEasting,
                  dfFalseNorthing );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      LambertConfConic_1SP                                            */
 /* -------------------------------------------------------------------- */
@@ -1220,7 +1219,7 @@ char * GTIFGetProj4Defn( GTIFDefn * psDefn )
                  psDefn->ProjParm[5],
                  psDefn->ProjParm[6] );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      CT_CylindricalEqualArea                                         */
 /* -------------------------------------------------------------------- */
@@ -1234,7 +1233,7 @@ char * GTIFGetProj4Defn( GTIFDefn * psDefn )
                  psDefn->ProjParm[5],
                  psDefn->ProjParm[6] );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      NewZealandMapGrid                                               */
 /* -------------------------------------------------------------------- */
@@ -1248,7 +1247,7 @@ char * GTIFGetProj4Defn( GTIFDefn * psDefn )
                  psDefn->ProjParm[5],
                  psDefn->ProjParm[6] );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Transverse Mercator - south oriented.                           */
 /* -------------------------------------------------------------------- */
@@ -1256,7 +1255,7 @@ char * GTIFGetProj4Defn( GTIFDefn * psDefn )
     {
         /* this appears to be an unsupported formulation with PROJ.4 */
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      ObliqueMercator (Hotine)                                        */
 /* -------------------------------------------------------------------- */
@@ -1277,6 +1276,43 @@ char * GTIFGetProj4Defn( GTIFDefn * psDefn )
                  psDefn->ProjParm[6] );
     }
 
+    else if( psDefn->CTProjection == CT_HotineObliqueMercatorAzimuthCenter )
+    {
+        /* special case for swiss oblique mercator : see GDAL bug 423 */
+        if( fabs(psDefn->ProjParm[2] - 90.0) < 0.0001
+            && fabs(psDefn->ProjParm[3]-90.0) < 0.0001 )
+        {
+            sprintf( szProjection+strlen(szProjection),
+                     "+proj=somerc +lat_0=%.16g +lon_0=%.16g"
+                     " +k_0=%.16g +x_0=%.16g +y_0=%.16g ",
+                     psDefn->ProjParm[0],
+                     psDefn->ProjParm[1],
+                     psDefn->ProjParm[4],
+                     psDefn->ProjParm[5],
+                     psDefn->ProjParm[6] );
+        }
+        else
+        {
+            sprintf( szProjection+strlen(szProjection),
+                     "+proj=omerc +lat_0=%.16g +lonc=%.16g +alpha=%.16g"
+                     " +k=%.16g +x_0=%.16g +y_0=%.16g ",
+                     psDefn->ProjParm[0],
+                     psDefn->ProjParm[1],
+                     psDefn->ProjParm[2],
+                     psDefn->ProjParm[4],
+                     psDefn->ProjParm[5],
+                     psDefn->ProjParm[6] );
+
+            /* RSO variant - http://trac.osgeo.org/proj/ticket/62 */
+            /* Note that gamma is only supported by PROJ 4.8.0 and later. */
+            /* FIXME: how to detect that gamma isn't set to default value */
+            /*if( psDefn->ProjParm[3] != 0.0 )
+            {
+                sprintf( szProjection+strlen(szProjection), "+gamma=%.16g ",
+                         psDefn->ProjParm[3] );
+            }*/
+        }
+    }
 /* ==================================================================== */
 /*      Handle ellipsoid information.                                   */
 /* ==================================================================== */
@@ -1300,11 +1336,11 @@ char * GTIFGetProj4Defn( GTIFDefn * psDefn )
     }
 
     strcat( szProjection, szUnits );
-    
+
     /* If we don't have anything, reset */
     if (strstr(szProjection, "+proj=") == NULL) { return CPLStrdup(""); }
 
-    return( CPLStrdup( szProjection ) );
+    return CPLStrdup( szProjection );
 }
 
 #if !defined(HAVE_LIBPROJ)
@@ -1316,10 +1352,10 @@ int GTIFProj4ToLatLong( GTIFDefn * psDefn, int nPoints,
     (void) nPoints;
     (void) padfX;
     (void) padfY;
-#ifdef DEBUG    
+#ifdef DEBUG
     fprintf( stderr,
              "GTIFProj4ToLatLong() - PROJ.4 support not compiled in.\n" );
-#endif    
+#endif
     return FALSE;
 }
 
@@ -1330,10 +1366,10 @@ int GTIFProj4FromLatLong( GTIFDefn * psDefn, int nPoints,
     (void) nPoints;
     (void) padfX;
     (void) padfY;
-#ifdef DEBUG    
+#ifdef DEBUG
     fprintf( stderr,
              "GTIFProj4FromLatLong() - PROJ.4 support not compiled in.\n" );
-#endif    
+#endif
     return FALSE;
 }
 #else
@@ -1354,7 +1390,7 @@ int GTIFProj4FromLatLong( GTIFDefn * psDefn, int nPoints,
     char	*pszProjection, **papszArgs;
     projPJ	*psPJ;
     int		i;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Get a projection definition.                                    */
 /* -------------------------------------------------------------------- */
@@ -1366,7 +1402,7 @@ int GTIFProj4FromLatLong( GTIFDefn * psDefn, int nPoints,
 /* -------------------------------------------------------------------- */
 /*      Parse into tokens for pj_init(), and initialize the projection. */
 /* -------------------------------------------------------------------- */
-    
+
     papszArgs = CSLTokenizeStringComplex( pszProjection, " +", TRUE, FALSE );
     free( pszProjection );
 
@@ -1414,7 +1450,7 @@ int GTIFProj4ToLatLong( GTIFDefn * psDefn, int nPoints,
     char	*pszProjection, **papszArgs;
     projPJ	*psPJ;
     int		i;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Get a projection definition.                                    */
 /* -------------------------------------------------------------------- */
@@ -1426,7 +1462,7 @@ int GTIFProj4ToLatLong( GTIFDefn * psDefn, int nPoints,
 /* -------------------------------------------------------------------- */
 /*      Parse into tokens for pj_init(), and initialize the projection. */
 /* -------------------------------------------------------------------- */
-    
+
     papszArgs = CSLTokenizeStringComplex( pszProjection, " +", TRUE, FALSE );
     free( pszProjection );
 
@@ -1461,4 +1497,3 @@ int GTIFProj4ToLatLong( GTIFDefn * psDefn, int nPoints,
 }
 
 #endif /* has proj_api.h and -lproj */
-
diff --git a/frmts/gtiff/libgeotiff/geotiffio.h b/frmts/gtiff/libgeotiff/geotiffio.h
index 32ec19e..b9da19b 100644
--- a/frmts/gtiff/libgeotiff/geotiffio.h
+++ b/frmts/gtiff/libgeotiff/geotiffio.h
@@ -1,6 +1,6 @@
-/* 
+/*
  * geotiffio.h
- * 
+ *
  * Standard include file for geotiff, including all
  * key and code definitions.
  *
@@ -11,11 +11,10 @@
  */
 
 
-#ifndef __geotiffio_h
-#define __geotiffio_h
+#ifndef LIBGEOTIFF_GEOTIFFIO_H_
+#define LIBGEOTIFF_GEOTIFFIO_H_
 
 #include "geotiff.h"  /* public key interface */
 #include "geovalues.h" /* key code definitions */
 
-#endif /* __geotiffio_h */
-
+#endif /* LIBGEOTIFF_GEOTIFFIO_H_ */
diff --git a/frmts/gtiff/libgeotiff/geovalues.h b/frmts/gtiff/libgeotiff/geovalues.h
index 1cd8444..f4224e2 100644
--- a/frmts/gtiff/libgeotiff/geovalues.h
+++ b/frmts/gtiff/libgeotiff/geovalues.h
@@ -11,10 +11,10 @@
  *
  **********************************************************************/
 
-#ifndef __geovalues_h_
-#define __geovalues_h_
+#ifndef LIBGEOTIFF_GEOVALUES_H_
+#define LIBGEOTIFF_GEOVALUES_H_
 
-/* If code values are added or modified, the "GvCurrentMinorRev" 
+/* If code values are added or modified, the "GvCurrentMinorRev"
  * number should be incremented here. If new Keys are added, then the
  * GvCurrentRevision number should be incremented instead, and the
  * GvCurrentMinorRev should be reset to zero (see "geokeys.h").
@@ -22,7 +22,7 @@
  * In addition, any changes here should be reflected in "geo_names.c"
  *
  */
- 
+
 #define GvCurrentMinorRev  0  /* First Major Rev EPSG Code Release  */
 
 
@@ -41,7 +41,7 @@
  * The section numbers refer to the GeoTIFF Specification section
  * in which the code values are documented.
  */
- 
+
 /************************************************************
  *         6.3.1 GeoTIFF General Codes
  ************************************************************/
@@ -112,5 +112,4 @@ typedef enum {
 	VDatumBase = 1
 } vdatum_t;
 
-#endif /* __geovalues_h_ */
-
+#endif /* LIBGEOTIFF_GEOVALUES_H_ */
diff --git a/frmts/gtiff/libgeotiff/xtiff.c b/frmts/gtiff/libgeotiff/xtiff.c
index 5e679dc..2b48516 100644
--- a/frmts/gtiff/libgeotiff/xtiff.c
+++ b/frmts/gtiff/libgeotiff/xtiff.c
@@ -13,7 +13,7 @@
  *    18 Sep 1995   -- Deprecated Integraph Matrix tag with new one.
  *                     Backward compatible support provided.  --NDR.
  */
- 
+
 #include "xtiffio.h"
 #include <stdio.h>
 #include "cpl_serv.h"
@@ -21,14 +21,14 @@
 /*  Tiff info structure.
  *
  *     Entry format:
- *        { TAGNUMBER, ReadCount, WriteCount, DataType, FIELDNUM, 
+ *        { TAGNUMBER, ReadCount, WriteCount, DataType, FIELDNUM,
  *          OkToChange, PassDirCountOnSet, AsciiName }
  *
  *     For ReadCount, WriteCount, -1 = unknown.
  */
 
 static const TIFFFieldInfo xtiffFieldInfo[] = {
-  
+
   /* XXX Insert Your tags here */
     { TIFFTAG_GEOPIXELSCALE,	-1,-1, TIFF_DOUBLE,	FIELD_CUSTOM,
       TRUE,	TRUE,	"GeoPixelScale" },
@@ -81,14 +81,14 @@ _XTIFFDefaultDirectory(TIFF *tif)
      * allow it to set up the rest of its own methods.
      */
 
-    if (_ParentExtender) 
+    if (_ParentExtender)
         (*_ParentExtender)(tif);
 }
 
 
 /**
 Registers an extension with libtiff for adding GeoTIFF tags.
-After this one-time intialization, any TIFF open function may be called in
+After this one-time initialization, any TIFF open function may be called in
 the usual manner to create a TIFF file that compatible with libgeotiff.
 The XTIFF open functions are simply for convenience: they call this
 and then pass their parameters on to the appropriate TIFF open function.
@@ -100,10 +100,10 @@ only register the extension the first time it is called.
 void XTIFFInitialize(void)
 {
     static int first_time=1;
-	
+
     if (! first_time) return; /* Been there. Done that. */
     first_time = 0;
-	
+
     /* Grab the inherited method and install */
     _ParentExtender = TIFFSetTagExtender(_XTIFFDefaultDirectory);
 }
@@ -137,13 +137,13 @@ XTIFFOpen(const char* name, const char* mode)
     TIFF *tif;
 
     /* Set up the callback */
-    XTIFFInitialize();	
-	
+    XTIFFInitialize();
+
     /* Open the file; the callback will set everything up
      */
     tif = TIFFOpen(name, mode);
     if (!tif) return tif;
-	
+
     return tif;
 }
 
@@ -153,13 +153,13 @@ XTIFFFdOpen(int fd, const char* name, const char* mode)
     TIFF *tif;
 
     /* Set up the callback */
-    XTIFFInitialize();	
+    XTIFFInitialize();
 
     /* Open the file; the callback will set everything up
      */
     tif = TIFFFdOpen(fd, name, mode);
     if (!tif) return tif;
-	
+
     return tif;
 }
 
@@ -171,10 +171,10 @@ XTIFFClientOpen(const char* name, const char* mode, thandle_t thehandle,
 	    TIFFMapFileProc MFProvc, TIFFUnmapFileProc UMFProc )
 {
     TIFF *tif;
-    
+
     /* Set up the callback */
-    XTIFFInitialize();	
-    
+    XTIFFInitialize();
+
     /* Open the file; the callback will set everything up
      */
     tif = TIFFClientOpen(name, mode, thehandle,
@@ -182,9 +182,9 @@ XTIFFClientOpen(const char* name, const char* mode, thandle_t thehandle,
                          SProc, CProc,
                          SzProc,
                          MFProvc, UMFProc);
-    
+
     if (!tif) return tif;
-    
+
     return tif;
 }
 
@@ -192,7 +192,7 @@ XTIFFClientOpen(const char* name, const char* mode, thandle_t thehandle,
  * Close a file opened with XTIFFOpen().
  *
  * @param tif The file handle returned by XTIFFOpen().
- * 
+ *
  * If a GTIF structure was created with GTIFNew()
  * for this file, it should be freed with GTIFFree()
  * <i>before</i> calling XTIFFClose().
diff --git a/frmts/gtiff/libgeotiff/xtiffio.h b/frmts/gtiff/libgeotiff/xtiffio.h
index a267087..c551cf9 100644
--- a/frmts/gtiff/libgeotiff/xtiffio.h
+++ b/frmts/gtiff/libgeotiff/xtiffio.h
@@ -4,8 +4,8 @@
  *    written by: Niles D. Ritter
  */
 
-#ifndef __xtiffio_h
-#define __xtiffio_h
+#ifndef LIBGEOTIFF_XTIFFIO_H_
+#define LIBGEOTIFF_XTIFFIO_H_
 
 #include "tiffio.h"
 #include "geo_config.h"
@@ -17,8 +17,8 @@
  * library (usually libtiff).
  */
 
-/* 
- *  Define public Tag names and values here 
+/*
+ *  Define public Tag names and values here
  */
 
 /* tags 33550 is a private tag registered to SoftDesk, Inc */
@@ -28,15 +28,15 @@
 #define TIFFTAG_GEOTIEPOINTS         33922
 /* tags 34263-34264 are private tags registered to NASA-JPL Carto Group */
 #ifdef JPL_TAG_SUPPORT
-#define TIFFTAG_JPL_CARTO_IFD        34263    /* $use GeoProjectionInfo ! */
+#define TIFFTAG_JPL_CARTO_IFD        34263   /* $use GeoProjectionInfo ! */
 #endif
-#define TIFFTAG_GEOTRANSMATRIX       34264    /* New Matrix Tag replaces 33920 */
+#define TIFFTAG_GEOTRANSMATRIX       34264   /* New Matrix Tag replaces 33920 */
 /* tags 34735-3438 are private tags registered to SPOT Image, Inc */
 #define TIFFTAG_GEOKEYDIRECTORY      34735
 #define TIFFTAG_GEODOUBLEPARAMS      34736
 #define TIFFTAG_GEOASCIIPARAMS       34737
 
-/* 
+/*
  *  Define Printing method flags. These
  *  flags may be passed in to TIFFPrintDirectory() to
  *  indicate that those particular field values should
@@ -65,12 +65,12 @@ extern "C" {
 #  endif
 #endif
 
-extern void CPL_DLL XTIFFInitialize();
+extern void CPL_DLL XTIFFInitialize(void);
 extern TIFF CPL_DLL * XTIFFOpen(const char* name, const char* mode);
 extern TIFF CPL_DLL * XTIFFFdOpen(int fd, const char* name, const char* mode);
 extern void CPL_DLL XTIFFClose(TIFF *tif);
 
-extern TIFF CPL_DLL * XTIFFClientOpen(const char* name, const char* mode, 
+extern TIFF CPL_DLL * XTIFFClientOpen(const char* name, const char* mode,
                                       thandle_t thehandle,
                                       TIFFReadWriteProc, TIFFReadWriteProc,
                                       TIFFSeekProc, TIFFCloseProc,
@@ -80,5 +80,4 @@ extern TIFF CPL_DLL * XTIFFClientOpen(const char* name, const char* mode,
 }
 #endif
 
-#endif /* __xtiffio_h */
-
+#endif /* LIBGEOTIFF_XTIFFIO_H_ */
diff --git a/frmts/gtiff/libtiff/GNUmakefile b/frmts/gtiff/libtiff/GNUmakefile
index db77c07..57e86dd 100644
--- a/frmts/gtiff/libtiff/GNUmakefile
+++ b/frmts/gtiff/libtiff/GNUmakefile
@@ -43,7 +43,7 @@ OBJ	= \
 
 O_OBJ	=	$(foreach file,$(OBJ),../../o/$(file))
 
-ALL_C_FLAGS =	$(CFLAGS) $(CPPFLAGS)
+ALL_C_FLAGS =	$(CFLAGS_NOFTRAPV) $(CPPFLAGS) -DDONT_DEPRECATE_SPRINTF
 
 ifeq ($(LIBZ_SETTING),internal) 
 XTRA_OPT =      -I../../zlib 
diff --git a/frmts/gtiff/libtiff/gdal_libtiff_symbol_rename.h b/frmts/gtiff/libtiff/gdal_libtiff_symbol_rename.h
index 9f030dd..88ffdd3 100644
--- a/frmts/gtiff/libtiff/gdal_libtiff_symbol_rename.h
+++ b/frmts/gtiff/libtiff/gdal_libtiff_symbol_rename.h
@@ -279,6 +279,8 @@
 #define setupMap gdal_setupMap
 #define swabHorAcc16 gdal_swabHorAcc16
 #define swabHorAcc32 gdal_swabHorAcc32
+#define swabHorDiff16 gdal_swabHorDiff16
+#define swabHorDiff32 gdal_swabHorDiff32
 #define tagCompare gdal_tagCompare
 #define tagNameCompare gdal_tagNameCompare
 #define td_lfind gdal_td_lfind
diff --git a/frmts/gtiff/libtiff/makefile.vc b/frmts/gtiff/libtiff/makefile.vc
index 2337536..d802a42 100644
--- a/frmts/gtiff/libtiff/makefile.vc
+++ b/frmts/gtiff/libtiff/makefile.vc
@@ -41,9 +41,11 @@ OBJ	= \
 
 GDAL_ROOT	=	..\..\..
 
+# /wd4324 silents warning C4324: '<unnamed-tag>' : structure was padded due to __declspec(align())
+# in tif_jpeg.c:147 and tif_ojpeg.c:248
+
 EXTRAFLAGS = 	-I..\..\zlib -DZIP_SUPPORT -DPIXARLOG_SUPPORT \
-		$(JPEG_FLAGS) $(JPEG12_FLAGS) $(LZMA_FLAGS) \
-		$(SOFTWARNFLAGS)
+		$(JPEG_FLAGS) $(JPEG12_FLAGS) $(LZMA_FLAGS) /wd4324
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
diff --git a/frmts/gtiff/libtiff/tif_aux.c b/frmts/gtiff/libtiff/tif_aux.c
index 927150a..fb6ece1 100644
--- a/frmts/gtiff/libtiff/tif_aux.c
+++ b/frmts/gtiff/libtiff/tif_aux.c
@@ -1,4 +1,4 @@
-/* $Id: tif_aux.c,v 1.26 2010-07-01 15:33:28 dron Exp $ */
+/* $Id: tif_aux.c,v 1.28 2016-01-23 21:20:34 erouault Exp $ */
 
 /*
  * Copyright (c) 1991-1997 Sam Leffler
@@ -100,7 +100,8 @@ TIFFDefaultTransferFunction(TIFFDirectory* td)
 
 	n = ((tmsize_t)1)<<td->td_bitspersample;
 	nbytes = n * sizeof (uint16);
-	if (!(tf[0] = (uint16 *)_TIFFmalloc(nbytes)))
+        tf[0] = (uint16 *)_TIFFmalloc(nbytes);
+	if (tf[0] == NULL)
 		return 0;
 	tf[0][0] = 0;
 	for (i = 1; i < n; i++) {
@@ -109,10 +110,12 @@ TIFFDefaultTransferFunction(TIFFDirectory* td)
 	}
 
 	if (td->td_samplesperpixel - td->td_extrasamples > 1) {
-		if (!(tf[1] = (uint16 *)_TIFFmalloc(nbytes)))
+                tf[1] = (uint16 *)_TIFFmalloc(nbytes);
+		if(tf[1] == NULL)
 			goto bad;
 		_TIFFmemcpy(tf[1], tf[0], nbytes);
-		if (!(tf[2] = (uint16 *)_TIFFmalloc(nbytes)))
+                tf[2] = (uint16 *)_TIFFmalloc(nbytes);
+		if (tf[2] == NULL)
 			goto bad;
 		_TIFFmemcpy(tf[2], tf[0], nbytes);
 	}
@@ -134,7 +137,8 @@ TIFFDefaultRefBlackWhite(TIFFDirectory* td)
 {
 	int i;
 
-	if (!(td->td_refblackwhite = (float *)_TIFFmalloc(6*sizeof (float))))
+        td->td_refblackwhite = (float *)_TIFFmalloc(6*sizeof (float));
+	if (td->td_refblackwhite == NULL)
 		return 0;
         if (td->td_photometric == PHOTOMETRIC_YCBCR) {
 		/*
@@ -163,7 +167,7 @@ TIFFDefaultRefBlackWhite(TIFFDirectory* td)
  * value if the tag is not present in the directory.
  *
  * NB:	We use the value in the directory, rather than
- *	explcit values so that defaults exist only one
+ *	explicit values so that defaults exist only one
  *	place in the library -- in TIFFDefaultDirectory.
  */
 int
diff --git a/frmts/gtiff/libtiff/tif_close.c b/frmts/gtiff/libtiff/tif_close.c
index 13d2bab..a0cb661 100644
--- a/frmts/gtiff/libtiff/tif_close.c
+++ b/frmts/gtiff/libtiff/tif_close.c
@@ -1,4 +1,4 @@
-/* $Id: tif_close.c,v 1.19 2010-03-10 18:56:48 bfriesen Exp $ */
+/* $Id: tif_close.c,v 1.21 2016-01-23 21:20:34 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -36,7 +36,7 @@
 
 /**
  * Auxiliary function to free the TIFF structure. Given structure will be
- * completetly freed, so you should save opened file handle and pointer
+ * completely freed, so you should save opened file handle and pointer
  * to the close procedure in external variables before calling
  * _TIFFCleanup(), if you will need these ones to close the file.
  * 
@@ -62,11 +62,11 @@ TIFFCleanup(TIFF* tif)
          */
 	while( tif->tif_clientinfo )
 	{
-		TIFFClientInfoLink *link = tif->tif_clientinfo;
+		TIFFClientInfoLink *psLink = tif->tif_clientinfo;
 
-		tif->tif_clientinfo = link->next;
-		_TIFFfree( link->name );
-		_TIFFfree( link );
+		tif->tif_clientinfo = psLink->next;
+		_TIFFfree( psLink->name );
+		_TIFFfree( psLink );
 	}
 
 	if (tif->tif_rawdata && (tif->tif_flags&TIFF_MYBUFFER))
diff --git a/frmts/gtiff/libtiff/tif_codec.c b/frmts/gtiff/libtiff/tif_codec.c
index 703e87d..7cb46f6 100644
--- a/frmts/gtiff/libtiff/tif_codec.c
+++ b/frmts/gtiff/libtiff/tif_codec.c
@@ -1,4 +1,4 @@
-/* $Id: tif_codec.c,v 1.16 2013-05-02 14:44:29 tgl Exp $ */
+/* $Id: tif_codec.c,v 1.17 2015-08-19 02:31:04 bfriesen Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -108,8 +108,7 @@ _notConfigured(TIFF* tif)
 	const TIFFCodec* c = TIFFFindCODEC(tif->tif_dir.td_compression);
         char compression_code[20];
         
-        snprintf(compression_code, sizeof(compression_code), "%d",
-		 tif->tif_dir.td_compression );
+        sprintf(compression_code, "%d",tif->tif_dir.td_compression );
 	TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
                      "%s compression support is not configured", 
                      c ? c->name : compression_code );
diff --git a/frmts/gtiff/libtiff/tif_color.c b/frmts/gtiff/libtiff/tif_color.c
index be4850c..d7a1ecd 100644
--- a/frmts/gtiff/libtiff/tif_color.c
+++ b/frmts/gtiff/libtiff/tif_color.c
@@ -1,4 +1,4 @@
-/* $Id: tif_color.c,v 1.19 2010-12-14 02:22:42 faxguy Exp $ */
+/* $Id: tif_color.c,v 1.20 2015-10-17 10:13:14 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -126,37 +126,37 @@ TIFFCIELabToRGBInit(TIFFCIELabToRGB* cielab,
 		    const TIFFDisplay *display, float *refWhite)
 {
 	int i;
-	double gamma;
+	double dfGamma;
 
 	cielab->range = CIELABTORGB_TABLE_RANGE;
 
 	_TIFFmemcpy(&cielab->display, display, sizeof(TIFFDisplay));
 
 	/* Red */
-	gamma = 1.0 / cielab->display.d_gammaR ;
+	dfGamma = 1.0 / cielab->display.d_gammaR ;
 	cielab->rstep =
 		(cielab->display.d_YCR - cielab->display.d_Y0R)	/ cielab->range;
 	for(i = 0; i <= cielab->range; i++) {
 		cielab->Yr2r[i] = cielab->display.d_Vrwr
-		    * ((float)pow((double)i / cielab->range, gamma));
+		    * ((float)pow((double)i / cielab->range, dfGamma));
 	}
 
 	/* Green */
-	gamma = 1.0 / cielab->display.d_gammaG ;
+	dfGamma = 1.0 / cielab->display.d_gammaG ;
 	cielab->gstep =
 	    (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
 	for(i = 0; i <= cielab->range; i++) {
 		cielab->Yg2g[i] = cielab->display.d_Vrwg
-		    * ((float)pow((double)i / cielab->range, gamma));
+		    * ((float)pow((double)i / cielab->range, dfGamma));
 	}
 
 	/* Blue */
-	gamma = 1.0 / cielab->display.d_gammaB ;
+	dfGamma = 1.0 / cielab->display.d_gammaB ;
 	cielab->bstep =
 	    (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
 	for(i = 0; i <= cielab->range; i++) {
 		cielab->Yb2b[i] = cielab->display.d_Vrwb
-		    * ((float)pow((double)i / cielab->range, gamma));
+		    * ((float)pow((double)i / cielab->range, dfGamma));
 	}
 
 	/* Init reference white point */
diff --git a/frmts/gtiff/libtiff/tif_compress.c b/frmts/gtiff/libtiff/tif_compress.c
index 20e72fd..f6b32df 100644
--- a/frmts/gtiff/libtiff/tif_compress.c
+++ b/frmts/gtiff/libtiff/tif_compress.c
@@ -1,4 +1,4 @@
-/* $Id: tif_compress.c,v 1.22 2010-03-10 18:56:48 bfriesen Exp $ */
+/* $Id: tif_compress.c,v 1.24 2015-11-22 15:31:03 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -85,7 +85,7 @@ TIFFNoDecode(TIFF* tif, const char* method)
 	return (-1);
 }
 
-int
+static int
 _TIFFNoFixupTags(TIFF* tif)
 {
 	(void) tif;
@@ -227,7 +227,7 @@ TIFFUnRegisterCODEC(TIFFCodec* c)
 	codec_t* cd;
 	codec_t** pcd;
 
-	for (pcd = ®isteredCODECS; (cd = *pcd); pcd = &cd->next)
+	for (pcd = ®isteredCODECS; (cd = *pcd) != NULL; pcd = &cd->next)
 		if (cd->info == c) {
 			*pcd = cd->next;
 			_TIFFfree(cd);
diff --git a/frmts/gtiff/libtiff/tif_config.h b/frmts/gtiff/libtiff/tif_config.h
index 3947399..05fca03 100644
--- a/frmts/gtiff/libtiff/tif_config.h
+++ b/frmts/gtiff/libtiff/tif_config.h
@@ -31,7 +31,7 @@
 #define DEFAULT_EXTRASAMPLE_AS_ALPHA 1
 
 /* Support strip chopping (whether or not to convert single-strip uncompressed
-   images to mutiple strips of ~8Kb to reduce memory usage) */
+   images to multiple strips of ~8Kb to reduce memory usage) */
 #define STRIPCHOP_DEFAULT TIFF_STRIPCHOP
 
 #define CHUNKY_STRIP_READ_SUPPORT 1
diff --git a/frmts/gtiff/libtiff/tif_config.h.wince b/frmts/gtiff/libtiff/tif_config.h.wince
index baf2298..51c4740 100644
--- a/frmts/gtiff/libtiff/tif_config.h.wince
+++ b/frmts/gtiff/libtiff/tif_config.h.wince
@@ -1,4 +1,4 @@
-/* $Id: tif_config.h.wince 19417 2010-04-15 16:28:40Z mloskot $ */
+/* $Id: tif_config.h.wince 32092 2015-12-08 14:54:56Z goatbar $ */
 
 /*
  * Windows CE platform config.
@@ -12,7 +12,7 @@
 
 /* Compatibility stuff. */
 
-/* Define as 0 or 1 according to the floating point format suported by the
+/* Define as 0 or 1 according to the floating point format supported by the
    machine */
 #define HAVE_IEEEFP 1
 
@@ -53,7 +53,7 @@
 #define DEFAULT_EXTRASAMPLE_AS_ALPHA 1
 
 /* Support strip chopping (whether or not to convert single-strip uncompressed
-   images to mutiple strips of ~8Kb to reduce memory usage) */
+   images to multiple strips of ~8Kb to reduce memory usage) */
 #define STRIPCHOP_DEFAULT TIFF_STRIPCHOP
 
 /* Default size of the strip in bytes (when strip chopping enabled) */
diff --git a/frmts/gtiff/libtiff/tif_dir.c b/frmts/gtiff/libtiff/tif_dir.c
index 17bf878..328b9d6 100644
--- a/frmts/gtiff/libtiff/tif_dir.c
+++ b/frmts/gtiff/libtiff/tif_dir.c
@@ -1,4 +1,4 @@
-/* $Id: tif_dir.c,v 1.119 2014-12-27 15:20:42 erouault Exp $ */
+/* $Id: tif_dir.c,v 1.125 2016-01-23 21:20:34 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -57,13 +57,13 @@ void _TIFFsetByteArray(void** vpp, void* vp, uint32 n)
     { setByteArray(vpp, vp, n, 1); }
 void _TIFFsetString(char** cpp, char* cp)
     { setByteArray((void**) cpp, (void*) cp, strlen(cp)+1, 1); }
-void _TIFFsetNString(char** cpp, char* cp, uint32 n)
+static void _TIFFsetNString(char** cpp, char* cp, uint32 n)
     { setByteArray((void**) cpp, (void*) cp, n, 1); }
 void _TIFFsetShortArray(uint16** wpp, uint16* wp, uint32 n)
     { setByteArray((void**) wpp, (void*) wp, n, sizeof (uint16)); }
 void _TIFFsetLongArray(uint32** lpp, uint32* lp, uint32 n)
     { setByteArray((void**) lpp, (void*) lp, n, sizeof (uint32)); }
-void _TIFFsetLong8Array(uint64** lpp, uint64* lp, uint32 n)
+static void _TIFFsetLong8Array(uint64** lpp, uint64* lp, uint32 n)
     { setByteArray((void**) lpp, (void*) lp, n, sizeof (uint64)); }
 void _TIFFsetFloatArray(float** fpp, float* fp, uint32 n)
     { setByteArray((void**) fpp, (void*) fp, n, sizeof (float)); }
@@ -170,7 +170,7 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
 	 * We want to force the custom code to be used for custom
 	 * fields even if the tag happens to match a well known 
 	 * one - important for reinterpreted handling of standard
-	 * tag values in custom directories (ie. EXIF) 
+	 * tag values in custom directories (i.e. EXIF) 
 	 */
 	if (fip->field_bit == FIELD_CUSTOM) {
 		standard_tag = 0;
@@ -402,7 +402,7 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
 		if ((tif->tif_flags & TIFF_INSUBIFD) == 0) {
 			td->td_nsubifd = (uint16) va_arg(ap, uint16_vap);
 			_TIFFsetLong8Array(&td->td_subifd, (uint64*) va_arg(ap, uint64*),
-			    (long) td->td_nsubifd);
+			    (uint32) td->td_nsubifd);
 		} else {
 			TIFFErrorExt(tif->tif_clientdata, module,
 				     "%s: Sorry, cannot nest SubIFDs",
@@ -421,7 +421,7 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
 		v = (td->td_samplesperpixel - td->td_extrasamples) > 1 ? 3 : 1;
 		for (i = 0; i < v; i++)
 			_TIFFsetShortArray(&td->td_transferfunction[i],
-			    va_arg(ap, uint16*), 1L<<td->td_bitspersample);
+			    va_arg(ap, uint16*), 1U<<td->td_bitspersample);
 		break;
 	case TIFFTAG_REFERENCEBLACKWHITE:
 		/* XXX should check for null range */
@@ -579,10 +579,10 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
 				   handled this way ... likely best if we move it into
 				   the directory structure with an explicit field in 
 				   libtiff 4.1 and assign it a FIELD_ value */
-				uint16 v[2];
-				v[0] = (uint16)va_arg(ap, int);
-				v[1] = (uint16)va_arg(ap, int);
-				_TIFFmemcpy(tv->value, &v, 4);
+				uint16 v2[2];
+				v2[0] = (uint16)va_arg(ap, int);
+				v2[1] = (uint16)va_arg(ap, int);
+				_TIFFmemcpy(tv->value, &v2, 4);
 			}
 
 			else if (fip->field_passcount
@@ -600,66 +600,66 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
 				case TIFF_BYTE:
 				case TIFF_UNDEFINED:
 					{
-						uint8 v = (uint8)va_arg(ap, int);
-						_TIFFmemcpy(val, &v, tv_size);
+						uint8 v2 = (uint8)va_arg(ap, int);
+						_TIFFmemcpy(val, &v2, tv_size);
 					}
 					break;
 				case TIFF_SBYTE:
 					{
-						int8 v = (int8)va_arg(ap, int);
-						_TIFFmemcpy(val, &v, tv_size);
+						int8 v2 = (int8)va_arg(ap, int);
+						_TIFFmemcpy(val, &v2, tv_size);
 					}
 					break;
 				case TIFF_SHORT:
 					{
-						uint16 v = (uint16)va_arg(ap, int);
-						_TIFFmemcpy(val, &v, tv_size);
+						uint16 v2 = (uint16)va_arg(ap, int);
+						_TIFFmemcpy(val, &v2, tv_size);
 					}
 					break;
 				case TIFF_SSHORT:
 					{
-						int16 v = (int16)va_arg(ap, int);
-						_TIFFmemcpy(val, &v, tv_size);
+						int16 v2 = (int16)va_arg(ap, int);
+						_TIFFmemcpy(val, &v2, tv_size);
 					}
 					break;
 				case TIFF_LONG:
 				case TIFF_IFD:
 					{
-						uint32 v = va_arg(ap, uint32);
-						_TIFFmemcpy(val, &v, tv_size);
+						uint32 v2 = va_arg(ap, uint32);
+						_TIFFmemcpy(val, &v2, tv_size);
 					}
 					break;
 				case TIFF_SLONG:
 					{
-						int32 v = va_arg(ap, int32);
-						_TIFFmemcpy(val, &v, tv_size);
+						int32 v2 = va_arg(ap, int32);
+						_TIFFmemcpy(val, &v2, tv_size);
 					}
 					break;
 				case TIFF_LONG8:
 				case TIFF_IFD8:
 					{
-						uint64 v = va_arg(ap, uint64);
-						_TIFFmemcpy(val, &v, tv_size);
+						uint64 v2 = va_arg(ap, uint64);
+						_TIFFmemcpy(val, &v2, tv_size);
 					}
 					break;
 				case TIFF_SLONG8:
 					{
-						int64 v = va_arg(ap, int64);
-						_TIFFmemcpy(val, &v, tv_size);
+						int64 v2 = va_arg(ap, int64);
+						_TIFFmemcpy(val, &v2, tv_size);
 					}
 					break;
 				case TIFF_RATIONAL:
 				case TIFF_SRATIONAL:
 				case TIFF_FLOAT:
 					{
-						float v = (float)va_arg(ap, double);
-						_TIFFmemcpy(val, &v, tv_size);
+						float v2 = (float)va_arg(ap, double);
+						_TIFFmemcpy(val, &v2, tv_size);
 					}
 					break;
 				case TIFF_DOUBLE:
 					{
-						double v = va_arg(ap, double);
-						_TIFFmemcpy(val, &v, tv_size);
+						double v2 = va_arg(ap, double);
+						_TIFFmemcpy(val, &v2, tv_size);
 					}
 					break;
 				default:
@@ -672,9 +672,9 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
 	}
 	}
 	if (status) {
-		const TIFFField* fip=TIFFFieldWithTag(tif,tag);
-		if (fip)                
-			TIFFSetFieldBit(tif, fip->field_bit);
+		const TIFFField* fip2=TIFFFieldWithTag(tif,tag);
+		if (fip2)                
+			TIFFSetFieldBit(tif, fip2->field_bit);
 		tif->tif_flags |= TIFF_DIRTYDIRECT;
 	}
 
@@ -683,31 +683,31 @@ end:
 	return (status);
 badvalue:
         {
-		const TIFFField* fip=TIFFFieldWithTag(tif,tag);
+		const TIFFField* fip2=TIFFFieldWithTag(tif,tag);
 		TIFFErrorExt(tif->tif_clientdata, module,
 		     "%s: Bad value %u for \"%s\" tag",
 		     tif->tif_name, v,
-		     fip ? fip->field_name : "Unknown");
+		     fip2 ? fip2->field_name : "Unknown");
 		va_end(ap);
         }
 	return (0);
 badvalue32:
         {
-		const TIFFField* fip=TIFFFieldWithTag(tif,tag);
+		const TIFFField* fip2=TIFFFieldWithTag(tif,tag);
 		TIFFErrorExt(tif->tif_clientdata, module,
 		     "%s: Bad value %u for \"%s\" tag",
 		     tif->tif_name, v32,
-		     fip ? fip->field_name : "Unknown");
+		     fip2 ? fip2->field_name : "Unknown");
 		va_end(ap);
         }
 	return (0);
 badvaluedouble:
         {
-        const TIFFField* fip=TIFFFieldWithTag(tif,tag);
+        const TIFFField* fip2=TIFFFieldWithTag(tif,tag);
         TIFFErrorExt(tif->tif_clientdata, module,
              "%s: Bad value %f for \"%s\" tag",
              tif->tif_name, dblval,
-             fip ? fip->field_name : "Unknown");
+             fip2 ? fip2->field_name : "Unknown");
         va_end(ap);
         }
     return (0);
@@ -834,7 +834,7 @@ _TIFFVGetField(TIFF* tif, uint32 tag, va_list ap)
 	 * We want to force the custom code to be used for custom
 	 * fields even if the tag happens to match a well known 
 	 * one - important for reinterpreted handling of standard
-	 * tag values in custom directories (ie. EXIF) 
+	 * tag values in custom directories (i.e. EXIF) 
 	 */
 	if (fip->field_bit == FIELD_CUSTOM) {
 		standard_tag = 0;
@@ -885,7 +885,7 @@ _TIFFVGetField(TIFF* tif, uint32 tag, va_list ap)
 				*va_arg(ap, double**) = td->td_sminsamplevalue;
 			else
 			{
-				/* libtiff historially treats this as a single value. */
+				/* libtiff historically treats this as a single value. */
 				uint16 i;
 				double v = td->td_sminsamplevalue[0];
 				for (i=1; i < td->td_samplesperpixel; ++i)
@@ -899,7 +899,7 @@ _TIFFVGetField(TIFF* tif, uint32 tag, va_list ap)
 				*va_arg(ap, double**) = td->td_smaxsamplevalue;
 			else
 			{
-				/* libtiff historially treats this as a single value. */
+				/* libtiff historically treats this as a single value. */
 				uint16 i;
 				double v = td->td_smaxsamplevalue[0];
 				for (i=1; i < td->td_samplesperpixel; ++i)
@@ -1486,7 +1486,8 @@ TIFFAdvanceDirectory(TIFF* tif, uint64* nextdir, uint64* off)
 				(void) TIFFSeekFile(tif,
 				    dircount16*20, SEEK_CUR);
 			if (!ReadOK(tif, nextdir, sizeof (uint64))) {
-				TIFFErrorExt(tif->tif_clientdata, module, "%s: Error fetching directory link",
+				TIFFErrorExt(tif->tif_clientdata, module,
+                                             "%s: Error fetching directory link",
 				    tif->tif_name);
 				return (0);
 			}
@@ -1513,10 +1514,14 @@ TIFFNumberOfDirectories(TIFF* tif)
 	n = 0;
 	while (nextdir != 0 && TIFFAdvanceDirectory(tif, &nextdir, NULL))
         {
-		if(++n == 0)
+                if (n != 65535) {
+                        ++n;
+                }
+		else
                 {
                         TIFFErrorExt(tif->tif_clientdata, module,
-                                     "Directory count exceeded 65535 limit, giving up on counting.");
+                                     "Directory count exceeded 65535 limit,"
+                                     " giving up on counting.");
                         return (65535);
                 }
         }
diff --git a/frmts/gtiff/libtiff/tif_dirinfo.c b/frmts/gtiff/libtiff/tif_dirinfo.c
index 7db4bdb..3d4f50f 100644
--- a/frmts/gtiff/libtiff/tif_dirinfo.c
+++ b/frmts/gtiff/libtiff/tif_dirinfo.c
@@ -1,4 +1,4 @@
-/* $Id: tif_dirinfo.c,v 1.121 2014-05-07 01:58:46 bfriesen Exp $ */
+/* $Id: tif_dirinfo.c,v 1.125 2016-01-23 21:20:34 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -38,14 +38,22 @@
  * NOTE: The second field (field_readcount) and third field (field_writecount)
  *       sometimes use the values TIFF_VARIABLE (-1), TIFF_VARIABLE2 (-3)
  *       and TIFF_SPP (-2). The macros should be used but would throw off
- *       the formatting of the code, so please interprete the -1, -2 and -3
+ *       the formatting of the code, so please interpret the -1, -2 and -3
  *       values accordingly.
  */
 
-static TIFFFieldArray tiffFieldArray;
-static TIFFFieldArray exifFieldArray;
-
-static TIFFField
+/* const object should be initialized */
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable : 4132 )
+#endif
+static const TIFFFieldArray tiffFieldArray;
+static const TIFFFieldArray exifFieldArray;
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
+
+static const TIFFField
 tiffFields[] = {
 	{ TIFFTAG_SUBFILETYPE, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_SUBFILETYPE, 1, 0, "SubfileType", NULL },
 	{ TIFFTAG_OSUBFILETYPE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_SUBFILETYPE, 1, 0, "OldSubfileType", NULL },
@@ -95,7 +103,7 @@ tiffFields[] = {
 	{ TIFFTAG_TILELENGTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_TILEDIMENSIONS, 0, 0, "TileLength", NULL },
 	{ TIFFTAG_TILEOFFSETS, -1, 1, TIFF_LONG8, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_STRIPOFFSETS, 0, 0, "TileOffsets", NULL },
 	{ TIFFTAG_TILEBYTECOUNTS, -1, 1, TIFF_LONG8, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_STRIPBYTECOUNTS, 0, 0, "TileByteCounts", NULL },
-	{ TIFFTAG_SUBIFD, -1, -1, TIFF_IFD8, 0, TIFF_SETGET_C16_IFD8, TIFF_SETGET_UNDEFINED, FIELD_SUBIFD, 1, 1, "SubIFD", &tiffFieldArray },
+	{ TIFFTAG_SUBIFD, -1, -1, TIFF_IFD8, 0, TIFF_SETGET_C16_IFD8, TIFF_SETGET_UNDEFINED, FIELD_SUBIFD, 1, 1, "SubIFD", (TIFFFieldArray*) &tiffFieldArray },
 	{ TIFFTAG_INKSET, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "InkSet", NULL },
 	{ TIFFTAG_INKNAMES, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_C16_ASCII, TIFF_SETGET_UNDEFINED, FIELD_INKNAMES, 1, 1, "InkNames", NULL },
 	{ TIFFTAG_NUMBEROFINKS, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "NumberOfInks", NULL },
@@ -134,7 +142,7 @@ tiffFields[] = {
 	/* end Pixar tags */
 	{ TIFFTAG_RICHTIFFIPTC, -3, -3, TIFF_LONG, 0, TIFF_SETGET_C32_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "RichTIFFIPTC", NULL },
 	{ TIFFTAG_PHOTOSHOP, -3, -3, TIFF_BYTE, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "Photoshop", NULL },
-	{ TIFFTAG_EXIFIFD, 1, 1, TIFF_IFD8, 0, TIFF_SETGET_IFD8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "EXIFIFDOffset", &exifFieldArray },
+	{ TIFFTAG_EXIFIFD, 1, 1, TIFF_IFD8, 0, TIFF_SETGET_IFD8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "EXIFIFDOffset", (TIFFFieldArray*) &exifFieldArray },
 	{ TIFFTAG_ICCPROFILE, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "ICC Profile", NULL },
 	{ TIFFTAG_GPSIFD, 1, 1, TIFF_IFD8, 0, TIFF_SETGET_IFD8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "GPSIFDOffset", NULL },
 	{ TIFFTAG_FAXRECVPARAMS, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UINT32, FIELD_CUSTOM, TRUE, FALSE, "FaxRecvParams", NULL },
@@ -211,7 +219,7 @@ tiffFields[] = {
 	/* begin pseudo tags */
 };
 
-static TIFFField
+static const TIFFField
 exifFields[] = {
 	{ EXIFTAG_EXPOSURETIME, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ExposureTime", NULL },
 	{ EXIFTAG_FNUMBER, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FNumber", NULL },
@@ -271,13 +279,13 @@ exifFields[] = {
 	{ EXIFTAG_IMAGEUNIQUEID, 33, 33, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ImageUniqueID", NULL }
 };
 
-static TIFFFieldArray
-tiffFieldArray = { tfiatImage, 0, TIFFArrayCount(tiffFields), tiffFields };
-static TIFFFieldArray
-exifFieldArray = { tfiatExif, 0, TIFFArrayCount(exifFields), exifFields };
+static const TIFFFieldArray
+tiffFieldArray = { tfiatImage, 0, TIFFArrayCount(tiffFields), (TIFFField*) tiffFields };
+static const TIFFFieldArray
+exifFieldArray = { tfiatExif, 0, TIFFArrayCount(exifFields), (TIFFField*) exifFields };
 
 /*
- *  We have our own local lfind() equivelent to avoid subtle differences
+ *  We have our own local lfind() equivalent to avoid subtle differences
  *  in types passed to lfind() on different systems. 
  */
 
@@ -521,7 +529,7 @@ TIFFFindField(TIFF* tif, uint32 tag, TIFFDataType dt)
 	return tif->tif_foundfield = (ret ? *ret : NULL);
 }
 
-const TIFFField*
+static const TIFFField*
 _TIFFFindFieldByName(TIFF* tif, const char *field_name, TIFFDataType dt)
 {
 	TIFFField key = {0, 0, 0, TIFF_NOTYPE, 0, 0, 0, 0, 0, 0, NULL, NULL};
diff --git a/frmts/gtiff/libtiff/tif_dirread.c b/frmts/gtiff/libtiff/tif_dirread.c
index 7835a7c..80d059b 100644
--- a/frmts/gtiff/libtiff/tif_dirread.c
+++ b/frmts/gtiff/libtiff/tif_dirread.c
@@ -1,4 +1,4 @@
-/* $Id: tif_dirread.c,v 1.183 2015-01-03 18:03:40 erouault Exp $ */
+/* $Id: tif_dirread.c,v 1.200 2016-01-03 10:01:25 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -2172,11 +2172,6 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntrySlong8Array(TIFF* tif, TIFFDirEn
 			break;
 	}
 	_TIFFfree(origdata);
-	if (err!=TIFFReadDirEntryErrOk)
-	{
-		_TIFFfree(data);
-		return(err);
-	}
 	*value=data;
 	return(TIFFReadDirEntryErrOk);
 }
@@ -2414,11 +2409,6 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryFloatArray(TIFF* tif, TIFFDirEnt
 			break;
 	}
 	_TIFFfree(origdata);
-	if (err!=TIFFReadDirEntryErrOk)
-	{
-		_TIFFfree(data);
-		return(err);
-	}
 	*value=data;
 	return(TIFFReadDirEntryErrOk);
 }
@@ -2657,11 +2647,6 @@ TIFFReadDirEntryDoubleArray(TIFF* tif, TIFFDirEntry* direntry, double** value)
 			break;
 	}
 	_TIFFfree(origdata);
-	if (err!=TIFFReadDirEntryErrOk)
-	{
-		_TIFFfree(data);
-		return(err);
-	}
 	*value=data;
 	return(TIFFReadDirEntryErrOk);
 }
@@ -2723,11 +2708,6 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryIfd8Array(TIFF* tif, TIFFDirEntr
 			break;
 	}
 	_TIFFfree(origdata);
-	if (err!=TIFFReadDirEntryErrOk)
-	{
-		_TIFFfree(data);
-		return(err);
-	}
 	*value=data;
 	return(TIFFReadDirEntryErrOk);
 }
@@ -3194,11 +3174,7 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLongSlong(int32 value)
 /*
  * Largest 32-bit unsigned integer value.
  */
-#if defined(__WIN32__) && defined(_MSC_VER)
-# define TIFF_UINT32_MAX 0xFFFFFFFFI64
-#else
-# define TIFF_UINT32_MAX 0xFFFFFFFFLL
-#endif
+#define TIFF_UINT32_MAX 0xFFFFFFFFU
 
 static enum TIFFReadDirEntryErr
 TIFFReadDirEntryCheckRangeLongLong8(uint64 value)
@@ -3212,7 +3188,7 @@ TIFFReadDirEntryCheckRangeLongLong8(uint64 value)
 static enum TIFFReadDirEntryErr
 TIFFReadDirEntryCheckRangeLongSlong8(int64 value)
 {
-	if ((value<0) || (value > TIFF_UINT32_MAX))
+	if ((value < 0) || (value > (int64) TIFF_UINT32_MAX))
 		return(TIFFReadDirEntryErrRange);
 	else
 		return(TIFFReadDirEntryErrOk);
@@ -3229,19 +3205,21 @@ TIFFReadDirEntryCheckRangeSlongLong(uint32 value)
 		return(TIFFReadDirEntryErrOk);
 }
 
+/* Check that the 8-byte unsigned value can fit in a 4-byte unsigned range */
 static enum TIFFReadDirEntryErr
 TIFFReadDirEntryCheckRangeSlongLong8(uint64 value)
 {
-	if (value > 0x7FFFFFFFUL)
+	if (value > 0x7FFFFFFF)
 		return(TIFFReadDirEntryErrRange);
 	else
 		return(TIFFReadDirEntryErrOk);
 }
 
+/* Check that the 8-byte signed value can fit in a 4-byte signed range */
 static enum TIFFReadDirEntryErr
 TIFFReadDirEntryCheckRangeSlongSlong8(int64 value)
 {
-	if ((value < 0L-0x80000000L) || (value > 0x7FFFFFFFL))
+        if ((value < 0-((int64) 0x7FFFFFFF+1)) || (value > 0x7FFFFFFF))
 		return(TIFFReadDirEntryErrRange);
 	else
 		return(TIFFReadDirEntryErrOk);
@@ -3286,11 +3264,7 @@ TIFFReadDirEntryCheckRangeLong8Slong8(int64 value)
 /*
  * Largest 64-bit signed integer value.
  */
-#if defined(__WIN32__) && defined(_MSC_VER)
-# define TIFF_INT64_MAX 0x7FFFFFFFFFFFFFFFI64
-#else
-# define TIFF_INT64_MAX 0x7FFFFFFFFFFFFFFFLL
-#endif
+#define TIFF_INT64_MAX ((int64)(((uint64) ~0) >> 1))
 
 static enum TIFFReadDirEntryErr
 TIFFReadDirEntryCheckRangeSlong8Long8(uint64 value)
@@ -3483,12 +3457,12 @@ TIFFReadDirectory(TIFF* tif)
 	 * the fields to check type and tag information,
 	 * and to extract info required to size data
 	 * structures.  A second pass is made afterwards
-	 * to read in everthing not taken in the first pass.
+	 * to read in everything not taken in the first pass.
 	 * But we must process the Compression tag first
 	 * in order to merge in codec-private tag definitions (otherwise
 	 * we may get complaints about unknown tags).  However, the
 	 * Compression tag may be dependent on the SamplesPerPixel
-	 * tag value because older TIFF specs permited Compression
+	 * tag value because older TIFF specs permitted Compression
 	 * to be written as a SamplesPerPixel-count tag entry.
 	 * Thus if we don't first figure out the correct SamplesPerPixel
 	 * tag value then we may end up ignoring the Compression tag
@@ -3689,7 +3663,7 @@ TIFFReadDirectory(TIFF* tif)
 				 * DataType and SampleFormat tags are supposed to be
 				 * written as one value/sample, but some vendors
 				 * incorrectly write one value only -- so we accept
-				 * that as well (yech). Other vendors write correct
+				 * that as well (yuck). Other vendors write correct
 				 * value for NumberOfSamples, but incorrect one for
 				 * BitsPerSample and friends, and we will read this
 				 * too.
@@ -3716,7 +3690,7 @@ TIFFReadDirectory(TIFF* tif)
 			case TIFFTAG_SMAXSAMPLEVALUE:
 				{
 
-					double *data;
+					double *data = NULL;
 					enum TIFFReadDirEntryErr err;
 					uint32 saved_flags;
 					int m;
@@ -3767,7 +3741,7 @@ TIFFReadDirectory(TIFF* tif)
 					uint32 countrequired;
 					uint32 incrementpersample;
 					uint16* value=NULL;
-                    /* It would be dangerous to instanciate those tag values */
+                    /* It would be dangerous to instantiate those tag values */
                     /* since if td_bitspersample has not yet been read (due to */
                     /* unordered tags), it could be read afterwards with a */
                     /* values greater than the default one (1), which may cause */
@@ -3780,7 +3754,19 @@ TIFFReadDirectory(TIFF* tif)
                                        fip ? fip->field_name : "unknown tagname");
                         continue;
                     }
-					countpersample=(1L<<tif->tif_dir.td_bitspersample);
+					/* ColorMap or TransferFunction for high bit */
+					/* depths do not make much sense and could be */
+					/* used as a denial of service vector */
+					if (tif->tif_dir.td_bitspersample > 24)
+					{
+					    fip = TIFFFieldWithTag(tif,dp->tdir_tag);
+					    TIFFWarningExt(tif->tif_clientdata,module,
+						"Ignoring %s because BitsPerSample=%d>24",
+						fip ? fip->field_name : "unknown tagname",
+						tif->tif_dir.td_bitspersample);
+					    continue;
+					}
+					countpersample=(1U<<tif->tif_dir.td_bitspersample);
 					if ((dp->tdir_tag==TIFFTAG_TRANSFERFUNCTION)&&(dp->tdir_count==(uint64)countpersample))
 					{
 						countrequired=countpersample;
@@ -4168,7 +4154,7 @@ TIFFReadDirectoryFindFieldInfo(TIFF* tif, uint16 tagid, uint32* fii)
 }
 
 /*
- * Read custom directory from the arbitarry offset.
+ * Read custom directory from the arbitrary offset.
  * The code is very similar to TIFFReadDirectory().
  */
 int
@@ -4295,8 +4281,8 @@ EstimateStripByteCounts(TIFF* tif, TIFFDirEntry* dir, uint16 dircount)
 	TIFFDirectory *td = &tif->tif_dir;
 	uint32 strip;
 
-    if( !_TIFFFillStriles( tif ) )
-        return -1;
+        if( !_TIFFFillStriles( tif ) )
+            return -1;
 
 	if (td->td_stripbytecount)
 		_TIFFfree(td->td_stripbytecount);
@@ -4318,7 +4304,7 @@ EstimateStripByteCounts(TIFF* tif, TIFFDirEntry* dir, uint16 dircount)
 		/* calculate amount of space used by indirect values */
 		for (dp = dir, n = dircount; n > 0; n--, dp++)
 		{
-			uint32 typewidth = TIFFDataWidth((TIFFDataType) dp->tdir_type);
+			uint32 typewidth;
 			uint64 datasize;
 			typewidth = TIFFDataWidth((TIFFDataType) dp->tdir_type);
 			if (typewidth == 0) {
@@ -4408,7 +4394,7 @@ TIFFCheckDirOffset(TIFF* tif, uint64 diroff)
 
 	tif->tif_dirnumber++;
 
-	if (tif->tif_dirnumber > tif->tif_dirlistsize) {
+	if (tif->tif_dirlist == NULL || tif->tif_dirnumber > tif->tif_dirlistsize) {
 		uint64* new_dirlist;
 
 		/*
@@ -4598,7 +4584,6 @@ TIFFFetchDirectory(TIFF* tif, uint64 diroff, TIFFDirEntry** pdir,
 		}
 		else
 		{
-			tmsize_t m;
 			uint64 dircount64;
 			m=off+sizeof(uint64);
 			if ((m<off)||(m<(tmsize_t)sizeof(uint64))||(m>tif->tif_size)) {
diff --git a/frmts/gtiff/libtiff/tif_dirwrite.c b/frmts/gtiff/libtiff/tif_dirwrite.c
index fa20609..33befd4 100644
--- a/frmts/gtiff/libtiff/tif_dirwrite.c
+++ b/frmts/gtiff/libtiff/tif_dirwrite.c
@@ -1,4 +1,4 @@
-/* $Id: tif_dirwrite.c,v 1.77 2012-07-06 19:18:31 bfriesen Exp $ */
+/* $Id: tif_dirwrite.c,v 1.81 2015-12-18 11:11:00 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -645,7 +645,7 @@ TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff)
 									assert(o->field_passcount==0);
 									TIFFGetField(tif,o->field_tag,&pb);
 									pa=(uint32)(strlen(pb));
-									if (!TIFFWriteDirectoryTagAscii(tif,&ndir,dir,o->field_tag,pa,pb))
+									if (!TIFFWriteDirectoryTagAscii(tif,&ndir,dir,(uint16)o->field_tag,pa,pb))
 										goto bad;
 								}
 								break;
@@ -656,7 +656,7 @@ TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff)
 									assert(o->field_readcount==1);
 									assert(o->field_passcount==0);
 									TIFFGetField(tif,o->field_tag,&p);
-									if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,o->field_tag,p))
+									if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,(uint16)o->field_tag,p))
 										goto bad;
 								}
 								break;
@@ -667,7 +667,7 @@ TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff)
 									assert(o->field_readcount==1);
 									assert(o->field_passcount==0);
 									TIFFGetField(tif,o->field_tag,&p);
-									if (!TIFFWriteDirectoryTagLong(tif,&ndir,dir,o->field_tag,p))
+									if (!TIFFWriteDirectoryTagLong(tif,&ndir,dir,(uint16)o->field_tag,p))
 										goto bad;
 								}
 								break;
@@ -679,7 +679,7 @@ TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff)
 									assert(o->field_readcount==TIFF_VARIABLE2);
 									assert(o->field_passcount==1);
 									TIFFGetField(tif,o->field_tag,&pa,&pb);
-									if (!TIFFWriteDirectoryTagUndefinedArray(tif,&ndir,dir,o->field_tag,pa,pb))
+									if (!TIFFWriteDirectoryTagUndefinedArray(tif,&ndir,dir,(uint16)o->field_tag,pa,pb))
 										goto bad;
 								}
 								break;
@@ -693,70 +693,72 @@ TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff)
 		}
 		for (m=0; m<(uint32)(tif->tif_dir.td_customValueCount); m++)
 		{
+                        uint16 tag = (uint16)tif->tif_dir.td_customValues[m].info->field_tag;
+                        uint32 count = tif->tif_dir.td_customValues[m].count;
 			switch (tif->tif_dir.td_customValues[m].info->field_type)
 			{
 				case TIFF_ASCII:
-					if (!TIFFWriteDirectoryTagAscii(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
+					if (!TIFFWriteDirectoryTagAscii(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value))
 						goto bad;
 					break;
 				case TIFF_UNDEFINED:
-					if (!TIFFWriteDirectoryTagUndefinedArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
+					if (!TIFFWriteDirectoryTagUndefinedArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value))
 						goto bad;
 					break;
 				case TIFF_BYTE:
-					if (!TIFFWriteDirectoryTagByteArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
+					if (!TIFFWriteDirectoryTagByteArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value))
 						goto bad;
 					break;
 				case TIFF_SBYTE:
-					if (!TIFFWriteDirectoryTagSbyteArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
+					if (!TIFFWriteDirectoryTagSbyteArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value))
 						goto bad;
 					break;
 				case TIFF_SHORT:
-					if (!TIFFWriteDirectoryTagShortArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
+					if (!TIFFWriteDirectoryTagShortArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value))
 						goto bad;
 					break;
 				case TIFF_SSHORT:
-					if (!TIFFWriteDirectoryTagSshortArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
+					if (!TIFFWriteDirectoryTagSshortArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value))
 						goto bad;
 					break;
 				case TIFF_LONG:
-					if (!TIFFWriteDirectoryTagLongArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
+					if (!TIFFWriteDirectoryTagLongArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value))
 						goto bad;
 					break;
 				case TIFF_SLONG:
-					if (!TIFFWriteDirectoryTagSlongArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
+					if (!TIFFWriteDirectoryTagSlongArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value))
 						goto bad;
 					break;
 				case TIFF_LONG8:
-					if (!TIFFWriteDirectoryTagLong8Array(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
+					if (!TIFFWriteDirectoryTagLong8Array(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value))
 						goto bad;
 					break;
 				case TIFF_SLONG8:
-					if (!TIFFWriteDirectoryTagSlong8Array(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
+					if (!TIFFWriteDirectoryTagSlong8Array(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value))
 						goto bad;
 					break;
 				case TIFF_RATIONAL:
-					if (!TIFFWriteDirectoryTagRationalArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
+					if (!TIFFWriteDirectoryTagRationalArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value))
 						goto bad;
 					break;
 				case TIFF_SRATIONAL:
-					if (!TIFFWriteDirectoryTagSrationalArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
+					if (!TIFFWriteDirectoryTagSrationalArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value))
 						goto bad;
 					break;
 				case TIFF_FLOAT:
-					if (!TIFFWriteDirectoryTagFloatArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
+					if (!TIFFWriteDirectoryTagFloatArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value))
 						goto bad;
 					break;
 				case TIFF_DOUBLE:
-					if (!TIFFWriteDirectoryTagDoubleArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
+					if (!TIFFWriteDirectoryTagDoubleArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value))
 						goto bad;
 					break;
 				case TIFF_IFD:
-					if (!TIFFWriteDirectoryTagIfdArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
+					if (!TIFFWriteDirectoryTagIfdArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value))
 						goto bad;
 					break;
 				case TIFF_IFD8:
-					if (!TIFFWriteDirectoryTagIfdIfd8Array(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
+					if (!TIFFWriteDirectoryTagIfdIfd8Array(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value))
 						goto bad;
 					break;
 				default:
@@ -778,7 +780,7 @@ TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff)
 				goto bad;
 		}
 		else
-			tif->tif_diroff=(TIFFSeekFile(tif,0,SEEK_END)+1)&(~1);
+			tif->tif_diroff=(TIFFSeekFile(tif,0,SEEK_END)+1)&(~((toff_t)1));
 		if (pdiroff!=NULL)
 			*pdiroff=tif->tif_diroff;
 		if (!(tif->tif_flags&TIFF_BIGTIFF))
@@ -828,7 +830,7 @@ TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff)
 		uint32 nTmp;
 		TIFFDirEntry* o;
 		n=dirmem;
-		*(uint16*)n=ndir;
+		*(uint16*)n=(uint16)ndir;
 		if (tif->tif_flags&TIFF_SWAB)
 			TIFFSwabShort((uint16*)n);
 		n+=2;
@@ -2368,7 +2370,7 @@ TIFFLinkDirectory(TIFF* tif)
 {
 	static const char module[] = "TIFFLinkDirectory";
 
-	tif->tif_diroff = (TIFFSeekFile(tif,0,SEEK_END)+1) &~ 1;
+	tif->tif_diroff = (TIFFSeekFile(tif,0,SEEK_END)+1) & (~((toff_t)1));
 
 	/*
 	 * Handle SubIFDs
@@ -2839,14 +2841,15 @@ _TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype,
                          "Error writing directory link");
             return (0);
         }
-        
-        _TIFFfree( buf_to_write );
     }
     else
     {
         memcpy( &entry_offset, buf_to_write, count*TIFFDataWidth(datatype));
     }
 
+    _TIFFfree( buf_to_write );
+    buf_to_write = 0;
+
 /* -------------------------------------------------------------------- */
 /*      Adjust the directory entry.                                     */
 /* -------------------------------------------------------------------- */
diff --git a/frmts/gtiff/libtiff/tif_dumpmode.c b/frmts/gtiff/libtiff/tif_dumpmode.c
index a94cf0b..a6a94c0 100644
--- a/frmts/gtiff/libtiff/tif_dumpmode.c
+++ b/frmts/gtiff/libtiff/tif_dumpmode.c
@@ -1,4 +1,4 @@
-/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_dumpmode.c,v 1.14 2011-04-02 20:54:09 bfriesen Exp $ */
+/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_dumpmode.c,v 1.15 2015-12-12 18:04:26 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -66,7 +66,7 @@ DumpModeEncode(TIFF* tif, uint8* pp, tmsize_t cc, uint16 s)
 		cc -= n;
 		if (tif->tif_rawcc >= tif->tif_rawdatasize &&
 		    !TIFFFlushData1(tif))
-			return (-1);
+			return (0);
 	}
 	return (1);
 }
diff --git a/frmts/gtiff/libtiff/tif_extension.c b/frmts/gtiff/libtiff/tif_extension.c
index 10afd41..39fab4c 100644
--- a/frmts/gtiff/libtiff/tif_extension.c
+++ b/frmts/gtiff/libtiff/tif_extension.c
@@ -1,4 +1,4 @@
-/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_extension.c,v 1.7 2010-03-10 18:56:48 bfriesen Exp $ */
+/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_extension.c,v 1.8 2015-12-06 11:13:43 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -66,13 +66,13 @@ TIFFTagMethods *TIFFAccessTagMethods( TIFF *tif )
 void *TIFFGetClientInfo( TIFF *tif, const char *name )
 
 {
-    TIFFClientInfoLink *link = tif->tif_clientinfo;
+    TIFFClientInfoLink *psLink = tif->tif_clientinfo;
 
-    while( link != NULL && strcmp(link->name,name) != 0 )
-        link = link->next;
+    while( psLink != NULL && strcmp(psLink->name,name) != 0 )
+        psLink = psLink->next;
 
-    if( link != NULL )
-        return link->data;
+    if( psLink != NULL )
+        return psLink->data;
     else
         return NULL;
 }
@@ -80,18 +80,18 @@ void *TIFFGetClientInfo( TIFF *tif, const char *name )
 void TIFFSetClientInfo( TIFF *tif, void *data, const char *name )
 
 {
-    TIFFClientInfoLink *link = tif->tif_clientinfo;
+    TIFFClientInfoLink *psLink = tif->tif_clientinfo;
 
     /*
     ** Do we have an existing link with this name?  If so, just
     ** set it.
     */
-    while( link != NULL && strcmp(link->name,name) != 0 )
-        link = link->next;
+    while( psLink != NULL && strcmp(psLink->name,name) != 0 )
+        psLink = psLink->next;
 
-    if( link != NULL )
+    if( psLink != NULL )
     {
-        link->data = data;
+        psLink->data = data;
         return;
     }
 
@@ -99,15 +99,15 @@ void TIFFSetClientInfo( TIFF *tif, void *data, const char *name )
     ** Create a new link.
     */
 
-    link = (TIFFClientInfoLink *) _TIFFmalloc(sizeof(TIFFClientInfoLink));
-    assert (link != NULL);
-    link->next = tif->tif_clientinfo;
-    link->name = (char *) _TIFFmalloc((tmsize_t)(strlen(name)+1));
-    assert (link->name != NULL);
-    strcpy(link->name, name);
-    link->data = data;
+    psLink = (TIFFClientInfoLink *) _TIFFmalloc(sizeof(TIFFClientInfoLink));
+    assert (psLink != NULL);
+    psLink->next = tif->tif_clientinfo;
+    psLink->name = (char *) _TIFFmalloc((tmsize_t)(strlen(name)+1));
+    assert (psLink->name != NULL);
+    strcpy(psLink->name, name);
+    psLink->data = data;
 
-    tif->tif_clientinfo = link;
+    tif->tif_clientinfo = psLink;
 }
 /*
  * Local Variables:
diff --git a/frmts/gtiff/libtiff/tif_fax3.c b/frmts/gtiff/libtiff/tif_fax3.c
index 2b2dccd..e053b52 100644
--- a/frmts/gtiff/libtiff/tif_fax3.c
+++ b/frmts/gtiff/libtiff/tif_fax3.c
@@ -1,4 +1,4 @@
-/* $Id: tif_fax3.c,v 1.74 2012-06-21 02:01:31 fwarmerdam Exp $ */
+/* $Id: tif_fax3.c,v 1.77 2015-12-19 21:50:52 erouault Exp $ */
 
 /*
  * Copyright (c) 1990-1997 Sam Leffler
@@ -442,8 +442,9 @@ _TIFFFax3fillruns(unsigned char* buf, uint32* runs, uint32* erun, uint32 lastx)
 			FILL(n, cp);
 			run &= 7;
 		    }
+                    /* Explicit 0xff masking to make icc -check=conversions happy */
 		    if (run)
-			cp[0] |= 0xff00 >> run;
+			cp[0] = (unsigned char)((cp[0] | (0xff00 >> run))&0xff);
 		} else
 		    cp[0] |= _fillmasks[run]>>bx;
 		x += runs[1];
@@ -696,7 +697,6 @@ Fax3PutEOL(TIFF* tif)
 				align = sp->bit + (8 - align);
 			else
 				align = sp->bit - align;
-			code = 0;
 			tparm=align; 
 			_PutBits(tif, 0, tparm);
 		}
@@ -814,7 +814,7 @@ find0span(unsigned char* bp, int32 bs, int32 be)
 	/*
 	 * Check partial byte on lhs.
 	 */
-	if (bits > 0 && (n = (bs & 7))) {
+	if (bits > 0 && (n = (bs & 7)) != 0) {
 		span = zeroruns[(*bp << n) & 0xff];
 		if (span > 8-n)		/* table value too generous */
 			span = 8-n;
@@ -873,7 +873,7 @@ find1span(unsigned char* bp, int32 bs, int32 be)
 	/*
 	 * Check partial byte on lhs.
 	 */
-	if (bits > 0 && (n = (bs & 7))) {
+	if (bits > 0 && (n = (bs & 7)) != 0) {
 		span = oneruns[(*bp << n) & 0xff];
 		if (span > 8-n)		/* table value too generous */
 			span = 8-n;
@@ -1181,7 +1181,7 @@ Fax3VSetField(TIFF* tif, uint32 tag, va_list ap)
 		return (*sp->vsetparent)(tif, tag, ap);
 	}
 	
-	if ((fip = TIFFFieldWithTag(tif, tag)))
+	if ((fip = TIFFFieldWithTag(tif, tag)) != NULL)
 		TIFFSetFieldBit(tif, fip->field_bit);
 	else
 		return 0;
diff --git a/frmts/gtiff/libtiff/tif_fax3.h b/frmts/gtiff/libtiff/tif_fax3.h
index b0f46c9..e0b2ca6 100644
--- a/frmts/gtiff/libtiff/tif_fax3.h
+++ b/frmts/gtiff/libtiff/tif_fax3.h
@@ -1,4 +1,4 @@
-/* $Id: tif_fax3.h,v 1.9 2011-03-10 20:23:07 fwarmerdam Exp $ */
+/* $Id: tif_fax3.h,v 1.11 2016-01-23 21:20:34 erouault Exp $ */
 
 /*
  * Copyright (c) 1990-1997 Sam Leffler
@@ -39,7 +39,7 @@
 
 /*
  * To override the default routine used to image decoded
- * spans one can use the pseduo tag TIFFTAG_FAXFILLFUNC.
+ * spans one can use the pseudo tag TIFFTAG_FAXFILLFUNC.
  * The routine must have the type signature given below;
  * for example:
  *
@@ -84,7 +84,7 @@ extern void _TIFFFax3fillruns(unsigned char*, uint32*, uint32*, uint32);
 typedef struct {                /* state table entry */
 	unsigned char State;    /* see above */
 	unsigned char Width;    /* width of code in bits */
-	uint32 Param;           /* unsigned 32-bit run length in bits */
+	uint16 Param;           /* unsigned 16-bit run length in bits */
 } TIFFFaxTabEnt;
 
 extern const TIFFFaxTabEnt TIFFFaxMainTable[];
diff --git a/frmts/gtiff/libtiff/tif_getimage.c b/frmts/gtiff/libtiff/tif_getimage.c
index a856cc5..c55dc22 100644
--- a/frmts/gtiff/libtiff/tif_getimage.c
+++ b/frmts/gtiff/libtiff/tif_getimage.c
@@ -1,4 +1,4 @@
-/* $Id: tif_getimage.c,v 1.87 2014-12-29 18:28:46 erouault Exp $ */
+/* $Id: tif_getimage.c,v 1.95 2016-01-23 21:20:34 erouault Exp $ */
 
 /*
  * Copyright (c) 1991-1997 Sam Leffler
@@ -182,20 +182,22 @@ TIFFRGBAImageOK(TIFF* tif, char emsg[1024])
 				    "Planarconfiguration", td->td_planarconfig);
 				return (0);
 			}
-			if( td->td_samplesperpixel != 3 )
+			if( td->td_samplesperpixel != 3 || colorchannels != 3 )
             {
                 sprintf(emsg,
-                        "Sorry, can not handle image with %s=%d",
-                        "Samples/pixel", td->td_samplesperpixel);
+                        "Sorry, can not handle image with %s=%d, %s=%d",
+                        "Samples/pixel", td->td_samplesperpixel,
+                        "colorchannels", colorchannels);
                 return 0;
             }
 			break;
 		case PHOTOMETRIC_CIELAB:
-            if( td->td_samplesperpixel != 3 || td->td_bitspersample != 8 )
+            if( td->td_samplesperpixel != 3 || colorchannels != 3 || td->td_bitspersample != 8 )
             {
                 sprintf(emsg,
-                        "Sorry, can not handle image with %s=%d and %s=%d",
+                        "Sorry, can not handle image with %s=%d, %s=%d and %s=%d",
                         "Samples/pixel", td->td_samplesperpixel,
+                        "colorchannels", colorchannels,
                         "Bits/sample", td->td_bitspersample);
                 return 0;
             }
@@ -255,6 +257,9 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
 	int colorchannels;
 	uint16 *red_orig, *green_orig, *blue_orig;
 	int n_color;
+	
+	if( !TIFFRGBAImageOK(tif, emsg) )
+		return 0;
 
 	/* Initialize to normal values */
 	img->row_offset = 0;
@@ -338,7 +343,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
 			}
 
 			/* copy the colormaps so we can modify them */
-			n_color = (1L << img->bitspersample);
+			n_color = (1U << img->bitspersample);
 			img->redcmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color);
 			img->greencmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color);
 			img->bluecmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color);
@@ -351,7 +356,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
 			_TIFFmemcpy( img->greencmap, green_orig, n_color * 2 );
 			_TIFFmemcpy( img->bluecmap, blue_orig, n_color * 2 );
 
-			/* fall thru... */
+			/* fall through... */
 		case PHOTOMETRIC_MINISWHITE:
 		case PHOTOMETRIC_MINISBLACK:
 			if (planarconfig == PLANARCONFIG_CONTIG
@@ -509,7 +514,7 @@ TIFFReadRGBAImageOriented(TIFF* tif,
     int ok;
 
 	if (TIFFRGBAImageOK(tif, emsg) && TIFFRGBAImageBegin(&img, tif, stop, emsg)) {
-		img.req_orientation = orientation;
+		img.req_orientation = (uint16)orientation;
 		/* XXX verify rwidth and rheight against width and height */
 		ok = TIFFRGBAImageGet(&img, raster+(rheight-img.height)*rwidth,
 			rwidth, img.height);
@@ -612,6 +617,10 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
     int32 fromskew, toskew;
     uint32 nrow;
     int ret = 1, flip;
+    uint32 this_tw, tocol;
+    int32 this_toskew, leftmost_toskew;
+    int32 leftmost_fromskew;
+    uint32 leftmost_tw;
 
     buf = (unsigned char*) _TIFFmalloc(TIFFTileSize(tif));
     if (buf == 0) {
@@ -632,37 +641,50 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
 	    toskew = -(int32)(tw - w);
     }
      
+    /*
+     *	Leftmost tile is clipped on left side if col_offset > 0.
+     */
+    leftmost_fromskew = img->col_offset % tw;
+    leftmost_tw = tw - leftmost_fromskew;
+    leftmost_toskew = toskew + leftmost_fromskew;
     for (row = 0; row < h; row += nrow)
     {
         rowstoread = th - (row + img->row_offset) % th;
     	nrow = (row + rowstoread > h ? h - row : rowstoread);
-	for (col = 0; col < w; col += tw) 
+	fromskew = leftmost_fromskew;
+	this_tw = leftmost_tw;
+	this_toskew = leftmost_toskew;
+	tocol = 0;
+	col = img->col_offset;
+	while (tocol < w)
         {
-	    if (TIFFReadTile(tif, buf, col+img->col_offset,  
+	    if (TIFFReadTile(tif, buf, col,  
 			     row+img->row_offset, 0, 0)==(tmsize_t)(-1) && img->stoponerr)
             {
                 ret = 0;
                 break;
             }
-	    
-	    pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif);  
-
-    	    if (col + tw > w) 
-            {
-                /*
-                 * Tile is clipped horizontally.  Calculate
-                 * visible portion and skewing factors.
-                 */
-                uint32 npix = w - col;
-                fromskew = tw - npix;
-                (*put)(img, raster+y*w+col, col, y,
-                       npix, nrow, fromskew, toskew + fromskew, buf + pos);
-            }
-            else 
-            {
-                (*put)(img, raster+y*w+col, col, y, tw, nrow, 0, toskew, buf + pos);
-            }
-        }
+            pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif) + \
+		   ((tmsize_t) fromskew * img->samplesperpixel);
+	    if (tocol + this_tw > w) 
+	    {
+		/*
+		 * Rightmost tile is clipped on right side.
+		 */
+		fromskew = tw - (w - tocol);
+		this_tw = tw - fromskew;
+		this_toskew = toskew + fromskew;
+	    }
+	    (*put)(img, raster+y*w+tocol, tocol, y, this_tw, nrow, fromskew, this_toskew, buf + pos);
+	    tocol += this_tw;
+	    col += this_tw;
+	    /*
+	     * After the leftmost tile, tiles are no longer clipped on left side.
+	     */
+	    fromskew = 0;
+	    this_tw = tw;
+	    this_toskew = toskew;
+	}
 
         y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow);
     }
@@ -712,7 +734,11 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
 	int alpha = img->alpha;
 	uint32 nrow;
 	int ret = 1, flip;
-        int colorchannels;
+        uint16 colorchannels;
+	uint32 this_tw, tocol;
+	int32 this_toskew, leftmost_toskew;
+	int32 leftmost_fromskew;
+	uint32 leftmost_tw;
 
 	tilesize = TIFFTileSize(tif);  
 	bufsize = TIFFSafeMultiply(tmsize_t,alpha?4:3,tilesize);
@@ -757,20 +783,31 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
             break;
         }
 
+	/*
+	 *	Leftmost tile is clipped on left side if col_offset > 0.
+	 */
+	leftmost_fromskew = img->col_offset % tw;
+	leftmost_tw = tw - leftmost_fromskew;
+	leftmost_toskew = toskew + leftmost_fromskew;
 	for (row = 0; row < h; row += nrow)
 	{
 		rowstoread = th - (row + img->row_offset) % th;
 		nrow = (row + rowstoread > h ? h - row : rowstoread);
-		for (col = 0; col < w; col += tw)
+		fromskew = leftmost_fromskew;
+		this_tw = leftmost_tw;
+		this_toskew = leftmost_toskew;
+		tocol = 0;
+		col = img->col_offset;
+		while (tocol < w)
 		{
-			if (TIFFReadTile(tif, p0, col+img->col_offset,  
+			if (TIFFReadTile(tif, p0, col,  
 			    row+img->row_offset,0,0)==(tmsize_t)(-1) && img->stoponerr)
 			{
 				ret = 0;
 				break;
 			}
 			if (colorchannels > 1 
-                            && TIFFReadTile(tif, p1, col+img->col_offset,  
+                            && TIFFReadTile(tif, p1, col,  
                                             row+img->row_offset,0,1) == (tmsize_t)(-1) 
                             && img->stoponerr)
 			{
@@ -778,7 +815,7 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
 				break;
 			}
 			if (colorchannels > 1 
-                            && TIFFReadTile(tif, p2, col+img->col_offset,  
+                            && TIFFReadTile(tif, p2, col,  
                                             row+img->row_offset,0,2) == (tmsize_t)(-1) 
                             && img->stoponerr)
 			{
@@ -786,7 +823,7 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
 				break;
 			}
 			if (alpha
-                            && TIFFReadTile(tif,pa,col+img->col_offset,  
+                            && TIFFReadTile(tif,pa,col,  
                                             row+img->row_offset,0,colorchannels) == (tmsize_t)(-1) 
                             && img->stoponerr)
                         {
@@ -794,23 +831,27 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
                             break;
 			}
 
-			pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif);  
-
-			if (col + tw > w)
+			pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif) + \
+			   ((tmsize_t) fromskew * img->samplesperpixel);
+			if (tocol + this_tw > w) 
 			{
 				/*
-				 * Tile is clipped horizontally.  Calculate
-				 * visible portion and skewing factors.
+				 * Rightmost tile is clipped on right side.
 				 */
-				uint32 npix = w - col;
-				fromskew = tw - npix;
-				(*put)(img, raster+y*w+col, col, y,
-				    npix, nrow, fromskew, toskew + fromskew,
-				    p0 + pos, p1 + pos, p2 + pos, (alpha?(pa+pos):NULL));
-			} else {
-				(*put)(img, raster+y*w+col, col, y,
-				    tw, nrow, 0, toskew, p0 + pos, p1 + pos, p2 + pos, (alpha?(pa+pos):NULL));
+				fromskew = tw - (w - tocol);
+				this_tw = tw - fromskew;
+				this_toskew = toskew + fromskew;
 			}
+			(*put)(img, raster+y*w+tocol, tocol, y, this_tw, nrow, fromskew, this_toskew, \
+				p0 + pos, p1 + pos, p2 + pos, (alpha?(pa+pos):NULL));
+			tocol += this_tw;
+			col += this_tw;
+			/*
+			* After the leftmost tile, tiles are no longer clipped on left side.
+			*/
+			fromskew = 0;
+			this_tw = tw;
+			this_toskew = toskew;
 		}
 
 		y += (flip & FLIP_VERTICALLY ?-(int32) nrow : (int32) nrow);
@@ -900,7 +941,8 @@ gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
 			break;
 		}
 
-		pos = ((row + img->row_offset) % rowsperstrip) * scanline;
+		pos = ((row + img->row_offset) % rowsperstrip) * scanline + \
+			((tmsize_t) img->col_offset * img->samplesperpixel);
 		(*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, buf + pos);
 		y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow);
 	}
@@ -947,7 +989,8 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
 	tmsize_t bufsize;
 	int32 fromskew, toskew;
 	int alpha = img->alpha;
-	int ret = 1, flip, colorchannels;
+	int ret = 1, flip;
+        uint16 colorchannels;
 
 	stripsize = TIFFStripSize(tif);  
 	bufsize = TIFFSafeMultiply(tmsize_t,alpha?4:3,stripsize);
@@ -1031,7 +1074,8 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
 			}
 		}
 
-		pos = ((row + img->row_offset) % rowsperstrip) * scanline;
+		pos = ((row + img->row_offset) % rowsperstrip) * scanline + \
+			((tmsize_t) img->col_offset * img->samplesperpixel);
 		(*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, p0 + pos, p1 + pos,
 		    p2 + pos, (alpha?(pa+pos):NULL));
 		y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow);
@@ -1640,15 +1684,15 @@ DECLARESepPutFunc(putRGBUAseparate16bittile)
 	uint16 *wa = (uint16*) a;
 	(void) img; (void) y;
 	while (h-- > 0) {
-		uint32 r,g,b,a;
+		uint32 r2,g2,b2,a2;
 		uint8* m;
 		for (x = w; x-- > 0;) {
-			a = img->Bitdepth16To8[*wa++];
-			m = img->UaToAa+(a<<8);
-			r = m[img->Bitdepth16To8[*wr++]];
-			g = m[img->Bitdepth16To8[*wg++]];
-			b = m[img->Bitdepth16To8[*wb++]];
-			*cp++ = PACK4(r,g,b,a);
+			a2 = img->Bitdepth16To8[*wa++];
+			m = img->UaToAa+(a2<<8);
+			r2 = m[img->Bitdepth16To8[*wr++]];
+			g2 = m[img->Bitdepth16To8[*wg++]];
+			b2 = m[img->Bitdepth16To8[*wb++]];
+			*cp++ = PACK4(r2,g2,b2,a2);
 		}
 		SKEW4(wr, wg, wb, wa, fromskew);
 		cp += toskew;
@@ -2432,7 +2476,7 @@ buildMap(TIFFRGBAImage* img)
     case PHOTOMETRIC_SEPARATED:
 	if (img->bitspersample == 8)
 	    break;
-	/* fall thru... */
+	/* fall through... */
     case PHOTOMETRIC_MINISBLACK:
     case PHOTOMETRIC_MINISWHITE:
 	if (!setupMap(img))
@@ -2470,29 +2514,33 @@ PickContigCase(TIFFRGBAImage* img)
 		case PHOTOMETRIC_RGB:
 			switch (img->bitspersample) {
 				case 8:
-					if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
+					if (img->alpha == EXTRASAMPLE_ASSOCALPHA &&
+						img->samplesperpixel >= 4)
 						img->put.contig = putRGBAAcontig8bittile;
-					else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
+					else if (img->alpha == EXTRASAMPLE_UNASSALPHA &&
+							 img->samplesperpixel >= 4)
 					{
 						if (BuildMapUaToAa(img))
 							img->put.contig = putRGBUAcontig8bittile;
 					}
-					else
+					else if( img->samplesperpixel >= 3 )
 						img->put.contig = putRGBcontig8bittile;
 					break;
 				case 16:
-					if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
+					if (img->alpha == EXTRASAMPLE_ASSOCALPHA &&
+						img->samplesperpixel >=4 )
 					{
 						if (BuildMapBitdepth16To8(img))
 							img->put.contig = putRGBAAcontig16bittile;
 					}
-					else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
+					else if (img->alpha == EXTRASAMPLE_UNASSALPHA &&
+							 img->samplesperpixel >=4 )
 					{
 						if (BuildMapBitdepth16To8(img) &&
 						    BuildMapUaToAa(img))
 							img->put.contig = putRGBUAcontig16bittile;
 					}
-					else
+					else if( img->samplesperpixel >=3 )
 					{
 						if (BuildMapBitdepth16To8(img))
 							img->put.contig = putRGBcontig16bittile;
@@ -2501,7 +2549,7 @@ PickContigCase(TIFFRGBAImage* img)
 			}
 			break;
 		case PHOTOMETRIC_SEPARATED:
-			if (buildMap(img)) {
+			if (img->samplesperpixel >=4 && buildMap(img)) {
 				if (img->bitspersample == 8) {
 					if (!img->Map)
 						img->put.contig = putRGBcontig8bitCMYKtile;
@@ -2597,7 +2645,7 @@ PickContigCase(TIFFRGBAImage* img)
 			}
 			break;
 		case PHOTOMETRIC_CIELAB:
-			if (buildMap(img)) {
+			if (img->samplesperpixel == 3 && buildMap(img)) {
 				if (img->bitspersample == 8)
 					img->put.contig = initCIELabConversion(img);
 				break;
@@ -2698,7 +2746,7 @@ BuildMapUaToAa(TIFFRGBAImage* img)
 	for (na=0; na<256; na++)
 	{
 		for (nv=0; nv<256; nv++)
-			*m++=(nv*na+127)/255;
+			*m++=(uint8)((nv*na+127)/255);
 	}
 	return(1);
 }
@@ -2718,7 +2766,7 @@ BuildMapBitdepth16To8(TIFFRGBAImage* img)
 	}
 	m=img->Bitdepth16To8;
 	for (n=0; n<65536; n++)
-		*m++=(n+128)/257;
+		*m++=(uint8)((n+128)/257);
 	return(1);
 }
 
diff --git a/frmts/gtiff/libtiff/tif_jpeg.c b/frmts/gtiff/libtiff/tif_jpeg.c
index dc77f55..70b72d8 100644
--- a/frmts/gtiff/libtiff/tif_jpeg.c
+++ b/frmts/gtiff/libtiff/tif_jpeg.c
@@ -1,4 +1,4 @@
-/* $Id: tif_jpeg.c,v 1.114 2014-12-30 16:37:22 erouault Exp $ */
+/* $Id: tif_jpeg.c,v 1.123 2016-01-23 21:20:34 erouault Exp $ */
 
 /*
  * Copyright (c) 1994-1997 Sam Leffler
@@ -58,7 +58,7 @@ int TIFFReInitJPEG_12( TIFF *tif, int scheme, int is_encode );
   Libjpeg's jmorecfg.h defines INT16 and INT32, but only if XMD_H is
   not defined.  Unfortunately, the MinGW and Borland compilers include
   a typedef for INT32, which causes a conflict.  MSVC does not include
-  a conficting typedef given the headers which are included.
+  a conflicting typedef given the headers which are included.
 */
 #if defined(__BORLANDC__) || defined(__MINGW32__)
 # define XMD_H 1
@@ -252,6 +252,9 @@ TIFFjpeg_create_compress(JPEGState* sp)
 	sp->err.error_exit = TIFFjpeg_error_exit;
 	sp->err.output_message = TIFFjpeg_output_message;
 
+	/* set client_data to avoid UMR warning from tools like Purify */
+	sp->cinfo.c.client_data = NULL;
+
 	return CALLVJPEG(sp, jpeg_create_compress(&sp->cinfo.c));
 }
 
@@ -263,6 +266,9 @@ TIFFjpeg_create_decompress(JPEGState* sp)
 	sp->err.error_exit = TIFFjpeg_error_exit;
 	sp->err.output_message = TIFFjpeg_output_message;
 
+	/* set client_data to avoid UMR warning from tools like Purify */
+	sp->cinfo.d.client_data = NULL;
+
 	return CALLVJPEG(sp, jpeg_create_decompress(&sp->cinfo.d));
 }
 
@@ -931,7 +937,7 @@ JPEGFixupTagsSubsamplingSkip(struct JPEGFixupTagsSubsamplingData* data, uint16 s
 	else
 	{
 		uint16 m;
-		m=skiplength-data->bufferbytesleft;
+		m=(uint16)(skiplength-data->bufferbytesleft);
 		if (m<=data->filebytesleft)
 		{
 			data->bufferbytesleft=0;
@@ -998,7 +1004,7 @@ JPEGSetupDecode(TIFF* tif)
 /*
  * Set up for decoding a strip or tile.
  */
-static int
+/*ARGSUSED*/ static int
 JPEGPreDecode(TIFF* tif, uint16 s)
 {
 	JPEGState *sp = JState(tif);
@@ -1174,7 +1180,8 @@ JPEGPreDecode(TIFF* tif, uint16 s)
  * Decode a chunk of pixels.
  * "Standard" case: returned data is not downsampled.
  */
-/*ARGSUSED*/ static int
+#if !JPEG_LIB_MK1_OR_12BIT
+static int
 JPEGDecode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
 {
 	JPEGState *sp = JState(tif);
@@ -1193,91 +1200,137 @@ JPEGDecode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
         
 	nrows = cc / sp->bytesperline;
 	if (cc % sp->bytesperline)
-		TIFFWarningExt(tif->tif_clientdata, tif->tif_name, "fractional scanline not read");
+		TIFFWarningExt(tif->tif_clientdata, tif->tif_name,
+                               "fractional scanline not read");
 
 	if( nrows > (tmsize_t) sp->cinfo.d.image_height )
 		nrows = sp->cinfo.d.image_height;
 
 	/* data is expected to be read in multiples of a scanline */
 	if (nrows)
-	{
-		JSAMPROW line_work_buf = NULL;
+        {
+                do
+                {
+                        /*
+                         * In the libjpeg6b-9a 8bit case.  We read directly into
+                         * the TIFF buffer.
+                         */
+                        JSAMPROW bufptr = (JSAMPROW)buf;
 
-		/*
-		 * For 6B, only use temporary buffer for 12 bit imagery.
-		 * For Mk1 always use it.
-		 */
-#if !defined(JPEG_LIB_MK1)
-		if( sp->cinfo.d.data_precision == 12 )
-#endif
-		{
-			line_work_buf = (JSAMPROW)
-			    _TIFFmalloc(sizeof(short) * sp->cinfo.d.output_width
-			    * sp->cinfo.d.num_components );
-		}
+                        if (TIFFjpeg_read_scanlines(sp, &bufptr, 1) != 1)
+                                return (0);
 
-		do {
-			if( line_work_buf != NULL )
-			{
-				/*
-				 * In the MK1 case, we aways read into a 16bit buffer, and then
-				 * pack down to 12bit or 8bit.  In 6B case we only read into 16
-				 * bit buffer for 12bit data, which we need to repack.
-				*/
-				if (TIFFjpeg_read_scanlines(sp, &line_work_buf, 1) != 1)
-					return (0);
+                        ++tif->tif_row;
+                        buf += sp->bytesperline;
+                        cc -= sp->bytesperline;
+                } while (--nrows > 0);
+        }
 
-				if( sp->cinfo.d.data_precision == 12 )
-				{
-					int value_pairs = (sp->cinfo.d.output_width
-					    * sp->cinfo.d.num_components) / 2;
-					int iPair;
+        /* Update information on consumed data */
+        tif->tif_rawcp = (uint8*) sp->src.next_input_byte;
+        tif->tif_rawcc = sp->src.bytes_in_buffer;
+                
+	/* Close down the decompressor if we've finished the strip or tile. */
+	return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height
+                || TIFFjpeg_finish_decompress(sp);
+}
+#endif /* !JPEG_LIB_MK1_OR_12BIT */
 
-					for( iPair = 0; iPair < value_pairs; iPair++ )
-					{
-						unsigned char *out_ptr =
-						    ((unsigned char *) buf) + iPair * 3;
-						JSAMPLE *in_ptr = line_work_buf + iPair * 2;
-
-						out_ptr[0] = (in_ptr[0] & 0xff0) >> 4;
-						out_ptr[1] = ((in_ptr[0] & 0xf) << 4)
-						    | ((in_ptr[1] & 0xf00) >> 8);
-						out_ptr[2] = ((in_ptr[1] & 0xff) >> 0);
-					}
-				}
-				else if( sp->cinfo.d.data_precision == 8 )
-				{
-					int value_count = (sp->cinfo.d.output_width
-					    * sp->cinfo.d.num_components);
-					int iValue;
+#if JPEG_LIB_MK1_OR_12BIT
+/*ARGSUSED*/ static int
+JPEGDecode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
+{
+	JPEGState *sp = JState(tif);
+	tmsize_t nrows;
+	(void) s;
 
-					for( iValue = 0; iValue < value_count; iValue++ )
-					{
-						((unsigned char *) buf)[iValue] =
-						    line_work_buf[iValue] & 0xff;
-					}
-				}
-			}
-			else
-			{
-				/*
-				 * In the libjpeg6b 8bit case.  We read directly into the
-				 * TIFF buffer.
-				*/
-				JSAMPROW bufptr = (JSAMPROW)buf;
+        /*
+        ** Update available information, buffer may have been refilled
+        ** between decode requests
+        */
+	sp->src.next_input_byte = (const JOCTET*) tif->tif_rawcp;
+	sp->src.bytes_in_buffer = (size_t) tif->tif_rawcc;
 
-				if (TIFFjpeg_read_scanlines(sp, &bufptr, 1) != 1)
-					return (0);
-			}
+        if( sp->bytesperline == 0 )
+                return 0;
+        
+	nrows = cc / sp->bytesperline;
+	if (cc % sp->bytesperline)
+		TIFFWarningExt(tif->tif_clientdata, tif->tif_name,
+                               "fractional scanline not read");
 
-			++tif->tif_row;
-			buf += sp->bytesperline;
-			cc -= sp->bytesperline;
-		} while (--nrows > 0);
+	if( nrows > (tmsize_t) sp->cinfo.d.image_height )
+		nrows = sp->cinfo.d.image_height;
 
-		if( line_work_buf != NULL )
-			_TIFFfree( line_work_buf );
-	}
+	/* data is expected to be read in multiples of a scanline */
+	if (nrows)
+        {
+                JSAMPROW line_work_buf = NULL;
+
+                /*
+                 * For 6B, only use temporary buffer for 12 bit imagery.
+                 * For Mk1 always use it.
+                 */
+                if( sp->cinfo.d.data_precision == 12 )
+                {
+                        line_work_buf = (JSAMPROW)
+                                _TIFFmalloc(sizeof(short) * sp->cinfo.d.output_width
+                                            * sp->cinfo.d.num_components );
+                }
+
+               do
+               {
+                       if( line_work_buf != NULL )
+                       {
+                               /*
+                                * In the MK1 case, we always read into a 16bit
+                                * buffer, and then pack down to 12bit or 8bit.
+                                * In 6B case we only read into 16 bit buffer
+                                * for 12bit data, which we need to repack.
+                                */
+                               if (TIFFjpeg_read_scanlines(sp, &line_work_buf, 1) != 1)
+                                       return (0);
+
+                               if( sp->cinfo.d.data_precision == 12 )
+                               {
+                                       int value_pairs = (sp->cinfo.d.output_width
+                                                          * sp->cinfo.d.num_components) / 2;
+                                       int iPair;
+
+                                       for( iPair = 0; iPair < value_pairs; iPair++ )
+                                       {
+                                               unsigned char *out_ptr =
+                                                       ((unsigned char *) buf) + iPair * 3;
+                                               JSAMPLE *in_ptr = line_work_buf + iPair * 2;
+
+                                               out_ptr[0] = (unsigned char)((in_ptr[0] & 0xff0) >> 4);
+                                               out_ptr[1] = (unsigned char)(((in_ptr[0] & 0xf) << 4)
+                                                       | ((in_ptr[1] & 0xf00) >> 8));
+                                               out_ptr[2] = (unsigned char)(((in_ptr[1] & 0xff) >> 0));
+                                       }
+                               }
+                               else if( sp->cinfo.d.data_precision == 8 )
+                               {
+                                       int value_count = (sp->cinfo.d.output_width
+                                                          * sp->cinfo.d.num_components);
+                                       int iValue;
+
+                                       for( iValue = 0; iValue < value_count; iValue++ )
+                                       {
+                                               ((unsigned char *) buf)[iValue] =
+                                                       line_work_buf[iValue] & 0xff;
+                                       }
+                               }
+                       }
+
+                       ++tif->tif_row;
+                       buf += sp->bytesperline;
+                       cc -= sp->bytesperline;
+               } while (--nrows > 0);
+
+               if( line_work_buf != NULL )
+                       _TIFFfree( line_work_buf );
+        }
 
         /* Update information on consumed data */
         tif->tif_rawcp = (uint8*) sp->src.next_input_byte;
@@ -1285,8 +1338,9 @@ JPEGDecode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
                 
 	/* Close down the decompressor if we've finished the strip or tile. */
 	return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height
-	    || TIFFjpeg_finish_decompress(sp);
+                || TIFFjpeg_finish_decompress(sp);
 }
+#endif /* JPEG_LIB_MK1_OR_12BIT */
 
 /*ARGSUSED*/ static int
 DecodeRowError(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
@@ -1313,7 +1367,7 @@ JPEGDecodeRaw(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
 	(void) s;
 
 	/* data is expected to be read in multiples of a scanline */
-	if ( (nrows = sp->cinfo.d.image_height) ) {
+	if ( (nrows = sp->cinfo.d.image_height) != 0 ) {
 
 		/* Cb,Cr both have sampling factors 1, so this is correct */
 		JDIMENSION clumps_per_line = sp->cinfo.d.comp_info[1].downsampled_width;            
@@ -1413,10 +1467,10 @@ JPEGDecodeRaw(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
 					{
 						unsigned char *out_ptr = ((unsigned char *) buf) + iPair * 3;
 						JSAMPLE *in_ptr = (JSAMPLE *) (tmpbuf + iPair * 2);
-						out_ptr[0] = (in_ptr[0] & 0xff0) >> 4;
-						out_ptr[1] = ((in_ptr[0] & 0xf) << 4)
-							| ((in_ptr[1] & 0xf00) >> 8);
-						out_ptr[2] = ((in_ptr[1] & 0xff) >> 0);
+						out_ptr[0] = (unsigned char)((in_ptr[0] & 0xff0) >> 4);
+						out_ptr[1] = (unsigned char)(((in_ptr[0] & 0xf) << 4)
+							| ((in_ptr[1] & 0xf00) >> 8));
+						out_ptr[2] = (unsigned char)(((in_ptr[1] & 0xff) >> 0));
 					}
 				}
 			}
@@ -1839,9 +1893,16 @@ JPEGEncode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
 
         if( sp->cinfo.c.data_precision == 12 )
         {
-            line16_count = (sp->bytesperline * 2) / 3;
+            line16_count = (int)((sp->bytesperline * 2) / 3);
             line16 = (short *) _TIFFmalloc(sizeof(short) * line16_count);
-	    // FIXME: undiagnosed malloc failure
+            if (!line16)
+            {
+                TIFFErrorExt(tif->tif_clientdata,
+			     "JPEGEncode",
+                             "Failed to allocate memory");
+
+                return 0;
+            }
         }
             
 	while (nrows-- > 0) {
@@ -2016,13 +2077,10 @@ JPEGCleanup(TIFF* tif)
 	tif->tif_tagmethods.vgetfield = sp->vgetparent;
 	tif->tif_tagmethods.vsetfield = sp->vsetparent;
 	tif->tif_tagmethods.printdir = sp->printdir;
-
-	if( sp != NULL ) {
-		if( sp->cinfo_initialized )
-		    TIFFjpeg_destroy(sp);	/* release libjpeg resources */
-		if (sp->jpegtables)		/* tag value */
-			_TIFFfree(sp->jpegtables);
-	}
+        if( sp->cinfo_initialized )
+                TIFFjpeg_destroy(sp);	/* release libjpeg resources */
+        if (sp->jpegtables)		/* tag value */
+                _TIFFfree(sp->jpegtables);
 	_TIFFfree(tif->tif_data);	/* release local state */
 	tif->tif_data = NULL;
 
@@ -2080,8 +2138,7 @@ JPEGVSetField(TIFF* tif, uint32 tag, va_list ap)
 			/* XXX */
 			return (0);
 		}
-		_TIFFsetByteArray(&sp->jpegtables, va_arg(ap, void*),
-		    (long) v32);
+		_TIFFsetByteArray(&sp->jpegtables, va_arg(ap, void*), v32);
 		sp->jpegtables_length = v32;
 		TIFFSetFieldBit(tif, FIELD_JPEGTABLES);
 		break;
@@ -2110,7 +2167,7 @@ JPEGVSetField(TIFF* tif, uint32 tag, va_list ap)
 		return (*sp->vsetparent)(tif, tag, ap);
 	}
 
-	if ((fip = TIFFFieldWithTag(tif, tag))) {
+	if ((fip = TIFFFieldWithTag(tif, tag)) != NULL) {
 		TIFFSetFieldBit(tif, fip->field_bit);
 	} else {
 		return (0);
@@ -2334,8 +2391,17 @@ here hopefully is harmless.
 */
             sp->jpegtables_length = SIZE_OF_JPEGTABLES;
             sp->jpegtables = (void *) _TIFFmalloc(sp->jpegtables_length);
-	    // FIXME: NULL-deref after malloc failure
-	    _TIFFmemset(sp->jpegtables, 0, SIZE_OF_JPEGTABLES);
+            if (sp->jpegtables)
+            {
+                _TIFFmemset(sp->jpegtables, 0, SIZE_OF_JPEGTABLES);
+            }
+            else
+            {
+                TIFFErrorExt(tif->tif_clientdata,
+			     "TIFFInitJPEG",
+                             "Failed to allocate memory for JPEG tables");
+                return 0;
+            }
 #undef SIZE_OF_JPEGTABLES
         }
 
diff --git a/frmts/gtiff/libtiff/tif_jpeg_12.c b/frmts/gtiff/libtiff/tif_jpeg_12.c
index 87aaa19..8499e64 100644
--- a/frmts/gtiff/libtiff/tif_jpeg_12.c
+++ b/frmts/gtiff/libtiff/tif_jpeg_12.c
@@ -5,6 +5,9 @@
 
 #  define TIFFInitJPEG TIFFInitJPEG_12
 
+int
+TIFFInitJPEG_12(TIFF* tif, int scheme);
+
 #  include LIBJPEG_12_PATH
 
 #  include "tif_jpeg.c"
diff --git a/frmts/gtiff/libtiff/tif_luv.c b/frmts/gtiff/libtiff/tif_luv.c
index eba6c08..60a174d 100644
--- a/frmts/gtiff/libtiff/tif_luv.c
+++ b/frmts/gtiff/libtiff/tif_luv.c
@@ -1,4 +1,4 @@
-/* $Id: tif_luv.c,v 1.35 2011-04-02 20:54:09 bfriesen Exp $ */
+/* $Id: tif_luv.c,v 1.41 2015-12-27 16:25:11 erouault Exp $ */
 
 /*
  * Copyright (c) 1997 Greg Ward Larson
@@ -202,7 +202,11 @@ LogL16Decode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
 	if (sp->user_datafmt == SGILOGDATAFMT_16BIT)
 		tp = (int16*) op;
 	else {
-		assert(sp->tbuflen >= npixels);
+		if(sp->tbuflen < npixels) {
+			TIFFErrorExt(tif->tif_clientdata, module,
+						 "Translation buffer too short");
+			return (0);
+		}
 		tp = (int16*) sp->tbuf;
 	}
 	_TIFFmemset((void*) tp, 0, npixels*sizeof (tp[0]));
@@ -211,9 +215,11 @@ LogL16Decode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
 	cc = tif->tif_rawcc;
 	/* get each byte string */
 	for (shft = 2*8; (shft -= 8) >= 0; ) {
-		for (i = 0; i < npixels && cc > 0; )
+		for (i = 0; i < npixels && cc > 0; ) {
 			if (*bp >= 128) {		/* run */
-				rc = *bp++ + (2-128);   /* TODO: potential input buffer overrun when decoding corrupt or truncated data */
+				if( cc < 2 )
+					break;
+				rc = *bp++ + (2-128);
 				b = (int16)(*bp++ << shft);
 				cc -= 2;
 				while (rc-- && i < npixels)
@@ -223,6 +229,7 @@ LogL16Decode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
 				while (--cc && rc-- && i < npixels)
 					tp[i++] |= (int16)*bp++ << shft;
 			}
+		}
 		if (i != npixels) {
 #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
 			TIFFErrorExt(tif->tif_clientdata, module,
@@ -268,13 +275,17 @@ LogLuvDecode24(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
 	if (sp->user_datafmt == SGILOGDATAFMT_RAW)
 		tp = (uint32 *)op;
 	else {
-		assert(sp->tbuflen >= npixels);
+		if(sp->tbuflen < npixels) {
+			TIFFErrorExt(tif->tif_clientdata, module,
+						 "Translation buffer too short");
+			return (0);
+		}
 		tp = (uint32 *) sp->tbuf;
 	}
 	/* copy to array of uint32 */
 	bp = (unsigned char*) tif->tif_rawcp;
 	cc = tif->tif_rawcc;
-	for (i = 0; i < npixels && cc > 0; i++) {
+	for (i = 0; i < npixels && cc >= 3; i++) {
 		tp[i] = bp[0] << 16 | bp[1] << 8 | bp[2];
 		bp += 3;
 		cc -= 3;
@@ -325,7 +336,11 @@ LogLuvDecode32(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
 	if (sp->user_datafmt == SGILOGDATAFMT_RAW)
 		tp = (uint32*) op;
 	else {
-		assert(sp->tbuflen >= npixels);
+		if(sp->tbuflen < npixels) {
+			TIFFErrorExt(tif->tif_clientdata, module,
+						 "Translation buffer too short");
+			return (0);
+		}
 		tp = (uint32*) sp->tbuf;
 	}
 	_TIFFmemset((void*) tp, 0, npixels*sizeof (tp[0]));
@@ -334,11 +349,13 @@ LogLuvDecode32(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
 	cc = tif->tif_rawcc;
 	/* get each byte string */
 	for (shft = 4*8; (shft -= 8) >= 0; ) {
-		for (i = 0; i < npixels && cc > 0; )
+		for (i = 0; i < npixels && cc > 0; ) {
 			if (*bp >= 128) {		/* run */
+				if( cc < 2 )
+					break;
 				rc = *bp++ + (2-128);
 				b = (uint32)*bp++ << shft;
-				cc -= 2;                /* TODO: potential input buffer overrun when decoding corrupt or truncated data */
+				cc -= 2;
 				while (rc-- && i < npixels)
 					tp[i++] |= b;
 			} else {			/* non-run */
@@ -346,6 +363,7 @@ LogLuvDecode32(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
 				while (--cc && rc-- && i < npixels)
 					tp[i++] |= (uint32)*bp++ << shft;
 			}
+		}
 		if (i != npixels) {
 #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
 			TIFFErrorExt(tif->tif_clientdata, module,
@@ -379,6 +397,9 @@ LogLuvDecodeStrip(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 {
 	tmsize_t rowlen = TIFFScanlineSize(tif);
 
+        if (rowlen == 0)
+                return 0;
+
 	assert(cc%rowlen == 0);
 	while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s))
 		bp += rowlen, cc -= rowlen;
@@ -395,6 +416,9 @@ LogLuvDecodeTile(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 {
 	tmsize_t rowlen = TIFFTileRowSize(tif);
 
+        if (rowlen == 0)
+                return 0;
+
 	assert(cc%rowlen == 0);
 	while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s))
 		bp += rowlen, cc -= rowlen;
@@ -407,6 +431,7 @@ LogLuvDecodeTile(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 static int
 LogL16Encode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 {
+	static const char module[] = "LogL16Encode";
 	LogLuvState* sp = EncoderState(tif);
 	int shft;
 	tmsize_t i;
@@ -427,7 +452,11 @@ LogL16Encode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 		tp = (int16*) bp;
 	else {
 		tp = (int16*) sp->tbuf;
-		assert(sp->tbuflen >= npixels);
+		if(sp->tbuflen < npixels) {
+			TIFFErrorExt(tif->tif_clientdata, module,
+						 "Translation buffer too short");
+			return (0);
+		}
 		(*sp->tfunc)(sp, bp, npixels);
 	}
 	/* compress each byte string */
@@ -500,6 +529,7 @@ LogL16Encode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 static int
 LogLuvEncode24(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 {
+	static const char module[] = "LogLuvEncode24";
 	LogLuvState* sp = EncoderState(tif);
 	tmsize_t i;
 	tmsize_t npixels;
@@ -515,7 +545,11 @@ LogLuvEncode24(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 		tp = (uint32*) bp;
 	else {
 		tp = (uint32*) sp->tbuf;
-		assert(sp->tbuflen >= npixels);
+		if(sp->tbuflen < npixels) {
+			TIFFErrorExt(tif->tif_clientdata, module,
+						 "Translation buffer too short");
+			return (0);
+		}
 		(*sp->tfunc)(sp, bp, npixels);
 	}
 	/* write out encoded pixels */
@@ -547,6 +581,7 @@ LogLuvEncode24(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 static int
 LogLuvEncode32(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 {
+	static const char module[] = "LogLuvEncode32";
 	LogLuvState* sp = EncoderState(tif);
 	int shft;
 	tmsize_t i;
@@ -568,7 +603,11 @@ LogLuvEncode32(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 		tp = (uint32*) bp;
 	else {
 		tp = (uint32*) sp->tbuf;
-		assert(sp->tbuflen >= npixels);
+		if(sp->tbuflen < npixels) {
+			TIFFErrorExt(tif->tif_clientdata, module,
+						 "Translation buffer too short");
+			return (0);
+		}
 		(*sp->tfunc)(sp, bp, npixels);
 	}
 	/* compress each byte string */
@@ -644,6 +683,9 @@ LogLuvEncodeStrip(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 {
 	tmsize_t rowlen = TIFFScanlineSize(tif);
 
+        if (rowlen == 0)
+                return 0;
+
 	assert(cc%rowlen == 0);
 	while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 1)
 		bp += rowlen, cc -= rowlen;
@@ -659,6 +701,9 @@ LogLuvEncodeTile(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 {
 	tmsize_t rowlen = TIFFTileRowSize(tif);
 
+        if (rowlen == 0)
+                return 0;
+
 	assert(cc%rowlen == 0);
 	while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 1)
 		bp += rowlen, cc -= rowlen;
@@ -683,7 +728,9 @@ LogLuvEncodeTile(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 #ifndef M_PI
 #define M_PI		3.14159265358979323846
 #endif
+#undef log2 /* Conflict with C'99 function */
 #define log2(x)		((1./M_LN2)*log(x))
+#undef exp2  /* Conflict with C'99 function */
 #define exp2(x)		exp(M_LN2*(x))
 
 #define itrunc(x,m)	((m)==SGILOGENCODE_NODITHER ? \
diff --git a/frmts/gtiff/libtiff/tif_lzma.c b/frmts/gtiff/libtiff/tif_lzma.c
index dedf1d9..0a9ad31 100644
--- a/frmts/gtiff/libtiff/tif_lzma.c
+++ b/frmts/gtiff/libtiff/tif_lzma.c
@@ -1,4 +1,4 @@
-/* $Id: tif_lzma.c,v 1.4 2011-12-22 00:29:29 bfriesen Exp $ */
+/* $Id: tif_lzma.c,v 1.5 2016-01-23 21:20:34 erouault Exp $ */
 
 /*
  * Copyright (c) 2010, Andrey Kiselev <dron at ak4719.spb.edu>
@@ -95,7 +95,7 @@ LZMAStrerror(lzma_ret ret)
 		case LZMA_PROG_ERROR:
 		    return "programming error";
 		default:
-		    return "unindentified liblzma error";
+		    return "unidentified liblzma error";
 	}
 }
 
@@ -490,6 +490,6 @@ bad:
 		     "No space for LZMA2 state block");
 	return 0;
 }
-#endif /* LZMA_SUPORT */
+#endif /* LZMA_SUPPORT */
 
 /* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/frmts/gtiff/libtiff/tif_lzw.c b/frmts/gtiff/libtiff/tif_lzw.c
index b81bc71..b2282b3 100644
--- a/frmts/gtiff/libtiff/tif_lzw.c
+++ b/frmts/gtiff/libtiff/tif_lzw.c
@@ -1,4 +1,4 @@
-/* $Id: tif_lzw.c,v 1.46 2014-11-20 16:47:21 erouault Exp $ */
+/* $Id: tif_lzw.c,v 1.51 2016-01-23 21:20:34 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -94,7 +94,7 @@ typedef struct {
 	unsigned short  nbits;          /* # of bits/code */
 	unsigned short  maxcode;        /* maximum code for lzw_nbits */
 	unsigned short  free_ent;       /* next free entry in hash table */
-	long            nextdata;       /* next bits of i/o */
+	unsigned long   nextdata;       /* next bits of i/o */
 	long            nextbits;       /* # of valid bits in lzw_nextdata */
 
 	int             rw_mode;        /* preserve rw_mode from init */
@@ -240,8 +240,8 @@ LZWSetupDecode(TIFF* tif)
 		 */
 		code = 255;
 		do {
-			sp->dec_codetab[code].value = code;
-			sp->dec_codetab[code].firstchar = code;
+			sp->dec_codetab[code].value = (unsigned char)code;
+			sp->dec_codetab[code].firstchar = (unsigned char)code;
 			sp->dec_codetab[code].length = 1;
 			sp->dec_codetab[code].next = NULL;
 		} while (code--);
@@ -367,7 +367,8 @@ LZWDecode(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s)
 	unsigned char *bp;
 	hcode_t code;
 	int len;
-	long nbits, nextbits, nextdata, nbitsmask;
+	long nbits, nextbits, nbitsmask;
+        unsigned long nextdata;
 	code_t *codep, *free_entp, *maxcodep, *oldcodep;
 
 	(void) s;
@@ -417,7 +418,7 @@ LZWDecode(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s)
 			--tp;
 			t = codep->value;
 			codep = codep->next;
-			*tp = t;
+			*tp = (char)t;
 		} while (--residue && codep);
 		sp->dec_restart = 0;
 	}
@@ -436,16 +437,18 @@ LZWDecode(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s)
 		if (code == CODE_EOI)
 			break;
 		if (code == CODE_CLEAR) {
-			free_entp = sp->dec_codetab + CODE_FIRST;
-			_TIFFmemset(free_entp, 0,
-				    (CSIZE - CODE_FIRST) * sizeof (code_t));
-			nbits = BITS_MIN;
-			nbitsmask = MAXCODE(BITS_MIN);
-			maxcodep = sp->dec_codetab + nbitsmask-1;
-			NextCode(tif, sp, bp, code, GetNextCode);
+			do {
+				free_entp = sp->dec_codetab + CODE_FIRST;
+				_TIFFmemset(free_entp, 0,
+					    (CSIZE - CODE_FIRST) * sizeof (code_t));
+				nbits = BITS_MIN;
+				nbitsmask = MAXCODE(BITS_MIN);
+				maxcodep = sp->dec_codetab + nbitsmask-1;
+				NextCode(tif, sp, bp, code, GetNextCode);
+			} while (code == CODE_CLEAR);	/* consecutive CODE_CLEAR codes */
 			if (code == CODE_EOI)
 				break;
-			if (code >= CODE_CLEAR) {
+			if (code > CODE_CLEAR) {
 				TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
 				"LZWDecode: Corrupted LZW table at scanline %d",
 					     tif->tif_row);
@@ -529,7 +532,7 @@ LZWDecode(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s)
 				--tp;
 				t = codep->value;
 				codep = codep->next;
-				*tp = t;
+				*tp = (char)t;
 			} while (codep && tp > op);
 			if (codep) {
 			    codeLoop(tif, module);
@@ -655,22 +658,24 @@ LZWDecodeCompat(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s)
 		if (code == CODE_EOI)
 			break;
 		if (code == CODE_CLEAR) {
-			free_entp = sp->dec_codetab + CODE_FIRST;
-			_TIFFmemset(free_entp, 0,
-				    (CSIZE - CODE_FIRST) * sizeof (code_t));
-			nbits = BITS_MIN;
-			nbitsmask = MAXCODE(BITS_MIN);
-			maxcodep = sp->dec_codetab + nbitsmask;
-			NextCode(tif, sp, bp, code, GetNextCodeCompat);
+			do {
+				free_entp = sp->dec_codetab + CODE_FIRST;
+				_TIFFmemset(free_entp, 0,
+					    (CSIZE - CODE_FIRST) * sizeof (code_t));
+				nbits = BITS_MIN;
+				nbitsmask = MAXCODE(BITS_MIN);
+				maxcodep = sp->dec_codetab + nbitsmask;
+				NextCode(tif, sp, bp, code, GetNextCodeCompat);
+			} while (code == CODE_CLEAR);	/* consecutive CODE_CLEAR codes */
 			if (code == CODE_EOI)
 				break;
-			if (code >= CODE_CLEAR) {
+			if (code > CODE_CLEAR) {
 				TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
 				"LZWDecode: Corrupted LZW table at scanline %d",
 					     tif->tif_row);
 				return (0);
 			}
-			*op++ = code, occ--;
+			*op++ = (char)code, occ--;
 			oldcodep = sp->dec_codetab + code;
 			continue;
 		}
@@ -742,11 +747,11 @@ LZWDecodeCompat(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s)
 				*--tp = codep->value;
 			} while( (codep = codep->next) != NULL );
 		} else
-			*op++ = code, occ--;
+			*op++ = (char)code, occ--;
 	}
 
 	tif->tif_rawcp = (uint8*) bp;
-	sp->lzw_nbits = nbits;
+	sp->lzw_nbits = (unsigned short)nbits;
 	sp->lzw_nextdata = nextdata;
 	sp->lzw_nextbits = nextbits;
 	sp->dec_nbitsmask = nbitsmask;
@@ -832,13 +837,15 @@ LZWPreEncode(TIFF* tif, uint16 s)
 	} else							\
 		rat = (incount<<8) / outcount;			\
 }
+
+/* Explicit 0xff masking to make icc -check=conversions happy */
 #define	PutNextCode(op, c) {					\
 	nextdata = (nextdata << nbits) | c;			\
 	nextbits += nbits;					\
-	*op++ = (unsigned char)(nextdata >> (nextbits-8));		\
+	*op++ = (unsigned char)((nextdata >> (nextbits-8))&0xff);		\
 	nextbits -= 8;						\
 	if (nextbits >= 8) {					\
-		*op++ = (unsigned char)(nextdata >> (nextbits-8));	\
+		*op++ = (unsigned char)((nextdata >> (nextbits-8))&0xff);	\
 		nextbits -= 8;					\
 	}							\
 	outcount += nbits;					\
@@ -868,7 +875,8 @@ LZWEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 	hcode_t ent;
 	long disp;
 	long incount, outcount, checkpoint;
-	long nextdata, nextbits;
+	unsigned long nextdata;
+        long nextbits;
 	int free_ent, maxcode, nbits;
 	uint8* op;
 	uint8* limit;
@@ -892,7 +900,7 @@ LZWEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 	nbits = sp->lzw_nbits;
 	op = tif->tif_rawcp;
 	limit = sp->enc_rawlimit;
-	ent = sp->enc_oldcode;
+	ent = (hcode_t)sp->enc_oldcode;
 
 	if (ent == (hcode_t) -1 && cc > 0) {
 		/*
@@ -928,7 +936,7 @@ LZWEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 				disp = 1;
 			do {
 				/*
-				 * Avoid pointer arithmetic 'cuz of
+				 * Avoid pointer arithmetic because of
 				 * wraparound problems with segments.
 				 */
 				if ((h -= disp) < 0)
@@ -955,8 +963,8 @@ LZWEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 			op = tif->tif_rawdata;
 		}
 		PutNextCode(op, ent);
-		ent = c;
-		hp->code = free_ent++;
+		ent = (hcode_t)c;
+		hp->code = (hcode_t)(free_ent++);
 		hp->hash = fcode;
 		if (free_ent == CODE_MAX-1) {
 			/* table is full, emit clear code and reset */
@@ -1013,9 +1021,9 @@ LZWEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 	sp->enc_oldcode = ent;
 	sp->lzw_nextdata = nextdata;
 	sp->lzw_nextbits = nextbits;
-	sp->lzw_free_ent = free_ent;
-	sp->lzw_maxcode = maxcode;
-	sp->lzw_nbits = nbits;
+	sp->lzw_free_ent = (unsigned short)free_ent;
+	sp->lzw_maxcode = (unsigned short)maxcode;
+	sp->lzw_nbits = (unsigned short)nbits;
 	tif->tif_rawcp = op;
 	return (1);
 }
@@ -1030,7 +1038,7 @@ LZWPostEncode(TIFF* tif)
 	register LZWCodecState *sp = EncoderState(tif);
 	uint8* op = tif->tif_rawcp;
 	long nextbits = sp->lzw_nextbits;
-	long nextdata = sp->lzw_nextdata;
+	unsigned long nextdata = sp->lzw_nextdata;
 	long outcount = sp->enc_outcount;
 	int nbits = sp->lzw_nbits;
 
@@ -1044,8 +1052,9 @@ LZWPostEncode(TIFF* tif)
 		sp->enc_oldcode = (hcode_t) -1;
 	}
 	PutNextCode(op, CODE_EOI);
+        /* Explicit 0xff masking to make icc -check=conversions happy */
 	if (nextbits > 0) 
-		*op++ = (unsigned char)(nextdata << (8-nextbits));
+		*op++ = (unsigned char)((nextdata << (8-nextbits))&0xff);
 	tif->tif_rawcc = (tmsize_t)(op - tif->tif_rawdata);
 	return (1);
 }
diff --git a/frmts/gtiff/libtiff/tif_next.c b/frmts/gtiff/libtiff/tif_next.c
index 17e0311..1a0cd0d 100644
--- a/frmts/gtiff/libtiff/tif_next.c
+++ b/frmts/gtiff/libtiff/tif_next.c
@@ -1,4 +1,4 @@
-/* $Id: tif_next.c,v 1.16 2014-12-29 12:09:11 erouault Exp $ */
+/* $Id: tif_next.c,v 1.18 2015-12-27 17:14:52 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -37,7 +37,7 @@
 	case 0:	op[0]  = (unsigned char) ((v) << 6); break;	\
 	case 1:	op[0] |= (v) << 4; break;	\
 	case 2:	op[0] |= (v) << 2; break;	\
-	case 3:	*op++ |= (v);	   break;	\
+	case 3:	*op++ |= (v);	   op_offset++; break;	\
 	}					\
 }
 
@@ -103,6 +103,7 @@ NeXTDecode(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s)
 		}
 		default: {
 			uint32 npixels = 0, grey;
+			tmsize_t op_offset = 0;
 			uint32 imagewidth = tif->tif_dir.td_imagewidth;
             if( isTiled(tif) )
                 imagewidth = tif->tif_dir.td_tilewidth;
@@ -122,10 +123,15 @@ NeXTDecode(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s)
 				 * bounds, potentially resulting in a security
 				 * issue.
 				 */
-				while (n-- > 0 && npixels < imagewidth)
+				while (n-- > 0 && npixels < imagewidth && op_offset < scanline)
 					SETPIXEL(op, grey);
 				if (npixels >= imagewidth)
 					break;
+                if (op_offset >= scanline ) {
+                    TIFFErrorExt(tif->tif_clientdata, module, "Invalid data for scanline %ld",
+                        (long) tif->tif_row);
+                    return (0);
+                }
 				if (cc == 0)
 					goto bad;
 				n = *bp++, cc--;
diff --git a/frmts/gtiff/libtiff/tif_ojpeg.c b/frmts/gtiff/libtiff/tif_ojpeg.c
index 61f4221..b0efcf5 100644
--- a/frmts/gtiff/libtiff/tif_ojpeg.c
+++ b/frmts/gtiff/libtiff/tif_ojpeg.c
@@ -1,4 +1,4 @@
-/* $Id: tif_ojpeg.c,v 1.58 2014-12-25 18:29:11 erouault Exp $ */
+/* $Id: tif_ojpeg.c,v 1.64 2016-01-23 21:20:34 erouault Exp $ */
 
 /* WARNING: The type of JPEG encapsulation defined by the TIFF Version 6.0
    specification is now totally obsolete and deprecated for new applications and
@@ -75,7 +75,7 @@
    OJPEGSubsamplingCorrect, making no note of any other data, reporting no warnings
    or errors, up to the point where either these values are read, or it's clear they
    aren't there. This means that some of the data is read twice, but we feel speed
-   in correcting these values is important enough to warrant this sacrifice. Allthough
+   in correcting these values is important enough to warrant this sacrifice. Although
    there is currently no define or other configuration mechanism to disable this behaviour,
    the actual header scanning is build to robustly respond with error report if it
    should encounter an uncorrected mismatch of subsampling values. See
@@ -84,7 +84,7 @@
    The restart interval and restart markers are the most tricky part... The restart
    interval can be specified in a tag. It can also be set inside the input JPEG stream.
    It can be used inside the input JPEG stream. If reading from strile data, we've
-   consistenly discovered the need to insert restart markers in between the different
+   consistently discovered the need to insert restart markers in between the different
    striles, as is also probably the most likely interpretation of the original TIFF 6.0
    specification. With all this setting of interval, and actual use of markers that is not
    predictable at the time of valid JPEG header assembly, the restart thing may turn
@@ -113,7 +113,7 @@
    planarconfig is not separate (vast majority). We may one day use that to build
    converters to JPEG, and/or to new-style JPEG compression inside TIFF.
 
-   A dissadvantage is the lack of random access to the individual striles. This is the
+   A disadvantage is the lack of random access to the individual striles. This is the
    reason for much of the complicated restart-and-position stuff inside OJPEGPreDecode.
    Applications would do well accessing all striles in order, as this will result in
    a single sequential scan of the input stream, and no restarting of LibJpeg decoding
@@ -135,7 +135,7 @@
  * 	The default mode, without JPEG_ENCAP_EXTERNAL, implements the call encapsulators
  * 	here, internally, with normal longjump.
  * SETJMP, LONGJMP, JMP_BUF: On some machines/environments a longjump equivalent is
- * 	conviniently available, but still it may be worthwhile to use _setjmp or sigsetjmp
+ * 	conveniently available, but still it may be worthwhile to use _setjmp or sigsetjmp
  * 	in place of plain setjmp. These macros will make it easier. It is useless
  * 	to fiddle with these if you define JPEG_ENCAP_EXTERNAL.
  * OJPEG_BUFFER: Define the size of the desired buffer here. Should be small enough so as to guarantee
@@ -200,7 +200,7 @@ static const TIFFField ojpegFields[] = {
   Libjpeg's jmorecfg.h defines INT16 and INT32, but only if XMD_H is
   not defined.  Unfortunately, the MinGW and Borland compilers include
   a typedef for INT32, which causes a conflict.  MSVC does not include
-  a conficting typedef given the headers which are included.
+  a conflicting typedef given the headers which are included.
 */
 #if defined(__BORLANDC__) || defined(__MINGW32__)
 # define XMD_H 1
@@ -1081,7 +1081,7 @@ OJPEGReadHeaderInfo(TIFF* tif)
 			TIFFErrorExt(tif->tif_clientdata,module,"Incompatible vertical subsampling and image strip/tile length");
 			return(0);
 		}
-		sp->restart_interval=((sp->strile_width+sp->subsampling_hor*8-1)/(sp->subsampling_hor*8))*(sp->strile_length/(sp->subsampling_ver*8));
+		sp->restart_interval=(uint16)(((sp->strile_width+sp->subsampling_hor*8-1)/(sp->subsampling_hor*8))*(sp->strile_length/(sp->subsampling_ver*8)));
 	}
 	if (OJPEGReadHeaderInfoSec(tif)==0)
 		return(0);
@@ -1103,7 +1103,7 @@ OJPEGReadSecondarySos(TIFF* tif, uint16 s)
 	assert(s<3);
 	assert(sp->sos_end[0].log!=0);
 	assert(sp->sos_end[s].log==0);
-	sp->plane_sample_offset=s-1;
+	sp->plane_sample_offset=(uint8)(s-1);
 	while(sp->sos_end[sp->plane_sample_offset].log==0)
 		sp->plane_sample_offset--;
 	sp->in_buffer_source=sp->sos_end[sp->plane_sample_offset].in_buffer_source;
@@ -1381,7 +1381,8 @@ OJPEGReadHeaderInfoSec(TIFF* tif)
 static int
 OJPEGReadHeaderInfoSecStreamDri(TIFF* tif)
 {
-	/* this could easilly cause trouble in some cases... but no such cases have occured sofar */
+	/* This could easily cause trouble in some cases... but no such cases have
+           occurred so far */
 	static const char module[]="OJPEGReadHeaderInfoSecStreamDri";
 	OJPEGState* sp=(OJPEGState*)tif->tif_data;
 	uint16 m;
@@ -1497,14 +1498,17 @@ OJPEGReadHeaderInfoSecStreamDht(TIFF* tif)
 		nb[sizeof(uint32)+1]=JPEG_MARKER_DHT;
 		nb[sizeof(uint32)+2]=(m>>8);
 		nb[sizeof(uint32)+3]=(m&255);
-		if (OJPEGReadBlock(sp,m-2,&nb[sizeof(uint32)+4])==0)
+		if (OJPEGReadBlock(sp,m-2,&nb[sizeof(uint32)+4])==0) {
+                        _TIFFfree(nb);
 			return(0);
+                }
 		o=nb[sizeof(uint32)+4];
 		if ((o&240)==0)
 		{
 			if (3<o)
 			{
 				TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DHT marker in JPEG data");
+                                _TIFFfree(nb);
 				return(0);
 			}
 			if (sp->dctable[o]!=0)
@@ -1516,12 +1520,14 @@ OJPEGReadHeaderInfoSecStreamDht(TIFF* tif)
 			if ((o&240)!=16)
 			{
 				TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DHT marker in JPEG data");
+                                _TIFFfree(nb);
 				return(0);
 			}
 			o&=15;
 			if (3<o)
 			{
 				TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DHT marker in JPEG data");
+                                _TIFFfree(nb);
 				return(0);
 			}
 			if (sp->actable[o]!=0)
@@ -1774,7 +1780,7 @@ OJPEGReadHeaderInfoSecTablesQTable(TIFF* tif)
 			ob[sizeof(uint32)+3]=67;
 			ob[sizeof(uint32)+4]=m;
 			TIFFSeekFile(tif,sp->qtable_offset[m],SEEK_SET); 
-			p=TIFFReadFile(tif,&ob[sizeof(uint32)+5],64);
+			p=(uint32)TIFFReadFile(tif,&ob[sizeof(uint32)+5],64);
 			if (p!=64)
 				return(0);
 			sp->qtable[m]=ob;
@@ -1817,7 +1823,7 @@ OJPEGReadHeaderInfoSecTablesDcTable(TIFF* tif)
 				}
 			}
 			TIFFSeekFile(tif,sp->dctable_offset[m],SEEK_SET);
-			p=TIFFReadFile(tif,o,16);
+			p=(uint32)TIFFReadFile(tif,o,16);
 			if (p!=16)
 				return(0);
 			q=0;
@@ -1833,12 +1839,12 @@ OJPEGReadHeaderInfoSecTablesDcTable(TIFF* tif)
 			*(uint32*)rb=ra;
 			rb[sizeof(uint32)]=255;
 			rb[sizeof(uint32)+1]=JPEG_MARKER_DHT;
-			rb[sizeof(uint32)+2]=((19+q)>>8);
+			rb[sizeof(uint32)+2]=(uint8)((19+q)>>8);
 			rb[sizeof(uint32)+3]=((19+q)&255);
 			rb[sizeof(uint32)+4]=m;
 			for (n=0; n<16; n++)
 				rb[sizeof(uint32)+5+n]=o[n];
-			p=TIFFReadFile(tif,&(rb[sizeof(uint32)+21]),q);
+			p=(uint32)TIFFReadFile(tif,&(rb[sizeof(uint32)+21]),q);
 			if (p!=q)
 				return(0);
 			sp->dctable[m]=rb;
@@ -1881,7 +1887,7 @@ OJPEGReadHeaderInfoSecTablesAcTable(TIFF* tif)
 				}
 			}
 			TIFFSeekFile(tif,sp->actable_offset[m],SEEK_SET);  
-			p=TIFFReadFile(tif,o,16);
+			p=(uint32)TIFFReadFile(tif,o,16);
 			if (p!=16)
 				return(0);
 			q=0;
@@ -1897,12 +1903,12 @@ OJPEGReadHeaderInfoSecTablesAcTable(TIFF* tif)
 			*(uint32*)rb=ra;
 			rb[sizeof(uint32)]=255;
 			rb[sizeof(uint32)+1]=JPEG_MARKER_DHT;
-			rb[sizeof(uint32)+2]=((19+q)>>8);
+			rb[sizeof(uint32)+2]=(uint8)((19+q)>>8);
 			rb[sizeof(uint32)+3]=((19+q)&255);
 			rb[sizeof(uint32)+4]=(16|m);
 			for (n=0; n<16; n++)
 				rb[sizeof(uint32)+5+n]=o[n];
-			p=TIFFReadFile(tif,&(rb[sizeof(uint32)+21]),q);
+			p=(uint32)TIFFReadFile(tif,&(rb[sizeof(uint32)+21]),q);
 			if (p!=q)
 				return(0);
 			sp->actable[m]=rb;
@@ -1960,6 +1966,7 @@ OJPEGReadBufferFill(OJPEGState* sp)
 				break;
 			case osibsJpegInterchangeFormat:
 				sp->in_buffer_source=osibsStrile;
+                                break;
 			case osibsStrile:
 				if (!_TIFFFillStriles( sp->tif ) 
 				    || sp->tif->tif_dir.td_stripoffset == NULL
@@ -2263,10 +2270,10 @@ OJPEGWriteStreamSof(TIFF* tif, void** mem, uint32* len)
 	/* P */
 	sp->out_buffer[4]=8;
 	/* Y */
-	sp->out_buffer[5]=(sp->sof_y>>8);
+	sp->out_buffer[5]=(uint8)(sp->sof_y>>8);
 	sp->out_buffer[6]=(sp->sof_y&255);
 	/* X */
-	sp->out_buffer[7]=(sp->sof_x>>8);
+	sp->out_buffer[7]=(uint8)(sp->sof_x>>8);
 	sp->out_buffer[8]=(sp->sof_x&255);
 	/* Nf */
 	sp->out_buffer[9]=sp->samples_per_pixel_per_plane;
@@ -2473,6 +2480,10 @@ OJPEGLibjpegJpegSourceMgrSkipInputData(jpeg_decompress_struct* cinfo, long num_b
 	jpeg_encap_unwind(tif);
 }
 
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable : 4702 ) /* unreachable code */
+#endif
 static boolean
 OJPEGLibjpegJpegSourceMgrResyncToRestart(jpeg_decompress_struct* cinfo, int desired)
 {
@@ -2482,6 +2493,9 @@ OJPEGLibjpegJpegSourceMgrResyncToRestart(jpeg_decompress_struct* cinfo, int desi
 	jpeg_encap_unwind(tif);
 	return(0);
 }
+#ifdef _MSC_VER
+#pragma warning( pop ) 
+#endif
 
 static void
 OJPEGLibjpegJpegSourceMgrTermSource(jpeg_decompress_struct* cinfo)
diff --git a/frmts/gtiff/libtiff/tif_open.c b/frmts/gtiff/libtiff/tif_open.c
index 8c88328..5c9036e 100644
--- a/frmts/gtiff/libtiff/tif_open.c
+++ b/frmts/gtiff/libtiff/tif_open.c
@@ -1,4 +1,4 @@
-/* $Id: tif_open.c,v 1.46 2010-12-06 16:54:54 faxguy Exp $ */
+/* $Id: tif_open.c,v 1.47 2016-01-23 21:20:34 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -168,7 +168,7 @@ TIFFClientOpen(
 	 * The following flags may be used to control intrinsic library
 	 * behaviour that may or may not be desirable (usually for
 	 * compatibility with some application that claims to support
-	 * TIFF but only supports some braindead idea of what the
+	 * TIFF but only supports some brain dead idea of what the
 	 * vendor thinks TIFF is):
 	 *
 	 * 'l' use little-endian byte order for creating a file
@@ -198,8 +198,8 @@ TIFFClientOpen(
 	 * The 'L', 'B', and 'H' flags are intended for applications
 	 * that can optimize operations on data by using a particular
 	 * bit order.  By default the library returns data in MSB2LSB
-	 * bit order for compatibiltiy with older versions of this
-	 * library.  Returning data in the bit order of the native cpu
+	 * bit order for compatibility with older versions of this
+	 * library.  Returning data in the bit order of the native CPU
 	 * makes the most sense but also requires applications to check
 	 * the value of the FillOrder tag; something they probably do
 	 * not do right now.
diff --git a/frmts/gtiff/libtiff/tif_packbits.c b/frmts/gtiff/libtiff/tif_packbits.c
index 9e77190..c79c0aa 100644
--- a/frmts/gtiff/libtiff/tif_packbits.c
+++ b/frmts/gtiff/libtiff/tif_packbits.c
@@ -1,4 +1,4 @@
-/* $Id: tif_packbits.c,v 1.22 2012-06-20 05:25:33 fwarmerdam Exp $ */
+/* $Id: tif_packbits.c,v 1.23 2015-11-22 15:31:03 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -38,7 +38,8 @@ PackBitsPreEncode(TIFF* tif, uint16 s)
 {
 	(void) s;
 
-	if (!(tif->tif_data = (uint8*)_TIFFmalloc(sizeof(tmsize_t))))
+        tif->tif_data = (uint8*)_TIFFmalloc(sizeof(tmsize_t));
+	if (tif->tif_data == NULL)
 		return (0);
 	/*
 	 * Calculate the scanline/tile-width size in bytes.
diff --git a/frmts/gtiff/libtiff/tif_pixarlog.c b/frmts/gtiff/libtiff/tif_pixarlog.c
index 044c411..fe25829 100644
--- a/frmts/gtiff/libtiff/tif_pixarlog.c
+++ b/frmts/gtiff/libtiff/tif_pixarlog.c
@@ -1,4 +1,4 @@
-/* $Id: tif_pixarlog.c,v 1.39 2012-12-10 17:27:13 tgl Exp $ */
+/* $Id: tif_pixarlog.c,v 1.43 2015-12-27 20:14:11 erouault Exp $ */
 
 /*
  * Copyright (c) 1996-1997 Sam Leffler
@@ -45,15 +45,15 @@
  * input is assumed to be unsigned linear color values that represent
  * the range 0-1.  In the case of IEEE values, the 0-1 range is assumed to
  * be the normal linear color range, in addition over 1 values are
- * accepted up to a value of about 25.0 to encode "hot" hightlights and such.
+ * accepted up to a value of about 25.0 to encode "hot" highlights and such.
  * The encoding is lossless for 8-bit values, slightly lossy for the
  * other bit depths.  The actual color precision should be better
  * than the human eye can perceive with extra room to allow for
  * error introduced by further image computation.  As with any quantized
  * color format, it is possible to perform image calculations which
  * expose the quantization error. This format should certainly be less 
- * susceptable to such errors than standard 8-bit encodings, but more
- * susceptable than straight 16-bit or 32-bit encodings.
+ * susceptible to such errors than standard 8-bit encodings, but more
+ * susceptible than straight 16-bit or 32-bit encodings.
  *
  * On reading the internal format is converted to the desired output format.
  * The program can request which format it desires by setting the internal
@@ -296,33 +296,35 @@ horizontalAccumulate16(uint16 *wp, int n, int stride, uint16 *op,
 static void
 horizontalAccumulate11(uint16 *wp, int n, int stride, uint16 *op)
 {
-    register unsigned int  cr, cg, cb, ca, mask;
+    register unsigned int cr, cg, cb, ca, mask;
 
     if (n >= stride) {
 	mask = CODE_MASK;
 	if (stride == 3) {
-	    op[0] = cr = wp[0];  op[1] = cg = wp[1];  op[2] = cb = wp[2];
+	    op[0] = wp[0];  op[1] = wp[1];  op[2] = wp[2];
+            cr = wp[0];  cg = wp[1];  cb = wp[2];
 	    n -= 3;
 	    while (n > 0) {
 		wp += 3;
 		op += 3;
 		n -= 3;
-		op[0] = (cr += wp[0]) & mask;
-		op[1] = (cg += wp[1]) & mask;
-		op[2] = (cb += wp[2]) & mask;
+		op[0] = (uint16)((cr += wp[0]) & mask);
+		op[1] = (uint16)((cg += wp[1]) & mask);
+		op[2] = (uint16)((cb += wp[2]) & mask);
 	    }
 	} else if (stride == 4) {
-	    op[0] = cr = wp[0];  op[1] = cg = wp[1];
-	    op[2] = cb = wp[2];  op[3] = ca = wp[3];
+	    op[0] = wp[0];  op[1] = wp[1];
+	    op[2] = wp[2];  op[3] = wp[3];
+            cr = wp[0]; cg = wp[1]; cb = wp[2]; ca = wp[3];
 	    n -= 4;
 	    while (n > 0) {
 		wp += 4;
 		op += 4;
 		n -= 4;
-		op[0] = (cr += wp[0]) & mask;
-		op[1] = (cg += wp[1]) & mask;
-		op[2] = (cb += wp[2]) & mask;
-		op[3] = (ca += wp[3]) & mask;
+		op[0] = (uint16)((cr += wp[0]) & mask);
+		op[1] = (uint16)((cg += wp[1]) & mask);
+		op[2] = (uint16)((cb += wp[2]) & mask);
+		op[3] = (uint16)((ca += wp[3]) & mask);
 	    } 
 	} else {
 	    REPEAT(stride, *op = *wp&mask; wp++; op++)
@@ -556,7 +558,7 @@ PixarLogMakeTables(PixarLogState *sp)
     for (i = 0; i < lt2size; i++)  {
 	if ((i*linstep)*(i*linstep) > ToLinearF[j]*ToLinearF[j+1])
 	    j++;
-	FromLT2[i] = j;
+	FromLT2[i] = (uint16)j;
     }
 
     /*
@@ -568,14 +570,14 @@ PixarLogMakeTables(PixarLogState *sp)
     for (i = 0; i < 16384; i++)  {
 	while ((i/16383.)*(i/16383.) > ToLinearF[j]*ToLinearF[j+1])
 	    j++;
-	From14[i] = j;
+	From14[i] = (uint16)j;
     }
 
     j = 0;
     for (i = 0; i < 256; i++)  {
 	while ((i/255.)*(i/255.) > ToLinearF[j]*ToLinearF[j+1])
 	    j++;
-	From8[i] = j;
+	From8[i] = (uint16)j;
     }
 
     Fltsize = (float)(lt2size/2);
@@ -702,7 +704,7 @@ PixarLogSetupDecode(TIFF* tif)
 	}
 
 	if (inflateInit(&sp->stream) != Z_OK) {
-		TIFFErrorExt(tif->tif_clientdata, module, "%s", sp->stream.msg);
+		TIFFErrorExt(tif->tif_clientdata, module, "%s", sp->stream.msg ? sp->stream.msg : "(null)");
 		return (0);
 	} else {
 		sp->state |= PLSTATE_INIT;
@@ -725,7 +727,7 @@ PixarLogPreDecode(TIFF* tif, uint16 s)
 	assert(sizeof(sp->stream.avail_in)==4);  /* if this assert gets raised,
 	    we need to simplify this code to reflect a ZLib that is likely updated
 	    to deal with 8byte memory sizes, though this code will respond
-	    apropriately even before we simplify it */
+	    appropriately even before we simplify it */
 	sp->stream.avail_in = (uInt) tif->tif_rawcc;
 	if ((tmsize_t)sp->stream.avail_in != tif->tif_rawcc)
 	{
@@ -774,7 +776,7 @@ PixarLogDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
 	assert(sizeof(sp->stream.avail_out)==4);  /* if this assert gets raised,
 	    we need to simplify this code to reflect a ZLib that is likely updated
 	    to deal with 8byte memory sizes, though this code will respond
-	    apropriately even before we simplify it */
+	    appropriately even before we simplify it */
 	sp->stream.avail_out = (uInt) (nsamples * sizeof(uint16));
 	if (sp->stream.avail_out != nsamples * sizeof(uint16))
 	{
@@ -789,14 +791,14 @@ PixarLogDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
 		if (state == Z_DATA_ERROR) {
 			TIFFErrorExt(tif->tif_clientdata, module,
 			    "Decoding error at scanline %lu, %s",
-			    (unsigned long) tif->tif_row, sp->stream.msg);
+			    (unsigned long) tif->tif_row, sp->stream.msg ? sp->stream.msg : "(null)");
 			if (inflateSync(&sp->stream) != Z_OK)
 				return (0);
 			continue;
 		}
 		if (state != Z_OK) {
 			TIFFErrorExt(tif->tif_clientdata, module, "ZLib error: %s",
-			    sp->stream.msg);
+			    sp->stream.msg ? sp->stream.msg : "(null)");
 			return (0);
 		}
 	} while (sp->stream.avail_out > 0);
@@ -898,7 +900,7 @@ PixarLogSetupEncode(TIFF* tif)
 	}
 
 	if (deflateInit(&sp->stream, sp->quality) != Z_OK) {
-		TIFFErrorExt(tif->tif_clientdata, module, "%s", sp->stream.msg);
+		TIFFErrorExt(tif->tif_clientdata, module, "%s", sp->stream.msg ? sp->stream.msg : "(null)");
 		return (0);
 	} else {
 		sp->state |= PLSTATE_INIT;
@@ -921,8 +923,8 @@ PixarLogPreEncode(TIFF* tif, uint16 s)
 	assert(sizeof(sp->stream.avail_out)==4);  /* if this assert gets raised,
 	    we need to simplify this code to reflect a ZLib that is likely updated
 	    to deal with 8byte memory sizes, though this code will respond
-	    apropriately even before we simplify it */
-	sp->stream.avail_out = tif->tif_rawdatasize;
+	    appropriately even before we simplify it */
+	sp->stream.avail_out = (uInt)tif->tif_rawdatasize;
 	if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize)
 	{
 		TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size");
@@ -953,9 +955,9 @@ horizontalDifferenceF(float *ip, int n, int stride, uint16 *wp, uint16 *FromLT2)
 		n -= 3;
 		wp += 3;
 		ip += 3;
-		r1 = (int32) CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1;
-		g1 = (int32) CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1;
-		b1 = (int32) CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1;
+		r1 = (int32) CLAMP(ip[0]); wp[0] = (uint16)((r1-r2) & mask); r2 = r1;
+		g1 = (int32) CLAMP(ip[1]); wp[1] = (uint16)((g1-g2) & mask); g2 = g1;
+		b1 = (int32) CLAMP(ip[2]); wp[2] = (uint16)((b1-b2) & mask); b2 = b1;
 	    }
 	} else if (stride == 4) {
 	    r2 = wp[0] = (uint16) CLAMP(ip[0]);
@@ -967,10 +969,10 @@ horizontalDifferenceF(float *ip, int n, int stride, uint16 *wp, uint16 *FromLT2)
 		n -= 4;
 		wp += 4;
 		ip += 4;
-		r1 = (int32) CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1;
-		g1 = (int32) CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1;
-		b1 = (int32) CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1;
-		a1 = (int32) CLAMP(ip[3]); wp[3] = (a1-a2) & mask; a2 = a1;
+		r1 = (int32) CLAMP(ip[0]); wp[0] = (uint16)((r1-r2) & mask); r2 = r1;
+		g1 = (int32) CLAMP(ip[1]); wp[1] = (uint16)((g1-g2) & mask); g2 = g1;
+		b1 = (int32) CLAMP(ip[2]); wp[2] = (uint16)((b1-b2) & mask); b2 = b1;
+		a1 = (int32) CLAMP(ip[3]); wp[3] = (uint16)((a1-a2) & mask); a2 = a1;
 	    }
 	} else {
 	    ip += n - 1;	/* point to last one */
@@ -1008,9 +1010,9 @@ horizontalDifference16(unsigned short *ip, int n, int stride,
 		n -= 3;
 		wp += 3;
 		ip += 3;
-		r1 = CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1;
-		g1 = CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1;
-		b1 = CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1;
+		r1 = CLAMP(ip[0]); wp[0] = (uint16)((r1-r2) & mask); r2 = r1;
+		g1 = CLAMP(ip[1]); wp[1] = (uint16)((g1-g2) & mask); g2 = g1;
+		b1 = CLAMP(ip[2]); wp[2] = (uint16)((b1-b2) & mask); b2 = b1;
 	    }
 	} else if (stride == 4) {
 	    r2 = wp[0] = CLAMP(ip[0]);  g2 = wp[1] = CLAMP(ip[1]);
@@ -1020,10 +1022,10 @@ horizontalDifference16(unsigned short *ip, int n, int stride,
 		n -= 4;
 		wp += 4;
 		ip += 4;
-		r1 = CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1;
-		g1 = CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1;
-		b1 = CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1;
-		a1 = CLAMP(ip[3]); wp[3] = (a1-a2) & mask; a2 = a1;
+		r1 = CLAMP(ip[0]); wp[0] = (uint16)((r1-r2) & mask); r2 = r1;
+		g1 = CLAMP(ip[1]); wp[1] = (uint16)((g1-g2) & mask); g2 = g1;
+		b1 = CLAMP(ip[2]); wp[2] = (uint16)((b1-b2) & mask); b2 = b1;
+		a1 = CLAMP(ip[3]); wp[3] = (uint16)((a1-a2) & mask); a2 = a1;
 	    }
 	} else {
 	    ip += n - 1;	/* point to last one */
@@ -1059,9 +1061,9 @@ horizontalDifference8(unsigned char *ip, int n, int stride,
 	    n -= 3;
 	    while (n > 0) {
 		n -= 3;
-		r1 = CLAMP(ip[3]); wp[3] = (r1-r2) & mask; r2 = r1;
-		g1 = CLAMP(ip[4]); wp[4] = (g1-g2) & mask; g2 = g1;
-		b1 = CLAMP(ip[5]); wp[5] = (b1-b2) & mask; b2 = b1;
+		r1 = CLAMP(ip[3]); wp[3] = (uint16)((r1-r2) & mask); r2 = r1;
+		g1 = CLAMP(ip[4]); wp[4] = (uint16)((g1-g2) & mask); g2 = g1;
+		b1 = CLAMP(ip[5]); wp[5] = (uint16)((b1-b2) & mask); b2 = b1;
 		wp += 3;
 		ip += 3;
 	    }
@@ -1071,10 +1073,10 @@ horizontalDifference8(unsigned char *ip, int n, int stride,
 	    n -= 4;
 	    while (n > 0) {
 		n -= 4;
-		r1 = CLAMP(ip[4]); wp[4] = (r1-r2) & mask; r2 = r1;
-		g1 = CLAMP(ip[5]); wp[5] = (g1-g2) & mask; g2 = g1;
-		b1 = CLAMP(ip[6]); wp[6] = (b1-b2) & mask; b2 = b1;
-		a1 = CLAMP(ip[7]); wp[7] = (a1-a2) & mask; a2 = a1;
+		r1 = CLAMP(ip[4]); wp[4] = (uint16)((r1-r2) & mask); r2 = r1;
+		g1 = CLAMP(ip[5]); wp[5] = (uint16)((g1-g2) & mask); g2 = g1;
+		b1 = CLAMP(ip[6]); wp[6] = (uint16)((b1-b2) & mask); b2 = b1;
+		a1 = CLAMP(ip[7]); wp[7] = (uint16)((a1-a2) & mask); a2 = a1;
 		wp += 4;
 		ip += 4;
 	    }
@@ -1161,7 +1163,7 @@ PixarLogEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 	assert(sizeof(sp->stream.avail_in)==4);  /* if this assert gets raised,
 	    we need to simplify this code to reflect a ZLib that is likely updated
 	    to deal with 8byte memory sizes, though this code will respond
-	    apropriately even before we simplify it */
+	    appropriately even before we simplify it */
 	sp->stream.avail_in = (uInt) (n * sizeof(uint16));
 	if ((sp->stream.avail_in / sizeof(uint16)) != (uInt) n)
 	{
@@ -1173,7 +1175,7 @@ PixarLogEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 	do {
 		if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) {
 			TIFFErrorExt(tif->tif_clientdata, module, "Encoder error: %s",
-			    sp->stream.msg);
+			    sp->stream.msg ? sp->stream.msg : "(null)");
 			return (0);
 		}
 		if (sp->stream.avail_out == 0) {
@@ -1215,7 +1217,7 @@ PixarLogPostEncode(TIFF* tif)
 		    break;
 		default:
 			TIFFErrorExt(tif->tif_clientdata, module, "ZLib error: %s",
-			sp->stream.msg);
+			sp->stream.msg ? sp->stream.msg : "(null)");
 		    return (0);
 		}
 	} while (state != Z_STREAM_END);
@@ -1227,7 +1229,7 @@ PixarLogClose(TIFF* tif)
 {
 	TIFFDirectory *td = &tif->tif_dir;
 
-	/* In a really sneaky (and really incorrect, and untruthfull, and
+	/* In a really sneaky (and really incorrect, and untruthful, and
 	 * troublesome, and error-prone) maneuver that completely goes against
 	 * the spirit of TIFF, and breaks TIFF, on close, we covertly
 	 * modify both bitspersample and sampleformat in the directory to
@@ -1285,7 +1287,7 @@ PixarLogVSetField(TIFF* tif, uint32 tag, va_list ap)
 			if (deflateParams(&sp->stream,
 			    sp->quality, Z_DEFAULT_STRATEGY) != Z_OK) {
 				TIFFErrorExt(tif->tif_clientdata, module, "ZLib error: %s",
-					sp->stream.msg);
+					sp->stream.msg ? sp->stream.msg : "(null)");
 				return (0);
 			}
 		}
diff --git a/frmts/gtiff/libtiff/tif_predict.c b/frmts/gtiff/libtiff/tif_predict.c
index f93c664..556b1c4 100644
--- a/frmts/gtiff/libtiff/tif_predict.c
+++ b/frmts/gtiff/libtiff/tif_predict.c
@@ -1,4 +1,4 @@
-/* $Id: tif_predict.c,v 1.32 2010-03-10 18:56:49 bfriesen Exp $ */
+/* $Id: tif_predict.c,v 1.37 2016-01-23 21:20:34 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -42,6 +42,8 @@ static void swabHorAcc32(TIFF* tif, uint8* cp0, tmsize_t cc);
 static void horDiff8(TIFF* tif, uint8* cp0, tmsize_t cc);
 static void horDiff16(TIFF* tif, uint8* cp0, tmsize_t cc);
 static void horDiff32(TIFF* tif, uint8* cp0, tmsize_t cc);
+static void swabHorDiff16(TIFF* tif, uint8* cp0, tmsize_t cc);
+static void swabHorDiff32(TIFF* tif, uint8* cp0, tmsize_t cc);
 static void fpAcc(TIFF* tif, uint8* cp0, tmsize_t cc);
 static void fpDiff(TIFF* tif, uint8* cp0, tmsize_t cc);
 static int PredictorDecodeRow(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s);
@@ -207,7 +209,24 @@ PredictorSetupEncode(TIFF* tif)
                     sp->encodetile = tif->tif_encodetile;
                     tif->tif_encodetile = PredictorEncodeTile;
                 }
-	}
+
+                /*
+                 * If the data is horizontally differenced 16-bit data that
+                 * requires byte-swapping, then it must be byte swapped after
+                 * the differentiation step.  We do this with a special-purpose
+                 * routine and override the normal post decoding logic that
+                 * the library setup when the directory was read.
+                 */
+                if (tif->tif_flags & TIFF_SWAB) {
+                    if (sp->encodepfunc == horDiff16) {
+                            sp->encodepfunc = swabHorDiff16;
+                            tif->tif_postdecode = _TIFFNoPostDecode;
+                    } else if (sp->encodepfunc == horDiff32) {
+                            sp->encodepfunc = swabHorDiff32;
+                            tif->tif_postdecode = _TIFFNoPostDecode;
+                    }
+                }
+        }
 
 	else if (sp->predictor == 3) {
 		sp->encodepfunc = fpDiff;
@@ -239,12 +258,18 @@ PredictorSetupEncode(TIFF* tif)
     case 0:  ;			\
     }
 
+/* Remarks related to C standard compliance in all below functions : */
+/* - to avoid any undefined behaviour, we only operate on unsigned types */
+/*   since the behaviour of "overflows" is defined (wrap over) */
+/* - when storing into the byte stream, we explicitly mask with 0xff so */
+/*   as to make icc -check=conversions happy (not necessary by the standard) */
+
 static void
 horAcc8(TIFF* tif, uint8* cp0, tmsize_t cc)
 {
 	tmsize_t stride = PredictorState(tif)->stride;
 
-	char* cp = (char*) cp0;
+	unsigned char* cp = (unsigned char*) cp0;
 	assert((cc%stride)==0);
 	if (cc > stride) {
 		/*
@@ -257,9 +282,9 @@ horAcc8(TIFF* tif, uint8* cp0, tmsize_t cc)
 			cc -= 3;
 			cp += 3;
 			while (cc>0) {
-				cp[0] = (char) (cr += cp[0]);
-				cp[1] = (char) (cg += cp[1]);
-				cp[2] = (char) (cb += cp[2]);
+				cp[0] = (unsigned char) ((cr += cp[0]) & 0xff);
+				cp[1] = (unsigned char) ((cg += cp[1]) & 0xff);
+				cp[2] = (unsigned char) ((cb += cp[2]) & 0xff);
 				cc -= 3;
 				cp += 3;
 			}
@@ -271,10 +296,10 @@ horAcc8(TIFF* tif, uint8* cp0, tmsize_t cc)
 			cc -= 4;
 			cp += 4;
 			while (cc>0) {
-				cp[0] = (char) (cr += cp[0]);
-				cp[1] = (char) (cg += cp[1]);
-				cp[2] = (char) (cb += cp[2]);
-				cp[3] = (char) (ca += cp[3]);
+				cp[0] = (unsigned char) ((cr += cp[0]) & 0xff);
+				cp[1] = (unsigned char) ((cg += cp[1]) & 0xff);
+				cp[2] = (unsigned char) ((cb += cp[2]) & 0xff);
+				cp[3] = (unsigned char) ((ca += cp[3]) & 0xff);
 				cc -= 4;
 				cp += 4;
 			}
@@ -282,7 +307,7 @@ horAcc8(TIFF* tif, uint8* cp0, tmsize_t cc)
 			cc -= stride;
 			do {
 				REPEAT4(stride, cp[stride] =
-					(char) (cp[stride] + *cp); cp++)
+					(unsigned char) ((cp[stride] + *cp) & 0xff); cp++)
 				cc -= stride;
 			} while (cc>0);
 		}
@@ -292,20 +317,11 @@ horAcc8(TIFF* tif, uint8* cp0, tmsize_t cc)
 static void
 swabHorAcc16(TIFF* tif, uint8* cp0, tmsize_t cc)
 {
-	tmsize_t stride = PredictorState(tif)->stride;
 	uint16* wp = (uint16*) cp0;
 	tmsize_t wc = cc / 2;
 
-	assert((cc%(2*stride))==0);
-
-	if (wc > stride) {
-		TIFFSwabArrayOfShort(wp, wc);
-		wc -= stride;
-		do {
-			REPEAT4(stride, wp[stride] += wp[0]; wp++)
-			wc -= stride;
-		} while (wc > 0);
-	}
+        TIFFSwabArrayOfShort(wp, wc);
+        horAcc16(tif, cp0, cc);
 }
 
 static void
@@ -320,7 +336,7 @@ horAcc16(TIFF* tif, uint8* cp0, tmsize_t cc)
 	if (wc > stride) {
 		wc -= stride;
 		do {
-			REPEAT4(stride, wp[stride] += wp[0]; wp++)
+			REPEAT4(stride, wp[stride] = (uint16)(((unsigned int)wp[stride] + (unsigned int)wp[0]) & 0xffff); wp++)
 			wc -= stride;
 		} while (wc > 0);
 	}
@@ -329,20 +345,11 @@ horAcc16(TIFF* tif, uint8* cp0, tmsize_t cc)
 static void
 swabHorAcc32(TIFF* tif, uint8* cp0, tmsize_t cc)
 {
-	tmsize_t stride = PredictorState(tif)->stride;
 	uint32* wp = (uint32*) cp0;
 	tmsize_t wc = cc / 4;
 
-	assert((cc%(4*stride))==0);
-
-	if (wc > stride) {
-		TIFFSwabArrayOfLong(wp, wc);
-		wc -= stride;
-		do {
-			REPEAT4(stride, wp[stride] += wp[0]; wp++)
-			wc -= stride;
-		} while (wc > 0);
-	}
+        TIFFSwabArrayOfLong(wp, wc);
+	horAcc32(tif, cp0, cc);
 }
 
 static void
@@ -382,7 +389,8 @@ fpAcc(TIFF* tif, uint8* cp0, tmsize_t cc)
 		return;
 
 	while (count > stride) {
-		REPEAT4(stride, cp[stride] += cp[0]; cp++)
+		REPEAT4(stride, cp[stride] =
+                        (unsigned char) ((cp[stride] + cp[0]) & 0xff); cp++)
 		count -= stride;
 	}
 
@@ -456,7 +464,7 @@ horDiff8(TIFF* tif, uint8* cp0, tmsize_t cc)
 {
 	TIFFPredictorState* sp = PredictorState(tif);
 	tmsize_t stride = sp->stride;
-	char* cp = (char*) cp0;
+	unsigned char* cp = (unsigned char*) cp0;
 
 	assert((cc%stride)==0);
 
@@ -466,33 +474,33 @@ horDiff8(TIFF* tif, uint8* cp0, tmsize_t cc)
 		 * Pipeline the most common cases.
 		 */
 		if (stride == 3) {
-			int r1, g1, b1;
-			int r2 = cp[0];
-			int g2 = cp[1];
-			int b2 = cp[2];
+			unsigned int r1, g1, b1;
+			unsigned int r2 = cp[0];
+			unsigned int g2 = cp[1];
+			unsigned  int b2 = cp[2];
 			do {
-				r1 = cp[3]; cp[3] = r1-r2; r2 = r1;
-				g1 = cp[4]; cp[4] = g1-g2; g2 = g1;
-				b1 = cp[5]; cp[5] = b1-b2; b2 = b1;
+				r1 = cp[3]; cp[3] = (unsigned char)((r1-r2)&0xff); r2 = r1;
+				g1 = cp[4]; cp[4] = (unsigned char)((g1-g2)&0xff); g2 = g1;
+				b1 = cp[5]; cp[5] = (unsigned char)((b1-b2)&0xff); b2 = b1;
 				cp += 3;
 			} while ((cc -= 3) > 0);
 		} else if (stride == 4) {
-			int r1, g1, b1, a1;
-			int r2 = cp[0];
-			int g2 = cp[1];
-			int b2 = cp[2];
-			int a2 = cp[3];
+			unsigned int r1, g1, b1, a1;
+			unsigned int r2 = cp[0];
+			unsigned int g2 = cp[1];
+			unsigned int b2 = cp[2];
+			unsigned int a2 = cp[3];
 			do {
-				r1 = cp[4]; cp[4] = r1-r2; r2 = r1;
-				g1 = cp[5]; cp[5] = g1-g2; g2 = g1;
-				b1 = cp[6]; cp[6] = b1-b2; b2 = b1;
-				a1 = cp[7]; cp[7] = a1-a2; a2 = a1;
+				r1 = cp[4]; cp[4] = (unsigned char)((r1-r2)&0xff); r2 = r1;
+				g1 = cp[5]; cp[5] = (unsigned char)((g1-g2)&0xff); g2 = g1;
+				b1 = cp[6]; cp[6] = (unsigned char)((b1-b2)&0xff); b2 = b1;
+				a1 = cp[7]; cp[7] = (unsigned char)((a1-a2)&0xff); a2 = a1;
 				cp += 4;
 			} while ((cc -= 4) > 0);
 		} else {
 			cp += cc - 1;
 			do {
-				REPEAT4(stride, cp[stride] -= cp[0]; cp--)
+				REPEAT4(stride, cp[stride] = (unsigned char)((cp[stride] - cp[0])&0xff); cp--)
 			} while ((cc -= stride) > 0);
 		}
 	}
@@ -503,7 +511,7 @@ horDiff16(TIFF* tif, uint8* cp0, tmsize_t cc)
 {
 	TIFFPredictorState* sp = PredictorState(tif);
 	tmsize_t stride = sp->stride;
-	int16 *wp = (int16*) cp0;
+	uint16 *wp = (uint16*) cp0;
 	tmsize_t wc = cc/2;
 
 	assert((cc%(2*stride))==0);
@@ -512,18 +520,29 @@ horDiff16(TIFF* tif, uint8* cp0, tmsize_t cc)
 		wc -= stride;
 		wp += wc - 1;
 		do {
-			REPEAT4(stride, wp[stride] -= wp[0]; wp--)
+			REPEAT4(stride, wp[stride] = (uint16)(((unsigned int)wp[stride] - (unsigned int)wp[0]) & 0xffff); wp--)
 			wc -= stride;
 		} while (wc > 0);
 	}
 }
 
 static void
+swabHorDiff16(TIFF* tif, uint8* cp0, tmsize_t cc)
+{
+    uint16* wp = (uint16*) cp0;
+    tmsize_t wc = cc / 2;
+
+    horDiff16(tif, cp0, cc);
+
+    TIFFSwabArrayOfShort(wp, wc);
+}
+
+static void
 horDiff32(TIFF* tif, uint8* cp0, tmsize_t cc)
 {
 	TIFFPredictorState* sp = PredictorState(tif);
 	tmsize_t stride = sp->stride;
-	int32 *wp = (int32*) cp0;
+	uint32 *wp = (uint32*) cp0;
 	tmsize_t wc = cc/4;
 
 	assert((cc%(4*stride))==0);
@@ -538,6 +557,17 @@ horDiff32(TIFF* tif, uint8* cp0, tmsize_t cc)
 	}
 }
 
+static void
+swabHorDiff32(TIFF* tif, uint8* cp0, tmsize_t cc)
+{
+    uint32* wp = (uint32*) cp0;
+    tmsize_t wc = cc / 4;
+
+    horDiff32(tif, cp0, cc);
+
+    TIFFSwabArrayOfLong(wp, wc);
+}
+
 /*
  * Floating point predictor differencing routine.
  */
@@ -573,7 +603,7 @@ fpDiff(TIFF* tif, uint8* cp0, tmsize_t cc)
 	cp = (uint8 *) cp0;
 	cp += cc - stride - 1;
 	for (count = cc; count > stride; count -= stride)
-		REPEAT4(stride, cp[stride] -= cp[0]; cp--)
+		REPEAT4(stride, cp[stride] = (unsigned char)((cp[stride] - cp[0])&0xff); cp--)
 }
 
 static int
@@ -670,7 +700,7 @@ PredictorVGetField(TIFF* tif, uint32 tag, va_list ap)
 
 	switch (tag) {
 	case TIFFTAG_PREDICTOR:
-		*va_arg(ap, uint16*) = sp->predictor;
+		*va_arg(ap, uint16*) = (uint16)sp->predictor;
 		break;
 	default:
 		return (*sp->vgetparent)(tif, tag, ap);
diff --git a/frmts/gtiff/libtiff/tif_print.c b/frmts/gtiff/libtiff/tif_print.c
index 9e27ae2..186f2ee 100644
--- a/frmts/gtiff/libtiff/tif_print.c
+++ b/frmts/gtiff/libtiff/tif_print.c
@@ -1,4 +1,4 @@
-/* $Id: tif_print.c,v 1.61 2012-12-12 22:50:18 tgl Exp $ */
+/* $Id: tif_print.c,v 1.64 2015-12-06 22:19:56 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -35,9 +35,9 @@
 #include <ctype.h>
 
 static void
-_TIFFprintAsciiBounded(FILE* fd, const char* cp, int max_chars);
+_TIFFprintAsciiBounded(FILE* fd, const char* cp, size_t max_chars);
 
-static const char *photoNames[] = {
+static const char * const photoNames[] = {
     "min-is-white",				/* PHOTOMETRIC_MINISWHITE */
     "min-is-black",				/* PHOTOMETRIC_MINISBLACK */
     "RGB color",				/* PHOTOMETRIC_RGB */
@@ -52,7 +52,7 @@ static const char *photoNames[] = {
 };
 #define	NPHOTONAMES	(sizeof (photoNames) / sizeof (photoNames[0]))
 
-static const char *orientNames[] = {
+static const char * const orientNames[] = {
     "0 (0x0)",
     "row 0 top, col 0 lhs",			/* ORIENTATION_TOPLEFT */
     "row 0 top, col 0 rhs",			/* ORIENTATION_TOPRIGHT */
@@ -237,7 +237,6 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
 {
 	TIFFDirectory *td = &tif->tif_dir;
 	char *sep;
-	uint16 i;
 	long l, n;
 
 #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
@@ -365,6 +364,7 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
 		}
 	}
 	if (TIFFFieldSet(tif,FIELD_EXTRASAMPLES) && td->td_extrasamples) {
+		uint16 i;
 		fprintf(fd, "  Extra Samples: %u<", td->td_extrasamples);
 		sep = "";
 		for (i = 0; i < td->td_extrasamples; i++) {
@@ -389,13 +389,14 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
 	}
 	if (TIFFFieldSet(tif,FIELD_INKNAMES)) {
 		char* cp;
+		uint16 i;
 		fprintf(fd, "  Ink Names: ");
 		i = td->td_samplesperpixel;
 		sep = "";
 		for (cp = td->td_inknames; 
 		     i > 0 && cp < td->td_inknames + td->td_inknameslen; 
 		     cp = strchr(cp,'\0')+1, i--) {
-			int max_chars = 
+			size_t max_chars = 
 				td->td_inknameslen - (cp - td->td_inknames);
 			fputs(sep, fd);
 			_TIFFprintAsciiBounded(fd, cp, max_chars);
@@ -481,6 +482,7 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
 	if (TIFFFieldSet(tif,FIELD_MAXSAMPLEVALUE))
 		fprintf(fd, "  Max Sample Value: %u\n", td->td_maxsamplevalue);
 	if (TIFFFieldSet(tif,FIELD_SMINSAMPLEVALUE)) {
+		int i;
 		int count = (tif->tif_flags & TIFF_PERSAMPLE) ? td->td_samplesperpixel : 1;
 		fprintf(fd, "  SMin Sample Value:");
 		for (i = 0; i < count; ++i)
@@ -488,6 +490,7 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
 		fprintf(fd, "\n");
 	}
 	if (TIFFFieldSet(tif,FIELD_SMAXSAMPLEVALUE)) {
+		int i;
 		int count = (tif->tif_flags & TIFF_PERSAMPLE) ? td->td_samplesperpixel : 1;
 		fprintf(fd, "  SMax Sample Value:");
 		for (i = 0; i < count; ++i)
@@ -527,6 +530,7 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
 			fprintf(fd, "(present)\n");
 	}
 	if (TIFFFieldSet(tif,FIELD_REFBLACKWHITE)) {
+		int i;
 		fprintf(fd, "  Reference Black/White:\n");
 		for (i = 0; i < 3; i++)
 		fprintf(fd, "    %2d: %5g %5g\n", i,
@@ -539,6 +543,7 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
 			fprintf(fd, "\n");
 			n = 1L<<td->td_bitspersample;
 			for (l = 0; l < n; l++) {
+				uint16 i;
 				fprintf(fd, "    %2lu: %5u",
 				    l, td->td_transferfunction[0][l]);
 				for (i = 1; i < td->td_samplesperpixel; i++)
@@ -550,6 +555,7 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
 			fprintf(fd, "(present)\n");
 	}
 	if (TIFFFieldSet(tif, FIELD_SUBIFD) && (td->td_subifd)) {
+		uint16 i;
 		fprintf(fd, "  SubIFD Offsets:");
 		for (i = 0; i < td->td_nsubifd; i++)
 #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
@@ -679,7 +685,7 @@ _TIFFprintAscii(FILE* fd, const char* cp)
 }
 
 static void
-_TIFFprintAsciiBounded(FILE* fd, const char* cp, int max_chars)
+_TIFFprintAsciiBounded(FILE* fd, const char* cp, size_t max_chars)
 {
 	for (; max_chars > 0 && *cp != '\0'; cp++, max_chars--) {
 		const char* tp;
diff --git a/frmts/gtiff/libtiff/tif_read.c b/frmts/gtiff/libtiff/tif_read.c
index b009519..9d67bf2 100644
--- a/frmts/gtiff/libtiff/tif_read.c
+++ b/frmts/gtiff/libtiff/tif_read.c
@@ -1,4 +1,4 @@
-/* $Id: tif_read.c,v 1.44 2014-12-23 10:15:35 erouault Exp $ */
+/* $Id: tif_read.c,v 1.47 2016-01-03 10:01:25 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -343,7 +343,7 @@ TIFFReadEncodedStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size)
 		rowsperstrip=td->td_imagelength;
 	stripsperplane=((td->td_imagelength+rowsperstrip-1)/rowsperstrip);
 	stripinplane=(strip%stripsperplane);
-	plane=(strip/stripsperplane);
+	plane=(uint16)(strip/stripsperplane);
 	rows=td->td_imagelength-stripinplane*rowsperstrip;
 	if (rows>rowsperstrip)
 		rows=rowsperstrip;
@@ -492,9 +492,9 @@ TIFFFillStrip(TIFF* tif, uint32 strip)
 	static const char module[] = "TIFFFillStrip";
 	TIFFDirectory *td = &tif->tif_dir;
 
-    if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
-        return 0;
-        
+        if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
+            return 0;
+
 	if ((tif->tif_flags&TIFF_NOREADRAW)==0)
 	{
 		uint64 bytecount = td->td_stripbytecount[strip];
@@ -795,9 +795,9 @@ TIFFFillTile(TIFF* tif, uint32 tile)
 	static const char module[] = "TIFFFillTile";
 	TIFFDirectory *td = &tif->tif_dir;
 
-    if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
-        return 0;
-        
+        if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
+            return 0;
+
 	if ((tif->tif_flags&TIFF_NOREADRAW)==0)
 	{
 		uint64 bytecount = td->td_stripbytecount[tile];
@@ -957,8 +957,8 @@ TIFFStartStrip(TIFF* tif, uint32 strip)
 {
 	TIFFDirectory *td = &tif->tif_dir;
 
-    if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
-        return 0;
+        if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
+            return 0;
 
 	if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
 		if (!(*tif->tif_setupdecode)(tif))
@@ -990,10 +990,12 @@ TIFFStartStrip(TIFF* tif, uint32 strip)
 static int
 TIFFStartTile(TIFF* tif, uint32 tile)
 {
+        static const char module[] = "TIFFStartTile";
 	TIFFDirectory *td = &tif->tif_dir;
+        uint32 howmany32;
 
-    if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
-        return 0;
+        if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
+                return 0;
 
 	if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
 		if (!(*tif->tif_setupdecode)(tif))
@@ -1001,12 +1003,18 @@ TIFFStartTile(TIFF* tif, uint32 tile)
 		tif->tif_flags |= TIFF_CODERSETUP;
 	}
 	tif->tif_curtile = tile;
-	tif->tif_row =
-	    (tile % TIFFhowmany_32(td->td_imagewidth, td->td_tilewidth)) *
-		td->td_tilelength;
-	tif->tif_col =
-	    (tile % TIFFhowmany_32(td->td_imagelength, td->td_tilelength)) *
-		td->td_tilewidth;
+        howmany32=TIFFhowmany_32(td->td_imagewidth, td->td_tilewidth);
+        if (howmany32 == 0) {
+                 TIFFErrorExt(tif->tif_clientdata,module,"Zero tiles");
+                return 0;
+        }
+	tif->tif_row = (tile % howmany32) * td->td_tilelength;
+        howmany32=TIFFhowmany_32(td->td_imagelength, td->td_tilelength);
+        if (howmany32 == 0) {
+                TIFFErrorExt(tif->tif_clientdata,module,"Zero tiles");
+                return 0;
+        }
+	tif->tif_col = (tile % howmany32) * td->td_tilewidth;
         tif->tif_flags &= ~TIFF_BUF4WRITE;
 	if (tif->tif_flags&TIFF_NOREADRAW)
 	{
diff --git a/frmts/gtiff/libtiff/tif_strip.c b/frmts/gtiff/libtiff/tif_strip.c
index 568e489..6cac71d 100644
--- a/frmts/gtiff/libtiff/tif_strip.c
+++ b/frmts/gtiff/libtiff/tif_strip.c
@@ -1,4 +1,4 @@
-/* $Id: tif_strip.c,v 1.35 2012-06-06 05:33:55 fwarmerdam Exp $ */
+/* $Id: tif_strip.c,v 1.36 2015-06-07 22:35:40 bfriesen Exp $ */
 
 /*
  * Copyright (c) 1991-1997 Sam Leffler
@@ -317,7 +317,14 @@ TIFFScanlineSize64(TIFF* tif)
 		}
 	}
 	else
+        {
 		scanline_size=TIFFhowmany_64(_TIFFMultiply64(tif,td->td_imagewidth,td->td_bitspersample,module),8);
+        }
+        if (scanline_size == 0)
+        {
+                TIFFErrorExt(tif->tif_clientdata,module,"Computed scanline size is zero");
+                return 0;
+        }
 	return(scanline_size);
 }
 tmsize_t
@@ -328,8 +335,7 @@ TIFFScanlineSize(TIFF* tif)
 	tmsize_t n;
 	m=TIFFScanlineSize64(tif);
 	n=(tmsize_t)m;
-	if ((uint64)n!=m)
-	{
+	if ((uint64)n!=m) {
 		TIFFErrorExt(tif->tif_clientdata,module,"Integer arithmetic overflow");
 		n=0;
 	}
diff --git a/frmts/gtiff/libtiff/tif_tile.c b/frmts/gtiff/libtiff/tif_tile.c
index 0ff7e85..388e168 100644
--- a/frmts/gtiff/libtiff/tif_tile.c
+++ b/frmts/gtiff/libtiff/tif_tile.c
@@ -1,4 +1,4 @@
-/* $Id: tif_tile.c,v 1.23 2012-06-06 05:33:55 fwarmerdam Exp $ */
+/* $Id: tif_tile.c,v 1.24 2015-06-07 22:35:40 bfriesen Exp $ */
 
 /*
  * Copyright (c) 1991-1997 Sam Leffler
@@ -143,17 +143,40 @@ TIFFNumberOfTiles(TIFF* tif)
 uint64
 TIFFTileRowSize64(TIFF* tif)
 {
+        static const char module[] = "TIFFTileRowSize64";
 	TIFFDirectory *td = &tif->tif_dir;
 	uint64 rowsize;
+	uint64 tilerowsize;
 
-	if (td->td_tilelength == 0 || td->td_tilewidth == 0)
+	if (td->td_tilelength == 0)
+        {
+                TIFFErrorExt(tif->tif_clientdata,module,"Tile length is zero");
+                return 0;
+        }
+        if (td->td_tilewidth == 0)
+        {
+                TIFFErrorExt(tif->tif_clientdata,module,"Tile width is zero");
 		return (0);
+        }
 	rowsize = _TIFFMultiply64(tif, td->td_bitspersample, td->td_tilewidth,
 	    "TIFFTileRowSize");
 	if (td->td_planarconfig == PLANARCONFIG_CONTIG)
+        {
+                if (td->td_samplesperpixel == 0)
+                {
+                        TIFFErrorExt(tif->tif_clientdata,module,"Samples per pixel is zero");
+                        return 0;
+                }
 		rowsize = _TIFFMultiply64(tif, rowsize, td->td_samplesperpixel,
 		    "TIFFTileRowSize");
-	return (TIFFhowmany8_64(rowsize));
+        }
+        tilerowsize=TIFFhowmany8_64(rowsize);
+        if (tilerowsize == 0)
+        {
+                TIFFErrorExt(tif->tif_clientdata,module,"Computed tile row size is zero");
+                return 0;
+        }
+	return (tilerowsize);
 }
 tmsize_t
 TIFFTileRowSize(TIFF* tif)
diff --git a/frmts/gtiff/libtiff/tif_vsi.c b/frmts/gtiff/libtiff/tif_vsi.c
index 459502e..7a34f78 100644
--- a/frmts/gtiff/libtiff/tif_vsi.c
+++ b/frmts/gtiff/libtiff/tif_vsi.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tif_vsi.c 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: tif_vsi.c 32883 2016-01-09 18:24:40Z rouault $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Implement system hook functions for libtiff on top of CPL/VSI,
@@ -35,6 +35,8 @@
 #include "tiffiop.h"
 #include "cpl_vsi.h"
 
+CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused) {}
+
 static tsize_t
 _tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size)
 {
@@ -69,10 +71,10 @@ _tiffSizeProc(thandle_t fd)
     toff_t        file_size;
 
     old_off = VSIFTellL( (VSILFILE *) fd );
-    VSIFSeekL( (VSILFILE *) fd, 0, SEEK_END );
+    CPL_IGNORE_RET_VAL_INT(VSIFSeekL( (VSILFILE *) fd, 0, SEEK_END ));
 
     file_size = (toff_t) VSIFTellL( (VSILFILE *) fd );
-    VSIFSeekL( (VSILFILE *) fd, old_off, SEEK_SET );
+    CPL_IGNORE_RET_VAL_INT(VSIFSeekL( (VSILFILE *) fd, old_off, SEEK_SET ));
 
     return file_size;
 }
@@ -107,12 +109,12 @@ TIFFOpen(const char* name, const char* mode)
 {
 	static const char module[] = "TIFFOpen";
 	int           i, a_out;
-        char          access[32];
+        char          szAccess[32];
         VSILFILE          *fp;
         TIFF          *tif;
 
         a_out = 0;
-        access[0] = '\0';
+        szAccess[0] = '\0';
         for( i = 0; mode[i] != '\0'; i++ )
         {
             if( mode[i] == 'r'
@@ -120,14 +122,14 @@ TIFFOpen(const char* name, const char* mode)
                 || mode[i] == '+'
                 || mode[i] == 'a' )
             {
-                access[a_out++] = mode[i];
-                access[a_out] = '\0';
+                szAccess[a_out++] = mode[i];
+                szAccess[a_out] = '\0';
             }
         }
 
-        strcat( access, "b" );
+        strcat( szAccess, "b" );
 
-        fp = VSIFOpenL( name, access );
+        fp = VSIFOpenL( name, szAccess );
 	if (fp == NULL) {
             if( errno >= 0 )
                 TIFFError(module,"%s: %s", name, VSIStrerror( errno ) );
@@ -145,7 +147,7 @@ TIFFOpen(const char* name, const char* mode)
         if( tif != NULL )
             tif->tif_fd = 0;
         else
-            VSIFCloseL( fp );
+            CPL_IGNORE_RET_VAL_INT(VSIFCloseL( fp ));
         
 	return tif;
 }
diff --git a/frmts/gtiff/libtiff/tif_write.c b/frmts/gtiff/libtiff/tif_write.c
index cb610fc..77114fd 100644
--- a/frmts/gtiff/libtiff/tif_write.c
+++ b/frmts/gtiff/libtiff/tif_write.c
@@ -1,4 +1,4 @@
-/* $Id: tif_write.c,v 1.38 2013-01-18 21:57:12 fwarmerdam Exp $ */
+/* $Id: tif_write.c,v 1.43 2015-12-12 18:04:26 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -115,6 +115,10 @@ TIFFWriteScanline(TIFF* tif, void* buf, uint32 row, uint16 sample)
 		if (strip >= td->td_stripsperimage && imagegrew)
 			td->td_stripsperimage =
 			    TIFFhowmany_32(td->td_imagelength,td->td_rowsperstrip);
+                if (td->td_stripsperimage == 0) {
+                        TIFFErrorExt(tif->tif_clientdata, module, "Zero strips per image");
+                        return (-1);
+                }
 		tif->tif_row =
 		    (strip % td->td_stripsperimage) * td->td_rowsperstrip;
 		if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
@@ -220,6 +224,11 @@ TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc)
         tif->tif_flags |= TIFF_BUF4WRITE;
 	tif->tif_curstrip = strip;
 
+        if (td->td_stripsperimage == 0) {
+                TIFFErrorExt(tif->tif_clientdata, module, "Zero strips per image");
+                return ((tmsize_t) -1);
+        }
+
 	tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
 	if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
 		if (!(*tif->tif_setupencode)(tif))
@@ -257,7 +266,7 @@ TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc)
 	tif->tif_postdecode( tif, (uint8*) data, cc );
 
 	if (!(*tif->tif_encodestrip)(tif, (uint8*) data, cc, sample))
-		return (0);
+		return ((tmsize_t) -1);
 	if (!(*tif->tif_postencode)(tif))
 		return ((tmsize_t) -1);
 	if (!isFillOrder(tif, td->td_fillorder) &&
@@ -311,6 +320,10 @@ TIFFWriteRawStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc)
 			return ((tmsize_t) -1);
 	}
 	tif->tif_curstrip = strip;
+        if (td->td_stripsperimage == 0) {
+                TIFFErrorExt(tif->tif_clientdata, module,"Zero strips per image");
+                return ((tmsize_t) -1);
+        }
 	tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
 	return (TIFFAppendToStrip(tif, strip, (uint8*) data, cc) ?
 	    cc : (tmsize_t) -1);
@@ -353,6 +366,7 @@ TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc)
 	static const char module[] = "TIFFWriteEncodedTile";
 	TIFFDirectory *td;
 	uint16 sample;
+        uint32 howmany32;
 
 	if (!WRITECHECKTILES(tif, module))
 		return ((tmsize_t)(-1));
@@ -398,10 +412,18 @@ TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc)
 	 * Compute tiles per row & per column to compute
 	 * current row and column
 	 */
-	tif->tif_row = (tile % TIFFhowmany_32(td->td_imagelength, td->td_tilelength))
-		* td->td_tilelength;
-	tif->tif_col = (tile % TIFFhowmany_32(td->td_imagewidth, td->td_tilewidth))
-		* td->td_tilewidth;
+        howmany32=TIFFhowmany_32(td->td_imagelength, td->td_tilelength);
+        if (howmany32 == 0) {
+                 TIFFErrorExt(tif->tif_clientdata,module,"Zero tiles");
+                return ((tmsize_t)(-1));
+        }
+	tif->tif_row = (tile % howmany32) * td->td_tilelength;
+        howmany32=TIFFhowmany_32(td->td_imagewidth, td->td_tilewidth);
+        if (howmany32 == 0) {
+                 TIFFErrorExt(tif->tif_clientdata,module,"Zero tiles");
+                return ((tmsize_t)(-1));
+        }
+	tif->tif_col = (tile % howmany32) * td->td_tilewidth;
 
 	if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
 		if (!(*tif->tif_setupencode)(tif))
@@ -424,7 +446,7 @@ TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc)
 	tif->tif_postdecode( tif, (uint8*) data, cc );
 
 	if (!(*tif->tif_encodetile)(tif, (uint8*) data, cc, sample))
-		return (0);
+		return ((tmsize_t) -1);
 	if (!(*tif->tif_postencode)(tif))
 		return ((tmsize_t)(-1));
 	if (!isFillOrder(tif, td->td_fillorder) &&
diff --git a/frmts/gtiff/libtiff/tif_zip.c b/frmts/gtiff/libtiff/tif_zip.c
index 22e9f35..954a1e5 100644
--- a/frmts/gtiff/libtiff/tif_zip.c
+++ b/frmts/gtiff/libtiff/tif_zip.c
@@ -1,4 +1,4 @@
-/* $Id: tif_zip.c,v 1.33 2014-12-25 18:29:11 erouault Exp $ */
+/* $Id: tif_zip.c,v 1.35 2015-11-22 22:37:27 erouault Exp $ */
 
 /*
  * Copyright (c) 1995-1997 Sam Leffler
@@ -135,7 +135,7 @@ ZIPPreDecode(TIFF* tif, uint16 s)
 	assert(sizeof(sp->stream.avail_in)==4);  /* if this assert gets raised,
 	    we need to simplify this code to reflect a ZLib that is likely updated
 	    to deal with 8byte memory sizes, though this code will respond
-	    apropriately even before we simplify it */
+	    appropriately even before we simplify it */
 	sp->stream.avail_in = (uInt) tif->tif_rawcc;
 	if ((tmsize_t)sp->stream.avail_in != tif->tif_rawcc)
 	{
@@ -162,7 +162,7 @@ ZIPDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
 	assert(sizeof(sp->stream.avail_out)==4);  /* if this assert gets raised,
 	    we need to simplify this code to reflect a ZLib that is likely updated
 	    to deal with 8byte memory sizes, though this code will respond
-	    apropriately even before we simplify it */
+	    appropriately even before we simplify it */
 	sp->stream.avail_out = (uInt) occ;
 	if ((tmsize_t)sp->stream.avail_out != occ)
 	{
@@ -239,8 +239,8 @@ ZIPPreEncode(TIFF* tif, uint16 s)
 	assert(sizeof(sp->stream.avail_out)==4);  /* if this assert gets raised,
 	    we need to simplify this code to reflect a ZLib that is likely updated
 	    to deal with 8byte memory sizes, though this code will respond
-	    apropriately even before we simplify it */
-	sp->stream.avail_out = tif->tif_rawdatasize;
+	    appropriately even before we simplify it */
+	sp->stream.avail_out = (uInt)tif->tif_rawdatasize;
 	if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize)
 	{
 		TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size");
@@ -266,7 +266,7 @@ ZIPEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 	assert(sizeof(sp->stream.avail_in)==4);  /* if this assert gets raised,
 	    we need to simplify this code to reflect a ZLib that is likely updated
 	    to deal with 8byte memory sizes, though this code will respond
-	    apropriately even before we simplify it */
+	    appropriately even before we simplify it */
 	sp->stream.avail_in = (uInt) cc;
 	if ((tmsize_t)sp->stream.avail_in != cc)
 	{
@@ -460,7 +460,7 @@ bad:
 		     "No space for ZIP state block");
 	return (0);
 }
-#endif /* ZIP_SUPORT */
+#endif /* ZIP_SUPPORT */
 
 /* vim: set ts=8 sts=8 sw=8 noet: */
 /*
diff --git a/frmts/gtiff/libtiff/tiff.h b/frmts/gtiff/libtiff/tiff.h
index bc46acd..fb39634 100644
--- a/frmts/gtiff/libtiff/tiff.h
+++ b/frmts/gtiff/libtiff/tiff.h
@@ -1,4 +1,4 @@
-/* $Id: tiff.h,v 1.69 2014-04-02 17:23:06 fwarmerdam Exp $ */
+/* $Id: tiff.h,v 1.70 2016-01-23 21:20:34 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -279,7 +279,7 @@ typedef enum {
 #define     PREDICTOR_FLOATINGPOINT	3	/* floating point predictor */
 #define	TIFFTAG_WHITEPOINT		318	/* image white point */
 #define	TIFFTAG_PRIMARYCHROMATICITIES	319	/* !primary chromaticities */
-#define	TIFFTAG_COLORMAP		320	/* RGB map for pallette image */
+#define	TIFFTAG_COLORMAP		320	/* RGB map for palette image */
 #define	TIFFTAG_HALFTONEHINTS		321	/* !highlight+shadow info */
 #define	TIFFTAG_TILEWIDTH		322	/* !tile width in pixels */
 #define	TIFFTAG_TILELENGTH		323	/* !tile height in pixels */
@@ -358,7 +358,7 @@ typedef enum {
 #define	TIFFTAG_JPEGRESTARTINTERVAL	515	/* !restart interval length */
 #define	TIFFTAG_JPEGLOSSLESSPREDICTORS	517	/* !lossless proc predictor */
 #define	TIFFTAG_JPEGPOINTTRANSFORM	518	/* !lossless point transform */
-#define	TIFFTAG_JPEGQTABLES		519	/* !Q matrice offsets */
+#define	TIFFTAG_JPEGQTABLES		519	/* !Q matrix offsets */
 #define	TIFFTAG_JPEGDCTABLES		520	/* !DCT table offsets */
 #define	TIFFTAG_JPEGACTABLES		521	/* !AC coefficient offsets */
 #define	TIFFTAG_YCBCRCOEFFICIENTS	529	/* !RGB -> YCbCr transform */
diff --git a/frmts/gtiff/libtiff/tiffio.h b/frmts/gtiff/libtiff/tiffio.h
index 038b670..6a84d80 100644
--- a/frmts/gtiff/libtiff/tiffio.h
+++ b/frmts/gtiff/libtiff/tiffio.h
@@ -1,4 +1,4 @@
-/* $Id: tiffio.h,v 1.91 2012-07-29 15:45:29 tgl Exp $ */
+/* $Id: tiffio.h,v 1.92 2016-01-23 21:20:34 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -208,7 +208,7 @@ struct _TIFFRGBAImage {
 	uint16 orientation;                     /* image orientation */
 	uint16 req_orientation;                 /* requested orientation */
 	uint16 photometric;                     /* image photometric interp */
-	uint16* redcmap;                        /* colormap pallete */
+	uint16* redcmap;                        /* colormap palette */
 	uint16* greencmap;
 	uint16* bluecmap;
 	/* get image data routine */
@@ -225,7 +225,7 @@ struct _TIFFRGBAImage {
 	TIFFYCbCrToRGB* ycbcr;                  /* YCbCr conversion state */
 	TIFFCIELabToRGB* cielab;                /* CIE L*a*b conversion state */
 
-	uint8* UaToAa;                          /* Unassociated alpha to associated alpha convertion LUT */
+	uint8* UaToAa;                          /* Unassociated alpha to associated alpha conversion LUT */
 	uint8* Bitdepth16To8;                   /* LUT for conversion from 16bit to 8bit values */
 
 	int row_offset;
diff --git a/frmts/gtiff/libtiff/tiffiop.h b/frmts/gtiff/libtiff/tiffiop.h
index 53357d8..8bcd0c1 100644
--- a/frmts/gtiff/libtiff/tiffiop.h
+++ b/frmts/gtiff/libtiff/tiffiop.h
@@ -1,4 +1,4 @@
-/* $Id: tiffiop.h,v 1.84 2012-05-30 01:50:17 fwarmerdam Exp $ */
+/* $Id: tiffiop.h,v 1.89 2016-01-23 21:20:34 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -57,6 +57,12 @@ extern void *lfind(const void *, const void *, size_t *, size_t,
 		   int (*)(const void *, const void *));
 #endif
 
+#if !defined(HAVE_SNPRINTF) && !defined(HAVE__SNPRINTF)
+#undef snprintf
+#define snprintf _TIFF_snprintf_f
+extern int snprintf(char* str, size_t size, const char* format, ...);
+#endif
+
 #include "tiffio.h"
 
 #include "tif_dir.h"
@@ -80,7 +86,7 @@ typedef struct client_info {
 
 /*
  * Typedefs for ``method pointers'' used internally.
- * these are depriciated and provided only for backwards compatibility
+ * these are deprecated and provided only for backwards compatibility.
  */
 typedef unsigned char tidataval_t;    /* internal image data value type */
 typedef tidataval_t* tidata_t;        /* reference to internal image data */
@@ -99,33 +105,33 @@ struct tiff {
 	int                  tif_fd;           /* open file descriptor */
 	int                  tif_mode;         /* open mode (O_*) */
 	uint32               tif_flags;
-	#define TIFF_FILLORDER   0x00003 /* natural bit fill order for machine */
-	#define TIFF_DIRTYHEADER 0x00004 /* header must be written on close */
-	#define TIFF_DIRTYDIRECT 0x00008 /* current directory must be written */
-	#define TIFF_BUFFERSETUP 0x00010 /* data buffers setup */
-	#define TIFF_CODERSETUP  0x00020 /* encoder/decoder setup done */
-	#define TIFF_BEENWRITING 0x00040 /* written 1+ scanlines to file */
-	#define TIFF_SWAB        0x00080 /* byte swap file information */
-	#define TIFF_NOBITREV    0x00100 /* inhibit bit reversal logic */
-	#define TIFF_MYBUFFER    0x00200 /* my raw data buffer; free on close */
-	#define TIFF_ISTILED     0x00400 /* file is tile, not strip- based */
-	#define TIFF_MAPPED      0x00800 /* file is mapped into memory */
-	#define TIFF_POSTENCODE  0x01000 /* need call to postencode routine */
-	#define TIFF_INSUBIFD    0x02000 /* currently writing a subifd */
-	#define TIFF_UPSAMPLED   0x04000 /* library is doing data up-sampling */
-	#define TIFF_STRIPCHOP   0x08000 /* enable strip chopping support */
-	#define TIFF_HEADERONLY  0x10000 /* read header only, do not process the first directory */
-	#define TIFF_NOREADRAW   0x20000 /* skip reading of raw uncompressed image data */
-	#define TIFF_INCUSTOMIFD 0x40000 /* currently writing a custom IFD */
-	#define TIFF_BIGTIFF     0x80000 /* read/write bigtiff */
-        #define TIFF_BUF4WRITE  0x100000 /* rawcc bytes are for writing */
-        #define TIFF_DIRTYSTRIP 0x200000 /* stripoffsets/stripbytecount dirty*/
-        #define TIFF_PERSAMPLE  0x400000 /* get/set per sample tags as arrays */
-        #define TIFF_BUFFERMMAP 0x800000 /* read buffer (tif_rawdata) points into mmap() memory */
+	#define TIFF_FILLORDER   0x00003U /* natural bit fill order for machine */
+	#define TIFF_DIRTYHEADER 0x00004U /* header must be written on close */
+	#define TIFF_DIRTYDIRECT 0x00008U /* current directory must be written */
+	#define TIFF_BUFFERSETUP 0x00010U /* data buffers setup */
+	#define TIFF_CODERSETUP  0x00020U /* encoder/decoder setup done */
+	#define TIFF_BEENWRITING 0x00040U /* written 1+ scanlines to file */
+	#define TIFF_SWAB        0x00080U /* byte swap file information */
+	#define TIFF_NOBITREV    0x00100U /* inhibit bit reversal logic */
+	#define TIFF_MYBUFFER    0x00200U /* my raw data buffer; free on close */
+	#define TIFF_ISTILED     0x00400U /* file is tile, not strip- based */
+	#define TIFF_MAPPED      0x00800U /* file is mapped into memory */
+	#define TIFF_POSTENCODE  0x01000U /* need call to postencode routine */
+	#define TIFF_INSUBIFD    0x02000U /* currently writing a subifd */
+	#define TIFF_UPSAMPLED   0x04000U /* library is doing data up-sampling */
+	#define TIFF_STRIPCHOP   0x08000U /* enable strip chopping support */
+	#define TIFF_HEADERONLY  0x10000U /* read header only, do not process the first directory */
+	#define TIFF_NOREADRAW   0x20000U /* skip reading of raw uncompressed image data */
+	#define TIFF_INCUSTOMIFD 0x40000U /* currently writing a custom IFD */
+	#define TIFF_BIGTIFF     0x80000U /* read/write bigtiff */
+        #define TIFF_BUF4WRITE  0x100000U /* rawcc bytes are for writing */
+        #define TIFF_DIRTYSTRIP 0x200000U /* stripoffsets/stripbytecount dirty*/
+        #define TIFF_PERSAMPLE  0x400000U /* get/set per sample tags as arrays */
+        #define TIFF_BUFFERMMAP 0x800000U /* read buffer (tif_rawdata) points into mmap() memory */
 	uint64               tif_diroff;       /* file offset of current directory */
 	uint64               tif_nextdiroff;   /* file offset of following directory */
 	uint64*              tif_dirlist;      /* list of offsets to already seen directories to prevent IFD looping */
-	uint16               tif_dirlistsize;  /* number of entires in offset list */
+	uint16               tif_dirlistsize;  /* number of entries in offset list */
 	uint16               tif_dirnumber;    /* number of already seen directories */
 	TIFFDirectory        tif_dir;          /* internal rep of current directory */
 	TIFFDirectory        tif_customdir;    /* custom IFDs are separated from the main ones */
@@ -258,6 +264,53 @@ struct tiff {
 
 #define TIFFArrayCount(a) (sizeof (a) / sizeof ((a)[0]))
 
+/*
+  Support for large files.
+
+  Windows read/write APIs support only 'unsigned int' rather than 'size_t'.
+  Windows off_t is only 32-bit, even in 64-bit builds.
+*/
+#if defined(HAVE_FSEEKO)
+/*
+  Use fseeko() and ftello() if they are available since they use
+  'off_t' rather than 'long'.  It is wrong to use fseeko() and
+  ftello() only on systems with special LFS support since some systems
+  (e.g. FreeBSD) support a 64-bit off_t by default.
+
+  For MinGW, __MSVCRT_VERSION__ must be at least 0x800 to expose these
+  interfaces. The MinGW compiler must support the requested version.  MinGW
+  does not distribute the CRT (it is supplied by Microsoft) so the correct CRT
+  must be available on the target computer in order for the program to run.
+*/
+#if defined(HAVE_FSEEKO)
+#  define fseek(stream,offset,whence)  fseeko(stream,offset,whence)
+#  define ftell(stream,offset,whence)  ftello(stream,offset,whence)
+#endif
+#endif
+#if defined(__WIN32__) && \
+        !(defined(_MSC_VER) && _MSC_VER < 1400) && \
+        !(defined(__MSVCRT_VERSION__) && __MSVCRT_VERSION__ < 0x800)
+typedef unsigned int TIFFIOSize_t;
+#define _TIFF_lseek_f(fildes,offset,whence)  _lseeki64(fildes,/* __int64 */ offset,whence)
+/* #define _TIFF_tell_f(fildes) /\* __int64 *\/ _telli64(fildes) */
+#define _TIFF_fseek_f(stream,offset,whence) _fseeki64(stream,/* __int64 */ offset,whence)
+#define _TIFF_fstat_f(fildes,stat_buff) _fstati64(fildes,/* struct _stati64 */ stat_buff)
+/* #define _TIFF_ftell_f(stream) /\* __int64 *\/ _ftelli64(stream) */
+/* #define _TIFF_stat_f(path,stat_buff) _stati64(path,/\* struct _stati64 *\/ stat_buff) */
+#define _TIFF_stat_s struct _stati64
+#define _TIFF_off_t __int64
+#else
+typedef size_t TIFFIOSize_t;
+#define _TIFF_lseek_f(fildes,offset,whence) lseek(fildes,offset,whence)
+/* #define _TIFF_tell_f(fildes) (_TIFF_lseek_f(fildes,0,SEEK_CUR)) */
+#define _TIFF_fseek_f(stream,offset,whence) fseek(stream,offset,whence)
+#define _TIFF_fstat_f(fildes,stat_buff) fstat(fildes,stat_buff)
+/* #define _TIFF_ftell_f(stream) ftell(stream) */
+/* #define _TIFF_stat_f(path,stat_buff) stat(path,stat_buff) */
+#define _TIFF_stat_s struct stat
+#define _TIFF_off_t off_t
+#endif
+
 #if defined(__cplusplus)
 extern "C" {
 #endif
diff --git a/frmts/gtiff/libtiff/tiffvers.h b/frmts/gtiff/libtiff/tiffvers.h
index 74f769c..e965814 100644
--- a/frmts/gtiff/libtiff/tiffvers.h
+++ b/frmts/gtiff/libtiff/tiffvers.h
@@ -1,4 +1,4 @@
-#define TIFFLIB_VERSION_STR "LIBTIFF, Version 4.0.4beta\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc."
+#define TIFFLIB_VERSION_STR "LIBTIFF, Version 4.0.6\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc."
 /*
  * This define can be used in code that requires
  * compilation-related definitions specific to a
@@ -6,4 +6,4 @@
  * version checking should be done based on the
  * string returned by TIFFGetVersion.
  */
-#define TIFFLIB_VERSION 20150126
+#define TIFFLIB_VERSION 20150912
diff --git a/frmts/gtiff/libtiff/uvcode.h b/frmts/gtiff/libtiff/uvcode.h
index 50f11d7..6286cfb 100644
--- a/frmts/gtiff/libtiff/uvcode.h
+++ b/frmts/gtiff/libtiff/uvcode.h
@@ -3,7 +3,7 @@
 #define UV_NDIVS	16289
 #define UV_VSTART	(float)0.016940
 #define UV_NVS		163
-static struct {
+static const struct {
 	float	ustart;
 	short	nus, ncum;
 }	uv_row[UV_NVS] = {
diff --git a/frmts/gtiff/tif_float.c b/frmts/gtiff/tif_float.c
index 4bfe8de..7575d42 100644
--- a/frmts/gtiff/tif_float.c
+++ b/frmts/gtiff/tif_float.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tif_float.c 21102 2010-11-08 20:47:38Z rouault $
+ * $Id: tif_float.c 33796 2016-03-27 13:21:07Z goatbar $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Floating point conversion functions. Convert 16- and 24-bit
@@ -11,7 +11,7 @@
  *
  * This code is based on the code from OpenEXR project with the following
  * copyright:
- * 
+ *
  * Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
  * Digital Ltd. LLC
  *
@@ -28,8 +28,8 @@
  * distribution.
  * *       Neither the name of Industrial Light & Magic nor the names of
  * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission. 
- * 
+ * from this software without specific prior written permission.
+ *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -61,61 +61,62 @@ GUInt32 HalfToFloat( GUInt16 iHalf )
 
     if (iExponent == 0)
     {
-	if (iMantissa == 0)
-	{
+        if (iMantissa == 0)
+        {
 /* -------------------------------------------------------------------- */
-/*	Plus or minus zero.			                        */
+/*      Plus or minus zero.                                             */
 /* -------------------------------------------------------------------- */
 
             return iSign << 31;
-	}
-	else
-	{
+        }
+        else
+        {
 /* -------------------------------------------------------------------- */
-/*	Denormalized number -- renormalize it.			        */
+/*      Denormalized number -- renormalize it.                          */
 /* -------------------------------------------------------------------- */
 
-	    while (!(iMantissa & 0x00000400))
-	    {
-		iMantissa <<= 1;
-		iExponent -=  1;
-	    }
+            while (!(iMantissa & 0x00000400))
+            {
+                iMantissa <<= 1;
+                iExponent -=  1;
+            }
 
-	    iExponent += 1;
-	    iMantissa &= ~0x00000400;
-	}
+            iExponent += 1;
+            iMantissa &= ~0x00000400U;
+        }
     }
     else if (iExponent == 31)
     {
-	if (iMantissa == 0)
-	{
+        if (iMantissa == 0)
+        {
 /* -------------------------------------------------------------------- */
-/*	 Positive or negative infinity.			                */
+/*       Positive or negative infinity.                                 */
 /* -------------------------------------------------------------------- */
 
-	    return (iSign << 31) | 0x7f800000;
-	}
-	else
-	{
+            return (iSign << 31) | 0x7f800000;
+        }
+        else
+        {
 /* -------------------------------------------------------------------- */
-/*	 NaN -- preserve sign and significand bits.	                */
+/*       NaN -- preserve sign and significand bits.                     */
 /* -------------------------------------------------------------------- */
 
-	    return (iSign << 31) | 0x7f800000 | (iMantissa << 13);
-	}
+            return (iSign << 31) | 0x7f800000 | (iMantissa << 13);
+        }
     }
 
 /* -------------------------------------------------------------------- */
-/*	 Normalized number.			                        */
+/*       Normalized number.                                             */
 /* -------------------------------------------------------------------- */
 
     iExponent = iExponent + (127 - 15);
     iMantissa = iMantissa << 13;
 
 /* -------------------------------------------------------------------- */
-/*	 Assemble sign, exponent and mantissa.			        */
+/*       Assemble sign, exponent and mantissa.                          */
 /* -------------------------------------------------------------------- */
 
+    /* coverity[overflow_sink] */
     return (iSign << 31) | (iExponent << 23) | iMantissa;
 }
 
@@ -134,60 +135,61 @@ GUInt32 TripleToFloat( GUInt32 iTriple )
 
     if (iExponent == 0)
     {
-	if (iMantissa == 0)
-	{
+        if (iMantissa == 0)
+        {
 /* -------------------------------------------------------------------- */
-/*	Plus or minus zero.			                        */
+/*      Plus or minus zero.                                             */
 /* -------------------------------------------------------------------- */
 
-	    return iSign << 31;
-	}
-	else
-	{
+            return iSign << 31;
+        }
+        else
+        {
 /* -------------------------------------------------------------------- */
-/*	Denormalized number -- renormalize it.			        */
+/*      Denormalized number -- renormalize it.                          */
 /* -------------------------------------------------------------------- */
 
-	    while (!(iMantissa & 0x00002000))
-	    {
-		iMantissa <<= 1;
-		iExponent -=  1;
-	    }
+            while (!(iMantissa & 0x00002000))
+            {
+                iMantissa <<= 1;
+                iExponent -= 1;
+            }
 
-	    iExponent += 1;
-	    iMantissa &= ~0x00002000;
-	}
+            iExponent += 1;
+            iMantissa &= ~0x00002000U;
+        }
     }
     else if (iExponent == 127)
     {
-	if (iMantissa == 0)
-	{
+        if (iMantissa == 0)
+        {
 /* -------------------------------------------------------------------- */
-/*	 Positive or negative infinity.			                */
+/*       Positive or negative infinity.                                 */
 /* -------------------------------------------------------------------- */
 
-	    return (iSign << 31) | 0x7f800000;
-	}
-	else
-	{
+            return (iSign << 31) | 0x7f800000;
+        }
+        else
+        {
 /* -------------------------------------------------------------------- */
-/*	 NaN -- preserve sign and significand bits.	                */
+/*       NaN -- preserve sign and significand bits.                     */
 /* -------------------------------------------------------------------- */
 
-	    return (iSign << 31) | 0x7f800000 | (iMantissa << 7);
-	}
+            return (iSign << 31) | 0x7f800000 | (iMantissa << 7);
+        }
     }
 
 /* -------------------------------------------------------------------- */
-/*	 Normalized number.			                        */
+/*       Normalized number.                                             */
 /* -------------------------------------------------------------------- */
 
     iExponent = iExponent + (127 - 63);
     iMantissa = iMantissa << 7;
 
 /* -------------------------------------------------------------------- */
-/*	 Assemble sign, exponent and mantissa.			        */
+/*       Assemble sign, exponent and mantissa.                          */
 /* -------------------------------------------------------------------- */
 
+    /* coverity[overflow_sink] */
     return (iSign << 31) | (iExponent << 23) | iMantissa;
 }
diff --git a/frmts/gtiff/tifvsi.cpp b/frmts/gtiff/tifvsi.cpp
index 70b6454..7a25846 100644
--- a/frmts/gtiff/tifvsi.cpp
+++ b/frmts/gtiff/tifvsi.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tifvsi.cpp 28873 2015-04-08 14:32:00Z rouault $
+ * $Id: tifvsi.cpp 33806 2016-03-28 22:26:19Z goatbar $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Implement system hook functions for libtiff on top of CPL/VSI,
@@ -37,7 +37,7 @@
 #include "cpl_conv.h"
 #include "tifvsi.h"
 
-#include <errno.h>
+#include <cerrno>
 
 // We avoid including xtiffio.h since it drags in the libgeotiff version
 // of the VSI functions.
@@ -47,7 +47,7 @@
 #endif
 
 CPL_C_START
-extern TIFF CPL_DLL * XTIFFClientOpen(const char* name, const char* mode, 
+extern TIFF CPL_DLL * XTIFFClientOpen(const char* name, const char* mode,
                                       thandle_t thehandle,
                                       TIFFReadWriteProc, TIFFReadWriteProc,
                                       TIFFSeekProc, TIFFCloseProc,
@@ -95,20 +95,20 @@ static tsize_t
 _tiffWriteProc(thandle_t th, tdata_t buf, tsize_t size)
 {
     GDALTiffHandle* psGTH = (GDALTiffHandle*) th;
-    
+
     // If we have a write buffer and are at end of file, then accumulate
     // the bytes until the buffer is full
     if( psGTH->bAtEndOfFile && psGTH->abyWriteBuffer )
     {
         const GByte* pabyData = (const GByte*) buf;
         tsize_t nRemainingBytes = size;
-        while( TRUE )
+        while( true )
         {
             if( psGTH->nWriteBufferSize + nRemainingBytes <= BUFFER_SIZE )
             {
                 memcpy( psGTH->abyWriteBuffer + psGTH->nWriteBufferSize,
                         pabyData, nRemainingBytes );
-                psGTH->nWriteBufferSize += nRemainingBytes;
+                psGTH->nWriteBufferSize += static_cast<int>(nRemainingBytes);
                 psGTH->nExpectedPos += size;
                 return size;
             }
@@ -128,7 +128,7 @@ _tiffWriteProc(thandle_t th, tdata_t buf, tsize_t size)
             nRemainingBytes -= nAppendable;
         }
     }
-    
+
     tsize_t nRet = VSIFWriteL( buf, 1, size, psGTH->fpL );
     if (nRet < size)
     {
@@ -168,7 +168,7 @@ _tiffSeekProc(thandle_t th, toff_t off, int whence)
     GTHFlushBuffer(th);
     psGTH->bAtEndOfFile = FALSE;
     psGTH->nExpectedPos = 0;
-    
+
     if( VSIFSeekL( psGTH->fpL, off, whence ) == 0 )
         return (toff_t) VSIFTellL( psGTH->fpL );
     else
@@ -194,17 +194,17 @@ _tiffSizeProc(thandle_t th)
     GDALTiffHandle* psGTH = (GDALTiffHandle*) th;
     vsi_l_offset  old_off;
     toff_t        file_size;
-    
+
     if( psGTH->bAtEndOfFile )
     {
         return (toff_t) psGTH->nExpectedPos;
     }
 
     old_off = VSIFTellL( psGTH->fpL );
-    VSIFSeekL( psGTH->fpL, 0, SEEK_END );
-    
+    CPL_IGNORE_RET_VAL(VSIFSeekL( psGTH->fpL, 0, SEEK_END ));
+
     file_size = (toff_t) VSIFTellL( psGTH->fpL );
-    VSIFSeekL( psGTH->fpL, old_off, SEEK_SET );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( psGTH->fpL, old_off, SEEK_SET ));
 
     return file_size;
 }
@@ -212,14 +212,14 @@ _tiffSizeProc(thandle_t th)
 static int
 _tiffMapProc(thandle_t th, tdata_t* pbase, toff_t* psize)
 {
-	(void) th; (void) pbase; (void) psize;
-	return (0);
+    (void) th; (void) pbase; (void) psize;
+    return (0);
 }
 
 static void
 _tiffUnmapProc(thandle_t th, tdata_t base, toff_t size)
 {
-	(void) th; (void) base; (void) size;
+    (void) th; (void) base; (void) size;
 }
 
 VSILFILE* VSI_TIFFGetVSILFile(thandle_t th)
@@ -266,13 +266,14 @@ TIFF* VSI_TIFFOpen(const char* name, const char* mode,
     }
 
     // No need to buffer on /vsimem/
-    if( strncmp(name, "/vsimem/", strlen("/vsimem/")) == 0 )
+    if( STARTS_WITH(name, "/vsimem/") )
         bAllocBuffer = FALSE;
 
     strcat( access, "b" );
 
-    VSIFSeekL(fpL, 0, SEEK_SET);
-    
+    if( VSIFSeekL(fpL, 0, SEEK_SET) < 0 )
+        return NULL;
+
     GDALTiffHandle* psGTH = (GDALTiffHandle*) CPLMalloc(sizeof(GDALTiffHandle));
     psGTH->fpL = fpL;
     psGTH->nExpectedPos = 0;
diff --git a/frmts/gtiff/tifvsi.h b/frmts/gtiff/tifvsi.h
index de7befc..a0e3ced 100644
--- a/frmts/gtiff/tifvsi.h
+++ b/frmts/gtiff/tifvsi.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tifvsi.h 28872 2015-04-08 14:25:20Z rouault $
+ * $Id: tifvsi.h 31787 2015-11-26 17:41:42Z rouault $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Implement system hook functions for libtiff on top of CPL/VSI,
diff --git a/frmts/gxf/README b/frmts/gxf/README
index 60f8166..eead1e8 100644
--- a/frmts/gxf/README
+++ b/frmts/gxf/README
@@ -12,7 +12,7 @@ GXF Irregularities
  o The #TRANSFORM is defined to have commas between fields, but in the
    example files it has spaces.  Treating both the same.
 
- o The document doesn't memtion it, but it seems that the first five
+ o The document doesn't mention it, but it seems that the first five
    characters have to be taken as sufficient for a field name.  For 
    instance the old sample file I have has only #TITL for the title,
    while new ones have #TITLE. 
@@ -28,7 +28,7 @@ GXF Irregularities
 
  o I reprojected gxf_text.gxf to lat/long producing latlong.gxf.  This
    file contains a #MAP_PROJECTION of "NAD83 / UTM zone 19N" even though
-   everything is in degrees.  Why?  Shouldn't it read "Geographic"?
+   everything is in degrees.  Why?  Should it read "Geographic"?
 
 
 
diff --git a/frmts/gxf/gxf_ogcwkt.c b/frmts/gxf/gxf_ogcwkt.c
index 8ab0f4a..04cc175 100644
--- a/frmts/gxf/gxf_ogcwkt.c
+++ b/frmts/gxf/gxf_ogcwkt.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gxf_ogcwkt.c 28565 2015-02-27 10:26:21Z rouault $
+ * $Id: gxf_ogcwkt.c 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  GXF Reader
  * Purpose:  Handle GXF to OGC WKT projection transformation.
@@ -31,7 +31,7 @@
 #include "gxfopen.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: gxf_ogcwkt.c 28565 2015-02-27 10:26:21Z rouault $");
+CPL_CVSID("$Id: gxf_ogcwkt.c 33720 2016-03-15 00:39:53Z goatbar $");
 
 /* -------------------------------------------------------------------- */
 /* the following #defines come from ogr_spatialref.h in the GDAL/OGR	*/
@@ -110,7 +110,7 @@ CPL_CVSID("$Id: gxf_ogcwkt.c 28565 2015-02-27 10:26:21Z rouault $");
 /*      This table was copied from gt_wkt_srs.cpp in the libgeotiff     */
 /*      distribution.  Please keep changes in sync.                     */
 /* -------------------------------------------------------------------- */
-static char *papszDatumEquiv[] =
+static const char * const papszDatumEquiv[] =
 {
     "Militar_Geographische_Institut",
     "Militar_Geographische_Institute",
@@ -173,9 +173,9 @@ static void WKTMassageDatum( char ** ppszDatum )
         pszDatum[j] = '\0';
     else
         pszDatum[j+1] = '\0';
-    
+
 /* -------------------------------------------------------------------- */
-/*      Search for datum equivelences.  Specific massaged names get     */
+/*      Search for datum equivalences.  Specific massaged names get     */
 /*      mapped to OpenGIS specified names.                              */
 /* -------------------------------------------------------------------- */
     for( i = 0; papszDatumEquiv[i] != NULL; i += 2 )
@@ -193,13 +193,15 @@ static void WKTMassageDatum( char ** ppszDatum )
 /*                           OGCWKTSetProj()                            */
 /************************************************************************/
 
-static void OGCWKTSetProj( char * pszProjection, char ** papszMethods,
+static void OGCWKTSetProj( char * pszProjection,
+                           size_t nProjectionSize,
+                           char ** papszMethods,
                            const char * pszTransformName,
-                           const char * pszParm1, 
-                           const char * pszParm2, 
-                           const char * pszParm3, 
-                           const char * pszParm4, 
-                           const char * pszParm5, 
+                           const char * pszParm1,
+                           const char * pszParm2,
+                           const char * pszParm3,
+                           const char * pszParm4,
+                           const char * pszParm5,
                            const char * pszParm6,
                            const char * pszParm7 )
 
@@ -216,13 +218,14 @@ static void OGCWKTSetProj( char * pszProjection, char ** papszMethods,
     apszParmNames[6] = pszParm7;
     apszParmNames[7] = NULL;
 
-    sprintf( pszProjection,
+    snprintf( pszProjection, nProjectionSize,
              "PROJECTION[\"%s\"]",
              pszTransformName );
 
     for( iParm = 0; iParm < nCount-1 && apszParmNames[iParm] != NULL; iParm++ )
     {
-        sprintf( pszProjection + strlen(pszProjection),
+        snprintf( pszProjection + strlen(pszProjection),
+                 nProjectionSize - strlen(pszProjection),
                  ",PARAMETER[\"%s\",%s]",
                  apszParmNames[iParm],
                  papszMethods[iParm+1] );
@@ -252,7 +255,7 @@ static void OGCWKTSetProj( char * pszProjection, char ** papszMethods,
  *
  * For example, the following GXF definitions:
  * <pre>
- * #UNIT_LENGTH                        
+ * #UNIT_LENGTH
  * m,1
  * #MAP_PROJECTION
  * "NAD83 / UTM zone 19N"
@@ -316,13 +319,13 @@ char *GXFGetMapProjectionAsOGCWKT( GXFHandle hGXF )
 
 #ifdef DBMALLOC
     malloc_chain_check(1);
-#endif    
-    
+#endif
+
 /* -------------------------------------------------------------------- */
 /*      Create the PROJCS.                                              */
 /* -------------------------------------------------------------------- */
     if( papszMethods == NULL
-        || papszMethods[0] == NULL 
+        || papszMethods[0] == NULL
         || EQUAL(papszMethods[0],"Geographic") )
     {
         /* do nothing */
@@ -330,7 +333,7 @@ char *GXFGetMapProjectionAsOGCWKT( GXFHandle hGXF )
 
     else if( EQUAL(papszMethods[0],"Lambert Conic Conformal (1SP)") )
     {
-        OGCWKTSetProj( szProjection, papszMethods,
+        OGCWKTSetProj( szProjection, sizeof(szProjection), papszMethods,
                        SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP,
                        SRS_PP_LATITUDE_OF_ORIGIN,
                        SRS_PP_CENTRAL_MERIDIAN,
@@ -340,10 +343,10 @@ char *GXFGetMapProjectionAsOGCWKT( GXFHandle hGXF )
                        NULL,
                        NULL );
     }
-    
+
     else if( EQUAL(papszMethods[0],"Lambert Conic Conformal (2SP)") )
     {
-        OGCWKTSetProj( szProjection, papszMethods,
+        OGCWKTSetProj( szProjection, sizeof(szProjection), papszMethods,
                        SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP,
                        SRS_PP_STANDARD_PARALLEL_1,
                        SRS_PP_STANDARD_PARALLEL_2,
@@ -353,10 +356,10 @@ char *GXFGetMapProjectionAsOGCWKT( GXFHandle hGXF )
                        SRS_PP_FALSE_NORTHING,
                        NULL );
     }
-    
+
     else if( EQUAL(papszMethods[0],"Lambert Conformal (2SP Belgium)") )
     {
-        OGCWKTSetProj( szProjection, papszMethods,
+        OGCWKTSetProj( szProjection, sizeof(szProjection), papszMethods,
                        SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM,
                        SRS_PP_STANDARD_PARALLEL_1,
                        SRS_PP_STANDARD_PARALLEL_2,
@@ -366,10 +369,10 @@ char *GXFGetMapProjectionAsOGCWKT( GXFHandle hGXF )
                        SRS_PP_FALSE_NORTHING,
                        NULL );
     }
-    
+
     else if( EQUAL(papszMethods[0],"Mercator (1SP)"))
     {
-        OGCWKTSetProj( szProjection, papszMethods,
+        OGCWKTSetProj( szProjection, sizeof(szProjection), papszMethods,
                        SRS_PT_MERCATOR_1SP,
                        SRS_PP_LATITUDE_OF_ORIGIN,
                        SRS_PP_CENTRAL_MERIDIAN,
@@ -379,10 +382,10 @@ char *GXFGetMapProjectionAsOGCWKT( GXFHandle hGXF )
                        NULL,
                        NULL );
     }
-    
+
     else if( EQUAL(papszMethods[0],"Mercator (2SP)"))
     {
-        OGCWKTSetProj( szProjection, papszMethods,
+        OGCWKTSetProj( szProjection, sizeof(szProjection), papszMethods,
                        SRS_PT_MERCATOR_2SP,
                        SRS_PP_LATITUDE_OF_ORIGIN,/* should it be StdParalle1?*/
                        SRS_PP_CENTRAL_MERIDIAN,
@@ -392,10 +395,10 @@ char *GXFGetMapProjectionAsOGCWKT( GXFHandle hGXF )
                        NULL,
                        NULL );
     }
-    
+
     else if( EQUAL(papszMethods[0],"Laborde Oblique Mercator") )
     {
-        OGCWKTSetProj( szProjection, papszMethods,
+        OGCWKTSetProj( szProjection, sizeof(szProjection), papszMethods,
                        SRS_PT_LABORDE_OBLIQUE_MERCATOR,
                        SRS_PP_LATITUDE_OF_CENTER,
                        SRS_PP_LONGITUDE_OF_CENTER,
@@ -409,7 +412,7 @@ char *GXFGetMapProjectionAsOGCWKT( GXFHandle hGXF )
 
     else if( EQUAL(papszMethods[0],"Hotine Oblique Mercator") )
     {
-        OGCWKTSetProj( szProjection, papszMethods,
+        OGCWKTSetProj( szProjection, sizeof(szProjection), papszMethods,
                        SRS_PT_HOTINE_OBLIQUE_MERCATOR,
                        SRS_PP_LATITUDE_OF_CENTER,
                        SRS_PP_LONGITUDE_OF_CENTER,
@@ -423,7 +426,7 @@ char *GXFGetMapProjectionAsOGCWKT( GXFHandle hGXF )
     else if( EQUAL(papszMethods[0],"New Zealand Map Grid") )
 
     {
-        OGCWKTSetProj( szProjection, papszMethods,
+        OGCWKTSetProj( szProjection, sizeof(szProjection), papszMethods,
                        SRS_PT_NEW_ZEALAND_MAP_GRID,
                        SRS_PP_LATITUDE_OF_ORIGIN,
                        SRS_PP_CENTRAL_MERIDIAN,
@@ -433,10 +436,10 @@ char *GXFGetMapProjectionAsOGCWKT( GXFHandle hGXF )
                        NULL,
                        NULL );
     }
-    
+
     else if( EQUAL(papszMethods[0],"Oblique Stereographic") )
     {
-        OGCWKTSetProj( szProjection, papszMethods,
+        OGCWKTSetProj( szProjection, sizeof(szProjection), papszMethods,
                        SRS_PT_OBLIQUE_STEREOGRAPHIC,
                        SRS_PP_LATITUDE_OF_ORIGIN,
                        SRS_PP_CENTRAL_MERIDIAN,
@@ -446,10 +449,10 @@ char *GXFGetMapProjectionAsOGCWKT( GXFHandle hGXF )
                        NULL,
                        NULL );
     }
-    
+
     else if( EQUAL(papszMethods[0],"Polar Stereographic") )
     {
-        OGCWKTSetProj( szProjection, papszMethods,
+        OGCWKTSetProj( szProjection, sizeof(szProjection), papszMethods,
                        SRS_PT_POLAR_STEREOGRAPHIC,
                        SRS_PP_LATITUDE_OF_ORIGIN,
                        SRS_PP_CENTRAL_MERIDIAN,
@@ -459,10 +462,10 @@ char *GXFGetMapProjectionAsOGCWKT( GXFHandle hGXF )
                        NULL,
                        NULL );
     }
-    
+
     else if( EQUAL(papszMethods[0],"Swiss Oblique Cylindrical") )
     {
-        OGCWKTSetProj( szProjection, papszMethods,
+        OGCWKTSetProj( szProjection, sizeof(szProjection), papszMethods,
                        SRS_PT_SWISS_OBLIQUE_CYLINDRICAL,
                        SRS_PP_LATITUDE_OF_CENTER,
                        SRS_PP_LONGITUDE_OF_CENTER,
@@ -472,10 +475,10 @@ char *GXFGetMapProjectionAsOGCWKT( GXFHandle hGXF )
                        NULL,
                        NULL );
     }
-    
+
     else if( EQUAL(papszMethods[0],"Transverse Mercator") )
     {
-        OGCWKTSetProj( szProjection, papszMethods,
+        OGCWKTSetProj( szProjection, sizeof(szProjection), papszMethods,
                        SRS_PT_TRANSVERSE_MERCATOR,
                        SRS_PP_LATITUDE_OF_ORIGIN,
                        SRS_PP_CENTRAL_MERIDIAN,
@@ -489,7 +492,7 @@ char *GXFGetMapProjectionAsOGCWKT( GXFHandle hGXF )
     else if( EQUAL(papszMethods[0],"Transverse Mercator (South Oriented)")
           || EQUAL(papszMethods[0],"Transverse Mercator (South Orientated)"))
     {
-        OGCWKTSetProj( szProjection, papszMethods,
+        OGCWKTSetProj( szProjection, sizeof(szProjection), papszMethods,
                        SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED,
                        SRS_PP_LATITUDE_OF_ORIGIN,
                        SRS_PP_CENTRAL_MERIDIAN,
@@ -502,7 +505,7 @@ char *GXFGetMapProjectionAsOGCWKT( GXFHandle hGXF )
 
     else if( EQUAL(papszMethods[0],"*Albers Conic") )
     {
-        OGCWKTSetProj( szProjection, papszMethods,
+        OGCWKTSetProj( szProjection, sizeof(szProjection), papszMethods,
                        SRS_PT_ALBERS_CONIC_EQUAL_AREA,
                        SRS_PP_STANDARD_PARALLEL_1,
                        SRS_PP_STANDARD_PARALLEL_2,
@@ -515,7 +518,7 @@ char *GXFGetMapProjectionAsOGCWKT( GXFHandle hGXF )
 
     else if( EQUAL(papszMethods[0],"*Equidistant Conic") )
     {
-        OGCWKTSetProj( szProjection, papszMethods,
+        OGCWKTSetProj( szProjection, sizeof(szProjection), papszMethods,
                        SRS_PT_EQUIDISTANT_CONIC,
                        SRS_PP_STANDARD_PARALLEL_1,
                        SRS_PP_STANDARD_PARALLEL_2,
@@ -528,7 +531,7 @@ char *GXFGetMapProjectionAsOGCWKT( GXFHandle hGXF )
 
     else if( EQUAL(papszMethods[0],"*Polyconic") )
     {
-        OGCWKTSetProj( szProjection, papszMethods,
+        OGCWKTSetProj( szProjection, sizeof(szProjection), papszMethods,
                        SRS_PT_POLYCONIC,
                        SRS_PP_LATITUDE_OF_ORIGIN,
                        SRS_PP_CENTRAL_MERIDIAN,
@@ -541,7 +544,6 @@ char *GXFGetMapProjectionAsOGCWKT( GXFHandle hGXF )
 
     CSLDestroy( papszMethods );
 
-    
 /* -------------------------------------------------------------------- */
 /*      Extract the linear Units specification.                         */
 /* -------------------------------------------------------------------- */
@@ -550,11 +552,12 @@ char *GXFGetMapProjectionAsOGCWKT( GXFHandle hGXF )
         if( strlen(psGXF->pszUnitName) > 80 )
             return CPLStrdup("");
 
-        CPLsprintf( szProjection+strlen(szProjection),
+        CPLsnprintf( szProjection+strlen(szProjection),
+                     sizeof(szProjection) - strlen(szProjection),
                  ",UNIT[\"%s\",%.15g]",
                  psGXF->pszUnitName, psGXF->dfUnitToMeter );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Build GEOGCS.  There are still "issues" with the generation     */
 /*      of the GEOGCS/Datum and Spheroid names.  Of these, only the     */
@@ -563,10 +566,10 @@ char *GXFGetMapProjectionAsOGCWKT( GXFHandle hGXF )
     if( CSLCount(psGXF->papszMapProjection) > 1 )
     {
         char	**papszTokens;
-        
+
         if( strlen(psGXF->papszMapProjection[1]) > 80 )
             return CPLStrdup("");
-        
+
         papszTokens = CSLTokenizeStringComplex(psGXF->papszMapProjection[1],
                                                ",", TRUE, TRUE );
 
@@ -589,8 +592,9 @@ char *GXFGetMapProjectionAsOGCWKT( GXFHandle hGXF )
 
             pszOGCDatum = CPLStrdup(papszTokens[0]);
             WKTMassageDatum( &pszOGCDatum );
-            
-            CPLsprintf( szGCS,
+
+            CPLsnprintf( szGCS,
+                        sizeof(szGCS),
                      "GEOGCS[\"%s\","
                        "DATUM[\"%s\","
                        "SPHEROID[\"%s\",%s,%.15g]],",
@@ -603,15 +607,19 @@ char *GXFGetMapProjectionAsOGCWKT( GXFHandle hGXF )
         }
 
         if( CSLCount(papszTokens) > 3 )
-            sprintf( szGCS + strlen(szGCS),
+            CPLsnprintf( szGCS + strlen(szGCS),
+                         sizeof(szGCS) - strlen(szGCS),
                      "PRIMEM[\"unnamed\",%s],",
                      papszTokens[3] );
-        
-        strcat( szGCS, "UNIT[\"degree\",0.0174532925199433]]" );
-        
+
+        CPLsnprintf( szGCS + strlen(szGCS),
+                     sizeof(szGCS) - strlen(szGCS),
+                     "%s",
+                     "UNIT[\"degree\",0.0174532925199433]]" );
+
         CSLDestroy( papszTokens );
     }
-    
+
     CPLAssert(strlen(szProjection) < sizeof(szProjection));
     CPLAssert(strlen(szGCS) < sizeof(szGCS));
 
@@ -624,18 +632,17 @@ char *GXFGetMapProjectionAsOGCWKT( GXFHandle hGXF )
             return CPLStrdup("");
 
         if( psGXF->papszMapProjection[0][0] == '"' )
-            sprintf( szWKT,
+            snprintf( szWKT, sizeof(szWKT),
                      "PROJCS[%s,%s,%s]",
                      psGXF->papszMapProjection[0],
                      szGCS,
                      szProjection );
         else
-            sprintf( szWKT,
+            snprintf( szWKT, sizeof(szWKT),
                      "PROJCS[\"%s\",%s,%s]",
                      psGXF->papszMapProjection[0],
                      szGCS,
                      szProjection );
-            
     }
     else
     {
@@ -644,4 +651,3 @@ char *GXFGetMapProjectionAsOGCWKT( GXFHandle hGXF )
 
     return( CPLStrdup( szWKT ) );
 }
-
diff --git a/frmts/gxf/gxf_proj4.c b/frmts/gxf/gxf_proj4.c
index 8e356c9..915f0aa 100644
--- a/frmts/gxf/gxf_proj4.c
+++ b/frmts/gxf/gxf_proj4.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gxf_proj4.c 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: gxf_proj4.c 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  GXF Reader
  * Purpose:  Handle GXF to PROJ.4 projection transformation.
@@ -30,7 +30,10 @@
 
 #include "gxfopen.h"
 
-CPL_CVSID("$Id: gxf_proj4.c 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: gxf_proj4.c 33720 2016-03-15 00:39:53Z goatbar $");
+
+
+#define SAFE_strcat(x,y) snprintf(x + strlen(x),sizeof(x) - strlen(x), "%s", y)
 
 /************************************************************************/
 /*                     GXFGetMapProjectionAsPROJ4()                     */
@@ -45,11 +48,11 @@ CPL_CVSID("$Id: gxf_proj4.c 27942 2014-11-11 00:57:41Z rouault $");
  *
  * The mapping of GXF projections to PROJ.4 format is not complete.  Please
  * see the gxf_proj4.c code to better understand limitations of this
- * translation.  Noteable PROJ.4 knows little about datums.
+ * translation.  In particular, PROJ.4 knows little about datums.
  *
  * For example, the following GXF definitions:
  * <pre>
- * #UNIT_LENGTH                        
+ * #UNIT_LENGTH
  * m,1
  * #MAP_PROJECTION
  * "NAD83 / UTM zone 19N"
@@ -95,282 +98,282 @@ char *GXFGetMapProjectionAsPROJ4( GXFHandle hGXF )
 
 #ifdef DBMALLOC
     malloc_chain_check(1);
-#endif    
-    
+#endif
+
     if( papszMethods == NULL
-        || papszMethods[0] == NULL 
+        || papszMethods[0] == NULL
         || EQUAL(papszMethods[0],"Geographic") )
     {
-        strcat( szPROJ4, "+proj=longlat" );
+        SAFE_strcat( szPROJ4, "+proj=longlat" );
     }
 
-#ifdef notdef    
+#ifdef notdef
     else if( EQUAL(papszMethods[0],"Lambert Conic Conformal (1SP)")
              && CSLCount(papszMethods) > 5 )
     {
         /* notdef: It isn't clear that this 1SP + scale method is even
            supported by PROJ.4
            Later note: It is not. */
-        
-        strcat( szPROJ4, "+proj=lcc" );
 
-        strcat( szPROJ4, " +lat_0=" );
-        strcat( szPROJ4, papszMethods[1] );
+        SAFE_strcat( szPROJ4, "+proj=lcc" );
+
+        SAFE_strcat( szPROJ4, " +lat_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[1] );
 
-        strcat( szPROJ4, " +lon_0=" );
-        strcat( szPROJ4, papszMethods[2] );
+        SAFE_strcat( szPROJ4, " +lon_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[2] );
 
-        strcat( szPROJ4, " +k=" );
-        strcat( szPROJ4, papszMethods[3] );
-        
-        strcat( szPROJ4, " +x_0=" );
-        strcat( szPROJ4, papszMethods[4] );
+        SAFE_strcat( szPROJ4, " +k=" );
+        SAFE_strcat( szPROJ4, papszMethods[3] );
 
-        strcat( szPROJ4, " +y_0=" );
-        strcat( szPROJ4, papszMethods[5] );
+        SAFE_strcat( szPROJ4, " +x_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[4] );
+
+        SAFE_strcat( szPROJ4, " +y_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[5] );
     }
-#endif    
+#endif
     else if( EQUAL(papszMethods[0],"Lambert Conic Conformal (2SP)")
              || EQUAL(papszMethods[0],"Lambert Conformal (2SP Belgium)") )
     {
         /* notdef: Note we are apparently losing whatever makes the
            Belgium variant different than normal LCC, but hopefully
            they are close! */
-        
-        strcat( szPROJ4, "+proj=lcc" );
+
+        SAFE_strcat( szPROJ4, "+proj=lcc" );
 
         if( CSLCount(papszMethods) > 1 )
         {
-            strcat( szPROJ4, " +lat_1=" );
-            strcat( szPROJ4, papszMethods[1] );
+            SAFE_strcat( szPROJ4, " +lat_1=" );
+            SAFE_strcat( szPROJ4, papszMethods[1] );
         }
 
         if( CSLCount(papszMethods) > 2 )
         {
-            strcat( szPROJ4, " +lat_2=" );
-            strcat( szPROJ4, papszMethods[2] );
+            SAFE_strcat( szPROJ4, " +lat_2=" );
+            SAFE_strcat( szPROJ4, papszMethods[2] );
         }
 
         if( CSLCount(papszMethods) > 3 )
         {
-            strcat( szPROJ4, " +lat_0=" );
-            strcat( szPROJ4, papszMethods[3] );
+            SAFE_strcat( szPROJ4, " +lat_0=" );
+            SAFE_strcat( szPROJ4, papszMethods[3] );
         }
 
         if( CSLCount(papszMethods) > 4 )
         {
-            strcat( szPROJ4, " +lon_0=" );
-            strcat( szPROJ4, papszMethods[4] );
+            SAFE_strcat( szPROJ4, " +lon_0=" );
+            SAFE_strcat( szPROJ4, papszMethods[4] );
         }
 
         if( CSLCount(papszMethods) > 5 )
         {
-            strcat( szPROJ4, " +x_0=" );
-            strcat( szPROJ4, papszMethods[5] );
+            SAFE_strcat( szPROJ4, " +x_0=" );
+            SAFE_strcat( szPROJ4, papszMethods[5] );
         }
 
         if( CSLCount(papszMethods) > 6 )
         {
-            strcat( szPROJ4, " +y_0=" );
-            strcat( szPROJ4, papszMethods[6] );
+            SAFE_strcat( szPROJ4, " +y_0=" );
+            SAFE_strcat( szPROJ4, papszMethods[6] );
         }
     }
-    
+
     else if( EQUAL(papszMethods[0],"Mercator (1SP)")
              && CSLCount(papszMethods) > 5 )
     {
-        /* notdef: it isn't clear that +proj=merc support a scale of other 
+        /* notdef: it isn't clear that +proj=merc support a scale of other
            than 1.0 in PROJ.4 */
-        
-        strcat( szPROJ4, "+proj=merc" );
 
-        strcat( szPROJ4, " +lat_ts=" );
-        strcat( szPROJ4, papszMethods[1] );
+        SAFE_strcat( szPROJ4, "+proj=merc" );
+
+        SAFE_strcat( szPROJ4, " +lat_ts=" );
+        SAFE_strcat( szPROJ4, papszMethods[1] );
+
+        SAFE_strcat( szPROJ4, " +lon_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[2] );
 
-        strcat( szPROJ4, " +lon_0=" );
-        strcat( szPROJ4, papszMethods[2] );
+        SAFE_strcat( szPROJ4, " +k=" );
+        SAFE_strcat( szPROJ4, papszMethods[3] );
 
-        strcat( szPROJ4, " +k=" );
-        strcat( szPROJ4, papszMethods[3] );
-        
-        strcat( szPROJ4, " +x_0=" );
-        strcat( szPROJ4, papszMethods[4] );
+        SAFE_strcat( szPROJ4, " +x_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[4] );
 
-        strcat( szPROJ4, " +y_0=" );
-        strcat( szPROJ4, papszMethods[5] );
+        SAFE_strcat( szPROJ4, " +y_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[5] );
     }
-    
+
     else if( EQUAL(papszMethods[0],"Mercator (2SP)")
              && CSLCount(papszMethods) > 4 )
     {
-        /* notdef: it isn't clear that +proj=merc support a scale of other 
+        /* notdef: it isn't clear that +proj=merc support a scale of other
            than 1.0 in PROJ.4 */
-        
-        strcat( szPROJ4, "+proj=merc" );
 
-        strcat( szPROJ4, " +lat_ts=" );
-        strcat( szPROJ4, papszMethods[1] );
+        SAFE_strcat( szPROJ4, "+proj=merc" );
+
+        SAFE_strcat( szPROJ4, " +lat_ts=" );
+        SAFE_strcat( szPROJ4, papszMethods[1] );
 
-        strcat( szPROJ4, " +lon_0=" );
-        strcat( szPROJ4, papszMethods[2] );
+        SAFE_strcat( szPROJ4, " +lon_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[2] );
 
-        strcat( szPROJ4, " +x_0=" );
-        strcat( szPROJ4, papszMethods[3] );
+        SAFE_strcat( szPROJ4, " +x_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[3] );
 
-        strcat( szPROJ4, " +y_0=" );
-        strcat( szPROJ4, papszMethods[4] );
+        SAFE_strcat( szPROJ4, " +y_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[4] );
     }
-    
-    else if( EQUAL(papszMethods[0],"Hotine Oblique Mercator") 
+
+    else if( EQUAL(papszMethods[0],"Hotine Oblique Mercator")
              && CSLCount(papszMethods) > 7 )
     {
         /* Note that only the second means of specifying omerc is supported
            by this code in GXF. */
-        strcat( szPROJ4, "+proj=omerc" );
+        SAFE_strcat( szPROJ4, "+proj=omerc" );
+
+        SAFE_strcat( szPROJ4, " +lat_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[1] );
 
-        strcat( szPROJ4, " +lat_0=" );
-        strcat( szPROJ4, papszMethods[1] );
-        
-        strcat( szPROJ4, " +lonc=" );
-        strcat( szPROJ4, papszMethods[2] );
-        
-        strcat( szPROJ4, " +alpha=" );
-        strcat( szPROJ4, papszMethods[3] );
+        SAFE_strcat( szPROJ4, " +lonc=" );
+        SAFE_strcat( szPROJ4, papszMethods[2] );
+
+        SAFE_strcat( szPROJ4, " +alpha=" );
+        SAFE_strcat( szPROJ4, papszMethods[3] );
 
         if( CPLAtof(papszMethods[4]) < 0.00001 )
         {
-            strcat( szPROJ4, " +not_rot" );
+            SAFE_strcat( szPROJ4, " +not_rot" );
         }
         else
         {
-#ifdef notdef            
+#ifdef notdef
             if( CPLAtof(papszMethods[4]) + CPLAtof(papszMethods[3]) < 0.00001 )
                 /* ok */;
             else
                 /* notdef: no way to specify arbitrary angles! */;
-#endif            
+#endif
         }
 
-        strcat( szPROJ4, " +k=" );
-        strcat( szPROJ4, papszMethods[5] );
+        SAFE_strcat( szPROJ4, " +k=" );
+        SAFE_strcat( szPROJ4, papszMethods[5] );
 
-        strcat( szPROJ4, " +x_0=" );
-        strcat( szPROJ4, papszMethods[6] );
+        SAFE_strcat( szPROJ4, " +x_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[6] );
 
-        strcat( szPROJ4, " +y_0=" );
-        strcat( szPROJ4, papszMethods[7] );
+        SAFE_strcat( szPROJ4, " +y_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[7] );
     }
 
     else if( EQUAL(papszMethods[0],"Laborde Oblique Mercator")
              && CSLCount(papszMethods) > 6 )
     {
-        strcat( szPROJ4, "+proj=labrd" );
+        SAFE_strcat( szPROJ4, "+proj=labrd" );
+
+        SAFE_strcat( szPROJ4, " +lat_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[1] );
 
-        strcat( szPROJ4, " +lat_0=" );
-        strcat( szPROJ4, papszMethods[1] );
-        
-        strcat( szPROJ4, " +lon_0=" );
-        strcat( szPROJ4, papszMethods[2] );
-        
-        strcat( szPROJ4, " +azi=" );
-        strcat( szPROJ4, papszMethods[3] );
+        SAFE_strcat( szPROJ4, " +lon_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[2] );
 
-        strcat( szPROJ4, " +k=" );
-        strcat( szPROJ4, papszMethods[4] );
+        SAFE_strcat( szPROJ4, " +azi=" );
+        SAFE_strcat( szPROJ4, papszMethods[3] );
 
-        strcat( szPROJ4, " +x_0=" );
-        strcat( szPROJ4, papszMethods[5] );
+        SAFE_strcat( szPROJ4, " +k=" );
+        SAFE_strcat( szPROJ4, papszMethods[4] );
 
-        strcat( szPROJ4, " +y_0=" );
-        strcat( szPROJ4, papszMethods[6] );
+        SAFE_strcat( szPROJ4, " +x_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[5] );
+
+        SAFE_strcat( szPROJ4, " +y_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[6] );
     }
-    
+
     else if( EQUAL(papszMethods[0],"New Zealand Map Grid")
              && CSLCount(papszMethods) > 4 )
     {
-        strcat( szPROJ4, "+proj=nzmg" );
-
-        strcat( szPROJ4, " +lat_0=" );
-        strcat( szPROJ4, papszMethods[1] );
-        
-        strcat( szPROJ4, " +lon_0=" );
-        strcat( szPROJ4, papszMethods[2] );
-        
-        strcat( szPROJ4, " +x_0=" );
-        strcat( szPROJ4, papszMethods[3] );
-
-        strcat( szPROJ4, " +y_0=" );
-        strcat( szPROJ4, papszMethods[4] );
+        SAFE_strcat( szPROJ4, "+proj=nzmg" );
+
+        SAFE_strcat( szPROJ4, " +lat_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[1] );
+
+        SAFE_strcat( szPROJ4, " +lon_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[2] );
+
+        SAFE_strcat( szPROJ4, " +x_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[3] );
+
+        SAFE_strcat( szPROJ4, " +y_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[4] );
     }
-    
+
     else if( EQUAL(papszMethods[0],"New Zealand Map Grid")
              && CSLCount(papszMethods) > 4 )
     {
-        strcat( szPROJ4, "+proj=nzmg" );
-
-        strcat( szPROJ4, " +lat_0=" );
-        strcat( szPROJ4, papszMethods[1] );
-        
-        strcat( szPROJ4, " +lon_0=" );
-        strcat( szPROJ4, papszMethods[2] );
-        
-        strcat( szPROJ4, " +x_0=" );
-        strcat( szPROJ4, papszMethods[3] );
-
-        strcat( szPROJ4, " +y_0=" );
-        strcat( szPROJ4, papszMethods[4] );
+        SAFE_strcat( szPROJ4, "+proj=nzmg" );
+
+        SAFE_strcat( szPROJ4, " +lat_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[1] );
+
+        SAFE_strcat( szPROJ4, " +lon_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[2] );
+
+        SAFE_strcat( szPROJ4, " +x_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[3] );
+
+        SAFE_strcat( szPROJ4, " +y_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[4] );
     }
-    
-    else if( EQUAL(papszMethods[0],"Oblique Stereographic") 
+
+    else if( EQUAL(papszMethods[0],"Oblique Stereographic")
              && CSLCount(papszMethods) > 5 )
     {
         /* there is an option to produce +lat_ts, which we ignore */
-        
-        strcat( szPROJ4, "+proj=stere" );
 
-        strcat( szPROJ4, " +lat_0=45" );
+        SAFE_strcat( szPROJ4, "+proj=stere" );
 
-        strcat( szPROJ4, " +lat_ts=" );
-        strcat( szPROJ4, papszMethods[1] );
-        
-        strcat( szPROJ4, " +lon_0=" );
-        strcat( szPROJ4, papszMethods[2] );
-        
-        strcat( szPROJ4, " +k=" );
-        strcat( szPROJ4, papszMethods[3] );
+        SAFE_strcat( szPROJ4, " +lat_0=45" );
 
-        strcat( szPROJ4, " +x_0=" );
-        strcat( szPROJ4, papszMethods[4] );
+        SAFE_strcat( szPROJ4, " +lat_ts=" );
+        SAFE_strcat( szPROJ4, papszMethods[1] );
 
-        strcat( szPROJ4, " +y_0=" );
-        strcat( szPROJ4, papszMethods[5] );
+        SAFE_strcat( szPROJ4, " +lon_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[2] );
+
+        SAFE_strcat( szPROJ4, " +k=" );
+        SAFE_strcat( szPROJ4, papszMethods[3] );
+
+        SAFE_strcat( szPROJ4, " +x_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[4] );
+
+        SAFE_strcat( szPROJ4, " +y_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[5] );
     }
-    
+
     else if( EQUAL(papszMethods[0],"Polar Stereographic")
              && CSLCount(papszMethods) > 5 )
     {
         /* there is an option to produce +lat_ts, which we ignore */
-        
-        strcat( szPROJ4, "+proj=stere" );
 
-        strcat( szPROJ4, " +lat_0=90" );
+        SAFE_strcat( szPROJ4, "+proj=stere" );
 
-        strcat( szPROJ4, " +lat_ts=" );
-        strcat( szPROJ4, papszMethods[1] );
-        
-        strcat( szPROJ4, " +lon_0=" );
-        strcat( szPROJ4, papszMethods[2] );
-        
-        strcat( szPROJ4, " +k=" );
-        strcat( szPROJ4, papszMethods[3] );
+        SAFE_strcat( szPROJ4, " +lat_0=90" );
 
-        strcat( szPROJ4, " +x_0=" );
-        strcat( szPROJ4, papszMethods[4] );
+        SAFE_strcat( szPROJ4, " +lat_ts=" );
+        SAFE_strcat( szPROJ4, papszMethods[1] );
 
-        strcat( szPROJ4, " +y_0=" );
-        strcat( szPROJ4, papszMethods[5] );
+        SAFE_strcat( szPROJ4, " +lon_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[2] );
+
+        SAFE_strcat( szPROJ4, " +k=" );
+        SAFE_strcat( szPROJ4, papszMethods[3] );
+
+        SAFE_strcat( szPROJ4, " +x_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[4] );
+
+        SAFE_strcat( szPROJ4, " +y_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[5] );
     }
-    
+
     else if( EQUAL(papszMethods[0],"Swiss Oblique Cylindrical")
              && CSLCount(papszMethods) > 4 )
     {
@@ -378,19 +381,19 @@ char *GXFGetMapProjectionAsPROJ4( GXFHandle hGXF )
            ObliqueMercator_Rosenmund, which GG's geotiff support just
            maps directly to +proj=omerc, though I find that questionable. */
 
-        strcat( szPROJ4, "+proj=omerc" );
+        SAFE_strcat( szPROJ4, "+proj=omerc" );
 
-        strcat( szPROJ4, " +lat_0=" );
-        strcat( szPROJ4, papszMethods[1] );
-        
-        strcat( szPROJ4, " +lonc=" );
-        strcat( szPROJ4, papszMethods[2] );
-        
-        strcat( szPROJ4, " +x_0=" );
-        strcat( szPROJ4, papszMethods[3] );
+        SAFE_strcat( szPROJ4, " +lat_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[1] );
 
-        strcat( szPROJ4, " +y_0=" );
-        strcat( szPROJ4, papszMethods[4] );
+        SAFE_strcat( szPROJ4, " +lonc=" );
+        SAFE_strcat( szPROJ4, papszMethods[2] );
+
+        SAFE_strcat( szPROJ4, " +x_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[3] );
+
+        SAFE_strcat( szPROJ4, " +y_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[4] );
     }
 
     else if( EQUAL(papszMethods[0],"Transverse Mercator")
@@ -400,22 +403,22 @@ char *GXFGetMapProjectionAsPROJ4( GXFHandle hGXF )
            ObliqueMercator_Rosenmund, which GG's geotiff support just
            maps directly to +proj=omerc, though I find that questionable. */
 
-        strcat( szPROJ4, "+proj=tmerc" );
-
-        strcat( szPROJ4, " +lat_0=" );
-        strcat( szPROJ4, papszMethods[1] );
-        
-        strcat( szPROJ4, " +lon_0=" );
-        strcat( szPROJ4, papszMethods[2] );
-        
-        strcat( szPROJ4, " +k=" );
-        strcat( szPROJ4, papszMethods[3] );
-        
-        strcat( szPROJ4, " +x_0=" );
-        strcat( szPROJ4, papszMethods[4] );
-
-        strcat( szPROJ4, " +y_0=" );
-        strcat( szPROJ4, papszMethods[5] );
+        SAFE_strcat( szPROJ4, "+proj=tmerc" );
+
+        SAFE_strcat( szPROJ4, " +lat_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[1] );
+
+        SAFE_strcat( szPROJ4, " +lon_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[2] );
+
+        SAFE_strcat( szPROJ4, " +k=" );
+        SAFE_strcat( szPROJ4, papszMethods[3] );
+
+        SAFE_strcat( szPROJ4, " +x_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[4] );
+
+        SAFE_strcat( szPROJ4, " +y_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[5] );
     }
 
     else if( EQUAL(papszMethods[0],"Transverse Mercator (South Oriented)")
@@ -425,74 +428,74 @@ char *GXFGetMapProjectionAsPROJ4( GXFHandle hGXF )
            normal, and I don't find any mention of it in Geotiff;s geo_ctrans.
            Translating as tmerc, but that is presumably wrong. */
 
-        strcat( szPROJ4, "+proj=tmerc" );
-
-        strcat( szPROJ4, " +lat_0=" );
-        strcat( szPROJ4, papszMethods[1] );
-        
-        strcat( szPROJ4, " +lon_0=" );
-        strcat( szPROJ4, papszMethods[2] );
-        
-        strcat( szPROJ4, " +k=" );
-        strcat( szPROJ4, papszMethods[3] );
-        
-        strcat( szPROJ4, " +x_0=" );
-        strcat( szPROJ4, papszMethods[4] );
-
-        strcat( szPROJ4, " +y_0=" );
-        strcat( szPROJ4, papszMethods[5] );
+        SAFE_strcat( szPROJ4, "+proj=tmerc" );
+
+        SAFE_strcat( szPROJ4, " +lat_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[1] );
+
+        SAFE_strcat( szPROJ4, " +lon_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[2] );
+
+        SAFE_strcat( szPROJ4, " +k=" );
+        SAFE_strcat( szPROJ4, papszMethods[3] );
+
+        SAFE_strcat( szPROJ4, " +x_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[4] );
+
+        SAFE_strcat( szPROJ4, " +y_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[5] );
     }
 
     else if( EQUAL(papszMethods[0],"*Equidistant Conic")
              && CSLCount(papszMethods) > 6 )
     {
-        strcat( szPROJ4, "+proj=eqdc" );
-
-        strcat( szPROJ4, " +lat_1=" );
-        strcat( szPROJ4, papszMethods[1] );
-        
-        strcat( szPROJ4, " +lat_2=" );
-        strcat( szPROJ4, papszMethods[2] );
-        
-        strcat( szPROJ4, " +lat_0=" );
-        strcat( szPROJ4, papszMethods[3] );
-        
-        strcat( szPROJ4, " +lon_0=" );
-        strcat( szPROJ4, papszMethods[4] );
-        
-        strcat( szPROJ4, " +x_0=" );
-        strcat( szPROJ4, papszMethods[5] );
-
-        strcat( szPROJ4, " +y_0=" );
-        strcat( szPROJ4, papszMethods[6] );
+        SAFE_strcat( szPROJ4, "+proj=eqdc" );
+
+        SAFE_strcat( szPROJ4, " +lat_1=" );
+        SAFE_strcat( szPROJ4, papszMethods[1] );
+
+        SAFE_strcat( szPROJ4, " +lat_2=" );
+        SAFE_strcat( szPROJ4, papszMethods[2] );
+
+        SAFE_strcat( szPROJ4, " +lat_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[3] );
+
+        SAFE_strcat( szPROJ4, " +lon_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[4] );
+
+        SAFE_strcat( szPROJ4, " +x_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[5] );
+
+        SAFE_strcat( szPROJ4, " +y_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[6] );
     }
 
-    else if( EQUAL(papszMethods[0],"*Polyconic") 
+    else if( EQUAL(papszMethods[0],"*Polyconic")
              && CSLCount(papszMethods) > 5 )
     {
-        strcat( szPROJ4, "+proj=poly" );
+        SAFE_strcat( szPROJ4, "+proj=poly" );
 
-        strcat( szPROJ4, " +lat_0=" );
-        strcat( szPROJ4, papszMethods[1] );
-        
-        strcat( szPROJ4, " +lon_0=" );
-        strcat( szPROJ4, papszMethods[2] );
+        SAFE_strcat( szPROJ4, " +lat_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[1] );
+
+        SAFE_strcat( szPROJ4, " +lon_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[2] );
 
 #ifdef notdef
         /*not supported by PROJ.4 */
-        strcat( szPROJ4, " +k=" );
-        strcat( szPROJ4, papszMethods[3] );
+        SAFE_strcat( szPROJ4, " +k=" );
+        SAFE_strcat( szPROJ4, papszMethods[3] );
 #endif
-        strcat( szPROJ4, " +x_0=" ); 
-        strcat( szPROJ4, papszMethods[4] );
+        SAFE_strcat( szPROJ4, " +x_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[4] );
 
-        strcat( szPROJ4, " +y_0=" );
-        strcat( szPROJ4, papszMethods[5] );
+        SAFE_strcat( szPROJ4, " +y_0=" );
+        SAFE_strcat( szPROJ4, papszMethods[5] );
     }
 
     else
     {
-        strcat( szPROJ4, "unknown" );
+        SAFE_strcat( szPROJ4, "unknown" );
     }
 
     CSLDestroy( papszMethods );
@@ -505,35 +508,35 @@ char *GXFGetMapProjectionAsPROJ4( GXFHandle hGXF )
     if( CSLCount(psGXF->papszMapProjection) > 1 )
     {
         char	**papszTokens;
-        
+
         if( strlen(psGXF->papszMapProjection[1]) > 80 )
             return CPLStrdup("");
-        
+
         papszTokens = CSLTokenizeStringComplex(psGXF->papszMapProjection[1],
                                                ",", TRUE, TRUE );
 
 
         if( EQUAL(papszTokens[0],"WGS 84") )
-            strcat( szPROJ4, " +ellps=WGS84" );
+            SAFE_strcat( szPROJ4, " +ellps=WGS84" );
         else if( EQUAL(papszTokens[0],"*WGS 72") )
-            strcat( szPROJ4, " +ellps=WGS72" );
+            SAFE_strcat( szPROJ4, " +ellps=WGS72" );
         else if( EQUAL(papszTokens[0],"*WGS 66") )
-            strcat( szPROJ4, " +ellps=WGS66" );
+            SAFE_strcat( szPROJ4, " +ellps=WGS66" );
         else if( EQUAL(papszTokens[0],"*WGS 60") )
-            strcat( szPROJ4, " +ellps=WGS60" );
+            SAFE_strcat( szPROJ4, " +ellps=WGS60" );
         else if( EQUAL(papszTokens[0],"Clarke 1866") )
-            strcat( szPROJ4, " +ellps=clrk66" );
+            SAFE_strcat( szPROJ4, " +ellps=clrk66" );
         else if( EQUAL(papszTokens[0],"Clarke 1880") )
-            strcat( szPROJ4, " +ellps=clrk80" );
+            SAFE_strcat( szPROJ4, " +ellps=clrk80" );
         else if( EQUAL(papszTokens[0],"GRS 1980") )
-            strcat( szPROJ4, " +ellps=GRS80" );
+            SAFE_strcat( szPROJ4, " +ellps=GRS80" );
         else if( CSLCount( papszTokens ) > 2 )
         {
-            sprintf( szPROJ4+strlen(szPROJ4),
+            snprintf( szPROJ4+strlen(szPROJ4), sizeof(szPROJ4)-strlen(szPROJ4),
                      " +a=%s +e=%s",
                      papszTokens[1], papszTokens[2] );
         }
-        
+
         CSLDestroy(papszTokens);
     }
 
@@ -544,34 +547,34 @@ char *GXFGetMapProjectionAsPROJ4( GXFHandle hGXF )
     {
         if( EQUAL(psGXF->pszUnitName,"ft") )
         {
-            strcat( szPROJ4, " +units=ft" );
+            SAFE_strcat( szPROJ4, " +units=ft" );
         }
         else if( EQUAL(psGXF->pszUnitName,"ftUS") )
         {
-            strcat( szPROJ4, " +units=us-ft" );
+            SAFE_strcat( szPROJ4, " +units=us-ft" );
         }
         else if( EQUAL(psGXF->pszUnitName,"km") )
         {
-            strcat( szPROJ4, " +units=km" );
+            SAFE_strcat( szPROJ4, " +units=km" );
         }
         else if( EQUAL(psGXF->pszUnitName,"mm") )
         {
-            strcat( szPROJ4, " +units=mm" );
+            SAFE_strcat( szPROJ4, " +units=mm" );
         }
         else if( EQUAL(psGXF->pszUnitName,"in") )
         {
-            strcat( szPROJ4, " +units=in" );
+            SAFE_strcat( szPROJ4, " +units=in" );
         }
         else if( EQUAL(psGXF->pszUnitName,"ftInd") )
         {
-            strcat( szPROJ4, " +units=ind-ft" );
+            SAFE_strcat( szPROJ4, " +units=ind-ft" );
         }
         else if( EQUAL(psGXF->pszUnitName,"lk") )
         {
-            strcat( szPROJ4, " +units=link" );
+            SAFE_strcat( szPROJ4, " +units=link" );
         }
     }
-    
+
     return( CPLStrdup( szPROJ4 ) );
 }
 
diff --git a/frmts/gxf/gxfdataset.cpp b/frmts/gxf/gxfdataset.cpp
index 47e420b..8ca0780 100644
--- a/frmts/gxf/gxfdataset.cpp
+++ b/frmts/gxf/gxfdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gxfdataset.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: gxfdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  GXF Reader
  * Purpose:  GDAL binding for GXF reader.
@@ -28,18 +28,11 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gxfopen.h"
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
+#include "gxfopen.h"
 
-CPL_CVSID("$Id: gxfdataset.cpp 27745 2014-09-27 16:38:57Z goatbar $");
-
-#ifndef PI
-#  define PI 3.14159265358979323846
-#endif
-
-CPL_C_START
-void	GDALRegister_GXF(void);
-CPL_C_END
+CPL_CVSID("$Id: gxfdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -52,7 +45,7 @@ class GXFRasterBand;
 class GXFDataset : public GDALPamDataset
 {
     friend class GXFRasterBand;
-    
+
     GXFHandle	hGXF;
 
     char	*pszProjection;
@@ -62,7 +55,7 @@ class GXFDataset : public GDALPamDataset
   public:
                 GXFDataset();
 		~GXFDataset();
-    
+
     static GDALDataset *Open( GDALOpenInfo * );
 
     CPLErr 	GetGeoTransform( double * padfTransform );
@@ -78,7 +71,7 @@ class GXFDataset : public GDALPamDataset
 class GXFRasterBand : public GDALPamRasterBand
 {
     friend class GXFDataset;
-    
+
   public:
 
     		GXFRasterBand( GXFDataset *, int );
@@ -92,13 +85,13 @@ class GXFRasterBand : public GDALPamRasterBand
 /*                           GXFRasterBand()                            */
 /************************************************************************/
 
-GXFRasterBand::GXFRasterBand( GXFDataset *poDS, int nBand )
+GXFRasterBand::GXFRasterBand( GXFDataset *poDSIn, int nBandIn )
 
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
-    
-    eDataType = poDS->eDataType;
+    poDS = poDSIn;
+    nBand = nBandIn;
+
+    eDataType = poDSIn->eDataType;
 
     nBlockXSize = poDS->GetRasterXSize();
     nBlockYSize = 1;
@@ -142,17 +135,17 @@ CPLErr GXFRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
         if( padfBuffer == NULL )
             return CE_Failure;
         eErr = GXFGetScanline( poGXF_DS->hGXF, nBlockYOff, padfBuffer );
-        
+
         for( i = 0; i < nBlockXSize; i++ )
             pafBuffer[i] = (float) padfBuffer[i];
-    
+
         CPLFree( padfBuffer );
     }
     else if (eDataType == GDT_Float64)
         eErr = GXFGetScanline( poGXF_DS->hGXF, nBlockYOff, (double*)pImage );
     else
         eErr = CE_Failure;
-    
+
     return eErr;
 }
 
@@ -205,8 +198,8 @@ CPLErr GXFDataset::GetGeoTransform( double * padfTransform )
     if( eErr != CE_None )
         return eErr;
 
-    // Transform to radians. 
-    dfRotation = (dfRotation / 360.0) * 2 * PI;
+    // Transform to radians.
+    dfRotation = (dfRotation / 360.0) * 2 * M_PI;
 
     padfTransform[1] = dfXSize * cos(dfRotation);
     padfTransform[2] = dfYSize * sin(dfRotation);
@@ -216,7 +209,7 @@ CPLErr GXFDataset::GetGeoTransform( double * padfTransform )
     // take into account that GXF is point or center of pixel oriented.
     padfTransform[0] = dfXOrigin - 0.5*padfTransform[1] - 0.5*padfTransform[2];
     padfTransform[3] = dfYOrigin - 0.5*padfTransform[4] - 0.5*padfTransform[5];
-    
+
     return CE_None;
 }
 
@@ -237,9 +230,9 @@ const char *GXFDataset::GetProjectionRef()
 GDALDataset *GXFDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    GXFHandle	hGXF;
+    GXFHandle	l_hGXF;
     int		i, bFoundKeyword, bFoundIllegal;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Before trying GXFOpen() we first verify that there is at        */
 /*      least one "\n#keyword" type signature in the first chunk of     */
@@ -256,11 +249,11 @@ GDALDataset *GXFDataset::Open( GDALOpenInfo * poOpenInfo )
              || poOpenInfo->pabyHeader[i] == 13)
             && poOpenInfo->pabyHeader[i+1] == '#' )
         {
-            if( strncmp((const char*)poOpenInfo->pabyHeader + i + 2, "include", strlen("include")) == 0 )
+            if( STARTS_WITH((const char*)poOpenInfo->pabyHeader + i + 2, "include") )
                 return NULL;
-            if( strncmp((const char*)poOpenInfo->pabyHeader + i + 2, "define", strlen("define")) == 0 )
+            if( STARTS_WITH((const char*)poOpenInfo->pabyHeader + i + 2, "define") )
                 return NULL;
-            if( strncmp((const char*)poOpenInfo->pabyHeader + i + 2, "ifdef", strlen("ifdef")) == 0 )
+            if( STARTS_WITH((const char*)poOpenInfo->pabyHeader + i + 2, "ifdef") )
                 return NULL;
             bFoundKeyword = TRUE;
         }
@@ -273,8 +266,7 @@ GDALDataset *GXFDataset::Open( GDALOpenInfo * poOpenInfo )
 
     if( !bFoundKeyword || bFoundIllegal )
         return NULL;
-    
-    
+
 /* -------------------------------------------------------------------- */
 /*      At this point it is plausible that this is a GXF file, but      */
 /*      we also now verify that there is a #GRID keyword before         */
@@ -289,12 +281,12 @@ GDALDataset *GXFDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
 
     char *pszBigBuf = (char *) CPLMalloc(BIGBUFSIZE);
-    nBytesRead = VSIFRead( pszBigBuf, 1, BIGBUFSIZE, fp );
+    nBytesRead = static_cast<int>(VSIFRead( pszBigBuf, 1, BIGBUFSIZE, fp ));
     VSIFClose( fp );
 
     for( i = 0; i < nBytesRead - 5 && !bGotGrid; i++ )
     {
-        if( pszBigBuf[i] == '#' && EQUALN(pszBigBuf+i+1,"GRID",4) )
+        if( pszBigBuf[i] == '#' && STARTS_WITH_CI(pszBigBuf+i+1, "GRID") )
             bGotGrid = TRUE;
     }
 
@@ -306,31 +298,31 @@ GDALDataset *GXFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Try opening the dataset.                                        */
 /* -------------------------------------------------------------------- */
-    
-    hGXF = GXFOpen( poOpenInfo->pszFilename );
-    
-    if( hGXF == NULL )
+
+    l_hGXF = GXFOpen( poOpenInfo->pszFilename );
+
+    if( l_hGXF == NULL )
         return( NULL );
-        
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
-        GXFClose(hGXF);
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        GXFClose(l_hGXF);
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The GXF driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
     GXFDataset 	*poDS;
 
     poDS = new GXFDataset();
-    
+
     const char* pszGXFDataType = CPLGetConfigOption("GXF_DATATYPE", "Float32");
     GDALDataType eDT = GDALGetDataTypeByName(pszGXFDataType);
     if (!(eDT == GDT_Float32 || eDT == GDT_Float64))
@@ -340,25 +332,25 @@ GDALDataset *GXFDataset::Open( GDALOpenInfo * poOpenInfo )
         eDT = GDT_Float32;
     }
 
-    poDS->hGXF = hGXF;
+    poDS->hGXF = l_hGXF;
     poDS->eDataType = eDT;
-    
+
 /* -------------------------------------------------------------------- */
 /*	Establish the projection.					*/
 /* -------------------------------------------------------------------- */
-    poDS->pszProjection = GXFGetMapProjectionAsOGCWKT( hGXF );
+    poDS->pszProjection = GXFGetMapProjectionAsOGCWKT( l_hGXF );
 
 /* -------------------------------------------------------------------- */
 /*      Capture some information from the file that is of interest.     */
 /* -------------------------------------------------------------------- */
-    GXFGetRawInfo( hGXF, &(poDS->nRasterXSize), &(poDS->nRasterYSize), NULL,
+    GXFGetRawInfo( l_hGXF, &(poDS->nRasterXSize), &(poDS->nRasterYSize), NULL,
                    NULL, NULL, &(poDS->dfNoDataValue) );
 
     if  (poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0)
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Invalid dimensions : %d x %d", 
-                  poDS->nRasterXSize, poDS->nRasterYSize); 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Invalid dimensions : %d x %d",
+                  poDS->nRasterXSize, poDS->nRasterYSize);
         delete poDS;
         return NULL;
     }
@@ -390,22 +382,19 @@ GDALDataset *GXFDataset::Open( GDALOpenInfo * poOpenInfo )
 void GDALRegister_GXF()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "GXF" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "GXF" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "GXF" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "GeoSoft Grid Exchange Format" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#GXF" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gxf" );
-
-        poDriver->pfnOpen = GXFDataset::Open;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "GXF" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "GeoSoft Grid Exchange Format" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#GXF" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gxf" );
+
+    poDriver->pfnOpen = GXFDataset::Open;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/gxf/gxfopen.c b/frmts/gxf/gxfopen.c
index 40d46ab..b0de5a7 100644
--- a/frmts/gxf/gxfopen.c
+++ b/frmts/gxf/gxfopen.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gxfopen.c 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: gxfopen.c 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  GXF Reader
  * Purpose:  Majority of Geosoft GXF reading code.
@@ -32,7 +32,7 @@
 #include <ctype.h>
 #include "gxfopen.h"
 
-CPL_CVSID("$Id: gxfopen.c 27044 2014-03-16 23:41:27Z rouault $");
+CPL_CVSID("$Id: gxfopen.c 33720 2016-03-15 00:39:53Z goatbar $");
 
 
 /* this is also defined in gdal.h which we avoid in this separable component */
@@ -56,7 +56,7 @@ static char **GXFReadHeaderValue( FILE * fp, char * pszHTitle )
     int		i;
     int     nLineCount = 0, nReturnLineCount = 0;
     int     bContinuedLine = FALSE;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Try to read a line.  If we fail or if this isn't a proper       */
 /*      header value then return the failure.                           */
@@ -101,7 +101,6 @@ static char **GXFReadHeaderValue( FILE * fp, char * pszHTitle )
             strcpy( pszHTitle, "#EOF" );
             return( NULL );
         }
-        i = 0;
     }
 
 /* -------------------------------------------------------------------- */
@@ -111,29 +110,34 @@ static char **GXFReadHeaderValue( FILE * fp, char * pszHTitle )
     do {
         int		nNextChar;
         char		*pszTrimmedLine;
+        size_t      nLen = strlen(pszLine);
 
         /* Lines are supposed to be limited to 80 characters */
-        if( strlen(pszLine) > 1024 )
+        if( nLen > 1024 )
         {
             CSLDestroy(papszReturn);
             return NULL;
         }
-        
+
         pszTrimmedLine = CPLStrdup( pszLine );
 
-        for( i = strlen(pszLine)-1; i >= 0 && pszLine[i] == ' '; i-- ) 
+        for( i = ((int)nLen)-1; i >= 0 && pszLine[i] == ' '; i-- )
             pszTrimmedLine[i] = '\0';
 
         if( bContinuedLine )
         {
-            char* pszTmp = (char*) VSIMalloc((strlen(papszReturn[nReturnLineCount-1]) - 1) + strlen(pszTrimmedLine) + 1);
+            char* pszTmp = (char*) VSIMalloc(strlen(papszReturn[nReturnLineCount-1]) + strlen(pszTrimmedLine) + 1);
             if( pszTmp == NULL )
             {
                 CSLDestroy(papszReturn);
+                CPLFree(pszTrimmedLine);
                 return NULL;
             }
             strcpy(pszTmp, papszReturn[nReturnLineCount-1]);
-            strcpy(pszTmp + (strlen(papszReturn[nReturnLineCount-1]) - 1), pszTrimmedLine);
+            if( pszTrimmedLine[0] == '\0' )
+                pszTmp[strlen(papszReturn[nReturnLineCount-1]) - 1] = 0;
+            else
+                strcpy(pszTmp + (strlen(papszReturn[nReturnLineCount-1]) - 1), pszTrimmedLine);
             CPLFree(papszReturn[nReturnLineCount-1]);
             papszReturn[nReturnLineCount-1] = pszTmp;
         }
@@ -145,12 +149,16 @@ static char **GXFReadHeaderValue( FILE * fp, char * pszHTitle )
 
         /* Is it a continued line ? */
         bContinuedLine = ( i >= 0 && pszTrimmedLine[i] == '\\' );
-        
+
         CPLFree( pszTrimmedLine );
-        
+
         nNextChar = VSIFGetc( fp );
-        VSIUngetc( nNextChar, fp );
-        
+        if( VSIUngetc( nNextChar, fp ) == EOF)
+        {
+            CSLDestroy(papszReturn);
+            return NULL;
+        }
+
         if( nNextChar == '#' )
             pszLine = NULL;
         else
@@ -216,70 +224,70 @@ GXFHandle GXFOpen( const char * pszFilename )
 
     psGXF->dfUnitToMeter = 1.0;
     psGXF->pszTitle = VSIStrdup("");
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read the header, one line at a time.                            */
 /* -------------------------------------------------------------------- */
     while( (papszList = GXFReadHeaderValue( fp, szTitle)) != NULL && nHeaderCount < MAX_HEADER_COUNT )
     {
-        if( EQUALN(szTitle,"#TITL",5) )
+        if( STARTS_WITH_CI(szTitle, "#TITL") )
         {
             CPLFree( psGXF->pszTitle );
             psGXF->pszTitle = CPLStrdup( papszList[0] );
         }
-        else if( EQUALN(szTitle,"#POIN",5) )
+        else if( STARTS_WITH_CI(szTitle, "#POIN") )
         {
             psGXF->nRawXSize = atoi(papszList[0]);
         }
-        else if( EQUALN(szTitle,"#ROWS",5) )
+        else if( STARTS_WITH_CI(szTitle, "#ROWS") )
         {
             psGXF->nRawYSize = atoi(papszList[0]);
         }
-        else if( EQUALN(szTitle,"#PTSE",5) )
+        else if( STARTS_WITH_CI(szTitle, "#PTSE") )
         {
             psGXF->dfXPixelSize = CPLAtof(papszList[0]);
         }
-        else if( EQUALN(szTitle,"#RWSE",5) )
+        else if( STARTS_WITH_CI(szTitle, "#RWSE") )
         {
             psGXF->dfYPixelSize = CPLAtof(papszList[0]);
         }
-        else if( EQUALN(szTitle,"#DUMM",5) )
+        else if( STARTS_WITH_CI(szTitle, "#DUMM") )
         {
             memset( psGXF->szDummy, 0, sizeof(psGXF->szDummy));
             strncpy( psGXF->szDummy, papszList[0], sizeof(psGXF->szDummy) - 1);
             psGXF->dfSetDummyTo = CPLAtof(papszList[0]);
         }
-        else if( EQUALN(szTitle,"#XORI",5) )
+        else if( STARTS_WITH_CI(szTitle, "#XORI") )
         {
             psGXF->dfXOrigin = CPLAtof(papszList[0]);
         }
-        else if( EQUALN(szTitle,"#YORI",5) )
+        else if( STARTS_WITH_CI(szTitle, "#YORI") )
         {
             psGXF->dfYOrigin = CPLAtof(papszList[0]);
         }
-        else if( EQUALN(szTitle,"#ZMIN",5) )
+        else if( STARTS_WITH_CI(szTitle, "#ZMIN") )
         {
             psGXF->dfZMinimum = CPLAtof(papszList[0]);
         }
-        else if( EQUALN(szTitle,"#ZMAX",5) )
+        else if( STARTS_WITH_CI(szTitle, "#ZMAX") )
         {
             psGXF->dfZMaximum = CPLAtof(papszList[0]);
         }
-        else if( EQUALN(szTitle,"#SENS",5) )
+        else if( STARTS_WITH_CI(szTitle, "#SENS") )
         {
             psGXF->nSense = atoi(papszList[0]);
         }
-        else if( EQUALN(szTitle,"#MAP_PROJECTION",8) )
+        else if( STARTS_WITH_CI(szTitle,"#MAP_PROJECTION") )
         {
             psGXF->papszMapProjection = papszList;
             papszList = NULL;
         }
-        else if( EQUALN(szTitle,"#MAP_D",5) )
+        else if( STARTS_WITH_CI(szTitle,"#MAP_D") )
         {
             psGXF->papszMapDatumTransform = papszList;
             papszList = NULL;
         }
-        else if( EQUALN(szTitle,"#UNIT",5) )
+        else if( STARTS_WITH_CI(szTitle, "#UNIT") )
         {
             char	**papszFields;
 
@@ -296,7 +304,7 @@ GXFHandle GXFOpen( const char * pszFilename )
 
             CSLDestroy( papszFields );
         }
-        else if( EQUALN(szTitle,"#TRAN",5) )
+        else if( STARTS_WITH_CI(szTitle, "#TRAN") )
         {
             char	**papszFields;
 
@@ -314,7 +322,7 @@ GXFHandle GXFOpen( const char * pszFilename )
 
             CSLDestroy( papszFields );
         }
-        else if( EQUALN(szTitle,"#GTYPE",5) )
+        else if( STARTS_WITH_CI(szTitle,"#GTYPE") )
         {
             psGXF->nGType = atoi(papszList[0]);
         }
@@ -323,17 +331,19 @@ GXFHandle GXFOpen( const char * pszFilename )
         nHeaderCount ++;
     }
 
+    CSLDestroy( papszList );
+
 /* -------------------------------------------------------------------- */
 /*      Did we find the #GRID?                                          */
 /* -------------------------------------------------------------------- */
-    if( !EQUALN(szTitle,"#GRID",5) )
+    if( !STARTS_WITH_CI(szTitle, "#GRID") )
     {
         GXFClose( psGXF );
         CPLError( CE_Failure, CPLE_WrongFormat,
                   "Didn't parse through to #GRID successfully in.\n"
                   "file `%s'.\n",
                   pszFilename );
-        
+
         return NULL;
     }
 
@@ -367,7 +377,7 @@ GXFHandle GXFOpen( const char * pszFilename )
         psGXF->dfZMaximum = (psGXF->dfZMaximum * psGXF->dfTransformScale)
             			+ psGXF->dfTransformOffset;
     }
-    
+
     return( (GXFHandle) psGXF );
 }
 
@@ -407,6 +417,7 @@ void GXFClose( GXFHandle hGXF )
 /*      values have to be recognised outside this function.             */
 /************************************************************************/
 
+static
 double GXFParseBase90( GXFInfo_t * psGXF, const char * pszText,
                        int bScale )
 
@@ -419,7 +430,7 @@ double GXFParseBase90( GXFInfo_t * psGXF, const char * pszText,
         i++;
     }
 
-    if( bScale ) 
+    if( bScale )
         return( (nValue * psGXF->dfTransformScale) + psGXF->dfTransformOffset);
     else
         return( nValue );
@@ -430,14 +441,15 @@ double GXFParseBase90( GXFInfo_t * psGXF, const char * pszText,
 /*                       GXFReadRawScanlineFrom()                       */
 /************************************************************************/
 
-static int GXFReadRawScanlineFrom( GXFInfo_t * psGXF, long iOffset,
+static CPLErr GXFReadRawScanlineFrom( GXFInfo_t * psGXF, long iOffset,
                                    long * pnNewOffset, double * padfLineBuf )
 
 {
     const char	*pszLine;
     int		nValuesRead = 0, nValuesSought = psGXF->nRawXSize;
-    
-    VSIFSeek( psGXF->fp, iOffset, SEEK_SET );
+
+    if( VSIFSeek( psGXF->fp, iOffset, SEEK_SET ) != 0 )
+        return CE_Failure;
 
     while( nValuesRead < nValuesSought )
     {
@@ -455,7 +467,7 @@ static int GXFReadRawScanlineFrom( GXFInfo_t * psGXF, long iOffset,
             while( *pszLine != '\0' && nValuesRead < nValuesSought )
             {
                 int		i;
-                
+
                 /* skip leading white space */
                 for( ; isspace((unsigned char)*pszLine); pszLine++ ) {}
 
@@ -481,7 +493,8 @@ static int GXFReadRawScanlineFrom( GXFInfo_t * psGXF, long iOffset,
 /* -------------------------------------------------------------------- */
         else
         {
-            int nLineLen = (int)strlen(pszLine);
+            size_t nLineLenOri = strlen(pszLine);
+            int nLineLen = (int)nLineLenOri;
 
             while( *pszLine != '\0' && nValuesRead < nValuesSought )
             {
@@ -504,25 +517,27 @@ static int GXFReadRawScanlineFrom( GXFInfo_t * psGXF, long iOffset,
                         pszLine = CPLReadLine( psGXF->fp );
                         if( pszLine == NULL )
                             return CE_Failure;
-                        nLineLen = (int)strlen(pszLine);
+                        nLineLenOri = strlen(pszLine);
+                        nLineLen = (int)nLineLenOri;
                         if( nLineLen < psGXF->nGType )
                             return CE_Failure;
                     }
-                    
+
                     nCount = (int) GXFParseBase90( psGXF, pszLine, FALSE);
                     pszLine += psGXF->nGType;
                     nLineLen -= psGXF->nGType;
-                    
+
                     if( nLineLen < psGXF->nGType )
                     {
                         pszLine = CPLReadLine( psGXF->fp );
                         if( pszLine == NULL )
                             return CE_Failure;
-                        nLineLen = (int)strlen(pszLine);
+                        nLineLenOri = strlen(pszLine);
+                        nLineLen = (int)nLineLenOri;
                         if( nLineLen < psGXF->nGType )
                             return CE_Failure;
                     }
-                    
+
                     if( *pszLine == '!' )
                         dfValue = psGXF->dfSetDummyTo;
                     else
@@ -533,7 +548,7 @@ static int GXFReadRawScanlineFrom( GXFInfo_t * psGXF, long iOffset,
                         CPLError(CE_Failure, CPLE_AppDefined, "Wrong count value");
                         return CE_Failure;
                     }
-                    
+
                     for( i=0; i < nCount && nValuesRead < nValuesSought; i++ )
                         padfLineBuf[nValuesRead++] = dfValue;
                 }
@@ -616,7 +631,7 @@ CPLErr GXFGetScanline( GXFHandle hGXF, int iScanline, double * padfLineBuf )
     {
         int	i;
         double	dfTemp;
-        
+
         for( i = psGXF->nRawXSize / 2 - 1; i >= 0; i-- )
         {
             dfTemp = padfLineBuf[i];
@@ -644,7 +659,7 @@ CPLErr GXFGetScanline( GXFHandle hGXF, int iScanline, double * padfLineBuf )
  *
  * @param hGXF the GXF file handle, as returned from GXFOpen().
  * @param iScanline the scanline to read, zero is the first scanline in the
- * file. 
+ * file.
  * @param padfLineBuf a buffer of doubles into which the scanline pixel
  * values are read.  This must be at least as long as a scanline.
  *
@@ -655,8 +670,8 @@ CPLErr GXFGetRawScanline( GXFHandle hGXF, int iScanline, double * padfLineBuf )
 
 {
     GXFInfo_t	*psGXF = (GXFInfo_t *) hGXF;
-    CPLErr	nErr;
-    
+    CPLErr	eErr;
+
 /* -------------------------------------------------------------------- */
 /*      Validate scanline.                                              */
 /* -------------------------------------------------------------------- */
@@ -669,22 +684,22 @@ CPLErr GXFGetRawScanline( GXFHandle hGXF, int iScanline, double * padfLineBuf )
     }
 
 /* -------------------------------------------------------------------- */
-/*      If we don't have the requested scanline, fetch preceeding       */
+/*      If we don't have the requested scanline, fetch preceding        */
 /*      scanlines to find the pointer to this scanline.                 */
 /* -------------------------------------------------------------------- */
     if( psGXF->panRawLineOffset[iScanline] == 0 )
     {
         int		i;
-        
+
         CPLAssert( iScanline > 0 );
 
         for( i = 0; i < iScanline; i++ )
         {
             if( psGXF->panRawLineOffset[i+1] == 0 )
             {
-                nErr = GXFGetRawScanline( hGXF, i, padfLineBuf );
-                if( nErr != CE_None )
-                    return( nErr );
+                eErr = GXFGetRawScanline( hGXF, i, padfLineBuf );
+                if( eErr != CE_None )
+                    return( eErr );
             }
         }
     }
@@ -692,12 +707,12 @@ CPLErr GXFGetRawScanline( GXFHandle hGXF, int iScanline, double * padfLineBuf )
 /* -------------------------------------------------------------------- */
 /*      Get this scanline, and update the offset for the next line.     */
 /* -------------------------------------------------------------------- */
-    nErr = (CPLErr)
+    eErr =
         GXFReadRawScanlineFrom( psGXF, psGXF->panRawLineOffset[iScanline],
                                 psGXF->panRawLineOffset+iScanline+1,
                                 padfLineBuf );
 
-    return nErr;
+    return eErr;
 }
 
 /************************************************************************/
@@ -714,7 +729,6 @@ static void GXFScanForZMinMax( GXFHandle hGXF )
     GXFInfo_t	*psGXF = (GXFInfo_t *) hGXF;
     int		iLine, iPixel;
     double	*padfScanline;
-    
 
     padfScanline = (double *) VSICalloc(sizeof(double),psGXF->nRawXSize);
     if( padfScanline == NULL )
@@ -784,7 +798,7 @@ static void GXFScanForZMinMax( GXFHandle hGXF )
  * in order to establish them.  This can be expensive.
  *
  * If no #DUMMY value was specified in the file, a default of -1e12 is used.
- * 
+ *
  * @param hGXF handle to GXF file returned by GXFOpen().
  * @param pnXSize int to be set with the width of the raw raster.  May be NULL.
  * @param pnYSize int to be set with the height of the raw raster. May be NULL.
@@ -793,7 +807,7 @@ static void GXFScanForZMinMax( GXFHandle hGXF )
  * @param pdfZMax double to set with minimum raster value, may be NULL.
  * @param pdfDummy double to set with dummy (nodata / invalid data) pixel
  * value.
- */ 
+ */
 
 CPLErr GXFGetRawInfo( GXFHandle hGXF, int *pnXSize, int *pnYSize,
                       int * pnSense, double * pdfZMin, double * pdfZMax,
@@ -816,7 +830,7 @@ CPLErr GXFGetRawInfo( GXFHandle hGXF, int *pnXSize, int *pnYSize,
     {
         GXFScanForZMinMax( hGXF );
     }
-    
+
     if( pdfZMin != NULL )
         *pdfZMin = psGXF->dfZMinimum;
 
@@ -834,15 +848,15 @@ CPLErr GXFGetRawInfo( GXFHandle hGXF, int *pnXSize, int *pnYSize,
 /************************************************************************/
 
 /**
- * Return the lines related to the map projection.  It is up to   
- * the caller to parse them and interprete.  The return result    
+ * Return the lines related to the map projection.  It is up to
+ * the caller to parse them and interpret.  The return result
  * will be NULL if no #MAP_PROJECTION line was found in the header.
- * 
+ *
  * @param hGXF the GXF file handle.
  *
  * @return a NULL terminated array of string pointers containing the
  * projection, or NULL.  The strings remained owned by the GXF API, and
- * should not be modified or freed by the caller.  
+ * should not be modified or freed by the caller.
  */
 
 char **GXFGetMapProjection( GXFHandle hGXF )
@@ -856,15 +870,15 @@ char **GXFGetMapProjection( GXFHandle hGXF )
 /************************************************************************/
 
 /**
- * Return the lines related to the datum transformation.  It is up to   
- * the caller to parse them and interpret.  The return result    
+ * Return the lines related to the datum transformation.  It is up to
+ * the caller to parse them and interpret.  The return result
  * will be NULL if no #MAP_DATUM_TRANSFORM line was found in the header.
- * 
+ *
  * @param hGXF the GXF file handle.
  *
  * @return a NULL terminated array of string pointers containing the
  * datum, or NULL.  The strings remained owned by the GXF API, and
- * should not be modified or freed by the caller.  
+ * should not be modified or freed by the caller.
  */
 
 char **GXFGetMapDatumTransform( GXFHandle hGXF )
@@ -901,7 +915,7 @@ char **GXFGetMapDatumTransform( GXFHandle hGXF )
  * @return Returns CE_None if successful, or CE_Failure if no posiitioning
  * information was found in the file.
  */
- 
+
 
 CPLErr GXFGetRawPosition( GXFHandle hGXF,
                           double * pdfXOrigin, double * pdfYOrigin,
@@ -910,7 +924,7 @@ CPLErr GXFGetRawPosition( GXFHandle hGXF,
 
 {
     GXFInfo_t	*psGXF = (GXFInfo_t *) hGXF;
-    
+
     if( pdfXOrigin != NULL )
         *pdfXOrigin = psGXF->dfXOrigin;
     if( pdfYOrigin != NULL )
@@ -960,7 +974,7 @@ CPLErr GXFGetRawPosition( GXFHandle hGXF,
  * @return Returns CE_None if successful, or CE_Failure if no posiitioning
  * information was found in the file.
  */
- 
+
 
 CPLErr GXFGetPosition( GXFHandle hGXF,
                        double * pdfXOrigin, double * pdfYOrigin,
@@ -979,7 +993,7 @@ CPLErr GXFGetPosition( GXFHandle hGXF,
         dfCXPixelSize = psGXF->dfXPixelSize;
         dfCYPixelSize = psGXF->dfYPixelSize;
         break;
-        
+
       case GXFS_UR_LEFT:
         dfCXOrigin = psGXF->dfXOrigin
             	     - (psGXF->nRawXSize-1) * psGXF->dfXPixelSize;
@@ -987,7 +1001,7 @@ CPLErr GXFGetPosition( GXFHandle hGXF,
         dfCXPixelSize = psGXF->dfXPixelSize;
         dfCYPixelSize = psGXF->dfYPixelSize;
         break;
-        
+
       case GXFS_LL_RIGHT:
         dfCXOrigin = psGXF->dfXOrigin;
         dfCYOrigin = psGXF->dfYOrigin
@@ -995,7 +1009,7 @@ CPLErr GXFGetPosition( GXFHandle hGXF,
         dfCXPixelSize = psGXF->dfXPixelSize;
         dfCYPixelSize = psGXF->dfYPixelSize;
         break;
-        
+
       case GXFS_LR_LEFT:
         dfCXOrigin = psGXF->dfXOrigin
             	     - (psGXF->nRawXSize-1) * psGXF->dfXPixelSize;
@@ -1028,5 +1042,3 @@ CPLErr GXFGetPosition( GXFHandle hGXF,
     else
         return( CE_None );
 }
-
-
diff --git a/frmts/gxf/gxfopen.h b/frmts/gxf/gxfopen.h
index ac915c8..8aa1251 100644
--- a/frmts/gxf/gxfopen.h
+++ b/frmts/gxf/gxfopen.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gxfopen.h 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: gxfopen.h 32179 2015-12-14 16:22:34Z goatbar $
  *
  * Project:  GXF Reader
  * Purpose:  GXF-3 access function declarations.
@@ -28,8 +28,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _GXFOPEN_H_INCLUDED
-#define _GXFOPEN_H_INCLUDED
+#ifndef GXFOPEN_H_INCLUDED
+#define GXFOPEN_H_INCLUDED
 
 /**
  * \file gxfopen.h
@@ -114,13 +114,11 @@ typedef struct {
 
     char	*pszUnitName;
     double	dfUnitToMeter;
-    
 
     double	dfZMaximum;
     double	dfZMinimum;
 
     long	*panRawLineOffset;
-    
 } GXFInfo_t;
 
-#endif /* ndef _GXFOPEN_H_INCLUDED */
+#endif /* ndef GXFOPEN_H_INCLUDED */
diff --git a/frmts/gxf/makefile.vc b/frmts/gxf/makefile.vc
index 9610488..f615673 100644
--- a/frmts/gxf/makefile.vc
+++ b/frmts/gxf/makefile.vc
@@ -1,8 +1,6 @@
 
 OBJ	=	gxfopen.obj gxfdataset.obj gxf_ogcwkt.obj 
 
-EXTRAFLAGS = 	-I..\iso8211
-
 GDAL_ROOT	=	..\..
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
diff --git a/frmts/hdf4/frmt_hdf4.html b/frmts/hdf4/frmt_hdf4.html
index 34fa36b..5041dba 100644
--- a/frmts/hdf4/frmt_hdf4.html
+++ b/frmts/hdf4/frmt_hdf4.html
@@ -1,4 +1,4 @@
-<!-- $Id: frmt_hdf4.html 22813 2011-07-25 19:01:41Z winkey $ -->
+<!-- $Id: frmt_hdf4.html 33795 2016-03-27 03:34:36Z goatbar $ -->
 
 <html>
 <head>
@@ -23,8 +23,8 @@ telemetry from `Aura' satellite.<p>
 
 Hierarchical Data Format is a container for several different datasets.
 For data storing Scientific Datasets (SDS) used most often. SDS is a
-multidimensional array filled by data.  One HDF file may contain several 
-different SDS arrays.  They may differ in size, number of dimensions and may 
+multidimensional array filled by data.  One HDF file may contain several
+different SDS arrays.  They may differ in size, number of dimensions and may
 represent data for different regions.<p>
 
 If the file contains only one SDS that appears to be an image, it may be
@@ -33,17 +33,17 @@ import the file via a two step process.  The first step is to get a report
 of the components images (SDS arrays) in the file using <b>gdalinfo</b>, and
 then to import the desired images using gdal_translate.
 
-The <b>gdalinfo</b> utility lists all multidimensional subdatasets from the 
-input HDF file. The name of individual images (subdatasets) are assigned to 
+The <b>gdalinfo</b> utility lists all multidimensional subdatasets from the
+input HDF file. The name of individual images (subdatasets) are assigned to
 the <b>SUBDATASET_n_NAME</b> metadata item.  The description for each image is
 found in the <b>SUBDATASET_n_DESC</b> metadata item.  For HDF4 images the
 subdataset names will be formatted like this:<p>
 
 <i>HDF4_SDS:subdataset_type:file_name:subdataset_index</i><p>
 
-where <i>subdataset_type</i> shows predefined names for some of the well 
+where <i>subdataset_type</i> shows predefined names for some of the well
 known HDF datasets, <i>file_name</i> is the name of the input file, and
-<i>subdataset_index</i> is the index of the image to use (for internal use in 
+<i>subdataset_index</i> is the index of the image to use (for internal use in
 GDAL).<p>
 
 On the second step you should provide this name for <b>gdalinfo</b> or
@@ -142,12 +142,12 @@ Band 12 Block=1354x2040 Type=UInt16, ColorInterp=Undefined
 Or you may use <b>gdal_translate</b> for reading image bands from this
 dataset.<p>
 
-Note that you should provide exactly the contents of the line marked 
+Note that you should provide exactly the contents of the line marked
 <b>SUBDATASET_n_NAME</b> to GDAL, including the <b>HDF4_SDS:</b> prefix.<p>
 
-This driver is intended only for importing remote sensing and geospatial 
-datasets in form of raster images. If you want explore all data contained in 
-HDF file you should use another tools (you can find information about 
+This driver is intended only for importing remote sensing and geospatial
+datasets in form of raster images. If you want explore all data contained in
+HDF file you should use another tools (you can find information about
 different HDF tools using links at end of this page).
 
 <h2>Georeference</h2>
@@ -159,13 +159,13 @@ shown in parenthesis):<p>
 
 <ul>
 	<li> HDF4 files created by GDAL (<B>GDAL_HDF4</B>)
-	
+
 	<li> ASTER Level 1A (<B>ASTER_L1A</B>)
-	
+
 	<li> ASTER Level 1B (<B>ASTER_L1B</B>)
-	
+
 	<li> ASTER Level 2 (<B>ASTER_L2</B>)
-	
+
 	<li> ASTER DEM (<B>AST14DEM</B>)
 
 	<li> MODIS Level 1B Earth View products (<B>MODIS_L1B</B>)
@@ -188,7 +188,7 @@ This driver supports creation of the HDF4 Scientific Datasets. You may create
 set of 2D datasets (one per each input band) or single 3D dataset where the third
 dimension represents band numbers. All metadata and band descriptions from
 the input dataset are stored as HDF4 attributes. Projection information (if it
-exists) and affine transformation coefficients also stored in form of 
+exists) and affine transformation coefficients also stored in form of
 attributes.
 Files, created by GDAL have the special attribute:<p>
 
@@ -208,18 +208,18 @@ Creation Options:<p>
 	to use. <b>RLE</b> is Run-length encoding, <b>HUFFMAN</b> is adaptive
 	Huffman, <b>DEFLATE</b> is GZIP "deflation" (Lempel/Ziv-77 dictionary
 	coder). <b>NONE</b> is the default.<p-->
-	
+
 </ul>
 
 <h2>Metadata</h2>
 
-All HDF4 attributes are transparently translated as GDAL metadata. In the HDF 
-file attributes may be assigned assigned to the whole file as well as to 
+All HDF4 attributes are transparently translated as GDAL metadata. In the HDF
+file attributes may be assigned assigned to the whole file as well as to
 particular subdatasets.
 
 <h2>Driver building</h2>
 
-This driver builded on top of NCSA HDF library, so you need one to compile
+This driver built on top of NCSA HDF library, so you need one to compile
 GDAL with HDF4 support. You may search your operating system distribution for
 the precompiled binaries or download source code or binaries from the NCSA HDF
 Home Page (see links below).<p>
diff --git a/frmts/hdf4/hdf-eos/EHapi.c b/frmts/hdf4/hdf-eos/EHapi.c
index 4dc1e88..c3d3666 100644
--- a/frmts/hdf4/hdf-eos/EHapi.c
+++ b/frmts/hdf4/hdf-eos/EHapi.c
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * $Id: EHapi.c 25847 2013-04-03 09:45:20Z dron $
+ * $Id: EHapi.c 32490 2015-12-27 09:29:13Z rouault $
  *
  * This module has a number of additions and improvements over the original
  * implementation to be suitable for usage in GDAL HDF driver.
@@ -16,6 +16,7 @@ copyright notice appear in all copies and that both that copyright notice and
 this permission notice appear in supporting documentation.
 */
 
+#include "cpl_port.h"
 #include <errno.h>
 #include "mfhdf.h"
 #include "HdfEosDef.h"
@@ -48,7 +49,7 @@ static int32 *EHXsdTable = NULL;
 static intn EHmetalist(char *, char *);
 static intn EHreset_maxopenfiles(intn);
 static intn EHget_maxopenfiles(intn *, intn *);
-static intn EHget_numfiles();
+static intn EHget_numfiles(void);
 
 /*----------------------------------------------------------------------------|
 |  BEGIN_PROLOG                                                               |
@@ -76,7 +77,7 @@ static intn EHget_numfiles();
 |  ======   ============  =================================================   |
 |  Jun 96   Joel Gales    Original Programmer                                 |
 |  Jul 96   Joel Gales    Add file id offset EHIDOFFSET                       |
-|  Aug 96   Joel Gales    Add "END" statment to structural metadata           |
+|  Aug 96   Joel Gales    Add "END" statement to structural metadata          |
 |  Sep 96   Joel Gales    Reverse order of Hopen ane SDstart statements       |
 |                         for RDWR and READ access                            |
 |  Oct 96   Joel Gales    Trap CREATE & RDWR (no write permission)            |
@@ -96,12 +97,12 @@ EHopen(char *filename, intn access)
     intn            curr_max = 0;	/* maximum # of HDF files to open */
     intn            sys_limit = 0;	/* OS limit for maximum # of opened files */
 
-    int32           HDFfid;	/* HDF file ID */
+    int32           HDFfid = 0;	/* HDF file ID */
     int32           fid = -1;	/* HDF-EOS file ID */
-    int32           sdInterfaceID;	/* HDF SDS interface ID */
+    int32           sdInterfaceID = 0;	/* HDF SDS interface ID */
     int32           attrIndex;	/* Structural Metadata attribute index */
 
-    uint8           acs;	/* Read (0) / Write (1) access code */
+    uint8           acs = 0;	/* Read (0) / Write (1) access code */
 
     char           *testname;	/* Test filename */
     char            errbuf[256];/* Error report buffer */
@@ -179,10 +180,10 @@ EHopen(char *filename, intn access)
 		{
 		    /* Set HDFEOS version number in file */
 		    /* --------------------------------- */
-		    sprintf(hdfeosVersion, "%s%s", "HDFEOS_V",
+		    snprintf(hdfeosVersion, sizeof(hdfeosVersion), "%s%s", "HDFEOS_V",
 			    HDFEOSVERSION1);
 		    SDsetattr(sdInterfaceID, "HDFEOSVersion", DFNT_CHAR8,
-			      strlen(hdfeosVersion), hdfeosVersion);
+			      (int)strlen(hdfeosVersion), hdfeosVersion);
 
 
 		    /* Get HDF file ID */
@@ -222,7 +223,7 @@ EHopen(char *filename, intn access)
 		    fid = -1;
 		    status = -1;
 		    HEpush(DFE_FNF, "EHopen", __FILE__, __LINE__);
-		    sprintf(errbuf, "%s%s%s", "\"", filename,
+		    snprintf(errbuf, sizeof(errbuf), "%s%s%s", "\"", filename,
 			    "\" cannot be created.");
 		    HEreport("%s\n", errbuf);
 		}
@@ -238,7 +239,7 @@ EHopen(char *filename, intn access)
 #ifndef _PGS_OLDNFS
 /* The following loop around the function Hopen is intended to deal with the NFS cache 
    problem when opening file fails with errno = 150 or 151. When NFS cache is updated,
-   this part of change is no longer neccessary.              10/18/1999   */
+   this part of change is no longer necessary.              10/18/1999   */
                 retryCount = 0;
                 HDFfid = -1;
                 while ((HDFfid == -1) && (retryCount < MAX_RETRIES))
@@ -247,7 +248,7 @@ EHopen(char *filename, intn access)
                 if((HDFfid == -1) && (errno == 150 || errno == 151))
                     {
                     HEpush(DFE_FNF, "EHopen", __FILE__, __LINE__);
-                    sprintf(errbuf, "\"%s\" cannot be opened for READ/WRITE access, will retry %d times.", filename,  (MAX_RETRIES - retryCount - 1));
+                    snprintf(errbuf, sizeof(errbuf), "\"%s\" cannot be opened for READ/WRITE access, will retry %d times.", filename,  (MAX_RETRIES - retryCount - 1));
                     HEreport("%s\n", errbuf);
                     }
                 retryCount++;
@@ -274,10 +275,10 @@ EHopen(char *filename, intn access)
 		      attrIndex = SDfindattr(sdInterfaceID, "HDFEOSVersion");
 		      if (attrIndex == -1)
 			{
-			  sprintf(hdfeosVersion, "%s%s", "HDFEOS_V",
+			  snprintf(hdfeosVersion, sizeof(hdfeosVersion), "%s%s", "HDFEOS_V",
 				  HDFEOSVERSION1);
 			  SDsetattr(sdInterfaceID, "HDFEOSVersion", DFNT_CHAR8,
-				    strlen(hdfeosVersion), hdfeosVersion);
+				    (int)strlen(hdfeosVersion), hdfeosVersion);
 			}
 		       /* Set open access to write */
 		       /* ------------------------ */
@@ -317,7 +318,7 @@ EHopen(char *filename, intn access)
                         fid = -1;
                         status = -1;
                         HEpush(DFE_FNF, "EHopen", __FILE__, __LINE__);
-                        sprintf(errbuf, "%s%s%s", "\"", filename,
+                        snprintf(errbuf, sizeof(errbuf), "%s%s%s", "\"", filename,
                             "\" cannot be opened for read/write access.");
                         HEreport("%s\n", errbuf);
                     }
@@ -328,7 +329,7 @@ EHopen(char *filename, intn access)
 		    fid = -1;
 		    status = -1;
 		    HEpush(DFE_FNF, "EHopen", __FILE__, __LINE__);
-		    sprintf(errbuf, "%s%s%s", "\"", filename,
+		    snprintf(errbuf, sizeof(errbuf), "%s%s%s", "\"", filename,
 			    "\" cannot be opened for RDWR access.");
 		    HEreport("%s\n", errbuf);
 		}
@@ -345,7 +346,7 @@ EHopen(char *filename, intn access)
 #ifndef _PGS_OLDNFS
 /* The following loop around the function Hopen is intended to deal with the NFS cache 
    problem when opening file fails with errno = 150 or 151. When NFS cache is updated,
-   this part of change is no longer neccessary.              10/18/1999   */
+   this part of change is no longer necessary.              10/18/1999   */
                 retryCount = 0;
                 HDFfid = -1;
                 while ((HDFfid == -1) && (retryCount < MAX_RETRIES))
@@ -354,7 +355,7 @@ EHopen(char *filename, intn access)
                 if((HDFfid == -1) && (errno == 150 || errno == 151))
                     {
                     HEpush(DFE_FNF, "EHopen", __FILE__, __LINE__);
-                    sprintf(errbuf, "\"%s\" cannot be opened for READONLY access, will retry %d times.", filename,  (MAX_RETRIES - retryCount - 1));
+                    snprintf(errbuf, sizeof(errbuf), "\"%s\" cannot be opened for READONLY access, will retry %d times.", filename,  (MAX_RETRIES - retryCount - 1));
                     HEreport("%s\n", errbuf);
                     }
                 retryCount++;
@@ -396,7 +397,7 @@ EHopen(char *filename, intn access)
                             fid = -1;
                             status = -1;
                             HEpush(DFE_FNF, "EHopen", __FILE__, __LINE__);
-                            sprintf(errbuf, "%s%s%s", "\"", filename,
+                            snprintf(errbuf, sizeof(errbuf), "%s%s%s", "\"", filename,
                             "\" cannot be opened for read access.");
                             HEreport("%s\n", errbuf);
                         }
@@ -544,7 +545,7 @@ EHchkfid(int32 fid, char *name, int32 * HDFfid, int32 * sdInterfaceID,
 |                                                                             |
 |  FUNCTION: EHidinfo                                                         |
 |                                                                             |
-|  DESCRIPTION: Gets Hopen and SD intereface IDs from HDF-EOS id              |
+|  DESCRIPTION: Gets Hopen and SD interface IDs from HDF-EOS id               |
 |                                                                             |
 |                                                                             |
 |  Return Value    Type     Units     Description                             |
@@ -663,7 +664,7 @@ EHgetversion(int32 fid, char *version)
 
     uint8           access;	/* Access code */
     int32           dum;	/* Dummy variable */
-    int32           sdInterfaceID;	/* HDF SDS interface ID */
+    int32           sdInterfaceID = 0;	/* HDF SDS interface ID */
     int32           attrIndex;	/* HDFEOS version attribute index */
     int32           count;	/* Version string size */
 
@@ -776,8 +777,8 @@ EHconvAng(float64 inAngle, intn code)
 	/* Convert packed degrees to degrees */
 	/* --------------------------------- */
     case HDFE_DMS_DEG:
-	deg = inAngle / 1000000;
-	min = (inAngle - deg * 1000000) / 1000;
+	deg = (int32)(inAngle / 1000000);
+	min = (int32)((inAngle - deg * 1000000) / 1000);
 	sec = (inAngle - deg * 1000000 - min * 1000);
 	outAngle = deg + min / 60.0 + sec / 3600.0;
 	break;
@@ -786,8 +787,8 @@ EHconvAng(float64 inAngle, intn code)
 	/* Convert degrees to packed degrees */
 	/* --------------------------------- */
     case HDFE_DEG_DMS:
-	deg = inAngle;
-	min = (inAngle - deg) * 60;
+	deg = (int32)(inAngle);
+	min = (int32)((inAngle - deg) * 60);
 	sec = (inAngle - deg - min / 60.0) * 3600;
 
 	if ((intn) sec == 60)
@@ -808,8 +809,8 @@ EHconvAng(float64 inAngle, intn code)
 	/* --------------------------------- */
     case HDFE_RAD_DMS:
 	inAngle = inAngle * RADIANS_TO_DEGREES;
-	deg = inAngle;
-	min = (inAngle - deg) * 60;
+	deg = (int32)(inAngle);
+	min = (int32)((inAngle - deg) * 60);
 	sec = (inAngle - deg - min / 60.0) * 3600;
 
 	if ((intn) sec == 60)
@@ -829,8 +830,8 @@ EHconvAng(float64 inAngle, intn code)
 	/* Convert packed degrees to radians */
 	/* --------------------------------- */
     case HDFE_DMS_RAD:
-	deg = inAngle / 1000000;
-	min = (inAngle - deg * 1000000) / 1000;
+	deg = (int32)(inAngle / 1000000);
+	min = (int32)((inAngle - deg * 1000000) / 1000);
 	sec = (inAngle - deg * 1000000 - min * 1000);
 	outAngle = deg + min / 60.0 + sec / 3600.0;
 	outAngle = outAngle * DEGREES_TO_RADIANS;
@@ -857,7 +858,7 @@ EHconvAng(float64 inAngle, intn code)
 |                                                                             |
 |  INPUTS:                                                                    |
 |  instring       const char          Input string                            |
-|  delim          const char          string delimitor                        |
+|  delim          const char          string delimiter                        |
 |                                                                             |
 |  OUTPUTS:                                                                   |
 |  pntr           char *              Pointer array to beginning of each      |
@@ -878,16 +879,16 @@ int32
 EHparsestr(const char *instring, const char delim, char *pntr[], int32 len[])
 {
     int32           i;		/* Loop index */
-    int32           prevDelimPos = 0;	/* Previous delimitor position */
+    int32           prevDelimPos = 0;	/* Previous delimiter position */
     int32           count;	/* Number of elements in string list */
     int32           slen;	/* String length */
 
-    char           *delimitor;	/* Pointer to delimitor */
+    char           *delimitor;	/* Pointer to delimiter */
 
 
-    /* Get length of input string list & Point to first delimitor */
+    /* Get length of input string list & Point to first delimiter */
     /* ---------------------------------------------------------- */
-    slen = strlen(instring);
+    slen = (int)strlen(instring);
     delimitor = strchr(instring, delim);
 
     /* If NULL string set count to zero otherwise set to 1 */
@@ -901,8 +902,8 @@ EHparsestr(const char *instring, const char delim, char *pntr[], int32 len[])
     {
 	pntr[0] = (char *)instring;
     }
-    /* If delimitor not found ... */
-    /* -------------------------- */
+    /* If delimiter not found ... */
+    /* ---------------------------- */
     if (delimitor == NULL)
     {
 	/* if string length requested then set to input string length */
@@ -912,14 +913,14 @@ EHparsestr(const char *instring, const char delim, char *pntr[], int32 len[])
 	    len[0] = slen;
 	}
     } else
-	/* Delimitors Found */
+	/* Delimiters Found */
 	/* ---------------- */
     {
 	/* Loop through all characters in string */
 	/* ------------------------------------- */
 	for (i = 1; i < slen; i++)
 	{
-	    /* If character is a delimitor ... */
+	    /* If character is a delimiter ... */
 	    /* ------------------------------- */
 	    if (instring[i] == delim)
 	    {
@@ -938,7 +939,7 @@ EHparsestr(const char *instring, const char delim, char *pntr[], int32 len[])
 		    /* ---------------------------------- */
 		    pntr[count] = (char *)instring + i + 1;
 		}
-		/* Reset previous delimitor position and increment counter */
+		/* Reset previous delimiter position and increment counter */
 		/* ------------------------------------------------------- */
 		prevDelimPos = i + 1;
 		count++;
@@ -964,7 +965,7 @@ EHparsestr(const char *instring, const char delim, char *pntr[], int32 len[])
 |                                                                             |
 |  FUNCTION: EHstrwithin                                                      |
 |                                                                             |
-|  DESCRIPTION: Searchs for string within target string                       |
+|  DESCRIPTION: Searches for string within target string                      |
 |                                                                             |
 |                                                                             |
 |  Return Value    Type     Units     Description                             |
@@ -974,7 +975,7 @@ EHparsestr(const char *instring, const char delim, char *pntr[], int32 len[])
 |  INPUTS:                                                                    |
 |  target         const char          Target string                           |
 |  search         const char          Search string                           |
-|  delim          const char          Delimitor                               |
+|  delim          const char          Delimiter                               |
 |                                                                             |
 |  OUTPUTS:                                                                   |
 |             None                                                            |
@@ -1079,7 +1080,7 @@ EHstrwithin(const char *target, const char *search, const char delim)
 |  INPUTS:                                                                    |
 |  ptr            char                String pointer array                    |
 |  nentries       int32               Number of string array elements         |
-|  delim          char                Delimitor                               |
+|  delim          char                Delimiter                               |
 |                                                                             |
 |  OUTPUTS:                                                                   |
 |  liststr        char                Output list string                      |
@@ -1113,7 +1114,7 @@ EHloadliststr(char *ptr[], int32 nentries, char *liststr, char delim)
     {
 	/* Get string length of string array entry */
 	/* --------------------------------------- */
-	slen = strlen(ptr[i]);
+	slen = (int)strlen(ptr[i]);
 
 
 	/* Copy string entry to string list */
@@ -1121,7 +1122,7 @@ EHloadliststr(char *ptr[], int32 nentries, char *liststr, char delim)
 	memcpy(liststr + off, ptr[i], slen + 1);
 
 
-	/* Concatenate with delimitor */
+	/* Concatenate with delimiter */
 	/* -------------------------- */
 	if (i != nentries - 1)
 	{
@@ -1377,7 +1378,7 @@ EHrevflds(char *dimlist, char *revdimlist)
     }
 
 
-    /* Replace comma delimitors by nulls */
+    /* Replace comma delimiters by nulls */
     /* --------------------------------- */
     for (indx = 0; indx < nentries - 1; indx++)
     {
@@ -1411,7 +1412,7 @@ EHrevflds(char *dimlist, char *revdimlist)
 |  count          int32               Number of OBJECTs in GROUP              |
 |                                                                             |
 |  INPUTS:                                                                    |
-|  metabur        char                Begin & end metadata pointer array      |
+|  metabuf        char                Begin & end metadata pointer array      |
 |                                                                             |
 |  OUTPUTS:                                                                   |
 |             None                                                            |
@@ -1471,7 +1472,7 @@ EHcntOBJECT(char *metabuf[])
 |  count          int32               Number of GROUPs in GROUP               |
 |                                                                             |
 |  INPUTS:                                                                    |
-|  metabur        char                Begin & end metadata pointer array      |
+|  metabuf        char                Begin & end metadata pointer array      |
 |                                                                             |
 |  OUTPUTS:                                                                   |
 |             None                                                            |
@@ -1612,7 +1613,7 @@ EHmetalist(char *instring, char *outstring)
 	outstring[listlen] = 0;
 
 
-	/* Add comma delimitor to output string */
+	/* Add comma delimiter to output string */
 	/* ------------------------------------ */
 	if (i != (nentries - 1))
 	{
@@ -1702,7 +1703,7 @@ EHinsertmeta(int32 sdInterfaceID, char *structname, char *structcode,
     char           *metaArr[2];	/* Array of metadata positions */
     char           *colon;	/* Colon position */
     char           *colon2;	/* 2nd colon position */
-    char           *slash;	/* Slash postion */
+    char           *slash;	/* Slash position */
     char           *utlstr;	/* Utility string */
     char           *utlstr2;	/* Utility string 2 */
 
@@ -1731,7 +1732,7 @@ EHinsertmeta(int32 sdInterfaceID, char *structname, char *structcode,
     {
 	/* Search for "StructMetadata.x" attribute */
 	/* --------------------------------------- */
-	sprintf(utlstr, "%s%d", "StructMetadata.", (int)nmeta);
+	snprintf(utlstr, UTLSTRSIZE, "%s%d", "StructMetadata.", (int)nmeta);
 	attrIndex = SDfindattr(sdInterfaceID, utlstr);
 
 
@@ -1763,15 +1764,15 @@ EHinsertmeta(int32 sdInterfaceID, char *structname, char *structcode,
     /* ------------------------ */
     for (i = 0; i < nmeta; i++)
     {
-	sprintf(utlstr, "%s%d", "StructMetadata.", i);
+	snprintf(utlstr, UTLSTRSIZE, "%s%d", "StructMetadata.", i);
 	attrIndex = SDfindattr(sdInterfaceID, utlstr);
-	metalen = strlen(metabuf);
+	metalen = (int)strlen(metabuf);
 	SDreadattr(sdInterfaceID, attrIndex, metabuf + metalen);
     }
 
     /* Determine length (# of characters) of metadata */
     /* ---------------------------------------------- */
-    metalen = strlen(metabuf);
+    metalen = (int)strlen(metabuf);
 
 
 
@@ -1809,13 +1810,13 @@ EHinsertmeta(int32 sdInterfaceID, char *structname, char *structcode,
 	/* ---------------------------------------------------- */
 	if (strcmp(structcode, "s") == 0)
 	{
-	    sprintf(utlstr, "%s%s", "SwathName=\"", structname);
+	    snprintf(utlstr, UTLSTRSIZE, "%s%s", "SwathName=\"", structname);
 	} else if (strcmp(structcode, "g") == 0)
 	{
-	    sprintf(utlstr, "%s%s", "GridName=\"", structname);
+	    snprintf(utlstr, UTLSTRSIZE, "%s%s", "GridName=\"", structname);
 	} else if (strcmp(structcode, "p") == 0)
 	{
-	    sprintf(utlstr, "%s%s", "PointName=\"", structname);
+	    snprintf(utlstr, UTLSTRSIZE, "%s%s", "PointName=\"", structname);
 	}
 	/* Do string search */
 	/* ---------------- */
@@ -1828,7 +1829,7 @@ EHinsertmeta(int32 sdInterfaceID, char *structname, char *structcode,
 	 */
 	if (metaptr == NULL)
 	{
-	    sprintf(utlstr, "%s%s", "GROUP=\"", structname);
+	    snprintf(utlstr, UTLSTRSIZE, "%s%s", "GROUP=\"", structname);
 	    metaptr = strstr(prevmetaptr, utlstr);
 	}
     }
@@ -1899,7 +1900,7 @@ EHinsertmeta(int32 sdInterfaceID, char *structname, char *structcode,
 
 	/* Build metadata entry string */
 	/* --------------------------- */
-	sprintf(utlstr, "%s%d%s%s%s%d%s%d%s",
+	snprintf(utlstr, UTLSTRSIZE, "%s%d%s%s%s%d%s%d%s",
                 "\t\t\tOBJECT=Dimension_", (int)count,
 		"\n\t\t\t\tDimensionName=\"", &metastr[0],
 		"\"\n\t\t\t\tSize=", (int)metadata[0],
@@ -1935,7 +1936,7 @@ EHinsertmeta(int32 sdInterfaceID, char *structname, char *structcode,
 
 	/* Build metadata entry string */
 	/* --------------------------- */
-	sprintf(utlstr, "%s%d%s%s%s%s%s%d%s%d%s%d%s",
+	snprintf(utlstr, UTLSTRSIZE, "%s%d%s%s%s%s%s%d%s%d%s%d%s",
 		"\t\t\tOBJECT=DimensionMap_", (int)count,
 		"\n\t\t\t\tGeoDimension=\"", &metastr[0],
 		"\"\n\t\t\t\tDataDimension=\"", &metastr[slen[0] + 1],
@@ -1973,7 +1974,7 @@ EHinsertmeta(int32 sdInterfaceID, char *structname, char *structcode,
 
 	/* Build metadata entry string */
 	/* --------------------------- */
-	sprintf(utlstr, "%s%d%s%s%s%s%s%d%s",
+	snprintf(utlstr, UTLSTRSIZE, "%s%d%s%s%s%s%s%d%s",
 		"\t\t\tOBJECT=IndexDimensionMap_", (int)count,
 		"\n\t\t\t\tGeoDimension=\"", &metastr[0],
 		"\"\n\t\t\t\tDataDimension=\"", &metastr[slen[0] + 1],
@@ -2021,7 +2022,7 @@ EHinsertmeta(int32 sdInterfaceID, char *structname, char *structcode,
 
 	/* Build metadata entry string */
 	/* --------------------------- */
-	sprintf(utlstr, "%s%d%s%s%s%s%s%s",
+	snprintf(utlstr, UTLSTRSIZE, "%s%d%s%s%s%s%s%s",
 		"\t\t\tOBJECT=GeoField_", (int)count,
 		"\n\t\t\t\tGeoFieldName=\"", metastr,
 		"\"\n\t\t\t\tDataType=", type,
@@ -2036,7 +2037,7 @@ EHinsertmeta(int32 sdInterfaceID, char *structname, char *structcode,
 	}
 	/* Add END_OBJECT terminator to metadata string */
 	/* -------------------------------------------- */
-	sprintf(utlstr2, "%s%d%s",
+	snprintf(utlstr2, UTLSTRSIZE, "%s%d%s",
 		"\n\t\t\tEND_OBJECT=GeoField_", (int)count, "\n");
 	strcat(utlstr, utlstr2);
 
@@ -2083,7 +2084,7 @@ EHinsertmeta(int32 sdInterfaceID, char *structname, char *structcode,
 
 	/* Build metadata entry string */
 	/* --------------------------- */
-	sprintf(utlstr, "%s%d%s%s%s%s%s%s",
+	snprintf(utlstr, UTLSTRSIZE, "%s%d%s%s%s%s%s%s",
 		"\t\t\tOBJECT=DataField_", (int)count,
 		"\n\t\t\t\tDataFieldName=\"", metastr,
 		"\"\n\t\t\t\tDataType=", type,
@@ -2098,7 +2099,7 @@ EHinsertmeta(int32 sdInterfaceID, char *structname, char *structcode,
 	}
 	/* Add END_OBJECT terminator to metadata string */
 	/* -------------------------------------------- */
-	sprintf(utlstr2, "%s%d%s",
+	snprintf(utlstr2, UTLSTRSIZE, "%s%d%s",
 		"\n\t\t\tEND_OBJECT=DataField_", (int)count, "\n");
 	strcat(utlstr, utlstr2);
 
@@ -2138,7 +2139,7 @@ EHinsertmeta(int32 sdInterfaceID, char *structname, char *structcode,
 
 	/* Build metadata entry string */
 	/* --------------------------- */
-	sprintf(utlstr, "%s%d%s%s%s%s%s%s%d%s",
+	snprintf(utlstr, UTLSTRSIZE, "%s%d%s%s%s%s%s%s%d%s",
 		"\t\t\tOBJECT=MergedFields_", (int)count,
 		"\n\t\t\t\tMergedFieldName=\"", metastr, "\"",
 		"\n\t\t\t\tFieldList=", utlstr2,
@@ -2168,7 +2169,7 @@ EHinsertmeta(int32 sdInterfaceID, char *structname, char *structcode,
 
 	/* Build metadata entry string */
 	/* --------------------------- */
-	sprintf(utlstr, "%s%d%s%s%s%d%s",
+	snprintf(utlstr, UTLSTRSIZE, "%s%d%s%s%s%d%s",
 		"\t\t\tGROUP=Level_", (int)count,
 		"\n\t\t\t\tLevelName=\"", metastr,
 		"\"\n\t\t\tEND_GROUP=Level_", (int)count, "\n");
@@ -2204,7 +2205,7 @@ EHinsertmeta(int32 sdInterfaceID, char *structname, char *structcode,
 
 	/* Build metadata entry string */
 	/* --------------------------- */
-	sprintf(utlstr, "%s%d%s%s%s%s%s%d%s%d%s",
+	snprintf(utlstr, UTLSTRSIZE, "%s%d%s%s%s%s%s%d%s%d%s",
 		"\t\t\t\tOBJECT=PointField_", (int)count,
 		"\n\t\t\t\t\tPointFieldName=\"", metastr,
 		"\"\n\t\t\t\t\tDataType=", type,
@@ -2248,7 +2249,7 @@ EHinsertmeta(int32 sdInterfaceID, char *structname, char *structcode,
 
 	/* Build metadata entry string */
 	/* --------------------------- */
-	sprintf(utlstr, "%s%d%s%s%s%s%s%s%s%d%s",
+	snprintf(utlstr, UTLSTRSIZE, "%s%d%s%s%s%s%s%s%s%d%s",
 		"\t\t\tOBJECT=LevelLink_", (int)count,
 		"\n\t\t\t\tParent=\"", metastr,
 		"\"\n\t\t\t\tChild=\"", slash + 1,
@@ -2299,11 +2300,11 @@ EHinsertmeta(int32 sdInterfaceID, char *structname, char *structcode,
 
     /* Get length of metadata string to insert */
     /* --------------------------------------- */
-    seglen = strlen(utlstr);
+    seglen = (int)strlen(utlstr);
 
-    /* Get offset of entry postion within existing metadata */
-    /* ---------------------------------------------------- */
-    offset = metaptr - metabuf;
+    /* Get offset of entry position within existing metadata */
+    /* ----------------------------------------------------- */
+    offset = (int)(metaptr - metabuf);
 
 
     /* If end of new metadata string outside of current metadata buffer ... */
@@ -2336,7 +2337,7 @@ EHinsertmeta(int32 sdInterfaceID, char *structname, char *structcode,
 	*(metabuf + seglen + i) = *(metabuf + i);
     }
 
-    /* Copy new metadat string (utlstr) into metadata */
+    /* Copy new metadata string (utlstr) into metadata */
     /* ---------------------------------------------- */
     memcpy(metaptr, utlstr, seglen);
 
@@ -2353,26 +2354,19 @@ EHinsertmeta(int32 sdInterfaceID, char *structname, char *structcode,
     /* --------------------------------- */
     for (i = 0; i < nmeta; i++)
     {
-	sprintf(utlstr, "%s%d", "StructMetadata.", i);
+	snprintf(utlstr, UTLSTRSIZE, "%s%d", "StructMetadata.", i);
 	SDsetattr(sdInterfaceID, utlstr, DFNT_CHAR8,
 		  32000, metabuf + i * 32000);
     }
 
-
-
     free(metabuf);
     free(utlstr);
     free(utlstr2);
 
     return (status);
-
 }
 
 
-
-
-
-
 /*----------------------------------------------------------------------------|
 |  BEGIN_PROLOG                                                               |
 |                                                                             |
@@ -2415,7 +2409,7 @@ EHgetmetavalue(char *metaptrs[], char *parameter, char *retstr)
 
     /* Get string length of parameter string + 1 */
     /* ----------------------------------------- */
-    slen = strlen(parameter) + 1;
+    slen = (int)strlen(parameter) + 1;
 
 
     /* Build search string (parameter string + "=") */
@@ -2529,7 +2523,7 @@ EHmetagroup(int32 sdInterfaceID, char *structname, char *structcode,
     {
 	/* Search for "StructMetadata.x" attribute */
 	/* --------------------------------------- */
-	sprintf(utlstr, "%s%d", "StructMetadata.", (int)nmeta);
+	snprintf(utlstr, UTLSTR_MAX_SIZE, "%s%d", "StructMetadata.", (int)nmeta);
 	attrIndex = SDfindattr(sdInterfaceID, utlstr);
 
 
@@ -2561,15 +2555,15 @@ EHmetagroup(int32 sdInterfaceID, char *structname, char *structcode,
     /* ------------------------ */
     for (i = 0; i < nmeta; i++)
     {
-	sprintf(utlstr, "%s%d", "StructMetadata.", i);
+	snprintf(utlstr, UTLSTR_MAX_SIZE, "%s%d", "StructMetadata.", i);
 	attrIndex = SDfindattr(sdInterfaceID, utlstr);
-	metalen = strlen(metabuf);
+	metalen = (int)strlen(metabuf);
 	SDreadattr(sdInterfaceID, attrIndex, metabuf + metalen);
     }
 
     /* Determine length (# of characters) of metadata */
     /* ---------------------------------------------- */
-    metalen = strlen(metabuf);
+    metalen = (int)strlen(metabuf);
 
 
 
@@ -2603,13 +2597,13 @@ EHmetagroup(int32 sdInterfaceID, char *structname, char *structcode,
     /* ---------------------------------------------------- */
     if (strcmp(structcode, "s") == 0)
     {
-	sprintf(utlstr, "%s%s", "SwathName=\"", structname);
+	snprintf(utlstr, UTLSTR_MAX_SIZE, "%s%s", "SwathName=\"", structname);
     } else if (strcmp(structcode, "g") == 0)
     {
-	sprintf(utlstr, "%s%s", "GridName=\"", structname);
+	snprintf(utlstr, UTLSTR_MAX_SIZE, "%s%s", "GridName=\"", structname);
     } else if (strcmp(structcode, "p") == 0)
     {
-	sprintf(utlstr, "%s%s", "PointName=\"", structname);
+	snprintf(utlstr, UTLSTR_MAX_SIZE, "%s%s", "PointName=\"", structname);
     }
     /* Do string search */
     /* ---------------- */
@@ -2622,23 +2616,23 @@ EHmetagroup(int32 sdInterfaceID, char *structname, char *structcode,
      */
     if (metaptr == NULL)
     {
-	sprintf(utlstr, "%s%s", "GROUP=\"", structname);
+	snprintf(utlstr, UTLSTR_MAX_SIZE, "%s%s", "GROUP=\"", structname);
 	metaptr = strstr(prevmetaptr, utlstr);
     }
     /* Find group within structure */
     /* --------------------------- */
     if (groupname != NULL)
     {
-	sprintf(utlstr, "%s%s", "GROUP=", groupname);
+	snprintf(utlstr, UTLSTR_MAX_SIZE, "%s%s", "GROUP=", groupname);
 	metaptr = strstr(metaptr, utlstr);
 
-	sprintf(utlstr, "%s%s", "\t\tEND_GROUP=", groupname);
+	snprintf(utlstr, UTLSTR_MAX_SIZE, "%s%s", "\t\tEND_GROUP=", groupname);
 	endptr = strstr(metaptr, utlstr);
     } else
     {
 	/* If groupname == NULL then find end of structure in metadata */
 	/* ----------------------------------------------------------- */
-	sprintf(utlstr, "%s", "\n\tEND_GROUP=");
+	snprintf(utlstr, UTLSTR_MAX_SIZE, "%s", "\n\tEND_GROUP=");
 	endptr = strstr(metaptr, utlstr);
     }
 
@@ -2692,7 +2686,7 @@ EHmetagroup(int32 sdInterfaceID, char *structname, char *structcode,
 |  END_PROLOG                                                                 |
 -----------------------------------------------------------------------------*/
 intn
-EHfillfld(int32 sdid, int32 rank, int32 truerank, int32 size, int32 off,
+EHfillfld(int32 sdid, int32 rank, CPL_UNUSED int32 truerank, int32 size, int32 off,
 	  int32 dims[], VOIDP fillval)
 {
     intn            i;		/* Loop index */
@@ -2906,8 +2900,8 @@ EHfillfld(int32 sdid, int32 rank, int32 truerank, int32 size, int32 off,
 |  func()         float64             Function to bisect                      |
 |  funcParms      float64             Function parameters (fixed)             |
 |  nParms         int32               Number of function parameters           |
-|  limLft         float64             Lower limit of function arguement       |
-|  limRgt         float64             Upper limit of function arguement       |
+|  limLft         float64             Lower limit of function argument       |
+|  limRgt         float64             Upper limit of function argument       |
 |  convCrit       float64             Convergence criterion                   |
 |                                                                             |
 |  OUTPUTS:                                                                   |
@@ -3087,8 +3081,8 @@ EHattr(int32 fid, int32 attrVgrpID, char *attrname, int32 numbertype,
      */
 
 
-    /* Get Attribute Vdata ID and "open" with approriate I/O code */
-    /* ---------------------------------------------------------- */
+    /* Get Attribute Vdata ID and "open" with appropriate I/O code */
+    /* ----------------------------------------------------------- */
     vdataID = EHgetid(fid, attrVgrpID, attrname, 1, wrcode);
 
     /* Write Attribute Section */
@@ -3322,7 +3316,7 @@ EHattrcat(int32 fid, int32 attrVgrpID, char *attrnames, int32 * strbufsize)
 		}
 		/* Increment attribute names string length */
 		/* --------------------------------------- */
-		slen = (nattr == 1) ? strlen(name) : strlen(name) + 1;
+		slen = (nattr == 1) ? (int)strlen(name) : (int)strlen(name) + 1;
 		*strbufsize += slen;
 	    }
 	    VSdetach(vdataID);
@@ -3393,7 +3387,7 @@ EHinquire(char *filename, char *type, char *objectlist, int32 * strbufsize)
     {
 	*strbufsize = 0;
     }
-    /* Search for objects from begining of HDF file */
+    /* Search for objects from beginning of HDF file */
     /* -------------------------------------------- */
     vgRef = -1;
 
@@ -3443,7 +3437,7 @@ EHinquire(char *filename, char *type, char *objectlist, int32 * strbufsize)
 	    }
 	    /* Compute string length of object entry */
 	    /* ------------------------------------- */
-	    slen = (nobj == 1) ? strlen(name) : strlen(name) + 1;
+	    slen = (nobj == 1) ? (int)strlen(name) : (int)strlen(name) + 1;
 
 
 	    /* If string buffer size is requested then increment buffer size */
diff --git a/frmts/hdf4/hdf-eos/GDapi.c b/frmts/hdf4/hdf-eos/GDapi.c
index 3fd0f82..58adbf9 100644
--- a/frmts/hdf4/hdf-eos/GDapi.c
+++ b/frmts/hdf4/hdf-eos/GDapi.c
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * $Id: GDapi.c 29336 2015-06-14 17:37:21Z rouault $
+ * $Id: GDapi.c 33123 2016-01-23 18:59:28Z rouault $
  *
  * This module has a number of additions and improvements over the original
  * implementation to be suitable for usage in GDAL HDF driver.
@@ -20,17 +20,17 @@ REVISIONS:
 
 Aug 31, 1999  Abe Taaheri    Changed memory allocation for utility strings to
                              the size of UTLSTR_MAX_SIZE.
-			     Added error check for memory unavailibilty in 
+			     Added error check for memory unavailability in
 			     several functions.
-			     Added check for NULL metabuf returned from 
-			     EHmeta... functions. NULL pointer retruned from 
+			     Added check for NULL metabuf returned from
+			     EHmeta... functions. NULL pointer returned from
 			     EHmeta... functions indicate that memory could not
 			     be allocated for metabuf.
-Jun  27, 2000  Abe Taaheri   Added support for EASE grid that uses 
+Jun  27, 2000  Abe Taaheri   Added support for EASE grid that uses
                              Behrmann Cylinderical Equal Area (BCEA) projection
 Oct  23, 2000  Abe Taaheri   Updated for ISINUS projection, so that both codes
                              31 and 99 can be used for this projection.
-Jan  15, 2003   Abe Taaheri  Modified for generalization of EASE Grid. 
+Jan  15, 2003   Abe Taaheri  Modified for generalization of EASE Grid.
 
 Jun  05, 2003 Bruce Beaumont / Abe Taaheri
 
@@ -101,7 +101,6 @@ extern  void inv_init(int32, int32, float64 *, int32, char *, char *, int32 *,
 
 #define	GDIDOFFSET 4194304
 #define SQUARE(x)       ((x) * (x))   /* x**2 */
-#define M_PI1		3.14159265358979323846
 
 static int32 GDXSDcomb[512*5];
 static char  GDXSDname[HDFE_NAMBUFSIZE];
@@ -157,7 +156,7 @@ static struct gridRegion *GDXRegion[NGRIDREGN];
 /* Static projection table */
 static const struct {
     int32 projcode;
-    char *projname;
+    const char *projname;
 } Projections[] = {
     {GCTP_GEO,	   "GCTP_GEO"},
     {GCTP_UTM,	   "GCTP_UTM"},
@@ -198,7 +197,7 @@ static const struct {
 };
 
 /* Compression Codes */
-static const char *HDFcomp[] = {
+static const char * const HDFcomp[] = {
     "HDFE_COMP_NONE",
     "HDFE_COMP_RLE",
     "HDFE_COMP_NBIT",
@@ -207,7 +206,7 @@ static const char *HDFcomp[] = {
 };
 
 /* Origin Codes */
-static const char *originNames[] = {
+static const char * const originNames[] = {
     "HDFE_GD_UL",
     "HDFE_GD_UR",
     "HDFE_GD_LL",
@@ -215,7 +214,7 @@ static const char *originNames[] = {
 };
 
 /* Pixel Registration Codes */
-static const char *pixregNames[] = {
+static const char * const pixregNames[] = {
     "HDFE_CENTER",
     "HDFE_CORNER"
 };
@@ -258,7 +257,7 @@ static intn GDmm2ll_cea(int32, int32, int32, float64[],	int32, int32,
 |                                                                             |
 |  INPUTS:                                                                    |
 |  filename       char                Filename                                |
-|  access         intn                HDF access code                         |
+|  l_access         intn                HDF l_access code                         |
 |                                                                             |
 |                                                                             |
 |  OUTPUTS:                                                                   |
@@ -274,14 +273,14 @@ static intn GDmm2ll_cea(int32, int32, int32, float64[],	int32, int32,
 |  END_PROLOG                                                                 |
 -----------------------------------------------------------------------------*/
 int32
-GDopen(char *filename, intn access)
+GDopen(char *filename, intn l_access)
 
 {
     int32           fid /* HDF-EOS file ID */ ;
 
-    /* Call EHopen to perform file access */
+    /* Call EHopen to perform file l_access */
     /* ---------------------------------- */
-    fid = EHopen(filename, access);
+    fid = EHopen(filename, l_access);
 
     return (fid);
 
@@ -332,7 +331,7 @@ GDcreate(int32 fid, char *gridname, int32 xdimsize, int32 ydimsize,
     intn            ngridopen = 0;	/* # of grid structures open */
     intn            status = 0;	/* routine return status variable */
 
-    uint8           access;	/* Read/Write file access code */
+    uint8           l_access;	/* Read/Write file l_access code */
 
     int32           HDFfid;	/* HDF file id */
     int32           vgRef;	/* Vgroup reference number */
@@ -355,9 +354,9 @@ GDcreate(int32 fid, char *gridname, int32 xdimsize, int32 ydimsize,
 
     /*
      * Check HDF-EOS file ID, get back HDF file ID, SD interface ID  and
-     * access code
+     * l_access code
      */
-    status = EHchkfid(fid, gridname, &HDFfid, &sdInterfaceID, &access);
+    status = EHchkfid(fid, gridname, &HDFfid, &sdInterfaceID, &l_access);
 
 
     /* Check gridname for length */
@@ -465,14 +464,14 @@ GDcreate(int32 fid, char *gridname, int32 xdimsize, int32 ydimsize,
 
 		/* Establish Grid in Structural MetaData Block */
 		/* -------------------------------------------- */
-		sprintf(header, "%s%d%s%s%s%s%d%s%s%d%s",
+		snprintf(header, sizeof(header), "%s%d%s%s%s%s%d%s%s%d%s",
 			"\tGROUP=GRID_", (int)(nGrid + 1),
 			"\n\t\tGridName=\"", gridname, "\"\n",
 			"\t\tXDim=", (int)xdimsize, "\n",
 			"\t\tYDim=", (int)ydimsize, "\n");
 
 
-		sprintf(footer,
+		snprintf(footer, sizeof(footer), 
 			"%s%s%s%s%s%s%s%d%s",
 			"\t\tGROUP=Dimension\n",
 			"\t\tEND_GROUP=Dimension\n",
@@ -495,14 +494,14 @@ GDcreate(int32 fid, char *gridname, int32 xdimsize, int32 ydimsize,
 		}
 		else
 		{
-		    CPLsprintf(refstr1, "%s%f%s%f%s",
+		    CPLsnprintf(refstr1, sizeof(refstr1), "%s%f%s%f%s",
 			    "(", upleftpt[0], ",", upleftpt[1], ")");
 
-		    CPLsprintf(refstr2, "%s%f%s%f%s",
+		    CPLsnprintf(refstr2, sizeof(refstr2), "%s%f%s%f%s",
 			    "(", lowrightpt[0], ",", lowrightpt[1], ")");
 		}
 
-		sprintf(utlbuf,
+		snprintf(utlbuf, sizeof(utlbuf),
 			"%s%s%s%s%s%s%s%s",
 			header,
 			"\t\tUpperLeftPointMtrs=", refstr1, "\n",
@@ -568,7 +567,7 @@ GDcreate(int32 fid, char *gridname, int32 xdimsize, int32 ydimsize,
 |                                                                             |
 |  INPUTS:                                                                    |
 |  fid            int32               HDF-EOS file id                         |
-|  gridname       char                grid sructure name                      |
+|  gridname       char                grid structure name                     |
 |                                                                             |
 |                                                                             |
 |  OUTPUTS:                                                                   |
@@ -594,7 +593,7 @@ GDattach(int32 fid, char *gridname)
     intn            ngridopen = 0;	/* # of grid structures open */
     intn            status;	/* routine return status variable */
 
-    uint8           acs;	/* Read/Write file access code */
+    uint8           acs;	/* Read/Write file l_access code */
 
     int32           HDFfid;	/* HDF file id */
     int32           vgRef;	/* Vgroup reference number */
@@ -602,28 +601,28 @@ GDattach(int32 fid, char *gridname)
     int32           gridID = -1;/* HDF-EOS grid ID */
     int32          *tags;	/* Pnt to Vgroup object tags array */
     int32          *refs;	/* Pnt to Vgroup object refs array */
-    int32           dum;	/* dummy varible */
+    int32           dum;	/* dummy variable */
     int32           sdInterfaceID;	/* HDF SDS interface ID */
     int32           nObjects;	/* # of objects in Vgroup */
     int32           nSDS;	/* SDS counter */
-    int32           index;	/* SDS index */
+    int32           l_index;	/* SDS l_index */
     int32           sdid;	/* SDS object ID */
     int32           idOffset = GDIDOFFSET;	/* Grid ID offset */
 
     char            name[80];	/* Vgroup name */
     char            class[80];	/* Vgroup class */
     char            errbuf[256];/* Buffer for error message */
-    char            acsCode[1];	/* Read/Write access char: "r/w" */
+    char            acsCode[1];	/* Read/Write l_access char: "r/w" */
 
 
-    /* Check HDF-EOS file ID, get back HDF file ID and access code */
+    /* Check HDF-EOS file ID, get back HDF file ID and l_access code */
     /* ----------------------------------------------------------- */
     status = EHchkfid(fid, gridname, &HDFfid, &dum, &acs);
 
 
     if (status == 0)
     {
-	/* Convert numeric access code to character */
+	/* Convert numeric l_access code to character */
 	/* ---------------------------------------- */
 
 	acsCode[0] = (acs == 1) ? 'w' : 'r';
@@ -774,8 +773,8 @@ GDattach(int32 fid, char *gridname)
 			    /* ---------------------------- */
 			    if (tags[j] == DFTAG_NDG)
 			    {
-				index = SDreftoindex(sdInterfaceID, refs[j]);
-				sdid = SDselect(sdInterfaceID, index);
+				l_index = SDreftoindex(sdInterfaceID, refs[j]);
+				sdid = SDselect(sdInterfaceID, l_index);
 				GDXGrid[i].sdsID[nSDS] = sdid;
 				nSDS++;
 				GDXGrid[i].nSDS++;
@@ -857,7 +856,7 @@ GDchkgdid(int32 gridID, char *routname,
 	  int32 * fid, int32 * sdInterfaceID, int32 * gdVgrpID)
 {
     intn            status = 0;	/* routine return status variable */
-    uint8           access;	/* Read/Write access code */
+    uint8           l_access;	/* Read/Write l_access code */
     int32           gID;	/* Grid ID - offset */
 
     int32           idOffset = GDIDOFFSET;	/* Grid ID offset */
@@ -899,7 +898,7 @@ GDchkgdid(int32 gridID, char *routname,
 	    /* Get file & SDS ids and Grid key */
 	    /* -------------------------------- */
 	    status = EHchkfid(GDXGrid[gID].fid, " ",
-			      fid, sdInterfaceID, &access);
+			      fid, sdInterfaceID, &l_access);
 	    *gdVgrpID = GDXGrid[gID].IDTable;
 	}
     }
@@ -923,7 +922,7 @@ GDchkgdid(int32 gridID, char *routname,
 |  INPUTS:                                                                    |
 |  gridID         int32               grid structure ID                       |
 |  dimname        char                Dimension name to define                |
-|  dim            int32               Dimemsion value                         |
+|  dim            int32               Dimension value                         |
 |                                                                             |
 |                                                                             |
 |  OUTPUTS:                                                                   |
@@ -1017,7 +1016,7 @@ GDdefproj(int32 gridID, int32 projcode, int32 zonecode, int32 spherecode,
 	  float64 projparm[])
 {
     intn            i;		/* Loop index */
-    intn	    projx;	/* Projection table index */
+    intn	    projx;	/* Projection table l_index */
     intn            status = 0;	/* routine return status variable */
 
     int32           fid;	/* HDF-EOS file ID */
@@ -1062,18 +1061,18 @@ GDdefproj(int32 gridID, int32 projcode, int32 zonecode, int32 spherecode,
 		    /* if projparm[i] is integer ... */
 		    if ((int32) projparm[i] == projparm[i])
 		    {
-			sprintf(utlbuf, "%d%s",
+			snprintf(utlbuf, sizeof(utlbuf), "%d%s",
 				(int) projparm[i], ",");
 		    }
 		    /* else projparm[i] is non-zero floating point ... */
 		    else
 		    {
-			CPLsprintf(utlbuf, "%f%s",	projparm[i], ",");
+			CPLsnprintf(utlbuf, sizeof(utlbuf), "%f%s",	projparm[i], ",");
 		    }
 		}
 		strcat(projparmbuf, utlbuf);
 	    }
-	    slen = strlen(projparmbuf);
+	    slen = (int)strlen(projparmbuf);
 
 	    /* Add trailing ")" */
 	    projparmbuf[slen - 1] = ')';
@@ -1090,15 +1089,15 @@ GDdefproj(int32 gridID, int32 projcode, int32 zonecode, int32 spherecode,
 
 	/* Build metadata string */
 	/* --------------------- */
-	if ((projcode == GCTP_GEO))
+	if (projcode == GCTP_GEO)
 	{
-	    sprintf(utlbuf,
+	    snprintf(utlbuf, sizeof(utlbuf),
 		    "%s%s%s",
 		    "\t\tProjection=", Projections[projx].projname, "\n");
 	}
 	else if (projcode == GCTP_UTM || projcode == GCTP_SPCS)
 	{
-	    sprintf(utlbuf,
+	    snprintf(utlbuf, sizeof(utlbuf),
 		    "%s%s%s%s%d%s%s%d%s",
 		    "\t\tProjection=", Projections[projx].projname, "\n",
 		    "\t\tZoneCode=", (int)zonecode, "\n",
@@ -1106,7 +1105,7 @@ GDdefproj(int32 gridID, int32 projcode, int32 zonecode, int32 spherecode,
 	}
 	else
 	{
-	    sprintf(utlbuf,
+	    snprintf(utlbuf, sizeof(utlbuf),
 		    "%s%s%s%s%s%s%s%d%s",
 		    "\t\tProjection=", Projections[projx].projname, "\n",
 		    "\t\tProjParams=", projparmbuf, "\n",
@@ -1187,7 +1186,7 @@ GDblkSOMoffset(int32 gridID, float32 offset[], int32 count, char *code)
 	if (projcode == GCTP_SOM && projparm[11] != 0)
 	{
 	    Vgetname(GDXGrid[gridID % idOffset].IDTable, gridname);
-	    sprintf(utlbuf, "%s%s", "_BLKSOM:", gridname);
+	    snprintf(utlbuf, sizeof(utlbuf),"%s%s", "_BLKSOM:", gridname);
 
 	    /* Write offset values as attribute */
 	    if (strcmp(code, "w") == 0)
@@ -1253,7 +1252,7 @@ GDdefcomp(int32 gridID, int32 compcode, intn compparm[])
     {
 	gID = gridID % idOffset;
 
-	/* Set compression code in compression exteral array */
+	/* Set compression code in compression external array */
 	GDXGrid[gID].compcode = compcode;
 
 	switch (compcode)
@@ -1431,9 +1430,9 @@ GDdeforigin(int32 gridID, int32 origincode)
     {
 	/* If proper origin code then write to structural metadata */
 	/* ------------------------------------------------------- */
-	if (origincode >= 0 && origincode < sizeof(originNames))
+	if (origincode >= 0 && origincode < (int32)sizeof(originNames))
 	{
-	    sprintf(utlbuf, "%s%s%s",
+	    snprintf(utlbuf, sizeof(utlbuf),"%s%s%s",
 		    "\t\tGridOrigin=", originNames[origincode], "\n");
 
 	    Vgetname(GDXGrid[gridID % idOffset].IDTable, gridname);
@@ -1503,9 +1502,9 @@ GDdefpixreg(int32 gridID, int32 pixregcode)
     {
 	/* If proper pix reg code then write to structural metadata */
 	/* -------------------------------------------------------- */
-	if (pixregcode >= 0 && pixregcode < sizeof(pixregNames))
+	if (pixregcode >= 0 && pixregcode < (int32)sizeof(pixregNames))
 	{
-	    sprintf(utlbuf, "%s%s%s",
+	    snprintf(utlbuf, sizeof(utlbuf),"%s%s%s",
 		    "\t\tPixelRegistration=", pixregNames[pixregcode], "\n");
 
 	    Vgetname(GDXGrid[gridID % idOffset].IDTable, gridname);
@@ -1615,7 +1614,7 @@ GDdiminfo(int32 gridID, char *dimname)
 
 	/* Search for dimension name (surrounded by quotes) */
 	/* ------------------------------------------------ */
-	sprintf(utlstr, "%s%s%s", "\"", dimname, "\"\n");
+	snprintf(utlstr, UTLSTR_MAX_SIZE, "%s%s%s", "\"", dimname, "\"\n");
 	metaptrs[0] = strstr(metaptrs[0], utlstr);
 
 	/*
@@ -1631,7 +1630,7 @@ GDdiminfo(int32 gridID, char *dimname)
 
 	    if (status == 0)
 	    {
-		size = atol(utlstr);
+		size = atoi(utlstr);
 	    }
 	    else
 	    {
@@ -1745,7 +1744,7 @@ GDgridinfo(int32 gridID, int32 * xdimsize, int32 * ydimsize,
 	    statmeta = EHgetmetavalue(metaptrs, "XDim", utlstr);
 	    if (statmeta == 0)
 	    {
-		*xdimsize = atol(utlstr);
+		*xdimsize = atoi(utlstr);
 	    }
 	    else
 	    {
@@ -1763,7 +1762,7 @@ GDgridinfo(int32 gridID, int32 * xdimsize, int32 * ydimsize,
 	    statmeta = EHgetmetavalue(metaptrs, "YDim", utlstr);
 	    if (statmeta == 0)
 	    {
-		*ydimsize = atol(utlstr);
+		*ydimsize = atoi(utlstr);
 	    }
 	    else
 	    {
@@ -1981,7 +1980,7 @@ GDprojinfo(int32 gridID, int32 * projcode, int32 * zonecode,
 		statmeta = EHgetmetavalue(metaptrs, "ZoneCode", utlstr);
 		if (statmeta == 0)
 		{
-		    *zonecode = atol(utlstr);
+		    *zonecode = atoi(utlstr);
 		}
 		else
 		{
@@ -2063,7 +2062,7 @@ GDprojinfo(int32 gridID, int32 * projcode, int32 * zonecode,
 		EHgetmetavalue(metaptrs, "SphereCode", utlstr);
 		if (statmeta == 0)
 		{
-		    *spherecode = atol(utlstr);
+		    *spherecode = atoi(utlstr);
 		}
 	    }
 	}
@@ -2173,7 +2172,7 @@ GDorigininfo(int32 gridID, int32 * origincode)
 	     * If "GridOrigin" string found in metadata then convert to
 	     * numeric origin code (fixed added: Jan 97)
 	     */
-	    for (i = 0; i < sizeof(originNames); i++)
+	    for (i = 0; i < (intn)sizeof(originNames); i++)
 	    {
 		if (strcmp(utlstr, originNames[i]) == 0)
 		{
@@ -2288,7 +2287,7 @@ GDpixreginfo(int32 gridID, int32 * pixregcode)
 	     * to numeric origin code (fixed added: Jan 97)
 	     */
 
-	    for (i = 0; i < sizeof(pixregNames); i++)
+	    for (i = 0; i < (intn)sizeof(pixregNames); i++)
 	    {
 		if (strcmp(utlstr, pixregNames[i]) == 0)
 		{
@@ -2382,7 +2381,7 @@ GDcompinfo(int32 gridID, char *fieldname, int32 * compcode, intn compparm[])
 
 
 	/* Search for field */
-	sprintf(utlstr, "%s%s%s", "\"", fieldname, "\"\n");
+	snprintf(utlstr, UTLSTR_MAX_SIZE, "%s%s%s", "\"", fieldname, "\"\n");
 	metaptrs[0] = strstr(metaptrs[0], utlstr);
 
 
@@ -2407,7 +2406,7 @@ GDcompinfo(int32 gridID, char *fieldname, int32 * compcode, intn compparm[])
 		if (statmeta == 0)
 		{
 		    /* Loop through compression types until match */
-		    for (i = 0; i < sizeof(HDFcomp); i++)
+		    for (i = 0; i < (intn)sizeof(HDFcomp); i++)
 		    {
 			if (strcmp(utlstr, HDFcomp[i]) == 0)
 			{
@@ -2424,7 +2423,7 @@ GDcompinfo(int32 gridID, char *fieldname, int32 * compcode, intn compparm[])
 		/* Initialize to zero */
 		for (i = 0; i < 4; i++)
 		{
-		    compparm[i] = 0.0;
+		    compparm[i] = 0;
 		}
 
 		/*
@@ -2537,7 +2536,7 @@ GDfieldinfo(int32 gridID, char *fieldname, int32 * rank, int32 dims[],
     int32           fid;	    /* HDF-EOS file ID */
     int32           sdInterfaceID;  /* HDF SDS interface ID */
     int32           idOffset = GDIDOFFSET;  /* Grid ID offset */
-    int32           ndims;	    /* Number of dimensions */
+    int32           ndims = 0;	    /* Number of dimensions */
     int32           slen[8];	    /* Length of each entry in parsed string */
     int32           dum;	    /* Dummy variable */
     int32           xdim;	    /* X dim size */
@@ -2580,7 +2579,7 @@ GDfieldinfo(int32 gridID, char *fieldname, int32 * rank, int32 dims[],
 
 
 	/* Search for field */
-	sprintf(utlstr, "%s%s%s", "\"", fieldname, "\"\n");
+	snprintf(utlstr, UTLSTR_MAX_SIZE, "%s%s%s", "\"", fieldname, "\"\n");
 	metaptrs[0] = strstr(metaptrs[0], utlstr);
 
 	/* If field found ... */
@@ -2765,7 +2764,7 @@ GDdeffield(int32 gridID, char *fieldname, char *dimlist,
     float64         projparm[13];	/* Projection Parameters */
 
     char           *dimbuf;	/* Dimension buffer */
-    char           *dimlist0;	/* Auxilliary dimension list */
+    char           *dimlist0;	/* Auxiliary dimension list */
     char           *comma;	/* Pointer to comma */
     char           *dimcheck;	/* Dimension check buffer */
     char            utlbuf[512];/* Utility buffer */
@@ -2790,6 +2789,8 @@ GDdeffield(int32 gridID, char *fieldname, char *dimlist,
 
     HDF_CHUNK_DEF   chunkDef;	/* Tiling structure */
 
+    memset(&c_info, 0, sizeof(c_info));
+    memset(&chunkDef, 0, sizeof(chunkDef));
 
 
     /* Setup error message strings */
@@ -2820,8 +2821,8 @@ GDdeffield(int32 gridID, char *fieldname, char *dimlist,
 	Vgetname(GDXGrid[gID].IDTable, gridname);
 
 
-	/* Allocate space for dimension buffer and auxilliary dimension list */
-	/* ----------------------------------------------------------------- */
+	/* Allocate space for dimension buffer and auxiliary dimension list */
+	/* ---------------------------------------------------------------- */
 	dimbuf = (char *) calloc(strlen(dimlist) + 64, 1);
 	if(dimbuf == NULL)
 	{ 
@@ -2873,8 +2874,8 @@ GDdeffield(int32 gridID, char *fieldname, char *dimlist,
 	}
 
 	/*
-	 * Copy dimension buffer to auxilliary dimlist and Append comma to
-	 * end of dimension list
+	 * Copy dimension buffer to auxiliary dimlist and append a comma to
+	 * end of dimension list.
 	 */
 	strcpy(dimlist0, dimbuf);
 	strcat(dimbuf, ",");
@@ -2973,15 +2974,13 @@ GDdeffield(int32 gridID, char *fieldname, char *dimlist,
 	}
 	free(dimbuf);
 
-
-
 	/* Check fieldname length */
 	/* ---------------------- */
 	if (status == 0)
 	{
 /* if ((intn) strlen(fieldname) > MAX_NC_NAME - 7)
 ** this was changed because HDF4.1r3 made a change in the
-** hlimits.h file.  We have notidfied NCSA and asked to have 
+** hlimits.h file.  We have notified NCSA and asked to have 
 ** it made the same as in previous versions of HDF
 ** see ncr 26314.  DaW  Apr 2000
 */
@@ -2993,8 +2992,6 @@ GDdeffield(int32 gridID, char *fieldname, char *dimlist,
 	    }
 	}
 
-
-
 	/* Check for valid numbertype */
 	/* -------------------------- */
 	if (status == 0)
@@ -3022,7 +3019,7 @@ GDdeffield(int32 gridID, char *fieldname, char *dimlist,
 	/* ------------ */
 	if (status == 0)
 	{
-	    /* Get Field Vgroup id, compresion code, & tiling code */
+	    /* Get Field Vgroup id, compression code, & tiling code */
 	    /* -------------------------------------------------- */
 	    vgid = GDXGrid[gID].VIDTable[0];
 	    compcode = GDXGrid[gID].compcode;
@@ -3074,7 +3071,7 @@ GDdeffield(int32 gridID, char *fieldname, char *dimlist,
 		GDXSDcomb[5 * i + 4] = numbertype;
 
 
-		/* Concatanate fieldname with combined name string */
+		/* Concatenate fieldname with combined name string */
 		/* ----------------------------------------------- */
 		if ((intn) strlen(GDXSDname) +
 		    (intn) strlen(fieldname) + 2 < HDFE_NAMBUFSIZE)
@@ -3121,7 +3118,7 @@ GDdeffield(int32 gridID, char *fieldname, char *dimlist,
 
 		/*
 		 * Concatanate field dimlist to merged dimlist and separate
-		 * fields with semi-colon
+		 * fields with semi-colon.
 		 */
 		if ((intn) strlen(GDXSDdims) +
 		    (intn) strlen(dimlist0) + 2 < HDFE_DIMBUFSIZE)
@@ -3220,7 +3217,7 @@ GDdeffield(int32 gridID, char *fieldname, char *dimlist,
 		/* --------------------------------------------------------- */
 		if (compcode != HDFE_COMP_NONE && tilecode == HDFE_NOTILE)
 		{
-		    status = SDsetcompress(sdid, (comp_coder_t) compcode, &c_info);
+                    /* status = */ SDsetcompress(sdid, (comp_coder_t) compcode, &c_info);
 		}
 
 
@@ -3279,7 +3276,7 @@ GDdeffield(int32 gridID, char *fieldname, char *dimlist,
 
 		    /* Call SDsetchunk routine */
 		    /* ----------------------- */
-		    status = SDsetchunk(sdid, chunkDef, chunkFlag);
+		    /* status = */ SDsetchunk(sdid, chunkDef, chunkFlag);
 		}
 
 
@@ -3330,14 +3327,14 @@ GDdeffield(int32 gridID, char *fieldname, char *dimlist,
 
 	    /* Setup metadata string */
 	    /* --------------------- */
-	    sprintf(utlbuf, "%s%s%s", fieldname, ":", dimlist0);
+	    snprintf(utlbuf, sizeof(utlbuf), "%s%s%s", fieldname, ":", dimlist0);
 
 
 	    /* Setup compression metadata */
 	    /* -------------------------- */
 	    if (compcode != HDFE_COMP_NONE)
 	    {
-		sprintf(utlbuf2,
+		snprintf(utlbuf2, sizeof(utlbuf2),
 			"%s%s",
 			":\n\t\t\t\tCompressionType=", HDFcomp[compcode]);
 
@@ -3345,7 +3342,7 @@ GDdeffield(int32 gridID, char *fieldname, char *dimlist,
 		{
 		case HDFE_COMP_NBIT:
 
-		    sprintf(parmbuf,
+		    snprintf(parmbuf, sizeof(parmbuf),
 			    "%s%d,%d,%d,%d%s",
 			    "\n\t\t\t\tCompressionParams=(",
 			    GDXGrid[gID].compparm[0],
@@ -3358,7 +3355,7 @@ GDdeffield(int32 gridID, char *fieldname, char *dimlist,
 
 		case HDFE_COMP_DEFLATE:
 
-		    sprintf(parmbuf,
+		    snprintf(parmbuf, sizeof(parmbuf),
 			    "%s%d",
 			    "\n\t\t\t\tDeflateLevel=",
 			    GDXGrid[gID].compparm[0]);
@@ -3377,20 +3374,20 @@ GDdeffield(int32 gridID, char *fieldname, char *dimlist,
 	    {
 		if (compcode == HDFE_COMP_NONE)
 		{
-		    sprintf(utlbuf2, "%s%d",
+		    snprintf(utlbuf2, sizeof(utlbuf2), "%s%d",
 			    ":\n\t\t\t\tTilingDimensions=(",
 			    (int)GDXGrid[gID].tiledims[0]);
 		}
 		else
 		{
-		    sprintf(utlbuf2, "%s%d",
+		    snprintf(utlbuf2, sizeof(utlbuf2), "%s%d",
 			    "\n\t\t\t\tTilingDimensions=(",
 			    (int)GDXGrid[gID].tiledims[0]);
 		}
 
 		for (i = 1; i < GDXGrid[gID].tilerank; i++)
 		{
-		    sprintf(parmbuf, ",%d", (int)GDXGrid[gID].tiledims[i]);
+		    snprintf(parmbuf, sizeof(parmbuf), ",%d", (int)GDXGrid[gID].tiledims[i]);
 		    strcat(utlbuf2, parmbuf);
 		}
 		strcat(utlbuf2, ")");
@@ -3474,7 +3471,7 @@ GDwritefieldmeta(int32 gridID, char *fieldname, char *dimlist,
 
     if (status == 0)
     {
-	sprintf(utlbuf, "%s%s%s", fieldname, ":", dimlist);
+	snprintf(utlbuf, sizeof(utlbuf), "%s%s%s", fieldname, ":", dimlist);
 
 	Vgetname(GDXGrid[gridID % idOffset].IDTable, gridname);
 	status = EHinsertmeta(sdInterfaceID, gridname, "g", 4L,
@@ -3534,16 +3531,17 @@ GDSDfldsrch(int32 gridID, int32 sdInterfaceID, const char *fieldname,
     int32           idOffset = GDIDOFFSET;	/* Grid ID offset */
     int32           dum;	/* Dummy variable */
     int32           dums[128];	/* Dummy array */
-    int32           attrIndex;	/* Attribute index */
+    int32           attrIndex;	/* Attribute l_index */
 
     char            name[2048];	/* Merged-Field Names */
     char            gridname[80];	/* Grid Name */
     char           *utlstr;/* Utility string */
     char           *metabuf;	/* Pointer to structural metadata (SM) */
     char           *metaptrs[2];/* Pointers to begin and end of SM section */
+#ifdef broken_logic
     char           *oldmetaptr;	/* Pointer within SM section */
     char           *metaptr;	/* Pointer within SM section */
-
+#endif
 
     /* Allocate space for utility string */
     /* --------------------------------- */
@@ -3597,7 +3595,7 @@ GDSDfldsrch(int32 gridID, int32 sdInterfaceID, const char *fieldname,
 		    return(-1);
 		}  
 
-
+#ifdef broken_logic
 		/* Initialize metaptr to beg. of section */
 		/* ------------------------------------- */
 		metaptr = metaptrs[0];
@@ -3610,7 +3608,7 @@ GDSDfldsrch(int32 gridID, int32 sdInterfaceID, const char *fieldname,
 
 		/* Search for Merged field name */
 		/* ---------------------------- */
-		sprintf(utlstr, "%s%s%s", "MergedFieldName=\"",
+		snprintf(utlstr, UTLSTR_MAX_SIZE, "%s%s%s", "MergedFieldName=\"",
 			name, "\"\n");
 		metaptr = strstr(metaptr, utlstr);
 
@@ -3619,10 +3617,10 @@ GDSDfldsrch(int32 gridID, int32 sdInterfaceID, const char *fieldname,
 		/* ----------------------------------- */
 		if (metaptr == NULL)
 		{
-		    sprintf(utlstr, "%s%s%s", "OBJECT=\"", name, "\"\n");
+		    snprintf(utlstr, UTLSTR_MAX_SIZE, "%s%s%s", "OBJECT=\"", name, "\"\n");
 		    metaptr = strstr(oldmetaptr, utlstr);
 		}
-
+#endif
 
 		/* Get field list and strip off leading and trailing quotes */
 		/* -------------------------------------------------------- */
@@ -3633,7 +3631,7 @@ GDSDfldsrch(int32 gridID, int32 sdInterfaceID, const char *fieldname,
 
 		/* Search for desired field within merged field list */
 		/* ------------------------------------------------- */
-		sprintf(utlstr, "%s%s%s", "\"", fieldname, "\"");
+		snprintf(utlstr, UTLSTR_MAX_SIZE, "%s%s%s", "\"", fieldname, "\"");
 		dum = EHstrwithin(utlstr, name, ',');
 
 		free(metabuf);
@@ -3662,7 +3660,7 @@ GDSDfldsrch(int32 gridID, int32 sdInterfaceID, const char *fieldname,
 		/* ------------------- */
 		if (*solo == 0)
 		{
-		    /* Get "Field Offsets" SDS attribute index */
+		    /* Get "Field Offsets" SDS attribute l_index */
 		    /* --------------------------------------- */
 		    attrIndex = SDfindattr(*sdid, "Field Offsets");
 
@@ -3677,7 +3675,7 @@ GDSDfldsrch(int32 gridID, int32 sdInterfaceID, const char *fieldname,
 		    }
 
 
-		    /* Get "Field Dims" SDS attribute index */
+		    /* Get "Field Dims" SDS attribute l_index */
 		    /* ------------------------------------ */
 		    attrIndex = SDfindattr(*sdid, "Field Dims");
 
@@ -4491,7 +4489,7 @@ GDinqdims(int32 gridID, char *dimnames, int32 dims[])
 		    if (dims != NULL)
 		    {
 			EHgetmetavalue(metaptrs, "Size", utlstr);
-			size = atol(utlstr);
+			size = atoi(utlstr);
 			dims[nDim] = size;
 		    }
 		    nDim++;
@@ -4846,7 +4844,7 @@ GDnentries(int32 gridID, int32 entrycode, int32 * strbufsize)
 		     * Get all string values Don't count quotes
 		     */
 		    EHgetmetavalue(metaptrs, &valName[i][0], utlstr);
-		    *strbufsize += strlen(utlstr) - 2;
+		    *strbufsize += (int32)strlen(utlstr) - 2;
 		}
 		/* Increment number of entries */
 		nEntries++;
@@ -4993,7 +4991,7 @@ GDsetfillvalue(int32 gridID, char *fieldname, VOIDP fillval)
 	    /* If unmerged field then call HDF set field routine */
 	    if (solo == 1)
 	    {
-		status = SDsetfillvalue(sdid, fillval);
+                /* status = */ SDsetfillvalue(sdid, fillval);
 	    }
 
 	    /*
@@ -5398,7 +5396,7 @@ GDdetach(int32 gridID)
 		    return(-1);
 		}
 
-		for (k = 0; k < sizeof(dimbuf1); k++)
+		for (k = 0; k < (intn)sizeof(dimbuf1); k++)
 		    dimbuf1[k] = 0;
 
 
@@ -5420,7 +5418,7 @@ GDdetach(int32 gridID)
 
 		for (j = i + 1, cmbfldcnt = 0; j < nflds; j++)
 		{
-		    for (k = 0; k < sizeof(dimbuf2); k++)
+		    for (k = 0; k < (intn)sizeof(dimbuf2); k++)
 			dimbuf2[k] = 0;
 		    memcpy(dimbuf2, dimptr[j], dimlen[j]);
 		    dum = EHparsestr(dimbuf2, ',', ptr2, slen2);
@@ -5438,7 +5436,7 @@ GDdetach(int32 gridID)
 			/* Add to combined dimension size */
 			match[0] += GDXSDcomb[5 * j];
 
-			/* Concatanate name */
+			/* Concatenate name */
 			strcat(nambuf, ",");
 			memcpy(nambuf + strlen(nambuf),
 			       nameptr[j], namelen[j]);
@@ -5526,7 +5524,7 @@ GDdetach(int32 gridID)
 
 		    if (k == 0 && rank > 2 && cmbfldcnt > 0)
 		    {
-			sprintf(dimbuf2, "%s%s_%d", "MRGDIM:",
+			snprintf(dimbuf2, sizeof(dimbuf2), "%s%s_%d", "MRGDIM:",
 				gridname, (int)dims[0]);
 		    }
 		    else
@@ -5762,7 +5760,7 @@ GDclose(int32 fid)
 |  Aug 96   Joel Gales    Original Programmer                                 |
 |  Sep 96   Raj Gejjaga   Fixed  bugs in Polar Stereographic and Goode        | |                         Homolosine default calculations.                    |
 |  Sep 96   Raj Gejjaga   Added code to compute default boundary points       |
-|                         for Lambert Azimuthal Polar and Equitorial          |
+|                         for Lambert Azimuthal Polar and Equatorial          |
 |                         projections.                                        |
 |  Feb 97   Raj Gejjaga   Added code to compute default boundary points       |
 |                         for Integerized Sinusoidal Grid.  Added error       |
@@ -6081,7 +6079,7 @@ GDgetdefaults(int32 projcode, int32 zonecode, float64 projparm[],
 
 	/*
 	 * Compute upperleft and lowerright values based on whether the
-	 * projection is south polar, north polar or equitorial
+	 * projection is south polar, north polar or equatorial
 	 */
 
 	if (plat == -90.0)
@@ -6325,7 +6323,7 @@ GDll2ij(int32 projcode, int32 zonecode, float64 projparm[],
     float64         scaleX;	/* X scale factor */
     float64         scaleY;	/* Y scale factor */
     float64         EHconvAng();/* Angle conversion routine */
-    float64         xMtr0, xMtr1, yMtr0, yMtr1;
+    float64         xMtr0 = 0, xMtr1, yMtr0 = 0, yMtr1;
     float64         lonrad1;	/* Longitude in radians of lowright point */
 
     /* If projection not GEO call GCTP initialization routine */
@@ -6455,14 +6453,14 @@ GDll2ij(int32 projcode, int32 zonecode, float64 projparm[],
 	    /* -------------- */
 	    if (projcode == GCTP_GEO)
 	    {
-	        /*allow map to span dateline */
+	        /* allow map to span dateline */
 	        lonrad0 = EHconvAng(upleftpt[0], HDFE_DMS_RAD);
 	        lonrad1 = EHconvAng(lowrightpt[0], HDFE_DMS_RAD);
-		/* if time-line is paased */
+		/* if time-line is passed */
 		if(lonrad < lonrad1)
 		  {
-		    if (lonrad < lonrad0) lonrad += 2.0 * M_PI1;
-		    if (lonrad > lonrad1) lonrad -= 2.0 * M_PI1;
+		    if (lonrad < lonrad0) lonrad += 2.0 * M_PI;
+		    if (lonrad > lonrad1) lonrad -= 2.0 * M_PI;
 		  }
 
 		/* Compute scaled distance to point from origin */
@@ -6491,7 +6489,7 @@ GDll2ij(int32 projcode, int32 zonecode, float64 projparm[],
 		    function cproj.c of GCTP) */
 		else {
 		  /* if projection is BCEA normalize x and y by cell size and
-		     measure it from the uperleft corner of the grid */
+		     measure it from the upperleft corner of the grid */
 		  
 		  /* Compute scaled distance to point from origin */
 		  /* -------------------------------------------- */
@@ -6539,7 +6537,7 @@ GDll2ij(int32 projcode, int32 zonecode, float64 projparm[],
 |  FUNCTION: GDrs2ll                                                          |
 |                                                                             |
 |  DESCRIPTION:  Converts EASE grid's (r,s) coordinates to longitude and      |
-|                latritude (in decimal degrees).                              |
+|                latitude (in decimal degrees).                               |
 |                                                                             |
 |                                                                             |
 |  Return Value    Type     Units     Description                             |
@@ -6754,13 +6752,13 @@ GDrs2ll(int32 projcode, float64 projparm[],
 		{
 		  errorcode = inv_trans[projcode] (xMtr, 0.0,
 						   &lonrad, &latrad);
-		  latrad = - M_PI1/2;
+		  latrad = - M_PI/2;
 		}
 	      else if( beta >= 1)
 		{
 		  errorcode = inv_trans[projcode] (xMtr, 0.0,
 						   &lonrad, &latrad);
-		  latrad = M_PI1/2;
+		  latrad = M_PI/2;
 		}
 	      else
 		{
@@ -6821,7 +6819,7 @@ GDrs2ll(int32 projcode, float64 projparm[],
 |                                                                             |
 |  END_PROLOG                                                                 |
 -----------------------------------------------------------------------------*/
-float64
+static float64
 lamazDxDtheta(float64 parms[])
 {
     float64         snTheta, sn2Theta, snTheta1, csTheta1, csLamda;
@@ -6868,7 +6866,7 @@ lamazDxDtheta(float64 parms[])
 |                                                                             |
 |  END_PROLOG                                                                 |
 -----------------------------------------------------------------------------*/
-float64
+static float64
 lamazDxDlamda(float64 parms[])
 {
     float64         snTheta, csTheta, snTheta1, csTheta1, csLamda;
@@ -6916,7 +6914,7 @@ lamazDxDlamda(float64 parms[])
 |                                                                             |
 |  END_PROLOG                                                                 |
 -----------------------------------------------------------------------------*/
-float64
+static float64
 lamazDyDtheta(float64 parms[])
 {
     float64         snTheta, csTheta, snTheta1, csTheta1, csLamda;
@@ -6966,7 +6964,7 @@ lamazDyDtheta(float64 parms[])
 |                                                                             |
 |  END_PROLOG                                                                 |
 -----------------------------------------------------------------------------*/
-float64
+static float64
 homDyDtheta(float64 parms[])
 {
     float64         tnTheta, tnTheta1, snLamda;
@@ -7014,7 +7012,7 @@ homDyDtheta(float64 parms[])
 |  Nov 96   Joel Gales    Original Programmer                                 |
 |  Mar 97   Joel Gales    Add support for LAMCC, POLYC, TM                    |
 |  Aug 99   Abe Taaheri   Add support for ALBERS, and MERCAT projections.     |
-|                         Also changed misstyped bisectParm[2] to             |
+|                         Also changed mistyped bisectParm[2] to              |
 |                         bisectParm[3] for HOM projection.                   |
 |  Jun 00   Abe Taaheri   Added support for EASE grid                         |
 |                                                                             |
@@ -7040,20 +7038,21 @@ GDtangentpnts(int32 projcode, float64 projparm[], float64 cornerlon[],
     float64         minLat;	/* Minimum latitude */
     float64         bisectParm[4];	/* Bisection parameters */
     float64         tanLat;	/* Tangent latitude */
-    float64         tanLon;	/* Tangent lontitude */
+    float64         tanLon;	/* Tangent longitude */
     float64         dotPrd;	/* Dot product */
     float64         centMerd;	/* Central Meridian */
     float64         orgLat;	/* Latitude of origin */
     float64         dpi;	/* Double precision pi */
 
+#if 0
     float64         lamazDxDtheta();	/* Lambert Azimuthal Dx/Dtheta */
     float64         lamazDxDlamda();	/* Lambert Azimuthal Dx/Dlamda */
     float64         lamazDyDtheta();	/* Lambert Azimuthal Dy/Dtheta */
     float64         homDyDtheta();	/* Oblique Mercator  Dy/Dtheta */
+#endif
 
-
-    /* Conpute pi (double precsion) */
-    /* ---------------------------- */
+    /* Compute pi (double precision) */
+    /* ----------------------------- */
     dpi = atan(1.0) * 4;
 
 
@@ -7620,10 +7619,10 @@ GDdefboxregion(int32 gridID, float64 cornerlon[], float64 cornerlat[])
     int32           spherecode;	    /* Sphere code */
     int32           row[32];	    /* Row array */
     int32           col[32];	    /* Column array */
-    int32           minCol = 0;	    /* Minimun column value */
-    int32           minRow = 0;	    /* Minimun row value */
-    int32           maxCol = 0;	    /* Maximun column value */
-    int32           maxRow = 0;	    /* Maximun row value */
+    int32           minCol = 0;	    /* Minimum column value */
+    int32           minRow = 0;	    /* Minimum row value */
+    int32           maxCol = 0;	    /* Maximum column value */
+    int32           maxRow = 0;	    /* Maximum row value */
     int32           npnts;	    /* Number of boundary
                                        (edge & tangent) pnts */
 
@@ -7763,7 +7762,7 @@ GDdefboxregion(int32 gridID, float64 cornerlon[], float64 cornerlat[])
         if (projcode == GCTP_SOM && projparm[11] != 0)
         {
             Vgetname(GDXGrid[gridID % idOffset].IDTable, gridname);
-            sprintf(utlbuf, "%s%s", "_BLKSOM:", gridname);
+            snprintf(utlbuf, 128, "%s%s", "_BLKSOM:", gridname);
 	    status = GDreadattr(gridID, utlbuf, offset);
 
             somupleftpt[0] = upleftpt[0];
@@ -7850,10 +7849,12 @@ GDdefboxregion(int32 gridID, float64 cornerlon[], float64 cornerlat[])
                       blockindexstop = j;
                    }
                 }
-                templeftpt[0] = upleftpt[0] + ((offset[j]/xdimsize)*abs(upleftpt[0] - lowrightpt[0])) + abs((upleftpt[0] - lowrightpt[0]))*(n-1);
+
+                // E. Rouault: FIXME: was really abs(int) indented here ? Forcing the cast to int to please compilers
+                templeftpt[0] = upleftpt[0] + ((offset[j]/xdimsize)*abs((int)(upleftpt[0] - lowrightpt[0]))) + abs((int)(upleftpt[0] - lowrightpt[0]))*(n-1);
                 templeftpt[1] = upleftpt[1] + ((lowrightpt[1] - upleftpt[1]))*(n-1);
 
-                temprightpt[0] = lowrightpt[0] + ((offset[j]/xdimsize)*abs(lowrightpt[0] - upleftpt[0])) + abs((lowrightpt[0] - upleftpt[0]))*(n-1);
+                temprightpt[0] = lowrightpt[0] + ((offset[j]/xdimsize)*abs((int)(lowrightpt[0] - upleftpt[0]))) + abs((int)(lowrightpt[0] - upleftpt[0]))*(n-1);
                 temprightpt[1] = lowrightpt[1] + ((upleftpt[1] - lowrightpt[1]))*(n-1);
 
                 somupleftpt[0] = templeftpt[0];
@@ -8232,7 +8233,7 @@ GDregioninfo(int32 gridID, int32 regionID, char *fieldname,
     int32           fid;	/* HDF-EOS file ID */
     int32           sdInterfaceID;	/* HDF SDS interface ID */
     int32           gdVgrpID;	/* Grid root Vgroup ID */
-    int32           index;	/* Dimension index */
+    int32           l_index;	/* Dimension l_index */
 
     char            dimlist[256];	/* Dimension list */
     char           *errMesg = "Vertical Dimension Not Found: \"%s\".\n";
@@ -8335,7 +8336,7 @@ GDregioninfo(int32 gridID, int32 regionID, char *fieldname,
 	    {
 		status = -1;
 		HEpush(DFE_GENAPP, "GDregioninfo", __FILE__, __LINE__);
-		sprintf(errbuf, "%s%s", errM1, errM2);
+		snprintf(errbuf, sizeof(errbuf), "%s%s", errM1, errM2);
 		HEreport(errbuf, fieldname);
 	    }
 	}
@@ -8383,16 +8384,16 @@ GDregioninfo(int32 gridID, int32 regionID, char *fieldname,
 	    {
 		/* Find vertical dimension within dimlist */
 		/* -------------------------------------- */
-		index = EHstrwithin(GDXRegion[regionID]->DimNamePtr[j],
+		l_index = EHstrwithin(GDXRegion[regionID]->DimNamePtr[j],
 				    dimlist, ',');
 
 		/* If dimension found ... */
 		/* ---------------------- */
-		if (index != -1)
+		if (l_index != -1)
 		{
 		    /* Compute dimension size */
 		    /* ---------------------- */
-		    dims[index] =
+		    dims[l_index] =
 			GDXRegion[regionID]->StopVertical[j] -
 			GDXRegion[regionID]->StartVertical[j] + 1;
 		}
@@ -8485,11 +8486,11 @@ GDextractregion(int32 gridID, int32 regionID, char *fieldname,
     int32           fid;	/* HDF-EOS file ID */
     int32           sdInterfaceID;	/* HDF SDS interface ID */
     int32           gdVgrpID;	/* Grid root Vgroup ID */
-    int32           index;	/* Dimension index */
+    int32           l_index;	/* Dimension l_index */
     int32           start[8];	/* Start array for data read */
     int32           edge[8];	/* Edge array for data read */
     int32           dims[8];	/* Dimensions */
-    int32           rank;	/* Field rank */
+    int32           rank = 0;	/* Field rank */
     int32           ntype;	/* Field number type */
     int32           origincode;	/* Pixel origin code */
 
@@ -8594,7 +8595,7 @@ GDextractregion(int32 gridID, int32 regionID, char *fieldname,
 	    {
 		status = -1;
 		HEpush(DFE_GENAPP, "GDextractregion", __FILE__, __LINE__);
-		sprintf(errbuf, "%s%s", errM1, errM2);
+		snprintf(errbuf, sizeof(errbuf), "%s%s", errM1, errM2);
 		HEreport(errbuf, fieldname);
 	    }
 	}
@@ -8624,43 +8625,43 @@ GDextractregion(int32 gridID, int32 regionID, char *fieldname,
 	/* --------------------------------- */
 	if (EHstrwithin("SOMBlockDim", dimlist, ',') == 0)
 	{
-	    index = EHstrwithin("SOMBlockDim", dimlist, ',');
-	    edge[index] = GDXRegion[regionID]->somCount;
-	    start[index] = GDXRegion[regionID]->somStart;
+	    l_index = EHstrwithin("SOMBlockDim", dimlist, ',');
+	    edge[l_index] = GDXRegion[regionID]->somCount;
+	    start[l_index] = GDXRegion[regionID]->somStart;
 	}
 
 
 	/* Set start & edge arrays for XDim */
 	/* -------------------------------- */
-	index = EHstrwithin("XDim", dimlist, ',');
+	l_index = EHstrwithin("XDim", dimlist, ',');
 	if (GDXRegion[regionID]->xCount != 0)
 	{
-	    edge[index] = GDXRegion[regionID]->xCount;
-	    start[index] = GDXRegion[regionID]->xStart;
+	    edge[l_index] = GDXRegion[regionID]->xCount;
+	    start[l_index] = GDXRegion[regionID]->xStart;
 	}
 
 	/* Adjust X-dim start if origin on right edge */
 	/* ------------------------------------------ */
 	if ((origincode & 1) == 1)
 	{
-	    start[index] = dims[index] - (start[index] + edge[index]);
+	    start[l_index] = dims[l_index] - (start[l_index] + edge[l_index]);
 	}
 
 
 	/* Set start & edge arrays for YDim */
 	/* -------------------------------- */
-	index = EHstrwithin("YDim", dimlist, ',');
+	l_index = EHstrwithin("YDim", dimlist, ',');
 	if (GDXRegion[regionID]->yCount != 0)
 	{
-	    start[index] = GDXRegion[regionID]->yStart;
-	    edge[index] = GDXRegion[regionID]->yCount;
+	    start[l_index] = GDXRegion[regionID]->yStart;
+	    edge[l_index] = GDXRegion[regionID]->yCount;
 	}
 
 	/* Adjust Y-dim start if origin on lower edge */
 	/* ------------------------------------------ */
 	if ((origincode & 2) == 2)
 	{
-	    start[index] = dims[index] - (start[index] + edge[index]);
+	    start[l_index] = dims[l_index] - (start[l_index] + edge[l_index]);
 	}
 
 
@@ -8676,17 +8677,17 @@ GDextractregion(int32 gridID, int32 regionID, char *fieldname,
 
 		/* Find vertical dimension within dimlist */
 		/* -------------------------------------- */
-		index = EHstrwithin(GDXRegion[regionID]->DimNamePtr[j],
+		l_index = EHstrwithin(GDXRegion[regionID]->DimNamePtr[j],
 				    dimlist, ',');
 
 		/* If dimension found ... */
 		/* ---------------------- */
-		if (index != -1)
+		if (l_index != -1)
 		{
 		    /* Compute start and edge for vertical dimension */
 		    /* --------------------------------------------- */
-		    start[index] = GDXRegion[regionID]->StartVertical[j];
-		    edge[index] = GDXRegion[regionID]->StopVertical[j] -
+		    start[l_index] = GDXRegion[regionID]->StartVertical[j];
+		    edge[l_index] = GDXRegion[regionID]->StopVertical[j] -
 			GDXRegion[regionID]->StartVertical[j] + 1;
 		}
 		else
@@ -8796,7 +8797,7 @@ GDdupregion(int32 oldregionID)
             {
                 if(GDXRegion[oldregionID]->DimNamePtr[j] != NULL)
                 {
-                    slendupregion = strlen(GDXRegion[oldregionID]->DimNamePtr[j]);
+                    slendupregion = (int)strlen(GDXRegion[oldregionID]->DimNamePtr[j]);
                     GDXRegion[i]->DimNamePtr[j] = (char *) malloc(slendupregion + 1);
                     strcpy(GDXRegion[i]->DimNamePtr[j],GDXRegion[oldregionID]->DimNamePtr[j]);
 		}
@@ -8895,7 +8896,7 @@ for (j=0; j<8; j++) \
 int32
 GDdefvrtregion(int32 gridID, int32 regionID, char *vertObj, float64 range[])
 {
-    intn            i, j, k, status;
+    intn            i, j = 0, k, status;
     uint8           found = 0;
 
     int16           vertINT16;
@@ -8934,7 +8935,7 @@ GDdefvrtregion(int32 gridID, int32 regionID, char *vertObj, float64 range[])
 
 	if (strcmp(dimlist, "DIM:") == 0)
 	{
-	    slen = strlen(vertObj) - 4;
+	    slen = (int)strlen(vertObj) - 4;
 	    if (regionID == -1)
 	    {
 		SETGRIDREG;
@@ -8979,7 +8980,7 @@ GDdefvrtregion(int32 gridID, int32 regionID, char *vertObj, float64 range[])
 		}
 		else
 		{
-		    slen = strlen(dimlist);
+		    slen = (int)strlen(dimlist);
 		    size = DFKNTsize(nt);
 		    vertArr = (char *) calloc(dims[0], size);
 		    if(vertArr == NULL)
@@ -9468,12 +9469,12 @@ GDgetpixvalues(int32 gridID, int32 nPixels, int32 pixRow[], int32 pixCol[],
     int32           edge[8];	/* GDreadfield edge array */
     int32           dims[8];	/* Field dimensions */
     int32           rank;	/* Field rank */
-    int32           xdum;	/* Location of "XDim" within field list */
-    int32           ydum;	/* Location of "YDim" within field list */
+    int32           xdum = 0;	/* Location of "XDim" within field list */
+    int32           ydum = 0;	/* Location of "YDim" within field list */
     int32           ntype;	/* Field number type */
     int32           origincode;	/* Origin code */
     int32           bufOffset;	/* Data buffer offset */
-    int32           size;	/* Size of returned data buffer for each
+    int32           size = 0;	/* Size of returned data buffer for each
 				 * value in bytes */
     int32           offset[8];	/* I/O offset (start) */
     int32           incr[8];	/* I/O increment (stride) */
@@ -9651,7 +9652,7 @@ GDgetpixvalues(int32 gridID, int32 nPixels, int32 pixRow[], int32 pixCol[],
 			/* Set I/O stride Section */
 			/* ---------------------- */
 			
-			/* In original code stride enetred as NULL. 
+			/* In original code stride entered as NULL.
 			   Abe Taaheri June 12, 1998 */
 			/*
 			 * If stride == NULL (default) set I/O stride to 1
@@ -9718,7 +9719,7 @@ GDgetpixvalues(int32 gridID, int32 nPixels, int32 pixRow[], int32 pixCol[],
 |   Date     Programmer   Description                                         |
 |  ======   ============  =================================================   |
 |  Aug 96   Joel Gales    Original Programmer                                 |
-|  Oct 96   Joel Gales    Fix array index problem with interpVal write        |
+|  Oct 96   Joel Gales    Fix array l_index problem with interpVal write        |
 |  Apr 97   Joel Gales    Trap interpolation boundary out of bounds error     |
 |  Jun 98   Abe Taaheri   changed the return value so that the Return Value   |
 |                         is size in bytes for the data buffer which is       |
@@ -9748,8 +9749,8 @@ GDinterpolate(int32 gridID, int32 nValues, float64 lonVal[], float64 latVal[],
     int32           dims[8];	/* Field dimensions */
     int32           numsize;	/* Size in bytes of number type */
     int32           rank;	/* Field rank */
-    int32           xdum;	/* Location of "XDim" within field list */
-    int32           ydum;	/* Location of "YDim" within field list */
+    int32           xdum = 0;	/* Location of "XDim" within field list */
+    int32           ydum = 0;	/* Location of "YDim" within field list */
     int32           ntype;	/* Number type */
     int32           dum;	/* Dummy variable */
     int32           size;	/* Size of returned data buffer for each
@@ -9758,13 +9759,13 @@ GDinterpolate(int32 gridID, int32 nValues, float64 lonVal[], float64 latVal[],
     int32           pixRow[4];	/* Pixel rows for 4 nearest neighbors */
     int32           tDen;	/* Interpolation denominator value 1 */
     int32           uDen;	/* Interpolation denominator value 2 */
-    int32           nRetn;	/* Number of data values returned */
+    int32           nRetn = 0;	/* Number of data values returned */
 
     float64         upleftpt[2];/* Upper left pt coordinates */
     float64         lowrightpt[2];	/* Lower right pt coordinates */
     float64         projparm[16];	/* Projection parameters */
-    float64         xVal;	/* "Exact" x location of interpolated point */
-    float64         yVal;	/* "Exact" y location of interpolated point */
+    float64         xVal = 0.0;	/* "Exact" x location of interpolated point */
+    float64         yVal = 0.0;	/* "Exact" y location of interpolated point */
     float64         tNum = 0.0;	/* Interpolation numerator value 1 */
     float64         uNum = 0.0;	/* Interpolation numerator value 2 */
 
@@ -10384,7 +10385,7 @@ Alexis Zubrow
 ********************************************************/
 
 intn
-GDsettilecache(int32 gridID, char *fieldname, int32 maxcache, int32 cachecode)
+GDsettilecache(int32 gridID, char *fieldname, int32 maxcache, CPL_UNUSED int32 cachecode)
 {
 
     intn            status = 0;	/* routine return status variable */
@@ -10511,6 +10512,8 @@ GDsettilecomp(int32 gridID, char *fieldname, int32 tilerank, int32*
     HDF_CHUNK_DEF   chunkDef;   /* Tiling structure */
     int32           chunkFlag;  /* Chunking (Tiling) flag */
  
+    c_info.nbit.nt = 0;
+ 
     /* Check for valid grid ID and get SDS interface ID */
     status = GDchkgdid(gridID, "GDsetfillvalue",
                        &fid, &sdInterfaceID, &gdVgrpID);
@@ -10641,7 +10644,7 @@ static intn GDll2mm_cea(int32 projcode,int32 zonecode, int32 spherecode,
 		 float64 projparm[],
 		 int32 xdimsize, int32 ydimsize,
 		 float64 upleftpt[], float64 lowrightpt[], int32 npnts,
-		 float64 lon[],float64 lat[],
+		 CPL_UNUSED float64 lon[],CPL_UNUSED float64 lat[],
 		 float64 x[],float64 y[], float64 *scaleX,float64 *scaleY)
 {
     intn            status = 0;	/* routine return status variable */
@@ -10769,8 +10772,8 @@ static intn GDll2mm_cea(int32 projcode,int32 zonecode, int32 spherecode,
 -----------------------------------------------------------------------------*/
 static intn GDmm2ll_cea(int32 projcode,int32 zonecode, int32 spherecode,
 		 float64 projparm[],
-		 int32 xdimsize, int32 ydimsize,
-		 float64 upleftpt[], float64 lowrightpt[], int32 npnts,
+		 CPL_UNUSED int32 xdimsize, CPL_UNUSED int32 ydimsize,
+		 CPL_UNUSED float64 upleftpt[], CPL_UNUSED float64 lowrightpt[], int32 npnts,
 		 float64 x[], float64 y[], 
 		 float64 longitude[], float64 latitude[])
 {
@@ -10866,4 +10869,3 @@ GDsdid(int32 gridID, const char *fieldname, int32 *sdid)
 
     return (status);
 }
-
diff --git a/frmts/hdf4/hdf-eos/SWapi.c b/frmts/hdf4/hdf-eos/SWapi.c
index 85c8ec9..6765694 100644
--- a/frmts/hdf4/hdf-eos/SWapi.c
+++ b/frmts/hdf4/hdf-eos/SWapi.c
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * $Id: SWapi.c 29336 2015-06-14 17:37:21Z rouault $
+ * $Id: SWapi.c 32805 2016-01-07 19:53:43Z rouault $
  *
  * This module has a number of additions and improvements over the original
  * implementation to be suitable for usage in GDAL HDF driver.
@@ -20,10 +20,10 @@ REVISIONS:
 
 Aug 31, 1999  Abe Taaheri    Changed memory allocation for utility strings to
                              the size of UTLSTR_MAX_SIZE.
-			     Added error check for memory unavailibilty in 
+			     Added error check for memory unavailability in
 			     several functions.
-			     Added check for NULL metabuf returned from 
-			     EHmeta... functions. NULL pointer retruned from 
+			     Added check for NULL metabuf returned from
+			     EHmeta... functions. NULL pointer returned from
 			     EHmeta... functions indicate that memory could not
 			     be allocated for metabuf.
 
@@ -38,13 +38,13 @@ June 05, 2003 Abe Taaheri / Bruce Beaumont
 			      in SWwrrdfield
 			    Removed declaration for unused variable tmpVal 
 			      in SWdefboxregion
-			    Added code in SWdefboxregion to check for index k
+			    Added code in SWdefboxregion to check for l_index k
 			      exceeding NSWATHREGN to avoid overwriting 
 			      memory
 			    Removed declaration for unused variable retchar 
-			      in SWregionindex
+			      in SWregionl_index
 			    Removed initialization code for unused variables 
-			      in SWregionindex
+			      in SWregionl_index
 			    Removed declarations for unused variables tstatus,
 			      nfields, nflgs, and swathname in SWextractregion
 			    Removed initialization code for unused variables 
@@ -74,6 +74,7 @@ June 05, 2003 Abe Taaheri / Bruce Beaumont
 			      in SWgeomapinfo
 ******************************************************************************/
 
+#include "cpl_port.h" /* for M_PI */
 #include "mfhdf.h"
 #include "hcomp.h"
 #include "HdfEosDef.h"
@@ -100,7 +101,6 @@ static intn  timeflag = 0;
 ** for floating scene subsetting
 ** Jul 1999 DaW
 */
-#define PI      3.141592653589793238
 #define RADOE	6371.0		/* Radius of Earth in Km */
 
 #define NSWATH 200
@@ -386,7 +386,7 @@ SWcreate(int32 fid, char *swathname)
 
 		/* Establish Swath in Structural MetaData Block */
 		/* -------------------------------------------- */
-		sprintf(utlbuf, "%s%ld%s%s%s",
+		snprintf(utlbuf, sizeof(utlbuf), "%s%ld%s%s%s",
 			"\tGROUP=SWATH_", (long)nSwath + 1,
 			"\n\t\tSwathName=\"", swathname, "\"\n");
 
@@ -402,7 +402,7 @@ SWcreate(int32 fid, char *swathname)
 		strcat(utlbuf, "\t\tEND_GROUP=DataField\n");
 		strcat(utlbuf, "\t\tGROUP=MergedFields\n");
 		strcat(utlbuf, "\t\tEND_GROUP=MergedFields\n");
-		sprintf(utlbuf2, "%s%ld%s",
+		snprintf(utlbuf2, sizeof(utlbuf2), "%s%ld%s",
 			"\tEND_GROUP=SWATH_", (long)nSwath + 1, "\n");
 		strcat(utlbuf, utlbuf2);
 
@@ -502,11 +502,11 @@ SWattach(int32 fid, char *swathname)
     int32           swathID = -1;	/* HDF-EOS swath ID */
     int32          *tags;	/* Pnt to Vgroup object tags array */
     int32          *refs;	/* Pnt to Vgroup object refs array */
-    int32           dum;	/* dummy varible */
+    int32           dum;	/* dummy variable */
     int32           sdInterfaceID;	/* HDF SDS interface ID */
     int32           nObjects;	/* # of objects in Vgroup */
     int32           nSDS;	/* SDS counter */
-    int32           index;	/* SDS index */
+    int32           l_index;	/* SDS l_index */
     int32           sdid;	/* SDS object ID */
     int32           idOffset = SWIDOFFSET;	/* Swath ID offset */
 
@@ -677,8 +677,8 @@ SWattach(int32 fid, char *swathname)
 			    /* ---------------------------- */
 			    if (tags[j] == DFTAG_NDG)
 			    {
-				index = SDreftoindex(sdInterfaceID, refs[j]);
-				sdid = SDselect(sdInterfaceID, index);
+				l_index = SDreftoindex(sdInterfaceID, refs[j]);
+				sdid = SDselect(sdInterfaceID, l_index);
 				SWXSwath[i].sdsID[nSDS] = sdid;
 				nSDS++;
 				SWXSwath[i].nSDS++;
@@ -742,8 +742,8 @@ SWattach(int32 fid, char *swathname)
 			    /* ---------------------------- */
 			    if (tags[j] == DFTAG_NDG)
 			    {
-				index = SDreftoindex(sdInterfaceID, refs[j]);
-				sdid = SDselect(sdInterfaceID, index);
+				l_index = SDreftoindex(sdInterfaceID, refs[j]);
+				sdid = SDselect(sdInterfaceID, l_index);
 				SWXSwath[i].sdsID[SWXSwath[i].nSDS] = sdid;
 				SWXSwath[i].nSDS++;
 			    }
@@ -883,7 +883,7 @@ SWchkswid(int32 swathID, char *routname,
 |  INPUTS:                                                                    |
 |  swathID        int32               swath structure ID                      |
 |  dimname        char                Dimension name to define                |
-|  dim            int32               Dimemsion value                         |
+|  dim            int32               Dimension value                         |
 |                                                                             |
 |  OUTPUTS:                                                                   |
 |             None                                                            |
@@ -1021,7 +1021,7 @@ SWdiminfo(int32 swathID, char *dimname)
 	}  
 
 	/* Search for dimension name (surrounded by quotes) */
-	sprintf(utlstr, "%s%s%s", "\"", dimname, "\"\n");
+	snprintf(utlstr, UTLSTR_MAX_SIZE, "%s%s%s", "\"", dimname, "\"\n");
 	metaptrs[0] = strstr(metaptrs[0], utlstr);
 
 	/*
@@ -1036,7 +1036,7 @@ SWdiminfo(int32 swathID, char *dimname)
 
 	    if (status == 0)
 	    {
-		size = atol(utlstr);
+		size = atoi(utlstr);
 	    }
 	    else
 	    {
@@ -1141,7 +1141,7 @@ SWmapinfo(int32 swathID, char *geodim, char *datadim, int32 * offset,
 	}
 
 	/* Search for mapping - GeoDim/DataDim (surrounded by quotes) */
-	sprintf(utlstr, "%s%s%s%s%s", "\t\t\t\tGeoDimension=\"", geodim,
+	snprintf(utlstr, UTLSTR_MAX_SIZE, "%s%s%s%s%s", "\t\t\t\tGeoDimension=\"", geodim,
 		"\"\n\t\t\t\tDataDimension=\"", datadim, "\"\n");
 	metaptrs[0] = strstr(metaptrs[0], utlstr);
 
@@ -1155,7 +1155,7 @@ SWmapinfo(int32 swathID, char *geodim, char *datadim, int32 * offset,
 	    statmeta = EHgetmetavalue(metaptrs, "Offset", utlstr);
 	    if (statmeta == 0)
 	    {
-		*offset = atol(utlstr);
+		*offset = atoi(utlstr);
 	    }
 	    else
 	    {
@@ -1169,7 +1169,7 @@ SWmapinfo(int32 swathID, char *geodim, char *datadim, int32 * offset,
 	    statmeta = EHgetmetavalue(metaptrs, "Increment", utlstr);
 	    if (statmeta == 0)
 	    {
-		*increment = atol(utlstr);
+		*increment = atoi(utlstr);
 	    }
 	    else
 	    {
@@ -1199,12 +1199,12 @@ SWmapinfo(int32 swathID, char *geodim, char *datadim, int32 * offset,
 |                                                                             |
 |  FUNCTION: SWidxmapinfo                                                     |
 |                                                                             |
-|  DESCRIPTION: Returns indexed mapping information                           |
+|  DESCRIPTION: Returns l_indexed mapping information                           |
 |                                                                             |
 |                                                                             |
 |  Return Value    Type     Units     Description                             |
 |  ============   ======  =========   =====================================   |
-|  gsize          int32               Number of index values (sz of geo dim)  |
+|  gsize          int32               Number of l_index values (sz of geo dim)  |
 |                                                                             |
 |  INPUTS:                                                                    |
 |  swathID        int32               swath structure id                      |
@@ -1213,7 +1213,7 @@ SWmapinfo(int32 swathID, char *geodim, char *datadim, int32 * offset,
 |                                                                             |
 |                                                                             |
 |  OUTPUTS:                                                                   |
-|  index          int32               array of index values                   |
+|  l_index          int32               array of l_index values                   |
 |                                                                             |
 |  NOTES:                                                                     |
 |                                                                             |
@@ -1225,7 +1225,7 @@ SWmapinfo(int32 swathID, char *geodim, char *datadim, int32 * offset,
 |  END_PROLOG                                                                 |
 -----------------------------------------------------------------------------*/
 int32
-SWidxmapinfo(int32 swathID, char *geodim, char *datadim, int32 index[])
+SWidxmapinfo(int32 swathID, char *geodim, char *datadim, int32 l_index[])
 {
     intn            status;	/* routine return status variable */
 
@@ -1247,17 +1247,17 @@ SWidxmapinfo(int32 swathID, char *geodim, char *datadim, int32 index[])
     if (status == 0)
     {
 	/* Find Index Mapping Vdata with Swath Attributes Vgroup */
-	sprintf(utlbuf, "%s%s%s%s", "INDXMAP:", geodim, "/", datadim);
+	snprintf(utlbuf, sizeof(utlbuf), "%s%s%s%s", "INDXMAP:", geodim, "/", datadim);
 	vgid = SWXSwath[swathID % idOffset].VIDTable[2];
 	vdataID = EHgetid(fid, vgid, utlbuf, 1, "r");
 
-	/* If found then get geodim size & read index mapping values */
+	/* If found then get geodim size & read l_index mapping values */
 	if (vdataID != -1)
 	{
 	    gsize = SWdiminfo(swathID, geodim);
 
 	    VSsetfields(vdataID, "Index");
-	    VSread(vdataID, (uint8 *) index, 1, FULL_INTERLACE);
+	    VSread(vdataID, (uint8 *) l_index, 1, FULL_INTERLACE);
 	    VSdetach(vdataID);
 	}
 	else
@@ -1352,7 +1352,7 @@ SWcompinfo(int32 swathID, char *fieldname, int32 * compcode, intn compparm[])
 	    return(-1);
 	}
 	/* Search for field */
-	sprintf(utlstr, "%s%s%s", "\"", fieldname, "\"\n");
+	snprintf(utlstr, UTLSTR_MAX_SIZE, "%s%s%s", "\"", fieldname, "\"\n");
 	metaptrs[0] = strstr(metaptrs[0], utlstr);
 
 	/* If not found then search in "GeoField" section */
@@ -1369,7 +1369,7 @@ SWcompinfo(int32 swathID, char *fieldname, int32 * compcode, intn compparm[])
 		return(-1);
 	    }
 	    /* Search for field */
-	    sprintf(utlstr, "%s%s%s", "\"", fieldname, "\"\n");
+	    snprintf(utlstr, UTLSTR_MAX_SIZE, "%s%s%s", "\"", fieldname, "\"\n");
 	    metaptrs[0] = strstr(metaptrs[0], utlstr);
 	}
 
@@ -1412,7 +1412,7 @@ SWcompinfo(int32 swathID, char *fieldname, int32 * compcode, intn compparm[])
 		/* Initialize to zero */
 		for (i = 0; i < 4; i++)
 		{
-		    compparm[i] = 0.0;
+		    compparm[i] = 0;
 		}
 
 		/*
@@ -1578,7 +1578,7 @@ SWfinfo(int32 swathID, const char *fieldtype, const char *fieldname,
 
 
     /* Search for field */
-    sprintf(utlstr, "%s%s%s", "\"", fieldname, "\"\n");
+    snprintf(utlstr, UTLSTR_MAX_SIZE, "%s%s%s", "\"", fieldname, "\"\n");
     metaptrs[0] = strstr(metaptrs[0], utlstr);
 
     /* If field found ... */
@@ -1627,7 +1627,7 @@ SWfinfo(int32 swathID, const char *fieldtype, const char *fieldname,
 
 	/*
 	 * Copy each entry in DimList and remove leading and trailing quotes,
-	 * Get dimension sizes and concatanate dimension names to dimension
+	 * Get dimension sizes and concatenate dimension names to dimension
 	 * list
 	 */
 	for (i = 0; i < ndims; i++)
@@ -1729,7 +1729,7 @@ SWfinfo(int32 swathID, const char *fieldtype, const char *fieldname,
 |                                                                             |
 |  FUNCTION: SWfieldinfo                                                      |
 |                                                                             |
-|  DESCRIPTION: Wrapper arount SWfinfo                                        |
+|  DESCRIPTION: Wrapper around SWfinfo                                        |
 |                                                                             |
 |                                                                             |
 |  Return Value    Type     Units     Description                             |
@@ -1881,7 +1881,7 @@ SWdefdimmap(int32 swathID, char *geodim, char *datadim, int32 offset,
 	/* ------------------------------------------ */
 	if (status == 0)
 	{
-	    sprintf(mapname, "%s%s%s", geodim, "/", datadim);
+	    snprintf(mapname, sizeof(mapname), "%s%s%s", geodim, "/", datadim);
 	    metadata[0] = offset;
 	    metadata[1] = increment;
 
@@ -1901,7 +1901,7 @@ SWdefdimmap(int32 swathID, char *geodim, char *datadim, int32 offset,
 |                                                                             |
 |  FUNCTION: SWdefidxmap                                                      |
 |                                                                             |
-|  DESCRIPTION: Defines indexed (non-linear) mapping between geolocation      |
+|  DESCRIPTION: Defines l_indexed (non-linear) mapping between geolocation      |
 |               and data dimensions                                           |
 |                                                                             |
 |                                                                             |
@@ -1913,7 +1913,7 @@ SWdefdimmap(int32 swathID, char *geodim, char *datadim, int32 offset,
 |  swathID        int32               swath structure ID                      |
 |  geodim         char                Geolocation dimension                   |
 |  datadim        char                Data dimension                          |
-|  index          int32               Index mapping array                     |
+|  l_index          int32               Index mapping array                     |
 |                                                                             |
 |  OUTPUTS:                                                                   |
 |             None                                                            |
@@ -1928,7 +1928,7 @@ SWdefdimmap(int32 swathID, char *geodim, char *datadim, int32 offset,
 |  END_PROLOG                                                                 |
 -----------------------------------------------------------------------------*/
 intn
-SWdefidxmap(int32 swathID, char *geodim, char *datadim, int32 index[])
+SWdefidxmap(int32 swathID, char *geodim, char *datadim, int32 l_index[])
 
 {
     intn            status;	/* routine return status variable */
@@ -1996,7 +1996,7 @@ SWdefidxmap(int32 swathID, char *geodim, char *datadim, int32 index[])
 	    }
 
 	    /* Name: "INDXMAP:" + geodim + "/" + datadim */
-	    sprintf(utlbuf, "%s%s%s%s", "INDXMAP:", geodim, "/", datadim);
+	    snprintf(utlbuf, sizeof(utlbuf), "%s%s%s%s", "INDXMAP:", geodim, "/", datadim);
 
 	    vdataID = VSattach(fid, -1, "w");
 	    VSsetname(vdataID, utlbuf);
@@ -2007,7 +2007,7 @@ SWdefidxmap(int32 swathID, char *geodim, char *datadim, int32 index[])
 	    /* Fieldname is "Index" */
 	    VSfdefine(vdataID, "Index", DFNT_INT32, gsize);
 	    VSsetfields(vdataID, "Index");
-	    memcpy(buf, index, 4 * gsize);
+	    memcpy(buf, l_index, 4 * gsize);
 
 	    /* Write to vdata and free data buffer */
 	    VSwrite(vdataID, buf, 1, FULL_INTERLACE);
@@ -2019,7 +2019,7 @@ SWdefidxmap(int32 swathID, char *geodim, char *datadim, int32 index[])
 
 
 	    /* Write to Structural Metadata */
-	    sprintf(mapname, "%s%s%s", geodim, "/", datadim);
+	    snprintf(mapname, sizeof(mapname), "%s%s%s", geodim, "/", datadim);
 	    Vgetname(SWXSwath[swathID % idOffset].IDTable, swathname);
 	    status = EHinsertmeta(sdInterfaceID, swathname, "s", 2L,
 				  mapname, &dum);
@@ -2079,7 +2079,7 @@ SWdefcomp(int32 swathID, int32 compcode, intn compparm[])
     {
 	sID = swathID % idOffset;
 
-	/* Set compression code in compression exteral array */
+	/* Set compression code in compression external array */
 	SWXSwath[sID].compcode = compcode;
 
 	switch (compcode)
@@ -2159,7 +2159,7 @@ SWdefinefield(int32 swathID, char *fieldtype, char *fieldname, char *dimlist,
     int32           cnt = 0;
 
     int32           fid;	/* HDF-EOS file ID */
-    int32           vdataID;	/* Vdata ID */
+    int32           vdataID = 0;	/* Vdata ID */
     int32           vgid;	/* Geo/Data field Vgroup ID */
     int32           sdInterfaceID;	/* HDF SDS interface ID */
     int32           sdid;	/* SDS object ID */
@@ -2184,7 +2184,7 @@ SWdefinefield(int32 swathID, char *fieldtype, char *fieldname, char *dimlist,
     char            swathname[80];	/* Swath name */
     char            errbuf1[128];	/* Error message buffer 1 */
     char            errbuf2[128];	/* Error message buffer 2 */
-    char            compparmbuf[128];	/* Compression parmeter string buffer */
+    char            compparmbuf[128];	/* Compression parameter string buffer */
 
     char           *HDFcomp[5] = {"HDFE_COMP_NONE", "HDFE_COMP_RLE",
 	"HDFE_COMP_NBIT", "HDFE_COMP_SKPHUFF",
@@ -2288,7 +2288,7 @@ SWdefinefield(int32 swathID, char *fieldtype, char *fieldname, char *dimlist,
             comma = strchr(comma, ',');
             if (comma != NULL)
             {
-               for (i=0; i<strlen(dimcheck) + 1; i++)
+               for (i=0; i<(intn)strlen(dimcheck) + 1; i++)
                {
                   dimbuf++;
                   cnt++;
@@ -2317,14 +2317,13 @@ SWdefinefield(int32 swathID, char *fieldtype, char *fieldname, char *dimlist,
 	    }
 	}
 
-
 	/* Check fieldname length */
 	/* ---------------------- */
 	if (status == 0)
 	{
 /* ((intn) strlen(fieldname) > MAX_NC_NAME - 7)
 ** this was changed because HDF4.1r3 made a change in the
-** hlimits.h file.  We have notidfied NCSA and asked to have 
+** hlimits.h file.  We have notified NCSA and asked to have 
 ** it made the same as in previous versions of HDF
 ** see ncr 26314.  DaW  Apr 2000
 */
@@ -2338,9 +2337,6 @@ SWdefinefield(int32 swathID, char *fieldtype, char *fieldname, char *dimlist,
 	    }
 	}
 
-
-
-
 	/* Check for valid numbertype */
 	/* -------------------------- */
 	if (status == 0)
@@ -2380,7 +2376,7 @@ SWdefinefield(int32 swathID, char *fieldtype, char *fieldname, char *dimlist,
 		vgid = SWXSwath[sID].VIDTable[1];
 	    }
 	    /*
-	     * Note: "fac" is used to destinguish geo fields from data fields
+	     * Note: "fac" is used to distinguish geo fields from data fields
 	     * so that they are not merged together
 	     */
 
@@ -2443,8 +2439,8 @@ SWdefinefield(int32 swathID, char *fieldtype, char *fieldname, char *dimlist,
 		    else
 		    {
 			/*
-			 * If match then concatanate current fieldname to
-			 * previous matching fieldnames
+			 * If match then concatenate current fieldname to
+			 * previous matching fieldnames.
 			 */
 			strcat(utlbuf, ",");
 			strcat(utlbuf, fieldname);
@@ -2555,7 +2551,7 @@ SWdefinefield(int32 swathID, char *fieldtype, char *fieldname, char *dimlist,
 		    SWXSDcomb[5 * i + 4] = numbertype;
 
 
-		    /* Concatanate fieldname with combined name string */
+		    /* Concatenate fieldname with combined name string */
 		    /* ----------------------------------------------- */
 		    if ((intn) strlen(SWXSDname) +
 			(intn) strlen(fieldname) + 2 < HDFE_NAMBUFSIZE)
@@ -2600,8 +2596,8 @@ SWdefinefield(int32 swathID, char *fieldtype, char *fieldname, char *dimlist,
 		    }
 
 		    /*
-		     * Concatanate field dimlist to merged dimlist and
-		     * separate fields with semi-colon
+		     * Concatenate field dimlist to merged dimlist and
+		     * separate fields with semi-colon.
 		     */
 		    if ((intn) strlen(SWXSDdims) +
 			(intn) strlen(dimlist) + 2 < HDFE_DIMBUFSIZE)
@@ -2670,7 +2666,7 @@ SWdefinefield(int32 swathID, char *fieldtype, char *fieldname, char *dimlist,
 		    /* ---------------------------------------------- */
 		    if (compcode != HDFE_COMP_NONE)
 		    {
-			status = SDsetcompress(sdid, (comp_coder_t) compcode, &c_info);
+                        /* status = */ SDsetcompress(sdid, (comp_coder_t) compcode, &c_info);
 		    }
 
 
@@ -2713,14 +2709,14 @@ SWdefinefield(int32 swathID, char *fieldtype, char *fieldname, char *dimlist,
 
 	    /* Setup metadata string */
 	    /* --------------------- */
-	    sprintf(utlbuf, "%s%s%s", fieldname, ":", dimlist);
+	    snprintf(utlbuf, sizeof(utlbuf), "%s%s%s", fieldname, ":", dimlist);
 
 
 	    /* Setup compression metadata */
 	    /* -------------------------- */
 	    if (compcode != HDFE_COMP_NONE)
 	    {
-		sprintf(utlbuf2,
+		snprintf(utlbuf2, sizeof(utlbuf2),
 			"%s%s",
 			":\n\t\t\t\tCompressionType=", HDFcomp[compcode]);
 
@@ -2728,7 +2724,7 @@ SWdefinefield(int32 swathID, char *fieldtype, char *fieldname, char *dimlist,
 		{
 		case HDFE_COMP_NBIT:
 
-		    sprintf(compparmbuf,
+		    snprintf(compparmbuf, sizeof(compparmbuf),
 			    "%s%d,%d,%d,%d%s",
 			    "\n\t\t\t\tCompressionParams=(",
 			    SWXSwath[sID].compparm[0],
@@ -2741,7 +2737,7 @@ SWdefinefield(int32 swathID, char *fieldtype, char *fieldname, char *dimlist,
 
 		case HDFE_COMP_DEFLATE:
 
-		    sprintf(compparmbuf,
+		    snprintf(compparmbuf, sizeof(compparmbuf),
 			    "%s%d",
 			    "\n\t\t\t\tDeflateLevel=",
 			    SWXSwath[sID].compparm[0]);
@@ -2749,7 +2745,7 @@ SWdefinefield(int32 swathID, char *fieldtype, char *fieldname, char *dimlist,
 		    break;
 		}
 
-		/* Concatanate compression parameters with compression code */
+		/* Concatenate compression parameters with compression code */
 		strcat(utlbuf, utlbuf2);
 	    }
 
@@ -2935,7 +2931,7 @@ SWwritegeometa(int32 swathID, char *fieldname, char *dimlist,
     {
 	/* Setup and write field metadata */
 	/* ------------------------------ */
-	sprintf(utlbuf, "%s%s%s", fieldname, ":", dimlist);
+	snprintf(utlbuf, sizeof(utlbuf), "%s%s%s", fieldname, ":", dimlist);
 
 	Vgetname(SWXSwath[swathID % idOffset].IDTable, swathname);
 	status = EHinsertmeta(sdInterfaceID, swathname, "s", 3L,
@@ -3000,7 +2996,7 @@ SWwritedatameta(int32 swathID, char *fieldname, char *dimlist,
     {
 	/* Setup and write field metadata */
 	/* ------------------------------ */
-	sprintf(utlbuf, "%s%s%s", fieldname, ":", dimlist);
+	snprintf(utlbuf, sizeof(utlbuf), "%s%s%s", fieldname, ":", dimlist);
 
 	Vgetname(SWXSwath[swathID % idOffset].IDTable, swathname);
 	status = EHinsertmeta(sdInterfaceID, swathname, "s", 4L,
@@ -3412,7 +3408,7 @@ SWinqdims(int32 swathID, char *dimnames, int32 dims[])
 			/* ----------------------- */
 			REMQUOTE
 
-			/* If not first name then add comma delimitor */
+			/* If not first name then add comma delimiter */
 			    if (nDim > 0)
 			{
 			    strcat(dimnames, ",");
@@ -3425,7 +3421,7 @@ SWinqdims(int32 swathID, char *dimnames, int32 dims[])
 		    if (dims != NULL)
 		    {
 			EHgetmetavalue(metaptrs, "Size", utlstr);
-			size = atol(utlstr);
+			size = atoi(utlstr);
 			dims[nDim] = size;
 		    }
 		    /* Increment number of dimensions */
@@ -3561,7 +3557,7 @@ SWinqmaps(int32 swathID, char *dimmaps, int32 offset[], int32 increment[])
 			REMQUOTE
 			    strcat(utlstr, "/");
 
-			/* if not first map then add comma delimitor */
+			/* If not first map then add comma delimiter. */
 			if (nMap > 0)
 			{
 			    strcat(dimmaps, ",");
@@ -3582,7 +3578,7 @@ SWinqmaps(int32 swathID, char *dimmaps, int32 offset[], int32 increment[])
 		    if (offset != NULL)
 		    {
 			EHgetmetavalue(metaptrs, "Offset", utlstr);
-			off = atol(utlstr);
+			off = atoi(utlstr);
 			offset[nMap] = off;
 		    }
 
@@ -3590,7 +3586,7 @@ SWinqmaps(int32 swathID, char *dimmaps, int32 offset[], int32 increment[])
 		    if (increment != NULL)
 		    {
 			EHgetmetavalue(metaptrs, "Increment", utlstr);
-			incr = atol(utlstr);
+			incr = atoi(utlstr);
 			increment[nMap] = incr;
 		    }
 
@@ -3628,18 +3624,18 @@ SWinqmaps(int32 swathID, char *dimmaps, int32 offset[], int32 increment[])
 |                                                                             |
 |  FUNCTION: SWinqidxmaps                                                     |
 |                                                                             |
-|  DESCRIPTION: Returns indexed mappings and index sizes                      |
+|  DESCRIPTION: Returns l_indexed mappings and l_index sizes                      |
 |                                                                             |
 |                                                                             |
 |  Return Value    Type     Units     Description                             |
 |  ============   ======  =========   =====================================   |
-|  nMap           int32               Number of indexed dimension mappings    |
+|  nMap           int32               Number of l_indexed dimension mappings    |
 |                                                                             |
 |  INPUTS:                                                                    |
 |  swathID        int32               swath structure ID                      |
 |                                                                             |
 |  OUTPUTS:                                                                   |
-|  idxmaps        char                indexed dimension mappings              |
+|  idxmaps        char                l_indexed dimension mappings              |
 |                                     (comma-separated)                       |
 |  idxsizes       int32               Number of elements in each mapping      |
 |                                                                             |
@@ -3688,7 +3684,7 @@ SWinqidxmaps(int32 swathID, char *idxmaps, int32 idxsizes[])
 
     if (status == 0)
     {
-	/* If mapping names or index sizes desired ... */
+	/* If mapping names or l_index sizes desired ... */
 	/* ------------------------------------------- */
 	if (idxmaps != NULL || idxsizes != NULL)
 	{
@@ -3727,7 +3723,7 @@ SWinqidxmaps(int32 swathID, char *idxmaps, int32 idxsizes[])
 			REMQUOTE
 			    strcat(utlstr, "/");
 
-			/* if not first map then add comma delimitor */
+			/* If not first map then add comma delimiter. */
 			if (nMap > 0)
 			{
 			    strcat(idxmaps, ",");
@@ -4139,7 +4135,7 @@ SWnentries(int32 swathID, int32 entrycode, int32 * strbufsize)
     int32           idOffset = SWIDOFFSET;	/* Swath ID offset */
     int32           nEntries = 0;   /* Number of entries */
     int32           metaflag;	    /* Old (0), New (1) metadata flag) */
-    int32           nVal;	    /* Number of strings to search for */
+    int32           nVal = 0;	    /* Number of strings to search for */
 
     char           *metabuf = NULL; /* Pointer to structural metadata (SM) */
     char           *metaptrs[2];    /* Pointers to begin and end of SM section */
@@ -4285,7 +4281,7 @@ SWnentries(int32 swathID, int32 entrycode, int32 * strbufsize)
                          * Get all string values Don't count quotes
                          */
                         EHgetmetavalue(metaptrs, &valName[i][0], utlstr);
-                        *strbufsize += strlen(utlstr) - 2;
+                        *strbufsize += (int32)strlen(utlstr) - 2;
                     }
                     /* Increment number of entries */
                     nEntries++;
@@ -4504,7 +4500,7 @@ SWSDfldsrch(int32 swathID, int32 sdInterfaceID, const char *fieldname,
     int32           idOffset = SWIDOFFSET;	/* Swath ID offset */
     int32           dum;	/* Dummy variable */
     int32           dums[128];	/* Dummy array */
-    int32           attrIndex;	/* Attribute index */
+    int32           attrIndex;	/* Attribute l_index */
 
     char            name[2048];	/* Merged-Field Names */
     char            swathname[80];	/* Swath Name */
@@ -4572,7 +4568,7 @@ SWSDfldsrch(int32 swathID, int32 sdInterfaceID, const char *fieldname,
 
 		/* Search for Merged field name */
 		/* ---------------------------- */
-		sprintf(utlstr, "%s%s%s", "MergedFieldName=\"",
+		snprintf(utlstr, UTLSTR_MAX_SIZE, "%s%s%s", "MergedFieldName=\"",
 			name, "\"\n");
 		metaptrs[0] = strstr(metaptrs[0], utlstr);
 
@@ -4581,7 +4577,7 @@ SWSDfldsrch(int32 swathID, int32 sdInterfaceID, const char *fieldname,
 		/* ----------------------------------- */
 		if (metaptrs[0] == NULL)
 		{
-		    sprintf(utlstr, "%s%s%s", "OBJECT=\"", name, "\"\n");
+		    snprintf(utlstr, UTLSTR_MAX_SIZE, "%s%s%s", "OBJECT=\"", name, "\"\n");
 		    metaptrs[0] = strstr(oldmetaptr, utlstr);
 		}
 
@@ -4592,7 +4588,7 @@ SWSDfldsrch(int32 swathID, int32 sdInterfaceID, const char *fieldname,
 		name[strlen(name) - 2] = 0;
 
 		/* Search for desired field within merged field list */
-		sprintf(utlstr, "%s%s%s", "\"", fieldname, "\"");
+		snprintf(utlstr, UTLSTR_MAX_SIZE, "%s%s%s", "\"", fieldname, "\"");
 		dum = EHstrwithin(utlstr, name, ',');
 
 		free(metabuf);
@@ -4620,7 +4616,7 @@ SWSDfldsrch(int32 swathID, int32 sdInterfaceID, const char *fieldname,
 		/* ------------------- */
 		if (*solo == 0)
 		{
-		    /* Get "Field Offsets" SDS attribute index */
+		    /* Get "Field Offsets" SDS attribute l_index */
 		    /* --------------------------------------- */
 		    attrIndex = SDfindattr(*sdid, "Field Offsets");
 
@@ -4635,7 +4631,7 @@ SWSDfldsrch(int32 swathID, int32 sdInterfaceID, const char *fieldname,
 		    }
 
 
-		    /* Get "Field Dims" SDS attribute index */
+		    /* Get "Field Dims" SDS attribute l_index */
 		    /* ------------------------------------ */
 		    attrIndex = SDfindattr(*sdid, "Field Dims");
 
@@ -4737,7 +4733,7 @@ SWwrrdfield(int32 swathID, const char *fieldname, const char *code,
     int32           nrec;	/* Number of records in Vdata */
 
     int32           offset[8];	/* I/O offset (start) */
-    int32           incr[8];	/* I/O incrment (stride) */
+    int32           incr[8];	/* I/O increment (stride) */
     int32           count[8];	/* I/O count (edge) */
     int32           dims[8];	/* Field/SDS dimensions */
     int32           mrgOffset;	/* Merged field offset */
@@ -5019,8 +5015,8 @@ SWwrrdfield(int32 swathID, const char *fieldname, const char *code,
 			}
 
 			/* Read records to recover previously written data */
-			status = VSsetfields(vdataID, fieldlist);
-			status = VSseek(vdataID, offset[0]);
+			/* status = */ VSsetfields(vdataID, fieldlist);
+			/* status = */ VSseek(vdataID, offset[0]);
 			nrec = VSread(vdataID, buf, count[0] * incr[0],
 				      FULL_INTERLACE);
 		    }
@@ -5033,7 +5029,7 @@ SWwrrdfield(int32 swathID, const char *fieldname, const char *code,
 
 		    /* Fill buffer with "Fill" value (if any) */
 		    /* -------------------------------------- */
-		    strcpy(attrName, "_FV_");
+		    strncpy(attrName, "_FV_", 80);
 		    strcat(attrName, fieldname);
 
 		    status = SWreadattr(swathID, attrName, (char *) fillbuf);
@@ -5286,7 +5282,7 @@ SWdefboxregion(int32 swathID, float64 cornerlon[], float64 cornerlat[],
 	       int32 mode)
 {
     intn            i;		/* Loop index */
-    intn            j;		/* Loop index */
+    intn            j = 0;		/* Loop index */
     intn            k;		/* Loop index */
     
     intn            status;	/* routine return status variable */
@@ -5863,10 +5859,10 @@ SWdefboxregion(int32 swathID, float64 cornerlon[], float64 cornerlat[],
 /*----------------------------------------------------------------------------|
 |  BEGIN_PROLOG                                                               |
 |                                                                             |
-|  FUNCTION: SWregionindex                                                    |
+|  FUNCTION: SWregionl_index                                                    |
 |                                                                             |
 |  DESCRIPTION: Finds swath cross tracks within area of interest and returns  |
-|               region index and region ID                                    |
+|               region l_index and region ID                                    |
 |                                                                             |
 |                                                                             |
 |  Return Value    Type     Units     Description                             |
@@ -5953,7 +5949,7 @@ SWregionindex(int32 swathID, float64 cornerlon[], float64 cornerlat[],
 
     /* Check for valid swath ID */
     /* ------------------------ */
-    status = SWchkswid(swathID, "SWregionindex", &fid, &sdInterfaceID,
+    status = SWchkswid(swathID, "SWregionl_index", &fid, &sdInterfaceID,
 		       &swVgrpID);
 
 
@@ -5962,7 +5958,7 @@ SWregionindex(int32 swathID, float64 cornerlon[], float64 cornerlat[],
     if (mode < 0 || mode > 2)
     {
 	status = -1;
-	HEpush(DFE_GENAPP, "SWregionindex", __FILE__, __LINE__);
+	HEpush(DFE_GENAPP, "SWregionl_index", __FILE__, __LINE__);
 	HEreport("Improper Inclusion Mode: %d.\n", mode);
     }
 
@@ -5975,7 +5971,7 @@ SWregionindex(int32 swathID, float64 cornerlon[], float64 cornerlat[],
 	if (statLon != 0)
 	{
 	    status = -1;
-	    HEpush(DFE_GENAPP, "SWregionindex", __FILE__, __LINE__);
+	    HEpush(DFE_GENAPP, "SWregionl_index", __FILE__, __LINE__);
 	    HEreport("\"Longitude\" field not found.\n");
 	}
 
@@ -5999,7 +5995,7 @@ SWregionindex(int32 swathID, float64 cornerlon[], float64 cornerlat[],
 		  /* Neither "Latitude" nor "Colatitude" field found */
 		  /* ----------------------------------------------- */
 		  status = -1;
-		  HEpush(DFE_GENAPP, "SWregionindex", __FILE__, __LINE__);
+		  HEpush(DFE_GENAPP, "SWregionl_index", __FILE__, __LINE__);
 		  HEreport(
 			   "Neither \"Latitude\" nor \"Colatitude\" fields found.\n");
 		}
@@ -6089,14 +6085,14 @@ SWregionindex(int32 swathID, float64 cornerlon[], float64 cornerlat[],
 	    lonArr = (char *) calloc(nElem, sizeof(float64));
 	    if(lonArr == NULL)
 	    { 
-		HEpush(DFE_NOSPACE,"SWregionindex", __FILE__, __LINE__);
+		HEpush(DFE_NOSPACE,"SWregionl_index", __FILE__, __LINE__);
 		return(-1);
 	    }
 	    
 	    latArr = (char *) calloc(nElem, sizeof(float64));
 	    if(latArr == NULL)
 	    { 
-		HEpush(DFE_NOSPACE,"SWregionindex", __FILE__, __LINE__);
+		HEpush(DFE_NOSPACE,"SWregionl_index", __FILE__, __LINE__);
 		free(lonArr);
 		return(-1);
 	    }
@@ -6107,7 +6103,7 @@ SWregionindex(int32 swathID, float64 cornerlon[], float64 cornerlat[],
 	    flag = (uint8 *) calloc(edge[0] + 1, 1);
 	    if(flag == NULL)
 	    { 
-		HEpush(DFE_NOSPACE,"SWregionindex", __FILE__, __LINE__);
+		HEpush(DFE_NOSPACE,"SWregionl_index", __FILE__, __LINE__);
 		free(lonArr);
 		free(latArr);
 		return(-1);
@@ -6235,13 +6231,13 @@ SWregionindex(int32 swathID, float64 cornerlon[], float64 cornerlat[],
 		lonArr = (char *) calloc(dims[1], sizeof(float64));
 		if(lonArr == NULL)
 		{ 
-		    HEpush(DFE_NOSPACE,"SWregionindex", __FILE__, __LINE__);
+		    HEpush(DFE_NOSPACE,"SWregionl_index", __FILE__, __LINE__);
 		    return(-1);
 		}
 		latArr = (char *) calloc(dims[1], sizeof(float64));
 		if(latArr == NULL)
 		{ 
-		    HEpush(DFE_NOSPACE,"SWregionindex", __FILE__, __LINE__);
+		    HEpush(DFE_NOSPACE,"SWregionl_index", __FILE__, __LINE__);
 		    free(lonArr);
 		    return(-1);
 		}
@@ -6382,7 +6378,7 @@ SWregionindex(int32 swathID, float64 cornerlon[], float64 cornerlat[],
 			    calloc(1, sizeof(struct swathRegion));
 			if(SWXRegion[k] == NULL)
 			{ 
-			    HEpush(DFE_NOSPACE,"SWregionindex", __FILE__, __LINE__);
+			    HEpush(DFE_NOSPACE,"SWregionl_index", __FILE__, __LINE__);
 			    return(-1);
 			}
 
@@ -6411,7 +6407,7 @@ SWregionindex(int32 swathID, float64 cornerlon[], float64 cornerlat[],
 		}
 		if (k >= NSWATHREGN)
 		  {
-		    HEpush(DFE_GENAPP, "SWregionindex", __FILE__, __LINE__);
+		    HEpush(DFE_GENAPP, "SWregionl_index", __FILE__, __LINE__);
 		    HEreport(
 			     "regionID exceeded NSWATHREGN.\n");
                     return (-1);
@@ -6825,7 +6821,7 @@ SWdeftimeperiod(int32 swathID, float64 starttime, float64 stoptime,
 |  Oct 96   Joel Gales    Mapping offset value not read from SWmapinfo        |
 |  Dec 96   Joel Gales    Vert Subset overwriting data buffer                 |
 |  Dec 96   Joel Gales    Add multiple vertical subsetting capability         |
-|  Mar 97   Joel Gales    Add support for index mapping                       |
+|  Mar 97   Joel Gales    Add support for l_index mapping                       |
 |  Jul 99   DaW 	  Add support for floating scene subsetting 	      |
 |  Feb 03   Terry Haran/                                                      |
 |           Abe Taaheri   Forced map offset to 0 so that data is extracted    |
@@ -6863,12 +6859,12 @@ SWextractregion(int32 swathID, int32 regionID, char *fieldname,
 
     int32	    numtype = 0; /* Used for L7 float scene sub. */
     int32	    count = 0;   /* Used for L7 float scene sub. */
-    int32           index;	/* Geo Dim Index */
+    int32           l_index = 0;	/* Geo Dim Index */
     int32           nDim;	/* Number of dimensions */
     int32           slen[64];	/* String length array */
     int32           dum;	/* Dummy variable */
-    int32           offset;	/* Mapping offset */
-    int32           incr;	/* Mapping increment */
+    int32           offset = 0;	/* Mapping offset */
+    int32           incr = 0;	/* Mapping increment */
     int32           nXtrk;	/* Number of cross tracks */
     int32           scan_shift = 0; /* Used to take out partial scans */
     int32           dumdims[8];	/* Dimensions from SWfieldinfo */
@@ -6878,10 +6874,10 @@ SWextractregion(int32 swathID, int32 regionID, char *fieldname,
     int32           rank = 0;	/* Field rank */
     int32           rk = 0;	/* Field rank */
     int32           ntype = 0;	/* Field number type */
-    int32           bufOffset;	/* Output buffer offset */
+    int32           bufOffset = 0;	/* Output buffer offset */
     int32           size;	/* Size of data buffer */
-    int32           idxMapElem = -1;	/* Number of index map elements  */
-    int32          *idxmap = NULL;	/* Pointer to index mapping array */
+    int32           idxMapElem = -1;	/* Number of l_index map elements  */
+    int32          *idxmap = NULL;	/* Pointer to l_index mapping array */
 
     int32	startscanline = 0;
     int32	stopscanline = 0;
@@ -7151,7 +7147,7 @@ SWextractregion(int32 swathID, int32 regionID, char *fieldname,
 		    if (statMap == 0)
 		    {
 			found = 1;
-			index = i;
+			l_index = i;
 			break;
 		    }
 		}
@@ -7161,11 +7157,11 @@ SWextractregion(int32 swathID, int32 regionID, char *fieldname,
 		/* ---------------------------------------------------- */
 		if (found == 0)
 		{
-		    index = EHstrwithin(geodim, dimlist, ',');
+		    l_index = EHstrwithin(geodim, dimlist, ',');
 
 		    /* Geo dimension found within subset field dimlist */
 		    /* ----------------------------------------------- */
-		    if (index != -1)
+		    if (l_index != -1)
 		    {
 			found = 1;
 			offset = 0;
@@ -7175,15 +7171,15 @@ SWextractregion(int32 swathID, int32 regionID, char *fieldname,
 
 
 
-		/* If mapping not found check for indexed mapping */
+		/* If mapping not found check for l_indexed mapping */
 		/* ---------------------------------------------- */
 		if (found == 0)
 		{
-		    /* Get size of geo dim & allocate space of index mapping */
+		    /* Get size of geo dim & allocate space of l_index mapping */
 		    /* ----------------------------------------------------- */
 		    dum = SWdiminfo(swathID, geodim);
 
-                    /* For Landsat files, the index mapping has two values   */
+                    /* For Landsat files, the l_index mapping has two values   */
                     /* for each point, a left and right point.  So for a 37  */
                     /* scene band file there are 2x2 points for each scene   */
                     /* meaning, 2x2x37 = 148 values.  The above function     */
@@ -7219,7 +7215,7 @@ SWextractregion(int32 swathID, int32 regionID, char *fieldname,
 			if (idxMapElem != -1)
 			{
 			    found = 1;
-			    index = i;
+			    l_index = i;
 			    break;
 			}
 		    }
@@ -7268,47 +7264,49 @@ SWextractregion(int32 swathID, int32 regionID, char *fieldname,
 			{
                            if (SWXRegion[regionID]->scanflag == 1)
                            {
-                              start[index] = SWXRegion[regionID]->StartRegion[k]/incr;
+                              start[l_index] = SWXRegion[regionID]->StartRegion[k]/incr;
                               if(SWXRegion[regionID]->band8flag == 2 || 
                                  SWXRegion[regionID]->band8flag == 3)
                               {
-                                 start[index] = (SWXRegion[regionID]->StartRegion[k]+detect_cnt)/incr;
+                                 start[l_index] = (SWXRegion[regionID]->StartRegion[k]+detect_cnt)/incr;
                                  status = SWfieldinfo(SWXRegion[regionID]->swathID,"scan_no",&rank,dims2,&nt,dimlist);
                                  buffer2 = (uint16 *)calloc(dims2[0], sizeof(uint16));
                                  status = SWreadfield(SWXRegion[regionID]->swathID,"scan_no",NULL,NULL,NULL,buffer2);
                                  if(incr == 1)
-                                    start[index] = start[index] - (buffer2[0] * detect_cnt);
+                                    start[l_index] = start[l_index] - (buffer2[0] * detect_cnt);
                                  else
-                                    start[index] = start[index] - buffer2[0];
+                                    start[l_index] = start[l_index] - buffer2[0];
                                  free(buffer2);
                               }
                               scan_shift = nXtrk % incr;
                               if(scan_shift != 0)
                                  nXtrk = nXtrk - scan_shift;
-			      edge[index] = nXtrk / incr;
+			      edge[l_index] = nXtrk / incr;
                               if (nXtrk % incr != 0)
-                                 edge[index]++;
+                                 edge[l_index]++;
                               if(long_status == -1 || incr == 1)
                               {
+                                 if( detect_cnt == 0 )
+                                     return -1;
                                  scan_shift = nXtrk % detect_cnt;
                                  if(scan_shift != 0)
-                                    edge[index] = nXtrk - scan_shift;
+                                    edge[l_index] = nXtrk - scan_shift;
                               }
 
                            }
                            else
                            {
-			      start[index] = SWXRegion[regionID]->StartRegion[k] * incr + offset;
-			      edge[index] = nXtrk * incr - offset;
+			      start[l_index] = SWXRegion[regionID]->StartRegion[k] * incr + offset;
+			      edge[l_index] = nXtrk * incr - offset;
                            }
 			}
 			else
 			{
 			    /* Negative increment (geodim > datadim) */
 			    /* ------------------------------------- */
-			    start[index] = SWXRegion[regionID]->StartRegion[k]
+			    start[l_index] = SWXRegion[regionID]->StartRegion[k]
 				/ (-incr) + offset;
-			    edge[index] = nXtrk / (-incr);
+			    edge[l_index] = nXtrk / (-incr);
 
 			    /*
 			     * If Xtrk not exactly divisible by incr, round
@@ -7317,7 +7315,7 @@ SWextractregion(int32 swathID, int32 regionID, char *fieldname,
 
 			    if (nXtrk % (-incr) != 0)
 			    {
-				edge[index]++;
+				edge[l_index]++;
 			    }
 			}
 
@@ -7359,7 +7357,7 @@ SWextractregion(int32 swathID, int32 regionID, char *fieldname,
 			}
 
 
-			/* Compute start & edge from index mappings */
+			/* Compute start & edge from l_index mappings */
 			/* ---------------------------------------- */
                         if (SWXRegion[regionID]->scanflag == 1 &&
                             (strcmp(fieldname, "Latitude") == 0 ||
@@ -7384,11 +7382,11 @@ SWextractregion(int32 swathID, int32 regionID, char *fieldname,
                                  if(startscanline < idxmap[0])
                                  {
                                     startscandim = 0;
-                                    start[index] = 0;
+                                    start[l_index] = 0;
                                     if(stopscanline > idxmap[scene_cnt * 2 - 1])
                                     {
                                        stopscandim = scene_cnt*2 - startscandim;
-                                       edge[index] = scene_cnt*2 - startscandim;
+                                       edge[l_index] = scene_cnt*2 - startscandim;
                                     }
                                  }
                            }
@@ -7398,14 +7396,14 @@ SWextractregion(int32 swathID, int32 regionID, char *fieldname,
                               if(idxmap[j] <= startscanline && idxmap[j+1] >= startscanline)
                                  if(startscandim == -1)
                                  {
-                                    start[index] = j;
+                                    start[l_index] = j;
                                     startscandim = j;
                                  }
                               if(idxmap[j] <= stopscanline && idxmap[j+1] >= stopscanline)
                                  if(startscandim != -1)
                                  {
-                                    edge[index] = j - start[index] + 2;
-                                    stopscandim = j - start[index] + 1;
+                                    edge[l_index] = j - start[l_index] + 2;
+                                    stopscandim = j - start[l_index] + 1;
                                  }
                               j = j + 2;
                            }
@@ -7416,13 +7414,13 @@ SWextractregion(int32 swathID, int32 regionID, char *fieldname,
                                  if(startscanline < idxmap[0])
                                  {
                                     startscandim = 0;
-                                    start[index] = 0;
+                                    start[l_index] = 0;
                                  }
                               if(stopscandim == -1)
                                  if(stopscanline > idxmap[scene_cnt * 2 - 1])
                                  {
-                                    stopscandim = scene_cnt*2 - start[index];
-                                    edge[index] = scene_cnt*2 - start[index];
+                                    stopscandim = scene_cnt*2 - start[l_index];
+                                    edge[l_index] = scene_cnt*2 - start[l_index];
                                  }
                            }
                            if(SWXRegion[regionID]->band8flag == 2)
@@ -7441,10 +7439,10 @@ SWextractregion(int32 swathID, int32 regionID, char *fieldname,
                                     {
                                        if(idxmap[j] <= startscanline && idxmap[j+1] >= startscanline)
                                        {
-                                          start[index] = j;
+                                          start[l_index] = j;
                                        }
                                        if(idxmap[j] <= stopscanline && idxmap[j+1] >= stopscanline)
-                                          edge[index] = j - start[index] + 2;
+                                          edge[l_index] = j - start[l_index] + 2;
                                        j = j + 2;
                                        if(idxmap[j] == 0  || idxmap[j+1] == 0)
                                           l = scene_cnt;
@@ -7465,20 +7463,20 @@ SWextractregion(int32 swathID, int32 regionID, char *fieldname,
                            if(startscanline < idxmap[0])
                            {
                               startscandim = 0;
-                              start[index] = 0;
+                              start[l_index] = 0;
                            }
                            for (l = 0; l < scene_cnt-1; l++)
                            {
                               if(idxmap[l] <= startscanline && idxmap[l+1] >= startscanline)
                                  if(startscandim == -1)
                                  {
-                                    start[index] = l;
+                                    start[l_index] = l;
                                     startscandim = l;
                                  }
                               if(idxmap[l] <= stopscanline && idxmap[l+1] >= stopscanline)
                                  if(stopscandim == -1)
                                  {
-                                    edge[index] = l - start[index] + 2;
+                                    edge[l_index] = l - start[l_index] + 2;
                                     stopscandim = l + 1;
                                  }
                             }
@@ -7486,7 +7484,7 @@ SWextractregion(int32 swathID, int32 regionID, char *fieldname,
                             {
                                if(stopscanline > idxmap[scene_cnt - 1])
                                {
-                                  edge[index] = scene_cnt - start[index];
+                                  edge[l_index] = scene_cnt - start[l_index];
                                   stopscandim = scene_cnt - 1;
                                }
                             }
@@ -7496,7 +7494,7 @@ SWextractregion(int32 swathID, int32 regionID, char *fieldname,
                                if(stopscandim == -1)
                                   if(stopscanline > idxmap[scene_cnt - 1])
                                   {
-                                     edge[index] = scene_cnt - start[index];
+                                     edge[l_index] = scene_cnt - start[l_index];
                                      stopscandim = scene_cnt -1;
                                   }
                             }
@@ -7508,8 +7506,8 @@ SWextractregion(int32 swathID, int32 regionID, char *fieldname,
                                   if(startscanline < idxmap[0])
                                   {
                                      startscandim = 0;
-                                     start[index] = 0;
-                                     edge[index] = stopscandim - startscandim + 1;
+                                     start[l_index] = 0;
+                                     edge[l_index] = stopscandim - startscandim + 1;
                                   }
                                }
                                if(startscandim == -1)
@@ -7519,9 +7517,9 @@ SWextractregion(int32 swathID, int32 regionID, char *fieldname,
                                   for (l = 0; l < scene_cnt-1; l++)
                                   {
                                      if(idxmap[l] <= startscanline && idxmap[l+1] >= startscanline)
-                                        start[index] = l;
+                                        start[l_index] = l;
                                      if(idxmap[l] <= stopscanline && idxmap[l+1] >= stopscanline)
-                                        edge[index] = l - start[index] + 1;
+                                        edge[l_index] = l - start[l_index] + 1;
                                   }
                                }
                            }
@@ -7531,8 +7529,8 @@ SWextractregion(int32 swathID, int32 regionID, char *fieldname,
                            if (SWXRegion[regionID]->scanflag == 1 && 
                                strcmp(fieldname,dfieldlist) == 0)
                            {
-                              start[index] = SWXRegion[regionID]->StartRegion[k];
-                              edge[index] = SWXRegion[regionID]->StopRegion[k] - 
+                              start[l_index] = SWXRegion[regionID]->StartRegion[k];
+                              edge[l_index] = SWXRegion[regionID]->StopRegion[k] - 
                                              SWXRegion[regionID]->StartRegion[k] + 1;
                               if(SWXRegion[regionID]->band8flag == 2 ||
 				 SWXRegion[regionID]->band8flag == 3 )
@@ -7540,15 +7538,15 @@ SWextractregion(int32 swathID, int32 regionID, char *fieldname,
                                  status = SWfieldinfo(SWXRegion[regionID]->swathID,"scan_no",&rank,dims2,&nt,dimlist);
                                  buffer2 = (uint16 *)calloc(dims2[0], sizeof(uint16));
                                  status = SWreadfield(SWXRegion[regionID]->swathID,"scan_no",NULL,NULL,NULL,buffer2);
-                                 start[index] = start[index] - (buffer2[0] * detect_cnt - detect_cnt);
+                                 start[l_index] = start[l_index] - (buffer2[0] * detect_cnt - detect_cnt);
                                  free(buffer2);
                               }
                            }
                            else
                            {
-			      start[index] = idxmap[SWXRegion[regionID]->StartRegion[k]];
+			      start[l_index] = idxmap[SWXRegion[regionID]->StartRegion[k]];
 
-			      edge[index] = idxmap[SWXRegion[regionID]->StopRegion[k]] -
+			      edge[l_index] = idxmap[SWXRegion[regionID]->StopRegion[k]] -
 			                 idxmap[SWXRegion[regionID]->StartRegion[k]] + 1;
                            }
                         }
@@ -7600,7 +7598,7 @@ SWextractregion(int32 swathID, int32 regionID, char *fieldname,
 	}
     }
 
-    /* Free index mappings if applicable */
+    /* Free l_index mappings if applicable */
     /* --------------------------------- */
     if (idxmap != NULL)
     {
@@ -7633,7 +7631,7 @@ SWextractregion(int32 swathID, int32 regionID, char *fieldname,
 |  buffer	  void		      Values to update                        |
 |  start	  int32		                                              |
 |  edge		  int32							      |
-|  idxmap	  int32 *	      Buffer of index mapping values          |
+|  idxmap	  int32 *	      Buffer of l_index mapping values          |
 |  startscanline  int32		      Start of scan region		      |
 |  stopscanline   int32		      Stop of scan region		      |
 |                                                                             |
@@ -7661,7 +7659,7 @@ int32 edge[], int32 *idxmap, int32 startscanline, int32 stopscanline)
                                         /*  L7 float scene sub.              */
    float32	*buffer2;
    float32	*bufferc;
-   float32	deg2rad = PI/180.00;
+   float32	deg2rad = (float32)(M_PI/180.00);
 
    float32	p1_long = 0.0;	/* point 1, longitude */
    float32	p2_long = 0.0;	/* point 2, longitude */
@@ -7811,13 +7809,13 @@ int32 edge[], int32 *idxmap, int32 startscanline, int32 stopscanline)
    {
       if (p2_long >= 90.0)
       {
-         p1_long = p1_long + 180.0;
-         p2_long = p2_long - 180.0;
+         p1_long = p1_long + 180.0f;
+         p2_long = p2_long - 180.0f;
          p1_long_l90_flag = 2;
       }
       else
       {
-         p1_long = p1_long + 180.0;
+         p1_long = p1_long + 180.0f;
          p1_long_l90_flag = 1;
       }
    }
@@ -7825,13 +7823,13 @@ int32 edge[], int32 *idxmap, int32 startscanline, int32 stopscanline)
    {
       if(p2_long <= -90.0)
       {
-         p1_long = p1_long - 180.0;
-         p2_long = p2_long + 180.0;
+         p1_long = p1_long - 180.0f;
+         p2_long = p2_long + 180.0f;
          p1_long_g90_flag = 2;
       }
       else
       {
-         p1_long = p1_long - 90.0;
+         p1_long = p1_long - 90.0f;
          p1_long_g90_flag = 1;
       }
    }
@@ -7839,31 +7837,31 @@ int32 edge[], int32 *idxmap, int32 startscanline, int32 stopscanline)
    {
       if (p1_long < 0.0)
       {
-         p2_long = p2_long + 90.0;
-         p1_long = p1_long + 90.0;
+         p2_long = p2_long + 90.0f;
+         p1_long = p1_long + 90.0f;
          p2_long_l90_flag = 2;
       }
       else
       {
-         p2_long = p2_long + 180.0;
+         p2_long = p2_long + 180.0f;
          p2_long_l90_flag = 1;
       }
    }
    if (p2_long >= 90.0 && p1_long_l90_flag != 2)
    {
-      p2_long = p2_long - 90.0;
+      p2_long = p2_long - 90.0f;
       p2_long_g90_flag = 1;
    }
 
 
-   x_p1 = RADOE * cos((p1_long*deg2rad)) * sin((p1_lat*deg2rad));
-   y_p1 = RADOE * sin((p1_long*deg2rad)) * sin((p1_lat*deg2rad));
-   z_p1 = RADOE * cos((p1_lat*deg2rad));
+   x_p1 = (float)(RADOE * cos((p1_long*deg2rad)) * sin((p1_lat*deg2rad)));
+   y_p1 = (float)(RADOE * sin((p1_long*deg2rad)) * sin((p1_lat*deg2rad)));
+   z_p1 = (float)(RADOE * cos((p1_lat*deg2rad)));
 
    
-   x_p2 = RADOE * cos((p2_long*deg2rad)) * sin((p2_lat*deg2rad));
-   y_p2 = RADOE * sin((p2_long*deg2rad)) * sin((p2_lat*deg2rad));
-   z_p2 = RADOE * cos((p2_lat*deg2rad));
+   x_p2 = (float)(RADOE * cos((p2_long*deg2rad)) * sin((p2_lat*deg2rad)));
+   y_p2 = (float)(RADOE * sin((p2_long*deg2rad)) * sin((p2_lat*deg2rad)));
+   z_p2 = (float)(RADOE * cos((p2_lat*deg2rad)));
 
    x_pi = x_p1 + (x_p2 - x_p1)*(scanline_pi-scanline_p1)/(scanline_p2-scanline_p1);
    y_pi = y_p1 + (y_p2 - y_p1)*(scanline_pi-scanline_p1)/(scanline_p2-scanline_p1);
@@ -7871,38 +7869,38 @@ int32 edge[], int32 *idxmap, int32 startscanline, int32 stopscanline)
 
    if (fieldflag == 1)
    {
-      pi_long = atan(y_pi/x_pi)*180.0/PI;
+      pi_long = (float)(atan(y_pi/x_pi)*180.0/M_PI);
       if (p1_long_l90_flag == 1 || p2_long_l90_flag == 1)
       {
-         pi_long = pi_long - 180.0;
+         pi_long = pi_long - 180.0f;
          p1_long_l90_flag = 0;
 	 p2_long_l90_flag = 0;
       }
       if (p1_long_g90_flag == 1 || p2_long_g90_flag == 1)
       {
-         pi_long = pi_long + 90.0;
+         pi_long = pi_long + 90.0f;
          p1_long_g90_flag = 0;
          p2_long_g90_flag = 0;
       }
       if (p1_long_l90_flag == 2)
       {
          if (pi_long > 0.0)
-            pi_long = pi_long - 180.0;
+            pi_long = pi_long - 180.0f;
          else if (pi_long < 0.0)
-            pi_long = pi_long + 180.0;
+            pi_long = pi_long + 180.0f;
          p1_long_l90_flag = 0;
       }
       if (p1_long_g90_flag == 2)
       {
          if (pi_long > 0.0)
-            pi_long = pi_long - 180.0;
+            pi_long = pi_long - 180.0f;
          else if (pi_long < 0.0)
-            pi_long = pi_long + 180.0;
+            pi_long = pi_long + 180.0f;
          p1_long_g90_flag = 0;
       }
       if (p2_long_l90_flag == 2)
       {
-         pi_long = pi_long - 90.0;
+         pi_long = pi_long - 90.0f;
          p2_long_l90_flag = 0;
       }
 
@@ -7934,7 +7932,7 @@ int32 edge[], int32 *idxmap, int32 startscanline, int32 stopscanline)
     }
     if (fieldflag == 2)
     {
-      pi_lat = atan((sqrt(x_pi*x_pi + y_pi*y_pi)/z_pi))*180.0/PI;
+      pi_lat = (float)(atan((sqrt(x_pi*x_pi + y_pi*y_pi)/z_pi))*180.0/M_PI);
       switch(pos2)
       {
       case UL:
@@ -7995,7 +7993,7 @@ int32 edge[], int32 *idxmap, int32 startscanline, int32 stopscanline)
 |   Date     Programmer   Description                                         |
 |  ======   ============  =================================================   |
 |  Jun 96   Joel Gales    Original Programmer                                 |
-|  Jun 03   Abe Taaheri   added clearing timeflag if SWextractregion failes   |
+|  Jun 03   Abe Taaheri   added clearing timeflag if SWextractregion fails    |
 |                                                                             |
 |  END_PROLOG                                                                 |
 -----------------------------------------------------------------------------*/
@@ -8122,7 +8120,7 @@ SWdupregion(int32 oldregionID)
 |  Jun 96   Joel Gales    Original Programmer                                 |
 |  Aug 96   Joel Gales    Add vertical subsetting                             |
 |  Dec 96   Joel Gales    Add multiple vertical subsetting capability         |
-|  Mar 97   Joel Gales    Add support for index mapping                       |
+|  Mar 97   Joel Gales    Add support for l_index mapping                       |
 |  Jul 99   DaW           Add support for floating scene subsetting           |
 |                                                                             |
 |  END_PROLOG                                                                 |
@@ -8152,18 +8150,18 @@ SWregioninfo(int32 swathID, int32 regionID, char *fieldname,
     int32           sdInterfaceID;	/* HDF SDS interface ID */
     int32           swVgrpID;	/* Swath Vgroup ID */
 
-    int32           index;	/* Geo Dim Index */
+    int32           l_index = 0;	/* Geo Dim Index */
     int32           nDim;	/* Number of dimensions */
     int32           slen[64];	/* String length array */
     int32           dum;	/* Dummy variable */
-    int32           incr;	/* Mapping increment */
+    int32           incr = 0;	/* Mapping increment */
     int32           nXtrk = 0;	/* Number of cross tracks */
     int32	    scan_shift = 0; /* Used to take out partial scans */
     int32	    startscandim = -1;    /* Used for floating scene region size */
     int32	    stopscandim = -1;    /* Used for floating scene region size */
     int32           dumdims[8];	/* Dimensions from SWfieldinfo */
-    int32           idxMapElem = -1;	/* Number of index map elements  */
-    int32          *idxmap = NULL;	/* Pointer to index mapping array */
+    int32           idxMapElem = -1;	/* Number of l_index map elements  */
+    int32          *idxmap = NULL;	/* Pointer to l_index mapping array */
     int32	    datafld = 0;
 
    uint8	scene_cnt = 0;		/* Number of scenes in swath */
@@ -8348,7 +8346,7 @@ SWregioninfo(int32 swathID, int32 regionID, char *fieldname,
 		if (statMap == 0)
 		{
 		    found = 1;
-		    index = i;
+		    l_index = i;
 		    break;
 		}
 	    }
@@ -8358,11 +8356,11 @@ SWregioninfo(int32 swathID, int32 regionID, char *fieldname,
 	    /* ---------------------------------------------------- */
 	    if (found == 0)
 	    {
-		index = EHstrwithin(geodim, dimlist, ',');
+		l_index = EHstrwithin(geodim, dimlist, ',');
 
 		/* Geo dimension found within subset field dimlist */
 		/* ----------------------------------------------- */
-		if (index != -1)
+		if (l_index != -1)
 		{
 		    found = 1;
 		    incr = 1;
@@ -8371,11 +8369,11 @@ SWregioninfo(int32 swathID, int32 regionID, char *fieldname,
 
 
 
-	    /* If mapping not found check for indexed mapping */
+	    /* If mapping not found check for l_indexed mapping */
 	    /* ---------------------------------------------- */
 	    if (found == 0)
 	    {
-		/* Get size of geo dim & allocate space of index mapping */
+		/* Get size of geo dim & allocate space of l_index mapping */
 		/* ----------------------------------------------------- */
 		dum = SWdiminfo(swathID, geodim);
 		idxmap = (int32 *) calloc(dum, sizeof(int32));
@@ -8400,7 +8398,7 @@ SWregioninfo(int32 swathID, int32 regionID, char *fieldname,
 		    if (idxMapElem != -1)
 		    {
 			found = 1;
-			index = i;
+			l_index = i;
 			break;
 		    }
 		}
@@ -8411,7 +8409,7 @@ SWregioninfo(int32 swathID, int32 regionID, char *fieldname,
 	    /* --------------------- */
 	    if (found == 1 && idxMapElem == -1)
 	    {
-		dims[index] = 0;
+		dims[l_index] = 0;
 
 		/* Loop through all regions */
 		/* ------------------------ */
@@ -8432,24 +8430,26 @@ SWregioninfo(int32 swathID, int32 regionID, char *fieldname,
                             scan_shift = nXtrk % incr;
                             if(scan_shift != 0)
                                nXtrk = nXtrk - scan_shift;
-                            dims[index] += nXtrk/incr;
+                            dims[l_index] += nXtrk/incr;
                             if(long_status == -1 || incr == 1)
                             {
+                               if( detect_cnt == 0 )
+                                   return -1;
                                scan_shift = nXtrk % detect_cnt;
                                if(scan_shift != 0)
-                                  dims[index] = nXtrk - scan_shift;
+                                  dims[l_index] = nXtrk - scan_shift;
                             }
                         }
 			else
                         {
-			   dims[index] += nXtrk * incr;
+			   dims[l_index] += nXtrk * incr;
                         }
 		    }
 		    else
 		    {
 			/* Negative increment (geodim > datadim) */
 			/* ------------------------------------- */
-			dims[index] += nXtrk / (-incr);
+			dims[l_index] += nXtrk / (-incr);
 
 			/*
 			 * If Xtrk not exactly divisible by incr, round dims
@@ -8457,7 +8457,7 @@ SWregioninfo(int32 swathID, int32 regionID, char *fieldname,
 			 */
 			if (nXtrk % (-incr) != 0)
 			{
-			    dims[index]++;
+			    dims[l_index]++;
 			}
 		    }
 		}
@@ -8468,7 +8468,7 @@ SWregioninfo(int32 swathID, int32 regionID, char *fieldname,
 		/* Indexed Mapping */
 		/* --------------- */
 
-		dims[index] = 0;
+		dims[l_index] = 0;
 
 		/* Loop through all regions */
 		/* ------------------------ */
@@ -8481,7 +8481,7 @@ SWregioninfo(int32 swathID, int32 regionID, char *fieldname,
                       stopscanline = SWXRegion[regionID]->StopRegion[k];
                       if (strcmp(fieldname,dfieldlist) == 0)
                       {
-                         dims[index] = stopscanline - startscanline + 1;
+                         dims[l_index] = stopscanline - startscanline + 1;
                          datafld = 1;
                       }
                       if (strcmp(fieldname, "Latitude") == 0 ||
@@ -8502,11 +8502,11 @@ SWregioninfo(int32 swathID, int32 regionID, char *fieldname,
                                if(startscanline < idxmap[0])
                                {
                                   startscandim = 0;
-                                  dims[index] = 0;
+                                  dims[l_index] = 0;
                                   if(stopscanline > idxmap[scene_cnt *2 - 1])
                                   {
                                      stopscandim = scene_cnt*2 - startscandim;
-                                     dims[index] = scene_cnt*2 - startscandim;
+                                     dims[l_index] = scene_cnt*2 - startscandim;
                                   }
                                }
                          }
@@ -8515,13 +8515,13 @@ SWregioninfo(int32 swathID, int32 regionID, char *fieldname,
                             if(idxmap[j] <= startscanline && idxmap[j+1] >= startscanline)
                                if(startscandim == -1)
                                {
-                                  dims[index] = j;
+                                  dims[l_index] = j;
                                   startscandim = j;
                                }
                             if(idxmap[j] <= stopscanline && idxmap[j+1] >= stopscanline)
                                if(startscandim != -1)
                                {
-                                  dims[index] = j - startscandim + 2;
+                                  dims[l_index] = j - startscandim + 2;
                                   stopscandim = j + 1;
                                }
                             j = j + 2;
@@ -8534,8 +8534,8 @@ SWregioninfo(int32 swathID, int32 regionID, char *fieldname,
                             if(stopscandim == -1)
                                if(stopscanline > idxmap[scene_cnt * 2 - 1])
                                {
-                                  stopscandim = scene_cnt*2 - dims[index];
-                                  dims[index] = scene_cnt*2 - dims[index];
+                                  stopscandim = scene_cnt*2 - dims[l_index];
+                                  dims[l_index] = scene_cnt*2 - dims[l_index];
                                }
                          }
                          if(SWXRegion[regionID]->band8flag == 3)
@@ -8545,7 +8545,7 @@ SWregioninfo(int32 swathID, int32 regionID, char *fieldname,
                                {
                                   startscandim = 0;
                                   if(stopscandim != -1)
-                                     dims[index] = stopscandim - startscandim + 1;
+                                     dims[l_index] = stopscandim - startscandim + 1;
                                }
                          }
                          if(SWXRegion[regionID]->band8flag == 2)
@@ -8564,11 +8564,11 @@ SWregioninfo(int32 swathID, int32 regionID, char *fieldname,
                                   {
                                      if(idxmap[j] <= startscanline && idxmap[j+1] >= startscanline)
                                      {
-                                        dims[index] = j;
+                                        dims[l_index] = j;
                                         startscandim = j;
                                      }
                                      if(idxmap[j] <= stopscanline && idxmap[j+1] >= stopscanline)
-                                        dims[index] = j - startscandim + 2;
+                                        dims[l_index] = j - startscandim + 2;
                                      j = j + 2;
                                      if(idxmap[j] == 0  || idxmap[j+1] == 0)
                                         l = scene_cnt;
@@ -8585,19 +8585,19 @@ SWregioninfo(int32 swathID, int32 regionID, char *fieldname,
                          if(startscanline < idxmap[0])
                          {
                             startscandim = 0;
-                            dims[index] = 0;
+                            dims[l_index] = 0;
                          }
                          for (l = 0; l < scene_cnt-1; l++)
                          {
                             if(idxmap[l] <= startscanline && idxmap[l+1] >= startscanline)
                                if(startscandim == -1)
                                {
-                                  dims[index] = l;
+                                  dims[l_index] = l;
                                   startscandim = l;
                                }
                             if(idxmap[l] <= stopscanline && idxmap[l+1] >= stopscanline)
                             {
-                               dims[index] = l - startscandim + 2;
+                               dims[l_index] = l - startscandim + 2;
                                stopscandim = l + 1;
                             }
                          }
@@ -8605,7 +8605,7 @@ SWregioninfo(int32 swathID, int32 regionID, char *fieldname,
                          {
                             if(stopscanline > idxmap[scene_cnt - 1])
                             {
-                               dims[index] = scene_cnt - startscandim;
+                               dims[l_index] = scene_cnt - startscandim;
                                stopscandim = scene_cnt - 1;
                             }
                          }
@@ -8614,7 +8614,7 @@ SWregioninfo(int32 swathID, int32 regionID, char *fieldname,
                             if(stopscandim == -1)
                                if(stopscanline > idxmap[scene_cnt - 1])
                                {
-                                  dims[index] = scene_cnt - startscandim;
+                                  dims[l_index] = scene_cnt - startscandim;
                                   stopscandim = scene_cnt - 1;
                                }
                          }
@@ -8626,7 +8626,7 @@ SWregioninfo(int32 swathID, int32 regionID, char *fieldname,
                                if(startscanline < idxmap[0])
                                {
                                   startscandim = 0;
-                                  dims[index] = stopscandim - startscandim + 1;
+                                  dims[l_index] = stopscandim - startscandim + 1;
                                }
                             }
                             if(startscandim == -1)
@@ -8636,9 +8636,9 @@ SWregioninfo(int32 swathID, int32 regionID, char *fieldname,
                                for (l = 0; l < scene_cnt-1; l++)
                                {
                                   if(idxmap[l] <= startscanline && idxmap[l+1] >= startscanline)
-                                     dims[index] = l;
+                                     dims[l_index] = l;
                                   if(idxmap[l] <= stopscanline && idxmap[l+1] >= stopscanline)
-                                     dims[index] = l - dims[index] + 1;
+                                     dims[l_index] = l - dims[l_index] + 1;
                                }
                             }
                          }
@@ -8653,7 +8653,7 @@ SWregioninfo(int32 swathID, int32 regionID, char *fieldname,
 		         nXtrk = idxmap[SWXRegion[regionID]->StopRegion[k]] -
 			         idxmap[SWXRegion[regionID]->StartRegion[k]] + 1;
 
-		         dims[index] += nXtrk;
+		         dims[l_index] += nXtrk;
                       }
                     }
 		}
@@ -8686,16 +8686,16 @@ SWregioninfo(int32 swathID, int32 regionID, char *fieldname,
 
 		    /* Find vertical dimension within dimlist */
 		    /* -------------------------------------- */
-		    index = EHstrwithin(SWXRegion[regionID]->DimNamePtr[j],
+		    l_index = EHstrwithin(SWXRegion[regionID]->DimNamePtr[j],
 					dimlist, ',');
 
 		    /* If dimension found ... */
 		    /* ---------------------- */
-		    if (index != -1)
+		    if (l_index != -1)
 		    {
 			/* Compute dimension size */
 			/* ---------------------- */
-			dims[index] =
+			dims[l_index] =
 			    SWXRegion[regionID]->StopVertical[j] -
 			    SWXRegion[regionID]->StartVertical[j] + 1;
 		    }
@@ -8740,7 +8740,7 @@ SWregioninfo(int32 swathID, int32 regionID, char *fieldname,
 
 
 
-    /* Free index mappings if applicable */
+    /* Free l_index mappings if applicable */
     /* --------------------------------- */
     if (idxmap != NULL)
     {
@@ -8784,7 +8784,7 @@ SWregioninfo(int32 swathID, int32 regionID, char *fieldname,
 |   Date     Programmer   Description                                         |
 |  ======   ============  =================================================   |
 |  Jun 96   Joel Gales    Original Programmer                                 |
-|  Jun 03   Abe Taaheri   added clearing timeflag if SWregioninfo failes      |
+|  Jun 03   Abe Taaheri   added clearing timeflag if SWregioninfo fails       |
 |                                                                             |
 |  END_PROLOG                                                                 |
 -----------------------------------------------------------------------------*/
@@ -8904,7 +8904,7 @@ int32
 SWdefvrtregion(int32 swathID, int32 regionID, char *vertObj, float64 range[])
 {
     intn            i;		/* Loop index */
-    intn            j;		/* Loop index */
+    intn            j = 0;		/* Loop index */
     intn            k;		/* Loop index */
     intn            status;	/* routine return status variable */
 
@@ -8953,7 +8953,7 @@ SWdefvrtregion(int32 swathID, int32 regionID, char *vertObj, float64 range[])
 	{
 	    /* Get string length of vertObj (minus "DIM:) */
 	    /* ------------------------------------------ */
-	    slen = strlen(vertObj) - 4;
+	    slen = (int)strlen(vertObj) - 4;
 
 
 	    /* If regionID = -1 then setup swath region entry */
@@ -9045,7 +9045,7 @@ SWdefvrtregion(int32 swathID, int32 regionID, char *vertObj, float64 range[])
 	    {
 		/* Get string length of vertical dimension */
 		/* --------------------------------------- */
-		slen = strlen(dimlist);
+		slen = (int)strlen(dimlist);
 
 
 		/* Get size in bytes of vertical field numbertype */
@@ -9406,7 +9406,7 @@ SWdefvrtregion(int32 swathID, int32 regionID, char *vertObj, float64 range[])
 |  END_PROLOG                                                                 |
 -----------------------------------------------------------------------------*/
 int32
-SWdefscanregion(int32 swathID, char *fieldname, float64 range[], int32 mode)
+SWdefscanregion(int32 swathID, char *fieldname, float64 range[], CPL_UNUSED int32 mode)
 {
     intn            j;		/* Loop index */
     intn            k;		/* Loop index */
@@ -9514,7 +9514,7 @@ SWdefscanregion(int32 swathID, char *fieldname, float64 range[], int32 mode)
     }
     else
     {
-       slen = strlen(fieldname);
+       slen = (int)strlen(fieldname);
        tfieldname = (char *)calloc(slen + 1, sizeof(char));
        strcpy(tfieldname, fieldname);
     }
@@ -9584,7 +9584,7 @@ SWdefscanregion(int32 swathID, char *fieldname, float64 range[], int32 mode)
           {
              idxmap = (int32 *)calloc(dimsize, sizeof(int32));
              (void) SWidxmapinfo(swathID, "GeoTrack", "ScanLineTrack", idxmap);
-             tmprange0 = range[0];
+             tmprange0 = (int32)range[0];
              if(band82flag != 1 && band83flag != 1)
              {
                 if (range[1] > idxmap[scene_cnt*2 - 1])
@@ -9595,7 +9595,7 @@ SWdefscanregion(int32 swathID, char *fieldname, float64 range[], int32 mode)
              }
              if(band82flag == 1 || band83flag == 1)
              {
-                tmprange0 = range[0] - (buffer[0] * detect_cnt - detect_cnt);
+                tmprange0 = (int32)(range[0] - (buffer[0] * detect_cnt - detect_cnt));
              }
              if(tmprange0 >= idxmap[scene_cnt * 2 - 1])
              {
@@ -9614,7 +9614,7 @@ SWdefscanregion(int32 swathID, char *fieldname, float64 range[], int32 mode)
 
     if (status == 0)
     {
-          slen = strlen(tfieldname);
+          slen = (int)strlen(tfieldname);
 
           SETSWTHREG;
 
@@ -9727,7 +9727,7 @@ SWsetfillvalue(int32 swathID, char *fieldname, VOIDP fillval)
 	    /* If unmerged field then call HDF set field routine */
 	    if (solo == 1)
 	    {
-		status = SDsetfillvalue(sdid, fillval);
+                /* status = */ SDsetfillvalue(sdid, fillval);
 	    }
 
 	    /*
@@ -9907,7 +9907,7 @@ SWdetach(int32 swathID)
 	Vgetname(SWXSwath[sID].IDTable, swathname);
 
 
-	/* Create 1D "orphened" fields */
+	/* Create 1D "orphaned" fields */
 	/* --------------------------- */
 	i = 0;
 
@@ -10172,7 +10172,7 @@ SWdetach(int32 swathID)
 		}
 		/* Zero out dimbuf1 */
 		/* ---------------- */
-		for (k = 0; k < sizeof(dimbuf1); k++)
+		for (k = 0; k < (intn)sizeof(dimbuf1); k++)
 		{
 		    dimbuf1[k] = 0;
 		}
@@ -10204,7 +10204,7 @@ SWdetach(int32 swathID)
 		    {
 			/* Zero out dimbuf2 */
 			/* ---------------- */
-			for (k = 0; k < sizeof(dimbuf2); k++)
+			for (k = 0; k < (intn)sizeof(dimbuf2); k++)
 			{
 			    dimbuf2[k] = 0;
 			}
@@ -10234,7 +10234,7 @@ SWdetach(int32 swathID)
 			    /* ------------------------------ */
 			    match[0] += SWXSDcomb[5 * j];
 
-			    /* Concatanate name */
+			    /* Concatenate name */
 			    /* ---------------- */
 			    strcat(nambuf, ",");
 			    memcpy(nambuf + strlen(nambuf),
@@ -10266,7 +10266,7 @@ SWdetach(int32 swathID)
 
 		if (abs(match[0]) == 1)
 		{
-		    /* Two Dimensional Array (no merging has occured) */
+		    /* Two Dimensional Array (no merging has occurred) */
 		    /* ---------------------------------------------- */
 		    dims[0] = abs(match[1]);
 		    dims[1] = abs(match[2]);
@@ -10361,12 +10361,12 @@ SWdetach(int32 swathID)
 		     */
 		    if (k == 0 && cmbfldcnt > 0)
 		    {
-			sprintf(dimbuf2, "%s%s_%ld", "MRGDIM:",
+			snprintf(dimbuf2, sizeof(dimbuf2), "%s%s_%ld", "MRGDIM:",
 				swathname, (long)dims[0]);
 		    }
 		    else
 		    {
-			/* Otherwise concatanate swathname to dim name */
+			/* Otherwise concatenate swathname to dim name */
 			/* ------------------------------------------- */
 			strcat(dimbuf2, ":");
 			strcat(dimbuf2, swathname);
@@ -10483,7 +10483,7 @@ SWdetach(int32 swathID)
 	}
 
 
-	/* Replace trailing delimitors on SWXSDname & SWXSDdims */
+	/* Replace trailing delimiters on SWXSDname & SWXSDdims */
 	/* ---------------------------------------------------- */
 	if (nflds != 0)
 	{
@@ -10639,12 +10639,14 @@ SWupdatescene(int32 swathID, int32 regionID)
  
     int32           startReg;   /* Indexed start region */
     int32           stopReg;    /* Indexed stop region */
-    int32           index[MAXNREGIONS]; /* to store indicies when stop and 
+    int32           l_index[MAXNREGIONS]; /* to store indices when stop and 
 					   start are different */
 					   
-    int32           ind;        /* index */
+    int32           ind;        /* l_index */
     int32           tempnRegions; /* temp number of regions */
 
+    memset(l_index, 0, sizeof(int32) * MAXNREGIONS);
+
     /* Check for valid swath ID */
     /* ------------------------ */
     status = SWchkswid(swathID, "SWupdatescene", &fid, &sdInterfaceID,
@@ -10705,9 +10707,9 @@ SWupdatescene(int32 swathID, int32 regionID)
 	   }
 	   else
 	   {
-	       /* store index number of regions that have different start and
+	       /* store l_index number of regions that have different start and
 		  stop */
-	       index[ind] = k;
+	       l_index[ind] = k;
 	       ind += 1;
 	   }
 	}
@@ -10723,9 +10725,9 @@ SWupdatescene(int32 swathID, int32 regionID)
 	for (k = 0; k < SWXRegion[regionID]->nRegions; k++)
 	{
 	    SWXRegion[regionID]->StartRegion[k] =
-	      SWXRegion[regionID]->StartRegion[index[k]];
+	      SWXRegion[regionID]->StartRegion[l_index[k]];
 	    SWXRegion[regionID]->StopRegion[k] =
-	      SWXRegion[regionID]->StopRegion[index[k]];
+	      SWXRegion[regionID]->StopRegion[l_index[k]];
 	}
 	
     }
@@ -10764,22 +10766,22 @@ SWupdatescene(int32 swathID, int32 regionID)
 |                                                                             |
 |  FUNCTION: SWupdateidxmap                                                   |
 |                                                                             |
-|  DESCRIPTION: Updates the map index for a specified region.                 |
+|  DESCRIPTION: Updates the map l_index for a specified region.                 |
 |                                                                             |
 |                                                                             |
 |  Return Value    Type     Units     Description                             |
 |  ============   ======  =========   =====================================   |
 |  nout           int32               return Number of elements in output     |
-|                                     index array if SUCCEED, (-1) FAIL       |
+|                                     l_index array if SUCCEED, (-1) FAIL       |
 |                                                                             |
 |  INPUTS:                                                                    |
 |  swathID        int32               Swath structure ID                      |
 |  regionID       int32               Region ID                               |
-|  indexin        int32               array of index values                   |
+|  l_indexin        int32               array of l_index values                   |
 |                                                                             |
 |  OUTPUTS:                                                                   |
-|  indexout       int32               array of index values                   |
-|  indicies	  int32		      array of start and stop in region       |
+|  l_indexout       int32               array of l_index values                   |
+|  indices	  int32		      array of start and stop in region       |
 |                                                                             |
 |  NOTES:                                                                     |
 |                                                                             |
@@ -10787,13 +10789,13 @@ SWupdatescene(int32 swathID, int32 regionID)
 |   Date     Programmer   Description                                         |
 |  ======   ============  =================================================   |
 |  Aug 97   Abe Taaheri   Original Programmer                                 |
-|  AUG 97   Abe Taaheri   Add support for index mapping                       |
+|  AUG 97   Abe Taaheri   Add support for l_index mapping                       |
 |  Sep 99   DaW		  Add support for Floating Scene Subsetting Landsat 7 |
 |                                                                             |
 |  END_PROLOG                                                                 |
 -----------------------------------------------------------------------------*/
 int32
-SWupdateidxmap(int32 swathID, int32 regionID, int32 indexin[], int32 indexout[], int32 indicies[])
+SWupdateidxmap(int32 swathID, int32 regionID, int32 l_indexin[], int32 l_indexout[], int32 indicies[])
 {
     intn            i;          /* Loop index */
     intn            j;          /* Loop index */
@@ -10810,7 +10812,7 @@ SWupdateidxmap(int32 swathID, int32 regionID, int32 indexin[], int32 indexout[],
  
     int32           startReg = 0;   /* Indexed start region */
     int32           stopReg = 0;    /* Indexed stop region */
-    int32           nout=-1;       /* Number of elements in output index array */
+    int32           nout=-1;       /* Number of elements in output l_index array */
     int32	    indexoffset = 0;
     uint8	    scene_cnt = 0;	/* Used for L7 float scene sub.      */
     uint8           detect_cnt = 0;     /* Used to convert scan to scanline  */
@@ -10856,7 +10858,7 @@ SWupdateidxmap(int32 swathID, int32 regionID, int32 indexin[], int32 indexout[],
 	for (k = 0; k < SWXRegion[regionID]->nRegions; k++)
 	{
 	    
-	    /* fix overlap index mapping problem for Landsat 7 */
+	    /* fix overlap l_index mapping problem for Landsat 7 */
 	    
 	    startReg = SWXRegion[regionID]->StartRegion[k];
 	    stopReg = SWXRegion[regionID]->StopRegion[k];
@@ -10896,18 +10898,18 @@ SWupdateidxmap(int32 swathID, int32 regionID, int32 indexin[], int32 indexout[],
                {
                   for(i=0; i<scene_cnt;i++)
                   {
-                     if(indexin[j] <= startReg && indexin[j+1] >= startReg)
+                     if(l_indexin[j] <= startReg && l_indexin[j+1] >= startReg)
                         if(indicies[0] == -1)
                            indicies[0] = j;
-                     if(indexin[j] <= stopReg && indexin[j+1] >= stopReg)
+                     if(l_indexin[j] <= stopReg && l_indexin[j+1] >= stopReg)
                         indicies[1] = j + 1;
                      j = j + 2;
-                     if(indexin[j] == 0 || indexin[j+1] == 0)
+                     if(l_indexin[j] == 0 || l_indexin[j+1] == 0)
                         i = scene_cnt;
                   }
                   if(indicies[0] == -1)
                   {
-                     if(startReg <= indexin[0])
+                     if(startReg <= l_indexin[0])
                         indicies[0] = 0;
                   }
                   if(indicies[0] == -1)
@@ -10915,11 +10917,11 @@ SWupdateidxmap(int32 swathID, int32 regionID, int32 indexin[], int32 indexout[],
                      j = 0;
                      for(i=0; i<scene_cnt; i++)
                      {
-                        if(indexin[j] <= startReg && indexin[j+1] >= startReg)
+                        if(l_indexin[j] <= startReg && l_indexin[j+1] >= startReg)
                            if(indicies[0] == -1)
                               indicies[0] = j;
                         j = j + 1;
-                        if(indexin[j] == 0 || indexin[j+1] == 0)
+                        if(l_indexin[j] == 0 || l_indexin[j+1] == 0)
                            i = scene_cnt;
                      }
                   }
@@ -10928,16 +10930,16 @@ SWupdateidxmap(int32 swathID, int32 regionID, int32 indexin[], int32 indexout[],
                      j = 0;
                      for(i=0; i<scene_cnt; i++)
                      {
-                        if(indexin[j] <= stopReg && indexin[j+1] >= stopReg)
+                        if(l_indexin[j] <= stopReg && l_indexin[j+1] >= stopReg)
                            if(indicies[1] == -1)
                               indicies[1] = j + 1;
                         j = j + 1;
-                        if(indexin[j] == 0 || indexin[j+1] == 0)
+                        if(l_indexin[j] == 0 || l_indexin[j+1] == 0)
                            i = scene_cnt;
                      }
                   }
                   if(indicies[1] == -1)
-                     if(stopReg > indexin[scene_cnt - 1])
+                     if(stopReg > l_indexin[scene_cnt - 1])
                         indicies[1] = scene_cnt - 1;
                }
 
@@ -10952,9 +10954,9 @@ SWupdateidxmap(int32 swathID, int32 regionID, int32 indexin[], int32 indexout[],
                   for(i=0; i<scene_cnt; i++)
                   {
                      j = j + 2;
-                     if(indexin[j] == 0 || indexin[j+1] == 0)
+                     if(l_indexin[j] == 0 || l_indexin[j+1] == 0)
                      {
-                        if(indexin[j] == 0)
+                        if(l_indexin[j] == 0)
                            gtflag = 1;
                         else
                            ngtflag = 1;
@@ -10966,28 +10968,28 @@ SWupdateidxmap(int32 swathID, int32 regionID, int32 indexin[], int32 indexout[],
                   {
                      for(i=0; i<scene_cnt; i++)
                      {
-		      if( startReg >= (indexin[j] + indexoffset - detect_cnt) && 
-			  startReg <= (indexin[j+1] + indexoffset - detect_cnt) )
+		      if( startReg >= (l_indexin[j] + indexoffset - detect_cnt) && 
+			  startReg <= (l_indexin[j+1] + indexoffset - detect_cnt) )
                            if(indicies[0] == -1)
                               indicies[0] = j;
-		      if( stopReg >= (indexin[j] + indexoffset - detect_cnt ) && 
-			  stopReg <= (indexin[j+1] + indexoffset - detect_cnt ) )
+		      if( stopReg >= (l_indexin[j] + indexoffset - detect_cnt ) && 
+			  stopReg <= (l_indexin[j+1] + indexoffset - detect_cnt ) )
                            indicies[1] = j + 1;
                         j = j + 2;
-                        if(indexin[j] == 0 || indexin[j+1] == 0)
+                        if(l_indexin[j] == 0 || l_indexin[j+1] == 0)
                            i = scene_cnt;
                      }
                      if(SWXRegion[regionID]->band8flag == 1)
                      {
                         if(indicies[1] == -1)
-                           if(stopReg > (indexin[j - 1] + indexoffset - detect_cnt))
+                           if(stopReg > (l_indexin[j - 1] + indexoffset - detect_cnt))
                               indicies[1] = j - 1;
                      }
                      if(SWXRegion[regionID]->band8flag == 2 ||
                         SWXRegion[regionID]->band8flag == 3)
                      {
 		       
-                        if(startReg >= (indexin[j - 1] + indexoffset - detect_cnt))
+                        if(startReg >= (l_indexin[j - 1] + indexoffset - detect_cnt))
                         {
                            indicies[0] = -1;
                            indicies[1] = -1;
@@ -11001,15 +11003,15 @@ SWupdateidxmap(int32 swathID, int32 regionID, int32 indexin[], int32 indexout[],
                            j = 0;
                            for(i=0; i<scene_cnt; i++)
                            {
-			     if( startReg >= (indexin[j] + indexoffset - detect_cnt) && 
-				 startReg <= (indexin[j+1] + indexoffset - detect_cnt) )
+			     if( startReg >= (l_indexin[j] + indexoffset - detect_cnt) && 
+				 startReg <= (l_indexin[j+1] + indexoffset - detect_cnt) )
 			       if(indicies[0] == -1)
 				 indicies[0] = j;
-			     if( stopReg >= (indexin[j] + indexoffset - detect_cnt ) && 
-				 stopReg <= (indexin[j+1] + indexoffset - detect_cnt ) )
+			     if( stopReg >= (l_indexin[j] + indexoffset - detect_cnt ) && 
+				 stopReg <= (l_indexin[j+1] + indexoffset - detect_cnt ) )
 			       indicies[1] = j + 1;
                               j = j + 2;
-                              if(indexin[j] == 0 || indexin[j+1] == 0)
+                              if(l_indexin[j] == 0 || l_indexin[j+1] == 0)
                                  i = scene_cnt;
                            }
                         }
@@ -11019,18 +11021,18 @@ SWupdateidxmap(int32 swathID, int32 regionID, int32 indexin[], int32 indexout[],
                            j = 0;
                            for(i=0; i<scene_cnt; i++)
                            {
-			     if( startReg >= (indexin[j] + indexoffset - detect_cnt) && 
-				 startReg <= (indexin[j+1] + indexoffset - detect_cnt) )
+			     if( startReg >= (l_indexin[j] + indexoffset - detect_cnt) && 
+				 startReg <= (l_indexin[j+1] + indexoffset - detect_cnt) )
 			       if(indicies[0] == -1)
 				 indicies[0] = j;
 		      
 			     j = j + 2;
-			     if(indexin[j] == 0 || indexin[j+1] == 0)
+			     if(l_indexin[j] == 0 || l_indexin[j+1] == 0)
 			       i = scene_cnt;
                            }
                         }
                         if(indicies[1] == -1)
-                           if(stopReg > (indexin[j - 1] + indexoffset - detect_cnt) )
+                           if(stopReg > (l_indexin[j - 1] + indexoffset - detect_cnt) )
                               indicies[1] = j - 1;
                      }
                      if(indicies[1] == -1)
@@ -11038,11 +11040,11 @@ SWupdateidxmap(int32 swathID, int32 regionID, int32 indexin[], int32 indexout[],
                         j = 0;
                         for(i=0; i<scene_cnt; i++)
                         {
-			  if( stopReg >= (indexin[j] + indexoffset - detect_cnt ) && 
-			      stopReg <= (indexin[j+1] + indexoffset - detect_cnt ) )
+			  if( stopReg >= (l_indexin[j] + indexoffset - detect_cnt ) && 
+			      stopReg <= (l_indexin[j+1] + indexoffset - detect_cnt ) )
 			    indicies[1] = j;
 			  j = j + 2;
-			  if(indexin[j] == 0 || indexin[j+1] == 0)
+			  if(l_indexin[j] == 0 || l_indexin[j+1] == 0)
 			    i = scene_cnt;
                         }
                      }
@@ -11052,18 +11054,18 @@ SWupdateidxmap(int32 swathID, int32 regionID, int32 indexin[], int32 indexout[],
                   {
                      for(i=0; i<scene_cnt; i++)
                      {
-		      if( startReg >= indexin[j] && startReg <= indexin[j+1])
+		      if( startReg >= l_indexin[j] && startReg <= l_indexin[j+1])
                            if(indicies[0] == -1)
                               indicies[0] = j;
-		      if( stopReg >= indexin[j] && stopReg <= indexin[j+1])
+		      if( stopReg >= l_indexin[j] && stopReg <= l_indexin[j+1])
                            indicies[1] = j + 1;
                         j = j + 2;
-                        if(indexin[j] == 0 || indexin[j+1] == 0)
+                        if(l_indexin[j] == 0 || l_indexin[j+1] == 0)
                            i = scene_cnt;
                      }
                      if(SWXRegion[regionID]->band8flag == 2)
                      {
-                        if(startReg >= indexin[j] )
+                        if(startReg >= l_indexin[j] )
                         {
                            if(indicies[0] == -1)
                               indicies[0] = j;
@@ -11071,10 +11073,10 @@ SWupdateidxmap(int32 swathID, int32 regionID, int32 indexin[], int32 indexout[],
                               indicies[1] = j;
                         }
                         if(indicies[0] == -1)
-                           if(startReg <= indexin[0])
+                           if(startReg <= l_indexin[0])
                               indicies[0] = 0;
                         if(indicies[1] == -1)
-                           if(stopReg > indexin[j])
+                           if(stopReg > l_indexin[j])
                               indicies[1] = j;
                      }
                      if(indicies[0] == -1)
@@ -11082,10 +11084,10 @@ SWupdateidxmap(int32 swathID, int32 regionID, int32 indexin[], int32 indexout[],
                         j = 0;
                         for(i=0; i<scene_cnt; i++)
                         {
-			  if( startReg >= indexin[j] && startReg <= indexin[j+1])
+			  if( startReg >= l_indexin[j] && startReg <= l_indexin[j+1])
 			    indicies[0] = j;
                            j = j + 2;
-                           if(indexin[j] == 0 || indexin[j+1] == 0)
+                           if(l_indexin[j] == 0 || l_indexin[j+1] == 0)
                               i = scene_cnt;
                         }
                      }
@@ -11094,25 +11096,25 @@ SWupdateidxmap(int32 swathID, int32 regionID, int32 indexin[], int32 indexout[],
                         j = 0;
                         for(i=0; i<scene_cnt; i++)
                         {
-		      if( stopReg >= indexin[j] && stopReg <= indexin[j+1])
+		      if( stopReg >= l_indexin[j] && stopReg <= l_indexin[j+1])
                               indicies[1] = j;
                            j = j + 2;
-                           if(indexin[j] == 0 || indexin[j+1] == 0)
+                           if(l_indexin[j] == 0 || l_indexin[j+1] == 0)
                               i = scene_cnt;
                         }
                      }
                      if(indicies[1] == -1)
                      {
-                        if(stopReg > indexin[j])
+                        if(stopReg > l_indexin[j])
                            indicies[1] = j;
                      }
                   }
                   if(indicies[0] == -1)
                   {
-                     if(startReg <= (indexin[0]+ indexoffset - detect_cnt) )
+                     if(startReg <= (l_indexin[0]+ indexoffset - detect_cnt) )
                         indicies[0] = 0;
                      if(indicies[1] == -1)
-                        if(stopReg > (indexin[j] + indexoffset - detect_cnt))
+                        if(stopReg > (l_indexin[j] + indexoffset - detect_cnt))
                            indicies[1] = j;
                   }
                }
@@ -11121,7 +11123,7 @@ SWupdateidxmap(int32 swathID, int32 regionID, int32 indexin[], int32 indexout[],
                   if(SWXRegion[regionID]->band8flag == 2 ||
                      SWXRegion[regionID]->band8flag == 3)
                   {
-                     if(stopReg < (indexin[0] + indexoffset - detect_cnt))
+                     if(stopReg < (l_indexin[0] + indexoffset - detect_cnt))
                      {
 		       /*status = SWfieldinfo(swathID, "scan_no", &rank, dims2, &nt, dimlist);
                         buffer = (uint16 *)calloc(dims2[0], sizeof(uint16));
@@ -11130,7 +11132,7 @@ SWupdateidxmap(int32 swathID, int32 regionID, int32 indexin[], int32 indexout[],
                         free(buffer);
                         startReg = startReg + (indexoffset - detect_cnt);
                         stopReg = stopReg + (indexoffset - 1); */
-                        if(stopReg >= (indexin[scene_cnt - 1] + indexoffset - detect_cnt))
+                        if(stopReg >= (l_indexin[scene_cnt - 1] + indexoffset - detect_cnt))
                         {
                            indicies[1] = scene_cnt - 1;
                         }
@@ -11139,17 +11141,17 @@ SWupdateidxmap(int32 swathID, int32 regionID, int32 indexin[], int32 indexout[],
                            j = 0;
                            for(i=0;i<scene_cnt;i++)
                            {
-		      if( stopReg >= (indexin[j] + indexoffset - detect_cnt ) && 
-			  stopReg <= (indexin[j+1] + indexoffset - detect_cnt ) )
+		      if( stopReg >= (l_indexin[j] + indexoffset - detect_cnt ) && 
+			  stopReg <= (l_indexin[j+1] + indexoffset - detect_cnt ) )
 			         indicies[1] = j;
 			      j = j + 2;
-                              if(indexin[j] == 0 || indexin[j+1] == 0)
+                              if(l_indexin[j] == 0 || l_indexin[j+1] == 0)
                                  i = scene_cnt;
                            }
                         }	
                      }
 
-                     if(startReg > (indexin[j - 1] + indexoffset - detect_cnt ))
+                     if(startReg > (l_indexin[j - 1] + indexoffset - detect_cnt ))
                      {
                         indicies[0] = -1;
                         indicies[1] = -1;
@@ -11163,22 +11165,22 @@ SWupdateidxmap(int32 swathID, int32 regionID, int32 indexin[], int32 indexout[],
                         j = 0;
                         for(i=0; i<scene_cnt; i++)
                         {
-		      if( startReg >= (indexin[j] + indexoffset - detect_cnt) && 
-			  startReg <= (indexin[j+1] + indexoffset - detect_cnt) )
+		      if( startReg >= (l_indexin[j] + indexoffset - detect_cnt) && 
+			  startReg <= (l_indexin[j+1] + indexoffset - detect_cnt) )
                               if(indicies[0] == -1)
                                  indicies[0] = j;
-		      if( stopReg >= (indexin[j] + indexoffset - detect_cnt ) && 
-			  stopReg <= (indexin[j+1] + indexoffset - detect_cnt ) )
+		      if( stopReg >= (l_indexin[j] + indexoffset - detect_cnt ) && 
+			  stopReg <= (l_indexin[j+1] + indexoffset - detect_cnt ) )
                               indicies[1] = j + 1;
                            j = j + 2;
-                           if(indexin[j] == 0 || indexin[j+1] == 0)
+                           if(l_indexin[j] == 0 || l_indexin[j+1] == 0)
                               i = scene_cnt;
                         }
                         if(indicies[0] == -1)
-                           if(startReg < (indexin[0] +  indexoffset - detect_cnt))
+                           if(startReg < (l_indexin[0] +  indexoffset - detect_cnt))
                               indicies[0] = 0;
                         if(indicies[1] == -1)
-                           if(stopReg > (indexin[j - 1] + indexoffset - detect_cnt))
+                           if(stopReg > (l_indexin[j - 1] + indexoffset - detect_cnt))
                               indicies[1] = j - 1;
                      }
                   }
@@ -11205,26 +11207,26 @@ SWupdateidxmap(int32 swathID, int32 regionID, int32 indexin[], int32 indexout[],
 	   }
         }
 	
-	if (indexout != NULL)
+	if (l_indexout != NULL)
 	{ 
            if(SWXRegion[regionID]->scanflag == 1)
            {
               nout = (indicies[1] - indicies[0] + 1);
               j = 0;
               if (nout == 1)
-                 indexout[0] = indexin[indicies[0]];
+                 l_indexout[0] = l_indexin[indicies[0]];
               for(i=0; i<nout;i++)
               {
-                 indexout[i] = indexin[indicies[0] + i];
+                 l_indexout[i] = l_indexin[indicies[0] + i];
               }
            }
            else
            {
-	      /* get new index values */
+	      /* get new l_index values */
               /* ==================== */
 	      for(i = startReg; i <= stopReg  ; i++)
 	      {
-	         indexout[i-startReg] = indexin[i];
+	         l_indexout[i-startReg] = l_indexin[i];
 	      }
 	      nout = (stopReg - startReg) + 1;
            }
@@ -11259,7 +11261,7 @@ SWupdateidxmap(int32 swathID, int32 regionID, int32 indexin[], int32 indexout[],
 |                                                                             |
 |  Return Value    Type     Units     Description                             |
 |  ============   ======  =========   =====================================   |
-|  status         intn                2 for indexed mapping, 1 for regular    |
+|  status         intn                2 for l_indexed mapping, 1 for regular    |
 |                                     mapping, 0 if the dimension is not      |
 |                                     and (-1) FAIL                           |
 |                                                                             |
@@ -11336,7 +11338,7 @@ SWgeomapinfo(int32 swathID, char *geodim)
 	    return(-1);
 	}
 	/* Search for mapping - GeoDim/DataDim (surrounded by quotes) */
-	sprintf(utlstrr, "%s%s%s", "\t\t\t\tGeoDimension=\"", geodim,
+	snprintf(utlstrr, UTLSTR_MAX_SIZE, "%s%s%s", "\t\t\t\tGeoDimension=\"", geodim,
 		"\"\n\t\t\t\tDataDimension=");
 	metaptrsr[0] = strstr(metaptrsr[0], utlstrr);
 	
@@ -11350,13 +11352,13 @@ SWgeomapinfo(int32 swathID, char *geodim)
 	    return(-1);
 	}
 	/* Search for mapping - GeoDim/DataDim (surrounded by quotes) */
-	sprintf(utlstri, "%s%s%s", "\t\t\t\tGeoDimension=\"", geodim,
+	snprintf(utlstri, UTLSTR_MAX_SIZE, "%s%s%s", "\t\t\t\tGeoDimension=\"", geodim,
 		"\"\n\t\t\t\tDataDimension=");
 	metaptrsi[0] = strstr(metaptrsi[0], utlstri);
 
 	/*
 	** If regular mapping found add 1 to status
-        ** If indexed mapping found add 2
+        ** If l_indexed mapping found add 2
         */
 	if (metaptrsr[0] < metaptrsr[1] && metaptrsr[0] != NULL)
 	{
@@ -11425,4 +11427,3 @@ SWsdid(int32 swathID, const char *fieldname, int32 *sdid)
 
     return (status);
 }
-
diff --git a/frmts/hdf4/hdf-eos/ease.h b/frmts/hdf4/hdf-eos/ease.h
index 8f28622..ab69e59 100644
--- a/frmts/hdf4/hdf-eos/ease.h
+++ b/frmts/hdf4/hdf-eos/ease.h
@@ -8,7 +8,7 @@
 #define BCEA_RE_M 6371228.0 /* Earth radius used in GCTP projection tools for
 			       Behrmann Cylindrical Equal Area projection */
 #define DEFAULT_BCEA_LTRUESCALE 30.00  /*Latitude of true scale in DMS */
-#define BCEA_COS_PHI1 cos(DEFAULT_BCEA_LTRUESCALE *3.141592653589793238 /180.0)
+#define BCEA_COS_PHI1 cos(DEFAULT_BCEA_LTRUESCALE * 3.141592653589793238 /180.0)
 #define PI      3.141592653589793238
 #define EASE_GRID_DEFAULT_UPLEFT_LON -180.0
 #define EASE_GRID_DEFAULT_UPLEFT_LAT  86.72 
diff --git a/frmts/hdf4/hdf-eos/gctp_wrap.c b/frmts/hdf4/hdf-eos/gctp_wrap.c
index 97d2d2e..ef2a0e7 100644
--- a/frmts/hdf4/hdf-eos/gctp_wrap.c
+++ b/frmts/hdf4/hdf-eos/gctp_wrap.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gctp_wrap.c 22751 2011-07-18 15:25:05Z winkey $
+ * $Id: gctp_wrap.c 32162 2015-12-13 14:16:21Z rouault $
  *
  * Project:  Hierarchical Data Format Release 4 (HDF4)
  * Purpose:  This is the wrapper code to use OGR Coordinate Transformation
@@ -46,6 +46,26 @@
 #define DEG (180.0 / PI)
 #define RAD (PI / 180.0)
 
+void for_init(
+int32 outsys,       /* output system code                               */
+int32 outzone,      /* output zone number                               */
+float64 *outparm,   /* output array of projection parameters    */
+int32 outdatum,     /* output datum                                     */
+char *fn27,         /* NAD 1927 parameter file                  */
+char *fn83,         /* NAD 1983 parameter file                  */
+int32 *iflg,        /* status flag                                      */
+int32 (*for_trans[])(double, double, double *, double *));
+
+void inv_init(
+int32 insys,            /* input system code                            */
+int32 inzone,           /* input zone number                            */
+float64 *inparm,        /* input array of projection parameters         */
+int32 indatum,      /* input datum code                         */
+char *fn27,                 /* NAD 1927 parameter file                  */
+char *fn83,                 /* NAD 1983 parameter file                  */
+int32 *iflg,            /* status flag                                  */
+int32 (*inv_trans[])(double, double, double*, double*));
+
 /***** static vars to store the transformers in *****/
 /***** this is not thread safe *****/
 
@@ -57,7 +77,7 @@ static OGRCoordinateTransformationH hForCT, hInvCT;
  gctp expects Longitude and Latitude values to be in radians
 ******************************************************************************/
 
-int32 osr_for(
+static int32 osr_for(
 double lon,			/* (I) Longitude 		*/
 double lat,			/* (I) Latitude 		*/
 double *x,			/* (O) X projection coordinate 	*/
@@ -86,8 +106,8 @@ int32 outsys,       /* output system code				*/
 int32 outzone,      /* output zone number				*/
 float64 *outparm,   /* output array of projection parameters	*/
 int32 outdatum,     /* output datum					*/
-char *fn27,         /* NAD 1927 parameter file			*/
-char *fn83,         /* NAD 1983 parameter file			*/
+CPL_UNUSED char *fn27,         /* NAD 1927 parameter file			*/
+CPL_UNUSED char *fn83,         /* NAD 1983 parameter file			*/
 int32 *iflg,        /* status flag					*/
 int32 (*for_trans[])(double, double, double *, double *))
                         /* forward function pointer			*/
@@ -114,7 +134,7 @@ int32 (*for_trans[])(double, double, double *, double *))
  gctp returns Longitude and Latitude values in radians
 ******************************************************************************/
 
-int32 osr_inv(
+static int32 osr_inv(
 double x,           /* (I) X projection coordinate 	*/
 double y,           /* (I) Y projection coordinate 	*/
 double *lon,        /* (O) Longitude 		*/
@@ -143,8 +163,8 @@ int32 insys,		/* input system code				*/
 int32 inzone,		/* input zone number				*/
 float64 *inparm,	/* input array of projection parameters         */
 int32 indatum,	    /* input datum code			        */
-char *fn27,		    /* NAD 1927 parameter file			*/
-char *fn83,		    /* NAD 1983 parameter file			*/
+CPL_UNUSED char *fn27,		    /* NAD 1927 parameter file			*/
+CPL_UNUSED char *fn83,		    /* NAD 1983 parameter file			*/
 int32 *iflg,		/* status flag					*/
 int32 (*inv_trans[])(double, double, double*, double*))	
                         /* inverse function pointer			*/
@@ -171,8 +191,9 @@ int32 (*inv_trans[])(double, double, double*, double*))
 
  note: gctp does not have a function that does this
 ******************************************************************************/
-
+#ifndef GDAL_COMPILATION
 void gctp_destroy(void) {
     OCTDestroyCoordinateTransformation ( hForCT );
     OCTDestroyCoordinateTransformation ( hInvCT );
 }
+#endif
diff --git a/frmts/hdf4/hdf4compat.h b/frmts/hdf4/hdf4compat.h
index 208832f..1ab5d16 100644
--- a/frmts/hdf4/hdf4compat.h
+++ b/frmts/hdf4/hdf4compat.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hdf4compat.h 15691 2008-11-07 09:54:58Z dron $
+ * $Id: hdf4compat.h 31777 2015-11-26 14:14:41Z rouault $
  *
  * Project:  Hierarchical Data Format Release 4 (HDF4)
  * Purpose:  Header file for HDF4 compatibility
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _HDF4COMPAT_H_INCLUDED_
-#define _HDF4COMPAT_H_INCLUDED_
+#ifndef HDF4COMPAT_H_INCLUDED_
+#define HDF4COMPAT_H_INCLUDED_
 
 /*  New versions of the HDF4 library define H4_xxx instead of xxx to
     avoid potential conflicts with NetCDF-3 library. The following
diff --git a/frmts/hdf4/hdf4dataset.cpp b/frmts/hdf4/hdf4dataset.cpp
index bb4156a..1652f78 100644
--- a/frmts/hdf4/hdf4dataset.cpp
+++ b/frmts/hdf4/hdf4dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hdf4dataset.cpp 29208 2015-05-19 13:54:59Z rouault $
+ * $Id: hdf4dataset.cpp 33722 2016-03-15 15:15:58Z dron $
  *
  * Project:  Hierarchical Data Format Release 4 (HDF4)
  * Purpose:  HDF4 Datasets. Open HDF4 file, fetch metadata and list of
@@ -30,31 +30,27 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_multiproc.h"
+#include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "gdal_priv.h"
+
 #include "hdf.h"
 #include "mfhdf.h"
 
 #include "HdfEosDef.h"
 
-#include "gdal_priv.h"
-#include "cpl_string.h"
-#include "cpl_multiproc.h"
-
-#include "hdf4compat.h"
 #include "hdf4dataset.h"
 
-CPL_CVSID("$Id: hdf4dataset.cpp 29208 2015-05-19 13:54:59Z rouault $");
+CPL_CVSID("$Id: hdf4dataset.cpp 33722 2016-03-15 15:15:58Z dron $");
 
-CPL_C_START
-void	GDALRegister_HDF4(void);
-CPL_C_END
-
-extern const char *pszGDALSignature;
+extern const char * const pszGDALSignature;
 
 CPLMutex *hHDF4Mutex = NULL;
 
 /************************************************************************/
 /* ==================================================================== */
-/*				HDF4Dataset				*/
+/*                              HDF4Dataset                             */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -62,18 +58,16 @@ CPLMutex *hHDF4Mutex = NULL;
 /*                           HDF4Dataset()                              */
 /************************************************************************/
 
-HDF4Dataset::HDF4Dataset()
-
-{
-    hSD = 0;
-    hGR = 0;
-    nImages = 0;
-    iSubdatasetType = H4ST_UNKNOWN;
-    pszSubdatasetType = NULL;
-    papszGlobalMetadata = NULL;
-    papszSubDatasets = NULL;
-    bIsHDFEOS = 0;
-}
+HDF4Dataset::HDF4Dataset() :
+    bIsHDFEOS(false),
+    hGR(0),
+    hSD(0),
+    nImages(0),
+    iSubdatasetType(H4ST_UNKNOWN),
+    pszSubdatasetType(NULL),
+    papszGlobalMetadata(NULL),
+    papszSubDatasets(NULL)
+{}
 
 /************************************************************************/
 /*                            ~HDF4Dataset()                            */
@@ -85,13 +79,13 @@ HDF4Dataset::~HDF4Dataset()
     CPLMutexHolderD(&hHDF4Mutex);
 
     if ( hSD )
-	SDend( hSD );
+        SDend( hSD );
     if ( hGR )
-	GRend( hGR );
+        GRend( hGR );
     if ( papszSubDatasets )
-	CSLDestroy( papszSubDatasets );
+        CSLDestroy( papszSubDatasets );
     if ( papszGlobalMetadata )
-	CSLDestroy( papszGlobalMetadata );
+        CSLDestroy( papszGlobalMetadata );
 }
 
 /************************************************************************/
@@ -112,10 +106,10 @@ char **HDF4Dataset::GetMetadataDomainList()
 char **HDF4Dataset::GetMetadata( const char *pszDomain )
 
 {
-    if( pszDomain != NULL && EQUALN( pszDomain, "SUBDATASETS", 11 ) )
+    if( pszDomain != NULL && STARTS_WITH_CI(pszDomain, "SUBDATASETS") )
         return papszSubDatasets;
-    else
-        return GDALDataset::GetMetadata( pszDomain );
+
+    return GDALDataset::GetMetadata( pszDomain );
 }
 
 /************************************************************************/
@@ -130,51 +124,62 @@ char **HDF4Dataset::GetMetadata( const char *pszDomain )
 char *SPrintArray( GDALDataType eDataType, const void *paDataArray,
                           int nValues, const char *pszDelimiter )
 {
-    char        *pszString, *pszField;
-    int         i, iFieldSize, iStringSize;
-
-    iFieldSize = 32 + strlen( pszDelimiter );
-    pszField = (char *)CPLMalloc( iFieldSize + 1 );
-    iStringSize = nValues * iFieldSize + 1;
-    pszString = (char *)CPLMalloc( iStringSize );
+    const int iFieldSize = 32 + static_cast<int>(strlen( pszDelimiter ) );
+    char *pszField = static_cast<char *>( CPLMalloc( iFieldSize + 1 ) );
+    const int iStringSize = nValues * iFieldSize + 1;
+    char *pszString = static_cast<char *>( CPLMalloc( iStringSize ) );
     memset( pszString, 0, iStringSize );
-    for ( i = 0; i < nValues; i++ )
+    for( int i = 0; i < nValues; i++ )
     {
         switch ( eDataType )
         {
             case GDT_Byte:
-                sprintf( pszField, "%d%s", ((GByte *)paDataArray)[i],
-                     (i < nValues - 1)?pszDelimiter:"" );
+                snprintf( pszField, iFieldSize + 1, "%d%s",
+                         reinterpret_cast<GByte *>(
+                             const_cast<void *>( paDataArray ) )[i],
+                         (i < nValues - 1)?pszDelimiter:"" );
                 break;
             case GDT_UInt16:
-                sprintf( pszField, "%u%s", ((GUInt16 *)paDataArray)[i],
-                     (i < nValues - 1)?pszDelimiter:"" );
+                snprintf( pszField, iFieldSize + 1, "%u%s",
+                         reinterpret_cast<GUInt16 *>(
+                             const_cast<void *>(  paDataArray ) )[i],
+                         (i < nValues - 1)?pszDelimiter:"" );
                 break;
             case GDT_Int16:
             default:
-                sprintf( pszField, "%d%s", ((GInt16 *)paDataArray)[i],
-                     (i < nValues - 1)?pszDelimiter:"" );
+                snprintf( pszField, iFieldSize + 1, "%d%s",
+                         reinterpret_cast<GInt16 *>(
+                             const_cast<void *>(  paDataArray ) )[i],
+                         (i < nValues - 1)?pszDelimiter:"" );
                 break;
             case GDT_UInt32:
-                sprintf( pszField, "%u%s", ((GUInt32 *)paDataArray)[i],
+                snprintf( pszField, iFieldSize + 1, "%u%s",
+                         reinterpret_cast<GUInt32 *>(
+                             const_cast<void *>(  paDataArray ) )[i],
                      (i < nValues - 1)?pszDelimiter:"" );
                 break;
             case GDT_Int32:
-                sprintf( pszField, "%d%s", ((GInt32 *)paDataArray)[i],
-                     (i < nValues - 1)?pszDelimiter:"" );
+                snprintf( pszField, iFieldSize + 1, "%d%s",
+                         reinterpret_cast<GInt32 *>(
+                                const_cast<void *>(  paDataArray ) )[i],
+                         (i < nValues - 1)?pszDelimiter:"" );
                 break;
             case GDT_Float32:
-                CPLsprintf( pszField, "%.10g%s", ((float *)paDataArray)[i],
-                     (i < nValues - 1)?pszDelimiter:"" );
+                CPLsnprintf( pszField, iFieldSize + 1, "%.10g%s",
+                             reinterpret_cast<float *>(
+                                 const_cast<void *>(  paDataArray ) )[i],
+                             (i < nValues - 1)?pszDelimiter:"" );
                 break;
             case GDT_Float64:
-                CPLsprintf( pszField, "%.15g%s", ((double *)paDataArray)[i],
-                     (i < nValues - 1)?pszDelimiter:"" );
+                CPLsnprintf( pszField, iFieldSize + 1, "%.15g%s",
+                             reinterpret_cast<double *>(
+                                 const_cast<void *>(  paDataArray ) )[i],
+                             (i < nValues - 1)?pszDelimiter:"" );
                 break;
         }
         strcat( pszString, pszField );
     }
-    
+
     CPLFree( pszField );
     return pszString;
 }
@@ -213,7 +218,7 @@ GDALDataType HDF4Dataset::GetDataType( int32 iNumType )
 }
 
 /************************************************************************/
-/*		Return the human readable name of data type		*/
+/*              Return the human readable name of data type             */
 /************************************************************************/
 
 const char *HDF4Dataset::GetDataTypeName( int32 iNumType )
@@ -244,13 +249,18 @@ const char *HDF4Dataset::GetDataTypeName( int32 iNumType )
 	    return "32-bit floating-point";
         case DFNT_FLOAT64:
 	    return "64-bit floating-point";
-	default:
-	    return "unknown type";
+        default:
+        {
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Unknown type %d\n", static_cast<int>(iNumType) );
+
+            return "unknown type";
+        }
     }
 }
 
 /************************************************************************/
-/*  Return the size of data type in bytes	                        */
+/*  Return the size of data type in bytes                               */
 /************************************************************************/
 
 int HDF4Dataset::GetDataTypeSize( int32 iNumType )
@@ -273,8 +283,12 @@ int HDF4Dataset::GetDataTypeSize( int32 iNumType )
         case DFNT_UINT64:
         case DFNT_FLOAT64:
 	    return 8;
-	default:
-	    return 0;
+        default:
+        {
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Unknown type %d\n", static_cast<int>(iNumType) );
+            return 0;
+        }
     }
 }
 
@@ -287,27 +301,42 @@ double HDF4Dataset::AnyTypeToDouble( int32 iNumType, void *pData )
     switch ( iNumType )
     {
         case DFNT_INT8:
-            return (double)*(char *)pData;
+            return *reinterpret_cast<double *>(
+                reinterpret_cast<char *>( pData ) );
         case DFNT_UINT8:
-            return (double)*(unsigned char *)pData;
+            return *reinterpret_cast<double *>(
+                reinterpret_cast<unsigned char *>( pData ) );
         case DFNT_INT16:
-            return (double)*(short *)pData;
+            return *reinterpret_cast<double *>(
+                reinterpret_cast<short *>( pData ) );
         case DFNT_UINT16:
-            return (double)*(unsigned short *)pData;
+            return *reinterpret_cast<double *>(
+                reinterpret_cast<unsigned short *>( pData ) );
         case DFNT_INT32:
-            return (double)*(int *)pData;
+            return *reinterpret_cast<double *>(
+                reinterpret_cast<int *>( pData ) );
         case DFNT_UINT32:
-            return (double)*(unsigned int *)pData;
+            return *reinterpret_cast<double *>(
+                reinterpret_cast<unsigned int *>( pData ) );
         case DFNT_INT64:
-            return (double)*(char *)pData; // highly suspicious ! Should be GIntBig. But cannot verify
+            // Highly suspicious! Should be GIntBig. But cannot verify.
+            return *reinterpret_cast<double *>(
+                reinterpret_cast<char *>( pData ) );
         case DFNT_UINT64:
-            return (double)*(GIntBig *)pData;
+            return *reinterpret_cast<double *>(
+                reinterpret_cast<GIntBig *>( pData ) );
         case DFNT_FLOAT32:
-            return (double)*(float *)pData;
+            return *reinterpret_cast<double *>(
+                reinterpret_cast<float *>( pData ) );
         case DFNT_FLOAT64:
-            return (double)*(double *)pData;
+            return *reinterpret_cast<double *>(
+                reinterpret_cast<double *>( pData ) );
         default:
+        {
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Unknown type %d\n", static_cast<int>(iNumType) );
             return 0.0;
+        }
     }
 }
 
@@ -315,28 +344,27 @@ double HDF4Dataset::AnyTypeToDouble( int32 iNumType, void *pData )
 /*         Tokenize HDF-EOS attributes.                                 */
 /************************************************************************/
 
-char **HDF4Dataset::HDF4EOSTokenizeAttrs( const char * pszString ) 
+char **HDF4Dataset::HDF4EOSTokenizeAttrs( const char * pszString )
 
 {
-    const char  *pszDelimiters = " \t\n\r";
+    const char  * const pszDelimiters = " \t\n\r";
     char        **papszRetList = NULL;
-    char        *pszToken;
-    int         nTokenMax, nTokenLen;
 
-    pszToken = (char *) CPLCalloc( 10, 1 );
-    nTokenMax = 10;
-    
+    char *pszToken = static_cast<char *>( CPLCalloc( 10, 1 ) );
+    int nTokenMax = 10;
+
     while( pszString != NULL && *pszString != '\0' )
     {
-        int     bInString = FALSE, bInBracket = FALSE;
+        bool bInString = false;
+        bool bInBracket = false;
+
+        int nTokenLen = 0;
 
-        nTokenLen = 0;
-        
-        // Try to find the next delimeter, marking end of token
+        // Try to find the next delimiter, marking end of token.
         for( ; *pszString != '\0'; pszString++ )
         {
 
-            // End if this is a delimeter skip it and break.
+            // End if this is a delimiter skip it and break.
             if ( !bInBracket && !bInString
                  && strchr(pszDelimiters, *pszString) != NULL )
             {
@@ -346,41 +374,34 @@ char **HDF4Dataset::HDF4EOSTokenizeAttrs( const char * pszString )
 
             // Sometimes in bracketed tokens we may found a sort of
             // paragraph formatting. We will remove unneeded spaces and new
-            // lines. 
+            // lines.
             if ( bInBracket )
                 if ( strchr("\r\n", *pszString) != NULL
                      || ( *pszString == ' '
                           && strchr(" \r\n", *(pszString - 1)) != NULL ) )
                 continue;
-            
+
             if ( *pszString == '"' )
             {
-                if ( bInString )
-                {
-                    bInString = FALSE;
-                    continue;
-                }
-                else
-                {
-                    bInString = TRUE;
-                    continue;
-                }
+                bInString = !bInString;
+                continue;
             }
             else if ( *pszString == '(' )
-	    {
+            {
                 bInBracket = TRUE;
-		continue;
-	    }
+                continue;
+            }
 	    else if ( *pszString == ')' )
-	    {
+            {
 		bInBracket = FALSE;
-		continue;
-	    }
+                continue;
+            }
 
 	    if( nTokenLen >= nTokenMax - 2 )
             {
                 nTokenMax = nTokenMax * 2 + 10;
-                pszToken = (char *) CPLRealloc( pszToken, nTokenMax );
+                pszToken = static_cast<char *>(
+                    CPLRealloc( pszToken, nTokenMax ) );
             }
 
             pszToken[nTokenLen] = *pszString;
@@ -395,7 +416,7 @@ char **HDF4Dataset::HDF4EOSTokenizeAttrs( const char * pszString )
         }
 
         // If the last token is an empty token, then we have to catch
-        // it now, otherwise we won't reenter the loop and it will be lost. 
+        // it now, otherwise we won't reenter the loop and it will be lost.
         if ( *pszString == '\0' && strchr(pszDelimiters, *(pszString-1)) )
         {
             papszRetList = CSLAddString( papszRetList, "" );
@@ -403,7 +424,7 @@ char **HDF4Dataset::HDF4EOSTokenizeAttrs( const char * pszString )
     }
 
     if( papszRetList == NULL )
-        papszRetList = (char **) CPLCalloc( sizeof(char *), 1 );
+        papszRetList = static_cast<char **>( CPLCalloc( sizeof(char *), 1 ) );
 
     CPLFree( pszToken );
 
@@ -421,35 +442,34 @@ char **HDF4Dataset::HDF4EOSGetObject( char **papszAttrList,
                                       char **ppszAttrClass,
                                       char **ppszAttrValue )
 {
-    int	    iCount, i, j;
     *ppszAttrName = NULL;
     *ppszAttrClass = NULL;
     *ppszAttrValue = NULL;
 
-    iCount = CSLCount( papszAttrList );
-    for ( i = 0; i < iCount - 2; i++ )
+    const int iCount = CSLCount( papszAttrList );
+    for( int i = 0; i < iCount - 2; i++ )
     {
-	if ( EQUAL( papszAttrList[i], "OBJECT" ) )
-	{
-	    i += 2;
-	    for ( j = 1; i + j < iCount - 2; j++ )
-	    {
-	        if ( EQUAL( papszAttrList[i + j], "END_OBJECT" ) ||
-		     EQUAL( papszAttrList[i + j], "OBJECT" ) )
-	            return &papszAttrList[i + j];
-	        else if ( EQUAL( papszAttrList[i + j], "CLASS" ) )
-	        {
-		    *ppszAttrClass = papszAttrList[i + j + 2];
+        if ( EQUAL( papszAttrList[i], "OBJECT" ) )
+        {
+            i += 2;
+            for ( int j = 1; i + j < iCount - 2; j++ )
+            {
+                if ( EQUAL( papszAttrList[i + j], "END_OBJECT" ) ||
+                     EQUAL( papszAttrList[i + j], "OBJECT" ) )
+                    return &papszAttrList[i + j];
+                else if ( EQUAL( papszAttrList[i + j], "CLASS" ) )
+                {
+                    *ppszAttrClass = papszAttrList[i + j + 2];
                     continue;
-	        }
-	        else if ( EQUAL( papszAttrList[i + j], "VALUE" ) )
-	        {
-		    *ppszAttrName = papszAttrList[i];
-	            *ppszAttrValue = papszAttrList[i + j + 2];
+                }
+                else if ( EQUAL( papszAttrList[i + j], "VALUE" ) )
+                {
+                    *ppszAttrName = papszAttrList[i];
+                    *ppszAttrValue = papszAttrList[i + j + 2];
                     continue;
-	        }
-	    }
-	}
+                }
+            }
+        }
     }
 
     return NULL;
@@ -462,30 +482,29 @@ char **HDF4Dataset::HDF4EOSGetObject( char **papszAttrList,
 char** HDF4Dataset::TranslateHDF4EOSAttributes( int32 iHandle,
     int32 iAttribute, int32 nValues, char **papszMetadata )
 {
-    char	*pszData;
-    
-    pszData = (char *)CPLMalloc( (nValues + 1) * sizeof(char) );
+    char *pszData = static_cast<char *>(
+        CPLMalloc( (nValues + 1) * sizeof(char) ) );
     pszData[nValues] = '\0';
     SDreadattr( iHandle, iAttribute, pszData );
     // HDF4-EOS attributes has followed structure:
-    // 
+    //
     // GROUP = <name>
     //   GROUPTYPE = <name>
     //
     //   GROUP = <name>
-    //   
+    //
     //     OBJECT = <name>
     //       CLASS = <string>
     //       NUM_VAL = <number>
     //       VALUE = <string> or <number>
     //     END_OBJECT = <name>
-    //     
+    //
     //     .......
     //     .......
     //     .......
-    //     
+    //
     //   END_GROUP = <name>
-    //   
+    //
     // .......
     // .......
     // .......
@@ -520,40 +539,41 @@ char** HDF4Dataset::TranslateHDF4EOSAttributes( int32 iHandle,
     //
     //  PARAMETERNAME.9 = "Spectral IR Surf Bidirect Reflectivity"
 
-    char *pszAttrName, *pszAttrClass, *pszAttrValue;
+    char *pszAttrName = NULL;
+    char *pszAttrClass = NULL;
+    char *pszAttrValue = NULL;
     char *pszAddAttrName = NULL;
-    char **papszAttrList, **papszAttrs;
-    
-    papszAttrList = HDF4EOSTokenizeAttrs( pszData );
-    papszAttrs = papszAttrList;
+
+    char ** const papszAttrList = HDF4EOSTokenizeAttrs( pszData );
+    char ** papszAttrs = papszAttrList;
     while ( papszAttrs )
     {
 	papszAttrs = HDF4EOSGetObject( papszAttrs, &pszAttrName,
                                        &pszAttrClass, &pszAttrValue );
 	if ( pszAttrName && pszAttrValue )
-	{
+        {
 	    // Now we should recognize special type of HDF EOS metastructures:
 	    // ADDITIONALATTRIBUTENAME = <name>
 	    // PARAMETERVALUE = <value>
 	    if ( EQUAL( pszAttrName, "ADDITIONALATTRIBUTENAME" ) )
 		pszAddAttrName = pszAttrValue;
 	    else if ( pszAddAttrName && EQUAL( pszAttrName, "PARAMETERVALUE" ) )
-	    {
+            {
 		papszMetadata =
 		    CSLAddNameValue( papszMetadata, pszAddAttrName, pszAttrValue );
 		pszAddAttrName = NULL;
-	    }
-	    else
-	    {
+            }
+            else
+            {
                 // Add class suffix to the key name if applicable
 		papszMetadata = CSLAddNameValue( papszMetadata,
                     pszAttrClass ?
                     CPLSPrintf("%s.%s", pszAttrName, pszAttrClass) : pszAttrName,
                     pszAttrValue );
-	    }
-	}
+            }
+        }
     }
-    
+
     CSLDestroy( papszAttrList );
     CPLFree( pszData );
 
@@ -568,12 +588,11 @@ char** HDF4Dataset::TranslateHDF4Attributes( int32 iHandle,
     int32 iAttribute, char *pszAttrName, int32 iNumType, int32 nValues,
     char **papszMetadata )
 {
-    void	*pData = NULL;
-    char	*pszTemp = NULL;
-    
+
 /* -------------------------------------------------------------------- */
 /*     Allocate a buffer to hold the attribute data.                    */
 /* -------------------------------------------------------------------- */
+    void *pData = NULL;
     if ( iNumType == DFNT_CHAR8 || iNumType == DFNT_UCHAR8 )
         pData = CPLMalloc( (nValues + 1) * GetDataTypeSize(iNumType) );
     else
@@ -585,20 +604,20 @@ char** HDF4Dataset::TranslateHDF4Attributes( int32 iHandle,
     SDreadattr( iHandle, iAttribute, pData );
     if ( iNumType == DFNT_CHAR8 || iNumType == DFNT_UCHAR8 )
     {
-        ((char *)pData)[nValues] = '\0';
-        papszMetadata = CSLAddNameValue( papszMetadata, pszAttrName, 
-                                         (const char *) pData );
+        reinterpret_cast<char *>( pData )[nValues] = '\0';
+        papszMetadata = CSLAddNameValue(
+            papszMetadata, pszAttrName,
+            const_cast<const char *>( reinterpret_cast<char *>( pData )) );
     }
     else
     {
+        char *pszTemp = NULL;
         pszTemp = SPrintArray( GetDataType(iNumType), pData, nValues, ", " );
         papszMetadata = CSLAddNameValue( papszMetadata, pszAttrName, pszTemp );
-        if ( pszTemp )
-	    CPLFree( pszTemp );
+        CPLFree( pszTemp );
     }
-    
-    if ( pData )
-	CPLFree( pData );
+
+    CPLFree( pData );
 
     return papszMetadata;
 }
@@ -609,46 +628,50 @@ char** HDF4Dataset::TranslateHDF4Attributes( int32 iHandle,
 
 CPLErr HDF4Dataset::ReadGlobalAttributes( int32 iHandler )
 {
-    int32	iAttribute, nValues, iNumType, nDatasets, nAttributes;
-    char	szAttrName[H4_MAX_NC_NAME];
-
 /* -------------------------------------------------------------------- */
 /*     Obtain number of SDSs and global attributes in input file.       */
 /* -------------------------------------------------------------------- */
+    int32 nDatasets, nAttributes;
     if ( SDfileinfo( iHandler, &nDatasets, &nAttributes ) != 0 )
-	return CE_Failure;
+        return CE_Failure;
+
+    char szAttrName[H4_MAX_NC_NAME];  // TODO: Get this off the stack.
 
     // Loop through the all attributes
-    for ( iAttribute = 0; iAttribute < nAttributes; iAttribute++ )
+    for( int32 iAttribute = 0; iAttribute < nAttributes; iAttribute++ )
     {
+        int32 iNumType = 0;
+        int32 nValues = 0;
+
         // Get information about the attribute. Note that the first
         // parameter is an SD interface identifier.
         SDattrinfo( iHandler, iAttribute, szAttrName, &iNumType, &nValues );
 
-        if ( EQUALN( szAttrName, "coremetadata", 12 )    ||
-	     EQUALN( szAttrName, "archivemetadata.", 16 ) ||
-	     EQUALN( szAttrName, "productmetadata.", 16 ) ||
-             EQUALN( szAttrName, "badpixelinformation", 19 ) ||
-	     EQUALN( szAttrName, "product_summary", 15 ) ||
-	     EQUALN( szAttrName, "dem_specific", 12 ) ||
-	     EQUALN( szAttrName, "bts_specific", 12 ) ||
-	     EQUALN( szAttrName, "etse_specific", 13 ) ||
-	     EQUALN( szAttrName, "dst_specific", 12 ) ||
-	     EQUALN( szAttrName, "acv_specific", 12 ) ||
-	     EQUALN( szAttrName, "act_specific", 12 ) ||
-	     EQUALN( szAttrName, "etst_specific", 13 ) ||
-	     EQUALN( szAttrName, "level_1_carryover", 17 ) )
+        if ( STARTS_WITH_CI(szAttrName, "coremetadata")    ||
+	     STARTS_WITH_CI(szAttrName, "archivemetadata.") ||
+	     STARTS_WITH_CI(szAttrName, "productmetadata.") ||
+             STARTS_WITH_CI(szAttrName, "badpixelinformation") ||
+	     STARTS_WITH_CI(szAttrName, "product_summary") ||
+	     STARTS_WITH_CI(szAttrName, "dem_specific") ||
+	     STARTS_WITH_CI(szAttrName, "bts_specific") ||
+	     STARTS_WITH_CI(szAttrName, "etse_specific") ||
+	     STARTS_WITH_CI(szAttrName, "dst_specific") ||
+	     STARTS_WITH_CI(szAttrName, "acv_specific") ||
+	     STARTS_WITH_CI(szAttrName, "act_specific") ||
+	     STARTS_WITH_CI(szAttrName, "etst_specific") ||
+	     STARTS_WITH_CI(szAttrName, "level_1_carryover") )
         {
-            bIsHDFEOS = 1;
-            papszGlobalMetadata = TranslateHDF4EOSAttributes( iHandler,
-		iAttribute, nValues, papszGlobalMetadata );
+            bIsHDFEOS = true;
+            papszGlobalMetadata
+                = TranslateHDF4EOSAttributes(
+                    iHandler, iAttribute, nValues, papszGlobalMetadata );
         }
 
         // Skip "StructMetadata.N" records. We will fetch information
         // from them using HDF-EOS API
-	else if ( EQUALN( szAttrName, "structmetadata.", 15 ) )
+	else if ( STARTS_WITH_CI(szAttrName, "structmetadata.") )
         {
-            bIsHDFEOS = 1;
+            bIsHDFEOS = true;
             continue;
         }
 
@@ -685,31 +708,29 @@ int HDF4Dataset::Identify( GDALOpenInfo * poOpenInfo )
 GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    int32	i;
-
     if( !Identify( poOpenInfo ) )
         return NULL;
-    
+
     CPLMutexHolderD(&hHDF4Mutex);
 
 /* -------------------------------------------------------------------- */
 /*      Try opening the dataset.                                        */
 /* -------------------------------------------------------------------- */
-    int32	hHDF4;
-    
+
     // Attempt to increase maximum number of opened HDF files
 #ifdef HDF4_HAS_MAXOPENFILES
-    intn        nCurrMax, nSysLimit;
+    intn nCurrMax = 0;
+    intn nSysLimit = 0;
 
     if ( SDget_maxopenfiles(&nCurrMax, &nSysLimit) >= 0
          && nCurrMax < nSysLimit )
     {
-        intn res = SDreset_maxopenfiles( nSysLimit );
+        /*intn res = */SDreset_maxopenfiles( nSysLimit );
     }
 #endif /* HDF4_HAS_MAXOPENFILES */
 
-    hHDF4 = Hopen(poOpenInfo->pszFilename, DFACC_READ, 0);
-    
+    int32 hHDF4 = Hopen(poOpenInfo->pszFilename, DFACC_READ, 0);
+
     if( hHDF4 <= 0 )
         return( NULL );
 
@@ -718,10 +739,9 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    HDF4Dataset *poDS;
-
-    CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
-    poDS = new HDF4Dataset();
+    // Release mutex otherwise we will deadlock with GDALDataset own mutex.
+    CPLReleaseMutex(hHDF4Mutex);
+    HDF4Dataset *poDS = new HDF4Dataset();
     CPLAcquireMutex(hHDF4Mutex, 1000.0);
 
     if( poOpenInfo->fpL != NULL )
@@ -729,7 +749,7 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
         VSIFCloseL(poOpenInfo->fpL);
         poOpenInfo->fpL = NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*          Open HDF SDS Interface.                                     */
 /* -------------------------------------------------------------------- */
@@ -737,7 +757,8 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
 
     if ( poDS->hSD == -1 )
     {
-        CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+      // Release mutex otherwise we will deadlock with GDALDataset own mutex.
+        CPLReleaseMutex(hHDF4Mutex);
         delete poDS;
         CPLAcquireMutex(hHDF4Mutex, 1000.0);
         CPLError( CE_Failure, CPLE_OpenFailed,
@@ -745,13 +766,14 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
                   poOpenInfo->pszFilename );
         return NULL;
     }
-   
+
 /* -------------------------------------------------------------------- */
-/*		Now read Global Attributes.				*/
+/*              Now read Global Attributes.                             */
 /* -------------------------------------------------------------------- */
     if ( poDS->ReadGlobalAttributes( poDS->hSD ) != CE_None )
     {
-        CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+        // Release mutex otherwise we will deadlock with GDALDataset own mutex.
+        CPLReleaseMutex(hHDF4Mutex);
         delete poDS;
         CPLAcquireMutex(hHDF4Mutex, 1000.0);
         CPLError( CE_Failure, CPLE_OpenFailed,
@@ -763,33 +785,32 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->SetMetadata( poDS->papszGlobalMetadata, "" );
 
 /* -------------------------------------------------------------------- */
-/*		Determine type of file we read.				*/
+/*              Determine type of file we read.                         */
 /* -------------------------------------------------------------------- */
-    const char	*pszValue;
-    
-    if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata,
-                                       "Signature"))
-	 && EQUAL( pszValue, pszGDALSignature ) )
+    const char *pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata,
+                                             "Signature");
+
+    if ( pszValue != NULL && EQUAL( pszValue, pszGDALSignature ) )
     {
 	poDS->iSubdatasetType = H4ST_GDAL;
 	poDS->pszSubdatasetType = "GDAL_HDF4";
     }
 
-    else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata, "Title"))
+    else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata, "Title")) != NULL
 	 && EQUAL( pszValue, "SeaWiFS Level-1A Data" ) )
     {
 	poDS->iSubdatasetType = H4ST_SEAWIFS_L1A;
 	poDS->pszSubdatasetType = "SEAWIFS_L1A";
     }
 
-    else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata, "Title"))
+    else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata, "Title")) != NULL
 	&& EQUAL( pszValue, "SeaWiFS Level-2 Data" ) )
     {
 	poDS->iSubdatasetType = H4ST_SEAWIFS_L2;
 	poDS->pszSubdatasetType = "SEAWIFS_L2";
     }
 
-    else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata, "Title"))
+    else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata, "Title")) != NULL
 	&& EQUAL( pszValue, "SeaWiFS Level-3 Standard Mapped Image" ) )
     {
 	poDS->iSubdatasetType = H4ST_SEAWIFS_L3;
@@ -797,8 +818,8 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
     else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata,
-                                            "L1 File Generated By"))
-	&& EQUALN( pszValue, "HYP version ", 12 ) )
+                                            "L1 File Generated By")) != NULL
+	&& STARTS_WITH_CI(pszValue, "HYP version ") )
     {
 	poDS->iSubdatasetType = H4ST_HYPERION_L1;
 	poDS->pszSubdatasetType = "HYPERION_L1";
@@ -811,50 +832,49 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
 /* -------------------------------------------------------------------- */
-/*  If we have HDF-EOS dataset, process it here.	                */
+/*  If we have HDF-EOS dataset, process it here.                        */
 /* -------------------------------------------------------------------- */
-    char	szName[VSNAMELENMAX + 1], szTemp[8192];
-    char	*pszString;
-    const char  *pszName;
-    int		nCount;
-    int32	aiDimSizes[H4_MAX_VAR_DIMS];
-    int32	iRank, iNumType, nAttrs;
-    bool        bIsHDF = true;
-    
+    int32 aiDimSizes[H4_MAX_VAR_DIMS];  // TODO: Get this off of the stack.
+    int32 iRank = 0;
+    int32 iNumType = 0;
+    int32 nAttrs = 0;
+    bool bIsHDF = true;
+
     // Sometimes "HDFEOSVersion" attribute is not defined and we will
     // determine HDF-EOS datasets using other records
     // (see ReadGlobalAttributes() method).
     if ( poDS->bIsHDFEOS
          || CSLFetchNameValue(poDS->papszGlobalMetadata, "HDFEOSVersion") )
     {
-        bIsHDF  = false;
-
-        int32   nSubDatasets, nStrBufSize;
-
 /* -------------------------------------------------------------------- */
 /*  Process swath layers.                                               */
 /* -------------------------------------------------------------------- */
         hHDF4 = SWopen( poOpenInfo->pszFilename, DFACC_READ );
         if( hHDF4 < 0)
         {
-            CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+            // Release mutex otherwise we will deadlock with GDALDataset own
+            // mutex.
+            CPLReleaseMutex(hHDF4Mutex);
             delete poDS;
             CPLAcquireMutex(hHDF4Mutex, 1000.0);
             CPLError( CE_Failure, CPLE_OpenFailed,
                       "Failed to open HDF-EOS file \"%s\" for swath reading.\n",
                       poOpenInfo->pszFilename );
             return NULL;
-        } 
-        nSubDatasets = SWinqswath(poOpenInfo->pszFilename, NULL, &nStrBufSize);
+        }
+        int32 nStrBufSize;
+        int32 nSubDatasets
+            = SWinqswath(poOpenInfo->pszFilename, NULL, &nStrBufSize);
+
 #ifdef DEBUG
-        CPLDebug( "HDF4", "Number of HDF-EOS swaths: %d", (int)nSubDatasets );
+        CPLDebug( "HDF4", "Number of HDF-EOS swaths: %d",
+                  static_cast<int>( nSubDatasets ) );
 #endif
+
         if ( nSubDatasets > 0 && nStrBufSize > 0 )
         {
-            char    *pszSwathList;
-            char    **papszSwaths;
-
-            pszSwathList = (char *)CPLMalloc( nStrBufSize + 1 );
+            char *pszSwathList
+                = static_cast<char *>( CPLMalloc( nStrBufSize + 1 ) );
             SWinqswath( poOpenInfo->pszFilename, pszSwathList, &nStrBufSize );
             pszSwathList[nStrBufSize] = '\0';
 
@@ -862,55 +882,58 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
             CPLDebug( "HDF4", "List of HDF-EOS swaths: %s", pszSwathList );
 #endif
 
-            papszSwaths =
+            char **papszSwaths =
                 CSLTokenizeString2( pszSwathList, ",", CSLT_HONOURSTRINGS );
             CPLFree( pszSwathList );
 
             if ( nSubDatasets != CSLCount(papszSwaths) )
             {
                 CSLDestroy( papszSwaths );
-                CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+                // Release mutex otherwise we will deadlock with GDALDataset own
+                // mutex.
+                CPLReleaseMutex(hHDF4Mutex);
                 delete poDS;
                 CPLAcquireMutex(hHDF4Mutex, 1000.0);
-                CPLDebug( "HDF4", "Can not parse list of HDF-EOS grids." );
+                CPLDebug( "HDF4", "Cannot parse list of HDF-EOS grids." );
                 return NULL;
             }
 
-            for ( i = 0; i < nSubDatasets; i++)
+            for( int32 i = 0; i < nSubDatasets; i++)
             {
-                char    *pszFieldList;
-                char    **papszFields;
-                int32   *paiRank, *paiNumType;
-                int32   hSW, nFields, j;
-
-                hSW = SWattach( hHDF4, papszSwaths[i] );
+                const int32 hSW = SWattach( hHDF4, papszSwaths[i] );
 
-                nFields = SWnentries( hSW, HDFE_NENTDFLD, &nStrBufSize );
-                pszFieldList = (char *)CPLMalloc( nStrBufSize + 1 );
-                paiRank = (int32 *)CPLMalloc( nFields * sizeof(int32) );
-                paiNumType = (int32 *)CPLMalloc( nFields * sizeof(int32) );
+                const int32 nFields
+                    = SWnentries( hSW, HDFE_NENTDFLD, &nStrBufSize );
+                char *pszFieldList = static_cast<char *>(
+                    CPLMalloc( nStrBufSize + 1 ) );
+                int32 *paiRank = static_cast<int32 *>(
+                    CPLMalloc( nFields * sizeof(int32) ) );
+                int32 *paiNumType = static_cast<int32 *>(
+                    CPLMalloc( nFields * sizeof(int32) ) );
 
                 SWinqdatafields( hSW, pszFieldList, paiRank, paiNumType );
 
 #ifdef DEBUG
                 {
-                    char *pszTmp =
+                    char * const pszTmp =
                         SPrintArray( GDT_UInt32, paiRank, nFields, "," );
 
                     CPLDebug( "HDF4", "Number of data fields in swath %d: %d",
-                              (int) i, (int) nFields );
+                              static_cast<int>( i ),
+                              static_cast<int>( nFields ) );
                     CPLDebug( "HDF4", "List of data fields in swath %d: %s",
-                              (int) i, pszFieldList );
+                              static_cast<int>( i ), pszFieldList );
                     CPLDebug( "HDF4", "Data fields ranks: %s", pszTmp );
 
                     CPLFree( pszTmp );
                 }
 #endif
 
-                papszFields = CSLTokenizeString2( pszFieldList, ",",
-                                                  CSLT_HONOURSTRINGS );
-                
-                for ( j = 0; j < nFields; j++ )
+                char **papszFields = CSLTokenizeString2( pszFieldList, ",",
+                                                         CSLT_HONOURSTRINGS );
+
+                char szTemp[256] = {'\0'};  // TODO: Get this off the stack.
+                for( int32 j = 0; j < nFields; j++ )
                 {
                     SWfieldinfo( hSW, papszFields[j], &iRank, aiDimSizes,
                                  &iNumType, NULL );
@@ -918,26 +941,28 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
                     if ( iRank < 2 )
                         continue;
 
-	            // Add field to the list of GDAL subdatasets
-                    nCount = CSLCount( poDS->papszSubDatasets ) / 2;
-                    sprintf( szTemp, "SUBDATASET_%d_NAME", nCount + 1 );
-	            // We will use the field index as an identificator.
+                    // Add field to the list of GDAL subdatasets
+                    const int nCount = CSLCount( poDS->papszSubDatasets ) / 2;
+                    snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_NAME", nCount + 1 );
+                    // We will use the field index as an identificator.
                     poDS->papszSubDatasets =
                         CSLSetNameValue( poDS->papszSubDatasets, szTemp,
                                 CPLSPrintf("HDF4_EOS:EOS_SWATH:\"%s\":%s:%s",
                                            poOpenInfo->pszFilename,
                                            papszSwaths[i], papszFields[j]) );
 
-                    sprintf( szTemp, "SUBDATASET_%d_DESC", nCount + 1 );
-                    pszString = SPrintArray( GDT_UInt32, aiDimSizes,
-                                             iRank, "x" );
+                    snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_DESC", nCount + 1 );
+                    char *pszString = SPrintArray( GDT_UInt32, aiDimSizes,
+                                                   iRank, "x" );
                     poDS->papszSubDatasets =
                         CSLSetNameValue( poDS->papszSubDatasets, szTemp,
-                                         CPLSPrintf( "[%s] %s %s (%s)", pszString,
+                                         CPLSPrintf( "[%s] %s %s (%s)",
+                                                     pszString,
                                          papszFields[j],
                                          papszSwaths[i],
                                          poDS->GetDataTypeName(iNumType) ) );
                     CPLFree( pszString );
+                    szTemp[0] = '\0';
                 }
 
                 CSLDestroy( papszFields );
@@ -956,49 +981,51 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
         hHDF4 = GDopen( poOpenInfo->pszFilename, DFACC_READ );
         nSubDatasets = GDinqgrid( poOpenInfo->pszFilename, NULL, &nStrBufSize );
+
 #ifdef DEBUG
-        CPLDebug( "HDF4", "Number of HDF-EOS grids: %d", (int)nSubDatasets );
+        CPLDebug( "HDF4", "Number of HDF-EOS grids: %d",
+                  static_cast<int>( nSubDatasets ) );
 #endif
+
         if ( nSubDatasets > 0 && nStrBufSize > 0 )
         {
-            char    *pszGridList;
-            char    **papszGrids;
-
-            pszGridList = (char *)CPLMalloc( nStrBufSize + 1 );
+            char *pszGridList
+                = static_cast<char *>( CPLMalloc( nStrBufSize + 1 ) );
             GDinqgrid( poOpenInfo->pszFilename, pszGridList, &nStrBufSize );
 
 #ifdef DEBUG
             CPLDebug( "HDF4", "List of HDF-EOS grids: %s", pszGridList );
 #endif
 
-            papszGrids =
+            char **papszGrids =
                 CSLTokenizeString2( pszGridList, ",", CSLT_HONOURSTRINGS );
             CPLFree( pszGridList );
 
             if ( nSubDatasets != CSLCount(papszGrids) )
             {
                 CSLDestroy( papszGrids );
-                GDclose( hHDF4 ); 
-                CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+                GDclose( hHDF4 );
+                // Release mutex otherwise we will deadlock with GDALDataset own
+                // mutex.
+                CPLReleaseMutex(hHDF4Mutex);
                 delete poDS;
                 CPLAcquireMutex(hHDF4Mutex, 1000.0);
-                CPLDebug( "HDF4", "Can not parse list of HDF-EOS grids." );
+                CPLDebug( "HDF4", "Cannot parse list of HDF-EOS grids." );
                 return NULL;
             }
 
-            for ( i = 0; i < nSubDatasets; i++)
+            for( int32 i = 0; i < nSubDatasets; i++)
             {
-                char    *pszFieldList;
-                char    **papszFields;
-                int32   *paiRank, *paiNumType;
-                int32   hGD, nFields, j;
+                const int32 hGD = GDattach( hHDF4, papszGrids[i] );
 
-                hGD = GDattach( hHDF4, papszGrids[i] );
-
-                nFields = GDnentries( hGD, HDFE_NENTDFLD, &nStrBufSize );
-                pszFieldList = (char *)CPLMalloc( nStrBufSize + 1 );
-                paiRank = (int32 *)CPLMalloc( nFields * sizeof(int32) );
-                paiNumType = (int32 *)CPLMalloc( nFields * sizeof(int32) );
+                const int32 nFields
+                    = GDnentries( hGD, HDFE_NENTDFLD, &nStrBufSize );
+                char *pszFieldList = static_cast<char *>(
+                    CPLMalloc( nStrBufSize + 1 ) );
+                int32 *paiRank = static_cast<int32 *>(
+                    CPLMalloc( nFields * sizeof(int32) ) );
+                int32 *paiNumType = static_cast<int32 *>(
+                    CPLMalloc( nFields * sizeof(int32) ) );
 
                 GDinqfields( hGD, pszFieldList, paiRank, paiNumType );
 
@@ -1007,19 +1034,20 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
                     char* pszTmp =
                             SPrintArray( GDT_UInt32, paiRank, nFields, "," );
                     CPLDebug( "HDF4", "Number of fields in grid %d: %d",
-                            (int) i, (int) nFields );
+                              static_cast<int>( i ),
+                              static_cast<int>( nFields ) );
                     CPLDebug( "HDF4", "List of fields in grid %d: %s",
-                            (int) i, pszFieldList );
-                    CPLDebug( "HDF4", "Fields ranks: %s",
-                            pszTmp );
+                              static_cast<int>( i ), pszFieldList );
+                    CPLDebug( "HDF4", "Fields ranks: %s", pszTmp );
                     CPLFree( pszTmp );
                 }
 #endif
 
-                papszFields = CSLTokenizeString2( pszFieldList, ",",
+                char **papszFields = CSLTokenizeString2( pszFieldList, ",",
                                                   CSLT_HONOURSTRINGS );
-                
-                for ( j = 0; j < nFields; j++ )
+
+                char szTemp[256];
+                for( int32 j = 0; j < nFields; j++ )
                 {
                     GDfieldinfo( hGD, papszFields[j], &iRank, aiDimSizes,
                                  &iNumType, NULL );
@@ -1027,22 +1055,23 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
                     if ( iRank < 2 )
                         continue;
 
-	            // Add field to the list of GDAL subdatasets
-                    nCount = CSLCount( poDS->papszSubDatasets ) / 2;
-                    sprintf( szTemp, "SUBDATASET_%d_NAME", nCount + 1 );
-	            // We will use the field index as an identificator.
+                    // Add field to the list of GDAL subdatasets
+                    const int nCount = CSLCount( poDS->papszSubDatasets ) / 2;
+                    snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_NAME", nCount + 1 );
+                    // We will use the field index as an identificator.
                     poDS->papszSubDatasets =
                         CSLSetNameValue(poDS->papszSubDatasets, szTemp,
                                 CPLSPrintf( "HDF4_EOS:EOS_GRID:\"%s\":%s:%s",
                                             poOpenInfo->pszFilename,
                                             papszGrids[i], papszFields[j]));
 
-                    sprintf( szTemp, "SUBDATASET_%d_DESC", nCount + 1 );
-                    pszString = SPrintArray( GDT_UInt32, aiDimSizes,
-                                             iRank, "x" );
+                    snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_DESC", nCount + 1 );
+                    char *pszString = SPrintArray( GDT_UInt32, aiDimSizes,
+                                                   iRank, "x" );
                     poDS->papszSubDatasets =
                         CSLSetNameValue( poDS->papszSubDatasets, szTemp,
-                                         CPLSPrintf("[%s] %s %s (%s)", pszString,
+                                         CPLSPrintf("[%s] %s %s (%s)",
+                                                    pszString,
                                              papszFields[j],
                                              papszGrids[i],
                                              poDS->GetDataTypeName(iNumType)) );
@@ -1063,51 +1092,61 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
         bIsHDF = ( nSubDatasets == 0 ); // Try to read as HDF
     }
 
+    char szName[VSNAMELENMAX + 1];
+
     if( bIsHDF )
     {
 
 /* -------------------------------------------------------------------- */
-/*  Make a list of subdatasets from SDSs contained in input HDF file.	*/
+/*  Make a list of subdatasets from SDSs contained in input HDF file.   */
 /* -------------------------------------------------------------------- */
-        int32   nDatasets;
+        int32 nDatasets = 0;
 
         if ( SDfileinfo( poDS->hSD, &nDatasets, &nAttrs ) != 0 )
-	    return NULL;
+            return NULL;
 
-        for ( i = 0; i < nDatasets; i++ )
-        {
-            int32	iSDS;
+        char szTemp[256] = {'\0'};  // TODO: Get this off the stack.
+        const char *pszName = NULL;
 
-            iSDS = SDselect( poDS->hSD, i );
-            if ( SDgetinfo( iSDS, szName, &iRank, aiDimSizes, &iNumType, &nAttrs) != 0 )
+        for( int32 i = 0; i < nDatasets; i++ )
+        {
+            const int32 iSDS = SDselect( poDS->hSD, i );
+            if ( SDgetinfo( iSDS, szName, &iRank, aiDimSizes, &iNumType,
+                            &nAttrs) != 0 )
                 return NULL;
-            
-            if ( iRank == 1 )		// Skip 1D datsets
+
+            if ( iRank == 1 )  // Skip 1D datsets
                     continue;
 
             // Do sort of known datasets. We will display only image bands
             if ( (poDS->iSubdatasetType == H4ST_SEAWIFS_L1A ) &&
-                      !EQUALN( szName, "l1a_data", 8 ) )
+                      !STARTS_WITH_CI(szName, "l1a_data") )
                     continue;
             else
                 pszName = szName;
-            
+
             // Add datasets with multiple dimensions to the list of GDAL subdatasets
-            nCount = CSLCount( poDS->papszSubDatasets ) / 2;
-            sprintf( szTemp, "SUBDATASET_%d_NAME", nCount + 1 );
+            const int nCount = CSLCount( poDS->papszSubDatasets ) / 2;
+            snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_NAME", nCount + 1 );
             // We will use SDS index as an identificator, because SDS names
             // are not unique. Filename also needed for further file opening
-            poDS->papszSubDatasets = CSLSetNameValue(poDS->papszSubDatasets, szTemp, 
+            poDS->papszSubDatasets = CSLSetNameValue(
+                  poDS->papszSubDatasets,
+                  szTemp,
                   CPLSPrintf( "HDF4_SDS:%s:\"%s\":%ld", poDS->pszSubdatasetType,
-                              poOpenInfo->pszFilename, (long)i) );
-            sprintf( szTemp, "SUBDATASET_%d_DESC", nCount + 1 );
-            pszString = SPrintArray( GDT_UInt32, aiDimSizes, iRank, "x" );
-            poDS->papszSubDatasets = CSLSetNameValue(poDS->papszSubDatasets, szTemp,
+                              poOpenInfo->pszFilename,
+                              static_cast<long>( i ) ) );
+            snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_DESC", nCount + 1 );
+            char *pszString = SPrintArray( GDT_UInt32, aiDimSizes, iRank, "x" );
+            poDS->papszSubDatasets = CSLSetNameValue(
+                poDS->papszSubDatasets,
+                szTemp,
                 CPLSPrintf( "[%s] %s (%s)", pszString,
                             pszName, poDS->GetDataTypeName(iNumType)) );
             CPLFree( pszString );
 
             SDendaccess( iSDS );
+            szTemp[0] = '\0';
         }
 
         SDend( poDS->hSD );
@@ -1126,7 +1165,9 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
     {
         if ( GRfileinfo( poDS->hGR, &poDS->nImages, &nAttrs ) == -1 )
         {
-            CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+            // Release mutex otherwise we will deadlock with GDALDataset own
+            // mutex.
+            CPLReleaseMutex(hHDF4Mutex);
             GRend( poDS->hGR );
             poDS->hGR = 0;
             Hclose( hHDF4 );
@@ -1135,17 +1176,20 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
             return NULL;
         }
 
-        for ( i = 0; i < poDS->nImages; i++ )
+        char szTemp[256] = {'\0'};  // TODO: Get this off the stack.
+        for( int32 i = 0; i < poDS->nImages; i++ )
         {
-            int32   iInterlaceMode; 
-            int32   iGR = GRselect( poDS->hGR, i );
+            const int32 iGR = GRselect( poDS->hGR, i );
 
             // iRank in GR interface has another meaning. It represents number
             // of samples per pixel. aiDimSizes has only two dimensions.
+            int32 iInterlaceMode;
             if ( GRgetiminfo( iGR, szName, &iRank, &iNumType, &iInterlaceMode,
                               aiDimSizes, &nAttrs ) != 0 )
             {
-                CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+                // Release mutex otherwise we will deadlock with GDALDataset
+                // own mutex.
+                CPLReleaseMutex(hHDF4Mutex);
                 GRend( poDS->hGR );
                 poDS->hGR = 0;
                 Hclose( hHDF4 );
@@ -1153,19 +1197,22 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
                 CPLAcquireMutex(hHDF4Mutex, 1000.0);
                 return NULL;
             }
-            nCount = CSLCount( poDS->papszSubDatasets ) / 2;
-            sprintf( szTemp, "SUBDATASET_%d_NAME", nCount + 1 );
+            const int nCount = CSLCount( poDS->papszSubDatasets ) / 2;
+            snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_NAME", nCount + 1 );
             poDS->papszSubDatasets = CSLSetNameValue(poDS->papszSubDatasets,
                 szTemp,CPLSPrintf( "HDF4_GR:UNKNOWN:\"%s\":%ld",
-                                   poOpenInfo->pszFilename, (long)i));
-            sprintf( szTemp, "SUBDATASET_%d_DESC", nCount + 1 );
-            pszString = SPrintArray( GDT_UInt32, aiDimSizes, 2, "x" );
+                                   poOpenInfo->pszFilename,
+                                   static_cast<long>( i ) ) );
+            snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_DESC", nCount + 1 );
+            char *pszString = SPrintArray( GDT_UInt32, aiDimSizes, 2, "x" );
             poDS->papszSubDatasets = CSLSetNameValue(poDS->papszSubDatasets,
-                szTemp, CPLSPrintf( "[%sx%ld] %s (%s)", pszString, (long)iRank,
+                szTemp, CPLSPrintf( "[%sx%ld] %s (%s)", pszString,
+                                    static_cast<long>( iRank ),
                                     szName, poDS->GetDataTypeName(iNumType)) );
             CPLFree( pszString );
 
             GRendaccess( iGR );
+            szTemp[0] = '\0';
         }
 
         GRend( poDS->hGR );
@@ -1184,14 +1231,15 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if ( CSLCount( poDS->papszSubDatasets ) / 2 == 1 )
     {
-        char *pszSDSName;
-        pszSDSName = CPLStrdup( CSLFetchNameValue( poDS->papszSubDatasets,
-                            "SUBDATASET_1_NAME" ));
-        CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+        char *pszSDSName = CPLStrdup( CSLFetchNameValue( poDS->papszSubDatasets,
+                                                         "SUBDATASET_1_NAME" ));
+        // Release mutex otherwise we will deadlock with GDALDataset own mutex.
+        CPLReleaseMutex(hHDF4Mutex);
         delete poDS;
         poDS = NULL;
 
-        GDALDataset* poRetDS = (GDALDataset*) GDALOpen( pszSDSName, poOpenInfo->eAccess );
+        GDALDataset* poRetDS = reinterpret_cast<GDALDataset*>(
+            GDALOpen( pszSDSName, poOpenInfo->eAccess ) );
         CPLFree( pszSDSName );
 
         CPLAcquireMutex(hHDF4Mutex, 1000.0);
@@ -1210,16 +1258,18 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
         if( poOpenInfo->eAccess == GA_Update )
         {
-            CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+            // Release mutex otherwise we will deadlock with GDALDataset own
+            // mutex.
+            CPLReleaseMutex(hHDF4Mutex);
             delete poDS;
             CPLAcquireMutex(hHDF4Mutex, 1000.0);
 
-            CPLError( CE_Failure, CPLE_NotSupported, 
-                      "The HDF4 driver does not support update access to existing"
-                      " datasets.\n" );
+            CPLError( CE_Failure, CPLE_NotSupported,
+                      "The HDF4 driver does not support update access to "
+                      "existing datasets.\n" );
             return NULL;
         }
-    
+
     }
 
     return( poDS );
@@ -1229,7 +1279,7 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
 /*                           HDF4UnloadDriver()                         */
 /************************************************************************/
 
-static void HDF4UnloadDriver(CPL_UNUSED GDALDriver* poDriver)
+static void HDF4UnloadDriver( GDALDriver * /* poDriver */ )
 {
     if( hHDF4Mutex != NULL )
         CPLDestroyMutex(hHDF4Mutex);
@@ -1237,39 +1287,35 @@ static void HDF4UnloadDriver(CPL_UNUSED GDALDriver* poDriver)
 }
 
 /************************************************************************/
-/*                        GDALRegister_HDF4()				*/
+/*                        GDALRegister_HDF4()                           */
 /************************************************************************/
 
 void GDALRegister_HDF4()
 
 {
-    GDALDriver	*poDriver;
-    
-    if (! GDAL_CHECK_VERSION("HDF4 driver"))
+    if( !GDAL_CHECK_VERSION( "HDF4 driver" ) )
         return;
 
-    if( GDALGetDriverByName( "HDF4" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "HDF4" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Hierarchical Data Format Release 4" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_hdf4.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "hdf" );
-        poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
-
-        poDriver->pfnOpen = HDF4Dataset::Open;
-        poDriver->pfnIdentify = HDF4Dataset::Identify;
-        poDriver->pfnUnloadDriver = HDF4UnloadDriver;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    if( GDALGetDriverByName( "HDF4" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "HDF4" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Hierarchical Data Format Release 4" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_hdf4.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "hdf" );
+    poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
+
+    poDriver->pfnOpen = HDF4Dataset::Open;
+    poDriver->pfnIdentify = HDF4Dataset::Identify;
+    poDriver->pfnUnloadDriver = HDF4UnloadDriver;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 
 #ifdef HDF4_PLUGIN
     GDALRegister_HDF4Image();
 #endif
-
 }
diff --git a/frmts/hdf4/hdf4dataset.h b/frmts/hdf4/hdf4dataset.h
index 98e60d0..d66f8d8 100644
--- a/frmts/hdf4/hdf4dataset.h
+++ b/frmts/hdf4/hdf4dataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hdf4dataset.h 28879 2015-04-09 11:05:49Z dron $
+ * $Id: hdf4dataset.h 33794 2016-03-26 13:19:07Z goatbar $
  *
  * Project:  Hierarchical Data Format Release 4 (HDF4)
  * Purpose:  Header file for HDF4 datasets reader.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _HDF4DATASET_H_INCLUDED_
-#define _HDF4DATASET_H_INCLUDED_
+#ifndef HDF4DATASET_H_INCLUDED_
+#define HDF4DATASET_H_INCLUDED_
 
 #include "cpl_list.h"
 #include "gdal_pam.h"
@@ -65,15 +65,15 @@ class HDF4Dataset : public GDALPamDataset
 
   private:
 
-    int         bIsHDFEOS;
+    bool bIsHDFEOS;
 
     static char **HDF4EOSTokenizeAttrs( const char *pszString );
     static char **HDF4EOSGetObject( char **papszAttrList, char **ppszAttrName,
                                     char **ppszAttrClass, char **ppszAttrValue );
-     
-  protected:
 
-    int32	hGR, hSD;
+  protected:
+    int32	hGR;
+    int32	hSD;
     int32	nImages;
     HDF4SubdatasetType iSubdatasetType;
     const char	*pszSubdatasetType;
@@ -94,8 +94,8 @@ class HDF4Dataset : public GDALPamDataset
 
   public:
                 HDF4Dataset();
-		~HDF4Dataset();
-    
+    virtual ~HDF4Dataset();
+
     virtual char      **GetMetadataDomainList();
     virtual char        **GetMetadata( const char * pszDomain = "" );
     static GDALDataset  *Open( GDALOpenInfo * );
@@ -106,5 +106,4 @@ char *SPrintArray( GDALDataType eDataType, const void *paDataArray,
                    int nValues, const char *pszDelimiter );
 
 
-#endif /* _HDF4DATASET_H_INCLUDED_ */
-
+#endif /* HDF4DATASET_H_INCLUDED_ */
diff --git a/frmts/hdf4/hdf4imagedataset.cpp b/frmts/hdf4/hdf4imagedataset.cpp
index 93869db..b716e2f 100644
--- a/frmts/hdf4/hdf4imagedataset.cpp
+++ b/frmts/hdf4/hdf4imagedataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hdf4imagedataset.cpp 29212 2015-05-20 09:28:31Z rouault $
+ * $Id: hdf4imagedataset.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  Hierarchical Data Format Release 4 (HDF4)
  * Purpose:  Read subdatasets of HDF4 file.
@@ -29,38 +29,47 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#if defined(_WIN32)
+// min/max are defined here on Windows, so block them.
+// TODO: Move this to someplace more appropriate.
+#  define NOMINMAX
+#endif
+
 #include <string.h>
 #include <math.h>
+
 #include "cpl_multiproc.h"
+#include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "gdal_priv.h"
+#include "ogr_spatialref.h"
 
 #include "hdf.h"
 #include "mfhdf.h"
 
 #include "HdfEosDef.h"
 
-#include "gdal_priv.h"
-#include "cpl_string.h"
-#include "ogr_spatialref.h"
-
 #include "hdf4compat.h"
 #include "hdf4dataset.h"
 
 #include "nasakeywordhandler.h"
 
-CPL_CVSID("$Id: hdf4imagedataset.cpp 29212 2015-05-20 09:28:31Z rouault $");
+#include <algorithm>
+
+CPL_CVSID("$Id: hdf4imagedataset.cpp 33808 2016-03-29 21:15:28Z goatbar $");
 
-CPL_C_START
-void    GDALRegister_HDF4(void);
-CPL_C_END
+static const int HDF4_SDS_MAXNAMELEN = 65;
 
-#define HDF4_SDS_MAXNAMELEN 65
+extern const char * const pszGDALSignature;
 
 // Signature to recognize files written by GDAL
-const char      *pszGDALSignature =
+const char      * const pszGDALSignature =
         "Created with GDAL (http://www.remotesensing.org/gdal/)";
 
 extern CPLMutex *hHDF4Mutex;
 
+static const int N_BUF_SIZE = 8192;
+
 /************************************************************************/
 /* ==================================================================== */
 /*  List of HDF-EOS Swath product types.                                */
@@ -137,7 +146,7 @@ class HDF4ImageDataset : public HDF4Dataset
 
   public:
                 HDF4ImageDataset();
-                ~HDF4ImageDataset();
+    virtual ~HDF4ImageDataset();
 
     static GDALDataset  *Open( GDALOpenInfo * );
     static GDALDataset  *Create( const char * pszFilename,
@@ -166,7 +175,8 @@ class HDF4ImageRasterBand : public GDALPamRasterBand
     int         bNoDataSet;
     double      dfNoDataValue;
 
-    int         bHaveScale, bHaveOffset;
+    int         bHaveScale;
+    int         bHaveOffset;
     double      dfScale;
     double      dfOffset;
 
@@ -175,14 +185,15 @@ class HDF4ImageRasterBand : public GDALPamRasterBand
   public:
 
                 HDF4ImageRasterBand( HDF4ImageDataset *, int, GDALDataType );
+    virtual ~HDF4ImageRasterBand() {}
 
     virtual CPLErr          IReadBlock( int, int, void * );
     virtual CPLErr          IWriteBlock( int, int, void * );
     virtual GDALColorInterp GetColorInterpretation();
     virtual GDALColorTable *GetColorTable();
-    virtual double	    GetNoDataValue( int * );
-    virtual CPLErr	    SetNoDataValue( double );
-    virtual double	    GetOffset( int *pbSuccess );
+    virtual double          GetNoDataValue( int * );
+    virtual CPLErr          SetNoDataValue( double );
+    virtual double          GetOffset( int *pbSuccess );
     virtual double          GetScale( int *pbSuccess );
     virtual const char     *GetUnitType();
 };
@@ -191,33 +202,33 @@ class HDF4ImageRasterBand : public GDALPamRasterBand
 /*                           HDF4ImageRasterBand()                      */
 /************************************************************************/
 
-HDF4ImageRasterBand::HDF4ImageRasterBand( HDF4ImageDataset *poDS, int nBand,
-                                          GDALDataType eType )
-
+HDF4ImageRasterBand::HDF4ImageRasterBand( HDF4ImageDataset *poDSIn, int nBandIn,
+                                          GDALDataType eType ) :
+    bNoDataSet(FALSE),
+    dfNoDataValue(-9999.0),
+    bHaveScale(FALSE),
+    bHaveOffset(FALSE),
+    dfScale(1.0),
+    dfOffset(0.0)
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
     eDataType = eType;
-    bNoDataSet = FALSE;
-    dfNoDataValue = -9999.0;
-
-    bHaveScale = bHaveOffset = FALSE;
-    dfScale = 1.0;
-    dfOffset = 0.0;
 
-    nBlockXSize = poDS->GetRasterXSize();
+    nBlockXSize = poDSIn->GetRasterXSize();
 
     // Aim for a block of about 1000000 pixels.  Chunking up substantially
     // improves performance in some situations.  For now we only chunk up for
-    // SDS and EOS based datasets since other variations haven't been tested. #2208
-    if( poDS->iDatasetType == HDF4_SDS ||
-        poDS->iDatasetType == HDF4_EOS)
+    // SDS and EOS based datasets since other variations haven't been
+    // tested. #2208
+    if( poDSIn->iDatasetType == HDF4_SDS ||
+        poDSIn->iDatasetType == HDF4_EOS)
     {
-        int nChunkSize =
+        const int nChunkSize =
             atoi( CPLGetConfigOption("HDF4_BLOCK_PIXELS", "1000000") );
 
-        nBlockYSize = nChunkSize / poDS->GetRasterXSize();
-        nBlockYSize = MAX(1,MIN(nBlockYSize,poDS->GetRasterYSize()));
+        nBlockYSize = nChunkSize / poDSIn->GetRasterXSize();
+        nBlockYSize = MAX(1,MIN(nBlockYSize,poDSIn->GetRasterYSize()));
     }
     else
     {
@@ -227,19 +238,19 @@ HDF4ImageRasterBand::HDF4ImageRasterBand( HDF4ImageDataset *poDS, int nBand,
     /* HDF4_EOS:EOS_GRID case. We ensure that the block size matches */
     /* the raster width, as the IReadBlock() code can only handle multiple */
     /* blocks per row */
-    if ( poDS->nBlockPreferredXSize == nBlockXSize &&
-         poDS->nBlockPreferredYSize > 0 )
+    if ( poDSIn->nBlockPreferredXSize == nBlockXSize &&
+         poDSIn->nBlockPreferredYSize > 0 )
     {
-        if (poDS->nBlockPreferredYSize == 1)
+        if (poDSIn->nBlockPreferredYSize == 1)
         {
             /* Avoid defaulting to tile reading when the preferred height is 1 */
             /* as it leads to very poor performance with : */
-            /* ftp://e4ftl01u.ecs.nasa.gov/MODIS_Composites/MOLT/MOD13Q1.005/2006.06.10/MOD13Q1.A2006161.h21v13.005.2008234103220.hd */
-            poDS->bReadTile = FALSE;
+            // ftp://e4ftl01u.ecs.nasa.gov/MODIS_Composites/MOLT/MOD13Q1.005/2006.06.10/MOD13Q1.A2006161.h21v13.005.2008234103220.hd
+            poDSIn->bReadTile = FALSE;
         }
         else
         {
-            nBlockYSize = poDS->nBlockPreferredYSize;
+            nBlockYSize = poDSIn->nBlockPreferredYSize;
         }
     }
 
@@ -247,10 +258,10 @@ HDF4ImageRasterBand::HDF4ImageRasterBand( HDF4ImageDataset *poDS, int nBand,
 /*      We need to avoid using the tile based api if we aren't          */
 /*      matching the tile size. (#4672)                                 */
 /* -------------------------------------------------------------------- */
-    if( nBlockXSize != poDS->nBlockPreferredXSize
-        || nBlockYSize != poDS->nBlockPreferredYSize ) 
+    if( nBlockXSize != poDSIn->nBlockPreferredXSize
+        || nBlockYSize != poDSIn->nBlockPreferredYSize )
     {
-        poDS->bReadTile = FALSE;
+        poDSIn->bReadTile = FALSE;
     }
 }
 
@@ -261,8 +272,10 @@ HDF4ImageRasterBand::HDF4ImageRasterBand( HDF4ImageDataset *poDS, int nBand,
 CPLErr HDF4ImageRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                         void * pImage )
 {
-    HDF4ImageDataset    *poGDS = (HDF4ImageDataset *) poDS;
-    int32               aiStart[H4_MAX_NC_DIMS], aiEdges[H4_MAX_NC_DIMS];
+    CPLAssert( nBlockXOff == 0 );
+    HDF4ImageDataset *poGDS = reinterpret_cast<HDF4ImageDataset *>( poDS );
+    int32 aiStart[H4_MAX_NC_DIMS];
+    int32 aiEdges[H4_MAX_NC_DIMS];
     CPLErr              eErr = CE_None;
 
     CPLMutexHolderD(&hHDF4Mutex);
@@ -270,16 +283,16 @@ CPLErr HDF4ImageRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     if( poGDS->eAccess == GA_Update )
     {
         memset( pImage, 0,
-                nBlockXSize * nBlockYSize * GDALGetDataTypeSize(eDataType) / 8 );
+                nBlockXSize * nBlockYSize
+                * GDALGetDataTypeSizeBytes(eDataType) );
         return CE_None;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Work out some block oriented details.                           */
 /* -------------------------------------------------------------------- */
-    int nYOff = nBlockYOff * nBlockYSize;
-    int nYSize = MIN(nYOff + nBlockYSize, poDS->GetRasterYSize()) - nYOff;
-    CPLAssert( nBlockXOff == 0 );
+    const int nYOff = nBlockYOff * nBlockYSize;
+    const int nYSize = MIN(nYOff + nBlockYSize, poDS->GetRasterYSize()) - nYOff;
 
 /* -------------------------------------------------------------------- */
 /*      HDF files with external data files, such as some landsat        */
@@ -366,17 +379,16 @@ CPLErr HDF4ImageRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
               eErr = CE_Failure;
           }
 
-          //SDendaccess( iSDS );
+          //SDendaccess( l_iSDS );
       }
       break;
 
       case HDF4_GR:
       {
-          int     nDataTypeSize =
-              GDALGetDataTypeSize(poGDS->GetDataType(poGDS->iNumType)) / 8;
-          GByte    *pbBuffer = (GByte *)
-              CPLMalloc(nBlockXSize*nBlockYSize*poGDS->iRank*nBlockYSize);
-          int     i, j;
+          const int nDataTypeSize =
+              GDALGetDataTypeSizeBytes(poGDS->GetDataType(poGDS->iNumType));
+          GByte *pbBuffer = reinterpret_cast<GByte *>(
+              CPLMalloc(nBlockXSize*nBlockYSize*poGDS->iRank*nBlockYSize) );
 
           aiStart[poGDS->iYDim] = nYOff;
           aiEdges[poGDS->iYDim] = nYSize;
@@ -392,10 +404,11 @@ CPLErr HDF4ImageRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
           }
           else
           {
-              for ( i = 0, j = (nBand - 1) * nDataTypeSize;
+              for ( int i = 0, j = (nBand - 1) * nDataTypeSize;
                     i < nBlockXSize * nDataTypeSize;
                     i += nDataTypeSize, j += poGDS->nBands * nDataTypeSize )
-                  memcpy( (GByte *)pImage + i, pbBuffer + j, nDataTypeSize );
+                  memcpy( reinterpret_cast<GByte *>( pImage ) + i,
+                          pbBuffer + j, nDataTypeSize );
           }
 
           CPLFree( pbBuffer );
@@ -408,10 +421,8 @@ CPLErr HDF4ImageRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
           {
             case H4ST_EOS_GRID:
             {
-                int32   hGD;
-
-                hGD = GDattach( poGDS->hHDF4,
-                                poGDS->pszSubdatasetName );
+                const int32 hGD = GDattach( poGDS->hHDF4,
+                                      poGDS->pszSubdatasetName );
                 switch ( poGDS->iRank )
                 {
                   case 4: // 4Dim: volume
@@ -457,9 +468,11 @@ CPLErr HDF4ImageRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                      (nBlockYOff + 1) * nBlockYSize <= nRasterYSize )
                 {
                     int32 tilecoords[] = { nBlockYOff , nBlockXOff };
-                    if( GDreadtile( hGD, poGDS->pszFieldName , tilecoords , pImage ) != 0 )
+                    if( GDreadtile( hGD, poGDS->pszFieldName,
+                                    tilecoords, pImage ) != 0 )
                     {
-                        CPLError( CE_Failure, CPLE_AppDefined, "GDreadtile() failed for block." );
+                        CPLError( CE_Failure, CPLE_AppDefined,
+                                  "GDreadtile() failed for block." );
                         eErr = CE_Failure;
                     }
                 }
@@ -477,10 +490,8 @@ CPLErr HDF4ImageRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             case H4ST_EOS_SWATH:
             case H4ST_EOS_SWATH_GEOL:
             {
-                int32   hSW;
-
-                hSW = SWattach( poGDS->hHDF4,
-                                poGDS->pszSubdatasetName );
+                const int32 hSW = SWattach( poGDS->hHDF4,
+                                            poGDS->pszSubdatasetName );
                 switch ( poGDS->iRank )
                 {
                   case 3: // 3Dim: volume
@@ -532,23 +543,24 @@ CPLErr HDF4ImageRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 CPLErr HDF4ImageRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                                          void * pImage )
 {
-    HDF4ImageDataset    *poGDS = (HDF4ImageDataset *)poDS;
-    int32               aiStart[H4_MAX_NC_DIMS], aiEdges[H4_MAX_NC_DIMS];
+    CPLAssert( nBlockXOff == 0 );
+    CPLAssert( nBlockYOff >= 0 );
+    CPLAssert( pImage != NULL );
+
+    HDF4ImageDataset *poGDS = reinterpret_cast<HDF4ImageDataset *>( poDS );
+    CPLAssert( poGDS != NULL );
+
+    int32 aiStart[H4_MAX_NC_DIMS];
+    int32 aiEdges[H4_MAX_NC_DIMS];
     CPLErr              eErr = CE_None;
-    
-    CPLMutexHolderD(&hHDF4Mutex);
 
-    CPLAssert( poGDS != NULL
-               && nBlockXOff == 0
-               && nBlockYOff >= 0
-               && pImage != NULL );
+    CPLMutexHolderD(&hHDF4Mutex);
 
 /* -------------------------------------------------------------------- */
 /*      Work out some block oriented details.                           */
 /* -------------------------------------------------------------------- */
-    int nYOff = nBlockYOff * nBlockYSize;
-    int nYSize = MIN(nYOff + nBlockYSize, poDS->GetRasterYSize()) - nYOff;
-    CPLAssert( nBlockXOff == 0 );
+    const int nYOff = nBlockYOff * nBlockYSize;
+    const int nYSize = MIN(nYOff + nBlockYSize, poDS->GetRasterYSize()) - nYOff;
 
 /* -------------------------------------------------------------------- */
 /*      Process based on rank.                                          */
@@ -557,7 +569,7 @@ CPLErr HDF4ImageRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     {
         case 3:
             {
-                int32   iSDS = SDselect( poGDS->hSD, poGDS->iDataset );
+                const int32 l_iSDS = SDselect( poGDS->hSD, poGDS->iDataset );
 
                 aiStart[poGDS->iBandDim] = nBand - 1;
                 aiEdges[poGDS->iBandDim] = 1;
@@ -568,28 +580,28 @@ CPLErr HDF4ImageRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                 aiStart[poGDS->iXDim] = nBlockXOff;
                 aiEdges[poGDS->iXDim] = nBlockXSize;
 
-                if ( (SDwritedata( iSDS, aiStart, NULL,
+                if ( (SDwritedata( l_iSDS, aiStart, NULL,
                                    aiEdges, (VOIDP)pImage )) < 0 )
                     eErr = CE_Failure;
 
-                SDendaccess( iSDS );
+                SDendaccess( l_iSDS );
             }
             break;
 
         case 2:
             {
-                int32 iSDS = SDselect( poGDS->hSD, nBand - 1 );
+                const int32 l_iSDS = SDselect( poGDS->hSD, nBand - 1 );
                 aiStart[poGDS->iYDim] = nYOff;
                 aiEdges[poGDS->iYDim] = nYSize;
 
                 aiStart[poGDS->iXDim] = nBlockXOff;
                 aiEdges[poGDS->iXDim] = nBlockXSize;
 
-                if ( (SDwritedata( iSDS, aiStart, NULL,
+                if ( (SDwritedata( l_iSDS, aiStart, NULL,
                                    aiEdges, (VOIDP)pImage )) < 0 )
                     eErr = CE_Failure;
 
-                SDendaccess( iSDS );
+                SDendaccess( l_iSDS );
             }
             break;
 
@@ -607,7 +619,7 @@ CPLErr HDF4ImageRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
 
 GDALColorTable *HDF4ImageRasterBand::GetColorTable()
 {
-    HDF4ImageDataset    *poGDS = (HDF4ImageDataset *) poDS;
+    HDF4ImageDataset *poGDS = reinterpret_cast<HDF4ImageDataset *>( poDS );
 
     return poGDS->poColorTable;
 }
@@ -618,7 +630,7 @@ GDALColorTable *HDF4ImageRasterBand::GetColorTable()
 
 GDALColorInterp HDF4ImageRasterBand::GetColorInterpretation()
 {
-    HDF4ImageDataset    *poGDS = (HDF4ImageDataset *) poDS;
+    HDF4ImageDataset *poGDS = reinterpret_cast<HDF4ImageDataset *>( poDS );
 
     if ( poGDS->iDatasetType == HDF4_SDS )
         return GCI_GrayIndex;
@@ -642,8 +654,8 @@ GDALColorInterp HDF4ImageRasterBand::GetColorInterpretation()
         else
             return GCI_GrayIndex;
     }
-    else
-        return GCI_GrayIndex;
+
+    return GCI_GrayIndex;
 }
 
 /************************************************************************/
@@ -681,8 +693,8 @@ const char *HDF4ImageRasterBand::GetUnitType()
 {
     if( osUnitType.size() > 0 )
         return osUnitType;
-    else
-        return GDALRasterBand::GetUnitType();
+
+    return GDALRasterBand::GetUnitType();
 }
 
 /************************************************************************/
@@ -698,8 +710,8 @@ double HDF4ImageRasterBand::GetOffset( int *pbSuccess )
             *pbSuccess = TRUE;
         return dfOffset;
     }
-    else
-        return GDALRasterBand::GetOffset( pbSuccess );
+
+    return GDALRasterBand::GetOffset( pbSuccess );
 }
 
 /************************************************************************/
@@ -715,8 +727,8 @@ double HDF4ImageRasterBand::GetScale( int *pbSuccess )
             *pbSuccess = TRUE;
         return dfScale;
     }
-    else
-        return GDALRasterBand::GetScale( pbSuccess );
+
+    return GDALRasterBand::GetScale( pbSuccess );
 }
 
 /************************************************************************/
@@ -836,6 +848,7 @@ HDF4ImageDataset::~HDF4ImageDataset()
                         break;
                     case H4ST_EOS_GRID:
                         GDclose( hHDF4 );
+                        break;
                     default:
                         break;
                 }
@@ -919,8 +932,8 @@ const char *HDF4ImageDataset::GetGCPProjection()
 {
     if( nGCPCount > 0 )
         return pszGCPProjection;
-    else
-        return "";
+
+    return "";
 }
 
 /************************************************************************/
@@ -939,10 +952,9 @@ const GDAL_GCP *HDF4ImageDataset::GetGCPs()
 void HDF4ImageDataset::FlushCache()
 
 {
-    int         iBand;
     char        *pszName;
     const char  *pszValue;
-    
+
     CPLMutexHolderD(&hHDF4Mutex);
 
     GDALDataset::FlushCache();
@@ -956,7 +968,7 @@ void HDF4ImageDataset::FlushCache()
                                    adfGeoTransform[2], adfGeoTransform[3],
                                    adfGeoTransform[4], adfGeoTransform[5] );
     if ( (SDsetattr( hSD, "TransformationMatrix", DFNT_CHAR8,
-                     strlen(pszValue) + 1, pszValue )) < 0 )
+                     static_cast<int>(strlen(pszValue)) + 1, pszValue )) < 0 )
     {
         CPLDebug( "HDF4Image",
                   "Cannot write transformation matrix to output file" );
@@ -966,7 +978,7 @@ void HDF4ImageDataset::FlushCache()
     if ( pszProjection != NULL && !EQUAL( pszProjection, "" ) )
     {
         if ( (SDsetattr( hSD, "Projection", DFNT_CHAR8,
-                         strlen(pszProjection) + 1, pszProjection )) < 0 )
+                         static_cast<int>(strlen(pszProjection)) + 1, pszProjection )) < 0 )
             {
                 CPLDebug( "HDF4Image",
                           "Cannot write projection information to output file");
@@ -983,7 +995,7 @@ void HDF4ImageDataset::FlushCache()
             pszName = NULL;
             pszValue = CPLParseNameValue( *papszMeta++, &pszName );
             if ( pszName != NULL && (SDsetattr( hSD, pszName, DFNT_CHAR8,
-                             strlen(pszValue) + 1, pszValue )) < 0 )
+                             static_cast<int>(strlen(pszValue)) + 1, pszValue )) < 0 )
             {
                 CPLDebug( "HDF4Image",
                           "Cannot write metadata information to output file");
@@ -994,17 +1006,17 @@ void HDF4ImageDataset::FlushCache()
     }
 
     // Write out NoData values
-    for ( iBand = 1; iBand <= nBands; iBand++ )
+    for ( int iBand = 1; iBand <= nBands; iBand++ )
     {
         HDF4ImageRasterBand *poBand =
-            (HDF4ImageRasterBand *)GetRasterBand(iBand);
+            reinterpret_cast<HDF4ImageRasterBand *>( GetRasterBand(iBand) );
 
         if ( poBand->bNoDataSet )
         {
             pszName = CPLStrdup( CPLSPrintf( "NoDataValue%d", iBand ) );
             pszValue = CPLSPrintf( "%f", poBand->dfNoDataValue );
             if ( (SDsetattr( hSD, pszName, DFNT_CHAR8,
-                             strlen(pszValue) + 1, pszValue )) < 0 )
+                             static_cast<int>(strlen(pszValue)) + 1, pszValue )) < 0 )
                 {
                     CPLDebug( "HDF4Image",
                               "Cannot write NoData value for band %d "
@@ -1016,17 +1028,17 @@ void HDF4ImageDataset::FlushCache()
     }
 
     // Write out band descriptions
-    for ( iBand = 1; iBand <= nBands; iBand++ )
+    for ( int iBand = 1; iBand <= nBands; iBand++ )
     {
         HDF4ImageRasterBand *poBand =
-            (HDF4ImageRasterBand *)GetRasterBand(iBand);
+            reinterpret_cast<HDF4ImageRasterBand *>( GetRasterBand(iBand) );
 
         pszName = CPLStrdup( CPLSPrintf( "BandDesc%d", iBand ) );
         pszValue = poBand->GetDescription();
         if ( pszValue != NULL && !EQUAL( pszValue, "" ) )
         {
             if ( (SDsetattr( hSD, pszName, DFNT_CHAR8,
-                             strlen(pszValue) + 1, pszValue )) < 0 )
+                             static_cast<int>(strlen(pszValue)) + 1, pszValue )) < 0 )
             {
                 CPLDebug( "HDF4Image",
                           "Cannot write band's %d description to output file",
@@ -1090,12 +1102,11 @@ void HDF4ImageDataset::ToGeoref( double *pdfGeoX, double *pdfGeoY )
 /************************************************************************/
 
 void HDF4ImageDataset::ReadCoordinates( const char *pszString,
-                                        double *pdfX, double *pdfY )
+                                        double *pdfCenterY, double *pdfCenterX )
 {
-    char **papszStrList;
-    papszStrList = CSLTokenizeString2( pszString, ", ", 0 );
-    *pdfX = CPLAtof( papszStrList[0] );
-    *pdfY = CPLAtof( papszStrList[1] );
+    char **papszStrList = CSLTokenizeString2( pszString, ", ", 0 );
+    *pdfCenterY = CPLAtof( papszStrList[0] ); /* lat */
+    *pdfCenterX = CPLAtof( papszStrList[1] ); /* lon */
     CSLDestroy( papszStrList );
 }
 
@@ -1188,12 +1199,11 @@ void HDF4ImageDataset::CaptureL1GMTLInfo()
 /*      Ingest the MTL using the NASAKeywordHandler written for the     */
 /*      PDS driver.                                                     */
 /* -------------------------------------------------------------------- */
-    NASAKeywordHandler oMTL;
-
     VSILFILE *fp = VSIFOpenL( osMTLFilename, "r" );
     if( fp == NULL )
         return;
 
+    NASAKeywordHandler oMTL;
     if( !oMTL.Ingest( fp, 0 ) )
     {
         VSIFCloseL( fp );
@@ -1204,10 +1214,8 @@ void HDF4ImageDataset::CaptureL1GMTLInfo()
 
 /* -------------------------------------------------------------------- */
 /*  Note: Different variation of MTL files use different group names.   */
-/*	      Check for LPGS_METADATA_FILE and L1_METADATA_FILE.        */
+/*            Check for LPGS_METADATA_FILE and L1_METADATA_FILE.        */
 /* -------------------------------------------------------------------- */
-    double dfULX, dfULY, dfLRX, dfLRY;
-    double dfLLX, dfLLY, dfURX, dfURY;
     CPLString osPrefix;
 
     if( oMTL.GetKeyword( "LPGS_METADATA_FILE.PRODUCT_METADATA"
@@ -1219,14 +1227,22 @@ void HDF4ImageDataset::CaptureL1GMTLInfo()
     else
         return;
 
-    dfULX = CPLAtof(oMTL.GetKeyword((osPrefix+"UL_CORNER_LON").c_str(), "0" ));
-    dfULY = CPLAtof(oMTL.GetKeyword((osPrefix+"UL_CORNER_LAT").c_str(), "0" ));
-    dfLRX = CPLAtof(oMTL.GetKeyword((osPrefix+"LR_CORNER_LON").c_str(), "0" ));
-    dfLRY = CPLAtof(oMTL.GetKeyword((osPrefix+"LR_CORNER_LAT").c_str(), "0" ));
-    dfLLX = CPLAtof(oMTL.GetKeyword((osPrefix+"LL_CORNER_LON").c_str(), "0" ));
-    dfLLY = CPLAtof(oMTL.GetKeyword((osPrefix+"LL_CORNER_LAT").c_str(), "0" ));
-    dfURX = CPLAtof(oMTL.GetKeyword((osPrefix+"UR_CORNER_LON").c_str(), "0" ));
-    dfURY = CPLAtof(oMTL.GetKeyword((osPrefix+"UR_CORNER_LAT").c_str(), "0" ));
+    const double dfULX
+        = CPLAtof( oMTL.GetKeyword( (osPrefix+"UL_CORNER_LON").c_str(), "0" ) );
+    const double dfULY
+        = CPLAtof( oMTL.GetKeyword( (osPrefix+"UL_CORNER_LAT").c_str(), "0" ) );
+    const double dfLRX
+        = CPLAtof( oMTL.GetKeyword( (osPrefix+"LR_CORNER_LON").c_str(), "0" ) );
+    const double dfLRY
+        = CPLAtof( oMTL.GetKeyword( (osPrefix+"LR_CORNER_LAT").c_str(), "0" ) );
+    const double dfLLX
+        = CPLAtof( oMTL.GetKeyword( (osPrefix+"LL_CORNER_LON").c_str(), "0" ) );
+    const double dfLLY
+        = CPLAtof( oMTL.GetKeyword( (osPrefix+"LL_CORNER_LAT").c_str(), "0" ) );
+    const double dfURX
+        = CPLAtof( oMTL.GetKeyword( (osPrefix+"UR_CORNER_LON").c_str(), "0" ) );
+    const double dfURY
+        = CPLAtof( oMTL.GetKeyword( (osPrefix+"UR_CORNER_LAT").c_str(), "0" ) );
 
     CPLFree( pszGCPProjection );
     pszGCPProjection = CPLStrdup( "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9108\"]],AXIS[\"Lat\",NORTH],AXIS[\"Long\",EAST],AUTHORITY[\"EPSG\",\"4326\"]]" );
@@ -1321,12 +1337,11 @@ void HDF4ImageDataset::CaptureNRLGeoTransform()
 /*      Collect the four corners.                                       */
 /* -------------------------------------------------------------------- */
     double adfXY[8];
-    static const char *apszItems[] = {
+    static const char * const apszItems[] = {
         "mapUpperLeft", "mapUpperRight", "mapLowerLeft", "mapLowerRight" };
-    int iCorner;
-    int bLLPossible = TRUE;
+    bool bLLPossible = true;
 
-    for( iCorner = 0; iCorner < 4; iCorner++ )
+    for( int iCorner = 0; iCorner < 4; iCorner++ )
     {
         const char *pszCornerLoc =
             CSLFetchNameValue( papszGlobalMetadata, apszItems[iCorner] );
@@ -1337,14 +1352,17 @@ void HDF4ImageDataset::CaptureNRLGeoTransform()
         char **papszTokens = CSLTokenizeStringComplex( pszCornerLoc, ",",
                                                        FALSE, FALSE );
         if( CSLCount( papszTokens ) != 2 )
+        {
+            CSLDestroy( papszTokens );
             return;
+        }
 
         adfXY[iCorner*2+0] = CPLAtof( papszTokens[1] );
         adfXY[iCorner*2+1] = CPLAtof( papszTokens[0] );
 
         if( adfXY[iCorner*2+0] < -360 || adfXY[iCorner*2+0] > 360
             || adfXY[iCorner*2+1] < -90 || adfXY[iCorner*2+1] > 90 )
-            bLLPossible = FALSE;
+            bLLPossible = false;
 
         CSLDestroy( papszTokens );
     }
@@ -1371,40 +1389,46 @@ void HDF4ImageDataset::CaptureNRLGeoTransform()
 /* -------------------------------------------------------------------- */
 /*      Can we find the USGS Projection Parameters?                     */
 /* -------------------------------------------------------------------- */
-    int  bGotGCTPProjection = FALSE;
-    int  iSDSIndex = FAIL, iSDS = FAIL;
+    bool bGotGCTPProjection = false;
+    int l_iSDSIndex = FAIL;
+    int l_iSDS = FAIL;
     const char *mapProjection = CSLFetchNameValue( papszGlobalMetadata,
                                                    "mapProjection" );
 
     if( mapProjection )
-        iSDSIndex = SDnametoindex( hSD, mapProjection );
+        l_iSDSIndex = SDnametoindex( hSD, mapProjection );
 
-    if( iSDSIndex != FAIL )
-        iSDS = SDselect( hSD, iSDSIndex );
+    if( l_iSDSIndex != FAIL )
+        l_iSDS = SDselect( hSD, l_iSDSIndex );
 
-    if( iSDS != FAIL )
+    if( l_iSDS != FAIL )
     {
-        char        szName[HDF4_SDS_MAXNAMELEN];
-        int32	    iRank, iNumType, nAttrs;
-        int32       aiDimSizes[H4_MAX_VAR_DIMS];
+        char        l_szName[HDF4_SDS_MAXNAMELEN];
+        int32 l_iRank, l_iNumType, l_nAttrs;
+        int32       l_aiDimSizes[H4_MAX_VAR_DIMS];
 
         double adfGCTP[29];
-        int32 aiStart[H4_MAX_NC_DIMS], aiEdges[H4_MAX_NC_DIMS];
+        int32 aiStart[H4_MAX_NC_DIMS];
+        int32 aiEdges[H4_MAX_NC_DIMS];
 
         aiStart[0] = 0;
         aiEdges[0] = 29;
 
-	if( SDgetinfo( iSDS, szName, &iRank, aiDimSizes, &iNumType,
-                       &nAttrs) == 0
-            && iNumType == DFNT_FLOAT64
-            && iRank == 1
-            && aiDimSizes[0] >= 29
-            && SDreaddata( iSDS, aiStart, NULL, aiEdges, adfGCTP ) == 0
-            && oSRS.importFromUSGS( (long) adfGCTP[1], (long) adfGCTP[2],
+        if( SDgetinfo( l_iSDS, l_szName, &l_iRank, l_aiDimSizes, &l_iNumType,
+                       &l_nAttrs) == 0
+            && l_iNumType == DFNT_FLOAT64
+            && l_iRank == 1
+            && l_aiDimSizes[0] >= 29
+            && SDreaddata( l_iSDS, aiStart, NULL, aiEdges, adfGCTP ) == 0
+            && oSRS.importFromUSGS( static_cast<long>( adfGCTP[1] ),
+                                    static_cast<long>( adfGCTP[2] ),
                                     adfGCTP+4,
-                                    (long) adfGCTP[3] ) == OGRERR_NONE )
+                                    static_cast<long>( adfGCTP[3] ) )
+            == OGRERR_NONE )
         {
-            CPLDebug( "HDF4Image", "GCTP Parms = %g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g",
+            CPLDebug( "HDF4Image",
+                      "GCTP Parms = %g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,"
+                      "%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g",
                       adfGCTP[0],
                       adfGCTP[1],
                       adfGCTP[2],
@@ -1440,7 +1464,7 @@ void HDF4ImageDataset::CaptureNRLGeoTransform()
             bGotGCTPProjection = TRUE;
         }
 
-        SDendaccess(iSDS);
+        SDendaccess(l_iSDS);
     }
 
 /* -------------------------------------------------------------------- */
@@ -1450,7 +1474,6 @@ void HDF4ImageDataset::CaptureNRLGeoTransform()
 /* -------------------------------------------------------------------- */
     if( bLLPossible && bGotGCTPProjection )
     {
-        double dfULX, dfULY, dfLRX, dfLRY;
         OGRSpatialReference oWGS84;
 
         oWGS84.SetWellKnownGeogCS( "WGS84" );
@@ -1458,11 +1481,11 @@ void HDF4ImageDataset::CaptureNRLGeoTransform()
         OGRCoordinateTransformation *poCT =
             OGRCreateCoordinateTransformation( &oWGS84, &oSRS );
 
-        dfULX = adfXY[0*2+0];
-        dfULY = adfXY[0*2+1];
+        double dfULX = adfXY[0*2+0];
+        double dfULY = adfXY[0*2+1];
 
-        dfLRX = adfXY[3*2+0];
-        dfLRY = adfXY[3*2+1];
+        double dfLRX = adfXY[3*2+0];
+        double dfLRY = adfXY[3*2+1];
 
         if( poCT->Transform( 1, &dfULX, &dfULY )
             && poCT->Transform( 1, &dfLRX, &dfLRY ) )
@@ -1536,21 +1559,24 @@ void HDF4ImageDataset::CaptureCoastwatchGCTPInfo()
 /* -------------------------------------------------------------------- */
 /*      Grab USGS/GCTP Parameters.                                      */
 /* -------------------------------------------------------------------- */
-    int nSys, nZone, nDatum, iParm;
-    double adfParms[15];
-    char **papszTokens;
-
-    nSys = atoi( CSLFetchNameValue( papszGlobalMetadata, "gctp_sys" ) );
-    nZone = atoi( CSLFetchNameValue( papszGlobalMetadata, "gctp_zone" ) );
-    nDatum = atoi( CSLFetchNameValue( papszGlobalMetadata, "gctp_datum" ) );
+    const int nSys
+        = atoi( CSLFetchNameValue( papszGlobalMetadata, "gctp_sys" ) );
+    const int nZone
+        = atoi( CSLFetchNameValue( papszGlobalMetadata, "gctp_zone" ) );
+    const int nDatum
+        = atoi( CSLFetchNameValue( papszGlobalMetadata, "gctp_datum" ) );
 
-    papszTokens = CSLTokenizeStringComplex(
+    char **papszTokens = CSLTokenizeStringComplex(
         CSLFetchNameValue( papszGlobalMetadata, "gctp_parm" ), ",",
         FALSE, FALSE );
     if( CSLCount(papszTokens) < 15 )
+    {
+        CSLDestroy(papszTokens);
         return;
+    }
 
-    for( iParm = 0; iParm < 15; iParm++ )
+    double adfParms[15];
+    for( int iParm = 0; iParm < 15; iParm++ )
         adfParms[iParm] = CPLAtof( papszTokens[iParm] );
     CSLDestroy( papszTokens );
 
@@ -1572,12 +1598,18 @@ void HDF4ImageDataset::CaptureCoastwatchGCTPInfo()
         CSLFetchNameValue( papszGlobalMetadata, "et_affine" ), ",",
         FALSE, FALSE );
     if( CSLCount(papszTokens) != 6 )
+    {
+        CSLDestroy(papszTokens);
         return;
+    }
 
     // We don't seem to have proper ef_affine docs so I don't
     // know which of these two coefficients goes where.
     if( CPLAtof(papszTokens[0]) != 0.0 || CPLAtof(papszTokens[3]) != 0.0 )
+    {
+        CSLDestroy(papszTokens);
         return;
+    }
 
     bHasGeoTransform = TRUE;
     adfGeoTransform[0] = CPLAtof( papszTokens[4] );
@@ -1590,6 +1622,8 @@ void HDF4ImageDataset::CaptureCoastwatchGCTPInfo()
     // Middle of pixel adjustment.
     adfGeoTransform[0] -= adfGeoTransform[1] * 0.5;
     adfGeoTransform[3] -= adfGeoTransform[5] * 0.5;
+
+    CSLDestroy(papszTokens);
 }
 
 /************************************************************************/
@@ -1600,7 +1634,7 @@ void HDF4ImageDataset::GetImageDimensions( char *pszDimList )
 {
     char    **papszDimList = CSLTokenizeString2( pszDimList, ",",
                                                  CSLT_HONOURSTRINGS );
-    int     i, nDimCount = CSLCount( papszDimList );
+    const int nDimCount = CSLCount( papszDimList );
 
     // TODO: check whether nDimCount is > 1 and do something if it isn't.
 
@@ -1610,7 +1644,7 @@ void HDF4ImageDataset::GetImageDimensions( char *pszDimList )
         nBandCount = 1;
     else
     {
-        for ( i = 0; i < nDimCount; i++ )
+        for( int i = 0; i < nDimCount; i++ )
         {
             if ( strstr( papszDimList[i], "band" ) )
             {
@@ -1634,11 +1668,11 @@ void HDF4ImageDataset::GetImageDimensions( char *pszDimList )
     iXDim = nDimCount - 1;
     iYDim = nDimCount - 2;
 
-    for ( i = 0; i < nDimCount; i++ )
+    for( int i = 0; i < nDimCount; i++ )
     {
-        if ( EQUALN( papszDimList[i], "X", 1 ) && iBandDim != i )
+        if ( STARTS_WITH_CI(papszDimList[i], "X") && iBandDim != i )
             iXDim = i;
-        else if ( EQUALN( papszDimList[i], "Y", 1 ) && iBandDim != i )
+        else if ( STARTS_WITH_CI(papszDimList[i], "Y") && iBandDim != i )
             iYDim = i;
     }
 
@@ -1681,11 +1715,8 @@ void HDF4ImageDataset::GetSwatAttrs( int32 hSW )
 
     if ( SWinqattrs( hSW, NULL, &nStrBufSize ) > 0 && nStrBufSize > 0 )
     {
-        char    *pszAttrList;
-        char    **papszAttributes;
-        int     i, nAttrs;
-
-        pszAttrList = (char *)CPLMalloc( nStrBufSize + 1 );
+        char *pszAttrList
+            = reinterpret_cast<char *>( CPLMalloc( nStrBufSize + 1 ) );
         SWinqattrs( hSW, pszAttrList, &nStrBufSize );
 
 #ifdef DEBUG
@@ -1693,45 +1724,45 @@ void HDF4ImageDataset::GetSwatAttrs( int32 hSW )
                   pszFieldName, pszAttrList );
 #endif
 
-        papszAttributes = CSLTokenizeString2( pszAttrList, ",",
-                                              CSLT_HONOURSTRINGS );
-        nAttrs = CSLCount( papszAttributes );
-        for ( i = 0; i < nAttrs; i++ )
+        char **papszAttributes = CSLTokenizeString2( pszAttrList, ",",
+                                                     CSLT_HONOURSTRINGS );
+        const int l_nAttrs = CSLCount( papszAttributes );
+        for( int i = 0; i < l_nAttrs; i++ )
         {
-            int32       iNumType, nValues;
-            void	*pData = NULL;
-            char	*pszTemp = NULL;
+            int32 l_iNumType;
+            int32 nValues;
 
-            SWattrinfo( hSW, papszAttributes[i], &iNumType, &nValues );
+            if( SWattrinfo( hSW, papszAttributes[i], &l_iNumType, &nValues ) < 0 )
+                continue;
 
-            if ( iNumType == DFNT_CHAR8 || iNumType == DFNT_UCHAR8 )
-                pData = CPLMalloc( (nValues + 1) * GetDataTypeSize(iNumType) );
+            void *pData = NULL;
+            if ( l_iNumType == DFNT_CHAR8 || l_iNumType == DFNT_UCHAR8 )
+                pData = CPLMalloc( (nValues + 1) * GetDataTypeSize(l_iNumType) );
             else
-                pData = CPLMalloc( nValues * GetDataTypeSize(iNumType) );
+                pData = CPLMalloc( nValues * GetDataTypeSize(l_iNumType) );
 
             SWreadattr( hSW, papszAttributes[i], pData );
 
-            if ( iNumType == DFNT_CHAR8 || iNumType == DFNT_UCHAR8 )
+            if ( l_iNumType == DFNT_CHAR8 || l_iNumType == DFNT_UCHAR8 )
             {
-                ((char *)pData)[nValues] = '\0';
-                papszLocalMetadata = CSLAddNameValue( papszLocalMetadata,
-                                                      papszAttributes[i],
-                                                      (const char *) pData );
+                reinterpret_cast<char *>( pData )[nValues] = '\0';
+                papszLocalMetadata = CSLAddNameValue(
+                    papszLocalMetadata,
+                    papszAttributes[i],
+                    const_cast<const char *>(
+                        reinterpret_cast<char *>( pData ) ) );
             }
             else
             {
-                pszTemp = SPrintArray( GetDataType(iNumType), pData,
-                                       nValues, ", " );
+                char *pszTemp = SPrintArray( GetDataType(l_iNumType), pData,
+                                             nValues, ", " );
                 papszLocalMetadata = CSLAddNameValue( papszLocalMetadata,
                                                       papszAttributes[i],
                                                       pszTemp );
-                if ( pszTemp )
-                    CPLFree( pszTemp );
+                CPLFree( pszTemp );
             }
 
-            if ( pData )
-                CPLFree( pData );
-
+            CPLFree( pData );
         }
 
         CSLDestroy( papszAttributes );
@@ -1742,24 +1773,25 @@ void HDF4ImageDataset::GetSwatAttrs( int32 hSW )
 /*      After fetching HDF-EOS specific stuff we will read the generic  */
 /*      HDF attributes and append them to the list of metadata.         */
 /* -------------------------------------------------------------------- */
-    int32   iSDS;
-    if ( SWsdid(hSW, pszFieldName, &iSDS) != -1 )
+    int32   l_iSDS;
+    if ( SWsdid(hSW, pszFieldName, &l_iSDS) != -1 )
     {
-        int32	    iRank, iNumType, iAttribute, nAttrs, nValues;
-        char        szName[HDF4_SDS_MAXNAMELEN];
-        int32       aiDimSizes[H4_MAX_VAR_DIMS];
+        int32 l_iRank, l_iNumType, l_nAttrs;
+        char        l_szName[HDF4_SDS_MAXNAMELEN];
+        int32       l_aiDimSizes[H4_MAX_VAR_DIMS];
 
-	if( SDgetinfo( iSDS, szName, &iRank, aiDimSizes, &iNumType,
-                       &nAttrs) == 0 )
+        if( SDgetinfo( l_iSDS, l_szName, &l_iRank, l_aiDimSizes, &l_iNumType,
+                       &l_nAttrs) == 0 )
         {
-            for ( iAttribute = 0; iAttribute < nAttrs; iAttribute++ )
+            for( int32 iAttribute = 0; iAttribute < l_nAttrs; iAttribute++ )
             {
-                char    szAttrName[H4_MAX_NC_NAME];
-                SDattrinfo( iSDS, iAttribute, szAttrName,
-                            &iNumType, &nValues );
+                char szAttrName[H4_MAX_NC_NAME];
+                int32 nValues;
+                SDattrinfo( l_iSDS, iAttribute, szAttrName,
+                            &l_iNumType, &nValues );
                 papszLocalMetadata =
-                    TranslateHDF4Attributes( iSDS, iAttribute,
-                                             szAttrName, iNumType,
+                    TranslateHDF4Attributes( l_iSDS, iAttribute,
+                                             szAttrName, l_iNumType,
                                              nValues, papszLocalMetadata );
             }
         }
@@ -1793,55 +1825,50 @@ void HDF4ImageDataset::GetGridAttrs( int32 hGD )
 
     if ( GDinqattrs( hGD, NULL, &nStrBufSize ) > 0 && nStrBufSize > 0 )
     {
-        char    *pszAttrList;
-        char    **papszAttributes;
-        int     i, nAttrs;
-
-        pszAttrList = (char *)CPLMalloc( nStrBufSize + 1 );
+        char *pszAttrList
+            = reinterpret_cast<char *>( CPLMalloc( nStrBufSize + 1 ) );
         GDinqattrs( hGD, pszAttrList, &nStrBufSize );
+
 #ifdef DEBUG
         CPLDebug( "HDF4Image", "List of attributes in grid %s: %s",
                   pszFieldName, pszAttrList );
 #endif
-        papszAttributes = CSLTokenizeString2( pszAttrList, ",",
-                                              CSLT_HONOURSTRINGS );
-        nAttrs = CSLCount( papszAttributes );
-        for ( i = 0; i < nAttrs; i++ )
+
+        char **papszAttributes = CSLTokenizeString2( pszAttrList, ",",
+                                                     CSLT_HONOURSTRINGS );
+        const int l_nAttrs = CSLCount( papszAttributes );
+        for ( int i = 0; i < l_nAttrs; i++ )
         {
-            int32       iNumType, nValues;
-            void	*pData = NULL;
-            char	*pszTemp = NULL;
+            int32       l_iNumType, nValues;
 
-            GDattrinfo( hGD, papszAttributes[i], &iNumType, &nValues );
+            GDattrinfo( hGD, papszAttributes[i], &l_iNumType, &nValues );
 
-            if ( iNumType == DFNT_CHAR8 || iNumType == DFNT_UCHAR8 )
-                pData = CPLMalloc( (nValues + 1) * GetDataTypeSize(iNumType) );
+            void *pData = NULL;
+            if ( l_iNumType == DFNT_CHAR8 || l_iNumType == DFNT_UCHAR8 )
+                pData = CPLMalloc( (nValues + 1) * GetDataTypeSize(l_iNumType) );
             else
-                pData = CPLMalloc( nValues * GetDataTypeSize(iNumType) );
+                pData = CPLMalloc( nValues * GetDataTypeSize(l_iNumType) );
 
             GDreadattr( hGD, papszAttributes[i], pData );
 
-            if ( iNumType == DFNT_CHAR8 || iNumType == DFNT_UCHAR8 )
+            if ( l_iNumType == DFNT_CHAR8 || l_iNumType == DFNT_UCHAR8 )
             {
-                ((char *)pData)[nValues] = '\0';
+                reinterpret_cast<char *>( pData )[nValues] = '\0';
                 papszLocalMetadata = CSLAddNameValue( papszLocalMetadata,
                                                       papszAttributes[i],
                                                       (const char *) pData );
             }
             else
             {
-                pszTemp = SPrintArray( GetDataType(iNumType), pData,
-                                       nValues, ", " );
+                char *pszTemp = SPrintArray( GetDataType(l_iNumType), pData,
+                                             nValues, ", " );
                 papszLocalMetadata = CSLAddNameValue( papszLocalMetadata,
                                                       papszAttributes[i],
                                                       pszTemp );
-                if ( pszTemp )
-                    CPLFree( pszTemp );
+                CPLFree( pszTemp );
             }
 
-            if ( pData )
-                CPLFree( pData );
-
+            CPLFree( pData );
         }
 
         CSLDestroy( papszAttributes );
@@ -1852,24 +1879,24 @@ void HDF4ImageDataset::GetGridAttrs( int32 hGD )
 /*      After fetching HDF-EOS specific stuff we will read the generic  */
 /*      HDF attributes and append them to the list of metadata.         */
 /* -------------------------------------------------------------------- */
-    int32   iSDS;
-    if ( GDsdid(hGD, pszFieldName, &iSDS) != -1 )
+    int32   l_iSDS;
+    if ( GDsdid(hGD, pszFieldName, &l_iSDS) != -1 )
     {
-        int32	    iRank, iNumType, iAttribute, nAttrs, nValues;
-        char        szName[HDF4_SDS_MAXNAMELEN];
-        int32       aiDimSizes[H4_MAX_VAR_DIMS];
+        int32 l_iRank, l_iNumType, l_nAttrs, nValues;
+        char        l_szName[HDF4_SDS_MAXNAMELEN];
+        int32       l_aiDimSizes[H4_MAX_VAR_DIMS];
 
-	if( SDgetinfo( iSDS, szName, &iRank, aiDimSizes, &iNumType,
-                       &nAttrs) == 0 )
+        if( SDgetinfo( l_iSDS, l_szName, &l_iRank, l_aiDimSizes, &l_iNumType,
+                       &l_nAttrs) == 0 )
         {
-            for ( iAttribute = 0; iAttribute < nAttrs; iAttribute++ )
+            for( int32 iAttribute = 0; iAttribute < l_nAttrs; iAttribute++ )
             {
                 char    szAttrName[H4_MAX_NC_NAME];
-                SDattrinfo( iSDS, iAttribute, szAttrName,
-                            &iNumType, &nValues );
+                SDattrinfo( l_iSDS, iAttribute, szAttrName,
+                            &l_iNumType, &nValues );
                 papszLocalMetadata =
-                    TranslateHDF4Attributes( iSDS, iAttribute,
-                                             szAttrName, iNumType,
+                    TranslateHDF4Attributes( l_iSDS, iAttribute,
+                                             szAttrName, l_iNumType,
                                              nValues, papszLocalMetadata );
             }
         }
@@ -1895,8 +1922,6 @@ void HDF4ImageDataset::GetGridAttrs( int32 hGD )
 void HDF4ImageDataset::ProcessModisSDSGeolocation(void)
 
 {
-    int iDSIndex, iXIndex=-1, iYIndex=-1;
-
     // No point in assigning geolocation to the geolocation SDSes themselves.
     if( EQUAL(szName,"longitude") || EQUAL(szName,"latitude") )
         return;
@@ -1910,44 +1935,47 @@ void HDF4ImageDataset::ProcessModisSDSGeolocation(void)
     int32   nDatasets, nAttributes;
 
     if ( SDfileinfo( hSD, &nDatasets, &nAttributes ) != 0 )
-	return;
-
+        return;
 
-    int nLongitudeWidth = 0, nLongitudeHeight = 0;
-    int nLatitudeWidth = 0, nLatitudeHeight = 0;
-    for( iDSIndex = 0; iDSIndex < nDatasets; iDSIndex++ )
+    int nLongitudeWidth = 0;
+    int nLongitudeHeight = 0;
+    int nLatitudeWidth = 0;
+    int nLatitudeHeight = 0;
+    int iXIndex=-1;
+    int iYIndex=-1;
+    for( int iDSIndex = 0; iDSIndex < nDatasets; iDSIndex++ )
     {
-        int32	    iRank, iNumType, nAttrs, iSDS;
-        char        szName[HDF4_SDS_MAXNAMELEN];
-        int32       aiDimSizes[H4_MAX_VAR_DIMS];
+        int32 l_iRank, l_iNumType, l_nAttrs;
+        char        l_szName[HDF4_SDS_MAXNAMELEN];
+        int32       l_aiDimSizes[H4_MAX_VAR_DIMS];
 
-	iSDS = SDselect( hSD, iDSIndex );
+        const int32 l_iSDS = SDselect( hSD, iDSIndex );
 
-	if( SDgetinfo( iSDS, szName, &iRank, aiDimSizes, &iNumType,
-                       &nAttrs) == 0 )
+        if( SDgetinfo( l_iSDS, l_szName, &l_iRank, l_aiDimSizes, &l_iNumType,
+                       &l_nAttrs) == 0 )
         {
-            if( EQUAL(szName,"latitude") )
+            if( EQUAL(l_szName,"latitude") )
             {
                 iYIndex = iDSIndex;
-                if( iRank == 2 )
+                if( l_iRank == 2 )
                 {
-                    nLatitudeWidth = aiDimSizes[1];
-                    nLatitudeHeight = aiDimSizes[0];
+                    nLatitudeWidth = l_aiDimSizes[1];
+                    nLatitudeHeight = l_aiDimSizes[0];
                 }
             }
 
-            if( EQUAL(szName,"longitude") )
+            if( EQUAL(l_szName,"longitude") )
             {
                 iXIndex = iDSIndex;
-                if( iRank == 2 )
+                if( l_iRank == 2 )
                 {
-                    nLongitudeWidth = aiDimSizes[1];
-                    nLongitudeHeight = aiDimSizes[0];
+                    nLongitudeWidth = l_aiDimSizes[1];
+                    nLongitudeHeight = l_aiDimSizes[0];
                 }
             }
         }
 
-        SDendaccess(iSDS);
+        SDendaccess(l_iSDS);
     }
 
     if( iXIndex == -1 || iYIndex == -1 )
@@ -1957,12 +1985,15 @@ void HDF4ImageDataset::ProcessModisSDSGeolocation(void)
     int nPixelStep = 1, nLineStep = 1;
     if( nLongitudeWidth != nLatitudeWidth || nLongitudeHeight != nLatitudeHeight )
     {
-        CPLDebug("HDF4", "Longitude and latitude subdatasets don't have same dimensions...");
+        CPLDebug("HDF4", "Longitude and latitude subdatasets don't have same "
+                 "dimensions...");
     }
     else if( nLongitudeWidth > 0 && nLongitudeHeight > 0 )
     {
-        nPixelStep = (int)(0.5 + 1.0 * nRasterXSize / nLongitudeWidth);
-        nLineStep = (int)(0.5 + 1.0 * nRasterYSize / nLongitudeHeight);
+        nPixelStep
+            = static_cast<int>( 0.5 + 1.0 * nRasterXSize / nLongitudeWidth );
+        nLineStep
+            = static_cast<int>( 0.5 + 1.0 * nRasterYSize / nLongitudeHeight );
         nPixelOffset = (nPixelStep-1) / 2;
         nLineOffset = (nLineStep-1) / 2;
     }
@@ -1970,10 +2001,10 @@ void HDF4ImageDataset::ProcessModisSDSGeolocation(void)
 /* -------------------------------------------------------------------- */
 /*      We found geolocation information.  Record it as metadata.       */
 /* -------------------------------------------------------------------- */
-    CPLString  osWrk;
 
     SetMetadataItem( "SRS", SRS_WKT_WGS84, "GEOLOCATION" );
 
+    CPLString  osWrk;
     osWrk.Printf( "HDF4_SDS:UNKNOWN:\"%s\":%d",
                   pszFilename, iXIndex );
     SetMetadataItem( "X_DATASET", osWrk, "GEOLOCATION" );
@@ -2002,20 +2033,6 @@ void HDF4ImageDataset::ProcessModisSDSGeolocation(void)
 
 int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
 {
-    char    szXGeo[8192] = "";
-    char    szYGeo[8192] = "";
-    char    szPixel[8192]= "";
-    char    szLine[8192] = "";
-    int32   iWrkNumType;
-    void    *pLat = NULL, *pLong = NULL;
-    void    *pLatticeX = NULL, *pLatticeY = NULL;
-    int32   iLatticeType, iLatticeDataSize = 0, iRank;
-    int32   nLatCount = 0, nLongCount = 0;
-    int32   nXPoints=0, nYPoints=0;
-    int32   nStrBufSize;
-    int     i, j, iDataSize = 0, iPixelDim=-1,iLineDim=-1, iLongDim=-1, iLatDim=-1;
-    int32   *paiRank = NULL, *paiNumType = NULL,
-        *paiOffset = NULL, *paiIncrement = NULL;
 
 /* -------------------------------------------------------------------- */
 /*  Determine a product name.                                           */
@@ -2026,25 +2043,25 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
     HDF4EOSProduct eProduct = PROD_UNKNOWN;
     if ( pszProduct )
     {
-        if ( EQUALN(pszProduct, "ASTL1A", 6) )
+        if ( STARTS_WITH_CI(pszProduct, "ASTL1A") )
             eProduct = PROD_ASTER_L1A;
-        else if ( EQUALN(pszProduct, "ASTL1B", 6) )
+        else if ( STARTS_WITH_CI(pszProduct, "ASTL1B") )
             eProduct = PROD_ASTER_L1B;
-        else if ( EQUALN(pszProduct, "AST_04", 6)
-                  || EQUALN(pszProduct, "AST_05", 6)
-                  || EQUALN(pszProduct, "AST_06", 6)
-                  || EQUALN(pszProduct, "AST_07", 6)
-                  || EQUALN(pszProduct, "AST_08", 6)
-                  || EQUALN(pszProduct, "AST_09", 6)
-                  || EQUALN(pszProduct, "AST13", 5)
-                  || EQUALN(pszProduct, "AST3", 4) )
+        else if ( STARTS_WITH_CI(pszProduct, "AST_04")
+                  || STARTS_WITH_CI(pszProduct, "AST_05")
+                  || STARTS_WITH_CI(pszProduct, "AST_06")
+                  || STARTS_WITH_CI(pszProduct, "AST_07")
+                  || STARTS_WITH_CI(pszProduct, "AST_08")
+                  || STARTS_WITH_CI(pszProduct, "AST_09")
+                  || STARTS_WITH_CI(pszProduct, "AST13")
+                  || STARTS_WITH_CI(pszProduct, "AST3") )
             eProduct = PROD_ASTER_L2;
-        else if ( EQUALN(pszProduct, "AST14", 5) )
+        else if ( STARTS_WITH_CI(pszProduct, "AST14") )
             eProduct = PROD_ASTER_L3;
-        else if ( EQUALN(pszProduct, "MOD02", 5)
-                  || EQUALN(pszProduct, "MYD02", 5) )
+        else if ( STARTS_WITH_CI(pszProduct, "MOD02")
+                  || STARTS_WITH_CI(pszProduct, "MYD02") )
             eProduct = PROD_MODIS_L1B;
-        else if ( EQUALN(pszProduct, "MOD07_L2", 8) )
+        else if ( STARTS_WITH_CI(pszProduct, "MOD07_L2") )
             eProduct = PROD_MODIS_L2;
     }
 
@@ -2052,10 +2069,15 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
 /*      Read names of geolocation fields and corresponding              */
 /*      geolocation maps.                                               */
 /* -------------------------------------------------------------------- */
-    int32   nDataFields = SWnentries( hSW, HDFE_NENTGFLD, &nStrBufSize );
-    char    *pszGeoList = (char *)CPLMalloc( nStrBufSize + 1 );
-    paiRank = (int32 *)CPLMalloc( nDataFields * sizeof(int32) );
-    paiNumType = (int32 *)CPLMalloc( nDataFields * sizeof(int32) );
+    int32 nStrBufSize;
+    const int32 nDataFields = SWnentries( hSW, HDFE_NENTGFLD, &nStrBufSize );
+    if( nDataFields < 0 || nDataFields > 1024 * 1024 )
+        return FALSE;
+    char *pszGeoList = reinterpret_cast<char *>( CPLMalloc( nStrBufSize + 1 ) );
+    int32 *paiRank
+        = reinterpret_cast<int32 *>( CPLMalloc( nDataFields * sizeof(int32) ) );
+    int32 *paiNumType
+        = reinterpret_cast<int32 *>( CPLMalloc( nDataFields * sizeof(int32) ) );
 
     if ( nDataFields !=
          SWinqgeofields(hSW, pszGeoList, paiRank, paiNumType) )
@@ -2068,14 +2090,13 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
 #ifdef DEBUG
     else
     {
-        char    *pszTmp;
         CPLDebug( "HDF4Image",
                   "Number of geolocation fields in swath \"%s\": %ld",
-                  pszSubdatasetName, (long)nDataFields );
+                  pszSubdatasetName, static_cast<long>( nDataFields ) );
         CPLDebug( "HDF4Image",
                   "List of geolocation fields in swath \"%s\": %s",
                   pszSubdatasetName, pszGeoList );
-        pszTmp = SPrintArray( GDT_UInt32, paiRank,
+        char *pszTmp = SPrintArray( GDT_UInt32, paiRank,
                               nDataFields, "," );
         CPLDebug( "HDF4Image",
                   "Geolocation fields ranks: %s", pszTmp );
@@ -2089,6 +2110,13 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
 /* -------------------------------------------------------------------- */
 /*      Read geolocation data.                                          */
 /* -------------------------------------------------------------------- */
+    char    szXGeo[N_BUF_SIZE] = "";
+    char    szYGeo[N_BUF_SIZE] = "";
+    char    szPixel[N_BUF_SIZE]= "";
+    char    szLine[N_BUF_SIZE] = "";
+    int32 *paiOffset = NULL;
+    int32 *paiIncrement = NULL;
+
     int32   nDimMaps = SWnentries( hSW, HDFE_NENTMAP, &nStrBufSize );
     if ( nDimMaps <= 0 )
     {
@@ -2097,24 +2125,39 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
         CPLDebug( "HDF4Image", "No geolocation maps in swath \"%s\"",
                   pszSubdatasetName );
         CPLDebug( "HDF4Image",
-                  "Suppose one-to-one mapping. X field is \"%s\", Y field is \"%s\"",
+                  "Suppose one-to-one mapping. X field is \"%s\", "
+                  "Y field is \"%s\"",
                   papszDimList[iXDim], papszDimList[iYDim] );
 #endif
 
-        strncpy( szPixel, papszDimList[iXDim], 8192 );
-        strncpy( szLine, papszDimList[iYDim], 8192 );
-        strncpy( szXGeo, papszDimList[iXDim], 8192 );
-        strncpy( szYGeo, papszDimList[iYDim], 8192 );
-        paiOffset = (int32 *)CPLCalloc( 2, sizeof(int32) );
-        paiIncrement = (int32 *)CPLCalloc( 2, sizeof(int32) );
-        paiOffset[0] = paiOffset[1] = 0;
-        paiIncrement[0] = paiIncrement[1] = 1;
+        strncpy( szPixel, papszDimList[iXDim], N_BUF_SIZE );
+        szPixel[N_BUF_SIZE - 1] = '\0';
+
+        strncpy( szLine, papszDimList[iYDim], N_BUF_SIZE );
+        szLine[N_BUF_SIZE - 1] = '\0';
+
+        strncpy( szXGeo, papszDimList[iXDim], N_BUF_SIZE );
+        szXGeo[N_BUF_SIZE - 1] = '\0';
+
+        strncpy( szYGeo, papszDimList[iYDim], N_BUF_SIZE );
+        szYGeo[N_BUF_SIZE - 1] = '\0';
+
+        paiOffset = reinterpret_cast<int32 *>( CPLCalloc( 2, sizeof(int32) ) );
+        paiIncrement
+            = reinterpret_cast<int32 *>( CPLCalloc( 2, sizeof(int32) ) );
+        paiOffset[0] = 0;
+        paiOffset[1] = 0;
+        paiIncrement[0] = 1;
+        paiIncrement[1] = 1;
     }
     else
     {
-        char *pszDimMaps = (char *)CPLMalloc( nStrBufSize + 1 );
-        paiOffset = (int32 *)CPLCalloc( nDimMaps, sizeof(int32) );
-        paiIncrement = (int32 *)CPLCalloc( nDimMaps, sizeof(int32) );
+        char *pszDimMaps
+            = reinterpret_cast<char *>( CPLMalloc( nStrBufSize + 1 ) );
+        paiOffset
+            = reinterpret_cast<int32 *>( CPLCalloc( nDimMaps, sizeof(int32) ) );
+        paiIncrement
+            = reinterpret_cast<int32 *>( CPLCalloc( nDimMaps, sizeof(int32) ) );
 
         *pszDimMaps = '\0';
         if ( nDimMaps != SWinqmaps(hSW, pszDimMaps, paiOffset, paiIncrement) )
@@ -2127,12 +2170,11 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
 #ifdef DEBUG
         else
         {
-            char    *pszTmp;
 
             CPLDebug( "HDF4Image",
                       "List of geolocation maps in swath \"%s\": %s",
                       pszSubdatasetName, pszDimMaps );
-            pszTmp = SPrintArray( GDT_Int32, paiOffset,
+            char *pszTmp = SPrintArray( GDT_Int32, paiOffset,
                                   nDimMaps, "," );
             CPLDebug( "HDF4Image",
                       "Geolocation map offsets: %s", pszTmp );
@@ -2147,22 +2189,28 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
 
         char    **papszDimMap = CSLTokenizeString2( pszDimMaps, ",",
                                                     CSLT_HONOURSTRINGS );
-        int     nDimMapCount = CSLCount(papszDimMap);
+        const int nDimMapCount = CSLCount(papszDimMap);
 
-        for ( i = 0; i < nDimMapCount; i++ )
+        for( int i = 0; i < nDimMapCount; i++ )
         {
             if ( strstr(papszDimMap[i], papszDimList[iXDim]) )
             {
-                strncpy( szPixel, papszDimList[iXDim], 8192 );
-                strncpy( szXGeo, papszDimMap[i], 8192 );
+                strncpy( szPixel, papszDimList[iXDim], N_BUF_SIZE );
+                szPixel[N_BUF_SIZE - 1] = '\0';
+
+                strncpy( szXGeo, papszDimMap[i], N_BUF_SIZE );
+                szXGeo[N_BUF_SIZE - 1] = '\0';
+
                 char *pszTemp = strchr( szXGeo, '/' );
                 if ( pszTemp )
                     *pszTemp = '\0';
             }
             else if ( strstr(papszDimMap[i], papszDimList[iYDim]) )
             {
-                strncpy( szLine, papszDimList[iYDim], 8192 );
-                strncpy( szYGeo, papszDimMap[i], 8192 );
+                strncpy( szLine, papszDimList[iYDim], N_BUF_SIZE );
+                szLine[N_BUF_SIZE - 1] = '\0';
+                strncpy( szYGeo, papszDimMap[i], N_BUF_SIZE );
+                szYGeo[N_BUF_SIZE - 1] = '\0';
                 char *pszTemp = strchr( szYGeo, '/' );
                 if ( pszTemp )
                     *pszTemp = '\0';
@@ -2174,33 +2222,56 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
     }
 
     if ( *szXGeo == 0 || *szYGeo == 0 )
+    {
+        CPLFree( paiOffset );
+        CPLFree( paiIncrement );
+        CPLFree( pszGeoList );
         return FALSE;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Read geolocation fields.                                        */
 /* -------------------------------------------------------------------- */
-    char    szGeoDimList[8192] = "";
+    char    szGeoDimList[N_BUF_SIZE] = "";
     char    **papszGeolocations = CSLTokenizeString2( pszGeoList, ",",
                                                       CSLT_HONOURSTRINGS );
     int     nGeolocationsCount = CSLCount( papszGeolocations );
-    int32   aiDimSizes[H4_MAX_VAR_DIMS];
+    int32   l_aiDimSizes[H4_MAX_VAR_DIMS];
 
-    for ( i = 0; i < nGeolocationsCount; i++ )
-    {
-        char    **papszGeoDimList = NULL;
+    int32 iWrkNumType = 0;
+    void *pLat = NULL;
+    void *pLong = NULL;
+
+    int32 l_iRank;
+    int32 nLatCount = 0;
+    int32 nLongCount = 0;
+    int32 nXPoints = 0;
+    int32 nYPoints = 0;
+    int iDataSize = 0;
+
+    int iPixelDim = -1;
+    int iLineDim = -1;
+    int iLongDim = -1;
+    int iLatDim = -1;
 
+    for( int i = 0; i < nGeolocationsCount; i++ )
+    {
         // Skip "SceneLineNumber" table if present in the list of geolocation
         // fields. It is not needed to fetch geocoding data.
         if ( EQUAL(papszGeolocations[i], "SceneLineNumber") )
             continue;
 
-        if ( SWfieldinfo( hSW, papszGeolocations[i], &iRank,
-                          aiDimSizes, &iWrkNumType, szGeoDimList ) < 0 )
+        if ( SWfieldinfo( hSW, papszGeolocations[i], &l_iRank,
+                          l_aiDimSizes, &iWrkNumType, szGeoDimList ) < 0 )
         {
 
             CPLDebug( "HDF4Image",
                       "Can't read attributes of geolocation field \"%s\"",
                       papszGeolocations[i] );
+            CSLDestroy(papszGeolocations);
+            CPLFree( paiOffset );
+            CPLFree( paiIncrement );
+            CPLFree( pszGeoList );
             return FALSE;
         }
 
@@ -2208,19 +2279,25 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
                   "List of dimensions in geolocation field \"%s\": %s",
                   papszGeolocations[i], szGeoDimList );
 
-        papszGeoDimList = CSLTokenizeString2( szGeoDimList,
-                                              ",", CSLT_HONOURSTRINGS );
+        char **papszGeoDimList = CSLTokenizeString2( szGeoDimList,
+                                                     ",", CSLT_HONOURSTRINGS );
 
-        if( CSLCount(papszGeoDimList) > H4_MAX_VAR_DIMS 
-            || CSLFindString( papszGeoDimList, szXGeo ) == -1
-            || CSLFindString( papszGeoDimList, szYGeo ) == -1 )
+        int iXGeo = CSLFindString( papszGeoDimList, szXGeo );
+        int iYGeo = CSLFindString( papszGeoDimList, szYGeo );
+        if( CSLCount(papszGeoDimList) > H4_MAX_VAR_DIMS
+            || iXGeo < 0
+            || iYGeo < 0 )
         {
             CSLDestroy( papszGeoDimList );
+            CSLDestroy(papszGeolocations);
+            CPLFree( paiOffset );
+            CPLFree( paiIncrement );
+            CPLFree( pszGeoList );
             return FALSE;
         }
 
-        nXPoints = aiDimSizes[CSLFindString( papszGeoDimList, szXGeo )];
-        nYPoints = aiDimSizes[CSLFindString( papszGeoDimList, szYGeo )];
+        nXPoints = l_aiDimSizes[iXGeo];
+        nYPoints = l_aiDimSizes[iYGeo];
 
         if ( EQUAL(szPixel, papszDimList[iXDim]) )
         {
@@ -2271,18 +2348,22 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
 /* -------------------------------------------------------------------- */
 /*      Do we have a lattice table?                                     */
 /* -------------------------------------------------------------------- */
-    if (SWfieldinfo(hSW, "LatticePoint", &iRank, aiDimSizes,
+    void *pLatticeX = NULL;
+    void *pLatticeY = NULL;
+    int32 iLatticeType;
+    int32 iLatticeDataSize = 0;
+    if (SWfieldinfo(hSW, "LatticePoint", &l_iRank, l_aiDimSizes,
                     &iLatticeType, szGeoDimList) == 0
-        && iRank == 3
-        && nXPoints == aiDimSizes[1]
-        && nYPoints == aiDimSizes[0]
-        && aiDimSizes[2] == 2 )
+        && l_iRank == 3
+        && nXPoints == l_aiDimSizes[1]
+        && nYPoints == l_aiDimSizes[0]
+        && l_aiDimSizes[2] == 2 )
     {
-        int32   iStart[H4_MAX_NC_DIMS], iEdges[H4_MAX_NC_DIMS];
-
         iLatticeDataSize =
             GetDataTypeSize( iLatticeType );
 
+        int32 iStart[H4_MAX_NC_DIMS];
+        int32 iEdges[H4_MAX_NC_DIMS];
         iStart[1] = 0;
         iEdges[1] = nXPoints;
 
@@ -2320,7 +2401,8 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
 /* -------------------------------------------------------------------- */
     const char *pszGEOL_AS_GCPS = CPLGetConfigOption( "GEOL_AS_GCPS",
                                                       "PARTIAL" );
-    int iGCPStepX, iGCPStepY;
+    int iGCPStepX;
+    int iGCPStepY;
 
     if( EQUAL(pszGEOL_AS_GCPS,"NONE") )
     {
@@ -2332,9 +2414,9 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
     }
     else
     {
-        // aim for 10x10 grid or so.
-        iGCPStepX = MAX(1,((nXPoints-1) / 11));
-        iGCPStepY = MAX(1,((nYPoints-1) / 11));
+        // Aim for 10x10 grid or so.
+        iGCPStepX = std::max( static_cast<int32>(1), ((nXPoints-1) / 11) );
+        iGCPStepY = std::max( static_cast<int32>(1), ((nYPoints-1) / 11) );
     }
 
 /* -------------------------------------------------------------------- */
@@ -2400,8 +2482,8 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
                       pszEllipsoidLine, pszEllipsoid );
 #endif
 
-            // Transform all mnemonical codes in the values.
-            int i, nParms;
+            // Transform all mnemonic codes in the values.
+            int nParms;
             // Projection is UTM by default
             long iProjSys = (pszProj) ?
                 USGSMnemonicToCode(pszProj) : 1L;
@@ -2419,16 +2501,16 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
                     iEllipsoid = 8L;
             }
 
-            double adfProjParms[15];
             char **papszParms = (pszParms) ?
                 CSLTokenizeString2( pszParms, ",",
                                     CSLT_HONOURSTRINGS ) : NULL;
             nParms = CSLCount(papszParms);
             if (nParms >= 15)
                 nParms = 15;
-            for (i = 0; i < nParms; i++)
+            double adfProjParms[15];
+            for( int i = 0; i < nParms; i++)
                 adfProjParms[i] = CPLAtof( papszParms[i] );
-            for (; i < 15; i++)
+            for ( int i = nParms; i < 15; i++)
                 adfProjParms[i] = 0.0;
 
             // Create projection definition
@@ -2448,14 +2530,13 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
         else if ( eProduct == PROD_ASTER_L3 )
         {
             double  dfCenterX, dfCenterY;
-            int     iZone;
 
             ReadCoordinates( CSLFetchNameValue(
                                  papszGlobalMetadata, "SCENECENTER" ),
                              &dfCenterY, &dfCenterX );
 
             // Calculate UTM zone from scene center coordinates
-            iZone = 30 + (int) ((dfCenterX + 6.0) / 6.0);
+            const int iZone = 30 + static_cast<int>( (dfCenterX + 6.0) / 6.0 );
 
             // Create projection definition
             if( dfCenterY > 0 )
@@ -2482,22 +2563,29 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
             nGCPCount = (((nXPoints-1) / iGCPStepX) + 1)
                 * (((nYPoints-1) / iGCPStepY) + 1);
 
-            pasGCPList = (GDAL_GCP *) CPLCalloc( nGCPCount, sizeof( GDAL_GCP ) );
+            pasGCPList = reinterpret_cast<GDAL_GCP *>(
+                CPLCalloc( nGCPCount, sizeof( GDAL_GCP ) ) );
             GDALInitGCPs( nGCPCount, pasGCPList );
 
             int iGCP = 0;
-            for ( i = 0; i < nYPoints; i += iGCPStepY )
+            for( int i = 0; i < nYPoints; i += iGCPStepY )
             {
-                for ( j = 0; j < nXPoints; j += iGCPStepX )
+                for( int j = 0; j < nXPoints; j += iGCPStepX )
                 {
                     int iGeoOff =  i * nXPoints + j;
 
                     pasGCPList[iGCP].dfGCPX =
-                        AnyTypeToDouble(iWrkNumType,
-                                        (void *)((char*)pLong+ iGeoOff*iDataSize));
+                        AnyTypeToDouble(
+                            iWrkNumType,
+                            reinterpret_cast<void *>(
+                                reinterpret_cast<char *>( pLong )
+                                + iGeoOff*iDataSize));
                     pasGCPList[iGCP].dfGCPY =
-                        AnyTypeToDouble(iWrkNumType,
-                                        (void *)((char*)pLat + iGeoOff*iDataSize));
+                        AnyTypeToDouble(
+                            iWrkNumType,
+                            reinterpret_cast<void *>(
+                                reinterpret_cast<char*>( pLat )
+                                + iGeoOff*iDataSize));
 
                     // GCPs in Level 1A/1B dataset are in geocentric
                     // coordinates. Convert them in geodetic (we
@@ -2521,13 +2609,17 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
                     if ( pLatticeX && pLatticeY )
                     {
                         pasGCPList[iGCP].dfGCPPixel =
-                            AnyTypeToDouble(iLatticeType,
-                                            (void *)((char *)pLatticeX
-                                                     + iGeoOff*iLatticeDataSize))+0.5;
+                            AnyTypeToDouble(
+                                iLatticeType,
+                                reinterpret_cast<void *>(
+                                    reinterpret_cast<char *>( pLatticeX )
+                                    + iGeoOff*iLatticeDataSize ) ) + 0.5;
                         pasGCPList[iGCP].dfGCPLine =
-                            AnyTypeToDouble(iLatticeType,
-                                            (void *)((char *)pLatticeY
-                                                     + iGeoOff*iLatticeDataSize))+0.5;
+                            AnyTypeToDouble(
+                                iLatticeType,
+                                reinterpret_cast<void *>(
+                                    reinterpret_cast<char *>( pLatticeY )
+                                    + iGeoOff*iLatticeDataSize ) ) + 0.5;
                     }
                     else if ( paiOffset && paiIncrement )
                     {
@@ -2552,10 +2644,9 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
             && iLatDim != -1 && iLongDim != -1
             && iPixelDim != -1 && iLineDim != -1 )
         {
-            CPLString  osWrk;
-
             SetMetadataItem( "SRS", pszGCPProjection, "GEOLOCATION" );
 
+            CPLString  osWrk;
             osWrk.Printf( "HDF4_EOS:EOS_SWATH_GEOL:\"%s\":%s:%s",
                           pszFilename, pszSubdatasetName,
                           papszGeolocations[iLongDim] );
@@ -2570,14 +2661,17 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
 
             if ( paiOffset && paiIncrement )
             {
-                osWrk.Printf( "%ld", (long)paiOffset[iPixelDim] );
+                osWrk.Printf( "%ld",
+                              static_cast<long>( paiOffset[iPixelDim] ) );
                 SetMetadataItem( "PIXEL_OFFSET", osWrk, "GEOLOCATION" );
-                osWrk.Printf( "%ld", (long)paiIncrement[iPixelDim] );
+                osWrk.Printf( "%ld",
+                              static_cast<long>( paiIncrement[iPixelDim] ) );
                 SetMetadataItem( "PIXEL_STEP", osWrk, "GEOLOCATION" );
 
-                osWrk.Printf( "%ld", (long)paiOffset[iLineDim] );
+                osWrk.Printf( "%ld", static_cast<long>( paiOffset[iLineDim] ) );
                 SetMetadataItem( "LINE_OFFSET", osWrk, "GEOLOCATION" );
-                osWrk.Printf( "%ld", (long)paiIncrement[iLineDim] );
+                osWrk.Printf( "%ld",
+                              static_cast<long>( paiIncrement[iLineDim] ) );
                 SetMetadataItem( "LINE_STEP", osWrk, "GEOLOCATION" );
             }
         }
@@ -2614,31 +2708,27 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
 
 GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 {
-    int     i;
-
-    if( !EQUALN( poOpenInfo->pszFilename, "HDF4_SDS:", 9 ) &&
-        !EQUALN( poOpenInfo->pszFilename, "HDF4_GR:", 8 ) &&
-        !EQUALN( poOpenInfo->pszFilename, "HDF4_GD:", 8 ) &&
-        !EQUALN( poOpenInfo->pszFilename, "HDF4_EOS:", 9 ) )
+    if( !STARTS_WITH_CI(poOpenInfo->pszFilename, "HDF4_SDS:") &&
+        !STARTS_WITH_CI(poOpenInfo->pszFilename, "HDF4_GR:") &&
+        !STARTS_WITH_CI(poOpenInfo->pszFilename, "HDF4_GD:") &&
+        !STARTS_WITH_CI(poOpenInfo->pszFilename, "HDF4_EOS:") )
         return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    char                **papszSubdatasetName;
-    HDF4ImageDataset    *poDS;
-
-    poDS = new HDF4ImageDataset( );
     if( poOpenInfo->fpL != NULL )
     {
         VSIFCloseL(poOpenInfo->fpL);
         poOpenInfo->fpL = NULL;
     }
-    
+
+    HDF4ImageDataset *poDS = new HDF4ImageDataset( );
     CPLMutexHolderD(&hHDF4Mutex);
 
-    papszSubdatasetName = CSLTokenizeString2( poOpenInfo->pszFilename,
-                                              ":", CSLT_HONOURSTRINGS | CSLT_PRESERVEESCAPES);
+    char **papszSubdatasetName
+        = CSLTokenizeString2( poOpenInfo->pszFilename,
+                              ":", CSLT_HONOURSTRINGS | CSLT_PRESERVEESCAPES);
     if ( CSLCount( papszSubdatasetName ) != 4
          && CSLCount( papszSubdatasetName ) != 5
          && CSLCount( papszSubdatasetName ) != 6 )
@@ -2655,8 +2745,10 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
     /* -------------------------------------------------------------------- */
     if (strlen(papszSubdatasetName[2]) == 1)
     {
-        char* pszFilename = (char*) CPLMalloc( 2 + strlen(papszSubdatasetName[3]) + 1);
-        sprintf(pszFilename, "%s:%s", papszSubdatasetName[2], papszSubdatasetName[3]);
+        const size_t nLen = 2 + strlen(papszSubdatasetName[3]) + 1;
+        char* pszFilename = reinterpret_cast<char *>(
+            CPLMalloc( nLen ) );
+        snprintf(pszFilename, nLen, "%s:%s", papszSubdatasetName[2], papszSubdatasetName[3]);
         CPLFree(papszSubdatasetName[2]);
         CPLFree(papszSubdatasetName[3]);
         papszSubdatasetName[2] = pszFilename;
@@ -2712,9 +2804,7 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Collect the remain (post filename) components to treat as       */
 /*      the subdataset name.                                            */
 /* -------------------------------------------------------------------- */
-    CPLString osSubdatasetName;
-
-    osSubdatasetName = papszSubdatasetName[3];
+    CPLString osSubdatasetName = papszSubdatasetName[3];
     if( papszSubdatasetName[4] != NULL )
     {
         osSubdatasetName += ":";
@@ -2724,7 +2814,6 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Try opening the dataset.                                        */
 /* -------------------------------------------------------------------- */
-    int32       iAttribute, nValues, iAttrNumType;
     double      dfNoData = 0, dfScale = 1, dfOffset = 0;
     int         bNoDataSet = FALSE, bHaveScale = FALSE, bHaveOffset = FALSE;
     const char  *pszUnits = NULL, *pszDescription = NULL;
@@ -2734,7 +2823,6 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if ( poDS->iDatasetType == HDF4_EOS )
     {
-        poDS->pszSubdatasetName = CPLStrdup( papszSubdatasetName[3] );
         if (papszSubdatasetName[4] == NULL)
         {
             CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
@@ -2742,6 +2830,7 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
             CPLAcquireMutex(hHDF4Mutex, 1000.0);
             return NULL;
         }
+        poDS->pszSubdatasetName = CPLStrdup( papszSubdatasetName[3] );
         poDS->pszFieldName = CPLStrdup( papszSubdatasetName[4] );
     }
     else
@@ -2752,8 +2841,6 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
     {
       case HDF4_EOS:
       {
-          void    *pNoDataValue = NULL;
-
           switch ( poDS->iSubdatasetType )
           {
 
@@ -2763,9 +2850,6 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
             case H4ST_EOS_SWATH:
             case H4ST_EOS_SWATH_GEOL:
             {
-                int32   hSW;
-                char    *pszDimList = NULL;
-
                 if( poOpenInfo->eAccess == GA_ReadOnly )
                     poDS->hHDF4 = SWopen( poDS->pszFilename, DFACC_READ );
                 else
@@ -2773,7 +2857,8 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 
                 if( poDS->hHDF4 <= 0 )
                 {
-                    CPLDebug( "HDF4Image", "Can't open file \"%s\" for swath reading",
+                    CPLDebug( "HDF4Image",
+                              "Can't open file \"%s\" for swath reading",
                               poDS->pszFilename );
                     CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
                     delete poDS;
@@ -2781,7 +2866,8 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
                     return( NULL );
                 }
 
-                hSW = SWattach( poDS->hHDF4, poDS->pszSubdatasetName );
+                const int32 hSW
+                    = SWattach( poDS->hHDF4, poDS->pszSubdatasetName );
                 if( hSW < 0 )
                 {
                     CPLDebug( "HDF4Image", "Can't attach to subdataset %s",
@@ -2808,7 +2894,8 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
                     return NULL;
                 }
 
-                pszDimList = (char *)CPLMalloc( nStrBufSize + 1 );
+                char *pszDimList = reinterpret_cast<char *>(
+                    CPLMalloc( nStrBufSize + 1 ) );
                 if ( SWfieldinfo( hSW, poDS->pszFieldName, &poDS->iRank,
                                   poDS->aiDimSizes, &poDS->iNumType,
                                   pszDimList ) < 0 )
@@ -2821,11 +2908,13 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
                     return NULL;
                 }
                 pszDimList[nStrBufSize] = '\0';
+
 #ifdef DEBUG
                 CPLDebug( "HDF4Image",
                           "List of dimensions in swath \"%s\": %s",
                           poDS->pszFieldName, pszDimList );
 #endif
+
                 poDS->GetImageDimensions( pszDimList );
 
 #ifdef DEBUG
@@ -2837,13 +2926,14 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*  Fetch metadata.                                                     */
 /* -------------------------------------------------------------------- */
-                if( poDS->iSubdatasetType == H4ST_EOS_SWATH ) /* Not H4ST_EOS_SWATH_GEOL */
+                // Not H4ST_EOS_SWATH_GEOL.
+                if( poDS->iSubdatasetType == H4ST_EOS_SWATH )
                     poDS->GetSwatAttrs( hSW );
 
 /* -------------------------------------------------------------------- */
 /*  Fetch NODATA value.                                                 */
 /* -------------------------------------------------------------------- */
-                pNoDataValue =
+                void *pNoDataValue =
                     CPLMalloc( poDS->GetDataTypeSize(poDS->iNumType) );
                 if ( SWgetfillvalue( hSW, poDS->pszFieldName,
                                      pNoDataValue ) != -1 )
@@ -2868,7 +2958,8 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Handle Geolocation processing.                                  */
 /* -------------------------------------------------------------------- */
-                if( poDS->iSubdatasetType == H4ST_EOS_SWATH ) /* Not H4ST_SWATH_GEOL */
+                // Not H4ST_SWATH_GEOL.
+                if( poDS->iSubdatasetType == H4ST_EOS_SWATH )
                 {
                     char **papszDimList =
                         CSLTokenizeString2( pszDimList, ",",
@@ -2894,11 +2985,6 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
             case H4ST_EOS_GRID:
             {
-                int32   hGD, iProjCode = 0, iZoneCode = 0, iSphereCode = 0;
-                int32   nXSize, nYSize;
-                char    szDimList[8192];
-                double  adfUpLeft[2], adfLowRight[2], adfProjParms[15];
-
                 if( poOpenInfo->eAccess == GA_ReadOnly )
                     poDS->hHDF4 = GDopen( poDS->pszFilename, DFACC_READ );
                 else
@@ -2906,7 +2992,8 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 
                 if( poDS->hHDF4 <= 0 )
                 {
-                    CPLDebug( "HDF4Image", "Can't open file \"%s\" for grid reading",
+                    CPLDebug( "HDF4Image",
+                              "Can't open file \"%s\" for grid reading",
                               poDS->pszFilename );
                     CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
                     delete poDS;
@@ -2914,11 +3001,13 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
                     return( NULL );
                 }
 
-                hGD = GDattach( poDS->hHDF4, poDS->pszSubdatasetName );
+                const int32 hGD
+                    = GDattach( poDS->hHDF4, poDS->pszSubdatasetName );
 
 /* -------------------------------------------------------------------- */
 /*      Decode the dimension map.                                       */
 /* -------------------------------------------------------------------- */
+                char szDimList[N_BUF_SIZE];
                 GDfieldinfo( hGD, poDS->pszFieldName, &poDS->iRank,
                              poDS->aiDimSizes, &poDS->iNumType, szDimList );
 #ifdef DEBUG
@@ -2929,30 +3018,39 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
                 poDS->GetImageDimensions( szDimList );
 
                 int32 tilecode, tilerank;
-                if( GDtileinfo( hGD , poDS->pszFieldName , &tilecode, &tilerank, NULL ) == 0 )
+                if( GDtileinfo( hGD, poDS->pszFieldName, &tilecode, &tilerank,
+                                NULL ) == 0 )
                 {
                     if ( tilecode == HDFE_TILE )
                     {
-                        int32 *tiledims = NULL;
-                        tiledims = (int32 *) CPLCalloc( tilerank , sizeof( int32 ) );
-                        GDtileinfo( hGD , poDS->pszFieldName , &tilecode, &tilerank, tiledims );
+                        int32 *tiledims = reinterpret_cast<int32 *>(
+                            CPLCalloc( tilerank , sizeof( int32 ) ) );
+                        GDtileinfo( hGD, poDS->pszFieldName, &tilecode,
+                                    &tilerank, tiledims );
                         if ( ( tilerank == 2 ) && ( poDS->iRank == tilerank  ) )
                         {
                             poDS->nBlockPreferredXSize = tiledims[1];
                             poDS->nBlockPreferredYSize = tiledims[0];
                             poDS->bReadTile = true;
 #ifdef DEBUG
-                            CPLDebug( "HDF4_EOS:EOS_GRID:","tilerank in grid %s: %d",
-                                      poDS->pszFieldName , (int)tilerank );
-                            CPLDebug( "HDF4_EOS:EOS_GRID:","tiledimens in grid %s: %d,%d",
-                                      poDS->pszFieldName , (int)tiledims[0] , (int)tiledims[1] );
+                            CPLDebug( "HDF4_EOS:EOS_GRID:",
+                                      "tilerank in grid %s: %d",
+                                      poDS->pszFieldName,
+                                      static_cast<int>( tilerank ) );
+                            CPLDebug( "HDF4_EOS:EOS_GRID:",
+                                      "tiledimens in grid %s: %d,%d",
+                                      poDS->pszFieldName,
+                                      static_cast<int>( tiledims[0] ),
+                                      static_cast<int>( tiledims[1] ) );
 #endif
                         }
 #ifdef DEBUG
                         else
                         {
-                                CPLDebug( "HDF4_EOS:EOS_GRID:","tilerank in grid %s: %d not supported",
-                                          poDS->pszFieldName , (int)tilerank );
+                            CPLDebug( "HDF4_EOS:EOS_GRID:",
+                                      "tilerank in grid %s: %d not supported",
+                                      poDS->pszFieldName,
+                                      static_cast<int>( tilerank ) );
                         }
 #endif
                         CPLFree(tiledims);
@@ -2960,22 +3058,30 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
                     else
                     {
 #ifdef DEBUG
-                        CPLDebug( "HDF4_EOS:EOS_GRID:","tilecode == HDFE_NOTILE in grid %s: %d",
-                                poDS->pszFieldName ,
-                                (int)poDS->iRank );
+                        CPLDebug( "HDF4_EOS:EOS_GRID:",
+                                  "tilecode == HDFE_NOTILE in grid %s: %d",
+                                  poDS->pszFieldName ,
+                                  static_cast<int>( poDS->iRank ) );
 #endif
                     }
                 }
+
 #ifdef DEBUG
                 else
                 {
-                    CPLDebug( "HDF4_EOS:EOS_GRID:","ERROR GDtileinfo %s", poDS->pszFieldName );
+                    CPLDebug( "HDF4_EOS:EOS_GRID:", "ERROR GDtileinfo %s",
+                              poDS->pszFieldName );
                 }
 #endif
 
 /* -------------------------------------------------------------------- */
 /*      Fetch projection information                                    */
 /* -------------------------------------------------------------------- */
+                int32 iProjCode = 0;
+                int32 iZoneCode = 0;
+                int32 iSphereCode = 0;
+                double adfProjParms[15];
+
                 if ( GDprojinfo( hGD, &iProjCode, &iZoneCode,
                                  &iSphereCode, adfProjParms) >= 0 )
                 {
@@ -2984,8 +3090,9 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
                               "Grid projection: "
                               "projection code: %ld, zone code %ld, "
                               "sphere code %ld",
-                              (long)iProjCode, (long)iZoneCode,
-                              (long)iSphereCode );
+                              static_cast<long>( iProjCode ),
+                              static_cast<long>( iZoneCode ),
+                              static_cast<long>( iSphereCode ) );
 #endif
                     poDS->oSRS.importFromUSGS( iProjCode, iZoneCode,
                                                adfProjParms, iSphereCode,
@@ -2999,6 +3106,10 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Fetch geotransformation matrix                                  */
 /* -------------------------------------------------------------------- */
+                int32 nXSize;
+                int32 nYSize;
+                double adfUpLeft[2];
+                double adfLowRight[2];
                 if ( GDgridinfo( hGD, &nXSize, &nYSize,
                                  adfUpLeft, adfLowRight ) >= 0 )
                 {
@@ -3010,7 +3121,8 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
                               "cols %ld, rows %ld",
                               adfUpLeft[0], adfUpLeft[1],
                               adfLowRight[0], adfLowRight[1],
-                              (long)nXSize, (long)nYSize );
+                              static_cast<long>( nXSize ),
+                              static_cast<long>( nYSize ) );
 #endif
                     if ( iProjCode )
                     {
@@ -3051,7 +3163,7 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Fetch NODATA value.                                             */
 /* -------------------------------------------------------------------- */
-                pNoDataValue =
+                void *pNoDataValue =
                     CPLMalloc( poDS->GetDataTypeSize(poDS->iNumType) );
                 if ( GDgetfillvalue( hGD, poDS->pszFieldName,
                                      pNoDataValue ) != -1 )
@@ -3090,7 +3202,7 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
               if ( pszTmp )
               {
                   dfScale = CPLAtof( pszTmp );
-                  // some producers (ie. lndcsm from LEDAPS) emit
+                  // some producers (i.e. lndcsm from LEDAPS) emit
                   // files with scale_factor=0 which is crazy to carry
                   // through.
                   if( dfScale == 0.0 )
@@ -3120,10 +3232,9 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
       case HDF4_SDS:
       {
-          int32 iSDS;
 
-          // Attempt to increase maximum number of opened HDF files
 #ifdef HDF4_HAS_MAXOPENFILES
+          // Attempt to increase maximum number of opened HDF files
           intn  nCurrMax, nSysLimit;
 
           if ( SDget_maxopenfiles(&nCurrMax, &nSysLimit) >= 0
@@ -3163,9 +3274,8 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
               return NULL;
           }
 
-          int32   nDatasets, nAttrs;
-
-          if ( SDfileinfo( poDS->hSD, &nDatasets, &nAttrs ) != 0 )
+          int32   nDatasets, l_nAttrs;
+          if ( SDfileinfo( poDS->hSD, &nDatasets, &l_nAttrs ) != 0 )
           {
               CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
               delete poDS;
@@ -3177,7 +3287,7 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
           {
               CPLError(CE_Failure, CPLE_AppDefined,
                        "Subdataset index should be between 0 and %ld",
-                       (long int)nDatasets - 1);
+                       static_cast<long int>( nDatasets ) - 1);
               CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
               delete poDS;
               CPLAcquireMutex(hHDF4Mutex, 1000.0);
@@ -3185,7 +3295,7 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
           }
 
           memset( poDS->aiDimSizes, 0, sizeof(int32) * H4_MAX_VAR_DIMS );
-          iSDS = SDselect( poDS->hSD, poDS->iDataset );
+          const int32 iSDS = SDselect( poDS->hSD, poDS->iDataset );
           SDgetinfo( iSDS, poDS->szName, &poDS->iRank, poDS->aiDimSizes,
                      &poDS->iNumType, &poDS->nAttrs);
 
@@ -3193,9 +3303,11 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
           poDS->papszLocalMetadata =
               CSLDuplicate( poDS->papszGlobalMetadata );
 
-          for ( iAttribute = 0; iAttribute < poDS->nAttrs; iAttribute++ )
+          for( int32 iAttribute = 0; iAttribute < poDS->nAttrs; iAttribute++ )
           {
               char  szAttrName[H4_MAX_NC_NAME];
+              int32 iAttrNumType;
+              int32 nValues;
               SDattrinfo( iSDS, iAttribute, szAttrName,
                           &iAttrNumType, &nValues );
               poDS->papszLocalMetadata =
@@ -3211,8 +3323,10 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
           CPLDebug( "HDF4Image",
                     "aiDimSizes[0]=%ld, aiDimSizes[1]=%ld, "
                     "aiDimSizes[2]=%ld, aiDimSizes[3]=%ld",
-                    (long)poDS->aiDimSizes[0], (long)poDS->aiDimSizes[1],
-                    (long)poDS->aiDimSizes[2], (long)poDS->aiDimSizes[3] );
+                    static_cast<long>( poDS->aiDimSizes[0] ),
+                    static_cast<long>( poDS->aiDimSizes[1] ),
+                    static_cast<long>( poDS->aiDimSizes[2] ),
+                    static_cast<long>( poDS->aiDimSizes[3] ) );
 #endif
 
           switch( poDS->iRank )
@@ -3228,7 +3342,7 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
               poDS->iYDim = 0;
               break;
             case 3:
-              /* FIXME ? We should probably remove the following test as there are valid datasets */
+              /* FIXME: We should probably remove the following test as there are valid datasets */
               /* where the height is lower than the band number : for example
                  http://www.iapmw.unibe.ch/research/projects/FriOWL/data/otd/LISOTD_HRAC_V2.2.hdf */
               /* which is a 720x360 x 365 bands */
@@ -3256,7 +3370,6 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
                       poDS->iBandDim = 2;
                       poDS->iXDim = 1;
                       poDS->iYDim = 0;
-
                   }
               }
               poDS->nBandCount = poDS->aiDimSizes[poDS->iBandDim];
@@ -3351,9 +3464,10 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
         // We will duplicate global metadata for every subdataset
         poDS->papszLocalMetadata = CSLDuplicate( poDS->papszGlobalMetadata );
 
-        for ( iAttribute = 0; iAttribute < poDS->nAttrs; iAttribute++ )
+        for( int32 iAttribute = 0; iAttribute < poDS->nAttrs; iAttribute++ )
         {
             char    szAttrName[H4_MAX_NC_NAME];
+            int32 nValues, iAttrNumType;
             GRattrinfo( poDS->iGR, iAttribute, szAttrName,
                         &iAttrNumType, &nValues );
             poDS->papszLocalMetadata =
@@ -3364,7 +3478,6 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
         }
         poDS->SetMetadata( poDS->papszLocalMetadata, "" );
         // Read colour table
-        GDALColorEntry oEntry;
 
         poDS->iPal = GRgetlutid ( poDS->iGR, poDS->iDataset );
         if ( poDS->iPal != -1 )
@@ -3373,7 +3486,8 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
                           &poDS->iPalInterlaceMode, &poDS->nPalEntries );
             GRreadlut( poDS->iPal, poDS->aiPaletteData );
             poDS->poColorTable = new GDALColorTable();
-            for( i = 0; i < N_COLOR_ENTRIES; i++ )
+            GDALColorEntry oEntry;
+            for( int i = 0; i < N_COLOR_ENTRIES; i++ )
             {
                 oEntry.c1 = poDS->aiPaletteData[i][0];
                 oEntry.c2 = poDS->aiPaletteData[i][1];
@@ -3421,7 +3535,7 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    for( i = 1; i <= poDS->nBandCount; i++ )
+    for( int i = 1; i <= poDS->nBandCount; i++ )
     {
         HDF4ImageRasterBand *poBand =
             new HDF4ImageRasterBand( poDS, i,
@@ -3451,9 +3565,6 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      HDF product has its own structure.                              */
 /* -------------------------------------------------------------------- */
 
-    // Variables for reading georeferencing
-    double          dfULX, dfULY, dfLRX, dfLRY;
-
     switch ( poDS->iSubdatasetType )
     {
 /* -------------------------------------------------------------------- */
@@ -3461,24 +3572,21 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
       case H4ST_GDAL:
       {
-          const char  *pszValue;
-
           CPLDebug( "HDF4Image",
                     "Input dataset interpreted as GDAL_HDF4" );
 
-          if ( (pszValue =
-                CSLFetchNameValue(poDS->papszGlobalMetadata,
-                                  "Projection")) )
+          const char  *pszValue =
+            CSLFetchNameValue( poDS->papszGlobalMetadata, "Projection" );
+          if ( pszValue != NULL )
           {
-              if ( poDS->pszProjection )
-                  CPLFree( poDS->pszProjection );
+              CPLFree( poDS->pszProjection );
               poDS->pszProjection = CPLStrdup( pszValue );
           }
           if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata,
-                                             "TransformationMatrix")) )
+                                             "TransformationMatrix")) != NULL )
           {
               int i = 0;
-              char *pszString = (char *) pszValue;
+              char *pszString = const_cast<char *>( pszValue );
               while ( *pszValue && i < 6 )
               {
                   poDS->adfGeoTransform[i++] = CPLStrtod(pszString, &pszString);
@@ -3486,18 +3594,18 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
               }
               poDS->bHasGeoTransform = TRUE;
           }
-          for( i = 1; i <= poDS->nBands; i++ )
+          for( int i = 1; i <= poDS->nBands; i++ )
           {
               if ( (pszValue =
                     CSLFetchNameValue(poDS->papszGlobalMetadata,
-                                      CPLSPrintf("BandDesc%d", i))) )
+                                      CPLSPrintf("BandDesc%d", i))) != NULL )
                   poDS->GetRasterBand( i )->SetDescription( pszValue );
           }
-          for( i = 1; i <= poDS->nBands; i++ )
+          for( int i = 1; i <= poDS->nBands; i++ )
           {
               if ( (pszValue =
                     CSLFetchNameValue(poDS->papszGlobalMetadata,
-                                      CPLSPrintf("NoDataValue%d", i))) )
+                                      CPLSPrintf("NoDataValue%d", i))) != NULL )
                   poDS->GetRasterBand(i)->SetNoDataValue( CPLAtof(pszValue) );
           }
       }
@@ -3512,7 +3620,7 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
           CPLDebug( "HDF4Image", "Input dataset interpreted as SEAWIFS_L3" );
 
           // Read band description
-          for ( i = 1; i <= poDS->nBands; i++ )
+          for ( int i = 1; i <= poDS->nBands; i++ )
           {
               poDS->GetRasterBand( i )->SetDescription(
                   CSLFetchNameValue( poDS->papszGlobalMetadata, "Parameter" ) );
@@ -3532,14 +3640,14 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
               poDS->oSRS.exportToWkt( &poDS->pszProjection );
           }
 
-          dfULX = CPLAtof( CSLFetchNameValue(poDS->papszGlobalMetadata,
-                                             "Westernmost Longitude") );
-          dfULY = CPLAtof( CSLFetchNameValue(poDS->papszGlobalMetadata,
-                                             "Northernmost Latitude") );
-          dfLRX = CPLAtof( CSLFetchNameValue(poDS->papszGlobalMetadata,
-                                             "Easternmost Longitude") );
-          dfLRY = CPLAtof( CSLFetchNameValue(poDS->papszGlobalMetadata,
-                                             "Southernmost Latitude") );
+          double dfULX = CPLAtof( CSLFetchNameValue(poDS->papszGlobalMetadata,
+                                                    "Westernmost Longitude") );
+          double dfULY = CPLAtof( CSLFetchNameValue(poDS->papszGlobalMetadata,
+                                                    "Northernmost Latitude") );
+          double dfLRX = CPLAtof( CSLFetchNameValue(poDS->papszGlobalMetadata,
+                                                    "Easternmost Longitude") );
+          double dfLRY = CPLAtof( CSLFetchNameValue(poDS->papszGlobalMetadata,
+                                                    "Southernmost Latitude") );
           poDS->ToGeoref( &dfULX, &dfULY );
           poDS->ToGeoref( &dfLRX, &dfLRY );
           poDS->adfGeoTransform[0] = dfULX;
@@ -3554,9 +3662,8 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
       }
       break;
 
-
 /* -------------------------------------------------------------------- */
-/*	Generic SDS							*/
+/*      Generic SDS                                                     */
 /* -------------------------------------------------------------------- */
       case H4ST_UNKNOWN:
       {
@@ -3564,8 +3671,7 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
           // This is a coastwatch convention.
           if( CSLFetchNameValue( poDS->papszLocalMetadata, "missing_value" ) )
           {
-              int i;
-              for( i = 1; i <= poDS->nBands; i++ )
+              for( int i = 1; i <= poDS->nBands; i++ )
               {
                   poDS->GetRasterBand(i)->SetNoDataValue(
                       CPLAtof( CSLFetchNameValue(poDS->papszLocalMetadata,
@@ -3577,10 +3683,11 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
           if( CSLFetchNameValue( poDS->papszLocalMetadata, "scale_factor" )
               && CSLFetchNameValue( poDS->papszLocalMetadata, "add_offset" ) )
           {
-              for( i = 1; i <= poDS->nBands; i++ )
+              for( int i = 1; i <= poDS->nBands; i++ )
               {
-                  HDF4ImageRasterBand *poBand =
-                      (HDF4ImageRasterBand *) poDS->GetRasterBand(i);
+                  HDF4ImageRasterBand *poBand
+                      = reinterpret_cast<HDF4ImageRasterBand *>(
+                          poDS->GetRasterBand(i) );
 
                   poBand->bHaveScale = poBand->bHaveOffset = TRUE;
                   poBand->dfScale =
@@ -3590,21 +3697,20 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
                   //poBand->dfOffset = -1 * poBand->dfScale *
                   //  CPLAtof( CSLFetchNameValue( poDS->papszLocalMetadata,
                   //                              "add_offset" ) );
-                  poBand->dfOffset = 
+                  poBand->dfOffset =
                       CPLAtof( CSLFetchNameValue( poDS->papszLocalMetadata,
                                                   "add_offset" ) );
               }
           }
 
-          // this is a modis level3 convention (data from ACT)
-          // Eg data/hdf/act/modis/MODAM2004280160000.L3_NOAA_GMX
+          // This is a modis level3 convention (data from ACT)
+          // e.g. data/hdf/act/modis/MODAM2004280160000.L3_NOAA_GMX
 
           if( CSLFetchNameValue( poDS->papszLocalMetadata,
                                  "scalingSlope" )
               && CSLFetchNameValue( poDS->papszLocalMetadata,
                                     "scalingIntercept" ) )
           {
-              int i;
               CPLString osUnits;
 
               if( CSLFetchNameValue( poDS->papszLocalMetadata,
@@ -3614,10 +3720,11 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
                                                "productUnits" );
               }
 
-              for( i = 1; i <= poDS->nBands; i++ )
+              for( int i = 1; i <= poDS->nBands; i++ )
               {
                   HDF4ImageRasterBand *poBand =
-                      (HDF4ImageRasterBand *) poDS->GetRasterBand(i);
+                      reinterpret_cast<HDF4ImageRasterBand *>(
+                          poDS->GetRasterBand(i) );
 
                   poBand->bHaveScale = poBand->bHaveOffset = TRUE;
                   poBand->dfScale =
@@ -3643,6 +3750,11 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
       break;
 
       default:
+
+#ifdef DEBUG_VERBOSE
+        CPLError( CE_Debug, CPLE_AppDefined,
+                  "Unknown subdata type %d\n", poDS->iSubdatasetType );
+#endif
         break;
     }
 
@@ -3674,12 +3786,6 @@ GDALDataset *HDF4ImageDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Create the dataset.                                             */
 /* -------------------------------------------------------------------- */
-    HDF4ImageDataset    *poDS;
-    const char          *pszSDSName;
-    int                 iBand;
-    int32               iSDS = -1;
-    int32               aiDimSizes[H4_MAX_VAR_DIMS];
-
     if( nBands == 0 )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
@@ -3687,8 +3793,20 @@ GDALDataset *HDF4ImageDataset::Create( const char * pszFilename,
         return NULL;
     }
 
-    poDS = new HDF4ImageDataset();
-    
+    // Try now to create the file to avoid memory leaks if it is
+    // the SDK that fails to do it.
+    VSILFILE* fpVSIL = VSIFOpenL( pszFilename, "wb" );
+    if( fpVSIL == NULL )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                "Failed to create %s.", pszFilename );
+        return NULL;
+    }
+    VSIFCloseL(fpVSIL);
+    VSIUnlink(pszFilename);
+
+    HDF4ImageDataset *poDS = new HDF4ImageDataset();
+
     CPLMutexHolderD(&hHDF4Mutex);
 
 /* -------------------------------------------------------------------- */
@@ -3698,7 +3816,7 @@ GDALDataset *HDF4ImageDataset::Create( const char * pszFilename,
     if ( CSLFetchNameValue( papszOptions, "RANK" ) != NULL &&
          EQUAL( CSLFetchNameValue( papszOptions, "RANK" ), "2" ) )
         poDS->iRank = 2;
-    
+
     poDS->hSD = SDstart( pszFilename, DFACC_CREATE );
     if ( poDS->hSD == -1 )
     {
@@ -3712,13 +3830,18 @@ GDALDataset *HDF4ImageDataset::Create( const char * pszFilename,
     poDS->iXDim = 1;
     poDS->iYDim = 0;
     poDS->iBandDim = 2;
+
+    int32 aiDimSizes[H4_MAX_VAR_DIMS];
     aiDimSizes[poDS->iXDim] = nXSize;
     aiDimSizes[poDS->iYDim] = nYSize;
     aiDimSizes[poDS->iBandDim] = nBands;
 
+    const char *pszSDSName = NULL;
+    int32 iSDS = -1;
+
     if ( poDS->iRank == 2 )
     {
-        for ( iBand = 0; iBand < nBands; iBand++ )
+        for( int iBand = 0; iBand < nBands; iBand++ )
         {
             pszSDSName = CPLSPrintf( "Band%d", iBand );
             switch ( eType )
@@ -3793,14 +3916,23 @@ GDALDataset *HDF4ImageDataset::Create( const char * pszFilename,
                 break;
         }
     }
-    else                                            // Should never happen
+    else
+    {
+        // Should never happen
+        CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+        delete poDS;
+        CPLAcquireMutex(hHDF4Mutex, 1000.0);
         return NULL;
+    }
 
     if ( iSDS < 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Can't create SDS with rank %ld for file %s",
-                  (long)poDS->iRank, pszFilename );
+                  static_cast<long>( poDS->iRank ), pszFilename );
+        CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+        delete poDS;
+        CPLAcquireMutex(hHDF4Mutex, 1000.0);
         return NULL;
     }
 
@@ -3814,13 +3946,13 @@ GDALDataset *HDF4ImageDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    for( iBand = 1; iBand <= nBands; iBand++ )
+    for( int iBand = 1; iBand <= nBands; iBand++ )
         poDS->SetBand( iBand, new HDF4ImageRasterBand( poDS, iBand, eType ) );
 
-    SDsetattr( poDS->hSD, "Signature", DFNT_CHAR8, strlen(pszGDALSignature) + 1,
+    SDsetattr( poDS->hSD, "Signature", DFNT_CHAR8, static_cast<int>(strlen(pszGDALSignature)) + 1,
                pszGDALSignature );
-    
-    return (GDALDataset *) poDS;
+
+    return reinterpret_cast<GDALDataset *>( poDS );
 }
 
 /************************************************************************/
@@ -3830,28 +3962,25 @@ GDALDataset *HDF4ImageDataset::Create( const char * pszFilename,
 void GDALRegister_HDF4Image()
 
 {
-    GDALDriver  *poDriver;
-
-    if( GDALGetDriverByName( "HDF4Image" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "HDF4Image" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "HDF4 Dataset" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_hdf4.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte Int16 UInt16 Int32 UInt32 Float32 Float64" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
+    if( GDALGetDriverByName( "HDF4Image" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "HDF4Image" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "HDF4 Dataset" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_hdf4.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte Int16 UInt16 Int32 UInt32 "
+                               "Float32 Float64" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "   <Option name='RANK' type='int' description='Rank of output SDS'/>"
 "</CreationOptionList>" );
 
-        poDriver->pfnOpen = HDF4ImageDataset::Open;
-        poDriver->pfnCreate = HDF4ImageDataset::Create;
+    poDriver->pfnOpen = HDF4ImageDataset::Open;
+    poDriver->pfnCreate = HDF4ImageDataset::Create;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/hdf5/bagdataset.cpp b/frmts/hdf5/bagdataset.cpp
index b18e3d2..54ded40 100644
--- a/frmts/hdf5/bagdataset.cpp
+++ b/frmts/hdf5/bagdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: bagdataset.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: bagdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Hierarchical Data Format Release 5 (HDF5)
  * Purpose:  Read BAG datasets.
@@ -30,18 +30,15 @@
 
 #include "gh5_convenience.h"
 
+#include "cpl_string.h"
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 #include "gdal_priv.h"
 #include "ogr_spatialref.h"
-#include "cpl_string.h"
-
-CPL_CVSID("$Id: bagdataset.cpp 27942 2014-11-11 00:57:41Z rouault $");
 
-CPL_C_START
-void    GDALRegister_BAG(void);
-CPL_C_END
+CPL_CVSID("$Id: bagdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
-OGRErr OGR_SRS_ImportFromISO19115( OGRSpatialReference *poThis, 
+OGRErr OGR_SRS_ImportFromISO19115( OGRSpatialReference *poThis,
                                    const char *pszISOXML );
 
 /************************************************************************/
@@ -51,7 +48,6 @@ OGRErr OGR_SRS_ImportFromISO19115( OGRSpatialReference *poThis,
 /************************************************************************/
 class BAGDataset : public GDALPamDataset
 {
-
     friend class BAGRasterBand;
 
     hid_t        hHDF5;
@@ -63,11 +59,11 @@ class BAGDataset : public GDALPamDataset
 
     char        *pszXMLMetadata;
     char        *apszMDList[2];
-    
+
 public:
     BAGDataset();
     ~BAGDataset();
-    
+
     virtual CPLErr GetGeoTransform( double * );
     virtual const char *GetProjectionRef(void);
     virtual char      **GetMetadataDomainList();
@@ -97,32 +93,27 @@ class BAGRasterBand : public GDALPamRasterBand
     double      dfMaximum;
 
 public:
-  
     BAGRasterBand( BAGDataset *, int );
     ~BAGRasterBand();
 
     bool                    Initialize( hid_t hDataset, const char *pszName );
 
     virtual CPLErr          IReadBlock( int, int, void * );
-    virtual double	    GetNoDataValue( int * ); 
+    virtual double	    GetNoDataValue( int * );
 
     virtual double GetMinimum( int *pbSuccess = NULL );
-    virtual double GetMaximum(int *pbSuccess = NULL );
+    virtual double GetMaximum( int *pbSuccess = NULL );
 };
 
 /************************************************************************/
 /*                           BAGRasterBand()                            */
 /************************************************************************/
-BAGRasterBand::BAGRasterBand( BAGDataset *poDS, int nBand )
-
+BAGRasterBand::BAGRasterBand( BAGDataset *poDS_, int nBand_ ) :
+    hDatasetID(-1), native(-1), dataspace(-1), bMinMaxSet(false),
+    dfMinimum(0.0), dfMaximum(0.0)
 {
-    this->poDS       = poDS;
-    this->nBand      = nBand;
-    
-    hDatasetID = -1;
-    dataspace = -1;
-    native = -1;
-    bMinMaxSet = false;
+    poDS = poDS_;
+    nBand = nBand_;
 }
 
 /************************************************************************/
@@ -145,18 +136,27 @@ BAGRasterBand::~BAGRasterBand()
 /*                             Initialize()                             */
 /************************************************************************/
 
-bool BAGRasterBand::Initialize( hid_t hDatasetID, const char *pszName )
+bool BAGRasterBand::Initialize( hid_t hDatasetIDIn, const char *pszName )
 
 {
     SetDescription( pszName );
 
-    this->hDatasetID = hDatasetID;
-
-    hid_t datatype     = H5Dget_type( hDatasetID );
-    dataspace          = H5Dget_space( hDatasetID );
-    int n_dims         = H5Sget_simple_extent_ndims( dataspace );
-    native             = H5Tget_native_type( datatype, H5T_DIR_ASCEND );
-    hsize_t dims[3], maxdims[3];
+    hDatasetID = hDatasetIDIn;
+
+    const hid_t datatype = H5Dget_type( hDatasetIDIn );
+    dataspace = H5Dget_space( hDatasetIDIn );
+    const int n_dims = H5Sget_simple_extent_ndims( dataspace );
+    native = H5Tget_native_type( datatype, H5T_DIR_ASCEND );
+    hsize_t dims[3] = {
+      static_cast<hsize_t>(0),
+      static_cast<hsize_t>(0),
+      static_cast<hsize_t>(0)
+    };
+    hsize_t maxdims[3] = {
+      static_cast<hsize_t>(0),
+      static_cast<hsize_t>(0),
+      static_cast<hsize_t>(0)
+    };
 
     eDataType = GH5_GetDataType( native );
 
@@ -164,8 +164,8 @@ bool BAGRasterBand::Initialize( hid_t hDatasetID, const char *pszName )
     {
         H5Sget_simple_extent_dims( dataspace, dims, maxdims );
 
-        nRasterXSize = (int) dims[1];
-        nRasterYSize = (int) dims[0];
+        nRasterXSize = static_cast<int>(dims[1]);
+        nRasterYSize = static_cast<int>(dims[0]);
     }
     else
     {
@@ -181,27 +181,31 @@ bool BAGRasterBand::Initialize( hid_t hDatasetID, const char *pszName )
 /*      Check for chunksize, and use it as blocksize for optimized      */
 /*      reading.                                                        */
 /* -------------------------------------------------------------------- */
-    hid_t listid = H5Dget_create_plist( hDatasetID );
+    const hid_t listid = H5Dget_create_plist( hDatasetIDIn );
     if (listid>0)
     {
         if(H5Pget_layout(listid) == H5D_CHUNKED)
         {
-            hsize_t panChunkDims[3];
-            int nDimSize = H5Pget_chunk(listid, 3, panChunkDims);
-            nBlockXSize  = (int) panChunkDims[nDimSize-1];
-            nBlockYSize  = (int) panChunkDims[nDimSize-2];
+            hsize_t panChunkDims[3] = {
+              static_cast<hsize_t>(0),
+              static_cast<hsize_t>(0),
+              static_cast<hsize_t>(0)
+            };
+            const int nDimSize = H5Pget_chunk(listid, 3, panChunkDims);
+            nBlockXSize  = static_cast<int>(panChunkDims[nDimSize-1]);
+            nBlockYSize  = static_cast<int>(panChunkDims[nDimSize-2]);
         }
 
         int nfilters = H5Pget_nfilters( listid );
 
-        H5Z_filter_t filter;
-        char         name[120];
+        char name[120];
         size_t       cd_nelmts = 20;
         unsigned int cd_values[20];
         unsigned int flags;
-        for (int i = 0; i < nfilters; i++) 
+        for (int i = 0; i < nfilters; i++)
         {
-          filter = H5Pget_filter(listid, i, &flags, (size_t *)&cd_nelmts, cd_values, 120, name);
+          const H5Z_filter_t filter =
+              H5Pget_filter(listid, i, &flags, &cd_nelmts, cd_values, 120, name);
           if (filter == H5Z_FILTER_DEFLATE)
             poDS->SetMetadataItem( "COMPRESSION", "DEFLATE", "IMAGE_STRUCTURE" );
           else if (filter == H5Z_FILTER_NBIT)
@@ -218,16 +222,16 @@ bool BAGRasterBand::Initialize( hid_t hDatasetID, const char *pszName )
 /* -------------------------------------------------------------------- */
 /*      Load min/max information.                                       */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszName,"elevation") 
-        && GH5_FetchAttribute( hDatasetID, "Maximum Elevation Value", 
-                            dfMaximum ) 
-        && GH5_FetchAttribute( hDatasetID, "Minimum Elevation Value", 
+    if( EQUAL(pszName,"elevation")
+        && GH5_FetchAttribute( hDatasetIDIn, "Maximum Elevation Value",
+                            dfMaximum )
+        && GH5_FetchAttribute( hDatasetIDIn, "Minimum Elevation Value",
                                dfMinimum ) )
         bMinMaxSet = true;
     else if( EQUAL(pszName,"uncertainty")
-             && GH5_FetchAttribute( hDatasetID, "Maximum Uncertainty Value", 
-                                    dfMaximum ) 
-             && GH5_FetchAttribute( hDatasetID, "Minimum Uncertainty Value", 
+             && GH5_FetchAttribute( hDatasetIDIn, "Maximum Uncertainty Value",
+                                    dfMaximum )
+             && GH5_FetchAttribute( hDatasetIDIn, "Minimum Uncertainty Value",
                                     dfMinimum ) )
     {
         /* Some products where uncertainty band is completely set to nodata */
@@ -235,10 +239,10 @@ bool BAGRasterBand::Initialize( hid_t hDatasetID, const char *pszName )
         if( dfMinimum != 0.0 && dfMaximum != 0.0 )
             bMinMaxSet = true;
     }
-    else if( EQUAL(pszName,"nominal_elevation") 
-             && GH5_FetchAttribute( hDatasetID, "max_value", 
-                                    dfMaximum ) 
-             && GH5_FetchAttribute( hDatasetID, "min_value", 
+    else if( EQUAL(pszName,"nominal_elevation")
+             && GH5_FetchAttribute( hDatasetIDIn, "max_value",
+                                    dfMaximum )
+             && GH5_FetchAttribute( hDatasetIDIn, "min_value",
                                     dfMinimum ) )
         bMinMaxSet = true;
 
@@ -258,8 +262,8 @@ double BAGRasterBand::GetMinimum( int * pbSuccess )
             *pbSuccess = TRUE;
         return dfMinimum;
     }
-    else
-        return GDALRasterBand::GetMinimum( pbSuccess );
+
+    return GDALRasterBand::GetMinimum( pbSuccess );
 }
 
 /************************************************************************/
@@ -275,8 +279,8 @@ double BAGRasterBand::GetMaximum( int * pbSuccess )
             *pbSuccess = TRUE;
         return dfMaximum;
     }
-    else
-        return GDALRasterBand::GetMaximum( pbSuccess );
+
+    return GDALRasterBand::GetMaximum( pbSuccess );
 }
 
 /************************************************************************/
@@ -290,12 +294,12 @@ double BAGRasterBand::GetNoDataValue( int * pbSuccess )
 
     if( EQUAL(GetDescription(),"elevation") )
         return  1000000.0;
-    else if( EQUAL(GetDescription(),"uncertainty") )
+    if( EQUAL(GetDescription(),"uncertainty") )
         return 1000000.0;
-    else if( EQUAL(GetDescription(),"nominal_elevation") )
+    if( EQUAL(GetDescription(),"nominal_elevation") )
         return 1000000.0;
-    else
-        return GDALPamRasterBand::GetNoDataValue( pbSuccess );
+
+    return GDALPamRasterBand::GetNoDataValue( pbSuccess );
 }
 
 /************************************************************************/
@@ -304,52 +308,57 @@ double BAGRasterBand::GetNoDataValue( int * pbSuccess )
 CPLErr BAGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                   void * pImage )
 {
-    herr_t      status;
-    hsize_t     count[3];
-    H5OFFSET_TYPE offset[3];
-    int         nSizeOfData;
-    hid_t       memspace;
-    hsize_t     col_dims[3];
-    hsize_t     rank;
-
-    rank=2;
-
-    offset[0] = MAX(0,nRasterYSize - (nBlockYOff+1)*nBlockYSize);
-    offset[1] = nBlockXOff*nBlockXSize;
-    count[0]  = nBlockYSize;
-    count[1]  = nBlockXSize;
-
-    nSizeOfData = H5Tget_size( native );
+    H5OFFSET_TYPE offset[3] = {
+      static_cast<H5OFFSET_TYPE>(MAX(0, nRasterYSize - (nBlockYOff+1)*nBlockYSize)),
+      static_cast<H5OFFSET_TYPE>(nBlockXOff * nBlockXSize),
+      static_cast<H5OFFSET_TYPE>(0)
+    };
+    hsize_t count[3] = {
+      static_cast<hsize_t>(nBlockYSize),
+      static_cast<hsize_t>(nBlockXSize),
+      static_cast<hsize_t>(0)
+    };
+
+    const int nSizeOfData = static_cast<int>(H5Tget_size( native ));
     memset( pImage,0,nBlockXSize*nBlockYSize*nSizeOfData );
 
 /*  blocksize may not be a multiple of imagesize */
-    count[0]  = MIN( size_t(nBlockYSize), GetYSize() - offset[0]);
-    count[1]  = MIN( size_t(nBlockXSize), GetXSize() - offset[1]);
+    count[0] = MIN( size_t(nBlockYSize), GetYSize() - offset[0] );
+    count[1] = MIN( size_t(nBlockXSize), GetXSize() - offset[1] );
 
     if( nRasterYSize - (nBlockYOff+1)*nBlockYSize < 0 )
     {
-        count[0] += (nRasterYSize - (nBlockYOff+1)*nBlockYSize);
+        count[0] += (nRasterYSize - (nBlockYOff+1)*nBlockYSize );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Select block from file space                                    */
 /* -------------------------------------------------------------------- */
-    status =  H5Sselect_hyperslab( dataspace,
-                                   H5S_SELECT_SET,
-                                   offset, NULL,
-                                   count, NULL );
+    herr_t status =  H5Sselect_hyperslab( dataspace,
+                                          H5S_SELECT_SET,
+                                          offset, NULL,
+                                          count, NULL );
+    if( status < 0 )
+        return CE_Failure;
 
 /* -------------------------------------------------------------------- */
 /*      Create memory space to receive the data                         */
 /* -------------------------------------------------------------------- */
-    col_dims[0]=nBlockYSize;
-    col_dims[1]=nBlockXSize;
-    memspace = H5Screate_simple( (int) rank, col_dims, NULL );
+    hsize_t col_dims[3] = {
+      static_cast<hsize_t>(nBlockYSize),
+      static_cast<hsize_t>(nBlockXSize),
+      static_cast<hsize_t>(0)
+    };
+    hsize_t rank = 2;
+    const hid_t memspace =
+        H5Screate_simple( static_cast<int>(rank), col_dims, NULL );
     H5OFFSET_TYPE mem_offset[3] = {0, 0, 0};
     status =  H5Sselect_hyperslab(memspace,
                                   H5S_SELECT_SET,
                                   mem_offset, NULL,
                                   count, NULL);
+    if( status < 0 )
+        return CE_Failure;
 
     status = H5Dread ( hDatasetID,
                        native,
@@ -363,19 +372,21 @@ CPLErr BAGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
 /*      Y flip the data.                                                */
 /* -------------------------------------------------------------------- */
-    int nLinesToFlip = count[0];
-    int nLineSize = nSizeOfData * nBlockXSize;
-    GByte *pabyTemp = (GByte *) CPLMalloc(nLineSize);
+    const int nLinesToFlip = static_cast<int>(count[0]);
+    const int nLineSize = nSizeOfData * nBlockXSize;
+    GByte *pabyTemp = static_cast<GByte *>(CPLMalloc(nLineSize));
 
     for( int iY = 0; iY < nLinesToFlip/2; iY++ )
     {
-        memcpy( pabyTemp, 
-                ((GByte *)pImage) + iY * nLineSize,
+        memcpy( pabyTemp,
+                reinterpret_cast<GByte *>(pImage) + iY * nLineSize,
                 nLineSize );
-        memcpy( ((GByte *)pImage) + iY * nLineSize,
-                ((GByte *)pImage) + (nLinesToFlip-iY-1) * nLineSize,
+        memcpy( reinterpret_cast<GByte *>(pImage) + iY * nLineSize,
+                (reinterpret_cast<GByte *>(pImage) + (nLinesToFlip-iY-1) *
+                 nLineSize),
                 nLineSize );
-        memcpy( ((GByte *)pImage) + (nLinesToFlip-iY-1) * nLineSize,
+        memcpy( (reinterpret_cast<GByte *>(pImage) + (nLinesToFlip-iY-1) *
+                 nLineSize),
                 pabyTemp,
                 nLineSize );
     }
@@ -391,8 +402,8 @@ CPLErr BAGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                   "H5Dread() failed for block." );
         return CE_Failure;
     }
-    else
-        return CE_None;
+
+    return CE_None;
 }
 
 /************************************************************************/
@@ -405,18 +416,20 @@ CPLErr BAGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /*                             BAGDataset()                             */
 /************************************************************************/
 
-BAGDataset::BAGDataset()
+BAGDataset::BAGDataset() :
+    hHDF5(-1),
+    pszProjection(NULL),
+    pszXMLMetadata(NULL)
 {
-    hHDF5 = -1;
-    pszXMLMetadata = NULL;
-    pszProjection = NULL;
-
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
+
+    apszMDList[0] = NULL;
+    apszMDList[1] = NULL;
 }
 
 /************************************************************************/
@@ -429,8 +442,8 @@ BAGDataset::~BAGDataset( )
     if( hHDF5 >= 0 )
         H5Fclose( hHDF5 );
 
-    CPLFree( pszXMLMetadata );
     CPLFree( pszProjection );
+    CPLFree( pszXMLMetadata );
 }
 
 /************************************************************************/
@@ -476,29 +489,27 @@ GDALDataset *BAGDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The BAG driver does not support update access." );
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Open the file as an HDF5 file.                                  */
 /* -------------------------------------------------------------------- */
-    hid_t hHDF5 = H5Fopen( poOpenInfo->pszFilename, 
+    hid_t hHDF5 = H5Fopen( poOpenInfo->pszFilename,
                            H5F_ACC_RDONLY, H5P_DEFAULT );
 
-    if( hHDF5 < 0 )  
+    if( hHDF5 < 0 )
         return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Confirm it is a BAG dataset by checking for the                 */
 /*      BAG_Root/Bag Version attribute.                                 */
 /* -------------------------------------------------------------------- */
-    hid_t hBagRoot = H5Gopen( hHDF5, "/BAG_root" );
-    hid_t hVersion = -1;
-
-    if( hBagRoot >= 0 )
-        hVersion = H5Aopen_name( hBagRoot, "Bag Version" );
+    const hid_t hBagRoot = H5Gopen( hHDF5, "/BAG_root" );
+    const hid_t hVersion =
+        ( hBagRoot >= 0 ) ? H5Aopen_name( hBagRoot, "Bag Version" ) : -1;
 
     if( hVersion < 0 )
     {
@@ -512,7 +523,7 @@ GDALDataset *BAGDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding dataset.                                 */
 /* -------------------------------------------------------------------- */
-    BAGDataset *poDS = new BAGDataset();
+    BAGDataset * const poDS = new BAGDataset();
 
     poDS->hHDF5 = hHDF5;
 
@@ -530,7 +541,7 @@ GDALDataset *BAGDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Fetch the elevation dataset and attach as a band.               */
 /* -------------------------------------------------------------------- */
     int nNextBand = 1;
-    hid_t hElevation = H5Dopen( hHDF5, "/BAG_root/elevation" );
+    const hid_t hElevation = H5Dopen( hHDF5, "/BAG_root/elevation" );
     if( hElevation < 0 )
     {
         delete poDS;
@@ -554,7 +565,7 @@ GDALDataset *BAGDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Try to do the same for the uncertainty band.                    */
 /* -------------------------------------------------------------------- */
-    hid_t hUncertainty = H5Dopen( hHDF5, "/BAG_root/uncertainty" );
+    const hid_t hUncertainty = H5Dopen( hHDF5, "/BAG_root/uncertainty" );
     BAGRasterBand *poUBand = new BAGRasterBand( poDS, nNextBand );
 
     if( hUncertainty >= 0 && poUBand->Initialize( hUncertainty, "uncertainty") )
@@ -573,7 +584,7 @@ GDALDataset *BAGDataset::Open( GDALOpenInfo * poOpenInfo )
         hNominal = H5Dopen( hHDF5, "/BAG_root/nominal_elevation" );
     } H5E_END_TRY;
 
-    BAGRasterBand *poNBand = new BAGRasterBand( poDS, nNextBand );
+    BAGRasterBand * const poNBand = new BAGRasterBand( poDS, nNextBand );
     if( hNominal >= 0 && poNBand->Initialize( hNominal,
                                               "nominal_elevation" ) )
     {
@@ -581,7 +592,7 @@ GDALDataset *BAGDataset::Open( GDALOpenInfo * poOpenInfo )
     }
     else
         delete poNBand;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Load the XML metadata.                                          */
 /* -------------------------------------------------------------------- */
@@ -611,15 +622,25 @@ void BAGDataset::LoadMetadata()
 /* -------------------------------------------------------------------- */
 /*      Load the metadata from the file.                                */
 /* -------------------------------------------------------------------- */
-    hid_t hMDDS = H5Dopen( hHDF5, "/BAG_root/metadata" );
-    hid_t datatype     = H5Dget_type( hMDDS );
-    hid_t dataspace    = H5Dget_space( hMDDS );
-    hid_t native       = H5Tget_native_type( datatype, H5T_DIR_ASCEND );
-    hsize_t dims[3], maxdims[3];
+    const hid_t hMDDS = H5Dopen( hHDF5, "/BAG_root/metadata" );
+    const hid_t datatype = H5Dget_type( hMDDS );
+    const hid_t dataspace = H5Dget_space( hMDDS );
+    const hid_t native = H5Tget_native_type( datatype, H5T_DIR_ASCEND );
+    hsize_t dims[3] = {
+      static_cast<hsize_t>(0),
+      static_cast<hsize_t>(0),
+      static_cast<hsize_t>(0)
+    };
+    hsize_t maxdims[3] = {
+      static_cast<hsize_t>(0),
+      static_cast<hsize_t>(0),
+      static_cast<hsize_t>(0)
+    };
 
     H5Sget_simple_extent_dims( dataspace, dims, maxdims );
 
-    pszXMLMetadata = (char *) CPLCalloc((int) (dims[0]+1),1);
+    pszXMLMetadata = static_cast<char *>(
+        CPLCalloc(static_cast<int>(dims[0]+1),1));
 
     H5Dread( hMDDS, native, H5S_ALL, dataspace, H5P_DEFAULT, pszXMLMetadata );
 
@@ -641,21 +662,21 @@ void BAGDataset::LoadMetadata()
 
     CPLStripXMLNamespace( psRoot, NULL, TRUE );
 
-    CPLXMLNode *psGeo = CPLSearchXMLNode( psRoot, "=MD_Georectified" );
+    CPLXMLNode * const psGeo = CPLSearchXMLNode( psRoot, "=MD_Georectified" );
 
     if( psGeo != NULL )
     {
-        char **papszCornerTokens = 
-            CSLTokenizeStringComplex( 
+        char **papszCornerTokens =
+            CSLTokenizeStringComplex(
                 CPLGetXMLValue( psGeo, "cornerPoints.Point.coordinates", "" ),
                 " ,", FALSE, FALSE );
 
         if( CSLCount(papszCornerTokens ) == 4 )
         {
-            double dfLLX = CPLAtof( papszCornerTokens[0] );
-            double dfLLY = CPLAtof( papszCornerTokens[1] );
-            double dfURX = CPLAtof( papszCornerTokens[2] );
-            double dfURY = CPLAtof( papszCornerTokens[3] );
+            const double dfLLX = CPLAtof( papszCornerTokens[0] );
+            const double dfLLY = CPLAtof( papszCornerTokens[1] );
+            const double dfURX = CPLAtof( papszCornerTokens[2] );
+            const double dfURY = CPLAtof( papszCornerTokens[3] );
 
             adfGeoTransform[0] = dfLLX;
             adfGeoTransform[1] = (dfURX - dfLLX) / (GetRasterXSize()-1);
@@ -677,7 +698,7 @@ void BAGDataset::LoadMetadata()
         == OGRERR_NONE )
     {
         oSRS.exportToWkt( &pszProjection );
-    } 
+    }
     else
     {
         ParseWKTFromXML( pszXMLMetadata );
@@ -686,7 +707,7 @@ void BAGDataset::LoadMetadata()
 /* -------------------------------------------------------------------- */
 /*      Fetch acquisition date.                                         */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psDateTime = CPLSearchXMLNode( psRoot, "=dateTime" );
+    CPLXMLNode * const psDateTime = CPLSearchXMLNode( psRoot, "=dateTime" );
     if( psDateTime != NULL )
     {
         const char *pszDateTimeValue = CPLGetXMLValue( psDateTime, NULL, "" );
@@ -702,14 +723,13 @@ void BAGDataset::LoadMetadata()
 /************************************************************************/
 OGRErr BAGDataset::ParseWKTFromXML( const char *pszISOXML )
 {
-    OGRSpatialReference oSRS;
-    CPLXMLNode *psRoot = CPLParseXMLString( pszISOXML );
+    CPLXMLNode * const psRoot = CPLParseXMLString( pszISOXML );
     OGRErr eOGRErr = OGRERR_FAILURE;
 
     if( psRoot == NULL )
         return eOGRErr;
 
-    CPLStripXMLNamespace( psRoot, NULL, TRUE ); 
+    CPLStripXMLNamespace( psRoot, NULL, TRUE );
 
     CPLXMLNode *psRSI = CPLSearchXMLNode( psRoot, "=referenceSystemInfo" );
     if( psRSI == NULL )
@@ -720,20 +740,25 @@ OGRErr BAGDataset::ParseWKTFromXML( const char *pszISOXML )
         return eOGRErr;
     }
 
+    OGRSpatialReference oSRS;
     oSRS.Clear();
 
-    const char *pszSRCodeString = 
-        CPLGetXMLValue( psRSI, "MD_ReferenceSystem.referenceSystemIdentifier.RS_Identifier.code.CharacterString", NULL );
+    const char *pszSRCodeString =
+        CPLGetXMLValue( psRSI, "MD_ReferenceSystem.referenceSystemIdentifier."
+                        "RS_Identifier.code.CharacterString", NULL );
     if( pszSRCodeString == NULL )
     {
         CPLDebug("BAG",
-          "Unable to find /MI_Metadata/referenceSystemInfo[1]/MD_ReferenceSystem[1]/referenceSystemIdentifier[1]/RS_Identifier[1]/code[1]/CharacterString[1] in metadata." );
+                 "Unable to find /MI_Metadata/referenceSystemInfo[1]/"
+                 "MD_ReferenceSystem[1]/referenceSystemIdentifier[1]/"
+                 "RS_Identifier[1]/code[1]/CharacterString[1] in metadata." );
         CPLDestroyXMLNode( psRoot );
         return eOGRErr;
     }
-    
-    const char *pszSRCodeSpace = 
-        CPLGetXMLValue( psRSI, "MD_ReferenceSystem.referenceSystemIdentifier.RS_Identifier.codeSpace.CharacterString", "" );
+
+    const char *pszSRCodeSpace =
+        CPLGetXMLValue( psRSI, "MD_ReferenceSystem.referenceSystemIdentifier."
+                        "RS_Identifier.codeSpace.CharacterString", "" );
     if( !EQUAL( pszSRCodeSpace, "WKT" ) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -742,7 +767,7 @@ OGRErr BAGDataset::ParseWKTFromXML( const char *pszISOXML )
         return eOGRErr;
     }
 
-    char* pszWKT = const_cast< char* >( pszSRCodeString );
+    char* pszWKT = const_cast<char *>( pszSRCodeString );
     if( oSRS.importFromWkt( &pszWKT ) != OGRERR_NONE )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -758,23 +783,28 @@ OGRErr BAGDataset::ParseWKTFromXML( const char *pszISOXML )
     if( psRSI == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-            "Unable to find second instance of <referenceSystemInfo> in metadata." );
+                  "Unable to find second instance of <referenceSystemInfo> "
+                  "in metadata." );
         CPLDestroyXMLNode( psRoot );
         return eOGRErr;
     }
 
-    pszSRCodeString = 
-      CPLGetXMLValue( psRSI, "MD_ReferenceSystem.referenceSystemIdentifier.RS_Identifier.code.CharacterString", NULL );
+    pszSRCodeString =
+      CPLGetXMLValue( psRSI, "MD_ReferenceSystem.referenceSystemIdentifier."
+                      "RS_Identifier.code.CharacterString", NULL );
     if( pszSRCodeString == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-            "Unable to find /MI_Metadata/referenceSystemInfo[2]/MD_ReferenceSystem[1]/referenceSystemIdentifier[1]/RS_Identifier[1]/code[1]/CharacterString[1] in metadata." );
+            "Unable to find /MI_Metadata/referenceSystemInfo[2]/"
+                  "MD_ReferenceSystem[1]/referenceSystemIdentifier[1]/"
+                  "RS_Identifier[1]/code[1]/CharacterString[1] in metadata." );
         CPLDestroyXMLNode( psRoot );
         return eOGRErr;
     }
 
-    pszSRCodeSpace = 
-        CPLGetXMLValue( psRSI, "MD_ReferenceSystem.referenceSystemIdentifier.RS_Identifier.codeSpace.CharacterString", "" );
+    pszSRCodeSpace =
+        CPLGetXMLValue( psRSI, "MD_ReferenceSystem.referenceSystemIdentifier."
+                        "RS_Identifier.codeSpace.CharacterString", "" );
     if( !EQUAL( pszSRCodeSpace, "WKT" ) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -783,18 +813,17 @@ OGRErr BAGDataset::ParseWKTFromXML( const char *pszISOXML )
         return eOGRErr;
     }
 
-    if( EQUALN(pszSRCodeString, "VERTCS", 6 ) )
+    if( STARTS_WITH_CI(pszSRCodeString, "VERTCS") )
     {
         CPLString oString( pszProjection );
+        CPLFree( pszProjection );
         oString += ",";
         oString += pszSRCodeString;
-        if ( pszProjection )
-            CPLFree( pszProjection );
         pszProjection = CPLStrdup( oString );
     }
 
     CPLDestroyXMLNode( psRoot );
-    
+
     return eOGRErr;
 }
 
@@ -810,8 +839,8 @@ CPLErr BAGDataset::GetGeoTransform( double *padfGeoTransform )
         memcpy( padfGeoTransform, adfGeoTransform, sizeof(double)*6 );
         return CE_None;
     }
-    else
-        return GDALPamDataset::GetGeoTransform( padfGeoTransform );
+
+    return GDALPamDataset::GetGeoTransform( padfGeoTransform );
 }
 
 /************************************************************************/
@@ -823,8 +852,8 @@ const char *BAGDataset::GetProjectionRef()
 {
     if( pszProjection )
         return pszProjection;
-    else 
-        return GDALPamDataset::GetProjectionRef();
+
+    return GDALPamDataset::GetProjectionRef();
 }
 
 /************************************************************************/
@@ -852,8 +881,8 @@ char **BAGDataset::GetMetadata( const char *pszDomain )
 
         return apszMDList;
     }
-    else
-        return GDALPamDataset::GetMetadata( pszDomain );
+
+    return GDALPamDataset::GetMetadata( pszDomain );
 }
 
 /************************************************************************/
@@ -862,24 +891,21 @@ char **BAGDataset::GetMetadata( const char *pszDomain )
 void GDALRegister_BAG( )
 
 {
-    GDALDriver  *poDriver;
-    
-    if (! GDAL_CHECK_VERSION("BAG"))
+    if( !GDAL_CHECK_VERSION( "BAG" ) )
         return;
 
-    if(  GDALGetDriverByName( "BAG" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "BAG" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Bathymetry Attributed Grid" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_bag.html" );
-        poDriver->pfnOpen = BAGDataset::Open;
-        poDriver->pfnIdentify = BAGDataset::Identify;
-
-        GetGDALDriverManager( )->RegisterDriver( poDriver );
-    }
+    if( GDALGetDriverByName( "BAG" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "BAG" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Bathymetry Attributed Grid" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_bag.html" );
+    poDriver->pfnOpen = BAGDataset::Open;
+    poDriver->pfnIdentify = BAGDataset::Identify;
+
+    GetGDALDriverManager( )->RegisterDriver( poDriver );
 }
diff --git a/frmts/hdf5/frmt_bag.html b/frmts/hdf5/frmt_bag.html
index 7cd95ef..4a4dce9 100644
--- a/frmts/hdf5/frmt_bag.html
+++ b/frmts/hdf5/frmt_bag.html
@@ -1,4 +1,4 @@
-<!-- $Id: frmt_bag.html 22975 2011-08-24 19:41:41Z rouault $ -->
+<!-- $Id: frmt_bag.html 33795 2016-03-27 03:34:36Z goatbar $ -->
 
 <html>
 <head>
@@ -10,16 +10,16 @@
 <h1>BAG --- Bathymetry Attributed Grid</h1>
 
 This driver provides read-only support for bathymetry data in the BAG format.
-BAG files are actually a specific product profile in an HDF5 file, but a 
+BAG files are actually a specific product profile in an HDF5 file, but a
 custom driver exists to present the data in a more convenient manner than
 is available through the generic HDF5 driver.<p>
 
-BAG files have two or three image bands representing Elevation (band 1), 
-Uncertainty (band 2) and Nominal Elevation (band 3) values for each cell in a 
+BAG files have two or three image bands representing Elevation (band 1),
+Uncertainty (band 2) and Nominal Elevation (band 3) values for each cell in a
 raster grid area.<p>
 
 The geotransform and coordinate system is extracted from the internal XML
-metadata provided with the dataset.  However, some products may have 
+metadata provided with the dataset.  However, some products may have
 unsupported coordinate system formats.<p>
 
 The full XML metadata is available in the "xml:BAG" metadata domain.<p>
diff --git a/frmts/hdf5/frmt_hdf5.html b/frmts/hdf5/frmt_hdf5.html
index d20ef19..e228f18 100644
--- a/frmts/hdf5/frmt_hdf5.html
+++ b/frmts/hdf5/frmt_hdf5.html
@@ -1,4 +1,4 @@
-<!-- $Id: frmt_hdf5.html 17235 2009-06-15 14:26:45Z warmerdam $ -->
+<!-- $Id: frmt_hdf5.html 33795 2016-03-27 03:34:36Z goatbar $ -->
 
 <html>
 <head>
@@ -9,7 +9,7 @@
 
 <h1>HDF5 --- Hierarchical Data Format Release 5 (HDF5)</h1>
 
-This driver intended for HDF5 file formats importing.   This 
+This driver intended for HDF5 file formats importing.   This
 modification is
 suited for use with remote sensing data and fully compatible with
 underlying HDF5.  This driver can import HDF5-EOS files.  Currently EOS use
@@ -20,16 +20,16 @@ telemetry from `Aura' satellite.<p>
 <h2>Multiple Image Handling (Subdatasets)</h2>
 
 Hierarchical Data Format is a container for several different datasets.
-For data storing. HDF contains multidimensional arrays filled by data.  
-One HDF file may contain several arrays.  They may differ in size, 
+For data storing. HDF contains multidimensional arrays filled by data.
+One HDF file may contain several arrays.  They may differ in size,
 number of dimensions.<p>
 
-The first step is to get a report of the components images (arrays) in the 
+The first step is to get a report of the components images (arrays) in the
 file using <b>gdalinfo</b>, and
 then to import the desired images using gdal_translate.
 
-The <b>gdalinfo</b> utility lists all multidimensional subdatasets from the 
-input HDF file. The name of individual images (subdatasets) are assigned to 
+The <b>gdalinfo</b> utility lists all multidimensional subdatasets from the
+input HDF file. The name of individual images (subdatasets) are assigned to
 the <b>SUBDATASET_n_NAME</b> metadata item.  The description for each image is
 found in the <b>SUBDATASET_n_DESC</b> metadata item.  For HDF5 images the
 subdataset names will be formatted like this:<p>
@@ -37,7 +37,7 @@ subdataset names will be formatted like this:<p>
 <i>HDF5:file_name:subdataset</i><p>
 
 where:<br> <i>file_name</i> is the name of the input file, and<br>
-<i>subdataset</i> is the dataset name of the array to use (for internal use in 
+<i>subdataset</i> is the dataset name of the array to use (for internal use in
 GDAL).<p>
 
 On the second step you should provide this name for <b>gdalinfo</b> or
@@ -124,7 +124,7 @@ Center      (  256.0,  256.0)
 Now select one of the subdatasets, described as
 <tt>[1645x60] CloudFraction (32-bit floating-point)</tt>:<p>
 <pre>
-$ gdalinfo HDF5:"OMI-Aura_L2-OMTO3_2005m0326t2307-o03709_v002-2005m0428t201311.he5":CloudFraction 
+$ gdalinfo HDF5:"OMI-Aura_L2-OMTO3_2005m0326t2307-o03709_v002-2005m0428t201311.he5":CloudFraction
 Driver: HDF5Image/HDF5 Dataset
 Size is 60, 1645
 Coordinate System is:
@@ -171,12 +171,12 @@ Open GDAL Datasets:
 You may use <b>gdal_translate</b> for reading image bands from this
 dataset.<p>
 
-Note that you should provide exactly the contents of the line marked 
+Note that you should provide exactly the contents of the line marked
 <b>SUBDATASET_n_NAME</b> to GDAL, including the <b>HDF5:</b> prefix.<p>
 
-This driver is intended only for importing remote sensing and geospatial 
-datasets in form of raster images(2D or 3D arrays). If you want explore all 
-data contained in HDF file you should use another tools (you can find 
+This driver is intended only for importing remote sensing and geospatial
+datasets in form of raster images(2D or 3D arrays). If you want explore all
+data contained in HDF file you should use another tools (you can find
 information about different HDF tools using links at end of this page).
 
 <h2>Georeference</h2>
@@ -196,14 +196,13 @@ No Metadata are read at this time from the HDF5 files.
 
 <h2>Driver building</h2>
 
-This driver builded on top of NCSA HDF5 library, so you need to dowload 
-prebuild HDF5 librariesI HDF5-1.6.4 library or higher.  You also need zlib 1.2 
-and szlib 2.0.  For windows user be sure to set the attributes writable 
-(especialy if you are using cygwin) and that the DLLs can be located 
+This driver built on top of NCSA HDF5 library, so you need to download
+prebuild HDF5 libraries: HDF5-1.6.4 library or higher.  You also need zlib 1.2
+and szlib 2.0.  For windows user be sure to set the attributes writable
+(especially if you are using Cygwin) and that the DLLs can be located
 somewhere by your PATH environment variable.
 
-You may also download source code  NCSA HDF
-Home Page (see links below).<p>
+You may also download source code NCSA HDF Home Page (see links below).<p>
 
 
 <h2>See Also:</h2>
@@ -212,7 +211,7 @@ Home Page (see links below).<p>
 <li> Implemented as <tt>gdal/frmts/hdf5/hdf5dataset.cpp</tt>
 and <tt>gdal/frmts/hdf5/hdf5imagedataset.cpp</tt>.<p>
 
-<li> <a href="http://hdf.ncsa.uiuc.edu/HDF5/release/obtain5.html">The NCSA HDF5 Dowload Page</a>
+<li> <a href="http://hdf.ncsa.uiuc.edu/HDF5/release/obtain5.html">The NCSA HDF5 Download Page</a>
 at the
 <a href="http://www.ncsa.uiuc.edu/">
 National Center for Supercomputing Applications
diff --git a/frmts/hdf5/gh5_convenience.cpp b/frmts/hdf5/gh5_convenience.cpp
index ca48e90..ae9fafd 100644
--- a/frmts/hdf5/gh5_convenience.cpp
+++ b/frmts/hdf5/gh5_convenience.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gh5_convenience.cpp 26010 2013-05-17 23:31:00Z warmerdam $
+ * $Id: gh5_convenience.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Hierarchical Data Format Release 5 (HDF5)
  * Purpose:  HDF5 convenience functions.
@@ -29,13 +29,13 @@
 
 #include "gh5_convenience.h"
 
-CPL_CVSID("$Id: gh5_convenience.cpp 26010 2013-05-17 23:31:00Z warmerdam $");
+CPL_CVSID("$Id: gh5_convenience.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /*                    GH5_FetchAttribute(CPLString)                     */
 /************************************************************************/
 
-bool GH5_FetchAttribute( hid_t loc_id, const char *pszAttrName, 
+bool GH5_FetchAttribute( hid_t loc_id, const char *pszAttrName,
                         CPLString &osResult, bool bReportError )
 
 {
@@ -57,12 +57,12 @@ bool GH5_FetchAttribute( hid_t loc_id, const char *pszAttrName,
     hid_t hAttrTypeID      = H5Aget_type( hAttr );
     hid_t hAttrNativeType  = H5Tget_native_type( hAttrTypeID, H5T_DIR_DEFAULT );
 
-    if( H5Tget_class( hAttrNativeType ) == H5T_STRING ) 
+    if( H5Tget_class( hAttrNativeType ) == H5T_STRING )
     {
-	int nAttrSize = H5Tget_size( hAttrTypeID );
+	size_t nAttrSize = H5Tget_size( hAttrTypeID );
         char *pachBuffer = (char *) CPLCalloc(nAttrSize+1,1);
 	H5Aread( hAttr, hAttrNativeType, pachBuffer );
-        
+
         osResult = pachBuffer;
         CPLFree( pachBuffer );
 
@@ -89,7 +89,7 @@ bool GH5_FetchAttribute( hid_t loc_id, const char *pszAttrName,
 /*                      GH5_FetchAttribute(double)                      */
 /************************************************************************/
 
-bool GH5_FetchAttribute( hid_t loc_id, const char *pszAttrName, 
+bool GH5_FetchAttribute( hid_t loc_id, const char *pszAttrName,
                          double &dfResult, bool bReportError )
 
 {
@@ -115,7 +115,7 @@ bool GH5_FetchAttribute( hid_t loc_id, const char *pszAttrName,
     hid_t hAttrSpace       = H5Aget_space( hAttr );
     hsize_t anSize[64];
     int nAttrDims       = H5Sget_simple_extent_dims( hAttrSpace, anSize, NULL );
-    
+
     int i, nAttrElements = 1;
 
     for( i=0; i < nAttrDims; i++ ) {
@@ -135,7 +135,7 @@ bool GH5_FetchAttribute( hid_t loc_id, const char *pszAttrName,
         H5Aclose( hAttr );
         return false;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read the value.                                                 */
 /* -------------------------------------------------------------------- */
@@ -181,47 +181,46 @@ bool GH5_FetchAttribute( hid_t loc_id, const char *pszAttrName,
 /*                                                                      */
 /*      Transform HDF5 datatype to GDAL datatype                        */
 /************************************************************************/
-GDALDataType GH5_GetDataType(hid_t TypeID) 
+GDALDataType GH5_GetDataType(hid_t TypeID)
 {
     if( H5Tequal( H5T_NATIVE_CHAR,        TypeID ) )
 	return GDT_Byte;
-    else if( H5Tequal( H5T_NATIVE_SCHAR,  TypeID ) ) 
+    else if( H5Tequal( H5T_NATIVE_SCHAR,  TypeID ) )
 	return GDT_Byte;
-    else if( H5Tequal( H5T_NATIVE_UCHAR,  TypeID ) ) 
+    else if( H5Tequal( H5T_NATIVE_UCHAR,  TypeID ) )
 	return GDT_Byte;
     else if( H5Tequal( H5T_NATIVE_SHORT,  TypeID ) )
 	return GDT_Int16;
-    else if( H5Tequal( H5T_NATIVE_USHORT, TypeID ) ) 
+    else if( H5Tequal( H5T_NATIVE_USHORT, TypeID ) )
 	return GDT_UInt16;
-    else if( H5Tequal( H5T_NATIVE_INT,    TypeID ) ) 
-	return GDT_Int32;      
-    else if( H5Tequal( H5T_NATIVE_UINT,   TypeID ) ) 
+    else if( H5Tequal( H5T_NATIVE_INT,    TypeID ) )
+	return GDT_Int32;
+    else if( H5Tequal( H5T_NATIVE_UINT,   TypeID ) )
 	return GDT_UInt32;
-    else if( H5Tequal( H5T_NATIVE_LONG,   TypeID ) ) 
+    else if( H5Tequal( H5T_NATIVE_LONG,   TypeID ) )
     {
         if( sizeof(long) == 4 )
-            return GDT_Int32;      
+            return GDT_Int32;
         else
             return GDT_Unknown;
     }
-    else if( H5Tequal( H5T_NATIVE_ULONG,  TypeID ) ) 
+    else if( H5Tequal( H5T_NATIVE_ULONG,  TypeID ) )
     {
         if( sizeof(unsigned long) == 4 )
-            return GDT_UInt32;      
+            return GDT_UInt32;
         else
             return GDT_Unknown;
     }
-    else if( H5Tequal( H5T_NATIVE_FLOAT,  TypeID ) ) 
+    else if( H5Tequal( H5T_NATIVE_FLOAT,  TypeID ) )
 	return GDT_Float32;
-    else if( H5Tequal( H5T_NATIVE_DOUBLE, TypeID ) ) 
+    else if( H5Tequal( H5T_NATIVE_DOUBLE, TypeID ) )
 	return GDT_Float64;
-    else if( H5Tequal( H5T_NATIVE_LLONG,  TypeID ) ) 
+    else if( H5Tequal( H5T_NATIVE_LLONG,  TypeID ) )
 	return GDT_Unknown;
-    else if( H5Tequal( H5T_NATIVE_ULLONG, TypeID ) ) 
+    else if( H5Tequal( H5T_NATIVE_ULLONG, TypeID ) )
 	return GDT_Unknown;
-    else if( H5Tequal( H5T_NATIVE_DOUBLE, TypeID ) ) 
+    else if( H5Tequal( H5T_NATIVE_DOUBLE, TypeID ) )
 	return GDT_Unknown;
 
     return GDT_Unknown;
 }
-
diff --git a/frmts/hdf5/gh5_convenience.h b/frmts/hdf5/gh5_convenience.h
index cf5ae18..78e2a4c 100644
--- a/frmts/hdf5/gh5_convenience.h
+++ b/frmts/hdf5/gh5_convenience.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gh5_convenience.h 17985 2009-11-10 13:39:46Z rouault $
+ * $Id: gh5_convenience.h 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Hierarchical Data Format Release 5 (HDF5)
  * Purpose:  HDF5 convenience functions.
@@ -27,12 +27,19 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _GH5_CONVENIENCE_H_INCLUDED_
-#define _GH5_CONVENIENCE_H_INCLUDED_
+#ifndef GH5_CONVENIENCE_H_INCLUDED_
+#define GH5_CONVENIENCE_H_INCLUDED_
 
 #define H5_USE_16_API
 
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable : 4005 ) /* warning C4005: '_HDF5USEDLL_' : macro redefinition */
+#endif
 #include "hdf5.h"
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
 
 #include "cpl_string.h"
 #include "gdal.h"
@@ -46,10 +53,10 @@
 #  define H5OFFSET_TYPE  hsize_t
 #endif
 
-bool GH5_FetchAttribute( hid_t loc_id, const char *pszName, 
+bool GH5_FetchAttribute( hid_t loc_id, const char *pszName,
                          CPLString &osResult, bool bReportError = false );
 bool GH5_FetchAttribute( hid_t loc_id, const char *pszName,
                          double &dfResult, bool bReportError = false );
 GDALDataType GH5_GetDataType(hid_t TypeID);
 
-#endif /* ndef _GH5_CONVENIENCE_H_INCLUDED_ */
+#endif /* ndef GH5_CONVENIENCE_H_INCLUDED_ */
diff --git a/frmts/hdf5/hdf5dataset.cpp b/frmts/hdf5/hdf5dataset.cpp
index abd7910..25fc6e9 100644
--- a/frmts/hdf5/hdf5dataset.cpp
+++ b/frmts/hdf5/hdf5dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hdf5dataset.cpp 28822 2015-03-30 13:56:19Z rouault $
+ * $Id: hdf5dataset.cpp 33460 2016-02-15 16:48:24Z rouault $
  *
  * Project:  Hierarchical Data Format Release 5 (HDF5)
  * Purpose:  HDF5 Datasets. Open HDF5 file, fetch metadata and list of
@@ -32,21 +32,26 @@
 
 #define H5_USE_16_API
 
-#define MAX_METADATA_LEN 32768
+#ifdef _MSC_VER
+#pragma warning( push )
+/* warning C4005: '_HDF5USEDLL_' : macro redefinition */
+#pragma warning( disable : 4005 )
+#endif
 
 #include "hdf5.h"
 
-#include "gdal_priv.h"
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
+
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "gdal_priv.h"
 #include "hdf5dataset.h"
 
-CPL_CVSID("$Id: hdf5dataset.cpp 28822 2015-03-30 13:56:19Z rouault $");
-
-CPL_C_START
-void GDALRegister_HDF5(void);
-CPL_C_END
-
+CPL_CVSID("$Id: hdf5dataset.cpp 33460 2016-02-15 16:48:24Z rouault $");
 
+static const size_t MAX_METADATA_LEN = 32768;
 
 /************************************************************************/
 /* ==================================================================== */
@@ -60,43 +65,43 @@ CPL_C_END
 void GDALRegister_HDF5()
 
 {
-    GDALDriver	*poDriver;
-    if( GDALGetDriverByName("HDF5") == NULL )
-    {
-        poDriver = new GDALDriver();
-        poDriver->SetDescription("HDF5");
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
-                                  "Hierarchical Data Format Release 5");
-        poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC,
-                                  "frmt_hdf5.html");
-        poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "hdf5");
-        poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES");
-        poDriver->pfnOpen = HDF5Dataset::Open;
-        poDriver->pfnIdentify = HDF5Dataset::Identify;
-        GetGDALDriverManager()->RegisterDriver(poDriver);
-    }
+    if( GDALGetDriverByName( "HDF5" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription("HDF5");
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
+                              "Hierarchical Data Format Release 5");
+    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC,
+                              "frmt_hdf5.html");
+    poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "hdf5");
+    poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES");
+
+    poDriver->pfnOpen = HDF5Dataset::Open;
+    poDriver->pfnIdentify = HDF5Dataset::Identify;
+    GetGDALDriverManager()->RegisterDriver(poDriver);
 
 #ifdef HDF5_PLUGIN
     GDALRegister_HDF5Image();
 #endif
-
 }
 
 /************************************************************************/
 /*                           HDF5Dataset()                      	*/
 /************************************************************************/
-HDF5Dataset::HDF5Dataset()
-{
-    papszSubDatasets    = NULL;
-    papszMetadata       = NULL;
-    poH5RootGroup       = NULL;
-    nSubDataCount       = 0;
-    hHDF5               = -1;
-    hGroupID            = -1;
-    bIsHDFEOS           = FALSE;
-    nDatasetType        = -1;
-}
+HDF5Dataset::HDF5Dataset() :
+    hHDF5(-1),
+    hGroupID(-1),
+    papszSubDatasets(NULL),
+    bIsHDFEOS(FALSE),
+    nDatasetType(-1),
+    nSubDataCount(0),
+    poH5RootGroup(NULL),
+    papszMetadata(NULL),
+    poH5CurrentObject(NULL)
+{}
 
 /************************************************************************/
 /*                            ~HDF5Dataset()                            */
@@ -219,37 +224,57 @@ int HDF5Dataset::Identify( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     static const char achSignature[] = "\211HDF\r\n\032\n";
 
-    if( poOpenInfo->pabyHeader )
+    if( ! poOpenInfo->pabyHeader )
+        return FALSE;
+
+    if( memcmp(poOpenInfo->pabyHeader,achSignature,8) == 0 )
     {
-        if( memcmp(poOpenInfo->pabyHeader,achSignature,8) == 0 )
+        CPLString osExt(CPLGetExtension(poOpenInfo->pszFilename));
+
+        /* The tests to avoid opening KEA and BAG drivers are not */
+        /* necessary when drivers are built in the core lib, as they */
+        /* are registered after HDF5, but in the case of plugins, we */
+        /* cannot do assumptions about the registration order */
+
+        /* Avoid opening kea files if the kea driver is available */
+        if( EQUAL(osExt, "KEA") &&
+            GDALGetDriverByName("KEA") != NULL )
         {
-            /* The tests to avoid opening KEA and BAG drivers are not */
-            /* necessary when drivers are built in the core lib, as they */
-            /* are registered after HDF5, but in the case of plugins, we */
-            /* cannot do assumptions about the registration order */
-
-            /* Avoid opening kea files if the kea driver is available */
-            if( EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "KEA") &&
-                GDALGetDriverByName("KEA") != NULL )
-            {
-                return FALSE;
-            }
+            return FALSE;
+        }
+
+        /* Avoid opening BAG files if the bag driver is available */
+        if( EQUAL(osExt, "BAG") &&
+            GDALGetDriverByName("BAG") != NULL )
+        {
+            return FALSE;
+        }
 
-            /* Avoid opening kea files if the bag driver is available */
-            if( EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "BAG") &&
-                GDALGetDriverByName("BAG") != NULL )
+        /* Avoid opening NC files if the netCDF driver is available and */
+        /* they are recognized by it */
+        if( (EQUAL(osExt, "NC") || EQUAL(osExt, "CDF") || EQUAL(osExt, "NC4")) &&
+            GDALGetDriverByName("netCDF") != NULL )
+        {
+            const char* const apszAllowedDriver [] = { "netCDF", NULL };
+            CPLPushErrorHandler(CPLQuietErrorHandler);
+            GDALDatasetH hDS =
+                GDALOpenEx( poOpenInfo->pszFilename, GDAL_OF_RASTER | GDAL_OF_VECTOR,
+                            apszAllowedDriver, NULL, NULL);
+            CPLPopErrorHandler();
+            if( hDS )
             {
+                GDALClose(hDS);
                 return FALSE;
             }
-
-            return TRUE;
         }
 
-        if( memcmp(poOpenInfo->pabyHeader,"<HDF_UserBlock>",15) == 0)
-        {
-            if( H5Fis_hdf5(poOpenInfo->pszFilename) )
-              return TRUE;
-        }
+        return TRUE;
+    }
+
+    if( memcmp(poOpenInfo->pabyHeader,"<HDF_UserBlock>",15) == 0)
+    {
+        if( H5Fis_hdf5(poOpenInfo->pszFilename) )
+          return TRUE;
     }
 
     return FALSE;
@@ -260,15 +285,13 @@ int HDF5Dataset::Identify( GDALOpenInfo * poOpenInfo )
 /************************************************************************/
 GDALDataset *HDF5Dataset::Open( GDALOpenInfo * poOpenInfo )
 {
-    HDF5Dataset *poDS;
-
     if( !Identify( poOpenInfo ) )
         return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Create datasource.                                              */
 /* -------------------------------------------------------------------- */
-    poDS = new HDF5Dataset();
+    HDF5Dataset * const poDS = new HDF5Dataset();
 
     poDS->SetDescription( poOpenInfo->pszFilename );
 
@@ -336,13 +359,12 @@ GDALDataset *HDF5Dataset::Open( GDALOpenInfo * poOpenInfo )
 /************************************************************************/
 void HDF5Dataset::DestroyH5Objects( HDF5GroupObjects *poH5Object )
 {
-    unsigned i;
-
 /* -------------------------------------------------------------------- */
 /*      Visit all objects                                               */
 /* -------------------------------------------------------------------- */
+    unsigned i = 0;  // i is used after the for loop.
 
-    for( i=0; i < poH5Object->nbObjs; i++ )
+    for( ; i < poH5Object->nbObjs; i++ )
         if( poH5Object->poHchild+i != NULL )
             DestroyH5Objects( poH5Object->poHchild+i );
 
@@ -363,7 +385,7 @@ void HDF5Dataset::DestroyH5Objects( HDF5GroupObjects *poH5Object )
 
     CPLFree( poH5Object->pszUnderscorePath );
     poH5Object->pszUnderscorePath = NULL;
-    
+
     if( poH5Object->native > 0 )
         H5Tclose( poH5Object->native );
     poH5Object->native = 0;
@@ -375,7 +397,6 @@ void HDF5Dataset::DestroyH5Objects( HDF5GroupObjects *poH5Object )
         CPLFree( poH5Object->poHchild );
         poH5Object->poHchild = NULL;
     }
-
 }
 
 /************************************************************************/
@@ -383,61 +404,71 @@ void HDF5Dataset::DestroyH5Objects( HDF5GroupObjects *poH5Object )
 /*                                                                      */
 /*      Find Dataset path for HDopen                                    */
 /************************************************************************/
-char* CreatePath( HDF5GroupObjects *poH5Object )
+static void CreatePath( HDF5GroupObjects *poH5Object )
 {
-    char pszPath[8192];
-    char pszUnderscoreSpaceInName[8192];
-    char *popszPath;
-    int  i;
-    char **papszPath;
-
 /* -------------------------------------------------------------------- */
 /*      Recurse to the root path                                        */
 /* -------------------------------------------------------------------- */
-    pszPath[0]='\0';
+    CPLString osPath;
     if( poH5Object->poHparent !=NULL ) {
-        popszPath=CreatePath( poH5Object->poHparent );
-        strcpy( pszPath,popszPath );
+        CreatePath( poH5Object->poHparent );
+        osPath = poH5Object->poHparent->pszPath;
     }
 
 /* -------------------------------------------------------------------- */
 /*      add name to the path                                            */
 /* -------------------------------------------------------------------- */
     if( !EQUAL( poH5Object->pszName,"/" ) ){
-        strcat( pszPath,"/" );
-        strcat( pszPath,poH5Object->pszName );
+        osPath.append( "/" );
+        osPath.append( poH5Object->pszName );
     }
 
 /* -------------------------------------------------------------------- */
 /*      fill up path for each object                                    */
 /* -------------------------------------------------------------------- */
+    CPLString osUnderscoreSpaceInName;
     if( poH5Object->pszPath == NULL ) {
 
         if( strlen( poH5Object->pszName ) == 1 ) {
-            strcat(pszPath, poH5Object->pszName );
-            strcpy(pszUnderscoreSpaceInName, poH5Object->pszName);
+            osPath.append( poH5Object->pszName );
+            osUnderscoreSpaceInName = poH5Object->pszName;
         }
         else {
 /* -------------------------------------------------------------------- */
 /*      Change space for underscore                                     */
 /* -------------------------------------------------------------------- */
-            papszPath = CSLTokenizeString2( pszPath,
-                            " ", CSLT_HONOURSTRINGS );
+            char** papszPath = CSLTokenizeString2(
+                osPath.c_str(), " ", CSLT_HONOURSTRINGS );
 
-            strcpy(pszUnderscoreSpaceInName,papszPath[0]);
-            for( i=1; i < CSLCount( papszPath ); i++ ) {
-                strcat( pszUnderscoreSpaceInName, "_" );
-                strcat( pszUnderscoreSpaceInName, papszPath[ i ] );
+            for( int i=0; papszPath[i] != NULL ; i++ ) {
+                if( i > 0 )
+                    osUnderscoreSpaceInName.append( "_" );
+                osUnderscoreSpaceInName.append( papszPath[ i ] );
             }
             CSLDestroy(papszPath);
 
         }
+
+        // -1 to give room for NUL in C strings.
+        static const size_t MAX_PATH = 8192 - 1;
+        // TODO(schwehr): Is it an issue if the results are longer than 8192?
+        // It appears that the output can never be longer than the source.
+        if ( osUnderscoreSpaceInName.size() > MAX_PATH )
+            CPLError( CE_Fatal, CPLE_AppDefined,
+                      "osUnderscoreSpaceInName longer than MAX_PATH: "
+                      "%u > %u",
+                      static_cast<unsigned int>(osUnderscoreSpaceInName.size()),
+                      static_cast<unsigned int>(MAX_PATH) );
+        if ( osPath.size() > MAX_PATH )
+            CPLError( CE_Fatal, CPLE_AppDefined,
+                      "osPath longer than MAX_PATH: %u > %u",
+                      static_cast<unsigned int>(osPath.size()),
+                      static_cast<unsigned int>(MAX_PATH) );
+
         poH5Object->pszUnderscorePath  =
-            CPLStrdup( pszUnderscoreSpaceInName );
-        poH5Object->pszPath  = CPLStrdup( pszPath );
+            CPLStrdup( osUnderscoreSpaceInName.c_str() );
+        poH5Object->pszPath = CPLStrdup( osPath.c_str() );
     }
-
-    return( poH5Object->pszPath );
 }
 
 /************************************************************************/
@@ -468,27 +499,13 @@ static int HDF5GroupCheckDuplicate( HDF5GroupObjects *poHparent,
 /*                                                                      */
 /*      Create HDF5 hierarchy into a linked list                        */
 /************************************************************************/
-herr_t HDF5CreateGroupObjs(hid_t hHDF5, const char *pszObjName,
-                           void *poHObjParent)
+herr_t HDF5CreateGroupObjs( hid_t hHDF5, const char *pszObjName,
+                            void *poHObjParent)
 {
-    hid_t       hGroupID;       /* identifier of group */
-    hid_t       hDatasetID;     /* identifier of dataset */
-    hsize_t     nbObjs=0;       /* number of objects in a group */
-    int         nbAttrs=0;      /* number of attributes in object */
-    unsigned    idx;
-    int         n_dims;
-    H5G_stat_t  oStatbuf;
-    hsize_t     *dims=NULL;
-    hsize_t     *maxdims=NULL;
-    hid_t       datatype;
-    hid_t       dataspace;
-    hid_t       native;
-
-    HDF5GroupObjects *poHchild;
-    HDF5GroupObjects *poHparent;
-
-    poHparent = ( HDF5GroupObjects * ) poHObjParent;
-    poHchild=poHparent->poHchild;
+    HDF5GroupObjects * const poHparent =
+        static_cast<HDF5GroupObjects *>(poHObjParent);
+    HDF5GroupObjects * poHchild = poHparent->poHchild;
+    H5G_stat_t oStatbuf;
 
     if( H5Gget_objinfo( hHDF5, pszObjName, FALSE, &oStatbuf ) < 0  )
         return -1;
@@ -497,7 +514,8 @@ herr_t HDF5CreateGroupObjs(hid_t hHDF5, const char *pszObjName,
 /* -------------------------------------------------------------------- */
 /*      Look for next child                                             */
 /* -------------------------------------------------------------------- */
-    for( idx=0; idx < poHparent->nbObjs; idx++ ) {
+    unsigned idx = 0;  // idx is used after the for loop.
+    for( ; idx < poHparent->nbObjs; idx++ ) {
         if( poHchild->pszName == NULL ) break;
         poHchild++;
     }
@@ -514,46 +532,51 @@ herr_t HDF5CreateGroupObjs(hid_t hHDF5, const char *pszObjName,
     poHchild->nIndex = idx;
     poHchild->poHparent = poHparent;
     poHchild->nRank     = 0;
-    poHchild->paDims    = 0;
+    poHchild->paDims    = NULL;
     poHchild->HDatatype = 0;
     poHchild->objno[0]  = oStatbuf.objno[0];
     poHchild->objno[1]  = oStatbuf.objno[1];
     if( poHchild->pszPath == NULL ) {
-        poHchild->pszPath  = CreatePath( poHchild );
+        CreatePath( poHchild );
     }
     if( poHparent->pszPath == NULL ) {
-        poHparent->pszPath = CreatePath( poHparent );
+        CreatePath( poHparent );
     }
 
-
     switch ( oStatbuf.type )
     {
         case H5G_LINK:
+        {
             poHchild->nbAttrs = 0;
             poHchild->nbObjs = 0;
             poHchild->poHchild = NULL;
             poHchild->nRank      = 0;
-            poHchild->paDims    = 0;
+            poHchild->paDims    = NULL;
             poHchild->HDatatype = 0;
             break;
-
+        }
         case H5G_GROUP:
+        {
+            hid_t hGroupID = H5I_INVALID_HID;  // Identifier of group.
             if( ( hGroupID = H5Gopen( hHDF5, pszObjName ) ) == -1  ) {
                 printf( "Error: unable to access \"%s\" group.\n",
                         pszObjName );
                 return -1;
             }
-            nbAttrs          = H5Aget_num_attrs( hGroupID );
+            // Number of attributes in object.
+            const int nbAttrs = H5Aget_num_attrs( hGroupID );
+            hsize_t nbObjs = 0;  // Number of objects in a group.
             H5Gget_num_objs( hGroupID, &nbObjs );
             poHchild->nbAttrs= nbAttrs;
             poHchild->nbObjs = (int) nbObjs;
             poHchild->nRank      = 0;
-            poHchild->paDims    = 0;
+            poHchild->paDims    = NULL;
             poHchild->HDatatype = 0;
 
             if( nbObjs > 0 ) {
-                poHchild->poHchild =( HDF5GroupObjects * )
-                CPLCalloc( (int)nbObjs, sizeof( HDF5GroupObjects ) );
+                poHchild->poHchild = static_cast<HDF5GroupObjects *>(
+                    CPLCalloc( static_cast<int>(nbObjs),
+                               sizeof( HDF5GroupObjects ) ) );
                 memset( poHchild->poHchild, 0,
                         (size_t) (sizeof( HDF5GroupObjects ) * nbObjs) );
             }
@@ -569,23 +592,28 @@ herr_t HDF5CreateGroupObjs(hid_t hHDF5, const char *pszObjName,
 
             H5Gclose( hGroupID );
             break;
-
+        }
         case H5G_DATASET:
-
+        {
+            hid_t hDatasetID = H5I_INVALID_HID;  // Identifier of dataset.
             if( ( hDatasetID = H5Dopen( hHDF5, pszObjName ) ) == -1  ) {
                 printf( "Error: unable to access \"%s\" dataset.\n",
                         pszObjName );
                 return -1;
             }
-            nbAttrs      = H5Aget_num_attrs( hDatasetID );
-            datatype     = H5Dget_type( hDatasetID );
-            dataspace    = H5Dget_space( hDatasetID );
-            n_dims       = H5Sget_simple_extent_ndims( dataspace );
-            native       = H5Tget_native_type( datatype, H5T_DIR_ASCEND );
+            const int nbAttrs = H5Aget_num_attrs( hDatasetID );
+            const hid_t datatype = H5Dget_type( hDatasetID );
+            const hid_t dataspace = H5Dget_space( hDatasetID );
+            const int n_dims = H5Sget_simple_extent_ndims( dataspace );
+            const hid_t native = H5Tget_native_type( datatype, H5T_DIR_ASCEND );
+            hsize_t *maxdims = NULL;
+            hsize_t *dims = NULL;
 
             if( n_dims > 0 ) {
-                dims     = (hsize_t *) CPLCalloc( n_dims,sizeof( hsize_t ) );
-                maxdims  = (hsize_t *) CPLCalloc( n_dims,sizeof( hsize_t ) );
+                dims = static_cast<hsize_t *>(
+                    CPLCalloc( n_dims,sizeof( hsize_t ) ) );
+                maxdims  = static_cast<hsize_t *>(
+                    CPLCalloc( n_dims,sizeof( hsize_t ) ) );
             }
             H5Sget_simple_extent_dims( dataspace, dims, maxdims );
             if( maxdims != NULL )
@@ -593,7 +621,7 @@ herr_t HDF5CreateGroupObjs(hid_t hHDF5, const char *pszObjName,
 
             if( n_dims > 0 ) {
                 poHchild->nRank     = n_dims;   // rank of the array
-                poHchild->paDims    = dims;      // dimmension of the array.
+                poHchild->paDims    = dims;      // dimension of the array.
                 poHchild->HDatatype = datatype;  // HDF5 datatype
             }
             else  {
@@ -609,16 +637,17 @@ herr_t HDF5CreateGroupObjs(hid_t hHDF5, const char *pszObjName,
             H5Sclose( dataspace );
             H5Dclose( hDatasetID );
             break;
-
+        }
         case H5G_TYPE:
+        {
             poHchild->nbAttrs = 0;
             poHchild->nbObjs = 0;
             poHchild->poHchild = NULL;
             poHchild->nRank      = 0;
-            poHchild->paDims    = 0;
+            poHchild->paDims    = NULL;
             poHchild->HDatatype = 0;
             break;
-
+        }
         default:
             break;
     }
@@ -631,30 +660,14 @@ herr_t HDF5CreateGroupObjs(hid_t hHDF5, const char *pszObjName,
 /*                          HDF5AttrIterate()                           */
 /************************************************************************/
 
-herr_t HDF5AttrIterate( hid_t hH5ObjID,
-                        const char *pszAttrName,
-                        void *pDS )
+static herr_t HDF5AttrIterate( hid_t hH5ObjID,
+                               const char *pszAttrName,
+                               // TODO(schwehr): void * -> HDF5Dataset *
+                               void *pDS )
 {
-    hid_t           hAttrID;
-    hid_t           hAttrTypeID;
-    hid_t           hAttrNativeType;
-    hid_t           hAttrSpace;
-
-    char           *szData = NULL;
-    hsize_t        nSize[64];
-    unsigned int   nAttrElmts;
-    hsize_t        nAttrSize;
-    hsize_t        i;
-    void           *buf = NULL;
-    unsigned int   nAttrDims;
-
-    char          **papszTokens;
-
-    HDF5Dataset    *poDS;
-    CPLString       osKey;
-    char           *szValue = NULL;
-
-    poDS = (HDF5Dataset *) pDS;
+    char **papszTokens = NULL;
+    CPLString osKey;
+    HDF5Dataset * const poDS = static_cast<HDF5Dataset *>(pDS);
 
     // Convert "/" into "_" for the path component
     const char* pszPath = poDS->poH5CurrentObject->pszUnderscorePath;
@@ -662,7 +675,7 @@ herr_t HDF5AttrIterate( hid_t hH5ObjID,
     {
         papszTokens = CSLTokenizeString2( pszPath, "/", CSLT_HONOURSTRINGS );
 
-        for( i = 0; papszTokens != NULL && papszTokens[i] != NULL; ++i )
+        for( hsize_t i = 0; papszTokens != NULL && papszTokens[i] != NULL; ++i )
         {
             if( i != 0)
                 osKey += '_';
@@ -674,7 +687,7 @@ herr_t HDF5AttrIterate( hid_t hH5ObjID,
     // Convert whitespaces into "_" for the attribute name component
     papszTokens = CSLTokenizeString2( pszAttrName, " ",
                             CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
-    for( i = 0; papszTokens != NULL && papszTokens[i] != NULL; ++i )
+    for( hsize_t i = 0; papszTokens != NULL && papszTokens[i] != NULL; ++i )
     {
         if(!osKey.empty())
             osKey += '_';
@@ -682,30 +695,40 @@ herr_t HDF5AttrIterate( hid_t hH5ObjID,
     }
     CSLDestroy( papszTokens );
 
-    hAttrID          = H5Aopen_name( hH5ObjID, pszAttrName );
-    hAttrTypeID      = H5Aget_type( hAttrID );
-    hAttrNativeType  = H5Tget_native_type( hAttrTypeID, H5T_DIR_DEFAULT );
-    hAttrSpace       = H5Aget_space( hAttrID );
-    nAttrDims        = H5Sget_simple_extent_dims( hAttrSpace, nSize, NULL );
+    const hid_t hAttrID         = H5Aopen_name( hH5ObjID, pszAttrName );
+    const hid_t hAttrTypeID     = H5Aget_type( hAttrID );
+    const hid_t hAttrNativeType = H5Tget_native_type( hAttrTypeID, H5T_DIR_DEFAULT );
+    const hid_t hAttrSpace      = H5Aget_space( hAttrID );
+
+    if( H5Tget_class( hAttrNativeType ) == H5T_VLEN )
+        return 0;
 
-    nAttrElmts = 1;
-    for( i=0; i < nAttrDims; i++ ) {
-        nAttrElmts *= (int) nSize[i];
+    hsize_t nSize[64];
+    const unsigned int nAttrDims =
+        H5Sget_simple_extent_dims( hAttrSpace, nSize, NULL );
+
+    unsigned int nAttrElmts = 1;
+    for( hsize_t i=0; i < nAttrDims; i++ ) {
+        nAttrElmts *= static_cast<int>(nSize[i]);
     }
 
+    char *szData = NULL;
+    hsize_t nAttrSize = 0;
+    char *szValue = NULL;
+
     if( H5Tget_class( hAttrNativeType ) == H5T_STRING )
     {
         if ( H5Tis_variable_str(hAttrNativeType) )
         {
-            char** papszStrings;
-            papszStrings = (char**) CPLMalloc( nAttrElmts * sizeof(char*) );
+            char** papszStrings = static_cast<char**>(
+                CPLMalloc( nAttrElmts * sizeof(char*) ) );
 
             // Read the values
             H5Aread( hAttrID, hAttrNativeType, papszStrings );
 
             // Concatenate all values as one string (separated by a space)
             CPLString osVal = papszStrings[0];
-            for( i=1; i < nAttrElmts; i++ ) {
+            for( hsize_t i=1; i < nAttrElmts; i++ ) {
                 osVal += " ";
                 osVal += papszStrings[i];
             }
@@ -726,19 +749,22 @@ herr_t HDF5AttrIterate( hid_t hH5ObjID,
         }
     }
     else {
+        const size_t nDataLen = 8192;
+        void *buf = NULL;
+
         if( nAttrElmts > 0 ) {
             buf = (void *) CPLMalloc( nAttrElmts*
                           H5Tget_size( hAttrNativeType ));
-            szData = (char*) CPLMalloc( 8192 );
-            szValue = (char*) CPLMalloc( MAX_METADATA_LEN );
+            szData = static_cast<char*>(CPLMalloc( nDataLen ));
+            szValue = static_cast<char*>(CPLMalloc( MAX_METADATA_LEN ));
             szData[0] = '\0';
             szValue[0] ='\0';
             H5Aread( hAttrID, hAttrNativeType, buf );
         }
-        if( H5Tequal( H5T_NATIVE_CHAR, hAttrNativeType ) 
+        if( H5Tequal( H5T_NATIVE_CHAR, hAttrNativeType )
             || H5Tequal( H5T_NATIVE_SCHAR,  hAttrNativeType ) ) {
-            for( i=0; i < nAttrElmts; i++ ) {
-                sprintf( szData, "%c ", ((char *) buf)[i]);
+            for( hsize_t i=0; i < nAttrElmts; i++ ) {
+                snprintf( szData, nDataLen, "%c ", ((char *) buf)[i]);
                 if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >=
                                                             MAX_METADATA_LEN )
                     CPLError( CE_Warning, CPLE_OutOfMemory,
@@ -746,8 +772,8 @@ herr_t HDF5AttrIterate( hid_t hH5ObjID,
             }
         }
         else if( H5Tequal( H5T_NATIVE_UCHAR,  hAttrNativeType ) ) {
-            for( i=0; i < nAttrElmts; i++ ) {
-                sprintf( szData, "%c", ((char *) buf)[i] );
+            for( hsize_t i=0; i < nAttrElmts; i++ ) {
+                snprintf( szData, nDataLen, "%c", ((char *) buf)[i] );
                 if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >=
                                                             MAX_METADATA_LEN )
                     CPLError( CE_Warning, CPLE_OutOfMemory,
@@ -755,8 +781,8 @@ herr_t HDF5AttrIterate( hid_t hH5ObjID,
             }
         }
         else if( H5Tequal( H5T_NATIVE_SHORT,  hAttrNativeType ) ) {
-            for( i=0; i < nAttrElmts; i++ ) {
-                sprintf( szData, "%d ", ((short *) buf)[i] );
+            for( hsize_t i=0; i < nAttrElmts; i++ ) {
+                snprintf( szData, nDataLen, "%d ", ((short *) buf)[i] );
                 if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >=
                                                             MAX_METADATA_LEN )
                     CPLError( CE_Warning, CPLE_OutOfMemory,
@@ -764,8 +790,8 @@ herr_t HDF5AttrIterate( hid_t hH5ObjID,
             }
         }
         else if( H5Tequal( H5T_NATIVE_USHORT, hAttrNativeType ) ) {
-            for( i=0; i < nAttrElmts; i++ ) {
-                sprintf( szData, "%ud ", ((unsigned short *) buf)[i] );
+            for( hsize_t i=0; i < nAttrElmts; i++ ) {
+                snprintf( szData, nDataLen, "%ud ", ((unsigned short *) buf)[i] );
                 if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >=
                                                             MAX_METADATA_LEN )
                     CPLError( CE_Warning, CPLE_OutOfMemory,
@@ -773,8 +799,8 @@ herr_t HDF5AttrIterate( hid_t hH5ObjID,
             }
         }
         else if( H5Tequal( H5T_NATIVE_INT,    hAttrNativeType ) ) {
-            for( i=0; i < nAttrElmts; i++ ) {
-                sprintf( szData, "%d ", ((int *) buf)[i] );
+            for( hsize_t i=0; i < nAttrElmts; i++ ) {
+                snprintf( szData, nDataLen, "%d ", ((int *) buf)[i] );
                 if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >=
                                                             MAX_METADATA_LEN )
                     CPLError( CE_Warning, CPLE_OutOfMemory,
@@ -782,8 +808,8 @@ herr_t HDF5AttrIterate( hid_t hH5ObjID,
             }
         }
         else if( H5Tequal( H5T_NATIVE_UINT,   hAttrNativeType ) ) {
-            for( i=0; i < nAttrElmts; i++ ) {
-                sprintf( szData, "%ud ", ((unsigned int *) buf)[i] );
+            for( hsize_t i=0; i < nAttrElmts; i++ ) {
+                snprintf( szData, nDataLen, "%ud ", ((unsigned int *) buf)[i] );
                 if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >=
                                                             MAX_METADATA_LEN )
                     CPLError( CE_Warning, CPLE_OutOfMemory,
@@ -791,8 +817,8 @@ herr_t HDF5AttrIterate( hid_t hH5ObjID,
             }
         }
         else if( H5Tequal( H5T_NATIVE_LONG,   hAttrNativeType ) ) {
-            for( i=0; i < nAttrElmts; i++ ) {
-                sprintf( szData, "%ld ", ((long *)buf)[i] );
+            for( hsize_t i=0; i < nAttrElmts; i++ ) {
+                snprintf( szData, nDataLen, "%ld ", ((long *)buf)[i] );
                 if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >=
                                                             MAX_METADATA_LEN )
                     CPLError( CE_Warning, CPLE_OutOfMemory,
@@ -800,8 +826,8 @@ herr_t HDF5AttrIterate( hid_t hH5ObjID,
             }
         }
         else if( H5Tequal( H5T_NATIVE_ULONG,  hAttrNativeType ) ) {
-            for( i=0; i < nAttrElmts; i++ ) {
-                sprintf( szData, "%ld ", ((unsigned long *)buf)[i] );
+            for( hsize_t i=0; i < nAttrElmts; i++ ) {
+                snprintf( szData, nDataLen, "%ld ", ((unsigned long *)buf)[i] );
                 if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >=
                                                             MAX_METADATA_LEN )
                     CPLError( CE_Warning, CPLE_OutOfMemory,
@@ -809,8 +835,8 @@ herr_t HDF5AttrIterate( hid_t hH5ObjID,
             }
         }
         else if( H5Tequal( H5T_NATIVE_FLOAT,  hAttrNativeType ) ) {
-            for( i=0; i < nAttrElmts; i++ ) {
-                CPLsprintf( szData, "%.8g ",  ((float *)buf)[i] );
+            for( hsize_t i=0; i < nAttrElmts; i++ ) {
+                CPLsnprintf( szData, nDataLen, "%.8g ",  ((float *)buf)[i] );
                 if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >=
                                                             MAX_METADATA_LEN )
                     CPLError( CE_Warning, CPLE_OutOfMemory,
@@ -818,8 +844,8 @@ herr_t HDF5AttrIterate( hid_t hH5ObjID,
             }
         }
         else if( H5Tequal( H5T_NATIVE_DOUBLE, hAttrNativeType ) ) {
-            for( i=0; i < nAttrElmts; i++ ) {
-                CPLsprintf( szData, "%.15g ",  ((double *)buf)[i] );
+            for( hsize_t i=0; i < nAttrElmts; i++ ) {
+                CPLsnprintf( szData, nDataLen, "%.15g ",  ((double *)buf)[i] );
                 if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >=
                                                             MAX_METADATA_LEN )
                     CPLError( CE_Warning, CPLE_OutOfMemory,
@@ -846,19 +872,14 @@ herr_t HDF5AttrIterate( hid_t hH5ObjID,
 /************************************************************************/
 CPLErr HDF5Dataset::CreateMetadata( HDF5GroupObjects *poH5Object, int nType)
 {
-    hid_t       hGroupID;       /* identifier of group */
-    hid_t       hDatasetID;
-    int         nbAttrs;
-
-    HDF5Dataset *poDS;
 
     if( !poH5Object->pszPath )
         return CE_None;
 
-    poDS = this;
+    HDF5Dataset * const poDS = this;
 
     poH5CurrentObject = poH5Object;
-    nbAttrs = poH5Object->nbAttrs;
+    int nbAttrs = poH5Object->nbAttrs;
 
     if( poH5Object->pszPath == NULL || EQUAL(poH5Object->pszPath, "" ) )
         return CE_None;
@@ -868,9 +889,10 @@ CPLErr HDF5Dataset::CreateMetadata( HDF5GroupObjects *poH5Object, int nType)
     case H5G_GROUP:
 
         if( nbAttrs > 0 ) {
-            hGroupID = H5Gopen( hHDF5, poH5Object->pszPath );
-            H5Aiterate( hGroupID, NULL, HDF5AttrIterate, (void *)poDS  );
-            H5Gclose( hGroupID );
+            // Identifier of group.
+            const hid_t l_hGroupID = H5Gopen( hHDF5, poH5Object->pszPath );
+            H5Aiterate( l_hGroupID, NULL, HDF5AttrIterate, (void *)poDS  );
+            H5Gclose( l_hGroupID );
         }
 
         break;
@@ -878,8 +900,9 @@ CPLErr HDF5Dataset::CreateMetadata( HDF5GroupObjects *poH5Object, int nType)
     case H5G_DATASET:
 
         if( nbAttrs > 0 ) {
-            hDatasetID =  H5Dopen(hHDF5, poH5Object->pszPath );
-            H5Aiterate( hDatasetID, NULL, HDF5AttrIterate, (void *)poDS );
+            hid_t hDatasetID =  H5Dopen(hHDF5, poH5Object->pszPath );
+            H5Aiterate( hDatasetID, NULL, HDF5AttrIterate,
+                        reinterpret_cast<void *>(poDS) );
             H5Dclose( hDatasetID );
         }
         break;
@@ -899,33 +922,34 @@ CPLErr HDF5Dataset::CreateMetadata( HDF5GroupObjects *poH5Object, int nType)
 HDF5GroupObjects* HDF5Dataset::HDF5FindDatasetObjectsbyPath
     ( HDF5GroupObjects *poH5Objects, const char* pszDatasetPath )
 {
-    unsigned i;
-    HDF5Dataset *poDS;
-    HDF5GroupObjects *poObjectsFound;
-    poDS=this;
-
     if( poH5Objects->nType == H5G_DATASET &&
         EQUAL( poH5Objects->pszUnderscorePath,pszDatasetPath ) ) {
 
-        /*      printf("found it! %ld\n",(long) poH5Objects);*/
-        return( poH5Objects );
+#ifdef DEBUG_VERBOSE
+      printf("found it! %p\n", poH5Objects);
+#endif
+        return poH5Objects;
     }
 
+    HDF5Dataset * const poDS = this;
+
     if( poH5Objects->nbObjs >0 )
-        for( i=0; i <poH5Objects->nbObjs; i++ )   {
-            poObjectsFound=
-            poDS->HDF5FindDatasetObjectsbyPath( poH5Objects->poHchild+i,
-                                                pszDatasetPath );
+    {
+        for( unsigned int i=0; i <poH5Objects->nbObjs; i++ )   {
+            HDF5GroupObjects *poObjectsFound =
+                poDS->HDF5FindDatasetObjectsbyPath( poH5Objects->poHchild+i,
+                                                    pszDatasetPath );
 /* -------------------------------------------------------------------- */
 /*      Is this our dataset??                                           */
 /* -------------------------------------------------------------------- */
-            if( poObjectsFound != NULL ) return( poObjectsFound );
+            if( poObjectsFound != NULL )
+                return poObjectsFound;
         }
+    }
 /* -------------------------------------------------------------------- */
 /*      Dataset has not been found!                                     */
 /* -------------------------------------------------------------------- */
-    return( NULL );
-
+    return NULL;
 }
 
 
@@ -936,34 +960,35 @@ HDF5GroupObjects* HDF5Dataset::HDF5FindDatasetObjectsbyPath
 HDF5GroupObjects* HDF5Dataset::HDF5FindDatasetObjects
     ( HDF5GroupObjects *poH5Objects, const char* pszDatasetName )
 {
-    unsigned i;
-    HDF5Dataset *poDS;
-    HDF5GroupObjects *poObjectsFound;
-    poDS=this;
-
     if( poH5Objects->nType == H5G_DATASET &&
         EQUAL( poH5Objects->pszName,pszDatasetName ) ) {
 
-        /*      printf("found it! %ld\n",(long) poH5Objects);*/
-        return( poH5Objects );
+#ifdef DEBUG_VERBOSE
+        printf("found it! %p\n", poH5Objects);
+#endif
+        return poH5Objects;
     }
 
-    if( poH5Objects->nbObjs >0 )
-        for( i=0; i <poH5Objects->nbObjs; i++ )   {
-            poObjectsFound=
-            poDS->HDF5FindDatasetObjects( poH5Objects->poHchild+i,
-                                          pszDatasetName );
+    HDF5Dataset *poDS = this;
+
+    if( poH5Objects->nbObjs > 0 )
+    {
+        for( unsigned int i=0; i <poH5Objects->nbObjs; i++ )   {
+            HDF5GroupObjects *poObjectsFound =
+                poDS->HDF5FindDatasetObjects( poH5Objects->poHchild+i,
+                                              pszDatasetName );
 /* -------------------------------------------------------------------- */
 /*      Is this our dataset??                                           */
 /* -------------------------------------------------------------------- */
-            if( poObjectsFound != NULL ) return( poObjectsFound );
+            if( poObjectsFound != NULL )
+                return poObjectsFound;
 
         }
+    }
 /* -------------------------------------------------------------------- */
 /*      Dataset has not been found!                                     */
 /* -------------------------------------------------------------------- */
-    return( NULL );
-
+    return NULL;
 }
 
 
@@ -975,10 +1000,7 @@ HDF5GroupObjects* HDF5Dataset::HDF5FindDatasetObjects
 CPLErr HDF5Dataset::HDF5ListGroupObjects( HDF5GroupObjects *poRootGroup,
 					  int bSUBDATASET )
 {
-    char szTemp[8192];
-    char szDim[8192];
-    HDF5Dataset *poDS;
-    poDS=this;
+    HDF5Dataset *poDS = this;
 
     if( poRootGroup->nbObjs >0 )
         for( hsize_t i=0; i < poRootGroup->nbObjs; i++ ) {
@@ -993,6 +1015,9 @@ CPLErr HDF5Dataset::HDF5ListGroupObjects( HDF5GroupObjects *poRootGroup,
 /* -------------------------------------------------------------------- */
 /*      Create Sub dataset list                                         */
 /* -------------------------------------------------------------------- */
+    char szTemp[8192];  // TODO: Get this off of the stack.
+    char szDim[8192];  // TODO: Get this off of the stack.
+
     if( (poRootGroup->nType == H5G_DATASET ) && bSUBDATASET
         && poDS->GetDataType( poRootGroup->native ) == GDT_Unknown )
     {
@@ -1007,16 +1032,16 @@ CPLErr HDF5Dataset::HDF5ListGroupObjects( HDF5GroupObjects *poRootGroup,
         szDim[0]='\0';
         switch( poRootGroup->nRank ) {
         case 3:
-            sprintf( szTemp,"%dx%dx%d",
-                (int)poRootGroup->paDims[0],
-                (int)poRootGroup->paDims[1],
-                (int)poRootGroup->paDims[2] );
+            snprintf( szTemp, sizeof(szTemp), "%dx%dx%d",
+                      static_cast<int>(poRootGroup->paDims[0]),
+                      static_cast<int>(poRootGroup->paDims[1]),
+                      static_cast<int>(poRootGroup->paDims[2]) );
             break;
 
         case 2:
-            sprintf( szTemp,"%dx%d",
-                (int)poRootGroup->paDims[0],
-                (int)poRootGroup->paDims[1] );
+            snprintf( szTemp, sizeof(szTemp), "%dx%d",
+                      static_cast<int>(poRootGroup->paDims[0]),
+                      static_cast<int>(poRootGroup->paDims[1]) );
             break;
 
         default:
@@ -1025,7 +1050,8 @@ CPLErr HDF5Dataset::HDF5ListGroupObjects( HDF5GroupObjects *poRootGroup,
         }
         strcat( szDim,szTemp );
 
-        sprintf( szTemp, "SUBDATASET_%d_NAME", ++(poDS->nSubDataCount) );
+        snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_NAME",
+                  ++(poDS->nSubDataCount) );
 
         poDS->papszSubDatasets =
             CSLSetNameValue( poDS->papszSubDatasets, szTemp,
@@ -1033,7 +1059,8 @@ CPLErr HDF5Dataset::HDF5ListGroupObjects( HDF5GroupObjects *poRootGroup,
                         poDS->GetDescription(),
                         poRootGroup->pszUnderscorePath ) );
 
-        sprintf(  szTemp, "SUBDATASET_%d_DESC", poDS->nSubDataCount );
+        snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_DESC",
+                  poDS->nSubDataCount );
 
         poDS->papszSubDatasets =
             CSLSetNameValue( poDS->papszSubDatasets, szTemp,
@@ -1054,10 +1081,8 @@ CPLErr HDF5Dataset::HDF5ListGroupObjects( HDF5GroupObjects *poRootGroup,
 /************************************************************************/
 CPLErr HDF5Dataset::ReadGlobalAttributes(int bSUBDATASET)
 {
-
-    HDF5GroupObjects *poRootGroup;
-
-    poRootGroup = (HDF5GroupObjects*) CPLCalloc(sizeof(HDF5GroupObjects), 1);
+    HDF5GroupObjects *poRootGroup = static_cast<HDF5GroupObjects*>(
+        CPLCalloc(sizeof(HDF5GroupObjects), 1) );
 
     poH5RootGroup=poRootGroup;
     poRootGroup->pszName   = CPLStrdup( "/" );
@@ -1071,7 +1096,8 @@ CPLErr HDF5Dataset::ReadGlobalAttributes(int bSUBDATASET)
         return CE_None;
     }
 
-    H5G_stat_t  oStatbuf;
+    H5G_stat_t oStatbuf = {{0, 0}, {0, 0}, 0, H5G_UNKNOWN, 0, 0, {0, 0, 0, 0}};
+
     if( H5Gget_objinfo( hHDF5, "/", FALSE, &oStatbuf ) < 0  )
         return CE_Failure;
     poRootGroup->objno[0] = oStatbuf.objno[0];
@@ -1090,11 +1116,11 @@ CPLErr HDF5Dataset::ReadGlobalAttributes(int bSUBDATASET)
     H5Gget_num_objs( hGroupID, &( poRootGroup->nbObjs ) );
 
     if( poRootGroup->nbObjs > 0 ) {
-        poRootGroup->poHchild = ( HDF5GroupObjects * )
-            CPLCalloc( poRootGroup->nbObjs,
-            sizeof( HDF5GroupObjects ) );
+        poRootGroup->poHchild = static_cast<HDF5GroupObjects *>(
+            CPLCalloc( static_cast<size_t>(poRootGroup->nbObjs),
+                       sizeof( HDF5GroupObjects ) ) );
         H5Giterate( hGroupID, "/", NULL,
-               HDF5CreateGroupObjs, (void *)poRootGroup );
+                    HDF5CreateGroupObjs, reinterpret_cast<void *>(poRootGroup) );
     }
     else poRootGroup->poHchild = NULL;
 
@@ -1114,36 +1140,22 @@ CPLErr HDF5Dataset::ReadGlobalAttributes(int bSUBDATASET)
  *        the attribute name must be the form:
  *            root attribute name
  *            SUBDATASET/subdataset attribute name
- * @param pdfValues pointer wich will store the array of doubles read.
- * @param nLen it stores the length of the array read. If NULL it doesn't 
- *        inform the lenght of the array.
+ * @param pdfValues pointer which will store the array of doubles read.
+ * @param nLen it stores the length of the array read. If NULL it doesn't
+ *        inform the length of the array.
  * @return CPLErr CE_None in case of success, CE_Failure in case of failure
  */
 CPLErr HDF5Dataset::HDF5ReadDoubleAttr(const char* pszAttrFullPath,
                                        double **pdfValues,int *nLen)
 {
-    CPLErr          retVal = CE_Failure;
-    hid_t           hAttrID=-1;
-    hid_t           hAttrTypeID=-1;
-    hid_t           hAttrNativeType=-1;
-    hid_t           hAttrSpace=-1;
-    hid_t           hObjAttrID=-1;
-
-    hsize_t         nSize[64];
-    unsigned int    nAttrElmts;
-    hsize_t         i;
-    unsigned int    nAttrDims;
+    CPLString osAttrFullPath(pszAttrFullPath);
 
-    size_t nSlashPos;
+    // Search for the last "/" in order to get the path to the attribute.
+    const size_t nSlashPos = osAttrFullPath.find_last_of("/");
 
-    CPLString osAttrFullPath(pszAttrFullPath);
     CPLString osObjName;
     CPLString osAttrName;
 
-    //Search for the last "/" in order to get the
-    //Path to the attribute
-    nSlashPos = osAttrFullPath.find_last_of("/");
-
     //If objects name have been found
     if(nSlashPos != CPLString::npos )
     {
@@ -1160,33 +1172,38 @@ CPLErr HDF5Dataset::HDF5ReadDoubleAttr(const char* pszAttrFullPath,
         osAttrName = pszAttrFullPath;
     }
 
-    hObjAttrID = H5Oopen( hHDF5, osObjName.c_str(),H5P_DEFAULT);
+    const hid_t hObjAttrID = H5Oopen( hHDF5, osObjName.c_str(), H5P_DEFAULT );
+
+    CPLErr retVal = CE_Failure;
 
     if(hObjAttrID < 0)
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Object %s could not be opened\n", pszAttrFullPath);
+                  "Object %s could not be opened\n", pszAttrFullPath );
         retVal = CE_Failure;
     }
     else
     {
-        //Open attribute handler by name, from the object handler opened
-        //earlier
-        hAttrID = H5Aopen_name( hObjAttrID, osAttrName.c_str());
+        // Open attribute handler by name, from the object handler opened
+        // earlier.
+        const hid_t hAttrID = H5Aopen_name( hObjAttrID, osAttrName.c_str() );
 
-        //Check for errors opening the attribute
+        // Check for errors opening the attribute.
         if(hAttrID <0)
         {
             CPLError( CE_Failure, CPLE_OpenFailed,
-                      "Attribute %s could not be opened\n", pszAttrFullPath);
+                      "Attribute %s could not be opened\n", pszAttrFullPath );
             retVal = CE_Failure;
         }
         else
         {
-            hAttrTypeID      = H5Aget_type( hAttrID );
-            hAttrNativeType  = H5Tget_native_type( hAttrTypeID, H5T_DIR_DEFAULT );
-            hAttrSpace       = H5Aget_space( hAttrID );
-            nAttrDims        = H5Sget_simple_extent_dims( hAttrSpace, nSize, NULL );
+            const hid_t hAttrTypeID = H5Aget_type( hAttrID );
+            const hid_t hAttrNativeType =
+                H5Tget_native_type( hAttrTypeID, H5T_DIR_DEFAULT );
+            const hid_t hAttrSpace = H5Aget_space( hAttrID );
+            hsize_t nSize[64];
+            unsigned int nAttrDims =
+                H5Sget_simple_extent_dims( hAttrSpace, nSize, NULL );
 
             if( !H5Tequal( H5T_NATIVE_DOUBLE, hAttrNativeType ) )
             {
@@ -1196,12 +1213,12 @@ CPLErr HDF5Dataset::HDF5ReadDoubleAttr(const char* pszAttrFullPath,
             }
             else
             {
-                //Get the ammount of elements
-                nAttrElmts = 1;
-                for( i=0; i < nAttrDims; i++ )
+                // Get the amount of elements.
+                unsigned int nAttrElmts = 1;
+                for( hsize_t i=0; i < nAttrDims; i++ )
                 {
                     //For multidimensional attributes
-                     nAttrElmts *= nSize[i];
+                     nAttrElmts *= static_cast<unsigned int>(nSize[i]);
                 }
 
                 if(nLen != NULL)
@@ -1213,7 +1230,7 @@ CPLErr HDF5Dataset::HDF5ReadDoubleAttr(const char* pszAttrFullPath,
                 if(H5Aread( hAttrID, hAttrNativeType, *pdfValues )<0)
                 {
                      CPLError( CE_Failure, CPLE_OpenFailed,
-                               "Attribute %s could not be opened\n", 
+                               "Attribute %s could not be opened\n",
                                pszAttrFullPath);
                      retVal = CE_Failure;
                 }
diff --git a/frmts/hdf5/hdf5dataset.h b/frmts/hdf5/hdf5dataset.h
index f73cd48..3f09246 100644
--- a/frmts/hdf5/hdf5dataset.h
+++ b/frmts/hdf5/hdf5dataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hdf5dataset.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: hdf5dataset.h 31777 2015-11-26 14:14:41Z rouault $
  *
  * Project:  Hierarchical Data Format Release 5 (HDF5)
  * Purpose:  Header file for HDF5 datasets reader.
@@ -28,8 +28,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _HDF5DATASET_H_INCLUDED_
-#define _HDF5DATASET_H_INCLUDED_
+#ifndef HDF5DATASET_H_INCLUDED_
+#define HDF5DATASET_H_INCLUDED_
 
 #include "gdal_pam.h"
 #include "cpl_list.h"
@@ -62,7 +62,7 @@ herr_t HDF5CreateGroupObjs(hid_t, const char *,void *);
 /************************************************************************/
 class HDF5Dataset : public GDALPamDataset
 {
-  protected:
+protected:
 
   hid_t            hHDF5;
   hid_t            hGroupID; /* H handler interface */
@@ -71,7 +71,6 @@ class HDF5Dataset : public GDALPamDataset
   int              nDatasetType;
   int              nSubDataCount;
 
-
   HDF5GroupObjects *poH5RootGroup; /* Contain hdf5 Groups information */
 
   CPLErr ReadGlobalAttributes(int);
@@ -97,14 +96,14 @@ class HDF5Dataset : public GDALPamDataset
    * 			the attribute name must be the form:
    * 					root attribute name
    * 					SUBDATASET/subdataset attribute name
-   * @param pdfValues pointer wich will store the array of doubles read.
+   * @param pdfValues pointer which will store the array of doubles read.
    * @param nLen it stores the length of the array read. If NULL it doesn't inform
-   *        the lenght of the array.
+   *        the length of the array.
    * @return CPLErr CE_None in case of success, CE_Failure in case of failure
    */
   CPLErr HDF5ReadDoubleAttr(const char* pszAttrName,double **pdfValues,int *nLen=NULL);
 
-  public:
+public:
 
   char	           **papszMetadata;
   HDF5GroupObjects *poH5CurrentObject;
@@ -116,7 +115,4 @@ class HDF5Dataset : public GDALPamDataset
   static int Identify(GDALOpenInfo *);
 };
 
-
-
-#endif /* _HDF5DATASET_H_INCLUDED_ */
-
+#endif /* HDF5DATASET_H_INCLUDED_ */
diff --git a/frmts/hdf5/hdf5imagedataset.cpp b/frmts/hdf5/hdf5imagedataset.cpp
index 257ad28..fa982cd 100644
--- a/frmts/hdf5/hdf5imagedataset.cpp
+++ b/frmts/hdf5/hdf5imagedataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hdf5imagedataset.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: hdf5imagedataset.cpp 33794 2016-03-26 13:19:07Z goatbar $
  *
  * Project:  Hierarchical Data Format Release 5 (HDF5)
  * Purpose:  Read subdatasets of HDF5 file.
@@ -30,19 +30,26 @@
 
 #define H5_USE_16_API
 
+#ifdef _MSC_VER
+#pragma warning( push )
+// warning C4005: '_HDF5USEDLL_' : macro redefinition.
+#pragma warning( disable : 4005 )
+#endif
+
 #include "hdf5.h"
 
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
+
+#include "cpl_string.h"
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 #include "gdal_priv.h"
-#include "cpl_string.h"
 #include "hdf5dataset.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: hdf5imagedataset.cpp 27745 2014-09-27 16:38:57Z goatbar $");
-
-CPL_C_START
-void GDALRegister_HDF5Image(void);
-CPL_C_END
+CPL_CVSID("$Id: hdf5imagedataset.cpp 33794 2016-03-26 13:19:07Z goatbar $");
 
 /* release 1.6.3 or 1.6.4 changed the type of count in some api functions */
 
@@ -88,17 +95,17 @@ class HDF5ImageDataset : public HDF5Dataset
     haddr_t      address;
     hid_t        datatype;
     hid_t        native;
-    H5T_class_t  clas;
+    H5T_class_t  class_;
     Hdf5ProductType    iSubdatasetType;
     HDF5CSKProductEnum iCSKProductType;
     double       adfGeoTransform[6];
     bool         bHasGeoTransform;
-    
+
     CPLErr CreateODIMH5Projection();
 
 public:
     HDF5ImageDataset();
-    ~HDF5ImageDataset();
+    virtual ~HDF5ImageDataset();
 
     CPLErr CreateProjections( );
     static GDALDataset  *Open( GDALOpenInfo * );
@@ -107,7 +114,7 @@ public:
     const char          *GetProjectionRef();
     virtual int         GetGCPCount( );
     virtual const char  *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs( ); 
+    virtual const GDAL_GCP *GetGCPs( );
     virtual CPLErr GetGeoTransform( double * padfTransform );
 
     Hdf5ProductType GetSubdatasetType() const {return iSubdatasetType;}
@@ -132,7 +139,7 @@ public:
     /**
      * Captures Geolocation information from a COSMO-SKYMED
      * file.
-     * The geoid will allways be WGS84
+     * The geoid will always be WGS84
      * The projection type may be UTM or UPS, depending on the
      * latitude from the center of the image.
      * @param iProductType type of HDF5 subproduct, see HDF5CSKProduct
@@ -141,17 +148,17 @@ public:
 
     /**
     * Get Geotransform information for COSMO-SKYMED files
-    * In case of sucess it stores the transformation
+    * In case of success it stores the transformation
     * in adfGeoTransform. In case of failure it doesn't
     * modify adfGeoTransform
     * @param iProductType type of HDF5 subproduct, see HDF5CSKProduct
     */
     void CaptureCSKGeoTransform(int iProductType);
-    
+
     /**
      * @param iProductType type of HDF5 subproduct, see HDF5CSKProduct
      */
-    void CaptureCSKGCPs(int iProductType);    
+    void CaptureCSKGCPs(int iProductType);
 };
 
 /************************************************************************/
@@ -163,30 +170,32 @@ public:
 /************************************************************************/
 /*                           HDF5ImageDataset()                         */
 /************************************************************************/
-HDF5ImageDataset::HDF5ImageDataset()
+HDF5ImageDataset::HDF5ImageDataset() :
+    pszProjection(NULL),
+    pszGCPProjection(NULL),
+    pasGCPList(NULL),
+    nGCPCount(0),
+    dims(NULL),
+    maxdims(NULL),
+    poH5Objects(NULL),
+    ndims(0), dimensions(0),
+    dataset_id(-1),
+    dataspace_id(-1),
+    size(0),
+    address(0),
+    datatype(-1),
+    native(-1),
+    class_(H5T_NO_CLASS),
+    iSubdatasetType(UNKNOWN_PRODUCT),
+    iCSKProductType(PROD_UNKNOWN),
+    bHasGeoTransform(false)
 {
-    nGCPCount       = 0;
-    pszProjection   = NULL;
-    pszGCPProjection= NULL;
-    pasGCPList      = NULL;
-    poH5Objects     = NULL;
-    poH5RootGroup   = NULL;
-    dims            = NULL;
-    maxdims         = NULL;
-    papszMetadata   = NULL;
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
-    iSubdatasetType    = UNKNOWN_PRODUCT;
-    iCSKProductType    = PROD_UNKNOWN;
-    bHasGeoTransform   = false;
-    dataset_id         = -1;
-    dataspace_id       = -1;
-    datatype           = -1;
-    native             = -1;
 }
 
 /************************************************************************/
@@ -195,7 +204,7 @@ HDF5ImageDataset::HDF5ImageDataset()
 HDF5ImageDataset::~HDF5ImageDataset( )
 {
     FlushCache();
-    
+
     if( dataset_id > 0 )
         H5Dclose(dataset_id);
     if( dataspace_id > 0 )
@@ -208,22 +217,16 @@ HDF5ImageDataset::~HDF5ImageDataset( )
     CPLFree(pszProjection);
     CPLFree(pszGCPProjection);
 
-    if( dims )
-        CPLFree( dims );
-
-    if( maxdims )
-        CPLFree( maxdims );
+    CPLFree( dims );
+    CPLFree( maxdims );
 
     if( nGCPCount > 0 )
     {
         for( int i = 0; i < nGCPCount; i++ )
         {
-            if( pasGCPList[i].pszId )
-                CPLFree( pasGCPList[i].pszId );
-            if( pasGCPList[i].pszInfo )
-                CPLFree( pasGCPList[i].pszInfo );
+            CPLFree( pasGCPList[i].pszId );
+            CPLFree( pasGCPList[i].pszInfo );
         }
-
         CPLFree( pasGCPList );
     }
 }
@@ -237,7 +240,7 @@ class HDF5ImageRasterBand : public GDALPamRasterBand
 {
     friend class HDF5ImageDataset;
 
-    int         bNoDataSet;
+    bool        bNoDataSet;
     double      dfNoDataValue;
 
 public:
@@ -255,23 +258,19 @@ public:
 /*                        ~HDF5ImageRasterBand()                        */
 /************************************************************************/
 
-HDF5ImageRasterBand::~HDF5ImageRasterBand()
-{
+HDF5ImageRasterBand::~HDF5ImageRasterBand() {}
 
-}
 /************************************************************************/
 /*                           HDF5ImageRasterBand()                      */
 /************************************************************************/
-HDF5ImageRasterBand::HDF5ImageRasterBand( HDF5ImageDataset *poDS, int nBand,
-                                          GDALDataType eType )
-
+HDF5ImageRasterBand::HDF5ImageRasterBand( HDF5ImageDataset *poDSIn, int nBandIn,
+                                          GDALDataType eType ) :
+    bNoDataSet(false),
+    dfNoDataValue(-9999.0)
 {
-    char          **papszMetaGlobal;
-    this->poDS    = poDS;
-    this->nBand   = nBand;
+    poDS = poDSIn;
+    nBand = nBandIn;
     eDataType     = eType;
-    bNoDataSet    = FALSE;
-    dfNoDataValue = -9999;
     nBlockXSize   = poDS->GetRasterXSize( );
     nBlockYSize   = 1;
 
@@ -279,40 +278,40 @@ HDF5ImageRasterBand::HDF5ImageRasterBand( HDF5ImageDataset *poDS, int nBand,
 /*      Take a copy of Global Metadata since  I can't pass Raster       */
 /*      variable to Iterate function.                                   */
 /* -------------------------------------------------------------------- */
-    papszMetaGlobal = CSLDuplicate( poDS->papszMetadata );
-    CSLDestroy( poDS->papszMetadata );
-    poDS->papszMetadata = NULL;
+    char **papszMetaGlobal = CSLDuplicate( poDSIn->papszMetadata );
+    CSLDestroy( poDSIn->papszMetadata );
+    poDSIn->papszMetadata = NULL;
 
-    if( poDS->poH5Objects->nType == H5G_DATASET ) {
-        poDS->CreateMetadata( poDS->poH5Objects, H5G_DATASET );
+    if( poDSIn->poH5Objects->nType == H5G_DATASET ) {
+        poDSIn->CreateMetadata( poDSIn->poH5Objects, H5G_DATASET );
     }
 
 /* -------------------------------------------------------------------- */
-/*      Recover Global Metadat and set Band Metadata                    */
+/*      Recover Global Metadata and set Band Metadata                   */
 /* -------------------------------------------------------------------- */
 
-    SetMetadata( poDS->papszMetadata );
+    SetMetadata( poDSIn->papszMetadata );
 
-    CSLDestroy( poDS->papszMetadata );
-    poDS->papszMetadata = CSLDuplicate( papszMetaGlobal );
+    CSLDestroy( poDSIn->papszMetadata );
+    poDSIn->papszMetadata = CSLDuplicate( papszMetaGlobal );
     CSLDestroy( papszMetaGlobal );
 
     /* check for chunksize and set it as the blocksize (optimizes read) */
-    hid_t listid = H5Dget_create_plist(((HDF5ImageDataset * )poDS)->dataset_id);
+    const hid_t listid = H5Dget_create_plist(poDSIn->dataset_id);
     if (listid>0)
     {
         if(H5Pget_layout(listid) == H5D_CHUNKED)
         {
-            hsize_t panChunkDims[3];
-            CPL_UNUSED int nDimSize = H5Pget_chunk(listid, 3, panChunkDims);
-            CPLAssert(nDimSize == poDS->ndims);
-            nBlockXSize   = (int) panChunkDims[poDS->GetXIndex()];
-            nBlockYSize   = (int) panChunkDims[poDS->GetYIndex()];
+            hsize_t panChunkDims[3] = {0, 0, 0};
+            const int nDimSize = H5Pget_chunk(listid, 3, panChunkDims);
+            CPL_IGNORE_RET_VAL(nDimSize);
+            CPLAssert(nDimSize == poDSIn->ndims);
+            nBlockXSize   = (int) panChunkDims[poDSIn->GetXIndex()];
+            nBlockYSize   = (int) panChunkDims[poDSIn->GetYIndex()];
         }
 
         H5Pclose(listid);
     }
-
 }
 
 /************************************************************************/
@@ -328,8 +327,8 @@ double HDF5ImageRasterBand::GetNoDataValue( int * pbSuccess )
 
         return dfNoDataValue;
     }
-    else
-        return GDALPamRasterBand::GetNoDataValue( pbSuccess );
+
+    return GDALPamRasterBand::GetNoDataValue( pbSuccess );
 }
 
 /************************************************************************/
@@ -338,7 +337,7 @@ double HDF5ImageRasterBand::GetNoDataValue( int * pbSuccess )
 CPLErr HDF5ImageRasterBand::SetNoDataValue( double dfNoData )
 
 {
-    bNoDataSet = TRUE;
+    bNoDataSet = true;
     dfNoDataValue = dfNoData;
 
     return CE_None;
@@ -350,15 +349,7 @@ CPLErr HDF5ImageRasterBand::SetNoDataValue( double dfNoData )
 CPLErr HDF5ImageRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                         void * pImage )
 {
-    herr_t      status;
-    hsize_t     count[3];
-    H5OFFSET_TYPE offset[3];
-    int         nSizeOfData;
-    hid_t       memspace;
-    hsize_t     col_dims[3];
-    hsize_t     rank;
-
-    HDF5ImageDataset    *poGDS = ( HDF5ImageDataset * ) poDS;
+    HDF5ImageDataset *poGDS = reinterpret_cast<HDF5ImageDataset * >(poDS);
 
     if( poGDS->eAccess == GA_Update ) {
         memset( pImage, 0,
@@ -367,29 +358,33 @@ CPLErr HDF5ImageRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         return CE_None;
     }
 
+    hsize_t count[3] = {0, 0, 0};
+    H5OFFSET_TYPE offset[3] = {0, 0, 0};
+    hsize_t col_dims[3] = {0, 0, 0};
+    hsize_t rank = 2;
+
     if( poGDS->IsComplexCSKL1A() )
     {
-        rank = 3; 
+        rank = 3;
         offset[2]   = nBand-1;
         count[2]    = 1;
         col_dims[2] = 1;
     }
     else if( poGDS->ndims == 3 )
     {
-        rank=3;
+        rank = 3;
         offset[0]   = nBand-1;
         count[0]    = 1;
         col_dims[0] = 1;
     }
-    else
-        rank = 2;
+    // Defaults to rank = 2;
 
-    offset[poGDS->GetYIndex()] = nBlockYOff*nBlockYSize;
-    offset[poGDS->GetXIndex()] = nBlockXOff*nBlockXSize;
+    offset[poGDS->GetYIndex()] = nBlockYOff*static_cast<hsize_t>(nBlockYSize);
+    offset[poGDS->GetXIndex()] = nBlockXOff*static_cast<hsize_t>(nBlockXSize);
     count[poGDS->GetYIndex()]  = nBlockYSize;
     count[poGDS->GetXIndex()]  = nBlockXSize;
 
-    nSizeOfData = H5Tget_size( poGDS->native );
+    const int nSizeOfData = static_cast<int>(H5Tget_size( poGDS->native ));
     memset( pImage,0,nBlockXSize*nBlockYSize*nSizeOfData );
 
     /*  blocksize may not be a multiple of imagesize */
@@ -403,10 +398,12 @@ CPLErr HDF5ImageRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
 /*      Select block from file space                                    */
 /* -------------------------------------------------------------------- */
-    status =  H5Sselect_hyperslab( poGDS->dataspace_id,
-                                   H5S_SELECT_SET,
-                                   offset, NULL,
-                                   count, NULL );
+    herr_t status =  H5Sselect_hyperslab( poGDS->dataspace_id,
+                                          H5S_SELECT_SET,
+                                          offset, NULL,
+                                          count, NULL );
+    if( status < 0 )
+        return CE_Failure;
 
 /* -------------------------------------------------------------------- */
 /*      Create memory space to receive the data                         */
@@ -414,12 +411,15 @@ CPLErr HDF5ImageRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     col_dims[poGDS->GetYIndex()]=nBlockYSize;
     col_dims[poGDS->GetXIndex()]=nBlockXSize;
 
-    memspace = H5Screate_simple( (int) rank, col_dims, NULL );
+    const hid_t memspace =
+        H5Screate_simple( static_cast<int>(rank), col_dims, NULL );
     H5OFFSET_TYPE mem_offset[3] = {0, 0, 0};
     status =  H5Sselect_hyperslab(memspace,
                                   H5S_SELECT_SET,
                                   mem_offset, NULL,
                                   count, NULL);
+    if( status < 0 )
+        return CE_Failure;
 
     status = H5Dread ( poGDS->dataset_id,
                        poGDS->native,
@@ -436,8 +436,8 @@ CPLErr HDF5ImageRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                   "H5Dread() failed for block." );
         return CE_Failure;
     }
-    else
-        return CE_None;
+
+    return CE_None;
 }
 
 /************************************************************************/
@@ -447,10 +447,10 @@ CPLErr HDF5ImageRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 int HDF5ImageDataset::Identify( GDALOpenInfo *poOpenInfo )
 
 {
-    if(!EQUALN( poOpenInfo->pszFilename, "HDF5:", 5 ) )
+    if(!STARTS_WITH_CI(poOpenInfo->pszFilename, "HDF5:") )
         return FALSE;
-    else
-        return TRUE;
+
+    return TRUE;
 }
 
 /************************************************************************/
@@ -458,12 +458,7 @@ int HDF5ImageDataset::Identify( GDALOpenInfo *poOpenInfo )
 /************************************************************************/
 GDALDataset *HDF5ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 {
-    int i;
-    HDF5ImageDataset    *poDS;
-    char szFilename[2048];
-
-    if(!EQUALN( poOpenInfo->pszFilename, "HDF5:", 5 ) ||
-        strlen(poOpenInfo->pszFilename) > sizeof(szFilename) - 3 )
+    if(!STARTS_WITH_CI(poOpenInfo->pszFilename, "HDF5:") )
         return NULL;
 
 /* -------------------------------------------------------------------- */
@@ -472,12 +467,12 @@ GDALDataset *HDF5ImageDataset::Open( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->eAccess == GA_Update )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
-                  "The HDF5ImageDataset driver does not support update access to existing"
-                  " datasets.\n" );
+                  "The HDF5ImageDataset driver does not support update access "
+                  " to existing datasets.\n" );
         return NULL;
     }
 
-    poDS = new HDF5ImageDataset();
+    HDF5ImageDataset *poDS = new HDF5ImageDataset();
 
     /* -------------------------------------------------------------------- */
     /*      Create a corresponding GDALDataset.                             */
@@ -501,33 +496,33 @@ GDALDataset *HDF5ImageDataset::Open( GDALOpenInfo * poOpenInfo )
     /* -------------------------------------------------------------------- */
     CPLString osSubdatasetName;
 
-    strcpy(szFilename, papszName[1]);
+    CPLString osFilename(papszName[1]);
 
     if( strlen(papszName[1]) == 1 && papszName[3] != NULL )
     {
-        strcat(szFilename, ":");
-        strcat(szFilename, papszName[2]);
+        osFilename += ":";
+        osFilename += papszName[2];
         osSubdatasetName = papszName[3];
     }
     else
         osSubdatasetName = papszName[2];
-    
+
     poDS->SetSubdatasetName( osSubdatasetName );
 
     CSLDestroy(papszName);
     papszName = NULL;
 
-    if( !H5Fis_hdf5(szFilename) ) {
+    if( !H5Fis_hdf5(osFilename) ) {
         delete poDS;
         return NULL;
     }
 
-    poDS->SetPhysicalFilename( szFilename );
+    poDS->SetPhysicalFilename( osFilename );
 
     /* -------------------------------------------------------------------- */
     /*      Try opening the dataset.                                        */
     /* -------------------------------------------------------------------- */
-    poDS->hHDF5 = H5Fopen(szFilename,
+    poDS->hHDF5 = H5Fopen(osFilename,
                           H5F_ACC_RDONLY,
                           H5P_DEFAULT );
 
@@ -579,20 +574,20 @@ GDALDataset *HDF5ImageDataset::Open( GDALOpenInfo * poOpenInfo )
                                                     poDS->dims,
                                                     poDS->maxdims );
     poDS->datatype = H5Dget_type( poDS->dataset_id );
-    poDS->clas     = H5Tget_class( poDS->datatype );
+    poDS->class_   = H5Tget_class( poDS->datatype );
     poDS->size     = H5Tget_size( poDS->datatype );
     poDS->address = H5Dget_offset( poDS->dataset_id );
     poDS->native  = H5Tget_native_type( poDS->datatype, H5T_DIR_ASCEND );
 
-    // CSK code in IdentifyProductType() and CreateProjections() 
+    // CSK code in IdentifyProductType() and CreateProjections()
     // uses dataset metadata.
     poDS->SetMetadata( poDS->papszMetadata );
 
     // Check if the hdf5 is a well known product type
     poDS->IdentifyProductType();
 
-    poDS->nRasterYSize=(int)poDS->dims[poDS->GetYIndex()];   // nRows
-    poDS->nRasterXSize=(int)poDS->dims[poDS->GetXIndex()];   // nCols
+    poDS->nRasterYSize=static_cast<int>(poDS->dims[poDS->GetYIndex()]); // nRows
+    poDS->nRasterXSize=static_cast<int>(poDS->dims[poDS->GetXIndex()]); // nCols
     if( poDS->IsComplexCSKL1A() )
     {
         poDS->nBands=(int) poDS->dims[2]; // nBands
@@ -606,8 +601,8 @@ GDALDataset *HDF5ImageDataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->nBands=1;
     }
 
-    for(  i = 1; i <= poDS->nBands; i++ ) {
-        HDF5ImageRasterBand *poBand =
+    for( int i = 1; i <= poDS->nBands; i++ ) {
+        HDF5ImageRasterBand * const poBand =
             new HDF5ImageRasterBand( poDS, i,
                             poDS->GetDataType( poDS->native ) );
 
@@ -628,7 +623,7 @@ GDALDataset *HDF5ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, ":::VIRTUAL:::" );
 
-    return( poDS );
+    return poDS;
 }
 
 
@@ -638,26 +633,23 @@ GDALDataset *HDF5ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 void GDALRegister_HDF5Image( )
 
 {
-    GDALDriver  *poDriver;
+    if( !GDAL_CHECK_VERSION( "HDF5Image driver" ) )
+        return;
 
-    if (! GDAL_CHECK_VERSION("HDF5Image driver"))
+    if( GDALGetDriverByName( "HDF5Image" ) != NULL )
         return;
 
-    if(  GDALGetDriverByName( "HDF5Image" ) == NULL )
-    {
-        poDriver = new GDALDriver( );
-
-        poDriver->SetDescription( "HDF5Image" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "HDF5 Dataset" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "frmt_hdf5.html" );
-        poDriver->pfnOpen = HDF5ImageDataset::Open;
-        poDriver->pfnIdentify = HDF5ImageDataset::Identify;
-
-        GetGDALDriverManager( )->RegisterDriver( poDriver );
-    }
+    GDALDriver *poDriver = new GDALDriver( );
+
+    poDriver->SetDescription( "HDF5Image" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "HDF5 Dataset" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_hdf5.html" );
+
+    poDriver->pfnOpen = HDF5ImageDataset::Open;
+    poDriver->pfnIdentify = HDF5ImageDataset::Identify;
+
+    GetGDALDriverManager( )->RegisterDriver( poDriver );
 }
 
 /************************************************************************/
@@ -673,11 +665,11 @@ void GDALRegister_HDF5Image( )
 
 CPLErr HDF5ImageDataset::CreateODIMH5Projection()
 {
-    const char* pszProj4String = GetMetadataItem("where_projdef");
-    const char* pszLL_lon = GetMetadataItem("where_LL_lon");
-    const char* pszLL_lat = GetMetadataItem("where_LL_lat");
-    const char* pszUR_lon = GetMetadataItem("where_UR_lon");
-    const char* pszUR_lat = GetMetadataItem("where_UR_lat");
+    const char* const pszProj4String = GetMetadataItem("where_projdef");
+    const char* const pszLL_lon = GetMetadataItem("where_LL_lon");
+    const char* const pszLL_lat = GetMetadataItem("where_LL_lat");
+    const char* const pszUR_lon = GetMetadataItem("where_UR_lon");
+    const char* const pszUR_lat = GetMetadataItem("where_UR_lat");
     if( pszProj4String == NULL ||
         pszLL_lon == NULL || pszLL_lat == NULL ||
         pszUR_lon == NULL || pszUR_lat == NULL )
@@ -708,10 +700,10 @@ CPLErr HDF5ImageDataset::CreateODIMH5Projection()
     delete poCT;
 
     /* Compute the geotransform now */
-    double dfPixelX = (dfURX - dfLLX) / nRasterXSize;
-    double dfPixelY = (dfURY - dfLLY) / nRasterYSize;
+    const double dfPixelX = (dfURX - dfLLX) / nRasterXSize;
+    const double dfPixelY = (dfURY - dfLLY) / nRasterYSize;
 
-    bHasGeoTransform = TRUE;
+    bHasGeoTransform = true;
     adfGeoTransform[0] = dfLLX;
     adfGeoTransform[1] = dfPixelX;
     adfGeoTransform[2] = 0;
@@ -730,10 +722,10 @@ CPLErr HDF5ImageDataset::CreateODIMH5Projection()
 /************************************************************************/
 CPLErr HDF5ImageDataset::CreateProjections()
 {
-    switch(iSubdatasetType)
-    {
-    case CSK_PRODUCT:
-    {
+ switch(iSubdatasetType)
+ {
+  case CSK_PRODUCT:
+  {
         const char *osMissionLevel = NULL;
         int productType = PROD_UNKNOWN;
 
@@ -742,19 +734,19 @@ CPLErr HDF5ImageDataset::CreateProjections()
             //Get the format's level
             osMissionLevel = HDF5Dataset::GetMetadataItem("Product_Type");
 
-            if(EQUALN(osMissionLevel,"RAW",3))
+            if(STARTS_WITH_CI(osMissionLevel, "RAW"))
                 productType  = PROD_CSK_L0;
 
-            if(EQUALN(osMissionLevel,"SSC",3))
+            if(STARTS_WITH_CI(osMissionLevel, "SSC"))
                 productType  = PROD_CSK_L1A;
 
-            if(EQUALN(osMissionLevel,"DGM",3))
+            if(STARTS_WITH_CI(osMissionLevel, "DGM"))
                 productType  = PROD_CSK_L1B;
 
-            if(EQUALN(osMissionLevel,"GEC",3))
+            if(STARTS_WITH_CI(osMissionLevel, "GEC"))
                 productType  = PROD_CSK_L1C;
 
-            if(EQUALN(osMissionLevel,"GTC",3))
+            if(STARTS_WITH_CI(osMissionLevel, "GTC"))
                 productType  = PROD_CSK_L1D;
         }
 
@@ -763,24 +755,14 @@ CPLErr HDF5ImageDataset::CreateProjections()
         CaptureCSKGCPs(productType);
 
         break;
-    }
-    case UNKNOWN_PRODUCT:
-    {
-#define NBGCPLAT 100
-#define NBGCPLON 30
-
-    hid_t LatitudeDatasetID  = -1;
-    hid_t LongitudeDatasetID = -1;
-    // hid_t LatitudeDataspaceID;
-    // hid_t LongitudeDataspaceID;
-    float* Latitude;
-    float* Longitude;
-    int    i,j;
-    int   nDeltaLat;
-    int   nDeltaLon;
-
-    nDeltaLat = nRasterYSize / NBGCPLAT;
-    nDeltaLon = nRasterXSize / NBGCPLON;
+  }
+  case UNKNOWN_PRODUCT:
+  {
+    static const int NBGCPLAT = 100;
+    static const int NBGCPLON = 30;
+
+    const int nDeltaLat = nRasterYSize / NBGCPLAT;
+    const int nDeltaLon = nRasterXSize / NBGCPLON;
 
     if( nDeltaLat == 0 || nDeltaLon == 0 )
         return CE_None;
@@ -795,7 +777,7 @@ CPLErr HDF5ImageDataset::CreateProjections()
         return CE_None;
     }
     /* -------------------------------------------------------------------- */
-    /*      The Lattitude and Longitude arrays must have a rank of 2 to     */
+    /*      The Latitude and Longitude arrays must have a rank of 2 to     */
     /*      retrieve GCPs.                                                  */
     /* -------------------------------------------------------------------- */
     if( poH5Objects->nRank != 2 ) {
@@ -805,19 +787,18 @@ CPLErr HDF5ImageDataset::CreateProjections()
     /* -------------------------------------------------------------------- */
     /*      Retrieve HDF5 data information                                  */
     /* -------------------------------------------------------------------- */
-    LatitudeDatasetID   = H5Dopen( hHDF5,poH5Objects->pszPath );
+    const hid_t LatitudeDatasetID   = H5Dopen( hHDF5,poH5Objects->pszPath );
     // LatitudeDataspaceID = H5Dget_space( dataset_id );
 
     poH5Objects=HDF5FindDatasetObjects( poH5RootGroup, "Longitude" );
-    LongitudeDatasetID   = H5Dopen( hHDF5,poH5Objects->pszPath );
+    const hid_t LongitudeDatasetID   = H5Dopen( hHDF5,poH5Objects->pszPath );
     // LongitudeDataspaceID = H5Dget_space( dataset_id );
 
     if( ( LatitudeDatasetID > 0 ) && ( LongitudeDatasetID > 0) ) {
-
-        Latitude         = ( float * ) CPLCalloc(  nRasterYSize*nRasterXSize,
-                            sizeof( float ) );
-        Longitude         = ( float * ) CPLCalloc( nRasterYSize*nRasterXSize,
-                            sizeof( float ) );
+        float * const Latitude = static_cast<float *>(
+            CPLCalloc( nRasterYSize*nRasterXSize, sizeof( float ) ) );
+        float * const Longitude = static_cast<float *>(
+            CPLCalloc( nRasterYSize*nRasterXSize, sizeof( float ) ) );
         memset( Latitude, 0, nRasterXSize*nRasterYSize*sizeof(  float ) );
         memset( Longitude, 0, nRasterXSize*nRasterYSize*sizeof( float ) );
 
@@ -846,43 +827,43 @@ CPLErr HDF5ImageDataset::CreateProjections()
     /* -------------------------------------------------------------------- */
         nGCPCount = nRasterYSize/nDeltaLat * nRasterXSize/nDeltaLon;
 
-        pasGCPList = ( GDAL_GCP * )
-            CPLCalloc( nGCPCount, sizeof( GDAL_GCP ) );
+        pasGCPList = static_cast<GDAL_GCP *>(
+            CPLCalloc( nGCPCount, sizeof( GDAL_GCP ) ) );
 
         GDALInitGCPs( nGCPCount, pasGCPList );
         int k=0;
 
-        int nYLimit = ((int)nRasterYSize/nDeltaLat) * nDeltaLat;
-        int nXLimit = ((int)nRasterXSize/nDeltaLon) * nDeltaLon;
-        for( j = 0; j < nYLimit; j+=nDeltaLat )
+        const int nYLimit = (static_cast<int>(nRasterYSize)/nDeltaLat) * nDeltaLat;
+        const int nXLimit = (static_cast<int>(nRasterXSize)/nDeltaLon) * nDeltaLon;
+        for( int j = 0; j < nYLimit; j+=nDeltaLat )
         {
-            for( i = 0; i < nXLimit; i+=nDeltaLon )
+            for( int i = 0; i < nXLimit; i+=nDeltaLon )
             {
-                int iGCP =  j * nRasterXSize + i;
-                pasGCPList[k].dfGCPX = ( double ) Longitude[iGCP]+180.0;
-                pasGCPList[k].dfGCPY = ( double ) Latitude[iGCP];
+                const int iGCP =  j * nRasterXSize + i;
+                pasGCPList[k].dfGCPX = static_cast<double>(Longitude[iGCP])+180.0;
+                pasGCPList[k].dfGCPY = static_cast<double>(Latitude[iGCP]);
 
                 pasGCPList[k].dfGCPPixel = i + 0.5;
                 pasGCPList[k++].dfGCPLine =  j + 0.5;
-
             }
         }
 
         CPLFree( Latitude );
         CPLFree( Longitude );
     }
-    
+
     if( LatitudeDatasetID > 0 )
         H5Dclose(LatitudeDatasetID);
     if( LongitudeDatasetID > 0 )
         H5Dclose(LongitudeDatasetID);
 
-        break;
-    }
-    }
-    return CE_None;
+    break;
+  }
+ }
 
+ return CE_None;
 }
+
 /************************************************************************/
 /*                          GetProjectionRef()                          */
 /************************************************************************/
@@ -892,8 +873,8 @@ const char *HDF5ImageDataset::GetProjectionRef( )
 {
     if( pszProjection )
         return pszProjection;
-    else
-        return GDALPamDataset::GetProjectionRef();
+
+    return GDALPamDataset::GetProjectionRef();
 }
 
 /************************************************************************/
@@ -905,8 +886,8 @@ int HDF5ImageDataset::GetGCPCount( )
 {
     if( nGCPCount > 0 )
         return nGCPCount;
-    else
-        return GDALPamDataset::GetGCPCount();
+
+    return GDALPamDataset::GetGCPCount();
 }
 
 /************************************************************************/
@@ -918,8 +899,8 @@ const char *HDF5ImageDataset::GetGCPProjection( )
 {
     if( nGCPCount > 0 )
         return pszGCPProjection;
-    else
-        return GDALPamDataset::GetGCPProjection();
+
+    return GDALPamDataset::GetGCPProjection();
 }
 
 /************************************************************************/
@@ -930,8 +911,8 @@ const GDAL_GCP *HDF5ImageDataset::GetGCPs( )
 {
     if( nGCPCount > 0 )
         return pasGCPList;
-    else
-        return GDALPamDataset::GetGCPs();
+
+    return GDALPamDataset::GetGCPs();
 }
 
 /************************************************************************/
@@ -945,8 +926,8 @@ CPLErr HDF5ImageDataset::GetGeoTransform( double * padfTransform )
         memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
         return CE_None;
     }
-    else
-        return GDALPamDataset::GetGeoTransform(padfTransform);
+
+    return GDALPamDataset::GetGeoTransform(padfTransform);
 }
 
 /************************************************************************/
@@ -965,20 +946,20 @@ void HDF5ImageDataset::IdentifyProductType()
 /************************************************************************/
 /*                               COSMO-SKYMED                           */
 /************************************************************************/
-    const char *pszMissionId;
 
     //Get the Mission Id as a char *, because the
     //field may not exist
-    pszMissionId = HDF5Dataset::GetMetadataItem("Mission_ID");
+    const char * const pszMissionId = HDF5Dataset::GetMetadataItem("Mission_ID");
 
     //If there is a Mission_ID field
     if(pszMissionId != NULL && strstr(GetDescription(), "QLK") == NULL)
     {
-        //Check if the mission type is CSK
-        if(EQUAL(pszMissionId,"CSK"))
+        //Check if the mission type is CSK or KMPS
+        //KMPS: Komsat-5 is Korean mission with a SAR instrument.
+        if(EQUAL(pszMissionId,"CSK") || EQUAL(pszMissionId,"KMPS"))
         {
             iSubdatasetType = CSK_PRODUCT;
-             
+
             const char *osMissionLevel = NULL;
 
             if(GetMetadataItem("Product_Type")!=NULL)
@@ -986,19 +967,19 @@ void HDF5ImageDataset::IdentifyProductType()
                 //Get the format's level
                 osMissionLevel = HDF5Dataset::GetMetadataItem("Product_Type");
 
-                if(EQUALN(osMissionLevel,"RAW",3))
+                if(STARTS_WITH_CI(osMissionLevel, "RAW"))
                     iCSKProductType  = PROD_CSK_L0;
 
-                if(EQUALN(osMissionLevel,"SCS",3))
+                if(STARTS_WITH_CI(osMissionLevel, "SCS"))
                     iCSKProductType  = PROD_CSK_L1A;
-                
-                if(EQUALN(osMissionLevel,"DGM",3))
+
+                if(STARTS_WITH_CI(osMissionLevel, "DGM"))
                     iCSKProductType  = PROD_CSK_L1B;
 
-                if(EQUALN(osMissionLevel,"GEC",3))
+                if(STARTS_WITH_CI(osMissionLevel, "GEC"))
                     iCSKProductType  = PROD_CSK_L1C;
 
-                if(EQUALN(osMissionLevel,"GTC",3))
+                if(STARTS_WITH_CI(osMissionLevel, "GTC"))
                     iCSKProductType  = PROD_CSK_L1D;
             }
         }
@@ -1012,37 +993,37 @@ void HDF5ImageDataset::IdentifyProductType()
 /**
  * Captures Geolocation information from a COSMO-SKYMED
  * file.
- * The geoid will allways be WGS84
+ * The geoid will always be WGS84
  * The projection type may be UTM or UPS, depending on the
  * latitude from the center of the image.
  * @param iProductType type of CSK subproduct, see HDF5CSKProduct
  */
 void HDF5ImageDataset::CaptureCSKGeolocation(int iProductType)
 {
-    double *dfProjFalseEastNorth;
-    double *dfProjScaleFactor;
-    double *dfCenterCoord;
-
-    //Set the ellipsoid to WGS84
+    // Set the ellipsoid to WGS84.
     oSRS.SetWellKnownGeogCS( "WGS84" );
 
     if(iProductType == PROD_CSK_L1C||iProductType == PROD_CSK_L1D)
     {
-        //Check if all the metadata attributes are present
+        double *dfProjFalseEastNorth = NULL;
+        double *dfProjScaleFactor = NULL;
+        double *dfCenterCoord = NULL;
+
+        // Check if all the metadata attributes are present.
         if(HDF5ReadDoubleAttr("Map Projection False East-North", &dfProjFalseEastNorth) == CE_Failure||
            HDF5ReadDoubleAttr("Map Projection Scale Factor", &dfProjScaleFactor) == CE_Failure||
            HDF5ReadDoubleAttr("Map Projection Centre", &dfCenterCoord) == CE_Failure||
            GetMetadataItem("Projection_ID") == NULL)
         {
-
             pszProjection = CPLStrdup("");
             pszGCPProjection = CPLStrdup("");
             CPLError( CE_Failure, CPLE_OpenFailed,
-                      "The CSK hdf5 file geolocation information is malformed\n" );
+                      "The CSK hdf5 file geolocation information is "
+                      "malformed\n" );
         }
         else
         {
-            //Fetch projection Type
+            // Fetch projection Type.
             CPLString osProjectionID = GetMetadataItem("Projection_ID");
 
             //If the projection is UTM
@@ -1053,7 +1034,7 @@ void HDF5ImageDataset::CaptureCSKGeolocation(int iProductType)
                 oSRS.SetTM(dfCenterCoord[0],
                            dfCenterCoord[1],
                            dfProjScaleFactor[0],
-                           dfProjFalseEastNorth[0], 
+                           dfProjFalseEastNorth[0],
                            dfProjFalseEastNorth[1]);
             }
             else
@@ -1063,7 +1044,7 @@ void HDF5ImageDataset::CaptureCSKGeolocation(int iProductType)
                 if(EQUAL(osProjectionID,"UPS"))
                 {
                     oSRS.SetProjCS(SRS_PT_POLAR_STEREOGRAPHIC);
-                    oSRS.SetPS(dfCenterCoord[0], 
+                    oSRS.SetPS(dfCenterCoord[0],
                                dfCenterCoord[1],
                                dfProjScaleFactor[0],
                                dfProjFalseEastNorth[0],
@@ -1096,48 +1077,42 @@ void HDF5ImageDataset::CaptureCSKGeolocation(int iProductType)
 
 /**
 * Get Geotransform information for COSMO-SKYMED files
-* In case of sucess it stores the transformation
+* In case of success it stores the transformation
 * in adfGeoTransform. In case of failure it doesn't
 * modify adfGeoTransform
 * @param iProductType type of CSK subproduct, see HDF5CSKProduct
 */
 void HDF5ImageDataset::CaptureCSKGeoTransform(int iProductType)
 {
-    double *pdOutUL;
-    double *pdLineSpacing;
-    double *pdColumnSpacing;
-
-    CPLString osULCoord;
-    CPLString osULPath;
-    CPLString osLineSpacingPath, osColumnSpacingPath;
-
     const char *pszSubdatasetName = GetSubdatasetName();
 
-    bHasGeoTransform = FALSE;
+    bHasGeoTransform = false;
     //If the product level is not L1C or L1D then
     //it doesn't have a valid projection
-    if(iProductType == PROD_CSK_L1C||iProductType == PROD_CSK_L1D)
+    if(iProductType == PROD_CSK_L1C || iProductType == PROD_CSK_L1D)
     {
         //If there is a subdataset
         if(pszSubdatasetName != NULL)
         {
-
-            osULPath = pszSubdatasetName ;
+            CPLString osULPath = pszSubdatasetName ;
             osULPath += "/Top Left East-North";
 
-            osLineSpacingPath = pszSubdatasetName;
+            CPLString osLineSpacingPath = pszSubdatasetName;
             osLineSpacingPath += "/Line Spacing";
 
-            osColumnSpacingPath = pszSubdatasetName;
+            CPLString osColumnSpacingPath = pszSubdatasetName;
             osColumnSpacingPath += "/Column Spacing";
 
+            double *pdOutUL = NULL;
+            double *pdLineSpacing = NULL;
+            double *pdColumnSpacing = NULL;
 
             //If it could find the attributes on the metadata
             if(HDF5ReadDoubleAttr(osULPath.c_str(), &pdOutUL) == CE_Failure ||
                HDF5ReadDoubleAttr(osLineSpacingPath.c_str(), &pdLineSpacing) == CE_Failure ||
                HDF5ReadDoubleAttr(osColumnSpacingPath.c_str(), &pdColumnSpacing) == CE_Failure)
             {
-                bHasGeoTransform = FALSE;
+                bHasGeoTransform = false;
             }
             else
             {
@@ -1153,7 +1128,6 @@ void HDF5ImageDataset::CaptureCSKGeoTransform(int iProductType)
                 adfGeoTransform[4] = 0;
                 adfGeoTransform[5] = -pdColumnSpacing[0];
 
-
                 CPLFree(pdOutUL);
                 CPLFree(pdLineSpacing);
                 CPLFree(pdColumnSpacing);
@@ -1182,19 +1156,16 @@ void HDF5ImageDataset::CaptureCSKGCPs(int iProductType)
     if(iProductType == PROD_CSK_L0||iProductType == PROD_CSK_L1A||
        iProductType == PROD_CSK_L1B)
     {
-        int i;
-        double *pdCornerCoordinates;
-
-        nGCPCount=4;
-        pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),4);
+        nGCPCount = 4;
+        pasGCPList = static_cast<GDAL_GCP *>( CPLCalloc(sizeof(GDAL_GCP),4) );
         CPLString osCornerName[4];
-        double pdCornerPixel[4];
-        double pdCornerLine[4];
+        double pdCornerPixel[4] = {0.0, 0.0, 0.0, 0.0};
+        double pdCornerLine[4] = {0.0, 0.0, 0.0, 0.0};
 
-        const char *pszSubdatasetName = GetSubdatasetName();
+        const char * const pszSubdatasetName = GetSubdatasetName();
 
         //Load the subdataset name first
-        for(i=0;i <4;i++)
+        for( int i=0; i < 4; i++ )
             osCornerName[i] = pszSubdatasetName;
 
         //Load the attribute name, and raster coordinates for
@@ -1216,21 +1187,23 @@ void HDF5ImageDataset::CaptureCSKGCPs(int iProductType)
         pdCornerLine[3] = GetRasterYSize();
 
         //For all the image's corners
-        for(i=0;i<4;i++)
+        for( int i=0;i<4;i++)
         {
             GDALInitGCPs( 1, pasGCPList + i );
 
             CPLFree( pasGCPList[i].pszId );
             pasGCPList[i].pszId = NULL;
 
-            //Retrieve the attributes
-            if(HDF5ReadDoubleAttr(osCornerName[i].c_str(), 
+            double *pdCornerCoordinates = NULL;
+
+            // Retrieve the attributes.
+            if(HDF5ReadDoubleAttr(osCornerName[i].c_str(),
                                   &pdCornerCoordinates) == CE_Failure)
             {
                 CPLError( CE_Failure, CPLE_OpenFailed,
                              "Error retrieving CSK GCPs\n" );
                 // Free on failure, e.g. in case of QLK subdataset.
-                for( int i = 0; i < 4; i++ )
+                for( i = 0; i < 4; i++ )
                 {
                     if( pasGCPList[i].pszId )
                         CPLFree( pasGCPList[i].pszId );
diff --git a/frmts/hdf5/iso19115_srs.cpp b/frmts/hdf5/iso19115_srs.cpp
index 78dd88a..5c10d4f 100644
--- a/frmts/hdf5/iso19115_srs.cpp
+++ b/frmts/hdf5/iso19115_srs.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: iso19115_srs.cpp 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: iso19115_srs.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  BAG Driver
  * Purpose:  Implements code to parse ISO 19115 metadata to extract a
@@ -34,13 +34,17 @@
 #include "cpl_minixml.h"
 #include "cpl_error.h"
 
-CPL_CVSID("$Id: iso19115_srs.cpp 27044 2014-03-16 23:41:27Z rouault $");
+CPL_CVSID("$Id: iso19115_srs.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+
+/* used by bagdataset.cpp */
+OGRErr OGR_SRS_ImportFromISO19115( OGRSpatialReference *poThis,
+                                   const char *pszISOXML );
 
 /************************************************************************/
 /*                     OGR_SRS_ImportFromISO19115()                     */
 /************************************************************************/
 
-OGRErr OGR_SRS_ImportFromISO19115( OGRSpatialReference *poThis, 
+OGRErr OGR_SRS_ImportFromISO19115( OGRSpatialReference *poThis,
                                    const char *pszISOXML )
 
 {
@@ -74,20 +78,20 @@ OGRErr OGR_SRS_ImportFromISO19115( OGRSpatialReference *poThis,
 /* -------------------------------------------------------------------- */
 /*      First, set the datum.                                           */
 /* -------------------------------------------------------------------- */
-    const char *pszDatum = 
+    const char *pszDatum =
         CPLGetXMLValue( psRSI, "MD_CRS.datum.RS_Identifier.code", "" );
-    
-    if( strlen(pszDatum) > 0 
+
+    if( strlen(pszDatum) > 0
         && poThis->SetWellKnownGeogCS( pszDatum ) != OGRERR_NONE )
     {
         CPLDestroyXMLNode( psRoot );
         return OGRERR_FAILURE;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Then try to extract the projection.                             */
 /* -------------------------------------------------------------------- */
-    const char *pszProjection = 
+    const char *pszProjection =
         CPLGetXMLValue( psRSI, "MD_CRS.projection.RS_Identifier.code", "" );
 
     if( EQUAL(pszProjection,"UTM") )
@@ -98,7 +102,7 @@ OGRErr OGR_SRS_ImportFromISO19115( OGRSpatialReference *poThis,
         ** We have encountered files (#5152) that identify the southern
         ** hemisphere with a false northing of 10000000 value.  The existing
         ** code checked for negative zones but it isn't clear if any actual
-        ** files use that. 
+        ** files use that.
         */
         int bNorth =  nZone > 0;
         if( bNorth )
@@ -120,7 +124,7 @@ OGRErr OGR_SRS_ImportFromISO19115( OGRSpatialReference *poThis,
     }
     else if( EQUAL(pszProjection,"Geodetic") )
     {
-        const char *pszEllipsoid = 
+        const char *pszEllipsoid =
             CPLGetXMLValue( psRSI, "MD_CRS.ellipsoid.RS_Identifier.code", "" );
 
         if( !EQUAL(pszDatum, "WGS84") ||
@@ -132,7 +136,7 @@ OGRErr OGR_SRS_ImportFromISO19115( OGRSpatialReference *poThis,
             return OGRERR_FAILURE;
         }
     }
-    else 
+    else
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "projection = %s not recognised by ISO 19115 parser.",
@@ -140,9 +144,8 @@ OGRErr OGR_SRS_ImportFromISO19115( OGRSpatialReference *poThis,
         CPLDestroyXMLNode( psRoot );
         return OGRERR_FAILURE;
     }
-    
+
     CPLDestroyXMLNode( psRoot );
 
     return OGRERR_NONE;
 }
-
diff --git a/frmts/hf2/hf2dataset.cpp b/frmts/hf2/hf2dataset.cpp
index 45c67f9..42aa869 100644
--- a/frmts/hf2/hf2dataset.cpp
+++ b/frmts/hf2/hf2dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hf2dataset.cpp 29772 2015-08-24 09:48:26Z rouault $
+ * $Id: hf2dataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  HF2 driver
  * Purpose:  GDALDataset driver for HF2/HFZ dataset.
@@ -28,14 +28,13 @@
  ****************************************************************************/
 
 #include "cpl_string.h"
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: hf2dataset.cpp 29772 2015-08-24 09:48:26Z rouault $");
+#include <limits>
 
-CPL_C_START
-void    GDALRegister_HF2(void);
-CPL_C_END
+CPL_CVSID("$Id: hf2dataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -48,7 +47,7 @@ class HF2RasterBand;
 class HF2Dataset : public GDALPamDataset
 {
     friend class HF2RasterBand;
-    
+
     VSILFILE   *fp;
     double      adfGeoTransform[6];
     char       *pszWKT;
@@ -61,14 +60,14 @@ class HF2Dataset : public GDALPamDataset
   public:
                  HF2Dataset();
     virtual     ~HF2Dataset();
-    
+
     virtual CPLErr GetGeoTransform( double * );
     virtual const char* GetProjectionRef();
-    
+
     static GDALDataset *Open( GDALOpenInfo * );
     static int          Identify( GDALOpenInfo * );
-    static GDALDataset *CreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
-                                    int bStrict, char ** papszOptions, 
+    static GDALDataset *CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
+                                    int bStrict, char ** papszOptions,
                                     GDALProgressFunc pfnProgress, void * pProgressData );
 };
 
@@ -98,19 +97,17 @@ class HF2RasterBand : public GDALPamRasterBand
 /*                           HF2RasterBand()                            */
 /************************************************************************/
 
-HF2RasterBand::HF2RasterBand( HF2Dataset *poDS, int nBand, GDALDataType eDT )
-
+HF2RasterBand::HF2RasterBand( HF2Dataset *poDSIn, int nBandIn, GDALDataType eDT ) :
+    pafBlockData(NULL),
+    nLastBlockYOff(-1)
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
 
     eDataType = eDT;
 
-    nBlockXSize = poDS->nTileSize;
+    nBlockXSize = poDSIn->nTileSize;
     nBlockYSize = 1;
-
-    pafBlockData = NULL;
-    nLastBlockYOff = -1;
 }
 
 /************************************************************************/
@@ -131,24 +128,25 @@ CPLErr HF2RasterBand::IReadBlock( int nBlockXOff, int nLineYOff,
 
 {
     HF2Dataset *poGDS = (HF2Dataset *) poDS;
+    // NOTE: the use of nBlockXSize for the y dimensions is intended
+
+    const int nXBlocks = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
+    const int nYBlocks = DIV_ROUND_UP(nRasterYSize, nBlockXSize);
 
-    int nXBlocks = (nRasterXSize + nBlockXSize - 1) / nBlockXSize;
-    int nYBlocks = (nRasterYSize + nBlockXSize - 1) / nBlockXSize;
-    
     if (!poGDS->LoadBlockMap())
         return CE_Failure;
-    
+
     if (pafBlockData == NULL)
     {
         pafBlockData = (float*)VSIMalloc3(nXBlocks * sizeof(float), poGDS->nTileSize, poGDS->nTileSize);
         if (pafBlockData == NULL)
             return CE_Failure;
     }
-    
+
     nLineYOff = nRasterYSize - 1 - nLineYOff;
 
-    int nBlockYOff = nLineYOff / nBlockXSize;
-    int nYOffInTile = nLineYOff % nBlockXSize;
+    const int nBlockYOff = nLineYOff / nBlockXSize;
+    const int nYOffInTile = nLineYOff % nBlockXSize;
 
     if (nBlockYOff != nLastBlockYOff)
     {
@@ -159,8 +157,7 @@ CPLErr HF2RasterBand::IReadBlock( int nBlockXOff, int nLineYOff,
         /* 4 * nBlockXSize is the upper bound */
         void* pabyData = CPLMalloc( 4 * nBlockXSize );
 
-        int nxoff;
-        for(nxoff = 0; nxoff < nXBlocks; nxoff++)
+        for(int nxoff = 0; nxoff < nXBlocks; nxoff++)
         {
             VSIFSeekL(poGDS->fp, poGDS->panBlockOffset[(nYBlocks - 1 - nBlockYOff) * nXBlocks + nxoff], SEEK_SET);
             float fScale, fOff;
@@ -168,12 +165,11 @@ CPLErr HF2RasterBand::IReadBlock( int nBlockXOff, int nLineYOff,
             VSIFReadL(&fOff, 4, 1, poGDS->fp);
             CPL_LSBPTR32(&fScale);
             CPL_LSBPTR32(&fOff);
-    
-            int nTileWidth = MIN(nBlockXSize, nRasterXSize - nxoff * nBlockXSize);
-            int nTileHeight = MIN(nBlockXSize, nRasterYSize - nBlockYOff * nBlockXSize);
-            
-            int j;
-            for(j=0;j<nTileHeight;j++)
+
+            const int nTileWidth = MIN(nBlockXSize, nRasterXSize - nxoff * nBlockXSize);
+            const int nTileHeight = MIN(nBlockXSize, nRasterYSize - nBlockYOff * nBlockXSize);
+
+            for(int j=0;j<nTileHeight;j++)
             {
                 GByte nWordSize;
                 VSIFReadL(&nWordSize, 1, 1, poGDS->fp);
@@ -187,23 +183,47 @@ CPLErr HF2RasterBand::IReadBlock( int nBlockXOff, int nLineYOff,
                 GInt32 nVal;
                 VSIFReadL(&nVal, 4, 1, poGDS->fp);
                 CPL_LSBPTR32(&nVal);
-                VSIFReadL(pabyData, nWordSize * (nTileWidth - 1), 1, poGDS->fp);
+                if( VSIFReadL(pabyData, static_cast<size_t>(nWordSize * (nTileWidth - 1)), 1, poGDS->fp) != 1 )
+                {
+                    CPLError(CE_Failure, CPLE_FileIO, "File too short");
+                    CPLFree(pabyData);
+                    return CE_Failure;
+                }
 #if defined(CPL_MSB)
                 if (nWordSize > 1)
                     GDALSwapWords(pabyData, nWordSize, nTileWidth - 1, nWordSize);
 #endif
 
-                pafBlockData[nxoff * nBlockXSize * nBlockXSize + j * nBlockXSize + 0] = nVal * fScale + fOff;
-                int i;
-                for(i=1;i<nTileWidth;i++)
+                double dfVal = nVal * (double)fScale + fOff;
+                if( dfVal > std::numeric_limits<float>::max() )
+                    dfVal = std::numeric_limits<float>::max();
+                else if( dfVal < std::numeric_limits<float>::min() )
+                    dfVal = std::numeric_limits<float>::min();
+                pafBlockData[nxoff * nBlockXSize * nBlockXSize + j * nBlockXSize + 0] = static_cast<float>(dfVal);
+                for(int i=1;i<nTileWidth;i++)
                 {
+                    int nInc;
                     if (nWordSize == 1)
-                        nVal += ((signed char*)pabyData)[i-1];
+                        nInc = ((signed char*)pabyData)[i-1];
                     else if (nWordSize == 2)
-                        nVal += ((GInt16*)pabyData)[i-1];
+                        nInc = ((GInt16*)pabyData)[i-1];
                     else
-                        nVal += ((GInt32*)pabyData)[i-1];
-                    pafBlockData[nxoff * nBlockXSize * nBlockXSize + j * nBlockXSize + i] = nVal * fScale + fOff;
+                        nInc = ((GInt32*)pabyData)[i-1];
+                    if( (nInc >= 0 && nVal > INT_MAX - nInc) ||
+                        (nInc == INT_MIN && nVal < 0) ||
+                        (nInc < 0 && nVal < INT_MIN - nInc ) )
+                    {
+                        CPLError(CE_Failure, CPLE_FileIO, "int32 overflow");
+                        CPLFree(pabyData);
+                        return CE_Failure;
+                    }
+                    nVal += nInc;
+                    dfVal = nVal * (double)fScale + fOff;
+                    if( dfVal > std::numeric_limits<float>::max() )
+                        dfVal = std::numeric_limits<float>::max();
+                    else if( dfVal < std::numeric_limits<float>::min() )
+                        dfVal = std::numeric_limits<float>::min();
+                    pafBlockData[nxoff * nBlockXSize * nBlockXSize + j * nBlockXSize + i] = static_cast<float>(dfVal);
                 }
             }
         }
@@ -211,7 +231,7 @@ CPLErr HF2RasterBand::IReadBlock( int nBlockXOff, int nLineYOff,
         CPLFree(pabyData);
     }
 
-    int nTileWidth = MIN(nBlockXSize, nRasterXSize - nBlockXOff * nBlockXSize);
+    const int nTileWidth = MIN(nBlockXSize, nRasterXSize - nBlockXOff * nBlockXSize);
     memcpy(pImage, pafBlockData + nBlockXOff * nBlockXSize * nBlockXSize +
                                   nYOffInTile * nBlockXSize,
            nTileWidth * sizeof(float));
@@ -223,19 +243,19 @@ CPLErr HF2RasterBand::IReadBlock( int nBlockXOff, int nLineYOff,
 /*                            ~HF2Dataset()                            */
 /************************************************************************/
 
-HF2Dataset::HF2Dataset()
+HF2Dataset::HF2Dataset() :
+    fp(NULL),
+    pszWKT(NULL),
+    panBlockOffset(NULL),
+    nTileSize(0),
+    bHasLoaderBlockMap(FALSE)
 {
-    fp = NULL;
-    pszWKT = NULL;
-    panBlockOffset = NULL;
     adfGeoTransform[0] = 0;
     adfGeoTransform[1] = 1;
     adfGeoTransform[2] = 0;
     adfGeoTransform[3] = 0;
     adfGeoTransform[4] = 0;
     adfGeoTransform[5] = 1;
-    bHasLoaderBlockMap = FALSE;
-    nTileSize = 0;
 }
 
 /************************************************************************/
@@ -263,17 +283,16 @@ int HF2Dataset::LoadBlockMap()
 
     bHasLoaderBlockMap = TRUE;
 
-    int nXBlocks = (nRasterXSize + nTileSize - 1) / nTileSize;
-    int nYBlocks = (nRasterYSize + nTileSize - 1) / nTileSize;
+    const int nXBlocks = (nRasterXSize + nTileSize - 1) / nTileSize;
+    const int nYBlocks = (nRasterYSize + nTileSize - 1) / nTileSize;
     panBlockOffset = (vsi_l_offset*) VSIMalloc3(sizeof(vsi_l_offset), nXBlocks, nYBlocks);
     if (panBlockOffset == NULL)
     {
         return FALSE;
     }
-    int i, j;
-    for(j = 0; j < nYBlocks; j++)
+    for(int j = 0; j < nYBlocks; j++)
     {
-        for(i = 0; i < nXBlocks; i++)
+        for(int i = 0; i < nXBlocks; i++)
         {
             vsi_l_offset nOff = VSIFTellL(fp);
             panBlockOffset[(nYBlocks - 1 - j) * nXBlocks + i] = nOff;
@@ -284,16 +303,21 @@ int HF2Dataset::LoadBlockMap()
             CPL_LSBPTR32(&fScale);
             CPL_LSBPTR32(&fOff);
             //printf("fScale = %f, fOff = %f\n", fScale, fOff);
-            int k;
-            int nCols = MIN(nTileSize, nRasterXSize - nTileSize *i);
-            int nLines = MIN(nTileSize, nRasterYSize - nTileSize *j);
-            for(k = 0; k < nLines; k++)
+            const int nCols = MIN(nTileSize, nRasterXSize - nTileSize *i);
+            const int nLines = MIN(nTileSize, nRasterYSize - nTileSize *j);
+            for(int k = 0; k < nLines; k++)
             {
                 GByte nWordSize;
-                VSIFReadL(&nWordSize, 1, 1, fp);
+                if( VSIFReadL(&nWordSize, 1, 1, fp) != 1 )
+                {
+                    CPLError(CE_Failure, CPLE_FileIO, "File too short");
+                    VSIFree(panBlockOffset);
+                    panBlockOffset = NULL;
+                    return FALSE;
+                }
                 //printf("nWordSize=%d\n", nWordSize);
                 if (nWordSize == 1 || nWordSize == 2 || nWordSize == 4)
-                    VSIFSeekL(fp, 4 + nWordSize * (nCols - 1), SEEK_CUR);
+                    VSIFSeekL(fp, static_cast<vsi_l_offset>(4 + nWordSize * (nCols - 1)), SEEK_CUR);
                 else
                 {
                     CPLError(CE_Failure, CPLE_AppDefined,
@@ -335,7 +359,7 @@ int HF2Dataset::Identify( GDALOpenInfo * poOpenInfo)
     if ((EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "hfz") ||
         (strlen(poOpenInfo->pszFilename) > 6 &&
          EQUAL(poOpenInfo->pszFilename + strlen(poOpenInfo->pszFilename) - 6, "hf2.gz"))) &&
-         !EQUALN(poOpenInfo->pszFilename, "/vsigzip/", 9))
+         !STARTS_WITH_CI(poOpenInfo->pszFilename, "/vsigzip/"))
     {
         osFilename = "/vsigzip/";
         osFilename += poOpenInfo->pszFilename;
@@ -379,7 +403,7 @@ GDALDataset *HF2Dataset::Open( GDALOpenInfo * poOpenInfo )
     if ((EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "hfz") ||
         (strlen(poOpenInfo->pszFilename) > 6 &&
          EQUAL(poOpenInfo->pszFilename + strlen(poOpenInfo->pszFilename) - 6, "hf2.gz"))) &&
-         !EQUALN(poOpenInfo->pszFilename, "/vsigzip/", 9))
+         !STARTS_WITH_CI(poOpenInfo->pszFilename, "/vsigzip/"))
     {
         osFilename = "/vsigzip/";
         osFilename += poOpenInfo->pszFilename;
@@ -537,9 +561,7 @@ GDALDataset *HF2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    HF2Dataset         *poDS;
-
-    poDS = new HF2Dataset();
+    HF2Dataset *poDS = new HF2Dataset();
     poDS->fp = fp;
     poDS->nRasterXSize = nXSize;
     poDS->nRasterYSize = nYSize;
@@ -566,28 +588,28 @@ GDALDataset *HF2Dataset::Open( GDALOpenInfo * poOpenInfo )
     }
     else
     {
-        int bHasSRS = FALSE;
+        bool bHasSRS = false;
         OGRSpatialReference oSRS;
-        oSRS.SetGeogCS("unknown", "unknown", "unknown", SRS_WGS84_SEMIMAJOR, SRS_WGS84_INVFLATTENING); 
+        oSRS.SetGeogCS("unknown", "unknown", "unknown", SRS_WGS84_SEMIMAJOR, SRS_WGS84_INVFLATTENING);
         if (bHasEPSGDatumCode)
         {
             if (nEPSGDatumCode == 23 || nEPSGDatumCode == 6326)
             {
-                bHasSRS = TRUE;
+                bHasSRS = true;
                 oSRS.SetWellKnownGeogCS("WGS84");
             }
             else if (nEPSGDatumCode >= 6000)
             {
                 char szName[32];
-                sprintf( szName, "EPSG:%d", nEPSGDatumCode-2000 );
+                snprintf( szName, sizeof(szName), "EPSG:%d", nEPSGDatumCode-2000 );
                 oSRS.SetWellKnownGeogCS( szName );
-                bHasSRS = TRUE;
+                bHasSRS = true;
             }
         }
 
         if (bHasUTMZone && ABS(nUTMZone) >= 1 && ABS(nUTMZone) <= 60)
         {
-            bHasSRS = TRUE;
+            bHasSRS = true;
             oSRS.SetUTM(ABS(nUTMZone), nUTMZone > 0);
         }
         if (bHasSRS)
@@ -598,8 +620,7 @@ GDALDataset *HF2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
     poDS->nBands = 1;
-    int i;
-    for( i = 0; i < poDS->nBands; i++ )
+    for( int i = 0; i < poDS->nBands; i++ )
     {
         poDS->SetBand( i+1, new HF2RasterBand( poDS, i+1, GDT_Float32 ) );
         poDS->GetRasterBand(i+1)->SetUnitType("m");
@@ -666,8 +687,8 @@ static void WriteDouble(VSILFILE* fp, double val)
 /************************************************************************/
 
 GDALDataset* HF2Dataset::CreateCopy( const char * pszFilename,
-                                     GDALDataset *poSrcDS, 
-                                     int bStrict, char ** papszOptions, 
+                                     GDALDataset *poSrcDS,
+                                     int bStrict, char ** papszOptions,
                                      GDALProgressFunc pfnProgress,
                                      void * pProgressData )
 {
@@ -677,14 +698,14 @@ GDALDataset* HF2Dataset::CreateCopy( const char * pszFilename,
     int nBands = poSrcDS->GetRasterCount();
     if (nBands == 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "HF2 driver does not support source dataset with zero band.\n");
         return NULL;
     }
 
     if (nBands != 1)
     {
-        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, 
+        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
                   "HF2 driver only uses the first band of the dataset.\n");
         if (bStrict)
             return NULL;
@@ -697,8 +718,8 @@ GDALDataset* HF2Dataset::CreateCopy( const char * pszFilename,
 /*      Get source dataset info                                         */
 /* -------------------------------------------------------------------- */
 
-    int nXSize = poSrcDS->GetRasterXSize();
-    int nYSize = poSrcDS->GetRasterYSize();
+    const int nXSize = poSrcDS->GetRasterXSize();
+    const int nYSize = poSrcDS->GetRasterYSize();
     double adfGeoTransform[6];
     poSrcDS->GetGeoTransform(adfGeoTransform);
     int bHasGeoTransform = !(adfGeoTransform[0] == 0 &&
@@ -709,7 +730,7 @@ GDALDataset* HF2Dataset::CreateCopy( const char * pszFilename,
                              adfGeoTransform[5] == 1);
     if (adfGeoTransform[2] != 0 || adfGeoTransform[4] != 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "HF2 driver does not support CreateCopy() from skewed or rotated dataset.\n");
         return NULL;
     }
@@ -729,10 +750,10 @@ GDALDataset* HF2Dataset::CreateCopy( const char * pszFilename,
 /*      Read creation options                                           */
 /* -------------------------------------------------------------------- */
     const char* pszCompressed = CSLFetchNameValue(papszOptions, "COMPRESS");
-    int bCompress = FALSE;
-    if (pszCompressed)
-        bCompress = CSLTestBoolean(pszCompressed);
-    
+    bool bCompress = false;
+    if( pszCompressed )
+        bCompress = CPLTestBool(pszCompressed);
+
     const char* pszVerticalPrecision = CSLFetchNameValue(papszOptions, "VERTICAL_PRECISION");
     if (pszVerticalPrecision)
     {
@@ -801,7 +822,7 @@ GDALDataset* HF2Dataset::CreateCopy( const char * pszFilename,
         }
         else
         {
-            double dfLinear = oSRS.GetLinearUnits();
+            const double dfLinear = oSRS.GetLinearUnits();
 
             if( ABS(dfLinear - 0.3048) < 0.0000001 )
                 nExtentUnits = 2;
@@ -833,7 +854,7 @@ GDALDataset* HF2Dataset::CreateCopy( const char * pszFilename,
     VSILFILE* fp = VSIFOpenL(osFilename.c_str(), "wb");
     if (fp == NULL)
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Cannot create %s", pszFilename );
         return NULL;
     }
@@ -848,7 +869,8 @@ GDALDataset* HF2Dataset::CreateCopy( const char * pszFilename,
     WriteInt(fp, nYSize);
     WriteShort(fp, (GInt16) nTileSize);
     WriteFloat(fp, fVertPres);
-    float fHorizScale = (float) ((fabs(adfGeoTransform[1]) + fabs(adfGeoTransform[5])) / 2);
+    const float fHorizScale
+        = (float) ((fabs(adfGeoTransform[1]) + fabs(adfGeoTransform[5])) / 2);
     WriteFloat(fp, fHorizScale);
     WriteInt(fp, nExtendedHeaderLen);
 
@@ -901,25 +923,23 @@ GDALDataset* HF2Dataset::CreateCopy( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Copy imagery                                                    */
 /* -------------------------------------------------------------------- */
-    int nXBlocks = (nXSize + nTileSize - 1) / nTileSize;
-    int nYBlocks = (nYSize + nTileSize - 1) / nTileSize;
+    const int nXBlocks = (nXSize + nTileSize - 1) / nTileSize;
+    const int nYBlocks = (nYSize + nTileSize - 1) / nTileSize;
 
-    void* pTileBuffer = (void*) VSIMalloc(nTileSize * nTileSize * (GDALGetDataTypeSize(eReqDT) / 8));
+    void* pTileBuffer = (void*) VSI_MALLOC_VERBOSE(nTileSize * nTileSize * (GDALGetDataTypeSize(eReqDT) / 8));
     if (pTileBuffer == NULL)
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
         VSIFCloseL(fp);
         return NULL;
     }
 
-    int i, j, k, l;
     CPLErr eErr = CE_None;
-    for(j=0;j<nYBlocks && eErr == CE_None;j++)
+    for(int j=0;j<nYBlocks && eErr == CE_None;j++)
     {
-        for(i=0;i<nXBlocks && eErr == CE_None;i++)
+        for(int i=0;i<nXBlocks && eErr == CE_None;i++)
         {
-            int nReqXSize = MIN(nTileSize, nXSize - i * nTileSize);
-            int nReqYSize = MIN(nTileSize, nYSize - j * nTileSize);
+            const int nReqXSize = MIN(nTileSize, nXSize - i * nTileSize);
+            const int nReqYSize = MIN(nTileSize, nYSize - j * nTileSize);
             eErr = poSrcDS->GetRasterBand(1)->RasterIO(GF_Read,
                                                 i * nTileSize, MAX(0, nYSize - (j + 1) * nTileSize),
                                                 nReqXSize, nReqYSize,
@@ -932,14 +952,14 @@ GDALDataset* HF2Dataset::CreateCopy( const char * pszFilename,
             {
                 WriteFloat(fp, 1); /* scale */
                 WriteFloat(fp, 0); /* offset */
-                for(k=0;k<nReqYSize;k++)
+                for(int k=0;k<nReqYSize;k++)
                 {
                     int nLastVal = ((short*)pTileBuffer)[(nReqYSize - k - 1) * nReqXSize + 0];
                     GByte nWordSize = 1;
-                    for(l=1;l<nReqXSize;l++)
+                    for(int l=1;l<nReqXSize;l++)
                     {
-                        int nVal = ((short*)pTileBuffer)[(nReqYSize - k - 1) * nReqXSize + l];
-                        int nDiff = nVal - nLastVal;
+                        const int nVal = ((short*)pTileBuffer)[(nReqYSize - k - 1) * nReqXSize + l];
+                        const int nDiff = nVal - nLastVal;
                         if (nDiff < -32768 || nDiff > 32767)
                         {
                             nWordSize = 4;
@@ -953,10 +973,10 @@ GDALDataset* HF2Dataset::CreateCopy( const char * pszFilename,
                     VSIFWriteL(&nWordSize, 1, 1, fp);
                     nLastVal = ((short*)pTileBuffer)[(nReqYSize - k - 1) * nReqXSize + 0];
                     WriteInt(fp, nLastVal);
-                    for(l=1;l<nReqXSize;l++)
+                    for(int l=1;l<nReqXSize;l++)
                     {
-                        int nVal = ((short*)pTileBuffer)[(nReqYSize - k - 1) * nReqXSize + l];
-                        int nDiff = nVal - nLastVal;
+                        const int nVal = ((short*)pTileBuffer)[(nReqYSize - k - 1) * nReqXSize + l];
+                        const int nDiff = nVal - nLastVal;
                         if (nWordSize == 1)
                         {
                             CPLAssert(nDiff >= -128 && nDiff <= 127);
@@ -980,7 +1000,7 @@ GDALDataset* HF2Dataset::CreateCopy( const char * pszFilename,
             {
                 float fMinVal = ((float*)pTileBuffer)[0];
                 float fMaxVal = fMinVal;
-                for(k=1;k<nReqYSize*nReqXSize;k++)
+                for(int k=1;k<nReqYSize*nReqXSize;k++)
                 {
                     float fVal = ((float*)pTileBuffer)[k];
                     if (fVal < fMinVal) fMinVal = fVal;
@@ -992,20 +1012,20 @@ GDALDataset* HF2Dataset::CreateCopy( const char * pszFilename,
                 float fOffset = fMinVal;
                 WriteFloat(fp, fScale); /* scale */
                 WriteFloat(fp, fOffset); /* offset */
-                for(k=0;k<nReqYSize;k++)
+                for(int k=0;k<nReqYSize;k++)
                 {
                     float fLastVal = ((float*)pTileBuffer)[(nReqYSize - k - 1) * nReqXSize + 0];
                     float fIntLastVal = (fLastVal - fOffset) / fScale;
                     CPLAssert(fIntLastVal >= -2147483648.0f && fIntLastVal <= 2147483647.0f);
                     int nLastVal = (int)fIntLastVal;
                     GByte nWordSize = 1;
-                    for(l=1;l<nReqXSize;l++)
+                    for(int l=1;l<nReqXSize;l++)
                     {
                         float fVal = ((float*)pTileBuffer)[(nReqYSize - k - 1) * nReqXSize + l];
                         float fIntVal = (fVal - fOffset) / fScale;
                         CPLAssert(fIntVal >= -2147483648.0f && fIntVal <= 2147483647.0f);
-                        int nVal = (int)fIntVal;
-                        int nDiff = nVal - nLastVal;
+                        const int nVal = (int)fIntVal;
+                        const int nDiff = nVal - nLastVal;
                         CPLAssert((int)((GIntBig)nVal - nLastVal) == nDiff);
                         if (nDiff < -32768 || nDiff > 32767)
                         {
@@ -1022,7 +1042,7 @@ GDALDataset* HF2Dataset::CreateCopy( const char * pszFilename,
                     fIntLastVal = (fLastVal - fOffset) / fScale;
                     nLastVal = (int)fIntLastVal;
                     WriteInt(fp, nLastVal);
-                    for(l=1;l<nReqXSize;l++)
+                    for(int l=1;l<nReqXSize;l++)
                     {
                         float fVal = ((float*)pTileBuffer)[(nReqYSize - k - 1) * nReqXSize + l];
                         float fIntVal = (fVal - fOffset) / fScale;
@@ -1074,33 +1094,29 @@ GDALDataset* HF2Dataset::CreateCopy( const char * pszFilename,
 void GDALRegister_HF2()
 
 {
-    GDALDriver  *poDriver;
-
-    if( GDALGetDriverByName( "HF2" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "HF2" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "HF2/HFZ heightfield raster" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_hf2.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "hf2" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    if( GDALGetDriverByName( "HF2" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "HF2" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "HF2/HFZ heightfield raster" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_hf2.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "hf2" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "   <Option name='VERTICAL_PRECISION' type='float' default='0.01' description='Vertical precision.'/>"
 "   <Option name='COMPRESS' type='boolean' default='false' description='Set to true to produce a GZip compressed file.'/>"
 "   <Option name='BLOCKSIZE' type='int' default='256' description='Tile size.'/>"
 "</CreationOptionList>");
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = HF2Dataset::Open;
-        poDriver->pfnIdentify = HF2Dataset::Identify;
-        poDriver->pfnCreateCopy = HF2Dataset::CreateCopy;
+    poDriver->pfnOpen = HF2Dataset::Open;
+    poDriver->pfnIdentify = HF2Dataset::Identify;
+    poDriver->pfnCreateCopy = HF2Dataset::CreateCopy;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
-
diff --git a/frmts/hfa/frmt_hfa.html b/frmts/hfa/frmt_hfa.html
index 0e28b46..a732a7d 100644
--- a/frmts/hfa/frmt_hfa.html
+++ b/frmts/hfa/frmt_hfa.html
@@ -8,8 +8,8 @@
 <h1>HFA -- Erdas Imagine .img</h1>
 
 GDAL supports Erdas Imagine .img format for read access and write.  The
-driver supports reading overviews, palettes, and georeferencing.  It 
-supports the erdas band types 
+driver supports reading overviews, palettes, and georeferencing.  It
+supports the Erdas band types
 u8, s8, u16, s16, u32, s32, f32, f64, c64 and c128.<p>
 
 Compressed and missing tiles in Erdas files should be handled properly on read.
@@ -19,7 +19,7 @@ larger than 2GiB) are also support for reading and writing.<p>
 
 Metadata reading and writing is supported at the dataset level, and for
 bands, but this is GDAL specific metadata - not metadata in an Imagine
-recognised form.  The metadata is stored in a table called GDAL_MetaData with
+recognized form.  The metadata is stored in a table called GDAL_MetaData with
 each column being a metadata item.  The title is the key and the row 1 value
 is the value.<p>
 
@@ -39,28 +39,28 @@ Creation Options:<p>
 (by default spill file created for images larger 2GiB only). Default=NO<p>
 <li> <b>COMPRESSED=YES</b>: Create file as compressed. Use of spill file disables compression. Default=NO<p>
 <li> <b>NBITS=1/2/4</b>: Create file with special sub-byte data types.<p>
-<li> <b>PIXELTYPE=[DEFAULT/SIGNEDBYTE]</b>: By setting this to SIGNEDBYTE, a 
+<li> <b>PIXELTYPE=[DEFAULT/SIGNEDBYTE]</b>: By setting this to SIGNEDBYTE, a
 new Byte file can be forced to be written as signed byte.<p>
 <li> <b>AUX=YES</b>: To create a .aux file. Default=NO<p>
 <li> <b>IGNOREUTM=YES</b> : Ignore UTM when selecting coordinate system - will use Transverse Mercator. Only used for Create() method. Default=NO<p>
 <li> <b>STATISTICS=YES</b> : To generate statistics and a histogram. Default=NO<p>
 <li> <b>DEPENDENT_FILE=filename</b> : Name of dependent file (must not have absolute path). Optional<p>
-<li> <b>FORCETOPESTRING=YES</b>: Force use of ArcGIS PE String in file instead of Imagine coordinate system format.  In some cases this improves ArcGIS coordinate system compatability.<p>
+<li> <b>FORCETOPESTRING=YES</b>: Force use of ArcGIS PE String in file instead of Imagine coordinate system format.  In some cases this improves ArcGIS coordinate system compatibility.<p>
 </ul>
 
-Erdas Imagine supports external creation of overviews (with gdaladdo for 
+Erdas Imagine supports external creation of overviews (with gdaladdo for
 instance).  To force them to be created in an .rrd file (rather than inside
 the original .img) set the global config option HFA_USE_RRD=YES).<p>
 
 Layer names can be set and retrieved with the GDALSetDescription/GDALGetDescription calls on the Raster Band objects. <p>
 
-<h2>Configuration Options</h2> 
-Currently two <a href="http://trac.osgeo.org/gdal/wiki/ConfigOptions">runtime configuration options</a> are supported by the HFA driver: 
+<h2>Configuration Options</h2>
+Currently two <a href="http://trac.osgeo.org/gdal/wiki/ConfigOptions">runtime configuration options</a> are supported by the HFA driver:
 
-<ul> 
-<li> <b>HFA_USE_RRD=YES/NO</b> : Whether to force creation of external overviews in Erdas rrd format and with .rrd file name extension (gdaladdo with combination -ro --config USE_RRD YES creates overview file with .aux extension). <p> 
+<ul>
+<li> <b>HFA_USE_RRD=YES/NO</b> : Whether to force creation of external overviews in Erdas rrd format and with .rrd file name extension (gdaladdo with combination -ro --config USE_RRD YES creates overview file with .aux extension). <p>
 <li> <b>HFA_COMPRESS_OVR=YES/NO</b> : (GDAL >= 1.11) Whether to create compressed overviews.
-Default is to only create compressed overviews when the file is compressed. <p> 
+Default is to only create compressed overviews when the file is compressed. <p>
 This configuration option can be used when building external overviews for a base image that is not in Erdas Imagine format. Resulting overview file will use the rrd structure and have .aux extension.
 <pre>
 gdaladdo out.tif --config USE_RRD YES --config HFA_COMPRESS_OVR YES 2 4 8
@@ -71,7 +71,7 @@ gdaladdo out.tif --config USE_RRD YES --config HFA_USE_RRD YES --config HFA_COMP
 </pre>
 
 </li>
-</ul> 
+</ul>
 
 See Also:<p>
 
diff --git a/frmts/hfa/hfa.h b/frmts/hfa/hfa.h
index a4fe34e..a173102 100644
--- a/frmts/hfa/hfa.h
+++ b/frmts/hfa/hfa.h
@@ -1,10 +1,10 @@
 /******************************************************************************
- * $Id: hfa.h 21687 2011-02-12 03:59:15Z warmerdam $
+ * $Id: hfa.h 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Public (C callable) interface for the Erdas Imagine reading
  *           code.  This include files, and it's implementing code depends
- *           on CPL, but not GDAL. 
+ *           on CPL, but not GDAL.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -29,8 +29,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _HFAOPEN_H_INCLUDED
-#define _HFAOPEN_H_INCLUDED
+#ifndef HFAOPEN_H_INCLUDED
+#define HFAOPEN_H_INCLUDED
 
 /* -------------------------------------------------------------------- */
 /*      Include standard portability stuff.                             */
@@ -38,11 +38,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-#ifdef HFA_PRIVATE
-typedef HFAInfo_t *HFAHandle;
-#else
-typedef void *HFAHandle;
-#endif
+typedef struct hfainfo *HFAHandle;
 
 /* -------------------------------------------------------------------- */
 /*      Structure definitions from eprj.h, with some type               */
@@ -109,12 +105,12 @@ typedef struct {
 
 typedef struct {
 	Eprj_ProType proType;		/* projection type */
-	long proNumber;			/* projection number for internal 
+	int proNumber;			/* projection number for internal
 					   projections */
 	char * proExeName;	/* projection executable name for
 					   EXTERNal projections */
 	char * proName;	/* projection name */
-	long proZone;			/* projection zone (UTM, SP only) */
+	int proZone;			/* projection zone (UTM, SP only) */
 	double proParams[15];	/* projection parameters array in the
 					   GCTP form */
 	Eprj_Spheroid proSpheroid;	/* projection spheroid */
@@ -127,19 +123,41 @@ typedef struct {
 } Efga_Polynomial;
 
 /* -------------------------------------------------------------------- */
+/*      data types.                                                     */
+/* -------------------------------------------------------------------- */
+typedef enum
+{
+    EPT_MIN = 0,
+    EPT_u1 = 0,
+    EPT_u2 = 1,
+    EPT_u4 = 2,
+    EPT_u8 = 3,
+    EPT_s8 = 4,
+    EPT_u16 = 5,
+    EPT_s16 = 6,
+    EPT_u32 = 7,
+    EPT_s32 = 8,
+    EPT_f32 = 9,
+    EPT_f64 = 10,
+    EPT_c64 = 11,
+    EPT_c128 = 12,
+    EPT_MAX = EPT_c128
+} EPTType;
+
+/* -------------------------------------------------------------------- */
 /*      Prototypes                                                      */
 /* -------------------------------------------------------------------- */
 
 CPL_C_START
 
 HFAHandle CPL_DLL HFAOpen( const char * pszFilename, const char * pszMode );
-void	CPL_DLL HFAClose( HFAHandle );
+int	CPL_DLL HFAClose( HFAHandle ); /* 0 = success */
 CPLErr HFADelete( const char *pszFilename );
 CPLErr HFARenameReferences( HFAHandle, const char *, const char * );
 
 HFAHandle CPL_DLL HFACreateLL( const char *pszFilename );
-HFAHandle CPL_DLL HFACreate( const char *pszFilename, int nXSize, int nYSize, 
-                             int nBands, int nDataType, char ** papszOptions );
+HFAHandle CPL_DLL HFACreate( const char *pszFilename, int nXSize, int nYSize,
+                             int nBands, EPTType eDataType, char ** papszOptions );
 const char CPL_DLL *HFAGetIGEFilename( HFAHandle );
 CPLErr  CPL_DLL HFAFlush( HFAHandle );
 int CPL_DLL HFACreateOverview( HFAHandle hHFA, int nBand, int nOverviewLevel,
@@ -158,37 +176,37 @@ CPLErr CPL_DLL HFASetProParameters( HFAHandle, const Eprj_ProParameters * );
 
 CPLErr CPL_DLL HFAGetRasterInfo( HFAHandle hHFA, int *pnXSize, int *pnYSize,
                                  int *pnBands );
-CPLErr CPL_DLL HFAGetBandInfo( HFAHandle hHFA, int nBand, int * pnDataType,
-                               int * pnBlockXSize, int * pnBlockYSize, 
+CPLErr CPL_DLL HFAGetBandInfo( HFAHandle hHFA, int nBand, EPTType* peDataType,
+                               int * pnBlockXSize, int * pnBlockYSize,
                                int *pnCompressionType );
 int    CPL_DLL HFAGetBandNoData( HFAHandle hHFA, int nBand, double *pdfValue );
 CPLErr CPL_DLL HFASetBandNoData( HFAHandle hHFA, int nBand, double dfValue );
 int    CPL_DLL HFAGetOverviewCount( HFAHandle hHFA, int nBand );
-CPLErr CPL_DLL HFAGetOverviewInfo( HFAHandle hHFA, int nBand, int nOverview, 
+CPLErr CPL_DLL HFAGetOverviewInfo( HFAHandle hHFA, int nBand, int nOverview,
                                    int * pnXSize, int * pnYSize,
                                    int * pnBlockXSize, int * pnBlockYSize,
-                                   int * pnHFADataType );
-CPLErr CPL_DLL HFAGetRasterBlock( HFAHandle hHFA, int nBand, int nXBlock, 
+                                   EPTType * peHFADataType );
+CPLErr CPL_DLL HFAGetRasterBlock( HFAHandle hHFA, int nBand, int nXBlock,
                                   int nYBlock, void * pData );
-CPLErr CPL_DLL HFAGetRasterBlockEx( HFAHandle hHFA, int nBand, int nXBlock, 
+CPLErr CPL_DLL HFAGetRasterBlockEx( HFAHandle hHFA, int nBand, int nXBlock,
                                     int nYBlock, void * pData, int nDataSize );
-CPLErr CPL_DLL HFAGetOverviewRasterBlock( HFAHandle hHFA, int nBand, 
+CPLErr CPL_DLL HFAGetOverviewRasterBlock( HFAHandle hHFA, int nBand,
                                           int iOverview,
                                    int nXBlock, int nYBlock, void * pData );
-CPLErr CPL_DLL HFAGetOverviewRasterBlockEx( HFAHandle hHFA, int nBand, 
+CPLErr CPL_DLL HFAGetOverviewRasterBlockEx( HFAHandle hHFA, int nBand,
                                           int iOverview,
                                    int nXBlock, int nYBlock, void * pData, int nDataSize );
-CPLErr CPL_DLL HFASetRasterBlock( HFAHandle hHFA, int nBand, 
+CPLErr CPL_DLL HFASetRasterBlock( HFAHandle hHFA, int nBand,
                                   int nXBlock, int nYBlock,
                                   void * pData );
-CPLErr CPL_DLL HFASetOverviewRasterBlock( 
-    HFAHandle hHFA, int nBand, int iOverview,int nXBlock, int nYBlock, 
+CPLErr CPL_DLL HFASetOverviewRasterBlock(
+    HFAHandle hHFA, int nBand, int iOverview,int nXBlock, int nYBlock,
     void * pData );
 const char * HFAGetBandName( HFAHandle hHFA, int nBand );
 void HFASetBandName( HFAHandle hHFA, int nBand, const char *pszName );
-int     CPL_DLL HFAGetDataTypeBits( int );
-const char CPL_DLL *HFAGetDataTypeName( int );
-CPLErr	CPL_DLL HFAGetPCT( HFAHandle, int, int *, 
+int     CPL_DLL HFAGetDataTypeBits( EPTType eDataType );
+const char CPL_DLL *HFAGetDataTypeName( EPTType eDataType );
+CPLErr	CPL_DLL HFAGetPCT( HFAHandle, int, int *,
                            double **, double **, double ** , double **,
                            double **);
 CPLErr  CPL_DLL HFASetPCT( HFAHandle, int, int, double *, double *, double *, double * );
@@ -198,57 +216,22 @@ CPLErr  CPL_DLL HFAGetDataRange( HFAHandle, int, double *, double * );
 char  CPL_DLL **HFAGetMetadata( HFAHandle hHFA, int nBand );
 CPLErr  CPL_DLL HFASetMetadata( HFAHandle hHFA, int nBand, char ** );
 char  CPL_DLL **HFAGetClassNames( HFAHandle hHFA, int nBand );
-int CPL_DLL 
-HFACreateLayer( HFAHandle psInfo, HFAEntry *poParent,
-                const char *pszLayerName,
-                int bOverview, int nBlockSize, 
-                int bCreateCompressed, int bCreateLargeRaster,
-                int bDependentLayer,
-                int nXSize, int nYSize, int nDataType, 
-                char **papszOptions,
-                
-                // these are only related to external (large) files
-                GIntBig nStackValidFlagsOffset, 
-                GIntBig nStackDataOffset,
-                int nStackCount, int nStackIndex );
 
 int CPL_DLL
-HFAReadXFormStack( HFAHandle psInfo, 
+HFAReadXFormStack( HFAHandle psInfo,
                    Efga_Polynomial **ppasPolyListForward,
                    Efga_Polynomial **ppasPolyListReverse );
 CPLErr CPL_DLL
 HFAWriteXFormStack( HFAHandle psInfo, int nBand, int nXFormCount,
                     Efga_Polynomial **ppasPolyListForward,
                     Efga_Polynomial **ppasPolyListReverse );
-int CPL_DLL 
+int CPL_DLL
 HFAEvaluateXFormStack( int nStepCount, int bForward,
                        Efga_Polynomial *pasPolyList,
                        double *pdfX, double *pdfY );
 
 char CPL_DLL **HFAReadCameraModel( HFAHandle psInfo );
 
-char *
-HFAPCSStructToWKT( const Eprj_Datum *psDatum,
-                   const Eprj_ProParameters *psPro,
-                   const Eprj_MapInfo *psMapInfo,
-                   HFAEntry *poMapInformation );
-
-/* -------------------------------------------------------------------- */
-/*      data types.                                                     */
-/* -------------------------------------------------------------------- */
-#define EPT_u1	0
-#define EPT_u2	1
-#define EPT_u4	2
-#define EPT_u8	3
-#define EPT_s8	4
-#define EPT_u16	5
-#define EPT_s16	6
-#define EPT_u32	7
-#define EPT_s32	8
-#define EPT_f32	9
-#define EPT_f64	10
-#define EPT_c64	11
-#define EPT_c128 12
 
 /* -------------------------------------------------------------------- */
 /*      Projection codes.                                               */
@@ -330,4 +313,4 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
 
 CPL_C_END
 
-#endif /* ndef _HFAOPEN_H_INCLUDED */
+#endif /* ndef HFAOPEN_H_INCLUDED */
diff --git a/frmts/hfa/hfa_overviews.cpp b/frmts/hfa/hfa_overviews.cpp
index c0b03fe..f6a12ff 100644
--- a/frmts/hfa/hfa_overviews.cpp
+++ b/frmts/hfa/hfa_overviews.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfa_overviews.cpp 25583 2013-01-30 18:48:22Z bishop $
+ * $Id: hfa_overviews.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Erdas Imagine Driver
  * Purpose:  Entry point for building overviews, used by non-imagine formats.
@@ -31,15 +31,15 @@
 #include "hfa_p.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: hfa_overviews.cpp 25583 2013-01-30 18:48:22Z bishop $");
+CPL_CVSID("$Id: hfa_overviews.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
-CPLErr HFAAuxBuildOverviews( const char *pszOvrFilename, 
+CPLErr HFAAuxBuildOverviews( const char *pszOvrFilename,
                              GDALDataset *poParentDS,
                              GDALDataset **ppoODS,
                              int nBands, int *panBandList,
-                             int nNewOverviews, int *panNewOverviewList, 
-                             const char *pszResampling, 
-                             GDALProgressFunc pfnProgress, 
+                             int nNewOverviews, int *panNewOverviewList,
+                             const char *pszResampling,
+                             GDALProgressFunc pfnProgress,
                              void *pProgressData )
 
 {
@@ -57,7 +57,7 @@ CPLErr HFAAuxBuildOverviews( const char *pszOvrFilename,
 
         for( iBand = 0; iBand < nBands; iBand++ )
         {
-            GDALRasterBand *poBand = 
+            GDALRasterBand *poBand =
                 poParentDS->GetRasterBand( panBandList[iBand] );
 
             if( iBand == 0 )
@@ -66,7 +66,7 @@ CPLErr HFAAuxBuildOverviews( const char *pszOvrFilename,
             {
                 if( eDT != poBand->GetRasterDataType() )
                 {
-                    CPLError( CE_Failure, CPLE_NotSupported, 
+                    CPLError( CE_Failure, CPLE_NotSupported,
                               "HFAAuxBuildOverviews() doesn't support a mixture of band"
                               " data types." );
                     return CE_Failure;
@@ -82,22 +82,22 @@ CPLErr HFAAuxBuildOverviews( const char *pszOvrFilename,
         GDALDriver *poHFADriver = (GDALDriver *) GDALGetDriverByName("HFA");
         if (poHFADriver == NULL)
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "HFA driver is unavailable." );
             return CE_Failure;
         }
-        
-        const char *apszOptions[4] = { "COMPRESSED=YES", "AUX=YES", 
+
+        const char *apszOptions[4] = { "COMPRESSED=YES", "AUX=YES",
                                        NULL, NULL };
-        
+
         CPLString osDepFileOpt = "DEPENDENT_FILE=";
         osDepFileOpt += CPLGetFilename(poParentDS->GetDescription());
         apszOptions[2] = osDepFileOpt.c_str();
 
-        *ppoODS = 
-            poHFADriver->Create( pszOvrFilename, 
-                                 poParentDS->GetRasterXSize(), 
-                                 poParentDS->GetRasterYSize(), 
+        *ppoODS =
+            poHFADriver->Create( pszOvrFilename,
+                                 poParentDS->GetRasterXSize(),
+                                 poParentDS->GetRasterYSize(),
                                  poParentDS->GetRasterCount(), eDT, (char **)apszOptions );
 
         if( *ppoODS == NULL )
@@ -116,7 +116,7 @@ CPLErr HFAAuxBuildOverviews( const char *pszOvrFilename,
     CPLString oAdjustedResampling = "NO_REGEN:";
     oAdjustedResampling += pszResampling;
 
-    CPLErr eErr = 
+    CPLErr eErr =
         (*ppoODS)->BuildOverviews( oAdjustedResampling,
                                    nNewOverviews, panNewOverviewList,
                                    nBands, panBandList,
@@ -124,4 +124,3 @@ CPLErr HFAAuxBuildOverviews( const char *pszOvrFilename,
 
     return eErr;
 }
-
diff --git a/frmts/hfa/hfa_p.h b/frmts/hfa/hfa_p.h
index f330c89..4c23140 100644
--- a/frmts/hfa/hfa_p.h
+++ b/frmts/hfa/hfa_p.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfa_p.h 28275 2015-01-02 18:45:58Z rouault $
+ * $Id: hfa_p.h 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Private class declarations for the HFA classes used to read
@@ -29,8 +29,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _HFA_P_H_INCLUDED
-#define _HFA_P_H_INCLUDED
+#ifndef HFA_P_H_INCLUDED
+#define HFA_P_H_INCLUDED
 
 #include "cpl_port.h"
 #include "cpl_error.h"
@@ -43,6 +43,8 @@
    void HFAStandard( int, void *);
 #endif
 
+#include "hfa.h"
+
 class HFAEntry;
 class HFAType;
 class HFADictionary;
@@ -63,7 +65,7 @@ typedef enum {
 /*      This is just a structure, and used hold info about the whole    */
 /*      dataset within hfaopen.cpp                                      */
 /************************************************************************/
-typedef struct hfainfo {
+struct hfainfo {
     VSILFILE	*fp;
 
     char	*pszPath;
@@ -75,7 +77,7 @@ typedef struct hfainfo {
     GUInt32     nEndOfFile;
     GUInt32	nRootPos;
     GUInt32	nDictionaryPos;
-    
+
     GInt16	nEntryHeaderLength;
     GInt32	nVersion;
 
@@ -96,24 +98,42 @@ typedef struct hfainfo {
     void        *pProParameters;
 
     struct hfainfo *psDependent;
-} HFAInfo_t;
+};
+
+typedef struct hfainfo HFAInfo_t;
 
 GUInt32 HFAAllocateSpace( HFAInfo_t *, GUInt32 );
 CPLErr  HFAParseBandInfo( HFAInfo_t * );
 HFAInfo_t *HFAGetDependent( HFAInfo_t *, const char * );
 HFAInfo_t *HFACreateDependent( HFAInfo_t *psBase );
-int HFACreateSpillStack( HFAInfo_t *, int nXSize, int nYSize, int nLayers, 
-                         int nBlockSize, int nDataType,
-                         GIntBig *pnValidFlagsOffset, 
+int HFACreateSpillStack( HFAInfo_t *, int nXSize, int nYSize, int nLayers,
+                         int nBlockSize, EPTType eDataType,
+                         GIntBig *pnValidFlagsOffset,
                          GIntBig *pnDataOffset );
 
-const char ** GetHFAAuxMetaDataList();
+const char * const * GetHFAAuxMetaDataList();
 
 double *HFAReadBFUniqueBins( HFAEntry *poBinFunc, int nPCTColors );
 
-#define HFA_PRIVATE
-
-#include "hfa.h"
+int CPL_DLL
+HFACreateLayer( HFAHandle psInfo, HFAEntry *poParent,
+                const char *pszLayerName,
+                int bOverview, int nBlockSize,
+                int bCreateCompressed, int bCreateLargeRaster,
+                int bDependentLayer,
+                int nXSize, int nYSize, EPTType eDataType,
+                char **papszOptions,
+
+                // these are only related to external (large) files
+                GIntBig nStackValidFlagsOffset,
+                GIntBig nStackDataOffset,
+                int nStackCount, int nStackIndex );
+
+char *
+HFAPCSStructToWKT( const Eprj_Datum *psDatum,
+                   const Eprj_ProParameters *psPro,
+                   const Eprj_MapInfo *psMapInfo,
+                   HFAEntry *poMapInformation );
 
 /************************************************************************/
 /*                               HFABand                                */
@@ -134,7 +154,7 @@ class HFABand
     int         nLayerStackCount;
     int         nLayerStackIndex;
 
-#define BFLG_VALID	0x01    
+#define BFLG_VALID	0x01
 #define BFLG_COMPRESSED	0x02
 
     int		nPCTColors;
@@ -143,7 +163,7 @@ class HFABand
 
     CPLErr	LoadBlockInfo();
     CPLErr	LoadExternalBlockInfo();
-    
+
     void ReAllocBlock( int iBlock, int nSize );
     void NullBlock( void * );
 
@@ -152,12 +172,12 @@ class HFABand
   public:
     		HFABand( HFAInfo_t *, HFAEntry * );
                 ~HFABand();
-                
+
     HFAInfo_t	*psInfo;
 
     VSILFILE	*fpExternal;
-                         
-    int		nDataType;
+
+    EPTType	eDataType;
     HFAEntry	*poNode;
 
     int		nBlockXSize;
@@ -175,10 +195,10 @@ class HFABand
     int         bOverviewsPending;
     int		nOverviews;
     HFABand     **papoOverviews;
-    
+
     CPLErr	GetRasterBlock( int nXBlock, int nYBlock, void * pData, int nDataSize );
     CPLErr	SetRasterBlock( int nXBlock, int nYBlock, void * pData );
-    
+
     const char * GetBandName();
     void SetBandName(const char *pszName);
 
@@ -206,14 +226,14 @@ class HFAEntry
 {
     int         bDirty;
     GUInt32	nFilePos;
-    
+
     HFAInfo_t	*psHFA;
     HFAEntry	*poParent;
     HFAEntry	*poPrev;
 
     GUInt32	nNextPos;
     HFAEntry	*poNext;
-    
+
     GUInt32	nChildPos;
     HFAEntry	*poChild;
 
@@ -235,56 +255,58 @@ class HFAEntry
     int         bIsMIFObject;
 
                 HFAEntry();
-                HFAEntry( HFAEntry *poContainer,
-                          const char *pszMIFObjectPath,
-                          const char * pszDictionnary, 
+                HFAEntry( const char * pszDictionary,
                           const char * pszTypeName,
                           int nDataSizeIn,
                           GByte* pabyDataIn );
-    std::vector<HFAEntry*> FindChildren( const char *pszName, 
+    std::vector<HFAEntry*> FindChildren( const char *pszName,
                                          const char *pszType,
                                          int nRecLevel,
                                          int* pbErrorDetected);
 
 public:
     static HFAEntry* New( HFAInfo_t * psHFA, GUInt32 nPos,
-                          HFAEntry * poParent, HFAEntry *poPrev);
+                          HFAEntry * poParent, HFAEntry *poPrev) CPL_WARN_UNUSED_RESULT;
 
-                 HFAEntry( HFAInfo_t *psHFA, 
+                 HFAEntry( HFAInfo_t *psHFA,
                           const char *pszNodeName,
                           const char *pszTypeName,
                           HFAEntry *poParent );
 
-                          
-    virtual     ~HFAEntry();                
-    
-    static HFAEntry*  BuildEntryFromMIFObject( HFAEntry *poContainer, const char *pszMIFObjectPath );
+    static HFAEntry* New( HFAInfo_t *psHFA,
+                          const char *pszNodeName,
+                          const char *pszTypeName,
+                          HFAEntry *poParent ) CPL_WARN_UNUSED_RESULT;
+
+    virtual     ~HFAEntry();
+
+    static HFAEntry*  BuildEntryFromMIFObject( HFAEntry *poContainer, const char *pszMIFObjectPath ) CPL_WARN_UNUSED_RESULT;
 
     CPLErr      RemoveAndDestroy();
 
-    GUInt32	GetFilePos() { return nFilePos; }
+    GUInt32	GetFilePos() CPL_WARN_UNUSED_RESULT { return nFilePos; }
 
-    const char	*GetName() { return szName; }
+    const char	*GetName() CPL_WARN_UNUSED_RESULT { return szName; }
     void SetName( const char *pszNodeName );
-    
-    const char  *GetType() { return szType; }
-    HFAType     *GetTypeObject();
-
-    GByte      *GetData() { LoadData(); return pabyData; }
-    GUInt32	GetDataPos() { return nDataPos; }
-    GUInt32	GetDataSize() { return nDataSize; }
-
-    HFAEntry	*GetChild();
-    HFAEntry	*GetNext();
-    HFAEntry    *GetNamedChild( const char * );
-    std::vector<HFAEntry*> FindChildren( const char *pszName, 
-                                         const char *pszType);
-
-    GInt32	GetIntField( const char *, CPLErr * = NULL );
-    double	GetDoubleField( const char *, CPLErr * = NULL );
-    const char	*GetStringField( const char *, CPLErr * = NULL, int *pnRemainingDataSize = NULL );
-    GIntBig     GetBigIntField( const char *, CPLErr * = NULL );
-    int         GetFieldCount( const char *, CPLErr * = NULL );
+
+    const char  *GetType() CPL_WARN_UNUSED_RESULT { return szType; }
+    HFAType     *GetTypeObject() CPL_WARN_UNUSED_RESULT;
+
+    GByte      *GetData() CPL_WARN_UNUSED_RESULT { LoadData(); return pabyData; }
+    GUInt32	GetDataPos() CPL_WARN_UNUSED_RESULT { return nDataPos; }
+    GUInt32	GetDataSize() CPL_WARN_UNUSED_RESULT { return nDataSize; }
+
+    HFAEntry	*GetChild() CPL_WARN_UNUSED_RESULT;
+    HFAEntry	*GetNext() CPL_WARN_UNUSED_RESULT;
+    HFAEntry    *GetNamedChild( const char * ) CPL_WARN_UNUSED_RESULT;
+    std::vector<HFAEntry*> FindChildren( const char *pszName,
+                                         const char *pszType) CPL_WARN_UNUSED_RESULT;
+
+    GInt32	GetIntField( const char *, CPLErr * = NULL ) CPL_WARN_UNUSED_RESULT;
+    double	GetDoubleField( const char *, CPLErr * = NULL ) CPL_WARN_UNUSED_RESULT;
+    const char	*GetStringField( const char *, CPLErr * = NULL, int *pnRemainingDataSize = NULL ) CPL_WARN_UNUSED_RESULT;
+    GIntBig     GetBigIntField( const char *, CPLErr * = NULL ) CPL_WARN_UNUSED_RESULT;
+    int         GetFieldCount( const char *, CPLErr * = NULL ) CPL_WARN_UNUSED_RESULT;
 
     CPLErr      SetIntField( const char *, int );
     CPLErr      SetDoubleField( const char *, double );
@@ -309,7 +331,7 @@ class HFAField
 {
   public:
     int		nBytes;
-    
+
     int		nItemCount;
     char	chPointer; 	/* '\0', '*' or 'p' */
     char	chItemType;	/* 1|2|4|e|... */
@@ -340,10 +362,10 @@ class HFAField
                      GByte *pabyData, GUInt32 nDataOffset, int nDataSize,
                      char chReqType, void *pValue );
 
-    void	DumpInstValue( FILE *fpOut, 
+    void	DumpInstValue( FILE *fpOut,
                      GByte *pabyData, GUInt32 nDataOffset, int nDataSize,
                      const char *pszPrefix = NULL );
-    
+
     int		GetInstBytes( GByte *, int );
     int		GetInstCount( GByte * pabyData, int nDataSize );
 };
@@ -361,7 +383,7 @@ class HFAType
 
   public:
     int		nBytes;
-    
+
     int		nFields;
     HFAField	**papoFields;
 
@@ -369,7 +391,7 @@ class HFAType
 
     		HFAType();
                 ~HFAType();
-                
+
     const char *Initialize( const char * );
 
     void	CompleteDefn( HFADictionary * );
@@ -377,7 +399,7 @@ class HFAType
     void	Dump( FILE * );
 
     int		GetInstBytes( GByte *, int );
-    int         GetInstCount( const char *pszField, 
+    int         GetInstCount( const char *pszField,
                           GByte *pabyData, GUInt32 nDataOffset, int nDataSize);
     int         ExtractInstValue( const char * pszField,
                                   GByte *pabyData, GUInt32 nDataOffset, int nDataSize,
@@ -385,7 +407,7 @@ class HFAType
     CPLErr      SetInstValue( const char * pszField,
                            GByte *pabyData, GUInt32 nDataOffset, int nDataSize,
                            char chReqType, void * pValue );
-    void	DumpInstValue( FILE *fpOut, 
+    void	DumpInstValue( FILE *fpOut,
                            GByte *pabyData, GUInt32 nDataOffset, int nDataSize,
                            const char *pszPrefix = NULL );
 };
@@ -403,7 +425,7 @@ class HFADictionary
 
     CPLString   osDictionaryText;
     int         bDictionaryTextDirty;
-    
+
                 HFADictionary( const char *pszDict );
                 ~HFADictionary();
 
@@ -419,20 +441,20 @@ class HFADictionary
 /*                             HFACompress                              */
 /*                                                                      */
 /*      Class that given a block of memory compresses the contents      */
-/*      using run  length encoding as used by Imagine.                  */
+/*      using run length encoding (RLE) as used by Imagine.             */
 /************************************************************************/
 
 class HFACompress
 {
 public:
-  HFACompress( void *pData, GUInt32 nBlockSize, int nDataType );
+  HFACompress( void *pData, GUInt32 nBlockSize, EPTType eDataType );
   ~HFACompress();
-  
+
   // This is the method that does the work.
   bool compressBlock();
 
   // static method to allow us to query whether HFA type supported
-  static bool QueryDataTypeSupported( int nHFADataType );
+  static bool QueryDataTypeSupported( EPTType eHFADataType );
 
   // Get methods - only valid after compressBlock has been called.
   GByte*  getCounts()     { return m_pCounts; };
@@ -442,7 +464,7 @@ public:
   GUInt32 getMin()        { return m_nMin; };
   GUInt32 getNumRuns()    { return m_nNumRuns; };
   GByte   getNumBits()    { return m_nNumBits; };
-  
+
 private:
   void makeCount( GUInt32 count, GByte *pCounter, GUInt32 *pnSizeCount );
   GUInt32 findMin( GByte *pNumBits );
@@ -452,21 +474,21 @@ private:
   void *m_pData;
   GUInt32 m_nBlockSize;
   GUInt32 m_nBlockCount;
-  int m_nDataType;
+  EPTType m_eDataType;
   int m_nDataTypeNumBits; // the number of bits the datatype we are trying to compress takes
-  
+
   GByte   *m_pCounts;
   GByte   *m_pCurrCount;
   GUInt32  m_nSizeCounts;
-  
+
   GByte   *m_pValues;
   GByte   *m_pCurrValues;
   GUInt32  m_nSizeValues;
-  
+
   GUInt32  m_nMin;
   GUInt32  m_nNumRuns;
   GByte    m_nNumBits; // the number of bits needed to compress the range of values in the block
-  
+
 };
 
-#endif /* ndef _HFA_P_H_INCLUDED */
+#endif /* ndef HFA_P_H_INCLUDED */
diff --git a/frmts/hfa/hfaband.cpp b/frmts/hfa/hfaband.cpp
index b70a7bc..9d8eff0 100644
--- a/frmts/hfa/hfaband.cpp
+++ b/frmts/hfa/hfaband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfaband.cpp 31391 2015-11-08 12:14:09Z rouault $
+ * $Id: hfaband.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Implementation of the HFABand, for accessing one Eimg_Layer.
@@ -30,45 +30,39 @@
 
 #include "hfa_p.h"
 #include "cpl_conv.h"
+#include "gdal_priv.h"
 
 /* include the compression code */
 
-CPL_CVSID("$Id: hfaband.cpp 31391 2015-11-08 12:14:09Z rouault $");
+CPL_CVSID("$Id: hfaband.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /*                              HFABand()                               */
 /************************************************************************/
 
-HFABand::HFABand( HFAInfo_t * psInfoIn, HFAEntry * poNodeIn )
-
+HFABand::HFABand( HFAInfo_t * psInfoIn, HFAEntry * poNodeIn ) :
+    panBlockStart(NULL),
+    panBlockSize(NULL),
+    panBlockFlag(NULL),
+    nPCTColors(-1),
+    padfPCTBins(NULL),
+    psInfo(psInfoIn),
+    fpExternal(NULL),
+    poNode(poNodeIn),
+    bNoDataSet(FALSE),
+    dfNoData(0.0),
+    bOverviewsPending(TRUE),
+    nOverviews(0),
+    papoOverviews(NULL)
 {
-    psInfo = psInfoIn;
-    poNode = poNodeIn;
-
-    bOverviewsPending = TRUE;
-
     nBlockXSize = poNodeIn->GetIntField( "blockWidth" );
     nBlockYSize = poNodeIn->GetIntField( "blockHeight" );
-    nDataType = poNodeIn->GetIntField( "pixelType" );
+    int nDataType = poNodeIn->GetIntField( "pixelType" );
 
     nWidth = poNodeIn->GetIntField( "width" );
     nHeight = poNodeIn->GetIntField( "height" );
 
-    panBlockStart = NULL;
-    panBlockSize = NULL;
-    panBlockFlag = NULL;
-
-    nPCTColors = -1;
     apadfPCT[0] = apadfPCT[1] = apadfPCT[2] = apadfPCT[3] = NULL;
-    padfPCTBins = NULL;
-
-    nOverviews = 0;
-    papoOverviews = NULL;
-
-    fpExternal = NULL;
-
-    bNoDataSet = FALSE;
-    dfNoData = 0.0;
 
     if (nWidth <= 0 || nHeight <= 0 || nBlockXSize <= 0 || nBlockYSize <= 0)
     {
@@ -77,17 +71,25 @@ HFABand::HFABand( HFAInfo_t * psInfoIn, HFAEntry * poNodeIn )
                  "HFABand::HFABand : (nWidth <= 0 || nHeight <= 0 || nBlockXSize <= 0 || nBlockYSize <= 0)");
         return;
     }
-    if (HFAGetDataTypeBits(nDataType) == 0)
+    if (nDataType < EPT_MIN || nDataType > EPT_MAX)
     {
         nWidth = nHeight = 0;
         CPLError(CE_Failure, CPLE_AppDefined,
                  "HFABand::HFABand : nDataType=%d unhandled", nDataType);
         return;
     }
+    eDataType = static_cast<EPTType>(nDataType);
+
+    nBlocksPerRow = DIV_ROUND_UP(nWidth, nBlockXSize);
+    nBlocksPerColumn = DIV_ROUND_UP(nHeight, nBlockYSize);
 
-    /* FIXME? : risk of overflow in additions and multiplication */
-    nBlocksPerRow = (nWidth + nBlockXSize - 1) / nBlockXSize;
-    nBlocksPerColumn = (nHeight + nBlockYSize - 1) / nBlockYSize;
+    if( nBlocksPerRow > INT_MAX / nBlocksPerColumn )
+    {
+        nWidth = nHeight = 0;
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "HFABand::HFABand : too big dimensions / block size");
+        return;
+    }
     nBlocks = nBlocksPerRow * nBlocksPerColumn;
 
 /* -------------------------------------------------------------------- */
@@ -95,13 +97,12 @@ HFABand::HFABand( HFAInfo_t * psInfoIn, HFAEntry * poNodeIn )
 /*      Objects?), not used by Imagine itself.                          */
 /* -------------------------------------------------------------------- */
     HFAEntry	*poNDNode = poNode->GetNamedChild("Eimg_NonInitializedValue");
-    
+
     if( poNDNode != NULL )
     {
         bNoDataSet = TRUE;
         dfNoData = poNDNode->GetDoubleField( "valueBD" );
     }
-
 }
 
 /************************************************************************/
@@ -117,12 +118,9 @@ HFABand::~HFABand()
     if( nOverviews > 0 )
         CPLFree( papoOverviews );
 
-    if ( panBlockStart )
-        CPLFree( panBlockStart );
-    if ( panBlockSize )
-        CPLFree( panBlockSize );
-    if ( panBlockFlag )
-        CPLFree( panBlockFlag );
+    CPLFree( panBlockStart );
+    CPLFree( panBlockSize );
+    CPLFree( panBlockFlag );
 
     CPLFree( apadfPCT[0] );
     CPLFree( apadfPCT[1] );
@@ -131,7 +129,7 @@ HFABand::~HFABand()
     CPLFree( padfPCTBins );
 
     if( fpExternal != NULL )
-        VSIFCloseL( fpExternal );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fpExternal ));
 }
 
 /************************************************************************/
@@ -153,49 +151,41 @@ CPLErr HFABand::LoadOverviews()
 
     if( poRRDNames != NULL )
     {
-        for( int iName = 0; TRUE; iName++ )
+        for( int iName = 0; true; iName++ )
         {
-            char	szField[128], *pszPath, *pszFilename, *pszEnd;
-            const char *pszName;
-            CPLErr      eErr;
-            HFAEntry   *poOvEntry;
-            int         i;
-            HFAInfo_t	*psHFA;
+            char  szField[128];
+            snprintf( szField, sizeof(szField), "nameList[%d].string", iName );
 
-            sprintf( szField, "nameList[%d].string", iName );
-
-            pszName = poRRDNames->GetStringField( szField, &eErr );
+            CPLErr eErr;
+            const char *pszName = poRRDNames->GetStringField( szField, &eErr );
             if( pszName == NULL || eErr != CE_None )
                 break;
 
-            pszFilename = CPLStrdup(pszName);
-            pszEnd = strstr(pszFilename,"(:");
+            char *pszFilename = CPLStrdup(pszName);
+            char *pszEnd = strstr(pszFilename,"(:");
             if( pszEnd == NULL )
             {
                 CPLFree( pszFilename );
                 continue;
             }
 
-            pszName = pszEnd + 2;
             pszEnd[0] = '\0';
 
-            char	*pszJustFilename;
-
-            pszJustFilename = CPLStrdup(CPLGetFilename(pszFilename));
-            psHFA = HFAGetDependent( psInfo, pszJustFilename );
+            char *pszJustFilename = CPLStrdup(CPLGetFilename(pszFilename));
+            HFAInfo_t *psHFA = HFAGetDependent( psInfo, pszJustFilename );
             CPLFree( pszJustFilename );
 
             // Try finding the dependent file as this file with the
             // extension .rrd.  This is intended to address problems
-            // with users changing the names of their files. 
+            // with users changing the names of their files.
             if( psHFA == NULL )
             {
-                char *pszBasename = 
+                char *pszBasename =
                     CPLStrdup(CPLGetBasename(psInfo->pszFilename));
-                
-                pszJustFilename = 
+
+                pszJustFilename =
                     CPLStrdup(CPLFormFilename(NULL, pszBasename, "rrd"));
-                CPLDebug( "HFA", "Failed to find overview file with expected name,\ntry %s instead.", 
+                CPLDebug( "HFA", "Failed to find overview file with expected name,\ntry %s instead.",
                           pszJustFilename );
                 psHFA = HFAGetDependent( psInfo, pszJustFilename );
                 CPLFree( pszJustFilename );
@@ -208,27 +198,27 @@ CPLErr HFABand::LoadOverviews()
                 continue;
             }
 
-            pszPath = pszEnd + 2;
+            char *pszPath = pszEnd + 2;
             if( pszPath[strlen(pszPath)-1] == ')' )
                 pszPath[strlen(pszPath)-1] = '\0';
 
-            for( i=0; pszPath[i] != '\0'; i++ )
+            for( int i=0; pszPath[i] != '\0'; i++ )
             {
                 if( pszPath[i] == ':' )
                     pszPath[i] = '.';
             }
 
-            poOvEntry = psHFA->poRoot->GetNamedChild( pszPath );
+            HFAEntry *poOvEntry = psHFA->poRoot->GetNamedChild( pszPath );
             CPLFree( pszFilename );
 
             if( poOvEntry == NULL )
                 continue;
 
-            /* 
-             * We have an overview node.  Instanatiate a HFABand from it, 
+            /*
+             * We have an overview node.  Instanatiate a HFABand from it,
              * and add to the list.
              */
-            papoOverviews = (HFABand **) 
+            papoOverviews = (HFABand **)
                 CPLRealloc(papoOverviews, sizeof(void*) * ++nOverviews );
             papoOverviews[nOverviews-1] = new HFABand( psHFA, poOvEntry );
             if (papoOverviews[nOverviews-1]->nWidth == 0)
@@ -248,7 +238,7 @@ CPLErr HFABand::LoadOverviews()
     HFAEntry *poBandProxyNode = poNode;
     HFAInfo_t *psOvHFA = psInfo;
 
-    if( nOverviews == 0 
+    if( nOverviews == 0
         && EQUAL(CPLGetExtension(psInfo->pszFilename),"aux") )
     {
         CPLString osRRDFilename = CPLResetExtension( psInfo->pszFilename,"rrd");
@@ -260,7 +250,7 @@ CPLErr HFABand::LoadOverviews()
         {
             psOvHFA = HFAGetDependent( psInfo, osRRDFilename );
             if( psOvHFA )
-                poBandProxyNode = 
+                poBandProxyNode =
                     psOvHFA->poRoot->GetNamedChild( poNode->GetName() );
             else
                 psOvHFA = psInfo;
@@ -274,15 +264,13 @@ CPLErr HFABand::LoadOverviews()
 /* -------------------------------------------------------------------- */
     if( nOverviews == 0 && poBandProxyNode != NULL )
     {
-        HFAEntry	*poChild;
-
-        for( poChild = poBandProxyNode->GetChild(); 
+        for( HFAEntry *poChild = poBandProxyNode->GetChild();
              poChild != NULL;
-             poChild = poChild->GetNext() ) 
+             poChild = poChild->GetNext() )
         {
             if( EQUAL(poChild->GetType(),"Eimg_Layer_SubSample") )
             {
-                papoOverviews = (HFABand **) 
+                papoOverviews = (HFABand **)
                     CPLRealloc(papoOverviews, sizeof(void*) * ++nOverviews );
                 papoOverviews[nOverviews-1] = new HFABand( psOvHFA, poChild );
                 if (papoOverviews[nOverviews-1]->nWidth == 0)
@@ -295,14 +283,12 @@ CPLErr HFABand::LoadOverviews()
             }
         }
 
-        int i1, i2; 
-        
         // bubble sort into biggest to smallest order.
-        for( i1 = 0; i1 < nOverviews; i1++ )
+        for( int i1 = 0; i1 < nOverviews; i1++ )
         {
-            for( i2 = 0; i2 < nOverviews-1; i2++ )
+            for( int i2 = 0; i2 < nOverviews-1; i2++ )
             {
-                if( papoOverviews[i2]->nWidth < 
+                if( papoOverviews[i2]->nWidth <
                     papoOverviews[i2+1]->nWidth )
                 {
                     HFABand *poTemp = papoOverviews[i2+1];
@@ -322,13 +308,10 @@ CPLErr HFABand::LoadOverviews()
 CPLErr	HFABand::LoadBlockInfo()
 
 {
-    int		iBlock;
-    HFAEntry	*poDMS;
-    
     if( panBlockFlag != NULL )
         return( CE_None );
 
-    poDMS = poNode->GetNamedChild( "RasterDMS" );
+    HFAEntry *poDMS = poNode->GetNamedChild( "RasterDMS" );
     if( poDMS == NULL )
     {
         if( poNode->GetNamedChild( "ExternalRasterDMS" ) != NULL )
@@ -340,15 +323,12 @@ CPLErr	HFABand::LoadBlockInfo()
         return CE_Failure;
     }
 
-    panBlockStart = (vsi_l_offset *)VSIMalloc2(sizeof(vsi_l_offset), nBlocks);
-    panBlockSize = (int *) VSIMalloc2(sizeof(int), nBlocks);
-    panBlockFlag = (int *) VSIMalloc2(sizeof(int), nBlocks);
+    panBlockStart = (vsi_l_offset *)VSI_MALLOC2_VERBOSE(sizeof(vsi_l_offset), nBlocks);
+    panBlockSize = (int *) VSI_MALLOC2_VERBOSE(sizeof(int), nBlocks);
+    panBlockFlag = (int *) VSI_MALLOC2_VERBOSE(sizeof(int), nBlocks);
 
     if (panBlockStart == NULL || panBlockSize == NULL || panBlockFlag == NULL)
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory,
-                 "HFABand::LoadBlockInfo : Out of memory\n");
-
         CPLFree(panBlockStart);
         CPLFree(panBlockSize);
         CPLFree(panBlockFlag);
@@ -358,37 +338,42 @@ CPLErr	HFABand::LoadBlockInfo()
         return CE_Failure;
     }
 
-    for( iBlock = 0; iBlock < nBlocks; iBlock++ )
+    for( int iBlock = 0; iBlock < nBlocks; iBlock++ )
     {
         CPLErr  eErr = CE_None;
         char	szVarName[64];
         int	nLogvalid, nCompressType;
 
-        sprintf( szVarName, "blockinfo[%d].offset", iBlock );
+        snprintf( szVarName, sizeof(szVarName), "blockinfo[%d].offset", iBlock );
         panBlockStart[iBlock] = (GUInt32)poDMS->GetIntField( szVarName, &eErr);
         if( eErr == CE_Failure )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Cannot read %s", szVarName);
             return eErr;
         }
-        
-        sprintf( szVarName, "blockinfo[%d].size", iBlock );
+
+        snprintf( szVarName, sizeof(szVarName), "blockinfo[%d].size", iBlock );
         panBlockSize[iBlock] = poDMS->GetIntField( szVarName, &eErr );
         if( eErr == CE_Failure )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Cannot read %s", szVarName);
             return eErr;
         }
-        
-        sprintf( szVarName, "blockinfo[%d].logvalid", iBlock );
+        if( panBlockSize[iBlock] < 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Invalid block size");
+            return CE_Failure;
+        }
+
+        snprintf( szVarName, sizeof(szVarName), "blockinfo[%d].logvalid", iBlock );
         nLogvalid = poDMS->GetIntField( szVarName, &eErr );
         if( eErr == CE_Failure )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Cannot read %s", szVarName);
             return eErr;
         }
-        
-        sprintf( szVarName, "blockinfo[%d].compressionType", iBlock );
+
+        snprintf( szVarName, sizeof(szVarName), "blockinfo[%d].compressionType", iBlock );
         nCompressType = poDMS->GetIntField( szVarName, &eErr );
         if( eErr == CE_Failure )
         {
@@ -413,16 +398,13 @@ CPLErr	HFABand::LoadBlockInfo()
 CPLErr	HFABand::LoadExternalBlockInfo()
 
 {
-    int		iBlock;
-    HFAEntry	*poDMS;
-    
     if( panBlockFlag != NULL )
         return( CE_None );
 
 /* -------------------------------------------------------------------- */
 /*      Get the info structure.                                         */
 /* -------------------------------------------------------------------- */
-    poDMS = poNode->GetNamedChild( "ExternalRasterDMS" );
+    HFAEntry *poDMS = poNode->GetNamedChild( "ExternalRasterDMS" );
     CPLAssert( poDMS != NULL );
 
     nLayerStackCount = poDMS->GetIntField( "layerStackCount" );
@@ -445,20 +427,19 @@ CPLErr	HFABand::LoadExternalBlockInfo()
 	fpExternal = VSIFOpenL( pszFullFilename, "r+b" );
     if( fpExternal == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Unable to open external data file:\n%s\n", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Unable to open external data file:\n%s\n",
                   pszFullFilename );
         return CE_Failure;
     }
-   
+
 /* -------------------------------------------------------------------- */
 /*      Verify header.                                                  */
 /* -------------------------------------------------------------------- */
     char	szHeader[49];
 
-    VSIFReadL( szHeader, 49, 1, fpExternal );
-
-    if( strncmp( szHeader, "ERDAS_IMG_EXTERNAL_RASTER", 26 ) != 0 )
+    if( VSIFReadL( szHeader, 49, 1, fpExternal ) != 1 ||
+        !STARTS_WITH( szHeader, "ERDAS_IMG_EXTERNAL_RASTER") )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Raw data file %s appears to be corrupt.\n",
@@ -469,35 +450,27 @@ CPLErr	HFABand::LoadExternalBlockInfo()
 /* -------------------------------------------------------------------- */
 /*      Allocate blockmap.                                              */
 /* -------------------------------------------------------------------- */
-    panBlockFlag = (int *) VSIMalloc2(sizeof(int), nBlocks);
+    panBlockFlag = (int *) VSI_MALLOC2_VERBOSE(sizeof(int), nBlocks);
     if (panBlockFlag == NULL)
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory,
-                 "HFABand::LoadExternalBlockInfo : Out of memory\n");
         return CE_Failure;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Load the validity bitmap.                                       */
 /* -------------------------------------------------------------------- */
-    unsigned char *pabyBlockMap;
-    int		  nBytesPerRow;
-
-    nBytesPerRow = (nBlocksPerRow + 7) / 8;
-    pabyBlockMap = (unsigned char *) 
-        VSIMalloc(nBytesPerRow*nBlocksPerColumn+20);
+    const int nBytesPerRow = (nBlocksPerRow + 7) / 8;
+    unsigned char *pabyBlockMap = (unsigned char *)
+        VSI_MALLOC_VERBOSE(nBytesPerRow*nBlocksPerColumn+20);
     if (pabyBlockMap == NULL)
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory,
-                 "HFABand::LoadExternalBlockInfo : Out of memory\n");
         return CE_Failure;
     }
 
-    VSIFSeekL( fpExternal, 
-               poDMS->GetBigIntField( "layerStackValidFlagsOffset" ),  
-               SEEK_SET );
-
-    if( VSIFReadL( pabyBlockMap, nBytesPerRow * nBlocksPerColumn + 20, 1, 
+    if( VSIFSeekL( fpExternal,
+               poDMS->GetBigIntField( "layerStackValidFlagsOffset" ),
+               SEEK_SET ) < 0 ||
+        VSIFReadL( pabyBlockMap, nBytesPerRow * nBlocksPerColumn + 20, 1,
                    fpExternal ) != 1 )
     {
         CPLError( CE_Failure, CPLE_FileIO,
@@ -511,15 +484,14 @@ CPLErr	HFABand::LoadExternalBlockInfo()
 /*      Validity is determined from the validity bitmap.                */
 /* -------------------------------------------------------------------- */
     nBlockStart = poDMS->GetBigIntField( "layerStackDataOffset" );
-    nBlockSize = (nBlockXSize*nBlockYSize*HFAGetDataTypeBits(nDataType)+7) / 8;
+    nBlockSize = (nBlockXSize*static_cast<vsi_l_offset>(nBlockYSize)
+                  *HFAGetDataTypeBits(eDataType)+7) / 8;
 
-    for( iBlock = 0; iBlock < nBlocks; iBlock++ )
+    for( int iBlock = 0; iBlock < nBlocks; iBlock++ )
     {
-        int	nRow, nColumn, nBit;
-
-        nColumn = iBlock % nBlocksPerRow;
-        nRow = iBlock / nBlocksPerRow;
-        nBit = nRow * nBytesPerRow * 8 + nColumn + 20 * 8;
+        const int nColumn = iBlock % nBlocksPerRow;
+        const int nRow = iBlock / nBlocksPerRow;
+        const int nBit = nRow * nBytesPerRow * 8 + nColumn + 20 * 8;
 
         if( (pabyBlockMap[nBit>>3] >> (nBit&7)) & 0x1 )
             panBlockFlag[iBlock] = BFLG_VALID;
@@ -542,25 +514,25 @@ CPLErr	HFABand::LoadExternalBlockInfo()
     if (nSrcBytes < (n)) goto not_enough_bytes;
 
 static CPLErr UncompressBlock( GByte *pabyCData, int nSrcBytes,
-                               GByte *pabyDest, int nMaxPixels, 
-                               int nDataType )
+                               GByte *pabyDest, int nMaxPixels,
+                               EPTType eDataType )
 
 {
     GUInt32  nDataMin;
-    int      nNumBits, nPixelsOutput=0;			
+    int      nNumBits, nPixelsOutput=0;
     GInt32   nNumRuns, nDataOffset;
     GByte *pabyCounter, *pabyValues;
     int   nValueBitOffset;
     int nCounterOffset;
-    
+
     CHECK_ENOUGH_BYTES(13);
 
     memcpy( &nDataMin, pabyCData, 4 );
     nDataMin = CPL_LSBWORD32( nDataMin );
-        
+
     memcpy( &nNumRuns, pabyCData+4, 4 );
     nNumRuns = CPL_LSBWORD32( nNumRuns );
-        
+
     memcpy( &nDataOffset, pabyCData+8, 4 );
     nDataOffset = CPL_LSBWORD32( nDataOffset );
 
@@ -574,7 +546,7 @@ static CPLErr UncompressBlock( GByte *pabyCData, int nSrcBytes,
     {
         pabyValues = pabyCData + 13;
         nValueBitOffset = 0;
-        
+
         if (nNumBits > INT_MAX / nMaxPixels ||
             nNumBits * nMaxPixels > INT_MAX - 7 ||
             (nNumBits * nMaxPixels + 7)/8 > INT_MAX - 13)
@@ -649,18 +621,18 @@ static CPLErr UncompressBlock( GByte *pabyCData, int nSrcBytes,
 /* -------------------------------------------------------------------- */
 /*      Now apply to the output buffer in a type specific way.          */
 /* -------------------------------------------------------------------- */
-            if( nDataType == EPT_u8 )
+            if( eDataType == EPT_u8 )
             {
                 ((GByte *) pabyDest)[nPixelsOutput] = (GByte) nDataValue;
             }
-            else if( nDataType == EPT_u1 )
+            else if( eDataType == EPT_u1 )
             {
                 if( nDataValue == 1 )
                     pabyDest[nPixelsOutput>>3] |= (1 << (nPixelsOutput & 0x7));
                 else
                     pabyDest[nPixelsOutput>>3] &= ~(1<<(nPixelsOutput & 0x7));
             }
-            else if( nDataType == EPT_u2 )
+            else if( eDataType == EPT_u2 )
             {
                 if( (nPixelsOutput & 0x3) == 0 )
                     pabyDest[nPixelsOutput>>2] = (GByte) nDataValue;
@@ -671,34 +643,34 @@ static CPLErr UncompressBlock( GByte *pabyCData, int nSrcBytes,
                 else
                     pabyDest[nPixelsOutput>>2] |= (GByte) (nDataValue<<6);
             }
-            else if( nDataType == EPT_u4 )
+            else if( eDataType == EPT_u4 )
             {
                 if( (nPixelsOutput & 0x1) == 0 )
                     pabyDest[nPixelsOutput>>1] = (GByte) nDataValue;
                 else
                     pabyDest[nPixelsOutput>>1] |= (GByte) (nDataValue<<4);
             }
-            else if( nDataType == EPT_s8 ) 
-            { 
-                ((GByte *) pabyDest)[nPixelsOutput] = (GByte) nDataValue; 
-            } 
-            else if( nDataType == EPT_u16 )
+            else if( eDataType == EPT_s8 )
+            {
+                ((GByte *) pabyDest)[nPixelsOutput] = (GByte) nDataValue;
+            }
+            else if( eDataType == EPT_u16 )
             {
                 ((GUInt16 *) pabyDest)[nPixelsOutput] = (GUInt16) nDataValue;
             }
-            else if( nDataType == EPT_s16 )
+            else if( eDataType == EPT_s16 )
             {
                 ((GInt16 *) pabyDest)[nPixelsOutput] = (GInt16) nDataValue;
             }
-            else if( nDataType == EPT_s32 )
+            else if( eDataType == EPT_s32 )
             {
                 ((GInt32 *) pabyDest)[nPixelsOutput] = nDataValue;
             }
-            else if( nDataType == EPT_u32 )
+            else if( eDataType == EPT_u32 )
             {
                 ((GUInt32 *) pabyDest)[nPixelsOutput] = nDataValue;
             }
-            else if( nDataType == EPT_f32 )
+            else if( eDataType == EPT_f32 )
             {
 /* -------------------------------------------------------------------- */
 /*      Note, floating point values are handled as if they were signed  */
@@ -710,7 +682,9 @@ static CPLErr UncompressBlock( GByte *pabyCData, int nSrcBytes,
             }
             else
             {
-                CPLAssert( FALSE );
+                CPLError( CE_Failure, CPLE_AppDefined,
+                      "Attempt to uncompress an unsupported pixel data type.");
+                return CE_Failure;
             }
         }
 
@@ -737,18 +711,16 @@ static CPLErr UncompressBlock( GByte *pabyCData, int nSrcBytes,
         return CE_Failure;
     }
     CHECK_ENOUGH_BYTES(nDataOffset + (nNumBits * nNumRuns + 7)/8);
-    
+
     pabyCounter = pabyCData + 13;
     nCounterOffset = 13;
     pabyValues = pabyCData + nDataOffset;
     nValueBitOffset = 0;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Loop over runs.                                                 */
 /* -------------------------------------------------------------------- */
-    int    iRun;
-
-    for( iRun = 0; iRun < nNumRuns; iRun++ )
+    for( int iRun = 0; iRun < nNumRuns; iRun++ )
     {
         int	nRepeatCount = 0;
         int	nDataValue;
@@ -847,88 +819,74 @@ static CPLErr UncompressBlock( GByte *pabyCData, int nSrcBytes,
 /* -------------------------------------------------------------------- */
 /*      Now apply to the output buffer in a type specific way.          */
 /* -------------------------------------------------------------------- */
-        if( nPixelsOutput + nRepeatCount > nMaxPixels )
+        if( nRepeatCount > INT_MAX - nPixelsOutput ||
+            nPixelsOutput + nRepeatCount > nMaxPixels )
         {
             CPLDebug("HFA", "Repeat count too big : %d", nRepeatCount);
             nRepeatCount = nMaxPixels - nPixelsOutput;
         }
-        
-        if( nDataType == EPT_u8 )
+
+        if( eDataType == EPT_u8 )
         {
-            int		i;
-            
-            for( i = 0; i < nRepeatCount; i++ )
+            for( int i = 0; i < nRepeatCount; i++ )
             {
                 //CPLAssert( nDataValue < 256 );
                 ((GByte *) pabyDest)[nPixelsOutput++] = (GByte)nDataValue;
             }
         }
-        else if( nDataType == EPT_u16 )
+        else if( eDataType == EPT_u16 )
         {
-            int		i;
-            
-            for( i = 0; i < nRepeatCount; i++ )
+            for( int i = 0; i < nRepeatCount; i++ )
             {
                 ((GUInt16 *) pabyDest)[nPixelsOutput++] = (GUInt16)nDataValue;
             }
         }
-        else if( nDataType == EPT_s8 )
+        else if( eDataType == EPT_s8 )
         {
-            int		i;
-            
-            for( i = 0; i < nRepeatCount; i++ )
+            for( int i = 0; i < nRepeatCount; i++ )
             {
                 //CPLAssert( nDataValue < 256 );
                 ((GByte *) pabyDest)[nPixelsOutput++] = (GByte)nDataValue;
             }
         }
-        else if( nDataType == EPT_s16 )
+        else if( eDataType == EPT_s16 )
         {
-            int		i;
-            
-            for( i = 0; i < nRepeatCount; i++ )
+            for( int i = 0; i < nRepeatCount; i++ )
             {
                 ((GInt16 *) pabyDest)[nPixelsOutput++] = (GInt16)nDataValue;
             }
         }
-        else if( nDataType == EPT_u32 )
+        else if( eDataType == EPT_u32 )
         {
-            int		i;
-            
-            for( i = 0; i < nRepeatCount; i++ )
+            for( int i = 0; i < nRepeatCount; i++ )
             {
                 ((GUInt32 *) pabyDest)[nPixelsOutput++] = (GUInt32)nDataValue;
             }
         }
-        else if( nDataType == EPT_s32 )
+        else if( eDataType == EPT_s32 )
         {
-            int		i;
-            
-            for( i = 0; i < nRepeatCount; i++ )
+            for( int i = 0; i < nRepeatCount; i++ )
             {
                 ((GInt32 *) pabyDest)[nPixelsOutput++] = (GInt32)nDataValue;
             }
         }
-        else if( nDataType == EPT_f32 )
+        else if( eDataType == EPT_f32 )
         {
-            int		i;
             float fDataValue;
 
             memcpy( &fDataValue, &nDataValue, 4);
-            for( i = 0; i < nRepeatCount; i++ )
+            for( int i = 0; i < nRepeatCount; i++ )
             {
                 ((float *) pabyDest)[nPixelsOutput++] = fDataValue;
             }
         }
-        else if( nDataType == EPT_u1 )
+        else if( eDataType == EPT_u1 )
         {
-            int		i;
-
             //CPLAssert( nDataValue == 0 || nDataValue == 1 );
-            
+
             if( nDataValue == 1 )
             {
-                for( i = 0; i < nRepeatCount; i++ )
+                for( int i = 0; i < nRepeatCount; i++ )
                 {
                     pabyDest[nPixelsOutput>>3] |= (1 << (nPixelsOutput & 0x7));
                     nPixelsOutput++;
@@ -936,20 +894,18 @@ static CPLErr UncompressBlock( GByte *pabyCData, int nSrcBytes,
             }
             else
             {
-                for( i = 0; i < nRepeatCount; i++ )
+                for( int i = 0; i < nRepeatCount; i++ )
                 {
                     pabyDest[nPixelsOutput>>3] &= ~(1<<(nPixelsOutput & 0x7));
                     nPixelsOutput++;
                 }
             }
         }
-        else if( nDataType == EPT_u2 )
+        else if( eDataType == EPT_u2 )
         {
-            int		i;
-
             //CPLAssert( nDataValue >= 0 && nDataValue < 4 );
 
-            for( i = 0; i < nRepeatCount; i++ )
+            for( int i = 0; i < nRepeatCount; i++ )
             {
                 if( (nPixelsOutput & 0x3) == 0 )
                     pabyDest[nPixelsOutput>>2] = (GByte) nDataValue;
@@ -962,13 +918,11 @@ static CPLErr UncompressBlock( GByte *pabyCData, int nSrcBytes,
                 nPixelsOutput++;
             }
         }
-        else if( nDataType == EPT_u4 )
+        else if( eDataType == EPT_u4 )
         {
-            int		i;
-
             //CPLAssert( nDataValue >= 0 && nDataValue < 16 );
-            
-            for( i = 0; i < nRepeatCount; i++ )
+
+            for( int i = 0; i < nRepeatCount; i++ )
             {
                 if( (nPixelsOutput & 0x1) == 0 )
                     pabyDest[nPixelsOutput>>1] = (GByte) nDataValue;
@@ -980,14 +934,14 @@ static CPLErr UncompressBlock( GByte *pabyCData, int nSrcBytes,
         }
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Attempt to uncompress an unsupported pixel data type.");
             return CE_Failure;
         }
     }
 
     return CE_None;
-    
+
   not_enough_bytes:
 
     CPLError(CE_Failure, CPLE_AppDefined, "Not enough bytes in compressed block");
@@ -1004,14 +958,14 @@ static CPLErr UncompressBlock( GByte *pabyCData, int nSrcBytes,
 void HFABand::NullBlock( void *pData )
 
 {
-    int nChunkSize = MAX(1,HFAGetDataTypeBits(nDataType)/8);
+    int nChunkSize = MAX(1,HFAGetDataTypeBits(eDataType)/8);
     int nWords = nBlockXSize * nBlockYSize;
 
     if( !bNoDataSet )
     {
 #ifdef ESRI_BUILD
         // We want special defaulting for 1 bit data in ArcGIS.
-        if ( nDataType >= EPT_u2 )
+        if ( eDataType >= EPT_u2 )
             memset( pData,   0, nChunkSize*nWords );
         else
             memset( pData, 255, nChunkSize*nWords );
@@ -1021,10 +975,9 @@ void HFABand::NullBlock( void *pData )
     }
     else
     {
-        GByte abyTmp[16];
-        int i;
+        GByte abyTmp[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 
-        switch( nDataType )
+        switch( eDataType )
         {
           case EPT_u1:
           {
@@ -1052,22 +1005,22 @@ void HFABand::NullBlock( void *pData )
 
           case EPT_u4:
           {
-              unsigned char byVal = 
+              unsigned char byVal =
                   (unsigned char) MAX(0,MIN(15,(int)dfNoData));
 
               nWords = (nWords + 1)/2;
-                  
+
               ((unsigned char *) abyTmp)[0] = byVal + (byVal << 4);
           }
           break;
 
           case EPT_u8:
-            ((unsigned char *) abyTmp)[0] = 
+            ((unsigned char *) abyTmp)[0] =
                 (unsigned char) MAX(0,MIN(255,(int)dfNoData));
             break;
 
           case EPT_s8:
-            ((signed char *) abyTmp)[0] = 
+            ((signed char *) abyTmp)[0] =
                 (signed char) MAX(-128,MIN(127,(int)dfNoData));
             break;
 
@@ -1127,9 +1080,9 @@ void HFABand::NullBlock( void *pData )
             break;
           }
         }
-            
-        for( i = 0; i < nWords; i++ )
-            memcpy( ((GByte *) pData) + nChunkSize * i, 
+
+        for( int i = 0; i < nWords; i++ )
+            memcpy( ((GByte *) pData) + nChunkSize * i,
                     abyTmp, nChunkSize );
     }
 
@@ -1142,13 +1095,10 @@ void HFABand::NullBlock( void *pData )
 CPLErr HFABand::GetRasterBlock( int nXBlock, int nYBlock, void * pData, int nDataSize )
 
 {
-    int		iBlock;
-    VSILFILE	*fpData;
-
     if( LoadBlockInfo() != CE_None )
         return CE_Failure;
 
-    iBlock = nXBlock + nYBlock * nBlocksPerRow;
+    int iBlock = nXBlock + nYBlock * nBlocksPerRow;
 
 /* -------------------------------------------------------------------- */
 /*      If the block isn't valid, we just return all zeros, and an	*/
@@ -1164,6 +1114,7 @@ CPLErr HFABand::GetRasterBlock( int nXBlock, int nYBlock, void * pData, int nDat
 /*      Otherwise we really read the data.                              */
 /* -------------------------------------------------------------------- */
     vsi_l_offset    nBlockOffset;
+    VSILFILE	*fpData;
 
     // Calculate block offset in case we have spill file. Use predefined
     // block map otherwise.
@@ -1186,16 +1137,16 @@ CPLErr HFABand::GetRasterBlock( int nXBlock, int nYBlock, void * pData, int nDat
 	// in update state and data for this block will be available later
         if ( psInfo->eAccess == HFA_Update )
         {
-            memset( pData, 0, 
-                    HFAGetDataTypeBits(nDataType)*nBlockXSize*nBlockYSize/8 );
+            memset( pData, 0,
+                    HFAGetDataTypeBits(eDataType)*nBlockXSize*nBlockYSize/8 );
             return CE_None;
         }
         else
         {
-            CPLError( CE_Failure, CPLE_FileIO, 
+            CPLError( CE_Failure, CPLE_FileIO,
                       "Seek to %x:%08x on %p failed\n%s",
                       (int) (nBlockOffset >> 32),
-                      (int) (nBlockOffset & 0xffffffff), 
+                      (int) (nBlockOffset & 0xffffffff),
                       fpData, VSIStrerror(errno) );
             return CE_Failure;
         }
@@ -1207,14 +1158,9 @@ CPLErr HFABand::GetRasterBlock( int nXBlock, int nYBlock, void * pData, int nDat
 /* -------------------------------------------------------------------- */
     if( panBlockFlag[iBlock] & BFLG_COMPRESSED )
     {
-        GByte 	*pabyCData;
-        CPLErr  eErr;
-
-        pabyCData = (GByte *) VSIMalloc( (size_t) nBlockSize );
+        GByte *pabyCData = (GByte *) VSI_MALLOC_VERBOSE( (size_t) nBlockSize );
         if (pabyCData == NULL)
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory,
-                      "HFABand::GetRasterBlock : Out of memory\n");
             return CE_Failure;
         }
 
@@ -1225,25 +1171,25 @@ CPLErr HFABand::GetRasterBlock( int nXBlock, int nYBlock, void * pData, int nDat
 	    // XXX: Suppose that file in update state
             if ( psInfo->eAccess == HFA_Update )
             {
-                memset( pData, 0, 
-                    HFAGetDataTypeBits(nDataType)*nBlockXSize*nBlockYSize/8 );
+                memset( pData, 0,
+                    HFAGetDataTypeBits(eDataType)*nBlockXSize*nBlockYSize/8 );
                 return CE_None;
             }
             else
             {
                 CPLError( CE_Failure, CPLE_FileIO,
-                          "Read of %d bytes at %x:%08x on %p failed.\n%s", 
-                          (int) nBlockSize, 
+                          "Read of %d bytes at %x:%08x on %p failed.\n%s",
+                          (int) nBlockSize,
                           (int) (nBlockOffset >> 32),
-                          (int) (nBlockOffset & 0xffffffff), 
+                          (int) (nBlockOffset & 0xffffffff),
                           fpData, VSIStrerror(errno) );
                 return CE_Failure;
             }
         }
 
-        eErr = UncompressBlock( pabyCData, (int) nBlockSize,
-                                (GByte *) pData, nBlockXSize*nBlockYSize,
-                                nDataType );
+        CPLErr eErr = UncompressBlock( pabyCData, (int) nBlockSize,
+                                       (GByte *) pData, nBlockXSize*nBlockYSize,
+                                       eDataType );
 
         CPLFree( pabyCData );
 
@@ -1263,15 +1209,15 @@ CPLErr HFABand::GetRasterBlock( int nXBlock, int nYBlock, void * pData, int nDat
 
     if( VSIFReadL( pData, (size_t) nBlockSize, 1, fpData ) != 1 )
     {
-	memset( pData, 0, 
-	    HFAGetDataTypeBits(nDataType)*nBlockXSize*nBlockYSize/8 );
+	memset( pData, 0,
+	    HFAGetDataTypeBits(eDataType)*nBlockXSize*nBlockYSize/8 );
 
         if( fpData != fpExternal )
-            CPLDebug( "HFABand", 
-                      "Read of %x:%08x bytes at %d on %p failed.\n%s", 
-                      (int) nBlockSize, 
+            CPLDebug( "HFABand",
+                      "Read of %x:%08x bytes at %d on %p failed.\n%s",
+                      (int) nBlockSize,
                       (int) (nBlockOffset >> 32),
-                      (int) (nBlockOffset & 0xffffffff), 
+                      (int) (nBlockOffset & 0xffffffff),
                       fpData, VSIStrerror(errno) );
 
 	return CE_None;
@@ -1283,28 +1229,28 @@ CPLErr HFABand::GetRasterBlock( int nXBlock, int nYBlock, void * pData, int nDat
 /*      files.                                                          */
 /* -------------------------------------------------------------------- */
 
-#ifdef CPL_MSB             
-    if( HFAGetDataTypeBits(nDataType) == 16 )
+#ifdef CPL_MSB
+    if( HFAGetDataTypeBits(eDataType) == 16 )
     {
         for( int ii = 0; ii < nBlockXSize*nBlockYSize; ii++ )
             CPL_SWAP16PTR( ((unsigned char *) pData) + ii*2 );
     }
-    else if( HFAGetDataTypeBits(nDataType) == 32 )
+    else if( HFAGetDataTypeBits(eDataType) == 32 )
     {
         for( int ii = 0; ii < nBlockXSize*nBlockYSize; ii++ )
             CPL_SWAP32PTR( ((unsigned char *) pData) + ii*4 );
     }
-    else if( nDataType == EPT_f64 )
+    else if( eDataType == EPT_f64 )
     {
         for( int ii = 0; ii < nBlockXSize*nBlockYSize; ii++ )
             CPL_SWAP64PTR( ((unsigned char *) pData) + ii*8 );
     }
-    else if( nDataType == EPT_c64 )
+    else if( eDataType == EPT_c64 )
     {
         for( int ii = 0; ii < nBlockXSize*nBlockYSize*2; ii++ )
             CPL_SWAP32PTR( ((unsigned char *) pData) + ii*4 );
     }
-    else if( nDataType == EPT_c128 )
+    else if( eDataType == EPT_c128 )
     {
         for( int ii = 0; ii < nBlockXSize*nBlockYSize*2; ii++ )
             CPL_SWAP64PTR( ((unsigned char *) pData) + ii*8 );
@@ -1321,7 +1267,7 @@ CPLErr HFABand::GetRasterBlock( int nXBlock, int nYBlock, void * pData, int nDat
 void HFABand::ReAllocBlock( int iBlock, int nSize )
 {
     /* For compressed files - need to realloc the space for the block */
-	
+
     // TODO: Should check to see if panBlockStart[iBlock] is not zero then do a HFAFreeSpace()
     // but that doesn't exist yet.
     // Instead as in interim measure it will reuse the existing block if
@@ -1330,24 +1276,28 @@ void HFABand::ReAllocBlock( int iBlock, int nSize )
     {
         panBlockSize[iBlock] = nSize;
         //fprintf( stderr, "Reusing block %d\n", iBlock );
+        return;
     }
-    else
+
+    panBlockStart[iBlock] = HFAAllocateSpace( psInfo, nSize );
+
+    panBlockSize[iBlock] = nSize;
+
+    // need to re - write this info to the RasterDMS node
+    HFAEntry	*poDMS = poNode->GetNamedChild( "RasterDMS" );
+
+    if (!poDMS)
     {
-        panBlockStart[iBlock] = HFAAllocateSpace( psInfo, nSize );
-	
-        panBlockSize[iBlock] = nSize;
-	
-        // need to re - write this info to the RasterDMS node
-        HFAEntry	*poDMS = poNode->GetNamedChild( "RasterDMS" );
-	 	
-        char	szVarName[64];
-        sprintf( szVarName, "blockinfo[%d].offset", iBlock );
-        poDMS->SetIntField( szVarName, (int) panBlockStart[iBlock] );
-		
-        sprintf( szVarName, "blockinfo[%d].size", iBlock );
-        poDMS->SetIntField( szVarName, panBlockSize[iBlock] );
+        CPLError(CE_Failure, CPLE_FileIO, "Unable to load RasterDMS");
+        return;
     }
 
+    char	szVarName[64];
+    snprintf( szVarName, sizeof(szVarName), "blockinfo[%d].offset", iBlock );
+    poDMS->SetIntField( szVarName, (int) panBlockStart[iBlock] );
+
+    snprintf( szVarName, sizeof(szVarName), "blockinfo[%d].size", iBlock );
+    poDMS->SetIntField( szVarName, panBlockSize[iBlock] );
 }
 
 
@@ -1358,9 +1308,6 @@ void HFABand::ReAllocBlock( int iBlock, int nSize )
 CPLErr HFABand::SetRasterBlock( int nXBlock, int nYBlock, void * pData )
 
 {
-    int		iBlock;
-    VSILFILE	*fpData;
-
     if( psInfo->eAccess == HFA_ReadOnly )
     {
         CPLError( CE_Failure, CPLE_NoWriteAccess,
@@ -1371,18 +1318,18 @@ CPLErr HFABand::SetRasterBlock( int nXBlock, int nYBlock, void * pData )
     if( LoadBlockInfo() != CE_None )
         return CE_Failure;
 
-    iBlock = nXBlock + nYBlock * nBlocksPerRow;
-    
+    const int iBlock = nXBlock + nYBlock * nBlocksPerRow;
+
 /* -------------------------------------------------------------------- */
 /*      For now we don't support write invalid uncompressed blocks.     */
 /*      To do so we will need logic to make space at the end of the     */
 /*      file in the right size.                                         */
 /* -------------------------------------------------------------------- */
     if( (panBlockFlag[iBlock] & BFLG_VALID) == 0
-        && !(panBlockFlag[iBlock] & BFLG_COMPRESSED) 
+        && !(panBlockFlag[iBlock] & BFLG_COMPRESSED)
         && panBlockStart[iBlock] == 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Attempt to write to invalid tile with number %d "
                   "(X position %d, Y position %d).  This\n operation currently "
                   "unsupported by HFABand::SetRasterBlock().\n",
@@ -1394,7 +1341,8 @@ CPLErr HFABand::SetRasterBlock( int nXBlock, int nYBlock, void * pData )
 /* -------------------------------------------------------------------- */
 /*      Move to the location that the data sits.                        */
 /* -------------------------------------------------------------------- */
-    vsi_l_offset    nBlockOffset;
+    VSILFILE *fpData = NULL;
+    vsi_l_offset nBlockOffset = 0;
 
     // Calculate block offset in case we have spill file. Use predefined
     // block map otherwise.
@@ -1419,17 +1367,16 @@ CPLErr HFABand::SetRasterBlock( int nXBlock, int nYBlock, void * pData )
         /* ------------------------------------------------------------ */
         /*      Write compressed data.				        */
         /* ------------------------------------------------------------ */
-        int nInBlockSize = (nBlockXSize * nBlockYSize * HFAGetDataTypeBits(nDataType) + 7 ) / 8;
+        int nInBlockSize = (nBlockXSize * nBlockYSize * HFAGetDataTypeBits(eDataType) + 7 ) / 8;
 
         /* create the compressor object */
-        HFACompress compress( pData, nInBlockSize, nDataType );
+        HFACompress compress( pData, nInBlockSize, eDataType );
         if( compress.getCounts() == NULL ||
             compress.getValues() == NULL)
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
             return CE_Failure;
         }
-     
+
         /* compress the data */
         if( compress.compressBlock() )
         {
@@ -1441,78 +1388,85 @@ CPLErr HFABand::SetRasterBlock( int nXBlock, int nYBlock, void * pData )
             GUInt32 nMin        = compress.getMin();
             GUInt32 nNumRuns    = compress.getNumRuns();
             GByte nNumBits      = compress.getNumBits();
-     
+
             /* Compensate for the header info */
             GUInt32 nDataOffset = nSizeCount + 13;
             int nTotalSize  = nSizeCount + nSizeValues + 13;
-     
-            //fprintf( stderr, "sizecount = %d sizevalues = %d min = %d numruns = %d numbits = %d\n", nSizeCount, nSizeValues, nMin, nNumRuns, (int)nNumBits );
 
             // Allocate space for the compressed block and seek to it.
             ReAllocBlock( iBlock, nTotalSize );
-	     	
+
             nBlockOffset = panBlockStart[iBlock];
             nBlockSize = panBlockSize[iBlock];
-	     	
+
             // Seek to offset
             if( VSIFSeekL( fpData, nBlockOffset, SEEK_SET ) != 0 )
             {
                 CPLError( CE_Failure, CPLE_FileIO, "Seek to %x:%08x on %p failed\n%s",
                           (int) (nBlockOffset >> 32),
-                          (int) (nBlockOffset & 0xffffffff), 
+                          (int) (nBlockOffset & 0xffffffff),
                           fpData, VSIStrerror(errno) );
                 return CE_Failure;
             }
-     	
+
    /* -------------------------------------------------------------------- */
    /*      Byte swap to local byte order if required.  It appears that     */
    /*      raster data is always stored in Intel byte order in Imagine     */
    /*      files.                                                          */
    /* -------------------------------------------------------------------- */
-     
+
 #ifdef CPL_MSB
- 
+
             CPL_SWAP32PTR( &nMin );
             CPL_SWAP32PTR( &nNumRuns );
             CPL_SWAP32PTR( &nDataOffset );
-     
+
 #endif /* def CPL_MSB */
-     
+
        /* Write out the Minimum value */
-            VSIFWriteL( &nMin, (size_t) sizeof( nMin ), 1, fpData );
-       
+            bool bRet = VSIFWriteL( &nMin, (size_t) sizeof( nMin ), 1, fpData ) > 0;
+
             /* the number of runs */
-            VSIFWriteL( &nNumRuns, (size_t) sizeof( nNumRuns ), 1, fpData );
-       
+            bRet &= VSIFWriteL( &nNumRuns, (size_t) sizeof( nNumRuns ), 1, fpData ) > 0;
+
             /* The offset to the data */
-            VSIFWriteL( &nDataOffset, (size_t) sizeof( nDataOffset ), 1, fpData );
-       
+            bRet &= VSIFWriteL( &nDataOffset, (size_t) sizeof( nDataOffset ), 1, fpData ) > 0;
+
             /* The number of bits */
-            VSIFWriteL( &nNumBits, (size_t) sizeof( nNumBits ), 1, fpData );
-       
+            bRet &= VSIFWriteL( &nNumBits, (size_t) sizeof( nNumBits ), 1, fpData ) > 0;
+
             /* The counters - MSB stuff handled in HFACompress */
-            VSIFWriteL( pCounts, (size_t) sizeof( GByte ), nSizeCount, fpData );
-       
+            bRet &= VSIFWriteL( pCounts, nSizeCount, 1, fpData ) > 0;
+
             /* The values - MSB stuff handled in HFACompress */
-            VSIFWriteL( pValues, (size_t) sizeof( GByte ), nSizeValues, fpData );
-       
+            bRet &= VSIFWriteL( pValues, nSizeValues, 1, fpData ) > 0;
+
+            if( !bRet )
+                return CE_Failure;
+
             /* Compressed data is freed in the HFACompress destructor */
         }
         else
         {
-            /* If we have actually made the block bigger - ie does not compress well */
+            /* If we have actually made the block bigger - i.e. does not compress well */
             panBlockFlag[iBlock] ^= BFLG_COMPRESSED;
             // alloc more space for the uncompressed block
             ReAllocBlock( iBlock, nInBlockSize );
-			 
+
             nBlockOffset = panBlockStart[iBlock];
             nBlockSize = panBlockSize[iBlock];
 
             /* Need to change the RasterDMS entry */
             HFAEntry	*poDMS = poNode->GetNamedChild( "RasterDMS" );
- 	
+
+            if (!poDMS)
+            {
+                CPLError(CE_Failure, CPLE_FileIO, "Unable to load RasterDMS");
+                return CE_Failure;
+            }
+
             char	szVarName[64];
-            sprintf( szVarName, "blockinfo[%d].compressionType", iBlock );
+            snprintf( szVarName, sizeof(szVarName), "blockinfo[%d].compressionType", iBlock );
             poDMS->SetIntField( szVarName, 0 );
         }
 
@@ -1524,13 +1478,19 @@ CPLErr HFABand::SetRasterBlock( int nXBlock, int nYBlock, void * pData )
             char	szVarName[64];
             HFAEntry	*poDMS = poNode->GetNamedChild( "RasterDMS" );
 
-            sprintf( szVarName, "blockinfo[%d].logvalid", iBlock );
+            if (!poDMS)
+            {
+                CPLError(CE_Failure, CPLE_FileIO, "Unable to load RasterDMS");
+                return CE_Failure;
+            }
+
+            snprintf( szVarName, sizeof(szVarName), "blockinfo[%d].logvalid", iBlock );
             poDMS->SetStringField( szVarName, "true" );
 
             panBlockFlag[iBlock] |= BFLG_VALID;
         }
     }
- 
+
 /* ==================================================================== */
 /*      Uncompressed TILE handling.                                     */
 /* ==================================================================== */
@@ -1541,7 +1501,7 @@ CPLErr HFABand::SetRasterBlock( int nXBlock, int nYBlock, void * pData )
         {
             CPLError( CE_Failure, CPLE_FileIO, "Seek to %x:%08x on %p failed\n%s",
                       (int) (nBlockOffset >> 32),
-                      (int) (nBlockOffset & 0xffffffff), 
+                      (int) (nBlockOffset & 0xffffffff),
                       fpData, VSIStrerror(errno) );
             return CE_Failure;
         }
@@ -1552,28 +1512,28 @@ CPLErr HFABand::SetRasterBlock( int nXBlock, int nYBlock, void * pData )
 /*      files.                                                          */
 /* -------------------------------------------------------------------- */
 
-#ifdef CPL_MSB             
-        if( HFAGetDataTypeBits(nDataType) == 16 )
+#ifdef CPL_MSB
+        if( HFAGetDataTypeBits(eDataType) == 16 )
         {
             for( int ii = 0; ii < nBlockXSize*nBlockYSize; ii++ )
                 CPL_SWAP16PTR( ((unsigned char *) pData) + ii*2 );
         }
-        else if( HFAGetDataTypeBits(nDataType) == 32 )
+        else if( HFAGetDataTypeBits(eDataType) == 32 )
         {
             for( int ii = 0; ii < nBlockXSize*nBlockYSize; ii++ )
                 CPL_SWAP32PTR( ((unsigned char *) pData) + ii*4 );
         }
-        else if( nDataType == EPT_f64 )
+        else if( eDataType == EPT_f64 )
         {
             for( int ii = 0; ii < nBlockXSize*nBlockYSize; ii++ )
                 CPL_SWAP64PTR( ((unsigned char *) pData) + ii*8 );
         }
-        else if( nDataType == EPT_c64 )
+        else if( eDataType == EPT_c64 )
         {
             for( int ii = 0; ii < nBlockXSize*nBlockYSize*2; ii++ )
                 CPL_SWAP32PTR( ((unsigned char *) pData) + ii*4 );
         }
-        else if( nDataType == EPT_c128 )
+        else if( eDataType == EPT_c128 )
         {
             for( int ii = 0; ii < nBlockXSize*nBlockYSize*2; ii++ )
                 CPL_SWAP64PTR( ((unsigned char *) pData) + ii*8 );
@@ -1585,11 +1545,11 @@ CPLErr HFABand::SetRasterBlock( int nXBlock, int nYBlock, void * pData )
 /* -------------------------------------------------------------------- */
         if( VSIFWriteL( pData, (size_t) nBlockSize, 1, fpData ) != 1 )
         {
-            CPLError( CE_Failure, CPLE_FileIO, 
+            CPLError( CE_Failure, CPLE_FileIO,
                       "Write of %d bytes at %x:%08x on %p failed.\n%s",
-                      (int) nBlockSize, 
+                      (int) nBlockSize,
                       (int) (nBlockOffset >> 32),
-                      (int) (nBlockOffset & 0xffffffff), 
+                      (int) (nBlockOffset & 0xffffffff),
                       fpData, VSIStrerror(errno) );
             return CE_Failure;
         }
@@ -1601,8 +1561,13 @@ CPLErr HFABand::SetRasterBlock( int nXBlock, int nYBlock, void * pData )
         {
             char	szVarName[64];
             HFAEntry	*poDMS = poNode->GetNamedChild( "RasterDMS" );
-
-            sprintf( szVarName, "blockinfo[%d].logvalid", iBlock );
+            if (poDMS == NULL) {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Unable to get RasterDMS when trying to mark "
+                          "block valid." );
+                return CE_Failure;
+            }
+            snprintf( szVarName, sizeof(szVarName), "blockinfo[%d].logvalid", iBlock );
             poDMS->SetStringField( szVarName, "true" );
 
             panBlockFlag[iBlock] |= BFLG_VALID;
@@ -1613,28 +1578,28 @@ CPLErr HFABand::SetRasterBlock( int nXBlock, int nYBlock, void * pData )
 /*      the callers buffer.                                             */
 /* -------------------------------------------------------------------- */
 
-#ifdef CPL_MSB             
-    if( HFAGetDataTypeBits(nDataType) == 16 )
+#ifdef CPL_MSB
+    if( HFAGetDataTypeBits(eDataType) == 16 )
     {
         for( int ii = 0; ii < nBlockXSize*nBlockYSize; ii++ )
             CPL_SWAP16PTR( ((unsigned char *) pData) + ii*2 );
     }
-    else if( HFAGetDataTypeBits(nDataType) == 32 )
+    else if( HFAGetDataTypeBits(eDataType) == 32 )
     {
         for( int ii = 0; ii < nBlockXSize*nBlockYSize; ii++ )
             CPL_SWAP32PTR( ((unsigned char *) pData) + ii*4 );
     }
-    else if( nDataType == EPT_f64 )
+    else if( eDataType == EPT_f64 )
     {
         for( int ii = 0; ii < nBlockXSize*nBlockYSize; ii++ )
             CPL_SWAP64PTR( ((unsigned char *) pData) + ii*8 );
     }
-    else if( nDataType == EPT_c64 )
+    else if( eDataType == EPT_c64 )
     {
         for( int ii = 0; ii < nBlockXSize*nBlockYSize*2; ii++ )
             CPL_SWAP32PTR( ((unsigned char *) pData) + ii*4 );
     }
-    else if( nDataType == EPT_c128 )
+    else if( eDataType == EPT_c128 )
     {
         for( int ii = 0; ii < nBlockXSize*nBlockYSize*2; ii++ )
             CPL_SWAP64PTR( ((unsigned char *) pData) + ii*8 );
@@ -1649,26 +1614,23 @@ CPLErr HFABand::SetRasterBlock( int nXBlock, int nYBlock, void * pData )
 /*                                                                      */
 /*      Return the Layer Name                                           */
 /************************************************************************/
- 
+
 const char * HFABand::GetBandName()
 {
     if( strlen(poNode->GetName()) > 0 )
-        return( poNode->GetName() );
-    else
+        return poNode->GetName();
+
+    for( int iBand = 0; iBand < psInfo->nBands; iBand++ )
     {
-        int iBand; 
-        for( iBand = 0; iBand < psInfo->nBands; iBand++ )
+        if( psInfo->papoBand[iBand] == this )
         {
-            if( psInfo->papoBand[iBand] == this )
-            {
-                osOverName.Printf( "Layer_%d", iBand+1 );
-                return osOverName;
-            }
+            osOverName.Printf( "Layer_%d", iBand+1 );
+            return osOverName;
         }
-
-        osOverName.Printf( "Layer_%x", poNode->GetFilePos() );
-        return osOverName;
     }
+
+    osOverName.Printf( "Layer_%x", poNode->GetFilePos() );
+    return osOverName;
 }
 
 /************************************************************************/
@@ -1676,7 +1638,7 @@ const char * HFABand::GetBandName()
 /*                                                                      */
 /*      Set the Layer Name                                              */
 /************************************************************************/
- 
+
 void HFABand::SetBandName(const char *pszName)
 {
     if( psInfo->eAccess == HFA_Update )
@@ -1685,43 +1647,40 @@ void HFABand::SetBandName(const char *pszName)
     }
 }
 
-/************************************************************************/ 
-/*                         SetNoDataValue()                             */ 
-/*                                                                      */ 
-/*      Set the band no-data value                                      */ 
-/************************************************************************/ 
-
-CPLErr HFABand::SetNoDataValue( double dfValue ) 
-{ 
-    CPLErr eErr = CE_Failure; 
-    
-    if ( psInfo->eAccess == HFA_Update ) 
-    { 
-        HFAEntry *poNDNode = poNode->GetNamedChild( "Eimg_NonInitializedValue" ); 
-        
-        if ( poNDNode == NULL ) 
-        { 
-            poNDNode = new HFAEntry( psInfo, 
-                                     "Eimg_NonInitializedValue",
-                                     "Eimg_NonInitializedValue",
-                                     poNode ); 
-        } 
-        
-        poNDNode->MakeData( 8 + 12 + 8 ); 
-        poNDNode->SetPosition(); 
-
-        poNDNode->SetIntField( "valueBD[-3]", EPT_f64 );
-        poNDNode->SetIntField( "valueBD[-2]", 1 );
-        poNDNode->SetIntField( "valueBD[-1]", 1 );
-        if ( poNDNode->SetDoubleField( "valueBD[0]", dfValue) != CE_Failure ) 
-        { 
-            bNoDataSet = TRUE; 
-            dfNoData = dfValue; 
-            eErr = CE_None; 
-        } 
-    } 
-    
-    return eErr;     
+/************************************************************************/
+/*                         SetNoDataValue()                             */
+/*                                                                      */
+/*      Set the band no-data value                                      */
+/************************************************************************/
+
+CPLErr HFABand::SetNoDataValue( double dfValue )
+{
+    if ( psInfo->eAccess != HFA_Update )
+        return CE_Failure;
+
+    HFAEntry *poNDNode = poNode->GetNamedChild( "Eimg_NonInitializedValue" );
+
+    if ( poNDNode == NULL )
+    {
+        poNDNode = HFAEntry::New( psInfo,
+                                 "Eimg_NonInitializedValue",
+                                 "Eimg_NonInitializedValue",
+                                 poNode );
+    }
+
+    poNDNode->MakeData( 8 + 12 + 8 );
+    poNDNode->SetPosition();
+
+    poNDNode->SetIntField( "valueBD[-3]", EPT_f64 );
+    poNDNode->SetIntField( "valueBD[-2]", 1 );
+    poNDNode->SetIntField( "valueBD[-1]", 1 );
+
+    if ( poNDNode->SetDoubleField( "valueBD[0]", dfValue) == CE_Failure )
+        return CE_Failure;
+
+    bNoDataSet = TRUE;
+    dfNoData = dfValue;
+    return CE_None;
 }
 
 /************************************************************************/
@@ -1738,20 +1697,22 @@ double *HFAReadBFUniqueBins( HFAEntry *poBinFunc, int nPCTColors )
 /*      First confirm this is a "BFUnique" bin function.  We don't      */
 /*      know what to do with any other types.                           */
 /* -------------------------------------------------------------------- */
-    const char *pszBinFunctionType = 
+    const char *pszBinFunctionType =
         poBinFunc->GetStringField( "binFunction.type.string" );
 
-    if( pszBinFunctionType == NULL 
+    if( pszBinFunctionType == NULL
         || !EQUAL(pszBinFunctionType,"BFUnique") )
         return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Process dictionary.                                             */
 /* -------------------------------------------------------------------- */
-    const char *pszDict = 
+    const char *pszDict =
         poBinFunc->GetStringField( "binFunction.MIFDictionary.string" );
     if( pszDict == NULL )
-        poBinFunc->GetStringField( "binFunction.MIFDictionary" );
+        pszDict = poBinFunc->GetStringField( "binFunction.MIFDictionary" );
+    if( pszDict == NULL )
+        return NULL;
 
     HFADictionary oMiniDict( pszDict );
 
@@ -1762,9 +1723,9 @@ double *HFAReadBFUniqueBins( HFAEntry *poBinFunc, int nPCTColors )
 /* -------------------------------------------------------------------- */
 /*      Field the MIFObject raw data pointer.                           */
 /* -------------------------------------------------------------------- */
-    const GByte *pabyMIFObject = (const GByte *) 
+    const GByte *pabyMIFObject = (const GByte *)
         poBinFunc->GetStringField("binFunction.MIFObject");
-    
+
     if( pabyMIFObject == NULL )
         return NULL;
 
@@ -1781,16 +1742,15 @@ double *HFAReadBFUniqueBins( HFAEntry *poBinFunc, int nPCTColors )
 /*      Decode bins.                                                    */
 /* -------------------------------------------------------------------- */
     double *padfBins = (double *) CPLCalloc(sizeof(double),nPCTColors);
-    int i;
 
     memcpy( padfBins, pabyMIFObject + 24, sizeof(double) * nPCTColors );
-    
-    for( i = 0; i < nPCTColors; i++ )
+
+    for( int i = 0; i < nPCTColors; i++ )
     {
         HFAStandard( 8, padfBins + i );
 //        CPLDebug( "HFA", "Bin[%d] = %g", i, padfBins[i] );
     }
-    
+
     return padfBins;
 }
 
@@ -1814,29 +1774,26 @@ CPLErr HFABand::GetPCT( int * pnColors,
     *ppadfBlue = NULL;
     *ppadfAlpha = NULL;
     *ppadfBins = NULL;
-        
+
 /* -------------------------------------------------------------------- */
 /*      If we haven't already tried to load the colors, do so now.      */
 /* -------------------------------------------------------------------- */
     if( nPCTColors == -1 )
     {
-        HFAEntry	*poColumnEntry;
-        int		i, iColumn;
 
         nPCTColors = 0;
 
-        poColumnEntry = poNode->GetNamedChild("Descriptor_Table.Red");
+        HFAEntry *poColumnEntry = poNode->GetNamedChild("Descriptor_Table.Red");
         if( poColumnEntry == NULL )
             return( CE_Failure );
 
         /* FIXME? : we could also check that nPCTColors is not too big */
         nPCTColors = poColumnEntry->GetIntField( "numRows" );
-        for( iColumn = 0; iColumn < 4; iColumn++ )
+        for( int iColumn = 0; iColumn < 4; iColumn++ )
         {
-            apadfPCT[iColumn] = (double *)VSIMalloc2(sizeof(double),nPCTColors);
+            apadfPCT[iColumn] = (double *)VSI_MALLOC2_VERBOSE(sizeof(double),nPCTColors);
             if (apadfPCT[iColumn] == NULL)
             {
-                CPLError(CE_Failure, CPLE_OutOfMemory, "Color palette will be ignored");
                 return CE_Failure;
             }
 
@@ -1853,7 +1810,7 @@ CPLErr HFABand::GetPCT( int * pnColors,
             if( poColumnEntry == NULL )
             {
                 double  *pdCol = apadfPCT[iColumn];
-                for( i = 0; i < nPCTColors; i++ )
+                for( int i = 0; i < nPCTColors; i++ )
                     pdCol[i] = 1.0;
             }
             else
@@ -1872,8 +1829,8 @@ CPLErr HFABand::GetPCT( int * pnColors,
                               "VSIFReadL() failed in HFABand::GetPCT()." );
                     return CE_Failure;
                 }
-                
-                for( i = 0; i < nPCTColors; i++ )
+
+                for( int i = 0; i < nPCTColors; i++ )
                     HFAStandard( 8, apadfPCT[iColumn] + i );
             }
         }
@@ -1881,9 +1838,9 @@ CPLErr HFABand::GetPCT( int * pnColors,
 /* -------------------------------------------------------------------- */
 /*      Do we have a custom binning function? If so, try reading it.    */
 /* -------------------------------------------------------------------- */
-        HFAEntry *poBinFunc = 
+        HFAEntry *poBinFunc =
             poNode->GetNamedChild("Descriptor_Table.#Bin_Function840#");
-        
+
         if( poBinFunc != NULL )
         {
             padfPCTBins = HFAReadBFUniqueBins( poBinFunc, nPCTColors );
@@ -1902,7 +1859,7 @@ CPLErr HFABand::GetPCT( int * pnColors,
     *ppadfBlue = apadfPCT[2];
     *ppadfAlpha = apadfPCT[3];
     *ppadfBins = padfPCTBins;
-    
+
     return( CE_None );
 }
 
@@ -1919,9 +1876,8 @@ CPLErr HFABand::SetPCT( int nColors,
 			double *padfAlpha)
 
 {
-    static const char *apszColNames[4] = {"Red", "Green", "Blue", "Opacity"};
+    static const char * const apszColNames[4] = {"Red", "Green", "Blue", "Opacity"};
     HFAEntry	*poEdsc_Table;
-    int          iColumn;
 
 /* -------------------------------------------------------------------- */
 /*      Do we need to try and clear any existing color table?           */
@@ -1931,12 +1887,11 @@ CPLErr HFABand::SetPCT( int nColors,
         poEdsc_Table = poNode->GetNamedChild( "Descriptor_Table" );
         if( poEdsc_Table == NULL )
             return CE_None;
-        
-        for( iColumn = 0; iColumn < 4; iColumn++ )
-        {
-            HFAEntry        *poEdsc_Column;
 
-            poEdsc_Column = poEdsc_Table->GetNamedChild(apszColNames[iColumn]);
+        for( int iColumn = 0; iColumn < 4; iColumn++ )
+        {
+          HFAEntry *poEdsc_Column
+              = poEdsc_Table->GetNamedChild(apszColNames[iColumn]);
             if( poEdsc_Column )
                 poEdsc_Column->RemoveAndDestroy();
         }
@@ -1948,9 +1903,9 @@ CPLErr HFABand::SetPCT( int nColors,
 /*      Create the Descriptor table.                                    */
 /* -------------------------------------------------------------------- */
     poEdsc_Table = poNode->GetNamedChild( "Descriptor_Table" );
-    if( poEdsc_Table == NULL 
+    if( poEdsc_Table == NULL
         || !EQUAL(poEdsc_Table->GetType(),"Edsc_Table") )
-        poEdsc_Table = new HFAEntry( psInfo, "Descriptor_Table", 
+        poEdsc_Table = HFAEntry::New( psInfo, "Descriptor_Table",
                                      "Edsc_Table", poNode );
 
     poEdsc_Table->SetIntField( "numrows", nColors );
@@ -1959,16 +1914,15 @@ CPLErr HFABand::SetPCT( int nColors,
 /*      Create the Binning function node.  I am not sure that we        */
 /*      really need this though.                                        */
 /* -------------------------------------------------------------------- */
-    HFAEntry       *poEdsc_BinFunction;
-
-    poEdsc_BinFunction = poEdsc_Table->GetNamedChild( "#Bin_Function#" );
-    if( poEdsc_BinFunction == NULL 
+    HFAEntry *poEdsc_BinFunction
+        = poEdsc_Table->GetNamedChild( "#Bin_Function#" );
+    if( poEdsc_BinFunction == NULL
         || !EQUAL(poEdsc_BinFunction->GetType(),"Edsc_BinFunction") )
-        poEdsc_BinFunction = new HFAEntry( psInfo, "#Bin_Function#", 
-                                           "Edsc_BinFunction", 
+        poEdsc_BinFunction = HFAEntry::New( psInfo, "#Bin_Function#",
+                                           "Edsc_BinFunction",
                                            poEdsc_Table );
 
-    // Because of the BaseData we have to hardcode the size. 
+    // Because of the BaseData we have to hardcode the size.
     poEdsc_BinFunction->MakeData( 30 );
 
     poEdsc_BinFunction->SetIntField( "numBins", nColors );
@@ -1979,9 +1933,8 @@ CPLErr HFABand::SetPCT( int nColors,
 /* -------------------------------------------------------------------- */
 /*      Process each color component                                    */
 /* -------------------------------------------------------------------- */
-    for( iColumn = 0; iColumn < 4; iColumn++ )
+    for( int iColumn = 0; iColumn < 4; iColumn++ )
     {
-        HFAEntry        *poEdsc_Column;
         double	    *padfValues=NULL;
         const char      *pszName = apszColNames[iColumn];
 
@@ -1997,12 +1950,12 @@ CPLErr HFABand::SetPCT( int nColors,
 /* -------------------------------------------------------------------- */
 /*      Create the Edsc_Column.                                         */
 /* -------------------------------------------------------------------- */
-        poEdsc_Column = poEdsc_Table->GetNamedChild( pszName );
-        if( poEdsc_Column == NULL 
+        HFAEntry *poEdsc_Column = poEdsc_Table->GetNamedChild( pszName );
+        if( poEdsc_Column == NULL
             || !EQUAL(poEdsc_Column->GetType(),"Edsc_Column") )
-            poEdsc_Column = new HFAEntry( psInfo, pszName, "Edsc_Column", 
+            poEdsc_Column = HFAEntry::New( psInfo, pszName, "Edsc_Column",
                                           poEdsc_Table );
-                                          
+
         poEdsc_Column->SetIntField( "numRows", nColors );
         poEdsc_Column->SetStringField( "dataType", "real" );
         poEdsc_Column->SetIntField( "maxNumChars", 0 );
@@ -2010,20 +1963,21 @@ CPLErr HFABand::SetPCT( int nColors,
 /* -------------------------------------------------------------------- */
 /*      Write the data out.                                             */
 /* -------------------------------------------------------------------- */
-        int		nOffset = HFAAllocateSpace( psInfo, 8*nColors);
-        double      *padfFileData;
+        int nOffset = HFAAllocateSpace( psInfo, 8*nColors);
 
         poEdsc_Column->SetIntField( "columnDataPtr", nOffset );
 
-        padfFileData = (double *) CPLMalloc(nColors*sizeof(double));
+        double *padfFileData = (double *) CPLMalloc(nColors*sizeof(double));
         for( int iColor = 0; iColor < nColors; iColor++ )
         {
             padfFileData[iColor] = padfValues[iColor];
             HFAStandard( 8, padfFileData + iColor );
         }
-        VSIFSeekL( psInfo->fp, nOffset, SEEK_SET );
-        VSIFWriteL( padfFileData, 8, nColors, psInfo->fp );
+        bool bRet = VSIFSeekL( psInfo->fp, nOffset, SEEK_SET ) >= 0;
+        bRet &= VSIFWriteL( padfFileData, 8, nColors, psInfo->fp ) == (size_t)nColors;
         CPLFree( padfFileData );
+        if( !bRet )
+            return CE_Failure;
     }
 
 /* -------------------------------------------------------------------- */
@@ -2041,12 +1995,8 @@ CPLErr HFABand::SetPCT( int nColors,
 int HFABand::CreateOverview( int nOverviewLevel, const char *pszResampling )
 
 {
-
-    CPLString osLayerName;
-    int    nOXSize, nOYSize;
-
-    nOXSize = (psInfo->nXSize + nOverviewLevel - 1) / nOverviewLevel;
-    nOYSize = (psInfo->nYSize + nOverviewLevel - 1) / nOverviewLevel;
+    const int nOXSize = (psInfo->nXSize + nOverviewLevel - 1) / nOverviewLevel;
+    const int nOYSize = (psInfo->nYSize + nOverviewLevel - 1) / nOverviewLevel;
 
 /* -------------------------------------------------------------------- */
 /*      Do we want to use a dependent file (.rrd) for the overviews?    */
@@ -2055,17 +2005,19 @@ int HFABand::CreateOverview( int nOverviewLevel, const char *pszResampling )
     HFAInfo_t *psRRDInfo = psInfo;
     HFAEntry *poParent = poNode;
 
-    if( CSLTestBoolean( CPLGetConfigOption( "HFA_USE_RRD", "NO" ) ) )
+    if( CPLTestBool( CPLGetConfigOption( "HFA_USE_RRD", "NO" ) ) )
     {
         psRRDInfo = HFACreateDependent( psInfo );
+        if( psRRDInfo == NULL )
+            return -1;
 
         poParent = psRRDInfo->poRoot->GetNamedChild( GetBandName() );
 
         // Need to create layer object.
         if( poParent == NULL )
         {
-            poParent = 
-                new HFAEntry( psRRDInfo, GetBandName(),
+            poParent =
+                HFAEntry::New( psRRDInfo, GetBandName(),
                               "Eimg_Layer", psRRDInfo->poRoot );
         }
     }
@@ -2075,10 +2027,10 @@ int HFABand::CreateOverview( int nOverviewLevel, const char *pszResampling )
 /*      this is the same as the base layer, but when                    */
 /*      AVERAGE_BIT2GRAYSCALE is in effect we force it to u8 from u1.   */
 /* -------------------------------------------------------------------- */
-    int nOverviewDataType = nDataType;
+    EPTType eOverviewDataType = eDataType;
 
-    if( EQUALN(pszResampling,"AVERAGE_BIT2GR",14) )
-        nOverviewDataType = EPT_u8;
+    if( STARTS_WITH_CI(pszResampling, "AVERAGE_BIT2GR") )
+        eOverviewDataType = EPT_u8;
 
 /* -------------------------------------------------------------------- */
 /*      Eventually we need to decide on the whether to use the spill    */
@@ -2086,19 +2038,19 @@ int HFABand::CreateOverview( int nOverviewLevel, const char *pszResampling )
 /*      will drive our .img file size near 4GB.  For now, just base     */
 /*      it on the config options.                                       */
 /* -------------------------------------------------------------------- */
-    int bCreateLargeRaster = CSLTestBoolean(
+    int bCreateLargeRaster = CPLTestBool(
         CPLGetConfigOption("USE_SPILL","NO") );
     GIntBig nValidFlagsOffset = 0, nDataOffset = 0;
 
-    if( (psRRDInfo->nEndOfFile 
+    if( (psRRDInfo->nEndOfFile
          + (nOXSize * (double) nOYSize)
-         * (HFAGetDataTypeBits(nOverviewDataType) / 8)) > 2000000000.0 )
+         * (HFAGetDataTypeBits(eOverviewDataType) / 8)) > 2000000000.0 )
         bCreateLargeRaster = TRUE;
 
     if( bCreateLargeRaster )
     {
-        if( !HFACreateSpillStack( psRRDInfo, nOXSize, nOYSize, 1, 
-                                  64, nOverviewDataType, 
+        if( !HFACreateSpillStack( psRRDInfo, nOXSize, nOYSize, 1,
+                                  64, eOverviewDataType,
                                   &nValidFlagsOffset, &nDataOffset ) )
 	{
 	    return -1;
@@ -2113,7 +2065,7 @@ int HFABand::CreateOverview( int nOverviewLevel, const char *pszResampling )
     int bCompressionType = FALSE;
     const char* pszCompressOvr = CPLGetConfigOption("HFA_COMPRESS_OVR", NULL);
     if( pszCompressOvr != NULL )
-        bCompressionType = CSLTestBoolean(pszCompressOvr);
+        bCompressionType = CPLTestBool(pszCompressOvr);
     else
     {
         HFAEntry *poDMS = poNode->GetNamedChild( "RasterDMS" );
@@ -2125,14 +2077,15 @@ int HFABand::CreateOverview( int nOverviewLevel, const char *pszResampling )
 /* -------------------------------------------------------------------- */
 /*      Create the layer.                                               */
 /* -------------------------------------------------------------------- */
+    CPLString osLayerName;
     osLayerName.Printf( "_ss_%d_", nOverviewLevel );
 
-    if( !HFACreateLayer( psRRDInfo, poParent, osLayerName, 
+    if( !HFACreateLayer( psRRDInfo, poParent, osLayerName,
                          TRUE, 64, bCompressionType, bCreateLargeRaster, FALSE,
-                         nOXSize, nOYSize, nOverviewDataType, NULL,
+                         nOXSize, nOYSize, eOverviewDataType, NULL,
                          nValidFlagsOffset, nDataOffset, 1, 0 ) )
         return -1;
-    
+
     HFAEntry *poOverLayer = poParent->GetNamedChild( osLayerName );
     if( poOverLayer == NULL )
         return -1;
@@ -2143,15 +2096,15 @@ int HFABand::CreateOverview( int nOverviewLevel, const char *pszResampling )
     HFAEntry *poRRDNamesList = poNode->GetNamedChild("RRDNamesList");
     if( poRRDNamesList == NULL )
     {
-        poRRDNamesList = new HFAEntry( psInfo, "RRDNamesList", 
-                                       "Eimg_RRDNamesList", 
+        poRRDNamesList = HFAEntry::New( psInfo, "RRDNamesList",
+                                       "Eimg_RRDNamesList",
                                        poNode );
         poRRDNamesList->MakeData( 23+16+8+ 3000 /* hack for growth room*/ );
 
         /* we need to hardcode file offset into the data, so locate it now */
         poRRDNamesList->SetPosition();
 
-        poRRDNamesList->SetStringField( "algorithm.string", 
+        poRRDNamesList->SetStringField( "algorithm.string",
                                         "IMAGINE 2X2 Resampling" );
     }
 
@@ -2162,13 +2115,13 @@ int HFABand::CreateOverview( int nOverviewLevel, const char *pszResampling )
     char szName[50];
     CPLString osNodeName;
 
-    sprintf( szName, "nameList[%d].string", iNextName );
+    snprintf( szName, sizeof(szName), "nameList[%d].string", iNextName );
 
-    osLayerName.Printf( "%s(:%s:_ss_%d_)", 
+    osLayerName.Printf( "%s(:%s:_ss_%d_)",
                         psRRDInfo->pszFilename, GetBandName(),
                         nOverviewLevel );
 
-    // TODO: Need to add to end of array (thats pretty hard).
+    // TODO: Need to add to end of array (that is pretty hard).
     if( poRRDNamesList->SetStringField( szName, osLayerName ) != CE_None )
     {
         poRRDNamesList->MakeData( poRRDNamesList->GetDataSize() + 3000 );
@@ -2179,7 +2132,7 @@ int HFABand::CreateOverview( int nOverviewLevel, const char *pszResampling )
 /* -------------------------------------------------------------------- */
 /*      Add to the list of overviews for this band.                     */
 /* -------------------------------------------------------------------- */
-    papoOverviews = (HFABand **) 
+    papoOverviews = (HFABand **)
         CPLRealloc(papoOverviews, sizeof(void*) * ++nOverviews );
     papoOverviews[nOverviews-1] = new HFABand( psRRDInfo, poOverLayer );
 
diff --git a/frmts/hfa/hfacompress.cpp b/frmts/hfa/hfacompress.cpp
index 3fcff76..8002332 100644
--- a/frmts/hfa/hfacompress.cpp
+++ b/frmts/hfa/hfacompress.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfacompress.cpp 23624 2011-12-21 19:31:43Z rouault $
+ * $Id: hfacompress.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Name:     hfadataset.cpp
  * Project:  Erdas Imagine Driver
@@ -30,27 +30,28 @@
 
 #include "hfa_p.h"
 
-CPL_CVSID("$Id: hfacompress.cpp 23624 2011-12-21 19:31:43Z rouault $");
+CPL_CVSID("$Id: hfacompress.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
-HFACompress::HFACompress( void *pData, GUInt32 nBlockSize, int nDataType )
+HFACompress::HFACompress( void *pData, GUInt32 nBlockSize, EPTType eDataType ) :
+    m_pData(pData),
+    m_nBlockSize(nBlockSize),
+    m_eDataType(eDataType),
+    m_pCurrCount(NULL),
+    m_nSizeCounts(0),
+    m_pCurrValues(NULL),
+    m_nSizeValues(0),
+    m_nMin(0),
+    m_nNumRuns(0),
+    m_nNumBits(0)
 {
-  m_pData       = pData;
-  m_nDataType   = nDataType;
-  m_nDataTypeNumBits    = HFAGetDataTypeBits( m_nDataType );
-  m_nBlockSize  = nBlockSize;
+  m_nDataTypeNumBits    = HFAGetDataTypeBits( m_eDataType );
   m_nBlockCount = (nBlockSize * 8) / m_nDataTypeNumBits;
 
   /* Allocate some memory for the count and values - probably too big */
   /* About right for worst case scenario tho */
-  m_pCounts     = (GByte*)VSIMalloc( m_nBlockCount * sizeof(GUInt32) + sizeof(GUInt32) );
-  m_nSizeCounts = 0;
-  
-  m_pValues     = (GByte*)VSIMalloc( m_nBlockCount * sizeof(GUInt32) + sizeof(GUInt32) );
-  m_nSizeValues = 0;
-  
-  m_nMin        = 0;
-  m_nNumRuns    = 0;
-  m_nNumBits    = 0;
+  m_pCounts     = (GByte*)VSI_MALLOC_VERBOSE( m_nBlockCount * sizeof(GUInt32) + sizeof(GUInt32) );
+
+  m_pValues     = (GByte*)VSI_MALLOC_VERBOSE( m_nBlockCount * sizeof(GUInt32) + sizeof(GUInt32) );
 }
 
 HFACompress::~HFACompress()
@@ -61,20 +62,19 @@ HFACompress::~HFACompress()
 }
 
 /* returns the number of bits needed to encode a count */
-GByte _FindNumBits( GUInt32 range )
+static GByte _FindNumBits( GUInt32 range )
 {
   if( range < 0xff )
   {
-    return 8; 
-  } 
-  else if( range < 0xffff )
-  {
-    return 16;
+    return 8;
   }
-  else
+
+  if( range < 0xffff )
   {
-    return 32; 
+    return 16;
   }
+
+  return 32;
 }
 
 /* Gets the value from the uncompressed block as a GUInt32 no matter the data type */
@@ -92,25 +92,25 @@ GUInt32 HFACompress::valueAsUInt32( GUInt32 iPixel )
   }
   else if( m_nDataTypeNumBits == 32 )
   {
-    val = ((GUInt32*)m_pData)[iPixel]; 
+    val = ((GUInt32*)m_pData)[iPixel];
   }
   else if( m_nDataTypeNumBits == 4 )
   {
       if( iPixel % 2 == 0 )
-          val = ((GByte*)m_pData)[iPixel/2] & 0x0f;  
+          val = ((GByte*)m_pData)[iPixel/2] & 0x0f;
       else
           val = (((GByte*)m_pData)[iPixel/2] & 0xf0) >> 4;
   }
   else if( m_nDataTypeNumBits == 2 )
   {
       if( iPixel % 4 == 0 )
-          val = ((GByte*)m_pData)[iPixel/4] & 0x03;  
+          val = ((GByte*)m_pData)[iPixel/4] & 0x03;
       else if( iPixel % 4 == 1 )
-          val = (((GByte*)m_pData)[iPixel/4] & 0x0c) >> 2;  
+          val = (((GByte*)m_pData)[iPixel/4] & 0x0c) >> 2;
       else if( iPixel % 4 == 2 )
-          val = (((GByte*)m_pData)[iPixel/4] & 0x30) >> 4;  
-      else 
-          val = (((GByte*)m_pData)[iPixel/4] & 0xc0) >> 6;  
+          val = (((GByte*)m_pData)[iPixel/4] & 0x30) >> 4;
+      else
+          val = (((GByte*)m_pData)[iPixel/4] & 0xc0) >> 6;
   }
   else if( m_nDataTypeNumBits == 1 )
   {
@@ -121,46 +121,43 @@ GUInt32 HFACompress::valueAsUInt32( GUInt32 iPixel )
   }
   else
   {
-    /* Should not get to here - check in compressBlock() should return false if 
+    /* Should not get to here - check in compressBlock() should return false if
     we can't compress this blcok because we don't know about the type */
-    CPLError( CE_Failure, CPLE_FileIO, "Imagine Datatype 0x%x (0x%x bits) not supported\n", 
-          m_nDataType,
+    CPLError( CE_Failure, CPLE_FileIO, "Imagine Datatype 0x%x (0x%x bits) not supported\n",
+          m_eDataType,
           m_nDataTypeNumBits );
     CPLAssert( FALSE );
   }
-  
+
   return val;
 }
 
 /* Finds the minimum value in a type specific fashion. This value is
   subtracted from each value in the compressed dataset. The maxmimum
-  value is also found and the number of bits that the range can be stored 
+  value is also found and the number of bits that the range can be stored
   is also returned. */
 /* TODO: Minimum value returned as pNumBits is now 8 - Imagine
   can handle 1, 2, and 4 bits as well */
 GUInt32 HFACompress::findMin( GByte *pNumBits )
 {
-GUInt32 u32Val;
-GUInt32 u32Min, u32Max;
-
-   u32Min = valueAsUInt32( 0 );
-   u32Max = u32Min;
+  GUInt32 u32Min = valueAsUInt32( 0 );
+  GUInt32 u32Max = u32Min;
 
   for( GUInt32 count = 1; count < m_nBlockCount; count++ )
   {
-    u32Val = valueAsUInt32( count );
+    GUInt32 u32Val = valueAsUInt32( count );
     if( u32Val < u32Min )
       u32Min = u32Val;
     else if( u32Val > u32Max )
       u32Max = u32Val;
-  }    
-  
+  }
+
   *pNumBits = _FindNumBits( u32Max - u32Min );
 
   return u32Min;
 }
 
-/* Codes the count in the way expected by Imagine - ie the lower 2 bits specify how many bytes
+/* Codes the count in the way expected by Imagine - i.e. the lower 2 bits specify how many bytes
    the count takes up */
 void HFACompress::makeCount( GUInt32 count, GByte *pCounter, GUInt32 *pnSizeCount )
 {
@@ -203,7 +200,7 @@ void HFACompress::makeCount( GUInt32 count, GByte *pCounter, GUInt32 *pnSizeCoun
 /* Encodes the value depending on the number of bits we are using */
 void HFACompress::encodeValue( GUInt32 val, GUInt32 repeat )
 {
-GUInt32 nSizeCount;
+  GUInt32 nSizeCount;
 
   makeCount( repeat, m_pCurrCount, &nSizeCount );
   m_pCurrCount += nSizeCount;
@@ -218,7 +215,7 @@ GUInt32 nSizeCount;
     /* Only storing 16 bits per value as the range is small */
     *(GUInt16*)m_pCurrValues = GUInt16(val - m_nMin);
 #ifndef CPL_MSB
-   CPL_SWAP16PTR( m_pCurrValues );      
+   CPL_SWAP16PTR( m_pCurrValues );
 #endif /* ndef CPL_MSB */
     m_pCurrValues += sizeof( GUInt16 );
   }
@@ -226,77 +223,77 @@ GUInt32 nSizeCount;
   {
     *(GUInt32*)m_pCurrValues = GUInt32(val - m_nMin);
 #ifndef CPL_MSB
-   CPL_SWAP32PTR( m_pCurrValues );      
+   CPL_SWAP32PTR( m_pCurrValues );
 #endif /* ndef CPL_MSB */
     m_pCurrValues += sizeof( GUInt32 );
   }
 }
 
 /* This is the guts of the file - call this to compress the block */
-/* returns false if the compression fails - ie compressed block bigger than input */
+/* returns false if the compression fails - i.e. compressed block bigger than input */
 bool HFACompress::compressBlock()
 {
-GUInt32 nLastUnique = 0;
+  GUInt32 nLastUnique = 0;
 
   /* Check we know about the datatype to be compressed.
-      If we can't compress it we should return false so that 
-      the block cannot be compressed (we can handle just about 
-      any type uncompressed) */
-  if( ! QueryDataTypeSupported( m_nDataType ) )
+     If we can't compress it we should return false so that
+     the block cannot be compressed (we can handle just about
+     any type uncompressed). */
+  if( ! QueryDataTypeSupported( m_eDataType ) )
   {
-    CPLDebug( "HFA", "Cannot compress HFA datatype 0x%x (0x%x bits). Writing uncompressed instead.\n", 
-              m_nDataType,
+    CPLDebug( "HFA", "Cannot compress HFA datatype 0x%x (0x%x bits). "
+              "Writing uncompressed instead.\n",
+              m_eDataType,
               m_nDataTypeNumBits );
-    return false; 
+    return false;
   }
 
   /* reset our pointers */
   m_pCurrCount  = m_pCounts;
   m_pCurrValues = m_pValues;
 
-  /* Get the minimum value - this can be subtracted from each value in the image */
+  /* Get the minimum value.  this can be subtracted from each value in
+     the image. */
   m_nMin = findMin( &m_nNumBits );
-  
-  /* Go thru the block */
-  GUInt32 u32Last, u32Val;
-  u32Last = valueAsUInt32( 0 );
-  u32Val = u32Last;
+
+  /* Go through the block. */
+  GUInt32 u32Last = valueAsUInt32( 0 );
   for( GUInt32 count = 1; count < m_nBlockCount; count++ )
   {
-    u32Val = valueAsUInt32( count );
+    GUInt32 u32Val = valueAsUInt32( count );
     if( u32Val != u32Last )
     {
-      /* The values have changed - ie a run has come to and end */
+      /* The values have changed - i.e. a run has come to and end */
       encodeValue( u32Last, count - nLastUnique );
-      
+
       if( ( m_pCurrValues - m_pValues ) > (int) m_nBlockSize )
       {
-      	return false;
+        return false;
       }
-      
+
       m_nNumRuns++;
       u32Last = u32Val;
       nLastUnique = count;
     }
   }
 
-  /* OK we have done the block but haven't got the last run because we were only looking for a change in values */
+  /* OK we have done the block but have not got the last run because we
+     were only looking for a change in values */
   encodeValue( u32Last, m_nBlockCount - nLastUnique );
   m_nNumRuns++;
-  
+
   /* set the size variables */
-  m_nSizeCounts = m_pCurrCount - m_pCounts;
-  m_nSizeValues = m_pCurrValues - m_pValues;
+  m_nSizeCounts = static_cast<GUInt32>(m_pCurrCount - m_pCounts);
+  m_nSizeValues = static_cast<GUInt32>(m_pCurrValues - m_pValues);
 
   // The 13 is for the header size - maybe this should live with some constants somewhere?
   return ( m_nSizeCounts +  m_nSizeValues + 13 ) < m_nBlockSize;
 }
 
-bool HFACompress::QueryDataTypeSupported( int nHFADataType )
+bool HFACompress::QueryDataTypeSupported( EPTType eHFADataType )
 {
-  int nBits = HFAGetDataTypeBits( nHFADataType );
-  
+  int nBits = HFAGetDataTypeBits( eHFADataType );
+
   return ( nBits == 8 ) || ( nBits == 16 ) || ( nBits == 32 ) || (nBits == 4)
       || (nBits == 2) || (nBits == 1);
 }
-
diff --git a/frmts/hfa/hfadataset.cpp b/frmts/hfa/hfadataset.cpp
index 952c953..64022c3 100644
--- a/frmts/hfa/hfadataset.cpp
+++ b/frmts/hfa/hfadataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfadataset.cpp 29764 2015-08-23 14:30:43Z rouault $
+ * $Id: hfadataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Name:     hfadataset.cpp
  * Project:  Erdas Imagine Driver
@@ -29,33 +29,26 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 #include "gdal_rat.h"
 #include "hfa_p.h"
 #include "ogr_spatialref.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: hfadataset.cpp 29764 2015-08-23 14:30:43Z rouault $");
-
-CPL_C_START
-void	GDALRegister_HFA(void);
-CPL_C_END
-
-#ifndef PI
-#  define PI 3.14159265358979323846
-#endif
+CPL_CVSID("$Id: hfadataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 #ifndef R2D
-#  define R2D	(180/PI)
+#  define R2D	(180/M_PI)
 #endif
 #ifndef D2R
-#  define D2R	(PI/180)
+#  define D2R	(M_PI/180)
 #endif
 
 int WritePeStringIfNeeded(OGRSpatialReference* poSRS, HFAHandle hHFA);
 void ClearSR(HFAHandle hHFA);
 
-static const char *apszDatumMap[] = {
+static const char * const apszDatumMap[] = {
     /* Imagine name, WKT name */
     "NAD27", "North_American_Datum_1927",
     "NAD83", "North_American_Datum_1983",
@@ -65,13 +58,13 @@ static const char *apszDatumMap[] = {
     NULL, NULL
 };
 
-static const char *apszUnitMap[] = {
+static const char * const apszUnitMap[] = {
     "meters", "1.0",
     "meter", "1.0",
     "m", "1.0",
     "centimeters", "0.01",
     "centimeter", "0.01",
-    "cm", "0.01", 
+    "cm", "0.01",
     "millimeters", "0.001",
     "millimeter", "0.001",
     "mm", "0.001",
@@ -80,7 +73,7 @@ static const char *apszUnitMap[] = {
     "km", "1000.0",
     "us_survey_feet", "0.3048006096012192",
     "us_survey_foot", "0.3048006096012192",
-    "feet", "0.3048006096012192", 
+    "feet", "0.3048006096012192",
     "foot", "0.3048006096012192",
     "ft", "0.3048006096012192",
     "international_feet", "0.3048",
@@ -260,7 +253,7 @@ static const int anUsgsEsriZones[] =
 
 class HFARasterBand;
 
-class CPL_DLL HFADataset : public GDALPamDataset
+class HFADataset CPL_FINAL : public GDALPamDataset
 {
     friend class HFARasterBand;
 
@@ -327,10 +320,10 @@ class CPL_DLL HFADataset : public GDALPamDataset
     virtual CPLErr SetMetadataItem( const char *, const char *, const char * = "" );
 
     virtual void   FlushCache( void );
-    virtual CPLErr IBuildOverviews( const char *pszResampling, 
-                                    int nOverviews, int *panOverviewList, 
+    virtual CPLErr IBuildOverviews( const char *pszResampling,
+                                    int nOverviews, int *panOverviewList,
                                     int nListBands, int *panBandList,
-                                    GDALProgressFunc pfnProgress, 
+                                    GDALProgressFunc pfnProgress,
                                     void * pProgressData );
 };
 
@@ -340,14 +333,14 @@ class CPL_DLL HFADataset : public GDALPamDataset
 /* ==================================================================== */
 /************************************************************************/
 
-class HFARasterBand : public GDALPamRasterBand
+class HFARasterBand CPL_FINAL : public GDALPamRasterBand
 {
     friend class HFADataset;
     friend class HFARasterAttributeTable;
 
     GDALColorTable *poCT;
 
-    int		nHFADataType;
+    EPTType	eHFADataType;
 
     int         nOverviews;
     int		nThisOverview;
@@ -359,7 +352,7 @@ class HFARasterBand : public GDALPamRasterBand
 
     int         bMetadataDirty;
 
-    GDALRasterAttributeTable *poDefaultRAT; 
+    GDALRasterAttributeTable *poDefaultRAT;
 
     void        ReadAuxMetadata();
     void        ReadHistogramMetadata();
@@ -416,7 +409,7 @@ public:
     int               bConvertColors; // map 0-1 floats to 0-255 ints
 };
 
-class HFARasterAttributeTable : public GDALRasterAttributeTable
+class HFARasterAttributeTable CPL_FINAL : public GDALRasterAttributeTable
 {
 private:
 
@@ -435,7 +428,7 @@ private:
 
     CPLString osWorkingResult;
 
-    void AddColumn(const char *pszName, GDALRATFieldType eType, GDALRATFieldUsage eUsage, 
+    void AddColumn(const char *pszName, GDALRATFieldType eType, GDALRATFieldUsage eUsage,
                 int nDataOffset, int nElementSize, HFAEntry *poColumn, int bIsBinValues=FALSE,
                 int bConvertColors=FALSE)
     {
@@ -454,10 +447,10 @@ private:
 
     void CreateDT()
     {
-        this->poDT = new HFAEntry( this->hHFA->papoBand[this->nBand-1]->psInfo, 
-                             this->osName, "Edsc_Table",
-                             this->hHFA->papoBand[this->nBand-1]->poNode );
-        this->poDT->SetIntField( "numrows", nRows );
+        poDT = HFAEntry::New( hHFA->papoBand[nBand-1]->psInfo,
+                              osName, "Edsc_Table",
+                              hHFA->papoBand[nBand-1]->poNode );
+        poDT->SetIntField( "numrows", nRows );
     }
 
 public:
@@ -465,13 +458,13 @@ public:
     ~HFARasterAttributeTable();
 
     GDALDefaultRasterAttributeTable *Clone() const;
-    
+
     virtual int           GetColumnCount() const;
 
     virtual const char   *GetNameOfCol( int ) const;
     virtual GDALRATFieldUsage GetUsageOfCol( int ) const;
     virtual GDALRATFieldType GetTypeOfCol( int ) const;
-    
+
     virtual int           GetColOfUsage( GDALRATFieldUsage ) const;
 
     virtual int           GetRowCount() const;
@@ -494,8 +487,8 @@ public:
     virtual int           GetRowOfValue( double dfValue ) const;
     virtual int           GetRowOfValue( int nValue ) const;
 
-    virtual CPLErr        CreateColumn( const char *pszFieldName, 
-                                GDALRATFieldType eFieldType, 
+    virtual CPLErr        CreateColumn( const char *pszFieldName,
+                                GDALRATFieldType eFieldType,
                                 GDALRATFieldUsage eFieldUsage );
     virtual CPLErr        SetLinearBinning( double dfRow0Min, double dfBinSize );
     virtual int           GetLinearBinning( double *pdfRow0Min, double *pdfBinSize ) const;
@@ -510,7 +503,9 @@ protected:
 /*                     HFARasterAttributeTable()                        */
 /************************************************************************/
 
-HFARasterAttributeTable::HFARasterAttributeTable(HFARasterBand *poBand, const char *pszName)
+HFARasterAttributeTable::HFARasterAttributeTable(HFARasterBand *poBand, const char *pszName) :
+    dfRow0Min(0.0),
+    dfBinSize(0.0)
 {
     this->hHFA = poBand->hHFA;
     this->poDT = poBand->hHFA->papoBand[poBand->nBand-1]->poNode->GetNamedChild(pszName);
@@ -527,17 +522,15 @@ HFARasterAttributeTable::HFARasterAttributeTable(HFARasterBand *poBand, const ch
 /* -------------------------------------------------------------------- */
 /*      Scan under table for columns.                                   */
 /* -------------------------------------------------------------------- */
-       HFAEntry *poDTChild;
-
-        for( poDTChild = poDT->GetChild(); 
-             poDTChild != NULL; 
+        for( HFAEntry *poDTChild = poDT->GetChild();
+             poDTChild != NULL;
              poDTChild = poDTChild->GetNext() )
         {
             if( EQUAL(poDTChild->GetType(),"Edsc_BinFunction") )
             {
-                double dfMax = poDTChild->GetDoubleField( "maxLimit" );
-                double dfMin = poDTChild->GetDoubleField( "minLimit" );
-                int    nBinCount = poDTChild->GetIntField( "numBins" );
+                const double dfMax = poDTChild->GetDoubleField( "maxLimit" );
+                const double dfMin = poDTChild->GetDoubleField( "minLimit" );
+                const int nBinCount = poDTChild->GetIntField( "numBins" );
 
                 if( nBinCount == this->nRows
                     && dfMax != dfMin && nBinCount != 0 )
@@ -550,18 +543,21 @@ HFARasterAttributeTable::HFARasterAttributeTable(HFARasterBand *poBand, const ch
                 }
             }
 
-            if( EQUAL(poDTChild->GetType(),"Edsc_BinFunction840") 
-                && EQUAL(poDTChild->GetStringField( "binFunction.type.string" ),
-                         "BFUnique") )
+            if( EQUAL(poDTChild->GetType(),"Edsc_BinFunction840") )
             {
-                AddColumn( "BinValues", GFT_Real, GFU_MinMax, 0, 0, poDTChild, TRUE);
+                const char* pszValue =
+                    poDTChild->GetStringField( "binFunction.type.string" );
+                if( pszValue && EQUAL(pszValue, "BFUnique") )
+                {
+                    AddColumn( "BinValues", GFT_Real, GFU_MinMax, 0, 0, poDTChild, TRUE);
+                }
             }
 
             if( !EQUAL(poDTChild->GetType(),"Edsc_Column") )
                 continue;
 
-            int nOffset = poDTChild->GetIntField( "columnDataPtr" );
-            const char * pszType = poDTChild->GetStringField( "dataType" );
+            const int nOffset = poDTChild->GetIntField( "columnDataPtr" );
+            const char *pszType = poDTChild->GetStringField( "dataType" );
             GDALRATFieldUsage eUsage = GFU_Generic;
             int bConvertColors = FALSE;
 
@@ -573,11 +569,11 @@ HFARasterAttributeTable::HFARasterAttributeTable(HFARasterBand *poBand, const ch
                 eType = GFT_Real;
             else if( EQUAL(pszType,"string") )
                 eType = GFT_String;
-            else if( EQUALN(pszType,"int",3) )
+            else if( STARTS_WITH_CI(pszType, "int") )
                 eType = GFT_Integer;
             else
                 continue;
-        
+
             if( EQUAL(poDTChild->GetName(),"Histogram") )
                 eUsage = GFU_PixelCount;
             else if( EQUAL(poDTChild->GetName(),"Red") )
@@ -616,6 +612,13 @@ HFARasterAttributeTable::HFARasterAttributeTable(HFARasterBand *poBand, const ch
             else if( eType == GFT_String )
             {
                 int nMaxNumChars = poDTChild->GetIntField( "maxNumChars" );
+                if( nMaxNumChars <= 0 )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Invalid nMaxNumChars = %d for column %s",
+                             nMaxNumChars, poDTChild->GetName());
+                    nMaxNumChars = 1;
+                }
                 AddColumn(poDTChild->GetName(), GFT_String, eUsage, nOffset, nMaxNumChars, poDTChild);
             }
             else if( eType == GFT_Integer )
@@ -623,7 +626,7 @@ HFARasterAttributeTable::HFARasterAttributeTable(HFARasterBand *poBand, const ch
                 int nSize = sizeof(GInt32);
                 if( bConvertColors )
                     nSize = sizeof(double);
-                AddColumn(poDTChild->GetName(), GFT_Integer, eUsage, nOffset, nSize, poDTChild, 
+                AddColumn(poDTChild->GetName(), GFT_Integer, eUsage, nOffset, nSize, poDTChild,
                                         FALSE, bConvertColors);
             }
         }
@@ -634,10 +637,7 @@ HFARasterAttributeTable::HFARasterAttributeTable(HFARasterBand *poBand, const ch
 /*                    ~HFARasterAttributeTable()                        */
 /************************************************************************/
 
-HFARasterAttributeTable::~HFARasterAttributeTable()
-{
-
-}
+HFARasterAttributeTable::~HFARasterAttributeTable() {}
 
 /************************************************************************/
 /*                              Clone()                                 */
@@ -657,11 +657,9 @@ GDALDefaultRasterAttributeTable *HFARasterAttributeTable::Clone() const
 
         if( aoFields[iCol].eType == GFT_Integer )
         {
-            int *panColData = (int*)VSIMalloc2(sizeof(int), this->nRows);
+            int *panColData = (int*)VSI_MALLOC2_VERBOSE(sizeof(int), this->nRows);
             if( panColData == NULL )
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory,
-                    "Memory Allocation failed in HFARasterAttributeTable::Clone");
                 delete poRAT;
                 return NULL;
             }
@@ -672,21 +670,19 @@ GDALDefaultRasterAttributeTable *HFARasterAttributeTable::Clone() const
                 CPLFree(panColData);
                 delete poRAT;
                 return NULL;
-            }           
+            }
 
             for( int iRow = 0; iRow < this->nRows; iRow++ )
             {
-                poRAT->SetValue(iRow, iCol, panColData[iRow]);            
+                poRAT->SetValue(iRow, iCol, panColData[iRow]);
             }
             CPLFree(panColData);
         }
         if( aoFields[iCol].eType == GFT_Real )
         {
-            double *padfColData = (double*)VSIMalloc2(sizeof(double), this->nRows);
+            double *padfColData = (double*)VSI_MALLOC2_VERBOSE(sizeof(double), this->nRows);
             if( padfColData == NULL )
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory,
-                    "Memory Allocation failed in HFARasterAttributeTable::Clone");
                 delete poRAT;
                 return NULL;
             }
@@ -697,21 +693,19 @@ GDALDefaultRasterAttributeTable *HFARasterAttributeTable::Clone() const
                 CPLFree(padfColData);
                 delete poRAT;
                 return NULL;
-            }           
+            }
 
             for( int iRow = 0; iRow < this->nRows; iRow++ )
             {
-                poRAT->SetValue(iRow, iCol, padfColData[iRow]);            
+                poRAT->SetValue(iRow, iCol, padfColData[iRow]);
             }
             CPLFree(padfColData);
         }
         if( aoFields[iCol].eType == GFT_String )
         {
-            char **papszColData = (char**)VSIMalloc2(sizeof(char*), this->nRows);
+            char **papszColData = (char**)VSI_MALLOC2_VERBOSE(sizeof(char*), this->nRows);
             if( papszColData == NULL )
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory,
-                    "Memory Allocation failed in HFARasterAttributeTable::Clone");
                 delete poRAT;
                 return NULL;
             }
@@ -722,7 +716,7 @@ GDALDefaultRasterAttributeTable *HFARasterAttributeTable::Clone() const
                 CPLFree(papszColData);
                 delete poRAT;
                 return NULL;
-            }           
+            }
 
             for( int iRow = 0; iRow < this->nRows; iRow++ )
             {
@@ -738,14 +732,14 @@ GDALDefaultRasterAttributeTable *HFARasterAttributeTable::Clone() const
 
     return poRAT;
 }
-    
+
 /************************************************************************/
 /*                          GetColumnCount()                            */
 /************************************************************************/
 
 int HFARasterAttributeTable::GetColumnCount() const
 {
-    return this->aoFields.size();
+    return static_cast<int>(aoFields.size());
 }
 
 /************************************************************************/
@@ -783,16 +777,14 @@ GDALRATFieldType HFARasterAttributeTable::GetTypeOfCol( int nCol ) const
 
     return this->aoFields[nCol].eType;
 }
-    
+
 /************************************************************************/
 /*                          GetColOfUsage()                             */
 /************************************************************************/
 
 int HFARasterAttributeTable::GetColOfUsage( GDALRATFieldUsage eUsage ) const
 {
-    unsigned int i;
-
-    for( i = 0; i < this->aoFields.size(); i++ )
+    for( unsigned int i = 0; i < this->aoFields.size(); i++ )
     {
         if( this->aoFields[i].eUsage == eUsage )
             return i;
@@ -817,9 +809,9 @@ int HFARasterAttributeTable::GetRowCount() const
 const char *HFARasterAttributeTable::GetValueAsString( int iRow, int iField ) const
 {
     // Get ValuesIO do do the work
-    char *apszStrList[1];
+    char *apszStrList[1] = { NULL };
     if( ((HFARasterAttributeTable*)this)->
-                ValuesIO(GF_Read, iField, iRow, 1, apszStrList ) != CPLE_None )
+                ValuesIO(GF_Read, iField, iRow, 1, apszStrList ) != CE_None )
     {
         return "";
     }
@@ -837,7 +829,7 @@ const char *HFARasterAttributeTable::GetValueAsString( int iRow, int iField ) co
 int HFARasterAttributeTable::GetValueAsInt( int iRow, int iField ) const
 {
     // Get ValuesIO do do the work
-    int nValue;
+    int nValue = 0;
     if( ((HFARasterAttributeTable*)this)->
                 ValuesIO(GF_Read, iField, iRow, 1, &nValue ) != CE_None )
     {
@@ -854,7 +846,7 @@ int HFARasterAttributeTable::GetValueAsInt( int iRow, int iField ) const
 double HFARasterAttributeTable::GetValueAsDouble( int iRow, int iField ) const
 {
     // Get ValuesIO do do the work
-    double dfValue;
+    double dfValue = 0.0;
     if( ((HFARasterAttributeTable*)this)->
                 ValuesIO(GF_Read, iField, iRow, 1, &dfValue ) != CE_None )
     {
@@ -915,7 +907,9 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
         return CE_Failure;
     }
 
-    if( iStartRow < 0 || (iStartRow+iLength) > this->nRows )
+    if( iStartRow < 0 ||
+        iLength >= INT_MAX - iStartRow ||
+        (iStartRow+iLength) > this->nRows )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "iStartRow (%d) + iLength(%d) out of range.", iStartRow, iLength );
@@ -926,11 +920,9 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
     if( aoFields[iField].bConvertColors )
     {
         // convert to/from float color field
-        int *panColData = (int*)VSIMalloc2(iLength, sizeof(int) );
+        int *panColData = (int*)VSI_MALLOC2_VERBOSE(iLength, sizeof(int) );
         if( panColData == NULL )
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory,
-                "Memory Allocation failed in HFARasterAttributeTable::ValuesIO");
             CPLFree(panColData);
             return CE_Failure;
         }
@@ -938,7 +930,7 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
         if( eRWFlag == GF_Write )
         {
             for( int i = 0; i < iLength; i++ )
-                panColData[i] = pdfData[i];
+                panColData[i] = static_cast<int>(pdfData[i]);
         }
 
         CPLErr ret = ColorsIO(eRWFlag, iField, iStartRow, iLength, panColData);
@@ -959,11 +951,9 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
         case GFT_Integer:
         {
             // allocate space for ints
-            int *panColData = (int*)VSIMalloc2(iLength, sizeof(int) );
+            int *panColData = (int*)VSI_MALLOC2_VERBOSE(iLength, sizeof(int) );
             if( panColData == NULL )
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory,
-                    "Memory Allocation failed in HFARasterAttributeTable::ValuesIO");
                 CPLFree(panColData);
                 return CE_Failure;
             }
@@ -972,7 +962,7 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
             {
                 // copy the application supplied doubles to ints
                 for( int i = 0; i < iLength; i++ )
-                    panColData[i] = pdfData[i];
+                    panColData[i] = static_cast<int>(pdfData[i]);
             }
 
             // do the ValuesIO as ints
@@ -999,12 +989,15 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
             {
                 // probably could change HFAReadBFUniqueBins to only read needed rows
                 double *padfBinValues = HFAReadBFUniqueBins( aoFields[iField].poColumn, iStartRow+iLength );
+                if( padfBinValues == NULL )
+                    return CE_Failure;
                 memcpy(pdfData, &padfBinValues[iStartRow], sizeof(double) * iLength);
                 CPLFree(padfBinValues);
             }
             else
             {
-                VSIFSeekL( hHFA->fp, aoFields[iField].nDataOffset + (iStartRow*aoFields[iField].nElementSize), SEEK_SET );
+                if(VSIFSeekL( hHFA->fp, aoFields[iField].nDataOffset + (static_cast<vsi_l_offset>(iStartRow)*aoFields[iField].nElementSize), SEEK_SET ) != 0 )
+                    return CE_Failure;
 
                 if( eRWFlag == GF_Read )
                 {
@@ -1041,11 +1034,9 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
         case GFT_String:
         {
             // allocate space for string pointers
-            char **papszColData = (char**)VSIMalloc2(iLength, sizeof(char*));
+            char **papszColData = (char**)VSI_MALLOC2_VERBOSE(iLength, sizeof(char*));
             if( papszColData == NULL )
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory,
-                    "Memory Allocation failed in HFARasterAttributeTable::ValuesIO");
                 return CE_Failure;
             }
 
@@ -1113,7 +1104,9 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
         return CE_Failure;
     }
 
-    if( iStartRow < 0 || (iStartRow+iLength) > this->nRows )
+    if( iStartRow < 0 ||
+        iLength >= INT_MAX - iStartRow ||
+        (iStartRow+iLength) > this->nRows )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "iStartRow (%d) + iLength(%d) out of range.", iStartRow, iLength );
@@ -1131,12 +1124,11 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
     {
         case GFT_Integer:
         {
-            VSIFSeekL( hHFA->fp, aoFields[iField].nDataOffset + (iStartRow*aoFields[iField].nElementSize), SEEK_SET );
-            GInt32 *panColData = (GInt32*)VSIMalloc2(iLength, sizeof(GInt32));
+            if( VSIFSeekL( hHFA->fp, aoFields[iField].nDataOffset + (static_cast<vsi_l_offset>(iStartRow)*aoFields[iField].nElementSize), SEEK_SET ) != 0 )
+                return CE_Failure;
+            GInt32 *panColData = (GInt32*)VSI_MALLOC2_VERBOSE(iLength, sizeof(GInt32));
             if( panColData == NULL )
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory,
-                    "Memory Allocation failed in HFARasterAttributeTable::ValuesIO");
                 return CE_Failure;
             }
 
@@ -1181,11 +1173,9 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
         case GFT_Real:
         {
             // allocate space for doubles
-            double *padfColData = (double*)VSIMalloc2(iLength, sizeof(double) );
+            double *padfColData = (double*)VSI_MALLOC2_VERBOSE(iLength, sizeof(double) );
             if( padfColData == NULL )
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory,
-                    "Memory Allocation failed in HFARasterAttributeTable::ValuesIO");
                 return CE_Failure;
             }
 
@@ -1208,7 +1198,7 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
             {
                 // copy them back to ints
                 for( int i = 0; i < iLength; i++ )
-                    pnData[i] = padfColData[i];
+                    pnData[i] = static_cast<int>(padfColData[i]);
             }
 
             CPLFree(padfColData);
@@ -1217,11 +1207,9 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
         case GFT_String:
         {
             // allocate space for string pointers
-            char **papszColData = (char**)VSIMalloc2(iLength, sizeof(char*));
+            char **papszColData = (char**)VSI_MALLOC2_VERBOSE(iLength, sizeof(char*));
             if( papszColData == NULL )
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory,
-                    "Memory Allocation failed in HFARasterAttributeTable::ValuesIO");
                 return CE_Failure;
             }
 
@@ -1252,7 +1240,7 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
             {
                 // copy them back to ints
                 for( int i = 0; i < iLength; i++ )
-                    pnData[i] = atol(papszColData[i]);
+                    pnData[i] = atoi(papszColData[i]);
             }
 
             // either we allocated them for write, or they were allocated
@@ -1289,7 +1277,9 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
         return CE_Failure;
     }
 
-    if( iStartRow < 0 || (iStartRow+iLength) > this->nRows )
+    if( iStartRow < 0 ||
+        iLength >= INT_MAX - iStartRow ||
+        (iStartRow+iLength) > this->nRows )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "iStartRow (%d) + iLength(%d) out of range.", iStartRow, iLength );
@@ -1300,11 +1290,9 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
     if( aoFields[iField].bConvertColors )
     {
         // convert to/from float color field
-        int *panColData = (int*)VSIMalloc2(iLength, sizeof(int) );
+        int *panColData = (int*)VSI_MALLOC2_VERBOSE(iLength, sizeof(int) );
         if( panColData == NULL )
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory,
-                "Memory Allocation failed in HFARasterAttributeTable::ValuesIO");
             CPLFree(panColData);
             return CE_Failure;
         }
@@ -1312,7 +1300,7 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
         if( eRWFlag == GF_Write )
         {
             for( int i = 0; i < iLength; i++ )
-                panColData[i] = atol(papszStrList[i]);
+                panColData[i] = atoi(papszStrList[i]);
         }
 
         CPLErr ret = ColorsIO(eRWFlag, iField, iStartRow, iLength, panColData);
@@ -1336,19 +1324,17 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
         case GFT_Integer:
         {
             // allocate space for ints
-            int *panColData = (int*)VSIMalloc2(iLength, sizeof(int) );
+            int *panColData = (int*)VSI_MALLOC2_VERBOSE(iLength, sizeof(int) );
             if( panColData == NULL )
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory,
-                    "Memory Allocation failed in HFARasterAttributeTable::ValuesIO");
                 return CE_Failure;
             }
-            
+
             if( eRWFlag == GF_Write )
             {
                 // convert user supplied strings to ints
                 for( int i = 0; i < iLength; i++ )
-                    panColData[i] = atol(papszStrList[i]);
+                    panColData[i] = atoi(papszStrList[i]);
             }
 
             // call values IO to read/write ints
@@ -1375,14 +1361,12 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
         case GFT_Real:
         {
             // allocate space for doubles
-            double *padfColData = (double*)VSIMalloc2(iLength, sizeof(double) );
+            double *padfColData = (double*)VSI_MALLOC2_VERBOSE(iLength, sizeof(double) );
             if( padfColData == NULL )
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory,
-                    "Memory Allocation failed in HFARasterAttributeTable::ValuesIO");
                 return CE_Failure;
             }
-            
+
             if( eRWFlag == GF_Write )
             {
                 // convert user supplied strings to doubles
@@ -1412,12 +1396,11 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
         break;
         case GFT_String:
         {
-            VSIFSeekL( hHFA->fp, aoFields[iField].nDataOffset + (iStartRow*aoFields[iField].nElementSize), SEEK_SET );
-            char *pachColData = (char*)VSIMalloc2(iLength, aoFields[iField].nElementSize);
+            if( VSIFSeekL( hHFA->fp, aoFields[iField].nDataOffset + (static_cast<vsi_l_offset>(iStartRow)*aoFields[iField].nElementSize), SEEK_SET ) != 0 )
+                return CE_Failure;
+            char *pachColData = (char*)VSI_MALLOC2_VERBOSE(iLength, aoFields[iField].nElementSize);
             if( pachColData == NULL )
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory,
-                    "Memory Allocation failed in HFARasterAttributeTable::ValuesIO");
                 return CE_Failure;
             }
 
@@ -1441,10 +1424,10 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
             else
             {
                 // we need to check that these strings will fit in the allocated space
-                int nNewMaxChars = aoFields[iField].nElementSize, nStringSize;
+                int nNewMaxChars = aoFields[iField].nElementSize;
                 for( int i = 0; i < iLength; i++ )
                 {
-                    nStringSize = strlen(papszStrList[i]) + 1;
+                    int nStringSize = static_cast<int>(strlen(papszStrList[i])) + 1;
                     if( nStringSize > nNewMaxChars )
                         nNewMaxChars = nStringSize;
                 }
@@ -1453,23 +1436,31 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
                 {
                     // OK we have a problem - the allocated space is not big enough
                     // we need to re-allocate the space and update the pointers
-                    // and copy accross the old data
-                    int nNewOffset = HFAAllocateSpace( this->hHFA->papoBand[this->nBand-1]->psInfo,
+                    // and copy across the old data
+                    const int nNewOffset = HFAAllocateSpace( this->hHFA->papoBand[this->nBand-1]->psInfo,
                                             this->nRows * nNewMaxChars);
                     char *pszBuffer = (char*)VSIMalloc2(aoFields[iField].nElementSize, sizeof(char));
                     char cNullByte = '\0';
                     for( int i = 0; i < this->nRows; i++ )
                     {
                         // seek to the old place
-                        VSIFSeekL( hHFA->fp, aoFields[iField].nDataOffset + (i*aoFields[iField].nElementSize), SEEK_SET );
+                        CPL_IGNORE_RET_VAL(VSIFSeekL( hHFA->fp, aoFields[iField].nDataOffset + (static_cast<vsi_l_offset>(i)*aoFields[iField].nElementSize), SEEK_SET ));
                         // read in old data
-                        VSIFReadL(pszBuffer, aoFields[iField].nElementSize, 1, hHFA->fp );
+                        CPL_IGNORE_RET_VAL(VSIFReadL(pszBuffer, aoFields[iField].nElementSize, 1, hHFA->fp ));
                         // seek to new place
-                        VSIFSeekL( hHFA->fp, nNewOffset + (i*nNewMaxChars), SEEK_SET );
+                        bool bOK = VSIFSeekL( hHFA->fp, nNewOffset + (static_cast<vsi_l_offset>(i)*nNewMaxChars), SEEK_SET ) == 0;
                         // write data to new place
-                        VSIFWriteL(pszBuffer, aoFields[iField].nElementSize, 1, hHFA->fp);
+                        bOK &= VSIFWriteL(pszBuffer, aoFields[iField].nElementSize, 1, hHFA->fp) == 1;
                         // make sure there is a terminating null byte just to be safe
-                        VSIFWriteL(&cNullByte, sizeof(char), 1, hHFA->fp);
+                        bOK &= VSIFWriteL(&cNullByte, sizeof(char), 1, hHFA->fp) == 1;
+                        if( !bOK )
+                        {
+                            CPLFree(pszBuffer);
+                            CPLFree(pachColData);
+                            CPLError( CE_Failure, CPLE_AppDefined,
+                                "HFARasterAttributeTable::ValuesIO : Cannot write values");
+                            return CE_Failure;
+                        }
                     }
                     // update our data structures
                     aoFields[iField].nElementSize = nNewMaxChars;
@@ -1483,16 +1474,18 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
 
                     // re-allocate our buffer
                     CPLFree(pachColData);
-                    pachColData = (char*)VSIMalloc2(iLength, nNewMaxChars);
+                    pachColData = (char*)VSI_MALLOC2_VERBOSE(iLength, nNewMaxChars);
                     if(pachColData == NULL )
                     {
-                        CPLError( CE_Failure, CPLE_OutOfMemory,
-                            "Memory Allocation failed in HFARasterAttributeTable::ValuesIO");
                         return CE_Failure;
                     }
 
                     // lastly seek to the right place in the new space ready to write
-                    VSIFSeekL( hHFA->fp, nNewOffset + (iStartRow*nNewMaxChars), SEEK_SET );
+                    if( VSIFSeekL( hHFA->fp, nNewOffset + (static_cast<vsi_l_offset>(iStartRow)*nNewMaxChars), SEEK_SET ) != 0 )
+                    {
+                        VSIFree(pachColData);
+                        return CE_Failure;
+                    }
                 }
 
                 // copy from application buffer
@@ -1520,29 +1513,31 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
 /*                               ColorsIO()                              */
 /************************************************************************/
 
-// Handle the fact that HFA stores colours as floats, but we need to 
+// Handle the fact that HFA stores colours as floats, but we need to
 // read them in as ints 0...255
 CPLErr HFARasterAttributeTable::ColorsIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, int *pnData)
 {
     // allocate space for doubles
-    double *padfData = (double*)VSIMalloc2(iLength, sizeof(double) );
+    double *padfData = (double*)VSI_MALLOC2_VERBOSE(iLength, sizeof(double) );
     if( padfData == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory,
-            "Memory Allocation failed in HFARasterAttributeTable::ColorsIO");
         return CE_Failure;
     }
 
     if( eRWFlag == GF_Write )
     {
         // copy the application supplied ints to doubles
-        // and convert 0..255 to 0..1 in the same manner 
+        // and convert 0..255 to 0..1 in the same manner
         // as the color table
         for( int i = 0; i < iLength; i++ )
             padfData[i] = pnData[i] / 255.0;
     }
 
-    VSIFSeekL( hHFA->fp, aoFields[iField].nDataOffset + (iStartRow*aoFields[iField].nElementSize), SEEK_SET );
+    if( VSIFSeekL( hHFA->fp, aoFields[iField].nDataOffset + (static_cast<vsi_l_offset>(iStartRow)*aoFields[iField].nElementSize), SEEK_SET ) != 0 )
+    {
+        CPLFree(padfData);
+        return CE_Failure;
+    }
 
     if( eRWFlag == GF_Read )
     {
@@ -1550,6 +1545,7 @@ CPLErr HFARasterAttributeTable::ColorsIO(GDALRWFlag eRWFlag, int iField, int iSt
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                 "HFARasterAttributeTable::ColorsIO : Cannot read values");
+            CPLFree(padfData);
             return CE_Failure;
         }
 #ifdef CPL_MSB
@@ -1566,6 +1562,7 @@ CPLErr HFARasterAttributeTable::ColorsIO(GDALRWFlag eRWFlag, int iField, int iSt
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                 "HFARasterAttributeTable::ColorsIO : Cannot write values");
+            CPLFree(padfData);
             return CE_Failure;
         }
     }
@@ -1573,7 +1570,7 @@ CPLErr HFARasterAttributeTable::ColorsIO(GDALRWFlag eRWFlag, int iField, int iSt
     if( eRWFlag == GF_Read )
     {
         // copy them back to ints converting 0..1 to 0..255 in
-        // the same manner as the color table 
+        // the same manner as the color table
         for( int i = 0; i < iLength; i++ )
             pnData[i] = MIN(255,(int) (padfData[i] * 256));
     }
@@ -1611,39 +1608,37 @@ void HFARasterAttributeTable::SetRowCount( int iCount )
         // We need to re-allocate space on disc
         for( int iCol = 0; iCol < (int)this->aoFields.size(); iCol++ )
         {
-            // new space 
-            int nNewOffset = HFAAllocateSpace( this->hHFA->papoBand[this->nBand-1]->psInfo,
+            // new space
+            const int nNewOffset = HFAAllocateSpace( this->hHFA->papoBand[this->nBand-1]->psInfo,
                                             iCount * aoFields[iCol].nElementSize);
 
             // only need to bother if there are actually rows
             if( this->nRows > 0 )
             {
                 // temp buffer for this column
-                void *pData = VSIMalloc2(this->nRows, aoFields[iCol].nElementSize);
+                void *pData = VSI_MALLOC2_VERBOSE(this->nRows, aoFields[iCol].nElementSize);
                 if( pData == NULL )
                 {
-                    CPLError( CE_Failure, CPLE_OutOfMemory,
-                        "Memory Allocation failed in HFARasterAttributeTable::SetRowCount");
                     return;
                 }
                 // read old data
-                VSIFSeekL( hHFA->fp, aoFields[iCol].nDataOffset, SEEK_SET );
-                if((int)VSIFReadL(pData, aoFields[iCol].nElementSize, this->nRows, hHFA->fp) != this->nRows )
+                if( VSIFSeekL( hHFA->fp, aoFields[iCol].nDataOffset, SEEK_SET ) != 0 ||
+                    (int)VSIFReadL(pData, aoFields[iCol].nElementSize, this->nRows, hHFA->fp) != this->nRows )
                 {
                     CPLError( CE_Failure, CPLE_AppDefined,
                         "HFARasterAttributeTable::SetRowCount : Cannot read values");
                     CPLFree(pData);
-                    return;                
+                    return;
                 }
 
                 // write data - new space will be uninitialised
-                VSIFSeekL( hHFA->fp, nNewOffset, SEEK_SET );
-                if((int)VSIFWriteL(pData, aoFields[iCol].nElementSize, this->nRows, hHFA->fp) != this->nRows )
+                if( VSIFSeekL( hHFA->fp, nNewOffset, SEEK_SET ) != 0 ||
+                    (int)VSIFWriteL(pData, aoFields[iCol].nElementSize, this->nRows, hHFA->fp) != this->nRows )
                 {
                     CPLError( CE_Failure, CPLE_AppDefined,
                             "HFARasterAttributeTable::SetRowCount : Cannot write values");
                     CPLFree(pData);
-                    return;                
+                    return;
                 }
                 CPLFree(pData);
             }
@@ -1686,8 +1681,8 @@ int HFARasterAttributeTable::GetRowOfValue( double dfValue ) const
         int iBin = (int) floor((dfValue - dfRow0Min) / dfBinSize);
         if( iBin < 0 || iBin >= this->nRows )
             return -1;
-        else
-            return iBin;
+
+        return iBin;
     }
 
 /* -------------------------------------------------------------------- */
@@ -1707,13 +1702,11 @@ int HFARasterAttributeTable::GetRowOfValue( double dfValue ) const
 /* -------------------------------------------------------------------- */
 /*      Search through rows for match.                                  */
 /* -------------------------------------------------------------------- */
-    int   iRow;
-
-    for( iRow = 0; iRow < this->nRows; iRow++ )
+    for( int iRow = 0; iRow < this->nRows; iRow++ )
     {
         if( nMinCol != -1 )
         {
-            while( iRow < this->nRows && dfValue < GetValueAsDouble(iRow, nMinCol) ) 
+            while( iRow < this->nRows && dfValue < GetValueAsDouble(iRow, nMinCol) )
                     iRow++;
 
             if( iRow == this->nRows )
@@ -1748,11 +1741,11 @@ int HFARasterAttributeTable::GetRowOfValue( int nValue ) const
 /*                          CreateColumn()                              */
 /************************************************************************/
 
-CPLErr HFARasterAttributeTable::CreateColumn( const char *pszFieldName, 
-                                GDALRATFieldType eFieldType, 
+CPLErr HFARasterAttributeTable::CreateColumn( const char *pszFieldName,
+                                GDALRATFieldType eFieldType,
                                 GDALRATFieldUsage eFieldUsage )
 {
-    if( this->eAccess == GA_ReadOnly )
+    if( eAccess == GA_ReadOnly )
     {
         CPLError( CE_Failure, CPLE_NoWriteAccess,
             "Dataset not open in update mode");
@@ -1760,7 +1753,7 @@ CPLErr HFARasterAttributeTable::CreateColumn( const char *pszFieldName,
     }
 
     // do we have a descriptor table already?
-    if( this->poDT == NULL || !EQUAL(this->poDT->GetType(),"Edsc_Table") )
+    if( poDT == NULL || !EQUAL(poDT->GetType(),"Edsc_Table") )
         CreateDT();
 
     int bConvertColors = FALSE;
@@ -1809,14 +1802,12 @@ CPLErr HFARasterAttributeTable::CreateColumn( const char *pszFieldName,
 /*      if necessary.                                                   */
 /* -------------------------------------------------------------------- */
 
-    HFAEntry        *poColumn;
-    poColumn = poDT->GetNamedChild(pszFieldName);
-        
+    HFAEntry *poColumn = poDT->GetNamedChild(pszFieldName);
+
     if(poColumn == NULL || !EQUAL(poColumn->GetType(),"Edsc_Column"))
-        poColumn = new HFAEntry( this->hHFA->papoBand[this->nBand-1]->psInfo,
+        poColumn = HFAEntry::New( hHFA->papoBand[nBand-1]->psInfo,
                                      pszFieldName, "Edsc_Column",
-                                     this->poDT );
-
+                                     poDT );
 
     poColumn->SetIntField( "numRows", this->nRows );
     int nElementSize = 0;
@@ -1847,12 +1838,12 @@ CPLErr HFARasterAttributeTable::CreateColumn( const char *pszFieldName,
         return CE_Failure;
     }
 
-    int nOffset = HFAAllocateSpace( this->hHFA->papoBand[this->nBand-1]->psInfo,
-                                        this->nRows * nElementSize );
+    const int nOffset = HFAAllocateSpace( this->hHFA->papoBand[this->nBand-1]->psInfo,
+                                          this->nRows * nElementSize );
     poColumn->SetIntField( "columnDataPtr", nOffset );
 
     if( bConvertColors )
-        // GDAL Int column 
+        // GDAL Int column
         eFieldType = GFT_Integer;
 
     AddColumn(pszFieldName, eFieldType, eFieldUsage, nOffset, nElementSize, poColumn, FALSE, bConvertColors);
@@ -1884,13 +1875,13 @@ CPLErr HFARasterAttributeTable::SetLinearBinning( double dfRow0MinIn, double dfB
     /* we should have an Edsc_BinFunction */
     HFAEntry *poBinFunction = this->poDT->GetNamedChild( "#Bin_Function#" );
     if( poBinFunction == NULL || !EQUAL(poBinFunction->GetType(),"Edsc_BinFunction") )
-        poBinFunction = new HFAEntry( hHFA->papoBand[nBand-1]->psInfo,
-                                      "#Bin_Function#", "Edsc_BinFunction",
-                                      this->poDT );
+        poBinFunction = HFAEntry::New( hHFA->papoBand[nBand-1]->psInfo,
+                                       "#Bin_Function#", "Edsc_BinFunction",
+                                       poDT );
 
-    // Because of the BaseData we have to hardcode the size. 
+    // Because of the BaseData we have to hardcode the size.
     poBinFunction->MakeData( 30 );
-       
+
     poBinFunction->SetStringField("binFunction", "direct");
     poBinFunction->SetDoubleField("minLimit",this->dfRow0Min);
     poBinFunction->SetDoubleField("maxLimit",(this->nRows -1)*this->dfBinSize+this->dfRow0Min);
@@ -1920,7 +1911,8 @@ int HFARasterAttributeTable::GetLinearBinning( double *pdfRow0Min, double *pdfBi
 
 CPLXMLNode *HFARasterAttributeTable::Serialize() const
 {
-    if( ( GetRowCount() * GetColumnCount() ) > RAT_MAX_ELEM_FOR_CLONE )
+    if( GetRowCount() != 0 &&
+        GetColumnCount() > RAT_MAX_ELEM_FOR_CLONE / GetRowCount() )
         return NULL;
 
     return GDALRasterAttributeTable::Serialize();
@@ -1930,40 +1922,39 @@ CPLXMLNode *HFARasterAttributeTable::Serialize() const
 /*                           HFARasterBand()                            */
 /************************************************************************/
 
-HFARasterBand::HFARasterBand( HFADataset *poDS, int nBand, int iOverview )
+HFARasterBand::HFARasterBand( HFADataset *poDSIn, int nBandIn, int iOverview )
 
 {
-    int nCompression;
-
     if( iOverview == -1 )
-        this->poDS = poDS;
+        poDS = poDSIn;
     else
-        this->poDS = NULL;
+        poDS = NULL;
 
-    this->hHFA = poDS->hHFA;
-    this->nBand = nBand;
+    this->hHFA = poDSIn->hHFA;
+    nBand = nBandIn;
     this->poCT = NULL;
     this->nThisOverview = iOverview;
     this->papoOverviewBands = NULL;
     this->bMetadataDirty = FALSE;
     this->poDefaultRAT = NULL;
-    this->nOverviews = -1; 
+    this->nOverviews = -1;
 
-    HFAGetBandInfo( hHFA, nBand, &nHFADataType,
+    int nCompression;
+    HFAGetBandInfo( hHFA, nBand, &eHFADataType,
                     &nBlockXSize, &nBlockYSize, &nCompression );
-    
+
 /* -------------------------------------------------------------------- */
 /*      If this is an overview, we need to fetch the actual size,       */
 /*      and block size.                                                 */
 /* -------------------------------------------------------------------- */
     if( iOverview > -1 )
     {
-        int nHFADataTypeO;
+        EPTType eHFADataTypeO;
 
         nOverviews = 0;
         if (HFAGetOverviewInfo( hHFA, nBand, iOverview,
                                 &nRasterXSize, &nRasterYSize,
-                                &nBlockXSize, &nBlockYSize, &nHFADataTypeO ) != CE_None)
+                                &nBlockXSize, &nBlockYSize, &eHFADataTypeO ) != CE_None)
         {
             nRasterXSize = nRasterYSize = 0;
             return;
@@ -1973,23 +1964,23 @@ HFARasterBand::HFARasterBand( HFADataset *poDS, int nBand, int iOverview )
 /*      If we are an 8bit overview of a 1bit layer, we need to mark     */
 /*      ourselves as being "resample: average_bit2grayscale".           */
 /* -------------------------------------------------------------------- */
-        if( nHFADataType == EPT_u1 && nHFADataTypeO == EPT_u8 )
+        if( eHFADataType == EPT_u1 && eHFADataTypeO == EPT_u8 )
         {
-            GDALMajorObject::SetMetadataItem( "RESAMPLING", 
+            GDALMajorObject::SetMetadataItem( "RESAMPLING",
                                               "AVERAGE_BIT2GRAYSCALE" );
             GDALMajorObject::SetMetadataItem( "NBITS", "8" );
-            nHFADataType = nHFADataTypeO;
         }
+        eHFADataType = eHFADataTypeO;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Set some other information.                                     */
 /* -------------------------------------------------------------------- */
     if( nCompression != 0 )
-        GDALMajorObject::SetMetadataItem( "COMPRESSION", "RLE", 
+        GDALMajorObject::SetMetadataItem( "COMPRESSION", "RLE",
                                           "IMAGE_STRUCTURE" );
 
-    switch( nHFADataType )
+    switch( eHFADataType )
     {
       case EPT_u1:
       case EPT_u2:
@@ -2036,20 +2027,20 @@ HFARasterBand::HFARasterBand( HFADataset *poDS, int nBand, int iOverview )
         /* notdef: this should really report an error, but this isn't
            so easy from within constructors. */
         CPLDebug( "GDAL", "Unsupported pixel type in HFARasterBand: %d.",
-                  (int) nHFADataType );
+                  eHFADataType );
         break;
     }
 
-    if( HFAGetDataTypeBits( nHFADataType ) < 8 )
+    if( HFAGetDataTypeBits( eHFADataType ) < 8 )
     {
-        GDALMajorObject::SetMetadataItem( 
-            "NBITS", 
-            CPLString().Printf( "%d", HFAGetDataTypeBits( nHFADataType ) ), "IMAGE_STRUCTURE" );
+        GDALMajorObject::SetMetadataItem(
+            "NBITS",
+            CPLString().Printf( "%d", HFAGetDataTypeBits( eHFADataType ) ), "IMAGE_STRUCTURE" );
     }
 
-    if( nHFADataType == EPT_s8 )
+    if( eHFADataType == EPT_s8 )
     {
-        GDALMajorObject::SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", 
+        GDALMajorObject::SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE",
                                           "IMAGE_STRUCTURE" );
     }
 
@@ -2070,7 +2061,7 @@ HFARasterBand::HFARasterBand( HFADataset *poDS, int nBand, int iOverview )
         {
             GDALColorEntry   sEntry;
 
-            // The following mapping assigns "equal sized" section of 
+            // The following mapping assigns "equal sized" section of
             // the [0...1] range to each possible output value and avoid
             // rounding issues for the "normal" values generated using n/255.
             // See bug #1732 for some discussion.
@@ -2078,7 +2069,7 @@ HFARasterBand::HFARasterBand( HFADataset *poDS, int nBand, int iOverview )
             sEntry.c2 = MIN(255,(short) (padfGreen[iColor] * 256));
             sEntry.c3 = MIN(255,(short) (padfBlue[iColor]  * 256));
             sEntry.c4 = MIN(255,(short) (padfAlpha[iColor] * 256));
-            
+
             if( padfBins != NULL )
                 poCT->SetColorEntry( (int) padfBins[iColor], &sEntry );
             else
@@ -2117,18 +2108,17 @@ HFARasterBand::~HFARasterBand()
 void HFARasterBand::ReadAuxMetadata()
 
 {
-    int i;
-    HFABand *poBand = hHFA->papoBand[nBand-1];
-
     // only load metadata for full resolution layer.
     if( nThisOverview != -1 )
         return;
 
-    const char ** pszAuxMetaData = GetHFAAuxMetaDataList();
-    for( i = 0; pszAuxMetaData[i] != NULL; i += 4 )
+    HFABand *poBand = hHFA->papoBand[nBand-1];
+
+    const char * const * pszAuxMetaData = GetHFAAuxMetaDataList();
+    for( int i = 0; pszAuxMetaData[i] != NULL; i += 4 )
     {
         HFAEntry *poEntry;
-        
+
         if( strlen(pszAuxMetaData[i]) > 0 )
             poEntry = poBand->poNode->GetNamedChild( pszAuxMetaData[i] );
         else
@@ -2144,21 +2134,20 @@ void HFARasterBand::ReadAuxMetadata()
         {
           case 'd':
           {
-              int nCount, iValue;
-              double dfValue;
               CPLString osValueList;
 
-              nCount = poEntry->GetFieldCount( pszFieldName, &eErr );
-              for( iValue = 0; eErr == CE_None && iValue < nCount; iValue++ )
+              int nCount = poEntry->GetFieldCount( pszFieldName, &eErr );
+              for( int iValue = 0; eErr == CE_None && iValue < nCount; iValue++ )
               {
                   CPLString osSubFieldName;
                   osSubFieldName.Printf( "%s[%d]", pszFieldName, iValue );
-                  dfValue = poEntry->GetDoubleField( osSubFieldName, &eErr );
+                  double dfValue
+                      = poEntry->GetDoubleField( osSubFieldName, &eErr );
                   if( eErr != CE_None )
                       break;
 
                   char szValueAsString[100];
-                  CPLsprintf( szValueAsString, "%.14g", dfValue );
+                  CPLsnprintf( szValueAsString, sizeof(szValueAsString), "%.14g", dfValue );
 
                   if( iValue > 0 )
                       osValueList += ",";
@@ -2171,20 +2160,19 @@ void HFARasterBand::ReadAuxMetadata()
           case 'i':
           case 'l':
           {
-              int nValue, nCount, iValue;
               CPLString osValueList;
 
-              nCount = poEntry->GetFieldCount( pszFieldName, &eErr );
-              for( iValue = 0; eErr == CE_None && iValue < nCount; iValue++ )
+              int nCount = poEntry->GetFieldCount( pszFieldName, &eErr );
+              for( int iValue = 0; eErr == CE_None && iValue < nCount; iValue++ )
               {
                   CPLString osSubFieldName;
                   osSubFieldName.Printf( "%s[%d]", pszFieldName, iValue );
-                  nValue = poEntry->GetIntField( osSubFieldName, &eErr );
+                  int nValue = poEntry->GetIntField( osSubFieldName, &eErr );
                   if( eErr != CE_None )
                       break;
 
                   char szValueAsString[100];
-                  sprintf( szValueAsString, "%d", nValue );
+                  snprintf( szValueAsString, sizeof(szValueAsString), "%d", nValue );
 
                   if( iValue > 0 )
                       osValueList += ",";
@@ -2197,8 +2185,8 @@ void HFARasterBand::ReadAuxMetadata()
           case 's':
           case 'e':
           {
-              const char *pszValue;
-              pszValue = poEntry->GetStringField( pszFieldName, &eErr );
+              const char *pszValue
+                  = poEntry->GetStringField( pszFieldName, &eErr );
               if( eErr == CE_None )
                   SetMetadataItem( pszAuxMetaData[i+2], pszValue );
           }
@@ -2216,14 +2204,13 @@ void HFARasterBand::ReadAuxMetadata()
 void HFARasterBand::ReadHistogramMetadata()
 
 {
-    int i;
-    HFABand *poBand = hHFA->papoBand[nBand-1];
-
     // only load metadata for full resolution layer.
     if( nThisOverview != -1 )
         return;
 
-    HFAEntry *poEntry = 
+    HFABand *poBand = hHFA->papoBand[nBand-1];
+
+    HFAEntry *poEntry =
         poBand->poNode->GetNamedChild( "Descriptor_Table.Histogram" );
     if ( poEntry == NULL )
         return;
@@ -2237,28 +2224,26 @@ void HFARasterBand::ReadHistogramMetadata()
 /* -------------------------------------------------------------------- */
 
     int nOffset =  poEntry->GetIntField( "columnDataPtr" );
-    const char * pszType =  poEntry->GetStringField( "dataType" );
+    const char *pszType =  poEntry->GetStringField( "dataType" );
     int nBinSize = 4;
-        
-    if( pszType != NULL && EQUALN( "real", pszType, 4 ) )
+
+    if( pszType != NULL && STARTS_WITH_CI(pszType, "real") )
         nBinSize = 8;
 
-    GUIntBig *panHistValues = (GUIntBig *) VSIMalloc2(sizeof(GUIntBig), nNumBins);
-    GByte  *pabyWorkBuf = (GByte *) VSIMalloc2(nBinSize, nNumBins);
-    
+    GUIntBig *panHistValues = (GUIntBig *) VSI_MALLOC2_VERBOSE(sizeof(GUIntBig), nNumBins);
+    GByte  *pabyWorkBuf = (GByte *) VSI_MALLOC2_VERBOSE(nBinSize, nNumBins);
+
     if (panHistValues == NULL || pabyWorkBuf == NULL)
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate memory");
         VSIFree(panHistValues);
         VSIFree(pabyWorkBuf);
         return;
     }
 
-    VSIFSeekL( hHFA->fp, nOffset, SEEK_SET );
-
-    if( (int)VSIFReadL( pabyWorkBuf, nBinSize, nNumBins, hHFA->fp ) != nNumBins)
+    if( VSIFSeekL( hHFA->fp, nOffset, SEEK_SET ) != 0 ||
+        (int)VSIFReadL( pabyWorkBuf, nBinSize, nNumBins, hHFA->fp ) != nNumBins)
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   "Cannot read histogram values." );
         CPLFree( panHistValues );
         CPLFree( pabyWorkBuf );
@@ -2266,17 +2251,17 @@ void HFARasterBand::ReadHistogramMetadata()
     }
 
     // Swap into local order.
-    for( i = 0; i < nNumBins; i++ )
+    for( int i = 0; i < nNumBins; i++ )
         HFAStandard( nBinSize, pabyWorkBuf + i*nBinSize );
 
     if( nBinSize == 8 ) // source is doubles
     {
-        for( i = 0; i < nNumBins; i++ )
+        for( int i = 0; i < nNumBins; i++ )
             panHistValues[i] = (GUIntBig) ((double *) pabyWorkBuf)[i];
     }
     else // source is 32bit integers
     {
-        for( i = 0; i < nNumBins; i++ )
+        for( int i = 0; i < nNumBins; i++ )
             panHistValues[i] = (GUIntBig) ((int *) pabyWorkBuf)[i];
     }
 
@@ -2290,26 +2275,28 @@ void HFARasterBand::ReadHistogramMetadata()
     HFAEntry *poBinEntry = poBand->poNode->GetNamedChild( "Descriptor_Table.#Bin_Function840#" );
 
     if( poBinEntry != NULL
-        && EQUAL(poBinEntry->GetType(),"Edsc_BinFunction840") 
-        && EQUAL(poBinEntry->GetStringField( "binFunction.type.string" ),
-                 "BFUnique") )
-        padfBinValues = HFAReadBFUniqueBins( poBinEntry, nNumBins );
+        && EQUAL(poBinEntry->GetType(),"Edsc_BinFunction840")  )
+    {
+        const char* pszValue = poBinEntry->GetStringField( "binFunction.type.string" );
+        if( pszValue && EQUAL(pszValue,"BFUnique") )
+            padfBinValues = HFAReadBFUniqueBins( poBinEntry, nNumBins );
+    }
 
     if( padfBinValues )
     {
         int nMaxValue = 0;
         int nMinValue = 1000000;
         int bAllInteger = TRUE;
-        
-        for( i = 0; i < nNumBins; i++ )
+
+        for( int i = 0; i < nNumBins; i++ )
         {
             if( padfBinValues[i] != floor(padfBinValues[i]) )
                 bAllInteger = FALSE;
-            
+
             nMaxValue = MAX(nMaxValue,(int)padfBinValues[i]);
             nMinValue = MIN(nMinValue,(int)padfBinValues[i]);
         }
-        
+
         if( nMinValue < 0 || nMaxValue > 1000 || !bAllInteger )
         {
             CPLFree( padfBinValues );
@@ -2318,10 +2305,10 @@ void HFARasterBand::ReadHistogramMetadata()
             return;
         }
 
-        int nNewBins = nMaxValue + 1;
+        const int nNewBins = nMaxValue + 1;
         GUIntBig *panNewHistValues = (GUIntBig *) CPLCalloc(sizeof(GUIntBig),nNewBins);
 
-        for( i = 0; i < nNumBins; i++ )
+        for( int i = 0; i < nNumBins; i++ )
             panNewHistValues[(int) padfBinValues[i]] = panHistValues[i];
 
         CPLFree( panHistValues );
@@ -2329,9 +2316,9 @@ void HFARasterBand::ReadHistogramMetadata()
         nNumBins = nNewBins;
 
         SetMetadataItem( "STATISTICS_HISTOMIN", "0" );
-        SetMetadataItem( "STATISTICS_HISTOMAX", 
+        SetMetadataItem( "STATISTICS_HISTOMAX",
                          CPLString().Printf("%d", nMaxValue ) );
-        SetMetadataItem( "STATISTICS_HISTONUMBINS", 
+        SetMetadataItem( "STATISTICS_HISTONUMBINS",
                          CPLString().Printf("%d", nMaxValue+1 ) );
 
         CPLFree(padfBinValues);
@@ -2353,17 +2340,16 @@ void HFARasterBand::ReadHistogramMetadata()
         if ( ( nBinValuesLen + strlen( szBuf ) + 2 ) > nBufSize )
         {
             nBufSize *= 2;
-            char* pszNewBinValues = (char *)VSIRealloc( pszBinValues, nBufSize );
+            char* pszNewBinValues = (char *)VSI_REALLOC_VERBOSE( pszBinValues, nBufSize );
             if (pszNewBinValues == NULL)
             {
-                CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate memory");
                 break;
             }
             pszBinValues = pszNewBinValues;
         }
         strcat( pszBinValues+nBinValuesLen, szBuf );
         strcat( pszBinValues+nBinValuesLen, "|" );
-        nBinValuesLen += strlen(pszBinValues+nBinValuesLen);
+        nBinValuesLen += static_cast<int>(strlen(pszBinValues+nBinValuesLen));
     }
 
     SetMetadataItem( "STATISTICS_HISTOBINVALUES", pszBinValues );
@@ -2386,17 +2372,17 @@ double HFARasterBand::GetNoDataValue( int *pbSuccess )
             *pbSuccess = TRUE;
         return dfNoData;
     }
-    else
-        return GDALPamRasterBand::GetNoDataValue( pbSuccess );
+
+    return GDALPamRasterBand::GetNoDataValue( pbSuccess );
 }
 
-/************************************************************************/ 
-/*                             SetNoDataValue()                         */ 
-/************************************************************************/ 
+/************************************************************************/
+/*                             SetNoDataValue()                         */
+/************************************************************************/
 
-CPLErr HFARasterBand::SetNoDataValue( double dfValue ) 
-{ 
-    return HFASetBandNoData( hHFA, nBand, dfValue ); 
+CPLErr HFARasterBand::SetNoDataValue( double dfValue )
+{
+    return HFASetBandNoData( hHFA, nBand, dfValue );
 }
 
 /************************************************************************/
@@ -2407,17 +2393,15 @@ double HFARasterBand::GetMinimum( int *pbSuccess )
 
 {
     const char *pszValue = GetMetadataItem( "STATISTICS_MINIMUM" );
-    
+
     if( pszValue != NULL )
     {
         if( pbSuccess )
             *pbSuccess = TRUE;
         return CPLAtofM(pszValue);
     }
-    else
-    {
-        return GDALRasterBand::GetMinimum( pbSuccess );
-    }
+
+    return GDALRasterBand::GetMinimum( pbSuccess );
 }
 
 /************************************************************************/
@@ -2428,17 +2412,15 @@ double HFARasterBand::GetMaximum( int *pbSuccess )
 
 {
     const char *pszValue = GetMetadataItem( "STATISTICS_MAXIMUM" );
-    
+
     if( pszValue != NULL )
     {
         if( pbSuccess )
             *pbSuccess = TRUE;
         return CPLAtofM(pszValue);
     }
-    else
-    {
-        return GDALRasterBand::GetMaximum( pbSuccess );
-    }
+
+    return GDALRasterBand::GetMaximum( pbSuccess );
 }
 
 /************************************************************************/
@@ -2483,8 +2465,8 @@ int HFARasterBand::GetOverviewCount()
 
     if( nOverviews == 0 )
         return GDALRasterBand::GetOverviewCount();
-    else
-        return nOverviews;
+
+    return nOverviews;
 }
 
 /************************************************************************/
@@ -2526,7 +2508,7 @@ CPLErr HFARasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                            nBlockXSize * nBlockYSize * (GDALGetDataTypeSize(eDataType) / 8));
     }
 
-    if( eErr == CE_None && nHFADataType == EPT_u4 )
+    if( eErr == CE_None && eHFADataType == EPT_u4 )
     {
         GByte	*pabyData = (GByte *) pImage;
 
@@ -2537,7 +2519,7 @@ CPLErr HFARasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             pabyData[ii]   = (pabyData[k]) & 0xf;
         }
     }
-    if( eErr == CE_None && nHFADataType == EPT_u2 )
+    if( eErr == CE_None && eHFADataType == EPT_u2 )
     {
         GByte	*pabyData = (GByte *) pImage;
 
@@ -2550,7 +2532,7 @@ CPLErr HFARasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             pabyData[ii]   = (pabyData[k]) & 0x3;
         }
     }
-    if( eErr == CE_None && nHFADataType == EPT_u1)
+    if( eErr == CE_None && eHFADataType == EPT_u1)
     {
         GByte	*pabyData = (GByte *) pImage;
 
@@ -2579,21 +2561,21 @@ CPLErr HFARasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
 /*      Do we need to pack 1/2/4 bit data?                              */
 /* -------------------------------------------------------------------- */
-    if( nHFADataType == EPT_u1 
-        || nHFADataType == EPT_u2
-        || nHFADataType == EPT_u4 )
+    if( eHFADataType == EPT_u1
+        || eHFADataType == EPT_u2
+        || eHFADataType == EPT_u4 )
     {
-        int nPixCount =  nBlockXSize * nBlockYSize;
+        const int nPixCount =  nBlockXSize * nBlockYSize;
         pabyOutBuf = (GByte *) VSIMalloc2(nBlockXSize, nBlockYSize);
         if (pabyOutBuf == NULL)
             return CE_Failure;
 
-        if( nHFADataType == EPT_u1 )
+        if( eHFADataType == EPT_u1 )
         {
             for( int ii = 0; ii < nPixCount - 7; ii += 8 )
             {
                 int k = ii>>3;
-                pabyOutBuf[k] = 
+                pabyOutBuf[k] =
                     (((GByte *) pImage)[ii] & 0x1)
                     | ((((GByte *) pImage)[ii+1]&0x1) << 1)
                     | ((((GByte *) pImage)[ii+2]&0x1) << 2)
@@ -2604,30 +2586,30 @@ CPLErr HFARasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                     | ((((GByte *) pImage)[ii+7]&0x1) << 7);
             }
         }
-        else if( nHFADataType == EPT_u2 )
+        else if( eHFADataType == EPT_u2 )
         {
             for( int ii = 0; ii < nPixCount - 3; ii += 4 )
             {
                 int k = ii>>2;
-                pabyOutBuf[k] = 
+                pabyOutBuf[k] =
                     (((GByte *) pImage)[ii] & 0x3)
                     | ((((GByte *) pImage)[ii+1]&0x3) << 2)
                     | ((((GByte *) pImage)[ii+2]&0x3) << 4)
                     | ((((GByte *) pImage)[ii+3]&0x3) << 6);
             }
         }
-        else if( nHFADataType == EPT_u4 )
+        else if( eHFADataType == EPT_u4 )
         {
             for( int ii = 0; ii < nPixCount - 1; ii += 2 )
             {
                 int k = ii>>1;
-                pabyOutBuf[k] = 
-                    (((GByte *) pImage)[ii] & 0xf) 
+                pabyOutBuf[k] =
+                    (((GByte *) pImage)[ii] & 0xf)
                     | ((((GByte *) pImage)[ii+1]&0xf) << 4);
             }
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Actually write out.                                             */
 /* -------------------------------------------------------------------- */
@@ -2654,13 +2636,13 @@ CPLErr HFARasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
 const char * HFARasterBand::GetDescription() const
 {
     const char *pszName = HFAGetBandName( hHFA, nBand );
-    
+
     if( pszName == NULL )
         return GDALPamRasterBand::GetDescription();
-    else
-        return pszName;
+
+    return pszName;
 }
- 
+
 /************************************************************************/
 /*                         SetDescription()                             */
 /************************************************************************/
@@ -2679,8 +2661,8 @@ GDALColorInterp HFARasterBand::GetColorInterpretation()
 {
     if( poCT != NULL )
         return GCI_PaletteIndex;
-    else
-        return GCI_Undefined;
+
+    return GCI_Undefined;
 }
 
 /************************************************************************/
@@ -2702,7 +2684,7 @@ CPLErr HFARasterBand::SetColorTable( GDALColorTable * poCTable )
 {
     if( GetAccess() == GA_ReadOnly )
     {
-        CPLError( CE_Failure, CPLE_NoWriteAccess, 
+        CPLError( CE_Failure, CPLE_NoWriteAccess,
                   "Unable to set color table on read-only file." );
         return CE_Failure;
     }
@@ -2723,7 +2705,7 @@ CPLErr HFARasterBand::SetColorTable( GDALColorTable * poCTable )
 /* -------------------------------------------------------------------- */
 /*      Write out the colortable, and update the configuration.         */
 /* -------------------------------------------------------------------- */
-    int nColors = poCTable->GetColorEntryCount();
+    const int nColors = poCTable->GetColorEntryCount();
 
     double *padfRed, *padfGreen, *padfBlue, *padfAlpha;
 
@@ -2735,9 +2717,9 @@ CPLErr HFARasterBand::SetColorTable( GDALColorTable * poCTable )
     for( int iColor = 0; iColor < nColors; iColor++ )
     {
         GDALColorEntry  sRGB;
-	    
+
         poCTable->GetColorEntryAsRGB( iColor, &sRGB );
-        
+
         padfRed[iColor] = sRGB.c1 / 255.0;
         padfGreen[iColor] = sRGB.c2 / 255.0;
         padfBlue[iColor] = sRGB.c3 / 255.0;
@@ -2754,7 +2736,7 @@ CPLErr HFARasterBand::SetColorTable( GDALColorTable * poCTable )
 
     if( poCT )
       delete poCT;
-    
+
     poCT = poCTable->Clone();
 
     return CE_None;
@@ -2798,9 +2780,7 @@ CPLErr HFARasterBand::CleanOverviews()
 /* -------------------------------------------------------------------- */
 /*      Clear our reference to overviews as bands.                      */
 /* -------------------------------------------------------------------- */
-    int iOverview;
-
-    for( iOverview = 0; iOverview < nOverviews; iOverview++ )
+    for( int iOverview = 0; iOverview < nOverviews; iOverview++ )
         delete papoOverviewBands[iOverview];
 
     CPLFree( papoOverviewBands );
@@ -2820,9 +2800,8 @@ CPLErr HFARasterBand::CleanOverviews()
 /* -------------------------------------------------------------------- */
 /*      Destroy and subsample layers under our band.                    */
 /* -------------------------------------------------------------------- */
-    HFAEntry *poChild;
-    for( poChild = poBand->poNode->GetChild(); 
-         poChild != NULL; ) 
+    for( HFAEntry *poChild = poBand->poNode->GetChild();
+         poChild != NULL; )
     {
         HFAEntry *poNext = poChild->GetNext();
 
@@ -2839,13 +2818,13 @@ CPLErr HFARasterBand::CleanOverviews()
 /* -------------------------------------------------------------------- */
     if( hHFA->psDependent != hHFA && hHFA->psDependent != NULL )
     {
-        CPLString osFilename = 
-            CPLFormFilename( hHFA->psDependent->pszPath, 
+        CPLString osFilename =
+            CPLFormFilename( hHFA->psDependent->pszPath,
                              hHFA->psDependent->pszFilename, NULL );
-        
-        HFAClose( hHFA->psDependent );
+
+        CPL_IGNORE_RET_VAL(HFAClose( hHFA->psDependent ));
         hHFA->psDependent = NULL;
-        
+
         CPLDebug( "HFA", "Unlink(%s)", osFilename.c_str() );
         VSIUnlink( osFilename );
     }
@@ -2857,21 +2836,17 @@ CPLErr HFARasterBand::CleanOverviews()
 /*                           BuildOverviews()                           */
 /************************************************************************/
 
-CPLErr HFARasterBand::BuildOverviews( const char *pszResampling, 
-                                      int nReqOverviews, int *panOverviewList, 
-                                      GDALProgressFunc pfnProgress, 
+CPLErr HFARasterBand::BuildOverviews( const char *pszResampling,
+                                      int nReqOverviews, int *panOverviewList,
+                                      GDALProgressFunc pfnProgress,
                                       void *pProgressData )
 
 {
-    int iOverview;
-    GDALRasterBand **papoOvBands;
-    int bNoRegen = FALSE;
-
     EstablishOverviews();
-    
+
     if( nThisOverview != -1 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Attempt to build overviews on an overview layer." );
 
         return CE_Failure;
@@ -2880,9 +2855,11 @@ CPLErr HFARasterBand::BuildOverviews( const char *pszResampling,
     if( nReqOverviews == 0 )
         return CleanOverviews();
 
-    papoOvBands = (GDALRasterBand **) CPLCalloc(sizeof(void*),nReqOverviews);
+    GDALRasterBand **papoOvBands
+        = (GDALRasterBand **) CPLCalloc(sizeof(void*),nReqOverviews);
 
-    if( EQUALN(pszResampling,"NO_REGEN:",9) )
+    int bNoRegen = FALSE;
+    if( STARTS_WITH_CI(pszResampling, "NO_REGEN:") )
     {
         pszResampling += 9;
         bNoRegen = TRUE;
@@ -2891,30 +2868,26 @@ CPLErr HFARasterBand::BuildOverviews( const char *pszResampling,
 /* -------------------------------------------------------------------- */
 /*      Loop over overview levels requested.                            */
 /* -------------------------------------------------------------------- */
-    for( iOverview = 0; iOverview < nReqOverviews; iOverview++ )
+    for( int iOverview = 0; iOverview < nReqOverviews; iOverview++ )
     {
 /* -------------------------------------------------------------------- */
 /*      Find this overview level.                                       */
 /* -------------------------------------------------------------------- */
-        int i, iResult = -1, nReqOvLevel;
-
-        nReqOvLevel = 
+        int nReqOvLevel =
             GDALOvLevelAdjust2(panOverviewList[iOverview],nRasterXSize,nRasterYSize);
 
-        for( i = 0; i < nOverviews && papoOvBands[iOverview] == NULL; i++ )
+        for( int i = 0; i < nOverviews && papoOvBands[iOverview] == NULL; i++ )
         {
-            int nThisOvLevel;
-            
             if( papoOverviewBands[i] == NULL )
             {
                 CPLDebug("HFA", "Shouldn't happen happened at line %d", __LINE__);
                 continue;
             }
 
-            nThisOvLevel = GDALComputeOvFactor(papoOverviewBands[i]->GetXSize(),
-                                               GetXSize(),
-                                               papoOverviewBands[i]->GetYSize(),
-                                               GetYSize());
+            int nThisOvLevel = GDALComputeOvFactor(papoOverviewBands[i]->GetXSize(),
+                                                   GetXSize(),
+                                                   papoOverviewBands[i]->GetYSize(),
+                                                   GetYSize());
 
             if( nReqOvLevel == nThisOvLevel )
                 papoOvBands[iOverview] = papoOverviewBands[i];
@@ -2925,23 +2898,26 @@ CPLErr HFARasterBand::BuildOverviews( const char *pszResampling,
 /* -------------------------------------------------------------------- */
         if( papoOvBands[iOverview] == NULL )
         {
-            iResult = HFACreateOverview( hHFA, nBand, 
+            int iResult = HFACreateOverview( hHFA, nBand,
                                          panOverviewList[iOverview],
                                          pszResampling );
             if( iResult < 0 )
+            {
+                CPLFree( papoOvBands );
                 return CE_Failure;
+            }
 
             if( papoOverviewBands == NULL && nOverviews == 0 && iResult > 0)
             {
                 CPLDebug("HFA", "Shouldn't happen happened at line %d", __LINE__);
-                papoOverviewBands = (HFARasterBand **) 
+                papoOverviewBands = (HFARasterBand **)
                     CPLCalloc( sizeof(void*), iResult );
             }
 
             nOverviews = iResult + 1;
-            papoOverviewBands = (HFARasterBand **) 
+            papoOverviewBands = (HFARasterBand **)
                 CPLRealloc( papoOverviewBands, sizeof(void*) * nOverviews);
-            papoOverviewBands[iResult] = new HFARasterBand( 
+            papoOverviewBands[iResult] = new HFARasterBand(
                 (HFADataset *) poDS, nBand, iResult );
 
             papoOvBands[iOverview] = papoOverviewBands[iResult];
@@ -2955,14 +2931,14 @@ CPLErr HFARasterBand::BuildOverviews( const char *pszResampling,
     CPLErr eErr = CE_None;
 
     if( !bNoRegen )
-        eErr = GDALRegenerateOverviews( (GDALRasterBandH) this, 
-                                        nReqOverviews, 
+        eErr = GDALRegenerateOverviews( (GDALRasterBandH) this,
+                                        nReqOverviews,
                                         (GDALRasterBandH *) papoOvBands,
-                                        pszResampling, 
+                                        pszResampling,
                                         pfnProgress, pProgressData );
-    
+
     CPLFree( papoOvBands );
-    
+
     return eErr;
 }
 
@@ -2970,28 +2946,27 @@ CPLErr HFARasterBand::BuildOverviews( const char *pszResampling,
 /*                        GetDefaultHistogram()                         */
 /************************************************************************/
 
-CPLErr 
+CPLErr
 HFARasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
                                     int *pnBuckets, GUIntBig ** ppanHistogram,
                                     int bForce,
-                                    GDALProgressFunc pfnProgress, 
+                                    GDALProgressFunc pfnProgress,
                                     void *pProgressData)
 
 {
-    if( GetMetadataItem( "STATISTICS_HISTOBINVALUES" ) != NULL 
-        && GetMetadataItem( "STATISTICS_HISTOMIN" ) != NULL 
+    if( GetMetadataItem( "STATISTICS_HISTOBINVALUES" ) != NULL
+        && GetMetadataItem( "STATISTICS_HISTOMIN" ) != NULL
         && GetMetadataItem( "STATISTICS_HISTOMAX" ) != NULL )
     {
-        int i;
         const char *pszNextBin;
-        const char *pszBinValues = 
+        const char *pszBinValues =
             GetMetadataItem( "STATISTICS_HISTOBINVALUES" );
 
         *pdfMin = CPLAtof(GetMetadataItem("STATISTICS_HISTOMIN"));
         *pdfMax = CPLAtof(GetMetadataItem("STATISTICS_HISTOMAX"));
 
         *pnBuckets = 0;
-        for( i = 0; pszBinValues[i] != '\0'; i++ )
+        for( int i = 0; pszBinValues[i] != '\0'; i++ )
         {
             if( pszBinValues[i] == '|' )
                 (*pnBuckets)++;
@@ -3000,7 +2975,7 @@ HFARasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
         *ppanHistogram = (GUIntBig *) CPLCalloc(sizeof(GUIntBig),*pnBuckets);
 
         pszNextBin = pszBinValues;
-        for( i = 0; i < *pnBuckets; i++ )
+        for( int i = 0; i < *pnBuckets; i++ )
         {
             (*ppanHistogram)[i] = (GUIntBig) CPLAtoGIntBig(pszNextBin);
 
@@ -3018,9 +2993,9 @@ HFARasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
         return CE_None;
     }
     else
-        return GDALPamRasterBand::GetDefaultHistogram( pdfMin, pdfMax, 
+        return GDALPamRasterBand::GetDefaultHistogram( pdfMin, pdfMax,
                                                        pnBuckets,ppanHistogram,
-                                                       bForce, 
+                                                       bForce,
                                                        pfnProgress,
                                                        pProgressData );
 }
@@ -3044,7 +3019,7 @@ CPLErr HFARasterBand::SetDefaultRAT( const GDALRasterAttributeTable * poRAT )
 
 GDALRasterAttributeTable *HFARasterBand::GetDefaultRAT()
 
-{		
+{
     if( poDefaultRAT == NULL )
         poDefaultRAT = new HFARasterAttributeTable(this, "Descriptor_Table" );
 
@@ -3055,45 +3030,45 @@ GDALRasterAttributeTable *HFARasterBand::GetDefaultRAT()
 /*                            WriteNamedRAT()                            */
 /************************************************************************/
 
-CPLErr HFARasterBand::WriteNamedRAT( CPL_UNUSED const char *pszName,
-                                     CPL_UNUSED const GDALRasterAttributeTable *poRAT )
+CPLErr HFARasterBand::WriteNamedRAT( const char * /*pszName*/,
+                                     const GDALRasterAttributeTable* poRAT )
 {
 /* -------------------------------------------------------------------- */
 /*      Find the requested table.                                       */
 /* -------------------------------------------------------------------- */
     HFAEntry * poDT = hHFA->papoBand[nBand-1]->poNode->GetNamedChild( "Descriptor_Table" );
     if( poDT == NULL || !EQUAL(poDT->GetType(),"Edsc_Table") )
-        poDT = new HFAEntry( hHFA->papoBand[nBand-1]->psInfo,
+        poDT = HFAEntry::New( hHFA->papoBand[nBand-1]->psInfo,
                              "Descriptor_Table", "Edsc_Table",
                              hHFA->papoBand[nBand-1]->poNode );
 
-    int nRowCount = poRAT->GetRowCount();
+    const int nRowCount = poRAT->GetRowCount();
 
     poDT->SetIntField( "numrows", nRowCount );
-    /* Check if binning is set on this RAT */    
+    /* Check if binning is set on this RAT */
     double dfBinSize, dfRow0Min;
-    if(poRAT->GetLinearBinning( &dfRow0Min, &dfBinSize)) 
+    if(poRAT->GetLinearBinning( &dfRow0Min, &dfBinSize))
     {
         /* then it should have an Edsc_BinFunction */
         HFAEntry *poBinFunction = poDT->GetNamedChild( "#Bin_Function#" );
         if( poBinFunction == NULL || !EQUAL(poBinFunction->GetType(),"Edsc_BinFunction") )
-            poBinFunction = new HFAEntry( hHFA->papoBand[nBand-1]->psInfo,
+            poBinFunction = HFAEntry::New( hHFA->papoBand[nBand-1]->psInfo,
                                           "#Bin_Function#", "Edsc_BinFunction",
                                           poDT );
-       
+
         poBinFunction->SetStringField("binFunction", "direct");
         poBinFunction->SetDoubleField("minLimit",dfRow0Min);
         poBinFunction->SetDoubleField("maxLimit",(nRowCount -1)*dfBinSize+dfRow0Min);
         poBinFunction->SetIntField("numBins",nRowCount);
     }
- 
+
 /* -------------------------------------------------------------------- */
 /*      Loop through each column in the RAT                             */
 /* -------------------------------------------------------------------- */
     for(int col = 0; col < poRAT->GetColumnCount(); col++)
     {
         const char *pszName = NULL;
- 
+
         if( poRAT->GetUsageOfCol(col) == GFU_Red )
         {
             pszName = "Red";
@@ -3122,38 +3097,37 @@ CPLErr HFARasterBand::WriteNamedRAT( CPL_UNUSED const char *pszName,
         {
             pszName = poRAT->GetNameOfCol(col);
         }
-            
+
 /* -------------------------------------------------------------------- */
 /*      Check to see if a column with pszName exists and create if      */
 /*      if necessary.                                                   */
 /* -------------------------------------------------------------------- */
 
-        HFAEntry        *poColumn;
-        poColumn = poDT->GetNamedChild(pszName);
-	    
+        HFAEntry *poColumn = poDT->GetNamedChild(pszName);
+
         if(poColumn == NULL || !EQUAL(poColumn->GetType(),"Edsc_Column"))
-	    poColumn = new HFAEntry( hHFA->papoBand[nBand-1]->psInfo,
+	    poColumn = HFAEntry::New( hHFA->papoBand[nBand-1]->psInfo,
                                      pszName, "Edsc_Column",
                                      poDT );
 
 
         poColumn->SetIntField( "numRows", nRowCount );
         // color cols which are integer in GDAL are written as floats in HFA
-        int bIsColorCol = FALSE;
+        bool bIsColorCol = false;
         if( ( poRAT->GetUsageOfCol(col) == GFU_Red ) || ( poRAT->GetUsageOfCol(col) == GFU_Green ) ||
             ( poRAT->GetUsageOfCol(col) == GFU_Blue) || ( poRAT->GetUsageOfCol(col) == GFU_Alpha ) )
         {
-            bIsColorCol = TRUE;
+            bIsColorCol = true;
         }
-   
+
         // write float also if a color column, or histogram
         if( ( poRAT->GetTypeOfCol(col) == GFT_Real ) || bIsColorCol || (poRAT->GetUsageOfCol(col) == GFU_PixelCount) )
         {
             int nOffset = HFAAllocateSpace( hHFA->papoBand[nBand-1]->psInfo,
-                                            nRowCount * sizeof(double) );
+                                            (GUInt32)nRowCount * (GUInt32)sizeof(double) );
             poColumn->SetIntField( "columnDataPtr", nOffset );
             poColumn->SetStringField( "dataType", "real" );
-            
+
             double *padfColData = (double*)CPLCalloc( nRowCount, sizeof(double) );
             for( int i = 0; i < nRowCount; i++)
             {
@@ -3166,8 +3140,13 @@ CPLErr HFARasterBand::WriteNamedRAT( CPL_UNUSED const char *pszName,
 #ifdef CPL_MSB
             GDALSwapWords( padfColData, 8, nRowCount, 8 );
 #endif
-            VSIFSeekL( hHFA->fp, nOffset, SEEK_SET );
-            VSIFWriteL( padfColData, nRowCount, sizeof(double), hHFA->fp );
+            if( VSIFSeekL( hHFA->fp, nOffset, SEEK_SET ) != 0 ||
+                VSIFWriteL( padfColData, nRowCount, sizeof(double), hHFA->fp ) != sizeof(double) )
+            {
+                CPLError(CE_Failure, CPLE_FileIO, "WriteNamedRAT() failed");
+                CPLFree( padfColData );
+                return CE_Failure;
+            }
             CPLFree( padfColData );
         }
         else if( poRAT->GetTypeOfCol(col) == GFT_String )
@@ -3177,35 +3156,40 @@ CPLErr HFARasterBand::WriteNamedRAT( CPL_UNUSED const char *pszName,
             for( int i = 0; i < nRowCount; i++)
             {
                 /* Include terminating byte */
-                nNumChars = strlen(poRAT->GetValueAsString(i,col)) + 1;
+                nNumChars = static_cast<int>(strlen(poRAT->GetValueAsString(i,col)) + 1);
                 if(nMaxNumChars < nNumChars)
                 {
                     nMaxNumChars = nNumChars;
                 }
             }
-       
+
             int nOffset = HFAAllocateSpace( hHFA->papoBand[nBand-1]->psInfo,
                                             (nRowCount+1) * nMaxNumChars );
             poColumn->SetIntField( "columnDataPtr", nOffset );
             poColumn->SetStringField( "dataType", "string" );
             poColumn->SetIntField( "maxNumChars", nMaxNumChars );
-       
+
             char *pachColData = (char*)CPLCalloc(nRowCount+1,nMaxNumChars);
             for( int i = 0; i < nRowCount; i++)
             {
                 strcpy(&pachColData[nMaxNumChars*i],poRAT->GetValueAsString(i,col));
             }
-            VSIFSeekL( hHFA->fp, nOffset, SEEK_SET );
-            VSIFWriteL( pachColData, nRowCount, nMaxNumChars, hHFA->fp );
+            if( VSIFSeekL( hHFA->fp, nOffset, SEEK_SET ) != 0 ||
+                VSIFWriteL( pachColData, nRowCount, nMaxNumChars, hHFA->fp ) != nMaxNumChars )
+            {
+                CPLError(CE_Failure, CPLE_FileIO, "WriteNamedRAT() failed");
+                CPLFree( pachColData );
+                return CE_Failure;
+            }
             CPLFree( pachColData );
         }
         else if (poRAT->GetTypeOfCol(col) == GFT_Integer)
         {
             int nOffset = HFAAllocateSpace( hHFA->papoBand[nBand-1]->psInfo,
-                                            nRowCount * sizeof(GInt32) );
+                                            (GUInt32)nRowCount * (GUInt32)sizeof(GInt32) );
             poColumn->SetIntField( "columnDataPtr", nOffset );
             poColumn->SetStringField( "dataType", "integer" );
-            
+
             GInt32 *panColData = (GInt32*)CPLCalloc(nRowCount, sizeof(GInt32));
             for( int i = 0; i < nRowCount; i++)
             {
@@ -3214,8 +3198,13 @@ CPLErr HFARasterBand::WriteNamedRAT( CPL_UNUSED const char *pszName,
 #ifdef CPL_MSB
             GDALSwapWords( panColData, 4, nRowCount, 4 );
 #endif
-            VSIFSeekL( hHFA->fp, nOffset, SEEK_SET );
-            VSIFWriteL( panColData, nRowCount, sizeof(GInt32), hHFA->fp );
+            if( VSIFSeekL( hHFA->fp, nOffset, SEEK_SET ) != 0 ||
+                VSIFWriteL( panColData, nRowCount, sizeof(GInt32), hHFA->fp ) != sizeof(GInt32) )
+            {
+                CPLError(CE_Failure, CPLE_FileIO, "WriteNamedRAT() failed");
+                CPLFree( panColData );
+                return CE_Failure;
+            }
             CPLFree( panColData );
         }
         else
@@ -3225,8 +3214,8 @@ CPLErr HFARasterBand::WriteNamedRAT( CPL_UNUSED const char *pszName,
                       "Writing this data type in a column is not supported for this Raster Attribute Table.");
         }
     }
-   
-    return CE_None;  
+
+    return CE_None;
 }
 
 
@@ -3251,6 +3240,7 @@ HFADataset::HFADataset()
     bForceToPEString = FALSE;
 
     nGCPCount = 0;
+    memset(asGCPList, 0, sizeof(asGCPList));
 }
 
 /************************************************************************/
@@ -3263,13 +3253,11 @@ HFADataset::~HFADataset()
     FlushCache();
 
 /* -------------------------------------------------------------------- */
-/*      Destroy the raster bands if they exist.  We forcably clean      */
+/*      Destroy the raster bands if they exist.  We forcibly clean      */
 /*      them up now to avoid any effort to write to them after the      */
 /*      file is closed.                                                 */
 /* -------------------------------------------------------------------- */
-    int i;
-
-    for( i = 0; i < nBands && papoBands != NULL; i++ )
+    for( int i = 0; i < nBands && papoBands != NULL; i++ )
     {
         if( papoBands[i] != NULL )
             delete papoBands[i];
@@ -3283,7 +3271,10 @@ HFADataset::~HFADataset()
 /* -------------------------------------------------------------------- */
     if( hHFA != NULL )
     {
-        HFAClose( hHFA );
+        if( HFAClose( hHFA ) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        }
         hHFA = NULL;
     }
 
@@ -3339,26 +3330,25 @@ void HFADataset::FlushCache()
 CPLErr HFADataset::WriteProjection()
 
 {
-    Eprj_Datum	        sDatum;
-    Eprj_ProParameters  sPro;
-    Eprj_MapInfo	sMapInfo;
     OGRSpatialReference	oSRS;
-    OGRSpatialReference *poGeogSRS = NULL;
-    int                 bHaveSRS;
     char		*pszP = pszProjection;
-    int                 bPEStringStored = FALSE;
+    bool bPEStringStored = false;
 
     bGeoDirty = FALSE;
 
+    bool bHaveSRS;
     if( pszProjection != NULL && strlen(pszProjection) > 0
         && oSRS.importFromWkt( &pszP ) == OGRERR_NONE )
-        bHaveSRS = TRUE;
+        bHaveSRS = true;
     else
-        bHaveSRS = FALSE;
+        bHaveSRS = false;
 
 /* -------------------------------------------------------------------- */
 /*      Initialize projection and datum.                                */
 /* -------------------------------------------------------------------- */
+    Eprj_Datum	        sDatum;
+    Eprj_ProParameters  sPro;
+    Eprj_MapInfo	sMapInfo;
     memset( &sPro, 0, sizeof(sPro) );
     memset( &sDatum, 0, sizeof(sDatum) );
     memset( &sMapInfo, 0, sizeof(sMapInfo) );
@@ -3366,6 +3356,7 @@ CPLErr HFADataset::WriteProjection()
 /* -------------------------------------------------------------------- */
 /*      Collect datum information.                                      */
 /* -------------------------------------------------------------------- */
+    OGRSpatialReference *poGeogSRS = NULL;
     if( bHaveSRS )
     {
         poGeogSRS = oSRS.CloneGeogCS();
@@ -3373,14 +3364,12 @@ CPLErr HFADataset::WriteProjection()
 
     if( poGeogSRS )
     {
-        int	i;
-
         sDatum.datumname = (char *) poGeogSRS->GetAttrValue( "GEOGCS|DATUM" );
         if( sDatum.datumname == NULL )
             sDatum.datumname = (char*) "";
 
         /* WKT to Imagine translation */
-        for( i = 0; apszDatumMap[i] != NULL; i += 2 )
+        for( int i = 0; apszDatumMap[i] != NULL; i += 2 )
         {
             if( EQUAL(sDatum.datumname,apszDatumMap[i+1]) )
             {
@@ -3402,7 +3391,7 @@ CPLErr HFADataset::WriteProjection()
             sDatum.datumname = (char*) "NAD83";
         if( nGCS == 4283 )
             sDatum.datumname = (char*) "GDA94";
-            
+
         if( poGeogSRS->GetTOWGS84( sDatum.params ) == OGRERR_NONE )
             sDatum.type = EPRJ_DATUM_PARAMETRIC;
         else if( EQUAL(sDatum.datumname,"NAD27") )
@@ -3417,7 +3406,7 @@ CPLErr HFADataset::WriteProjection()
         }
 
         /* Verify if we need to write a ESRI PE string */
-        bPEStringStored = WritePeStringIfNeeded(&oSRS, hHFA);
+        bPEStringStored = CPL_TO_BOOL(WritePeStringIfNeeded(&oSRS, hHFA));
 
         sPro.proSpheroid.sphereName = (char *)
             poGeogSRS->GetAttrValue( "GEOGCS|DATUM|SPHEROID" );
@@ -3453,7 +3442,7 @@ CPLErr HFADataset::WriteProjection()
         HFASetPEString( hHFA, pszPEString );
         CPLFree( pszPEString );
 
-        bPEStringStored = TRUE;
+        bPEStringStored = true;
     }
     else if( pszProjName == NULL )
     {
@@ -3501,7 +3490,7 @@ CPLErr HFADataset::WriteProjection()
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,SRS_PT_MERCATOR_1SP) 
+    else if( EQUAL(pszProjName,SRS_PT_MERCATOR_1SP)
              && oSRS.GetProjParm(SRS_PP_SCALE_FACTOR) == 1.0 )
     {
         sPro.proNumber = EPRJ_MERCATOR;
@@ -3965,8 +3954,8 @@ CPLErr HFADataset::WriteProjection()
         sPro.proExeName = (char*) EPRJ_EXTERNAL_NZMG;
         sPro.proName = (char*) "New Zealand Map Grid";
         sPro.proZone = 0;
-        sPro.proParams[0] = 0;  // false easting etc not stored in .img it seems 
-        sPro.proParams[1] = 0;  // always fixed by definition. 
+        sPro.proParams[0] = 0;  // false easting etc not stored in .img it seems
+        sPro.proParams[1] = 0;  // always fixed by definition.
         sPro.proParams[2] = 0;
         sPro.proParams[3] = 0;
         sPro.proParams[4] = 0;
@@ -3974,18 +3963,18 @@ CPLErr HFADataset::WriteProjection()
         sPro.proParams[6] = 0;
         sPro.proParams[7] = 0;
     }
-    // Anything we can't map, we store as an ESRI PE_STRING 
+    // Anything we can't map, we store as an ESRI PE_STRING
     else if( oSRS.IsProjected() || oSRS.IsGeographic() )
     {
         if(!bPEStringStored)
         {
-            char *pszPEString = NULL;
             oSRS.morphToESRI();
+            char *pszPEString = NULL;
             oSRS.exportToWkt( &pszPEString );
             // need to transform this into ESRI format.
             HFASetPEString( hHFA, pszPEString );
             CPLFree( pszPEString );
-            bPEStringStored = TRUE;
+            bPEStringStored = true;
         }
     }
     else
@@ -4030,11 +4019,11 @@ CPLErr HFADataset::WriteProjection()
     else if( bHaveSRS && oSRS.GetLinearUnits() != 1.0 )
     {
         double dfClosestDiff = 100.0;
-        int    iClosest=-1, iUnit;
+        int    iClosest=-1;
         char *pszUnitName = NULL;
         double dfActualSize = oSRS.GetLinearUnits( &pszUnitName );
 
-        for( iUnit = 0; apszUnitMap[iUnit] != NULL; iUnit += 2 )
+        for( int iUnit = 0; apszUnitMap[iUnit] != NULL; iUnit += 2 )
         {
             if( fabs(CPLAtof(apszUnitMap[iUnit+1]) - dfActualSize) < dfClosestDiff )
             {
@@ -4042,12 +4031,12 @@ CPLErr HFADataset::WriteProjection()
                 dfClosestDiff = fabs(CPLAtof(apszUnitMap[iUnit+1])-dfActualSize);
             }
         }
-        
+
         if( iClosest == -1 ||  fabs(dfClosestDiff/dfActualSize) > 0.0001 )
         {
-            CPLError( CE_Warning, CPLE_NotSupported, 
+            CPLError( CE_Warning, CPLE_NotSupported,
                       "Unable to identify Erdas units matching %s/%gm,\n"
-                      "output units will be wrong.", 
+                      "output units will be wrong.",
                       pszUnitName, dfActualSize );
         }
         else
@@ -4067,7 +4056,7 @@ CPLErr HFADataset::WriteProjection()
     }
     else
     {
-        HFASetGeoTransform( hHFA, 
+        HFASetGeoTransform( hHFA,
                             sMapInfo.proName, sMapInfo.units,
                             adfGeoTransform );
     }
@@ -4110,9 +4099,9 @@ int WritePeStringIfNeeded(OGRSpatialReference* poSRS, HFAHandle hHFA)
   if( pszDatum == NULL )
       pszDatum = "";
   if(strstr(pszGEOGCS, "GCS_"))
-    gcsNameOffset = strlen("GCS_");
+    gcsNameOffset = static_cast<int>(strlen("GCS_"));
   if(strstr(pszDatum, "D_"))
-    datumNameOffset = strlen("D_");
+    datumNameOffset = static_cast<int>(strlen("D_"));
 
   if(!EQUAL(pszGEOGCS+gcsNameOffset, pszDatum+datumNameOffset))
     ret = TRUE;
@@ -4228,9 +4217,9 @@ void ClearSR(HFAHandle hHFA)
             }
             poMIEntry->FlushToDisk();
             char* peStr = HFAGetPEString( hHFA );
-            if( peStr != NULL && strlen(peStr) > 0 )           
+            if( peStr != NULL && strlen(peStr) > 0 )
                 HFASetPEString( hHFA, "" );
-        }  
+        }
     }
     return;
 }
@@ -4245,13 +4234,13 @@ void ClearSR(HFAHandle hHFA)
 static int ESRIToUSGSZone( int nESRIZone )
 
 {
-    int		nPairs = sizeof(anUsgsEsriZones) / (2*sizeof(int));
-    int		i;
-
+    if( nESRIZone == INT_MIN )
+        return 0;
     if( nESRIZone < 0 )
         return ABS(nESRIZone);
 
-    for( i = 0; i < nPairs; i++ )
+    const int nPairs = sizeof(anUsgsEsriZones) / (2*sizeof(int));
+    for( int i = 0; i < nPairs; i++ )
     {
         if( anUsgsEsriZones[i*2+1] == nESRIZone )
             return anUsgsEsriZones[i*2];
@@ -4336,24 +4325,24 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
         const char  *pszUnits = NULL;
 
         if( psMapInfo )
-            pszUnits = psMapInfo->units; 
+            pszUnits = psMapInfo->units;
         else if( poMapInformation != NULL )
             pszUnits = poMapInformation->GetStringField( "units.string" );
-        
+
         if( pszUnits != NULL )
         {
-            for( iUnitIndex = 0; 
-                 apszUnitMap[iUnitIndex] != NULL; 
+            for( iUnitIndex = 0;
+                 apszUnitMap[iUnitIndex] != NULL;
                  iUnitIndex += 2 )
             {
                 if( EQUAL(apszUnitMap[iUnitIndex], pszUnits ) )
                     break;
             }
-            
+
             if( apszUnitMap[iUnitIndex] == NULL )
                 iUnitIndex = 0;
-            
-            oSRS.SetLinearUnits( pszUnits, 
+
+            oSRS.SetLinearUnits( pszUnits,
                                  CPLAtof(apszUnitMap[iUnitIndex+1]) );
         }
         else
@@ -4385,12 +4374,10 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
 
     if( psDatum != NULL )
     {
-        int	i;
-
         pszDatumName = psDatum->datumname;
 
         /* Imagine to WKT translation */
-        for( i = 0; pszDatumName != NULL && apszDatumMap[i] != NULL; i += 2 )
+        for( int i = 0; pszDatumName != NULL && apszDatumMap[i] != NULL; i += 2 )
         {
             if( EQUAL(pszDatumName,apszDatumMap[i]) )
             {
@@ -4421,12 +4408,12 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
         oSRS.SetProjCS( "unnamed" );
         oSRS.SetUTM( psPro->proZone, psPro->proParams[3] >= 0.0 );
 
-        // The PCS name from the above function may be different with the input name. 
-        // If there is a PCS name in psMapInfo that is different with 
-        // the one in psPro, just use it as the PCS name. This case happens 
-        // if the dataset's SR was written by the new GDAL. 
-        if( psMapInfo && strlen(psMapInfo->proName) > 0 
-            && strlen(psPro->proName) > 0 
+        // The PCS name from the above function may be different with the input name.
+        // If there is a PCS name in psMapInfo that is different with
+        // the one in psPro, just use it as the PCS name. This case happens
+        // if the dataset's SR was written by the new GDAL.
+        if( psMapInfo && strlen(psMapInfo->proName) > 0
+            && strlen(psPro->proName) > 0
             && !EQUAL(psMapInfo->proName, psPro->proName) )
             oSRS.SetProjCS( psMapInfo->proName );
         break;
@@ -4435,25 +4422,27 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
       {
           char *pszUnitsName = NULL;
           double dfLinearUnits = oSRS.GetLinearUnits( &pszUnitsName );
-          
+
           pszUnitsName = CPLStrdup( pszUnitsName );
 
-          /* Historically, hfa used esri state plane zone code. Try esri pe string first. */ 
+          /* Historically, hfa used esri state plane zone code. Try esri pe string first. */
           int zoneCode = ESRIToUSGSZone(psPro->proZone);
-          char nad[32];
-          strcpy(nad, "HARN");
+          const char* pszDatum;
           if(psDatum)
-              strcpy(nad, psDatum->datumname);
-          char units[32];
-          strcpy(units, "meters");
+              pszDatum = psDatum->datumname;
+          else
+              pszDatum = "HARN";
+          const char* pszUnits;
           if(psMapInfo)
-              strcpy(units, psMapInfo->units);
+              pszUnits = psMapInfo->units;
           else if(pszUnitsName && strlen(pszUnitsName) > 0)
-              strcpy(units, pszUnitsName);
+              pszUnits = pszUnitsName;
+          else
+              pszUnits = "meters";
           int proNu = 0;
           if(psPro)
               proNu = psPro->proNumber;
-          if(oSRS.ImportFromESRIStatePlaneWKT(zoneCode, nad, units, proNu) == OGRERR_NONE)
+          if(oSRS.ImportFromESRIStatePlaneWKT(zoneCode, pszDatum, pszUnits, proNu) == OGRERR_NONE)
           {
               CPLFree( pszUnitsName );
               oSRS.morphFromESRI();
@@ -4466,15 +4455,15 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
           }
 
           /* Set state plane zone.  Set NAD83/27 on basis of spheroid */
-          oSRS.SetStatePlane( ESRIToUSGSZone(psPro->proZone), 
+          oSRS.SetStatePlane( ESRIToUSGSZone(psPro->proZone),
                               fabs(psPro->proSpheroid.a - 6378137.0)< 1.0,
                               pszUnitsName, dfLinearUnits );
 
           CPLFree( pszUnitsName );
 
           // Same as the UTM, The following is needed.
-          if( psMapInfo && strlen(psMapInfo->proName) > 0 
-              && strlen(psPro->proName) > 0 
+          if( psMapInfo && strlen(psMapInfo->proName) > 0
+              && strlen(psPro->proName) > 0
               && !EQUAL(psMapInfo->proName, psPro->proName) )
               oSRS.SetProjCS( psMapInfo->proName );
       }
@@ -4585,9 +4574,9 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
 
       case EPRJ_PLATE_CARREE:
       case EPRJ_EQUIRECTANGULAR:
-        oSRS.SetEquirectangular2( 0.0, 
+        oSRS.SetEquirectangular2( 0.0,
                                   psPro->proParams[4]*R2D,
-                                  psPro->proParams[5]*R2D, 
+                                  psPro->proParams[5]*R2D,
                                   psPro->proParams[6], psPro->proParams[7] );
         break;
 
@@ -4695,9 +4684,9 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
       case EPRJ_LOXIMUTHAL:
       {
           oSRS.SetProjection( "Loximuthal" );
-          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
+          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
                            psPro->proParams[4] * R2D );
-          oSRS.SetNormProjParm( "central_parallel", 
+          oSRS.SetNormProjParm( "central_parallel",
                            psPro->proParams[5] * R2D );
           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
           oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
@@ -4707,7 +4696,7 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
       case EPRJ_QUARTIC_AUTHALIC:
       {
           oSRS.SetProjection( "Quartic_Authalic" );
-          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
+          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
                            psPro->proParams[4] * R2D );
           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
           oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
@@ -4717,9 +4706,9 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
       case EPRJ_WINKEL_I:
       {
           oSRS.SetProjection( "Winkel_I" );
-          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
+          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
                            psPro->proParams[4] * R2D );
-          oSRS.SetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 
+          oSRS.SetNormProjParm( SRS_PP_STANDARD_PARALLEL_1,
                            psPro->proParams[2] * R2D );
           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
           oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
@@ -4729,9 +4718,9 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
       case EPRJ_WINKEL_II:
       {
           oSRS.SetProjection( "Winkel_II" );
-          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
+          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
                            psPro->proParams[4] * R2D );
-          oSRS.SetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 
+          oSRS.SetNormProjParm( SRS_PP_STANDARD_PARALLEL_1,
                            psPro->proParams[2] * R2D );
           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
           oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
@@ -4741,7 +4730,7 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
       case EPRJ_BEHRMANN:
       {
           oSRS.SetProjection( "Behrmann" );
-          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
+          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
                            psPro->proParams[4] * R2D );
           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
           oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
@@ -4758,9 +4747,9 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
       case EPRJ_DOUBLE_STEREOGRAPHIC:
       {
           oSRS.SetProjection( "Double_Stereographic" );
-          oSRS.SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 
+          oSRS.SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN,
                            psPro->proParams[5] * R2D );
-          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
+          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
                            psPro->proParams[4] * R2D );
           oSRS.SetNormProjParm( SRS_PP_SCALE_FACTOR, psPro->proParams[2] );
           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
@@ -4771,7 +4760,7 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
       case EPRJ_AITOFF:
       {
           oSRS.SetProjection( "Aitoff" );
-          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
+          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
                            psPro->proParams[4] * R2D );
           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
           oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
@@ -4781,7 +4770,7 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
       case EPRJ_CRASTER_PARABOLIC:
       {
           oSRS.SetProjection( "Craster_Parabolic" );
-          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
+          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
                            psPro->proParams[4] * R2D );
           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
           oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
@@ -4789,14 +4778,14 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
       break;
 
       case EPRJ_CYLINDRICAL_EQUAL_AREA:
-          oSRS.SetCEA(psPro->proParams[2] * R2D, psPro->proParams[4] * R2D, 
+          oSRS.SetCEA(psPro->proParams[2] * R2D, psPro->proParams[4] * R2D,
                       psPro->proParams[6], psPro->proParams[7]);
       break;
 
       case EPRJ_FLAT_POLAR_QUARTIC:
       {
           oSRS.SetProjection( "Flat_Polar_Quartic" );
-          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
+          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
                            psPro->proParams[4] * R2D );
           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
           oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
@@ -4806,7 +4795,7 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
       case EPRJ_TIMES:
       {
           oSRS.SetProjection( "Times" );
-          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
+          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
                            psPro->proParams[4] * R2D );
           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
           oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
@@ -4818,7 +4807,7 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
           oSRS.SetProjection( "Winkel_Tripel" );
           oSRS.SetNormProjParm( SRS_PP_STANDARD_PARALLEL_1,
                            psPro->proParams[2] * R2D );
-          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
+          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
                            psPro->proParams[4] * R2D );
           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
           oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
@@ -4828,7 +4817,7 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
       case EPRJ_HAMMER_AITOFF:
       {
           oSRS.SetProjection( "Hammer_Aitoff" );
-          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
+          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
                            psPro->proParams[4] * R2D );
           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
           oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
@@ -4870,7 +4859,7 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
       break;
 
       case EPRJ_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN:
-        oSRS.SetHOM2PNO( psPro->proParams[5] * R2D, 
+        oSRS.SetHOM2PNO( psPro->proParams[5] * R2D,
                          psPro->proParams[8] * R2D,
                          psPro->proParams[9] * R2D,
                          psPro->proParams[10] * R2D,
@@ -4914,10 +4903,10 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
         if( pszDatumName == NULL)
             oSRS.SetGeogCS( pszDatumName, pszDatumName, pszEllipsoidName,
                             psPro->proSpheroid.a, dfInvFlattening );
-        else if( EQUAL(pszDatumName,"WGS 84") 
+        else if( EQUAL(pszDatumName,"WGS 84")
             ||  EQUAL(pszDatumName,"WGS_1984") )
             oSRS.SetWellKnownGeogCS( "WGS84" );
-        else if( strstr(pszDatumName,"NAD27") != NULL 
+        else if( strstr(pszDatumName,"NAD27") != NULL
                  || EQUAL(pszDatumName,"North_American_Datum_1927") )
             oSRS.SetWellKnownGeogCS( "NAD27" );
         else if( strstr(pszDatumName,"NAD83") != NULL
@@ -4951,10 +4940,8 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
 /* -------------------------------------------------------------------- */
     if( oSRS.exportToWkt( &pszNewProj ) == OGRERR_NONE )
         return pszNewProj;
-    else
-    {
-        return NULL;
-    }
+
+    return NULL;
 }
 
 /************************************************************************/
@@ -4964,9 +4951,6 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
 CPLErr HFADataset::ReadProjection()
 
 {
-    const Eprj_Datum	      *psDatum;
-    const Eprj_ProParameters  *psPro;
-    const Eprj_MapInfo        *psMapInfo;
     OGRSpatialReference        oSRS;
     char *pszPE_COORDSYS = NULL;
     int bTryReadingPEString = TRUE;
@@ -4977,12 +4961,12 @@ CPLErr HFADataset::ReadProjection()
 /*      We make a particular effort to adapt the mapinfo->proname as    */
 /*      the PROJCS[] name per #2422.                                    */
 /* -------------------------------------------------------------------- */
-    psDatum = HFAGetDatum( hHFA );
-    psPro = HFAGetProParameters( hHFA );
-    psMapInfo = HFAGetMapInfo( hHFA );
+    const Eprj_Datum *psDatum = HFAGetDatum( hHFA );
+    const Eprj_ProParameters *psPro = HFAGetProParameters( hHFA );
+    const Eprj_MapInfo *psMapInfo = HFAGetMapInfo( hHFA );
 
     HFAEntry *poMapInformation = NULL;
-    if( psMapInfo == NULL ) 
+    if( psMapInfo == NULL )
     {
         HFABand *poBand = hHFA->papoBand[0];
         poMapInformation = poBand->poNode->GetNamedChild("MapInformation");
@@ -5000,15 +4984,15 @@ CPLErr HFADataset::ReadProjection()
         return CE_None;
     }
 
-    pszProjection = HFAPCSStructToWKT( psDatum, psPro, psMapInfo, 
+    pszProjection = HFAPCSStructToWKT( psDatum, psPro, psMapInfo,
                                        poMapInformation );
 
     // If we got a valid projection and managed to identify a EPSG code,
     // then do not use the ESRI PE String.
     if( pszProjection != NULL )
     {
-        OGRSpatialReference oSRS(pszProjection);
-        if( oSRS.GetAuthorityCode(NULL) != NULL )
+        OGRSpatialReference oSRS2(pszProjection);
+        if( oSRS2.GetAuthorityCode(NULL) != NULL )
             bTryReadingPEString = FALSE;
     }
 
@@ -5018,21 +5002,40 @@ CPLErr HFADataset::ReadProjection()
     if( bTryReadingPEString )
         pszPE_COORDSYS = HFAGetPEString( hHFA );
     if( pszPE_COORDSYS != NULL
-        && strlen(pszPE_COORDSYS) > 0 
+        && strlen(pszPE_COORDSYS) > 0
         && oSRS.SetFromUserInput( pszPE_COORDSYS ) == OGRERR_NONE )
     {
         CPLFree( pszPE_COORDSYS );
 
         oSRS.morphFromESRI();
+
+        // Copy TOWGS84 clause from HFA SRS to PE SRS
+        if( pszProjection != NULL )
+        {
+            OGRSpatialReference oSRS_HFA(pszProjection);
+            double adfCoeffs[7];
+            if( oSRS_HFA.GetTOWGS84(adfCoeffs, 7) == OGRERR_NONE &&
+                oSRS.GetAttrNode("TOWGS84") == NULL )
+            {
+                oSRS.SetTOWGS84(adfCoeffs[0],
+                                adfCoeffs[1],
+                                adfCoeffs[2],
+                                adfCoeffs[3],
+                                adfCoeffs[4],
+                                adfCoeffs[5],
+                                adfCoeffs[6]);
+            }
+        }
+
         oSRS.Fixup();
 
         CPLFree( pszProjection );
         pszProjection = NULL;
         oSRS.exportToWkt( &pszProjection );
-        
+
         return CE_None;
     }
-    
+
     CPLFree( pszPE_COORDSYS );
 
     if( pszProjection != NULL )
@@ -5040,7 +5043,7 @@ CPLErr HFADataset::ReadProjection()
     else
     {
         pszProjection = CPLStrdup("");
-        return CE_Failure;					
+        return CE_Failure;
     }
 }
 
@@ -5048,18 +5051,16 @@ CPLErr HFADataset::ReadProjection()
 /*                          IBuildOverviews()                           */
 /************************************************************************/
 
-CPLErr HFADataset::IBuildOverviews( const char *pszResampling, 
-                                    int nOverviews, int *panOverviewList, 
+CPLErr HFADataset::IBuildOverviews( const char *pszResampling,
+                                    int nOverviews, int *panOverviewList,
                                     int nListBands, int *panBandList,
-                                    GDALProgressFunc pfnProgress, 
+                                    GDALProgressFunc pfnProgress,
                                     void * pProgressData )
-    
-{
-    int i;
 
+{
     if( GetAccess() == GA_ReadOnly )
     {
-        for( i = 0; i < nListBands; i++ )
+        for( int i = 0; i < nListBands; i++ )
         {
             if (HFAGetOverviewCount(hHFA, panBandList[i]) > 0)
             {
@@ -5069,33 +5070,31 @@ CPLErr HFADataset::IBuildOverviews( const char *pszResampling,
             }
         }
 
-        return GDALDataset::IBuildOverviews( pszResampling, 
-                                             nOverviews, panOverviewList, 
-                                             nListBands, panBandList, 
+        return GDALDataset::IBuildOverviews( pszResampling,
+                                             nOverviews, panOverviewList,
+                                             nListBands, panBandList,
                                              pfnProgress, pProgressData );
     }
 
-    for( i = 0; i < nListBands; i++ )
+    for( int i = 0; i < nListBands; i++ )
     {
-        CPLErr eErr;
-        GDALRasterBand *poBand;
-
         void* pScaledProgressData = GDALCreateScaledProgress(
                 i * 1.0 / nListBands, (i + 1) * 1.0 / nListBands,
                 pfnProgress, pProgressData);
 
-        poBand = GetRasterBand( panBandList[i] );
-        
+        GDALRasterBand *poBand = GetRasterBand( panBandList[i] );
+
         //GetRasterBand can return NULL
         if(poBand == NULL)
         {
             CPLError(CE_Failure, CPLE_ObjectNull,
-                        "GetRasterBand failed");        
-            return CE_Failure; 
+                        "GetRasterBand failed");
+            GDALDestroyScaledProgress(pScaledProgressData);
+            return CE_Failure;
         }
-        
-        eErr = 
-            poBand->BuildOverviews( pszResampling, nOverviews, panOverviewList,
+
+        CPLErr eErr
+            = poBand->BuildOverviews( pszResampling, nOverviews, panOverviewList,
                                     GDALScaledProgress, pScaledProgressData );
 
         GDALDestroyScaledProgress(pScaledProgressData);
@@ -5118,10 +5117,10 @@ int HFADataset::Identify( GDALOpenInfo * poOpenInfo )
 /*      Verify that this is a HFA file.                                 */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->nHeaderBytes < 15
-        || !EQUALN((char *) poOpenInfo->pabyHeader,"EHFA_HEADER_TAG",15) )
+        || !STARTS_WITH_CI((char *) poOpenInfo->pabyHeader, "EHFA_HEADER_TAG") )
         return FALSE;
-    else
-        return TRUE;
+
+    return TRUE;
 }
 
 /************************************************************************/
@@ -5131,9 +5130,6 @@ int HFADataset::Identify( GDALOpenInfo * poOpenInfo )
 GDALDataset *HFADataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    HFAHandle	hHFA;
-    int		i;
-
 /* -------------------------------------------------------------------- */
 /*      Verify that this is a HFA file.                                 */
 /* -------------------------------------------------------------------- */
@@ -5143,6 +5139,8 @@ GDALDataset *HFADataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Open the file.                                                  */
 /* -------------------------------------------------------------------- */
+    HFAHandle	hHFA;
+
     if( poOpenInfo->eAccess == GA_Update )
         hHFA = HFAOpen( poOpenInfo->pszFilename, "r+" );
     else
@@ -5154,9 +5152,7 @@ GDALDataset *HFADataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    HFADataset 	*poDS;
-
-    poDS = new HFADataset();
+    HFADataset 	*poDS = new HFADataset();
 
     poDS->hHFA = hHFA;
     poDS->eAccess = poOpenInfo->eAccess;
@@ -5170,7 +5166,7 @@ GDALDataset *HFADataset::Open( GDALOpenInfo * poOpenInfo )
     if( poDS->nBands == 0 )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to open %s, it has zero usable bands.",
                   poOpenInfo->pszFilename );
         return NULL;
@@ -5179,7 +5175,7 @@ GDALDataset *HFADataset::Open( GDALOpenInfo * poOpenInfo )
     if( poDS->nRasterXSize == 0 || poDS->nRasterYSize == 0 )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to open %s, it has no pixels.",
                   poOpenInfo->pszFilename );
         return NULL;
@@ -5193,14 +5189,14 @@ GDALDataset *HFADataset::Open( GDALOpenInfo * poOpenInfo )
     {
         Efga_Polynomial *pasPolyListForward = NULL;
         Efga_Polynomial *pasPolyListReverse = NULL;
-        int nStepCount = 
-            HFAReadXFormStack( hHFA, &pasPolyListForward, 
+        int nStepCount =
+            HFAReadXFormStack( hHFA, &pasPolyListForward,
                                &pasPolyListReverse );
 
         if( nStepCount > 0 )
         {
-            poDS->UseXFormStack( nStepCount, 
-                                 pasPolyListForward, 
+            poDS->UseXFormStack( nStepCount,
+                                 pasPolyListForward,
                                  pasPolyListReverse );
             CPLFree( pasPolyListForward );
             CPLFree( pasPolyListReverse );
@@ -5226,18 +5222,18 @@ GDALDataset *HFADataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < poDS->nBands; i++ )
+    for( int i = 0; i < poDS->nBands; i++ )
     {
         poDS->SetBand( i+1, new HFARasterBand( poDS, i+1, -1 ) );
     }
 
 /* -------------------------------------------------------------------- */
-/*      Collect GDAL custom Metadata, and "auxilary" metadata from      */
+/*      Collect GDAL custom Metadata, and "auxiliary" metadata from     */
 /*      well known HFA structures for the bands.  We defer this till    */
 /*      now to ensure that the bands are properly setup before          */
 /*      interacting with PAM.                                           */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < poDS->nBands; i++ )
+    for( int i = 0; i < poDS->nBands; i++ )
     {
         HFARasterBand *poBand = (HFARasterBand *) poDS->GetRasterBand( i+1 );
 
@@ -5247,7 +5243,7 @@ GDALDataset *HFADataset::Open( GDALOpenInfo * poOpenInfo )
             poBand->SetMetadata( papszMD );
             CSLDestroy( papszMD );
         }
-        
+
         poBand->ReadAuxMetadata();
         poBand->ReadHistogramMetadata();
     }
@@ -5269,7 +5265,7 @@ GDALDataset *HFADataset::Open( GDALOpenInfo * poOpenInfo )
     HFAEntry  *poEntry = psInfo->poRoot->GetNamedChild("DependentFile");
     if( poEntry != NULL )
     {
-        poDS->SetMetadataItem( "HFA_DEPENDENT_FILE", 
+        poDS->SetMetadataItem( "HFA_DEPENDENT_FILE",
                                poEntry->GetStringField( "dependent.string" ),
                                "HFA" );
     }
@@ -5284,11 +5280,11 @@ GDALDataset *HFADataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Check for external overviews.                                   */
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Clear dirty metadata flags.                                     */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < poDS->nBands; i++ )
+    for( int i = 0; i < poDS->nBands; i++ )
     {
         HFARasterBand *poBand = (HFARasterBand *) poDS->GetRasterBand( i+1 );
         poBand->bMetadataDirty = FALSE;
@@ -5364,8 +5360,8 @@ CPLErr HFADataset::GetGeoTransform( double * padfTransform )
         memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
         return CE_None;
     }
-    else
-        return GDALPamDataset::GetGeoTransform( padfTransform );
+
+    return GDALPamDataset::GetGeoTransform( padfTransform );
 }
 
 /************************************************************************/
@@ -5391,27 +5387,26 @@ CPLErr HFADataset::SetGeoTransform( double * padfTransform )
 /*      seeks.                                                          */
 /************************************************************************/
 
-CPLErr HFADataset::IRasterIO( GDALRWFlag eRWFlag, 
+CPLErr HFADataset::IRasterIO( GDALRWFlag eRWFlag,
                               int nXOff, int nYOff, int nXSize, int nYSize,
-                              void *pData, int nBufXSize, int nBufYSize, 
+                              void *pData, int nBufXSize, int nBufYSize,
                               GDALDataType eBufType,
-                              int nBandCount, int *panBandMap, 
+                              int nBandCount, int *panBandMap,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
                               GSpacing nBandSpace,
                               GDALRasterIOExtraArg* psExtraArg )
 
 {
-    if( hHFA->papoBand[panBandMap[0]-1]->fpExternal != NULL 
+    if( hHFA->papoBand[panBandMap[0]-1]->fpExternal != NULL
         && nBandCount > 1 )
-        return GDALDataset::BlockBasedRasterIO( 
+        return GDALDataset::BlockBasedRasterIO(
             eRWFlag, nXOff, nYOff, nXSize, nYSize,
-            pData, nBufXSize, nBufYSize, eBufType, 
+            pData, nBufXSize, nBufYSize, eBufType,
             nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace, psExtraArg );
-    else
-        return 
-            GDALDataset::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                                    pData, nBufXSize, nBufYSize, eBufType, 
-                                    nBandCount, panBandMap, 
+
+    return GDALDataset::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                                    pData, nBufXSize, nBufYSize, eBufType,
+                                    nBandCount, panBandMap,
                                     nPixelSpace, nLineSpace, nBandSpace, psExtraArg );
 }
 
@@ -5427,14 +5422,12 @@ void HFADataset::UseXFormStack( int nStepCount,
 /* -------------------------------------------------------------------- */
 /*      Generate GCPs using the transform.                              */
 /* -------------------------------------------------------------------- */
-    double dfXRatio, dfYRatio;
-
     nGCPCount = 0;
     GDALInitGCPs( 36, asGCPList );
 
-    for( dfYRatio = 0.0; dfYRatio < 1.001; dfYRatio += 0.2 )
+    for( double dfYRatio = 0.0; dfYRatio < 1.001; dfYRatio += 0.2 )
     {
-        for( dfXRatio = 0.0; dfXRatio < 1.001; dfXRatio += 0.2 )
+        for( double dfXRatio = 0.0; dfXRatio < 1.001; dfXRatio += 0.2 )
         {
             double dfLine = 0.5 + (GetRasterYSize()-1) * dfYRatio;
             double dfPixel = 0.5 + (GetRasterXSize()-1) * dfXRatio;
@@ -5457,36 +5450,34 @@ void HFADataset::UseXFormStack( int nStepCount,
 /* -------------------------------------------------------------------- */
 /*      Store the transform as metadata.                                */
 /* -------------------------------------------------------------------- */
-    int iStep, i;
-
-    GDALMajorObject::SetMetadataItem( 
-        "XFORM_STEPS", 
+    GDALMajorObject::SetMetadataItem(
+        "XFORM_STEPS",
         CPLString().Printf("%d",nStepCount),
         "XFORMS" );
 
-    for( iStep = 0; iStep < nStepCount; iStep++ )
+    for( int iStep = 0; iStep < nStepCount; iStep++ )
     {
-        GDALMajorObject::SetMetadataItem( 
+        GDALMajorObject::SetMetadataItem(
             CPLString().Printf("XFORM%d_ORDER", iStep),
             CPLString().Printf("%d",pasPLForward[iStep].order),
             "XFORMS" );
 
         if( pasPLForward[iStep].order == 1 )
         {
-            for( i = 0; i < 4; i++ )
-                GDALMajorObject::SetMetadataItem( 
+            for( int i = 0; i < 4; i++ )
+                GDALMajorObject::SetMetadataItem(
                     CPLString().Printf("XFORM%d_POLYCOEFMTX[%d]", iStep, i),
                     CPLString().Printf("%.15g",
                                        pasPLForward[iStep].polycoefmtx[i]),
                     "XFORMS" );
-            
-            for( i = 0; i < 2; i++ )
-                GDALMajorObject::SetMetadataItem( 
+
+            for( int i = 0; i < 2; i++ )
+                GDALMajorObject::SetMetadataItem(
                     CPLString().Printf("XFORM%d_POLYCOEFVECTOR[%d]", iStep, i),
                     CPLString().Printf("%.15g",
                                        pasPLForward[iStep].polycoefvector[i]),
                     "XFORMS" );
-            
+
             continue;
         }
 
@@ -5500,29 +5491,29 @@ void HFADataset::UseXFormStack( int nStepCount,
             nCoefCount = 18;
         }
 
-        for( i = 0; i < nCoefCount; i++ )
-            GDALMajorObject::SetMetadataItem( 
+        for( int i = 0; i < nCoefCount; i++ )
+            GDALMajorObject::SetMetadataItem(
                 CPLString().Printf("XFORM%d_FWD_POLYCOEFMTX[%d]", iStep, i),
                 CPLString().Printf("%.15g",
                                    pasPLForward[iStep].polycoefmtx[i]),
                 "XFORMS" );
-            
-        for( i = 0; i < 2; i++ )
-            GDALMajorObject::SetMetadataItem( 
+
+        for( int i = 0; i < 2; i++ )
+            GDALMajorObject::SetMetadataItem(
                 CPLString().Printf("XFORM%d_FWD_POLYCOEFVECTOR[%d]", iStep, i),
                 CPLString().Printf("%.15g",
                                    pasPLForward[iStep].polycoefvector[i]),
                 "XFORMS" );
-            
-        for( i = 0; i < nCoefCount; i++ )
-            GDALMajorObject::SetMetadataItem( 
+
+        for( int i = 0; i < nCoefCount; i++ )
+            GDALMajorObject::SetMetadataItem(
                 CPLString().Printf("XFORM%d_REV_POLYCOEFMTX[%d]", iStep, i),
                 CPLString().Printf("%.15g",
                                    pasPLReverse[iStep].polycoefmtx[i]),
                 "XFORMS" );
-            
-        for( i = 0; i < 2; i++ )
-            GDALMajorObject::SetMetadataItem( 
+
+        for( int i = 0; i < 2; i++ )
+            GDALMajorObject::SetMetadataItem(
                 CPLString().Printf("XFORM%d_REV_POLYCOEFVECTOR[%d]", iStep, i),
                 CPLString().Printf("%.15g",
                                    pasPLReverse[iStep].polycoefvector[i]),
@@ -5549,8 +5540,8 @@ const char *HFADataset::GetGCPProjection()
 {
     if( nGCPCount > 0 )
         return pszProjection;
-    else
-        return "";
+
+    return "";
 }
 
 /************************************************************************/
@@ -5574,13 +5565,13 @@ char **HFADataset::GetFileList()
 
     if( HFAGetIGEFilename( hHFA ) != NULL )
     {
-        papszFileList = CSLAddString( papszFileList, 
+        papszFileList = CSLAddString( papszFileList,
                                       HFAGetIGEFilename( hHFA ) );
     }
 
     // Request an overview to force opening of dependent overview
-    // files. 
-    if( nBands > 0 
+    // files.
+    if( nBands > 0
         && GetRasterBand(1)->GetOverviewCount() > 0 )
         GetRasterBand(1)->GetOverview(0);
 
@@ -5588,16 +5579,16 @@ char **HFADataset::GetFileList()
     {
         HFAInfo_t *psDep = hHFA->psDependent;
 
-        papszFileList = 
-            CSLAddString( papszFileList, 
-                          CPLFormFilename( psDep->pszPath, 
+        papszFileList =
+            CSLAddString( papszFileList,
+                          CPLFormFilename( psDep->pszPath,
                                            psDep->pszFilename, NULL ));
-        
+
         if( HFAGetIGEFilename( psDep ) != NULL )
-            papszFileList = CSLAddString( papszFileList, 
+            papszFileList = CSLAddString( papszFileList,
                                           HFAGetIGEFilename( psDep ) );
     }
-    
+
     return papszFileList;
 }
 
@@ -5611,67 +5602,65 @@ GDALDataset *HFADataset::Create( const char * pszFilenameIn,
                                  char ** papszParmList )
 
 {
-    int		nHfaDataType;
     int         nBits = 0;
-    const char *pszPixelType;
-
 
     if( CSLFetchNameValue( papszParmList, "NBITS" ) != NULL )
         nBits = atoi(CSLFetchNameValue(papszParmList,"NBITS"));
 
-    pszPixelType = 
-        CSLFetchNameValue( papszParmList, "PIXELTYPE" );
+    const char *pszPixelType
+        = CSLFetchNameValue( papszParmList, "PIXELTYPE" );
     if( pszPixelType == NULL )
         pszPixelType = "";
 
 /* -------------------------------------------------------------------- */
 /*      Translate the data type.                                        */
 /* -------------------------------------------------------------------- */
+    EPTType	eHfaDataType;
     switch( eType )
     {
       case GDT_Byte:
         if( nBits == 1 )
-            nHfaDataType = EPT_u1;
+            eHfaDataType = EPT_u1;
         else if( nBits == 2 )
-            nHfaDataType = EPT_u2;
+            eHfaDataType = EPT_u2;
         else if( nBits == 4 )
-            nHfaDataType = EPT_u4;
+            eHfaDataType = EPT_u4;
         else if( EQUAL(pszPixelType,"SIGNEDBYTE") )
-            nHfaDataType = EPT_s8;
+            eHfaDataType = EPT_s8;
         else
-            nHfaDataType = EPT_u8;
+            eHfaDataType = EPT_u8;
         break;
 
       case GDT_UInt16:
-        nHfaDataType = EPT_u16;
+        eHfaDataType = EPT_u16;
         break;
 
       case GDT_Int16:
-        nHfaDataType = EPT_s16;
+        eHfaDataType = EPT_s16;
         break;
 
       case GDT_Int32:
-        nHfaDataType = EPT_s32;
+        eHfaDataType = EPT_s32;
         break;
 
       case GDT_UInt32:
-        nHfaDataType = EPT_u32;
+        eHfaDataType = EPT_u32;
         break;
 
       case GDT_Float32:
-        nHfaDataType = EPT_f32;
+        eHfaDataType = EPT_f32;
         break;
 
       case GDT_Float64:
-        nHfaDataType = EPT_f64;
+        eHfaDataType = EPT_f64;
         break;
 
       case GDT_CFloat32:
-        nHfaDataType = EPT_c64;
+        eHfaDataType = EPT_c64;
         break;
 
       case GDT_CFloat64:
-        nHfaDataType = EPT_c128;
+        eHfaDataType = EPT_c128;
         break;
 
       default:
@@ -5679,20 +5668,21 @@ GDALDataset *HFADataset::Create( const char * pszFilenameIn,
                  "Data type %s not supported by Erdas Imagine (HFA) format.\n",
                   GDALGetDataTypeName( eType ) );
         return NULL;
-
     }
 
 /* -------------------------------------------------------------------- */
 /*      Create the new file.                                            */
 /* -------------------------------------------------------------------- */
-    HFAHandle hHFA;
-
-    hHFA = HFACreate( pszFilenameIn, nXSize, nYSize, nBands,
-                      nHfaDataType, papszParmList );
+    HFAHandle hHFA = HFACreate( pszFilenameIn, nXSize, nYSize, nBands,
+                                eHfaDataType, papszParmList );
     if( hHFA == NULL )
         return NULL;
 
-    HFAClose( hHFA );
+    if( HFAClose( hHFA ) != 0 )
+    {
+        CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        return NULL;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Open the dataset normally.                                      */
@@ -5711,13 +5701,13 @@ GDALDataset *HFADataset::Create( const char * pszFilenameIn,
     }
 
 /* -------------------------------------------------------------------- */
-/*      Sometimes we can improve ArcGIS compatability by forcing        */
+/*      Sometimes we can improve ArcGIS compatibility by forcing        */
 /*      generation of a PEString instead of traditional Imagine         */
 /*      coordinate system descriptions.                                 */
 /* -------------------------------------------------------------------- */
     if( poDS != NULL )
     {
-        poDS->bForceToPEString = 
+        poDS->bForceToPEString =
             CSLFetchBoolean( papszParmList, "FORCETOPESTRING", FALSE );
     }
 
@@ -5741,7 +5731,6 @@ CPLErr HFADataset::Rename( const char *pszNewName, const char *pszOldName )
     GDALDriver *poDriver = (GDALDriver*) GDALGetDriverByName( "HFA" );
 
     CPLErr eErr = poDriver->DefaultRename( pszNewName, pszOldName );
-    
     if( eErr != CE_None )
         return eErr;
 
@@ -5749,10 +5738,8 @@ CPLErr HFADataset::Rename( const char *pszNewName, const char *pszOldName )
 /*      Now try to go into the .img file and update RRDNames[]          */
 /*      lists.                                                          */
 /* -------------------------------------------------------------------- */
-    CPLString osOldBasename, osNewBasename;
-
-    osOldBasename = CPLGetBasename( pszOldName );
-    osNewBasename = CPLGetBasename( pszNewName );
+    CPLString osOldBasename = CPLGetBasename( pszOldName );
+    CPLString osNewBasename = CPLGetBasename( pszNewName );
 
     if( osOldBasename != osNewBasename )
     {
@@ -5765,10 +5752,11 @@ CPLErr HFADataset::Rename( const char *pszNewName, const char *pszOldName )
             HFAGetOverviewCount( hHFA, 1 );
 
             if( hHFA->psDependent != NULL )
-                HFARenameReferences( hHFA->psDependent, 
+                HFARenameReferences( hHFA->psDependent,
                                      osNewBasename, osOldBasename );
 
-            HFAClose( hHFA );
+            if( HFAClose( hHFA ) != 0 )
+                eErr = CE_Failure;
         }
     }
 
@@ -5791,7 +5779,7 @@ CPLErr HFADataset::CopyFiles( const char *pszNewName, const char *pszOldName )
     GDALDriver *poDriver = (GDALDriver*) GDALGetDriverByName( "HFA" );
 
     CPLErr eErr = poDriver->DefaultCopyFiles( pszNewName, pszOldName );
-    
+
     if( eErr != CE_None )
         return eErr;
 
@@ -5799,10 +5787,8 @@ CPLErr HFADataset::CopyFiles( const char *pszNewName, const char *pszOldName )
 /*      Now try to go into the .img file and update RRDNames[]          */
 /*      lists.                                                          */
 /* -------------------------------------------------------------------- */
-    CPLString osOldBasename, osNewBasename;
-
-    osOldBasename = CPLGetBasename( pszOldName );
-    osNewBasename = CPLGetBasename( pszNewName );
+    CPLString osOldBasename = CPLGetBasename( pszOldName );
+    CPLString osNewBasename = CPLGetBasename( pszNewName );
 
     if( osOldBasename != osNewBasename )
     {
@@ -5815,10 +5801,11 @@ CPLErr HFADataset::CopyFiles( const char *pszNewName, const char *pszOldName )
             HFAGetOverviewCount( hHFA, 1 );
 
             if( hHFA->psDependent != NULL )
-                HFARenameReferences( hHFA->psDependent, 
+                HFARenameReferences( hHFA->psDependent,
                                      osNewBasename, osOldBasename );
 
-            HFAClose( hHFA );
+            if( HFAClose( hHFA ) != 0 )
+                eErr = CE_Failure;
         }
     }
 
@@ -5835,53 +5822,55 @@ HFADataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                         char ** papszOptions,
                         GDALProgressFunc pfnProgress, void * pProgressData )
 {
-    HFADataset	*poDS;
-    GDALDataType eType = GDT_Byte;
-    int          iBand;
-    int          nBandCount = poSrcDS->GetRasterCount();
-    char         **papszModOptions = CSLDuplicate( papszOptions );
-
 /* -------------------------------------------------------------------- */
 /*      Do we really just want to create an .aux file?                  */
 /* -------------------------------------------------------------------- */
-    int bCreateAux = CSLFetchBoolean( papszOptions, "AUX", FALSE );
+    bool bCreateAux = CPL_TO_BOOL(CSLFetchBoolean( papszOptions, "AUX", FALSE ));
 
 /* -------------------------------------------------------------------- */
 /*      Establish a representative data type to use.                    */
 /* -------------------------------------------------------------------- */
+    char **papszModOptions = CSLDuplicate( papszOptions );
     if( !pfnProgress( 0.0, NULL, pProgressData ) )
+    {
+        CSLDestroy(papszModOptions);
         return NULL;
+    }
 
-    for( iBand = 0; iBand < nBandCount; iBand++ )
+    const int nBandCount = poSrcDS->GetRasterCount();
+    GDALDataType eType = GDT_Byte;
+
+    for( int iBand = 0; iBand < nBandCount; iBand++ )
     {
         GDALRasterBand *poBand = poSrcDS->GetRasterBand( iBand+1 );
         eType = GDALDataTypeUnion( eType, poBand->GetRasterDataType() );
     }
 
 /* -------------------------------------------------------------------- */
-/*      If we have PIXELTYPE metadadata in the source, pass it          */
+/*      If we have PIXELTYPE metadata in the source, pass it            */
 /*      through as a creation option.                                   */
 /* -------------------------------------------------------------------- */
     if( CSLFetchNameValue( papszOptions, "PIXELTYPE" ) == NULL
-        && nBandCount > 0 
+        && nBandCount > 0
         && eType == GDT_Byte
-        && poSrcDS->GetRasterBand(1)->GetMetadataItem( "PIXELTYPE", 
+        && poSrcDS->GetRasterBand(1)->GetMetadataItem( "PIXELTYPE",
                                                        "IMAGE_STRUCTURE" ) )
     {
-        papszModOptions = 
-            CSLSetNameValue( papszModOptions, "PIXELTYPE", 
-                             poSrcDS->GetRasterBand(1)->GetMetadataItem( 
+        papszModOptions =
+            CSLSetNameValue( papszModOptions, "PIXELTYPE",
+                             poSrcDS->GetRasterBand(1)->GetMetadataItem(
                                  "PIXELTYPE", "IMAGE_STRUCTURE" ) );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Create the file.                                                */
 /* -------------------------------------------------------------------- */
-    poDS = (HFADataset *) Create( pszFilename,
-                                  poSrcDS->GetRasterXSize(),
-                                  poSrcDS->GetRasterYSize(),
-                                  nBandCount,
-                                  eType, papszModOptions );
+    HFADataset *poDS
+        = (HFADataset *) Create( pszFilename,
+                                 poSrcDS->GetRasterXSize(),
+                                 poSrcDS->GetRasterYSize(),
+                                 nBandCount,
+                                 eType, papszModOptions );
 
     CSLDestroy( papszModOptions );
 
@@ -5892,12 +5881,10 @@ HFADataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      Does the source have a PCT for any of the bands?  If so,        */
 /*      copy it over.                                                   */
 /* -------------------------------------------------------------------- */
-    for( iBand = 0; iBand < nBandCount; iBand++ )
+    for( int iBand = 0; iBand < nBandCount; iBand++ )
     {
         GDALRasterBand *poBand = poSrcDS->GetRasterBand( iBand+1 );
-        GDALColorTable *poCT;
-
-        poCT = poBand->GetColorTable();
+        GDALColorTable *poCT = poBand->GetColorTable();
         if( poCT != NULL )
         {
             poDS->GetRasterBand(iBand+1)->SetColorTable(poCT);
@@ -5911,9 +5898,8 @@ HFADataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     if( poSrcDS->GetMetadata() != NULL )
         poDS->SetMetadata( poSrcDS->GetMetadata() );
 
-    for( iBand = 0; iBand < nBandCount; iBand++ )
+    for( int iBand = 0; iBand < nBandCount; iBand++ )
     {
-        int bSuccess;
         GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand+1 );
         GDALRasterBand *poDstBand = poDS->GetRasterBand(iBand+1);
 
@@ -5923,6 +5909,7 @@ HFADataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         if( strlen(poSrcBand->GetDescription()) > 0 )
             poDstBand->SetDescription( poSrcBand->GetDescription() );
 
+        int bSuccess;
         double dfNoDataValue = poSrcBand->GetNoDataValue( &bSuccess );
         if( bSuccess )
             poDstBand->SetNoDataValue( dfNoDataValue );
@@ -5932,7 +5919,6 @@ HFADataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      Copy projection information.                                    */
 /* -------------------------------------------------------------------- */
     double	adfGeoTransform[6];
-    const char  *pszProj;
 
     if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None
         && (adfGeoTransform[0] != 0.0 || adfGeoTransform[1] != 1.0
@@ -5940,7 +5926,7 @@ HFADataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             || adfGeoTransform[4] != 0.0 || fabs(adfGeoTransform[5]) != 1.0))
         poDS->SetGeoTransform( adfGeoTransform );
 
-    pszProj = poSrcDS->GetProjectionRef();
+    const char *pszProj = poSrcDS->GetProjectionRef();
     if( pszProj != NULL && strlen(pszProj) > 0 )
         poDS->SetProjection( pszProj );
 
@@ -5949,12 +5935,11 @@ HFADataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
     if( !bCreateAux )
     {
-        CPLErr eErr;
+        CPLErr eErr
+            = GDALDatasetCopyWholeRaster( (GDALDatasetH) poSrcDS,
+                                          (GDALDatasetH) poDS,
+                                          NULL, pfnProgress, pProgressData );
 
-        eErr = GDALDatasetCopyWholeRaster( (GDALDatasetH) poSrcDS, 
-                                           (GDALDatasetH) poDS,
-                                           NULL, pfnProgress, pProgressData );
-        
         if( eErr != CE_None )
         {
             delete poDS;
@@ -5967,7 +5952,7 @@ HFADataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
     if( CSLFetchBoolean( papszOptions, "STATISTICS", FALSE ) )
     {
-        for( iBand = 0; iBand < nBandCount; iBand++ )
+        for( int iBand = 0; iBand < nBandCount; iBand++ )
         {
             GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand+1 );
             double dfMin, dfMax, dfMean, dfStdDev;
@@ -5977,26 +5962,26 @@ HFADataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             // Statistics
             // -----------------------------------------------------------
 
-            if( poSrcBand->GetStatistics( TRUE, FALSE, &dfMin, &dfMax, 
+            if( poSrcBand->GetStatistics( TRUE, FALSE, &dfMin, &dfMax,
                                           &dfMean, &dfStdDev ) == CE_None
-                || poSrcBand->ComputeStatistics( TRUE, &dfMin, &dfMax, 
-                                                 &dfMean, &dfStdDev, 
+                || poSrcBand->ComputeStatistics( TRUE, &dfMin, &dfMax,
+                                                 &dfMean, &dfStdDev,
                                                  pfnProgress, pProgressData )
                 == CE_None )
             {
                 CPLString osValue;
-                
-                papszStatsMD = 
-                    CSLSetNameValue( papszStatsMD, "STATISTICS_MINIMUM", 
+
+                papszStatsMD =
+                    CSLSetNameValue( papszStatsMD, "STATISTICS_MINIMUM",
                                      osValue.Printf( "%.15g", dfMin ) );
-                papszStatsMD = 
-                    CSLSetNameValue( papszStatsMD, "STATISTICS_MAXIMUM", 
+                papszStatsMD =
+                    CSLSetNameValue( papszStatsMD, "STATISTICS_MAXIMUM",
                                      osValue.Printf( "%.15g", dfMax ) );
-                papszStatsMD = 
-                    CSLSetNameValue( papszStatsMD, "STATISTICS_MEAN", 
+                papszStatsMD =
+                    CSLSetNameValue( papszStatsMD, "STATISTICS_MEAN",
                                      osValue.Printf( "%.15g", dfMean ) );
-                papszStatsMD = 
-                    CSLSetNameValue( papszStatsMD, "STATISTICS_STDDEV", 
+                papszStatsMD =
+                    CSLSetNameValue( papszStatsMD, "STATISTICS_STDDEV",
                                      osValue.Printf( "%.15g", dfStdDev ) );
             }
 
@@ -6007,36 +5992,36 @@ HFADataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             int nBuckets;
             GUIntBig *panHistogram = NULL;
 
-            if( poSrcBand->GetDefaultHistogram( &dfMin, &dfMax, 
-                                                &nBuckets, &panHistogram, 
-                                                TRUE, 
+            if( poSrcBand->GetDefaultHistogram( &dfMin, &dfMax,
+                                                &nBuckets, &panHistogram,
+                                                TRUE,
                                                 pfnProgress, pProgressData )
                 == CE_None )
             {
                 CPLString osValue;
-                char *pszBinValues = (char *) CPLCalloc(20,nBuckets+1);
-                int iBin, nBinValuesLen = 0;
                 double dfBinWidth = (dfMax - dfMin) / nBuckets;
-                
-                papszStatsMD = CSLSetNameValue( 
-                    papszStatsMD, "STATISTICS_HISTOMIN", 
+
+                papszStatsMD = CSLSetNameValue(
+                    papszStatsMD, "STATISTICS_HISTOMIN",
                     osValue.Printf( "%.15g", dfMin+dfBinWidth*0.5 ) );
-                papszStatsMD = CSLSetNameValue( 
-                    papszStatsMD, "STATISTICS_HISTOMAX", 
+                papszStatsMD = CSLSetNameValue(
+                    papszStatsMD, "STATISTICS_HISTOMAX",
                     osValue.Printf( "%.15g", dfMax-dfBinWidth*0.5 ) );
-                papszStatsMD = 
-                    CSLSetNameValue( papszStatsMD, "STATISTICS_HISTONUMBINS", 
+                papszStatsMD =
+                    CSLSetNameValue( papszStatsMD, "STATISTICS_HISTONUMBINS",
                                      osValue.Printf( "%d", nBuckets ) );
 
-                for( iBin = 0; iBin < nBuckets; iBin++ )
+                int nBinValuesLen = 0;
+                char *pszBinValues = (char *) CPLCalloc(20, nBuckets+1);
+                for( int iBin = 0; iBin < nBuckets; iBin++ )
                 {
-                    
-                    strcat( pszBinValues+nBinValuesLen, 
+
+                    strcat( pszBinValues+nBinValuesLen,
                             osValue.Printf( CPL_FRMT_GUIB, panHistogram[iBin]) );
                     strcat( pszBinValues+nBinValuesLen, "|" );
-                    nBinValuesLen += strlen(pszBinValues+nBinValuesLen);
+                    nBinValuesLen += static_cast<int>(strlen(pszBinValues+nBinValuesLen));
                 }
-                papszStatsMD = 
+                papszStatsMD =
                     CSLSetNameValue( papszStatsMD, "STATISTICS_HISTOBINVALUES",
                                      pszBinValues );
                 CPLFree( pszBinValues );
@@ -6078,23 +6063,21 @@ HFADataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 void GDALRegister_HFA()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "HFA" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "HFA" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "HFA" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Erdas Imagine Images (.img)" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "frmt_hfa.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "img" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
-                                   "Byte Int16 UInt16 Int32 UInt32 Float32 Float64 CFloat32 CFloat64" );
+    poDriver->SetDescription( "HFA" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Erdas Imagine Images (.img)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_hfa.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "img" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte Int16 UInt16 Int32 UInt32 Float32 Float64 CFloat32 CFloat64" );
 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "   <Option name='BLOCKSIZE' type='integer' description='tile width/height (32-2048)' default='64'/>"
 "   <Option name='USE_SPILL' type='boolean' description='Force use of spill file'/>"
@@ -6108,16 +6091,14 @@ void GDALRegister_HFA()
 "   <Option name='FORCETOPESTRING' type='boolean' description='Force use of ArcGIS PE String in file instead of Imagine coordinate system format'/>"
 "</CreationOptionList>" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = HFADataset::Open;
-        poDriver->pfnCreate = HFADataset::Create;
-        poDriver->pfnCreateCopy = HFADataset::CreateCopy;
-        poDriver->pfnIdentify = HFADataset::Identify;
-        poDriver->pfnRename = HFADataset::Rename;
-        poDriver->pfnCopyFiles = HFADataset::CopyFiles;
-        
+    poDriver->pfnOpen = HFADataset::Open;
+    poDriver->pfnCreate = HFADataset::Create;
+    poDriver->pfnCreateCopy = HFADataset::CreateCopy;
+    poDriver->pfnIdentify = HFADataset::Identify;
+    poDriver->pfnRename = HFADataset::Rename;
+    poDriver->pfnCopyFiles = HFADataset::CopyFiles;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/hfa/hfadictionary.cpp b/frmts/hfa/hfadictionary.cpp
index ed26cb9..cd67e10 100644
--- a/frmts/hfa/hfadictionary.cpp
+++ b/frmts/hfa/hfadictionary.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfadictionary.cpp 21184 2010-12-01 03:11:03Z warmerdam $
+ * $Id: hfadictionary.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Implementation of the HFADictionary class for managing the
@@ -32,35 +32,35 @@
 #include "hfa_p.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: hfadictionary.cpp 21184 2010-12-01 03:11:03Z warmerdam $");
+CPL_CVSID("$Id: hfadictionary.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
-static const char *apszDefDefn[] = {
+static const char * const apszDefDefn[] = {
 
     "Edsc_Table",
     "{1:lnumrows,}Edsc_Table",
 
-    "Edsc_Column", 
-    "{1:lnumRows,1:LcolumnDataPtr,1:e4:integer,real,complex,string,dataType,1:lmaxNumChars,}Edsc_Column", 
-    
+    "Edsc_Column",
+    "{1:lnumRows,1:LcolumnDataPtr,1:e4:integer,real,complex,string,dataType,1:lmaxNumChars,}Edsc_Column",
+
     "Eprj_Size",
     "{1:dwidth,1:dheight,}Eprj_Size",
 
     "Eprj_Coordinate",
     "{1:dx,1:dy,}Eprj_Coordinate",
 
-    "Eprj_MapInfo", 
+    "Eprj_MapInfo",
     "{0:pcproName,1:*oEprj_Coordinate,upperLeftCenter,1:*oEprj_Coordinate,lowerRightCenter,1:*oEprj_Size,pixelSize,0:pcunits,}Eprj_MapInfo",
-    
-    "Eimg_StatisticsParameters830", 
+
+    "Eimg_StatisticsParameters830",
     "{0:poEmif_String,LayerNames,1:*bExcludedValues,1:oEmif_String,AOIname,1:lSkipFactorX,1:lSkipFactorY,1:*oEdsc_BinFunction,BinFunction,}Eimg_StatisticsParameters830",
-    
-    "Esta_Statistics", 
+
+    "Esta_Statistics",
     "{1:dminimum,1:dmaximum,1:dmean,1:dmedian,1:dmode,1:dstddev,}Esta_Statistics",
 
-    "Edsc_BinFunction", 
+    "Edsc_BinFunction",
     "{1:lnumBins,1:e4:direct,linear,logarithmic,explicit,binFunctionType,1:dminLimit,1:dmaxLimit,1:*bbinLimits,}Edsc_BinFunction",
 
-    "Eimg_NonInitializedValue", 
+    "Eimg_NonInitializedValue",
     "{1:*bvalueBD,}Eimg_NonInitializedValue",
 
     "Eprj_MapProjection842",
@@ -71,7 +71,7 @@ static const char *apszDefDefn[] = {
 
     "Eprj_ProParameters",
     "{1:e2:EPRJ_INTERNAL,EPRJ_EXTERNAL,proType,1:lproNumber,0:pcproExeName,0:pcproName,1:lproZone,0:pdproParams,1:*oEprj_Spheroid,proSpheroid,}Eprj_ProParameters",
-    
+
     "Eprj_Datum",
     "{0:pcdatumname,1:e3:EPRJ_DATUM_PARAMETRIC,EPRJ_DATUM_GRID,EPRJ_DATUM_REGRESSION,type,0:pdparams,0:pcgridname,}Eprj_Datum",
 
@@ -80,8 +80,6 @@ static const char *apszDefDefn[] = {
 
     NULL,
     NULL };
-    
-    
 
 /************************************************************************/
 /* ==================================================================== */
@@ -94,26 +92,17 @@ static const char *apszDefDefn[] = {
 /*                           HFADictionary()                            */
 /************************************************************************/
 
-HFADictionary::HFADictionary( const char * pszString )
-
+HFADictionary::HFADictionary( const char * pszString ) :
+    nTypes(0), nTypesMax(0), papoTypes(NULL), osDictionaryText(pszString),
+    bDictionaryTextDirty(FALSE)
 {
-    int		i;
-    
-    nTypes = 0;
-    nTypesMax = 0;
-    papoTypes = NULL;
-
-    osDictionaryText = pszString;
-    bDictionaryTextDirty = FALSE;
 
 /* -------------------------------------------------------------------- */
 /*      Read all the types.                                             */
 /* -------------------------------------------------------------------- */
     while( pszString != NULL && *pszString != '.' )
     {
-        HFAType		*poNewType;
-
-        poNewType = new HFAType();
+        HFAType	*poNewType = new HFAType();
         pszString = poNewType->Initialize( pszString );
 
         if( pszString != NULL )
@@ -125,7 +114,7 @@ HFADictionary::HFADictionary( const char * pszString )
 /* -------------------------------------------------------------------- */
 /*      Complete the definitions.                                       */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < nTypes; i++ )
+    for( int i = 0; i < nTypes; i++ )
     {
         papoTypes[i]->CompleteDefn( this );
     }
@@ -138,11 +127,9 @@ HFADictionary::HFADictionary( const char * pszString )
 HFADictionary::~HFADictionary()
 
 {
-    int		i;
-
-    for( i = 0; i < nTypes; i++ )
+    for( int i = 0; i < nTypes; i++ )
         delete papoTypes[i];
-    
+
     CPLFree( papoTypes );
 }
 
@@ -153,7 +140,12 @@ HFADictionary::~HFADictionary()
 void HFADictionary::AddType( HFAType *poType )
 
 {
-    if( nTypes == nTypesMax )
+    if( nTypes == nTypesMax
+#ifdef DEBUG
+        // To please Coverity.
+        || papoTypes == NULL
+#endif
+        )
     {
         nTypesMax = nTypes * 2 + 10;
         papoTypes = (HFAType **) CPLRealloc( papoTypes,
@@ -170,9 +162,7 @@ void HFADictionary::AddType( HFAType *poType )
 HFAType * HFADictionary::FindType( const char * pszName )
 
 {
-    int		i;
-
-    for( i = 0; i < nTypes; i++ )
+    for( int i = 0; i < nTypes; i++ )
     {
         if( papoTypes[i]->pszTypeName != NULL &&
             strcmp(pszName,papoTypes[i]->pszTypeName) == 0 )
@@ -184,7 +174,7 @@ HFAType * HFADictionary::FindType( const char * pszName )
 /*      it to the dictionary now.  I'm not sure how some files end      */
 /*      up being distributed using types not in the dictionary.         */
 /* -------------------------------------------------------------------- */
-    for( i = 0; apszDefDefn[i] != NULL; i += 2 )
+    for( int i = 0; apszDefDefn[i] != NULL; i += 2 )
     {
         if( strcmp( pszName, apszDefDefn[i] ) == 0 )
         {
@@ -246,7 +236,7 @@ int HFADictionary::GetItemSize( char chType )
 
       case 'b':
         return -1;
-        
+
       case 'o':
       case 'x':
         return 0;
@@ -265,11 +255,9 @@ int HFADictionary::GetItemSize( char chType )
 void HFADictionary::Dump( FILE * fp )
 
 {
-    int		i;
-    
-    VSIFPrintf( fp, "\nHFADictionary:\n" );
+    CPL_IGNORE_RET_VAL(VSIFPrintf( fp, "\nHFADictionary:\n" ));
 
-    for( i = 0; i < nTypes; i++ )
+    for( int i = 0; i < nTypes; i++ )
     {
         papoTypes[i]->Dump( fp );
     }
diff --git a/frmts/hfa/hfaentry.cpp b/frmts/hfa/hfaentry.cpp
index b8a126e..c64c478 100644
--- a/frmts/hfa/hfaentry.cpp
+++ b/frmts/hfa/hfaentry.cpp
@@ -1,9 +1,9 @@
 /******************************************************************************
- * $Id: hfaentry.cpp 32495 2015-12-27 13:07:01Z rouault $
+ * $Id: hfaentry.cpp 33845 2016-04-01 13:43:02Z goatbar $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Implementation of the HFAEntry class for reading and relating
- *           one node in the HFA object tree structure. 
+ *           one node in the HFA object tree structure.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -38,33 +38,30 @@
 #include "hfa_p.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: hfaentry.cpp 32495 2015-12-27 13:07:01Z rouault $");
+CPL_CVSID("$Id: hfaentry.cpp 33845 2016-04-01 13:43:02Z goatbar $");
 
 /************************************************************************/
 /*                              HFAEntry()                              */
 /************************************************************************/
 
-HFAEntry::HFAEntry()
+HFAEntry::HFAEntry() :
+    bDirty(FALSE),
+    nFilePos(0),
+    psHFA(NULL),
+    poParent(NULL),
+    poPrev(NULL),
+    nNextPos(0),
+    poNext(NULL),
+    nChildPos(0),
+    poChild(NULL),
+    poType(NULL),
+    nDataPos(0),
+    nDataSize(0),
+    pabyData(NULL),
+    bIsMIFObject(FALSE)
 {
-    psHFA = NULL;
-
-    nFilePos = 0;
-    bDirty = FALSE;
-    bIsMIFObject = FALSE;
-
-    poParent = NULL;
-    poPrev = NULL;
-
-    poNext = poChild = NULL;
-
-    nDataPos = nDataSize = 0;
-    nNextPos = nChildPos = 0;
-
-    szName[0] = szType[0] = '\0';
-
-    pabyData = NULL;
-
-    poType = NULL;
+    szName[0] = '\0';
+    szType[0] = '\0';
 }
 
 /************************************************************************/
@@ -79,7 +76,7 @@ HFAEntry* HFAEntry::New( HFAInfo_t * psHFAIn, GUInt32 nPos,
 {
     HFAEntry* poEntry = new HFAEntry;
     poEntry->psHFA = psHFAIn;
-    
+
     poEntry->nFilePos = nPos;
     poEntry->poParent = poParentIn;
     poEntry->poPrev = poPrevIn;
@@ -88,7 +85,6 @@ HFAEntry* HFAEntry::New( HFAInfo_t * psHFAIn, GUInt32 nPos,
 /*      Read the entry information from the file.                       */
 /* -------------------------------------------------------------------- */
     GInt32	anEntryNums[6];
-    int		i;
 
     if( VSIFSeekL( poEntry->psHFA->fp, poEntry->nFilePos, SEEK_SET ) == -1
         || VSIFReadL( anEntryNums, sizeof(GInt32), 6, poEntry->psHFA->fp ) < 1 )
@@ -100,7 +96,7 @@ HFAEntry* HFAEntry::New( HFAInfo_t * psHFAIn, GUInt32 nPos,
         return NULL;
     }
 
-    for( i = 0; i < 6; i++ )
+    for( int i = 0; i < 6; i++ )
         HFAStandard( 4, anEntryNums + i );
 
     poEntry->nNextPos = anEntryNums[0];
@@ -133,34 +129,32 @@ HFAEntry* HFAEntry::New( HFAInfo_t * psHFAIn, GUInt32 nPos,
 /*      would be written to disk later.                                 */
 /************************************************************************/
 
-HFAEntry::HFAEntry( HFAInfo_t * psHFAIn, 
-                    const char * pszNodeName, 
+HFAEntry::HFAEntry( HFAInfo_t * psHFAIn,
+                    const char * pszNodeName,
                     const char * pszTypeName,
-                    HFAEntry * poParentIn )
-
+                    HFAEntry * poParentIn ) :
+    nFilePos(0),
+    psHFA(psHFAIn),
+    poParent(poParentIn),
+    poPrev(NULL),
+    nNextPos(0),
+    poNext(NULL),
+    nChildPos(0),
+    poChild(NULL),
+    poType(NULL),
+    nDataPos(0),
+    nDataSize(0),
+    pabyData(NULL),
+    bIsMIFObject(FALSE)
 {
 /* -------------------------------------------------------------------- */
 /*      Initialize Entry                                                */
 /* -------------------------------------------------------------------- */
-    psHFA = psHFAIn;
-    
-    nFilePos = 0;
-    bIsMIFObject = FALSE;
-
-    poParent = poParentIn;
-    poPrev = poNext = poChild = NULL;
-
-    nDataPos = nDataSize = 0;
-    nNextPos = nChildPos = 0;
-
     SetName( pszNodeName );
     memset( szType, 0, sizeof(szType) );
     strncpy( szType, pszTypeName, sizeof(szType) );
     szType[sizeof(szType)-1] = '\0';
 
-    pabyData = NULL;
-    poType = NULL;
-
 /* -------------------------------------------------------------------- */
 /*      Update the previous or parent node to refer to this one.        */
 /* -------------------------------------------------------------------- */
@@ -187,25 +181,41 @@ HFAEntry::HFAEntry( HFAInfo_t * psHFAIn,
 }
 
 /************************************************************************/
+/*                              New()                                   */
+/*                                                                      */
+/*      Construct an HFAEntry in memory, with the intention that it     */
+/*      would be written to disk later.                                 */
+/************************************************************************/
+
+HFAEntry* HFAEntry::New( HFAInfo_t * psHFAIn,
+                         const char * pszNodeName,
+                         const char * pszTypeName,
+                         HFAEntry * poParentIn )
+{
+    CPLAssert( poParentIn != NULL );
+    return new HFAEntry(psHFAIn, pszNodeName, pszTypeName, poParentIn);
+}
+
+/************************************************************************/
 /*                      BuildEntryFromMIFObject()                       */
 /*                                                                      */
 /*      Create a pseudo-HFAEntry wrapping a MIFObject.                  */
 /************************************************************************/
 
-HFAEntry* HFAEntry::BuildEntryFromMIFObject( HFAEntry *poContainer, const char *pszMIFObjectPath )
+HFAEntry* HFAEntry::BuildEntryFromMIFObject( HFAEntry *poContainer,
+                                             const char *pszMIFObjectPath )
 {
-    const char* pszField;
     CPLString osFieldName;
 
     osFieldName.Printf("%s.%s", pszMIFObjectPath, "MIFDictionary" );
-    pszField = poContainer->GetStringField( osFieldName.c_str() );
+    const char *pszField = poContainer->GetStringField( osFieldName.c_str() );
     if (pszField == NULL)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s entry",
                  osFieldName.c_str());
         return NULL;
     }
-    CPLString osDictionnary = pszField;
+    CPLString osDictionary = pszField;
 
     osFieldName.Printf("%s.%s", pszMIFObjectPath, "type.string" );
     pszField = poContainer->GetStringField( osFieldName.c_str() );
@@ -247,15 +257,14 @@ HFAEntry* HFAEntry::BuildEntryFromMIFObject( HFAEntry *poContainer, const char *
         return NULL;
     }
 
-    GByte* pabyData = (GByte *) VSIMalloc(nMIFObjectSize);
-    if (pabyData == NULL)
+    GByte* l_pabyData = (GByte *) VSIMalloc(nMIFObjectSize);
+    if (l_pabyData == NULL)
         return NULL;
 
-    memcpy( pabyData, pszField, nMIFObjectSize );
+    memcpy( l_pabyData, pszField, nMIFObjectSize );
 
-    return new HFAEntry(poContainer, pszMIFObjectPath,
-                        osDictionnary, osType,
-                        nMIFObjectSize, pabyData);
+    return new HFAEntry(osDictionary, osType,
+                        nMIFObjectSize, l_pabyData);
 
 }
 
@@ -265,25 +274,25 @@ HFAEntry* HFAEntry::BuildEntryFromMIFObject( HFAEntry *poContainer, const char *
 /*      Create a pseudo-HFAEntry wrapping a MIFObject.                  */
 /************************************************************************/
 
-HFAEntry::HFAEntry( CPL_UNUSED HFAEntry * poContainer,
-                    CPL_UNUSED const char *pszMIFObjectPath,
-                    const char * pszDictionnary,
+HFAEntry::HFAEntry( const char * pszDictionary,
                     const char * pszTypeName,
                     int nDataSizeIn,
-                    GByte* pabyDataIn )
+                    GByte* pabyDataIn ) :
+    bDirty(FALSE),
+    nFilePos(0),
+    poParent(NULL),
+    poPrev(NULL),
+    nNextPos(0),
+    poNext(NULL),
+    nChildPos(0),
+    poChild(NULL),
+    nDataPos(0),
+    nDataSize(0),
+    bIsMIFObject(TRUE)
 {
 /* -------------------------------------------------------------------- */
 /*      Initialize Entry                                                */
 /* -------------------------------------------------------------------- */
-    nFilePos = 0;
-
-    poParent = poPrev = poNext = poChild = NULL;
-
-    bIsMIFObject = TRUE;
-
-    nDataPos = nDataSize = 0;
-    nNextPos = nChildPos = 0;
-
     memset( szName, 0, sizeof(szName) );
 
 /* -------------------------------------------------------------------- */
@@ -295,7 +304,7 @@ HFAEntry::HFAEntry( CPL_UNUSED HFAEntry * poContainer,
     psHFA->bTreeDirty = FALSE;
     psHFA->poRoot = this;
 
-    psHFA->poDictionary = new HFADictionary( pszDictionnary );
+    psHFA->poDictionary = new HFADictionary( pszDictionary );
 
 /* -------------------------------------------------------------------- */
 /*      Work out the type for this MIFObject.                           */
@@ -303,7 +312,7 @@ HFAEntry::HFAEntry( CPL_UNUSED HFAEntry * poContainer,
     memset( szType, 0, sizeof(szType) );
     strncpy( szType, pszTypeName, sizeof(szType) );
     szType[sizeof(szType)-1] = '\0';
-    
+
     poType = psHFA->poDictionary->FindType( szType );
 
     nDataSize = nDataSizeIn;
@@ -321,7 +330,7 @@ HFAEntry::~HFAEntry()
 
 {
     CPLFree( pabyData );
-    
+
     if( poNext != NULL )
         delete poNext;
 
@@ -370,7 +379,7 @@ CPLErr HFAEntry::RemoveAndDestroy()
     {
         poNext->poPrev = poPrev;
     }
-    
+
     poNext = NULL;
     poPrev = NULL;
     poParent = NULL;
@@ -430,20 +439,20 @@ HFAEntry *HFAEntry::GetNext()
         // Check if we have a loop on the next node in this sibling chain.
         HFAEntry *poPast;
 
-        for( poPast = this; 
-             poPast != NULL && poPast->nFilePos != nNextPos; 
+        for( poPast = this;
+             poPast != NULL && poPast->nFilePos != nNextPos;
              poPast = poPast->poPrev ) {}
 
         if( poPast != NULL )
         {
             CPLError( CE_Warning, CPLE_AppDefined,
                       "Corrupt (looping) entry in %s, ignoring some entries after %s.",
-                      psHFA->pszFilename, 
+                      psHFA->pszFilename,
                       szName );
             nNextPos = 0;
             return NULL;
         }
-             
+
         poNext = HFAEntry::New( psHFA, nNextPos, poParent, this );
         if( poNext == NULL )
             nNextPos = 0;
@@ -474,14 +483,12 @@ void HFAEntry::LoadData()
 /* -------------------------------------------------------------------- */
 /*      Allocate buffer, and read data.                                 */
 /* -------------------------------------------------------------------- */
-    pabyData = (GByte *) VSIMalloc(nDataSize + 1);
+    pabyData = (GByte *) VSI_MALLOC_VERBOSE(nDataSize + 1);
     if (pabyData == NULL)
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory,
-                  "VSIMalloc() failed in HFAEntry::LoadData()." );
         return;
     }
-    
+
     if( VSIFSeekL( psHFA->fp, nDataPos, SEEK_SET ) < 0 )
     {
         CPLError( CE_Failure, CPLE_FileIO,
@@ -562,10 +569,10 @@ GByte *HFAEntry::MakeData( int nSize )
         {
             nFilePos = 0;
             nDataPos = 0;
-            if (poPrev != NULL) poPrev->MarkDirty(); 
-            if (poNext != NULL) poNext->MarkDirty(); 
-            if (poChild != NULL) poChild->MarkDirty(); 
-            if (poParent != NULL) poParent->MarkDirty(); 
+            if (poPrev != NULL) poPrev->MarkDirty();
+            if (poNext != NULL) poNext->MarkDirty();
+            if (poChild != NULL) poChild->MarkDirty();
+            if (poParent != NULL) poParent->MarkDirty();
         }
     }
     else
@@ -611,7 +618,6 @@ std::vector<HFAEntry*> HFAEntry::FindChildren( const char *pszName,
 
 {
     std::vector<HFAEntry*> apoChildren;
-    HFAEntry *poEntry;
 
     if( *pbErrorDetected )
         return apoChildren;
@@ -623,10 +629,9 @@ std::vector<HFAEntry*> HFAEntry::FindChildren( const char *pszName,
         return apoChildren;
     }
 
-    for( poEntry = GetChild(); poEntry != NULL; poEntry = poEntry->GetNext() )
+    for( HFAEntry *poEntry = GetChild(); poEntry != NULL; poEntry = poEntry->GetNext() )
     {
         std::vector<HFAEntry*> apoEntryChildren;
-        size_t i;
 
         if( (pszName == NULL || EQUAL(poEntry->GetName(),pszName))
             && (pszType == NULL || EQUAL(poEntry->GetType(),pszType)) )
@@ -637,7 +642,7 @@ std::vector<HFAEntry*> HFAEntry::FindChildren( const char *pszName,
         if( *pbErrorDetected )
             return apoChildren;
 
-        for( i = 0; i < apoEntryChildren.size(); i++ )
+        for( size_t i = 0; i < apoEntryChildren.size(); i++ )
             apoChildren.push_back( apoEntryChildren[i] );
     }
 
@@ -659,14 +664,12 @@ std::vector<HFAEntry*> HFAEntry::FindChildren( const char *pszName,
 HFAEntry *HFAEntry::GetNamedChild( const char * pszName )
 
 {
-    int		nNameLen;
-    HFAEntry	*poEntry;
-
 /* -------------------------------------------------------------------- */
 /*      Establish how much of this name path is for the next child.     */
-/*      Up to the '.' or end of estring.                                */
+/*      Up to the '.' or end of the string.                             */
 /* -------------------------------------------------------------------- */
-    for( nNameLen = 0;
+    int nNameLen = 0;
+    for( ;
          pszName[nNameLen] != '.'
              && pszName[nNameLen] != '\0'
              && pszName[nNameLen] != ':';
@@ -675,7 +678,7 @@ HFAEntry *HFAEntry::GetNamedChild( const char * pszName )
 /* -------------------------------------------------------------------- */
 /*      Scan children looking for this name.                            */
 /* -------------------------------------------------------------------- */
-    for( poEntry = GetChild(); poEntry != NULL; poEntry = poEntry->GetNext() )
+    for( HFAEntry *poEntry = GetChild(); poEntry != NULL; poEntry = poEntry->GetNext() )
     {
         if( EQUALN(poEntry->GetName(),pszName,nNameLen)
             && (int) strlen(poEntry->GetName()) == nNameLen )
@@ -699,23 +702,21 @@ HFAEntry *HFAEntry::GetNamedChild( const char * pszName )
 /************************************************************************/
 /*                           GetFieldValue()                            */
 /************************************************************************/
-        
+
 int HFAEntry::GetFieldValue( const char * pszFieldPath,
                              char chReqType, void *pReqReturn,
                              int *pnRemainingDataSize)
 
 {
-    HFAEntry	*poEntry = this;
-    
 /* -------------------------------------------------------------------- */
 /*      Is there a node path in this string?                            */
 /* -------------------------------------------------------------------- */
     if( strchr(pszFieldPath,':') != NULL )
     {
-        poEntry = GetNamedChild( pszFieldPath );
+        HFAEntry* poEntry = GetNamedChild( pszFieldPath );
         if( poEntry == NULL )
             return FALSE;
-        
+
         pszFieldPath = strchr(pszFieldPath,':') + 1;
     }
 
@@ -726,7 +727,7 @@ int HFAEntry::GetFieldValue( const char * pszFieldPath,
 
     if( pabyData == NULL )
         return FALSE;
-    
+
     if( poType == NULL )
         return FALSE;
 
@@ -746,17 +747,15 @@ int HFAEntry::GetFieldValue( const char * pszFieldPath,
 
 int HFAEntry::GetFieldCount( const char * pszFieldPath, CPL_UNUSED CPLErr *peErr )
 {
-    HFAEntry	*poEntry = this;
-
 /* -------------------------------------------------------------------- */
 /*      Is there a node path in this string?                            */
 /* -------------------------------------------------------------------- */
     if( strchr(pszFieldPath,':') != NULL )
     {
-        poEntry = GetNamedChild( pszFieldPath );
+        HFAEntry* poEntry = GetNamedChild( pszFieldPath );
         if( poEntry == NULL )
             return -1;
-        
+
         pszFieldPath = strchr(pszFieldPath,':') + 1;
     }
 
@@ -767,7 +766,7 @@ int HFAEntry::GetFieldCount( const char * pszFieldPath, CPL_UNUSED CPLErr *peErr
 
     if( pabyData == NULL )
         return -1;
-    
+
     if( poType == NULL )
         return -1;
 
@@ -795,20 +794,18 @@ GInt32 HFAEntry::GetIntField( const char * pszFieldPath, CPLErr *peErr )
 
         return 0;
     }
-    else
-    {
-        if( peErr != NULL )
-            *peErr = CE_None;
 
-        return nIntValue;
-    }
+    if( peErr != NULL )
+        *peErr = CE_None;
+
+    return nIntValue;
 }
 
 /************************************************************************/
 /*                           GetBigIntField()                           */
 /*                                                                      */
 /*      This is just a helper method that reads two ULONG array         */
-/*      entries as a GBigInt.  The passed name should be the name of    */
+/*      entries as a GIntBig.  The passed name should be the name of    */
 /*      the array with no array index.  Array indexes 0 and 1 will      */
 /*      be concatenated.                                                */
 /************************************************************************/
@@ -816,16 +813,15 @@ GInt32 HFAEntry::GetIntField( const char * pszFieldPath, CPLErr *peErr )
 GIntBig HFAEntry::GetBigIntField( const char *pszFieldPath, CPLErr *peErr )
 
 {
-    GUInt32 nLower, nUpper;
     char szFullFieldPath[1024];
 
-    sprintf( szFullFieldPath, "%s[0]", pszFieldPath );
-    nLower = GetIntField( szFullFieldPath, peErr );
+    snprintf( szFullFieldPath, sizeof(szFullFieldPath), "%s[0]", pszFieldPath );
+    const GUInt32 nLower = GetIntField( szFullFieldPath, peErr );
     if( peErr != NULL && *peErr != CE_None )
         return 0;
 
-    sprintf( szFullFieldPath, "%s[1]", pszFieldPath );
-    nUpper = GetIntField( szFullFieldPath, peErr );
+    snprintf( szFullFieldPath, sizeof(szFullFieldPath), "%s[1]", pszFieldPath );
+    const GUInt32 nUpper = GetIntField( szFullFieldPath, peErr );
     if( peErr != NULL && *peErr != CE_None )
         return 0;
 
@@ -848,13 +844,11 @@ double HFAEntry::GetDoubleField( const char * pszFieldPath, CPLErr *peErr )
 
         return 0.0;
     }
-    else
-    {
-        if( peErr != NULL )
-            *peErr = CE_None;
 
-        return dfDoubleValue;
-    }
+    if( peErr != NULL )
+        *peErr = CE_None;
+
+    return dfDoubleValue;
 }
 
 /************************************************************************/
@@ -874,34 +868,30 @@ const char *HFAEntry::GetStringField( const char * pszFieldPath, CPLErr *peErr,
 
         return NULL;
     }
-    else
-    {
-        if( peErr != NULL )
-            *peErr = CE_None;
 
-        return pszResult;
-    }
+    if( peErr != NULL )
+        *peErr = CE_None;
+
+    return pszResult;
 }
 
 /************************************************************************/
 /*                           SetFieldValue()                            */
 /************************************************************************/
-        
+
 CPLErr HFAEntry::SetFieldValue( const char * pszFieldPath,
                                 char chReqType, void *pValue )
 
 {
-    HFAEntry	*poEntry = this;
-    
 /* -------------------------------------------------------------------- */
 /*      Is there a node path in this string?                            */
 /* -------------------------------------------------------------------- */
     if( strchr(pszFieldPath,':') != NULL )
     {
-        poEntry = GetNamedChild( pszFieldPath );
+        HFAEntry* poEntry = GetNamedChild( pszFieldPath );
         if( poEntry == NULL )
             return CE_Failure;
-        
+
         pszFieldPath = strchr(pszFieldPath,':') + 1;
     }
 
@@ -910,7 +900,7 @@ CPLErr HFAEntry::SetFieldValue( const char * pszFieldPath,
 /*      from a file, or instantiating a new node.                       */
 /* -------------------------------------------------------------------- */
     LoadData();
-    if( MakeData() == NULL 
+    if( MakeData() == NULL
         || pabyData == NULL
         || poType == NULL )
     {
@@ -932,7 +922,7 @@ CPLErr HFAEntry::SetFieldValue( const char * pszFieldPath,
 /*                           SetStringField()                           */
 /************************************************************************/
 
-CPLErr HFAEntry::SetStringField( const char * pszFieldPath, 
+CPLErr HFAEntry::SetStringField( const char * pszFieldPath,
                                  const char * pszValue )
 
 {
@@ -976,8 +966,8 @@ void HFAEntry::SetPosition()
 /* -------------------------------------------------------------------- */
     if( nFilePos == 0 )
     {
-        nFilePos = HFAAllocateSpace( psHFA, 
-                                     psHFA->nEntryHeaderLength 
+        nFilePos = HFAAllocateSpace( psHFA,
+                                     psHFA->nEntryHeaderLength
                                      + nDataSize );
 
         if( nDataSize > 0 )
@@ -987,7 +977,7 @@ void HFAEntry::SetPosition()
 /* -------------------------------------------------------------------- */
 /*      Force all children to set their position.                       */
 /* -------------------------------------------------------------------- */
-    for( HFAEntry *poThisChild = poChild; 
+    for( HFAEntry *poThisChild = poChild;
          poThisChild != NULL;
          poThisChild = poThisChild->poNext )
     {
@@ -1005,8 +995,6 @@ void HFAEntry::SetPosition()
 CPLErr HFAEntry::FlushToDisk()
 
 {
-    CPLErr	eErr = CE_None;
-
 /* -------------------------------------------------------------------- */
 /*      If we are the root node, call SetPosition() on the whole        */
 /*      tree to ensure that all entries have an allocated position.     */
@@ -1031,55 +1019,54 @@ CPLErr HFAEntry::FlushToDisk()
 /* -------------------------------------------------------------------- */
 /*      Write the Ehfa_Entry fields.                                    */
 /* -------------------------------------------------------------------- */
-        GUInt32		nLong;
 
         //VSIFFlushL( psHFA->fp );
         if( VSIFSeekL( psHFA->fp, nFilePos, SEEK_SET ) != 0 )
         {
-            CPLError( CE_Failure, CPLE_FileIO, 
+            CPLError( CE_Failure, CPLE_FileIO,
                       "Failed to seek to %d for writing, out of disk space?",
                       nFilePos );
             return CE_Failure;
         }
 
-        nLong = nNextPos;
+        GUInt32 nLong = nNextPos;
         HFAStandard( 4, &nLong );
-        VSIFWriteL( &nLong, 4, 1, psHFA->fp );
+        bool bOK = VSIFWriteL( &nLong, 4, 1, psHFA->fp ) > 0;
 
         if( poPrev != NULL )
             nLong = poPrev->nFilePos;
         else
             nLong = 0;
         HFAStandard( 4, &nLong );
-        VSIFWriteL( &nLong, 4, 1, psHFA->fp );
+        bOK &= VSIFWriteL( &nLong, 4, 1, psHFA->fp ) > 0;
 
         if( poParent != NULL )
             nLong = poParent->nFilePos;
         else
             nLong = 0;
         HFAStandard( 4, &nLong );
-        VSIFWriteL( &nLong, 4, 1, psHFA->fp );
+        bOK &= VSIFWriteL( &nLong, 4, 1, psHFA->fp ) > 0;
 
         nLong = nChildPos;
         HFAStandard( 4, &nLong );
-        VSIFWriteL( &nLong, 4, 1, psHFA->fp );
+        bOK &= VSIFWriteL( &nLong, 4, 1, psHFA->fp ) > 0;
 
-        
         nLong = nDataPos;
         HFAStandard( 4, &nLong );
-        VSIFWriteL( &nLong, 4, 1, psHFA->fp );
+        bOK &= VSIFWriteL( &nLong, 4, 1, psHFA->fp ) > 0;
 
         nLong = nDataSize;
         HFAStandard( 4, &nLong );
-        VSIFWriteL( &nLong, 4, 1, psHFA->fp );
+        bOK &= VSIFWriteL( &nLong, 4, 1, psHFA->fp ) > 0;
 
-        VSIFWriteL( szName, 1, 64, psHFA->fp );
-        VSIFWriteL( szType, 1, 32, psHFA->fp );
+        bOK &= VSIFWriteL( szName, 1, 64, psHFA->fp ) > 0;
+        bOK &= VSIFWriteL( szType, 1, 32, psHFA->fp ) > 0;
 
         nLong = 0; /* Should we keep the time, or set it more reasonably? */
-        if( VSIFWriteL( &nLong, 4, 1, psHFA->fp ) != 1 )
+        bOK &= VSIFWriteL( &nLong, 4, 1, psHFA->fp ) > 0;
+        if( !bOK )
         {
-            CPLError( CE_Failure, CPLE_FileIO, 
+            CPLError( CE_Failure, CPLE_FileIO,
                       "Failed to write HFAEntry %s(%s), out of disk space?",
                       szName, szType );
             return CE_Failure;
@@ -1091,10 +1078,10 @@ CPLErr HFAEntry::FlushToDisk()
         //VSIFFlushL( psHFA->fp );
         if( nDataSize > 0 && pabyData != NULL )
         {
-            if( VSIFSeekL( psHFA->fp, nDataPos, SEEK_SET ) != 0 
+            if( VSIFSeekL( psHFA->fp, nDataPos, SEEK_SET ) != 0
                 || VSIFWriteL( pabyData, nDataSize, 1, psHFA->fp ) != 1 )
             {
-                CPLError( CE_Failure, CPLE_FileIO, 
+                CPLError( CE_Failure, CPLE_FileIO,
                           "Failed to write %d bytes HFAEntry %s(%s) data,\n"
                           "out of disk space?",
                           nDataSize, szName, szType );
@@ -1108,11 +1095,11 @@ CPLErr HFAEntry::FlushToDisk()
 /* -------------------------------------------------------------------- */
 /*      Process all the children of this node                           */
 /* -------------------------------------------------------------------- */
-    for( HFAEntry *poThisChild = poChild; 
+    for( HFAEntry *poThisChild = poChild;
          poThisChild != NULL;
          poThisChild = poThisChild->poNext )
     {
-        eErr = poThisChild->FlushToDisk();
+        CPLErr eErr = poThisChild->FlushToDisk();
         if( eErr != CE_None )
             return eErr;
     }
diff --git a/frmts/hfa/hfafield.cpp b/frmts/hfa/hfafield.cpp
index 26b1f48..3a8eab9 100644
--- a/frmts/hfa/hfafield.cpp
+++ b/frmts/hfa/hfafield.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfafield.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: hfafield.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Implementation of the HFAField class for managing information
@@ -31,10 +31,10 @@
 
 #include "hfa_p.h"
 
-CPL_CVSID("$Id: hfafield.cpp 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: hfafield.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 #define MAX_ENTRY_REPORT   16
-                           
+
 /************************************************************************/
 /* ==================================================================== */
 /*		                HFAField				*/
@@ -45,22 +45,16 @@ CPL_CVSID("$Id: hfafield.cpp 27942 2014-11-11 00:57:41Z rouault $");
 /*                              HFAField()                              */
 /************************************************************************/
 
-HFAField::HFAField()
-
-{
-    nBytes = 0;
-
-    nItemCount = 0;
-    chPointer = '\0';
-    chItemType = '\0';
-
-    pszItemObjectType = NULL;
-    poItemObjectType = NULL;
-
-    papszEnumNames = NULL;
-
-    pszFieldName = NULL;
-}
+HFAField::HFAField() :
+    nBytes(0),
+    nItemCount(0),
+    chPointer('\0'),
+    chItemType('\0'),
+    pszItemObjectType(NULL),
+    poItemObjectType(NULL),
+    papszEnumNames(NULL),
+    pszFieldName(NULL)
+{ }
 
 /************************************************************************/
 /*                             ~HFAField()                              */
@@ -81,19 +75,19 @@ HFAField::~HFAField()
 const char *HFAField::Initialize( const char * pszInput )
 
 {
-    int		i;
-    
 /* -------------------------------------------------------------------- */
 /*      Read the number.                                                */
 /* -------------------------------------------------------------------- */
     nItemCount = atoi(pszInput);
+    if( nItemCount < 0 )
+        return NULL;
 
     while( *pszInput != '\0' && *pszInput != ':' )
         pszInput++;
 
     if( *pszInput == '\0' )
         return NULL;
-    
+
     pszInput++;
 
 /* -------------------------------------------------------------------- */
@@ -120,6 +114,8 @@ const char *HFAField::Initialize( const char * pszInput )
 /* -------------------------------------------------------------------- */
 /*      If this is an object, we extract the type of the object.        */
 /* -------------------------------------------------------------------- */
+    int i;   // TODO: Describe why i needs to span chItemType blocks.
+
     if( chItemType == 'o' )
     {
         for( i = 0; pszInput[i] != '\0' && pszInput[i] != ','; i++ ) {}
@@ -153,7 +149,7 @@ const char *HFAField::Initialize( const char * pszInput )
                 nBraceDepth++;
             else if( *pszInput == '}' )
                 nBraceDepth--;
-            
+
             pszInput++;
         }
         if (*pszInput == '\0')
@@ -180,7 +176,6 @@ const char *HFAField::Initialize( const char * pszInput )
     if( chItemType == 'e' )
     {
         int	nEnumCount = atoi(pszInput);
-        int	iEnum;
 
         if (nEnumCount < 0 || nEnumCount > 100000)
             return NULL;
@@ -194,17 +189,15 @@ const char *HFAField::Initialize( const char * pszInput )
         papszEnumNames = (char **) VSICalloc(sizeof(char *), nEnumCount+1);
         if (papszEnumNames == NULL)
             return NULL;
-        
-        for( iEnum = 0; iEnum < nEnumCount; iEnum++ )
+
+        for( int iEnum = 0; iEnum < nEnumCount; iEnum++ )
         {
-            char	*pszToken;
-            
             for( i = 0; pszInput[i] != '\0' && pszInput[i] != ','; i++ ) {}
 
             if( pszInput[i] != ',' )
                 return NULL;
 
-            pszToken = (char *) CPLMalloc(i+1);
+            char *pszToken = (char *) CPLMalloc(i+1);
             strncpy( pszToken, pszInput, i );
             pszToken[i] = '\0';
 
@@ -226,7 +219,7 @@ const char *HFAField::Initialize( const char * pszInput )
     pszFieldName[i] = '\0';
 
     pszInput += i+1;
-    
+
     return( pszInput );
 }
 
@@ -258,15 +251,27 @@ void HFAField::CompleteDefn( HFADictionary * poDict )
         poItemObjectType->CompleteDefn( poDict );
         if( poItemObjectType->nBytes == -1 )
             nBytes = -1;
+        else if( poItemObjectType->nBytes != 0 &&
+                 nItemCount > INT_MAX / poItemObjectType->nBytes )
+            nBytes = -1;
         else
             nBytes = poItemObjectType->nBytes * nItemCount;
 
         if( chPointer == '*' && nBytes != -1 )
-            nBytes += 8; /* count, and offset */
+        {
+            if( nBytes > INT_MAX - 8 )
+                nBytes = -1;
+            else
+                nBytes += 8; /* count, and offset */
+        }
     }
     else
     {
-        nBytes = poDict->GetItemSize( chItemType ) * nItemCount;
+        const int nItemSize = poDict->GetItemSize( chItemType );
+        if( nItemSize != 0 && nItemCount > INT_MAX / nItemSize )
+            nBytes = -1;
+        else
+            nBytes = nItemSize * nItemCount;
     }
 }
 
@@ -278,25 +283,25 @@ void HFAField::Dump( FILE * fp )
 
 {
     const char	*pszTypeName;
-    
+
     switch( chItemType )
     {
       case '1':
         pszTypeName = "U1";
         break;
-        
+
       case '2':
         pszTypeName = "U2";
         break;
-        
+
       case '4':
         pszTypeName = "U4";
         break;
-        
+
       case 'c':
         pszTypeName = "UCHAR";
         break;
-        
+
       case 'C':
         pszTypeName = "CHAR";
         break;
@@ -304,47 +309,47 @@ void HFAField::Dump( FILE * fp )
       case 'e':
         pszTypeName = "ENUM";
         break;
-        
+
       case 's':
         pszTypeName = "USHORT";
         break;
-        
+
       case 'S':
         pszTypeName = "SHORT";
         break;
-        
+
       case 't':
         pszTypeName = "TIME";
         break;
-        
+
       case 'l':
         pszTypeName = "ULONG";
         break;
-        
+
       case 'L':
         pszTypeName = "LONG";
         break;
-        
+
       case 'f':
         pszTypeName = "FLOAT";
         break;
-        
+
       case 'd':
         pszTypeName = "DOUBLE";
         break;
-        
+
       case 'm':
         pszTypeName = "COMPLEX";
         break;
-        
+
       case 'M':
         pszTypeName = "DCOMPLEX";
         break;
-        
+
       case 'b':
         pszTypeName = "BASEDATA";
         break;
-        
+
       case 'o':
         pszTypeName = pszItemObjectType;
         break;
@@ -357,20 +362,18 @@ void HFAField::Dump( FILE * fp )
         CPLAssert( FALSE );
         pszTypeName = "Unknown";
     }
-    
-    VSIFPrintf( fp, "    %-19s %c %s[%d];\n",
+
+    CPL_IGNORE_RET_VAL(VSIFPrintf( fp, "    %-19s %c %s[%d];\n",
                 pszTypeName,
                 chPointer ? chPointer : ' ',
-                pszFieldName, nItemCount );
+                pszFieldName, nItemCount ));
 
     if( papszEnumNames != NULL )
     {
-        int	i;
-        
-        for( i = 0; papszEnumNames[i] != NULL; i++ )
+        for( int i = 0; papszEnumNames[i] != NULL; i++ )
         {
-            VSIFPrintf( fp, "        %s=%d\n",
-                        papszEnumNames[i], i );
+            CPL_IGNORE_RET_VAL(VSIFPrintf( fp, "        %s=%d\n",
+                        papszEnumNames[i], i ));
         }
     }
 }
@@ -392,16 +395,11 @@ HFAField::SetInstValue( const char * pszField, int nIndexValue,
     if( chPointer != '\0' )
     {
         GUInt32		nCount;
-        GUInt32		nOffset;
-
-         /* set the count for fixed sized arrays */
-        if( nBytes > -1 )
-            nCount = nItemCount;
 
-        // The count returned for BASEDATA's are the contents, 
+        // The count returned for BASEDATA's are the contents,
         // but here we really want to mark it as one BASEDATA instance
         // (see #2144)
-        if( chItemType == 'b' ) 
+        if( chItemType == 'b' )
             nCount = 1;
 
         /* Set the size from string length */
@@ -410,7 +408,7 @@ HFAField::SetInstValue( const char * pszField, int nIndexValue,
             if( pValue == NULL )
                 nCount = 0;
             else
-                nCount = strlen((char *) pValue) + 1;
+                nCount = static_cast<GUInt32>(strlen((char *) pValue) + 1);
         }
 
         /* set size based on index ... assumes in-order setting of array */
@@ -427,6 +425,7 @@ HFAField::SetInstValue( const char * pszField, int nIndexValue,
         }
 
         // we will update the object count iff we are writing beyond the end
+        GUInt32		nOffset;
         memcpy( &nOffset, pabyData, 4 );
         HFAStandard( 4, &nOffset );
         if( nOffset < nCount )
@@ -456,13 +455,13 @@ HFAField::SetInstValue( const char * pszField, int nIndexValue,
     if( (chItemType == 'c' || chItemType == 'C') && chReqType == 's' )
     {
         int	nBytesToCopy;
-        
+
         if( nBytes == -1 )
         {
             if( pValue == NULL )
                 nBytesToCopy = 0;
             else
-                nBytesToCopy = strlen((char *) pValue) + 1;
+                nBytesToCopy = static_cast<int>(strlen((char *) pValue) + 1);
         }
         else
             nBytesToCopy = nBytes;
@@ -492,11 +491,13 @@ HFAField::SetInstValue( const char * pszField, int nIndexValue,
 
     if( chReqType == 's' )
     {
+        CPLAssert( pValue != NULL );
         nIntValue = atoi((char *) pValue);
         dfDoubleValue = CPLAtof((char *) pValue);
     }
     else if( chReqType == 'd' )
     {
+        CPLAssert( pValue != NULL );
         dfDoubleValue = *((double *) pValue);
         if( dfDoubleValue > INT_MAX )
             nIntValue = INT_MAX;
@@ -507,14 +508,15 @@ HFAField::SetInstValue( const char * pszField, int nIndexValue,
     }
     else if( chReqType == 'i' )
     {
-        dfDoubleValue = *((int *) pValue);
+        CPLAssert( pValue != NULL );
         nIntValue = *((int *) pValue);
+        dfDoubleValue = nIntValue;
     }
     else if( chReqType == 'p' )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
             "HFAField::SetInstValue() not supported yet for pointer values." );
-        
+
         return CE_Failure;
     }
     else
@@ -540,7 +542,10 @@ HFAField::SetInstValue( const char * pszField, int nIndexValue,
         }
 
         if( chReqType == 's' )
+        {
+            CPLAssert( pValue != NULL );
             pabyData[nIndexValue] = ((char *) pValue)[0];
+        }
         else
             pabyData[nIndexValue] = (char) nIntValue;
         break;
@@ -550,12 +555,13 @@ HFAField::SetInstValue( const char * pszField, int nIndexValue,
       {
           if( chItemType == 'e' && chReqType == 's' )
           {
+              CPLAssert( pValue != NULL );
               nIntValue = CSLFindString( papszEnumNames, (char *) pValue );
               if( nIntValue == -1 )
               {
-                  CPLError( CE_Failure, CPLE_AppDefined, 
+                  CPLError( CE_Failure, CPLE_AppDefined,
                             "Attempt to set enumerated field with unknown"
-                            " value `%s'.", 
+                            " value `%s'.",
                             (char *) pValue );
                   return CE_Failure;
               }
@@ -595,7 +601,7 @@ HFAField::SetInstValue( const char * pszField, int nIndexValue,
           memcpy( pabyData + nIndexValue*2, &nNumber, 2 );
       }
       break;
-        
+
       case 't':
       case 'l':
       {
@@ -614,11 +620,11 @@ HFAField::SetInstValue( const char * pszField, int nIndexValue,
           memcpy( pabyData + nIndexValue*4, &nNumber, 4 );
       }
       break;
-      
+
       case 'L':
       {
           GInt32	nNumber = nIntValue;
-          
+
           if( nIndexValue*4 + 4 > nDataSize )
           {
               CPLError( CE_Failure, CPLE_AppDefined,
@@ -632,11 +638,11 @@ HFAField::SetInstValue( const char * pszField, int nIndexValue,
           memcpy( pabyData + nIndexValue*4, &nNumber, 4 );
       }
       break;
-      
+
       case 'f':
       {
           float		fNumber = (float) dfDoubleValue;
-          
+
           if( nIndexValue*4 + 4 > nDataSize )
           {
               CPLError( CE_Failure, CPLE_AppDefined,
@@ -650,11 +656,11 @@ HFAField::SetInstValue( const char * pszField, int nIndexValue,
           memcpy( pabyData + nIndexValue*4, &fNumber, 4 );
       }
       break;
-        
+
       case 'd':
       {
           double	dfNumber = dfDoubleValue;
-          
+
           if( nIndexValue*8 + 8 > nDataSize )
           {
               CPLError( CE_Failure, CPLE_AppDefined,
@@ -669,10 +675,10 @@ HFAField::SetInstValue( const char * pszField, int nIndexValue,
       }
       break;
 
-    case 'b': 
-    { 
-        GInt32 nRows = 1; 
-        GInt32 nColumns = 1; 
+    case 'b':
+    {
+        GInt32 nRows = 1;
+        GInt32 nColumns = 1;
         GInt16 nBaseItemType;
 
         // Extract existing rows, columns, and datatype.
@@ -685,7 +691,7 @@ HFAField::SetInstValue( const char * pszField, int nIndexValue,
 
         // Are we using special index values to update the rows, columnrs
         // or type?
-        
+
         if( nIndexValue == -3 )
             nBaseItemType = (GInt16) nIntValue;
         else if( nIndexValue == -2 )
@@ -693,56 +699,60 @@ HFAField::SetInstValue( const char * pszField, int nIndexValue,
         else if( nIndexValue == -1 )
             nRows = nIntValue;
 
-        if( nIndexValue < -3 || nIndexValue >= nRows * nColumns ) 
-            return CE_Failure; 
+        if( nIndexValue < -3 || nIndexValue >= nRows * nColumns )
+            return CE_Failure;
 
         // Write back the rows, columns and basedatatype.
-        HFAStandard( 4, &nRows ); 
-        memcpy( pabyData, &nRows, 4 ); 
-        HFAStandard( 4, &nColumns ); 
-        memcpy( pabyData+4, &nColumns, 4 ); 
-        HFAStandard( 2, &nBaseItemType ); 
-        memcpy ( pabyData + 8, &nBaseItemType, 2 ); 
+        HFAStandard( 4, &nRows );
+        memcpy( pabyData, &nRows, 4 );
+        HFAStandard( 4, &nColumns );
+        memcpy( pabyData+4, &nColumns, 4 );
+        HFAStandard( 2, &nBaseItemType );
+        memcpy ( pabyData + 8, &nBaseItemType, 2 );
         HFAStandard( 2, &nBaseItemType ); // swap back for our use.
 
-        // We ignore the 2 byte objecttype value.  
+        if( nBaseItemType < EPT_MIN || nBaseItemType > EPT_MAX )
+            return CE_Failure;
+        EPTType eBaseItemType = static_cast<EPTType>(nBaseItemType);
+
+        // We ignore the 2 byte objecttype value.
 
-        nDataSize -= 12; 
+        nDataSize -= 12;
 
         if( nIndexValue >= 0 )
-        { 
-            if( (nIndexValue+1) * (HFAGetDataTypeBits(nBaseItemType)/8)
-                > nDataSize ) 
-            { 
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                          "Attempt to extend field %s in node past end of data,\n" 
-                          "not currently supported.", 
-                          pszField ); 
-                return CE_Failure; 
-            } 
-
-            if( nBaseItemType == EPT_f64 )
+        {
+            if( (nIndexValue+1) * (HFAGetDataTypeBits(eBaseItemType)/8)
+                > nDataSize )
             {
-                double dfNumber = dfDoubleValue; 
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Attempt to extend field %s in node past end of data,\n"
+                          "not currently supported.",
+                          pszField );
+                return CE_Failure;
+            }
+
+            if( eBaseItemType == EPT_f64 )
+            {
+                double dfNumber = dfDoubleValue;
 
-                HFAStandard( 8, &dfNumber ); 
-                memcpy( pabyData + 12 + nIndexValue * 8, &dfNumber, 8 ); 
+                HFAStandard( 8, &dfNumber );
+                memcpy( pabyData + 12 + nIndexValue * 8, &dfNumber, 8 );
             }
-            else if (nBaseItemType == EPT_u8)
+            else if (eBaseItemType == EPT_u8)
             {
                 unsigned char nNumber = (unsigned char)dfDoubleValue;
                 memcpy( pabyData + 12 + nIndexValue, &nNumber, 1);
             }
             else
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                          "Setting basedata field %s with type %s not currently supported.", 
-                          pszField, HFAGetDataTypeName( nBaseItemType ) ); 
-                return CE_Failure; 
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Setting basedata field %s with type %s not currently supported.",
+                          pszField, HFAGetDataTypeName( eBaseItemType ) );
+                return CE_Failure;
             }
-        } 
-    } 
-    break;               
+        }
+    }
+    break;
 
       case 'o':
         if( poItemObjectType != NULL )
@@ -858,14 +868,14 @@ HFAField::ExtractInstValue( const char * pszField, int nIndexValue,
 
         if( nOffset != (GUInt32) (nDataOffset + 8) )
         {
-#ifdef notdef            
+#ifdef notdef
             CPLError( CE_Warning, CPLE_AppDefined,
                       "%s.%s points at %d, not %d as expected\n",
                       pszFieldName, pszField ? pszField : "",
                       nOffset, nDataOffset+8 );
-#endif            
+#endif
         }
-        
+
         pabyData += 8;
 
         nDataOffset += 8;
@@ -936,7 +946,7 @@ HFAField::ExtractInstValue( const char * pszField, int nIndexValue,
           dfDoubleRet = nIntRet;
       }
       break;
-        
+
       case 't':
       case 'l':
       {
@@ -952,7 +962,7 @@ HFAField::ExtractInstValue( const char * pszField, int nIndexValue,
           dfDoubleRet = nIntRet;
       }
       break;
-      
+
       case 'L':
       {
           GInt32	nNumber;
@@ -967,7 +977,7 @@ HFAField::ExtractInstValue( const char * pszField, int nIndexValue,
           dfDoubleRet = nIntRet;
       }
       break;
-      
+
       case 'f':
       {
           float		fNumber;
@@ -982,7 +992,7 @@ HFAField::ExtractInstValue( const char * pszField, int nIndexValue,
           nIntRet = (int) fNumber;
       }
       break;
-        
+
       case 'd':
       {
           double	dfNumber;
@@ -1005,22 +1015,26 @@ HFAField::ExtractInstValue( const char * pszField, int nIndexValue,
 
           if( nDataSize < 12 )
               return FALSE;
-        
+
           memcpy( &nRows, pabyData, 4 );
           HFAStandard( 4, &nRows );
           memcpy( &nColumns, pabyData+4, 4 );
           HFAStandard( 4, &nColumns );
           memcpy( &nBaseItemType, pabyData+8, 2 );
           HFAStandard( 2, &nBaseItemType );
-          // We ignore the 2 byte objecttype value. 
+          // We ignore the 2 byte objecttype value.
 
-          if( nIndexValue < -3 || nIndexValue >= nRows * nColumns )
+          if( nIndexValue < -3 ||
+              nRows <= 0 ||
+              nColumns <= 0 ||
+              nRows > INT_MAX / nColumns ||
+              nIndexValue >= nRows * nColumns )
               return FALSE;
 
           pabyData += 12;
           nDataSize -= 12;
 
-          if( nIndexValue == -3 ) 
+          if( nIndexValue == -3 )
           {
               dfDoubleRet = nIntRet = nBaseItemType;
           }
@@ -1261,10 +1275,10 @@ HFAField::ExtractInstValue( const char * pszField, int nIndexValue,
             /* not go here, but that can happen if the file is corrupted */
             /* so reserve the first 8 bytes before the string to contain null bytes */
             memset(szNumberString, 0, 8);
-            CPLsprintf( szNumberString + 8, "%.14g", dfDoubleRet );
+            CPLsnprintf( szNumberString + 8, sizeof(szNumberString) - 8, "%.14g", dfDoubleRet );
             pszStringRet = szNumberString + 8;
         }
-        
+
         *((char **) pReqReturn) = pszStringRet;
         return( TRUE );
     }
@@ -1304,7 +1318,7 @@ int HFAField::GetInstBytes( GByte *pabyData, int nDataSize )
 {
     int		nCount;
     int		nInstBytes = 0;
-    
+
     if( nBytes > -1 )
         return nBytes;
 
@@ -1335,32 +1349,39 @@ int HFAField::GetInstBytes( GByte *pabyData, int nDataSize )
 
         GInt32 nRows, nColumns;
         GInt16 nBaseItemType;
-        
+
         memcpy( &nRows, pabyData, 4 );
         HFAStandard( 4, &nRows );
         memcpy( &nColumns, pabyData+4, 4 );
         HFAStandard( 4, &nColumns );
         memcpy( &nBaseItemType, pabyData+8, 2 );
         HFAStandard( 2, &nBaseItemType );
+        if( nBaseItemType < EPT_MIN || nBaseItemType > EPT_MAX )
+            return -1;
+        EPTType eBaseItemType = static_cast<EPTType>(nBaseItemType);
 
         nInstBytes += 12;
-        
+
         if (nRows < 0 || nColumns < 0)
             return -1;
         if (nColumns != 0 && nRows > INT_MAX / nColumns)
             return -1;
-        if (nColumns != 0 && ((HFAGetDataTypeBits(nBaseItemType) + 7) / 8) * nRows > INT_MAX / nColumns)
+        if( nRows != 0 && ((HFAGetDataTypeBits(eBaseItemType) + 7) / 8) > INT_MAX / nRows )
+            return -1;
+        if (nColumns != 0 && ((HFAGetDataTypeBits(eBaseItemType) + 7) / 8) * nRows > INT_MAX / nColumns)
             return -1;
-        if (((HFAGetDataTypeBits(nBaseItemType) + 7) / 8) * nRows * nColumns > INT_MAX - nInstBytes)
+        if (((HFAGetDataTypeBits(eBaseItemType) + 7) / 8) * nRows * nColumns > INT_MAX - nInstBytes)
             return -1;
 
-        nInstBytes += 
-            ((HFAGetDataTypeBits(nBaseItemType) + 7) / 8) * nRows * nColumns;
+        nInstBytes +=
+            ((HFAGetDataTypeBits(eBaseItemType) + 7) / 8) * nRows * nColumns;
     }
     else if( poItemObjectType == NULL )
     {
         if (nCount != 0 && HFADictionary::GetItemSize(chItemType) > INT_MAX / nCount)
             return -1;
+        if( nCount * HFADictionary::GetItemSize(chItemType) > INT_MAX - nInstBytes )
+            return -1;
         nInstBytes += nCount * HFADictionary::GetItemSize(chItemType);
     }
     else
@@ -1439,7 +1460,7 @@ int HFAField::GetInstCount( GByte * pabyData, int nDataSize )
 /*                           DumpInstValue()                            */
 /************************************************************************/
 
-void HFAField::DumpInstValue( FILE *fpOut, 
+void HFAField::DumpInstValue( FILE *fpOut,
                            GByte *pabyData, GUInt32 nDataOffset, int nDataSize,
                            const char *pszPrefix )
 
@@ -1459,16 +1480,16 @@ void HFAField::DumpInstValue( FILE *fpOut,
         if( ExtractInstValue( NULL, 0,
                               pabyData, nDataOffset, nDataSize,
                               's', &pReturn ) )
-            VSIFPrintf( fpOut, "%s%s = `%s'\n",
+            CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "%s%s = `%s'\n",
                         pszPrefix, pszFieldName,
-                        (char *) pReturn );
+                        (char *) pReturn ));
         else
-            VSIFPrintf( fpOut, "%s%s = (access failed)\n",
-                        pszPrefix, pszFieldName );
+            CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "%s%s = (access failed)\n",
+                        pszPrefix, pszFieldName ));
 
         return;
     }
-            
+
 /* -------------------------------------------------------------------- */
 /*      For BASEDATA objects, we want to first dump their dimension     */
 /*      and type.                                                       */
@@ -1476,36 +1497,38 @@ void HFAField::DumpInstValue( FILE *fpOut,
     if( chItemType == 'b' )
     {
         int nDataType, nRows, nColumns;
-        int bSuccess = ExtractInstValue( NULL, -3, pabyData, nDataOffset, 
+        int bSuccess = ExtractInstValue( NULL, -3, pabyData, nDataOffset,
                           nDataSize, 'i', &nDataType );
         if (bSuccess)
         {
-            ExtractInstValue( NULL, -2, pabyData, nDataOffset, 
+            ExtractInstValue( NULL, -2, pabyData, nDataOffset,
                             nDataSize, 'i', &nColumns );
-            ExtractInstValue( NULL, -1, pabyData, nDataOffset, 
+            ExtractInstValue( NULL, -1, pabyData, nDataOffset,
                             nDataSize, 'i', &nRows );
-            VSIFPrintf( fpOut, "%sBASEDATA(%s): %dx%d of %s\n", 
+            CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "%sBASEDATA(%s): %dx%d of %s\n",
                         pszPrefix, pszFieldName,
-                        nColumns, nRows, HFAGetDataTypeName( nDataType ) );
+                        nColumns, nRows,
+                        (nDataType >= EPT_MIN && nDataType <= EPT_MAX) ?
+                            HFAGetDataTypeName( static_cast<EPTType>(nDataType) ): "invalid type" ));
         }
         else
         {
-            VSIFPrintf( fpOut, "%sBASEDATA(%s): empty\n", 
-                        pszPrefix, pszFieldName );
+            CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "%sBASEDATA(%s): empty\n",
+                        pszPrefix, pszFieldName ));
         }
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Dump each entry in the field array.                             */
 /* -------------------------------------------------------------------- */
     for( iEntry = 0; iEntry < MIN(MAX_ENTRY_REPORT,nEntries); iEntry++ )
     {
         if( nEntries == 1 )
-            VSIFPrintf( fpOut, "%s%s = ", pszPrefix, pszFieldName );
+            CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "%s%s = ", pszPrefix, pszFieldName ));
         else
-            VSIFPrintf( fpOut, "%s%s[%d] = ",
-                        pszPrefix, pszFieldName, iEntry );
-        
+            CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "%s%s[%d] = ",
+                        pszPrefix, pszFieldName, iEntry ));
+
         switch( chItemType )
         {
           case 'f':
@@ -1515,9 +1538,9 @@ void HFAField::DumpInstValue( FILE *fpOut,
               if( ExtractInstValue( NULL, iEntry,
                                     pabyData, nDataOffset, nDataSize,
                                     'd', &dfValue ) )
-                  VSIFPrintf( fpOut, "%f\n", dfValue );
+                  CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "%f\n", dfValue ));
               else
-                  VSIFPrintf( fpOut, "(access failed)\n" );
+                  CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "(access failed)\n" ));
           }
           break;
 
@@ -1525,12 +1548,12 @@ void HFAField::DumpInstValue( FILE *fpOut,
           {
               double dfValue;
 
-              if( ExtractInstValue( NULL, iEntry, 
-                                    pabyData, nDataOffset, nDataSize, 
+              if( ExtractInstValue( NULL, iEntry,
+                                    pabyData, nDataOffset, nDataSize,
                                     'd', &dfValue ) )
-                  VSIFPrintf( fpOut, "%s%.15g\n", pszPrefix, dfValue );
+                  CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "%s%.15g\n", pszPrefix, dfValue ));
               else
-                  VSIFPrintf( fpOut, "%s(access failed)\n", pszPrefix );
+                  CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "%s(access failed)\n", pszPrefix ));
           }
           break;
 
@@ -1538,9 +1561,9 @@ void HFAField::DumpInstValue( FILE *fpOut,
             if( ExtractInstValue( NULL, iEntry,
                                   pabyData, nDataOffset, nDataSize,
                                   's', &pReturn ) )
-                VSIFPrintf( fpOut, "%s\n", (char *) pReturn );
+                CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "%s\n", (char *) pReturn ));
             else
-                VSIFPrintf( fpOut, "(access failed)\n" );
+                CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "(access failed)\n" ));
             break;
 
           case 'o':
@@ -1548,18 +1571,18 @@ void HFAField::DumpInstValue( FILE *fpOut,
                                    pabyData, nDataOffset, nDataSize,
                                    'p', &pReturn ) )
             {
-                VSIFPrintf( fpOut, "(access failed)\n" );
+                CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "(access failed)\n" ));
             }
             else
             {
                 int		nByteOffset;
 
-                VSIFPrintf( fpOut, "\n" );
-                
-                nByteOffset = ((GByte *) pReturn) - pabyData;
-            
-                sprintf( szLongFieldName, "%s    ", pszPrefix );
-            
+                CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "\n" ));
+
+                nByteOffset = static_cast<int>(((GByte *) pReturn) - pabyData);
+
+                snprintf( szLongFieldName, sizeof(szLongFieldName), "%s    ", pszPrefix );
+
                 if( poItemObjectType )
                     poItemObjectType->DumpInstValue( fpOut,
                                                      pabyData + nByteOffset,
@@ -1576,9 +1599,9 @@ void HFAField::DumpInstValue( FILE *fpOut,
               if( ExtractInstValue( NULL, iEntry,
                                     pabyData, nDataOffset, nDataSize,
                                     'i', &nIntValue ) )
-                  VSIFPrintf( fpOut, "%d\n", nIntValue );
+                  CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "%d\n", nIntValue ));
               else
-                  VSIFPrintf( fpOut, "(access failed)\n" );
+                  CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "(access failed)\n" ));
           }
           break;
         }
@@ -1588,6 +1611,6 @@ void HFAField::DumpInstValue( FILE *fpOut,
         printf( "%s ... remaining instances omitted ...\n", pszPrefix );
 
     if( nEntries == 0 )
-        VSIFPrintf( fpOut, "%s%s = (no values)\n", pszPrefix, pszFieldName );
+        CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "%s%s = (no values)\n", pszPrefix, pszFieldName ));
 
 }
diff --git a/frmts/hfa/hfaopen.cpp b/frmts/hfa/hfaopen.cpp
index 0026775..b114325 100644
--- a/frmts/hfa/hfaopen.cpp
+++ b/frmts/hfa/hfaopen.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfaopen.cpp 28831 2015-04-01 16:46:05Z rouault $
+ * $Id: hfaopen.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Supporting functions for HFA (.img) ... main (C callable) API
@@ -31,7 +31,7 @@
  *
  * hfaopen.cpp
  *
- * Supporting routines for reading Erdas Imagine (.imf) Heirarchical
+ * Supporting routines for reading Erdas Imagine (.imf) Hierarchical
  * File Architecture files.  This is intended to be a library independent
  * of the GDAL core, but dependent on the Common Portability Library.
  *
@@ -42,10 +42,10 @@
 #include <limits.h>
 #include <vector>
 
-CPL_CVSID("$Id: hfaopen.cpp 28831 2015-04-01 16:46:05Z rouault $");
+CPL_CVSID("$Id: hfaopen.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 
-static const char *apszAuxMetadataItems[] = {
+static const char * const apszAuxMetadataItems[] = {
 
 // node/entry            field_name                  metadata_key       type
 
@@ -66,7 +66,7 @@ static const char *apszAuxMetadataItems[] = {
 };
 
 
-const char ** GetHFAAuxMetaDataList()
+const char * const * GetHFAAuxMetaDataList()
 {
     return apszAuxMetadataItems;
 }
@@ -83,9 +83,13 @@ static char * HFAGetDictionary( HFAHandle hHFA )
     char	*pszDictionary = (char *) CPLMalloc(nDictMax);
     int		nDictSize = 0;
 
-    VSIFSeekL( hHFA->fp, hHFA->nDictionaryPos, SEEK_SET );
+    if( VSIFSeekL( hHFA->fp, hHFA->nDictionaryPos, SEEK_SET ) < 0 )
+    {
+        pszDictionary[nDictSize] = '\0';
+        return pszDictionary;
+    }
 
-    while( TRUE )
+    while( true )
     {
         if( nDictSize >= nDictMax-1 )
         {
@@ -147,16 +151,16 @@ HFAHandle HFAOpen( const char * pszFilename, const char * pszAccess )
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Attempt to read 16 byte header failed for\n%s.",
                   pszFilename );
-
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
         return NULL;
     }
 
-    if( !EQUALN(szHeader,"EHFA_HEADER_TAG",15) )
+    if( !STARTS_WITH_CI(szHeader, "EHFA_HEADER_TAG") )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "File %s is not an Imagine HFA file ... header wrong.",
                   pszFilename );
-
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
         return NULL;
     }
 
@@ -177,32 +181,38 @@ HFAHandle HFAOpen( const char * pszFilename, const char * pszAccess )
 /* -------------------------------------------------------------------- */
 /*	Where is the header?						*/
 /* -------------------------------------------------------------------- */
-    VSIFReadL( &nHeaderPos, sizeof(GInt32), 1, fp );
+    bool bRet = VSIFReadL( &nHeaderPos, sizeof(GInt32), 1, fp ) > 0;
     HFAStandard( 4, &nHeaderPos );
 
 /* -------------------------------------------------------------------- */
 /*      Read the header.                                                */
 /* -------------------------------------------------------------------- */
-    VSIFSeekL( fp, nHeaderPos, SEEK_SET );
+    bRet &= VSIFSeekL( fp, nHeaderPos, SEEK_SET ) >= 0;
 
-    VSIFReadL( &(psInfo->nVersion), sizeof(GInt32), 1, fp );
+    bRet &= VSIFReadL( &(psInfo->nVersion), sizeof(GInt32), 1, fp ) > 0;
     HFAStandard( 4, &(psInfo->nVersion) );
 
-    VSIFReadL( szHeader, 4, 1, fp ); /* skip freeList */
+    bRet &= VSIFReadL( szHeader, 4, 1, fp ) > 0; /* skip freeList */
 
-    VSIFReadL( &(psInfo->nRootPos), sizeof(GInt32), 1, fp );
+    bRet &= VSIFReadL( &(psInfo->nRootPos), sizeof(GInt32), 1, fp ) > 0;
     HFAStandard( 4, &(psInfo->nRootPos) );
 
-    VSIFReadL( &(psInfo->nEntryHeaderLength), sizeof(GInt16), 1, fp );
+    bRet &= VSIFReadL( &(psInfo->nEntryHeaderLength), sizeof(GInt16), 1, fp ) > 0;
     HFAStandard( 2, &(psInfo->nEntryHeaderLength) );
 
-    VSIFReadL( &(psInfo->nDictionaryPos), sizeof(GInt32), 1, fp );
+    bRet &= VSIFReadL( &(psInfo->nDictionaryPos), sizeof(GInt32), 1, fp ) > 0;
     HFAStandard( 4, &(psInfo->nDictionaryPos) );
 
 /* -------------------------------------------------------------------- */
 /*      Collect file size.                                              */
 /* -------------------------------------------------------------------- */
-    VSIFSeekL( fp, 0, SEEK_END );
+    bRet &= VSIFSeekL( fp, 0, SEEK_END ) >= 0;
+    if( !bRet )
+    {
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
+        CPLFree(psInfo);
+        return NULL;
+    }
     psInfo->nEndOfFile = (GUInt32) VSIFTellL( fp );
 
 /* -------------------------------------------------------------------- */
@@ -211,6 +221,7 @@ HFAHandle HFAOpen( const char * pszFilename, const char * pszAccess )
     psInfo->poRoot = HFAEntry::New( psInfo, psInfo->nRootPos, NULL, NULL );
     if( psInfo->poRoot == NULL )
     {
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
         CPLFree(psInfo);
         return NULL;
     }
@@ -255,8 +266,9 @@ HFAInfo_t *HFACreateDependent( HFAInfo_t *psBase )
     VSILFILE *fp = VSIFOpenL( oRRDFilename, "rb" );
     if( fp != NULL )
     {
-        VSIFCloseL( fp );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
         psBase->psDependent = HFAOpen( oRRDFilename, "rb" );
+        // FIXME? this is not going to be reused but recreated...
     }
 
 /* -------------------------------------------------------------------- */
@@ -264,6 +276,8 @@ HFAInfo_t *HFACreateDependent( HFAInfo_t *psBase )
 /* -------------------------------------------------------------------- */
     HFAInfo_t *psDep;
     psDep = psBase->psDependent = HFACreateLL( oRRDFilename );
+    if( psDep == NULL )
+        return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Add the DependentFile node with the pointer back to the         */
@@ -276,14 +290,14 @@ HFAInfo_t *HFACreateDependent( HFAInfo_t *psBase )
         pszDependentFile = poEntry->GetStringField( "dependent.string" );
     if( pszDependentFile == NULL )
         pszDependentFile = psBase->pszFilename;
-    
-    HFAEntry *poDF = new HFAEntry( psDep, "DependentFile", 
+
+    HFAEntry *poDF = HFAEntry::New( psDep, "DependentFile",
                                    "Eimg_DependentFile", psDep->poRoot );
 
-    poDF->MakeData( strlen(pszDependentFile) + 50 );
+    poDF->MakeData( static_cast<int>(strlen(pszDependentFile) + 50) );
     poDF->SetPosition();
     poDF->SetStringField( "dependent.string", pszDependentFile );
-    
+
     return psDep;
 }
 
@@ -318,7 +332,7 @@ HFAInfo_t *HFAGetDependent( HFAInfo_t *psBase, const char *pszFilename )
     fp = VSIFOpenL( pszDependent, pszMode );
     if( fp != NULL )
     {
-        VSIFCloseL( fp );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
         psBase->psDependent = HFAOpen( pszDependent, pszMode );
     }
 
@@ -384,20 +398,26 @@ CPLErr HFAParseBandInfo( HFAInfo_t *psInfo )
 /*                              HFAClose()                              */
 /************************************************************************/
 
-void HFAClose( HFAHandle hHFA )
+int HFAClose( HFAHandle hHFA )
 
 {
+    int nRet = 0;
     int		i;
 
-    if( hHFA->eAccess == HFA_Update && (hHFA->bTreeDirty || hHFA->poDictionary->bDictionaryTextDirty) )
+    if( hHFA->eAccess == HFA_Update && (hHFA->bTreeDirty ||
+        (hHFA->poDictionary != NULL && hHFA->poDictionary->bDictionaryTextDirty)) )
         HFAFlush( hHFA );
 
     if( hHFA->psDependent != NULL )
-        HFAClose( hHFA->psDependent );
+    {
+        if( HFAClose( hHFA->psDependent ) != 0 )
+            nRet = -1;
+    }
 
     delete hHFA->poRoot;
 
-    VSIFCloseL( hHFA->fp );
+    if( VSIFCloseL( hHFA->fp ) != 0 )
+        nRet = -1;
 
     if( hHFA->poDictionary != NULL )
         delete hHFA->poDictionary;
@@ -441,6 +461,7 @@ void HFAClose( HFAHandle hHFA )
     }
 
     CPLFree( hHFA );
+    return nRet;
 }
 
 /************************************************************************/
@@ -448,6 +469,7 @@ void HFAClose( HFAHandle hHFA )
 /*  Used from HFADelete() function.                                     */
 /************************************************************************/
 
+static
 CPLErr HFARemove( const char *pszFilename )
 
 {
@@ -509,7 +531,7 @@ CPLErr HFADelete( const char *pszFilename )
                                             pszRawFilename, NULL ) );
         }
 
-        HFAClose( psInfo );
+        CPL_IGNORE_RET_VAL(HFAClose( psInfo ));
     }
     return HFARemove( pszFilename );
 }
@@ -535,7 +557,7 @@ CPLErr HFAGetRasterInfo( HFAHandle hHFA, int * pnXSize, int * pnYSize,
 /*                           HFAGetBandInfo()                           */
 /************************************************************************/
 
-CPLErr HFAGetBandInfo( HFAHandle hHFA, int nBand, int * pnDataType,
+CPLErr HFAGetBandInfo( HFAHandle hHFA, int nBand, EPTType * peDataType,
                        int * pnBlockXSize, int * pnBlockYSize,
                        int *pnCompressionType )
 
@@ -548,8 +570,8 @@ CPLErr HFAGetBandInfo( HFAHandle hHFA, int nBand, int * pnDataType,
 
     HFABand *poBand = hHFA->papoBand[nBand-1];
 
-    if( pnDataType != NULL )
-        *pnDataType = poBand->nDataType;
+    if( peDataType != NULL )
+        *peDataType = poBand->eDataType;
 
     if( pnBlockXSize != NULL )
         *pnBlockXSize = poBand->nBlockXSize;
@@ -563,7 +585,7 @@ CPLErr HFAGetBandInfo( HFAHandle hHFA, int nBand, int * pnDataType,
     if( pnCompressionType != NULL )
     {
         HFAEntry	*poDMS;
-    
+
         *pnCompressionType = 0;
 
         poDMS = poBand->poNode->GetNamedChild( "RasterDMS" );
@@ -603,24 +625,24 @@ int HFAGetBandNoData( HFAHandle hHFA, int nBand, double *pdfNoData )
     return poBand->bNoDataSet;
 }
 
-/************************************************************************/ 
-/*                          HFASetBandNoData()                          */ 
-/*                                                                      */ 
-/*      attempts to set a no-data value on the given band               */ 
-/************************************************************************/ 
+/************************************************************************/
+/*                          HFASetBandNoData()                          */
+/*                                                                      */
+/*      attempts to set a no-data value on the given band               */
+/************************************************************************/
 
-CPLErr HFASetBandNoData( HFAHandle hHFA, int nBand, double dfValue ) 
+CPLErr HFASetBandNoData( HFAHandle hHFA, int nBand, double dfValue )
 
-{ 
-    if ( nBand < 0 || nBand > hHFA->nBands ) 
-    { 
-        CPLAssert( FALSE ); 
-        return CE_Failure; 
-    } 
+{
+    if ( nBand < 0 || nBand > hHFA->nBands )
+    {
+        CPLAssert( FALSE );
+        return CE_Failure;
+    }
 
-    HFABand *poBand = hHFA->papoBand[nBand - 1]; 
+    HFABand *poBand = hHFA->papoBand[nBand - 1];
 
-    return poBand->SetNoDataValue( dfValue ); 
+    return poBand->SetNoDataValue( dfValue );
 }
 
 /************************************************************************/
@@ -651,7 +673,7 @@ int HFAGetOverviewCount( HFAHandle hHFA, int nBand )
 CPLErr HFAGetOverviewInfo( HFAHandle hHFA, int nBand, int iOverview,
                            int * pnXSize, int * pnYSize,
                            int * pnBlockXSize, int * pnBlockYSize,
-                           int * pnHFADataType )
+                           EPTType * peHFADataType )
 
 {
     HFABand	*poBand;
@@ -688,8 +710,8 @@ CPLErr HFAGetOverviewInfo( HFAHandle hHFA, int nBand, int iOverview,
     if( pnBlockYSize != NULL )
         *pnBlockYSize = poBand->nBlockYSize;
 
-    if( pnHFADataType != NULL )
-        *pnHFADataType = poBand->nDataType;
+    if( peHFADataType != NULL )
+        *peHFADataType = poBand->eDataType;
 
     return( CE_None );
 }
@@ -808,10 +830,10 @@ void HFASetBandName( HFAHandle hHFA, int nBand, const char *pszName )
 /*                         HFAGetDataTypeBits()                         */
 /************************************************************************/
 
-int HFAGetDataTypeBits( int nDataType )
+int HFAGetDataTypeBits( EPTType eDataType )
 
 {
-    switch( nDataType )
+    switch( eDataType )
     {
       case EPT_u1:
         return 1;
@@ -843,17 +865,18 @@ int HFAGetDataTypeBits( int nDataType )
         return 128;
     }
 
-    return 0;
+    CPLAssert(FALSE);
+    return 1;
 }
 
 /************************************************************************/
 /*                         HFAGetDataTypeName()                         */
 /************************************************************************/
 
-const char *HFAGetDataTypeName( int nDataType )
+const char *HFAGetDataTypeName( EPTType eDataType )
 
 {
-    switch( nDataType )
+    switch( eDataType )
     {
       case EPT_u1:
         return "u1";
@@ -895,6 +918,7 @@ const char *HFAGetDataTypeName( int nDataType )
         return "c128";
 
       default:
+        CPLAssert(FALSE);
         return "unknown";
     }
 }
@@ -967,7 +991,7 @@ const Eprj_MapInfo *HFAGetMapInfo( HFAHandle hHFA )
    psMapInfo->pixelSize.height =
        poMIEntry->GetDoubleField("pixelSize.height",&eErr);
 
-   // The following is basically a hack to get files with 
+   // The following is basically a hack to get files with
    // non-standard MapInfo's that misname the pixelSize fields. (#3338)
    if( eErr != CE_None )
    {
@@ -991,7 +1015,7 @@ const Eprj_MapInfo *HFAGetMapInfo( HFAHandle hHFA )
 static int HFAInvGeoTransform( double *gt_in, double *gt_out )
 
 {
-    double	det, inv_det;
+    double det, inv_det;
 
     /* we assume a 3rd row that is [1 0 0] */
 
@@ -1004,7 +1028,7 @@ static int HFAInvGeoTransform( double *gt_in, double *gt_out )
 
     inv_det = 1.0 / det;
 
-    /* compute adjoint, and devide by determinate */
+    /* compute adjoint, and divide by determinate */
 
     gt_out[1] =  gt_in[5] * inv_det;
     gt_out[4] = -gt_in[4] * inv_det;
@@ -1077,9 +1101,9 @@ int HFAGetGeoTransform( HFAHandle hHFA, double *padfGeoTransform )
     if( hHFA->nBands == 0 )
         return FALSE;
 
-    HFAEntry *poXForm0 = 
+    HFAEntry *poXForm0 =
         hHFA->papoBand[0]->poNode->GetNamedChild( "MapToPixelXForm.XForm0" );
-    
+
     if( poXForm0 == NULL )
         return FALSE;
 
@@ -1095,7 +1119,7 @@ int HFAGetGeoTransform( HFAHandle hHFA, double *padfGeoTransform )
         return FALSE;
 
     // we should check that the exponent list is 0 0 1 0 0 1 but
-    // we don't because we are lazy 
+    // we don't because we are lazy
 
     // fetch geotransform values.
     double adfXForm[6];
@@ -1109,11 +1133,12 @@ int HFAGetGeoTransform( HFAHandle hHFA, double *padfGeoTransform )
 
     // invert
 
-    HFAInvGeoTransform( adfXForm, padfGeoTransform );
+    if( !HFAInvGeoTransform( adfXForm, padfGeoTransform ) )
+        memset( padfGeoTransform, 0, 6 * sizeof(double) );
 
     // Adjust origin from center of top left pixel to top left corner
     // of top left pixel.
-    
+
     padfGeoTransform[0] -= padfGeoTransform[1] * 0.5;
     padfGeoTransform[0] -= padfGeoTransform[2] * 0.5;
     padfGeoTransform[3] -= padfGeoTransform[4] * 0.5;
@@ -1142,7 +1167,7 @@ CPLErr HFASetMapInfo( HFAHandle hHFA, const Eprj_MapInfo *poMapInfo )
         poMIEntry = hHFA->papoBand[iBand]->poNode->GetNamedChild( "Map_Info" );
         if( poMIEntry == NULL )
         {
-            poMIEntry = new HFAEntry( hHFA, "Map_Info", "Eprj_MapInfo",
+            poMIEntry = HFAEntry::New( hHFA, "Map_Info", "Eprj_MapInfo",
                                       hHFA->papoBand[iBand]->poNode );
         }
 
@@ -1154,9 +1179,9 @@ CPLErr HFASetMapInfo( HFAHandle hHFA, const Eprj_MapInfo *poMapInfo )
         int	nSize;
         GByte   *pabyData;
 
-        nSize = 48 + 40
+        nSize = static_cast<int>(48 + 40
             + strlen(poMapInfo->proName) + 1
-            + strlen(poMapInfo->units) + 1;
+            + strlen(poMapInfo->units) + 1);
 
         pabyData = poMIEntry->MakeData( nSize );
         memset( pabyData, 0, nSize );
@@ -1192,12 +1217,12 @@ CPLErr HFASetMapInfo( HFAHandle hHFA, const Eprj_MapInfo *poMapInfo )
 /************************************************************************/
 /*                           HFAGetPEString()                           */
 /*                                                                      */
-/*      Some files have a ProjectionX node contining the ESRI style     */
+/*      Some files have a ProjectionX node containing the ESRI style    */
 /*      PE_STRING.  This function allows fetching from it.              */
 /************************************************************************/
 
 char *HFAGetPEString( HFAHandle hHFA )
- 
+
 {
     if( hHFA->nBands == 0 )
         return NULL;
@@ -1223,8 +1248,8 @@ char *HFAGetPEString( HFAHandle hHFA )
     GByte *pabyData = poProX->GetData();
     int    nDataSize = poProX->GetDataSize();
 
-    while( nDataSize > 10 
-           && !EQUALN((const char *) pabyData,"PE_COORDSYS,.",13) ) {
+    while( nDataSize > 10
+           && !STARTS_WITH_CI((const char *) pabyData, "PE_COORDSYS,.") ) {
         pabyData++;
         nDataSize--;
     }
@@ -1236,7 +1261,7 @@ char *HFAGetPEString( HFAHandle hHFA )
 /*      Skip ahead to the actual string.                                */
 /* -------------------------------------------------------------------- */
     pabyData += 30;
-    nDataSize -= 30;
+    /*nDataSize -= 30;*/
 
     return CPLStrdup( (const char *) pabyData );
 }
@@ -1265,7 +1290,7 @@ CPLErr HFASetPEString( HFAHandle hHFA, const char *pszPEString )
 
 /* -------------------------------------------------------------------- */
 /*      If we are setting an empty string then a missing entry is       */
-/*      equivelent.                                                     */
+/*      equivalent.                                                     */
 /* -------------------------------------------------------------------- */
         if( strlen(pszPEString) == 0 && poProX == NULL )
             continue;
@@ -1275,17 +1300,17 @@ CPLErr HFASetPEString( HFAHandle hHFA, const char *pszPEString )
 /* -------------------------------------------------------------------- */
         if( poProX == NULL )
         {
-            poProX = new HFAEntry( hHFA, "ProjectionX","Eprj_MapProjection842",
+            poProX = HFAEntry::New( hHFA, "ProjectionX","Eprj_MapProjection842",
                                    hHFA->papoBand[iBand]->poNode );
-            if( poProX == NULL || poProX->GetTypeObject() == NULL )
+            if( poProX->GetTypeObject() == NULL )
                 return CE_Failure;
         }
 
 /* -------------------------------------------------------------------- */
 /*      Prepare the data area with some extra space just in case.       */
 /* -------------------------------------------------------------------- */
-        GByte *pabyData = poProX->MakeData( 700 + strlen(pszPEString) );
-        if( !pabyData ) 
+        GByte *pabyData = poProX->MakeData( static_cast<int>(700 + strlen(pszPEString)) );
+        if( !pabyData )
           return CE_Failure;
 
         memset( pabyData, 0, 250+strlen(pszPEString) );
@@ -1293,7 +1318,7 @@ CPLErr HFASetPEString( HFAHandle hHFA, const char *pszPEString )
         poProX->SetPosition();
 
         poProX->SetStringField( "projection.type.string", "PE_COORDSYS" );
-        poProX->SetStringField( "projection.MIFDictionary.string", 
+        poProX->SetStringField( "projection.MIFDictionary.string",
                                 "{0:pcstring,}Emif_String,{1:x{0:pcstring,}Emif_String,coordSys,}PE_COORDSYS,." );
 
 /* -------------------------------------------------------------------- */
@@ -1306,8 +1331,8 @@ CPLErr HFASetPEString( HFAHandle hHFA, const char *pszPEString )
         GUInt32   iOffset = poProX->GetDataPos();
         GUInt32   nSize;
 
-        while( nDataSize > 10 
-               && !EQUALN((const char *) pabyData,"PE_COORDSYS,.",13) ) {
+        while( nDataSize > 10
+               && !STARTS_WITH_CI((const char *) pabyData, "PE_COORDSYS,.") ) {
             pabyData++;
             nDataSize--;
             iOffset++;
@@ -1317,18 +1342,18 @@ CPLErr HFASetPEString( HFAHandle hHFA, const char *pszPEString )
 
         pabyData += 14;
         iOffset += 14;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Set the size and offset of the mifobject.                       */
 /* -------------------------------------------------------------------- */
         iOffset += 8;
 
-        nSize = strlen(pszPEString) + 9;
+        nSize = static_cast<GUInt32>(strlen(pszPEString) + 9);
 
         HFAStandard( 4, &nSize );
         memcpy( pabyData, &nSize, 4 );
         pabyData += 4;
-    
+
         HFAStandard( 4, &iOffset );
         memcpy( pabyData, &iOffset, 4 );
         pabyData += 4;
@@ -1336,8 +1361,8 @@ CPLErr HFASetPEString( HFAHandle hHFA, const char *pszPEString )
 /* -------------------------------------------------------------------- */
 /*      Set the size and offset of the string value.                    */
 /* -------------------------------------------------------------------- */
-        nSize = strlen(pszPEString) + 1;
-    
+        nSize = static_cast<GUInt32>(strlen(pszPEString) + 1);
+
         HFAStandard( 4, &nSize );
         memcpy( pabyData, &nSize, 4 );
         pabyData += 4;
@@ -1351,7 +1376,7 @@ CPLErr HFASetPEString( HFAHandle hHFA, const char *pszPEString )
 /*      Place the string itself.                                        */
 /* -------------------------------------------------------------------- */
         memcpy( pabyData, pszPEString, strlen(pszPEString)+1 );
-    
+
         poProX->SetStringField( "title.string", "PE" );
     }
 
@@ -1403,7 +1428,7 @@ const Eprj_ProParameters *HFAGetProParameters( HFAHandle hHFA )
     {
         char	szFieldName[40];
 
-        sprintf( szFieldName, "proParams[%d]", i );
+        snprintf( szFieldName, sizeof(szFieldName), "proParams[%d]", i );
         psProParms->proParams[i] = poMIEntry->GetDoubleField(szFieldName);
     }
 
@@ -1441,7 +1466,7 @@ CPLErr HFASetProParameters( HFAHandle hHFA, const Eprj_ProParameters *poPro )
         poMIEntry = hHFA->papoBand[iBand]->poNode->GetNamedChild("Projection");
         if( poMIEntry == NULL )
         {
-            poMIEntry = new HFAEntry( hHFA, "Projection","Eprj_ProParameters",
+            poMIEntry = HFAEntry::New( hHFA, "Projection","Eprj_ProParameters",
                                       hHFA->papoBand[iBand]->poNode );
         }
 
@@ -1453,12 +1478,12 @@ CPLErr HFASetProParameters( HFAHandle hHFA, const Eprj_ProParameters *poPro )
         int	nSize;
         GByte   *pabyData;
 
-        nSize = 34 + 15 * 8
+        nSize = static_cast<int>(34 + 15 * 8
             + 8 + strlen(poPro->proName) + 1
-            + 32 + 8 + strlen(poPro->proSpheroid.sphereName) + 1;
+            + 32 + 8 + strlen(poPro->proSpheroid.sphereName) + 1);
 
         if( poPro->proExeName != NULL )
-            nSize += strlen(poPro->proExeName) + 1;
+            nSize += static_cast<int>(strlen(poPro->proExeName) + 1);
 
         pabyData = poMIEntry->MakeData( nSize );
         if(!pabyData)
@@ -1545,13 +1570,20 @@ const Eprj_Datum *HFAGetDatum( HFAHandle hHFA )
 /*      Fetch the fields.                                               */
 /* -------------------------------------------------------------------- */
     psDatum->datumname = CPLStrdup(poMIEntry->GetStringField("datumname"));
-    psDatum->type = (Eprj_DatumType) poMIEntry->GetIntField("type");
+    int nDatumType = poMIEntry->GetIntField("type");
+    if( nDatumType < 0 || nDatumType > EPRJ_DATUM_NONE )
+    {
+        CPLDebug("HFA", "Invalid value for datum type: %d", nDatumType);
+        psDatum->type = EPRJ_DATUM_NONE;
+    }
+    else
+        psDatum->type = static_cast<Eprj_DatumType>(nDatumType);
 
     for( i = 0; i < 7; i++ )
     {
         char	szFieldName[30];
 
-        sprintf( szFieldName, "params[%d]", i );
+        snprintf( szFieldName, sizeof(szFieldName), "params[%d]", i );
         psDatum->params[i] = poMIEntry->GetDoubleField(szFieldName);
     }
 
@@ -1591,7 +1623,7 @@ CPLErr HFASetDatum( HFAHandle hHFA, const Eprj_Datum *poDatum )
         poDatumEntry = poProParms->GetNamedChild("Datum");
         if( poDatumEntry == NULL )
         {
-            poDatumEntry = new HFAEntry( hHFA, "Datum","Eprj_Datum",
+            poDatumEntry = HFAEntry::New( hHFA, "Datum","Eprj_Datum",
                                       poProParms );
         }
 
@@ -1603,10 +1635,10 @@ CPLErr HFASetDatum( HFAHandle hHFA, const Eprj_Datum *poDatum )
         int	nSize;
         GByte   *pabyData;
 
-        nSize = 26 + strlen(poDatum->datumname) + 1 + 7*8;
+        nSize = static_cast<int>(26 + strlen(poDatum->datumname) + 1 + 7*8);
 
         if( poDatum->gridname != NULL )
-            nSize += strlen(poDatum->gridname) + 1;
+            nSize += static_cast<int>(strlen(poDatum->gridname) + 1);
 
         pabyData = poDatumEntry->MakeData( nSize );
         if(!pabyData)
@@ -1644,7 +1676,7 @@ CPLErr HFASetDatum( HFAHandle hHFA, const Eprj_Datum *poDatum )
 /************************************************************************/
 
 CPLErr HFAGetPCT( HFAHandle hHFA, int nBand, int *pnColors,
-                  double **ppadfRed, double **ppadfGreen, 
+                  double **ppadfRed, double **ppadfGreen,
 		  double **ppadfBlue , double **ppadfAlpha,
                   double **ppadfBins )
 
@@ -1664,7 +1696,7 @@ CPLErr HFAGetPCT( HFAHandle hHFA, int nBand, int *pnColors,
 /************************************************************************/
 
 CPLErr HFASetPCT( HFAHandle hHFA, int nBand, int nColors,
-                  double *padfRed, double *padfGreen, double *padfBlue, 
+                  double *padfRed, double *padfGreen, double *padfBlue,
 		  double *padfAlpha )
 
 {
@@ -1710,7 +1742,7 @@ static void	HFADumpNode( HFAEntry *poEntry, int nIndent, int bVerbose,
                              FILE * fp )
 
 {
-    static char	szSpaces[256];
+    char	szSpaces[256];
     int		i;
 
     for( i = 0; i < nIndent*2; i++ )
@@ -1792,7 +1824,7 @@ void HFAStandard( int nBytes, void * pData )
 /*      file.                                                           */
 /* ==================================================================== */
 
-static const char *aszDefaultDD[] = {
+static const char * const aszDefaultDD[] = {
 "{1:lversion,1:LfreeList,1:LrootEntryPtr,1:sentryHeaderLength,1:LdictionaryPtr,}Ehfa_File,{1:Lnext,1:Lprev,1:Lparent,1:Lchild,1:Ldata,1:ldataSize,64:cname,32:ctype,1:tmodTime,}Ehfa_Entry,{16:clabel,1:LheaderPtr,}Ehfa_HeaderTag,{1:LfreeList,1:lfreeSize,}Ehfa_FreeListNode,{1:lsize,1:Lptr,}Ehfa_Data,{1:lwidth,1:lheight,1:e3:thematic,athematic,fft of real-valued data,layerType,",
 "1:e13:u1,u2,u4,u8,s8,u16,s16,u32,s32,f32,f64,c64,c128,pixelType,1:lblockWidth,1:lblockHeight,}Eimg_Layer,{1:lwidth,1:lheight,1:e3:thematic,athematic,fft of real-valued data,layerType,1:e13:u1,u2,u4,u8,s8,u16,s16,u32,s32,f32,f64,c64,c128,pixelType,1:lblockWidth,1:lblockHeight,}Eimg_Layer_SubSample,{1:e2:raster,vector,type,1:LdictionaryPtr,}Ehfa_Layer,{1:LspaceUsedForRasterData,}ImgFormatInfo831,{1:sfileCode,1:Loffset,1:lsize,1:e2:false,true,logvalid,",
 "1:e2:no compression,ESRI GRID compression,compressionType,}Edms_VirtualBlockInfo,{1:lmin,1:lmax,}Edms_FreeIDList,{1:lnumvirtualblocks,1:lnumobjectsperblock,1:lnextobjectnum,1:e2:no compression,RLC compression,compressionType,0:poEdms_VirtualBlockInfo,blockinfo,0:poEdms_FreeIDList,freelist,1:tmodTime,}Edms_State,{0:pcstring,}Emif_String,{1:oEmif_String,fileName,2:LlayerStackValidFlagsOffset,2:LlayerStackDataOffset,1:LlayerStackCount,1:LlayerStackIndex,}ImgExternalRaster,{1:oEmif_String,a [...]
@@ -1856,11 +1888,11 @@ HFAHandle HFACreateLL( const char * pszFilename )
 /* -------------------------------------------------------------------- */
     GInt32	nHeaderPos;
 
-    VSIFWriteL( (void *) "EHFA_HEADER_TAG", 1, 16, fp );
+    bool bRet = VSIFWriteL( (void *) "EHFA_HEADER_TAG", 1, 16, fp ) > 0;
 
     nHeaderPos = 20;
     HFAStandard( 4, &nHeaderPos );
-    VSIFWriteL( &nHeaderPos, 4, 1, fp );
+    bRet &= VSIFWriteL( &nHeaderPos, 4, 1, fp ) > 0;
 
 /* -------------------------------------------------------------------- */
 /*      Write the Ehfa_File node, locked in at offset 20.               */
@@ -1880,11 +1912,11 @@ HFAHandle HFACreateLL( const char * pszFilename )
     HFAStandard( 2, &nEntryHeaderLength );
     HFAStandard( 4, &nDictionaryPtr );
 
-    VSIFWriteL( &nVersion, 4, 1, fp );
-    VSIFWriteL( &nFreeList, 4, 1, fp );
-    VSIFWriteL( &nRootEntry, 4, 1, fp );
-    VSIFWriteL( &nEntryHeaderLength, 2, 1, fp );
-    VSIFWriteL( &nDictionaryPtr, 4, 1, fp );
+    bRet &= VSIFWriteL( &nVersion, 4, 1, fp ) > 0;
+    bRet &= VSIFWriteL( &nFreeList, 4, 1, fp ) > 0;
+    bRet &= VSIFWriteL( &nRootEntry, 4, 1, fp ) > 0;
+    bRet &= VSIFWriteL( &nEntryHeaderLength, 2, 1, fp ) > 0;
+    bRet &= VSIFWriteL( &nDictionaryPtr, 4, 1, fp ) > 0;
 
 /* -------------------------------------------------------------------- */
 /*      Write the dictionary, locked in at location 38.  Note that      */
@@ -1895,7 +1927,7 @@ HFAHandle HFACreateLL( const char * pszFilename )
     int      nDictLen = 0, iChunk;
 
     for( iChunk = 0; aszDefaultDD[iChunk] != NULL; iChunk++ )
-        nDictLen += strlen(aszDefaultDD[iChunk]);
+        nDictLen += static_cast<int>(strlen(aszDefaultDD[iChunk]));
 
     psInfo->pszDictionary = (char *) CPLMalloc(nDictLen+1);
     psInfo->pszDictionary[0] = '\0';
@@ -1903,8 +1935,13 @@ HFAHandle HFACreateLL( const char * pszFilename )
     for( iChunk = 0; aszDefaultDD[iChunk] != NULL; iChunk++ )
         strcat( psInfo->pszDictionary, aszDefaultDD[iChunk] );
 
-    VSIFWriteL( (void *) psInfo->pszDictionary, 1,
-                strlen(psInfo->pszDictionary)+1, fp );
+    bRet &= VSIFWriteL( (void *) psInfo->pszDictionary,
+                strlen(psInfo->pszDictionary)+1, 1, fp ) > 0;
+    if( !bRet )
+    {
+        CPL_IGNORE_RET_VAL(HFAClose( psInfo ));
+        return NULL;
+    }
 
     psInfo->poDictionary = new HFADictionary( psInfo->pszDictionary );
 
@@ -1994,42 +2031,42 @@ CPLErr HFAFlush( HFAHandle hHFA )
 /*      Flush Dictionary to disk.                                       */
 /* -------------------------------------------------------------------- */
     GUInt32 nNewDictionaryPos = hHFA->nDictionaryPos;
-
+    bool bRet = true;
     if( hHFA->poDictionary->bDictionaryTextDirty )
     {
-        VSIFSeekL( hHFA->fp, 0, SEEK_END );
+        bRet &= VSIFSeekL( hHFA->fp, 0, SEEK_END ) >= 0;
         nNewDictionaryPos = (GUInt32) VSIFTellL( hHFA->fp );
-        VSIFWriteL( hHFA->poDictionary->osDictionaryText.c_str(), 
+        bRet &= VSIFWriteL( hHFA->poDictionary->osDictionaryText.c_str(),
                     strlen(hHFA->poDictionary->osDictionaryText.c_str()) + 1,
-                    1, hHFA->fp );
+                    1, hHFA->fp ) > 0;
         hHFA->poDictionary->bDictionaryTextDirty = FALSE;
     }
 
 /* -------------------------------------------------------------------- */
 /*      do we need to update the Ehfa_File pointer to the root node?    */
 /* -------------------------------------------------------------------- */
-    if( hHFA->nRootPos != hHFA->poRoot->GetFilePos() 
+    if( hHFA->nRootPos != hHFA->poRoot->GetFilePos()
         || nNewDictionaryPos != hHFA->nDictionaryPos )
     {
         GUInt32		nOffset;
         GUInt32         nHeaderPos;
 
-        VSIFSeekL( hHFA->fp, 16, SEEK_SET );
-        VSIFReadL( &nHeaderPos, sizeof(GInt32), 1, hHFA->fp );
+        bRet &= VSIFSeekL( hHFA->fp, 16, SEEK_SET ) >= 0;
+        bRet &= VSIFReadL( &nHeaderPos, sizeof(GInt32), 1, hHFA->fp ) > 0;
         HFAStandard( 4, &nHeaderPos );
 
         nOffset = hHFA->nRootPos = hHFA->poRoot->GetFilePos();
         HFAStandard( 4, &nOffset );
-        VSIFSeekL( hHFA->fp, nHeaderPos+8, SEEK_SET );
-        VSIFWriteL( &nOffset, 4, 1, hHFA->fp );
+        bRet &= VSIFSeekL( hHFA->fp, nHeaderPos+8, SEEK_SET ) >= 0;
+        bRet &= VSIFWriteL( &nOffset, 4, 1, hHFA->fp ) > 0;
 
         nOffset = hHFA->nDictionaryPos = nNewDictionaryPos;
         HFAStandard( 4, &nOffset );
-        VSIFSeekL( hHFA->fp, nHeaderPos+14, SEEK_SET );
-        VSIFWriteL( &nOffset, 4, 1, hHFA->fp );
+        bRet &= VSIFSeekL( hHFA->fp, nHeaderPos+14, SEEK_SET ) >= 0;
+        bRet &= VSIFWriteL( &nOffset, 4, 1, hHFA->fp ) > 0;
     }
 
-    return CE_None;
+    return (bRet) ? CE_None : CE_Failure;
 }
 
 /************************************************************************/
@@ -2045,7 +2082,7 @@ HFACreateLayer( HFAHandle psInfo, HFAEntry *poParent,
                 int bOverview, int nBlockSize,
                 int bCreateCompressed, int bCreateLargeRaster,
                 int bDependentLayer,
-                int nXSize, int nYSize, int nDataType,
+                int nXSize, int nYSize, EPTType eDataType,
                 CPL_UNUSED char **papszOptions,
 
                 // these are only related to external (large) files
@@ -2062,7 +2099,7 @@ HFACreateLayer( HFAHandle psInfo, HFAEntry *poParent,
         pszLayerType = "Eimg_Layer_SubSample";
     else
         pszLayerType = "Eimg_Layer";
-    
+
     if (nBlockSize <= 0)
     {
         CPLError(CE_Failure, CPLE_IllegalArg, "HFACreateLayer : nBlockXSize < 0");
@@ -2078,18 +2115,18 @@ HFACreateLayer( HFAHandle psInfo, HFAEntry *poParent,
     nBlocksPerColumn = (nYSize + nBlockSize - 1) / nBlockSize;
     nBlocks = nBlocksPerRow * nBlocksPerColumn;
     nBytesPerBlock = (nBlockSize * nBlockSize
-                      * HFAGetDataTypeBits(nDataType) + 7) / 8;
+                      * HFAGetDataTypeBits(eDataType) + 7) / 8;
 
 /* -------------------------------------------------------------------- */
 /*      Create the Eimg_Layer for the band.                             */
 /* -------------------------------------------------------------------- */
     poEimg_Layer =
-        new HFAEntry( psInfo, pszLayerName, pszLayerType, poParent );
+        HFAEntry::New( psInfo, pszLayerName, pszLayerType, poParent );
 
     poEimg_Layer->SetIntField( "width", nXSize );
     poEimg_Layer->SetIntField( "height", nYSize );
     poEimg_Layer->SetStringField( "layerType", "athematic" );
-    poEimg_Layer->SetIntField( "pixelType", nDataType );
+    poEimg_Layer->SetIntField( "pixelType", eDataType );
     poEimg_Layer->SetIntField( "blockWidth", nBlockSize );
     poEimg_Layer->SetIntField( "blockHeight", nBlockSize );
 
@@ -2106,7 +2143,7 @@ HFACreateLayer( HFAHandle psInfo, HFAEntry *poParent,
         GByte	*pabyData;
 
         poEdms_State =
-            new HFAEntry( psInfo, "RasterDMS", "Edms_State", poEimg_Layer );
+            HFAEntry::New( psInfo, "RasterDMS", "Edms_State", poEimg_Layer );
 
         nDmsSize = 14 * nBlocks + 38;
         pabyData = poEdms_State->MakeData( nDmsSize );
@@ -2117,10 +2154,10 @@ HFACreateLayer( HFAHandle psInfo, HFAEntry *poParent,
                                    nBlockSize*nBlockSize );
         poEdms_State->SetIntField( "nextobjectnum",
                                    nBlockSize*nBlockSize*nBlocks );
-				  
-        /* Is file compressed or not? */     
+
+        /* Is file compressed or not? */
         if( bCreateCompressed )
-        {				       
+        {
             poEdms_State->SetStringField( "compressionType", "RLC compression" );
         }
         else
@@ -2157,8 +2194,8 @@ HFACreateLayer( HFAHandle psInfo, HFAEntry *poParent,
 
             /* offset */
             if( bCreateCompressed )
-            {				     
-                /* flag it with zero offset - will allocate space when we compress it */  
+            {
+                /* flag it with zero offset - will allocate space when we compress it */
                 nValue = 0;
             }
             else
@@ -2205,21 +2242,21 @@ HFACreateLayer( HFAHandle psInfo, HFAEntry *poParent,
         HFAEntry *poEdms_State;
 
         poEdms_State =
-            new HFAEntry( psInfo, "ExternalRasterDMS",
+            HFAEntry::New( psInfo, "ExternalRasterDMS",
                           "ImgExternalRaster", poEimg_Layer );
-        poEdms_State->MakeData( 8 + strlen(psInfo->pszIGEFilename) + 1 + 6 * 4 );
+        poEdms_State->MakeData( static_cast<int>(8 + strlen(psInfo->pszIGEFilename) + 1 + 6 * 4) );
 
-        poEdms_State->SetStringField( "fileName.string", 
+        poEdms_State->SetStringField( "fileName.string",
                                       psInfo->pszIGEFilename );
 
         poEdms_State->SetIntField( "layerStackValidFlagsOffset[0]",
                                  (int) (nStackValidFlagsOffset & 0xFFFFFFFF));
-        poEdms_State->SetIntField( "layerStackValidFlagsOffset[1]", 
+        poEdms_State->SetIntField( "layerStackValidFlagsOffset[1]",
                                  (int) (nStackValidFlagsOffset >> 32) );
 
         poEdms_State->SetIntField( "layerStackDataOffset[0]",
                                    (int) (nStackDataOffset & 0xFFFFFFFF) );
-        poEdms_State->SetIntField( "layerStackDataOffset[1]", 
+        poEdms_State->SetIntField( "layerStackDataOffset[1]",
                                    (int) (nStackDataOffset >> 32 ) );
         poEdms_State->SetIntField( "layerStackCount", nStackCount );
         poEdms_State->SetIntField( "layerStackIndex", nStackIndex );
@@ -2232,12 +2269,12 @@ HFACreateLayer( HFAHandle psInfo, HFAEntry *poParent,
     {
         HFAEntry *poDepLayerName;
 
-        poDepLayerName = 
-            new HFAEntry( psInfo, "DependentLayerName",
+        poDepLayerName =
+            HFAEntry::New( psInfo, "DependentLayerName",
                           "Eimg_DependentLayerName", poEimg_Layer );
-        poDepLayerName->MakeData( 8 + strlen(pszLayerName) + 2 );
+        poDepLayerName->MakeData( static_cast<int>(8 + strlen(pszLayerName) + 2) );
 
-        poDepLayerName->SetStringField( "ImageLayerName.string", 
+        poDepLayerName->SetStringField( "ImageLayerName.string",
                                         pszLayerName );
     }
 
@@ -2247,34 +2284,34 @@ HFACreateLayer( HFAHandle psInfo, HFAEntry *poParent,
     HFAEntry *poEhfa_Layer;
     GUInt32  nLDict;
     char     szLDict[128], chBandType;
-    
-    if( nDataType == EPT_u1 )
+
+    if( eDataType == EPT_u1 )
         chBandType = '1';
-    else if( nDataType == EPT_u2 )
+    else if( eDataType == EPT_u2 )
         chBandType = '2';
-    else if( nDataType == EPT_u4 )
+    else if( eDataType == EPT_u4 )
         chBandType = '4';
-    else if( nDataType == EPT_u8 )
+    else if( eDataType == EPT_u8 )
         chBandType = 'c';
-    else if( nDataType == EPT_s8 )
+    else if( eDataType == EPT_s8 )
         chBandType = 'C';
-    else if( nDataType == EPT_u16 )
+    else if( eDataType == EPT_u16 )
         chBandType = 's';
-    else if( nDataType == EPT_s16 )
+    else if( eDataType == EPT_s16 )
         chBandType = 'S';
-    else if( nDataType == EPT_u32 )
-        // for some reason erdas imagine expects an L for unsinged 32 bit ints
+    else if( eDataType == EPT_u32 )
+        // for some reason erdas imagine expects an L for unsigned 32 bit ints
         // otherwise it gives strange "out of memory errors"
         chBandType = 'L';
-    else if( nDataType == EPT_s32 )
+    else if( eDataType == EPT_s32 )
         chBandType = 'L';
-    else if( nDataType == EPT_f32 )
+    else if( eDataType == EPT_f32 )
         chBandType = 'f';
-    else if( nDataType == EPT_f64 )
+    else if( eDataType == EPT_f64 )
         chBandType = 'd';
-    else if( nDataType == EPT_c64 )
+    else if( eDataType == EPT_c64 )
         chBandType = 'm';
-    else if( nDataType == EPT_c128 )
+    else if( eDataType == EPT_c128 )
         chBandType = 'M';
     else
     {
@@ -2283,21 +2320,21 @@ HFACreateLayer( HFAHandle psInfo, HFAEntry *poParent,
     }
 
     // the first value in the entry below gives the number of pixels within a block
-    sprintf( szLDict, "{%d:%cdata,}RasterDMS,.", nBlockSize*nBlockSize, chBandType );
+    snprintf( szLDict, sizeof(szLDict), "{%d:%cdata,}RasterDMS,.", nBlockSize*nBlockSize, chBandType );
 
-    poEhfa_Layer = new HFAEntry( psInfo, "Ehfa_Layer", "Ehfa_Layer",
+    poEhfa_Layer = HFAEntry::New( psInfo, "Ehfa_Layer", "Ehfa_Layer",
                                  poEimg_Layer );
     poEhfa_Layer->MakeData();
     poEhfa_Layer->SetPosition();
-    nLDict = HFAAllocateSpace( psInfo, strlen(szLDict) + 1 );
+    nLDict = HFAAllocateSpace( psInfo, static_cast<GUInt32>(strlen(szLDict) + 1) );
 
     poEhfa_Layer->SetStringField( "type", "raster" );
     poEhfa_Layer->SetIntField( "dictionaryPtr", nLDict );
 
-    VSIFSeekL( psInfo->fp, nLDict, SEEK_SET );
-    VSIFWriteL( (void *) szLDict, strlen(szLDict) + 1, 1, psInfo->fp );
+    bool bRet = VSIFSeekL( psInfo->fp, nLDict, SEEK_SET ) >= 0;
+    bRet &= VSIFWriteL( (void *) szLDict, strlen(szLDict) + 1, 1, psInfo->fp ) > 0;
 
-    return TRUE;
+    return bRet;
 }
 
 
@@ -2307,7 +2344,7 @@ HFACreateLayer( HFAHandle psInfo, HFAEntry *poParent,
 
 HFAHandle HFACreate( const char * pszFilename,
                      int nXSize, int nYSize, int nBands,
-                     int nDataType, char ** papszOptions )
+                     EPTType eDataType, char ** papszOptions )
 
 {
     HFAHandle	psInfo;
@@ -2318,15 +2355,16 @@ HFAHandle HFACreate( const char * pszFilename,
     {
         nBlockSize = atoi( pszValue );
         // check for sane values
-        if ( (( nBlockSize < 32 ) || (nBlockSize > 2048))
-            && !CSLTestBoolean(CPLGetConfigOption("FORCE_BLOCKSIZE", "NO")) )
+        if ( nBlockSize == 0 ||
+            ((( nBlockSize < 32 ) || (nBlockSize > 2048))
+            && !CPLTestBool(CPLGetConfigOption("FORCE_BLOCKSIZE", "NO"))) )
         {
             nBlockSize = 64;
         }
     }
     int bCreateLargeRaster = CSLFetchBoolean(papszOptions,"USE_SPILL",
                                              FALSE);
-    int bCreateCompressed = 
+    int bCreateCompressed =
         CSLFetchBoolean(papszOptions,"COMPRESS", FALSE)
         || CSLFetchBoolean(papszOptions,"COMPRESSED", FALSE);
     int bCreateAux = CSLFetchBoolean(papszOptions,"AUX", FALSE);
@@ -2343,15 +2381,15 @@ HFAHandle HFACreate( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Create the DependentFile node if requested.                     */
 /* -------------------------------------------------------------------- */
-    const char *pszDependentFile = 
+    const char *pszDependentFile =
         CSLFetchNameValue( papszOptions, "DEPENDENT_FILE" );
 
     if( pszDependentFile != NULL )
     {
-        HFAEntry *poDF = new HFAEntry( psInfo, "DependentFile", 
+        HFAEntry *poDF = HFAEntry::New( psInfo, "DependentFile",
                                        "Eimg_DependentFile", psInfo->poRoot );
 
-        poDF->MakeData( strlen(pszDependentFile) + 50 );
+        poDF->MakeData( static_cast<int>(strlen(pszDependentFile) + 50) );
         poDF->SetPosition();
         poDF->SetStringField( "dependent.string", pszDependentFile );
     }
@@ -2365,7 +2403,7 @@ HFAHandle HFACreate( const char * pszFilename,
     nBlocksPerColumn = (nYSize + nBlockSize - 1) / nBlockSize;
     nBlocks = nBlocksPerRow * nBlocksPerColumn;
     nBytesPerBlock = (nBlockSize * nBlockSize
-                      * HFAGetDataTypeBits(nDataType) + 7) / 8;
+                      * HFAGetDataTypeBits(eDataType) + 7) / 8;
 
     CPLDebug( "HFACreate", "Blocks per row %d, blocks per column %d, "
 	      "total number of blocks %d, bytes per block %d.",
@@ -2392,7 +2430,7 @@ HFAHandle HFACreate( const char * pszFilename,
     if( !bCreateAux )
     {
         HFAEntry *poImgFormat;
-        poImgFormat = new HFAEntry( psInfo, "IMGFormatInfo",
+        poImgFormat = HFAEntry::New( psInfo, "IMGFormatInfo",
                                     "ImgFormatInfo831", psInfo->poRoot );
         poImgFormat->MakeData();
         if ( bCreateLargeRaster )
@@ -2414,8 +2452,8 @@ HFAHandle HFACreate( const char * pszFilename,
 
     if( bCreateLargeRaster )
     {
-        if( !HFACreateSpillStack( psInfo, nXSize, nYSize, nBands, 
-                                  nBlockSize, nDataType, 
+        if( !HFACreateSpillStack( psInfo, nXSize, nYSize, nBands,
+                                  nBlockSize, eDataType,
                                   &nValidFlagsOffset, &nDataOffset ) )
 	{
 	    CPLFree( pszRawFilename );
@@ -2433,15 +2471,15 @@ HFAHandle HFACreate( const char * pszFilename,
     {
         char		szName[128];
 
-        sprintf( szName, "Layer_%d", iBand + 1 );
+        snprintf( szName, sizeof(szName), "Layer_%d", iBand + 1 );
 
         if( !HFACreateLayer( psInfo, psInfo->poRoot, szName, FALSE, nBlockSize,
                              bCreateCompressed, bCreateLargeRaster, bCreateAux,
-                             nXSize, nYSize, nDataType, papszOptions,
+                             nXSize, nYSize, eDataType, papszOptions,
                              nValidFlagsOffset, nDataOffset,
                              nBands, iBand ) )
         {
-            HFAClose( psInfo );
+            CPL_IGNORE_RET_VAL(HFAClose( psInfo ));
             return NULL;
         }
     }
@@ -2521,7 +2559,7 @@ char ** HFAGetMetadata( HFAHandle hHFA, int nBand )
         int        columnDataPtr;
 
         // Skip the #Bin_Function# entry.
-        if( EQUALN(poColumn->GetName(),"#",1) )
+        if( STARTS_WITH_CI(poColumn->GetName(), "#") )
             continue;
 
         pszValue = poColumn->GetStringField( "dataType" );
@@ -2531,33 +2569,31 @@ char ** HFAGetMetadata( HFAHandle hHFA, int nBand )
         columnDataPtr = poColumn->GetIntField( "columnDataPtr" );
         if( columnDataPtr == 0 )
             continue;
-            
+
 /* -------------------------------------------------------------------- */
-/*      read up to nMaxNumChars bytes from the indicated location.      */
+/*      Read up to nMaxNumChars bytes from the indicated location.      */
 /*      allocate required space temporarily                             */
-/*      nMaxNumChars should have been set by GDAL orginally so we should*/
-/*      trust it, but who knows...                                      */
+/*      nMaxNumChars should have been set by GDAL originally so we      */
+/*      should trust it, but who knows...                               */
 /* -------------------------------------------------------------------- */
         int nMaxNumChars = poColumn->GetIntField( "maxNumChars" );
 
-        if( nMaxNumChars == 0 )
+        if( nMaxNumChars <= 0 )
         {
             papszMD = CSLSetNameValue( papszMD, poColumn->GetName(), "" );
         }
         else
         {
-            char *pszMDValue = (char*) VSIMalloc(nMaxNumChars);
+            char *pszMDValue = (char*) VSI_MALLOC_VERBOSE(nMaxNumChars);
             if (pszMDValue == NULL)
             {
-                CPLError(CE_Failure, CPLE_OutOfMemory,
-                         "HFAGetMetadata : Out of memory while allocating %d bytes", nMaxNumChars);
                 continue;
             }
 
             if( VSIFSeekL( hHFA->fp, columnDataPtr, SEEK_SET ) != 0 )
                 continue;
 
-            int nMDBytes = VSIFReadL( pszMDValue, 1, nMaxNumChars, hHFA->fp );
+            int nMDBytes = static_cast<int>(VSIFReadL( pszMDValue, 1, nMaxNumChars, hHFA->fp ));
             if( nMDBytes == 0 )
             {
                 CPLFree( pszMDValue );
@@ -2566,7 +2602,7 @@ char ** HFAGetMetadata( HFAHandle hHFA, int nBand )
 
             pszMDValue[nMaxNumChars-1] = '\0';
 
-            papszMD = CSLSetNameValue( papszMD, poColumn->GetName(), 
+            papszMD = CSLSetNameValue( papszMD, poColumn->GetName(),
                                        pszMDValue );
             CPLFree( pszMDValue );
         }
@@ -2584,7 +2620,7 @@ char ** HFAGetMetadata( HFAHandle hHFA, int nBand )
 /*      information (like histogram or stats info).                     */
 /************************************************************************/
 
-static CPLErr 
+static CPLErr
 HFASetGDALMetadata( HFAHandle hHFA, int nBand, char **papszMD )
 
 {
@@ -2607,9 +2643,9 @@ HFASetGDALMetadata( HFAHandle hHFA, int nBand, char **papszMD )
     HFAEntry	*poEdsc_Table = poNode->GetNamedChild( "GDAL_MetaData" );
 
     if( poEdsc_Table == NULL || !EQUAL(poEdsc_Table->GetType(),"Edsc_Table") )
-        poEdsc_Table = new HFAEntry( hHFA, "GDAL_MetaData", "Edsc_Table",
+        poEdsc_Table = HFAEntry::New( hHFA, "GDAL_MetaData", "Edsc_Table",
                                  poNode );
-        
+
     poEdsc_Table->SetIntField( "numrows", 1 );
 
 /* -------------------------------------------------------------------- */
@@ -2617,15 +2653,15 @@ HFASetGDALMetadata( HFAHandle hHFA, int nBand, char **papszMD )
 /*      really need this though.                                        */
 /*      Check it doesn't exist already                                  */
 /* -------------------------------------------------------------------- */
-    HFAEntry       *poEdsc_BinFunction = 
+    HFAEntry       *poEdsc_BinFunction =
         poEdsc_Table->GetNamedChild( "#Bin_Function#" );
 
-    if( poEdsc_BinFunction == NULL 
+    if( poEdsc_BinFunction == NULL
         || !EQUAL(poEdsc_BinFunction->GetType(),"Edsc_BinFunction") )
-        poEdsc_BinFunction = new HFAEntry( hHFA, "#Bin_Function#", 
+        poEdsc_BinFunction = HFAEntry::New( hHFA, "#Bin_Function#",
                                            "Edsc_BinFunction", poEdsc_Table );
 
-    // Because of the BaseData we have to hardcode the size. 
+    // Because of the BaseData we have to hardcode the size.
     poEdsc_BinFunction->MakeData( 30 );
 
     poEdsc_BinFunction->SetIntField( "numBins", 1 );
@@ -2636,6 +2672,7 @@ HFASetGDALMetadata( HFAHandle hHFA, int nBand, char **papszMD )
 /* -------------------------------------------------------------------- */
 /*      Process each metadata item as a separate column.		*/
 /* -------------------------------------------------------------------- */
+    bool bRet = true;
     for( int iColumn = 0; papszMD[iColumn] != NULL; iColumn++ )
     {
         HFAEntry        *poEdsc_Column;
@@ -2652,29 +2689,29 @@ HFASetGDALMetadata( HFAHandle hHFA, int nBand, char **papszMD )
 /* -------------------------------------------------------------------- */
         poEdsc_Column = poEdsc_Table->GetNamedChild(pszKey);
 
-        if( poEdsc_Column == NULL 
+        if( poEdsc_Column == NULL
             || !EQUAL(poEdsc_Column->GetType(),"Edsc_Column") )
-            poEdsc_Column = new HFAEntry( hHFA, pszKey, "Edsc_Column",
+            poEdsc_Column = HFAEntry::New( hHFA, pszKey, "Edsc_Column",
                                           poEdsc_Table );
 
         poEdsc_Column->SetIntField( "numRows", 1 );
         poEdsc_Column->SetStringField( "dataType", "string" );
-        poEdsc_Column->SetIntField( "maxNumChars", strlen(pszValue)+1 );
+        poEdsc_Column->SetIntField( "maxNumChars", static_cast<GUInt32>(strlen(pszValue)+1) );
 
 /* -------------------------------------------------------------------- */
 /*      Write the data out.                                             */
 /* -------------------------------------------------------------------- */
-        int      nOffset = HFAAllocateSpace( hHFA, strlen(pszValue)+1);
+        int      nOffset = HFAAllocateSpace( hHFA, static_cast<GUInt32>(strlen(pszValue)+1));
 
         poEdsc_Column->SetIntField( "columnDataPtr", nOffset );
 
-        VSIFSeekL( hHFA->fp, nOffset, SEEK_SET );
-        VSIFWriteL( (void *) pszValue, 1, strlen(pszValue)+1, hHFA->fp );
+        bRet &= VSIFSeekL( hHFA->fp, nOffset, SEEK_SET ) >= 0;
+        bRet &= VSIFWriteL( (void *) pszValue, strlen(pszValue)+1, 1, hHFA->fp ) > 0;
 
         CPLFree( pszKey );
     }
 
-    return CE_Failure;
+    return (bRet) ? CE_None : CE_Failure;
 }
 
 /************************************************************************/
@@ -2697,7 +2734,14 @@ CPLErr HFASetMetadata( HFAHandle hHFA, int nBand, char **papszMD )
         poNode = hHFA->poRoot;
     else
         return CE_Failure;
-
+#ifdef DEBUG
+    /* To please Clang Static Analyzer */
+    if( poNode == NULL )
+    {
+        CPLAssert(FALSE);
+        return CE_Failure;
+    }
+#endif
 /* -------------------------------------------------------------------- */
 /*      Check if the Metadata is an "known" entity which should be      */
 /*      stored in a better place.                                       */
@@ -2705,7 +2749,7 @@ CPLErr HFASetMetadata( HFAHandle hHFA, int nBand, char **papszMD )
     char * pszBinValues = NULL;
     int bCreatedHistogramParameters = FALSE;
     int bCreatedStatistics = FALSE;
-    const char ** pszAuxMetaData = GetHFAAuxMetaDataList();
+    const char * const * pszAuxMetaData = GetHFAAuxMetaDataList();
     // check each metadata item
     for( int iColumn = 0; papszMD[iColumn] != NULL; iColumn++ )
     {
@@ -2736,20 +2780,20 @@ CPLErr HFASetMetadata( HFAHandle hHFA, int nBand, char **papszMD )
             if( poEntry == NULL && strlen(pszAuxMetaData[i+3]) > 0 )
             {
                 // child does not yet exist --> create it
-                poEntry = new HFAEntry( hHFA, pszAuxMetaData[i], pszAuxMetaData[i+3],
+                poEntry = HFAEntry::New( hHFA, pszAuxMetaData[i], pszAuxMetaData[i+3],
                                         poNode );
 
-                if ( EQUALN( "Statistics", pszAuxMetaData[i], 10 ) )
+                if ( STARTS_WITH_CI(pszAuxMetaData[i], "Statistics") )
                     bCreatedStatistics = TRUE;
-                
-                if( EQUALN( "HistogramParameters", pszAuxMetaData[i], 19 ) )
+
+                if( STARTS_WITH_CI(pszAuxMetaData[i], "HistogramParameters") )
                 {
                     // this is a bit nasty I need to set the string field for the object
                     // first because the SetStringField sets the count for the object
                     // BinFunction to the length of the string
                     poEntry->MakeData( 70 );
                     poEntry->SetStringField( "BinFunction.binFunctionType", "direct" );
-                    
+
                     bCreatedHistogramParameters = TRUE;
                 }
             }
@@ -2785,8 +2829,9 @@ CPLErr HFASetMetadata( HFAHandle hHFA, int nBand, char **papszMD )
                 CPLAssert( FALSE );
             }
         }
-        else if ( EQUALN( "STATISTICS_HISTOBINVALUES", pszKey, strlen(pszKey) ) )
+        else if ( STARTS_WITH_CI( pszKey, "STATISTICS_HISTOBINVALUES" ) )
         {
+            CPLFree(pszBinValues);
             pszBinValues = CPLStrdup( pszValue );
         }
         else
@@ -2798,6 +2843,7 @@ CPLErr HFASetMetadata( HFAHandle hHFA, int nBand, char **papszMD )
 /* -------------------------------------------------------------------- */
 /*      Special case to write out the histogram.                        */
 /* -------------------------------------------------------------------- */
+    bool bRet = true;
     if ( pszBinValues != NULL )
     {
         HFAEntry * poEntry = poNode->GetNamedChild( "HistogramParameters" );
@@ -2810,25 +2856,25 @@ CPLErr HFASetMetadata( HFAHandle hHFA, int nBand, char **papszMD )
             int nNumBins = poEntry->GetIntField( "BinFunction.numBins" );
             double dMinLimit = poEntry->GetDoubleField( "BinFunction.minLimit" );
             double dMaxLimit = poEntry->GetDoubleField( "BinFunction.maxLimit" );
-            
+
             // fill the descriptor table - check it isn't there already
             poEntry = poNode->GetNamedChild( "Descriptor_Table" );
             if( poEntry == NULL || !EQUAL(poEntry->GetType(),"Edsc_Table") )
-                poEntry = new HFAEntry( hHFA, "Descriptor_Table", "Edsc_Table", poNode );
-                
+                poEntry = HFAEntry::New( hHFA, "Descriptor_Table", "Edsc_Table", poNode );
+
             poEntry->SetIntField( "numRows", nNumBins );
 
             // bin function
             HFAEntry * poBinFunc = poEntry->GetNamedChild( "#Bin_Function#" );
             if( poBinFunc == NULL || !EQUAL(poBinFunc->GetType(),"Edsc_BinFunction") )
-                poBinFunc = new HFAEntry( hHFA, "#Bin_Function#", "Edsc_BinFunction", poEntry );
+                poBinFunc = HFAEntry::New( hHFA, "#Bin_Function#", "Edsc_BinFunction", poEntry );
 
             poBinFunc->MakeData( 30 );
             poBinFunc->SetIntField( "numBins", nNumBins );
             poBinFunc->SetDoubleField( "minLimit", dMinLimit );
             poBinFunc->SetDoubleField( "maxLimit", dMaxLimit );
             // direct for thematic layers, linear otherwise
-            if ( EQUALN ( poNode->GetStringField("layerType"), "thematic", 8) )
+            if ( STARTS_WITH_CI(poNode->GetStringField("layerType"), "thematic") )
                 poBinFunc->SetStringField( "binFunctionType", "direct" );
             else
                 poBinFunc->SetStringField( "binFunctionType", "linear" );
@@ -2836,8 +2882,8 @@ CPLErr HFASetMetadata( HFAHandle hHFA, int nBand, char **papszMD )
             // we need a child named histogram
             HFAEntry * poHisto = poEntry->GetNamedChild( "Histogram" );
             if( poHisto == NULL || !EQUAL(poHisto->GetType(),"Edsc_Column") )
-                poHisto = new HFAEntry( hHFA, "Histogram", "Edsc_Column", poEntry );
-                
+                poHisto = HFAEntry::New( hHFA, "Histogram", "Edsc_Column", poEntry );
+
             poHisto->SetIntField( "numRows", nNumBins );
             // allocate space for the bin values
             GUInt32 nOffset = HFAAllocateSpace( hHFA, nNumBins*8 );
@@ -2852,11 +2898,11 @@ CPLErr HFASetMetadata( HFAHandle hHFA, int nBand, char **papszMD )
                 if ( pszEnd != NULL )
                 {
                     *pszEnd = 0;
-                    VSIFSeekL( hHFA->fp, nOffset + 8*nBin, SEEK_SET );
+                    bRet &= VSIFSeekL( hHFA->fp, nOffset + 8*nBin, SEEK_SET ) >= 0;
                     double nValue = CPLAtof( pszWork );
                     HFAStandard( 8, &nValue );
 
-                    VSIFWriteL( (void *)&nValue, 1, 8, hHFA->fp );
+                    bRet &= VSIFWriteL( (void *)&nValue, 8, 1, hHFA->fp ) > 0;
                     pszWork = pszEnd + 1;
                 }
             }
@@ -2864,13 +2910,13 @@ CPLErr HFASetMetadata( HFAHandle hHFA, int nBand, char **papszMD )
         else if ( poEntry != NULL )
         {
             // In this case, there are HistogramParameters present, but we did not
-            // create them. However, we might be modifying them, in the case where 
-            // the data has changed and the histogram counts need to be updated. It could 
-            // be worse than that, but that is all we are going to cope with for now. 
-            // We are assuming that we did not change any of the other stuff, like 
+            // create them. However, we might be modifying them, in the case where
+            // the data has changed and the histogram counts need to be updated. It could
+            // be worse than that, but that is all we are going to cope with for now.
+            // We are assuming that we did not change any of the other stuff, like
             // skip factors and so forth. The main need for this case is for programs
             // (such as Imagine itself) which will happily modify the pixel values
-            // without re-calculating the histogram counts. 
+            // without re-calculating the histogram counts.
             int nNumBins = poEntry->GetIntField( "BinFunction.numBins" );
             HFAEntry *poEntryDescrTbl = poNode->GetNamedChild( "Descriptor_Table" );
             HFAEntry *poHisto = NULL;
@@ -2881,11 +2927,11 @@ CPLErr HFASetMetadata( HFAHandle hHFA, int nBand, char **papszMD )
                 int nOffset = poHisto->GetIntField( "columnDataPtr" );
                 // write out histogram data
                 char * pszWork = pszBinValues;
-                
+
                 // Check whether histogram counts were written as int or double
                 bool bCountIsInt = TRUE;
                 const char *pszDataType = poHisto->GetStringField("dataType");
-                if ( EQUALN(pszDataType, "real", strlen(pszDataType)) )
+                if ( STARTS_WITH_CI(pszDataType, "real") )
                 {
                     bCountIsInt = FALSE;
                 }
@@ -2897,16 +2943,16 @@ CPLErr HFASetMetadata( HFAHandle hHFA, int nBand, char **papszMD )
                         *pszEnd = 0;
                         if ( bCountIsInt ) {
                             // Histogram counts were written as ints, so re-write them the same way
-                            VSIFSeekL( hHFA->fp, nOffset + 4*nBin, SEEK_SET );
+                            bRet &= VSIFSeekL( hHFA->fp, nOffset + 4*nBin, SEEK_SET ) >= 0;
                             int nValue = atoi( pszWork );
                             HFAStandard( 4, &nValue );
-                            VSIFWriteL( (void *)&nValue, 1, 4, hHFA->fp );
+                            bRet &= VSIFWriteL( (void *)&nValue, 4, 1, hHFA->fp ) > 0;
                         } else {
                             // Histogram were written as doubles, as is now the default behaviour
-                            VSIFSeekL( hHFA->fp, nOffset + 8*nBin, SEEK_SET );
+                            bRet &= VSIFSeekL( hHFA->fp, nOffset + 8*nBin, SEEK_SET ) >= 0;
                             double nValue = CPLAtof( pszWork );
                             HFAStandard( 8, &nValue );
-                            VSIFWriteL( (void *)&nValue, 1, 8, hHFA->fp );
+                            bRet &= VSIFWriteL( (void *)&nValue, 8, 1, hHFA->fp ) > 0;
                         }
                         pszWork = pszEnd + 1;
                     }
@@ -2922,10 +2968,10 @@ CPLErr HFASetMetadata( HFAHandle hHFA, int nBand, char **papszMD )
 /* -------------------------------------------------------------------- */
     if( bCreatedStatistics )
     {
-        HFAEntry *poEntry = 
-            new HFAEntry( hHFA, "StatisticsParameters", 
+        HFAEntry *poEntry =
+            HFAEntry::New( hHFA, "StatisticsParameters",
                           "Eimg_StatisticsParameters830", poNode );
-        
+
         poEntry->MakeData( 70 );
         //poEntry->SetStringField( "BinFunction.binFunctionType", "linear" );
 
@@ -2936,15 +2982,18 @@ CPLErr HFASetMetadata( HFAHandle hHFA, int nBand, char **papszMD )
 /* -------------------------------------------------------------------- */
 /*      Write out metadata items without a special place.               */
 /* -------------------------------------------------------------------- */
-    if( CSLCount( papszGDALMD) != 0 )
+    if( bRet && CSLCount( papszGDALMD) != 0 )
     {
         CPLErr eErr = HFASetGDALMetadata( hHFA, nBand, papszGDALMD );
-        
+
         CSLDestroy( papszGDALMD );
         return eErr;
     }
     else
+    {
+        CSLDestroy( papszGDALMD );
         return CE_Failure;
+    }
 }
 
 /************************************************************************/
@@ -2963,12 +3012,12 @@ const char *HFAGetIGEFilename( HFAHandle hHFA )
     if( hHFA->pszIGEFilename == NULL )
     {
         HFAEntry    *poDMS = NULL;
-        std::vector<HFAEntry*> apoDMSList = 
+        std::vector<HFAEntry*> apoDMSList =
             hHFA->poRoot->FindChildren( NULL, "ImgExternalRaster" );
 
         if( apoDMSList.size() > 0 )
             poDMS = apoDMSList[0];
-        
+
 /* -------------------------------------------------------------------- */
 /*      Get the IGE filename from if we have an ExternalRasterDMS       */
 /* -------------------------------------------------------------------- */
@@ -2976,25 +3025,25 @@ const char *HFAGetIGEFilename( HFAHandle hHFA )
         {
             const char *pszRawFilename =
                 poDMS->GetStringField( "fileName.string" );
-            
+
             if( pszRawFilename != NULL )
             {
                 VSIStatBufL sStatBuf;
-                CPLString osFullFilename = 
+                CPLString osFullFilename =
                     CPLFormFilename( hHFA->pszPath, pszRawFilename, NULL );
 
                 if( VSIStatL( osFullFilename, &sStatBuf ) != 0 )
                 {
                     CPLString osExtension = CPLGetExtension(pszRawFilename);
                     CPLString osBasename = CPLGetBasename(hHFA->pszFilename);
-                    CPLString osFullFilename = 
-                        CPLFormFilename( hHFA->pszPath, osBasename, 
+                    osFullFilename =
+                        CPLFormFilename( hHFA->pszPath, osBasename,
                                          osExtension );
 
                     if( VSIStatL( osFullFilename, &sStatBuf ) == 0 )
-                        hHFA->pszIGEFilename = 
+                        hHFA->pszIGEFilename =
                             CPLStrdup(
-                                CPLFormFilename( NULL, osBasename, 
+                                CPLFormFilename( NULL, osBasename,
                                                  osExtension ) );
                     else
                         hHFA->pszIGEFilename = CPLStrdup( pszRawFilename );
@@ -3021,9 +3070,9 @@ const char *HFAGetIGEFilename( HFAHandle hHFA )
 /*      file.  Create the spill file if it didn't exist before.         */
 /************************************************************************/
 
-int HFACreateSpillStack( HFAInfo_t *psInfo, int nXSize, int nYSize, 
-                         int nLayers, int nBlockSize, int nDataType,
-                         GIntBig *pnValidFlagsOffset, 
+int HFACreateSpillStack( HFAInfo_t *psInfo, int nXSize, int nYSize,
+                         int nLayers, int nBlockSize, EPTType eDataType,
+                         GIntBig *pnValidFlagsOffset,
                          GIntBig *pnDataOffset )
 
 {
@@ -3031,7 +3080,7 @@ int HFACreateSpillStack( HFAInfo_t *psInfo, int nXSize, int nYSize,
 /*      Form .ige filename.                                             */
 /* -------------------------------------------------------------------- */
     char *pszFullFilename;
-    
+
     if (nBlockSize <= 0)
     {
         CPLError(CE_Failure, CPLE_IllegalArg, "HFACreateSpillStack : nBlockXSize < 0");
@@ -3041,25 +3090,26 @@ int HFACreateSpillStack( HFAInfo_t *psInfo, int nXSize, int nYSize,
     if( psInfo->pszIGEFilename == NULL )
     {
         if( EQUAL(CPLGetExtension(psInfo->pszFilename),"rrd") )
-            psInfo->pszIGEFilename = 
+            psInfo->pszIGEFilename =
                 CPLStrdup( CPLResetExtension( psInfo->pszFilename, "rde" ) );
         else if( EQUAL(CPLGetExtension(psInfo->pszFilename),"aux") )
-            psInfo->pszIGEFilename = 
+            psInfo->pszIGEFilename =
                 CPLStrdup( CPLResetExtension( psInfo->pszFilename, "axe" ) );
-        else								
-            psInfo->pszIGEFilename = 
+        else
+            psInfo->pszIGEFilename =
                 CPLStrdup( CPLResetExtension( psInfo->pszFilename, "ige" ) );
     }
 
-    pszFullFilename = 
+    pszFullFilename =
         CPLStrdup( CPLFormFilename( psInfo->pszPath, psInfo->pszIGEFilename, NULL ) );
 
 /* -------------------------------------------------------------------- */
 /*      Try and open it.  If we fail, create it and write the magic     */
 /*      header.                                                         */
 /* -------------------------------------------------------------------- */
-    static const char *pszMagick = "ERDAS_IMG_EXTERNAL_RASTER";
+    static const char * const pszMagick = "ERDAS_IMG_EXTERNAL_RASTER";
     VSILFILE *fpVSIL;
+    bool bRet = true;
 
     fpVSIL = VSIFOpenL( pszFullFilename, "r+b" );
     if( fpVSIL == NULL )
@@ -3073,7 +3123,7 @@ int HFACreateSpillStack( HFAInfo_t *psInfo, int nXSize, int nYSize,
             return FALSE;
         }
 
-        VSIFWriteL( (void *) pszMagick, 1, strlen(pszMagick)+1, fpVSIL );
+        bRet &= VSIFWriteL( (void *) pszMagick, strlen(pszMagick)+1, 1, fpVSIL ) > 0;
     }
 
     CPLFree( pszFullFilename );
@@ -3088,7 +3138,7 @@ int HFACreateSpillStack( HFAInfo_t *psInfo, int nXSize, int nYSize,
     nBlocksPerColumn = (nYSize + nBlockSize - 1) / nBlockSize;
     /* nBlocks = nBlocksPerRow * nBlocksPerColumn; */
     nBytesPerBlock = (nBlockSize * nBlockSize
-                      * HFAGetDataTypeBits(nDataType) + 7) / 8;
+                      * HFAGetDataTypeBits(eDataType) + 7) / 8;
 
     nBytesPerRow = ( nBlocksPerRow + 7 ) / 8;
     nBlockMapSize = nBytesPerRow * nBlocksPerColumn;
@@ -3100,27 +3150,27 @@ int HFACreateSpillStack( HFAInfo_t *psInfo, int nXSize, int nYSize,
     GByte bUnknown;
     GInt32 nValue32;
 
-    VSIFSeekL( fpVSIL, 0, SEEK_END );
+    bRet &= VSIFSeekL( fpVSIL, 0, SEEK_END ) >= 0;
 
     bUnknown = 1;
-    VSIFWriteL( &bUnknown, 1, 1, fpVSIL );
+    bRet &= VSIFWriteL( &bUnknown, 1, 1, fpVSIL ) > 0;
     nValue32 = nLayers;
     HFAStandard( 4, &nValue32 );
-    VSIFWriteL( &nValue32, 4, 1, fpVSIL );
+    bRet &= VSIFWriteL( &nValue32, 4, 1, fpVSIL ) > 0;
     nValue32 = nXSize;
     HFAStandard( 4, &nValue32 );
-    VSIFWriteL( &nValue32, 4, 1, fpVSIL );
+    bRet &= VSIFWriteL( &nValue32, 4, 1, fpVSIL ) > 0;
     nValue32 = nYSize;
     HFAStandard( 4, &nValue32 );
-    VSIFWriteL( &nValue32, 4, 1, fpVSIL );
+    bRet &= VSIFWriteL( &nValue32, 4, 1, fpVSIL ) > 0;
     nValue32 = nBlockSize;
     HFAStandard( 4, &nValue32 );
-    VSIFWriteL( &nValue32, 4, 1, fpVSIL );
-    VSIFWriteL( &nValue32, 4, 1, fpVSIL );
+    bRet &= VSIFWriteL( &nValue32, 4, 1, fpVSIL ) > 0;
+    bRet &= VSIFWriteL( &nValue32, 4, 1, fpVSIL ) > 0;
     bUnknown = 3;
-    VSIFWriteL( &bUnknown, 1, 1, fpVSIL );
+    bRet &= VSIFWriteL( &bUnknown, 1, 1, fpVSIL ) > 0;
     bUnknown = 0;
-    VSIFWriteL( &bUnknown, 1, 1, fpVSIL );
+    bRet &= VSIFWriteL( &bUnknown, 1, 1, fpVSIL ) > 0;
 
 /* -------------------------------------------------------------------- */
 /*      Write out ValidFlags section(s).                                */
@@ -3130,14 +3180,13 @@ int HFACreateSpillStack( HFAInfo_t *psInfo, int nXSize, int nYSize,
 
     *pnValidFlagsOffset = VSIFTellL( fpVSIL );
 
-    pabyBlockMap = (unsigned char *) VSIMalloc( nBlockMapSize );
+    pabyBlockMap = (unsigned char *) VSI_MALLOC_VERBOSE( nBlockMapSize );
     if (pabyBlockMap == NULL)
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory, "HFACreateSpillStack : Out of memory");
-        VSIFCloseL( fpVSIL );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fpVSIL ));
         return FALSE;
     }
-    
+
     memset( pabyBlockMap, 0xff, nBlockMapSize );
     for ( iBand = 0; iBand < nLayers; iBand++ )
     {
@@ -3145,18 +3194,18 @@ int HFACreateSpillStack( HFAInfo_t *psInfo, int nXSize, int nYSize,
 
         nValue32 = 1;	// Unknown
         HFAStandard( 4, &nValue32 );
-        VSIFWriteL( &nValue32, 4, 1, fpVSIL );
+        bRet &= VSIFWriteL( &nValue32, 4, 1, fpVSIL ) > 0;
         nValue32 = 0;	// Unknown
-        VSIFWriteL( &nValue32, 4, 1, fpVSIL );
+        bRet &= VSIFWriteL( &nValue32, 4, 1, fpVSIL ) > 0;
         nValue32 = nBlocksPerColumn;
         HFAStandard( 4, &nValue32 );
-        VSIFWriteL( &nValue32, 4, 1, fpVSIL );
+        bRet &= VSIFWriteL( &nValue32, 4, 1, fpVSIL ) > 0;
         nValue32 = nBlocksPerRow;
         HFAStandard( 4, &nValue32 );
-        VSIFWriteL( &nValue32, 4, 1, fpVSIL );
+        bRet &= VSIFWriteL( &nValue32, 4, 1, fpVSIL ) > 0;
         nValue32 = 0x30000;	// Unknown
         HFAStandard( 4, &nValue32 );
-        VSIFWriteL( &nValue32, 4, 1, fpVSIL );
+        bRet &= VSIFWriteL( &nValue32, 4, 1, fpVSIL ) > 0;
 
         iRemainder = nBlocksPerRow % 8;
         CPLDebug( "HFACreate",
@@ -3168,7 +3217,7 @@ int HFACreateSpillStack( HFAInfo_t *psInfo, int nXSize, int nYSize,
                 pabyBlockMap[i] = (GByte) ((1<<iRemainder) - 1);
         }
 
-        VSIFWriteL( pabyBlockMap, 1, nBlockMapSize, fpVSIL );
+        bRet &= VSIFWriteL( pabyBlockMap, nBlockMapSize, 1, fpVSIL ) > 0;
     }
     CPLFree(pabyBlockMap);
     pabyBlockMap = NULL;
@@ -3176,12 +3225,13 @@ int HFACreateSpillStack( HFAInfo_t *psInfo, int nXSize, int nYSize,
 /* -------------------------------------------------------------------- */
 /*      Extend the file to account for all the imagery space.           */
 /* -------------------------------------------------------------------- */
-    GIntBig nTileDataSize = ((GIntBig) nBytesPerBlock) 
+    GIntBig nTileDataSize = ((GIntBig) nBytesPerBlock)
         * nBlocksPerRow * nBlocksPerColumn * nLayers;
 
     *pnDataOffset = VSIFTellL( fpVSIL );
-    
-    if( VSIFSeekL( fpVSIL, nTileDataSize - 1 + *pnDataOffset, SEEK_SET ) != 0 
+
+    if( !bRet ||
+        VSIFSeekL( fpVSIL, nTileDataSize - 1 + *pnDataOffset, SEEK_SET ) != 0
         || VSIFWriteL( (void *) "", 1, 1, fpVSIL ) != 1 )
     {
         CPLError( CE_Failure, CPLE_FileIO,
@@ -3191,11 +3241,12 @@ int HFACreateSpillStack( HFAInfo_t *psInfo, int nXSize, int nYSize,
                   (double) nTileDataSize - 1 + *pnDataOffset,
                   VSIStrerror( errno ) );
 
-        VSIFCloseL( fpVSIL );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fpVSIL ));
         return FALSE;
     }
 
-    VSIFCloseL( fpVSIL );
+    if( VSIFCloseL( fpVSIL ) != 0 )
+        return FALSE;
 
     return TRUE;
 }
@@ -3204,7 +3255,7 @@ int HFACreateSpillStack( HFAInfo_t *psInfo, int nXSize, int nYSize,
 /*                       HFAReadAndValidatePoly()                       */
 /************************************************************************/
 
-static int HFAReadAndValidatePoly( HFAEntry *poTarget, 
+static int HFAReadAndValidatePoly( HFAEntry *poTarget,
                                    const char *pszName,
                                    Efga_Polynomial *psRetPoly )
 
@@ -3226,7 +3277,7 @@ static int HFAReadAndValidatePoly( HFAEntry *poTarget,
 
     osFldName.Printf( "%snumdimtransform", pszName );
     numdimtransform = poTarget->GetIntField(osFldName);
-    
+
     osFldName.Printf( "%snumdimpolynomial", pszName );
     numdimpolynomial = poTarget->GetIntField(osFldName);
 
@@ -3236,8 +3287,8 @@ static int HFAReadAndValidatePoly( HFAEntry *poTarget,
     if( numdimtransform != 2 || numdimpolynomial != 2 )
         return FALSE;
 
-    if( (psRetPoly->order == 1 && termcount != 3) 
-        || (psRetPoly->order == 2 && termcount != 6) 
+    if( (psRetPoly->order == 1 && termcount != 3)
+        || (psRetPoly->order == 2 && termcount != 6)
         || (psRetPoly->order == 3 && termcount != 10) )
         return FALSE;
 
@@ -3272,7 +3323,7 @@ static int HFAReadAndValidatePoly( HFAEntry *poTarget,
 int HFAReadXFormStack( HFAHandle hHFA,
                        Efga_Polynomial **ppasPolyListForward,
                        Efga_Polynomial **ppasPolyListReverse )
- 
+
 {
     if( hHFA->nBands == 0 )
         return 0;
@@ -3294,7 +3345,7 @@ int HFAReadXFormStack( HFAHandle hHFA,
     *ppasPolyListForward = NULL;
     *ppasPolyListReverse = NULL;
 
-    for( poXForm = poXFormHeader->GetChild(); 
+    for( poXForm = poXFormHeader->GetChild();
          poXForm != NULL;
          poXForm = poXForm->GetNext() )
     {
@@ -3302,10 +3353,10 @@ int HFAReadXFormStack( HFAHandle hHFA,
         Efga_Polynomial sForward, sReverse;
         memset( &sForward, 0, sizeof(sForward) );
         memset( &sReverse, 0, sizeof(sReverse) );
-        
+
         if( EQUAL(poXForm->GetType(),"Efga_Polynomial") )
         {
-            bSuccess = 
+            bSuccess =
                 HFAReadAndValidatePoly( poXForm, "", &sForward );
 
             if( bSuccess )
@@ -3320,6 +3371,8 @@ int HFAReadXFormStack( HFAHandle hHFA,
                 adfGT[5] = sForward.polycoefmtx[3];
 
                 bSuccess = HFAInvGeoTransform( adfGT, adfInvGT );
+                if( !bSuccess )
+                    memset( adfInvGT, 0, sizeof(adfInvGT) );
 
                 sReverse.order = sForward.order;
                 sReverse.polycoefvector[0] = adfInvGT[0];
@@ -3332,29 +3385,29 @@ int HFAReadXFormStack( HFAHandle hHFA,
         }
         else if( EQUAL(poXForm->GetType(),"GM_PolyPair") )
         {
-            bSuccess = 
+            bSuccess =
                 HFAReadAndValidatePoly( poXForm, "forward.", &sForward );
-            bSuccess = bSuccess && 
+            bSuccess = bSuccess &&
                 HFAReadAndValidatePoly( poXForm, "reverse.", &sReverse );
         }
 
         if( bSuccess )
         {
             nStepCount++;
-            *ppasPolyListForward = (Efga_Polynomial *) 
-                CPLRealloc( *ppasPolyListForward, 
+            *ppasPolyListForward = (Efga_Polynomial *)
+                CPLRealloc( *ppasPolyListForward,
                             sizeof(Efga_Polynomial) * nStepCount);
-            memcpy( *ppasPolyListForward + nStepCount - 1, 
+            memcpy( *ppasPolyListForward + nStepCount - 1,
                     &sForward, sizeof(sForward) );
 
-            *ppasPolyListReverse = (Efga_Polynomial *) 
-                CPLRealloc( *ppasPolyListReverse, 
+            *ppasPolyListReverse = (Efga_Polynomial *)
+                CPLRealloc( *ppasPolyListReverse,
                             sizeof(Efga_Polynomial) * nStepCount);
-            memcpy( *ppasPolyListReverse + nStepCount - 1, 
+            memcpy( *ppasPolyListReverse + nStepCount - 1,
                     &sReverse, sizeof(sReverse) );
         }
     }
-    
+
     return nStepCount;
 }
 
@@ -3381,11 +3434,11 @@ int HFAEvaluateXFormStack( int nStepCount, int bForward,
 
         if( psStep->order == 1 )
         {
-            dfXOut = psStep->polycoefvector[0] 
+            dfXOut = psStep->polycoefvector[0]
                 + psStep->polycoefmtx[0] * *pdfX
                 + psStep->polycoefmtx[2] * *pdfY;
 
-            dfYOut = psStep->polycoefvector[1] 
+            dfYOut = psStep->polycoefvector[1]
                 + psStep->polycoefmtx[1] * *pdfX
                 + psStep->polycoefmtx[3] * *pdfY;
 
@@ -3394,13 +3447,13 @@ int HFAEvaluateXFormStack( int nStepCount, int bForward,
         }
         else if( psStep->order == 2 )
         {
-            dfXOut = psStep->polycoefvector[0] 
+            dfXOut = psStep->polycoefvector[0]
                 + psStep->polycoefmtx[0] * *pdfX
                 + psStep->polycoefmtx[2] * *pdfY
                 + psStep->polycoefmtx[4] * *pdfX * *pdfX
                 + psStep->polycoefmtx[6] * *pdfX * *pdfY
                 + psStep->polycoefmtx[8] * *pdfY * *pdfY;
-            dfYOut = psStep->polycoefvector[1] 
+            dfYOut = psStep->polycoefvector[1]
                 + psStep->polycoefmtx[1] * *pdfX
                 + psStep->polycoefmtx[3] * *pdfY
                 + psStep->polycoefmtx[5] * *pdfX * *pdfX
@@ -3412,7 +3465,7 @@ int HFAEvaluateXFormStack( int nStepCount, int bForward,
         }
         else if( psStep->order == 3 )
         {
-            dfXOut = psStep->polycoefvector[0] 
+            dfXOut = psStep->polycoefvector[0]
                 + psStep->polycoefmtx[ 0] * *pdfX
                 + psStep->polycoefmtx[ 2] * *pdfY
                 + psStep->polycoefmtx[ 4] * *pdfX * *pdfX
@@ -3422,7 +3475,7 @@ int HFAEvaluateXFormStack( int nStepCount, int bForward,
                 + psStep->polycoefmtx[12] * *pdfX * *pdfX * *pdfY
                 + psStep->polycoefmtx[14] * *pdfX * *pdfY * *pdfY
                 + psStep->polycoefmtx[16] * *pdfY * *pdfY * *pdfY;
-            dfYOut = psStep->polycoefvector[1] 
+            dfYOut = psStep->polycoefvector[1]
                 + psStep->polycoefmtx[ 1] * *pdfX
                 + psStep->polycoefmtx[ 3] * *pdfY
                 + psStep->polycoefmtx[ 5] * *pdfX * *pdfX
@@ -3447,7 +3500,7 @@ int HFAEvaluateXFormStack( int nStepCount, int bForward,
 /*                         HFAWriteXFormStack()                         */
 /************************************************************************/
 
-CPLErr HFAWriteXFormStack( HFAHandle hHFA, int nBand, int nXFormCount, 
+CPLErr HFAWriteXFormStack( HFAHandle hHFA, int nBand, int nXFormCount,
                            Efga_Polynomial **ppasPolyListForward,
                            Efga_Polynomial **ppasPolyListReverse )
 
@@ -3457,7 +3510,7 @@ CPLErr HFAWriteXFormStack( HFAHandle hHFA, int nBand, int nXFormCount,
 
     if( ppasPolyListForward[0]->order != 1 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "For now HFAWriteXFormStack() only supports order 1 polynomials" );
         return CE_Failure;
     }
@@ -3474,8 +3527,8 @@ CPLErr HFAWriteXFormStack( HFAHandle hHFA, int nBand, int nXFormCount,
 
         for( nBand = 1; nBand <= hHFA->nBands; nBand++ )
         {
-            eErr = HFAWriteXFormStack( hHFA, nBand, nXFormCount, 
-                                       ppasPolyListForward, 
+            eErr = HFAWriteXFormStack( hHFA, nBand, nXFormCount,
+                                       ppasPolyListForward,
                                        ppasPolyListReverse );
             if( eErr != CE_None )
                 return eErr;
@@ -3489,11 +3542,11 @@ CPLErr HFAWriteXFormStack( HFAHandle hHFA, int nBand, int nXFormCount,
 /* -------------------------------------------------------------------- */
     HFAEntry *poBandNode = hHFA->papoBand[nBand-1]->poNode;
     HFAEntry *poXFormHeader;
-    
+
     poXFormHeader = poBandNode->GetNamedChild( "MapToPixelXForm" );
     if( poXFormHeader == NULL )
     {
-        poXFormHeader = new HFAEntry( hHFA, "MapToPixelXForm", 
+        poXFormHeader = HFAEntry::New( hHFA, "MapToPixelXForm",
                                       "Exfr_GenericXFormHeader", poBandNode );
         poXFormHeader->MakeData( 23 );
         poXFormHeader->SetPosition();
@@ -3510,10 +3563,10 @@ CPLErr HFAWriteXFormStack( HFAHandle hHFA, int nBand, int nXFormCount,
         osXFormName.Printf( "XForm%d", iXForm );
 
         HFAEntry *poXForm = poXFormHeader->GetNamedChild( osXFormName );
-        
+
         if( poXForm == NULL )
         {
-            poXForm = new HFAEntry( hHFA, osXFormName, "Efga_Polynomial",
+            poXForm = HFAEntry::New( hHFA, osXFormName, "Efga_Polynomial",
                                     poXFormHeader );
             poXForm->MakeData( 136 );
             poXForm->SetPosition();
@@ -3533,21 +3586,21 @@ CPLErr HFAWriteXFormStack( HFAHandle hHFA, int nBand, int nXFormCount,
         poXForm->SetIntField( "polycoefmtx[-3]", EPT_f64 );
         poXForm->SetIntField( "polycoefmtx[-2]", 2 );
         poXForm->SetIntField( "polycoefmtx[-1]", 2 );
-        poXForm->SetDoubleField( "polycoefmtx[0]", 
+        poXForm->SetDoubleField( "polycoefmtx[0]",
                                  psForward->polycoefmtx[0] );
-        poXForm->SetDoubleField( "polycoefmtx[1]", 
+        poXForm->SetDoubleField( "polycoefmtx[1]",
                                  psForward->polycoefmtx[1] );
-        poXForm->SetDoubleField( "polycoefmtx[2]", 
+        poXForm->SetDoubleField( "polycoefmtx[2]",
                                  psForward->polycoefmtx[2] );
-        poXForm->SetDoubleField( "polycoefmtx[3]", 
+        poXForm->SetDoubleField( "polycoefmtx[3]",
                                  psForward->polycoefmtx[3] );
 
         poXForm->SetIntField( "polycoefvector[-3]", EPT_f64 );
         poXForm->SetIntField( "polycoefvector[-2]", 1 );
         poXForm->SetIntField( "polycoefvector[-1]", 2 );
-        poXForm->SetDoubleField( "polycoefvector[0]", 
+        poXForm->SetDoubleField( "polycoefvector[0]",
                                  psForward->polycoefvector[0] );
-        poXForm->SetDoubleField( "polycoefvector[1]", 
+        poXForm->SetDoubleField( "polycoefvector[1]",
                                  psForward->polycoefvector[1] );
     }
 
@@ -3559,7 +3612,7 @@ CPLErr HFAWriteXFormStack( HFAHandle hHFA, int nBand, int nXFormCount,
 /************************************************************************/
 
 char **HFAReadCameraModel( HFAHandle hHFA )
-    
+
 {
     if( hHFA->nBands == 0 )
         return NULL;
@@ -3569,7 +3622,7 @@ char **HFAReadCameraModel( HFAHandle hHFA )
 /* -------------------------------------------------------------------- */
     HFAEntry *poXForm;
 
-    poXForm = 
+    poXForm =
         hHFA->papoBand[0]->poNode->GetNamedChild( "MapToPixelXForm.XForm0" );
     if( poXForm == NULL )
         return NULL;
@@ -3583,22 +3636,22 @@ char **HFAReadCameraModel( HFAHandle hHFA )
     const char *pszValue;
     int i;
     char **papszMD = NULL;
-    static const char *apszFields[] = { 
+    static const char * const apszFields[] = {
         "direction", "refType", "demsource", "PhotoDirection", "RotationSystem",
-        "demfilename", "demzunits", 
-        "forSrcAffine[0]", "forSrcAffine[1]", "forSrcAffine[2]", 
-        "forSrcAffine[3]", "forSrcAffine[4]", "forSrcAffine[5]", 
-        "forDstAffine[0]", "forDstAffine[1]", "forDstAffine[2]", 
-        "forDstAffine[3]", "forDstAffine[4]", "forDstAffine[5]", 
-        "invSrcAffine[0]", "invSrcAffine[1]", "invSrcAffine[2]", 
-        "invSrcAffine[3]", "invSrcAffine[4]", "invSrcAffine[5]", 
-        "invDstAffine[0]", "invDstAffine[1]", "invDstAffine[2]", 
-        "invDstAffine[3]", "invDstAffine[4]", "invDstAffine[5]", 
-        "z_mean", "lat0", "lon0", 
-        "coeffs[0]", "coeffs[1]", "coeffs[2]", 
-        "coeffs[3]", "coeffs[4]", "coeffs[5]", 
-        "coeffs[6]", "coeffs[7]", "coeffs[8]", 
-        "LensDistortion[0]", "LensDistortion[1]", "LensDistortion[2]", 
+        "demfilename", "demzunits",
+        "forSrcAffine[0]", "forSrcAffine[1]", "forSrcAffine[2]",
+        "forSrcAffine[3]", "forSrcAffine[4]", "forSrcAffine[5]",
+        "forDstAffine[0]", "forDstAffine[1]", "forDstAffine[2]",
+        "forDstAffine[3]", "forDstAffine[4]", "forDstAffine[5]",
+        "invSrcAffine[0]", "invSrcAffine[1]", "invSrcAffine[2]",
+        "invSrcAffine[3]", "invSrcAffine[4]", "invSrcAffine[5]",
+        "invDstAffine[0]", "invDstAffine[1]", "invDstAffine[2]",
+        "invDstAffine[3]", "invDstAffine[4]", "invDstAffine[5]",
+        "z_mean", "lat0", "lon0",
+        "coeffs[0]", "coeffs[1]", "coeffs[2]",
+        "coeffs[3]", "coeffs[4]", "coeffs[5]",
+        "coeffs[6]", "coeffs[7]", "coeffs[8]",
+        "LensDistortion[0]", "LensDistortion[1]", "LensDistortion[2]",
         NULL };
 
     for( i = 0; apszFields[i] != NULL; i++ )
@@ -3624,20 +3677,27 @@ char **HFAReadCameraModel( HFAHandle hHFA )
 
         memset( &sDatum, 0, sizeof(sDatum));
 
-        sDatum.datumname = 
+        sDatum.datumname =
             (char *) poProjInfo->GetStringField("earthModel.datum.datumname");
-        sDatum.type = (Eprj_DatumType) poProjInfo->GetIntField(
-            "earthModel.datum.type");
+
+        int nDatumType = poProjInfo->GetIntField("earthModel.datum.type");
+        if( nDatumType < 0 || nDatumType > EPRJ_DATUM_NONE )
+        {
+            CPLDebug("HFA", "Invalid value for datum type: %d", nDatumType);
+            sDatum.type = EPRJ_DATUM_NONE;
+        }
+        else
+            sDatum.type = static_cast<Eprj_DatumType>(nDatumType);
 
         for( i = 0; i < 7; i++ )
         {
             char	szFieldName[60];
 
-            sprintf( szFieldName, "earthModel.datum.params[%d]", i );
+            snprintf( szFieldName, sizeof(szFieldName), "earthModel.datum.params[%d]", i );
             sDatum.params[i] = poProjInfo->GetDoubleField(szFieldName);
         }
 
-        sDatum.gridname = (char *) 
+        sDatum.gridname = (char *)
             poProjInfo->GetStringField("earthModel.datum.gridname");
 
     /* -------------------------------------------------------------------- */
@@ -3657,7 +3717,7 @@ char **HFAReadCameraModel( HFAHandle hHFA )
         {
             char	szFieldName[40];
 
-            sprintf( szFieldName, "projectionObject.proParams[%d]", i );
+            snprintf( szFieldName, sizeof(szFieldName), "projectionObject.proParams[%d]", i );
             sPro.proParams[i] = poProjInfo->GetDoubleField(szFieldName);
         }
 
@@ -3684,7 +3744,7 @@ char **HFAReadCameraModel( HFAHandle hHFA )
 
         if( pszProjection )
         {
-            papszMD = 
+            papszMD =
                 CSLSetNameValue( papszMD, "outputProjection", pszProjection );
             CPLFree( pszProjection );
         }
@@ -3698,9 +3758,9 @@ char **HFAReadCameraModel( HFAHandle hHFA )
     pszValue = poXForm->GetStringField( "outputHorizontalUnits.string" );
     if( pszValue == NULL )
         pszValue = "";
-    
+
     papszMD = CSLSetNameValue( papszMD, "outputHorizontalUnits", pszValue );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Fetch the elevationinfo.                                        */
 /* -------------------------------------------------------------------- */
@@ -3711,8 +3771,8 @@ char **HFAReadCameraModel( HFAHandle hHFA )
 
         if( poElevInfo->GetDataSize() != 0 )
         {
-            static const char *apszEFields[] = { 
-                "verticalDatum.datumname", 
+            static const char * const apszEFields[] = {
+                "verticalDatum.datumname",
                 "verticalDatum.type",
                 "elevationUnit",
                 "elevationType",
@@ -3741,7 +3801,7 @@ char **HFAReadCameraModel( HFAHandle hHFA )
 /*      and shared geotransforms.                                       */
 /************************************************************************/
 
-CPLErr HFASetGeoTransform( HFAHandle hHFA, 
+CPLErr HFASetGeoTransform( HFAHandle hHFA,
                            const char *pszProName,
                            const char *pszUnits,
                            double *padfGeoTransform )
@@ -3755,13 +3815,13 @@ CPLErr HFASetGeoTransform( HFAHandle hHFA,
     for( nBand = 1; nBand <= hHFA->nBands; nBand++ )
     {
         HFAEntry *poBandNode = hHFA->papoBand[nBand-1]->poNode;
-        
+
         HFAEntry *poMI = poBandNode->GetNamedChild( "MapInformation" );
         if( poMI == NULL )
         {
-            poMI = new HFAEntry( hHFA, "MapInformation", 
+            poMI = HFAEntry::New( hHFA, "MapInformation",
                                  "Eimg_MapInformation", poBandNode );
-            poMI->MakeData( 18 + strlen(pszProName) + strlen(pszUnits) );
+            poMI->MakeData( static_cast<int>(18 + strlen(pszProName) + strlen(pszUnits)) );
             poMI->SetPosition();
         }
 
@@ -3784,7 +3844,8 @@ CPLErr HFASetGeoTransform( HFAHandle hHFA,
     adfAdjTransform[3] += adfAdjTransform[5] * 0.5;
 
     // Invert
-    HFAInvGeoTransform( adfAdjTransform, adfRevTransform );
+    if( !HFAInvGeoTransform( adfAdjTransform, adfRevTransform ) )
+        memset(adfRevTransform, 0, sizeof(adfRevTransform));
 
     // Assign to polynomial object.
 
@@ -3810,8 +3871,8 @@ CPLErr HFASetGeoTransform( HFAHandle hHFA,
 /*      files and should include references to .aux, .rrd and .ige.     */
 /************************************************************************/
 
-CPLErr HFARenameReferences( HFAHandle hHFA, 
-                            const char *pszNewBase, 
+CPLErr HFARenameReferences( HFAHandle hHFA,
+                            const char *pszNewBase,
                             const char *pszOldBase )
 
 {
@@ -3819,7 +3880,7 @@ CPLErr HFARenameReferences( HFAHandle hHFA,
 /*      Handle RRDNamesList updates.                                    */
 /* -------------------------------------------------------------------- */
     size_t iNode;
-    std::vector<HFAEntry*> apoNodeList = 
+    std::vector<HFAEntry*> apoNodeList =
         hHFA->poRoot->FindChildren( "RRDNamesList", NULL );
 
     for( iNode = 0; iNode < apoNodeList.size(); iNode++ )
@@ -3829,14 +3890,14 @@ CPLErr HFARenameReferences( HFAHandle hHFA,
 
         // Collect all the existing names.
         int i, nNameCount = poRRDNL->GetFieldCount( "nameList" );
-        
+
         CPLString osAlgorithm = poRRDNL->GetStringField("algorithm.string");
         for( i = 0; i < nNameCount; i++ )
         {
             CPLString osFN;
             osFN.Printf( "nameList[%d].string", i );
             aosNL.push_back( poRRDNL->GetStringField(osFN) );
-        } 
+        }
 
         // Adjust the names to the new form.
         for( i = 0; i < nNameCount; i++ )
@@ -3847,15 +3908,15 @@ CPLErr HFARenameReferences( HFAHandle hHFA,
                 osNew += aosNL[i].c_str() + strlen(pszOldBase);
                 aosNL[i] = osNew;
             }
-        } 
+        }
 
-        // try to make sure the RRDNamesList is big enough to hold the 
-        // adjusted name list. 
+        // try to make sure the RRDNamesList is big enough to hold the
+        // adjusted name list.
         if( strlen(pszNewBase) > strlen(pszOldBase) )
         {
             CPLDebug( "HFA", "Growing RRDNamesList to hold new names" );
-            poRRDNL->MakeData( poRRDNL->GetDataSize() 
-                               + nNameCount * (strlen(pszNewBase) - strlen(pszOldBase)) );
+            poRRDNL->MakeData( static_cast<int>(poRRDNL->GetDataSize()
+                               + nNameCount * (strlen(pszNewBase) - strlen(pszOldBase))) );
         }
 
         // Initialize the whole thing to zeros for a clean start.
@@ -3868,7 +3929,7 @@ CPLErr HFARenameReferences( HFAHandle hHFA,
             CPLString osFN;
             osFN.Printf( "nameList[%d].string", i );
             poRRDNL->SetStringField( osFN, aosNL[i] );
-        } 
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -3884,25 +3945,25 @@ CPLErr HFARenameReferences( HFAHandle hHFA,
         if( poERDMS == NULL )
             continue;
 
-        // Fetch all existing values. 
+        // Fetch all existing values.
         CPLString osFileName = poERDMS->GetStringField("fileName.string");
         GInt32 anValidFlagsOffset[2], anStackDataOffset[2];
         GInt32 nStackCount, nStackIndex;
 
-        anValidFlagsOffset[0] = 
+        anValidFlagsOffset[0] =
             poERDMS->GetIntField( "layerStackValidFlagsOffset[0]" );
-        anValidFlagsOffset[1] = 
+        anValidFlagsOffset[1] =
             poERDMS->GetIntField( "layerStackValidFlagsOffset[1]" );
-        
-        anStackDataOffset[0] = 
+
+        anStackDataOffset[0] =
             poERDMS->GetIntField( "layerStackDataOffset[0]" );
-        anStackDataOffset[1] = 
+        anStackDataOffset[1] =
             poERDMS->GetIntField( "layerStackDataOffset[1]" );
 
         nStackCount = poERDMS->GetIntField( "layerStackCount" );
         nStackIndex = poERDMS->GetIntField( "layerStackIndex" );
 
-        // Update the filename. 
+        // Update the filename.
         if( strncmp(osFileName,pszOldBase,strlen(pszOldBase)) == 0 )
         {
             CPLString osNew = pszNewBase;
@@ -3914,8 +3975,8 @@ CPLErr HFARenameReferences( HFAHandle hHFA,
         if( strlen(pszNewBase) > strlen(pszOldBase) )
         {
             CPLDebug( "HFA", "Growing ExternalRasterDMS to hold new names" );
-            poERDMS->MakeData( poERDMS->GetDataSize() 
-                               + (strlen(pszNewBase) - strlen(pszOldBase)) );
+            poERDMS->MakeData( static_cast<int>(poERDMS->GetDataSize()
+                               + (strlen(pszNewBase) - strlen(pszOldBase))) );
         }
 
         // Initialize the whole thing to zeros for a clean start.
@@ -3923,14 +3984,14 @@ CPLErr HFARenameReferences( HFAHandle hHFA,
 
         // Write it all out again, this may change the size of the node.
         poERDMS->SetStringField( "fileName.string", osFileName );
-        poERDMS->SetIntField( "layerStackValidFlagsOffset[0]", 
+        poERDMS->SetIntField( "layerStackValidFlagsOffset[0]",
                               anValidFlagsOffset[0] );
-        poERDMS->SetIntField( "layerStackValidFlagsOffset[1]", 
+        poERDMS->SetIntField( "layerStackValidFlagsOffset[1]",
                               anValidFlagsOffset[1] );
-        
-        poERDMS->SetIntField( "layerStackDataOffset[0]", 
+
+        poERDMS->SetIntField( "layerStackDataOffset[0]",
                               anStackDataOffset[0] );
-        poERDMS->SetIntField( "layerStackDataOffset[1]", 
+        poERDMS->SetIntField( "layerStackDataOffset[1]",
                               anStackDataOffset[1] );
 
         poERDMS->SetIntField( "layerStackCount", nStackCount );
@@ -3952,12 +4013,12 @@ CPLErr HFARenameReferences( HFAHandle hHFA,
         if( strlen(pszNewBase) > strlen(pszOldBase) )
         {
             CPLDebug( "HFA", "Growing DependentFile to hold new names" );
-            apoNodeList[iNode]->MakeData( apoNodeList[iNode]->GetDataSize() 
-                                          + (strlen(pszNewBase) 
-                                             - strlen(pszOldBase)) );
+            apoNodeList[iNode]->MakeData( static_cast<int>(apoNodeList[iNode]->GetDataSize()
+                                          + (strlen(pszNewBase)
+                                             - strlen(pszOldBase))) );
         }
 
-        // Update the filename. 
+        // Update the filename.
         if( strncmp(osFileName,pszOldBase,strlen(pszOldBase)) == 0 )
         {
             CPLString osNew = pszNewBase;
@@ -3966,7 +4027,7 @@ CPLErr HFARenameReferences( HFAHandle hHFA,
         }
 
         apoNodeList[iNode]->SetStringField( "dependent.string", osFileName );
-    }        
+    }
 
     return CE_None;
 }
diff --git a/frmts/hfa/hfatest.cpp b/frmts/hfa/hfatest.cpp
index 07b28fa..5a55f46 100644
--- a/frmts/hfa/hfatest.cpp
+++ b/frmts/hfa/hfatest.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfatest.cpp 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: hfatest.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Testing mainline for HFA services - transitory.
@@ -31,7 +31,7 @@
 #include "hfa_p.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: hfatest.cpp 27044 2014-03-16 23:41:27Z rouault $");
+CPL_CVSID("$Id: hfatest.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /*                               Usage()                                */
@@ -49,10 +49,10 @@ static void Usage()
 /************************************************************************/
 #ifndef WIN32
 char *
-HFAPCSStructToWKT( const Eprj_Datum *psDatum,
-                   const Eprj_ProParameters *psPro,
-                   const Eprj_MapInfo *psMapInfo,
-                   HFAEntry *poMapInformation )
+HFAPCSStructToWKT( const Eprj_Datum *,
+                   const Eprj_ProParameters *,
+                   const Eprj_MapInfo *,
+                   HFAEntry * )
 {
     return NULL;
 }
@@ -65,27 +65,22 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
 int main( int argc, char ** argv )
 
 {
-    const char	*pszFilename = NULL;
-    int		nDumpTree = FALSE;
-    int		nDumpDict = FALSE;
-    int		nRastReport = FALSE;
-    int		i, nXSize, nYSize, nBands;
-    HFAHandle	hHFA;
-    const Eprj_MapInfo *psMapInfo;
-    const Eprj_ProParameters *psProParameters;
-    const Eprj_Datum *psDatum;
-
 /* -------------------------------------------------------------------- */
 /*      Handle arguments.                                               */
 /* -------------------------------------------------------------------- */
-    for( i = 1; i < argc; i++ )
+    const char *pszFilename = NULL;
+    bool bDumpTree = false;
+    bool bDumpDict = false;
+    bool bRastReport = false;
+
+    for( int i = 1; i < argc; i++ )
     {
         if( EQUAL(argv[i],"-dd") )
-            nDumpDict = TRUE;
+            bDumpDict = TRUE;
         else if( EQUAL(argv[i],"-dt") )
-            nDumpTree = TRUE;
+            bDumpTree = TRUE;
         else if( EQUAL(argv[i],"-dr") )
-            nRastReport = TRUE;
+            bRastReport = TRUE;
         else if( pszFilename == NULL )
             pszFilename = argv[i];
         else
@@ -104,7 +99,7 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
 /*      Open the file.                                                  */
 /* -------------------------------------------------------------------- */
-    hHFA = HFAOpen( pszFilename, "r" );
+    HFAHandle hHFA = HFAOpen( pszFilename, "r" );
 
     if( hHFA == NULL )
     {
@@ -115,7 +110,7 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
 /*      Do we want to walk the tree dumping out general information?    */
 /* -------------------------------------------------------------------- */
-    if( nDumpDict )
+    if( bDumpDict )
     {
         HFADumpDictionary( hHFA, stdout );
     }
@@ -123,7 +118,7 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
 /*      Do we want to walk the tree dumping out general information?    */
 /* -------------------------------------------------------------------- */
-    if( nDumpTree )
+    if( bDumpTree )
     {
         HFADumpTree( hHFA, stdout );
     }
@@ -131,45 +126,47 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
 /*      Dump indirectly collected data about bands.                     */
 /* -------------------------------------------------------------------- */
+    int nXSize, nYSize, nBands;
     HFAGetRasterInfo( hHFA, &nXSize, &nYSize, &nBands );
 
-    if( nRastReport )
+    if( bRastReport )
     {
         printf( "Raster Size = %d x %d\n", nXSize, nYSize );
 
-        for( i = 1; i <= nBands; i++ )
+        for( int i = 1; i <= nBands; i++ )
         {
-            int	nDataType, nColors, nOverviews, iOverview;
-            double	*padfRed, *padfGreen, *padfBlue, *padfAlpha, *padfBins;
-            int nBlockXSize, nBlockYSize, nCompressionType;
-        
-            HFAGetBandInfo( hHFA, i, &nDataType, &nBlockXSize, &nBlockYSize, 
+            EPTType eDataType;
+            int nBlockXSize;
+            int nBlockYSize;
+            int nCompressionType;
+
+            HFAGetBandInfo( hHFA, i, &eDataType, &nBlockXSize, &nBlockYSize,
                             &nCompressionType );
-            nOverviews = HFAGetOverviewCount( hHFA, i );
+            int nOverviews = HFAGetOverviewCount( hHFA, i );
 
             printf( "Band %d: %dx%d tiles, type = %d\n",
-                    i, nBlockXSize, nBlockYSize, nDataType );
+                    i, nBlockXSize, nBlockYSize, eDataType );
 
-            for( iOverview=0; iOverview < nOverviews; iOverview++ )
+            for( int iOverview=0; iOverview < nOverviews; iOverview++ )
             {
-                HFAGetOverviewInfo( hHFA, i, iOverview, 
-                                    &nXSize, &nYSize, 
+                HFAGetOverviewInfo( hHFA, i, iOverview,
+                                    &nXSize, &nYSize,
                                     &nBlockXSize, &nBlockYSize, NULL );
-                printf( "  Overview: %dx%d (blocksize %dx%d)\n", 
+                printf( "  Overview: %dx%d (blocksize %dx%d)\n",
                         nXSize, nYSize, nBlockXSize, nBlockYSize );
             }
 
-            if( HFAGetPCT( hHFA, i, &nColors, &padfRed, &padfGreen, 
+            int nColors;
+            double *padfRed, *padfGreen, *padfBlue, *padfAlpha, *padfBins;
+            if( HFAGetPCT( hHFA, i, &nColors, &padfRed, &padfGreen,
 			   &padfBlue, &padfAlpha, &padfBins )
                 == CE_None )
             {
-                int	j;
-
-                for( j = 0; j < nColors; j++ )
+                for( int j = 0; j < nColors; j++ )
                 {
                     printf( "PCT[%d] = %f,%f,%f %f\n",
                             (padfBins != NULL) ? (int) padfBins[j] : j,
-                            padfRed[j], padfGreen[j], 
+                            padfRed[j], padfGreen[j],
 			    padfBlue[j], padfAlpha[j]);
                 }
             }
@@ -198,7 +195,7 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
 /*      Dump the map info structure.                                    */
 /* -------------------------------------------------------------------- */
-        psMapInfo = HFAGetMapInfo( hHFA );
+        const Eprj_MapInfo *psMapInfo = HFAGetMapInfo( hHFA );
 
         if( psMapInfo != NULL )
         {
@@ -214,11 +211,16 @@ int main( int argc, char ** argv )
         }
 
     }
-    
-    psProParameters = HFAGetProParameters( hHFA );
 
-    psDatum = HFAGetDatum( hHFA );
-    
+
+    // const Eprj_ProParameters *psProParameters;
+    // psProParameters =
+    HFAGetProParameters( hHFA );
+
+    // const Eprj_Datum *psDatum;
+    // psDatum =
+    HFAGetDatum( hHFA );
+
     HFAClose( hHFA );
 
     VSICleanupFileManager();
diff --git a/frmts/hfa/hfatype.cpp b/frmts/hfa/hfatype.cpp
index da95e36..5ef0fe5 100644
--- a/frmts/hfa/hfatype.cpp
+++ b/frmts/hfa/hfatype.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfatype.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: hfatype.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Implementation of the HFAType class, for managing one type
@@ -31,7 +31,7 @@
 
 #include "hfa_p.h"
 
-CPL_CVSID("$Id: hfatype.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: hfatype.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -43,15 +43,13 @@ CPL_CVSID("$Id: hfatype.cpp 27745 2014-09-27 16:38:57Z goatbar $");
 /*                              HFAType()                               */
 /************************************************************************/
 
-HFAType::HFAType()
-
-{
-    nBytes = 0;
-    nFields = 0;
-    papoFields = NULL;
-    pszTypeName = NULL;
-    bInCompleteDefn = FALSE;
-}
+HFAType::HFAType() :
+    bInCompleteDefn(FALSE),
+    nBytes(0),
+    nFields(0),
+    papoFields(NULL),
+    pszTypeName(NULL)
+{ }
 
 /************************************************************************/
 /*                              ~HFAType()                              */
@@ -60,9 +58,7 @@ HFAType::HFAType()
 HFAType::~HFAType()
 
 {
-    int		i;
-
-    for( i = 0; i < nFields; i++ )
+    for( int i = 0; i < nFields; i++ )
     {
         delete papoFields[i];
     }
@@ -79,9 +75,6 @@ HFAType::~HFAType()
 const char *HFAType::Initialize( const char * pszInput )
 
 {
-    int		i;
-    
-    
     if( *pszInput != '{' )
     {
         if( *pszInput != '\0' )
@@ -122,15 +115,15 @@ const char *HFAType::Initialize( const char * pszInput )
 /*      Collect the name.                                               */
 /* -------------------------------------------------------------------- */
     pszInput++; /* skip `}' */
-
-    for( i = 0; pszInput[i] != '\0' && pszInput[i] != ','; i++ ) {}
+    int i = 0;
+    for( ; pszInput[i] != '\0' && pszInput[i] != ','; i++ ) {}
     if (pszInput[i] == '\0')
         return NULL;
 
     pszTypeName = (char *) CPLMalloc(i+1);
     strncpy( pszTypeName, pszInput, i );
     pszTypeName[i] = '\0';
-    
+
     pszInput += i+1;
 
     return( pszInput );
@@ -143,8 +136,6 @@ const char *HFAType::Initialize( const char * pszInput )
 void HFAType::CompleteDefn( HFADictionary * poDict )
 
 {
-    int		i;
-
 /* -------------------------------------------------------------------- */
 /*      This may already be done, if an earlier object required this    */
 /*      object (as a field), and forced an early computation of the     */
@@ -167,13 +158,15 @@ void HFAType::CompleteDefn( HFADictionary * poDict )
 /*      isn't really accurate for object with variable sized            */
 /*      subobjects.                                                     */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < nFields; i++ )
+    for( int i = 0; i < nFields; i++ )
     {
         papoFields[i]->CompleteDefn( poDict );
         if( papoFields[i]->nBytes < 0 || nBytes == -1 )
             nBytes = -1;
-        else
+        else if( nBytes < INT_MAX - papoFields[i]->nBytes )
             nBytes += papoFields[i]->nBytes;
+        else
+            nBytes = -1;
     }
 
     bInCompleteDefn = FALSE;
@@ -186,30 +179,29 @@ void HFAType::CompleteDefn( HFADictionary * poDict )
 void HFAType::Dump( FILE * fp )
 
 {
-    int		i;
-    
-    VSIFPrintf( fp, "HFAType %s/%d bytes\n", pszTypeName, nBytes );
+    CPL_IGNORE_RET_VAL(VSIFPrintf( fp, "HFAType %s/%d bytes\n", pszTypeName, nBytes ));
 
-    for( i = 0; i < nFields; i++ )
+    for( int i = 0; i < nFields; i++ )
     {
         papoFields[i]->Dump( fp );
     }
 
-    VSIFPrintf( fp, "\n" );
+    CPL_IGNORE_RET_VAL(VSIFPrintf( fp, "\n" ));
 }
 
 /************************************************************************/
 /*                            SetInstValue()                            */
 /************************************************************************/
 
-CPLErr 
+CPLErr
 HFAType::SetInstValue( const char * pszFieldPath,
                        GByte *pabyData, GUInt32 nDataOffset, int nDataSize,
                        char chReqType, void *pValue )
 
 {
-    int		nArrayIndex = 0, nNameLen, iField, nByteOffset;
-    const char	*pszRemainder;
+    int nArrayIndex = 0;
+    int nNameLen;
+    const char *pszRemainder;
 
 /* -------------------------------------------------------------------- */
 /*      Parse end of field name, possible index value and               */
@@ -218,9 +210,9 @@ HFAType::SetInstValue( const char * pszFieldPath,
     if( strchr(pszFieldPath,'[') != NULL )
     {
         const char	*pszEnd = strchr(pszFieldPath,'[');
-        
+
         nArrayIndex = atoi(pszEnd+1);
-        nNameLen = pszEnd - pszFieldPath;
+        nNameLen = static_cast<int>(pszEnd - pszFieldPath);
 
         pszRemainder = strchr(pszFieldPath,'.');
         if( pszRemainder != NULL )
@@ -230,23 +222,24 @@ HFAType::SetInstValue( const char * pszFieldPath,
     else if( strchr(pszFieldPath,'.') != NULL )
     {
         const char	*pszEnd = strchr(pszFieldPath,'.');
-        
-        nNameLen = pszEnd - pszFieldPath;
+
+        nNameLen = static_cast<int>(pszEnd - pszFieldPath);
 
         pszRemainder = pszEnd + 1;
     }
 
     else
     {
-        nNameLen = strlen(pszFieldPath);
+        nNameLen = static_cast<int>(strlen(pszFieldPath));
         pszRemainder = pszFieldPath/*NULL*/;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Find this field within this type, if possible.                  */
 /* -------------------------------------------------------------------- */
-    nByteOffset = 0;
-    for( iField = 0; iField < nFields && nByteOffset < nDataSize; iField++ )
+    int nByteOffset = 0;
+    int iField = 0;
+    for( ; iField < nFields && nByteOffset < nDataSize; iField++ )
     {
         if( EQUALN(pszFieldPath,papoFields[iField]->pszFieldName,nNameLen)
             && papoFields[iField]->pszFieldName[nNameLen] == '\0' )
@@ -290,8 +283,8 @@ HFAType::GetInstCount( const char * pszFieldPath,
                        int nDataSize )
 {
     /* int		nArrayIndex = 0; */
-    int		nNameLen, iField, nByteOffset;
-    const char	*pszRemainder;
+    int		nNameLen;
+    /*const char	*pszRemainder;*/
 
 /* -------------------------------------------------------------------- */
 /*      Parse end of field name, possible index value and               */
@@ -302,33 +295,34 @@ HFAType::GetInstCount( const char * pszFieldPath,
         const char	*pszEnd = strchr(pszFieldPath,'[');
 
         /* nArrayIndex = atoi(pszEnd+1); */
-        nNameLen = pszEnd - pszFieldPath;
+        nNameLen = static_cast<int>(pszEnd - pszFieldPath);
 
-        pszRemainder = strchr(pszFieldPath,'.');
+        /*pszRemainder = strchr(pszFieldPath,'.');
         if( pszRemainder != NULL )
-            pszRemainder++;
+            pszRemainder++;*/
     }
 
     else if( strchr(pszFieldPath,'.') != NULL )
     {
         const char	*pszEnd = strchr(pszFieldPath,'.');
 
-        nNameLen = pszEnd - pszFieldPath;
+        nNameLen = static_cast<int>(pszEnd - pszFieldPath);
 
-        pszRemainder = pszEnd + 1;
+        /*pszRemainder = pszEnd + 1;*/
     }
 
     else
     {
-        nNameLen = strlen(pszFieldPath);
-        pszRemainder = NULL;
+        nNameLen = static_cast<int>(strlen(pszFieldPath));
+        /*pszRemainder = NULL;*/
     }
 
 /* -------------------------------------------------------------------- */
 /*      Find this field within this type, if possible.                  */
 /* -------------------------------------------------------------------- */
-    nByteOffset = 0;
-    for( iField = 0; iField < nFields && nByteOffset < nDataSize; iField++ )
+    int nByteOffset = 0;
+    int iField = 0;
+    for( ; iField < nFields && nByteOffset < nDataSize; iField++ )
     {
         if( EQUALN(pszFieldPath,papoFields[iField]->pszFieldName,nNameLen)
             && papoFields[iField]->pszFieldName[nNameLen] == '\0' )
@@ -363,7 +357,7 @@ HFAType::GetInstCount( const char * pszFieldPath,
 /*                                                                      */
 /*      Extract the value of a field instance within this type.         */
 /*      Most of the work is done by the ExtractInstValue() for the      */
-/*      HFAField, but this methond does the field name parsing.         */
+/*      HFAField, but this method does the field name parsing.          */
 /*                                                                      */
 /*      field names have the form:                                      */
 /*                                                                      */
@@ -382,8 +376,9 @@ HFAType::ExtractInstValue( const char * pszFieldPath,
                            char chReqType, void *pReqReturn, int *pnRemainingDataSize )
 
 {
-    int		nArrayIndex = 0, nNameLen, iField, nByteOffset;
-    const char	*pszRemainder;
+    int nArrayIndex = 0;
+    int nNameLen;
+    const char *pszRemainder;
 
 /* -------------------------------------------------------------------- */
 /*      Parse end of field name, possible index value and               */
@@ -397,9 +392,9 @@ HFAType::ExtractInstValue( const char * pszFieldPath,
             || pszFirstDot > pszFirstArray) )
     {
         const char	*pszEnd = pszFirstArray;
-        
+
         nArrayIndex = atoi(pszEnd+1);
-        nNameLen = pszEnd - pszFieldPath;
+        nNameLen = static_cast<int>(pszEnd - pszFieldPath);
 
         pszRemainder = strchr(pszFieldPath,'.');
         if( pszRemainder != NULL )
@@ -409,23 +404,24 @@ HFAType::ExtractInstValue( const char * pszFieldPath,
     else if( pszFirstDot != NULL )
     {
         const char	*pszEnd = pszFirstDot;
-        
-        nNameLen = pszEnd - pszFieldPath;
+
+        nNameLen = static_cast<int>(pszEnd - pszFieldPath);
 
         pszRemainder = pszEnd + 1;
     }
 
     else
     {
-        nNameLen = strlen(pszFieldPath);
+        nNameLen = static_cast<int>(strlen(pszFieldPath));
         pszRemainder = NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Find this field within this type, if possible.                  */
 /* -------------------------------------------------------------------- */
-    nByteOffset = 0;
-    for( iField = 0; iField < nFields && nByteOffset < nDataSize; iField++ )
+    int nByteOffset = 0;
+    int iField = 0;
+    for( ; iField < nFields && nByteOffset < nDataSize; iField++ )
     {
         if( EQUALN(pszFieldPath,papoFields[iField]->pszFieldName,nNameLen)
             && papoFields[iField]->pszFieldName[nNameLen] == '\0' )
@@ -470,17 +466,14 @@ void HFAType::DumpInstValue( FILE * fpOut,
                              int nDataSize, const char * pszPrefix )
 
 {
-    int		iField;
-    
-    for ( iField = 0; iField < nFields && nDataSize > 0; iField++ )
+    for ( int iField = 0; iField < nFields && nDataSize > 0; iField++ )
     {
         HFAField	*poField = papoFields[iField];
-        int		nInstBytes;
-        
+
         poField->DumpInstValue( fpOut, pabyData, nDataOffset,
                                 nDataSize, pszPrefix );
 
-        nInstBytes = poField->GetInstBytes( pabyData, nDataSize );
+        const int nInstBytes = poField->GetInstBytes( pabyData, nDataSize );
         if (nInstBytes < 0 || nDataOffset > UINT_MAX - nInstBytes)
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Invalid return value");
@@ -490,7 +483,7 @@ void HFAType::DumpInstValue( FILE * fpOut,
         pabyData += nInstBytes;
         nDataOffset += nInstBytes;
         nDataSize -= nInstBytes;
-    }    
+    }
 }
 
 /************************************************************************/
@@ -504,27 +497,24 @@ int HFAType::GetInstBytes( GByte *pabyData, int nDataSize )
 {
     if( nBytes >= 0 )
         return( nBytes );
-    else
+
+    int	nTotal = 0;
+
+    for( int iField = 0; iField < nFields && nTotal < nDataSize; iField++ )
     {
-        int	nTotal = 0;
-        int	iField;
-    
-        for( iField = 0; iField < nFields && nTotal < nDataSize; iField++ )
+        HFAField	*poField = papoFields[iField];
+
+        const int nInstBytes = poField->GetInstBytes( pabyData,
+                                                      nDataSize - nTotal );
+        if (nInstBytes < 0 || nTotal > INT_MAX - nInstBytes)
         {
-            HFAField	*poField = papoFields[iField];
-
-            int nInstBytes = poField->GetInstBytes( pabyData,
-                                                    nDataSize - nTotal );
-            if (nInstBytes < 0 || nTotal > INT_MAX - nInstBytes)
-            {
-                CPLError(CE_Failure, CPLE_AppDefined, "Invalid return value");
-                return -1;
-            }
-
-            pabyData += nInstBytes;
-            nTotal += nInstBytes;
+            CPLError(CE_Failure, CPLE_AppDefined, "Invalid return value");
+            return -1;
         }
 
-        return( nTotal );
+        pabyData += nInstBytes;
+        nTotal += nInstBytes;
     }
+
+    return( nTotal );
 }
diff --git a/frmts/hfa/makefile.vc b/frmts/hfa/makefile.vc
index f38e2bb..a50de96 100644
--- a/frmts/hfa/makefile.vc
+++ b/frmts/hfa/makefile.vc
@@ -8,7 +8,7 @@ GDAL_ROOT	=	..\..
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
 default:	$(OBJ)
-        for %I in ($(OBJ)) do xcopy /D  /Y %I ..\o
+        xcopy /D  /Y *.obj ..\o
 
 clean:
 	-del *.obj
diff --git a/frmts/idrisi/IdrisiDataset.cpp b/frmts/idrisi/IdrisiDataset.cpp
index ac56d28..5be3936 100644
--- a/frmts/idrisi/IdrisiDataset.cpp
+++ b/frmts/idrisi/IdrisiDataset.cpp
@@ -1,5 +1,5 @@
 /*****************************************************************************
-* $Id: IdrisiDataset.cpp 27942 2014-11-11 00:57:41Z rouault $
+* $Id: IdrisiDataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
 *
 * Project:  Idrisi Raster Image File Driver
 * Purpose:  Read/write Idrisi Raster Image Format RST
@@ -32,107 +32,104 @@
 * DEALINGS IN THE SOFTWARE.
 ****************************************************************************/
 
-#include "gdal_priv.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
 #include "cpl_csv.h"
-#include "ogr_spatialref.h"
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 #include "gdal_alg.h"
+#include "gdal_priv.h"
 #include "gdal_rat.h"
+#include "ogr_spatialref.h"
 #include "idrisi.h"
 
-CPL_CVSID( "$Id: IdrisiDataset.cpp 27942 2014-11-11 00:57:41Z rouault $" );
+CPL_CVSID( "$Id: IdrisiDataset.cpp 33720 2016-03-15 00:39:53Z goatbar $" );
 
-CPL_C_START
-void GDALRegister_IDRISI( void);
-CPL_C_END
-
-#ifdef WIN32        
-#define PATHDELIM       '\\'
+#ifdef WIN32
+#  define PATHDELIM       '\\'
 #else
-#define PATHDELIM       '/'
-#endif 
+#  define PATHDELIM       '/'
+#endif
 
 //----- Safe numeric conversion, NULL as zero
 #define atoi_nz(s) (s == NULL ? (int)      0 : atoi(s))
 #define CPLAtof_nz(s) (s == NULL ? (double) 0.0 : CPLAtof(s))
 
 //----- file extensions:
-#define extRST          "rst"
-#define extRDC          "rdc"
-#define extSMP          "smp"
-#define extREF          "ref"
-#define extRSTu         "RST"
-#define extRDCu         "RDC"
-#define extSMPu         "SMP"
-#define extREFu         "REF"
+static const char * const extRST = "rst";
+static const char * const extRDC         = "rdc";
+static const char * const extSMP         = "smp";
+static const char * const extREF         = "ref";
+// static const char * const extRSTu        = "RST";
+static const char * const extRDCu        = "RDC";
+static const char * const extSMPu        = "SMP";
+static const char * const extREFu        = "REF";
 
 //----- field names on rdc file:
-#define rdcFILE_FORMAT  "file format "
-#define rdcFILE_TITLE   "file title  "
-#define rdcDATA_TYPE    "data type   "
-#define rdcFILE_TYPE    "file type   "
-#define rdcCOLUMNS      "columns     "
-#define rdcROWS         "rows        "
-#define rdcREF_SYSTEM   "ref. system "
-#define rdcREF_UNITS    "ref. units  "
-#define rdcUNIT_DIST    "unit dist.  "
-#define rdcMIN_X        "min. X      "
-#define rdcMAX_X        "max. X      "
-#define rdcMIN_Y        "min. Y      "
-#define rdcMAX_Y        "max. Y      "
-#define rdcPOSN_ERROR   "pos'n error "
-#define rdcRESOLUTION   "resolution  "
-#define rdcMIN_VALUE    "min. value  "
-#define rdcMAX_VALUE    "max. value  "
-#define rdcDISPLAY_MIN  "display min "
-#define rdcDISPLAY_MAX  "display max "
-#define rdcVALUE_UNITS  "value units "
-#define rdcVALUE_ERROR  "value error "
-#define rdcFLAG_VALUE   "flag value  "
-#define rdcFLAG_DEFN    "flag def'n  "
-#define rdcFLAG_DEFN2   "flag def`n  "
-#define rdcLEGEND_CATS  "legend cats "
-#define rdcLINEAGES     "lineage     "
-#define rdcCOMMENTS     "comment     "
-#define rdcCODE_N       "code %6d "
+static const char * const rdcFILE_FORMAT  = "file format ";
+static const char * const rdcFILE_TITLE   = "file title  ";
+static const char * const rdcDATA_TYPE    = "data type   ";
+static const char * const rdcFILE_TYPE    = "file type   ";
+static const char * const rdcCOLUMNS      = "columns     ";
+static const char * const rdcROWS         = "rows        ";
+static const char * const rdcREF_SYSTEM   = "ref. system ";
+static const char * const rdcREF_UNITS    = "ref. units  ";
+static const char * const rdcUNIT_DIST    = "unit dist.  ";
+static const char * const rdcMIN_X        = "min. X      ";
+static const char * const rdcMAX_X        = "max. X      ";
+static const char * const rdcMIN_Y        = "min. Y      ";
+static const char * const rdcMAX_Y        = "max. Y      ";
+static const char * const rdcPOSN_ERROR   = "pos'n error ";
+static const char * const rdcRESOLUTION   = "resolution  ";
+static const char * const rdcMIN_VALUE    = "min. value  ";
+static const char * const rdcMAX_VALUE    = "max. value  ";
+static const char * const rdcDISPLAY_MIN  = "display min ";
+static const char * const rdcDISPLAY_MAX  = "display max ";
+static const char * const rdcVALUE_UNITS  = "value units ";
+static const char * const rdcVALUE_ERROR  = "value error ";
+static const char * const rdcFLAG_VALUE   = "flag value  ";
+static const char * const rdcFLAG_DEFN    = "flag def'n  ";
+static const char * const rdcFLAG_DEFN2   = "flag def`n  ";
+static const char * const rdcLEGEND_CATS  = "legend cats ";
+static const char * const rdcLINEAGES     = "lineage     ";
+static const char * const rdcCOMMENTS     = "comment     ";
+static const char * const rdcCODE_N       = "code %6d ";
 
 //----- ".ref" file field names:
-#define refREF_SYSTEM   "ref. system "
-#define refREF_SYSTEM2  "ref.system  "
-#define refPROJECTION   "projection  "
-#define refDATUM        "datum       " 
-#define refDELTA_WGS84  "delta WGS84 " 
-#define refELLIPSOID    "ellipsoid   "
-#define refMAJOR_SAX    "major s-ax  " 
-#define refMINOR_SAX    "minor s-ax  "
-#define refORIGIN_LONG  "origin long "
-#define refORIGIN_LAT   "origin lat  "
-#define refORIGIN_X     "origin X    "
-#define refORIGIN_Y     "origin Y    "
-#define refSCALE_FAC    "scale fac   "
-#define refUNITS        "units       "
-#define refPARAMETERS   "parameters  "
-#define refSTANDL_1     "stand ln 1  "
-#define refSTANDL_2     "stand ln 2  "
+static const char * const refREF_SYSTEM   = "ref. system ";
+static const char * const refREF_SYSTEM2  = "ref.system  ";
+static const char * const refPROJECTION   = "projection  ";
+static const char * const refDATUM        = "datum       " ;
+static const char * const refDELTA_WGS84  = "delta WGS84 " ;
+static const char * const refELLIPSOID    = "ellipsoid   ";
+static const char * const refMAJOR_SAX    = "major s-ax  " ;
+static const char * const refMINOR_SAX    = "minor s-ax  ";
+static const char * const refORIGIN_LONG  = "origin long ";
+static const char * const refORIGIN_LAT   = "origin lat  ";
+static const char * const refORIGIN_X     = "origin X    ";
+static const char * const refORIGIN_Y     = "origin Y    ";
+static const char * const refSCALE_FAC    = "scale fac   ";
+static const char * const refUNITS        = "units       ";
+static const char * const refPARAMETERS   = "parameters  ";
+static const char * const refSTANDL_1     = "stand ln 1  ";
+static const char * const refSTANDL_2     = "stand ln 2  ";
 
 //----- standard values:
-#define rstVERSION      "Idrisi Raster A.1"
-#define rstBYTE         "byte"
-#define rstINTEGER      "integer"
-#define rstREAL         "real"
-#define rstRGB24        "rgb24"
-#define rstDEGREE       "deg"
-#define rstMETER        "m"
-#define rstLATLONG      "latlong"
-#define rstLATLONG2     "lat/long"
-#define rstPLANE        "plane"
-#define rstUTM          "utm-%d%c"
-#define rstSPC          "spc%2d%2s%d"
+static const char * const rstVERSION      = "Idrisi Raster A.1";
+static const char * const rstBYTE         = "byte";
+static const char * const rstINTEGER      = "integer";
+static const char * const rstREAL         = "real";
+static const char * const rstRGB24        = "rgb24";
+static const char * const rstDEGREE       = "deg";
+static const char * const rstMETER        = "m";
+static const char * const rstLATLONG      = "latlong";
+static const char * const rstLATLONG2     = "lat/long";
+static const char * const rstPLANE        = "plane";
+static const char * const rstUTM          = "utm-%d%c";
+static const char * const rstSPC          = "spc%2d%2s%d";
 
 //----- palette file( .smp ) header size:
-#define smpHEADERSIZE    18
+static const int smpHEADERSIZE = 18;
 
 //----- check if file exists:
 bool FileExists( const char *pszPath );
@@ -205,7 +202,7 @@ struct OriginTab83 {
 	const char *spcs;
 };
 
-#define ORIGIN_COUNT    148
+static const int ORIGIN_COUNT = 148;
 
 //---- USA State plane coordinate system in IDRISI
 static const OriginTab83 SPCS83Origin[] = {
@@ -245,8 +242,8 @@ static const OriginTab83 SPCS83Origin[] = {
 	{156.67,  20.33,    "SPC83HI2"},
 	{158.00,  21.17,    "SPC83HI3"},
 	{159.50,  21.83,    "SPC83HI4"},
-	{160.17,  21.67,    "SPC83HI5"}, 
-	{112.17,  41.67,    "SPC83ID1"}, 
+	{160.17,  21.67,    "SPC83HI5"},
+	{112.17,  41.67,    "SPC83ID1"},
 	{114.00,  41.67,    "SPC83ID2"},
 	{115.75,  41.67,    "SPC83ID3"},
 	{88.33,   36.67,    "SPC83IL1"},
@@ -300,7 +297,7 @@ static const OriginTab83 SPCS83Origin[] = {
 	{118.58,  34.75,    "SPC83NV3"},
 	{71.67,   42.50,    "SPC83NH1"},
 	{74.50,   38.83,    "SPC83NJ1"},
-	{74.67,   38.83,    "SPC27NJ1"},//NAD27 
+	{74.67,   38.83,    "SPC27NJ1"},//NAD27
 	{104.33,  31.00,    "SPC83NM1"},
 	{106.25,  31.00,    "SPC83NM2"},
 	{107.83,  31.00,    "SPC83NM3"},
@@ -374,7 +371,7 @@ int GetStateCode ( const char *pszState );
 const char *GetStateName( int nCode );
 
 //----- Conversion Table definition
-struct ConvertionTab {
+struct ConversionTab {
     const char *pszName;
     int nDefaultI;
     int nDefaultG;
@@ -382,7 +379,7 @@ struct ConvertionTab {
 };
 
 //----- Linear Unit Conversion Table
-static const ConvertionTab aoLinearUnitsConv[] = {
+static const ConversionTab aoLinearUnitsConv[] = {
     {"m",            /*  0 */  0,   1,  1.0},
     {SRS_UL_METER,   /*  1 */  0,   1,  1.0},
     {"meters",       /*  2 */  0,   1,  1.0},
@@ -411,12 +408,12 @@ static const ConvertionTab aoLinearUnitsConv[] = {
     {SRS_UA_RADIAN,  /* 20 */ 19,  20,  0.0},
     {"radians",      /* 21 */ 19,  20,  0.0}
 };
-#define LINEAR_UNITS_COUNT (sizeof(aoLinearUnitsConv) / sizeof(ConvertionTab))
+#define LINEAR_UNITS_COUNT (sizeof(aoLinearUnitsConv) / sizeof(ConversionTab))
 
 //----- Get the index of a given linear unit
 int GetUnitIndex( const char *pszUnitName );
 
-//----- Get the defaut name
+//----- Get the default name
 char *GetUnitDefault( const char *pszUnitName, const char *pszToMeter = NULL );
 
 //----- Get the "to meter"
@@ -448,9 +445,9 @@ private:
     char *pszProjection;
     char **papszCategories;
     char *pszUnitType;
-	//move GeoReference2Wkt() into header file
+    // Move GeoReference2Wkt() into header file.
     CPLErr Wkt2GeoReference( const char *pszProjString,
-        char **pszRefSystem, 
+        char **pszRefSystem,
         char **pszRefUnit );
 
 protected:
@@ -464,14 +461,14 @@ public:
     static GDALDataset *Create( const char *pszFilename,
         int nXSize,
         int nYSize,
-        int nBands, 
+        int nBands,
         GDALDataType eType,
         char **papszOptions );
-    static GDALDataset *CreateCopy( const char *pszFilename, 
+    static GDALDataset *CreateCopy( const char *pszFilename,
         GDALDataset *poSrcDS,
         int bStrict,
         char **papszOptions,
-        GDALProgressFunc pfnProgress, 
+        GDALProgressFunc pfnProgress,
         void * pProgressData );
     virtual char **GetFileList(void);
     virtual CPLErr GetGeoTransform( double *padfTransform );
@@ -488,15 +485,15 @@ class IdrisiRasterBand : public GDALPamRasterBand
 {
     friend class IdrisiDataset;
 
-    GDALRasterAttributeTable *poDefaultRAT; 
+    GDALRasterAttributeTable *poDefaultRAT;
 
 private:
     int     nRecordSize;
     GByte *pabyScanLine;
 
 public:
-    IdrisiRasterBand( IdrisiDataset *poDS, 
-        int nBand, 
+    IdrisiRasterBand( IdrisiDataset *poDS,
+        int nBand,
         GDALDataType eDataType );
     ~IdrisiRasterBand();
 
@@ -512,10 +509,10 @@ public:
 
     virtual CPLErr SetCategoryNames( char **papszCategoryNames );
     virtual CPLErr SetNoDataValue( double dfNoDataValue );
-    virtual CPLErr SetColorTable( GDALColorTable *poColorTable ); 
+    virtual CPLErr SetColorTable( GDALColorTable *poColorTable );
     virtual CPLErr SetUnitType( const char *pszUnitType );
     virtual CPLErr SetStatistics( double dfMin, double dfMax,
-                                  double dfMean, double dfStdDev ); 
+                                  double dfMean, double dfStdDev );
     CPLErr SetMinMax( double dfMin, double dfMax );
     virtual GDALRasterAttributeTable *GetDefaultRAT();
     virtual CPLErr SetDefaultRAT( const GDALRasterAttributeTable * );
@@ -533,16 +530,16 @@ public:
 /*                           IdrisiDataset()                            */
 /************************************************************************/
 
-IdrisiDataset::IdrisiDataset()
+IdrisiDataset::IdrisiDataset() :
+    fp(NULL),
+    pszFilename(NULL),
+    pszDocFilename(NULL),
+    papszRDC(NULL),
+    pszProjection(NULL),
+    papszCategories(NULL),
+    pszUnitType(NULL)
 {
-    pszFilename = NULL;
-    fp = NULL;
-    papszRDC = NULL;
-    pszDocFilename = NULL;
-    pszProjection = NULL;
     poColorTable = new GDALColorTable();
-    papszCategories = NULL;
-    pszUnitType = NULL;
 
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
@@ -562,9 +559,6 @@ IdrisiDataset::~IdrisiDataset()
 
     if( papszRDC != NULL )
     {
-		
-        int i;
-
         //int bSuccessMin = FALSE;
         //int bSuccessMax = FALSE;
 
@@ -573,7 +567,7 @@ IdrisiDataset::~IdrisiDataset()
         double dfMean = 0.0;
         double dfStdDev = 0.0;
 
-        for( i = 0; i < nBands; i++ )
+        for( int i = 0; i < nBands; i++ )
         {
             IdrisiRasterBand *poBand = (IdrisiRasterBand*) GetRasterBand( i + 1 );
             poBand->ComputeStatistics( false, &dfMin, &dfMax, &dfMean, &dfStdDev, NULL, NULL);
@@ -588,7 +582,7 @@ IdrisiDataset::~IdrisiDataset()
             */
             poBand->SetMinMax( dfMin, dfMax);
         }
-		
+
         if( eAccess == GA_Update )
         {
             CSLSetNameValueSeparator( papszRDC, ": " );
@@ -649,20 +643,18 @@ GDALDataset *IdrisiDataset::Open( GDALOpenInfo *poOpenInfo )
     }
 
     // --------------------------------------------------------------------
-    //      Create a corresponding GDALDataset                   
+    //      Create a corresponding GDALDataset
     // --------------------------------------------------------------------
 
-    IdrisiDataset *poDS;
-
-    poDS = new IdrisiDataset();
+    IdrisiDataset *poDS = new IdrisiDataset();
     poDS->eAccess = poOpenInfo->eAccess;
     poDS->pszFilename = CPLStrdup( poOpenInfo->pszFilename );
 
     if( poOpenInfo->eAccess == GA_ReadOnly )
     {
         poDS->fp = VSIFOpenL( poDS->pszFilename, "rb" );
-    } 
-    else 
+    }
+    else
     {
         poDS->fp = VSIFOpenL( poDS->pszFilename, "r+b" );
     }
@@ -678,16 +670,16 @@ GDALDataset *IdrisiDataset::Open( GDALOpenInfo *poOpenInfo )
     poDS->papszRDC = CSLDuplicate( papszLRDC );
     CSLDestroy( papszLRDC );
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     //      Load information from rdc
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     poDS->nRasterXSize = atoi_nz( CSLFetchNameValue( poDS->papszRDC, rdcCOLUMNS ) );
     poDS->nRasterYSize = atoi_nz( CSLFetchNameValue( poDS->papszRDC, rdcROWS ) );
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     //      Create band information
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     const char *pszDataType = CSLFetchNameValue( poDS->papszRDC, rdcDATA_TYPE );
     if( pszDataType == NULL )
@@ -726,8 +718,7 @@ GDALDataset *IdrisiDataset::Open( GDALOpenInfo *poOpenInfo )
         return NULL;
     }
 
-    int i;
-    for(i=0;i<poDS->nBands;i++)
+    for(int i=0;i<poDS->nBands;i++)
     {
         IdrisiRasterBand* band = (IdrisiRasterBand*) poDS->GetRasterBand(i+1);
         if (band->pabyScanLine == NULL)
@@ -737,9 +728,9 @@ GDALDataset *IdrisiDataset::Open( GDALOpenInfo *poOpenInfo )
         }
     }
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     //      Load the transformation matrix
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     const char *pszMinX = CSLFetchNameValue( poDS->papszRDC, rdcMIN_X );
     const char *pszMaxX = CSLFetchNameValue( poDS->papszRDC, rdcMAX_X );
@@ -761,9 +752,9 @@ GDALDataset *IdrisiDataset::Open( GDALOpenInfo *poOpenInfo )
         dfMaxY = CPLAtof_nz( pszMaxY );
         dfUnit = CPLAtof_nz( pszUnit );
 
-        dfMinX = dfMinX * dfUnit; 
-        dfMaxX = dfMaxX * dfUnit; 
-        dfMinY = dfMinY * dfUnit; 
+        dfMinX = dfMinX * dfUnit;
+        dfMaxX = dfMaxX * dfUnit;
+        dfMinY = dfMinY * dfUnit;
         dfMaxY = dfMaxY * dfUnit;
 
         dfYPixSz = ( dfMinY - dfMaxY ) / poDS->nRasterYSize;
@@ -777,15 +768,15 @@ GDALDataset *IdrisiDataset::Open( GDALOpenInfo *poOpenInfo )
         poDS->adfGeoTransform[5] = dfYPixSz;
     }
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     //      Set Color Table in the presence of a smp file
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     if( poDS->nBands != 3 )
     {
         const char *pszSMPFilename = CPLResetExtension( poDS->pszFilename, extSMP );
-        VSILFILE *fpSMP;
-        if( ( fpSMP = VSIFOpenL( pszSMPFilename, "rb" ) ) != NULL )
+        VSILFILE *fpSMP = VSIFOpenL( pszSMPFilename, "rb" );
+        if( fpSMP != NULL )
         {
             int dfMaxValue = atoi_nz( CSLFetchNameValue( poDS->papszRDC, rdcMAX_VALUE ) );
             int nCatCount = atoi_nz( CSLFetchNameValue( poDS->papszRDC, rdcLEGEND_CATS ) );
@@ -800,7 +791,7 @@ GDALDataset *IdrisiDataset::Open( GDALOpenInfo *poOpenInfo )
                 oEntry.c1 = (short) aucRGB[0];
                 oEntry.c2 = (short) aucRGB[1];
                 oEntry.c3 = (short) aucRGB[2];
-                oEntry.c4 = (short) 255;                      
+                oEntry.c4 = (short) 255;
                 poDS->poColorTable->SetColorEntry( i, &oEntry );
                 i++;
             }
@@ -808,9 +799,9 @@ GDALDataset *IdrisiDataset::Open( GDALOpenInfo *poOpenInfo )
         }
     }
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     //      Check for Unit Type
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     const char *pszValueUnit = CSLFetchNameValue( poDS->papszRDC, rdcVALUE_UNITS );
 
@@ -818,11 +809,11 @@ GDALDataset *IdrisiDataset::Open( GDALOpenInfo *poOpenInfo )
         poDS->pszUnitType = CPLStrdup( "unspecified" );
     else
     {
-        if( EQUALN( pszValueUnit, "meter", 4 ) )
+        if( STARTS_WITH_CI( pszValueUnit, "meter" ) )
         {
             poDS->pszUnitType = CPLStrdup( "m" );
         }
-        else if( EQUALN( pszValueUnit, "feet", 4 ) )
+        else if( STARTS_WITH_CI(pszValueUnit, "feet") )
         {
             poDS->pszUnitType = CPLStrdup( "ft" );
         }
@@ -830,9 +821,9 @@ GDALDataset *IdrisiDataset::Open( GDALOpenInfo *poOpenInfo )
             poDS->pszUnitType = CPLStrdup( pszValueUnit );
     }
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     //      Check for category names.
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     int nCatCount = atoi_nz( CSLFetchNameValue( poDS->papszRDC, rdcLEGEND_CATS ) );
 
@@ -842,21 +833,22 @@ GDALDataset *IdrisiDataset::Open( GDALOpenInfo *poOpenInfo )
         //      Sequentialize categories names, from 0 to the last "code n"
         // ----------------------------------------------------------------
 
-        int nCode = 0;
-        int nCount = 0;
         int nLine = -1;
         for( int i = 0;( i < CSLCount( poDS->papszRDC ) ) &&( nLine == -1 ); i++ )
             if( EQUALN( poDS->papszRDC[i], rdcLEGEND_CATS, 11 ) )
                 nLine = i;//get the line where legend cats is
+
         if( nLine > 0 )
         {
-            sscanf( poDS->papszRDC[++nLine], rdcCODE_N, &nCode );//asign legend cats to nCode
+            int nCode = 0;
+            int nCount = 0;
+            sscanf( poDS->papszRDC[++nLine], rdcCODE_N, &nCode );//assign legend cats to nCode
             for( int i = 0;( i < 255 ) &&( nCount < nCatCount ); i++ )
             {
                 if( i == nCode )
                 {
-                    poDS->papszCategories = 
-                        CSLAddString( poDS->papszCategories, 
+                    poDS->papszCategories =
+                        CSLAddString( poDS->papszCategories,
                         CPLParseNameValue( poDS->papszRDC[nLine], NULL ) );
                     nCount++;
                     if( nCount < nCatCount )
@@ -872,7 +864,7 @@ GDALDataset *IdrisiDataset::Open( GDALOpenInfo *poOpenInfo )
     /*      Automatic Generated Color Table                                 */
     /* -------------------------------------------------------------------- */
 
-    if( poDS->papszCategories != NULL && 
+    if( poDS->papszCategories != NULL &&
       ( poDS->poColorTable->GetColorEntryCount() == 0 ) )
     {
         int nEntryCount = CSLCount(poDS->papszCategories);
@@ -889,7 +881,7 @@ GDALDataset *IdrisiDataset::Open( GDALOpenInfo *poOpenInfo )
         sToColor.c3 = (short) ( 255 );
         sToColor.c4 = (short) ( 255 );
 
-        poDS->poColorTable->CreateColorRamp( 
+        poDS->poColorTable->CreateColorRamp(
             0, &sFromColor, ( nEntryCount - 1 ), &sToColor );
     }
 
@@ -914,24 +906,22 @@ GDALDataset *IdrisiDataset::Open( GDALOpenInfo *poOpenInfo )
 /************************************************************************/
 
 GDALDataset *IdrisiDataset::Create( const char *pszFilename,
-                                   int nXSize, 
-                                   int nYSize, 
-                                   int nBands, 
+                                   int nXSize,
+                                   int nYSize,
+                                   int nBands,
                                    GDALDataType eType,
-                                   char **papszOptions )
+                                    char ** /* papszOptions */ )
 {
-    (void) papszOptions;
-
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     //      Check input options
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
-    if( nBands != 1 && nBands != 3) 
+    if( nBands != 1 && nBands != 3)
     {
 		CPLError( CE_Failure, CPLE_AppDefined,
                 "Attempt to create IDRISI dataset with an illegal number of bands(%d)."
                 " Try again by selecting a specific band if possible. \n", nBands);
-		return NULL;  
+		return NULL;
     }
 
 	if( nBands == 3 && eType != GDT_Byte )
@@ -943,14 +933,14 @@ GDALDataset *IdrisiDataset::Create( const char *pszFilename,
         return NULL;
     }
 
-    // ---------------------------------------------------------------- 
-    //  Create the header file with minimun information
-    // ---------------------------------------------------------------- 
+    // ----------------------------------------------------------------
+    //  Create the header file with minimum information
+    // ----------------------------------------------------------------
 
     const char *pszLDataType;
 
     switch( eType )
-    {    
+    {
     case GDT_Byte:
         if( nBands == 1 )
             pszLDataType = rstBYTE;
@@ -960,7 +950,7 @@ GDALDataset *IdrisiDataset::Create( const char *pszFilename,
     case GDT_Int16:
         pszLDataType = rstINTEGER;
         break;
-    case GDT_Float32:                
+    case GDT_Float32:
         pszLDataType = rstREAL;
         break;
 	//--- process compatible data types
@@ -1000,9 +990,7 @@ GDALDataset *IdrisiDataset::Create( const char *pszFilename,
         return NULL;
     };
 
-    char **papszLRDC;
-
-    papszLRDC = NULL;
+    char **papszLRDC = NULL;
     papszLRDC = CSLAddNameValue( papszLRDC, rdcFILE_FORMAT,   rstVERSION );
     papszLRDC = CSLAddNameValue( papszLRDC, rdcFILE_TITLE,    "" );
     papszLRDC = CSLAddNameValue( papszLRDC, rdcDATA_TYPE,     pszLDataType );
@@ -1030,20 +1018,17 @@ GDALDataset *IdrisiDataset::Create( const char *pszFilename,
     papszLRDC = CSLAddNameValue( papszLRDC, rdcLINEAGES,      "" );
     papszLRDC = CSLAddNameValue( papszLRDC, rdcCOMMENTS,      "" );
 
-    const char *pszLDocFilename;
-    pszLDocFilename = CPLResetExtension( pszFilename, extRDC );
+    const char *pszLDocFilename = CPLResetExtension( pszFilename, extRDC );
 
     CSLSetNameValueSeparator( papszLRDC, ": " );
     SaveAsCRLF( papszLRDC, pszLDocFilename );
     CSLDestroy( papszLRDC );
 
-    // ---------------------------------------------------------------- 
+    // ----------------------------------------------------------------
     //  Create an empty data file
-    // ---------------------------------------------------------------- 
-
-    VSILFILE *fp;
+    // ----------------------------------------------------------------
 
-    fp = VSIFOpenL( pszFilename, "wb+" );
+    VSILFILE *fp = VSIFOpenL( pszFilename, "wb+" );
 
     if( fp == NULL )
     {
@@ -1060,11 +1045,11 @@ GDALDataset *IdrisiDataset::Create( const char *pszFilename,
 /*                             CreateCopy()                             */
 /************************************************************************/
 
-GDALDataset *IdrisiDataset::CreateCopy( const char *pszFilename, 
+GDALDataset *IdrisiDataset::CreateCopy( const char *pszFilename,
                                        GDALDataset *poSrcDS,
                                        int bStrict,
                                        char **papszOptions,
-                                       GDALProgressFunc pfnProgress, 
+                                       GDALProgressFunc pfnProgress,
                                        void *pProgressData )
 {
     if( !pfnProgress( 0.0, NULL, pProgressData ) )
@@ -1073,15 +1058,15 @@ GDALDataset *IdrisiDataset::CreateCopy( const char *pszFilename,
     // ------------------------------------------------------------------------
     //      Check number of bands
     // ------------------------------------------------------------------------
-	if ( !( poSrcDS->GetRasterCount() == 1 ) && !( poSrcDS->GetRasterCount() == 3 ))
-	{
-		CPLError( CE_Failure, CPLE_AppDefined,
-                "Attempt to create IDRISI dataset with an illegal number of bands(%d)."
-                " Try again by selecting a specific band if possible.\n",
-				poSrcDS->GetRasterCount() );
-		return NULL; 
+    if ( !( poSrcDS->GetRasterCount() == 1 ) && !( poSrcDS->GetRasterCount() == 3 ))
+    {
+            CPLError( CE_Failure, CPLE_AppDefined,
+            "Attempt to create IDRISI dataset with an illegal number of bands(%d)."
+            " Try again by selecting a specific band if possible.\n",
+                            poSrcDS->GetRasterCount() );
+            return NULL;
 
-	}
+    }
     if ( ( poSrcDS->GetRasterCount() == 3 ) &&
          ( ( poSrcDS->GetRasterBand( 1 )->GetRasterDataType() != GDT_Byte ) ||
          ( poSrcDS->GetRasterBand( 2 )->GetRasterDataType() != GDT_Byte ) ||
@@ -1098,16 +1083,14 @@ GDALDataset *IdrisiDataset::CreateCopy( const char *pszFilename,
     //      Check Data types
     // ------------------------------------------------------------------------
 
-    int i;
-
-    for( i = 1; i <= poSrcDS->GetRasterCount(); i++ )
+    for( int i = 1; i <= poSrcDS->GetRasterCount(); i++ )
     {
         GDALDataType eType = poSrcDS->GetRasterBand( i )->GetRasterDataType();
 
         if( bStrict )
         {
-            if( eType != GDT_Byte && 
-                eType != GDT_Int16 && 
+            if( eType != GDT_Byte &&
+                eType != GDT_Int16 &&
                 eType != GDT_Float32 )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
@@ -1119,11 +1102,11 @@ GDALDataset *IdrisiDataset::CreateCopy( const char *pszFilename,
         }
         else
         {
-            if( eType != GDT_Byte && 
-                eType != GDT_Int16 && 
-                eType != GDT_UInt16 && 
-                eType != GDT_UInt32 && 
-                eType != GDT_Int32 && 
+            if( eType != GDT_Byte &&
+                eType != GDT_Int16 &&
+                eType != GDT_UInt16 &&
+                eType != GDT_UInt32 &&
+                eType != GDT_Int32 &&
                 eType != GDT_Float32 &&
                 eType != GDT_Float64 )
             {
@@ -1136,7 +1119,7 @@ GDALDataset *IdrisiDataset::CreateCopy( const char *pszFilename,
     }
 
     // --------------------------------------------------------------------
-    //      Define data type 
+    //      Define data type
     // --------------------------------------------------------------------
 
     GDALRasterBand *poBand = poSrcDS->GetRasterBand( 1 );
@@ -1145,19 +1128,16 @@ GDALDataset *IdrisiDataset::CreateCopy( const char *pszFilename,
     int bSuccessMin = FALSE;
     int bSuccessMax = FALSE;
 
-    double dfMin;
-    double dfMax;
-
-    dfMin = poBand->GetMinimum( &bSuccessMin );
-    dfMax = poBand->GetMaximum( &bSuccessMax );
+    double dfMin = poBand->GetMinimum( &bSuccessMin );
+    double dfMax = poBand->GetMaximum( &bSuccessMax );
 
     if( ! ( bSuccessMin && bSuccessMax ) )
     {
       poBand->GetStatistics( false, true, &dfMin, &dfMax, NULL, NULL );
     }
 
-    if(!( ( eType == GDT_Byte ) || 
-          ( eType == GDT_Int16 ) || 
+    if(!( ( eType == GDT_Byte ) ||
+          ( eType == GDT_Int16 ) ||
           ( eType == GDT_Float32 ) ) )
     {
         if( eType == GDT_Float64 )
@@ -1166,10 +1146,10 @@ GDALDataset *IdrisiDataset::CreateCopy( const char *pszFilename,
         }
         else
         {
-            if( ( dfMin < (double) SHRT_MIN ) || 
+            if( ( dfMin < (double) SHRT_MIN ) ||
                 ( dfMax > (double) SHRT_MAX ) )
             {
-                eType = GDT_Float32; 
+                eType = GDT_Float32;
             }
             else
             {
@@ -1182,13 +1162,11 @@ GDALDataset *IdrisiDataset::CreateCopy( const char *pszFilename,
     //      Create the dataset
     // --------------------------------------------------------------------
 
-    IdrisiDataset *poDS;
-
-    poDS = (IdrisiDataset *) IdrisiDataset::Create( pszFilename, 
-        poSrcDS->GetRasterXSize(), 
-        poSrcDS->GetRasterYSize(), 
-        poSrcDS->GetRasterCount(), 
-        eType, 
+    IdrisiDataset *poDS = (IdrisiDataset *) IdrisiDataset::Create( pszFilename,
+        poSrcDS->GetRasterXSize(),
+        poSrcDS->GetRasterYSize(),
+        poSrcDS->GetRasterCount(),
+        eType,
         papszOptions );
 
     if( poDS == NULL )
@@ -1211,13 +1189,10 @@ GDALDataset *IdrisiDataset::CreateCopy( const char *pszFilename,
     //      Copy information to the raster band(s)
     // --------------------------------------------------------------------
 
-    GDALRasterBand *poSrcBand;
-    int bHasNoDataValue;
-    double dfNoDataValue;
 
-    for( i = 1; i <= poDS->nBands; i++ )
+    for( int i = 1; i <= poDS->nBands; i++ )
     {
-        poSrcBand = poSrcDS->GetRasterBand( i );
+        GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( i );
         IdrisiRasterBand* poDstBand = (IdrisiRasterBand*) poDS->GetRasterBand( i );
 
         if( poDS->nBands == 1 )
@@ -1237,7 +1212,8 @@ GDALDataset *IdrisiDataset::CreateCopy( const char *pszFilename,
         dfMin = poSrcBand->GetMinimum( NULL );
         dfMax = poSrcBand->GetMaximum( NULL );
         poDstBand->SetMinMax( dfMin, dfMax );
-        dfNoDataValue = poSrcBand->GetNoDataValue( &bHasNoDataValue );
+        int bHasNoDataValue;
+        double dfNoDataValue = poSrcBand->GetNoDataValue( &bHasNoDataValue );
         if( bHasNoDataValue )
             poDstBand->SetNoDataValue( dfNoDataValue );
     }
@@ -1246,9 +1222,13 @@ GDALDataset *IdrisiDataset::CreateCopy( const char *pszFilename,
     //      Copy image data
     // --------------------------------------------------------------------
 
-    GDALDatasetCopyWholeRaster( (GDALDatasetH) poSrcDS, 
+    if( GDALDatasetCopyWholeRaster( (GDALDatasetH) poSrcDS,
                                 (GDALDatasetH) poDS, NULL,
-                                pfnProgress, pProgressData );
+                                pfnProgress, pProgressData ) != CE_None )
+    {
+        delete poDS;
+        return NULL;
+    }
 
     // --------------------------------------------------------------------
     //      Finalize
@@ -1266,13 +1246,12 @@ GDALDataset *IdrisiDataset::CreateCopy( const char *pszFilename,
 char **IdrisiDataset::GetFileList()
 {
     char **papszFileList = GDALPamDataset::GetFileList();
-    const char *pszAssociated;
-        
+
     // --------------------------------------------------------------------
     //      Symbol table file
     // --------------------------------------------------------------------
 
-    pszAssociated = CPLResetExtension( pszFilename, extSMP );
+    const char *pszAssociated = CPLResetExtension( pszFilename, extSMP );
 
     if( FileExists( pszAssociated ) )
     {
@@ -1359,7 +1338,7 @@ CPLErr  IdrisiDataset::GetGeoTransform( double * padfTransform )
 /************************************************************************/
 
 CPLErr  IdrisiDataset::SetGeoTransform( double * padfTransform )
-{    
+{
     if( padfTransform[2] != 0.0 || padfTransform[4] != 0.0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -1372,13 +1351,12 @@ CPLErr  IdrisiDataset::SetGeoTransform( double * padfTransform )
     // Update the .rdc file
     // --------------------------------------------------------------------
 
-    double dfMinX, dfMaxX, dfMinY, dfMaxY, dfXPixSz, dfYPixSz;
-
-    dfXPixSz = padfTransform[1];
-    dfYPixSz = padfTransform[5];
-    dfMinX   = padfTransform[0];
-    dfMaxX   = ( dfXPixSz * nRasterXSize ) + dfMinX;
+    double dfXPixSz = padfTransform[1];
+    double dfYPixSz = padfTransform[5];
+    double dfMinX = padfTransform[0];
+    double dfMaxX = ( dfXPixSz * nRasterXSize ) + dfMinX;
 
+    double dfMinY, dfMaxY;
     if( dfYPixSz < 0 )
     {
         dfMaxY   = padfTransform[3];
@@ -1434,15 +1412,14 @@ const char *IdrisiDataset::GetProjectionRef( void )
 /************************************************************************/
 
 CPLErr IdrisiDataset::SetProjection( const char *pszProjString )
-{   
+{
     CPLFree( pszProjection );
     pszProjection = CPLStrdup( pszProjString );
-    CPLErr eResult = CE_None;
 
     char *pszRefSystem = NULL;
     char *pszRefUnit = NULL;
 
-    eResult = Wkt2GeoReference( pszProjString, &pszRefSystem, &pszRefUnit );
+    CPLErr eResult = Wkt2GeoReference( pszProjString, &pszRefSystem, &pszRefUnit );
 
     papszRDC = CSLSetNameValue( papszRDC, rdcREF_SYSTEM, pszRefSystem );
     papszRDC = CSLSetNameValue( papszRDC, rdcREF_UNITS,  pszRefUnit );
@@ -1457,41 +1434,34 @@ CPLErr IdrisiDataset::SetProjection( const char *pszProjString )
 /*                          IdrisiRasterBand()                          */
 /************************************************************************/
 
-IdrisiRasterBand::IdrisiRasterBand( IdrisiDataset *poDS, 
-                                    int nBand, 
-                                    GDALDataType eDataType )
+IdrisiRasterBand::IdrisiRasterBand( IdrisiDataset *poDSIn,
+                                    int nBandIn,
+                                    GDALDataType eDataTypeIn )
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
-    this->eDataType = eDataType;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
+    this->eDataType = eDataTypeIn;
     this->poDefaultRAT = NULL;
     this->fMinimum = 0.0;
     this->fMaximum = 0.0;
     this->bFirstVal = true;
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     //      Set Dimension
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     nBlockYSize = 1;
     nBlockXSize = poDS->GetRasterXSize();
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     //      Get ready for reading and writing
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     nRecordSize  = poDS->GetRasterXSize() * GDALGetDataTypeSize( eDataType ) / 8;
 
-    pabyScanLine = (GByte*) VSIMalloc2( nRecordSize, poDS->nBands );
+    pabyScanLine = (GByte*) VSI_MALLOC2_VERBOSE( nRecordSize, poDSIn->nBands );
 
-    if( pabyScanLine == NULL )
-    {
-        CPLError(CE_Failure, CPLE_OutOfMemory,
-                 "IdrisiRasterBand::IdrisiRasterBand : Out of memory (nRasterXSize = %d)",
-                  poDS->GetRasterXSize());
-    }
-
-    nRecordSize *= poDS->nBands;
+    nRecordSize *= poDSIn->nBands;
 }
 
 /************************************************************************/
@@ -1512,33 +1482,32 @@ IdrisiRasterBand::~IdrisiRasterBand()
 /*                             IReadBlock()                             */
 /************************************************************************/
 
-CPLErr IdrisiRasterBand::IReadBlock( int nBlockXOff, 
+CPLErr IdrisiRasterBand::IReadBlock( int nBlockXOff,
                                      int nBlockYOff,
                                      void *pImage )
 {
     IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
 
-    if( VSIFSeekL( poGDS->fp, 
+    if( VSIFSeekL( poGDS->fp,
         vsi_l_offset(nRecordSize) * nBlockYOff, SEEK_SET ) < 0 )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
-            "Can't seek(%s) block with X offset %d and Y offset %d.\n%s", 
+        CPLError( CE_Failure, CPLE_FileIO,
+            "Can't seek(%s) block with X offset %d and Y offset %d.\n%s",
             poGDS->pszFilename, nBlockXOff, nBlockYOff, VSIStrerror( errno ) );
         return CE_Failure;
     }
 
     if( (int) VSIFReadL( pabyScanLine, 1, nRecordSize, poGDS->fp ) < nRecordSize )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
-            "Can't read(%s) block with X offset %d and Y offset %d.\n%s", 
+        CPLError( CE_Failure, CPLE_FileIO,
+            "Can't read(%s) block with X offset %d and Y offset %d.\n%s",
             poGDS->pszFilename, nBlockXOff, nBlockYOff, VSIStrerror( errno ) );
         return CE_Failure;
     }
 
-    if( poGDS->nBands == 3 ) 
+    if( poGDS->nBands == 3 )
     {
-        int i, j;
-        for( i = 0, j = ( 3 - nBand ); i < nBlockXSize; i++, j += 3 )
+        for( int i = 0, j = ( 3 - nBand ); i < nBlockXSize; i++, j += 3 )
         {
             ( (GByte*) pImage )[i] = pabyScanLine[j];
         }
@@ -1548,7 +1517,7 @@ CPLErr IdrisiRasterBand::IReadBlock( int nBlockXOff,
         memcpy( pImage, pabyScanLine, nRecordSize );
     }
 
-#ifdef CPL_MSB    
+#ifdef CPL_MSB
     if( eDataType == GDT_Float32 )
         GDALSwapWords( pImage, 4, nBlockXSize * nBlockYSize, 4 );
 #endif
@@ -1560,13 +1529,13 @@ CPLErr IdrisiRasterBand::IReadBlock( int nBlockXOff,
 /*                            IWriteBlock()                             */
 /************************************************************************/
 
-CPLErr IdrisiRasterBand::IWriteBlock( int nBlockXOff, 
+CPLErr IdrisiRasterBand::IWriteBlock( int nBlockXOff,
                                       int nBlockYOff,
                                       void *pImage )
 {
     IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
 
-#ifdef CPL_MSB    
+#ifdef CPL_MSB
     // Swap in input buffer if needed.
     if( eDataType == GDT_Float32 )
         GDALSwapWords( pImage, 4, nBlockXSize * nBlockYSize, 4 );
@@ -1578,9 +1547,9 @@ CPLErr IdrisiRasterBand::IWriteBlock( int nBlockXOff,
     }
     else
     {
-        if( nBand > 1 ) 
+        if( nBand > 1 )
         {
-            VSIFSeekL( poGDS->fp, 
+            VSIFSeekL( poGDS->fp,
                 vsi_l_offset(nRecordSize) * nBlockYOff, SEEK_SET );
             VSIFReadL( pabyScanLine, 1, nRecordSize, poGDS->fp );
         }
@@ -1591,7 +1560,7 @@ CPLErr IdrisiRasterBand::IWriteBlock( int nBlockXOff,
         }
     }
 
-#ifdef CPL_MSB    
+#ifdef CPL_MSB
     // Swap input buffer back to original form.
     if( eDataType == GDT_Float32 )
         GDALSwapWords( pImage, 4, nBlockXSize * nBlockYSize, 4 );
@@ -1601,8 +1570,8 @@ CPLErr IdrisiRasterBand::IWriteBlock( int nBlockXOff,
 
     if( (int) VSIFWriteL( pabyScanLine, 1, nRecordSize, poGDS->fp ) < nRecordSize )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
-            "Can't write(%s) block with X offset %d and Y offset %d.\n%s", 
+        CPLError( CE_Failure, CPLE_FileIO,
+            "Can't write(%s) block with X offset %d and Y offset %d.\n%s",
             poGDS->pszFilename, nBlockXOff, nBlockYOff, VSIStrerror( errno ) );
         return CE_Failure;
     }
@@ -1610,15 +1579,13 @@ CPLErr IdrisiRasterBand::IWriteBlock( int nBlockXOff,
     int bHasNoDataValue = FALSE;
     float fNoDataValue = (float) GetNoDataValue(&bHasNoDataValue);
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     //      Search for the minimum and maximum values
-    // -------------------------------------------------------------------- 
-
-    int i, j;
+    // --------------------------------------------------------------------
 
     if( eDataType == GDT_Float32 )
     {
-        for( i = 0; i < nBlockXSize; i++ )
+        for( int i = 0; i < nBlockXSize; i++ )
         {
             float fVal = ((float*) pabyScanLine)[i]; //this is fine
             if( !bHasNoDataValue || fVal != fNoDataValue )
@@ -1638,7 +1605,7 @@ CPLErr IdrisiRasterBand::IWriteBlock( int nBlockXOff,
     }
     else if( eDataType == GDT_Int16 )
     {
-        for( i = 0; i < nBlockXSize; i++ )
+        for( int i = 0; i < nBlockXSize; i++ )
         {
             float fVal = (float) ((GInt16*) pabyScanLine)[i];
             if( !bHasNoDataValue || fVal != fNoDataValue )
@@ -1658,7 +1625,7 @@ CPLErr IdrisiRasterBand::IWriteBlock( int nBlockXOff,
     }
     else if( poGDS->nBands == 1 )
     {
-        for( i = 0; i < nBlockXSize; i++ )
+        for( int i = 0; i < nBlockXSize; i++ )
         {
             float fVal = (float) ((GByte*) pabyScanLine)[i];
             if( !bHasNoDataValue || fVal != fNoDataValue )
@@ -1678,7 +1645,7 @@ CPLErr IdrisiRasterBand::IWriteBlock( int nBlockXOff,
     }
     else
     {
-        for( i = 0, j = ( 3 - nBand ); i < nBlockXSize; i++, j += 3 )
+        for( int i = 0, j = ( 3 - nBand ); i < nBlockXSize; i++, j += 3 )
         {
             float fVal = (float) ((GByte*) pabyScanLine)[j];
             if( !bHasNoDataValue || fVal != fNoDataValue )
@@ -1705,14 +1672,14 @@ CPLErr IdrisiRasterBand::IWriteBlock( int nBlockXOff,
 /************************************************************************/
 
 double IdrisiRasterBand::GetMinimum( int *pbSuccess )
-{      
+{
     IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
 
     if (CSLFetchNameValue( poGDS->papszRDC, rdcMIN_VALUE ) == NULL)
         return GDALPamRasterBand::GetMinimum(pbSuccess);
 
     double adfMinValue[3];
-    CPLsscanf( CSLFetchNameValue( poGDS->papszRDC, rdcMIN_VALUE ), "%lf %lf %lf", 
+    CPLsscanf( CSLFetchNameValue( poGDS->papszRDC, rdcMIN_VALUE ), "%lf %lf %lf",
         &adfMinValue[0], &adfMinValue[1], &adfMinValue[2] );
 
     if( pbSuccess )
@@ -1728,20 +1695,20 @@ double IdrisiRasterBand::GetMinimum( int *pbSuccess )
 /************************************************************************/
 
 double IdrisiRasterBand::GetMaximum( int *pbSuccess )
-{      
+{
     IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
 
     if (CSLFetchNameValue( poGDS->papszRDC, rdcMAX_VALUE ) == NULL)
         return GDALPamRasterBand::GetMaximum(pbSuccess);
 
     double adfMaxValue[3];
-    CPLsscanf( CSLFetchNameValue( poGDS->papszRDC, rdcMAX_VALUE ), "%lf %lf %lf", 
+    CPLsscanf( CSLFetchNameValue( poGDS->papszRDC, rdcMAX_VALUE ), "%lf %lf %lf",
         &adfMaxValue[0], &adfMaxValue[1], &adfMaxValue[2] );
 
     if( pbSuccess )
-  {
+    {
         *pbSuccess = true;
-  }
+    }
 
     return adfMaxValue[this->nBand - 1];
 }
@@ -1751,25 +1718,23 @@ double IdrisiRasterBand::GetMaximum( int *pbSuccess )
 /************************************************************************/
 
 double IdrisiRasterBand::GetNoDataValue( int *pbSuccess )
-{      
+{
     IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
 
-    double dfNoData;
-    const char *pszFlagDefn;
+    const char *pszFlagDefn = NULL;
 
     if( CSLFetchNameValue( poGDS->papszRDC, rdcFLAG_DEFN ) != NULL )
         pszFlagDefn = CSLFetchNameValue( poGDS->papszRDC, rdcFLAG_DEFN );
     else if( CSLFetchNameValue( poGDS->papszRDC, rdcFLAG_DEFN2 ) != NULL )
         pszFlagDefn = CSLFetchNameValue( poGDS->papszRDC, rdcFLAG_DEFN2 );
-    else
-        pszFlagDefn = CPLStrdup( "none" );
 
     // ------------------------------------------------------------------------
-    // If Flag_Def is not "none", Flag_Value means "background" 
+    // If Flag_Def is not "none", Flag_Value means "background"
     // or "missing data"
     // ------------------------------------------------------------------------
 
-    if( ! EQUAL( pszFlagDefn, "none" ) )
+    double dfNoData;
+    if( pszFlagDefn != NULL && ! EQUAL( pszFlagDefn, "none" ) )
     {
         dfNoData = CPLAtof_nz( CSLFetchNameValue( poGDS->papszRDC, rdcFLAG_VALUE ) );
         if( pbSuccess )
@@ -1790,12 +1755,12 @@ double IdrisiRasterBand::GetNoDataValue( int *pbSuccess )
 /************************************************************************/
 
 CPLErr IdrisiRasterBand::SetNoDataValue( double dfNoDataValue )
-{      
+{
     IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
 
-    poGDS->papszRDC = 
+    poGDS->papszRDC =
         CSLSetNameValue( poGDS->papszRDC, rdcFLAG_VALUE, CPLSPrintf( "%.7g", dfNoDataValue ) );
-    poGDS->papszRDC = 
+    poGDS->papszRDC =
         CSLSetNameValue( poGDS->papszRDC, rdcFLAG_DEFN,  "missing data" );
 
     return CE_None;
@@ -1806,7 +1771,7 @@ CPLErr IdrisiRasterBand::SetNoDataValue( double dfNoDataValue )
 /************************************************************************/
 
 GDALColorInterp IdrisiRasterBand::GetColorInterpretation()
-{               
+{
     IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
 
     if( poGDS->nBands == 3 )
@@ -1830,7 +1795,7 @@ GDALColorInterp IdrisiRasterBand::GetColorInterpretation()
 /************************************************************************/
 
 char **IdrisiRasterBand::GetCategoryNames()
-{      
+{
     IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
 
     return poGDS->papszCategories;
@@ -1841,8 +1806,8 @@ char **IdrisiRasterBand::GetCategoryNames()
 /************************************************************************/
 
 CPLErr IdrisiRasterBand::SetCategoryNames( char **papszCategoryNames )
-{      
-    int nCatCount = CSLCount( papszCategoryNames );
+{
+    const int nCatCount = CSLCount( papszCategoryNames );
 
     if( nCatCount == 0 )
         return CE_None;
@@ -1856,8 +1821,8 @@ CPLErr IdrisiRasterBand::SetCategoryNames( char **papszCategoryNames )
     //        Search for the "Legend cats  : N" line
     // ------------------------------------------------------
 
-    int i, nLine = -1;
-    for( i = 0;( i < CSLCount( poGDS->papszRDC ) ) &&( nLine == -1 ); i++ )
+    int nLine = -1;
+    for( int i = 0;( i < CSLCount( poGDS->papszRDC ) ) &&( nLine == -1 ); i++ )
         if( EQUALN( poGDS->papszRDC[i], rdcLEGEND_CATS, 12 ) )
             nLine = i;
 
@@ -1867,7 +1832,7 @@ CPLErr IdrisiRasterBand::SetCategoryNames( char **papszCategoryNames )
     int nCount = atoi_nz( CSLFetchNameValue( poGDS->papszRDC, rdcLEGEND_CATS ) );
 
     // ------------------------------------------------------
-    //        Delte old instance of the categoty names
+    //        Delete old instance of the category names
     // ------------------------------------------------------
 
     if( nCount > 0 )
@@ -1875,11 +1840,11 @@ CPLErr IdrisiRasterBand::SetCategoryNames( char **papszCategoryNames )
 
     nCount = 0;
 
-    for( i = 0; i < nCatCount; i++ )
+    for( int i = 0; i < nCatCount; i++ )
     {
         if( ( strlen( papszCategoryNames[i] ) > 0 ) )
         {
-            poGDS->papszRDC = CSLInsertString( poGDS->papszRDC,( nLine + nCount + 1 ), 
+            poGDS->papszRDC = CSLInsertString( poGDS->papszRDC,( nLine + nCount + 1 ),
                 CPLSPrintf( "%s:%s", CPLSPrintf( rdcCODE_N, i ), papszCategoryNames[i] ) );
             nCount++;
         }
@@ -1895,17 +1860,15 @@ CPLErr IdrisiRasterBand::SetCategoryNames( char **papszCategoryNames )
 /************************************************************************/
 
 GDALColorTable *IdrisiRasterBand::GetColorTable()
-{               
+{
     IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
 
     if( poGDS->poColorTable->GetColorEntryCount() == 0 )
     {
         return NULL;
     }
-    else
-    {
-        return poGDS->poColorTable;
-    }
+
+    return poGDS->poColorTable;
 }
 
 /************************************************************************/
@@ -1913,7 +1876,7 @@ GDALColorTable *IdrisiRasterBand::GetColorTable()
 /************************************************************************/
 
 CPLErr IdrisiRasterBand::SetColorTable( GDALColorTable *poColorTable )
-{      
+{
     if( poColorTable == NULL )
     {
         return CE_None;
@@ -1930,11 +1893,11 @@ CPLErr IdrisiRasterBand::SetColorTable( GDALColorTable *poColorTable )
 
     poGDS->poColorTable = poColorTable->Clone();
 
-    const char *pszSMPFilename;
-    pszSMPFilename = CPLResetExtension( poGDS->pszFilename, extSMP );
-    VSILFILE *fpSMP;
+    const char *pszSMPFilename
+        = CPLResetExtension( poGDS->pszFilename, extSMP );
+    VSILFILE *fpSMP = VSIFOpenL( pszSMPFilename, "w" );
 
-    if( ( fpSMP = VSIFOpenL( pszSMPFilename, "w" ) ) != NULL )
+    if( fpSMP != NULL )
     {
         VSIFWriteL( "[Idrisi]", 8, 1, fpSMP );
         GByte nPlatform = 1;    VSIFWriteL( &nPlatform, 1, 1, fpSMP );
@@ -1947,9 +1910,8 @@ CPLErr IdrisiRasterBand::SetColorTable( GDALColorTable *poColorTable )
 
         GDALColorEntry oEntry;
         GByte aucRGB[3];
-        int i;
 
-        for( i = 0; i < poColorTable->GetColorEntryCount(); i++ )
+        for( int i = 0; i < poColorTable->GetColorEntryCount(); i++ )
         {
             poColorTable->GetColorEntryAsRGB( i, &oEntry );
             aucRGB[0] = (GByte) oEntry.c1;
@@ -1957,8 +1919,8 @@ CPLErr IdrisiRasterBand::SetColorTable( GDALColorTable *poColorTable )
             aucRGB[2] = (GByte) oEntry.c3;
             VSIFWriteL( &aucRGB, 3, 1, fpSMP );
         }
-        /* smp files always have 256 occurences */
-        for( i = poColorTable->GetColorEntryCount(); i <= 255; i++ )
+        /* smp files always have 256 occurrences. */
+        for( int i = poColorTable->GetColorEntryCount(); i <= 255; i++ )
         {
             poColorTable->GetColorEntryAsRGB( i, &oEntry );
             aucRGB[0] = (GByte) 0;
@@ -1988,17 +1950,17 @@ const char *IdrisiRasterBand::GetUnitType()
 /************************************************************************/
 
 CPLErr IdrisiRasterBand::SetUnitType( const char *pszUnitType )
-{      
+{
     IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
 
     if( strlen( pszUnitType ) == 0 )
     {
-        poGDS->papszRDC = 
+        poGDS->papszRDC =
             CSLSetNameValue( poGDS->papszRDC, rdcVALUE_UNITS, "unspecified" );
     }
     else
     {
-        poGDS->papszRDC = 
+        poGDS->papszRDC =
             CSLSetNameValue( poGDS->papszRDC, rdcVALUE_UNITS, pszUnitType );
     }
 
@@ -2010,9 +1972,9 @@ CPLErr IdrisiRasterBand::SetUnitType( const char *pszUnitType )
 /************************************************************************/
 
 CPLErr IdrisiRasterBand::SetMinMax( double dfMin, double dfMax )
-{      
+{
     IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
-    
+
     fMinimum = (float)dfMin;
     fMaximum = (float)dfMax;
 
@@ -2029,24 +1991,24 @@ CPLErr IdrisiRasterBand::SetMinMax( double dfMin, double dfMax )
 
     if( poGDS->nBands == 3 )
     {
-        poGDS->papszRDC = 
+        poGDS->papszRDC =
             CSLSetNameValue( poGDS->papszRDC, rdcMIN_VALUE,   CPLSPrintf( "%.8g %.8g %.8g", adfMin[0], adfMin[1], adfMin[2] ) );
-        poGDS->papszRDC = 
+        poGDS->papszRDC =
             CSLSetNameValue( poGDS->papszRDC, rdcMAX_VALUE,   CPLSPrintf( "%.8g %.8g %.8g", adfMax[0], adfMax[1], adfMax[2] ) );
-        poGDS->papszRDC = 
+        poGDS->papszRDC =
             CSLSetNameValue( poGDS->papszRDC, rdcDISPLAY_MIN, CPLSPrintf( "%.8g %.8g %.8g", adfMin[0], adfMin[1], adfMin[2] ) );
-        poGDS->papszRDC = 
+        poGDS->papszRDC =
             CSLSetNameValue( poGDS->papszRDC, rdcDISPLAY_MAX, CPLSPrintf( "%.8g %.8g %.8g", adfMax[0], adfMax[1], adfMax[2] ) );
     }
     else
     {
-        poGDS->papszRDC = 
+        poGDS->papszRDC =
             CSLSetNameValue( poGDS->papszRDC, rdcMIN_VALUE,   CPLSPrintf( "%.8g", adfMin[0] ) );
-        poGDS->papszRDC = 
+        poGDS->papszRDC =
             CSLSetNameValue( poGDS->papszRDC, rdcMAX_VALUE,   CPLSPrintf( "%.8g", adfMax[0] ) );
-        poGDS->papszRDC = 
+        poGDS->papszRDC =
             CSLSetNameValue( poGDS->papszRDC, rdcDISPLAY_MIN, CPLSPrintf( "%.8g", adfMin[0] ) );
-        poGDS->papszRDC = 
+        poGDS->papszRDC =
             CSLSetNameValue( poGDS->papszRDC, rdcDISPLAY_MAX, CPLSPrintf( "%.8g", adfMax[0] ) );
     }
 
@@ -2083,8 +2045,6 @@ CPLErr IdrisiRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT )
     int iRed   = poRAT->GetColOfUsage( GFU_Red );
     int iGreen = poRAT->GetColOfUsage( GFU_Green );
     int iBlue  = poRAT->GetColOfUsage( GFU_Blue );
-    int iName  = -1;
-    int i;
 
     GDALColorTable *poCT = NULL;
     char **papszNames = NULL;
@@ -2095,11 +2055,11 @@ CPLErr IdrisiRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT )
     // Seek for "Value" field index (AGIS standards field name)
     // ----------------------------------------------------------
 
-    if( GetColorTable() == 0 || GetColorTable()->GetColorEntryCount() == 0 )
+    if( GetColorTable() == NULL || GetColorTable()->GetColorEntryCount() == 0 )
     {
-        for( i = 0; i < poRAT->GetColumnCount(); i++ )
+        for( int i = 0; i < poRAT->GetColumnCount(); i++ )
         {
-            if EQUALN( "Value", poRAT->GetNameOfCol( i ), 5 ) 
+            if STARTS_WITH_CI(poRAT->GetNameOfCol( i ), "Value")
             {
                 iValue = i;
                 break;
@@ -2117,24 +2077,25 @@ CPLErr IdrisiRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT )
     // Seek for Name field index
     // ----------------------------------------------------------
 
-    if( GetCategoryNames() == 0 || CSLCount( GetCategoryNames() ) == 0 )
+    int iName  = -1;
+    if( CSLCount( GetCategoryNames() ) == 0 )
     {
         iName  = poRAT->GetColOfUsage( GFU_Name );
         if( iName == -1 )
         {
-            for( i = 0; i < poRAT->GetColumnCount(); i++ )
+            for( int i = 0; i < poRAT->GetColumnCount(); i++ )
             {
-                if EQUALN( "Class_Name", poRAT->GetNameOfCol( i ), 10 )
+                if STARTS_WITH_CI(poRAT->GetNameOfCol( i ), "Class_Name")
                 {
                     iName = i;
                     break;
-                } 
-                else if EQUALN( "Categor", poRAT->GetNameOfCol( i ), 7 )
+                }
+                else if STARTS_WITH_CI(poRAT->GetNameOfCol( i ), "Categor")
                 {
                     iName = i;
                     break;
-                } 
-                else if EQUALN( "Name",  poRAT->GetNameOfCol( i ), 4 )
+                }
+                else if STARTS_WITH_CI(poRAT->GetNameOfCol( i ), "Name")
                 {
                     iName = i;
                     break;
@@ -2145,8 +2106,8 @@ CPLErr IdrisiRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT )
         /* if still can't find it use the first String column */
 
         if( iName == -1 )
-        {   
-            for( i = 0; i < poRAT->GetColumnCount(); i++ )
+        {
+            for( int i = 0; i < poRAT->GetColumnCount(); i++ )
             {
                 if( poRAT->GetTypeOfCol( i ) == GFT_String )
                 {
@@ -2201,13 +2162,13 @@ CPLErr IdrisiRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT )
                 sColor.c1  = (short) ( dRed   * nFact );
                 sColor.c2  = (short) ( dGreen * nFact );
                 sColor.c3  = (short) ( dBlue  * nFact );
-                sColor.c4  = (short) ( 255    / nFact );    
+                sColor.c4  = (short) ( 255    / nFact );
                 poCT->SetColorEntry( iEntry, &sColor );
             }
 
             if( iName != -1 )
             {
-                papszNames = CSLAddString( papszNames, 
+                papszNames = CSLAddString( papszNames,
                     poRAT->GetValueAsString( iEntry, iName ) );
             }
 
@@ -2228,7 +2189,7 @@ CPLErr IdrisiRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT )
                 sColor.c1  = (short) 0;
                 sColor.c2  = (short) 0;
                 sColor.c3  = (short) 0;
-                sColor.c4  = (short) 255;    
+                sColor.c4  = (short) 255;
                 poCT->SetColorEntry( iEntry, &sColor );
             }
 
@@ -2261,7 +2222,7 @@ CPLErr IdrisiRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT )
     // Update Attribute Table
     // ----------------------------------------------------------
 
-    if( poDefaultRAT ) 
+    if( poDefaultRAT )
     {
         delete poDefaultRAT;
     }
@@ -2276,7 +2237,7 @@ CPLErr IdrisiRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT )
 /************************************************************************/
 
 GDALRasterAttributeTable *IdrisiRasterBand::GetDefaultRAT()
-{        
+{
     IdrisiDataset *poGDS = (IdrisiDataset *) poDS;
 
     if( poGDS->papszCategories == NULL )
@@ -2290,7 +2251,7 @@ GDALRasterAttributeTable *IdrisiRasterBand::GetDefaultRAT()
     // Create the bands Attribute Table
     // ----------------------------------------------------------
 
-    if( poDefaultRAT ) 
+    if( poDefaultRAT )
     {
         delete poDefaultRAT;
     }
@@ -2314,16 +2275,15 @@ GDALRasterAttributeTable *IdrisiRasterBand::GetDefaultRAT()
     poDefaultRAT->CreateColumn( "Class_name", GFT_String,  GFU_Name );
 
     // ----------------------------------------------------------
-    // Loop throught the Category Names
+    // Loop through the Category Names.
     // ----------------------------------------------------------
 
     GDALColorEntry sEntry;
     int iName = poDefaultRAT->GetColOfUsage( GFU_Name );
     int nEntryCount = CSLCount( poGDS->papszCategories );
-    int iEntry = 0;
     int iRows = 0;
 
-    for( iEntry = 0; iEntry < nEntryCount; iEntry++ )
+    for( int iEntry = 0; iEntry < nEntryCount; iEntry++ )
     {
         if EQUAL( poGDS->papszCategories[iEntry], "" )
         {
@@ -2343,7 +2303,7 @@ GDALRasterAttributeTable *IdrisiRasterBand::GetDefaultRAT()
         poDefaultRAT->SetValue( iRows, iName, poGDS->papszCategories[iEntry] );
         iRows++;
     }
-  
+
     return poDefaultRAT;
 }
 
@@ -2353,30 +2313,30 @@ GDALRasterAttributeTable *IdrisiRasterBand::GetDefaultRAT()
 
 /***
 * Converts Idrisi geographic reference information to OpenGIS WKT.
-* 
-* The Idrisi metadata file contain two fields that describe the  
-* geographic reference, RefSystem and RefUnit. 
-* 
-* RefSystem can contains the world "plane" or the name of a georeference 
+*
+* The Idrisi metadata file contain two fields that describe the
+* geographic reference, RefSystem and RefUnit.
+*
+* RefSystem can contains the world "plane" or the name of a georeference
 * file <refsystem>.ref that details the geographic reference
-* system( coordinate system and projection parameters ). RefUnits 
-* indicates the unit of the image bounds. 
-* 
-* The georeference files are generally located in the product installation 
-* folder $IDRISIDIR\Georef, but they are first looked for in the same  
-* folder as the data file. 
-*  
-* If a Reference system names can be recognized by a name convention 
-* it will be interpreted without the need to read the georeference file. 
-* That includes "latlong" and all the UTM and State Plane zones.  
-* 
-* RefSystem "latlong" means that the data is not project and the coordinate 
-* system is WGS84. RefSystem "plane" means that the there is no coordinate 
+* system( coordinate system and projection parameters ). RefUnits
+* indicates the unit of the image bounds.
+*
+* The georeference files are generally located in the product installation
+* folder $IDRISIDIR\Georef, but they are first looked for in the same
+* folder as the data file.
+*
+* If a Reference system names can be recognized by a name convention
+* it will be interpreted without the need to read the georeference file.
+* That includes "latlong" and all the UTM and State Plane zones.
+*
+* RefSystem "latlong" means that the data is not project and the coordinate
+* system is WGS84. RefSystem "plane" means that the there is no coordinate
 * system but the it is possible to calculate areas and distance by looking
 * at the RefUnits.
-*  
-* If the environment variable IDRISIDIR is not set and the georeference file  
-* need to be read then the projection string will result as unknown. 
+*
+* If the environment variable IDRISIDIR is not set and the georeference file
+* need to be read then the projection string will result as unknown.
 ***/
 
 CPLErr IdrisiGeoReference2Wkt( const char* pszFilename,
@@ -2389,7 +2349,7 @@ CPLErr IdrisiGeoReference2Wkt( const char* pszFilename,
     *ppszProjString = NULL;
 
     // ---------------------------------------------------------
-    //  Plane 
+    //  Plane
     // ---------------------------------------------------------
 
     if( EQUAL( pszRefSystem, rstPLANE ) )
@@ -2410,7 +2370,7 @@ CPLErr IdrisiGeoReference2Wkt( const char* pszFilename,
     //  Latlong
     // ---------------------------------------------------------
 
-    if( EQUAL( pszRefSystem, rstLATLONG  ) || 
+    if( EQUAL( pszRefSystem, rstLATLONG  ) ||
         EQUAL( pszRefSystem, rstLATLONG2 ) )
     {
         oSRS.SetWellKnownGeogCS( "WGS84" );
@@ -2422,8 +2382,7 @@ CPLErr IdrisiGeoReference2Wkt( const char* pszFilename,
     //  Prepare for scanning in lower case
     // ---------------------------------------------------------
 
-    char *pszRefSystemLower;
-    pszRefSystemLower = CPLStrdup( pszRefSystem );
+    char *pszRefSystemLower = CPLStrdup( pszRefSystem );
     CPLStrlwr( pszRefSystemLower );
 
     // ---------------------------------------------------------
@@ -2472,7 +2431,7 @@ CPLErr IdrisiGeoReference2Wkt( const char* pszFilename,
             oSRS.SetWellKnownGeogCS( CPLSPrintf( "NAD%d", nNAD ) );
         }
     }
-    
+
     CPLFree( pszRefSystemLower );
     pszRefSystemLower = NULL;
 
@@ -2480,7 +2439,7 @@ CPLErr IdrisiGeoReference2Wkt( const char* pszFilename,
     //  Search for georeference file <RefSystem>.ref
     // ------------------------------------------------------------------
 
-    const char *pszFName = CPLSPrintf( "%s%c%s.ref", 
+    const char *pszFName = CPLSPrintf( "%s%c%s.ref",
         CPLGetDirname( pszFilename ), PATHDELIM,  pszRefSystem );
 
     if( ! FileExists( pszFName ) )
@@ -2493,7 +2452,7 @@ CPLErr IdrisiGeoReference2Wkt( const char* pszFilename,
 
         if( ( pszIdrisiDir ) != NULL )
         {
-            pszFName = CPLSPrintf( "%s%cgeoref%c%s.ref", 
+            pszFName = CPLSPrintf( "%s%cgeoref%c%s.ref",
                 pszIdrisiDir, PATHDELIM, PATHDELIM, pszRefSystem );
         }
     }
@@ -2523,7 +2482,7 @@ CPLErr IdrisiGeoReference2Wkt( const char* pszFilename,
     }
 
     // ------------------------------------------------------------------
-    //  Read values from georeference file 
+    //  Read values from georeference file
     // ------------------------------------------------------------------
 
     char **papszRef = CSLLoad( pszFName );
@@ -2543,14 +2502,14 @@ CPLErr IdrisiGeoReference2Wkt( const char* pszFilename,
     char *pszProjName           = CPLStrdup( CSLFetchNameValue( papszRef, refPROJECTION ) );
     char *pszDatum              = CPLStrdup( CSLFetchNameValue( papszRef, refDATUM ) );
     char *pszEllipsoid          = CPLStrdup( CSLFetchNameValue( papszRef, refELLIPSOID ) );
-    double dfCenterLat          = CPLAtof_nz( CSLFetchNameValue( papszRef, refORIGIN_LAT ) );
-    double dfCenterLong         = CPLAtof_nz( CSLFetchNameValue( papszRef, refORIGIN_LONG ) );
-    double dfSemiMajor          = CPLAtof_nz( CSLFetchNameValue( papszRef, refMAJOR_SAX ) );
-    double dfSemiMinor          = CPLAtof_nz( CSLFetchNameValue( papszRef, refMINOR_SAX ) );
-    double dfFalseEasting       = CPLAtof_nz( CSLFetchNameValue( papszRef, refORIGIN_X ) );
-    double dfFalseNorthing      = CPLAtof_nz( CSLFetchNameValue( papszRef, refORIGIN_Y ) );
-    double dfStdP1              = CPLAtof_nz( CSLFetchNameValue( papszRef, refSTANDL_1 ) );
-    double dfStdP2              = CPLAtof_nz( CSLFetchNameValue( papszRef, refSTANDL_2 ) );
+    const double dfCenterLat    = CPLAtof_nz( CSLFetchNameValue( papszRef, refORIGIN_LAT ) );
+    const double dfCenterLong   = CPLAtof_nz( CSLFetchNameValue( papszRef, refORIGIN_LONG ) );
+    const double dfSemiMajor    = CPLAtof_nz( CSLFetchNameValue( papszRef, refMAJOR_SAX ) );
+    const double dfSemiMinor    = CPLAtof_nz( CSLFetchNameValue( papszRef, refMINOR_SAX ) );
+    const double dfFalseEasting = CPLAtof_nz( CSLFetchNameValue( papszRef, refORIGIN_X ) );
+    const double dfFalseNorthing = CPLAtof_nz( CSLFetchNameValue( papszRef, refORIGIN_Y ) );
+    const double dfStdP1        = CPLAtof_nz( CSLFetchNameValue( papszRef, refSTANDL_1 ) );
+    const double dfStdP2        = CPLAtof_nz( CSLFetchNameValue( papszRef, refSTANDL_2 ) );
     double dfScale;
     double adfToWGS84[3] = { 0.0, 0.0, 0.0 };
 
@@ -2579,30 +2538,30 @@ CPLErr IdrisiGeoReference2Wkt( const char* pszFilename,
         //  Is it a WGS84 equivalent?
         // ----------------------------------------------------------------------
 
-        if( ( EQUALN( pszEllipsoid, "WGS", 3 ) ) &&( strstr( pszEllipsoid, "84" ) ) &&
-            ( EQUALN( pszDatum, "WGS", 3 ) )     &&( strstr( pszDatum, "84" ) ) &&
+        if( ( STARTS_WITH_CI(pszEllipsoid, "WGS") ) &&( strstr( pszEllipsoid, "84" ) ) &&
+            ( STARTS_WITH_CI(pszDatum, "WGS") )     &&( strstr( pszDatum, "84" ) ) &&
             ( adfToWGS84[0] == 0.0 ) &&( adfToWGS84[1] == 0.0 ) &&( adfToWGS84[2] == 0.0 ) )
         {
             nEPSG = 4326;
         }
 
         // ----------------------------------------------------------------------
-        //  Match GCS's DATUM_NAME by using 'ApproxString' over Datum 
+        //  Match GCS's DATUM_NAME by using 'ApproxString' over Datum
         // ----------------------------------------------------------------------
 
         if( nEPSG == 0 )
         {
-            nEPSG = atoi_nz( CSVGetField( CSVFilename( "gcs.csv" ), 
+            nEPSG = atoi_nz( CSVGetField( CSVFilename( "gcs.csv" ),
                 "DATUM_NAME", pszDatum, CC_ApproxString, "COORD_REF_SYS_CODE" ) );
         }
 
         // ----------------------------------------------------------------------
-        //  Match GCS's COORD_REF_SYS_NAME by using 'ApproxString' over Datum 
+        //  Match GCS's COORD_REF_SYS_NAME by using 'ApproxString' over Datum
         // ----------------------------------------------------------------------
 
         if( nEPSG == 0 )
         {
-            nEPSG = atoi_nz( CSVGetField( CSVFilename( "gcs.csv" ), 
+            nEPSG = atoi_nz( CSVGetField( CSVFilename( "gcs.csv" ),
                 "COORD_REF_SYS_NAME", pszDatum, CC_ApproxString, "COORD_REF_SYS_CODE" ) );
         }
 
@@ -2616,10 +2575,10 @@ CPLErr IdrisiGeoReference2Wkt( const char* pszFilename,
             //  Create GeogCS based on the georeference file info
             // --------------------------------------------------
 
-            oSRS.SetGeogCS( pszRefSystem, 
-                pszDatum, 
-                pszEllipsoid, 
-                dfSemiMajor, 
+            oSRS.SetGeogCS( pszRefSystem,
+                pszDatum,
+                pszEllipsoid,
+                dfSemiMajor,
                 (dfSemiMinor == dfSemiMajor) ? 0.0 : ( -1.0 /( dfSemiMinor / dfSemiMajor - 1.0 ) ) );
         }
 
@@ -2637,12 +2596,12 @@ CPLErr IdrisiGeoReference2Wkt( const char* pszFilename,
     if( EQUAL( pszProjName, "none" ) )
     {
         oSRS.exportToWkt( ppszProjString );
-        
+
         CPLFree( pszGeorefName );
         CPLFree( pszProjName );
         CPLFree( pszDatum );
         CPLFree( pszEllipsoid );
-        
+
         return CE_None;
     }
 
@@ -2678,7 +2637,7 @@ CPLErr IdrisiGeoReference2Wkt( const char* pszFilename,
     {
         oSRS.SetTM( dfCenterLat, dfCenterLong, dfScale, dfFalseEasting, dfFalseNorthing );
     }
-    else if EQUALN( pszProjName, "Gauss-Kruger", 9 )
+    else if EQUAL( pszProjName, "Gauss-Kruger" )
     {
         oSRS.SetTM( dfCenterLat, dfCenterLong, dfScale, dfFalseEasting, dfFalseNorthing );
     }
@@ -2686,7 +2645,7 @@ CPLErr IdrisiGeoReference2Wkt( const char* pszFilename,
     {
         oSRS.SetLCC( dfStdP1, dfStdP2, dfCenterLat, dfCenterLong, dfFalseEasting, dfFalseNorthing );
     }
-    else if( EQUALN( pszProjName, "Plate Carr" "\xE9" "e", 10 ) ) /* 'eacute' in ISO-8859-1 */
+    else if( EQUAL( pszProjName, "Plate Carr" "\xE9" "e" ) ) /* 'eacute' in ISO-8859-1 */
     {
         oSRS.SetEquirectangular( dfCenterLat, dfCenterLong, dfFalseEasting, dfFalseNorthing );
     }
@@ -2698,23 +2657,23 @@ CPLErr IdrisiGeoReference2Wkt( const char* pszFilename,
         oSRS.SetProjParm( SRS_PP_FALSE_EASTING,       dfFalseEasting );
         oSRS.SetProjParm( SRS_PP_FALSE_NORTHING,      dfFalseNorthing );
     }
-    else if( EQUALN( pszProjName, "Lambert North Polar Azimuthal Equal Area", 15 ) ||
-        EQUALN( pszProjName, "Lambert South Polar Azimuthal Equal Area", 15 ) ||
-        EQUALN( pszProjName, "Lambert Transverse Azimuthal Equal Area", 15 ) ||
-        EQUALN( pszProjName, "Lambert Oblique Polar Azimuthal Equal Area", 15 ) )
+    else if( EQUAL( pszProjName, "Lambert North Polar Azimuthal Equal Area" ) ||
+        EQUAL( pszProjName, "Lambert South Polar Azimuthal Equal Area" ) ||
+        EQUAL( pszProjName, "Lambert Transverse Azimuthal Equal Area" ) ||
+        EQUAL( pszProjName, "Lambert Oblique Polar Azimuthal Equal Area" ) )
     {
         oSRS.SetLAEA( dfCenterLat, dfCenterLong, dfFalseEasting, dfFalseNorthing );
     }
-    else if( EQUALN( pszProjName, "North Polar Stereographic", 15 ) ||
-        EQUALN( pszProjName, "South Polar Stereographic", 15 ) )
+    else if( EQUAL( pszProjName, "North Polar Stereographic" ) ||
+        EQUAL( pszProjName, "South Polar Stereographic" ) )
     {
         oSRS.SetPS( dfCenterLat, dfCenterLong, dfScale, dfFalseEasting, dfFalseNorthing );
     }
-    else if( EQUALN( pszProjName, "Transverse Stereographic", 15 ) )
+    else if( EQUAL( pszProjName, "Transverse Stereographic" ) )
     {
         oSRS.SetStereographic( dfCenterLat, dfCenterLong, dfScale, dfFalseEasting, dfFalseNorthing );
     }
-    else if( EQUALN( pszProjName, "Oblique Stereographic", 15 ) )
+    else if( EQUAL( pszProjName, "Oblique Stereographic" ) )
     {
         oSRS.SetOS( dfCenterLat, dfCenterLong, dfScale, dfFalseEasting, dfFalseNorthing );
     }
@@ -2729,18 +2688,18 @@ CPLErr IdrisiGeoReference2Wkt( const char* pszFilename,
     }
     else
     {
-        CPLError( CE_Warning, CPLE_NotSupported, 
-            "Projection not listed on Idrisi User's Manual( v.15.0/2005 ).\n\t" 
+        CPLError( CE_Warning, CPLE_NotSupported,
+            "Projection not listed on Idrisi User's Manual( v.15.0/2005 ).\n\t"
             "[\"%s\" in georeference file \"%s\"]",
             pszProjName, pszFName );
         oSRS.Clear();
         oSRS.exportToWkt( ppszProjString );
-        
+
         CPLFree( pszGeorefName );
         CPLFree( pszProjName );
         CPLFree( pszDatum );
         CPLFree( pszEllipsoid );
-        
+
         return CE_Warning;
     }
 
@@ -2767,12 +2726,12 @@ CPLErr IdrisiGeoReference2Wkt( const char* pszFilename,
     oSRS.SetProjCS( pszGeorefName );
 
     oSRS.exportToWkt( ppszProjString );
-        
+
     CPLFree( pszGeorefName );
     CPLFree( pszProjName );
     CPLFree( pszDatum );
     CPLFree( pszEllipsoid );
-        
+
     return CE_None;
 }
 
@@ -2782,19 +2741,19 @@ CPLErr IdrisiGeoReference2Wkt( const char* pszFilename,
 
 /***
 * Converts OpenGIS WKT to Idrisi geographic reference information.
-* 
+*
 * That function will fill up the two parameters RefSystem and RefUnit
 * that goes into the Idrisi metadata. But it could also create
-* a companying georeference file to the output if necessary.
+* a accompanying georeference file to the output if necessary.
 *
 * First it will try to identify the ProjString as Local, WGS84 or
 * one of the Idrisi name convention reference systems
-* otherwise, if the projection system is supported by Idrisi,  
-* it will create a companying georeference files.
+* otherwise, if the projection system is supported by Idrisi,
+* it will create a accompanying georeference files.
 ***/
 
 CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
-                                        char **pszRefSystem, 
+                                        char **pszRefSystem,
                                         char **pszRefUnit )
 {
     // -----------------------------------------------------
@@ -2818,7 +2777,7 @@ CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
     if( oSRS.IsLocal() )
     {
         *pszRefSystem = CPLStrdup( rstPLANE );
-        *pszRefUnit   = GetUnitDefault( oSRS.GetAttrValue( "UNIT" ), 
+        *pszRefUnit   = GetUnitDefault( oSRS.GetAttrValue( "UNIT" ),
                                         CPLSPrintf( "%f", oSRS.GetLinearUnits() ) );
         return CE_None;
     }
@@ -2837,9 +2796,9 @@ CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
                 {
                     nGCSCode = atoi( oSRS.GetAuthorityCode( "GEOGCS" ) );
                 }
-        if( ( nGCSCode == 4326 ) ||( 
-                ( EQUALN( pszSpheroid, "WGS", 3 ) ) &&( strstr( pszSpheroid, "84" ) ) &&
-                ( EQUALN( pszDatum, "WGS", 3 ) )    &&( strstr( pszDatum, "84" ) ) ) )
+        if( ( nGCSCode == 4326 ) ||(
+                ( STARTS_WITH_CI(pszSpheroid, "WGS") ) &&( strstr( pszSpheroid, "84" ) ) &&
+                ( STARTS_WITH_CI(pszDatum, "WGS") )    &&( strstr( pszDatum, "84" ) ) ) )
         {
             *pszRefSystem = CPLStrdup( rstLATLONG );
             *pszRefUnit   = CPLStrdup( rstDEGREE );
@@ -2857,7 +2816,7 @@ CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
     }
 
     // -----------------------------------------------------
-    //  Prepare to match some projections 
+    //  Prepare to match some projections
     // -----------------------------------------------------
 
     const char *pszProjName = oSRS.GetAttrValue( "PROJECTION" );
@@ -2893,23 +2852,24 @@ CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
     if( EQUAL( pszProjName, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP ) ||
         EQUAL( pszProjName, SRS_PT_TRANSVERSE_MERCATOR ) )
     {
-        const char *pszPCSCode;
-        const char *pszID = CPLStrdup( oSRS.GetAuthorityCode( "PROJCS" ) );
-        if( strlen( pszID ) > 0 )
+        CPLString osPCSCode;
+        const char *pszID = oSRS.GetAuthorityCode( "PROJCS" );
+        if( pszID != NULL && strlen( pszID ) > 0 )
         {
-            pszPCSCode = CPLStrdup( CSVGetField( CSVFilename( "stateplane.csv" ),
-                                                 "EPSG_PCS_CODE", pszID, CC_Integer, "ID" ) );
-            if( strlen( pszPCSCode ) > 0 )
+            const char* pszPCSCode = CSVGetField( CSVFilename( "stateplane.csv" ),
+                                                 "EPSG_PCS_CODE", pszID, CC_Integer, "ID" );
+            osPCSCode = (pszPCSCode) ? pszPCSCode : "";
+            if( osPCSCode.size() )
             {
-                int nNADYear   = 83;
-                int nZone      = pszPCSCode[strlen( pszPCSCode ) - 1] - '0';
-                int nSPCode    = atoi_nz( pszPCSCode );
+                int nZone      = osPCSCode[osPCSCode.size() - 1] - '0';
+                int nSPCode    = atoi_nz( osPCSCode );
 
                 if( nZone == 0 )
                     nZone = 1;
                 else
                     nSPCode = nSPCode - nZone + 1;
 
+                int nNADYear = 83;
                 if( nSPCode > 10000 )
                 {
                     nNADYear = 27;
@@ -2921,8 +2881,10 @@ CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
                     *pszRefSystem   = CPLStrdup( CPLSPrintf( rstSPC, nNADYear, pszState, nZone ) );
                     *pszRefUnit     = GetUnitDefault( oSRS.GetAttrValue( "UNIT" ),
                                                       CPLSPrintf( "%f", oSRS.GetLinearUnits() ) );
+                    CPLFree( pszState );
                     return CE_None;
                 }
+                CPLFree( pszState );
             }
         }//
 
@@ -2932,12 +2894,12 @@ CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
 
         const char *pszNAD83 = "83";
         const char *pszNAD27 = "27";
-        int isOldNAD = FALSE;
+        bool bIsOldNAD = false;
 
         const char *pszDatumValue = oSRS.GetAttrValue("DATUM",0);
         if( (strstr(pszDatumValue, pszNAD83) == NULL) && (strstr(pszDatumValue, pszNAD27) != NULL ))
             //strcpy(pszNAD, "27");
-            isOldNAD = TRUE;
+            bIsOldNAD = true;
 
         if ( (oSRS.FindProjParm("central_meridian",NULL) != -1) && (oSRS.FindProjParm("central_meridian",NULL) != -1) )
         {
@@ -2947,14 +2909,14 @@ CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
             dfLat = (int)(fabs(dfLat) * 100 + 0.5) / 100.0;
             *pszRefSystem = CPLStrdup(GetSpcs(dfLon, dfLat));
         }
-		
+
         if(*pszRefSystem != NULL)
         {
             //Convert 83 TO 27
-            if(isOldNAD)
+            if(bIsOldNAD)
             {
                 char pszOutRefSystem[9];
-                NAD83to27(pszOutRefSystem, *pszRefSystem);	
+                NAD83to27(pszOutRefSystem, *pszRefSystem);
                 *pszRefSystem = CPLStrdup(pszOutRefSystem);
             }
             *pszRefUnit = GetUnitDefault( oSRS.GetAttrValue( "UNIT" ), CPLSPrintf( "%f", oSRS.GetLinearUnits() ) );
@@ -2977,8 +2939,8 @@ CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
                 {
                     pszProjectionOut =  "Mercator" ;
                 }
-        if EQUAL( pszProjName, SRS_PT_TRANSVERSE_MERCATOR )         
-                {   
+        if EQUAL( pszProjName, SRS_PT_TRANSVERSE_MERCATOR )
+                {
                     pszProjectionOut =  "Transverse Mercator" ;
                 }
         else if EQUAL( pszProjName, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP )
@@ -2990,14 +2952,14 @@ CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
                          pszProjectionOut =  "Plate Carr" "\xE9" "e" ; /* 'eacute' in ISO-8859-1 */
                      }
         else if EQUAL( pszProjName, SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA )
-                     {   
+                     {
                          double dfCenterLat = oSRS.GetProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0, NULL );
                          if( dfCenterLat == 0.0 )
-                             pszProjectionOut =  "Lambert Transverse Azimuthal Equal Area" ; 
+                             pszProjectionOut =  "Lambert Transverse Azimuthal Equal Area" ;
                          else if( fabs( dfCenterLat ) == 90.0 )
                              pszProjectionOut =  "Lambert Oblique Polar Azimuthal Equal Area" ;
                          else if( dfCenterLat > 0.0 )
-                             pszProjectionOut =  "Lambert North Oblique Azimuthal Equal Area" ; 
+                             pszProjectionOut =  "Lambert North Oblique Azimuthal Equal Area" ;
                          else
                              pszProjectionOut =  "Lambert South Oblique Azimuthal Equal Area" ;
                      }
@@ -3052,19 +3014,19 @@ CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
     char *pszGeorefName         = CPLStrdup( "Unknown" );
     char *pszDatum              = CPLStrdup( oSRS.GetAttrValue( "DATUM" ) );
     char *pszEllipsoid          = CPLStrdup( oSRS.GetAttrValue( "SPHEROID" ) );
-    double dfSemiMajor          = oSRS.GetSemiMajor();        
-    double dfSemiMinor          = oSRS.GetSemiMinor();        
+    double dfSemiMajor          = oSRS.GetSemiMajor();
+    double dfSemiMinor          = oSRS.GetSemiMinor();
     double adfToWGS84[3];
     oSRS.GetTOWGS84( adfToWGS84, 3 );
 
     double dfCenterLat          = 0.0;
-    double dfCenterLong         = 0.0;        
-    double dfFalseNorthing      = 0.0;    
-    double dfFalseEasting       = 0.0;    
+    double dfCenterLong         = 0.0;
+    double dfFalseNorthing      = 0.0;
+    double dfFalseEasting       = 0.0;
     double dfScale              = 1.0;
-    int nParameters             = 0;         
-    double dfStdP1              = 0.0;            
-    double dfStdP2              = 0.0;            
+    int nParameters             = 0;
+    double dfStdP1              = 0.0;
+    double dfStdP2              = 0.0;
     char *pszAngularUnit        = CPLStrdup( oSRS.GetAttrValue( "GEOGCS|UNIT" ) );
     char *pszLinearUnit;
 
@@ -3078,7 +3040,7 @@ CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
         dfFalseEasting  = oSRS.GetProjParm( SRS_PP_FALSE_EASTING, 0.0, NULL );
         dfScale         = oSRS.GetProjParm( SRS_PP_SCALE_FACTOR, 0.0, NULL );
         dfStdP1         = oSRS.GetProjParm( SRS_PP_STANDARD_PARALLEL_1, -0.1, NULL );
-        dfStdP2         = oSRS.GetProjParm( SRS_PP_STANDARD_PARALLEL_2, -0.1, NULL );  
+        dfStdP2         = oSRS.GetProjParm( SRS_PP_STANDARD_PARALLEL_2, -0.1, NULL );
         if( dfStdP1 != -0.1 )
         {
             nParameters = 1;
@@ -3098,10 +3060,10 @@ CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
     // ---------------------------------------------------------
 
     char **papszRef = NULL;
-    papszRef = CSLAddNameValue( papszRef, refREF_SYSTEM,   pszGeorefName );  
-    papszRef = CSLAddNameValue( papszRef, refPROJECTION,   pszProjectionOut );  
-    papszRef = CSLAddNameValue( papszRef, refDATUM,        pszDatum );     
-    papszRef = CSLAddNameValue( papszRef, refDELTA_WGS84,  CPLSPrintf( "%.3g %.3g %.3g", 
+    papszRef = CSLAddNameValue( papszRef, refREF_SYSTEM,   pszGeorefName );
+    papszRef = CSLAddNameValue( papszRef, refPROJECTION,   pszProjectionOut );
+    papszRef = CSLAddNameValue( papszRef, refDATUM,        pszDatum );
+    papszRef = CSLAddNameValue( papszRef, refDELTA_WGS84,  CPLSPrintf( "%.3g %.3g %.3g",
                                                                        adfToWGS84[0], adfToWGS84[1], adfToWGS84[2] ) );
     papszRef = CSLAddNameValue( papszRef, refELLIPSOID,    pszEllipsoid );
     papszRef = CSLAddNameValue( papszRef, refMAJOR_SAX,    CPLSPrintf( "%.3f", dfSemiMajor ) );
@@ -3141,7 +3103,7 @@ bool FileExists( const char *pszPath )
 {
     VSIStatBufL  sStat;
 
-    return (bool) ( VSIStatL( pszPath, &sStat ) == 0 );
+    return VSIStatL( pszPath, &sStat ) == 0;
 }
 
 /************************************************************************/
@@ -3150,9 +3112,7 @@ bool FileExists( const char *pszPath )
 
 int GetStateCode( const char *pszState )
 {
-    unsigned int i;
-
-    for( i = 0; i < US_STATE_COUNT; i++ )
+    for( unsigned int i = 0; i < US_STATE_COUNT; i++ )
     {
         if EQUAL( pszState, aoUSStateTable[i].pszName )
         {
@@ -3168,9 +3128,7 @@ int GetStateCode( const char *pszState )
 
 const char *GetStateName( int nCode )
 {
-    unsigned int i;
-
-    for( i = 0; i < US_STATE_COUNT; i++ )
+    for( unsigned int i = 0; i < US_STATE_COUNT; i++ )
     {
         if( nCode == aoUSStateTable[i].nCode )
         {
@@ -3187,8 +3145,7 @@ const char *GetStateName( int nCode )
 
 char *GetSpcs(double dfLon, double dfLat)
 {
-    int i;
-    for( i=0; i<ORIGIN_COUNT; i++)
+    for( int i=0; i<ORIGIN_COUNT; i++)
     {
         if(( dfLon == SPCS83Origin[i].longitude ) && ( dfLat == SPCS83Origin[i].latitude ))
         {
@@ -3203,10 +3160,8 @@ char *GetSpcs(double dfLon, double dfLat)
 /************************************************************************/
 void NAD83to27( char *pszOutRef, char *pszInRef)
 {
-    char *pOutput, *pInput;
-
-    pOutput = pszOutRef;
-    pInput = pszInRef;
+    char *pOutput = pszOutRef;
+    char *pInput = pszInRef;
     strncpy(pOutput, pInput, 3);
 
     pOutput = pOutput +3;
@@ -3218,17 +3173,13 @@ void NAD83to27( char *pszOutRef, char *pszInRef)
     strcpy(pOutput, pInput);
 }
 
-
-
 /************************************************************************/
 /*                            GetUnitIndex()                            */
 /************************************************************************/
 
 int GetUnitIndex( const char *pszUnitName )
 {
-    int i;
-
-    for( i = 0; i < (int) LINEAR_UNITS_COUNT; i++ )
+    for( int i = 0; i < (int) LINEAR_UNITS_COUNT; i++ )
     {
         if EQUAL( pszUnitName, aoLinearUnitsConv[i].pszName )
         {
@@ -3244,13 +3195,11 @@ int GetUnitIndex( const char *pszUnitName )
 
 int GetToMeterIndex( const char *pszToMeter )
 {
-    double dfToMeter = CPLAtof_nz(pszToMeter);
+    const double dfToMeter = CPLAtof_nz(pszToMeter);
 
     if( dfToMeter != 0.0 )
     {
-        int i;
-
-        for( i = 0; i < (int) LINEAR_UNITS_COUNT; i++ )
+        for( int i = 0; i < (int) LINEAR_UNITS_COUNT; i++ )
         {
             if ( ABS( aoLinearUnitsConv[i].dfConv - dfToMeter ) < 0.00001 )
             {
@@ -3290,18 +3239,18 @@ char *GetUnitDefault( const char *pszUnitName, const char *pszToMeter )
 /***
  * Write a stringlist to a CR + LF terminated text file.
  *
- * Returns the number of lines written, or 0 if the file could not 
+ * Returns the number of lines written, or 0 if the file could not
  * be written.
  */
 
 int  SaveAsCRLF(char **papszStrList, const char *pszFname)
 {
-    VSILFILE    *fp;
+    VSILFILE *fp = VSIFOpenL(pszFname, "wt");
     int     nLines = 0;
 
     if (papszStrList)
     {
-        if ((fp = VSIFOpenL(pszFname, "wt")) != NULL)
+        if (fp != NULL)
         {
             while(*papszStrList != NULL)
             {
@@ -3336,26 +3285,24 @@ int  SaveAsCRLF(char **papszStrList, const char *pszFname)
 
 void GDALRegister_IDRISI()
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "RST" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "RST" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "RST" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, rstVERSION );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_Idrisi.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, extRST );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte Int16 Float32" );
+    poDriver->SetDescription( "RST" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, rstVERSION );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_Idrisi.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, extRST );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte Int16 Float32" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = IdrisiDataset::Open;
-        poDriver->pfnCreate = IdrisiDataset::Create;
-        poDriver->pfnCreateCopy = IdrisiDataset::CreateCopy;
+    poDriver->pfnOpen = IdrisiDataset::Open;
+    poDriver->pfnCreate = IdrisiDataset::Create;
+    poDriver->pfnCreateCopy = IdrisiDataset::CreateCopy;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
-
diff --git a/frmts/idrisi/frmt_Idrisi.html b/frmts/idrisi/frmt_Idrisi.html
index e342177..fe2c34f 100644
--- a/frmts/idrisi/frmt_Idrisi.html
+++ b/frmts/idrisi/frmt_Idrisi.html
@@ -4,34 +4,34 @@
 	</head>
 	<body bgcolor="#ffffff">
 		<h1>RST --- Idrisi Raster Format</h1>
-		<P class="MsoNormal">This format is basically a raw one. There is just one band per 
-			files, except in the RGB24 data type where the Red, Green and Blue bands are 
-			store interleafed by pixels in the order Blue, Green and Red. The others data 
-			type are unsigned 8 bits integer with values from 0 to 255 or signed 16 bits 
-			integer with values from -32.768 to 32.767 or 32 bits single precision floating 
-			point.32 bits. The description of the file is stored in a companying text file, 
+		<P class="MsoNormal">This format is basically a raw one. There is just one band per
+			files, except in the RGB24 data type where the Red, Green and Blue bands are
+			store interleaved by pixels in the order Blue, Green and Red. The others data
+			type are unsigned 8 bits integer with values from 0 to 255 or signed 16 bits
+			integer with values from -32.768 to 32.767 or 32 bits single precision floating
+			point.32 bits. The description of the file is stored in a accompanying text file,
 			extension RDC.
 		</P>
-		<P class="MsoNormal">The RDC image description file doesn't include color table, or 
-			detailed geographic referencing information. The color table if present can be 
-			obtained by another companying file using the same base name as the RST file 
+		<P class="MsoNormal">The RDC image description file doesn't include color table, or
+			detailed geographic referencing information. The color table if present can be
+			obtained by another accompanying file using the same base name as the RST file
 			and SMP as extension.
 		</P>
-		<P class="MsoNormal">For geographical referencing identification, the RDC file 
-			contains information that points to a file that holds the geographic reference 
+		<P class="MsoNormal">For geographical referencing identification, the RDC file
+			contains information that points to a file that holds the geographic reference
 			details. Those files uses extension REF and
-			<SPAN style="mso-spacerun: yes"> </SPAN>resides in the same folder as the 
+			<SPAN style="mso-spacerun: yes"> </SPAN>resides in the same folder as the
 			RST image or more likely in the Idrisi installation folders.</P>
-		<P class="MsoNormal">Therefore the presence or absence of the Idrisi software in 
-			the running operation system will determine the way that this driver will work. 
-			By setting the environment variable IDRISIDIR pointing to the Idrisi main 
-			installation folder will enable GDAL to find more detailed information about 
+		<P class="MsoNormal">Therefore the presence or absence of the Idrisi software in
+			the running operation system will determine the way that this driver will work.
+			By setting the environment variable IDRISIDIR pointing to the Idrisi main
+			installation folder will enable GDAL to find more detailed information about
 			geographical reference and projection in the REF files.</P>
-		<P class="MsoNormal">Note that the RST driver recognizes the name convention used 
-			in Idrisi for UTM and State Plane geographic reference so it doesn't need to 
-			access the REF files. That is the case for RDC file that specify "utm-30n" or 
-			"spc87ma1" in the "ref. system" field. Note that exporting to RST in any other 
-			geographical reference system will generate a suggested REF content in the 
+		<P class="MsoNormal">Note that the RST driver recognizes the name convention used
+			in Idrisi for UTM and State Plane geographic reference so it doesn't need to
+			access the REF files. That is the case for RDC file that specify "utm-30n" or
+			"spc87ma1" in the "ref. system" field. Note that exporting to RST in any other
+			geographical reference system will generate a suggested REF content in the
 			comment section of the RDC file.
 		</P>
 		<P></P>
diff --git a/frmts/idrisi/idrisi.h b/frmts/idrisi/idrisi.h
index 912f170..4f18292 100644
--- a/frmts/idrisi/idrisi.h
+++ b/frmts/idrisi/idrisi.h
@@ -1,5 +1,5 @@
 /*****************************************************************************
-* $Id: idrisi.h 27044 2014-03-16 23:41:27Z rouault $
+* $Id: idrisi.h 31777 2015-11-26 14:14:41Z rouault $
 *
 * Project:  Idrisi Raster Image File Driver
 * Purpose:  Read/write Idrisi Raster Image Format RST
@@ -28,8 +28,8 @@
 * DEALINGS IN THE SOFTWARE.
 ****************************************************************************/
 
-#ifndef _IDRISI_H_INCLUDED
-#define _IDRISI_H_INCLUDED
+#ifndef IDRISI_H_INCLUDED
+#define IDRISI_H_INCLUDED
 
 #include "cpl_error.h"
 
@@ -38,4 +38,4 @@ CPLErr IdrisiGeoReference2Wkt( const char* pszFilename,
                                const char *pszRefUnits,
                                char **ppszProjString );
 
-#endif /*  _IDRISI_H_INCLUDED */
+#endif /*  IDRISI_H_INCLUDED */
diff --git a/frmts/idrisi/rdc.txt b/frmts/idrisi/rdc.txt
index a19c562..1bee3d2 100644
--- a/frmts/idrisi/rdc.txt
+++ b/frmts/idrisi/rdc.txt
@@ -39,7 +39,7 @@ min Y: The minimum Y coordinate (bottom edge) of the image.
 
 max Y: The maximum Y coordinate (top edge) of the image.
 
-pos'n error: A measure of the accuracy of the positions in the image. This field can be used to record the RMS (Root Mean Square) error of locational positions in the reference system. At present, this field is not analytical, but rather is for informational purposes only. (See RESAMPLE Note 5.)
+pos'n error: A measure of the accuracy of the positions in the image. This field can be used to record the RMS (Root Mean Square) error of positions in the reference system. At present, this field is not analytic, but rather is for informational purposes only. (See RESAMPLE Note 5.)
 
 resolution: The inherent resolution of the image. In most cases, this should correspond to the result of dividing the range of reference coordinates in X by the number of columns in the image. However, there are some rare instances where it might differ from this result. An example is the case of LANDSAT Band 6 (Thermal) imagery. The resolution of those data is actually 120 meters, and would be recorded as such in this field. However, the data is distributed in an apparent 30 meter forma [...]
 
@@ -55,7 +55,7 @@ display max: The value in the image to display with the last palette color and l
 
 value units: The unit of measure of the values in the image. It is suggested that the term classes be used for all qualitative data sets, and that whenever standard linear units are appropriate, that the same abbreviations that are used for reference units should also be used (m, ft, mi, km, deg, rad).
 
-value error: This field is very important and should be filled out whenever possible. It records the error in the data values that appear in image cells. For qualitative data, this should be recorded as a proportional error. For quantitative data, the value here should be an RMS error figure. For example, for a DEM, an RMS error of 3 would indicate 68% of all values will be within � 3 meters of the stated elevation, that approximately 95% will be within � 6 meters, and so on. This field  [...]
+value error: This field is very important and should be filled out whenever possible. It records the error in the data values that appear in image cells. For qualitative data, this should be recorded as a proportional error. For quantitative data, the value here should be an RMS error figure. For example, for a DEM, an RMS error of 3 would indicate 68% of all values will be within ± 3 meters of the stated elevation, that approximately 95% will be within ± 6 meters, and so on. This field  [...]
 
 flag value: Any value in the image that is not a data value, but rather has a special meaning. If there is no flag value, this entry should remain blank.
 
@@ -123,4 +123,4 @@ comment	: based on a stratified random sample of 37 points.
 
 Note
 
-In versions of IDRISI prior to idrisi32, these files had a .DOC extension. The format has also changed. To convert images from earlier versions to idrisi32, or to convert an idrisi32 image to an earlier version, use IDRISI Conversion Tools from the File menu.
\ No newline at end of file
+In versions of IDRISI prior to idrisi32, these files had a .DOC extension. The format has also changed. To convert images from earlier versions to idrisi32, or to convert an idrisi32 image to an earlier version, use IDRISI Conversion Tools from the File menu.
diff --git a/frmts/idrisi/rst.txt b/frmts/idrisi/rst.txt
index 145ee63..fc1b406 100644
--- a/frmts/idrisi/rst.txt
+++ b/frmts/idrisi/rst.txt
@@ -44,7 +44,7 @@ The numbers in an image file may be integer, byte or real. This is termed the da
 2. Byte values are positive integer numbers ranging from 0 to 255. 
 3. Real numbers have a fractional part, or are whole numbers outside the integer range. 
 
-The real data types can store values within a range of � 1 x 10 to the power of 38 with a precision of 7 significant figures. IDRISI supports the standard IEEE 4-byte real number format. 
+The real data types can store values within a range of ± 1 x 10 to the power of 38 with a precision of 7 significant figures. IDRISI supports the standard IEEE 4-byte real number format. 
 Two other data types are supported by Idrisi32. These are RGB8 and RGB24. Both of these are produced by the COMPOSITE module. An RGB8 file has byte data values, but these values have special meaning. The RGB24 data type indicates a band-interleaved-by-pixel format that is displayed in true color. For more information on both RGB8 and RGB24 files, see COMPOSITE.
 
 Image files may be stored in ASCII, binary or packed binary file types. The module CONVERT may be used to change data or file type. However, most routines in IDRISI expect the binary format only. 
diff --git a/frmts/ilwis/frmt_ilwis.html b/frmts/ilwis/frmt_ilwis.html
index 0cde447..9644703 100644
--- a/frmts/ilwis/frmt_ilwis.html
+++ b/frmts/ilwis/frmt_ilwis.html
@@ -7,8 +7,9 @@
 
 <h1>ILWIS -- Raster Map</h1>
 
-This driver implements reading and writing of ILWIS raster maps and map lists. 
-Select the raster fileswith <tt>the.mpr</tt> (for raster map) or <tt>the.mpl</tt> (for maplist) extensions.</p>
+This driver implements reading and writing of ILWIS raster maps and map lists.
+Select the raster files with <tt>the.mpr</tt> (for raster map) or
+<tt>the.mpl</tt> (for maplist) extensions.</p>
 
 <P>Features:</p>
 
@@ -17,7 +18,7 @@ Select the raster fileswith <tt>the.mpr</tt> (for raster map) or <tt>the.mpl</tt
 
  <li> Supports map lists with an associated set of ILWIS raster maps.</li>
  <li> Read and write geo-reference (.grf).
-     Support for geo-referencing transform is limited to north-oriented 
+     Support for geo-referencing transform is limited to north-oriented
      GeoRefCorner only. If possible the affine transform is
      computed from the corner coordinates.</li>
  <li> Read and write coordinate files (.csy).
diff --git a/frmts/ilwis/ilwiscoordinatesystem.cpp b/frmts/ilwis/ilwiscoordinatesystem.cpp
index d94eca7..c34a9d5 100644
--- a/frmts/ilwis/ilwiscoordinatesystem.cpp
+++ b/frmts/ilwis/ilwiscoordinatesystem.cpp
@@ -29,21 +29,22 @@
 #include "ilwisdataset.h"
 
 #include <string>
-using namespace std;
 
-typedef struct 
+using std::string;
+
+typedef struct
 {
     const char  *pszIlwisDatum;
-		const char  *pszWKTDatum; 
+		const char  *pszWKTDatum;
     int   nEPSGCode;
 } IlwisDatums;
 
-typedef struct 
+typedef struct
 {
     const char  *pszIlwisEllips;
     int   nEPSGCode;
 		double semiMajor;
-		double invFlattening; 
+		double invFlattening;
 } IlwisEllips;
 
 string ReadElement(string section, string entry, string filename);
@@ -57,9 +58,9 @@ static const IlwisDatums iwDatums[] =
     { "Afgooye", "Afgooye", 4205 },
 		//AGREF --- skipped
     { "Ain el Abd 1970", "Ain_el_Abd_1970", 4204 },
-		{ "American Samoa 1962", "American_Samoa_1962", 4169 },    
+		{ "American Samoa 1962", "American_Samoa_1962", 4169 },
 		//Anna 1 Astro 1965 --- skipped
-		{ "Antigua Island Astro 1943", "Antigua_1943", 4601 },    
+		{ "Antigua Island Astro 1943", "Antigua_1943", 4601 },
 		{ "Arc 1950", "Arc_1950", 4209 },    //Arc 1950
 		{ "Arc 1960", "Arc_1960", 4210 },    //Arc 1960
 		//Ascension Island 1958
@@ -67,7 +68,7 @@ static const IlwisDatums iwDatums[] =
 		//Astro DOS 71/4
 		//Astro Tern Island (FRIG) 1961
 		//Astronomical Station 1952
-		{ "Australian Geodetic 1966", "Australian_Geodetic_Datum_1966", 4202 },    
+		{ "Australian Geodetic 1966", "Australian_Geodetic_Datum_1966", 4202 },
 		{ "Australian Geodetic 1984", "Australian_Geodetic_Datum_1984", 4203 },
 		//Ayabelle Lighthouse
 		//Bellevue (IGN)
@@ -232,15 +233,11 @@ static const IlwisEllips iwEllips[] =
     { NULL, 0, 0.0, 0.0 }
 };
 
-#ifndef PI
-#  define PI 3.14159265358979323846
-#endif
-
 #ifndef R2D
-#  define R2D	(180/PI)
+#  define R2D	(180/M_PI)
 #endif
 #ifndef D2R
-#  define D2R	(PI/180)
+#  define D2R	(M_PI/180)
 #endif
 
 /* ==================================================================== */
@@ -257,34 +254,32 @@ static const IlwisEllips iwEllips[] =
 #define ILW_Latitude_True_Scale "Latitude of True Scale"
 #define ILW_Height_Persp_Center "Height Persp. Center"
 
-double ReadPrjParms(string section, string entry, string filename)
+static double ReadPrjParms(string section, string entry, string filename)
 {
     string str = ReadElement(section, entry, filename);
     //string str="";
     if (str.length() != 0)
         return CPLAtof(str.c_str());
-    else
-        return 0;
+
+    return 0.0;
 }
 
 static int fetchParms(string csyFileName, double * padfPrjParams)
 {
-    int     i;
-
     //Fill all projection parameters with zero
-    for ( i = 0; i < 13; i++ )
+    for ( int i = 0; i < 13; i++ )
         padfPrjParams[i] = 0.0;
-		
+
     string pszProj = ReadElement("CoordSystem", "Projection", csyFileName);
     string pszEllips = ReadElement("CoordSystem", "Ellipsoid", csyFileName);
 
     //fetch info about a custom ellipsoid
-    if( EQUALN( pszEllips.c_str(), "User Defined", 12 ) )
+    if( STARTS_WITH_CI(pszEllips.c_str(), "User Defined") )
     {
         padfPrjParams[0] = ReadPrjParms("Ellipsoid", "a", csyFileName);
         padfPrjParams[2] = ReadPrjParms("Ellipsoid", "1/f", csyFileName);
     }
-    else if( EQUALN( pszEllips.c_str(), "Sphere", 6 ) )
+    else if( STARTS_WITH_CI(pszEllips.c_str(), "Sphere") )
     {
         padfPrjParams[0] = ReadPrjParms("CoordSystem", "Sphere Radius", csyFileName);
     }
@@ -317,13 +312,13 @@ static int fetchParms(string csyFileName, double * padfPrjParams)
 **/
 static int mapTMParms(string sProj, double dfZone, double &dfFalseEasting, double &dfCentralMeridian)
 {
-    if( EQUALN( sProj.c_str(), "Gauss-Krueger Germany", 21 ) )
+    if( STARTS_WITH_CI(sProj.c_str(), "Gauss-Krueger Germany") )
     {
         //Zone number must be in the range 1 to 3
         dfCentralMeridian = 6.0 + (dfZone - 1) * 3;
-        dfFalseEasting = 2500000 + (dfZone - 1) * 1000000; 
+        dfFalseEasting = 2500000 + (dfZone - 1) * 1000000;
     }
-    else if( EQUALN( sProj.c_str(), "Gauss-Boaga Italy", 17 ) )
+    else if( STARTS_WITH_CI(sProj.c_str(), "Gauss-Boaga Italy") )
     {
         if ( dfZone == 1)
         {
@@ -338,7 +333,7 @@ static int mapTMParms(string sProj, double dfZone, double &dfFalseEasting, doubl
         else
             return false;
     }
-    else if( EQUALN( sProj.c_str(), "Gauss Colombia", 14 ) )
+    else if( STARTS_WITH_CI(sProj.c_str(), "Gauss Colombia") )
     {
         //Zone number must be in the range 1 to 4
         dfCentralMeridian = -77.08097220 + (dfZone - 1) * 3;
@@ -355,7 +350,7 @@ static int mapTMParms(string sProj, double dfZone, double &dfFalseEasting, doubl
 **/
 static void scaleFromLATTS( string sEllips, double phits, double &scale )
 {
-    if( EQUALN( sEllips.c_str(), "Sphere", 6 ) ) 
+    if( STARTS_WITH_CI(sEllips.c_str(), "Sphere") )
     {
         scale = cos(phits);
     }
@@ -385,27 +380,27 @@ static void scaleFromLATTS( string sEllips, double phits, double &scale )
 /**
  * Import coordinate system from ILWIS projection definition.
  *
- * The method will import projection definition in ILWIS, 
+ * The method will import projection definition in ILWIS,
  * It uses 13 parameters to define the coordinate system
- * and datum/ellipsoid specified in the padfPrjParams array. 
+ * and datum/ellipsoid specified in the padfPrjParams array.
  *
  * @param csyFileName Name of .csy file
-**/ 
+**/
 
 CPLErr ILWISDataset::ReadProjection( string csyFileName )
 {
     string pszEllips;
     string pszDatum;
     string pszProj;
-		
+
     //translate ILWIS pre-defined coordinate systems
-    if( EQUALN( csyFileName.c_str(), "latlon.csy", 10 )) 
+    if( STARTS_WITH_CI(csyFileName.c_str(), "latlon.csy"))
     {
         pszProj = "LatLon";
         pszDatum = "";
         pszEllips = "Sphere";
-    }	
-    else if ( EQUALN( csyFileName.c_str(), "LatlonWGS84.csy", 15 ))			
+    }
+    else if ( STARTS_WITH_CI(csyFileName.c_str(), "LatlonWGS84.csy"))
     {
         pszProj = "LatLon";
         pszDatum = "WGS 1984";
@@ -414,7 +409,7 @@ CPLErr ILWISDataset::ReadProjection( string csyFileName )
     else
     {
         pszProj = ReadElement("CoordSystem", "Type", csyFileName);
-        if( !EQUALN( pszProj.c_str(), "LatLon", 7 ) )
+        if( !STARTS_WITH_CI( pszProj.c_str(), "LatLon" ) )
             pszProj = ReadElement("CoordSystem", "Projection", csyFileName);
         pszDatum = ReadElement("CoordSystem", "Datum", csyFileName);
         pszEllips = ReadElement("CoordSystem", "Ellipsoid", csyFileName);
@@ -425,217 +420,214 @@ CPLErr ILWISDataset::ReadProjection( string csyFileName )
 /* -------------------------------------------------------------------- */
     double     padfPrjParams[13];
     fetchParms(csyFileName, padfPrjParams);
-		
+
     OGRSpatialReference oSRS;
 /* -------------------------------------------------------------------- */
 /*      Operate on the basis of the projection name.                    */
 /* -------------------------------------------------------------------- */
-    if( EQUALN( pszProj.c_str(), "LatLon", 7 ) )
+    if( STARTS_WITH_CI(pszProj.c_str(), "LatLon") )
     {
         //set datum later
     }
-    else if( EQUALN( pszProj.c_str(), "Albers EqualArea Conic", 22  ) )
+    else if( STARTS_WITH_CI(pszProj.c_str(), "Albers EqualArea Conic") )
     {
         oSRS.SetProjCS("Albers EqualArea Conic");
         oSRS.SetACEA( padfPrjParams[7], padfPrjParams[8],
                       padfPrjParams[5], padfPrjParams[6],
                       padfPrjParams[3], padfPrjParams[4] );
-                 
     }
-    else if( EQUALN( pszProj.c_str(), "Azimuthal Equidistant", 21 ) )
+    else if( STARTS_WITH_CI(pszProj.c_str(), "Azimuthal Equidistant") )
     {
         oSRS.SetProjCS("Azimuthal Equidistant");
         oSRS.SetAE( padfPrjParams[5], padfPrjParams[6],
                     padfPrjParams[3], padfPrjParams[4] );
     }
-    else if( EQUALN( pszProj.c_str(), "Central Cylindrical", 19 ) )
+    else if( STARTS_WITH_CI(pszProj.c_str(), "Central Cylindrical") )
     {
         //Use Central Parallel for dfStdP1
         //padfPrjParams[5] is always to zero
         oSRS.SetProjCS("Central Cylindrical");
         oSRS.SetCEA( padfPrjParams[5], padfPrjParams[6],
-                     padfPrjParams[3], padfPrjParams[4] ); 
+                     padfPrjParams[3], padfPrjParams[4] );
     }
-    else if( EQUALN( pszProj.c_str(), "Cassini", 7 ) )
+    else if( STARTS_WITH_CI(pszProj.c_str(), "Cassini") )
     {
-        //Use Latitude_Of_True_Scale for dfCenterLat 
+        //Use Latitude_Of_True_Scale for dfCenterLat
         //Scale Factor 1.0 should always be defined
         oSRS.SetProjCS("Cassini");
-        oSRS.SetCS(  padfPrjParams[10], padfPrjParams[6],  
+        oSRS.SetCS(  padfPrjParams[10], padfPrjParams[6],
                      padfPrjParams[3], padfPrjParams[4] );
     }
-    else if( EQUALN( pszProj.c_str(), "DutchRD", 7 ) )
+    else if( STARTS_WITH_CI(pszProj.c_str(), "DutchRD") )
     {
         oSRS.SetProjCS("DutchRD");
         oSRS.SetStereographic  (  52.156160556,  5.387638889,
-                                  0.9999079,  
+                                  0.9999079,
                                   155000,  463000);
-																	 
     }
-    else if( EQUALN( pszProj.c_str(), "Equidistant Conic", 17 ) )
+    else if( STARTS_WITH_CI(pszProj.c_str(), "Equidistant Conic") )
     {
         oSRS.SetProjCS("Equidistant Conic");
         oSRS.SetEC(  padfPrjParams[7], padfPrjParams[8],
-                     padfPrjParams[5], padfPrjParams[6],	
+                     padfPrjParams[5], padfPrjParams[6],
                      padfPrjParams[3], padfPrjParams[4] );
     }
-    else if( EQUALN( pszProj.c_str(), "Gauss-Krueger Germany", 21 ) )
+    else if( STARTS_WITH_CI(pszProj.c_str(), "Gauss-Krueger Germany") )
     {
         //FalseNorthing and CenterLat are always set to 0
         //Scale 1.0 is defined
         //FalseEasting and CentralMeridian are defined by the selected zone
-        mapTMParms("Gauss-Krueger Germany", padfPrjParams[11], 
+        mapTMParms("Gauss-Krueger Germany", padfPrjParams[11],
                    padfPrjParams[3], padfPrjParams[6]);
         oSRS.SetProjCS("Gauss-Krueger Germany");
         oSRS.SetTM(  0, padfPrjParams[6],
-                     1.0, 	
+                     1.0,
                      padfPrjParams[3], 0 );
     }
-    else if ( EQUALN( pszProj.c_str(),"Gauss-Boaga Italy", 17 ) )
+    else if ( STARTS_WITH_CI(pszProj.c_str(), "Gauss-Boaga Italy") )
     {
         //FalseNorthing and CenterLat are always set to 0
         //Scale 0.9996 is defined
         //FalseEasting and CentralMeridian are defined by the selected zone
-        mapTMParms("Gauss-Boaga Italy", padfPrjParams[11], 
+        mapTMParms("Gauss-Boaga Italy", padfPrjParams[11],
                    padfPrjParams[3], padfPrjParams[6]);
         oSRS.SetProjCS("Gauss-Boaga Italy");
         oSRS.SetTM(  0, padfPrjParams[6],
-                     0.9996, 	
+                     0.9996,
                      padfPrjParams[3], 0 );
     }
-    else if ( EQUALN( pszProj.c_str(),"Gauss Colombia", 14 ))
+    else if ( STARTS_WITH_CI(pszProj.c_str(), "Gauss Colombia"))
     {
         // 1000000 used for FalseNorthing and FalseEasting
-        // 1.0 used for scale 
-        // CenterLat is defined 45.1609259259259 
+        // 1.0 used for scale
+        // CenterLat is defined 45.1609259259259
         // CentralMeridian is defined by the selected zone
-        mapTMParms("Gauss Colombia", padfPrjParams[11], 
+        mapTMParms("Gauss Colombia", padfPrjParams[11],
                    padfPrjParams[3], padfPrjParams[6]);
         oSRS.SetProjCS("Gauss Colombia");
         oSRS.SetTM(  45.1609259259259, padfPrjParams[6],
-                     1.0, 	
+                     1.0,
                      1000000, 1000000 );
     }
-    else if( EQUALN( pszProj.c_str(), "Gnomonic", 8 ) )
+    else if( STARTS_WITH_CI(pszProj.c_str(), "Gnomonic") )
     {
         oSRS.SetProjCS("Gnomonic");
         oSRS.SetGnomonic( padfPrjParams[5], padfPrjParams[6],
                           padfPrjParams[3], padfPrjParams[4] );
     }
-    else if( EQUALN( pszProj.c_str(), "Lambert Conformal Conic", 23 ) )
+    else if( STARTS_WITH_CI(pszProj.c_str(), "Lambert Conformal Conic") )
     {
-        // should use 1.0 for scale factor in Ilwis definition 
+        // should use 1.0 for scale factor in Ilwis definition
         oSRS.SetProjCS("Lambert Conformal Conic");
         oSRS.SetLCC(	padfPrjParams[7], padfPrjParams[8],
                         padfPrjParams[5], padfPrjParams[6],
                         padfPrjParams[3], padfPrjParams[4] );
     }
-    else if( EQUALN( pszProj.c_str(), "Lambert Cylind EqualArea", 24 ) )
+    else if( STARTS_WITH_CI(pszProj.c_str(), "Lambert Cylind EqualArea") )
     {
         // Latitude_Of_True_Scale used for dfStdP1 ?
         oSRS.SetProjCS("Lambert Conformal Conic");
-        oSRS.SetCEA(	padfPrjParams[10], 
-                        padfPrjParams[6], 
+        oSRS.SetCEA(	padfPrjParams[10],
+                        padfPrjParams[6],
                         padfPrjParams[3], padfPrjParams[4] );
     }
-    else if( EQUALN( pszProj.c_str(), "Mercator", 8 ) )
+    else if( STARTS_WITH_CI(pszProj.c_str(), "Mercator") )
     {
-        // use 0 for CenterLat, scale is computed from the 
+        // use 0 for CenterLat, scale is computed from the
         // Latitude_Of_True_Scale
         scaleFromLATTS( pszEllips, padfPrjParams[10], padfPrjParams[9] );
         oSRS.SetProjCS("Mercator");
-        oSRS.SetMercator(	0, padfPrjParams[6], 
-                                padfPrjParams[9], 
+        oSRS.SetMercator(	0, padfPrjParams[6],
+                                padfPrjParams[9],
                                 padfPrjParams[3], padfPrjParams[4] );
     }
-    else if( EQUALN( pszProj.c_str(), "Miller", 6 ) )
+    else if( STARTS_WITH_CI(pszProj.c_str(), "Miller") )
     {
         // use 0 for CenterLat
         oSRS.SetProjCS("Miller");
-        oSRS.SetMC(	0, padfPrjParams[6], 
+        oSRS.SetMC(	0, padfPrjParams[6],
                         padfPrjParams[3], padfPrjParams[4] );
     }
-    else if( EQUALN( pszProj.c_str(), "Mollweide", 9 ) )
+    else if( STARTS_WITH_CI(pszProj.c_str(), "Mollweide") )
     {
         oSRS.SetProjCS("Mollweide");
-        oSRS.SetMollweide(	padfPrjParams[6], 
+        oSRS.SetMollweide(	padfPrjParams[6],
                                 padfPrjParams[3], padfPrjParams[4] );
     }
-    else if( EQUALN( pszProj.c_str(), "Orthographic", 12 ) )
+    else if( STARTS_WITH_CI(pszProj.c_str(), "Orthographic") )
     {
         oSRS.SetProjCS("Orthographic");
-        oSRS.SetOrthographic (	padfPrjParams[5], padfPrjParams[6], 
+        oSRS.SetOrthographic (	padfPrjParams[5], padfPrjParams[6],
                                 padfPrjParams[3], padfPrjParams[4] );
     }
-    else if( EQUALN( pszProj.c_str(), "Plate Carree", 12 ) ||
-             EQUALN( pszProj.c_str(), "Plate Rectangle", 15 ))
+    else if( STARTS_WITH_CI(pszProj.c_str(), "Plate Carree") ||
+             STARTS_WITH_CI(pszProj.c_str(), "Plate Rectangle"))
     {
         // set 0.0 for CenterLat for Plate Carree projection
         // skipp Latitude_Of_True_Scale for Plate Rectangle projection definition
-        oSRS.SetProjCS(pszProj.c_str());				
-        oSRS.SetEquirectangular(	padfPrjParams[5], padfPrjParams[6], 
+        oSRS.SetProjCS(pszProj.c_str());
+        oSRS.SetEquirectangular(	padfPrjParams[5], padfPrjParams[6],
                                         padfPrjParams[3], padfPrjParams[4] );
     }
-    else if( EQUALN( pszProj.c_str(), "PolyConic", 9 ) )
+    else if( STARTS_WITH_CI(pszProj.c_str(), "PolyConic") )
     {
         // skipp scale factor
         oSRS.SetProjCS("PolyConic");
-        oSRS.SetPolyconic(	padfPrjParams[5], padfPrjParams[6], 
+        oSRS.SetPolyconic(	padfPrjParams[5], padfPrjParams[6],
                                 padfPrjParams[3], padfPrjParams[4] );
     }
-    else if( EQUALN( pszProj.c_str(), "Robinson", 8 ) )
+    else if( STARTS_WITH_CI(pszProj.c_str(), "Robinson") )
     {
         oSRS.SetProjCS("Robinson");
         oSRS.SetRobinson(	padfPrjParams[6],
                                 padfPrjParams[3], padfPrjParams[4] );
     }
-    else if( EQUALN( pszProj.c_str(), "Sinusoidal", 10 ) )
+    else if( STARTS_WITH_CI(pszProj.c_str(), "Sinusoidal") )
     {
-        oSRS.SetProjCS("Sinusoidal");	
-        oSRS.SetSinusoidal(	padfPrjParams[6], 
+        oSRS.SetProjCS("Sinusoidal");
+        oSRS.SetSinusoidal(	padfPrjParams[6],
                                 padfPrjParams[3], padfPrjParams[4] );
     }
-    else if( EQUALN( pszProj.c_str(), "Stereographic", 13 ) )
+    else if( STARTS_WITH_CI(pszProj.c_str(), "Stereographic") )
     {
-        oSRS.SetProjCS("Stereographic");	
+        oSRS.SetProjCS("Stereographic");
         oSRS.SetStereographic(	padfPrjParams[5], padfPrjParams[6],
                                 padfPrjParams[9],
                                 padfPrjParams[3], padfPrjParams[4] );
-	
     }
-    else if( EQUALN( pszProj.c_str(), "Transverse Mercator", 19 ) )
+    else if( STARTS_WITH_CI(pszProj.c_str(), "Transverse Mercator") )
     {
-        oSRS.SetProjCS("Transverse Mercator");	
+        oSRS.SetProjCS("Transverse Mercator");
         oSRS.SetStereographic(	padfPrjParams[5], padfPrjParams[6],
                                 padfPrjParams[9],
                                 padfPrjParams[3], padfPrjParams[4] );
     }
-    else if( EQUALN( pszProj.c_str(), "UTM", 3 ) )
+    else if( STARTS_WITH_CI(pszProj.c_str(), "UTM") )
     {
         string pszNH = ReadElement("Projection", "Northern Hemisphere", csyFileName);
         oSRS.SetProjCS("UTM");
-        if( EQUALN( pszNH.c_str(), "Yes", 3 ) )
-            oSRS.SetUTM( (int) padfPrjParams[11], 1);  
+        if( STARTS_WITH_CI(pszNH.c_str(), "Yes") )
+            oSRS.SetUTM( (int) padfPrjParams[11], 1);
         else
-            oSRS.SetUTM( (int) padfPrjParams[11], 0);  
+            oSRS.SetUTM( (int) padfPrjParams[11], 0);
     }
-    else if( EQUALN( pszProj.c_str(), "VanderGrinten", 13 ) )
+    else if( STARTS_WITH_CI(pszProj.c_str(), "VanderGrinten") )
     {
         oSRS.SetVDG(	padfPrjParams[6],
                         padfPrjParams[3], padfPrjParams[4] );
     }
-    else if( EQUALN( pszProj.c_str(), "GeoStationary Satellite", 23 ) )
+    else if( STARTS_WITH_CI(pszProj.c_str(), "GeoStationary Satellite") )
     {
-        oSRS.SetGEOS( padfPrjParams[6], 
-                      padfPrjParams[12], 
-                      padfPrjParams[3], 
+        oSRS.SetGEOS( padfPrjParams[6],
+                      padfPrjParams[12],
+                      padfPrjParams[3],
                       padfPrjParams[4] );
     }
-    else if( EQUALN( pszProj.c_str(), "MSG Perspective", 15 ) )
+    else if( STARTS_WITH_CI(pszProj.c_str(), "MSG Perspective") )
     {
-        oSRS.SetGEOS( padfPrjParams[6], 
-                      padfPrjParams[12], 
-                      padfPrjParams[3], 
+        oSRS.SetGEOS( padfPrjParams[6],
+                      padfPrjParams[12],
+                      padfPrjParams[3],
                       padfPrjParams[4] );
     }
     else
@@ -661,26 +653,25 @@ CPLErr ILWISDataset::ReadProjection( string csyFileName )
                 break;
             }
             piwDatum++;
-        } //end of searchong for matching datum
+        } // End of searching for matching datum.
 
 
 /* -------------------------------------------------------------------- */
 /*      If no matching for datum definition, fetch info about an        */
-/*			ellipsoid.  semi major axis is always	returned in meters        */ 
+/*      ellipsoid.  semi major axis is always returned in meters        */
 /* -------------------------------------------------------------------- */
         const IlwisEllips *piwEllips =  iwEllips;
         if (pszEllips.length() == 0)
             pszEllips="Sphere";
-        if ( !piwDatum->pszIlwisDatum )  
-																				 
+        if ( !piwDatum->pszIlwisDatum )
         {
             while ( piwEllips->pszIlwisEllips )
             {
                 if( EQUALN( pszEllips.c_str(), piwEllips->pszIlwisEllips, strlen(piwEllips->pszIlwisEllips) ) )
                 {
                     double dfSemiMajor = piwEllips->semiMajor;
-                    if( EQUALN( pszEllips.c_str(), "Sphere", 6 ) && padfPrjParams[0] != 0 )
-                    {	
+                    if( STARTS_WITH_CI(pszEllips.c_str(), "Sphere") && padfPrjParams[0] != 0 )
+                    {
                         dfSemiMajor = padfPrjParams[0];
                     }
                     oSRS.SetGeogCS( CPLSPrintf(
@@ -689,28 +680,27 @@ CPLErr ILWISDataset::ReadProjection( string csyFileName )
                                     CPLSPrintf(
                                         "Not specified (based on %s spheroid)",
                                         piwEllips->pszIlwisEllips ),
-                                    piwEllips->pszIlwisEllips, 
+                                    piwEllips->pszIlwisEllips,
                                     dfSemiMajor,
                                     piwEllips->invFlattening,
                                     NULL, 0.0, NULL, 0.0 );
                     oSRS.SetAuthority( "SPHEROID", "EPSG", piwEllips->nEPSGCode );
-										
+
                     break;
                 }
                 piwEllips++;
             } //end of searching for matching ellipsoid
-        } 
-				
+        }
+
 /* -------------------------------------------------------------------- */
 /*      If no matching for ellipsoid definition, fetch info about an    */
 /*			user defined ellipsoid. If cannot find, default to WGS 84       */
 /* -------------------------------------------------------------------- */
-        if ( !piwEllips->pszIlwisEllips )      
+        if ( !piwEllips->pszIlwisEllips )
         {
 
-            if( EQUALN( pszEllips.c_str(), "User Defined", 12 ) )
+            if( STARTS_WITH_CI(pszEllips.c_str(), "User Defined") )
             {
-                
                 oSRS.SetGeogCS( "Unknown datum based upon the custom ellipsoid",
                                 "Not specified (based on custom ellipsoid)",
                                 "Custom ellipsoid",
@@ -725,7 +715,7 @@ CPLErr ILWISDataset::ReadProjection( string csyFileName )
         }
 
     } // end of if ( !IsLocal() )
-		
+
 /* -------------------------------------------------------------------- */
 /*      Units translation                                          */
 /* -------------------------------------------------------------------- */
@@ -736,30 +726,29 @@ CPLErr ILWISDataset::ReadProjection( string csyFileName )
     oSRS.FixupOrdering();
     CPLFree(pszProjection);
     oSRS.exportToWkt( &pszProjection );
-    
 
     return CE_None;
 }
 
-void WriteFalseEastNorth(string csFileName, OGRSpatialReference oSRS)
+static void WriteFalseEastNorth(string csFileName, OGRSpatialReference oSRS)
 {
-			WriteElement("Projection", ILW_False_Easting, csFileName, 
-										oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0));
-			WriteElement("Projection", ILW_False_Northing, csFileName, 
-										oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0));
+    WriteElement("Projection", ILW_False_Easting, csFileName,
+                 oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0));
+    WriteElement("Projection", ILW_False_Northing, csFileName,
+                 oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0));
 }
 
-void WriteProjectionName(string csFileName, string stProjection)
+static void WriteProjectionName(string csFileName, string stProjection)
 {
     WriteElement("CoordSystem", "Type", csFileName, "Projection");
     WriteElement("CoordSystem", "Projection", csFileName, stProjection);
 }
 
-void WriteUTM(string csFileName, OGRSpatialReference oSRS)
+static void WriteUTM(string csFileName, OGRSpatialReference oSRS)
 {
-    int	bNorth, nZone;
+    int	bNorth;
 
-    nZone = oSRS.GetUTMZone( &bNorth );
+    int nZone = oSRS.GetUTMZone( &bNorth );
     WriteElement("CoordSystem", "Type", csFileName, "Projection");
     WriteElement("CoordSystem", "Projection", csFileName, "UTM");
     if (bNorth)
@@ -769,222 +758,224 @@ void WriteUTM(string csFileName, OGRSpatialReference oSRS)
     WriteElement("Projection", "Zone", csFileName, nZone);
 }
 
-void WriteAlbersConicEqualArea(string csFileName, OGRSpatialReference oSRS)
+static void WriteAlbersConicEqualArea(string csFileName, OGRSpatialReference oSRS)
 {
     WriteProjectionName(csFileName, "Albers EqualArea Conic");
     WriteFalseEastNorth(csFileName, oSRS);
-    WriteElement("Projection", ILW_Central_Meridian, csFileName, 
+    WriteElement("Projection", ILW_Central_Meridian, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
-    WriteElement("Projection", ILW_Central_Parallel, csFileName, 
+    WriteElement("Projection", ILW_Central_Parallel, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
-    WriteElement("Projection", ILW_Standard_Parallel_1, csFileName, 
+    WriteElement("Projection", ILW_Standard_Parallel_1, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0));
-    WriteElement("Projection", ILW_Standard_Parallel_2, csFileName, 
+    WriteElement("Projection", ILW_Standard_Parallel_2, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0));
 }
-void WriteAzimuthalEquidistant(string csFileName, OGRSpatialReference oSRS)
+
+static void WriteAzimuthalEquidistant(string csFileName, OGRSpatialReference oSRS)
 {
     WriteProjectionName(csFileName, "Azimuthal Equidistant");
     WriteFalseEastNorth(csFileName, oSRS);
-    WriteElement("Projection", ILW_Central_Meridian, csFileName, 
+    WriteElement("Projection", ILW_Central_Meridian, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
-    WriteElement("Projection", ILW_Central_Parallel, csFileName, 
+    WriteElement("Projection", ILW_Central_Parallel, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
-    WriteElement("Projection", ILW_Scale_Factor, csFileName, "1.0000000000"); 
+    WriteElement("Projection", ILW_Scale_Factor, csFileName, "1.0000000000");
 }
-void WriteCylindricalEqualArea(string csFileName, OGRSpatialReference oSRS)
+
+static void WriteCylindricalEqualArea(string csFileName, OGRSpatialReference oSRS)
 {
     WriteProjectionName(csFileName, "Central Cylindrical");
     WriteFalseEastNorth(csFileName, oSRS);
-    WriteElement("Projection", ILW_Central_Meridian, csFileName, 
+    WriteElement("Projection", ILW_Central_Meridian, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
 }
 
-void WriteCassiniSoldner(string csFileName, OGRSpatialReference oSRS)
+static void WriteCassiniSoldner(string csFileName, OGRSpatialReference oSRS)
 {
     WriteProjectionName(csFileName, "Cassini");
     WriteFalseEastNorth(csFileName, oSRS);
-    WriteElement("Projection", ILW_Central_Meridian, csFileName, 
+    WriteElement("Projection", ILW_Central_Meridian, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
-    WriteElement("Projection", ILW_Latitude_True_Scale, csFileName, 
+    WriteElement("Projection", ILW_Latitude_True_Scale, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
-    WriteElement("Projection", ILW_Scale_Factor, csFileName, "1.0000000000"); 
+    WriteElement("Projection", ILW_Scale_Factor, csFileName, "1.0000000000");
 }
 
-void WriteStereographic(string csFileName, OGRSpatialReference oSRS)
+static void WriteStereographic(string csFileName, OGRSpatialReference oSRS)
 {
     WriteProjectionName(csFileName, "Stereographic");
     WriteFalseEastNorth(csFileName, oSRS);
-    WriteElement("Projection", ILW_Central_Meridian, csFileName, 
+    WriteElement("Projection", ILW_Central_Meridian, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
-    WriteElement("Projection", ILW_Central_Parallel, csFileName, 
+    WriteElement("Projection", ILW_Central_Parallel, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
-    WriteElement("Projection", ILW_Scale_Factor, csFileName, 
-                 oSRS.GetNormProjParm(SRS_PP_SCALE_FACTOR, 0.0)); 
+    WriteElement("Projection", ILW_Scale_Factor, csFileName,
+                 oSRS.GetNormProjParm(SRS_PP_SCALE_FACTOR, 0.0));
 }
 
-void WriteEquidistantConic(string csFileName, OGRSpatialReference oSRS)
+static void WriteEquidistantConic(string csFileName, OGRSpatialReference oSRS)
 {
     WriteProjectionName(csFileName, "Equidistant Conic");
     WriteFalseEastNorth(csFileName, oSRS);
-    WriteElement("Projection", ILW_Central_Meridian, csFileName, 
+    WriteElement("Projection", ILW_Central_Meridian, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
-    WriteElement("Projection", ILW_Central_Parallel, csFileName, 
+    WriteElement("Projection", ILW_Central_Parallel, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
-    WriteElement("Projection", ILW_Standard_Parallel_1, csFileName, 
-                 oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0)); 
-    WriteElement("Projection", ILW_Standard_Parallel_2, csFileName, 
+    WriteElement("Projection", ILW_Standard_Parallel_1, csFileName,
+                 oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0));
+    WriteElement("Projection", ILW_Standard_Parallel_2, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0));
 }
 
-void WriteTransverseMercator(string csFileName, OGRSpatialReference oSRS)
+static void WriteTransverseMercator(string csFileName, OGRSpatialReference oSRS)
 {
     WriteProjectionName(csFileName, "Transverse Mercator");
     WriteFalseEastNorth(csFileName, oSRS);
-    WriteElement("Projection", ILW_Central_Meridian, csFileName, 
+    WriteElement("Projection", ILW_Central_Meridian, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
-    WriteElement("Projection", ILW_Central_Parallel, csFileName, 
+    WriteElement("Projection", ILW_Central_Parallel, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
-    WriteElement("Projection", ILW_Scale_Factor, csFileName, 
-                 oSRS.GetNormProjParm(SRS_PP_SCALE_FACTOR, 0.0)); 
+    WriteElement("Projection", ILW_Scale_Factor, csFileName,
+                 oSRS.GetNormProjParm(SRS_PP_SCALE_FACTOR, 0.0));
 }
 
-void WriteGnomonic(string csFileName, OGRSpatialReference oSRS)
+static void WriteGnomonic(string csFileName, OGRSpatialReference oSRS)
 {
     WriteProjectionName(csFileName, "Gnomonic");
     WriteFalseEastNorth(csFileName, oSRS);
-    WriteElement("Projection", ILW_Central_Meridian, csFileName, 
+    WriteElement("Projection", ILW_Central_Meridian, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
-    WriteElement("Projection", ILW_Central_Parallel, csFileName, 
+    WriteElement("Projection", ILW_Central_Parallel, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
 }
 
-void WriteLambertConformalConic(string csFileName, OGRSpatialReference oSRS)
+static void WriteLambertConformalConic(string csFileName, OGRSpatialReference oSRS)
 {
     WriteProjectionName(csFileName, "Lambert Conformal Conic");
     WriteFalseEastNorth(csFileName, oSRS);
-    WriteElement("Projection", ILW_Central_Meridian, csFileName, 
+    WriteElement("Projection", ILW_Central_Meridian, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
-    WriteElement("Projection", ILW_Central_Parallel, csFileName, 
+    WriteElement("Projection", ILW_Central_Parallel, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
-    WriteElement("Projection", ILW_Scale_Factor, csFileName, "1.0000000000"); 
+    WriteElement("Projection", ILW_Scale_Factor, csFileName, "1.0000000000");
 }
 
-void WriteLambertConformalConic2SP(string csFileName, OGRSpatialReference oSRS)
+static void WriteLambertConformalConic2SP(string csFileName, OGRSpatialReference oSRS)
 {
     WriteProjectionName(csFileName, "Lambert Conformal Conic");
     WriteFalseEastNorth(csFileName, oSRS);
-    WriteElement("Projection", ILW_Central_Meridian, csFileName, 
+    WriteElement("Projection", ILW_Central_Meridian, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
-    WriteElement("Projection", ILW_Central_Parallel, csFileName, 
+    WriteElement("Projection", ILW_Central_Parallel, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
-    WriteElement("Projection", ILW_Scale_Factor, csFileName, "1.0000000000"); 
-    WriteElement("Projection", ILW_Standard_Parallel_1, csFileName, 
-                 oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0)); 
-    WriteElement("Projection", ILW_Standard_Parallel_2, csFileName, 
+    WriteElement("Projection", ILW_Scale_Factor, csFileName, "1.0000000000");
+    WriteElement("Projection", ILW_Standard_Parallel_1, csFileName,
+                 oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0));
+    WriteElement("Projection", ILW_Standard_Parallel_2, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0));
 }
 
-void WriteLambertAzimuthalEqualArea(string csFileName, OGRSpatialReference oSRS)
+static void WriteLambertAzimuthalEqualArea(string csFileName, OGRSpatialReference oSRS)
 {
     WriteProjectionName(csFileName, "Lambert Azimuthal EqualArea");
     WriteFalseEastNorth(csFileName, oSRS);
-    WriteElement("Projection", ILW_Central_Meridian, csFileName, 
+    WriteElement("Projection", ILW_Central_Meridian, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
-    WriteElement("Projection", ILW_Central_Parallel, csFileName, 
+    WriteElement("Projection", ILW_Central_Parallel, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
 }
 
-void WriteMercator_1SP(string csFileName, OGRSpatialReference oSRS)
+static void WriteMercator_1SP(string csFileName, OGRSpatialReference oSRS)
 {
     WriteProjectionName(csFileName, "Mercator");
     WriteFalseEastNorth(csFileName, oSRS);
-    WriteElement("Projection", ILW_Central_Meridian, csFileName, 
+    WriteElement("Projection", ILW_Central_Meridian, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
-    WriteElement("Projection", ILW_Latitude_True_Scale, csFileName, 
+    WriteElement("Projection", ILW_Latitude_True_Scale, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
 }
 
-void WriteMillerCylindrical(string csFileName, OGRSpatialReference oSRS)
+static void WriteMillerCylindrical(string csFileName, OGRSpatialReference oSRS)
 {
     WriteProjectionName(csFileName, "Miller");
     WriteFalseEastNorth(csFileName, oSRS);
-    WriteElement("Projection", ILW_Central_Meridian, csFileName, 
+    WriteElement("Projection", ILW_Central_Meridian, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
 }
 
-void WriteMolleweide(string csFileName, OGRSpatialReference oSRS)
+static void WriteMolleweide(string csFileName, OGRSpatialReference oSRS)
 {
     WriteProjectionName(csFileName, "Mollweide");
     WriteFalseEastNorth(csFileName, oSRS);
-    WriteElement("Projection", ILW_Central_Meridian, csFileName, 
+    WriteElement("Projection", ILW_Central_Meridian, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
 }
 
-void WriteOrthographic(string csFileName, OGRSpatialReference oSRS)
+static void WriteOrthographic(string csFileName, OGRSpatialReference oSRS)
 {
     WriteProjectionName(csFileName, "Orthographic");
     WriteFalseEastNorth(csFileName, oSRS);
-    WriteElement("Projection", ILW_Central_Meridian, csFileName, 
+    WriteElement("Projection", ILW_Central_Meridian, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
-    WriteElement("Projection", ILW_Central_Parallel, csFileName, 
+    WriteElement("Projection", ILW_Central_Parallel, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
 }
 
-void WritePlateRectangle(string csFileName, OGRSpatialReference oSRS)
+static void WritePlateRectangle(string csFileName, OGRSpatialReference oSRS)
 {
     WriteProjectionName(csFileName, "Plate Rectangle");
     WriteFalseEastNorth(csFileName, oSRS);
-    WriteElement("Projection", ILW_Central_Meridian, csFileName, 
+    WriteElement("Projection", ILW_Central_Meridian, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
-    WriteElement("Projection", ILW_Central_Parallel, csFileName, 
+    WriteElement("Projection", ILW_Central_Parallel, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
-    WriteElement("Projection", ILW_Latitude_True_Scale, csFileName, "0.0000000000"); 
+    WriteElement("Projection", ILW_Latitude_True_Scale, csFileName, "0.0000000000");
 }
 
-void WritePolyConic(string csFileName, OGRSpatialReference oSRS)
+static void WritePolyConic(string csFileName, OGRSpatialReference oSRS)
 {
     WriteProjectionName(csFileName, "PolyConic");
     WriteFalseEastNorth(csFileName, oSRS);
-    WriteElement("Projection", ILW_Central_Meridian, csFileName, 
+    WriteElement("Projection", ILW_Central_Meridian, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
-    WriteElement("Projection", ILW_Central_Parallel, csFileName, 
+    WriteElement("Projection", ILW_Central_Parallel, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
-    WriteElement("Projection", ILW_Scale_Factor, csFileName, "1.0000000000"); 
+    WriteElement("Projection", ILW_Scale_Factor, csFileName, "1.0000000000");
 }
 
-void WriteRobinson(string csFileName, OGRSpatialReference oSRS)
+static void WriteRobinson(string csFileName, OGRSpatialReference oSRS)
 {
     WriteProjectionName(csFileName, "Robinson");
     WriteFalseEastNorth(csFileName, oSRS);
-    WriteElement("Projection", ILW_Central_Meridian, csFileName, 
+    WriteElement("Projection", ILW_Central_Meridian, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
 }
 
-void WriteSinusoidal(string csFileName, OGRSpatialReference oSRS)
+static void WriteSinusoidal(string csFileName, OGRSpatialReference oSRS)
 {
     WriteProjectionName(csFileName, "Sinusoidal");
     WriteFalseEastNorth(csFileName, oSRS);
-    WriteElement("Projection", ILW_Central_Meridian, csFileName, 
+    WriteElement("Projection", ILW_Central_Meridian, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
 }
 
-void WriteVanderGrinten(string csFileName, OGRSpatialReference oSRS)
+static void WriteVanderGrinten(string csFileName, OGRSpatialReference oSRS)
 {
     WriteProjectionName(csFileName, "VanderGrinten");
     WriteFalseEastNorth(csFileName, oSRS);
-    WriteElement("Projection", ILW_Central_Meridian, csFileName, 
+    WriteElement("Projection", ILW_Central_Meridian, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
 }
 
-void WriteGeoStatSat(string csFileName, OGRSpatialReference oSRS)
+static void WriteGeoStatSat(string csFileName, OGRSpatialReference oSRS)
 {
     WriteProjectionName(csFileName, "GeoStationary Satellite");
     WriteFalseEastNorth(csFileName, oSRS);
-    WriteElement("Projection", ILW_Central_Meridian, csFileName, 
+    WriteElement("Projection", ILW_Central_Meridian, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
-    WriteElement("Projection", ILW_Scale_Factor, csFileName, "1.0000000000"); 
-    WriteElement("Projection", ILW_Height_Persp_Center, csFileName, 
+    WriteElement("Projection", ILW_Scale_Factor, csFileName, "1.0000000000");
+    WriteElement("Projection", ILW_Height_Persp_Center, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_SATELLITE_HEIGHT, 35785831.0));
 }
 
@@ -995,32 +986,32 @@ void WriteGeoStatSat(string csFileName, OGRSpatialReference oSRS)
  * Export coordinate system in ILWIS projection definition.
  *
  * Converts the loaded coordinate reference system into ILWIS projection
- * definition to the extent possible.	
- */	
-CPLErr ILWISDataset::WriteProjection() 
+ * definition to the extent possible.
+ */
+CPLErr ILWISDataset::WriteProjection()
 
 {
     OGRSpatialReference oSRS;
     OGRSpatialReference *poGeogSRS = NULL;
-    int                 bHaveSRS;
     char		*pszP = pszProjection;
-		
+
     string csFileName = CPLResetExtension(osFileName, "csy" );
     string pszBaseName = string(CPLGetBasename( osFileName ));
     string pszPath = string(CPLGetPath( osFileName ));
-    bool fProjection = ((strlen(pszProjection)>0) && (pszProjection != NULL));
-    if( fProjection && (oSRS.importFromWkt( &pszP ) == OGRERR_NONE) )
+    bool bProjection = ((pszProjection != NULL) && (strlen(pszProjection)>0));
+    bool bHaveSRS;
+    if( bProjection && (oSRS.importFromWkt( &pszP ) == OGRERR_NONE) )
     {
-        bHaveSRS = TRUE;
+        bHaveSRS = true;
     }
     else
-        bHaveSRS = FALSE;
-		
+        bHaveSRS = false;
+
     const IlwisDatums   *piwDatum = iwDatums;
     string pszEllips;
     string pszDatum;
     string pszProj;
-		
+
 /* -------------------------------------------------------------------- */
 /*      Collect datum/ellips information.                                      */
 /* -------------------------------------------------------------------- */
@@ -1047,13 +1038,12 @@ CPLErr ILWISDataset::WriteProjection()
                 break;
             }
             piwDatum++;
-        } //end of searchong for matching datum
+        } // End of searching for matching datum.
         WriteElement("CoordSystem", "Width", csFileName, 28);
-        double a, /* b, */f;
         pszEllips = poGeogSRS->GetAttrValue( "GEOGCS|DATUM|SPHEROID" );
-        a = poGeogSRS->GetSemiMajor();
+        double a = poGeogSRS->GetSemiMajor();
         /* b = */ poGeogSRS->GetSemiMinor();
-        f = poGeogSRS->GetInvFlattening();
+        double f = poGeogSRS->GetInvFlattening();
         WriteElement("CoordSystem", "Ellipsoid", csFileName, "User Defined");
         WriteElement("Ellipsoid", "a", csFileName, a);
         WriteElement("Ellipsoid", "1/f", csFileName, f);
@@ -1106,7 +1096,7 @@ CPLErr ILWISDataset::WriteProjection()
     }
     else if( EQUAL(pszProjName,SRS_PT_STEREOGRAPHIC) )
     {
-        WriteStereographic(csFileName, oSRS);		
+        WriteStereographic(csFileName, oSRS);
     }
     else if( EQUAL(pszProjName,SRS_PT_EQUIDISTANT_CONIC) )
     {
@@ -1170,16 +1160,15 @@ CPLErr ILWISDataset::WriteProjection()
     }
     else if( EQUAL(pszProjName,SRS_PT_VANDERGRINTEN) )
     {
-        WriteVanderGrinten(csFileName, oSRS);  
+        WriteVanderGrinten(csFileName, oSRS);
     }
     else if( EQUAL(pszProjName,SRS_PT_GEOSTATIONARY_SATELLITE) )
     {
-        WriteGeoStatSat(csFileName, oSRS);  
+        WriteGeoStatSat(csFileName, oSRS);
     }
     else
     {
         // Projection unknown by ILWIS
-				
     }
 
 /* -------------------------------------------------------------------- */
diff --git a/frmts/ilwis/ilwisdataset.cpp b/frmts/ilwis/ilwisdataset.cpp
index b0ba8aa..60ae880 100644
--- a/frmts/ilwis/ilwisdataset.cpp
+++ b/frmts/ilwis/ilwisdataset.cpp
@@ -29,12 +29,20 @@
 
 
 #include "ilwisdataset.h"
-#include <float.h>
-#include <limits.h>
+#include <cfloat>
+#include <climits>
 
 #include <string>
 
-using namespace std;
+#include "gdal_frmts.h"
+
+using std::string;
+
+/* used by ilwsicoordinatesystem.cpp */
+string ReadElement(string section, string entry, string filename);
+bool WriteElement(string sSection, string sEntry, string fn, string sValue);
+bool WriteElement(string sSection, string sEntry, string fn, int nValue);
+bool WriteElement(string sSection, string sEntry, string fn, double dValue);
 
 // IniFile.cpp: implementation of the IniFile class.
 //
@@ -49,11 +57,11 @@ bool CompareAsNum::operator() (const string& s1, const string& s2) const
 static string TrimSpaces(const string& input)
 {
     // find first non space
-    if ( input.empty()) 
+    if ( input.empty() )
         return string();
 
-    size_t iFirstNonSpace = input.find_first_not_of(' ');
-    size_t iFindLastSpace = input.find_last_not_of(' ');
+    const size_t iFirstNonSpace = input.find_first_not_of(' ');
+    const size_t iFindLastSpace = input.find_last_not_of(' ');
     if (iFirstNonSpace == string::npos || iFindLastSpace == string::npos)
         return string();
 
@@ -158,13 +166,13 @@ void IniFile::RemoveSection(const string& section)
 
 void IniFile::Load()
 {
-    enum ParseState { FindSection, FindKey, ReadFindKey, StoreKey, None } state;
     VSILFILE *filIni = VSIFOpenL(filename.c_str(), "r");
     if (filIni == NULL)
         return;
 
     string section, key, value;
-    state = FindSection;
+    enum ParseState { FindSection, FindKey, ReadFindKey, StoreKey, None } state
+        = FindSection;
     string s;
     while (!VSIFEofL(filIni) || !s.empty() )
     {
@@ -206,7 +214,7 @@ void IniFile::Load()
             SetKeyValue(section, key, value);
             state = FindSection;
             break;
-            
+
           case None:
             // Do we need to do anything?  Perhaps this never occurs.
             break;
@@ -235,7 +243,7 @@ void IniFile::Store()
         for (iterEntry = (*entries).begin(); iterEntry != (*entries).end(); ++iterEntry)
         {
             string key = (*iterEntry).first;
-            osLine.Printf( "%s=%s\r\n", 
+            osLine.Printf( "%s=%s\r\n",
                            TrimSpaces(key).c_str(), (*iterEntry).second.c_str());
             VSIFWriteL( osLine.c_str(), 1, strlen(osLine), filIni );
         }
@@ -252,8 +260,8 @@ void IniFile::Store()
 static long longConv(double x) {
     if ((x == rUNDEF) || (x > LONG_MAX) || (x < LONG_MIN))
         return iUNDEF;
-    else
-        return (long)floor(x + 0.5);
+
+    return (long)floor(x + 0.5);
 }
 
 string ReadElement(string section, string entry, string filename)
@@ -289,9 +297,9 @@ bool WriteElement(string sSection, string sEntry,
         return false;
 
     char strdouble[45];
-    sprintf(strdouble, "%d", nValue);
+    snprintf(strdouble, sizeof(strdouble), "%d", nValue);
     string sValue = string(strdouble);
-    return WriteElement(sSection, sEntry, fn, sValue) != 0;
+    return WriteElement(sSection, sEntry, fn, sValue);
 }
 
 bool WriteElement(string sSection, string sEntry,
@@ -301,9 +309,9 @@ bool WriteElement(string sSection, string sEntry,
         return false;
 
     char strdouble[45];
-    CPLsprintf(strdouble, "%.6f", dValue);
+    CPLsnprintf(strdouble, sizeof(strdouble), "%.6f", dValue);
     string sValue = string(strdouble);
-    return WriteElement(sSection, sEntry, fn, sValue) != 0;
+    return WriteElement(sSection, sEntry, fn, sValue);
 }
 
 static CPLErr GetRowCol(string str,int &Row, int &Col)
@@ -314,9 +322,9 @@ static CPLErr GetRowCol(string str,int &Row, int &Col)
     {
         Row = atoi(str.substr(0, iPos).c_str());
     }
-    else 
+    else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Read of RowCol failed.");
         return CE_Failure;
     }
@@ -334,18 +342,18 @@ static GDALDataType ILWIS2GDALType(ilwisStoreType stStoreType)
   GDALDataType eDataType = GDT_Unknown;
 
   switch (stStoreType){
-	  case stByte: {
-	    eDataType = GDT_Byte;
+    case stByte: {
+      eDataType = GDT_Byte;
       break;
-		} 
+    }
     case stInt:{
       eDataType = GDT_Int16;
       break;
-		}
+    }
     case stLong:{
       eDataType = GDT_Int32;
       break;
-		}
+    }
     case stFloat:{
       eDataType = GDT_Float32;
       break;
@@ -365,8 +373,7 @@ static GDALDataType ILWIS2GDALType(ilwisStoreType stStoreType)
 //Determine store type of ILWIS raster
 static string GDALType2ILWIS(GDALDataType type)
 {
-    string sStoreType;
-    sStoreType = "";
+    string sStoreType = "";
     switch( type )
     {
       case GDT_Byte:{
@@ -396,7 +403,7 @@ static string GDALType2ILWIS(GDALDataType type)
                     "Data type %s not supported by ILWIS format.\n",
                     GDALGetDataTypeName( type ) );
           break;
-      }	
+      }
     }
     return sStoreType;
 }
@@ -404,7 +411,7 @@ static string GDALType2ILWIS(GDALDataType type)
 static CPLErr GetStoreType(string pszFileName, ilwisStoreType &stStoreType)
 {
     string st = ReadElement("MapStore", "Type", pszFileName.c_str());
-		
+
     if( EQUAL(st.c_str(),"byte"))
     {
         stStoreType = stByte;
@@ -425,9 +432,9 @@ static CPLErr GetStoreType(string pszFileName, ilwisStoreType &stStoreType)
     {
         stStoreType = stReal;
     }
-    else 
+    else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unsupported ILWIS store type.");
         return CE_Failure;
     }
@@ -435,13 +442,12 @@ static CPLErr GetStoreType(string pszFileName, ilwisStoreType &stStoreType)
 }
 
 
-ILWISDataset::ILWISDataset()
-
+ILWISDataset::ILWISDataset() :
+    bGeoDirty(FALSE),
+    bNewDataset(FALSE)
 {
-		bGeoDirty = FALSE;
-		bNewDataset = FALSE;
     pszProjection = CPLStrdup("");
-		adfGeoTransform[0] = 0.0;
+    adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[3] = 0.0;
@@ -479,7 +485,7 @@ void ILWISDataset::CollectTransformCoef(string &pszRefName)
     else
         georef = ReadElement("MapList", "GeoRef", osFileName);
 
-    //Capture the geotransform, only if the georef is not 'none', 
+    //Capture the geotransform, only if the georef is not 'none',
     //otherwise, the default transform should be returned.
     if( (georef.length() != 0) && !EQUAL(georef.c_str(),"none"))
     {
@@ -489,26 +495,26 @@ void ILWISDataset::CollectTransformCoef(string &pszRefName)
         pszRefName = string(CPLFormFilename(pszPath.c_str(),
                                             pszBaseName.c_str(),"grf" ));
 
-        //Check the geo-reference type,support for the GeoRefCorners only 
+        //Check the geo-reference type,support for the GeoRefCorners only
         string georeftype = ReadElement("GeoRef", "Type", pszRefName);
         if (EQUAL(georeftype.c_str(),"GeoRefCorners"))
         {
-            //Center or top-left corner of the pixel approach? 
+            //Center or top-left corner of the pixel approach?
             string IsCorner = ReadElement("GeoRefCorners", "CornersOfCorners", pszRefName);
 
-            //Collect the extent of the coordinates 
+            //Collect the extent of the coordinates
             string sMinX = ReadElement("GeoRefCorners", "MinX", pszRefName);
             string sMinY = ReadElement("GeoRefCorners", "MinY", pszRefName);
             string sMaxX = ReadElement("GeoRefCorners", "MaxX", pszRefName);
             string sMaxY = ReadElement("GeoRefCorners", "MaxY", pszRefName);
-				
+
             //Calculate pixel size in X and Y direction from the extent
             double deltaX = CPLAtof(sMaxX.c_str()) - CPLAtof(sMinX.c_str());
             double deltaY = CPLAtof(sMaxY.c_str()) - CPLAtof(sMinY.c_str());
 
             double PixelSizeX = deltaX / (double)nRasterXSize;
             double PixelSizeY = deltaY / (double)nRasterYSize;
-				
+
             if (EQUAL(IsCorner.c_str(),"Yes"))
             {
                 adfGeoTransform[0] = CPLAtof(sMinX.c_str());
@@ -538,8 +544,8 @@ void ILWISDataset::CollectTransformCoef(string &pszRefName)
 
 CPLErr ILWISDataset::WriteGeoReference()
 {
-    //check wheather we should write out a georeference file. 
-    //dataset must be north up 
+    // Check whether we should write out a georeference file.
+    // Dataset must be north up.
     if( adfGeoTransform[0] != 0.0 || adfGeoTransform[1] != 1.0
         || adfGeoTransform[2] != 0.0 || adfGeoTransform[3] != 0.0
         || adfGeoTransform[4] != 0.0 || fabs(adfGeoTransform[5]) != 1.0 )
@@ -549,11 +555,11 @@ CPLErr ILWISDataset::WriteGeoReference()
         {
             int   nXSize = GetRasterXSize();
             int   nYSize = GetRasterYSize();
-            double dLLLat = (adfGeoTransform[3] 
+            double dLLLat = (adfGeoTransform[3]
                       + nYSize * adfGeoTransform[5] );
             double dLLLong = (adfGeoTransform[0] );
             double dURLat  = (adfGeoTransform[3] );
-            double dURLong = (adfGeoTransform[0] 
+            double dURLong = (adfGeoTransform[0]
                        + nXSize * adfGeoTransform[1] );
 
             string grFileName = CPLResetExtension(osFileName, "grf" );
@@ -568,10 +574,10 @@ CPLErr ILWISDataset::WriteGeoReference()
             WriteElement("GeoRefCorners", "MaxY", grFileName, dURLat);
 
             //Re-write the GeoRef property to raster ODF
-            //Form band file name  
+            //Form band file name
             string sBaseName = string(CPLGetBasename(osFileName) );
             string sPath = string(CPLGetPath(osFileName));
-            if (nBands == 1) 
+            if (nBands == 1)
             {
                 WriteElement("Map", "GeoRef", osFileName, sBaseName + ".grf");
             }
@@ -581,9 +587,9 @@ CPLErr ILWISDataset::WriteGeoReference()
                 {
                     if (iBand == 0)
                       WriteElement("MapList", "GeoRef", osFileName, sBaseName + ".grf");
-                    char pszName[100];
-                    sprintf(pszName, "%s_band_%d", sBaseName.c_str(),iBand + 1 );
-                    string pszODFName = string(CPLFormFilename(sPath.c_str(),pszName,"mpr"));
+                    char szName[100];
+                    snprintf(szName, sizeof(szName), "%s_band_%d", sBaseName.c_str(),iBand + 1 );
+                    string pszODFName = string(CPLFormFilename(sPath.c_str(),szName,"mpr"));
                     WriteElement("Map", "GeoRef", pszODFName, sBaseName + ".grf");
                 }
             }
@@ -623,7 +629,7 @@ CPLErr ILWISDataset::SetProjection( const char * pszNewProjection )
 CPLErr ILWISDataset::GetGeoTransform( double * padfTransform )
 
 {
-    memcpy( padfTransform,  adfGeoTransform, sizeof(double) * 6 ); 
+    memcpy( padfTransform,  adfGeoTransform, sizeof(double) * 6 );
     return( CE_None );
 }
 
@@ -642,11 +648,13 @@ CPLErr ILWISDataset::SetGeoTransform( double * padfTransform )
     return CE_None;
 }
 
-bool CheckASCII(unsigned char * buf, int size)
+static bool CheckASCII(unsigned char * buf, int size)
 {
 	for (int i = 0; i < size; ++i)
-		if (!isascii(buf[i]))
-			return false;
+        {
+            if (!isascii(buf[i]))
+                return false;
+        }
 
 	return true;
 }
@@ -673,14 +681,14 @@ GDALDataset *ILWISDataset::Open( GDALOpenInfo * poOpenInfo )
     string ilwistype = ReadElement("Ilwis", "Type", poOpenInfo->pszFilename);
     if( ilwistype.length() == 0)
         return NULL;
-		
+
     string sFileType;	//map or map list
     int    iBandCount;
     string mapsize;
-    string maptype = ReadElement("BaseMap", "Type", poOpenInfo->pszFilename);
-    string sBaseName = string(CPLGetBasename(poOpenInfo->pszFilename) );
-    string sPath = string(CPLGetPath( poOpenInfo->pszFilename));
-							
+    const string maptype = ReadElement("BaseMap", "Type", poOpenInfo->pszFilename);
+    const string sBaseName = string(CPLGetBasename(poOpenInfo->pszFilename) );
+    const string sPath = string(CPLGetPath( poOpenInfo->pszFilename));
+
     //Verify whether it is a map list or a map
     if( EQUAL(ilwistype.c_str(),"MapList") )
     {
@@ -692,29 +700,30 @@ GDALDataset *ILWISDataset::Open( GDALOpenInfo * poOpenInfo )
         {
             //Form the band file name.
             char cBandName[45];
-            sprintf( cBandName, "Map%d", iBand);
+            snprintf( cBandName, sizeof(cBandName), "Map%d", iBand);
             string sBandName = ReadElement("MapList", string(cBandName), poOpenInfo->pszFilename);
             string pszBandBaseName = string(CPLGetBasename(sBandName.c_str()) );
             string pszBandPath = string(CPLGetPath( sBandName.c_str()));
             if ( 0 == pszBandPath.length() )
-            { 
+            {
                 sBandName = string(CPLFormFilename(sPath.c_str(),
                                                    pszBandBaseName.c_str(),"mpr" ));
             }
-            //Verify the file exetension, it must be an ILWIS raw data file
-            //with extension .mp#, otherwise, unsupported 
-            //This drive only supports a map list which stores a set of ILWIS raster maps, 
+            // Verify the file extension, it must be an ILWIS raw data file
+            // with extension .mp#, otherwise, unsupported
+            // This drive only supports a map list which stores a set
+            // of ILWIS raster maps,
             string sMapStoreName = ReadElement("MapStore", "Data", sBandName);
-            string sExt = CPLGetExtension( sMapStoreName.c_str() );
-            if ( !EQUALN( sExt.c_str(), "mp#", 3 ))
+            sExt = CPLGetExtension( sMapStoreName.c_str() );
+            if ( !STARTS_WITH_CI(sExt.c_str(), "mp#"))
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
                           "Unsupported ILWIS data file. \n"
                           "can't treat as raster.\n" );
-                return FALSE;
+                return NULL;
             }
         }
-    }	
+    }
     else if(EQUAL(ilwistype.c_str(),"BaseMap") && EQUAL(maptype.c_str(),"Map"))
     {
         sFileType = "Map";
@@ -722,13 +731,13 @@ GDALDataset *ILWISDataset::Open( GDALOpenInfo * poOpenInfo )
         mapsize = ReadElement("Map", "Size", poOpenInfo->pszFilename);
         string sMapType = ReadElement("Map", "Type", poOpenInfo->pszFilename);
         ilwisStoreType stStoreType;
-        if (  
+        if (
             GetStoreType(string(poOpenInfo->pszFilename), stStoreType) != CE_None )
         {
             //CPLError( CE_Failure, CPLE_AppDefined,
             //			"Unsupported ILWIS data file. \n"
             //			"can't treat as raster.\n" );
-            return FALSE;
+            return NULL;
         }
     }
     else
@@ -736,25 +745,32 @@ GDALDataset *ILWISDataset::Open( GDALOpenInfo * poOpenInfo )
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Unsupported ILWIS data file. \n"
                   "can't treat as raster.\n" );
-        return FALSE;
-    }	
+        return NULL;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    ILWISDataset 	*poDS;
-    poDS = new ILWISDataset();
-		
+    ILWISDataset *poDS = new ILWISDataset();
+
 /* -------------------------------------------------------------------- */
 /*      Capture raster size from ILWIS file (.mpr).                     */
 /* -------------------------------------------------------------------- */
     int Row = 0, Col = 0;
     if ( GetRowCol(mapsize, Row, Col) != CE_None)
-        return FALSE;
+    {
+        delete poDS;
+        return NULL;
+    }
+    if( !GDALCheckDatasetDimensions(Col, Row) )
+    {
+        delete poDS;
+        return NULL;
+    }
     poDS->nRasterXSize = Col;
     poDS->nRasterYSize = Row;
     poDS->osFileName = poOpenInfo->pszFilename;
-    poDS->pszFileType = sFileType;  
+    poDS->pszFileType = sFileType;
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
@@ -764,7 +780,7 @@ GDALDataset *ILWISDataset::Open( GDALOpenInfo * poOpenInfo )
     {
         poDS->SetBand( iBand+1, new ILWISRasterBand( poDS, iBand+1 ) );
     }
-		
+
 /* -------------------------------------------------------------------- */
 /*      Collect the geotransform coefficients                           */
 /* -------------------------------------------------------------------- */
@@ -776,7 +792,7 @@ GDALDataset *ILWISDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( (pszGeoRef.length() != 0) && !EQUAL(pszGeoRef.c_str(),"none"))
     {
-		
+
         //	Fetch coordinate system
         string csy = ReadElement("GeoRef", "CoordSystem", pszGeoRef);
         string pszProj;
@@ -785,8 +801,8 @@ GDALDataset *ILWISDataset::Open( GDALOpenInfo * poOpenInfo )
         {
 
             //Form the coordinate system file name
-            if( !(EQUALN( csy.c_str(), "latlon.csy", 10 )) && 
-                !(EQUALN( csy.c_str(), "LatlonWGS84.csy", 15 )))            
+            if( !(STARTS_WITH_CI(csy.c_str(), "latlon.csy")) &&
+                !(STARTS_WITH_CI(csy.c_str(), "LatlonWGS84.csy")))
             {
                 string pszBaseName = string(CPLGetBasename(csy.c_str()) );
                 string pszPath = string(CPLGetPath( poDS->osFileName ));
@@ -800,9 +816,9 @@ GDALDataset *ILWISDataset::Open( GDALOpenInfo * poOpenInfo )
             {
                 pszProj = "LatLon";
             }
-					
-            if( (EQUALN( pszProj.c_str(), "LatLon", 6 )) || 
-                (EQUALN( pszProj.c_str(), "Projection", 10 )))			
+
+            if( (STARTS_WITH_CI(pszProj.c_str(), "LatLon")) ||
+                (STARTS_WITH_CI(pszProj.c_str(), "Projection")))
                 poDS->ReadProjection( csy );
         }
     }
@@ -831,11 +847,11 @@ void ILWISDataset::FlushCache()
     GDALDataset::FlushCache();
 
     if( bGeoDirty == TRUE )
-		{
-				WriteGeoReference();
+    {
+        WriteGeoReference();
         WriteProjection();
-				bGeoDirty = FALSE;
-		}
+        bGeoDirty = FALSE;
+    }
 }
 
 /************************************************************************/
@@ -849,9 +865,6 @@ GDALDataset *ILWISDataset::Create(const char* pszFilename,
                                   int nBands, GDALDataType eType,
                                   CPL_UNUSED char** papszParmList)
 {
-    ILWISDataset	*poDS;
-    int 		iBand;
-
 /* -------------------------------------------------------------------- */
 /*      Verify input options.                                           */
 /* -------------------------------------------------------------------- */
@@ -878,9 +891,9 @@ GDALDataset *ILWISDataset::Create(const char* pszFilename,
     else if( EQUAL(sStoreType.c_str(),"Real") || EQUAL(sStoreType.c_str(),"float"))
         stepsize = 0;
 
-    string pszBaseName = string(CPLGetBasename( pszFilename ));
-    string pszPath = string(CPLGetPath( pszFilename ));
-		
+    const string pszBaseName = string(CPLGetBasename( pszFilename ));
+    const string pszPath = string(CPLGetPath( pszFilename ));
+
 /* -------------------------------------------------------------------- */
 /*      Write out object definition file for each band                  */
 /* -------------------------------------------------------------------- */
@@ -889,9 +902,9 @@ GDALDataset *ILWISDataset::Create(const char* pszFilename,
     string pszFileName;
 
     char strsize[45];
-    sprintf(strsize, "%d %d", nYSize, nXSize);
-    
-    //Form map/maplist name. 
+    snprintf(strsize, sizeof(strsize), "%d %d", nYSize, nXSize);
+
+    //Form map/maplist name.
     if ( nBands == 1 )
     {
         pszODFName = string(CPLFormFilename(pszPath.c_str(),pszBaseName.c_str(),"mpr"));
@@ -907,26 +920,26 @@ GDALDataset *ILWISDataset::Create(const char* pszFilename,
         WriteElement("MapList", "Maps", string(pszFileName), nBands);
     }
 
-    for( iBand = 0; iBand < nBands; iBand++ )
+    for( int iBand = 0; iBand < nBands; iBand++ )
     {
         if ( nBands > 1 )
         {
-            char pszBandName[100];
-            sprintf(pszBandName, "%s_band_%d", pszBaseName.c_str(),iBand + 1 );
-            pszODFName = string(pszBandName) + ".mpr";
-            pszDataBaseName = string(pszBandName);
-            sprintf(pszBandName, "Map%d", iBand);	
-            WriteElement("MapList", string(pszBandName), string(pszFileName), pszODFName);
+            char szBandName[100];
+            snprintf(szBandName, sizeof(szBandName), "%s_band_%d", pszBaseName.c_str(),iBand + 1 );
+            pszODFName = string(szBandName) + ".mpr";
+            pszDataBaseName = string(szBandName);
+            snprintf(szBandName, sizeof(szBandName), "Map%d", iBand);
+            WriteElement("MapList", string(szBandName), string(pszFileName), pszODFName);
             pszODFName = CPLFormFilename(pszPath.c_str(),pszDataBaseName.c_str(),"mpr");
         }
 /* -------------------------------------------------------------------- */
 /*      Write data definition per band (.mpr)                           */
 /* -------------------------------------------------------------------- */
-				
+
         WriteElement("Ilwis", "Type", pszODFName, "BaseMap");
         WriteElement("BaseMap", "Type", pszODFName, "Map");
         WriteElement("Map", "Type", pszODFName, "MapStore");
-				
+
         WriteElement("BaseMap", "Domain", pszODFName, sDomain);
         string pszDataName = pszDataBaseName + ".mp#";
         WriteElement("MapStore", "Data", pszODFName, pszDataName);
@@ -937,17 +950,15 @@ GDALDataset *ILWISDataset::Create(const char* pszFilename,
         // For now write-out a "Range" that is as broad as possible.
         // If later a better range is found (by inspecting metadata in the source dataset),
         // the "Range" will be overwritten by a better version.
-        double adfMinMax[2];
-        adfMinMax[0] = -9999999.9;
-        adfMinMax[1] = 9999999.9;
+        double adfMinMax[2] = {-9999999.9, 9999999.9};
         char strdouble[45];
-        CPLsprintf(strdouble, "%.3f:%.3f:%3f:offset=0", adfMinMax[0], adfMinMax[1],stepsize);
-        string range = string(strdouble);
+        CPLsnprintf(strdouble, sizeof(strdouble), "%.3f:%.3f:%3f:offset=0", adfMinMax[0], adfMinMax[1],stepsize);
+        string range(strdouble);
         WriteElement("BaseMap", "Range", pszODFName, range);
 
         WriteElement("Map", "GeoRef", pszODFName, "none.grf");
         WriteElement("Map", "Size", pszODFName, string(strsize));
-							
+
 /* -------------------------------------------------------------------- */
 /*      Try to create the data file.                                    */
 /* -------------------------------------------------------------------- */
@@ -963,7 +974,7 @@ GDALDataset *ILWISDataset::Create(const char* pszFilename,
         }
         VSIFCloseL( fp );
     }
-    poDS = new ILWISDataset();
+    ILWISDataset *poDS = new ILWISDataset();
     poDS->nRasterXSize = nXSize;
     poDS->nRasterYSize = nYSize;
     poDS->nBands = nBands;
@@ -981,7 +992,7 @@ GDALDataset *ILWISDataset::Create(const char* pszFilename,
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
 
-    for( iBand = 1; iBand <= poDS->nBands; iBand++ )
+    for( int iBand = 1; iBand <= poDS->nBands; iBand++ )
     {
         poDS->SetBand( iBand, new ILWISRasterBand( poDS, iBand ) );
     }
@@ -996,52 +1007,46 @@ GDALDataset *ILWISDataset::Create(const char* pszFilename,
 
 GDALDataset *
 ILWISDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
-                        int bStrict, char ** papszOptions,
-                        GDALProgressFunc pfnProgress, void * pProgressData )
+                          int /* bStrict */, char ** papszOptions,
+                          GDALProgressFunc pfnProgress, void * pProgressData )
 
 {
-    
-    ILWISDataset	*poDS;
-    GDALDataType eType = GDT_Byte;
-    int iBand;
-    (void) bStrict;
-
-		
-    int   nXSize = poSrcDS->GetRasterXSize();
-    int   nYSize = poSrcDS->GetRasterYSize();
-    int   nBands = poSrcDS->GetRasterCount();
-
     if( !pfnProgress( 0.0, NULL, pProgressData ) )
         return NULL;
 
+    const int nXSize = poSrcDS->GetRasterXSize();
+    const int nYSize = poSrcDS->GetRasterYSize();
+    const int nBands = poSrcDS->GetRasterCount();
+
 /* -------------------------------------------------------------------- */
 /*      Create the basic dataset.                                       */
 /* -------------------------------------------------------------------- */
-    for( iBand = 0; iBand < nBands; iBand++ )
+    GDALDataType eType = GDT_Byte;
+    for( int iBand = 0; iBand < nBands; iBand++ )
     {
         GDALRasterBand *poBand = poSrcDS->GetRasterBand( iBand+1 );
         eType = GDALDataTypeUnion( eType, poBand->GetRasterDataType() );
     }
 
-    poDS = (ILWISDataset *) Create( pszFilename,
-                                    poSrcDS->GetRasterXSize(),
-                                    poSrcDS->GetRasterYSize(),
-                                    nBands,
-                                    eType, papszOptions );
+    ILWISDataset *poDS = (ILWISDataset *) Create( pszFilename,
+                                                  poSrcDS->GetRasterXSize(),
+                                                  poSrcDS->GetRasterYSize(),
+                                                  nBands,
+                                                  eType, papszOptions );
 
     if( poDS == NULL )
         return NULL;
-    string pszBaseName = string(CPLGetBasename( pszFilename ));
-    string pszPath = string(CPLGetPath( pszFilename ));
-				
+    const string pszBaseName = string(CPLGetBasename( pszFilename ));
+    const string pszPath = string(CPLGetPath( pszFilename ));
+
 /* -------------------------------------------------------------------- */
 /*  Copy and geo-transform and projection information.                  */
 /* -------------------------------------------------------------------- */
     double adfGeoTransform[6];
     string georef = "none.grf";
 
-    //check wheather we should create georeference file. 
-    //source dataset must be north up 
+    // Check whether we should create georeference file.
+    // Source dataset must be north up.
     if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None
         && (adfGeoTransform[0] != 0.0 || adfGeoTransform[1] != 1.0
             || adfGeoTransform[2] != 0.0 || adfGeoTransform[3] != 0.0
@@ -1059,52 +1064,50 @@ ILWISDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Create the output raster files for each band                    */
 /* -------------------------------------------------------------------- */
-		
-    for( iBand = 0; iBand < nBands; iBand++ )
+
+    for( int iBand = 0; iBand < nBands; iBand++ )
     {
-        VSILFILE *fpData;
-        GByte *pData;
-        
+        VSILFILE *fpData = NULL;
+
         GDALRasterBand *poBand = poSrcDS->GetRasterBand( iBand+1 );
         ILWISRasterBand *desBand = (ILWISRasterBand *) poDS->GetRasterBand( iBand+1 );
-        
+
 /* -------------------------------------------------------------------- */
 /*      Translate the data type.                                        */
 /* -------------------------------------------------------------------- */
         int nLineSize =  nXSize * GDALGetDataTypeSize(eType) / 8;
-        pData = (GByte *) CPLMalloc( nLineSize );
 
         //Determine the nodata value
         int bHasNoDataValue;
-        double dNoDataValue = poBand->GetNoDataValue(&bHasNoDataValue); 
-        				
+        double dNoDataValue = poBand->GetNoDataValue(&bHasNoDataValue);
+
         //Determine store type of ILWIS raster
-        string sStoreType = GDALType2ILWIS( eType );
+        const string sStoreType = GDALType2ILWIS( eType );
         double stepsize = 1;
         if( EQUAL(sStoreType.c_str(),""))
             return NULL;
         else if( EQUAL(sStoreType.c_str(),"Real") || EQUAL(sStoreType.c_str(),"float"))
             stepsize = 0;
 
-        //Form the image file name, create the object definition file. 
+        //Form the image file name, create the object definition file.
         string pszODFName;
         string pszDataBaseName;
-        if (nBands == 1) 
+        if (nBands == 1)
         {
             pszODFName = string(CPLFormFilename(pszPath.c_str(),pszBaseName.c_str(),"mpr"));
             pszDataBaseName = pszBaseName;
         }
         else
         {
-            char pszName[100];
-            sprintf(pszName, "%s_band_%d", pszBaseName.c_str(),iBand + 1 );
-            pszODFName = string(CPLFormFilename(pszPath.c_str(),pszName,"mpr"));
-            pszDataBaseName = string(pszName);
+            char szName[100];
+            snprintf(szName, sizeof(szName), "%s_band_%d", pszBaseName.c_str(),iBand + 1 );
+            pszODFName = string(CPLFormFilename(pszPath.c_str(),szName,"mpr"));
+            pszDataBaseName = string(szName);
         }
 /* -------------------------------------------------------------------- */
 /*      Write data definition file for each band (.mpr)                 */
 /* -------------------------------------------------------------------- */
-				
+
         double adfMinMax[2];
         int    bGotMin, bGotMax;
 
@@ -1116,20 +1119,18 @@ ILWISDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         {
             // only write a range if we got a correct one from the source dataset (otherwise ILWIS can't show the map properly)
             char strdouble[45];
-            CPLsprintf(strdouble, "%.3f:%.3f:%3f:offset=0", adfMinMax[0], adfMinMax[1],stepsize);
+            CPLsnprintf(strdouble, sizeof(strdouble), "%.3f:%.3f:%3f:offset=0", adfMinMax[0], adfMinMax[1],stepsize);
             string range = string(strdouble);
             WriteElement("BaseMap", "Range", pszODFName, range);
         }
         WriteElement("Map", "GeoRef", pszODFName, georef);
-				
+
 /* -------------------------------------------------------------------- */
 /*      Loop over image, copy the image data.                           */
 /* -------------------------------------------------------------------- */
-        CPLErr      eErr = CE_None;
-			
-        //For file name for raw data, and create binary files. 
+        //For file name for raw data, and create binary files.
         string pszDataFileName = CPLResetExtension(pszODFName.c_str(), "mp#" );
-				
+
         fpData = desBand->fpRaw;
         if( fpData == NULL )
         {
@@ -1139,10 +1140,13 @@ ILWISDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             return NULL;
         }
 
+        GByte *pData = (GByte *) CPLMalloc( nLineSize );
+
+        CPLErr eErr = CE_None;
         for( int iLine = 0; iLine < nYSize && eErr == CE_None; iLine++ )
         {
-            eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, 
-                                     pData, nXSize, 1, eType, 
+            eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1,
+                                     pData, nXSize, 1, eType,
                                      0, 0, NULL );
 
             if( eErr == CE_None )
@@ -1159,34 +1163,34 @@ ILWISDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                             if ( ((GByte * )pData)[iCol] == dNoDataValue )
                                 (( GByte * )pData)[iCol] = 0;
                         }
-                        else if( EQUAL(sStoreType.c_str(),"Int"))	
+                        else if( EQUAL(sStoreType.c_str(),"Int"))
                         {
                             if ( ((GInt16 * )pData)[iCol] == dNoDataValue )
                                 (( GInt16 * )pData)[iCol] = shUNDEF;
                         }
-                        else if( EQUAL(sStoreType.c_str(),"Long"))	
+                        else if( EQUAL(sStoreType.c_str(),"Long"))
                         {
                             if ( ((GInt32 * )pData)[iCol] == dNoDataValue )
                                 (( GInt32 * )pData)[iCol] = iUNDEF;
                         }
-                        else if( EQUAL(sStoreType.c_str(),"float"))	
+                        else if( EQUAL(sStoreType.c_str(),"float"))
                         {
                             if ((((float * )pData)[iCol] == dNoDataValue ) || (CPLIsNan((( float * )pData)[iCol])))
                                 (( float * )pData)[iCol] = flUNDEF;
                         }
-                        else if( EQUAL(sStoreType.c_str(),"Real"))	
+                        else if( EQUAL(sStoreType.c_str(),"Real"))
                         {
                             if ((((double * )pData)[iCol] == dNoDataValue ) || (CPLIsNan((( double * )pData)[iCol])))
                                 (( double * )pData)[iCol] = rUNDEF;
                         }
                     }
                 }
-                int iSize = VSIFWriteL( pData, 1, nLineSize, desBand->fpRaw );
+                int iSize = static_cast<int>(VSIFWriteL( pData, 1, nLineSize, desBand->fpRaw ));
                 if ( iSize < 1 )
                 {
                     CPLFree( pData );
                     //CPLFree( pData32 );
-                    CPLError( CE_Failure, CPLE_FileIO, 
+                    CPLError( CE_Failure, CPLE_FileIO,
                               "Write of file failed with fwrite error.");
                     return NULL;
                 }
@@ -1221,28 +1225,31 @@ ILWISDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*                       ILWISRasterBand()                              */
 /************************************************************************/
 
-ILWISRasterBand::ILWISRasterBand( ILWISDataset *poDS, int nBand )
+ILWISRasterBand::ILWISRasterBand( ILWISDataset *poDSIn, int nBandIn )
 
 {
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
+
     string sBandName;
-    if ( EQUAL(poDS->pszFileType.c_str(),"Map"))  		
-        sBandName = string(poDS->osFileName);
+    if ( EQUAL(poDSIn->pszFileType.c_str(),"Map"))
+        sBandName = string(poDSIn->osFileName);
     else //map list
     {
         //Form the band name
         char cBandName[45];
-        sprintf( cBandName, "Map%d", nBand-1);
-        sBandName = ReadElement("MapList", string(cBandName), string(poDS->osFileName));
-        string sInputPath = string(CPLGetPath( poDS->osFileName));	
+        snprintf( cBandName, sizeof(cBandName), "Map%d", nBand-1);
+        sBandName = ReadElement("MapList", string(cBandName), string(poDSIn->osFileName));
+        string sInputPath = string(CPLGetPath( poDSIn->osFileName));
         string sBandPath = string(CPLGetPath( sBandName.c_str()));
         string sBandBaseName = string(CPLGetBasename( sBandName.c_str()));
         if ( 0==sBandPath.length() )
-            sBandName = string(CPLFormFilename(sInputPath.c_str(),sBandBaseName.c_str(),"mpr" ));		
+            sBandName = string(CPLFormFilename(sInputPath.c_str(),sBandBaseName.c_str(),"mpr" ));
         else
-            sBandName = string(CPLFormFilename(sBandPath.c_str(),sBandBaseName.c_str(),"mpr" ));		
+          sBandName = string(CPLFormFilename(sBandPath.c_str(),sBandBaseName.c_str(),"mpr" ));
     }
 
-    if (poDS->bNewDataset)
+    if (poDSIn->bNewDataset)
     {
       // Called from Create():
       // eDataType is defaulted to GDT_Byte by GDALRasterBand::GDALRasterBand
@@ -1251,16 +1258,15 @@ ILWISRasterBand::ILWISRasterBand( ILWISDataset *poDS, int nBand )
       // the most compact storeType possible, without going through all values.
         GetStoreType(sBandName, psInfo.stStoreType);
         eDataType = ILWIS2GDALType(psInfo.stStoreType);
-    }					
+    }
     else // Called from Open(), thus convert ILWIS type from ODF to eDataType
         GetILWISInfo(sBandName);
-    this->poDS = poDS;
-    this->nBand = nBand;
+
     nBlockXSize = poDS->GetRasterXSize();
     nBlockYSize = 1;
     switch (psInfo.stStoreType)
     {
-      case stByte: 
+      case stByte:
         nSizePerPixel = GDALGetDataTypeSize(GDT_Byte) / 8;
         break;
       case stInt:
@@ -1300,8 +1306,8 @@ ILWISRasterBand::~ILWISRasterBand()
 void ILWISRasterBand::ILWISOpen( string pszFileName )
 {
     ILWISDataset* dataset = (ILWISDataset*) poDS;
-    string pszDataFile;
-    pszDataFile = string(CPLResetExtension( pszFileName.c_str(), "mp#" ));
+    string pszDataFile
+        = string(CPLResetExtension( pszFileName.c_str(), "mp#" ));
 
     fpRaw = VSIFOpenL( pszDataFile.c_str(), (dataset->eAccess == GA_Update) ? "rb+" : "rb");
 }
@@ -1384,39 +1390,39 @@ CPLErr ILWISRasterBand::GetILWISInfo(string pszFileName)
 
     // Check against all "system-domains"
     if ( EQUAL(pszBaseName.c_str(),"value") // is it a system domain with Type=DomainValue?
-        || EQUAL(pszBaseName.c_str(),"count") 
-        || EQUAL(pszBaseName.c_str(),"distance") 
-        || EQUAL(pszBaseName.c_str(),"min1to1") 
-        || EQUAL(pszBaseName.c_str(),"nilto1") 
-        || EQUAL(pszBaseName.c_str(),"noaa") 
-        || EQUAL(pszBaseName.c_str(),"perc") 
+        || EQUAL(pszBaseName.c_str(),"count")
+        || EQUAL(pszBaseName.c_str(),"distance")
+        || EQUAL(pszBaseName.c_str(),"min1to1")
+        || EQUAL(pszBaseName.c_str(),"nilto1")
+        || EQUAL(pszBaseName.c_str(),"noaa")
+        || EQUAL(pszBaseName.c_str(),"perc")
         || EQUAL(pszBaseName.c_str(),"radar") )
     {
         ReadValueDomainProperties(pszFileName);
     }
-    else if( EQUAL(pszBaseName.c_str(),"bool") 
-             || EQUAL(pszBaseName.c_str(),"byte") 
-             || EQUAL(pszBaseName.c_str(),"bit") 
-             || EQUAL(pszBaseName.c_str(),"image") 
-             || EQUAL(pszBaseName.c_str(),"colorcmp") 
-             || EQUAL(pszBaseName.c_str(),"flowdirection") 
-             || EQUAL(pszBaseName.c_str(),"hortonratio") 
+    else if( EQUAL(pszBaseName.c_str(),"bool")
+             || EQUAL(pszBaseName.c_str(),"byte")
+             || EQUAL(pszBaseName.c_str(),"bit")
+             || EQUAL(pszBaseName.c_str(),"image")
+             || EQUAL(pszBaseName.c_str(),"colorcmp")
+             || EQUAL(pszBaseName.c_str(),"flowdirection")
+             || EQUAL(pszBaseName.c_str(),"hortonratio")
              || EQUAL(pszBaseName.c_str(),"yesno") )
     {
         eDataType = GDT_Byte;
-        if( EQUAL(pszBaseName.c_str(),"image") 
+        if( EQUAL(pszBaseName.c_str(),"image")
             || EQUAL(pszBaseName.c_str(),"colorcmp"))
             psInfo.stDomain = pszBaseName;
     }
-    else if( EQUAL(pszBaseName.c_str(),"color") 
+    else if( EQUAL(pszBaseName.c_str(),"color")
              || EQUAL(pszBaseName.c_str(),"none" )
-             || EQUAL(pszBaseName.c_str(),"coordbuf") 
-             || EQUAL(pszBaseName.c_str(),"binary") 
+             || EQUAL(pszBaseName.c_str(),"coordbuf")
+             || EQUAL(pszBaseName.c_str(),"binary")
              || EQUAL(pszBaseName.c_str(),"string") )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unsupported ILWIS domain type.");
-        return CE_Failure;		
+        return CE_Failure;
     }
     else
     {
@@ -1427,11 +1433,11 @@ CPLErr ILWISRasterBand::GetILWISInfo(string pszFileName)
         {
             ReadValueDomainProperties(pszFileName);
         }
-        else if((!EQUAL(domType.c_str(),"domainbit")) 
-                && (!EQUAL(domType.c_str(),"domainstring")) 
+        else if((!EQUAL(domType.c_str(),"domainbit"))
+                && (!EQUAL(domType.c_str(),"domainstring"))
                 && (!EQUAL(domType.c_str(),"domaincolor"))
-                && (!EQUAL(domType.c_str(),"domainbinary")) 
-                && (!EQUAL(domType.c_str(),"domaincoordBuf")) 
+                && (!EQUAL(domType.c_str(),"domainbinary"))
+                && (!EQUAL(domType.c_str(),"domaincoordBuf"))
                 && (!EQUAL(domType.c_str(),"domaincoord")))
         {
             // Type is "DomainClass", "DomainBool" or "DomainIdentifier".
@@ -1441,12 +1447,12 @@ CPLErr ILWISRasterBand::GetILWISInfo(string pszFileName)
         }
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Unsupported ILWIS domain type.");
-            return CE_Failure;		
+            return CE_Failure;
         }
     }
-		
+
     return CE_None;
 }
 
@@ -1505,7 +1511,7 @@ CPLErr ILWISRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff, int nBlockYOff,
         else
         {
             CPLFree( pData );
-            CPLError( CE_Failure, CPLE_FileIO, 
+            CPLError( CE_Failure, CPLE_FileIO,
                       "Read of file failed with fread error.");
             return CE_Failure;
         }
@@ -1519,34 +1525,33 @@ CPLErr ILWISRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff, int nBlockYOff,
 
     switch (psInfo.stStoreType)
     {
-      int iCol;
       case stByte:
-        for( iCol = 0; iCol < nBlockXSize; iCol++ )
+        for( int iCol = 0; iCol < nBlockXSize; iCol++ )
         {
           double rV = psInfo.bUseValueRange ? psInfo.vr.rValue(((GByte *) pData)[iCol]) : ((GByte *) pData)[iCol];
           SetValue(pImage, iCol, rV);
         }
         break;
       case stInt:
-        for( iCol = 0; iCol < nBlockXSize; iCol++ )
+        for( int iCol = 0; iCol < nBlockXSize; iCol++ )
         {
           double rV = psInfo.bUseValueRange ? psInfo.vr.rValue(((GInt16 *) pData)[iCol]) : ((GInt16 *) pData)[iCol];
           SetValue(pImage, iCol, rV);
         }
       break;
       case stLong:
-        for( iCol = 0; iCol < nBlockXSize; iCol++ )
+        for( int iCol = 0; iCol < nBlockXSize; iCol++ )
         {
           double rV = psInfo.bUseValueRange ? psInfo.vr.rValue(((GInt32 *) pData)[iCol]) : ((GInt32 *) pData)[iCol];
           SetValue(pImage, iCol, rV);
         }
         break;
       case stFloat:
-        for( iCol = 0; iCol < nBlockXSize; iCol++ )
+        for( int iCol = 0; iCol < nBlockXSize; iCol++ )
           ((float *) pImage)[iCol] = ((float *) pData)[iCol];
-        break;  
+        break;
       case stReal:
-        for( iCol = 0; iCol < nBlockXSize; iCol++ )
+        for( int iCol = 0; iCol < nBlockXSize; iCol++ )
           ((double *) pImage)[iCol] = ((double *) pData)[iCol];
         break;
       default:
@@ -1639,7 +1644,7 @@ void ILWISRasterBand::FillWithNoData(void * pImage)
           case stReal:
             ((double*)pImage)[0] = rUNDEF;
             break;
-          default: // should there be handling for stByte? 
+          default: // should there be handling for stByte?
             break;
         }
         int iItemSize = GDALGetDataTypeSize(eDataType) / 8;
@@ -1672,7 +1677,7 @@ CPLErr ILWISRasterBand::IWriteBlock(CPL_UNUSED int nBlockXOff, int nBlockYOff,
     int nXSize = dataset->GetRasterXSize();
     int nBlockSize = nBlockXSize * nBlockYSize * nSizePerPixel;
     void *pData = CPLMalloc(nBlockSize);
-    
+
     VSIFSeekL( fpRaw, nBlockSize * nBlockYOff, SEEK_SET );
 
     bool fDataExists = (VSIFReadL( pData, 1, nBlockSize, fpRaw ) >= 1);
@@ -1690,41 +1695,40 @@ CPLErr ILWISRasterBand::IWriteBlock(CPL_UNUSED int nBlockXOff, int nBlockYOff,
         // thus only fill in gaps (nodata values)
         switch (psInfo.stStoreType)
         {
-          int iCol;
           case stByte:
-            for (iCol = 0; iCol < nXSize; iCol++ )
+            for (int iCol = 0; iCol < nXSize; iCol++ )
                 if ((( GByte * )pData)[iCol] == 0)
                 {
                     double rV = GetValue(pImage, iCol);
-                    (( GByte * )pData)[iCol] = (GByte) 
+                    (( GByte * )pData)[iCol] = (GByte)
                         (psInfo.bUseValueRange ? psInfo.vr.iRaw(rV) : rV);
                 }
             break;
           case stInt:
-            for (iCol = 0; iCol < nXSize; iCol++ )
+            for (int iCol = 0; iCol < nXSize; iCol++ )
                 if ((( GInt16 * )pData)[iCol] == shUNDEF)
                 {
                     double rV = GetValue(pImage, iCol);
-                    (( GInt16 * )pData)[iCol] = (GInt16) 
+                    (( GInt16 * )pData)[iCol] = (GInt16)
                         (psInfo.bUseValueRange ? psInfo.vr.iRaw(rV) : rV);
                 }
             break;
           case stLong:
-            for (iCol = 0; iCol < nXSize; iCol++ )
+            for (int iCol = 0; iCol < nXSize; iCol++ )
                 if ((( GInt32 * )pData)[iCol] == iUNDEF)
                 {
                     double rV = GetValue(pImage, iCol);
-                    (( GInt32 * )pData)[iCol] = (GInt32) 
+                    (( GInt32 * )pData)[iCol] = (GInt32)
                         (psInfo.bUseValueRange ? psInfo.vr.iRaw(rV) : rV);
                 }
             break;
           case stFloat:
-            for (iCol = 0; iCol < nXSize; iCol++ )
+            for (int iCol = 0; iCol < nXSize; iCol++ )
                 if ((( float * )pData)[iCol] == flUNDEF)
                     (( float * )pData)[iCol] = ((float* )pImage)[iCol];
             break;
           case stReal:
-            for (iCol = 0; iCol < nXSize; iCol++ )
+            for (int iCol = 0; iCol < nXSize; iCol++ )
                 if ((( double * )pData)[iCol] == rUNDEF)
                     (( double * )pData)[iCol] = ((double* )pImage)[iCol];
             break;
@@ -1735,25 +1739,24 @@ CPLErr ILWISRasterBand::IWriteBlock(CPL_UNUSED int nBlockXOff, int nBlockYOff,
         // fpRaw (thus pData) is still empty, just write the data
         switch (psInfo.stStoreType)
         {
-          int iCol;
           case stByte:
-            for (iCol = 0; iCol < nXSize; iCol++ )
+            for (int iCol = 0; iCol < nXSize; iCol++ )
             {
                 double rV = GetValue(pImage, iCol);
-                (( GByte * )pData)[iCol] = (GByte) 
+                (( GByte * )pData)[iCol] = (GByte)
                     (psInfo.bUseValueRange ? psInfo.vr.iRaw(rV) : rV);
             }
             break;
           case stInt:
-            for (iCol = 0; iCol < nXSize; iCol++ )
+            for (int iCol = 0; iCol < nXSize; iCol++ )
             {
                 double rV = GetValue(pImage, iCol);
-                (( GInt16 * )pData)[iCol] = (GInt16) 
+                (( GInt16 * )pData)[iCol] = (GInt16)
                     (psInfo.bUseValueRange ? psInfo.vr.iRaw(rV) : rV);
             }
             break;
           case stLong:
-            for (iCol = 0; iCol < nXSize; iCol++ )
+            for (int iCol = 0; iCol < nXSize; iCol++ )
             {
                 double rV = GetValue(pImage, iCol);
                 ((GInt32 *)pData)[iCol] = (GInt32)
@@ -1761,11 +1764,11 @@ CPLErr ILWISRasterBand::IWriteBlock(CPL_UNUSED int nBlockXOff, int nBlockYOff,
             }
             break;
           case stFloat:
-            for (iCol = 0; iCol < nXSize; iCol++ )
+            for (int iCol = 0; iCol < nXSize; iCol++ )
                 (( float * )pData)[iCol] = ((float* )pImage)[iCol];
             break;
           case stReal:
-            for (iCol = 0; iCol < nXSize; iCol++ )
+            for (int iCol = 0; iCol < nXSize; iCol++ )
                 (( double * )pData)[iCol] = ((double* )pImage)[iCol];
             break;
         }
@@ -1779,7 +1782,7 @@ CPLErr ILWISRasterBand::IWriteBlock(CPL_UNUSED int nBlockXOff, int nBlockYOff,
     if (VSIFWriteL( pData, 1, nBlockSize, fpRaw ) < 1)
     {
         CPLFree( pData );
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   "Write of file failed with fwrite error.");
         return CE_Failure;
     }
@@ -1794,37 +1797,35 @@ CPLErr ILWISRasterBand::IWriteBlock(CPL_UNUSED int nBlockXOff, int nBlockYOff,
 double ILWISRasterBand::GetNoDataValue( int *pbSuccess )
 
 {
-    if( pbSuccess != NULL )
+    if( pbSuccess )
         *pbSuccess = TRUE;
 
     if( eDataType == GDT_Float64 )
         return rUNDEF;
-    else if( eDataType == GDT_Int32)
+    if( eDataType == GDT_Int32)
         return iUNDEF;
-    else if( eDataType == GDT_Int16)
+    if( eDataType == GDT_Int16)
         return shUNDEF;
-    else if( eDataType == GDT_Float32)
+    if( eDataType == GDT_Float32)
         return flUNDEF;
-    else if( EQUAL(psInfo.stDomain.c_str(),"image") 
-             || EQUAL(psInfo.stDomain.c_str(),"colorcmp")) 
+    if( pbSuccess &&
+             (EQUAL(psInfo.stDomain.c_str(),"image")
+              || EQUAL(psInfo.stDomain.c_str(),"colorcmp")))
     {
-        *pbSuccess = false;
-        return 0;
+        *pbSuccess = FALSE;
     }
-    else
-        return 0;
+
+    // TODO: Defaults to pbSuccess TRUE.  Is the unhandled case really success?
+    return 0.0;
 }
 
 /************************************************************************/
 /*                      ValueRange()                                    */
 /************************************************************************/
-double Max(double a, double b) 
-{ return (a>=b && a!=rUNDEF) ? a : b; }
 
 static double doubleConv(const char* s)
 {
-    if (s == 0) return rUNDEF;
-    char *endptr;
+    if (s == NULL) return rUNDEF;
     char *begin = const_cast<char*>(s);
 
     // skip leading spaces; strtol will return 0 on a string with only spaces
@@ -1833,7 +1834,8 @@ static double doubleConv(const char* s)
 
     if (strlen(begin) == 0) return rUNDEF;
     errno = 0;
-    double r = CPLStrtod(begin, &endptr);
+    char *endptr;
+    const double r = CPLStrtod(begin, &endptr);
     if ((0 == *endptr) && (errno==0))
         return r;
     while (*endptr != 0) { // check trailing spaces
@@ -1844,22 +1846,28 @@ static double doubleConv(const char* s)
     return r;
 }
 
-ValueRange::ValueRange(string sRng)
+ValueRange::ValueRange(string sRng) :
+    _rLo(0.0), _rHi(0.0), _rStep(0.0), _iDec(0), _r0(0.0), iRawUndef(0),
+    _iWidth(0), st(stByte)
 {
     char* sRange = new char[sRng.length() + 1];
     for (unsigned int i = 0; i < sRng.length(); ++i)
         sRange[i] = sRng[i];
     sRange[sRng.length()] = 0;
-	
+
     char *p1 = strchr(sRange, ':');
-    if (0 == p1)
+    if (NULL == p1)
+    {
+        delete[] sRange;
+        init();
         return;
+    }
 
     char *p3 = strstr(sRange, ",offset=");
-    if (0 == p3)
+    if (NULL == p3)
         p3 = strstr(sRange, ":offset=");
     _r0 = rUNDEF;
-    if (0 != p3) {
+    if (NULL != p3) {
         _r0 = doubleConv(p3+8);
         *p3 = 0;
     }
@@ -1871,7 +1879,7 @@ ValueRange::ValueRange(string sRng)
     }
 
     p2 = strchr(sRange, ':');
-    if (p2 != 0) {
+    if (p2 != NULL) {
         *p2 = 0;
         _rLo = CPLAtof(sRange);
         _rHi = CPLAtof(p2+1);
@@ -1879,9 +1887,9 @@ ValueRange::ValueRange(string sRng)
     else {
         _rLo = CPLAtof(sRange);
         _rHi = _rLo;
-    }  
+    }
     init(_r0);
-	 
+
     delete [] sRange;
 }
 
@@ -1893,7 +1901,7 @@ ValueRange::ValueRange(double min, double max)	// step = 1
     init();
 }
 
-ValueRange::ValueRange(double min, double max, double step)	
+ValueRange::ValueRange(double min, double max, double step)
 {
     _rLo = min;
     _rHi = max;
@@ -1917,7 +1925,6 @@ void ValueRange::init()
 
 void ValueRange::init(double rRaw0)
 {
-    try {
         _iDec = 0;
         if (_rStep < 0)
             _rStep = 0;
@@ -1946,14 +1953,14 @@ void ValueRange::init(double rRaw0)
         {
             st = stReal;
             _rStep = 0;
-        }			
+        }
         else {
             r = get_rHi() - get_rLo();
             if (r <= ULONG_MAX) {
                 r /= _rStep;
                 r += 1;
             }
-            r += 1; 
+            r += 1;
             if (r > LONG_MAX)
                 st = stReal;
             else {
@@ -1975,59 +1982,49 @@ void ValueRange::init(double rRaw0)
             iRawUndef = shUNDEF;
         else
             iRawUndef = 0;
-    }
-    catch (std::exception*) {
-        st = stReal;
-        _r0 = 0;
-        _rStep = 0.0001;
-        _rHi = 1e300;
-        _rLo = -1e300;
-        iRawUndef = iUNDEF;
-    }
 }
 
 string ValueRange::ToString()
 {
     char buffer[200];
     if (fabs(get_rLo()) > 1.0e20 || fabs(get_rHi()) > 1.0e20)
-        CPLsprintf(buffer, "%g:%g:%f:offset=%g", get_rLo(), get_rHi(), get_rStep(), get_rRaw0());
+        CPLsnprintf(buffer, sizeof(buffer), "%g:%g:%f:offset=%g", get_rLo(), get_rHi(), get_rStep(), get_rRaw0());
     else if (get_iDec() >= 0)
-        CPLsprintf(buffer, "%.*f:%.*f:%.*f:offset=%.0f", get_iDec(), get_rLo(), get_iDec(), get_rHi(), get_iDec(), get_rStep(), get_rRaw0());
+        CPLsnprintf(buffer, sizeof(buffer), "%.*f:%.*f:%.*f:offset=%.0f", get_iDec(), get_rLo(), get_iDec(), get_rHi(), get_iDec(), get_rStep(), get_rRaw0());
     else
-        CPLsprintf(buffer, "%f:%f:%f:offset=%.0f", get_rLo(), get_rHi(), get_rStep(), get_rRaw0());
+        CPLsnprintf(buffer, sizeof(buffer), "%f:%f:%f:offset=%.0f", get_rLo(), get_rHi(), get_rStep(), get_rRaw0());
     return string(buffer);
 }
 
-double ValueRange::rValue(int iRaw)
+double ValueRange::rValue(int iRawIn)
 {
-    if (iRaw == iUNDEF || iRaw == iRawUndef)
+    if (iRawIn == iUNDEF || iRawIn == iRawUndef)
         return rUNDEF;
-    double rVal = iRaw + _r0;
+    double rVal = iRawIn + _r0;
     rVal *= _rStep;
     if (get_rLo() == get_rHi())
         return rVal;
-    double rEpsilon = _rStep == 0.0 ? 1e-6 : _rStep / 3.0; // avoid any rounding problems with an epsilon directly based on the
+    const double rEpsilon = _rStep == 0.0 ? 1e-6 : _rStep / 3.0; // avoid any rounding problems with an epsilon directly based on the
     // the stepsize
     if ((rVal - get_rLo() < -rEpsilon) || (rVal - get_rHi() > rEpsilon))
         return rUNDEF;
     return rVal;
 }
 
-int ValueRange::iRaw(double rValue)
+int ValueRange::iRaw(double rValueIn)
 {
-    if (rValue == rUNDEF) // || !fContains(rValue))
+    if (rValueIn == rUNDEF) // || !fContains(rValue))
         return iUNDEF;
-    double rEpsilon = _rStep == 0.0 ? 1e-6 : _rStep / 3.0;	
-    if (rValue - get_rLo() < -rEpsilon) // take a little rounding tolerance
+    const double rEpsilon = _rStep == 0.0 ? 1e-6 : _rStep / 3.0;
+    if (rValueIn - get_rLo() < -rEpsilon) // take a little rounding tolerance
         return iUNDEF;
-    else if (rValue - get_rHi() > rEpsilon) // take a little rounding tolerance
+    else if (rValueIn - get_rHi() > rEpsilon) // take a little rounding tolerance
         return iUNDEF;
-    rValue /= _rStep;
-    double rVal = floor(rValue+0.5);
+    rValueIn /= _rStep;
+    double rVal = floor(rValueIn+0.5);
     rVal -= _r0;
-    long iVal;
-    iVal = longConv(rVal);
-    return iVal;
+    long iVal = longConv(rVal);
+    return static_cast<int>(iVal);
 }
 
 
@@ -2038,25 +2035,22 @@ int ValueRange::iRaw(double rValue)
 void GDALRegister_ILWIS()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "ILWIS" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "ILWIS" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "ILWIS" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "ILWIS Raster Map" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "mpr/mpl" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte Int16 Int32 Float64" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = ILWISDataset::Open;
-        poDriver->pfnCreate = ILWISDataset::Create;
-        poDriver->pfnCreateCopy = ILWISDataset::CreateCopy;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "ILWIS" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "ILWIS Raster Map" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "mpr/mpl" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte Int16 Int32 Float64" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = ILWISDataset::Open;
+    poDriver->pfnCreate = ILWISDataset::Create;
+    poDriver->pfnCreateCopy = ILWISDataset::CreateCopy;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/ilwis/ilwisdataset.h b/frmts/ilwis/ilwisdataset.h
index 072690f..ab2db03 100644
--- a/frmts/ilwis/ilwisdataset.h
+++ b/frmts/ilwis/ilwisdataset.h
@@ -39,13 +39,14 @@
 #include  <io.h>
 #endif
 
-#include  <cstdio>
-#include  <cstdlib>
-#include <string>
+#include <cstdio>
+#include <cstdlib>
+
 #include <map>
+#include <string>
 
 CPL_C_START
-void	GDALRegister_ILWIS(void);
+void GDALRegister_ILWIS();
 CPL_C_END
 
 #define shUNDEF	-32767
@@ -54,7 +55,7 @@ CPL_C_END
 #define	rUNDEF  ((double)-1e308)
 
 enum ilwisStoreType
-{	
+{
     stByte,
     stInt,
     stLong,
@@ -66,15 +67,15 @@ class ValueRange
 {
 public:
     ValueRange(double min, double max);	// step = 1
-    ValueRange(double min, double max, double step);	
+    ValueRange(double min, double max, double step);
     ValueRange(std::string str);
     std::string ToString();
     ilwisStoreType get_NeededStoreType() { return st; }
     double get_rLo() { return _rLo; }
     double get_rHi() { return _rHi; }
     double get_rStep() { return _rStep; }
-    double get_rRaw0() { return _r0; }	
-    int get_iDec() { return _iDec; }	
+    double get_rRaw0() { return _r0; }
+    int get_iDec() { return _iDec; }
     double rValue(int raw);
     int iRaw(double value);
 
@@ -96,7 +97,7 @@ private:
 
 struct ILWISInfo
 {
-    ILWISInfo() : bUseValueRange(false), vr(0, 0) {}
+    ILWISInfo() : bUseValueRange(false), vr(0, 0), stStoreType(stByte) {}
     bool bUseValueRange;
     ValueRange vr;
     ilwisStoreType stStoreType;
@@ -121,9 +122,9 @@ public:
     ~ILWISRasterBand();
     CPLErr GetILWISInfo(std::string pszFileName);
     void ILWISOpen( std::string pszFilename);
-				
+
     virtual CPLErr IReadBlock( int, int, void * );
-    virtual CPLErr IWriteBlock( int, int, void * ); 
+    virtual CPLErr IWriteBlock( int, int, void * );
     virtual double GetNoDataValue( int *pbSuccess );
 
 private:
@@ -150,13 +151,13 @@ class ILWISDataset : public GDALPamDataset
     CPLErr WriteProjection();
     CPLErr WriteGeoReference();
     void   CollectTransformCoef(std::string &pszRefFile );
-		
+
 public:
     ILWISDataset();
     ~ILWISDataset();
 
     static GDALDataset *Open( GDALOpenInfo * );
-		
+
     static GDALDataset *CreateCopy( const char * pszFilename,
                                     GDALDataset *poSrcDS,
                                     int bStrict, char ** papszOptions,
@@ -164,10 +165,10 @@ public:
                                     void * pProgressData );
 
     static GDALDataset *Create(const char* pszFilename,
-                               int nXSize, int nYSize, 
+                               int nXSize, int nYSize,
                                int nBands, GDALDataType eType,
-                               char** papszParmList); 
-		
+                               char** papszParmList);
+
     virtual CPLErr 	GetGeoTransform( double * padfTransform );
     virtual CPLErr  SetGeoTransform( double * );
 
@@ -178,7 +179,7 @@ public:
 };
 
 // IniFile.h: interface for the IniFile class.
-// 
+//
 //////////////////////////////////////////////////////////////////////
 
 class CompareAsNum
@@ -190,7 +191,7 @@ public:
 typedef std::map<std::string, std::string>          SectionEntries;
 typedef std::map<std::string, SectionEntries*> Sections;
 
-class IniFile  
+class IniFile
 {
 public:
     IniFile(const std::string& filename);
@@ -210,5 +211,3 @@ private:
     void Load();
     void Store();
 };
-
-
diff --git a/frmts/ilwis/makefile.vc b/frmts/ilwis/makefile.vc
index 9897821..72d6628 100644
--- a/frmts/ilwis/makefile.vc
+++ b/frmts/ilwis/makefile.vc
@@ -1,8 +1,6 @@
 
 OBJ	=	ilwisdataset.obj ilwiscoordinatesystem.obj
 
-EXTRAFLAGS = 	-I..\iso8211
-
 GDAL_ROOT	=	..\..
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
diff --git a/frmts/ingr/IngrTypes.cpp b/frmts/ingr/IngrTypes.cpp
index b828201..c7d4c16 100644
--- a/frmts/ingr/IngrTypes.cpp
+++ b/frmts/ingr/IngrTypes.cpp
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * $Id: IngrTypes.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: IngrTypes.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Intergraph Raster Format support
  * Purpose:  Types support function
@@ -63,14 +63,14 @@ static const INGR_FormatDescription INGR_FormatTable[] = {
     {AdaptiveGrayScale,       "Adaptive Gray Scale",         GDT_Byte},
     {JPEGGRAY,                "JPEG GRAY",                   GDT_Byte},
     {JPEGRGB,                 "JPEG RGB",                    GDT_Byte},
-    {JPEGCYMK,                "JPEG CYMK",                   GDT_Byte},
+    {JPEGCMYK,                "JPEG CMYK",                   GDT_Byte},
     {TiledRasterData,         "Tiled Raste Data",            GDT_Byte},
     {NotUsedReserved,         "Not Used( Reserved )",        GDT_Byte},
     {ContinuousTone,          "Continuous Tone",             GDT_Byte},
     {LineArt,                 "LineArt",                     GDT_Byte}
 };
 
-static const char *IngrOrientation[] = {
+static const char * const IngrOrientation[] = {
     "Upper Left Vertical",
     "Upper Right Vertical",
     "Lower Left Vertical",
@@ -170,14 +170,11 @@ static const double INGR_LRH_Flip[16] =
         0.0,  0.0,  0.0,  1.0
     };
 
-void INGR_MultiplyMatrix( double *padfA, real64 *padfB, const double *padfC )
+static void INGR_MultiplyMatrix( double *padfA, real64 *padfB, const double *padfC )
 {
-    int i;
-    int j;
-
-    for( i = 0; i < 4; i++ )
+    for( int i = 0; i < 4; i++ )
     {
-        for( j = 0; j < 4; j++ )
+        for( int j = 0; j < 4; j++ )
         {
             padfA[(i * 4) + j] = (double)
                 padfB[(i * 4) + 0] * padfC[(0 * 4) + j] +
@@ -188,15 +185,20 @@ void INGR_MultiplyMatrix( double *padfA, real64 *padfB, const double *padfC )
     }
 }
 
+// TODO: Move function to port and change gdal_priv.h macro to function header.
+#undef DIV_ROUND_UP
+static int DIV_ROUND_UP(int a, int b)
+{
+    return (a % b) == 0 ? (a / b) : (a / b) + 1;
+}
+
 // -----------------------------------------------------------------------------
 //                                                            INGR_GetDataType()
 // -----------------------------------------------------------------------------
 
 GDALDataType CPL_STDCALL INGR_GetDataType( uint16 eCode )
 {
-    unsigned int i;
-
-    for( i = 0; i < FORMAT_TAB_COUNT; i++ )
+    for( unsigned int i = 0; i < FORMAT_TAB_COUNT; i++ )
     {
 		if( eCode == INGR_FormatTable[i].eFormatCode )
         {
@@ -213,9 +215,7 @@ GDALDataType CPL_STDCALL INGR_GetDataType( uint16 eCode )
 
 const char * CPL_STDCALL INGR_GetFormatName( uint16 eCode )
 {
-    unsigned int i;
-
-    for( i = 0; i < FORMAT_TAB_COUNT; i++ )
+    for( unsigned int i = 0; i < FORMAT_TAB_COUNT; i++ )
     {
         if( eCode == INGR_FormatTable[i].eFormatCode )
         {
@@ -234,15 +234,15 @@ const char * CPL_STDCALL INGR_GetOrientation( uint8 nIndex )
 {
     if (nIndex < sizeof(IngrOrientation) / sizeof(IngrOrientation[0]))
         return IngrOrientation[nIndex];
-    else
-        return "invalid orientation";
+
+    return "invalid orientation";
 }
 
 // -----------------------------------------------------------------------------
 //                                                              INGR_GetFormat()
 // -----------------------------------------------------------------------------
 
-INGR_Format CPL_STDCALL INGR_GetFormat( GDALDataType eType, 
+INGR_Format CPL_STDCALL INGR_GetFormat( GDALDataType eType,
                                         const char *pszCompression )
 {
     if( EQUAL( pszCompression, "None" ) ||
@@ -261,9 +261,7 @@ INGR_Format CPL_STDCALL INGR_GetFormat( GDALDataType eType,
         }
     }
 
-    unsigned int i;
-
-    for( i = 0; i < FORMAT_TAB_COUNT; i++ )
+    for( unsigned int i = 0; i < FORMAT_TAB_COUNT; i++ )
     {
         if( EQUAL( pszCompression, INGR_FormatTable[i].pszName ) )
         {
@@ -278,7 +276,7 @@ INGR_Format CPL_STDCALL INGR_GetFormat( GDALDataType eType,
 //                                                         INGR_GetTransMatrix()
 // -----------------------------------------------------------------------------
 
-void CPL_STDCALL INGR_GetTransMatrix( INGR_HeaderOne *pHeaderOne, 
+void CPL_STDCALL INGR_GetTransMatrix( INGR_HeaderOne *pHeaderOne,
                                       double *padfGeoTransform )
 {
     // -------------------------------------------------------------
@@ -294,7 +292,7 @@ void CPL_STDCALL INGR_GetTransMatrix( INGR_HeaderOne *pHeaderOne,
     {
         padfGeoTransform[0] = 0.0;
         padfGeoTransform[1] = 1.0;
-        padfGeoTransform[2] = 0.0; 
+        padfGeoTransform[2] = 0.0;
         padfGeoTransform[3] = 0.0;
         padfGeoTransform[4] = 0.0;
         padfGeoTransform[5] = 1.0;
@@ -302,43 +300,50 @@ void CPL_STDCALL INGR_GetTransMatrix( INGR_HeaderOne *pHeaderOne,
     }
 
     // -------------------------------------------------------------
-    // Calculate Concatened Tranformation Matrix based on Orientation
+    // Calculate Concatenated Transformation Matrix based on Orientation
     // -------------------------------------------------------------
 
     double adfConcat[16];
-   
+
     switch( (INGR_Orientation ) pHeaderOne->ScanlineOrientation )
     {
         case UpperLeftVertical:
             {
-                unsigned int i = 0;
-                for(i = 0; i < 16; i++)
+                for(unsigned int i = 0; i < 16; i++)
                 {
                     adfConcat[i] = (double) pHeaderOne->TransformationMatrix[i];
                 }
             }
             break;
         case UpperRightVertical:
-            INGR_MultiplyMatrix( adfConcat, pHeaderOne->TransformationMatrix, INGR_URV_Flip ); 
+            INGR_MultiplyMatrix( adfConcat, pHeaderOne->TransformationMatrix, INGR_URV_Flip );
             break;
         case LowerLeftVertical:
-            INGR_MultiplyMatrix( adfConcat, pHeaderOne->TransformationMatrix, INGR_LLV_Flip ); 
+            INGR_MultiplyMatrix( adfConcat, pHeaderOne->TransformationMatrix, INGR_LLV_Flip );
             break;
         case LowerRightVertical:
-            INGR_MultiplyMatrix( adfConcat, pHeaderOne->TransformationMatrix, INGR_LRV_Flip ); 
+            INGR_MultiplyMatrix( adfConcat, pHeaderOne->TransformationMatrix, INGR_LRV_Flip );
             break;
         case UpperLeftHorizontal:
-            INGR_MultiplyMatrix( adfConcat, pHeaderOne->TransformationMatrix, INGR_ULH_Flip ); 
+            INGR_MultiplyMatrix( adfConcat, pHeaderOne->TransformationMatrix, INGR_ULH_Flip );
             break;
         case UpperRightHorizontal:
-            INGR_MultiplyMatrix( adfConcat, pHeaderOne->TransformationMatrix, INGR_URH_Flip ); 
+            INGR_MultiplyMatrix( adfConcat, pHeaderOne->TransformationMatrix, INGR_URH_Flip );
             break;
         case LowerLeftHorizontal:
-            INGR_MultiplyMatrix( adfConcat, pHeaderOne->TransformationMatrix, INGR_LLH_Flip ); 
+            INGR_MultiplyMatrix( adfConcat, pHeaderOne->TransformationMatrix, INGR_LLH_Flip );
             break;
         case LowerRightHorizontal:
-            INGR_MultiplyMatrix( adfConcat, pHeaderOne->TransformationMatrix, INGR_LRH_Flip ); 
+            INGR_MultiplyMatrix( adfConcat, pHeaderOne->TransformationMatrix, INGR_LRH_Flip );
             break;
+        default:
+            padfGeoTransform[0] = 0.0;
+            padfGeoTransform[1] = 1.0;
+            padfGeoTransform[2] = 0.0;
+            padfGeoTransform[3] = 0.0;
+            padfGeoTransform[4] = 0.0;
+            padfGeoTransform[5] = 1.0;
+            return;
     }
 
     // -------------------------------------------------------------
@@ -359,9 +364,7 @@ void CPL_STDCALL INGR_GetTransMatrix( INGR_HeaderOne *pHeaderOne,
 
 void CPL_STDCALL INGR_SetTransMatrix( real64 *padfMatrix, double *padfGeoTransform )
 {
-    unsigned int i;
-
-    for( i = 0; i < 15; i++ )
+    for( unsigned int i = 0; i < 15; i++ )
     {
         padfMatrix[i] = 0.0;
     }
@@ -424,7 +427,7 @@ uint32 CPL_STDCALL INGR_GetTileDirectory( VSILFILE *fp,
     GByte abyBuf[SIZEOF_TDIR];
 
     if( ( VSIFSeekL( fp, nOffset, SEEK_SET ) == -1 ) ||
-        ( VSIFReadL( abyBuf, 1, SIZEOF_TDIR, fp ) == 0 ) )
+        ( VSIFReadL( abyBuf, 1, SIZEOF_TDIR, fp ) != SIZEOF_TDIR ) )
     {
         CPLDebug("INGR", "Error reading tiles header");
         return 0;
@@ -442,9 +445,14 @@ uint32 CPL_STDCALL INGR_GetTileDirectory( VSILFILE *fp,
     // ----------------------------------------------------------------
     // Calculate the number of tiles
     // ----------------------------------------------------------------
-
-    int nTilesPerCol = (int) ceil( (float) nBandXSize / pTileDir->TileSize );
-    int nTilesPerRow = (int) ceil( (float) nBandYSize / pTileDir->TileSize );
+    int nTilesPerCol = DIV_ROUND_UP(nBandXSize, pTileDir->TileSize);
+    int nTilesPerRow = DIV_ROUND_UP(nBandYSize, pTileDir->TileSize);
+    if( nTilesPerCol > INT_MAX / nTilesPerRow )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                    "Too many tiles : %u x %u", nTilesPerCol, nTilesPerRow);
+        return 0;
+    }
 
     uint32 nTiles = nTilesPerCol * nTilesPerRow;
 
@@ -452,12 +460,11 @@ uint32 CPL_STDCALL INGR_GetTileDirectory( VSILFILE *fp,
     // Load the tile table (first tile s already read)
     // ----------------------------------------------------------------
 
-    *pahTiles  = (INGR_TileItem*) VSICalloc( nTiles, SIZEOF_TILE );
-    GByte *pabyBuf  = (GByte*) VSICalloc( ( nTiles - 1 ), SIZEOF_TILE );
+    *pahTiles  = (INGR_TileItem*) VSI_CALLOC_VERBOSE( nTiles, SIZEOF_TILE );
+    GByte *pabyBuf  = (GByte*) VSI_CALLOC_VERBOSE( ( nTiles - 1 ), SIZEOF_TILE );
 
     if (*pahTiles == NULL || pabyBuf == NULL)
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
         CPLFree( *pahTiles );
         *pahTiles = NULL;
         CPLFree( pabyBuf );
@@ -469,7 +476,7 @@ uint32 CPL_STDCALL INGR_GetTileDirectory( VSILFILE *fp,
     (*pahTiles)[0].Used       = pTileDir->First.Used;
 
     if( nTiles > 1 &&
-      ( VSIFReadL( pabyBuf, ( nTiles - 1 ), SIZEOF_TILE, fp ) == 0 ) )
+      ( VSIFReadL( pabyBuf, ( nTiles - 1 ), SIZEOF_TILE, fp ) != SIZEOF_TILE ) )
     {
         CPLDebug("INGR", "Error reading tiles table");
         CPLFree( *pahTiles );
@@ -478,11 +485,9 @@ uint32 CPL_STDCALL INGR_GetTileDirectory( VSILFILE *fp,
         return 0;
     }
 
-    unsigned int i;
-
-    for( i = 1; i < nTiles; i++ )
+    for( unsigned int i = 1; i < nTiles; i++ )
     {
-        INGR_TileItemDiskToMem( &((*pahTiles)[i]), 
+        INGR_TileItemDiskToMem( &((*pahTiles)[i]),
                                 &pabyBuf[ (i - 1) * SIZEOF_TILE] );
     }
 
@@ -525,10 +530,9 @@ void CPL_STDCALL INGR_GetIGDSColors( VSILFILE *fp,
         return;
     }
 
-    unsigned int i = 0;
     unsigned int n = 0;
 
-    for( i = 0; i < nEntries; i++ )
+    for( unsigned int i = 0; i < nEntries; i++ )
     {
         BUF2STRC( pabyBuf, n, hIGDSColors.Entry[i].v_red );
         BUF2STRC( pabyBuf, n, hIGDSColors.Entry[i].v_green );
@@ -545,7 +549,7 @@ void CPL_STDCALL INGR_GetIGDSColors( VSILFILE *fp,
 
     oEntry.c4 = 255;
 
-    for( i = 0; i < nEntries; i++ )
+    for( unsigned int i = 0; i < nEntries; i++ )
     {
         oEntry.c1 = hIGDSColors.Entry[i].v_red;
         oEntry.c2 = hIGDSColors.Entry[i].v_green;
@@ -562,7 +566,7 @@ uint32 CPL_STDCALL INGR_SetEnvironColors( GDALColorTable *poColorTable,
                                           INGR_ColorTableVar *pEnvironTable )
 {
     GDALColorEntry oEntry;
-    real32 fNormFactor = 0xfff / 255;
+    const real32 fNormFactor = static_cast<real32>(0xfff) / 255;
     int i;
 
     for( i = 0; i < poColorTable->GetColorEntryCount(); i++ )
@@ -601,13 +605,12 @@ void CPL_STDCALL INGR_GetEnvironVColors( VSILFILE *fp,
 
     INGR_ColorTableVar hVLTColors;
 
-    hVLTColors.Entry = (vlt_slot*) VSICalloc( nEntries, SIZEOF_VLTS );
+    hVLTColors.Entry = (vlt_slot*) VSI_CALLOC_VERBOSE( nEntries, SIZEOF_VLTS );
 
-    GByte *pabyBuf = (GByte*) VSICalloc( nEntries, SIZEOF_VLTS );
+    GByte *pabyBuf = (GByte*) VSI_CALLOC_VERBOSE( nEntries, SIZEOF_VLTS );
 
     if (hVLTColors.Entry == NULL || pabyBuf == NULL)
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
         CPLFree( pabyBuf );
         CPLFree( hVLTColors.Entry );
         return;
@@ -621,10 +624,9 @@ void CPL_STDCALL INGR_GetEnvironVColors( VSILFILE *fp,
         return;
     }
 
-    unsigned int i = 0;
     unsigned int n = 0;
 
-    for( i = 0; i < nEntries; i++ )
+    for( unsigned int i = 0; i < nEntries; i++ )
     {
         BUF2STRC( pabyBuf, n, hVLTColors.Entry[i].v_slot );
         BUF2STRC( pabyBuf, n, hVLTColors.Entry[i].v_red );
@@ -636,7 +638,7 @@ void CPL_STDCALL INGR_GetEnvironVColors( VSILFILE *fp,
 
 
 #if defined(CPL_MSB)
-    for (i = 0; i < nEntries; i++)
+    for ( unsigned int i = 0; i < nEntries; i++)
     {
         CPL_LSBPTR16(&hVLTColors.Entry[i].v_slot);
         CPL_LSBPTR16(&hVLTColors.Entry[i].v_red);
@@ -653,7 +655,7 @@ void CPL_STDCALL INGR_GetEnvironVColors( VSILFILE *fp,
     real32 fMaxGreen    = 0.0;
     real32 fMaxBlues    = 0.0;
 
-    for( i = 0; i < nEntries; i++ )
+    for( unsigned int i = 0; i < nEntries; i++ )
     {
         fMaxRed   = MAX( fMaxRed  , hVLTColors.Entry[i].v_red );
         fMaxGreen = MAX( fMaxGreen, hVLTColors.Entry[i].v_green );
@@ -664,12 +666,10 @@ void CPL_STDCALL INGR_GetEnvironVColors( VSILFILE *fp,
     // Calculate Normalization Factor
     // -------------------------------------------------------------
 
-    real32 fNormFactor  = 0.0;
-
-    fNormFactor  = ( fMaxRed > fMaxGreen ? fMaxRed : fMaxGreen );
+    real32 fNormFactor  = ( fMaxRed > fMaxGreen ? fMaxRed : fMaxGreen );
     fNormFactor  = ( fNormFactor > fMaxBlues ? fNormFactor : fMaxBlues );
     if (fNormFactor)
-        fNormFactor  = 255 / fNormFactor;
+        fNormFactor = 255 / fNormFactor;
 
     // -------------------------------------------------------------
     // Loads GDAL Color Table ( filling the wholes )
@@ -677,7 +677,7 @@ void CPL_STDCALL INGR_GetEnvironVColors( VSILFILE *fp,
 
     GDALColorEntry oEntry;
 
-    for( i = 0;  i < nEntries; i++ )
+    for( unsigned int i = 0;  i < nEntries; i++ )
     {
         oEntry.c1 = (short) ( hVLTColors.Entry[i].v_red   * fNormFactor );
         oEntry.c2 = (short) ( hVLTColors.Entry[i].v_green * fNormFactor );
@@ -719,6 +719,7 @@ INGR_MinMax CPL_STDCALL INGR_SetMinMax( GDALDataType eType, double dValue )
         break;
     case GDT_Float64:
         uResult.AsReal64  = (real64) dValue;
+        break;
     default:
         uResult.AsUint8   = (uint8) 0;
     }
@@ -760,17 +761,19 @@ uint32 CPL_STDCALL INGR_GetDataBlockSize( const char *pszFilename,
         // -------------------------------------------------------------
 
         VSIStatBufL  sStat;
-        VSIStatL( pszFilename, &sStat );
+        if( VSIStatL( pszFilename, &sStat ) != 0 ||
+            sStat.st_size < nDataOffset )
+            return 0;
         return (uint32) (sStat.st_size - nDataOffset);
     }
-    else
-    {
-        // -------------------------------------------------------------
-        // Until the end of the band
-        // -------------------------------------------------------------
 
-        return nBandOffset - nDataOffset;
-    }
+    // -------------------------------------------------------------
+    // Until the end of the band
+    // -------------------------------------------------------------
+
+    if( nBandOffset < nDataOffset )
+        return 0;
+    return nBandOffset - nDataOffset;
 }
 
 // -----------------------------------------------------------------------------
@@ -779,7 +782,7 @@ uint32 CPL_STDCALL INGR_GetDataBlockSize( const char *pszFilename,
 
 INGR_VirtualFile CPL_STDCALL INGR_CreateVirtualFile( const char *pszFilename,
                                                      INGR_Format eFormat,
-                                                     int nXSize, 
+                                                     int nXSize,
                                                      int nYSize,
                                                      int nTileSize,
                                                      int nQuality,
@@ -787,7 +790,7 @@ INGR_VirtualFile CPL_STDCALL INGR_CreateVirtualFile( const char *pszFilename,
                                                      int nBufferSize,
                                                      int nBand )
 {
-    INGR_VirtualFile hVirtual;
+    INGR_VirtualFile hVirtual = {NULL, NULL, NULL};
 
     hVirtual.pszFileName = CPLSPrintf( "/vsimem/%s.virtual",
         CPLGetBasename( pszFilename ) );
@@ -796,8 +799,9 @@ INGR_VirtualFile CPL_STDCALL INGR_CreateVirtualFile( const char *pszFilename,
 
     switch( eFormat )
     {
-    case JPEGRGB: 
+    case JPEGRGB:
         nJPGComponents = 3;
+        // fallthrough
     case JPEGGRAY:
         {
             GByte *pabyHeader = (GByte*) CPLCalloc( 1, 2048 );
@@ -819,6 +823,8 @@ INGR_VirtualFile CPL_STDCALL INGR_CreateVirtualFile( const char *pszFilename,
             REVERSEBITSBUFFER( pabyBuffer, nBufferSize );
             VSILFILE *fpL = VSIFOpenL( hVirtual.pszFileName, "w+" );
             TIFF *hTIFF = VSI_TIFFOpen( hVirtual.pszFileName, "w+", fpL );
+            if( hTIFF == NULL ) /* shouldn't happen */
+                return hVirtual;
             TIFFSetField( hTIFF, TIFFTAG_IMAGEWIDTH,      nXSize );
             TIFFSetField( hTIFF, TIFFTAG_IMAGELENGTH,     nYSize );
             TIFFSetField( hTIFF, TIFFTAG_BITSPERSAMPLE,   1 );
@@ -844,13 +850,18 @@ INGR_VirtualFile CPL_STDCALL INGR_CreateVirtualFile( const char *pszFilename,
     if( hVirtual.poDS )
     {
         hVirtual.poBand = (GDALRasterBand*) GDALGetRasterBand( hVirtual.poDS, nBand );
+        if( hVirtual.poBand == NULL )
+        {
+            INGR_ReleaseVirtual(&hVirtual);
+            hVirtual.poDS = NULL;
+        }
     }
 
     return hVirtual;
 }
 
 // -----------------------------------------------------------------------------
-//                                                            INGR_ReleaseVirtual()
+//                                                       INGR_ReleaseVirtual()
 // -----------------------------------------------------------------------------
 
 void CPL_STDCALL INGR_ReleaseVirtual( INGR_VirtualFile *poTiffMem )
@@ -860,7 +871,7 @@ void CPL_STDCALL INGR_ReleaseVirtual( INGR_VirtualFile *poTiffMem )
 }
 
 // -----------------------------------------------------------------------------
-//                                                            INGR_ReleaseVirtual()
+//                                                       INGR_ReadJpegQuality()
 // -----------------------------------------------------------------------------
 
 int CPL_STDCALL INGR_ReadJpegQuality( VSILFILE *fp, uint32 nAppDataOfseet,
@@ -886,13 +897,20 @@ int CPL_STDCALL INGR_ReadJpegQuality( VSILFILE *fp, uint32 nAppDataOfseet,
 
         INGR_JPEGAppDataDiskToMem(&hJpegData, abyBuf);
 
+        if( hJpegData.RemainingLength == 0 ||
+            hJpegData.RemainingLength > INT_MAX ||
+            nNext > INT_MAX - hJpegData.RemainingLength )
+        {
+            return INGR_JPEGQDEFAULT;
+        }
+
         nNext += hJpegData.RemainingLength;
 
         if( nNext > ( nSeekLimit - SIZEOF_JPGAD ) )
         {
             return INGR_JPEGQDEFAULT;
         }
-    } 
+    }
     while( ! ( hJpegData.ApplicationType == 2 &&
         hJpegData.SubTypeCode == 12 ) );
 
@@ -907,7 +925,7 @@ int CPL_STDCALL INGR_ReadJpegQuality( VSILFILE *fp, uint32 nAppDataOfseet,
 //  Pass NULL as pabyDstData to obtain pnBytesConsumed and bypass decompression.
 // -----------------------------------------------------------------------------
 
-int CPL_STDCALL 
+int CPL_STDCALL
 INGR_Decode( INGR_Format eFormat, GByte *pabySrcData, GByte *pabyDstData,
              uint32 nSrcBytes, uint32 nBlockSize, uint32 *pnBytesConsumed )
 
@@ -921,7 +939,7 @@ INGR_Decode( INGR_Format eFormat, GByte *pabySrcData, GByte *pabyDstData,
 
       case RunLengthEncodedC:
         return INGR_DecodeRunLengthPaletted( pabySrcData,  pabyDstData,
-                                             nSrcBytes, nBlockSize, 
+                                             nSrcBytes, nBlockSize,
                                              pnBytesConsumed );
 
       default:
@@ -939,53 +957,47 @@ int CPL_STDCALL INGR_DecodeRunLength( GByte *pabySrcData, GByte *pabyDstData,
                                       uint32 nSrcBytes, uint32 nBlockSize,
                                       uint32 *pnBytesConsumed )
 {
-    signed char cAtomHead;
-
-    unsigned int nRun;
-    unsigned int i; 
-    unsigned int iInput;
-    unsigned int iOutput;
-    unsigned int inc;
-
-    iInput = 0;
-    iOutput = 0;
+    unsigned int iInput = 0;
+    unsigned int iOutput = 0;
 
     while( ( iInput < nSrcBytes ) && ( iOutput < nBlockSize ) )
     {
-        cAtomHead = (char) pabySrcData[iInput++];
+        const signed char cAtomHead = (char) pabySrcData[iInput++];
 
         if( cAtomHead > 0 )
         {
-            nRun = cAtomHead;
-            
+            const unsigned int nRun = cAtomHead;
+
             if (pabyDstData)
             {
-                for( i = 0; i < nRun && iInput < nSrcBytes && iOutput < nBlockSize; i++ )
+                for( unsigned int i = 0; i < nRun && iInput < nSrcBytes && iOutput < nBlockSize; i++ )
                 {
                     pabyDstData[iOutput++] = pabySrcData[iInput++];
                 }
             }
             else
             {
-                inc = MIN(nRun, MIN(nSrcBytes - iInput, nBlockSize - iOutput));
+                const unsigned int inc
+                    = MIN(nRun, MIN(nSrcBytes - iInput, nBlockSize - iOutput));
                 iInput += inc;
                 iOutput += inc;
             }
         }
         else if( cAtomHead < 0 )
         {
-            nRun = abs( cAtomHead );
+            const unsigned int nRun = abs( cAtomHead );
 
             if (pabyDstData)
             {
-                for( i = 0; i < nRun && iInput < nSrcBytes && iOutput < nBlockSize; i++ )
+                for( unsigned int i = 0; i < nRun && iInput < nSrcBytes && iOutput < nBlockSize; i++ )
                 {
                     pabyDstData[iOutput++] = pabySrcData[iInput];
                 }
             }
             else
             {
-                inc = MIN(nRun, MIN(nSrcBytes - iInput, nBlockSize - iOutput));
+                const unsigned int inc
+                    = MIN(nRun, MIN(nSrcBytes - iInput, nBlockSize - iOutput));
                 iOutput += inc;
             }
             iInput++;
@@ -1002,31 +1014,28 @@ int CPL_STDCALL INGR_DecodeRunLength( GByte *pabySrcData, GByte *pabyDstData,
 //                                                INGR_DecodeRunLengthPaletted()
 // -----------------------------------------------------------------------------
 
-int CPL_STDCALL 
+int CPL_STDCALL
 INGR_DecodeRunLengthPaletted( GByte *pabySrcData, GByte *pabyDstData,
-                              uint32 nSrcBytes, uint32 nBlockSize, 
+                              uint32 nSrcBytes, uint32 nBlockSize,
                               uint32 *pnBytesConsumed )
 {
-    unsigned short nColor;
-    unsigned short nCount;
-
-    unsigned int i; 
-    unsigned int iInput;
-    unsigned int iOutput;
-
-    unsigned short *pauiSrc = (unsigned short *) pabySrcData;
     unsigned int nSrcShorts = nSrcBytes / 2;
+    if (nSrcShorts == 0)
+    {
+        if( pnBytesConsumed != NULL )
+            *pnBytesConsumed = 0;
+        return 0;
+    }
 
-    iInput = 0;
-    iOutput = 0;
+    unsigned int iInput = 0;
+    unsigned int iOutput = 0;
 
-    if ( nSrcShorts == 0 )
-        return 0;
+    unsigned short *pauiSrc = (unsigned short *) pabySrcData;
 
     do
     {
-        nCount = 0;
-        nColor = CPL_LSBWORD16( pauiSrc[ iInput ] );
+        unsigned int nCount = 0;
+        unsigned int nColor = CPL_LSBWORD16( pauiSrc[ iInput ] );
         iInput++;
 
         if( nColor == 0x5900 ||
@@ -1044,7 +1053,7 @@ INGR_DecodeRunLengthPaletted( GByte *pabySrcData, GByte *pabyDstData,
 
         if (pabyDstData)
         {
-            for( i = 0; i < nCount && iOutput < nBlockSize; i++ )
+            for( unsigned int i = 0; i < nCount && iOutput < nBlockSize; i++ )
             {
                 pabyDstData[iOutput++] = (unsigned char) nColor;
             }
@@ -1066,31 +1075,27 @@ INGR_DecodeRunLengthPaletted( GByte *pabySrcData, GByte *pabyDstData,
 //                                                INGR_DecodeRunLengthBitonal()
 // -----------------------------------------------------------------------------
 
-int CPL_STDCALL 
+int CPL_STDCALL
 INGR_DecodeRunLengthBitonal( GByte *pabySrcData, GByte *pabyDstData,
                              uint32 nSrcBytes, uint32 nBlockSize,
                              uint32 *pnBytesConsumed )
 {
-    unsigned short i;
-    unsigned int   j;
+    const unsigned int nSrcShorts = nSrcBytes / 2;
+    if (nSrcShorts == 0)
+    {
+        if( pnBytesConsumed != NULL )
+            *pnBytesConsumed = 0;
+        return 0;
+    }
+
     unsigned int   iInput = 0;
     unsigned int   iOutput = 0;
     unsigned short *pauiSrc = (unsigned short *) pabySrcData;
-    unsigned int   nSrcShorts = nSrcBytes / 2;
-    unsigned short nRun;
-    unsigned char  nValue = 0;
     bool bHeader = true;
 
-    if (nSrcShorts == 0)
-        return 0;
-
-
     // Check for scanline header
     do
     {
-        unsigned int nWordsInScanline;
-        unsigned int nTotal;
-
         if( CPL_LSBWORD16(pauiSrc[0]) != 0x5900 )
         {
             bHeader = false;
@@ -1129,7 +1134,8 @@ INGR_DecodeRunLengthBitonal( GByte *pabySrcData, GByte *pabyDstData,
             break;
         }
 
-        nWordsInScanline = ((unsigned int) CPL_LSBWORD16(pauiSrc[1])) + 2;
+        unsigned int nWordsInScanline
+            = ((unsigned int) CPL_LSBWORD16(pauiSrc[1])) + 2;
         if (nSrcShorts >= nWordsInScanline + 5)
         {
             // Do some quick extra tests on next scanline.
@@ -1142,7 +1148,7 @@ INGR_DecodeRunLengthBitonal( GByte *pabySrcData, GByte *pabyDstData,
                 (CPL_LSBWORD16(pauiSrc[nWordsInScanline+1]) < 3) ||
                 ((CPL_LSBWORD16(pauiSrc[nWordsInScanline+1]) & 1) == 0) ||
                 (CPL_LSBWORD16(pauiSrc[nWordsInScanline+3]) != 0) ||
-                (((((unsigned int)CPL_LSBWORD16(pauiSrc[2])) + 1) & 0x0000FFFF) != 
+                (((((unsigned int)CPL_LSBWORD16(pauiSrc[2])) + 1) & 0x0000FFFF) !=
                    ((unsigned int)CPL_LSBWORD16(pauiSrc[nWordsInScanline+2]))))
             {
                 bHeader = false;
@@ -1155,12 +1161,14 @@ INGR_DecodeRunLengthBitonal( GByte *pabySrcData, GByte *pabyDstData,
             bHeader = false;
             break;
         }
+        if( nWordsInScanline < 4 )
+            return 0;
 
         // If we get here, we add all the span values and see if they add up to the nBlockSize.
-        j = 0;
-        nTotal = 0;
 
-        for(;j < nWordsInScanline - 4; j++)
+        unsigned int nTotal = 0;
+
+        for( unsigned int j = 0; j < nWordsInScanline - 4; j++)
         {
             nTotal += (unsigned int) CPL_LSBWORD16(pauiSrc[j+4]);
         }
@@ -1178,14 +1186,15 @@ INGR_DecodeRunLengthBitonal( GByte *pabySrcData, GByte *pabyDstData,
     if (iInput >= nSrcShorts)
         return 0;
 
+    unsigned char nValue = 0;
     do
     {
-        nRun = CPL_LSBWORD16(pauiSrc[ iInput ]);
+        unsigned short nRun = CPL_LSBWORD16(pauiSrc[ iInput ]);
         iInput++;
-               
+
         if (pabyDstData)
         {
-            for( i = 0; i < nRun && iOutput < nBlockSize; i++ )
+            for( unsigned short i = 0; i < nRun && iOutput < nBlockSize; i++ )
             {
                 pabyDstData[ iOutput++ ] = nValue;
             }
@@ -1196,7 +1205,6 @@ INGR_DecodeRunLengthBitonal( GByte *pabySrcData, GByte *pabyDstData,
         {
             iOutput += MIN(nRun, nBlockSize - iOutput);
         }
-        
     }
     while( ( iInput < nSrcShorts ) && ( iOutput < nBlockSize ) );
 
@@ -1208,9 +1216,9 @@ INGR_DecodeRunLengthBitonal( GByte *pabySrcData, GByte *pabyDstData,
 
         // Should never be pairs of consecutive empty spans,
         // except at end and start of two scanlines.
-        // We must adjust to start at the correct location in the 
+        // We must adjust to start at the correct location in the
         // next scanline, otherwise the colours will be inverted.
-        // iInput should be odd since scanline is 
+        // iInput should be odd since scanline is
         // supposed to start and end with OFF span.
         if ((iInput&1) == 0)
             iInput--;
@@ -1227,45 +1235,48 @@ INGR_DecodeRunLengthBitonal( GByte *pabySrcData, GByte *pabyDstData,
 //                                           INGR_DecodeRunLengthBitonalTiled()
 // -----------------------------------------------------------------------------
 
-int CPL_STDCALL 
+int CPL_STDCALL
 INGR_DecodeRunLengthBitonalTiled( GByte *pabySrcData, GByte *pabyDstData,
                                   uint32 nSrcBytes, uint32 nBlockSize,
                                   uint32 *pnBytesConsumed )
 {
-    unsigned short i; 
+    unsigned int   nSrcShorts = nSrcBytes / 2;
+    if (nSrcShorts == 0)
+    {
+        if( pnBytesConsumed != NULL )
+            *pnBytesConsumed = 0;
+        return 0;
+    }
+
     unsigned int   iInput = 0;
     unsigned int   iOutput = 0;
     unsigned short *pauiSrc = (unsigned short *) pabySrcData;
-    unsigned int   nSrcShorts = nSrcBytes / 2;
     unsigned short nRun = 0;
     unsigned char  nValue = 0;
     unsigned short previous = 0;
 
-    if (nSrcShorts == 0)
-        return 0;
 
     if( CPL_LSBWORD16(pauiSrc[0]) != 0x5900 )
     {
         nRun     = 256;
         nValue   = 0;
-        previous = 0;
         do
         {
             previous = nRun;
 
             nRun = CPL_LSBWORD16(pauiSrc[ iInput ]);
             iInput++;
-            
+
             if( nRun == 0 && previous == 0 ) // new line
             {
-                nValue = 0; 
+                nValue = 0;
             }
 
-            for( i = 0; i < nRun && iOutput < nBlockSize; i++ )
+            for( unsigned short i = 0; i < nRun && iOutput < nBlockSize; i++ )
             {
                 pabyDstData[ iOutput++ ] = nValue;
             }
-            
+
             if( nRun != 0 )
             {
                 nValue = ( nValue == 1 ? 0 : 1 );
@@ -1279,18 +1290,18 @@ INGR_DecodeRunLengthBitonalTiled( GByte *pabySrcData, GByte *pabyDstData,
         {
             nRun = CPL_LSBWORD16(pauiSrc[ iInput ]);
             iInput++;
-            
+
             if( nRun == 0x5900 )
             {
                 iInput+=3; // line id, data size, skip offset
                 continue;
             }
-            
-            for( i = 0; i < nRun && iOutput < nBlockSize; i++ )
+
+            for( unsigned short i = 0; i < nRun && iOutput < nBlockSize; i++ )
             {
                 pabyDstData[ iOutput++ ] = nValue;
             }
-            
+
             nValue = ( nValue == 1 ? 0 : 1 );
         }
         while( ( iInput < nSrcShorts ) && ( iOutput < nBlockSize ) );
@@ -1346,45 +1357,45 @@ void CPL_STDCALL INGR_HeaderOneDiskToMem(INGR_HeaderOne* pHeaderOne, const GByte
     CPL_LSBPTR16(&pHeaderOne->DataTypeModifier);
     switch (INGR_GetDataType(pHeaderOne->DataTypeCode))
     {
-    case GDT_Byte:    
+    case GDT_Byte:
         pHeaderOne->Minimum.AsUint8 = *(uint8*)&(pHeaderOne->Minimum);
-        pHeaderOne->Maximum.AsUint8 = *(uint8*)&(pHeaderOne->Maximum); 
+        pHeaderOne->Maximum.AsUint8 = *(uint8*)&(pHeaderOne->Maximum);
         break;
-    case GDT_Int16:   
+    case GDT_Int16:
         pHeaderOne->Minimum.AsUint16 = CPL_LSBWORD16(*(uint16*)&(pHeaderOne->Minimum));
-        pHeaderOne->Maximum.AsUint16 = CPL_LSBWORD16(*(uint16*)&(pHeaderOne->Maximum)); 
+        pHeaderOne->Maximum.AsUint16 = CPL_LSBWORD16(*(uint16*)&(pHeaderOne->Maximum));
         break;
-    case GDT_UInt16:  
+    case GDT_UInt16:
         pHeaderOne->Minimum.AsUint16 = CPL_LSBWORD16(*(uint16*)&(pHeaderOne->Minimum));
-        pHeaderOne->Maximum.AsUint16 = CPL_LSBWORD16(*(uint16*)&(pHeaderOne->Maximum)); 
+        pHeaderOne->Maximum.AsUint16 = CPL_LSBWORD16(*(uint16*)&(pHeaderOne->Maximum));
         break;
-    case GDT_Int32:   
+    case GDT_Int32:
         pHeaderOne->Minimum.AsUint32 = CPL_LSBWORD32(*(uint32*)&(pHeaderOne->Minimum));
-        pHeaderOne->Maximum.AsUint32 = CPL_LSBWORD32(*(uint32*)&(pHeaderOne->Maximum)); 
+        pHeaderOne->Maximum.AsUint32 = CPL_LSBWORD32(*(uint32*)&(pHeaderOne->Maximum));
         break;
-    case GDT_UInt32:  
+    case GDT_UInt32:
         pHeaderOne->Minimum.AsUint32 = CPL_LSBWORD32(*(uint32*)&(pHeaderOne->Minimum));
-        pHeaderOne->Maximum.AsUint32 = CPL_LSBWORD32(*(uint32*)&(pHeaderOne->Maximum)); 
+        pHeaderOne->Maximum.AsUint32 = CPL_LSBWORD32(*(uint32*)&(pHeaderOne->Maximum));
         break;
         /* FIXME ? I'm not sure this is correct for floats */
-    case GDT_Float32: 
+    case GDT_Float32:
         pHeaderOne->Minimum.AsUint32 = CPL_LSBWORD32(*(uint32*)&(pHeaderOne->Minimum));
-        pHeaderOne->Maximum.AsUint32 = CPL_LSBWORD32(*(uint32*)&(pHeaderOne->Maximum)); 
+        pHeaderOne->Maximum.AsUint32 = CPL_LSBWORD32(*(uint32*)&(pHeaderOne->Maximum));
         break;
-    case GDT_Float64: 
-        CPL_LSBPTR64(&pHeaderOne->Minimum.AsReal64); CPL_LSBPTR64(&pHeaderOne->Maximum.AsReal64); 
+    case GDT_Float64:
+        CPL_LSBPTR64(&pHeaderOne->Minimum.AsReal64); CPL_LSBPTR64(&pHeaderOne->Maximum.AsReal64);
         break;
     default: break;
     }
 #endif
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Convert WAX REAL*8 to IEEE double
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     if( pHeaderOne->GridFileVersion == 1 ||
-      ( pHeaderOne->GridFileVersion == 2 && 
-        ( pHeaderOne->TransformationMatrix[10] != 1.0 && 
+      ( pHeaderOne->GridFileVersion == 2 &&
+        ( pHeaderOne->TransformationMatrix[10] != 1.0 &&
           pHeaderOne->TransformationMatrix[15] != 1.0 ) ) )
     {
         INGR_DGN2IEEEDouble( &pHeaderOne->XViewOrigin );
@@ -1396,9 +1407,7 @@ void CPL_STDCALL INGR_HeaderOneDiskToMem(INGR_HeaderOne* pHeaderOne, const GByte
         INGR_DGN2IEEEDouble( &pHeaderOne->RotationAngle );
         INGR_DGN2IEEEDouble( &pHeaderOne->SkewAngle );
 
-        uint8 i;
-
-        for( i = 0; i < 16; i++ )
+        for( uint8 i = 0; i < 16; i++ )
         {
             INGR_DGN2IEEEDouble( &pHeaderOne->TransformationMatrix[i]);
         }
@@ -1415,9 +1424,7 @@ void CPL_STDCALL INGR_HeaderOneDiskToMem(INGR_HeaderOne* pHeaderOne, const GByte
         CPL_LSBPTR64( &pHeaderOne->RotationAngle );
         CPL_LSBPTR64( &pHeaderOne->SkewAngle );
 
-        uint8 i;
-
-        for( i = 0; i < 16; i++ )
+        for( uint8 i = 0; i < 16; i++ )
         {
             CPL_LSBPTR64( &pHeaderOne->TransformationMatrix[i]);
         }
@@ -1471,9 +1478,7 @@ void CPL_STDCALL INGR_HeaderOneMemToDisk(const INGR_HeaderOne* pHeaderOne, GByte
         CPL_LSBPTR64( &pLSBHeaderOne->RotationAngle );
         CPL_LSBPTR64( &pLSBHeaderOne->SkewAngle );
 
-        uint8 i;
-
-        for( i = 0; i < 16; i++ )
+        for( uint8 i = 0; i < 16; i++ )
         {
             CPL_LSBPTR64( &pLSBHeaderOne->TransformationMatrix[i]);
         }
@@ -1519,21 +1524,21 @@ void CPL_STDCALL INGR_HeaderTwoADiskToMem(INGR_HeaderTwoA* pHeaderTwo, const GBy
 {
     unsigned int n = 0;
 
-    BUF2STRC( pabyBuf, n, pHeaderTwo->Gain );                    
-    BUF2STRC( pabyBuf, n, pHeaderTwo->OffsetThreshold );         
-    BUF2STRC( pabyBuf, n, pHeaderTwo->View1 );                   
-    BUF2STRC( pabyBuf, n, pHeaderTwo->View2 );                   
-    BUF2STRC( pabyBuf, n, pHeaderTwo->ViewNumber );              
-    BUF2STRC( pabyBuf, n, pHeaderTwo->Reserved2 );               
-    BUF2STRC( pabyBuf, n, pHeaderTwo->Reserved3 );               
-    BUF2STRC( pabyBuf, n, pHeaderTwo->AspectRatio );             
-    BUF2STRC( pabyBuf, n, pHeaderTwo->CatenatedFilePointer );    
-    BUF2STRC( pabyBuf, n, pHeaderTwo->ColorTableType );          
-    BUF2STRC( pabyBuf, n, pHeaderTwo->Reserved8 );               
-    BUF2STRC( pabyBuf, n, pHeaderTwo->NumberOfCTEntries );       
+    BUF2STRC( pabyBuf, n, pHeaderTwo->Gain );
+    BUF2STRC( pabyBuf, n, pHeaderTwo->OffsetThreshold );
+    BUF2STRC( pabyBuf, n, pHeaderTwo->View1 );
+    BUF2STRC( pabyBuf, n, pHeaderTwo->View2 );
+    BUF2STRC( pabyBuf, n, pHeaderTwo->ViewNumber );
+    BUF2STRC( pabyBuf, n, pHeaderTwo->Reserved2 );
+    BUF2STRC( pabyBuf, n, pHeaderTwo->Reserved3 );
+    BUF2STRC( pabyBuf, n, pHeaderTwo->AspectRatio );
+    BUF2STRC( pabyBuf, n, pHeaderTwo->CatenatedFilePointer );
+    BUF2STRC( pabyBuf, n, pHeaderTwo->ColorTableType );
+    BUF2STRC( pabyBuf, n, pHeaderTwo->Reserved8 );
+    BUF2STRC( pabyBuf, n, pHeaderTwo->NumberOfCTEntries );
     BUF2STRC( pabyBuf, n, pHeaderTwo->ApplicationPacketPointer );
-    BUF2STRC( pabyBuf, n, pHeaderTwo->ApplicationPacketLength ); 
-    BUF2STRC( pabyBuf, n, pHeaderTwo->Reserved );           
+    BUF2STRC( pabyBuf, n, pHeaderTwo->ApplicationPacketLength );
+    BUF2STRC( pabyBuf, n, pHeaderTwo->Reserved );
 
 #if defined(CPL_MSB)
     CPL_LSBPTR64(&pHeaderTwo->AspectRatio);
@@ -1563,21 +1568,21 @@ void CPL_STDCALL INGR_HeaderTwoAMemToDisk(const INGR_HeaderTwoA* pHeaderTwo, GBy
     pLSBHeaderTwo = (INGR_HeaderTwoA* )pHeaderTwo;
 #endif
 
-    STRC2BUF( pabyBuf, n, pLSBHeaderTwo->Gain );                    
-    STRC2BUF( pabyBuf, n, pLSBHeaderTwo->OffsetThreshold );         
-    STRC2BUF( pabyBuf, n, pLSBHeaderTwo->View1 );                   
-    STRC2BUF( pabyBuf, n, pLSBHeaderTwo->View2 );                   
-    STRC2BUF( pabyBuf, n, pLSBHeaderTwo->ViewNumber );              
-    STRC2BUF( pabyBuf, n, pLSBHeaderTwo->Reserved2 );               
-    STRC2BUF( pabyBuf, n, pLSBHeaderTwo->Reserved3 );               
-    STRC2BUF( pabyBuf, n, pLSBHeaderTwo->AspectRatio );             
-    STRC2BUF( pabyBuf, n, pLSBHeaderTwo->CatenatedFilePointer );    
-    STRC2BUF( pabyBuf, n, pLSBHeaderTwo->ColorTableType );          
-    STRC2BUF( pabyBuf, n, pLSBHeaderTwo->Reserved8 );               
-    STRC2BUF( pabyBuf, n, pLSBHeaderTwo->NumberOfCTEntries );       
+    STRC2BUF( pabyBuf, n, pLSBHeaderTwo->Gain );
+    STRC2BUF( pabyBuf, n, pLSBHeaderTwo->OffsetThreshold );
+    STRC2BUF( pabyBuf, n, pLSBHeaderTwo->View1 );
+    STRC2BUF( pabyBuf, n, pLSBHeaderTwo->View2 );
+    STRC2BUF( pabyBuf, n, pLSBHeaderTwo->ViewNumber );
+    STRC2BUF( pabyBuf, n, pLSBHeaderTwo->Reserved2 );
+    STRC2BUF( pabyBuf, n, pLSBHeaderTwo->Reserved3 );
+    STRC2BUF( pabyBuf, n, pLSBHeaderTwo->AspectRatio );
+    STRC2BUF( pabyBuf, n, pLSBHeaderTwo->CatenatedFilePointer );
+    STRC2BUF( pabyBuf, n, pLSBHeaderTwo->ColorTableType );
+    STRC2BUF( pabyBuf, n, pLSBHeaderTwo->Reserved8 );
+    STRC2BUF( pabyBuf, n, pLSBHeaderTwo->NumberOfCTEntries );
     STRC2BUF( pabyBuf, n, pLSBHeaderTwo->ApplicationPacketPointer );
-    STRC2BUF( pabyBuf, n, pLSBHeaderTwo->ApplicationPacketLength ); 
-    STRC2BUF( pabyBuf, n, pLSBHeaderTwo->Reserved );           
+    STRC2BUF( pabyBuf, n, pLSBHeaderTwo->ApplicationPacketLength );
+    STRC2BUF( pabyBuf, n, pLSBHeaderTwo->Reserved );
 
 #if defined(CPL_MSB)
     CPLFree(pLSBHeaderTwo);
@@ -1597,7 +1602,7 @@ void CPL_STDCALL INGR_TileHeaderDiskToMem(INGR_TileHeader* pTileHeader, const GB
     BUF2STRC( pabyBuf, n, pTileHeader->Properties );
     BUF2STRC( pabyBuf, n, pTileHeader->DataTypeCode );
     BUF2STRC( pabyBuf, n, pTileHeader->Reserved2 );
-    BUF2STRC( pabyBuf, n, pTileHeader->TileSize ); 
+    BUF2STRC( pabyBuf, n, pTileHeader->TileSize );
     BUF2STRC( pabyBuf, n, pTileHeader->Reserved3 );
     BUF2STRC( pabyBuf, n, pTileHeader->First.Start );
     BUF2STRC( pabyBuf, n, pTileHeader->First.Allocated );
@@ -1652,7 +1657,6 @@ void CPL_STDCALL INGR_JPEGAppDataDiskToMem(INGR_JPEGAppData* pJPEGAppData, const
 #endif
 }
 
-
 //  ------------------------------------------------------------------
 //    Pasted from the DNG OGR Driver to avoid dependency on OGR
 //  ------------------------------------------------------------------
@@ -1708,7 +1712,7 @@ void    INGR_DGN2IEEEDouble(void * dbl)
     sign         = dt.hi & 0x80000000;
 
 /* -------------------------------------------------------------------- */
-/*      Adjust the exponent so that we may work with it                 */      
+/*      Adjust the exponent so that we may work with it                 */
 /* -------------------------------------------------------------------- */
     exponent = dt.hi >> 23;
     exponent = exponent & 0x000000ff;
@@ -1720,7 +1724,7 @@ void    INGR_DGN2IEEEDouble(void * dbl)
 /*      Save the bits that we are discarding so we can round properly   */
 /* -------------------------------------------------------------------- */
     rndbits = dt.lo & 0x00000007;
-        
+
     dt.lo = dt.lo >> 3;
     dt.lo = (dt.lo & 0x1fffffff) | (dt.hi << 29);
 
@@ -1734,8 +1738,6 @@ void    INGR_DGN2IEEEDouble(void * dbl)
     dt.hi = dt.hi & 0x000fffff;
     dt.hi = dt.hi | (exponent << 20) | sign;
 
-
-
 #ifdef CPL_LSB
 /* -------------------------------------------------------------------- */
 /*      Change the number to a byte swapped format                      */
@@ -1743,14 +1745,8 @@ void    INGR_DGN2IEEEDouble(void * dbl)
     src = (unsigned char *) &dt;
     dest = (unsigned char *) dbl;
 
-    dest[0] = src[4];
-    dest[1] = src[5];
-    dest[2] = src[6];
-    dest[3] = src[7];
-    dest[4] = src[0];
-    dest[5] = src[1];
-    dest[6] = src[2];
-    dest[7] = src[3];
+    memcpy(dest + 0, src + 4, 4);
+    memcpy(dest + 4, src + 0, 4);
 #else
     memcpy( dbl, &dt, 8 );
 #endif
diff --git a/frmts/ingr/IngrTypes.h b/frmts/ingr/IngrTypes.h
index 70c9ffb..79ce8cf 100644
--- a/frmts/ingr/IngrTypes.h
+++ b/frmts/ingr/IngrTypes.h
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * $Id: IngrTypes.h 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: IngrTypes.h 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Intergraph Raster Format support
  * Purpose:  Types, constants and functions definition
@@ -35,7 +35,7 @@
 #include "cpl_port.h"
 #include "gdal.h"
 #include "gdal_priv.h"
-#include "math.h"
+#include <cmath>
 
 CPL_C_START
 #include "tiffio.h"
@@ -69,25 +69,25 @@ typedef float               real32;
 
 typedef struct {
 #if defined(CPL_LSB)
-    uint16 Version   : 6;        // ??????00 00000000 
-    uint16 Is2Dor3D  : 2;        // 000000?? 00000000 
+    uint16 Version   : 6;        // ??????00 00000000
+    uint16 Is2Dor3D  : 2;        // 000000?? 00000000
 #else
-    uint16 Is2Dor3D  : 2;        // 000000?? 00000000 
-    uint16 Version   : 6;        // ??????00 00000000 
+    uint16 Is2Dor3D  : 2;        // 000000?? 00000000
+    uint16 Version   : 6;        // ??????00 00000000
 #endif
-    uint16 Type      : 8;        // 00000000 ???????? 
+    uint16 Type      : 8;        // 00000000 ????????
 } INGR_HeaderType;
 
 //  ----------------------------------------------------------------------------
 //    Data type dependent Minimum and Maximum type
 //  ----------------------------------------------------------------------------
 
-typedef union 
+typedef union
 {
-    uint8   AsUint8;          
-    uint16  AsUint16;          
-    uint32  AsUint32;          
-    real32  AsReal32;          
+    uint8   AsUint8;
+    uint16  AsUint16;
+    uint32  AsUint32;
+    real32  AsReal32;
     real64  AsReal64;
 } INGR_MinMax;
 
@@ -96,38 +96,39 @@ typedef union
 //  ----------------------------------------------------------------------------
 
 typedef enum {
-    PackedBinary                     = 1,   // 1 bit / pixel  
-    ByteInteger                      = 2,   // 8 bits / pixel  
-    WordIntegers                     = 3,   // 16 bits / pixel  
-    Integers32Bit                    = 4,     
-    FloatingPoint32Bit               = 5,     
-    FloatingPoint64Bit               = 6,     
-    Complex                          = 7,   // 64 bits / pixel  
-    DoublePrecisionComplex           = 8,     
-    RunLengthEncoded                 = 9,   // Bi-level Images  
-    RunLengthEncodedC                = 10,  // Gray Scale, Color  
-    FigureOfMerit                    = 11,  // FOM  
-    DTMFlags                         = 12,    
-    RLEVariableValuesWithZS          = 13,  // Simple  
-    RLEBinaryValues                  = 14,  // w/ Edge Type  
-    RLEVariableValues                = 15,  // w/ Edge Type  
-    RLEVariableValuesWithZ           = 16,  // w/ Edge Type  
-    RLEVariableValuesC               = 17,  // Color Table and Shade  
-    RLEVariableValuesN               = 18,  // w/ Normals  
-    QuadTreeEncoded                  = 19,    
-    CCITTGroup4                      = 24,  // Bi-level Images  
-    RunLengthEncodedRGB              = 25,  // Full Color  
-    VariableRunLength                = 26,    
-    AdaptiveRGB                      = 27,  // Full Color  
-    Uncompressed24bit                = 28,  // Full Color  
-    AdaptiveGrayScale                = 29,    
-    JPEGGRAY                         = 30,  // Gray Scale  
-    JPEGRGB                          = 31,  // Full Color RGB  
-    JPEGCYMK                         = 32,  // CYMK  
+    IngrUnknownFrmt                  = 0,
+    PackedBinary                     = 1,   // 1 bit / pixel
+    ByteInteger                      = 2,   // 8 bits / pixel
+    WordIntegers                     = 3,   // 16 bits / pixel
+    Integers32Bit                    = 4,
+    FloatingPoint32Bit               = 5,
+    FloatingPoint64Bit               = 6,
+    Complex                          = 7,   // 64 bits / pixel
+    DoublePrecisionComplex           = 8,
+    RunLengthEncoded                 = 9,   // Bi-level Images
+    RunLengthEncodedC                = 10,  // Gray Scale, Color
+    FigureOfMerit                    = 11,  // FOM
+    DTMFlags                         = 12,
+    RLEVariableValuesWithZS          = 13,  // Simple
+    RLEBinaryValues                  = 14,  // w/ Edge Type
+    RLEVariableValues                = 15,  // w/ Edge Type
+    RLEVariableValuesWithZ           = 16,  // w/ Edge Type
+    RLEVariableValuesC               = 17,  // Color Table and Shade
+    RLEVariableValuesN               = 18,  // w/ Normals
+    QuadTreeEncoded                  = 19,
+    CCITTGroup4                      = 24,  // Bi-level Images
+    RunLengthEncodedRGB              = 25,  // Full Color
+    VariableRunLength                = 26,
+    AdaptiveRGB                      = 27,  // Full Color
+    Uncompressed24bit                = 28,  // Full Color
+    AdaptiveGrayScale                = 29,
+    JPEGGRAY                         = 30,  // Gray Scale
+    JPEGRGB                          = 31,  // Full Color RGB
+    JPEGCMYK                         = 32,  // CMYK
     TiledRasterData                  = 65,  // See tile directory Data Type Code (DTC)
-    NotUsedReserved                  = 66,   
-    ContinuousTone                   = 67,  // CYMK  
-    LineArt                          = 68   // CYMK/RGB  
+    NotUsedReserved                  = 66,
+    ContinuousTone                   = 67,  // CMYK
+    LineArt                          = 68   // CMYK/RGB
 } INGR_Format;
 
 struct INGR_FormatDescription {
@@ -143,16 +144,16 @@ struct INGR_FormatDescription {
 //  ----------------------------------------------------------------------------
 
 typedef enum {
-    GenericRasterImageFile           = 0, 
-    DigitalTerrainModeling           = 1, 
-    GridDataUtilities                = 2, 
-    DrawingScanning                  = 3, 
-    ImageProcessing                  = 4, 
-    HiddenSurfaces                   = 5, 
-    ImagitexScannerProduct           = 6, 
-    ScreenCopyPlotting               = 7, 
-    IMAGEandMicroStationImager       = 8, 
-    ModelView                        = 9 
+    GenericRasterImageFile           = 0,
+    DigitalTerrainModeling           = 1,
+    GridDataUtilities                = 2,
+    DrawingScanning                  = 3,
+    ImageProcessing                  = 4,
+    HiddenSurfaces                   = 5,
+    ImagitexScannerProduct           = 6,
+    ScreenCopyPlotting               = 7,
+    IMAGEandMicroStationImager       = 8,
+    ModelView                        = 9
 } INGR_Application;
 
 //  ----------------------------------------------------------------------------
@@ -175,23 +176,23 @@ typedef enum {
 //  ----------------------------------------------------------------------------
 
 typedef enum {
-    HasLineHeader                    = 1,   
-    // Every line of raster data has a 4 word 
+    HasLineHeader                    = 1,
+    // Every line of raster data has a 4 word
     // raster line header at the beginning of
-    // the line. In the line header, the Words 
+    // the line. In the line header, the Words
     // to Follow field specifies the amount
-    // of data following the field, indicating 
+    // of data following the field, indicating
     // the start of the next scanline of raster
     // data
-    NoLineHeader                     = 0    
-    // No raster line headers exist. The application 
-    // must calculate where lines of raster data 
-    // start and end. This process is simple for 
-    // non-run length encoded data. It is a fixed 
-    // value; therefore, the line length can be 
-    // calculated from the data type ( DTC ) and 
-    // the number of pixels per line ( PPL ). In 
-    // a run length compression case, the data must 
+    NoLineHeader                     = 0
+    // No raster line headers exist. The application
+    // must calculate where lines of raster data
+    // start and end. This process is simple for
+    // non-run length encoded data. It is a fixed
+    // value; therefore, the line length can be
+    // calculated from the data type ( DTC ) and
+    // the number of pixels per line ( PPL ). In
+    // a run length compression case, the data must
     // be decoded to find the end of a raster line.
 } INGR_IndexingMethod;
 
@@ -234,33 +235,33 @@ struct igds_slot
 //  ----------------------------------------------------------------------------
 
 typedef struct {
-    INGR_HeaderType     HeaderType;                 
-    uint16              WordsToFollow;              
-    uint16              DataTypeCode;               
-    uint16              ApplicationType;            
-    real64              XViewOrigin;                
-    real64              YViewOrigin;                
-    real64              ZViewOrigin;                
-    real64              XViewExtent;                
-    real64              YViewExtent;                
-    real64              ZViewExtent;                
-    real64              TransformationMatrix[16];   
-    uint32              PixelsPerLine;              
-    uint32              NumberOfLines;              
-    int16               DeviceResolution;           
-    uint8               ScanlineOrientation;        
-    uint8               ScannableFlag;              
-    real64              RotationAngle;              
-    real64              SkewAngle;                  
-    uint16              DataTypeModifier;           
-    char                DesignFileName[66];         
-    char                DataBaseFileName[66];       
-    char                ParentGridFileName[66];     
-    char                FileDescription[80];        
-    INGR_MinMax         Minimum;                    
-    INGR_MinMax         Maximum;                    
-    char                Reserved[3];                
-    uint8               GridFileVersion;            
+    INGR_HeaderType     HeaderType;
+    uint16              WordsToFollow;
+    uint16              DataTypeCode;
+    uint16              ApplicationType;
+    real64              XViewOrigin;
+    real64              YViewOrigin;
+    real64              ZViewOrigin;
+    real64              XViewExtent;
+    real64              YViewExtent;
+    real64              ZViewExtent;
+    real64              TransformationMatrix[16];
+    uint32              PixelsPerLine;
+    uint32              NumberOfLines;
+    int16               DeviceResolution;
+    uint8               ScanlineOrientation;
+    uint8               ScannableFlag;
+    real64              RotationAngle;
+    real64              SkewAngle;
+    uint16              DataTypeModifier;
+    char                DesignFileName[66];
+    char                DataBaseFileName[66];
+    char                ParentGridFileName[66];
+    char                FileDescription[80];
+    INGR_MinMax         Minimum;
+    INGR_MinMax         Maximum;
+    char                Reserved[3];
+    uint8               GridFileVersion;
 } INGR_HeaderOne;
 
 //  ----------------------------------------------------------------------------
@@ -268,25 +269,25 @@ typedef struct {
 //  ----------------------------------------------------------------------------
 
 typedef struct {
-    uint8               Gain;                       
-    uint8               OffsetThreshold;            
-    uint8               View1;                      
-    uint8               View2;                      
-    uint8               ViewNumber;                 
-    uint8               Reserved2;                  
-    uint16              Reserved3;                  
-    real64              AspectRatio;                
-    uint32              CatenatedFilePointer;       
-    uint16              ColorTableType;             
-    uint16              Reserved8;                  
-    uint32              NumberOfCTEntries;          
-    uint32              ApplicationPacketPointer;   
-    uint32              ApplicationPacketLength;    
-    uint16              Reserved[110];              
+    uint8               Gain;
+    uint8               OffsetThreshold;
+    uint8               View1;
+    uint8               View2;
+    uint8               ViewNumber;
+    uint8               Reserved2;
+    uint16              Reserved3;
+    real64              AspectRatio;
+    uint32              CatenatedFilePointer;
+    uint16              ColorTableType;
+    uint16              Reserved8;
+    uint32              NumberOfCTEntries;
+    uint32              ApplicationPacketPointer;
+    uint32              ApplicationPacketLength;
+    uint16              Reserved[110];
 } INGR_HeaderTwoA;
 
 typedef    struct {
-    uint16              ApplicationData[128];       
+    uint16              ApplicationData[128];
 } INGR_HeaderTwoB;
 
 //  ----------------------------------------------------------------------------
@@ -298,7 +299,7 @@ typedef    struct {
 } INGR_ColorTable256;
 
 //  ----------------------------------------------------------------------------
-//    Extra Block( s ) for dynamic allocated color table with intensit level entries
+//    Extra Block(s) for dynamic allocated color table with intensity level entries.
 //  ----------------------------------------------------------------------------
 
 typedef    struct {
@@ -319,7 +320,8 @@ typedef     struct {
 //    Tile Directory Header
 //  ----------------------------------------------------------------------------
 
-typedef    struct {
+typedef struct INGR_TileHeader {
+    INGR_TileHeader();
     uint16              ApplicationType;
     uint16              SubTypeCode;
     uint32              WordsToFollow;
@@ -329,7 +331,7 @@ typedef    struct {
     uint16              Properties;
     uint16              DataTypeCode;
     uint8               Reserved2[100];
-    uint32              TileSize; 
+    uint32              TileSize;
     uint32              Reserved3;
     INGR_TileItem       First;
 } INGR_TileHeader;
@@ -355,7 +357,7 @@ typedef     struct {
             |     512     |
             |             |
             +-------------+  -  512  -  Header Block Two ( First Half )
-            |     256     |             
+            |     256     |
             +-------------+  -  768  -  Header Block Two ( Second Half )
             |     256     |             ( Application Data )
             +-------------+  -  1024 -  Extra Header Info or Image Data
@@ -367,12 +369,12 @@ typedef     struct {
             |     512     |
             |             |
             +-------------+  -  512  -  Header Block Two ( First Half )
-            |     256     |             
+            |     256     |
             +-------------+  -  768  -  IGDS 256 Entries
-            |     768     |             Color Table 
+            |     768     |             Color Table
             |             |
             |             |
-            +-------------+  -  1536 -  Extra Header Info or Image Data  
+            +-------------+  -  1536 -  Extra Header Info or Image Data
             |     ...     |
 
                    Headers Blocks with EnvironV Color Table
@@ -381,13 +383,13 @@ typedef     struct {
             |     512     |
             |             |
             +-------------+  -  512  -  Header Block Two
-            |     512     |             
-            |             |                             
+            |     512     |
+            |             |
             +-------------+  -  1024 -  EnvironV Color
             :   n x 512   :             Table
             :             :
             :             :
-            +-------------+  ( n+2 )x512  - Extra Header Info or Image Data  
+            +-------------+  ( n+2 )x512  - Extra Header Info or Image Data
             |     ...     |
 
 */
@@ -414,7 +416,7 @@ typedef     struct {
 void   INGR_DGN2IEEEDouble(void * dbl);
 
 //  ------------------------------------------------------------------
-//    Compression, Data Format, Data Type related funtions
+//    Compression, Data Format, Data Type related functions
 //  ------------------------------------------------------------------
 
 uint32 CPL_STDCALL INGR_GetDataBlockSize( const char *pszFileName,
@@ -428,7 +430,7 @@ uint32 CPL_STDCALL INGR_GetTileDirectory( VSILFILE *fp,
                                           INGR_TileHeader *pTileDir,
                                           INGR_TileItem **pahTiles);
 
-INGR_Format CPL_STDCALL INGR_GetFormat( GDALDataType eType, 
+INGR_Format CPL_STDCALL INGR_GetFormat( GDALDataType eType,
                                         const char *pszCompression );
 
 const char * CPL_STDCALL INGR_GetFormatName( uint16 eCode );
@@ -441,9 +443,9 @@ const char * CPL_STDCALL INGR_GetOrientation( uint8 nIndex );
 //    Transformation Matrix conversion
 //  ------------------------------------------------------------------
 
-void CPL_STDCALL INGR_GetTransMatrix( INGR_HeaderOne *pHeaderOne, 
+void CPL_STDCALL INGR_GetTransMatrix( INGR_HeaderOne *pHeaderOne,
                                       double *padfGeoTransform );
-void CPL_STDCALL INGR_SetTransMatrix( real64 *padfMatrix, 
+void CPL_STDCALL INGR_SetTransMatrix( real64 *padfMatrix,
                                       double *padfGeoTransform );
 
 //  ------------------------------------------------------------------
@@ -476,27 +478,27 @@ double CPL_STDCALL INGR_GetMinMax( GDALDataType eType, INGR_MinMax hVal );
 //  ------------------------------------------------------------------
 
 int CPL_STDCALL
-INGR_Decode( INGR_Format eFormat, 
+INGR_Decode( INGR_Format eFormat,
              GByte *pabySrcData, GByte *pabyDstData,
              uint32 nSrcBytes, uint32 nBlockSize,
              uint32 *pnBytesConsumed );
 
-int CPL_STDCALL 
+int CPL_STDCALL
 INGR_DecodeRunLength( GByte *pabySrcData, GByte *pabyDstData,
                       uint32 nSrcBytes, uint32 nBlockSize,
                       uint32 *pnBytesConsumed );
 
-int CPL_STDCALL 
+int CPL_STDCALL
 INGR_DecodeRunLengthBitonal( GByte *pabySrcData, GByte *pabyDstData,
                              uint32 nSrcBytes, uint32 nBlockSize,
                              uint32 *pnBytesConsumed );
 
-int CPL_STDCALL 
+int CPL_STDCALL
 INGR_DecodeRunLengthBitonalTiled( GByte *pabySrcData, GByte *pabyDstData,
                                   uint32 nSrcBytes, uint32 nBlockSize,
                                   uint32 *pnBytesConsumed );
 
-int CPL_STDCALL 
+int CPL_STDCALL
 INGR_DecodeRunLengthPaletted( GByte *pabySrcData, GByte *pabyDstData,
                               uint32 nSrcBytes, uint32 nBlockSize,
                               uint32 *pnBytesConsumed );
@@ -509,7 +511,7 @@ INGR_DecodeRunLengthPaletted( GByte *pabySrcData, GByte *pabyDstData,
 
 INGR_VirtualFile CPL_STDCALL INGR_CreateVirtualFile( const char *pszFilename,
                                                      INGR_Format eFormat,
-                                                     int nXSize, 
+                                                     int nXSize,
                                                      int nYSize,
                                                      int nTileSize,
                                                      int nQuality,
@@ -551,7 +553,7 @@ typedef     struct {
     memcpy( &ff, &bb[nn], ss);  \
     nn += ss;                   \
 }
-    
+
 #define STRC2BUF(bb, nn, ff)    \
 {                               \
     int ss = sizeof(ff);        \
@@ -572,4 +574,3 @@ void CPL_STDCALL INGR_TileItemDiskToMem(INGR_TileItem* pTileItem, const GByte *p
 void CPL_STDCALL INGR_JPEGAppDataDiskToMem(INGR_JPEGAppData* pJPEGAppData, const GByte *pabyBuf);
 
 #endif
-
diff --git a/frmts/ingr/IntergraphBand.cpp b/frmts/ingr/IntergraphBand.cpp
index 3cb1422..ab53179 100644
--- a/frmts/ingr/IntergraphBand.cpp
+++ b/frmts/ingr/IntergraphBand.cpp
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * $Id: IntergraphBand.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: IntergraphBand.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Intergraph Raster Format support
  * Purpose:  Read/Write Intergraph Raster Format, band support
@@ -35,49 +35,83 @@
 #include "ogr_spatialref.h"
 #include "gdal_pam.h"
 #include "gdal_alg.h"
-#include "math.h"
+#include <cmath>
 
 #include "IntergraphDataset.h"
 #include "IntergraphBand.h"
 #include "IngrTypes.h"
 
+#include <algorithm>
+
+using std::fill;
+
 //  ----------------------------------------------------------------------------
 //                                  IntergraphRasterBand::IntergraphRasterBand()
 //  ----------------------------------------------------------------------------
 
-IntergraphRasterBand::IntergraphRasterBand( IntergraphDataset *poDS, 
-                                            int nBand,
+INGR_TileHeader::INGR_TileHeader() :
+    ApplicationType(0),
+    SubTypeCode(0),
+    WordsToFollow(0),
+    PacketVersion(0),
+    Identifier(0),
+    Properties(0),
+    DataTypeCode(0),
+    TileSize(0),
+    Reserved3(0)
+{
+    fill( Reserved, Reserved + CPL_ARRAYSIZE(Reserved), 0 );
+    fill( Reserved2, Reserved2 + CPL_ARRAYSIZE(Reserved2), 0 );
+    First.Start = 0;
+    First.Allocated = 0;
+    First.Used = 0;
+}
+
+IntergraphRasterBand::IntergraphRasterBand( IntergraphDataset *poDSIn,
+                                            int nBandIn,
                                             int nBandOffset,
-                                            GDALDataType eType )
+                                            GDALDataType eType ) :
+    poColorTable(NULL),
+    nDataOffset(0),
+    nBlockBufSize(0),
+    nBandStart(nBandOffset),
+    nRGBIndex(0),
+    eFormat(IngrUnknownFrmt),
+    bTiled(FALSE),
+    nFullBlocksX(0),
+    nFullBlocksY(0),
+    pabyBlockBuf(NULL),
+    nTiles(0),
+    pahTiles(NULL),
+    nRLEOffset(0)
 {
     this->poColorTable  = new GDALColorTable();
+    this->poDS          = poDSIn;
+    this->nBand         = nBandIn != 0 ? nBandIn : poDSIn->nBands;
+    eDataType     = eType;
 
-    this->poDS          = poDS;
-    this->nBand         = nBand != 0 ? nBand : poDS->nBands;
-    this->nTiles        = 0;
-    this->eDataType     = eType;
-    this->pabyBlockBuf  = NULL;
-    this->pahTiles      = NULL;
-    this->nRGBIndex     = 0;
-    this->nBandStart    = nBandOffset;
-    this->bTiled        = FALSE;
-
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Get Header Info
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
-    memcpy(&hHeaderOne, &poDS->hHeaderOne, sizeof(hHeaderOne));
-    memcpy(&hHeaderTwo, &poDS->hHeaderTwo, sizeof(hHeaderTwo));
+    memcpy(&hHeaderOne, &poDSIn->hHeaderOne, sizeof(hHeaderOne));
+    memcpy(&hHeaderTwo, &poDSIn->hHeaderTwo, sizeof(hHeaderTwo));
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Get the image start from Words to Follow (WTF)
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
+    if( nBandOffset > INT_MAX - (2 + ( 2 * ( hHeaderOne.WordsToFollow + 1 ) )) )
+    {
+        pabyBlockBuf = NULL;
+        CPLError(CE_Failure, CPLE_AppDefined, "Invalid header values");
+        return;
+    }
 
     nDataOffset = nBandOffset + 2 + ( 2 * ( hHeaderOne.WordsToFollow + 1 ) );
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Get Color Tabel from Color Table Type (CTV)
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     uint32 nEntries = hHeaderTwo.NumberOfCTEntries;
 
@@ -86,46 +120,46 @@ IntergraphRasterBand::IntergraphRasterBand( IntergraphDataset *poDS,
         switch ( hHeaderTwo.ColorTableType )
         {
         case EnvironVColorTable:
-            INGR_GetEnvironVColors( poDS->fp, nBandOffset, nEntries, poColorTable );
+            INGR_GetEnvironVColors( poDSIn->fp, nBandOffset, nEntries, poColorTable );
             if (poColorTable->GetColorEntryCount() == 0)
                 return;
             break;
         case IGDSColorTable:
-            INGR_GetIGDSColors( poDS->fp, nBandOffset, nEntries, poColorTable );
+            INGR_GetIGDSColors( poDSIn->fp, nBandOffset, nEntries, poColorTable );
             if (poColorTable->GetColorEntryCount() == 0)
                 return;
             break;
         default:
-            CPLDebug( "INGR", "Wrong Color table type (%d), number of colors (%d)", 
+            CPLDebug( "INGR", "Wrong Color table type (%d), number of colors (%d)",
                 hHeaderTwo.ColorTableType, nEntries );
         }
     }
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Set Dimension
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     nRasterXSize  = hHeaderOne.PixelsPerLine;
     nRasterYSize  = hHeaderOne.NumberOfLines;
-    
+
     nBlockXSize   = nRasterXSize;
     nBlockYSize   = 1;
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Get tile directory
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
-    this->eFormat = (INGR_Format) hHeaderOne.DataTypeCode;
+    eFormat = (INGR_Format) hHeaderOne.DataTypeCode;
 
-    this->bTiled = (hHeaderOne.DataTypeCode == TiledRasterData);
+    bTiled = (hHeaderOne.DataTypeCode == TiledRasterData);
 
     if( bTiled )
     {
-        nTiles = INGR_GetTileDirectory( poDS->fp, 
-                                        nDataOffset, 
-                                        nRasterXSize, 
+        nTiles = INGR_GetTileDirectory( poDSIn->fp,
+                                        nDataOffset,
+                                        nRasterXSize,
                                         nRasterYSize,
-                                        &hTileDir, 
+                                        &hTileDir,
                                         &pahTiles );
         if (nTiles == 0)
             return;
@@ -146,27 +180,38 @@ IntergraphRasterBand::IntergraphRasterBand( IntergraphDataset *poDS,
         return;
     }
 
-    // -------------------------------------------------------------------- 
-    // Incomplete tiles have Block Offset greater than: 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
+    // Incomplete tiles have Block Offset greater than:
+    // --------------------------------------------------------------------
 
     nFullBlocksX  = ( nRasterXSize / nBlockXSize );
     nFullBlocksY  = ( nRasterYSize / nBlockYSize );
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Get the Data Type from Format
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
-    this->eDataType = INGR_GetDataType( (uint16) eFormat );
+    eDataType = INGR_GetDataType( (uint16) eFormat );
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Allocate buffer for a Block of data
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
+
+    if( nBlockYSize == 0 ||
+        nBlockXSize > INT_MAX / nBlockYSize ||
+        nBlockXSize > INT_MAX / 4 - 2 ||
+        GDALGetDataTypeSize( eDataType ) == 0 ||
+        nBlockYSize > INT_MAX / (GDALGetDataTypeSize( eDataType ) / 8) ||
+        nBlockXSize > INT_MAX / (nBlockYSize * (GDALGetDataTypeSize( eDataType ) / 8)) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Too big block size");
+        return;
+    }
 
-    nBlockBufSize = nBlockXSize * nBlockYSize * 
-                    GDALGetDataTypeSize( eDataType ) / 8;
+    nBlockBufSize = nBlockXSize * nBlockYSize *
+                    (GDALGetDataTypeSize( eDataType ) / 8);
 
-    if (eFormat == RunLengthEncoded)    
+    if (eFormat == RunLengthEncoded)
     {
         pabyBlockBuf = (GByte*) VSIMalloc3( nBlockXSize*4+2, nBlockYSize,
                                             GDALGetDataTypeSize( eDataType ) / 8);
@@ -183,24 +228,24 @@ IntergraphRasterBand::IntergraphRasterBand( IntergraphDataset *poDS,
         return;
     }
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // More Metadata Information
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
-    SetMetadataItem( "FORMAT", INGR_GetFormatName( (uint16) eFormat ), 
+    SetMetadataItem( "FORMAT", INGR_GetFormatName( (uint16) eFormat ),
         "IMAGE_STRUCTURE" );
 
     if( bTiled )
     {
-        SetMetadataItem( "TILESSIZE", CPLSPrintf ("%d", hTileDir.TileSize), 
+        SetMetadataItem( "TILESSIZE", CPLSPrintf ("%d", hTileDir.TileSize),
             "IMAGE_STRUCTURE" );
     }
     else
     {
-        SetMetadataItem( "TILED", "NO", "IMAGE_STRUCTURE" ); 
+        SetMetadataItem( "TILED", "NO", "IMAGE_STRUCTURE" );
     }
 
-    SetMetadataItem( "ORIENTATION", 
+    SetMetadataItem( "ORIENTATION",
         INGR_GetOrientation( hHeaderOne.ScanlineOrientation ),
         "IMAGE_STRUCTURE" );
 
@@ -220,15 +265,8 @@ IntergraphRasterBand::IntergraphRasterBand( IntergraphDataset *poDS,
 
 IntergraphRasterBand::~IntergraphRasterBand()
 {
-    if( pabyBlockBuf )
-    {
-        CPLFree( pabyBlockBuf );
-    }
-
-    if( pahTiles )
-    {
-        CPLFree( pahTiles );
-    }
+    CPLFree( pabyBlockBuf );
+    CPLFree( pahTiles );
 
     if( poColorTable )
     {
@@ -243,8 +281,8 @@ IntergraphRasterBand::~IntergraphRasterBand()
 double IntergraphRasterBand::GetMinimum( int *pbSuccess )
 {
 
-    double dMinimum = INGR_GetMinMax( eDataType, hHeaderOne.Minimum ); 
-    double dMaximum = INGR_GetMinMax( eDataType, hHeaderOne.Maximum ); 
+    const double dMinimum = INGR_GetMinMax( eDataType, hHeaderOne.Minimum );
+    const double dMaximum = INGR_GetMinMax( eDataType, hHeaderOne.Maximum );
 
     if( pbSuccess )
     {
@@ -260,8 +298,8 @@ double IntergraphRasterBand::GetMinimum( int *pbSuccess )
 
 double IntergraphRasterBand::GetMaximum( int *pbSuccess )
 {
-    double dMinimum = INGR_GetMinMax( eDataType, hHeaderOne.Minimum ); 
-    double dMaximum = INGR_GetMinMax( eDataType, hHeaderOne.Maximum ); 
+    const double dMinimum = INGR_GetMinMax( eDataType, hHeaderOne.Minimum );
+    const double dMaximum = INGR_GetMinMax( eDataType, hHeaderOne.Maximum );
 
     if( pbSuccess )
     {
@@ -278,16 +316,16 @@ double IntergraphRasterBand::GetMaximum( int *pbSuccess )
 GDALColorInterp IntergraphRasterBand::GetColorInterpretation()
 {
     if( eFormat == AdaptiveRGB ||
-        eFormat == Uncompressed24bit || 
+        eFormat == Uncompressed24bit ||
         eFormat == ContinuousTone )
-    {               
+    {
         switch( nRGBIndex )
         {
-        case 1: 
+        case 1:
             return GCI_RedBand;
-        case 2: 
+        case 2:
             return GCI_GreenBand;
-        case 3: 
+        case 3:
             return GCI_BlueBand;
         }
         return GCI_GrayIndex;
@@ -298,10 +336,8 @@ GDALColorInterp IntergraphRasterBand::GetColorInterpretation()
         {
             return GCI_PaletteIndex;
         }
-        else
-        {
-            return GCI_GrayIndex;
-        }
+
+        return GCI_GrayIndex;
     }
 
 }
@@ -316,25 +352,23 @@ GDALColorTable *IntergraphRasterBand::GetColorTable()
     {
         return NULL;
     }
-    else
-    {
-        return poColorTable;
-    }
+
+    return poColorTable;
 }
 
 //  ----------------------------------------------------------------------------
 //                                         IntergraphRasterBand::SetColorTable()
 //  ----------------------------------------------------------------------------
 
-CPLErr IntergraphRasterBand::SetColorTable( GDALColorTable *poColorTable )
-{      
-    if( poColorTable == NULL )
+CPLErr IntergraphRasterBand::SetColorTable( GDALColorTable *poColorTableIn )
+{
+    if( poColorTableIn == NULL )
     {
         return CE_None;
     }
 
     delete this->poColorTable;
-    this->poColorTable = poColorTable->Clone();
+    this->poColorTable = poColorTableIn->Clone();
 
     return CE_None;
 }
@@ -343,14 +377,14 @@ CPLErr IntergraphRasterBand::SetColorTable( GDALColorTable *poColorTable )
 //                                         IntergraphRasterBand::SetStatistics()
 //  ----------------------------------------------------------------------------
 
-CPLErr IntergraphRasterBand::SetStatistics( double dfMin, 
-                                            double dfMax, 
-                                            double dfMean, 
+CPLErr IntergraphRasterBand::SetStatistics( double dfMin,
+                                            double dfMax,
+                                            double dfMean,
                                             double dfStdDev )
-{      
+{
     hHeaderOne.Minimum = INGR_SetMinMax( eDataType, dfMin );
     hHeaderOne.Maximum = INGR_SetMinMax( eDataType, dfMax );
-    
+
     return GDALRasterBand::SetStatistics( dfMin, dfMax, dfMean, dfStdDev );
 }
 
@@ -358,7 +392,7 @@ CPLErr IntergraphRasterBand::SetStatistics( double dfMin,
 //                                            IntergraphRasterBand::IReadBlock()
 //  ----------------------------------------------------------------------------
 
-CPLErr IntergraphRasterBand::IReadBlock( int nBlockXOff, 
+CPLErr IntergraphRasterBand::IReadBlock( int nBlockXOff,
                                          int nBlockYOff,
                                          void *pImage )
 {
@@ -372,10 +406,10 @@ CPLErr IntergraphRasterBand::IReadBlock( int nBlockXOff,
 
     if( nBytesRead == 0 )
     {
-        memset( pImage, 0, nBlockXSize * nBlockYSize * 
-                    GDALGetDataTypeSize( eDataType ) / 8 );
-        CPLError( CE_Failure, CPLE_FileIO, 
-            "Can't read (%s) tile with X offset %d and Y offset %d.\n", 
+        memset( pImage, 0, nBlockXSize * nBlockYSize *
+                    (GDALGetDataTypeSize( eDataType ) / 8) );
+        CPLError( CE_Failure, CPLE_FileIO,
+            "Can't read (%s) tile with X offset %d and Y offset %d.\n",
             ((IntergraphDataset*)poDS)->pszFilename, nBlockXOff, nBlockYOff );
         return CE_Failure;
     }
@@ -384,18 +418,19 @@ CPLErr IntergraphRasterBand::IReadBlock( int nBlockXOff,
     // Reshape blocks if needed
     // --------------------------------------------------------------------
 
-    if( nBlockXOff == nFullBlocksX || 
+    if( nBlockXOff == nFullBlocksX ||
         nBlockYOff == nFullBlocksY )
     {
-        ReshapeBlock( nBlockXOff, nBlockYOff, nBlockBufSize, pabyBlockBuf );
+        if( !ReshapeBlock( nBlockXOff, nBlockYOff, nBlockBufSize, pabyBlockBuf ) )
+            return CE_Failure;
     }
 
     // --------------------------------------------------------------------
     // Copy block buffer to image
     // --------------------------------------------------------------------
 
-    memcpy( pImage, pabyBlockBuf, nBlockXSize * nBlockYSize * 
-        GDALGetDataTypeSize( eDataType ) / 8 );
+    memcpy( pImage, pabyBlockBuf, nBlockXSize * nBlockYSize *
+        (GDALGetDataTypeSize( eDataType ) / 8) );
 
 #ifdef CPL_MSB
     if( eDataType == GDT_Int16 || eDataType == GDT_UInt16)
@@ -413,11 +448,11 @@ CPLErr IntergraphRasterBand::IReadBlock( int nBlockXOff,
 //                                        IntergraphRasterBand::HandleUninstantiatedTile()
 //  ----------------------------------------------------------------------------
 
-int IntergraphRasterBand::HandleUninstantiatedTile(int nBlockXOff, 
+int IntergraphRasterBand::HandleUninstantiatedTile(int nBlockXOff,
                                                    int nBlockYOff,
                                                    void* pImage)
 {
-    if( bTiled && pahTiles[nBlockXOff + nBlockYOff * nBlocksPerRow].Start == 0 ) 
+    if( bTiled && pahTiles[nBlockXOff + nBlockYOff * nBlocksPerRow].Start == 0 )
     {
         // ------------------------------------------------------------
         // Uninstantieted tile, unique value
@@ -425,39 +460,40 @@ int IntergraphRasterBand::HandleUninstantiatedTile(int nBlockXOff,
         int nColor = pahTiles[nBlockXOff + nBlockYOff * nBlocksPerRow].Used;
         switch( GetColorInterpretation() )
         {
-            case GCI_RedBand: 
+            case GCI_RedBand:
                 nColor >>= 16; break;
-            case GCI_GreenBand: 
+            case GCI_GreenBand:
                 nColor >>= 8; break;
             default:
                 break;
         }
-        memset( pImage, nColor, nBlockXSize * nBlockYSize * 
-                    GDALGetDataTypeSize( eDataType ) / 8 );
+        memset( pImage, nColor, nBlockXSize * nBlockYSize *
+                    (GDALGetDataTypeSize( eDataType ) / 8) );
         return TRUE;
     }
-    else
-        return FALSE;
+
+
+    return FALSE;
 }
 
 //  ----------------------------------------------------------------------------
 //                                        IntergraphRGBBand::IntergraphRGBBand()
 //  ----------------------------------------------------------------------------
 
-IntergraphRGBBand::IntergraphRGBBand( IntergraphDataset *poDS, 
-                                     int nBand,
+IntergraphRGBBand::IntergraphRGBBand( IntergraphDataset *poDSIn,
+                                     int nBandIn,
                                      int nBandOffset,
                                      int nRGorB )
-    : IntergraphRasterBand( poDS, nBand, nBandOffset )
+    : IntergraphRasterBand( poDSIn, nBandIn, nBandOffset )
 {
     if (pabyBlockBuf == NULL)
         return;
 
     nRGBIndex     = (uint8) nRGorB;
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Reallocate buffer for a block of RGB Data
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     nBlockBufSize *= 3;
     CPLFree( pabyBlockBuf );
@@ -472,12 +508,12 @@ IntergraphRGBBand::IntergraphRGBBand( IntergraphDataset *poDS,
 //                                               IntergraphRGBBand::IReadBlock()
 //  ----------------------------------------------------------------------------
 
-CPLErr IntergraphRGBBand::IReadBlock( int nBlockXOff, 
+CPLErr IntergraphRGBBand::IReadBlock( int nBlockXOff,
                                       int nBlockYOff,
                                       void *pImage )
 {
-    if( IntergraphRasterBand::IReadBlock( nBlockXOff, 
-                                          nBlockYOff, 
+    if( IntergraphRasterBand::IReadBlock( nBlockXOff,
+                                          nBlockYOff,
                                           pImage ) != CE_None )
     {
         return CE_Failure;
@@ -487,10 +523,8 @@ CPLErr IntergraphRGBBand::IReadBlock( int nBlockXOff,
     // Extract the band of interest from the block buffer
     // --------------------------------------------------------------------
 
-    int i, j;
-
-    for ( i = 0, j = ( nRGBIndex - 1 ); 
-          i < ( nBlockXSize * nBlockYSize ); 
+    for ( int i = 0, j = ( nRGBIndex - 1 );
+          i < ( nBlockXSize * nBlockYSize );
           i++, j += 3 )
     {
         ( (GByte*) pImage )[i] = pabyBlockBuf[j];
@@ -503,11 +537,11 @@ CPLErr IntergraphRGBBand::IReadBlock( int nBlockXOff,
 //                                        IntergraphRLEBand::IntergraphRLEBand()
 //  ----------------------------------------------------------------------------
 
-IntergraphRLEBand::IntergraphRLEBand( IntergraphDataset *poDS, 
-                                     int nBand,
+IntergraphRLEBand::IntergraphRLEBand( IntergraphDataset *poDSIn,
+                                     int nBandIn,
                                      int nBandOffset,
                                      int nRGorB )
-    : IntergraphRasterBand( poDS, nBand, nBandOffset )
+    : IntergraphRasterBand( poDSIn, nBandIn, nBandOffset )
 {
     nRLESize         = 0;
     nRGBIndex        = (uint8) nRGorB;
@@ -518,7 +552,7 @@ IntergraphRLEBand::IntergraphRLEBand( IntergraphDataset *poDS,
     if (pabyBlockBuf == NULL)
         return;
 
-    if( ! this->bTiled )
+    if( !bTiled )
     {
         // ------------------------------------------------------------
         // Load all rows at once
@@ -529,8 +563,10 @@ IntergraphRLEBand::IntergraphRLEBand( IntergraphDataset *poDS,
         if( eFormat == RunLengthEncodedC || eFormat == RunLengthEncoded )
         {
             nBlockYSize = 1;
-            panRLELineOffset = (uint32 *) 
-                CPLCalloc(sizeof(uint32),nRasterYSize);
+            panRLELineOffset = (uint32 *)
+                VSI_CALLOC_VERBOSE(sizeof(uint32),nRasterYSize);
+            if( panRLELineOffset == NULL )
+                return;
             nFullBlocksY = nRasterYSize;
         }
         else
@@ -539,10 +575,15 @@ IntergraphRLEBand::IntergraphRLEBand( IntergraphDataset *poDS,
             nFullBlocksY = 1;
         }
 
-        nRLESize     = INGR_GetDataBlockSize( poDS->pszFilename, 
+        nRLESize     = INGR_GetDataBlockSize( poDSIn->pszFilename,
                           hHeaderTwo.CatenatedFilePointer,
                           nDataOffset);
 
+        if( nBlockYSize == 0 || nBlockXSize > INT_MAX / nBlockYSize )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Too big block size");
+            return;
+        }
         nBlockBufSize = nBlockXSize * nBlockYSize;
     }
     else
@@ -551,25 +592,31 @@ IntergraphRLEBand::IntergraphRLEBand( IntergraphDataset *poDS,
         // Find the biggest tile
         // ------------------------------------------------------------
 
-        uint32 iTiles;
-        for( iTiles = 0; iTiles < nTiles; iTiles++)
+        for( uint32 iTiles = 0; iTiles < nTiles; iTiles++)
         {
             nRLESize = MAX( pahTiles[iTiles].Used, nRLESize );
         }
     }
 
     // ----------------------------------------------------------------
-    // Realocate the decompressed Buffer 
+    // Reallocate the decompressed buffer.
     // ----------------------------------------------------------------
 
     if( eFormat == AdaptiveRGB ||
         eFormat == ContinuousTone )
     {
+        if( nBlockBufSize > INT_MAX / 3 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Too big block size");
+            return;
+        }
         nBlockBufSize *= 3;
     }
 
-    CPLFree( pabyBlockBuf );
-    pabyBlockBuf = (GByte*) VSIMalloc( nBlockBufSize );
+    CPLFree(pabyBlockBuf);
+    pabyBlockBuf = NULL;
+    if( nBlockBufSize > 0 )
+        pabyBlockBuf = (GByte*) VSIMalloc( nBlockBufSize );
     if (pabyBlockBuf == NULL)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Cannot allocate %d bytes", nBlockBufSize);
@@ -579,7 +626,10 @@ IntergraphRLEBand::IntergraphRLEBand( IntergraphDataset *poDS,
     // Create a RLE buffer
     // ----------------------------------------------------------------
 
-    pabyRLEBlock = (GByte*) VSIMalloc( nRLESize );
+    if( nRLESize == 0 )
+        pabyRLEBlock = (GByte*) VSIMalloc( 1 );
+    else if( nRLESize < INT_MAX )
+        pabyRLEBlock = (GByte*) VSIMalloc( nRLESize );
     if (pabyRLEBlock == NULL)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Cannot allocate %d bytes", nRLESize);
@@ -610,7 +660,7 @@ IntergraphRLEBand::~IntergraphRLEBand()
 //                                               IntergraphRLEBand::IReadBlock()
 //  ----------------------------------------------------------------------------
 
-CPLErr IntergraphRLEBand::IReadBlock( int nBlockXOff, 
+CPLErr IntergraphRLEBand::IReadBlock( int nBlockXOff,
                                       int nBlockYOff,
                                       void *pImage )
 {
@@ -619,7 +669,7 @@ CPLErr IntergraphRLEBand::IReadBlock( int nBlockXOff,
     // --------------------------------------------------------------------
 
     uint32 nBytesRead;
-    
+
     if( bTiled || !bRLEBlockLoaded )
     {
         if (HandleUninstantiatedTile( nBlockXOff, nBlockYOff, pImage ))
@@ -642,11 +692,11 @@ CPLErr IntergraphRLEBand::IReadBlock( int nBlockXOff,
 
     if( nBytesRead == 0 )
     {
-        memset( pImage, 0, nBlockXSize * nBlockYSize * 
-                    GDALGetDataTypeSize( eDataType ) / 8 );
-        CPLError( CE_Failure, CPLE_FileIO, 
-            "Can't read (%s) tile with X offset %d and Y offset %d.\n%s", 
-            ((IntergraphDataset*)poDS)->pszFilename, nBlockXOff, nBlockYOff, 
+        memset( pImage, 0, nBlockXSize * nBlockYSize *
+                    (GDALGetDataTypeSize( eDataType ) / 8) );
+        CPLError( CE_Failure, CPLE_FileIO,
+            "Can't read (%s) tile with X offset %d and Y offset %d.\n%s",
+            ((IntergraphDataset*)poDS)->pszFilename, nBlockXOff, nBlockYOff,
             VSIStrerror( errno ) );
         return CE_Failure;
     }
@@ -656,7 +706,7 @@ CPLErr IntergraphRLEBand::IReadBlock( int nBlockXOff,
     // ----------------------------------------------------------------
 
     int nVirtualXSize = nBlockXSize;
-    int nVirtualYSize = nBlockYSize; 
+    int nVirtualYSize = nBlockYSize;
 
     if( nBlockXOff == nFullBlocksX )
     {
@@ -668,24 +718,30 @@ CPLErr IntergraphRLEBand::IReadBlock( int nBlockXOff,
         nVirtualYSize = nRasterYSize % nBlockYSize;
     }
 
+    int nExpectedOutputBytes = nVirtualXSize * nVirtualYSize;
+    if( eFormat == AdaptiveRGB ||
+        eFormat == ContinuousTone )
+    {
+        nExpectedOutputBytes *= 3;
+    }
+
     // --------------------------------------------------------------------
     // Decode Run Length
     // --------------------------------------------------------------------
 
+    int nOutputBytes;
     if( bTiled && eFormat == RunLengthEncoded )
     {
-        nBytesRead = 
-            INGR_DecodeRunLengthBitonalTiled( pabyRLEBlock, pabyBlockBuf,  
+        nOutputBytes =
+            INGR_DecodeRunLengthBitonalTiled( pabyRLEBlock, pabyBlockBuf,
                                               nRLESize, nBlockBufSize, NULL );
     }
-    
     else if( bTiled || panRLELineOffset == NULL )
     {
-        nBytesRead = INGR_Decode( eFormat, pabyRLEBlock, pabyBlockBuf,  
-                                  nRLESize, nBlockBufSize, 
+        nOutputBytes = INGR_Decode( eFormat, pabyRLEBlock, pabyBlockBuf,
+                                  nRLESize, nBlockBufSize,
                                   NULL );
     }
-
     else
     {
         uint32 nBytesConsumed;
@@ -700,39 +756,60 @@ CPLErr IntergraphRLEBand::IReadBlock( int nBlockXOff,
                 iLine--;
             for( ; iLine < nBlockYOff; iLine++ )
             {
-                // Pass NULL as destination so that no decompression 
+                // Pass NULL as destination so that no decompression
                 // actually takes place.
-                INGR_Decode( eFormat,
-                             pabyRLEBlock + panRLELineOffset[iLine], 
+                if( nRLESize < panRLELineOffset[iLine] ||
+                    (uint32)INGR_Decode( eFormat,
+                             pabyRLEBlock + panRLELineOffset[iLine],
                              NULL,  nRLESize - panRLELineOffset[iLine], nBlockBufSize,
-                             &nBytesConsumed );
+                             &nBytesConsumed ) < nBlockBufSize )
+                {
+                    memset( pImage, 0, nBlockXSize * nBlockYSize *
+                                (GDALGetDataTypeSize( eDataType ) / 8) );
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                        "Can't decode line %d", iLine );
+                    return CE_Failure;
+                }
 
                 if( iLine < nRasterYSize-1 )
-                    panRLELineOffset[iLine+1] = 
+                    panRLELineOffset[iLine+1] =
                         panRLELineOffset[iLine] + nBytesConsumed;
             }
-        } 
-        
-        // Read the requested line.
-        nBytesRead = 
-            INGR_Decode( eFormat,
-                         pabyRLEBlock + panRLELineOffset[nBlockYOff], 
+        }
+
+        if( nRLESize < panRLELineOffset[nBlockYOff] )
+            nOutputBytes = 0;
+        else
+        {
+            // Read the requested line.
+            nOutputBytes = INGR_Decode( eFormat,
+                         pabyRLEBlock + panRLELineOffset[nBlockYOff],
                          pabyBlockBuf,  nRLESize - panRLELineOffset[nBlockYOff], nBlockBufSize,
                          &nBytesConsumed );
-            
-        if( nBlockYOff < nRasterYSize-1 )
-            panRLELineOffset[nBlockYOff+1] = 
-                panRLELineOffset[nBlockYOff] + nBytesConsumed;
+            if( nOutputBytes == nExpectedOutputBytes && nBlockYOff < nRasterYSize-1 )
+                panRLELineOffset[nBlockYOff+1] =
+                    panRLELineOffset[nBlockYOff] + nBytesConsumed;
+        }
+    }
+
+    if( nOutputBytes < nExpectedOutputBytes )
+    {
+        memset( pImage, 0, nBlockXSize * nBlockYSize *
+                    (GDALGetDataTypeSize( eDataType ) / 8) );
+        CPLError( CE_Failure, CPLE_AppDefined,
+            "Can't decode block (%d, %d)", nBlockXOff, nBlockYOff );
+        return CE_Failure;
     }
 
     // --------------------------------------------------------------------
     // Reshape blocks if needed
     // --------------------------------------------------------------------
 
-    if( nBlockXOff == nFullBlocksX || 
+    if( nBlockXOff == nFullBlocksX ||
         nBlockYOff == nFullBlocksY )
     {
-        ReshapeBlock( nBlockXOff, nBlockYOff, nBlockBufSize, pabyBlockBuf );
+        if( !ReshapeBlock( nBlockXOff, nBlockYOff, nBlockBufSize, pabyBlockBuf ) )
+            return CE_Failure;
     }
 
     // --------------------------------------------------------------------
@@ -742,10 +819,9 @@ CPLErr IntergraphRLEBand::IReadBlock( int nBlockXOff,
     if( eFormat == AdaptiveRGB ||
         eFormat == ContinuousTone )
     {
-        int i, j;
         GByte *pabyImage = (GByte*) pImage;
-        j = ( nRGBIndex - 1 ) * nVirtualXSize;
-        for ( i = 0; i < nVirtualYSize; i++ )
+        int j = ( nRGBIndex - 1 ) * nVirtualXSize;
+        for ( int i = 0; i < nVirtualYSize; i++ )
         {
             memcpy( &pabyImage[i * nBlockXSize], &pabyBlockBuf[j], nBlockXSize );
             j += ( 3 * nBlockXSize );
@@ -763,28 +839,27 @@ CPLErr IntergraphRLEBand::IReadBlock( int nBlockXOff,
 //                                  IntergraphBitmapBand::IntergraphBitmapBand()
 //  ----------------------------------------------------------------------------
 
-IntergraphBitmapBand::IntergraphBitmapBand( IntergraphDataset *poDS, 
-                                            int nBand,
+IntergraphBitmapBand::IntergraphBitmapBand( IntergraphDataset *poDSIn,
+                                            int nBandIn,
                                             int nBandOffset,
                                             int nRGorB )
-    : IntergraphRasterBand( poDS, nBand, nBandOffset, GDT_Byte )
+    : IntergraphRasterBand( poDSIn, nBandIn, nBandOffset, GDT_Byte ),
+      pabyBMPBlock(NULL),
+      nBMPSize(0),
+      nQuality(0),
+      nRGBBand(nRGorB)
 {
-    nBMPSize    = 0;
-    nRGBBand    = nRGorB;
-    pabyBMPBlock = NULL;
-
     if (pabyBlockBuf == NULL)
         return;
 
-
-    if( ! this->bTiled )
+    if( !bTiled )
     {
         // ------------------------------------------------------------
         // Load all rows at once
         // ------------------------------------------------------------
 
         nBlockYSize = nRasterYSize;
-        nBMPSize    = INGR_GetDataBlockSize( poDS->pszFilename, 
+        nBMPSize    = INGR_GetDataBlockSize( poDSIn->pszFilename,
                                              hHeaderTwo.CatenatedFilePointer,
                                              nDataOffset);
     }
@@ -794,8 +869,7 @@ IntergraphBitmapBand::IntergraphBitmapBand( IntergraphDataset *poDS,
         // Find the biggest tile
         // ------------------------------------------------------------
 
-        uint32 iTiles;
-        for( iTiles = 0; iTiles < nTiles; iTiles++)
+        for( uint32 iTiles = 0; iTiles < nTiles; iTiles++)
         {
             nBMPSize = MAX( pahTiles[iTiles].Used, nBMPSize );
         }
@@ -826,9 +900,9 @@ IntergraphBitmapBand::IntergraphBitmapBand( IntergraphDataset *poDS,
 
 	if( eFormat == JPEGGRAY ||
 		eFormat == JPEGRGB  ||
-		eFormat == JPEGCYMK )
+		eFormat == JPEGCMYK )
 	{
-        nQuality = INGR_ReadJpegQuality( poDS->fp, 
+        nQuality = INGR_ReadJpegQuality( poDSIn->fp,
             hHeaderTwo.ApplicationPacketPointer,
             nDataOffset );
 	}
@@ -853,34 +927,29 @@ GDALColorInterp IntergraphBitmapBand::GetColorInterpretation()
     {
         switch( nRGBBand )
         {
-        case 1: 
+        case 1:
             return GCI_RedBand;
-        case 2: 
+        case 2:
             return GCI_GreenBand;
-        case 3: 
+        case 3:
             return GCI_BlueBand;
         }
         return GCI_GrayIndex;
     }
-    else
+
+    if( poColorTable->GetColorEntryCount() > 0 )
     {
-        if( poColorTable->GetColorEntryCount() > 0 )
-        {
-            return GCI_PaletteIndex;
-        }
-        else
-        {
-            return GCI_GrayIndex;
-        }
+        return GCI_PaletteIndex;
     }
 
+    return GCI_GrayIndex;
 }
 
 //  ----------------------------------------------------------------------------
 //                                            IntergraphBitmapBand::IReadBlock()
 //  ----------------------------------------------------------------------------
 
-CPLErr IntergraphBitmapBand::IReadBlock( int nBlockXOff, 
+CPLErr IntergraphBitmapBand::IReadBlock( int nBlockXOff,
                                          int nBlockYOff,
                                          void *pImage )
 {
@@ -896,11 +965,11 @@ CPLErr IntergraphBitmapBand::IReadBlock( int nBlockXOff,
 
     if( nBytesRead == 0 )
     {
-        memset( pImage, 0, nBlockXSize * nBlockYSize * 
-                    GDALGetDataTypeSize( eDataType ) / 8 );
-        CPLError( CE_Failure, CPLE_FileIO, 
-            "Can't read (%s) tile with X offset %d and Y offset %d.\n%s", 
-            ((IntergraphDataset*)poDS)->pszFilename, nBlockXOff, nBlockYOff, 
+        memset( pImage, 0, nBlockXSize * nBlockYSize *
+                    (GDALGetDataTypeSize( eDataType ) / 8) );
+        CPLError( CE_Failure, CPLE_FileIO,
+            "Can't read (%s) tile with X offset %d and Y offset %d.\n%s",
+            ((IntergraphDataset*)poDS)->pszFilename, nBlockXOff, nBlockYOff,
             VSIStrerror( errno ) );
         return CE_Failure;
     }
@@ -910,7 +979,7 @@ CPLErr IntergraphBitmapBand::IReadBlock( int nBlockXOff,
     // ----------------------------------------------------------------
 
     int nVirtualXSize = nBlockXSize;
-    int nVirtualYSize = nBlockYSize; 
+    int nVirtualYSize = nBlockYSize;
 
     if( nBlockXOff == nFullBlocksX )
     {
@@ -926,21 +995,21 @@ CPLErr IntergraphBitmapBand::IReadBlock( int nBlockXOff,
 	// Create an in memory small tiff file (~400K)
     // ----------------------------------------------------------------
 
-    poGDS->hVirtual = INGR_CreateVirtualFile( poGDS->pszFilename, 
+    poGDS->hVirtual = INGR_CreateVirtualFile( poGDS->pszFilename,
                                               eFormat,
                                               nVirtualXSize,
                                               nVirtualYSize,
                                               hTileDir.TileSize,
                                               nQuality,
-                                              pabyBMPBlock, 
-                                              nBytesRead, 
+                                              pabyBMPBlock,
+                                              nBytesRead,
                                               nRGBBand );
 
-    if( poGDS->hVirtual.poDS == NULL )
+    if( poGDS->hVirtual.poBand == NULL )
     {
-        memset( pImage, 0, nBlockXSize * nBlockYSize * 
-                    GDALGetDataTypeSize( eDataType ) / 8 );
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        memset( pImage, 0, nBlockXSize * nBlockYSize *
+                    (GDALGetDataTypeSize( eDataType ) / 8) );
+        CPLError( CE_Failure, CPLE_AppDefined,
 			"Unable to open virtual file.\n"
 			"Is the GTIFF and JPEG driver available?" );
         return CE_Failure;
@@ -950,39 +1019,42 @@ CPLErr IntergraphBitmapBand::IReadBlock( int nBlockXOff,
 	// Read the unique block from the in memory file and release it
     // ----------------------------------------------------------------
 
-    poGDS->hVirtual.poBand->RasterIO( GF_Read, 0, 0, 
-        nVirtualXSize, nVirtualYSize, pImage, 
-        nVirtualXSize, nVirtualYSize, GDT_Byte, 0, 0, NULL );
+    if( poGDS->hVirtual.poBand->RasterIO( GF_Read, 0, 0,
+        nVirtualXSize, nVirtualYSize, pImage,
+        nVirtualXSize, nVirtualYSize, GDT_Byte, 0, 0, NULL) != CE_None )
+    {
+        INGR_ReleaseVirtual( &poGDS->hVirtual );
+        return CE_Failure;
+    }
 
     // --------------------------------------------------------------------
     // Reshape blocks if needed
     // --------------------------------------------------------------------
 
-    if( nBlockXOff == nFullBlocksX || 
+    CPLErr eErr = CE_None;
+    if( nBlockXOff == nFullBlocksX ||
         nBlockYOff == nFullBlocksY )
     {
-        ReshapeBlock( nBlockXOff, nBlockYOff, nBlockBufSize, (GByte*) pImage );
+        if( !ReshapeBlock( nBlockXOff, nBlockYOff, nBlockBufSize, (GByte*) pImage ) )
+            eErr = CE_Failure;
     }
 
     INGR_ReleaseVirtual( &poGDS->hVirtual );
 
-    return CE_None;
-} 
+    return eErr;
+}
 
 //  ----------------------------------------------------------------------------
 //                                          IntergraphRasterBand::LoadBlockBuf()
 //  ----------------------------------------------------------------------------
 
-int IntergraphRasterBand::LoadBlockBuf( int nBlockXOff, 
+int IntergraphRasterBand::LoadBlockBuf( int nBlockXOff,
                                         int nBlockYOff,
                                         int nBlobkBytes,
                                         GByte *pabyBlock )
 {
-    IntergraphDataset *poGDS = ( IntergraphDataset * ) poDS;
-
-    uint32 nSeekOffset  = 0;
+    vsi_l_offset nSeekOffset  = 0;
     uint32 nReadSize    = 0;
-    uint32 nBlockId     = 0;
 
     // --------------------------------------------------------------------
     // Read from tiles or read from strip
@@ -990,37 +1062,43 @@ int IntergraphRasterBand::LoadBlockBuf( int nBlockXOff,
 
     if( bTiled )
     {
-        nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
+        uint32 nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
 
-        if( pahTiles[nBlockId].Start == 0 ) 
+        if( pahTiles[nBlockId].Start == 0 )
         {
             return 0;
         }
 
-        nSeekOffset   = pahTiles[nBlockId].Start + nDataOffset;
+        nSeekOffset   = static_cast<vsi_l_offset>(pahTiles[nBlockId].Start) + nDataOffset;
         nReadSize     = pahTiles[nBlockId].Used;
 
-        if( (int) nReadSize > nBlobkBytes ) 
+        CPLAssert( nBlobkBytes >= 0 );
+        if( nReadSize > (uint32)nBlobkBytes )
         {
-            CPLDebug( "INGR", 
-                      "LoadBlockBuf(%d,%d) - trimmed tile size from %d to %d.", 
+            CPLDebug( "INGR",
+                      "LoadBlockBuf(%d,%d) - trimmed tile size from %u to %d.",
                       nBlockXOff, nBlockYOff,
-                      (int) nReadSize, (int) nBlobkBytes );
+                      nReadSize, nBlobkBytes );
             nReadSize = nBlobkBytes;
         }
     }
     else
     {
-        nSeekOffset   = nDataOffset + ( nBlockBufSize * nBlockYOff );
+        nSeekOffset   = nDataOffset + ( static_cast<vsi_l_offset>(nBlockBufSize) * nBlockYOff );
         nReadSize     = nBlobkBytes;
     }
 
+    IntergraphDataset *poGDS = ( IntergraphDataset * ) poDS;
+
     if( VSIFSeekL( poGDS->fp, nSeekOffset, SEEK_SET ) < 0 )
     {
         return 0;
     }
 
-    return VSIFReadL( pabyBlock, 1, nReadSize, poGDS->fp );
+    uint32 nRead = static_cast<uint32>(VSIFReadL( pabyBlock, 1, nReadSize, poGDS->fp ));
+    if( nRead < nReadSize )
+        memset( pabyBlock + nRead, 0, nReadSize - nRead );
+    return static_cast<int>(nRead);
 }
 
 //  ----------------------------------------------------------------------------
@@ -1029,18 +1107,20 @@ int IntergraphRasterBand::LoadBlockBuf( int nBlockXOff,
 
 /**
  *  Complete Tile with zeroes to fill up a Block
- * 
+ *
  *         ###    ##000   ######    ###00
  *         ### => ##000 , 000000 or ###00
  *                ##000   000000    00000
  ***/
 
-void IntergraphRasterBand::ReshapeBlock( int nBlockXOff, 
+bool IntergraphRasterBand::ReshapeBlock( int nBlockXOff,
                                          int nBlockYOff,
                                          int nBlockBytes,
                                          GByte *pabyBlock )
 {
-    GByte *pabyTile = (GByte*) CPLCalloc( 1, nBlockBufSize );
+    GByte *pabyTile = (GByte*) VSI_MALLOC_VERBOSE( nBlockBufSize );
+    if( pabyTile == NULL )
+        return false;
 
     memcpy( pabyTile, pabyBlock, nBlockBytes );
     memset( pabyBlock, 0, nBlockBytes );
@@ -1066,19 +1146,20 @@ void IntergraphRasterBand::ReshapeBlock( int nBlockXOff,
 
     for( int iRow = 0; iRow < nRowSize; iRow++ )
     {
-        memcpy( pabyBlock + ( iRow * nCellBytes * nBlockXSize ), 
-                pabyTile  + ( iRow * nCellBytes * nColSize ), 
+        memcpy( pabyBlock + ( iRow * nCellBytes * nBlockXSize ),
+                pabyTile  + ( iRow * nCellBytes * nColSize ),
                 nCellBytes * nColSize);
     }
 
-    CPLFree( pabyTile );
+    VSIFree( pabyTile );
+    return true;
 }
 
 //  ----------------------------------------------------------------------------
 //                                           IntergraphRasterBand::IWriteBlock()
 //  ----------------------------------------------------------------------------
 
-CPLErr IntergraphRasterBand::IWriteBlock( int nBlockXOff, 
+CPLErr IntergraphRasterBand::IWriteBlock( int nBlockXOff,
                                           int nBlockYOff,
                                           void *pImage )
 {
@@ -1092,15 +1173,14 @@ CPLErr IntergraphRasterBand::IWriteBlock( int nBlockXOff,
         FlushBandHeader();
     }
 
-    if( nRGBIndex > 0 ) 
+    if( nRGBIndex > 0 )
     {
-        if( nBand > 1 ) 
+        if( nBand > 1 )
         {
             VSIFSeekL( poGDS->fp, nDataOffset + ( nBlockBufSize * nBlockYOff ), SEEK_SET );
             VSIFReadL( pabyBlockBuf, 1, nBlockBufSize, poGDS->fp );
         }
-        int i, j;
-        for( i = 0, j = ( 3 - nRGBIndex ); i < nBlockXSize; i++, j += 3 )
+        for( int i = 0, j = ( 3 - nRGBIndex ); i < nBlockXSize; i++, j += 3 )
         {
             pabyBlockBuf[j] = ( ( GByte * ) pImage )[i];
         }
@@ -1131,7 +1211,7 @@ CPLErr IntergraphRasterBand::IWriteBlock( int nBlockXOff,
                     pOutput[nRLECount++] = CPL_LSBWORD16(0);
                     nLastCount -= 32767;
                 }
-                pOutput[nRLECount++] = CPL_LSBWORD16(nLastCount);
+                pOutput[nRLECount++] = static_cast<GInt16>(CPL_LSBWORD16(nLastCount));
                 nLastCount = 1;
                 nValue ^= 1;
             }
@@ -1147,8 +1227,8 @@ CPLErr IntergraphRasterBand::IWriteBlock( int nBlockXOff,
 
         if (nLastCount != 0)
         {
-            pOutput[nRLECount++] = CPL_LSBWORD16(nLastCount);
-            nLastCount = 0;
+            pOutput[nRLECount++] = static_cast<GInt16>(CPL_LSBWORD16(nLastCount));
+            /*nLastCount = 0;*/
             nValue ^= 1;
         }
 
@@ -1175,8 +1255,8 @@ CPLErr IntergraphRasterBand::IWriteBlock( int nBlockXOff,
 
     if( ( uint32 ) VSIFWriteL( pabyBlockBuf, 1, nBlockSize, poGDS->fp ) < nBlockSize )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
-            "Can't write (%s) block with X offset %d and Y offset %d.\n%s", 
+        CPLError( CE_Failure, CPLE_FileIO,
+            "Can't write (%s) block with X offset %d and Y offset %d.\n%s",
             poGDS->pszFilename, nBlockXOff, nBlockYOff, VSIStrerror( errno ) );
         return CE_Failure;
     }
@@ -1195,8 +1275,6 @@ void IntergraphRasterBand::FlushBandHeader( void )
         return;
     }
 
-    IntergraphDataset *poGDS = ( IntergraphDataset* ) poDS;
-
     INGR_ColorTable256 hCTab;
 
     if( poColorTable->GetColorEntryCount() > 0 )
@@ -1212,6 +1290,7 @@ void IntergraphRasterBand::FlushBandHeader( void )
             ( ( 3 * SIZEOF_HDR1 ) + ( nBlockBufSize * nRasterYSize ) );
     }
 
+    IntergraphDataset *poGDS = ( IntergraphDataset* ) poDS;
     VSIFSeekL( poGDS->fp, nBandStart, SEEK_SET );
 
     GByte abyBuf[MAX(SIZEOF_HDR1,SIZEOF_CTAB)];
@@ -1224,10 +1303,9 @@ void IntergraphRasterBand::FlushBandHeader( void )
 
     VSIFWriteL( abyBuf, 1, SIZEOF_HDR2_A, poGDS->fp );
 
-    unsigned int i = 0;
     unsigned int n = 0;
 
-    for( i = 0; i < 256; i++ )
+    for( unsigned int i = 0; i < 256; i++ )
     {
         STRC2BUF( abyBuf, n, hCTab.Entry[i].v_red );
         STRC2BUF( abyBuf, n, hCTab.Entry[i].v_green );
@@ -1265,5 +1343,5 @@ void IntergraphRasterBand::BlackWhiteCT( bool bReverse )
     {
         poColorTable->SetColorEntry( 0, &oBlack );
 	    poColorTable->SetColorEntry( 1, &oWhite );
-    }    
+    }
 }
diff --git a/frmts/ingr/IntergraphBand.h b/frmts/ingr/IntergraphBand.h
index 9439aaf..26043d9 100644
--- a/frmts/ingr/IntergraphBand.h
+++ b/frmts/ingr/IntergraphBand.h
@@ -1,5 +1,5 @@
 /*****************************************************************************
-* $Id: IntergraphBand.h 27044 2014-03-16 23:41:27Z rouault $
+* $Id: IntergraphBand.h 33720 2016-03-15 00:39:53Z goatbar $
 *
 * Project:  Intergraph Raster Format support
 * Purpose:  Read selected types of Intergraph Raster Format
@@ -50,7 +50,7 @@ protected:
     int             nFullBlocksX;
     int             nFullBlocksY;
 
-    GByte	       *pabyBlockBuf;
+    GByte	   *pabyBlockBuf;
     uint32          nTiles;
 
     INGR_TileItem  *pahTiles;
@@ -58,29 +58,29 @@ protected:
     INGR_HeaderOne  hHeaderOne;
     INGR_HeaderTwoA hHeaderTwo;
     INGR_TileHeader hTileDir;
-    
+
     int             nRLEOffset;
 
 public:
-    IntergraphRasterBand( IntergraphDataset *poDS, 
+    IntergraphRasterBand( IntergraphDataset *poDS,
         int nBand,
         int nBandOffset,
         GDALDataType eType = GDT_Unknown);
     ~IntergraphRasterBand();
 
     virtual double GetMinimum( int *pbSuccess = NULL );
-    virtual double GetMaximum( int *pbSuccess = NULL );    
+    virtual double GetMaximum( int *pbSuccess = NULL );
     virtual GDALColorTable *GetColorTable();
     virtual GDALColorInterp GetColorInterpretation();
     virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void *pImage );
     virtual CPLErr IWriteBlock( int nBlockXOff, int nBlockYOff, void *pImage );
-    virtual CPLErr SetColorTable( GDALColorTable *poColorTable ); 
+    virtual CPLErr SetColorTable( GDALColorTable *poColorTable );
     virtual CPLErr SetStatistics( double dfMin, double dfMax, double dfMean, double dfStdDev );
 
 protected:
     int  HandleUninstantiatedTile( int nBlockXOff, int nBlockYOff, void* pImage);
     int  LoadBlockBuf( int nBlockXOff, int nBlockYOff, int nBlockBytes, GByte *pabyBlock );
-    void ReshapeBlock( int nBlockXOff, int nBlockYOff, int nBlockBytes, GByte *pabyBlock );
+    bool ReshapeBlock( int nBlockXOff, int nBlockYOff, int nBlockBytes, GByte *pabyBlock );
     void FlushBandHeader( void );
     void BlackWhiteCT( bool bReverse = false );
 };
@@ -92,7 +92,7 @@ protected:
 class IntergraphRGBBand : public IntergraphRasterBand
 {
 public:
-    IntergraphRGBBand( IntergraphDataset *poDS, 
+    IntergraphRGBBand( IntergraphDataset *poDS,
         int nBand,
         int nBandOffset,
         int nRGorB );
@@ -115,7 +115,7 @@ private:
     int             nRGBBand;
 
 public:
-    IntergraphBitmapBand( IntergraphDataset *poDS, 
+    IntergraphBitmapBand( IntergraphDataset *poDS,
         int nBand,
         int nBandOffset,
         int nRGorB = 1 );
@@ -140,7 +140,7 @@ private:
     uint32         *panRLELineOffset;
 
 public:
-    IntergraphRLEBand( IntergraphDataset *poDS, 
+    IntergraphRLEBand( IntergraphDataset *poDS,
         int nBand,
         int nBandOffset,
         int nRGorB = 0);
diff --git a/frmts/ingr/IntergraphDataset.cpp b/frmts/ingr/IntergraphDataset.cpp
index 4cea75a..404182d 100644
--- a/frmts/ingr/IntergraphDataset.cpp
+++ b/frmts/ingr/IntergraphDataset.cpp
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * $Id: IntergraphDataset.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: IntergraphDataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Intergraph Raster Format support
  * Purpose:  Read/Write Intergraph Raster Format, dataset support
@@ -28,13 +28,14 @@
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
 
-#include "gdal_priv.h"
 #include "cpl_conv.h"
-#include "cpl_string.h"
 #include "cpl_csv.h"
-#include "ogr_spatialref.h"
-#include "gdal_pam.h"
+#include "cpl_string.h"
+#include "gdal_frmts.h"
 #include "gdal_alg.h"
+#include "gdal_pam.h"
+#include "gdal_priv.h"
+#include "ogr_spatialref.h"
 
 #include "IntergraphDataset.h"
 #include "IntergraphBand.h"
@@ -44,11 +45,10 @@
 //                                        IntergraphDataset::IntergraphDataset()
 //  ----------------------------------------------------------------------------
 
-IntergraphDataset::IntergraphDataset()
+IntergraphDataset::IntergraphDataset() :
+    fp(NULL),
+    pszFilename(NULL)
 {
-    pszFilename = NULL;
-    fp = NULL;
-
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
@@ -91,45 +91,45 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
         return NULL;
     }
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Assign Header Information
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     INGR_HeaderOne hHeaderOne;
 
     INGR_HeaderOneDiskToMem( &hHeaderOne, (GByte*) poOpenInfo->pabyHeader);
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Check Header Type (HTC) Version
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     if( hHeaderOne.HeaderType.Version != INGR_HEADER_VERSION )
     {
         return NULL;
     }
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Check Header Type (HTC) 2D / 3D Flag
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
-    if( ( hHeaderOne.HeaderType.Is2Dor3D != INGR_HEADER_2D ) && 
+    if( ( hHeaderOne.HeaderType.Is2Dor3D != INGR_HEADER_2D ) &&
         ( hHeaderOne.HeaderType.Is2Dor3D != INGR_HEADER_3D ) )
     {
         return NULL;
     }
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Check Header Type (HTC) Type Flag
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     if( hHeaderOne.HeaderType.Type != INGR_HEADER_TYPE )
     {
         return NULL;
     }
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Check Grid File Version (VER)
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     if( hHeaderOne.GridFileVersion != 1 &&
         hHeaderOne.GridFileVersion != 2 &&
@@ -138,18 +138,18 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
         return NULL;
     }
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Check Words To Follow (WTC) Minimum Value
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     if( hHeaderOne.WordsToFollow < 254 )
     {
         return NULL;
     }
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Check Words To Follow (WTC) Integrity
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     float fHeaderBlocks = (float) ( hHeaderOne.WordsToFollow + 2 ) / 256;
 
@@ -158,23 +158,23 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
         return NULL;
     }
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Get Data Type Code (DTC) => Format Type
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     INGR_Format eFormat = (INGR_Format) hHeaderOne.DataTypeCode;
 
-    // -------------------------------------------------------------------- 
-    // We need to scan around the file, so we open it now. 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
+    // We need to scan around the file, so we open it now.
+    // --------------------------------------------------------------------
 
     VSILFILE   *fp;
 
     if( poOpenInfo->eAccess == GA_ReadOnly  )
     {
         fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
-    } 
-    else 
+    }
+    else
     {
         fp = VSIFOpenL( poOpenInfo->pszFilename, "r+b" );
     }
@@ -185,9 +185,9 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
         return NULL;
     }
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Get Format Type from the tile directory
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     if( hHeaderOne.DataTypeCode == TiledRasterData )
     {
@@ -201,7 +201,7 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
             (VSIFReadL( abyBuffer, 1, SIZEOF_TDIR, fp ) == 0) )
         {
             VSIFCloseL( fp );
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                 "Error reading tiles header" );
             return NULL;
         }
@@ -215,30 +215,30 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
             hTileDir.PacketVersion       == 1 &&
             hTileDir.Identifier          == 1 ) )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                 "Cannot recognize tiles header info");
             VSIFCloseL( fp );
             return NULL;
         }
-            
+
         eFormat = (INGR_Format) hTileDir.DataTypeCode;
     }
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Check Scannable Flag
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 /*
     if (hHeaderOne.ScannableFlag == HasLineHeader)
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
             "Intergraph Raster Scannable Line Header not supported yet" );
         VSIFCloseL( fp );
         return NULL;
     }
 */
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Check supported Format Type
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     if( eFormat != ByteInteger &&
         eFormat != WordIntegers &&
@@ -253,10 +253,10 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
         eFormat != AdaptiveGrayScale &&
         eFormat != ContinuousTone &&
         eFormat != JPEGGRAY &&
-        eFormat != JPEGRGB && 
-        eFormat != JPEGCYMK )
+        eFormat != JPEGRGB &&
+        eFormat != JPEGCMYK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
             "Intergraph Raster Format %d ( \"%s\" ) not supported",
             hHeaderOne.DataTypeCode, INGR_GetFormatName( (uint16) eFormat ) );
         VSIFCloseL( fp );
@@ -267,22 +267,20 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
     // Create a corresponding GDALDataset
     // -----------------------------------------------------------------
 
-    IntergraphDataset *poDS;
-
-    poDS = new IntergraphDataset();
+    IntergraphDataset *poDS = new IntergraphDataset();
     poDS->eAccess = poOpenInfo->eAccess;
     poDS->pszFilename = CPLStrdup( poOpenInfo->pszFilename );
     poDS->fp = fp;
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Get X Size from Pixels Per Line (PPL)
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     poDS->nRasterXSize = hHeaderOne.PixelsPerLine;
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Get Y Size from Number of Lines (NOL)
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     poDS->nRasterYSize = hHeaderOne.NumberOfLines;
 
@@ -295,24 +293,24 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
         return NULL;
     }
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Get Geo Transformation from Homogeneous Transformation Matrix (TRN)
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     INGR_GetTransMatrix( &hHeaderOne, poDS->adfGeoTransform );
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Set Metadata Information
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
-    poDS->SetMetadataItem( "VERSION", 
+    poDS->SetMetadataItem( "VERSION",
         CPLSPrintf ( "%d", hHeaderOne.GridFileVersion ), "IMAGE_STRUCTURE" );
     poDS->SetMetadataItem( "RESOLUTION",
         CPLSPrintf ( "%d", (hHeaderOne.DeviceResolution < 0)?-hHeaderOne.DeviceResolution:1) );
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Create Band Information
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     int nBands = 0;
     int nBandOffset = 0;
@@ -323,22 +321,32 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
     {
         VSIFSeekL( poDS->fp, nBandOffset, SEEK_SET );
 
-        VSIFReadL( abyBuf, 1, SIZEOF_HDR1, poDS->fp );
+        if( VSIFReadL( abyBuf, 1, SIZEOF_HDR1, poDS->fp ) != SIZEOF_HDR1 )
+            break;
 
         INGR_HeaderOneDiskToMem( &poDS->hHeaderOne, abyBuf );
+        if( hHeaderOne.PixelsPerLine != poDS->hHeaderOne.PixelsPerLine ||
+            hHeaderOne.NumberOfLines != poDS->hHeaderOne.NumberOfLines )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Not all bands have same dimensions");
+            delete poDS;
+            return NULL;
+        }
 
-        VSIFReadL( abyBuf, 1, SIZEOF_HDR2_A, poDS->fp );
+        if( VSIFReadL( abyBuf, 1, SIZEOF_HDR2_A, poDS->fp ) != SIZEOF_HDR2_A )
+            break;
 
         INGR_HeaderTwoADiskToMem( &poDS->hHeaderTwo, abyBuf );
 
         switch( eFormat )
         {
         case JPEGRGB:
-        case JPEGCYMK:
+        case JPEGCMYK:
         {
             IntergraphBitmapBand* poBand;
             nBands++;
-            poDS->SetBand( nBands, 
+            poDS->SetBand( nBands,
                 poBand = new IntergraphBitmapBand( poDS, nBands, nBandOffset, 1 ));
             if (poBand->pabyBMPBlock == NULL)
             {
@@ -346,7 +354,7 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
                 return NULL;
             }
             nBands++;
-            poDS->SetBand( nBands, 
+            poDS->SetBand( nBands,
                 poBand = new IntergraphBitmapBand( poDS, nBands, nBandOffset, 2 ));
             if (poBand->pabyBMPBlock == NULL)
             {
@@ -354,7 +362,7 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
                 return NULL;
             }
             nBands++;
-            poDS->SetBand( nBands, 
+            poDS->SetBand( nBands,
                 poBand = new IntergraphBitmapBand( poDS, nBands, nBandOffset, 3 ));
             if (poBand->pabyBMPBlock == NULL)
             {
@@ -368,7 +376,7 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
         {
             IntergraphBitmapBand* poBand;
             nBands++;
-            poDS->SetBand( nBands, 
+            poDS->SetBand( nBands,
                 poBand = new IntergraphBitmapBand( poDS, nBands, nBandOffset ));
             if (poBand->pabyBMPBlock == NULL)
             {
@@ -383,7 +391,7 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
         {
             IntergraphRLEBand* poBand;
             nBands++;
-            poDS->SetBand( nBands, 
+            poDS->SetBand( nBands,
                 poBand = new IntergraphRLEBand( poDS, nBands, nBandOffset ));
             if (poBand->pabyBlockBuf == NULL || poBand->pabyRLEBlock == NULL)
             {
@@ -397,7 +405,7 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
         {
             IntergraphRLEBand* poBand;
             nBands++;
-            poDS->SetBand( nBands, 
+            poDS->SetBand( nBands,
                 poBand = new IntergraphRLEBand( poDS, nBands, nBandOffset, 1 ));
             if (poBand->pabyBlockBuf == NULL || poBand->pabyRLEBlock == NULL)
             {
@@ -405,7 +413,7 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
                 return NULL;
             }
             nBands++;
-            poDS->SetBand( nBands, 
+            poDS->SetBand( nBands,
                 poBand = new IntergraphRLEBand( poDS, nBands, nBandOffset, 2 ));
             if (poBand->pabyBlockBuf == NULL || poBand->pabyRLEBlock == NULL)
             {
@@ -413,7 +421,7 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
                 return NULL;
             }
             nBands++;
-            poDS->SetBand( nBands, 
+            poDS->SetBand( nBands,
                 poBand = new IntergraphRLEBand( poDS, nBands, nBandOffset, 3 ));
             if (poBand->pabyBlockBuf == NULL || poBand->pabyRLEBlock == NULL)
             {
@@ -426,7 +434,7 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
         {
             IntergraphRGBBand* poBand;
             nBands++;
-            poDS->SetBand( nBands, 
+            poDS->SetBand( nBands,
                 poBand = new IntergraphRGBBand( poDS, nBands, nBandOffset, 1 ));
             if (poBand->pabyBlockBuf == NULL)
             {
@@ -434,7 +442,7 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
                 return NULL;
             }
             nBands++;
-            poDS->SetBand( nBands, 
+            poDS->SetBand( nBands,
                 poBand = new IntergraphRGBBand( poDS, nBands, nBandOffset, 2 ));
             if (poBand->pabyBlockBuf == NULL)
             {
@@ -442,7 +450,7 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
                 return NULL;
             }
             nBands++;
-            poDS->SetBand( nBands, 
+            poDS->SetBand( nBands,
                 poBand = new IntergraphRGBBand( poDS, nBands, nBandOffset, 3 ));
             if (poBand->pabyBlockBuf == NULL)
             {
@@ -455,7 +463,7 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
         {
             IntergraphRasterBand* poBand;
             nBands++;
-            poDS->SetBand( nBands, 
+            poDS->SetBand( nBands,
                 poBand = new IntergraphRasterBand( poDS, nBands, nBandOffset ));
             if (poBand->pabyBlockBuf == NULL)
             {
@@ -475,16 +483,16 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
 
     poDS->nBands = nBands;
 
-    // -------------------------------------------------------------------- 
-    // Initialize any PAM information                                 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
+    // Initialize any PAM information
+    // --------------------------------------------------------------------
 
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->TryLoadXML();
 
-    /* -------------------------------------------------------------------- */
+    /* --------------------------------------------------------------------*/
     /*      Check for external overviews.                                   */
-    /* -------------------------------------------------------------------- */
+    /* --------------------------------------------------------------------*/
 
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
@@ -496,31 +504,30 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
 //  ----------------------------------------------------------------------------
 
 GDALDataset *IntergraphDataset::Create( const char *pszFilename,
-                                        int nXSize, 
-                                        int nYSize, 
-                                        int nBands, 
+                                        int nXSize,
+                                        int nYSize,
+                                        int nBands,
                                         GDALDataType eType,
                                         char **papszOptions )
 {
     int nDeviceResolution = 1;
-    const char *pszValue;
-    const char *pszCompression = NULL;
 
-    pszValue = CSLFetchNameValue(papszOptions, "RESOLUTION");
+    const char *pszValue = CSLFetchNameValue(papszOptions, "RESOLUTION");
     if( pszValue != NULL )
         nDeviceResolution = -atoi( pszValue );
 
     char *pszExtension = CPLStrlwr(CPLStrdup(CPLGetExtension(pszFilename)));
+    const char *pszCompression = NULL;
     if ( EQUAL( pszExtension, "rle" ) )
         pszCompression = INGR_GetFormatName(RunLengthEncoded);
     CPLFree(pszExtension);
-	
+
     if( eType != GDT_Byte &&
-        eType != GDT_Int16 && 
-        eType != GDT_Int32 && 
-        eType != GDT_UInt16 && 
-        eType != GDT_UInt32 && 
-        eType != GDT_Float32&& 
+        eType != GDT_Int16 &&
+        eType != GDT_Int32 &&
+        eType != GDT_UInt16 &&
+        eType != GDT_UInt32 &&
+        eType != GDT_Float32&&
         eType != GDT_Float64 )
     {
         CPLError( CE_Failure, CPLE_AppDefined, "Data type not supported (%s)",
@@ -528,18 +535,17 @@ GDALDataset *IntergraphDataset::Create( const char *pszFilename,
         return NULL;
     }
 
-    // -------------------------------------------------------------------- 
-    //  Fill headers with minimun information
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
+    //  Fill headers with minimum information
+    // --------------------------------------------------------------------
 
     INGR_HeaderOne  hHdr1;
     INGR_HeaderTwoA hHdr2;
     INGR_ColorTable256 hCTab;
-    int             i;
-    
-    memset(&hHdr1, 0, SIZEOF_HDR1);
-    memset(&hHdr2, 0, SIZEOF_HDR2_A);
-    memset(&hCTab, 0, SIZEOF_CTAB);
+
+    memset(&hHdr1, 0, sizeof(hHdr1));
+    memset(&hHdr2, 0, sizeof(hHdr2));
+    memset(&hCTab, 0, sizeof(hCTab));
 
     hHdr1.HeaderType.Version    = INGR_HEADER_VERSION;
     hHdr1.HeaderType.Type       = INGR_HEADER_TYPE;
@@ -553,12 +559,12 @@ GDALDataset *IntergraphDataset::Create( const char *pszFilename,
     hHdr1.XViewExtent           = 0.0;
     hHdr1.YViewExtent           = 0.0;
     hHdr1.ZViewExtent           = 0.0;
-    for( i = 0; i < 15; i++ )
+    for( int i = 0; i < 15; i++ )
         hHdr1.TransformationMatrix[i]   = 0.0;
     hHdr1.TransformationMatrix[15]      = 1.0;
     hHdr1.PixelsPerLine         = nXSize;
     hHdr1.NumberOfLines         = nYSize;
-    hHdr1.DeviceResolution      = nDeviceResolution;
+    hHdr1.DeviceResolution      = static_cast<int16>(nDeviceResolution);
     hHdr1.ScanlineOrientation   = UpperLeftHorizontal;
     hHdr1.ScannableFlag         = NoLineHeader;
     hHdr1.RotationAngle         = 0.0;
@@ -586,14 +592,14 @@ GDALDataset *IntergraphDataset::Create( const char *pszFilename,
     hHdr2.ColorTableType        = NoColorTable;
     hHdr2.NumberOfCTEntries     = 0;
     hHdr2.Reserved8             = 0;
-    for( i = 0; i < 110; i++ )
+    for( int i = 0; i < 110; i++ )
         hHdr2.Reserved[i]       = 0;
     hHdr2.ApplicationPacketLength   = 0;
     hHdr2.ApplicationPacketPointer  = 0;
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     //  RGB Composite assumption
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     if( eType  == GDT_Byte  &&
         nBands == 3 )
@@ -601,15 +607,15 @@ GDALDataset *IntergraphDataset::Create( const char *pszFilename,
         hHdr1.DataTypeCode = Uncompressed24bit;
     }
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     //  Create output file with minimum header info
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     VSILFILE *fp = VSIFOpenL( pszFilename, "wb+" );
 
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
             "Attempt to create file %s' failed.\n", pszFilename );
         return NULL;
     }
@@ -626,7 +632,7 @@ GDALDataset *IntergraphDataset::Create( const char *pszFilename,
 
     unsigned int n = 0;
 
-    for( i = 0; i < 256; i++ )
+    for( int i = 0; i < 256; i++ )
     {
         STRC2BUF( abyBuf, n, hCTab.Entry[i].v_red );
         STRC2BUF( abyBuf, n, hCTab.Entry[i].v_green );
@@ -637,9 +643,9 @@ GDALDataset *IntergraphDataset::Create( const char *pszFilename,
 
     VSIFCloseL( fp );
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     //  Returns a new IntergraphDataset from the created file
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     return ( IntergraphDataset * ) GDALOpen( pszFilename, GA_Update );
 }
@@ -648,19 +654,17 @@ GDALDataset *IntergraphDataset::Create( const char *pszFilename,
 //                                               IntergraphDataset::CreateCopy()
 //  ----------------------------------------------------------------------------
 
-GDALDataset *IntergraphDataset::CreateCopy( const char *pszFilename, 
+GDALDataset *IntergraphDataset::CreateCopy( const char *pszFilename,
                                            GDALDataset *poSrcDS,
-                                           int bStrict,
+                                            int /* bStrict  */ ,
                                            char **papszOptions,
-                                           GDALProgressFunc pfnProgress, 
+                                           GDALProgressFunc pfnProgress,
                                            void *pProgressData )
 {
-    (void) bStrict;
-
     int nBands = poSrcDS->GetRasterCount();
     if (nBands == 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "Intergraph driver does not support source dataset with zero band.\n");
         return NULL;
     }
@@ -670,41 +674,38 @@ GDALDataset *IntergraphDataset::CreateCopy( const char *pszFilename,
         return NULL;
     }
 
-    // -------------------------------------------------------------------- 
-    // Query GDAL Data Type 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
+    // Query GDAL Data Type
+    // --------------------------------------------------------------------
 
     GDALDataType eType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Copy metadata
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     char **papszCreateOptions = CSLDuplicate( papszOptions );
-    const char  *pszValue;
-	
-    pszValue = CSLFetchNameValue(papszCreateOptions, "RESOLUTION");
+    const char  *pszValue = CSLFetchNameValue(papszCreateOptions, "RESOLUTION");
     if( pszValue == NULL )
     {
         const char *value = poSrcDS->GetMetadataItem("RESOLUTION");
         if (value)
         {
-            papszCreateOptions = CSLSetNameValue( papszCreateOptions, "RESOLUTION", 
+            papszCreateOptions = CSLSetNameValue( papszCreateOptions, "RESOLUTION",
                 value );
         }
     }
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Create IntergraphDataset
-    // -------------------------------------------------------------------- 
-
-    IntergraphDataset *poDstDS;
-
-    poDstDS = (IntergraphDataset*) IntergraphDataset::Create( pszFilename, 
-        poSrcDS->GetRasterXSize(), 
-        poSrcDS->GetRasterYSize(), 
-        poSrcDS->GetRasterCount(), 
-        eType, 
+    // --------------------------------------------------------------------
+
+    IntergraphDataset *poDstDS
+        = (IntergraphDataset*) IntergraphDataset::Create( pszFilename,
+        poSrcDS->GetRasterXSize(),
+        poSrcDS->GetRasterYSize(),
+        poSrcDS->GetRasterCount(),
+        eType,
         papszCreateOptions );
 
     CSLDestroy( papszCreateOptions );
@@ -714,9 +715,9 @@ GDALDataset *IntergraphDataset::CreateCopy( const char *pszFilename,
         return NULL;
     }
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Copy Transformation Matrix to the dataset
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     double adfGeoTransform[6];
 
@@ -724,17 +725,15 @@ GDALDataset *IntergraphDataset::CreateCopy( const char *pszFilename,
     poSrcDS->GetGeoTransform( adfGeoTransform );
     poDstDS->SetGeoTransform( adfGeoTransform );
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Copy information to the raster band
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
-    GDALRasterBand *poSrcBand;
-    GDALRasterBand *poDstBand;
     double dfMin;
     double dfMax;
     double dfMean;
     double dfStdDev = -1;
-    
+
     for( int i = 1; i <= poDstDS->nBands; i++)
     {
         delete poDstDS->GetRasterBand(i);
@@ -752,10 +751,10 @@ GDALDataset *IntergraphDataset::CreateCopy( const char *pszFilename,
     {
         for( int i = 1; i <= poSrcDS->GetRasterCount(); i++ )
         {
-            poSrcBand = poSrcDS->GetRasterBand(i);
+            GDALRasterBand* poSrcBand = poSrcDS->GetRasterBand(i);
             eType = poSrcDS->GetRasterBand(i)->GetRasterDataType();
 
-            poDstBand = new IntergraphRasterBand( poDstDS, i, 0, eType );
+            GDALRasterBand* poDstBand = new IntergraphRasterBand( poDstDS, i, 0, eType );
             poDstDS->SetBand( i, poDstBand );
 
             poDstBand->SetCategoryNames( poSrcBand->GetCategoryNames() );
@@ -765,18 +764,13 @@ GDALDataset *IntergraphDataset::CreateCopy( const char *pszFilename,
         }
     }
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Copy image data
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     int nXSize = poDstDS->GetRasterXSize();
     int nYSize = poDstDS->GetRasterYSize();
 
-    int nBlockXSize;
-    int nBlockYSize;
-
-    CPLErr eErr = CE_None;
-
     for( int iBand = 1; iBand <= poSrcDS->GetRasterCount(); iBand++ )
     {
         GDALRasterBand *poDstBand = poDstDS->GetRasterBand( iBand );
@@ -786,52 +780,62 @@ GDALDataset *IntergraphDataset::CreateCopy( const char *pszFilename,
         // Copy Untiled / Uncompressed
         // ------------------------------------------------------------
 
-        int   iYOffset, iXOffset;
-        void *pData;
+        int nBlockXSize;
+        int nBlockYSize;
 
         poSrcBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
 
+        // TODO: Is this correct?  It appears to overwrite the block sizes.
         nBlockXSize = nXSize;
         nBlockYSize = 1;
 
-        pData = CPLMalloc( nBlockXSize * nBlockYSize * GDALGetDataTypeSize( eType ) / 8 );
+        void *pData
+            = CPLMalloc( nBlockXSize * nBlockYSize
+                         * GDALGetDataTypeSize( eType ) / 8 );
 
-        for( iYOffset = 0; iYOffset < nYSize; iYOffset += nBlockYSize )
+        for( int iYOffset = 0; iYOffset < nYSize; iYOffset += nBlockYSize )
         {
-            for( iXOffset = 0; iXOffset < nXSize; iXOffset += nBlockXSize )
+            CPLErr eErr = CE_None;
+            for( int iXOffset = 0; iXOffset < nXSize; iXOffset += nBlockXSize )
             {
-                eErr = poSrcBand->RasterIO( GF_Read, 
-                    iXOffset, iYOffset, 
+                eErr = poSrcBand->RasterIO( GF_Read,
+                    iXOffset, iYOffset,
                     nBlockXSize, nBlockYSize,
                     pData, nBlockXSize, nBlockYSize,
                     eType, 0, 0, NULL );
                 if( eErr != CE_None )
                 {
+                    CPLFree( pData );
+                    delete poDstDS;
                     return NULL;
                 }
-                eErr = poDstBand->RasterIO( GF_Write, 
-                    iXOffset, iYOffset, 
+                eErr = poDstBand->RasterIO( GF_Write,
+                    iXOffset, iYOffset,
                     nBlockXSize, nBlockYSize,
                     pData, nBlockXSize, nBlockYSize,
                     eType, 0, 0, NULL );
                 if( eErr != CE_None )
                 {
+                    CPLFree( pData );
+                    delete poDstDS;
                     return NULL;
                 }
             }
-            if( ( eErr == CE_None ) && ( ! pfnProgress( 
+            if( ( eErr == CE_None ) && ( ! pfnProgress(
                 ( iYOffset + 1 ) / ( double ) nYSize, NULL, pProgressData ) ) )
             {
-                eErr = CE_Failure;
                 CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated CreateCopy()" );
+                CPLFree( pData );
+                delete poDstDS;
+                return NULL;
             }
         }
         CPLFree( pData );
     }
 
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
     // Finalize
-    // -------------------------------------------------------------------- 
+    // --------------------------------------------------------------------
 
     poDstDS->FlushCache();
 
@@ -872,10 +876,8 @@ CPLErr IntergraphDataset::SetGeoTransform( double *padfTransform )
 //                                            IntergraphDataset::SetProjection()
 //  ----------------------------------------------------------------------------
 
-CPLErr IntergraphDataset::SetProjection( const char *pszProjString )
-{   
-    (void) pszProjString;
-
+CPLErr IntergraphDataset::SetProjection( const char * /* pszProjString */ )
+{
     return CE_None;
 }
 
@@ -885,22 +887,23 @@ CPLErr IntergraphDataset::SetProjection( const char *pszProjString )
 
 void GDALRegister_INGR()
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "INGR" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "INGR" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-
-        poDriver->SetDescription( "INGR" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Intergraph Raster" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_IntergraphRaster.html" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-            "Byte Int16 Int32 Float32 Float64" );
-        poDriver->pfnOpen = IntergraphDataset::Open;
-        poDriver->pfnCreate    = IntergraphDataset::Create;
-        poDriver->pfnCreateCopy = IntergraphDataset::CreateCopy;
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "INGR" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Intergraph Raster" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_IntergraphRaster.html" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte Int16 Int32 Float32 Float64" );
+
+    poDriver->pfnOpen = IntergraphDataset::Open;
+    poDriver->pfnCreate    = IntergraphDataset::Create;
+    poDriver->pfnCreateCopy = IntergraphDataset::CreateCopy;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/ingr/IntergraphDataset.h b/frmts/ingr/IntergraphDataset.h
index 29b4a89..2532f28 100644
--- a/frmts/ingr/IntergraphDataset.h
+++ b/frmts/ingr/IntergraphDataset.h
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * $Id: IntergraphDataset.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: IntergraphDataset.h 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Intergraph Raster Format support
  * Purpose:  Read selected types of Intergraph Raster Format
@@ -58,18 +58,17 @@ public:
     static GDALDataset *Create( const char *pszFilename,
         int nXSize,
         int nYSize,
-        int nBands, 
+        int nBands,
         GDALDataType eType,
         char **papszOptions );
-    static GDALDataset *CreateCopy( const char *pszFilename, 
+    static GDALDataset *CreateCopy( const char *pszFilename,
         GDALDataset *poSrcDS,
         int bStrict,
         char **papszOptions,
-        GDALProgressFunc pfnProgress, 
+        GDALProgressFunc pfnProgress,
         void * pProgressData );
 
     virtual CPLErr GetGeoTransform( double *padfTransform );
     virtual CPLErr SetGeoTransform( double *padfTransform );
     virtual CPLErr SetProjection( const char *pszProjString );
 };
-
diff --git a/frmts/ingr/JpegHelper.cpp b/frmts/ingr/JpegHelper.cpp
index 79fdd69..a54eea6 100644
--- a/frmts/ingr/JpegHelper.cpp
+++ b/frmts/ingr/JpegHelper.cpp
@@ -2,7 +2,7 @@
  * $Id:  $
  *
  * Project:  Creates a jpeg header
- * Purpose:  Abreviated JPEG support
+ * Purpose:  Abbreviated JPEG support
  * Author:   Ivan Lucena, [lucena_ivan at hotmail.com]
  *
  ******************************************************************************
@@ -124,7 +124,7 @@ static const GByte JPGHLP_DQT_chrominance[64] = {
      59, 59, 59, 59, 59, 59, 59, 59
 };
 
-static const GByte ZIGZAG[64] = { 
+static const GByte ZIGZAG[64] = {
       0,  1,  5,  6, 14, 15, 27, 28,
       2,  4,  7, 13, 16, 26, 29, 42,
       3,  8, 12, 17, 25, 30, 41, 43,
@@ -148,8 +148,6 @@ int JPGHLP_HeaderMaker( GByte *pabyBuffer,
                         CPL_UNUSED const int nRestart,
                         const int nQuality )
 {
-    int i;
-
     GByte *pabNext = pabyBuffer;
 
     // ------------------------------------------------------------------------
@@ -163,7 +161,7 @@ int JPGHLP_HeaderMaker( GByte *pabyBuffer,
     // Application Segment
     // ------------------------------------------------------------------------
 
-    *( pabNext++ )      = 0xFF;         // Tag Mark      
+    *( pabNext++ )      = 0xFF;         // Tag Mark
     *( pabNext++ )      = 0xE0;         // APP0
     *( pabNext++ )      = 0x00;         // Segment Length (msb)
     *( pabNext++ )      = 0x10;         // Segment Length (lsb)
@@ -196,7 +194,7 @@ int JPGHLP_HeaderMaker( GByte *pabyBuffer,
         ADJUST( abQuantTables[1], *, 0.5 );
     }
 
-    for( i = 0; i < 2 && i < nComponents; i++ )
+    for( int i = 0; i < 2 && i < nComponents; i++ )
     {
         *( pabNext++ )  = 0xFF;         // Tag Mark
         *( pabNext++ )  = 0xDB;         // DQT
@@ -212,21 +210,21 @@ int JPGHLP_HeaderMaker( GByte *pabyBuffer,
     // ------------------------------------------------------------------------
 
     *( pabNext++ )      = 0xFF;
-    *( pabNext++ )      = 0xC0;         // SOF 
-    *( pabNext++ )      = 0;            // Segment Length (msb) 
+    *( pabNext++ )      = 0xC0;         // SOF
+    *( pabNext++ )      = 0;            // Segment Length (msb)
     if ( nComponents > 1 )
-        *( pabNext++ )  = 17;           // Segment Length (lsb) 
+        *( pabNext++ )  = 17;           // Segment Length (lsb)
     else
         *( pabNext++ )  = 11;           // Segment Length (lsb)
-    *( pabNext++ )      = 8;            // 8-bit Precision 
-    *( pabNext++ )      = (GByte) (nRows >> 8); // Height in rows (msb) 
-    *( pabNext++ )      = (GByte) nRows;// Height in rows (lsb) 
+    *( pabNext++ )      = 8;            // 8-bit Precision
+    *( pabNext++ )      = (GByte) (nRows >> 8); // Height in rows (msb)
+    *( pabNext++ )      = (GByte) nRows;// Height in rows (lsb)
     *( pabNext++ )      = (GByte) (nCols >> 8); // Width in columns (msb)
     *( pabNext++ )      = (GByte) nCols;// Width in columns (lsb)
-    *( pabNext++ )      = (GByte) nComponents;// Number of components 
+    *( pabNext++ )      = (GByte) nComponents;// Number of components
     *( pabNext++ )      = 0;            // Component ID
     *( pabNext++ )      = 0x21;         // Hozontal/Vertical Sampling
-    *( pabNext++ )      = 0;            // Quantization table ID 
+    *( pabNext++ )      = 0;            // Quantization table ID
     if ( nComponents > 1 )
     {
         *( pabNext++ )  = 1;            // Component ID
@@ -263,16 +261,15 @@ int JPGHLP_HeaderMaker( GByte *pabyBuffer,
     pnHTs[1][2]         = sizeof(JPGHLP_2DC_Symbols);
     pnHTs[1][3]         = sizeof(JPGHLP_2AC_Symbols);
 
-    int j, k;
-    for( i = 0; i < 2 && i < nComponents; i++ )
+    for( int i = 0; i < 2 && i < nComponents; i++ )
     {
-        for( j = 0; j < 2; j++ )
+        for( int j = 0; j < 2; j++ )
         {
-            k = j + 2;
-            int nCodes  = pnHTs[i][j];
-            int nSymbols = pnHTs[i][k];
+            const int k = j + 2;
+            const int nCodes  = pnHTs[i][j];
+            const int nSymbols = pnHTs[i][k];
             *( pabNext++ ) = 0xFF;                  // Tag Mark
-            *( pabNext++ ) = 0xc4;                  // DHT 
+            *( pabNext++ ) = 0xc4;                  // DHT
             *( pabNext++ ) = 0;                     // Segment Length (msb)
             *( pabNext++ ) = (GByte) (3 + nCodes + nSymbols); // Segment Length (lsb)
             *( pabNext++ ) = (GByte) ((j << 4) | i);          // Table ID
@@ -288,30 +285,30 @@ int JPGHLP_HeaderMaker( GByte *pabyBuffer,
     // ------------------------------------------------------------------------
 
     *( pabNext++ )      = 0xFF;         // Tag Mark
-    *( pabNext++ )      = 0xDA;         // SOS 
+    *( pabNext++ )      = 0xDA;         // SOS
     if (nComponents > 1 )
     {
-        *( pabNext++ )  = 0;            // Segment Length (msb) 
+        *( pabNext++ )  = 0;            // Segment Length (msb)
         *( pabNext++ )  = 12;           // Segment Length (lsb)
-        *( pabNext++ )  = 3;            // Number of components 
-        *( pabNext++ )  = 0;            // Components 0 
-        *( pabNext++ )  = 0;            // Huffman table ID 
-        *( pabNext++ )  = 1;            // Components 1 
+        *( pabNext++ )  = 3;            // Number of components
+        *( pabNext++ )  = 0;            // Components 0
+        *( pabNext++ )  = 0;            // Huffman table ID
+        *( pabNext++ )  = 1;            // Components 1
         *( pabNext++ )  = 0x11;         // Huffman table ID
-        *( pabNext++ )  = 2;            // Components 2 
+        *( pabNext++ )  = 2;            // Components 2
         *( pabNext++ )  = 0x11;         // Huffman table ID
     }
     else
     {
         *( pabNext++ )  = 0;            // Segment Length (msb)
         *( pabNext++ )  = 8;            // Segment Length (lsb)
-        *( pabNext++ )  = 1;            // Number of components 
+        *( pabNext++ )  = 1;            // Number of components
         *( pabNext++ )  = 0;            // Components 0
         *( pabNext++ )  = 0;            // Huffman table ID
     }
     *( pabNext++ )      = 0;            // First DCT coefficient
-    *( pabNext++ )      = 63;           // Last DCT coefficient 
+    *( pabNext++ )      = 63;           // Last DCT coefficient
     *( pabNext++ )      = 0;            // Spectral selection
 
-    return pabNext - pabyBuffer;
+    return static_cast<int>(pabNext - pabyBuffer);
 }
diff --git a/frmts/ingr/JpegHelper.h b/frmts/ingr/JpegHelper.h
index b97f46d..cc80a93 100644
--- a/frmts/ingr/JpegHelper.h
+++ b/frmts/ingr/JpegHelper.h
@@ -2,7 +2,7 @@
  * $Id:  $
  *
  * Project:  Project:  Creates a jpeg header
- * Purpose:  Abreviated JPEG support
+ * Purpose:  Abbreviated JPEG support
  * Author:   Ivan Lucena, [lucena_ivan at hotmail.com]
  *
  ******************************************************************************
@@ -33,8 +33,8 @@
 #include "cpl_port.h"
 
 int JPGHLP_HeaderMaker( GByte *pabyBuffer,
-                        const int nCols, 
-                        const int nRows, 
-                        const int nComponents, 
+                        const int nCols,
+                        const int nRows,
+                        const int nComponents,
                         const int nRestart,
                         const int nQuality );
diff --git a/frmts/ingr/frmt_intergraphraster.html b/frmts/ingr/frmt_intergraphraster.html
index 4be1740..a7f4eac 100644
--- a/frmts/ingr/frmt_intergraphraster.html
+++ b/frmts/ingr/frmt_intergraphraster.html
@@ -1,231 +1,232 @@
-<!-- $Id: frmt_intergraphraster.html 25785 2013-03-23 11:34:53Z rouault $ -->
-
-<html>
-<head>
-<title>INGR --- Intergraph Raster Format</title>
-</head>
-
-<body bgcolor="#ffffff">
-
-<h1>INGR --- Intergraph Raster Format</h1>
-
-This format is supported for read and writes access.<p>
-
-The Intergraph Raster File Format was the native file format used by
-Intergraph software applications to store raster data. It is manifested in
-several internal data formats.<p>
-
-<h2> Reading INGR Files</h2>
-
-Those are the data formats that the INGR driver supports for reading:<p>
-
-<ul>
-  <li>2 - Byte Integer</li>
-  <li>3 - Word Integer</li>
-  <li>4 - Integers 32 bit</li>
-  <li>5 - Floating Point 32 bit</li>
-  <li>6 - Floating Point 64 bit</li>
-  <li>9 - Run Length Encoded</li>
-  <li>10 - Run Length Encoded Color</li>
-  <li>24 - CCITT Group 4</li>
-  <li>27 - Adaptive RGB</li>
-  <li>28 - Uncompressed 24 bit</li>
-  <li>29 - Adaptive Gray Scale</li>
-  <li>30 - JPEG GRAY</li>
-  <li>31 - JPEG RGB </li>
-  <li>32 - JPEG CYMK</li>
-  <li>65 - Tiled</li>
-  <li>67 - Continuous Tone </li>
-</ul>
-
-The format "65 - Tiled" is not a format; it is just an indication that the file 
-is tiled. In this case the tile header contains the real data format code that could be any of the above formats. The INGR driver can read tiled and untilled 
-instance of any of the supported data formats.<p>
-
-<h2>Writing INGR Files</h2>
-
-Those are the data formats that the INGR driver supports for writing:<p>
-
-<ul>
-  <li>2 - Byte Integer</li>
-  <li>3 - Word Integers</li>
-  <li>4 - Integers 32Bit</li>
-  <li>5 - Floating Point 32Bit</li>
-  <li>6 - Floating Point 64Bit</li>
-</ul>
-
-Type 9 RLE bitonal compression is used when outputting ".rle" file. Other file types are uncompressed.<p>
-
-Note that writing in that format is not encouraged.<p>
-
-<h2>File Extension</h2>
-
-The following is a partial listing of INGR file extensions:<p>
-  
-<table style="width: 501px; height: 394px; text-align: left; margin-left: 0px; margin-right: auto;" border="1">
-  <tbody>
-    <tr>
-    <td align="left">
-      <p>.cot</p>
-      </td>
-    <td align="left">
-      <p>8-bit grayscale or color table data</p>
-      </td>
-  </tr>
-  <tr>
-    <td align="left">
-      <p>.ctc</p>
-      </td>
-    <td align="left">
-      <p>8-bit grayscale using PackBits-type compression (uncommon)</p>
-      </td>
-  </tr>
-  <tr>
-    <td align="left">
-      <p>.rgb</p>
-      </td>
-    <td align="left">
-      <p>24-bit color and grayscale (uncompressed and PackBits-type compression)</p>
-      </td>
-  </tr>
-  <tr>
-    <td align="left">
-      <p>.ctb</p>
-      </td>
-    <td align="left">
-      <p>8-bit color table data (uncompressed or run-length encoded)</p>
-      </td>
-  </tr>
-  <tr>
-    <td align="left">
-      <p>.grd</p>
-      </td>
-    <td align="left">
-      <p>8, 16 and 32 bit elevation data</p>
-      </td>
-  </tr>
-  <tr>
-    <td align="left">
-      <p>.crl</p>
-      </td>
-    <td align="left">
-      <p>8 or 16 bit, run-length compressed grayscale or color table data</p>
-      </td>
-  </tr>
-  <tr>
-    <td align="left">
-      <p>.tpe</p>
-      </td>
-    <td align="left">
-      <p>8 or 16 bit, run-length compressed grayscale or color table data</p>
-      </td>
-  </tr>
-  <tr>
-    <td align="left">
-      <p>.lsr</p>
-      </td>
-    <td align="left">
-      <p>8 or 16 bit, run-length compressed grayscale or color table data</p>
-      </td>
-  </tr>
-  <tr>
-    <td align="left">
-      <p>.rle</p>
-      </td>
-    <td align="left">
-      <p>1-bit run-length compressed data (16-bit runs) </p>
-      </td>
-  </tr>
-  <tr>
-    <td align="left">
-      <p>.cit</p>
-      </td>
-    <td align="left">
-      <p>CCITT G3 or G4 1-bit data</p>
-      </td>
-  </tr>
-  <tr>
-    <td align="left">
-      <p>.g3</p>
-      </td>
-    <td align="left">
-      <p>CCITT G3 1-bit data</p>
-      </td>
-  </tr>
-  <tr>
-    <td align="left">
-      <p>.g4</p>
-      </td>
-    <td align="left">
-      <p>CCITT G4 1-bit data</p>
-      </td>
-  </tr>
-  <tr>
-    <td align="left">
-      <p>.tg4</p>
-      </td>
-    <td align="left">
-      <p>CCITT G4 1-bit data (tiled)</p>
-      </td>
-  </tr>
-  <tr>
-    <td align="left">
-      <p>.cmp</p>
-      </td>
-    <td align="left">
-      <p>JPEG grayscale, RGB, or CMYK</p>
-      </td>
-  </tr>
-  <tr>
-    <td align="left">
-      <p>.jpg
-    </p>
-      </td>
-      <td align="left">
-      <p>JPEG grayscale, RGB, or CMYK</p>
-      </td>
-    </tr>
-  </tbody>
-</table>
-<div style="text-align: left;">Source: <a href="http://www.oreilly.com/www/centers/gff/formats/ingr/index.htm">http://www.oreilly.com/www/centers/gff/formats/ingr/index.htm</a><br>
-</div>
-<br>
-
-The INGR driver does not require any especial file
-extension in order to identify or create an INGR file.<p>
-
-<h2>Georeference</h2>
-
-The INGR driver does not support reading or writing
-georeference information. The reason for that is because there is no universal
-way of storing georeferencing in INGR files. It could have georeference stored
-in a companying .dgn file or in application specific data storage inside the
-file itself.<p>
-
-<h2>Metadata</h2>
-
-The following creation option and bandset metadata is available.<p>
-<ul type="disc">
-<li>RESOLUTION: This is the DPI (dots per inch). Microns not supported.</li>
-</ul>
-
-
-<h2>See Also:</h2>
-
-For more information:<p>
-
-<ul type="disc">
-
-  <li> Implemented as <tt>gdal/frmts/ingr/intergraphraster.cpp</tt>.
-  </li>
-
-  <li> <a href="http://www.intergraph.com">www.intergraph.com</a></li>
-
-  <li><a href="http://www.oreilly.com/www/centers/gff/formats/ingr/index.htm">http://www.oreilly.com/www/centers/gff/formats/ingr/index.htm</a></li>
-
-  <li>File specification: <a href="ftp://ftp.intergraph.com/pub/bbs/scan/note/rffrgps.zip/">ftp://ftp.intergraph.com/pub/bbs/scan/note/rffrgps.zip/</a></li>
-
-</ul>
-
-</body>
-</html>
+<!-- $Id: frmt_intergraphraster.html 33795 2016-03-27 03:34:36Z goatbar $ -->
+
+<html>
+<head>
+<title>INGR --- Intergraph Raster Format</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>INGR --- Intergraph Raster Format</h1>
+
+This format is supported for read and writes access.<p>
+
+The Intergraph Raster File Format was the native file format used by
+Intergraph software applications to store raster data. It is manifested in
+several internal data formats.<p>
+
+<h2> Reading INGR Files</h2>
+
+Those are the data formats that the INGR driver supports for reading:<p>
+
+<ul>
+  <li>2 - Byte Integer</li>
+  <li>3 - Word Integer</li>
+  <li>4 - Integers 32 bit</li>
+  <li>5 - Floating Point 32 bit</li>
+  <li>6 - Floating Point 64 bit</li>
+  <li>9 - Run Length Encoded</li>
+  <li>10 - Run Length Encoded Color</li>
+  <li>24 - CCITT Group 4</li>
+  <li>27 - Adaptive RGB</li>
+  <li>28 - Uncompressed 24 bit</li>
+  <li>29 - Adaptive Gray Scale</li>
+  <li>30 - JPEG GRAY</li>
+  <li>31 - JPEG RGB </li>
+  <li>32 - JPEG CMYK</li>
+  <li>65 - Tiled</li>
+  <li>67 - Continuous Tone </li>
+</ul>
+
+The format "65 - Tiled" is not a format; it is just an indication that the
+file is tiled. In this case the tile header contains the real data format code
+that could be any of the above formats. The INGR driver can read tiled and
+untiled instance of any of the supported data formats.<p>
+
+<h2>Writing INGR Files</h2>
+
+Those are the data formats that the INGR driver supports for writing:<p>
+
+<ul>
+  <li>2 - Byte Integer</li>
+  <li>3 - Word Integers</li>
+  <li>4 - Integers 32Bit</li>
+  <li>5 - Floating Point 32Bit</li>
+  <li>6 - Floating Point 64Bit</li>
+</ul>
+
+Type 9 RLE bitonal compression is used when outputting ".rle" file. Other file types are uncompressed.<p>
+
+Note that writing in that format is not encouraged.<p>
+
+<h2>File Extension</h2>
+
+The following is a partial listing of INGR file extensions:<p>
+
+<table style="width: 501px; height: 394px; text-align: left; margin-left: 0px; margin-right: auto;" border="1">
+  <tbody>
+    <tr>
+    <td align="left">
+      <p>.cot</p>
+      </td>
+    <td align="left">
+      <p>8-bit grayscale or color table data</p>
+      </td>
+  </tr>
+  <tr>
+    <td align="left">
+      <p>.ctc</p>
+      </td>
+    <td align="left">
+      <p>8-bit grayscale using PackBits-type compression (uncommon)</p>
+      </td>
+  </tr>
+  <tr>
+    <td align="left">
+      <p>.rgb</p>
+      </td>
+    <td align="left">
+      <p>24-bit color and grayscale (uncompressed and PackBits-type compression)</p>
+      </td>
+  </tr>
+  <tr>
+    <td align="left">
+      <p>.ctb</p>
+      </td>
+    <td align="left">
+      <p>8-bit color table data (uncompressed or run-length encoded)</p>
+      </td>
+  </tr>
+  <tr>
+    <td align="left">
+      <p>.grd</p>
+      </td>
+    <td align="left">
+      <p>8, 16 and 32 bit elevation data</p>
+      </td>
+  </tr>
+  <tr>
+    <td align="left">
+      <p>.crl</p>
+      </td>
+    <td align="left">
+      <p>8 or 16 bit, run-length compressed grayscale or color table data</p>
+      </td>
+  </tr>
+  <tr>
+    <td align="left">
+      <p>.tpe</p>
+      </td>
+    <td align="left">
+      <p>8 or 16 bit, run-length compressed grayscale or color table data</p>
+      </td>
+  </tr>
+  <tr>
+    <td align="left">
+      <p>.lsr</p>
+      </td>
+    <td align="left">
+      <p>8 or 16 bit, run-length compressed grayscale or color table data</p>
+      </td>
+  </tr>
+  <tr>
+    <td align="left">
+      <p>.rle</p>
+      </td>
+    <td align="left">
+      <p>1-bit run-length compressed data (16-bit runs) </p>
+      </td>
+  </tr>
+  <tr>
+    <td align="left">
+      <p>.cit</p>
+      </td>
+    <td align="left">
+      <p>CCITT G3 or G4 1-bit data</p>
+      </td>
+  </tr>
+  <tr>
+    <td align="left">
+      <p>.g3</p>
+      </td>
+    <td align="left">
+      <p>CCITT G3 1-bit data</p>
+      </td>
+  </tr>
+  <tr>
+    <td align="left">
+      <p>.g4</p>
+      </td>
+    <td align="left">
+      <p>CCITT G4 1-bit data</p>
+      </td>
+  </tr>
+  <tr>
+    <td align="left">
+      <p>.tg4</p>
+      </td>
+    <td align="left">
+      <p>CCITT G4 1-bit data (tiled)</p>
+      </td>
+  </tr>
+  <tr>
+    <td align="left">
+      <p>.cmp</p>
+      </td>
+    <td align="left">
+      <p>JPEG grayscale, RGB, or CMYK</p>
+      </td>
+  </tr>
+  <tr>
+    <td align="left">
+      <p>.jpg
+    </p>
+      </td>
+      <td align="left">
+      <p>JPEG grayscale, RGB, or CMYK</p>
+      </td>
+    </tr>
+  </tbody>
+</table>
+<div style="text-align: left;">Source: <a href="http://www.oreilly.com/www/centers/gff/formats/ingr/index.htm">http://www.oreilly.com/www/centers/gff/formats/ingr/index.htm</a><br>
+</div>
+<br>
+
+The INGR driver does not require any especial file
+extension in order to identify or create an INGR file.<p>
+
+<h2>Georeference</h2>
+
+The INGR driver does not support reading or writing
+georeference information. The reason for that is because there is no universal
+way of storing georeferencing in INGR files. It could have georeference stored
+in a accompanying .dgn file or in application specific data storage inside the
+file itself.<p>
+
+<h2>Metadata</h2>
+
+The following creation option and bandset metadata is available.<p>
+<ul type="disc">
+<li>RESOLUTION: This is the DPI (dots per inch). Microns not supported.</li>
+</ul>
+
+
+<h2>See Also:</h2>
+
+For more information:<p>
+
+<ul type="disc">
+
+  <li> Implemented as <tt>gdal/frmts/ingr/intergraphraster.cpp</tt>.
+  </li>
+
+  <li> <a href="http://www.intergraph.com">www.intergraph.com</a></li>
+
+  <li><a href="http://www.oreilly.com/www/centers/gff/formats/ingr/index.htm">http://www.oreilly.com/www/centers/gff/formats/ingr/index.htm</a></li>
+
+  <li>File specification: <a href="ftp://ftp.intergraph.com/pub/bbs/scan/note/rffrgps.zip/">ftp://ftp.intergraph.com/pub/bbs/scan/note/rffrgps.zip/</a></li>
+
+</ul>
+
+</body>
+</html>
diff --git a/frmts/iris/irisdataset.cpp b/frmts/iris/irisdataset.cpp
index cb7d0f7..5d79e28 100644
--- a/frmts/iris/irisdataset.cpp
+++ b/frmts/iris/irisdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: irisdataset.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: irisdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  IRIS Reader
  * Purpose:  All code for IRIS format Reader
@@ -38,16 +38,13 @@
 #  define RAD2DEG (180.0/M_PI)
 #endif
 
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
-#include <sstream>
-
 
-CPL_CVSID("$Id: irisdataset.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+#include <sstream>
 
-CPL_C_START
-void	GDALRegister_IRIS(void);
-CPL_C_END
+CPL_CVSID("$Id: irisdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 #define ARRAY_ELEMENT_COUNT(x) ((sizeof(x))/sizeof(x[0]))
 
@@ -69,8 +66,8 @@ class IRISDataset : public GDALPamDataset
     double                dfNoDataValue;
     static const char* const   aszProductNames[];
     static const char* const   aszDataTypeCodes[];
-    static const char* const   aszDataTypes[];   
-    static const char* const   aszProjections[];   
+    static const char* const   aszDataTypes[];
+    static const char* const   aszProjections[];
     unsigned short        nProductCode;
     unsigned short        nDataTypeCode;
     unsigned char         nProjectionCode;
@@ -80,16 +77,16 @@ class IRISDataset : public GDALPamDataset
     int                   bHasLoadedProjection;
     void                  LoadProjection();
     std::pair <double,double> GeodesicCalculation(float fLat, float fLon, float fAngle, float fDist, float fEquatorialRadius, float fPolarRadius, float fFlattening);
-    public:
-        IRISDataset();
-        ~IRISDataset();
+
+public:
+    IRISDataset();
+    ~IRISDataset();
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int Identify( GDALOpenInfo * );
 
     CPLErr 	GetGeoTransform( double * padfTransform );
     const char *GetProjectionRef();
- 
 };
 
 const char* const IRISDataset::aszProductNames[]= {
@@ -137,6 +134,7 @@ const char* const IRISDataset::aszDataTypes[]={
     "Albedo (2 byte)", "VIL Density (2 byte)", "Turbulence (2 byte)"};
 const char* const IRISDataset::aszProjections[]={
     "Azimutal equidistant","Mercator","Polar Stereographic","UTM",
+    // FIXME: is it a typo here or in IRIS itself: Perspective or Prespective ?
     "Prespective from geosync","Equidistant cylindrical","Gnomonic",
     "Gauss conformal","Lambert conformal conic"};
 
@@ -150,14 +148,13 @@ class IRISRasterBand : public GDALPamRasterBand
 {
     friend class IRISDataset;
 
- 
     unsigned char*        pszRecord;
     int                   bBufferAllocFailed;
 
-    public:
-        IRISRasterBand( IRISDataset *, int );
-        ~IRISRasterBand();
-    
+public:
+    IRISRasterBand( IRISDataset *, int );
+    ~IRISRasterBand();
+
     virtual CPLErr IReadBlock( int, int, void * );
 
     virtual double          GetNoDataValue( int * );
@@ -169,10 +166,10 @@ class IRISRasterBand : public GDALPamRasterBand
 /*                           IRISRasterBand()                           */
 /************************************************************************/
 
-IRISRasterBand::IRISRasterBand( IRISDataset *poDS, int nBand )
+IRISRasterBand::IRISRasterBand( IRISDataset *poDSIn, int nBandIn )
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
     eDataType = GDT_Float32;
     nBlockXSize = poDS->GetRasterXSize();
     nBlockYSize = 1;
@@ -210,12 +207,10 @@ CPLErr IRISRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
         if (bBufferAllocFailed)
             return CE_Failure;
 
-        pszRecord = (unsigned char *) VSIMalloc(nBlockXSize*nDataLength);
+        pszRecord = (unsigned char *) VSI_MALLOC_VERBOSE(nBlockXSize*nDataLength);
 
         if (pszRecord == NULL)
         {
-            CPLError(CE_Failure, CPLE_OutOfMemory,
-                     "Cannot allocate scanline buffer");
             bBufferAllocFailed = TRUE;
             return CE_Failure;
         }
@@ -229,15 +224,15 @@ CPLErr IRISRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 
     if( (int)VSIFReadL( pszRecord, nBlockXSize*nDataLength, 1, poGDS->fp ) != 1 )
         return CE_Failure;
-    
+
     //If datatype is dbZ or dBT:
     //See point 3.3.3 at page 3.33 of the manual
     if(poGDS->nDataTypeCode == 2 || poGDS->nDataTypeCode == 1){
         float fVal;
         for (i=0;i<nBlockXSize;i++){
-            fVal = (((float) *(pszRecord+i*nDataLength)) -64)/2.0;
-            if (fVal == 95.5)
-                fVal = -9999;
+            fVal = (((float) *(pszRecord+i*nDataLength)) -64)/2.0f;
+            if (fVal == 95.5f)
+                fVal = -9999.0f;
             ((float *) pImage)[i] = fVal;
         }
     //If datatype is dbZ2 or dBT2:
@@ -245,9 +240,9 @@ CPLErr IRISRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     } else if(poGDS->nDataTypeCode == 8 || poGDS->nDataTypeCode == 9){
         float fVal;
         for (i=0;i<nBlockXSize;i++){
-            fVal = (((float) CPL_LSBUINT16PTR(pszRecord+i*nDataLength)) - 32768)/100.0;
-            if (fVal == 327.67)
-                fVal = -9999;
+            fVal = (((float) CPL_LSBUINT16PTR(pszRecord+i*nDataLength)) - 32768)/100.0f;
+            if (fVal == 327.67f)
+                fVal = -9999.0f;
             ((float *) pImage)[i] = fVal;
         }
     //Fliquid2 (Rain1 & Rainn products)
@@ -260,74 +255,74 @@ CPLErr IRISRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
             nExp = nVal>>12;
             nMantissa = nVal - (nExp<<12);
             if (nVal == 65535)
-                fVal2 = -9999;
+                fVal2 = -9999.0f;
             else if (nExp == 0)
-                fVal2 = (float) nMantissa / 1000.0;
+                fVal2 = (float) nMantissa / 1000.0f;
             else
-                fVal2 = (float)((nMantissa+4096)<<(nExp-1))/1000.0;
+                fVal2 = (float)((nMantissa+4096)<<(nExp-1))/1000.0f;
             ((float *) pImage)[i] = fVal2;
         }
     //VIL2 (VIL products)
     //See point 3.3.41 at page 3.54 of the manual
-    } else if(poGDS->nDataTypeCode == 33){ 
+    } else if(poGDS->nDataTypeCode == 33){
         float fVal;
         for (i=0;i<nBlockXSize;i++){
             fVal = (float) CPL_LSBUINT16PTR(pszRecord+i*nDataLength);
-            if (fVal == 65535)
-                ((float *) pImage)[i] = -9999;
+            if (fVal == 65535.0f)
+                ((float *) pImage)[i] = -9999.0f;
             else if (fVal == 0)
-                ((float *) pImage)[i] = -1;
+                ((float *) pImage)[i] = -1.0f;
             else
-                ((float *) pImage)[i] = (fVal-1)/1000;
+                ((float *) pImage)[i] = (fVal-1)/1000.0f;
         }
-    //HEIGTH (TOPS products)
+    //HEIGHT (TOPS products)
     //See point 3.3.14 at page 3.46 of the manual
-    } else if(poGDS->nDataTypeCode == 32){ 
+    } else if(poGDS->nDataTypeCode == 32){
         unsigned char nVal;
         for (i=0;i<nBlockXSize;i++){
             nVal =  *(pszRecord+i*nDataLength) ;
             if (nVal == 255)
-                ((float *) pImage)[i] = -9999;
+                ((float *) pImage)[i] = -9999.0f;
             else if (nVal == 0)
-                ((float *) pImage)[i] = -1;
+                ((float *) pImage)[i] = -1.0f;
             else
-                ((float *) pImage)[i] = ((float) nVal - 1) / 10;
-        }		
+                ((float *) pImage)[i] = ((float) nVal - 1) / 10.0f;
+        }
     //VEL (Velocity 1-Byte in PPI & others)
     //See point 3.3.37 at page 3.53 of the manual
     } else if(poGDS->nDataTypeCode == 3){
           float fVal;
         for (i=0;i<nBlockXSize;i++){
             fVal = (float) *(pszRecord+i*nDataLength);
-            if (fVal == 0)
-                fVal = -9997; 
-            else if(fVal == 1)
-                fVal = -9998; 
-            else if(fVal == 255)
-                fVal = -9999; 
+            if (fVal == 0.0f)
+                fVal = -9997.0f;
+            else if(fVal == 1.0f)
+                fVal = -9998.0f;
+            else if(fVal == 255.0f)
+                fVal = -9999.0f;
             else
-                fVal = poGDS->fNyquistVelocity * (fVal - 128)/127;
-            ((float *) pImage)[i] = fVal;     
-        }       
+                fVal = poGDS->fNyquistVelocity * (fVal - 128.0f)/127.0f;
+            ((float *) pImage)[i] = fVal;
+        }
     //SHEAR (1-Byte Shear)
     //See point 3.3.23 at page 3.39 of the manual
     } else if(poGDS->nDataTypeCode == 35){
         float fVal;
         for (i=0;i<nBlockXSize;i++){
             fVal = (float) *(pszRecord+i*nDataLength);
-            if (fVal == 0.0)
-                fVal = -9998;
-            else if (fVal == 255.0)
-                fVal = -9999;
+            if (fVal == 0.0f)
+                fVal = -9998.0f;
+            else if (fVal == 255.0f)
+                fVal = -9999.0f;
             else
-                fVal = (fVal - 128) * 0.2;
+                fVal = (fVal - 128.0f) * 0.2f;
             ((float *) pImage)[i] = fVal;
         }
 
     }
 
     return CE_None;
-} 
+}
 
 /************************************************************************/
 /*                           SetNoDataValue()                           */
@@ -380,11 +375,10 @@ double IRISRasterBand::GetNoDataValue( int * pbSuccess )
 /************************************************************************/
 
 IRISDataset::IRISDataset()
-
+    : fp(NULL), bNoDataSet(0), dfNoDataValue(0.0), nProductCode(0),
+      nDataTypeCode(0), nProjectionCode(0), fNyquistVelocity(0.0),
+      pszSRS_WKT(NULL), bHasLoadedProjection(FALSE)
 {
-    bHasLoadedProjection = FALSE;
-    fp = NULL;
-    pszSRS_WKT = NULL;
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
@@ -416,8 +410,8 @@ void IRISDataset::LoadProjection()
     float fInvFlattening = float( (CPL_LSBUINT32PTR (abyHeader+224+320+12)))/1000000; //Point 3.2.27 pag 3-15
     float fFlattening;
     float fPolarRadius;
-    
-    if(fEquatorialRadius == 0){ // if Radius is 0, change to 6371000 Point 3.2.27 pag 3-15 (old IRIS verions)
+
+    if(fEquatorialRadius == 0){ // if Radius is 0, change to 6371000 Point 3.2.27 pag 3-15 (old IRIS versions)
         fEquatorialRadius = 6371000;
         fPolarRadius = fEquatorialRadius;
         fInvFlattening = 0;
@@ -431,52 +425,52 @@ void IRISDataset::LoadProjection()
             fPolarRadius = fEquatorialRadius * (1-fFlattening);
         }
     }
-    
+
     float fCenterLon = 360 * float((CPL_LSBUINT32PTR (abyHeader+112+320+12))) / 4294967295LL;
     float fCenterLat = 360 * float((CPL_LSBUINT32PTR (abyHeader+108+320+12))) / 4294967295LL;
 
     float fProjRefLon = 360 * float((CPL_LSBUINT32PTR (abyHeader+244+320+12))) / 4294967295LL;
-    float fProjRefLat = 360 * float((CPL_LSBUINT32PTR (abyHeader+240+320+12))) / 4294967295LL; 
-    
+    float fProjRefLat = 360 * float((CPL_LSBUINT32PTR (abyHeader+240+320+12))) / 4294967295LL;
+
     float fRadarLocX, fRadarLocY, fScaleX, fScaleY;
 
     fRadarLocX = float (CPL_LSBSINT32PTR (abyHeader + 112 + 12 )) / 1000;
     fRadarLocY = float (CPL_LSBSINT32PTR (abyHeader + 116 + 12 )) / 1000;
- 
+
     fScaleX = float (CPL_LSBSINT32PTR (abyHeader + 88 + 12 )) / 100;
     fScaleY = float (CPL_LSBSINT32PTR (abyHeader + 92 + 12 )) / 100;
-    
+
     OGRSpatialReference oSRSOut;
-    
+
     ////MERCATOR PROJECTION
     if(EQUAL(aszProjections[nProjectionCode],"Mercator")){
         OGRCoordinateTransformation *poTransform = NULL;
         OGRSpatialReference oSRSLatLon;
-        
+
         oSRSOut.SetGeogCS("unnamed ellipse",
-                        "unknown", 
-                        "unnamed", 
-                        fEquatorialRadius, fInvFlattening, 
-                        "Greenwich", 0.0, 
+                        "unknown",
+                        "unnamed",
+                        fEquatorialRadius, fInvFlattening,
+                        "Greenwich", 0.0,
                         "degree", 0.0174532925199433);
-    
+
         oSRSOut.SetMercator(fProjRefLat,fProjRefLon,1,0,0);
 	oSRSOut.exportToWkt(&pszSRS_WKT);
-        
+
         //The center coordinates are given in LatLon on the defined ellipsoid. Necessary to calculate geotransform.
-        
+
         oSRSLatLon.SetGeogCS("unnamed ellipse",
-                        "unknown", 
-                        "unnamed", 
-                        fEquatorialRadius, fInvFlattening, 
-                        "Greenwich", 0.0, 
+                        "unknown",
+                        "unnamed",
+                        fEquatorialRadius, fInvFlattening,
+                        "Greenwich", 0.0,
                         "degree", 0.0174532925199433);
-        
+
         poTransform = OGRCreateCoordinateTransformation( &oSRSLatLon,
                                                   &oSRSOut );
         std::pair <double,double> oPositionX2 = GeodesicCalculation(fCenterLat, fCenterLon, 90, fScaleX, fEquatorialRadius, fPolarRadius, fFlattening);
         std::pair <double,double> oPositionY2 = GeodesicCalculation(fCenterLat, fCenterLon, 0, fScaleY, fEquatorialRadius, fPolarRadius, fFlattening);
-        
+
         double dfLon2, dfLat2;
         dfLon2 = oPositionX2.first;
         dfLat2 = oPositionY2.second;
@@ -491,23 +485,23 @@ void IRISDataset::LoadProjection()
 
         if( poTransform == NULL || !poTransform->Transform( 1, &dfX2, &dfY2 ) )
              CPLError( CE_Failure, CPLE_None, "Transformation Failed\n" );
-        
+
         adfGeoTransform[0] = dfX - (fRadarLocX * (dfX2 - dfX));
         adfGeoTransform[1] = dfX2 - dfX;
         adfGeoTransform[2] = 0.0;
         adfGeoTransform[3] = dfY + (fRadarLocY * (dfY2 - dfY));
         adfGeoTransform[4] = 0.0;
         adfGeoTransform[5] = -1*(dfY2 - dfY);
-        
+
         delete poTransform;
-        
+
     }else if(EQUAL(aszProjections[nProjectionCode],"Azimutal equidistant")){
-        
+
         oSRSOut.SetGeogCS("unnamed ellipse",
-                        "unknown", 
-                        "unnamed", 
-                        fEquatorialRadius, fInvFlattening, 
-                        "Greenwich", 0.0, 
+                        "unknown",
+                        "unnamed",
+                        fEquatorialRadius, fInvFlattening,
+                        "Greenwich", 0.0,
                         "degree", 0.0174532925199433);
         oSRSOut.SetAE(fProjRefLat,fProjRefLon,0,0);
         oSRSOut.exportToWkt(&pszSRS_WKT) ;
@@ -526,7 +520,6 @@ void IRISDataset::LoadProjection()
         adfGeoTransform[4] = 0.0;
         adfGeoTransform[5] = -1*fScaleY;
     }
-    
 }
 
 /******************************************************************************/
@@ -619,7 +612,7 @@ CPLErr IRISDataset::GetGeoTransform( double * padfTransform )
 
 const char *IRISDataset::GetProjectionRef(){
     if (!bHasLoadedProjection)
-        LoadProjection(); 
+        LoadProjection();
     return pszSRS_WKT;
 }
 
@@ -634,6 +627,7 @@ int IRISDataset::Identify( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Confirm that the file is an IRIS file                           */
 /* -------------------------------------------------------------------- */
+    // TODO: Translate to English.
     //Si no el posem, peta al fer el translate, quan s'obre Identify des de GDALIdentifyDriver
     if( poOpenInfo->nHeaderBytes < 640 )
         return FALSE;
@@ -646,7 +640,7 @@ int IRISDataset::Identify( GDALOpenInfo * poOpenInfo )
     /*Check if the two headers are 27 (product hdr) & 26 (product configuration), and the product type is in the range 1 -> 34*/
     if( !(nId1 == 27 && nId2 == 26 && nType > 0 && nType < 35) )
         return FALSE;
-     
+
     return TRUE;
 }
 
@@ -675,7 +669,7 @@ GDALDataset *IRISDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The IRIS driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
@@ -684,9 +678,7 @@ GDALDataset *IRISDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    IRISDataset *poDS;
-
-    poDS = new IRISDataset();
+    IRISDataset *poDS = new IRISDataset();
 
     poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
     if (poDS->fp == NULL)
@@ -694,7 +686,7 @@ GDALDataset *IRISDataset::Open( GDALOpenInfo * poOpenInfo )
         delete poDS;
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read the header.                                                */
 /* -------------------------------------------------------------------- */
@@ -708,21 +700,19 @@ GDALDataset *IRISDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->nRasterYSize = nYSize;
     if  (poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Invalid dimensions : %d x %d", 
-                  poDS->nRasterXSize, poDS->nRasterYSize); 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Invalid dimensions : %d x %d",
+                  poDS->nRasterXSize, poDS->nRasterYSize);
         delete poDS;
         return NULL;
     }
-    
+
     if( !GDALCheckBandCount(nNumBands, TRUE) )
     {
         delete poDS;
         return NULL;
     }
 
-    
-    
 /* -------------------------------------------------------------------- */
 /*      Setting the Metadata                                            */
 /* -------------------------------------------------------------------- */
@@ -734,9 +724,9 @@ GDALDataset *IRISDataset::Open( GDALOpenInfo * poOpenInfo )
         delete poDS;
         return NULL;
     }
-    
+
     poDS->SetMetadataItem( "PRODUCT",poDS->aszProductNames[poDS->nProductCode]);
-    
+
     poDS->nDataTypeCode = CPL_LSBUINT16PTR (poDS->abyHeader+130+12);
     if( poDS->nDataTypeCode >= ARRAY_ELEMENT_COUNT(poDS->aszDataTypeCodes) )
     {
@@ -777,24 +767,23 @@ GDALDataset *IRISDataset::Open( GDALOpenInfo * poOpenInfo )
 
     ////TIMES
     int nSeconds = CPL_LSBSINT32PTR(poDS->abyHeader+20+12);
-    
+
     int nHour =  (nSeconds - (nSeconds%3600)) /3600;
     int nMinute = ((nSeconds - nHour * 3600) - (nSeconds - nHour * 3600)%60)/ 60;
     int nSecond = nSeconds - nHour * 3600 - nMinute * 60;
-    
+
     short nYear = CPL_LSBSINT16PTR(poDS->abyHeader+26+12);
     short nMonth = CPL_LSBSINT16PTR(poDS->abyHeader+28+12);
     short nDay = CPL_LSBSINT16PTR(poDS->abyHeader+30+12);
 
     poDS->SetMetadataItem( "TIME_PRODUCT_GENERATED", CPLString().Printf("%d-%02d-%02d %02d:%02d:%02d", nYear, nMonth, nDay, nHour, nMinute, nSecond ) );
 
-
     nSeconds = CPL_LSBSINT32PTR(poDS->abyHeader+32+12);
-    
+
     nHour =  (nSeconds - (nSeconds%3600)) /3600;
     nMinute = ((nSeconds - nHour * 3600) - (nSeconds - nHour * 3600)%60)/ 60;
     nSecond = nSeconds - nHour * 3600 - nMinute * 60;
-    
+
     nYear = CPL_LSBSINT16PTR(poDS->abyHeader+26+12);
     nMonth = CPL_LSBSINT16PTR(poDS->abyHeader+28+12);
     nDay = CPL_LSBSINT16PTR(poDS->abyHeader+30+12);
@@ -826,10 +815,10 @@ GDALDataset *IRISDataset::Open( GDALOpenInfo * poOpenInfo )
     char szTaskName[13] = "";
     FillString(szTaskName, sizeof(szTaskName), poDS->abyHeader+74+12);
     poDS->SetMetadataItem( "TASK_NAME",szTaskName);
-   
-    short nRadarHeight = CPL_LSBSINT16PTR(poDS->abyHeader+284+320+12);
+
+    const short nRadarHeight = CPL_LSBSINT16PTR(poDS->abyHeader+284+320+12);
     poDS->SetMetadataItem( "RADAR_HEIGHT",CPLString().Printf("%d m",nRadarHeight));
-    short nGroundHeight = CPL_LSBSINT16PTR(poDS->abyHeader+118+320+12);
+    const short nGroundHeight = CPL_LSBSINT16PTR(poDS->abyHeader+118+320+12);
     poDS->SetMetadataItem( "GROUND_HEIGHT",CPLString().Printf("%d m",nRadarHeight-nGroundHeight)); //Ground height over the sea level
 
     unsigned short nFlags = CPL_LSBUINT16PTR (poDS->abyHeader+86+12);
@@ -845,9 +834,9 @@ GDALDataset *IRISDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
     //Wave values
-    poDS->SetMetadataItem( "PRF",CPLString().Printf("%d Hz",CPL_LSBSINT32PTR(poDS->abyHeader+120+320+12))); 
-    poDS->SetMetadataItem( "WAVELENGTH",CPLString().Printf("%4.2f cm",(float) CPL_LSBSINT32PTR(poDS->abyHeader+148+320+12)/100)); 
-    unsigned short nPolarizationType = CPL_LSBUINT16PTR (poDS->abyHeader+172+320+12);
+    poDS->SetMetadataItem( "PRF",CPLString().Printf("%d Hz",CPL_LSBSINT32PTR(poDS->abyHeader+120+320+12)));
+    poDS->SetMetadataItem( "WAVELENGTH",CPLString().Printf("%4.2f cm",(float) CPL_LSBSINT32PTR(poDS->abyHeader+148+320+12)/100));
+    const unsigned short nPolarizationType = CPL_LSBUINT16PTR (poDS->abyHeader+172+320+12);
     float fNyquist = (CPL_LSBSINT32PTR(poDS->abyHeader+120+320+12))*((float) CPL_LSBSINT32PTR(poDS->abyHeader+148+320+12)/10000)/4; //See section 3.3.37 & 3.2.54
     if (nPolarizationType == 1)
         fNyquist = fNyquist * 2;
@@ -856,10 +845,12 @@ GDALDataset *IRISDataset::Open( GDALOpenInfo * poOpenInfo )
     else if(nPolarizationType == 3)
         fNyquist = fNyquist * 4;
     poDS->fNyquistVelocity = fNyquist;
-    poDS->SetMetadataItem( "NYQUIST_VELOCITY",CPLString().Printf("%.2f m/s",fNyquist)); 
+    poDS->SetMetadataItem( "NYQUIST_VELOCITY",CPLString().Printf("%.2f m/s",fNyquist));
 
-    ///Product dependent metadata (stored in 80 bytes fromm 162 bytes at the product header) See point 3.2.30 at page 3.19 of the manual
-    //See point 3.2.25 at page 3.12 of the manual
+    // Product dependent metadata (stored in 80 bytes from 162 bytes
+    // at the product header) See point 3.2.30 at page 3.19 of the
+    // manual.
+    //See point 3.2.25 at page 3.12 of the manual.
     if (EQUAL(poDS->aszProductNames[poDS->nProductCode],"PPI")){
         //Degrees = 360 * (Binary Angle)*2^N
         //float fElevation = 360 * float((CPL_LSBUINT16PTR (poDS->abyHeader+164+12))) / 65536;
@@ -872,11 +863,11 @@ GDALDataset *IRISDataset::Open( GDALOpenInfo * poOpenInfo )
             poDS->SetMetadataItem( "DATA_TYPE_UNITS","m/s");
         //See point 3.2.2 at page 3.2 of the manual
     } else if (EQUAL(poDS->aszProductNames[poDS->nProductCode],"CAPPI")){
-        float fElevation = ((float) CPL_LSBSINT32PTR(poDS->abyHeader+4+164+12))/100;
+        const float fElevation = ((float) CPL_LSBSINT32PTR(poDS->abyHeader+4+164+12))/100;
         poDS->SetMetadataItem( "CAPPI_BOTTOM_HEIGHT",CPLString().Printf("%.1f m",fElevation));
-        float fAzimuthSmoothingForShear = 360 * float((CPL_LSBUINT16PTR (poDS->abyHeader+10+164+12))) / 65536;
+        const float fAzimuthSmoothingForShear = 360 * float((CPL_LSBUINT16PTR (poDS->abyHeader+10+164+12))) / 65536;
         poDS->SetMetadataItem( "AZIMUTH_SMOOTHING_FOR_SHEAR" ,CPLString().Printf("%.1f", fAzimuthSmoothingForShear));
-        unsigned int  nMaxAgeVVPCorrection = CPL_LSBUINT32PTR (poDS->abyHeader+24+164+12);
+        const unsigned int  nMaxAgeVVPCorrection = CPL_LSBUINT32PTR (poDS->abyHeader+24+164+12);
         poDS->SetMetadataItem( "MAX_AGE_FOR_SHEAR_VVP_CORRECTION" ,CPLString().Printf("%d s", nMaxAgeVVPCorrection));
         if (EQUAL(poDS->aszDataTypeCodes[poDS->nDataTypeCode],"dBZ"))
             poDS->SetMetadataItem( "DATA_TYPE_UNITS","dBZ");
@@ -884,66 +875,69 @@ GDALDataset *IRISDataset::Open( GDALOpenInfo * poOpenInfo )
             poDS->SetMetadataItem( "DATA_TYPE_UNITS","m/s");
         //See point 3.2.32 at page 3.19 of the manual
     } else if (EQUAL(poDS->aszProductNames[poDS->nProductCode],"RAIN1") || EQUAL(poDS->aszProductNames[poDS->nProductCode],"RAINN")){
-        short nNumProducts = CPL_LSBSINT16PTR(poDS->abyHeader+170+320+12);
+        const short nNumProducts = CPL_LSBSINT16PTR(poDS->abyHeader+170+320+12);
         poDS->SetMetadataItem( "NUM_FILES_USED",CPLString().Printf("%d",nNumProducts));
-    
-        float fMinZAcum= (float)((CPL_LSBUINT32PTR (poDS->abyHeader+164+12))-32768)/1000;
+
+        const float fMinZAcum= (float)((CPL_LSBUINT32PTR (poDS->abyHeader+164+12))-32768)/1000;
         poDS->SetMetadataItem( "MINIMUM_Z_TO_ACUMULATE",CPLString().Printf("%f",fMinZAcum));
 
-        unsigned short nSecondsOfAccumulation = CPL_LSBUINT16PTR (poDS->abyHeader+6+164+12);
+        const unsigned short nSecondsOfAccumulation = CPL_LSBUINT16PTR (poDS->abyHeader+6+164+12);
         poDS->SetMetadataItem( "SECONDS_OF_ACCUMULATION",CPLString().Printf("%d s",nSecondsOfAccumulation));
 
-        unsigned int nSpanInputFiles = CPL_LSBUINT32PTR (poDS->abyHeader+24+164+12);
+        const unsigned int nSpanInputFiles = CPL_LSBUINT32PTR (poDS->abyHeader+24+164+12);
         poDS->SetMetadataItem( "SPAN_OF_INPUT_FILES",CPLString().Printf("%d s",nSpanInputFiles));
         poDS->SetMetadataItem( "DATA_TYPE_UNITS","mm");
 
         char szInputProductName[13] = "";
         for(int k=0; k<12;k++)
             szInputProductName[k] = * (char *) (poDS->abyHeader+k+12+164+12);
-        poDS->SetMetadataItem( "INPUT_PRODUCT_NAME",CPLString().Printf("%s",szInputProductName));        
-    
+        poDS->SetMetadataItem( "INPUT_PRODUCT_NAME",CPLString().Printf("%s",szInputProductName));
+
         if (EQUAL(poDS->aszProductNames[poDS->nProductCode],"RAINN"))
-             poDS->SetMetadataItem( "NUM_HOURS_ACCUMULATE",CPLString().Printf("%d",CPL_LSBUINT16PTR (poDS->abyHeader+10+164+12)));   
-        
+             poDS->SetMetadataItem( "NUM_HOURS_ACCUMULATE",CPLString().Printf("%d",CPL_LSBUINT16PTR (poDS->abyHeader+10+164+12)));
+
     //See point 3.2.73 at page 3.36 of the manual
     } else if (EQUAL(poDS->aszProductNames[poDS->nProductCode],"VIL")){
-        float fBottomHeigthInterval = (float) CPL_LSBSINT32PTR(poDS->abyHeader+4+164+12) / 100;
-        poDS->SetMetadataItem( "BOTTOM_OF_HEIGTH_INTERVAL",CPLString().Printf("%.1f m",fBottomHeigthInterval)); 
-        float fTopHeigthInterval = (float) CPL_LSBSINT32PTR(poDS->abyHeader+8+164+12) / 100;
-        poDS->SetMetadataItem( "TOP_OF_HEIGTH_INTERVAL",CPLString().Printf("%.1f m",fTopHeigthInterval));   
+        const float fBottomHeightInterval = (float) CPL_LSBSINT32PTR(poDS->abyHeader+4+164+12) / 100;
+        // TYPO in metadata key: FIXME ?
+        poDS->SetMetadataItem( "BOTTOM_OF_HEIGTH_INTERVAL",CPLString().Printf("%.1f m",fBottomHeightInterval));
+        const float fTopHeightInterval = (float) CPL_LSBSINT32PTR(poDS->abyHeader+8+164+12) / 100;
+        // TYPO in metadata key: FIXME ?
+        poDS->SetMetadataItem( "TOP_OF_HEIGTH_INTERVAL",CPLString().Printf("%.1f m",fTopHeightInterval));
         poDS->SetMetadataItem( "VIL_DENSITY_NOT_AVAILABLE_VALUE","-1");
         poDS->SetMetadataItem( "DATA_TYPE_UNITS","mm");
     //See point 3.2.68 at page 3.36 of the manual
     } else if (EQUAL(poDS->aszProductNames[poDS->nProductCode],"TOPS")){
-        float fZThreshold = (float) CPL_LSBSINT16PTR(poDS->abyHeader+4+164+12) / 16;
+        const float fZThreshold = (float) CPL_LSBSINT16PTR(poDS->abyHeader+4+164+12) / 16;
         poDS->SetMetadataItem( "Z_THRESHOLD",CPLString().Printf("%.1f dBZ",fZThreshold));
         poDS->SetMetadataItem( "ECHO_TOPS_NOT_AVAILABLE_VALUE","-1");
         poDS->SetMetadataItem( "DATA_TYPE_UNITS","km");
     //See point 3.2.20 at page 3.10 of the manual
     } else if (EQUAL(poDS->aszProductNames[poDS->nProductCode],"MAX")){
-        float fBottomInterval = (float) CPL_LSBSINT32PTR(poDS->abyHeader+4+164+12) / 100;
+        const float fBottomInterval = (float) CPL_LSBSINT32PTR(poDS->abyHeader+4+164+12) / 100;
         poDS->SetMetadataItem( "BOTTOM_OF_INTERVAL",CPLString().Printf("%.1f m",fBottomInterval));
-        float fTopInterval = (float) CPL_LSBSINT32PTR(poDS->abyHeader+8+164+12) / 100;
+        const float fTopInterval = (float) CPL_LSBSINT32PTR(poDS->abyHeader+8+164+12) / 100;
         poDS->SetMetadataItem( "TOP_OF_INTERVAL",CPLString().Printf("%.1f m",fTopInterval));
-        int nNumPixelsSidePanels = CPL_LSBSINT32PTR(poDS->abyHeader+12+164+12); 
-        poDS->SetMetadataItem( "NUM_PIXELS_SIDE_PANELS",CPLString().Printf("%d",nNumPixelsSidePanels));         
-        short nHorizontalSmootherSidePanels = CPL_LSBSINT16PTR(poDS->abyHeader+16+164+12); 
-        poDS->SetMetadataItem( "HORIZONTAL_SMOOTHER_SIDE_PANELS",CPLString().Printf("%d",nHorizontalSmootherSidePanels));   
-        short nVerticalSmootherSidePanels = CPL_LSBSINT16PTR(poDS->abyHeader+18+164+12); 
+        const int nNumPixelsSidePanels = CPL_LSBSINT32PTR(poDS->abyHeader+12+164+12);
+        poDS->SetMetadataItem( "NUM_PIXELS_SIDE_PANELS",CPLString().Printf("%d",nNumPixelsSidePanels));
+        const short nHorizontalSmootherSidePanels = CPL_LSBSINT16PTR(poDS->abyHeader+16+164+12);
+        poDS->SetMetadataItem( "HORIZONTAL_SMOOTHER_SIDE_PANELS",CPLString().Printf("%d",nHorizontalSmootherSidePanels));
+        const short nVerticalSmootherSidePanels = CPL_LSBSINT16PTR(poDS->abyHeader+18+164+12);
         poDS->SetMetadataItem( "VERTICAL_SMOOTHER_SIDE_PANELS",CPLString().Printf("%d",nVerticalSmootherSidePanels));
     }
 
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
+    /* coverity[tainted_data] */
     for (int iBandNum = 1; iBandNum <= nNumBands; iBandNum++) {
         poDS->SetBand( iBandNum, new IRISRasterBand( poDS, iBandNum ));
 
         poDS->GetRasterBand(iBandNum)->SetNoDataValue(-9999);
         //Calculating the band height to include it in the band metadata. Only for the CAPPI product
         if (EQUAL(poDS->aszProductNames[poDS->nProductCode],"CAPPI")){
-            float fScaleZ = float (CPL_LSBSINT32PTR (poDS->abyHeader + 96 + 12 )) / 100;
-            float fOffset = ((float) CPL_LSBSINT32PTR(poDS->abyHeader+4+164+12))/100;
+            const float fScaleZ = float (CPL_LSBSINT32PTR (poDS->abyHeader + 96 + 12 )) / 100;
+            const float fOffset = ((float) CPL_LSBSINT32PTR(poDS->abyHeader+4+164+12))/100;
 
             poDS->GetRasterBand(iBandNum)->SetMetadataItem("height",CPLString().Printf("%.0f m",fOffset + fScaleZ*(iBandNum-1)));
         }
@@ -969,24 +963,21 @@ GDALDataset *IRISDataset::Open( GDALOpenInfo * poOpenInfo )
 void GDALRegister_IRIS()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "IRIS" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "IRIS" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "IRIS" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "IRIS data (.PPI, .CAPPi etc)" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#IRIS" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "ppi" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = IRISDataset::Open;
-        poDriver->pfnIdentify = IRISDataset::Identify;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "IRIS" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "IRIS data (.PPI, .CAPPi etc)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#IRIS" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "ppi" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = IRISDataset::Open;
+    poDriver->pfnIdentify = IRISDataset::Identify;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/iso8211/8211createfromxml.cpp b/frmts/iso8211/8211createfromxml.cpp
index 012988f..67b7305 100644
--- a/frmts/iso8211/8211createfromxml.cpp
+++ b/frmts/iso8211/8211createfromxml.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: 8211createfromxml.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: 8211createfromxml.cpp 33035 2016-01-17 22:05:23Z rouault $
  *
  * Project:  ISO8211 library
  * Purpose:  Create a 8211 file from a XML dump file generated by "8211dump -xml"
@@ -27,12 +27,14 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_conv.h"
 #include "cpl_minixml.h"
+#include "cpl_string.h"
 #include "iso8211.h"
 #include <map>
 #include <string>
 
-CPL_CVSID("$Id: 8211createfromxml.cpp 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: 8211createfromxml.cpp 33035 2016-01-17 22:05:23Z rouault $");
 
 int main(int nArgc, char* papszArgv[])
 {
@@ -60,14 +62,14 @@ int main(int nArgc, char* papszArgv[])
         printf( "Usage: 8211createfromxml filename.xml outfilename\n" );
         exit( 1 );
     }
-    
+
     CPLXMLNode* poRoot = CPLParseXMLFile( pszFilename );
     if( poRoot == NULL )
     {
         fprintf(stderr, "Cannot parse XML file '%s'\n", pszFilename);
         exit( 1 );
     }
-    
+
     CPLXMLNode* poXMLDDFModule = CPLSearchXMLNode(poRoot, "=DDFModule");
     if( poXMLDDFModule == NULL )
     {
@@ -104,6 +106,18 @@ int main(int nArgc, char* papszArgv[])
     int nSizeFieldLength = 3;
     int nSizeFieldPos = 4;
 
+    chInterchangeLevel = CPLGetXMLValue(poXMLDDFModule, "_interchangeLevel", CPLSPrintf("%c", chInterchangeLevel))[0];
+    chLeaderIden = CPLGetXMLValue(poXMLDDFModule, "_leaderIden", CPLSPrintf("%c", chLeaderIden))[0];
+    chCodeExtensionIndicator = CPLGetXMLValue(poXMLDDFModule, "_inlineCodeExtensionIndicator", CPLSPrintf("%c", chCodeExtensionIndicator))[0];
+    chVersionNumber = CPLGetXMLValue(poXMLDDFModule, "_versionNumber", CPLSPrintf("%c", chVersionNumber))[0];
+    chAppIndicator = CPLGetXMLValue(poXMLDDFModule, "_appIndicator", CPLSPrintf("%c", chAppIndicator))[0];
+    char szExtendedCharSet[4];
+    snprintf(szExtendedCharSet, sizeof(szExtendedCharSet), "%s", CPLGetXMLValue(poXMLDDFModule, "_extendedCharSet", pszExtendedCharSet));
+    pszExtendedCharSet = szExtendedCharSet;
+    nSizeFieldLength = atoi(CPLGetXMLValue(poXMLDDFModule, "_sizeFieldLength", CPLSPrintf("%d", nSizeFieldLength)));
+    nSizeFieldPos = atoi(CPLGetXMLValue(poXMLDDFModule, "_sizeFieldPos", CPLSPrintf("%d", nSizeFieldPos)));
+    nSizeFieldTag = atoi(CPLGetXMLValue(poXMLDDFModule, "_sizeFieldTag", CPLSPrintf("%d", nSizeFieldTag)));
+
     oModule.Initialize(chInterchangeLevel,
                        chLeaderIden,
                        chCodeExtensionIndicator,
@@ -113,6 +127,7 @@ int main(int nArgc, char* papszArgv[])
                        nSizeFieldLength,
                        nSizeFieldPos,
                        nSizeFieldTag);
+    oModule.SetFieldControlLength(atoi(CPLGetXMLValue(poXMLDDFModule, "_fieldControlLength", CPLSPrintf("%d", oModule.GetFieldControlLength()))));
 
     int bCreated = FALSE;
 
@@ -151,7 +166,7 @@ int main(int nArgc, char* papszArgv[])
                 pszArrayDescr = "";
             else if( eStructCode == dsc_array )
                 pszArrayDescr = "*";
- 
+
             poFDefn->Create( CPLGetXMLValue(psIter, "tag", ""),
                              CPLGetXMLValue(psIter, "fieldName", ""),
                              pszArrayDescr,
@@ -170,11 +185,16 @@ int main(int nArgc, char* papszArgv[])
                 psSubIter = psSubIter->psNext;
             }
 
+            pszFormatControls = CPLGetXMLValue(psIter, "formatControls", NULL);
+            if( pszFormatControls )
+                poFDefn->SetFormatControls(pszFormatControls);
+
             oModule.AddField( poFDefn );
         }
         else if( psIter->eType == CXT_Element &&
                  strcmp(psIter->pszValue, "DDFRecord") == 0 )
         {
+            //const bool bFirstRecord = !bCreated;
             if( !bCreated )
             {
                 oModule.Create( pszOutFilename );
@@ -184,6 +204,12 @@ int main(int nArgc, char* papszArgv[])
             DDFRecord *poRec = new DDFRecord( &oModule );
             std::map<std::string, int> oMapField;
 
+            //if( !bFirstRecord )
+            //    poRec->SetReuseHeader(atoi(CPLGetXMLValue(psIter, "reuseHeader", CPLSPrintf("%d", poRec->GetReuseHeader()))));
+            poRec->SetSizeFieldLength(atoi(CPLGetXMLValue(psIter, "_sizeFieldLength", CPLSPrintf("%d", poRec->GetSizeFieldLength()))));
+            poRec->SetSizeFieldPos(atoi(CPLGetXMLValue(psIter, "_sizeFieldPos", CPLSPrintf("%d", poRec->GetSizeFieldPos()))));
+            poRec->SetSizeFieldTag(atoi(CPLGetXMLValue(psIter, "_sizeFieldTag", CPLSPrintf("%d", poRec->GetSizeFieldTag()))));
+
             CPLXMLNode* psSubIter = psIter->psChild;
             while( psSubIter != NULL )
             {
@@ -198,13 +224,13 @@ int main(int nArgc, char* papszArgv[])
                         fprintf(stderr, "Can't find field '%s'\n", pszFieldName );
                         exit(1);
                     }
-                    
+
                     int nFieldOcc = oMapField[pszFieldName];
                     oMapField[pszFieldName] ++ ;
 
                     poField = poRec->AddField( poFieldDefn );
                     const char* pszValue = CPLGetXMLValue(psSubIter, "value", NULL);
-                    if( pszValue != NULL && strncmp(pszValue, "0x", 2) == 0 )
+                    if( pszValue != NULL && STARTS_WITH(pszValue, "0x") )
                     {
                         pszValue += 2;
                         int nDataLen = (int)strlen(pszValue)  / 2;
@@ -258,7 +284,7 @@ int main(int nArgc, char* papszArgv[])
                                                               pszSubfieldValue );
                                 }
                                 else if( strcmp(pszSubfieldType, "binary") == 0 &&
-                                         strncmp(pszSubfieldValue, "0x", 2) == 0 )
+                                         STARTS_WITH(pszSubfieldValue, "0x") )
                                 {
                                     pszSubfieldValue += 2;
                                     int nDataLen = (int)strlen(pszSubfieldValue) / 2;
diff --git a/frmts/iso8211/8211dump.cpp b/frmts/iso8211/8211dump.cpp
index 212ab23..e0e6e28 100644
--- a/frmts/iso8211/8211dump.cpp
+++ b/frmts/iso8211/8211dump.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: 8211dump.cpp 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: 8211dump.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  SDTS Translator
- * Purpose:  Dump 8211 file in verbose form - just a junk program. 
+ * Purpose:  Dump 8211 file in verbose form - just a junk program.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -33,7 +33,7 @@
 #include "cpl_vsi.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: 8211dump.cpp 27044 2014-03-16 23:41:27Z rouault $");
+CPL_CVSID("$Id: 8211dump.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 
 int main( int nArgc, char ** papszArgv )
@@ -43,6 +43,7 @@ int main( int nArgc, char ** papszArgv )
     const char  *pszFilename = NULL;
     int         bFSPTHack = FALSE;
     int         bXML = FALSE;
+    bool        bAllDetails = false;
 
 /* -------------------------------------------------------------------- */
 /*      Check arguments.                                                */
@@ -53,13 +54,18 @@ int main( int nArgc, char ** papszArgv )
             bFSPTHack = TRUE;
         else if( EQUAL(papszArgv[iArg],"-xml") )
             bXML = TRUE;
+        else if( EQUAL(papszArgv[iArg],"-xml_all_details") )
+        {
+            bXML = TRUE;
+            bAllDetails = true;
+        }
         else
             pszFilename = papszArgv[iArg];
     }
 
     if( pszFilename == NULL )
     {
-        printf( "Usage: 8211dump [-xml] [-fspt_repeating] filename\n" );
+        printf( "Usage: 8211dump [-xml|-xml_all_details] [-fspt_repeating] filename\n" );
         exit( 1 );
     }
 
@@ -77,7 +83,7 @@ int main( int nArgc, char ** papszArgv )
         DDFFieldDefn *poFSPT = oModule.FindFieldDefn( "FSPT" );
 
         if( poFSPT == NULL )
-            fprintf( stderr, 
+            fprintf( stderr,
                      "unable to find FSPT field to set repeating flag.\n" );
         else
             poFSPT->SetRepeatingFlag( TRUE );
@@ -89,7 +95,21 @@ int main( int nArgc, char ** papszArgv )
     DDFRecord       *poRecord;
     if( bXML )
     {
-        printf("<DDFModule>\n");
+        printf("<DDFModule");
+        if( bAllDetails )
+        {
+            printf(" _interchangeLevel=\"%c\"", oModule.GetInterchangeLevel());
+            printf(" _leaderIden=\"%c\"", oModule.GetLeaderIden());
+            printf(" _inlineCodeExtensionIndicator=\"%c\"", oModule.GetCodeExtensionIndicator());
+            printf(" _versionNumber=\"%c\"", oModule.GetVersionNumber());
+            printf(" _appIndicator=\"%c\"", oModule.GetAppIndicator());
+            printf(" _extendedCharSet=\"%s\"", oModule.GetExtendedCharSet());
+            printf(" _fieldControlLength=\"%d\"", oModule.GetFieldControlLength());
+            printf(" _sizeFieldLength=\"%d\"", oModule.GetSizeFieldLength());
+            printf(" _sizeFieldPos=\"%d\"", oModule.GetSizeFieldPos());
+            printf(" _sizeFieldTag=\"%d\"", oModule.GetSizeFieldTag());
+        }
+        printf(">\n");
 
         int nFieldDefnCount = oModule.GetFieldCount();
         for( int i = 0; i < nFieldDefnCount; i++ )
@@ -101,19 +121,19 @@ int main( int nArgc, char ** papszArgv )
                 case dsc_elementary:
                     pszDataStructCode = "elementary";
                     break;
-                    
+
                 case dsc_vector:
                     pszDataStructCode = "vector";
                     break;
-                    
+
                 case dsc_array:
                     pszDataStructCode = "array";
                     break;
-                    
+
                 case dsc_concatenated:
                     pszDataStructCode = "concatenated";
                     break;
-                    
+
                 default:
                     pszDataStructCode = "(unknown)";
                     break;
@@ -125,27 +145,27 @@ int main( int nArgc, char ** papszArgv )
                 case dtc_char_string:
                     pszDataTypeCode = "char_string";
                     break;
-                    
+
                 case dtc_implicit_point:
                     pszDataTypeCode = "implicit_point";
                     break;
-                    
+
                 case dtc_explicit_point:
                     pszDataTypeCode = "explicit_point";
                     break;
-                    
+
                 case dtc_explicit_point_scaled:
                     pszDataTypeCode = "explicit_point_scaled";
                     break;
-                    
+
                 case dtc_char_bit_string:
                     pszDataTypeCode = "char_bit_string";
                     break;
-                    
+
                 case dtc_bit_string:
                     pszDataTypeCode = "bit_string";
                     break;
-                    
+
                 case dtc_mixed_data_type:
                     pszDataTypeCode = "mixed_data_type";
                     break;
@@ -154,16 +174,20 @@ int main( int nArgc, char ** papszArgv )
                     pszDataTypeCode = "(unknown)";
                     break;
             }
-            
-            printf("<DDFFieldDefn tag=\"%s\" fieldName=\"%s\" arrayDescr=\"%s\" "
-                   "formatControls=\"%s\" dataStructCode=\"%s\" dataTypeCode=\"%s\">\n",
+
+            printf("<DDFFieldDefn tag=\"%s\" fieldName=\"%s\""
+                   " dataStructCode=\"%s\" dataTypeCode=\"%s\"",
                    poFieldDefn->GetName(),
                    poFieldDefn->GetDescription(),
-                   poFieldDefn->GetArrayDescr(),
-                   poFieldDefn->GetFormatControls(),
                    pszDataStructCode,
                    pszDataTypeCode);
             int nSubfieldCount = poFieldDefn->GetSubfieldCount();
+            if( bAllDetails || nSubfieldCount == 0 )
+            {
+                printf(" arrayDescr=\"%s\"", poFieldDefn->GetArrayDescr());
+                printf(" formatControls=\"%s\"", poFieldDefn->GetFormatControls());
+            }
+            printf(">\n");
             for( int iSubField = 0; iSubField < nSubfieldCount; iSubField++ )
             {
                 DDFSubfieldDefn* poSubFieldDefn = poFieldDefn->GetSubfield(iSubField);
@@ -176,7 +200,17 @@ int main( int nArgc, char ** papszArgv )
         for( poRecord = oModule.ReadRecord();
              poRecord != NULL; poRecord = oModule.ReadRecord() )
         {
-            printf("<DDFRecord>\n");
+            printf("<DDFRecord");
+            if( bAllDetails )
+            {
+                if( poRecord->GetReuseHeader() )
+                    printf(" reuseHeader=\"1\"");
+                printf(" dataSize=\"%d\"", poRecord->GetDataSize());
+                printf(" _sizeFieldTag=\"%d\"", poRecord->GetSizeFieldTag());
+                printf(" _sizeFieldPos=\"%d\"", poRecord->GetSizeFieldPos());
+                printf(" _sizeFieldLength=\"%d\"", poRecord->GetSizeFieldLength());
+            }
+            printf(">\n");
             int nFieldCount = poRecord->GetFieldCount();
             for( int iField = 0; iField < nFieldCount; iField++ )
             {
@@ -282,12 +316,9 @@ int main( int nArgc, char ** papszArgv )
     }
 
     oModule.Close();
-    
+
 #ifdef DBMALLOC
     malloc_dump(1);
 #endif
 
 }
-
-
-
diff --git a/frmts/iso8211/Makefile.in b/frmts/iso8211/Makefile.in
index 33559f3..e1f5485 100644
--- a/frmts/iso8211/Makefile.in
+++ b/frmts/iso8211/Makefile.in
@@ -17,44 +17,44 @@ libiso8211.a:	$(OBJ)
 	ar r libiso8211.a $(OBJ)
 
 ddfmodule.o:	ddfmodule.cpp
-	$(CXX) -c $(CXXFLAGS) ddfmodule.cpp 
+	$(CXX) -c $(CXXFLAGS) ddfmodule.cpp
 
 ddfutils.o:	ddfutils.cpp
-	$(CXX) -c $(CXXFLAGS) ddfutils.cpp 
+	$(CXX) -c $(CXXFLAGS) ddfutils.cpp
 
 ddffielddefn.o:	ddffielddefn.cpp
-	$(CXX) -c $(CXXFLAGS) ddffielddefn.cpp 
+	$(CXX) -c $(CXXFLAGS) ddffielddefn.cpp
 
 ddfrecord.o:	ddfrecord.cpp
-	$(CXX) -c $(CXXFLAGS) ddfrecord.cpp 
+	$(CXX) -c $(CXXFLAGS) ddfrecord.cpp
 
 ddffield.o:	ddffield.cpp
-	$(CXX) -c $(CXXFLAGS) ddffield.cpp 
+	$(CXX) -c $(CXXFLAGS) ddffield.cpp
 
 ddfsubfielddefn.o:	ddfsubfielddefn.cpp
-	$(CXX) -c $(CXXFLAGS) ddfsubfielddefn.cpp 
+	$(CXX) -c $(CXXFLAGS) ddfsubfielddefn.cpp
 
 cpl_error.o:	cpl_error.cpp
-	$(CXX) -c $(CXXFLAGS) cpl_error.cpp 
+	$(CXX) -c $(CXXFLAGS) cpl_error.cpp
 
 cpl_string.o:	cpl_string.cpp
-	$(CXX) -c $(CXXFLAGS) cpl_string.cpp 
+	$(CXX) -c $(CXXFLAGS) cpl_string.cpp
 
 cpl_conv.o:	cpl_conv.cpp
-	$(CXX) -c $(CXXFLAGS) cpl_conv.cpp 
+	$(CXX) -c $(CXXFLAGS) cpl_conv.cpp
 
 cpl_vsisimple.o:	cpl_vsisimple.cpp
-	$(CXX) -c $(CXXFLAGS) cpl_vsisimple.cpp 
+	$(CXX) -c $(CXXFLAGS) cpl_vsisimple.cpp
 
 #
 #	Mainlines
 #
 
 8211view.o:	8211view.cpp
-	$(CXX) -c $(CXXFLAGS) 8211view.cpp 
+	$(CXX) -c $(CXXFLAGS) 8211view.cpp
 
 8211dump.o:	8211dump.cpp
-	$(CXX) -c $(CXXFLAGS) 8211dump.cpp 
+	$(CXX) -c $(CXXFLAGS) 8211dump.cpp
 
 8211view:	8211view.o libiso8211.a
 	$(CXX) $(CXXFLAGS) 8211view.o libiso8211.a $(LIBS) -o 8211view
diff --git a/frmts/iso8211/ddffield.cpp b/frmts/iso8211/ddffield.cpp
index d239bab..b94eda2 100644
--- a/frmts/iso8211/ddffield.cpp
+++ b/frmts/iso8211/ddffield.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ddffield.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: ddffield.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  ISO 8211 Access
  * Purpose:  Implements the DDFField class.
@@ -30,7 +30,7 @@
 #include "iso8211.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ddffield.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: ddffield.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 // Note, we implement no constructor for this class to make instantiation
 // cheaper.  It is required that the Initialize() be called before anything
@@ -60,7 +60,7 @@ void DDFField::Initialize( DDFFieldDefn *poDefnIn, const char * pachDataIn,
  * subfields is written to the given debugging file handle.  Note that
  * field definition information (ala DDFFieldDefn) isn't written.
  *
- * @param fp The standard io file handle to write to.  ie. stderr
+ * @param fp The standard IO file handle to write to.  i.e. stderr
  */
 
 void DDFField::Dump( FILE * fp )
@@ -100,14 +100,14 @@ void DDFField::Dump( FILE * fp )
             fprintf( fp, "      ...\n" );
             break;
         }
-        
+
         for( int i = 0; i < poDefn->GetSubfieldCount(); i++ )
         {
             int         nBytesConsumed;
 
             poDefn->GetSubfield(i)->DumpData( pachData + iOffset,
                                               nDataSize - iOffset, fp );
-        
+
             poDefn->GetSubfield(i)->GetDataLength( pachData + iOffset,
                                                    nDataSize - iOffset,
                                                    &nBytesConsumed );
@@ -149,7 +149,7 @@ const char *DDFField::GetSubfieldData( DDFSubfieldDefn *poSFDefn,
 
 {
     int         iOffset = 0;
-    
+
     if( poSFDefn == NULL )
         return NULL;
 
@@ -165,15 +165,23 @@ const char *DDFField::GetSubfieldData( DDFSubfieldDefn *poSFDefn,
         {
             int nBytesConsumed;
             DDFSubfieldDefn * poThisSFDefn = poDefn->GetSubfield( iSF );
-            
+
+            if( nDataSize < iOffset )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Invalid data size for subfield %s of %s",
+                         poThisSFDefn->GetName(), poDefn->GetName());
+                return NULL;
+            }
+
             if( poThisSFDefn == poSFDefn && iSubfieldIndex == 0 )
             {
                 if( pnMaxBytes != NULL )
                     *pnMaxBytes = nDataSize - iOffset;
-                
+
                 return pachData + iOffset;
             }
-            
+
             poThisSFDefn->GetDataLength( pachData+iOffset, nDataSize - iOffset,
                                          &nBytesConsumed);
             iOffset += nBytesConsumed;
@@ -191,14 +199,14 @@ const char *DDFField::GetSubfieldData( DDFSubfieldDefn *poSFDefn,
 /************************************************************************/
 
 /**
- * How many times do the subfields of this record repeat?  This    
+ * How many times do the subfields of this record repeat?  This
  * will always be one for non-repeating fields.
  *
  * @return The number of times that the subfields of this record occur
  * in this record.  This will be one for non-repeating fields.
  *
  * @see <a href="example.html">8211view example program</a>
- * for demonstation of handling repeated fields properly.
+ * for a demonstration of handling repeated fields properly.
  */
 
 int DDFField::GetRepeatCount()
@@ -208,7 +216,7 @@ int DDFField::GetRepeatCount()
         return 1;
 
 /* -------------------------------------------------------------------- */
-/*      The occurance count depends on how many copies of this          */
+/*      The occurrence count depends on how many copies of this         */
 /*      field's list of subfields can fit into the data space.          */
 /* -------------------------------------------------------------------- */
     if( poDefn->GetFixedWidth() )
@@ -226,8 +234,8 @@ int DDFField::GetRepeatCount()
 /*      much value for testing.                                         */
 /* -------------------------------------------------------------------- */
     int         iOffset = 0, iRepeatCount = 1;
-    
-    while( TRUE )
+
+    while( true )
     {
         for( int iSF = 0; iSF < poDefn->GetSubfieldCount(); iSF++ )
         {
@@ -237,7 +245,7 @@ int DDFField::GetRepeatCount()
             if( poThisSFDefn->GetWidth() > nDataSize - iOffset )
                 nBytesConsumed = poThisSFDefn->GetWidth();
             else
-                poThisSFDefn->GetDataLength( pachData+iOffset, 
+                poThisSFDefn->GetDataLength( pachData+iOffset,
                                              nDataSize - iOffset,
                                              &nBytesConsumed);
 
@@ -261,18 +269,18 @@ int DDFField::GetRepeatCount()
  * Get field instance data and size.
  *
  * The returned data pointer and size values are suitable for use with
- * DDFRecord::SetFieldRaw(). 
+ * DDFRecord::SetFieldRaw().
  *
- * @param nInstance a value from 0 to GetRepeatCount()-1.  
+ * @param nInstance a value from 0 to GetRepeatCount()-1.
  * @param pnInstanceSize a location to put the size (in bytes) of the
  * field instance data returned.  This size will include the unit terminator
  * (if any), but not the field terminator.  This size pointer may be NULL
  * if not needed.
  *
- * @return the data pointer, or NULL on error. 
+ * @return the data pointer, or NULL on error.
  */
 
-const char *DDFField::GetInstanceData( int nInstance, 
+const char *DDFField::GetInstanceData( int nInstance,
                                        int *pnInstanceSize )
 
 {
@@ -289,7 +297,7 @@ const char *DDFField::GetInstanceData( int nInstance,
     if( poDefn->GetSubfieldCount() == 0 )
     {
         pachWrkData = GetData();
-        if( pnInstanceSize != 0 )
+        if( pnInstanceSize != NULL )
             *pnInstanceSize = GetDataSize();
         return pachWrkData;
     }
@@ -298,13 +306,15 @@ const char *DDFField::GetInstanceData( int nInstance,
 /*      Get a pointer to the start of the existing data for this        */
 /*      iteration of the field.                                         */
 /* -------------------------------------------------------------------- */
-    int         nBytesRemaining1, nBytesRemaining2;
+    int         nBytesRemaining1 = 0, nBytesRemaining2 = 0;
     DDFSubfieldDefn *poFirstSubfield;
 
     poFirstSubfield = poDefn->GetSubfield(0);
 
     pachWrkData = GetSubfieldData(poFirstSubfield, &nBytesRemaining1,
                                nInstance);
+    if( pachWrkData == NULL )
+        return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Figure out the size of the entire field instance, including     */
@@ -313,17 +323,20 @@ const char *DDFField::GetInstanceData( int nInstance,
     if( pnInstanceSize != NULL )
     {
         DDFSubfieldDefn *poLastSubfield;
-        int              nLastSubfieldWidth;
+        int              nLastSubfieldWidth = 0;
         const char          *pachLastData;
-        
+
         poLastSubfield = poDefn->GetSubfield(poDefn->GetSubfieldCount()-1);
-        
-        pachLastData = GetSubfieldData( poLastSubfield, &nBytesRemaining2, 
+
+        pachLastData = GetSubfieldData( poLastSubfield, &nBytesRemaining2,
                                         nInstance );
-        poLastSubfield->GetDataLength( pachLastData, nBytesRemaining2, 
+        if( pachLastData == NULL )
+            return NULL;
+
+        poLastSubfield->GetDataLength( pachLastData, nBytesRemaining2,
                                        &nLastSubfieldWidth );
-        
-        *pnInstanceSize = 
+
+        *pnInstanceSize =
             nBytesRemaining1 - (nBytesRemaining2 - nLastSubfieldWidth);
     }
 
diff --git a/frmts/iso8211/ddffielddefn.cpp b/frmts/iso8211/ddffielddefn.cpp
index 725a657..2051478 100644
--- a/frmts/iso8211/ddffielddefn.cpp
+++ b/frmts/iso8211/ddffielddefn.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ddffielddefn.cpp 28348 2015-01-23 15:27:13Z rouault $
+ * $Id: ddffielddefn.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  ISO 8211 Access
  * Purpose:  Implements the DDFFieldDefn class.
@@ -31,7 +31,7 @@
 #include "cpl_string.h"
 #include <ctype.h>
 
-CPL_CVSID("$Id: ddffielddefn.cpp 28348 2015-01-23 15:27:13Z rouault $");
+CPL_CVSID("$Id: ddffielddefn.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 #define CPLE_DiscardedFormat   1301
 
@@ -40,18 +40,11 @@ CPL_CVSID("$Id: ddffielddefn.cpp 28348 2015-01-23 15:27:13Z rouault $");
 /************************************************************************/
 
 DDFFieldDefn::DDFFieldDefn()
-
-{
-    poModule = NULL;
-    pszTag = NULL;
-    _fieldName = NULL;
-    _arrayDescr = NULL;
-    _formatControls = NULL;
-    nSubfieldCount = 0;
-    papoSubfields = NULL;
-    bRepeatingSubfields = FALSE;
-    nFixedWidth = 0;
-}
+    : poModule(NULL), pszTag(NULL), _fieldName(NULL), _arrayDescr(NULL),
+      _formatControls(NULL), bRepeatingSubfields(FALSE), nFixedWidth(0),
+      _data_struct_code(dsc_elementary), _data_type_code(dtc_char_string),
+      nSubfieldCount(0), papoSubfields(NULL)
+{ }
 
 /************************************************************************/
 /*                           ~DDFFieldDefn()                            */
@@ -60,13 +53,12 @@ DDFFieldDefn::DDFFieldDefn()
 DDFFieldDefn::~DDFFieldDefn()
 
 {
-    int   i;
-
     CPLFree( pszTag );
     CPLFree( _fieldName );
     CPLFree( _arrayDescr );
     CPLFree( _formatControls );
 
+    int i;
     for( i = 0; i < nSubfieldCount; i++ )
         delete papoSubfields[i];
     CPLFree( papoSubfields );
@@ -76,7 +68,7 @@ DDFFieldDefn::~DDFFieldDefn()
 /*                            AddSubfield()                             */
 /************************************************************************/
 
-void DDFFieldDefn::AddSubfield( const char *pszName, 
+void DDFFieldDefn::AddSubfield( const char *pszName,
                                 const char *pszFormat )
 
 {
@@ -99,7 +91,7 @@ void DDFFieldDefn::AddSubfield( DDFSubfieldDefn *poNewSFDefn,
     papoSubfields = (DDFSubfieldDefn ** )
         CPLRealloc( papoSubfields, sizeof(void*) * nSubfieldCount );
     papoSubfields[nSubfieldCount-1] = poNewSFDefn;
-    
+
     if( bDontAddToFormat )
         return;
 
@@ -112,20 +104,20 @@ void DDFFieldDefn::AddSubfield( DDFSubfieldDefn *poNewSFDefn,
         CPLFree( _formatControls );
         _formatControls = CPLStrdup( "()" );
     }
-    
-    int nOldLen = strlen(_formatControls);
-    
-    char *pszNewFormatControls = (char *) 
+
+    int nOldLen = static_cast<int>(strlen(_formatControls));
+
+    char *pszNewFormatControls = (char *)
         CPLMalloc(nOldLen+3+strlen(poNewSFDefn->GetFormat()));
-    
+
     strcpy( pszNewFormatControls, _formatControls );
     pszNewFormatControls[nOldLen-1] = '\0';
     if( pszNewFormatControls[nOldLen-2] != '(' )
         strcat( pszNewFormatControls, "," );
-    
+
     strcat( pszNewFormatControls, poNewSFDefn->GetFormat() );
     strcat( pszNewFormatControls, ")" );
-    
+
     CPLFree( _formatControls );
     _formatControls = pszNewFormatControls;
 
@@ -135,10 +127,10 @@ void DDFFieldDefn::AddSubfield( DDFSubfieldDefn *poNewSFDefn,
     if( _arrayDescr == NULL )
         _arrayDescr = CPLStrdup("");
 
-    _arrayDescr = (char *) 
-        CPLRealloc(_arrayDescr, 
+    _arrayDescr = (char *)
+        CPLRealloc(_arrayDescr,
                    strlen(_arrayDescr)+strlen(poNewSFDefn->GetName())+2);
-    if( strlen(_arrayDescr) > 0 && 
+    if( strlen(_arrayDescr) > 0 &&
        (_arrayDescr[0] != '*' || strlen(_arrayDescr) > 1) )
         strcat( _arrayDescr, "!" );
     strcat( _arrayDescr, poNewSFDefn->GetName() );
@@ -151,8 +143,8 @@ void DDFFieldDefn::AddSubfield( DDFSubfieldDefn *poNewSFDefn,
 /*      of from an existing file.                                       */
 /************************************************************************/
 
-int DDFFieldDefn::Create( const char *pszTag, const char *pszFieldName, 
-                          const char *pszDescription, 
+int DDFFieldDefn::Create( const char *pszTagIn, const char *pszFieldName,
+                          const char *pszDescription,
                           DDF_data_struct_code eDataStructCode,
                           DDF_data_type_code   eDataTypeCode,
                           const char *pszFormat )
@@ -160,10 +152,10 @@ int DDFFieldDefn::Create( const char *pszTag, const char *pszFieldName,
 {
     CPLAssert( this->pszTag == NULL );
     poModule = NULL;
-    this->pszTag = CPLStrdup( pszTag );
+    this->pszTag = CPLStrdup( pszTagIn );
     _fieldName = CPLStrdup( pszFieldName );
     _arrayDescr = CPLStrdup( pszDescription );
-    
+
     _data_struct_code = eDataStructCode;
     _data_type_code = eDataTypeCode;
 
@@ -179,17 +171,31 @@ int DDFFieldDefn::Create( const char *pszTag, const char *pszFieldName,
 }
 
 /************************************************************************/
+/*                         SetFormatControls()                          */
+/************************************************************************/
+
+void DDFFieldDefn::SetFormatControls(const char* pszVal)
+{
+    CPLFree(_formatControls);
+    _formatControls = CPLStrdup(pszVal ? pszVal : "");
+}
+
+/************************************************************************/
 /*                          GenerateDDREntry()                          */
 /************************************************************************/
 
-int DDFFieldDefn::GenerateDDREntry( char **ppachData, 
+int DDFFieldDefn::GenerateDDREntry( DDFModule * poModuleIn, char **ppachData,
                                     int *pnLength )
 
 {
-    *pnLength = 9 + strlen(_fieldName) + 1 
+    const int         iFDOffset = poModuleIn->GetFieldControlLength();
+    CPLAssert(iFDOffset >= 6 && iFDOffset <= 9);
+    *pnLength = static_cast<int>(iFDOffset + strlen(_fieldName) + 1
         + strlen(_arrayDescr) + 1
-        + strlen(_formatControls) + 1;
+        + strlen(_formatControls) + 1);
 
+    if( strlen(_arrayDescr) == 0 )
+        *pnLength -= 1;
     if( strlen(_formatControls) == 0 )
         *pnLength -= 1;
 
@@ -197,7 +203,7 @@ int DDFFieldDefn::GenerateDDREntry( char **ppachData,
         return TRUE;
 
     *ppachData = (char *) CPLMalloc( *pnLength+1 );
-    
+
     if( _data_struct_code == dsc_elementary )
         (*ppachData)[0] = '0';
     else if( _data_struct_code == dsc_vector )
@@ -206,7 +212,7 @@ int DDFFieldDefn::GenerateDDREntry( char **ppachData,
         (*ppachData)[0] = '2';
     else if( _data_struct_code == dsc_concatenated )
         (*ppachData)[0] = '3';
-    
+
     if( _data_type_code == dtc_char_string )
         (*ppachData)[1] = '0';
     else if( _data_type_code == dtc_implicit_point )
@@ -226,16 +232,24 @@ int DDFFieldDefn::GenerateDDREntry( char **ppachData,
     (*ppachData)[3] = '0';
     (*ppachData)[4] = ';';
     (*ppachData)[5] = '&';
-    (*ppachData)[6] = ' ';
-    (*ppachData)[7] = ' ';
-    (*ppachData)[8] = ' ';
-    sprintf( *ppachData + 9, "%s%c%s", 
-             _fieldName, DDF_UNIT_TERMINATOR, _arrayDescr );
-
+    if( iFDOffset > 6 )
+        (*ppachData)[6] = ' ';
+    if( iFDOffset > 7 )
+        (*ppachData)[7] = ' ';
+    if( iFDOffset > 8 )
+        (*ppachData)[8] = ' ';
+    snprintf( *ppachData + iFDOffset, *pnLength+1 - iFDOffset, "%s",
+             _fieldName );
+    if( strlen(_arrayDescr) > 0 )
+        snprintf( *ppachData + strlen(*ppachData),
+                  *pnLength+1 - strlen(*ppachData), "%c%s",
+                 DDF_UNIT_TERMINATOR, _arrayDescr );
     if( strlen(_formatControls) > 0 )
-        sprintf( *ppachData + strlen(*ppachData), "%c%s",
+        snprintf( *ppachData + strlen(*ppachData),
+                  *pnLength+1 - strlen(*ppachData), "%c%s",
                  DDF_UNIT_TERMINATOR, _formatControls );
-    sprintf( *ppachData + strlen(*ppachData), "%c", DDF_FIELD_TERMINATOR );
+    snprintf( *ppachData + strlen(*ppachData),
+              *pnLength+1 - strlen(*ppachData), "%c", DDF_FIELD_TERMINATOR );
 
     return TRUE;
 }
@@ -248,7 +262,7 @@ int DDFFieldDefn::GenerateDDREntry( char **ppachData,
 /************************************************************************/
 
 int DDFFieldDefn::Initialize( DDFModule * poModuleIn,
-                              const char * pszTagIn, 
+                              const char * pszTagIn,
                               int nFieldEntrySize,
                               const char * pachFieldArea )
 
@@ -257,7 +271,7 @@ int DDFFieldDefn::Initialize( DDFModule * poModuleIn,
     int         nCharsConsumed;
 
     poModule = poModuleIn;
-    
+
     pszTag = CPLStrdup( pszTagIn );
 
 /* -------------------------------------------------------------------- */
@@ -283,8 +297,8 @@ int DDFFieldDefn::Initialize( DDFModule * poModuleIn,
         break;
 
       default:
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Unrecognised data_struct_code value %c.\n"
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Unrecognized data_struct_code value %c.\n"
                   "Field %s initialization incorrect.",
                   pachFieldArea[0], pszTag );
         _data_struct_code = dsc_elementary;
@@ -296,39 +310,39 @@ int DDFFieldDefn::Initialize( DDFModule * poModuleIn,
       case '0':
         _data_type_code = dtc_char_string;
         break;
-        
+
       case '1':
         _data_type_code = dtc_implicit_point;
         break;
-        
+
       case '2':
         _data_type_code = dtc_explicit_point;
         break;
-        
+
       case '3':
         _data_type_code = dtc_explicit_point_scaled;
         break;
-        
+
       case '4':
         _data_type_code = dtc_char_bit_string;
         break;
-        
+
       case '5':
         _data_type_code = dtc_bit_string;
         break;
-        
+
       case '6':
         _data_type_code = dtc_mixed_data_type;
         break;
 
       default:
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Unrecognised data_type_code value %c.\n"
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Unrecognized data_type_code value %c.\n"
                   "Field %s initialization incorrect.",
                   pachFieldArea[1], pszTag );
         _data_type_code = dtc_char_string;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Capture the field name, description (sub field names), and      */
 /*      format statements.                                              */
@@ -340,20 +354,20 @@ int DDFFieldDefn::Initialize( DDFModule * poModuleIn,
                           DDF_UNIT_TERMINATOR, DDF_FIELD_TERMINATOR,
                           &nCharsConsumed );
     iFDOffset += nCharsConsumed;
-    
+
     _arrayDescr =
         DDFFetchVariable( pachFieldArea + iFDOffset,
                           nFieldEntrySize - iFDOffset,
-                          DDF_UNIT_TERMINATOR, DDF_FIELD_TERMINATOR, 
+                          DDF_UNIT_TERMINATOR, DDF_FIELD_TERMINATOR,
                           &nCharsConsumed );
     iFDOffset += nCharsConsumed;
-    
+
     _formatControls =
         DDFFetchVariable( pachFieldArea + iFDOffset,
                           nFieldEntrySize - iFDOffset,
-                          DDF_UNIT_TERMINATOR, DDF_FIELD_TERMINATOR, 
+                          DDF_UNIT_TERMINATOR, DDF_FIELD_TERMINATOR,
                           &nCharsConsumed );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Parse the subfield info.                                        */
 /* -------------------------------------------------------------------- */
@@ -365,7 +379,7 @@ int DDFFieldDefn::Initialize( DDFModule * poModuleIn,
         if( !ApplyFormats() )
             return FALSE;
     }
-    
+
     return TRUE;
 }
 
@@ -379,14 +393,14 @@ int DDFFieldDefn::Initialize( DDFModule * poModuleIn,
  * A variety of information about this field definition, and all it's
  * subfields is written to the give debugging file handle.
  *
- * @param fp The standard io file handle to write to.  ie. stderr
+ * @param fp The standard IO file handle to write to.  i.e. stderr
  */
 
 void DDFFieldDefn::Dump( FILE * fp )
 
 {
     const char  *pszValue = "";
-    
+
     fprintf( fp, "  DDFFieldDefn:\n" );
     fprintf( fp, "      Tag = `%s'\n", pszTag );
     fprintf( fp, "      _fieldName = `%s'\n", _fieldName );
@@ -398,19 +412,19 @@ void DDFFieldDefn::Dump( FILE * fp )
       case dsc_elementary:
         pszValue = "elementary";
         break;
-        
+
       case dsc_vector:
         pszValue = "vector";
         break;
-        
+
       case dsc_array:
         pszValue = "array";
         break;
-        
+
       case dsc_concatenated:
         pszValue = "concatenated";
         break;
-        
+
       default:
         CPLAssert( FALSE );
         pszValue = "(unknown)";
@@ -423,27 +437,27 @@ void DDFFieldDefn::Dump( FILE * fp )
       case dtc_char_string:
         pszValue = "char_string";
         break;
-        
+
       case dtc_implicit_point:
         pszValue = "implicit_point";
         break;
-        
+
       case dtc_explicit_point:
         pszValue = "explicit_point";
         break;
-        
+
       case dtc_explicit_point_scaled:
         pszValue = "explicit_point_scaled";
         break;
-        
+
       case dtc_char_bit_string:
         pszValue = "char_bit_string";
         break;
-        
+
       case dtc_bit_string:
         pszValue = "bit_string";
         break;
-        
+
       case dtc_mixed_data_type:
         pszValue = "mixed_data_type";
         break;
@@ -453,7 +467,7 @@ void DDFFieldDefn::Dump( FILE * fp )
         pszValue = "(unknown)";
         break;
     }
-    
+
     fprintf( fp, "      _data_type_code = %s\n", pszValue );
 
     for( int i = 0; i < nSubfieldCount; i++ )
@@ -511,7 +525,7 @@ int DDFFieldDefn::BuildSubfields()
     for( int iSF = 0; iSF < nSFCount; iSF++ )
     {
         DDFSubfieldDefn *poSFDefn = new DDFSubfieldDefn;
-        
+
         poSFDefn->SetName( papszSubfieldNames[iSF] );
         AddSubfield( poSFDefn, TRUE );
     }
@@ -571,9 +585,9 @@ char *DDFFieldDefn::ExtractSubstring( const char * pszSrc )
 char *DDFFieldDefn::ExpandFormat( const char * pszSrc )
 
 {
-    int         nDestMax = 32;
+    size_t      nDestMax = 32;
     char       *pszDest = (char *) CPLMalloc(nDestMax+1);
-    int         iSrc, iDst;
+    size_t      iSrc, iDst;
     int         nRepeat = 0;
 
     iSrc = 0;
@@ -583,7 +597,7 @@ char *DDFFieldDefn::ExpandFormat( const char * pszSrc )
     while( pszSrc[iSrc] != '\0' )
     {
         /* This is presumably an extra level of brackets around some
-           binary stuff related to rescaning which we don't care to do
+           binary stuff related to rescanning which we don't care to do
            (see 6.4.3.3 of the standard.  We just strip off the extra
            layer of brackets */
         if( (iSrc == 0 || pszSrc[iSrc-1] == ',') && pszSrc[iSrc] == '(' )
@@ -591,8 +605,7 @@ char *DDFFieldDefn::ExpandFormat( const char * pszSrc )
             char       *pszContents = ExtractSubstring( pszSrc+iSrc );
             char       *pszExpandedContents = ExpandFormat( pszContents );
 
-            if( (int) (strlen(pszExpandedContents) + strlen(pszDest) + 1)
-                > nDestMax )
+            if( strlen(pszExpandedContents) + strlen(pszDest) + 1 > nDestMax )
             {
                 nDestMax = 2 * (strlen(pszExpandedContents) + strlen(pszDest));
                 pszDest = (char *) CPLRealloc(pszDest,nDestMax+1);
@@ -600,7 +613,7 @@ char *DDFFieldDefn::ExpandFormat( const char * pszSrc )
 
             strcat( pszDest, pszExpandedContents );
             iDst = strlen(pszDest);
-            
+
             iSrc = iSrc + strlen(pszContents) + 2;
 
             CPLFree( pszContents );
@@ -613,20 +626,19 @@ char *DDFFieldDefn::ExpandFormat( const char * pszSrc )
         {
             const char *pszNext;
             nRepeat = atoi(pszSrc+iSrc);
-            
+
             // skip over repeat count.
             for( pszNext = pszSrc+iSrc; isdigit(*pszNext); pszNext++ )
                 iSrc++;
 
             char       *pszContents = ExtractSubstring( pszNext );
             char       *pszExpandedContents = ExpandFormat( pszContents );
-                
+
             for( int i = 0; i < nRepeat; i++ )
             {
-                if( (int) (strlen(pszExpandedContents) + strlen(pszDest) + 1 + 1)
-                    > nDestMax )
+                if( strlen(pszExpandedContents) + strlen(pszDest) + 1 + 1 > nDestMax )
                 {
-                    nDestMax = 
+                    nDestMax =
                         2 * (strlen(pszExpandedContents) + strlen(pszDest) + 1);
                     pszDest = (char *) CPLRealloc(pszDest,nDestMax+1);
                 }
@@ -637,7 +649,7 @@ char *DDFFieldDefn::ExpandFormat( const char * pszSrc )
             }
 
             iDst = strlen(pszDest);
-            
+
             if( pszNext[0] == '(' )
                 iSrc = iSrc + strlen(pszContents) + 2;
             else
@@ -661,7 +673,7 @@ char *DDFFieldDefn::ExpandFormat( const char * pszSrc )
 
     return pszDest;
 }
-                                 
+
 /************************************************************************/
 /*                            ApplyFormats()                            */
 /*                                                                      */
@@ -675,7 +687,7 @@ int DDFFieldDefn::ApplyFormats()
 {
     char        *pszFormatList;
     char        **papszFormatItems;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Verify that the format string is contained within brackets.     */
 /* -------------------------------------------------------------------- */
@@ -683,10 +695,10 @@ int DDFFieldDefn::ApplyFormats()
         || _formatControls[0] != '('
         || _formatControls[strlen(_formatControls)-1] != ')' )
     {
-        CPLError( CE_Warning, CPLE_DiscardedFormat,
+        CPLError( CE_Warning, (CPLErrorNum)CPLE_DiscardedFormat,
                   "Format controls for `%s' field missing brackets:%s",
                   pszTag, _formatControls );
-        
+
         return FALSE;
     }
 
@@ -708,7 +720,7 @@ int DDFFieldDefn::ApplyFormats()
 /*      Apply the format items to subfields.                            */
 /* -------------------------------------------------------------------- */
     int iFormatItem;
-    
+
     for( iFormatItem = 0;
          papszFormatItems[iFormatItem] != NULL;
          iFormatItem++ )
@@ -724,15 +736,15 @@ int DDFFieldDefn::ApplyFormats()
         // by names?  This may be legal by the 8211 specification, but
         // isn't encountered in any formats we care about so we just
         // blow.
-        
+
         if( iFormatItem >= nSubfieldCount )
         {
-            CPLError( CE_Warning, CPLE_DiscardedFormat,
+            CPLError( CE_Warning, (CPLErrorNum)CPLE_DiscardedFormat,
                       "Got more formats than subfields for field `%s'.",
                       pszTag );
             break;
         }
-        
+
         if( !papoSubfields[iFormatItem]->SetFormat(pszPastPrefix) )
         {
             CSLDestroy( papszFormatItems );
@@ -747,7 +759,7 @@ int DDFFieldDefn::ApplyFormats()
 
     if( iFormatItem < nSubfieldCount )
     {
-        CPLError( CE_Warning, CPLE_DiscardedFormat,
+        CPLError( CE_Warning, (CPLErrorNum)CPLE_DiscardedFormat,
                   "Got less formats than subfields for field `%s'.",
                   pszTag );
         return FALSE;
@@ -777,13 +789,13 @@ int DDFFieldDefn::ApplyFormats()
 /************************************************************************/
 
 /**
- * Find a subfield definition by it's mnemonic tag.  
+ * Find a subfield definition by it's mnemonic tag.
  *
  * @param pszMnemonic The name of the field.
  *
  * @return The subfield pointer, or NULL if there isn't any such subfield.
  */
- 
+
 
 DDFSubfieldDefn *DDFFieldDefn::FindSubfieldDefn( const char * pszMnemonic )
 
@@ -819,7 +831,7 @@ DDFSubfieldDefn *DDFFieldDefn::GetSubfield( int i )
         CPLAssert( FALSE );
         return NULL;
     }
-             
+
     return papoSubfields[i];
 }
 
@@ -833,7 +845,7 @@ DDFSubfieldDefn *DDFFieldDefn::GetSubfield( int i )
 
 char *DDFFieldDefn::GetDefaultValue( int *pnSize )
 
-{                                                                       
+{
 /* -------------------------------------------------------------------- */
 /*      Loop once collecting the sum of the subfield lengths.           */
 /* -------------------------------------------------------------------- */
@@ -844,7 +856,7 @@ char *DDFFieldDefn::GetDefaultValue( int *pnSize )
     {
         int nSubfieldSize;
 
-        if( !papoSubfields[iSubfield]->GetDefaultValue( NULL, 0, 
+        if( !papoSubfields[iSubfield]->GetDefaultValue( NULL, 0,
                                                         &nSubfieldSize ) )
             return NULL;
         nTotalSize += nSubfieldSize;
@@ -866,7 +878,7 @@ char *DDFFieldDefn::GetDefaultValue( int *pnSize )
     {
         int nSubfieldSize;
 
-        if( !papoSubfields[iSubfield]->GetDefaultValue( 
+        if( !papoSubfields[iSubfield]->GetDefaultValue(
                 pachData + nOffset, nTotalSize - nOffset, &nSubfieldSize ) )
         {
             CPLAssert( FALSE );
diff --git a/frmts/iso8211/ddfmodule.cpp b/frmts/iso8211/ddfmodule.cpp
index bdc6e28..ec1b943 100644
--- a/frmts/iso8211/ddfmodule.cpp
+++ b/frmts/iso8211/ddfmodule.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ddfmodule.cpp 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: ddfmodule.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  ISO 8211 Access
  * Purpose:  Implements the DDFModule class.
@@ -31,7 +31,7 @@
 #include "iso8211.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ddfmodule.cpp 27044 2014-03-16 23:41:27Z rouault $");
+CPL_CVSID("$Id: ddfmodule.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 /************************************************************************/
 /*                             DDFModule()                              */
@@ -41,8 +41,8 @@ CPL_CVSID("$Id: ddfmodule.cpp 27044 2014-03-16 23:41:27Z rouault $");
  * The constructor.
  */
 
-DDFModule::DDFModule()
-
+DDFModule::DDFModule() :
+    nFirstRecordOffset(0)
 {
     nFieldDefnCount = 0;
     papoFieldDefns = NULL;
@@ -58,7 +58,7 @@ DDFModule::DDFModule()
     _inlineCodeExtensionIndicator = '\0';
     _versionNumber = '\0';
     _appIndicator = '\0';
-    _fieldControlLength = '\0';
+    _fieldControlLength = 9;
     strcpy( _extendedCharSet, " ! " );
 
     _recLength = 0;
@@ -102,7 +102,7 @@ void DDFModule::Close()
 /* -------------------------------------------------------------------- */
     if( fpDDF != NULL )
     {
-        VSIFCloseL( fpDDF );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fpDDF ));
         fpDDF = NULL;
     }
 
@@ -116,22 +116,22 @@ void DDFModule::Close()
     }
 
 /* -------------------------------------------------------------------- */
-/*      Cleanup the clones.  Deleting them will cause a callback to     */
-/*      remove them from the list.                                      */
+/*      Cleanup the clones.                                             */
 /* -------------------------------------------------------------------- */
-    while( nCloneCount > 0 )
-        delete papoClones[0];
-
+    for( int i = 0; i < nCloneCount; i++ )
+    {
+        papoClones[i]->RemoveIsCloneFlag();
+        delete papoClones[i];
+    }
+    nCloneCount = 0;
     nMaxCloneCount = 0;
     CPLFree( papoClones );
     papoClones = NULL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Cleanup the field definitions.                                  */
 /* -------------------------------------------------------------------- */
-    int i;
-
-    for( i = 0; i < nFieldDefnCount; i++ )
+    for( int i = 0; i < nFieldDefnCount; i++ )
         delete papoFieldDefns[i];
     CPLFree( papoFieldDefns );
     papoFieldDefns = NULL;
@@ -152,7 +152,7 @@ void DDFModule::Close()
  * read, and all the field and subfield definitions will be available.
  *
  * @param pszFilename   The name of the file to open.
- * @param bFailQuietly If FALSE a CPL Error is issued for non-8211 files, 
+ * @param bFailQuietly If FALSE a CPL Error is issued for non-8211 files,
  * otherwise quietly return NULL.
  *
  * @return FALSE if the open fails or TRUE if it succeeds.  Errors messages
@@ -169,7 +169,7 @@ int DDFModule::Open( const char * pszFilename, int bFailQuietly )
 /* -------------------------------------------------------------------- */
     if( fpDDF != NULL )
         Close();
-    
+
 /* -------------------------------------------------------------------- */
 /*      Open the file.                                                  */
 /* -------------------------------------------------------------------- */
@@ -188,17 +188,17 @@ int DDFModule::Open( const char * pszFilename, int bFailQuietly )
 /*      Read the 24 byte leader.                                        */
 /* -------------------------------------------------------------------- */
     char        achLeader[nLeaderSize];
-    
+
     if( (int)VSIFReadL( achLeader, 1, nLeaderSize, fpDDF ) != nLeaderSize )
     {
-        VSIFCloseL( fpDDF );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fpDDF ));
         fpDDF = NULL;
 
         if( !bFailQuietly )
             CPLError( CE_Failure, CPLE_FileIO,
                       "Leader is short on DDF file `%s'.",
                       pszFilename );
-        
+
         return FALSE;
     }
 
@@ -257,7 +257,7 @@ int DDFModule::Open( const char * pszFilename, int bFailQuietly )
 /* -------------------------------------------------------------------- */
     if( !bValid )
     {
-        VSIFCloseL( fpDDF );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fpDDF ));
         fpDDF = NULL;
 
         if( !bFailQuietly )
@@ -283,7 +283,7 @@ int DDFModule::Open( const char * pszFilename, int bFailQuietly )
             CPLError( CE_Failure, CPLE_FileIO,
                       "Header record is short on DDF file `%s'.",
                       pszFilename );
-        
+
         return FALSE;
     }
 
@@ -311,13 +311,13 @@ int DDFModule::Open( const char * pszFilename, int bFailQuietly )
         int     nEntryOffset = nLeaderSize + i*nFieldEntryWidth;
         int     nFieldLength, nFieldPos;
         DDFFieldDefn *poFDefn;
-        
+
         strncpy( szTag, pachRecord+nEntryOffset, _sizeFieldTag );
         szTag[_sizeFieldTag] = '\0';
 
         nEntryOffset += _sizeFieldTag;
         nFieldLength = DDFScanInt( pachRecord+nEntryOffset, _sizeFieldLength );
-        
+
         nEntryOffset += _sizeFieldLength;
         nFieldPos = DDFScanInt( pachRecord+nEntryOffset, _sizeFieldPos );
 
@@ -332,7 +332,7 @@ int DDFModule::Open( const char * pszFilename, int bFailQuietly )
             CPLFree( pachRecord );
             return FALSE;
         }
-        
+
         poFDefn = new DDFFieldDefn();
         if( poFDefn->Initialize( this, szTag, nFieldLength,
                                  pachRecord+_fieldAreaStart+nFieldPos ) )
@@ -342,13 +342,13 @@ int DDFModule::Open( const char * pszFilename, int bFailQuietly )
     }
 
     CPLFree( pachRecord );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Record the current file offset, the beginning of the first      */
 /*      data record.                                                    */
 /* -------------------------------------------------------------------- */
     nFirstRecordOffset = (long)VSIFTellL( fpDDF );
-    
+
     return TRUE;
 }
 
@@ -357,7 +357,7 @@ int DDFModule::Open( const char * pszFilename, int bFailQuietly )
 /************************************************************************/
 
 int DDFModule::Initialize( char chInterchangeLevel,
-                           char chLeaderIden, 
+                           char chLeaderIden,
                            char chCodeExtensionIndicator,
                            char chVersionNumber,
                            char chAppIndicator,
@@ -372,7 +372,7 @@ int DDFModule::Initialize( char chInterchangeLevel,
     _inlineCodeExtensionIndicator = chCodeExtensionIndicator;
     _versionNumber = chVersionNumber;
     _appIndicator = chAppIndicator;
-    strcpy( _extendedCharSet, pszExtendedCharSet );
+    snprintf( _extendedCharSet, sizeof(_extendedCharSet), "%s", pszExtendedCharSet );
     _sizeFieldLength = nSizeFieldLength;
     _sizeFieldPos = nSizeFieldPos;
     _sizeFieldTag = nSizeFieldTag;
@@ -388,19 +388,19 @@ int DDFModule::Create( const char *pszFilename )
 
 {
     CPLAssert( fpDDF == NULL );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create the file on disk.                                        */
 /* -------------------------------------------------------------------- */
     fpDDF = VSIFOpenL( pszFilename, "wb+" );
     if( fpDDF == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "Failed to create file %s, check path and permissions.",
                   pszFilename );
         return FALSE;
     }
-    
+
     bReadOnly = FALSE;
 
 /* -------------------------------------------------------------------- */
@@ -408,18 +408,17 @@ int DDFModule::Create( const char *pszFilename )
 /* -------------------------------------------------------------------- */
     int iField;
 
-    _fieldControlLength = 9;
-    _recLength = 24 
-        + nFieldDefnCount * (_sizeFieldLength+_sizeFieldPos+_sizeFieldTag) 
+    _recLength = 24
+        + nFieldDefnCount * (_sizeFieldLength+_sizeFieldPos+_sizeFieldTag)
         + 1;
-    
+
     _fieldAreaStart = _recLength;
 
     for( iField=0; iField < nFieldDefnCount; iField++ )
     {
         int nLength;
 
-        papoFieldDefns[iField]->GenerateDDREntry( NULL, &nLength );
+        papoFieldDefns[iField]->GenerateDDREntry( this, NULL, &nLength );
         _recLength += nLength;
     }
 
@@ -428,20 +427,20 @@ int DDFModule::Create( const char *pszFilename )
 /* -------------------------------------------------------------------- */
     char achLeader[25];
 
-    sprintf( achLeader+0, "%05d", (int) _recLength );
+    snprintf( achLeader+0, sizeof(achLeader)-0, "%05d", (int) _recLength );
     achLeader[5] = _interchangeLevel;
     achLeader[6] = _leaderIden;
     achLeader[7] = _inlineCodeExtensionIndicator;
     achLeader[8] = _versionNumber;
     achLeader[9] = _appIndicator;
-    sprintf( achLeader+10, "%02d", (int) _fieldControlLength );
-    sprintf( achLeader+12, "%05d", (int) _fieldAreaStart );
+    snprintf( achLeader+10, sizeof(achLeader)-10, "%02d", (int) _fieldControlLength );
+    snprintf( achLeader+12, sizeof(achLeader)-12, "%05d", (int) _fieldAreaStart );
     strncpy( achLeader+17, _extendedCharSet, 3 );
-    sprintf( achLeader+20, "%1d", (int) _sizeFieldLength );
-    sprintf( achLeader+21, "%1d", (int) _sizeFieldPos );
+    snprintf( achLeader+20, sizeof(achLeader)-20, "%1d", (int) _sizeFieldLength );
+    snprintf( achLeader+21, sizeof(achLeader)-21, "%1d", (int) _sizeFieldPos );
     achLeader[22] = '0';
-    sprintf( achLeader+23, "%1d", (int) _sizeFieldTag );
-    VSIFWriteL( achLeader, 24, 1, fpDDF );
+    snprintf( achLeader+23, sizeof(achLeader)-23, "%1d", (int) _sizeFieldTag );
+    int bRet = VSIFWriteL( achLeader, 24, 1, fpDDF ) > 0;
 
 /* -------------------------------------------------------------------- */
 /*      Write out directory entries.                                    */
@@ -455,22 +454,24 @@ int DDFModule::Create( const char *pszFilename )
 
         CPLAssert(_sizeFieldLength + _sizeFieldPos + _sizeFieldTag < (int)sizeof(achDirEntry));
 
-        papoFieldDefns[iField]->GenerateDDREntry( NULL, &nLength );
+        papoFieldDefns[iField]->GenerateDDREntry( this, NULL, &nLength );
 
         CPLAssert( (int)strlen(papoFieldDefns[iField]->GetName()) == _sizeFieldTag );
         strcpy( achDirEntry, papoFieldDefns[iField]->GetName() );
-        sprintf(szFormat, "%%0%dd", (int)_sizeFieldLength);
-        sprintf( achDirEntry + _sizeFieldTag, szFormat, nLength );
-        sprintf(szFormat, "%%0%dd", (int)_sizeFieldTag);
-        sprintf( achDirEntry + _sizeFieldTag + _sizeFieldLength, 
-                 szFormat, nOffset );
+        snprintf(szFormat, sizeof(szFormat), "%%0%dd", (int)_sizeFieldLength);
+        snprintf( achDirEntry + _sizeFieldTag, sizeof(achDirEntry) - _sizeFieldTag,
+                  szFormat, nLength );
+        snprintf(szFormat, sizeof(szFormat), "%%0%dd", (int)_sizeFieldPos);
+        snprintf( achDirEntry + _sizeFieldTag + _sizeFieldLength,
+                  sizeof(achDirEntry) - _sizeFieldTag - _sizeFieldLength,
+                  szFormat, nOffset );
         nOffset += nLength;
 
-        VSIFWriteL( achDirEntry, _sizeFieldLength + _sizeFieldPos + _sizeFieldTag, 1, fpDDF );
+        bRet &= VSIFWriteL( achDirEntry, _sizeFieldLength + _sizeFieldPos + _sizeFieldTag, 1, fpDDF ) > 0;
     }
 
     char chUT = DDF_FIELD_TERMINATOR;
-    VSIFWriteL( &chUT, 1, 1, fpDDF );
+    bRet &= VSIFWriteL( &chUT, 1, 1, fpDDF ) > 0;
 
 /* -------------------------------------------------------------------- */
 /*      Write out the field descriptions themselves.                    */
@@ -480,12 +481,12 @@ int DDFModule::Create( const char *pszFilename )
         char *pachData;
         int nLength;
 
-        papoFieldDefns[iField]->GenerateDDREntry( &pachData, &nLength );
-        VSIFWriteL( pachData, nLength, 1, fpDDF );
+        papoFieldDefns[iField]->GenerateDDREntry( this, &pachData, &nLength );
+        bRet &= VSIFWriteL( pachData, nLength, 1, fpDDF ) > 0;
         CPLFree( pachData );
     }
-    
-    return TRUE;
+
+    return bRet ? TRUE : FALSE;
 }
 
 /************************************************************************/
@@ -497,16 +498,16 @@ int DDFModule::Create( const char *pszFilename )
  *
  * A variety of information about the module is written to the debugging
  * file.  This includes all the field and subfield definitions read from
- * the header. 
+ * the header.
  *
- * @param fp The standard io file handle to write to.  ie. stderr.
+ * @param fp The standard IO file handle to write to.  i.e. stderr.
  */
 
 void DDFModule::Dump( FILE * fp )
 
 {
     fprintf( fp, "DDFModule:\n" );
-    fprintf( fp, "    _recLength = %ld\n", _recLength );
+    fprintf( fp, "    _recLength = %d\n", _recLength );
     fprintf( fp, "    _interchangeLevel = %c\n", _interchangeLevel );
     fprintf( fp, "    _leaderIden = %c\n", _leaderIden );
     fprintf( fp, "    _inlineCodeExtensionIndicator = %c\n",
@@ -515,10 +516,10 @@ void DDFModule::Dump( FILE * fp )
     fprintf( fp, "    _appIndicator = %c\n", _appIndicator );
     fprintf( fp, "    _extendedCharSet = `%s'\n", _extendedCharSet );
     fprintf( fp, "    _fieldControlLength = %d\n", _fieldControlLength );
-    fprintf( fp, "    _fieldAreaStart = %ld\n", _fieldAreaStart );
-    fprintf( fp, "    _sizeFieldLength = %ld\n", _sizeFieldLength );
-    fprintf( fp, "    _sizeFieldPos = %ld\n", _sizeFieldPos );
-    fprintf( fp, "    _sizeFieldTag = %ld\n", _sizeFieldTag );
+    fprintf( fp, "    _fieldAreaStart = %d\n", _fieldAreaStart );
+    fprintf( fp, "    _sizeFieldLength = %d\n", _sizeFieldLength );
+    fprintf( fp, "    _sizeFieldPos = %d\n", _sizeFieldPos );
+    fprintf( fp, "    _sizeFieldTag = %d\n", _sizeFieldTag );
 
     for( int i = 0; i < nFieldDefnCount; i++ )
     {
@@ -548,7 +549,7 @@ DDFFieldDefn *DDFModule::FindFieldDefn( const char *pszFieldName )
 
 {
     int         i;
-    
+
 /* -------------------------------------------------------------------- */
 /*      This pass tries to reduce the cost of comparing strings by      */
 /*      first checking the first character, and by using strcmp()       */
@@ -556,7 +557,7 @@ DDFFieldDefn *DDFModule::FindFieldDefn( const char *pszFieldName )
     for( i = 0; i < nFieldDefnCount; i++ )
     {
         const char *pszThisName = papoFieldDefns[i]->GetName();
-        
+
         if( *pszThisName == *pszFieldName
             && strcmp( pszFieldName+1, pszThisName+1) == 0 )
             return papoFieldDefns[i];
@@ -590,7 +591,7 @@ DDFFieldDefn *DDFModule::FindFieldDefn( const char *pszFieldName )
  * @return A pointer to a DDFRecord object is returned, or NULL if a read
  * error, or end of file occurs.  The returned record is owned by the
  * module, and should not be deleted by the application.  The record is
- * only valid untill the next ReadRecord() at which point it is overwritten.
+ * only valid until the next ReadRecord() at which point it is overwritten.
  */
 
 DDFRecord *DDFModule::ReadRecord()
@@ -612,18 +613,18 @@ DDFRecord *DDFModule::ReadRecord()
 /**
  * Add new field definition.
  *
- * Field definitions may only be added to DDFModules being used for 
- * writing, not those being used for reading.  Ownership of the 
+ * Field definitions may only be added to DDFModules being used for
+ * writing, not those being used for reading.  Ownership of the
  * DDFFieldDefn object is taken by the DDFModule.
  *
- * @param poNewFDefn definition to be added to the module. 
+ * @param poNewFDefn definition to be added to the module.
  */
 
 void DDFModule::AddField( DDFFieldDefn *poNewFDefn )
 
 {
     nFieldDefnCount++;
-    papoFieldDefns = (DDFFieldDefn **) 
+    papoFieldDefns = (DDFFieldDefn **)
         CPLRealloc(papoFieldDefns, sizeof(void*)*nFieldDefnCount);
     papoFieldDefns[nFieldDefnCount-1] = poNewFDefn;
 }
@@ -647,7 +648,7 @@ DDFFieldDefn *DDFModule::GetField(int i)
     else
         return papoFieldDefns[i];
 }
-    
+
 /************************************************************************/
 /*                           AddCloneRecord()                           */
 /*                                                                      */
@@ -655,7 +656,7 @@ DDFFieldDefn *DDFModule::GetField(int i)
 /*      them up when the module is destroyed.                           */
 /************************************************************************/
 
-void DDFModule::AddCloneRecord( DDFRecord * poRecord )
+void DDFModule::AddCloneRecord( DDFRecord * poRecordIn )
 
 {
 /* -------------------------------------------------------------------- */
@@ -671,21 +672,21 @@ void DDFModule::AddCloneRecord( DDFRecord * poRecord )
 /* -------------------------------------------------------------------- */
 /*      Add to the list.                                                */
 /* -------------------------------------------------------------------- */
-    papoClones[nCloneCount++] = poRecord;
+    papoClones[nCloneCount++] = poRecordIn;
 }
 
 /************************************************************************/
 /*                         RemoveCloneRecord()                          */
 /************************************************************************/
 
-void DDFModule::RemoveCloneRecord( DDFRecord * poRecord )
+void DDFModule::RemoveCloneRecord( DDFRecord * poRecordIn )
 
 {
     int         i;
- 
+
     for( i = 0; i < nCloneCount; i++ )
     {
-        if( papoClones[i] == poRecord )
+        if( papoClones[i] == poRecordIn )
         {
             papoClones[i] = papoClones[nCloneCount-1];
             nCloneCount--;
@@ -702,7 +703,7 @@ void DDFModule::RemoveCloneRecord( DDFRecord * poRecord )
 
 /**
  * Return to first record.
- * 
+ *
  * The next call to ReadRecord() will read the first data record in the file.
  *
  * @param nOffset the offset in the file to return to.  By default this is
@@ -718,10 +719,10 @@ void DDFModule::Rewind( long nOffset )
 
     if( fpDDF == NULL )
         return;
-    
-    VSIFSeekL( fpDDF, nOffset, SEEK_SET );
+
+    if( VSIFSeekL( fpDDF, nOffset, SEEK_SET ) < 0 )
+        return;
 
     if( nOffset == nFirstRecordOffset && poRecord != NULL )
         poRecord->Clear();
-        
 }
diff --git a/frmts/iso8211/ddfrecord.cpp b/frmts/iso8211/ddfrecord.cpp
index d66f883..1286175 100644
--- a/frmts/iso8211/ddfrecord.cpp
+++ b/frmts/iso8211/ddfrecord.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ddfrecord.cpp 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: ddfrecord.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  ISO 8211 Access
  * Purpose:  Implements the DDFRecord class.
@@ -31,7 +31,7 @@
 #include "iso8211.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ddfrecord.cpp 27044 2014-03-16 23:41:27Z rouault $");
+CPL_CVSID("$Id: ddfrecord.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 static const int nLeaderSize = 24;
 
@@ -57,8 +57,8 @@ DDFRecord::DDFRecord( DDFModule * poModuleIn )
     bIsClone = FALSE;
 
     _sizeFieldTag = poModuleIn->GetSizeFieldTag();
-    _sizeFieldPos = 0;
-    _sizeFieldLength = 0;
+    _sizeFieldPos = 5;
+    _sizeFieldLength = 5;
 }
 
 /************************************************************************/
@@ -85,7 +85,7 @@ DDFRecord::~DDFRecord()
  * subfields is written to the given debugging file handle.  Note that
  * field definition information (ala DDFFieldDefn) isn't written.
  *
- * @param fp The standard io file handle to write to.  ie. stderr
+ * @param fp The standard IO file handle to write to.  i.e. stderr
  */
 
 void DDFRecord::Dump( FILE * fp )
@@ -94,7 +94,7 @@ void DDFRecord::Dump( FILE * fp )
     fprintf( fp, "DDFRecord:\n" );
     fprintf( fp, "    nReuseHeader = %d\n", nReuseHeader );
     fprintf( fp, "    nDataSize = %d\n", nDataSize );
-    fprintf( fp, 
+    fprintf( fp,
              "    _sizeFieldLength=%d, _sizeFieldPos=%d, _sizeFieldTag=%d\n",
              _sizeFieldLength, _sizeFieldPos, _sizeFieldTag );
 
@@ -135,6 +135,7 @@ int DDFRecord::Read()
 /* -------------------------------------------------------------------- */
     size_t      nReadBytes;
 
+    CPLAssert( nFieldOffset <= nDataSize );
     nReadBytes = VSIFReadL( pachData + nFieldOffset, 1,
                             nDataSize - nFieldOffset,
                             poModule->GetFP() );
@@ -148,13 +149,13 @@ int DDFRecord::Read()
     {
         CPLError( CE_Failure, CPLE_FileIO,
                   "Data record is short on DDF file.\n" );
-        
+
         return FALSE;
     }
 
-    // notdef: eventually we may have to do something at this point to 
-    // notify the DDFField's that their data values have changed. 
-    
+    // notdef: eventually we may have to do something at this point to
+    // notify the DDFField's that their data values have changed.
+
     return TRUE;
 }
 
@@ -165,7 +166,7 @@ int DDFRecord::Read()
 /**
  * Write record out to module.
  *
- * This method writes the current record to the module to which it is 
+ * This method writes the current record to the module to which it is
  * attached.  Normally this would be at the end of the file, and only used
  * for modules newly created with DDFModule::Create().  Rewriting existing
  * records is not supported at this time.  Calling Write() multiple times
@@ -180,7 +181,7 @@ int DDFRecord::Write()
 {
     if( !ResetDirectory() )
         return FALSE;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Prepare leader.                                                 */
 /* -------------------------------------------------------------------- */
@@ -188,11 +189,11 @@ int DDFRecord::Write()
 
     memset( szLeader, ' ', nLeaderSize );
 
-    sprintf( szLeader+0, "%05d", (int) (nDataSize + nLeaderSize) );
+    snprintf( szLeader+0, sizeof(szLeader)-0, "%05d", (int) (nDataSize + nLeaderSize) );
     szLeader[5] = ' ';
     szLeader[6] = 'D';
-    
-    sprintf( szLeader + 12, "%05d", (int) (nFieldOffset + nLeaderSize) );
+
+    snprintf( szLeader+12, sizeof(szLeader)-12, "%05d", (int) (nFieldOffset + nLeaderSize) );
     szLeader[17] = ' ';
 
     szLeader[20] = (char) ('0' + _sizeFieldLength);
@@ -205,14 +206,14 @@ int DDFRecord::Write()
 /* -------------------------------------------------------------------- */
 /*      Write the leader.                                               */
 /* -------------------------------------------------------------------- */
-    VSIFWriteL( szLeader, nLeaderSize, 1, poModule->GetFP() );
+    int bRet = VSIFWriteL( szLeader, nLeaderSize, 1, poModule->GetFP() ) > 0;
 
 /* -------------------------------------------------------------------- */
 /*      Write the remainder of the record.                              */
 /* -------------------------------------------------------------------- */
-    VSIFWriteL( pachData, nDataSize, 1, poModule->GetFP() );
-    
-    return TRUE;
+    bRet &= VSIFWriteL( pachData, nDataSize, 1, poModule->GetFP() ) > 0;
+
+    return bRet ? TRUE : FALSE;
 }
 
 /************************************************************************/
@@ -254,14 +255,14 @@ int DDFRecord::ReadHeader()
 /*      Clear any existing information.                                 */
 /* -------------------------------------------------------------------- */
     Clear();
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read the 24 byte leader.                                        */
 /* -------------------------------------------------------------------- */
     char        achLeader[nLeaderSize];
     int         nReadBytes;
 
-    nReadBytes = VSIFReadL(achLeader,1,nLeaderSize,poModule->GetFP());
+    nReadBytes = static_cast<int>(VSIFReadL(achLeader,1,nLeaderSize,poModule->GetFP()));
     if( nReadBytes == 0 && VSIFEofL( poModule->GetFP() ) )
     {
         return FALSE;
@@ -270,7 +271,7 @@ int DDFRecord::ReadHeader()
     {
         CPLError( CE_Failure, CPLE_FileIO,
                   "Leader is short on DDF file." );
-        
+
         return FALSE;
     }
 
@@ -279,20 +280,20 @@ int DDFRecord::ReadHeader()
 /* -------------------------------------------------------------------- */
     int         _recLength, _fieldAreaStart;
     char        _leaderIden;
-    
+
     _recLength                    = DDFScanInt( achLeader+0, 5 );
     _leaderIden                   = achLeader[6];
     _fieldAreaStart               = DDFScanInt(achLeader+12,5);
-    
+
     _sizeFieldLength = achLeader[20] - '0';
     _sizeFieldPos = achLeader[21] - '0';
     _sizeFieldTag = achLeader[23] - '0';
 
-    if( _sizeFieldLength < 0 || _sizeFieldLength > 9 
+    if( _sizeFieldLength < 0 || _sizeFieldLength > 9
         || _sizeFieldPos < 0 || _sizeFieldPos > 9
         || _sizeFieldTag < 0 || _sizeFieldTag > 9 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "ISO8211 record leader appears to be corrupt." );
         return FALSE;
     }
@@ -305,15 +306,14 @@ int DDFRecord::ReadHeader()
 /* -------------------------------------------------------------------- */
 /*      Is there anything seemly screwy about this record?              */
 /* -------------------------------------------------------------------- */
-    if(( _recLength <= 24 || _recLength > 100000000
+    if( ((_recLength <= 24 || _recLength > 100000000) && (_recLength != 0))
          || _fieldAreaStart < 24 || _fieldAreaStart > 100000 )
-       && (_recLength != 0))
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   "Data record appears to be corrupt on DDF file.\n"
                   " -- ensure that the files were uncompressed without modifying\n"
                   "carriage return/linefeeds (by default WINZIP does this)." );
-        
+
         return FALSE;
     }
 
@@ -330,9 +330,9 @@ int DDFRecord::ReadHeader()
         if( VSIFReadL( pachData, 1, nDataSize, poModule->GetFP()) !=
             (size_t) nDataSize )
         {
-            CPLError( CE_Failure, CPLE_FileIO, 
+            CPLError( CE_Failure, CPLE_FileIO,
                       "Data record is short on DDF file." );
-          
+
             return FALSE;
         }
 
@@ -340,34 +340,40 @@ int DDFRecord::ReadHeader()
 /*      If we don't find a field terminator at the end of the record    */
 /*      we will read extra bytes till we get to it.                     */
 /* -------------------------------------------------------------------- */
-        while( pachData[nDataSize-1] != DDF_FIELD_TERMINATOR 
+        while( pachData[nDataSize-1] != DDF_FIELD_TERMINATOR
                && (nDataSize < 2 || pachData[nDataSize-2] != DDF_FIELD_TERMINATOR) )
         {
             nDataSize++;
             pachData = (char *) CPLRealloc(pachData,nDataSize);
-            
+
             if( VSIFReadL( pachData + nDataSize - 1, 1, 1, poModule->GetFP() )
                 != 1 )
             {
-                CPLError( CE_Failure, CPLE_FileIO, 
+                CPLError( CE_Failure, CPLE_FileIO,
                           "Data record is short on DDF file." );
-                
+
                 return FALSE;
             }
-            CPLDebug( "ISO8211", 
+            CPLDebug( "ISO8211",
                       "Didn't find field terminator, read one more byte." );
         }
 
+        if( nFieldOffset >= nDataSize )
+        {
+            CPLError(CE_Failure, CPLE_AssertionFailed, "nFieldOffset < nDataSize");
+            return FALSE;
+        }
+
 /* -------------------------------------------------------------------- */
 /*      Loop over the directory entries, making a pass counting them.   */
 /* -------------------------------------------------------------------- */
         int         i;
         int         nFieldEntryWidth;
-      
+
         nFieldEntryWidth = _sizeFieldLength + _sizeFieldPos + _sizeFieldTag;
         if( nFieldEntryWidth <= 0 )
         {
-            CPLError( CE_Failure, CPLE_FileIO, 
+            CPLError( CE_Failure, CPLE_FileIO,
                       "Invalid entry width = %d", nFieldEntryWidth);
             return FALSE;
         }
@@ -377,39 +383,39 @@ int DDFRecord::ReadHeader()
         {
             if( pachData[i] == DDF_FIELD_TERMINATOR )
                 break;
-          
+
             nFieldCount++;
         }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Allocate, and read field definitions.                           */
 /* -------------------------------------------------------------------- */
         paoFields = new DDFField[nFieldCount];
-    
+
         for( i = 0; i < nFieldCount; i++ )
         {
             char    szTag[128];
             int     nEntryOffset = i*nFieldEntryWidth;
             int     nFieldLength, nFieldPos;
-          
+
 /* -------------------------------------------------------------------- */
 /*      Read the position information and tag.                          */
 /* -------------------------------------------------------------------- */
             strncpy( szTag, pachData+nEntryOffset, _sizeFieldTag );
             szTag[_sizeFieldTag] = '\0';
-          
+
             nEntryOffset += _sizeFieldTag;
             nFieldLength = DDFScanInt( pachData+nEntryOffset, _sizeFieldLength );
-          
+
             nEntryOffset += _sizeFieldLength;
             nFieldPos = DDFScanInt( pachData+nEntryOffset, _sizeFieldPos );
-          
+
 /* -------------------------------------------------------------------- */
 /*      Find the corresponding field in the module directory.           */
 /* -------------------------------------------------------------------- */
             DDFFieldDefn    *poFieldDefn = poModule->FindFieldDefn( szTag );
-          
-            if( poFieldDefn == NULL )
+
+            if( poFieldDefn == NULL || nFieldLength < 0 || nFieldPos < 0  )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
                           "Undefined field `%s' encountered in data record.",
@@ -429,11 +435,11 @@ int DDFRecord::ReadHeader()
 /* -------------------------------------------------------------------- */
 /*      Assign info the DDFField.                                       */
 /* -------------------------------------------------------------------- */
-            paoFields[i].Initialize( poFieldDefn, 
+            paoFields[i].Initialize( poFieldDefn,
                                      pachData + _fieldAreaStart + nFieldPos - nLeaderSize,
                                      nFieldLength );
         }
-      
+
         return TRUE;
     }
 /* ==================================================================== */
@@ -444,7 +450,7 @@ int DDFRecord::ReadHeader()
 /*      See Bugzilla bug 181 and test with file US4CN21M.000.           */
 /* ==================================================================== */
     else {
-        CPLDebug( "ISO8211", 
+        CPLDebug( "ISO8211",
                   "Record with zero length, use variant (C.1.5.1) logic." );
 
         /* ----------------------------------------------------------------- */
@@ -469,29 +475,26 @@ int DDFRecord::ReadHeader()
                       nFieldEntryWidth );
             return FALSE;
         }
-        
-        char *tmpBuf = (char*)VSIMalloc(nFieldEntryWidth);
+
+        char *tmpBuf = (char*)VSI_MALLOC_VERBOSE(nFieldEntryWidth);
 
         if( tmpBuf == NULL )
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory, 
-                      "Attempt to allocate %d byte ISO8211 record buffer failed.", 
-                      nFieldEntryWidth );
             return FALSE;
         }
-      
+
         // while we're not at the end, store this entry,
         // and keep on reading...
         do {
             // read an Entry:
-            if(nFieldEntryWidth != 
+            if(nFieldEntryWidth !=
                (int) VSIFReadL(tmpBuf, 1, nFieldEntryWidth, poModule->GetFP())) {
                 CPLError(CE_Failure, CPLE_FileIO,
                          "Data record is short on DDF file.");
                 CPLFree(tmpBuf);
                 return FALSE;
             }
-      
+
             // move this temp buffer into more permanent storage:
             char *newBuf = (char*)CPLMalloc(nDataSize+nFieldEntryWidth);
             if(pachData!=NULL) {
@@ -517,7 +520,8 @@ int DDFRecord::ReadHeader()
         int rewindSize = nFieldEntryWidth - 1;
         VSILFILE *fp = poModule->GetFP();
         vsi_l_offset pos = VSIFTellL(fp) - rewindSize;
-        VSIFSeekL(fp, pos, SEEK_SET);
+        if( VSIFSeekL(fp, pos, SEEK_SET) < 0 )
+            return FALSE;
         nDataSize -= rewindSize;
 
         // --------------------------------------------------------------------
@@ -527,31 +531,27 @@ int DDFRecord::ReadHeader()
             int nEntryOffset = (i*nFieldEntryWidth) + _sizeFieldTag;
             int nFieldLength = DDFScanInt(pachData + nEntryOffset,
                                           _sizeFieldLength);
-            char *tmpBuf = NULL;
+            tmpBuf = NULL;
             if( nFieldLength >= 0 )
-                tmpBuf = (char*)VSIMalloc(nFieldLength);
+                tmpBuf = (char*)VSI_MALLOC_VERBOSE(nFieldLength);
             if( tmpBuf == NULL )
             {
-                CPLError(CE_Failure, CPLE_OutOfMemory,
-                         "Cannot allocate %d bytes", nFieldLength);
                 return FALSE;
             }
 
             // read an Entry:
-            if(nFieldLength != 
+            if(nFieldLength !=
                (int) VSIFReadL(tmpBuf, 1, nFieldLength, poModule->GetFP())) {
                 CPLError(CE_Failure, CPLE_FileIO,
                          "Data record is short on DDF file.");
                 CPLFree(tmpBuf);
                 return FALSE;
             }
-      
+
             // move this temp buffer into more permanent storage:
-            char *newBuf = (char*)VSIMalloc(nDataSize+nFieldLength);
+            char *newBuf = (char*)VSI_MALLOC_VERBOSE(nDataSize+nFieldLength);
             if( newBuf == NULL )
             {
-                CPLError(CE_Failure, CPLE_OutOfMemory,
-                         "Cannot allocate %d bytes", nDataSize + nFieldLength);
                 CPLFree(tmpBuf);
                 return FALSE;
             }
@@ -562,36 +562,42 @@ int DDFRecord::ReadHeader()
             pachData = newBuf;
             nDataSize += nFieldLength;
         }
-    
+
+        if( nFieldOffset >= nDataSize )
+        {
+            CPLError(CE_Failure, CPLE_AssertionFailed, "nFieldOffset < nDataSize");
+            return FALSE;
+        }
+
         /* ----------------------------------------------------------------- */
         /*     Allocate, and read field definitions.                         */
         /* ----------------------------------------------------------------- */
         paoFields = new DDFField[nFieldCount];
-      
+
         for( i = 0; i < nFieldCount; i++ )
         {
             char    szTag[128];
             int     nEntryOffset = i*nFieldEntryWidth;
             int     nFieldLength, nFieldPos;
-          
+
             /* ------------------------------------------------------------- */
             /* Read the position information and tag.                        */
             /* ------------------------------------------------------------- */
             strncpy( szTag, pachData+nEntryOffset, _sizeFieldTag );
             szTag[_sizeFieldTag] = '\0';
-          
+
             nEntryOffset += _sizeFieldTag;
             nFieldLength = DDFScanInt( pachData+nEntryOffset, _sizeFieldLength );
-          
+
             nEntryOffset += _sizeFieldLength;
             nFieldPos = DDFScanInt( pachData+nEntryOffset, _sizeFieldPos );
-          
+
             /* ------------------------------------------------------------- */
             /* Find the corresponding field in the module directory.         */
             /* ------------------------------------------------------------- */
             DDFFieldDefn    *poFieldDefn = poModule->FindFieldDefn( szTag );
-          
-            if( poFieldDefn == NULL )
+
+            if( poFieldDefn == NULL || nFieldLength < 0 || nFieldPos < 0 )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
                           "Undefined field `%s' encountered in data record.",
@@ -612,12 +618,12 @@ int DDFRecord::ReadHeader()
             /* Assign info the DDFField.                                     */
             /* ------------------------------------------------------------- */
 
-            paoFields[i].Initialize( poFieldDefn, 
+            paoFields[i].Initialize( poFieldDefn,
                                      pachData + _fieldAreaStart
                                      + nFieldPos - nLeaderSize,
                                      nFieldLength );
         }
-      
+
         return TRUE;
     }
 }
@@ -636,7 +642,7 @@ int DDFRecord::ReadHeader()
  *
  * @return Pointer to the requested DDFField.  This pointer is to an
  * internal object, and should not be freed.  It remains valid until
- * the next record read. 
+ * the next record read.
  */
 
 DDFField * DDFRecord::FindField( const char * pszName, int iFieldIndex )
@@ -709,7 +715,7 @@ int DDFRecord::GetIntSubfield( const char * pszField, int iFieldIndex,
         pnSuccess = &nDummyErr;
 
     *pnSuccess = FALSE;
-            
+
 /* -------------------------------------------------------------------- */
 /*      Fetch the field. If this fails, return zero.                    */
 /* -------------------------------------------------------------------- */
@@ -730,18 +736,20 @@ int DDFRecord::GetIntSubfield( const char * pszField, int iFieldIndex,
 /*      Get a pointer to the data.                                      */
 /* -------------------------------------------------------------------- */
     int         nBytesRemaining;
-    
-    const char *pachData = poField->GetSubfieldData(poSFDefn,
+
+    const char *l_pachData = poField->GetSubfieldData(poSFDefn,
                                                     &nBytesRemaining,
                                                     iSubfieldIndex);
+    if( l_pachData == NULL )
+        return 0;
 
 /* -------------------------------------------------------------------- */
 /*      Return the extracted value.                                     */
 /*                                                                      */
-/*      Assume an error has occured if no bytes are consumed.           */
+/*      Assume an error has occurred if no bytes are consumed.           */
 /* -------------------------------------------------------------------- */
     int nConsumedBytes = 0;
-    int nResult = poSFDefn->ExtractIntData( pachData, nBytesRemaining, 
+    int nResult = poSFDefn->ExtractIntData( l_pachData, nBytesRemaining,
                                             &nConsumedBytes );
 
     if( nConsumedBytes > 0 )
@@ -782,7 +790,7 @@ double DDFRecord::GetFloatSubfield( const char * pszField, int iFieldIndex,
         pnSuccess = &nDummyErr;
 
     *pnSuccess = FALSE;
-            
+
 /* -------------------------------------------------------------------- */
 /*      Fetch the field. If this fails, return zero.                    */
 /* -------------------------------------------------------------------- */
@@ -803,16 +811,18 @@ double DDFRecord::GetFloatSubfield( const char * pszField, int iFieldIndex,
 /*      Get a pointer to the data.                                      */
 /* -------------------------------------------------------------------- */
     int         nBytesRemaining;
-    
-    const char *pachData = poField->GetSubfieldData(poSFDefn,
+
+    const char *l_pachData = poField->GetSubfieldData(poSFDefn,
                                                     &nBytesRemaining,
                                                     iSubfieldIndex);
+    if( l_pachData == NULL )
+        return 0;
 
 /* -------------------------------------------------------------------- */
 /*      Return the extracted value.                                     */
 /* -------------------------------------------------------------------- */
     int nConsumedBytes = 0;
-    double dfResult = poSFDefn->ExtractFloatData( pachData, nBytesRemaining, 
+    double dfResult = poSFDefn->ExtractFloatData( l_pachData, nBytesRemaining,
                                                   &nConsumedBytes );
 
     if( nConsumedBytes > 0 )
@@ -856,7 +866,7 @@ DDFRecord::GetStringSubfield( const char * pszField, int iFieldIndex,
         pnSuccess = &nDummyErr;
 
     *pnSuccess = FALSE;
-            
+
 /* -------------------------------------------------------------------- */
 /*      Fetch the field. If this fails, return zero.                    */
 /* -------------------------------------------------------------------- */
@@ -877,17 +887,19 @@ DDFRecord::GetStringSubfield( const char * pszField, int iFieldIndex,
 /*      Get a pointer to the data.                                      */
 /* -------------------------------------------------------------------- */
     int         nBytesRemaining;
-    
-    const char *pachData = poField->GetSubfieldData(poSFDefn,
+
+    const char *l_pachData = poField->GetSubfieldData(poSFDefn,
                                                     &nBytesRemaining,
                                                     iSubfieldIndex);
+    if( l_pachData == NULL )
+        return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Return the extracted value.                                     */
 /* -------------------------------------------------------------------- */
     *pnSuccess = TRUE;
 
-    return( poSFDefn->ExtractStringData( pachData, nBytesRemaining, NULL ) );
+    return( poSFDefn->ExtractStringData( l_pachData, nBytesRemaining, NULL ) );
 }
 
 /************************************************************************/
@@ -919,23 +931,23 @@ DDFRecord * DDFRecord::Clone()
 
     poNR->nReuseHeader = FALSE;
     poNR->nFieldOffset = nFieldOffset;
-    
+
     poNR->nDataSize = nDataSize;
     poNR->pachData = (char *) CPLMalloc(nDataSize);
     memcpy( poNR->pachData, pachData, nDataSize );
-    
+
     poNR->nFieldCount = nFieldCount;
     poNR->paoFields = new DDFField[nFieldCount];
     for( int i = 0; i < nFieldCount; i++ )
     {
         int     nOffset;
 
-        nOffset = (paoFields[i].GetData() - pachData);
+        nOffset = static_cast<int>(paoFields[i].GetData() - pachData);
         poNR->paoFields[i].Initialize( paoFields[i].GetFieldDefn(),
                                        poNR->pachData + nOffset,
                                        paoFields[i].GetDataSize() );
     }
-    
+
     poNR->bIsClone = TRUE;
     poModule->AddCloneRecord( poNR );
 
@@ -954,11 +966,11 @@ DDFRecord * DDFRecord::Clone()
  * references are transcribed onto the new module based on field names.
  * If any fields don't have a similarly named field on the target module
  * the operation will fail.  No validation of field types and properties
- * is done, but this operation is intended only to be used between 
- * modules with matching definitions of all affected fields. 
+ * is done, but this operation is intended only to be used between
+ * modules with matching definitions of all affected fields.
  *
  * The new record will be managed as a clone by the target module in
- * a manner similar to regular clones. 
+ * a manner similar to regular clones.
  *
  * @param poTargetModule the module on which the record copy should be
  * created.
@@ -998,10 +1010,10 @@ DDFRecord *DDFRecord::CloneOn( DDFModule *poTargetModule )
         DDFField        *poField = poClone->paoFields+i;
         DDFFieldDefn    *poDefn;
 
-        poDefn = poTargetModule->FindFieldDefn( 
+        poDefn = poTargetModule->FindFieldDefn(
             poField->GetFieldDefn()->GetName() );
-        
-        poField->Initialize( poDefn, poField->GetData(), 
+
+        poField->Initialize( poDefn, poField->GetData(),
                              poField->GetDataSize() );
     }
 
@@ -1020,18 +1032,18 @@ DDFRecord *DDFRecord::CloneOn( DDFModule *poTargetModule )
 /**
  * Delete a field instance from a record.
  *
- * Remove a field from this record, cleaning up the data            
- * portion and repacking the fields list.  We don't try to          
- * reallocate the data area of the record to be smaller.            
- *                                                                       
- * NOTE: This method doesn't actually remove the header             
- * information for this field from the record tag list yet.        
- * This should be added if the resulting record is even to be      
- * written back to disk!                                           
+ * Remove a field from this record, cleaning up the data
+ * portion and repacking the fields list.  We don't try to
+ * reallocate the data area of the record to be smaller.
+ *
+ * NOTE: This method doesn't actually remove the header
+ * information for this field from the record tag list yet.
+ * This should be added if the resulting record is even to be
+ * written back to disk!
  *
  * @param poTarget the field instance on this record to delete.
  *
- * @return TRUE on success, or FALSE on failure.  Failure can occur if 
+ * @return TRUE on success, or FALSE on failure.  Failure can occur if
  * poTarget isn't really a field on this record.
  */
 
@@ -1082,14 +1094,14 @@ int DDFRecord::DeleteField( DDFField *poTarget )
  *
  * This method will rearrange a DDFRecord altering the amount of space
  * reserved for one of the existing fields.  All following fields will
- * be shifted accordingly.  This includes updating the DDFField infos, 
+ * be shifted accordingly.  This includes updating the DDFField infos,
  * and actually moving stuff within the data array after reallocating
  * to the desired size.
  *
  * @param poField the field to alter.
  * @param nNewDataSize the number of data bytes to be reserved for the field.
  *
- * @return TRUE on success or FALSE on failure. 
+ * @return TRUE on success or FALSE on failure.
  */
 
 int DDFRecord::ResizeField( DDFField *poField, int nNewDataSize )
@@ -1128,8 +1140,8 @@ int DDFRecord::ResizeField( DDFField *poField, int nNewDataSize )
 /* -------------------------------------------------------------------- */
 /*      How much data needs to be shifted up or down after this field?  */
 /* -------------------------------------------------------------------- */
-    nBytesToMove = nDataSize 
-        - (poField->GetData()+poField->GetDataSize()-pachOldData+nBytesToAdd);
+    nBytesToMove = nDataSize
+        - static_cast<int>(poField->GetData()+poField->GetDataSize()-pachOldData+nBytesToAdd);
 
 /* -------------------------------------------------------------------- */
 /*      Update fields to point into newly allocated buffer.             */
@@ -1138,9 +1150,9 @@ int DDFRecord::ResizeField( DDFField *poField, int nNewDataSize )
     {
         int     nOffset;
 
-        nOffset = paoFields[i].GetData() - pachOldData;
-        paoFields[i].Initialize( paoFields[i].GetFieldDefn(), 
-                                 pachData + nOffset, 
+        nOffset = static_cast<int>(paoFields[i].GetData() - pachOldData);
+        paoFields[i].Initialize( paoFields[i].GetFieldDefn(),
+                                 pachData + nOffset,
                                  paoFields[i].GetDataSize() );
     }
 
@@ -1149,14 +1161,14 @@ int DDFRecord::ResizeField( DDFField *poField, int nNewDataSize )
 /* -------------------------------------------------------------------- */
     if( nBytesToMove > 0 )
         memmove( (char *)poField->GetData()+poField->GetDataSize()+nBytesToAdd,
-                 (char *)poField->GetData()+poField->GetDataSize(), 
+                 (char *)poField->GetData()+poField->GetDataSize(),
                  nBytesToMove );
-             
+
 /* -------------------------------------------------------------------- */
 /*      Update the target fields info.                                  */
 /* -------------------------------------------------------------------- */
     poField->Initialize( poField->GetFieldDefn(),
-                         poField->GetData(), 
+                         poField->GetData(),
                          poField->GetDataSize() + nBytesToAdd );
 
 /* -------------------------------------------------------------------- */
@@ -1171,9 +1183,9 @@ int DDFRecord::ResizeField( DDFField *poField, int nNewDataSize )
 
             pszOldDataLocation = (char *) paoFields[i].GetData();
 
-            paoFields[i].Initialize( paoFields[i].GetFieldDefn(), 
+            paoFields[i].Initialize( paoFields[i].GetFieldDefn(),
                                      pszOldDataLocation + nBytesToAdd,
-                                     paoFields[i].GetDataSize() ); 
+                                     paoFields[i].GetDataSize() );
         }
     }
     else
@@ -1184,9 +1196,9 @@ int DDFRecord::ResizeField( DDFField *poField, int nNewDataSize )
 
             pszOldDataLocation = (char *) paoFields[i].GetData();
 
-            paoFields[i].Initialize( paoFields[i].GetFieldDefn(), 
+            paoFields[i].Initialize( paoFields[i].GetFieldDefn(),
                                      pszOldDataLocation + nBytesToAdd,
-                                     paoFields[i].GetDataSize() ); 
+                                     paoFields[i].GetDataSize() );
         }
     }
 
@@ -1201,12 +1213,12 @@ int DDFRecord::ResizeField( DDFField *poField, int nNewDataSize )
  * Add a new field to record.
  *
  * Add a new zero sized field to the record.  The new field is always
- * added at the end of the record. 
+ * added at the end of the record.
  *
  * NOTE: This method doesn't currently update the header information for
  * the record to include the field information for this field, so the
- * resulting record image isn't suitable for writing to disk.  However, 
- * everything else about the record state should be updated properly to 
+ * resulting record image isn't suitable for writing to disk.  However,
+ * everything else about the record state should be updated properly to
  * reflect the new field.
  *
  * @param poDefn the definition of the field to be added.
@@ -1241,10 +1253,10 @@ DDFField *DDFRecord::AddField( DDFFieldDefn *poDefn )
     }
     else
     {
-        paoFields[nFieldCount-1].Initialize( 
-            poDefn, 
+        paoFields[nFieldCount-1].Initialize(
+            poDefn,
             paoFields[nFieldCount-2].GetData()
-            + paoFields[nFieldCount-2].GetDataSize(), 
+            + paoFields[nFieldCount-2].GetDataSize(),
             0 );
     }
 
@@ -1263,10 +1275,10 @@ DDFField *DDFRecord::AddField( DDFFieldDefn *poDefn )
 /**
  * Set the raw contents of a field instance.
  *
- * @param poField the field to set data within. 
+ * @param poField the field to set data within.
  * @param iIndexWithinField The instance of this field to replace.  Must
  * be a value between 0 and GetRepeatCount().  If GetRepeatCount() is used, a
- * new instance of the field is appeneded.
+ * new instance of the field is appended.
  * @param pachRawData the raw data to replace this field instance with.
  * @param nRawDataSize the number of bytes pointed to by pachRawData.
  *
@@ -1301,7 +1313,7 @@ DDFRecord::SetFieldRaw( DDFField *poField, int iIndexWithinField,
 /*      Are we adding an instance?  This is easier and different        */
 /*      than replacing an existing instance.                            */
 /* -------------------------------------------------------------------- */
-    if( iIndexWithinField == nRepeatCount 
+    if( iIndexWithinField == nRepeatCount
         || !poField->GetFieldDefn()->IsRepeating() )
     {
         char    *pachFieldData;
@@ -1312,13 +1324,13 @@ DDFRecord::SetFieldRaw( DDFField *poField, int iIndexWithinField,
 
         nOldSize = poField->GetDataSize();
         if( nOldSize == 0 )
-            nOldSize++; // for added DDF_FIELD_TERMINATOR. 
+            nOldSize++; // for added DDF_FIELD_TERMINATOR.
 
         if( !ResizeField( poField, nOldSize + nRawDataSize ) )
             return FALSE;
 
         pachFieldData = (char *) poField->GetData();
-        memcpy( pachFieldData + nOldSize - 1, 
+        memcpy( pachFieldData + nOldSize - 1,
                 pachRawData, nRawDataSize );
         pachFieldData[nOldSize+nRawDataSize-1] = DDF_FIELD_TERMINATOR;
 
@@ -1332,7 +1344,7 @@ DDFRecord::SetFieldRaw( DDFField *poField, int iIndexWithinField,
     const char *pachWrkData;
     int         nInstanceSize;
 
-    // We special case this to avoid alot of warnings when initializing 
+    // We special case this to avoid a lot of warnings when initializing
     // the field the first time.
     if( poField->GetDataSize() == 0 )
     {
@@ -1341,7 +1353,7 @@ DDFRecord::SetFieldRaw( DDFField *poField, int iIndexWithinField,
     }
     else
     {
-        pachWrkData = poField->GetInstanceData( iIndexWithinField, 
+        pachWrkData = poField->GetInstanceData( iIndexWithinField,
                                                 &nInstanceSize );
     }
 
@@ -1355,11 +1367,11 @@ DDFRecord::SetFieldRaw( DDFField *poField, int iIndexWithinField,
 
     pachNewImage = (char *) CPLMalloc(nNewFieldSize);
 
-    nPreBytes = pachWrkData - poField->GetData();
+    nPreBytes = static_cast<int>(pachWrkData - poField->GetData());
     nPostBytes = poField->GetDataSize() - nPreBytes - nInstanceSize;
 
     memcpy( pachNewImage, poField->GetData(), nPreBytes );
-    memcpy( pachNewImage + nPreBytes + nRawDataSize, 
+    memcpy( pachNewImage + nPreBytes + nRawDataSize,
             poField->GetData() + nPreBytes + nInstanceSize,
             nPostBytes );
     memcpy( pachNewImage + nPreBytes, pachRawData, nRawDataSize );
@@ -1381,7 +1393,7 @@ DDFRecord::SetFieldRaw( DDFField *poField, int iIndexWithinField,
 
 int
 DDFRecord::UpdateFieldRaw( DDFField *poField, int iIndexWithinField,
-                           int nStartOffset, int nOldSize, 
+                           int nStartOffset, int nOldSize,
                            const char *pachRawData, int nRawDataSize )
 
 {
@@ -1409,10 +1421,10 @@ DDFRecord::UpdateFieldRaw( DDFField *poField, int iIndexWithinField,
 /* -------------------------------------------------------------------- */
     char *pachWrkData;
     int         nInstanceSize, nPostBytes, nPreBytes;
-        
-    pachWrkData = (char *) poField->GetInstanceData( iIndexWithinField, 
+
+    pachWrkData = (char *) poField->GetInstanceData( iIndexWithinField,
                                                      &nInstanceSize );
-    nPreBytes = pachWrkData - poField->GetData() + nStartOffset;
+    nPreBytes = static_cast<int>(pachWrkData - poField->GetData() + nStartOffset);
     nPostBytes = poField->GetDataSize() - nPreBytes - nOldSize;
 
 /* -------------------------------------------------------------------- */
@@ -1431,17 +1443,17 @@ DDFRecord::UpdateFieldRaw( DDFField *poField, int iIndexWithinField,
 /* -------------------------------------------------------------------- */
     if( nRawDataSize < nOldSize )
     {
-        memcpy( ((char*) poField->GetData()) + nPreBytes, 
+        memcpy( ((char*) poField->GetData()) + nPreBytes,
                 pachRawData, nRawDataSize );
-        memmove( ((char *) poField->GetData()) + nPreBytes + nRawDataSize, 
-                 ((char *) poField->GetData()) + nPreBytes + nOldSize, 
+        memmove( ((char *) poField->GetData()) + nPreBytes + nRawDataSize,
+                 ((char *) poField->GetData()) + nPreBytes + nOldSize,
                  nPostBytes );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Resize the whole buffer.                                        */
 /* -------------------------------------------------------------------- */
-    if( !ResizeField( poField, 
+    if( !ResizeField( poField,
                       poField->GetDataSize() - nOldSize + nRawDataSize ) )
         return FALSE;
 
@@ -1451,10 +1463,10 @@ DDFRecord::UpdateFieldRaw( DDFField *poField, int iIndexWithinField,
 /* -------------------------------------------------------------------- */
     if( nRawDataSize >= nOldSize )
     {
-        memmove( ((char *) poField->GetData()) + nPreBytes + nRawDataSize, 
-                 ((char *) poField->GetData()) + nPreBytes + nOldSize, 
+        memmove( ((char *) poField->GetData()) + nPreBytes + nRawDataSize,
+                 ((char *) poField->GetData()) + nPreBytes + nOldSize,
                  nPostBytes );
-        memcpy( ((char*) poField->GetData()) + nPreBytes, 
+        memcpy( ((char*) poField->GetData()) + nPreBytes,
                 pachRawData, nRawDataSize );
     }
 
@@ -1474,11 +1486,8 @@ int DDFRecord::ResetDirectory()
 
 /* -------------------------------------------------------------------- */
 /*      Eventually we should try to optimize the size of offset and     */
-/*      field length.  For now we will use 5 for each which is          */
-/*      pretty big.                                                     */
+/*      field length.                                                   */
 /* -------------------------------------------------------------------- */
-    _sizeFieldPos = 5;
-    _sizeFieldLength = 5;
 
 /* -------------------------------------------------------------------- */
 /*      Compute how large the directory needs to be.                    */
@@ -1499,18 +1508,18 @@ int DDFRecord::ResetDirectory()
 
         nNewDataSize = nDataSize - nFieldOffset + nDirSize;
         pachNewData = (char *) CPLMalloc(nNewDataSize);
-        memcpy( pachNewData + nDirSize, 
-                pachData + nFieldOffset, 
+        memcpy( pachNewData + nDirSize,
+                pachData + nFieldOffset,
                 nNewDataSize - nDirSize );
-     
-        for( iField = 0; iField < nFieldCount; iField++ )
+
+        for( iField = 0; paoFields != NULL && iField < nFieldCount; iField++ )
         {
             int nOffset;
-            DDFField *poField = GetField( iField );
+            DDFField *poField = /*GetField( iField )*/ paoFields + iField;
 
-            nOffset = poField->GetData() - pachData - nFieldOffset + nDirSize;
-            poField->Initialize( poField->GetFieldDefn(), 
-                                 pachNewData + nOffset, 
+            nOffset = static_cast<int>(poField->GetData() - pachData - nFieldOffset + nDirSize);
+            poField->Initialize( poField->GetFieldDefn(),
+                                 pachNewData + nOffset,
                                  poField->GetDataSize() );
         }
 
@@ -1523,22 +1532,24 @@ int DDFRecord::ResetDirectory()
 /* -------------------------------------------------------------------- */
 /*      Now set each directory entry.                                   */
 /* -------------------------------------------------------------------- */
-    for( iField = 0; iField < nFieldCount; iField++ )
+    for( iField = 0; paoFields != NULL && iField < nFieldCount; iField++ )
     {
-        DDFField *poField = GetField( iField );
+        DDFField *poField = /*GetField( iField )*/ paoFields + iField;
         DDFFieldDefn *poDefn = poField->GetFieldDefn();
         char      szFormat[128];
 
-        sprintf( szFormat, "%%%ds%%0%dd%%0%dd", 
+        snprintf( szFormat, sizeof(szFormat), "%%%ds%%0%dd%%0%dd",
                  _sizeFieldTag, _sizeFieldLength, _sizeFieldPos );
 
-        sprintf( pachData + nEntrySize * iField, szFormat, 
+        snprintf( pachData + nEntrySize * iField,
+                  nEntrySize+1,
+                  szFormat,
                  poDefn->GetName(), poField->GetDataSize(),
                  poField->GetData() - pachData - nFieldOffset );
     }
 
     pachData[nEntrySize * nFieldCount] = DDF_FIELD_TERMINATOR;
-        
+
     return TRUE;
 }
 
@@ -1552,18 +1563,18 @@ int DDFRecord::ResetDirectory()
  * This method is normally only used internally by the AddField() method
  * to initialize the new field instance with default subfield values.  It
  * installs default data for one instance of the field in the record
- * using the DDFFieldDefn::GetDefaultValue() method and 
- * DDFRecord::SetFieldRaw(). 
+ * using the DDFFieldDefn::GetDefaultValue() method and
+ * DDFRecord::SetFieldRaw().
  *
- * @param poField the field within the record to be assign a default 
- * instance. 
+ * @param poField the field within the record to be assign a default
+ * instance.
  * @param iIndexWithinField the instance to set (may not have been tested with
- * values other than 0). 
+ * values other than 0).
  *
- * @return TRUE on success or FALSE on failure. 
+ * @return TRUE on success or FALSE on failure.
  */
 
-int DDFRecord::CreateDefaultFieldInstance( DDFField *poField, 
+int DDFRecord::CreateDefaultFieldInstance( DDFField *poField,
                                            int iIndexWithinField )
 
 {
@@ -1588,22 +1599,22 @@ int DDFRecord::CreateDefaultFieldInstance( DDFField *poField,
 /**
  * Set a string subfield in record.
  *
- * The value of a given subfield is replaced with a new string value 
- * formatted appropriately. 
+ * The value of a given subfield is replaced with a new string value
+ * formatted appropriately.
  *
  * @param pszField the field name to operate on.
  * @param iFieldIndex the field index to operate on (zero based).
- * @param pszSubfield the subfield name to operate on. 
- * @param iSubfieldIndex the subfield index to operate on (zero based). 
- * @param pszValue the new string to place in the subfield.  This may be 
- * arbitrary binary bytes if nValueLength is specified. 
- * @param nValueLength the number of valid bytes in pszValue, may be -1 to 
- * internally fetch with strlen(). 
- * 
- * @return TRUE if successful, and FALSE if not. 
+ * @param pszSubfield the subfield name to operate on.
+ * @param iSubfieldIndex the subfield index to operate on (zero based).
+ * @param pszValue the new string to place in the subfield.  This may be
+ * arbitrary binary bytes if nValueLength is specified.
+ * @param nValueLength the number of valid bytes in pszValue, may be -1 to
+ * internally fetch with strlen().
+ *
+ * @return TRUE if successful, and FALSE if not.
  */
 
-int DDFRecord::SetStringSubfield( const char *pszField, int iFieldIndex, 
+int DDFRecord::SetStringSubfield( const char *pszField, int iFieldIndex,
                                   const char *pszSubfield, int iSubfieldIndex,
                                   const char *pszValue, int nValueLength )
 
@@ -1611,7 +1622,7 @@ int DDFRecord::SetStringSubfield( const char *pszField, int iFieldIndex,
 /* -------------------------------------------------------------------- */
 /*      Fetch the field. If this fails, return zero.                    */
 /* -------------------------------------------------------------------- */
-    DDFField *poField; 
+    DDFField *poField;
 
     poField = FindField( pszField, iFieldIndex );
     if( poField == NULL )
@@ -1639,22 +1650,26 @@ int DDFRecord::SetStringSubfield( const char *pszField, int iFieldIndex,
 /*      Get a pointer to the data.                                      */
 /* -------------------------------------------------------------------- */
     int         nMaxBytes;
-    char *pachSubfieldData = (char *) 
+    char *pachSubfieldData = (char *)
         poField->GetSubfieldData(poSFDefn, &nMaxBytes,
                                  iSubfieldIndex);
+    if( pachSubfieldData == NULL )
+        return FALSE;
 
 /* -------------------------------------------------------------------- */
 /*      Add new instance if we have run out of data.                    */
 /* -------------------------------------------------------------------- */
-    if( nMaxBytes == 0 
+    if( nMaxBytes == 0
         || (nMaxBytes == 1 && pachSubfieldData[0] == DDF_FIELD_TERMINATOR) )
     {
         CreateDefaultFieldInstance( poField, iSubfieldIndex );
 
         // Refetch.
-        pachSubfieldData = (char *) 
+        pachSubfieldData = (char *)
             poField->GetSubfieldData(poSFDefn, &nMaxBytes,
                                      iSubfieldIndex);
+        if( pachSubfieldData == NULL )
+            return FALSE;
     }
 
 /* -------------------------------------------------------------------- */
@@ -1681,14 +1696,14 @@ int DDFRecord::SetStringSubfield( const char *pszField, int iFieldIndex,
     pachFieldInstData = poField->GetInstanceData( iFieldIndex,
                                                   &nInstanceSize );
 
-    nStartOffset = pachSubfieldData - pachFieldInstData;
+    nStartOffset = static_cast<int>(pachSubfieldData - pachFieldInstData);
 
     pachNewData = (char *) CPLMalloc(nFormattedLen);
-    poSFDefn->FormatStringValue( pachNewData, nFormattedLen, NULL, 
+    poSFDefn->FormatStringValue( pachNewData, nFormattedLen, NULL,
                                  pszValue, nValueLength );
-    
+
     nSuccess = UpdateFieldRaw( poField, iFieldIndex,
-                               nStartOffset, nExistingLength, 
+                               nStartOffset, nExistingLength,
                                pachNewData, nFormattedLen );
 
     CPLFree( pachNewData );
@@ -1703,19 +1718,19 @@ int DDFRecord::SetStringSubfield( const char *pszField, int iFieldIndex,
 /**
  * Set an integer subfield in record.
  *
- * The value of a given subfield is replaced with a new integer value 
- * formatted appropriately. 
+ * The value of a given subfield is replaced with a new integer value
+ * formatted appropriately.
  *
  * @param pszField the field name to operate on.
  * @param iFieldIndex the field index to operate on (zero based).
- * @param pszSubfield the subfield name to operate on. 
- * @param iSubfieldIndex the subfield index to operate on (zero based). 
- * @param nNewValue the new value to place in the subfield. 
- * 
- * @return TRUE if successful, and FALSE if not. 
+ * @param pszSubfield the subfield name to operate on.
+ * @param iSubfieldIndex the subfield index to operate on (zero based).
+ * @param nNewValue the new value to place in the subfield.
+ *
+ * @return TRUE if successful, and FALSE if not.
  */
 
-int DDFRecord::SetIntSubfield( const char *pszField, int iFieldIndex, 
+int DDFRecord::SetIntSubfield( const char *pszField, int iFieldIndex,
                                const char *pszSubfield, int iSubfieldIndex,
                                int nNewValue )
 
@@ -1723,7 +1738,7 @@ int DDFRecord::SetIntSubfield( const char *pszField, int iFieldIndex,
 /* -------------------------------------------------------------------- */
 /*      Fetch the field. If this fails, return zero.                    */
 /* -------------------------------------------------------------------- */
-    DDFField *poField; 
+    DDFField *poField;
 
     poField = FindField( pszField, iFieldIndex );
     if( poField == NULL )
@@ -1750,22 +1765,26 @@ int DDFRecord::SetIntSubfield( const char *pszField, int iFieldIndex,
 /*      Get a pointer to the data.                                      */
 /* -------------------------------------------------------------------- */
     int         nMaxBytes;
-    char *pachSubfieldData = (char *) 
+    char *pachSubfieldData = (char *)
         poField->GetSubfieldData(poSFDefn, &nMaxBytes,
                                  iSubfieldIndex);
+    if( pachSubfieldData == NULL )
+        return FALSE;
 
 /* -------------------------------------------------------------------- */
 /*      Add new instance if we have run out of data.                    */
 /* -------------------------------------------------------------------- */
-    if( nMaxBytes == 0 
+    if( nMaxBytes == 0
         || (nMaxBytes == 1 && pachSubfieldData[0] == DDF_FIELD_TERMINATOR) )
     {
         CreateDefaultFieldInstance( poField, iSubfieldIndex );
 
         // Refetch.
-        pachSubfieldData = (char *) 
+        pachSubfieldData = (char *)
             poField->GetSubfieldData(poSFDefn, &nMaxBytes,
                                      iSubfieldIndex);
+        if( pachSubfieldData == NULL )
+            return FALSE;
     }
 
 /* -------------------------------------------------------------------- */
@@ -1792,14 +1811,14 @@ int DDFRecord::SetIntSubfield( const char *pszField, int iFieldIndex,
     pachFieldInstData = poField->GetInstanceData( iFieldIndex,
                                                   &nInstanceSize );
 
-    nStartOffset = pachSubfieldData - pachFieldInstData;
+    nStartOffset = static_cast<int>(pachSubfieldData - pachFieldInstData);
 
     pachNewData = (char *) CPLMalloc(nFormattedLen);
-    poSFDefn->FormatIntValue( pachNewData, nFormattedLen, NULL, 
+    poSFDefn->FormatIntValue( pachNewData, nFormattedLen, NULL,
                               nNewValue );
-    
+
     nSuccess = UpdateFieldRaw( poField, iFieldIndex,
-                               nStartOffset, nExistingLength, 
+                               nStartOffset, nExistingLength,
                                pachNewData, nFormattedLen );
 
     CPLFree( pachNewData );
@@ -1814,19 +1833,19 @@ int DDFRecord::SetIntSubfield( const char *pszField, int iFieldIndex,
 /**
  * Set a float subfield in record.
  *
- * The value of a given subfield is replaced with a new float value 
- * formatted appropriately. 
+ * The value of a given subfield is replaced with a new float value
+ * formatted appropriately.
  *
  * @param pszField the field name to operate on.
  * @param iFieldIndex the field index to operate on (zero based).
- * @param pszSubfield the subfield name to operate on. 
- * @param iSubfieldIndex the subfield index to operate on (zero based). 
- * @param dfNewValue the new value to place in the subfield. 
- * 
- * @return TRUE if successful, and FALSE if not. 
+ * @param pszSubfield the subfield name to operate on.
+ * @param iSubfieldIndex the subfield index to operate on (zero based).
+ * @param dfNewValue the new value to place in the subfield.
+ *
+ * @return TRUE if successful, and FALSE if not.
  */
 
-int DDFRecord::SetFloatSubfield( const char *pszField, int iFieldIndex, 
+int DDFRecord::SetFloatSubfield( const char *pszField, int iFieldIndex,
                                  const char *pszSubfield, int iSubfieldIndex,
                                  double dfNewValue )
 
@@ -1834,7 +1853,7 @@ int DDFRecord::SetFloatSubfield( const char *pszField, int iFieldIndex,
 /* -------------------------------------------------------------------- */
 /*      Fetch the field. If this fails, return zero.                    */
 /* -------------------------------------------------------------------- */
-    DDFField *poField; 
+    DDFField *poField;
 
     poField = FindField( pszField, iFieldIndex );
     if( poField == NULL )
@@ -1861,22 +1880,26 @@ int DDFRecord::SetFloatSubfield( const char *pszField, int iFieldIndex,
 /*      Get a pointer to the data.                                      */
 /* -------------------------------------------------------------------- */
     int         nMaxBytes;
-    char *pachSubfieldData = (char *) 
+    char *pachSubfieldData = (char *)
         poField->GetSubfieldData(poSFDefn, &nMaxBytes,
                                  iSubfieldIndex);
+    if( pachSubfieldData == NULL )
+        return FALSE;
 
 /* -------------------------------------------------------------------- */
 /*      Add new instance if we have run out of data.                    */
 /* -------------------------------------------------------------------- */
-    if( nMaxBytes == 0 
+    if( nMaxBytes == 0
         || (nMaxBytes == 1 && pachSubfieldData[0] == DDF_FIELD_TERMINATOR) )
     {
         CreateDefaultFieldInstance( poField, iSubfieldIndex );
 
         // Refetch.
-        pachSubfieldData = (char *) 
+        pachSubfieldData = (char *)
             poField->GetSubfieldData(poSFDefn, &nMaxBytes,
                                      iSubfieldIndex);
+        if( pachSubfieldData == NULL )
+            return FALSE;
     }
 
 /* -------------------------------------------------------------------- */
@@ -1906,11 +1929,11 @@ int DDFRecord::SetFloatSubfield( const char *pszField, int iFieldIndex,
     nStartOffset = (int) (pachSubfieldData - pachFieldInstData);
 
     pachNewData = (char *) CPLMalloc(nFormattedLen);
-    poSFDefn->FormatFloatValue( pachNewData, nFormattedLen, NULL, 
+    poSFDefn->FormatFloatValue( pachNewData, nFormattedLen, NULL,
                               dfNewValue );
-    
+
     nSuccess = UpdateFieldRaw( poField, iFieldIndex,
-                               nStartOffset, nExistingLength, 
+                               nStartOffset, nExistingLength,
                                pachNewData, nFormattedLen );
 
     CPLFree( pachNewData );
diff --git a/frmts/iso8211/ddfsubfielddefn.cpp b/frmts/iso8211/ddfsubfielddefn.cpp
index 341b31d..40cc1c3 100644
--- a/frmts/iso8211/ddfsubfielddefn.cpp
+++ b/frmts/iso8211/ddfsubfielddefn.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ddfsubfielddefn.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: ddfsubfielddefn.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  ISO 8211 Access
  * Purpose:  Implements the DDFSubfieldDefn class.
@@ -32,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ddfsubfielddefn.cpp 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: ddfsubfielddefn.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 /************************************************************************/
 /*                          DDFSubfieldDefn()                           */
@@ -42,13 +42,13 @@ DDFSubfieldDefn::DDFSubfieldDefn()
 
 {
     pszName = NULL;
-    
+
     bIsVariable = TRUE;
     nFormatWidth = 0;
-    chFormatDelimeter = DDF_UNIT_TERMINATOR;
+    chFormatDelimiter = DDF_UNIT_TERMINATOR;
     eBinaryFormat = NotBinary;
     eType = DDFString;
-    
+
     pszFormatString = CPLStrdup("");
 
     nMaxBufChars = 0;
@@ -75,12 +75,12 @@ void DDFSubfieldDefn::SetName( const char * pszNewName )
 
 {
     int         i;
-    
+
     CPLFree( pszName );
 
     pszName = CPLStrdup( pszNewName );
 
-    for( i = strlen(pszName)-1; i > 0 && pszName[i] == ' '; i-- )
+    for( i = static_cast<int>(strlen(pszName))-1; i > 0 && pszName[i] == ' '; i-- )
         pszName[i] = '\0';
 }
 
@@ -107,11 +107,18 @@ int DDFSubfieldDefn::SetFormat( const char * pszFormat )
     if( pszFormatString[1] == '(' )
     {
         nFormatWidth = atoi(pszFormatString+2);
+        if( nFormatWidth < 0 )
+        {
+             CPLError( CE_Failure, CPLE_AppDefined,
+                       "Format width %s is invalid.",
+                       pszFormatString+2 );
+            return FALSE;
+        }
         bIsVariable = nFormatWidth == 0;
     }
     else
         bIsVariable = TRUE;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Interpret the format string.                                    */
 /* -------------------------------------------------------------------- */
@@ -125,7 +132,7 @@ int DDFSubfieldDefn::SetFormat( const char * pszFormat )
       case 'R':
         eType = DDFFloat;
         break;
-        
+
       case 'I':
       case 'S':
         eType = DDFInt;
@@ -137,15 +144,16 @@ int DDFSubfieldDefn::SetFormat( const char * pszFormat )
         bIsVariable = FALSE;
         if( pszFormatString[1] == '(' )
         {
-            if( atoi(pszFormatString+2) % 8 != 0 )
+            nFormatWidth = atoi(pszFormatString+2);
+            if( nFormatWidth < 0 || nFormatWidth % 8 != 0 )
             {
                  CPLError( CE_Failure, CPLE_AppDefined,
                            "Format width %s is invalid.",
                            pszFormatString+2 );
                 return FALSE;
             }
-            
-            nFormatWidth = atoi(pszFormatString+2) / 8;
+
+            nFormatWidth = nFormatWidth / 8;
             eBinaryFormat = SInt; // good default, works for SDTS.
 
             if( nFormatWidth < 5 )
@@ -153,12 +161,19 @@ int DDFSubfieldDefn::SetFormat( const char * pszFormat )
             else
                 eType = DDFBinaryString;
         }
-        
+
         // or do we have a binary type indicator? (is it binary)
         else
         {
             eBinaryFormat = (DDFBinaryFormat) (pszFormatString[1] - '0');
             nFormatWidth = atoi(pszFormatString+2);
+            if( nFormatWidth < 0 )
+            {
+                 CPLError( CE_Failure, CPLE_AppDefined,
+                           "Format width %s is invalid.",
+                           pszFormatString+2 );
+                return FALSE;
+            }
 
             if( eBinaryFormat == SInt || eBinaryFormat == UInt )
                 eType = DDFInt;
@@ -168,22 +183,22 @@ int DDFSubfieldDefn::SetFormat( const char * pszFormat )
         break;
 
       case 'X':
-        // 'X' is extra space, and shouldn't be directly assigned to a
-        // subfield ... I haven't encountered it in use yet though.
+        // 'X' is extra space, and should not be directly assigned to a
+        // subfield ... I have not encountered it in use yet though.
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Format type of `%c' not supported.\n",
                   pszFormatString[0] );
-        
+
         return FALSE;
-        
+
       default:
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Format type of `%c' not recognised.\n",
                   pszFormatString[0] );
-        
+
         return FALSE;
     }
-    
+
     return TRUE;
 }
 
@@ -197,7 +212,7 @@ int DDFSubfieldDefn::SetFormat( const char * pszFormat )
  * A variety of information about this field definition is written to the
  * give debugging file handle.
  *
- * @param fp The standard io file handle to write to.  ie. stderr
+ * @param fp The standard IO file handle to write to.  i.e. stderr
  */
 
 void DDFSubfieldDefn::Dump( FILE * fp )
@@ -229,13 +244,13 @@ void DDFSubfieldDefn::Dump( FILE * fp )
  * @param pachSourceData The pointer to the raw data for this field.  This
  * may have come from DDFRecord::GetData(), taking into account skip factors
  * over previous subfields data.
- * @param nMaxBytes The maximum number of bytes that are accessable after
+ * @param nMaxBytes The maximum number of bytes that are accessible after
  * pachSourceData.
  * @param pnConsumedBytes Pointer to an integer into which the number of
  * bytes consumed by this field should be written.  May be NULL to ignore.
  *
  * @return The number of bytes at pachSourceData which are actual data for
- * this record (not including unit, or field terminator).  
+ * this record (not including unit, or field terminator).
  */
 
 int DDFSubfieldDefn::GetDataLength( const char * pachSourceData,
@@ -246,7 +261,7 @@ int DDFSubfieldDefn::GetDataLength( const char * pachSourceData,
     {
         if( nFormatWidth > nMaxBytes )
         {
-            CPLError( CE_Warning, CPLE_AppDefined, 
+            CPLError( CE_Warning, CPLE_AppDefined,
                       "Only %d bytes available for subfield %s with\n"
                       "format string %s ... returning shortened data.",
                       nMaxBytes, pszName, pszFormatString );
@@ -270,30 +285,30 @@ int DDFSubfieldDefn::GetDataLength( const char * pachSourceData,
         int     bAsciiField = TRUE;
         int     extraConsumedBytes = 0;
 
-        /* We only check for the field terminator because of some buggy 
+        /* We only check for the field terminator because of some buggy
          * datasets with missing format terminators.  However, we have found
-         * the field terminator and unit terminators are legal characters 
+         * the field terminator and unit terminators are legal characters
          * within the fields of some extended datasets (such as JP34NC94.000).
-         * So we don't check for the field terminator and unit terminators as 
-         * a single byte if the field appears to be multi-byte which we 
+         * So we don't check for the field terminator and unit terminators as
+         * a single byte if the field appears to be multi-byte which we
          * establish by checking for the buffer ending with 0x1e 0x00 (a
-         * two byte field terminator). 
+         * two byte field terminator).
          *
-         * In the case of S57, the subfield ATVL of the NATF field can be 
-         * encoded in lexical level 2 (see S57 specification, Edition 3.1, 
-         * paragraph 2.4 and 2.5). In that case the Unit Terminator and Field 
+         * In the case of S57, the subfield ATVL of the NATF field can be
+         * encoded in lexical level 2 (see S57 specification, Edition 3.1,
+         * paragraph 2.4 and 2.5). In that case the Unit Terminator and Field
          * Terminator are followed by the NULL character.
-         * A better fix would be to read the NALL tag in the DSSI to check 
-         * that the lexical level is 2, instead of relying on the value of 
+         * A better fix would be to read the NALL tag in the DSSI to check
+         * that the lexical level is 2, instead of relying on the value of
          * the first byte as we are doing - but that is not information
          * that is available at the libiso8211 level (bug #1526)
          */
 
         // If the whole field ends with 0x1e 0x00 then we assume this
         // field is a double byte character set.
-        if( nMaxBytes > 1 
-            && (pachSourceData[nMaxBytes-2] == chFormatDelimeter
-                || pachSourceData[nMaxBytes-2] == DDF_FIELD_TERMINATOR) 
+        if( nMaxBytes > 1
+            && (pachSourceData[nMaxBytes-2] == chFormatDelimiter
+                || pachSourceData[nMaxBytes-2] == DDF_FIELD_TERMINATOR)
             && pachSourceData[nMaxBytes-1] == 0x00 )
             bAsciiField = FALSE;
 
@@ -304,15 +319,15 @@ int DDFSubfieldDefn::GetDataLength( const char * pachSourceData,
         {
             if (bAsciiField)
             {
-                if (pachSourceData[nLength] == chFormatDelimeter ||
+                if (pachSourceData[nLength] == chFormatDelimiter ||
                     pachSourceData[nLength] == DDF_FIELD_TERMINATOR)
                     break;
             }
             else
             {
-                if (nLength > 0 
-                    && (pachSourceData[nLength-1] == chFormatDelimeter 
-                        || pachSourceData[nLength-1] == DDF_FIELD_TERMINATOR) 
+                if (nLength > 0
+                    && (pachSourceData[nLength-1] == chFormatDelimiter
+                        || pachSourceData[nLength-1] == DDF_FIELD_TERMINATOR)
                     && pachSourceData[nLength] == 0)
                 {
                     // Suck up the field terminator if one follows
@@ -322,9 +337,9 @@ int DDFSubfieldDefn::GetDataLength( const char * pachSourceData,
                         pachSourceData[nLength+1] == DDF_FIELD_TERMINATOR)
                         extraConsumedBytes++;
                     break;
-                } 
+                }
             }
-            
+
             nLength++;
         }
 
@@ -335,7 +350,7 @@ int DDFSubfieldDefn::GetDataLength( const char * pachSourceData,
             else
                 *pnConsumedBytes = nLength + extraConsumedBytes + 1;
         }
-        
+
         return nLength;
     }
 }
@@ -360,7 +375,7 @@ int DDFSubfieldDefn::GetDataLength( const char * pachSourceData,
  * @param pachSourceData The pointer to the raw data for this field.  This
  * may have come from DDFRecord::GetData(), taking into account skip factors
  * over previous subfields data.
- * @param nMaxBytes The maximum number of bytes that are accessable after
+ * @param nMaxBytes The maximum number of bytes that are accessible after
  * pachSourceData.
  * @param pnConsumedBytes Pointer to an integer into which the number of
  * bytes consumed by this field should be written.  May be NULL to ignore.
@@ -389,7 +404,7 @@ DDFSubfieldDefn::ExtractStringData( const char * pachSourceData,
     if( nMaxBufChars < nLength+1 )
     {
         CPLFree( pachBuffer );
-        
+
         nMaxBufChars = nLength+1;
         pachBuffer = (char *) CPLMalloc(nMaxBufChars);
     }
@@ -419,7 +434,7 @@ DDFSubfieldDefn::ExtractStringData( const char * pachSourceData,
  * @param pachSourceData The pointer to the raw data for this field.  This
  * may have come from DDFRecord::GetData(), taking into account skip factors
  * over previous subfields data.
- * @param nMaxBytes The maximum number of bytes that are accessable after
+ * @param nMaxBytes The maximum number of bytes that are accessible after
  * pachSourceData.
  * @param pnConsumedBytes Pointer to an integer into which the number of
  * bytes consumed by this field should be written.  May be NULL to ignore.
@@ -469,9 +484,9 @@ DDFSubfieldDefn::ExtractFloatData( const char * pachSourceData,
           // word aligned.
 #ifdef CPL_LSB
           if( pszFormatString[0] == 'B' )
-#else            
+#else
               if( pszFormatString[0] == 'b' )
-#endif            
+#endif
               {
                   for( int i = 0; i < nFormatWidth; i++ )
                       abyData[nFormatWidth-i-1] = pachSourceData[i];
@@ -496,7 +511,7 @@ DDFSubfieldDefn::ExtractFloatData( const char * pachSourceData,
                   //CPLAssert( FALSE );
                   return 0.0;
               }
-            
+
             case SInt:
               if( nFormatWidth == 1 )
                   return( *((signed char *) abyData) );
@@ -509,7 +524,7 @@ DDFSubfieldDefn::ExtractFloatData( const char * pachSourceData,
                   //CPLAssert( FALSE );
                   return 0.0;
               }
-            
+
             case FloatReal:
               if( nFormatWidth == 4 )
                   return( *((float *) pabyData) );
@@ -521,7 +536,7 @@ DDFSubfieldDefn::ExtractFloatData( const char * pachSourceData,
                   return 0.0;
               }
 
-            case NotBinary:            
+            case NotBinary:
             case FPReal:
             case FloatComplex:
               //CPLAssert( FALSE );
@@ -555,7 +570,7 @@ DDFSubfieldDefn::ExtractFloatData( const char * pachSourceData,
  * @param pachSourceData The pointer to the raw data for this field.  This
  * may have come from DDFRecord::GetData(), taking into account skip factors
  * over previous subfields data.
- * @param nMaxBytes The maximum number of bytes that are accessable after
+ * @param nMaxBytes The maximum number of bytes that are accessible after
  * pachSourceData.
  * @param pnConsumedBytes Pointer to an integer into which the number of
  * bytes consumed by this field should be written.  May be NULL to ignore.
@@ -590,7 +605,7 @@ DDFSubfieldDefn::ExtractIntData( const char * pachSourceData,
 
           if( nFormatWidth > nMaxBytes || nFormatWidth >= (int)sizeof(abyData) )
           {
-              CPLError( CE_Warning, CPLE_AppDefined, 
+              CPLError( CE_Warning, CPLE_AppDefined,
                         "Attempt to extract int subfield %s with format %s\n"
                         "failed as only %d bytes available.  Using zero.",
                         pszName, pszFormatString, MIN(nMaxBytes, (int)sizeof(abyData)) );
@@ -605,9 +620,9 @@ DDFSubfieldDefn::ExtractIntData( const char * pachSourceData,
           // word aligned.
 #ifdef CPL_LSB
           if( pszFormatString[0] == 'B' )
-#else            
+#else
               if( pszFormatString[0] == 'b' )
-#endif            
+#endif
               {
                   for( int i = 0; i < nFormatWidth; i++ )
                       abyData[nFormatWidth-i-1] = pachSourceData[i];
@@ -632,7 +647,7 @@ DDFSubfieldDefn::ExtractIntData( const char * pachSourceData,
                   //CPLAssert( FALSE );
                   return 0;
               }
-            
+
             case SInt:
               if( nFormatWidth == 4 )
                   return( *((GInt32 *) pabyData) );
@@ -645,7 +660,7 @@ DDFSubfieldDefn::ExtractIntData( const char * pachSourceData,
                   //CPLAssert( FALSE );
                   return 0;
               }
-            
+
             case FloatReal:
               if( nFormatWidth == 4 )
                   return( (int) *((float *) pabyData) );
@@ -657,7 +672,7 @@ DDFSubfieldDefn::ExtractIntData( const char * pachSourceData,
                   return 0;
               }
 
-            case NotBinary:            
+            case NotBinary:
             case FPReal:
             case FloatComplex:
               //CPLAssert( FALSE );
@@ -695,6 +710,11 @@ void DDFSubfieldDefn::DumpData( const char * pachData, int nMaxBytes,
                                 FILE * fp )
 
 {
+    if( nMaxBytes < 0 )
+    {
+        fprintf( fp, "      Subfield `%s' = {invalid length}\n", pszName );
+        return;
+    }
     if( eType == DDFFloat )
         fprintf( fp, "      Subfield `%s' = %f\n",
                  pszName,
@@ -728,17 +748,17 @@ void DDFSubfieldDefn::DumpData( const char * pachData, int nMaxBytes,
 /************************************************************************/
 
 /**
- * Get default data. 
+ * Get default data.
  *
  * Returns the default subfield data contents for this subfield definition.
- * For variable length numbers this will normally be "0<unit-terminator>". 
+ * For variable length numbers this will normally be "0<unit-terminator>".
  * For variable length strings it will be "<unit-terminator>".  For fixed
  * length numbers it is zero filled.  For fixed length strings it is space
- * filled.  For binary numbers it is binary zero filled. 
+ * filled.  For binary numbers it is binary zero filled.
  *
  * @param pachData the buffer into which the returned default will be placed.
  * May be NULL if just querying default size.
- * @param nBytesAvailable the size of pachData in bytes. 
+ * @param nBytesAvailable the size of pachData in bytes.
  * @param pnBytesUsed will receive the size of the subfield default data in
  * bytes.
  *
@@ -746,7 +766,7 @@ void DDFSubfieldDefn::DumpData( const char * pachData, int nMaxBytes,
  * small to hold the default.
  */
 
-int DDFSubfieldDefn::GetDefaultValue( char *pachData, int nBytesAvailable, 
+int DDFSubfieldDefn::GetDefaultValue( char *pachData, int nBytesAvailable,
                                       int *pnBytesUsed )
 
 {
@@ -772,15 +792,17 @@ int DDFSubfieldDefn::GetDefaultValue( char *pachData, int nBytesAvailable,
     }
     else
     {
+        char chFillChar;
         if( GetBinaryFormat() == NotBinary )
         {
             if( GetType() == DDFInt || GetType() == DDFFloat )
-                memset( pachData, '0', nDefaultSize );
+                chFillChar = '0'; /* ASCII zero intended */
             else
-                memset( pachData, ' ', nDefaultSize );
+                chFillChar = ' ';
         }
         else
-            memset( pachData, 0, nDefaultSize );
+            chFillChar = 0;
+        memset( pachData, chFillChar, nDefaultSize );
     }
 
     return TRUE;
@@ -794,11 +816,11 @@ int DDFSubfieldDefn::GetDefaultValue( char *pachData, int nBytesAvailable,
  * Format string subfield value.
  *
  * Returns a buffer with the passed in string value reformatted in a way
- * suitable for storage in a DDFField for this subfield.  
+ * suitable for storage in a DDFField for this subfield.
  */
 
-int DDFSubfieldDefn::FormatStringValue( char *pachData, int nBytesAvailable, 
-                                        int *pnBytesUsed, 
+int DDFSubfieldDefn::FormatStringValue( char *pachData, int nBytesAvailable,
+                                        int *pnBytesUsed,
                                         const char *pszValue,
                                         int nValueLength )
 
@@ -806,14 +828,14 @@ int DDFSubfieldDefn::FormatStringValue( char *pachData, int nBytesAvailable,
     int nSize;
 
     if( nValueLength == -1 )
-        nValueLength = strlen(pszValue);
+        nValueLength = static_cast<int>(strlen(pszValue));
 
     if( bIsVariable )
     {
         nSize = nValueLength + 1;
     }
     else
-    {                                                                  
+    {
         nSize = nFormatWidth;
     }
 
@@ -856,24 +878,24 @@ int DDFSubfieldDefn::FormatStringValue( char *pachData, int nBytesAvailable,
  * Format int subfield value.
  *
  * Returns a buffer with the passed in int value reformatted in a way
- * suitable for storage in a DDFField for this subfield.  
+ * suitable for storage in a DDFField for this subfield.
  */
 
-int DDFSubfieldDefn::FormatIntValue( char *pachData, int nBytesAvailable, 
+int DDFSubfieldDefn::FormatIntValue( char *pachData, int nBytesAvailable,
                                      int *pnBytesUsed, int nNewValue )
 
 {
     int nSize;
     char szWork[30];
 
-    sprintf( szWork, "%d", nNewValue );
+    snprintf( szWork, sizeof(szWork), "%d", nNewValue );
 
     if( bIsVariable )
     {
-        nSize = strlen(szWork) + 1;
+        nSize = static_cast<int>(strlen(szWork)) + 1;
     }
     else
-    {                                                                  
+    {
         nSize = nFormatWidth;
 
         if( GetBinaryFormat() == NotBinary && (int) strlen(szWork) > nSize )
@@ -902,10 +924,13 @@ int DDFSubfieldDefn::FormatIntValue( char *pachData, int nBytesAvailable,
         switch( GetBinaryFormat() )
         {
           case NotBinary:
-            memset( pachData, '0', nSize );
+          {
+            char chFillChar = '0'; /* ASCII zero intended */
+            memset( pachData, chFillChar, nSize );
             strncpy( pachData + nSize - strlen(szWork), szWork,
                      strlen(szWork) );
             break;
+          }
 
           case UInt:
           case SInt:
@@ -945,21 +970,21 @@ int DDFSubfieldDefn::FormatIntValue( char *pachData, int nBytesAvailable,
  * Format float subfield value.
  *
  * Returns a buffer with the passed in float value reformatted in a way
- * suitable for storage in a DDFField for this subfield.  
+ * suitable for storage in a DDFField for this subfield.
  */
 
-int DDFSubfieldDefn::FormatFloatValue( char *pachData, int nBytesAvailable, 
+int DDFSubfieldDefn::FormatFloatValue( char *pachData, int nBytesAvailable,
                                        int *pnBytesUsed, double dfNewValue )
 
 {
     int nSize;
     char szWork[120];
 
-    CPLsprintf( szWork, "%.16g", dfNewValue );
+    CPLsnprintf( szWork, sizeof(szWork), "%.16g", dfNewValue );
 
     if( bIsVariable )
     {
-        nSize = strlen(szWork) + 1;
+        nSize = static_cast<int>(strlen(szWork)) + 1;
     }
     else
     {
@@ -987,7 +1012,9 @@ int DDFSubfieldDefn::FormatFloatValue( char *pachData, int nBytesAvailable,
     {
         if( GetBinaryFormat() == NotBinary )
         {
-            memset( pachData, '0', nSize );
+            const char chFillZeroASCII = '0'; /* ASCII zero intended */
+            /* coverity[bad_memset] */
+            memset( pachData, chFillZeroASCII, nSize );
             strncpy( pachData + nSize - strlen(szWork), szWork,
                      strlen(szWork) );
         }
diff --git a/frmts/iso8211/ddfutils.cpp b/frmts/iso8211/ddfutils.cpp
index 50b0da7..bd9265e 100644
--- a/frmts/iso8211/ddfutils.cpp
+++ b/frmts/iso8211/ddfutils.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ddfutils.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: ddfutils.cpp 32179 2015-12-14 16:22:34Z goatbar $
  *
  * Project:  ISO 8211 Access
  * Purpose:  Various utility functions.
@@ -30,7 +30,7 @@
 #include "iso8211.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ddfutils.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: ddfutils.cpp 32179 2015-12-14 16:22:34Z goatbar $");
 
 /************************************************************************/
 /*                             DDFScanInt()                             */
@@ -39,7 +39,7 @@ CPL_CVSID("$Id: ddfutils.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
 /*      as an integer.                                                  */
 /************************************************************************/
 
-long DDFScanInt( const char * pszString, int nMaxChars )
+int DDFScanInt( const char * pszString, int nMaxChars )
 
 {
     char        szWorking[33];
@@ -64,7 +64,7 @@ int DDFScanVariable( const char *pszRecord, int nMaxChars, int nDelimChar )
 
 {
     int         i;
-    
+
     for( i = 0; i < nMaxChars-1 && pszRecord[i] != nDelimChar; i++ ) {}
 
     return i;
diff --git a/frmts/iso8211/intro.dox b/frmts/iso8211/intro.dox
index da726d9..0c2cc72 100644
--- a/frmts/iso8211/intro.dox
+++ b/frmts/iso8211/intro.dox
@@ -14,7 +14,7 @@ introduce it here, with reference to the library classes representing
 the components.<p>
 
 An 8211 file (DDFModule) 
-consists of a series of logical records.  The fiarst record
+consists of a series of logical records.  The first record
 is special, and is called the DDR (Data Description Record).  It basically
 contains definitions of all the data objects (fields or DDFFieldDefn objects) 
 that can occur on the following data records.<p>
@@ -61,7 +61,7 @@ DDFSubfieldDefn::ExtractStringValue(), or DDFSubfieldDefn::ExtractFloatValue().
 Note that there is no object instantiated for individual subfields of a
 DDFField.  Instead the application extracts a pointer to the subfields
 raw data, and then uses the DDFSubfieldDefn for that subfield to extract
-a useable value from the raw data.<p>
+a usable value from the raw data.<p>
 
 Once the end of the file has been encountered (DDFModule::ReadRecord() returns
 NULL), the DDFModule should be deleted, which will close the file, and
@@ -142,7 +142,7 @@ The precise license text is:<p>
 
 <ol>
 
-<li> First, fetch the source.  The most recent source should be accessable at
+<li> First, fetch the source.  The most recent source should be accessible at
 an url such as 
 <a href="http://home.gdal.org/projects/iso8211/iso8211lib-1.4.zip">
 http://home.gdal.org/projects/iso8211/iso8211lib-1.4.zip</a>.<p>
diff --git a/frmts/iso8211/iso8211.h b/frmts/iso8211/iso8211.h
index 81b51d4..92d933f 100644
--- a/frmts/iso8211/iso8211.h
+++ b/frmts/iso8211/iso8211.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: iso8211.h 25841 2013-04-02 21:30:03Z rouault $
+ * $Id: iso8211.h 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  ISO 8211 Access
  * Purpose:  Main declarations for ISO 8211.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _ISO8211_H_INCLUDED
-#define _ISO8211_H_INCLUDED
+#ifndef ISO8211_H_INCLUDED
+#define ISO8211_H_INCLUDED
 
 #include "cpl_port.h"
 #include "cpl_vsi.h"
@@ -42,13 +42,13 @@ typedef enum {
     DDFString,
     DDFBinaryString
 } DDFDataType;
-  
+
 /************************************************************************/
 /*      These should really be private to the library ... they are      */
 /*      mostly conveniences.                                            */
 /************************************************************************/
 
-long CPL_ODLL DDFScanInt( const char *pszString, int nMaxChars );
+int CPL_ODLL  DDFScanInt( const char *pszString, int nMaxChars );
 int  CPL_ODLL DDFScanVariable( const char * pszString, int nMaxChars, int nDelimChar );
 char CPL_ODLL *DDFFetchVariable( const char *pszString, int nMaxChars,
                         int nDelimChar1, int nDelimChar2,
@@ -73,22 +73,21 @@ class DDFField;
 /**
   The primary class for reading ISO 8211 files.  This class contains all
   the information read from the DDR record, and is used to read records
-  from the file.           
-
-*/  
+  from the file.
+*/
 
 class CPL_ODLL DDFModule
 {
   public:
                 DDFModule();
                 ~DDFModule();
-                
+
     int         Open( const char * pszFilename, int bFailQuietly = FALSE );
     int         Create( const char *pszFilename );
     void        Close();
 
     int         Initialize( char chInterchangeLevel = '3',
-                            char chLeaderIden = 'L', 
+                            char chLeaderIden = 'L',
                             char chCodeExtensionIndicator = 'E',
                             char chVersionNumber = '1',
                             char chAppIndicator = ' ',
@@ -109,16 +108,28 @@ class CPL_ODLL DDFModule
     int         GetFieldCount() { return nFieldDefnCount; }
     DDFFieldDefn *GetField(int);
     void        AddField( DDFFieldDefn *poNewFDefn );
-    
+
     // This is really just for internal use.
     int         GetFieldControlLength() { return _fieldControlLength; }
     void        AddCloneRecord( DDFRecord * );
     void        RemoveCloneRecord( DDFRecord * );
-    
+
     // This is just for DDFRecord.
     VSILFILE   *GetFP() { return fpDDF; }
     int         GetSizeFieldTag() const { return (int)_sizeFieldTag; }
-    
+
+    // Advanced uses for 8211dump/8211createfromxml
+    int         GetSizeFieldPos() const { return _sizeFieldPos; }
+    int         GetSizeFieldLength() const { return _sizeFieldLength; }
+    char        GetInterchangeLevel() const { return _interchangeLevel; }
+    char        GetLeaderIden() const { return _leaderIden; }
+    char        GetCodeExtensionIndicator() const { return _inlineCodeExtensionIndicator; }
+    char        GetVersionNumber() const { return _versionNumber; }
+    char        GetAppIndicator() const { return _appIndicator; }
+    const char* GetExtendedCharSet() const { return _extendedCharSet; }
+    void        SetFieldControlLength(int nVal) { _fieldControlLength = nVal; }
+
+
   private:
     VSILFILE    *fpDDF;
     int         bReadOnly;
@@ -131,14 +142,14 @@ class CPL_ODLL DDFModule
     int         _fieldControlLength;
     char        _extendedCharSet[4];
 
-    long _recLength;
+    int _recLength;
     char _leaderIden;
-    long _fieldAreaStart;
-    long _sizeFieldLength;
-    long _sizeFieldPos;
-    long _sizeFieldTag;
+    int _fieldAreaStart;
+    int _sizeFieldLength;
+    int _sizeFieldPos;
+    int _sizeFieldTag;
 
-    // One DirEntry per field.  
+    // One DirEntry per field.
     int         nFieldDefnCount;
     DDFFieldDefn **papoFieldDefns;
 
@@ -154,12 +165,12 @@ class CPL_ODLL DDFModule
 /************************************************************************/
 
   typedef enum { dsc_elementary, dsc_vector, dsc_array, dsc_concatenated } DDF_data_struct_code;
-  typedef enum { dtc_char_string, 
-                 dtc_implicit_point, 
-                 dtc_explicit_point, 
-                 dtc_explicit_point_scaled, 
-                 dtc_char_bit_string, 
-                 dtc_bit_string, 
+  typedef enum { dtc_char_string,
+                 dtc_implicit_point,
+                 dtc_explicit_point,
+                 dtc_explicit_point_scaled,
+                 dtc_char_bit_string,
+                 dtc_bit_string,
                  dtc_mixed_data_type } DDF_data_type_code;
 
 /**
@@ -183,26 +194,26 @@ class CPL_ODLL DDFFieldDefn
     void        AddSubfield( DDFSubfieldDefn *poNewSFDefn,
                              int bDontAddToFormat = FALSE );
     void        AddSubfield( const char *pszName, const char *pszFormat );
-    int         GenerateDDREntry( char **ppachData, int *pnLength ); 
-                            
+    int         GenerateDDREntry( DDFModule * poModule, char **ppachData, int *pnLength );
+
     int         Initialize( DDFModule * poModule, const char *pszTag,
                             int nSize, const char * pachRecord );
-    
+
     void        Dump( FILE * fp );
 
     /** Fetch a pointer to the field name (tag).
-     * @return this is an internal copy and shouldn't be freed.
+     * @return this is an internal copy and should not be freed.
      */
     const char  *GetName() { return pszTag; }
 
-    /** Fetch a longer descriptio of this field.
-     * @return this is an internal copy and shouldn't be freed.
+    /** Fetch a longer description of this field.
+     * @return this is an internal copy and should not be freed.
      */
     const char  *GetDescription() { return _fieldName; }
 
     /** Get the number of subfields. */
     int         GetSubfieldCount() { return nSubfieldCount; }
-    
+
     DDFSubfieldDefn *GetSubfield( int i );
     DDFSubfieldDefn *FindSubfieldDefn( const char * );
 
@@ -228,12 +239,14 @@ class CPL_ODLL DDFFieldDefn
     void SetRepeatingFlag( int n ) { bRepeatingSubfields = n; }
 
     char        *GetDefaultValue( int *pnSize );
-    
+
     const char  *GetArrayDescr() const { return _arrayDescr; }
     const char  *GetFormatControls() const { return _formatControls; }
     DDF_data_struct_code GetDataStructCode() const { return _data_struct_code; }
     DDF_data_type_code GetDataTypeCode() const { return _data_type_code; }
-    
+
+    void        SetFormatControls(const char* pszVal);
+
   private:
 
     static char       *ExtractSubstring( const char * );
@@ -246,7 +259,7 @@ class CPL_ODLL DDFFieldDefn
     char *      _formatControls;
 
     int         bRepeatingSubfields;
-    int         nFixedWidth;    // zero if variable. 
+    int         nFixedWidth;    // zero if variable.
 
     int         BuildSubfields();
     int         ApplyFormats();
@@ -268,7 +281,7 @@ class CPL_ODLL DDFFieldDefn
 
 /**
  * Information from the DDR record describing one subfield of a DDFFieldDefn.
- * All subfields of a field will occur in each occurance of that field
+ * All subfields of a field will occur in each occurrence of that field
  * (as a DDFField) in a DDFRecord.  Subfield's actually contain formatted
  * data (as instances within a record).
  */
@@ -284,7 +297,7 @@ public:
 
     /** Get pointer to subfield name. */
     const char  *GetName() { return pszName; }
-    
+
     /** Get pointer to subfield format string */
     const char  *GetFormat() { return pszFormatString; }
     int         SetFormat( const char * pszFormat );
@@ -296,7 +309,7 @@ public:
      * @return The subfield type.  One of DDFInt, DDFFloat, DDFString or
      * DDFBinaryString.
      */
-      
+
     DDFDataType GetType() { return eType; }
 
     double      ExtractFloatData( const char *pachData, int nMaxBytes,
@@ -308,27 +321,27 @@ public:
     int         GetDataLength( const char *, int, int * );
     void        DumpData( const char *pachData, int nMaxBytes, FILE * fp );
 
-    int         FormatStringValue( char *pachData, int nBytesAvailable, 
-                                   int *pnBytesUsed, const char *pszValue, 
+    int         FormatStringValue( char *pachData, int nBytesAvailable,
+                                   int *pnBytesUsed, const char *pszValue,
                                    int nValueLength = -1 );
 
-    int         FormatIntValue( char *pachData, int nBytesAvailable, 
+    int         FormatIntValue( char *pachData, int nBytesAvailable,
                                 int *pnBytesUsed, int nNewValue );
 
-    int         FormatFloatValue( char *pachData, int nBytesAvailable, 
+    int         FormatFloatValue( char *pachData, int nBytesAvailable,
                                   int *pnBytesUsed, double dfNewValue );
 
     /** Get the subfield width (zero for variable). */
     int         GetWidth() { return nFormatWidth; } // zero for variable.
 
-    int         GetDefaultValue( char *pachData, int nBytesAvailable, 
+    int         GetDefaultValue( char *pachData, int nBytesAvailable,
                                  int *pnBytesUsed );
-    
+
     void        Dump( FILE * fp );
 
 /**
   Binary format: this is the digit immediately following the B or b for
-  binary formats. 
+  binary formats.
   */
 typedef enum {
     NotBinary=0,
@@ -340,23 +353,23 @@ typedef enum {
 } DDFBinaryFormat;
 
     DDFBinaryFormat GetBinaryFormat(void) const { return eBinaryFormat; }
-    
+
 
 private:
 
   char      *pszName;   // a.k.a. subfield mnemonic
-  char      *pszFormatString; 
+  char      *pszFormatString;
 
   DDFDataType           eType;
   DDFBinaryFormat       eBinaryFormat;
 
 /* -------------------------------------------------------------------- */
 /*      bIsVariable determines whether we using the                     */
-/*      chFormatDelimeter (TRUE), or the fixed width (FALSE).           */
+/*      chFormatDelimiter (TRUE), or the fixed width (FALSE).           */
 /* -------------------------------------------------------------------- */
   int        bIsVariable;
-  
-  char       chFormatDelimeter;
+
+  char       chFormatDelimiter;
   int        nFormatWidth;
 
 /* -------------------------------------------------------------------- */
@@ -388,7 +401,7 @@ class CPL_ODLL DDFRecord
 
     DDFRecord  *Clone();
     DDFRecord  *CloneOn( DDFModule * );
-    
+
     void        Dump( FILE * );
 
     /** Get the number of DDFFields on this record. */
@@ -404,13 +417,13 @@ class CPL_ODLL DDFRecord
     const char *GetStringSubfield( const char *, int, const char *, int,
                                    int * = NULL );
 
-    int         SetIntSubfield( const char *pszField, int iFieldIndex, 
+    int         SetIntSubfield( const char *pszField, int iFieldIndex,
                                 const char *pszSubfield, int iSubfieldIndex,
                                 int nValue );
-    int         SetStringSubfield( const char *pszField, int iFieldIndex, 
+    int         SetStringSubfield( const char *pszField, int iFieldIndex,
                                    const char *pszSubfield, int iSubfieldIndex,
                                    const char *pszValue, int nValueLength=-1 );
-    int         SetFloatSubfield( const char *pszField, int iFieldIndex, 
+    int         SetFloatSubfield( const char *pszField, int iFieldIndex,
                                   const char *pszSubfield, int iSubfieldIndex,
                                   double dfNewValue );
 
@@ -419,7 +432,7 @@ class CPL_ODLL DDFRecord
 
     /**
      * Fetch the raw data for this record.  The returned pointer is effectively
-     * to the data for the first field of the record, and is of size 
+     * to the data for the first field of the record, and is of size
      * GetDataSize().
      */
     const char  *GetData() { return pachData; }
@@ -436,26 +449,37 @@ class CPL_ODLL DDFRecord
 
     int CreateDefaultFieldInstance( DDFField *poField, int iIndexWithinField );
 
-    int SetFieldRaw( DDFField *poField, int iIndexWithinField, 
+    int SetFieldRaw( DDFField *poField, int iIndexWithinField,
                      const char *pachRawData, int nRawDataSize );
-    int UpdateFieldRaw( DDFField *poField, int iIndexWithinField, 
+    int UpdateFieldRaw( DDFField *poField, int iIndexWithinField,
                         int nStartOffset, int nOldSize,
                         const char *pachRawData, int nRawDataSize );
 
     int         Write();
-    
+
+    // Advanced uses for 8211dump/8211createfromxml
+    int         GetReuseHeader() const { return nReuseHeader; }
+    int         GetSizeFieldTag() const { return _sizeFieldTag; }
+    int         GetSizeFieldPos() const { return _sizeFieldPos; }
+    int         GetSizeFieldLength() const { return _sizeFieldLength; }
+    //void        SetReuseHeader(int bFlag) { nReuseHeader = bFlag; }
+    void        SetSizeFieldTag(int nVal) { _sizeFieldTag = nVal; }
+    void        SetSizeFieldPos(int nVal) { _sizeFieldPos = nVal; }
+    void        SetSizeFieldLength(int nVal) { _sizeFieldLength = nVal; }
+
     // This is really just for the DDFModule class.
     int         Read();
     void        Clear();
     int         ResetDirectory();
-    
+    void        RemoveIsCloneFlag() { bIsClone = FALSE; }
+
   private:
 
     int         ReadHeader();
-    
+
     DDFModule   *poModule;
 
-    int         nReuseHeader;   
+    int         nReuseHeader;
 
     int         nFieldOffset;   // field data area, not dir entries.
 
@@ -502,7 +526,7 @@ class CPL_ODLL DDFField
 
     /**
      * Return the pointer to the entire data block for this record. This
-     * is an internal copy, and shouldn't be freed by the application.
+     * is an internal copy, and should not be freed by the application.
      */
     const char         *GetData() { return pachData; }
 
@@ -513,7 +537,7 @@ class CPL_ODLL DDFField
 
     /** Fetch the corresponding DDFFieldDefn. */
     DDFFieldDefn        *GetFieldDefn() { return poDefn; }
-    
+
   private:
     DDFFieldDefn        *poDefn;
 
@@ -523,4 +547,4 @@ class CPL_ODLL DDFField
 };
 
 
-#endif /* ndef _ISO8211_H_INCLUDED */
+#endif /* ndef ISO8211_H_INCLUDED */
diff --git a/frmts/iso8211/mkcatalog.cpp b/frmts/iso8211/mkcatalog.cpp
index cf81617..33bae38 100644
--- a/frmts/iso8211/mkcatalog.cpp
+++ b/frmts/iso8211/mkcatalog.cpp
@@ -1,5 +1,5 @@
 /* ****************************************************************************
- * $Id: mkcatalog.cpp 16861 2009-04-26 19:22:29Z rouault $
+ * $Id: mkcatalog.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  ISO8211 Library
  * Purpose:  Test ISO8211 writing capability.
@@ -29,7 +29,7 @@
 
 #include "iso8211.h"
 
-CPL_CVSID("$Id: mkcatalog.cpp 16861 2009-04-26 19:22:29Z rouault $");
+CPL_CVSID("$Id: mkcatalog.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 
 /************************************************************************/
@@ -58,7 +58,7 @@ void mk_s57()
 /* -------------------------------------------------------------------- */
     poFDefn = new DDFFieldDefn();
 
-    poFDefn->Create( "0001", "ISO 8211 Record Identifier", "", 
+    poFDefn->Create( "0001", "ISO 8211 Record Identifier", "",
                      dsc_elementary, dtc_bit_string,
                      "(b12)" );
 
@@ -197,7 +197,7 @@ void mk_s57()
 
 /* -------------------------------------------------------------------- */
 
-// need to add: VRPC, VRPT, SGCC, FRID, FOID, ATTF, NATF, FFPC, 
+// need to add: VRPC, VRPT, SGCC, FRID, FOID, ATTF, NATF, FFPC,
 // FFPT, FSPC, and FSPT
 
 /* -------------------------------------------------------------------- */
@@ -325,8 +325,8 @@ void mk_catalog()
 /* -------------------------------------------------------------------- */
     poFDefn = new DDFFieldDefn();
 
-    poFDefn->Create( "0000", "", "0001CATD", 
-                     dsc_elementary, 
+    poFDefn->Create( "0000", "", "0001CATD",
+                     dsc_elementary,
                      dtc_char_string );
 
     oModule.AddField( poFDefn );
@@ -336,7 +336,7 @@ void mk_catalog()
 /* -------------------------------------------------------------------- */
     poFDefn = new DDFFieldDefn();
 
-    poFDefn->Create( "0001", "ISO 8211 Record Identifier", "", 
+    poFDefn->Create( "0001", "ISO 8211 Record Identifier", "",
                      dsc_elementary, dtc_bit_string,
                      "(b12)" );
 
@@ -384,7 +384,7 @@ void mk_catalog()
     poRec->SetStringSubfield( "CATD", 0, "FILE", 0, "CATALOG.030" );
     poRec->SetStringSubfield( "CATD", 0, "VOLM", 0, "V01X01" );
     poRec->SetStringSubfield( "CATD", 0, "IMPL", 0, "ASC" );
-    poRec->SetStringSubfield( "CATD", 0, "COMT", 0, 
+    poRec->SetStringSubfield( "CATD", 0, "COMT", 0,
                               "Exchange Set Catalog file" );
     poRec->Write();
     delete poRec;
@@ -421,4 +421,3 @@ int main( int nArgc, char ** papszArgv )
 {
     mk_s57();
 }
-
diff --git a/frmts/iso8211/timetest.cpp b/frmts/iso8211/timetest.cpp
index 163c451..11c321b 100644
--- a/frmts/iso8211/timetest.cpp
+++ b/frmts/iso8211/timetest.cpp
@@ -1,5 +1,5 @@
 /* ****************************************************************************
- * $Id: timetest.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: timetest.cpp 32179 2015-12-14 16:22:34Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Example program dumping data in 8211 data to stdout.
@@ -71,8 +71,7 @@ int main( int nArgc, char ** papszArgv )
         DDFRecord       *poRecord;
         int             nRecordCount = 0;
         int             nFieldCount = 0;
-            
-    
+
         while( (poRecord = oModule.ReadRecord()) != NULL )
         {
             /* ------------------------------------------------------------ */
@@ -108,13 +107,13 @@ static void ViewRecordField( DDFField * poField )
     int         nBytesRemaining;
     const char  *pachFieldData;
     DDFFieldDefn *poFieldDefn = poField->GetFieldDefn();
-    
+
     // Get pointer to this fields raw data.  We will move through
     // it consuming data as we report subfield values.
-            
+
     pachFieldData = poField->GetData();
     nBytesRemaining = poField->GetDataSize();
-                
+
     /* -------------------------------------------------------- */
     /*      Loop over the repeat count for this fields          */
     /*      subfields.  The repeat count will almost            */
@@ -123,7 +122,7 @@ static void ViewRecordField( DDFField * poField )
     int         iRepeat, nRepeatCount;
 
     nRepeatCount = poField->GetRepeatCount();
-            
+
     for( iRepeat = 0; iRepeat < nRepeatCount; iRepeat++ )
     {
 
@@ -132,7 +131,7 @@ static void ViewRecordField( DDFField * poField )
         /*   the data pointer as we consume data.                   */
         /* -------------------------------------------------------- */
         int     iSF;
-        
+
         for( iSF = 0; iSF < poFieldDefn->GetSubfieldCount(); iSF++ )
         {
             DDFSubfieldDefn *poSFDefn = poFieldDefn->GetSubfield( iSF );
@@ -157,7 +156,7 @@ static int ViewSubfield( DDFSubfieldDefn *poSFDefn,
 
 {
     int         nBytesConsumed = 0;
-    
+
     switch( poSFDefn->GetType() )
     {
       case DDFInt:
diff --git a/frmts/jaxapalsar/frmt_palsar.html b/frmts/jaxapalsar/frmt_palsar.html
index 2d2abb0..2677f4d 100644
--- a/frmts/jaxapalsar/frmt_palsar.html
+++ b/frmts/jaxapalsar/frmt_palsar.html
@@ -32,7 +32,7 @@ This driver does not support products created using the Vexcel processor (i.e. p
 <p>See Also:</p>
 
 <ul>
-<li> <a href="http://www.alos-restec.jp/sampledata_e.html">RESTEC Sample Data</a></li>
+<li> <a href="http://www.alos-restec.jp/en/staticpages/index.php/service-sampledata">RESTEC Sample Data</a></li>
 </ul>
 
 </body>
diff --git a/frmts/jaxapalsar/jaxapalsardataset.cpp b/frmts/jaxapalsar/jaxapalsardataset.cpp
index a6717a8..01bb7b3 100644
--- a/frmts/jaxapalsar/jaxapalsardataset.cpp
+++ b/frmts/jaxapalsar/jaxapalsardataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: jaxapalsardataset.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: jaxapalsardataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  PALSAR JAXA imagery reader
  * Purpose:  Support for PALSAR L1.1/1.5 imagery and appropriate metadata from
@@ -30,15 +30,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: jaxapalsardataset.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: jaxapalsardataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
-CPL_C_START
-void	GDALRegister_PALSARJaxa(void);
-CPL_C_END
-
-#if defined(WIN32) || defined(WIN32CE)
+#if defined(WIN32)
 #define SEP_STRING "\\"
 #else
 #define SEP_STRING "/"
@@ -80,7 +77,7 @@ CPL_C_END
 		(x) = atoi(psBuf); \
 	} while (0);
 
-/* read string fields 
+/* read string fields
  * note: string must be size of field to be extracted + 1
  */
 #define READ_STRING(s, n, f) \
@@ -140,7 +137,8 @@ CPL_C_END
 enum eFileType {
 	level_11 = 0,
 	level_15,
-    level_10
+        level_10,
+        level_unknown = 999,
 };
 
 enum ePolarization {
@@ -176,18 +174,18 @@ public:
     static void ReadMetadata( PALSARJaxaDataset *poDS, VSILFILE *fp );
 };
 
-PALSARJaxaDataset::PALSARJaxaDataset()
-{
-    pasGCPList = NULL;
-    nGCPCount = 0;
-}
+PALSARJaxaDataset::PALSARJaxaDataset() :
+    pasGCPList(NULL),
+    nGCPCount(0),
+    nFileType(level_unknown)
+{ }
 
 PALSARJaxaDataset::~PALSARJaxaDataset()
 {
-    if( nGCPCount > 0 ) 
+    if( nGCPCount > 0 )
     {
-        GDALDeinitGCPs( nGCPCount, pasGCPList ); 
-        CPLFree( pasGCPList ); 
+        GDALDeinitGCPs( nGCPCount, pasGCPList );
+        CPLFree( pasGCPList );
     }
 }
 
@@ -206,6 +204,7 @@ class PALSARJaxaRasterBand : public GDALRasterBand {
     int nBitsPerSample;
     int nSamplesPerGroup;
     int nRecordSize;
+
 public:
     PALSARJaxaRasterBand( PALSARJaxaDataset *poDS, int nBand, VSILFILE *fp );
     ~PALSARJaxaRasterBand();
@@ -217,10 +216,13 @@ public:
 /*                         PALSARJaxaRasterBand()                       */
 /************************************************************************/
 
-PALSARJaxaRasterBand::PALSARJaxaRasterBand( PALSARJaxaDataset *poDS, 
-	int nBand, VSILFILE *fp )
+PALSARJaxaRasterBand::PALSARJaxaRasterBand( PALSARJaxaDataset *poDSIn,
+                                            int nBandIn, VSILFILE *fpIn ) :
+    nPolarization(hh)
 {
-    this->fp = fp;
+    poDS = poDSIn;
+    nBand = nBandIn;
+    this->fp = fpIn;
 
     /* Read image options record to determine the type of data */
     VSIFSeekL( fp, BITS_PER_SAMPLE_OFFSET, SEEK_SET );
@@ -242,19 +244,23 @@ PALSARJaxaRasterBand::PALSARJaxaRasterBand( PALSARJaxaDataset *poDS,
         nFileType = level_15;
     }
 
-    poDS->nFileType = nFileType;
+    poDSIn->nFileType = nFileType;
 
     /* Read number of range/azimuth lines */
     VSIFSeekL( fp, NUMBER_LINES_OFFSET, SEEK_SET );
     READ_CHAR_VAL( nRasterYSize, NUMBER_LINES_LENGTH, fp );
     VSIFSeekL( fp, SAR_DATA_RECORD_LENGTH_OFFSET, SEEK_SET );
     READ_CHAR_VAL( nRecordSize, SAR_DATA_RECORD_LENGTH_LENGTH, fp );
-    nRasterXSize = (nRecordSize -
+    int nDenom = ((nBitsPerSample / 8) * nSamplesPerGroup);
+    if( nDenom == 0 )
+        nRasterXSize = 0;
+    else
+        nRasterXSize = (nRecordSize -
                     (nFileType != level_15 ? SIG_DAT_REC_OFFSET : PROC_DAT_REC_OFFSET))
-        / ((nBitsPerSample / 8) * nSamplesPerGroup);
+        / nDenom;
 
-    poDS->nRasterXSize = nRasterXSize;
-    poDS->nRasterYSize = nRasterYSize;
+    poDSIn->nRasterXSize = nRasterXSize;
+    poDSIn->nRasterYSize = nRasterYSize;
 
     /* Polarization */
     switch (nBand) {
@@ -274,15 +280,16 @@ PALSARJaxaRasterBand::PALSARJaxaRasterBand( PALSARJaxaDataset *poDS,
         nPolarization = vv;
         SetMetadataItem( "POLARIMETRIC_INTERP", "VV" );
         break;
+      // TODO: What about the default?
     }
-	
+
     /* size of block we can read */
     nBlockXSize = nRasterXSize;
     nBlockYSize = 1;
 
     /* set the file pointer to the first SAR data record */
     VSIFSeekL( fp, IMAGE_OPT_DESC_LENGTH, SEEK_SET );
-}	
+}
 
 /************************************************************************/
 /*                        ~PALSARJaxaRasterBand()                       */
@@ -310,7 +317,7 @@ CPLErr PALSARJaxaRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
         nNumBytes = 2;
     }
 
-    int nOffset = IMAGE_OPT_DESC_LENGTH + ((nBlockYOff - 1) * nRecordSize) + 
+    int nOffset = IMAGE_OPT_DESC_LENGTH + ((nBlockYOff - 1) * nRecordSize) +
         (nFileType == level_11 ? SIG_DAT_REC_OFFSET : PROC_DAT_REC_OFFSET);
 
     VSIFSeekL( fp, nOffset, SEEK_SET );
@@ -319,7 +326,7 @@ CPLErr PALSARJaxaRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 #ifdef CPL_LSB
     if (nFileType == level_11)
         GDALSwapWords( pImage, 4, nBlockXSize * 2, 4 );
-    else 
+    else
         GDALSwapWords( pImage, 2, nBlockXSize, 2 );
 #endif
 
@@ -369,49 +376,49 @@ void PALSARJaxaDataset::ReadMetadata( PALSARJaxaDataset *poDS, VSILFILE *fp ) {
     else {
         poDS->SetMetadataItem( "PRODUCT_LEVEL", "1.5" );
         /* extract equivalent number of looks */
-        VSIFSeekL( fp, LEADER_FILE_DESCRIPTOR_LENGTH + 
+        VSIFSeekL( fp, LEADER_FILE_DESCRIPTOR_LENGTH +
                   EFFECTIVE_LOOKS_AZIMUTH_OFFSET, SEEK_SET );
-        char pszENL[17];
+        char szENL[17];
         double dfENL;
         READ_CHAR_FLOAT(dfENL, 16, fp);
-        sprintf( pszENL, "%-16.1f", dfENL );
-        poDS->SetMetadataItem( "AZIMUTH_LOOKS", pszENL );
+        snprintf( szENL, sizeof(szENL), "%-16.1f", dfENL );
+        poDS->SetMetadataItem( "AZIMUTH_LOOKS", szENL );
 
         /* extract pixel spacings */
         VSIFSeekL( fp, LEADER_FILE_DESCRIPTOR_LENGTH +
                   DATA_SET_SUMMARY_LENGTH + PIXEL_SPACING_OFFSET, SEEK_SET );
         double dfPixelSpacing;
         double dfLineSpacing;
-        char pszPixelSpacing[33];
-        char pszLineSpacing[33];
+        char szPixelSpacing[33];
+        char szLineSpacing[33];
         READ_CHAR_FLOAT(dfPixelSpacing, 16, fp);
         READ_CHAR_FLOAT(dfLineSpacing, 16, fp);
-        sprintf( pszPixelSpacing, "%-32.1f",dfPixelSpacing );
-        sprintf( pszLineSpacing, "%-32.1f", dfLineSpacing );
-        poDS->SetMetadataItem( "PIXEL_SPACING", pszPixelSpacing );
-        poDS->SetMetadataItem( "LINE_SPACING", pszPixelSpacing );
+        snprintf( szPixelSpacing, sizeof(szPixelSpacing), "%-32.1f",dfPixelSpacing );
+        snprintf( szLineSpacing, sizeof(szLineSpacing), "%-32.1f", dfLineSpacing );
+        poDS->SetMetadataItem( "PIXEL_SPACING", szPixelSpacing );
+        poDS->SetMetadataItem( "LINE_SPACING", szPixelSpacing );
 
         /* Alphanumeric projection name */
         VSIFSeekL( fp, LEADER_FILE_DESCRIPTOR_LENGTH +
                   DATA_SET_SUMMARY_LENGTH + ALPHANUMERIC_PROJECTION_NAME_OFFSET,
                   SEEK_SET );
-        char pszProjName[33];
-        READ_STRING(pszProjName, 32, fp);
-        poDS->SetMetadataItem( "PROJECTION_NAME", pszProjName );
-		
+        char szProjName[33];
+        READ_STRING(szProjName, 32, fp);
+        poDS->SetMetadataItem( "PROJECTION_NAME", szProjName );
+
         /* Extract corner GCPs */
         poDS->nGCPCount = 4;
-        poDS->pasGCPList = (GDAL_GCP *)CPLCalloc( sizeof(GDAL_GCP), 
+        poDS->pasGCPList = (GDAL_GCP *)CPLCalloc( sizeof(GDAL_GCP),
                                                   poDS->nGCPCount );
         GDALInitGCPs( poDS->nGCPCount, poDS->pasGCPList );
 
         /* setup the GCPs */
         int i;
         for (i = 0; i < poDS->nGCPCount; i++) {
-            char pszID[2];
-            sprintf( pszID, "%d", i + 1);
+            char szID[30];
+            snprintf( szID, sizeof(szID), "%d", i + 1);
             CPLFree(poDS->pasGCPList[i].pszId);
-            poDS->pasGCPList[i].pszId = CPLStrdup( pszID );
+            poDS->pasGCPList[i].pszId = CPLStrdup( szID );
             poDS->pasGCPList[i].dfGCPZ = 0.0;
         }
 
@@ -419,7 +426,7 @@ void PALSARJaxaDataset::ReadMetadata( PALSARJaxaDataset *poDS, VSILFILE *fp ) {
         /* seek to start of GCPs */
         VSIFSeekL( fp, LEADER_FILE_DESCRIPTOR_LENGTH +
                   DATA_SET_SUMMARY_LENGTH + TOP_LEFT_LAT_OFFSET, SEEK_SET );
-		
+
         /* top-left GCP */
         READ_CHAR_FLOAT(dfTemp, 16, fp);
         poDS->pasGCPList[0].dfGCPY = dfTemp;
@@ -474,9 +481,8 @@ int PALSARJaxaDataset::Identify( GDALOpenInfo *poOpenInfo ) {
         return 0;
 
     /* First, check that this is a PALSAR image indeed */
-    if ( !EQUALN((char *)(poOpenInfo->pabyHeader + 60),"AL", 2) 
-         || !EQUALN(CPLGetBasename((char *)(poOpenInfo->pszFilename)) + 4, 
-                    "ALPSR", 5) )
+    if ( !STARTS_WITH_CI((char *)(poOpenInfo->pabyHeader + 60), "AL")
+         || !STARTS_WITH_CI(CPLGetBasename((char *)(poOpenInfo->pszFilename)) + 4, "ALPSR") )
     {
         return 0;
     }
@@ -521,18 +527,18 @@ GDALDataset *PALSARJaxaDataset::Open( GDALOpenInfo * poOpenInfo ) {
     /* Check that this actually is a JAXA PALSAR product */
     if ( !PALSARJaxaDataset::Identify(poOpenInfo) )
         return NULL;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The JAXAPALSAR driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
     }
-    
+
     PALSARJaxaDataset *poDS = new PALSARJaxaDataset();
 
     /* Get the suffix of the filename, we'll need this */
@@ -540,25 +546,26 @@ GDALDataset *PALSARJaxaDataset::Open( GDALOpenInfo * poOpenInfo ) {
                                  (CPLGetFilename( poOpenInfo->pszFilename ) + 3) );
 
     /* Try to read each of the polarizations */
-    char *pszImgFile = (char *)VSIMalloc( 
-        strlen( CPLGetDirname( poOpenInfo->pszFilename ) ) + 
-        strlen( pszSuffix ) + 8 );
+    const size_t nImgFileLen =
+        strlen( CPLGetDirname( poOpenInfo->pszFilename ) ) +
+        strlen( pszSuffix ) + 8;
+    char *pszImgFile = (char *)CPLMalloc( nImgFileLen );
 
     int nBandNum = 1;
 
     /* HH */
     VSILFILE *fpHH;
-    sprintf( pszImgFile, "%s%sIMG-HH%s", 
+    snprintf( pszImgFile, nImgFileLen, "%s%sIMG-HH%s",
              CPLGetDirname(poOpenInfo->pszFilename), SEP_STRING, pszSuffix );
     fpHH = VSIFOpenL( pszImgFile, "rb" );
-    if (fpHH != NULL) { 
+    if (fpHH != NULL) {
         poDS->SetBand( nBandNum, new PALSARJaxaRasterBand( poDS, 0, fpHH ) );
         nBandNum++;
     }
 
     /* HV */
     VSILFILE *fpHV;
-    sprintf( pszImgFile, "%s%sIMG-HV%s", 
+    snprintf( pszImgFile, nImgFileLen, "%s%sIMG-HV%s",
              CPLGetDirname(poOpenInfo->pszFilename), SEP_STRING, pszSuffix );
     fpHV = VSIFOpenL( pszImgFile, "rb" );
     if (fpHV != NULL) {
@@ -568,7 +575,7 @@ GDALDataset *PALSARJaxaDataset::Open( GDALOpenInfo * poOpenInfo ) {
 
     /* VH */
     VSILFILE *fpVH;
-    sprintf( pszImgFile, "%s%sIMG-VH%s", 
+    snprintf( pszImgFile, nImgFileLen, "%s%sIMG-VH%s",
              CPLGetDirname(poOpenInfo->pszFilename), SEP_STRING, pszSuffix );
     fpVH = VSIFOpenL( pszImgFile, "rb" );
     if (fpVH != NULL) {
@@ -578,7 +585,7 @@ GDALDataset *PALSARJaxaDataset::Open( GDALOpenInfo * poOpenInfo ) {
 
     /* VV */
     VSILFILE *fpVV;
-    sprintf( pszImgFile, "%s%sIMG-VV%s",
+    snprintf( pszImgFile, nImgFileLen, "%s%sIMG-VV%s",
              CPLGetDirname(poOpenInfo->pszFilename), SEP_STRING, pszSuffix );
     fpVV = VSIFOpenL( pszImgFile, "rb" );
     if (fpVV != NULL) {
@@ -607,10 +614,10 @@ GDALDataset *PALSARJaxaDataset::Open( GDALOpenInfo * poOpenInfo ) {
     }
 
     /* read metadata from Leader file. */
-    char *pszLeaderFilename = (char *)VSIMalloc( 
-        strlen( CPLGetDirname( poOpenInfo->pszFilename ) ) + 
-        strlen(pszSuffix) + 5 );
-    sprintf( pszLeaderFilename, "%s%sLED%s", 
+    const size_t nLeaderFilenameLen = strlen( CPLGetDirname( poOpenInfo->pszFilename ) ) +
+        strlen(pszSuffix) + 5;
+    char *pszLeaderFilename = (char *)CPLMalloc( nLeaderFilenameLen );
+    snprintf( pszLeaderFilename, nLeaderFilenameLen, "%s%sLED%s",
              CPLGetDirname( poOpenInfo->pszFilename ) , SEP_STRING, pszSuffix );
 
     VSILFILE *fpLeader = VSIFOpenL( pszLeaderFilename, "rb" );
@@ -642,21 +649,23 @@ GDALDataset *PALSARJaxaDataset::Open( GDALOpenInfo * poOpenInfo ) {
 /*                      GDALRegister_PALSARJaxa()                       */
 /************************************************************************/
 
-void GDALRegister_PALSARJaxa() {
-    GDALDriver	*poDriver;
-
-    if( GDALGetDriverByName( "JAXAPALSAR" ) == NULL ) {
-        poDriver = new GDALDriver();
-        poDriver->SetDescription( "JAXAPALSAR" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "JAXA PALSAR Product Reader (Level 1.1/1.5)" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_palsar.html" );
-        poDriver->pfnOpen = PALSARJaxaDataset::Open;
-        poDriver->pfnIdentify = PALSARJaxaDataset::Identify;
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+void GDALRegister_PALSARJaxa()
+
+{
+    if( GDALGetDriverByName( "JAXAPALSAR" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "JAXAPALSAR" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "JAXA PALSAR Product Reader (Level 1.1/1.5)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_palsar.html" );
+
+    poDriver->pfnOpen = PALSARJaxaDataset::Open;
+    poDriver->pfnIdentify = PALSARJaxaDataset::Identify;
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/jdem/jdemdataset.cpp b/frmts/jdem/jdemdataset.cpp
index 5bd7a92..9de4534 100644
--- a/frmts/jdem/jdemdataset.cpp
+++ b/frmts/jdem/jdemdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: jdemdataset.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: jdemdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  JDEM Reader
  * Purpose:  All code for Japanese DEM Reader
@@ -28,13 +28,10 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: jdemdataset.cpp 27745 2014-09-27 16:38:57Z goatbar $");
-
-CPL_C_START
-void	GDALRegister_JDEM(void);
-CPL_C_END
+CPL_CVSID("$Id: jdemdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /*                            JDEMGetField()                            */
@@ -61,16 +58,15 @@ static double JDEMGetAngle( char *pszField )
 
 {
     int		nAngle = JDEMGetField( pszField, 7 );
-    int		nDegree, nMin, nSec;
 
     // Note, this isn't very general purpose, but it would appear
     // from the field widths that angles are never negative.  Nice
-    // to be a country in the "first quadrant". 
+    // to be a country in the "first quadrant".
+
+    const int nDegree = nAngle / 10000;
+    const int nMin = (nAngle / 100) % 100;
+    const int nSec = nAngle % 100;
 
-    nDegree = nAngle / 10000;
-    nMin = (nAngle / 100) % 100;
-    nSec = nAngle % 100;
-    
     return nDegree + nMin / 60.0 + nSec / 3600.0;
 }
 
@@ -92,7 +88,7 @@ class JDEMDataset : public GDALPamDataset
   public:
                      JDEMDataset();
                     ~JDEMDataset();
-    
+
     static GDALDataset *Open( GDALOpenInfo * );
     static int Identify( GDALOpenInfo * );
 
@@ -113,12 +109,12 @@ class JDEMRasterBand : public GDALPamRasterBand
     int          nRecordSize;
     char*        pszRecord;
     int          bBufferAllocFailed;
-    
+
   public:
 
     		JDEMRasterBand( JDEMDataset *, int );
                 ~JDEMRasterBand();
-    
+
     virtual CPLErr IReadBlock( int, int, void * );
 };
 
@@ -127,11 +123,12 @@ class JDEMRasterBand : public GDALPamRasterBand
 /*                           JDEMRasterBand()                            */
 /************************************************************************/
 
-JDEMRasterBand::JDEMRasterBand( JDEMDataset *poDS, int nBand )
-
+JDEMRasterBand::JDEMRasterBand( JDEMDataset *poDSIn, int nBandIn ) :
+    pszRecord(NULL),
+    bBufferAllocFailed(FALSE)
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
 
     eDataType = GDT_Float32;
 
@@ -140,8 +137,6 @@ JDEMRasterBand::JDEMRasterBand( JDEMDataset *poDS, int nBand )
 
     /* Cannot overflow as nBlockXSize <= 999 */
     nRecordSize = nBlockXSize*5 + 9 + 2;
-    pszRecord = NULL;
-    bBufferAllocFailed = FALSE;
 }
 
 /************************************************************************/
@@ -163,44 +158,41 @@ CPLErr JDEMRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 
 {
     JDEMDataset *poGDS = (JDEMDataset *) poDS;
-    int		i;
-    
+
     if (pszRecord == NULL)
     {
         if (bBufferAllocFailed)
             return CE_Failure;
 
-        pszRecord = (char *) VSIMalloc(nRecordSize);
+        pszRecord = (char *) VSI_MALLOC_VERBOSE(nRecordSize);
         if (pszRecord == NULL)
         {
-            CPLError(CE_Failure, CPLE_OutOfMemory,
-                     "Cannot allocate scanline buffer");
             bBufferAllocFailed = TRUE;
             return CE_Failure;
         }
     }
 
-    VSIFSeekL( poGDS->fp, 1011 + nRecordSize*nBlockYOff, SEEK_SET );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( poGDS->fp, 1011 + nRecordSize*nBlockYOff, SEEK_SET ));
 
-    VSIFReadL( pszRecord, 1, nRecordSize, poGDS->fp );
+    CPL_IGNORE_RET_VAL(VSIFReadL( pszRecord, 1, nRecordSize, poGDS->fp ));
 
     if( !EQUALN((char *) poGDS->abyHeader,pszRecord,6) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "JDEM Scanline corrupt.  Perhaps file was not transferred\n"
                   "in binary mode?" );
         return CE_Failure;
     }
-    
+
     if( JDEMGetField( pszRecord + 6, 3 ) != nBlockYOff + 1 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "JDEM scanline out of order, JDEM driver does not\n"
                   "currently support partial datasets." );
         return CE_Failure;
     }
 
-    for( i = 0; i < nBlockXSize; i++ )
+    for( int i = 0; i < nBlockXSize; i++ )
         ((float *) pImage)[i] = (float)
             (JDEMGetField( pszRecord + 9 + 5 * i, 5) * 0.1);
 
@@ -217,11 +209,9 @@ CPLErr JDEMRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /*                            JDEMDataset()                             */
 /************************************************************************/
 
-JDEMDataset::JDEMDataset() : fp(NULL)
-
-{
-    fp = NULL;
-}
+JDEMDataset::JDEMDataset() :
+    fp(NULL)
+{ }
 
 /************************************************************************/
 /*                           ~JDEMDataset()                             */
@@ -232,7 +222,7 @@ JDEMDataset::~JDEMDataset()
 {
     FlushCache();
     if( fp != NULL )
-        VSIFCloseL( fp );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
 }
 
 /************************************************************************/
@@ -242,22 +232,19 @@ JDEMDataset::~JDEMDataset()
 CPLErr JDEMDataset::GetGeoTransform( double * padfTransform )
 
 {
-    double	dfLLLat, dfLLLong, dfURLat, dfURLong;
+    const double dfLLLat = JDEMGetAngle( (char *) abyHeader + 29 );
+    const double dfLLLong = JDEMGetAngle( (char *) abyHeader + 36 );
+    const double dfURLat = JDEMGetAngle( (char *) abyHeader + 43 );
+    const double dfURLong = JDEMGetAngle( (char *) abyHeader + 50 );
 
-    dfLLLat = JDEMGetAngle( (char *) abyHeader + 29 );
-    dfLLLong = JDEMGetAngle( (char *) abyHeader + 36 );
-    dfURLat = JDEMGetAngle( (char *) abyHeader + 43 );
-    dfURLong = JDEMGetAngle( (char *) abyHeader + 50 );
-    
     padfTransform[0] = dfLLLong;
     padfTransform[3] = dfURLat;
     padfTransform[1] = (dfURLong - dfLLLong) / GetRasterXSize();
     padfTransform[2] = 0.0;
-        
+
     padfTransform[4] = 0.0;
     padfTransform[5] = -1 * (dfURLat - dfLLLat) / GetRasterYSize();
 
-
     return CE_None;
 }
 
@@ -286,12 +273,12 @@ int JDEMDataset::Identify( GDALOpenInfo * poOpenInfo )
         return FALSE;
 
     /* check if century values seem reasonable */
-    if( (!EQUALN((char *)poOpenInfo->pabyHeader+11,"19",2)
-          && !EQUALN((char *)poOpenInfo->pabyHeader+11,"20",2))
-        || (!EQUALN((char *)poOpenInfo->pabyHeader+15,"19",2)
-             && !EQUALN((char *)poOpenInfo->pabyHeader+15,"20",2))
-        || (!EQUALN((char *)poOpenInfo->pabyHeader+19,"19",2)
-             && !EQUALN((char *)poOpenInfo->pabyHeader+19,"20",2)) )
+    if( (!STARTS_WITH_CI((char *)poOpenInfo->pabyHeader+11, "19")
+          && !STARTS_WITH_CI((char *)poOpenInfo->pabyHeader+11, "20"))
+        || (!STARTS_WITH_CI((char *)poOpenInfo->pabyHeader+15, "19")
+             && !STARTS_WITH_CI((char *)poOpenInfo->pabyHeader+15, "20"))
+        || (!STARTS_WITH_CI((char *)poOpenInfo->pabyHeader+19, "19")
+             && !STARTS_WITH_CI((char *)poOpenInfo->pabyHeader+19, "20")) )
     {
         return FALSE;
     }
@@ -317,12 +304,12 @@ GDALDataset *JDEMDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The JDEM driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
     }
-    
+
     /* Check that the file pointer from GDALOpenInfo* is available */
     if( poOpenInfo->fpL == NULL )
     {
@@ -332,26 +319,24 @@ GDALDataset *JDEMDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    JDEMDataset 	*poDS;
-
-    poDS = new JDEMDataset();
+    JDEMDataset *poDS = new JDEMDataset();
 
     /* Borrow the file pointer from GDALOpenInfo* */
     poDS->fp = poOpenInfo->fpL;
     poOpenInfo->fpL = NULL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read the header.                                                */
 /* -------------------------------------------------------------------- */
-    VSIFReadL( poDS->abyHeader, 1, 1012, poDS->fp );
+    CPL_IGNORE_RET_VAL(VSIFReadL( poDS->abyHeader, 1, 1012, poDS->fp ));
 
     poDS->nRasterXSize = JDEMGetField( (char *) poDS->abyHeader + 23, 3 );
     poDS->nRasterYSize = JDEMGetField( (char *) poDS->abyHeader + 26, 3 );
     if  (poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Invalid dimensions : %d x %d", 
-                  poDS->nRasterXSize, poDS->nRasterYSize); 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Invalid dimensions : %d x %d",
+                  poDS->nRasterXSize, poDS->nRasterYSize);
         delete poDS;
         return NULL;
     }
@@ -376,30 +361,26 @@ GDALDataset *JDEMDataset::Open( GDALOpenInfo * poOpenInfo )
 }
 
 /************************************************************************/
-/*                          GDALRegister_JDEM()                          */
+/*                          GDALRegister_JDEM()                         */
 /************************************************************************/
 
 void GDALRegister_JDEM()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "JDEM" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "JDEM" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "JDEM" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Japanese DEM (.mem)" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#JDEM" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "mem" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = JDEMDataset::Open;
-        poDriver->pfnIdentify = JDEMDataset::Identify;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "JDEM" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Japanese DEM (.mem)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#JDEM" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "mem" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = JDEMDataset::Open;
+    poDriver->pfnIdentify = JDEMDataset::Identify;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/jdem/makefile.vc b/frmts/jdem/makefile.vc
index d4a2635..d9075b4 100644
--- a/frmts/jdem/makefile.vc
+++ b/frmts/jdem/makefile.vc
@@ -1,8 +1,6 @@
 
 OBJ	=	jdemdataset.obj
 
-EXTRAFLAGS = 	-I..\iso8211
-
 GDAL_ROOT	=	..\..
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
diff --git a/frmts/jp2kak/GNUmakefile b/frmts/jp2kak/GNUmakefile
index 5a3e7c0..94e610f 100644
--- a/frmts/jp2kak/GNUmakefile
+++ b/frmts/jp2kak/GNUmakefile
@@ -19,7 +19,7 @@ INSTOBJ = $(foreach d,$(APPOBJ),../o/$(notdir $(d)))
 
 #CXXFLAGS :=	$(CXXFLAGS) -DFILEIO_DEBUG
 
-CPPFLAGS	:=	 $(KAKINC) -I. $(CPPFLAGS)
+CPPFLAGS	:=	 $(KAKINC) -I. $(CPPFLAGS) -DKDU_X86_INTRINSICS
 
 default:	$(OBJ:.o=.$(OBJ_EXT))
 
diff --git a/frmts/jp2kak/frmt_jp2kak.html b/frmts/jp2kak/frmt_jp2kak.html
index 5c09aa3..44a46e6 100644
--- a/frmts/jp2kak/frmt_jp2kak.html
+++ b/frmts/jp2kak/frmt_jp2kak.html
@@ -7,16 +7,16 @@
 
 <h1>JP2KAK -- JPEG-2000 (based on Kakadu)</h1>
 
-Most forms of JPEG2000 JP2 and JPC compressed images (ISO/IEC 15444-1) can be 
+Most forms of JPEG2000 JP2 and JPC compressed images (ISO/IEC 15444-1) can be
 read with GDAL using a driver based on the Kakadu library.  As well, new images
 can be written.  Existing images cannot be updated in place.<p>
 
-The JPEG2000 file format supports lossy and lossless compression of 
-8bit and 16bit images with 1 or more bands (components).  Via the 
+The JPEG2000 file format supports lossy and lossless compression of
+8bit and 16bit images with 1 or more bands (components).  Via the
 <a href="http://www.mappingscience.com/msi.html">GeoJP2 (tm)</a> mechanism,
 GeoTIFF style coordinate system and georeferencing information can be embedded
 within the JP2 file.  JPEG2000 files use a substantially different format and
-compression mechanism than the traditional JPEG compression and JPEG JFIF 
+compression mechanism than the traditional JPEG compression and JPEG JFIF
 format.  They are distinct compression mechanisms produced by the same
 group.  JPEG2000 is based on wavelet compression.<p>
 
@@ -29,10 +29,10 @@ driver unless the builder purchases a license for the library and configures
 accordingly.  GDAL includes <a href="frmt_jpeg2000.html">another JPEG2000 driver</a>
 based on the free JasPer library.<p>
 
-When reading images this driver will represent the bands as being 
+When reading images this driver will represent the bands as being
 Byte (8bit unsigned), 16 bit signed or 16 bit unsigned.  Georeferencing
-and coordinate system information will be available if the file is a 
-GeoJP2 (tm) file.  Files color encoded in YCbCr color space will be 
+and coordinate system information will be available if the file is a
+GeoJP2 (tm) file.  Files color encoded in YCbCr color space will be
 automatically translated to RGB.  Paletted images are also supported.<P>
 
 Starting with GDAL 1.9.0, XMP metadata can be extracted from JPEG2000 files, and will be
@@ -40,13 +40,13 @@ stored as XML raw content in the xml:XMP metadata domain.<p>
 
 <h2>Configuration Options</h2>
 
-The JP2KAK driver supports the following 
+The JP2KAK driver supports the following
 <a href="http://trac.osgeo.org/gdal/ConfigOptions">Config Options</a>.
 These runtime options can be used to alter the behavior of the driver.
 
 <ul>
 <li> <b>JP2KAK_THREADS</b>=n: By default an effort is made to take advantage of
-multi-threading on multi-core computers using default rules from the Kakadu 
+multi-threading on multi-core computers using default rules from the Kakadu
 library.  This option may be set to a value of zero to avoid using additional
 threads or to a specific count to create the requested number of worker threads.<p>
 
@@ -54,8 +54,8 @@ threads or to a specific count to create the requested number of worker threads.
 of problems with the JPEG2000 data stream.  Defaults to NO.<p>
 
 <li> <b>JP2KAK_RESILIENT</b>=YES/NO: This can be set to YES to force Kakadu to
-maximimize resilience with incorrectly created JPEG2000 data files, likely at
-some cost in performance.  This is likely to be necessary if, amoung other reasons,
+maximize resilience with incorrectly created JPEG2000 data files, likely at
+some cost in performance.  This is likely to be necessary if, among other reasons,
 you get an error message about "Expected to find EPH marker following packet header"
 or error reports indicating the need to run with the resilient and sequential flags
 on.  Defaults to NO.<p>
@@ -79,7 +79,7 @@ copy from an existing dataset.<p>
 
 JPEG2000 overviews are maintained as part of the mathematical description of
 the image.  Overviews cannot be built as a separate process, but on read the
-image will generally be represented as having overview levels at various 
+image will generally be represented as having overview levels at various
 power of two factors.<p>
 
 Creation Options:<p>
@@ -88,7 +88,7 @@ Creation Options:<p>
 
 <li> <b>QUALITY=n</b>: Set the compressed size ratio as a percentage
 of the size of the uncompressed image.  The default is 20 indicating that
-the resulting image should be 20% of the size of the uncompressed image. 
+the resulting image should be 20% of the size of the uncompressed image.
 Actual final image size may not exactly match that requested depending on
 various factors. A value of 100 will result in use of the lossless compression
 algorithm . On typical image data, if you specify a value greater than 65, it
@@ -121,13 +121,13 @@ If filename is just set to YES, a minimal instance will be built.<p>
 
 <li> <b>GeoJP2=YES/NO</b>: Indicates whether a UUID/GeoTIFF box conforming to the GeoJP2 (GeoTIFF in JPEG2000) specification should be included in the file.  Defaults to YES.<p>
 
-<li> <b>LAYERS=n</b>: Control the number of layers produced.  These are 
+<li> <b>LAYERS=n</b>: Control the number of layers produced.  These are
 sort of like resolution layers, but not exactly.  The default value is
 12 and this works well in most situations.<p>
 
 <li> <b>ROI=xoff,yoff,xsize,ysize</b>: Selects a region to be a region of
 interest to process with higher data quality.  The various "R" flags below may
-be used to control the amount better.  For example the settings 
+be used to control the amount better.  For example the settings
 "ROI=0,0,100,100", "Rweight=7" would encode the top left 100x100 area of
 the image with considerable higher quality compared to the rest of the image.
 <p>
@@ -139,9 +139,9 @@ are considered to be for advanced use only.  Consult Kakadu documentation
 to better understand their meaning.<p>
 
 <ul>
-<li> <b>Corder</b>: Defaults to "PRCL". 
+<li> <b>Corder</b>: Defaults to "PRCL".
 <li> <b>Cprecincts</b>: Defaults to "{512,512},{256,512},{128,512},{64,512},{32,512},{16,512},{8,512},{4,512},{2,512}".
-<li> <b>ORGgen_plt</b>: Defaults to "yes". 
+<li> <b>ORGgen_plt</b>: Defaults to "yes".
 <li> <b>Cmodes</b>: Kakadu library default used.
 <li> <b>Clevels</b>: Kakadu library default used.
 <li> <b>Rshift</b>: Kakadu library default used.
diff --git a/frmts/jp2kak/jp2kak.lst b/frmts/jp2kak/jp2kak.lst
index 55f334e..8d1f784 100644
--- a/frmts/jp2kak/jp2kak.lst
+++ b/frmts/jp2kak/jp2kak.lst
@@ -26,3 +26,10 @@ KAK_OBJ +=	\
     $(KAKDIR)/apps/make/ssse3_region_decompressor.o \
     $(KAKDIR)/apps/make/avx2_stripe_transfer.o
 endif
+
+# The following are for Kakadu 7.7 and later
+# for kdu_supp::kdu_window::add_metareq(unsigned int, int, bool, int, bool, long long, int)
+ifneq ($(wildcard $(KAKDIR)/apps/make/kdu_client_windo?.o),)
+KAK_OBJ +=      \
+    $(KAKDIR)/apps/make/kdu_client_window.o
+endif
diff --git a/frmts/jp2kak/jp2kak_headers.h b/frmts/jp2kak/jp2kak_headers.h
new file mode 100644
index 0000000..ca698e3
--- /dev/null
+++ b/frmts/jp2kak/jp2kak_headers.h
@@ -0,0 +1,68 @@
+/******************************************************************************
+ *
+ * Project:  GDAL
+ * Purpose:  Includes JP2KAK SDK headers
+ * Author:   Even Rouault <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+#ifndef JP2KAK_HEADERS_H
+#define JP2KAK_HEADERS_H
+
+#include "cpl_port.h"
+
+#ifdef HAVE_GCC_SYSTEM_HEADER
+#pragma GCC system_header
+#endif
+
+#include "jp2_local.h"
+
+// Kakadu core includes
+#include "kdu_elementary.h"
+#include "kdu_messaging.h"
+#include "kdu_params.h"
+#include "kdu_compressed.h"
+#include "kdu_sample_processing.h"
+#include "kdu_stripe_decompressor.h"
+#include "kdu_arch.h"
+
+// Application level includes
+#include "kdu_file_io.h"
+#include "jp2.h"
+
+// ROI related.
+#include "kdu_roi_processing.h"
+#include "kdu_image.h"
+#include "roi_sources.h"
+
+// I don't think JPIP support currently works due to changes in
+// classes like kdu_window ... some fixing required if someone wants it.
+// #define USE_JPIP
+
+#ifdef USE_JPIP
+#  include "kdu_client.h"
+#else
+#  define kdu_client void
+#endif
+
+#endif
diff --git a/frmts/jp2kak/jp2kakdataset.cpp b/frmts/jp2kak/jp2kakdataset.cpp
index b09d45e..6e570fc 100644
--- a/frmts/jp2kak/jp2kakdataset.cpp
+++ b/frmts/jp2kak/jp2kakdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: jp2kakdataset.cpp 29496 2015-07-07 22:29:46Z rouault $
+ * $Id: jp2kakdataset.cpp 33812 2016-03-29 23:14:24Z goatbar $
  *
  * Project:  JPEG-2000
  * Purpose:  Implementation of the ISO/IEC 15444-1 standard based on Kakadu.
@@ -28,46 +28,24 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#ifdef DEBUG_BOOL
+#define DO_NOT_USE_DEBUG_BOOL
+#endif
+
+#include "cpl_multiproc.h"
+#include "cpl_string.h"
+#include "gdal_frmts.h"
 #include "gdaljp2abstractdataset.h"
 #include "gdaljp2metadata.h"
-#include "cpl_string.h"
-#include "cpl_multiproc.h"
-#include "jp2_local.h"
 
 #include "../mem/memdataset.h"
 
-// Kakadu core includes
-#include "kdu_elementary.h"
-#include "kdu_messaging.h"
-#include "kdu_params.h"
-#include "kdu_compressed.h"
-#include "kdu_sample_processing.h"
-#include "kdu_stripe_decompressor.h"
-#include "kdu_arch.h"
+#include "jp2kak_headers.h"
 
 #include "subfile_source.h"
 #include "vsil_target.h"
 
-// Application level includes
-#include "kdu_file_io.h"
-#include "jp2.h"
-
-// ROI related.
-#include "kdu_roi_processing.h"
-#include "kdu_image.h"
-#include "roi_sources.h"
-
-// I don't think JPIP support currently works due to changes in 
-// classes like kdu_window ... some fixing required if someone wants it.
-// #define USE_JPIP
-
-#ifdef USE_JPIP
-#  include "kdu_client.h" 
-#else
-#  define kdu_client void
-#endif
-
-CPL_CVSID("$Id: jp2kakdataset.cpp 29496 2015-07-07 22:29:46Z rouault $");
+CPL_CVSID("$Id: jp2kakdataset.cpp 33812 2016-03-29 23:14:24Z goatbar $");
 
 // Before v7.5 Kakadu does not advertise its version well
 // After v7.5 Kakadu has KDU_{MAJOR,MINOR,PATCH}_VERSION defines so it's easier
@@ -81,15 +59,14 @@ CPL_CVSID("$Id: jp2kakdataset.cpp 29496 2015-07-07 22:29:46Z rouault $");
     using namespace kdu_supp;
 #endif
 
-// #define KAKADU_JPX	1
+// #define KAKADU_JPX 1
 
-static int kakadu_initialized = FALSE;
+static bool kakadu_initialized = false;
 
-static unsigned char jp2_header[] = 
-{0x00,0x00,0x00,0x0c,0x6a,0x50,0x20,0x20,0x0d,0x0a,0x87,0x0a};
+static const unsigned char jp2_header[] =
+    {0x00,0x00,0x00,0x0c,0x6a,0x50,0x20,0x20,0x0d,0x0a,0x87,0x0a};
 
-static unsigned char jpc_header[] = 
-{0xff,0x4f};
+static const unsigned char jpc_header[] = {0xff,0x4f};
 
 /* -------------------------------------------------------------------- */
 /*      The number of tiles at a time we will push through the          */
@@ -99,7 +76,7 @@ static unsigned char jpc_header[] =
 
 /************************************************************************/
 /* ==================================================================== */
-/*				JP2KAKDataset				*/
+/*                            JP2KAKDataset                             */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -112,7 +89,7 @@ class JP2KAKDataset : public GDALJP2AbstractDataset
     kdu_compressed_source *poRawInput;
     jp2_family_src  *family;
     kdu_client      *jpip_client;
-    kdu_dims dims; 
+    kdu_dims dims;
     int            nResCount;
     bool           bPreferNPReads;
     kdu_thread_env *poThreadEnv;
@@ -121,7 +98,7 @@ class JP2KAKDataset : public GDALJP2AbstractDataset
     int            bResilient;
     int            bFussy;
     bool           bUseYCC;
-    
+
     bool           bPromoteTo8Bit;
 
     int         TestUseBlockIO( int, int, int, int, int, int,
@@ -143,8 +120,8 @@ class JP2KAKDataset : public GDALJP2AbstractDataset
 
   public:
                 JP2KAKDataset();
-		~JP2KAKDataset();
-    
+    virtual ~JP2KAKDataset();
+
     virtual CPLErr IBuildOverviews( const char *, int, int *,
                                     int, int *, GDALProgressFunc, void * );
 
@@ -165,11 +142,11 @@ class JP2KAKRasterBand : public GDALPamRasterBand
 
     JP2KAKDataset *poBaseDS;
 
-    int         nDiscardLevels; 
+    int         nDiscardLevels;
 
-    kdu_dims 	band_dims; 
+    kdu_dims    band_dims;
 
-    int		nOverviewCount;
+    int         nOverviewCount;
     JP2KAKRasterBand **papoOverviewBand;
 
     kdu_client      *jpip_client;
@@ -179,7 +156,7 @@ class JP2KAKRasterBand : public GDALPamRasterBand
     GDALColorTable oCT;
 
     int         bYCbCrReported;
-    
+
     GDALColorInterp eInterp;
 
     virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
@@ -187,15 +164,15 @@ class JP2KAKRasterBand : public GDALPamRasterBand
                               GSpacing nPixelSpace, GSpacing nLineSpace,
                               GDALRasterIOExtraArg* psExtraArg);
 
-    int            HasExternalOverviews() 
+    int            HasExternalOverviews()
                    { return GDALPamRasterBand::GetOverviewCount() != 0; }
 
   public:
 
-    		JP2KAKRasterBand( int, int, kdu_codestream, int, kdu_client *,
+                JP2KAKRasterBand( int, int, kdu_codestream, int, kdu_client *,
                                   jp2_channels, JP2KAKDataset * );
-    		~JP2KAKRasterBand();
-    
+    virtual ~JP2KAKRasterBand();
+
     virtual CPLErr IReadBlock( int, int, void * );
 
     virtual int    GetOverviewCount();
@@ -207,9 +184,9 @@ class JP2KAKRasterBand : public GDALPamRasterBand
     // internal
 
     void        ApplyPalette( jp2_palette oJP2Palette );
-    void        ProcessYCbCrTile(kdu_tile tile, GByte *pabyBuffer, 
-                                 int nBlockXOff, int nBlockYOff,
-                                 int nTileOffsetX, int nTileOffsetY );
+    void        ProcessYCbCrTile( kdu_tile tile, GByte *pabyBuffer,
+                                  int nBlockXOff, int nBlockYOff,
+                                  int nTileOffsetX, int nTileOffsetY );
     void        ProcessTile(kdu_tile tile, GByte *pabyBuffer );
 };
 
@@ -219,10 +196,12 @@ class JP2KAKRasterBand : public GDALPamRasterBand
 /* ==================================================================== */
 /************************************************************************/
 
-class kdu_cpl_error_message : public kdu_thread_safe_message 
+class kdu_cpl_error_message : public kdu_thread_safe_message
 {
 public: // Member classes
-    kdu_cpl_error_message( CPLErr eErrClass ) 
+    using kdu_thread_safe_message::put_text;
+
+    kdu_cpl_error_message( CPLErr eErrClass )
     {
         m_eErrClass = eErrClass;
         m_pszError = NULL;
@@ -234,17 +213,15 @@ public: // Member classes
             m_pszError = CPLStrdup( string );
         else
         {
-            m_pszError = (char *) 
+            m_pszError = (char *)
                 CPLRealloc(m_pszError, strlen(m_pszError) + strlen(string)+1 );
             strcat( m_pszError, string );
         }
     }
 
-    class JP2KAKException
-    {
-    };
+    class JP2KAKException {};
 
-    void flush(bool end_of_message=false) 
+    void flush(bool end_of_message=false)
     {
         kdu_thread_safe_message::flush(end_of_message);
 
@@ -278,47 +255,45 @@ private:
 /*                           JP2KAKRasterBand()                         */
 /************************************************************************/
 
-JP2KAKRasterBand::JP2KAKRasterBand( int nBand, int nDiscardLevels,
-                                    kdu_codestream oCodeStream,
-                                    int nResCount, kdu_client *jpip_client,
+JP2KAKRasterBand::JP2KAKRasterBand( int nBandIn, int nDiscardLevelsIn,
+                                    kdu_codestream oCodeStreamIn,
+                                    int nResCount, kdu_client *jpip_clientIn,
                                     jp2_channels oJP2Channels,
-                                    JP2KAKDataset *poBaseDSIn )
-
+                                    JP2KAKDataset *poBaseDSIn ) :
+    poBaseDS(poBaseDSIn),
+    nDiscardLevels(nDiscardLevelsIn),
+    jpip_client(jpip_clientIn),
+    oCodeStream(oCodeStreamIn),
+    bYCbCrReported(FALSE)
 {
-    this->nBand = nBand;
-    this->poBaseDS = poBaseDSIn;
-
-    bYCbCrReported = FALSE;
+    nBand = nBandIn;  // From GDALRasterBand.
 
     if( oCodeStream.get_bit_depth(nBand-1) > 8
         && oCodeStream.get_bit_depth(nBand-1) <= 16
         && oCodeStream.get_signed(nBand-1) )
-        this->eDataType = GDT_Int16;
+        eDataType = GDT_Int16;
     else if( oCodeStream.get_bit_depth(nBand-1) > 8
              && oCodeStream.get_bit_depth(nBand-1) <= 16
              && !oCodeStream.get_signed(nBand-1) )
-        this->eDataType = GDT_UInt16;
+        eDataType = GDT_UInt16;
     else
-        this->eDataType = GDT_Byte;
-
-    this->nDiscardLevels = nDiscardLevels;
-    this->oCodeStream = oCodeStream;
-
-    this->jpip_client = jpip_client;
+        eDataType = GDT_Byte;
 
     oCodeStream.apply_input_restrictions( 0, 0, nDiscardLevels, 0, NULL );
     oCodeStream.get_dims( 0, band_dims );
 
-    this->nRasterXSize = band_dims.size.x;
-    this->nRasterYSize = band_dims.size.y;
+    nRasterXSize = band_dims.size.x;
+    nRasterYSize = band_dims.size.y;
 
 /* -------------------------------------------------------------------- */
 /*      Capture some useful metadata.                                   */
 /* -------------------------------------------------------------------- */
-    if( oCodeStream.get_bit_depth(nBand-1) % 8 != 0 && !poBaseDSIn->bPromoteTo8Bit )
+    if( oCodeStream.get_bit_depth(nBand-1) % 8 != 0 &&
+        !poBaseDSIn->bPromoteTo8Bit )
     {
-        SetMetadataItem( "NBITS", 
-                         CPLString().Printf("%d",oCodeStream.get_bit_depth(nBand-1)), 
+        SetMetadataItem( "NBITS",
+                         CPLString().Printf(
+                             "%d",oCodeStream.get_bit_depth(nBand-1)),
                          "IMAGE_STRUCTURE" );
     }
     SetMetadataItem( "COMPRESSION", "JP2000", "IMAGE_STRUCTURE" );
@@ -330,7 +305,7 @@ JP2KAKRasterBand::JP2KAKRasterBand( int nBand, int nDiscardLevels,
         nBlockXSize = 2048;
     else
         nBlockXSize = nRasterXSize;
-    
+
     if( nRasterYSize >= 256 )
         nBlockYSize = 128;
     else
@@ -339,13 +314,16 @@ JP2KAKRasterBand::JP2KAKRasterBand( int nBand, int nDiscardLevels,
 /* -------------------------------------------------------------------- */
 /*      Figure out the color interpretation for this band.              */
 /* -------------------------------------------------------------------- */
-    
+
     eInterp = GCI_Undefined;
 
     if( oJP2Channels.exists() )
     {
-        int nRedIndex=-1, nGreenIndex=-1, nBlueIndex=-1, nLutIndex;
-        int nCSI;
+        int nRedIndex = -1;
+        int nGreenIndex = -1;
+        int nBlueIndex = -1;
+        int nLutIndex = 0;
+        int nCSI = 0;
 
         if( oJP2Channels.get_num_colours() == 3 )
         {
@@ -367,7 +345,7 @@ JP2KAKRasterBand::JP2KAKRasterBand( int nBand, int nDiscardLevels,
         else if( nLutIndex != -1 )
             eInterp = GCI_PaletteIndex;
 
-        // Establish color band this is. 
+        // Establish color band this is.
         else if( nRedIndex == nBand-1 )
             eInterp = GCI_RedBand;
         else if( nGreenIndex == nBand-1 )
@@ -380,11 +358,13 @@ JP2KAKRasterBand::JP2KAKRasterBand( int nBand, int nDiscardLevels,
         // Could this band be an alpha band?
         if( eInterp == GCI_Undefined )
         {
-            int color_idx, opacity_idx, lut_idx;
-
-            for( color_idx = 0; 
+            for( int color_idx = 0;
                  color_idx < oJP2Channels.get_num_colours(); color_idx++ )
             {
+                int opacity_idx = 0;
+                int lut_idx = 0;
+
+                // get_opacity_mapping sets that last 3 args by non-const refs.
                 if( oJP2Channels.get_opacity_mapping( color_idx, opacity_idx,
                                                       lut_idx, nCSI ) )
                 {
@@ -408,7 +388,7 @@ JP2KAKRasterBand::JP2KAKRasterBand( int nBand, int nDiscardLevels,
         eInterp = GCI_BlueBand;
     else
         eInterp = GCI_GrayIndex;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Do we have any overviews?  Only check if we are the full res    */
 /*      image.                                                          */
@@ -417,12 +397,11 @@ JP2KAKRasterBand::JP2KAKRasterBand( int nBand, int nDiscardLevels,
     papoOverviewBand = 0;
     if( nDiscardLevels == 0 && GDALPamRasterBand::GetOverviewCount() == 0 )
     {
-        int  nXSize = nRasterXSize, nYSize = nRasterYSize;
+        int nXSize = nRasterXSize;
+        int nYSize = nRasterYSize;
 
         for( int nDiscard = 1; nDiscard < nResCount; nDiscard++ )
         {
-            kdu_dims  dims;
-
             nXSize = (nXSize+1) / 2;
             nYSize = (nYSize+1) / 2;
 
@@ -430,16 +409,17 @@ JP2KAKRasterBand::JP2KAKRasterBand( int nBand, int nDiscardLevels,
                 continue; /* skip super reduced resolution layers */
 
             oCodeStream.apply_input_restrictions( 0, 0, nDiscard, 0, NULL );
+            kdu_dims dims;  // struct with default constructor.
             oCodeStream.get_dims( 0, dims );
 
             if( (dims.size.x == nXSize || dims.size.x == nXSize-1)
                 && (dims.size.y == nYSize || dims.size.y == nYSize-1) )
             {
                 nOverviewCount++;
-                papoOverviewBand = (JP2KAKRasterBand **) 
-                    CPLRealloc( papoOverviewBand, 
-                                sizeof(void*) * nOverviewCount );
-                papoOverviewBand[nOverviewCount-1] = 
+                papoOverviewBand = static_cast<JP2KAKRasterBand **>(
+                    CPLRealloc( papoOverviewBand,
+                                sizeof(void*) * nOverviewCount ) );
+                papoOverviewBand[nOverviewCount-1] =
                     new JP2KAKRasterBand( nBand, nDiscard, oCodeStream, 0,
                                           jpip_client, oJP2Channels,
                                           poBaseDS );
@@ -447,7 +427,7 @@ JP2KAKRasterBand::JP2KAKRasterBand( int nBand, int nDiscardLevels,
             else
             {
                 CPLDebug( "GDAL", "Discard %dx%d JPEG2000 overview layer,\n"
-                          "expected %dx%d.", 
+                          "expected %dx%d.",
                           dims.size.x, dims.size.y, nXSize, nYSize );
             }
         }
@@ -476,8 +456,8 @@ int JP2KAKRasterBand::GetOverviewCount()
 {
     if( GDALPamRasterBand::GetOverviewCount() > 0 )
         return GDALPamRasterBand::GetOverviewCount();
-    else
-        return nOverviewCount;
+
+    return nOverviewCount;
 }
 
 /************************************************************************/
@@ -490,10 +470,10 @@ GDALRasterBand *JP2KAKRasterBand::GetOverview( int iOverviewIndex )
     if( GDALPamRasterBand::GetOverviewCount() > 0 )
         return GDALPamRasterBand::GetOverview( iOverviewIndex );
 
-    else if( iOverviewIndex < 0 || iOverviewIndex >= nOverviewCount )
+    if( iOverviewIndex < 0 || iOverviewIndex >= nOverviewCount )
         return NULL;
-    else
-        return papoOverviewBand[iOverviewIndex];
+
+    return papoOverviewBand[iOverviewIndex];
 }
 
 /************************************************************************/
@@ -501,28 +481,27 @@ GDALRasterBand *JP2KAKRasterBand::GetOverview( int iOverviewIndex )
 /************************************************************************/
 
 CPLErr JP2KAKRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
-                                      void * pImage )
+                                     void * pImage )
 {
-    int  nWordSize = GDALGetDataTypeSize( eDataType ) / 8;
-    int nOvMult = 1, nLevelsLeft = nDiscardLevels;
+    const int nWordSize = GDALGetDataTypeSizeBytes( eDataType );
+    int nOvMult = 1;
+    int nLevelsLeft = nDiscardLevels;
     while( nLevelsLeft-- > 0 )
         nOvMult *= 2;
 
-    CPLDebug( "JP2KAK", "IReadBlock(%d,%d) on band %d.", 
+    CPLDebug( "JP2KAK", "IReadBlock(%d,%d) on band %d.",
               nBlockXOff, nBlockYOff, nBand );
 
 /* -------------------------------------------------------------------- */
 /*      Compute the normal window, and buffer size.                     */
 /* -------------------------------------------------------------------- */
-    int  nWXOff, nWYOff, nWXSize, nWYSize, nXSize, nYSize;
+    int nWXOff = nBlockXOff * nBlockXSize * nOvMult;
+    int nWYOff = nBlockYOff * nBlockYSize * nOvMult;
+    int nWXSize = nBlockXSize * nOvMult;
+    int nWYSize = nBlockYSize * nOvMult;
 
-    nWXOff = nBlockXOff * nBlockXSize * nOvMult;
-    nWYOff = nBlockYOff * nBlockYSize * nOvMult;
-    nWXSize = nBlockXSize * nOvMult;
-    nWYSize = nBlockYSize * nOvMult;
-
-    nXSize = nBlockXSize;
-    nYSize = nBlockYSize;
+    int nXSize = nBlockXSize;
+    int nYSize = nBlockYSize;
 
 /* -------------------------------------------------------------------- */
 /*      Adjust if we have a partial block on the right or bottom of     */
@@ -555,11 +534,12 @@ CPLErr JP2KAKRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
     if( !poBaseDS->bUseYCC )
     {
-        return poBaseDS->DirectRasterIO( GF_Read, 
+        return poBaseDS->DirectRasterIO( GF_Read,
                                          nWXOff, nWYOff, nWXSize, nWYSize,
                                          pImage, nXSize, nYSize,
-                                         eDataType, 1, &nBand, 
-                                         nWordSize, nWordSize*nBlockXSize, 0, &sExtraArg );
+                                         eDataType, 1, &nBand,
+                                         nWordSize, nWordSize*nBlockXSize,
+                                         0, &sExtraArg );
     }
 
 /* -------------------------------------------------------------------- */
@@ -569,9 +549,8 @@ CPLErr JP2KAKRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
     CPLErr eErr = CE_None;
     std::vector<int> anBands;
-    int iBand;
 
-    for( iBand = 0; iBand < poBaseDS->GetRasterCount(); iBand++ )
+    for( int iBand = 0; iBand < poBaseDS->GetRasterCount(); iBand++ )
     {
         GDALRasterBand* poBand = poBaseDS->GetRasterBand(iBand+1);
         if ( poBand->GetRasterDataType() != eDataType )
@@ -579,34 +558,37 @@ CPLErr JP2KAKRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         anBands.push_back(iBand+1);
     }
 
-    GByte *pabyWrkBuffer = (GByte *) 
-        VSIMalloc3( nWordSize * anBands.size(), nBlockXSize, nBlockYSize );
+    GByte *pabyWrkBuffer = static_cast<GByte *>(
+        VSIMalloc3( nWordSize * anBands.size(), nBlockXSize, nBlockYSize ) );
     if( pabyWrkBuffer == NULL )
         return CE_Failure;
 
-    eErr = poBaseDS->DirectRasterIO( GF_Read, 
+    eErr = poBaseDS->DirectRasterIO( GF_Read,
                                      nWXOff, nWYOff, nWXSize, nWYSize,
                                      pabyWrkBuffer, nXSize, nYSize,
-                                     eDataType, anBands.size(), &anBands[0],
-                                     nWordSize, nWordSize*nBlockXSize, 
+                                     eDataType,
+                                     static_cast<int>(anBands.size()),
+                                     &anBands[0],
+                                     nWordSize, nWordSize*nBlockXSize,
                                      nWordSize*nBlockXSize*nBlockYSize,
                                      &sExtraArg );
 
     if( eErr == CE_None )
     {
         int nBandStart = 0;
-        for( iBand = 0; iBand < (int) anBands.size(); iBand++ )
+        const int nTotalBands = static_cast<int>(anBands.size());
+        for( int iBand = 0; iBand < nTotalBands; iBand++ )
         {
             if( anBands[iBand] == nBand )
             {
-                // application requested band.
-                memcpy( pImage, pabyWrkBuffer + nBandStart, 
+                // Application requested band.
+                memcpy( pImage, pabyWrkBuffer + nBandStart,
                         nWordSize * nBlockXSize * nBlockYSize );
             }
             else
             {
                 // all others are pushed into cache.
-                GDALRasterBand *poBaseBand = 
+                GDALRasterBand *poBaseBand =
                     poBaseDS->GetRasterBand(anBands[iBand]);
                 JP2KAKRasterBand *poBand = NULL;
 
@@ -614,12 +596,15 @@ CPLErr JP2KAKRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                     poBand = (JP2KAKRasterBand *) poBaseBand;
                 else
                 {
-                    int iOver;
+                    int iOver = 0;  // Used after for.
 
-                    for( iOver = 0; iOver < poBaseBand->GetOverviewCount(); iOver++ )
+                    for( ; iOver < poBaseBand->GetOverviewCount(); iOver++ )
                     {
-                        poBand = (JP2KAKRasterBand *) 
-                            poBaseBand->GetOverview( iOver );
+                        poBand = dynamic_cast<JP2KAKRasterBand *>(
+                            poBaseBand->GetOverview( iOver ) );
+                        if( poBand == NULL )
+                            CPLError( CE_Fatal, CPLE_AppDefined,
+                                      "Dynamic cast failed" );
                         if( poBand->nDiscardLevels == nDiscardLevels )
                             break;
                     }
@@ -632,16 +617,17 @@ CPLErr JP2KAKRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                 GDALRasterBlock *poBlock = NULL;
 
                 if( poBand != NULL )
-                    poBlock = poBand->GetLockedBlockRef( nBlockXOff, nBlockYOff, TRUE );
+                    poBlock = poBand->GetLockedBlockRef(
+                        nBlockXOff, nBlockYOff, TRUE );
 
                 if( poBlock )
                 {
-                    memcpy( poBlock->GetDataRef(), pabyWrkBuffer + nBandStart, 
+                    memcpy( poBlock->GetDataRef(), pabyWrkBuffer + nBandStart,
                             nWordSize * nBlockXSize * nBlockYSize );
                     poBlock->DropLock();
                 }
             }
-            
+
             nBandStart += nWordSize * nBlockXSize * nBlockYSize;
         }
     }
@@ -654,11 +640,11 @@ CPLErr JP2KAKRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /*                             IRasterIO()                              */
 /************************************************************************/
 
-CPLErr 
+CPLErr
 JP2KAKRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                              int nXOff, int nYOff, int nXSize, int nYSize,
                              void * pData, int nBufXSize, int nBufYSize,
-                             GDALDataType eBufType, 
+                             GDALDataType eBufType,
                              GSpacing nPixelSpace, GSpacing nLineSpace,
                              GDALRasterIOExtraArg* psExtraArg)
 
@@ -666,12 +652,12 @@ JP2KAKRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 /* -------------------------------------------------------------------- */
 /*      We need various criteria to skip out to block based methods.    */
 /* -------------------------------------------------------------------- */
-    if( poBaseDS->TestUseBlockIO( nXOff, nYOff, nXSize, nYSize, 
+    if( poBaseDS->TestUseBlockIO( nXOff, nYOff, nXSize, nYSize,
                                   nBufXSize, nBufYSize,
                                   eBufType, 1, &nBand ) )
-        return GDALPamRasterBand::IRasterIO( 
+        return GDALPamRasterBand::IRasterIO(
             eRWFlag, nXOff, nYOff, nXSize, nYSize,
-            pData, nBufXSize, nBufYSize, eBufType, 
+            pData, nBufXSize, nBufYSize, eBufType,
             nPixelSpace, nLineSpace, psExtraArg );
     else
     {
@@ -680,16 +666,16 @@ JP2KAKRasterBand::IRasterIO( GDALRWFlag eRWFlag,
         // Adjust request for overview level.
         while( nOverviewDiscard > 0 )
         {
-            nXOff  = nXOff * 2;
-            nYOff  = nYOff * 2;
-            nXSize = nXSize * 2;
-            nYSize = nYSize * 2;
+            nXOff *= 2;
+            nYOff *= 2;
+            nXSize *= 2;
+            nYSize *= 2;
             nOverviewDiscard--;
         }
 
-        return poBaseDS->DirectRasterIO( 
+        return poBaseDS->DirectRasterIO(
             eRWFlag, nXOff, nYOff, nXSize, nYSize,
-            pData, nBufXSize, nBufYSize, eBufType, 
+            pData, nBufXSize, nBufYSize, eBufType,
             1, &nBand, nPixelSpace, nLineSpace, 0, psExtraArg );
     }
 }
@@ -713,7 +699,7 @@ void JP2KAKRasterBand::ApplyPalette( jp2_palette oJP2Palette )
     if( oJP2Palette.get_num_luts() < 3 )
     {
         CPLDebug( "JP2KAK", "JP2KAKRasterBand::ApplyPalette()\n"
-                  "Odd get_num_luts() value (%d)", 
+                  "Odd get_num_luts() value (%d)",
                   oJP2Palette.get_num_luts() );
         return;
     }
@@ -722,38 +708,46 @@ void JP2KAKRasterBand::ApplyPalette( jp2_palette oJP2Palette )
 /*      Fetch the lut entries.  Note that they are normalized in the    */
 /*      -0.5 to 0.5 range.                                              */
 /* -------------------------------------------------------------------- */
-    float *pafLUT;
-    int   iColor, nCount = oJP2Palette.get_num_entries();
+    const int nCount = oJP2Palette.get_num_entries();
 
-    pafLUT = (float *) CPLCalloc(sizeof(float)*4, nCount);
+    float * const pafLUT =
+        static_cast<float *>( CPLCalloc(sizeof(float)*4, nCount) );
 
-    oJP2Palette.get_lut(0, pafLUT + 0);
-    oJP2Palette.get_lut(1, pafLUT + nCount);
-    oJP2Palette.get_lut(2, pafLUT + nCount*2);
+    const int nRed = 0;  // TODO(schwehr): Verify these constants are correct.
+    const int nGreen = 1;
+    const int nBlue = 2;
+    const int nAlpha = 3;
+    oJP2Palette.get_lut(nRed, pafLUT + 0);
+    oJP2Palette.get_lut(nGreen, pafLUT + nCount);
+    oJP2Palette.get_lut(nBlue, pafLUT + nCount*2);
 
     if( oJP2Palette.get_num_luts() == 4 )
     {
-        oJP2Palette.get_lut( 3, pafLUT + nCount*3 );
+        oJP2Palette.get_lut( nAlpha, pafLUT + nCount * 3 );
     }
     else
     {
-        for( iColor = 0; iColor < nCount; iColor++ )
+        for( int iColor = 0; iColor < nCount; iColor++ )
         {
-            pafLUT[nCount*3 + iColor] = 0.5;
+            pafLUT[nCount * 3 + iColor] = 0.5;
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Apply to GDAL colortable.                                       */
 /* -------------------------------------------------------------------- */
-    for( iColor=0; iColor < nCount; iColor++ )
+    for( int iColor=0; iColor < nCount; iColor++ )
     {
-        GDALColorEntry sEntry;
-
-        sEntry.c1 = (short) MAX(0,MIN(255,pafLUT[iColor + nCount*0]*256+128));
-        sEntry.c2 = (short) MAX(0,MIN(255,pafLUT[iColor + nCount*1]*256+128));
-        sEntry.c3 = (short) MAX(0,MIN(255,pafLUT[iColor + nCount*2]*256+128));
-        sEntry.c4 = (short) MAX(0,MIN(255,pafLUT[iColor + nCount*3]*256+128));
+        GDALColorEntry sEntry = {
+            static_cast<short>(
+                MAX(0,MIN(255,pafLUT[iColor + nCount*0]*256+128))),
+            static_cast<short>(
+                MAX(0,MIN(255,pafLUT[iColor + nCount*1]*256+128))),
+            static_cast<short>(
+                MAX(0,MIN(255,pafLUT[iColor + nCount*2]*256+128))),
+            static_cast<short>(
+                MAX(0,MIN(255,pafLUT[iColor + nCount*3]*256+128)))
+        };
 
         oCT.SetColorEntry( iColor, &sEntry );
     }
@@ -782,13 +776,13 @@ GDALColorTable *JP2KAKRasterBand::GetColorTable()
 {
     if( oCT.GetColorEntryCount() > 0 )
         return &oCT;
-    else
-        return NULL;
+
+    return NULL;
 }
 
 /************************************************************************/
 /* ==================================================================== */
-/*				JP2KAKDataset				*/
+/*                           JP2KAKDataset                              */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -796,20 +790,17 @@ GDALColorTable *JP2KAKRasterBand::GetColorTable()
 /*                           JP2KAKDataset()                           */
 /************************************************************************/
 
-JP2KAKDataset::JP2KAKDataset()
-
+JP2KAKDataset::JP2KAKDataset() :
+    poInput(NULL),
+    poRawInput(NULL),
+    family(NULL),
+    jpip_client(NULL),
+    bPreferNPReads(false),
+    poThreadEnv(NULL),
+    bCached(FALSE),  // TODO: bool.
+    bPromoteTo8Bit(false)
 {
-    poInput = NULL;
-    poRawInput = NULL;
-    family = NULL;
-    jpip_client = NULL;
-    poThreadEnv = NULL;
-
-    bCached = 0;
-    bPreferNPReads = false;
-    bPromoteTo8Bit = false;
-
-    poDriver = (GDALDriver*) GDALGetDriverByName( "JP2KAK" );
+    poDriver = static_cast<GDALDriver *>( GDALGetDriverByName( "JP2KAK" ) );
 }
 
 /************************************************************************/
@@ -854,10 +845,10 @@ JP2KAKDataset::~JP2KAKDataset()
 /*                          IBuildOverviews()                           */
 /************************************************************************/
 
-CPLErr JP2KAKDataset::IBuildOverviews( const char *pszResampling, 
+CPLErr JP2KAKDataset::IBuildOverviews( const char *pszResampling,
                                        int nOverviews, int *panOverviewList,
-                                       int nListBands, int *panBandList, 
-                                       GDALProgressFunc pfnProgress, 
+                                       int nListBands, int *panBandList,
+                                       GDALProgressFunc pfnProgress,
                                        void *pProgressData )
 
 {
@@ -868,9 +859,10 @@ CPLErr JP2KAKDataset::IBuildOverviews( const char *pszResampling,
 /* -------------------------------------------------------------------- */
     for( int iBand = 0; iBand < GetRasterCount(); iBand++ )
     {
-        JP2KAKRasterBand *poBand = 
-            (JP2KAKRasterBand *) GetRasterBand( iBand+1 );
-
+        JP2KAKRasterBand *poBand =
+            dynamic_cast<JP2KAKRasterBand *>( GetRasterBand( iBand+1 ) );
+        if( poBand == NULL )
+            CPLError( CE_Fatal, CPLE_AppDefined, "Dynamic cast failed" );
         for( int i = 0; i < poBand->nOverviewCount; i++ )
             delete poBand->papoOverviewBand[i];
 
@@ -879,9 +871,9 @@ CPLErr JP2KAKDataset::IBuildOverviews( const char *pszResampling,
         poBand->nOverviewCount = 0;
     }
 
-    return GDALPamDataset::IBuildOverviews( pszResampling, 
-                                            nOverviews, panOverviewList, 
-                                            nListBands, panBandList, 
+    return GDALPamDataset::IBuildOverviews( pszResampling,
+                                            nOverviews, panOverviewList,
+                                            nListBands, panBandList,
                                             pfnProgress, pProgressData );
 }
 
@@ -897,11 +889,11 @@ void JP2KAKDataset::KakaduInitialize()
 /* -------------------------------------------------------------------- */
     if( !kakadu_initialized )
     {
-        kakadu_initialized = TRUE;
+        kakadu_initialized = true;
 
         kdu_cpl_error_message oErrHandler( CE_Failure );
         kdu_cpl_error_message oWarningHandler( CE_Warning );
-        
+
         kdu_customize_warnings(new kdu_cpl_error_message( CE_Warning ) );
         kdu_customize_errors(new kdu_cpl_error_message( CE_Failure ) );
     }
@@ -919,13 +911,10 @@ int JP2KAKDataset::Identify( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->nHeaderBytes < (int) sizeof(jp2_header) )
     {
-        const char  *pszExtension = NULL;
-
-        pszExtension = CPLGetExtension( poOpenInfo->pszFilename );
-        if( (EQUALN(poOpenInfo->pszFilename,"http://",7)
-             || EQUALN(poOpenInfo->pszFilename,"https://",8)
-             || EQUALN(poOpenInfo->pszFilename,"jpip://",7))
-            && EQUAL(pszExtension,"jp2") )
+        if( (STARTS_WITH_CI(poOpenInfo->pszFilename, "http://")
+             || STARTS_WITH_CI(poOpenInfo->pszFilename, "https://")
+             || STARTS_WITH_CI(poOpenInfo->pszFilename, "jpip://"))
+            && EQUAL(CPLGetExtension( poOpenInfo->pszFilename ), "jp2") )
         {
 #ifdef USE_JPIP
             return TRUE;
@@ -933,7 +922,7 @@ int JP2KAKDataset::Identify( GDALOpenInfo * poOpenInfo )
             return FALSE;
 #endif
         }
-        else if( EQUALN(poOpenInfo->pszFilename,"J2K_SUBFILE:",12) )
+        else if( STARTS_WITH_CI(poOpenInfo->pszFilename, "J2K_SUBFILE:") )
             return TRUE;
         else
             return FALSE;
@@ -946,21 +935,20 @@ int JP2KAKDataset::Identify( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( memcmp(poOpenInfo->pabyHeader,jp2_header,sizeof(jp2_header)) == 0 )
         return TRUE;
-    else if( memcmp( poOpenInfo->pabyHeader, jpc_header, 
+    else if( memcmp( poOpenInfo->pabyHeader, jpc_header,
                      sizeof(jpc_header) ) == 0 )
     {
-        const char  *pszExtension = NULL;
-
-        pszExtension = CPLGetExtension( poOpenInfo->pszFilename );
-        if( EQUAL(pszExtension,"jpc") 
-            || EQUAL(pszExtension,"j2k") 
-            || EQUAL(pszExtension,"jp2") 
-            || EQUAL(pszExtension,"jpx") 
+        const char * const pszExtension =
+            CPLGetExtension( poOpenInfo->pszFilename );
+        if( EQUAL(pszExtension,"jpc")
+            || EQUAL(pszExtension,"j2k")
+            || EQUAL(pszExtension,"jp2")
+            || EQUAL(pszExtension,"jpx")
             || EQUAL(pszExtension,"j2c") )
            return TRUE;
 
         // We also want to handle jpc datastreams vis /vsisubfile.
-        if( strstr(poOpenInfo->pszFilename,"vsisubfile") != NULL )
+        if( strstr(poOpenInfo->pszFilename, "vsisubfile") != NULL )
             return TRUE;
     }
 
@@ -974,20 +962,19 @@ int JP2KAKDataset::Identify( GDALOpenInfo * poOpenInfo )
 GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    subfile_source *poRawInput = NULL;
-    const char  *pszExtension = NULL;
-    int         bIsJPIP = FALSE;
-    int         bIsSubfile = FALSE;
-    GByte      *pabyHeader = NULL;
-
     if( !Identify( poOpenInfo ) )
         return NULL;
 
-    int bResilient = CSLTestBoolean(
+    subfile_source *poRawInput = NULL;
+    bool bIsJPIP = false;
+    bool bIsSubfile = false;
+    GByte *pabyHeader = NULL;
+
+    const bool bResilient = CPLTestBool(
         CPLGetConfigOption( "JP2KAK_RESILIENT", "NO" ) );
 
     /* Doesn't seem to bring any real performance gain on Linux */
-    int bBuffered = CSLTestBoolean(
+    const bool bBuffered = CPLTestBool(
         CPLGetConfigOption( "JP2KAK_BUFFERED",
 #ifdef WIN32
                             "YES"
@@ -1001,19 +988,19 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     KakaduInitialize();
 
-    pszExtension = CPLGetExtension( poOpenInfo->pszFilename );
+    const char *pszExtension = CPLGetExtension( poOpenInfo->pszFilename );
     if( poOpenInfo->nHeaderBytes < 16 )
     {
-        if( (EQUALN(poOpenInfo->pszFilename,"http://",7)
-             || EQUALN(poOpenInfo->pszFilename,"https://",8)
-             || EQUALN(poOpenInfo->pszFilename,"jpip://",7))
+        if( (STARTS_WITH_CI(poOpenInfo->pszFilename, "http://")
+             || STARTS_WITH_CI(poOpenInfo->pszFilename, "https://")
+             || STARTS_WITH_CI(poOpenInfo->pszFilename, "jpip://"))
             && EQUAL(pszExtension,"jp2") )
         {
-            bIsJPIP = TRUE;
+            bIsJPIP = true;
         }
-        else if( EQUALN(poOpenInfo->pszFilename,"J2K_SUBFILE:",12) )
+        else if( STARTS_WITH_CI(poOpenInfo->pszFilename, "J2K_SUBFILE:") )
         {
-            static GByte abySubfileHeader[16];
+            static GByte abySubfileHeader[16] = { 0 };
 
             try
             {
@@ -1031,7 +1018,7 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
 
             pabyHeader = abySubfileHeader;
 
-            bIsSubfile = TRUE;
+            bIsSubfile = true;
         }
         else
             return NULL;
@@ -1049,7 +1036,8 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
     VSIStatBuf sStat;
     if( poRawInput == NULL
         && !bIsJPIP
-        && (bBuffered || bResilient || VSIStat(poOpenInfo->pszFilename, &sStat) != 0) )
+        && (bBuffered || bResilient ||
+            VSIStat(poOpenInfo->pszFilename, &sStat) != 0) )
     {
         try
         {
@@ -1066,14 +1054,14 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      If the header is a JP2 header, mark this as a JP2 dataset.      */
 /* -------------------------------------------------------------------- */
-    if( pabyHeader && memcmp(pabyHeader,jp2_header,sizeof(jp2_header)) == 0 )
+    if( pabyHeader && memcmp(pabyHeader, jp2_header, sizeof(jp2_header)) == 0 )
         pszExtension = "jp2";
 
 /* -------------------------------------------------------------------- */
 /*      Try to open the file in a manner depending on the extension.    */
 /* -------------------------------------------------------------------- */
     kdu_compressed_source *poInput = NULL;
-    kdu_client      *jpip_client = NULL;
+    kdu_client *jpip_client = NULL;
     jp2_palette oJP2Palette;
     jp2_channels oJP2Channels;
 
@@ -1084,13 +1072,12 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
         if( bIsJPIP )
         {
 #ifdef USE_JPIP
-            jp2_source *jp2_src;
             char *pszWrk = CPLStrdup(strstr(poOpenInfo->pszFilename,"://")+3);
             char *pszRequest = strstr(pszWrk,"/");
-     
+
             if( pszRequest == NULL )
             {
-                CPLDebug( "JP2KAK", 
+                CPLDebug( "JP2KAK",
                           "Failed to parse JPIP server and request." );
                 CPLFree( pszWrk );
                 return NULL;
@@ -1098,27 +1085,28 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
 
             *(pszRequest++) = '\0';
 
-            CPLDebug( "JP2KAK", "server=%s, request=%s", 
+            CPLDebug( "JP2KAK", "server=%s, request=%s",
                       pszWrk, pszRequest );
 
             CPLSleep( 15.0 );
             jpip_client = new kdu_client;
-            jpip_client->connect( pszWrk, NULL, pszRequest, "http-tcp", 
+            jpip_client->connect( pszWrk, NULL, pszRequest, "http-tcp",
                                   "" );
-            
+
             CPLDebug( "JP2KAK", "After connect()" );
 
             bool bin0_complete = false;
 
             while( jpip_client->get_databin_length(KDU_META_DATABIN,0,0,
-                                                   &bin0_complete) <= 0 
+                                                   &bin0_complete) <= 0
                    || !bin0_complete )
                 CPLSleep( 0.25 );
 
             family = new jp2_family_src;
             family->open( jpip_client );
 
-            jp2_src = new jp2_source;
+            // TODO(schwehr): Check for memory leaks.
+            jp2_source *jp2_src = new jp2_source;
             jp2_src->open( family );
             jp2_src->read_header();
 
@@ -1137,7 +1125,7 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
 
             poInput = jp2_src;
 #else
-            CPLError( CE_Failure, CPLE_OpenFailed, 
+            CPLError( CE_Failure, CPLE_OpenFailed,
                       "JPIP Protocol not supported by GDAL with Kakadu 3.4 or on Unix." );
             return NULL;
 #endif
@@ -1171,8 +1159,9 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
             if( oColors.get_space() != JP2_sRGB_SPACE
                 && oColors.get_space() != JP2_sLUM_SPACE )
             {
-                CPLDebug( "JP2KAK", "Unusual ColorSpace=%d, not further interpreted.", 
-                          (int) oColors.get_space() );
+                CPLDebug( "JP2KAK",
+                          "Unusual ColorSpace=%d, not further interpreted.",
+                          static_cast<int>( oColors.get_space() ) );
             }
         }
         else if( poRawInput == NULL )
@@ -1194,7 +1183,7 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    JP2KAKDataset 	*poDS = NULL;
+    JP2KAKDataset *poDS = NULL;
 
     try
     {
@@ -1207,7 +1196,7 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
 
         poDS->bCached = bBuffered;
         poDS->bResilient = bResilient;
-        poDS->bFussy = CSLTestBoolean(
+        poDS->bFussy = CPLTestBool(
             CPLGetConfigOption( "JP2KAK_FUSSY", "NO" ) );
 
         if( poDS->bFussy )
@@ -1223,7 +1212,7 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Get overall image size.                                         */
 /* -------------------------------------------------------------------- */
         poDS->oCodeStream.get_dims( 0, poDS->dims );
-        
+
         poDS->nRasterXSize = poDS->dims.size.x;
         poDS->nRasterYSize = poDS->dims.size.y;
 
@@ -1234,13 +1223,11 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->nBands = poDS->oCodeStream.get_num_components();
 
         if (poDS->nBands > 1 )
-        { 
-            int iDim;
-        
-            for( iDim = 1; iDim < poDS->nBands; iDim++ )
+        {
+            for( int iDim = 1; iDim < poDS->nBands; iDim++ )
             {
-                kdu_dims  dim_this_comp;
-            
+                kdu_dims dim_this_comp;
+
                 poDS->oCodeStream.get_dims(iDim, dim_this_comp);
 
                 if( dim_this_comp != poDS->dims )
@@ -1263,12 +1250,10 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
 
         if( nNumThreads > 0 )
         {
-            int iThread;
-
             poDS->poThreadEnv = new kdu_thread_env;
             poDS->poThreadEnv->create();
 
-            for( iThread=0; iThread < nNumThreads; iThread++ )
+            for( int iThread=0; iThread < nNumThreads; iThread++ )
             {
                 if( !poDS->poThreadEnv->add_thread() )
                     break;
@@ -1285,7 +1270,7 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
         siz_params *siz = poDS->oCodeStream.access_siz();
         kdu_params *cod = siz->access_cluster(COD_params);
-        bool use_precincts;
+        bool use_precincts = false;
 
         cod->get(Cuse_precincts,0,0,use_precincts);
 
@@ -1293,23 +1278,23 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
         if( EQUAL(pszPersist,"AUTO") )
         {
             if( !use_precincts && !bIsJPIP
-                && (poDS->nRasterXSize * (double) poDS->nRasterYSize) 
+                && (poDS->nRasterXSize * (double) poDS->nRasterYSize)
                 > 100000000.0 )
                 poDS->bPreferNPReads = true;
         }
         else
-            poDS->bPreferNPReads = !CSLTestBoolean(pszPersist);
+            poDS->bPreferNPReads = !CPLTestBool(pszPersist);
 
-        CPLDebug( "JP2KAK", "Cuse_precincts=%d, PreferNonPersistentReads=%d", 
-                  (int) use_precincts, poDS->bPreferNPReads );
+        CPLDebug( "JP2KAK", "Cuse_precincts=%d, PreferNonPersistentReads=%d",
+                  use_precincts ? 1 : 0, poDS->bPreferNPReads ? 1 : 0 );
 
 /* -------------------------------------------------------------------- */
 /*      Deduce some other info about the dataset.                       */
 /* -------------------------------------------------------------------- */
-        int order; 
-        
-        cod->get(Corder,0,0,order);
-        
+        int order = 0;
+
+        cod->get(Corder, 0, 0, order);
+
         if( order == Corder_LRCP )
         {
             CPLDebug( "JP2KAK", "order=LRCP" );
@@ -1341,14 +1326,14 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
         }
 
         poDS->bUseYCC = false;
-        cod->get(Cycc,0,0,poDS->bUseYCC);
+        cod->get(Cycc, 0, 0, poDS->bUseYCC);
         if( poDS->bUseYCC )
             CPLDebug( "JP2KAK", "ycc=true" );
 
 /* -------------------------------------------------------------------- */
 /*      find out how many resolutions levels are available.             */
 /* -------------------------------------------------------------------- */
-        kdu_dims tile_indices; 
+        kdu_dims tile_indices;
         poDS->oCodeStream.get_valid_tiles(tile_indices);
 
         kdu_tile tile = poDS->oCodeStream.open_tile(tile_indices.pos);
@@ -1357,7 +1342,6 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
 
         CPLDebug( "JP2KAK", "nResCount=%d", poDS->nResCount );
 
-
 /* -------------------------------------------------------------------- */
 /*      Should we promote alpha channel to 8 bits ?                     */
 /* -------------------------------------------------------------------- */
@@ -1366,18 +1350,18 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
                                 poDS->oCodeStream.get_bit_depth(1) == 8 &&
                                 poDS->oCodeStream.get_bit_depth(2) == 8 &&
                                 poDS->oCodeStream.get_bit_depth(3) == 1 &&
-                                CSLFetchBoolean(poOpenInfo->papszOpenOptions, "1BIT_ALPHA_PROMOTION", TRUE));
+                                CSLFetchBoolean(poOpenInfo->papszOpenOptions,
+                                                "1BIT_ALPHA_PROMOTION", TRUE));
         if( poDS->bPromoteTo8Bit )
-            CPLDebug( "JP2KAK",  "Fourth (alpha) band is promoted from 1 bit to 8 bit");
+            CPLDebug( "JP2KAK",
+                      "Fourth (alpha) band is promoted from 1 bit to 8 bit");
 
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-        int iBand;
-    
-        for( iBand = 1; iBand <= poDS->nBands; iBand++ )
+        for( int iBand = 1; iBand <= poDS->nBands; iBand++ )
         {
-            JP2KAKRasterBand *poBand = 
+            JP2KAKRasterBand *poBand =
                 new JP2KAKRasterBand(iBand,0,poDS->oCodeStream,poDS->nResCount,
                                      jpip_client, oJP2Channels, poDS );
 
@@ -1400,7 +1384,8 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
         CPLString osPhysicalFilename = poOpenInfo->pszFilename;
 
-        if( bIsSubfile || EQUALN(poOpenInfo->pszFilename,"/vsisubfile/",12) )
+        if( bIsSubfile ||
+            STARTS_WITH_CI(poOpenInfo->pszFilename, "/vsisubfile/") )
         {
             if( strstr(poOpenInfo->pszFilename,",") != NULL )
                 osPhysicalFilename = strstr(poOpenInfo->pszFilename,",") + 1;
@@ -1419,15 +1404,16 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Check for external overviews.                                   */
 /* -------------------------------------------------------------------- */
         poDS->oOvManager.Initialize( poDS, osPhysicalFilename );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
         if( poOpenInfo->eAccess == GA_Update )
         {
             delete poDS;
-            CPLError( CE_Failure, CPLE_NotSupported, 
-                      "The JP2KAK driver does not support update access to existing"
+            CPLError( CE_Failure, CPLE_NotSupported,
+                      "The JP2KAK driver does not support "
+                      "update access to existing"
                       " datasets.\n" );
             return NULL;
         }
@@ -1438,7 +1424,8 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
         if( poOpenInfo->nOpenFlags & GDAL_OF_VECTOR )
         {
             poDS->LoadVectorLayers(
-                CSLFetchBoolean(poOpenInfo->papszOpenOptions, "OPEN_REMOTE_GML", FALSE));
+                CSLFetchBoolean( poOpenInfo->papszOpenOptions,
+                                 "OPEN_REMOTE_GML", FALSE ) );
 
             // If file opened in vector-only mode and there's no vector,
             // return
@@ -1470,21 +1457,21 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
 /*                           DirectRasterIO()                           */
 /************************************************************************/
 
-CPLErr 
-JP2KAKDataset::DirectRasterIO( CPL_UNUSED GDALRWFlag eRWFlag,
+CPLErr
+JP2KAKDataset::DirectRasterIO( GDALRWFlag /* eRWFlag */,
                                int nXOff, int nYOff, int nXSize, int nYSize,
                                void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType, 
+                               GDALDataType eBufType,
                                int nBandCount, int *panBandMap,
                                GSpacing nPixelSpace, GSpacing nLineSpace,
                                GSpacing nBandSpace,
                                GDALRasterIOExtraArg* psExtraArg)
-    
+
 {
     kdu_codestream *poCodeStream = &oCodeStream;
     const char *pszPersistency = "";
 
-    CPLAssert( eBufType == GDT_Byte 
+    CPLAssert( eBufType == GDT_Byte
                || eBufType == GDT_Int16
                || eBufType == GDT_UInt16 );
 
@@ -1519,8 +1506,8 @@ JP2KAKDataset::DirectRasterIO( CPL_UNUSED GDALRWFlag eRWFlag,
         if( bResilient )
             oWCodeStream.set_resilient();
 
-        poCodeStream= &oWCodeStream;
-        
+        poCodeStream = &oWCodeStream;
+
         pszPersistency = "(non-persistent)";
     }
 
@@ -1530,32 +1517,33 @@ JP2KAKDataset::DirectRasterIO( CPL_UNUSED GDALRWFlag eRWFlag,
     int nDiscardLevels = 0;
     int nResMult = 1;
 
-    while( nDiscardLevels < nResCount - 1 
+    while( nDiscardLevels < nResCount - 1
            && nBufXSize * nResMult * 2 < nXSize * 1.01
            && nBufYSize * nResMult * 2 < nYSize * 1.01 )
     {
         nDiscardLevels++;
-        nResMult = nResMult * 2;
+        nResMult *= 2;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Prepare component indices list.                                 */
 /* -------------------------------------------------------------------- */
-    CPLErr eErr=CE_None;
-    int *component_indices;
-    int *stripe_heights, *sample_offsets, *sample_gaps, *row_gaps, *precisions;
-    bool *is_signed;
-    int i;
-    
-    component_indices = (int *) CPLMalloc(sizeof(int) * nBandCount);
-    stripe_heights = (int *) CPLMalloc(sizeof(int) * nBandCount);
-    sample_offsets = (int *) CPLMalloc(sizeof(int) * nBandCount);
-    sample_gaps = (int *) CPLMalloc(sizeof(int) * nBandCount);
-    row_gaps = (int *) CPLMalloc(sizeof(int) * nBandCount);
-    precisions = (int *) CPLMalloc(sizeof(int) * nBandCount);
-    is_signed = (bool *) CPLMalloc(sizeof(bool) * nBandCount);
-
-    for( i = 0; i < nBandCount; i++ )
+    CPLErr eErr = CE_None;
+
+    int *component_indices =
+        static_cast<int *>( CPLMalloc(sizeof(int) * nBandCount) );
+    int *stripe_heights =
+        static_cast<int *>( CPLMalloc(sizeof(int) * nBandCount) );
+    int *sample_offsets =
+        static_cast<int *>( CPLMalloc(sizeof(int) * nBandCount) );
+    int *sample_gaps =
+        static_cast<int *>( CPLMalloc(sizeof(int) * nBandCount) );
+    int *row_gaps = static_cast<int *>( CPLMalloc(sizeof(int) * nBandCount) );
+    int *precisions = static_cast<int *>( CPLMalloc(sizeof(int) * nBandCount) );
+    bool *is_signed =
+        static_cast<bool *>( CPLMalloc(sizeof(bool) * nBandCount) );
+
+    for( int i = 0; i < nBandCount; i++ )
         component_indices[i] = panBandMap[i] - 1;
 
 /* -------------------------------------------------------------------- */
@@ -1564,59 +1552,80 @@ JP2KAKDataset::DirectRasterIO( CPL_UNUSED GDALRWFlag eRWFlag,
 /* -------------------------------------------------------------------- */
     try
     {
-        kdu_dims dims;
+        kdu_dims l_dims;
         poCodeStream->apply_input_restrictions( 0, 0, nDiscardLevels, 0, NULL );
-        poCodeStream->get_dims( 0, dims );
-
-        dims.pos.x = dims.pos.x + nXOff/nResMult;
-        dims.pos.y = dims.pos.y + nYOff/nResMult;
-        dims.size.x = nXSize/nResMult;
-        dims.size.y = nYSize/nResMult;
-    
-        kdu_dims dims_roi;
-
-        poCodeStream->map_region( 0, dims, dims_roi );
-        poCodeStream->apply_input_restrictions( nBandCount, component_indices, 
-                                              nDiscardLevels, 0, &dims_roi,
+        poCodeStream->get_dims( 0, l_dims );
+        int nOvrXSize = l_dims.size.x;
+        int nOvrYSize = l_dims.size.y;
+
+        l_dims.pos.x = l_dims.pos.x + nXOff/nResMult;
+        l_dims.pos.y = l_dims.pos.y + nYOff/nResMult;
+        l_dims.size.x = nXSize/nResMult;
+        l_dims.size.y = nYSize/nResMult;
+
+        // Check if rounding helps detecting when data is being requested exactly
+        // at the current resolution
+        if( nBufXSize != l_dims.size.x &&
+            static_cast<int>(0.5 + static_cast<double>(nXSize)/nResMult)
+            == nBufXSize )
+        {
+            l_dims.size.x = nBufXSize;
+        }
+        if( nBufYSize != l_dims.size.y &&
+            static_cast<int>(0.5 + static_cast<double>(nYSize)/nResMult)
+            == nBufYSize )
+        {
+            l_dims.size.y = nBufYSize;
+        }
+        if( l_dims.pos.x + l_dims.size.x > nOvrXSize )
+            l_dims.size.x = nOvrXSize - l_dims.pos.x;
+        if( l_dims.pos.y + l_dims.size.y > nOvrYSize )
+            l_dims.size.y = nOvrYSize - l_dims.pos.y;
+
+        kdu_dims l_dims_roi;
+
+        poCodeStream->map_region( 0, l_dims, l_dims_roi );
+        poCodeStream->apply_input_restrictions( nBandCount, component_indices,
+                                              nDiscardLevels, 0, &l_dims_roi,
                                               KDU_WANT_OUTPUT_COMPONENTS);
 
 /* -------------------------------------------------------------------- */
 /*      Special case where the data is being requested exactly at       */
 /*      this resolution.  Avoid any extra sampling pass.                */
 /* -------------------------------------------------------------------- */
-        if( nBufXSize == dims.size.x && nBufYSize == dims.size.y )
+        if( nBufXSize == l_dims.size.x && nBufYSize == l_dims.size.y )
         {
             kdu_stripe_decompressor decompressor;
             decompressor.start(*poCodeStream,false,false,poThreadEnv);
-        
+
             CPLDebug( "JP2KAK", "DirectRasterIO() for %d,%d,%d,%d -> %dx%d (no intermediate) %s",
                       nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize,
                       pszPersistency );
 
-            for( i = 0; i < nBandCount; i++ )
+            for( int i = 0; i < nBandCount; i++ )
             {
-                stripe_heights[i] = dims.size.y;
+                stripe_heights[i] = l_dims.size.y;
                 precisions[i] = poCodeStream->get_bit_depth(i);
                 if( eBufType == GDT_Byte )
                 {
                     is_signed[i] = false;
-                    sample_offsets[i] = i * nBandSpace;
-                    sample_gaps[i] = nPixelSpace;
-                    row_gaps[i] = nLineSpace;
+                    sample_offsets[i] = static_cast<int>(i * nBandSpace);
+                    sample_gaps[i] = static_cast<int>(nPixelSpace);
+                    row_gaps[i] = static_cast<int>(nLineSpace);
                 }
                 else if( eBufType == GDT_Int16 )
                 {
                     is_signed[i] = true;
-                    sample_offsets[i] = i * nBandSpace / 2;
-                    sample_gaps[i] = nPixelSpace / 2;
-                    row_gaps[i] = nLineSpace / 2;
+                    sample_offsets[i] = static_cast<int>(i * nBandSpace / 2);
+                    sample_gaps[i] = static_cast<int>(nPixelSpace / 2);
+                    row_gaps[i] = static_cast<int>(nLineSpace / 2);
                 }
                 else if( eBufType == GDT_UInt16 )
                 {
                     is_signed[i] = false;
-                    sample_offsets[i] = i * nBandSpace / 2;
-                    sample_gaps[i] = nPixelSpace / 2;
-                    row_gaps[i] = nLineSpace / 2;
+                    sample_offsets[i] = static_cast<int>(i * nBandSpace / 2);
+                    sample_gaps[i] = static_cast<int>(nPixelSpace / 2);
+                    row_gaps[i] = static_cast<int>(nLineSpace / 2);
                     /* Introduced in r25136 with an unrelated commit message.
                     Reverted per ticket #5328
                     if( precisions[i] == 12 )
@@ -1625,7 +1634,7 @@ JP2KAKDataset::DirectRasterIO( CPL_UNUSED GDALRWFlag eRWFlag,
                       precisions[i] = 16;
                     }*/
                 }
-                
+
             }
 
             if( eBufType == GDT_Byte )
@@ -1644,31 +1653,28 @@ JP2KAKDataset::DirectRasterIO( CPL_UNUSED GDALRWFlag eRWFlag,
 /* -------------------------------------------------------------------- */
         else
         {
-            int nDataTypeSize = GDALGetDataTypeSize(eBufType) / 8;
-            GByte *pabyIntermediate = (GByte *) 
-                VSIMalloc3(dims.size.x, dims.size.y, nDataTypeSize*nBandCount );
+            const int nDataTypeSize = GDALGetDataTypeSize(eBufType) / 8;
+            GByte *pabyIntermediate = static_cast<GByte *>(
+                VSI_MALLOC3_VERBOSE( l_dims.size.x, l_dims.size.y,
+                                     nDataTypeSize*nBandCount ) );
             if( pabyIntermediate == NULL )
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory, 
-                          "Failed to allocate %d byte intermediate decompression buffer for jpeg2000.", 
-                          dims.size.x * dims.size.y * nDataTypeSize * nBandCount );
-
                 return CE_Failure;
             }
 
-            CPLDebug( "JP2KAK", 
+            CPLDebug( "JP2KAK",
                       "DirectRasterIO() for %d,%d,%d,%d -> %dx%d -> %dx%d %s",
-                      nXOff, nYOff, nXSize, nYSize, 
-                      dims.size.x, dims.size.y, 
-                      nBufXSize, nBufYSize, 
+                      nXOff, nYOff, nXSize, nYSize,
+                      l_dims.size.x, l_dims.size.y,
+                      nBufXSize, nBufYSize,
                       pszPersistency );
 
             kdu_stripe_decompressor decompressor;
-            decompressor.start(*poCodeStream,false,false,poThreadEnv);
-        
-            for( i = 0; i < nBandCount; i++ )
+            decompressor.start(*poCodeStream, false, false, poThreadEnv);
+
+            for( int i = 0; i < nBandCount; i++ )
             {
-                stripe_heights[i] = dims.size.y;
+                stripe_heights[i] = l_dims.size.y;
                 precisions[i] = poCodeStream->get_bit_depth(i);
 
                 if( eBufType == GDT_Int16 || eBufType == GDT_UInt16 )
@@ -1679,17 +1685,18 @@ JP2KAKDataset::DirectRasterIO( CPL_UNUSED GDALRWFlag eRWFlag,
                         is_signed[i] = false;
                 }
             }
-            
+
             if( eBufType == GDT_Byte )
-                decompressor.pull_stripe( (kdu_byte *) pabyIntermediate, 
-                                          stripe_heights, NULL, NULL, NULL,
-                                          precisions );
+                decompressor.pull_stripe(
+                    reinterpret_cast<kdu_byte *>( pabyIntermediate ),
+                    stripe_heights, NULL, NULL, NULL,
+                    precisions );
             else
-                decompressor.pull_stripe( (kdu_int16 *) pabyIntermediate, 
-                                          stripe_heights,
-                                          NULL, NULL, NULL,
-                                          precisions, is_signed );
-                
+                decompressor.pull_stripe(
+                    reinterpret_cast<kdu_int16 *>( pabyIntermediate ),
+                    stripe_heights, NULL, NULL, NULL,
+                    precisions, is_signed );
+
             decompressor.finish();
 
             if( psExtraArg->eResampleAlg == GRIORA_NearestNeighbour )
@@ -1698,39 +1705,41 @@ JP2KAKDataset::DirectRasterIO( CPL_UNUSED GDALRWFlag eRWFlag,
 /*      Then resample (normally downsample) from the intermediate       */
 /*      buffer into the final buffer in the desired output layout.      */
 /* -------------------------------------------------------------------- */
-                int iY, iX;
-                double dfYRatio = dims.size.y / (double) nBufYSize;
-                double dfXRatio = dims.size.x / (double) nBufXSize;
+                const double dfYRatio =
+                    l_dims.size.y / static_cast<double>( nBufYSize );
+                const double dfXRatio =
+                    l_dims.size.x / static_cast<double>( nBufXSize );
 
-                for( iY = 0; iY < nBufYSize; iY++ )
+                for( int iY = 0; iY < nBufYSize; iY++ )
                 {
                     int iSrcY = (int) floor( (iY + 0.5) * dfYRatio );
 
-                    iSrcY = MIN(iSrcY, dims.size.y-1);
+                    iSrcY = MIN(iSrcY, l_dims.size.y-1);
 
-                    for( iX = 0; iX < nBufXSize; iX++ )
+                    for( int iX = 0; iX < nBufXSize; iX++ )
                     {
-                        int iSrcX = (int) floor( (iX + 0.5) * dfXRatio );
+                        int iSrcX =
+                            static_cast<int>( floor( (iX + 0.5) * dfXRatio ) );
 
-                        iSrcX = MIN(iSrcX, dims.size.x-1);
+                        iSrcX = MIN(iSrcX, l_dims.size.x-1);
 
-                        for( i = 0; i < nBandCount; i++ )
+                        for( int i = 0; i < nBandCount; i++ )
                         {
                             if( eBufType == GDT_Byte )
                                 ((GByte *) pData)[iX*nPixelSpace
                                                 + iY*nLineSpace
-                                                + i*nBandSpace] = 
+                                                + i*nBandSpace] =
                                     pabyIntermediate[iSrcX*nBandCount
-                                                    + iSrcY*dims.size.x*nBandCount
+                                                    + iSrcY*l_dims.size.x*nBandCount
                                                     + i];
                             else if( eBufType == GDT_Int16
                                     || eBufType == GDT_UInt16 )
                                 ((GUInt16 *) pData)[iX*nPixelSpace/2
                                                 + iY*nLineSpace/2
-                                                + i*nBandSpace/2] = 
+                                                + i*nBandSpace/2] =
                                     ((GUInt16 *)pabyIntermediate)[
                                         iSrcX*nBandCount
-                                        + iSrcY*dims.size.x*nBandCount
+                                        + iSrcY*l_dims.size.x*nBandCount
                                         + i];
                         }
                     }
@@ -1739,43 +1748,56 @@ JP2KAKDataset::DirectRasterIO( CPL_UNUSED GDALRWFlag eRWFlag,
             else
             {
                 /* Create a MEM dataset that wraps the input buffer */
-                GDALDataset* poMEMDS = MEMDataset::Create("", dims.size.x,
-                                                        dims.size.y, 0,
-                                                        eBufType, NULL);
-                char szBuffer[64];
-                int nRet;
+                GDALDataset* poMEMDS = MEMDataset::Create( "", l_dims.size.x,
+                                                           l_dims.size.y, 0,
+                                                           eBufType, NULL);
+                char szBuffer[64] = { '\0' };
+                int nRet = 0;
 
-                for( i = 0; i < nBandCount; i++ )
+                for( int i = 0; i < nBandCount; i++ )
                 {
 
-                    nRet = CPLPrintPointer(szBuffer, pabyIntermediate + i * nDataTypeSize, sizeof(szBuffer));
+                    nRet = CPLPrintPointer(
+                        szBuffer, pabyIntermediate + i * nDataTypeSize,
+                        sizeof(szBuffer) );
                     szBuffer[nRet] = 0;
-                    char** papszOptions = CSLSetNameValue(NULL, "DATAPOINTER", szBuffer);
+                    char** papszOptions =
+                        CSLSetNameValue(NULL, "DATAPOINTER", szBuffer);
 
                     papszOptions = CSLSetNameValue(papszOptions, "PIXELOFFSET",
-                        CPLSPrintf(CPL_FRMT_GIB, (GIntBig)nDataTypeSize * nBandCount));
+                        CPLSPrintf(
+                            CPL_FRMT_GIB,
+                            static_cast<GIntBig>(nDataTypeSize) * nBandCount));
 
                     papszOptions = CSLSetNameValue(papszOptions, "LINEOFFSET",
-                        CPLSPrintf(CPL_FRMT_GIB, (GIntBig)nDataTypeSize * nBandCount * dims.size.x));
+                        CPLSPrintf(
+                            CPL_FRMT_GIB,
+                            static_cast<GIntBig>(nDataTypeSize)
+                            * nBandCount * l_dims.size.x) );
 
                     poMEMDS->AddBand(eBufType, papszOptions);
                     CSLDestroy(papszOptions);
 
-                    const char* pszNBITS = GetRasterBand(i+1)->GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
+                    const char* pszNBITS = GetRasterBand(i+1)->
+                        GetMetadataItem( "NBITS", "IMAGE_STRUCTURE" );
                     if( pszNBITS )
-                        poMEMDS->GetRasterBand(i+1)->SetMetadataItem("NBITS", pszNBITS, "IMAGE_STRUCTURE");
+                        poMEMDS->GetRasterBand(i+1)->
+                            SetMetadataItem( "NBITS", pszNBITS,
+                                             "IMAGE_STRUCTURE");
                 }
 
                 GDALRasterIOExtraArg sExtraArgTmp;
                 INIT_RASTERIO_EXTRA_ARG(sExtraArgTmp);
                 sExtraArgTmp.eResampleAlg = psExtraArg->eResampleAlg;
 
-                poMEMDS->RasterIO(GF_Read, 0, 0, dims.size.x, dims.size.y,
-                                  pData, nBufXSize, nBufYSize,
-                                  eBufType,
-                                  nBandCount, NULL,
-                                  nPixelSpace, nLineSpace, nBandSpace,
-                                  &sExtraArgTmp);
+                CPL_IGNORE_RET_VAL(
+                    poMEMDS->RasterIO(
+                        GF_Read, 0, 0, l_dims.size.x, l_dims.size.y,
+                        pData, nBufXSize, nBufYSize,
+                        eBufType,
+                        nBandCount, NULL,
+                        nPixelSpace, nLineSpace, nBandSpace,
+                        &sExtraArgTmp ) );
 
                 GDALClose(poMEMDS);
             }
@@ -1784,7 +1806,7 @@ JP2KAKDataset::DirectRasterIO( CPL_UNUSED GDALRWFlag eRWFlag,
         }
     }
 /* -------------------------------------------------------------------- */
-/*      Catch interal Kakadu errors.                                    */
+/*      Catch internal Kakadu errors.                                   */
 /* -------------------------------------------------------------------- */
     catch( ... )
     {
@@ -1796,11 +1818,12 @@ JP2KAKDataset::DirectRasterIO( CPL_UNUSED GDALRWFlag eRWFlag,
 /* -------------------------------------------------------------------- */
     if( nBandCount == 4 && bPromoteTo8Bit )
     {
-        for(int j=0;j<nBufYSize;j++)
+        for( int j=0; j < nBufYSize; j++ )
         {
-            for(i=0;i<nBufXSize;i++)
+            for( int i=0; i < nBufXSize; i++ )
             {
-                ((GByte*)pData)[j*nLineSpace+i*nPixelSpace+3*nBandSpace] *= 255;
+                static_cast<GByte*>(
+                    pData)[j*nLineSpace+i*nPixelSpace+3*nBandSpace] *= 255;
             }
         }
     }
@@ -1833,10 +1856,10 @@ JP2KAKDataset::DirectRasterIO( CPL_UNUSED GDALRWFlag eRWFlag,
 /*      (FALSE) for a given request configuration and environment.      */
 /************************************************************************/
 
-int 
+int
 JP2KAKDataset::TestUseBlockIO( int nXOff, int nYOff, int nXSize, int nYSize,
                                int nBufXSize, int nBufYSize,
-                               GDALDataType eDataType, 
+                               GDALDataType eDataType,
                                int nBandCount, int *panBandList )
 
 {
@@ -1850,11 +1873,9 @@ JP2KAKDataset::TestUseBlockIO( int nXOff, int nYOff, int nXSize, int nYSize,
              && eDataType != GDT_UInt16 ) )
         return TRUE;
 
-    int i, j; 
-    
-    for( i = 0; i < nBandCount; i++ )
+    for( int i = 0; i < nBandCount; i++ )
     {
-        for( j = i+1; j < nBandCount; j++ )
+        for( int j = i+1; j < nBandCount; j++ )
             if( panBandList[j] == panBandList[i] )
                 return TRUE;
     }
@@ -1867,16 +1888,21 @@ JP2KAKDataset::TestUseBlockIO( int nXOff, int nYOff, int nXSize, int nYSize,
     if( GetRasterCount() == 0 )
         return TRUE;
 
-    JP2KAKRasterBand *poWrkBand = (JP2KAKRasterBand*) GetRasterBand(1);
-    if( poWrkBand->HasExternalOverviews() ) 
-    {
-        int    nOverview;
-        int    nXOff2=nXOff, nYOff2=nYOff, nXSize2=nXSize, nYSize2=nYSize;
-
-        nOverview =
-            GDALBandGetBestOverviewLevel2( poWrkBand, 
-                                          nXOff2, nYOff2, nXSize2, nYSize2,
-                                          nBufXSize, nBufYSize, NULL);
+    JP2KAKRasterBand *poWrkBand =
+        dynamic_cast<JP2KAKRasterBand *>( GetRasterBand(1) );
+    if( poWrkBand == NULL )
+        CPLError( CE_Fatal, CPLE_AppDefined, "Dynamic cast failed" );
+    if( poWrkBand->HasExternalOverviews() )
+    {
+        int nXOff2=nXOff;
+        int nYOff2=nYOff;
+        int nXSize2=nXSize;
+        int nYSize2=nYSize;
+
+        const int nOverview =
+            GDALBandGetBestOverviewLevel2( poWrkBand,
+                                           nXOff2, nYOff2, nXSize2, nYSize2,
+                                           nBufXSize, nBufYSize, NULL );
         if (nOverview >= 0 )
             return TRUE;
     }
@@ -1885,17 +1911,17 @@ JP2KAKDataset::TestUseBlockIO( int nXOff, int nYOff, int nXSize, int nYSize,
 /*      The rest of the rules are io strategy stuff, and use            */
 /*      configuration checks.                                           */
 /* -------------------------------------------------------------------- */
-    int bUseBlockedIO = bForceCachedIO;
+    bool bUseBlockedIO = bForceCachedIO;
 
-    if( nYSize == 1 || nXSize * ((double) nYSize) < 100.0 )
-        bUseBlockedIO = TRUE;
+    if( nYSize == 1 || nXSize * static_cast<double>(nYSize) < 100.0 )
+        bUseBlockedIO = true;
 
-    if( nBufYSize == 1 || nBufXSize * ((double) nBufYSize) < 100.0 )
-        bUseBlockedIO = TRUE;
+    if( nBufYSize == 1 || nBufXSize * static_cast<double>(nBufYSize) < 100.0 )
+        bUseBlockedIO = true;
 
     if( strlen(CPLGetConfigOption( "GDAL_ONE_BIG_READ", "")) > 0 )
-        bUseBlockedIO = 
-            !CSLTestBoolean(CPLGetConfigOption( "GDAL_ONE_BIG_READ", ""));
+        bUseBlockedIO =
+            !CPLTestBool(CPLGetConfigOption( "GDAL_ONE_BIG_READ", ""));
 
     return bUseBlockedIO;
 }
@@ -1907,7 +1933,7 @@ JP2KAKDataset::TestUseBlockIO( int nXOff, int nYOff, int nXSize, int nYSize,
 CPLErr JP2KAKDataset::IRasterIO( GDALRWFlag eRWFlag,
                                  int nXOff, int nYOff, int nXSize, int nYSize,
                                  void * pData, int nBufXSize, int nBufYSize,
-                                 GDALDataType eBufType, 
+                                 GDALDataType eBufType,
                                  int nBandCount, int *panBandMap,
                                  GSpacing nPixelSpace, GSpacing nLineSpace,
                                  GSpacing nBandSpace,
@@ -1919,15 +1945,16 @@ CPLErr JP2KAKDataset::IRasterIO( GDALRWFlag eRWFlag,
 /* -------------------------------------------------------------------- */
     if( TestUseBlockIO( nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize,
                         eBufType, nBandCount, panBandMap ) )
-        return GDALPamDataset::IRasterIO( 
+        return GDALPamDataset::IRasterIO(
             eRWFlag, nXOff, nYOff, nXSize, nYSize,
-            pData, nBufXSize, nBufYSize, eBufType, 
-            nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace, psExtraArg );
-    else
-        return DirectRasterIO( 
-            eRWFlag, nXOff, nYOff, nXSize, nYSize,
-            pData, nBufXSize, nBufYSize, eBufType, 
-            nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace, psExtraArg );
+            pData, nBufXSize, nBufYSize, eBufType,
+            nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace,
+            psExtraArg );
+
+    return DirectRasterIO(
+        eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
+        eBufType, nBandCount, panBandMap, nPixelSpace, nLineSpace,
+        nBandSpace, psExtraArg );
 }
 
 /************************************************************************/
@@ -1939,21 +1966,20 @@ CPLErr JP2KAKDataset::IRasterIO( GDALRWFlag eRWFlag,
 static void JP2KAKWriteBox( jp2_target *jp2_out, GDALJP2Box *poBox )
 
 {
-    GUInt32 nBoxType;
-
     if( poBox == NULL )
         return;
 
-    memcpy( &nBoxType, poBox->GetType(), 4 );
+    GUInt32 nBoxType = 0;
+    memcpy( &nBoxType, poBox->GetType(), sizeof(nBoxType) );
     CPL_MSBPTR32( &nBoxType );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Write to a box on the JP2 file.                                 */
 /* -------------------------------------------------------------------- */
     jp2_out->open_next( nBoxType );
 
-    jp2_out->write( (kdu_byte *) poBox->GetWritableData(), 
-                    (int) poBox->GetDataLength() );
+    jp2_out->write( const_cast<kdu_byte *>( poBox->GetWritableData() ),
+                    static_cast<int>( poBox->GetDataLength() ) );
 
     jp2_out->close();
 
@@ -1964,9 +1990,9 @@ static void JP2KAKWriteBox( jp2_target *jp2_out, GDALJP2Box *poBox )
 /*                     JP2KAKCreateCopy_WriteTile()                     */
 /************************************************************************/
 
-static int 
+static int
 JP2KAKCreateCopy_WriteTile( GDALDataset *poSrcDS, kdu_tile &oTile,
-                            kdu_roi_image *poROIImage, 
+                            kdu_roi_image *poROIImage,
                             int nXOff, int nYOff, int nXSize, int nYSize,
                             bool bReversible, int nBits, GDALDataType eType,
                             kdu_codestream &oCodeStream, int bFlushEnabled,
@@ -1974,31 +2000,32 @@ JP2KAKCreateCopy_WriteTile( GDALDataset *poSrcDS, kdu_tile &oTile,
                             GDALProgressFunc pfnProgress, void * pProgressData,
                             bool bComseg )
 
-{                                       
+{
 /* -------------------------------------------------------------------- */
 /*      Create one big tile, and a compressing engine, and line         */
 /*      buffer for each component.                                      */
 /* -------------------------------------------------------------------- */
-    int c, num_components = oTile.get_num_components(); 
-    kdu_push_ifc  *engines = new kdu_push_ifc[num_components];
-    kdu_line_buf  *lines = new kdu_line_buf[num_components];
+    int num_components = oTile.get_num_components();
+    kdu_push_ifc *engines = new kdu_push_ifc[num_components];
+    kdu_line_buf *lines = new kdu_line_buf[num_components];
     kdu_sample_allocator allocator;
-    
-    // Ticket #4050 patch : use a 32 bits kdu_line_buf for GDT_UInt16 reversible compression
-    // ToDo: test for GDT_UInt16?
-    bool   bUseShorts = bReversible;
-    if ((eType == GDT_UInt16)&&(bReversible))
+
+    // Ticket #4050 patch: Use a 32 bits kdu_line_buf for GDT_UInt16 reversible
+    // compression.
+    // TODO: test for GDT_UInt16?
+    bool bUseShorts = bReversible;
+    if( (eType == GDT_UInt16) && bReversible )
         bUseShorts = false;
 
-    for (c=0; c < num_components; c++)
+    for( int c=0; c < num_components; c++ )
     {
-        kdu_resolution res = oTile.access_component(c).access_resolution(); 
+        kdu_resolution res = oTile.access_component(c).access_resolution();
         kdu_roi_node *roi_node = NULL;
 
         if( poROIImage != NULL )
         {
             kdu_dims  dims;
-            
+
             res.get_dims(dims);
             roi_node = poROIImage->acquire_node(c,dims);
         }
@@ -2018,46 +2045,48 @@ JP2KAKCreateCopy_WriteTile( GDALDataset *poSrcDS, kdu_tile &oTile,
         allocator.finalize();
 #endif
 
-        for (c=0; c < num_components; c++)
+        for( int c=0; c < num_components; c++ )
             lines[c].create();
     }
     catch( ... )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "allocate.finalize() failed, likely out of memory for compression information." );
+        // TODO(schwehr): Should this block do any cleanup?
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "allocate.finalize() failed, likely out of memory for "
+                  "compression information." );
         return FALSE;
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Write whole image.  Write 1024 lines of each component, then    */
 /*      go back to the first, and do again.  This gives the rate        */
 /*      computing machine all components to make good estimates.        */
 /* -------------------------------------------------------------------- */
-    int  iLine, iLinesWritten = 0;
+    int iLinesWritten = 0;
 
-    GByte *pabyBuffer = (GByte *) 
-        CPLMalloc(nXSize * (GDALGetDataTypeSize(eType)/8) );
+    // TODO(schwehr): Making pabyBuffer void* should simplify the casting below.
+    GByte *pabyBuffer = static_cast<GByte *>(
+        CPLMalloc(nXSize * (GDALGetDataTypeSize(eType)/8) ) );
 
     CPLAssert( !oTile.get_ycc() );
 
-    int bRet = TRUE;
-    for( iLine = 0; iLine < nYSize && bRet; iLine += TILE_CHUNK_SIZE )
+    bool bRet = true;
+    for( int iLine = 0; iLine < nYSize && bRet; iLine += TILE_CHUNK_SIZE )
     {
-        for (c=0; c < num_components && bRet; c++)
+        for( int c=0; c < num_components && bRet; c++ )
         {
             GDALRasterBand *poBand = poSrcDS->GetRasterBand( c+1 );
-            int iSubline = 0;
-        
-            for( iSubline = iLine; 
+
+            for( int iSubline = iLine;
                  iSubline < iLine+TILE_CHUNK_SIZE && iSubline < nYSize;
                  iSubline++ )
             {
-                if( poBand->RasterIO( GF_Read, 
-                                      nXOff, nYOff+iSubline, nXSize, 1, 
-                                      (void *) pabyBuffer, nXSize, 1, eType,
+                if( poBand->RasterIO( GF_Read,
+                                      nXOff, nYOff+iSubline, nXSize, 1,
+                                      pabyBuffer, nXSize, 1, eType,
                                       0, 0, NULL ) == CE_Failure )
                 {
-                    bRet = FALSE;
+                    bRet = false;
                     break;
                 }
 
@@ -2065,81 +2094,82 @@ JP2KAKCreateCopy_WriteTile( GDALDataset *poSrcDS, kdu_tile &oTile,
                 {
                     kdu_sample16 *dest = lines[c].get_buf16();
                     kdu_byte *sp = pabyBuffer;
-                
-                    for (int n=nXSize; n > 0; n--, dest++, sp++)
+
+                    for( int n=nXSize; n > 0; n--, dest++, sp++ )
                         dest->ival = ((kdu_int16)(*sp)) - 128;
                 }
                 else if( bReversible && eType == GDT_Int16 )
                 {
                     kdu_sample16 *dest = lines[c].get_buf16();
-                    GInt16 *sp = (GInt16 *) pabyBuffer;
-                
-                    for (int n=nXSize; n > 0; n--, dest++, sp++)
+                    GInt16 *sp = reinterpret_cast<GInt16 *>( pabyBuffer );
+
+                    for( int n=nXSize; n > 0; n--, dest++, sp++ )
                         dest->ival = *sp;
                 }
                 else if( bReversible && eType == GDT_UInt16 )
                 {
-                    // Ticket #4050 patch : use a 32 bits kdu_line_buf for GDT_UInt16 reversible compression
+                    // Ticket #4050 patch : use a 32 bits kdu_line_buf for
+                    // GDT_UInt16 reversible compression
                     kdu_sample32 *dest = lines[c].get_buf32();
-                    GUInt16 *sp = (GUInt16 *) pabyBuffer;
-                
-                    for (int n=nXSize; n > 0; n--, dest++, sp++)
-                        dest->ival = (kdu_int32)(*sp)-32768;
+                    GUInt16 *sp = reinterpret_cast<GUInt16 *>( pabyBuffer );
+
+                    for( int n=nXSize; n > 0; n--, dest++, sp++ )
+                        dest->ival = static_cast<kdu_int32>(*sp)-32768;
                 }
                 else if( eType == GDT_Byte )
                 {
                     kdu_sample32 *dest = lines[c].get_buf32();
                     kdu_byte *sp = pabyBuffer;
-                    int nOffset = 1 << (nBits-1);
-                    float fScale = (float) (1.0 / (1 << nBits));
-                
+                    const int nOffset = 1 << (nBits-1);
+                    const float fScale = static_cast<float>(1.0 / (1 << nBits));
+
                     for (int n=nXSize; n > 0; n--, dest++, sp++)
-                        dest->fval = (float) 
-                            ((((kdu_int16)(*sp))-nOffset) * fScale);
+                        dest->fval = static_cast<float>
+                            (((static_cast<kdu_int16>(*sp))-nOffset) * fScale);
                 }
                 else if( eType == GDT_Int16 )
                 {
                     kdu_sample32 *dest = lines[c].get_buf32();
-                    GInt16  *sp = (GInt16 *) pabyBuffer;
-                    float fScale = (float) (1.0 / (1 << nBits));
-                
-                    for (int n=nXSize; n > 0; n--, dest++, sp++)
-                        dest->fval = (float) 
-                            (((kdu_int16)(*sp)) * fScale);
+                    GInt16 *sp = reinterpret_cast<GInt16 *>( pabyBuffer );
+                    const float fScale = static_cast<float>(1.0 / (1 << nBits));
+
+                    for( int n=nXSize; n > 0; n--, dest++, sp++ )
+                        dest->fval = static_cast<float>
+                            ((static_cast<kdu_int16>(*sp)) * fScale);
                 }
                 else if( eType == GDT_UInt16 )
                 {
                     kdu_sample32 *dest = lines[c].get_buf32();
-                    GUInt16  *sp = (GUInt16 *) pabyBuffer;
-                    int nOffset = 1 << (nBits-1);
-                    float fScale = (float) (1.0 / (1 << nBits));
-                
-                    for (int n=nXSize; n > 0; n--, dest++, sp++)
-                        dest->fval = (float) 
-                            (((int)(*sp) - nOffset) * fScale);
+                    GUInt16 *sp = reinterpret_cast<GUInt16 *>(pabyBuffer);
+                    const int nOffset = 1 << (nBits-1);
+                    const float fScale = static_cast<float>(1.0 / (1 << nBits));
+
+                    for( int n=nXSize; n > 0; n--, dest++, sp++ )
+                        dest->fval = static_cast<float>
+                            ((static_cast<int>(*sp) - nOffset) * fScale);
                 }
                 else if( eType == GDT_Float32 )
                 {
                     kdu_sample32 *dest = lines[c].get_buf32();
-                    float  *sp = (float *) pabyBuffer;
-                
-                    for (int n=nXSize; n > 0; n--, dest++, sp++)
+                    float *sp = reinterpret_cast<float *>( pabyBuffer );
+
+                    for( int n=nXSize; n > 0; n--, dest++, sp++ )
                         dest->fval = *sp;  /* scale it? */
                 }
 
 #if KDU_MAJOR_VERSION >= 7
                 engines[c].push(lines[c]);
 #else
-                engines[c].push(lines[c],true);
+                engines[c].push(lines[c], true);
 #endif
-
                 iLinesWritten++;
 
-                if( !pfnProgress( iLinesWritten 
-                                  / (double) (num_components * nYSize),
-                                  NULL, pProgressData ) )
+                if( !pfnProgress(
+                    iLinesWritten /
+                    static_cast<double> (num_components * nYSize),
+                    NULL, pProgressData ) )
                 {
-                    bRet = FALSE;
+                    bRet = false;
                     break;
                 }
             }
@@ -2149,7 +2179,7 @@ JP2KAKCreateCopy_WriteTile( GDALDataset *poSrcDS, kdu_tile &oTile,
 
         if( oCodeStream.ready_for_flush() && bFlushEnabled )
         {
-            CPLDebug( "JP2KAK", 
+            CPLDebug( "JP2KAK",
                       "Calling oCodeStream.flush() at line %d",
                       MIN(nYSize,iLine+TILE_CHUNK_SIZE) );
             try
@@ -2159,11 +2189,11 @@ JP2KAKCreateCopy_WriteTile( GDALDataset *poSrcDS, kdu_tile &oTile,
             }
             catch(...)
             {
-                bRet = FALSE;
+                bRet = false;
             }
         }
         else if( bFlushEnabled )
-            CPLDebug( "JP2KAK", 
+            CPLDebug( "JP2KAK",
                       "read_for_flush() is false at line %d.",
                       iLine );
     }
@@ -2171,7 +2201,7 @@ JP2KAKCreateCopy_WriteTile( GDALDataset *poSrcDS, kdu_tile &oTile,
 /* -------------------------------------------------------------------- */
 /*      Cleanup resources.                                              */
 /* -------------------------------------------------------------------- */
-    for( c = 0; c < num_components; c++ )
+    for( int c = 0; c < num_components; c++ )
         engines[c].destroy();
 
     delete[] engines;
@@ -2190,19 +2220,11 @@ JP2KAKCreateCopy_WriteTile( GDALDataset *poSrcDS, kdu_tile &oTile,
 /************************************************************************/
 
 static GDALDataset *
-JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
-                  int bStrict, char ** papszOptions, 
+JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
+                  int bStrict, char ** papszOptions,
                   GDALProgressFunc pfnProgress, void * pProgressData )
 
 {
-    int	   nXSize = poSrcDS->GetRasterXSize();
-    int    nYSize = poSrcDS->GetRasterYSize();
-    int    nTileXSize = nXSize;
-    int    nTileYSize = nYSize;
-    bool   bReversible = false;
-    int    bFlushEnabled = CSLFetchBoolean( papszOptions, "FLUSH", TRUE );
-    int    nBits;
-
     if( poSrcDS->GetRasterCount() == 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -2215,11 +2237,11 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
     if( !kakadu_initialized )
     {
-        kakadu_initialized = TRUE;
+        kakadu_initialized = true;
 
         kdu_cpl_error_message oErrHandler( CE_Failure );
         kdu_cpl_error_message oWarningHandler( CE_Warning );
-        
+
         kdu_customize_warnings(new kdu_cpl_error_message( CE_Warning ) );
         kdu_customize_errors(new kdu_cpl_error_message( CE_Failure ) );
     }
@@ -2228,25 +2250,25 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      What data type should we use?  We assume all datatypes match    */
 /*      the first band.                                                 */
 /* -------------------------------------------------------------------- */
-    GDALDataType eType;
     GDALRasterBand *poPrototypeBand = poSrcDS->GetRasterBand(1);
 
-    eType = poPrototypeBand->GetRasterDataType();
+    GDALDataType eType = poPrototypeBand->GetRasterDataType();
     if( eType != GDT_Byte && eType != GDT_Int16 && eType != GDT_UInt16
         && eType != GDT_Float32 )
     {
         if( bStrict )
         {
-            CPLError(CE_Failure, CPLE_AppDefined, 
-                     "JP2KAK (JPEG2000) driver does not support data type %s.",
-                     GDALGetDataTypeName( eType ) );
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "JP2KAK (JPEG2000) driver does not support data type %s.",
+                      GDALGetDataTypeName( eType ) );
             return NULL;
         }
 
-        CPLError(CE_Warning, CPLE_AppDefined, 
-                 "JP2KAK (JPEG2000) driver does not support data type %s, forcing to Float32.",
-                 GDALGetDataTypeName( eType ) );
-        
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "JP2KAK (JPEG2000) driver does not support data type %s, "
+                  "forcing to Float32.",
+                  GDALGetDataTypeName( eType ) );
+
         eType = GDT_Float32;
     }
 
@@ -2259,23 +2281,24 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      How many layers?                                                */
 /* -------------------------------------------------------------------- */
-    int      layer_count = 12;
+    int layer_count = 12;
 
     if( CSLFetchNameValue(papszOptions,"LAYERS") != NULL )
         layer_count = atoi(CSLFetchNameValue(papszOptions,"LAYERS"));
     else if( CSLFetchNameValue(papszOptions,"Clayers") != NULL )
         layer_count = atoi(CSLFetchNameValue(papszOptions,"Clayers"));
-    
+
 /* -------------------------------------------------------------------- */
-/*	Establish how many bytes of data we want for each layer.  	*/
-/*	We take the quality as a percentage, so if QUALITY of 50 is	*/
-/*	selected, we will set the base layer to 50% the default size.   */
-/*	We let the other layers be computed internally.                 */
+/*      Establish how many bytes of data we want for each layer.        */
+/*      We take the quality as a percentage, so if QUALITY of 50 is     */
+/*      selected, we will set the base layer to 50% the default size.   */
+/*      We let the other layers be computed internally.                 */
 /* -------------------------------------------------------------------- */
-    kdu_long *layer_bytes;
-    double   dfQuality = 20.0;
+    bool bReversible = false;
+    double dfQuality = 20.0;
 
-    layer_bytes = (kdu_long *) CPLCalloc(sizeof(kdu_long),layer_count);
+    kdu_long *layer_bytes = static_cast<kdu_long *>(
+        CPLCalloc(sizeof(kdu_long),layer_count) );
 
     if( CSLFetchNameValue(papszOptions,"QUALITY") != NULL )
     {
@@ -2291,17 +2314,20 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         return NULL;
     }
 
+    const int nXSize = poSrcDS->GetRasterXSize();
+    const int nYSize = poSrcDS->GetRasterYSize();
+
     if( dfQuality < 99.5 )
     {
-        double dfLayerBytes = 
-            (nXSize * ((double) nYSize) * dfQuality / 100.0);
+        double dfLayerBytes =
+            (nXSize * static_cast<double>(nYSize) * dfQuality / 100.0);
 
         dfLayerBytes *= (GDALGetDataTypeSize(eType) / 8);
         dfLayerBytes *= GDALGetRasterCount(poSrcDS);
 
         if( dfLayerBytes > 2000000000.0 && sizeof(kdu_long) == 4 )
         {
-            CPLError( CE_Warning, CPLE_AppDefined, 
+            CPLError( CE_Warning, CPLE_AppDefined,
                       "Trimmming maximum size of file 2GB from %.1fGB\n"
                       "to avoid overflow of kdu_long layer size.",
                       dfLayerBytes / 1000000000.0 );
@@ -2310,7 +2336,7 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
         layer_bytes[layer_count-1] = (kdu_long) dfLayerBytes;
 
-        CPLDebug( "JP2KAK", "layer_bytes[] = %g\n", 
+        CPLDebug( "JP2KAK", "layer_bytes[] = %g\n",
                   (double) layer_bytes[layer_count-1] );
     }
     else
@@ -2319,20 +2345,23 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Do we want to use more than one tile?                           */
 /* -------------------------------------------------------------------- */
+    int nTileXSize = nXSize;
+    int nTileYSize = nYSize;
+
     if( nTileXSize > 25000 )
     {
         // Don't generate tiles that are terrible wide by default, as
-        // they consume alot of memory for the compression engine.
+        // they consume a lot of memory for the compression engine.
         nTileXSize = 20000;
     }
 
-    if( (nTileYSize / TILE_CHUNK_SIZE) > 253) 
+    if( (nTileYSize / TILE_CHUNK_SIZE) > 253)
     {
         // We don't want to process a tile in more than 255 chunks as there
         // is a limit on the number of tile parts in a tile and we are likely
         // to flush out a tile part for each processing chunk.  If we might
         // go over try trimming our Y tile size such that we will get about
-        // 200 tile parts. 
+        // 200 tile parts.
         nTileYSize = 200 * TILE_CHUNK_SIZE;
     }
 
@@ -2357,13 +2386,13 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     if( nTileXSize > nXSize ) nTileXSize = nXSize;
     if( nTileYSize > nYSize ) nTileYSize = nYSize;
 
-    CPLDebug( "JP2KAK", "Final JPEG2000 Tile Size is %dP x %dL.", 
+    CPLDebug( "JP2KAK", "Final JPEG2000 Tile Size is %dP x %dL.",
               nTileXSize, nTileYSize );
-      
+
 /* -------------------------------------------------------------------- */
 /*      Do we want a comment segment emitted?                           */
 /* -------------------------------------------------------------------- */
-    bool bComseg;
+    bool bComseg = false;
 
     if( CSLFetchBoolean( papszOptions, "COMSEG", TRUE ) )
         bComseg = true;
@@ -2373,11 +2402,13 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Work out the precision.                                         */
 /* -------------------------------------------------------------------- */
-    if( CSLFetchNameValue( papszOptions, "NBITS" ) != NULL )
+    int nBits = 0;
+
+  if( CSLFetchNameValue( papszOptions, "NBITS" ) != NULL )
         nBits = atoi(CSLFetchNameValue(papszOptions,"NBITS"));
-    else if( poPrototypeBand->GetMetadataItem( "NBITS", "IMAGE_STRUCTURE" ) 
+    else if( poPrototypeBand->GetMetadataItem( "NBITS", "IMAGE_STRUCTURE" )
              != NULL )
-        nBits = atoi(poPrototypeBand->GetMetadataItem( "NBITS", 
+        nBits = atoi(poPrototypeBand->GetMetadataItem( "NBITS",
                                                        "IMAGE_STRUCTURE" ));
     else
         nBits = GDALGetDataTypeSize(eType);
@@ -2385,7 +2416,7 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Establish the general image parameters.                         */
 /* -------------------------------------------------------------------- */
-    siz_params  oSizeParams;
+    siz_params oSizeParams;
 
     oSizeParams.set( Scomponents, 0, 0, poSrcDS->GetRasterCount() );
     oSizeParams.set( Sdims, 0, 0, nYSize );
@@ -2400,34 +2431,34 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     {
         oSizeParams.set( Stiles, 0, 0, nTileYSize );
         oSizeParams.set( Stiles, 0, 1, nTileXSize );
-        
+
         CPLDebug( "JP2KAK", "Stiles=%d,%d", nTileYSize, nTileXSize );
     }
 
-    kdu_params *poSizeRef = &oSizeParams; poSizeRef->finalize();
+    kdu_params *poSizeRef = &oSizeParams;
+    poSizeRef->finalize();
 
 /* -------------------------------------------------------------------- */
 /*      Open output file, and setup codestream.                         */
 /* -------------------------------------------------------------------- */
-    jp2_family_tgt         family;
+    if( !pfnProgress( 0.0, NULL, pProgressData ) )
+        return NULL;
+
+    jp2_family_tgt family;
 #ifdef KAKADU_JPX
-    jpx_family_tgt         jpx_family;
-    jpx_target             jpx_out;
-    int			   bIsJPX = !EQUAL(CPLGetExtension(pszFilename),"jpf");
+    jpx_family_tgt jpx_family;
+    jpx_target jpx_out;
+    const bool bIsJPX = !EQUAL(CPLGetExtension(pszFilename),"jpf");
 #else
-    int                    bIsJPX = FALSE;
+    const bool bIsJPX = false;
 #endif
 
     kdu_compressed_target *poOutputFile = NULL;
-    jp2_target             jp2_out;
-    int                    bIsJP2 = !EQUAL(CPLGetExtension(pszFilename),"jpc")
-        && !bIsJPX;
-    kdu_codestream         oCodeStream;
+    jp2_target jp2_out;
+    const bool bIsJP2 = !EQUAL(CPLGetExtension(pszFilename),"jpc") && !bIsJPX;
+    kdu_codestream oCodeStream;
 
-    vsil_target            oVSILTarget;
-
-    if( !pfnProgress( 0.0, NULL, pProgressData ) )
-        return NULL;
+    vsil_target oVSILTarget;
 
     try
     {
@@ -2463,11 +2494,12 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Do we have a high res region of interest?                       */
 /* -------------------------------------------------------------------- */
-    kdu_roi_image  *poROIImage = NULL;
+    kdu_roi_image *poROIImage = NULL;
     char **papszROIDefs = CSLFetchNameValueMultiple( papszOptions, "ROI" );
-    int iROI;
-    
-    for( iROI = 0; papszROIDefs != NULL && papszROIDefs[iROI] != NULL; iROI++ )
+
+    for( int iROI = 0;
+         papszROIDefs != NULL && papszROIDefs[iROI] != NULL;
+         ++iROI )
     {
         kdu_dims region;
         char **papszTokens = CSLTokenizeStringComplex( papszROIDefs[iROI], ",",
@@ -2476,7 +2508,7 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         if( CSLCount(papszTokens) != 4 )
         {
             CPLError( CE_Warning, CPLE_AppDefined,
-                      "Skipping corrupt ROI def = \n%s", 
+                      "Skipping corrupt ROI def = \n%s",
                       papszROIDefs[iROI] );
             continue;
         }
@@ -2496,11 +2528,11 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      Set some particular parameters.                                 */
 /* -------------------------------------------------------------------- */
     oCodeStream.access_siz()->parse_string(
-        CPLString().Printf("Clayers=%d",layer_count).c_str());
+        CPLString().Printf("Clayers=%d", layer_count).c_str());
     oCodeStream.access_siz()->parse_string("Cycc=no");
     if( eType == GDT_Int16 || eType == GDT_UInt16 )
         oCodeStream.access_siz()->parse_string("Qstep=0.0000152588");
-        
+
     if( bReversible )
         oCodeStream.access_siz()->parse_string("Creversible=yes");
     else
@@ -2509,14 +2541,14 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Set some user-overridable parameters.                           */
 /* -------------------------------------------------------------------- */
-    int iParm;
-    const char *apszParms[] = 
-        { "Corder", "PCRL", 
-          "Cprecincts", "{512,512},{256,512},{128,512},{64,512},{32,512},{16,512},{8,512},{4,512},{2,512}",
-          "ORGgen_plt", "yes", 
+    const char *apszParms[] =
+        { "Corder", "PCRL",
+          "Cprecincts", "{512,512},{256,512},{128,512},{64,512},{32,512},"
+              "{16,512},{8,512},{4,512},{2,512}",
+          "ORGgen_plt", "yes",
           "ORGgen_tlm", NULL,
-          "Qguard", NULL, 
-          "Cmodes", NULL, 
+          "Qguard", NULL,
+          "Cmodes", NULL,
           "Clevels", NULL,
           "Cblk", NULL,
           "Rshift", NULL,
@@ -2525,11 +2557,11 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
           "Sprofile", NULL,
           NULL, NULL };
 
-    for( iParm = 0; apszParms[iParm] != NULL; iParm += 2 )
+    for( int iParm = 0; apszParms[iParm] != NULL; iParm += 2 )
     {
-        const char *pszValue = 
+        const char *pszValue =
             CSLFetchNameValue( papszOptions, apszParms[iParm] );
-        
+
         if( pszValue == NULL )
             pszValue = apszParms[iParm+1];
 
@@ -2568,17 +2600,18 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
     if( bIsJP2 )
     {
-        // Set dimensional information (all redundant with the SIZ marker segment)
+        // Set dimensional information.
+        // All redundant with the SIZ marker segment.
         jp2_dimensions dims = jp2_out.access_dimensions();
         dims.init(&oSizeParams);
-        
-        // Set colour space information (mandatory)
+
+        // Set colour space information (mandatory).
         jp2_colour colour = jp2_out.access_colour();
 
         if( bHaveCT || poSrcDS->GetRasterCount() == 3 )
             colour.init( JP2_sRGB_SPACE );
-        else if( poSrcDS->GetRasterCount() >= 4 
-                 && poSrcDS->GetRasterBand(4)->GetColorInterpretation() 
+        else if( poSrcDS->GetRasterCount() >= 4
+                 && poSrcDS->GetRasterBand(4)->GetColorInterpretation()
                  == GCI_AlphaBand )
         {
             colour.init( JP2_sRGB_SPACE );
@@ -2591,7 +2624,7 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             jp2_out.access_channels().set_opacity_mapping(2,3);
         }
         else if( poSrcDS->GetRasterCount() >= 2
-                 && poSrcDS->GetRasterBand(2)->GetColorInterpretation() 
+                 && poSrcDS->GetRasterBand(2)->GetColorInterpretation()
                  == GCI_AlphaBand )
         {
             colour.init( JP2_sLUM_SPACE );
@@ -2608,18 +2641,20 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             && poSrcDS->GetMetadataItem("TIFFTAG_RESOLUTIONUNIT") != NULL )
         {
             jp2_resolution res = jp2_out.access_resolution();
-            double dfXRes = 
+            double dfXRes =
                 CPLAtof(poSrcDS->GetMetadataItem("TIFFTAG_XRESOLUTION"));
-            double dfYRes = 
+            double dfYRes =
                 CPLAtof(poSrcDS->GetMetadataItem("TIFFTAG_YRESOLUTION"));
 
             if( atoi(poSrcDS->GetMetadataItem("TIFFTAG_RESOLUTIONUNIT")) == 2 )
             {
-                // convert pixels per inch to pixels per cm. 
-                dfXRes = dfXRes * 39.37 / 100.0;
-                dfYRes = dfYRes * 39.37 / 100.0;
+                // Convert pixels per inch to pixels per cm.
+                // TODO(schwehr): Change this to 1.0 / 2.54 if correct.
+                const double dfInchToCm = 39.37 / 100.0;
+                dfXRes *= dfInchToCm;
+                dfYRes *= dfInchToCm;
             }
-            
+
             // convert to pixels per meter.
             dfXRes *= 100.0;
             dfYRes *= 100.0;
@@ -2640,18 +2675,17 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
     if( bIsJP2 && bHaveCT )
     {
-        jp2_palette oJP2Palette;
-        GDALColorTable *poCT = poPrototypeBand->GetColorTable();
-        int  iColor, nCount = poCT->GetColorEntryCount();
-        kdu_int32 *panLUT = (kdu_int32 *) 
-            CPLMalloc(sizeof(kdu_int32) * nCount * 3);
-        
-        oJP2Palette = jp2_out.access_palette();
+        GDALColorTable * const poCT = poPrototypeBand->GetColorTable();
+        const int nCount = poCT->GetColorEntryCount();
+        kdu_int32 *panLUT = static_cast<kdu_int32 *>(
+            CPLMalloc(sizeof(kdu_int32) * nCount * 3) );
+
+        jp2_palette oJP2Palette = jp2_out.access_palette();
         oJP2Palette.init( 3, nCount );
 
-        for( iColor = 0; iColor < nCount; iColor++ )
+        for( int iColor = 0; iColor < nCount; iColor++ )
         {
-            GDALColorEntry sEntry;
+            GDALColorEntry sEntry = { 0, 0, 0, 0 };
 
             poCT->GetColorEntryAsRGB( iColor, &sEntry );
             panLUT[iColor + nCount * 0] = sEntry.c1;
@@ -2682,14 +2716,14 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      Set the GeoTIFF and GML boxes if georeferencing is available,   */
 /*      and this is a JP2 file.                                         */
 /* -------------------------------------------------------------------- */
-    double	adfGeoTransform[6];
+    double adfGeoTransform[6] = { 0.0 };
     if( bIsJP2
         && ((poSrcDS->GetGeoTransform(adfGeoTransform) == CE_None
-             && (adfGeoTransform[0] != 0.0 
-                 || adfGeoTransform[1] != 1.0 
-                 || adfGeoTransform[2] != 0.0 
-                 || adfGeoTransform[3] != 0.0 
-                 || adfGeoTransform[4] != 0.0 
+             && (adfGeoTransform[0] != 0.0
+                 || adfGeoTransform[1] != 1.0
+                 || adfGeoTransform[2] != 0.0
+                 || adfGeoTransform[3] != 0.0
+                 || adfGeoTransform[4] != 0.0
                  || ABS(adfGeoTransform[5]) != 1.0))
             || poSrcDS->GetGCPCount() > 0
             || poSrcDS->GetMetadata("RPC") != NULL) )
@@ -2709,14 +2743,20 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
         oJP2MD.SetRPCMD( poSrcDS->GetMetadata("RPC") );
 
-        const char* pszAreaOrPoint = poSrcDS->GetMetadataItem(GDALMD_AREA_OR_POINT);
-        oJP2MD.bPixelIsPoint = pszAreaOrPoint != NULL && EQUAL(pszAreaOrPoint, GDALMD_AOP_POINT);
+        const char* const pszAreaOrPoint =
+            poSrcDS->GetMetadataItem(GDALMD_AREA_OR_POINT);
+        oJP2MD.bPixelIsPoint =
+            pszAreaOrPoint != NULL && EQUAL(pszAreaOrPoint, GDALMD_AOP_POINT);
 
         if( CSLFetchBoolean( papszOptions, "GMLJP2", TRUE ) )
         {
-            const char* pszGMLJP2V2Def = CSLFetchNameValue( papszOptions, "GMLJP2V2_DEF" );
+            const char* pszGMLJP2V2Def =
+                CSLFetchNameValue( papszOptions, "GMLJP2V2_DEF" );
             if( pszGMLJP2V2Def != NULL )
-                JP2KAKWriteBox( &jp2_out, oJP2MD.CreateGMLJP2V2(nXSize,nYSize,pszGMLJP2V2Def,poSrcDS) );
+                JP2KAKWriteBox(
+                    &jp2_out,
+                    oJP2MD.CreateGMLJP2V2(
+                        nXSize,nYSize,pszGMLJP2V2Def,poSrcDS) );
             else
                 JP2KAKWriteBox( &jp2_out, oJP2MD.CreateGMLJP2(nXSize,nYSize) );
         }
@@ -2727,24 +2767,21 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Do we have any XML boxes we want to preserve?                   */
 /* -------------------------------------------------------------------- */
-    int iBox;
-    
-    for( iBox = 0; TRUE; iBox++ )
+
+    for( int iBox = 0; true; iBox++ )
     {
         CPLString oName;
-        char **papszMD;
-
         oName.Printf( "xml:BOX_%d", iBox );
-        papszMD = poSrcDS->GetMetadata( oName );
-        
+        char **papszMD = poSrcDS->GetMetadata( oName );
+
         if( papszMD == NULL || CSLCount(papszMD) != 1 )
             break;
 
         GDALJP2Box *poXMLBox = new GDALJP2Box();
 
         poXMLBox->SetType( "xml " );
-        poXMLBox->SetWritableData( strlen(papszMD[0])+1, 
-                                   (GByte *) papszMD[0] );
+        poXMLBox->SetWritableData( static_cast<int>(strlen(papszMD[0])+1),
+                                   reinterpret_cast<GByte *>( papszMD[0] ) );
         JP2KAKWriteBox( &jp2_out, poXMLBox );
     }
 
@@ -2758,17 +2795,18 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      Create one big tile, and a compressing engine, and line         */
 /*      buffer for each component.                                      */
 /* -------------------------------------------------------------------- */
-    int iTileXOff, iTileYOff;
     double dfPixelsDone = 0.0;
-    double dfPixelsTotal = nXSize * (double) nYSize;
-    
-    for( iTileYOff = 0; iTileYOff < nYSize; iTileYOff += nTileYSize )
+    const double dfPixelsTotal = nXSize * static_cast<double>( nYSize );
+    const int bFlushEnabled = CSLFetchBoolean( papszOptions, "FLUSH", TRUE );
+
+    for( int iTileYOff = 0; iTileYOff < nYSize; iTileYOff += nTileYSize )
     {
-        for( iTileXOff = 0; iTileXOff < nXSize; iTileXOff += nTileXSize )
+        for( int iTileXOff = 0; iTileXOff < nXSize; iTileXOff += nTileXSize )
         {
             kdu_tile oTile = oCodeStream.open_tile(
                 kdu_coords(iTileXOff/nTileXSize,iTileYOff/nTileYSize));
-            int nThisTileXSize, nThisTileYSize;
+            int nThisTileXSize = 0;
+            int nThisTileYSize = 0;
 
             // ---------------------------------------------------------------
             // Is this a partial tile on the right or bottom?
@@ -2776,7 +2814,7 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                 nThisTileXSize = nTileXSize;
             else
                 nThisTileXSize = nXSize - iTileXOff;
-    
+
             if( iTileYOff + nTileYSize < nYSize )
                 nThisTileYSize = nTileYSize;
             else
@@ -2785,21 +2823,20 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             // ---------------------------------------------------------------
             // Setup scaled progress monitor
 
-            void *pScaledProgressData;
-            double dfPixelsDoneAfter = 
+            double dfPixelsDoneAfter =
                 dfPixelsDone + (nThisTileXSize * (double) nThisTileYSize);
 
-            pScaledProgressData = 
+            void *pScaledProgressData =
                 GDALCreateScaledProgress( dfPixelsDone / dfPixelsTotal,
                                           dfPixelsDoneAfter / dfPixelsTotal,
                                           pfnProgress, pProgressData );
-            if( !JP2KAKCreateCopy_WriteTile( poSrcDS, oTile, poROIImage, 
-                                             iTileXOff, iTileYOff, 
-                                             nThisTileXSize, nThisTileYSize, 
-                                             bReversible, nBits, eType, 
+            if( !JP2KAKCreateCopy_WriteTile( poSrcDS, oTile, poROIImage,
+                                             iTileXOff, iTileYOff,
+                                             nThisTileXSize, nThisTileYSize,
+                                             bReversible, nBits, eType,
                                              oCodeStream, bFlushEnabled,
                                              layer_bytes, layer_count,
-                                             GDALScaledProgress, 
+                                             GDALScaledProgress,
                                              pScaledProgressData, bComseg ) )
             {
                 GDALDestroyScaledProgress( pScaledProgressData );
@@ -2816,7 +2853,7 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             oTile.close();
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Finish flushing out results.                                    */
 /* -------------------------------------------------------------------- */
@@ -2853,43 +2890,40 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 }
 
 /************************************************************************/
-/*                        GDALRegister_JP2KAK()				*/
+/*                        GDALRegister_JP2KAK()                         */
 /************************************************************************/
 
 void GDALRegister_JP2KAK()
 
 {
-    GDALDriver	*poDriver;
-    
-    if (! GDAL_CHECK_VERSION("JP2KAK driver"))
+    if( !GDAL_CHECK_VERSION( "JP2KAK driver" ) )
         return;
 
-    if( GDALGetDriverByName( "JP2KAK" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "JP2KAK" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "JPEG-2000 (based on Kakadu " 
-                                   KDU_CORE_VERSION ")" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_jp2kak.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte Int16 UInt16" );
-        poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/jp2" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jp2" );
-
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-        
-        poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST, 
+    if( GDALGetDriverByName( "JP2KAK" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "JP2KAK" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "JPEG-2000 (based on Kakadu "
+                               KDU_CORE_VERSION ")" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_jp2kak.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte Int16 UInt16" );
+    poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/jp2" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jp2" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
 "<OpenOptionList>"
 "   <Option name='1BIT_ALPHA_PROMOTION' type='boolean' description='Whether a 1-bit alpha channel should be promoted to 8-bit' default='YES'/>"
 "   <Option name='OPEN_REMOTE_GML' type='boolean' description='Whether to load remote vector layers referenced by a link in a GMLJP2 v2 box' default='NO'/>"
 "</OpenOptionList>" );
 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "   <Option name='QUALITY' type='integer' description='0.01-100, 100 is lossless'/>"
 "   <Option name='BLOCKXSIZE' type='int' description='Tile Width'/>"
@@ -2915,10 +2949,9 @@ void GDALRegister_JP2KAK()
 "   <Option name='Rweight' type='string'/>"
 "</CreationOptionList>" );
 
-        poDriver->pfnOpen = JP2KAKDataset::Open;
-        poDriver->pfnIdentify = JP2KAKDataset::Identify;
-        poDriver->pfnCreateCopy = JP2KAKCreateCopy;
+    poDriver->pfnOpen = JP2KAKDataset::Open;
+    poDriver->pfnIdentify = JP2KAKDataset::Identify;
+    poDriver->pfnCreateCopy = JP2KAKCreateCopy;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/jp2kak/makefile.vc b/frmts/jp2kak/makefile.vc
index 0df4db3..6a015f5 100644
--- a/frmts/jp2kak/makefile.vc
+++ b/frmts/jp2kak/makefile.vc
@@ -29,6 +29,11 @@ KAK_APPS_OBJ = $(KAK_APPS_OBJ) \
        $(OBJ_PREFIX)\render\$(OBJ_CONFIG)\ssse3_region_decompressor.obj \
 !ENDIF
 
+# TODO: add kdu_client_window.obj
+#!IFDEF KAKADU_7_7_OR_LATER
+#
+#!ENDIF
+
 OBJ	=	jp2kakdataset.obj
 EXTRAFLAGS = 	$(KAKINC) /DKDU_PENTIUM_MSVC /EHsc $(KAKFLAGS)
 
diff --git a/frmts/jp2kak/subfile_source.h b/frmts/jp2kak/subfile_source.h
index 731e226..5e50cd4 100644
--- a/frmts/jp2kak/subfile_source.h
+++ b/frmts/jp2kak/subfile_source.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: subfile_source.h 27787 2014-10-03 01:08:03Z rcoup $
+ * $Id: subfile_source.h 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  JPEG-2000
  * Purpose:  Implements read-only virtual io on a subregion of a file.
@@ -45,7 +45,7 @@
 
 class subfile_source : public kdu_compressed_source {
 
-  public: 
+  public:
     subfile_source() { file = NULL; }
     ~subfile_source() { close(); }
 
@@ -64,8 +64,8 @@ class subfile_source : public kdu_compressed_source {
               char** papszTokens = CSLTokenizeString2(fname + 12, ",", 0);
               if (CSLCount(papszTokens) >= 2)
               {
-                  subfile_offset = (int) CPLScanUIntBig(papszTokens[0], strlen(papszTokens[0]));
-                  subfile_size = (int) CPLScanUIntBig(papszTokens[1], strlen(papszTokens[1]));
+                  subfile_offset = (int) CPLScanUIntBig(papszTokens[0], static_cast<int>(strlen(papszTokens[0])));
+                  subfile_size = (int) CPLScanUIntBig(papszTokens[1], static_cast<int>(strlen(papszTokens[1])));
               }
               else
               {
@@ -93,14 +93,14 @@ class subfile_source : public kdu_compressed_source {
           {
               real_filename = fname;
               subfile_offset = 0;
-              subfile_size = 0; 
+              subfile_size = 0;
           }
 
           file = VSIFOpenL( real_filename, "r");
           if( file == NULL )
           {
               kdu_error e;
-              e << "Unable to open compressed data file, \"" << 
+              e << "Unable to open compressed data file, \"" <<
                   real_filename << "\"!";
               return;
           }
@@ -111,62 +111,50 @@ class subfile_source : public kdu_compressed_source {
               if( file == NULL )
               {
                   kdu_error e;
-                  e << "Unable to open compressed data file, \"" << 
+                  e << "Unable to open compressed data file, \"" <<
                       real_filename << "\"!";
                   return;
               }
           }
 
-          if( bSequential ) 
+          if( bSequential )
             capabilities = KDU_SOURCE_CAP_SEQUENTIAL;
           else
             capabilities = KDU_SOURCE_CAP_SEQUENTIAL | KDU_SOURCE_CAP_SEEKABLE;
 
-          seek_origin = subfile_offset;
           seek( 0 );
       }
 
     int get_capabilities() { return capabilities; }
 
     bool seek(kdu_long offset)
-      { 
+      {
           assert(file != NULL);
           if( file == NULL )
               return false;
-          
+
           if (!(capabilities & KDU_SOURCE_CAP_SEEKABLE))
               return false;
-          
-          if( VSIFSeekL( file, seek_origin+offset, SEEK_SET ) == 0 )
+
+          if( VSIFSeekL( file, subfile_offset+offset, SEEK_SET ) == 0 )
               return true;
           else
               return false;
       }
 
-    bool set_seek_origin(kdu_long position)
-      { 
-          if (!(capabilities & KDU_SOURCE_CAP_SEEKABLE))
-              return false;
-          seek_origin = position + subfile_offset;
-          return true;
-      }
-
-    kdu_long get_pos(bool absolute)
-      { 
+    kdu_long get_pos()
+      {
         if (file == NULL) return -1;
         kdu_long result = VSIFTellL( file );
-        if (!absolute) 
-            result -= seek_origin;
-        else
-            result -= subfile_offset;
+        result -= subfile_offset;
         return result;
       }
 
     int read(kdu_byte *buf, int num_bytes)
-      { 
+      {
         assert(file != NULL);
 
-        num_bytes = VSIFReadL(buf,1,(size_t) num_bytes,file);
+        num_bytes = static_cast<int>(VSIFReadL(buf,1,(size_t) num_bytes,file));
         return num_bytes;
       }
 
@@ -180,10 +168,9 @@ class subfile_source : public kdu_compressed_source {
 
   private: // Data
     int capabilities;
-    kdu_long seek_origin;
 
     int subfile_offset;
     int subfile_size;
-    
+
     VSILFILE *file;
   };
diff --git a/frmts/jp2kak/vsil_target.h b/frmts/jp2kak/vsil_target.h
index 0ae0daa..d7929ee 100644
--- a/frmts/jp2kak/vsil_target.h
+++ b/frmts/jp2kak/vsil_target.h
@@ -37,7 +37,7 @@
 
 class vsil_target : public kdu_compressed_target {
 
-public: 
+public:
     vsil_target() { file = NULL; }
     ~vsil_target() { close(); }
 
@@ -48,7 +48,7 @@ public:
             if( file == NULL )
             {
                 kdu_error e;
-                e << "Unable to open compressed data file, \"" << 
+                e << "Unable to open compressed data file, \"" <<
                     fname << "\"!";
                 return;
             }
@@ -58,7 +58,7 @@ public:
         {
             if( file == NULL )
                 return false;
-            
+
             if( (int) VSIFWriteL( buf, 1, num_bytes, file ) != num_bytes )
                 return false;
             else
@@ -98,4 +98,3 @@ public:
 private: // Data
     VSILFILE *file;
 };
-
diff --git a/frmts/jpeg/GNUmakefile b/frmts/jpeg/GNUmakefile
index 7a40ade..4cb2c31 100644
--- a/frmts/jpeg/GNUmakefile
+++ b/frmts/jpeg/GNUmakefile
@@ -30,14 +30,16 @@ OBJ :=	jcapimin12.o jcapistd12.o jccoefct12.o jccolor12.o jcdctmgr12.o jchuff12.
         jdpostct12.o jdsample12.o jdtrans12.o jerror12.o jfdctflt12.o jfdctfst12.o \
         jfdctint12.o jidctflt12.o jidctfst12.o jidctint12.o jidctred12.o jquant112.o \
         jquant212.o jutils12.o jmemmgr12.o jmemansi12.o \
-	$(OBJ) jpgdataset_12.o 
+        $(OBJ) jpgdataset_12.o vsidataio_12.o
 endif
 
-CPPFLAGS	:=	$(XTRA_OPT)  $(CPPFLAGS) -I../mem
+CPPFLAGS	:=	$(XTRA_OPT)  $(CPPFLAGS) -I../mem -DENABLE_LIBJPEG_NO_RETURN
+# # Enable this to compile with -Wextra -Werror and get around the jump complaint.
+# CPPFLAGS += -Wno-clobbered
 
 default:	install-obj
 
-$(O_OBJ): jpgdataset.cpp
+$(O_OBJ): jpgdataset.cpp vsidataio.cpp
 
 clean:
 	rm -f *.o $(O_OBJ) libjpeg12/*.c libjpeg12/*.h
diff --git a/frmts/jpeg/frmt_jpeg.html b/frmts/jpeg/frmt_jpeg.html
index fe8d546..09e623a 100644
--- a/frmts/jpeg/frmt_jpeg.html
+++ b/frmts/jpeg/frmt_jpeg.html
@@ -8,23 +8,24 @@
 <h1>JPEG -- JPEG JFIF File Format</h1>
 
 The JPEG JFIF format is supported for reading, and batch writing, but not
-update in place.  JPEG files are represented as one band (greyscale) or three 
+update in place.  JPEG files are represented as one band (greyscale) or three
 band (RGB) datasets with Byte valued bands.<p>
 
 The driver will automatically convert images whose color space is YCbCr, CMYK or
 YCbCrK to RGB, unless GDAL_JPEG_TO_RGB is set to NO (YES is the default). When
 color space translation to RGB is done, the source color space is indicated in the
-SOURCE_COLOR_SPACE metedata of the IMAGE_STRUCTURE domain.<p>
-
-There is currently no support for georeferencing information or metadata for
-JPEG files. But if an ESRI world file exists with the .jgw, .jpgw/.jpegw or 
-.wld suffixes, it will be read and used to establish the geotransform for 
-the image. If available a MapInfo .tab file will also be used for 
-georeferencing.  Overviews can be built for JPEG files as an external 
+SOURCE_COLOR_SPACE metadata of the IMAGE_STRUCTURE domain.<p>
+
+EXIF metadata can be read from JPEG files (but this will not result in a
+georeferenced image even if the EXIF_GPSLatitude and EXIF_GPSLongitude tags are
+set). But if an ESRI world file exists with the .jgw, .jpgw/.jpegw or
+.wld suffixes, it will be read and used to establish the geotransform for
+the image. If available a MapInfo .tab file will also be used for
+georeferencing.  Overviews can be built for JPEG files as an external
 .ovr file.<p>
 
-The driver also supports the "zlib compressed mask appended to the file" 
-approach used by a few data providers to add a bitmask to identify pixels that 
+The driver also supports the "zlib compressed mask appended to the file"
+approach used by a few data providers to add a bitmask to identify pixels that
 are not valid data.
 See <a href="http://trac.osgeo.org/gdal/wiki/rfc15_nodatabitmask">RFC 15</a> for further details.<p>
 
@@ -68,8 +69,8 @@ used as overviews, and generated by GDAL.<p>
 <h2>Error management</h2>
 
 While decoding, libjpeg has resiliency towards some errors in the JPEG datastream and will
-try to recover from them as much of possible. Starting with GDAL 1.11.2, 
-such errors will be reported as GDAL Warnings, but can optionaly be considered
+try to recover from them as much of possible. Starting with GDAL 1.11.2,
+such errors will be reported as GDAL Warnings, but can optionally be considered
 as true Errors by setting the GDAL_ERROR_ON_LIBJPEG_WARNING configuration option
 to TRUE.
 
@@ -146,4 +147,3 @@ taken into account if EXIF_THUMBNAIL=YES.<p>
 
 </body>
 </html>
-
diff --git a/frmts/jpeg/jpgdataset.cpp b/frmts/jpeg/jpgdataset.cpp
index 60edbff..b74b8b8 100644
--- a/frmts/jpeg/jpgdataset.cpp
+++ b/frmts/jpeg/jpgdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: jpgdataset.cpp 29267 2015-05-29 20:47:00Z rouault $
+ * $Id: jpgdataset.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  JPEG JFIF Driver
  * Purpose:  Implement GDAL JPEG Support based on IJG libjpeg.
@@ -31,23 +31,26 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
+#undef ENABLE_LIBJPEG_NO_RETURN
+
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
 #include "gdalexif.h"
 #include "memdataset.h"
 
 #include <setjmp.h>
 
-#define TIFF_VERSION            42
+static const int TIFF_VERSION = 42;
 
-#define TIFF_BIGENDIAN          0x4d4d
-#define TIFF_LITTLEENDIAN       0x4949
+static const int TIFF_BIGENDIAN = 0x4d4d;
+static const int TIFF_LITTLEENDIAN = 0x4949;
 
-#define JPEG_TIFF_IMAGEWIDTH        0x100
-#define JPEG_TIFF_IMAGEHEIGHT       0x101
-#define JPEG_TIFF_COMPRESSION       0x103
-#define JPEG_EXIF_JPEGIFOFSET       0x201
-#define JPEG_EXIF_JPEGIFBYTECOUNT   0x202
+static const int JPEG_TIFF_IMAGEWIDTH      = 0x100;
+static const int JPEG_TIFF_IMAGEHEIGHT     = 0x101;
+static const int JPEG_TIFF_COMPRESSION     = 0x103;
+static const int JPEG_EXIF_JPEGIFOFSET     = 0x201;
+static const int JPEG_EXIF_JPEGIFBYTECOUNT = 0x202;
 /*
  * TIFF header.
  */
@@ -57,10 +60,10 @@ typedef struct {
         GUInt32  tiff_diroff;    /* byte offset to first directory */
 } TIFFHeader;
 
-CPL_CVSID("$Id: jpgdataset.cpp 29267 2015-05-29 20:47:00Z rouault $");
+CPL_CVSID("$Id: jpgdataset.cpp 33808 2016-03-29 21:15:28Z goatbar $");
 
 CPL_C_START
-#ifdef LIBJPEG_12_PATH 
+#ifdef LIBJPEG_12_PATH
 #  include LIBJPEG_12_PATH
 #else
 #  include "jpeglib.h"
@@ -72,12 +75,19 @@ CPL_C_END
 #  pragma warning(disable:4611)
 #endif
 
+typedef struct
+{
+    const char* pszFilename;
+    VSILFILE* fpLin;
+    char** papszSiblingFiles;
+    int nScaleFactor;
+    int bDoPAMInitialize;
+    int bUseInternalOverviews;
+} JPGDatasetOpenArgs;
+
+
 #if defined(JPEG_DUAL_MODE_8_12) && !defined(JPGDataset)
-GDALDataset* JPEGDataset12Open(const char* pszFilename,
-                               VSILFILE* fpLin,
-                               char** papszSiblingFiles,
-                               int nScaleFactor,
-                               int bDoPAMInitialize);
+GDALDataset* JPEGDataset12Open(JPGDatasetOpenArgs* psArgs);
 GDALDataset* JPEGDataset12CreateCopy( const char * pszFilename,
                                     GDALDataset *poSrcDS,
                                     int bStrict, char ** papszOptions,
@@ -85,16 +95,12 @@ GDALDataset* JPEGDataset12CreateCopy( const char * pszFilename,
                                     void * pProgressData );
 #endif
 
-CPL_C_START
-void	GDALRegister_JPEG(void);
-CPL_C_END
-
 #include "vsidataio.h"
 
-/*  
-* Do we want to do special processing suitable for when JSAMPLE is a 
-* 16bit value?   
-*/ 
+/*
+* Do we want to do special processing suitable for when JSAMPLE is a
+* 16bit value?
+*/
 #if defined(JPEG_LIB_MK1)
 #  define JPEG_LIB_MK1_OR_12BIT 1
 #elif BITS_IN_JSAMPLE == 12
@@ -104,27 +110,36 @@ CPL_C_END
 class JPGDatasetCommon;
 GDALRasterBand* JPGCreateBand(JPGDatasetCommon* poDS, int nBand);
 
+typedef void (*my_jpeg_write_m_header) (void* cinfo, int marker, unsigned int datalen);
+typedef void (*my_jpeg_write_m_byte) (void* cinfo, int val);
+
 CPLErr JPGAppendMask( const char *pszJPGFilename, GDALRasterBand *poMask,
                       GDALProgressFunc pfnProgress, void * pProgressData );
 void   JPGAddEXIFOverview( GDALDataType eWorkDT,
                            GDALDataset* poSrcDS, char** papszOptions,
-                           j_compress_ptr cinfo,
-                           void (*p_jpeg_write_m_header) (j_compress_ptr cinfo, int marker, unsigned int datalen),
-                           void (*p_jpeg_write_m_byte) (j_compress_ptr cinfo, int val),
-                           GDALDataset *(pCreateCopy)( const char *, GDALDataset *, 
+                           void* cinfo,
+                           my_jpeg_write_m_header p_jpeg_write_m_header,
+                           my_jpeg_write_m_byte p_jpeg_write_m_byte,
+                           GDALDataset *(pCreateCopy)( const char *, GDALDataset *,
                                      int, char **,
-                                     GDALProgressFunc pfnProgress, 
+                                     GDALProgressFunc pfnProgress,
                                      void * pProgressData ) );
-void JPGAddICCProfile( struct jpeg_compress_struct *pInfo,
+void JPGAddICCProfile( void *pInfo,
                        const char *pszICCProfile,
-                       void (*p_jpeg_write_m_header) (j_compress_ptr cinfo, int marker, unsigned int datalen),
-                       void (*p_jpeg_write_m_byte) (j_compress_ptr cinfo, int val));
+                       my_jpeg_write_m_header p_jpeg_write_m_header,
+                       my_jpeg_write_m_byte p_jpeg_write_m_byte);
 
-typedef struct
+typedef struct GDALJPEGErrorStruct
 {
     jmp_buf     setjmp_buffer;
     int         bNonFatalErrorEncountered;
     void      (*p_previous_emit_message)(j_common_ptr cinfo, int msg_level);
+    GDALJPEGErrorStruct() :
+        bNonFatalErrorEncountered(FALSE),
+        p_previous_emit_message(NULL)
+    {
+        memset(&setjmp_buffer, 0, sizeof(setjmp_buffer));
+    }
 } GDALJPEGErrorStruct;
 
 /************************************************************************/
@@ -142,9 +157,6 @@ protected:
     friend class JPGRasterBand;
     friend class JPGMaskBand;
 
-    GDALJPEGErrorStruct sErrorStruct;
-    int           ErrorOutOnNonFatalError();
-
     int           nScaleFactor;
     int           bHasInitInternalOverviews;
     int           nInternalOverviewsCurrent;
@@ -154,9 +166,9 @@ protected:
     GDALDataset*  InitEXIFOverview();
 
     char   *pszProjection;
-    int	   bGeoTransformValid;
+    int    bGeoTransformValid;
     double adfGeoTransform[6];
-    int	   nGCPCount;
+    int    nGCPCount;
     GDAL_GCP *pasGCPList;
 
     VSILFILE   *fpImage;
@@ -170,11 +182,11 @@ protected:
     int    bHasReadICCMetadata;
     char   **papszMetadata;
     char   **papszSubDatasets;
-    int	   bigendian;
+    int    bigendian;
     int    nExifOffset;
     int    nInterOffset;
     int    nGPSOffset;
-    int	   bSwabflag;
+    int    bSwabflag;
     int    nTiffDirStart;
     int    nTIFFHEADER;
     int    bHasDoneJpegCreateDecompress;
@@ -203,8 +215,9 @@ protected:
     GByte  *pabyCMask;
     int    nCMaskSize;
 
-    J_COLOR_SPACE eGDALColorSpace;   /* color space exposed by GDAL. Not necessarily the in_color_space nor */
-                                     /* the out_color_space of JPEG library */
+    // Color space exposed by GDAL.  Not necessarily the in_color_space nor
+    // the out_color_space of JPEG library.
+    J_COLOR_SPACE eGDALColorSpace;
 
     int    bIsSubfile;
     int    bHasTriedLoadWorldFileOrTab;
@@ -212,13 +225,13 @@ protected:
     CPLString osWldFilename;
 
     virtual int         CloseDependentDatasets();
-    
+
     virtual CPLErr IBuildOverviews( const char *, int, int *,
                                     int, int *, GDALProgressFunc, void * );
 
   public:
                  JPGDatasetCommon();
-                 ~JPGDatasetCommon();
+    virtual ~JPGDatasetCommon();
 
     virtual CPLErr      IRasterIO( GDALRWFlag, int, int, int, int,
                                    void *, int, int, GDALDataType,
@@ -244,8 +257,6 @@ protected:
 
     static int          Identify( GDALOpenInfo * );
     static GDALDataset *Open( GDALOpenInfo * );
-
-    static void EmitMessage(j_common_ptr cinfo, int msg_level);
 };
 
 /************************************************************************/
@@ -256,6 +267,12 @@ protected:
 
 class JPGDataset : public JPGDatasetCommon
 {
+    GDALJPEGErrorStruct sErrorStruct;
+
+    int           ErrorOutOnNonFatalError();
+
+    static void EmitMessage(j_common_ptr cinfo, int msg_level);
+
     struct jpeg_decompress_struct sDInfo;
     struct jpeg_error_mgr sJErr;
 
@@ -272,13 +289,9 @@ class JPGDataset : public JPGDatasetCommon
 
   public:
                  JPGDataset();
-                 ~JPGDataset();
+    virtual ~JPGDataset();
 
-    static GDALDataset *Open( const char* pszFilename,
-                              VSILFILE* fpLin,
-                              char** papszSiblingFiles,
-                              int nScaleFactor,
-                              int bDoPAMInitialize );
+    static GDALDataset *Open( JPGDatasetOpenArgs* psArgs );
     static GDALDataset* CreateCopy( const char * pszFilename,
                                     GDALDataset *poSrcDS,
                                     int bStrict, char ** papszOptions,
@@ -307,15 +320,15 @@ class JPGRasterBand : public GDALPamRasterBand
     JPGDatasetCommon   *poGDS;
 
   public:
-
                    JPGRasterBand( JPGDatasetCommon *, int );
+    virtual ~JPGRasterBand() {}
 
     virtual CPLErr IReadBlock( int, int, void * );
     virtual GDALColorInterp GetColorInterpretation();
 
     virtual GDALRasterBand *GetMaskBand();
     virtual int             GetMaskFlags();
-    
+
     virtual GDALRasterBand *GetOverview(int i);
     virtual int             GetOverviewCount();
 };
@@ -334,7 +347,8 @@ class JPGMaskBand : public GDALRasterBand
     virtual CPLErr IReadBlock( int, int, void * );
 
   public:
-		JPGMaskBand( JPGDataset *poDS );
+                JPGMaskBand( JPGDataset *poDS );
+    virtual ~JPGMaskBand() {}
 };
 
 /************************************************************************/
@@ -395,7 +409,8 @@ void JPGDatasetCommon::ReadEXIFMetadata()
 /*                        ReadXMPMetadata()                             */
 /************************************************************************/
 
-/* See §2.1.3 of http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/XMPSpecificationPart3.pdf */
+// See §2.1.3 of
+// http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/XMPSpecificationPart3.pdf
 
 void JPGDatasetCommon::ReadXMPMetadata()
 {
@@ -408,16 +423,18 @@ void JPGDatasetCommon::ReadXMPMetadata()
 /* -------------------------------------------------------------------- */
 /*      Search for APP1 chunk.                                          */
 /* -------------------------------------------------------------------- */
-    GByte abyChunkHeader[2+2+29];
+    // TODO(schwehr): What are these constants?
+    GByte abyChunkHeader[2+2+29] = { 0 };
     int nChunkLoc = 2;
     int bFoundXMP = FALSE;
 
-    for( ; TRUE; )
+    while(true)
     {
         if( VSIFSeekL( fpImage, nChunkLoc, SEEK_SET ) != 0 )
             break;
 
-        if( VSIFReadL( abyChunkHeader, sizeof(abyChunkHeader), 1, fpImage ) != 1 )
+        if( VSIFReadL( abyChunkHeader, sizeof(abyChunkHeader), 1, fpImage )
+            != 1 )
             break;
 
         nChunkLoc += 2 + abyChunkHeader[2] * 256 + abyChunkHeader[3];
@@ -430,7 +447,8 @@ void JPGDatasetCommon::ReadXMPMetadata()
             break; // Not an APP chunk.
 
         if( abyChunkHeader[1] == 0xe1
-            && strncmp((const char *) abyChunkHeader + 4,"http://ns.adobe.com/xap/1.0/",28) == 0 )
+            && STARTS_WITH(reinterpret_cast<char *>(abyChunkHeader) + 4,
+                           "http://ns.adobe.com/xap/1.0/") )
         {
             bFoundXMP = TRUE;
             break; // APP1 - XMP
@@ -439,10 +457,10 @@ void JPGDatasetCommon::ReadXMPMetadata()
 
     if (bFoundXMP)
     {
-        int nXMPLength = abyChunkHeader[2] * 256 + abyChunkHeader[3];
+        const int nXMPLength = abyChunkHeader[2] * 256 + abyChunkHeader[3];
         if (nXMPLength > 2 + 29)
         {
-            char* pszXMP = (char*)VSIMalloc(nXMPLength - 2 - 29 + 1);
+          char* pszXMP = static_cast<char*>(VSIMalloc(nXMPLength - 2 - 29 + 1));
             if (pszXMP)
             {
                 if (VSIFReadL( pszXMP, nXMPLength - 2 - 29, 1, fpImage ) == 1)
@@ -452,9 +470,7 @@ void JPGDatasetCommon::ReadXMPMetadata()
                     /* Avoid setting the PAM dirty bit just for that */
                     int nOldPamFlags = nPamFlags;
 
-                    char *apszMDList[2];
-                    apszMDList[0] = pszXMP;
-                    apszMDList[1] = NULL;
+                    char *apszMDList[2] = { pszXMP, NULL };
                     SetMetadata(apszMDList, "xml:XMP");
 
                     nPamFlags = nOldPamFlags;
@@ -503,14 +519,14 @@ char  **JPGDatasetCommon::GetMetadata( const char * pszDomain )
 /*                       GetMetadataItem()                              */
 /************************************************************************/
 const char *JPGDatasetCommon::GetMetadataItem( const char * pszName,
-                                         const char * pszDomain )
+                                               const char * pszDomain )
 {
     if (fpImage == NULL)
         return NULL;
     if (eAccess == GA_ReadOnly && !bHasReadEXIFMetadata &&
         (pszDomain == NULL || EQUAL(pszDomain, "")) &&
         pszName != NULL &&
-        (EQUAL(pszName, "COMMENT") || EQUALN(pszName, "EXIF_", 5)))
+        (EQUAL(pszName, "COMMENT") || STARTS_WITH_CI(pszName, "EXIF_")))
         ReadEXIFMetadata();
     if (eAccess == GA_ReadOnly && !bHasReadICCMetadata &&
         pszDomain != NULL && EQUAL(pszDomain, "COLOR_PROFILE"))
@@ -533,25 +549,23 @@ void JPGDatasetCommon::ReadICCProfile()
 
     int nTotalSize = 0;
     int nChunkCount = -1;
-    int anChunkSize[256];
-    char *apChunk[256];
-
-    memset(anChunkSize, 0, 256 * sizeof(int));
-    memset(apChunk, 0, 256 * sizeof(char*));
+    int anChunkSize[256] = { 0 };
+    char *apChunk[256] = { NULL };
 
 /* -------------------------------------------------------------------- */
 /*      Search for APP2 chunk.                                          */
 /* -------------------------------------------------------------------- */
-    GByte abyChunkHeader[18];
+    GByte abyChunkHeader[18] = { 0 };
     int nChunkLoc = 2;
     bool bOk = true;
 
-    for( ; TRUE; ) 
+    while(true)
     {
         if( VSIFSeekL( fpImage, nChunkLoc, SEEK_SET ) != 0 )
             break;
 
-        if( VSIFReadL( abyChunkHeader, sizeof(abyChunkHeader), 1, fpImage ) != 1 )
+        if( VSIFReadL( abyChunkHeader, sizeof(abyChunkHeader), 1, fpImage )
+            != 1 )
             break;
 
         if( abyChunkHeader[0] != 0xFF )
@@ -570,7 +584,8 @@ void JPGDatasetCommon::ReadICCProfile()
         int nChunkLength = abyChunkHeader[2] * 256 + abyChunkHeader[3];
 
         if( abyChunkHeader[1] == 0xe2
-            && memcmp((const char *) abyChunkHeader + 4,"ICC_PROFILE\0",12) == 0 )
+            && memcmp( reinterpret_cast<char *>(abyChunkHeader) + 4,
+                       "ICC_PROFILE\0",12) == 0 )
         {
             /* Get length and segment ID */
             /* Header: */
@@ -579,9 +594,9 @@ void JPGDatasetCommon::ReadICCProfile()
             /* ICC_PROFILE\0 tag: 12 bytes */
             /* Segment index: 1 bytes */
             /* Total segments: 1 bytes */
-            int nICCChunkLength = nChunkLength - 16;
-            int nICCChunkID = abyChunkHeader[16];
-            int nICCMaxChunkID = abyChunkHeader[17];
+            const int nICCChunkLength = nChunkLength - 16;
+            const int nICCChunkID = abyChunkHeader[16];
+            const int nICCMaxChunkID = abyChunkHeader[17];
 
             if (nChunkCount == -1)
                 nChunkCount = nICCMaxChunkID;
@@ -593,8 +608,9 @@ void JPGDatasetCommon::ReadICCProfile()
                 break;
             }
 
-            /* Check that no segment ID is larger than the total segment count */
-            if ((nICCChunkID > nChunkCount) || (nICCChunkID == 0) || (nChunkCount == 0)) 
+            // Check that no segment ID is larger than the total segment count.
+            if( (nICCChunkID > nChunkCount) || (nICCChunkID == 0) ||
+                (nChunkCount == 0) )
             {
                 bOk = false;
                 break;
@@ -608,10 +624,12 @@ void JPGDatasetCommon::ReadICCProfile()
             }
 
             /* Load it */
-            apChunk[nICCChunkID-1] = (char*)VSIMalloc(nICCChunkLength);
+            apChunk[nICCChunkID-1]
+                = static_cast<char*>(VSIMalloc(nICCChunkLength));
             anChunkSize[nICCChunkID-1] = nICCChunkLength;
 
-            if( VSIFReadL( apChunk[nICCChunkID-1], nICCChunkLength, 1, fpImage ) != 1 )
+            if( VSIFReadL( apChunk[nICCChunkID-1], nICCChunkLength, 1, fpImage )
+                != 1 )
             {
                 bOk = false;
                 break;
@@ -631,7 +649,6 @@ void JPGDatasetCommon::ReadICCProfile()
                 /* Missing segment... abort */
                 bOk = false;
                 break;
-                
             }
             nTotalSize += anChunkSize[i];
         }
@@ -640,7 +657,7 @@ void JPGDatasetCommon::ReadICCProfile()
     /* Merge all segments together and set metadata */
     if (bOk && nChunkCount > 0)
     {
-        char *pBuffer = (char*)VSIMalloc(nTotalSize);
+        char *pBuffer = static_cast<char*>(VSIMalloc(nTotalSize));
         char *pBufferPtr = pBuffer;
         for(int i = 0; i < nChunkCount; i++)
         {
@@ -649,7 +666,8 @@ void JPGDatasetCommon::ReadICCProfile()
         }
 
         /* Escape the profile */
-        char *pszBase64Profile = CPLBase64Encode(nTotalSize, (const GByte*)pBuffer);
+        char *pszBase64Profile =
+            CPLBase64Encode( nTotalSize, reinterpret_cast<GByte *>(pBuffer) );
 
         /* Avoid setting the PAM dirty bit just for that */
         int nOldPamFlags = nPamFlags;
@@ -680,44 +698,44 @@ void JPGDatasetCommon::ReadICCProfile()
 /************************************************************************/
 int JPGDatasetCommon::EXIFInit(VSILFILE *fp)
 {
-    int           one = 1;
-    TIFFHeader    hdr;
-    
     if( nTiffDirStart == 0 )
         return FALSE;
     else if( nTiffDirStart > 0 )
         return TRUE;
     nTiffDirStart = 0;
-  
-    bigendian = (*(char *)&one == 0);
+
+    // TODO: Do a compile time endian check.
+    int one = 1;
+    bigendian = (*reinterpret_cast<char *>(&one) == 0);
 
 /* -------------------------------------------------------------------- */
 /*      Search for APP1 chunk.                                          */
 /* -------------------------------------------------------------------- */
-    GByte abyChunkHeader[10];
+    GByte abyChunkHeader[10] = { 0 };
     int nChunkLoc = 2;
 
-    for( ; TRUE; ) 
+    while(true)
     {
         if( VSIFSeekL( fp, nChunkLoc, SEEK_SET ) != 0 )
             return FALSE;
 
         if( VSIFReadL( abyChunkHeader, sizeof(abyChunkHeader), 1, fp ) != 1 )
             return FALSE;
-        
+
         int nChunkLength = abyChunkHeader[2] * 256 + abyChunkHeader[3];
         // COM marker
         if( abyChunkHeader[0] == 0xFF && abyChunkHeader[1] == 0xFE &&
             nChunkLength >= 2 )
         {
-            char* pszComment = (char*)CPLMalloc(nChunkLength - 2 + 1);
+            char* pszComment =
+                static_cast<char*>(CPLMalloc(nChunkLength - 2 + 1));
             if( nChunkLength > 2 &&
                 VSIFSeekL( fp, nChunkLoc + 4, SEEK_SET ) == 0 &&
                 VSIFReadL(pszComment, nChunkLength - 2, 1, fp) == 1 )
             {
                 pszComment[nChunkLength-2] = 0;
                 /* Avoid setting the PAM dirty bit just for that */
-                int nOldPamFlags = nPamFlags;
+                const int nOldPamFlags = nPamFlags;
                 /* Set ICC profile metadata */
                 SetMetadataItem( "COMMENT", pszComment );
                 nPamFlags = nOldPamFlags;
@@ -726,12 +744,12 @@ int JPGDatasetCommon::EXIFInit(VSILFILE *fp)
         }
         else
         {
-            if( abyChunkHeader[0] != 0xFF 
+            if( abyChunkHeader[0] != 0xFF
                 || (abyChunkHeader[1] & 0xf0) != 0xe0 )
                 break; // Not an APP chunk.
 
             if( abyChunkHeader[1] == 0xe1
-                && strncmp((const char *) abyChunkHeader + 4,"Exif",4) == 0 )
+                && STARTS_WITH((const char *) abyChunkHeader + 4, "Exif") )
             {
                 nTIFFHEADER = nChunkLoc + 10;
             }
@@ -739,19 +757,21 @@ int JPGDatasetCommon::EXIFInit(VSILFILE *fp)
 
         nChunkLoc += 2 + nChunkLength;
     }
-    
+
     if( nTIFFHEADER < 0 )
         return FALSE;
 
 /* -------------------------------------------------------------------- */
 /*      Read TIFF header                                                */
 /* -------------------------------------------------------------------- */
+    TIFFHeader hdr = { 0, 0, 0 };
+
     VSIFSeekL(fp, nTIFFHEADER, SEEK_SET);
-    if(VSIFReadL(&hdr,1,sizeof(hdr),fp) != sizeof(hdr)) 
+    if( VSIFReadL(&hdr, 1, sizeof(hdr), fp) != sizeof(hdr) )
     {
         CPLError( CE_Failure, CPLE_FileIO,
                   "Failed to read %d byte from image header.",
-                  (int) sizeof(hdr));
+                  static_cast<int>( sizeof(hdr) ) );
                   return FALSE;
     }
 
@@ -759,25 +779,23 @@ int JPGDatasetCommon::EXIFInit(VSILFILE *fp)
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Not a TIFF file, bad magic number %u (%#x)",
-                  hdr.tiff_magic, hdr.tiff_magic);
+                  hdr.tiff_magic, hdr.tiff_magic );
         return FALSE;
     }
 
     if (hdr.tiff_magic == TIFF_BIGENDIAN)    bSwabflag = !bigendian;
     if (hdr.tiff_magic == TIFF_LITTLEENDIAN) bSwabflag = bigendian;
 
-
     if (bSwabflag) {
         CPL_SWAP16PTR(&hdr.tiff_version);
         CPL_SWAP32PTR(&hdr.tiff_diroff);
     }
 
-
     if (hdr.tiff_version != TIFF_VERSION)
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Not a TIFF file, bad version number %u (%#x)",
-                 hdr.tiff_version, hdr.tiff_version); 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Not a TIFF file, bad version number %u (%#x)",
+                  hdr.tiff_version, hdr.tiff_version );
         return FALSE;
     }
     nTiffDirStart = hdr.tiff_diroff;
@@ -794,10 +812,10 @@ int JPGDatasetCommon::EXIFInit(VSILFILE *fp)
 /*                            JPGMaskBand()                             */
 /************************************************************************/
 
-JPGMaskBand::JPGMaskBand( JPGDataset *poDS )
+JPGMaskBand::JPGMaskBand( JPGDataset *poDSIn )
 
 {
-    this->poDS = poDS;
+    poDS = poDSIn;
     nBand = 0;
 
     nRasterXSize = poDS->GetRasterXSize();
@@ -812,9 +830,9 @@ JPGMaskBand::JPGMaskBand( JPGDataset *poDS )
 /*                             IReadBlock()                             */
 /************************************************************************/
 
-CPLErr JPGMaskBand::IReadBlock( CPL_UNUSED int nBlockX, int nBlockY, void *pImage )
+CPLErr JPGMaskBand::IReadBlock( int /* nBlockX */, int nBlockY, void *pImage )
 {
-    JPGDataset *poJDS = (JPGDataset *) poDS;
+    JPGDataset *poJDS = static_cast<JPGDataset *>( poDS );
 
 /* -------------------------------------------------------------------- */
 /*      Make sure the mask is loaded and decompressed.                  */
@@ -826,28 +844,28 @@ CPLErr JPGMaskBand::IReadBlock( CPL_UNUSED int nBlockX, int nBlockY, void *pImag
 /* -------------------------------------------------------------------- */
 /*      Set mask based on bitmask for this scanline.                    */
 /* -------------------------------------------------------------------- */
-    int iX;
-    GUInt32 iBit = (GUInt32)nBlockY * (GUInt32)nBlockXSize;
+    GUInt32 iBit =
+        static_cast<GUInt32>(nBlockY) * static_cast<GUInt32>(nBlockXSize);
 
     if( poJDS->bMaskLSBOrder )
     {
-        for( iX = 0; iX < nBlockXSize; iX++ )
+        for( int iX = 0; iX < nBlockXSize; iX++ )
         {
             if( poJDS->pabyBitMask[iBit>>3] & (0x1 << (iBit&7)) )
-                ((GByte *) pImage)[iX] = 255;
+                reinterpret_cast<GByte *>(pImage)[iX] = 255;
             else
-                ((GByte *) pImage)[iX] = 0;
+                reinterpret_cast<GByte *>(pImage)[iX] = 0;
             iBit++;
         }
     }
     else
     {
-        for( iX = 0; iX < nBlockXSize; iX++ )
+        for( int iX = 0; iX < nBlockXSize; iX++ )
         {
             if( poJDS->pabyBitMask[iBit>>3] & (0x1 << (7 - (iBit&7))) )
-                ((GByte *) pImage)[iX] = 255;
+                reinterpret_cast<GByte *>(pImage)[iX] = 255;
             else
-                ((GByte *) pImage)[iX] = 0;
+                reinterpret_cast<GByte *>(pImage)[iX] = 0;
             iBit++;
         }
     }
@@ -859,21 +877,21 @@ CPLErr JPGMaskBand::IReadBlock( CPL_UNUSED int nBlockX, int nBlockY, void *pImag
 /*                           JPGRasterBand()                            */
 /************************************************************************/
 
-JPGRasterBand::JPGRasterBand( JPGDatasetCommon *poDS, int nBand )
-
+JPGRasterBand::JPGRasterBand( JPGDatasetCommon *poDSIn, int nBandIn ) :
+    poGDS(poDSIn)
 {
-    this->poDS = poGDS = poDS;
+    poDS = poDSIn;
 
-    this->nBand = nBand;
-    if( poDS->GetDataPrecision() == 12 )
+    nBand = nBandIn;
+    if( poDSIn->GetDataPrecision() == 12 )
         eDataType = GDT_UInt16;
     else
         eDataType = GDT_Byte;
 
-    nBlockXSize = poDS->nRasterXSize;;
+    nBlockXSize = poDSIn->nRasterXSize;
     nBlockYSize = 1;
 
-    GDALMajorObject::SetMetadataItem("COMPRESSION","JPEG","IMAGE_STRUCTURE");
+    GDALMajorObject::SetMetadataItem("COMPRESSION", "JPEG", "IMAGE_STRUCTURE");
 }
 
 /************************************************************************/
@@ -893,12 +911,10 @@ CPLErr JPGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                   void * pImage )
 
 {
-    CPLErr      eErr;
-    int         nXSize = GetXSize();
-    int         nWordSize = GDALGetDataTypeSize(eDataType) / 8;
-    
     CPLAssert( nBlockXOff == 0 );
 
+    const int nXSize = GetXSize();
+    const int nWordSize = GDALGetDataTypeSize(eDataType) / 8;
     if (poGDS->fpImage == NULL)
     {
         memset( pImage, 0, nXSize * nWordSize );
@@ -908,18 +924,18 @@ CPLErr JPGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
 /*      Load the desired scanline into the working buffer.              */
 /* -------------------------------------------------------------------- */
-    eErr = poGDS->LoadScanline( nBlockYOff );
+    CPLErr eErr = poGDS->LoadScanline( nBlockYOff );
     if( eErr != CE_None )
         return eErr;
 
 /* -------------------------------------------------------------------- */
-/*      Transfer between the working buffer the the callers buffer.     */
+/*      Transfer between the working buffer the callers buffer.         */
 /* -------------------------------------------------------------------- */
     if( poGDS->GetRasterCount() == 1 )
     {
-#ifdef JPEG_LIB_MK1_OR_12BIT
-        GDALCopyWords( poGDS->pabyScanline, GDT_UInt16, 2, 
-                       pImage, eDataType, nWordSize, 
+#ifdef JPEG_LIB_MK1
+        GDALCopyWords( poGDS->pabyScanline, GDT_UInt16, 2,
+                       pImage, eDataType, nWordSize,
                        nXSize );
 #else
         memcpy( pImage, poGDS->pabyScanline, nXSize * nWordSize );
@@ -927,73 +943,72 @@ CPLErr JPGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     }
     else
     {
-#ifdef JPEG_LIB_MK1_OR_12BIT
-        GDALCopyWords( poGDS->pabyScanline + (nBand-1) * 2, 
-                       GDT_UInt16, 6, 
-                       pImage, eDataType, nWordSize, 
+#ifdef JPEG_LIB_MK1
+        GDALCopyWords( poGDS->pabyScanline + (nBand-1) * 2,
+                       GDT_UInt16, 6,
+                       pImage, eDataType, nWordSize,
                        nXSize );
 #else
         if (poGDS->eGDALColorSpace == JCS_RGB &&
-            poGDS->GetOutColorSpace() == JCS_CMYK)
+            poGDS->GetOutColorSpace() == JCS_CMYK &&
+            eDataType == GDT_Byte)
         {
-            CPLAssert(eDataType == GDT_Byte);
-            int i;
             if (nBand == 1)
             {
-                for(i=0;i<nXSize;i++)
+                for( int i=0; i < nXSize; i++ )
                 {
-                    int C = poGDS->pabyScanline[i * 4 + 0];
-                    int K = poGDS->pabyScanline[i * 4 + 3];
-                    ((GByte*)pImage)[i] = (GByte) ((C * K) / 255);
+                    const int C = poGDS->pabyScanline[i * 4 + 0];
+                    const int K = poGDS->pabyScanline[i * 4 + 3];
+                    reinterpret_cast<GByte *>(pImage)[i] =
+                        static_cast<GByte>( (C * K) / 255 );
                 }
             }
-            else  if (nBand == 2)
+            else if (nBand == 2)
             {
-                for(i=0;i<nXSize;i++)
+                for( int i=0; i < nXSize; i++ )
                 {
-                    int M = poGDS->pabyScanline[i * 4 + 1];
-                    int K = poGDS->pabyScanline[i * 4 + 3];
-                    ((GByte*)pImage)[i] = (GByte) ((M * K) / 255);
+                    const int M = poGDS->pabyScanline[i * 4 + 1];
+                    const int K = poGDS->pabyScanline[i * 4 + 3];
+                    reinterpret_cast<GByte*>(pImage)[i] =
+                        static_cast<GByte>( (M * K) / 255 );
                 }
             }
             else if (nBand == 3)
             {
-                for(i=0;i<nXSize;i++)
+                for( int i=0; i < nXSize; i++ )
                 {
-                    int Y = poGDS->pabyScanline[i * 4 + 2];
-                    int K = poGDS->pabyScanline[i * 4 + 3];
-                    ((GByte*)pImage)[i] = (GByte) ((Y * K) / 255);
+                    const int Y = poGDS->pabyScanline[i * 4 + 2];
+                    const int K = poGDS->pabyScanline[i * 4 + 3];
+                    reinterpret_cast<GByte *>(pImage)[i] =
+                        static_cast<GByte>( (Y * K) / 255 );
                 }
             }
         }
         else
         {
-            GDALCopyWords( poGDS->pabyScanline + (nBand-1) * nWordSize, 
-                        eDataType, nWordSize * poGDS->GetRasterCount(), 
-                        pImage, eDataType, nWordSize, 
+            GDALCopyWords( poGDS->pabyScanline + (nBand-1) * nWordSize,
+                        eDataType, nWordSize * poGDS->GetRasterCount(),
+                        pImage, eDataType, nWordSize,
                         nXSize );
         }
 #endif
     }
 
 /* -------------------------------------------------------------------- */
-/*      Forceably load the other bands associated with this scanline.   */
+/*      Forcibly load the other bands associated with this scanline.    */
 /* -------------------------------------------------------------------- */
     if( nBand == 1 )
     {
-        GDALRasterBlock *poBlock;
-
-        int iBand;
-        for(iBand = 2; iBand <= poGDS->GetRasterCount() ; iBand++)
+        for( int iBand = 2; iBand <= poGDS->GetRasterCount() ; iBand++ )
         {
-            poBlock = 
-                poGDS->GetRasterBand(iBand)->GetLockedBlockRef(nBlockXOff,nBlockYOff);
+            GDALRasterBlock * const poBlock
+                = poGDS->GetRasterBand(iBand)->
+                    GetLockedBlockRef(nBlockXOff, nBlockYOff);
             if( poBlock != NULL )
                 poBlock->DropLock();
         }
     }
 
-
     return CE_None;
 }
 
@@ -1015,7 +1030,7 @@ GDALColorInterp JPGRasterBand::GetColorInterpretation()
         else if( nBand == 2 )
             return GCI_GreenBand;
 
-        else 
+        else
             return GCI_BlueBand;
     }
     else if( poGDS->eGDALColorSpace == JCS_CMYK)
@@ -1047,11 +1062,9 @@ GDALColorInterp JPGRasterBand::GetColorInterpretation()
         else
             return GCI_BlackBand;
     }
-    else
-    {
-        CPLAssert(0);
-        return GCI_Undefined;
-    }
+
+    CPLAssert(0);
+    return GCI_Undefined;
 }
 
 /************************************************************************/
@@ -1069,7 +1082,7 @@ GDALRasterBand *JPGRasterBand::GetMaskBand()
 
     if( !poGDS->bHasCheckedForMask)
     {
-        if( CSLTestBoolean(CPLGetConfigOption("JPEG_READ_MASK", "YES")))
+        if( CPLTestBool(CPLGetConfigOption("JPEG_READ_MASK", "YES")))
             poGDS->CheckForMask();
         poGDS->bHasCheckedForMask = TRUE;
     }
@@ -1080,8 +1093,8 @@ GDALRasterBand *JPGRasterBand::GetMaskBand()
 
         return poGDS->poMaskBand;
     }
-    else
-        return GDALPamRasterBand::GetMaskBand();
+
+    return GDALPamRasterBand::GetMaskBand();
 }
 
 /************************************************************************/
@@ -1100,8 +1113,8 @@ int JPGRasterBand::GetMaskFlags()
     GetMaskBand();
     if( poGDS->poMaskBand != NULL )
         return GMF_PER_DATASET;
-    else
-        return GDALPamRasterBand::GetMaskFlags();
+
+    return GDALPamRasterBand::GetMaskFlags();
 }
 
 /************************************************************************/
@@ -1117,8 +1130,8 @@ GDALRasterBand* JPGRasterBand::GetOverview(int i)
 
     if( i < 0 || i >= poGDS->nInternalOverviewsCurrent )
         return NULL;
-    else
-        return poGDS->papoInternalOverviews[i]->GetRasterBand(nBand);
+
+    return poGDS->papoInternalOverviews[i]->GetRasterBand(nBand);
 }
 
 /************************************************************************/
@@ -1141,59 +1154,50 @@ int JPGRasterBand::GetOverviewCount()
 /* ==================================================================== */
 /************************************************************************/
 
-JPGDatasetCommon::JPGDatasetCommon()
-
+JPGDatasetCommon::JPGDatasetCommon() :
+    nScaleFactor(1),
+    bHasInitInternalOverviews(FALSE),
+    nInternalOverviewsCurrent(0),
+    nInternalOverviewsToFree(0),
+    papoInternalOverviews(NULL),
+    pszProjection(NULL),
+    bGeoTransformValid(FALSE),
+    nGCPCount(0),
+    pasGCPList(NULL),
+    fpImage(NULL),
+    nSubfileOffset(0),
+    nLoadedScanline(-1),
+    pabyScanline(NULL),
+    bHasReadEXIFMetadata(FALSE),
+    bHasReadXMPMetadata(FALSE),
+    bHasReadICCMetadata(FALSE),
+    papszMetadata(NULL),
+    papszSubDatasets(NULL),
+    bigendian(1),
+    nExifOffset(-1),
+    nInterOffset(-1),
+    nGPSOffset(-1),
+    bSwabflag(FALSE),
+    nTiffDirStart(-1),
+    nTIFFHEADER(-1),
+    bHasDoneJpegCreateDecompress(FALSE),
+    bHasDoneJpegStartDecompress(FALSE),
+    bHasCheckedForMask(FALSE),
+    poMaskBand(NULL),
+    pabyBitMask(NULL),
+    bMaskLSBOrder(TRUE),
+    pabyCMask(NULL),
+    nCMaskSize(0),
+    eGDALColorSpace(JCS_UNKNOWN),
+    bIsSubfile(FALSE),
+    bHasTriedLoadWorldFileOrTab(FALSE)
 {
-    fpImage = NULL;
-
-    nScaleFactor = 1;
-    bHasInitInternalOverviews = FALSE;
-    nInternalOverviewsCurrent = 0;
-    nInternalOverviewsToFree = 0;
-    papoInternalOverviews = NULL;
-
-    pabyScanline = NULL;
-    nLoadedScanline = -1;
-
-    bHasReadEXIFMetadata = FALSE;
-    bHasReadXMPMetadata = FALSE;
-    bHasReadICCMetadata = FALSE;
-    papszMetadata   = NULL;
-    papszSubDatasets= NULL;
-    nExifOffset     = -1;
-    nInterOffset    = -1;
-    nGPSOffset      = -1;
-    nTiffDirStart   = -1;
-    nTIFFHEADER     = -1;
-
-    pszProjection = NULL;
-    bGeoTransformValid = FALSE;
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
-    nGCPCount = 0;
-    pasGCPList = NULL;
-
-    bHasDoneJpegCreateDecompress = FALSE;
-    bHasDoneJpegStartDecompress = FALSE;
-
-    bHasCheckedForMask = FALSE;
-    poMaskBand = NULL;
-    pabyBitMask = NULL;
-    bMaskLSBOrder = TRUE;
-    pabyCMask = NULL;
-    nCMaskSize = 0;
-
-    eGDALColorSpace = JCS_UNKNOWN;
-
-    bIsSubfile = FALSE;
-    bHasTriedLoadWorldFileOrTab = FALSE;
-
-    sErrorStruct.bNonFatalErrorEncountered = FALSE;
-    sErrorStruct.p_previous_emit_message = NULL;
 }
 
 /************************************************************************/
@@ -1256,16 +1260,17 @@ GDALDataset* JPGDatasetCommon::InitEXIFOverview()
     if( !EXIFInit(fpImage) )
         return NULL;
 
-    GUInt16 nEntryCount;
 /* -------------------------------------------------------------------- */
 /*      Read number of entry in directory                               */
 /* -------------------------------------------------------------------- */
-    if( VSIFSeekL(fpImage, nTiffDirStart+nTIFFHEADER, SEEK_SET) != 0
+    GUInt16 nEntryCount = 0;
+    if( nTiffDirStart > INT_MAX - nTIFFHEADER ||
+        VSIFSeekL(fpImage, nTiffDirStart+nTIFFHEADER, SEEK_SET) != 0
         || VSIFReadL(&nEntryCount,1,sizeof(GUInt16),fpImage) != sizeof(GUInt16) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                "Error reading EXIF Directory count at %d.",
-                nTiffDirStart + nTIFFHEADER );
+                "Error reading EXIF Directory count at " CPL_FRMT_GUIB,
+                 static_cast<vsi_l_offset>(nTiffDirStart) + nTIFFHEADER );
         return NULL;
     }
 
@@ -1282,11 +1287,12 @@ GDALDataset* JPGDatasetCommon::InitEXIFOverview()
     }
 
     // Skip EXIF entries
-    VSIFSeekL(fpImage, nEntryCount * sizeof(TIFFDirEntry), SEEK_CUR );
+    VSIFSeekL( fpImage, nEntryCount * sizeof(GDALEXIFTIFFDirEntry), SEEK_CUR );
 
     // Read offset of next directory (IFD1)
-    GUInt32 nNextDirOff;
-    if( VSIFReadL(&nNextDirOff, 1, sizeof(GUInt32), fpImage) != sizeof(GUInt32) )
+    GUInt32 nNextDirOff = 0;
+    if( VSIFReadL(&nNextDirOff, 1, sizeof(GUInt32), fpImage) !=
+        sizeof(GUInt32) )
         return NULL;
     if( bSwabflag )
         CPL_SWAP32PTR(&nNextDirOff);
@@ -1294,15 +1300,15 @@ GDALDataset* JPGDatasetCommon::InitEXIFOverview()
         return NULL;
 
     // Seek to IFD1
-    if( VSIFSeekL(fpImage, nTIFFHEADER+nNextDirOff, SEEK_SET) != 0
-        || VSIFReadL(&nEntryCount,1,sizeof(GUInt16),fpImage) != sizeof(GUInt16) )
+    if( VSIFSeekL(fpImage, nTIFFHEADER+nNextDirOff, SEEK_SET) != 0 ||
+        VSIFReadL(&nEntryCount,1,sizeof(GUInt16),fpImage) != sizeof(GUInt16) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                "Error reading IFD1 Directory count at %d.",
-                nTIFFHEADER + nNextDirOff );
+                  "Error reading IFD1 Directory count at %d.",
+                  nTIFFHEADER + nNextDirOff );
         return NULL;
     }
-    
+
     if (bSwabflag)
         TIFFSwabShort(&nEntryCount);
     if( nEntryCount > 125 )
@@ -1314,14 +1320,18 @@ GDALDataset* JPGDatasetCommon::InitEXIFOverview()
     }
     /* CPLDebug("JPEG", "IFD1 entry count = %d", nEntryCount); */
 
-    int nImageWidth = 0, nImageHeight = 0, nCompression = 6;
-    GUInt32 nJpegIFOffset = 0, nJpegIFByteCount = 0;
+    int nImageWidth = 0;
+    int nImageHeight = 0;
+    int nCompression = 6;
+    GUInt32 nJpegIFOffset = 0;
+    GUInt32 nJpegIFByteCount = 0;
     for( int i = 0; i < nEntryCount; i ++ )
     {
-        TIFFDirEntry sEntry;
+        GDALEXIFTIFFDirEntry sEntry;
         if( VSIFReadL(&sEntry,1,sizeof(sEntry),fpImage) != sizeof(sEntry) )
         {
-            CPLError( CE_Warning, CPLE_AppDefined, "Cannot read entry %d of IFD1",
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Cannot read entry %d of IFD1",
                       i );
             return NULL;
         }
@@ -1332,8 +1342,13 @@ GDALDataset* JPGDatasetCommon::InitEXIFOverview()
             TIFFSwabLong (&sEntry.tdir_count);
             TIFFSwabLong (&sEntry.tdir_offset);
         }
-        /*CPLDebug("JPEG", "tag = %d (0x%4X), type = %d, count = %d, offset = %d",
-                 sEntry.tdir_tag, sEntry.tdir_tag, sEntry.tdir_type, sEntry.tdir_count, sEntry.tdir_offset );*/
+
+#ifdef DEBUG_VERBOSE
+        CPLDebug( "JPEG",
+                  "tag = %d (0x%4X), type = %d, count = %d, offset = %d",
+                  sEntry.tdir_tag, sEntry.tdir_tag, sEntry.tdir_type,
+                  sEntry.tdir_count, sEntry.tdir_offset );
+#endif
 
         if( (sEntry.tdir_type == TIFF_SHORT || sEntry.tdir_type == TIFF_LONG) &&
             sEntry.tdir_count == 1 )
@@ -1365,14 +1380,24 @@ GDALDataset* JPGDatasetCommon::InitEXIFOverview()
         nImageHeight >= nRasterYSize ||
         nJpegIFOffset == 0 ||
         nJpegIFOffset > 0xFFFFFFFFU - nTIFFHEADER ||
-        (int)nJpegIFByteCount <= 0 )
+        static_cast<int>(nJpegIFByteCount) <= 0 )
     {
         return NULL;
     }
 
-    const char* pszSubfile = CPLSPrintf("JPEG_SUBFILE:%u,%d,%s",
-                            nTIFFHEADER + nJpegIFOffset, nJpegIFByteCount, GetDescription());
-    return JPGDataset::Open(pszSubfile, NULL, NULL, 1, FALSE);
+    const char* pszSubfile =
+        CPLSPrintf( "JPEG_SUBFILE:%u,%d,%s",
+                    nTIFFHEADER + nJpegIFOffset,
+                    nJpegIFByteCount,
+                    GetDescription() );
+    JPGDatasetOpenArgs sArgs;
+    sArgs.pszFilename = pszSubfile;
+    sArgs.fpLin = NULL;
+    sArgs.papszSiblingFiles = NULL;
+    sArgs.nScaleFactor = 1;
+    sArgs.bDoPAMInitialize = FALSE;
+    sArgs.bUseInternalOverviews = FALSE;
+    return JPGDataset::Open(&sArgs);
 }
 
 /************************************************************************/
@@ -1386,7 +1411,7 @@ void JPGDatasetCommon::InitInternalOverviews()
     bHasInitInternalOverviews = TRUE;
 
 /* -------------------------------------------------------------------- */
-/*      Instanciate on-the-fly overviews (if no external ones).         */
+/*      Instantiate on-the-fly overviews (if no external ones).         */
 /* -------------------------------------------------------------------- */
     if( nScaleFactor == 1 && GetRasterBand(1)->GetOverviewCount() == 0 )
     {
@@ -1407,26 +1432,26 @@ void JPGDatasetCommon::InitInternalOverviews()
                 }
                 else
                 {
-                    CPLDebug("JPEG", "EXIF overview (%d x %d) detected",
-                            poEXIFOverview->GetRasterXSize(),
-                            poEXIFOverview->GetRasterYSize());
+                    CPLDebug( "JPEG", "EXIF overview (%d x %d) detected",
+                              poEXIFOverview->GetRasterXSize(),
+                              poEXIFOverview->GetRasterYSize() );
                 }
             }
             VSIFSeekL( fpImage, nCurOffset, SEEK_SET );
         }
 
-        /* libjpeg-6b only suppports 2, 4 and 8 scale denominators */
+        /* libjpeg-6b only supports 2, 4 and 8 scale denominators */
         /* TODO: Later versions support more */
 
-        int i;
         int nImplicitOverviews = 0;
 
         /* For the needs of the implicit JPEG-in-TIFF overview mechanism */
-        if( CSLTestBoolean(CPLGetConfigOption("JPEG_FORCE_INTERNAL_OVERVIEWS", "NO")) )
+        if( CPLTestBool(
+               CPLGetConfigOption("JPEG_FORCE_INTERNAL_OVERVIEWS", "NO")) )
             nImplicitOverviews = 3;
         else
         {
-            for(i = 2; i >= 0; i--)
+            for( int i = 2; i >= 0; i--)
             {
                 if( nRasterXSize >= (256 << i) || nRasterYSize >= (256 << i) )
                 {
@@ -1438,33 +1463,44 @@ void JPGDatasetCommon::InitInternalOverviews()
 
         if( nImplicitOverviews > 0 )
         {
-            papoInternalOverviews = (GDALDataset**)
-                    CPLMalloc((nImplicitOverviews + (poEXIFOverview ? 1 : 0)) * sizeof(GDALDataset*));
-            for(i = 0; i < nImplicitOverviews; i++ )
+            papoInternalOverviews = static_cast<GDALDataset **>(
+                CPLMalloc(
+                    (nImplicitOverviews + (poEXIFOverview ? 1 : 0))
+                    * sizeof(GDALDataset*)) );
+            for( int i = 0; i < nImplicitOverviews; i++ )
             {
                 if( poEXIFOverview != NULL &&
                     poEXIFOverview->GetRasterXSize() >= nRasterXSize >> (i + 1) )
                 {
                     break;
                 }
-                GDALDataset* poImplicitOverview =
-                    JPGDataset::Open(GetDescription(), NULL, NULL, 1 << (i + 1), FALSE);
+                JPGDatasetOpenArgs sArgs;
+                sArgs.pszFilename = GetDescription();
+                sArgs.fpLin = NULL;
+                sArgs.papszSiblingFiles = NULL;
+                sArgs.nScaleFactor = 1 << (i + 1);
+                sArgs.bDoPAMInitialize = FALSE;
+                sArgs.bUseInternalOverviews = FALSE;
+                GDALDataset* poImplicitOverview = JPGDataset::Open(&sArgs);
                 if( poImplicitOverview == NULL )
                     break;
-                papoInternalOverviews[nInternalOverviewsCurrent] = poImplicitOverview;
+                papoInternalOverviews[nInternalOverviewsCurrent] =
+                    poImplicitOverview;
                 nInternalOverviewsCurrent ++;
                 nInternalOverviewsToFree ++;
             }
             if( poEXIFOverview != NULL )
             {
-                papoInternalOverviews[nInternalOverviewsCurrent] = poEXIFOverview;
+                papoInternalOverviews[nInternalOverviewsCurrent] =
+                    poEXIFOverview;
                 nInternalOverviewsCurrent ++;
                 nInternalOverviewsToFree ++;
             }
         }
         else if( poEXIFOverview )
         {
-            papoInternalOverviews = (GDALDataset**) CPLMalloc(sizeof(GDALDataset*));
+            papoInternalOverviews =
+                static_cast<GDALDataset**>( CPLMalloc(sizeof(GDALDataset*)) );
             papoInternalOverviews[0] = poEXIFOverview;
             nInternalOverviewsCurrent ++;
             nInternalOverviewsToFree ++;
@@ -1476,42 +1512,23 @@ void JPGDatasetCommon::InitInternalOverviews()
 /*                          IBuildOverviews()                           */
 /************************************************************************/
 
-CPLErr JPGDatasetCommon::IBuildOverviews( const char *pszResampling, 
+CPLErr JPGDatasetCommon::IBuildOverviews( const char *pszResampling,
                                           int nOverviewsListCount,
-                                          int *panOverviewList, 
+                                          int *panOverviewList,
                                           int nListBands, int *panBandList,
-                                          GDALProgressFunc pfnProgress, 
+                                          GDALProgressFunc pfnProgress,
                                           void * pProgressData )
 {
-    CPLErr eErr;
-
     bHasInitInternalOverviews = TRUE;
     nInternalOverviewsCurrent = 0;
 
-    eErr = GDALPamDataset::IBuildOverviews(pszResampling,
+    return GDALPamDataset::IBuildOverviews(pszResampling,
                                            nOverviewsListCount,
                                            panOverviewList,
                                            nListBands, panBandList,
                                            pfnProgress, pProgressData);
-
-    return eErr;
-}
-
-/************************************************************************/
-/*                      ErrorOutOnNonFatalError()                       */
-/************************************************************************/
-
-int JPGDatasetCommon::ErrorOutOnNonFatalError()
-{
-    if( sErrorStruct.bNonFatalErrorEncountered )
-    {
-        sErrorStruct.bNonFatalErrorEncountered = FALSE;
-        return TRUE;
-    }
-    return FALSE;
 }
 
-
 /************************************************************************/
 /*                           FlushCache()                               */
 /************************************************************************/
@@ -1537,10 +1554,13 @@ void JPGDatasetCommon::FlushCache()
 /*                            JPGDataset()                              */
 /************************************************************************/
 
-JPGDataset::JPGDataset()
-
+JPGDataset::JPGDataset() :
+    nQLevel(0)
 {
+    memset(&sDInfo, 0, sizeof(sDInfo));
     sDInfo.data_precision = 8;
+
+    memset(&sJErr, 0, sizeof(sJErr));
 }
 
 /************************************************************************/
@@ -1563,6 +1583,20 @@ JPGDataset::~JPGDataset()
 }
 
 /************************************************************************/
+/*                      ErrorOutOnNonFatalError()                       */
+/************************************************************************/
+
+int JPGDataset::ErrorOutOnNonFatalError()
+{
+    if( sErrorStruct.bNonFatalErrorEncountered )
+    {
+        sErrorStruct.bNonFatalErrorEncountered = FALSE;
+        return TRUE;
+    }
+    return FALSE;
+}
+
+/************************************************************************/
 /*                            LoadScanline()                            */
 /************************************************************************/
 
@@ -1573,7 +1607,7 @@ CPLErr JPGDataset::LoadScanline( int iLine )
         return CE_None;
 
     // setup to trap a fatal error.
-    if (setjmp(sErrorStruct.setjmp_buffer)) 
+    if (setjmp(sErrorStruct.setjmp_buffer))
         return CE_Failure;
 
     if (!bHasDoneJpegStartDecompress)
@@ -1603,8 +1637,8 @@ CPLErr JPGDataset::LoadScanline( int iLine )
                 CPLAssert(0);
         }
 
-        pabyScanline = (GByte *)
-            CPLMalloc(nJPEGBands * GetRasterXSize() * 2);
+        pabyScanline = static_cast<GByte *>(
+            CPLMalloc(nJPEGBands * GetRasterXSize() * 2) );
     }
 
     if( iLine < nLoadedScanline )
@@ -1612,12 +1646,10 @@ CPLErr JPGDataset::LoadScanline( int iLine )
         if( Restart() != CE_None )
             return CE_Failure;
     }
-        
+
     while( nLoadedScanline < iLine )
     {
-        JSAMPLE	*ppSamples;
-            
-        ppSamples = (JSAMPLE *) pabyScanline;
+        JSAMPLE *ppSamples = reinterpret_cast<JSAMPLE *>( pabyScanline );
         jpeg_read_scanlines( &sDInfo, &ppSamples, 1 );
         if( ErrorOutOnNonFatalError() )
             return CE_Failure;
@@ -1645,7 +1677,7 @@ CPLErr JPGDataset::LoadScanline( int iLine )
 
 static const GByte Q1table[64] =
 {
-   8,    72,  72,  72,  72,  72,  72,  72, // 0 - 7
+    8,    72,  72,  72,  72,  72,  72,  72, // 0 - 7
     72,   72,  78,  74,  76,  74,  78,  89, // 8 - 15
     81,   84,  84,  81,  89, 106,  93,  94, // 16 - 23
     99,   94,  93, 106, 129, 111, 108, 116, // 24 - 31
@@ -1667,27 +1699,27 @@ static const GByte Q2table[64] =
 static const GByte Q3table[64] =
 {
      8, 10, 10, 10,
-    10, 10, 10, 10, 10, 10, 11, 10, 11, 10, 11, 13, 11, 12, 12, 11, 13, 15, 
-    13, 13, 14, 13, 13, 15, 18, 16, 15, 16, 16, 15, 16, 18, 19, 18, 19, 21, 
-    19, 18, 19, 22, 23, 25, 25, 23, 22, 27, 30, 32, 30, 27, 36, 40, 40, 36, 
-    50, 53, 50, 68, 68, 91 
-}; 
+    10, 10, 10, 10, 10, 10, 11, 10, 11, 10, 11, 13, 11, 12, 12, 11, 13, 15,
+    13, 13, 14, 13, 13, 15, 18, 16, 15, 16, 16, 15, 16, 18, 19, 18, 19, 21,
+    19, 18, 19, 22, 23, 25, 25, 23, 22, 27, 30, 32, 30, 27, 36, 40, 40, 36,
+    50, 53, 50, 68, 68, 91
+};
 
 static const GByte Q4table[64] =
 {
     8, 7, 7, 7,
-    7, 7, 7, 7, 7, 7, 8, 7, 8, 7, 8, 9, 8, 8, 8, 8, 9, 11, 
-    9, 9, 10, 9, 9, 11, 13, 11, 11, 12, 12, 11, 11, 13, 14, 13, 14, 15, 
-    14, 13, 14, 16, 16, 18, 18, 16, 16, 20, 22, 23, 22, 20, 26, 29, 29, 26, 
+    7, 7, 7, 7, 7, 7, 8, 7, 8, 7, 8, 9, 8, 8, 8, 8, 9, 11,
+    9, 9, 10, 9, 9, 11, 13, 11, 11, 12, 12, 11, 11, 13, 14, 13, 14, 15,
+    14, 13, 14, 16, 16, 18, 18, 16, 16, 20, 22, 23, 22, 20, 26, 29, 29, 26,
     36, 38, 36, 49, 49, 65
 };
 
 static const GByte Q5table[64] =
 {
-    4, 4, 4, 4, 
+    4, 4, 4, 4,
     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6,
-    5, 5, 6, 5, 5, 6, 7, 6, 6, 6, 6, 6, 6, 7, 8, 7, 8, 8, 
-    8, 7, 8, 9, 9, 10, 10, 9, 9, 11, 12, 13, 12, 11, 14, 16, 16, 14, 
+    5, 5, 6, 5, 5, 6, 7, 6, 6, 6, 6, 6, 6, 7, 8, 7, 8, 8,
+    8, 7, 8, 9, 9, 10, 10, 9, 9, 11, 12, 13, 12, 11, 14, 16, 16, 14,
     20, 21, 20, 27, 27, 36
 };
 
@@ -1695,7 +1727,7 @@ static const GByte AC_BITS[16] =
 { 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 125 };
 
 static const GByte AC_HUFFVAL[256] = {
-    0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,          
+    0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
     0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
     0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08,
     0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0,
@@ -1715,22 +1747,22 @@ static const GByte AC_HUFFVAL[256] = {
     0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2,
     0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
     0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
-    0xF9, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0xF9, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 
 static const GByte DC_BITS[16] =
-{ 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
+    { 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
 
 static const GByte DC_HUFFVAL[256] = {
-    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
     0x08, 0x09, 0x0A, 0x0B };
 
 void JPGDataset::LoadDefaultTables( int n )
@@ -1739,11 +1771,10 @@ void JPGDataset::LoadDefaultTables( int n )
         return;
 
 /* -------------------------------------------------------------------- */
-/*      Load quantization table						*/
+/*      Load quantization table                                         */
 /* -------------------------------------------------------------------- */
-    int i;
-    JQUANT_TBL  *quant_ptr;
-    const GByte *pabyQTable;
+    JQUANT_TBL  *quant_ptr = NULL;
+    const GByte *pabyQTable = NULL;
 
     if( nQLevel == 1 )
         pabyQTable = Q1table;
@@ -1759,11 +1790,11 @@ void JPGDataset::LoadDefaultTables( int n )
         return;
 
     if (sDInfo.quant_tbl_ptrs[n] == NULL)
-        sDInfo.quant_tbl_ptrs[n] = 
-            jpeg_alloc_quant_table((j_common_ptr) &(sDInfo));
-    
-    quant_ptr = sDInfo.quant_tbl_ptrs[n];	/* quant_ptr is JQUANT_TBL* */
-    for (i = 0; i < 64; i++) {
+        sDInfo.quant_tbl_ptrs[n] =
+            jpeg_alloc_quant_table(reinterpret_cast<j_common_ptr>( &(sDInfo) ) );
+
+    quant_ptr = sDInfo.quant_tbl_ptrs[n];  /* quant_ptr is JQUANT_TBL* */
+    for (int i = 0; i < 64; i++) {
         /* Qtable[] is desired quantization table, in natural array order */
         quant_ptr->quantval[i] = pabyQTable[i];
     }
@@ -1771,20 +1802,19 @@ void JPGDataset::LoadDefaultTables( int n )
 /* -------------------------------------------------------------------- */
 /*      Load AC huffman table.                                          */
 /* -------------------------------------------------------------------- */
-    JHUFF_TBL  *huff_ptr;
-
     if (sDInfo.ac_huff_tbl_ptrs[n] == NULL)
         sDInfo.ac_huff_tbl_ptrs[n] =
             jpeg_alloc_huff_table((j_common_ptr)&sDInfo);
 
-    huff_ptr = sDInfo.ac_huff_tbl_ptrs[n];	/* huff_ptr is JHUFF_TBL* */
+    /* huff_ptr is JHUFF_TBL* */
+    JHUFF_TBL *huff_ptr = sDInfo.ac_huff_tbl_ptrs[n];
 
-    for (i = 1; i <= 16; i++) {
+    for (int i = 1; i <= 16; i++) {
         /* counts[i] is number of Huffman codes of length i bits, i=1..16 */
         huff_ptr->bits[i] = AC_BITS[i-1];
     }
 
-    for (i = 0; i < 256; i++) {
+    for (int i = 0; i < 256; i++) {
         /* symbols[] is the list of Huffman symbols, in code-length order */
         huff_ptr->huffval[i] = AC_HUFFVAL[i];
     }
@@ -1796,14 +1826,14 @@ void JPGDataset::LoadDefaultTables( int n )
         sDInfo.dc_huff_tbl_ptrs[n] =
             jpeg_alloc_huff_table((j_common_ptr)&sDInfo);
 
-    huff_ptr = sDInfo.dc_huff_tbl_ptrs[n];	/* huff_ptr is JHUFF_TBL* */
+    huff_ptr = sDInfo.dc_huff_tbl_ptrs[n];      /* huff_ptr is JHUFF_TBL* */
 
-    for (i = 1; i <= 16; i++) {
+    for (int i = 1; i <= 16; i++) {
         /* counts[i] is number of Huffman codes of length i bits, i=1..16 */
         huff_ptr->bits[i] = DC_BITS[i-1];
     }
 
-    for (i = 0; i < 256; i++) {
+    for (int i = 0; i < 256; i++) {
         /* symbols[] is the list of Huffman symbols, in code-length order */
         huff_ptr->huffval[i] = DC_HUFFVAL[i];
     }
@@ -1836,7 +1866,7 @@ CPLErr JPGDataset::Restart()
 
 {
     // setup to trap a fatal error.
-    if (setjmp(sErrorStruct.setjmp_buffer)) 
+    if (setjmp(sErrorStruct.setjmp_buffer))
         return CE_Failure;
 
     J_COLOR_SPACE colorSpace = sDInfo.out_color_space;
@@ -1913,11 +1943,11 @@ CPLErr JPGDatasetCommon::GetGeoTransform( double * padfTransform )
     if( bGeoTransformValid )
     {
         memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
-        
+
         return CE_None;
     }
-    else 
-        return eErr;
+
+    return eErr;
 }
 
 /************************************************************************/
@@ -1927,7 +1957,7 @@ CPLErr JPGDatasetCommon::GetGeoTransform( double * padfTransform )
 int JPGDatasetCommon::GetGCPCount()
 
 {
-    int nPAMGCPCount = GDALPamDataset::GetGCPCount();
+    const int nPAMGCPCount = GDALPamDataset::GetGCPCount();
     if( nPAMGCPCount != 0 )
         return nPAMGCPCount;
 
@@ -1943,7 +1973,7 @@ int JPGDatasetCommon::GetGCPCount()
 const char *JPGDatasetCommon::GetGCPProjection()
 
 {
-    int nPAMGCPCount = GDALPamDataset::GetGCPCount();
+    const int nPAMGCPCount = GDALPamDataset::GetGCPCount();
     if( nPAMGCPCount != 0 )
         return GDALPamDataset::GetGCPProjection();
 
@@ -1951,8 +1981,8 @@ const char *JPGDatasetCommon::GetGCPProjection()
 
     if( pszProjection && nGCPCount > 0 )
         return pszProjection;
-    else
-        return "";
+
+    return "";
 }
 
 /************************************************************************/
@@ -1962,7 +1992,7 @@ const char *JPGDatasetCommon::GetGCPProjection()
 const GDAL_GCP *JPGDatasetCommon::GetGCPs()
 
 {
-    int nPAMGCPCount = GDALPamDataset::GetGCPCount();
+    const int nPAMGCPCount = GDALPamDataset::GetGCPCount();
     if( nPAMGCPCount != 0 )
         return GDALPamDataset::GetGCPs();
 
@@ -1980,15 +2010,21 @@ const GDAL_GCP *JPGDatasetCommon::GetGCPs()
 /************************************************************************/
 
 CPLErr JPGDatasetCommon::IRasterIO( GDALRWFlag eRWFlag,
-                              int nXOff, int nYOff, int nXSize, int nYSize,
-                              void *pData, int nBufXSize, int nBufYSize, 
-                              GDALDataType eBufType,
-                              int nBandCount, int *panBandMap, 
-                              GSpacing nPixelSpace, GSpacing nLineSpace,
-                              GSpacing nBandSpace,
-                              GDALRasterIOExtraArg* psExtraArg )
+                                    int nXOff, int nYOff, int nXSize, int nYSize,
+                                    void *pData, int nBufXSize, int nBufYSize,
+                                    GDALDataType eBufType,
+                                    int nBandCount, int *panBandMap,
+                                    GSpacing nPixelSpace, GSpacing nLineSpace,
+                                    GSpacing nBandSpace,
+                                    GDALRasterIOExtraArg* psExtraArg )
 
 {
+    // Coverity says that we cannot pass a nullptr to IRasterIO.
+    if (panBandMap == NULL)
+    {
+      return CE_Failure;
+    }
+
     if((eRWFlag == GF_Read) &&
        (nBandCount == 3) &&
        (nBands == 3) &&
@@ -2003,16 +2039,13 @@ CPLErr JPGDatasetCommon::IRasterIO( GDALRWFlag eRWFlag,
        GetOutColorSpace() != JCS_YCCK && GetOutColorSpace() != JCS_CMYK )
     {
         Restart();
-        int y;
-        CPLErr tmpError;
-        int x;
 
         // Pixel interleaved case
         if( nBandSpace == 1 )
         {
-            for(y = 0; y < nYSize; ++y)
+            for(int y = 0; y < nYSize; ++y)
             {
-                tmpError = LoadScanline(y);
+                CPLErr tmpError = LoadScanline(y);
                 if(tmpError != CE_None) return tmpError;
 
                 if( nPixelSpace == 3 )
@@ -2022,9 +2055,9 @@ CPLErr JPGDatasetCommon::IRasterIO( GDALRWFlag eRWFlag,
                 }
                 else
                 {
-                    for(x = 0; x < nXSize; ++x)
+                    for(int x = 0; x < nXSize; ++x)
                     {
-                        memcpy(&(((GByte*)pData)[(y*nLineSpace) + (x*nPixelSpace)]), 
+                        memcpy(&(((GByte*)pData)[(y*nLineSpace) + (x*nPixelSpace)]),
                                (const GByte*)&(pabyScanline[x*3]), 3);
                     }
                 }
@@ -2032,15 +2065,18 @@ CPLErr JPGDatasetCommon::IRasterIO( GDALRWFlag eRWFlag,
         }
         else
         {
-            for(y = 0; y < nYSize; ++y)
+            for(int y = 0; y < nYSize; ++y)
             {
-                tmpError = LoadScanline(y);
+                CPLErr tmpError = LoadScanline(y);
                 if(tmpError != CE_None) return tmpError;
-                for(x = 0; x < nXSize; ++x)
+                for(int x = 0; x < nXSize; ++x)
                 {
-                    ((GByte*)pData)[(y*nLineSpace) + (x*nPixelSpace)] = pabyScanline[x*3];
-                    ((GByte*)pData)[(y*nLineSpace) + (x*nPixelSpace) + nBandSpace] = pabyScanline[x*3+1];
-                    ((GByte*)pData)[(y*nLineSpace) + (x*nPixelSpace) + 2 * nBandSpace] = pabyScanline[x*3+2];
+                    static_cast<GByte*>(pData)[(y*nLineSpace) + (x*nPixelSpace)] =
+                        pabyScanline[x*3];
+                    ((GByte*)pData)[(y*nLineSpace) + (x*nPixelSpace) + nBandSpace] =
+                        pabyScanline[x*3+1];
+                    ((GByte*)pData)[(y*nLineSpace) + (x*nPixelSpace) + 2 * nBandSpace] =
+                        pabyScanline[x*3+2];
                 }
             }
         }
@@ -2049,8 +2085,8 @@ CPLErr JPGDatasetCommon::IRasterIO( GDALRWFlag eRWFlag,
     }
 
     return GDALPamDataset::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                                     pData, nBufXSize, nBufYSize, eBufType, 
-                                     nBandCount, panBandMap, 
+                                     pData, nBufXSize, nBufYSize, eBufType,
+                                     nBandCount, panBandMap,
                                      nPixelSpace, nLineSpace, nBandSpace,
                                      psExtraArg);
 }
@@ -2073,8 +2109,7 @@ static int JPEGDatasetIsJPEGLS( GDALOpenInfo * poOpenInfo )
         || pabyHeader[1] != 0xd8 )
         return FALSE;
 
-    int nOffset = 2;
-    for (;nOffset + 4 < nHeaderBytes;)
+    for (int nOffset = 2; nOffset + 4 < nHeaderBytes;)
     {
         if (pabyHeader[nOffset] != 0xFF)
             return FALSE;
@@ -2107,24 +2142,22 @@ static int JPEGDatasetIsJPEGLS( GDALOpenInfo * poOpenInfo )
 int JPGDatasetCommon::Identify( GDALOpenInfo * poOpenInfo )
 
 {
-    GByte  *pabyHeader = NULL;
-    int    nHeaderBytes = poOpenInfo->nHeaderBytes;
-
 /* -------------------------------------------------------------------- */
 /*      If it is a subfile, read the JPEG header.                       */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(poOpenInfo->pszFilename,"JPEG_SUBFILE:",13) )
+    if( STARTS_WITH_CI(poOpenInfo->pszFilename, "JPEG_SUBFILE:") )
         return TRUE;
 
 /* -------------------------------------------------------------------- */
-/*	First we check to see if the file has the expected header	*/
-/*	bytes.								*/    
+/*      First we check to see if the file has the expected header       */
+/*      bytes.                                                          */
 /* -------------------------------------------------------------------- */
-    pabyHeader = poOpenInfo->pabyHeader;
+    const int nHeaderBytes = poOpenInfo->nHeaderBytes;
 
     if( nHeaderBytes < 10 )
         return FALSE;
 
+    GByte * const pabyHeader = poOpenInfo->pabyHeader;
     if( pabyHeader[0] != 0xff
         || pabyHeader[1] != 0xd8
         || pabyHeader[2] != 0xff )
@@ -2152,19 +2185,26 @@ GDALDataset *JPGDatasetCommon::Open( GDALOpenInfo * poOpenInfo )
 
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The JPEG driver does not support update access to existing"
-                  " datasets.\n" );
+                  " datasets." );
         return NULL;
     }
 
     VSILFILE* fpL = poOpenInfo->fpL;
     poOpenInfo->fpL = NULL;
 
-    return JPGDataset::Open(poOpenInfo->pszFilename,
-                            fpL,
-                            poOpenInfo->GetSiblingFiles(),
-                            1, TRUE);
+    JPGDatasetOpenArgs sArgs;
+    sArgs.pszFilename = poOpenInfo->pszFilename;
+    sArgs.fpLin = fpL;
+    sArgs.papszSiblingFiles = poOpenInfo->GetSiblingFiles();
+    sArgs.nScaleFactor = 1;
+    sArgs.bDoPAMInitialize = TRUE;
+    sArgs.bUseInternalOverviews =
+        CSLFetchBoolean( poOpenInfo->papszOpenOptions, "USE_INTERNAL_OVERVIEWS",
+                         TRUE);
+
+    return JPGDataset::Open(&sArgs);
 }
 
 #endif // !defined(JPGDataset)
@@ -2173,56 +2213,85 @@ GDALDataset *JPGDatasetCommon::Open( GDALOpenInfo * poOpenInfo )
 /*                                Open()                                */
 /************************************************************************/
 
-GDALDataset *JPGDataset::Open( const char* pszFilename,
-                               VSILFILE* fpLin,
-                               char** papszSiblingFiles,
-                               int nScaleFactor,
-                               int bDoPAMInitialize )
+GDALDataset *JPGDataset::Open( JPGDatasetOpenArgs* psArgs )
 
 {
+    JPGDataset  *poDS = new JPGDataset();
+    /* Will detect mismatch between compile-time and run-time libjpeg versions */
+    if (setjmp(poDS->sErrorStruct.setjmp_buffer))
+    {
+#if defined(JPEG_DUAL_MODE_8_12) && !defined(JPGDataset)
+        if (poDS->sDInfo.data_precision == 12 && poDS->fpImage != NULL)
+        {
+            VSILFILE* fpImage = poDS->fpImage;
+            poDS->fpImage = NULL;
+            delete poDS;
+            psArgs->fpLin = fpImage;
+            return JPEGDataset12Open(psArgs);
+        }
+#endif
+        delete poDS;
+        return NULL;
+    }
+
+    const char* pszFilename = psArgs->pszFilename;
+    VSILFILE* fpLin = psArgs->fpLin;
+    char** papszSiblingFiles = psArgs->papszSiblingFiles;
+    const int nScaleFactor = psArgs->nScaleFactor;
+    const int bDoPAMInitialize = psArgs->bDoPAMInitialize;
+    const int bUseInternalOverviews = psArgs->bUseInternalOverviews;
+
 /* -------------------------------------------------------------------- */
 /*      If it is a subfile, read the JPEG header.                       */
 /* -------------------------------------------------------------------- */
-    int bIsSubfile = FALSE;
+    bool bIsSubfile = false;
     GUIntBig subfile_offset = 0;
     GUIntBig subfile_size = 0;
     const char *real_filename = pszFilename;
     int nQLevel = -1;
 
-    if( EQUALN(pszFilename,"JPEG_SUBFILE:",13) )
+    if( STARTS_WITH_CI(pszFilename, "JPEG_SUBFILE:") )
     {
-        char** papszTokens;
-        int bScan = FALSE;
+        bool bScan = false;
 
-        if( EQUALN(pszFilename,"JPEG_SUBFILE:Q",14) )
+        if( STARTS_WITH_CI(pszFilename, "JPEG_SUBFILE:Q") )
         {
-            papszTokens = CSLTokenizeString2(pszFilename + 14, ",", 0);
+            char** papszTokens = CSLTokenizeString2(pszFilename + 14, ",", 0);
             if (CSLCount(papszTokens) >= 3)
             {
                 nQLevel = atoi(papszTokens[0]);
-                subfile_offset = CPLScanUIntBig(papszTokens[1], strlen(papszTokens[1]));
-                subfile_size = CPLScanUIntBig(papszTokens[2], strlen(papszTokens[2]));
-                bScan = TRUE;
+                subfile_offset =
+                    CPLScanUIntBig( papszTokens[1],
+                                    static_cast<int>(strlen(papszTokens[1])) );
+                subfile_size =
+                    CPLScanUIntBig( papszTokens[2],
+                                    static_cast<int>(strlen(papszTokens[2])) );
+                bScan = true;
             }
             CSLDestroy(papszTokens);
         }
         else
         {
-            papszTokens = CSLTokenizeString2(pszFilename + 13, ",", 0);
+            char** papszTokens = CSLTokenizeString2(pszFilename + 13, ",", 0);
             if (CSLCount(papszTokens) >= 2)
             {
-                subfile_offset = CPLScanUIntBig(papszTokens[0], strlen(papszTokens[0]));
-                subfile_size = CPLScanUIntBig(papszTokens[1], strlen(papszTokens[1]));
-                bScan = TRUE;
+                subfile_offset =
+                    CPLScanUIntBig( papszTokens[0],
+                                    static_cast<int>(strlen(papszTokens[0])));
+                subfile_size =
+                    CPLScanUIntBig( papszTokens[1],
+                                    static_cast<int>(strlen(papszTokens[1])) );
+                bScan = true;
             }
             CSLDestroy(papszTokens);
         }
 
-        if( !bScan ) 
+        if( !bScan )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
-                      "Corrupt subfile definition: %s", 
+            CPLError( CE_Failure, CPLE_OpenFailed,
+                      "Corrupt subfile definition: %s",
                       pszFilename );
+            delete poDS;
             return NULL;
         }
 
@@ -2235,13 +2304,15 @@ GDALDataset *JPGDataset::Open( const char* pszFilename,
             real_filename++;
         else
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
-                      "Could not find filename in subfile definition.");
+            CPLError( CE_Failure, CPLE_OpenFailed,
+                      "Could not find filename in subfile definition." );
+            delete poDS;
             return NULL;
         }
 
         CPLDebug( "JPG",
-                  "real_filename %s, offset=" CPL_FRMT_GUIB ", size=" CPL_FRMT_GUIB "\n", 
+                  "real_filename %s, offset=" CPL_FRMT_GUIB ", size="
+                  CPL_FRMT_GUIB "\n",
                   real_filename, subfile_offset, subfile_size);
 
         bIsSubfile = TRUE;
@@ -2250,17 +2321,18 @@ GDALDataset *JPGDataset::Open( const char* pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Open the file using the large file api if necessary.            */
 /* -------------------------------------------------------------------- */
-    VSILFILE* fpImage;
+    VSILFILE* fpImage = fpLin;
 
-    if( fpLin == NULL )
+    if( fpImage == NULL )
     {
         fpImage = VSIFOpenL( real_filename, "rb" );
 
         if( fpImage == NULL )
         {
             CPLError( CE_Failure, CPLE_OpenFailed,
-                    "VSIFOpenL(%s) failed unexpectedly in jpgdataset.cpp",
-                    real_filename );
+                      "VSIFOpenL(%s) failed unexpectedly in jpgdataset.cpp",
+                      real_filename );
+            delete poDS;
             return NULL;
         }
     }
@@ -2270,9 +2342,6 @@ GDALDataset *JPGDataset::Open( const char* pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    JPGDataset	*poDS;
-
-    poDS = new JPGDataset();
     poDS->nQLevel = nQLevel;
     poDS->fpImage = fpImage;
 
@@ -2284,29 +2353,23 @@ GDALDataset *JPGDataset::Open( const char* pszFilename,
 
     poDS->eAccess = GA_ReadOnly;
 
-    /* Will detect mismatch between compile-time and run-time libjpeg versions */
-    if (setjmp(poDS->sErrorStruct.setjmp_buffer)) 
-    {
-        delete poDS;
-        return NULL;
-    }
-
     poDS->sDInfo.err = jpeg_std_error( &(poDS->sJErr) );
     poDS->sJErr.error_exit = JPGDataset::ErrorExit;
     poDS->sErrorStruct.p_previous_emit_message = poDS->sJErr.emit_message;
-    poDS->sJErr.emit_message = JPGDatasetCommon::EmitMessage;
-    poDS->sDInfo.client_data = (void *) &(poDS->sErrorStruct);
+    poDS->sJErr.emit_message = JPGDataset::EmitMessage;
+    poDS->sDInfo.client_data =
+        reinterpret_cast<void *>( &(poDS->sErrorStruct) );
 
     jpeg_create_decompress( &(poDS->sDInfo) );
     poDS->bHasDoneJpegCreateDecompress = TRUE;
 
     /* This is to address bug related in ticket #1795 */
-    if (CPLGetConfigOption("JPEGMEM", NULL) == NULL)
+    if( CPLGetConfigOption("JPEGMEM", NULL) == NULL )
     {
-        /* If the user doesn't provide a value for JPEGMEM, we want to be sure */
-        /* that at least 500 MB will be used before creating the temporary file */
+        // If the user doesn't provide a value for JPEGMEM, we want to be sure
+        // that at least 500 MB will be used before creating the temporary file.
         poDS->sDInfo.mem->max_memory_to_use =
-                MAX(poDS->sDInfo.mem->max_memory_to_use, 500 * 1024 * 1024);
+            MAX(poDS->sDInfo.mem->max_memory_to_use, 500 * 1024 * 1024);
     }
 
 /* -------------------------------------------------------------------- */
@@ -2321,26 +2384,7 @@ GDALDataset *JPGDataset::Open( const char* pszFilename,
 #endif // !defined(JPGDataset)
 
 /* -------------------------------------------------------------------- */
-/*      If a fatal error occurs after this, we will return NULL         */
-/* -------------------------------------------------------------------- */
-    if (setjmp(poDS->sErrorStruct.setjmp_buffer)) 
-    {
-#if defined(JPEG_DUAL_MODE_8_12) && !defined(JPGDataset)
-        if (poDS->sDInfo.data_precision == 12)
-        {
-            fpImage = poDS->fpImage;
-            poDS->fpImage = NULL;
-            delete poDS;
-            return JPEGDataset12Open(pszFilename, fpImage, papszSiblingFiles,
-                                     nScaleFactor, bDoPAMInitialize);
-        }
-#endif
-        delete poDS;
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*	Read pre-image data after ensuring the file is rewound.         */
+/*      Read pre-image data after ensuring the file is rewound.         */
 /* -------------------------------------------------------------------- */
     VSIFSeekL( poDS->fpImage, poDS->nSubfileOffset, SEEK_SET );
 
@@ -2350,9 +2394,9 @@ GDALDataset *JPGDataset::Open( const char* pszFilename,
     if( poDS->sDInfo.data_precision != 8
         && poDS->sDInfo.data_precision != 12 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
-                  "GDAL JPEG Driver doesn't support files with precision of"
-                  " other than 8 or 12 bits." );
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "GDAL JPEG Driver doesn't support files with precision of "
+                  "other than 8 or 12 bits." );
         delete poDS;
         return NULL;
     }
@@ -2363,8 +2407,10 @@ GDALDataset *JPGDataset::Open( const char* pszFilename,
 
     poDS->nScaleFactor = nScaleFactor;
     poDS->SetScaleNumAndDenom();
-    poDS->nRasterXSize = (poDS->sDInfo.image_width + nScaleFactor - 1) / nScaleFactor;
-    poDS->nRasterYSize = (poDS->sDInfo.image_height + nScaleFactor - 1) / nScaleFactor;
+    poDS->nRasterXSize =
+        (poDS->sDInfo.image_width + nScaleFactor - 1) / nScaleFactor;
+    poDS->nRasterYSize =
+        (poDS->sDInfo.image_height + nScaleFactor - 1) / nScaleFactor;
 
     poDS->sDInfo.out_color_space = poDS->sDInfo.jpeg_color_space;
     poDS->eGDALColorSpace = poDS->sDInfo.jpeg_color_space;
@@ -2380,20 +2426,23 @@ GDALDataset *JPGDataset::Open( const char* pszFilename,
     else if( poDS->sDInfo.jpeg_color_space == JCS_YCbCr )
     {
         poDS->nBands = 3;
-        if (CSLTestBoolean(CPLGetConfigOption("GDAL_JPEG_TO_RGB", "YES")))
+        if (CPLTestBool(CPLGetConfigOption("GDAL_JPEG_TO_RGB", "YES")))
         {
             poDS->sDInfo.out_color_space = JCS_RGB;
             poDS->eGDALColorSpace = JCS_RGB;
-            poDS->SetMetadataItem( "SOURCE_COLOR_SPACE", "YCbCr", "IMAGE_STRUCTURE" );
+            poDS->SetMetadataItem(
+                "SOURCE_COLOR_SPACE", "YCbCr", "IMAGE_STRUCTURE" );
         }
     }
     else if( poDS->sDInfo.jpeg_color_space == JCS_CMYK )
     {
-        if (CSLTestBoolean(CPLGetConfigOption("GDAL_JPEG_TO_RGB", "YES")))
+        if (poDS->sDInfo.data_precision == 8 &&
+            CPLTestBool(CPLGetConfigOption("GDAL_JPEG_TO_RGB", "YES")))
         {
             poDS->eGDALColorSpace = JCS_RGB;
             poDS->nBands = 3;
-            poDS->SetMetadataItem( "SOURCE_COLOR_SPACE", "CMYK", "IMAGE_STRUCTURE" );
+            poDS->SetMetadataItem(
+                "SOURCE_COLOR_SPACE", "CMYK", "IMAGE_STRUCTURE" );
         }
         else
         {
@@ -2402,11 +2451,13 @@ GDALDataset *JPGDataset::Open( const char* pszFilename,
     }
     else if( poDS->sDInfo.jpeg_color_space == JCS_YCCK )
     {
-        if (CSLTestBoolean(CPLGetConfigOption("GDAL_JPEG_TO_RGB", "YES")))
+        if (poDS->sDInfo.data_precision == 8 &&
+            CPLTestBool(CPLGetConfigOption("GDAL_JPEG_TO_RGB", "YES")))
         {
             poDS->eGDALColorSpace = JCS_RGB;
             poDS->nBands = 3;
-            poDS->SetMetadataItem( "SOURCE_COLOR_SPACE", "YCbCrK", "IMAGE_STRUCTURE" );
+            poDS->SetMetadataItem(
+                "SOURCE_COLOR_SPACE", "YCbCrK", "IMAGE_STRUCTURE" );
 
             /* libjpeg does the translation from YCrCbK -> CMYK internally */
             /* and we'll do the translation to RGB in IReadBlock() */
@@ -2419,8 +2470,8 @@ GDALDataset *JPGDataset::Open( const char* pszFilename,
     }
     else
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
-                  "Unrecognised jpeg_color_space value of %d.\n", 
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Unrecognized jpeg_color_space value of %d.\n",
                   poDS->sDInfo.jpeg_color_space );
         delete poDS;
         return NULL;
@@ -2458,17 +2509,22 @@ GDALDataset *JPGDataset::Open( const char* pszFilename,
 /* -------------------------------------------------------------------- */
         poDS->oOvManager.Initialize( poDS, real_filename, papszSiblingFiles );
 
+        if( !bUseInternalOverviews )
+            poDS->bHasInitInternalOverviews = TRUE;
+
         /* In the case of a file downloaded through the HTTP driver, this one */
         /* will unlink the temporary /vsimem file just after GDALOpen(), so */
         /* later VSIFOpenL() when reading internal overviews would fail. */
         /* Initialize them now */
-        if( strncmp(real_filename, "/vsimem/http_", strlen("/vsimem/http_")) == 0 )
+        if( STARTS_WITH(real_filename, "/vsimem/http_") )
         {
             poDS->InitInternalOverviews();
         }
     }
     else
+    {
         poDS->nPamFlags |= GPF_NOSAVE;
+    }
 
     poDS->bIsSubfile = bIsSubfile;
 
@@ -2493,8 +2549,9 @@ void JPGDatasetCommon::LoadWorldFileOrTab()
 
     /* TIROS3 JPEG files have a .wld extension, so don't look for .wld as */
     /* as worldfile ! */
-    int bEndsWithWld = strlen(GetDescription()) > 4 &&
-                        EQUAL( GetDescription() + strlen(GetDescription()) - 4, ".wld");
+    const bool bEndsWithWld =
+        strlen(GetDescription()) > 4 &&
+        EQUAL( GetDescription() + strlen(GetDescription()) - 4, ".wld");
     bGeoTransformValid =
         GDALReadWorldFile2( GetDescription(), NULL,
                             adfGeoTransform,
@@ -2502,17 +2559,21 @@ void JPGDatasetCommon::LoadWorldFileOrTab()
         || GDALReadWorldFile2( GetDescription(), ".jpw",
                                 adfGeoTransform,
                                oOvManager.GetSiblingFiles(), &pszWldFilename )
-        || ( !bEndsWithWld && GDALReadWorldFile2( GetDescription(), ".wld",
-                                adfGeoTransform,
-                                oOvManager.GetSiblingFiles(), &pszWldFilename ));
+        || ( !bEndsWithWld &&
+             GDALReadWorldFile2( GetDescription(), ".wld",
+                                 adfGeoTransform,
+                                 oOvManager.GetSiblingFiles(),
+                                 &pszWldFilename ));
 
     if( !bGeoTransformValid )
     {
-        int bTabFileOK =
-            GDALReadTabFile2( GetDescription(), adfGeoTransform,
-                              &pszProjection,
-                              &nGCPCount, &pasGCPList,
-                              oOvManager.GetSiblingFiles(), &pszWldFilename );
+        const bool bTabFileOK =
+            CPL_TO_BOOL(
+                GDALReadTabFile2( GetDescription(), adfGeoTransform,
+                                  &pszProjection,
+                                  &nGCPCount, &pasGCPList,
+                                  oOvManager.GetSiblingFiles(),
+                                  &pszWldFilename ));
 
         if( bTabFileOK && nGCPCount == 0 )
             bGeoTransformValid = TRUE;
@@ -2536,8 +2597,8 @@ char **JPGDatasetCommon::GetFileList()
 
     LoadWorldFileOrTab();
 
-    if (osWldFilename.size() != 0 &&
-        CSLFindString(papszFileList, osWldFilename) == -1)
+    if( osWldFilename.size() != 0 &&
+        CSLFindString(papszFileList, osWldFilename) == -1 )
     {
         papszFileList = CSLAddString( papszFileList, osWldFilename );
     }
@@ -2552,32 +2613,30 @@ char **JPGDatasetCommon::GetFileList()
 void JPGDatasetCommon::CheckForMask()
 
 {
-    GIntBig nFileSize;
-    GUInt32 nImageSize;
-
     /* Save current position to avoid disturbing JPEG stream decoding */
-    vsi_l_offset nCurOffset = VSIFTellL(fpImage);
+    const vsi_l_offset nCurOffset = VSIFTellL(fpImage);
 
 /* -------------------------------------------------------------------- */
 /*      Go to the end of the file, pull off four bytes, and see if      */
 /*      it is plausibly the size of the real image data.                */
 /* -------------------------------------------------------------------- */
     VSIFSeekL( fpImage, 0, SEEK_END );
-    nFileSize = VSIFTellL( fpImage );
+    GIntBig nFileSize = VSIFTellL( fpImage );
     VSIFSeekL( fpImage, nFileSize - 4, SEEK_SET );
-    
+
+    GUInt32 nImageSize = 0;
     VSIFReadL( &nImageSize, 4, 1, fpImage );
     CPL_LSBPTR32( &nImageSize );
 
+    GByte abyEOD[2] = { 0, 0 };
+
     if( nImageSize < nFileSize / 2 || nImageSize > nFileSize - 4 )
         goto end;
 
 /* -------------------------------------------------------------------- */
-/*      If that seems ok, seek back, and verify that just preceeding    */
+/*      If that seems okay, seek back, and verify that just preceding   */
 /*      the bitmask is an apparent end-of-jpeg-data marker.             */
 /* -------------------------------------------------------------------- */
-    GByte abyEOD[2];
-
     VSIFSeekL( fpImage, nImageSize - 2, SEEK_SET );
     VSIFReadL( abyEOD, 2, 1, fpImage );
     if( abyEOD[0] != 0xff || abyEOD[1] != 0xd9 )
@@ -2586,13 +2645,10 @@ void JPGDatasetCommon::CheckForMask()
 /* -------------------------------------------------------------------- */
 /*      We seem to have a mask.  Read it in.                            */
 /* -------------------------------------------------------------------- */
-    nCMaskSize = (int) (nFileSize - nImageSize - 4);
-    pabyCMask = (GByte *) VSIMalloc(nCMaskSize);
+    nCMaskSize = static_cast<int>(nFileSize - nImageSize - 4);
+    pabyCMask = static_cast<GByte *>( VSI_MALLOC_VERBOSE(nCMaskSize) );
     if (pabyCMask == NULL)
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory,
-                 "Cannot allocate memory (%d bytes) for mask compressed buffer",
-                 nCMaskSize);
         goto end;
     }
     VSIFReadL( pabyCMask, nCMaskSize, 1, fpImage );
@@ -2600,6 +2656,7 @@ void JPGDatasetCommon::CheckForMask()
     CPLDebug( "JPEG", "Got %d byte compressed bitmask.",
               nCMaskSize );
 
+    // TODO(schwehr): Refactor to not use goto.
 end:
     VSIFSeekL( fpImage, nCurOffset, SEEK_SET );
 }
@@ -2617,18 +2674,15 @@ void JPGDatasetCommon::DecompressMask()
 /* -------------------------------------------------------------------- */
 /*      Allocate 1bit buffer - may be slightly larger than needed.      */
 /* -------------------------------------------------------------------- */
-    int nBufSize = nRasterYSize * ((nRasterXSize+7)/8);
-    pabyBitMask = (GByte *) VSIMalloc( nBufSize );
+    const int nBufSize = nRasterYSize * ((nRasterXSize + 7) / 8);
+    pabyBitMask = static_cast<GByte *>( VSI_MALLOC_VERBOSE( nBufSize ) );
     if (pabyBitMask == NULL)
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory,
-                 "Cannot allocate memory (%d bytes) for mask uncompressed buffer",
-                 nBufSize);
         CPLFree(pabyCMask);
         pabyCMask = NULL;
         return;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Decompress                                                      */
 /* -------------------------------------------------------------------- */
@@ -2646,64 +2700,76 @@ void JPGDatasetCommon::DecompressMask()
 
         CPLFree( pabyBitMask );
         pabyBitMask = NULL;
+
+        return;
     }
-    else
-    {
-        const char* pszJPEGMaskBitOrder = CPLGetConfigOption("JPEG_MASK_BIT_ORDER", "AUTO");
-        if( EQUAL(pszJPEGMaskBitOrder, "LSB") )
-            bMaskLSBOrder = TRUE;
-        else if( EQUAL(pszJPEGMaskBitOrder, "MSB") )
-            bMaskLSBOrder = FALSE;
-        else if( nRasterXSize > 8 && nRasterYSize > 1 )
+
+    const char* pszJPEGMaskBitOrder = CPLGetConfigOption("JPEG_MASK_BIT_ORDER", "AUTO");
+    if( EQUAL(pszJPEGMaskBitOrder, "LSB") )
+        bMaskLSBOrder = TRUE;
+    else if( EQUAL(pszJPEGMaskBitOrder, "MSB") )
+        bMaskLSBOrder = FALSE;
+    else if( nRasterXSize > 8 && nRasterYSize > 1 )
+    {
+        // Test MSB ordering hypothesis in a very restrictive case where it is
+        // *obviously* ordered as MSB ! (unless someone coded something
+        // specifically to defeat the below logic)
+        // The case considered here is dop_465_6100.jpg from #5102.
+        // The mask is identical for each line, starting with 1's and ending
+        // with 0's (or starting with 0's and ending with 1's), and no other
+        // intermediate change.
+        // We can detect the MSB ordering since the lsb bits at the end of the
+        // first line will be set with the 1's of the beginning of the second
+        // line.
+        // We can only be sure of this heuristics if the change of value occurs
+        // in the middle of a byte, or if the raster width is not a multiple of
+        // 8.
+        int nPrevValBit = 0;
+        int nChangedValBit = 0;
+        int iX = 0;  // Used after for.
+        for( ; iX < nRasterXSize; iX++ )
         {
-            /* Test MSB ordering hypothesis in a very restrictive case where it is */
-            /* *obviously* ordered as MSB ! (unless someone coded something */
-            /* specifically to defeat the below logic) */
-            /* The case considered here is dop_465_6100.jpg from #5102 */
-            /* The mask is identical for each line, starting with 1's and ending with 0's */
-            /* (or starting with 0's and ending with 1's), and no other intermediate change. */
-            /* We can detect the MSB ordering since the lsb bits at the end of the first */
-            /* line will be set with the 1's of the beginning of the second line. */
-            /* We can only be sure of this heuristics if the change of value occurs in the */
-            /* middle of a byte, or if the raster width is not a multiple of 8. */
-            int iX;
-            int nPrevValBit = 0;
-            int nChangedValBit = 0;
-            for( iX = 0; iX < nRasterXSize; iX++ )
+            const int nValBit =
+                (pabyBitMask[iX>>3] & (0x1 << (7 - (iX&7)))) != 0;
+            if( iX == 0 )
+                nPrevValBit = nValBit;
+            else if( nValBit != nPrevValBit )
             {
-                int nValBit = (pabyBitMask[iX>>3] & (0x1 << (7 - (iX&7)))) != 0;
-                if( iX == 0 )
-                    nPrevValBit = nValBit;
-                else if( nValBit != nPrevValBit )
+                nPrevValBit = nValBit;
+                nChangedValBit ++;
+                if( nChangedValBit == 1 )
                 {
-                    nPrevValBit = nValBit;
-                    nChangedValBit ++;
-                    if( nChangedValBit == 1 )
-                    {
-                        int bValChangedOnByteBoundary = ((iX % 8) == 0);
-                        if( bValChangedOnByteBoundary && ((nRasterXSize % 8) == 0 ) )
-                            break;
-                    }
-                    else
+                    const bool bValChangedOnByteBoundary = ((iX % 8) == 0);
+                    if( bValChangedOnByteBoundary &&
+                        ((nRasterXSize % 8) == 0 ) )
                         break;
                 }
-                int iNextLineX = iX + nRasterXSize;
-                int nNextLineValBit = (pabyBitMask[iNextLineX>>3] & (0x1 << (7 - (iNextLineX&7)))) != 0;
-                if( nValBit != nNextLineValBit )
+                else
+                {
                     break;
+                }
             }
+            const int iNextLineX = iX + nRasterXSize;
+            const int nNextLineValBit =
+                (pabyBitMask[iNextLineX>>3] & (0x1 << (7 - (iNextLineX&7))))
+                != 0;
+            if( nValBit != nNextLineValBit )
+                break;
+        }
 
-            if( iX == nRasterXSize )
-            {
-                CPLDebug("JPEG", "Bit ordering in mask is guessed to be msb (unusual)");
-                bMaskLSBOrder = FALSE;
-            }
-            else
-                bMaskLSBOrder = TRUE;
+        if( iX == nRasterXSize )
+        {
+            CPLDebug(
+                "JPEG", "Bit ordering in mask is guessed to be msb (unusual)" );
+            bMaskLSBOrder = FALSE;
         }
         else
             bMaskLSBOrder = TRUE;
     }
+    else
+    {
+        bMaskLSBOrder = TRUE;
+    }
 }
 
 #endif // !defined(JPGDataset)
@@ -2714,8 +2780,9 @@ void JPGDatasetCommon::DecompressMask()
 
 void JPGDataset::ErrorExit(j_common_ptr cinfo)
 {
-    GDALJPEGErrorStruct* psErrorStruct = (GDALJPEGErrorStruct* ) cinfo->client_data;
-    char buffer[JMSG_LENGTH_MAX];
+    GDALJPEGErrorStruct* psErrorStruct =
+        static_cast<GDALJPEGErrorStruct *>( cinfo->client_data );
+    char buffer[JMSG_LENGTH_MAX] = { '\0' };
 
     /* Create the message */
     (*cinfo->err->format_message) (cinfo, buffer);
@@ -2733,42 +2800,48 @@ void JPGDataset::ErrorExit(j_common_ptr cinfo)
     longjmp(psErrorStruct->setjmp_buffer, 1);
 }
 
-#if !defined(JPGDataset)
-
 /************************************************************************/
 /*                             EmitMessage()                            */
 /************************************************************************/
 
-void JPGDatasetCommon::EmitMessage(j_common_ptr cinfo, int msg_level)
+void JPGDataset::EmitMessage(j_common_ptr cinfo, int msg_level)
 {
-    GDALJPEGErrorStruct* psErrorStruct = (GDALJPEGErrorStruct* ) cinfo->client_data;
+    GDALJPEGErrorStruct* psErrorStruct =
+        static_cast<GDALJPEGErrorStruct *>( cinfo->client_data );
     if( msg_level >= 0 ) /* Trace message */
     {
         if( psErrorStruct->p_previous_emit_message != NULL )
             psErrorStruct->p_previous_emit_message(cinfo, msg_level);
     }
-    else /* Warning : libjpeg will try to recover but the image will be likely corrupted */
+    else
     {
+        // Warning : libjpeg will try to recover but the image will be likely
+        // corrupted.
+
         struct jpeg_error_mgr * err = cinfo->err;
-        /* It's a warning message.  Since corrupt files may generate many warnings,
-        * the policy implemented here is to show only the first warning,
-        * unless trace_level >= 3.
-        */
+
+        // It's a warning message.  Since corrupt files may generate many
+        // warnings, the policy implemented here is to show only the first
+        // warning, unless trace_level >= 3.
         if (err->num_warnings == 0 || err->trace_level >= 3)
         {
-            char buffer[JMSG_LENGTH_MAX];
+            char buffer[JMSG_LENGTH_MAX] = { '\0' };
 
             /* Create the message */
             (*cinfo->err->format_message) (cinfo, buffer);
 
-            if( CSLTestBoolean(CPLGetConfigOption("GDAL_ERROR_ON_LIBJPEG_WARNING", "NO")) )
+            if( CPLTestBool(
+                   CPLGetConfigOption("GDAL_ERROR_ON_LIBJPEG_WARNING", "NO")) )
             {
                 psErrorStruct->bNonFatalErrorEncountered = TRUE;
                 CPLError( CE_Failure, CPLE_AppDefined, "libjpeg: %s", buffer );
             }
             else
             {
-                CPLError( CE_Warning, CPLE_AppDefined, "libjpeg: %s (this warning can be turned as an error by setting GDAL_ERROR_ON_LIBJPEG_WARNING to TRUE)", buffer );
+                CPLError( CE_Warning, CPLE_AppDefined,
+                          "libjpeg: %s (this warning can be turned as an error "
+                          "by setting GDAL_ERROR_ON_LIBJPEG_WARNING to TRUE)",
+                          buffer );
             }
         }
 
@@ -2777,16 +2850,18 @@ void JPGDatasetCommon::EmitMessage(j_common_ptr cinfo, int msg_level)
     }
 }
 
+#if !defined(JPGDataset)
+
 /************************************************************************/
 /*                           JPGAddICCProfile()                         */
 /*                                                                      */
 /*      This function adds an ICC profile to a JPEG file.               */
 /************************************************************************/
 
-void JPGAddICCProfile( struct jpeg_compress_struct *pInfo,
+void JPGAddICCProfile( void *pInfo,
                        const char *pszICCProfile,
-                       void (*p_jpeg_write_m_header) (j_compress_ptr cinfo, int marker, unsigned int datalen),
-                       void (*p_jpeg_write_m_byte) (j_compress_ptr cinfo, int val))
+                       my_jpeg_write_m_header p_jpeg_write_m_header,
+                       my_jpeg_write_m_byte p_jpeg_write_m_byte )
 {
     if( pszICCProfile == NULL )
         return;
@@ -2802,15 +2877,16 @@ void JPGAddICCProfile( struct jpeg_compress_struct *pInfo,
     while( nEmbedLen != 0)
     {
         /* 65535 - 16 bytes for header = 65519 */
-        int nChunkLen = (nEmbedLen > 65519)?65519:nEmbedLen;
+        const int nChunkLen = (nEmbedLen > 65519) ? 65519 : nEmbedLen;
         nEmbedLen -= nChunkLen;
 
         /* write marker and length. */
-        p_jpeg_write_m_header(pInfo, JPEG_APP0 + 2,
-			        (unsigned int) (nChunkLen + 14));
+        p_jpeg_write_m_header(
+            pInfo, JPEG_APP0 + 2,
+            static_cast<unsigned int>( nChunkLen + 14 ) );
 
         /* Write identifier */
-        for(int i = 0; i < 12; i++)
+        for( int i = 0; i < 12; i++ )
             p_jpeg_write_m_byte(pInfo, paHeader[i]);
 
         /* Write ID and max ID */
@@ -2826,7 +2902,7 @@ void JPGAddICCProfile( struct jpeg_compress_struct *pInfo,
         pEmbedPtr += nChunkLen;
     }
 
-    CPLFree(pEmbedBuffer);        
+    CPLFree(pEmbedBuffer);
 }
 
 /************************************************************************/
@@ -2845,44 +2921,45 @@ CPLErr JPGAppendMask( const char *pszJPGFilename, GDALRasterBand *poMask,
                       GDALProgressFunc pfnProgress, void * pProgressData )
 
 {
-    int nXSize = poMask->GetXSize();
-    int nYSize = poMask->GetYSize();
-    int nBitBufSize = nYSize * ((nXSize+7)/8);
-    int iX, iY;
-    GByte *pabyBitBuf, *pabyMaskLine;
+    const int nXSize = poMask->GetXSize();
+    const int nYSize = poMask->GetYSize();
+    const int nBitBufSize = nYSize * ((nXSize + 7) / 8);
     CPLErr eErr = CE_None;
 
 /* -------------------------------------------------------------------- */
 /*      Allocate uncompressed bit buffer.                               */
 /* -------------------------------------------------------------------- */
-    pabyBitBuf = (GByte *) VSICalloc(1,nBitBufSize);
+    GByte *pabyBitBuf =
+        static_cast<GByte *>( VSI_CALLOC_VERBOSE(1,nBitBufSize) );
 
-    pabyMaskLine = (GByte *) VSIMalloc(nXSize);
+    GByte *pabyMaskLine =
+        static_cast<GByte *>( VSI_MALLOC_VERBOSE(nXSize) );
     if (pabyBitBuf == NULL || pabyMaskLine == NULL)
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
         eErr = CE_Failure;
     }
 
     /* No reason to set it to MSB, unless for debugging purposes */
     /* to be able to generate a unusual LSB ordered mask (#5102) */
-    const char* pszJPEGMaskBitOrder = CPLGetConfigOption("JPEG_WRITE_MASK_BIT_ORDER", "LSB");
+    const char* pszJPEGMaskBitOrder =
+        CPLGetConfigOption("JPEG_WRITE_MASK_BIT_ORDER", "LSB");
     int bMaskLSBOrder = EQUAL(pszJPEGMaskBitOrder, "LSB");
 
 /* -------------------------------------------------------------------- */
 /*      Set bit buffer from mask band, scanline by scanline.            */
 /* -------------------------------------------------------------------- */
     GUInt32 iBit = 0;
-    for( iY = 0; eErr == CE_None && iY < nYSize; iY++ )
+    for( int iY = 0; eErr == CE_None && iY < nYSize; iY++ )
     {
         eErr = poMask->RasterIO( GF_Read, 0, iY, nXSize, 1,
-                                 pabyMaskLine, nXSize, 1, GDT_Byte, 0, 0, NULL );
+                                 pabyMaskLine, nXSize, 1, GDT_Byte,
+                                 0, 0, NULL );
         if( eErr != CE_None )
             break;
 
         if( bMaskLSBOrder )
         {
-            for( iX = 0; iX < nXSize; iX++ )
+            for( int iX = 0; iX < nXSize; iX++ )
             {
                 if( pabyMaskLine[iX] != 0 )
                     pabyBitBuf[iBit>>3] |= (0x1 << (iBit&7));
@@ -2892,7 +2969,7 @@ CPLErr JPGAppendMask( const char *pszJPGFilename, GDALRasterBand *poMask,
         }
         else
         {
-            for( iX = 0; iX < nXSize; iX++ )
+            for( int iX = 0; iX < nXSize; iX++ )
             {
                 if( pabyMaskLine[iX] != 0 )
                     pabyBitBuf[iBit>>3] |= (0x1 << (7 - (iBit&7)));
@@ -2902,14 +2979,15 @@ CPLErr JPGAppendMask( const char *pszJPGFilename, GDALRasterBand *poMask,
         }
 
         if( eErr == CE_None
-            && !pfnProgress( (iY + 1) / (double) nYSize, NULL, pProgressData ) )
+            && !pfnProgress( (iY + 1) / static_cast<double>( nYSize ),
+                             NULL, pProgressData ) )
         {
             eErr = CE_Failure;
             CPLError( CE_Failure, CPLE_UserInterrupt,
                       "User terminated JPGAppendMask()" );
         }
     }
-    
+
     CPLFree( pabyMaskLine );
 
 /* -------------------------------------------------------------------- */
@@ -2919,10 +2997,10 @@ CPLErr JPGAppendMask( const char *pszJPGFilename, GDALRasterBand *poMask,
 
     if( eErr == CE_None )
     {
-        pabyCMask = (GByte *) VSIMalloc(nBitBufSize + 30);
+        pabyCMask =
+            static_cast<GByte *>( VSI_MALLOC_VERBOSE(nBitBufSize + 30) );
         if (pabyCMask == NULL)
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
             eErr = CE_Failure;
         }
     }
@@ -2934,7 +3012,7 @@ CPLErr JPGAppendMask( const char *pszJPGFilename, GDALRasterBand *poMask,
                             pabyCMask, nBitBufSize + 30,
                             &nTotalOut ) == NULL )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Deflate compression of jpeg bit mask failed." );
             eErr = CE_Failure;
         }
@@ -2945,13 +3023,10 @@ CPLErr JPGAppendMask( const char *pszJPGFilename, GDALRasterBand *poMask,
 /* -------------------------------------------------------------------- */
     if( eErr == CE_None )
     {
-        VSILFILE *fpOut;
-        GUInt32 nImageSize;
-
-        fpOut = VSIFOpenL( pszJPGFilename, "r+" );
+        VSILFILE *fpOut = VSIFOpenL( pszJPGFilename, "r+" );
         if( fpOut == NULL )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Failed to open jpeg to append bitmask." );
             eErr = CE_Failure;
         }
@@ -2959,10 +3034,10 @@ CPLErr JPGAppendMask( const char *pszJPGFilename, GDALRasterBand *poMask,
         {
             VSIFSeekL( fpOut, 0, SEEK_END );
 
-            nImageSize = (GUInt32) VSIFTellL( fpOut );
+            GUInt32 nImageSize = static_cast<GUInt32>( VSIFTellL( fpOut ) );
             CPL_LSBPTR32( &nImageSize );
 
-            if( VSIFWriteL( pabyCMask, 1, nTotalOut, fpOut ) 
+            if( VSIFWriteL( pabyCMask, 1, nTotalOut, fpOut )
                 != nTotalOut )
             {
                 CPLError( CE_Failure, CPLE_FileIO,
@@ -2989,23 +3064,26 @@ CPLErr JPGAppendMask( const char *pszJPGFilename, GDALRasterBand *poMask,
 
 void   JPGAddEXIFOverview( GDALDataType eWorkDT,
                            GDALDataset* poSrcDS, char** papszOptions,
-                           j_compress_ptr cinfo,
-                           void (*p_jpeg_write_m_header) (j_compress_ptr cinfo, int marker, unsigned int datalen),
-                           void (*p_jpeg_write_m_byte) (j_compress_ptr cinfo, int val),
-                           GDALDataset *(pCreateCopy)( const char *, GDALDataset *, 
+                           void* cinfo,
+                           my_jpeg_write_m_header p_jpeg_write_m_header,
+                           my_jpeg_write_m_byte p_jpeg_write_m_byte,
+                           GDALDataset *(pCreateCopy)( const char *, GDALDataset *,
                                      int, char **,
-                                     GDALProgressFunc pfnProgress, 
+                                     GDALProgressFunc pfnProgress,
                                      void * pProgressData ))
 {
-    int  nBands = poSrcDS->GetRasterCount();
-    int  nXSize = poSrcDS->GetRasterXSize();
-    int  nYSize = poSrcDS->GetRasterYSize();
-
-    int bGenerateEXIFThumbnail =
-        CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "EXIF_THUMBNAIL", "NO"));
-    const char* pszThumbnailWidth = CSLFetchNameValue(papszOptions, "THUMBNAIL_WIDTH");
-    const char* pszThumbnailHeight = CSLFetchNameValue(papszOptions, "THUMBNAIL_HEIGHT");
-    int nOvrWidth = 0, nOvrHeight = 0;
+    const int nBands = poSrcDS->GetRasterCount();
+    const int nXSize = poSrcDS->GetRasterXSize();
+    const int nYSize = poSrcDS->GetRasterYSize();
+
+    bool bGenerateEXIFThumbnail =
+        CPLTestBool(CSLFetchNameValueDef(papszOptions, "EXIF_THUMBNAIL", "NO"));
+    const char* pszThumbnailWidth =
+        CSLFetchNameValue(papszOptions, "THUMBNAIL_WIDTH");
+    const char* pszThumbnailHeight =
+        CSLFetchNameValue(papszOptions, "THUMBNAIL_HEIGHT");
+    int nOvrWidth = 0;
+    int nOvrHeight = 0;
     if( pszThumbnailWidth == NULL && pszThumbnailHeight == NULL )
     {
         if( nXSize >= nYSize )
@@ -3035,32 +3113,38 @@ void   JPGAddEXIFOverview( GDALDataType eWorkDT,
     }
     if( nOvrWidth == 0 )
     {
-        nOvrWidth = (int)((GIntBig)nOvrHeight * nXSize / nYSize);
+        nOvrWidth = static_cast<int>(
+            static_cast<GIntBig>(nOvrHeight) * nXSize / nYSize);
         if( nOvrWidth == 0 ) nOvrWidth = 1;
     }
     else if( nOvrHeight == 0 )
     {
-        nOvrHeight = (int)((GIntBig)nOvrWidth * nYSize / nXSize);
+        nOvrHeight = static_cast<int>(
+            static_cast<GIntBig>(nOvrWidth) * nYSize / nXSize);
         if( nOvrHeight == 0 ) nOvrHeight = 1;
     }
 
     if( bGenerateEXIFThumbnail && nXSize > nOvrWidth && nYSize > nOvrHeight )
     {
-        GDALDataset* poMemDS = MEMDataset::Create("", nOvrWidth, nOvrHeight, nBands, eWorkDT, NULL);
-        GDALRasterBand** papoSrcBands = (GDALRasterBand**)CPLMalloc(nBands * sizeof(GDALRasterBand*));
-        GDALRasterBand*** papapoOverviewBands= (GDALRasterBand***)CPLMalloc(nBands * sizeof(GDALRasterBand**));
-        int i;
-        for(i=0;i<nBands;i++)
+        GDALDataset* poMemDS =
+            MEMDataset::Create( "", nOvrWidth, nOvrHeight, nBands,
+                                eWorkDT, NULL );
+        GDALRasterBand** papoSrcBands = static_cast<GDALRasterBand **>(
+            CPLMalloc(nBands * sizeof(GDALRasterBand*) ) );
+        GDALRasterBand*** papapoOverviewBands = static_cast<GDALRasterBand***>(
+            CPLMalloc(nBands * sizeof(GDALRasterBand**)) );
+        for(int i=0;i<nBands;i++)
         {
             papoSrcBands[i] = poSrcDS->GetRasterBand(i+1);
-            papapoOverviewBands[i] = (GDALRasterBand**)CPLMalloc(sizeof(GDALRasterBand*));
+            papapoOverviewBands[i] = static_cast<GDALRasterBand **>(
+                CPLMalloc(sizeof(GDALRasterBand*)) );
             papapoOverviewBands[i][0] = poMemDS->GetRasterBand(i+1);
         }
-        CPLErr eErr = GDALRegenerateOverviewsMultiBand(nBands, papoSrcBands,
-                                        1, papapoOverviewBands,
-                                        "AVERAGE", NULL, NULL);
+        CPLErr eErr = GDALRegenerateOverviewsMultiBand( nBands, papoSrcBands,
+                                                        1, papapoOverviewBands,
+                                                        "AVERAGE", NULL, NULL );
         CPLFree(papoSrcBands);
-        for(i=0;i<nBands;i++)
+        for(int i=0;i<nBands;i++)
         {
             CPLFree(papapoOverviewBands[i]);
         }
@@ -3073,19 +3157,24 @@ void   JPGAddEXIFOverview( GDALDataType eWorkDT,
         }
 
         CPLString osTmpFile(CPLSPrintf("/vsimem/ovrjpg%p",poMemDS));
-        GDALDataset* poOutDS = pCreateCopy(osTmpFile, poMemDS, 0, NULL, GDALDummyProgress, NULL);
+        GDALDataset* poOutDS =
+            pCreateCopy(osTmpFile, poMemDS, 0, NULL, GDALDummyProgress, NULL);
+        bool bExifOverviewSuccess = poOutDS != NULL;
         delete poOutDS;
+        poOutDS = NULL;
         GDALClose(poMemDS);
         vsi_l_offset nJPEGIfByteCount = 0;
         GByte* pabyOvr = NULL;
-        if( poOutDS != NULL )
+        if( bExifOverviewSuccess )
             pabyOvr = VSIGetMemFileBuffer( osTmpFile, &nJPEGIfByteCount, TRUE );
         VSIUnlink(osTmpFile);
 
-        unsigned int nMarkerSize = 6 + 16 + 5 * 12 + 4 + nJPEGIfByteCount;
+        const unsigned int nMarkerSize =
+            6 + 16 + 5 * 12 + 4 + static_cast<unsigned int>(nJPEGIfByteCount);
         if( pabyOvr == NULL )
         {
-            CPLError(CE_Warning, CPLE_AppDefined, "Could not generate EXIF overview");
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Could not generate EXIF overview" );
         }
         else if( nMarkerSize < 65536 )
         {
@@ -3097,7 +3186,8 @@ void   JPGAddEXIFOverview( GDALDataType eWorkDT,
             p_jpeg_write_m_byte( cinfo, '\0' );
             p_jpeg_write_m_byte( cinfo, '\0' );
 
-            p_jpeg_write_m_byte( cinfo, TIFF_LITTLEENDIAN & 0xff ); /* TIFF little-endian signature */
+            // TIFF little-endian signature.
+            p_jpeg_write_m_byte( cinfo, TIFF_LITTLEENDIAN & 0xff );
             p_jpeg_write_m_byte( cinfo, TIFF_LITTLEENDIAN >> 8 );
             p_jpeg_write_m_byte( cinfo, TIFF_VERSION );
             p_jpeg_write_m_byte( cinfo, 0x00 );
@@ -3194,23 +3284,27 @@ void   JPGAddEXIFOverview( GDALDataType eWorkDT,
             p_jpeg_write_m_byte( cinfo, 0 );
             p_jpeg_write_m_byte( cinfo, 0 );
 
-            p_jpeg_write_m_byte( cinfo, nJPEGIfByteCount & 0xff );
-            p_jpeg_write_m_byte( cinfo, nJPEGIfByteCount >> 8 );
+            p_jpeg_write_m_byte(
+                cinfo, static_cast<GByte>(nJPEGIfByteCount & 0xff) );
+            p_jpeg_write_m_byte(
+                cinfo, static_cast<GByte>(nJPEGIfByteCount >> 8) );
             p_jpeg_write_m_byte( cinfo, 0 );
             p_jpeg_write_m_byte( cinfo, 0 );
 
-            p_jpeg_write_m_byte( cinfo, 0 ); /* Offset of IFD2 == 0 ==> end of TIFF directory */
+            // Offset of IFD2 == 0 ==> end of TIFF directory.
+            p_jpeg_write_m_byte( cinfo, 0 );
             p_jpeg_write_m_byte( cinfo, 0 );
             p_jpeg_write_m_byte( cinfo, 0 );
             p_jpeg_write_m_byte( cinfo, 0 );
 
-            for(int i=0; i<(int)nJPEGIfByteCount; i++)
+            for( int i=0; i < static_cast<int>(nJPEGIfByteCount); i++ )
                 p_jpeg_write_m_byte( cinfo, pabyOvr[i] );
         }
         else
         {
-            CPLError(CE_Warning, CPLE_AppDefined,
-                     "Cannot write EXIF thumbnail. The size of the EXIF segment exceeds 65536 bytes");
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Cannot write EXIF thumbnail. "
+                      "The size of the EXIF segment exceeds 65536 bytes" );
         }
         CPLFree(pabyOvr);
     }
@@ -3228,23 +3322,16 @@ JPGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                         GDALProgressFunc pfnProgress, void * pProgressData )
 
 {
-    int  nBands = poSrcDS->GetRasterCount();
-    int  nXSize = poSrcDS->GetRasterXSize();
-    int  nYSize = poSrcDS->GetRasterYSize();
-    int  nQuality = 75;
-    int  bProgressive = FALSE;
-    int  nCloneFlags = GCIF_PAM_DEFAULT;
-    const char* pszVal;
-
     if( !pfnProgress( 0.0, NULL, pProgressData ) )
         return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Some some rudimentary checks                                    */
 /* -------------------------------------------------------------------- */
+    const int nBands = poSrcDS->GetRasterCount();
     if( nBands != 1 && nBands != 3 && nBands != 4 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "JPEG driver doesn't support %d bands.  Must be 1 (grey), "
                   "3 (RGB) or 4 bands.\n", nBands );
 
@@ -3254,85 +3341,96 @@ JPGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     if (nBands == 1 &&
         poSrcDS->GetRasterBand(1)->GetColorTable() != NULL)
     {
-        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, 
+        CPLError( bStrict ? CE_Failure : CE_Warning, CPLE_NotSupported,
                   "JPEG driver ignores color table. "
                   "The source raster band will be considered as grey level.\n"
-                  "Consider using color table expansion (-expand option in gdal_translate)\n");
+                  "Consider using color table expansion "
+                  "(-expand option in gdal_translate)" );
         if (bStrict)
             return NULL;
     }
 
+    VSILFILE *fpImage = NULL;
+    GDALJPEGErrorStruct sErrorStruct;
+    sErrorStruct.bNonFatalErrorEncountered = FALSE;
+
+    if (setjmp(sErrorStruct.setjmp_buffer))
+    {
+        if( fpImage )
+            VSIFCloseL( fpImage );
+        return NULL;
+    }
+
     GDALDataType eDT = poSrcDS->GetRasterBand(1)->GetRasterDataType();
 
 #if defined(JPEG_LIB_MK1_OR_12BIT) || defined(JPEG_DUAL_MODE_8_12)
     if( eDT != GDT_Byte && eDT != GDT_UInt16 )
     {
-        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, 
+        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
                   "JPEG driver doesn't support data type %s. "
                   "Only eight and twelve bit bands supported (Mk1 libjpeg).\n",
-                  GDALGetDataTypeName( 
+                  GDALGetDataTypeName(
                       poSrcDS->GetRasterBand(1)->GetRasterDataType()) );
 
-        if (bStrict)
+        if( bStrict )
             return NULL;
     }
 
     if( eDT == GDT_UInt16 || eDT == GDT_Int16 )
     {
 #if defined(JPEG_DUAL_MODE_8_12) && !defined(JPGDataset)
-        return JPEGDataset12CreateCopy(pszFilename, poSrcDS,
-                                bStrict, papszOptions, 
-                                pfnProgress, pProgressData );
+        return JPEGDataset12CreateCopy( pszFilename, poSrcDS,
+                                        bStrict, papszOptions,
+                                        pfnProgress, pProgressData );
 #else
         eDT = GDT_UInt16;
 #endif
     }
     else
+    {
         eDT = GDT_Byte;
+    }
 
 #else
     if( eDT != GDT_Byte )
     {
-        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, 
+        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
                   "JPEG driver doesn't support data type %s. "
-                  "Only eight bit byte bands supported.\n", 
-                  GDALGetDataTypeName( 
+                  "Only eight bit byte bands supported.\n",
+                  GDALGetDataTypeName(
                       poSrcDS->GetRasterBand(1)->GetRasterDataType()) );
 
-        if (bStrict)
+        if( bStrict )
             return NULL;
     }
-    
-    eDT = GDT_Byte; // force to 8bit. 
+
+    eDT = GDT_Byte; // force to 8bit.
 #endif
 
 /* -------------------------------------------------------------------- */
 /*      What options has the user selected?                             */
 /* -------------------------------------------------------------------- */
-    if( CSLFetchNameValue(papszOptions,"QUALITY") != NULL )
+    int nQuality = 75;
+    if( CSLFetchNameValue(papszOptions, "QUALITY") != NULL )
     {
-        nQuality = atoi(CSLFetchNameValue(papszOptions,"QUALITY"));
+        nQuality = atoi(CSLFetchNameValue(papszOptions, "QUALITY"));
         if( nQuality < 10 || nQuality > 100 )
         {
             CPLError( CE_Failure, CPLE_IllegalArg,
                       "QUALITY=%s is not a legal value in the range 10-100.",
-                      CSLFetchNameValue(papszOptions,"QUALITY") );
+                      CSLFetchNameValue(papszOptions, "QUALITY") );
             return NULL;
         }
     }
 
-    bProgressive = CSLFetchBoolean( papszOptions, "PROGRESSIVE", FALSE );
-
 /* -------------------------------------------------------------------- */
 /*      Create the dataset.                                             */
 /* -------------------------------------------------------------------- */
-    VSILFILE	*fpImage;
-
     fpImage = VSIFOpenL( pszFilename, "wb" );
     if( fpImage == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Unable to create jpeg file %s.\n", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Unable to create jpeg file %s.\n",
                   pszFilename );
         return NULL;
     }
@@ -3340,27 +3438,21 @@ JPGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Initialize JPG access to the file.                              */
 /* -------------------------------------------------------------------- */
+
     struct jpeg_compress_struct sCInfo;
     struct jpeg_error_mgr sJErr;
-    GDALJPEGErrorStruct sErrorStruct;
-    sErrorStruct.bNonFatalErrorEncountered = FALSE;
-    
-    if (setjmp(sErrorStruct.setjmp_buffer)) 
-    {
-        VSIFCloseL( fpImage );
-        return NULL;
-    }
-
     sCInfo.err = jpeg_std_error( &sJErr );
     sJErr.error_exit = JPGDataset::ErrorExit;
     sErrorStruct.p_previous_emit_message = sJErr.emit_message;
-    sJErr.emit_message = JPGDatasetCommon::EmitMessage;
-    sCInfo.client_data = (void *) &(sErrorStruct);
+    sJErr.emit_message = JPGDataset::EmitMessage;
+    sCInfo.client_data = reinterpret_cast<void *>( &(sErrorStruct) );
 
     jpeg_create_compress( &sCInfo );
-    
+
     jpeg_vsiio_dest( &sCInfo, fpImage );
-    
+
+    const int nXSize = poSrcDS->GetRasterXSize();
+    const int nYSize = poSrcDS->GetRasterYSize();
     sCInfo.image_width = nXSize;
     sCInfo.image_height = nYSize;
     sCInfo.input_components = nBands;
@@ -3377,8 +3469,8 @@ JPGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     /* This is to address bug related in ticket #1795 */
     if (CPLGetConfigOption("JPEGMEM", NULL) == NULL)
     {
-        /* If the user doesn't provide a value for JPEGMEM, we want to be sure */
-        /* that at least 500 MB will be used before creating the temporary file */
+        // If the user doesn't provide a value for JPEGMEM, we want to be sure
+        // that at least 500 MB will be used before creating the temporary file.
         sCInfo.mem->max_memory_to_use =
                 MAX(sCInfo.mem->max_memory_to_use, 500 * 1024 * 1024);
     }
@@ -3392,9 +3484,9 @@ JPGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         sCInfo.data_precision = 8;
     }
 
-    pszVal = CSLFetchNameValue(papszOptions, "ARITHMETIC");
+    const char* pszVal = CSLFetchNameValue(papszOptions, "ARITHMETIC");
     if( pszVal )
-        sCInfo.arith_code = CSLTestBoolean(pszVal);
+        sCInfo.arith_code = CPLTestBool(pszVal);
 
     /* Optimized Huffman coding. Supposedly slower according to libjpeg doc */
     /* but no longer significant with today computer standards */
@@ -3412,93 +3504,99 @@ JPGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     pszVal = CSLFetchNameValue(papszOptions, "COLOR_TRANSFORM");
     if( pszVal )
     {
-        sCInfo.color_transform = EQUAL(pszVal, "RGB1") ? JCT_SUBTRACT_GREEN : JCT_NONE;
+        sCInfo.color_transform =
+            EQUAL(pszVal, "RGB1") ? JCT_SUBTRACT_GREEN : JCT_NONE;
         jpeg_set_colorspace(&sCInfo, JCS_RGB);
     }
     else
 #endif
 
     /* Mostly for debugging purposes */
-    if( nBands == 3 && CSLTestBoolean(CPLGetConfigOption("JPEG_WRITE_RGB", "NO")) )
+    if( nBands == 3 && CPLTestBool(CPLGetConfigOption("JPEG_WRITE_RGB", "NO")) )
     {
         jpeg_set_colorspace(&sCInfo, JCS_RGB);
     }
 
-    GDALDataType eWorkDT;
 #ifdef JPEG_LIB_MK1
     sCInfo.bits_in_jsample = sCInfo.data_precision;
-    eWorkDT = GDT_UInt16; /* Always force to 16 bit for JPEG_LIB_MK1 */
+    // Always force to 16 bit for JPEG_LIB_MK1
+    const GDALDataType eWorkDT = GDT_UInt16;
 #else
-    eWorkDT = eDT;
+    const GDALDataType eWorkDT = eDT;
 #endif
 
     jpeg_set_quality( &sCInfo, nQuality, TRUE );
 
+    const bool bProgressive
+        = CPL_TO_BOOL(CSLFetchBoolean( papszOptions, "PROGRESSIVE", FALSE ));
     if( bProgressive )
         jpeg_simple_progression( &sCInfo );
 
     jpeg_start_compress( &sCInfo, TRUE );
 
-    JPGAddEXIFOverview( eWorkDT, poSrcDS, papszOptions, 
-                        &sCInfo, jpeg_write_m_header, jpeg_write_m_byte,
-                        CreateCopy ); 
+    JPGAddEXIFOverview( eWorkDT, poSrcDS, papszOptions,
+                        &sCInfo,
+                        (my_jpeg_write_m_header)jpeg_write_m_header,
+                        (my_jpeg_write_m_byte)jpeg_write_m_byte,
+                        CreateCopy );
 
 /* -------------------------------------------------------------------- */
 /*      Add comment if available                                        */
 /* -------------------------------------------------------------------- */
     const char *pszComment = CSLFetchNameValue(papszOptions, "COMMENT");
     if( pszComment )
-        jpeg_write_marker(&sCInfo, JPEG_COM, (const JOCTET*)pszComment,
-                          (unsigned int)strlen(pszComment));
+        jpeg_write_marker( &sCInfo, JPEG_COM,
+                           reinterpret_cast<const JOCTET*>(pszComment),
+                           static_cast<unsigned int>(strlen(pszComment) ) );
 
 /* -------------------------------------------------------------------- */
 /*      Save ICC profile if available                                   */
 /* -------------------------------------------------------------------- */
-    const char *pszICCProfile = CSLFetchNameValue(papszOptions, "SOURCE_ICC_PROFILE");
+    const char *pszICCProfile =
+        CSLFetchNameValue(papszOptions, "SOURCE_ICC_PROFILE");
     if (pszICCProfile == NULL)
-        pszICCProfile = poSrcDS->GetMetadataItem( "SOURCE_ICC_PROFILE", "COLOR_PROFILE" );
+        pszICCProfile =
+            poSrcDS->GetMetadataItem( "SOURCE_ICC_PROFILE", "COLOR_PROFILE" );
 
     if (pszICCProfile != NULL)
         JPGAddICCProfile( &sCInfo, pszICCProfile,
-                          jpeg_write_m_header, jpeg_write_m_byte );
+                          (my_jpeg_write_m_header)jpeg_write_m_header,
+                          (my_jpeg_write_m_byte)jpeg_write_m_byte );
 
 /* -------------------------------------------------------------------- */
 /*      Does the source have a mask?  If so, we will append it to the   */
 /*      jpeg file after the imagery.                                    */
 /* -------------------------------------------------------------------- */
-    int nMaskFlags = poSrcDS->GetRasterBand(1)->GetMaskFlags();
-    int bAppendMask =( !(nMaskFlags & GMF_ALL_VALID)
-        && (nBands == 1 || (nMaskFlags & GMF_PER_DATASET)) );
-
-    bAppendMask &= CSLFetchBoolean( papszOptions, "INTERNAL_MASK", TRUE );
+    const int nMaskFlags = poSrcDS->GetRasterBand(1)->GetMaskFlags();
+    const bool bAppendMask = !(nMaskFlags & GMF_ALL_VALID)
+        && (nBands == 1 || (nMaskFlags & GMF_PER_DATASET))
+        && CPL_TO_BOOL(
+            CSLFetchBoolean( papszOptions, "INTERNAL_MASK", TRUE ) );
 
 /* -------------------------------------------------------------------- */
 /*      Loop over image, copying image data.                            */
 /* -------------------------------------------------------------------- */
-    GByte 	*pabyScanline;
-    CPLErr      eErr = CE_None;
-    int         nWorkDTSize = GDALGetDataTypeSize(eWorkDT) / 8;
-    bool        bClipWarn = false;
-
-    pabyScanline = (GByte *) CPLMalloc( nBands * nXSize * nWorkDTSize );
+    CPLErr eErr = CE_None;
+    const int nWorkDTSize = GDALGetDataTypeSize(eWorkDT) / 8;
+    bool bClipWarn = false;
+    GByte *pabyScanline
+        = static_cast<GByte *>( CPLMalloc( nBands * nXSize * nWorkDTSize ) );
 
     for( int iLine = 0; iLine < nYSize && eErr == CE_None; iLine++ )
     {
-        JSAMPLE      *ppSamples;
-
-        eErr = poSrcDS->RasterIO( GF_Read, 0, iLine, nXSize, 1, 
+        eErr = poSrcDS->RasterIO( GF_Read, 0, iLine, nXSize, 1,
                                   pabyScanline, nXSize, 1, eWorkDT,
                                   nBands, NULL,
-                                  nBands*nWorkDTSize, 
-                                  nBands * nXSize * nWorkDTSize, nWorkDTSize, NULL );
+                                  nBands * nWorkDTSize,
+                                  nBands * nXSize * nWorkDTSize,
+                                  nWorkDTSize, NULL );
 
         // clamp 16bit values to 12bit.
         if( nWorkDTSize == 2 )
         {
-            GUInt16 *panScanline = (GUInt16 *) pabyScanline;
-            int iPixel;
+            GUInt16 *panScanline = reinterpret_cast<GUInt16 *>( pabyScanline );
 
-            for( iPixel = 0; iPixel < nXSize*nBands; iPixel++ )
+            for( int iPixel = 0; iPixel < nXSize*nBands; iPixel++ )
             {
                 if( panScanline[iPixel] > 4095 )
                 {
@@ -3507,23 +3605,26 @@ JPGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                     {
                         bClipWarn = true;
                         CPLError( CE_Warning, CPLE_AppDefined,
-                                  "One or more pixels clipped to fit 12bit domain for jpeg output." );
+                                  "One or more pixels clipped to fit "
+                                  "12bit domain for jpeg output." );
                     }
                 }
             }
         }
 
-        ppSamples = (JSAMPLE *) pabyScanline;
+        JSAMPLE  *ppSamples = reinterpret_cast<JSAMPLE *>( pabyScanline );
 
         if( eErr == CE_None )
             jpeg_write_scanlines( &sCInfo, &ppSamples, 1 );
 
-        if( eErr == CE_None 
-            && !pfnProgress( (iLine+1) / ((bAppendMask ? 2 : 1) * (double) nYSize),
-                             NULL, pProgressData ) )
+        if( eErr == CE_None &&
+            !pfnProgress(
+                (iLine + 1) / ( (bAppendMask ? 2 : 1) *
+                                static_cast<double>(nYSize) ),
+                NULL, pProgressData ) )
         {
             eErr = CE_Failure;
-            CPLError( CE_Failure, CPLE_UserInterrupt, 
+            CPLError( CE_Failure, CPLE_UserInterrupt,
                       "User terminated CreateCopy()" );
         }
     }
@@ -3548,13 +3649,16 @@ JPGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Append masks to the jpeg file if necessary.                     */
 /* -------------------------------------------------------------------- */
+    int nCloneFlags = GCIF_PAM_DEFAULT;
     if( bAppendMask )
     {
         CPLDebug( "JPEG", "Appending Mask Bitmap" );
 
-        void* pScaledData = GDALCreateScaledProgress( 0.5, 1, pfnProgress, pProgressData );
-        eErr = JPGAppendMask( pszFilename, poSrcDS->GetRasterBand(1)->GetMaskBand(),
-                              GDALScaledProgress, pScaledData );
+        void* pScaledData =
+            GDALCreateScaledProgress( 0.5, 1, pfnProgress, pProgressData );
+        eErr = JPGAppendMask(
+            pszFilename, poSrcDS->GetRasterBand(1)->GetMaskBand(),
+            GDALScaledProgress, pScaledData );
         GDALDestroyScaledProgress( pScaledData );
         nCloneFlags &= (~GCIF_MASK);
 
@@ -3570,22 +3674,32 @@ JPGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
     if( CSLFetchBoolean( papszOptions, "WORLDFILE", FALSE ) )
     {
-	double      adfGeoTransform[6];
-	
-	poSrcDS->GetGeoTransform( adfGeoTransform );
-	GDALWriteWorldFile( pszFilename, "wld", adfGeoTransform );
+        double adfGeoTransform[6] = { 0.0 };
+
+        poSrcDS->GetGeoTransform( adfGeoTransform );
+        GDALWriteWorldFile( pszFilename, "wld", adfGeoTransform );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Re-open dataset, and copy any auxiliary pam information.         */
 /* -------------------------------------------------------------------- */
 
-    /* If outputing to stdout, we can't reopen it, so we'll return */
+    /* If writing to stdout, we can't reopen it, so return */
     /* a fake dataset to make the caller happy */
-    if( CSLTestBoolean(CPLGetConfigOption("GDAL_OPEN_AFTER_COPY", "YES")) )
+    if( CPLTestBool(CPLGetConfigOption("GDAL_OPEN_AFTER_COPY", "YES")) )
     {
         CPLPushErrorHandler(CPLQuietErrorHandler);
-        JPGDataset *poDS = (JPGDataset*) Open( pszFilename, NULL, NULL, 1, TRUE );
+
+        JPGDatasetOpenArgs sArgs;
+        sArgs.pszFilename = pszFilename;
+        sArgs.fpLin = NULL;
+        sArgs.papszSiblingFiles = NULL;
+        sArgs.nScaleFactor = 1;
+        sArgs.bDoPAMInitialize = TRUE;
+        sArgs.bUseInternalOverviews = TRUE;
+
+        // TODO(schwehr): Dynamic cast?
+        JPGDataset *poDS = (JPGDataset*) Open( &sArgs );
         CPLPopErrorHandler();
         if( poDS )
         {
@@ -3629,25 +3743,25 @@ char** GDALJPGDriver::GetMetadata( const char * pszDomain )
 
 static void GDALJPEGIsArithmeticCodingAvailableErrorExit(j_common_ptr cinfo)
 {
-    jmp_buf* p_setjmp_buffer = (jmp_buf* ) cinfo->client_data;
+    jmp_buf* p_setjmp_buffer = static_cast<jmp_buf *>( cinfo->client_data );
     /* Return control to the setjmp point */
     longjmp(*p_setjmp_buffer, 1);
 }
 
 /* Runtime check if arithmetic coding is available */
-static int GDALJPEGIsArithmeticCodingAvailable()
+static bool GDALJPEGIsArithmeticCodingAvailable()
 {
     struct jpeg_compress_struct sCInfo;
     struct jpeg_error_mgr sJErr;
     jmp_buf     setjmp_buffer;
-    if (setjmp(setjmp_buffer)) 
+    if (setjmp(setjmp_buffer))
     {
         jpeg_destroy_compress( &sCInfo );
-        return FALSE;
+        return false;
     }
     sCInfo.err = jpeg_std_error( &sJErr );
     sJErr.error_exit = GDALJPEGIsArithmeticCodingAvailableErrorExit;
-    sCInfo.client_data = (void *) &(setjmp_buffer);
+    sCInfo.client_data = reinterpret_cast<void *>( &(setjmp_buffer) );
     jpeg_create_compress( &sCInfo );
     /* Hopefully nothing will be written */
     jpeg_stdio_dest(&sCInfo, stderr);
@@ -3660,8 +3774,8 @@ static int GDALJPEGIsArithmeticCodingAvailable()
     jpeg_start_compress( &sCInfo, FALSE );
     jpeg_abort_compress( &sCInfo );
     jpeg_destroy_compress( &sCInfo );
-    
-    return TRUE;
+
+    return true;
 }
 
 const char *GDALJPGDriver::GetMetadataItem( const char * pszName,
@@ -3675,7 +3789,7 @@ const char *GDALJPGDriver::GetMetadataItem( const char * pszName,
 "<CreationOptionList>\n"
 "   <Option name='PROGRESSIVE' type='boolean' description='whether to generate a progressive JPEG' default='NO'/>\n"
 "   <Option name='QUALITY' type='int' description='good=100, bad=0, default=75'/>\n"
-"   <Option name='WORLDFILE' type='boolean' description='whether to geneate a worldfile' default='NO'/>\n"
+"   <Option name='WORLDFILE' type='boolean' description='whether to generate a worldfile' default='NO'/>\n"
 "   <Option name='INTERNAL_MASK' type='boolean' description='whether to generate a validity mask' default='YES'/>\n";
         if( GDALJPEGIsArithmeticCodingAvailable() )
             osCreationOptions +=
@@ -3705,36 +3819,35 @@ const char *GDALJPGDriver::GetMetadataItem( const char * pszName,
 void GDALRegister_JPEG()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "JPEG" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "JPEG" ) == NULL )
-    {
-        poDriver = new GDALJPGDriver();
-        
-        poDriver->SetDescription( "JPEG" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "JPEG JFIF" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_jpeg.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jpg" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "jpg jpeg" );
-        poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/jpeg" );
+    GDALDriver *poDriver = new GDALJPGDriver();
+
+    poDriver->SetDescription( "JPEG" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "JPEG JFIF" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_jpeg.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jpg" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "jpg jpeg" );
+    poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/jpeg" );
 
 #if defined(JPEG_LIB_MK1_OR_12BIT) || defined(JPEG_DUAL_MODE_8_12)
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte UInt16" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte UInt16" );
 #else
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte" );
 #endif
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnIdentify = JPGDatasetCommon::Identify;
-        poDriver->pfnOpen = JPGDatasetCommon::Open;
-        poDriver->pfnCreateCopy = JPGDataset::CreateCopy;
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+"<OpenOptionList>\n"
+"   <Option name='USE_INTERNAL_OVERVIEWS' type='boolean' description='whether to use implicit internal overviews' default='YES'/>\n"
+"</OpenOptionList>\n");
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    poDriver->pfnIdentify = JPGDatasetCommon::Identify;
+    poDriver->pfnOpen = JPGDatasetCommon::Open;
+    poDriver->pfnCreateCopy = JPGDataset::CreateCopy;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
 #endif
diff --git a/frmts/jpeg/jpgdataset_12.cpp b/frmts/jpeg/jpgdataset_12.cpp
index 6115370..f8a68a5 100644
--- a/frmts/jpeg/jpgdataset_12.cpp
+++ b/frmts/jpeg/jpgdataset_12.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: jpgdataset_12.cpp 28028 2014-11-30 11:46:11Z rouault $
+ * $Id: jpgdataset_12.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  JPEG JFIF Driver
  * Purpose:  Implement GDAL JPEG Support based on IJG libjpeg.
@@ -28,18 +28,27 @@
  ****************************************************************************/
 
 #if defined(JPEG_DUAL_MODE_8_12)
-#define LIBJPEG_12_PATH   "libjpeg12/jpeglib.h" 
+
+#undef ENABLE_LIBJPEG_NO_RETURN
+
+#define LIBJPEG_12_PATH   "libjpeg12/jpeglib.h"
 #define JPGDataset        JPGDataset12
+#define GDALJPEGErrorStruct     GDALJPEGErrorStruct12
+#define jpeg_vsiio_src    jpeg_vsiio_src_12
+#define jpeg_vsiio_dest   jpeg_vsiio_dest_12
+
 #include "jpgdataset.cpp"
 
-GDALDataset* JPEGDataset12Open(const char* pszFilename,
-                               VSILFILE* fpLin,
-                               char** papszSiblingFiles,
-                               int nScaleFactor,
-                               int bDoPAMInitialize)
+GDALDataset* JPEGDataset12Open(JPGDatasetOpenArgs* psArgs);
+GDALDataset* JPEGDataset12CreateCopy( const char * pszFilename,
+                                    GDALDataset *poSrcDS,
+                                    int bStrict, char ** papszOptions,
+                                    GDALProgressFunc pfnProgress,
+                                    void * pProgressData );
+
+GDALDataset* JPEGDataset12Open(JPGDatasetOpenArgs* psArgs)
 {
-    return JPGDataset12::Open(pszFilename, fpLin, papszSiblingFiles, nScaleFactor,
-                              bDoPAMInitialize);
+    return JPGDataset12::Open(psArgs);
 }
 
 GDALDataset* JPEGDataset12CreateCopy( const char * pszFilename,
diff --git a/frmts/jpeg/libjpeg/jccoefct.c b/frmts/jpeg/libjpeg/jccoefct.c
index 6c1d57f..3c55893 100644
--- a/frmts/jpeg/libjpeg/jccoefct.c
+++ b/frmts/jpeg/libjpeg/jccoefct.c
@@ -133,7 +133,7 @@ start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
 /*
  * Process some data in the single-pass case.
  * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
- * per call, ie, v_samp_factor block rows for each component in the image.
+ * per call, i.e. v_samp_factor block rows for each component in the image.
  * Returns TRUE if the iMCU row is completed, FALSE if suspended.
  *
  * NB: input_buf contains a plane for each component in image,
@@ -224,7 +224,7 @@ compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
 /*
  * Process some data in the first pass of a multi-pass case.
  * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
- * per call, ie, v_samp_factor block rows for each component in the image.
+ * per call, i.e. v_samp_factor block rows for each component in the image.
  * This amount of data is read from the source buffer, DCT'd and quantized,
  * and saved into the virtual arrays.  We also generate suitable dummy blocks
  * as needed at the right and lower edges.  (The dummy blocks are constructed
diff --git a/frmts/jpeg/libjpeg/jcmarker.c b/frmts/jpeg/libjpeg/jcmarker.c
index 125a15d..6c86aa1 100644
--- a/frmts/jpeg/libjpeg/jcmarker.c
+++ b/frmts/jpeg/libjpeg/jcmarker.c
@@ -142,16 +142,16 @@ emit_2bytes (j_compress_ptr cinfo, int value)
  */
 
 LOCAL(int)
-emit_dqt (j_compress_ptr cinfo, int index)
+emit_dqt (j_compress_ptr cinfo, int l_index)
 /* Emit a DQT marker */
 /* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */
 {
-  JQUANT_TBL * qtbl = cinfo->quant_tbl_ptrs[index];
+  JQUANT_TBL * qtbl = cinfo->quant_tbl_ptrs[l_index];
   int prec;
   int i;
 
   if (qtbl == NULL)
-    ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, index);
+    ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, l_index);
 
   prec = 0;
   for (i = 0; i < DCTSIZE2; i++) {
@@ -164,7 +164,7 @@ emit_dqt (j_compress_ptr cinfo, int index)
 
     emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2);
 
-    emit_byte(cinfo, index + (prec<<4));
+    emit_byte(cinfo, l_index + (prec<<4));
 
     for (i = 0; i < DCTSIZE2; i++) {
       /* The table entries must be emitted in zigzag order. */
@@ -182,21 +182,21 @@ emit_dqt (j_compress_ptr cinfo, int index)
 
 
 LOCAL(void)
-emit_dht (j_compress_ptr cinfo, int index, boolean is_ac)
+emit_dht (j_compress_ptr cinfo, int l_index, boolean is_ac)
 /* Emit a DHT marker */
 {
   JHUFF_TBL * htbl;
   int length, i;
   
   if (is_ac) {
-    htbl = cinfo->ac_huff_tbl_ptrs[index];
-    index += 0x10;		/* output index has AC bit set */
+    htbl = cinfo->ac_huff_tbl_ptrs[l_index];
+    l_index += 0x10;		/* output l_index has AC bit set */
   } else {
-    htbl = cinfo->dc_huff_tbl_ptrs[index];
+    htbl = cinfo->dc_huff_tbl_ptrs[l_index];
   }
 
   if (htbl == NULL)
-    ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, index);
+    ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, l_index);
   
   if (! htbl->sent_table) {
     emit_marker(cinfo, M_DHT);
@@ -206,7 +206,7 @@ emit_dht (j_compress_ptr cinfo, int index, boolean is_ac)
       length += htbl->bits[i];
     
     emit_2bytes(cinfo, length + 2 + 1 + 16);
-    emit_byte(cinfo, index);
+    emit_byte(cinfo, l_index);
     
     for (i = 1; i <= 16; i++)
       emit_byte(cinfo, htbl->bits[i]);
diff --git a/frmts/jpeg/libjpeg/jcparam.c b/frmts/jpeg/libjpeg/jcparam.c
index 6f987d8..be95a0b 100644
--- a/frmts/jpeg/libjpeg/jcparam.c
+++ b/frmts/jpeg/libjpeg/jcparam.c
@@ -670,7 +670,7 @@ jpeg_simple_progression (j_compress_ptr cinfo)
     scanptr = fill_a_scan(scanptr, 2, 1, 63, 1, 0);
     scanptr = fill_a_scan(scanptr, 1, 1, 63, 1, 0);
     /* Luma bottom bit comes last since it's usually largest scan */
-    scanptr = fill_a_scan(scanptr, 0, 1, 63, 1, 0);
+    /*scanptr = */fill_a_scan(scanptr, 0, 1, 63, 1, 0);
   } else {
     /* All-purpose script for other color spaces. */
     /* Successive approximation first pass */
@@ -681,7 +681,7 @@ jpeg_simple_progression (j_compress_ptr cinfo)
     scanptr = fill_scans(scanptr, ncomps, 1, 63, 2, 1);
     /* Successive approximation final pass */
     scanptr = fill_dc_scans(scanptr, ncomps, 1, 0);
-    scanptr = fill_scans(scanptr, ncomps, 1, 63, 1, 0);
+    /*scanptr = */fill_scans(scanptr, ncomps, 1, 63, 1, 0);
   }
 }
 
diff --git a/frmts/jpeg/libjpeg/jcsample.c b/frmts/jpeg/libjpeg/jcsample.c
index c544c7d..a3618c6 100644
--- a/frmts/jpeg/libjpeg/jcsample.c
+++ b/frmts/jpeg/libjpeg/jcsample.c
@@ -29,7 +29,7 @@
  *   Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.
  *
  * The downsampling algorithm used here is a simple average of the source
- * pixels covered by the output pixel.  The hi-falutin sampling literature
+ * pixels covered by the output pixel.  The highfalutin sampling literature
  * refers to this as a "box filter".  In general the characteristics of a box
  * filter are not very good, but for the specific cases we normally use (1:1
  * and 2:1 ratios) the box is equivalent to a "triangle filter" which is not
diff --git a/frmts/jpeg/libjpeg/jdhuff.c b/frmts/jpeg/libjpeg/jdhuff.c
index a87274e..f843cc8 100644
--- a/frmts/jpeg/libjpeg/jdhuff.c
+++ b/frmts/jpeg/libjpeg/jdhuff.c
@@ -457,10 +457,7 @@ static const int extend_test[16] =   /* entry n is 2**(n-1) */
     0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
 
 static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
-  { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
-    ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
-    ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
-    ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 };
+  { 0, -1, -3, -7, -15, -31, -63, -127, -255, -511, -1023, -2047, -4095, -8191, -16383, -32767 };
 
 #endif /* AVOID_TABLES */
 
diff --git a/frmts/jpeg/libjpeg/jdinput.c b/frmts/jpeg/libjpeg/jdinput.c
index 0c2ac8f..a08e8ba 100644
--- a/frmts/jpeg/libjpeg/jdinput.c
+++ b/frmts/jpeg/libjpeg/jdinput.c
@@ -306,7 +306,7 @@ consume_markers (j_decompress_ptr cinfo)
        */
     } else {			/* 2nd or later SOS marker */
       if (! inputctl->pub.has_multiple_scans)
-	ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */
+	ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I was not expecting this! */
       start_input_pass(cinfo);
     }
     break;
diff --git a/frmts/jpeg/libjpeg/jdmarker.c b/frmts/jpeg/libjpeg/jdmarker.c
index c9325af..b526900 100644
--- a/frmts/jpeg/libjpeg/jdmarker.c
+++ b/frmts/jpeg/libjpeg/jdmarker.c
@@ -380,29 +380,29 @@ get_dac (j_decompress_ptr cinfo)
 /* Process a DAC marker */
 {
   INT32 length;
-  int index, val;
+  int l_index, val;
   INPUT_VARS(cinfo);
 
   INPUT_2BYTES(cinfo, length, return FALSE);
   length -= 2;
   
   while (length > 0) {
-    INPUT_BYTE(cinfo, index, return FALSE);
+    INPUT_BYTE(cinfo, l_index, return FALSE);
     INPUT_BYTE(cinfo, val, return FALSE);
 
     length -= 2;
 
-    TRACEMS2(cinfo, 1, JTRC_DAC, index, val);
+    TRACEMS2(cinfo, 1, JTRC_DAC, l_index, val);
 
-    if (index < 0 || index >= (2*NUM_ARITH_TBLS))
-      ERREXIT1(cinfo, JERR_DAC_INDEX, index);
+    if (l_index < 0 || l_index >= (2*NUM_ARITH_TBLS))
+      ERREXIT1(cinfo, JERR_DAC_INDEX, l_index);
 
-    if (index >= NUM_ARITH_TBLS) { /* define AC table */
-      cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = (UINT8) val;
+    if (l_index >= NUM_ARITH_TBLS) { /* define AC table */
+      cinfo->arith_ac_K[l_index-NUM_ARITH_TBLS] = (UINT8) val;
     } else {			/* define DC table */
-      cinfo->arith_dc_L[index] = (UINT8) (val & 0x0F);
-      cinfo->arith_dc_U[index] = (UINT8) (val >> 4);
-      if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index])
+      cinfo->arith_dc_L[l_index] = (UINT8) (val & 0x0F);
+      cinfo->arith_dc_U[l_index] = (UINT8) (val >> 4);
+      if (cinfo->arith_dc_L[l_index] > cinfo->arith_dc_U[l_index])
 	ERREXIT1(cinfo, JERR_DAC_VALUE, val);
     }
   }
@@ -428,7 +428,7 @@ get_dht (j_decompress_ptr cinfo)
   INT32 length;
   UINT8 bits[17];
   UINT8 huffval[256];
-  int i, index, count;
+  int i, l_index, count;
   JHUFF_TBL **htblptr;
   INPUT_VARS(cinfo);
 
@@ -436,9 +436,9 @@ get_dht (j_decompress_ptr cinfo)
   length -= 2;
   
   while (length > 16) {
-    INPUT_BYTE(cinfo, index, return FALSE);
+    INPUT_BYTE(cinfo, l_index, return FALSE);
 
-    TRACEMS1(cinfo, 1, JTRC_DHT, index);
+    TRACEMS1(cinfo, 1, JTRC_DHT, l_index);
       
     bits[0] = 0;
     count = 0;
@@ -467,16 +467,17 @@ get_dht (j_decompress_ptr cinfo)
 
     length -= count;
 
-    if (index & 0x10) {		/* AC table definition */
-      index -= 0x10;
-      htblptr = &cinfo->ac_huff_tbl_ptrs[index];
+    if (l_index & 0x10) {		/* AC table definition */
+      l_index -= 0x10;
+      if (l_index < 0 || l_index >= NUM_HUFF_TBLS)
+        ERREXIT1(cinfo, JERR_DHT_INDEX, l_index);
+      htblptr = &cinfo->ac_huff_tbl_ptrs[l_index];
     } else {			/* DC table definition */
-      htblptr = &cinfo->dc_huff_tbl_ptrs[index];
+      if (l_index < 0 || l_index >= NUM_HUFF_TBLS)
+        ERREXIT1(cinfo, JERR_DHT_INDEX, l_index);
+      htblptr = &cinfo->dc_huff_tbl_ptrs[l_index];
     }
 
-    if (index < 0 || index >= NUM_HUFF_TBLS)
-      ERREXIT1(cinfo, JERR_DHT_INDEX, index);
-
     if (*htblptr == NULL)
       *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
   
@@ -1310,7 +1311,7 @@ jpeg_save_markers (j_decompress_ptr cinfo, int marker_code,
   long maxlength;
   jpeg_marker_parser_method processor;
 
-  /* Length limit mustn't be larger than what we can allocate
+  /* Length limit must not be larger than what we can allocate
    * (should only be a concern in a 16-bit environment).
    */
   maxlength = cinfo->mem->max_alloc_chunk - SIZEOF(struct jpeg_marker_struct);
diff --git a/frmts/jpeg/libjpeg/jdmaster.c b/frmts/jpeg/libjpeg/jdmaster.c
index 2802c5b..7f0849a 100644
--- a/frmts/jpeg/libjpeg/jdmaster.c
+++ b/frmts/jpeg/libjpeg/jdmaster.c
@@ -76,7 +76,7 @@ use_merged_upsample (j_decompress_ptr cinfo)
 /*
  * Compute output image dimensions and related values.
  * NOTE: this is exported for possible use by application.
- * Hence it mustn't do anything that can't be done twice.
+ * Hence it must not do anything that can't be done twice.
  * Also note that it may be called before the master module is initialized!
  */
 
diff --git a/frmts/jpeg/libjpeg/jdphuff.c b/frmts/jpeg/libjpeg/jdphuff.c
index 2267809..cf6fc20 100644
--- a/frmts/jpeg/libjpeg/jdphuff.c
+++ b/frmts/jpeg/libjpeg/jdphuff.c
@@ -211,10 +211,7 @@ static const int extend_test[16] =   /* entry n is 2**(n-1) */
     0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
 
 static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
-  { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
-    ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
-    ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
-    ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 };
+  { 0, -1, -3, -7, -15, -31, -63, -127, -255, -511, -1023, -2047, -4095, -8191, -16383, -32767 };
 
 #endif /* AVOID_TABLES */
 
diff --git a/frmts/jpeg/libjpeg/jdsample.c b/frmts/jpeg/libjpeg/jdsample.c
index f9979d3..6e1299f 100644
--- a/frmts/jpeg/libjpeg/jdsample.c
+++ b/frmts/jpeg/libjpeg/jdsample.c
@@ -180,7 +180,7 @@ noop_upsample (CPL_UNUSED j_decompress_ptr cinfo, CPL_UNUSED jpeg_component_info
  * This is not used for typical JPEG files, so it need not be fast.
  * Nor, for that matter, is it particularly accurate: the algorithm is
  * simple replication of the input pixel onto the corresponding output
- * pixels.  The hi-falutin sampling literature refers to this as a
+ * pixels.  The highfalutin sampling literature refers to this as a
  * "box filter".  A box filter tends to introduce visible artifacts,
  * so if you are actually going to use 3:1 or 4:1 sampling ratios
  * you would be well advised to improve this code.
diff --git a/frmts/jpeg/libjpeg/jerror.c b/frmts/jpeg/libjpeg/jerror.c
index 09c6c6e..bffbaf0 100644
--- a/frmts/jpeg/libjpeg/jerror.c
+++ b/frmts/jpeg/libjpeg/jerror.c
@@ -71,6 +71,9 @@ const char * const jpeg_std_message_table[] = {
  */
 
 METHODDEF(void)
+error_exit (j_common_ptr cinfo) LIBJPEG_NO_RETURN;
+
+METHODDEF(void)
 error_exit (j_common_ptr cinfo)
 {
   /* Always display the message */
diff --git a/frmts/jpeg/libjpeg/jmemansi.c b/frmts/jpeg/libjpeg/jmemansi.c
index 27a22c5..d8de223 100644
--- a/frmts/jpeg/libjpeg/jmemansi.c
+++ b/frmts/jpeg/libjpeg/jmemansi.c
@@ -143,6 +143,7 @@ GLOBAL(void)
 jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
 			 CPL_UNUSED long total_bytes_needed)
 {
+  /* coverity[secure_temp] */
   if ((info->temp_file = tmpfile()) == NULL)
     ERREXITS(cinfo, JERR_TFILE_CREATE, "");
   info->read_backing_store = read_backing_store;
diff --git a/frmts/jpeg/libjpeg/jmemmgr.c b/frmts/jpeg/libjpeg/jmemmgr.c
index d801b32..410098a 100644
--- a/frmts/jpeg/libjpeg/jmemmgr.c
+++ b/frmts/jpeg/libjpeg/jmemmgr.c
@@ -214,6 +214,9 @@ print_mem_stats (j_common_ptr cinfo, int pool_id)
 
 
 LOCAL(void)
+out_of_memory (j_common_ptr cinfo, int which) LIBJPEG_NO_RETURN;
+
+LOCAL(void)
 out_of_memory (j_common_ptr cinfo, int which)
 /* Report an out-of-memory error and stop execution */
 /* If we compiled MEM_STATS support, report alloc requests before dying */
@@ -303,7 +306,7 @@ alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
       if (slop < MIN_SLOP)	/* give up when it gets real small */
 	out_of_memory(cinfo, 2); /* jpeg_get_small failed */
     }
-    mem->total_space_allocated += min_request + slop;
+    mem->total_space_allocated += (long)(min_request + slop);
     /* Success, initialize the new pool header and add to end of list */
     hdr_ptr->hdr.next = NULL;
     hdr_ptr->hdr.bytes_used = 0;
@@ -363,7 +366,7 @@ alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
 					    SIZEOF(large_pool_hdr));
   if (hdr_ptr == NULL)
     out_of_memory(cinfo, 4);	/* jpeg_get_large failed */
-  mem->total_space_allocated += sizeofobject + SIZEOF(large_pool_hdr);
+  mem->total_space_allocated += (long)(sizeofobject + SIZEOF(large_pool_hdr));
 
   /* Success, initialize the new pool header and add to list */
   hdr_ptr->hdr.next = mem->large_list[pool_id];
@@ -973,7 +976,7 @@ free_pool (j_common_ptr cinfo, int pool_id)
 		  lhdr_ptr->hdr.bytes_left +
 		  SIZEOF(large_pool_hdr);
     jpeg_free_large(cinfo, (void FAR *) lhdr_ptr, space_freed);
-    mem->total_space_allocated -= space_freed;
+    mem->total_space_allocated -= (long)space_freed;
     lhdr_ptr = next_lhdr_ptr;
   }
 
@@ -987,7 +990,7 @@ free_pool (j_common_ptr cinfo, int pool_id)
 		  shdr_ptr->hdr.bytes_left +
 		  SIZEOF(small_pool_hdr);
     jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed);
-    mem->total_space_allocated -= space_freed;
+    mem->total_space_allocated -= (long)space_freed;
     shdr_ptr = next_shdr_ptr;
   }
 }
diff --git a/frmts/jpeg/libjpeg/jmorecfg.h b/frmts/jpeg/libjpeg/jmorecfg.h
index 2c0edf9..c800279 100644
--- a/frmts/jpeg/libjpeg/jmorecfg.h
+++ b/frmts/jpeg/libjpeg/jmorecfg.h
@@ -186,7 +186,7 @@ typedef unsigned int JDIMENSION;
 #define METHODDEF(type)		static type
 /* a function used only in its module: */
 #define LOCAL(type)		static type
-/* a function referenced thru EXTERNs: */
+/* a function referenced through EXTERNs: */
 #define GLOBAL(type)		type
 /* a reference to a GLOBAL function: */
 #define EXTERN(type)		extern type
diff --git a/frmts/jpeg/libjpeg/jpeglib.h b/frmts/jpeg/libjpeg/jpeglib.h
index 100333e..f247ad9 100644
--- a/frmts/jpeg/libjpeg/jpeglib.h
+++ b/frmts/jpeg/libjpeg/jpeglib.h
@@ -640,9 +640,16 @@ struct jpeg_decompress_struct {
 
 /* Error handler object */
 
+#if defined(__GNUC__) && __GNUC__ >= 3 && defined(ENABLE_LIBJPEG_NO_RETURN)
+#define LIBJPEG_NO_RETURN                                __attribute__((noreturn))
+#else
+#define LIBJPEG_NO_RETURN
+#endif
+
+
 struct jpeg_error_mgr {
   /* Error exit handler: does not return to caller */
-  JMETHOD(void, error_exit, (j_common_ptr cinfo));
+  JMETHOD(void, error_exit, (j_common_ptr cinfo)) LIBJPEG_NO_RETURN;
   /* Conditionally emit a trace or warning message */
   JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level));
   /* Routine that actually outputs a trace or error message */
diff --git a/frmts/jpeg/libjpeg/jquant1.c b/frmts/jpeg/libjpeg/jquant1.c
index 56a3dc8..aa424cb 100644
--- a/frmts/jpeg/libjpeg/jquant1.c
+++ b/frmts/jpeg/libjpeg/jquant1.c
@@ -107,7 +107,7 @@ static const UINT8 base_dither_matrix[ODITHER_SIZE][ODITHER_SIZE] = {
  * Errors are accumulated into the array fserrors[], at a resolution of
  * 1/16th of a pixel count.  The error at a given pixel is propagated
  * to its not-yet-processed neighbors using the standard F-S fractions,
- *		...	(here)	7/16
+` *		...	(here)	7/16
  *		3/16	5/16	1/16
  * We work left-to-right on even rows, right-to-left on odd rows.
  *
diff --git a/frmts/jpeg/libjpeg/jquant2.c b/frmts/jpeg/libjpeg/jquant2.c
index f9f597b..7bf2115 100644
--- a/frmts/jpeg/libjpeg/jquant2.c
+++ b/frmts/jpeg/libjpeg/jquant2.c
@@ -531,9 +531,9 @@ compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor)
       }
     }
   
-  cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total);
-  cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total);
-  cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total);
+  cinfo->colormap[0][icolor] = (JSAMPLE) ((total) ? ((c0total + (total>>1)) / total) : 0);
+  cinfo->colormap[1][icolor] = (JSAMPLE) ((total) ? ((c1total + (total>>1)) / total) : 0);
+  cinfo->colormap[2][icolor] = (JSAMPLE) ((total) ? ((c2total + (total>>1)) / total) : 0);
 }
 
 
@@ -1030,7 +1030,7 @@ pass2_fs_dither (j_decompress_ptr cinfo,
       /* If we have not seen this color before, find nearest colormap */
       /* entry and update the cache */
       if (*cachep == 0)
-	fill_inverse_cmap(cinfo, cur0>>C0_SHIFT,cur1>>C1_SHIFT,cur2>>C2_SHIFT);
+	fill_inverse_cmap(cinfo, (int)(cur0>>C0_SHIFT),(int)(cur1>>C1_SHIFT),(int)(cur2>>C2_SHIFT));
       /* Now emit the colormap index for this cell */
       { register int pixcode = *cachep - 1;
 	*outptr = (JSAMPLE) pixcode;
diff --git a/frmts/jpeg/libjpeg12/jmorecfg.h.12 b/frmts/jpeg/libjpeg12/jmorecfg.h.12
index fc671e0..d6c7cb0 100644
--- a/frmts/jpeg/libjpeg12/jmorecfg.h.12
+++ b/frmts/jpeg/libjpeg12/jmorecfg.h.12
@@ -20,6 +20,24 @@
  * We do not support run-time selection of data precision, sorry.
  */
 
+#define jpeg_memory_mgr         jpeg_memory_mgr12
+#define JSAMPLE                 JSAMPLE12
+#define jpeg_decompress_struct  jpeg_decompress_struct12
+#define jpeg_source_mgr         jpeg_source_mgr12
+#define jpeg_decompress_struct  jpeg_decompress_struct12
+#define jpeg_compress_struct    jpeg_compress_struct12
+#define j_compress_ptr          j_compress_ptr12
+#define jpeg_common_struct      jpeg_common_struct12
+#define j_common_ptr            j_common_ptr12
+#define alloc_sarray            alloc_sarray12
+#define JSAMPROW                JSAMPROW12
+#define jpeg_error_mgr          jpeg_error_mgr12
+#define error_exit              error_exit12
+#define jpeg_progress_mgr       jpeg_progress_mgr12
+#define progress_monitor        progress_monitor12
+#define jpeg_destination_mgr    jpeg_destination_mgr12
+#define init_destination        init_destination12
+
 #define BITS_IN_JSAMPLE  12	/* use 8 or 12 */
 #define NEED_12_BIT_NAMES
 
@@ -187,7 +205,7 @@ typedef unsigned int JDIMENSION;
 #define METHODDEF(type)		static type
 /* a function used only in its module: */
 #define LOCAL(type)		static type
-/* a function referenced thru EXTERNs: */
+/* a function referenced through EXTERNs: */
 #define GLOBAL(type)		type
 /* a reference to a GLOBAL function: */
 #define EXTERN(type)		extern type
diff --git a/frmts/jpeg/makefile.vc b/frmts/jpeg/makefile.vc
index 85c8b14..5233906 100644
--- a/frmts/jpeg/makefile.vc
+++ b/frmts/jpeg/makefile.vc
@@ -2,7 +2,7 @@ GDAL_ROOT	=	..\..
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
 
-OBJ	=    jpgdataset.obj jpgdataset_12.obj vsidataio.obj
+OBJ	=    jpgdataset.obj jpgdataset_12.obj vsidataio.obj vsidataio_12.obj
 
 
 !IFDEF JPEG_EXTERNAL_LIB
diff --git a/frmts/jpeg/vsidataio.cpp b/frmts/jpeg/vsidataio.cpp
index f03d5e7..cca3f62 100644
--- a/frmts/jpeg/vsidataio.cpp
+++ b/frmts/jpeg/vsidataio.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vsidataio.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: vsidataio.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  JPEG JFIF Driver
  * Purpose:  Implement JPEG read/write io indirection through VSI.
@@ -30,7 +30,7 @@
 
 #include "vsidataio.h"
 
-CPL_CVSID("$Id: vsidataio.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: vsidataio.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 CPL_C_START
 #include "jerror.h"
@@ -49,8 +49,7 @@ typedef struct {
 
 typedef my_source_mgr * my_src_ptr;
 
-#define INPUT_BUF_SIZE  4096	/* choose an efficiently fread'able size */
-
+static const size_t INPUT_BUF_SIZE = 4096; /* choose an efficiently fread'able size */
 
 /*
  * Initialize source --- called by jpeg_read_header
@@ -107,9 +106,7 @@ METHODDEF(boolean)
 fill_input_buffer (j_decompress_ptr cinfo)
 {
   my_src_ptr src = (my_src_ptr) cinfo->src;
-  size_t nbytes;
-
-  nbytes = VSIFReadL(src->buffer, 1, INPUT_BUF_SIZE, src->infile);
+  size_t nbytes = VSIFReadL(src->buffer, 1, INPUT_BUF_SIZE, src->infile);
 
   if (nbytes <= 0) {
     if (src->start_of_file)	/* Treat empty input file as fatal error */
@@ -128,8 +125,8 @@ fill_input_buffer (j_decompress_ptr cinfo)
   return TRUE;
 }
 
-/* 
- * The Intel IPP performance libraries do not necessarily read the 
+/*
+ * The Intel IPP performance libraries do not necessarily read the
  * entire contents of the buffer with each pass, so each re-fill
  * copies the remaining buffer bytes to the front of the buffer,
  * then fills up the rest with new data.
@@ -141,7 +138,6 @@ fill_input_buffer_ipp (j_decompress_ptr cinfo)
   my_src_ptr src = (my_src_ptr) cinfo->src;
   size_t bytes_left = src->pub.bytes_in_buffer;
   size_t bytes_to_read = INPUT_BUF_SIZE - bytes_left;
-  size_t nbytes;
 
   if(src->start_of_file || cinfo->progressive_mode)
   {
@@ -150,7 +146,8 @@ fill_input_buffer_ipp (j_decompress_ptr cinfo)
 
   memmove(src->buffer,src->pub.next_input_byte,bytes_left);
 
-  nbytes = VSIFReadL(src->buffer + bytes_left, 1, bytes_to_read, src->infile);
+  size_t nbytes
+      = VSIFReadL(src->buffer + bytes_left, 1, bytes_to_read, src->infile);
 
   if(nbytes <= 0)
   {
@@ -185,7 +182,6 @@ fill_input_buffer_ipp (j_decompress_ptr cinfo)
 }
 #endif /* IPPJ_HUFF */
 
-
 /*
  * Skip data --- used to skip over a potentially large amount of
  * uninteresting data (such as an APPn marker).
@@ -220,7 +216,6 @@ skip_input_data (j_decompress_ptr cinfo, long num_bytes)
   }
 }
 
-
 /*
  * An additional method that can be provided by data source modules is the
  * resync_to_restart method for error recovery in the presence of RST markers.
@@ -229,7 +224,6 @@ skip_input_data (j_decompress_ptr cinfo, long num_bytes)
  * is possible.
  */
 
-
 /*
  * Terminate source --- called by jpeg_finish_decompress
  * after all data has been read.  Often a no-op.
@@ -245,7 +239,6 @@ term_source (CPL_UNUSED j_decompress_ptr cinfo)
   /* no work necessary here */
 }
 
-
 /*
  * Prepare for input from a stdio stream.
  * The caller must have already opened the stream, and is responsible
@@ -304,8 +297,8 @@ typedef struct {
 
 typedef my_destination_mgr * my_dest_ptr;
 
-#define OUTPUT_BUF_SIZE  4096	/* choose an efficiently fwrite'able size */
-
+/* choose an efficiently fwrite'able size */
+static const size_t OUTPUT_BUF_SIZE = 4096;
 
 /*
  * Initialize destination --- called by jpeg_start_compress
diff --git a/frmts/jpeg/vsidataio.h b/frmts/jpeg/vsidataio.h
index 57a87f3..17a73cf 100644
--- a/frmts/jpeg/vsidataio.h
+++ b/frmts/jpeg/vsidataio.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vsidataio.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: vsidataio.h 32062 2015-12-07 11:02:56Z rouault $
  *
  * Project:  JPEG JFIF Driver
  * Purpose:  Implement JPEG read/write io indirection through VSI.
@@ -34,7 +34,11 @@
 #include "cpl_vsi.h"
 
 CPL_C_START
-#include "jpeglib.h"
+#ifdef LIBJPEG_12_PATH
+#  include LIBJPEG_12_PATH
+#else
+#  include "jpeglib.h"
+#endif
 CPL_C_END
 
 void jpeg_vsiio_src (j_decompress_ptr cinfo, VSILFILE * infile);
diff --git a/frmts/jpeg/vsidataio_12.cpp b/frmts/jpeg/vsidataio_12.cpp
new file mode 100644
index 0000000..6322238
--- /dev/null
+++ b/frmts/jpeg/vsidataio_12.cpp
@@ -0,0 +1,43 @@
+/******************************************************************************
+ * $Id: vsidataio_12.cpp 33720 2016-03-15 00:39:53Z goatbar $
+ *
+ * Project:  JPEG JFIF Driver
+ * Purpose:  Implement JPEG read/write io indirection through VSI.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *           Code partially derived from libjpeg jdatasrc.c and jdatadst.c.
+ *
+ ******************************************************************************
+ * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#if defined(JPEG_DUAL_MODE_8_12)
+#define LIBJPEG_12_PATH   "libjpeg12/jpeglib.h"
+
+#define jpeg_vsiio_src    jpeg_vsiio_src_12
+#define jpeg_vsiio_dest   jpeg_vsiio_dest_12
+#define my_source_mgr     my_source_mgr_12
+#define my_src_ptr        my_src_ptr_12
+#define my_destination_mgr my_destination_mgr_12
+#define my_dest_ptr      my_dest_ptr_12
+
+#include "vsidataio.cpp"
+
+#endif
diff --git a/frmts/jpeg2000/frmt_jpeg2000.html b/frmts/jpeg2000/frmt_jpeg2000.html
index b994964..a3398ca 100644
--- a/frmts/jpeg2000/frmt_jpeg2000.html
+++ b/frmts/jpeg2000/frmt_jpeg2000.html
@@ -152,7 +152,7 @@ included in the file.  Defaults to YES.<p>
 
 	<tr>
 		<td>ilyrrates=[, ,. . . ,      ]</td>
-		
+
 		<td>Specify the rates for any intermediate layers.
 			The argument to this option is a comma separated
 			list of N rates. Each rate is a positive real number.
@@ -160,7 +160,7 @@ included in the file.  Defaults to YES.<p>
 			in the list should be less than or equal to the
 			overall rate (as specified with the rate option).</td>
 	</tr>
-	
+
 	<tr>
 		<td>prg=p</td>
 		<td>Set the progression order to p. The argument
@@ -201,7 +201,7 @@ included in the file.  Defaults to YES.<p>
 		for all possible image geometries.
 		(See standard for more details.)</td>
 	</tr>
-	
+
 	<tr>
 		<td>nomct</td>
 		<td>Disallow the use of any multicomponent transform.</td>
@@ -254,7 +254,7 @@ included in the file.  Defaults to YES.<p>
 		<td>resetprob</td>
 		<td>Reset the probability models after each coding pass.<td>
 	</tr>
-	
+
 	<tr>
 		<td>numgbits=n</td>
 		<td>Set the number of guard bits to n.''</td>
@@ -275,7 +275,7 @@ enabled. Modified version can be downloaded from
 ftp://ftp.remotesensing.org/gdal/jasper-1.900.1.uuid.tar.gz</a><p>
 
 <li> <a href="http://www.jpeg.org/JPEG2000.html">
-Official JPEG-2000 page 
+Official JPEG-2000 page
 <a><p>
 
 <li> <a href="http://www.ece.uvic.ca/~mdadams/jasper/">
diff --git a/frmts/jpeg2000/jpeg2000_vsil_io.cpp b/frmts/jpeg2000/jpeg2000_vsil_io.cpp
index 982b4a0..74f1e64 100644
--- a/frmts/jpeg2000/jpeg2000_vsil_io.cpp
+++ b/frmts/jpeg2000/jpeg2000_vsil_io.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: jpeg2000_vsil_io.cpp 29469 2015-07-04 11:42:30Z rouault $
+ * $Id: jpeg2000_vsil_io.cpp 33123 2016-01-23 18:59:28Z rouault $
  *
  * Project:  JPEG-2000
  * Purpose:  Return a stream for a VSIL file
@@ -7,7 +7,7 @@
  *
  ******************************************************************************/
 
-/* Following code is mostly derived from jas_stream.c, which is licenced */
+/* Following code is mostly derived from jas_stream.c, which is licensed */
 /* under the below terms */
  
 /*
@@ -77,7 +77,7 @@
 #include "jpeg2000_vsil_io.h"
 #include "cpl_vsi.h"
 
-CPL_CVSID("$Id: jpeg2000_vsil_io.cpp 29469 2015-07-04 11:42:30Z rouault $");
+CPL_CVSID("$Id: jpeg2000_vsil_io.cpp 33123 2016-01-23 18:59:28Z rouault $");
 
 /*
  * File descriptor file object.
@@ -93,13 +93,13 @@ typedef struct {
 static int JPEG2000_VSIL_read(jas_stream_obj_t *obj, char *buf, int cnt)
 {
 	jas_stream_VSIFL_t *fileobj = JAS_CAST(jas_stream_VSIFL_t *, obj);
-	return VSIFReadL(buf, 1, cnt, fileobj->fp);
+	return static_cast<int>(VSIFReadL(buf, 1, cnt, fileobj->fp));
 }
 
 static int JPEG2000_VSIL_write(jas_stream_obj_t *obj, char *buf, int cnt)
 {
 	jas_stream_VSIFL_t *fileobj = JAS_CAST(jas_stream_VSIFL_t *, obj);
-	return VSIFWriteL(buf, 1, cnt, fileobj->fp);
+	return static_cast<int>(VSIFWriteL(buf, 1, cnt, fileobj->fp));
 }
 
 static long JPEG2000_VSIL_seek(jas_stream_obj_t *obj, long offset, int origin)
@@ -123,13 +123,16 @@ static long JPEG2000_VSIL_seek(jas_stream_obj_t *obj, long offset, int origin)
 static int JPEG2000_VSIL_close(jas_stream_obj_t *obj)
 {
 	jas_stream_VSIFL_t *fileobj = JAS_CAST(jas_stream_VSIFL_t *, obj);
-    VSIFCloseL(fileobj->fp);
-    fileobj->fp = NULL;
+        if( fileobj->fp != NULL )
+        {
+            VSIFCloseL(fileobj->fp);
+            fileobj->fp = NULL;
+        }
 	jas_free(fileobj);
 	return 0;
 }
 
-static jas_stream_ops_t JPEG2000_VSIL_stream_fileops = {
+static const jas_stream_ops_t JPEG2000_VSIL_stream_fileops = {
 	JPEG2000_VSIL_read,
 	JPEG2000_VSIL_write,
 	JPEG2000_VSIL_seek,
@@ -145,18 +148,18 @@ static jas_stream_t *JPEG2000_VSIL_jas_stream_create()
 	jas_stream_t *stream;
 
 	if (!(stream = (jas_stream_t*) jas_malloc(sizeof(jas_stream_t)))) {
-		return 0;
+		return NULL;
 	}
 	stream->openmode_ = 0;
 	stream->bufmode_ = 0;
 	stream->flags_ = 0;
-	stream->bufbase_ = 0;
-	stream->bufstart_ = 0;
+	stream->bufbase_ = NULL;
+	stream->bufstart_ = NULL;
 	stream->bufsize_ = 0;
-	stream->ptr_ = 0;
+	stream->ptr_ = NULL;
 	stream->cnt_ = 0;
-	stream->ops_ = 0;
-	stream->obj_ = 0;
+	stream->ops_ = NULL;
+	stream->obj_ = NULL;
 	stream->rwcnt_ = 0;
 	stream->rwlimit_ = -1;
 
@@ -169,7 +172,7 @@ static void JPEG2000_VSIL_jas_stream_destroy(jas_stream_t *stream)
 	this memory. */
 	if ((stream->bufmode_ & JAS_STREAM_FREEBUF) && stream->bufbase_) {
 		jas_free(stream->bufbase_);
-		stream->bufbase_ = 0;
+		stream->bufbase_ = NULL;
 	}
 	jas_free(stream);
 }
@@ -258,7 +261,7 @@ jas_stream_t *JPEG2000_VSIL_fopen(const char *filename, const char *mode)
 
 	/* Allocate a stream object. */
 	if (!(stream = JPEG2000_VSIL_jas_stream_create())) {
-		return 0;
+		return NULL;
 	}
 
 	/* Parse the mode string. */
@@ -267,22 +270,22 @@ jas_stream_t *JPEG2000_VSIL_fopen(const char *filename, const char *mode)
 	/* Allocate space for the underlying file stream object. */
 	if (!(obj = (jas_stream_VSIFL_t*) jas_malloc(sizeof(jas_stream_VSIFL_t)))) {
 		JPEG2000_VSIL_jas_stream_destroy(stream);
-		return 0;
+		return NULL;
 	}
 	obj->fp = NULL;
 	stream->obj_ = (void *) obj;
 
 	/* Select the operations for a file stream object. */
-	stream->ops_ = &JPEG2000_VSIL_stream_fileops;
+	stream->ops_ = const_cast<jas_stream_ops_t*> (&JPEG2000_VSIL_stream_fileops);
 
 	/* Open the underlying file. */
 	if ((obj->fp = VSIFOpenL(filename, mode)) == NULL) {
-		JPEG2000_VSIL_jas_stream_destroy(stream);
-		return 0;
+		jas_stream_close(stream);
+		return NULL;
 	}
 
 	/* By default, use full buffering for this type of stream. */
-	JPEG2000_VSIL_jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0);
+	JPEG2000_VSIL_jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, NULL, 0);
 
 	return stream;
 }
diff --git a/frmts/jpeg2000/jpeg2000_vsil_io.h b/frmts/jpeg2000/jpeg2000_vsil_io.h
index 3c65713..3af42cf 100644
--- a/frmts/jpeg2000/jpeg2000_vsil_io.h
+++ b/frmts/jpeg2000/jpeg2000_vsil_io.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: jpeg2000_vsil_io.h 29469 2015-07-04 11:42:30Z rouault $
+ * $Id: jpeg2000_vsil_io.h 29468 2015-07-04 11:39:50Z rouault $
  *
  * Project:  JPEG-2000
  * Purpose:  Return a stream for a VSIL file
diff --git a/frmts/jpeg2000/jpeg2000dataset.cpp b/frmts/jpeg2000/jpeg2000dataset.cpp
index 69f46d4..c88c234 100644
--- a/frmts/jpeg2000/jpeg2000dataset.cpp
+++ b/frmts/jpeg2000/jpeg2000dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: jpeg2000dataset.cpp 29171 2015-05-07 19:49:07Z rouault $
+ * $Id: jpeg2000dataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  JPEG-2000
  * Purpose:  Partial implementation of the ISO/IEC 15444-1 standard
@@ -28,18 +28,15 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_string.h"
+#include "gdal_frmts.h"
 #include "gdaljp2abstractdataset.h"
 #include "gdaljp2metadata.h"
-#include "cpl_string.h"
 
 #include <jasper/jasper.h>
 #include "jpeg2000_vsil_io.h"
 
-CPL_CVSID("$Id: jpeg2000dataset.cpp 29171 2015-05-07 19:49:07Z rouault $");
-
-CPL_C_START
-void    GDALRegister_JPEG2000(void);
-CPL_C_END
+CPL_CVSID("$Id: jpeg2000dataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 // XXX: Part of code below extracted from the JasPer internal headers and
 // must be in sync with JasPer version (this one works with JasPer 1.900.1)
@@ -183,7 +180,7 @@ class JPEG2000Dataset : public GDALJP2AbstractDataset
   public:
                 JPEG2000Dataset();
                 ~JPEG2000Dataset();
-    
+
     static int           Identify( GDALOpenInfo * );
     static GDALDataset  *Open( GDALOpenInfo * );
 };
@@ -197,12 +194,12 @@ class JPEG2000Dataset : public GDALJP2AbstractDataset
 class JPEG2000RasterBand : public GDALPamRasterBand
 {
     friend class JPEG2000Dataset;
-    
+
     // NOTE: poDS may be altered for NITF/JPEG2000 files!
     JPEG2000Dataset     *poGDS;
 
     jas_matrix_t        *psMatrix;
-    
+
     int                  iDepth;
     int                  bSignedness;
 
@@ -210,7 +207,7 @@ class JPEG2000RasterBand : public GDALPamRasterBand
 
                 JPEG2000RasterBand( JPEG2000Dataset *, int, int, int );
                 ~JPEG2000RasterBand();
-                
+
     virtual CPLErr IReadBlock( int, int, void * );
     virtual GDALColorInterp GetColorInterpretation();
 };
@@ -220,15 +217,15 @@ class JPEG2000RasterBand : public GDALPamRasterBand
 /*                           JPEG2000RasterBand()                       */
 /************************************************************************/
 
-JPEG2000RasterBand::JPEG2000RasterBand( JPEG2000Dataset *poDS, int nBand,
-                int iDepth, int bSignedness )
+JPEG2000RasterBand::JPEG2000RasterBand( JPEG2000Dataset *poDSIn, int nBandIn,
+                int iDepthIn, int bSignednessIn )
 
 {
-    this->poDS = poDS;
-    poGDS = poDS;
-    this->nBand = nBand;
-    this->iDepth = iDepth;
-    this->bSignedness = bSignedness;
+    this->poDS = poDSIn;
+    poGDS = poDSIn;
+    this->nBand = nBandIn;
+    this->iDepth = iDepthIn;
+    this->bSignedness = bSignednessIn;
 
     // XXX: JasPer can't handle data with depth > 32 bits
     // Maximum possible depth for JPEG2000 is 38!
@@ -256,14 +253,14 @@ JPEG2000RasterBand::JPEG2000RasterBand( JPEG2000Dataset *poDS, int nBand,
     }
     // FIXME: Figure out optimal block size!
     // Should the block size be fixed or determined dynamically?
-    nBlockXSize = MIN(256, poDS->nRasterXSize);
-    nBlockYSize = MIN(256, poDS->nRasterYSize);
+    nBlockXSize = MIN(256, poDSIn->nRasterXSize);
+    nBlockYSize = MIN(256, poDSIn->nRasterYSize);
     psMatrix = jas_matrix_create(nBlockYSize, nBlockXSize);
 
-    if( iDepth % 8 != 0 && !poDS->bPromoteTo8Bit )
+    if( iDepth % 8 != 0 && !poDSIn->bPromoteTo8Bit )
     {
-        SetMetadataItem( "NBITS", 
-                         CPLString().Printf("%d",iDepth), 
+        SetMetadataItem( "NBITS",
+                         CPLString().Printf("%d",iDepth),
                          "IMAGE_STRUCTURE" );
     }
     SetMetadataItem( "COMPRESSION", "JP2000", "IMAGE_STRUCTURE" );
@@ -276,7 +273,7 @@ JPEG2000RasterBand::JPEG2000RasterBand( JPEG2000Dataset *poDS, int nBand,
 JPEG2000RasterBand::~JPEG2000RasterBand()
 {
     if ( psMatrix )
-        jas_matrix_destroy( psMatrix );    
+        jas_matrix_destroy( psMatrix );
 }
 
 /************************************************************************/
@@ -380,11 +377,11 @@ GDALColorInterp JPEG2000RasterBand::GetColorInterpretation()
     {
         return GCI_Undefined;
     }
-    
+
     if ( jas_clrspc_fam( jas_image_clrspc( poGDS->psImage ) ) ==
          JAS_CLRSPC_FAM_GRAY )
         return GCI_GrayIndex;
-    else if ( jas_clrspc_fam( jas_image_clrspc( poGDS->psImage ) ) == 
+    else if ( jas_clrspc_fam( jas_image_clrspc( poGDS->psImage ) ) ==
               JAS_CLRSPC_FAM_RGB )
     {
         switch ( jas_image_cmpttype( poGDS->psImage, nBand - 1 ) )
@@ -415,14 +412,15 @@ GDALColorInterp JPEG2000RasterBand::GetColorInterpretation()
 /*                           JPEG2000Dataset()                          */
 /************************************************************************/
 
-JPEG2000Dataset::JPEG2000Dataset()
+JPEG2000Dataset::JPEG2000Dataset() :
+    iFormat(0)
 {
     psStream = NULL;
     psImage = NULL;
     nBands = 0;
     bAlreadyDecoded = FALSE;
     bPromoteTo8Bit = FALSE;
-    
+
     poDriver = (GDALDriver *)GDALGetDriverByName("JPEG2000");
 }
 
@@ -448,15 +446,15 @@ int JPEG2000Dataset::DecodeImage()
 {
     if (bAlreadyDecoded)
         return psImage != NULL;
-        
-    bAlreadyDecoded = TRUE;    
-    if ( !( psImage = jas_image_decode(psStream, iFormat, 0) ) )
+
+    bAlreadyDecoded = TRUE;
+    if ( !( psImage = jas_image_decode(psStream, iFormat, NULL) ) )
     {
         CPLDebug( "JPEG2000", "Unable to decode image. Format: %s, %d",
                   jas_image_fmttostr( iFormat ), iFormat );
         return FALSE;
     }
-    
+
     /* Case of a JP2 image : check that the properties given by */
     /* the JP2 boxes match the ones of the code stream */
     if (nBands != 0)
@@ -471,7 +469,7 @@ int JPEG2000Dataset::DecodeImage()
             psImage = NULL;
             return FALSE;
         }
-        
+
         if (nRasterXSize != jas_image_cmptwidth( psImage, 0 ) ||
             nRasterYSize != jas_image_cmptheight( psImage, 0 ) )
         {
@@ -485,7 +483,7 @@ int JPEG2000Dataset::DecodeImage()
             psImage = NULL;
             return FALSE;
         }
-        
+
         int iBand;
         for ( iBand = 0; iBand < nBands; iBand++ )
         {
@@ -503,9 +501,9 @@ int JPEG2000Dataset::DecodeImage()
             }
         }
     }
-    
+
     /* Ask for YCbCr -> RGB translation */
-    if ( jas_clrspc_fam( jas_image_clrspc( psImage ) ) == 
+    if ( jas_clrspc_fam( jas_image_clrspc( psImage ) ) ==
               JAS_CLRSPC_FAM_YCBCR )
     {
         jas_image_t *psRGBImage;
@@ -524,7 +522,7 @@ int JPEG2000Dataset::DecodeImage()
         jas_cmprof_destroy(psRGBProf);
         psImage = psRGBImage;
     }
-    
+
     return TRUE;
 }
 
@@ -547,11 +545,11 @@ int JPEG2000Dataset::Identify( GDALOpenInfo * poOpenInfo )
 {
     static const unsigned char jpc_header[] = {0xff,0x4f};
     static const unsigned char jp2_box_jp[] = {0x6a,0x50,0x20,0x20}; /* 'jP  ' */
-        
-    if( poOpenInfo->nHeaderBytes >= 16 
-        && (memcmp( poOpenInfo->pabyHeader, jpc_header, 
+
+    if( poOpenInfo->nHeaderBytes >= 16
+        && (memcmp( poOpenInfo->pabyHeader, jpc_header,
                     sizeof(jpc_header) ) == 0
-            || memcmp( poOpenInfo->pabyHeader + 4, jp2_box_jp, 
+            || memcmp( poOpenInfo->pabyHeader + 4, jp2_box_jp,
                     sizeof(jp2_box_jp) ) == 0
             /* PGX file*/
             || (memcmp( poOpenInfo->pabyHeader, "PG", 2) == 0 &&
@@ -559,7 +557,7 @@ int JPEG2000Dataset::Identify( GDALOpenInfo * poOpenInfo )
                 (memcmp( poOpenInfo->pabyHeader + 3, "ML", 2) == 0 ||
                  memcmp( poOpenInfo->pabyHeader + 3, "LM", 2) == 0))) )
         return TRUE;
-    
+
     else
         return FALSE;
 }
@@ -574,7 +572,7 @@ GDALDataset *JPEG2000Dataset::Open( GDALOpenInfo * poOpenInfo )
     int         iFormat;
     char        *pszFormatName = NULL;
     jas_stream_t *sS;
-    
+
     if (!Identify(poOpenInfo))
         return NULL;
 
@@ -591,23 +589,23 @@ GDALDataset *JPEG2000Dataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
     if ( strlen( pszFormatName ) < 3 ||
-        (!EQUALN( pszFormatName, "jp2", 3 ) &&
-         !EQUALN( pszFormatName, "jpc", 3 ) &&
-         !EQUALN( pszFormatName, "pgx", 3 )) )
+        (!STARTS_WITH_CI(pszFormatName, "jp2") &&
+         !STARTS_WITH_CI(pszFormatName, "jpc") &&
+         !STARTS_WITH_CI(pszFormatName, "pgx")) )
     {
-        CPLDebug( "JPEG2000", "JasPer reports file is format type `%s'.", 
+        CPLDebug( "JPEG2000", "JasPer reports file is format type `%s'.",
                   pszFormatName );
         jas_stream_close( sS );
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
         jas_stream_close(sS);
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The JPEG2000 driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
@@ -624,20 +622,19 @@ GDALDataset *JPEG2000Dataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->psStream = sS;
     poDS->iFormat = iFormat;
 
-    if ( EQUALN( pszFormatName, "jp2", 3 ) )
+    if ( STARTS_WITH_CI(pszFormatName, "jp2") )
     {
         // XXX: Hack to read JP2 boxes from input file. JasPer hasn't public
         // API call for such things, so we will use internal JasPer functions.
         jp2_box_t *box;
-        box = 0;
-        while ( ( box = jp2_box_get(poDS->psStream) ) )
+        while ( ( box = jp2_box_get(poDS->psStream) ) != NULL )
         {
             switch (box->type)
             {
                 case JP2_BOX_IHDR:
-                poDS->nBands = box->data.ihdr.numcmpts;
-                poDS->nRasterXSize = box->data.ihdr.width;
-                poDS->nRasterYSize = box->data.ihdr.height;
+                poDS->nBands = static_cast<int>(box->data.ihdr.numcmpts);
+                poDS->nRasterXSize = static_cast<int>(box->data.ihdr.width);
+                poDS->nRasterYSize = static_cast<int>(box->data.ihdr.height);
                 CPLDebug( "JPEG2000",
                           "IHDR box found. Dump: "
                           "width=%d, height=%d, numcmpts=%d, bpp=%d",
@@ -646,7 +643,7 @@ GDALDataset *JPEG2000Dataset::Open( GDALOpenInfo * poOpenInfo )
                 /* ISO/IEC 15444-1:2004 I.5.3.1 specifies that 255 means that all */
                 /* components have not the same bit depth and/or sign and that a */
                 /* BPCC box must then follow to specify them for each component */
-                if ( box->data.ihdr.bpc != 255 )
+                if ( box->data.ihdr.bpc != 255 && paiDepth == NULL && pabSignedness == NULL )
                 {
                     paiDepth = (int *)CPLMalloc(poDS->nBands * sizeof(int));
                     pabSignedness = (int *)CPLMalloc(poDS->nBands * sizeof(int));
@@ -705,18 +702,22 @@ GDALDataset *JPEG2000Dataset::Open( GDALOpenInfo * poOpenInfo )
                 break;
             }
             jp2_box_destroy( box );
-            box = 0;
+            box = NULL;
         }
         if( !paiDepth || !pabSignedness )
         {
             delete poDS;
             CPLDebug( "JPEG2000", "Unable to read JP2 header boxes.\n" );
+            CPLFree( paiDepth );
+            CPLFree( pabSignedness );
             return NULL;
         }
         if ( jas_stream_rewind( poDS->psStream ) < 0 )
         {
             delete poDS;
             CPLDebug( "JPEG2000", "Unable to rewind input stream.\n" );
+            CPLFree( paiDepth );
+            CPLFree( pabSignedness );
             return NULL;
         }
     }
@@ -729,8 +730,8 @@ GDALDataset *JPEG2000Dataset::Open( GDALOpenInfo * poOpenInfo )
         }
 
         poDS->nBands = jas_image_numcmpts( poDS->psImage );
-        poDS->nRasterXSize = jas_image_cmptwidth( poDS->psImage, 0 );
-        poDS->nRasterYSize = jas_image_cmptheight( poDS->psImage, 0 );
+        poDS->nRasterXSize = static_cast<int>(jas_image_cmptwidth( poDS->psImage, 0 ));
+        poDS->nRasterYSize = static_cast<int>(jas_image_cmptheight( poDS->psImage, 0 ));
         paiDepth = (int *)CPLMalloc( poDS->nBands * sizeof(int) );
         pabSignedness = (int *)CPLMalloc( poDS->nBands * sizeof(int) );
         for ( iBand = 0; iBand < poDS->nBands; iBand++ )
@@ -739,7 +740,7 @@ GDALDataset *JPEG2000Dataset::Open( GDALOpenInfo * poOpenInfo )
             pabSignedness[iBand] = jas_image_cmptsgnd( poDS->psImage, iBand );
         }
     }
-    
+
     if ( !GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) ||
          !GDALCheckBandCount(poDS->nBands, 0) )
     {
@@ -771,13 +772,11 @@ GDALDataset *JPEG2000Dataset::Open( GDALOpenInfo * poOpenInfo )
     {
         poDS->SetBand( iBand, new JPEG2000RasterBand( poDS, iBand,
             paiDepth[iBand - 1], pabSignedness[iBand - 1] ) );
-        
+
     }
-    
-    if ( paiDepth )
-        CPLFree( paiDepth );
-    if ( pabSignedness )
-        CPLFree( pabSignedness );
+
+    CPLFree( paiDepth );
+    CPLFree( pabSignedness );
 
     poDS->LoadJP2Metadata(poOpenInfo);
 
@@ -818,8 +817,8 @@ GDALDataset *JPEG2000Dataset::Open( GDALOpenInfo * poOpenInfo )
 /************************************************************************/
 
 static GDALDataset *
-JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
-                    int bStrict, char ** papszOptions, 
+JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
+                    int bStrict, char ** papszOptions,
                     GDALProgressFunc pfnProgress, void * pProgressData )
 
 {
@@ -838,14 +837,14 @@ JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
     if (poSrcDS->GetRasterBand(1)->GetColorTable() != NULL)
     {
-        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, 
+        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
                   "JPEG2000 driver ignores color table. "
                   "The source raster band will be considered as grey level.\n"
                   "Consider using color table expansion (-expand option in gdal_translate)\n");
         if (bStrict)
             return NULL;
     }
-    
+
     for ( iBand = 0; iBand < nBands; iBand++ )
     {
         poBand = poSrcDS->GetRasterBand( iBand + 1);
@@ -858,7 +857,7 @@ JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                 break;
 
             default:
-                if( !CSLTestBoolean(CPLGetConfigOption("JPEG2000_FORCE_CREATION", "NO")) )
+                if( !CPLTestBool(CPLGetConfigOption("JPEG2000_FORCE_CREATION", "NO")) )
                 {
                     CPLError(CE_Failure, CPLE_AppDefined,
                              "A band of the source dataset is of type %s, which might cause crashes in libjasper. "
@@ -869,7 +868,7 @@ JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                 break;
         }
     }
-    
+
     if( !pfnProgress( 0.0, NULL, pProgressData ) )
         return NULL;
 
@@ -880,18 +879,19 @@ JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     jas_image_t         *psImage;
 
     JPEG2000Init();
-    const char* pszAccess = EQUALN(pszFilename, "/vsisubfile/", 12) ? "r+b" : "w+b";
+    const char* pszAccess = STARTS_WITH_CI(pszFilename, "/vsisubfile/") ? "r+b" : "w+b";
     if( !(psStream = JPEG2000_VSIL_fopen( pszFilename, pszAccess) ) )
     {
-        CPLError( CE_Failure, CPLE_FileIO, "Unable to create file %s.\n", 
+        CPLError( CE_Failure, CPLE_FileIO, "Unable to create file %s.\n",
                   pszFilename );
         return NULL;
     }
-    
+
     if ( !(psImage = jas_image_create0()) )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory, "Unable to create image %s.\n", 
+        CPLError( CE_Failure, CPLE_OutOfMemory, "Unable to create image %s.\n",
                   pszFilename );
+        jas_stream_close( psStream );
         return NULL;
     }
 
@@ -906,22 +906,23 @@ JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
     sComps = (jas_image_cmptparm_t*)
         CPLMalloc( nBands * sizeof(jas_image_cmptparm_t) );
-  
+
     if ( !(psMatrix = jas_matrix_create( 1, nXSize )) )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory, 
+        CPLError( CE_Failure, CPLE_OutOfMemory,
                   "Unable to create matrix with size %dx%d.\n", 1, nYSize );
         CPLFree( sComps );
         jas_image_destroy( psImage );
+        jas_stream_close( psStream );
         return NULL;
     }
     paiScanline = (GUInt32 *) CPLMalloc( nXSize *
                             GDALGetDataTypeSize(GDT_UInt32) / 8 );
-    
+
     for ( iBand = 0; iBand < nBands; iBand++ )
     {
         poBand = poSrcDS->GetRasterBand( iBand + 1);
-        
+
         sComps[iBand].tlx = sComps[iBand].tly = 0;
         sComps[iBand].hstep = sComps[iBand].vstep = 1;
         sComps[iBand].width = nXSize;
@@ -946,32 +947,33 @@ JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
         for( iLine = 0; eErr == CE_None && iLine < nYSize; iLine++ )
         {
-            eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, 
+            eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1,
                               paiScanline, nXSize, 1, GDT_UInt32,
                               sizeof(GUInt32), sizeof(GUInt32) * nXSize, NULL );
             for ( iPixel = 0; iPixel < nXSize; iPixel++ )
                 jas_matrix_setv( psMatrix, iPixel, paiScanline[iPixel] );
-            
+
             if( (jas_image_writecmpt(psImage, iBand, 0, iLine,
                               nXSize, 1, psMatrix)) < 0 )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                    "Unable to write scanline %d of the component %d.\n", 
+                CPLError( CE_Failure, CPLE_AppDefined,
+                    "Unable to write scanline %d of the component %d.\n",
                     iLine, iBand );
                 jas_matrix_destroy( psMatrix );
                 CPLFree( paiScanline );
                 CPLFree( sComps );
                 jas_image_destroy( psImage );
+                jas_stream_close( psStream );
                 return NULL;
             }
-            
+
             if( eErr == CE_None &&
             !pfnProgress( ((iLine + 1) + iBand * nYSize) /
                           ((double) nYSize * nBands),
                          NULL, pProgressData) )
             {
                 eErr = CE_Failure;
-                CPLError( CE_Failure, CPLE_UserInterrupt, 
+                CPLError( CE_Failure, CPLE_UserInterrupt,
                       "User terminated CreateCopy()" );
             }
         }
@@ -1013,13 +1015,13 @@ JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         "numgbits",
         NULL
     };
-    
+
     pszFormatName = CSLFetchNameValue( papszOptions, "FORMAT" );
     if ( !pszFormatName ||
-         (!EQUALN( pszFormatName, "jp2", 3 ) &&
-          !EQUALN( pszFormatName, "jpc", 3 ) ) )
+         (!STARTS_WITH_CI(pszFormatName, "jp2") &&
+          !STARTS_WITH_CI(pszFormatName, "jpc") ) )
         pszFormatName = "jp2";
-    
+
     pszOptionBuf[0] = '\0';
     if ( papszOptions )
     {
@@ -1033,8 +1035,8 @@ JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                 {
                     int m, n;
 
-                    n = strlen( pszOptionBuf );
-                    m = n + strlen( papszOptions[i] ) + 1;
+                    n = static_cast<int>(strlen( pszOptionBuf ));
+                    m = n + static_cast<int>(strlen( papszOptions[i] )) + 1;
                     if ( m > OPTSMAX )
                         break;
                     if ( n > 0 )
@@ -1083,7 +1085,7 @@ JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     {
         /* JAS_CLRSPC_UNKNOWN causes crashes in Jasper jp2_enc.c at line 231 */
         /* iccprof = jas_iccprof_createfromcmprof(jas_image_cmprof(image)); */
-        /* but if we explictely set the cmprof, it does not work better */
+        /* but if we explicitly set the cmprof, it does not work better */
         /* since it would abort at line 281 later ... */
         /* So the best option is to switch to gray colorspace */
         /* And we need to switch at the band level too, otherwise Kakadu or */
@@ -1099,17 +1101,17 @@ JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      Set the GeoTIFF box if georeferencing is available, and this    */
 /*      is a JP2 file.                                                  */
 /* -------------------------------------------------------------------- */
-    if ( EQUALN( pszFormatName, "jp2", 3 ) )
+    if ( STARTS_WITH_CI(pszFormatName, "jp2") )
     {
 #ifdef HAVE_JASPER_UUID
         double  adfGeoTransform[6];
         if( CSLFetchBoolean( papszOptions, "GeoJP2", TRUE ) &&
             ((poSrcDS->GetGeoTransform(adfGeoTransform) == CE_None
-                 && (adfGeoTransform[0] != 0.0 
-                     || adfGeoTransform[1] != 1.0 
-                     || adfGeoTransform[2] != 0.0 
-                     || adfGeoTransform[3] != 0.0 
-                     || adfGeoTransform[4] != 0.0 
+                 && (adfGeoTransform[0] != 0.0
+                     || adfGeoTransform[1] != 1.0
+                     || adfGeoTransform[2] != 0.0
+                     || adfGeoTransform[3] != 0.0
+                     || adfGeoTransform[4] != 0.0
                      || ABS(adfGeoTransform[5]) != 1.0))
                 || poSrcDS->GetGCPCount() > 0
                 || poSrcDS->GetMetadata("RPC") != NULL ) )
@@ -1152,6 +1154,7 @@ JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                 CPLFree( paiScanline );
                 CPLFree( sComps );
                 jas_image_destroy( psImage );
+                jas_stream_close( psStream );
                 return NULL;
             }
             jp2_box_destroy( box );
@@ -1167,6 +1170,7 @@ JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                 CPLFree( paiScanline );
                 CPLFree( sComps );
                 jas_image_destroy( psImage );
+                jas_stream_close( psStream );
                 return NULL;
             }
 #ifdef HAVE_JASPER_UUID
@@ -1183,12 +1187,13 @@ JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             CPLFree( paiScanline );
             CPLFree( sComps );
             jas_image_destroy( psImage );
+            jas_stream_close( psStream );
             return NULL;
         }
     }
 
     jas_stream_flush( psStream );
-    
+
     jas_matrix_destroy( psMatrix );
     CPLFree( paiScanline );
     CPLFree( sComps );
@@ -1203,7 +1208,7 @@ JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Add GMLJP2 box at end of file.                                  */
 /* -------------------------------------------------------------------- */
-    if ( EQUALN( pszFormatName, "jp2", 3 ) )
+    if ( STARTS_WITH_CI(pszFormatName, "jp2") )
     {
         double  adfGeoTransform[6];
         if( CSLFetchBoolean( papszOptions, "GMLJP2", TRUE ) &&
@@ -1220,7 +1225,7 @@ JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                 GUInt32   nLBox;
                 GUInt32   nTBox;
 
-                while(TRUE)
+                while( true )
                 {
                     if( VSIFReadL(&nLBox, 4, 1, fp) != 1 ||
                         VSIFReadL(&nTBox, 4, 1, fp) != 1 )
@@ -1289,7 +1294,7 @@ JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     if( CSLFetchBoolean( papszOptions, "WORLDFILE", FALSE ) )
     {
         double      adfGeoTransform[6];
-        
+
         poSrcDS->GetGeoTransform( adfGeoTransform );
         GDALWriteWorldFile( pszFilename, "wld", adfGeoTransform );
     }
@@ -1343,36 +1348,35 @@ JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 void GDALRegister_JPEG2000()
 
 {
-    GDALDriver  *poDriver;
-    
-    if (! GDAL_CHECK_VERSION("JPEG2000 driver"))
+    if( !GDAL_CHECK_VERSION( "JPEG2000 driver" ) )
         return;
 
-    if( GDALGetDriverByName( "JPEG2000" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "JPEG2000" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "JPEG-2000 part 1 (ISO/IEC 15444-1), based on Jasper library" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_jpeg2000.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte Int16 UInt16 Int32 UInt32" );
-        poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/jp2" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jp2" );
-        
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST, 
+    if( GDALGetDriverByName( "JPEG2000" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "JPEG2000" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "JPEG-2000 part 1 (ISO/IEC 15444-1), "
+                               "based on Jasper library" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_jpeg2000.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte Int16 UInt16 Int32 UInt32" );
+    poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/jp2" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jp2" );
+
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
 "<OpenOptionList>"
 "   <Option name='1BIT_ALPHA_PROMOTION' type='boolean' description='Whether a 1-bit alpha channel should be promoted to 8-bit' default='YES'/>"
 "   <Option name='OPEN_REMOTE_GML' type='boolean' description='Whether to load remote vector layers referenced by a link in a GMLJP2 v2 box' default='NO'/>"
 "</OpenOptionList>" );
 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "   <Option name='FORMAT' type='string-select' default='according to file extension. If unknown, default to J2K'>"
 "       <Value>JP2</Value>"
@@ -1408,11 +1412,9 @@ void GDALRegister_JPEG2000()
 "   <Option name='numgbits' type='string' />"
 "</CreationOptionList>"  );
 
-        poDriver->pfnIdentify = JPEG2000Dataset::Identify;
-        poDriver->pfnOpen = JPEG2000Dataset::Open;
-        poDriver->pfnCreateCopy = JPEG2000CreateCopy;
+    poDriver->pfnIdentify = JPEG2000Dataset::Identify;
+    poDriver->pfnOpen = JPEG2000Dataset::Open;
+    poDriver->pfnCreateCopy = JPEG2000CreateCopy;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
-
diff --git a/frmts/jpegls/jpeglsdataset.cpp b/frmts/jpegls/jpeglsdataset.cpp
index d13807d..499c174 100644
--- a/frmts/jpegls/jpeglsdataset.cpp
+++ b/frmts/jpegls/jpeglsdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: jpeglsdataset.cpp 28785 2015-03-26 20:46:45Z goatbar $
+ * $Id: jpeglsdataset.cpp 33833 2016-03-31 17:31:52Z rouault $
  *
  * Project:  JPEGLS driver based on CharLS library
  * Purpose:  JPEGLS driver based on CharLS library
@@ -27,17 +27,16 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
 
 /* CharLS header */
 #include <interface.h>
 
-extern "C" void GDALRegister_JPEGLS();
-
 /* g++ -Wall -g fmrts/jpegls/jpeglsdataset.cpp -shared -fPIC -o gdal_JPEGLS.so -Iport -Igcore -L. -lgdal -I/home/even/charls-1.0 -L/home/even/charls-1.0/build -lCharLS */
 
-CPL_CVSID("$Id: jpeglsdataset.cpp 28785 2015-03-26 20:46:45Z goatbar $");
+CPL_CVSID("$Id: jpeglsdataset.cpp 33833 2016-03-31 17:31:52Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -94,14 +93,14 @@ class JPEGLSRasterBand : public GDALPamRasterBand
 /*                        JPEGLSRasterBand()                            */
 /************************************************************************/
 
-JPEGLSRasterBand::JPEGLSRasterBand( JPEGLSDataset *poDS, int nBand)
+JPEGLSRasterBand::JPEGLSRasterBand( JPEGLSDataset *poDSIn, int nBandIn)
 
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
-    this->eDataType = (poDS->nBitsPerSample <= 8) ? GDT_Byte : GDT_Int16;
-    this->nBlockXSize = poDS->nRasterXSize;
-    this->nBlockYSize = poDS->nRasterYSize;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
+    this->eDataType = (poDSIn->nBitsPerSample <= 8) ? GDT_Byte : GDT_Int16;
+    this->nBlockXSize = poDSIn->nRasterXSize;
+    this->nBlockYSize = poDSIn->nRasterYSize;
 }
 
 /************************************************************************/
@@ -138,7 +137,7 @@ static const char* JPEGLSGetErrorAsString(JLS_ERROR eCode)
 /*                             IReadBlock()                             */
 /************************************************************************/
 
-CPLErr JPEGLSRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
+CPLErr JPEGLSRasterBand::IReadBlock( int /*nBlockXOff*/, int /*nBlockYOff*/,
                                       void * pImage )
 {
     JPEGLSDataset *poGDS = (JPEGLSDataset *) poDS;
@@ -178,7 +177,6 @@ CPLErr JPEGLSRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             }
         }
     }
-    
 
     return CE_None;
 }
@@ -273,21 +271,21 @@ CPLErr JPEGLSDataset::Uncompress()
 
     int nUncompressedSize = nRasterXSize * nRasterYSize *
                             nBands * (GDALGetDataTypeSize(GetRasterBand(1)->GetRasterDataType()) / 8);
-    pabyUncompressedData = (GByte*)VSIMalloc(nUncompressedSize);
+    pabyUncompressedData = (GByte*)VSI_MALLOC_VERBOSE(nUncompressedSize);
     if (pabyUncompressedData == NULL)
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
         VSIFree(pabyCompressedData);
         return CE_Failure;
     }
 
 
-    JLS_ERROR eError = JpegLsDecode(pabyUncompressedData, nUncompressedSize, pabyCompressedData, nFileSize, NULL);
+    JLS_ERROR eError = JpegLsDecode( pabyUncompressedData, nUncompressedSize,
+                                     pabyCompressedData, nFileSize, NULL);
     if (eError != OK)
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                    "Uncompression of data failed : %s",
-                    JPEGLSGetErrorAsString(eError));
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Decompression of data failed : %s",
+                  JPEGLSGetErrorAsString(eError) );
         VSIFree(pabyCompressedData);
         VSIFree(pabyUncompressedData);
         pabyUncompressedData = NULL;
@@ -399,7 +397,7 @@ GDALDataset *JPEGLSDataset::Open( GDALOpenInfo * poOpenInfo )
             return NULL;
         GByte abyBuffer[1028];
         GByte abySignature[] = { 0xFF, 0xD8, 0xFF, 0xF7 };
-        while(TRUE)
+        while( true )
         {
             if (VSIFReadL(abyBuffer, 1, 1028, fp) != 1028)
             {
@@ -496,7 +494,7 @@ GDALDataset *JPEGLSDataset::Open( GDALOpenInfo * poOpenInfo )
 GDALDataset *
 JPEGLSDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                 int bStrict, char ** papszOptions,
-                GDALProgressFunc pfnProgress, void * pProgressData )
+                GDALProgressFunc /*pfnProgress*/, void * /*pProgressData*/ )
 
 {
     int  nBands = poSrcDS->GetRasterCount();
@@ -541,19 +539,20 @@ JPEGLSDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
     int nWordSize = GDALGetDataTypeSize(eDT) / 8;
     int nUncompressedSize = nXSize * nYSize * nBands * nWordSize;
-    int nCompressedSize = nUncompressedSize + 256; /* FIXME? bug in charls-1.0beta ?. I needed a "+ something" to avoid erros on byte.tif */
-    GByte* pabyDataCompressed = (GByte*)VSIMalloc(nCompressedSize);
-    GByte* pabyDataUncompressed = (GByte*)VSIMalloc(nUncompressedSize);
+    // FIXME? bug in charls-1.0beta ?. I needed a "+ something" to
+    // avoid errors on byte.tif.
+    int nCompressedSize = nUncompressedSize + 256;
+    GByte* pabyDataCompressed = (GByte*)VSI_MALLOC_VERBOSE(nCompressedSize);
+    GByte* pabyDataUncompressed = (GByte*)VSI_MALLOC_VERBOSE(nUncompressedSize);
     if (pabyDataCompressed == NULL || pabyDataUncompressed == NULL)
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
         VSIFree(pabyDataCompressed);
         VSIFree(pabyDataUncompressed);
         return NULL;
     }
 
     CPLErr eErr;
-    eErr = poSrcDS->s(GF_Read, 0, 0, nXSize, nYSize,
+    eErr = poSrcDS->RasterIO(GF_Read, 0, 0, nXSize, nYSize,
                       pabyDataUncompressed, nXSize, nYSize,
                       eDT, nBands, NULL,
                       nBands * nWordSize, nBands * nWordSize * nXSize, nWordSize, NULL);
@@ -605,7 +604,7 @@ JPEGLSDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         if (nBits != 8 && nBits != 16)
             sParams.bitspersample = nBits;
     }
-    
+
     sParams.components = nBands;
     JLS_ERROR eError = JpegLsEncode(pabyDataCompressed, nCompressedSize,
                                     &nWritten,
@@ -654,26 +653,22 @@ JPEGLSDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 void GDALRegister_JPEGLS()
 
 {
-    GDALDriver  *poDriver;
+    if( !GDAL_CHECK_VERSION( "JPEGLS driver" ) )
+        return;
 
-    if (! GDAL_CHECK_VERSION("JPEGLS driver"))
+    if( GDALGetDriverByName( "JPEGLS" ) != NULL )
         return;
 
-    if( GDALGetDriverByName( "JPEGLS" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-
-        poDriver->SetDescription( "JPEGLS" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "JPEGLS" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "frmt_jpegls.html" );
-        //poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/jls" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jls" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
-                                   "Byte Int16" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "JPEGLS" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "JPEGLS" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_jpegls.html" );
+    // poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/jls" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jls" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte Int16" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>\n"
 "   <Option name='INTERLEAVE' type='string-select' default='BAND' description='File interleaving'>"
 "       <Value>PIXEL</Value>"
@@ -682,14 +677,13 @@ void GDALRegister_JPEGLS()
 "   </Option>"
 "   <Option name='LOSS_FACTOR' type='int' default='0' description='0 = lossless, 1 = near lossless, > 1 lossless'/>"
 "</CreationOptionList>\n" );
-        
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnIdentify = JPEGLSDataset::Identify;
-        poDriver->pfnOpen = JPEGLSDataset::Open;
-        poDriver->pfnCreateCopy = JPEGLSDataset::CreateCopy;
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    poDriver->pfnIdentify = JPEGLSDataset::Identify;
+    poDriver->pfnOpen = JPEGLSDataset::Open;
+    poDriver->pfnCreateCopy = JPEGLSDataset::CreateCopy;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
 
diff --git a/frmts/jpipkak/GNUmakefile b/frmts/jpipkak/GNUmakefile
index 0144e02..30298e1 100644
--- a/frmts/jpipkak/GNUmakefile
+++ b/frmts/jpipkak/GNUmakefile
@@ -22,12 +22,18 @@ default:	$(OBJ:.o=.$(OBJ_EXT))
 # apps makefiles, so we copy it and build it ourselves.  Perhaps this 
 # won't be needed with newer versions of Kakadu.  Tested with 6.2.
 kdu_cache.cpp:	  $(KAKDIR)/apps/caching_sources/kdu_cache.cpp
-	cp $(KAKDIR)/apps/caching_sources/kdu_cache.cpp .
+	echo "#include \"cpl_port.h\"" > kdu_cache_wrapper.h
+	echo "#ifdef HAVE_GCC_SYSTEM_HEADER" >> kdu_cache_wrapper.h
+	echo "#pragma GCC system_header" >> kdu_cache_wrapper.h
+	echo "#endif" >> kdu_cache_wrapper.h
+	cat $(KAKDIR)/apps/caching_sources/kdu_cache.cpp >> kdu_cache_wrapper.h
+	echo "#include \"kdu_cache_wrapper.h\"" > kdu_cache.cpp
 
 clean:
 	rm -f *.o $(O_OBJ)
 	rm -f $(INSTOBJ)
 	rm -f kdu_cache.cpp
+	rm -f kdu_cache_wrapper.h
 
 install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
 
diff --git a/frmts/jpipkak/frmt_jpipkak.html b/frmts/jpipkak/frmt_jpipkak.html
index af34fe5..8a4c44d 100644
--- a/frmts/jpipkak/frmt_jpipkak.html
+++ b/frmts/jpipkak/frmt_jpipkak.html
@@ -1,249 +1,256 @@
-<html>
-<head>
-<title>JPIPKAK - JPIP Streaming</title>
-</head>
-<body bgcolor="#ffffff">
-  <h1>JPIPKAK - JPIP Streaming</h1>
-  <p>
-  JPEG 2000 Interactive Protocol (JPIP) flexibility with respect to random access, code stream reordering and incremental decoding is highly exploitable in a networked environment allowing access to remote large files using limited bandwidth connections or high contention networks.
-  </p>
-  <h2>JPIPKAK - JPIP Overview</h2>
-  <p>
-  A brief overview of the JPIP event sequence is presented in this section, more information can be found at <a target="_blank" href="http://www.jpeg.org/jpeg2000/j2kpart9.html">JPEG 2000 Interactive Protocol (Part 9 � JPIP)</a> and the specification can (and should) be purchased from <a target="_blank" href="http://www.iso.org">ISO</a>.  
-  </p>
-  <p>
-  An earlier version of JPEG 2000 Part 9 is available here <a href="http://www.jpeg.org/public/fcd15444-9v2.pdf">http://www.jpeg.org/public/fcd15444-9v2.pdf</a>, noting the ISO copyright, diagrams are not replicated in this documentation.
-  </p>
-  <p>
-  The JPIP protocol has been abstracted in this format driver, requests are made at the 1:1 resolution level.
-  </p>
-  <img src="jpipsequence.png" alt="JPIP Sequence Diagram"/>
-  <ol>
-    <li><a name="initJPIP">Initial</a> JPIP request for a target image, a target id, a session over http, data to be returned as a jpp-stream are requested and a maximum length is put on the response.  In this case no initial window is requested, though it can be.
-Server responds with a target identifier that can be used to identify the image on the server and a JPIP-cnew response header which includes the path to the JPIP server which will handle all future requests and a cid session identifier.  A session is required so that that the server can model the state of the client connection, only sending the data that is required.
-</li>
-   <li>Client requests particular view windows on the target image with a maximum response length and includes the session identifier established in the previous communication.
-'fsiz' is used to identify the resolution associated with the requested view-window. The values 'fx' and 'fy' specify the dimensions of the desired image resolution. 
-'roff' is used to identify the upper left hand corner off the spatial region associated with the requested view-windw. 
-'rsiz' is used to identify the horizontal and vertical extents of the spatial region associated with the requested view-window.</li>
-  </ol>
-  <h2>JPIPKAK -approach</h2>
-  <p>
-  The JPIPKAK driver uses an approach that was first demonstrated here, <a target="_blank" href="http://www.drc-dev.ohiolink.edu/browser/J2KViewer">J2KViewer</a>, by Juan Pablo Garcia Ortiz of separating the communication layer (socket / http) from the Kakadu kdu_cache object.  Separating the communication layer from the data object is desirable since it allows the use of optimized http client libraries such as libcurl, Apache HttpClient (note that  jportiz used a plain Java socket) and  [...]
-  </p>
-  <p>
-Kakadu's implementation of client communication with a JPIP server uses a socket, and this socket connection holds the state for this client session.  A client session with Kakadu can be recreated using the JPIP cache operations between client and server, but no use of traditional HTTP cookies is supported since JPIP is neutral to the transport layer.
- </p>
- <p>
-The JPIPKAK driver is written using a HTTP client library with the Kakadu cache object and supports optimized communication with a JPIP server (which may or may not support HTTP sessions) and the high performance of the kakadu kdu_region_decompressor.
-  </p>
-  <img src="components.PNG" alt="Component Diagram"/>
-  <h2>JPIPKAK - implementation</h2>
-  <p>
-  The implementation supports the GDAL C++ and C API, and provides an initial SWIG wrapper for this driver with a Java ImageIO example (<b>TODO</b> - qGIS Example).
-  </p>
-  <p>
-  The driver uses a simple threading model to support requesting reads of the data and remote fetching.  This threading model supports two separate client windows, with just one connection to the server.  Requests to the server are multiplexed to utilize available bandwidth efficiently. The client identifies these windows by using �0� (low) or �1� (high) values to a �PRIORITY� metadata request option.
-  </p>
-  <i>
-  <p>
-  Note: SSL support
-  </p>
-  <p>If the client is built with support for SSL, then driver determines whether to use SSL if the request is a jpips:// protocol as opposed to jpip:// . Note that the driver does not verify server certificates using the Curl certificate bundle and is currently set to accept all SSL server certificates.
-</p>
-   <p>
-   Note: libCurl
-   </p>
-   <p>
-   JPIP sets client/server values using HTTP headers, modifications have been made to the GDAL  HTTP portability library to support this.
-   </p>
-  </i>
-  <img src="gdalsequence.PNG" alt="GDAL Sequence Diagram"/>
-  <ol>
-    <li>
-    GDALGetDatasetDriver
-    <p>
-    Fetch the driver to which this dataset relates. 
-    </p>
-    </li>
-    <li>
-    Open
-    <p>
-    If the filename contained in the <code>GDALOpenInfo</code> object has a case insensitive URI scheme of jpip or jpips the <code>JPIPKAKDataset</code> is created and initialised</a>, otherwise NULL is returned.
-    </p>
-    </li>
-    <li>
-    Initialize
-    <p>
-    Initialisation involves making an initial connection to the JPIP Server to establish a session and to retrieve the initial metadata about the image (ref. <a href="#initJPIP">JPIP Sequence Diagram</a>).
-    </p>
-    <p>
-    If the connection fails, the function returns false and the <code>Open</code> function returns NULL indicating that opening the dataset with this driver failed.
-    </p>
-    <p>
-    If the connection is successful, then subsequent requests to the JPIP server are made to retrieve all the available metadata about the image.  Metadata items are set using the <code>GDALMajorObject->SetMetadataItem</code> in the "JPIP" domain.
-    </p>
-    <p>
-    If the metadata returned from the server includes GeoJP2 UUID box, or a GMLJP2 XML box then this metadata is parsed and sets the geographic metadata of this dataset.
-    </p>
-    </li>
-    <li>
-    GDALGetMetadata
-    <p>
-    C API to <code>JPIPKAKDataset->GetMetadata</code>
-    </p>
-    </li>
-    <li>
-    GetMetadata
-    <p>
-    returns metadata for the "JPIP" domain, keys are "JPIP_NQUALITYLAYERS", "JPIP_NRESOLUTIONLEVELS", "JPIP_NCOMPS" and "JPIP_SPRECISION" 
-    </p>
-    </li>
-    <li>
-    GDALEndAsyncRasterIO
-    <p>
-    If the asynchronous raster IO is active and not required, the C API calls <code>JPIPKAKDataset->EndAsyncRasterIO</code>
-    </p>
-    </li>
-    <li>
-    EndAsyncRasterIO
-    <p>
-    The JPIPKAKAsyncRasterIO object is deleted
-    </p>
-    </li>
-    <li>
-    delete
-    <p>
-    </p>
-    </li>
-    <li>
-    GDALBeginAsyncRasterIO
-    <p>
-    C API to <code>JPIPKAKDataset->BeginAsyncRasterIO</code>
-    </p>
-    </li>
-    <li>
-    BeginAsyncRasterIO
-    <p>
-    The client has set the requested view window at 1:1 and have optionally set the discard level, quality layers and thread priority metadata items.
-    </p>
-    </li>
-    <li>
-    Create
-    <p>
-    Creates a JPIPKAKAsyncRasterIO Object
-    </p>
-    </li>
-    <li>
-    Start
-    <p>
-    Configures the kakadu machinery and starts a background thread (if not already running) to communicate to the server the current view window request.  The background thread results in the <code>kdu_cache</code> object being updated until the JPIP server sends an "End Of Response" (EOR) message for the current view window request.
-    </p>
-    </li>
-    <li>
-    GDALLockBuffer<a name="GDALLockBuffer"/>
-    <p>
-    C API to LockBuffer
-    </p>
-    </li>
-    <li>
-    LockBuffer<a name="LockBuffer"/>
-    <p>
-    Not implemented in <code>JPIPKAKAsyncRasterIO</code>, a lock is acquired in <code>JPIPKAKAsyncRasterIO->GetNextUpdatedRegion</code>
-    </p>
-    </li>
-    <li>
-    GDALGetNextUpdatedRegion<a name="GDALGetNextUpdatedRegion"/>
-    <p>
-    C API to GetNextUpdatedRegion
-    </p>
-    </li>
-    <li>
-    GetNextUpdatedRegion<a name="GetNextUpdatedRegion"/>
-    <p>
-    The function decompresses the available data to generate an image (according to the dataset buffer type set in <code>JPIPKAKDataset->BeginAsyncRasterIO</code>)
-    The window width, height (at the requested discard level) decompressed is returned in the region pointer and can be rendered by the client.
-    The status of the rendering operation is one of <code>GARIO_PENDING, GARIO_UPDATE, GARIO_ERROR, GARIO_COMPLETE</code> from the <code>GDALAsyncStatusType</code> structure.  <code>GARIO_UPDATE, GARIO_PENDING</code> require more reads of GetNextUpdatedRegion to get the full image data, this is the progressive rendering of JPIP.   <code>GARIO_COMPLETE</code> indicates the window is complete.
-    </p>
-    <p>
-    <code>GDALAsyncStatusType</code> is a structure used by<code>GetNextUpdatedRegion</code> to indicate whether the function should be called again when either kakadu has more data in its cache to decompress, or the server has not sent an End Of Response (EOR) message to indicate the request window is complete.
-    </p>
-    <p>
-    The region passed into this function is passed by reference, and the caller can read this region when the result returns to find the region that has been decompressed.  The image data is packed into the buffer, e.g. RGB if the region requested has 3 components.
-    </p>
-    </li>
-    <li>
-    GDALUnlockBuffer<a name="GDALUnlockBuffer"/>
-    <p>
-    C Api to UnlockBuffer
-    </p>
-    </li>
-    <li>
-    UnlockBuffer<a name="UnlockBuffer"/>
-    <p>
-    Not implemented in <code>JPIPKAKAsyncRasterIO</code>, a lock is acquired in <code>JPIPKAKAsyncRasterIO->GetNextUpdatedRegion</code>
-    </p>
-    </li>
-    <li>
-    Draw<a name="Draw"/>
-    <p>
-    Client renders image data
-    </p>
-    </li>
-    <li>
-    <a href="#GDALLockBuffer">GDALLockBuffer</a>
-    <p>
-    </p>
-    </li>
-    <li>
-    <a href="#LockBuffer">LockBuffer</a>
-    <p>
-    </p>
-    </li>
-    <li>
-    <a href="#GDALGetNextUpdatedRegion">GDALGetNextUpdatedRegion</a>
-    <p>
-    </p>
-    </li>
-    <li>
-    <a href="#GetNextUpdatedRegion">GetNextUpdatedRegion</a>
-    <p>
-    </p>
-    </li>
-    <li>
-    <a href="#GDALUnlockBuffer">GDALUnlockBuffer</a>
-    <p>
-    </p>
-    </li>
-    <li>
-    <a href="#UnlockBuffer">UnlockBuffer</a>
-    <p>
-    </p>
-    </li>
-    <li>
-    <a href="#Draw">Draw</a>
-    <p>
-    </p>
-    </li>
-  </ol>
-  <h2>JPIPKAK - installation requirements</h2>
-  <ul>
-    <li><a target="_blank" href="http://curl.haxx.se/">Libcurl 7.9.4</a></li>
-    <li><a target="_blank" href="http://www.openssl.org/">OpenSSL 0.9.8K</a> (if SSL is required, a JPIPS connection)</li>
-    <li><a target="_blank" href="http://www.kakadusoftware.com">Kakadu</a> (tested with v5.2.6 and v6)</li>
-  </ul>
-  <p>Currently only a Windows makefile is provided, however this should compile on Linux as well as there are no Windows dependencies.</p>
-  <p>See Also:
-    <ul>
-        <li><a target="_blank" href="http://www.jpeg.org/jpeg2000/j2kpart9.html">JPEG 2000 Interactive Protocol (Part 9 � JPIP)</a></li>
-        <li><a target="_blank" href="http://www.opengeospatial.org/standards/gmljp2">http://www.opengeospatial.org/standards/gmljp2</a></li>
-        <li><a target="_blank" href="http://www.kakadusoftware.com">Kakadu Software </a></li>
-        <li><a target="_blank" href="http://iasdemo.ittvis.com/">IAS demo (example JPIP(S) streams)</a></li>
-    </ul>
-  </p>
-  <h2>NOTES</h2>
-  <p>
-  Driver originally developed by <a target="_blank" href="http://www.ittvis.com">ITT VIS</a> and donated to GDAL to enable SSL enabled JPIP client streaming of remote JPEG 2000 datasets.
-  </p>
-</body>
-</html>
\ No newline at end of file
+<html>
+<head>
+<meta http-equiv=Content-Type content="text/html; charset=utf-8">
+<title>JPIPKAK - JPIP Streaming</title>
+</head>
+<body bgcolor="#ffffff">
+  <h1>JPIPKAK - JPIP Streaming</h1>
+  <p>
+  JPEG 2000 Interactive Protocol (JPIP) flexibility with respect to random access, code stream reordering and incremental decoding is highly exploitable in a networked environment allowing access to remote large files using limited bandwidth connections or high contention networks.
+  </p>
+  <h2>JPIPKAK - JPIP Overview</h2>
+  <p>
+  A brief overview of the JPIP event sequence is presented in this section, more information can be found at <a target="_blank" href="http://www.jpeg.org/jpeg2000/j2kpart9.html">JPEG 2000 Interactive Protocol (Part 9 – JPIP)</a> and the specification can (and should) be purchased from <a target="_blank" href="http://www.iso.org">ISO</a>.
+  </p>
+  <p>
+  An earlier version of JPEG 2000 Part 9 is available here <a href="http://www.jpeg.org/public/fcd15444-9v2.pdf">http://www.jpeg.org/public/fcd15444-9v2.pdf</a>, noting the ISO copyright, diagrams are not replicated in this documentation.
+  </p>
+  <p>
+  The JPIP protocol has been abstracted in this format driver, requests are made at the 1:1 resolution level.
+  </p>
+  <img src="jpipsequence.png" alt="JPIP Sequence Diagram"/>
+  <ol>
+    <li><a name="initJPIP">Initial</a> JPIP request for a target image, a target id, a session over http, data to be returned as a jpp-stream are requested and a maximum length is put on the response.  In this case no initial window is requested, though it can be.
+Server responds with a target identifier that can be used to identify the image on the server and a JPIP-cnew response header which includes the path to the JPIP server which will handle all future requests and a cid session identifier.  A session is required so that that the server can model the state of the client connection, only sending the data that is required.
+</li>
+   <li>Client requests particular view windows on the target image with a maximum response length and includes the session identifier established in the previous communication.
+'fsiz' is used to identify the resolution associated with the requested view-window. The values 'fx' and 'fy' specify the dimensions of the desired image resolution.
+'roff' is used to identify the upper left hand corner off the spatial region associated with the requested view-windw.
+'rsiz' is used to identify the horizontal and vertical extents of the spatial region associated with the requested view-window.</li>
+  </ol>
+  <h2>JPIPKAK -approach</h2>
+  <p>
+  The JPIPKAK driver uses an approach that was first demonstrated here, <a target="_blank" href="http://www.drc-dev.ohiolink.edu/browser/J2KViewer">J2KViewer</a>, by Juan Pablo Garcia Ortiz of separating the communication layer (socket / http) from the Kakadu kdu_cache object.  Separating the communication layer from the data object is desirable since it allows the use of optimized http client libraries such as libcurl, Apache HttpClient (note that  jportiz used a plain Java socket) and  [...]
+  </p>
+  <p>
+Kakadu's implementation of client communication with a JPIP server uses a socket, and this socket connection holds the state for this client session.  A client session with Kakadu can be recreated using the JPIP cache operations between client and server, but no use of traditional HTTP cookies is supported since JPIP is neutral to the transport layer.
+ </p>
+ <p>
+The JPIPKAK driver is written using a HTTP client library with the Kakadu cache object and supports optimized communication with a JPIP server (which may or may not support HTTP sessions) and the high performance of the kakadu kdu_region_decompressor.
+  </p>
+  <img src="components.PNG" alt="Component Diagram"/>
+  <h2>JPIPKAK - implementation</h2>
+  <p>
+  The implementation supports the GDAL C++ and C API, and provides an initial SWIG wrapper for this driver with a Java ImageIO example (<b>TODO</b> - qGIS Example).
+  </p>
+  <p>
+  The driver uses a simple threading model to support requesting reads of the data and remote fetching.  This threading model supports two separate client windows, with just one connection to the server.  Requests to the server are multiplexed to utilize available bandwidth efficiently. The client identifies these windows by using “0” (low) or “1” (high) values to a “PRIORITY” metadata request option.
+  </p>
+  <i>
+  <p>
+  Note: SSL support
+  </p>
+  <p>If the client is built with support for SSL, then driver determines whether to use SSL if the request is a jpips:// protocol as opposed to jpip:// . Note that the driver does not verify server certificates using the Curl certificate bundle and is currently set to accept all SSL server certificates.
+</p>
+   <p>
+   Note: libCurl
+   </p>
+   <p>
+   JPIP sets client/server values using HTTP headers, modifications have been made to the GDAL  HTTP portability library to support this.
+   </p>
+  </i>
+  <img src="gdalsequence.PNG" alt="GDAL Sequence Diagram"/>
+  <ol>
+    <li>
+    GDALGetDatasetDriver
+    <p>
+    Fetch the driver to which this dataset relates.
+    </p>
+    </li>
+    <li>
+    Open
+    <p>
+    If the filename contained in the <code>GDALOpenInfo</code> object
+    has a case insensitive URI scheme of JPIP or JPIPS
+    the <code>JPIPKAKDataset</code> is created and initialized</a>,
+    otherwise NULL is returned.
+    </p>
+    </li>
+    <li>
+    Initialize
+    <p>
+    Initialization involves making an initial connection to the JPIP
+    Server to establish a session and to retrieve the initial metadata
+    about the image (ref. <a href="#initJPIP">JPIP Sequence
+    Diagram</a>).
+    </p>
+    <p>
+    If the connection fails, the function returns false and the <code>Open</code> function returns NULL indicating that opening the dataset with this driver failed.
+    </p>
+    <p>
+    If the connection is successful, then subsequent requests to the JPIP server are made to retrieve all the available metadata about the image.  Metadata items are set using the <code>GDALMajorObject->SetMetadataItem</code> in the "JPIP" domain.
+    </p>
+    <p>
+    If the metadata returned from the server includes GeoJP2 UUID box, or a GMLJP2 XML box then this metadata is parsed and sets the geographic metadata of this dataset.
+    </p>
+    </li>
+    <li>
+    GDALGetMetadata
+    <p>
+    C API to <code>JPIPKAKDataset->GetMetadata</code>
+    </p>
+    </li>
+    <li>
+    GetMetadata
+    <p>
+    returns metadata for the "JPIP" domain, keys are "JPIP_NQUALITYLAYERS", "JPIP_NRESOLUTIONLEVELS", "JPIP_NCOMPS" and "JPIP_SPRECISION"
+    </p>
+    </li>
+    <li>
+    GDALEndAsyncRasterIO
+    <p>
+    If the asynchronous raster IO is active and not required, the C API calls <code>JPIPKAKDataset->EndAsyncRasterIO</code>
+    </p>
+    </li>
+    <li>
+    EndAsyncRasterIO
+    <p>
+    The JPIPKAKAsyncRasterIO object is deleted
+    </p>
+    </li>
+    <li>
+    delete
+    <p>
+    </p>
+    </li>
+    <li>
+    GDALBeginAsyncRasterIO
+    <p>
+    C API to <code>JPIPKAKDataset->BeginAsyncRasterIO</code>
+    </p>
+    </li>
+    <li>
+    BeginAsyncRasterIO
+    <p>
+    The client has set the requested view window at 1:1 and have optionally set the discard level, quality layers and thread priority metadata items.
+    </p>
+    </li>
+    <li>
+    Create
+    <p>
+    Creates a JPIPKAKAsyncRasterIO Object
+    </p>
+    </li>
+    <li>
+    Start
+    <p>
+    Configures the kakadu machinery and starts a background thread (if not already running) to communicate to the server the current view window request.  The background thread results in the <code>kdu_cache</code> object being updated until the JPIP server sends an "End Of Response" (EOR) message for the current view window request.
+    </p>
+    </li>
+    <li>
+    GDALLockBuffer<a name="GDALLockBuffer"/>
+    <p>
+    C API to LockBuffer
+    </p>
+    </li>
+    <li>
+    LockBuffer<a name="LockBuffer"/>
+    <p>
+    Not implemented in <code>JPIPKAKAsyncRasterIO</code>, a lock is acquired in <code>JPIPKAKAsyncRasterIO->GetNextUpdatedRegion</code>
+    </p>
+    </li>
+    <li>
+    GDALGetNextUpdatedRegion<a name="GDALGetNextUpdatedRegion"/>
+    <p>
+    C API to GetNextUpdatedRegion
+    </p>
+    </li>
+    <li>
+    GetNextUpdatedRegion<a name="GetNextUpdatedRegion"/>
+    <p>
+    The function decompresses the available data to generate an image (according to the dataset buffer type set in <code>JPIPKAKDataset->BeginAsyncRasterIO</code>)
+    The window width, height (at the requested discard level) decompressed is returned in the region pointer and can be rendered by the client.
+    The status of the rendering operation is one of <code>GARIO_PENDING, GARIO_UPDATE, GARIO_ERROR, GARIO_COMPLETE</code> from the <code>GDALAsyncStatusType</code> structure.  <code>GARIO_UPDATE, GARIO_PENDING</code> require more reads of GetNextUpdatedRegion to get the full image data, this is the progressive rendering of JPIP.   <code>GARIO_COMPLETE</code> indicates the window is complete.
+    </p>
+    <p>
+    <code>GDALAsyncStatusType</code> is a structure used by<code>GetNextUpdatedRegion</code> to indicate whether the function should be called again when either kakadu has more data in its cache to decompress, or the server has not sent an End Of Response (EOR) message to indicate the request window is complete.
+    </p>
+    <p>
+    The region passed into this function is passed by reference, and the caller can read this region when the result returns to find the region that has been decompressed.  The image data is packed into the buffer, e.g. RGB if the region requested has 3 components.
+    </p>
+    </li>
+    <li>
+    GDALUnlockBuffer<a name="GDALUnlockBuffer"/>
+    <p>
+    C Api to UnlockBuffer
+    </p>
+    </li>
+    <li>
+    UnlockBuffer<a name="UnlockBuffer"/>
+    <p>
+    Not implemented in <code>JPIPKAKAsyncRasterIO</code>, a lock is acquired in <code>JPIPKAKAsyncRasterIO->GetNextUpdatedRegion</code>
+    </p>
+    </li>
+    <li>
+    Draw<a name="Draw"/>
+    <p>
+    Client renders image data
+    </p>
+    </li>
+    <li>
+    <a href="#GDALLockBuffer">GDALLockBuffer</a>
+    <p>
+    </p>
+    </li>
+    <li>
+    <a href="#LockBuffer">LockBuffer</a>
+    <p>
+    </p>
+    </li>
+    <li>
+    <a href="#GDALGetNextUpdatedRegion">GDALGetNextUpdatedRegion</a>
+    <p>
+    </p>
+    </li>
+    <li>
+    <a href="#GetNextUpdatedRegion">GetNextUpdatedRegion</a>
+    <p>
+    </p>
+    </li>
+    <li>
+    <a href="#GDALUnlockBuffer">GDALUnlockBuffer</a>
+    <p>
+    </p>
+    </li>
+    <li>
+    <a href="#UnlockBuffer">UnlockBuffer</a>
+    <p>
+    </p>
+    </li>
+    <li>
+    <a href="#Draw">Draw</a>
+    <p>
+    </p>
+    </li>
+  </ol>
+  <h2>JPIPKAK - installation requirements</h2>
+  <ul>
+    <li><a target="_blank" href="http://curl.haxx.se/">Libcurl 7.9.4</a></li>
+    <li><a target="_blank" href="http://www.openssl.org/">OpenSSL 0.9.8K</a> (if SSL is required, a JPIPS connection)</li>
+    <li><a target="_blank" href="http://www.kakadusoftware.com">Kakadu</a> (tested with v5.2.6 and v6)</li>
+  </ul>
+  <p>Currently only a Windows makefile is provided, however this should compile on Linux as well as there are no Windows dependencies.</p>
+  <p>See Also:
+    <ul>
+        <li><a target="_blank" href="http://www.jpeg.org/jpeg2000/j2kpart9.html">JPEG 2000 Interactive Protocol (Part 9 – JPIP)</a></li>
+        <li><a target="_blank" href="http://www.opengeospatial.org/standards/gmljp2">http://www.opengeospatial.org/standards/gmljp2</a></li>
+        <li><a target="_blank" href="http://www.kakadusoftware.com">Kakadu Software </a></li>
+        <li><a target="_blank" href="http://iasdemo.ittvis.com/">IAS demo (example JPIP(S) streams)</a></li>
+    </ul>
+  </p>
+  <h2>NOTES</h2>
+  <p>
+  Driver originally developed by <a target="_blank" href="http://www.ittvis.com">ITT VIS</a> and donated to GDAL to enable SSL enabled JPIP client streaming of remote JPEG 2000 datasets.
+  </p>
+</body>
+</html>
diff --git a/frmts/jpipkak/jpipkak_headers.h b/frmts/jpipkak/jpipkak_headers.h
new file mode 100644
index 0000000..15cad1c
--- /dev/null
+++ b/frmts/jpipkak/jpipkak_headers.h
@@ -0,0 +1,42 @@
+/******************************************************************************
+ *
+ * Project:  GDAL
+ * Purpose:  Includes JP2KAK SDK headers
+ * Author:   Even Rouault <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+#ifndef JPIPKAK_HEADERS_H
+#define JPIPKAK_HEADERS_H
+
+#include "cpl_port.h"
+
+#ifdef HAVE_GCC_SYSTEM_HEADER
+#pragma GCC system_header
+#endif
+
+#include "kdu_cache.h"
+#include "kdu_region_decompressor.h"
+#include "kdu_file_io.h"
+
+#endif /* JPIPKAK_HEADERS_H */
diff --git a/frmts/jpipkak/jpipkakdataset.cpp b/frmts/jpipkak/jpipkakdataset.cpp
index a0253cf..c47c038 100644
--- a/frmts/jpipkak/jpipkakdataset.cpp
+++ b/frmts/jpipkak/jpipkakdataset.cpp
@@ -2,23 +2,23 @@
  * $Id: jpipkakdataset.cpp 2008-10-01 nbarker $
  *
  * Project:  jpip read driver
- * Purpose:  GDAL bindings for JPIP.  
+ * Purpose:  GDAL bindings for JPIP.
  * Author:   Norman Barker, ITT VIS, norman.barker at gmail.com
  *
  ******************************************************************************
- * ITT Visual Information Systems grants you use of this code, under the 
+ * ITT Visual Information Systems grants you use of this code, under the
  * following license:
- * 
- * Copyright (c) 2000-2007, ITT Visual Information Solutions 
+ *
+ * Copyright (c) 2000-2007, ITT Visual Information Solutions
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * to deal in the Software without restriction, including without limitation
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions: 
+ * Software is furnished to do so, subject to the following conditions:
  * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software. 
+ * in all copies or substantial portions of the Software.
 
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
@@ -29,12 +29,16 @@
  * DEALINGS IN THE SOFTWARE.
 **/
 
-#include "jpipkakdataset.h"
+#ifdef DEBUG_BOOL
+#define DO_NOT_USE_DEBUG_BOOL
+#endif
 
+#include "gdal_frmts.h"
+#include "jpipkakdataset.h"
 
-/* 
+/*
 ** The following are for testing premature stream termination support.
-** This is a mechanism to test handling of failed or incomplete reads 
+** This is a mechanism to test handling of failed or incomplete reads
 ** from the server, and is not normally active.  For this reason we
 ** don't worry about the non-threadsafe nature of the debug support
 ** variables below.
@@ -56,10 +60,12 @@ static int nPSTTargetOffset = -1;
 /* ==================================================================== */
 /************************************************************************/
 
-class jpipkak_kdu_cpl_error_message : public kdu_message 
+class jpipkak_kdu_cpl_error_message : public kdu_message
 {
 public: // Member classes
-    jpipkak_kdu_cpl_error_message( CPLErr eErrClass ) 
+    using kdu_message::put_text;
+
+    jpipkak_kdu_cpl_error_message( CPLErr eErrClass )
     {
         m_eErrClass = eErrClass;
         m_pszError = NULL;
@@ -71,7 +77,7 @@ public: // Member classes
             m_pszError = CPLStrdup( string );
         else
         {
-            m_pszError = (char *) 
+            m_pszError = (char *)
                 CPLRealloc(m_pszError, strlen(m_pszError) + strlen(string)+1 );
             strcat( m_pszError, string );
         }
@@ -81,7 +87,7 @@ public: // Member classes
     {
     };
 
-    void flush(bool end_of_message=false) 
+    void flush(bool end_of_message=false)
     {
         if( m_pszError == NULL )
             return;
@@ -113,19 +119,19 @@ private:
 /*                         JPIPKAKRasterBand()                          */
 /************************************************************************/
 
-JPIPKAKRasterBand::JPIPKAKRasterBand( int nBand, int nDiscardLevels,
-                                      kdu_codestream *oCodeStream,
+JPIPKAKRasterBand::JPIPKAKRasterBand( int nBandIn, int nDiscardLevelsIn,
+                                      kdu_codestream *oCodeStreamIn,
                                       int nResCount,
                                       JPIPKAKDataset *poBaseDSIn )
 
 {
-    this->nBand = nBand;
+    this->nBand = nBandIn;
     poBaseDS = poBaseDSIn;
 
     eDataType = poBaseDSIn->eDT;
 
-    this->nDiscardLevels = nDiscardLevels;
-    this->oCodeStream = oCodeStream;
+    this->nDiscardLevels = nDiscardLevelsIn;
+    this->oCodeStream = oCodeStreamIn;
 
     oCodeStream->apply_input_restrictions( 0, 0, nDiscardLevels, 0, NULL );
     oCodeStream->get_dims( 0, band_dims );
@@ -140,7 +146,7 @@ JPIPKAKRasterBand::JPIPKAKRasterBand( int nBand, int nDiscardLevels,
         nBlockXSize = 2048;
     else
         nBlockXSize = nRasterXSize;
-    
+
     if( nRasterYSize >= 256 )
         nBlockYSize = 128;
     else
@@ -149,9 +155,9 @@ JPIPKAKRasterBand::JPIPKAKRasterBand( int nBand, int nDiscardLevels,
 /* -------------------------------------------------------------------- */
 /*      Figure out the color interpretation for this band.              */
 /* -------------------------------------------------------------------- */
-    
+
     eInterp = GCI_Undefined;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Do we have any overviews?  Only check if we are the full res    */
 /*      image.                                                          */
@@ -180,17 +186,17 @@ JPIPKAKRasterBand::JPIPKAKRasterBand( int nBand, int nDiscardLevels,
                 && (dims.size.y == nYSize || dims.size.y == nYSize-1) )
             {
                 nOverviewCount++;
-                papoOverviewBand = (JPIPKAKRasterBand **) 
-                    CPLRealloc( papoOverviewBand, 
+                papoOverviewBand = (JPIPKAKRasterBand **)
+                    CPLRealloc( papoOverviewBand,
                                 sizeof(void*) * nOverviewCount );
-                papoOverviewBand[nOverviewCount-1] = 
+                papoOverviewBand[nOverviewCount-1] =
                     new JPIPKAKRasterBand( nBand, nDiscard, oCodeStream, 0,
                                            poBaseDS );
             }
             else
             {
                 CPLDebug( "GDAL", "Discard %dx%d JPEG2000 overview layer,\n"
-                          "expected %dx%d.", 
+                          "expected %dx%d.",
                           dims.size.x, dims.size.y, nXSize, nYSize );
             }
         }
@@ -240,7 +246,7 @@ GDALRasterBand *JPIPKAKRasterBand::GetOverview( int iOverviewIndex )
 CPLErr JPIPKAKRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                       void * pImage )
 {
-    CPLDebug( "JPIPKAK", "IReadBlock(%d,%d) on band %d.", 
+    CPLDebug( "JPIPKAK", "IReadBlock(%d,%d) on band %d.",
               nBlockXOff, nBlockYOff, nBand );
 
 /* -------------------------------------------------------------------- */
@@ -272,7 +278,7 @@ CPLErr JPIPKAKRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         xSize = poBaseDS->GetRasterXSize() - xOff;
         nBufXSize= MAX(xSize/nZoom,1);
     }
-    
+
     if( yOff + ySize > poBaseDS->GetRasterYSize() )
     {
         ySize = poBaseDS->GetRasterYSize() - yOff;
@@ -285,23 +291,23 @@ CPLErr JPIPKAKRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     GDALAsyncReader* ario = poBaseDS->
         BeginAsyncReader(xOff, yOff, xSize, ySize,
                          pImage, nBufXSize,nBufYSize,
-                         eDataType, 1, &nBand, 
+                         eDataType, 1, &nBand,
                          nPixelSpace, nLineSpace, nBandSpace, NULL);
 
     if( ario == NULL )
         return CE_Failure;
 
     int nXBufOff; // absolute x image offset
-    int nYBufOff; // abolute y image offset
+    int nYBufOff; // absolute y image offset
     int nXBufSize;
     int nYBufSize;
 
     GDALAsyncStatusType status;
 
-    do 
+    do
     {
-        status = ario->GetNextUpdatedRegion(-1.0, 
-                                            &nXBufOff, &nYBufOff, 
+        status = ario->GetNextUpdatedRegion(-1.0,
+                                            &nXBufOff, &nYBufOff,
                                             &nXBufSize, &nYBufSize );
     } while (status != GARIO_ERROR && status != GARIO_COMPLETE );
 
@@ -317,46 +323,47 @@ CPLErr JPIPKAKRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /*                             IRasterIO()                              */
 /************************************************************************/
 
-CPLErr 
+CPLErr
 JPIPKAKRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                               int nXOff, int nYOff, int nXSize, int nYSize,
                               void * pData, int nBufXSize, int nBufYSize,
-                              GDALDataType eBufType, 
+                              GDALDataType eBufType,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
                               GDALRasterIOExtraArg* psExtraArg)
-    
+
 {
 /* -------------------------------------------------------------------- */
 /*      We need various criteria to skip out to block based methods.    */
 /* -------------------------------------------------------------------- */
-    if( poBaseDS->TestUseBlockIO( nXOff, nYOff, nXSize, nYSize, 
+    if( poBaseDS->TestUseBlockIO( nXOff, nYOff, nXSize, nYSize,
                                   nBufXSize, nBufYSize,
                                   eBufType, 1, &nBand ) )
-        return GDALPamRasterBand::IRasterIO( 
+        return GDALPamRasterBand::IRasterIO(
             eRWFlag, nXOff, nYOff, nXSize, nYSize,
-            pData, nBufXSize, nBufYSize, eBufType, 
+            pData, nBufXSize, nBufYSize, eBufType,
             nPixelSpace, nLineSpace, psExtraArg );
 
 /* -------------------------------------------------------------------- */
 /*      Otherwise do this as a single uncached async rasterio.          */
 /* -------------------------------------------------------------------- */
-    GDALAsyncReader* ario = 
+    GDALAsyncReader* ario =
         poBaseDS->BeginAsyncReader(nXOff, nYOff, nXSize, nYSize,
-                                   pData, nBufXSize, nBufYSize, eBufType, 
+                                   pData, nBufXSize, nBufYSize, eBufType,
                                    1, &nBand,
-                                   nPixelSpace, nLineSpace, 0, NULL);
-    
+                                   static_cast<int>(nPixelSpace),
+                                   static_cast<int>(nLineSpace), 0, NULL);
+
     if( ario == NULL )
         return CE_Failure;
-    
+
     GDALAsyncStatusType status;
 
-    do 
+    do
     {
         int nXBufOff,nYBufOff,nXBufSize,nYBufSize;
 
-        status = ario->GetNextUpdatedRegion(-1.0, 
-                                            &nXBufOff, &nYBufOff, 
+        status = ario->GetNextUpdatedRegion(-1.0,
+                                            &nXBufOff, &nYBufOff,
                                             &nXBufSize, &nYBufSize );
     } while (status != GARIO_ERROR && status != GARIO_COMPLETE );
 
@@ -371,12 +378,12 @@ JPIPKAKRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 /*****************************************/
 /*         JPIPKAKDataset()              */
 /*****************************************/
-JPIPKAKDataset::JPIPKAKDataset()         
+JPIPKAKDataset::JPIPKAKDataset()
 {
     pszPath = NULL;
     pszCid = NULL;
     pszProjection = NULL;
-	
+
     poCache = NULL;
     poCodestream = NULL;
     poDecompressor = NULL;
@@ -482,66 +489,66 @@ int JPIPKAKDataset::Initialize(const char* pszDatasetName, int bReinitializing )
 
     osPersistent.Printf( "PERSISTENT=JPIPKAK:%p", this );
 
-    char *apszOptions[] = { 
+    char *apszOptions[] = {
         (char *) osHeaders.c_str(),
         (char *) osPersistent.c_str(),
-        NULL 
+        NULL
     };
 
     // Setup url to have http in place of jpip protocol indicator.
     CPLString osURL = "http";
     osURL += (pszDatasetName + 4);
-    
-    CPLAssert( strncmp(pszDatasetName,"jpip",4) == 0 );
 
-    // make initial request to the server for a session, we are going to 
+    CPLAssert( STARTS_WITH(pszDatasetName, "jpip") );
+
+    // make initial request to the server for a session, we are going to
     // assume that the jpip communication is stateful, rather than one-shot
-    // stateless requests append pszUrl with jpip request parameters for a 
+    // stateless requests append pszUrl with jpip request parameters for a
     // stateful session (multi-shot communications)
     // "cnew=http&type=jpp-stream&stream=0&tid=0&len="
     CPLString osRequest;
     osRequest.Printf("%s?%s%i", osURL.c_str(),
                      "cnew=http&type=jpp-stream&stream=0&tid=0&len=", 2000);
-	
+
     CPLHTTPResult *psResult = CPLHTTPFetch(osRequest, apszOptions);
-	
+
     if ( psResult == NULL)
         return FALSE;
 
     if( psResult->nDataLen == 0 || psResult->pabyData == NULL  )
     {
 
-        CPLError(CE_Failure, CPLE_AppDefined, 
+        CPLError(CE_Failure, CPLE_AppDefined,
                  "No data was returned from the given URL" );
         CPLHTTPDestroyResult( psResult );
         return FALSE;
     }
 
-    if (psResult->nStatus != 0) 
+    if (psResult->nStatus != 0)
     {
         CPLHTTPDestroyResult( psResult );
-        CPLError(CE_Failure, CPLE_AppDefined, 
+        CPLError(CE_Failure, CPLE_AppDefined,
                  "Curl reports error: %d: %s", psResult->nStatus, psResult->pszErrBuf );
-        return FALSE;        
+        return FALSE;
     }
 
-    // parse the response headers, and the initial data until we get to the 
+    // parse the response headers, and the initial data until we get to the
     // codestream definition
     char** pszHdrs = psResult->papszHeaders;
     const char* pszCnew = CSLFetchNameValue(pszHdrs, "JPIP-cnew");
 
     if( pszCnew == NULL )
     {
-        if( psResult->pszContentType != NULL 
-            && EQUALN(psResult->pszContentType,"text/html",9) )
-            CPLDebug( "JPIPKAK", "%s", 
+        if( psResult->pszContentType != NULL
+            && STARTS_WITH_CI(psResult->pszContentType, "text/html") )
+            CPLDebug( "JPIPKAK", "%s",
                       psResult->pabyData );
 
         CPLHTTPDestroyResult( psResult );
-        CPLError(CE_Failure, CPLE_AppDefined, 
+        CPLError(CE_Failure, CPLE_AppDefined,
                  "Unable to parse required cnew and tid response headers" );
 
-        return FALSE;    
+        return FALSE;
     }
 
     // parse cnew response
@@ -551,7 +558,7 @@ int JPIPKAKDataset::Initialize(const char* pszDatasetName, int bReinitializing )
     for (int i = 0; i < CSLCount(papszTokens); i++)
     {
         // looking for cid, path
-        if (EQUALN(papszTokens[i], "cid", 3))
+        if (STARTS_WITH_CI(papszTokens[i], "cid"))
         {
             char *pszKey = NULL;
             const char *pszValue = CPLParseNameValue(papszTokens[i], &pszKey );
@@ -559,7 +566,7 @@ int JPIPKAKDataset::Initialize(const char* pszDatasetName, int bReinitializing )
             CPLFree( pszKey );
         }
 
-        if (EQUALN(papszTokens[i], "path", 4))
+        if (STARTS_WITH_CI(papszTokens[i], "path"))
         {
             char *pszKey = NULL;
             const char *pszValue = CPLParseNameValue(papszTokens[i], &pszKey );
@@ -577,8 +584,8 @@ int JPIPKAKDataset::Initialize(const char* pszDatasetName, int bReinitializing )
         return FALSE;
     }
 
-    // ok, good to go with jpip, get to the codestream before returning 
-    // successful initialisation of the driver
+    // Okay, good to go with JPIP, get to the codestream before returning
+    // successful initialization of the driver
     try
     {
         poCache = new kdu_cache();
@@ -591,7 +598,7 @@ int JPIPKAKDataset::Initialize(const char* pszDatasetName, int bReinitializing )
                                   bError );
         CPLHTTPDestroyResult(psResult);
 
-        // continue making requests in the main thread to get all the available 
+        // continue making requests in the main thread to get all the available
         // metadata for data bin 0, and reach the codestream
 
         // format the new request
@@ -603,12 +610,12 @@ int JPIPKAKDataset::Initialize(const char* pszDatasetName, int bReinitializing )
         // find context path
         found = osRequest.find_first_of("/");
         osRequest.erase(found);
-			
+
         osRequestUrl.Printf("%s%s/%s?cid=%s&stream=0&len=%i", osProtocol.c_str(), osRequest.c_str(), pszPath, pszCid, 2000);
 
         while (!bFinished && !bError )
         {
-            CPLHTTPResult *psResult = CPLHTTPFetch(osRequestUrl, apszOptions);
+            psResult = CPLHTTPFetch(osRequestUrl, apszOptions);
             bFinished = ReadFromInput(psResult->pabyData, psResult->nDataLen,
                                       bError );
             CPLHTTPDestroyResult(psResult);
@@ -618,7 +625,7 @@ int JPIPKAKDataset::Initialize(const char* pszDatasetName, int bReinitializing )
             return FALSE;
 
         // clean up osRequest, remove variable len= parameter
-        size_t pos = osRequestUrl.find_last_of("&");	
+        size_t pos = osRequestUrl.find_last_of("&");
         osRequestUrl.erase(pos);
 
         // create codestream
@@ -643,11 +650,11 @@ int JPIPKAKDataset::Initialize(const char* pszDatasetName, int bReinitializing )
         kdu_channel_mapping oChannels;
         oChannels.configure(*poCodestream);
         kdu_coords* ref_expansion = new kdu_coords(1, 1);
-					
+
         // get available resolutions, image width / height etc.
         kdu_dims view_dims = poDecompressor->
             get_rendered_image_dims(*poCodestream, &oChannels, -1, 0,
-                                    *ref_expansion, *ref_expansion, 
+                                    *ref_expansion, *ref_expansion,
                                     KDU_WANT_OUTPUT_COMPONENTS);
 
         nRasterXSize = view_dims.size.x;
@@ -656,7 +663,7 @@ int JPIPKAKDataset::Initialize(const char* pszDatasetName, int bReinitializing )
         // Establish the datatype - we will use the same datatype for
         // all bands based on the first.  This really doesn't do something
         // great for >16 bit images.
-        if( poCodestream->get_bit_depth(0) > 8 
+        if( poCodestream->get_bit_depth(0) > 8
             && poCodestream->get_signed(0) )
         {
             eDT = GDT_Int16;
@@ -671,9 +678,9 @@ int JPIPKAKDataset::Initialize(const char* pszDatasetName, int bReinitializing )
 
         if( poCodestream->get_bit_depth(0) % 8 != 8
             && poCodestream->get_bit_depth(0) < 16 )
-            SetMetadataItem( 
-                "NBITS", 
-                CPLString().Printf("%d",poCodestream->get_bit_depth(0)), 
+            SetMetadataItem(
+                "NBITS",
+                CPLString().Printf("%d",poCodestream->get_bit_depth(0)),
                 "IMAGE_STRUCTURE" );
 
         // TODO add color interpretation
@@ -696,7 +703,7 @@ int JPIPKAKDataset::Initialize(const char* pszDatasetName, int bReinitializing )
     }
     catch(...)
     {
-        CPLError(CE_Failure, CPLE_AppDefined, 
+        CPLError(CE_Failure, CPLE_AppDefined,
                  "Trapped Kakadu exception attempting to initialize JPIP access." );
         return FALSE;
     }
@@ -713,13 +720,13 @@ int JPIPKAKDataset::Initialize(const char* pszDatasetName, int bReinitializing )
 /*      Setup band objects.                                             */
 /* -------------------------------------------------------------------- */
     int iBand;
-    
+
     for( iBand = 1; iBand <= nBands; iBand++ )
     {
-        JPIPKAKRasterBand *poBand = 
+        JPIPKAKRasterBand *poBand =
             new JPIPKAKRasterBand(iBand,0,poCodestream,nResLevels,
                                   this );
-	
+
         SetBand( iBand, poBand );
     }
 
@@ -742,7 +749,7 @@ int JPIPKAKDataset::Initialize(const char* pszDatasetName, int bReinitializing )
         SetMetadataItem("JPIP_YCC", "YES", "JPIP");
     else
         SetMetadataItem("JPIP_YCC", "NO", "JPIP");
-	
+
 /* ==================================================================== */
 /*      Parse geojp2, or gmljp2, we will assume that the core           */
 /*      metadata  of gml or a geojp2 uuid have been sent in the         */
@@ -755,7 +762,7 @@ int JPIPKAKDataset::Initialize(const char* pszDatasetName, int bReinitializing )
 
     if( nLen == 0 )
     {
-        CPLError(CE_Failure, CPLE_AppDefined, 
+        CPLError(CE_Failure, CPLE_AppDefined,
                  "Unable to open stream to parse metadata boxes" );
         return FALSE;
     }
@@ -784,24 +791,24 @@ int JPIPKAKDataset::Initialize(const char* pszDatasetName, int bReinitializing )
             pszProjection = CPLStrdup(oJP2Geo.pszProjection);
             bGeoTransformValid = TRUE;
 
-            memcpy(adfGeoTransform, oJP2Geo.adfGeoTransform, 
+            memcpy(adfGeoTransform, oJP2Geo.adfGeoTransform,
                    sizeof(double) * 6 );
             nGCPCount = oJP2Geo.nGCPCount;
             pasGCPList = oJP2Geo.pasGCPList;
 
             oJP2Geo.pasGCPList = NULL;
             oJP2Geo.nGCPCount = 0;
-						
+
             int iBox;
 
-            for( iBox = 0; 
+            for( iBox = 0;
                  oJP2Geo.papszGMLMetadata
-                     && oJP2Geo.papszGMLMetadata[iBox] != NULL; 
+                     && oJP2Geo.papszGMLMetadata[iBox] != NULL;
                  iBox++ )
             {
                 char *pszName = NULL;
-                const char *pszXML = 
-                    CPLParseNameValue( oJP2Geo.papszGMLMetadata[iBox], 
+                const char *pszXML =
+                    CPLParseNameValue( oJP2Geo.papszGMLMetadata[iBox],
                                        &pszName );
                 CPLString osDomain;
                 char *apszMDList[2];
@@ -817,14 +824,14 @@ int JPIPKAKDataset::Initialize(const char* pszDatasetName, int bReinitializing )
         else
         {
             // treat as cartesian, no geo metadata
-            CPLError(CE_Warning, CPLE_AppDefined, 
+            CPLError(CE_Warning, CPLE_AppDefined,
                      "Parsed metadata boxes from jpip stream, geographic metadata not found - is the server using placeholders for this data?" );
-						
+
         }
     }
     catch(...)
     {
-        CPLError(CE_Failure, CPLE_AppDefined, 
+        CPLError(CE_Failure, CPLE_AppDefined,
                  "Unable to parse geographic metadata boxes from jpip stream" );
     }
 
@@ -862,7 +869,7 @@ long JPIPKAKDataset::ReadVBAS(GByte* pabyData, int nLen )
         }
 
 #ifdef PST_DEBUG
-        if( nPSTThisInstance == nPSTTargetInstance 
+        if( nPSTThisInstance == nPSTTargetInstance
             && nPos >= nPSTTargetOffset )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
@@ -926,10 +933,10 @@ JPIPDataSegment* JPIPKAKDataset::ReadSegment(GByte* pabyData, int nLen,
                 return NULL;
             }
             else if (m >= 2) {
-                nClassId = ReadVBAS(pabyData, nLen);
+                nClassId = static_cast<int>(ReadVBAS(pabyData, nLen));
                 if (m > 2)
                 {
-                    nCodestream = ReadVBAS(pabyData, nLen);
+                    nCodestream = static_cast<int>(ReadVBAS(pabyData, nLen));
                     if( nCodestream < 0 )
                     {
                         bError = TRUE;
@@ -942,7 +949,7 @@ JPIPDataSegment* JPIPKAKDataset::ReadSegment(GByte* pabyData, int nLen,
 
             segment->SetClassId(nClassId);
             segment->SetCodestreamIdx(nCodestream);
-            
+
             nNextVal = ReadVBAS(pabyData, nLen);
             if( nNextVal == -1 )
             {
@@ -965,9 +972,9 @@ JPIPDataSegment* JPIPKAKDataset::ReadSegment(GByte* pabyData, int nLen,
         if ((segment->GetLen() > 0) && (!segment->IsEOR()))
         {
             GByte* pabyDataSegment = (GByte *) CPLCalloc(1,segment->GetLen());
-			
+
             // copy data from input array pabyData to the data segment
-            memcpy(pabyDataSegment, 
+            memcpy(pabyDataSegment,
                    pabyData + nPos,
                    segment->GetLen());
 
@@ -989,17 +996,17 @@ JPIPDataSegment* JPIPKAKDataset::ReadSegment(GByte* pabyData, int nLen,
 /******************************************/
 /*           KakaduClassId()              */
 /******************************************/
-int JPIPKAKDataset::KakaduClassId(int nClassId)
+int JPIPKAKDataset::KakaduClassId(int nClassIdIn)
 {
-    if (nClassId == 0)
+    if (nClassIdIn == 0)
         return KDU_PRECINCT_DATABIN;
-    else if (nClassId == 2)
+    else if (nClassIdIn == 2)
         return KDU_TILE_HEADER_DATABIN;
-    else if (nClassId == 6)
+    else if (nClassIdIn == 6)
         return KDU_MAIN_HEADER_DATABIN;
-    else if (nClassId == 8)  
+    else if (nClassIdIn == 8)
         return KDU_META_DATABIN;
-    else if (nClassId == 4)
+    else if (nClassIdIn == 4)
         return KDU_TILE_DATABIN;
     else
         return -1;
@@ -1027,36 +1034,35 @@ int JPIPKAKDataset::ReadFromInput(GByte* pabyData, int nLen, int &bError )
     {
         nPSTTargetInstance = atoi(CPLGetConfigOption("PST_INSTANCE","0"));
     }
-    
+
     if( nPSTTargetOffset != -1 && nPSTThisInstance == 0 )
     {
         CPLDebug( "JPIPKAK", "Premature Stream Termination Activated, PST_OFFSET=%d, PST_INSTANCE=%d",
                   nPSTTargetOffset, nPSTTargetInstance );
     }
-    if( nPSTTargetOffset != -1 
+    if( nPSTTargetOffset != -1
         && nPSTThisInstance == nPSTTargetInstance )
     {
-        CPLDebug( "JPIPKAK", "Premature Stream Termination in force for this input instance, PST_OFFSET=%d, data length=%d", 
+        CPLDebug( "JPIPKAK", "Premature Stream Termination in force for this input instance, PST_OFFSET=%d, data length=%d",
                   nPSTTargetOffset, nLen );
     }
-#endif // def PST_DEBUG 
-    
+#endif // def PST_DEBUG
+
     // parse the data stream, reading the vbas and adding to the kakadu cache
     // we could parse all the boxes by hand, and just add data to the kakadu cache
     // we will do it the easy way and retrieve the metadata through the kakadu query api
-    
+
     nPos = 0;
     JPIPDataSegment* pSegment = NULL;
-    
+
     while ((pSegment = ReadSegment(pabyData, nLen, bError)) != NULL)
     {
-	
         if (pSegment->IsEOR())
-        {		
-            if ((pSegment->GetId() == JPIPKAKDataset::JPIP_EOR_IMAGE_DONE) || 
+        {
+            if ((pSegment->GetId() == JPIPKAKDataset::JPIP_EOR_IMAGE_DONE) ||
                 (pSegment->GetId() == JPIPKAKDataset::JPIP_EOR_WINDOW_DONE))
                 res = TRUE;
-            
+
             delete pSegment;
             break;
         }
@@ -1064,9 +1070,11 @@ int JPIPKAKDataset::ReadFromInput(GByte* pabyData, int nLen, int &bError )
         {
             // add data to kakadu
             //CPLDebug("JPIPKAK", "Parsed JPIP Segment class=%i stream=%i id=%i offset=%i len=%i isFinal=%i isEOR=%i", pSegment->GetClassId(), pSegment->GetCodestreamIdx(), pSegment->GetId(), pSegment->GetOffset(), pSegment->GetLen(), pSegment->IsFinal(), pSegment->IsEOR());
-            poCache->add_to_databin(KakaduClassId(pSegment->GetClassId()), pSegment->GetCodestreamIdx(),
-                                    pSegment->GetId(), pSegment->GetData(), pSegment->GetOffset(), pSegment->GetLen(), pSegment->IsFinal());
-            
+            poCache->add_to_databin(KakaduClassId(static_cast<int>(pSegment->GetClassId())), pSegment->GetCodestreamIdx(),
+                                    pSegment->GetId(), pSegment->GetData(),
+                                    static_cast<int>(pSegment->GetOffset()),
+                                    static_cast<int>(pSegment->GetLen()), pSegment->IsFinal());
+
             delete pSegment;
         }
     }
@@ -1098,7 +1106,7 @@ CPLErr JPIPKAKDataset::GetGeoTransform( double * padfTransform )
     if( bGeoTransformValid )
     {
         memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
-    
+
         return CE_None;
     }
     else
@@ -1145,7 +1153,7 @@ const GDAL_GCP *JPIPKAKDataset::GetGCPs()
 CPLErr JPIPKAKDataset::IRasterIO( GDALRWFlag eRWFlag,
                                   int nXOff, int nYOff, int nXSize, int nYSize,
                                   void * pData, int nBufXSize, int nBufYSize,
-                                  GDALDataType eBufType, 
+                                  GDALDataType eBufType,
                                   int nBandCount, int *panBandMap,
                                   GSpacing nPixelSpace, GSpacing nLineSpace,
                                   GSpacing nBandSpace,
@@ -1157,31 +1165,33 @@ CPLErr JPIPKAKDataset::IRasterIO( GDALRWFlag eRWFlag,
 /* -------------------------------------------------------------------- */
     if( TestUseBlockIO( nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize,
                         eBufType, nBandCount, panBandMap ) )
-        return GDALPamDataset::IRasterIO( 
+        return GDALPamDataset::IRasterIO(
             eRWFlag, nXOff, nYOff, nXSize, nYSize,
-            pData, nBufXSize, nBufYSize, eBufType, 
+            pData, nBufXSize, nBufYSize, eBufType,
             nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace, psExtraArg );
 
 /* -------------------------------------------------------------------- */
 /*      Otherwise do this as a single uncached async rasterio.          */
 /* -------------------------------------------------------------------- */
-    GDALAsyncReader* ario = 
+    GDALAsyncReader* ario =
         BeginAsyncReader(nXOff, nYOff, nXSize, nYSize,
-                         pData, nBufXSize, nBufYSize, eBufType, 
-                         nBandCount, panBandMap, 
-                         nPixelSpace, nLineSpace, nBandSpace, NULL);
+                         pData, nBufXSize, nBufYSize, eBufType,
+                         nBandCount, panBandMap,
+                         static_cast<int>(nPixelSpace),
+                         static_cast<int>(nLineSpace),
+                         static_cast<int>(nBandSpace), NULL);
 
     if( ario == NULL )
         return CE_Failure;
-    
+
     GDALAsyncStatusType status;
 
-    do 
+    do
     {
         int nXBufOff,nYBufOff,nXBufSize,nYBufSize;
 
-        status = ario->GetNextUpdatedRegion(-1.0, 
-                                            &nXBufOff, &nYBufOff, 
+        status = ario->GetNextUpdatedRegion(-1.0,
+                                            &nXBufOff, &nYBufOff,
                                             &nXBufSize, &nYBufSize );
     } while (status != GARIO_ERROR && status != GARIO_COMPLETE );
 
@@ -1197,11 +1207,11 @@ CPLErr JPIPKAKDataset::IRasterIO( GDALRWFlag eRWFlag,
 /*                           TestUseBlockIO()                           */
 /************************************************************************/
 
-int 
+int
 JPIPKAKDataset::TestUseBlockIO( CPL_UNUSED int nXOff, CPL_UNUSED int nYOff,
                                 int nXSize, int nYSize,
                                 int nBufXSize, int nBufYSize,
-                                CPL_UNUSED GDALDataType eDataType, 
+                                CPL_UNUSED GDALDataType eDataType,
                                 int nBandCount, int *panBandList )
 
 {
@@ -1209,8 +1219,8 @@ JPIPKAKDataset::TestUseBlockIO( CPL_UNUSED int nXOff, CPL_UNUSED int nYOff,
 /*      Due to limitations in DirectRasterIO() we can only handle       */
 /*      it no duplicates in the band list.                              */
 /* -------------------------------------------------------------------- */
-    int i, j; 
-    
+    int i, j;
+
     for( i = 0; i < nBandCount; i++ )
     {
         for( j = i+1; j < nBandCount; j++ )
@@ -1231,7 +1241,7 @@ JPIPKAKDataset::TestUseBlockIO( CPL_UNUSED int nXOff, CPL_UNUSED int nYOff,
         bUseBlockedIO = TRUE;
 
     if( bUseBlockedIO
-        && CSLTestBoolean( CPLGetConfigOption( "GDAL_ONE_BIG_READ", "NO") ) )
+        && CPLTestBool( CPLGetConfigOption( "GDAL_ONE_BIG_READ", "NO") ) )
         bUseBlockedIO = FALSE;
 
     return bUseBlockedIO;
@@ -1241,9 +1251,9 @@ JPIPKAKDataset::TestUseBlockIO( CPL_UNUSED int nXOff, CPL_UNUSED int nYOff,
 /*                     BeginAsyncReader()                              */
 /*************************************************************************/
 
-GDALAsyncReader* 
+GDALAsyncReader*
 JPIPKAKDataset::BeginAsyncReader(int xOff, int yOff,
-                                   int xSize, int ySize, 
+                                   int xSize, int ySize,
                                    void *pBuf,
                                    int bufXSize, int bufYSize,
                                    GDALDataType bufType,
@@ -1276,7 +1286,7 @@ JPIPKAKDataset::BeginAsyncReader(int xOff, int yOff,
         nLineSpace = nPixelSpace * bufXSize;
     if( nBandSpace == 0 )
         nBandSpace = nLineSpace * bufYSize;
-    
+
 /* -------------------------------------------------------------------- */
 /*      check we have sensible values for windowing.                    */
 /* -------------------------------------------------------------------- */
@@ -1332,13 +1342,10 @@ JPIPKAKDataset::BeginAsyncReader(int xOff, int yOff,
         ario->nAppLineSpace = nLineSpace;
         ario->nAppBandSpace = nBandSpace;
 
-        ario->pBuf = VSIMalloc3(bufXSize,bufYSize,ario->nPixelSpace*nBandCount);
+        ario->pBuf = VSI_MALLOC3_VERBOSE(bufXSize,bufYSize,ario->nPixelSpace*nBandCount);
         if( ario->pBuf == NULL )
         {
             delete ario;
-            CPLError( CE_Failure, CPLE_OutOfMemory,
-                      "Failed to allocate %d byte work buffer.",
-                      bufXSize * bufYSize * ario->nPixelSpace );
             return NULL;
         }
 
@@ -1358,7 +1365,7 @@ JPIPKAKDataset::BeginAsyncReader(int xOff, int yOff,
     const char* pszLevel = CSLFetchNameValue(papszOptions, "LEVEL");
     const char* pszLayers = CSLFetchNameValue(papszOptions, "LAYERS");
     const char* pszPriority = CSLFetchNameValue(papszOptions, "PRIORITY");
-	
+
     if (pszLayers)
         ario->nQualityLayers = atoi(pszLayers);
     else
@@ -1420,8 +1427,8 @@ GDALDataset *JPIPKAKDataset::Open(GDALOpenInfo * poOpenInfo)
 {
     // test jpip and jpips, assuming jpip is using http as the transport layer
     // jpip = http, jpips = https (note SSL is allowed, but jpips is not in the ISO spec)
-    if (EQUALN(poOpenInfo->pszFilename,"jpip://", 7)
-        || EQUALN(poOpenInfo->pszFilename,"jpips://",8))
+    if (STARTS_WITH_CI(poOpenInfo->pszFilename, "jpip://")
+        || STARTS_WITH_CI(poOpenInfo->pszFilename, "jpips://"))
     {
         // perform the initial connection
         // using cpl_http for the connection
@@ -1453,31 +1460,27 @@ GDALDataset *JPIPKAKDataset::Open(GDALOpenInfo * poOpenInfo)
 }
 
 /************************************************************************/
-/*                        GDALRegister_JPIPKAK()			*/
+/*                        GDALRegister_JPIPKAK()                        */
 /************************************************************************/
 
 void GDALRegister_JPIPKAK()
 {
-    GDALDriver *poDriver;
-	
-    if (! GDAL_CHECK_VERSION("JPIPKAK driver"))
+    if( !GDAL_CHECK_VERSION( "JPIPKAK driver" ) )
         return;
 
-    if( GDALGetDriverByName( "JPIPKAK" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "JPIPKAK" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "JPIP (based on Kakadu)" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_jpipkak.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/jpp-stream" );
-
-        poDriver->pfnOpen = JPIPKAKDataset::Open;
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    if( GDALGetDriverByName( "JPIPKAK" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "JPIPKAK" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "JPIP (based on Kakadu)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_jpipkak.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/jpp-stream" );
+
+    poDriver->pfnOpen = JPIPKAKDataset::Open;
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
 
 /************************************************************************/
@@ -1518,7 +1521,7 @@ void JPIPKAKAsyncReader::Start()
     bComplete = 0;
 
     // check a thread is not already running
-    if (((bHighPriority) && (poJDS->bHighThreadRunning)) || 
+    if (((bHighPriority) && (poJDS->bHighThreadRunning)) ||
         ((!bHighPriority) && (poJDS->bLowThreadRunning)))
         CPLError(CE_Failure, CPLE_AppDefined, "JPIPKAKAsyncReader supports at most two concurrent server communication threads");
     else
@@ -1533,24 +1536,24 @@ void JPIPKAKAsyncReader::Start()
 
         // find current canvas width and height in the cache and check we don't
         // exceed this in our process request
-        kdu_dims view_dims;	
+        kdu_dims view_dims;
         kdu_coords ref_expansion;
         ref_expansion.x = 1;
         ref_expansion.y = 1;
 
         view_dims = ((JPIPKAKDataset*)poDS)->poDecompressor->
-            get_rendered_image_dims(*((JPIPKAKDataset*)poDS)->poCodestream, &channels, 
-                                    -1, nLevel, 
+            get_rendered_image_dims(*((JPIPKAKDataset*)poDS)->poCodestream, &channels,
+                                    -1, nLevel,
                                     ref_expansion );
 
         kdu_coords* view_siz = view_dims.access_size();
-		
+
         // Establish the decimation implied by our resolution level.
         int nRes = 1;
         if (nLevel > 0)
             nRes = 2 << (nLevel - 1);
 
-        // setup expansion to account for the difference between 
+        // setup expansion to account for the difference between
         // the selected level and the buffer resolution.
         exp_numerator.x = nBufXSize;
         exp_numerator.y = nBufYSize;
@@ -1586,8 +1589,8 @@ void JPIPKAKAsyncReader::Start()
 
             comps.erase(comps.length() -1);
         }
-	
-        jpipUrl.Printf("%s&type=jpp-stream&roff=%i,%i&rsiz=%i,%i&fsiz=%i,%i,closest&quality=%i&comps=%s", 
+
+        jpipUrl.Printf("%s&type=jpp-stream&roff=%i,%i&rsiz=%i,%i&fsiz=%i,%i,closest&quality=%i&comps=%s",
                        ((JPIPKAKDataset*)poDS)->osRequestUrl.c_str(),
                        rr_win.pos.x, rr_win.pos.y,
                        rr_win.size.x, rr_win.size.y,
@@ -1603,10 +1606,10 @@ void JPIPKAKAsyncReader::Start()
             poJDS->bHighThreadFinished = 0;
         else
             poJDS->bLowThreadFinished = 0;
-        
+
         //CPLDebug("JPIPKAKAsyncReader", "THREADING TURNED OFF");
         if (CPLCreateThread(JPIPWorkerFunc, pRequest) == -1)
-            CPLError(CE_Failure, CPLE_AppDefined, 
+            CPLError(CE_Failure, CPLE_AppDefined,
                      "Unable to create worker jpip  thread" );
         // run in main thread as a test
         //JPIPWorkerFunc(pRequest);
@@ -1623,7 +1626,7 @@ void JPIPKAKAsyncReader::Stop()
     bComplete = 1;
     if (poJDS->pGlobalMutex)
     {
-        if (((bHighPriority) && (!poJDS->bHighThreadFinished)) || 
+        if (((bHighPriority) && (!poJDS->bHighThreadFinished)) ||
             ((!bHighPriority) && (!poJDS->bLowThreadFinished)))
         {
             CPLDebug( "JPIPKAK", "JPIPKAKAsyncReader::Stop() requested." );
@@ -1634,7 +1637,7 @@ void JPIPKAKAsyncReader::Stop()
                 CPLAcquireMutex(poJDS->pGlobalMutex, 100.0);
                 poJDS->bHighThreadRunning = 0;
                 CPLReleaseMutex(poJDS->pGlobalMutex);
-		
+
                 while (!poJDS->bHighThreadFinished)
                     CPLSleep(0.1);
             }
@@ -1643,7 +1646,7 @@ void JPIPKAKAsyncReader::Stop()
                 CPLAcquireMutex(poJDS->pGlobalMutex, 100.0);
                 poJDS->bLowThreadRunning = 0;
                 CPLReleaseMutex(poJDS->pGlobalMutex);
-		
+
                 while (!poJDS->bLowThreadFinished)
                 {
                     CPLSleep(0.1);
@@ -1658,7 +1661,7 @@ void JPIPKAKAsyncReader::Stop()
 /*                        GetNextUpdatedRegion()                        */
 /************************************************************************/
 
-GDALAsyncStatusType 
+GDALAsyncStatusType
 JPIPKAKAsyncReader::GetNextUpdatedRegion(double dfTimeout,
                                          int* pnxbufoff,
                                          int* pnybufoff,
@@ -1689,7 +1692,7 @@ JPIPKAKAsyncReader::GetNextUpdatedRegion(double dfTimeout,
         // poll for change in cache size
         clock_t end_wait = 0;
 
-        end_wait = clock() + (int) (dfTimeout * CLOCKS_PER_SEC); 
+        end_wait = clock() + (int) (dfTimeout * CLOCKS_PER_SEC);
         while ((nSize == 0) && ((bHighPriority && poJDS->bHighThreadRunning) ||
                                 (!bHighPriority && poJDS->bLowThreadRunning)))
         {
@@ -1718,14 +1721,14 @@ JPIPKAKAsyncReader::GetNextUpdatedRegion(double dfTimeout,
         *pnxbufoff = 0;
         *pnybufoff = 0;
         *pnxbufsize = 0;
-        *pnybufsize = 0;		
+        *pnybufsize = 0;
 
         // Indicate an error if the thread finished prematurely
-        if( (bHighPriority 
-             && !poJDS->bHighThreadRunning 
+        if( (bHighPriority
+             && !poJDS->bHighThreadRunning
              && poJDS->bHighThreadFinished)
-            || (!bHighPriority 
-                && !poJDS->bLowThreadRunning 
+            || (!bHighPriority
+                && !poJDS->bLowThreadRunning
                 && poJDS->bLowThreadFinished) )
         {
             if( osErrorMsg != "" )
@@ -1734,7 +1737,7 @@ JPIPKAKAsyncReader::GetNextUpdatedRegion(double dfTimeout,
             else
                 CPLError( CE_Failure, CPLE_AppDefined,
                           "Working thread failed without complete data. (%d,%d,%d)",
-                          bHighPriority, 
+                          bHighPriority,
                           poJDS->bHighThreadRunning,
                           poJDS->bHighThreadFinished );
             poJDS->bNeedReinitialize = TRUE;
@@ -1760,7 +1763,7 @@ JPIPKAKAsyncReader::GetNextUpdatedRegion(double dfTimeout,
         poJDS->poCodestream->apply_input_restrictions( 0, 0, 0, 0, NULL );
 
         view_dims = poJDS->poDecompressor->get_rendered_image_dims(
-            *poJDS->poCodestream, &channels, 
+            *poJDS->poCodestream, &channels,
             -1, nLevel, exp_numerator, exp_denominator );
 
         double x_ratio, y_ratio;
@@ -1776,14 +1779,14 @@ JPIPKAKAsyncReader::GetNextUpdatedRegion(double dfTimeout,
 
         region.size.x = MIN(region.size.x,nBufXSize);
         region.size.y = MIN(region.size.y,nBufYSize);
-        
+
         if( region.pos.x + region.size.x > view_dims.size.x )
             region.size.x = view_dims.size.x - region.pos.x;
         if( region.pos.y + region.size.y > view_dims.size.y )
             region.size.y = view_dims.size.y - region.pos.y;
-        
+
         region.pos += view_dims.pos;
-    
+
         CPLAssert( nBytesPerPixel == 1 || nBytesPerPixel == 2  );
 
         if( poJDS->poCodestream->get_bit_depth(0) > 16 )
@@ -1799,7 +1802,7 @@ JPIPKAKAsyncReader::GetNextUpdatedRegion(double dfTimeout,
 /*      Now we process the available cached jpeg2000 data into          */
 /*      imagery.  The kdu_region_decompressor only seems to support     */
 /*      reading back one or three components at a time, we may need     */
-/*      to do severalp processing passes to get the bands we            */
+/*      to do several processing passes to get the bands we             */
 /*      want. We try to do groups of three were possible, and handle    */
 /*      the rest one band at a time.                                    */
 /* ==================================================================== */
@@ -1815,7 +1818,7 @@ JPIPKAKAsyncReader::GetNextUpdatedRegion(double dfTimeout,
 
         if( nBandCount - nBandsCompleted >= 3 )
         {
-            CPLDebug( "JPIPKAK", "process bands %d,%d,%d", 
+            CPLDebug( "JPIPKAK", "process bands %d,%d,%d",
                       panBandMap[nBandsCompleted],
                       panBandMap[nBandsCompleted+1],
                       panBandMap[nBandsCompleted+2] );
@@ -1826,7 +1829,7 @@ JPIPKAKAsyncReader::GetNextUpdatedRegion(double dfTimeout,
         }
         else
         {
-            CPLDebug( "JPIPKAK", "process band %d", 
+            CPLDebug( "JPIPKAK", "process band %d",
                       panBandMap[nBandsCompleted] );
             component_indices.push_back( panBandMap[nBandsCompleted++]-1 );
         }
@@ -1837,8 +1840,8 @@ JPIPKAKAsyncReader::GetNextUpdatedRegion(double dfTimeout,
         kdu_dims region_pass = region;
 
         poJDS->poCodestream->apply_input_restrictions(
-            component_indices.size(), &(component_indices[0]), 
-            nLevel, nQualityLayers, &region_pass, 
+            static_cast<int>(component_indices.size()), &(component_indices[0]),
+            nLevel, nQualityLayers, &region_pass,
             KDU_WANT_CODESTREAM_COMPONENTS);
 
         channels.configure(*(poJDS->poCodestream));
@@ -1848,30 +1851,30 @@ JPIPKAKAsyncReader::GetNextUpdatedRegion(double dfTimeout,
 
         kdu_dims incomplete_region = region_pass;
         kdu_coords origin = region_pass.pos;
-        
+
         int bIsDecompressing = FALSE;
-		
+
         CPLAcquireMutex(poJDS->pGlobalMutex, 100.0);
 
         try
         {
 
             bIsDecompressing = poJDS->poDecompressor->start(
-                *(poJDS->poCodestream), 
-                &channels, -1, nLevel, nQualityLayers, 
-                region_pass, exp_numerator, exp_denominator, TRUE);	
-        
+                *(poJDS->poCodestream),
+                &channels, -1, nLevel, nQualityLayers,
+                region_pass, exp_numerator, exp_denominator, TRUE);
+
             *pnxbufoff = 0;
             *pnybufoff = 0;
             *pnxbufsize = region_pass.access_size()->x;
             *pnybufsize = region_pass.access_size()->y;
-        
+
             // Setup channel buffers
             std::vector<kdu_byte*> channel_bufs;
 
             for( i=0; i < component_indices.size(); i++ )
-                channel_bufs.push_back( 
-                    ((kdu_byte *) pBuf) 
+                channel_bufs.push_back(
+                    ((kdu_byte *) pBuf)
                     + (i+nBandsCompleted-component_indices.size()) * nBandSpace );
 
             int pixel_gap = nPixelSpace / nBytesPerPixel;
@@ -1882,8 +1885,8 @@ JPIPKAKAsyncReader::GetNextUpdatedRegion(double dfTimeout,
                 if( nBytesPerPixel == 1 )
                 {
                     bIsDecompressing = poJDS->poDecompressor->
-                        process(&(channel_bufs[0]), false, 
-                                pixel_gap, origin, row_gap, 1000000, 0, 
+                        process(&(channel_bufs[0]), false,
+                                pixel_gap, origin, row_gap, 1000000, 0,
                                 incomplete_region, region_pass,
                                 0, false );
                 }
@@ -1891,14 +1894,14 @@ JPIPKAKAsyncReader::GetNextUpdatedRegion(double dfTimeout,
                 {
                     bIsDecompressing = poJDS->poDecompressor->
                         process((kdu_uint16**) &(channel_bufs[0]), false,
-                                pixel_gap, origin, row_gap, 1000000, 0, 
+                                pixel_gap, origin, row_gap, 1000000, 0,
                                 incomplete_region, region_pass,
                                 nPrecision, false );
                 }
-            
+
                 CPLDebug( "JPIPKAK",
                           "processed=%d,%d %dx%d   - incomplete=%d,%d %dx%d",
-                          region_pass.pos.x, region_pass.pos.y, 
+                          region_pass.pos.x, region_pass.pos.y,
                           region_pass.size.x, region_pass.size.y,
                           incomplete_region.pos.x, incomplete_region.pos.y,
                           incomplete_region.size.x, incomplete_region.size.y );
@@ -1931,7 +1934,7 @@ JPIPKAKAsyncReader::GetNextUpdatedRegion(double dfTimeout,
         int iY, iBand;
         GByte *pabySrc = (GByte *) pBuf;
         GByte *pabyDst = (GByte *) pAppBuf;
-        
+
         for( iBand = 0; iBand < nBandCount; iBand++ )
         {
             for( iY = 0; iY < nBufYSize; iY++ )
@@ -1939,7 +1942,7 @@ JPIPKAKAsyncReader::GetNextUpdatedRegion(double dfTimeout,
                 GDALCopyWords( pabySrc + nLineSpace * iY + nBandSpace * iBand,
                                poJDS->eDT, nPixelSpace,
                                pabyDst + nAppLineSpace*iY + nAppBandSpace*iBand,
-                               eBufType, nAppPixelSpace, 
+                               eBufType, nAppPixelSpace,
                                nBufXSize );
             }
         }
@@ -1959,18 +1962,18 @@ JPIPKAKAsyncReader::GetNextUpdatedRegion(double dfTimeout,
         const long x = poJDS->nLowThreadByteCount - nDataRead;
         size = x;
     }
-    
+
     if ((bComplete) && (nSize == size))
         result = GARIO_COMPLETE;
     else
         result = GARIO_UPDATE;
-    
+
     nDataRead += nSize;
 
     if( result == GARIO_ERROR )
         poJDS->bNeedReinitialize = TRUE;
-    
-    return result;	
+
+    return result;
 }
 
 /************************************************************************/
@@ -2006,9 +2009,9 @@ static void JPIPWorkerFunc(void *req)
     int nMinimumTransmissionLength = 2000;
 
     JPIPRequest *pRequest = (JPIPRequest *)req;
-    JPIPKAKDataset *poJDS = 
+    JPIPKAKDataset *poJDS =
         (JPIPKAKDataset*)(pRequest->poARIO->GetGDALDataset());
-	
+
     int bPriority = pRequest->bPriority;
 
     CPLAcquireMutex(poJDS->pGlobalMutex, 100.0);
@@ -2034,13 +2037,13 @@ static void JPIPWorkerFunc(void *req)
 
     osPersistent.Printf( "PERSISTENT=JPIPKAK:%p", poJDS );
 
-    char *apszOptions[] = { 
+    char *apszOptions[] = {
         (char *) osHeaders.c_str(),
         (char *) osPersistent.c_str(),
-        NULL 
+        NULL
     };
 
-    while (TRUE)
+    while( true )
     {
         // modulate the len= parameter to use the currently available bandwidth
         long nStart = clock();
@@ -2072,7 +2075,7 @@ static void JPIPWorkerFunc(void *req)
         if( psResult->pszContentType != NULL )
             CPLDebug( "JPIPKAK", "Content-type: %s", psResult->pszContentType );
 
-        if( psResult->pszContentType != NULL 
+        if( psResult->pszContentType != NULL
             && strstr(psResult->pszContentType,"html") != NULL )
         {
             CPLDebug( "JPIPKAK", "%s", psResult->pabyData );
@@ -2080,10 +2083,10 @@ static void JPIPWorkerFunc(void *req)
 
         int bytes = psResult->nDataLen;
         long nEnd = clock();
-		
+
         if ((nEnd - nStart) > 0)
             nCurrentTransmissionLength = (int) MAX(bytes / ((1.0 * (nEnd - nStart)) / CLOCKS_PER_SEC), nMinimumTransmissionLength);
-		
+
 
         CPLAcquireMutex(poJDS->pGlobalMutex, 100.0);
 
@@ -2095,7 +2098,7 @@ static void JPIPWorkerFunc(void *req)
             poJDS->nLowThreadByteCount += psResult->nDataLen;
 
         pRequest->poARIO->SetComplete(bComplete);
-		
+
         CPLReleaseMutex(poJDS->pGlobalMutex);
         CPLHTTPDestroyResult(psResult);
 
@@ -2123,4 +2126,3 @@ static void JPIPWorkerFunc(void *req)
     // end of thread
     delete pRequest;
 }
-
diff --git a/frmts/jpipkak/jpipkakdataset.h b/frmts/jpipkak/jpipkakdataset.h
index 45117a6..0ee7f83 100644
--- a/frmts/jpipkak/jpipkakdataset.h
+++ b/frmts/jpipkak/jpipkakdataset.h
@@ -2,22 +2,22 @@
  * $Id: jpipkakdataset.cpp 2008-10-01 nbarker $
  *
  * Project:  jpip read driver
- * Purpose:  GDAL bindings for JPIP.  
+ * Purpose:  GDAL bindings for JPIP.
  * Author:   Norman Barker, ITT VIS, norman.barker at gmail.com
  *
  ******************************************************************************
  * ITT Visual Information Systems grants you use of this code, under the following license:
- * 
- * Copyright (c) 2000-2007, ITT Visual Information Solutions 
+ *
+ * Copyright (c) 2000-2007, ITT Visual Information Solutions
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * to deal in the Software without restriction, including without limitation
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions: 
+ * Software is furnished to do so, subject to the following conditions:
  * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software. 
+ * in all copies or substantial portions of the Software.
 
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
@@ -36,9 +36,7 @@
 #include "cpl_vsi.h"
 #include "cpl_multiproc.h"
 
-#include "kdu_cache.h"
-#include "kdu_region_decompressor.h"
-#include "kdu_file_io.h"
+#include "jpipkak_headers.h"
 
 #include <time.h>
 
@@ -69,25 +67,25 @@ private:
     int bIsFinal;
     int bIsEOR;
 public:
-    int GetId(){return nId;}
-    int GetAux(){return nAux;}
-    int GetClassId(){return nClassId;}
-    int GetCodestreamIdx(){return nCodestream;}
-    int GetOffset(){return nOffset;}
-    int GetLen(){return nLen;}
+    long GetId(){return nId;}
+    long GetAux(){return nAux;}
+    long GetClassId(){return nClassId;}
+    long GetCodestreamIdx(){return nCodestream;}
+    long GetOffset(){return nOffset;}
+    long GetLen(){return nLen;}
     GByte* GetData(){return pabyData;}
     int IsFinal(){return bIsFinal;}
     int IsEOR(){return bIsEOR;}
 
-    void SetId(long nId){this->nId = nId;}
-    void SetAux(long nAux){this->nAux = nAux;}
-    void SetClassId(long nClassId){this->nClassId = nClassId;}
-    void SetCodestreamIdx(long nCodestream){this->nCodestream = nCodestream;}
-    void SetOffset(long nOffset){this->nOffset = nOffset;}
-    void SetLen(long nLen){this->nLen = nLen;}
-    void SetData(GByte* pabyData){this->pabyData = pabyData;}
-    void SetFinal(int bIsFinal){this->bIsFinal = bIsFinal;}
-    void SetEOR(int bIsEOR){this->bIsEOR = bIsEOR;}
+    void SetId(long nIdIn){this->nId = nIdIn;}
+    void SetAux(long nAuxIn){this->nAux = nAuxIn;}
+    void SetClassId(long nClassIdIn){this->nClassId = nClassIdIn;}
+    void SetCodestreamIdx(long nCodestreamIn){this->nCodestream = nCodestreamIn;}
+    void SetOffset(long nOffsetIn){this->nOffset = nOffsetIn;}
+    void SetLen(long nLenIn){this->nLen = nLenIn;}
+    void SetData(GByte* pabyDataIn){this->pabyData = pabyDataIn;}
+    void SetFinal(int bIsFinalIn){this->bIsFinal = bIsFinalIn;}
+    void SetEOR(int bIsEORIn){this->bIsEOR = bIsEORIn;}
     JPIPDataSegment();
     ~JPIPDataSegment();
 };
@@ -102,7 +100,6 @@ class JPIPKAKDataset: public GDALPamDataset
 private:
     int       bNeedReinitialize;
     CPLString osRequestUrl;
-    char* pszTid;
     char* pszPath;
     char* pszCid;
     char* pszProjection;
@@ -141,13 +138,13 @@ private:
     int KakaduClassId(int nClassId);
 
     CPLMutex *pGlobalMutex;
- 
+
     // support two communication threads to the server, a main and an overview thread
     volatile int bHighThreadRunning;
     volatile int bLowThreadRunning;
     volatile int bHighThreadFinished;
     volatile int bLowThreadFinished;
-    
+
     // transmission counts
     volatile long nHighThreadByteCount;
     volatile long nLowThreadByteCount;
@@ -158,7 +155,7 @@ public:
 
     // progressive methods
     virtual GDALAsyncReader* BeginAsyncReader(int xOff, int yOff,
-                                              int xSize, int ySize, 
+                                              int xSize, int ySize,
                                               void *pBuf,
                                               int bufXSize, int bufYSize,
                                               GDALDataType bufType,
@@ -175,7 +172,7 @@ public:
     int ReadFromInput(GByte* pabyData, int nLen, int& bError );
 
     int TestUseBlockIO( int nXOff, int nYOff, int nXSize, int nYSize,
-                        int nBufXSize, int nBufYSize, GDALDataType eDataType, 
+                        int nBufXSize, int nBufYSize, GDALDataType eDataType,
                         int nBandCount, int *panBandList );
 
     //gdaldataset methods
@@ -187,7 +184,7 @@ public:
     virtual CPLErr IRasterIO( GDALRWFlag eRWFlag,
                               int nXOff, int nYOff, int nXSize, int nYSize,
                               void * pData, int nBufXSize, int nBufYSize,
-                              GDALDataType eBufType, 
+                              GDALDataType eBufType,
                               int nBandCount, int *panBandMap,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
                               GSpacing nBandSpace,
@@ -201,7 +198,7 @@ public:
     static const GByte PRECINCT_DATA_BIN_CLASS = 0;
     static const GByte TILE_HEADER_DATA_BIN_CLASS = 2;
     static const GByte TILE_DATA_BIN_CLASS = 4;
-	
+
     friend class JPIPKAKAsyncReader;
     friend class JPIPKAKRasterBand;
     friend void JPIPWorkerFunc(void*);
@@ -219,9 +216,9 @@ class JPIPKAKRasterBand : public GDALPamRasterBand
 
     JPIPKAKDataset *poBaseDS;
 
-    int         nDiscardLevels; 
+    int         nDiscardLevels;
 
-    kdu_dims 	band_dims; 
+    kdu_dims 	band_dims;
 
     int		nOverviewCount;
     JPIPKAKRasterBand **papoOverviewBand;
@@ -236,7 +233,7 @@ public:
     JPIPKAKRasterBand( int, int, kdu_codestream *, int,
                        JPIPKAKDataset * );
     ~JPIPKAKRasterBand();
-    
+
     virtual CPLErr IReadBlock( int, int, void * );
     virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
                               void *, int, int, GDALDataType,
diff --git a/frmts/kea/GNUmakefile b/frmts/kea/GNUmakefile
index e63bc98..b4afb5d 100644
--- a/frmts/kea/GNUmakefile
+++ b/frmts/kea/GNUmakefile
@@ -3,7 +3,7 @@ include ../../GDALmake.opt
 
 OBJ	=	keaband.o keacopy.o keadataset.o keadriver.o keamaskband.o keaoverview.o kearat.o
 
-CPPFLAGS	:=	 $(KEA_INC) $(CPPFLAGS)
+CPPFLAGS	:=	 $(KEA_INC) $(CPPFLAGS) -DDO_NOT_USE_DEBUG_BOOL
 
 default:	$(OBJ:.o=.$(OBJ_EXT))
 
diff --git a/frmts/kea/frmt_kea.html b/frmts/kea/frmt_kea.html
index 287a86c..9e098e9 100644
--- a/frmts/kea/frmt_kea.html
+++ b/frmts/kea/frmt_kea.html
@@ -25,7 +25,7 @@ Landcare Research, New Zealand, and the wider community.<p>
 <li>Affine geotransform, WKT projection, GCP</li>
 <li>Metadata at dataset and band level</li>
 <li>Per-band description</li>
-<li>Per-band nodata and color interpration</li>
+<li>Per-band nodata and color interpretation</li>
 <li>Per-band color table</li>
 <li>Per-band RAT (Raster Attribute Table) of arbitrary size</li>
 <li>Internal overviews and mask bands</li>
diff --git a/frmts/kea/keaband.cpp b/frmts/kea/keaband.cpp
index 287b2ca..c2b4024 100644
--- a/frmts/kea/keaband.cpp
+++ b/frmts/kea/keaband.cpp
@@ -1,5 +1,5 @@
 /*
- * $Id: keaband.cpp 28011 2014-11-26 13:47:09Z rouault $
+ * $Id: keaband.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *  keaband.cpp
  *
  *  Created by Pete Bunting on 01/08/2012.
@@ -7,23 +7,23 @@
  *
  *  This file is part of LibKEA.
  *
- *  Permission is hereby granted, free of charge, to any person 
- *  obtaining a copy of this software and associated documentation 
- *  files (the "Software"), to deal in the Software without restriction, 
- *  including without limitation the rights to use, copy, modify, 
- *  merge, publish, distribute, sublicense, and/or sell copies of the 
- *  Software, and to permit persons to whom the Software is furnished 
+ *  Permission is hereby granted, free of charge, to any person
+ *  obtaining a copy of this software and associated documentation
+ *  files (the "Software"), to deal in the Software without restriction,
+ *  including without limitation the rights to use, copy, modify,
+ *  merge, publish, distribute, sublicense, and/or sell copies of the
+ *  Software, and to permit persons to whom the Software is furnished
  *  to do so, subject to the following conditions:
  *
- *  The above copyright notice and this permission notice shall be 
+ *  The above copyright notice and this permission notice shall be
  *  included in all copies or substantial portions of the Software.
  *
- *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
- *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
- *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
- *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 
- *  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
- *  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ *  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
  */
@@ -34,7 +34,6 @@
 #include "kearat.h"
 
 #include "gdal_rat.h"
-#include "libkea/KEAAttributeTable.h"
 
 #include <map>
 #include <vector>
@@ -42,7 +41,7 @@
 #include <limits.h>
 
 // constructor
-KEARasterBand::KEARasterBand( KEADataset *pDataset, int nSrcBand, GDALAccess eAccess, kealib::KEAImageIO *pImageIO, int *pRefCount )
+KEARasterBand::KEARasterBand( KEADataset *pDataset, int nSrcBand, GDALAccess eAccessIn, kealib::KEAImageIO *pImageIO, int *pRefCount )
 {
     this->poDS = pDataset; // our pointer onto the dataset
     this->nBand = nSrcBand; // this is the band we are
@@ -52,11 +51,12 @@ KEARasterBand::KEARasterBand( KEADataset *pDataset, int nSrcBand, GDALAccess eAc
     this->nBlockYSize = pImageIO->getImageBlockSize(nSrcBand);
     this->nRasterXSize = this->poDS->GetRasterXSize();          // ask the dataset for the total image size
     this->nRasterYSize = this->poDS->GetRasterYSize();
-    this->eAccess = eAccess;
+    this->eAccess = eAccessIn;
 
     if( pImageIO->attributeTablePresent(nSrcBand) )
     {
-        this->m_nAttributeChunkSize = pImageIO->getAttributeTableChunkSize(nSrcBand);
+        this->m_nAttributeChunkSize
+            = pImageIO->getAttributeTableChunkSize(nSrcBand);
     }
     else
     {
@@ -69,7 +69,7 @@ KEARasterBand::KEARasterBand( KEADataset *pDataset, int nSrcBand, GDALAccess eAc
     // increment the refcount as we now have a reference to imageio
     (*this->m_pnRefCount)++;
 
-    // initialise overview variables
+    // Initialize overview variables
     m_nOverviews = 0;
     m_panOverviewBands = NULL;
 
@@ -83,7 +83,7 @@ KEARasterBand::KEARasterBand( KEADataset *pDataset, int nSrcBand, GDALAccess eAc
     this->m_pAttributeTable = NULL;  // no RAT yet
     this->m_pColorTable = NULL;     // no color table yet
 
-    // initialise the metadata as a CPLStringList
+    // Initialize the metadata as a CPLStringList.
     m_papszMetadataList = NULL;
     this->UpdateMetadataList();
 }
@@ -117,7 +117,7 @@ KEARasterBand::~KEARasterBand()
         {
             m_pImageIO->close();
         }
-        catch (kealib::KEAIOException &e)
+        catch (const kealib::KEAIOException &)
         {
         }
         delete m_pImageIO;
@@ -137,7 +137,7 @@ void KEARasterBand::UpdateMetadataList()
         // add to our list
         m_papszMetadataList = CSLSetNameValue(m_papszMetadataList, iterMetaData->first.c_str(), iterMetaData->second.c_str());
     }
-    // we have a pseudo metadata item that tells if we are thematic 
+    // we have a pseudo metadata item that tells if we are thematic
     // or continuous like the HFA driver
     if( this->m_pImageIO->getImageBandLayerType(this->nBand) == kealib::kea_continuous )
     {
@@ -205,11 +205,11 @@ CPLErr KEARasterBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage
         }
         this->m_pImageIO->readImageBlock2Band( this->nBand, pImage, this->nBlockXSize * nBlockXOff,
                                             this->nBlockYSize * nBlockYOff,
-                                            nxsize, nysize, this->nBlockXSize, this->nBlockYSize, 
+                                            nxsize, nysize, this->nBlockXSize, this->nBlockYSize,
                                             this->m_eKEADataType );
         return CE_None;
     }
-    catch (kealib::KEAIOException &e)
+    catch (const kealib::KEAIOException &e)
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                 "Failed to read file: %s", e.what() );
@@ -243,7 +243,7 @@ CPLErr KEARasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff, void * pImage
                                             this->m_eKEADataType );
         return CE_None;
     }
-    catch (kealib::KEAIOException &e)
+    catch (const kealib::KEAIOException &e)
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                 "Failed to write file: %s", e.what() );
@@ -258,7 +258,7 @@ void KEARasterBand::SetDescription(const char *pszDescription)
         this->m_pImageIO->setImageBandDescription(this->nBand, pszDescription);
         GDALPamRasterBand::SetDescription(pszDescription);
     }
-    catch (kealib::KEAIOException &e)
+    catch (const kealib::KEAIOException &)
     {
         // ignore?
     }
@@ -272,7 +272,7 @@ CPLErr KEARasterBand::SetMetadataItem(const char *pszName, const char *pszValue,
         return CE_Failure;
     try
     {
-        // if it is LAYER_TYPE handle it seperately
+        // if it is LAYER_TYPE handle it separately
         if( EQUAL( pszName, "LAYER_TYPE" ) )
         {
             if( EQUAL( pszValue, "athematic" ) )
@@ -293,7 +293,7 @@ CPLErr KEARasterBand::SetMetadataItem(const char *pszName, const char *pszValue,
         m_papszMetadataList = CSLSetNameValue( m_papszMetadataList, pszName, pszValue );
         return CE_None;
     }
-    catch (kealib::KEAIOException &e)
+    catch (const kealib::KEAIOException &)
     {
         return CE_Failure;
     }
@@ -305,7 +305,7 @@ const char *KEARasterBand::GetMetadataItem (const char *pszName, const char *psz
     // only deal with 'default' domain - no geolocation etc
     if( ( pszDomain != NULL ) && ( *pszDomain != '\0' ) )
         return NULL;
-    // get it out of the CSLStringList so we can be sure it is persistant
+    // get it out of the CSLStringList so we can be sure it is persistent
     return CSLFetchNameValue(m_papszMetadataList, pszName);
 }
 
@@ -316,7 +316,7 @@ char **KEARasterBand::GetMetadata(const char *pszDomain)
     if( ( pszDomain != NULL ) && ( *pszDomain != '\0' ) )
         return NULL;
     // conveniently we already have it in this format
-    return m_papszMetadataList; 
+    return m_papszMetadataList;
 }
 
 // set the metdata as a CSLStringList
@@ -339,7 +339,7 @@ CPLErr KEARasterBand::SetMetadata(char **papszMetadata, const char *pszDomain)
                 pszValue = "";
             if( pszName != NULL )
             {
-                // it is LAYER_TYPE? if so handle seperately
+                // it is LAYER_TYPE? if so handle separately
                 if( EQUAL( pszName, "LAYER_TYPE" ) )
                 {
                     if( EQUAL( pszValue, "athematic" ) )
@@ -361,7 +361,7 @@ CPLErr KEARasterBand::SetMetadata(char **papszMetadata, const char *pszDomain)
             nIndex++;
         }
     }
-    catch (kealib::KEAIOException &e)
+    catch (const kealib::KEAIOException &)
     {
         return CE_Failure;
     }
@@ -384,7 +384,7 @@ double KEARasterBand::GetNoDataValue(int *pbSuccess)
 
         return dVal;
     }
-    catch (kealib::KEAIOException &e)
+    catch (const kealib::KEAIOException &)
     {
         if( pbSuccess != NULL )
             *pbSuccess = 0;
@@ -432,7 +432,20 @@ CPLErr KEARasterBand::SetNoDataValue(double dfNoData)
         }
         return CE_None;
     }
-    catch (kealib::KEAIOException &e)
+    catch (const kealib::KEAIOException &)
+    {
+        return CE_Failure;
+    }
+}
+
+CPLErr KEARasterBand::DeleteNoDataValue()
+{
+    try
+    {
+        m_pImageIO->undefineNoDataValue(this->nBand);
+        return CE_None;
+    }
+    catch (const kealib::KEAIOException &)
     {
         return CE_Failure;
     }
@@ -448,7 +461,7 @@ GDALRasterAttributeTable *KEARasterBand::GetDefaultRAT()
             kealib::KEAAttributeTable *pKEATable = this->m_pImageIO->getAttributeTable(kealib::kea_att_file, this->nBand);
             this->m_pAttributeTable = new KEARasterAttributeTable(pKEATable);
         }
-        catch(kealib::KEAException &e)
+        catch(const kealib::KEAException &e)
         {
             CPLError( CE_Failure, CPLE_AppDefined, "Failed to read attributes: %s", e.what() );
         }
@@ -502,11 +515,9 @@ CPLErr KEARasterBand::SetDefaultRAT(const GDALRasterAttributeTable *poRAT)
             // ok now copy data
             if( eFieldType == GFT_Integer )
             {
-                int *panIntData = (int*)VSIMalloc2(numRows, sizeof(int));
+                int *panIntData = (int*)VSI_MALLOC2_VERBOSE(numRows, sizeof(int));
                 if( panIntData == NULL )
                 {
-                    CPLError( CE_Failure, CPLE_OutOfMemory,
-                        "Memory Allocation failed in KEARasterAttributeTable::SetDefaultRAT");
                     return CE_Failure;
                 }
 
@@ -518,11 +529,9 @@ CPLErr KEARasterBand::SetDefaultRAT(const GDALRasterAttributeTable *poRAT)
             }
             else if( eFieldType == GFT_Real )
             {
-                double *padfFloatData = (double*)VSIMalloc2(numRows, sizeof(double));
+                double *padfFloatData = (double*)VSI_MALLOC2_VERBOSE(numRows, sizeof(double));
                 if( padfFloatData == NULL )
                 {
-                    CPLError( CE_Failure, CPLE_OutOfMemory,
-                        "Memory Allocation failed in KEARasterAttributeTable::SetDefaultRAT");
                     return CE_Failure;
                 }
 
@@ -534,11 +543,9 @@ CPLErr KEARasterBand::SetDefaultRAT(const GDALRasterAttributeTable *poRAT)
             }
             else
             {
-                char **papszStringData = (char**)VSIMalloc2(numRows, sizeof(char*));
+                char **papszStringData = (char**)VSI_MALLOC2_VERBOSE(numRows, sizeof(char*));
                 if( papszStringData == NULL )
                 {
-                    CPLError( CE_Failure, CPLE_OutOfMemory,
-                        "Memory Allocation failed in KEARasterAttributeTable::SetDefaultRAT");
                     return CE_Failure;
                 }
 
@@ -553,7 +560,7 @@ CPLErr KEARasterBand::SetDefaultRAT(const GDALRasterAttributeTable *poRAT)
             }
         }
     }
-    catch(kealib::KEAException &e)
+    catch(const kealib::KEAException &e)
     {
         CPLError( CE_Failure, CPLE_AppDefined, "Failed to write attributes: %s", e.what() );
         return CE_Failure;
@@ -599,15 +606,15 @@ GDALColorTable *KEARasterBand::GetColorTable()
                 {
                     // maybe could be more efficient using ValuesIO
                     GDALColorEntry colorEntry;
-                    colorEntry.c1 = pKEATable->GetValueAsInt(nRowIndex, nRedIdx);
-                    colorEntry.c2 = pKEATable->GetValueAsInt(nRowIndex, nGreenIdx);
-                    colorEntry.c3 = pKEATable->GetValueAsInt(nRowIndex, nBlueIdx);
-                    colorEntry.c4 = pKEATable->GetValueAsInt(nRowIndex, nAlphaIdx);
+                    colorEntry.c1 = static_cast<short>(pKEATable->GetValueAsInt(nRowIndex, nRedIdx));
+                    colorEntry.c2 = static_cast<short>(pKEATable->GetValueAsInt(nRowIndex, nGreenIdx));
+                    colorEntry.c3 = static_cast<short>(pKEATable->GetValueAsInt(nRowIndex, nBlueIdx));
+                    colorEntry.c4 = static_cast<short>(pKEATable->GetValueAsInt(nRowIndex, nAlphaIdx));
                     this->m_pColorTable->SetColorEntry(nRowIndex, &colorEntry);
                 }
             }
         }
-        catch(kealib::KEAException &e)
+        catch(const kealib::KEAException &e)
         {
             CPLError( CE_Failure, CPLE_AppDefined, "Failed to read color table: %s", e.what() );
             delete this->m_pColorTable;
@@ -705,7 +712,7 @@ CPLErr KEARasterBand::SetColorTable(GDALColorTable *poCT)
         delete this->m_pColorTable;
         this->m_pColorTable = NULL;
     }
-    catch(kealib::KEAException &e)
+    catch(const kealib::KEAException &e)
     {
         CPLError( CE_Failure, CPLE_AppDefined, "Failed to write color table: %s", e.what() );
         return CE_Failure;
@@ -720,11 +727,11 @@ GDALColorInterp KEARasterBand::GetColorInterpretation()
     {
         ekeainterp = this->m_pImageIO->getImageBandClrInterp(this->nBand);
     }
-    catch(kealib::KEAException &e)
+    catch(const kealib::KEAException &)
     {
         return GCI_GrayIndex;
     }
-        
+
     GDALColorInterp egdalinterp;
     switch(ekeainterp)
     {
@@ -781,7 +788,7 @@ GDALColorInterp KEARasterBand::GetColorInterpretation()
             egdalinterp = GCI_GrayIndex;
             break;
     }
-        
+
     return egdalinterp;
 }
 
@@ -847,9 +854,9 @@ CPLErr KEARasterBand::SetColorInterpretation(GDALColorInterp egdalinterp)
     {
         this->m_pImageIO->setImageBandClrInterp(this->nBand, ekeainterp);
     }
-    catch(kealib::KEAException &e)
+    catch(const kealib::KEAException &)
     {
-        // do nothing? The docs say CE_Failure only if unsupporte by format
+        // Do nothing? The docs say CE_Failure only if unsupported by format.
     }
     return CE_None;
 }
@@ -877,7 +884,7 @@ void KEARasterBand::readExistingOverviews()
     m_nOverviews = this->m_pImageIO->getNumOfOverviews(this->nBand);
     m_panOverviewBands = (KEAOverview**)CPLMalloc(sizeof(KEAOverview*) * m_nOverviews);
 
-    uint64_t nXSize, nYSize;    
+    uint64_t nXSize, nYSize;
     for( int nCount = 0; nCount < m_nOverviews; nCount++ )
     {
         this->m_pImageIO->getOverviewSize(this->nBand, nCount + 1, &nXSize, &nYSize);
@@ -905,7 +912,7 @@ GDALRasterBand* KEARasterBand::GetOverview(int nOverview)
     }
 }
 
-CPLErr KEARasterBand::CreateMaskBand(CPL_UNUSED int nFlags)
+CPLErr KEARasterBand::CreateMaskBand(int)
 {
     if( m_bMaskBandOwned )
         delete m_pMaskBand;
@@ -914,7 +921,7 @@ CPLErr KEARasterBand::CreateMaskBand(CPL_UNUSED int nFlags)
     {
         this->m_pImageIO->createMask(this->nBand);
     }
-    catch(kealib::KEAException &e)
+    catch(const kealib::KEAException &e)
     {
         CPLError( CE_Failure, CPLE_AppDefined, "Failed to create mask band: %s", e.what());
         return CE_Failure;
@@ -940,7 +947,7 @@ GDALRasterBand* KEARasterBand::GetMaskBand()
                 m_pMaskBand = GDALPamRasterBand::GetMaskBand();
             }
         }
-        catch(kealib::KEAException &e)
+        catch(const kealib::KEAException &)
         {
             // do nothing?
         }
@@ -960,7 +967,7 @@ int KEARasterBand::GetMaskFlags()
             return GDALPamRasterBand::GetMaskFlags();
         }
     }
-    catch(kealib::KEAException &e)
+    catch(const kealib::KEAException &)
     {
         // do nothing?
     }
@@ -968,4 +975,3 @@ int KEARasterBand::GetMaskFlags()
     // none of the other flags seem to make sense...
     return 0;
 }
-
diff --git a/frmts/kea/keaband.h b/frmts/kea/keaband.h
index 24b556e..430cfeb 100644
--- a/frmts/kea/keaband.h
+++ b/frmts/kea/keaband.h
@@ -1,5 +1,5 @@
 /*
- * $Id: keaband.h 29258 2015-05-28 22:08:43Z rouault $
+ * $Id: keaband.h 33720 2016-03-15 00:39:53Z goatbar $
  *  keaband.h
  *
  *  Created by Pete Bunting on 01/08/2012.
@@ -7,23 +7,23 @@
  *
  *  This file is part of LibKEA.
  *
- *  Permission is hereby granted, free of charge, to any person 
- *  obtaining a copy of this software and associated documentation 
- *  files (the "Software"), to deal in the Software without restriction, 
- *  including without limitation the rights to use, copy, modify, 
- *  merge, publish, distribute, sublicense, and/or sell copies of the 
- *  Software, and to permit persons to whom the Software is furnished 
+ *  Permission is hereby granted, free of charge, to any person
+ *  obtaining a copy of this software and associated documentation
+ *  files (the "Software"), to deal in the Software without restriction,
+ *  including without limitation the rights to use, copy, modify,
+ *  merge, publish, distribute, sublicense, and/or sell copies of the
+ *  Software, and to permit persons to whom the Software is furnished
  *  to do so, subject to the following conditions:
  *
- *  The above copyright notice and this permission notice shall be 
+ *  The above copyright notice and this permission notice shall be
  *  included in all copies or substantial portions of the Software.
  *
- *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
- *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
- *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
- *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 
- *  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
- *  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ *  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
  */
@@ -32,9 +32,6 @@
 #define KEABAND_H
 
 #include "gdal_pam.h"
-#if defined(USE_GCC_VISIBILITY_FLAG) && !defined(DllExport)
-#define DllExport CPL_DLL
-#endif
 #include "keadataset.h"
 
 class KEAOverview;
@@ -78,6 +75,7 @@ public:
     // virtual methods for the no data value
     double GetNoDataValue(int *pbSuccess=NULL);
     CPLErr SetNoDataValue(double dfNoData);
+    virtual CPLErr DeleteNoDataValue();
 
     // virtual methods for RATs
     GDALRasterAttributeTable *GetDefaultRAT();
@@ -91,7 +89,7 @@ public:
     GDALColorInterp GetColorInterpretation();
     CPLErr SetColorInterpretation(GDALColorInterp gdalinterp);
 
-    // virtual mthods for band masks
+    // Virtual methods for band masks.
     CPLErr CreateMaskBand(int nFlags);
     GDALRasterBand* GetMaskBand();
     int GetMaskFlags();
diff --git a/frmts/kea/keacopy.cpp b/frmts/kea/keacopy.cpp
index 8301765..9fca903 100644
--- a/frmts/kea/keacopy.cpp
+++ b/frmts/kea/keacopy.cpp
@@ -1,5 +1,5 @@
 /*
- * $Id: keacopy.cpp 28437 2015-02-07 15:50:57Z rouault $
+ * $Id: keacopy.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *  keacopy.cpp
  *
  *  Created by Pete Bunting on 01/08/2012.
@@ -7,23 +7,23 @@
  *
  *  This file is part of LibKEA.
  *
- *  Permission is hereby granted, free of charge, to any person 
- *  obtaining a copy of this software and associated documentation 
- *  files (the "Software"), to deal in the Software without restriction, 
- *  including without limitation the rights to use, copy, modify, 
- *  merge, publish, distribute, sublicense, and/or sell copies of the 
- *  Software, and to permit persons to whom the Software is furnished 
+ *  Permission is hereby granted, free of charge, to any person
+ *  obtaining a copy of this software and associated documentation
+ *  files (the "Software"), to deal in the Software without restriction,
+ *  including without limitation the rights to use, copy, modify,
+ *  merge, publish, distribute, sublicense, and/or sell copies of the
+ *  Software, and to permit persons to whom the Software is furnished
  *  to do so, subject to the following conditions:
  *
- *  The above copyright notice and this permission notice shall be 
+ *  The above copyright notice and this permission notice shall be
  *  included in all copies or substantial portions of the Software.
  *
- *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
- *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
- *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
- *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 
- *  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
- *  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ *  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
  */
@@ -31,9 +31,8 @@
 #include <cmath>
 #include "gdal_priv.h"
 #include "gdal_rat.h"
-#include "libkea/KEAImageIO.h"
-#include "libkea/KEAAttributeTable.h"
-#include "libkea/KEAAttributeTableInMem.h"
+
+#include "keacopy.h"
 
 // Support functions for CreateCopy()
 
@@ -59,11 +58,11 @@ bool KEACopyRasterData( GDALRasterBand *pBand, kealib::KEAImageIO *pImageIO, int
     void *pData = VSIMalloc3( nPixelSize, nBlockSize, nBlockSize);
     if( pData == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, "Unable to allocate memory" );        
+        CPLError( CE_Failure, CPLE_AppDefined, "Unable to allocate memory" );
         return false;
     }
     // for progress
-    int nTotalBlocks = std::ceil( (double)nXSize / (double)nBlockSize ) * std::ceil( (double)nYSize / (double)nBlockSize );
+    int nTotalBlocks = static_cast<int>(std::ceil( (double)nXSize / (double)nBlockSize ) * std::ceil( (double)nYSize / (double)nBlockSize ));
     int nBlocksComplete = 0;
     double dLastFraction = -1;
     // go through the image
@@ -83,9 +82,12 @@ bool KEACopyRasterData( GDALRasterBand *pBand, kealib::KEAImageIO *pImageIO, int
                 nxsize -= (nxtotalsize - nXSize);
 
             // read in from GDAL
-            if( pBand->RasterIO( GF_Read, nX, nY, nxsize, nysize, pData, nxsize, nysize, eGDALType, nPixelSize, nPixelSize * nBlockSize, NULL) != CE_None )
+            if( pBand->RasterIO( GF_Read, nX, nY, nxsize, nysize, pData,
+                                 nxsize, nysize, eGDALType, nPixelSize,
+                                 nPixelSize * nBlockSize, NULL) != CE_None )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, "Unable to read blcok at %d %d\n", nX, nY );
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Unable to read block at %d %d\n", nX, nY );
                 return false;
             }
             // write out to KEA
@@ -111,7 +113,7 @@ bool KEACopyRasterData( GDALRasterBand *pBand, kealib::KEAImageIO *pImageIO, int
             }
         }
     }
-    
+
     CPLFree( pData );
     return true;
 }
@@ -137,7 +139,7 @@ static void KEACopyRAT(GDALRasterBand *pBand, kealib::KEAImageIO *pImageIO, int
         int blueIdx = -1;
         bool alphaDef = false;
         int alphaIdx = -1;*/
-        
+
         int numCols = gdalAtt->GetColumnCount();
         std::vector<kealib::KEAATTField*> *fields = new std::vector<kealib::KEAATTField*>();
         kealib::KEAATTField *field;
@@ -145,7 +147,7 @@ static void KEACopyRAT(GDALRasterBand *pBand, kealib::KEAImageIO *pImageIO, int
         {
             field = new kealib::KEAATTField();
             field->name = gdalAtt->GetNameOfCol(ni);
-            
+
             field->dataType = kealib::kea_att_string;
             switch(gdalAtt->GetTypeOfCol(ni))
             {
@@ -162,7 +164,7 @@ static void KEACopyRAT(GDALRasterBand *pBand, kealib::KEAImageIO *pImageIO, int
                     // leave as "kea_att_string"
                     break;
             }
-            
+
             if(bInputHFA && (field->name == "Histogram"))
             {
                 field->usage = "PixelCount";
@@ -222,12 +224,14 @@ static void KEACopyRAT(GDALRasterBand *pBand, kealib::KEAImageIO *pImageIO, int
                         break;
                 }
             }
-            
+
             fields->push_back(field);
         }
-        
-        keaAtt->addFields(fields); // This function will populate the field indexs used within the KEA RAT.
-        
+
+        // This function will populate the field indexes used within
+        // the KEA RAT.
+        keaAtt->addFields(fields);
+
         int numRows = gdalAtt->GetRowCount();
         keaAtt->addRows(numRows);
 
@@ -248,7 +252,8 @@ static void KEACopyRAT(GDALRasterBand *pBand, kealib::KEAImageIO *pImageIO, int
                 switch(field->dataType)
                 {
                     case kealib::kea_att_int:
-                        ((GDALRasterAttributeTable*)gdalAtt)->ValuesIO(GF_Read, nj, ni, nLength, pnIntBuffer);
+                        ((GDALRasterAttributeTable*)gdalAtt)->ValuesIO(
+                            GF_Read, nj, ni, nLength, pnIntBuffer);
                         for( int i = 0; i < nLength; i++ )
                         {
                             pnInt64Buffer[i] = pnIntBuffer[i];
@@ -260,10 +265,10 @@ static void KEACopyRAT(GDALRasterBand *pBand, kealib::KEAImageIO *pImageIO, int
                         keaAtt->setFloatFields(ni, nLength, field->idx, pfDoubleBuffer);
                         break;
                     case kealib::kea_att_string:
-                        {   
+                        {
                             char **papszColData = (char**)VSIMalloc2(nLength, sizeof(char*));
                             ((GDALRasterAttributeTable*)gdalAtt)->ValuesIO(GF_Read, nj, ni, nLength, papszColData);
-                     
+
                             std::vector<std::string> aStringBuffer;
                             for( int i = 0; i < nLength; i++ )
                             {
@@ -316,7 +321,7 @@ static void KEACopyMetadata( GDALMajorObject *pObject, kealib::KEAImageIO *pImag
                 pszValue = "";
             if( pszName != NULL )
             {
-                // it is LAYER_TYPE and a Band? if so handle seperately
+                // it is LAYER_TYPE and a Band? if so handle separately
                 if( ( nBand != -1 ) && EQUAL( pszName, "LAYER_TYPE" ) )
                 {
                     if( EQUAL( pszValue, "athematic" ) )
@@ -330,8 +335,8 @@ static void KEACopyMetadata( GDALMajorObject *pObject, kealib::KEAImageIO *pImag
                 }
                 else if( ( nBand != -1 ) && EQUAL( pszName, "STATISTICS_HISTOBINVALUES") )
                 {
-                    // this gets copied accross as part of the attributes
-                    // so ignore for now
+                    // This gets copied across as part of the attributes
+                    // so ignore for now.
                 }
                 else
                 {
@@ -355,7 +360,7 @@ static void KEACopyDescription(GDALRasterBand *pBand, kealib::KEAImageIO *pImage
     pImageIO->setImageBandDescription(nBand, pszDesc);
 }
 
-// copies the no data value accross
+// copies the no data value across
 static void KEACopyNoData(GDALRasterBand *pBand, kealib::KEAImageIO *pImageIO, int nBand)
 {
     int bSuccess = 0;
@@ -384,7 +389,7 @@ static bool KEACopyBand( GDALRasterBand *pBand, kealib::KEAImageIO *pImageIO, in
             return false;
     }
 
-    // now metadata 
+    // now metadata
     KEACopyMetadata(pBand, pImageIO, nBand);
 
     // and attributes
@@ -421,7 +426,7 @@ static void KEACopySpatialInfo(GDALDataset *pDataset, kealib::KEAImageIO *pImage
     pImageIO->setSpatialInfo( pSpatialInfo );
 }
 
-// copies the GCP's accross
+// copies the GCP's across
 static void KEACopyGCPs(GDALDataset *pDataset, kealib::KEAImageIO *pImageIO)
 {
     int nGCPs = pDataset->GetGCPCount();
@@ -449,7 +454,7 @@ static void KEACopyGCPs(GDALDataset *pDataset, kealib::KEAImageIO *pImageIO)
         {
             pImageIO->setGCPs(&KEAGCPs, pszGCPProj);
         }
-        catch(kealib::KEAException &e)
+        catch(const kealib::KEAException &)
         {
         }
 
@@ -462,11 +467,12 @@ static void KEACopyGCPs(GDALDataset *pDataset, kealib::KEAImageIO *pImageIO)
 
 
 
-bool KEACopyFile( GDALDataset *pDataset, kealib::KEAImageIO *pImageIO, GDALProgressFunc pfnProgress, void *pProgressData )
+bool KEACopyFile( GDALDataset *pDataset, kealib::KEAImageIO *pImageIO,
+                  GDALProgressFunc pfnProgress, void *pProgressData )
 {
     // Main function - copies pDataset to pImageIO
 
-    // copy accross the spatial info
+    // Copy across the spatial info.
     KEACopySpatialInfo( pDataset, pImageIO);
 
     // dataset metadata
@@ -474,13 +480,14 @@ bool KEACopyFile( GDALDataset *pDataset, kealib::KEAImageIO *pImageIO, GDALProgr
 
     // GCPs
     KEACopyGCPs(pDataset, pImageIO);
-    
+
     // now copy all the bands over
     int nBands = pDataset->GetRasterCount();
     for( int nBand = 0; nBand < nBands; nBand++ )
     {
         GDALRasterBand *pBand = pDataset->GetRasterBand(nBand + 1);
-        if( !KEACopyBand( pBand, pImageIO, nBand +1, nBands, pfnProgress, pProgressData ) )
+        if( !KEACopyBand( pBand, pImageIO, nBand +1, nBands, pfnProgress,
+                          pProgressData ) )
             return false;
     }
 
diff --git a/frmts/kea/keacopy.h b/frmts/kea/keacopy.h
index d2c6825..04ebde0 100644
--- a/frmts/kea/keacopy.h
+++ b/frmts/kea/keacopy.h
@@ -1,5 +1,5 @@
 /*
- * $Id: keacopy.h 29258 2015-05-28 22:08:43Z rouault $
+ * $Id: keacopy.h 33720 2016-03-15 00:39:53Z goatbar $
  *  keacopy.h
  *
  *  Created by Pete Bunting on 01/08/2012.
@@ -7,23 +7,23 @@
  *
  *  This file is part of LibKEA.
  *
- *  Permission is hereby granted, free of charge, to any person 
- *  obtaining a copy of this software and associated documentation 
- *  files (the "Software"), to deal in the Software without restriction, 
- *  including without limitation the rights to use, copy, modify, 
- *  merge, publish, distribute, sublicense, and/or sell copies of the 
- *  Software, and to permit persons to whom the Software is furnished 
+ *  Permission is hereby granted, free of charge, to any person
+ *  obtaining a copy of this software and associated documentation
+ *  files (the "Software"), to deal in the Software without restriction,
+ *  including without limitation the rights to use, copy, modify,
+ *  merge, publish, distribute, sublicense, and/or sell copies of the
+ *  Software, and to permit persons to whom the Software is furnished
  *  to do so, subject to the following conditions:
  *
- *  The above copyright notice and this permission notice shall be 
+ *  The above copyright notice and this permission notice shall be
  *  included in all copies or substantial portions of the Software.
  *
- *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
- *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
- *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
- *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 
- *  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
- *  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ *  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
  */
@@ -32,10 +32,8 @@
 #define KEACOPY_H
 
 #include "gdal_priv.h"
-#if defined(USE_GCC_VISIBILITY_FLAG) && !defined(DllExport)
-#define DllExport CPL_DLL
-#endif
-#include "libkea/KEAImageIO.h"
+
+#include "libkea_headers.h"
 
 bool KEACopyFile( GDALDataset *pDataset, kealib::KEAImageIO *pImageIO, GDALProgressFunc pfnProgress, void *pProgressData );
 
diff --git a/frmts/kea/keadataset.cpp b/frmts/kea/keadataset.cpp
index 4826e0d..08bfba6 100644
--- a/frmts/kea/keadataset.cpp
+++ b/frmts/kea/keadataset.cpp
@@ -1,5 +1,5 @@
 /*
- * $Id: keadataset.cpp 28825 2015-03-30 14:48:50Z rouault $
+ * $Id: keadataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *  keadataset.cpp
  *
  *  Created by Pete Bunting on 01/08/2012.
@@ -7,23 +7,23 @@
  *
  *  This file is part of LibKEA.
  *
- *  Permission is hereby granted, free of charge, to any person 
- *  obtaining a copy of this software and associated documentation 
- *  files (the "Software"), to deal in the Software without restriction, 
- *  including without limitation the rights to use, copy, modify, 
- *  merge, publish, distribute, sublicense, and/or sell copies of the 
- *  Software, and to permit persons to whom the Software is furnished 
+ *  Permission is hereby granted, free of charge, to any person
+ *  obtaining a copy of this software and associated documentation
+ *  files (the "Software"), to deal in the Software without restriction,
+ *  including without limitation the rights to use, copy, modify,
+ *  merge, publish, distribute, sublicense, and/or sell copies of the
+ *  Software, and to permit persons to whom the Software is furnished
  *  to do so, subject to the following conditions:
  *
- *  The above copyright notice and this permission notice shall be 
+ *  The above copyright notice and this permission notice shall be
  *  included in all copies or substantial portions of the Software.
  *
- *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
- *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
- *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
- *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 
- *  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
- *  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ *  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
  */
@@ -32,8 +32,6 @@
 #include "keaband.h"
 #include "keacopy.h"
 
-#include "libkea/KEACommon.h"
-
 // Function for converting a libkea type into a GDAL type
 GDALDataType KEA_to_GDAL_Type( kealib::KEADataType ekeaType )
 {
@@ -103,7 +101,7 @@ kealib::KEADataType GDAL_to_KEA_Type( GDALDataType egdalType )
     return ekeaType;
 }
 
-// static function - pointer set in driver 
+// static function - pointer set in driver
 GDALDataset *KEADataset::Open( GDALOpenInfo * poOpenInfo )
 {
     if( Identify( poOpenInfo ) )
@@ -128,7 +126,7 @@ GDALDataset *KEADataset::Open( GDALOpenInfo * poOpenInfo )
 
             return pDataset;
         }
-        catch (kealib::KEAIOException &e)
+        catch (const kealib::KEAIOException &)
         {
             // was a problem - can't be a valid file
             return NULL;
@@ -143,7 +141,7 @@ GDALDataset *KEADataset::Open( GDALOpenInfo * poOpenInfo )
 
 // static function- pointer set in driver
 // this function is called in preference to Open
-// 
+//
 int KEADataset::Identify( GDALOpenInfo * poOpenInfo )
 {
     bool bisKEA = false;
@@ -164,7 +162,7 @@ int KEADataset::Identify( GDALOpenInfo * poOpenInfo )
         // is this a KEA file?
         bisKEA = kealib::KEAImageIO::isKEAImage( poOpenInfo->pszFilename );
     }
-    catch (kealib::KEAIOException &e)
+    catch (const kealib::KEAIOException &)
     {
         bisKEA = false;
     }
@@ -244,16 +242,16 @@ H5::H5File *KEADataset::CreateLL( const char * pszFilename,
                   GDALGetDataTypeName(eType) );
         return NULL;
     }
-    
+
     try
     {
         // now create it
         H5::H5File *keaImgH5File = kealib::KEAImageIO::createKEAImage( pszFilename,
                                                     keaDataType,
                                                     nXSize, nYSize, nBands,
-                                                    NULL, NULL, nimageblockSize, 
+                                                    NULL, NULL, nimageblockSize,
                                                     nattblockSize, nmdcElmts, nrdccNElmts,
-                                                    nrdccNBytes, nrdccW0, nsieveBuf, 
+                                                    nrdccNBytes, nrdccW0, nsieveBuf,
                                                     nmetaBlockSize, ndeflate );
         return keaImgH5File;
     }
@@ -277,11 +275,12 @@ GDALDataset *KEADataset::Create( const char * pszFilename,
     if( keaImgH5File == NULL )
         return NULL;
 
-    bool bThematic = CSLTestBoolean(CSLFetchNameValueDef( papszParmList, "THEMATIC", "FALSE" ));
+    bool bThematic =
+        CPLTestBool(CSLFetchNameValueDef( papszParmList, "THEMATIC", "FALSE" ));
 
     try
     {
-        // create our dataset object                            
+        // create our dataset object
         KEADataset *pDataset = new KEADataset( keaImgH5File, GA_Update );
 
         pDataset->SetDescription( pszFilename );
@@ -308,7 +307,7 @@ GDALDataset *KEADataset::Create( const char * pszFilename,
 }
 
 GDALDataset *KEADataset::CreateCopy( const char * pszFilename, GDALDataset *pSrcDs,
-                                CPL_UNUSED int bStrict, char **  papszParmList, 
+                                CPL_UNUSED int bStrict, char **  papszParmList,
                                 GDALProgressFunc pfnProgress, void *pProgressData )
 {
     // get the data out of the input dataset
@@ -322,13 +321,14 @@ GDALDataset *KEADataset::CreateCopy( const char * pszFilename, GDALDataset *pSrc
     if( keaImgH5File == NULL )
         return NULL;
 
-    bool bThematic = CSLTestBoolean(CSLFetchNameValueDef( papszParmList, "THEMATIC", "FALSE" ));
+    bool bThematic =
+        CPLTestBool(CSLFetchNameValueDef( papszParmList, "THEMATIC", "FALSE" ));
 
     try
     {
         // create the imageio
         kealib::KEAImageIO *pImageIO = new kealib::KEAImageIO();
-        
+
         // open the file
         pImageIO->openKEAImageHeader( keaImgH5File );
 
@@ -344,7 +344,7 @@ GDALDataset *KEADataset::CreateCopy( const char * pszFilename, GDALDataset *pSrc
         {
             pImageIO->close();
         }
-        catch (kealib::KEAIOException &e)
+        catch (const kealib::KEAIOException &)
         {
         }
         delete pImageIO;
@@ -372,17 +372,21 @@ GDALDataset *KEADataset::CreateCopy( const char * pszFilename, GDALDataset *pSrc
             pDataset->GetRasterBand(nCount+1)->SetColorInterpretation(
                 pSrcDs->GetRasterBand(nCount+1)->GetColorInterpretation());
         }
-        
+
         // KEA has no concept of per-dataset mask band for now.
         for( int nCount = 0; nCount < nBands; nCount++ )
         {
             if( pSrcDs->GetRasterBand(nCount+1)->GetMaskFlags() == 0 ) // Per-band mask
             {
                 pDataset->GetRasterBand(nCount+1)->CreateMaskBand(0);
-                GDALRasterBandCopyWholeRaster(
+                if( GDALRasterBandCopyWholeRaster(
                     (GDALRasterBandH)pSrcDs->GetRasterBand(nCount+1)->GetMaskBand(),
                     (GDALRasterBandH)pDataset->GetRasterBand(nCount+1)->GetMaskBand(),
-                    NULL, NULL, NULL);
+                    NULL, NULL, NULL) != CE_None )
+                {
+                    delete pDataset;
+                    return NULL;
+                }
             }
         }
 
@@ -399,15 +403,15 @@ GDALDataset *KEADataset::CreateCopy( const char * pszFilename, GDALDataset *pSrc
 }
 
 // constructor
-KEADataset::KEADataset( H5::H5File *keaImgH5File, GDALAccess eAccess )
+KEADataset::KEADataset( H5::H5File *keaImgH5File, GDALAccess eAccessIn )
 {
     try
     {
-        // create the image IO and initilize the refcount
+        // Create the image IO and initialize the refcount.
         m_pImageIO = new kealib::KEAImageIO();
         m_pnRefcount = new int(1);
 
-        // NULL until we read them in 
+        // NULL until we read them in.
         m_papszMetadataList = NULL;
         m_pGCPs = NULL;
         m_pszGCPProjection = NULL;
@@ -418,26 +422,27 @@ KEADataset::KEADataset( H5::H5File *keaImgH5File, GDALAccess eAccess )
 
         // get the dimensions
         this->nBands = m_pImageIO->getNumOfImageBands();
-        this->nRasterXSize = pSpatialInfo->xSize;
-        this->nRasterYSize = pSpatialInfo->ySize;
-        this->eAccess = eAccess;
+        this->nRasterXSize = static_cast<int>(pSpatialInfo->xSize);
+        this->nRasterYSize = static_cast<int>(pSpatialInfo->ySize);
+        this->eAccess = eAccessIn;
 
         // create all the bands
         for( int nCount = 0; nCount < nBands; nCount++ )
         {
-            // note GDAL uses indices starting at 1 and so does kealib
-            // create band object
-            KEARasterBand *pBand = new KEARasterBand( this, nCount + 1, eAccess, m_pImageIO, m_pnRefcount );
+            // Note: GDAL uses indices starting at 1 and so does kealib.
+            // Create band object.
+            KEARasterBand *pBand = new KEARasterBand(
+                this, nCount + 1, eAccess, m_pImageIO, m_pnRefcount );
             // read in overviews
             pBand->readExistingOverviews();
             // set the band into this dataset
-            this->SetBand( nCount + 1, pBand );            
+            this->SetBand( nCount + 1, pBand );
         }
 
         // read in the metadata
         this->UpdateMetadataList();
     }
-    catch (kealib::KEAIOException &e)
+    catch (const kealib::KEAIOException &e)
     {
         // ignore?
         CPLError( CE_Warning, CPLE_AppDefined,
@@ -457,7 +462,7 @@ KEADataset::~KEADataset()
         {
             m_pImageIO->close();
         }
-        catch (kealib::KEAIOException &e)
+        catch (const kealib::KEAIOException &)
         {
         }
         delete m_pImageIO;
@@ -492,10 +497,10 @@ CPLErr KEADataset::GetGeoTransform( double * padfTransform )
         padfTransform[3] = pSpatialInfo->tlY;
         padfTransform[4] = pSpatialInfo->yRot;
         padfTransform[5] = pSpatialInfo->yRes;
-    
+
         return CE_None;
     }
-    catch (kealib::KEAIOException &e)
+    catch (const kealib::KEAIOException &e)
     {
         CPLError( CE_Warning, CPLE_AppDefined,
                 "Unable to read geotransform: %s", e.what() );
@@ -512,7 +517,7 @@ const char *KEADataset::GetProjectionRef()
         // should be safe since pSpatialInfo should be around a while...
         return pSpatialInfo->wktString.c_str();
     }
-    catch (kealib::KEAIOException &e)
+    catch (const kealib::KEAIOException &)
     {
         return NULL;
     }
@@ -536,7 +541,7 @@ CPLErr KEADataset::SetGeoTransform (double *padfTransform )
         m_pImageIO->setSpatialInfo( pSpatialInfo );
         return CE_None;
     }
-    catch (kealib::KEAIOException &e)
+    catch (const kealib::KEAIOException &e)
     {
         CPLError( CE_Warning, CPLE_AppDefined,
                 "Unable to write geotransform: %s", e.what() );
@@ -557,7 +562,7 @@ CPLErr KEADataset::SetProjection( const char *pszWKT )
         m_pImageIO->setSpatialInfo( pSpatialInfo );
         return CE_None;
     }
-    catch (kealib::KEAIOException &e)
+    catch (const kealib::KEAIOException &e)
     {
         CPLError( CE_Warning, CPLE_AppDefined,
                 "Unable to write projection: %s", e.what() );
@@ -573,8 +578,8 @@ void * KEADataset::GetInternalHandle(const char *)
 
 // this is called by GDALDataset::BuildOverviews. we implement this function to support
 // building of overviews
-CPLErr KEADataset::IBuildOverviews(const char *pszResampling, int nOverviews, int *panOverviewList, 
-                                    int nListBands, int *panBandList, GDALProgressFunc pfnProgress, 
+CPLErr KEADataset::IBuildOverviews(const char *pszResampling, int nOverviews, int *panOverviewList,
+                                    int nListBands, int *panBandList, GDALProgressFunc pfnProgress,
                                     void *pProgressData)
 {
     // go through the list of bands that have been passed in
@@ -620,7 +625,7 @@ CPLErr KEADataset::SetMetadataItem(const char *pszName, const char *pszValue, co
         m_papszMetadataList = CSLSetNameValue( m_papszMetadataList, pszName, pszValue );
         return CE_None;
     }
-    catch (kealib::KEAIOException &e)
+    catch (const kealib::KEAIOException &e)
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                 "Unable to write metadata: %s", e.what() );
@@ -634,18 +639,18 @@ const char *KEADataset::GetMetadataItem (const char *pszName, const char *pszDom
     // only deal with 'default' domain - no geolocation etc
     if( ( pszDomain != NULL ) && ( *pszDomain != '\0' ) )
         return NULL;
-    // string returned from CSLFetchNameValue should be persistant
+    // string returned from CSLFetchNameValue should be persistent
     return CSLFetchNameValue(m_papszMetadataList, pszName);
 }
 
 // get the whole metadata as CSLStringList
 char **KEADataset::GetMetadata(const char *pszDomain)
-{ 
+{
     // only deal with 'default' domain - no geolocation etc
     if( ( pszDomain != NULL ) && ( *pszDomain != '\0' ) )
         return NULL;
     // this is what we store it as anyway
-    return m_papszMetadataList; 
+    return m_papszMetadataList;
 }
 
 // set the whole metadata as a CSLStringList
@@ -677,7 +682,7 @@ CPLErr KEADataset::SetMetadata(char **papszMetadata, const char *pszDomain)
             nIndex++;
         }
     }
-    catch (kealib::KEAIOException &e)
+    catch (const kealib::KEAIOException &e)
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                 "Unable to write metadata: %s", e.what() );
@@ -699,20 +704,20 @@ CPLErr KEADataset::AddBand(GDALDataType eType, char **papszOptions)
     if (papszOptions != NULL) {
         const char *pszValue = CSLFetchNameValue(papszOptions,"IMAGEBLOCKSIZE");
         if ( pszValue != NULL ) {
-            nimageBlockSize = atol(pszValue);
+            nimageBlockSize = atoi(pszValue);
         }
 
         pszValue = CSLFetchNameValue(papszOptions, "ATTBLOCKSIZE");
         if (pszValue != NULL) {
-            nattBlockSize = atol(pszValue);
+            nattBlockSize = atoi(pszValue);
         }
 
         pszValue = CSLFetchNameValue(papszOptions, "DEFLATE");
         if (pszValue != NULL) {
-            ndeflate = atol(pszValue);
+            ndeflate = atoi(pszValue);
         }
     }
-    
+
     kealib::KEADataType keaDataType = GDAL_to_KEA_Type( eType );
     if( keaDataType == kealib::kea_undefined )
     {
@@ -721,11 +726,11 @@ CPLErr KEADataset::AddBand(GDALDataType eType, char **papszOptions)
                   GDALGetDataTypeName(eType) );
         return CE_Failure;
     }
-    
+
     try {
         m_pImageIO->addImageBand(keaDataType, "", nimageBlockSize,
                 nattBlockSize, ndeflate);
-    } catch (kealib::KEAIOException &e) {
+    } catch (const kealib::KEAIOException &e) {
         CPLError( CE_Failure, CPLE_AppDefined,
                 "Unable to create band: %s", e.what() );
         return CE_Failure;
@@ -735,7 +740,7 @@ CPLErr KEADataset::AddBand(GDALDataType eType, char **papszOptions)
     // note GDAL uses indices starting at 1 and so does kealib
     KEARasterBand *pBand = new KEARasterBand(this, this->nBands+1, this->eAccess,
             m_pImageIO, m_pnRefcount);
-    this->SetBand(this->nBands+1, pBand);            
+    this->SetBand(this->nBands+1, pBand);
 
     return CE_None;
 }
@@ -747,7 +752,7 @@ int KEADataset::GetGCPCount()
     {
         return m_pImageIO->getGCPCount();
     }
-    catch (kealib::KEAIOException &e) 
+    catch (const kealib::KEAIOException &)
     {
         return 0;
     }
@@ -763,7 +768,7 @@ const char* KEADataset::GetGCPProjection()
             std::string sProj = m_pImageIO->getGCPProjection();
             m_pszGCPProjection = CPLStrdup( sProj.c_str() );
         }
-        catch (kealib::KEAIOException &e) 
+        catch (const kealib::KEAIOException &)
         {
             return NULL;
         }
@@ -799,7 +804,7 @@ const GDAL_GCP* KEADataset::GetGCPs()
 
             delete pKEAGCPs;
         }
-        catch (kealib::KEAIOException &e) 
+        catch (const kealib::KEAIOException &)
         {
             return NULL;
         }
@@ -832,7 +837,7 @@ CPLErr KEADataset::SetGCPs(int nGCPCount, const GDAL_GCP *pasGCPList, const char
     {
         m_pImageIO->setGCPs(pKEAGCPs, pszGCPProjection);
     }
-    catch (kealib::KEAIOException &e) 
+    catch (const kealib::KEAIOException &e)
     {
         CPLError( CE_Warning, CPLE_AppDefined,
                 "Unable to write GCPs: %s", e.what() );
diff --git a/frmts/kea/keadataset.h b/frmts/kea/keadataset.h
index 836cfab..037f914 100644
--- a/frmts/kea/keadataset.h
+++ b/frmts/kea/keadataset.h
@@ -1,5 +1,5 @@
 /*
- * $Id: keadataset.h 29258 2015-05-28 22:08:43Z rouault $
+ * $Id: keadataset.h 33720 2016-03-15 00:39:53Z goatbar $
  *  keadataset.h
  *
  *  Created by Pete Bunting on 01/08/2012.
@@ -7,23 +7,23 @@
  *
  *  This file is part of LibKEA.
  *
- *  Permission is hereby granted, free of charge, to any person 
- *  obtaining a copy of this software and associated documentation 
- *  files (the "Software"), to deal in the Software without restriction, 
- *  including without limitation the rights to use, copy, modify, 
- *  merge, publish, distribute, sublicense, and/or sell copies of the 
- *  Software, and to permit persons to whom the Software is furnished 
+ *  Permission is hereby granted, free of charge, to any person
+ *  obtaining a copy of this software and associated documentation
+ *  files (the "Software"), to deal in the Software without restriction,
+ *  including without limitation the rights to use, copy, modify,
+ *  merge, publish, distribute, sublicense, and/or sell copies of the
+ *  Software, and to permit persons to whom the Software is furnished
  *  to do so, subject to the following conditions:
  *
- *  The above copyright notice and this permission notice shall be 
+ *  The above copyright notice and this permission notice shall be
  *  included in all copies or substantial portions of the Software.
  *
- *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
- *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
- *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
- *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 
- *  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
- *  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ *  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
  */
@@ -32,10 +32,8 @@
 #define KEADATASET_H
 
 #include "gdal_pam.h"
-#if defined(USE_GCC_VISIBILITY_FLAG) && !defined(DllExport)
-#define DllExport CPL_DLL
-#endif
-#include "libkea/KEAImageIO.h"
+
+#include "libkea_headers.h"
 
 // class that implements a GDAL dataset
 class KEADataset : public GDALPamDataset
@@ -49,7 +47,7 @@ public:
     // constructor/destructor
     KEADataset( H5::H5File *keaImgH5File, GDALAccess eAccess );
     ~KEADataset();
-    
+
     // static methods that handle open and creation
     // the driver class has pointers to these
     static GDALDataset *Open( GDALOpenInfo * );
@@ -59,7 +57,7 @@ public:
                                   GDALDataType eType,
                                   char **  papszParmList );
     static GDALDataset *CreateCopy( const char * pszFilename, GDALDataset *pSrcDs,
-                                int bStrict, char **  papszParmList, 
+                                int bStrict, char **  papszParmList,
                                 GDALProgressFunc pfnProgress, void *pProgressData );
 
     // virtual methods for dealing with transform and projection
@@ -89,9 +87,9 @@ public:
     CPLErr SetGCPs(int nGCPCount, const GDAL_GCP *pasGCPList, const char *pszGCPProjection);
 
 protected:
-    // this method builds overviews for the specified bands. 
-    virtual CPLErr IBuildOverviews(const char *pszResampling, int nOverviews, int *panOverviewList, 
-                                    int nListBands, int *panBandList, GDALProgressFunc pfnProgress, 
+    // this method builds overviews for the specified bands.
+    virtual CPLErr IBuildOverviews(const char *pszResampling, int nOverviews, int *panOverviewList,
+                                    int nListBands, int *panBandList, GDALProgressFunc pfnProgress,
                                     void *pProgressData);
 
     // internal method to update m_papszMetadataList
diff --git a/frmts/kea/keadriver.cpp b/frmts/kea/keadriver.cpp
index 46c1f36..24208c6 100644
--- a/frmts/kea/keadriver.cpp
+++ b/frmts/kea/keadriver.cpp
@@ -1,5 +1,5 @@
 /*
- * $Id: keadriver.cpp 28041 2014-12-01 11:33:47Z rouault $
+ * $Id: keadriver.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *  keadriver.cpp
  *
  *  Created by Pete Bunting on 01/08/2012.
@@ -7,87 +7,78 @@
  *
  *  This file is part of LibKEA.
  *
- *  Permission is hereby granted, free of charge, to any person 
- *  obtaining a copy of this software and associated documentation 
- *  files (the "Software"), to deal in the Software without restriction, 
- *  including without limitation the rights to use, copy, modify, 
- *  merge, publish, distribute, sublicense, and/or sell copies of the 
- *  Software, and to permit persons to whom the Software is furnished 
+ *  Permission is hereby granted, free of charge, to any person
+ *  obtaining a copy of this software and associated documentation
+ *  files (the "Software"), to deal in the Software without restriction,
+ *  including without limitation the rights to use, copy, modify,
+ *  merge, publish, distribute, sublicense, and/or sell copies of the
+ *  Software, and to permit persons to whom the Software is furnished
  *  to do so, subject to the following conditions:
  *
- *  The above copyright notice and this permission notice shall be 
+ *  The above copyright notice and this permission notice shall be
  *  included in all copies or substantial portions of the Software.
  *
- *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
- *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
- *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
- *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 
- *  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
- *  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ *  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
  */
 
+#include "gdal_frmts.h"
 #include "keadataset.h"
 
-CPL_C_START
-void CPL_DLL GDALRegister_KEA(void);
-CPL_C_END
-
 // method to register this driver
 void GDALRegister_KEA()
 {
-    GDALDriver  *poDriver;
-
-    if (! GDAL_CHECK_VERSION("KEA"))
+    if( !GDAL_CHECK_VERSION( "KEA" ) )
         return;
 
-    if( GDALGetDriverByName( "KEA" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "KEA" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "KEA Image Format (.kea)" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "kea" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "frmt_kea.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                            "Byte Int16 UInt16 Int32 UInt32 Float32 Float64" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
-CPLSPrintf("\
-<CreationOptionList> \
-<Option name='IMAGEBLOCKSIZE' type='int' description='The size of each block for image data' default='%d'/> \
-<Option name='ATTBLOCKSIZE' type='int' description='The size of each block for attribute data' default='%d'/> \
-<Option name='MDC_NELMTS' type='int' description='Number of elements in the meta data cache' default='%d'/> \
-<Option name='RDCC_NELMTS' type='int' description='Number of elements in the raw data chunk cache' default='%d'/> \
-<Option name='RDCC_NBYTES' type='int' description='Total size of the raw data chunk cache, in bytes' default='%d'/> \
-<Option name='RDCC_W0' type='float' min='0' max='1' description='Preemption policy' default='%.2f'/> \
-<Option name='SIEVE_BUF' type='int' description='Sets the maximum size of the data sieve buffer' default='%d'/> \
-<Option name='META_BLOCKSIZE' type='int' description='Sets the minimum size of metadata block allocations' default='%d'/> \
-<Option name='DEFLATE' type='int' description='0 (no compression) to 9 (max compression)' default='%d'/> \
-<Option name='THEMATIC' type='boolean' description='If YES then all bands are set to thematic' default='NO'/> \
-</CreationOptionList>",
-           (int)kealib::KEA_IMAGE_CHUNK_SIZE,
-           (int)kealib::KEA_ATT_CHUNK_SIZE,
-           (int)kealib::KEA_MDC_NELMTS,
-           (int)kealib::KEA_RDCC_NELMTS,
-           (int)kealib::KEA_RDCC_NBYTES,
-           kealib::KEA_RDCC_W0,
-           (int)kealib::KEA_SIEVE_BUF,
-           (int)kealib::KEA_META_BLOCKSIZE,
-           kealib::KEA_DEFLATE));
+    if( GDALGetDriverByName( "KEA" ) != NULL )
+      return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "KEA" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "KEA Image Format (.kea)" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "kea" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_kea.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte Int16 UInt16 Int32 UInt32 "
+                               "Float32 Float64" );
+    poDriver->SetMetadataItem(
+        GDAL_DMD_CREATIONOPTIONLIST,
+        CPLSPrintf(
+"<CreationOptionList> "
+"<Option name='IMAGEBLOCKSIZE' type='int' description='The size of each block for image data' default='%d'/> "
+"<Option name='ATTBLOCKSIZE' type='int' description='The size of each block for attribute data' default='%d'/> "
+"<Option name='MDC_NELMTS' type='int' description='Number of elements in the meta data cache' default='%d'/> "
+"<Option name='RDCC_NELMTS' type='int' description='Number of elements in the raw data chunk cache' default='%d'/> "
+"<Option name='RDCC_NBYTES' type='int' description='Total size of the raw data chunk cache, in bytes' default='%d'/> "
+"<Option name='RDCC_W0' type='float' min='0' max='1' description='Preemption policy' default='%.2f'/> "
+"<Option name='SIEVE_BUF' type='int' description='Sets the maximum size of the data sieve buffer' default='%d'/> "
+"<Option name='META_BLOCKSIZE' type='int' description='Sets the minimum size of metadata block allocations' default='%d'/> "
+"<Option name='DEFLATE' type='int' description='0 (no compression) to 9 (max compression)' default='%d'/> "
+"<Option name='THEMATIC' type='boolean' description='If YES then all bands are set to thematic' default='NO'/> "
+"</CreationOptionList>",
+        static_cast<int>(kealib::KEA_IMAGE_CHUNK_SIZE),
+        static_cast<int>(kealib::KEA_ATT_CHUNK_SIZE),
+        static_cast<int>(kealib::KEA_MDC_NELMTS),
+        static_cast<int>(kealib::KEA_RDCC_NELMTS),
+        static_cast<int>(kealib::KEA_RDCC_NBYTES),
+        kealib::KEA_RDCC_W0,
+        static_cast<int>(kealib::KEA_SIEVE_BUF),
+        static_cast<int>(kealib::KEA_META_BLOCKSIZE),
+        kealib::KEA_DEFLATE ) );
 
-        // pointer to open function
-        poDriver->pfnOpen = KEADataset::Open;
-        // pointer to identify function
-        poDriver->pfnIdentify = KEADataset::Identify;
-        // pointer to create function
-        poDriver->pfnCreate = KEADataset::Create;
-        // pointer to create copy function
-        poDriver->pfnCreateCopy = KEADataset::CreateCopy;
+    poDriver->pfnOpen = KEADataset::Open;
+    poDriver->pfnIdentify = KEADataset::Identify;
+    poDriver->pfnCreate = KEADataset::Create;
+    poDriver->pfnCreateCopy = KEADataset::CreateCopy;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/kea/keamaskband.cpp b/frmts/kea/keamaskband.cpp
index 9f7ac2a..bd8de99 100644
--- a/frmts/kea/keamaskband.cpp
+++ b/frmts/kea/keamaskband.cpp
@@ -1,5 +1,5 @@
 /*
- * $Id: keamaskband.cpp 28011 2014-11-26 13:47:09Z rouault $
+ * $Id: keamaskband.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *  keamaskband.cpp
  *
  *  Created by Pete Bunting on 01/08/2012.
@@ -7,23 +7,23 @@
  *
  *  This file is part of LibKEA.
  *
- *  Permission is hereby granted, free of charge, to any person 
- *  obtaining a copy of this software and associated documentation 
- *  files (the "Software"), to deal in the Software without restriction, 
- *  including without limitation the rights to use, copy, modify, 
- *  merge, publish, distribute, sublicense, and/or sell copies of the 
- *  Software, and to permit persons to whom the Software is furnished 
+ *  Permission is hereby granted, free of charge, to any person
+ *  obtaining a copy of this software and associated documentation
+ *  files (the "Software"), to deal in the Software without restriction,
+ *  including without limitation the rights to use, copy, modify,
+ *  merge, publish, distribute, sublicense, and/or sell copies of the
+ *  Software, and to permit persons to whom the Software is furnished
  *  to do so, subject to the following conditions:
  *
- *  The above copyright notice and this permission notice shall be 
+ *  The above copyright notice and this permission notice shall be
  *  included in all copies or substantial portions of the Software.
  *
- *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
- *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
- *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
- *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 
- *  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
- *  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ *  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
  */
@@ -31,7 +31,7 @@
 #include "keamaskband.h"
 
 // constructor
-KEAMaskBand::KEAMaskBand(GDALRasterBand *pParent, 
+KEAMaskBand::KEAMaskBand(GDALRasterBand *pParent,
                 kealib::KEAImageIO *pImageIO, int *pRefCount)
 {
     m_nSrcBand = pParent->GetBand();
@@ -65,7 +65,7 @@ KEAMaskBand::~KEAMaskBand()
         {
             m_pImageIO->close();
         }
-        catch (kealib::KEAIOException &e)
+        catch (const kealib::KEAIOException &)
         {
         }
         delete m_pImageIO;
@@ -95,7 +95,7 @@ CPLErr KEAMaskBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage )
         this->m_pImageIO->readImageBlock2BandMask( this->m_nSrcBand,
                                             pImage, this->nBlockXSize * nBlockXOff,
                                             this->nBlockYSize * nBlockYOff,
-                                            nxsize, nysize, this->nBlockXSize, this->nBlockYSize, 
+                                            nxsize, nysize, this->nBlockXSize, this->nBlockYSize,
                                             kealib::kea_8uint );
     }
     catch (kealib::KEAIOException &e)
@@ -127,7 +127,7 @@ CPLErr KEAMaskBand::IWriteBlock( int nBlockXOff, int nBlockYOff, void * pImage )
             nysize -= (nytotalsize - this->nRasterYSize);
         }
 
-        this->m_pImageIO-> writeImageBlock2BandMask( this->m_nSrcBand, 
+        this->m_pImageIO-> writeImageBlock2BandMask( this->m_nSrcBand,
                                             pImage, this->nBlockXSize * nBlockXOff,
                                             this->nBlockYSize * nBlockYOff,
                                             nxsize, nysize, this->nBlockXSize, this->nBlockYSize,
diff --git a/frmts/kea/keamaskband.h b/frmts/kea/keamaskband.h
index 06ce911..65e1bc2 100644
--- a/frmts/kea/keamaskband.h
+++ b/frmts/kea/keamaskband.h
@@ -1,5 +1,5 @@
 /*
- * $Id: keamaskband.h 29258 2015-05-28 22:08:43Z rouault $
+ * $Id: keamaskband.h 33720 2016-03-15 00:39:53Z goatbar $
  *  keamaskband.h
  *
  *  Created by Pete Bunting on 01/08/2012.
@@ -7,23 +7,23 @@
  *
  *  This file is part of LibKEA.
  *
- *  Permission is hereby granted, free of charge, to any person 
- *  obtaining a copy of this software and associated documentation 
- *  files (the "Software"), to deal in the Software without restriction, 
- *  including without limitation the rights to use, copy, modify, 
- *  merge, publish, distribute, sublicense, and/or sell copies of the 
- *  Software, and to permit persons to whom the Software is furnished 
+ *  Permission is hereby granted, free of charge, to any person
+ *  obtaining a copy of this software and associated documentation
+ *  files (the "Software"), to deal in the Software without restriction,
+ *  including without limitation the rights to use, copy, modify,
+ *  merge, publish, distribute, sublicense, and/or sell copies of the
+ *  Software, and to permit persons to whom the Software is furnished
  *  to do so, subject to the following conditions:
  *
- *  The above copyright notice and this permission notice shall be 
+ *  The above copyright notice and this permission notice shall be
  *  included in all copies or substantial portions of the Software.
  *
- *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
- *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
- *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
- *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 
- *  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
- *  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ *  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
  */
@@ -32,10 +32,8 @@
 #define KEAMASKBAND_H
 
 #include "gdal_priv.h"
-#if defined(USE_GCC_VISIBILITY_FLAG) && !defined(DllExport)
-#define DllExport CPL_DLL
-#endif
-#include "libkea/KEAImageIO.h"
+
+#include "libkea_headers.h"
 
 class KEAMaskBand : public GDALRasterBand
 {
diff --git a/frmts/kea/keaoverview.cpp b/frmts/kea/keaoverview.cpp
index df6d3b0..ca3d156 100644
--- a/frmts/kea/keaoverview.cpp
+++ b/frmts/kea/keaoverview.cpp
@@ -1,5 +1,5 @@
 /*
- * $Id: keaoverview.cpp 28011 2014-11-26 13:47:09Z rouault $
+ * $Id: keaoverview.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *  keaoverview.cpp
  *
  *  Created by Pete Bunting on 01/08/2012.
@@ -7,23 +7,23 @@
  *
  *  This file is part of LibKEA.
  *
- *  Permission is hereby granted, free of charge, to any person 
- *  obtaining a copy of this software and associated documentation 
- *  files (the "Software"), to deal in the Software without restriction, 
- *  including without limitation the rights to use, copy, modify, 
- *  merge, publish, distribute, sublicense, and/or sell copies of the 
- *  Software, and to permit persons to whom the Software is furnished 
+ *  Permission is hereby granted, free of charge, to any person
+ *  obtaining a copy of this software and associated documentation
+ *  files (the "Software"), to deal in the Software without restriction,
+ *  including without limitation the rights to use, copy, modify,
+ *  merge, publish, distribute, sublicense, and/or sell copies of the
+ *  Software, and to permit persons to whom the Software is furnished
  *  to do so, subject to the following conditions:
  *
- *  The above copyright notice and this permission notice shall be 
+ *  The above copyright notice and this permission notice shall be
  *  included in all copies or substantial portions of the Software.
  *
- *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
- *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
- *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
- *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 
- *  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
- *  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ *  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
  */
@@ -31,17 +31,17 @@
 #include "keaoverview.h"
 
 // constructor
-KEAOverview::KEAOverview(KEADataset *pDataset, int nSrcBand, GDALAccess eAccess,
+KEAOverview::KEAOverview(KEADataset *pDataset, int nSrcBand, GDALAccess eAccessIn,
                 kealib::KEAImageIO *pImageIO, int *pRefCount,
                 int nOverviewIndex, uint64_t nXSize, uint64_t nYSize)
- : KEARasterBand( pDataset, nSrcBand, eAccess, pImageIO, pRefCount )
+ : KEARasterBand( pDataset, nSrcBand, eAccessIn, pImageIO, pRefCount )
 {
     this->m_nOverviewIndex = nOverviewIndex;
     // overridden from the band - not the same size as the band obviously
     this->nBlockXSize = pImageIO->getOverviewBlockSize(nSrcBand, nOverviewIndex);
     this->nBlockYSize = pImageIO->getOverviewBlockSize(nSrcBand, nOverviewIndex);
-    this->nRasterXSize = nXSize;
-    this->nRasterYSize = nYSize;
+    this->nRasterXSize = static_cast<int>(nXSize);
+    this->nRasterYSize = static_cast<int>(nYSize);
 }
 
 KEAOverview::~KEAOverview()
@@ -71,7 +71,7 @@ CPLErr KEAOverview::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage )
         this->m_pImageIO->readFromOverview( this->nBand, this->m_nOverviewIndex,
                                             pImage, this->nBlockXSize * nBlockXOff,
                                             this->nBlockYSize * nBlockYOff,
-                                            nxsize, nysize, this->nBlockXSize, this->nBlockYSize, 
+                                            nxsize, nysize, this->nBlockXSize, this->nBlockYSize,
                                             this->m_eKEADataType );
         return CE_None;
     }
@@ -127,5 +127,5 @@ GDALRasterAttributeTable *KEAOverview::GetDefaultRAT()
 CPLErr KEAOverview::SetDefaultRAT(CPL_UNUSED const GDALRasterAttributeTable *poRAT)
 {
     // KEARasterBand implements this, but we don't want to
-    return CE_Failure;    
+    return CE_Failure;
 }
diff --git a/frmts/kea/keaoverview.h b/frmts/kea/keaoverview.h
index b3f8c2d..b2b5891 100644
--- a/frmts/kea/keaoverview.h
+++ b/frmts/kea/keaoverview.h
@@ -1,5 +1,5 @@
 /*
- * $Id: keaoverview.h 29258 2015-05-28 22:08:43Z rouault $
+ * $Id: keaoverview.h 33720 2016-03-15 00:39:53Z goatbar $
  *  keaoverview.h
  *
  *  Created by Pete Bunting on 01/08/2012.
@@ -7,23 +7,23 @@
  *
  *  This file is part of LibKEA.
  *
- *  Permission is hereby granted, free of charge, to any person 
- *  obtaining a copy of this software and associated documentation 
- *  files (the "Software"), to deal in the Software without restriction, 
- *  including without limitation the rights to use, copy, modify, 
- *  merge, publish, distribute, sublicense, and/or sell copies of the 
- *  Software, and to permit persons to whom the Software is furnished 
+ *  Permission is hereby granted, free of charge, to any person
+ *  obtaining a copy of this software and associated documentation
+ *  files (the "Software"), to deal in the Software without restriction,
+ *  including without limitation the rights to use, copy, modify,
+ *  merge, publish, distribute, sublicense, and/or sell copies of the
+ *  Software, and to permit persons to whom the Software is furnished
  *  to do so, subject to the following conditions:
  *
- *  The above copyright notice and this permission notice shall be 
+ *  The above copyright notice and this permission notice shall be
  *  included in all copies or substantial portions of the Software.
  *
- *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
- *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
- *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
- *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 
- *  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
- *  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ *  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
  */
@@ -32,18 +32,15 @@
 #define KEAOVERVIEW_H
 
 #include "cpl_port.h"
-#if defined(USE_GCC_VISIBILITY_FLAG) && !defined(DllExport)
-#define DllExport CPL_DLL
-#endif
 #include "keaband.h"
 
 // overview class. Derives from our band class
-// and just overrited and read/write block functions
+// and just overrides the read/write block functions
 class KEAOverview : public KEARasterBand
 {
     int         m_nOverviewIndex; // the index of this overview
 public:
-    KEAOverview(KEADataset *pDataset, int nSrcBand, GDALAccess eAccess, 
+    KEAOverview(KEADataset *pDataset, int nSrcBand, GDALAccess eAccess,
                 kealib::KEAImageIO *pImageIO, int *pRefCount,
                 int nOverviewIndex, uint64_t nXSize, uint64_t nYSize );
     ~KEAOverview();
diff --git a/frmts/kea/kearat.cpp b/frmts/kea/kearat.cpp
index 886e406..41efa66 100644
--- a/frmts/kea/kearat.cpp
+++ b/frmts/kea/kearat.cpp
@@ -1,5 +1,5 @@
 /*
- * $Id: kearat.cpp 28014 2014-11-26 14:43:45Z rouault $
+ * $Id: kearat.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *  kearat.cpp
  *
  *  Created by Pete Bunting on 01/08/2012.
@@ -7,23 +7,23 @@
  *
  *  This file is part of LibKEA.
  *
- *  Permission is hereby granted, free of charge, to any person 
- *  obtaining a copy of this software and associated documentation 
- *  files (the "Software"), to deal in the Software without restriction, 
- *  including without limitation the rights to use, copy, modify, 
- *  merge, publish, distribute, sublicense, and/or sell copies of the 
- *  Software, and to permit persons to whom the Software is furnished 
+ *  Permission is hereby granted, free of charge, to any person
+ *  obtaining a copy of this software and associated documentation
+ *  files (the "Software"), to deal in the Software without restriction,
+ *  including without limitation the rights to use, copy, modify,
+ *  merge, publish, distribute, sublicense, and/or sell copies of the
+ *  Software, and to permit persons to whom the Software is furnished
  *  to do so, subject to the following conditions:
  *
- *  The above copyright notice and this permission notice shall be 
+ *  The above copyright notice and this permission notice shall be
  *  included in all copies or substantial portions of the Software.
  *
- *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
- *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
- *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
- *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 
- *  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
- *  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ *  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
  */
@@ -39,7 +39,7 @@ KEARasterAttributeTable::KEARasterAttributeTable(kealib::KEAAttributeTable *poKE
         {
             sKEAField = poKEATable->getField(nColumnIndex);
         }
-        catch(kealib::KEAATTException &e)
+        catch(const kealib::KEAATTException &)
         {
             // pKEATable->getField raised exception because we have a missing column
             continue;
@@ -103,78 +103,72 @@ GDALDefaultRasterAttributeTable *KEARasterAttributeTable::Clone() const
                 break;
         }
         poRAT->CreateColumn(sName, eGDALType, eGDALUsage);
-        poRAT->SetRowCount(m_poKEATable->getSize());
-        
+        poRAT->SetRowCount(static_cast<int>(m_poKEATable->getSize()));
+
         if( m_poKEATable->getSize() == 0 )
             continue;
 
         if( eGDALType == GFT_Integer )
         {
-            int *panColData = (int*)VSIMalloc2(sizeof(int), m_poKEATable->getSize());
+            int *panColData = (int*)VSI_MALLOC2_VERBOSE(sizeof(int), m_poKEATable->getSize());
             if( panColData == NULL )
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory,
-                    "Memory Allocation failed in KEARasterAttributeTable::Clone");
                 delete poRAT;
                 return NULL;
             }
 
             if( (const_cast<KEARasterAttributeTable*>(this))->
-                        ValuesIO(GF_Read, iCol, 0, m_poKEATable->getSize(), panColData ) != CE_None )
+                        ValuesIO(GF_Read, iCol, 0, static_cast<int>(m_poKEATable->getSize()), panColData ) != CE_None )
             {
                 CPLFree(panColData);
                 delete poRAT;
                 return NULL;
-            }           
+            }
 
             for( int iRow = 0; iRow < (int)m_poKEATable->getSize(); iRow++ )
             {
-                poRAT->SetValue(iRow, iCol, panColData[iRow]);            
+                poRAT->SetValue(iRow, iCol, panColData[iRow]);
             }
             CPLFree(panColData);
         }
         if( eGDALType == GFT_Real )
         {
-            double *padfColData = (double*)VSIMalloc2(sizeof(double), m_poKEATable->getSize());
+            double *padfColData = (double*)VSI_MALLOC2_VERBOSE(sizeof(double), m_poKEATable->getSize());
             if( padfColData == NULL )
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory,
-                    "Memory Allocation failed in KEARasterAttributeTable::Clone");
                 delete poRAT;
                 return NULL;
             }
             if( (const_cast<KEARasterAttributeTable*>(this))->
-                        ValuesIO(GF_Read, iCol, 0, m_poKEATable->getSize(), padfColData ) != CE_None )
+                        ValuesIO(GF_Read, iCol, 0, static_cast<int>(m_poKEATable->getSize()), padfColData ) != CE_None )
             {
                 CPLFree(padfColData);
                 delete poRAT;
                 return NULL;
-            }           
+            }
 
             for( int iRow = 0; iRow < (int)m_poKEATable->getSize(); iRow++ )
             {
-                poRAT->SetValue(iRow, iCol, padfColData[iRow]);            
+                poRAT->SetValue(iRow, iCol, padfColData[iRow]);
             }
             CPLFree(padfColData);
         }
         if( eGDALType == GFT_String )
         {
-            char **papszColData = (char**)VSIMalloc2(sizeof(char*), m_poKEATable->getSize());
+            char **papszColData = (char**)VSI_MALLOC2_VERBOSE(sizeof(char*), m_poKEATable->getSize());
             if( papszColData == NULL )
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory,
-                    "Memory Allocation failed in KEARasterAttributeTable::Clone");
                 delete poRAT;
                 return NULL;
             }
 
             if( (const_cast<KEARasterAttributeTable*>(this))->
-                    ValuesIO(GF_Read, iCol, 0, m_poKEATable->getSize(), papszColData ) != CE_None )
+                    ValuesIO(GF_Read, iCol, 0, static_cast<int>(m_poKEATable->getSize()), papszColData ) != CE_None )
             {
                 CPLFree(papszColData);
                 delete poRAT;
                 return NULL;
-            }           
+            }
 
             for( int iRow = 0; iRow < (int)m_poKEATable->getSize(); iRow++ )
             {
@@ -208,7 +202,7 @@ GDALRATFieldUsage KEARasterAttributeTable::GetUsageOfCol( int nCol ) const
         return GFU_Generic;
 
     GDALRATFieldUsage eGDALUsage;
-    std::string keausage = m_aoFields[nCol].usage;    
+    std::string keausage = m_aoFields[nCol].usage;
 
     if( keausage == "PixelCount" )
         eGDALUsage = GFU_PixelCount;
@@ -305,7 +299,7 @@ const char *KEARasterAttributeTable::GetValueAsString( int iRow, int iField ) co
     // Get ValuesIO do do the work
     char *apszStrList[1];
     if( (const_cast<KEARasterAttributeTable*>(this))->
-                ValuesIO(GF_Read, iField, iRow, 1, apszStrList ) != CPLE_None )
+                ValuesIO(GF_Read, iField, iRow, 1, apszStrList ) != CE_None )
     {
         return "";
     }
@@ -391,11 +385,9 @@ CPLErr KEARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
         case kealib::kea_att_int:
         {
             // allocate space for ints
-            int *panColData = (int*)VSIMalloc2(iLength, sizeof(int) );
+            int *panColData = (int*)VSI_MALLOC2_VERBOSE(iLength, sizeof(int) );
             if( panColData == NULL )
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory,
-                    "Memory Allocation failed in KEARasterAttributeTable::ValuesIO");
                 return CE_Failure;
             }
 
@@ -403,7 +395,7 @@ CPLErr KEARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
             {
                 // copy the application supplied doubles to ints
                 for( int i = 0; i < iLength; i++ )
-                    panColData[i] = pdfData[i];
+                    panColData[i] = static_cast<int>(pdfData[i]);
             }
 
             // do the ValuesIO as ints
@@ -443,11 +435,9 @@ CPLErr KEARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
         case kealib::kea_att_string:
         {
             // allocate space for string pointers
-            char **papszColData = (char**)VSIMalloc2(iLength, sizeof(char*));
+            char **papszColData = (char**)VSI_MALLOC2_VERBOSE(iLength, sizeof(char*));
             if( papszColData == NULL )
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory,
-                    "Memory Allocation failed in KEARasterAttributeTable::ValuesIO");
                 return CE_Failure;
             }
 
@@ -525,11 +515,9 @@ CPLErr KEARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
         case kealib::kea_att_bool:
         {
             // need to convert to/from bools
-            bool *panColData = (bool*)VSIMalloc2(iLength, sizeof(bool) );
+            bool *panColData = (bool*)VSI_MALLOC2_VERBOSE(iLength, sizeof(bool) );
             if( panColData == NULL )
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory,
-                    "Memory Allocation failed in KEARasterAttributeTable::ValuesIO");
                 return CE_Failure;
             }
 
@@ -567,11 +555,9 @@ CPLErr KEARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
         case kealib::kea_att_int:
         {
             // need to convert to/from int64_t
-            int64_t *panColData = (int64_t*)VSIMalloc2(iLength, sizeof(int64_t) );
+            int64_t *panColData = (int64_t*)VSI_MALLOC2_VERBOSE(iLength, sizeof(int64_t) );
             if( panColData == NULL )
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory,
-                    "Memory Allocation failed in KEARasterAttributeTable::ValuesIO");
                 return CE_Failure;
             }
 
@@ -600,7 +586,7 @@ CPLErr KEARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
             {
                 // copy them back to ints
                 for( int i = 0; i < iLength; i++ )
-                    pnData[i] = panColData[i];
+                    pnData[i] = static_cast<int>(panColData[i]);
             }
             CPLFree(panColData);
         }
@@ -608,11 +594,9 @@ CPLErr KEARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
         case kealib::kea_att_float:
         {
             // allocate space for doubles
-            double *padfColData = (double*)VSIMalloc2(iLength, sizeof(double) );
+            double *padfColData = (double*)VSI_MALLOC2_VERBOSE(iLength, sizeof(double) );
             if( padfColData == NULL )
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory,
-                    "Memory Allocation failed in KEARasterAttributeTable::ValuesIO");
                 return CE_Failure;
             }
 
@@ -635,7 +619,7 @@ CPLErr KEARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
             {
                 // copy them back to ints
                 for( int i = 0; i < iLength; i++ )
-                    pnData[i] = padfColData[i];
+                    pnData[i] = static_cast<int>(padfColData[i]);
             }
 
             CPLFree(padfColData);
@@ -644,11 +628,9 @@ CPLErr KEARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
         case kealib::kea_att_string:
         {
             // allocate space for string pointers
-            char **papszColData = (char**)VSIMalloc2(iLength, sizeof(char*));
+            char **papszColData = (char**)VSI_MALLOC2_VERBOSE(iLength, sizeof(char*));
             if( papszColData == NULL )
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory,
-                    "Memory Allocation failed in KEARasterAttributeTable::ValuesIO");
                 return CE_Failure;
             }
 
@@ -679,7 +661,7 @@ CPLErr KEARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
             {
                 // copy them back to ints
                 for( int i = 0; i < iLength; i++ )
-                    pnData[i] = atol(papszColData[i]);
+                    pnData[i] = atoi(papszColData[i]);
             }
 
             // either we allocated them for write, or they were allocated
@@ -727,18 +709,16 @@ CPLErr KEARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
         case kealib::kea_att_int:
         {
             // allocate space for ints
-            int *panColData = (int*)VSIMalloc2(iLength, sizeof(int) );
+            int *panColData = (int*)VSI_MALLOC2_VERBOSE(iLength, sizeof(int) );
             if( panColData == NULL )
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory,
-                    "Memory Allocation failed in KEARasterAttributeTable::ValuesIO");
                 return CE_Failure;
             }
             if( eRWFlag == GF_Write )
             {
                 // convert user supplied strings to ints
                 for( int i = 0; i < iLength; i++ )
-                    panColData[i] = atol(papszStrList[i]);
+                    panColData[i] = atoi(papszStrList[i]);
             }
 
             // call values IO to read/write ints
@@ -765,14 +745,12 @@ CPLErr KEARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
         case kealib::kea_att_float:
         {
             // allocate space for doubles
-            double *padfColData = (double*)VSIMalloc2(iLength, sizeof(double) );
+            double *padfColData = (double*)VSI_MALLOC2_VERBOSE(iLength, sizeof(double) );
             if( padfColData == NULL )
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory,
-                    "Memory Allocation failed in KEARasterAttributeTable::ValuesIO");
                 return CE_Failure;
             }
-            
+
             if( eRWFlag == GF_Write )
             {
                 // convert user supplied strings to doubles
@@ -860,8 +838,8 @@ void KEARasterAttributeTable::SetRowCount( int iCount )
     // can't shrink
 }
 
-CPLErr KEARasterAttributeTable::CreateColumn( const char *pszFieldName, 
-                                GDALRATFieldType eFieldType, 
+CPLErr KEARasterAttributeTable::CreateColumn( const char *pszFieldName,
+                                GDALRATFieldType eFieldType,
                                 GDALRATFieldUsage eFieldUsage )
 {
     /*if( this->eAccess == GA_ReadOnly )
diff --git a/frmts/kea/kearat.h b/frmts/kea/kearat.h
index 2213de1..447d2e9 100644
--- a/frmts/kea/kearat.h
+++ b/frmts/kea/kearat.h
@@ -1,5 +1,5 @@
 /*
- * $Id: kearat.h 29258 2015-05-28 22:08:43Z rouault $
+ * $Id: kearat.h 33720 2016-03-15 00:39:53Z goatbar $
  *  kearat.h
  *
  *  Created by Pete Bunting on 01/08/2012.
@@ -7,23 +7,23 @@
  *
  *  This file is part of LibKEA.
  *
- *  Permission is hereby granted, free of charge, to any person 
- *  obtaining a copy of this software and associated documentation 
- *  files (the "Software"), to deal in the Software without restriction, 
- *  including without limitation the rights to use, copy, modify, 
- *  merge, publish, distribute, sublicense, and/or sell copies of the 
- *  Software, and to permit persons to whom the Software is furnished 
+ *  Permission is hereby granted, free of charge, to any person
+ *  obtaining a copy of this software and associated documentation
+ *  files (the "Software"), to deal in the Software without restriction,
+ *  including without limitation the rights to use, copy, modify,
+ *  merge, publish, distribute, sublicense, and/or sell copies of the
+ *  Software, and to permit persons to whom the Software is furnished
  *  to do so, subject to the following conditions:
  *
- *  The above copyright notice and this permission notice shall be 
+ *  The above copyright notice and this permission notice shall be
  *  included in all copies or substantial portions of the Software.
  *
- *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
- *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
- *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
- *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 
- *  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
- *  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ *  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
  */
@@ -33,9 +33,7 @@
 
 #include "gdal_priv.h"
 #include "gdal_rat.h"
-#if defined(USE_GCC_VISIBILITY_FLAG) && !defined(DllExport)
-#define DllExport CPL_DLL
-#endif
+
 #include "keaband.h"
 
 class KEARasterAttributeTable : public GDALRasterAttributeTable
@@ -56,7 +54,7 @@ public:
     virtual const char   *GetNameOfCol( int ) const;
     virtual GDALRATFieldUsage GetUsageOfCol( int ) const;
     virtual GDALRATFieldType GetTypeOfCol( int ) const;
-    
+
     virtual int           GetColOfUsage( GDALRATFieldUsage ) const;
 
     virtual int           GetRowCount() const;
@@ -76,8 +74,8 @@ public:
     virtual int           ChangesAreWrittenToFile();
     virtual void          SetRowCount( int iCount );
 
-    virtual CPLErr        CreateColumn( const char *pszFieldName, 
-                                GDALRATFieldType eFieldType, 
+    virtual CPLErr        CreateColumn( const char *pszFieldName,
+                                GDALRATFieldType eFieldType,
                                 GDALRATFieldUsage eFieldUsage );
 
     virtual CPLXMLNode   *Serialize() const;
diff --git a/frmts/kea/libkea_headers.h b/frmts/kea/libkea_headers.h
new file mode 100644
index 0000000..e373882
--- /dev/null
+++ b/frmts/kea/libkea_headers.h
@@ -0,0 +1,57 @@
+/******************************************************************************
+ *
+ * Project:  GDAL
+ * Purpose:  Includes libkea headers
+ * Author:   Even Rouault <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+#ifndef GDAL_LIBKEA_HEADERS_H
+#define GDAL_LIBKEA_HEADERS_H
+
+#include "cpl_port.h"
+
+#ifdef HAVE_GCC_SYSTEM_HEADER
+#pragma GCC system_header
+#endif
+
+#if defined(USE_GCC_VISIBILITY_FLAG) && !defined(DllExport)
+#define DllExport CPL_DLL
+#endif
+
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable : 4290 )  /* C++ exception specification ignored except to indicate a function is not __declspec(nothrow)*/
+#endif
+
+#include "libkea/KEACommon.h"
+#include "libkea/KEAImageIO.h"
+#include "libkea/KEAAttributeTable.h"
+#include "libkea/KEAAttributeTableInMem.h"
+
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
+
+
+#endif /* GDAL_LIBKEA_HEADERS_H */
diff --git a/frmts/kmlsuperoverlay/kmlsuperoverlaydataset.cpp b/frmts/kmlsuperoverlay/kmlsuperoverlaydataset.cpp
index 58767b0..4cd6979 100644
--- a/frmts/kmlsuperoverlay/kmlsuperoverlaydataset.cpp
+++ b/frmts/kmlsuperoverlay/kmlsuperoverlaydataset.cpp
@@ -38,10 +38,11 @@
 #include <algorithm>
 #include <fstream>
 
+#include "cpl_conv.h"
 #include "cpl_error.h"
 #include "cpl_string.h"
-#include "cpl_conv.h"
 #include "cpl_vsi.h"
+#include "gdal_frmts.h"
 #include "ogr_spatialref.h"
 #include "../vrt/gdal_vrt.h"
 #include "../vrt/vrtdataset.h"
@@ -51,7 +52,7 @@ using namespace std;
 /************************************************************************/
 /*                           GenerateTiles()                            */
 /************************************************************************/
-void GenerateTiles(std::string filename,
+static void GenerateTiles(std::string filename,
                    CPL_UNUSED int zoom,
                    int rxsize,
                    int rysize,
@@ -72,10 +73,10 @@ void GenerateTiles(std::string filename,
 
     if (isJpegDriver && bands == 4)
         bands = 3;
-   
+
     poTmpDataset = poMemDriver->Create("", dxsize, dysize, bands, GDT_Byte, NULL);
-   
-    if (isJpegDriver == false)//Jpeg dataset only has one or three bands
+
+    if (!isJpegDriver)//Jpeg dataset only has one or three bands
     {
         if (bands < 4)//add transparency to files with one band or three bands
         {
@@ -84,11 +85,11 @@ void GenerateTiles(std::string filename,
         }
     }
 
-    int rowOffset = rysize/dysize;
-    int loopCount = rysize/rowOffset;
+    const int rowOffset = rysize/dysize;
+    const int loopCount = rysize/rowOffset;
     for (int row = 0; row < loopCount; row++)
     {
-        if (isJpegDriver == false)
+        if (!isJpegDriver)
         {
             for (int i = 0; i < dxsize; i++)
             {
@@ -99,36 +100,24 @@ void GenerateTiles(std::string filename,
         for (int band = 1; band <= bands; band++)
         {
             GDALRasterBand* poBand = poSrcDs->GetRasterBand(band);
-
             int hasNoData = 0;
-            bool isSigned = false;
-            double noDataValue = poBand->GetNoDataValue(&hasNoData);
+            const double noDataValue = poBand->GetNoDataValue(&hasNoData);
             const char* pixelType = poBand->GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
-            if (pixelType)
-            {
-                if (strcmp(pixelType, "SIGNEDBYTE") == 0)
-                {
-                    isSigned = true; 
-                }
-            }
+            const bool isSigned = ( pixelType && (strcmp(pixelType, "SIGNEDBYTE") == 0) );
 
             int yOffset = ry + row * rowOffset;
-            bool bReadFailed = false;
-            if (poBand)
-            {
-                CPLErr errTest = 
-                    poBand->RasterIO( GF_Read, rx, yOffset, rxsize, rowOffset, pafScanline, dxsize, 1, GDT_Byte, 0, 0, NULL);
+            CPLErr errTest =
+                poBand->RasterIO( GF_Read, rx, yOffset, rxsize, rowOffset, pafScanline, dxsize, 1, GDT_Byte, 0, 0, NULL);
 
-                if ( errTest == CE_Failure )
-                {
-                    hasNoData = 1;
-                    bReadFailed = true;
-                }
+            const bool bReadFailed = ( errTest == CE_Failure );
+            if ( bReadFailed )
+            {
+                hasNoData = 1;
             }
 
 
             //fill the true or false for hadnoData array if the source data has nodata value
-            if (isJpegDriver == false)
+            if (!isJpegDriver)
             {
                 if (hasNoData == 1)
                 {
@@ -140,7 +129,7 @@ void GenerateTiles(std::string filename,
                         {
                             tmpv -= 128;
                         }
-                        if (tmpv == noDataValue || bReadFailed == true)
+                        if (tmpv == noDataValue || bReadFailed)
                         {
                             hadnoData[j] = true;
                         }
@@ -148,22 +137,22 @@ void GenerateTiles(std::string filename,
                 }
             }
 
-            if (bReadFailed == false)
+            if (!bReadFailed)
             {
                 GDALRasterBand* poBandtmp = poTmpDataset->GetRasterBand(band);
-                poBandtmp->RasterIO(GF_Write, 0, row, dxsize, 1, pafScanline, dxsize, 1, GDT_Byte, 
-                                    0, 0, NULL);
+                CPL_IGNORE_RET_VAL( poBandtmp->RasterIO(GF_Write, 0, row, dxsize, 1, pafScanline, dxsize, 1, GDT_Byte,
+                                    0, 0, NULL) );
             }
-        } 
+        }
 
         //fill the values for alpha band
-        if (isJpegDriver == false)
+        if (!isJpegDriver)
         {
             if (alphaBand)
             {
                 for (int i = 0; i < dxsize; i++)
                 {
-                    if (hadnoData[i] == true)
+                    if (hadnoData[i])
                     {
                         pafScanline[i] = 0;
                     }
@@ -171,10 +160,10 @@ void GenerateTiles(std::string filename,
                     {
                         pafScanline[i] = 255;
                     }
-                }    
+                }
 
-                alphaBand->RasterIO(GF_Write, 0, row, dxsize, 1, pafScanline, dxsize, 1, GDT_Byte, 
-                                    0, 0, NULL);
+                CPL_IGNORE_RET_VAL( alphaBand->RasterIO(GF_Write, 0, row, dxsize, 1, pafScanline, dxsize, 1, GDT_Byte,
+                                    0, 0, NULL) );
             }
         }
     }
@@ -200,12 +189,12 @@ void GenerateTiles(std::string filename,
 /************************************************************************/
 
 static
-int  GenerateRootKml(const char* filename, 
+int  GenerateRootKml(const char* filename,
                      const char* kmlfilename,
-                     double north, 
-                     double south, 
-                     double east, 
-                     double west, 
+                     double north,
+                     double south,
+                     double east,
+                     double west,
                      int tilesize,
                      const char* pszOverlayName,
                      const char* pszOverlayDescription)
@@ -223,7 +212,7 @@ int  GenerateRootKml(const char* filename,
     if( pszOverlayName == NULL )
         pszOverlayName = tmpfilename;
 
-    // If we haven't writen any features yet, output the layer's schema
+    // If we have not written any features yet, output the layer's schema.
     VSIFPrintfL(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
     VSIFPrintfL(fp, "<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n");
     VSIFPrintfL(fp, "\t<Document>\n");
@@ -285,11 +274,11 @@ int  GenerateRootKml(const char* filename,
 /************************************************************************/
 
 static
-int  GenerateChildKml(std::string filename, 
-                      int zoom, int ix, int iy, 
-                      double zoomxpixel, double zoomypixel, int dxsize, int dysize, 
-                      double south, double west, int xsize, 
-                      int ysize, int maxzoom, 
+int  GenerateChildKml(std::string filename,
+                      int zoom, int ix, int iy,
+                      double zoomxpixel, double zoomypixel, int dxsize, int dysize,
+                      double south, double west, int xsize,
+                      int ysize, int maxzoom,
                       OGRCoordinateTransformation * poTransform,
                       std::string fileExt,
                       bool fixAntiMeridian,
@@ -358,7 +347,7 @@ int  GenerateChildKml(std::string filename,
         if (tmp < tmp1)
         {
             ychildern.push_back(iy*2+1);
-        }     
+        }
         maxLodPix = 2048;
     }
 
@@ -490,7 +479,7 @@ int  GenerateChildKml(std::string filename,
     VSIFPrintfL(fp, "\t</Document>\n");
     VSIFPrintfL(fp, "</kml>\n");
     VSIFCloseL(fp);
-    
+
     return TRUE;
 }
 
@@ -520,7 +509,7 @@ GDALDataset *KmlSuperOverlayCreateCopy( const char * pszFilename,
     int bands = poSrcDS->GetRasterCount();
     if (bands != 1 && bands != 3 && bands != 4)
         return NULL;
-   
+
     //correct the file and get the directory
     char* output_dir = NULL;
     if (pszFilename == NULL)
@@ -541,7 +530,7 @@ GDALDataset *KmlSuperOverlayCreateCopy( const char * pszFilename,
         {
             isKmz = true;
         }
-    
+
         output_dir = CPLStrdup(CPLGetPath(pszFilename));
         if (strcmp(output_dir, "") == 0)
         {
@@ -612,16 +601,16 @@ GDALDataset *KmlSuperOverlayCreateCopy( const char * pszFilename,
     if (poSrcDS->GetProjectionRef() != NULL)
     {
         OGRSpatialReference poDsUTM;
-     
+
         char* projStr = (char*)poSrcDS->GetProjectionRef();
-     
+
         if (poDsUTM.importFromWkt(&projStr) == OGRERR_NONE)
         {
             if (poDsUTM.IsProjected())
             {
                 OGRSpatialReference poLatLong;
                 poLatLong.SetWellKnownGeogCS( "WGS84" );
-           
+
                 poTransform = OGRCreateCoordinateTransformation( &poDsUTM, &poLatLong );
                 if( poTransform != NULL )
                 {
@@ -632,7 +621,7 @@ GDALDataset *KmlSuperOverlayCreateCopy( const char * pszFilename,
         }
     }
 
-    bool fixAntiMeridian = CSLFetchBoolean( papszOptions, "FIX_ANTIMERIDIAN", FALSE );
+    bool fixAntiMeridian = CPL_TO_BOOL(CSLFetchBoolean( papszOptions, "FIX_ANTIMERIDIAN", FALSE ));
     if ( fixAntiMeridian && east < west )
     {
         east += 360;
@@ -676,7 +665,7 @@ GDALDataset *KmlSuperOverlayCreateCopy( const char * pszFilename,
         zoomypixels.push_back(fabs(adfGeoTransform[5]) * pow(2.0, (maxzoom - zoom)));
     }
 
-    std::string tmpFileName; 
+    std::string tmpFileName;
     std::vector<std::string> fileVector;
     int nRet;
 
@@ -697,7 +686,7 @@ GDALDataset *KmlSuperOverlayCreateCopy( const char * pszFilename,
                                north, south, east, west, (int)tilexsize,
                                pszOverlayName, pszOverlayDescription);
     }
-    
+
     if (nRet == FALSE)
     {
         OGRCoordinateTransformation::DestroyCT( poTransform );
@@ -766,7 +755,7 @@ GDALDataset *KmlSuperOverlayCreateCopy( const char * pszFilename,
 
         xloop = xloop>0 ? xloop : 1;
         yloop = yloop>0 ? yloop : 1;
-        
+
         std::stringstream zoomStr;
         zoomStr << zoom;
 
@@ -808,7 +797,7 @@ GDALDataset *KmlSuperOverlayCreateCopy( const char * pszFilename,
                     fileVector.push_back(filename);
                 }
 
-                GenerateTiles(filename, zoom, rxsize, rysize, ix, iy, rx, ry, dxsize, 
+                GenerateTiles(filename, zoom, rxsize, rysize, ix, iy, rx, ry, dxsize,
                               dysize, bands, poSrcDS, poOutputTileDriver, poMemDriver, isJpegDriver);
                 std::string childKmlfile = zoomDir + "/" + iyStr.str() + ".kml";
                 if (isKmz)
@@ -829,7 +818,7 @@ GDALDataset *KmlSuperOverlayCreateCopy( const char * pszFilename,
                     zoomypix = 1;
                 }
 
-                GenerateChildKml(childKmlfile, zoom, ix, iy, zoomxpix, zoomypix, 
+                GenerateChildKml(childKmlfile, zoom, ix, iy, zoomxpix, zoomypix,
                                  dxsize, dysize, tmpSouth, adfGeoTransform[0],
                                  xsize, ysize, maxzoom, poTransform, fileExt, fixAntiMeridian,
                                  pszAltitude, pszAltitudeMode);
@@ -865,7 +854,7 @@ static CPLString KMLRemoveSlash(const char* pszPathIn)
 {
     char* pszPath = CPLStrdup(pszPathIn);
 
-    while(TRUE)
+    while( true )
     {
         char* pszSlashDotDot = strstr(pszPath, "/../");
         if (pszSlashDotDot == NULL || pszSlashDotDot == pszPath)
@@ -931,9 +920,9 @@ int KmlSuperOverlayReadDataset::CloseDependentDatasets()
     int bRet = FALSE;
     if( poDSIcon != NULL )
     {
-        CPLString osFilename(poDSIcon->GetDescription());
+        CPLString l_osFilename(poDSIcon->GetDescription());
         delete poDSIcon;
-        VSIUnlink(osFilename);
+        VSIUnlink(l_osFilename);
         poDSIcon = NULL;
         bRet = TRUE;
     }
@@ -992,11 +981,11 @@ CPLErr KmlSuperOverlayReadDataset::GetGeoTransform( double * padfGeoTransform )
 /*                        KmlSuperOverlayRasterBand()                   */
 /************************************************************************/
 
-KmlSuperOverlayRasterBand::KmlSuperOverlayRasterBand(KmlSuperOverlayReadDataset* poDS,
-                                                     CPL_UNUSED int nBand)
+KmlSuperOverlayRasterBand::KmlSuperOverlayRasterBand(KmlSuperOverlayReadDataset* poDSIn,
+                                                     int)
 {
-    nRasterXSize = poDS->nRasterXSize;
-    nRasterYSize = poDS->nRasterYSize;
+    nRasterXSize = poDSIn->nRasterXSize;
+    nRasterYSize = poDSIn->nRasterYSize;
     eDataType = GDT_Byte;
     nBlockXSize = 256;
     nBlockYSize = 256;
@@ -1016,7 +1005,7 @@ CPLErr KmlSuperOverlayRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff, vo
         nXSize = nRasterXSize - nXOff;
     if( nYOff + nYSize > nRasterYSize )
         nYSize = nRasterYSize - nYOff;
-    
+
     GDALRasterIOExtraArg sExtraArg;
     INIT_RASTERIO_EXTRA_ARG(sExtraArg);
 
@@ -1099,14 +1088,14 @@ int KmlSuperOverlayGetBoundingBox(CPLXMLNode* psNode, double* adfExtents)
         psBox = CPLGetXMLNode(psNode, "LatLonAltBox");
     if( psBox == NULL )
         return FALSE;
-    
+
     const char* pszNorth = CPLGetXMLValue(psBox, "north", NULL);
     const char* pszSouth = CPLGetXMLValue(psBox, "south", NULL);
     const char* pszEast = CPLGetXMLValue(psBox, "east", NULL);
     const char* pszWest = CPLGetXMLValue(psBox, "west", NULL);
     if( pszNorth == NULL || pszSouth == NULL || pszEast == NULL || pszWest == NULL )
         return FALSE;
-    
+
     adfExtents[0] = CPLAtof(pszWest);
     adfExtents[1] = CPLAtof(pszSouth);
     adfExtents[2] = CPLAtof(pszEast);
@@ -1128,7 +1117,7 @@ class SubImageDesc
 CPLErr KmlSuperOverlayReadDataset::IRasterIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
                                void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType, 
+                               GDALDataType eBufType,
                                int nBandCount, int *panBandMap,
                                GSpacing nPixelSpace, GSpacing nLineSpace,
                                GSpacing nBandSpace,
@@ -1155,7 +1144,7 @@ CPLErr KmlSuperOverlayReadDataset::IRasterIO( GDALRWFlag eRWFlag,
                                     nXSize * nOvrFactor,
                                     nYSize * nOvrFactor,
                                     pData, nBufXSize, nBufYSize,
-                                    eBufType, 
+                                    eBufType,
                                     nBandCount, panBandMap,
                                     nPixelSpace, nLineSpace, nBandSpace, &sExtraArgs);
     }
@@ -1198,13 +1187,13 @@ CPLErr KmlSuperOverlayReadDataset::IRasterIO( GDALRWFlag eRWFlag,
                     dfRequestYMin < adfExtents[3] && dfRequestYMax > adfExtents[1] )
                 {
                     CPLString osSubFilename;
-                    if( strncmp(pszHref, "http", 4) == 0)
+                    if( STARTS_WITH(pszHref, "http"))
                         osSubFilename = CPLSPrintf("/vsicurl_streaming/%s", pszHref);
                     else
                     {
                         const char* pszBaseFilename = osFilename.c_str();
                         if( EQUAL(CPLGetExtension(pszBaseFilename), "kmz") &&
-                            strncmp(pszBaseFilename, "/vsizip/", 8) != 0 )
+                            !STARTS_WITH(pszBaseFilename, "/vsizip/") )
                         {
                             osSubFilename = "/vsizip/";
                             osSubFilename += CPLGetPath(pszBaseFilename);
@@ -1222,68 +1211,69 @@ CPLErr KmlSuperOverlayReadDataset::IRasterIO( GDALRWFlag eRWFlag,
                     if( EQUAL(CPLGetExtension(osSubFilename), "kml") )
                     {
                         KmlSuperOverlayReadDataset* poRoot = poParent ? poParent : this;
-                        LinkedDataset* psLink = poRoot->oMapChildren[osSubFilename];
-                        if( psLink == NULL )
+                        LinkedDataset* psLinkDS = poRoot->oMapChildren[osSubFilename];
+                        if( psLinkDS == NULL )
                         {
                             if( poRoot->oMapChildren.size() == 64 )
                             {
-                                psLink = poRoot->psLastLink;
-                                CPLAssert(psLink);
-                                poRoot->oMapChildren.erase(psLink->osSubFilename);
-                                GDALClose(psLink->poDS);
-                                if( psLink->psPrev != NULL )
+                                psLinkDS = poRoot->psLastLink;
+                                CPLAssert(psLinkDS);
+                                poRoot->oMapChildren.erase(psLinkDS->osSubFilename);
+                                GDALClose(psLinkDS->poDS);
+                                if( psLinkDS->psPrev != NULL )
                                 {
-                                    poRoot->psLastLink = psLink->psPrev;
-                                    psLink->psPrev->psNext = NULL;
+                                    poRoot->psLastLink = psLinkDS->psPrev;
+                                    psLinkDS->psPrev->psNext = NULL;
                                 }
                                 else
                                 {
-                                    CPLAssert(psLink == poRoot->psFirstLink);
+                                    CPLAssert(psLinkDS == poRoot->psFirstLink);
                                     poRoot->psFirstLink = poRoot->psLastLink = NULL;
                                 }
                             }
                             else
-                                psLink = new LinkedDataset();
+                                psLinkDS = new LinkedDataset();
 
-                            poRoot->oMapChildren[osSubFilename] = psLink;
+                            poRoot->oMapChildren[osSubFilename] = psLinkDS;
                             poSubImageDS = (KmlSuperOverlayReadDataset*)
                                 KmlSuperOverlayReadDataset::Open(osSubFilename, poRoot);
                             if( poSubImageDS )
                                 poSubImageDS->MarkAsShared();
                             else
-                                CPLDebug("KMLSuperOverlay", "Cannt open %s", osSubFilename.c_str());
-                            psLink->osSubFilename = osSubFilename;
-                            psLink->poDS = poSubImageDS;
-                            psLink->psPrev = NULL;
-                            psLink->psNext = poRoot->psFirstLink;
+                                CPLDebug( "KMLSuperOverlay", "Cannot open %s",
+                                          osSubFilename.c_str() );
+                            psLinkDS->osSubFilename = osSubFilename;
+                            psLinkDS->poDS = poSubImageDS;
+                            psLinkDS->psPrev = NULL;
+                            psLinkDS->psNext = poRoot->psFirstLink;
                             if( poRoot->psFirstLink != NULL )
                             {
                                 CPLAssert(poRoot->psFirstLink->psPrev == NULL);
-                                poRoot->psFirstLink->psPrev = psLink;
+                                poRoot->psFirstLink->psPrev = psLinkDS;
                             }
                             else
-                                poRoot->psLastLink = psLink;
-                            poRoot->psFirstLink = psLink;
+                                poRoot->psLastLink = psLinkDS;
+                            poRoot->psFirstLink = psLinkDS;
                         }
                         else
                         {
-                            poSubImageDS = psLink->poDS;
-                            if( psLink != poRoot->psFirstLink )
+                            poSubImageDS = psLinkDS->poDS;
+                            if( psLinkDS != poRoot->psFirstLink )
                             {
-                                if( psLink == poRoot->psLastLink )
+                                if( psLinkDS == poRoot->psLastLink )
                                 {
-                                    poRoot->psLastLink = psLink->psPrev;
+                                    poRoot->psLastLink = psLinkDS->psPrev;
                                     CPLAssert(poRoot->psLastLink != NULL );
                                     poRoot->psLastLink->psNext = NULL;
                                 }
                                 else
-                                    psLink->psNext->psPrev = psLink->psPrev;
-                                CPLAssert( psLink->psPrev != NULL );
-                                psLink->psPrev->psNext = psLink->psNext;
-                                psLink->psPrev = NULL;
-                                poRoot->psFirstLink->psPrev = psLink;
-                                psLink->psNext = poRoot->psFirstLink;
-                                poRoot->psFirstLink = psLink;
+                                    psLinkDS->psNext->psPrev = psLinkDS->psPrev;
+                                CPLAssert( psLinkDS->psPrev != NULL );
+                                psLinkDS->psPrev->psNext = psLinkDS->psNext;
+                                psLinkDS->psPrev = NULL;
+                                poRoot->psFirstLink->psPrev = psLinkDS;
+                                psLinkDS->psNext = poRoot->psFirstLink;
+                                poRoot->psFirstLink = psLinkDS;
                             }
                         }
                     }
@@ -1422,8 +1412,9 @@ CPLErr KmlSuperOverlayReadDataset::IRasterIO( GDALRWFlag eRWFlag,
 
     GDALProgressFunc  pfnProgressGlobal = psExtraArg->pfnProgress;
     void             *pProgressDataGlobal = psExtraArg->pProgressData;
+    CPLErr eErr = CE_None;
 
-    for(int iBandIdx = 0; iBandIdx < nBandCount; iBandIdx++ )
+    for(int iBandIdx = 0; iBandIdx < nBandCount && eErr == CE_None; iBandIdx++ )
     {
         int nBand = panBandMap[iBandIdx];
 
@@ -1433,7 +1424,8 @@ CPLErr KmlSuperOverlayReadDataset::IRasterIO( GDALRWFlag eRWFlag,
             for(int j = 0; j < nBufYSize; j ++ )
             {
                 GDALCopyWords( &nVal, GDT_Byte, 0,
-                            ((GByte*) pData) + j * nLineSpace + iBandIdx * nBandSpace, eBufType, nPixelSpace,
+                            ((GByte*) pData) + j * nLineSpace + iBandIdx * nBandSpace, eBufType,
+                            static_cast<int>(nPixelSpace),
                             nBufXSize );
             }
             continue;
@@ -1454,13 +1446,13 @@ CPLErr KmlSuperOverlayReadDataset::IRasterIO( GDALRWFlag eRWFlag,
         INIT_RASTERIO_EXTRA_ARG(sExtraArgs);
         sExtraArgs.eResampleAlg = psExtraArg->eResampleAlg;
         sExtraArgs.pfnProgress = GDALScaledProgress;
-        sExtraArgs.pProgressData = 
+        sExtraArgs.pProgressData =
             GDALCreateScaledProgress( 1.0 * iBandIdx / nBandCount,
                                       1.0 * (iBandIdx + 1) / nBandCount,
                                       pfnProgressGlobal,
                                       pProgressDataGlobal );
 
-        poDSIcon->GetRasterBand(nIconBand)->RasterIO( eRWFlag,
+        eErr = poDSIcon->GetRasterBand(nIconBand)->RasterIO( eRWFlag,
                                                       nReqXOff,
                                                       nReqYOff,
                                                       nReqXSize,
@@ -1476,7 +1468,7 @@ CPLErr KmlSuperOverlayReadDataset::IRasterIO( GDALRWFlag eRWFlag,
     psExtraArg->pfnProgress = pfnProgressGlobal;
     psExtraArg->pProgressData = pProgressDataGlobal;
 
-    return CE_None;
+    return eErr;
 
 }
 
@@ -1502,7 +1494,8 @@ int KmlSuperOverlayFindRegionStartInternal(CPLXMLNode* psNode,
         *ppsLink = psLink;
         return TRUE;
     }
-    if( strcmp(psNode->pszValue, "Document") == 0 &&
+    if( (strcmp(psNode->pszValue, "Document") == 0 ||
+         strcmp(psNode->pszValue, "Folder") == 0) &&
         (psRegion = CPLGetXMLNode(psNode, "Region")) != NULL &&
         (psGroundOverlay = CPLGetXMLNode(psNode, "GroundOverlay")) != NULL )
     {
@@ -1567,14 +1560,14 @@ int KmlSuperOverlayReadDataset::Identify(GDALOpenInfo * poOpenInfo)
     if( !EQUAL(pszExt, "kml") ||
         strstr((const char*)poOpenInfo->pabyHeader, "<kml") == NULL )
         return FALSE;
-    
+
     for( int i=0;i<2;i++ )
     {
         if( strstr((const char*)poOpenInfo->pabyHeader, "<NetworkLink>") != NULL &&
             strstr((const char*)poOpenInfo->pabyHeader, "<Region>") != NULL &&
             strstr((const char*)poOpenInfo->pabyHeader, "<Link>") != NULL )
             return TRUE;
-        
+
         if( strstr((const char*)poOpenInfo->pabyHeader, "<Document>") != NULL &&
             strstr((const char*)poOpenInfo->pabyHeader, "<Region>") != NULL &&
             strstr((const char*)poOpenInfo->pabyHeader, "<GroundOverlay>") != NULL )
@@ -1583,7 +1576,7 @@ int KmlSuperOverlayReadDataset::Identify(GDALOpenInfo * poOpenInfo)
         if( i == 0 && !poOpenInfo->TryToIngest(1024*10) )
             return FALSE;
     }
-    
+
     return -1;
 }
 
@@ -1616,7 +1609,7 @@ GDALDataset* KmlSuperOverlayLoadIcon(const char* pszBaseFilename, const char* ps
     }
 
     CPLString osSubFilename;
-    if( strncmp(pszIcon, "http", 4) == 0)
+    if( STARTS_WITH(pszIcon, "http"))
         osSubFilename = CPLSPrintf("/vsicurl_streaming/%s", pszIcon);
     else
     {
@@ -1679,7 +1672,7 @@ static void KmlSuperOverlayComputeDepth(CPLString osFilename,
             if( EQUAL(pszExt, "kml") )
             {
                 CPLString osSubFilename;
-                if( strncmp(pszHref, "http", 4) == 0)
+                if( STARTS_WITH(pszHref, "http"))
                     osSubFilename = CPLSPrintf("/vsicurl_streaming/%s", pszHref);
                 else
                 {
@@ -1943,13 +1936,13 @@ void KmlSingleDocRasterDataset::BuildOverviews()
 /*                      KmlSingleDocRasterRasterBand()                  */
 /************************************************************************/
 
-KmlSingleDocRasterRasterBand::KmlSingleDocRasterRasterBand(KmlSingleDocRasterDataset* poDS,
-                                                           int nBand)
+KmlSingleDocRasterRasterBand::KmlSingleDocRasterRasterBand(KmlSingleDocRasterDataset* poDSIn,
+                                                           int nBandIn)
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
-    nBlockXSize = poDS->nTileSize;
-    nBlockYSize = poDS->nTileSize;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
+    nBlockXSize = poDSIn->nTileSize;
+    nBlockYSize = poDSIn->nTileSize;
     eDataType = GDT_Byte;
 }
 
@@ -1963,7 +1956,7 @@ CPLErr KmlSingleDocRasterRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     KmlSingleDocRasterDataset* poGDS = (KmlSingleDocRasterDataset*) poDS;
     const char* pszImageFilename = CPLFormFilename( poGDS->osDirname,
         CPLSPrintf("kml_image_L%d_%d_%d", poGDS->nLevel, nBlockYOff, nBlockXOff), poGDS->osNominalExt );
-    if( poGDS->poCurTileDS == NULL || 
+    if( poGDS->poCurTileDS == NULL ||
         strcmp(CPLGetFilename(poGDS->poCurTileDS->GetDescription()),
                CPLGetFilename(pszImageFilename)) != 0 )
     {
@@ -2026,13 +2019,13 @@ CPLErr KmlSingleDocRasterRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                         if( poEntry != NULL )
                         {
                             if( nBand == 1 )
-                                ((GByte*) pImage)[j * nBlockXSize + i] = poEntry->c1;
+                                ((GByte*) pImage)[j * nBlockXSize + i] = static_cast<GByte>(poEntry->c1);
                             else if( nBand == 2 )
-                                ((GByte*) pImage)[j * nBlockXSize + i] = poEntry->c2;
+                                ((GByte*) pImage)[j * nBlockXSize + i] = static_cast<GByte>(poEntry->c2);
                             else if( nBand == 3 )
-                                ((GByte*) pImage)[j * nBlockXSize + i] = poEntry->c3;
+                                ((GByte*) pImage)[j * nBlockXSize + i] = static_cast<GByte>(poEntry->c3);
                             else
-                                ((GByte*) pImage)[j * nBlockXSize + i] = poEntry->c4;
+                                ((GByte*) pImage)[j * nBlockXSize + i] = static_cast<GByte>(poEntry->c4);
                         }
                     }
                 }
@@ -2126,7 +2119,7 @@ static void KmlSingleDocCollectTiles(CPLXMLNode* psNode,
         int level, j, i;
         char szExt[4];
         const char* pszHref = CPLGetXMLValue(psNode, "", "");
-        if( strncmp(pszHref, "http", 4) == 0 )
+        if( STARTS_WITH(pszHref, "http") )
         {
             osURLBase = CPLGetPath(pszHref);
         }
@@ -2289,9 +2282,9 @@ GDALDataset *KmlSuperOverlayReadDataset::Open(const char* pszFilename,
     const char* pszExt = CPLGetExtension(pszFilename);
     if( EQUAL(pszExt, "kmz") )
     {
-        if( strncmp(pszFilename, "/vsizip/", 8) != 0 )
+        if( !STARTS_WITH(pszFilename, "/vsizip/") )
             osFilename = CPLSPrintf("/vsizip/%s", pszFilename);
-        char** papszFiles = CPLReadDir(osFilename);
+        char** papszFiles = VSIReadDir(osFilename);
         if( papszFiles == NULL )
             return NULL;
         char** papszIter = papszFiles;
@@ -2325,6 +2318,15 @@ GDALDataset *KmlSuperOverlayReadDataset::Open(const char* pszFilename,
     if( psNode == NULL )
         return NULL;
 
+    GDALDataset* psSingleDocDS = KmlSingleDocRasterDataset::Open(pszFilename,
+                                                                 osFilename,
+                                                                 psNode);
+    if( psSingleDocDS != NULL )
+    {
+        CPLDestroyXMLNode(psNode);
+        return psSingleDocDS;
+    }
+
     CPLXMLNode* psRegion = NULL;
     CPLXMLNode* psDocument = NULL;
     CPLXMLNode* psGroundOverlay = NULL;
@@ -2332,11 +2334,8 @@ GDALDataset *KmlSuperOverlayReadDataset::Open(const char* pszFilename,
     if( !KmlSuperOverlayFindRegionStart(psNode, &psRegion,
                                         &psDocument, &psGroundOverlay, &psLink) )
     {
-        GDALDataset* psDS = KmlSingleDocRasterDataset::Open(pszFilename,
-                                                            osFilename,
-                                                            psNode);
         CPLDestroyXMLNode(psNode);
-        return psDS;
+        return NULL;
     }
 
     if( psLink != NULL )
@@ -2349,7 +2348,7 @@ GDALDataset *KmlSuperOverlayReadDataset::Open(const char* pszFilename,
         }
 
         CPLString osSubFilename;
-        if( strncmp(pszHref, "http", 4) == 0)
+        if( STARTS_WITH(pszHref, "http"))
             osSubFilename = CPLSPrintf("/vsicurl_streaming/%s", pszHref);
         else
         {
@@ -2491,23 +2490,22 @@ static CPLErr KmlSuperOverlayDatasetDelete(CPL_UNUSED const char* fileName)
 /*                    GDALRegister_KMLSUPEROVERLAY()                    */
 /************************************************************************/
 
-void GDALRegister_KMLSUPEROVERLAY()
-   
+void CPL_DLL GDALRegister_KMLSUPEROVERLAY()
+
 {
-    GDALDriver	*poDriver;
-   
-    if( GDALGetDriverByName( "KMLSUPEROVERLAY" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-      
-        poDriver->SetDescription( "KMLSUPEROVERLAY" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Kml Super Overlay" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte Int16 UInt16 Int32 UInt32 Float32 Float64 CInt16 CInt32 CFloat32 CFloat64" );
-
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    if( GDALGetDriverByName( "KMLSUPEROVERLAY" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "KMLSUPEROVERLAY" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Kml Super Overlay" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte Int16 UInt16 Int32 UInt32 Float32 Float64 "
+                               "CInt16 CInt32 CFloat32 CFloat64" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "   <Option name='NAME' type='string' description='Overlay name'/>"
 "   <Option name='DESCRIPTION' type='string' description='Overlay description'/>"
@@ -2525,13 +2523,12 @@ void GDALRegister_KMLSUPEROVERLAY()
 "   <Option name='FIX_ANTIMERIDIAN' type='boolean' description='Fix for images crossing the antimeridian causing errors in Google Earth' />"
 "</CreationOptionList>" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnIdentify = KmlSuperOverlayReadDataset::Identify;
-        poDriver->pfnOpen = KmlSuperOverlayReadDataset::Open;
-        poDriver->pfnCreateCopy = KmlSuperOverlayCreateCopy;
-        poDriver->pfnDelete = KmlSuperOverlayDatasetDelete;
-      
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    poDriver->pfnIdentify = KmlSuperOverlayReadDataset::Identify;
+    poDriver->pfnOpen = KmlSuperOverlayReadDataset::Open;
+    poDriver->pfnCreateCopy = KmlSuperOverlayCreateCopy;
+    poDriver->pfnDelete = KmlSuperOverlayDatasetDelete;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/kmlsuperoverlay/kmlsuperoverlaydataset.h b/frmts/kmlsuperoverlay/kmlsuperoverlaydataset.h
index 724c8b8..b5c0d80 100644
--- a/frmts/kmlsuperoverlay/kmlsuperoverlaydataset.h
+++ b/frmts/kmlsuperoverlay/kmlsuperoverlaydataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: kmlsuperoverlaydataset.h 
+ * $Id: kmlsuperoverlaydataset.h
  *
  * Project:  KmlSuperOverlay
  * Purpose:  Implements write support for KML superoverlay - KMZ.
@@ -27,7 +27,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
- 
+
 #ifndef KMLSUPEROVERLAYDATASET_H_INCLUDED
 #define KMLSUPEROVERLAYDATASET_H_INCLUDED
 
@@ -37,7 +37,7 @@
 #include <map>
 
 CPL_C_START
-void CPL_DLL GDALRegister_KMLSUPEROVERLAY(void);
+void CPL_DLL GDALRegister_KMLSUPEROVERLAY();
 CPL_C_END
 
 /************************************************************************/
@@ -90,11 +90,11 @@ class KmlSuperOverlayReadDataset : public GDALDataset
 
     virtual CPLErr GetGeoTransform( double * );
     virtual const char *GetProjectionRef();
-    
+
     virtual CPLErr IRasterIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
                                void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType, 
+                               GDALDataType eBufType,
                                int nBandCount, int *panBandMap,
                                GSpacing nPixelSpace, GSpacing nLineSpace,
                                GSpacing nBandSpace,
@@ -123,4 +123,3 @@ class KmlSuperOverlayRasterBand: public GDALRasterBand
 };
 
 #endif /* ndef KMLSUPEROVERLAYDATASET_H_INCLUDED */
-
diff --git a/frmts/l1b/frmt_l1b.html b/frmts/l1b/frmt_l1b.html
index 95da65d..b3dd03e 100644
--- a/frmts/l1b/frmt_l1b.html
+++ b/frmts/l1b/frmt_l1b.html
@@ -9,7 +9,7 @@
 
 GDAL supports NOAA Polar Orbiter Level 1b Data Set format for reading. Now it can
 read NOAA-9(F) --- NOAA-17(M) datasets. NOTE: only AVHRR instrument supported
-now, if you want read data from other instruments, write to me (Andrey Kiselev, 
+now, if you want read data from other instruments, write to me (Andrey Kiselev,
 <a href=mailto:dron at ak4719.spb.edu>dron at ak4719.spb.edu</a>). AVHRR
 LAC/HRPT (1 km resolution) and GAC (4 km resolution) should be processed
 correctly.
@@ -129,7 +129,7 @@ dataset. The values of each pixel are 0 = unknown; 1 = clear; 2 = cloudy; 3 = pa
 NOAA >=15 datasets that report in their header to have missing scan lines
 will expose a per-dataset mask band (following
 <a href="https://trac.osgeo.org/gdal/wiki/rfc15_nodatabitmask">RFC 15: Band Masks</a>)
-to indicate such scan lines. 
+to indicate such scan lines.
 
 <h2>See Also:</h2>
 
@@ -143,12 +143,17 @@ Guide'' (TIROS-N -- NOAA-14 satellites) and in the ``NOAA KLM User's Guide''
 NOAA Technical Documentation Introduction Page
 </a><p>
 
+<li> There are a great variety of L1B datasets, sometimes with variations in
+header locations that are not documented in the official NOAA documentation. In
+case a dataset is not recognized by the GDAL L1B driver, the <a href="http://www.pytroll.org/">pytroll</a> package
+might be able to recognize it.<p>
+
 <li>  Excellent and complete review contained in the printed book ``The
 Advanced Very High Resolution Radiometer (AVHRR)'' by Arthur P. Cracknell,
 Taylor and Francis Ltd., 1997, ISBN 0-7484-0209-8.
 </a><p>
 
-<li> NOAA data can be downloaded from the 
+<li> NOAA data can be downloaded from the
 <a href="http://www.class.noaa.gov/">Comprehensive Large Array-data Stewardship System (CLASS)</a>
 (former SAA). Actually it is only source of Level 1b datasets for me, so my implementation
 tested with that files only. <p>
diff --git a/frmts/l1b/l1bdataset.cpp b/frmts/l1b/l1bdataset.cpp
index 3988acb..e246f6e 100644
--- a/frmts/l1b/l1bdataset.cpp
+++ b/frmts/l1b/l1bdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: l1bdataset.cpp 29330 2015-06-14 12:11:11Z rouault $
+ * $Id: l1bdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  NOAA Polar Orbiter Level 1b Dataset Reader (AVHRR)
  * Purpose:  Can read NOAA-9(F)-NOAA-17(M) AVHRR datasets
@@ -34,15 +34,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: l1bdataset.cpp 29330 2015-06-14 12:11:11Z rouault $");
-
-CPL_C_START
-void    GDALRegister_L1B(void);
-CPL_C_END
+CPL_CVSID("$Id: l1bdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 typedef enum {                  // File formats
     L1B_NONE,           // Not a L1B format
@@ -118,7 +115,7 @@ typedef enum {          // AVHRR Earth location indication
 /*                      AVHRR band widths                               */
 /************************************************************************/
 
-static const char *apszBandDesc[] =
+static const char * const apszBandDesc[] =
 {
     // NOAA-7 -- METOP-2 channels
     "AVHRR Channel 1:  0.58  micrometers -- 0.68 micrometers",
@@ -201,6 +198,8 @@ class TimeCode {
     char        pszString[L1B_TIMECODE_LENGTH];
 
   public:
+    TimeCode() : lYear(0), lDay(0), lMillisecond(0) {}
+
     void SetYear(long year)
     {
         lYear = year;
@@ -289,7 +288,7 @@ class L1BDataset : public GDALPamDataset
     int         bGuessDataFormat;
 
     int         bByteSwap;
-    
+
     int             bExposeMaskBand;
     GDALRasterBand* poMaskBand;
 
@@ -301,7 +300,7 @@ class L1BDataset : public GDALPamDataset
                                int *peLocationIndicator );
     CPLErr      ProcessDatasetHeader(const char* pszFilename);
     int         ComputeFileOffsets();
-    
+
     void        FetchMetadata();
     void        FetchMetadataNOAA15();
 
@@ -318,7 +317,7 @@ class L1BDataset : public GDALPamDataset
   public:
                 L1BDataset( L1BFileFormat );
                 ~L1BDataset();
-    
+
     virtual int GetGCPCount();
     virtual const char *GetGCPProjection();
     virtual const GDAL_GCP *GetGCPs();
@@ -341,7 +340,7 @@ class L1BRasterBand : public GDALPamRasterBand
   public:
 
                 L1BRasterBand( L1BDataset *, int );
-    
+
 //    virtual double GetNoDataValue( int *pbSuccess = NULL );
     virtual CPLErr IReadBlock( int, int, void * );
     virtual GDALRasterBand *GetMaskBand();
@@ -361,7 +360,7 @@ class L1BMaskBand: public GDALPamRasterBand
   public:
 
                 L1BMaskBand( L1BDataset * );
-    
+
     virtual CPLErr IReadBlock( int, int, void * );
 };
 
@@ -369,12 +368,12 @@ class L1BMaskBand: public GDALPamRasterBand
 /*                            L1BMaskBand()                             */
 /************************************************************************/
 
-L1BMaskBand::L1BMaskBand( L1BDataset *poDS )
+L1BMaskBand::L1BMaskBand( L1BDataset *poDSIn )
 {
-    CPLAssert(poDS->eL1BFormat == L1B_NOAA15 ||
-              poDS->eL1BFormat == L1B_NOAA15_NOHDR);
+    CPLAssert(poDSIn->eL1BFormat == L1B_NOAA15 ||
+              poDSIn->eL1BFormat == L1B_NOAA15_NOHDR);
 
-    this->poDS = poDS;
+    this->poDS = poDSIn;
     eDataType = GDT_Byte;
 
     nRasterXSize = poDS->GetRasterXSize();
@@ -393,10 +392,10 @@ CPLErr L1BMaskBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 {
     L1BDataset  *poGDS = (L1BDataset *) poDS;
 
-    VSIFSeekL( poGDS->fp, poGDS->GetLineOffset(nBlockYOff) + 24, SEEK_SET );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( poGDS->fp, poGDS->GetLineOffset(nBlockYOff) + 24, SEEK_SET ));
 
     GByte abyData[4];
-    VSIFReadL( abyData, 1, 4, poGDS->fp );
+    CPL_IGNORE_RET_VAL(VSIFReadL( abyData, 1, 4, poGDS->fp ));
     GUInt32 n32 = poGDS->GetUInt32(abyData);
 
     if( (n32 >> 31) != 0 ) /* fatal flag */
@@ -411,11 +410,11 @@ CPLErr L1BMaskBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /*                           L1BRasterBand()                            */
 /************************************************************************/
 
-L1BRasterBand::L1BRasterBand( L1BDataset *poDS, int nBand )
+L1BRasterBand::L1BRasterBand( L1BDataset *poDSIn, int nBandIn )
 
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
     eDataType = GDT_UInt16;
 
     nBlockXSize = poDS->GetRasterXSize();
@@ -459,7 +458,7 @@ CPLErr L1BRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /* -------------------------------------------------------------------- */
 /*      Seek to data.                                                   */
 /* -------------------------------------------------------------------- */
-    VSIFSeekL( poGDS->fp, poGDS->GetLineOffset(nBlockYOff), SEEK_SET );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( poGDS->fp, poGDS->GetLineOffset(nBlockYOff), SEEK_SET ));
 
 /* -------------------------------------------------------------------- */
 /*      Read data into the buffer.                                      */
@@ -473,7 +472,7 @@ CPLErr L1BRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
             {
                 // Read packed scanline
                 GUInt32 *iRawScan = (GUInt32 *)CPLMalloc(poGDS->nRecordSize);
-                VSIFReadL( iRawScan, 1, poGDS->nRecordSize, poGDS->fp );
+                CPL_IGNORE_RET_VAL(VSIFReadL( iRawScan, 1, poGDS->nRecordSize, poGDS->fp ));
 
                 iScan = (GUInt16 *)CPLMalloc(poGDS->nBufferSize);
                 j = 0;
@@ -495,7 +494,7 @@ CPLErr L1BRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
             {
                 // Read unpacked scanline
                 GUInt16 *iRawScan = (GUInt16 *)CPLMalloc(poGDS->nRecordSize);
-                VSIFReadL( iRawScan, 1, poGDS->nRecordSize, poGDS->fp );
+                CPL_IGNORE_RET_VAL(VSIFReadL( iRawScan, 1, poGDS->nRecordSize, poGDS->fp ));
 
                 iScan = (GUInt16 *)CPLMalloc(poGDS->GetRasterXSize()
                                              * poGDS->nBands * sizeof(GUInt16));
@@ -511,8 +510,8 @@ CPLErr L1BRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
             {
                 // Read 8-bit unpacked scanline
                 GByte   *byRawScan = (GByte *)CPLMalloc(poGDS->nRecordSize);
-                VSIFReadL( byRawScan, 1, poGDS->nRecordSize, poGDS->fp );
-                
+                CPL_IGNORE_RET_VAL(VSIFReadL( byRawScan, 1, poGDS->nRecordSize, poGDS->fp ));
+
                 iScan = (GUInt16 *)CPLMalloc(poGDS->GetRasterXSize()
                                              * poGDS->nBands * sizeof(GUInt16));
                 for (i = 0; i < poGDS->GetRasterXSize() * poGDS->nBands; i++)
@@ -524,7 +523,7 @@ CPLErr L1BRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
         default: // NOTREACHED
             break;
     }
-    
+
     int nBlockSize = nBlockXSize * nBlockYSize;
     if (poGDS->eLocationIndicator == DESCEND)
     {
@@ -542,7 +541,7 @@ CPLErr L1BRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
             j += poGDS->nBands;
         }
     }
-    
+
     CPLFree(iScan);
     return CE_None;
 }
@@ -551,14 +550,14 @@ CPLErr L1BRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /*                           L1BDataset()                               */
 /************************************************************************/
 
-L1BDataset::L1BDataset( L1BFileFormat eL1BFormat )
+L1BDataset::L1BDataset( L1BFileFormat eL1BFormatIn )
 
 {
     eSource = UNKNOWN_STATION;
     eProcCenter = UNKNOWN_CENTER;
     // sStartTime
     // sStopTime
-    bHighGCPDensityStrategy = CSLTestBoolean(CPLGetConfigOption("L1B_HIGH_GCP_DENSITY", "TRUE"));
+    bHighGCPDensityStrategy = CPLTestBool(CPLGetConfigOption("L1B_HIGH_GCP_DENSITY", "TRUE"));
     pasGCPList = NULL;
     nGCPCount = 0;
     iGCPOffset = 0;
@@ -568,7 +567,7 @@ L1BDataset::L1BDataset( L1BFileFormat eL1BFormat )
     eLocationIndicator = DESCEND; // XXX: should be initialised
     iGCPStart = 0;
     iGCPStep = 0;
-    this->eL1BFormat = eL1BFormat;
+    this->eL1BFormat = eL1BFormatIn;
     nBufferSize = 0;
     eSpacecraftID = TIROSN;
     eProductType = HRPT;
@@ -606,7 +605,7 @@ L1BDataset::~L1BDataset()
     if ( pszGCPProjection )
         CPLFree( pszGCPProjection );
     if( fp != NULL )
-        VSIFCloseL( fp );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
     delete poMaskBand;
 }
 
@@ -706,7 +705,7 @@ void L1BDataset::FetchNOAA9TimeCode( TimeCode *psTime,
     GUInt32 lTemp;
 
     lTemp = ((piRecordHeader[2] >> 1) & 0x7F);
-    psTime->SetYear((lTemp > 77) ? 
+    psTime->SetYear((lTemp > 77) ?
         (lTemp + 1900) : (lTemp + 2000)); // Avoid `Year 2000' problem
     psTime->SetDay((GUInt32)(piRecordHeader[2] & 0x01) << 8
                    | (GUInt32)piRecordHeader[3]);
@@ -838,20 +837,20 @@ void L1BDataset::ProcessRecordHeaders()
 {
     void    *pRecordHeader = CPLMalloc( nRecordDataStart );
 
-    VSIFSeekL(fp, nDataStartOffset, SEEK_SET);
-    VSIFReadL(pRecordHeader, 1, nRecordDataStart, fp);
+    CPL_IGNORE_RET_VAL(VSIFSeekL(fp, nDataStartOffset, SEEK_SET));
+    CPL_IGNORE_RET_VAL(VSIFReadL(pRecordHeader, 1, nRecordDataStart, fp));
 
     FetchTimeCode( &sStartTime, pRecordHeader, &eLocationIndicator );
 
-    VSIFSeekL( fp, nDataStartOffset + (nRasterYSize - 1) * nRecordSize,
-              SEEK_SET);
-    VSIFReadL( pRecordHeader, 1, nRecordDataStart, fp );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( fp, nDataStartOffset + (nRasterYSize - 1) * nRecordSize,
+              SEEK_SET));
+    CPL_IGNORE_RET_VAL(VSIFReadL( pRecordHeader, 1, nRecordDataStart, fp ));
 
     FetchTimeCode( &sStopTime, pRecordHeader, NULL );
 
 /* -------------------------------------------------------------------- */
 /*      Pick a skip factor so that we will get roughly 20 lines         */
-/*      worth of GCPs.  That should give respectible coverage on all    */
+/*      worth of GCPs.  That should give respectable coverage on all    */
 /*      but the longest swaths.                                         */
 /* -------------------------------------------------------------------- */
     int nTargetLines;
@@ -875,7 +874,7 @@ void L1BDataset::ProcessRecordHeaders()
             {
                 dfLineStep = nRasterYSize / nGCPsPerLine;
             }
-            nTargetLines = nRasterYSize / dfLineStep;
+            nTargetLines = static_cast<int>(nRasterYSize / dfLineStep);
         }
     }
     else
@@ -887,11 +886,10 @@ void L1BDataset::ProcessRecordHeaders()
 /* -------------------------------------------------------------------- */
 /*      Initialize the GCP list.                                        */
 /* -------------------------------------------------------------------- */
-    pasGCPList = (GDAL_GCP *)VSICalloc( nTargetLines * nGCPsPerLine,
+    pasGCPList = (GDAL_GCP *)VSI_CALLOC_VERBOSE( nTargetLines * nGCPsPerLine,
                                         sizeof(GDAL_GCP) );
     if (pasGCPList == NULL)
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
         CPLFree( pRecordHeader );
         return;
     }
@@ -917,8 +915,8 @@ void L1BDataset::ProcessRecordHeaders()
             continue;
         iPrevLine = iLine;
 
-        VSIFSeekL( fp, nDataStartOffset + iLine * nRecordSize, SEEK_SET );
-        VSIFReadL( pRecordHeader, 1, nRecordDataStart, fp );
+        CPL_IGNORE_RET_VAL(VSIFSeekL( fp, nDataStartOffset + iLine * nRecordSize, SEEK_SET ));
+        CPL_IGNORE_RET_VAL(VSIFReadL( pRecordHeader, 1, nRecordDataStart, fp ));
 
         int nGCPsOnThisLine = FetchGCPs( pasGCPList + nGCPCount, (GByte *)pRecordHeader, iLine );
 
@@ -963,7 +961,7 @@ void L1BDataset::ProcessRecordHeaders()
 
     if( nGCPCount < nTargetLines * nGCPsPerLine )
     {
-        GDALDeinitGCPs( nTargetLines * nGCPsPerLine - nGCPCount, 
+        GDALDeinitGCPs( nTargetLines * nGCPsPerLine - nGCPCount,
                         pasGCPList + nGCPCount );
     }
 
@@ -1019,14 +1017,14 @@ void L1BDataset::FetchMetadata()
         return;
     }
 
-    VSIFPrintfL(fpCSV, "SCANLINE,NBLOCKYOFF,YEAR,DAY,MS_IN_DAY,");
-    VSIFPrintfL(fpCSV, "FATAL_FLAG,TIME_ERROR,DATA_GAP,DATA_JITTER,INSUFFICIENT_DATA_FOR_CAL,NO_EARTH_LOCATION,DESCEND,P_N_STATUS,");
-    VSIFPrintfL(fpCSV, "BIT_SYNC_STATUS,SYNC_ERROR,FRAME_SYNC_ERROR,FLYWHEELING,BIT_SLIPPAGE,C3_SBBC,C4_SBBC,C5_SBBC,");
-    VSIFPrintfL(fpCSV, "TIP_PARITY_FRAME_1,TIP_PARITY_FRAME_2,TIP_PARITY_FRAME_3,TIP_PARITY_FRAME_4,TIP_PARITY_FRAME_5,");
-    VSIFPrintfL(fpCSV, "SYNC_ERRORS,");
-    VSIFPrintfL(fpCSV, "CAL_SLOPE_C1,CAL_INTERCEPT_C1,CAL_SLOPE_C2,CAL_INTERCEPT_C2,CAL_SLOPE_C3,CAL_INTERCEPT_C3,CAL_SLOPE_C4,CAL_INTERCEPT_C4,CAL_SLOPE_C5,CAL_INTERCEPT_C5,");
-    VSIFPrintfL(fpCSV, "NUM_SOLZENANGLES_EARTHLOCPNTS");
-    VSIFPrintfL(fpCSV, "\n");
+    CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "SCANLINE,NBLOCKYOFF,YEAR,DAY,MS_IN_DAY,"));
+    CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "FATAL_FLAG,TIME_ERROR,DATA_GAP,DATA_JITTER,INSUFFICIENT_DATA_FOR_CAL,NO_EARTH_LOCATION,DESCEND,P_N_STATUS,"));
+    CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "BIT_SYNC_STATUS,SYNC_ERROR,FRAME_SYNC_ERROR,FLYWHEELING,BIT_SLIPPAGE,C3_SBBC,C4_SBBC,C5_SBBC,"));
+    CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "TIP_PARITY_FRAME_1,TIP_PARITY_FRAME_2,TIP_PARITY_FRAME_3,TIP_PARITY_FRAME_4,TIP_PARITY_FRAME_5,"));
+    CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "SYNC_ERRORS,"));
+    CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "CAL_SLOPE_C1,CAL_INTERCEPT_C1,CAL_SLOPE_C2,CAL_INTERCEPT_C2,CAL_SLOPE_C3,CAL_INTERCEPT_C3,CAL_SLOPE_C4,CAL_INTERCEPT_C4,CAL_SLOPE_C5,CAL_INTERCEPT_C5,"));
+    CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "NUM_SOLZENANGLES_EARTHLOCPNTS"));
+    CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "\n"));
 
     GByte* pabyRecordHeader = (GByte*)CPLMalloc(nRecordDataStart);
 
@@ -1035,23 +1033,23 @@ void L1BDataset::FetchMetadata()
 /* -------------------------------------------------------------------- */
 /*      Seek to data.                                                   */
 /* -------------------------------------------------------------------- */
-        VSIFSeekL( fp, GetLineOffset(nBlockYOff), SEEK_SET );
+        CPL_IGNORE_RET_VAL(VSIFSeekL( fp, GetLineOffset(nBlockYOff), SEEK_SET ));
 
-        VSIFReadL( pabyRecordHeader, 1, nRecordDataStart, fp );
+        CPL_IGNORE_RET_VAL(VSIFReadL( pabyRecordHeader, 1, nRecordDataStart, fp ));
 
         GUInt16 nScanlineNumber = GetUInt16(pabyRecordHeader);
 
         TimeCode timeCode;
         FetchTimeCode( &timeCode, pabyRecordHeader, NULL );
 
-        VSIFPrintfL(fpCSV,
+        CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV,
                     "%d,%d,%d,%d,%d,",
                     nScanlineNumber,
                     nBlockYOff,
                     (int)timeCode.GetYear(),
                     (int)timeCode.GetDay(),
-                    (int)timeCode.GetMillisecond());
-        VSIFPrintfL(fpCSV,
+                    (int)timeCode.GetMillisecond()));
+        CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV,
                     "%d,%d,%d,%d,%d,%d,%d,%d,",
                     (pabyRecordHeader[8] >> 7) & 1,
                     (pabyRecordHeader[8] >> 6) & 1,
@@ -1060,8 +1058,8 @@ void L1BDataset::FetchMetadata()
                     (pabyRecordHeader[8] >> 3) & 1,
                     (pabyRecordHeader[8] >> 2) & 1,
                     (pabyRecordHeader[8] >> 1) & 1,
-                    (pabyRecordHeader[8] >> 0) & 1);
-        VSIFPrintfL(fpCSV,
+                    (pabyRecordHeader[8] >> 0) & 1));
+        CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV,
                     "%d,%d,%d,%d,%d,%d,%d,%d,",
                     (pabyRecordHeader[9] >> 7) & 1,
                     (pabyRecordHeader[9] >> 6) & 1,
@@ -1070,31 +1068,31 @@ void L1BDataset::FetchMetadata()
                     (pabyRecordHeader[9] >> 3) & 1,
                     (pabyRecordHeader[9] >> 2) & 1,
                     (pabyRecordHeader[9] >> 1) & 1,
-                    (pabyRecordHeader[9] >> 0) & 1);
-        VSIFPrintfL(fpCSV,
+                    (pabyRecordHeader[9] >> 0) & 1));
+        CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV,
                     "%d,%d,%d,%d,%d,",
                     (pabyRecordHeader[10] >> 7) & 1,
                     (pabyRecordHeader[10] >> 6) & 1,
                     (pabyRecordHeader[10] >> 5) & 1,
                     (pabyRecordHeader[10] >> 4) & 1,
-                    (pabyRecordHeader[10] >> 3) & 1);
-        VSIFPrintfL(fpCSV, "%d,", pabyRecordHeader[11] >> 2);
+                    (pabyRecordHeader[10] >> 3) & 1));
+        CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "%d,", pabyRecordHeader[11] >> 2));
         GInt32 i32;
         for(int i=0;i<10;i++)
         {
             i32 = GetInt32(pabyRecordHeader + 12 + 4 *i);
             /* Scales : http://www.ncdc.noaa.gov/oa/pod-guide/ncdc/docs/podug/html/c3/sec3-3.htm */
             if( (i % 2) == 0 )
-                VSIFPrintfL(fpCSV, "%f,", i32 / pow(2.0, 30.0));
+                CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "%f,", i32 / pow(2.0, 30.0)));
             else
-                VSIFPrintfL(fpCSV, "%f,", i32 / pow(2.0, 22.0));
+                CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "%f,", i32 / pow(2.0, 22.0)));
         }
-        VSIFPrintfL(fpCSV, "%d", pabyRecordHeader[52]);
-        VSIFPrintfL(fpCSV, "\n");
+        CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "%d", pabyRecordHeader[52]));
+        CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "\n"));
     }
 
     CPLFree(pabyRecordHeader);
-    VSIFCloseL(fpCSV);
+    CPL_IGNORE_RET_VAL(VSIFCloseL(fpCSV));
 }
 
 /************************************************************************/
@@ -1120,38 +1118,38 @@ void L1BDataset::FetchMetadataNOAA15()
         return;
     }
 
-    VSIFPrintfL(fpCSV, "SCANLINE,NBLOCKYOFF,YEAR,DAY,MS_IN_DAY,SAT_CLOCK_DRIF_DELTA,SOUTHBOUND,SCANTIME_CORRECTED,C3_SELECT,");
-    VSIFPrintfL(fpCSV, "FATAL_FLAG,TIME_ERROR,DATA_GAP,INSUFFICIENT_DATA_FOR_CAL,"
+    CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "SCANLINE,NBLOCKYOFF,YEAR,DAY,MS_IN_DAY,SAT_CLOCK_DRIF_DELTA,SOUTHBOUND,SCANTIME_CORRECTED,C3_SELECT,"));
+    CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "FATAL_FLAG,TIME_ERROR,DATA_GAP,INSUFFICIENT_DATA_FOR_CAL,"
                        "NO_EARTH_LOCATION,FIRST_GOOD_TIME_AFTER_CLOCK_UPDATE,"
                        "INSTRUMENT_STATUS_CHANGED,SYNC_LOCK_DROPPED,"
                        "FRAME_SYNC_ERROR,FRAME_SYNC_DROPPED_LOCK,FLYWHEELING,"
                        "BIT_SLIPPAGE,TIP_PARITY_ERROR,REFLECTED_SUNLIGHT_C3B,"
-                       "REFLECTED_SUNLIGHT_C4,REFLECTED_SUNLIGHT_C5,RESYNC,P_N_STATUS,");
-    VSIFPrintfL(fpCSV, "BAD_TIME_CAN_BE_INFERRED,BAD_TIME_CANNOT_BE_INFERRED,"
-                       "TIME_DISCONTINUITY,REPEAT_SCAN_TIME,");
-    VSIFPrintfL(fpCSV, "UNCALIBRATED_BAD_TIME,CALIBRATED_FEWER_SCANLINES,"
+                       "REFLECTED_SUNLIGHT_C4,REFLECTED_SUNLIGHT_C5,RESYNC,P_N_STATUS,"));
+    CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "BAD_TIME_CAN_BE_INFERRED,BAD_TIME_CANNOT_BE_INFERRED,"
+                       "TIME_DISCONTINUITY,REPEAT_SCAN_TIME,"));
+    CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "UNCALIBRATED_BAD_TIME,CALIBRATED_FEWER_SCANLINES,"
                        "UNCALIBRATED_BAD_PRT,CALIBRATED_MARGINAL_PRT,"
-                       "UNCALIBRATED_CHANNELS,");
-    VSIFPrintfL(fpCSV, "NO_EARTH_LOC_BAD_TIME,EARTH_LOC_QUESTIONABLE_TIME,"
-                       "EARTH_LOC_QUESTIONABLE,EARTH_LOC_VERY_QUESTIONABLE,");
-    VSIFPrintfL(fpCSV, "C3B_UNCALIBRATED,C3B_QUESTIONABLE,C3B_ALL_BLACKBODY,"
-                       "C3B_ALL_SPACEVIEW,C3B_MARGINAL_BLACKBODY,C3B_MARGINAL_SPACEVIEW,");
-    VSIFPrintfL(fpCSV, "C4_UNCALIBRATED,C4_QUESTIONABLE,C4_ALL_BLACKBODY,"
-                       "C4_ALL_SPACEVIEW,C4_MARGINAL_BLACKBODY,C4_MARGINAL_SPACEVIEW,");
-    VSIFPrintfL(fpCSV, "C5_UNCALIBRATED,C5_QUESTIONABLE,C5_ALL_BLACKBODY,"
-                       "C5_ALL_SPACEVIEW,C5_MARGINAL_BLACKBODY,C5_MARGINAL_SPACEVIEW,");
-    VSIFPrintfL(fpCSV, "BIT_ERRORS,");
+                       "UNCALIBRATED_CHANNELS,"));
+    CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "NO_EARTH_LOC_BAD_TIME,EARTH_LOC_QUESTIONABLE_TIME,"
+                       "EARTH_LOC_QUESTIONABLE,EARTH_LOC_VERY_QUESTIONABLE,"));
+    CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "C3B_UNCALIBRATED,C3B_QUESTIONABLE,C3B_ALL_BLACKBODY,"
+                       "C3B_ALL_SPACEVIEW,C3B_MARGINAL_BLACKBODY,C3B_MARGINAL_SPACEVIEW,"));
+    CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "C4_UNCALIBRATED,C4_QUESTIONABLE,C4_ALL_BLACKBODY,"
+                       "C4_ALL_SPACEVIEW,C4_MARGINAL_BLACKBODY,C4_MARGINAL_SPACEVIEW,"));
+    CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "C5_UNCALIBRATED,C5_QUESTIONABLE,C5_ALL_BLACKBODY,"
+                       "C5_ALL_SPACEVIEW,C5_MARGINAL_BLACKBODY,C5_MARGINAL_SPACEVIEW,"));
+    CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "BIT_ERRORS,"));
     for(i=0;i<3;i++)
     {
         const char* pszChannel = (i==0) ? "C1" : (i==1) ? "C2" : "C3A";
         for(j=0;j<3;j++)
         {
             const char* pszType = (j==0) ? "OP": (j==1) ? "TEST": "PRELAUNCH";
-            VSIFPrintfL(fpCSV, "VIS_%s_CAL_%s_SLOPE_1,", pszType, pszChannel);
-            VSIFPrintfL(fpCSV, "VIS_%s_CAL_%s_INTERCEPT_1,", pszType, pszChannel);
-            VSIFPrintfL(fpCSV, "VIS_%s_CAL_%s_SLOPE_2,", pszType, pszChannel);
-            VSIFPrintfL(fpCSV, "VIS_%s_CAL_%s_INTERCEPT_2,", pszType, pszChannel);
-            VSIFPrintfL(fpCSV, "VIS_%s_CAL_%s_INTERSECTION,", pszType, pszChannel);
+            CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "VIS_%s_CAL_%s_SLOPE_1,", pszType, pszChannel));
+            CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "VIS_%s_CAL_%s_INTERCEPT_1,", pszType, pszChannel));
+            CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "VIS_%s_CAL_%s_SLOPE_2,", pszType, pszChannel));
+            CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "VIS_%s_CAL_%s_INTERCEPT_2,", pszType, pszChannel));
+            CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "VIS_%s_CAL_%s_INTERSECTION,", pszType, pszChannel));
         }
     }
     for(i=0;i<3;i++)
@@ -1160,16 +1158,16 @@ void L1BDataset::FetchMetadataNOAA15()
         for(j=0;j<2;j++)
         {
             const char* pszType = (j==0) ? "OP": "TEST";
-            VSIFPrintfL(fpCSV, "IR_%s_CAL_%s_COEFF_1,", pszType, pszChannel);
-            VSIFPrintfL(fpCSV, "IR_%s_CAL_%s_COEFF_2,", pszType, pszChannel);
-            VSIFPrintfL(fpCSV, "IR_%s_CAL_%s_COEFF_3,", pszType, pszChannel);
+            CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "IR_%s_CAL_%s_COEFF_1,", pszType, pszChannel));
+            CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "IR_%s_CAL_%s_COEFF_2,", pszType, pszChannel));
+            CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "IR_%s_CAL_%s_COEFF_3,", pszType, pszChannel));
         }
     }
-    VSIFPrintfL(fpCSV, "EARTH_LOC_CORR_TIP_EULER,EARTH_LOC_IND,"
+    CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "EARTH_LOC_CORR_TIP_EULER,EARTH_LOC_IND,"
                        "SPACECRAFT_ATT_CTRL,ATT_SMODE,ATT_PASSIVE_WHEEL_TEST,"
                        "TIME_TIP_EULER,TIP_EULER_ROLL,TIP_EULER_PITCH,TIP_EULER_YAW,"
-                       "SPACECRAFT_ALT");
-    VSIFPrintfL(fpCSV, "\n");
+                       "SPACECRAFT_ALT"));
+    CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "\n"));
 
     GByte* pabyRecordHeader = (GByte*)CPLMalloc(nRecordDataStart);
     GInt16 i16;
@@ -1182,9 +1180,9 @@ void L1BDataset::FetchMetadataNOAA15()
 /* -------------------------------------------------------------------- */
 /*      Seek to data.                                                   */
 /* -------------------------------------------------------------------- */
-        VSIFSeekL( fp, GetLineOffset(nBlockYOff), SEEK_SET );
+        CPL_IGNORE_RET_VAL(VSIFSeekL( fp, GetLineOffset(nBlockYOff), SEEK_SET ));
 
-        VSIFReadL( pabyRecordHeader, 1, nRecordDataStart, fp );
+        CPL_IGNORE_RET_VAL(VSIFReadL( pabyRecordHeader, 1, nRecordDataStart, fp ));
 
         GUInt16 nScanlineNumber = GetUInt16(pabyRecordHeader);
 
@@ -1196,7 +1194,7 @@ void L1BDataset::FetchMetadataNOAA15()
         /* Scanline bit field */
         n16 = GetInt16(pabyRecordHeader + 12);
 
-        VSIFPrintfL(fpCSV,
+        CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV,
                     "%d,%d,%d,%d,%d,%d,%d,%d,%d,",
                     nScanlineNumber,
                     nBlockYOff,
@@ -1206,10 +1204,10 @@ void L1BDataset::FetchMetadataNOAA15()
                     i16,
                     (n16 >> 15) & 1,
                     (n16 >> 14) & 1,
-                    (n16) & 3);
+                    (n16) & 3));
 
         n32 = GetUInt32(pabyRecordHeader + 24);
-        VSIFPrintfL(fpCSV,"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,",
+        CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV,"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,",
                     (n32 >> 31) & 1,
                     (n32 >> 30) & 1,
                     (n32 >> 29) & 1,
@@ -1227,10 +1225,10 @@ void L1BDataset::FetchMetadataNOAA15()
                     (n32 >> 4) & 3,
                     (n32 >> 2) & 3,
                     (n32 >> 1) & 1,
-                    (n32 >> 0) & 1);
+                    (n32 >> 0) & 1));
 
         n32 = GetUInt32(pabyRecordHeader + 28);
-        VSIFPrintfL(fpCSV,"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,",
+        CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV,"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,",
                     (n32 >> 23) & 1,
                     (n32 >> 22) & 1,
                     (n32 >> 21) & 1,
@@ -1243,23 +1241,23 @@ void L1BDataset::FetchMetadataNOAA15()
                     (n32 >> 7) & 1,
                     (n32 >> 6) & 1,
                     (n32 >> 5) & 1,
-                    (n32 >> 4) & 1);
+                    (n32 >> 4) & 1));
 
         for(i=0;i<3;i++)
         {
             n16 = GetUInt16(pabyRecordHeader + 32 + 2 * i);
-            VSIFPrintfL(fpCSV,"%d,%d,%d,%d,%d,%d,",
-                    (n32 >> 7) & 1,
-                    (n32 >> 6) & 1,
-                    (n32 >> 5) & 1,
-                    (n32 >> 4) & 1,
-                    (n32 >> 2) & 1,
-                    (n32 >> 1) & 1);
+            CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV,"%d,%d,%d,%d,%d,%d,",
+                    (n16 >> 7) & 1,
+                    (n16 >> 6) & 1,
+                    (n16 >> 5) & 1,
+                    (n16 >> 4) & 1,
+                    (n16 >> 2) & 1,
+                    (n16 >> 1) & 1));
         }
 
         /* Bit errors */
         n16 = GetUInt16(pabyRecordHeader + 38);
-        VSIFPrintfL(fpCSV, "%d,", n16);
+        CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "%d,", n16));
 
         int nOffset = 48;
         for(i=0;i<3;i++)
@@ -1268,53 +1266,53 @@ void L1BDataset::FetchMetadataNOAA15()
             {
                 i32 = GetInt32(pabyRecordHeader + nOffset);
                 nOffset += 4;
-                VSIFPrintfL(fpCSV, "%f,", i32 / pow(10.0, 7.0));
+                CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "%f,", i32 / pow(10.0, 7.0)));
                 i32 = GetInt32(pabyRecordHeader + nOffset);
                 nOffset += 4;
-                VSIFPrintfL(fpCSV, "%f,", i32 / pow(10.0, 6.0));
+                CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "%f,", i32 / pow(10.0, 6.0)));
                 i32 = GetInt32(pabyRecordHeader + nOffset);
                 nOffset += 4;
-                VSIFPrintfL(fpCSV, "%f,", i32 / pow(10.0, 7.0));
+                CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "%f,", i32 / pow(10.0, 7.0)));
                 i32 = GetInt32(pabyRecordHeader + nOffset);
                 nOffset += 4;
-                VSIFPrintfL(fpCSV, "%f,", i32 / pow(10.0, 6.0));
+                CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "%f,", i32 / pow(10.0, 6.0)));
                 i32 = GetInt32(pabyRecordHeader + nOffset);
                 nOffset += 4;
-                VSIFPrintfL(fpCSV, "%d,", i32);
+                CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "%d,", i32));
             }
         }
         for(i=0;i<18;i++)
         {
             i32 = GetInt32(pabyRecordHeader + nOffset);
             nOffset += 4;
-            VSIFPrintfL(fpCSV, "%f,", i32 / pow(10.0, 6.0));
+            CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "%f,", i32 / pow(10.0, 6.0)));
         }
 
         n32 = GetUInt32(pabyRecordHeader + 312);
-        VSIFPrintfL(fpCSV,"%d,%d,%d,%d,%d,",
+        CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV,"%d,%d,%d,%d,%d,",
                     (n32 >> 16) & 1,
                     (n32 >> 12) & 15,
                     (n32 >> 8) & 15,
                     (n32 >> 4) & 15,
-                    (n32 >> 0) & 15);
+                    (n32 >> 0) & 15));
 
         n32 = GetUInt32(pabyRecordHeader + 316);
-        VSIFPrintfL(fpCSV,"%d,",n32);
+        CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV,"%d,",n32));
 
         for(i=0;i<3;i++)
         {
             i16 = GetUInt16(pabyRecordHeader + 320 + 2 * i);
-            VSIFPrintfL(fpCSV,"%f,",i16 / pow(10.0,3.0));
+            CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV,"%f,",i16 / pow(10.0,3.0)));
         }
 
         n16 = GetUInt16(pabyRecordHeader + 326);
-        VSIFPrintfL(fpCSV,"%f",n16 / pow(10.0,1.0));
+        CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV,"%f",n16 / pow(10.0,1.0)));
 
-        VSIFPrintfL(fpCSV, "\n");
+        CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCSV, "\n"));
     }
 
     CPLFree(pabyRecordHeader);
-    VSIFCloseL(fpCSV);
+    CPL_IGNORE_RET_VAL(VSIFCloseL(fpCSV));
 }
 
 /************************************************************************/
@@ -1334,7 +1332,7 @@ static const GByte EBCDICToASCII[] =
 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x5C, 0x00, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -1390,13 +1388,13 @@ CPLErr L1BDataset::ProcessDatasetHeader(const char* pszFilename)
         }
 
         // Determine processing center where the dataset was created
-        if ( EQUALN(szDatasetName, "CMS", 3) )
+        if ( STARTS_WITH_CI(szDatasetName, "CMS") )
              eProcCenter = CMS;
-        else if ( EQUALN(szDatasetName, "DSS", 3) )
+        else if ( STARTS_WITH_CI(szDatasetName, "DSS") )
              eProcCenter = DSS;
-        else if ( EQUALN(szDatasetName, "NSS", 3) )
+        else if ( STARTS_WITH_CI(szDatasetName, "NSS") )
              eProcCenter = NSS;
-        else if ( EQUALN(szDatasetName, "UKM", 3) )
+        else if ( STARTS_WITH_CI(szDatasetName, "UKM") )
              eProcCenter = UKM;
         else
              eProcCenter = UNKNOWN_CENTER;
@@ -1419,19 +1417,15 @@ CPLErr L1BDataset::ProcessDatasetHeader(const char* pszFilename)
         }
 
         // Determine data format (10-bit packed or 8/16-bit unpacked)
-        if ( EQUALN((const char *)abyTBMHeader + L1B_NOAA9_HDR_WORD_OFF,
-                    "10", 2) )
+        if ( STARTS_WITH_CI((const char *)abyTBMHeader + L1B_NOAA9_HDR_WORD_OFF, "10") )
             iDataFormat = PACKED10BIT;
-        else if ( EQUALN((const char *)abyTBMHeader + L1B_NOAA9_HDR_WORD_OFF,
-                         "16", 2) )
+        else if ( STARTS_WITH_CI((const char *)abyTBMHeader + L1B_NOAA9_HDR_WORD_OFF, "16") )
             iDataFormat = UNPACKED16BIT;
-        else if ( EQUALN((const char *)abyTBMHeader + L1B_NOAA9_HDR_WORD_OFF,
-                         "08", 2) )
+        else if ( STARTS_WITH_CI((const char *)abyTBMHeader + L1B_NOAA9_HDR_WORD_OFF, "08") )
             iDataFormat = UNPACKED8BIT;
-        else if ( EQUALN((const char *)abyTBMHeader + L1B_NOAA9_HDR_WORD_OFF,
-                         "  ", 2)
+        else if ( STARTS_WITH_CI((const char *)abyTBMHeader + L1B_NOAA9_HDR_WORD_OFF, "  ")
                   || abyTBMHeader[L1B_NOAA9_HDR_WORD_OFF] == '\0' )
-            /* Empty string can be found in the following samples : 
+            /* Empty string can be found in the following samples :
                 http://www2.ncdc.noaa.gov/docs/podug/data/avhrr/franh.1b (10 bit)
                 http://www2.ncdc.noaa.gov/docs/podug/data/avhrr/frang.1b (10 bit)
                 http://www2.ncdc.noaa.gov/docs/podug/data/avhrr/calfilel.1b (16 bit)
@@ -1477,7 +1471,7 @@ CPLErr L1BDataset::ProcessDatasetHeader(const char* pszFilename)
             {
                 /* We could also use the time code to determine TIROS-N */
                 if( strlen(pszFilename) == L1B_DATASET_NAME_SIZE &&
-                    strncmp(pszFilename + 8, ".TN.", 4) == 0 )
+                    STARTS_WITH(pszFilename + 8, ".TN.") )
                     eSpacecraftID = TIROSN;
                 else
                     eSpacecraftID = NOAA11;
@@ -1490,7 +1484,7 @@ CPLErr L1BDataset::ProcessDatasetHeader(const char* pszFilename)
             {
                 /* We could also use the time code to determine NOAA6 */
                 if( strlen(pszFilename) == L1B_DATASET_NAME_SIZE &&
-                    strncmp(pszFilename + 8, ".NA.", 4) == 0 )
+                    STARTS_WITH(pszFilename + 8, ".NA.") )
                     eSpacecraftID = NOAA6;
                 else
                     eSpacecraftID = NOAA13;
@@ -1579,14 +1573,11 @@ CPLErr L1BDataset::ProcessDatasetHeader(const char* pszFilename)
             }
 
             // Determine data format (10-bit packed or 8/16-bit unpacked)
-            if ( EQUALN((const char *)abyARSHeader + L1B_NOAA15_HDR_WORD_OFF,
-                        "10", 2) )
+            if ( STARTS_WITH_CI((const char *)abyARSHeader + L1B_NOAA15_HDR_WORD_OFF, "10") )
                 iDataFormat = PACKED10BIT;
-            else if ( EQUALN((const char *)abyARSHeader + L1B_NOAA15_HDR_WORD_OFF,
-                             "16", 2) )
+            else if ( STARTS_WITH_CI((const char *)abyARSHeader + L1B_NOAA15_HDR_WORD_OFF, "16") )
                 iDataFormat = UNPACKED16BIT;
-            else if ( EQUALN((const char *)abyARSHeader + L1B_NOAA15_HDR_WORD_OFF,
-                             "08", 2) )
+            else if ( STARTS_WITH_CI((const char *)abyARSHeader + L1B_NOAA15_HDR_WORD_OFF, "08") )
                 iDataFormat = UNPACKED8BIT;
             else
             {
@@ -1622,17 +1613,17 @@ CPLErr L1BDataset::ProcessDatasetHeader(const char* pszFilename)
         szDatasetName[L1B_DATASET_NAME_SIZE] = '\0';
 
         // Determine processing center where the dataset was created
-        if ( EQUALN((const char *)abyRecHeader
-                    + L1B_NOAA15_HDR_REC_SITE_OFF, "CMS", 3) )
+        if ( STARTS_WITH_CI((const char *)abyRecHeader
+                    + L1B_NOAA15_HDR_REC_SITE_OFF, "CMS") )
              eProcCenter = CMS;
-        else if ( EQUALN((const char *)abyRecHeader
-                         + L1B_NOAA15_HDR_REC_SITE_OFF, "DSS", 3) )
+        else if ( STARTS_WITH_CI((const char *)abyRecHeader
+                         + L1B_NOAA15_HDR_REC_SITE_OFF, "DSS") )
              eProcCenter = DSS;
-        else if ( EQUALN((const char *)abyRecHeader
-                         + L1B_NOAA15_HDR_REC_SITE_OFF, "NSS", 3) )
+        else if ( STARTS_WITH_CI((const char *)abyRecHeader
+                         + L1B_NOAA15_HDR_REC_SITE_OFF, "NSS") )
              eProcCenter = NSS;
-        else if ( EQUALN((const char *)abyRecHeader
-                         + L1B_NOAA15_HDR_REC_SITE_OFF, "UKM", 3) )
+        else if ( STARTS_WITH_CI((const char *)abyRecHeader
+                         + L1B_NOAA15_HDR_REC_SITE_OFF, "UKM") )
              eProcCenter = UKM;
         else
              eProcCenter = UNKNOWN_CENTER;
@@ -1641,8 +1632,8 @@ CPLErr L1BDataset::ProcessDatasetHeader(const char* pszFilename)
 
         /* Some products from NOAA-18 and NOAA-19 coming from 'ess' processing station */
         /* have little-endian ordering. Try to detect it with some consistency checks */
-        for(int i=0;i<=2;i++)
-        {
+        int i=0;
+        do {
             nFormatVersionYear = GetUInt16(abyRecHeader + L1B_NOAA15_HDR_REC_FORMAT_VERSION_YEAR_OFF);
             nFormatVersionDayOfYear = GetUInt16(abyRecHeader + L1B_NOAA15_HDR_REC_FORMAT_VERSION_DAY_OFF);
             nHeaderRecCount = GetUInt16(abyRecHeader + L1B_NOAA15_HDR_REC_HDR_REC_COUNT_OFF);
@@ -1660,7 +1651,8 @@ CPLErr L1BDataset::ProcessDatasetHeader(const char* pszFilename)
             }
             else
                 break;
-        }
+            i ++;
+        } while( i <= 2 );
         nRecordSizeFromHeader = GetUInt16(abyRecHeader + L1B_NOAA15_HDR_REC_LOGICAL_REC_LENGTH_OFF);
         int nFormatVersion = GetUInt16(abyRecHeader + L1B_NOAA15_HDR_REC_FORMAT_VERSION_OFF);
         CPLDebug("L1B", "NOAA Level 1b Format Version Number = %d", nFormatVersion);
@@ -1670,13 +1662,13 @@ CPLErr L1BDataset::ProcessDatasetHeader(const char* pszFilename)
         int nBlockSize = GetUInt16(abyRecHeader + L1B_NOAA15_HDR_REC_BLOCK_SIZE_OFF);
         CPLDebug("L1B", "Block Size of source Level 1b data set prior to processing = %d", nBlockSize);
         CPLDebug("L1B", "Count of Header Records in this Data Set = %d", nHeaderRecCount);
-        
+
         int nDataRecordCount = GetUInt16(abyRecHeader + L1B_NOAA15_HDR_REC_DATA_RECORD_COUNT_OFF);
         CPLDebug("L1B", "Count of Data Records = %d", nDataRecordCount);
-        
+
         int nCalibratedScanlineCount = GetUInt16(abyRecHeader + L1B_NOAA15_HDR_REC_CALIBRATED_SCANLINE_COUNT_OFF);
         CPLDebug("L1B", "Count of Calibrated, Earth Located Scan Lines = %d", nCalibratedScanlineCount);
-        
+
         int nMissingScanlineCount = GetUInt16(abyRecHeader + L1B_NOAA15_HDR_REC_MISSING_SCANLINE_COUNT_OFF);
         CPLDebug("L1B", "Count of Missing Scan Lines = %d", nMissingScanlineCount);
         if( nMissingScanlineCount != 0 )
@@ -1761,7 +1753,7 @@ CPLErr L1BDataset::ProcessDatasetHeader(const char* pszFilename)
                 return CE_Failure;
         }
 
-        // Fetch hinstrument status. Helps to determine whether we have
+        // Fetch instrument status. Helps to determine whether we have
         // 3A or 3B channel in the dataset.
         iInstrumentStatus = GetUInt32(abyRecHeader + L1B_NOAA15_HDR_REC_STAT_OFF);
 
@@ -1941,7 +1933,7 @@ CPLErr L1BDataset::ProcessDatasetHeader(const char* pszFilename)
             break;
     }
     SetMetadataItem( "PROCESSING_CENTER",  pszText );
-    
+
     return CE_None;
 }
 
@@ -2305,11 +2297,11 @@ class L1BGeolocRasterBand: public GDALRasterBand
 /*                        L1BGeolocDataset()                            */
 /************************************************************************/
 
-L1BGeolocDataset::L1BGeolocDataset(L1BDataset* poL1BDS,
-                                   int bInterpolGeolocationDS)
+L1BGeolocDataset::L1BGeolocDataset(L1BDataset* poL1BDSIn,
+                                   int bInterpolGeolocationDSIn)
 {
-    this->poL1BDS = poL1BDS;
-    this->bInterpolGeolocationDS = bInterpolGeolocationDS;
+    this->poL1BDS = poL1BDSIn;
+    this->bInterpolGeolocationDS = bInterpolGeolocationDSIn;
     if( bInterpolGeolocationDS )
         nRasterXSize = poL1BDS->nRasterXSize;
     else
@@ -2330,12 +2322,12 @@ L1BGeolocDataset::~L1BGeolocDataset()
 /*                        L1BGeolocRasterBand()                         */
 /************************************************************************/
 
-L1BGeolocRasterBand::L1BGeolocRasterBand(L1BGeolocDataset* poDS, int nBand)
+L1BGeolocRasterBand::L1BGeolocRasterBand(L1BGeolocDataset* poDSIn, int nBandIn)
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
-    nRasterXSize = poDS->nRasterXSize;
-    nRasterYSize = poDS->nRasterYSize;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
+    nRasterXSize = poDSIn->nRasterXSize;
+    nRasterYSize = poDSIn->nRasterYSize;
     eDataType = GDT_Float64;
     nBlockXSize = nRasterXSize;
     nBlockYSize = 1;
@@ -2438,8 +2430,8 @@ L1BInterpol(double vals[],
     /* Interpolate all intermediate points using two before and two after */
     for (i=knownFirst; i<IDX(numKnown-1); i++)
     {
-        double x[MIDDLE_INTERP_ORDER];
-        double y[MIDDLE_INTERP_ORDER];
+        double x2[MIDDLE_INTERP_ORDER];
+        double y2[MIDDLE_INTERP_ORDER];
         int startpt;
 
         /* Find a suitable set of two known points before and two after */
@@ -2450,10 +2442,10 @@ L1BInterpol(double vals[],
             startpt = numKnown-MIDDLE_INTERP_ORDER;
         for (j=0; j<MIDDLE_INTERP_ORDER; j++)
         {
-            x[j] = IDX(startpt+j);
-            y[j] = vals[IDX(startpt+j)];
+            x2[j] = IDX(startpt+j);
+            y2[j] = vals[IDX(startpt+j)];
         }
-        vals[i] = LagrangeInterpol(x, y, i, MIDDLE_INTERP_ORDER);
+        vals[i] = LagrangeInterpol(x2, y2, i, MIDDLE_INTERP_ORDER);
     }
 }
 
@@ -2477,9 +2469,9 @@ CPLErr L1BGeolocRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff,
 /* -------------------------------------------------------------------- */
 /*      Seek to data.                                                   */
 /* -------------------------------------------------------------------- */
-    VSIFSeekL( poL1BDS->fp, poL1BDS->GetLineOffset(nBlockYOff), SEEK_SET );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( poL1BDS->fp, poL1BDS->GetLineOffset(nBlockYOff), SEEK_SET ));
 
-    VSIFReadL( pabyRecordHeader, 1, poL1BDS->nRecordDataStart, poL1BDS->fp );
+    CPL_IGNORE_RET_VAL(VSIFReadL( pabyRecordHeader, 1, poL1BDS->nRecordDataStart, poL1BDS->fp ));
 
     /* Fetch the GCPs for the row */
     int nGotGCPs = poL1BDS->FetchGCPs(pasGCPList, pabyRecordHeader, nBlockYOff );
@@ -2539,7 +2531,7 @@ CPLErr L1BGeolocRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff,
     CPLFree(pabyRecordHeader);
     GDALDeinitGCPs( poL1BDS->nGCPsPerLine, pasGCPList );
     CPLFree(pasGCPList);
-    
+
     return CE_None;
 }
 
@@ -2603,11 +2595,11 @@ class L1BSolarZenithAnglesRasterBand: public GDALRasterBand
 /*                  L1BSolarZenithAnglesDataset()                       */
 /************************************************************************/
 
-L1BSolarZenithAnglesDataset::L1BSolarZenithAnglesDataset(L1BDataset* poL1BDS)
+L1BSolarZenithAnglesDataset::L1BSolarZenithAnglesDataset(L1BDataset* poL1BDSIn)
 {
-    this->poL1BDS = poL1BDS;
+    this->poL1BDS = poL1BDSIn;
     nRasterXSize = 51;
-    nRasterYSize = poL1BDS->nRasterYSize;
+    nRasterYSize = poL1BDSIn->nRasterYSize;
 }
 
 /************************************************************************/
@@ -2623,12 +2615,12 @@ L1BSolarZenithAnglesDataset::~L1BSolarZenithAnglesDataset()
 /*                  L1BSolarZenithAnglesRasterBand()                    */
 /************************************************************************/
 
-L1BSolarZenithAnglesRasterBand::L1BSolarZenithAnglesRasterBand(L1BSolarZenithAnglesDataset* poDS, int nBand)
+L1BSolarZenithAnglesRasterBand::L1BSolarZenithAnglesRasterBand(L1BSolarZenithAnglesDataset* poDSIn, int nBandIn)
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
-    nRasterXSize = poDS->nRasterXSize;
-    nRasterYSize = poDS->nRasterYSize;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
+    nRasterXSize = poDSIn->nRasterXSize;
+    nRasterYSize = poDSIn->nRasterYSize;
     eDataType = GDT_Float32;
     nBlockXSize = nRasterXSize;
     nBlockYSize = 1;
@@ -2651,9 +2643,9 @@ CPLErr L1BSolarZenithAnglesRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff,
 /* -------------------------------------------------------------------- */
 /*      Seek to data.                                                   */
 /* -------------------------------------------------------------------- */
-    VSIFSeekL( poL1BDS->fp, poL1BDS->GetLineOffset(nBlockYOff), SEEK_SET );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( poL1BDS->fp, poL1BDS->GetLineOffset(nBlockYOff), SEEK_SET ));
 
-    VSIFReadL( pabyRecordHeader, 1, poL1BDS->nRecordSize, poL1BDS->fp );
+    CPL_IGNORE_RET_VAL(VSIFReadL( pabyRecordHeader, 1, poL1BDS->nRecordSize, poL1BDS->fp ));
 
     int nValidValues = MIN(nRasterXSize, pabyRecordHeader[poL1BDS->iGCPCodeOffset]);
     float* pafData = (float*)pData;
@@ -2676,7 +2668,7 @@ CPLErr L1BSolarZenithAnglesRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff,
 
     for(i=0;i<nValidValues;i++)
     {
-        pafData[i] = pabyRecordHeader[poL1BDS->iGCPCodeOffset + 1 + i] / 2.0;
+        pafData[i] = pabyRecordHeader[poL1BDS->iGCPCodeOffset + 1 + i] / 2.0f;
 
         if( bHasFractional )
         {
@@ -2707,18 +2699,18 @@ CPLErr L1BSolarZenithAnglesRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff,
                          nBlockYOff, i, nFractional);
             }
 
-            pafData[i] += nFractional / 10.0;
+            pafData[i] += nFractional / 10.0f;
         }
     }
 
     for(;i<nRasterXSize;i++)
-        pafData[i] = GetNoDataValue(NULL);
+        pafData[i] = static_cast<float>(GetNoDataValue(NULL));
 
     if( poL1BDS->eLocationIndicator == ASCEND )
     {
         for(i=0;i<nRasterXSize/2;i++)
         {
-            double fTmp = pafData[i];
+            float fTmp = pafData[i];
             pafData[i] = pafData[nRasterXSize-1-i];
             pafData[nRasterXSize-1-i] = fTmp;
         }
@@ -2788,9 +2780,9 @@ class L1BNOAA15AnglesRasterBand: public GDALRasterBand
 /*                       L1BNOAA15AnglesDataset()                       */
 /************************************************************************/
 
-L1BNOAA15AnglesDataset::L1BNOAA15AnglesDataset(L1BDataset* poL1BDS)
+L1BNOAA15AnglesDataset::L1BNOAA15AnglesDataset(L1BDataset* poL1BDSIn)
 {
-    this->poL1BDS = poL1BDS;
+    this->poL1BDS = poL1BDSIn;
     nRasterXSize = 51;
     nRasterYSize = poL1BDS->nRasterYSize;
 }
@@ -2808,12 +2800,12 @@ L1BNOAA15AnglesDataset::~L1BNOAA15AnglesDataset()
 /*                      L1BNOAA15AnglesRasterBand()                     */
 /************************************************************************/
 
-L1BNOAA15AnglesRasterBand::L1BNOAA15AnglesRasterBand(L1BNOAA15AnglesDataset* poDS, int nBand)
+L1BNOAA15AnglesRasterBand::L1BNOAA15AnglesRasterBand(L1BNOAA15AnglesDataset* poDSIn, int nBandIn)
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
-    nRasterXSize = poDS->nRasterXSize;
-    nRasterYSize = poDS->nRasterYSize;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
+    nRasterXSize = poDSIn->nRasterXSize;
+    nRasterYSize = poDSIn->nRasterYSize;
     eDataType = GDT_Float32;
     nBlockXSize = nRasterXSize;
     nBlockYSize = 1;
@@ -2842,23 +2834,23 @@ CPLErr L1BNOAA15AnglesRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff,
 /* -------------------------------------------------------------------- */
 /*      Seek to data.                                                   */
 /* -------------------------------------------------------------------- */
-    VSIFSeekL( poL1BDS->fp, poL1BDS->GetLineOffset(nBlockYOff), SEEK_SET );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( poL1BDS->fp, poL1BDS->GetLineOffset(nBlockYOff), SEEK_SET ));
 
-    VSIFReadL( pabyRecordHeader, 1, poL1BDS->nRecordSize, poL1BDS->fp );
+    CPL_IGNORE_RET_VAL(VSIFReadL( pabyRecordHeader, 1, poL1BDS->nRecordSize, poL1BDS->fp ));
 
     float* pafData = (float*)pData;
 
     for(i=0;i<nRasterXSize;i++)
     {
         GInt16 i16 = poL1BDS->GetInt16(pabyRecordHeader + 328 + 6 * i + 2 * (nBand - 1));
-        pafData[i] = i16 / 100.0;
+        pafData[i] = i16 / 100.0f;
     }
 
     if( poL1BDS->eLocationIndicator == ASCEND )
     {
         for(i=0;i<nRasterXSize/2;i++)
         {
-            double fTmp = pafData[i];
+            float fTmp = pafData[i];
             pafData[i] = pafData[nRasterXSize-1-i];
             pafData[nRasterXSize-1-i] = fTmp;
         }
@@ -2916,11 +2908,11 @@ class L1BCloudsRasterBand: public GDALRasterBand
 /*                         L1BCloudsDataset()                           */
 /************************************************************************/
 
-L1BCloudsDataset::L1BCloudsDataset(L1BDataset* poL1BDS)
+L1BCloudsDataset::L1BCloudsDataset(L1BDataset* poL1BDSIn)
 {
-    this->poL1BDS = poL1BDS;
-    nRasterXSize = poL1BDS->nRasterXSize;
-    nRasterYSize = poL1BDS->nRasterYSize;
+    this->poL1BDS = poL1BDSIn;
+    nRasterXSize = poL1BDSIn->nRasterXSize;
+    nRasterYSize = poL1BDSIn->nRasterYSize;
 }
 
 /************************************************************************/
@@ -2936,12 +2928,12 @@ L1BCloudsDataset::~L1BCloudsDataset()
 /*                         L1BCloudsRasterBand()                        */
 /************************************************************************/
 
-L1BCloudsRasterBand::L1BCloudsRasterBand(L1BCloudsDataset* poDS, int nBand)
+L1BCloudsRasterBand::L1BCloudsRasterBand(L1BCloudsDataset* poDSIn, int nBandIn)
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
-    nRasterXSize = poDS->nRasterXSize;
-    nRasterYSize = poDS->nRasterYSize;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
+    nRasterXSize = poDSIn->nRasterXSize;
+    nRasterYSize = poDSIn->nRasterYSize;
     eDataType = GDT_Byte;
     nBlockXSize = nRasterXSize;
     nBlockYSize = 1;
@@ -2964,9 +2956,9 @@ CPLErr L1BCloudsRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff,
 /* -------------------------------------------------------------------- */
 /*      Seek to data.                                                   */
 /* -------------------------------------------------------------------- */
-    VSIFSeekL( poL1BDS->fp, poL1BDS->GetLineOffset(nBlockYOff), SEEK_SET );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( poL1BDS->fp, poL1BDS->GetLineOffset(nBlockYOff), SEEK_SET ));
 
-    VSIFReadL( pabyRecordHeader, 1, poL1BDS->nRecordSize, poL1BDS->fp );
+    CPL_IGNORE_RET_VAL(VSIFReadL( pabyRecordHeader, 1, poL1BDS->nRecordSize, poL1BDS->fp ));
 
     GByte* pabyData = (GByte*)pData;
 
@@ -3047,7 +3039,7 @@ L1BFileFormat L1BDataset::DetectFormat( const char* pszFilename,
          && *(pabyHeader + 8 + 61) == 'K' )
         return L1B_NOAA9;
 
-    // Finally try the AAPP formats 
+    // Finally try the AAPP formats
     if ( *(pabyHeader + 25) == '.'
          && *(pabyHeader + 30) == '.'
          && *(pabyHeader + 33) == '.'
@@ -3083,15 +3075,15 @@ L1BFileFormat L1BDataset::DetectFormat( const char* pszFilename,
 int L1BDataset::Identify( GDALOpenInfo *poOpenInfo )
 
 {
-    if ( EQUALN( poOpenInfo->pszFilename, "L1BGCPS:", strlen("L1BGCPS:") ) )
+    if ( STARTS_WITH_CI(poOpenInfo->pszFilename, "L1BGCPS:") )
         return TRUE;
-    if ( EQUALN( poOpenInfo->pszFilename, "L1BGCPS_INTERPOL:", strlen("L1BGCPS_INTERPOL:") ) )
+    if ( STARTS_WITH_CI(poOpenInfo->pszFilename, "L1BGCPS_INTERPOL:") )
         return TRUE;
-    if ( EQUALN( poOpenInfo->pszFilename, "L1B_SOLAR_ZENITH_ANGLES:", strlen("L1B_SOLAR_ZENITH_ANGLES:") ) )
+    if ( STARTS_WITH_CI(poOpenInfo->pszFilename, "L1B_SOLAR_ZENITH_ANGLES:") )
         return TRUE;
-    if ( EQUALN( poOpenInfo->pszFilename, "L1B_ANGLES:", strlen("L1B_ANGLES:") ) )
+    if ( STARTS_WITH_CI(poOpenInfo->pszFilename, "L1B_ANGLES:") )
         return TRUE;
-    if ( EQUALN( poOpenInfo->pszFilename, "L1B_CLOUDS:", strlen("L1B_CLOUDS:") ) )
+    if ( STARTS_WITH_CI(poOpenInfo->pszFilename, "L1B_CLOUDS:") )
         return TRUE;
 
     if ( DetectFormat(CPLGetFilename(poOpenInfo->pszFilename),
@@ -3119,31 +3111,31 @@ GDALDataset *L1BDataset::Open( GDALOpenInfo * poOpenInfo )
     int bAskCloudsDS = FALSE;
     L1BFileFormat eL1BFormat;
 
-    if ( EQUALN( poOpenInfo->pszFilename, "L1BGCPS:", strlen("L1BGCPS:") ) ||
-         EQUALN( poOpenInfo->pszFilename, "L1BGCPS_INTERPOL:", strlen("L1BGCPS_INTERPOL:") ) ||
-         EQUALN( poOpenInfo->pszFilename, "L1B_SOLAR_ZENITH_ANGLES:", strlen("L1B_SOLAR_ZENITH_ANGLES:") )||
-         EQUALN( poOpenInfo->pszFilename, "L1B_ANGLES:", strlen("L1B_ANGLES:") )||
-         EQUALN( poOpenInfo->pszFilename, "L1B_CLOUDS:", strlen("L1B_CLOUDS:") ) )
+    if ( STARTS_WITH_CI(poOpenInfo->pszFilename, "L1BGCPS:") ||
+         STARTS_WITH_CI(poOpenInfo->pszFilename, "L1BGCPS_INTERPOL:") ||
+         STARTS_WITH_CI(poOpenInfo->pszFilename, "L1B_SOLAR_ZENITH_ANGLES:")||
+         STARTS_WITH_CI(poOpenInfo->pszFilename, "L1B_ANGLES:")||
+         STARTS_WITH_CI(poOpenInfo->pszFilename, "L1B_CLOUDS:") )
     {
         GByte abyHeader[1024];
         const char* pszFilename;
-        if( EQUALN( poOpenInfo->pszFilename, "L1BGCPS_INTERPOL:", strlen("L1BGCPS_INTERPOL:")) )
+        if( STARTS_WITH_CI(poOpenInfo->pszFilename, "L1BGCPS_INTERPOL:") )
         {
             bAskGeolocationDS = TRUE;
             bInterpolGeolocationDS = TRUE;
             pszFilename = poOpenInfo->pszFilename + strlen("L1BGCPS_INTERPOL:");
         }
-        else if (EQUALN( poOpenInfo->pszFilename, "L1BGCPS:", strlen("L1BGCPS:") ) )
+        else if (STARTS_WITH_CI(poOpenInfo->pszFilename, "L1BGCPS:") )
         {
             bAskGeolocationDS = TRUE;
             pszFilename = poOpenInfo->pszFilename + strlen("L1BGCPS:");
         }
-        else if (EQUALN( poOpenInfo->pszFilename, "L1B_SOLAR_ZENITH_ANGLES:", strlen("L1B_SOLAR_ZENITH_ANGLES:") ) )
+        else if (STARTS_WITH_CI(poOpenInfo->pszFilename, "L1B_SOLAR_ZENITH_ANGLES:") )
         {
             bAskSolarZenithAnglesDS = TRUE;
             pszFilename = poOpenInfo->pszFilename + strlen("L1B_SOLAR_ZENITH_ANGLES:");
         }
-        else if (EQUALN( poOpenInfo->pszFilename, "L1B_ANGLES:", strlen("L1B_ANGLES:") ) )
+        else if (STARTS_WITH_CI(poOpenInfo->pszFilename, "L1B_ANGLES:") )
         {
             bAskAnglesDS = TRUE;
             pszFilename = poOpenInfo->pszFilename + strlen("L1B_ANGLES:");
@@ -3165,7 +3157,7 @@ GDALDataset *L1BDataset::Open( GDALOpenInfo * poOpenInfo )
                      "Can't open file \"%s\".", osFilename.c_str() );
             return NULL;
         }
-        VSIFReadL( abyHeader, 1, sizeof(abyHeader)-1, fp);
+        CPL_IGNORE_RET_VAL(VSIFReadL( abyHeader, 1, sizeof(abyHeader)-1, fp));
         abyHeader[sizeof(abyHeader)-1] = '\0';
         eL1BFormat = DetectFormat( CPLGetFilename(osFilename),
                                    abyHeader, sizeof(abyHeader) );
@@ -3178,7 +3170,7 @@ GDALDataset *L1BDataset::Open( GDALOpenInfo * poOpenInfo )
     if ( eL1BFormat == L1B_NONE )
     {
         if( fp != NULL )
-            VSIFCloseL(fp);
+            CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
         return NULL;
     }
 
@@ -3187,11 +3179,11 @@ GDALDataset *L1BDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The L1B driver does not support update access to existing"
                   " datasets.\n" );
         if( fp != NULL )
-            VSIFCloseL(fp);
+            CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
         return NULL;
     }
 
@@ -3206,12 +3198,12 @@ GDALDataset *L1BDataset::Open( GDALOpenInfo * poOpenInfo )
     if( fp == NULL )
         fp = VSIFOpenL( osFilename, "rb" );
     poDS->fp = fp;
-    if ( !poDS->fp )
+    if ( !poDS->fp || VSIStatL(osFilename, &sStat) != 0 )
     {
         CPLDebug( "L1B", "Can't open file \"%s\".", osFilename.c_str() );
         goto bad;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read the header.                                                */
 /* -------------------------------------------------------------------- */
@@ -3221,8 +3213,6 @@ GDALDataset *L1BDataset::Open( GDALOpenInfo * poOpenInfo )
         goto bad;
     }
 
-    VSIStatL(osFilename, &sStat);
-
     if( poDS->eL1BFormat == L1B_NOAA15_NOHDR &&
         poDS->nRecordSizeFromHeader == 22016 &&
         (sStat.st_size % poDS->nRecordSizeFromHeader) == 0 )
@@ -3249,7 +3239,7 @@ GDALDataset *L1BDataset::Open( GDALOpenInfo * poOpenInfo )
             if (!poDS->ComputeFileOffsets())
                 goto bad;
 
-            nTempYSize = (sStat.st_size - poDS->nDataStartOffset) / poDS->nRecordSize;
+            nTempYSize = static_cast<int>((sStat.st_size - poDS->nDataStartOffset) / poDS->nRecordSize);
             if (nTempYSize < 5)
                 continue;
 
@@ -3260,8 +3250,8 @@ GDALDataset *L1BDataset::Open( GDALOpenInfo * poOpenInfo )
             {
                 nScanlineNumber = 0;
 
-                VSIFSeekL(poDS->fp, poDS->nDataStartOffset + i * poDS->nRecordSize, SEEK_SET);
-                VSIFReadL(&nScanlineNumber, 1, 2, poDS->fp);
+                CPL_IGNORE_RET_VAL(VSIFSeekL(poDS->fp, poDS->nDataStartOffset + i * poDS->nRecordSize, SEEK_SET));
+                CPL_IGNORE_RET_VAL(VSIFReadL(&nScanlineNumber, 1, 2, poDS->fp));
                 nScanlineNumber = poDS->GetUInt16(&nScanlineNumber);
 
                 if (i == 1)
@@ -3306,10 +3296,11 @@ GDALDataset *L1BDataset::Open( GDALOpenInfo * poOpenInfo )
     CPLDebug("L1B", "iCLAVRStart = %d", poDS->iCLAVRStart);
     CPLDebug("L1B", "nRecordSize = %d", poDS->nRecordSize);
 
-    // Compute number of lines dinamycally, so we can read partially
-    // downloaded files
+    // Compute number of lines dynamically, so we can read partially
+    // downloaded files.
     poDS->nRasterYSize =
-        (sStat.st_size - poDS->nDataStartOffset) / poDS->nRecordSize;
+        static_cast<int>( (sStat.st_size - poDS->nDataStartOffset)
+                          / poDS->nRecordSize);
 
 /* -------------------------------------------------------------------- */
 /*      Deal with GCPs                                                  */
@@ -3357,7 +3348,7 @@ GDALDataset *L1BDataset::Open( GDALOpenInfo * poOpenInfo )
 
     {
         CPLString  osTMP;
-        int bInterpol = CSLTestBoolean(CPLGetConfigOption("L1B_INTERPOL_GCPS", "TRUE"));
+        int bInterpol = CPLTestBool(CPLGetConfigOption("L1B_INTERPOL_GCPS", "TRUE"));
 
         poOutDS->SetMetadataItem( "SRS", poDS->pszGCPProjection, "GEOLOCATION" ); /* unused by gdalgeoloc.cpp */
 
@@ -3386,7 +3377,7 @@ GDALDataset *L1BDataset::Open( GDALOpenInfo * poOpenInfo )
         poOutDS->SetMetadataItem( "LINE_OFFSET", "0", "GEOLOCATION" );
         poOutDS->SetMetadataItem( "LINE_STEP", "1", "GEOLOCATION" );
     }
-    
+
     if( poOutDS != poDS )
         return poOutDS;
 
@@ -3424,11 +3415,11 @@ GDALDataset *L1BDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
     int iBand, i;
-    
+
     for( iBand = 1, i = 0; iBand <= poDS->nBands; iBand++ )
     {
         poDS->SetBand( iBand, new L1BRasterBand( poDS, iBand ));
-        
+
         // Channels descriptions
         if ( poDS->eSpacecraftID >= NOAA6 && poDS->eSpacecraftID <= METOP3 )
         {
@@ -3452,7 +3443,7 @@ GDALDataset *L1BDataset::Open( GDALOpenInfo * poOpenInfo )
                         poDS->GetRasterBand(iBand)->SetDescription( apszBandDesc[7] );
                     else
                         poDS->GetRasterBand(iBand)->SetDescription( apszBandDesc[6] );
-                else    
+                else
                     poDS->GetRasterBand(iBand)->SetDescription( apszBandDesc[2] );
                 i |= 0x04;
                 continue;
@@ -3478,7 +3469,7 @@ GDALDataset *L1BDataset::Open( GDALOpenInfo * poOpenInfo )
             }
         }
     }
-    
+
     if( poDS->bExposeMaskBand )
         poDS->poMaskBand = new L1BMaskBand(poDS);
 
@@ -3496,7 +3487,7 @@ GDALDataset *L1BDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Fetch metadata in CSV file                                      */
 /* -------------------------------------------------------------------- */
-    if( CSLTestBoolean(CPLGetConfigOption("L1B_FETCH_METADATA", "NO")) )
+    if( CPLTestBool(CPLGetConfigOption("L1B_FETCH_METADATA", "NO")) )
     {
         poDS->FetchMetadata();
     }
@@ -3515,25 +3506,21 @@ bad:
 void GDALRegister_L1B()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "L1B" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "L1B" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "L1B" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "NOAA Polar Orbiter Level 1b Data Set" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_l1b.html" );
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
+    poDriver->SetDescription( "L1B" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "NOAA Polar Orbiter Level 1b Data Set" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_l1b.html" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
 
-        poDriver->pfnOpen = L1BDataset::Open;
-        poDriver->pfnIdentify = L1BDataset::Identify;
+    poDriver->pfnOpen = L1BDataset::Open;
+    poDriver->pfnIdentify = L1BDataset::Identify;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/leveller/frmt_leveller.html b/frmts/leveller/frmt_leveller.html
index 39a0aae..b2a10f3 100644
--- a/frmts/leveller/frmt_leveller.html
+++ b/frmts/leveller/frmt_leveller.html
@@ -8,52 +8,53 @@
 <h1>Leveller --- Daylon Leveller Heightfield</h1>
 
 Leveller heightfields store 32-bit elevation values.
-Format versions 4 through 7 are supported with various caveats 
-(see below). The file extension for Leveller heightfields is "TER" (which 
+Format versions 4 through 9 are supported with various caveats
+(see below). The file extension for Leveller heightfields is "TER" (which
 is the same as Terragen, but the driver only recognizes Leveller files).<p>
 
-Blocks are organized as pixel-high scanlines (rows), with the first scanline 
-at the top (north) edge of the DEM, and adjacent pixels on each line 
+Blocks are organized as pixel-high scanlines (rows), with the first scanline
+at the top (north) edge of the DEM, and adjacent pixels on each line
 increasing from left to right (west to east).<p>
 
-The band type is always Float32, even though format versions 4 and 5 
-physically use 16.16 fixed-point. The driver autoconverts them to 
+The band type is always Float32, even though format versions 4 and 5
+physically use 16.16 fixed-point. The driver auto-converts them to
 floating-point.<p>
 
 
 <h2>Reading</h2>
-<tt>dataset::GetProjectionRef()</tt> will return only a local coordinate system 
+<tt>dataset::GetProjectionRef()</tt> will return only a local coordinate system
 for file versions 4 through 6.<p>
 
-<tt>dataset::GetGeoTransform()</tt> returns a simple world scaling with a centered 
-origin for formats 4 through 6. For version 7, it returns a realworld transform 
-except for rotations. The identity transform is not considered an error condition; 
+<tt>dataset::GetGeoTransform()</tt> returns a simple world scaling with a centered
+origin for formats 4 through 6. For versions 7 and higher, it returns a real-world transform
+except for rotations. The identity transform is not considered an error condition;
 Leveller documents often use them.<p>
 
-<tt>band::GetUnitType()</tt> will report the measurement units used 
+<tt>band::GetUnitType()</tt> will report the measurement units used
 by the file instead of converting unusual types to meters.
 A list of unit types is in the <tt>levellerdataset.cpp</tt> module.<p>
 
-<tt>band::GetScale()</tt> and <tt>band::GetOffset()</tt> will 
-return the physical-to-logical (i.e., raw to realworld) transform 
+<tt>band::GetScale()</tt> and <tt>band::GetOffset()</tt> will
+return the physical-to-logical (i.e., raw to real-world) transform
 for the elevation data.<p>
 
 
 <h2>Writing</h2>
 The <tt>dataset::Create()</tt> call is supported, but for version 7 files only.<p>
 
-<tt>band::SetUnitType()</tt> can be set to any of the unit types listed 
+<tt>band::SetUnitType()</tt> can be set to any of the unit types listed
 in the <tt>levellerdataset.cpp</tt> module.<p>
 
 <tt>dataset::SetGeoTransform()</tt> should not include rotation data.<p>
 
-As with the Terragen driver, the <tt>MINUSERPIXELVALUE</tt> option must be 
-specified. This lets the driver correctly map from logical (realworld) elevations 
+As with the Terragen driver, the <tt>MINUSERPIXELVALUE</tt> option must be
+specified. This lets the driver correctly map from logical (real-world) elevations
 to physical elevations.<p>
 
 Header information is written out on the first call to <tt>band::IWriteBlock</tt>.<p>
 
 <h2>History</h2>
+v1.3 (Aug 30/14): Added v9 read support, fixed missing typecast warnings.<p>
 v1.2 (Jul 17/07): Added v7 and Create support.<p>
 v1.1 (Oct 20/05): Fixed coordsys and elev scaling errors.<p>
 
@@ -62,8 +63,8 @@ v1.1 (Oct 20/05): Fixed coordsys and elev scaling errors.<p>
 <ul>
 <li> Implemented as <tt>gdal/frmts/leveller/levellerdataset.cpp</tt>.<p>
 
-<li> <a href="http://www.daylongraphics.com/products/leveller/dev/index.htm">
-Leveller SDK</a>, which documents the Leveller format.<p>
+<li> Visit <a href="http://www.daylongraphics.com">Daylon Graphics</a>
+for the Leveller SDK, which documents the Leveller format.<p>
 
 </ul>
 
diff --git a/frmts/leveller/levellerdataset.cpp b/frmts/leveller/levellerdataset.cpp
index 98cbd30..d16db53 100644
--- a/frmts/leveller/levellerdataset.cpp
+++ b/frmts/leveller/levellerdataset.cpp
@@ -5,7 +5,7 @@
  * Purpose:  Reader for Leveller TER documents
  * Author:   Ray Gardener, Daylon Graphics Ltd.
  *
- * Portions of this module derived from GDAL drivers by 
+ * Portions of this module derived from GDAL drivers by
  * Frank Warmerdam, see http://www.gdal.org
  *
  ******************************************************************************
@@ -32,24 +32,19 @@
  ****************************************************************************/
 
 
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: levellerdataset.cpp 28435 2015-02-07 14:35:34Z rouault $");
+CPL_CVSID("$Id: levellerdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
-CPL_C_START
-void	GDALRegister_Leveller(void);
-CPL_C_END
-
-#if 1
-
-#define str_equal(_s1, _s2)	(0 == strcmp((_s1),(_s2)))
-#define array_size(_a)		(sizeof(_a) / sizeof(_a[0]))
+static bool str_equal(const char *_s1, const char *_s2) {
+    return 0 == strcmp(_s1, _s2);
+}
 
 /*GDALDataset *LevellerCreateCopy( const char *, GDALDataset *, int, char **,
-                                GDALProgressFunc pfnProgress, 
+                                GDALProgressFunc pfnProgress,
                                 void * pProgressData );
-
 */
 
 /************************************************************************/
@@ -158,7 +153,7 @@ static const double kdays_per_year = 365.25;
 static const double kdLStoM = 299792458.0;
 static const double kdLYtoM = kdLStoM * kdays_per_year * 24 * 60 * 60;
 static const double kdInch = 0.3048 / 12;
-static const double kPI = 3.1415926535897932384626433832795;
+static const double kPI = M_PI;
 
 static const int kFirstLinearMeasureIdx = 9;
 
@@ -169,66 +164,66 @@ static const measurement_unit kUnits[] =
 	{ "%", 1.0, UNITLABEL_PERCENT }, // not actually used
 
 	{ "rad", 1.0, UNITLABEL_RADIAN },
-	{ "\xB0", kPI / 180.0, UNITLABEL_DEGREE }, // \xB0 is Unicode degree symbol 
+	{ "\xB0", kPI / 180.0, UNITLABEL_DEGREE }, // \xB0 is Unicode degree symbol
 	{ "d", kPI / 180.0, UNITLABEL_DEGREE },
 	{ "deg", kPI / 180.0, UNITLABEL_DEGREE },
 	{ "'", kPI / (60.0 * 180.0), UNITLABEL_ARCMINUTE },
 	{ "\"", kPI / (3600.0 * 180.0), UNITLABEL_ARCSECOND },
 
 	{ "ym", 1.0e-24, UNITLABEL_YM },
-	{ "zm", 1.0e-21, UNITLABEL_ZM }, 
+	{ "zm", 1.0e-21, UNITLABEL_ZM },
 	{ "am", 1.0e-18, UNITLABEL_AM },
-	{ "fm", 1.0e-15, UNITLABEL_FM }, 
-	{ "pm", 1.0e-12, UNITLABEL_PM }, 
-	{ "A",  1.0e-10, UNITLABEL_A }, 
-	{ "nm", 1.0e-9, UNITLABEL_NM }, 
-	{ "u",  1.0e-6, UNITLABEL_U }, 
-	{ "um", 1.0e-6, UNITLABEL_UM }, 
-	{ "ppt", kdInch / 72.27, UNITLABEL_PPT }, 
-	{ "pt", kdInch / 72.0, UNITLABEL_PT }, 
-    { "mm", 1.0e-3, UNITLABEL_MM }, 
-	{ "p", kdInch / 6.0, UNITLABEL_P }, 
-	{ "cm", 1.0e-2, UNITLABEL_CM }, 
-	{ "in", kdInch, UNITLABEL_IN }, 
-	{ "dft", 0.03048, UNITLABEL_DFT }, 
-	{ "dm", 0.1, UNITLABEL_DM }, 
-	{ "li", 0.2011684 /* GDAL 0.20116684023368047 ? */, UNITLABEL_LI },  
-	{ "sli", 0.201168402336805, UNITLABEL_SLI }, 
-	{ "sp", 0.2286, UNITLABEL_SP }, 
-	{ "ft", 0.3048, UNITLABEL_FT }, 
-	{ "sft", 1200.0 / 3937.0, UNITLABEL_SFT }, 
-    { "yd", 0.9144, UNITLABEL_YD }, 
-	{ "syd", 0.914401828803658, UNITLABEL_SYD }, 
-	{ "m", 1.0, UNITLABEL_M }, 
-	{ "fath", 1.8288, UNITLABEL_FATH }, 
-	{ "rd", 5.02921, UNITLABEL_RD }, 
-	{ "dam", 10.0, UNITLABEL_DAM }, 
-	{ "dkm", 10.0, UNITLABEL_DKM }, 
-	{ "ch", 20.1168 /* GDAL: 2.0116684023368047 ? */, UNITLABEL_CH },  
-	{ "sch", 20.1168402336805, UNITLABEL_SCH }, 
+	{ "fm", 1.0e-15, UNITLABEL_FM },
+	{ "pm", 1.0e-12, UNITLABEL_PM },
+	{ "A",  1.0e-10, UNITLABEL_A },
+	{ "nm", 1.0e-9, UNITLABEL_NM },
+	{ "u",  1.0e-6, UNITLABEL_U },
+	{ "um", 1.0e-6, UNITLABEL_UM },
+	{ "ppt", kdInch / 72.27, UNITLABEL_PPT },
+	{ "pt", kdInch / 72.0, UNITLABEL_PT },
+    { "mm", 1.0e-3, UNITLABEL_MM },
+	{ "p", kdInch / 6.0, UNITLABEL_P },
+	{ "cm", 1.0e-2, UNITLABEL_CM },
+	{ "in", kdInch, UNITLABEL_IN },
+	{ "dft", 0.03048, UNITLABEL_DFT },
+	{ "dm", 0.1, UNITLABEL_DM },
+	{ "li", 0.2011684 /* GDAL 0.20116684023368047 ? */, UNITLABEL_LI },
+	{ "sli", 0.201168402336805, UNITLABEL_SLI },
+	{ "sp", 0.2286, UNITLABEL_SP },
+	{ "ft", 0.3048, UNITLABEL_FT },
+	{ "sft", 1200.0 / 3937.0, UNITLABEL_SFT },
+    { "yd", 0.9144, UNITLABEL_YD },
+	{ "syd", 0.914401828803658, UNITLABEL_SYD },
+	{ "m", 1.0, UNITLABEL_M },
+	{ "fath", 1.8288, UNITLABEL_FATH },
+	{ "rd", 5.02921, UNITLABEL_RD },
+	{ "dam", 10.0, UNITLABEL_DAM },
+	{ "dkm", 10.0, UNITLABEL_DKM },
+	{ "ch", 20.1168 /* GDAL: 2.0116684023368047 ? */, UNITLABEL_CH },
+	{ "sch", 20.1168402336805, UNITLABEL_SCH },
 	{ "hm", 100.0, UNITLABEL_HM },
-	{ "f", 201.168, UNITLABEL_F }, 
-	{ "km", 1000.0, UNITLABEL_KM }, 
-	{ "mi", 1609.344, UNITLABEL_MI }, 
-	{ "smi", 1609.34721869444, UNITLABEL_SMI }, 
-	{ "nmi", 1853.0, UNITLABEL_NMI }, 
-	{ "Mm", 1.0e+6, UNITLABEL_MEGAM }, 
-    { "ls", kdLStoM, UNITLABEL_LS }, 
-	{ "Gm", 1.0e+9, UNITLABEL_GM }, 
-	{ "lm", kdLStoM * 60, UNITLABEL_LM }, 
-	{ "AU", 8.317 * kdLStoM * 60, UNITLABEL_AU }, 
-	{ "Tm", 1.0e+12, UNITLABEL_TM }, 
-	{ "lhr", 60.0 * 60.0 * kdLStoM, UNITLABEL_LHR }, 
-	{ "ld", 24 * 60.0 * 60.0 * kdLStoM, UNITLABEL_LD },  
-	{ "Pm", 1.0e+15, UNITLABEL_PETAM }, 
-	{ "ly", kdLYtoM, UNITLABEL_LY }, 
-	{ "pc", 3.2616 * kdLYtoM, UNITLABEL_PC }, 
-	{ "Em", 1.0e+18, UNITLABEL_EXAM }, 
-	{ "kly", 1.0e+3 * kdLYtoM, UNITLABEL_KLY }, 
-	{ "kpc", 3.2616 * 1.0e+3 * kdLYtoM, UNITLABEL_KPC }, 
-	{ "Zm", 1.0e+21, UNITLABEL_ZETTAM }, 
-	{ "Mly", 1.0e+6 * kdLYtoM, UNITLABEL_MLY }, 
-	{ "Mpc", 3.2616 * 1.0e+6 * kdLYtoM, UNITLABEL_MPC }, 
+	{ "f", 201.168, UNITLABEL_F },
+	{ "km", 1000.0, UNITLABEL_KM },
+	{ "mi", 1609.344, UNITLABEL_MI },
+	{ "smi", 1609.34721869444, UNITLABEL_SMI },
+	{ "nmi", 1853.0, UNITLABEL_NMI },
+	{ "Mm", 1.0e+6, UNITLABEL_MEGAM },
+    { "ls", kdLStoM, UNITLABEL_LS },
+	{ "Gm", 1.0e+9, UNITLABEL_GM },
+	{ "lm", kdLStoM * 60, UNITLABEL_LM },
+	{ "AU", 8.317 * kdLStoM * 60, UNITLABEL_AU },
+	{ "Tm", 1.0e+12, UNITLABEL_TM },
+	{ "lhr", 60.0 * 60.0 * kdLStoM, UNITLABEL_LHR },
+	{ "ld", 24 * 60.0 * 60.0 * kdLStoM, UNITLABEL_LD },
+	{ "Pm", 1.0e+15, UNITLABEL_PETAM },
+	{ "ly", kdLYtoM, UNITLABEL_LY },
+	{ "pc", 3.2616 * kdLYtoM, UNITLABEL_PC },
+	{ "Em", 1.0e+18, UNITLABEL_EXAM },
+	{ "kly", 1.0e+3 * kdLYtoM, UNITLABEL_KLY },
+	{ "kpc", 3.2616 * 1.0e+3 * kdLYtoM, UNITLABEL_KPC },
+	{ "Zm", 1.0e+21, UNITLABEL_ZETTAM },
+	{ "Mly", 1.0e+6 * kdLYtoM, UNITLABEL_MLY },
+	{ "Mpc", 3.2616 * 1.0e+6 * kdLYtoM, UNITLABEL_MPC },
 	{ "Ym", 1.0e+24, UNITLABEL_YOTTAM }
 };
 
@@ -248,20 +243,20 @@ class LevellerRasterBand;
 class LevellerDataset : public GDALPamDataset
 {
     friend class LevellerRasterBand;
-	friend class digital_axis;
+    friend class digital_axis;
 
     int			m_version;
 
-	char*		m_pszFilename;
+    char*		m_pszFilename;
     char*		m_pszProjection;
 
     //char		m_szUnits[8];
-	char		m_szElevUnits[8];
+    char		m_szElevUnits[8];
     double		m_dElevScale;	// physical-to-logical scaling.
     double		m_dElevBase;	// logical offset.
     double		m_adfTransform[6];
-	//double		m_dMeasurePerPixel;
-	double		m_dLogSpan[2];
+    //double		m_dMeasurePerPixel;
+    double		m_dLogSpan[2];
 
     VSILFILE*			m_fp;
     vsi_l_offset	m_nDataOffset;
@@ -303,7 +298,7 @@ class LevellerDataset : public GDALPamDataset
 public:
     LevellerDataset();
     ~LevellerDataset();
-    
+
     static GDALDataset* Open( GDALOpenInfo* );
 	static int Identify( GDALOpenInfo* );
     static GDALDataset* Create( const char* pszFilename,
@@ -321,21 +316,21 @@ public:
 class digital_axis
 {
 	public:
-		digital_axis() : m_eStyle(LEV_DA_PIXEL_SIZED) {}
+  digital_axis() : m_eStyle(LEV_DA_PIXEL_SIZED), m_fixedEnd(0) {}
 
 		bool get(LevellerDataset& ds, VSILFILE* fp, int n)
 		{
 			char szTag[32];
-			sprintf(szTag, "coordsys_da%d_style", n);
+			snprintf(szTag, sizeof(szTag), "coordsys_da%d_style", n);
 			if(!ds.get(m_eStyle, fp, szTag))
 				return false;
-			sprintf(szTag, "coordsys_da%d_fixedend", n);
+			snprintf(szTag, sizeof(szTag), "coordsys_da%d_fixedend", n);
 			if(!ds.get(m_fixedEnd, fp, szTag))
 				return false;
-			sprintf(szTag, "coordsys_da%d_v0", n);
+			snprintf(szTag, sizeof(szTag), "coordsys_da%d_v0", n);
 			if(!ds.get(m_d[0], fp, szTag))
 				return false;
-			sprintf(szTag, "coordsys_da%d_v1", n);
+			snprintf(szTag, sizeof(szTag), "coordsys_da%d_v1", n);
 			if(!ds.get(m_d[1], fp, szTag))
 				return false;
 			return true;
@@ -352,7 +347,7 @@ class digital_axis
 
 					case LEV_DA_PIXEL_SIZED:
 						return m_d[1] + (m_d[0] * (pixels-1));
-				}					
+				}
 			}
 			return m_d[0];
 		}
@@ -363,7 +358,7 @@ class digital_axis
 			if(m_eStyle == LEV_DA_PIXEL_SIZED)
 				return m_d[1 - m_fixedEnd];
 
-			return this->length(pixels) / (pixels - 1);
+			return this->length(static_cast<int>(pixels)) / (pixels - 1);
 		}
 
 		double length(int pixels) const
@@ -380,7 +375,7 @@ class digital_axis
 
 				case LEV_DA_PIXEL_SIZED:
 					return m_d[1 - m_fixedEnd] * (pixels-1);
-					
+
 			}
 			CPLAssert(FALSE);
 			return 0.0;
@@ -388,7 +383,7 @@ class digital_axis
 
 
 	protected:
-		int		m_eStyle;
+		int	m_eStyle;
 		size_t	m_fixedEnd;
 		double	m_d[2];
 };
@@ -409,9 +404,11 @@ class LevellerRasterBand : public GDALPamRasterBand
 
 public:
 
-    LevellerRasterBand(LevellerDataset*);
+    explicit LevellerRasterBand(LevellerDataset*);
     ~LevellerRasterBand();
-    
+
+    bool        Init();
+
     // Geomeasure support.
     virtual const char* GetUnitType();
     virtual double GetScale(int* pbSuccess = NULL);
@@ -419,7 +416,7 @@ public:
 
     virtual CPLErr IReadBlock( int, int, void * );
     virtual CPLErr IWriteBlock( int, int, void * );
-	virtual CPLErr SetUnitType( const char* );
+    virtual CPLErr SetUnitType( const char* );
 };
 
 
@@ -427,27 +424,34 @@ public:
 /*                         LevellerRasterBand()                         */
 /************************************************************************/
 
-LevellerRasterBand::LevellerRasterBand( LevellerDataset *poDS )
-	:
-	m_pLine(NULL),
-	m_bFirstTime(true)
+LevellerRasterBand::LevellerRasterBand( LevellerDataset *poDSIn ) :
+    m_pLine(NULL),
+    m_bFirstTime(true)
 {
-    this->poDS = poDS;
+    this->poDS = poDSIn;
     this->nBand = 1;
 
     eDataType = GDT_Float32;
 
     nBlockXSize = poDS->GetRasterXSize();
-    nBlockYSize = 1;//poDS->GetRasterYSize();
-
-	m_pLine = (float*)CPLMalloc(sizeof(float) * nBlockXSize);
+    nBlockYSize = 1; // poDS->GetRasterYSize();
 }
 
 
+/************************************************************************/
+/*                           Init()                                     */
+/************************************************************************/
+
+bool LevellerRasterBand::Init()
+{
+    m_pLine = reinterpret_cast<float*>(
+        VSI_MALLOC2_VERBOSE( sizeof(float), nBlockXSize) );
+    return m_pLine != NULL;
+}
+
 LevellerRasterBand::~LevellerRasterBand()
 {
-	if(m_pLine != NULL)
-		CPLFree(m_pLine);
+    CPLFree(m_pLine);
 }
 
 /************************************************************************/
@@ -471,7 +475,7 @@ CPLErr LevellerRasterBand::IWriteBlock
 */
 	const size_t pixelsize = sizeof(float);
 
-	LevellerDataset& ds = *(LevellerDataset*)poDS;
+	LevellerDataset& ds = *reinterpret_cast<LevellerDataset*>( poDS );
 	if(m_bFirstTime)
 	{
 		m_bFirstTime = false;
@@ -480,22 +484,22 @@ CPLErr LevellerRasterBand::IWriteBlock
 		ds.m_nDataOffset = VSIFTellL(ds.m_fp);
 	}
 	const size_t rowbytes = nBlockXSize * pixelsize;
-	const float* pfImage = (float*)pImage;
+	const float* pfImage = reinterpret_cast<float *>( pImage );
 
 	if(0 == VSIFSeekL(
-       ds.m_fp, ds.m_nDataOffset + nBlockYOff * rowbytes, 
-       SEEK_SET))
+               ds.m_fp, ds.m_nDataOffset + nBlockYOff * rowbytes,
+               SEEK_SET))
 	{
 		for(size_t x = 0; x < (size_t)nBlockXSize; x++)
 		{
 			// Convert logical elevations to physical.
-                    m_pLine[x] = (float) 
-				((pfImage[x] - ds.m_dElevBase) / ds.m_dElevScale);
+                    m_pLine[x] = static_cast<float>(
+                        (pfImage[x] - ds.m_dElevBase) / ds.m_dElevScale );
 		}
 
-#ifdef CPL_MSB 
+#ifdef CPL_MSB
 		GDALSwapWords( m_pLine, pixelsize, nBlockXSize, pixelsize );
-#endif    
+#endif
 		if(1 == VSIFWriteL(m_pLine, rowbytes, 1, ds.m_fp))
 			return CE_None;
 	}
@@ -506,7 +510,7 @@ CPLErr LevellerRasterBand::IWriteBlock
 
 CPLErr LevellerRasterBand::SetUnitType( const char* psz )
 {
-	LevellerDataset& ds = *(LevellerDataset*)poDS;
+    LevellerDataset& ds = *reinterpret_cast<LevellerDataset *>( poDS );
 
 	if(strlen(psz) >= sizeof(ds.m_szElevUnits))
 		return CE_Failure;
@@ -530,7 +534,7 @@ CPLErr LevellerRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     CPLAssert( nBlockXOff == 0  );
     CPLAssert( pImage != NULL );
 
-    LevellerDataset *poGDS = (LevellerDataset *) poDS;
+    LevellerDataset *poGDS = reinterpret_cast<LevellerDataset *>( poDS );
 
 /* -------------------------------------------------------------------- */
 /*      Seek to scanline.                                               */
@@ -538,51 +542,50 @@ CPLErr LevellerRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     const size_t rowbytes = nBlockXSize * sizeof(float);
 
     if(0 != VSIFSeekL(
-           poGDS->m_fp, 
-           poGDS->m_nDataOffset + nBlockYOff * rowbytes, 
+           poGDS->m_fp,
+           poGDS->m_nDataOffset + nBlockYOff * rowbytes,
            SEEK_SET))
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
-                  ".bt Seek failed:%s", VSIStrerror( errno ) );
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Leveller seek failed: %s", VSIStrerror( errno ) );
         return CE_Failure;
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Read the scanline into the image buffer.                        */
 /* -------------------------------------------------------------------- */
 
     if( VSIFReadL( pImage, rowbytes, 1, poGDS->m_fp ) != 1 )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
-                  "Leveller read failed:%s", VSIStrerror( errno ) );
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Leveller read failed: %s", VSIStrerror( errno ) );
         return CE_Failure;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Swap on MSB platforms.                                          */
 /* -------------------------------------------------------------------- */
-#ifdef CPL_MSB 
+#ifdef CPL_MSB
     GDALSwapWords( pImage, 4, nRasterXSize, 4 );
-#endif    
+#endif
 
 /* -------------------------------------------------------------------- */
 /*      Convert from legacy-format fixed-point if necessary.            */
 /* -------------------------------------------------------------------- */
-    float* pf = (float*)pImage;
-	
+    float* pf = reinterpret_cast<float *>( pImage );
+
     if(poGDS->m_version < 6)
     {
-        GInt32* pi = (int*)pImage;
+        GInt32* pi = reinterpret_cast<int *>( pImage );
         for(size_t i = 0; i < (size_t)nBlockXSize; i++)
-            pf[i] = (float)pi[i] / 65536;
+            pf[i] = static_cast<float>( pi[i] ) / 65536;
     }
 
 
-#if 0
 /* -------------------------------------------------------------------- */
 /*      Convert raw elevations to realworld elevs.                      */
 /* -------------------------------------------------------------------- */
+#if 0
     for(size_t i = 0; i < nBlockXSize; i++)
         pf[i] *= poGDS->m_dWorldscale; //this->GetScale();
 #endif
@@ -590,28 +593,25 @@ CPLErr LevellerRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     return CE_None;
 }
 
-
-
 /************************************************************************/
 /*                            GetUnitType()                             */
 /************************************************************************/
 const char *LevellerRasterBand::GetUnitType()
 {
-	// Return elevation units.
+    // Return elevation units.
 
-	LevellerDataset *poGDS = (LevellerDataset *) poDS;
+    LevellerDataset *poGDS = reinterpret_cast<LevellerDataset *>( poDS );
 
     return poGDS->m_szElevUnits;
 }
 
-
 /************************************************************************/
 /*                              GetScale()                              */
 /************************************************************************/
 
 double LevellerRasterBand::GetScale(int* pbSuccess)
 {
-    LevellerDataset *poGDS = (LevellerDataset *) poDS;
+    LevellerDataset *poGDS = reinterpret_cast<LevellerDataset *>( poDS );
 	if(pbSuccess != NULL)
 		*pbSuccess = TRUE;
 	return poGDS->m_dElevScale;
@@ -623,13 +623,12 @@ double LevellerRasterBand::GetScale(int* pbSuccess)
 
 double LevellerRasterBand::GetOffset(int* pbSuccess)
 {
-    LevellerDataset *poGDS = (LevellerDataset *) poDS;
+    LevellerDataset *poGDS = reinterpret_cast<LevellerDataset *>( poDS );
 	if(pbSuccess != NULL)
 		*pbSuccess = TRUE;
 	return poGDS->m_dElevBase;
 }
 
-
 /************************************************************************/
 /* ==================================================================== */
 /*				LevellerDataset		                */
@@ -640,12 +639,10 @@ double LevellerRasterBand::GetOffset(int* pbSuccess)
 /*                          LevellerDataset()                           */
 /************************************************************************/
 
-LevellerDataset::LevellerDataset()
-{
-    m_fp = NULL;
-    m_pszProjection = NULL;
-    m_pszFilename = NULL;
-}
+LevellerDataset::LevellerDataset() :
+    m_version(0), m_pszFilename(NULL), m_pszProjection(NULL), m_dElevScale(),
+    m_dElevBase(), m_fp(NULL), m_nDataOffset()
+{ }
 
 /************************************************************************/
 /*                          ~LevellerDataset()                          */
@@ -662,7 +659,7 @@ LevellerDataset::~LevellerDataset()
         VSIFCloseL( m_fp );
 }
 
-static double degrees_to_radians(double d) 
+static double degrees_to_radians(double d)
 {
 	return (d * 0.017453292);
 }
@@ -708,23 +705,22 @@ bool LevellerDataset::compute_elev_scaling
 		const double kdEarthCircumPolar = 40007849;
 		const double kdEarthCircumEquat = 40075004;
 
-		double xr, yr;
-		xr = 0.5 * this->nRasterXSize;
-		yr = 0.5 * this->nRasterYSize;
+		const double xr = 0.5 * nRasterXSize;
+		const double yr = 0.5 * nRasterYSize;
 
 		double xg[2], yg[2];
-		this->raw_to_proj(xr, yr, xg[0], yg[0]);
-		this->raw_to_proj(xr+1, yr+1, xg[1], yg[1]);
-		
+		raw_to_proj(xr, yr, xg[0], yg[0]);
+		raw_to_proj(xr+1, yr+1, xg[1], yg[1]);
+
 		// The earths' circumference shrinks using a sin()
 		// curve as we go up in latitude.
-		const double dLatCircum = kdEarthCircumEquat 
+		const double dLatCircum = kdEarthCircumEquat
 			* sin(degrees_to_radians(90.0 - yg[0]));
 
 		// Derive meter distance between geolongitudes
 		// in xg[0] and xg[1].
-		double dx = fabs(xg[1] - xg[0]) / 360.0 * dLatCircum;
-		double dy = fabs(yg[1] - yg[0]) / 360.0 * kdEarthCircumPolar;
+		const double dx = fabs(xg[1] - xg[0]) / 360.0 * dLatCircum;
+		const double dy = fabs(yg[1] - yg[0]) / 360.0 * kdEarthCircumPolar;
 
 		m_dElevScale = average(dx, dy);
 	}
@@ -747,68 +743,67 @@ bool LevellerDataset::compute_elev_scaling
 
 bool LevellerDataset::write_header()
 {
-	char szHeader[5];
-	strcpy(szHeader, "trrn");
-	szHeader[4] = 7; // TER v7 introduced w/ Lev 2.6.
+    char szHeader[5];
+    strcpy(szHeader, "trrn");
+    szHeader[4] = 7; // TER v7 introduced w/ Lev 2.6.
 
-	if(1 != VSIFWriteL(szHeader, 5, 1, m_fp)
-		|| !this->write_tag("hf_w", (size_t)nRasterXSize)
-		|| !this->write_tag("hf_b", (size_t)nRasterYSize))
-	{
+    if(1 != VSIFWriteL(szHeader, 5, 1, m_fp)
+       || !this->write_tag("hf_w", (size_t)nRasterXSize)
+       || !this->write_tag("hf_b", (size_t)nRasterYSize))
+    {
         CPLError( CE_Failure, CPLE_FileIO, "Could not write header" );
         return false;
-	}
+    }
 
-	m_dElevBase = 0.0;
-	m_dElevScale = 1.0;
+    m_dElevBase = 0.0;
+    m_dElevScale = 1.0;
 
-	if(m_pszProjection == NULL || m_pszProjection[0] == 0)
-	{
-		this->write_tag("csclass", LEV_COORDSYS_RASTER);
-	}
-	else
-	{
-		this->write_tag("coordsys_wkt", m_pszProjection);
-		const UNITLABEL units_elev = this->id_to_code(m_szElevUnits);
-		
-		const int bHasECS = 
-			(units_elev != UNITLABEL_PIXEL && units_elev != UNITLABEL_UNKNOWN);
+    if(m_pszProjection == NULL || m_pszProjection[0] == 0)
+    {
+        write_tag("csclass", LEV_COORDSYS_RASTER);
+    }
+    else
+    {
+        write_tag("coordsys_wkt", m_pszProjection);
+        const UNITLABEL units_elev = this->id_to_code(m_szElevUnits);
 
-		this->write_tag("coordsys_haselevm", bHasECS);
+        const int bHasECS =
+            (units_elev != UNITLABEL_PIXEL && units_elev != UNITLABEL_UNKNOWN);
 
-	    OGRSpatialReference sr(m_pszProjection);
+	write_tag("coordsys_haselevm", bHasECS);
 
-		if(bHasECS)
-		{
-			if(!this->compute_elev_scaling(sr))
-				return false;
+        OGRSpatialReference sr(m_pszProjection);
 
-			// Raw-to-real units scaling.
-			this->write_tag("coordsys_em_scale", m_dElevScale);
+        if(bHasECS)
+        {
+            if(!this->compute_elev_scaling(sr))
+                return false;
 
-			//elev offset, in real units.
-			this->write_tag("coordsys_em_base", m_dElevBase);
-				
-			this->write_tag("coordsys_em_units", units_elev);
-		}
+            // Raw-to-real units scaling.
+            write_tag("coordsys_em_scale", m_dElevScale);
+
+            // Elev offset, in real units.
+            write_tag("coordsys_em_base", m_dElevBase);
+            write_tag("coordsys_em_units", units_elev);
+        }
 
 
-		if(sr.IsLocal())
-		{
-			this->write_tag("csclass", LEV_COORDSYS_LOCAL);
+        if(sr.IsLocal())
+        {
+            write_tag("csclass", LEV_COORDSYS_LOCAL);
 
-			const double dfLinear = sr.GetLinearUnits();
-			const int n = this->meter_measure_to_code(dfLinear);
-			this->write_tag("coordsys_units", n);
+            const double dfLinear = sr.GetLinearUnits();
+            const int n = this->meter_measure_to_code(dfLinear);
+            write_tag("coordsys_units", n);
 		}
 		else
 		{
-			this->write_tag("csclass", LEV_COORDSYS_GEO);
+            write_tag("csclass", LEV_COORDSYS_GEO);
 		}
 
 		if( m_adfTransform[2] != 0.0 || m_adfTransform[4] != 0.0)
 		{
-			CPLError( CE_Failure, CPLE_IllegalArg, 
+			CPLError( CE_Failure, CPLE_IllegalArg,
 				"Cannot handle rotated geotransform" );
 			return false;
 		}
@@ -818,20 +813,20 @@ bool LevellerDataset::write_header()
 		// We need to look into this and adjust accordingly.
 
 		// Write north-south digital axis.
-		this->write_tag("coordsys_da0_style", LEV_DA_PIXEL_SIZED);
-		this->write_tag("coordsys_da0_fixedend", 0);
-		this->write_tag("coordsys_da0_v0", m_adfTransform[3]);
-		this->write_tag("coordsys_da0_v1", m_adfTransform[5]);
+	    write_tag("coordsys_da0_style", LEV_DA_PIXEL_SIZED);
+            write_tag("coordsys_da0_fixedend", 0);
+            write_tag("coordsys_da0_v0", m_adfTransform[3]);
+            write_tag("coordsys_da0_v1", m_adfTransform[5]);
 
 		// Write east-west digital axis.
-		this->write_tag("coordsys_da1_style", LEV_DA_PIXEL_SIZED);
-		this->write_tag("coordsys_da1_fixedend", 0);
-		this->write_tag("coordsys_da1_v0", m_adfTransform[0]);
-		this->write_tag("coordsys_da1_v1", m_adfTransform[1]);
+	    write_tag("coordsys_da1_style", LEV_DA_PIXEL_SIZED);
+            write_tag("coordsys_da1_fixedend", 0);
+            write_tag("coordsys_da1_v0", m_adfTransform[0]);
+            write_tag("coordsys_da1_v1", m_adfTransform[1]);
 	}
 
 
-	this->write_tag_start("hf_data", 
+	this->write_tag_start("hf_data",
 		sizeof(float) * nRasterXSize * nRasterYSize);
 
 	return true;
@@ -844,8 +839,7 @@ bool LevellerDataset::write_header()
 
 CPLErr LevellerDataset::SetGeoTransform( double *padfGeoTransform )
 {
-	memcpy(m_adfTransform, padfGeoTransform, 
-		sizeof(m_adfTransform));
+    memcpy(m_adfTransform, padfGeoTransform, sizeof(m_adfTransform));
 
 	return CE_None;
 }
@@ -857,8 +851,7 @@ CPLErr LevellerDataset::SetGeoTransform( double *padfGeoTransform )
 
 CPLErr LevellerDataset::SetProjection( const char * pszNewProjection )
 {
-	if(m_pszProjection != NULL)
-		CPLFree(m_pszProjection);
+    CPLFree(m_pszProjection);
 
 	m_pszProjection = CPLStrdup(pszNewProjection);
 
@@ -873,7 +866,7 @@ GDALDataset* LevellerDataset::Create
 (
 	const char* pszFilename,
     int nXSize, int nYSize, int nBands,
-    GDALDataType eType, char** papszOptions 
+    GDALDataType eType, char** papszOptions
 )
 {
 	if(nBands != 1)
@@ -898,7 +891,7 @@ GDALDataset* LevellerDataset::Create
 	LevellerDataset* poDS = new LevellerDataset;
 
     poDS->eAccess = GA_Update;
-	
+
 	poDS->m_pszFilename = CPLStrdup(pszFilename);
 
     poDS->m_fp = VSIFOpenL( pszFilename, "wb+" );
@@ -918,58 +911,65 @@ GDALDataset* LevellerDataset::Create
     poDS->nRasterXSize = nXSize;
     poDS->nRasterYSize = nYSize;
 
-
-    const char* pszValue = CSLFetchNameValue( 
+    const char* pszValue = CSLFetchNameValue(
 		papszOptions,"MINUSERPIXELVALUE");
     if( pszValue != NULL )
         poDS->m_dLogSpan[0] = CPLAtof( pszValue );
 	else
 	{
 		delete poDS;
-		CPLError( CE_Failure, CPLE_IllegalArg, 
+		CPLError( CE_Failure, CPLE_IllegalArg,
 			"MINUSERPIXELVALUE must be specified." );
 		return NULL;
 	}
 
-    pszValue = CSLFetchNameValue( 
+    pszValue = CSLFetchNameValue(
 		papszOptions,"MAXUSERPIXELVALUE");
     if( pszValue != NULL )
         poDS->m_dLogSpan[1] = CPLAtof( pszValue );
 
-	if(poDS->m_dLogSpan[1] < poDS->m_dLogSpan[0])
-	{
-		double t = poDS->m_dLogSpan[0];
-		poDS->m_dLogSpan[0] = poDS->m_dLogSpan[1];
-		poDS->m_dLogSpan[1] = t;
-	}
+    if(poDS->m_dLogSpan[1] < poDS->m_dLogSpan[0])
+    {
+            double t = poDS->m_dLogSpan[0];
+            poDS->m_dLogSpan[0] = poDS->m_dLogSpan[1];
+            poDS->m_dLogSpan[1] = t;
+    }
+
+// --------------------------------------------------------------------
+//      Instance a band.
+// --------------------------------------------------------------------
+    LevellerRasterBand* poBand = new LevellerRasterBand( poDS );
+    poDS->SetBand( 1, poBand );
 
-// -------------------------------------------------------------------- 
-//      Instance a band.                                                
-// -------------------------------------------------------------------- 
-    poDS->SetBand( 1, new LevellerRasterBand( poDS ) );
+    if( !poBand->Init() )
+    {
+        delete poDS;
+        return NULL;
+    }
 
-	return poDS;
-}								
+    return poDS;
+}
 
 
 bool LevellerDataset::write_byte(size_t n)
 {
-	unsigned char uch = (unsigned char)n;
-	return (1 == VSIFWriteL(&uch, 1, 1, m_fp));
+    unsigned char uch = static_cast<unsigned char>( n );
+    return 1 == VSIFWriteL(&uch, 1, 1, m_fp);
 }
 
 
 bool LevellerDataset::write(int n)
 {
 	CPL_LSBPTR32(&n);
-	return (1 == VSIFWriteL(&n, sizeof(n), 1, m_fp));
+    return 1 == VSIFWriteL(&n, sizeof(n), 1, m_fp);
 }
 
 
 bool LevellerDataset::write(size_t n)
 {
-	CPL_LSBPTR32(&n);
-	return (1 == VSIFWriteL(&n, sizeof(n), 1, m_fp));
+        GUInt32 n32 = (GUInt32)n;
+	CPL_LSBPTR32(&n32);
+	return (1 == VSIFWriteL(&n32, sizeof(n32), 1, m_fp));
 }
 
 
@@ -988,7 +988,7 @@ bool LevellerDataset::write_tag_start(const char* pszTag, size_t n)
 		return (1 == VSIFWriteL(pszTag, strlen(pszTag), 1, m_fp)
 			&& this->write(n));
 	}
-	
+
 	return false;
 }
 
@@ -1019,12 +1019,12 @@ bool LevellerDataset::write_tag(const char* pszTag, const char* psz)
 	CPLAssert(strlen(pszTag) <= kMaxTagNameLen);
 
 	char sz[kMaxTagNameLen + 1];
-	sprintf(sz, "%sl", pszTag);
+	snprintf(sz, sizeof(sz), "%sl", pszTag);
 	const size_t len = strlen(psz);
 
 	if(len > 0 && this->write_tag(sz, len))
 	{
-		sprintf(sz, "%sd", pszTag);
+		snprintf(sz, sizeof(sz), "%sd", pszTag);
 		this->write_tag_start(sz, len);
 		return (1 == VSIFWriteL(psz, len, 1, m_fp));
 	}
@@ -1036,7 +1036,7 @@ bool LevellerDataset::locate_data(vsi_l_offset& offset, size_t& len, VSILFILE* f
 {
     // Locate the file offset of the desired tag's data.
     // If it is not available, return false.
-    // If the tag is found, leave the filemark at the 
+    // If the tag is found, leave the filemark at the
     // start of its data.
 
     if(0 != VSIFSeekL(fp, 5, SEEK_SET))
@@ -1093,10 +1093,10 @@ bool LevellerDataset::get(int& n, VSILFILE* fp, const char* psz)
         if(1 == VSIFReadL(&value, sizeof(value), 1, fp))
         {
             CPL_LSBPTR32(&value);
-            n = (int)value;
+            n = static_cast<int>( value );
             return true;
         }
-    }	
+    }
     return false;
 }
 
@@ -1116,7 +1116,7 @@ bool LevellerDataset::get(double& d, VSILFILE* fp, const char* pszTag)
             CPL_LSBPTR64(&d);
             return true;
         }
-    }	
+    }
     return false;
 }
 
@@ -1130,7 +1130,7 @@ bool LevellerDataset::get(char* pszValue, size_t maxchars, VSILFILE* fp, const c
 
     // We can assume 8-bit encoding, so just go straight
     // to the *_d tag.
-    sprintf(szTag, "%sd", pszTag);
+    snprintf(szTag, sizeof(szTag), "%sd", pszTag);
 
     vsi_l_offset offset;
     size_t		 len;
@@ -1145,7 +1145,7 @@ bool LevellerDataset::get(char* pszValue, size_t maxchars, VSILFILE* fp, const c
             pszValue[len] = 0; // terminate C-string
             return true;
         }
-    }	
+    }
 
     return false;
 }
@@ -1165,7 +1165,7 @@ UNITLABEL LevellerDataset::meter_measure_to_code(double dM) const
 
 UNITLABEL LevellerDataset::id_to_code(const char* pszUnits) const
 {
-	// Convert a readable UOM to its OEM code. 
+	// Convert a readable UOM to its OEM code.
 
 	const measurement_unit* pu = this->get_uom(pszUnits);
 	return (pu != NULL ? pu->oemCode : UNITLABEL_UNKNOWN);
@@ -1174,7 +1174,7 @@ UNITLABEL LevellerDataset::id_to_code(const char* pszUnits) const
 
 const char* LevellerDataset::code_to_id(UNITLABEL code) const
 {
-	// Convert a measurement unit's OEM ID to its readable ID. 
+	// Convert a measurement unit's OEM ID to its readable ID.
 
 	const measurement_unit* pu = this->get_uom(code);
 	return (pu != NULL ? pu->pszID : NULL);
@@ -1183,12 +1183,12 @@ const char* LevellerDataset::code_to_id(UNITLABEL code) const
 
 const measurement_unit* LevellerDataset::get_uom(const char* pszUnits) const
 {
-    for(size_t i = 0; i < array_size(kUnits); i++)
+    for(size_t i = 0; i < CPL_ARRAYSIZE(kUnits); i++)
     {
         if(strcmp(pszUnits, kUnits[i].pszID) == 0)
             return &kUnits[i];
     }
-    CPLError( CE_Failure, CPLE_AppDefined, 
+    CPLError( CE_Failure, CPLE_AppDefined,
               "Unknown measurement units: %s", pszUnits );
     return NULL;
 }
@@ -1196,12 +1196,12 @@ const measurement_unit* LevellerDataset::get_uom(const char* pszUnits) const
 
 const measurement_unit* LevellerDataset::get_uom(UNITLABEL code) const
 {
-    for(size_t i = 0; i < array_size(kUnits); i++)
+    for(size_t i = 0; i < CPL_ARRAYSIZE(kUnits); i++)
     {
         if(kUnits[i].oemCode == code)
             return &kUnits[i];
     }
-    CPLError( CE_Failure, CPLE_AppDefined, 
+    CPLError( CE_Failure, CPLE_AppDefined,
               "Unknown measurement unit code: %08x", code );
     return NULL;
 }
@@ -1209,7 +1209,7 @@ const measurement_unit* LevellerDataset::get_uom(UNITLABEL code) const
 
 const measurement_unit* LevellerDataset::get_uom(double dM) const
 {
-    for(size_t i = kFirstLinearMeasureIdx; i < array_size(kUnits); i++)
+    for(size_t i = kFirstLinearMeasureIdx; i < CPL_ARRAYSIZE(kUnits); i++)
     {
 		if(dM >= 1.0e-4)
 		{
@@ -1219,7 +1219,7 @@ const measurement_unit* LevellerDataset::get_uom(double dM) const
 		else if(dM == kUnits[i].dScale)
 			return &kUnits[i];
     }
-    CPLError( CE_Failure, CPLE_AppDefined, 
+    CPLError( CE_Failure, CPLE_AppDefined,
               "Unknown measurement conversion factor: %f", dM );
     return NULL;
 }
@@ -1231,14 +1231,14 @@ const measurement_unit* LevellerDataset::get_uom(double dM) const
 
 bool LevellerDataset::convert_measure
 (
-	double d, 
+	double d,
 	double& dResult,
-	const char* pszSpace 
+	const char* pszSpace
 )
 {
     // Convert a measure to meters.
 
-    for(size_t i = kFirstLinearMeasureIdx; i < array_size(kUnits); i++)
+    for(size_t i = kFirstLinearMeasureIdx; i < CPL_ARRAYSIZE(kUnits); i++)
     {
         if(str_equal(pszSpace, kUnits[i].pszID))
 		{
@@ -1246,7 +1246,7 @@ bool LevellerDataset::convert_measure
 			return true;
 		}
     }
-    CPLError( CE_Failure, CPLE_FileIO, 
+    CPLError( CE_Failure, CPLE_FileIO,
               "Unknown linear measurement unit: '%s'", pszSpace );
     return false;
 }
@@ -1258,21 +1258,18 @@ bool LevellerDataset::make_local_coordsys(const char* pszName, const char* pszUn
 
 	sr.SetLocalCS(pszName);
 	double d;
-	return ( this->convert_measure(1.0, d, pszUnits)
-		&& OGRERR_NONE == sr.SetLinearUnits(pszUnits, d) 
-		&& OGRERR_NONE == sr.exportToWkt(&m_pszProjection) );
+    return ( convert_measure(1.0, d, pszUnits)
+             && OGRERR_NONE == sr.SetLinearUnits(pszUnits, d)
+             && OGRERR_NONE == sr.exportToWkt(&m_pszProjection) );
 }
 
 
 bool LevellerDataset::make_local_coordsys(const char* pszName, UNITLABEL code)
 {
-	const char* pszUnitID = this->code_to_id(code);
-	return ( pszUnitID != NULL
-		&& this->make_local_coordsys(pszName, pszUnitID));
+    const char* pszUnitID = code_to_id(code);
+    return pszUnitID != NULL && make_local_coordsys(pszName, pszUnitID);
 }
 
-
-
 /************************************************************************/
 /*                            load_from_file()                            */
 /************************************************************************/
@@ -1280,14 +1277,14 @@ bool LevellerDataset::make_local_coordsys(const char* pszName, UNITLABEL code)
 bool LevellerDataset::load_from_file(VSILFILE* file, const char* pszFilename)
 {
     // get hf dimensions
-    if(!this->get(nRasterXSize, file, "hf_w"))
+    if(!get(nRasterXSize, file, "hf_w"))
 	{
 		CPLError( CE_Failure, CPLE_OpenFailed,
 					  "Cannot determine heightfield width." );
         return false;
 	}
 
-    if(!this->get(nRasterYSize, file, "hf_b"))
+    if(!get(nRasterYSize, file, "hf_b"))
 	{
 		CPLError( CE_Failure, CPLE_OpenFailed,
 					  "Cannot determine heightfield breadth." );
@@ -1303,7 +1300,7 @@ bool LevellerDataset::load_from_file(VSILFILE* file, const char* pszFilename)
 
     // Record start of pixel data
     size_t datalen;
-    if(!this->locate_data(m_nDataOffset, datalen, file, "hf_data"))
+    if(!locate_data(m_nDataOffset, datalen, file, "hf_data"))
 	{
 		CPLError( CE_Failure, CPLE_OpenFailed,
 					  "Cannot locate elevation data." );
@@ -1311,7 +1308,7 @@ bool LevellerDataset::load_from_file(VSILFILE* file, const char* pszFilename)
 	}
 
     // Sanity check: do we have enough pixels?
-    if(datalen != nRasterXSize * nRasterYSize * sizeof(float))
+    if(static_cast<GUIntBig>(datalen) != static_cast<GUIntBig>(nRasterXSize) * static_cast<GUIntBig>(nRasterYSize) * sizeof(float))
 	{
 		CPLError( CE_Failure, CPLE_OpenFailed,
 					  "File does not have enough data." );
@@ -1331,81 +1328,83 @@ bool LevellerDataset::load_from_file(VSILFILE* file, const char* pszFilename)
     m_dElevBase = 0.0;
 	strcpy(m_szElevUnits, "");
 
-	if(m_version == 7)
-	{
-		// Read coordsys info.
-		int csclass = LEV_COORDSYS_RASTER;
-	    (void)this->get(csclass, file, "csclass");
-
-		if(csclass != LEV_COORDSYS_RASTER)
-		{
-			// Get projection details and units.
-
-			CPLAssert(m_pszProjection == NULL);
-
-			if(csclass == LEV_COORDSYS_LOCAL)
-			{
-				UNITLABEL unitcode;
-				//char szLocalUnits[8];
-                                int unitcode_int;
-				if(!this->get(unitcode_int, file, "coordsys_units"))
-					unitcode_int = UNITLABEL_M;
-                                unitcode = (UNITLABEL) unitcode_int;
-
-				if(!this->make_local_coordsys("Leveller", unitcode))
-				{
-					CPLError( CE_Failure, CPLE_OpenFailed,
-								  "Cannot define local coordinate system." );
-					return false;
-				}
-			}
-			else if(csclass == LEV_COORDSYS_GEO)
-			{
-				char szWKT[1024];
-				if(!this->get(szWKT, 1023, file, "coordsys_wkt"))
-					return 0;
-
-				m_pszProjection = (char*)CPLMalloc(strlen(szWKT) + 1);
-				strcpy(m_pszProjection, szWKT);
-			}
-			else
-			{
-				CPLError( CE_Failure, CPLE_OpenFailed,
-						  "Unknown coordinate system type in %s.",
-						  pszFilename );
-				return false;
-			}
-
-			// Get ground extents.
-			digital_axis axis_ns, axis_ew;
-
-			if(axis_ns.get(*this, file, 0)
-				&& axis_ew.get(*this, file, 1))
-			{
-				m_adfTransform[0] = axis_ew.origin(nRasterXSize);
-				m_adfTransform[1] = axis_ew.scaling(nRasterXSize);
-				m_adfTransform[2] = 0.0;
+    if(m_version >= 7)
+    {
+        // Read coordsys info.
+        int csclass = LEV_COORDSYS_RASTER;
+        /* (void) */ get(csclass, file, "csclass");
 
-				m_adfTransform[3] = axis_ns.origin(nRasterYSize);
-				m_adfTransform[4] = 0.0;
-				m_adfTransform[5] = axis_ns.scaling(nRasterYSize);
-			}
-		}
+        if(csclass != LEV_COORDSYS_RASTER)
+        {
+            // Get projection details and units.
+            CPLAssert(m_pszProjection == NULL);
+
+            if(csclass == LEV_COORDSYS_LOCAL)
+            {
+                UNITLABEL unitcode;
+                // char szLocalUnits[8];
+                int unitcode_int;
+                if(!get(unitcode_int, file, "coordsys_units"))
+                    unitcode_int = UNITLABEL_M;
+                unitcode = static_cast<UNITLABEL>( unitcode_int );
+
+                if( !make_local_coordsys("Leveller", unitcode) )
+                {
+                    CPLError( CE_Failure, CPLE_OpenFailed,
+                              "Cannot define local coordinate system." );
+                    return false;
+                }
+            }
+            else if(csclass == LEV_COORDSYS_GEO)
+            {
+                char szWKT[1024];
+                if(!get(szWKT, 1023, file, "coordsys_wkt"))
+                    return false;
+
+                m_pszProjection = reinterpret_cast<char *>( CPLMalloc(strlen(szWKT) + 1) );
+                strcpy(m_pszProjection, szWKT);
+            }
+            else
+            {
+                CPLError( CE_Failure, CPLE_OpenFailed,
+                          "Unknown coordinate system type in %s.",
+                          pszFilename );
+                return false;
+            }
+
+            // Get ground extents.
+            digital_axis axis_ns, axis_ew;
+
+            if(axis_ns.get(*this, file, 0)
+               && axis_ew.get(*this, file, 1))
+            {
+                m_adfTransform[0] = axis_ew.origin(nRasterXSize);
+                m_adfTransform[1] = axis_ew.scaling(nRasterXSize);
+                m_adfTransform[2] = 0.0;
+
+                m_adfTransform[3] = axis_ns.origin(nRasterYSize);
+                m_adfTransform[4] = 0.0;
+                m_adfTransform[5] = axis_ns.scaling(nRasterYSize);
+            }
+        }
 
 		// Get vertical (elev) coordsys.
 		int bHasVertCS = FALSE;
 		if(this->get(bHasVertCS, file, "coordsys_haselevm") && bHasVertCS)
 		{
-			this->get(m_dElevScale, file, "coordsys_em_scale");
-			this->get(m_dElevBase, file, "coordsys_em_base");
+                    get(m_dElevScale, file, "coordsys_em_scale");
+                    get(m_dElevBase, file, "coordsys_em_base");
 			UNITLABEL unitcode;
                         int unitcode_int;
-			if(this->get(unitcode_int, file, "coordsys_em_units"))
+			if(get(unitcode_int, file, "coordsys_em_units"))
 			{
-                                unitcode = (UNITLABEL) unitcode_int;
-				const char* pszUnitID = this->code_to_id(unitcode);
+                            unitcode = static_cast<UNITLABEL>( unitcode_int );
+                            const char* pszUnitID = code_to_id(unitcode);
 				if(pszUnitID != NULL)
-					strcpy(m_szElevUnits, pszUnitID);
+                                {
+                                    strncpy(m_szElevUnits, pszUnitID, sizeof(m_szElevUnits));
+                                    m_szElevUnits[sizeof(m_szElevUnits) - 1] = '\0';
+                                }
 				else
 				{
 					CPLError( CE_Failure, CPLE_OpenFailed,
@@ -1419,17 +1418,17 @@ bool LevellerDataset::load_from_file(VSILFILE* file, const char* pszFilename)
 	}
 	else
 	{
-		// Legacy files use world units.
+            // Legacy files use world units.
 	    char szWorldUnits[32];
-		strcpy(szWorldUnits, "m");
+            strcpy(szWorldUnits, "m");
 
 	    double dWorldscale = 1.0;
 
-		if(this->get(dWorldscale, file, "hf_worldspacing"))
-		{
+            if(get(dWorldscale, file, "hf_worldspacing"))
+            {
 			//m_bHasWorldscale = true;
-			if(this->get(szWorldUnits, sizeof(szWorldUnits)-1, file, 
-				"hf_worldspacinglabel"))
+                    if(get(szWorldUnits, sizeof(szWorldUnits)-1, file,
+                           "hf_worldspacinglabel"))
 			{
 				// Drop long name, if present.
 				char* p = strchr(szWorldUnits, ' ');
@@ -1438,7 +1437,7 @@ bool LevellerDataset::load_from_file(VSILFILE* file, const char* pszFilename)
 			}
 
 #if 0
-			// If the units are something besides m/ft/sft, 
+			// If the units are something besides m/ft/sft,
 			// then convert them to meters.
 
 			if(!str_equal("m", szWorldUnits)
@@ -1450,19 +1449,19 @@ bool LevellerDataset::load_from_file(VSILFILE* file, const char* pszFilename)
 			}
 #endif
 
-			// Our extents are such that the origin is at the 
+			// Our extents are such that the origin is at the
 			// center of the heightfield.
 			m_adfTransform[0] = -0.5 * dWorldscale * (nRasterXSize-1);
 			m_adfTransform[3] = -0.5 * dWorldscale * (nRasterYSize-1);
 			m_adfTransform[1] = dWorldscale;
 			m_adfTransform[5] = dWorldscale;
 		}
-		m_dElevScale = dWorldscale; // this was 1.0 before because 
+		m_dElevScale = dWorldscale; // this was 1.0 before because
 		// we were converting to real elevs ourselves, but
-		// some callers may want both the raw pixels and the 
+		// some callers may want both the raw pixels and the
 		// transform to get real elevs.
 
-		if(!this->make_local_coordsys("Leveller world space", szWorldUnits))
+        if(!make_local_coordsys("Leveller world space", szWorldUnits))
 		{
 			CPLError( CE_Failure, CPLE_OpenFailed,
 						  "Cannot define local coordinate system." );
@@ -1479,7 +1478,7 @@ bool LevellerDataset::load_from_file(VSILFILE* file, const char* pszFilename)
 
 const char*	LevellerDataset::GetProjectionRef(void)
 {
-    return (m_pszProjection == NULL ? "" : m_pszProjection);
+    return m_pszProjection == NULL ? "" : m_pszProjection;
 }
 
 /************************************************************************/
@@ -1489,7 +1488,7 @@ const char*	LevellerDataset::GetProjectionRef(void)
 CPLErr LevellerDataset::GetGeoTransform(double* padfTransform)
 
 {
-	memcpy(padfTransform, m_adfTransform, sizeof(m_adfTransform));
+    memcpy(padfTransform, m_adfTransform, sizeof(m_adfTransform));
     return CE_None;
 }
 
@@ -1502,7 +1501,7 @@ int LevellerDataset::Identify( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->nHeaderBytes < 4 )
         return FALSE;
 
-    return EQUALN((const char *) poOpenInfo->pabyHeader, "trrn", 4);
+    return STARTS_WITH_CI(reinterpret_cast<const char *>( poOpenInfo->pabyHeader ), "trrn");
 }
 
 /************************************************************************/
@@ -1513,25 +1512,22 @@ GDALDataset *LevellerDataset::Open( GDALOpenInfo * poOpenInfo )
 {
     // The file should have at least 5 header bytes
     // and hf_w, hf_b, and hf_data tags.
-#ifdef DEBUG
 
-#endif
     if( poOpenInfo->nHeaderBytes < 5+13+13+16 )
         return NULL;
 
-	if( !LevellerDataset::Identify(poOpenInfo))
-		return NULL;
+    if( !LevellerDataset::Identify(poOpenInfo))
+        return NULL;
 
     const int version = poOpenInfo->pabyHeader[4];
-    if(version < 4 || version > 7)
+    if(version < 4 || version > 9)
         return NULL;
 
-
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
 
-	LevellerDataset* poDS = new LevellerDataset();
+    LevellerDataset* poDS = new LevellerDataset();
 
     poDS->m_version = version;
 
@@ -1546,13 +1542,14 @@ GDALDataset *LevellerDataset::Open( GDALOpenInfo * poOpenInfo )
         CPLError( CE_Failure, CPLE_OpenFailed,
                   "Failed to re-open %s within Leveller driver.",
                   poOpenInfo->pszFilename );
+        delete poDS;
         return NULL;
     }
     poDS->eAccess = poOpenInfo->eAccess;
 
-    
+
 /* -------------------------------------------------------------------- */
-/*	Read the file.							                            */
+/*	Read the file.                                                  */
 /* -------------------------------------------------------------------- */
     if( !poDS->load_from_file( poDS->m_fp, poOpenInfo->pszFilename ) )
     {
@@ -1563,7 +1560,13 @@ GDALDataset *LevellerDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    poDS->SetBand( 1, new LevellerRasterBand( poDS ));
+    LevellerRasterBand* poBand = new LevellerRasterBand( poDS );
+    poDS->SetBand( 1, poBand);
+    if( !poBand->Init() )
+    {
+        delete poDS;
+        return NULL;
+    }
 
     poDS->SetMetadataItem( GDALMD_AREA_OR_POINT, GDALMD_AOP_POINT );
 
@@ -1581,15 +1584,6 @@ GDALDataset *LevellerDataset::Open( GDALOpenInfo * poOpenInfo )
     return( poDS );
 }
 
-#else
-// stub so that module compiles
-class LevellerDataset : public GDALPamDataset
-{
-	public:
-		static GDALDataset* Open( GDALOpenInfo* ) { return NULL; }
-};
-#endif
-
 /************************************************************************/
 /*                        GDALRegister_Leveller()                       */
 /************************************************************************/
@@ -1597,27 +1591,20 @@ class LevellerDataset : public GDALPamDataset
 void GDALRegister_Leveller()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "Leveller" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "Leveller" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "Leveller" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, 
-                                   "ter" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Leveller heightfield" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_leveller.html" );
-        
-#if GDAL_VERSION_NUM >= 1500
-        poDriver->pfnIdentify = LevellerDataset::Identify;
-#endif
-        poDriver->pfnOpen = LevellerDataset::Open;
-        poDriver->pfnCreate = LevellerDataset::Create;
+    GDALDriver *poDriver = new GDALDriver();
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    poDriver->SetDescription( "Leveller" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "ter" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Leveller heightfield" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_leveller.html" );
+
+    poDriver->pfnIdentify = LevellerDataset::Identify;
+    poDriver->pfnOpen = LevellerDataset::Open;
+    poDriver->pfnCreate = LevellerDataset::Create;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/makefile.vc b/frmts/makefile.vc
index 8d35038..f91ea2f 100644
--- a/frmts/makefile.vc
+++ b/frmts/makefile.vc
@@ -14,7 +14,8 @@ EXTRAFLAGS =	-DFRMT_ceos -DFRMT_aigrid -DFRMT_elas -DFRMT_hfa -DFRMT_gtiff\
 		-DFRMT_adrg -DFRMT_coasp -DFRMT_tsx -DFRMT_blx -DFRMT_til \
 		-DFRMT_r -DFRMT_northwood -DFRMT_saga -DFRMT_xyz -DFRMT_hf2 \
 		-DFRMT_kmlsuperoverlay -DFRMT_ozi -DFRMT_ctg -DFRMT_e00grid \
-		-DFRMT_zmap -DFRMT_ngsgeoid -DFRMT_iris -DFRMT_map
+		-DFRMT_zmap -DFRMT_ngsgeoid -DFRMT_iris -DFRMT_map -DFRMT_cals \
+		-DFRMT_safe -DFRMT_sentinel2
 
 MOREEXTRA 	=	
 
@@ -106,7 +107,7 @@ PLUGINFLAGS	=	$(PLUGINFLAGS) -DFRMT_fits
 !ENDIF
 !ENDIF
 
-!IF DEFINED(POPPLER_LIBS) || DEFINED(PODOFO_LIBS)
+!IF DEFINED(POPPLER_LIBS) || DEFINED(PODOFO_LIBS) || DEFINED(PDFIUM_LIBS)
 !IF "$(PDF_PLUGIN)" != "YES"
 EXTRAFLAGS	=	$(EXTRAFLAGS) -DFRMT_pdf
 !ELSE
@@ -131,7 +132,7 @@ EXTRAFLAGS	=	$(EXTRAFLAGS) -DFRMT_grib
 !ENDIF
 
 !IFDEF CURL_LIB
-EXTRAFLAGS	=	$(EXTRAFLAGS) -DFRMT_wcs -DFRMT_wms -DFRMT_plmosaic
+EXTRAFLAGS	=	$(EXTRAFLAGS) -DFRMT_wcs -DFRMT_wms -DFRMT_plmosaic -DFRMT_wmts
 !ENDIF
 
 !IFDEF SDE_ENABLED
@@ -180,6 +181,10 @@ PLUGINFLAGS	=	$(PLUGINFLAGS) -DFRMT_kea
 !ENDIF
 !ENDIF
 
+!IFDEF MRF_SETTING
+EXTRAFLAGS	=	$(EXTRAFLAGS) -DFRMT_mrf
+!ENDIF
+
 default:	o\gdalallregister.obj subdirs
 
 list:
diff --git a/frmts/map/GNUmakefile b/frmts/map/GNUmakefile
index e85bf23..ec2560c 100644
--- a/frmts/map/GNUmakefile
+++ b/frmts/map/GNUmakefile
@@ -3,8 +3,6 @@ include ../../GDALmake.opt
 
 OBJ	=	mapdataset.o
 
-
-
 default:	$(OBJ:.o=.$(OBJ_EXT))
 
 clean:
diff --git a/frmts/map/mapdataset.cpp b/frmts/map/mapdataset.cpp
index 726f444..c0a592c 100644
--- a/frmts/map/mapdataset.cpp
+++ b/frmts/map/mapdataset.cpp
@@ -27,12 +27,13 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 #include "gdal_proxy.h"
-#include "ogr_spatialref.h"
 #include "ogr_geometry.h"
+#include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: mapdataset.cpp 27559 2014-08-04 17:52:19Z rouault $");
+CPL_CVSID("$Id: mapdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -82,9 +83,9 @@ class MAPWrapperRasterBand : public GDALProxyRasterBand
     virtual GDALRasterBand* RefUnderlyingRasterBand() { return poBaseBand; }
 
   public:
-    MAPWrapperRasterBand( GDALRasterBand* poBaseBand )
+    explicit MAPWrapperRasterBand( GDALRasterBand* poBaseBandIn )
         {
-            this->poBaseBand = poBaseBand;
+            this->poBaseBand = poBaseBandIn;
             eDataType = poBaseBand->GetRasterDataType();
             poBaseBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
         }
@@ -97,21 +98,20 @@ class MAPWrapperRasterBand : public GDALProxyRasterBand
 /* ==================================================================== */
 /************************************************************************/
 
-MAPDataset::MAPDataset()
-
+MAPDataset::MAPDataset() :
+    poImageDS(NULL),
+    pszWKT(NULL),
+    bGeoTransformValid(false),
+    nGCPCount(0),
+    pasGCPList(NULL),
+    poNeatLine(NULL)
 {
-    poImageDS = NULL;
-    pszWKT = NULL;
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
-    nGCPCount = 0;
-    pasGCPList = NULL;
-    poNeatLine = NULL;
-    bGeoTransformValid = false;
 }
 
 /************************************************************************/
@@ -126,11 +126,9 @@ MAPDataset::~MAPDataset()
         GDALClose( poImageDS );
         poImageDS = NULL;
     }
-    if (pszWKT != NULL)
-    {
-        CPLFree(pszWKT);
-        pszWKT = NULL;
-    }
+
+    CPLFree(pszWKT);
+
     if (nGCPCount)
     {
         GDALDeinitGCPs( nGCPCount, pasGCPList );
@@ -167,22 +165,21 @@ int MAPDataset::CloseDependentDatasets()
 int MAPDataset::Identify( GDALOpenInfo *poOpenInfo )
 
 {
-    if( poOpenInfo->nHeaderBytes < 200 
+    if( poOpenInfo->nHeaderBytes < 200
         || !EQUAL(CPLGetExtension(poOpenInfo->pszFilename),"MAP") )
         return FALSE;
 
-    if( strstr((const char *) poOpenInfo->pabyHeader,"OziExplorer Map Data File") == NULL )
+    if( strstr(reinterpret_cast<const char *>( poOpenInfo->pabyHeader ),
+               "OziExplorer Map Data File") == NULL )
         return FALSE;
-    else
-        return TRUE;
+
+    return TRUE;
 }
 
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
 
-#define MAX_GCP 30
-
 GDALDataset *MAPDataset::Open( GDALOpenInfo * poOpenInfo )
 {
     if( !Identify( poOpenInfo ) )
@@ -193,12 +190,12 @@ GDALDataset *MAPDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The MAP driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
@@ -209,29 +206,30 @@ GDALDataset *MAPDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Try to load and parse the .MAP file.                            */
 /* -------------------------------------------------------------------- */
 
-    int bOziFileOK = 
-         GDALLoadOziMapFile( poOpenInfo->pszFilename,
-                             poDS->adfGeoTransform, 
+    bool bOziFileOK =
+         CPL_TO_BOOL(GDALLoadOziMapFile( poOpenInfo->pszFilename,
+                             poDS->adfGeoTransform,
                              &poDS->pszWKT,
-                             &poDS->nGCPCount, &poDS->pasGCPList );
+                             &poDS->nGCPCount, &poDS->pasGCPList ));
 
     if ( bOziFileOK && poDS->nGCPCount == 0 )
          poDS->bGeoTransformValid = TRUE;
 
-   /* We need to read again the .map file because the GDALLoadOziMapFile function
-      does not returns all required data . An API change is necessary : maybe in GDAL 2.0 ? */
-
-    char	**papszLines;
-    int		iLine, nLines=0;
+    /* We need to read again the .map file because the GDALLoadOziMapFile function
+       does not returns all required data . An API change is necessary : maybe in GDAL 2.0 ? */
 
-    papszLines = CSLLoad2( poOpenInfo->pszFilename, 200, 200, NULL );
+    char **papszLines = CSLLoad2( poOpenInfo->pszFilename, 200, 200, NULL );
 
     if ( !papszLines )
+    {
+        delete poDS;
         return NULL;
+    }
 
-    nLines = CSLCount( papszLines );
+    const int nLines = CSLCount( papszLines );
     if( nLines < 2 )
     {
+        delete poDS;
         CSLDestroy(papszLines);
         return NULL;
     }
@@ -244,7 +242,7 @@ GDALDataset *MAPDataset::Open( GDALOpenInfo * poOpenInfo )
     VSIStatBufL sStat;
     if (VSIStatL(poDS->osImgFilename, &sStat) != 0)
     {
-        CPLString osPath = CPLGetPath(poOpenInfo->pszFilename);
+        const CPLString osPath = CPLGetPath(poOpenInfo->pszFilename);
         if (CPLIsFilenameRelative(poDS->osImgFilename))
         {
             poDS->osImgFilename = CPLFormCIFilename(osPath, poDS->osImgFilename, NULL);
@@ -259,7 +257,8 @@ GDALDataset *MAPDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Try and open the file.                                          */
 /* -------------------------------------------------------------------- */
-    poDS->poImageDS = (GDALDataset *) GDALOpen(poDS->osImgFilename, GA_ReadOnly );
+    poDS->poImageDS = reinterpret_cast<GDALDataset *>(
+        GDALOpen(poDS->osImgFilename, GA_ReadOnly ) );
     if( poDS->poImageDS == NULL || poDS->poImageDS->GetRasterCount() == 0)
     {
         CSLDestroy(papszLines);
@@ -270,18 +269,16 @@ GDALDataset *MAPDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Attach the bands.                                               */
 /* -------------------------------------------------------------------- */
-    int iBand;
-
     poDS->nRasterXSize = poDS->poImageDS->GetRasterXSize();
     poDS->nRasterYSize = poDS->poImageDS->GetRasterYSize();
     if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
     {
-        delete poDS;
         GDALClose( poDS->poImageDS );
+        delete poDS;
         return NULL;
     }
 
-    for( iBand = 1; iBand <= poDS->poImageDS->GetRasterCount(); iBand++ )
+    for( int iBand = 1; iBand <= poDS->poImageDS->GetRasterCount(); iBand++ )
         poDS->SetBand( iBand,
                        new MAPWrapperRasterBand( poDS->poImageDS->GetRasterBand( iBand )) );
 
@@ -291,14 +288,14 @@ GDALDataset *MAPDataset::Open( GDALOpenInfo * poOpenInfo )
 
     /* First, we need to check if it is necessary to define a neatline */
     bool bNeatLine = false;
-    char **papszTok;
-    for ( iLine = 10; iLine < nLines; iLine++ )
+    for ( int iLine = 10; iLine < nLines; iLine++ )
     {
-        if ( EQUALN(papszLines[iLine], "MMPXY,", 6) )
+        if ( STARTS_WITH_CI(papszLines[iLine], "MMPXY,") )
         {
-            papszTok = CSLTokenizeString2( papszLines[iLine], ",",
-                                           CSLT_STRIPLEADSPACES
-                                           | CSLT_STRIPENDSPACES );
+            char **papszTok
+                = CSLTokenizeString2( papszLines[iLine], ",",
+                                      CSLT_STRIPLEADSPACES
+                                      | CSLT_STRIPENDSPACES );
 
             if ( CSLCount(papszTok) != 4 )
             {
@@ -306,8 +303,8 @@ GDALDataset *MAPDataset::Open( GDALOpenInfo * poOpenInfo )
                 continue;
             }
 
-            int x = CPLAtofM(papszTok[2]);
-            int y = CPLAtofM(papszTok[3]);
+            const int x = atoi(papszTok[2]);
+            const int y = atoi(papszTok[3]);
             if (( x != 0 && x != poDS->nRasterXSize) || (y != 0 && y != poDS->nRasterYSize) )
             {
                 bNeatLine = true;
@@ -326,13 +323,14 @@ GDALDataset *MAPDataset::Open( GDALOpenInfo * poOpenInfo )
 
         if ( poDS->bGeoTransformValid )        /* Compute the projected coordinates of the corners */
         {
-            for ( iLine = 10; iLine < nLines; iLine++ )
+            for ( int iLine = 10; iLine < nLines; iLine++ )
             {
-                if ( EQUALN(papszLines[iLine], "MMPXY,", 6) )
+                if ( STARTS_WITH_CI(papszLines[iLine], "MMPXY,") )
                 {
-                    papszTok = CSLTokenizeString2( papszLines[iLine], ",",
-                                                   CSLT_STRIPLEADSPACES
-                                                   | CSLT_STRIPENDSPACES );
+                    char **papszTok
+                        = CSLTokenizeString2( papszLines[iLine], ",",
+                                              CSLT_STRIPLEADSPACES
+                                              | CSLT_STRIPENDSPACES );
 
                     if ( CSLCount(papszTok) != 4 )
                     {
@@ -340,12 +338,12 @@ GDALDataset *MAPDataset::Open( GDALOpenInfo * poOpenInfo )
                         continue;
                     }
 
-                    double x = CPLAtofM(papszTok[2]);
-                    double y = CPLAtofM(papszTok[3]);
-                    double X = poDS->adfGeoTransform[0] + x * poDS->adfGeoTransform[1] +
-                                            y * poDS->adfGeoTransform[2];
-                    double Y = poDS->adfGeoTransform[3] + x * poDS->adfGeoTransform[4] +
-                                            y * poDS->adfGeoTransform[5];
+                    const double x = CPLAtofM(papszTok[2]);
+                    const double y = CPLAtofM(papszTok[3]);
+                    const double X = poDS->adfGeoTransform[0] + x * poDS->adfGeoTransform[1] +
+                        y * poDS->adfGeoTransform[2];
+                    const double Y = poDS->adfGeoTransform[3] + x * poDS->adfGeoTransform[4] +
+                        y * poDS->adfGeoTransform[5];
                     poRing->addPoint(X, Y);
                     CPLDebug( "CORNER MMPXY", "%f, %f, %f, %f", x, y, X, Y);
                     CSLDestroy(papszTok);
@@ -354,24 +352,24 @@ GDALDataset *MAPDataset::Open( GDALOpenInfo * poOpenInfo )
         }
         else /* Convert the geographic coordinates to projected coordinates */
         {
-            OGRSpatialReference oSRS;
-            OGRSpatialReference *poLatLong = NULL;
             OGRCoordinateTransformation *poTransform = NULL;
-            OGRErr eErr;
             char *pszWKT = poDS->pszWKT;
 
-            if ( &poDS->pszWKT != NULL )
+            if ( pszWKT != NULL )
             {
-                eErr = oSRS.importFromWkt ( &pszWKT );
-                if ( eErr == OGRERR_NONE )
+                OGRSpatialReference oSRS;
+                OGRSpatialReference *poLatLong = NULL;
+                if ( OGRERR_NONE == oSRS.importFromWkt ( &pszWKT ))
                     poLatLong = oSRS.CloneGeogCS();
-                    if ( poLatLong )
-                        poTransform = OGRCreateCoordinateTransformation( poLatLong, &oSRS );
+                if ( poLatLong )
+                    poTransform = OGRCreateCoordinateTransformation( poLatLong, &oSRS );
+                if ( poLatLong )
+                    delete poLatLong;
             }
 
-            for ( iLine = 10; iLine < nLines; iLine++ )
+            for ( int iLine = 10; iLine < nLines; iLine++ )
             {
-                if ( EQUALN(papszLines[iLine], "MMPLL,", 6) )
+                if ( STARTS_WITH_CI(papszLines[iLine], "MMPLL,") )
                 {
                     CPLDebug( "MMPLL", "%s", papszLines[iLine] );
                     char **papszTok = NULL;
@@ -396,10 +394,8 @@ GDALDataset *MAPDataset::Open( GDALOpenInfo * poOpenInfo )
                     CSLDestroy(papszTok);
                 }
             }
-            if (poTransform)
+            if ( poTransform )
                 delete poTransform;
-            if (poLatLong)
-                delete poLatLong;
         }
 
         poRing->closeRings();
@@ -435,7 +431,7 @@ CPLErr MAPDataset::GetGeoTransform( double * padfTransform )
 {
     memcpy(padfTransform, adfGeoTransform, 6 * sizeof(double));
 
-    return( (nGCPCount == 0) ? CE_None : CE_Failure );
+    return (nGCPCount == 0) ? CE_None : CE_Failure;
 }
 
 
@@ -475,7 +471,7 @@ char** MAPDataset::GetFileList()
     char **papszFileList = GDALDataset::GetFileList();
 
     papszFileList = CSLAddString( papszFileList, osImgFilename );
-    
+
     return papszFileList;
 }
 
@@ -486,26 +482,20 @@ char** MAPDataset::GetFileList()
 void GDALRegister_MAP()
 
 {
-    GDALDriver	*poDriver;
-
-    if( GDALGetDriverByName( "MAP" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "MAP" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "OziExplorer .MAP" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_map.html" );
+    if( GDALGetDriverByName( "MAP" ) != NULL )
+        return;
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->pfnOpen = MAPDataset::Open;
-        poDriver->pfnIdentify = MAPDataset::Identify;
+    poDriver->SetDescription( "MAP" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "OziExplorer .MAP" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_map.html" );
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
-}
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
+    poDriver->pfnOpen = MAPDataset::Open;
+    poDriver->pfnIdentify = MAPDataset::Identify;
 
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/frmts/mbtiles/GNUmakefile b/frmts/mbtiles/GNUmakefile
index 338acea..6aee9b1 100644
--- a/frmts/mbtiles/GNUmakefile
+++ b/frmts/mbtiles/GNUmakefile
@@ -7,7 +7,7 @@ ifeq ($(LIBZ_SETTING),internal)
   XTRA_OPT :=   $(XTRA_OPT) -I../zlib
 endif
 
-CPPFLAGS	:=	$(JSON_INCLUDE) $(XTRA_OPT)  $(CPPFLAGS) -I../../ogr
+CPPFLAGS	:=	$(JSON_INCLUDE) $(XTRA_OPT)  $(CPPFLAGS) -I../../ogr -I../../ogr/ogrsf_frmts/gpkg -I../../ogr/ogrsf_frmts/sqlite $(SQLITE_INC)
 
 default:	$(OBJ:.o=.$(OBJ_EXT))
 
@@ -15,3 +15,5 @@ clean:
 	rm -f *.o $(O_OBJ)
 
 install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+$(O_OBJ): ../../ogr/ogrsf_frmts/gpkg/gpkgmbtilescommon.h
diff --git a/frmts/mbtiles/frmt_mbtiles.html b/frmts/mbtiles/frmt_mbtiles.html
index aecf85a..2e1722e 100644
--- a/frmts/mbtiles/frmt_mbtiles.html
+++ b/frmts/mbtiles/frmt_mbtiles.html
@@ -1,115 +1,257 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<title>MBTiles</title>
-</head>
-
-<body>
-
-<h1>MBTiles</h1>
-
-<p>Starting with GDAL 1.10, the MBTiles driver allows reading rasters in the MBTiles format,
-which is a specification for storing tiled map data in SQLite databases.</p>
-
-<p>GDAL/OGR must be compiled with OGR SQLite driver support, and JPEG and PNG drivers.</p>
-
-<p>The SRS is always the Pseudo-Mercator (a.k.a Google Mercator) projection.</p>
-
-<p>The driver can retrieve pixel attributes encoded according to the UTFGrid specification
-available in some MBTiles files. They can be obtained with the gdallocationinfo utility, or
-with a GetMetadataItem("Pixel_iCol_iLine", "LocationInfo") call on a band object.<p>
-
-<h2>Examples:</h2>
-
-<ul>
-
-<li>Accessing a remote MBTiles raster :
-<pre>
-$ gdalinfo /vsicurl/http://a.tiles.mapbox.com/v3/kkaefer.iceland.mbtiles
-</pre>
-Output:
-<pre>
-Driver: MBTiles/MBTiles
-Files: /vsicurl/http://a.tiles.mapbox.com/v3/kkaefer.iceland.mbtiles
-Size is 16384, 16384
-Coordinate System is:
-PROJCS["WGS 84 / Pseudo-Mercator",
-    GEOGCS["WGS 84",
-        DATUM["WGS_1984",
-            SPHEROID["WGS 84",6378137,298.257223563,
-                AUTHORITY["EPSG","7030"]],
-            AUTHORITY["EPSG","6326"]],
-        PRIMEM["Greenwich",0,
-            AUTHORITY["EPSG","8901"]],
-        UNIT["degree",0.0174532925199433,
-            AUTHORITY["EPSG","9122"]],
-        AUTHORITY["EPSG","4326"]],
-    PROJECTION["Mercator_1SP"],
-    PARAMETER["central_meridian",0],
-    PARAMETER["scale_factor",1],
-    PARAMETER["false_easting",0],
-    PARAMETER["false_northing",0],
-    UNIT["metre",1,
-        AUTHORITY["EPSG","9001"]],
-    AXIS["X",EAST],
-    AXIS["Y",NORTH],
-    EXTENSION["PROJ4","+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext  +no_defs"],
-    AUTHORITY["EPSG","3857"]]
-Origin = (-3757031.250000000000000,11271093.750000000000000)
-Pixel Size = (152.873992919921875,-152.873992919921875)
-Image Structure Metadata:
-  INTERLEAVE=PIXEL
-Corner Coordinates:
-Upper Left  (-3757031.250,11271093.750) ( 33d44'59.95"W, 70d36'45.36"N)
-Lower Left  (-3757031.250, 8766406.250) ( 33d44'59.95"W, 61d36'22.97"N)
-Upper Right (-1252343.750,11271093.750) ( 11d14'59.98"W, 70d36'45.36"N)
-Lower Right (-1252343.750, 8766406.250) ( 11d14'59.98"W, 61d36'22.97"N)
-Center      (-2504687.500,10018750.000) ( 22d29'59.97"W, 66d30'47.68"N)
-Band 1 Block=256x256 Type=Byte, ColorInterp=Red
-  Overviews: 8192x8192, 4096x4096, 2048x2048, 1024x1024, 512x512
-  Mask Flags: PER_DATASET ALPHA
-  Overviews of mask band: 8192x8192, 4096x4096, 2048x2048, 1024x1024, 512x512
-Band 2 Block=256x256 Type=Byte, ColorInterp=Green
-  Overviews: 8192x8192, 4096x4096, 2048x2048, 1024x1024, 512x512
-  Mask Flags: PER_DATASET ALPHA
-  Overviews of mask band: 8192x8192, 4096x4096, 2048x2048, 1024x1024, 512x512
-Band 3 Block=256x256 Type=Byte, ColorInterp=Blue
-  Overviews: 8192x8192, 4096x4096, 2048x2048, 1024x1024, 512x512
-  Mask Flags: PER_DATASET ALPHA
-  Overviews of mask band: 8192x8192, 4096x4096, 2048x2048, 1024x1024, 512x512
-Band 4 Block=256x256 Type=Byte, ColorInterp=Alpha
-  Overviews: 8192x8192, 4096x4096, 2048x2048, 1024x1024, 512x512
-</pre>
-</li>
-
-
-<li>Reading pixel attributes encoded according to the UTFGrid specification :
-<pre>
-$ gdallocationinfo /vsicurl/http://a.tiles.mapbox.com/v3/mapbox.geography-class.mbtiles -wgs84 2 49 -b 1 -xml
-</pre>
-Output:
-<pre>
-<Report pixel="33132" line="22506">
-  <BandReport band="1">
-    <LocationInfo>
-      <Key>74</Key>
-      <JSon>{"admin":"France","flag_png":"iVBORw0KGgoAAAANSUhEUgAAAGQAAABDEAIAAAC1uevOAAAACXBIWXMAAABIAAAASABGyWs+AAAABmJLR0T///////8JWPfcAAABPklEQVR42u3cMRLBQBSA4Zc9CgqcALXC4bThBA5gNFyFM+wBVNFqjYTszpfi1Sm++bOv2ETEdNK2pc/T9ny977rCn+fx8rjtc7dMmybnxXy9KncGWGCBBRZYYIEFFlhggQUWWGCBBRZYYIE1/GzSLB0CLLAUCyywwAILLLDAAgsssGyFlcAqnJRiKRZYYIEFFlhggQUWWGDZCsFSLLDAAgsssP4DazQowVIssMACy1ZYG6wP30qxwFIssMACCyywwOr/HAYWWIplKwQLLLDAAgssZyywwAILLLDAqh6We4VgKZatECywFAsssMACCyywwAILLLBshWCBpVhggQUWWGCB [...]
-    </LocationInfo>
-    <Value>238</Value>
-  </BandReport>
-</Report>
-</pre>
-</li>
-
-</ul>
-
-<p>See Also:</p>
-
-<ul>
-<li><a href="https://github.com/mapbox/mbtiles-spec">MBTiles specification</a></li>
-<li><a href="https://github.com/mapbox/utfgrid-spec/blob/master/1.0/utfgrid.md">UTFGrid specification</a></li>
-</ul>
-
-</body>
-</html>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>MBTiles</title>
+</head>
+
+<body>
+
+<h1>MBTiles</h1>
+
+<p>Starting with GDAL 1.10, the MBTiles driver allows reading rasters in the MBTiles format,
+which is a specification for storing tiled map data in SQLite databases.</p>
+<p>Starting with GDAL 2.1, the MBTiles driver has creation and write support for MBTiles
+datasets.</p>
+
+<p>GDAL/OGR must be compiled with OGR SQLite driver support, and JPEG and PNG drivers.</p>
+
+<p>The SRS is always the Pseudo-Mercator (a.k.a Google Mercator) projection.</p>
+
+<p>By default, the driver will try to determine the number of bands by probing
+the content of one tile. It is possible to alter this behaviour by defining the
+MBTILES_BAND_COUNT configuration option (or starting with GDAL 2.1, the
+BAND_COUNT open option) to the number of bands. The values supported are 1, 2, 3
+or 4. Four band (Red,Green,Blue,Alpha) dataset gives the maximum compatibility
+with the various encodings of tiles that can be stored.</p>
+
+<p>The driver will use the 'bounds' metadata in the metadata table and do necessary
+tile clipping, if needed, to respect that extent. However that information being optional,
+if omitted, the driver will use the extent of the tiles at the maximum zoom level.
+The user can also specify the USE_BOUNDS=NO open option to force the use of
+the actual extent of tiles at the maximum zoom level. Or
+it can specify any of MINX/MINY/MAXX/MAXY to have a custom extent.<p>
+
+<p>The driver can retrieve pixel attributes encoded according to the UTFGrid specification
+available in some MBTiles files. They can be obtained with the gdallocationinfo utility, or
+with a GetMetadataItem("Pixel_iCol_iLine", "LocationInfo") call on a band object.<p>
+
+<h2>Opening options</h2>
+
+Starting with GDAL 2.1, the following open options are available:
+<ul>
+<li><b>ZOOM_LEVEL</b>=value: Integer value between 0 and the maximum filled in
+the <i>tiles</i> table. By default, the driver will select the maximum
+zoom level, such as at least one tile at that zoom level is found in the raster table.</li>
+<li><b>BAND_COUNT</b>=AUTO/1/2/3/4: Number of bands of the dataset exposed after opening.
+Some conversions will be done when possible and implemented, but this might fail
+in some cases, depending on the BAND_COUNT value and the number of bands of the tile.
+Defaults to AUTO.</li>
+<li><b>MINX</b>=value: Minimum easting (in EPSG:3857) of the area of interest.</li>
+<li><b>MINY</b>=value: Minimum northing (in EPSG:3857) of the area of interest.</li>
+<li><b>MAXX</b>=value: Maximum easting (in EPSG:3857) of the area of interest.</li>
+<li><b>MAXY</b>=value: Maximum northing (in EPSG:3857) of the area of interest.</li>
+<li><b>USE_BOUNDS</b>=YES/NO: Whether to use the bounds metadata, when available, to determine the AOI. Defaults to YES.</li>
+<li><b>TILE_FORMAT</b>=PNG/PNG8/JPEG: Format used to store tiles. See
+<a href="#tile_format">Tile format</a> section. Only used in update mode. Defaults to PNG.</li>
+<li><b>QUALITY</b>=1-100: Quality setting for JPEG compression. Only used in update mode. Default to 75.</li>
+<li><b>ZLEVEL</b>=1-9: DEFLATE compression level for PNG tiles. Only used in update mode. Default to 6.</li>
+<li><b>DITHER</b>=YES/NO: Whether to use Floyd-Steinberg dithering (for TILE_FORMAT=PNG8).
+Only used in update mode. Defaults to NO.</li>
+</ul>
+
+<h2>Creation issues</h2>
+
+<p>Depending of the number of bands of the input dataset and the tile format
+selected, the driver will do the necessary conversions to be compatible with the
+tile format. When using the CreateCopy() API (such as with gdal_translate),
+automatic reprojection of the input dataset to EPSG:3857 (WebMercator) will be done,
+with selection of the appropriate zoom level.</p>
+
+<p>Fully transparent tiles will not be written to the database, as allowed by
+the format.</p>
+
+<p>The driver implements the Create() and IWriteBlock() methods, so that arbitrary
+writing of raster blocks is possible, enabling the direct use of MBTiles as
+the output dataset of utilities such as gdalwarp.</p>
+
+<p>On creation, raster blocks can be written only if the geotransformation
+matrix has been set with SetGeoTransform() This is effectively needed to determine
+the zoom level of the full resolution dataset based on the pixel resolution, dataset
+and tile dimensions.</p>
+
+<p>Technical/implementation note: in the general case, GDAL blocks
+do not exactly match a single MBTiles tile. In which case, each GDAL
+block will overlap four MBTiles tiles. This is easily handled on the read side,
+but on creation/update side, such configuration could cause numerous decompression/
+recompression of tiles to be done, which might cause unnecessary quality loss when using
+lossy compression (JPEG). To avoid that, the driver will create a temporary
+database next to the main MBTiles file to store partial MBTiles tiles in a
+lossless (and uncompressed) way. Once a tile has received data for its four quadrants
+and for all the bands (or the dataset is closed or explicitly flushed with FlushCache()),
+those uncompressed tiles are definitely transferred to the MBTiles file with
+the appropriate compression. All of this is transparent to the user of GDAL API/utilities</p>
+
+<h3><a id="tile_formats">Tile formats</a></h3>
+
+<p>MBTiles can store tiles in PNG or JPEG. Support for those tile formats
+depend if the underlying drivers are available in GDAL. By default, GDAL will PNG
+tiles.</p>
+
+<p>It is possible to select the tile format by setting the creation/open
+option TILE_FORMAT to one of PNG, PNG8 or JPEG. When using JPEG, the alpha channel
+will not be stored.</p>
+
+<p>PNG8 can be selected to use 8-bit PNG with a color table up to 256 colors.
+On creation, an optimized color table is computed for each tile. The DITHER
+option can be set to YES to use Floyd/Steinberg dithering algorithm, which
+spreads the quantization error on neighbouring pixels for better rendering (note
+however than when zooming in, this can cause non desirable visual artifacts).
+Setting it to YES will generally cause less effective compression.
+Note that at that time, such an 8-bit PNG formulation is only used for fully opaque tiles,
+as the median-cut algorithm currently implemented to compute the optimal color
+table does not support alpha channel (even if PNG8 format would potentially allow
+color table with transparency). So when selecting PNG8, non fully opaque tiles
+will be stored as 32-bit PNG.</p>
+
+<h3>Creation options</h3>
+
+<p>The following creation options are available:</p>
+
+<ul>
+<li><b>NAME</b>=string. Tileset name, used to set the 'name' metadata item.
+If not specified, the basename of the filename will be used.</li>
+<li><b>DESCRIPTION</b>=string. A description of the layer, used to set the 'description' metadata item.
+If not specified, the basename of the filename will be used.</li>
+<li><b>TYPE</b>=overlay/baselayer. The layer type, used to set the 'type' metadata
+item. Default to 'overlay'.</li>
+<li><b>VERSION</b>=string. The version of the tileset, as a plain number, used
+to set the 'version' metadata item. Default to '1.1'.</li>
+<li><b>TILE_FORMAT</b>=PNG/PNG8/JPEG: Format used to store tiles. See
+<a href="#tile_formats">Tile formats</a> section. Defaults to PNG.</li>
+<li><b>QUALITY</b>=1-100: Quality setting for JPEG compression. Default to 75.</li>
+<li><b>ZLEVEL</b>=1-9: DEFLATE compression level for PNG tiles. Default to 6.</li>
+<li><b>DITHER</b>=YES/NO: Whether to use Floyd-Steinberg dithering (for TILE_FORMAT=PNG8).
+Defaults to NO.</li>
+<li><b>ZOOM_LEVEL_STRATEGY</b>=AUTO/LOWER/UPPER. Strategy to determine zoom level.
+LOWER will select the
+zoom level immediately below the theoretical computed non-integral zoom level,
+leading to subsampling. On the contrary, UPPER will select the immediately above
+zoom level, leading to oversampling. Defaults to AUTO which selects the closest
+zoom level.</li>
+<li><b>RESAMPLING</b>=NEAREST/BILINEAR/CUBIC/CUBICSPLINE/LANCZOS/MODE/AVERAGE.
+Resampling algorithm. Defaults to BILINEAR.</li>
+<li><b>WRITE_BOUNDS</b>=YES/NO: Whether to write the bounds 'metadata' item.
+Defaults to YES.</li>
+</ul>
+
+<h2>Overviews</h2>
+
+<p>gdaladdo / BuildOverviews() can be used to compute overviews. Only power-of-two
+overview factors (2,4,8,16,...) are supported.</p>
+
+<p>If more overview levels are specified than available, the extra ones are silently
+ignored.</p>
+
+<p>Overviews can also be cleared with the -clean option of gdaladdo (or
+BuildOverviews() with nOverviews=0)</p>
+
+<h2>Examples:</h2>
+
+<ul>
+
+<li>Accessing a remote MBTiles raster :
+<pre>
+$ gdalinfo /vsicurl/http://a.tiles.mapbox.com/v3/kkaefer.iceland.mbtiles
+</pre>
+Output:
+<pre>
+Driver: MBTiles/MBTiles
+Files: /vsicurl/http://a.tiles.mapbox.com/v3/kkaefer.iceland.mbtiles
+Size is 16384, 16384
+Coordinate System is:
+PROJCS["WGS 84 / Pseudo-Mercator",
+    GEOGCS["WGS 84",
+        DATUM["WGS_1984",
+            SPHEROID["WGS 84",6378137,298.257223563,
+                AUTHORITY["EPSG","7030"]],
+            AUTHORITY["EPSG","6326"]],
+        PRIMEM["Greenwich",0,
+            AUTHORITY["EPSG","8901"]],
+        UNIT["degree",0.0174532925199433,
+            AUTHORITY["EPSG","9122"]],
+        AUTHORITY["EPSG","4326"]],
+    PROJECTION["Mercator_1SP"],
+    PARAMETER["central_meridian",0],
+    PARAMETER["scale_factor",1],
+    PARAMETER["false_easting",0],
+    PARAMETER["false_northing",0],
+    UNIT["metre",1,
+        AUTHORITY["EPSG","9001"]],
+    AXIS["X",EAST],
+    AXIS["Y",NORTH],
+    EXTENSION["PROJ4","+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext  +no_defs"],
+    AUTHORITY["EPSG","3857"]]
+Origin = (-3757031.250000000000000,11271093.750000000000000)
+Pixel Size = (152.873992919921875,-152.873992919921875)
+Image Structure Metadata:
+  INTERLEAVE=PIXEL
+Corner Coordinates:
+Upper Left  (-3757031.250,11271093.750) ( 33d44'59.95"W, 70d36'45.36"N)
+Lower Left  (-3757031.250, 8766406.250) ( 33d44'59.95"W, 61d36'22.97"N)
+Upper Right (-1252343.750,11271093.750) ( 11d14'59.98"W, 70d36'45.36"N)
+Lower Right (-1252343.750, 8766406.250) ( 11d14'59.98"W, 61d36'22.97"N)
+Center      (-2504687.500,10018750.000) ( 22d29'59.97"W, 66d30'47.68"N)
+Band 1 Block=256x256 Type=Byte, ColorInterp=Red
+  Overviews: 8192x8192, 4096x4096, 2048x2048, 1024x1024, 512x512
+  Mask Flags: PER_DATASET ALPHA
+  Overviews of mask band: 8192x8192, 4096x4096, 2048x2048, 1024x1024, 512x512
+Band 2 Block=256x256 Type=Byte, ColorInterp=Green
+  Overviews: 8192x8192, 4096x4096, 2048x2048, 1024x1024, 512x512
+  Mask Flags: PER_DATASET ALPHA
+  Overviews of mask band: 8192x8192, 4096x4096, 2048x2048, 1024x1024, 512x512
+Band 3 Block=256x256 Type=Byte, ColorInterp=Blue
+  Overviews: 8192x8192, 4096x4096, 2048x2048, 1024x1024, 512x512
+  Mask Flags: PER_DATASET ALPHA
+  Overviews of mask band: 8192x8192, 4096x4096, 2048x2048, 1024x1024, 512x512
+Band 4 Block=256x256 Type=Byte, ColorInterp=Alpha
+  Overviews: 8192x8192, 4096x4096, 2048x2048, 1024x1024, 512x512
+</pre>
+</li>
+
+<li>Reading pixel attributes encoded according to the UTFGrid specification :
+<pre>
+$ gdallocationinfo /vsicurl/http://a.tiles.mapbox.com/v3/mapbox.geography-class.mbtiles -wgs84 2 49 -b 1 -xml
+</pre>
+Output:
+<pre>
+<Report pixel="33132" line="22506">
+  <BandReport band="1">
+    <LocationInfo>
+      <Key>74</Key>
+      <JSon>{"admin":"France","flag_png":"iVBORw0KGgoAAAANSUhEUgAAAGQAAABDEAIAAAC1uevOAAAACXBIWXMAAABIAAAASABGyWs+AAAABmJLR0T///////8JWPfcAAABPklEQVR42u3cMRLBQBSA4Zc9CgqcALXC4bThBA5gNFyFM+wBVNFqjYTszpfi1Sm++bOv2ETEdNK2pc/T9ny977rCn+fx8rjtc7dMmybnxXy9KncGWGCBBRZYYIEFFlhggQUWWGCBBRZYYIE1/GzSLB0CLLAUCyywwAILLLDAAgsssGyFlcAqnJRiKRZYYIEFFlhggQUWWGDZCsFSLLDAAgsssP4DazQowVIssMACy1ZYG6wP30qxwFIssMACCyywwOr/HAYWWIplKwQLLLDAAgssZyywwAILLLDAqh6We4VgKZatECywFAsssMACCyywwAILLLBshWCBpVhggQUWWGCB [...]
+    </LocationInfo>
+    <Value>238</Value>
+  </BandReport>
+</Report>
+</pre>
+</li>
+
+<li>Converting a dataset to MBTiles and adding overviews :
+<pre>
+$ gdal_translate my_dataset.tif my_dataset.mbtiles -of MBTILES
+$ gdaladdo -r average my_dataset.mbtiles 2 4 8 16
+</pre>
+</li>
+
+</ul>
+
+<p>See Also:</p>
+
+<ul>
+<li><a href="https://github.com/mapbox/mbtiles-spec">MBTiles specification</a></li>
+<li><a href="https://github.com/mapbox/utfgrid-spec/blob/master/1.0/utfgrid.md">UTFGrid specification</a></li>
+</ul>
+
+</body>
+</html>
diff --git a/frmts/mbtiles/makefile.vc b/frmts/mbtiles/makefile.vc
index 3687c75..bc82f8d 100644
--- a/frmts/mbtiles/makefile.vc
+++ b/frmts/mbtiles/makefile.vc
@@ -1,7 +1,7 @@
 
 OBJ	=	mbtilesdataset.obj
 
-EXTRAFLAGS = -I../../ogr -I../../ogr/ogrsf_frmts/geojson -I../../ogr/ogrsf_frmts/geojson/libjson -I../zlib
+EXTRAFLAGS = -I../../ogr -I../../ogr/ogrsf_frmts/gpkg  -I../../ogr/ogrsf_frmts/sqlite $(SQLITE_INC) -I../../ogr/ogrsf_frmts/geojson -I../../ogr/ogrsf_frmts/geojson/libjson -I../zlib
 
 GDAL_ROOT	=	..\..
 
diff --git a/frmts/mbtiles/mbtilesdataset.cpp b/frmts/mbtiles/mbtilesdataset.cpp
index 75cac22..cea0a87 100644
--- a/frmts/mbtiles/mbtilesdataset.cpp
+++ b/frmts/mbtiles/mbtilesdataset.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: mbtilesdataset.cpp 28884 2015-04-12 20:48:02Z rouault $
+ * $Id: mbtilesdataset.cpp 33828 2016-03-31 15:19:48Z rouault $
  *
  * Project:  GDAL MBTiles driver
  * Purpose:  Implement GDAL MBTiles support using OGR SQLite driver
- * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ * Author:   Even Rouault, Even Rouault <even.rouault at spatialys.com>
  *
  **********************************************************************
- * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ * Copyright (c) 2012-2016, Even Rouault <even.rouault at spatialys.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -31,32 +31,41 @@
 #include "gdal_pam.h"
 #include "ogr_api.h"
 #include "cpl_vsil_curl_priv.h"
+#include "gpkgmbtilescommon.h"
+#include "gdalwarper.h"
 
 #include "zlib.h"
 #include "json.h"
 
 #include <math.h>
 
-extern "C" void GDALRegister_MBTiles();
-
-CPL_CVSID("$Id: mbtilesdataset.cpp 28884 2015-04-12 20:48:02Z rouault $");
+CPL_CVSID("$Id: mbtilesdataset.cpp 33828 2016-03-31 15:19:48Z rouault $");
 
 static const char * const apszAllowedDrivers[] = {"JPEG", "PNG", NULL};
 
+#define SRS_EPSG_3857 "PROJCS[\"WGS 84 / Pseudo-Mercator\",GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]],PROJECTION[\"Mercator_1SP\"],PARAMETER[\"central_meridian\",0],PARAMETER[\"scale_factor\",1],PARAMETER[\"false_easting\",0],PARAMETER[\"false_nort [...]
+
+#define SPHERICAL_RADIUS        6378137.0
+#define MAX_GM                  (SPHERICAL_RADIUS * M_PI)               // 20037508.342789244
+
+// TileMatrixSet origin : caution this is in GeoPackage / WMTS convention ! That is upper-left corner
+#define TMS_ORIGIN_X        -MAX_GM
+#define TMS_ORIGIN_Y         MAX_GM
+
 class MBTilesBand;
 
 /************************************************************************/
 /*                         MBTILESOpenSQLiteDB()                        */
 /************************************************************************/
 
-OGRDataSourceH MBTILESOpenSQLiteDB(const char* pszFilename,
-                                      GDALAccess eAccess)
+static OGRDataSourceH MBTILESOpenSQLiteDB(const char* pszFilename,
+                                          GDALAccess eAccess)
 {
-    const char* apszAllowedDrivers[] = { "SQLITE", NULL };
+    const char* l_apszAllowedDrivers[] = { "SQLITE", NULL };
     return (OGRDataSourceH)GDALOpenEx(pszFilename,
-                                      GDAL_OF_VECTOR |
+                                      GDAL_OF_VECTOR | GDAL_OF_INTERNAL |
                                       ((eAccess == GA_Update) ? GDAL_OF_UPDATE : 0),
-                                      apszAllowedDrivers, NULL, NULL);
+                                      l_apszAllowedDrivers, NULL, NULL);
 }
 
 /************************************************************************/
@@ -65,57 +74,105 @@ OGRDataSourceH MBTILESOpenSQLiteDB(const char* pszFilename,
 /* ==================================================================== */
 /************************************************************************/
 
-class MBTilesDataset : public GDALPamDataset
+class MBTilesDataset : public GDALPamDataset, public GDALGPKGMBTilesLikePseudoDataset
 {
     friend class MBTilesBand;
 
   public:
                  MBTilesDataset();
-                 MBTilesDataset(MBTilesDataset* poMainDS, int nLevel);
 
     virtual     ~MBTilesDataset();
 
     virtual CPLErr GetGeoTransform(double* padfGeoTransform);
+    virtual CPLErr SetGeoTransform( double* padfGeoTransform );
     virtual const char* GetProjectionRef();
-    
+    virtual CPLErr SetProjection( const char* pszProjection );
+
     virtual char      **GetMetadataDomainList();
     virtual char      **GetMetadata( const char * pszDomain = "" );
+    virtual const char *GetMetadataItem( const char* pszName, const char * pszDomain = "" );
+
+    virtual CPLErr    IBuildOverviews(
+                        const char * pszResampling,
+                        int nOverviews, int * panOverviewList,
+                        int nBandsIn, CPL_UNUSED int * panBandList,
+                        GDALProgressFunc pfnProgress, void * pProgressData );
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int          Identify( GDALOpenInfo * );
-
-    char*               FindKey(int iPixel, int iLine,
-                                int& nTileColumn, int& nTileRow, int& nZoomLevel);
-    void                ComputeTileColTileRowZoomLevel( int nBlockXOff,
-                                                        int nBlockYOff,
-                                                        int &nTileColumn,
-                                                        int &nTileRow,
-                                                        int &nZoomLevel );
-    int                 HasNonEmptyGrids();
-
-  protected:
-    virtual int         CloseDependentDatasets();
+    static GDALDataset* Create( const char * pszFilename,
+                                   int nXSize,
+                                   int nYSize,
+                                   int nBandsIn,
+                                   GDALDataType eDT,
+                                   char **papszOptions );
+    static GDALDataset* CreateCopy( const char *pszFilename,
+                                                GDALDataset *poSrcDS,
+                                                int bStrict,
+                                                char ** papszOptions,
+                                                GDALProgressFunc pfnProgress,
+                                                void * pProgressData );
+
+    char*               FindKey(int iPixel, int iLine);
+
+    bool                HasNonEmptyGrids();
 
   private:
 
-    int bMustFree;
+    bool m_bWriteBounds;
     MBTilesDataset* poMainDS;
-    int nLevel;
-    int nMinTileCol, nMinTileRow;
-    int nMinLevel;
+    bool m_bGeoTransformValid;
+    double m_adfGeoTransform[6];
 
-    char** papszMetadata;
-    char** papszImageStructure;
-
-    int nResolutions;
-    MBTilesDataset** papoOverviews;
+    int m_nOverviewCount;
+    MBTilesDataset** m_papoOverviewDS;
 
     OGRDataSourceH hDS;
+    sqlite3* hDB;
+
+#ifdef HAVE_SQLITE_VFS
+    sqlite3_vfs*        pMyVFS;
+#endif
 
-    int bFetchedMetadata;
+    bool bFetchedMetadata;
     CPLStringList aosList;
 
-    int bHasNonEmptyGrids;
+    int nHasNonEmptyGrids;
+
+    bool m_bInFlushCache;
+
+    void ParseCompressionOptions(char** papszOptions);
+    CPLErr FinalizeRasterRegistration();
+    void ComputeTileAndPixelShifts();
+    int InitRaster ( MBTilesDataset* poParentDS,
+                     int nZoomLevel,
+                     int nBandCount,
+                     double dfGDALMinX,
+                     double dfGDALMinY,
+                     double dfGDALMaxX,
+                     double dfGDALMaxY );
+
+    bool CreateInternal( const char * pszFilename,
+                         int nXSize,
+                         int nYSize,
+                         int nBandsIn,
+                         GDALDataType eDT,
+                         char **papszOptions );
+
+    protected:
+        // Coming from GDALGPKGMBTilesLikePseudoDataset
+
+        virtual CPLErr                  IFlushCacheWithErrCode();
+        virtual int                     IGetRasterCount() { return nBands; }
+        virtual GDALRasterBand*         IGetRasterBand(int nBand) { return GetRasterBand(nBand); }
+        virtual sqlite3                *IGetDB() { return hDB; }
+        virtual bool                    IGetUpdate() { return eAccess == GA_Update; }
+        virtual bool                    ICanIWriteBlock();
+        virtual void                    IStartTransaction();
+        virtual void                    ICommitTransaction();
+        virtual const char             *IGetFilename() { return GetDescription(); }
+        virtual int                     GetRowFromIntoTopConvention(int nRow);
+
 };
 
 /************************************************************************/
@@ -124,273 +181,30 @@ class MBTilesDataset : public GDALPamDataset
 /* ==================================================================== */
 /************************************************************************/
 
-class MBTilesBand: public GDALPamRasterBand
+class MBTilesBand: public GDALGPKGMBTilesLikeRasterBand
 {
     friend class MBTilesDataset;
 
     CPLString               osLocationInfo;
 
   public:
-                            MBTilesBand( MBTilesDataset* poDS, int nBand,
-                                            GDALDataType eDataType,
-                                            int nBlockXSize, int nBlockYSize);
-
-    virtual GDALColorInterp GetColorInterpretation();
+                            MBTilesBand( MBTilesDataset* poDS );
 
     virtual int             GetOverviewCount();
     virtual GDALRasterBand* GetOverview(int nLevel);
 
-    virtual CPLErr          IReadBlock( int, int, void * );
-
     virtual char      **GetMetadataDomainList();
     virtual const char *GetMetadataItem( const char * pszName,
                                          const char * pszDomain = "" );
 };
 
 /************************************************************************/
-/*                            MBTilesBand()                          */
-/************************************************************************/
-
-MBTilesBand::MBTilesBand(MBTilesDataset* poDS, int nBand,
-                                GDALDataType eDataType,
-                                int nBlockXSize, int nBlockYSize)
-{
-    this->poDS = poDS;
-    this->nBand = nBand;
-    this->eDataType = eDataType;
-    this->nBlockXSize = nBlockXSize;
-    this->nBlockYSize = nBlockYSize;
-}
-
-/************************************************************************/
-/*                            IReadBlock()                              */
+/*                            MBTilesBand()                             */
 /************************************************************************/
 
-CPLErr MBTilesBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage)
+MBTilesBand::MBTilesBand(MBTilesDataset* poDSIn) :
+      GDALGPKGMBTilesLikeRasterBand(poDSIn, 256, 256)
 {
-    MBTilesDataset* poGDS = (MBTilesDataset*) poDS;
-
-    int bGotTile = FALSE;
-    CPLAssert(eDataType == GDT_Byte);
-
-    int nTileColumn, nTileRow, nZoomLevel;
-    poGDS->ComputeTileColTileRowZoomLevel(nBlockXOff, nBlockYOff,
-                                          nTileColumn, nTileRow, nZoomLevel);
-
-    const char* pszSQL = CPLSPrintf("SELECT tile_data FROM tiles WHERE "
-                                    "tile_column = %d AND tile_row = %d AND zoom_level=%d",
-                                    nTileColumn, nTileRow, nZoomLevel);
-    CPLDebug("MBTILES", "nBand=%d, nBlockXOff=%d, nBlockYOff=%d, %s",
-             nBand, nBlockXOff, nBlockYOff, pszSQL);
-    OGRLayerH hSQLLyr = OGR_DS_ExecuteSQL(poGDS->hDS, pszSQL, NULL, NULL);
-
-    OGRFeatureH hFeat = hSQLLyr ? OGR_L_GetNextFeature(hSQLLyr) : NULL;
-    if (hFeat != NULL)
-    {
-        CPLString osMemFileName;
-        osMemFileName.Printf("/vsimem/%p", this);
-
-        int nDataSize = 0;
-        GByte* pabyData = OGR_F_GetFieldAsBinary(hFeat, 0, &nDataSize);
-
-        VSILFILE * fp = VSIFileFromMemBuffer( osMemFileName.c_str(), pabyData,
-                                            nDataSize, FALSE);
-        VSIFCloseL(fp);
-
-        GDALDatasetH hDSTile = GDALOpenEx(osMemFileName.c_str(),
-                                          GDAL_OF_RASTER | GDAL_OF_INTERNAL,
-                                          apszAllowedDrivers, NULL, NULL);
-        if (hDSTile != NULL)
-        {
-            int nTileBands = GDALGetRasterCount(hDSTile);
-            if (nTileBands == 4 && poGDS->nBands == 3)
-                nTileBands = 3;
-
-            if (GDALGetRasterXSize(hDSTile) == nBlockXSize &&
-                GDALGetRasterYSize(hDSTile) == nBlockYSize &&
-                (nTileBands == poGDS->nBands ||
-                 (nTileBands == 1 && (poGDS->nBands == 3 || poGDS->nBands == 4)) ||
-                 (nTileBands == 3 && poGDS->nBands == 4)))
-            {
-                int iBand;
-                void* pSrcImage = NULL;
-                GByte abyTranslation[256][4];
-
-                bGotTile = TRUE;
-
-                GDALColorTableH hCT = GDALGetRasterColorTable(GDALGetRasterBand(hDSTile, 1));
-                if (nTileBands == 1 && (poGDS->nBands == 3 || poGDS->nBands == 4))
-                {
-                    if (hCT != NULL)
-                        pSrcImage = CPLMalloc(nBlockXSize * nBlockYSize);
-                    iBand = 1;
-                }
-                else
-                    iBand = nBand;
-
-                if (nTileBands == 3 && poGDS->nBands == 4 && iBand == 4)
-                    memset(pImage, 255, nBlockXSize * nBlockYSize);
-                else
-                {
-                    GDALRasterIO(GDALGetRasterBand(hDSTile, iBand), GF_Read,
-                                0, 0, nBlockXSize, nBlockYSize,
-                                pImage, nBlockXSize, nBlockYSize, eDataType, 0, 0);
-                }
-
-                if (pSrcImage != NULL && hCT != NULL)
-                {
-                    int i;
-                    memcpy(pSrcImage, pImage, nBlockXSize * nBlockYSize);
-
-                    int nEntryCount = GDALGetColorEntryCount( hCT );
-                    if (nEntryCount > 256)
-                        nEntryCount = 256;
-                    for(i = 0; i < nEntryCount; i++)
-                    {
-                        const GDALColorEntry* psEntry = GDALGetColorEntry( hCT, i );
-                        abyTranslation[i][0] = (GByte) psEntry->c1;
-                        abyTranslation[i][1] = (GByte) psEntry->c2;
-                        abyTranslation[i][2] = (GByte) psEntry->c3;
-                        abyTranslation[i][3] = (GByte) psEntry->c4;
-                    }
-                    for(; i < 256; i++)
-                    {
-                        abyTranslation[i][0] = 0;
-                        abyTranslation[i][1] = 0;
-                        abyTranslation[i][2] = 0;
-                        abyTranslation[i][3] = 0;
-                    }
-
-                    for(i = 0; i < nBlockXSize * nBlockYSize; i++)
-                    {
-                        ((GByte*)pImage)[i] = abyTranslation[((GByte*)pSrcImage)[i]][nBand-1];
-                    }
-                }
-
-                for(int iOtherBand=1;iOtherBand<=poGDS->nBands;iOtherBand++)
-                {
-                    GDALRasterBlock *poBlock;
-
-                    if (iOtherBand == nBand)
-                        continue;
-
-                    poBlock = ((MBTilesBand*)poGDS->GetRasterBand(iOtherBand))->
-                        TryGetLockedBlockRef(nBlockXOff,nBlockYOff);
-
-                    if (poBlock != NULL)
-                    {
-                        poBlock->DropLock();
-                        continue;
-                    }
-
-                    poBlock = poGDS->GetRasterBand(iOtherBand)->
-                        GetLockedBlockRef(nBlockXOff,nBlockYOff, TRUE);
-                    if (poBlock == NULL)
-                        break;
-
-                    GByte* pabySrcBlock = (GByte *) poBlock->GetDataRef();
-                    if( pabySrcBlock == NULL )
-                    {
-                        poBlock->DropLock();
-                        break;
-                    }
-
-                    if (nTileBands == 3 && poGDS->nBands == 4 && iOtherBand == 4)
-                        memset(pabySrcBlock, 255, nBlockXSize * nBlockYSize);
-                    else if (nTileBands == 1 && (poGDS->nBands == 3 || poGDS->nBands == 4))
-                    {
-                        int i;
-                        if (pSrcImage)
-                        {
-                            for(i = 0; i < nBlockXSize * nBlockYSize; i++)
-                            {
-                                ((GByte*)pabySrcBlock)[i] =
-                                    abyTranslation[((GByte*)pSrcImage)[i]][iOtherBand-1];
-                            }
-                        }
-                        else
-                            memcpy(pabySrcBlock, pImage, nBlockXSize * nBlockYSize);
-                    }
-                    else
-                    {
-                        GDALRasterIO(GDALGetRasterBand(hDSTile, iOtherBand), GF_Read,
-                            0, 0, nBlockXSize, nBlockYSize,
-                            pabySrcBlock, nBlockXSize, nBlockYSize, eDataType, 0, 0);
-                    }
-
-                    poBlock->DropLock();
-                }
-
-                CPLFree(pSrcImage);
-            }
-            else if (GDALGetRasterXSize(hDSTile) == nBlockXSize &&
-                     GDALGetRasterYSize(hDSTile) == nBlockYSize &&
-                     (nTileBands == 3 && poGDS->nBands == 1))
-            {
-                bGotTile = TRUE;
-
-                GByte* pabyRGBImage = (GByte*)CPLMalloc(3 * nBlockXSize * nBlockYSize);
-                GDALDatasetRasterIO(hDSTile, GF_Read,
-                                    0, 0, nBlockXSize, nBlockYSize,
-                                    pabyRGBImage, nBlockXSize, nBlockYSize, eDataType,
-                                    3, NULL, 3, 3 * nBlockXSize, 1);
-                for(int i=0;i<nBlockXSize*nBlockYSize;i++)
-                {
-                    int R = pabyRGBImage[3*i];
-                    int G = pabyRGBImage[3*i+1];
-                    int B = pabyRGBImage[3*i+2];
-                    GByte Y = (GByte)((213 * R + 715 * G + 72 * B) / 1000);
-                    ((GByte*)pImage)[i] = Y;
-                }
-                CPLFree(pabyRGBImage);
-            }
-            else
-            {
-                CPLDebug("MBTILES", "tile size = %d, tile height = %d, tile bands = %d",
-                         GDALGetRasterXSize(hDSTile), GDALGetRasterYSize(hDSTile),
-                         GDALGetRasterCount(hDSTile));
-            }
-            GDALClose(hDSTile);
-        }
-
-        VSIUnlink( osMemFileName.c_str() );
-
-        OGR_F_Destroy(hFeat);
-    }
-
-    OGR_DS_ReleaseResultSet(poGDS->hDS, hSQLLyr);
-
-    if (!bGotTile)
-    {
-        memset(pImage, (nBand == 4) ? 0 : 255, nBlockXSize * nBlockYSize);
-
-        for(int iOtherBand=1;iOtherBand<=poGDS->nBands;iOtherBand++)
-        {
-            GDALRasterBlock *poBlock;
-
-            if (iOtherBand == nBand)
-                continue;
-
-            poBlock = poGDS->GetRasterBand(iOtherBand)->
-                GetLockedBlockRef(nBlockXOff,nBlockYOff, TRUE);
-            if (poBlock == NULL)
-                break;
-
-            GByte* pabySrcBlock = (GByte *) poBlock->GetDataRef();
-            if( pabySrcBlock == NULL )
-            {
-                poBlock->DropLock();
-                break;
-            }
-
-            memset(pabySrcBlock, (iOtherBand == 4) ? 0 : 255,
-                   nBlockXSize * nBlockYSize);
-
-            poBlock->DropLock();
-        }
-    }
-
-    return CE_None;
 }
 
 /************************************************************************/
@@ -415,8 +229,9 @@ static unsigned utf8decode(const char* p, const char* end, int* len)
   } else if (c == 0xe0) {
     if (((unsigned char*)p)[1] < 0xa0) goto FAIL;
     goto UTF8_3;
+  }
 #if STRICT_RFC3629
-  } else if (c == 0xed) {
+  else if (c == 0xed) {
     // RFC 3629 says surrogate chars are illegal.
     if (((unsigned char*)p)[1] >= 0xa0) goto FAIL;
     goto UTF8_3;
@@ -425,8 +240,9 @@ static unsigned utf8decode(const char* p, const char* end, int* len)
     if (((unsigned char*)p)[1]==0xbf &&
     ((unsigned char*)p)[2]>=0xbe) goto FAIL;
     goto UTF8_3;
+  }
 #endif
-  } else if (c < 0xf0) {
+  else if (c < 0xf0) {
   UTF8_3:
     if (p+2 >= end || (p[2]&0xc0) != 0x80) goto FAIL;
     *len = 3;
@@ -462,34 +278,11 @@ static unsigned utf8decode(const char* p, const char* end, int* len)
   }
 }
 
-
-/************************************************************************/
-/*                  ComputeTileColTileRowZoomLevel()                    */
-/************************************************************************/
-
-void MBTilesDataset::ComputeTileColTileRowZoomLevel(int nBlockXOff,
-                                                    int nBlockYOff,
-                                                    int &nTileColumn,
-                                                    int &nTileRow,
-                                                    int &nZoomLevel)
-{
-    const int nBlockYSize = 256;
-
-    int _nMinLevel = (poMainDS) ? poMainDS->nMinLevel : nMinLevel;
-    int _nMinTileCol = (poMainDS) ? poMainDS->nMinTileCol : nMinTileCol;
-    int _nMinTileRow = (poMainDS) ? poMainDS->nMinTileRow : nMinTileRow;
-    _nMinTileCol >>= nLevel;
-
-    nTileColumn = nBlockXOff + _nMinTileCol;
-    nTileRow = (((nRasterYSize / nBlockYSize - 1 - nBlockYOff) << nLevel) + _nMinTileRow) >> nLevel;
-    nZoomLevel = ((poMainDS) ? poMainDS->nResolutions : nResolutions) - nLevel + _nMinLevel;
-}
-
 /************************************************************************/
 /*                          HasNonEmptyGrids()                          */
 /************************************************************************/
 
-int MBTilesDataset::HasNonEmptyGrids()
+bool MBTilesDataset::HasNonEmptyGrids()
 {
     OGRLayerH hSQLLyr;
     OGRFeatureH hFeat;
@@ -498,34 +291,34 @@ int MBTilesDataset::HasNonEmptyGrids()
     if (poMainDS)
         return poMainDS->HasNonEmptyGrids();
 
-    if (bHasNonEmptyGrids >= 0)
-        return bHasNonEmptyGrids;
+    if (nHasNonEmptyGrids >= 0)
+        return nHasNonEmptyGrids != FALSE;
 
-    bHasNonEmptyGrids = FALSE;
+    nHasNonEmptyGrids = false;
 
     if (OGR_DS_GetLayerByName(hDS, "grids") == NULL)
-        return FALSE;
+        return false;
 
     pszSQL = "SELECT type FROM sqlite_master WHERE name = 'grids'";
     CPLDebug("MBTILES", "%s", pszSQL);
     hSQLLyr = OGR_DS_ExecuteSQL(hDS, pszSQL, NULL, NULL);
     if (hSQLLyr == NULL)
-        return FALSE;
+        return false;
 
     hFeat = OGR_L_GetNextFeature(hSQLLyr);
     if (hFeat == NULL || !OGR_F_IsFieldSet(hFeat, 0))
     {
         OGR_F_Destroy(hFeat);
         OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
-        return FALSE;
+        return false;
     }
 
-    int bGridsIsView = strcmp(OGR_F_GetFieldAsString(hFeat, 0), "view") == 0;
+    bool bGridsIsView = strcmp(OGR_F_GetFieldAsString(hFeat, 0), "view") == 0;
 
     OGR_F_Destroy(hFeat);
     OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
 
-    bHasNonEmptyGrids = TRUE;
+    nHasNonEmptyGrids = TRUE;
 
     /* In the case 'grids' is a view (and a join between the 'map' and 'grid_utfgrid' layers */
     /* the cost of evaluating a join is very long, even if grid_utfgrid is empty */
@@ -540,29 +333,34 @@ int MBTilesDataset::HasNonEmptyGrids()
             hFeat = OGR_L_GetNextFeature(hGridUTFGridLyr);
             OGR_F_Destroy(hFeat);
 
-            bHasNonEmptyGrids = hFeat != NULL;
+            nHasNonEmptyGrids = hFeat != NULL;
         }
     }
 
-    return bHasNonEmptyGrids;
+    return nHasNonEmptyGrids != FALSE;
 }
 
 /************************************************************************/
 /*                             FindKey()                                */
 /************************************************************************/
 
-char* MBTilesDataset::FindKey(int iPixel, int iLine,
-                              int& nTileColumn, int& nTileRow, int& nZoomLevel)
+char* MBTilesDataset::FindKey(int iPixel, int iLine)
 {
     const int nBlockXSize = 256, nBlockYSize = 256;
-    int nBlockXOff = iPixel / nBlockXSize;
-    int nBlockYOff = iLine / nBlockYSize;
 
-    int nColInBlock = iPixel % nBlockXSize;
-    int nRowInBlock = iLine % nBlockXSize;
+    // Compute shift between GDAL origin and TileMatrixSet origin
+    // Caution this is in GeoPackage / WMTS convention ! That is upper-left corner
+    const int nShiftXPixels = (int)floor(0.5 + (m_adfGeoTransform[0] - TMS_ORIGIN_X) /  m_adfGeoTransform[1]);
+    const int nShiftYPixelsFromGPKGOrigin = (int)floor(0.5 + (m_adfGeoTransform[3] - TMS_ORIGIN_Y) /  m_adfGeoTransform[5]);
 
-    ComputeTileColTileRowZoomLevel(nBlockXOff, nBlockYOff,
-                                   nTileColumn, nTileRow, nZoomLevel);
+    const int iLineFromGPKGOrigin = iLine + nShiftYPixelsFromGPKGOrigin;
+    const int iLineFromMBTilesOrigin = m_nTileMatrixHeight * nBlockYSize - 1 - iLineFromGPKGOrigin;
+    const int iPixelFromMBTilesOrigin = iPixel + nShiftXPixels;
+
+    const int nTileColumn = iPixelFromMBTilesOrigin / nBlockXSize;
+    const int nTileRow = iLineFromMBTilesOrigin / nBlockYSize;
+    int nColInTile = iPixelFromMBTilesOrigin % nBlockXSize;
+    int nRowInTile = nBlockYSize - 1 - (iLineFromMBTilesOrigin % nBlockYSize);
 
     char* pszKey = NULL;
 
@@ -573,11 +371,11 @@ char* MBTilesDataset::FindKey(int iPixel, int iLine,
     int i;
 
     /* See https://github.com/mapbox/utfgrid-spec/blob/master/1.0/utfgrid.md */
-    /* for the explanation of the following processings */
+    /* for the explanation of the following process */
 
     pszSQL = CPLSPrintf("SELECT grid FROM grids WHERE "
                         "zoom_level = %d AND tile_column = %d AND tile_row = %d",
-                        nZoomLevel, nTileColumn, nTileRow);
+                        m_nZoomLevel, nTileColumn, nTileRow);
     CPLDebug("MBTILES", "%s", pszSQL);
     hSQLLyr = OGR_DS_ExecuteSQL(hDS, pszSQL, NULL, NULL);
     if (hSQLLyr == NULL)
@@ -595,7 +393,13 @@ char* MBTilesDataset::FindKey(int iPixel, int iLine,
     GByte* pabyData = OGR_F_GetFieldAsBinary(hFeat, 0, &nDataSize);
 
     int nUncompressedSize = 256*256;
-    GByte* pabyUncompressed = (GByte*)CPLMalloc(nUncompressedSize + 1);
+    GByte* pabyUncompressed = (GByte*)VSIMalloc(nUncompressedSize + 1);
+    if( pabyUncompressed == NULL )
+    {
+        OGR_F_Destroy(hFeat);
+        OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
+        return NULL;
+    }
 
     z_stream sStream;
     memset(&sStream, 0, sizeof(sStream));
@@ -659,10 +463,10 @@ char* MBTilesDataset::FindKey(int iPixel, int iLine,
             goto end;
 
         nFactor = 256 / nLines;
-        nRowInBlock /= nFactor;
-        nColInBlock /= nFactor;
+        nRowInTile /= nFactor;
+        nColInTile /= nFactor;
 
-        poRow = json_object_array_get_idx(poGrid, nRowInBlock);
+        poRow = json_object_array_get_idx(poGrid, nRowInTile);
 
         /* Extract line of interest in grid */
         if (poRow != NULL && json_object_is_type(poRow, json_type_string))
@@ -704,7 +508,7 @@ char* MBTilesDataset::FindKey(int iPixel, int iLine,
                 if (res > 127 && len == 1)
                     break;
 
-                if (iCol == nColInBlock)
+                if (iCol == nColInTile)
                 {
                     nKey = (int)res;
                     //CPLDebug("MBTILES", "Key index = %d", nKey);
@@ -734,8 +538,7 @@ char* MBTilesDataset::FindKey(int iPixel, int iLine,
 end:
     if (jsobj)
         json_object_put(jsobj);
-    if (pabyUncompressed)
-        CPLFree(pabyUncompressed);
+    VSIFree(pabyUncompressed);
     if (hFeat)
         OGR_F_Destroy(hFeat);
     if (hSQLLyr)
@@ -767,7 +570,7 @@ const char *MBTilesBand::GetMetadataItem( const char * pszName,
 /* ==================================================================== */
     if( pszDomain != NULL
         && EQUAL(pszDomain,"LocationInfo")
-        && (EQUALN(pszName,"Pixel_",6) || EQUALN(pszName,"GeoPixel_",9)) )
+        && (STARTS_WITH_CI(pszName, "Pixel_") || STARTS_WITH_CI(pszName, "GeoPixel_")) )
     {
         int iPixel, iLine;
 
@@ -777,12 +580,12 @@ const char *MBTilesBand::GetMetadataItem( const char * pszName,
 /* -------------------------------------------------------------------- */
 /*      What pixel are we aiming at?                                    */
 /* -------------------------------------------------------------------- */
-        if( EQUALN(pszName,"Pixel_",6) )
+        if( STARTS_WITH_CI(pszName, "Pixel_") )
         {
             if( sscanf( pszName+6, "%d_%d", &iPixel, &iLine ) != 2 )
                 return NULL;
         }
-        else if( EQUALN(pszName,"GeoPixel_",9) )
+        else if( STARTS_WITH_CI(pszName, "GeoPixel_") )
         {
             double adfGeoTransform[6];
             double adfInvGeoTransform[6];
@@ -820,8 +623,7 @@ const char *MBTilesBand::GetMetadataItem( const char * pszName,
             || iLine >= GetYSize() )
             return NULL;
 
-        int nTileColumn = -1, nTileRow = -1, nZoomLevel = -1;
-        char* pszKey = poGDS->FindKey(iPixel, iLine, nTileColumn, nTileRow, nZoomLevel);
+        char* pszKey = poGDS->FindKey(iPixel, iLine);
 
         if (pszKey != NULL)
         {
@@ -890,8 +692,8 @@ int MBTilesBand::GetOverviewCount()
 {
     MBTilesDataset* poGDS = (MBTilesDataset*) poDS;
 
-    if (poGDS->nResolutions >= 1)
-        return poGDS->nResolutions;
+    if (poGDS->m_nOverviewCount >= 1)
+        return poGDS->m_nOverviewCount;
     else
         return GDALPamRasterBand::GetOverviewCount();
 }
@@ -904,13 +706,13 @@ GDALRasterBand* MBTilesBand::GetOverview(int nLevel)
 {
     MBTilesDataset* poGDS = (MBTilesDataset*) poDS;
 
-    if (poGDS->nResolutions == 0)
+    if (poGDS->m_nOverviewCount == 0)
         return GDALPamRasterBand::GetOverview(nLevel);
 
-    if (nLevel < 0 || nLevel >= poGDS->nResolutions)
+    if (nLevel < 0 || nLevel >= poGDS->m_nOverviewCount)
         return NULL;
 
-    GDALDataset* poOvrDS = poGDS->papoOverviews[nLevel];
+    GDALDataset* poOvrDS = poGDS->m_papoOverviewDS[nLevel];
     if (poOvrDS)
         return poOvrDS->GetRasterBand(nBand);
     else
@@ -918,261 +720,506 @@ GDALRasterBand* MBTilesBand::GetOverview(int nLevel)
 }
 
 /************************************************************************/
-/*                   GetColorInterpretation()                           */
+/*                         MBTilesDataset()                          */
 /************************************************************************/
 
-GDALColorInterp MBTilesBand::GetColorInterpretation()
+MBTilesDataset::MBTilesDataset()
 {
-    MBTilesDataset* poGDS = (MBTilesDataset*) poDS;
-    if (poGDS->nBands == 1)
-    {
-        return GCI_GrayIndex;
-    }
-    else if (poGDS->nBands == 3 || poGDS->nBands == 4)
-    {
-        if (nBand == 1)
-            return GCI_RedBand;
-        else if (nBand == 2)
-            return GCI_GreenBand;
-        else if (nBand == 3)
-            return GCI_BlueBand;
-        else if (nBand == 4)
-            return GCI_AlphaBand;
-    }
-
-    return GCI_Undefined;
+    m_bWriteBounds = true;
+    poMainDS = NULL;
+    m_nOverviewCount = 0;
+    hDS = NULL;
+    m_papoOverviewDS = NULL;
+    bFetchedMetadata = false;
+    nHasNonEmptyGrids = -1;
+    hDB = NULL;
+#ifdef HAVE_SQLITE_VFS
+    pMyVFS = NULL;
+#endif
+    m_bGeoTransformValid = false;
+    m_adfGeoTransform[0] = 0.0;
+    m_adfGeoTransform[1] = 1.0;
+    m_adfGeoTransform[2] = 0.0;
+    m_adfGeoTransform[3] = 0.0;
+    m_adfGeoTransform[4] = 0.0;
+    m_adfGeoTransform[5] = 1.0;
+    m_bInFlushCache = false;
+
+    m_osRasterTable = "tiles";
+    m_eTF = GPKG_TF_PNG;
 }
 
 /************************************************************************/
-/*                         MBTilesDataset()                          */
+/*                        ~MBTilesDataset()                             */
 /************************************************************************/
 
-MBTilesDataset::MBTilesDataset()
+MBTilesDataset::~MBTilesDataset()
 {
-    bMustFree = FALSE;
-    nLevel = 0;
-    poMainDS = NULL;
-    nResolutions = 0;
-    hDS = NULL;
-    papoOverviews = NULL;
-    papszMetadata = NULL;
-    papszImageStructure =
-        CSLAddString(NULL, "INTERLEAVE=PIXEL");
-    nMinTileCol = nMinTileRow = 0;
-    nMinLevel = 0;
-    bFetchedMetadata = FALSE;
-    bHasNonEmptyGrids = -1;
+    FlushCache();
+
+    if (poMainDS == NULL)
+    {
+        if (m_papoOverviewDS)
+        {
+            for(int i=0;i<m_nOverviewCount;i++)
+                delete m_papoOverviewDS[i];
+            CPLFree(m_papoOverviewDS);
+        }
+
+        if (hDS != NULL)
+        {
+            OGRReleaseDataSource(hDS);
+            hDB = NULL;
+        }
+        if( hDB != NULL )
+        {
+            sqlite3_close(hDB);
+
+#ifdef HAVE_SQLITE_VFS
+            if (pMyVFS)
+            {
+                sqlite3_vfs_unregister(pMyVFS);
+                CPLFree(pMyVFS->pAppData);
+                CPLFree(pMyVFS);
+            }
+#endif
+        }
+    }
 }
 
 /************************************************************************/
-/*                          MBTilesDataset()                            */
+/*                         IStartTransaction()                          */
 /************************************************************************/
 
-MBTilesDataset::MBTilesDataset(MBTilesDataset* poMainDS, int nLevel)
+void MBTilesDataset::IStartTransaction()
 {
-    bMustFree = FALSE;
-    this->nLevel = nLevel;
-    this->poMainDS = poMainDS;
-    nResolutions = poMainDS->nResolutions - nLevel;
-    hDS = poMainDS->hDS;
-    papoOverviews = poMainDS->papoOverviews + nLevel;
-    papszMetadata = poMainDS->papszMetadata;
-    papszImageStructure =  poMainDS->papszImageStructure;
-
-    nRasterXSize = poMainDS->nRasterXSize / (1 << nLevel);
-    nRasterYSize = poMainDS->nRasterYSize / (1 << nLevel);
-    nMinTileCol = nMinTileRow = 0;
-    nMinLevel = 0;
-    bFetchedMetadata = FALSE;
-    bHasNonEmptyGrids = -1;
+    sqlite3_exec( hDB, "BEGIN", NULL, NULL, NULL );
 }
 
 /************************************************************************/
-/*                        ~MBTilesDataset()                             */
+/*                         ICommitTransaction()                         */
 /************************************************************************/
 
-MBTilesDataset::~MBTilesDataset()
+void MBTilesDataset::ICommitTransaction()
 {
-    CloseDependentDatasets();
+    sqlite3_exec( hDB, "COMMIT", NULL, NULL, NULL );
 }
 
 /************************************************************************/
-/*                      CloseDependentDatasets()                        */
+/*                         ICanIWriteBlock()                            */
 /************************************************************************/
 
-int MBTilesDataset::CloseDependentDatasets()
+bool MBTilesDataset::ICanIWriteBlock()
 {
-    int bRet = GDALPamDataset::CloseDependentDatasets();
-
-    if (poMainDS == NULL && !bMustFree)
+    if( eAccess != GA_Update )
     {
-        CSLDestroy(papszMetadata);
-        papszMetadata = NULL;
-        CSLDestroy(papszImageStructure);
-        papszImageStructure = NULL;
-
-        int i;
-
-        if (papoOverviews)
-        {
-            for(i=0;i<nResolutions;i++)
-            {
-                if (papoOverviews[i] != NULL &&
-                    papoOverviews[i]->bMustFree)
-                {
-                    papoOverviews[i]->poMainDS = NULL;
-                }
-                delete papoOverviews[i];
-            }
-            CPLFree(papoOverviews);
-            papoOverviews = NULL;
-            nResolutions = 0;
-            bRet = TRUE;
-        }
-
-        if (hDS != NULL)
-            OGRReleaseDataSource(hDS);
-        hDS = NULL;
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "IWriteBlock() not supported on dataset opened in read-only mode");
+        return false;
     }
-    else if (poMainDS != NULL && bMustFree)
+
+    if( !m_bGeoTransformValid )
     {
-        poMainDS->papoOverviews[nLevel-1] = NULL;
-        delete poMainDS;
-        poMainDS = NULL;
-        bRet = TRUE;
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "IWriteBlock() not supported if georeferencing not set");
+        return false;
     }
-
-    return bRet;
+    return true;
 }
 
 /************************************************************************/
-/*                          GetGeoTransform()                           */
+/*                         IFlushCacheWithErrCode()                            */
 /************************************************************************/
 
-#define MAX_GM 20037508.34
+CPLErr MBTilesDataset::IFlushCacheWithErrCode()
 
-CPLErr MBTilesDataset::GetGeoTransform(double* padfGeoTransform)
 {
-    int nMaxLevel = nMinLevel + nResolutions;
-    if (nMaxLevel == 0)
-    {
-        padfGeoTransform[0] = -MAX_GM;
-        padfGeoTransform[1] = 2 * MAX_GM / nRasterXSize;
-        padfGeoTransform[2] = 0;
-        padfGeoTransform[3] = MAX_GM;
-        padfGeoTransform[4] = 0;
-        padfGeoTransform[5] = -2 * MAX_GM / nRasterYSize;
-    }
-    else
-    {
-        int nMaxTileCol = nMinTileCol + nRasterXSize / 256;
-        int nMaxTileRow = nMinTileRow + nRasterYSize / 256;
-        int nMiddleTile = (1 << nMaxLevel) / 2;
-        padfGeoTransform[0] = 2 * MAX_GM * (nMinTileCol - nMiddleTile) / (1 << nMaxLevel);
-        padfGeoTransform[1] = 2 * MAX_GM * (nMaxTileCol - nMinTileCol) / (1 << nMaxLevel) / nRasterXSize;
-        padfGeoTransform[2] = 0;
-        padfGeoTransform[3] = 2 * MAX_GM * (nMaxTileRow - nMiddleTile) / (1 << nMaxLevel);
-        padfGeoTransform[4] = 0;
-        padfGeoTransform[5] = -2 * MAX_GM * (nMaxTileRow - nMinTileRow) / (1 << nMaxLevel) / nRasterYSize;
-    }
-    return CE_None;
+    if( m_bInFlushCache )
+        return CE_None;
+    m_bInFlushCache = true;
+    // Short circuit GDALPamDataset to avoid serialization to .aux.xml
+    GDALDataset::FlushCache();
+
+    CPLErr eErr = FlushTiles();
+
+    m_bInFlushCache = false;
+    return eErr;
 }
 
 /************************************************************************/
-/*                         GetProjectionRef()                           */
+/*                         ICanIWriteBlock()                            */
 /************************************************************************/
 
-const char* MBTilesDataset::GetProjectionRef()
+int MBTilesDataset::GetRowFromIntoTopConvention(int nRow)
 {
-    return "PROJCS[\"WGS 84 / Pseudo-Mercator\",GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]],PROJECTION[\"Mercator_1SP\"],PARAMETER[\"central_meridian\",0],PARAMETER[\"scale_factor\",1],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0],U [...]
+    return m_nTileMatrixHeight - 1 - nRow;
 }
 
 /************************************************************************/
-/*                      GetMetadataDomainList()                         */
+/*                          GetGeoTransform()                           */
 /************************************************************************/
 
-char **MBTilesDataset::GetMetadataDomainList()
+CPLErr MBTilesDataset::GetGeoTransform(double* padfGeoTransform)
 {
-    return BuildMetadataDomainList(GDALDataset::GetMetadataDomainList(),
-                                   TRUE,
-                                   "", NULL);
+    memcpy(padfGeoTransform, m_adfGeoTransform, 6 * sizeof(double));
+    return ( m_bGeoTransformValid ) ? CE_None : CE_Failure;
 }
 
 /************************************************************************/
-/*                            GetMetadata()                             */
+/*                     SphericalMercatorToLongLat()                     */
 /************************************************************************/
 
-char** MBTilesDataset::GetMetadata( const char * pszDomain )
+static void SphericalMercatorToLongLat(double* x, double* y)
 {
-    if (pszDomain != NULL && !EQUAL(pszDomain, ""))
-        return GDALPamDataset::GetMetadata(pszDomain);
+  double lng = *x / SPHERICAL_RADIUS / M_PI * 180;
+  double lat = 2 * (atan(exp(*y / SPHERICAL_RADIUS)) - M_PI / 4) / M_PI * 180;
+  *x = lng;
+  *y = lat;
+}
 
-    if (bFetchedMetadata)
-        return aosList.List();
+/************************************************************************/
+/*                     LongLatToSphericalMercator()                     */
+/************************************************************************/
 
-    bFetchedMetadata = TRUE;
+static void LongLatToSphericalMercator(double* x, double* y)
+{
+  double X = SPHERICAL_RADIUS * (*x) / 180 * M_PI;
+  double Y = SPHERICAL_RADIUS * log( tan(M_PI / 4 + 0.5 * (*y) / 180 * M_PI) );
+  *x = X;
+  *y = Y;
+}
 
-    OGRLayerH hSQLLyr = OGR_DS_ExecuteSQL(hDS,
-            "SELECT name, value FROM metadata", NULL, NULL);
-    if (hSQLLyr == NULL)
-        return NULL;
+/************************************************************************/
+/*                          SetGeoTransform()                           */
+/************************************************************************/
 
-    if (OGR_FD_GetFieldCount(OGR_L_GetLayerDefn(hSQLLyr)) != 2)
+CPLErr MBTilesDataset::SetGeoTransform( double* padfGeoTransform )
+{
+    if( eAccess != GA_Update )
     {
-        OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
-        return NULL;
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "SetGeoTransform() not supported on read-only dataset");
+        return CE_Failure;
+    }
+    if( m_bGeoTransformValid )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Cannot modify geotransform once set");
+        return CE_Failure;
+    }
+    if( padfGeoTransform[2] != 0.0 || padfGeoTransform[4] != 0 ||
+        padfGeoTransform[5] > 0.0 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Only north-up non rotated geotransform supported");
+        return CE_Failure;
     }
 
-    OGRFeatureH hFeat;
-    while( (hFeat = OGR_L_GetNextFeature(hSQLLyr)) != NULL )
+    if( m_bWriteBounds )
     {
-        if (OGR_F_IsFieldSet(hFeat, 0) && OGR_F_IsFieldSet(hFeat, 1))
+        double minx = padfGeoTransform[0];
+        double miny = padfGeoTransform[3] + nRasterYSize * padfGeoTransform[5];
+        double maxx = padfGeoTransform[0] + nRasterXSize * padfGeoTransform[1];
+        double maxy = padfGeoTransform[3];
+
+        SphericalMercatorToLongLat(&minx, &miny);
+        SphericalMercatorToLongLat(&maxx, &maxy);
+        if( fabs(minx + 180) < 1e-7 && fabs(maxx - 180) < 1e-7 )
         {
-            const char* pszName = OGR_F_GetFieldAsString(hFeat, 0);
-            const char* pszValue = OGR_F_GetFieldAsString(hFeat, 1);
-            if (pszValue[0] != '\0' &&
-                strncmp(pszValue, "function(",9) != 0 &&
-                strstr(pszValue, "<img ") == NULL &&
-                strstr(pszValue, "<p>") == NULL &&
-                strstr(pszValue, "</p>") == NULL &&
-                strstr(pszValue, "<div") == NULL)
-            {
-                aosList.AddNameValue(pszName, pszValue);
-            }
+            minx = -180.0;
+            maxx = 180.0;
         }
-        OGR_F_Destroy(hFeat);
+
+        char* pszSQL = sqlite3_mprintf(
+            "INSERT INTO metadata (name, value) VALUES ('bounds', '%.18g,%.18g,%.18g,%.18g')",
+            minx, miny, maxx, maxy );
+        sqlite3_exec( hDB, pszSQL, NULL, NULL, NULL );
+        sqlite3_free(pszSQL);
     }
-    OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
 
-    return aosList.List();
+    const double dfPixelXSizeZoomLevel0 = 2 * MAX_GM / 256;
+    const double dfPixelYSizeZoomLevel0 = 2 * MAX_GM / 256;
+    for( m_nZoomLevel = 0; m_nZoomLevel < 25; m_nZoomLevel++ )
+    {
+        double dfExpectedPixelXSize = dfPixelXSizeZoomLevel0 / (1 << m_nZoomLevel);
+        double dfExpectedPixelYSize = dfPixelYSizeZoomLevel0 / (1 << m_nZoomLevel);
+        if( fabs( padfGeoTransform[1] - dfExpectedPixelXSize ) < 1e-8 * dfExpectedPixelXSize &&
+            fabs( fabs(padfGeoTransform[5]) - dfExpectedPixelYSize ) < 1e-8 * dfExpectedPixelYSize )
+        {
+            break;
+        }
+    }
+    if( m_nZoomLevel == 25 )
+    {
+        m_nZoomLevel = -1;
+        CPLError(CE_Failure, CPLE_NotSupported,
+                  "Could not find an appropriate zoom level that matches raster pixel size");
+        return CE_Failure;
+    }
+
+    memcpy(m_adfGeoTransform, padfGeoTransform, 6 * sizeof(double));
+    m_bGeoTransformValid = true;
+
+    return FinalizeRasterRegistration();
 }
 
 /************************************************************************/
-/*                             Identify()                               */
+/*                      ComputeTileAndPixelShifts()                     */
 /************************************************************************/
 
-int MBTilesDataset::Identify(GDALOpenInfo* poOpenInfo)
+void MBTilesDataset::ComputeTileAndPixelShifts()
 {
-    if (EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "MBTILES") &&
-        poOpenInfo->nHeaderBytes >= 1024 &&
-        EQUALN((const char*)poOpenInfo->pabyHeader, "SQLite Format 3", 15))
-    {
-        return TRUE;
-    }
+    int nTileWidth, nTileHeight;
+    GetRasterBand(1)->GetBlockSize(&nTileWidth, &nTileHeight);
+
+    // Compute shift between GDAL origin and TileMatrixSet origin
+    // Caution this is in GeoPackage / WMTS convention ! That is upper-left corner
+    int nShiftXPixels = (int)floor(0.5 + (m_adfGeoTransform[0] - TMS_ORIGIN_X) /  m_adfGeoTransform[1]);
+    m_nShiftXTiles = (int)floor(1.0 * nShiftXPixels / nTileWidth);
+    m_nShiftXPixelsMod = ((nShiftXPixels % nTileWidth) + nTileWidth) % nTileWidth;
+    int nShiftYPixels = (int)floor(0.5 + (m_adfGeoTransform[3] - TMS_ORIGIN_Y) /  m_adfGeoTransform[5]);
+    m_nShiftYTiles = (int)floor(1.0 * nShiftYPixels / nTileHeight);
+    m_nShiftYPixelsMod = ((nShiftYPixels % nTileHeight) + nTileHeight) % nTileHeight;
 
-    return FALSE;
 }
 
 /************************************************************************/
-/*                        MBTilesGetMinMaxZoomLevel()                   */
+/*                      FinalizeRasterRegistration()                    */
 /************************************************************************/
 
-static
-int MBTilesGetMinMaxZoomLevel(OGRDataSourceH hDS, int bHasMap,
-                                int &nMinLevel, int &nMaxLevel)
+CPLErr MBTilesDataset::FinalizeRasterRegistration()
 {
-    const char* pszSQL;
-    OGRLayerH hSQLLyr;
+    m_nTileMatrixWidth = (1 << m_nZoomLevel);
+    m_nTileMatrixHeight = (1 << m_nZoomLevel);
+
+    ComputeTileAndPixelShifts();
+
+    double dfGDALMinX = m_adfGeoTransform[0];
+    double dfGDALMinY = m_adfGeoTransform[3] + nRasterYSize * m_adfGeoTransform[5];
+    double dfGDALMaxX = m_adfGeoTransform[0] + nRasterXSize * m_adfGeoTransform[1];
+    double dfGDALMaxY = m_adfGeoTransform[3];
+
+    m_nOverviewCount = m_nZoomLevel;
+    m_papoOverviewDS = (MBTilesDataset**) CPLCalloc(sizeof(MBTilesDataset*),
+                                                           m_nOverviewCount);
+
+    for(int i=0; i<m_nOverviewCount; i++)
+    {
+        MBTilesDataset* poOvrDS = new MBTilesDataset();
+        poOvrDS->InitRaster ( this, i, nBands,
+                              dfGDALMinX, dfGDALMinY,
+                              dfGDALMaxX, dfGDALMaxY );
+
+        m_papoOverviewDS[m_nZoomLevel-1-i] = poOvrDS;
+    }
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                         InitRaster()                                 */
+/************************************************************************/
+
+int MBTilesDataset::InitRaster ( MBTilesDataset* poParentDS,
+                                 int nZoomLevel,
+                                 int nBandCount,
+                                 double dfGDALMinX,
+                                 double dfGDALMinY,
+                                 double dfGDALMaxX,
+                                 double dfGDALMaxY )
+{
+    m_nZoomLevel = nZoomLevel;
+    m_nTileMatrixWidth = 1 << nZoomLevel;
+    m_nTileMatrixHeight = 1 << nZoomLevel;
+
+    const int nTileWidth = 256;
+    const int nTileHeight = 256;
+    const double dfPixelXSize = 2 * MAX_GM / 256 / (1 << nZoomLevel);
+    const double dfPixelYSize = dfPixelXSize;
+
+    m_bGeoTransformValid = true;
+    m_adfGeoTransform[0] = dfGDALMinX;
+    m_adfGeoTransform[1] = dfPixelXSize;
+    m_adfGeoTransform[3] = dfGDALMaxY;
+    m_adfGeoTransform[5] = -dfPixelYSize;
+    double dfRasterXSize = 0.5 + (dfGDALMaxX - dfGDALMinX) / dfPixelXSize;
+    double dfRasterYSize = 0.5 + (dfGDALMaxY - dfGDALMinY) / dfPixelYSize;
+    if( dfRasterXSize > INT_MAX || dfRasterYSize > INT_MAX )
+        return FALSE;
+    nRasterXSize = (int)dfRasterXSize;
+    nRasterYSize = (int)dfRasterYSize;
+
+    m_pabyCachedTiles = (GByte*) VSI_MALLOC3_VERBOSE(4 * 4, nTileWidth, nTileHeight);
+    if( m_pabyCachedTiles == NULL )
+    {
+        return FALSE;
+    }
+
+    for(int i = 1; i <= nBandCount; i ++)
+        SetBand( i, new MBTilesBand(this) );
+
+    ComputeTileAndPixelShifts();
+
+    GDALDataset::SetMetadataItem("INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE");
+    GDALDataset::SetMetadataItem("ZOOM_LEVEL", CPLSPrintf("%d", m_nZoomLevel));
+
+    if( poParentDS )
+    {
+        m_poParentDS = poParentDS;
+        poMainDS = poParentDS;
+        eAccess = poParentDS->eAccess;
+        hDB = poParentDS->hDB;
+        m_eTF = poParentDS->m_eTF;
+        m_nQuality = poParentDS->m_nQuality;
+        m_nZLevel = poParentDS->m_nZLevel;
+        m_bDither = poParentDS->m_bDither;
+        m_osWHERE = poParentDS->m_osWHERE;
+        SetDescription(CPLSPrintf("%s - zoom_level=%d",
+                                  poParentDS->GetDescription(), m_nZoomLevel));
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                         GetProjectionRef()                           */
+/************************************************************************/
+
+const char* MBTilesDataset::GetProjectionRef()
+{
+    return SRS_EPSG_3857;
+}
+
+/************************************************************************/
+/*                           SetProjection()                            */
+/************************************************************************/
+
+CPLErr MBTilesDataset::SetProjection( const char* pszProjection )
+{
+    if( eAccess != GA_Update )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "SetProjection() not supported on read-only dataset");
+        return CE_Failure;
+    }
+
+    OGRSpatialReference oSRS;
+    if( oSRS.SetFromUserInput(pszProjection) != OGRERR_NONE )
+        return CE_Failure;
+    if( oSRS.GetAuthorityName(NULL) == NULL ||
+        !EQUAL(oSRS.GetAuthorityName(NULL), "EPSG") ||
+        oSRS.GetAuthorityCode(NULL) == NULL ||
+        !EQUAL(oSRS.GetAuthorityCode(NULL), "3857") )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Only EPSG:3857 supported on MBTiles dataset");
+        return CE_Failure;
+    }
+    return CE_None;
+}
+
+/************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **MBTilesDataset::GetMetadataDomainList()
+{
+    return BuildMetadataDomainList(GDALDataset::GetMetadataDomainList(),
+                                   TRUE,
+                                   "", NULL);
+}
+
+/************************************************************************/
+/*                            GetMetadata()                             */
+/************************************************************************/
+
+char** MBTilesDataset::GetMetadata( const char * pszDomain )
+{
+    if (pszDomain != NULL && !EQUAL(pszDomain, ""))
+        return GDALPamDataset::GetMetadata(pszDomain);
+
+    if (bFetchedMetadata)
+        return aosList.List();
+
+    bFetchedMetadata = true;
+    aosList = CPLStringList(GDALPamDataset::GetMetadata(), FALSE);
+
+    OGRLayerH hSQLLyr = OGR_DS_ExecuteSQL(hDS,
+            "SELECT name, value FROM metadata", NULL, NULL);
+    if (hSQLLyr == NULL)
+        return NULL;
+
+    if (OGR_FD_GetFieldCount(OGR_L_GetLayerDefn(hSQLLyr)) != 2)
+    {
+        OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
+        return NULL;
+    }
+
+    OGRFeatureH hFeat;
+    while( (hFeat = OGR_L_GetNextFeature(hSQLLyr)) != NULL )
+    {
+        if (OGR_F_IsFieldSet(hFeat, 0) && OGR_F_IsFieldSet(hFeat, 1))
+        {
+            const char* pszName = OGR_F_GetFieldAsString(hFeat, 0);
+            const char* pszValue = OGR_F_GetFieldAsString(hFeat, 1);
+            if (pszValue[0] != '\0' &&
+                !STARTS_WITH(pszValue, "function(") &&
+                strstr(pszValue, "<img ") == NULL &&
+                strstr(pszValue, "<p>") == NULL &&
+                strstr(pszValue, "</p>") == NULL &&
+                strstr(pszValue, "<div") == NULL)
+            {
+                aosList.AddNameValue(pszName, pszValue);
+            }
+        }
+        OGR_F_Destroy(hFeat);
+    }
+    OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
+
+    return aosList.List();
+}
+
+/************************************************************************/
+/*                         GetMetadataItem()                            */
+/************************************************************************/
+
+const char *MBTilesDataset::GetMetadataItem( const char* pszName, const char * pszDomain )
+{
+    if( pszDomain == NULL || EQUAL(pszDomain, "") )
+    {
+        const char* pszValue = CSLFetchNameValue( GetMetadata(), pszName );
+        if( pszValue )
+            return pszValue;
+    }
+    return GDALPamDataset::GetMetadataItem(pszName, pszDomain);
+}
+
+/************************************************************************/
+/*                             Identify()                               */
+/************************************************************************/
+
+int MBTilesDataset::Identify(GDALOpenInfo* poOpenInfo)
+{
+    if (EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "MBTILES") &&
+        poOpenInfo->nHeaderBytes >= 1024 &&
+        STARTS_WITH_CI((const char*)poOpenInfo->pabyHeader, "SQLite Format 3"))
+    {
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+/************************************************************************/
+/*                        MBTilesGetMinMaxZoomLevel()                   */
+/************************************************************************/
+
+static
+int MBTilesGetMinMaxZoomLevel(OGRDataSourceH hDS, int bHasMap,
+                                int &nMinLevel, int &nMaxLevel)
+{
+    const char* pszSQL;
+    OGRLayerH hSQLLyr;
     OGRFeatureH hFeat;
     int bHasMinMaxLevel = FALSE;
 
@@ -1289,63 +1336,80 @@ int MBTilesGetMinMaxZoomLevel(OGRDataSourceH hDS, int bHasMap,
 }
 
 /************************************************************************/
+/*                   MBTilesTileCoordToWorldCoord()                     */
+/************************************************************************/
+
+static double MBTilesTileCoordToWorldCoord(double dfTileCoord, int nZoomLevel)
+{
+    return -MAX_GM + 2 * MAX_GM * (dfTileCoord / (1 << nZoomLevel));
+}
+
+/************************************************************************/
+/*                   MBTilesWorldCoordToTileCoord()                     */
+/************************************************************************/
+
+static double MBTilesWorldCoordToTileCoord(double dfWorldCoord, int nZoomLevel)
+{
+    return (dfWorldCoord + MAX_GM) / (2 * MAX_GM) * (1 << nZoomLevel);
+}
+
+/************************************************************************/
 /*                           MBTilesGetBounds()                         */
 /************************************************************************/
 
 static
-int MBTilesGetBounds(OGRDataSourceH hDS,
-                     CPL_UNUSED int nMinLevel,
+bool MBTilesGetBounds(OGRDataSourceH hDS, bool bUseBounds,
                      int nMaxLevel,
-                     int& nMinTileRow, int& nMaxTileRow,
-                     int& nMinTileCol, int &nMaxTileCol)
+                     double& minX, double& minY,
+                     double& maxX, double& maxY)
 {
     const char* pszSQL;
-    int bHasBounds = FALSE;
+    bool bHasBounds = false;
     OGRLayerH hSQLLyr;
     OGRFeatureH hFeat;
 
-    pszSQL = "SELECT value FROM metadata WHERE name = 'bounds'";
-    CPLDebug("MBTILES", "%s", pszSQL);
-    hSQLLyr = OGR_DS_ExecuteSQL(hDS, pszSQL, NULL, NULL);
-    if (hSQLLyr)
+    if( bUseBounds )
     {
-        hFeat = OGR_L_GetNextFeature(hSQLLyr);
-        if (hFeat != NULL)
+        pszSQL = "SELECT value FROM metadata WHERE name = 'bounds'";
+        CPLDebug("MBTILES", "%s", pszSQL);
+        hSQLLyr = OGR_DS_ExecuteSQL(hDS, pszSQL, NULL, NULL);
+        if (hSQLLyr)
         {
-            const char* pszBounds = OGR_F_GetFieldAsString(hFeat, 0);
-            char** papszTokens = CSLTokenizeString2(pszBounds, ",", 0);
-            if (CSLCount(papszTokens) != 4 ||
-                fabs(CPLAtof(papszTokens[0])) > 180 ||
-                fabs(CPLAtof(papszTokens[1])) > 86 ||
-                fabs(CPLAtof(papszTokens[2])) > 180 ||
-                fabs(CPLAtof(papszTokens[3])) > 86 ||
-                CPLAtof(papszTokens[0]) > CPLAtof(papszTokens[2]) ||
-                CPLAtof(papszTokens[1]) > CPLAtof(papszTokens[3]))
+            hFeat = OGR_L_GetNextFeature(hSQLLyr);
+            if (hFeat != NULL)
             {
-                CPLError(CE_Failure, CPLE_AppDefined, "Invalid value for 'bounds' metadata");
-                CSLDestroy(papszTokens);
-                OGR_F_Destroy(hFeat);
-                OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
-                return FALSE;
-            }
-
-            #define FORTPI      0.78539816339744833
-            /* Latitude to Google-mercator northing */
-            #define LAT_TO_NORTHING(lat) \
-                6378137 * log(tan(FORTPI + .5 * (lat) / 180 * (4 * FORTPI)))
+                const char* pszBounds = OGR_F_GetFieldAsString(hFeat, 0);
+                char** papszTokens = CSLTokenizeString2(pszBounds, ",", 0);
+                if (CSLCount(papszTokens) != 4 ||
+                    fabs(CPLAtof(papszTokens[0])) > 180 ||
+                    fabs(CPLAtof(papszTokens[1])) >= 89.99 ||
+                    fabs(CPLAtof(papszTokens[2])) > 180 ||
+                    fabs(CPLAtof(papszTokens[3])) >= 89.99 ||
+                    CPLAtof(papszTokens[0]) > CPLAtof(papszTokens[2]) ||
+                    CPLAtof(papszTokens[1]) > CPLAtof(papszTokens[3]))
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined, "Invalid value for 'bounds' metadata");
+                    CSLDestroy(papszTokens);
+                    OGR_F_Destroy(hFeat);
+                    OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
+                    return false;
+                }
 
-            nMinTileCol = (int)(((CPLAtof(papszTokens[0]) + 180) / 360) * (1 << nMaxLevel));
-            nMaxTileCol = (int)(((CPLAtof(papszTokens[2]) + 180) / 360) * (1 << nMaxLevel));
-            nMinTileRow = (int)(0.5 + ((LAT_TO_NORTHING(CPLAtof(papszTokens[1])) + MAX_GM) / (2* MAX_GM)) * (1 << nMaxLevel));
-            nMaxTileRow = (int)(0.5 + ((LAT_TO_NORTHING(CPLAtof(papszTokens[3])) + MAX_GM) / (2* MAX_GM)) * (1 << nMaxLevel));
+                minX = CPLAtof(papszTokens[0]);
+                minY = CPLAtof(papszTokens[1]);
+                maxX = CPLAtof(papszTokens[2]);
+                maxY = CPLAtof(papszTokens[3]);
+                LongLatToSphericalMercator(&minX, &minY);
+                LongLatToSphericalMercator(&maxX, &maxY);
 
-            bHasBounds = TRUE;
+                bHasBounds = true;
 
-            CSLDestroy(papszTokens);
+                CSLDestroy(papszTokens);
 
-            OGR_F_Destroy(hFeat);
-        }
-        OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
+                OGR_F_Destroy(hFeat);
+            }
+            OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
+      }
     }
 
     if (!bHasBounds)
@@ -1357,14 +1421,14 @@ int MBTilesGetBounds(OGRDataSourceH hDS,
         hSQLLyr = OGR_DS_ExecuteSQL(hDS, pszSQL, NULL, NULL);
         if (hSQLLyr == NULL)
         {
-            return FALSE;
+            return false;
         }
 
         hFeat = OGR_L_GetNextFeature(hSQLLyr);
         if (hFeat == NULL)
         {
             OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
-            return FALSE;
+            return false;
         }
 
         if (OGR_F_IsFieldSet(hFeat, 0) &&
@@ -1372,11 +1436,15 @@ int MBTilesGetBounds(OGRDataSourceH hDS,
             OGR_F_IsFieldSet(hFeat, 2) &&
             OGR_F_IsFieldSet(hFeat, 3))
         {
-            nMinTileCol = OGR_F_GetFieldAsInteger(hFeat, 0);
-            nMaxTileCol = OGR_F_GetFieldAsInteger(hFeat, 1) + 1;
-            nMinTileRow = OGR_F_GetFieldAsInteger(hFeat, 2);
-            nMaxTileRow = OGR_F_GetFieldAsInteger(hFeat, 3) + 1;
-            bHasBounds = TRUE;
+            int nMinTileCol = OGR_F_GetFieldAsInteger(hFeat, 0);
+            int nMaxTileCol = OGR_F_GetFieldAsInteger(hFeat, 1);
+            int nMinTileRow = OGR_F_GetFieldAsInteger(hFeat, 2);
+            int nMaxTileRow = OGR_F_GetFieldAsInteger(hFeat, 3);
+            minX = MBTilesTileCoordToWorldCoord(nMinTileCol, nMaxLevel);
+            minY = MBTilesTileCoordToWorldCoord(nMinTileRow, nMaxLevel);
+            maxX = MBTilesTileCoordToWorldCoord(nMaxTileCol + 1, nMaxLevel);
+            maxY = MBTilesTileCoordToWorldCoord(nMaxTileRow + 1, nMaxLevel);
+            bHasBounds = true;
         }
 
         OGR_F_Destroy(hFeat);
@@ -1501,7 +1569,6 @@ static int MBTilesCurlReadCbk(CPL_UNUSED VSILFILE* fp,
 
 static
 int MBTilesGetBandCount(OGRDataSourceH &hDS,
-                        CPL_UNUSED int nMinLevel,
                         int nMaxLevel,
                         int nMinTileRow, int nMaxTileRow,
                         int nMinTileCol, int nMaxTileCol)
@@ -1517,7 +1584,7 @@ int MBTilesGetBandCount(OGRDataSourceH &hDS,
     /* Small trick to get the VSILFILE associated with the OGR SQLite */
     /* DB */
     CPLString osDSName(OGR_DS_GetName(hDS));
-    if (strncmp(osDSName.c_str(), "/vsicurl/", 9) == 0)
+    if (STARTS_WITH(osDSName.c_str(), "/vsicurl/"))
     {
         CPLErrorReset();
         CPLPushErrorHandler(CPLQuietErrorHandler);
@@ -1532,7 +1599,7 @@ int MBTilesGetBandCount(OGRDataSourceH &hDS,
                 if (OGR_F_IsFieldSet(hFeat, 0))
                 {
                     const char* pszPointer = OGR_F_GetFieldAsString(hFeat, 0);
-                    fpCURLOGR = (VSILFILE* )CPLScanPointer( pszPointer, strlen(pszPointer) );
+                    fpCURLOGR = (VSILFILE* )CPLScanPointer( pszPointer, static_cast<int>(strlen(pszPointer)) );
                 }
                 OGR_F_Destroy(hFeat);
             }
@@ -1549,7 +1616,7 @@ int MBTilesGetBandCount(OGRDataSourceH &hDS,
 
     if (fpCURLOGR)
     {
-        /* Install a spy on the file connexion that will intercept */
+        /* Install a spy on the file connection that will intercept */
         /* PNG or JPEG headers, to interrupt their downloading */
         /* once the header is found. Speeds up dataset opening. */
         CPLErrorReset();
@@ -1570,10 +1637,10 @@ int MBTilesGetBandCount(OGRDataSourceH &hDS,
             OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
             hSQLLyr = NULL;
 
-            /* Re-open OGR SQLite DB, because with our spy we have simulated an I/O error */
-            /* that SQLite will have difficulies to recover within the existing connection */
-            /* No worry ! This will be fast because the /vsicurl/ cache has cached the already */
-            /* read blocks */
+            // Re-open OGR SQLite DB, because with our spy we have simulated an
+            // I/O error that SQLite will have difficulties to recover within
+            // the existing connection.  This will be fast because
+            // the /vsicurl/ cache has cached the already read blocks.
             OGRReleaseDataSource(hDS);
             hDS = MBTILESOpenSQLiteDB(osDSName.c_str(), GA_ReadOnly);
             if (hDS == NULL)
@@ -1595,7 +1662,7 @@ int MBTilesGetBandCount(OGRDataSourceH &hDS,
         hSQLLyr = OGR_DS_ExecuteSQL(hDS, pszSQL, NULL, NULL);
     }
 
-    while( TRUE )
+    while( true )
     {
         if (hSQLLyr == NULL && bFirstSelect)
         {
@@ -1641,7 +1708,7 @@ int MBTilesGetBandCount(OGRDataSourceH &hDS,
 
     nBands = GDALGetRasterCount(hDSTile);
 
-    if ((nBands != 1 && nBands != 3 && nBands != 4) ||
+    if ((nBands != 1 && nBands != 2 && nBands != 3 && nBands != 4) ||
         GDALGetRasterXSize(hDSTile) != 256 ||
         GDALGetRasterYSize(hDSTile) != 256 ||
         GDALGetRasterDataType(GDALGetRasterBand(hDSTile, 1)) != GDT_Byte)
@@ -1694,7 +1761,8 @@ GDALDataset* MBTilesDataset::Open(GDALOpenInfo* poOpenInfo)
 /*      Open underlying OGR DB                                          */
 /* -------------------------------------------------------------------- */
 
-    OGRDataSourceH hDS = MBTILESOpenSQLiteDB(poOpenInfo->pszFilename, GA_ReadOnly);
+    OGRDataSourceH hDS = MBTILESOpenSQLiteDB(poOpenInfo->pszFilename,
+                                             poOpenInfo->eAccess);
 
     MBTilesDataset* poDS = NULL;
 
@@ -1709,16 +1777,11 @@ GDALDataset* MBTilesDataset::Open(GDALOpenInfo* poOpenInfo)
         CPLString osSQL;
         OGRLayerH hMetadataLyr, hRasterLyr;
         OGRFeatureH hFeat;
-        int nResolutions;
-        int iBand, nBands, nBlockXSize, nBlockYSize;
-        GDALDataType eDataType;
+        int nBands;
         OGRLayerH hSQLLyr = NULL;
         int nMinLevel = -1, nMaxLevel = -1;
-        int nMinTileRow = 0, nMaxTileRow = 0, nMinTileCol = 0, nMaxTileCol = 0;
-        int bHasBounds = FALSE;
         int bHasMinMaxLevel = FALSE;
         int bHasMap;
-        const char* pszBandCount;
 
         osMetadataTableName = "metadata";
 
@@ -1765,6 +1828,10 @@ GDALDataset* MBTilesDataset::Open(GDALOpenInfo* poOpenInfo)
         bHasMinMaxLevel = MBTilesGetMinMaxZoomLevel(hDS, bHasMap,
                                                     nMinLevel, nMaxLevel);
 
+        const char* pszZoomLevel = CSLFetchNameValue(poOpenInfo->papszOpenOptions, "ZOOM_LEVEL");
+        if( pszZoomLevel != NULL )
+            nMaxLevel = atoi(pszZoomLevel);
+
         if (bHasMinMaxLevel && (nMinLevel < 0 || nMinLevel > nMaxLevel))
         {
             CPLError(CE_Failure, CPLE_AppDefined,
@@ -1789,30 +1856,53 @@ GDALDataset* MBTilesDataset::Open(GDALOpenInfo* poOpenInfo)
 /* -------------------------------------------------------------------- */
 /*      Get bounds                                                      */
 /* -------------------------------------------------------------------- */
-
-        bHasBounds = MBTilesGetBounds(hDS, nMinLevel, nMaxLevel,
-                                      nMinTileRow, nMaxTileRow,
-                                      nMinTileCol, nMaxTileCol);
+        double dfMinX = 0.0, dfMinY = 0.0, dfMaxX = 0.0, dfMaxY = 0.0;
+        bool bUseBounds = CPLFetchBool(const_cast<const char**>(poOpenInfo->papszOpenOptions),
+                                      "USE_BOUNDS", true);
+        const char* pszMinX = CSLFetchNameValue(poOpenInfo->papszOpenOptions, "MINX");
+        const char* pszMinY = CSLFetchNameValue(poOpenInfo->papszOpenOptions, "MINY");
+        const char* pszMaxX = CSLFetchNameValue(poOpenInfo->papszOpenOptions, "MAXX");
+        const char* pszMaxY = CSLFetchNameValue(poOpenInfo->papszOpenOptions, "MAXY");
+        bool bHasBounds;
+        if( pszMinX != NULL && pszMinY != NULL && pszMaxX != NULL && pszMaxY != NULL )
+        {
+            bHasBounds = true;
+        }
+        else
+        {
+            bHasBounds = MBTilesGetBounds(hDS, bUseBounds, nMaxLevel,
+                                          dfMinX, dfMinY,
+                                          dfMaxX, dfMaxY);
+        }
         if (!bHasBounds)
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Cannot find min and max tile numbers");
             goto end;
         }
+        if( pszMinX != NULL ) dfMinX = CPLAtof(pszMinX);
+        if( pszMinY != NULL ) dfMinY = CPLAtof(pszMinY);
+        if( pszMaxX != NULL ) dfMaxX = CPLAtof(pszMaxX);
+        if( pszMaxY != NULL ) dfMaxY = CPLAtof(pszMaxY);
 
 /* -------------------------------------------------------------------- */
 /*      Get number of bands                                             */
 /* -------------------------------------------------------------------- */
-
-        pszBandCount = CPLGetConfigOption("MBTILES_BAND_COUNT", "-1");
+        const char* pszBandCount = CSLFetchNameValueDef(
+            poOpenInfo->papszOpenOptions, "BAND_COUNT",
+            CPLGetConfigOption("MBTILES_BAND_COUNT", "-1"));
         nBands = atoi(pszBandCount);
 
-        if( ! (nBands == 1 || nBands == 3 || nBands == 4) )
+        if( ! (nBands == 1 || nBands == 2 || nBands == 3 || nBands == 4) )
         {
-            nBands = MBTilesGetBandCount(hDS, nMinLevel, nMaxLevel,
+            int nMinTileCol = static_cast<int>(MBTilesWorldCoordToTileCoord( dfMinX, nMaxLevel ));
+            int nMinTileRow = static_cast<int>(MBTilesWorldCoordToTileCoord( dfMinY, nMaxLevel ));
+            int nMaxTileCol = static_cast<int>(MBTilesWorldCoordToTileCoord( dfMaxX, nMaxLevel ));
+            int nMaxTileRow = static_cast<int>(MBTilesWorldCoordToTileCoord( dfMaxY, nMaxLevel ));
+            nBands = MBTilesGetBandCount(hDS, nMaxLevel,
                                          nMinTileRow, nMaxTileRow,
                                          nMinTileCol, nMaxTileCol);
             if (nBands < 0)
-                goto end;
+                nBands = 4;
         }
 
 /* -------------------------------------------------------------------- */
@@ -1822,74 +1912,68 @@ GDALDataset* MBTilesDataset::Open(GDALOpenInfo* poOpenInfo)
         poDS = new MBTilesDataset();
         poDS->eAccess = poOpenInfo->eAccess;
         poDS->hDS = hDS;
+        poDS->hDB = (sqlite3*) GDALGetInternalHandle( (GDALDatasetH)hDS, "SQLITE_HANDLE" );
+        CPLAssert(poDS->hDB != NULL);
 
         /* poDS will release it from now */
         hDS = NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Store resolutions                                               */
-/* -------------------------------------------------------------------- */
-        poDS->nMinLevel = nMinLevel;
-        poDS->nResolutions = nResolutions = nMaxLevel - nMinLevel;
+        poDS->InitRaster ( NULL, nMaxLevel, nBands,
+                           dfMinX, dfMinY, dfMaxX, dfMaxY );
 
-/* -------------------------------------------------------------------- */
-/*      Round bounds to the lowest zoom level                           */
-/* -------------------------------------------------------------------- */
-
-        //CPLDebug("MBTILES", "%d %d %d %d", nMinTileCol, nMinTileRow, nMaxTileCol, nMaxTileRow);
-        nMinTileCol = (int)(1.0 * nMinTileCol / (1 << nResolutions)) * (1 << nResolutions);
-        nMinTileRow = (int)(1.0 * nMinTileRow / (1 << nResolutions)) * (1 << nResolutions);
-        nMaxTileCol = (int)ceil(1.0 * nMaxTileCol / (1 << nResolutions)) * (1 << nResolutions);
-        nMaxTileRow = (int)ceil(1.0 * nMaxTileRow / (1 << nResolutions)) * (1 << nResolutions);
-
-/* -------------------------------------------------------------------- */
-/*      Compute raster size, geotransform and projection                */
-/* -------------------------------------------------------------------- */
-        poDS->nMinTileCol = nMinTileCol;
-        poDS->nMinTileRow = nMinTileRow;
-        poDS->nRasterXSize = (nMaxTileCol-nMinTileCol) * 256;
-        poDS->nRasterYSize = (nMaxTileRow-nMinTileRow) * 256;
+        if( poDS->eAccess == GA_Update )
+        {
+            // So that we can edit all potential overviews
+            nMinLevel = 0;
 
-        nBlockXSize = nBlockYSize = 256;
-        eDataType = GDT_Byte;
+            const char* pszFormat = poDS->GetMetadataItem("format");
+            if( pszFormat != NULL && (EQUAL(pszFormat, "jpg") || EQUAL(pszFormat, "jpeg")) )
+            {
+                poDS->m_eTF = GPKG_TF_JPEG;
+            }
 
-/* -------------------------------------------------------------------- */
-/*      Add bands                                                       */
-/* -------------------------------------------------------------------- */
+            const char* pszTF = CSLFetchNameValue(poOpenInfo->papszOpenOptions, "TILE_FORMAT");
+            if( pszTF )
+            {
+                poDS->m_eTF = GDALGPKGMBTilesGetTileFormat(pszTF);
+                if( (pszFormat != NULL && (EQUAL(pszFormat, "jpg") || EQUAL(pszFormat, "jpeg")) &&
+                     poDS->m_eTF != GPKG_TF_JPEG) ||
+                    (pszFormat != NULL && EQUAL(pszFormat, "png") && poDS->m_eTF == GPKG_TF_JPEG) )
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "Format metadata = '%s', but TILE_FORMAT='%s'",
+                             pszFormat, pszTF);
+                }
+            }
 
-        for(iBand=0;iBand<nBands;iBand++)
-            poDS->SetBand(iBand+1, new MBTilesBand(poDS, iBand+1, eDataType,
-                                                  nBlockXSize, nBlockYSize));
+            poDS->ParseCompressionOptions(poOpenInfo->papszOpenOptions);
+        }
 
 /* -------------------------------------------------------------------- */
 /*      Add overview levels as internal datasets                        */
 /* -------------------------------------------------------------------- */
-        if (nResolutions >= 1)
+        for( int iLevel = nMaxLevel - 1; iLevel >= nMinLevel; iLevel-- )
         {
-            poDS->papoOverviews = (MBTilesDataset**)
-                CPLCalloc(nResolutions, sizeof(MBTilesDataset*));
-            int nLev;
-            for(nLev=1;nLev<=nResolutions;nLev++)
-            {
-                poDS->papoOverviews[nLev-1] = new MBTilesDataset(poDS, nLev);
+            MBTilesDataset* poOvrDS = new MBTilesDataset();
+            poOvrDS->InitRaster ( poDS, iLevel, nBands, dfMinX, dfMinY, dfMaxX, dfMaxY );
 
-                for(iBand=0;iBand<nBands;iBand++)
-                {
-                    poDS->papoOverviews[nLev-1]->SetBand(iBand+1,
-                        new MBTilesBand(poDS->papoOverviews[nLev-1], iBand+1, eDataType,
-                                           nBlockXSize, nBlockYSize));
-                }
+            poDS->m_papoOverviewDS = (MBTilesDataset**) CPLRealloc(poDS->m_papoOverviewDS,
+                            sizeof(MBTilesDataset*) * (poDS->m_nOverviewCount+1));
+            poDS->m_papoOverviewDS[poDS->m_nOverviewCount ++] = poOvrDS;
+
+            if( poOvrDS->GetRasterXSize() < 256 &&
+                poOvrDS->GetRasterYSize() < 256 )
+            {
+                break;
             }
         }
 
-        poDS->SetMetadata(poDS->papszImageStructure, "IMAGE_STRUCTURE");
-
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
         poDS->SetDescription( poOpenInfo->pszFilename );
 
-        if ( !EQUALN(poOpenInfo->pszFilename, "/vsicurl/", 9) )
+        if ( !STARTS_WITH_CI(poOpenInfo->pszFilename, "/vsicurl/") )
             poDS->TryLoadXML();
         else
         {
@@ -1905,34 +1989,621 @@ end:
 }
 
 /************************************************************************/
-/*                       GDALRegister_MBTiles()                         */
+/*                                Create()                              */
 /************************************************************************/
 
-void GDALRegister_MBTiles()
+GDALDataset* MBTilesDataset::Create( const char * pszFilename,
+                                   int nXSize,
+                                   int nYSize,
+                                   int nBandsIn,
+                                   GDALDataType eDT,
+                                   char **papszOptions )
+{
+    MBTilesDataset* poDS = new MBTilesDataset();
+    if( !poDS->CreateInternal(pszFilename, nXSize, nYSize, nBandsIn, eDT, papszOptions) )
+    {
+        delete poDS;
+        poDS = NULL;
+    }
+    return poDS;
+}
+
+/************************************************************************/
+/*                            CreateInternal()                          */
+/************************************************************************/
 
+bool MBTilesDataset::CreateInternal( const char * pszFilename,
+                                   int nXSize,
+                                   int nYSize,
+                                   int nBandsIn,
+                                   GDALDataType eDT,
+                                   char **papszOptions )
 {
-    GDALDriver  *poDriver;
+    if( eDT != GDT_Byte )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, "Only Byte supported");
+        return false;
+    }
+    if( nBandsIn != 1 && nBandsIn != 2 && nBandsIn != 3 && nBandsIn != 4 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                  "Only 1 (Grey/ColorTable), 2 (Grey+Alpha), 3 (RGB) or 4 (RGBA) band dataset supported");
+        return false;
+    }
 
-    if (! GDAL_CHECK_VERSION("MBTiles driver"))
-        return;
+    // for test/debug purposes only. true is the nominal value
+    m_bPNGSupports2Bands = CPLTestBool(CPLGetConfigOption("MBTILES_PNG_SUPPORTS_2BANDS", "TRUE"));
+    m_bPNGSupportsCT = CPLTestBool(CPLGetConfigOption("MBTILES_PNG_SUPPORTS_CT", "TRUE"));
+    m_bWriteBounds = CPLFetchBool(const_cast<const char**>(papszOptions), "WRITE_BOUNDS", true);
+
+    VSIUnlink( pszFilename );
+    SetDescription( pszFilename );
+
+    int rc;
+#ifdef HAVE_SQLITE_VFS
+    if (STARTS_WITH(pszFilename, "/vsi"))
+    {
+        pMyVFS = OGRSQLiteCreateVFS(NULL, NULL);
+        sqlite3_vfs_register(pMyVFS, 0);
+        rc = sqlite3_open_v2( pszFilename, &hDB, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, pMyVFS->zName );
+    }
+    else
+#endif
+    {
+        rc = sqlite3_open( pszFilename, &hDB );
+    }
+
+    if( rc != SQLITE_OK )
+    {
+        CPLError(CE_Failure, CPLE_FileIO, "Cannot create %s", pszFilename);
+        return false;
+    }
+
+    sqlite3_exec( hDB, "PRAGMA synchronous = OFF", NULL, NULL, NULL );
+
+    rc = sqlite3_exec( hDB, "CREATE TABLE tiles ("
+          "zoom_level INTEGER NOT NULL,"
+          "tile_column INTEGER NOT NULL,"
+          "tile_row INTEGER NOT NULL,"
+          "tile_data BLOB NOT NULL,"
+          "UNIQUE (zoom_level, tile_column, tile_row) )", NULL, NULL, NULL );
+    if( rc != SQLITE_OK )
+    {
+        CPLError(CE_Failure, CPLE_FileIO, "Cannot create tiles table");
+        return false;
+    }
+
+    rc = sqlite3_exec( hDB, "CREATE TABLE metadata (name TEXT, value TEXT)", NULL, NULL, NULL );
+    if( rc != SQLITE_OK )
+    {
+        CPLError(CE_Failure, CPLE_FileIO, "Cannot create metadata table");
+        return false;
+    }
+
+    char* pszSQL;
+
+    const char* pszName = CSLFetchNameValueDef(papszOptions, "NAME",
+                                               CPLGetBasename(pszFilename));
+    pszSQL = sqlite3_mprintf(
+        "INSERT INTO metadata (name, value) VALUES ('name', '%q')", pszName );
+    sqlite3_exec( hDB, pszSQL, NULL, NULL, NULL );
+    sqlite3_free(pszSQL);
+
+    const char* pszType = CSLFetchNameValueDef(papszOptions, "TYPE",
+                                               "overlay");
+    pszSQL = sqlite3_mprintf(
+        "INSERT INTO metadata (name, value) VALUES ('type', '%q')", pszType );
+    sqlite3_exec( hDB, pszSQL, NULL, NULL, NULL );
+    sqlite3_free(pszSQL);
+
+    const char* pszDescription = CSLFetchNameValueDef(papszOptions, "DESCRIPTION",
+                                               CPLGetBasename(pszFilename));
+    pszSQL = sqlite3_mprintf(
+        "INSERT INTO metadata (name, value) VALUES ('description', '%q')", pszDescription );
+    sqlite3_exec( hDB, pszSQL, NULL, NULL, NULL );
+    sqlite3_free(pszSQL);
+
+    const char* pszVersion = CSLFetchNameValueDef(papszOptions, "VERSION", "1.1");
+    pszSQL = sqlite3_mprintf(
+        "INSERT INTO metadata (name, value) VALUES ('version', '%q')", pszVersion );
+    sqlite3_exec( hDB, pszSQL, NULL, NULL, NULL );
+    sqlite3_free(pszSQL);
+
+    const char* pszTF = CSLFetchNameValue(papszOptions, "TILE_FORMAT");
+    if( pszTF )
+        m_eTF = GDALGPKGMBTilesGetTileFormat(pszTF);
+
+    const char* pszFormat = CSLFetchNameValueDef(papszOptions, "FORMAT",
+                                        (m_eTF == GPKG_TF_JPEG) ? "jpg" : "png" );
+    pszSQL = sqlite3_mprintf(
+        "INSERT INTO metadata (name, value) VALUES ('format', '%q')", pszFormat );
+    sqlite3_exec( hDB, pszSQL, NULL, NULL, NULL );
+    sqlite3_free(pszSQL);
+
+    m_bNew = true;
+    eAccess = GA_Update;
+    nRasterXSize = nXSize;
+    nRasterYSize = nYSize;
+
+    m_pabyCachedTiles = (GByte*) VSI_MALLOC3_VERBOSE(4 * 4, 256, 256);
+    if( m_pabyCachedTiles == NULL )
+    {
+        return false;
+    }
+
+    for(int i = 1; i <= nBandsIn; i ++)
+        SetBand( i, new MBTilesBand(this) );
+
+    ParseCompressionOptions(papszOptions);
+
+    return true;
+}
+
+/************************************************************************/
+/*                            CreateCopy()                              */
+/************************************************************************/
+
+typedef struct
+{
+    const char*         pszName;
+    GDALResampleAlg     eResampleAlg;
+} WarpResamplingAlg;
+
+static const WarpResamplingAlg asResamplingAlg[] =
+{
+    { "NEAREST", GRA_NearestNeighbour },
+    { "BILINEAR", GRA_Bilinear },
+    { "CUBIC", GRA_Cubic },
+    { "CUBICSPLINE", GRA_CubicSpline },
+    { "LANCZOS", GRA_Lanczos },
+    { "MODE", GRA_Mode },
+    { "AVERAGE", GRA_Average },
+};
+
+GDALDataset* MBTilesDataset::CreateCopy( const char *pszFilename,
+                                         GDALDataset *poSrcDS,
+                                         int /*bStrict*/,
+                                         char ** papszOptions,
+                                         GDALProgressFunc pfnProgress,
+                                         void * pProgressData )
+{
+
+    int nBands = poSrcDS->GetRasterCount();
+    if( nBands != 1 && nBands != 2 && nBands != 3 && nBands != 4 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                    "Only 1 (Grey/ColorTable), 2 (Grey+Alpha), 3 (RGB) or 4 (RGBA) band dataset supported");
+        return NULL;
+    }
+
+    char** papszTO = CSLSetNameValue( NULL, "DST_SRS", SRS_EPSG_3857 );
+    void* hTransformArg =
+            GDALCreateGenImgProjTransformer2( poSrcDS, NULL, papszTO );
+    if( hTransformArg == NULL )
+    {
+        CSLDestroy(papszTO);
+        return NULL;
+    }
+
+    GDALTransformerInfo* psInfo = (GDALTransformerInfo*)hTransformArg;
+    double adfGeoTransform[6];
+    double adfExtent[4];
+    int    nXSize, nYSize;
+
+    if ( GDALSuggestedWarpOutput2( poSrcDS,
+                                  psInfo->pfnTransform, hTransformArg,
+                                  adfGeoTransform,
+                                  &nXSize, &nYSize,
+                                  adfExtent, 0 ) != CE_None )
+    {
+        CSLDestroy(papszTO);
+        GDALDestroyGenImgProjTransformer( hTransformArg );
+        return NULL;
+    }
+
+    GDALDestroyGenImgProjTransformer( hTransformArg );
+    hTransformArg = NULL;
 
-    if( GDALGetDriverByName( "MBTiles" ) == NULL )
+    int nZoomLevel;
+    double dfComputedRes = adfGeoTransform[1];
+    double dfPrevRes = 0, dfRes = 0;
+    const double dfPixelXSizeZoomLevel0 = 2 * MAX_GM / 256;
+    for(nZoomLevel = 0; nZoomLevel < 25; nZoomLevel++)
+    {
+        dfRes = dfPixelXSizeZoomLevel0 / (1 << nZoomLevel);
+        if( dfComputedRes > dfRes )
+            break;
+        dfPrevRes = dfRes;
+    }
+    if( nZoomLevel == 25 )
     {
-        poDriver = new GDALDriver();
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Could not find an appropriate zoom level");
+        CSLDestroy(papszTO);
+        return NULL;
+    }
+
+    const char* pszZoomLevelStrategy = CSLFetchNameValueDef(papszOptions,
+                                                            "ZOOM_LEVEL_STRATEGY",
+                                                            "AUTO");
+    if( fabs( dfComputedRes - dfRes ) / dfRes > 1e-8 )
+    {
+        if( EQUAL(pszZoomLevelStrategy, "LOWER") )
+        {
+            if( nZoomLevel > 0 )
+                nZoomLevel --;
+        }
+        else if( EQUAL(pszZoomLevelStrategy, "UPPER") )
+        {
+            /* do nothing */
+        }
+        else if( nZoomLevel > 0 )
+        {
+            if( dfPrevRes / dfComputedRes < dfComputedRes / dfRes )
+                nZoomLevel --;
+        }
+    }
+
+    dfRes = dfPixelXSizeZoomLevel0 / (1 << nZoomLevel);
 
-        poDriver->SetDescription( "MBTiles" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "MBTiles" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "frmt_mbtiles.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "mbtiles" );
+    double dfMinX = adfExtent[0];
+    double dfMinY = adfExtent[1];
+    double dfMaxX = adfExtent[2];
+    double dfMaxY = adfExtent[3];
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    nXSize = (int) ( 0.5 + ( dfMaxX - dfMinX ) / dfRes );
+    nYSize = (int) ( 0.5 + ( dfMaxY - dfMinY ) / dfRes );
+    adfGeoTransform[1] = dfRes;
+    adfGeoTransform[5] = -dfRes;
 
-        poDriver->pfnOpen = MBTilesDataset::Open;
-        poDriver->pfnIdentify = MBTilesDataset::Identify;
+    int nTargetBands = nBands;
+    /* For grey level or RGB, if there's reprojection involved, add an alpha */
+    /* channel */
+    if( (nBands == 1 && poSrcDS->GetRasterBand(1)->GetColorTable() == NULL) ||
+        nBands == 3 )
+    {
+        OGRSpatialReference oSrcSRS;
+        oSrcSRS.SetFromUserInput(poSrcDS->GetProjectionRef());
+        oSrcSRS.AutoIdentifyEPSG();
+        if( oSrcSRS.GetAuthorityCode(NULL) == NULL ||
+            atoi(oSrcSRS.GetAuthorityCode(NULL)) != 3857 )
+        {
+            nTargetBands ++;
+        }
+    }
+
+    GDALDataset* poDS = Create( pszFilename, nXSize, nYSize, nTargetBands, GDT_Byte,
+                                   papszOptions );
+    if( poDS == NULL )
+    {
+        CSLDestroy(papszTO);
+        return NULL;
+    }
+    poDS->SetGeoTransform(adfGeoTransform);
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
+    hTransformArg =
+        GDALCreateGenImgProjTransformer2( poSrcDS, poDS, papszTO );
+    CSLDestroy(papszTO);
+    if( hTransformArg == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "GDALCreateGenImgProjTransformer2 failed");
+        delete poDS;
+        return NULL;
     }
+
+/* -------------------------------------------------------------------- */
+/*      Warp the transformer with a linear approximator                 */
+/* -------------------------------------------------------------------- */
+    hTransformArg =
+        GDALCreateApproxTransformer( GDALGenImgProjTransform,
+                                     hTransformArg, 0.125 );
+    GDALApproxTransformerOwnsSubtransformer(hTransformArg, TRUE);
+
+/* -------------------------------------------------------------------- */
+/*      Setup warp options.                                             */
+/* -------------------------------------------------------------------- */
+    GDALWarpOptions *psWO = GDALCreateWarpOptions();
+
+    psWO->papszWarpOptions = NULL;
+    psWO->eWorkingDataType = GDT_Byte;
+
+    GDALResampleAlg eResampleAlg = GRA_Bilinear;
+    const char* pszResampling = CSLFetchNameValue(papszOptions, "RESAMPLING");
+    if( pszResampling )
+    {
+        for(size_t iAlg = 0; iAlg < sizeof(asResamplingAlg)/sizeof(asResamplingAlg[0]); iAlg ++)
+        {
+            if( EQUAL(pszResampling, asResamplingAlg[iAlg].pszName) )
+            {
+                eResampleAlg = asResamplingAlg[iAlg].eResampleAlg;
+                break;
+            }
+        }
+    }
+    psWO->eResampleAlg = eResampleAlg;
+
+    psWO->hSrcDS = poSrcDS;
+    psWO->hDstDS = poDS;
+
+    psWO->pfnTransformer = GDALApproxTransform;
+    psWO->pTransformerArg = hTransformArg;
+
+    psWO->pfnProgress = pfnProgress;
+    psWO->pProgressArg = pProgressData;
+
+/* -------------------------------------------------------------------- */
+/*      Setup band mapping.                                             */
+/* -------------------------------------------------------------------- */
+
+    if( nBands == 2 || nBands == 4 )
+        psWO->nBandCount = nBands - 1;
+    else
+        psWO->nBandCount = nBands;
+
+    psWO->panSrcBands = (int *) CPLMalloc(psWO->nBandCount*sizeof(int));
+    psWO->panDstBands = (int *) CPLMalloc(psWO->nBandCount*sizeof(int));
+
+    for( int i = 0; i < psWO->nBandCount; i++ )
+    {
+        psWO->panSrcBands[i] = i+1;
+        psWO->panDstBands[i] = i+1;
+    }
+
+    if( nBands == 2 || nBands == 4 )
+    {
+        psWO->nSrcAlphaBand = nBands;
+    }
+    if( nTargetBands == 2 || nTargetBands == 4 )
+    {
+        psWO->nDstAlphaBand = nTargetBands;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Initialize and execute the warp.                                */
+/* -------------------------------------------------------------------- */
+    GDALWarpOperation oWO;
+
+    CPLErr eErr = oWO.Initialize( psWO );
+    if( eErr == CE_None )
+    {
+        /*if( bMulti )
+            eErr = oWO.ChunkAndWarpMulti( 0, 0, nXSize, nYSize );
+        else*/
+        eErr = oWO.ChunkAndWarpImage( 0, 0, nXSize, nYSize );
+    }
+    if (eErr != CE_None)
+    {
+        delete poDS;
+        poDS = NULL;
+    }
+
+    GDALDestroyTransformer( hTransformArg );
+    GDALDestroyWarpOptions( psWO );
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                        ParseCompressionOptions()                     */
+/************************************************************************/
+
+void MBTilesDataset::ParseCompressionOptions(char** papszOptions)
+{
+    const char* pszZLevel = CSLFetchNameValue(papszOptions, "ZLEVEL");
+    if( pszZLevel )
+        m_nZLevel = atoi(pszZLevel);
+
+    const char* pszQuality = CSLFetchNameValue(papszOptions, "QUALITY");
+    if( pszQuality )
+        m_nQuality = atoi(pszQuality);
+
+    const char* pszDither = CSLFetchNameValue(papszOptions, "DITHER");
+    if( pszDither )
+        m_bDither = CPLTestBool(pszDither);
+}
+
+/************************************************************************/
+/*                          IBuildOverviews()                           */
+/************************************************************************/
+
+static int GetFloorPowerOfTwo(int n)
+{
+    int p2 = 1;
+    while( (n = n >> 1) > 0 )
+    {
+        p2 <<= 1;
+    }
+    return p2;
+}
+
+CPLErr MBTilesDataset::IBuildOverviews(
+                        const char * pszResampling,
+                        int nOverviews, int * panOverviewList,
+                        int nBandsIn, int * /*panBandList*/,
+                        GDALProgressFunc pfnProgress, void * pProgressData )
+{
+    if( GetAccess() != GA_Update )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Overview building not supported on a database opened in read-only mode");
+        return CE_Failure;
+    }
+    if( m_poParentDS != NULL )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Overview building not supported on overview dataset");
+        return CE_Failure;
+    }
+
+    if( nOverviews == 0 )
+    {
+        for(int i=0;i<m_nOverviewCount;i++)
+            m_papoOverviewDS[i]->FlushCache();
+        char* pszSQL = sqlite3_mprintf("DELETE FROM 'tiles' WHERE zoom_level < %d",
+                                       m_nZoomLevel);
+        char* pszErrMsg = NULL;
+        int ret = sqlite3_exec(hDB, pszSQL, NULL, NULL, &pszErrMsg);
+        sqlite3_free(pszSQL);
+        if( ret != SQLITE_OK )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Failure: %s",
+                     pszErrMsg ? pszErrMsg : "");
+            sqlite3_free(pszErrMsg);
+            return CE_Failure;
+        }
+        return CE_None;
+    }
+
+    if( nBandsIn != nBands )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Generation of overviews only"
+                  "supported when operating on all bands." );
+        return CE_Failure;
+    }
+
+    if( m_nOverviewCount == 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Image too small to support overviews");
+        return CE_Failure;
+    }
+
+    FlushCache();
+    for(int i=0;i<nOverviews;i++)
+    {
+        if( panOverviewList[i] < 2 )
+        {
+            CPLError(CE_Failure, CPLE_IllegalArg, "Overview factor '%d' must be >= 2",
+                     panOverviewList[i]);
+            return CE_Failure;
+        }
+
+        if( GetFloorPowerOfTwo( panOverviewList[i] ) != panOverviewList[i] )
+        {
+            CPLError(CE_Failure, CPLE_IllegalArg, "Overview factor '%d' is not a power of 2",
+                     panOverviewList[i]);
+            return CE_Failure;
+        }
+    }
+
+    GDALRasterBand*** papapoOverviewBands = (GDALRasterBand ***) CPLCalloc(sizeof(void*),nBands);
+    int iCurOverview = 0;
+    for( int iBand = 0; iBand < nBands; iBand++ )
+    {
+        papapoOverviewBands[iBand] = (GDALRasterBand **) CPLCalloc(sizeof(void*),nOverviews);
+        iCurOverview = 0;
+        for(int i=0;i<nOverviews;i++)
+        {
+            int nVal = panOverviewList[i];
+            int iOvr = -1;
+            while( nVal > 1 )
+            {
+                nVal >>= 1;
+                iOvr ++;
+            }
+            if( iOvr >= m_nOverviewCount )
+            {
+                continue;
+            }
+            GDALDataset* poODS = m_papoOverviewDS[iOvr];
+            papapoOverviewBands[iBand][iCurOverview] = poODS->GetRasterBand(iBand+1);
+            iCurOverview++ ;
+        }
+    }
+
+    CPLErr eErr = GDALRegenerateOverviewsMultiBand(nBands, papoBands,
+                                     iCurOverview, papapoOverviewBands,
+                                     pszResampling, pfnProgress, pProgressData );
+
+    for( int iBand = 0; iBand < nBands; iBand++ )
+    {
+        CPLFree(papapoOverviewBands[iBand]);
+    }
+    CPLFree(papapoOverviewBands);
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                       GDALRegister_MBTiles()                         */
+/************************************************************************/
+
+void GDALRegister_MBTiles()
+
+{
+    if( !GDAL_CHECK_VERSION( "MBTiles driver" ) )
+        return;
+
+    if( GDALGetDriverByName( "MBTiles" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "MBTiles" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "MBTiles" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_mbtiles.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "mbtiles" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte" );
+
+#define COMPRESSION_OPTIONS \
+"  <Option name='TILE_FORMAT' type='string-select' description='Format to use to create tiles' default='PNG'>" \
+"    <Value>PNG</Value>" \
+"    <Value>PNG8</Value>" \
+"    <Value>JPEG</Value>" \
+"  </Option>" \
+"  <Option name='QUALITY' type='int' min='1' max='100' description='Quality for JPEG tiles' default='75'/>" \
+"  <Option name='ZLEVEL' type='int' min='1' max='9' description='DEFLATE compression level for PNG tiles' default='6'/>" \
+"  <Option name='DITHER' type='boolean' description='Whether to apply Floyd-Steinberg dithering (for TILE_FORMAT=PNG8)' default='NO'/>" \
+
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST, "<OpenOptionList>"
+"  <Option name='ZOOM_LEVEL' type='integer' description='Zoom level of full resolution. If not specified, maximum non-empty zoom level'/>"
+"  <Option name='BAND_COUNT' type='string-select' description='Number of raster bands' default='AUTO'>"
+"    <Value>AUTO</Value>"
+"    <Value>1</Value>"
+"    <Value>2</Value>"
+"    <Value>3</Value>"
+"    <Value>4</Value>"
+"  </Option>"
+"  <Option name='MINX' type='float' description='Minimum X of area of interest'/>"
+"  <Option name='MINY' type='float' description='Minimum Y of area of interest'/>"
+"  <Option name='MAXX' type='float' description='Maximum X of area of interest'/>"
+"  <Option name='MAXY' type='float' description='Maximum Y of area of interest'/>"
+"  <Option name='USE_BOUNDS' type='boolean' description='Whether to use the bounds metadata, when available, to determine the AOI' default='YES'/>"
+COMPRESSION_OPTIONS
+"</OpenOptionList>");
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, "<CreationOptionList>"
+"  <Option name='NAME' type='string' description='Tileset name'/>"
+"  <Option name='DESCRIPTION' type='string' description='A description of the layer'/>"
+"  <Option name='TYPE' type='string-select' description='Layer type' default='overlay'>"
+"    <Value>overlay</Value>"
+"    <Value>baselayer</Value>"
+"  </Option>"
+"  <Option name='VERSION' type='string' description='The version of the tileset, as a plain number' default='1.1'/>"
+COMPRESSION_OPTIONS
+"  <Option name='ZOOM_LEVEL_STRATEGY' type='string-select' description='Strategy to determine zoom level.' default='AUTO'>"
+"    <Value>AUTO</Value>"
+"    <Value>LOWER</Value>"
+"    <Value>UPPER</Value>"
+"  </Option>"
+"  <Option name='RESAMPLING' type='string-select' description='Resampling algorithm.' default='BILINEAR'>"
+"    <Value>NEAREST</Value>"
+"    <Value>BILINEAR</Value>"
+"    <Value>CUBIC</Value>"
+"    <Value>CUBICSPLINE</Value>"
+"    <Value>LANCZOS</Value>"
+"    <Value>MODE</Value>"
+"    <Value>AVERAGE</Value>"
+"  </Option>"
+"  <Option name='WRITE_BOUNDS' type='boolean' description='Whether to write the bounds metadata' default='YES'/>"
+"</CreationOptionList>");
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = MBTilesDataset::Open;
+    poDriver->pfnIdentify = MBTilesDataset::Identify;
+    poDriver->pfnCreateCopy = MBTilesDataset::CreateCopy;
+    poDriver->pfnCreate = MBTilesDataset::Create;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/mem/frmt_mem.html b/frmts/mem/frmt_mem.html
index 65f10d0..c8578f7 100644
--- a/frmts/mem/frmt_mem.html
+++ b/frmts/mem/frmt_mem.html
@@ -32,7 +32,7 @@ For example:
 </pre>
 
 <ul>
-<li> DATAPOINTER: pointer to the first pixel of the first band represented as 
+<li> DATAPOINTER: pointer to the first pixel of the first band represented as
 a long integer.  NOTE!  This may not work on platforms where a long is 32 bits and a pointer is 64 bits. (required)
 <li> PIXELS: Width of raster in pixels. (required)
 <li> LINES: Height of raster in lines. (required)
@@ -48,7 +48,7 @@ a long integer.  NOTE!  This may not work on platforms where a long is 32 bits a
 There are no supported creation options.<p>
 
 The MEM format is one of the few that supports the AddBand() method.
-The AddBand() method supports DATAPOINTER, PIXELOFFSET and LINEOFFSET 
+The AddBand() method supports DATAPOINTER, PIXELOFFSET and LINEOFFSET
 options to reference an existing memory array.<p>
 
 </body>
diff --git a/frmts/mem/memdataset.cpp b/frmts/mem/memdataset.cpp
index 06bd387..1c2e48f 100644
--- a/frmts/mem/memdataset.cpp
+++ b/frmts/mem/memdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: memdataset.cpp 28899 2015-04-14 09:27:00Z rouault $
+ * $Id: memdataset.cpp 33838 2016-03-31 20:42:32Z goatbar $
  *
  * Project:  Memory Array Translator
  * Purpose:  Complete implementation.
@@ -28,42 +28,69 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "memdataset.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "memdataset.h"
 
-CPL_CVSID("$Id: memdataset.cpp 28899 2015-04-14 09:27:00Z rouault $");
+CPL_CVSID("$Id: memdataset.cpp 33838 2016-03-31 20:42:32Z goatbar $");
 
 /************************************************************************/
 /*                        MEMCreateRasterBand()                         */
 /************************************************************************/
 
-GDALRasterBandH MEMCreateRasterBand( GDALDataset *poDS, int nBand, 
-                                    GByte *pabyData, GDALDataType eType, 
-                                    int nPixelOffset, int nLineOffset, 
-                                    int bAssumeOwnership )
+GDALRasterBandH MEMCreateRasterBand( GDALDataset *poDS, int nBand,
+                                     GByte *pabyData, GDALDataType eType,
+                                     int nPixelOffset, int nLineOffset,
+                                     int bAssumeOwnership )
 
 {
-    return (GDALRasterBandH) 
-        new MEMRasterBand( poDS, nBand, pabyData, eType, nPixelOffset, 
-                           nLineOffset, bAssumeOwnership );
+    return reinterpret_cast<GDALRasterBandH>(
+        new MEMRasterBand( poDS, nBand, pabyData, eType, nPixelOffset,
+                           nLineOffset, bAssumeOwnership ) );
 }
 
 /************************************************************************/
-/*                           MEMRasterBand()                            */
+/*                       MEMCreateRasterBandEx()                        */
 /************************************************************************/
 
-MEMRasterBand::MEMRasterBand( GDALDataset *poDS, int nBand,
-                              GByte *pabyDataIn, GDALDataType eTypeIn, 
-                              GSpacing nPixelOffsetIn, GSpacing nLineOffsetIn,
-                              int bAssumeOwnership, const char * pszPixelType)
+GDALRasterBandH MEMCreateRasterBandEx( GDALDataset *poDS, int nBand,
+                                       GByte *pabyData, GDALDataType eType,
+                                       GSpacing nPixelOffset,
+                                       GSpacing nLineOffset,
+                                       int bAssumeOwnership )
 
 {
-    //CPLDebug( "MEM", "MEMRasterBand(%p)", this );
+    return reinterpret_cast<GDALRasterBandH>(
+        new MEMRasterBand( poDS, nBand, pabyData, eType, nPixelOffset,
+                           nLineOffset, bAssumeOwnership ) );
+}
+
+/************************************************************************/
+/*                           MEMRasterBand()                            */
+/************************************************************************/
 
-    this->poDS = poDS;
-    this->nBand = nBand;
+MEMRasterBand::MEMRasterBand( GDALDataset *poDSIn, int nBandIn,
+                              GByte *pabyDataIn, GDALDataType eTypeIn,
+                              GSpacing nPixelOffsetIn, GSpacing nLineOffsetIn,
+                              int bAssumeOwnership, const char * pszPixelType) :
+    GDALPamRasterBand(FALSE),
+    pabyData(pabyDataIn),
+    // Skip nPixelOffset and nLineOffset.
+    bOwnData(bAssumeOwnership),
+    bNoDataSet(FALSE),
+    dfNoData(0.0),
+    poColorTable(NULL),
+    eColorInterp(GCI_Undefined),
+    pszUnitType(NULL),
+    papszCategoryNames(NULL),
+    dfOffset(0.0),
+    dfScale(1.0),
+    psSavedHistograms(NULL)
+{
+    poDS = poDSIn;
+    nBand = nBandIn;
 
-    this->eAccess = poDS->GetAccess();
+    eAccess = poDS->GetAccess();
 
     eDataType = eTypeIn;
 
@@ -71,31 +98,17 @@ MEMRasterBand::MEMRasterBand( GDALDataset *poDS, int nBand,
     nBlockYSize = 1;
 
     if( nPixelOffsetIn == 0 )
-        nPixelOffsetIn = GDALGetDataTypeSize(eTypeIn) / 8;
+        nPixelOffsetIn = GDALGetDataTypeSizeBytes(eTypeIn);
 
     if( nLineOffsetIn == 0 )
-        nLineOffsetIn = nPixelOffsetIn * (size_t)nBlockXSize;
+        nLineOffsetIn = nPixelOffsetIn * static_cast<size_t>(nBlockXSize);
 
     nPixelOffset = nPixelOffsetIn;
     nLineOffset = nLineOffsetIn;
     bOwnData = bAssumeOwnership;
 
-    pabyData = pabyDataIn;
-
-    bNoDataSet  = FALSE;
-
-    poColorTable = NULL;
-    
-    eColorInterp = GCI_Undefined;
-
-    papszCategoryNames = NULL;
-    dfOffset = 0.0;
-    dfScale = 1.0;
-    pszUnitType = NULL;
-    psSavedHistograms = NULL;
-
     if( pszPixelType && EQUAL(pszPixelType,"SIGNEDBYTE") )
-        this->SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" );
+        SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" );
 }
 
 /************************************************************************/
@@ -105,10 +118,8 @@ MEMRasterBand::MEMRasterBand( GDALDataset *poDS, int nBand,
 MEMRasterBand::~MEMRasterBand()
 
 {
-    //CPLDebug( "MEM", "~MEMRasterBand(%p)", this );
     if( bOwnData )
     {
-        //CPLDebug( "MEM", "~MEMRasterBand() - free raw data." );
         VSIFree( pabyData );
     }
 
@@ -131,23 +142,25 @@ CPLErr MEMRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                                   int nBlockYOff,
                                   void * pImage )
 {
-    int     nWordSize = GDALGetDataTypeSize( eDataType ) / 8;
     CPLAssert( nBlockXOff == 0 );
 
+    const int nWordSize = GDALGetDataTypeSize( eDataType ) / 8;
+
     if( nPixelOffset == nWordSize )
     {
-        memcpy( pImage, 
-                pabyData + nLineOffset*(size_t)nBlockYOff, 
-                nPixelOffset * nBlockXSize );
+        memcpy( pImage,
+                pabyData + nLineOffset*(size_t)nBlockYOff,
+                static_cast<size_t>(nPixelOffset) * nBlockXSize );
     }
     else
     {
-        GByte *pabyCur = pabyData + nLineOffset * (size_t)nBlockYOff;
+        GByte * const pabyCur =
+            pabyData + nLineOffset * static_cast<size_t>(nBlockYOff);
 
         for( int iPixel = 0; iPixel < nBlockXSize; iPixel++ )
         {
-            memcpy( ((GByte *) pImage) + iPixel*nWordSize, 
-                    pabyCur + iPixel*nPixelOffset, 
+            memcpy( reinterpret_cast<GByte *>(pImage) + iPixel*nWordSize,
+                    pabyCur + iPixel*nPixelOffset,
                     nWordSize );
         }
     }
@@ -163,23 +176,24 @@ CPLErr MEMRasterBand::IWriteBlock( CPL_UNUSED int nBlockXOff,
                                    int nBlockYOff,
                                    void * pImage )
 {
-    int     nWordSize = GDALGetDataTypeSize( eDataType ) / 8;
     CPLAssert( nBlockXOff == 0 );
+    const int nWordSize = GDALGetDataTypeSize( eDataType ) / 8;
 
     if( nPixelOffset == nWordSize )
     {
-        memcpy( pabyData+nLineOffset*(size_t)nBlockYOff, 
-                pImage, 
-                nPixelOffset * nBlockXSize );
+        memcpy( pabyData+nLineOffset*(size_t)nBlockYOff,
+                pImage,
+                static_cast<size_t>(nPixelOffset) * nBlockXSize );
     }
     else
     {
-        GByte *pabyCur = pabyData + nLineOffset*(size_t)nBlockYOff;
+        GByte *pabyCur =
+            pabyData + nLineOffset * static_cast<size_t>(nBlockYOff);
 
         for( int iPixel = 0; iPixel < nBlockXSize; iPixel++ )
         {
-            memcpy( pabyCur + iPixel*nPixelOffset, 
-                    ((GByte *) pImage) + iPixel*nWordSize, 
+            memcpy( pabyCur + iPixel*nPixelOffset,
+                    reinterpret_cast<GByte *>( pImage ) + iPixel*nWordSize,
                     nWordSize );
         }
     }
@@ -204,37 +218,44 @@ CPLErr MEMRasterBand::IRasterIO( GDALRWFlag eRWFlag,
         return GDALRasterBand::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
                                          pData, nBufXSize, nBufYSize,
                                          eBufType,
-                                         nPixelSpaceBuf, nLineSpaceBuf,
+                                         static_cast<int>(nPixelSpaceBuf),
+                                         nLineSpaceBuf,
                                          psExtraArg);
     }
 
-    // In case block based I/O has been done before
+    // In case block based I/O has been done before.
     FlushCache();
 
     if( eRWFlag == GF_Read )
     {
-        for(int iLine=0;iLine<nYSize;iLine++)
+        for( int iLine=0; iLine < nYSize; iLine++ )
         {
-            GDALCopyWords( pabyData + nLineOffset*(size_t)(iLine + nYOff) + nXOff*nPixelOffset,
-                           eDataType,
-                           nPixelOffset,
-                           ((GByte*)pData) + nLineSpaceBuf*(size_t)iLine,
-                           eBufType,
-                           nPixelSpaceBuf,
-                           nXSize);
+            GDALCopyWords(
+                pabyData + nLineOffset*static_cast<size_t>(iLine + nYOff) +
+                nXOff*nPixelOffset,
+                eDataType,
+                static_cast<int>(nPixelOffset),
+                reinterpret_cast<GByte*>( pData ) +
+                nLineSpaceBuf * static_cast<size_t>(iLine),
+                eBufType,
+                static_cast<int>(nPixelSpaceBuf),
+                nXSize );
         }
     }
     else
     {
-        for(int iLine=0;iLine<nYSize;iLine++)
+        for( int iLine = 0; iLine < nYSize; iLine++ )
         {
-            GDALCopyWords( ((GByte*)pData) + nLineSpaceBuf*(size_t)iLine,
-                           eBufType,
-                           nPixelSpaceBuf,
-                           pabyData + nLineOffset*(size_t)(iLine + nYOff) + nXOff*nPixelOffset,
-                           eDataType,
-                           nPixelOffset,
-                           nXSize);
+            GDALCopyWords(
+                reinterpret_cast<GByte *>( pData ) +
+                nLineSpaceBuf*(size_t)iLine,
+                eBufType,
+                static_cast<int>(nPixelSpaceBuf),
+                pabyData + nLineOffset*static_cast<size_t>(iLine + nYOff) +
+                nXOff*nPixelOffset,
+                eDataType,
+                static_cast<int>(nPixelOffset),
+                nXSize );
         }
     }
     return CE_None;
@@ -247,16 +268,17 @@ CPLErr MEMRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 CPLErr MEMDataset::IRasterIO( GDALRWFlag eRWFlag,
                               int nXOff, int nYOff, int nXSize, int nYSize,
                               void * pData, int nBufXSize, int nBufYSize,
-                              GDALDataType eBufType, 
+                              GDALDataType eBufType,
                               int nBandCount, int *panBandMap,
                               GSpacing nPixelSpaceBuf,
                               GSpacing nLineSpaceBuf,
                               GSpacing nBandSpaceBuf,
                               GDALRasterIOExtraArg* psExtraArg)
 {
-    int eBufTypeSize = GDALGetDataTypeSize(eBufType) / 8;
+    const int eBufTypeSize = GDALGetDataTypeSize(eBufType) / 8;
 
-    /* Detect if we have a pixel-interleaved buffer and a pixel-interleaved dataset */
+    // Detect if we have a pixel-interleaved buffer and a pixel-interleaved
+    // dataset.
     if( nXSize == nBufXSize && nYSize == nBufYSize &&
         nBandCount == nBands && nBands > 1 &&
         nBandSpaceBuf == eBufTypeSize &&
@@ -272,7 +294,9 @@ CPLErr MEMDataset::IRasterIO( GDALRWFlag eRWFlag,
         {
             if( panBandMap[iBandIndex] != iBandIndex + 1 )
                 break;
-            MEMRasterBand *poBand = (MEMRasterBand*) GetRasterBand(iBandIndex + 1);
+
+            MEMRasterBand *poBand = reinterpret_cast<MEMRasterBand *>(
+                GetRasterBand(iBandIndex + 1) );
             if( iBandIndex == 0 )
             {
                 eDT = poBand->GetRasterDataType();
@@ -280,7 +304,7 @@ CPLErr MEMDataset::IRasterIO( GDALRWFlag eRWFlag,
                 nPixelOffset = poBand->nPixelOffset;
                 nLineOffset = poBand->nLineOffset;
                 eDTSize = GDALGetDataTypeSize(eDT) / 8;
-                if( nPixelOffset != nBands * eDTSize )
+                if( nPixelOffset != static_cast<GSpacing>(nBands) * eDTSize )
                     break;
             }
             else if( poBand->GetRasterDataType() != eDT ||
@@ -298,42 +322,56 @@ CPLErr MEMDataset::IRasterIO( GDALRWFlag eRWFlag,
             {
                 for(int iLine=0;iLine<nYSize;iLine++)
                 {
-                    GDALCopyWords( pabyData + nLineOffset*(size_t)(iLine + nYOff) + nXOff*nPixelOffset,
-                                   eDT,
-                                   eDTSize,
-                                   ((GByte*)pData) + nLineSpaceBuf*(size_t)iLine,
-                                   eBufType,
-                                   eBufTypeSize,
-                                   nXSize * nBands);
+                    GDALCopyWords(
+                        pabyData +
+                        nLineOffset*static_cast<size_t>(iLine + nYOff) +
+                        nXOff*nPixelOffset,
+                        eDT,
+                        eDTSize,
+                        reinterpret_cast<GByte *>( pData ) +
+                        nLineSpaceBuf * static_cast<size_t>(iLine),
+                        eBufType,
+                        eBufTypeSize,
+                        nXSize * nBands );
                 }
             }
             else
             {
                 for(int iLine=0;iLine<nYSize;iLine++)
                 {
-                    GDALCopyWords( ((GByte*)pData) + nLineSpaceBuf*(size_t)iLine,
-                                   eBufType,
-                                   eBufTypeSize,
-                                   pabyData + nLineOffset*(size_t)(iLine + nYOff) + nXOff*nPixelOffset,
-                                   eDT,
-                                   eDTSize,
-                                   nXSize * nBands);
+                    GDALCopyWords(
+                        reinterpret_cast<GByte *>( pData ) +
+                        nLineSpaceBuf*(size_t)iLine,
+                        eBufType,
+                        eBufTypeSize,
+                        pabyData +
+                        nLineOffset * static_cast<size_t>(iLine + nYOff) +
+                        nXOff*nPixelOffset,
+                        eDT,
+                        eDTSize,
+                        nXSize * nBands);
                 }
             }
             return CE_None;
         }
     }
-    
-    GDALProgressFunc  pfnProgressGlobal = psExtraArg->pfnProgress;
-    void             *pProgressDataGlobal = psExtraArg->pProgressData;
+
+    if( nBufXSize != nXSize || nBufYSize != nYSize )
+        return GDALDataset::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                                   pData, nBufXSize, nBufYSize,
+                                   eBufType, nBandCount, panBandMap,
+                                   nPixelSpaceBuf, nLineSpaceBuf, nBandSpaceBuf,
+                                   psExtraArg );
+
+    GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
+    void *pProgressDataGlobal = psExtraArg->pProgressData;
 
     CPLErr eErr = CE_None;
-    for( int iBandIndex = 0; 
-         iBandIndex < nBandCount && eErr == CE_None; 
+    for( int iBandIndex = 0;
+         iBandIndex < nBandCount && eErr == CE_None;
          iBandIndex++ )
     {
         GDALRasterBand *poBand = GetRasterBand(panBandMap[iBandIndex]);
-        GByte *pabyBandData;
 
         if (poBand == NULL)
         {
@@ -341,23 +379,25 @@ CPLErr MEMDataset::IRasterIO( GDALRWFlag eRWFlag,
             break;
         }
 
-        pabyBandData = ((GByte *) pData) + iBandIndex * nBandSpaceBuf;
+        GByte *pabyBandData
+            = reinterpret_cast<GByte *>(pData) + iBandIndex * nBandSpaceBuf;
 
         psExtraArg->pfnProgress = GDALScaledProgress;
-        psExtraArg->pProgressData = 
+        psExtraArg->pProgressData =
             GDALCreateScaledProgress( 1.0 * iBandIndex / nBandCount,
                                       1.0 * (iBandIndex + 1) / nBandCount,
                                       pfnProgressGlobal,
                                       pProgressDataGlobal );
 
-        eErr = poBand->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, 
-                                  (void *) pabyBandData, nBufXSize, nBufYSize,
-                                  eBufType, nPixelSpaceBuf, nLineSpaceBuf,
-                                 psExtraArg);
+        eErr = poBand->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                                 reinterpret_cast<void *>( pabyBandData ),
+                                 nBufXSize, nBufYSize,
+                                 eBufType, nPixelSpaceBuf, nLineSpaceBuf,
+                                 psExtraArg );
 
         GDALDestroyScaledProgress( psExtraArg->pProgressData );
     }
-    
+
     psExtraArg->pfnProgress = pfnProgressGlobal;
     psExtraArg->pProgressData = pProgressDataGlobal;
 
@@ -375,8 +415,8 @@ double MEMRasterBand::GetNoDataValue( int *pbSuccess )
 
     if( bNoDataSet )
         return dfNoData;
-    else
-        return 0.0;
+
+    return 0.0;
 }
 
 /************************************************************************/
@@ -391,6 +431,18 @@ CPLErr MEMRasterBand::SetNoDataValue( double dfNewValue )
 }
 
 /************************************************************************/
+/*                         DeleteNoDataValue()                          */
+/************************************************************************/
+
+CPLErr MEMRasterBand::DeleteNoDataValue()
+{
+    dfNoData = 0.0;
+    bNoDataSet = FALSE;
+
+    return CE_None;
+}
+
+/************************************************************************/
 /*                       GetColorInterpretation()                       */
 /************************************************************************/
 
@@ -399,8 +451,8 @@ GDALColorInterp MEMRasterBand::GetColorInterpretation()
 {
     if( poColorTable != NULL )
         return GCI_PaletteIndex;
-    else
-        return eColorInterp;
+
+    return eColorInterp;
 }
 
 /************************************************************************/
@@ -452,8 +504,8 @@ const char *MEMRasterBand::GetUnitType()
 {
     if( pszUnitType == NULL )
         return "";
-    else
-        return pszUnitType;
+
+    return pszUnitType;
 }
 
 /************************************************************************/
@@ -464,7 +516,7 @@ CPLErr MEMRasterBand::SetUnitType( const char *pszNewValue )
 
 {
     CPLFree( pszUnitType );
-    
+
     if( pszNewValue == NULL )
         pszUnitType = NULL;
     else
@@ -548,18 +600,16 @@ CPLErr MEMRasterBand::SetCategoryNames( char ** papszNewNames )
 /*                        SetDefaultHistogram()                         */
 /************************************************************************/
 
-CPLErr MEMRasterBand::SetDefaultHistogram( double dfMin, double dfMax, 
+CPLErr MEMRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
                                            int nBuckets, GUIntBig *panHistogram)
 
 {
-    CPLXMLNode *psNode;
-
 /* -------------------------------------------------------------------- */
 /*      Do we have a matching histogram we should replace?              */
 /* -------------------------------------------------------------------- */
-    psNode = PamFindMatchingHistogram( psSavedHistograms, 
-                                       dfMin, dfMax, nBuckets,
-                                       TRUE, TRUE );
+    CPLXMLNode *psNode = PamFindMatchingHistogram( psSavedHistograms,
+                                                   dfMin, dfMax, nBuckets,
+                                                   TRUE, TRUE );
     if( psNode != NULL )
     {
         /* blow this one away */
@@ -570,10 +620,8 @@ CPLErr MEMRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
 /* -------------------------------------------------------------------- */
 /*      Translate into a histogram XML tree.                            */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psHistItem;
-
-    psHistItem = PamHistogramToXMLTree( dfMin, dfMax, nBuckets, 
-                                        panHistogram, TRUE, FALSE );
+    CPLXMLNode *psHistItem = PamHistogramToXMLTree( dfMin, dfMax, nBuckets,
+                                                    panHistogram, TRUE, FALSE );
     if( psHistItem == NULL )
         return CE_Failure;
 
@@ -585,48 +633,47 @@ CPLErr MEMRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
     if( psSavedHistograms == NULL )
         psSavedHistograms = CPLCreateXMLNode( NULL, CXT_Element,
                                               "Histograms" );
-            
+
     psHistItem->psNext = psSavedHistograms->psChild;
     psSavedHistograms->psChild = psHistItem;
-    
+
     return CE_None;
 }
+
 /************************************************************************/
 /*                        GetDefaultHistogram()                         */
 /************************************************************************/
 
-CPLErr 
-MEMRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax, 
-                                    int *pnBuckets, GUIntBig **ppanHistogram, 
+CPLErr
+MEMRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
+                                    int *pnBuckets, GUIntBig **ppanHistogram,
                                     int bForce,
-                                    GDALProgressFunc pfnProgress, 
+                                    GDALProgressFunc pfnProgress,
                                     void *pProgressData )
-    
+
 {
     if( psSavedHistograms != NULL )
     {
-        CPLXMLNode *psXMLHist;
-
-        for( psXMLHist = psSavedHistograms->psChild;
+        for( CPLXMLNode *psXMLHist = psSavedHistograms->psChild;
              psXMLHist != NULL; psXMLHist = psXMLHist->psNext )
         {
-            int bApprox, bIncludeOutOfRange;
-
             if( psXMLHist->eType != CXT_Element
                 || !EQUAL(psXMLHist->pszValue,"HistItem") )
                 continue;
 
-            if( PamParseHistogram( psXMLHist, pdfMin, pdfMax, pnBuckets, 
+            int bApprox = FALSE;
+            int bIncludeOutOfRange = FALSE;
+            if( PamParseHistogram( psXMLHist, pdfMin, pdfMax, pnBuckets,
                                    ppanHistogram, &bIncludeOutOfRange,
                                    &bApprox ) )
                 return CE_None;
-            else
-                return CE_Failure;
+
+            return CE_Failure;
         }
     }
 
-    return GDALRasterBand::GetDefaultHistogram( pdfMin, pdfMax, pnBuckets, 
-                                                ppanHistogram, bForce, 
+    return GDALRasterBand::GetDefaultHistogram( pdfMin, pdfMax, pnBuckets,
+                                                ppanHistogram, bForce,
                                                 pfnProgress,pProgressData);
 }
 
@@ -641,20 +688,19 @@ MEMRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
 /*                            MEMDataset()                             */
 /************************************************************************/
 
-MEMDataset::MEMDataset()
-
+MEMDataset::MEMDataset() :
+    GDALDataset(FALSE),
+    bGeoTransformSet(FALSE),
+    pszProjection(NULL),
+    nGCPCount(0),
+    pasGCPs(NULL)
 {
-    pszProjection = NULL;
-    bGeoTransformSet = FALSE;
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = -1.0;
-
-    nGCPCount = 0;
-    pasGCPs = NULL;
 }
 
 /************************************************************************/
@@ -671,6 +717,25 @@ MEMDataset::~MEMDataset()
     CPLFree( pasGCPs );
 }
 
+#if 0
+/************************************************************************/
+/*                          EnterReadWrite()                            */
+/************************************************************************/
+
+int MEMDataset::EnterReadWrite(CPL_UNUSED GDALRWFlag eRWFlag)
+{
+    return TRUE;
+}
+
+/************************************************************************/
+/*                         LeaveReadWrite()                             */
+/************************************************************************/
+
+void MEMDataset::LeaveReadWrite()
+{
+}
+#endif  // if 0
+
 /************************************************************************/
 /*                          GetProjectionRef()                          */
 /************************************************************************/
@@ -680,8 +745,8 @@ const char *MEMDataset::GetProjectionRef()
 {
     if( pszProjection == NULL )
         return "";
-    else
-        return pszProjection;
+
+    return pszProjection;
 }
 
 /************************************************************************/
@@ -707,8 +772,8 @@ CPLErr MEMDataset::GetGeoTransform( double *padfGeoTransform )
     memcpy( padfGeoTransform, adfGeoTransform, sizeof(double) * 6 );
     if( bGeoTransformSet )
         return CE_None;
-    else
-        return CE_Failure;
+
+    return CE_Failure;
 }
 
 /************************************************************************/
@@ -728,19 +793,19 @@ CPLErr MEMDataset::SetGeoTransform( double *padfGeoTransform )
 /*                          GetInternalHandle()                         */
 /************************************************************************/
 
-void *MEMDataset::GetInternalHandle( const char * pszRequest)
+void *MEMDataset::GetInternalHandle( const char * pszRequest )
 
 {
-    // check for MEMORYnnn string in pszRequest (nnnn can be up to 10 
+    // check for MEMORYnnn string in pszRequest (nnnn can be up to 10
     // digits, or even omitted)
-    if( EQUALN(pszRequest,"MEMORY",6))
+    if( STARTS_WITH_CI(pszRequest, "MEMORY"))
     {
-        if(int BandNumber = CPLScanLong(&pszRequest[6], 10))
+        if(int BandNumber = static_cast<int>(CPLScanLong(&pszRequest[6], 10)))
         {
-            MEMRasterBand *RequestedRasterBand = 
-                (MEMRasterBand *)GetRasterBand(BandNumber);
+            MEMRasterBand *RequestedRasterBand =
+                reinterpret_cast<MEMRasterBand *>( GetRasterBand(BandNumber) );
 
-            // we're within a MEMDataset so the only thing a RasterBand 
+            // we're within a MEMDataset so the only thing a RasterBand
             // could be is a MEMRasterBand
 
             if( RequestedRasterBand != NULL )
@@ -816,9 +881,8 @@ CPLErr MEMDataset::SetGCPs( int nNewCount, const GDAL_GCP *pasNewGCPList,
 CPLErr MEMDataset::AddBand( GDALDataType eType, char **papszOptions )
 
 {
-    int nBandId = GetRasterCount() + 1;
-    GByte *pData;
-    int   nPixelSize = (GDALGetDataTypeSize(eType) / 8);
+    const int nBandId = GetRasterCount() + 1;
+    const GSpacing nPixelSize = GDALGetDataTypeSizeBytes(eType);
 
 /* -------------------------------------------------------------------- */
 /*      Do we need to allocate the memory ourselves?  This is the       */
@@ -826,19 +890,23 @@ CPLErr MEMDataset::AddBand( GDALDataType eType, char **papszOptions )
 /* -------------------------------------------------------------------- */
     if( CSLFetchNameValue( papszOptions, "DATAPOINTER" ) == NULL )
     {
-
-        pData = (GByte *) 
-            VSICalloc(nPixelSize * GetRasterXSize(), GetRasterYSize() );
+        const GSpacing nTmp = nPixelSize * GetRasterXSize();
+        GByte *pData = NULL;
+#if SIZEOF_VOIDP == 4
+        if( nTmp > INT_MAX )
+            pData = NULL;
+        else
+#endif
+            pData = reinterpret_cast<GByte *>(
+                VSI_CALLOC_VERBOSE((size_t)nTmp, GetRasterYSize() ) );
 
         if( pData == NULL )
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory,
-                      "Unable to create band arrays ... out of memory." );
             return CE_Failure;
         }
 
         SetBand( nBandId,
-                 new MEMRasterBand( this, nBandId, pData, eType, nPixelSize, 
+                 new MEMRasterBand( this, nBandId, pData, eType, nPixelSize,
                                     nPixelSize * GetRasterXSize(), TRUE ) );
 
         return CE_None;
@@ -847,28 +915,27 @@ CPLErr MEMDataset::AddBand( GDALDataType eType, char **papszOptions )
 /* -------------------------------------------------------------------- */
 /*      Get layout of memory and other flags.                           */
 /* -------------------------------------------------------------------- */
-    const char *pszOption;
-    GSpacing nPixelOffset, nLineOffset;
-    const char *pszDataPointer;
-
-    pszDataPointer = CSLFetchNameValue(papszOptions,"DATAPOINTER");
-    pData = (GByte *) CPLScanPointer(pszDataPointer,
-                                     strlen(pszDataPointer));
-    
-    pszOption = CSLFetchNameValue(papszOptions,"PIXELOFFSET");
+    const char *pszDataPointer = CSLFetchNameValue(papszOptions, "DATAPOINTER");
+    GByte *pData = reinterpret_cast<GByte *>(
+        CPLScanPointer( pszDataPointer,
+                        static_cast<int>(strlen(pszDataPointer)) ) );
+
+    const char *pszOption = CSLFetchNameValue(papszOptions, "PIXELOFFSET");
+    GSpacing nPixelOffset;
     if( pszOption == NULL )
         nPixelOffset = nPixelSize;
     else
-        nPixelOffset = CPLScanUIntBig(pszOption, strlen(pszOption));
+        nPixelOffset = CPLAtoGIntBig(pszOption);
 
-    pszOption = CSLFetchNameValue(papszOptions,"LINEOFFSET");
+    pszOption = CSLFetchNameValue(papszOptions, "LINEOFFSET");
+    GSpacing nLineOffset;
     if( pszOption == NULL )
-        nLineOffset = GetRasterXSize() * (size_t)nPixelOffset;
+        nLineOffset = GetRasterXSize() * static_cast<size_t>( nPixelOffset );
     else
-        nLineOffset = CPLScanUIntBig(pszOption, strlen(pszOption));
+        nLineOffset = CPLAtoGIntBig(pszOption);
 
     SetBand( nBandId,
-             new MEMRasterBand( this, nBandId, pData, eType, 
+             new MEMRasterBand( this, nBandId, pData, eType,
                                 nPixelOffset, nLineOffset, FALSE ) );
 
     return CE_None;
@@ -881,18 +948,17 @@ CPLErr MEMDataset::AddBand( GDALDataType eType, char **papszOptions )
 GDALDataset *MEMDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    char    **papszOptions;
-
 /* -------------------------------------------------------------------- */
 /*      Do we have the special filename signature for MEM format        */
 /*      description strings?                                            */
 /* -------------------------------------------------------------------- */
-    if( !EQUALN(poOpenInfo->pszFilename,"MEM:::",6) 
+    if( !STARTS_WITH_CI(poOpenInfo->pszFilename, "MEM:::")
         || poOpenInfo->fpL != NULL )
         return NULL;
 
-    papszOptions = CSLTokenizeStringComplex(poOpenInfo->pszFilename+6, ",",
-                                            TRUE, FALSE );
+    char **papszOptions
+        = CSLTokenizeStringComplex(poOpenInfo->pszFilename+6, ",",
+                                   TRUE, FALSE );
 
 /* -------------------------------------------------------------------- */
 /*      Verify we have all required fields                              */
@@ -901,9 +967,10 @@ GDALDataset *MEMDataset::Open( GDALOpenInfo * poOpenInfo )
         || CSLFetchNameValue( papszOptions, "LINES" ) == NULL
         || CSLFetchNameValue( papszOptions, "DATAPOINTER" ) == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-              "Missing required field (one of PIXELS, LINES or DATAPOINTER)\n"
-              "Unable to access in-memory array." );
+        CPLError(
+            CE_Failure, CPLE_AppDefined,
+            "Missing required field (one of PIXELS, LINES or DATAPOINTER).  "
+            "Unable to access in-memory array." );
 
         CSLDestroy( papszOptions );
         return NULL;
@@ -912,9 +979,7 @@ GDALDataset *MEMDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create the new MEMDataset object.                               */
 /* -------------------------------------------------------------------- */
-    MEMDataset *poDS;
-
-    poDS = new MEMDataset();
+    MEMDataset *poDS = new MEMDataset();
 
     poDS->nRasterXSize = atoi(CSLFetchNameValue(papszOptions,"PIXELS"));
     poDS->nRasterYSize = atoi(CSLFetchNameValue(papszOptions,"LINES"));
@@ -923,22 +988,14 @@ GDALDataset *MEMDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Extract other information.                                      */
 /* -------------------------------------------------------------------- */
-    const char *pszOption;
-    GDALDataType eType;
-    int nBands;
-    GSpacing nPixelOffset, nLineOffset, nBandOffset;
-    const char *pszDataPointer;
-    GByte *pabyData;
-
-    pszOption = CSLFetchNameValue(papszOptions,"BANDS");
-    if( pszOption == NULL )
-        nBands = 1;
-    else
+    const char *pszOption = CSLFetchNameValue(papszOptions,"BANDS");
+    int nBands = 1;
+    if( pszOption != NULL )
     {
         nBands = atoi(pszOption);
     }
 
-    if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) ||
+    if( !GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) ||
         !GDALCheckBandCount(nBands, TRUE))
     {
         CSLDestroy( papszOptions );
@@ -947,31 +1004,28 @@ GDALDataset *MEMDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
     pszOption = CSLFetchNameValue(papszOptions,"DATATYPE");
-    if( pszOption == NULL )
-        eType = GDT_Byte;
-    else
+    GDALDataType eType = GDT_Byte;
+    if( pszOption != NULL )
     {
         if( atoi(pszOption) > 0 && atoi(pszOption) < GDT_TypeCount )
-            eType = (GDALDataType) atoi(pszOption);
+            eType = static_cast<GDALDataType>( atoi(pszOption) );
         else
         {
-            int iType;
-            
             eType = GDT_Unknown;
-            for( iType = 0; iType < GDT_TypeCount; iType++ )
+            for( int iType = 0; iType < GDT_TypeCount; iType++ )
             {
                 if( EQUAL(GDALGetDataTypeName((GDALDataType) iType),
                           pszOption) )
                 {
-                    eType = (GDALDataType) iType;
+                    eType = static_cast<GDALDataType>( iType );
                     break;
                 }
             }
-            
+
             if( eType == GDT_Unknown )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
-                          "DATATYPE=%s not recognised.", 
+                          "DATATYPE=%s not recognised.",
                           pszOption );
                 CSLDestroy( papszOptions );
                 delete poDS;
@@ -980,37 +1034,44 @@ GDALDataset *MEMDataset::Open( GDALOpenInfo * poOpenInfo )
         }
     }
 
-    pszOption = CSLFetchNameValue(papszOptions,"PIXELOFFSET");
+    pszOption = CSLFetchNameValue(papszOptions, "PIXELOFFSET");
+    GSpacing nPixelOffset;
     if( pszOption == NULL )
-        nPixelOffset = GDALGetDataTypeSize(eType) / 8;
+        nPixelOffset = GDALGetDataTypeSizeBytes(eType);
     else
-        nPixelOffset = CPLScanUIntBig(pszOption, strlen(pszOption));
+        nPixelOffset = CPLScanUIntBig(pszOption,
+                                      static_cast<int>(strlen(pszOption)));
 
-    pszOption = CSLFetchNameValue(papszOptions,"LINEOFFSET");
+    pszOption = CSLFetchNameValue(papszOptions, "LINEOFFSET");
+    GSpacing nLineOffset = 0;
     if( pszOption == NULL )
-        nLineOffset = poDS->nRasterXSize * (size_t) nPixelOffset;
+        nLineOffset = poDS->nRasterXSize * static_cast<size_t>( nPixelOffset );
     else
-        nLineOffset = CPLScanUIntBig(pszOption, strlen(pszOption));
+        nLineOffset = CPLScanUIntBig(pszOption,
+                                     static_cast<int>(strlen(pszOption)));
 
-    pszOption = CSLFetchNameValue(papszOptions,"BANDOFFSET");
+    pszOption = CSLFetchNameValue(papszOptions, "BANDOFFSET");
+    GSpacing nBandOffset = 0;
     if( pszOption == NULL )
-        nBandOffset = nLineOffset * (size_t) poDS->nRasterYSize;
+        nBandOffset = nLineOffset * static_cast<size_t>( poDS->nRasterYSize );
     else
-        nBandOffset = CPLScanUIntBig(pszOption, strlen(pszOption));
+        nBandOffset = CPLScanUIntBig(pszOption,
+                                     static_cast<int>(strlen(pszOption)));
 
-    pszDataPointer = CSLFetchNameValue(papszOptions,"DATAPOINTER");
-    pabyData = (GByte *) CPLScanPointer( pszDataPointer, 
-                                         strlen(pszDataPointer) );
+    const char *pszDataPointer = CSLFetchNameValue(papszOptions,"DATAPOINTER");
+    GByte *pabyData = reinterpret_cast<GByte *>(
+        CPLScanPointer( pszDataPointer,
+                        static_cast<int>(strlen(pszDataPointer)) ) );
 
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
     for( int iBand = 0; iBand < nBands; iBand++ )
     {
-        poDS->SetBand( iBand+1, 
-                       new MEMRasterBand( poDS, iBand+1, 
+        poDS->SetBand( iBand+1,
+                       new MEMRasterBand( poDS, iBand+1,
                                           pabyData + iBand * nBandOffset,
-                                          eType, nPixelOffset, nLineOffset, 
+                                          eType, nPixelOffset, nLineOffset,
                                           FALSE ) );
     }
 
@@ -1025,7 +1086,7 @@ GDALDataset *MEMDataset::Open( GDALOpenInfo * poOpenInfo )
 /*                               Create()                               */
 /************************************************************************/
 
-GDALDataset *MEMDataset::Create( CPL_UNUSED const char * pszFilename,
+GDALDataset *MEMDataset::Create( const char * /* pszFilename */,
                                  int nXSize,
                                  int nYSize,
                                  int nBands,
@@ -1035,28 +1096,32 @@ GDALDataset *MEMDataset::Create( CPL_UNUSED const char * pszFilename,
 
 /* -------------------------------------------------------------------- */
 /*      Do we want a pixel interleaved buffer?  I mostly care about     */
-/*      this to test pixel interleaved io in other contexts, but it     */
-/*      could be useful to create a directly accessable buffer for      */
+/*      this to test pixel interleaved IO in other contexts, but it     */
+/*      could be useful to create a directly accessible buffer for      */
 /*      some apps.                                                      */
 /* -------------------------------------------------------------------- */
-    int bPixelInterleaved = FALSE;
+    bool bPixelInterleaved = false;
     const char *pszOption = CSLFetchNameValue( papszOptions, "INTERLEAVE" );
     if( pszOption && EQUAL(pszOption,"PIXEL") )
-        bPixelInterleaved = TRUE;
-        
+        bPixelInterleaved = true;
+
 /* -------------------------------------------------------------------- */
 /*      First allocate band data, verifying that we can get enough      */
 /*      memory.                                                         */
 /* -------------------------------------------------------------------- */
-    std::vector<GByte*> apbyBandData;
-    int   	iBand;
-    int         nWordSize = GDALGetDataTypeSize(eType) / 8;
-    int         bAllocOK = TRUE;
+    const int nWordSize = GDALGetDataTypeSize(eType) / 8;
+    if( nBands > 0 && nWordSize > 0 && (nBands > INT_MAX / nWordSize ||
+        (GIntBig)nXSize * nYSize > GINTBIG_MAX / (nWordSize * nBands)) )
+    {
+        CPLError( CE_Failure, CPLE_OutOfMemory, "Multiplication overflow");
+        return NULL;
+    }
 
-    GUIntBig nGlobalBigSize = (GUIntBig)nWordSize * nBands * nXSize * nYSize;
-    size_t nGlobalSize = (size_t)nGlobalBigSize;
+    const GUIntBig nGlobalBigSize
+        = static_cast<GUIntBig>(nWordSize) * nBands * nXSize * nYSize;
+    const size_t nGlobalSize = static_cast<size_t>(nGlobalBigSize);
 #if SIZEOF_VOIDP == 4
-    if( (GUIntBig)nGlobalSize != nGlobalBigSize )
+    if( static_cast<GUIntBig>(nGlobalSize) != nGlobalBigSize )
     {
         CPLError( CE_Failure, CPLE_OutOfMemory,
                   "Cannot allocate " CPL_FRMT_GUIB " bytes on this platform.",
@@ -1065,25 +1130,31 @@ GDALDataset *MEMDataset::Create( CPL_UNUSED const char * pszFilename,
     }
 #endif
 
+    std::vector<GByte*> apbyBandData;
+    bool bAllocOK = true;
+
     if( bPixelInterleaved )
     {
-        apbyBandData.push_back( 
-            (GByte *) VSICalloc( 1, nGlobalSize ) );
+        apbyBandData.push_back(
+            reinterpret_cast<GByte *>( VSI_CALLOC_VERBOSE( 1, nGlobalSize ) ) );
 
         if( apbyBandData[0] == NULL )
             bAllocOK = FALSE;
         else
         {
-            for( iBand = 1; iBand < nBands; iBand++ )
+            for( int iBand = 1; iBand < nBands; iBand++ )
                 apbyBandData.push_back( apbyBandData[0] + iBand * nWordSize );
         }
     }
     else
     {
-        for( iBand = 0; iBand < nBands; iBand++ )
+        for( int iBand = 0; iBand < nBands; iBand++ )
         {
-            apbyBandData.push_back( 
-                (GByte *) VSICalloc( 1, ((size_t)nWordSize) * nXSize * nYSize ) );
+            apbyBandData.push_back(
+                reinterpret_cast<GByte *>(
+                    VSI_CALLOC_VERBOSE(
+                        1,
+                        static_cast<size_t>(nWordSize) * nXSize * nYSize ) ) );
             if( apbyBandData[iBand] == NULL )
             {
                 bAllocOK = FALSE;
@@ -1094,29 +1165,27 @@ GDALDataset *MEMDataset::Create( CPL_UNUSED const char * pszFilename,
 
     if( !bAllocOK )
     {
-        for( iBand = 0; iBand < (int) apbyBandData.size(); iBand++ )
+        for( int iBand = 0;
+             iBand < static_cast<int>( apbyBandData.size() );
+             iBand++ )
         {
             if( apbyBandData[iBand] )
                 VSIFree( apbyBandData[iBand] );
         }
-        CPLError( CE_Failure, CPLE_OutOfMemory,
-                    "Unable to create band arrays ... out of memory." );
         return NULL;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Create the new GTiffDataset object.                             */
 /* -------------------------------------------------------------------- */
-    MEMDataset *poDS;
-
-    poDS = new MEMDataset();
+    MEMDataset *poDS = new MEMDataset();
 
     poDS->nRasterXSize = nXSize;
     poDS->nRasterYSize = nYSize;
     poDS->eAccess = GA_Update;
 
     const char *pszPixelType = CSLFetchNameValue( papszOptions, "PIXELTYPE" );
-    if( pszPixelType && EQUAL(pszPixelType,"SIGNEDBYTE") )
+    if( pszPixelType && EQUAL(pszPixelType, "SIGNEDBYTE") )
         poDS->SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" );
 
     if( bPixelInterleaved )
@@ -1125,13 +1194,13 @@ GDALDataset *MEMDataset::Create( CPL_UNUSED const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    for( iBand = 0; iBand < nBands; iBand++ )
+    for( int iBand = 0; iBand < nBands; iBand++ )
     {
-        MEMRasterBand *poNewBand;
+        MEMRasterBand *poNewBand = NULL;
 
         if( bPixelInterleaved )
             poNewBand = new MEMRasterBand( poDS, iBand+1, apbyBandData[iBand],
-                                           eType, nWordSize * nBands, 0, 
+                                           eType, nWordSize * nBands, 0,
                                            iBand == 0 );
         else
             poNewBand = new MEMRasterBand( poDS, iBand+1, apbyBandData[iBand],
@@ -1152,7 +1221,7 @@ GDALDataset *MEMDataset::Create( CPL_UNUSED const char * pszFilename,
 
 static int MEMDatasetIdentify( GDALOpenInfo * poOpenInfo )
 {
-    return (strncmp(poOpenInfo->pszFilename, "MEM:::", 6) == 0 &&
+    return (STARTS_WITH(poOpenInfo->pszFilename, "MEM:::") &&
             poOpenInfo->fpL == NULL);
 }
 
@@ -1160,7 +1229,7 @@ static int MEMDatasetIdentify( GDALOpenInfo * poOpenInfo )
 /*                       MEMDatasetDelete()                             */
 /************************************************************************/
 
-static CPLErr MEMDatasetDelete(CPL_UNUSED const char* fileName)
+static CPLErr MEMDatasetDelete( const char* /* fileName */)
 {
     /* Null implementation, so that people can Delete("MEM:::") */
     return CE_None;
@@ -1173,20 +1242,19 @@ static CPLErr MEMDatasetDelete(CPL_UNUSED const char* fileName)
 void GDALRegister_MEM()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "MEM" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "MEM" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "MEM" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "In Memory Raster" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte Int16 UInt16 Int32 UInt32 Float32 Float64 CInt16 CInt32 CFloat32 CFloat64" );
-
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "MEM" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "In Memory Raster" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte Int16 UInt16 Int32 UInt32 Float32 Float64 "
+                               "CInt16 CInt32 CFloat32 CFloat64" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "   <Option name='INTERLEAVE' type='string-select' default='BAND'>"
 "       <Value>BAND</Value>"
@@ -1194,17 +1262,17 @@ void GDALRegister_MEM()
 "   </Option>"
 "</CreationOptionList>" );
 
-/* Define GDAL_NO_OPEN_FOR_MEM_DRIVER macro to undefine Open() method for MEM driver. */
-/* Otherwise, bad user input can trigger easily a GDAL crash as random pointers can be passed as a string. */
-/* All code in GDAL tree using the MEM driver use the Create() method only, so Open() */
-/* is not needed, except for esoteric uses */
+    // Define GDAL_NO_OPEN_FOR_MEM_DRIVER macro to undefine Open() method for
+    // MEM driver.  Otherwise, bad user input can trigger easily a GDAL crash
+    // as random pointers can be passed as a string.  All code in GDAL tree
+    // using the MEM driver use the Create() method only, so Open() is not
+    // needed, except for esoteric uses.
 #ifndef GDAL_NO_OPEN_FOR_MEM_DRIVER
-        poDriver->pfnOpen = MEMDataset::Open;
-        poDriver->pfnIdentify = MEMDatasetIdentify;
+    poDriver->pfnOpen = MEMDataset::Open;
+    poDriver->pfnIdentify = MEMDatasetIdentify;
 #endif
-        poDriver->pfnCreate = MEMDataset::Create;
-        poDriver->pfnDelete = MEMDatasetDelete;
+    poDriver->pfnCreate = MEMDataset::Create;
+    poDriver->pfnDelete = MEMDatasetDelete;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/mem/memdataset.h b/frmts/mem/memdataset.h
index 54b6301..d11e7a7 100644
--- a/frmts/mem/memdataset.h
+++ b/frmts/mem/memdataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: memdataset.h 28899 2015-04-14 09:27:00Z rouault $
+ * $Id: memdataset.h 33838 2016-03-31 20:42:32Z goatbar $
  *
  * Project:  Memory Array Translator
  * Purpose:  Declaration of MEMDataset, and MEMRasterBand.
@@ -34,15 +34,18 @@
 #include "gdal_priv.h"
 
 CPL_C_START
-void	GDALRegister_MEM(void);
+void GDALRegister_MEM();
 /* Caution: if changing this prototype, also change in swig/include/gdal_python.i
    where it is redefined */
 GDALRasterBandH CPL_DLL MEMCreateRasterBand( GDALDataset *, int, GByte *,
                                              GDALDataType, int, int, int );
+GDALRasterBandH CPL_DLL MEMCreateRasterBandEx( GDALDataset *, int, GByte *,
+                                               GDALDataType, GSpacing, GSpacing,
+                                               int );
 CPL_C_END
 
 /************************************************************************/
-/*				MEMDataset				*/
+/*                            MEMDataset                                */
 /************************************************************************/
 
 class MEMRasterBand;
@@ -50,7 +53,7 @@ class MEMRasterBand;
 class CPL_DLL MEMDataset : public GDALDataset
 {
     int         bGeoTransformSet;
-    double	adfGeoTransform[6];
+    double      adfGeoTransform[6];
 
     char        *pszProjection;
 
@@ -58,6 +61,12 @@ class CPL_DLL MEMDataset : public GDALDataset
     GDAL_GCP    *pasGCPs;
     CPLString    osGCPProjection;
 
+#if 0
+  protected:
+    virtual int                 EnterReadWrite(GDALRWFlag eRWFlag);
+    virtual void                LeaveReadWrite();
+#endif
+
   public:
                  MEMDataset();
     virtual      ~MEMDataset();
@@ -76,18 +85,18 @@ class CPL_DLL MEMDataset : public GDALDataset
     virtual CPLErr SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
                             const char *pszGCPProjection );
 
-    virtual CPLErr        AddBand( GDALDataType eType, 
+    virtual CPLErr        AddBand( GDALDataType eType,
                                    char **papszOptions=NULL );
     virtual CPLErr  IRasterIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
                                void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType, 
+                               GDALDataType eBufType,
                                int nBandCount, int *panBandMap,
                                GSpacing nPixelSpaceBuf,
                                GSpacing nLineSpaceBuf,
                                GSpacing nBandSpaceBuf,
                                GDALRasterIOExtraArg* psExtraArg);
-    
+
     static GDALDataset *Open( GDALOpenInfo * );
     static GDALDataset *Create( const char * pszFilename,
                                 int nXSize, int nYSize, int nBands,
@@ -116,17 +125,18 @@ class CPL_DLL MEMRasterBand : public GDALPamRasterBand
 
     char           *pszUnitType;
     char           **papszCategoryNames;
-    
+
     double         dfOffset;
     double         dfScale;
 
     CPLXMLNode    *psSavedHistograms;
-  public:
 
+  public:
                    MEMRasterBand( GDALDataset *poDS, int nBand,
                                   GByte *pabyData, GDALDataType eType,
                                   GSpacing nPixelOffset, GSpacing nLineOffset,
-                                  int bAssumeOwnership,  const char * pszPixelType = NULL);
+                                  int bAssumeOwnership,
+                                  const char * pszPixelType = NULL );
     virtual        ~MEMRasterBand();
 
     virtual CPLErr IReadBlock( int, int, void * );
@@ -140,15 +150,16 @@ class CPL_DLL MEMRasterBand : public GDALPamRasterBand
                                   GDALRasterIOExtraArg* psExtraArg );
     virtual double GetNoDataValue( int *pbSuccess = NULL );
     virtual CPLErr SetNoDataValue( double );
+    virtual CPLErr DeleteNoDataValue();
 
     virtual GDALColorInterp GetColorInterpretation();
     virtual GDALColorTable *GetColorTable();
-    virtual CPLErr SetColorTable( GDALColorTable * ); 
+    virtual CPLErr SetColorTable( GDALColorTable * );
 
     virtual CPLErr SetColorInterpretation( GDALColorInterp );
 
     virtual const char *GetUnitType();
-    CPLErr SetUnitType( const char * ); 
+    CPLErr SetUnitType( const char * );
 
     virtual char **GetCategoryNames();
     virtual CPLErr SetCategoryNames( char ** );
@@ -161,13 +172,13 @@ class CPL_DLL MEMRasterBand : public GDALPamRasterBand
     virtual CPLErr SetDefaultHistogram( double dfMin, double dfMax,
                                         int nBuckets, GUIntBig *panHistogram );
     virtual CPLErr GetDefaultHistogram( double *pdfMin, double *pdfMax,
-                                        int *pnBuckets, GUIntBig ** ppanHistogram,
+                                        int *pnBuckets,
+                                        GUIntBig ** ppanHistogram,
                                         int bForce,
                                         GDALProgressFunc, void *pProgressData);
 
-    // allow access to MEM driver's private internal memory buffer
-    GByte *GetData(void) const {return(pabyData);}
+    // Allow access to MEM driver's private internal memory buffer.
+    GByte *GetData(void) const { return(pabyData); }
 };
 
 #endif /* ndef MEMDATASET_H_INCLUDED */
-
diff --git a/frmts/mrf/GNUmakefile b/frmts/mrf/GNUmakefile
new file mode 100644
index 0000000..b0565d6
--- /dev/null
+++ b/frmts/mrf/GNUmakefile
@@ -0,0 +1,67 @@
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+# 
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+include ../../GDALmake.opt
+
+PLUGIN_PATH	=	$(prefix)/lib/gdalplugins/$(GDAL_VERSION_MAJOR).$(GDAL_VERSION_MINOR)
+FILES	=	marfa_dataset mrf_band JPEG_band PNG_band Raw_band Tif_band mrf_util mrf_overview
+OBJ 	=	$(addsuffix .o, $(FILES))
+LO_O_OBJ	=	$(addsuffix .lo,$(basename $(O_OBJ)))
+DEPENDS	= marfa.h
+
+# For GDAL < 2.1
+CPPFLAGS        :=      $(GDAL_INCLUDE) $(CPPFLAGS)
+
+# JPEG12_ENABLED is set only with the internal jpeg library
+ifeq ($(JPEG12_ENABLED),yes)
+FILES	:= $(FILES) JPEG12_band
+XTRA_OPT := $(XTRA_OPT) -DJPEG12_SUPPORTED
+endif
+
+ifeq ($(JPEG_SETTING),internal) 
+XTRA_OPT        :=      $(XTRA_OPT) -I../jpeg/libjpeg
+endif
+
+ifeq ($(PNG_SETTING),internal) 
+XTRA_OPT        :=      $(XTRA_OPT) -I../png/libpng -DINTERNAL_PNG
+endif
+
+ifeq ($(LIBZ_SETTING),internal) 
+XTRA_OPT        :=      $(XTRA_OPT) -I../zlib
+endif
+
+ifneq ("$(wildcard libLERC)","")
+LIBLERC	= libLERC
+OBJ	:=	$(OBJ) LERC_band.o
+XTRA_OPT	:=	$(XTRA_OPT) -DLERC -I $(LIBLERC)
+SUBLIBS := libLERC
+endif
+
+CPPFLAGS        :=      $(XTRA_OPT)  $(CPPFLAGS)
+
+default:	$(OBJ:.o=.$(OBJ_EXT)) $(SUBLIBS)
+
+clean:
+	rm -rf *.o *.lo .libs/$(OBJ) .libs $(O_OBJ) $(LO_O_OBJ) gdal_mrf.so.1
+	cd $(LIBLERC); $(MAKE) clean
+
+install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
+	cd $(LIBLERC); $(MAKE) install-obj
+
+$(OBJ) $(O_OBJ):    $(DEPENDS)
+
+plugin: $(OBJ)
+	g++ -shared -W1,-soname,gdal_mrf.so.1 $(OBJ) -o gdal_mrf.so.1
+
+iplugin: gdal_mrf.so.1 plugin
+	mkdir -p $(PLUGIN_PATH)
+	cp $< $(PLUGIN_PATH)/gdal_mrf.so
diff --git a/frmts/mrf/JPEG12_band.cpp b/frmts/mrf/JPEG12_band.cpp
new file mode 100644
index 0000000..29fc485
--- /dev/null
+++ b/frmts/mrf/JPEG12_band.cpp
@@ -0,0 +1,26 @@
+/*
+* Copyright 2015 Esri
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include "marfa.h"
+
+#if defined(LIBJPEG_12_H)
+// Including LIBJPEG_12_H preculdes libjpeg.h from being read again
+CPL_C_START
+#include LIBJPEG_12_H
+CPL_C_END
+#define  JPEG12_ON
+#include "JPEG_band.cpp"
+#endif
+
diff --git a/frmts/mrf/JPEG_band.cpp b/frmts/mrf/JPEG_band.cpp
new file mode 100644
index 0000000..5468afc
--- /dev/null
+++ b/frmts/mrf/JPEG_band.cpp
@@ -0,0 +1,371 @@
+/*
+* Copyright (c) 2002-2012, California Institute of Technology.
+* All rights reserved.  Based on Government Sponsored Research under contracts NAS7-1407 and/or NAS7-03001.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+*   1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+*   2. Redistributions in binary form must reproduce the above copyright notice,
+*      this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+*   3. Neither the name of the California Institute of Technology (Caltech), its operating division the Jet Propulsion Laboratory (JPL),
+*      the National Aeronautics and Space Administration (NASA), nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE CALIFORNIA INSTITUTE OF TECHNOLOGY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* Copyright 2014-2015 Esri
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+
+
+/*
+ * $Id$
+ * JPEG band
+ * JPEG page compression and decompression functions, gets compiled twice
+ * LIBJPEG_12_H is defined if both 8 and 12 bit JPEG will be supported
+ * JPEG12_ON    is defined for the 12 bit versions
+ */
+
+#include "marfa.h"
+#include <setjmp.h>
+
+CPL_C_START
+#include <jpeglib.h>
+CPL_C_END
+
+NAMESPACE_MRF_START
+
+typedef struct MRFJPEGErrorStruct
+{
+    jmp_buf     setjmpBuffer;
+
+    MRFJPEGErrorStruct()
+    {
+        memset(&setjmpBuffer, 0, sizeof(setjmpBuffer));
+    }
+} MRFJPEGErrorStruct;
+
+/**
+*\brief Called when jpeg wants to report a warning
+* msgLevel can be:
+* -1 Corrupt data
+* 0 always display
+* 1... Trace level
+*/
+
+static void emitMessage(j_common_ptr cinfo, int msgLevel)
+{
+    if (msgLevel > 0) return; // No trace msgs
+    // There can be many warnings, just print the first one
+    if (cinfo->err->num_warnings++ >1) return;
+    char buffer[JMSG_LENGTH_MAX];
+    cinfo->err->format_message(cinfo, buffer);
+    CPLError(CE_Failure, CPLE_AppDefined, "%s", buffer);
+}
+
+static void errorExit(j_common_ptr cinfo)
+{
+    MRFJPEGErrorStruct* psErrorStruct = (MRFJPEGErrorStruct* ) cinfo->client_data;
+    // format the warning message
+    char buffer[JMSG_LENGTH_MAX];
+
+    cinfo->err->format_message(cinfo, buffer);
+    CPLError(CE_Failure, CPLE_AppDefined, "%s", buffer);
+    // return control to the setjmp point
+    longjmp(psErrorStruct->setjmpBuffer, 1);
+}
+
+
+/**
+*\Brief Do nothing stub function for JPEG library, called
+*/
+static void stub_source_dec(j_decompress_ptr /*cinfo*/) {}
+
+/**
+*\Brief: This function is supposed to do refilling of the input buffer,
+* but as we provided everything at the beginning, if it is called, then
+* we have an error.
+*/
+static boolean fill_input_buffer_dec(j_decompress_ptr cinfo)
+{
+    if (0 != cinfo->src->bytes_in_buffer)
+	return TRUE;
+    CPLError(CE_Failure, CPLE_AppDefined, "Invalid JPEG stream");
+    return FALSE;
+}
+
+/**
+*\Brief: Do nothing stub function for JPEG library, not called
+*/
+static void skip_input_data_dec(j_decompress_ptr /*cinfo*/, long /*l*/) {};
+
+// Destination should be already set up
+static void init_or_terminate_destination(j_compress_ptr /*cinfo*/) {}
+
+// Called if the buffer provided is too small
+static boolean empty_output_buffer(j_compress_ptr /*cinfo*/) {
+    std::cerr << "JPEG Output buffer empty called\n";
+    return FALSE;
+}
+
+/*
+ *\Brief Compress a JPEG page
+ *
+ * For now it only handles byte data, grayscale, RGB or CMYK
+ *
+ * Returns the compressed size in dest.size
+ */
+#if defined(JPEG12_ON)
+CPLErr JPEG_Band::CompressJPEG12(buf_mgr &dst, buf_mgr &src)
+#else
+CPLErr JPEG_Band::CompressJPEG(buf_mgr &dst, buf_mgr &src)
+#endif
+
+{
+    // The cinfo should stay open and reside in the DS, since it can be left initialized
+    // It saves some time because it has the tables initialized
+    struct jpeg_compress_struct cinfo;
+    MRFJPEGErrorStruct sErrorStruct;
+    struct jpeg_error_mgr sJErr;
+
+    jpeg_destination_mgr jmgr;
+    jmgr.next_output_byte = (JOCTET *)dst.buffer;
+    jmgr.free_in_buffer = dst.size;
+    jmgr.init_destination = init_or_terminate_destination;
+    jmgr.empty_output_buffer = empty_output_buffer;
+    jmgr.term_destination = init_or_terminate_destination;
+
+    // Look at the source of this, some interesting tidbits
+    cinfo.err = jpeg_std_error( &sJErr );
+    sJErr.error_exit = errorExit;
+    sJErr.emit_message = emitMessage;
+    cinfo.client_data = (void *) &(sErrorStruct);
+    jpeg_create_compress(&cinfo);
+    cinfo.dest = &jmgr;
+
+    // The page specific info, size and color spaces
+    cinfo.image_width = img.pagesize.x;
+    cinfo.image_height = img.pagesize.y;
+    cinfo.input_components = img.pagesize.c;
+    switch (cinfo.input_components) {
+    case 1:cinfo.in_color_space = JCS_GRAYSCALE; break;
+    case 3:cinfo.in_color_space = JCS_RGB; break;  // Stored as YCbCr 4:2:0 by default
+    default:
+	cinfo.in_color_space = JCS_UNKNOWN; // 2, 4-10 bands
+    }
+
+    // Set all required fields and overwrite the ones we want to change
+    jpeg_set_defaults(&cinfo);
+
+    // Override certain settings
+    jpeg_set_quality(&cinfo, img.quality, TRUE);
+    cinfo.dct_method = JDCT_FLOAT; // Pretty fast and precise
+    cinfo.optimize_coding = optimize; // Set "OPTIMIZE=TRUE" in OPTIONS, default for 12bit
+
+    // Do we explicitly turn off the YCC color and downsampling?
+
+    if (cinfo.in_color_space == JCS_RGB) {
+	if (rgb) {  // Stored as RGB
+	    jpeg_set_colorspace(&cinfo, JCS_RGB);  // Huge files
+	} else if (sameres) { // YCC, somewhat larger files with improved color spatial detail
+	    cinfo.comp_info[0].h_samp_factor = 1;
+	    cinfo.comp_info[0].v_samp_factor = 1;
+
+	    // Enabling these lines will make the color components use the same tables as Y, even larger file with slightly better color depth detail
+	    // cinfo.comp_info[1].quant_tbl_no = 0;
+	    // cinfo.comp_info[2].quant_tbl_no = 0;
+
+	    // cinfo.comp_info[1].dc_tbl_no = 0;
+	    // cinfo.comp_info[2].dc_tbl_no = 0;
+
+	    // cinfo.comp_info[1].ac_tbl_no = 0;
+	    // cinfo.comp_info[2].ac_tbl_no = 0;
+	}
+    }
+
+    int linesize = cinfo.image_width*cinfo.num_components*((cinfo.data_precision == 8) ? 1 : 2);
+    JSAMPROW *rowp = (JSAMPROW *)CPLMalloc(sizeof(JSAMPROW)*img.pagesize.y);
+    for (int i = 0; i < img.pagesize.y; i++)
+	rowp[i] = (JSAMPROW)(src.buffer + i*linesize);
+
+    if (setjmp(sErrorStruct.setjmpBuffer)) {
+	CPLError(CE_Failure, CPLE_AppDefined, "MRF: JPEG compression error");
+	jpeg_destroy_compress(&cinfo);
+	CPLFree(rowp);
+	return CE_Failure;
+    }
+
+    jpeg_start_compress(&cinfo, TRUE);
+    jpeg_write_scanlines(&cinfo, rowp, img.pagesize.y);
+    jpeg_finish_compress(&cinfo);
+    jpeg_destroy_compress(&cinfo);
+
+    CPLFree(rowp);
+
+    // Figure out the size
+    dst.size -= jmgr.free_in_buffer;
+
+    return CE_None;
+}
+
+/**
+ *\brief In memory decompression of JPEG file
+ *
+ * @param data pointer to output buffer
+ * @param png pointer to PNG in memory
+ * @param sz if non-zero, test that uncompressed data fits in the buffer.
+ */
+#if defined(JPEG12_ON)
+CPLErr JPEG_Band::DecompressJPEG12(buf_mgr &dst, buf_mgr &isrc)
+#else
+CPLErr JPEG_Band::DecompressJPEG(buf_mgr &dst, buf_mgr &isrc)
+#endif
+
+{
+    int nbands = img.pagesize.c;
+    // Locals, clean up after themselves
+    jpeg_decompress_struct cinfo;
+    MRFJPEGErrorStruct sErrorStruct;
+    struct jpeg_error_mgr sJErr;
+
+    memset(&cinfo, 0, sizeof(cinfo));
+
+    struct jpeg_source_mgr src;
+
+    cinfo.err = jpeg_std_error( &sJErr );
+    sJErr.error_exit = errorExit;
+    sJErr.emit_message = emitMessage;
+    cinfo.client_data = (void *) &(sErrorStruct);
+
+    src.next_input_byte = (JOCTET *)isrc.buffer;
+    src.bytes_in_buffer = isrc.size;
+    src.term_source = src.init_source = stub_source_dec;
+    src.skip_input_data = skip_input_data_dec;
+    src.fill_input_buffer = fill_input_buffer_dec;
+    src.resync_to_restart = jpeg_resync_to_restart;
+
+    jpeg_create_decompress(&cinfo);
+
+    if (setjmp(sErrorStruct.setjmpBuffer)) {
+        CPLError(CE_Failure, CPLE_AppDefined, "MRF: Error reading JPEG page");
+        jpeg_destroy_decompress(&cinfo);
+        return CE_Failure;
+    }
+
+    cinfo.src = &src;
+    jpeg_read_header(&cinfo, TRUE);
+    // Use float, it is actually faster than the ISLOW method by a tiny bit
+    cinfo.dct_method = JDCT_FLOAT;
+
+    //
+    // Tolerate different input if we can do the conversion
+    // Gray and RGB for example
+    // This also means that a RGB MRF can be read as grayscale and vice versa
+    // If libJPEG can't convert it will throw an error
+    //
+    if (nbands == 3 && cinfo.num_components != nbands)
+	cinfo.out_color_space = JCS_RGB;
+    if (nbands == 1 && cinfo.num_components != nbands)
+	cinfo.out_color_space = JCS_GRAYSCALE;
+
+    int linesize = cinfo.image_width * nbands * ((cinfo.data_precision == 8) ? 1 : 2);
+
+    jpeg_start_decompress(&cinfo);
+
+    // We have a mismatch between the real and the declared data format
+    // warn and fail if output buffer is too small
+    if (linesize*cinfo.image_height!=dst.size) {
+        CPLError(CE_Warning,CPLE_AppDefined,"MRF: read JPEG size is wrong");
+        if (linesize*cinfo.image_height>dst.size) {
+            CPLError(CE_Failure,CPLE_AppDefined,"MRF: JPEG decompress buffer overflow");
+            jpeg_destroy_decompress(&cinfo);
+            return CE_Failure;
+        }
+    }
+    // Decompress, two lines at a time
+    while (cinfo.output_scanline < cinfo.image_height ) {
+        char *rp[2];
+        rp[0]=(char *)dst.buffer+linesize*cinfo.output_scanline;
+        rp[1]=rp[0]+linesize;
+        // if this fails, it calls the error handler
+        // which will report an error
+        jpeg_read_scanlines(&cinfo,JSAMPARRAY(rp),2);
+    }
+    jpeg_finish_decompress(&cinfo);
+    jpeg_destroy_decompress(&cinfo);
+    return CE_None;
+}
+
+// This part get done only once
+#if !defined(JPEG12_ON)
+
+// Type dependent dispachers
+CPLErr JPEG_Band::Decompress(buf_mgr &dst, buf_mgr &src)
+{
+#if defined(LIBJPEG_12_H)
+    if (GDT_Byte != img.dt)
+	return DecompressJPEG12(dst, src);
+#endif
+    return DecompressJPEG(dst, src);
+}
+
+CPLErr JPEG_Band::Compress(buf_mgr &dst, buf_mgr &src)
+{
+#if defined(LIBJPEG_12_H)
+    if (GDT_Byte != img.dt)
+	return CompressJPEG12(dst, src);
+#endif
+    return CompressJPEG(dst, src);
+}
+
+// PHOTOMETRIC == MULTISPECTRAL turns off YCbCr conversion and downsampling
+JPEG_Band::JPEG_Band(GDALMRFDataset *pDS, const ILImage &image, int b, int level) :
+GDALMRFRasterBand(pDS, image, b, int(level)), sameres(FALSE), rgb(FALSE), optimize(false)
+{
+    int nbands = image.pagesize.c;
+    //  TODO: Add 12bit JPEG support
+    // Check behavior on signed 16bit.  Does the libjpeg sign extend?
+#if defined(LIBJPEG_12_H)
+    if (GDT_Byte != image.dt && GDT_UInt16 != image.dt) {
+#else
+    if (GDT_Byte != image.dt) {
+#endif
+	CPLError(CE_Failure, CPLE_NotSupported, "Data type not supported by MRF JPEG");
+	return;
+    }
+
+    if (nbands == 3) { // Only the 3 band JPEG has storage flavors
+	CPLString const &pm = pDS->GetPhotometricInterpretation();
+	if (pm == "RGB" || pm == "MULTISPECTRAL") { // Explicit RGB or MS
+	    rgb = TRUE;
+	    sameres = TRUE;
+	}
+	if (pm == "YCC")
+	    sameres = TRUE;
+    }
+
+    if (GDT_Byte == image.dt)
+	optimize = GetOptlist().FetchBoolean("OPTIMIZE", FALSE) != FALSE;
+    else
+	optimize = true; // Required for 12bit
+}
+#endif
+
+NAMESPACE_MRF_END
diff --git a/frmts/mrf/LERC_band.cpp b/frmts/mrf/LERC_band.cpp
new file mode 100644
index 0000000..b886187
--- /dev/null
+++ b/frmts/mrf/LERC_band.cpp
@@ -0,0 +1,301 @@
+/*
+Copyright 2013-2015 Esri
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+A local copy of the license and additional notices are located with the
+source distribution at:
+http://github.com/Esri/lerc/
+
+LERC band implementation
+LERC page compression and decompression functions
+
+Contributors:  Lucian Plesea
+*/
+
+#include "marfa.h"
+#include <algorithm>
+#include <CntZImage.h>
+#include <Lerc2.h>
+
+USING_NAMESPACE_LERC
+
+NAMESPACE_MRF_START
+
+// Load a buffer into a zImg
+template <typename T> void CntZImgFill(CntZImage &zImg, T *src, const ILImage &img)
+{
+    int w = img.pagesize.x;
+    int h = img.pagesize.y;
+
+    zImg.resize(w, h);
+    T *ptr = src;
+
+    // No data value
+    float ndv = float(img.NoDataValue);
+    if (!img.hasNoData) ndv = 0;
+
+    for (int i = 0; i < h; i++)
+	for (int j = 0; j < w; j++) {
+	    zImg(i, j).z = float(*ptr++);
+	    zImg(i, j).cnt = !CPLIsEqual(zImg(i, j).z, ndv);
+	}
+    return;
+}
+
+// Unload a zImg into a buffer
+template <typename T> void CntZImgUFill(CntZImage &zImg, T *dst, const ILImage &img)
+{
+    int h = static_cast<int>(zImg.getHeight());
+    int w = static_cast<int>(zImg.getWidth());
+    T *ptr = dst;
+    T ndv = (T)(img.NoDataValue);
+    // Use 0 if nodata is not defined
+    if (!img.hasNoData) ndv = 0;
+    for (int i = 0; i < h; i++)
+	for (int j = 0; j < w; j++)
+	    *ptr++ = (zImg(i, j).cnt == 0) ? ndv : (T)(zImg(i, j).z);
+}
+
+//  LERC 1 compression
+static CPLErr CompressLERC(buf_mgr &dst, buf_mgr &src, const ILImage &img, double precision)
+{
+    CntZImage zImg;
+    // Fill data into zImg
+#define FILL(T) CntZImgFill(zImg, (T *)(src.buffer), img)
+    switch (img.dt) {
+    case GDT_Byte:	FILL(GByte);	break;
+    case GDT_UInt16:	FILL(GUInt16);	break;
+    case GDT_Int16:	FILL(GInt16);	break;
+    case GDT_Int32:	FILL(GInt32);	break;
+    case GDT_UInt32:	FILL(GUInt32);	break;
+    case GDT_Float32:	FILL(float);	break;
+    case GDT_Float64:	FILL(double);	break;
+    default: break;
+    }
+#undef FILL
+
+    Byte *ptr = (Byte *)dst.buffer;
+
+    // if it can't compress in output buffer it will crash
+    if (!zImg.write(&ptr, precision)) {
+	CPLError(CE_Failure,CPLE_AppDefined,"MRF: Error during LERC compression");
+	return CE_Failure;
+    }
+
+    // write changes the value of the pointer, we can find the size by testing how far it moved
+    dst.size = ptr - (Byte *)dst.buffer;
+    CPLDebug("MRF_LERC","LERC Compressed to %d\n", (int)dst.size);
+    return CE_None;
+}
+
+static CPLErr DecompressLERC(buf_mgr &dst, buf_mgr &src, const ILImage &img)
+{
+    CntZImage zImg;
+    Byte *ptr = (Byte *)src.buffer;
+    if (!zImg.read(&ptr, 1e12))
+    {
+	CPLError(CE_Failure,CPLE_AppDefined,"MRF: Error during LERC decompression");
+	return CE_Failure;
+    }
+
+// Unpack from zImg to dst buffer, calling the right type
+#define UFILL(T) CntZImgUFill(zImg, (T *)(dst.buffer), img)
+    switch (img.dt) {
+    case GDT_Byte:	UFILL(GByte);	break;
+    case GDT_UInt16:	UFILL(GUInt16); break;
+    case GDT_Int16:	UFILL(GInt16);	break;
+    case GDT_Int32:	UFILL(GInt32);	break;
+    case GDT_UInt32:	UFILL(GUInt32); break;
+    case GDT_Float32:	UFILL(float);	break;
+    case GDT_Float64:	UFILL(double);	break;
+    default: break;
+    }
+#undef UFILL
+
+    return CE_None;
+}
+
+// Populate a bitmask based on comparison with the image no data value
+// Returns the number of NoData values found
+template <typename T> int MaskFill(BitMask2 &bitMask, T *src, const ILImage &img)
+{
+    int w = img.pagesize.x;
+    int h = img.pagesize.y;
+    int count = 0;
+
+    bitMask.SetSize(w, h);
+    bitMask.SetAllValid();
+    T *ptr = src;
+
+    // No data value
+    T ndv = T(img.NoDataValue);
+    if (!img.hasNoData) ndv = 0; // It really doesn't get called when img doesn't have NoDataValue
+
+    for (int i = 0; i < h; i++)
+	for (int j = 0; j < w; j++)
+	    if (ndv == *ptr++) {
+		bitMask.SetInvalid(i, j);
+		count++;
+	    }
+
+    return count;
+}
+
+static CPLErr CompressLERC2(buf_mgr &dst, buf_mgr &src, const ILImage &img, double precision)
+{
+    int w = img.pagesize.x;
+    int h = img.pagesize.y;
+    // So we build a bitmask to pass a pointer to bytes, which gets converted to a bitmask?
+    BitMask2 bitMask;
+    int ndv_count = 0;
+    if (img.hasNoData) { // Only build a bitmask if no data value is defined
+	switch (img.dt) {
+
+#define MASK(T) ndv_count = MaskFill(bitMask, (T *)(src.buffer), img)
+
+	case GDT_Byte:		MASK(GByte);	break;
+	case GDT_UInt16:	MASK(GUInt16);	break;
+	case GDT_Int16:		MASK(GInt16);	break;
+	case GDT_Int32:		MASK(GInt32);	break;
+	case GDT_UInt32:	MASK(GUInt32);	break;
+	case GDT_Float32:	MASK(float);	break;
+	case GDT_Float64:	MASK(double);	break;
+        default:                CPLAssert(FALSE); break;
+
+#undef MASK
+	}
+    }
+    // Set bitmask if it has some ndvs
+    Lerc2 lerc2(w, h, (ndv_count == 0) ? NULL : bitMask.Bits());
+    bool success = false;
+    Byte *ptr = (Byte *)dst.buffer;
+
+    long sz = 0;
+    switch (img.dt) {
+
+#define ENCODE(T) if (true) { \
+    sz = lerc2.ComputeNumBytesNeededToWrite((T *)(src.buffer), precision, ndv_count != 0);\
+    success = lerc2.Encode((T *)(src.buffer), &ptr);\
+    }
+
+    case GDT_Byte:	ENCODE(GByte);	    break;
+    case GDT_UInt16:	ENCODE(GUInt16);    break;
+    case GDT_Int16:	ENCODE(GInt16);	    break;
+    case GDT_Int32:	ENCODE(GInt32);	    break;
+    case GDT_UInt32:	ENCODE(GUInt32);    break;
+    case GDT_Float32:	ENCODE(float);	    break;
+    case GDT_Float64:	ENCODE(double);	    break;
+    default:            CPLAssert(FALSE); break;
+
+#undef ENCODE
+    }
+
+    // write changes the value of the pointer, we can find the size by testing how far it moved
+    dst.size = (char *)ptr - dst.buffer;
+    if (!success || sz != static_cast<long>(dst.size)) {
+	CPLError(CE_Failure, CPLE_AppDefined, "MRF: Error during LERC2 compression");
+	return CE_Failure;
+    }
+    CPLDebug("MRF_LERC", "LERC2 Compressed to %d\n", (int)sz);
+    return CE_None;
+}
+
+// Populate a bitmask based on comparison with the image no data value
+template <typename T> void UnMask(BitMask2 &bitMask, T *arr, const ILImage &img)
+{
+    int w = img.pagesize.x;
+    int h = img.pagesize.y;
+    if (w * h == bitMask.CountValidBits())
+	return;
+    T *ptr = arr;
+    T ndv = T(img.NoDataValue);
+    if (!img.hasNoData) ndv = 0; // It doesn't get called when img doesn't have NoDataValue
+    for (int i = 0; i < h; i++)
+	for (int j = 0; j < w; j++, ptr++)
+	    if (!bitMask.IsValid(i, j))
+		*ptr = ndv;
+    return;
+}
+
+CPLErr LERC_Band::Decompress(buf_mgr &dst, buf_mgr &src)
+{
+    const Byte *ptr = (Byte *)(src.buffer);
+    Lerc2::HeaderInfo hdInfo;
+    Lerc2 lerc2;
+    if (!lerc2.GetHeaderInfo(ptr, hdInfo))
+	return DecompressLERC(dst, src, img);
+    // It is lerc2 here
+    bool success = false;
+    BitMask2 bitMask(img.pagesize.x, img.pagesize.y);
+    switch (img.dt) {
+#define DECODE(T) success = lerc2.Decode(&ptr, reinterpret_cast<T *>(dst.buffer), bitMask.Bits())
+    case GDT_Byte:	DECODE(GByte);	    break;
+    case GDT_UInt16:	DECODE(GUInt16);    break;
+    case GDT_Int16:	DECODE(GInt16);	    break;
+    case GDT_Int32:	DECODE(GInt32);	    break;
+    case GDT_UInt32:	DECODE(GUInt32);    break;
+    case GDT_Float32:	DECODE(float);	    break;
+    case GDT_Float64:	DECODE(double);	    break;
+    default:            CPLAssert(FALSE);   break;
+#undef DECODE
+    }
+    if (!success) {
+	CPLError(CE_Failure, CPLE_AppDefined, "MRF: Error during LERC2 decompression");
+	return CE_Failure;
+    }
+    if (!img.hasNoData)
+	return CE_None;
+
+    // Fill in no data values
+    switch (img.dt) {
+#define UNMASK(T) UnMask(bitMask, reinterpret_cast<T *>(dst.buffer), img)
+    case GDT_Byte:	UNMASK(GByte);	    break;
+    case GDT_UInt16:	UNMASK(GUInt16);    break;
+    case GDT_Int16:	UNMASK(GInt16);	    break;
+    case GDT_Int32:	UNMASK(GInt32);	    break;
+    case GDT_UInt32:	UNMASK(GUInt32);    break;
+    case GDT_Float32:	UNMASK(float);	    break;
+    case GDT_Float64:	UNMASK(double);	    break;
+    default:            CPLAssert(FALSE);   break;
+#undef DECODE
+    }
+    return CE_None;
+}
+
+CPLErr LERC_Band::Compress(buf_mgr &dst, buf_mgr &src)
+{
+    if (version == 2)
+	return CompressLERC2(dst, src, img, precision);
+    else
+	return CompressLERC(dst, src, img, precision);
+}
+
+LERC_Band::LERC_Band(GDALMRFDataset *pDS, const ILImage &image, int b, int level):
+    GDALMRFRasterBand(pDS, image, b, level)
+{
+    // Pick 1/1000 for floats and 0.5 losless for integers
+    if (eDataType == GDT_Float32 || eDataType == GDT_Float64 )
+	precision = strtod(GetOptionValue( "LERC_PREC" , ".001" ),NULL);
+    else
+	precision = std::max(0.5, strtod(GetOptionValue("LERC_PREC", ".5"), NULL));
+
+    // Encode in V2 by default
+    version = GetOptlist().FetchBoolean("V1", FALSE) ? 1:2;
+
+    // Enlarge the page buffer in this case, LERC may expand data
+    pDS->SetPBufferSize( 2 * image.pageSizeBytes);
+}
+
+LERC_Band::~LERC_Band()
+{
+}
+
+
+NAMESPACE_MRF_END
diff --git a/frmts/mrf/PNG_band.cpp b/frmts/mrf/PNG_band.cpp
new file mode 100644
index 0000000..b9fd707
--- /dev/null
+++ b/frmts/mrf/PNG_band.cpp
@@ -0,0 +1,372 @@
+/*
+* Copyright (c) 2002-2012, California Institute of Technology.
+* All rights reserved.  Based on Government Sponsored Research under contracts NAS7-1407 and/or NAS7-03001.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+*   1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+*   2. Redistributions in binary form must reproduce the above copyright notice,
+*      this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+*   3. Neither the name of the California Institute of Technology (Caltech), its operating division the Jet Propulsion Laboratory (JPL),
+*      the National Aeronautics and Space Administration (NASA), nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE CALIFORNIA INSTITUTE OF TECHNOLOGY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* Copyright 2014-2015 Esri
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+
+
+/*
+ * $Id$
+ * PNG band
+ * PNG page compression and decompression functions
+ * These functions are not methods, they reside in the global space
+ *
+ */
+
+#include "marfa.h"
+#include <cassert>
+
+CPL_C_START
+#ifdef INTERNAL_PNG
+#include "../png/libpng/png.h"
+#else
+#include <png.h>
+#endif
+CPL_C_END
+
+NAMESPACE_MRF_START
+
+// Do Nothing
+static void flush_png(png_structp) {}
+
+// Warning Emit
+static void pngWH(png_struct * /*png*/, png_const_charp message)
+{
+    CPLError(CE_Warning, CPLE_AppDefined, "MRF: PNG warning %s", message);
+}
+
+// Fatal Warning
+static void pngEH(png_struct *png, png_const_charp message)
+{
+    CPLError(CE_Failure, CPLE_AppDefined, "MRF: PNG Failure %s", message);
+    longjmp(png_jmpbuf(png), 1);
+}
+
+// Read memory handlers for PNG
+// No check for attempting to read past the end of the buffer
+
+static void read_png(png_structp pngp, png_bytep data, png_size_t length)
+{
+    buf_mgr *pmgr = (buf_mgr *)png_get_io_ptr(pngp);
+    if( pmgr->size < length )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "MRF: PNG Failure: Not enough bytes in buffer");
+        longjmp(png_jmpbuf(pngp), 1);
+    }
+    memcpy(data, pmgr->buffer, length);
+    pmgr->buffer += length;
+    pmgr->size -= length;
+}
+
+static void write_png(png_structp pngp, png_bytep data, png_size_t length) {
+    buf_mgr *mgr = (buf_mgr *)png_get_io_ptr(pngp);
+    // Buffer could be too small, trigger an error on debug mode
+    assert(length <= mgr->size);
+    memcpy(mgr->buffer, data, length);
+    mgr->buffer += length;
+    mgr->size -= length;
+}
+
+/**
+ *\brief In memory decompression of PNG file
+ */
+
+CPLErr PNG_Band::DecompressPNG(buf_mgr &dst, buf_mgr &src)
+{
+    png_bytep* png_rowp = NULL;
+    volatile png_bytep *p_volatile_png_rowp = (volatile png_bytep *) &png_rowp;
+
+    // pngp=png_create_read_struct(PNG_LIBPNG_VER_STRING,0,pngEH,pngWH);
+    png_structp pngp = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+    if (NULL == pngp) {
+	CPLError(CE_Failure, CPLE_AppDefined, "MRF: Error creating PNG decompress");
+	return CE_Failure;
+    }
+
+    png_infop infop = png_create_info_struct(pngp);
+    if (NULL == infop) {
+	if (pngp) png_destroy_read_struct(&pngp, &infop, NULL);
+	CPLError(CE_Failure, CPLE_AppDefined, "MRF: Error creating PNG info");
+	return CE_Failure;
+    }
+
+    if (setjmp(png_jmpbuf(pngp))) {
+	CPLError(CE_Failure, CPLE_AppDefined, "MRF: Error during PNG decompress");
+	CPLFree((void*)(*p_volatile_png_rowp));
+	png_destroy_read_struct(&pngp, &infop, NULL);
+	return CE_Failure;
+    }
+
+    // The mgr data ptr is already set up
+    png_set_read_fn(pngp, &src, read_png);
+    // Ready to read
+    png_read_info(pngp, infop);
+    GInt32 height = static_cast<GInt32>(png_get_image_height(pngp, infop));
+    GInt32 byte_count = png_get_bit_depth(pngp, infop) / 8;
+    // Check the size
+    if (dst.size < (png_get_rowbytes(pngp, infop)*height)) {
+	CPLError(CE_Failure, CPLE_AppDefined,
+	    "MRF: PNG Page data bigger than the buffer provided");
+	png_destroy_read_struct(&pngp, &infop, NULL);
+	return CE_Failure;
+    }
+
+    png_rowp = (png_bytep *)CPLMalloc(sizeof(png_bytep)*height);
+
+    int rowbytes = static_cast<int>(png_get_rowbytes(pngp, infop));
+    for (int i = 0; i < height; i++)
+	png_rowp[i] = (png_bytep)dst.buffer + i*rowbytes;
+
+    // Finally, the read
+    // This is the lower level, the png_read_end allows some transforms
+    // Like palette to RGBA
+    png_read_image(pngp, png_rowp);
+
+    if (byte_count != 1) { // Swap from net order if data is short
+	for (int i = 0; i < height; i++) {
+	    unsigned short int*p = (unsigned short int *)png_rowp[i];
+	    for (int j = 0; j < rowbytes / 2; j++, p++)
+		*p = net16(*p);
+	}
+    }
+
+    //    ppmWrite("Test.ppm",(char *)data,ILSize(512,512,1,4,0));
+    // Required
+    png_read_end(pngp, infop);
+
+    // png_set_rows(pngp,infop,png_rowp);
+    // png_read_png(pngp,infop,PNG_TRANSFORM_IDENTITY,0);
+
+    CPLFree(png_rowp);
+    png_destroy_read_struct(&pngp, &infop, NULL);
+    return CE_None;
+}
+
+/**
+ *\Brief Compress a page in PNG format
+ * Returns the compressed size in dst.size
+ *
+ */
+
+CPLErr PNG_Band::CompressPNG(buf_mgr &dst, buf_mgr &src)
+
+{
+    png_structp pngp;
+    png_infop infop;
+    buf_mgr mgr = dst;
+
+    pngp = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, pngEH, pngWH);
+    if (!pngp) {
+	CPLError(CE_Failure, CPLE_AppDefined, "MRF: Error creating png structure");
+	return CE_Failure;
+    }
+    infop = png_create_info_struct(pngp);
+    if (!infop) {
+	png_destroy_write_struct(&pngp, NULL);
+	CPLError(CE_Failure, CPLE_AppDefined, "MRF: Error creating png info structure");
+	return CE_Failure;
+    }
+
+    if (setjmp(png_jmpbuf(pngp))) {
+	png_destroy_write_struct(&pngp, &infop);
+	CPLError(CE_Failure, CPLE_AppDefined, "MRF: Error during png init");
+	return CE_Failure;
+    }
+
+    png_set_write_fn(pngp, &mgr, write_png, flush_png);
+
+    int png_ctype;
+
+    switch (img.pagesize.c) {
+    case 1: if (PNGColors != NULL) png_ctype = PNG_COLOR_TYPE_PALETTE;
+	    else png_ctype = PNG_COLOR_TYPE_GRAY;
+	    break;
+    case 2: png_ctype = PNG_COLOR_TYPE_GRAY_ALPHA; break;
+    case 3: png_ctype = PNG_COLOR_TYPE_RGB; break;
+    case 4: png_ctype = PNG_COLOR_TYPE_RGB_ALPHA; break;
+    default: { // This never happens if we check at the open
+	CPLError(CE_Failure, CPLE_AppDefined, "MRF:PNG Write with %d colors called",
+	    img.pagesize.c);
+	return CE_Failure;
+    }
+    }
+
+    png_set_IHDR(pngp, infop, img.pagesize.x, img.pagesize.y,
+	GDALGetDataTypeSize(img.dt), png_ctype,
+	PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+    // Optional, force certain filters only.  Makes it somewhat faster but worse compression
+    // png_set_filter(pngp, PNG_FILTER_TYPE_BASE, PNG_FILTER_SUB);
+
+#if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER > 10200) && defined(PNG_SELECT_READ)
+    png_uint_32 mask, flags;
+
+    flags = png_get_asm_flags(pngp);
+    mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE);
+    png_set_asm_flags(pngp, flags | mask); // use flags &~mask to disable all
+
+    // Test that the MMX is compiled into PNG
+    //	fprintf(stderr,"MMX support is %d\n", png_mmx_support());
+
+#endif
+
+    // Let the quality control the compression level
+    // Supposedly low numbers work well too while being fast
+    png_set_compression_level(pngp, img.quality / 10);
+
+    // Custom strategy for zlib, set using the band option Z_STRATEGY
+    if (deflate_flags & ZFLAG_SMASK)
+	png_set_compression_strategy(pngp, (deflate_flags & ZFLAG_SMASK) >> 6);
+
+    // Write the palette and the transparencies if they exist
+    if (PNGColors != NULL)
+    {
+	png_set_PLTE(pngp, infop, (png_colorp)PNGColors, PalSize);
+	if (TransSize != 0)
+	    png_set_tRNS(pngp, infop, (unsigned char*)PNGAlpha, TransSize, NULL);
+    }
+
+    png_write_info(pngp, infop);
+
+    png_bytep *png_rowp = (png_bytep *)CPLMalloc(sizeof(png_bytep)*img.pagesize.y);
+
+    if (setjmp(png_jmpbuf(pngp))) {
+	CPLFree(png_rowp);
+	png_destroy_write_struct(&pngp, &infop);
+	CPLError(CE_Failure, CPLE_AppDefined, "MRF: Error during png compression");
+	return CE_Failure;
+    }
+
+    int rowbytes = static_cast<int>(png_get_rowbytes(pngp, infop));
+    for (int i = 0; i < img.pagesize.y; i++) {
+	png_rowp[i] = (png_bytep)(src.buffer + i*rowbytes);
+	if (img.dt != GDT_Byte) { // Swap to net order if data is short
+	    unsigned short int*p = (unsigned short int *)png_rowp[i];
+	    for (int j = 0; j < rowbytes / 2; j++, p++) *p = net16(*p);
+	}
+    }
+
+    png_write_image(pngp, png_rowp);
+    png_write_end(pngp, infop);
+
+    // Done
+    CPLFree(png_rowp);
+    png_destroy_write_struct(&pngp, &infop);
+
+    // Done
+    // mgr.size holds the available bytes, so the size of the compressed png
+    // is the original destination size minus the still available bytes
+    dst.size -= mgr.size;
+
+    return CE_None;
+}
+
+CPLErr PNG_Band::Decompress(buf_mgr &dst, buf_mgr &src)
+{
+    return DecompressPNG(dst, src);
+}
+
+// The PNG internal palette is set on first band write
+CPLErr PNG_Band::Compress(buf_mgr &dst, buf_mgr &src)
+{   // Late set palette
+    if (img.comp == IL_PPNG && !PNGColors && ResetPalette() != CE_None)
+	return CE_Failure;
+    return CompressPNG(dst, src);
+}
+
+
+CPLErr PNG_Band::ResetPalette()
+{   // Convert the GDAL LUT to PNG style
+    GDALColorTable *poCT = GetColorTable();
+
+    if (!poCT) {
+	CPLError(CE_Failure, CPLE_NotSupported, "MRF PPNG needs a color table");
+	return CE_Failure;
+    }
+
+    TransSize = PalSize = poCT->GetColorEntryCount();
+
+    png_color *pasPNGColors = (png_color *)CPLMalloc(sizeof(png_color) * PalSize);
+    unsigned char *pabyAlpha = (unsigned char *)CPLMalloc(TransSize);
+    PNGColors = (void *)pasPNGColors;
+    PNGAlpha = (void *)pabyAlpha;
+    bool NoTranspYet = true;
+
+    // Set the palette from the end to reduce the size of the opacity mask
+    for (int iColor = PalSize - 1; iColor >= 0; iColor--)
+    {
+	GDALColorEntry  sEntry;
+	poCT->GetColorEntryAsRGB(iColor, &sEntry);
+
+	pasPNGColors[iColor].red = (png_byte)sEntry.c1;
+	pasPNGColors[iColor].green = (png_byte)sEntry.c2;
+	pasPNGColors[iColor].blue = (png_byte)sEntry.c3;
+	if (NoTranspYet && sEntry.c4 == 255)
+	    TransSize--;
+	else {
+	    NoTranspYet = false;
+	    pabyAlpha[iColor] = (unsigned char)sEntry.c4;
+	}
+    }
+
+    return CE_None;
+}
+
+/**
+ * \Brief For PPNG, builds the data structures needed to write the palette
+ * The presence of the PNGColors and PNGAlpha is used as a flag for PPNG only
+ */
+
+PNG_Band::PNG_Band(GDALMRFDataset *pDS, const ILImage &image, int b, int level) :
+GDALMRFRasterBand(pDS, image, b, level), PNGColors(NULL), PNGAlpha(NULL), PalSize(0), TransSize(0)
+
+{   // Check error conditions
+    if (image.dt != GDT_Byte && image.dt != GDT_Int16 && image.dt != GDT_UInt16) {
+	CPLError(CE_Failure, CPLE_NotSupported, "Data type not supported by MRF PNG");
+	return;
+    }
+    if (image.pagesize.c > 4) {
+	CPLError(CE_Failure, CPLE_NotSupported, "MRF PNG can only handle up to 4 bands per page");
+	return;
+    }
+    // PNGs can be larger than the source, especially for small page size
+    poDS->SetPBufferSize( image.pageSizeBytes + 100);
+}
+
+PNG_Band::~PNG_Band() {
+    CPLFree(PNGColors);
+    CPLFree(PNGAlpha);
+}
+
+NAMESPACE_MRF_END
diff --git a/frmts/mrf/README b/frmts/mrf/README
new file mode 100644
index 0000000..74c86e2
--- /dev/null
+++ b/frmts/mrf/README
@@ -0,0 +1,94 @@
+Introduction
+
+This software is designed for encoding image data into Tiled WMS format, known as Meta Raster Format or MRF.  TWMS is based on packing all tiles into a single binary data file with external index and header files.  MRF data encoding is performed using a custom GDAL driver.
+
+Requirements
+
+gdal 1.9.0  (NOTE:  Source code must be retained to build MRF driver.)
+
+Step 1 – Install GDAL
+
+The MRF driver plugin links with the rest of GDAL and it has to be compiled with the same compiler, libraries and same options that GDAL was compiled.  It is a plugin, but that doesn’t mean you compile it once and it works on any system with any GDAL.
+
+Download gdal-1.9.0 source:
+wget http://download.osgeo.org/gdal/gdal190.zip
+
+Unpack gdal-1.9.0 source:
+mkdir src
+mv gdal190.zip src/
+cd src/
+unzip gdal190.zip
+
+Go to the gdal source directory:
+cd gdal-1.9.0/
+
+Configure gdal source install:
+set LD_LIBRARY_PATH "<gdal install location>/lib:$LD_LIBRARY_PATH"
+./configure --prefix=<gdal install location>
+The <gdal install location> should be different from where you build the source code for gdal.
+
+Make gdal:
+make
+
+Install gdal:
+make install
+
+
+Step 2 – Install MRF driver
+
+Where,
+<tag location>
+configuration management
+
+<destination_directory>
+location of the MRF driver plugin source code
+
+<gdal source directory>
+location of GDAL source code
+
+<gdal install location>
+location of GDAL installed software
+
+Check out tagged copy of twms gdal driver:
+Eg: svn co https://<tag location> <destination_directory>
+
+Copy the mrf gdal driver to the gdal source tree (this plugin must be compiled here):
+cp -R <destination_directory>/GDAL_MRF/*  <gdal source directory>/frmts/
+
+Go to the mrf driver source directory:
+cd frmts/mrf
+
+Make the driver:
+cp GNUMake Makefile
+make plugin
+
+Install the driver:
+mkdir –p <gdal install location>/lib/gdalplugins
+
+make iplugin
+-OR-
+cp gdal_mrf.so.1 <gdal install location>/lib/gdalplugins
+
+Create links:
+cd <gdal install location>/lib/gdalplugins
+ln -s gdal_mrf.so.1 gdal_mrf.so
+ln –s <gdal install location>/lib/gdalplugins <destination_directory>
+
+Step 3 – Testing
+Verify that the MRF driver is recognized by GDAL:
+gdalinfo --format MRF
+
+List of delivered files
+frmt_marfa.html
+GNUmakefile
+JPEG_band.cpp
+makefile.vc
+marfa_dataset.cpp
+marfa.h
+mrf_band.cpp
+PNG_band.cpp
+Raw_band.cpp
+Tif_band.cpp
+util.cpp
+ZLIB_band.cpp
+
diff --git a/frmts/mrf/Raw_band.cpp b/frmts/mrf/Raw_band.cpp
new file mode 100644
index 0000000..a7f04ab
--- /dev/null
+++ b/frmts/mrf/Raw_band.cpp
@@ -0,0 +1,65 @@
+/*
+* Copyright (c) 2002-2012, California Institute of Technology.
+* All rights reserved.  Based on Government Sponsored Research under contracts NAS7-1407 and/or NAS7-03001.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+*   1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+*   2. Redistributions in binary form must reproduce the above copyright notice,
+*      this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+*   3. Neither the name of the California Institute of Technology (Caltech), its operating division the Jet Propulsion Laboratory (JPL),
+*      the National Aeronautics and Space Administration (NASA), nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE CALIFORNIA INSTITUTE OF TECHNOLOGY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* Copyright 2014 Esri
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/*
+ * $Id$
+ * raw band
+ * raw page compression and decompression functions
+ * Simple copy of data
+ *
+ */
+
+#include "marfa.h"
+
+NAMESPACE_MRF_START
+
+inline CPLErr NONE(buf_mgr &dst, buf_mgr &src)
+{
+    memcpy(dst.buffer, src.buffer, src.size);
+    dst.size=src.size;
+    return CE_None;
+}
+
+CPLErr Raw_Band::Decompress(buf_mgr &dst, buf_mgr &src)
+{
+    return NONE(dst,src);
+}
+
+CPLErr Raw_Band::Compress(buf_mgr &dst, buf_mgr &src)
+{
+    return NONE(dst,src);
+}
+
+NAMESPACE_MRF_END
diff --git a/frmts/mrf/Tif_band.cpp b/frmts/mrf/Tif_band.cpp
new file mode 100644
index 0000000..158795f
--- /dev/null
+++ b/frmts/mrf/Tif_band.cpp
@@ -0,0 +1,207 @@
+/*
+* Copyright (c) 2002-2012, California Institute of Technology.
+* All rights reserved.  Based on Government Sponsored Research under contracts NAS7-1407 and/or NAS7-03001.
+* Redistribution and use in source and binary forms, with or without modification, are permitted provided
+* that the following conditions are met:
+*   1. Redistributions of source code must retain the above copyright notice, this list of conditions and
+*      the following disclaimer.
+*   2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+*      the following disclaimer in the documentation and/or other materials provided with the distribution.
+*   3. Neither the name of the California Institute of Technology (Caltech), its operating division the
+*      Jet Propulsion Laboratory (JPL), the National Aeronautics and Space Administration (NASA),
+*      nor the names of its contributors may be used to endorse or promote products derived from this software
+*      without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE CALIFORNIA INSTITUTE OF TECHNOLOGY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* Copyright 2014-2015 Esri
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/*
+ * TIFF band
+ * TIFF page compression and decompression functions
+ *
+ * Author:  Lucian Plesea, lplesea at esri.com
+ *
+ */
+
+#include "marfa.h"
+
+NAMESPACE_MRF_START
+
+// Returns a string in /vsimem/ + prefix + count that doesn't exist when this function gets called
+// It is not thread safe, open the result as soon as possible
+static CPLString uniq_memfname(const char *prefix)
+{
+
+// Define MRF_LOCAL_TMP to use local files instead of RAM
+// #define MRF_LOCAL_TMP
+#if defined(MRF_LOCAL_TMP)
+    return CPLGenerateTempFilename(prefix);
+#else
+    CPLString fname;
+    VSIStatBufL statb;
+    static unsigned int cnt=0;
+    do fname.Printf("/vsimem/%s_%08x",prefix, cnt++);
+    while (!VSIStatL(fname, &statb));
+    return fname;
+#endif
+}
+
+//
+// Uses GDAL to create a temporary TIF file, using the band create options
+// copies the content to the destination buffer then erases the temp TIF
+//
+static CPLErr CompressTIF(buf_mgr &dst, buf_mgr &src, const ILImage &img, char **papszOptions)
+{
+    CPLErr ret;
+    GDALDriver *poTiffDriver = GetGDALDriverManager()->GetDriverByName("GTiff");
+    VSIStatBufL statb;
+    CPLString fname = uniq_memfname("mrf_tif_write");
+
+    GDALDataset *poTiff = poTiffDriver->Create(fname, img.pagesize.x, img.pagesize.y,
+	img.pagesize.c, img.dt, papszOptions );
+
+    // Read directly to avoid double caching in GDAL
+    // Unfortunately not possible for multiple bands
+    if (img.pagesize.c == 1) {
+	ret = poTiff->GetRasterBand(1)->WriteBlock(0,0,src.buffer);
+    } else {
+	ret = poTiff->RasterIO(GF_Write, 0,0,img.pagesize.x,img.pagesize.y,
+	    src.buffer, img.pagesize.x, img.pagesize.y, img.dt, img.pagesize.c,
+	    NULL, 0,0,0
+#if GDAL_VERSION_MAJOR >= 2
+            ,NULL
+#endif
+	    );
+    }
+    if (CE_None != ret)	return ret;
+    GDALClose(poTiff);
+
+    // Check that we can read the file
+    if (VSIStatL(fname, &statb))
+    {
+	CPLError(CE_Failure,CPLE_AppDefined,
+	    "MRF: TIFF, can't stat %s", fname.c_str());
+        return CE_Failure;
+    }
+
+    if (size_t(statb.st_size) > dst.size)
+    {
+	CPLError(CE_Failure,CPLE_AppDefined,
+	    "MRF: TIFF, Tiff generated is too large");
+        return CE_Failure;
+    }
+
+    VSILFILE *pf = VSIFOpenL(fname,"rb");
+    if (pf == NULL)
+    {
+	CPLError(CE_Failure,CPLE_AppDefined,
+	    "MRF: TIFF, can't open %s", fname.c_str());
+        return CE_Failure;
+    }
+
+    VSIFReadL(dst.buffer, static_cast<size_t>(statb.st_size), 1, pf);
+    dst.size = static_cast<size_t>(statb.st_size);
+    VSIFCloseL(pf);
+    VSIUnlink(fname);
+
+    return CE_None;
+}
+
+// Read from a RAM Tiff. This is rather generic
+static CPLErr DecompressTIF(buf_mgr &dst, buf_mgr &src, const ILImage &img)
+{
+    CPLString fname = uniq_memfname("mrf_tif_read");
+    VSILFILE *fp = VSIFileFromMemBuffer(fname, (GByte *)(src.buffer), src.size, false);
+    // Comes back opened, but we can't use it
+    if (fp)
+	VSIFCloseL(fp);
+    else {
+	CPLError(CE_Failure,CPLE_AppDefined,
+	    "MRF: TIFF, can't open %s as a temp file", fname.c_str());
+        return CE_Failure;
+    }
+#if GDAL_VERSION_MAJOR >= 2
+    const char* const apszAllowedDrivers[] = { "GTiff", NULL };
+    GDALDataset *poTiff = reinterpret_cast<GDALDataset*>(GDALOpenEx(fname, GDAL_OF_RASTER, apszAllowedDrivers, NULL, NULL));
+#else
+    GDALDataset *poTiff = reinterpret_cast<GDALDataset*>(GDALOpen(fname, GA_ReadOnly));
+#endif
+    if (poTiff == NULL) {
+	CPLError(CE_Failure,CPLE_AppDefined,
+	    "MRF: TIFF, can't open page as a Tiff");
+        VSIUnlink(fname);
+        return CE_Failure;
+    }
+
+    CPLErr ret;
+    // Bypass the GDAL caching
+    if (img.pagesize.c == 1) {
+	ret = poTiff->GetRasterBand(1)->ReadBlock(0,0,dst.buffer);
+    } else {
+	ret = poTiff->RasterIO(GF_Read,0,0,img.pagesize.x,img.pagesize.y,
+	    dst.buffer, img.pagesize.x, img.pagesize.y, img.dt, img.pagesize.c,
+	    NULL, 0,0,0
+#if GDAL_VERSION_MAJOR >= 2
+            ,NULL
+#endif
+	    );
+    }
+    GDALClose(poTiff);
+    VSIUnlink(fname);
+
+    return ret;
+}
+
+CPLErr TIF_Band::Decompress(buf_mgr &dst, buf_mgr &src)
+{
+    return DecompressTIF(dst, src, img);
+}
+
+CPLErr TIF_Band::Compress(buf_mgr &dst, buf_mgr &src)
+{
+    return CompressTIF(dst,src,img, papszOptions);
+}
+
+TIF_Band::TIF_Band(GDALMRFDataset *pDS, const ILImage &image, int b, int level):
+        GDALMRFRasterBand(pDS,image,b,int(level))
+{
+    // Increase the page buffer by 1K in case Tiff expands data
+    pDS->SetPBufferSize(image.pageSizeBytes + 1024);
+
+    // Static create options for TIFF tiles
+    papszOptions = CSLAddNameValue(NULL, "COMPRESS", "DEFLATE");
+    papszOptions = CSLAddNameValue(papszOptions, "TILED", "Yes");
+    papszOptions = CSLAddNameValue(papszOptions, "BLOCKXSIZE", CPLString().Printf("%d",img.pagesize.x));
+    papszOptions = CSLAddNameValue(papszOptions, "BLOCKYSIZE", CPLString().Printf("%d",img.pagesize.y));
+    int q = img.quality / 10;
+    // Move down so the default 85 maps to 6.  This makes the maz ZLEVEL 8, which is OK
+    if (q >2) q-=2;
+    papszOptions = CSLAddNameValue(papszOptions, "ZLEVEL", CPLString().Printf("%d",q));
+};
+
+TIF_Band::~TIF_Band()
+{
+    CSLDestroy(papszOptions);
+};
+
+NAMESPACE_MRF_END
diff --git a/frmts/mrf/frmt_marfa.html b/frmts/mrf/frmt_marfa.html
new file mode 100644
index 0000000..9bc3b7b
--- /dev/null
+++ b/frmts/mrf/frmt_marfa.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<!--
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>MRF -- Meta Raster Format</title>
+	<STYLE type="text/css">
+		td.xml { font-family: monospace; white-space: pre; padding-right: 20px; }
+		td.desc { }
+		span.value { color: #00B000; }
+		body { background-color: #ffffff; }
+	</STYLE>
+</head>
+
+<body>
+
+<h1>MRF -- Meta Raster Format</h1>
+
+<p>Integrated in GDAL >= 2.1. Available as plugin for prior versions.</p>
+
+<p>
+  Access to a indexed heap of regular tiles (blocks).  Controlled by an xml file, usually organized as a pyramid of overviews, with level zero being the full resolution image.  None, PNG, JPEG, ZLIB tile packing are implemented
+</p>
+<p>
+  For file creation options, see "gdalinfo --format MRF"
+</p>
+
+<h2>Links</h2>
+
+<ul>
+<li><a href="https://github.com/nasa-gibs/mrf/blob/master/src/gdal_mrf/frmts/mrf/docs/MUG.md">MRF User Guide</a></li>
+<li><a href="https://github.com/nasa-gibs/mrf/blob/master/spec/mrf_spec.md">MRF Specification</a></li>
+<li><a href="https://github.com/nasa-gibs/mrf">Source repository nasa-gibs/mrf</a></li>
+</ul>
+
+</body>
+</html>
diff --git a/frmts/mrf/libLERC/BitMask.cpp b/frmts/mrf/libLERC/BitMask.cpp
new file mode 100644
index 0000000..2053e42
--- /dev/null
+++ b/frmts/mrf/libLERC/BitMask.cpp
@@ -0,0 +1,158 @@
+/*
+Copyright 2015 Esri
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+A local copy of the license and additional notices are located with the
+source distribution at:
+http://github.com/Esri/lerc/
+Contributors:  Thomas Maurer
+    Lucian Plesea 2014
+
+Despite the file name, only the RLE codec of a bitmask is in this file
+The LERC RLE encoding is the one designed by Thomas Maurer
+In the encoded stream there are two types of sequences and an end marker
+- A repeating byte sequence, starts with a negative, low endian 16bit count,
+    between 5 and 32767, followed by the repeated byte value
+- A non-repeating sequence, starts with a positive, low endian 16bit count,
+    between 1 and 32767, followed by count bytes
+- Count of -32768 is the end marker
+0 to 4 byte repeats are not encoded as repeated byte sequence
+*/
+
+#include "BitMask.h"
+#include <cassert>
+
+NAMESPACE_LERC_START
+
+#define MAX_RUN 32767
+#define MIN_RUN 5
+// End of Transmission
+#define EOT -(MAX_RUN + 1)
+
+// Decode a RLE bitmask, size should be already set
+// Returns false if input seems wrong
+// Not safe if fed garbage !!!
+// Zero size mask is fine, only checks the end marker
+bool BitMask::RLEdecompress(const Byte* src) {
+    Byte *dst = m_pBits;
+    int sz = Size();
+    short int count;
+    assert(src);
+
+// Read a two bye short int
+#define READ_COUNT if (true) { count = *src++; count += (*src++ << 8); }
+
+    while (sz) { // One sequence per loop
+	READ_COUNT;
+	if (count < 0) { // negative count for repeats
+	    Byte b = *src++;
+	    sz += count;
+	    while (0 != count++)
+		*dst++ = b;
+	} else { // No repeats
+	    sz -= count;
+	    while (0 != count--)
+		*dst++ = *src++;
+	}
+    }
+    READ_COUNT;
+    return (count == EOT);
+}
+
+// Encode helper function
+// It returns how many times the byte at *s is repeated
+// a value between 1 and min(max_count, MAX_RUN)
+inline static int run_length(const Byte *s, int max_count)
+{
+    assert(max_count && s);
+    if (max_count > MAX_RUN)
+	max_count = MAX_RUN;
+    const Byte c = *s++;
+    for (int count = 1; count < max_count; count++)
+	if (c != *s++)
+	    return count;
+    return max_count;
+}
+
+//
+// RLE compressed size is bound by n + 4 + 2 * (n - 1) / 32767
+//
+int BitMask::RLEcompress(Byte *dst) const {
+    assert(dst);
+    // Next input byte
+    Byte *src = m_pBits;
+    Byte *start = dst;
+    // left to process
+    int sz = Size();
+
+    // Pointer to current sequence count
+    Byte *pCnt = dst;
+    // non-repeated byte count
+    int oddrun = 0;
+
+// Store a two byte count in low endian
+#define WRITE_COUNT(val) if (true) { *pCnt++ = Byte(val & 0xff); *pCnt++ = Byte(val >> 8); }
+// Flush an existing odd run
+#define FLUSH if (oddrun) { WRITE_COUNT(oddrun); pCnt += oddrun; dst = pCnt + 2; oddrun = 0; }
+
+    dst += 2; // Skip the space for the first count
+    while (sz) {
+	int run = run_length(src, sz);
+	if (run < MIN_RUN) { // Use one byte
+	    *dst++ = *src++;
+	    sz--;
+	    if (MAX_RUN == ++oddrun)
+		FLUSH;
+	} else { // Found a run
+	    FLUSH;
+	    WRITE_COUNT(-run);
+	    *pCnt++ = *src;
+	    src += run;
+	    sz -= run;
+	    dst = pCnt + 2; // after the next marker
+	}
+    }
+    FLUSH;
+    WRITE_COUNT(EOT); // End marker
+    // return compressed output size
+    return int(pCnt - start);
+}
+
+// calculate encoded size
+int BitMask::RLEsize() const {
+    // Next input byte
+    Byte *src = m_pBits;
+    // left to process
+    int sz = Size();
+    // current non-repeated byte count
+    int oddrun = 0;
+    // Simulate an odd run flush
+#define SIMFLUSH if (oddrun) { osz += oddrun + 2; oddrun = 0; }
+    // output size, start with size of end marker
+    int osz = 2;
+    while (sz) {
+	int run = run_length(src, sz);
+	if (run < MIN_RUN) {
+	    src++;
+	    sz--;
+	    if (MAX_RUN == ++oddrun)
+		SIMFLUSH;
+	} else {
+	    SIMFLUSH;
+	    src += run;
+	    sz -= run;
+	    osz += 3; // Any run is 3 bytes
+	}
+    }
+    SIMFLUSH;
+    return osz;
+}
+
+NAMESPACE_LERC_END
diff --git a/frmts/mrf/libLERC/BitMask.h b/frmts/mrf/libLERC/BitMask.h
new file mode 100644
index 0000000..7855643
--- /dev/null
+++ b/frmts/mrf/libLERC/BitMask.h
@@ -0,0 +1,70 @@
+/*
+Copyright 2015 Esri
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+A local copy of the license and additional notices are located with the
+source distribution at:
+http://github.com/Esri/lerc/
+Contributors:  Thomas Maurer
+	       Lucian Plesea
+*/
+
+#ifndef BITMASK_H
+#define BITMASK_H
+#include "Defines.h"
+
+NAMESPACE_LERC_START
+
+/** BitMask - Convenient and fast access to binary mask bits
+* includes RLE compression and decompression, in BitMask.cpp
+*
+*/
+
+class BitMask
+{
+public:
+  BitMask(int nCols, int nRows) : m_pBits(NULL), m_nRows(nRows), m_nCols(nCols)
+  {
+      m_pBits = new Byte[Size()];
+      if (!m_pBits)
+	  m_nRows = m_nCols = 0;
+      else
+	  m_pBits[Size() - 1] = 0; // Set potential pad bytes to zero
+  }
+  ~BitMask()				      { if (m_pBits) delete[] m_pBits; }
+
+  Byte  IsValid(int k) const                  { return (m_pBits[k >> 3] & Bit(k)) != 0; }
+  void  SetValid(int k) const                 { m_pBits[k >> 3] |= Bit(k); }
+  void  SetInvalid(int k) const               { m_pBits[k >> 3] &= ~Bit(k); }
+  int	Size() const			      { return (m_nCols * m_nRows - 1) / 8 + 1; }
+
+  // max RLE compressed size is n + 4 + 2 * (n - 1) / 32767
+  // Returns encoded size
+  int RLEcompress(Byte *aRLE) const;
+  // current encoded size
+  int RLEsize() const;
+  // Decompress a RLE bitmask, bitmask size should be already set
+  // Returns false if input seems wrong
+  bool RLEdecompress(const Byte* src);
+
+private:
+  Byte*  m_pBits;
+  int   m_nRows, m_nCols;
+
+  Byte  Bit(int k) const                      { return (1 << 7) >> (k & 7); }
+
+  // Disable assignment op, default and copy constructor
+  BitMask();
+  BitMask(const BitMask& copy);
+  BitMask& operator=(const BitMask& m);
+};
+
+NAMESPACE_LERC_END
+#endif
diff --git a/frmts/mrf/libLERC/BitMask2.cpp b/frmts/mrf/libLERC/BitMask2.cpp
new file mode 100644
index 0000000..d4ae71d
--- /dev/null
+++ b/frmts/mrf/libLERC/BitMask2.cpp
@@ -0,0 +1,125 @@
+/*
+Copyright 2015 Esri
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+A local copy of the license and additional notices are located with the
+source distribution at:
+http://github.com/Esri/lerc/
+Contributors:  Thomas Maurer
+*/
+
+//
+// BitMask2.cpp
+//
+
+#include "BitMask2.h"
+#include <algorithm>
+#include <cstring>
+#include <iostream>
+#include <cassert>
+
+NAMESPACE_LERC_START
+
+// -------------------------------------------------------------------------- ;
+
+BitMask2::BitMask2() : m_pBits(NULL), m_nCols(0), m_nRows(0)
+{
+}
+
+// -------------------------------------------------------------------------- ;
+
+BitMask2::BitMask2(int nCols, int nRows) : m_pBits(NULL), m_nCols(0), m_nRows(0)
+{
+  SetSize(nCols, nRows);
+}
+
+// -------------------------------------------------------------------------- ;
+
+BitMask2::BitMask2(const BitMask2& src) : m_pBits(NULL), m_nCols(0), m_nRows(0)
+{
+  SetSize(src.m_nCols, src.m_nRows);
+  if (m_pBits && src.m_pBits)
+    memcpy(m_pBits, src.m_pBits, Size());
+}
+
+// -------------------------------------------------------------------------- ;
+
+BitMask2& BitMask2::operator= (const BitMask2& src)
+{
+  if (this == &src) return *this;
+
+  SetSize(src.m_nCols, src.m_nRows);
+  if (src.m_pBits)
+    memcpy(m_pBits, src.m_pBits, Size());
+
+  return *this;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool BitMask2::SetSize(int nCols, int nRows)
+{
+  if (nCols != m_nCols || nRows != m_nRows)
+  {
+    Clear();
+    m_nCols = nCols;
+    m_nRows = nRows;
+    m_pBits = new Byte[Size()];
+  }
+  return m_pBits != NULL;
+}
+
+// -------------------------------------------------------------------------- ;
+//
+// Count of set bits in a byte, done in 7 32bit instructions
+// Adds every two bits sideways, makes four copies, masks each of the four results
+// the last multiplication adds the four results together in the top nibble
+// This is potentially slower for input data
+//
+static inline int csb(unsigned int v) {
+    return ((((v - ((v >> 1) & 0x55)) * 0x1010101) & 0x30c00c03) * 0x10040041) >> 0x1c;
+}
+
+// Number of bits set.
+// We really only need to know if full, empty or in between
+int BitMask2::CountValidBits() const
+{
+  assert(Size());
+  const Byte* ptr = m_pBits;
+  int sum = 0;
+
+  // The first loop is in multiples of four, to let the compiler optimize
+  for (int i = 0; i < (Size()/4) * 4; i++)
+      sum += csb(*ptr++);
+  // Second loop for the leftover bytes, up to three
+  for (int i = 0; i < Size() % 4; i++)
+      sum += csb(*ptr++);
+
+  // Subtract the defined bits potentially contained in the last byte
+  // Number of undefined bytes is (C*R)%8
+  // The undefined bits are at the low bit position, use a mask for them
+  sum -= csb((*--ptr) & ((1 << ((m_nCols * m_nRows) % 8)) -1));
+
+  return sum;
+}
+
+// -------------------------------------------------------------------------- ;
+
+void BitMask2::Clear()
+{
+  delete[] m_pBits;
+  m_pBits = NULL;
+  m_nCols = 0;
+  m_nRows = 0;
+}
+
+// -------------------------------------------------------------------------- ;
+
+NAMESPACE_LERC_END
diff --git a/frmts/mrf/libLERC/BitMask2.h b/frmts/mrf/libLERC/BitMask2.h
new file mode 100644
index 0000000..eba1b6d
--- /dev/null
+++ b/frmts/mrf/libLERC/BitMask2.h
@@ -0,0 +1,72 @@
+/*
+Copyright 2015 Esri
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+A local copy of the license and additional notices are located with the
+source distribution at:
+http://github.com/Esri/lerc/
+Contributors:  Thomas Maurer
+*/
+
+#ifndef BITMASK2_H
+#define BITMASK2_H
+
+#include "Defines.h"
+#include <cstring>
+
+NAMESPACE_LERC_START
+
+/** BitMask2 - Convenient and fast access to binary mask bits
+ *
+ */
+
+class BitMask2
+{
+public:
+  BitMask2();
+  BitMask2(int nCols, int nRows);
+  BitMask2(const BitMask2& src);
+  virtual ~BitMask2()                        { Clear(); }
+
+  BitMask2& operator= (const BitMask2& src);
+
+  // 1: valid, 0: not valid
+  Byte IsValid(int k) const                  { return (m_pBits[k >> 3] & Bit(k)) > 0; }
+  Byte IsValid(int row, int col) const       { return IsValid(row * m_nCols + col); }
+
+  void  SetValid(int k) const                { m_pBits[k >> 3] |= Bit(k); }
+  void  SetValid(int row, int col) const     { SetValid(row * m_nCols + col); }
+
+  void  SetInvalid(int k) const              { m_pBits[k >> 3] &= ~Bit(k); }
+  void  SetInvalid(int row, int col) const   { SetInvalid(row * m_nCols + col); }
+
+  void  SetAllValid() const                  { memset(m_pBits, ~0, Size()); }
+  void  SetAllInvalid() const                { memset(m_pBits,  0, Size()); }
+
+  bool  SetSize(int nCols, int nRows);
+
+  int  GetWidth() const                      { return m_nCols; }
+  int  GetHeight() const                     { return m_nRows; }
+  int  Size() const                          { return (m_nCols * m_nRows + 7) >> 3; }
+  const Byte* Bits() const                   { return m_pBits; }
+  Byte* Bits()                               { return m_pBits; }
+  Byte  Bit(int k) const                     { return (1 << 7) >> (k & 7); }
+
+  int  CountValidBits() const;
+  void  Clear();
+
+private:
+  Byte*  m_pBits;
+  int    m_nCols,
+         m_nRows;
+};
+
+NAMESPACE_LERC_END
+#endif
diff --git a/frmts/mrf/libLERC/BitStuffer.cpp b/frmts/mrf/libLERC/BitStuffer.cpp
new file mode 100644
index 0000000..ea7b30c
--- /dev/null
+++ b/frmts/mrf/libLERC/BitStuffer.cpp
@@ -0,0 +1,313 @@
+/*
+Copyright 2015 Esri
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+A local copy of the license and additional notices are located with the
+source distribution at:
+
+http://github.com/Esri/lerc/
+
+Contributors:  Thomas Maurer
+*/
+
+#include "BitStuffer.h"
+#include <cstring>
+
+// -------------------------------------------------------------------------- ;
+
+using namespace std;
+
+NAMESPACE_LERC_START
+
+// -------------------------------------------------------------------------- ;
+
+// see the old stream IO functions below on how to call.
+// if you change write(...) / read(...), don't forget to update computeNumBytesNeeded(...).
+
+bool BitStuffer::write(Byte** ppByte, const vector<unsigned int>& dataVec) const
+{
+  if (!ppByte || dataVec.empty())
+    return false;
+
+  unsigned int maxElem = findMax(dataVec);
+
+  int numBits = 0;
+  while (maxElem >> numBits)
+    numBits++;
+  Byte numBitsByte = (Byte)numBits;
+  unsigned int numElements = (unsigned int)dataVec.size();
+  unsigned int numUInts = (numElements * numBits + 31) / 32;
+
+  // use the upper 2 bits to encode the type used for numElements: Byte, ushort, or uint
+  int n = numBytesUInt(numElements);
+  int bits67 = (n == 4) ? 0 : 3 - n;
+  numBitsByte |= bits67 << 6;
+
+  **ppByte = numBitsByte;
+  (*ppByte)++;
+
+  if (!writeUInt(ppByte, numElements, n))
+    return false;
+
+  if (numUInts > 0)    // numBits can be 0, then we only write the header
+  {
+    unsigned int numBytes = numUInts * sizeof(unsigned int);
+    unsigned int* arr = (unsigned int*)(*ppByte);
+
+    memset(arr, 0, numBytes);
+
+    // do the stuffing
+    const unsigned int* srcPtr = &dataVec[0];
+    unsigned int* dstPtr = arr;
+    int bitPos = 0;
+
+    for (unsigned int i = 0; i < numElements; i++)
+    {
+      if (32 - bitPos >= numBits)
+      {
+        unsigned int dstValue;
+        memcpy(&dstValue, dstPtr, sizeof(unsigned int));
+        dstValue |= (*srcPtr++) << (32 - bitPos - numBits);
+        memcpy(dstPtr, &dstValue, sizeof(unsigned int));
+        bitPos += numBits;
+        if (bitPos == 32)    // shift >= 32 is undefined
+        {
+          bitPos = 0;
+          dstPtr++;
+        }
+      }
+      else
+      {
+        int n2 = numBits - (32 - bitPos);
+        unsigned int dstValue;
+        memcpy(&dstValue, dstPtr, sizeof(unsigned int));
+        dstValue |= (*srcPtr  ) >> n2;
+        memcpy(dstPtr, &dstValue, sizeof(unsigned int));
+        dstPtr++;
+        memcpy(&dstValue, dstPtr, sizeof(unsigned int));
+        dstValue |= (*srcPtr++) << (32 - n2);
+        memcpy(dstPtr, &dstValue, sizeof(unsigned int));
+        bitPos = n2;
+      }
+    }
+
+    // save the 0-3 bytes not used in the last UInt
+    unsigned int numBytesNotNeeded = numTailBytesNotNeeded(numElements, numBits);
+    unsigned int n2 = numBytesNotNeeded;
+    while (n2--)
+    {
+      unsigned int dstValue;
+      memcpy(&dstValue, dstPtr, sizeof(unsigned int));
+      dstValue >>= 8;
+      memcpy(dstPtr, &dstValue, sizeof(unsigned int));
+    }
+
+    dstPtr = arr;
+    for (unsigned int i = 0; i < numUInts; i++)
+    {
+      SWAP_4(*dstPtr);
+      dstPtr++;
+    }
+
+    *ppByte += numBytes - numBytesNotNeeded;
+  }
+
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool BitStuffer::read(Byte** ppByte, vector<unsigned int>& dataVec) const
+{
+  if (!ppByte)
+    return false;
+
+  Byte numBitsByte = **ppByte;
+  (*ppByte)++;
+
+  int bits67 = numBitsByte >> 6;
+  int n = (bits67 == 0) ? 4 : 3 - bits67;
+
+  numBitsByte &= 63;    // bits 0-5;
+
+  unsigned int numElements = 0;
+  if (!readUInt(ppByte, numElements, n))
+    return false;
+
+  if (numBitsByte >= 32)
+    return false;
+
+  int numBits = numBitsByte;
+  unsigned int numUInts = (numElements * numBits + 31) / 32;
+  dataVec.resize(numElements, 0);    // init with 0
+
+  if (numUInts > 0)    // numBits can be 0
+  {
+    unsigned int numBytes = numUInts * sizeof(unsigned int);
+    unsigned int* arr = (unsigned int*)(*ppByte);
+
+    unsigned int* srcPtr = arr;
+    for (unsigned int i = 0; i < numUInts; i++)
+    {
+      SWAP_4(*srcPtr);
+      srcPtr++;
+    }
+
+    // needed to save the 0-3 bytes not used in the last UInt
+    srcPtr--;
+    unsigned int lastUInt;
+    memcpy(&lastUInt, srcPtr, sizeof(unsigned int));
+    unsigned int numBytesNotNeeded = numTailBytesNotNeeded(numElements, numBits);
+    unsigned int n2 = numBytesNotNeeded;
+    while (n2--)
+    {
+      unsigned int srcValue;
+      memcpy(&srcValue, srcPtr, sizeof(unsigned int));
+      srcValue <<= 8;
+      memcpy(srcPtr, &srcValue, sizeof(unsigned int));
+    }
+
+    // do the un-stuffing
+    srcPtr = arr;
+    unsigned int* dstPtr = &dataVec[0];
+    int bitPos = 0;
+
+    for (unsigned int i = 0; i < numElements; i++)
+    {
+      if (32 - bitPos >= numBits)
+      {
+        unsigned int srcValue;
+        memcpy(&srcValue, srcPtr, sizeof(unsigned int));
+        unsigned int n3 = srcValue << bitPos;
+        *dstPtr++ = n3 >> (32 - numBits);
+        bitPos += numBits;
+        if (bitPos == 32)    // shift >= 32 is undefined
+        {
+          bitPos = 0;
+          srcPtr++;
+        }
+      }
+      else
+      {
+        unsigned int srcValue;
+        memcpy(&srcValue, srcPtr, sizeof(unsigned int));
+        srcPtr ++;
+        unsigned int n3 = srcValue << bitPos;
+        *dstPtr = n3 >> (32 - numBits);
+        bitPos -= (32 - numBits);
+        memcpy(&srcValue, srcPtr, sizeof(unsigned int));
+        *dstPtr++ |= srcValue >> (32 - bitPos);
+      }
+    }
+
+    if (numBytesNotNeeded > 0)
+      memcpy(srcPtr, &lastUInt, sizeof(unsigned int)); // restore the last UInt
+
+    *ppByte += numBytes - numBytesNotNeeded;
+  }
+
+  return true;
+}
+
+unsigned int BitStuffer::computeNumBytesNeeded(unsigned int numElem, unsigned int maxElem)
+{
+  int numBits = 0;
+  while (maxElem >> numBits)
+    numBits++;
+  unsigned int numUInts = (numElem * numBits + 31) / 32;
+  unsigned int numBytes = 1 + numBytesUInt(numElem) + numUInts * sizeof(unsigned int) -
+    numTailBytesNotNeeded(numElem, numBits);
+
+  return numBytes;
+}
+
+// -------------------------------------------------------------------------- ;
+// -------------------------------------------------------------------------- ;
+unsigned int BitStuffer::findMax(const vector<unsigned int>& dataVec) const
+{
+  unsigned int maxElem = 0;
+  for (size_t i = 0; i < dataVec.size(); i++)
+      maxElem = max(maxElem, dataVec[i]);
+  return maxElem;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool BitStuffer::writeUInt(Byte** ppByte, unsigned int k, int numBytes) const
+{
+  Byte* ptr = *ppByte;
+
+  if (numBytes == 1)
+  {
+    *ptr = (Byte)k;
+  }
+  else if (numBytes == 2)
+  {
+    unsigned short s = (unsigned short)k;
+    SWAP_2(s);
+    memcpy(ptr, &s, sizeof(unsigned short));
+  }
+  else if (numBytes == 4)
+  {
+    SWAP_4(k);
+    memcpy(ptr, &k, sizeof(unsigned int));
+  }
+  else
+    return false;
+
+  *ppByte = ptr + numBytes;
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool BitStuffer::readUInt(Byte** ppByte, unsigned int& k, int numBytes) const
+{
+  Byte* ptr = *ppByte;
+
+  if (numBytes == 1)
+  {
+    k = *ptr;
+  }
+  else if (numBytes == 2)
+  {
+    unsigned short s;
+    memcpy(&s, ptr, sizeof(unsigned short));
+    SWAP_2(s);
+    k = s;
+  }
+  else if (numBytes == 4)
+  {
+    memcpy(&k, ptr, sizeof(unsigned int));
+    SWAP_4(k);
+  }
+  else
+    return false;
+
+  *ppByte = ptr + numBytes;
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+unsigned int BitStuffer::numTailBytesNotNeeded(unsigned int numElem, int numBits)
+{
+  int numBitsTail = (numElem * numBits) & 31;
+  int numBytesTail = (numBitsTail + 7) >> 3;
+  return (numBytesTail > 0) ? 4 - numBytesTail : 0;
+}
+
+// -------------------------------------------------------------------------- ;
+
+NAMESPACE_LERC_END
diff --git a/frmts/mrf/libLERC/BitStuffer.h b/frmts/mrf/libLERC/BitStuffer.h
new file mode 100644
index 0000000..e7bb9f4
--- /dev/null
+++ b/frmts/mrf/libLERC/BitStuffer.h
@@ -0,0 +1,59 @@
+/*
+Copyright 2015 Esri
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+A local copy of the license and additional notices are located with the
+source distribution at:
+http://github.com/Esri/lerc/
+Contributors:  Thomas Maurer
+*/
+
+#ifndef BITSTUFFER_H
+#define BITSTUFFER_H
+
+// ---- includes ------------------------------------------------------------ ;
+
+#include <vector>
+#include <algorithm>
+#include "Defines.h"
+
+NAMESPACE_LERC_START
+/** Bit stuffer, for writing unsigned int arrays compressed lossless
+ *
+ */
+
+class BitStuffer
+{
+public:
+  BitStuffer()           {}
+  virtual ~BitStuffer()  {}
+
+  // these 2 do not allocate memory. Byte ptr is moved like a file pointer.
+  bool write(Byte** ppByte, const std::vector<unsigned int>& dataVec) const;
+  bool read( Byte** ppByte, std::vector<unsigned int>& dataVec) const;
+
+  static unsigned int computeNumBytesNeeded(unsigned int numElem, unsigned int maxElem);
+  static unsigned int numExtraBytesToAllocate()  { return 3; }
+
+protected:
+  unsigned int findMax(const std::vector<unsigned int>& dataVec) const;
+
+  // numBytes = 1, 2, or 4
+  bool writeUInt(Byte** ppByte, unsigned int k, int numBytes) const;
+  bool readUInt( Byte** ppByte, unsigned int& k, int numBytes) const;
+
+  static int numBytesUInt(unsigned int k)  { return (k < 256) ? 1 : (k < (1 << 16)) ? 2 : 4; }
+  static unsigned int numTailBytesNotNeeded(unsigned int numElem, int numBits);
+};
+
+// -------------------------------------------------------------------------- ;
+
+NAMESPACE_LERC_END
+#endif
diff --git a/frmts/mrf/libLERC/BitStuffer2.cpp b/frmts/mrf/libLERC/BitStuffer2.cpp
new file mode 100644
index 0000000..7aa9eee
--- /dev/null
+++ b/frmts/mrf/libLERC/BitStuffer2.cpp
@@ -0,0 +1,360 @@
+/*
+Copyright 2015 Esri
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+A local copy of the license and additional notices are located with the
+source distribution at:
+
+http://github.com/Esri/lerc/
+
+Contributors:  Thomas Maurer
+*/
+
+#include "BitStuffer2.h"
+#include <algorithm>
+#include <cstring>
+
+using namespace std;
+
+NAMESPACE_LERC_START
+
+// -------------------------------------------------------------------------- ;
+
+// if you change Encode(...) / Decode(...), don't forget to update ComputeNumBytesNeeded(...)
+
+bool BitStuffer2::EncodeSimple(Byte** ppByte, const vector<unsigned int>& dataVec) const
+{
+  if (!ppByte || dataVec.empty())
+    return false;
+
+  unsigned int maxElem = *max_element(dataVec.begin(), dataVec.end());
+  int numBits = 0;
+  while ((numBits < 32) && (maxElem >> numBits))
+    numBits++;
+
+  if (numBits >= 32)
+    return false;
+
+  Byte numBitsByte = (Byte)numBits;
+  unsigned int numElements = (unsigned int)dataVec.size();
+  unsigned int numUInts = (numElements * numBits + 31) / 32;
+
+  // use the upper 2 bits to encode the type used for numElements: Byte, ushort, or uint
+  int n = NumBytesUInt(numElements);
+  int bits67 = (n == 4) ? 0 : 3 - n;
+  numBitsByte |= bits67 << 6;
+
+  // bit5 = 0 means simple mode
+
+  **ppByte = numBitsByte;
+  (*ppByte)++;
+
+  if (!EncodeUInt(ppByte, numElements, n))
+    return false;
+
+  if (numUInts > 0)    // numBits can be 0, then we only write the header
+    BitStuff(ppByte, dataVec, numBits);
+
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool BitStuffer2::EncodeLut(Byte** ppByte,
+                            const vector<Quant>& sortedDataVec) const
+{
+  if (!ppByte || sortedDataVec.empty())
+    return false;
+
+  if (sortedDataVec[0].first != 0)    // corresponds to min
+    return false;
+
+  // collect the different values for the lut
+  unsigned int numElem = (unsigned int)sortedDataVec.size();
+  unsigned int indexLut = 0;
+
+  m_tmpLutVec.resize(0);    // omit the 0 throughout that corresponds to min
+  m_tmpIndexVec.assign(numElem, 0);
+
+  for (unsigned int i = 1; i < numElem; i++)
+  {
+    unsigned int prev = static_cast<unsigned int>(sortedDataVec[i - 1].first);
+    m_tmpIndexVec[sortedDataVec[i - 1].second] = indexLut;
+
+    if (sortedDataVec[i].first != prev)
+    {
+      m_tmpLutVec.push_back(static_cast<unsigned int>(sortedDataVec[i].first));
+      indexLut++;
+    }
+  }
+  m_tmpIndexVec[sortedDataVec[numElem - 1].second] = indexLut;    // don't forget the last one
+
+  // write first 2 data elements same as simple, but bit5 set to 1
+  unsigned int maxElem = m_tmpLutVec.back();
+  int numBits = 0;
+  while ((numBits < 32) && (maxElem >> numBits))
+    numBits++;
+
+  if (numBits >= 32)
+    return false;
+
+  Byte numBitsByte = (Byte)numBits;
+
+  // use the upper 2 bits to encode the type used for numElem: byte, ushort, or uint
+  int n = NumBytesUInt(numElem);
+  int bits67 = (n == 4) ? 0 : 3 - n;
+  numBitsByte |= bits67 << 6;
+
+  numBitsByte |= (1 << 5);    // bit 5 = 1 means lut mode
+
+  **ppByte = numBitsByte;
+  (*ppByte)++;
+
+  if (!EncodeUInt(ppByte, numElem, n))    // numElements = numIndexes to lut
+    return false;
+
+  unsigned int nLut = (unsigned int)m_tmpLutVec.size();
+  if (nLut < 1 || nLut >= 255)
+    return false;
+
+  **ppByte = (Byte)nLut + 1;    // size of lut, incl the 0
+  (*ppByte)++;
+
+  BitStuff(ppByte, m_tmpLutVec, numBits);    // lut
+
+  int nBitsLut = 0;
+  while (nLut >> nBitsLut)
+    nBitsLut++;
+
+  BitStuff(ppByte, m_tmpIndexVec, nBitsLut);    // indexes
+
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+// if you change Encode(...) / Decode(...), don't forget to update ComputeNumBytesNeeded(...)
+
+bool BitStuffer2::Decode(const Byte** ppByte, vector<unsigned int>& dataVec) const
+{
+  if (!ppByte)
+    return false;
+
+  Byte numBitsByte = **ppByte;
+  (*ppByte)++;
+
+  int bits67 = numBitsByte >> 6;
+  int n = (bits67 == 0) ? 4 : 3 - bits67;
+
+  bool doLut = (numBitsByte & (1 << 5)) ? true : false;    // bit 5
+  numBitsByte &= 31;    // bits 0-4;
+
+  unsigned int numElements = 0;
+  if (!DecodeUInt(ppByte, numElements, n))
+    return false;
+
+  int numBits = numBitsByte;
+  dataVec.resize(numElements, 0);    // init with 0
+
+  if (!doLut)
+  {
+    if (numBits > 0)    // numBits can be 0
+      BitUnStuff(ppByte, dataVec, numElements, numBits);
+  }
+  else
+  {
+    Byte nLutByte = **ppByte;
+    (*ppByte)++;
+
+    int nLut = nLutByte - 1;
+    BitUnStuff(ppByte, m_tmpLutVec, nLut, numBits);    // unstuff lut w/o the 0
+
+    int nBitsLut = 0;
+    while (nLut >> nBitsLut)
+      nBitsLut++;
+
+    BitUnStuff(ppByte, dataVec, numElements, nBitsLut);    // unstuff indexes
+
+    // replace indexes by values
+    m_tmpLutVec.insert(m_tmpLutVec.begin(), 0);    // put back in the 0
+    for (unsigned int i = 0; i < numElements; i++)
+      dataVec[i] = m_tmpLutVec[dataVec[i]];
+  }
+
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+unsigned int BitStuffer2::ComputeNumBytesNeededLut(const vector<Quant >& sortedDataVec,
+                                                    bool& doLut) const
+{
+  unsigned int maxElem = static_cast<unsigned int>(sortedDataVec.back().first);
+  unsigned int numElem = (unsigned int)sortedDataVec.size();
+
+  int numBits = 0;
+  while ((numBits < 32) && (maxElem >> numBits))
+    numBits++;
+  unsigned int numBytes = 1 + NumBytesUInt(numElem) + ((numElem * numBits + 7) >> 3);
+
+  // go through and count how often the value changes
+  int nLut = 0;
+  for (unsigned int i = 1; i < numElem; i++)
+    if (sortedDataVec[i].first != sortedDataVec[i - 1].first)
+      nLut++;
+
+  int nBitsLut = 0;
+  while (nLut >> nBitsLut)
+    nBitsLut++;
+
+  unsigned int numBitsTotalLut = nLut * numBits;    // num bits w/o the 0
+  unsigned int numBytesLut = 1 + NumBytesUInt(numElem) + 1 + ((numBitsTotalLut + 7) >> 3) + ((numElem * nBitsLut + 7) >> 3);
+
+  doLut = numBytesLut < numBytes;
+  return min(numBytesLut, numBytes);
+}
+
+// -------------------------------------------------------------------------- ;
+// -------------------------------------------------------------------------- ;
+
+void BitStuffer2::BitStuff(Byte** ppByte, const vector<unsigned int>& dataVec, int numBits) const
+{
+  unsigned int numElements = (unsigned int)dataVec.size();
+  unsigned int numUInts = (numElements * numBits + 31) / 32;
+  unsigned int numBytes = numUInts * sizeof(unsigned int);
+  unsigned int* arr = (unsigned int*)(*ppByte);
+
+  memset(arr, 0, numBytes);
+
+  // do the stuffing
+  const unsigned int* srcPtr = &dataVec[0];
+  unsigned int* dstPtr = arr;
+  int bitPos = 0;
+
+  for (unsigned int i = 0; i < numElements; i++)
+  {
+    if (32 - bitPos >= numBits)
+    {
+      unsigned int dstValue;
+      memcpy(&dstValue, dstPtr, sizeof(unsigned int));
+      dstValue |= (*srcPtr++) << (32 - bitPos - numBits);
+      memcpy(dstPtr, &dstValue, sizeof(unsigned int));
+      bitPos += numBits;
+      if (bitPos == 32)    // shift >= 32 is undefined
+      {
+        bitPos = 0;
+        dstPtr++;
+      }
+    }
+    else
+    {
+      unsigned int dstValue;
+      int n = numBits - (32 - bitPos);
+      memcpy(&dstValue, dstPtr, sizeof(unsigned int));
+      dstValue |= (*srcPtr  ) >> n;
+      memcpy(dstPtr, &dstValue, sizeof(unsigned int));
+      dstPtr ++;
+      memcpy(&dstValue, dstPtr, sizeof(unsigned int));
+      dstValue |= (*srcPtr++) << (32 - n);
+      memcpy(dstPtr, &dstValue, sizeof(unsigned int));
+      bitPos = n;
+    }
+  }
+
+  // save the 0-3 bytes not used in the last UInt
+  unsigned int numBytesNotNeeded = NumTailBytesNotNeeded(numElements, numBits);
+  unsigned int n = numBytesNotNeeded;
+  while (n--)
+  {
+    unsigned int dstValue;
+    memcpy(&dstValue, dstPtr, sizeof(unsigned int));
+    dstValue >>= 8;
+    memcpy(dstPtr, &dstValue, sizeof(unsigned int));
+  }
+
+  *ppByte += numBytes - numBytesNotNeeded;
+}
+
+// -------------------------------------------------------------------------- ;
+
+void BitStuffer2::BitUnStuff(const Byte** ppByte, vector<unsigned int>& dataVec,
+                             unsigned int numElements, int numBits) const
+{
+  dataVec.resize(numElements, 0);    // init with 0
+
+  unsigned int numUInts = (numElements * numBits + 31) / 32;
+  unsigned int numBytes = numUInts * sizeof(unsigned int);
+  unsigned int* arr = (unsigned int*)(*ppByte);
+
+  unsigned int* srcPtr = arr;
+  srcPtr += numUInts;
+
+  // needed to save the 0-3 bytes not used in the last UInt
+  srcPtr--;
+  unsigned int lastUInt;
+  memcpy(&lastUInt, srcPtr, sizeof(unsigned int));
+  unsigned int numBytesNotNeeded = NumTailBytesNotNeeded(numElements, numBits);
+  unsigned int n = numBytesNotNeeded;
+  while (n--)
+  {
+    unsigned int srcValue;
+    memcpy(&srcValue, srcPtr, sizeof(unsigned int));
+    srcValue <<= 8;
+    memcpy(srcPtr, &srcValue, sizeof(unsigned int));
+  }
+
+  // do the un-stuffing
+  srcPtr = arr;
+  unsigned int* dstPtr = &dataVec[0];
+  int bitPos = 0;
+
+  for (unsigned int i = 0; i < numElements; i++)
+  {
+    if (32 - bitPos >= numBits)
+    {
+      unsigned int srcValue;
+      memcpy(&srcValue, srcPtr, sizeof(unsigned int));
+      unsigned int n2 = srcValue << bitPos;
+      *dstPtr++ = n2 >> (32 - numBits);
+      bitPos += numBits;
+      if (bitPos == 32)    // shift >= 32 is undefined
+      {
+        bitPos = 0;
+        srcPtr++;
+      }
+    }
+    else
+    {
+      unsigned int srcValue;
+      memcpy(&srcValue, srcPtr, sizeof(unsigned int));
+      srcPtr ++;
+      unsigned int n2 = srcValue << bitPos;
+      *dstPtr = n2 >> (32 - numBits);
+      bitPos -= (32 - numBits);
+      memcpy(&srcValue, srcPtr, sizeof(unsigned int));
+      *dstPtr++ |= srcValue >> (32 - bitPos);
+    }
+  }
+
+  if (numBytesNotNeeded > 0)
+  {
+    memcpy(srcPtr, &lastUInt, sizeof(unsigned int));  // restore the last UInt
+  }
+
+  *ppByte += numBytes - numBytesNotNeeded;
+}
+
+// -------------------------------------------------------------------------- ;
+
+NAMESPACE_LERC_END
diff --git a/frmts/mrf/libLERC/BitStuffer2.h b/frmts/mrf/libLERC/BitStuffer2.h
new file mode 100644
index 0000000..527d6f5
--- /dev/null
+++ b/frmts/mrf/libLERC/BitStuffer2.h
@@ -0,0 +1,143 @@
+
+/*
+Copyright 2015 Esri
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+A local copy of the license and additional notices are located with the
+source distribution at:
+http://github.com/Esri/lerc/
+Contributors:  Thomas Maurer
+*/
+#ifndef BITSTUFFER2_H
+#define BITSTUFFER2_H
+// ---- includes ------------------------------------------------------------ ;
+
+#include "Defines.h"
+#include <vector>
+#include <cstring>
+
+NAMESPACE_LERC_START
+
+// -------------------------------------------------------------------------- ;
+
+// ---- related classes ----------------------------------------------------- ;
+
+// -------------------------------------------------------------------------- ;
+
+/** Bit stuffer, for writing unsigned int arrays compressed lossless
+ *
+ */
+
+class BitStuffer2
+{
+public:
+  BitStuffer2()           {}
+  virtual ~BitStuffer2()  {}
+
+  // these 3 do not allocate memory. Byte ptr is moved like a file pointer.
+  bool EncodeSimple(Byte** ppByte, const std::vector<unsigned int>& dataVec) const;
+  bool EncodeLut(Byte** ppByte, const std::vector<Quant>& sortedDataVec) const;
+  bool Decode(const Byte** ppByte, std::vector<unsigned int>& dataVec) const;
+
+  unsigned int ComputeNumBytesNeededSimple(unsigned int numElem, unsigned int maxElem) const;
+  unsigned int ComputeNumBytesNeededLut(const std::vector<Quant>& sortedDataVec,
+                                         bool& doLut) const;
+
+  static unsigned int NumExtraBytesToAllocate()  { return 3; }
+
+private:
+  mutable std::vector<unsigned int>  m_tmpLutVec, m_tmpIndexVec;
+
+  void BitStuff(Byte** ppByte, const std::vector<unsigned int>& dataVec, int numBits) const;
+  void BitUnStuff(const Byte** ppByte, std::vector<unsigned int>& dataVec, unsigned int numElements, int numBits) const;
+  bool EncodeUInt(Byte** ppByte, unsigned int k, int numBytes) const;     // numBytes = 1, 2, or 4
+  bool DecodeUInt(const Byte** ppByte, unsigned int& k, int numBytes) const;
+  int NumBytesUInt(unsigned int k) const  { return (k < 256) ? 1 : (k < (1 << 16)) ? 2 : 4; }
+  unsigned int NumTailBytesNotNeeded(unsigned int numElem, int numBits) const;
+};
+
+// -------------------------------------------------------------------------- ;
+// -------------------------------------------------------------------------- ;
+
+inline
+unsigned int BitStuffer2::ComputeNumBytesNeededSimple(unsigned int numElem, unsigned int maxElem) const
+{
+  int numBits = 0;
+  while ((numBits < 32) && (maxElem >> numBits))
+    numBits++;
+  return 1 + NumBytesUInt(numElem) + ((numElem * numBits + 7) >> 3);
+}
+
+// -------------------------------------------------------------------------- ;
+
+inline
+bool BitStuffer2::EncodeUInt(Byte** ppByte, unsigned int k, int numBytes) const
+{
+  Byte* ptr = *ppByte;
+
+  if (numBytes == 1)
+    *ptr = (Byte)k;
+  else if (numBytes == 2)
+  {
+    const unsigned short kShort = (unsigned short)k;
+    memcpy(ptr, &kShort, sizeof(unsigned short));
+  }
+  else if (numBytes == 4)
+  {
+    const unsigned int kInt = (unsigned int)k;
+    memcpy(ptr, &kInt, sizeof(unsigned int));
+  }
+  else
+    return false;
+
+  *ppByte += numBytes;
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+inline
+bool BitStuffer2::DecodeUInt(const Byte** ppByte, unsigned int& k, int numBytes) const
+{
+  const Byte* ptr = *ppByte;
+
+  if (numBytes == 1)
+    k = *ptr;
+  else if (numBytes == 2)
+  {
+    unsigned short s;
+    memcpy(&s, ptr, sizeof(unsigned short));
+    k = s;
+  }
+  else if (numBytes == 4)
+  {
+    memcpy(&k, ptr, sizeof(unsigned int));
+  }
+  else
+    return false;
+
+  *ppByte += numBytes;
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+inline
+unsigned int BitStuffer2::NumTailBytesNotNeeded(unsigned int numElem, int numBits) const
+{
+  int numBitsTail = (numElem * numBits) & 31;
+  int numBytesTail = (numBitsTail + 7) >> 3;
+  return (numBytesTail > 0) ? 4 - numBytesTail : 0;
+}
+
+// -------------------------------------------------------------------------- ;
+
+NAMESPACE_LERC_END
+#endif
diff --git a/frmts/mrf/libLERC/CntZImage.cpp b/frmts/mrf/libLERC/CntZImage.cpp
new file mode 100644
index 0000000..ba4b105
--- /dev/null
+++ b/frmts/mrf/libLERC/CntZImage.cpp
@@ -0,0 +1,1251 @@
+/*
+Copyright 2015 Esri
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+A local copy of the license and additional notices are located with the
+source distribution at:
+
+http://github.com/Esri/lerc/
+
+Contributors:  Thomas Maurer
+*/
+
+#include "CntZImage.h"
+#include "BitStuffer.h"
+#include "BitMask.h"
+#include "Defines.h"
+#include <cmath>
+#include <cfloat>
+#include <cstring>
+
+using namespace std;
+
+NAMESPACE_LERC_START
+
+CntZImage::CntZImage()
+{
+  type_ = CNT_Z;
+  memset(&m_infoFromComputeNumBytes, 0, sizeof(m_infoFromComputeNumBytes));
+};
+
+// -------------------------------------------------------------------------- ;
+
+bool CntZImage::resizeFill0(int width, int height)
+{
+  if (!resize(width, height))
+    return false;
+
+  memset(getData(), 0, width * height * sizeof(CntZ));
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool CntZImage::hasValidPixel() const
+{
+  for (int i = 0; i < height_; i++)
+  {
+    const CntZ* ptr = data_ + i * width_;
+    for (int j = 0; j < width_; j++)
+    {
+      if (ptr->cnt > 0)
+        return true;
+      ptr++;
+    }
+  }
+  return false;
+}
+
+// -------------------------------------------------------------------------- ;
+
+void CntZImage::normalize()
+{
+  for (int i = 0; i < height_; i++)
+  {
+    CntZ* ptr = data_ + i * width_;
+    for (int j = 0; j < width_; j++)
+    {
+      if (ptr->cnt > 0)
+      {
+        ptr->z /= ptr->cnt;
+        ptr->cnt = 1;
+      }
+      ptr++;
+    }
+  }
+}
+
+// -------------------------------------------------------------------------- ;
+
+// computes the size of a CntZImage of any width and height, but all void / invalid,
+// and then compressed
+
+unsigned int CntZImage::computeNumBytesNeededToWriteVoidImage()
+{
+  unsigned int cnt = 0;
+
+  CntZImage zImg;
+  cnt += (unsigned int)zImg.getTypeString().length();    // "CntZImage ", 10 bytes
+  cnt += 2 * sizeof(int);
+  cnt += 2 * sizeof(int);
+  cnt += 1 * sizeof(double);
+
+  // cnt part
+  cnt += 3 * sizeof(int);
+  cnt += sizeof(float);
+
+  // z part
+  cnt += 3 * sizeof(int);
+  cnt += sizeof(float);
+  cnt += 1;
+
+  return cnt;
+}
+
+// -------------------------------------------------------------------------- ;
+
+unsigned int CntZImage::computeNumBytesNeededToWrite(double maxZError,
+                                                      bool onlyZPart,
+                                                      InfoFromComputeNumBytes& info) const
+{
+  unsigned int cnt = 0;
+
+  cnt += (unsigned int)getTypeString().length();
+  cnt += 2 * sizeof(int);
+  cnt += 2 * sizeof(int);
+  cnt += 1 * sizeof(double);
+
+  int numTilesVert, numTilesHori, numBytesOpt;
+  float maxValInImg;
+
+  // cnt part first
+  if (!onlyZPart)
+  {
+    float cntMin, cntMax;
+    if (!computeCntStats(0, static_cast<int>(height_), 0, static_cast<int>(width_), cntMin, cntMax))
+      return false;
+
+    bool bCntsNoInt = true;
+    numTilesVert = 0;    // no tiling
+    numTilesHori = 0;
+    maxValInImg = cntMax;
+
+    if (cntMin == cntMax)    // cnt part is const
+    {
+      bCntsNoInt = fabsf(cntMax - (int)(cntMax + 0.5f)) > 0.0001;
+      numBytesOpt = 0;    // nothing else to encode
+    }
+    else
+    {
+      bCntsNoInt = cntsNoInt();
+      if (!bCntsNoInt && cntMin == 0 && cntMax == 1)    // cnt part is binary mask, use fast RLE class
+      {
+        // convert to bit mask
+        BitMask bitMask(width_, height_);
+	// in case bitMask allocation fails
+	if (!bitMask.Size()) return 0;
+        const CntZ* srcPtr = getData();
+        for (int k = 0; k < width_ * height_ ; k++, srcPtr++)
+        {
+          if (srcPtr->cnt <= 0)
+            bitMask.SetInvalid(k);
+	  else
+	    bitMask.SetValid(k);
+        }
+
+        // determine numBytes needed to encode
+	numBytesOpt = static_cast<int>(bitMask.RLEsize());
+      }
+      else
+      {
+        if (!findTiling(false, 0, bCntsNoInt, numTilesVert, numTilesHori, numBytesOpt, maxValInImg))
+          return 0;
+      }
+    }
+
+    info.cntsNoInt       = bCntsNoInt;
+    info.numTilesVertCnt = numTilesVert;
+    info.numTilesHoriCnt = numTilesHori;
+    info.numBytesCnt     = numBytesOpt;
+    info.maxCntInImg     = maxValInImg;
+
+    cnt += 3 * sizeof(int);
+    cnt += sizeof(float);
+    cnt += numBytesOpt;
+  }
+
+  // z part second
+  {
+    if (!findTiling(true, maxZError, false, numTilesVert, numTilesHori, numBytesOpt, maxValInImg))
+    {
+      return 0;
+    }
+
+    info.maxZError     = maxZError;
+    info.numTilesVertZ = numTilesVert;
+    info.numTilesHoriZ = numTilesHori;
+    info.numBytesZ     = numBytesOpt;
+    info.maxZInImg     = maxValInImg;
+
+    cnt += 3 * sizeof(int);
+    cnt += sizeof(float);
+    cnt += numBytesOpt;
+  }
+
+  return cnt;
+}
+
+// -------------------------------------------------------------------------- ;
+// if you change the file format, don't forget to update not only write and
+// read functions, and the file version number, but also the computeNumBytes...
+// and numBytes... functions
+
+bool CntZImage::write(Byte** ppByte,
+                      double maxZError,
+                      bool useInfoFromPrevComputeNumBytes,
+                      bool onlyZPart) const
+{
+  const int version = 11;
+
+  assert(ppByte && *ppByte);
+  if (getSize() == 0)
+    return false;
+
+  int versionSwap = version;
+  int typeSwap    = type_;
+  int heightSwap = static_cast<int>(height_);
+  int widthSwap  = static_cast<int>(width_);
+  double maxZErrorSwap = maxZError;
+
+  SWAP_4(versionSwap);
+  SWAP_4(typeSwap);
+  SWAP_4(heightSwap);
+  SWAP_4(widthSwap);
+  SWAP_8(maxZErrorSwap);
+
+  Byte* ptr = *ppByte;
+
+  memcpy(ptr, getTypeString().c_str(), getTypeString().length());
+  ptr += getTypeString().length();
+
+  memcpy(ptr, &versionSwap, sizeof(int));  ptr += sizeof(int);
+  memcpy(ptr, &typeSwap, sizeof(int));  ptr += sizeof(int);
+  memcpy(ptr, &heightSwap, sizeof(int));  ptr += sizeof(int);
+  memcpy(ptr, &widthSwap, sizeof(int));  ptr += sizeof(int);
+  memcpy(ptr, &maxZErrorSwap, sizeof(double));  ptr += sizeof(double);
+
+  *ppByte = ptr;
+
+  InfoFromComputeNumBytes info;
+  memset(&info, 0, sizeof(InfoFromComputeNumBytes));
+
+  if (useInfoFromPrevComputeNumBytes && (maxZError == m_infoFromComputeNumBytes.maxZError))
+    info = m_infoFromComputeNumBytes;
+  else if (0 == computeNumBytesNeededToWrite(maxZError, onlyZPart, info))
+    return false;
+
+  for (int iPart = 0; iPart < 2; iPart++)
+  {
+    bool zPart = iPart ? true : false;    // first cnt part, then z part
+
+    if (!zPart && onlyZPart)
+      continue;
+
+    bool bCntsNoInt = false;
+    int numTilesVert, numTilesHori, numBytesOpt, numBytesWritten = 0;
+    float maxValInImg;
+
+    if (!zPart)
+    {
+      bCntsNoInt   = info.cntsNoInt;
+      numTilesVert = info.numTilesVertCnt;
+      numTilesHori = info.numTilesHoriCnt;
+      numBytesOpt  = info.numBytesCnt;
+      maxValInImg  = info.maxCntInImg;
+    }
+    else
+    {
+      numTilesVert = info.numTilesVertZ;
+      numTilesHori = info.numTilesHoriZ;
+      numBytesOpt  = info.numBytesZ;
+      maxValInImg  = info.maxZInImg;
+    }
+
+    int numTilesVertSwap = numTilesVert;
+    int numTilesHoriSwap = numTilesHori;
+    int numBytesOptSwap  = numBytesOpt;
+    float maxValInImgSwap = maxValInImg;
+
+    SWAP_4(numTilesVertSwap);
+    SWAP_4(numTilesHoriSwap);
+    SWAP_4(numBytesOptSwap);
+    SWAP_4(maxValInImgSwap);
+
+    ptr = *ppByte;
+    memcpy(ptr, &numTilesVertSwap, sizeof(int));  ptr += sizeof(int);
+    memcpy(ptr, &numTilesHoriSwap, sizeof(int));  ptr += sizeof(int);
+    memcpy(ptr, &numBytesOptSwap, sizeof(int));  ptr += sizeof(int);
+    memcpy(ptr, &maxValInImgSwap, sizeof(float));  ptr += sizeof(float);
+
+    *ppByte = ptr;
+    Byte* bArr = ptr;
+
+    if (!zPart && numTilesVert == 0 && numTilesHori == 0)    // no tiling for cnt part
+    {
+      if (numBytesOpt > 0)    // cnt part is binary mask, use fast RLE class
+      {
+        // convert to bit mask
+        BitMask bitMask(width_, height_);
+        const CntZ* srcPtr = getData();
+        for (int k = 0; k < width_ * height_ ; k++, srcPtr++)
+        {
+	  if (srcPtr->cnt <= 0)
+	    bitMask.SetInvalid(k);
+	  else
+	    bitMask.SetValid(k);
+        }
+
+        // RLE encoding, update numBytesWritten
+	numBytesWritten = static_cast<int>(bitMask.RLEcompress(bArr));
+      }
+    }
+    else
+    {
+      // encode tiles to buffer
+      float maxVal;
+      if (!writeTiles(zPart, maxZError, bCntsNoInt, numTilesVert, numTilesHori,
+	  bArr, numBytesWritten, maxVal))
+        return false;
+    }
+
+    if (numBytesWritten != numBytesOpt)
+      return false;
+
+    *ppByte += numBytesWritten;
+  }
+
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool CntZImage::read(Byte** ppByte,
+                     double maxZError,
+                     bool onlyHeader,
+                     bool onlyZPart)
+{
+  assert(ppByte && *ppByte);
+
+  size_t len = getTypeString().length();
+  string typeStr(len, '0');
+
+  memcpy(&typeStr[0], *ppByte, len);
+  *ppByte += len;
+
+  if (typeStr != getTypeString())
+  {
+    return false;
+  }
+
+  int version = 0, type = 0;
+  int width = 0, height = 0;
+  double maxZErrorInFile = 0;
+
+  Byte* ptr = *ppByte;
+
+  memcpy(&version, ptr, sizeof(int));  ptr += sizeof(int);
+  memcpy(&type, ptr, sizeof(int));  ptr += sizeof(int);
+  memcpy(&height, ptr, sizeof(int));  ptr += sizeof(int);
+  memcpy(&width, ptr, sizeof(int));  ptr += sizeof(int);
+  memcpy(&maxZErrorInFile, ptr, sizeof(double));  ptr += sizeof(double);
+
+  *ppByte = ptr;
+
+  SWAP_4(version);
+  SWAP_4(type);
+  SWAP_4(height);
+  SWAP_4(width);
+  SWAP_8(maxZErrorInFile);
+
+  if (version != 11 || type != type_)
+    return false;
+
+  if (width > 20000 || height > 20000)
+    return false;
+
+  if (maxZErrorInFile > maxZError)
+    return false;
+
+  if (onlyHeader)
+    return true;
+
+  if (!onlyZPart && !resizeFill0(width, height))
+    return false;
+
+  for (int iPart = 0; iPart < 2; iPart++)
+  {
+    bool zPart = iPart ? true : false;    // first cnt part, then z part
+
+    if (!zPart && onlyZPart)
+      continue;
+
+    int numTilesVert = 0, numTilesHori = 0, numBytes = 0;
+    float maxValInImg = 0;
+
+    ptr = *ppByte;
+    memcpy(&numTilesVert, ptr, sizeof(int));  ptr += sizeof(int);
+    memcpy(&numTilesHori, ptr, sizeof(int));  ptr += sizeof(int);
+    memcpy(&numBytes, ptr, sizeof(int));  ptr += sizeof(int);
+    memcpy(&maxValInImg, ptr, sizeof(float));  ptr += sizeof(float);
+
+    *ppByte = ptr;
+    Byte *bArr = ptr;
+
+    SWAP_4(numTilesVert);
+    SWAP_4(numTilesHori);
+    SWAP_4(numBytes);
+    SWAP_4(maxValInImg);
+
+    if (!zPart && numTilesVert == 0 && numTilesHori == 0)    // no tiling for this cnt part
+    {
+      if (numBytes == 0)    // cnt part is const
+      {
+        CntZ* dstPtr = getData();
+        for (int i = 0; i < height_; i++)
+          for (int j = 0; j < width_; j++)
+          {
+            dstPtr->cnt = maxValInImg;
+            dstPtr++;
+          }
+      }
+
+      if (numBytes > 0)    // cnt part is binary mask, RLE compressed
+      {
+        // Read bit mask
+        BitMask bitMask(width_, height_);
+	if (!bitMask.RLEdecompress(bArr))
+	    return false;
+
+	CntZ* dstPtr = getData();
+	for (int k = 0; k < width_ * height_; k++, dstPtr++)
+	  dstPtr->cnt = bitMask.IsValid(k) ? 1.0f:0.0f;
+      }
+    }
+    else if (!readTiles(zPart, maxZErrorInFile, numTilesVert, numTilesHori, maxValInImg, bArr))
+    {
+      return false;
+    }
+
+    *ppByte += numBytes;
+  }
+
+  m_tmpDataVec.clear();
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool CntZImage::findTiling(bool zPart, double maxZError, bool cntsNoIntIn,
+                           int& numTilesVertA,
+                           int& numTilesHoriA,
+                           int& numBytesOptA,
+                           float& maxValInImgA) const
+{
+  const int tileWidthArr[] = {8, 11, 15, 20, 32, 64};
+  const int numConfigs = 6;
+
+  // first, do the entire image as 1 block
+  numTilesVertA = 1;
+  numTilesHoriA = 1;
+  if (!writeTiles(zPart, maxZError, cntsNoIntIn, 1, 1, NULL, numBytesOptA, maxValInImgA))
+  {
+    return false;
+  }
+
+  // if cnt part is constant 1 (all valid), or 0 or -1 (all invalid),
+  // or if all is invalid so z part is empty, then we have to write the header only
+  if (numBytesOptA == (zPart ? numBytesZTile(0, 0, 0, 0) : numBytesCntTile(0, 0, 0, false)))
+  {
+    //printf("block size = %d,  bpp = %f\n", height_ / numTilesVertA, (float)numBytesOptA * 8 / (height_ * width_));
+    return true;
+  }
+
+  int numBytesPrev = 0;
+
+  for (int k = 0; k < numConfigs; k++)
+  {
+    int tileWidth = tileWidthArr[k];
+
+    int numTilesVert = static_cast<int>(height_ / tileWidth);
+    int numTilesHori = static_cast<int>(width_  / tileWidth);
+
+    if (numTilesVert * numTilesHori < 2)
+    {
+      return true;
+    }
+
+    int numBytes = 0;
+    float maxVal;
+    if (!writeTiles(zPart, maxZError, cntsNoIntIn, numTilesVert, numTilesHori, NULL, numBytes, maxVal))
+      return false;
+
+    if (numBytes < numBytesOptA)
+    {
+      numTilesVertA = numTilesVert;
+      numTilesHoriA = numTilesHori;
+      numBytesOptA = numBytes;
+    }
+
+    //printf("  block size = %d,  bpp = %f\n", height_ / numTilesVert, (float)numBytes * 8 / (height_ * width_));
+
+    if (k > 0 && numBytes > numBytesPrev)    // we stop once things get worse by further increasing the block size
+    {
+      //printf("block size = %d,  bpp = %f\n", height_ / numTilesVertA, (float)numBytesOptA * 8 / (height_ * width_));
+      return true;
+    }
+
+    numBytesPrev = numBytes;
+  }
+
+  //printf("block size = %d,  bpp = %f\n", height_ / numTilesVertA, (float)numBytesOptA * 8 / (height_ * width_));
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool CntZImage::writeTiles(bool zPart, double maxZError, bool cntsNoIntIn,
+                           int numTilesVert, int numTilesHori,
+                           Byte* bArr, int& numBytes, float& maxValInImg) const
+{
+  Byte* ptr = bArr;
+  numBytes = 0;
+  maxValInImg = -FLT_MAX;
+
+  for (int iTile = 0; iTile <= numTilesVert; iTile++)
+  {
+    int tileH = static_cast<int>(height_ / numTilesVert);
+    int i0 = iTile * tileH;
+    if (iTile == numTilesVert)
+      tileH = height_ % numTilesVert;
+
+    if (tileH == 0)
+      continue;
+
+    for (int jTile = 0; jTile <= numTilesHori; jTile++)
+    {
+      int tileW = static_cast<int>(width_ / numTilesHori);
+      int j0 = jTile * tileW;
+      if (jTile == numTilesHori)
+        tileW = width_ % numTilesHori;
+
+      if (tileW == 0)
+        continue;
+
+      float cntMin = 0, cntMax = 0, zMin = 0, zMax = 0;
+      int numValidPixel = 0;
+
+      bool rv = zPart ? computeZStats(  i0, i0 + tileH, j0, j0 + tileW, zMin, zMax, numValidPixel) :
+                        computeCntStats(i0, i0 + tileH, j0, j0 + tileW, cntMin, cntMax);
+      if (!rv)
+        return false;
+
+      maxValInImg = zPart ? max(zMax, maxValInImg) : max(cntMax, maxValInImg);
+
+      int numBytesNeeded = zPart ? numBytesZTile(numValidPixel, zMin, zMax, maxZError) :
+                                    numBytesCntTile(tileH * tileW, cntMin, cntMax, cntsNoIntIn);
+      numBytes += numBytesNeeded;
+
+      if (bArr)
+      {
+        int numBytesWritten;
+        rv = zPart ? writeZTile(  &ptr, numBytesWritten, i0, i0 + tileH, j0, j0 + tileW, numValidPixel, zMin, zMax, maxZError) :
+                          writeCntTile(&ptr, numBytesWritten, i0, i0 + tileH, j0, j0 + tileW, cntMin, cntMax, cntsNoIntIn);
+        if (!rv)
+          return false;
+        if (numBytesWritten != numBytesNeeded)
+          return false;
+      }
+    }
+  }
+
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool CntZImage::readTiles(bool zPart, double maxZErrorInFile,
+                          int numTilesVert, int numTilesHori, float maxValInImg,
+                          Byte* bArr)
+{
+  Byte* ptr = bArr;
+
+  for (int iTile = 0; iTile <= numTilesVert; iTile++)
+  {
+    int tileH = static_cast<int>(height_ / numTilesVert);
+    int i0 = iTile * tileH;
+    if (iTile == numTilesVert)
+      tileH = height_ % numTilesVert;
+
+    if (tileH == 0)
+      continue;
+
+    for (int jTile = 0; jTile <= numTilesHori; jTile++)
+    {
+      int tileW = static_cast<int>(width_ / numTilesHori);
+      int j0 = jTile * tileW;
+      if (jTile == numTilesHori)
+        tileW = width_ % numTilesHori;
+
+      if (tileW == 0)
+        continue;
+
+      bool rv = zPart ? readZTile(  &ptr, i0, i0 + tileH, j0, j0 + tileW, maxZErrorInFile, maxValInImg) :
+                        readCntTile(&ptr, i0, i0 + tileH, j0, j0 + tileW);
+
+      if (!rv)
+        return false;
+    }
+  }
+
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool CntZImage::cntsNoInt() const
+{
+  float cntMaxErr = 0;
+  for (int i = 0; i < height_; i++)
+  {
+    const CntZ* ptr = data_ + i * width_;
+    for (int j = 0; j < width_; j++)
+    {
+      float cntErr = fabsf(ptr->cnt - (int)(ptr->cnt + 0.5f));
+      cntMaxErr = max(cntErr, cntMaxErr);
+      ptr++;
+    }
+  }
+  return (cntMaxErr > 0.0001);
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool CntZImage::computeCntStats(int i0, int i1, int j0, int j1,
+                                float& cntMinA, float& cntMaxA) const
+{
+
+  if (i0 < 0 || j0 < 0 || i1 > height_ || j1 > width_)
+    return false;
+
+  // determine cnt ranges
+  float cntMin =  FLT_MAX;
+  float cntMax = -FLT_MAX;
+
+  for (int i = i0; i < i1; i++)
+  {
+    const CntZ* ptr = data_ + i * width_ + j0;
+    for (int j = j0; j < j1; j++)
+    {
+      cntMin = min(ptr->cnt, cntMin);
+      cntMax = max(ptr->cnt, cntMax);
+      ptr++;
+    }
+  }
+
+  cntMinA = cntMin;
+  cntMaxA = cntMax;
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool CntZImage::computeZStats(int i0, int i1, int j0, int j1,
+                              float& zMinA, float& zMaxA, int& numValidPixelA) const
+{
+
+  if (i0 < 0 || j0 < 0 || i1 > height_ || j1 > width_)
+    return false;
+
+  // determine z ranges
+  float zMin =  FLT_MAX;
+  float zMax = -FLT_MAX;
+  int numValidPixel = 0;
+
+  for (int i = i0; i < i1; i++)
+  {
+    const CntZ* ptr = data_ + i * width_ + j0;
+    for (int j = j0; j < j1; j++)
+    {
+      if (ptr->cnt > 0)    // cnt <= 0 means ignore z
+      {
+        zMin = min(ptr->z, zMin);
+        zMax = max(ptr->z, zMax);
+        numValidPixel++;
+      }
+      ptr++;
+    }
+  }
+
+  if (zMin > zMax)
+  {
+    zMin = 0;
+    zMax = 0;
+  }
+
+  zMinA = zMin;
+  zMaxA = zMax;
+  numValidPixelA = numValidPixel;
+
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+int CntZImage::numBytesCntTile(int numPixel, float cntMin, float cntMax, bool cntsNoIntIn) const
+{
+  if (cntMin == cntMax && (cntMin == 0 || cntMin == -1 || cntMin == 1))
+    return 1;
+
+  if (cntsNoIntIn || (cntMax - cntMin) > (1 << 28))
+  {
+    return(int)(1 + numPixel * sizeof(float));
+  }
+  else
+  {
+    unsigned int maxElem = (unsigned int)(cntMax - cntMin + 0.5f);
+    return 1 + numBytesFlt(floorf(cntMin + 0.5f)) + BitStuffer::computeNumBytesNeeded(numPixel, maxElem);
+  }
+}
+
+// -------------------------------------------------------------------------- ;
+
+int CntZImage::numBytesZTile(int numValidPixel, float zMin, float zMax, double maxZError) const
+{
+  if (numValidPixel == 0 || (zMin == 0 && zMax == 0))
+    return 1;
+
+  if (maxZError == 0 || (double)(zMax - zMin) / (2 * maxZError) > (1 << 28))
+  {
+    return(int)(1 + numValidPixel * sizeof(float));
+  }
+  else
+  {
+    unsigned int maxElem = (unsigned int)((double)(zMax - zMin) / (2 * maxZError) + 0.5);
+    if (maxElem == 0)
+      return 1 + numBytesFlt(zMin);
+    else
+      return 1 + numBytesFlt(zMin) + BitStuffer::computeNumBytesNeeded(numValidPixel, maxElem);
+  }
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool CntZImage::writeCntTile(Byte** ppByte, int& numBytes,
+                             int i0, int i1, int j0, int j1,
+                             float cntMin, float cntMax, bool cntsNoIntIn) const
+{
+  Byte* ptr = *ppByte;
+  int numPixel = (i1 - i0) * (j1 - j0);
+
+  if (cntMin == cntMax && (cntMin == 0 || cntMin == -1 || cntMin == 1))    // special case all constant 0, -1, or 1
+  {
+    if (cntMin == 0)
+      *ptr++ = 2;
+    else if (cntMin == -1)
+      *ptr++ = 3;
+    else if (cntMin == 1)
+      *ptr++ = 4;
+
+    numBytes = 1;
+    *ppByte = ptr;
+    return true;
+  }
+
+  if (cntsNoIntIn || cntMax - cntMin > (1 << 28))
+  {
+    // write cnt's as flt arr uncompressed
+    *ptr++ = 0;
+    float* dstPtr = (float*)ptr;
+
+    for (int i = i0; i < i1; i++)
+    {
+      const CntZ* srcPtr = getData() + i * width_ + j0;
+      for (int j = j0; j < j1; j++)
+      {
+        *dstPtr = srcPtr->cnt;
+        SWAP_4(*dstPtr);
+        srcPtr++;
+        dstPtr++;
+      }
+    }
+
+    ptr += numPixel * sizeof(float);
+  }
+  else
+  {
+    // write cnt's as int arr bit stuffed
+    Byte flag = 1;
+    float offset = floorf(cntMin + 0.5f);
+    int n = numBytesFlt(offset);
+    int bits67 = (n == 4) ? 0 : 3 - n;
+    flag |= bits67 << 6;
+
+    *ptr++ = flag;
+
+    if (!writeFlt(&ptr, offset, n))
+      return false;
+
+    vector<unsigned int> dataVec(numPixel, 0);
+    unsigned int* dstPtr = &dataVec[0];
+
+    for (int i = i0; i < i1; i++)
+    {
+      const CntZ* srcPtr = getData() + i * width_ + j0;
+      for (int j = j0; j < j1; j++)
+      {
+        *dstPtr++ = (int)(srcPtr->cnt - offset + 0.5f);
+        srcPtr++;
+      }
+    }
+
+    BitStuffer bitStuffer;
+    if (!bitStuffer.write(&ptr, dataVec))
+      return false;
+  }
+
+  numBytes = (int)(ptr - *ppByte);
+  *ppByte = ptr;
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool CntZImage::writeZTile(Byte** ppByte, int& numBytes,
+                           int i0, int i1, int j0, int j1,
+                           int numValidPixel,
+                           float zMin, float zMax, double maxZError) const
+{
+  Byte* ptr = *ppByte;
+  int cntPixel = 0;
+
+  if (numValidPixel == 0 || (zMin == 0 && zMax == 0))    // special cases
+  {
+    *ptr++ = 2;    // set compression flag to 2 to mark tile as constant 0
+    numBytes = 1;
+    *ppByte = ptr;
+    return true;
+  }
+
+  if (maxZError == 0 ||                                       // user asks lossless OR
+      (double)(zMax - zMin) / (2 * maxZError) > (1 << 28))    // we'd need > 28 bit
+  {
+    // write z's as flt arr uncompressed
+    *ptr++ = 0;
+    float* dstPtr = (float*)ptr;
+
+    for (int i = i0; i < i1; i++)
+    {
+      const CntZ* srcPtr = getData() + i * width_ + j0;
+      for (int j = j0; j < j1; j++)
+      {
+        if (srcPtr->cnt > 0)
+        {
+          *dstPtr = srcPtr->z;
+          SWAP_4(*dstPtr);
+          dstPtr++;
+          cntPixel++;
+        }
+        srcPtr++;
+      }
+    }
+
+    if (cntPixel != numValidPixel)
+      return false;
+
+    ptr += numValidPixel * sizeof(float);
+  }
+  else
+  {
+    // write z's as int arr bit stuffed
+    Byte flag = 1;
+    unsigned int maxElem = (unsigned int)((double)(zMax - zMin) / (2 * maxZError) + 0.5);
+    if (maxElem == 0)
+    {
+      flag = 3;    // set compression flag to 3 to mark tile as constant zMin
+    }
+
+    int n = numBytesFlt(zMin);
+    int bits67 = (n == 4) ? 0 : 3 - n;
+    flag |= bits67 << 6;
+
+    *ptr++ = flag;
+
+    if (!writeFlt(&ptr, zMin, n))
+      return false;
+
+    if (maxElem > 0)
+    {
+      vector<unsigned int> dataVec(numValidPixel, 0);
+      unsigned int* dstPtr = &dataVec[0];
+      double scale = 1 / (2 * maxZError);
+
+      for (int i = i0; i < i1; i++)
+      {
+        const CntZ* srcPtr = getData() + i * width_ + j0;
+        for (int j = j0; j < j1; j++)
+        {
+          if (srcPtr->cnt > 0)
+          {
+            *dstPtr++ = (unsigned int)((srcPtr->z - zMin) * scale + 0.5);
+            cntPixel++;
+          }
+          srcPtr++;
+        }
+      }
+
+      if (cntPixel != numValidPixel)
+        return false;
+
+      BitStuffer bitStuffer;
+      if (!bitStuffer.write(&ptr, dataVec))
+        return false;
+    }
+  }
+
+  numBytes = (int)(ptr - *ppByte);
+  *ppByte = ptr;
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool CntZImage::readCntTile(Byte** ppByte, int i0, int i1, int j0, int j1)
+{
+  Byte* ptr = *ppByte;
+  int numPixel = (i1 - i0) * (j1 - j0);
+
+  Byte comprFlag = *ptr++;
+
+  if (comprFlag == 2)    // entire tile is constant 0 (invalid)
+  {                      // here we depend on resizeFill0()
+    *ppByte = ptr;
+    return true;
+  }
+
+  if (comprFlag == 3 || comprFlag == 4)    // entire tile is constant -1 (invalid) or 1 (valid)
+  {
+    CntZ cz1m = {-1, 0};
+    CntZ cz1p = { 1, 0};
+    CntZ cz1 = (comprFlag == 3) ? cz1m : cz1p;
+
+    for (int i = i0; i < i1; i++)
+    {
+      CntZ* dstPtr = getData() + i * width_ + j0;
+      for (int j = j0; j < j1; j++)
+        *dstPtr++ = cz1;
+    }
+
+    *ppByte = ptr;
+    return true;
+  }
+
+  if ((comprFlag & 63) > 4)
+    return false;
+
+  if (comprFlag == 0)
+  {
+    // read cnt's as flt arr uncompressed
+    const float* srcPtr = (const float*)ptr;
+
+    for (int i = i0; i < i1; i++)
+    {
+      CntZ* dstPtr = getData() + i * width_ + j0;
+      for (int j = j0; j < j1; j++)
+      {
+        dstPtr->cnt = *srcPtr++;
+        SWAP_4(dstPtr->cnt);
+        dstPtr++;
+      }
+    }
+
+    ptr += numPixel * sizeof(float);
+  }
+  else
+  {
+    // read cnt's as int arr bit stuffed
+    int bits67 = comprFlag >> 6;
+    int n = (bits67 == 0) ? 4 : 3 - bits67;
+
+    float offset = 0;
+    if (!readFlt(&ptr, offset, n))
+      return false;
+
+    vector<unsigned int>& dataVec = m_tmpDataVec;
+    BitStuffer bitStuffer;
+    if (!bitStuffer.read(&ptr, dataVec))
+      return false;
+
+    unsigned int* srcPtr = &dataVec[0];
+
+    for (int i = i0; i < i1; i++)
+    {
+      CntZ* dstPtr = getData() + i * width_ + j0;
+      for (int j = j0; j < j1; j++)
+      {
+        dstPtr->cnt = offset + (float)(*srcPtr++);
+        dstPtr++;
+      }
+    }
+  }
+
+  *ppByte = ptr;
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool CntZImage::readZTile(Byte** ppByte, int i0, int i1, int j0, int j1,
+                          double maxZErrorInFile, float maxZInImg)
+{
+  Byte* ptr = *ppByte;
+  int numPixel = 0;
+
+  Byte comprFlag = *ptr++;
+  int bits67 = comprFlag >> 6;
+  comprFlag &= 63;
+
+  if (comprFlag == 2)    // entire zTile is constant 0 (if valid or invalid doesn't matter)
+  {
+    for (int i = i0; i < i1; i++)
+    {
+      CntZ* dstPtr = getData() + i * width_ + j0;
+      for (int j = j0; j < j1; j++)
+      {
+        if (dstPtr->cnt > 0)
+          dstPtr->z = 0;
+        dstPtr++;
+      }
+    }
+
+    *ppByte = ptr;
+    return true;
+  }
+
+  if (comprFlag > 3)
+    return false;
+
+  if (comprFlag == 0)
+  {
+    // read z's as flt arr uncompressed
+    const float* srcPtr = (const float*)ptr;
+
+    for (int i = i0; i < i1; i++)
+    {
+      CntZ* dstPtr = getData() + i * width_ + j0;
+      for (int j = j0; j < j1; j++)
+      {
+        if (dstPtr->cnt > 0)
+        {
+          dstPtr->z = *srcPtr++;
+          SWAP_4(dstPtr->z);
+          numPixel++;
+        }
+        dstPtr++;
+      }
+    }
+
+    ptr += numPixel * sizeof(float);
+  }
+  else
+  {
+    // read z's as int arr bit stuffed
+    int n = (bits67 == 0) ? 4 : 3 - bits67;
+    float offset = 0;
+    if (!readFlt(&ptr, offset, n))
+      return false;
+
+    if (comprFlag == 3)
+    {
+      for (int i = i0; i < i1; i++)
+      {
+        CntZ* dstPtr = getData() + i * width_ + j0;
+        for (int j = j0; j < j1; j++)
+        {
+          if (dstPtr->cnt > 0)
+            dstPtr->z = offset;
+          dstPtr++;
+        }
+      }
+    }
+    else
+    {
+      vector<unsigned int>& dataVec = m_tmpDataVec;
+      BitStuffer bitStuffer;
+      if (!bitStuffer.read(&ptr, dataVec))
+        return false;
+
+      double invScale = 2 * maxZErrorInFile;
+      unsigned int* srcPtr = &dataVec[0];
+
+      for (int i = i0; i < i1; i++)
+      {
+        CntZ* dstPtr = getData() + i * width_ + j0;
+        for (int j = j0; j < j1; j++)
+        {
+          if (dstPtr->cnt > 0)
+          {
+            float z = (float)(offset + *srcPtr++ * invScale);
+            dstPtr->z = min(z, maxZInImg);    // make sure we stay in the orig range
+          }
+          dstPtr++;
+        }
+      }
+    }
+  }
+
+  *ppByte = ptr;
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+int CntZImage::numBytesFlt(float z) const
+{
+  short s = (short)z;
+  signed char c = static_cast<signed char>(s);
+  return ((float)c == z) ? 1 : ((float)s == z) ? 2 : 4;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool CntZImage::writeFlt(Byte** ppByte, float z, int numBytes) const
+{
+  Byte* ptr = *ppByte;
+
+  if (numBytes == 1)
+  {
+    char c = (char)z;
+    *((char*)ptr) = c;
+  }
+  else if (numBytes == 2)
+  {
+    short s = (short)z;
+    SWAP_2(s);
+    *((short*)ptr) = s;
+  }
+  else if (numBytes == 4)
+  {
+    SWAP_4(z);
+    *((float*)ptr) = z;
+  }
+  else
+    return false;
+
+  *ppByte = ptr + numBytes;
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool CntZImage::readFlt(Byte** ppByte, float& z, int numBytes) const
+{
+  Byte* ptr = *ppByte;
+
+  if (numBytes == 1)
+  {
+    char c = *((char*)ptr);
+    z = c;
+  }
+  else if (numBytes == 2)
+  {
+    short s = *((short*)ptr);
+    SWAP_2(s);
+    z = s;
+  }
+  else if (numBytes == 4)
+  {
+    z = *((float*)ptr);
+    SWAP_4(z);
+  }
+  else
+    return false;
+
+  *ppByte = ptr + numBytes;
+  return true;
+}
+
+// ADJUST goes LSB to MSB in bytes, regardless of endianness
+// POFFSET is the relative byte offset for a given type, for native endian
+#if defined BIG_ENDIAN
+#define ADJUST(ptr) (--(ptr))
+#define POFFSET(T) sizeof(T)
+#else
+#define ADJUST(ptr) ((ptr)++)
+#define POFFSET(T) 0
+#endif
+
+#define NEXTBYTE (*(*ppByte)++)
+
+// endianness and alignment safe
+// returns the number of bytes it wrote, adjusts *ppByte
+int CntZImage::writeVal(Byte **ppByte, float z, int numBytes) const
+{
+    assert(ppByte && *ppByte);
+    assert(0 == numBytes || 1 == numBytes || 2 == numBytes || 4 == numBytes);
+
+    short s = (short)z;
+    // Calculate numBytes if needed
+    if (0 == numBytes)
+	numBytes = (z != (float)s) ? 4 : (s != (signed char)s) ? 2 : 1;
+
+    if (4 == numBytes) {
+	// Store as floating point, 4 bytes in LSB order
+	Byte *fp = (Byte *)&z + POFFSET(float);
+	NEXTBYTE = *ADJUST(fp);
+	NEXTBYTE = *ADJUST(fp);
+	NEXTBYTE = *ADJUST(fp);
+	NEXTBYTE = *ADJUST(fp);
+	return 4;
+    }
+
+    // Int types, 2 or 1 bytes
+    NEXTBYTE = (Byte)s; // Lower byte first
+    if (2 == numBytes)
+	NEXTBYTE = (Byte)(s >> 8); // Second byte
+    return numBytes;
+}
+
+// endianness and alignment safe, not alliasing safe
+void CntZImage::readVal(Byte **ppByte, float &val, int numBytes) const
+{
+    assert(numBytes == 4 || numBytes == 2 || numBytes == 1);
+    assert(ppByte && *ppByte);
+    assert(abs(static_cast<int>((Byte *)&val - *ppByte)) >= 4); // Alliasing check
+
+    // Floating point, read the 4 bytes in LSB first order
+    if (4 == numBytes) {
+	Byte *vp = ((Byte*)&val) + POFFSET(float);
+	*ADJUST(vp) = NEXTBYTE;
+	*ADJUST(vp) = NEXTBYTE;
+	*ADJUST(vp) = NEXTBYTE;
+	*ADJUST(vp) = NEXTBYTE;
+	return;
+    }
+
+    int v = (int)((signed char)NEXTBYTE); // Low byte, signed extended
+    if (2 == numBytes)
+	v = (256 * (signed char)NEXTBYTE) | (v & 0xff);
+    val = static_cast<float>(v);
+}
+
+NAMESPACE_LERC_END
diff --git a/frmts/mrf/libLERC/CntZImage.h b/frmts/mrf/libLERC/CntZImage.h
new file mode 100644
index 0000000..0833e54
--- /dev/null
+++ b/frmts/mrf/libLERC/CntZImage.h
@@ -0,0 +1,168 @@
+
+/*
+Copyright 2015 Esri
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+A local copy of the license and additional notices are located with the
+source distribution at:
+http://github.com/Esri/lerc/
+Contributors:  Thomas Maurer
+*/
+
+#ifndef CNTZIMAGE_H
+#define CNTZIMAGE_H
+
+// Define on big endian machines
+// #define BIG_ENDIAN
+
+// ---- includes ------------------------------------------------------------ ;
+
+#include "TImage.hpp"
+#include "BitStuffer.h"
+
+NAMESPACE_LERC_START
+
+// -------------------------------------------------------------------------- ;
+
+// ---- related classes ----------------------------------------------------- ;
+
+//class String;
+
+// -------------------------------------------------------------------------- ;
+
+/**	count / z image
+ *
+ *	count can also be a weight, therefore float;
+ *	z can be elevation or intensity;
+ */
+
+
+class CntZImage : public TImage< CntZ >
+{
+public:
+  CntZImage();
+  const std::string getTypeString() const { return "CntZImage "; }
+
+  bool resizeFill0(int width, int height);
+  bool hasValidPixel() const;
+  void normalize();
+
+  /// binary file IO with optional compression
+  /// (maxZError = 0  means no lossy compression for Z; the Cnt part is compressed lossless or not at all)
+  /// read succeeds only if maxZError on file <= maxZError requested (!)
+
+  unsigned int computeNumBytesNeededToWrite(double maxZError, bool onlyZPart = false)
+    { return computeNumBytesNeededToWrite(maxZError, onlyZPart, m_infoFromComputeNumBytes); }
+
+  static unsigned int numExtraBytesToAllocate()    { return BitStuffer::numExtraBytesToAllocate(); }
+  static unsigned int computeNumBytesNeededToWriteVoidImage();
+
+  /// these 2 do not allocate memory. Byte ptr is moved like a file pointer.
+  bool write(Byte** ppByte,
+             double maxZError = 0,
+             bool useInfoFromPrevComputeNumBytes = false,
+             bool onlyZPart = false) const;
+
+  bool read(Byte** ppByte,
+             double maxZError,
+             bool onlyHeader = false,
+             bool onlyZPart = false);
+
+  template<class T> bool ConvertToMemBlock(T* arr, T noDataValue) const
+  {
+    if (!arr)
+      return false;
+
+    const CntZ* srcPtr = getData();
+    T* dstPtr = arr;
+
+    for (int i = 0; i < height_*width_; i++)
+    {
+      if (srcPtr->cnt > 0)
+	*dstPtr++ = (T)srcPtr->z;
+      else
+	*dstPtr++ = noDataValue;
+      srcPtr++;
+    }
+
+    return true;
+  };
+
+protected:
+
+  struct InfoFromComputeNumBytes
+  {
+    double maxZError;
+    bool cntsNoInt;
+    int numTilesVertCnt;
+    int numTilesHoriCnt;
+    int numBytesCnt;
+    float maxCntInImg;
+    int numTilesVertZ;
+    int numTilesHoriZ;
+    int numBytesZ;
+    float maxZInImg;
+  };
+
+  unsigned int computeNumBytesNeededToWrite(double maxZError, bool onlyZPart,
+    InfoFromComputeNumBytes& info) const;
+
+
+  bool findTiling(bool zPart, double maxZError, bool cntsNoInt,
+    int& numTilesVert, int& numTilesHori, int& numBytesOpt, float& maxValInImg) const;
+
+  bool writeTiles(bool zPart, double maxZError, bool cntsNoInt,
+    int numTilesVert, int numTilesHori, Byte* bArr, int& numBytes, float& maxValInImg) const;
+
+  bool readTiles( bool zPart, double maxZErrorInFile,
+    int numTilesVert, int numTilesHori, float maxValInImg, Byte* bArr);
+
+  bool cntsNoInt() const;
+  bool computeCntStats(int i0, int i1, int j0, int j1, float& cntMin, float& cntMax) const;
+  bool computeZStats(  int i0, int i1, int j0, int j1, float& zMin, float& zMax, int& numValidPixel) const;
+
+  int numBytesCntTile(int numPixel, float cntMin, float cntMax, bool cntsNoInt) const;
+  int numBytesZTile(int numValidPixel, float zMin, float zMax, double maxZError) const;
+
+  bool writeCntTile(Byte** ppByte, int& numBytes, int i0, int i1, int j0, int j1,
+    float cntMin, float cntMax, bool cntsNoInt) const;
+
+  bool writeZTile(Byte** ppByte, int& numBytes, int i0, int i1, int j0, int j1,
+    int numValidPixel, float zMin, float zMax, double maxZError) const;
+
+  bool readCntTile(Byte** ppByte, int i0, int i1, int j0, int j1);
+  bool readZTile(  Byte** ppByte, int i0, int i1, int j0, int j1, double maxZErrorInFile, float maxZInImg);
+
+  int numBytesFlt(float z) const;    // returns 1, 2, or 4
+  // These are not portable on architectures that enforce alignment
+  bool writeFlt(Byte** ppByte, float z, int numBytes) const;
+  bool readFlt( Byte** ppByte, float& z, int numBytes) const;
+
+  // Portable versions of the above, endian independent if BIG_ENDIAN is defined when needed
+
+  // Writes a floating point value as 1 or 2 byte LSB int or 4 byte LSB float
+  // If numBytes is 0, it figures how many bytes to use
+  // returns the number of bytes used
+  int writeVal(Byte** ppByte, float z, int numBytes = 0) const;
+  // Reads from an LSB int for 1, 2 bytes, or LSB float for 4
+  // Not safe when alliased, cannot be used to read in place
+  void readVal(Byte** ppByte, float& z, int numBytes = 4) const;
+
+protected:
+
+  InfoFromComputeNumBytes m_infoFromComputeNumBytes;
+
+  std::vector<unsigned int> m_tmpDataVec;    // used in read fcts
+};
+
+// -------------------------------------------------------------------------- ;
+
+NAMESPACE_LERC_END
+#endif
diff --git a/frmts/mrf/libLERC/Defines.h b/frmts/mrf/libLERC/Defines.h
new file mode 100644
index 0000000..134ef85
--- /dev/null
+++ b/frmts/mrf/libLERC/Defines.h
@@ -0,0 +1,87 @@
+/*
+Copyright 2015 Esri
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+A local copy of the license and additional notices are located with the
+source distribution at:
+http://github.com/Esri/lerc/
+Contributors:
+    Thomas Maurer
+    Lucian Plesea
+*/
+
+#ifndef LERC_DEFINES_H
+#define LERC_DEFINES_H
+
+// For std::pair
+#include <utility>
+#include <cstddef>
+
+// This is useful when compiling within GDAL in DEBUG_BOOL mode, where a
+// MSVCPedanticBool class is used as an alias for the bool type, so as
+// to catch more easily int/bool misuses, even on Linux
+// Also for NULL_AS_NULLPTR mode where NULL is aliased to C++11 nullptr
+#if defined(DEBUG_BOOL) || defined(NULL_AS_NULLPTR)
+#include "cpl_port.h"
+#endif
+
+#define NAMESPACE_LERC_START namespace LercNS {
+#define NAMESPACE_LERC_END }
+#define USING_NAMESPACE_LERC using namespace LercNS;
+
+NAMESPACE_LERC_START
+
+typedef unsigned char Byte;
+
+// unsigned long pair sortable by first
+struct Quant : public std::pair<unsigned int, unsigned int>
+{
+    // This is default behavior in C++14, but not before
+    bool operator<(const Quant& other) const {
+	return first < other.first;
+    }
+};
+
+#ifdef SWAPB    // define this on big endian system
+
+#define LITTLE2LOCAL_ENDIAN_WORD(x) \
+  ( ((*((uint16_t *)(&x)) & 0xff00) >>  8) \
+  | ((*((uint16_t *)(&x)) & 0x00ff) <<  8) )
+
+#define LITTLE2LOCAL_ENDIAN_DWORD(x) \
+  ( ((*((uint32_t *)(&x)) & 0xff000000) >> 24) \
+  | ((*((uint32_t *)(&x)) & 0x00ff0000) >>  8) \
+  | ((*((uint32_t *)(&x)) & 0x0000ff00) <<  8) \
+  | ((*((uint32_t *)(&x)) & 0x000000ff) << 24) )
+
+#define LITTLE2LOCAL_ENDIAN_QWORD(x) \
+  ( ((*((uint64_t *)(&x)) & 0xff00000000000000) >> 56) \
+  | ((*((uint64_t *)(&x)) & 0x00ff000000000000) >> 40) \
+  | ((*((uint64_t *)(&x)) & 0x0000ff0000000000) >> 24) \
+  | ((*((uint64_t *)(&x)) & 0x000000ff00000000) >>  8) \
+  | ((*((uint64_t *)(&x)) & 0x00000000ff000000) <<  8) \
+  | ((*((uint64_t *)(&x)) & 0x0000000000ff0000) << 24) \
+  | ((*((uint64_t *)(&x)) & 0x000000000000ff00) << 40) \
+  | ((*((uint64_t *)(&x)) & 0x00000000000000ff) << 56) )
+
+#define SWAP_2(x) *((uint16_t *)&x) = LITTLE2LOCAL_ENDIAN_WORD(x)
+#define SWAP_4(x) *((uint32_t *)&x) = LITTLE2LOCAL_ENDIAN_DWORD(x)
+#define SWAP_8(x) *((uint64_t *)&x) = LITTLE2LOCAL_ENDIAN_QWORD(x)
+
+#else // SWAPB
+
+#define SWAP_2(x)
+#define SWAP_4(x)
+#define SWAP_8(x)
+
+#endif // SWAPB
+
+NAMESPACE_LERC_END
+#endif
diff --git a/frmts/mrf/libLERC/GNUmakefile b/frmts/mrf/libLERC/GNUmakefile
new file mode 100644
index 0000000..6957eeb
--- /dev/null
+++ b/frmts/mrf/libLERC/GNUmakefile
@@ -0,0 +1,28 @@
+# $Id$
+#
+# Makefile to build zlib using GNU Make and GCC.
+#
+include ../../../GDALmake.opt
+
+OBJ = \
+	BitMask.o\
+	BitMask2.o\
+	BitStuffer.o\
+	BitStuffer2.o\
+	CntZImage.o\
+	Huffman.o\
+	RLE.o\
+	Lerc2.o
+
+O_OBJ   =       $(foreach file,$(OBJ),../../o/$(file))
+
+default:	$(OBJ:.o=.$(OBJ_EXT))
+
+install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f $(O_OBJ) *.a *.o *.lo
+
+../../o/%.$(OBJ_EXT):   %.cpp
+	$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -I../../port $< -o $@
+
diff --git a/frmts/mrf/libLERC/Huffman.cpp b/frmts/mrf/libLERC/Huffman.cpp
new file mode 100644
index 0000000..dc6bd0b
--- /dev/null
+++ b/frmts/mrf/libLERC/Huffman.cpp
@@ -0,0 +1,550 @@
+/*
+Copyright 2015 Esri
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+A local copy of the license and additional notices are located with the
+source distribution at:
+
+http://github.com/Esri/lerc/
+
+Contributors:  Thomas Maurer
+*/
+
+#include "Huffman.h"
+#include "BitStuffer2.h"
+#include <queue>
+#include <cstring>
+#include <algorithm>
+
+using namespace std;
+
+NAMESPACE_LERC_START
+
+// -------------------------------------------------------------------------- ;
+
+bool Huffman::ComputeCodes(const vector<int>& histo)
+{
+  if (histo.empty() || histo.size() >= m_maxHistoSize)
+    return false;
+
+  priority_queue<Node, vector<Node>, less<Node> > pq;
+
+  int numNodes = 0;
+
+  int size = (int)histo.size();
+  for (int i = 0; i < size; i++)    // add all leaf nodes
+    if (histo[i] > 0)
+      pq.push(Node((short)i, histo[i]));
+
+  if (pq.size() < 2)    // histo has only 0 or 1 bin that is not empty; quit Huffman and give it to Lerc
+    return false;
+
+  while (pq.size() > 1)    // build the Huffman tree
+  {
+    Node* child0 = new Node(pq.top());
+    numNodes++;
+    pq.pop();
+    Node* child1 = new Node(pq.top());
+    numNodes++;
+    pq.pop();
+    pq.push(Node(child0, child1));
+  }
+
+  m_codeTable.resize(size);
+  memset(&m_codeTable[0], 0, size * sizeof(m_codeTable[0]));
+  if (!pq.top().TreeToLUT(0, 0, m_codeTable))    // fill the LUT
+    return false;
+
+  Node nodeNonConst = pq.top();
+  nodeNonConst.FreeTree(numNodes);
+
+  if (numNodes != 0)    // check the ref count
+    return false;
+
+  if (!ConvertCodesToCanonical())
+    return false;
+
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool Huffman::ComputeCompressedSize(const std::vector<int>& histo, int& numBytes, double& avgBpp) const
+{
+  if (histo.empty() || histo.size() >= m_maxHistoSize)
+    return false;
+
+  numBytes = 0;
+  if (!ComputeNumBytesCodeTable(numBytes))    // header and code table
+    return false;
+
+  int numBits = 0, numElem = 0;
+  int size = (int)histo.size();
+  for (int i = 0; i < size; i++)
+    if (histo[i] > 0)
+    {
+      numBits += histo[i] * m_codeTable[i].first;
+      numElem += histo[i];
+    }
+
+  /* to please Coverity about potential divide by zero below */
+  if( numElem == 0 )
+    return false;
+
+  int numUInts = ((((numBits + 7) >> 3) + 3) >> 2) + 1;    // add one more as the decode LUT can read ahead
+  numBytes += 4 * numUInts;    // data huffman coded
+  avgBpp = 8 * numBytes / (double)numElem;
+
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool Huffman::SetCodes(const vector<pair<short, unsigned int> >& codeTable)
+{
+  if (codeTable.empty() || codeTable.size() >= m_maxHistoSize)
+    return false;
+
+  m_codeTable = codeTable;
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool Huffman::WriteCodeTable(Byte** ppByte) const
+{
+  if (!ppByte)
+    return false;
+
+  int i0, i1, maxLen;
+  if (!GetRange(i0, i1, maxLen))
+    return false;
+
+  int size = (int)m_codeTable.size();
+  vector<unsigned int> dataVec(i1 - i0, 0);
+
+  for (int i = i0; i < i1; i++)
+  {
+    int k = GetIndexWrapAround(i, size);
+    dataVec[i - i0] = (unsigned int)m_codeTable[k].first;
+  }
+
+  // header
+  vector<int> intVec;
+  intVec.push_back(3);    // huffman version, 3 uses canonical huffman codes
+  intVec.push_back(size);
+  intVec.push_back(i0);   // code range
+  intVec.push_back(i1);
+
+  Byte* ptr = *ppByte;
+
+  for (size_t i = 0; i < intVec.size(); i++)
+  {
+    *((int*)ptr) = intVec[i];
+    ptr += sizeof(int);
+  }
+
+  BitStuffer2 bitStuffer2;
+  if (!bitStuffer2.EncodeSimple(&ptr, dataVec))    // code lengths, bit stuffed
+    return false;
+
+  if (!BitStuffCodes(&ptr, i0, i1))    // variable length codes, bit stuffed
+    return false;
+
+  *ppByte = ptr;
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool Huffman::ReadCodeTable(const Byte** ppByte)
+{
+  if (!ppByte || !(*ppByte))
+    return false;
+
+  const Byte* ptr = *ppByte;
+
+  int version = *((int*)ptr);    // version
+  ptr += sizeof(int);
+
+  if (version < 2) // allow forward compatibility
+    return false;
+
+  vector<int> intVec(4, 0);
+  for (size_t i = 1; i < intVec.size(); i++)
+  {
+    intVec[i] = *((int*)ptr);
+    ptr += sizeof(int);
+  }
+
+  int size = intVec[1];
+  int i0 = intVec[2];
+  int i1 = intVec[3];
+
+  if (i0 >= i1 || size > (int)m_maxHistoSize)
+    return false;
+
+  vector<unsigned int> dataVec(i1 - i0, 0);
+  BitStuffer2 bitStuffer2;
+  if (!bitStuffer2.Decode(&ptr, dataVec))    // unstuff the code lengths
+    return false;
+
+  m_codeTable.resize(size);
+  memset(&m_codeTable[0], 0, size * sizeof(m_codeTable[0]));
+
+  for (int i = i0; i < i1; i++)
+  {
+    int k = GetIndexWrapAround(i, size);
+    m_codeTable[k].first = (short)dataVec[i - i0];
+  }
+
+  if (!BitUnStuffCodes(&ptr, i0, i1))    // unstuff the codes
+    return false;
+
+  *ppByte = ptr;
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool Huffman::BuildTreeFromCodes(int& numBitsLUT)
+{
+  int i0, i1, maxLen;
+  if (!GetRange(i0, i1, maxLen))
+    return false;
+
+  // build decode LUT using max of 12 bits
+  int size = (int)m_codeTable.size();
+
+  bool bNeedTree = maxLen > m_maxNumBitsLUT;
+  numBitsLUT = min(maxLen, m_maxNumBitsLUT);
+
+  m_decodeLUT.clear();
+  m_decodeLUT.assign(1 << numBitsLUT, pair<short, short>((short)-1, (short)-1));
+
+  for (int i = i0; i < i1; i++)
+  {
+    int k = GetIndexWrapAround(i, size);
+    int len = m_codeTable[k].first;
+    if (len > 0 && len <= numBitsLUT)
+    {
+      int code = m_codeTable[k].second << (numBitsLUT - len);
+      pair<short, short> entry((short)len, (short)k);
+      int numEntries = 1 << (numBitsLUT - len);
+      for (int j = 0; j < numEntries; j++)
+        m_decodeLUT[code | j] = entry;    // add the duplicates
+    }
+  }
+
+  if (!bNeedTree)    // decode LUT covers it all, no tree needed
+    return true;
+
+  // go over the codes too long for the LUT and count how many leading bits are 0 for all of them
+  m_numBitsToSkipInTree = 32;
+  for (int i = i0; i < i1; i++)
+  {
+    int k = GetIndexWrapAround(i, size);
+    int len = m_codeTable[k].first;
+
+    if (len > 0 && len > numBitsLUT)    // only codes not in the decode LUT
+    {
+      unsigned int code = m_codeTable[k].second;
+      int shift = 1;
+      while (code >> shift) shift++;
+      m_numBitsToSkipInTree = min(m_numBitsToSkipInTree, len - shift);
+    }
+  }
+
+  int numNodesCreated = 1;
+  Node emptyNode((short)-1, 0);
+
+  if (!m_root)
+    m_root = new Node(emptyNode);
+
+  for (int i = i0; i < i1; i++)
+  {
+    int k = GetIndexWrapAround(i, size);
+    int len = m_codeTable[k].first;
+
+    if (len > 0 && len > numBitsLUT)    // add only codes not in the decode LUT
+    {
+      unsigned int code = m_codeTable[k].second;
+      Node* node = m_root;
+      int j = len - m_numBitsToSkipInTree; // reduce len by number of leading bits from above
+
+      while (--j >= 0)    // go over the bits
+      {
+        if (code & (1 << j))
+        {
+          if (!node->child1)
+          {
+            node->child1 = new Node(emptyNode);
+            numNodesCreated++;
+          }
+          node = node->child1;
+        }
+        else
+        {
+          if (!node->child0)
+          {
+            node->child0 = new Node(emptyNode);
+            numNodesCreated++;
+          }
+          node = node->child0;
+        }
+
+        if (j == 0)    // last bit, leaf node
+        {
+          node->value = (short)k;    // set the value
+        }
+      }
+    }
+  }
+
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+void Huffman::Clear()
+{
+  m_codeTable.clear();
+  m_decodeLUT.clear();
+  if (m_root)
+  {
+    int n = 0;
+    m_root->FreeTree(n);
+    delete m_root;
+    m_root = NULL;
+  }
+}
+
+// -------------------------------------------------------------------------- ;
+// -------------------------------------------------------------------------- ;
+
+bool Huffman::ComputeNumBytesCodeTable(int& numBytes) const
+{
+  int i0, i1, maxLen;
+  if (!GetRange(i0, i1, maxLen))
+    return false;
+
+  int size = (int)m_codeTable.size();
+  int sum = 0;
+  for (int i = i0; i < i1; i++)
+  {
+    int k = GetIndexWrapAround(i, size);
+    sum += m_codeTable[k].first;
+  }
+
+  numBytes = 4 * sizeof(int);    // version, size, first bin, (last + 1) bin
+
+  BitStuffer2 bitStuffer2;
+  numBytes += bitStuffer2.ComputeNumBytesNeededSimple((unsigned int)(i1 - i0), (unsigned int)maxLen);    // code lengths
+  int numUInts = (((sum + 7) >> 3) + 3) >> 2;
+  numBytes += 4 * numUInts;    // byte array with the codes bit stuffed
+
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool Huffman::GetRange(int& i0, int& i1, int& maxCodeLength) const
+{
+  if (m_codeTable.empty() || m_codeTable.size() >= m_maxHistoSize)
+    return false;
+
+  // first, check for peak somewhere in the middle with 0 stretches left and right
+  int size = (int)m_codeTable.size();
+  int i = 0;
+  while (i < size && m_codeTable[i].first == 0) i++;
+  i0 = i;
+  i = size - 1;
+  while (i >= 0 && m_codeTable[i].first == 0) i--;
+  i1 = i + 1;    // exclusive
+
+  if (i1 <= i0)
+    return false;
+
+  // second, cover the common case that the peak is close to 0
+  pair<int, int> segm(0, 0);
+  int j = 0;
+  while (j < size)    // find the largest stretch of 0's, if any
+  {
+    while (j < size && m_codeTable[j].first > 0) j++;
+    int k0 = j;
+    while (j < size && m_codeTable[j].first == 0) j++;
+    int k1 = j;
+
+    if (k1 - k0 > segm.second)
+      segm = pair<int, int>(k0, k1 - k0);
+  }
+
+  if (size - segm.second < i1 - i0)
+  {
+    i0 = segm.first + segm.second;
+    i1 = segm.first + size;    // do wrap around
+  }
+
+  if (i1 <= i0)
+    return false;
+
+  int maxLen = 0;
+  for (i = i0; i < i1; i++)
+  {
+    int k = GetIndexWrapAround(i, size);
+    int len = m_codeTable[k].first;
+    maxLen = max(maxLen, len);
+  }
+
+  if (maxLen <= 0 || maxLen > 32)
+    return false;
+
+  maxCodeLength = maxLen;
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool Huffman::BitStuffCodes(Byte** ppByte, int i0, int i1) const
+{
+  if (!ppByte)
+    return false;
+
+  unsigned int* arr = (unsigned int*)(*ppByte);
+  unsigned int* dstPtr = arr;
+  int size = (int)m_codeTable.size();
+  int bitPos = 0;
+
+  for (int i = i0; i < i1; i++)
+  {
+    int k = GetIndexWrapAround(i, size);
+    int len = m_codeTable[k].first;
+    if (len > 0)
+    {
+      unsigned int val = m_codeTable[k].second;
+
+      if (32 - bitPos >= len)
+      {
+        if (bitPos == 0)
+          *dstPtr = 0;
+
+        *dstPtr |= val << (32 - bitPos - len);
+        bitPos += len;
+        if (bitPos == 32)
+        {
+          bitPos = 0;
+          dstPtr++;
+        }
+      }
+      else
+      {
+        bitPos += len - 32;
+        *dstPtr++ |= val >> bitPos;
+        *dstPtr = val << (32 - bitPos);
+      }
+    }
+  }
+
+  size_t numUInts = dstPtr - arr + (bitPos > 0 ? 1 : 0);
+  *ppByte += numUInts * sizeof(unsigned int);
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool Huffman::BitUnStuffCodes(const Byte** ppByte, int i0, int i1)
+{
+  if (!ppByte || !(*ppByte))
+    return false;
+
+  const unsigned int* arr = (const unsigned int*)(*ppByte);
+  const unsigned int* srcPtr = arr;
+  int size = (int)m_codeTable.size();
+  int bitPos = 0;
+
+  for (int i = i0; i < i1; i++)
+  {
+    int k = GetIndexWrapAround(i, size);
+    int len = m_codeTable[k].first;
+    if (len > 0)
+    {
+      m_codeTable[k].second = ((*srcPtr) << bitPos) >> (32 - len);
+
+      if (32 - bitPos >= len)
+      {
+        bitPos += len;
+        if (bitPos == 32)
+        {
+          bitPos = 0;
+          srcPtr++;
+        }
+      }
+      else
+      {
+        bitPos += len - 32;
+        srcPtr++;
+        m_codeTable[k].second |= (*srcPtr) >> (32 - bitPos);
+      }
+    }
+  }
+
+  size_t numUInts = srcPtr - arr + (bitPos > 0 ? 1 : 0);
+  *ppByte += numUInts * sizeof(unsigned int);
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+struct MyLargerThanOp
+{
+  inline bool operator() (const pair<int, int>& p0, const pair<int, int>& p1)  { return p0.first > p1.first; }
+};
+
+// -------------------------------------------------------------------------- ;
+
+bool Huffman::ConvertCodesToCanonical()
+{
+  // from the non canonical code book, create an array to be sorted in descending order:
+  //   codeLength * tableSize - index
+
+  int tableSize = (int)m_codeTable.size();
+  vector<pair<int, int> > sortVec(tableSize);
+  memset(&sortVec[0], 0, tableSize * sizeof(pair<int, int>));
+
+  for (int i = 0; i < tableSize; i++)
+    if (m_codeTable[i].first > 0)
+      sortVec[i] = pair<int, int>(m_codeTable[i].first * tableSize - i, i);
+
+  // sort descending
+  std::sort(sortVec.begin(), sortVec.end(), MyLargerThanOp());
+
+  // create canonical codes and assign to orig code table
+  unsigned int codeCanonical = 0;
+  int index = sortVec[0].second;
+  short codeLen = m_codeTable[index].first;
+  int i = 0;
+  while (i < tableSize && sortVec[i].first > 0)
+  {
+    index = sortVec[i++].second;
+    short delta = codeLen - m_codeTable[index].first;
+    codeCanonical >>= delta;
+    codeLen -= delta;
+    m_codeTable[index].second = codeCanonical++;
+  }
+
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+NAMESPACE_LERC_END
diff --git a/frmts/mrf/libLERC/Huffman.h b/frmts/mrf/libLERC/Huffman.h
new file mode 100644
index 0000000..1249f88
--- /dev/null
+++ b/frmts/mrf/libLERC/Huffman.h
@@ -0,0 +1,203 @@
+/*
+Copyright 2015 Esri
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+A local copy of the license and additional notices are located with the
+source distribution at:
+
+http://github.com/Esri/lerc/
+
+Contributors:  Thomas Maurer
+*/
+
+#ifndef HUFFMAN_H
+#define HUFFMAN_H
+// ---- includes ------------------------------------------------------------ ;
+
+#include "Defines.h"
+#include <vector>
+
+NAMESPACE_LERC_START
+
+// ---- related classes ----------------------------------------------------- ;
+
+// -------------------------------------------------------------------------- ;
+
+class Huffman
+{
+public:
+  Huffman() : m_maxHistoSize(1 << 15), m_maxNumBitsLUT(12), m_numBitsToSkipInTree(0), m_root(NULL) {};
+  ~Huffman() { Clear(); };
+
+  // Limitation: We limit the max Huffman code length to 32 bit. If this happens, the function ComputeCodes()
+  // returns false. In that case don't use Huffman coding but Lerc only instead.
+  // This won't happen easily. For the worst case input maximizing the Huffman code length the counts in the
+  // histogram have to follow the Fibonacci sequence. Even then, for < 9,227,465 data values, 32 bit is
+  // the max Huffman code length possible.
+
+  bool ComputeCodes(const std::vector<int>& histo);    // input histogram, size < 2^15
+
+  bool ComputeCompressedSize(const std::vector<int>& histo, int& numBytes, double& avgBpp) const;
+
+  // LUT of same size as histogram, each entry has length of Huffman bit code, and the bit code
+  const std::vector<std::pair<short, unsigned int> >& GetCodes() const  { return m_codeTable; }
+  bool SetCodes(const std::vector<std::pair<short, unsigned int> >& codeTable);
+
+  bool WriteCodeTable(Byte** ppByte) const;
+  bool ReadCodeTable(const Byte** ppByte);
+
+  bool BuildTreeFromCodes(int& numBitsLUT);
+  bool DecodeOneValue(const unsigned int** srcPtr, int& bitPos, int numBitsLUT, int& value) const;
+  void Clear();
+
+private:
+
+  struct Node
+  {
+    int weight;
+    short value;
+    Node *child0, *child1;
+
+    Node(short val, int cnt)    // new leaf node for val
+    {
+      value = val;
+      weight = -cnt;
+      child0 = child1 = NULL;
+    }
+
+    Node(Node* c0, Node* c1)    // new internal node from children c0 and c1
+    {
+      value = -1;
+      weight = c0->weight + c1->weight;
+      child0 = c0;
+      child1 = c1;
+    }
+
+    bool operator < (const Node& other) const  { return weight < other.weight; }
+
+    bool TreeToLUT(short numBits, unsigned int bits, std::vector<std::pair<short, unsigned int> >& luTable) const
+    {
+      if (child0)
+      {
+        if (numBits == 32    // the max huffman code length we allow
+          || !child0->TreeToLUT(numBits + 1, (bits << 1) + 0, luTable)
+          || !child1->TreeToLUT(numBits + 1, (bits << 1) + 1, luTable))
+        {
+          return false;
+        }
+      }
+      else
+        luTable[value] = std::pair<short, unsigned int>(numBits, bits);
+
+      return true;
+    }
+
+    void FreeTree(int& n)
+    {
+      if (child0)
+      {
+        child0->FreeTree(n);
+        delete child0;
+        child0 = NULL;
+        n--;
+      }
+      if (child1)
+      {
+        child1->FreeTree(n);
+        delete child1;
+        child1 = NULL;
+        n--;
+      }
+    }
+  };
+
+private:
+
+  size_t m_maxHistoSize;
+  std::vector<std::pair<short, unsigned int> > m_codeTable;
+  std::vector<std::pair<short, short> > m_decodeLUT;
+  int m_maxNumBitsLUT;
+  int m_numBitsToSkipInTree;
+  Node* m_root;
+
+  int GetIndexWrapAround(int i, int size) const  { return i - (i < size ? 0 : size); }
+  bool ComputeNumBytesCodeTable(int& numBytes) const;
+  bool GetRange(int& i0, int& i1, int& maxCodeLength) const;
+  bool BitStuffCodes(Byte** ppByte, int i0, int i1) const;
+  bool BitUnStuffCodes(const Byte** ppByte, int i0, int i1);
+  bool ConvertCodesToCanonical();
+};
+
+// -------------------------------------------------------------------------- ;
+
+inline bool Huffman::DecodeOneValue(const unsigned int** ppSrc, int& bitPos, int numBitsLUT, int& value) const
+{
+  if (!ppSrc || !(*ppSrc) || bitPos < 0 || bitPos > 32)
+    return false;
+
+  // first get the next (up to) 12 bits as a copy
+  /* coverity[large_shift] */
+  int valTmp = ((**ppSrc) << bitPos) >> (32 - numBitsLUT);
+  if (32 - bitPos < numBitsLUT)
+    valTmp |= (*(*ppSrc + 1)) >> (64 - bitPos - numBitsLUT);
+
+  if (m_decodeLUT[valTmp].first >= 0)    // if there, move the correct number of bits and done
+  {
+    value = m_decodeLUT[valTmp].second;
+    bitPos += m_decodeLUT[valTmp].first;
+    if (bitPos >= 32)
+    {
+      bitPos -= 32;
+      (*ppSrc)++;
+    }
+    return true;
+  }
+
+  // if not there, go through the tree (slow)
+
+  if (!m_root)
+    return false;
+
+  // skip leading 0 bits before entering the tree
+  bitPos += m_numBitsToSkipInTree;
+  if (bitPos >= 32)
+  {
+    bitPos -= 32;
+    (*ppSrc)++;
+  }
+
+  const Node* node = m_root;
+  value = -1;
+  while (value < 0)
+  {
+    /* coverity[large_shift] */
+    int bit = ((**ppSrc) << bitPos) >> 31;
+    bitPos++;
+    if (bitPos == 32)
+    {
+      bitPos = 0;
+      (*ppSrc)++;
+    }
+
+    node = bit ? node->child1 : node->child0;
+
+    if (node->value >= 0)    // reached a leaf node
+      value = node->value;
+  }
+
+  return true;
+}
+
+NAMESPACE_LERC_END
+#endif
diff --git a/frmts/mrf/libLERC/Image.h b/frmts/mrf/libLERC/Image.h
new file mode 100644
index 0000000..33d9ac4
--- /dev/null
+++ b/frmts/mrf/libLERC/Image.h
@@ -0,0 +1,88 @@
+/*
+Copyright 2015 Esri
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+A local copy of the license and additional notices are located with the
+source distribution at:
+
+http://github.com/Esri/lerc/
+
+Contributors:  Thomas Maurer
+*/
+
+#ifndef IMAGE_H
+#define IMAGE_H
+
+// ---- includes ------------------------------------------------------------ ;
+#include "Defines.h"
+#include <string>
+
+NAMESPACE_LERC_START
+
+/**	Base class for all image classes
+ *
+ */
+
+class Image
+{
+public:
+
+  virtual ~Image()    {};
+
+  enum Type
+  {
+    BYTE,
+    RGB,
+    SHORT,
+    LONG,
+    FLOAT,
+    DOUBLE,
+    COMPLEX,
+    POINT3F,
+    CNT_Z,
+    CNT_ZXY,
+    Last_Type_
+  };
+
+  bool isType(Type t) const	 { return t == type_; }
+  Type getType() const           { return type_; }
+  int getWidth() const          { return width_; }
+  int getHeight() const         { return height_; }
+  int getSize() const           { return width_ * height_; }
+
+  bool isInside(int row, int col) const
+  {
+      return row >= 0 && row < height_ && col >= 0 && col < width_;
+  }
+
+  const virtual std::string getTypeString() const = 0;
+
+protected:
+
+  Image() : type_(Last_Type_), width_(0), height_(0)   {};
+
+  /// compare
+  bool operator == (const Image& img) const
+  {
+      return type_ == img.type_ && width_ == img.width_ && height_ == img.height_;
+  }
+  bool operator != (const Image& img) const	{ return !operator==(img); };
+
+  Type type_;
+  int width_, height_;
+
+};
+
+NAMESPACE_LERC_END
+#endif
diff --git a/frmts/mrf/libLERC/LICENSE.TXT b/frmts/mrf/libLERC/LICENSE.TXT
new file mode 100644
index 0000000..863d150
--- /dev/null
+++ b/frmts/mrf/libLERC/LICENSE.TXT
@@ -0,0 +1,101 @@
+Apache License - 2.0
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control 
+with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management 
+of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial 
+ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, 
+and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to 
+compiled object code, generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice 
+that is included in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the 
+editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes 
+of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, 
+the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work 
+or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual 
+or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of 
+electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on 
+electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for 
+the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing 
+by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and 
+subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, 
+worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, 
+publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, 
+non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, 
+sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are 
+necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work
+or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You
+under this License for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications,
+and in Source or Object form, provided that You meet the following conditions:
+
+    1. You must give any other recipients of the Work or Derivative Works a copy of this License; and
+
+    2. You must cause any modified files to carry prominent notices stating that You changed the files; and
+
+    3. You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices 
+    from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+
+    4. If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a 
+    readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the 
+    Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the 
+    Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever 
+    such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. 
+    You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, 
+    provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to 
+    Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your 
+    modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with 
+    the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You 
+to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, 
+nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except 
+as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides 
+its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, 
+any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for 
+determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under 
+this License.
+
+8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required
+by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, 
+including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the 
+use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or 
+any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a 
+fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting 
+such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree 
+to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
\ No newline at end of file
diff --git a/frmts/mrf/libLERC/Lerc2.cpp b/frmts/mrf/libLERC/Lerc2.cpp
new file mode 100644
index 0000000..ad4ce6e
--- /dev/null
+++ b/frmts/mrf/libLERC/Lerc2.cpp
@@ -0,0 +1,309 @@
+/*
+Copyright 2015 Esri
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+A local copy of the license and additional notices are located with the
+source distribution at:
+
+http://github.com/Esri/lerc/
+
+Contributors:  Thomas Maurer
+*/
+
+//
+// Lerc2.cpp
+//
+
+#include "Lerc2.h"
+#include <cassert>
+
+using namespace std;
+
+NAMESPACE_LERC_START
+
+// -------------------------------------------------------------------------- ;
+
+Lerc2::Lerc2()
+{
+  Init();
+}
+
+// -------------------------------------------------------------------------- ;
+
+Lerc2::Lerc2(int nCols, int nRows, const Byte* pMaskBits)
+{
+  Init();
+  Set(nCols, nRows, pMaskBits);
+}
+
+// -------------------------------------------------------------------------- ;
+
+void Lerc2::Init()
+{
+  // Lerc 2 only works if size of int is 4 bytes
+  assert(4 == sizeof(int));
+  m_currentVersion    = 2;    // 2: added Huffman coding to 8 bit types DT_Char, DT_Byte;
+  m_microBlockSize    = 8;
+  m_maxValToQuantize  = 0;
+  m_encodeMask        = true;
+  m_writeDataOneSweep = false;
+
+  m_headerInfo.RawInit();
+  m_headerInfo.version = m_currentVersion;
+  m_headerInfo.microBlockSize = m_microBlockSize;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool Lerc2::Set(int nCols, int nRows, const Byte* pMaskBits)
+{
+  if (!m_bitMask.SetSize(nCols, nRows))
+    return false;
+
+  if (pMaskBits)
+  {
+    memcpy(m_bitMask.Bits(), pMaskBits, m_bitMask.Size());
+    m_headerInfo.numValidPixel = m_bitMask.CountValidBits();
+  }
+  else
+  {
+    m_headerInfo.numValidPixel = nCols * nRows;
+    m_bitMask.SetAllValid();
+  }
+
+  m_headerInfo.nCols = nCols;
+  m_headerInfo.nRows = nRows;
+
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool Lerc2::Set(const BitMask2& bitMask)
+{
+  m_bitMask = bitMask;
+
+  m_headerInfo.numValidPixel = m_bitMask.CountValidBits();
+  m_headerInfo.nCols = m_bitMask.GetWidth();
+  m_headerInfo.nRows = m_bitMask.GetHeight();
+
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+unsigned int Lerc2::ComputeNumBytesHeader() const
+{
+  // header
+  unsigned int numBytes = (unsigned int)FileKey().length();
+  numBytes += 7 * sizeof(int);
+  numBytes += 3 * sizeof(double);
+  return numBytes;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool Lerc2::GetHeaderInfo(const Byte* pByte, struct HeaderInfo& headerInfo) const
+{
+  if (!pByte)
+    return false;
+
+  return ReadHeader(&pByte, headerInfo);
+}
+
+// -------------------------------------------------------------------------- ;
+// -------------------------------------------------------------------------- ;
+
+bool Lerc2::WriteHeader(Byte** ppByte) const
+{
+  if (!ppByte)
+    return false;
+
+  string fileKey = FileKey();
+  const HeaderInfo& hd = m_headerInfo;
+
+  vector<int> intVec;
+  intVec.push_back(m_currentVersion);
+  intVec.push_back(hd.nRows);
+  intVec.push_back(hd.nCols);
+  intVec.push_back(hd.numValidPixel);
+  intVec.push_back(hd.microBlockSize);
+  intVec.push_back(hd.blobSize);
+  intVec.push_back((int)hd.dt);
+
+  vector<double> dblVec;
+  dblVec.push_back(hd.maxZError);
+  dblVec.push_back(hd.zMin);
+  dblVec.push_back(hd.zMax);
+
+  Byte* ptr = *ppByte;
+
+  memcpy(ptr, fileKey.c_str(), fileKey.length());
+  ptr += fileKey.length();
+
+  memcpy( ptr, &intVec[0], intVec.size() * sizeof(int) );
+  ptr += intVec.size() * sizeof(int);
+
+  memcpy( ptr, &dblVec[0], dblVec.size() * sizeof(double) );
+  ptr += dblVec.size() * sizeof(double);
+
+  *ppByte = ptr;
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool Lerc2::ReadHeader(const Byte** ppByte, struct HeaderInfo& headerInfo) const
+{
+  if (!ppByte || !*ppByte)
+    return false;
+
+  const Byte* ptr = *ppByte;
+
+  string fileKey = FileKey();
+  HeaderInfo& hd = headerInfo;
+  hd.RawInit();
+
+  if (0 != memcmp(ptr, fileKey.c_str(), fileKey.length()))
+    return false;
+
+  ptr += fileKey.length();
+
+  memcpy(&(hd.version), ptr, sizeof(int));
+  ptr += sizeof(int);
+
+  if (hd.version > m_currentVersion)    // this reader is outdated
+    return false;
+
+  std::vector<int>  intVec(7, 0);
+  std::vector<double> dblVec(3, 0);
+
+  memcpy(&intVec[1], ptr, sizeof(int) * (intVec.size() - 1));
+  ptr += sizeof(int) * (intVec.size() - 1);
+
+  memcpy(&dblVec[0], ptr, sizeof(double) * dblVec.size());
+  ptr += sizeof(double) * dblVec.size();
+
+  hd.nRows          = intVec[1];
+  hd.nCols          = intVec[2];
+  hd.numValidPixel  = intVec[3];
+  hd.microBlockSize = intVec[4];
+  hd.blobSize       = intVec[5];
+  hd.dt             = static_cast<DataType>(intVec[6]);
+
+  hd.maxZError      = dblVec[0];
+  hd.zMin           = dblVec[1];
+  hd.zMax           = dblVec[2];
+
+  *ppByte = ptr;
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool Lerc2::WriteMask(Byte** ppByte) const
+{
+  if (!ppByte)
+    return false;
+
+  int numValid = m_headerInfo.numValidPixel;
+  int numTotal = m_headerInfo.nCols * m_headerInfo.nRows;
+
+  bool needMask = numValid > 0 && numValid < numTotal;
+
+  Byte* ptr = *ppByte;
+
+  if (needMask && m_encodeMask)
+  {
+    Byte* pArrRLE;
+    size_t numBytesRLE;
+    RLE rle;
+    if (!rle.compress((const Byte*)m_bitMask.Bits(), m_bitMask.Size(), &pArrRLE, numBytesRLE, false))
+      return false;
+
+    int numBytesMask = (int)numBytesRLE;
+    memcpy(ptr, &numBytesMask, sizeof(int));    // num bytes for compressed mask
+    ptr += sizeof(int);
+    memcpy(ptr, pArrRLE, numBytesRLE);
+    ptr += numBytesRLE;
+
+    delete[] pArrRLE;
+  }
+  else
+  {
+    memset(ptr, 0, sizeof(int));
+    ptr += sizeof(int);
+  }
+
+  *ppByte = ptr;
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool Lerc2::ReadMask(const Byte** ppByte)
+{
+  if (!ppByte)
+    return false;
+
+  int numValid = m_headerInfo.numValidPixel;
+  int w = m_headerInfo.nCols;
+  int h = m_headerInfo.nRows;
+
+  const Byte* ptr = *ppByte;
+
+  int numBytesMask;
+  memcpy(&numBytesMask, ptr, sizeof(int));
+  ptr += sizeof(int);
+
+  if ((numValid == 0 || numValid == w * h) && (numBytesMask != 0))
+    return false;
+
+  if (!m_bitMask.SetSize(w, h))
+    return false;
+
+  if (numValid == 0)
+    m_bitMask.SetAllInvalid();
+  else if (numValid == w * h)
+    m_bitMask.SetAllValid();
+  else if (numBytesMask > 0)    // read it in
+  {
+    RLE rle;
+    if (!rle.decompress(ptr, m_bitMask.Bits()))
+      return false;
+
+    ptr += numBytesMask;
+  }
+  // else use previous mask
+
+  *ppByte = ptr;
+  return true;
+}
+
+void Lerc2::SortQuantArray(const vector<unsigned int>& quantVec,
+    vector<Quant>& sortedQuantVec) const
+{
+    int numElem = (int)quantVec.size();
+    sortedQuantVec.resize(numElem);
+
+    for (int i = 0; i < numElem; i++) {
+	sortedQuantVec[i].first = quantVec[i];
+	sortedQuantVec[i].second = i;
+    }
+    sort(sortedQuantVec.begin(), sortedQuantVec.end());
+}
+
+// -------------------------------------------------------------------------- ;
+
+NAMESPACE_LERC_END
diff --git a/frmts/mrf/libLERC/Lerc2.h b/frmts/mrf/libLERC/Lerc2.h
new file mode 100644
index 0000000..56558e0
--- /dev/null
+++ b/frmts/mrf/libLERC/Lerc2.h
@@ -0,0 +1,1472 @@
+/*
+Copyright 2015 Esri
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+A local copy of the license and additional notices are located with the
+source distribution at:
+
+http://github.com/Esri/lerc/
+
+Contributors:  Thomas Maurer
+*/
+
+#ifndef LERC2_H
+#define LERC2_H
+
+#include "BitMask2.h"
+#include "BitStuffer2.h"
+#include "Huffman.h"
+#include "RLE.h"
+#include <vector>
+#include <string>
+#include <utility>
+#include <algorithm>
+#include <typeinfo>
+#include <cfloat>
+#include <cmath>
+
+NAMESPACE_LERC_START
+
+#define TryHuffman
+
+/**   Lerc2
+ *
+ *    -- allow for lossless compression of all common data types
+ *    -- avoid data type conversions and copies
+ *    -- optimized compression for segmented rasters (10-15x lossless)
+ *    -- micro block is 8x8 fixed, only gets doubled to 16x16 if bit rate < 1 bpp
+ *    -- cnt is replaced by bit mask
+ *    -- Lerc blob header has data range [min, max]
+ *    -- harden consistency checks to detect if the byte blob has been tampered with
+ *    -- drop support for big endian, this is legacy now
+ *
+ */
+
+class Lerc2
+{
+public:
+  Lerc2();
+  Lerc2(int nCols, int nRows, const Byte* pMaskBits = NULL);    // valid / invalid bits as byte array
+  virtual ~Lerc2()  {}
+
+  bool Set(int nCols, int nRows, const Byte* pMaskBits = NULL);
+  bool Set(const BitMask2& bitMask);
+
+  template<class T>
+  unsigned int ComputeNumBytesNeededToWrite(const T* arr, double maxZError, bool encodeMask);
+
+  unsigned int ComputeNumBytesHeader() const;
+
+  static unsigned int NumExtraBytesToAllocate()  { return BitStuffer2::NumExtraBytesToAllocate(); }
+
+  /// does not allocate memory;  byte ptr is moved like a file pointer
+  template<class T>
+  bool Encode(const T* arr, Byte** ppByte) const;
+
+  // data types supported by Lerc2
+  enum DataType {DT_Char, DT_Byte, DT_Short, DT_UShort, DT_Int, DT_UInt, DT_Float, DT_Double, DT_Undefined};
+
+  struct HeaderInfo
+  {
+    int version,
+        nCols,
+        nRows,
+        numValidPixel,
+        microBlockSize,
+        blobSize;
+    DataType dt;
+    double  zMin,
+            zMax,
+            maxZError;
+
+    void RawInit()  { memset(this, 0, sizeof(struct HeaderInfo)); }
+  };
+
+  bool GetHeaderInfo(const Byte* pByte, struct HeaderInfo& headerInfo) const;
+
+  /// does not allocate memory;  byte ptr is moved like a file pointer
+  template<class T>
+  bool Decode(const Byte** ppByte, T* arr, Byte* pMaskBits = 0);    // if mask ptr is not 0, mask bits are returned (even if all valid or same as previous)
+
+private:
+  int         m_currentVersion,
+              m_microBlockSize,
+              m_maxValToQuantize;
+  BitMask2    m_bitMask;
+  HeaderInfo  m_headerInfo;
+  BitStuffer2 m_bitStuffer2;
+  bool        m_encodeMask,
+              m_writeDataOneSweep;
+
+  mutable std::vector<std::pair<short, unsigned int> > m_huffmanCodes;    // <= 256 codes, 1.5 kB
+
+private:
+  std::string FileKey() const  { return "Lerc2 "; }
+  void Init();
+  bool WriteHeader(Byte** ppByte) const;
+  bool ReadHeader(const Byte** ppByte, struct HeaderInfo& headerInfo) const;
+  bool WriteMask(Byte** ppByte) const;
+  bool ReadMask(const Byte** ppByte);
+
+  template<class T>
+  bool WriteDataOneSweep(const T* data, Byte** ppByte) const;
+
+  template<class T>
+  bool ReadDataOneSweep(const Byte** ppByte, T* data) const;
+
+  template<class T>
+  bool WriteTiles(const T* data, Byte** ppByte, int& numBytes, double& zMinA, double& zMaxA) const;
+
+  template<class T>
+  bool ReadTiles(const Byte** ppByte, T* data) const;
+
+  template<class T>
+  bool ComputeStats(const T* data, int i0, int i1, int j0, int j1,
+                    T& zMinA, T& zMaxA, int& numValidPixelA, bool& tryLutA) const;
+
+  double ComputeMaxVal(double zMin, double zMax, double maxZError) const;
+
+  template<class T>
+  bool NeedToQuantize(int numValidPixel, T zMin, T zMax) const;
+
+  template<class T>
+  bool Quantize(const T* data, int i0, int i1, int j0, int j1, T zMin, int numValidPixel,
+                std::vector<unsigned int>& quantVec) const;
+
+  template<class T>
+  int NumBytesTile(int numValidPixel, T zMin, T zMax, bool& tryLut,
+                   const std::vector<Quant >& sortedQuantVec) const;
+
+  template<class T>
+  bool WriteTile(const T* data, Byte** ppByte, int& numBytesWritten,
+                 int i0, int i1, int j0, int j1, int numValidPixel, T zMin, T zMax,
+                 const std::vector<unsigned int>& quantVec, bool doLut,
+                 const std::vector<Quant >& sortedQuantVec) const;
+
+  template<class T>
+  bool ReadTile(const Byte** ppByte, T* data, int i0, int i1, int j0, int j1,
+                std::vector<unsigned int>& bufferVec) const;
+
+  template<class T>
+  int TypeCode(T z, DataType& dtUsed) const;
+
+  DataType GetDataTypeUsed(int typeCode) const;
+
+  bool WriteVariableDataType(Byte** ppByte, double z, DataType dtUsed) const;
+
+  double ReadVariableDataType(const Byte** ppByte, DataType dtUsed) const;
+
+  template<class T>
+  DataType GetDataType(T z) const;
+
+  unsigned int GetMaxValToQuantize(DataType dt) const;
+
+  void SortQuantArray(const std::vector<unsigned int>& quantVec,
+                      std::vector<Quant>& sortedQuantVec) const;
+
+  template<class T>
+  bool ComputeHistoForHuffman(const T* data, std::vector<int>& histo) const;
+
+  template<class T>
+  bool EncodeHuffman(const T* data, Byte** ppByte, T& zMinA, T& zMaxA) const;
+
+  template<class T>
+  bool DecodeHuffman(const Byte** ppByte, T* data) const;
+
+};
+
+// -------------------------------------------------------------------------- ;
+// -------------------------------------------------------------------------- ;
+
+template<class T>
+unsigned int Lerc2::ComputeNumBytesNeededToWrite(const T* arr, double maxZError, bool encodeMask)
+{
+  if (!arr)
+    return 0;
+
+  // header
+  unsigned int numBytes = (unsigned int)FileKey().length();
+  numBytes += 7 * sizeof(int);
+  numBytes += 3 * sizeof(double);
+
+  // valid / invalid mask
+  int numValid = m_headerInfo.numValidPixel;
+  int numTotal = m_headerInfo.nCols * m_headerInfo.nRows;
+
+  bool needMask = numValid > 0 && numValid < numTotal;
+
+  m_encodeMask = encodeMask;
+
+  numBytes += 1 * sizeof(int);    // the mask encode numBytes
+
+  if (needMask && encodeMask)
+  {
+    RLE rle;
+    size_t n = rle.computeNumBytesRLE((const Byte*)m_bitMask.Bits(), m_bitMask.Size());
+    numBytes += (unsigned int)n;
+  }
+
+  m_headerInfo.dt = GetDataType(arr[0]);
+
+  if (m_headerInfo.dt == DT_Undefined)
+    return 0;
+
+  if (m_headerInfo.dt < DT_Float)
+    maxZError = std::max(0.5, std::floor(maxZError));
+
+  m_headerInfo.maxZError = maxZError;
+  m_headerInfo.zMin = 0;
+  m_headerInfo.zMax = 0;
+  m_headerInfo.microBlockSize = m_microBlockSize;
+  m_headerInfo.blobSize = numBytes;
+
+  if (numValid == 0)
+    return numBytes;
+
+  m_maxValToQuantize = GetMaxValToQuantize(m_headerInfo.dt);
+
+  // data
+  m_writeDataOneSweep = false;
+  int nBytes = 0;
+  Byte* ptr = NULL;    // only emulate the writing and just count the bytes needed
+
+  if (!WriteTiles(arr, &ptr, nBytes, m_headerInfo.zMin, m_headerInfo.zMax))
+    return 0;
+
+  if (m_headerInfo.zMin == m_headerInfo.zMax)    // image is const
+    return numBytes;
+
+  bool bHuffmanLostRun1 = m_huffmanCodes.empty();
+
+  int nBytesOneSweep = (int)(numValid * sizeof(T));
+
+  // if resulting bit rate < x (1 bpp), try with double block size to reduce block header overhead
+  if ((nBytes * 8 < numTotal * 1) && (nBytesOneSweep * 4 > nBytes))
+  {
+    m_headerInfo.microBlockSize = m_microBlockSize * 2;
+    double zMin, zMax;
+    int nBytes2 = 0;
+    if (!WriteTiles(arr, &ptr, nBytes2, zMin, zMax))
+      return 0;
+
+    if (nBytes2 <= nBytes)
+    {
+      nBytes = nBytes2;
+    }
+    else
+    {
+      m_headerInfo.microBlockSize = m_microBlockSize;    // reset to orig
+
+      if (bHuffmanLostRun1)
+        m_huffmanCodes.resize(0);    // if huffman lost on first run, reset it
+    }
+  }
+
+  if (nBytesOneSweep <= nBytes)
+  {
+    m_writeDataOneSweep = true;    // fallback: write data binary uncompressed in one sweep
+    nBytes = nBytesOneSweep;
+  }
+
+  m_headerInfo.blobSize += nBytes + 1;    // nBytes + flag
+  return m_headerInfo.blobSize;
+}
+
+// -------------------------------------------------------------------------- ;
+
+template<class T>
+bool Lerc2::Encode(const T* arr, Byte** ppByte) const
+{
+  if (!arr || !ppByte)
+    return false;
+
+  if (!WriteHeader(ppByte))
+    return false;
+
+  if (!WriteMask(ppByte))
+    return false;
+
+  if (m_headerInfo.numValidPixel == 0)
+    return true;
+
+  if (m_headerInfo.zMin == m_headerInfo.zMax)    // image is const
+    return true;
+
+  if (!m_writeDataOneSweep)
+  {
+    **ppByte = 0;    // write flag
+    (*ppByte)++;
+
+    int numBytes = 0;
+    double zMinA, zMaxA;
+    if (!WriteTiles(arr, ppByte, numBytes, zMinA, zMaxA))
+      return false;
+  }
+  else
+  {
+    **ppByte = 1;    // write flag
+    (*ppByte)++;
+
+    if (!WriteDataOneSweep(arr, ppByte))
+      return false;
+  }
+
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+template<class T>
+bool Lerc2::Decode(const Byte** ppByte, T* arr, Byte* pMaskBits)
+{
+  if (!arr || !ppByte)
+    return false;
+
+  if (!ReadHeader(ppByte, m_headerInfo))
+    return false;
+
+  if (!ReadMask(ppByte))
+    return false;
+
+  if (pMaskBits)    // return proper mask bits even if they were not stored
+    memcpy(pMaskBits, m_bitMask.Bits(), m_bitMask.Size());
+
+  memset(arr, 0, m_headerInfo.nCols * m_headerInfo.nRows * sizeof(T));
+
+  if (m_headerInfo.numValidPixel == 0)
+    return true;
+
+  if (m_headerInfo.zMin == m_headerInfo.zMax)    // image is const
+  {
+    T z0 = (T)m_headerInfo.zMin;
+    for (int i = 0; i < m_headerInfo.nRows; i++)
+    {
+      int k = i * m_headerInfo.nCols;
+      for (int j = 0; j < m_headerInfo.nCols; j++, k++)
+        if (m_bitMask.IsValid(k))
+          arr[k] = z0;
+    }
+    return true;
+  }
+
+  Byte readDataOneSweep = **ppByte;    // read flag
+  (*ppByte)++;
+
+  if (!readDataOneSweep)
+  {
+    if (!ReadTiles(ppByte, arr))
+      return false;
+  }
+  else
+  {
+    if (!ReadDataOneSweep(ppByte, arr))
+      return false;
+  }
+
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+// -------------------------------------------------------------------------- ;
+
+template<class T>
+bool Lerc2::WriteDataOneSweep(const T* data, Byte** ppByte) const
+{
+  T* dstPtr = (T*)(*ppByte);
+  int cntPixel = 0;
+
+  for (int i = 0; i < m_headerInfo.nRows; i++)
+  {
+    int k = i * m_headerInfo.nCols;
+    for (int j = 0; j < m_headerInfo.nCols; j++, k++)
+      if (m_bitMask.IsValid(k))
+      {
+        *dstPtr++ = data[k];
+        cntPixel++;
+      }
+  }
+
+  (*ppByte) += cntPixel * sizeof(T);
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+template<class T>
+bool Lerc2::ReadDataOneSweep(const Byte** ppByte, T* data) const
+{
+  const T* srcPtr = (const T*)(*ppByte);
+  int cntPixel = 0;
+
+  for (int i = 0; i < m_headerInfo.nRows; i++)
+  {
+    int k = i * m_headerInfo.nCols;
+    for (int j = 0; j < m_headerInfo.nCols; j++, k++)
+      if (m_bitMask.IsValid(k))
+      {
+        data[k] = *srcPtr++;
+        cntPixel++;
+      }
+  }
+
+  (*ppByte) += cntPixel * sizeof(T);
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+template<class T>
+bool Lerc2::WriteTiles(const T* data, Byte** ppByte, int& numBytes, double& zMinA, double& zMaxA) const
+{
+  if (!data || !ppByte)
+    return false;
+
+  numBytes = 0;
+  int numBytesLerc = 0;
+  int numBytesHuffman = 0;
+  zMinA = DBL_MAX;
+  zMaxA = -DBL_MAX;
+
+#ifdef TryHuffman
+  if ((m_headerInfo.dt == DT_Byte || m_headerInfo.dt == DT_Char)    // try Huffman coding
+    && m_headerInfo.maxZError == 0.5)    // for lossless only, maybe later extend to lossy, but Byte and lossy is rare
+  {
+    numBytes += 1;    // flag Huffman / Lerc2
+
+    if (!*ppByte)    // compute histo and numBytesHuffman
+    {
+      std::vector<int> histoHuffman;
+      if (!ComputeHistoForHuffman(data, histoHuffman))
+        return false;
+
+      double avgBpp = 0;
+      Huffman huffman;
+      if (huffman.ComputeCodes(histoHuffman)
+       && huffman.ComputeCompressedSize(histoHuffman, numBytesHuffman, avgBpp))
+      {
+        m_huffmanCodes = huffman.GetCodes();    // save Huffman codes for later use
+      }
+      else
+      {
+        m_huffmanCodes.resize(0);    // if huffman fails, go Lerc
+      }
+    }
+    else if (!m_huffmanCodes.empty())   // encode Huffman, not Lerc2
+    {
+      **ppByte = 1;    // write out flag Huffman
+      (*ppByte)++;
+
+      Huffman huffman;
+      if (!huffman.SetCodes(m_huffmanCodes) || !huffman.WriteCodeTable(ppByte))    // header and code table
+        return false;
+
+      T zMin = 0, zMax = 0;
+      if (!EncodeHuffman(data, ppByte, zMin, zMax))    // data bit stuffed
+        return false;
+
+      zMinA = zMin;    // also update stats, to be clean
+      zMaxA = zMax;
+
+      return true;    // done.
+    }
+    else    // encode Lerc2, not Huffman
+    {
+      **ppByte = 0;    // write out flag Lerc2, proceed below with Lerc2 ...
+      (*ppByte)++;
+    }
+  }
+#endif  // TryHuffman
+
+  std::vector<unsigned int> quantVec;
+  std::vector<Quant> sortedQuantVec;
+
+  int mbSize = m_headerInfo.microBlockSize;
+  int height = m_headerInfo.nRows;
+  int width = m_headerInfo.nCols;
+
+  int numTilesVert = (height + mbSize - 1) / mbSize;
+  int numTilesHori = (width + mbSize - 1) / mbSize;
+
+  for (int iTile = 0; iTile < numTilesVert; iTile++)
+  {
+    int tileH = mbSize;
+    int i0 = iTile * tileH;
+    if (iTile == numTilesVert - 1)
+      tileH = height - i0;
+
+    for (int jTile = 0; jTile < numTilesHori; jTile++)
+    {
+      int tileW = mbSize;
+      int j0 = jTile * tileW;
+      if (jTile == numTilesHori - 1)
+        tileW = width - j0;
+
+      T zMin = 0, zMax = 0;
+      int numValidPixel = 0;
+      bool tryLut = false;
+
+      if (!ComputeStats(data, i0, i0 + tileH, j0, j0 + tileW, zMin, zMax,
+	  numValidPixel, tryLut))
+        return false;
+
+      if (numValidPixel > 0)
+      {
+        zMinA = std::min(zMinA, (double)zMin);
+        zMaxA = std::max(zMaxA, (double)zMax);
+      }
+
+      // if needed, quantize the data here once
+      if ((*ppByte || tryLut) && NeedToQuantize(numValidPixel, zMin, zMax))
+      {
+        if (!Quantize(data, i0, i0 + tileH, j0, j0 + tileW, zMin, numValidPixel, quantVec))
+          return false;
+
+        if (tryLut)
+          SortQuantArray(quantVec, sortedQuantVec);
+      }
+
+      int numBytesNeeded = NumBytesTile(numValidPixel, zMin, zMax, tryLut, sortedQuantVec);
+      numBytesLerc += numBytesNeeded;
+
+      if (*ppByte)    // if 0, just count the bytes needed
+      {
+        int numBytesWritten = 0;
+        if (!WriteTile(data, ppByte, numBytesWritten, i0, i0 + tileH, j0, j0 + tileW, numValidPixel, zMin, zMax,
+          quantVec, tryLut, sortedQuantVec))
+        {
+          return false;
+        }
+        if (numBytesWritten != numBytesNeeded)
+        {
+          return false;
+        }
+      }
+    }
+  }
+
+#ifdef TryHuffman
+  if ((m_headerInfo.dt == DT_Byte || m_headerInfo.dt == DT_Char)
+    && m_headerInfo.maxZError == 0.5)    // for lossless only, maybe later extend to lossy, but Byte and lossy is rare
+  {
+    if (!m_huffmanCodes.empty() && numBytesHuffman < numBytesLerc)
+    {
+      numBytes += numBytesHuffman;
+    }
+    else
+    {
+      numBytes += numBytesLerc;
+      m_huffmanCodes.resize(0);
+    }
+    return true;
+  }
+#endif
+
+  numBytes = numBytesLerc;
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+template<class T>
+bool Lerc2::ReadTiles(const Byte** ppByte, T* data) const
+{
+  if (!data || !ppByte || !(*ppByte))
+    return false;
+
+#ifdef TryHuffman
+  if (m_headerInfo.version > 1
+    && (m_headerInfo.dt == DT_Byte || m_headerInfo.dt == DT_Char)    // try Huffman coding
+    && m_headerInfo.maxZError == 0.5)    // for lossless only, maybe later extend to lossy, but Byte and lossy is rare
+  {
+    Byte flag = **ppByte;    // read flag Huffman / Lerc2
+    (*ppByte)++;
+
+    if (flag == 1)    // decode Huffman
+    {
+      Huffman huffman;
+      if (!huffman.ReadCodeTable(ppByte))    // header and code table
+        return false;
+
+      m_huffmanCodes = huffman.GetCodes();
+
+      if (!DecodeHuffman(ppByte, data))    // data
+        return false;
+
+      return true;    // done.
+    }
+    // else decode Lerc2
+  }
+#endif  // TryHuffman
+
+  std::vector<unsigned int> bufferVec;
+
+  int mbSize = m_headerInfo.microBlockSize;
+  int height = m_headerInfo.nRows;
+  int width = m_headerInfo.nCols;
+
+  int numTilesVert = (height + mbSize - 1) / mbSize;
+  int numTilesHori = (width + mbSize - 1) / mbSize;
+
+  for (int iTile = 0; iTile < numTilesVert; iTile++)
+  {
+    int tileH = mbSize;
+    int i0 = iTile * tileH;
+    if (iTile == numTilesVert - 1)
+      tileH = height - i0;
+
+    for (int jTile = 0; jTile < numTilesHori; jTile++)
+    {
+      int tileW = mbSize;
+      int j0 = jTile * tileW;
+      if (jTile == numTilesHori - 1)
+        tileW = width - j0;
+
+      if (!ReadTile(ppByte, data, i0, i0 + tileH, j0, j0 + tileW, bufferVec))
+        return false;
+    }
+  }
+
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+template<class T>
+bool Lerc2::ComputeStats(const T* data, int i0, int i1, int j0, int j1,
+                         T& zMinA, T& zMaxA, int& numValidPixelA, bool& tryLutA) const
+{
+  if (!data || i0 < 0 || j0 < 0 || i1 > m_headerInfo.nRows || j1 > m_headerInfo.nCols)
+    return false;
+
+  tryLutA = false;
+
+  T zMin = 0, zMax = 0, prevVal = 0;
+  int numValidPixel = 0;
+  int cntSameVal = 0;
+
+  for (int i = i0; i < i1; i++)
+  {
+    int k = i * m_headerInfo.nCols + j0;
+
+    for (int j = j0; j < j1; j++, k++)
+      if (m_bitMask.IsValid(k))
+      {
+        T val = data[k];
+        if (numValidPixel > 0)
+        {
+          zMin = std::min(zMin, val);
+          zMax = std::max(zMax, val);
+        }
+        else
+          zMin = zMax = val;    // init
+
+        numValidPixel++;
+
+        if (val == prevVal)
+          cntSameVal++;
+
+        prevVal = val;
+      }
+  }
+
+  if (numValidPixel > 0)
+  {
+    zMinA = zMin;
+    zMaxA = zMax;
+    tryLutA = (zMax > zMin) && (2 * cntSameVal > numValidPixel) && (numValidPixel > 4);
+  }
+
+  numValidPixelA = numValidPixel;
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+inline double Lerc2::ComputeMaxVal(double zMin, double zMax, double maxZError) const
+{
+  double fac = 1 / (2 * maxZError);
+  return (zMax - zMin) * fac;
+}
+
+// -------------------------------------------------------------------------- ;
+
+template<class T>
+bool Lerc2::NeedToQuantize(int numValidPixel, T zMin, T zMax) const
+{
+  if (numValidPixel == 0 || m_headerInfo.maxZError == 0)
+    return false;
+
+  double maxVal = ComputeMaxVal(zMin, zMax, m_headerInfo.maxZError);
+  return !(maxVal > m_maxValToQuantize || (unsigned int)(maxVal + 0.5) == 0);
+}
+
+// -------------------------------------------------------------------------- ;
+
+template<class T>
+bool Lerc2::Quantize(const T* data, int i0, int i1, int j0, int j1, T zMin,
+  int numValidPixel, std::vector<unsigned int>& quantVec) const
+{
+  if (!data || i0 < 0 || j0 < 0 || i1 > m_headerInfo.nRows || j1 > m_headerInfo.nCols)
+    return false;
+
+  quantVec.resize(numValidPixel);
+  unsigned int* dstPtr = &quantVec[0];
+  int cntPixel = 0;
+
+  if (m_headerInfo.dt < DT_Float && m_headerInfo.maxZError == 0.5)    // int lossless
+  {
+    if ((i1 - i0) * (j1 - j0) == numValidPixel)    // all valid
+    {
+      for (int i = i0; i < i1; i++)
+      {
+        int k = i * m_headerInfo.nCols + j0;
+        for (int j = j0; j < j1; j++, k++)
+        {
+          *dstPtr++ = (unsigned int)(data[k] - zMin);
+          cntPixel++;
+        }
+      }
+    }
+    else    // not all valid
+    {
+      for (int i = i0; i < i1; i++)
+      {
+        int k = i * m_headerInfo.nCols + j0;
+        for (int j = j0; j < j1; j++, k++)
+          if (m_bitMask.IsValid(k))
+          {
+            *dstPtr++ = (unsigned int)(data[k] - zMin);
+            cntPixel++;
+          }
+      }
+    }
+  }
+  else    // float and/or lossy
+  {
+    double scale = 1 / (2 * m_headerInfo.maxZError);
+    double zMinDbl = (double)zMin;
+
+    if ((i1 - i0) * (j1 - j0) == numValidPixel)    // all valid
+    {
+      for (int i = i0; i < i1; i++)
+      {
+        int k = i * m_headerInfo.nCols + j0;
+        for (int j = j0; j < j1; j++, k++)
+        {
+          *dstPtr++ = (unsigned int)(((double)data[k] - zMinDbl) * scale + 0.5);
+          //*dstPtr++ = (unsigned int)(((double)(data[k] - zMin) * scale + 0.5));
+          cntPixel++;
+        }
+      }
+    }
+    else    // not all valid
+    {
+      for (int i = i0; i < i1; i++)
+      {
+        int k = i * m_headerInfo.nCols + j0;
+        for (int j = j0; j < j1; j++, k++)
+          if (m_bitMask.IsValid(k))
+          {
+            *dstPtr++ = (unsigned int)(((double)data[k] - zMinDbl) * scale + 0.5);
+            cntPixel++;
+          }
+      }
+    }
+  }
+
+  return (cntPixel == numValidPixel);
+}
+
+// -------------------------------------------------------------------------- ;
+
+template<class T>
+int Lerc2::NumBytesTile(int numValidPixel, T zMin, T zMax, bool& tryLut,  // can get set to false by the function
+                         const std::vector<Quant>& sortedQuantVec) const
+{
+  if (numValidPixel == 0 || (zMin == 0 && zMax == 0))
+    return 1;
+
+  double maxVal, maxZError = m_headerInfo.maxZError;
+
+  if (maxZError == 0 || (maxVal = ComputeMaxVal(zMin, zMax, maxZError)) > m_maxValToQuantize)
+  {
+    return(int)(1 + numValidPixel * sizeof(T));
+  }
+  else
+  {
+    //enum DataType {DT_Char, DT_Byte, DT_Short, DT_UShort, DT_Int, DT_UInt, DT_Float, DT_Double};
+    static const Byte sizeArr[] = {1, 1, 2, 2, 4, 4, 4, 8};
+    DataType dtUsed;
+    TypeCode(zMin, dtUsed); // Called to set dtUsed, return value is ignored
+    int nBytesForMin = sizeArr[dtUsed];
+    int nBytes = 1 + nBytesForMin;
+
+    unsigned int maxElem = (unsigned int)(maxVal + 0.5);
+    if (maxElem > 0)
+    {
+      nBytes += (!tryLut) ? m_bitStuffer2.ComputeNumBytesNeededSimple(numValidPixel, maxElem)
+                          : m_bitStuffer2.ComputeNumBytesNeededLut(sortedQuantVec, tryLut);
+    }
+
+    return nBytes;
+  }
+}
+
+// -------------------------------------------------------------------------- ;
+
+template<class T>
+bool Lerc2::WriteTile(const T* data, Byte** ppByte, int& numBytesWritten,
+                      int i0, int i1, int j0, int j1, int numValidPixel, T zMin, T zMax,
+                      const std::vector<unsigned int>& quantVec, bool doLut,
+                      const std::vector<Quant>& sortedQuantVec) const
+{
+  Byte* ptr = *ppByte;
+  Byte comprFlag = ((j0 >> 3) & 15) << 2;    // use bits 2345 for integrity check
+  int cntPixel = 0;
+
+  if (numValidPixel == 0 || (zMin == 0 && zMax == 0))    // special cases
+  {
+    *ptr++ = comprFlag | 2;    // set compression flag to 2 to mark tile as constant 0
+    numBytesWritten = 1;
+    *ppByte = ptr;
+    return true;
+  }
+
+  double maxVal, maxZError = m_headerInfo.maxZError;
+
+  if (maxZError == 0 || (maxVal = ComputeMaxVal(zMin, zMax, maxZError)) > m_maxValToQuantize)
+  {
+    *ptr++ = comprFlag | 0;    // write z's binary uncompressed
+    T* dstPtr = (T*)ptr;
+
+    for (int i = i0; i < i1; i++)
+    {
+      int k = i * m_headerInfo.nCols + j0;
+      for (int j = j0; j < j1; j++, k++)
+        if (m_bitMask.IsValid(k))
+        {
+          *dstPtr++ = data[k];
+          cntPixel++;
+        }
+    }
+
+    if (cntPixel != numValidPixel)
+      return false;
+
+    ptr += numValidPixel * sizeof(T);
+  }
+  else
+  {
+    // write z's as int arr bit stuffed
+    unsigned int maxElem = (unsigned int)(maxVal + 0.5);
+    if (maxElem == 0)
+      comprFlag |= 3;    // set compression flag to 3 to mark tile as constant zMin
+    else
+      comprFlag |= 1;    // use bit stuffing
+
+    DataType dtUsed;
+    int bits67 = TypeCode(zMin, dtUsed);
+    comprFlag |= bits67 << 6;
+
+    *ptr++ = comprFlag;
+
+    if (!WriteVariableDataType(&ptr, (double)zMin, dtUsed))
+      return false;
+
+    if (maxElem > 0)
+    {
+      if (quantVec.size() != (size_t)numValidPixel)
+        return false;
+
+      if (!doLut)
+      {
+        if (!m_bitStuffer2.EncodeSimple(&ptr, quantVec))
+          return false;
+      }
+      else
+      {
+        if (!m_bitStuffer2.EncodeLut(&ptr, sortedQuantVec))
+          return false;
+      }
+    }
+  }
+
+  numBytesWritten = (int)(ptr - *ppByte);
+  *ppByte = ptr;
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+template<class T>
+bool Lerc2::ReadTile(const Byte** ppByte, T* data, int i0, int i1, int j0, int j1,
+                     std::vector<unsigned int>& bufferVec) const
+{
+  const Byte* ptr = *ppByte;
+  int numPixel = 0;
+
+  Byte comprFlag = *ptr++;
+  int bits67 = comprFlag >> 6;
+  //comprFlag &= 63;
+
+  int testCode = (comprFlag >> 2) & 15;    // use bits 2345 for integrity check
+  if (testCode != ((j0 >> 3) & 15))
+    return false;
+
+  comprFlag &= 3;
+
+  if (comprFlag == 2)    // entire tile is constant 0 (if valid or invalid doesn't matter)
+  {
+    for (int i = i0; i < i1; i++)
+    {
+      int k = i * m_headerInfo.nCols + j0;
+      for (int j = j0; j < j1; j++, k++)
+        if (m_bitMask.IsValid(k))
+          data[k] = 0;
+    }
+
+    *ppByte = ptr;
+    return true;
+  }
+
+  else if (comprFlag == 0)    // read z's binary uncompressed
+  {
+    const T* srcPtr = (const T*)ptr;
+
+    for (int i = i0; i < i1; i++)
+    {
+      int k = i * m_headerInfo.nCols + j0;
+      for (int j = j0; j < j1; j++, k++)
+        if (m_bitMask.IsValid(k))
+        {
+          data[k] = *srcPtr++;
+          numPixel++;
+        }
+    }
+
+    ptr += numPixel * sizeof(T);
+  }
+  else
+  {
+    // read z's as int arr bit stuffed
+    DataType dtUsed = GetDataTypeUsed(bits67);
+    double offset = ReadVariableDataType(&ptr, dtUsed);
+
+    if (comprFlag == 3)
+    {
+      for (int i = i0; i < i1; i++)
+      {
+        int k = i * m_headerInfo.nCols + j0;
+        for (int j = j0; j < j1; j++, k++)
+          if (m_bitMask.IsValid(k))
+            data[k] = (T)offset;
+      }
+    }
+    else
+    {
+      if (!m_bitStuffer2.Decode(&ptr, bufferVec))
+        return false;
+
+      double invScale = 2 * m_headerInfo.maxZError;    // for int types this is int
+      unsigned int* srcPtr = &bufferVec[0];
+
+      if (bufferVec.size() == size_t((i1 - i0) * (j1 - j0)))    // all valid
+      {
+        for (int i = i0; i < i1; i++)
+        {
+          int k = i * m_headerInfo.nCols + j0;
+          for (int j = j0; j < j1; j++, k++)
+          {
+            double z = offset + *srcPtr++ * invScale;
+            data[k] = (T)std::min(z, m_headerInfo.zMax);    // make sure we stay in the orig range
+          }
+        }
+      }
+      else    // not all valid
+      {
+        for (int i = i0; i < i1; i++)
+        {
+          int k = i * m_headerInfo.nCols + j0;
+          for (int j = j0; j < j1; j++, k++)
+            if (m_bitMask.IsValid(k))
+            {
+              double z = offset + *srcPtr++ * invScale;
+              data[k] = (T)std::min(z, m_headerInfo.zMax);    // make sure we stay in the orig range
+            }
+        }
+      }
+    }
+  }
+
+  *ppByte = ptr;
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+template<class T>
+int Lerc2::TypeCode(T z, DataType& dtUsed) const
+{
+  Byte b = (Byte)z;
+  DataType dt = m_headerInfo.dt;
+  switch (dt)
+  {
+    case DT_Short:
+    {
+      char c = (char)z;
+      int tc = (T)c == z ? 2 : (T)b == z ? 1 : 0;
+      dtUsed = (DataType)(dt - tc);
+		  return tc;
+    }
+    case DT_UShort:
+    {
+      int tc = (T)b == z ? 1 : 0;
+      dtUsed = (DataType)(dt - 2 * tc);
+		  return tc;
+    }
+    case DT_Int:
+    {
+      short s = (short)z;
+      unsigned short us = (unsigned short)z;
+      int tc = (T)b == z ? 3 : (T)s == z ? 2 : (T)us == z? 1 : 0;
+      dtUsed = (DataType)(dt - tc);
+      return tc;
+    }
+    case DT_UInt:
+    {
+      unsigned short us = (unsigned short)z;
+      int tc = (T)b == z ? 2 : (T)us == z? 1 : 0;
+      dtUsed = (DataType)(dt - 2 * tc);
+      return tc;
+    }
+    case DT_Float:
+    {
+      short s = (short)z;
+      int tc = (T)b == z ? 2 : (T)s == z? 1 : 0;
+      dtUsed = tc == 0 ? dt : (tc == 1 ? DT_Short : DT_Byte);
+      return tc;
+    }
+    case DT_Double:
+    {
+      short s = (short)z;
+      int l = (int)z;
+      float f = (float)z;
+      int tc = (T)s == z ? 3 : (T)l == z? 2 : (T)f == z ? 1 : 0;
+      dtUsed = tc == 0 ? dt : (DataType)(dt - 2 * tc + 1);
+      return tc;
+    }
+    default:
+    {
+      dtUsed = dt;
+      return 0;
+    }
+  }
+}
+
+// -------------------------------------------------------------------------- ;
+
+inline
+Lerc2::DataType Lerc2::GetDataTypeUsed(int tc) const
+{
+  DataType dt = m_headerInfo.dt;
+  switch (dt)
+  {
+    case DT_Short:
+    case DT_Int:     return (DataType)(dt - tc);
+    case DT_UShort:
+    case DT_UInt:    return (DataType)(dt - 2 * tc);
+    case DT_Float:   return tc == 0 ? dt : (tc == 1 ? DT_Short : DT_Byte);
+    case DT_Double:  return tc == 0 ? dt : (DataType)(dt - 2 * tc + 1);
+    default:
+      return dt;
+  }
+}
+
+// -------------------------------------------------------------------------- ;
+
+inline
+bool Lerc2::WriteVariableDataType(Byte** ppByte, double z, DataType dtUsed) const
+{
+  Byte* ptr = *ppByte;
+
+  switch (dtUsed)
+  {
+    case DT_Char:    *((char*)ptr)           = (char)z;            ptr++;     break;
+    case DT_Byte:    *((Byte*)ptr)           = (Byte)z;            ptr++;     break;
+    case DT_Short: { short s = (short)z;
+                     memcpy(ptr, &s, sizeof(short));
+                     ptr += 2;
+                     break; }
+    case DT_UShort:{ unsigned short us = (unsigned short)z;
+                     memcpy(ptr, &us, sizeof(unsigned short));
+                     ptr += 2;
+                     break; }
+    case DT_Int:   { int i = (int)z;
+                     memcpy(ptr, &i, sizeof(int));
+                     ptr += 4;
+                     break; }
+    case DT_UInt:  { unsigned int n = (unsigned int)z;
+                     memcpy(ptr, &n, sizeof(unsigned int));
+                     ptr += 4;
+                     break; }
+    case DT_Float: { float f = (float)z;
+                     memcpy(ptr, &f, sizeof(float));
+                     ptr += 4;
+                     break; }
+    case DT_Double:  memcpy(ptr, &z, sizeof(double)); ptr += 8;  break;
+    default:
+      return false;
+  }
+
+  *ppByte = ptr;
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+inline
+double Lerc2::ReadVariableDataType(const Byte** ppByte, DataType dtUsed) const
+{
+  const Byte* ptr = *ppByte;
+
+  switch (dtUsed)
+  {
+    case DT_Char:
+    {
+      char c = *((char*)ptr);
+      *ppByte = ptr + 1;
+      return c;
+    }
+    case DT_Byte:
+    {
+      Byte b = *((Byte*)ptr);
+      *ppByte = ptr + 1;
+      return b;
+    }
+    case DT_Short:
+    {
+      short s;
+      memcpy(&s, ptr, sizeof(short));
+      *ppByte = ptr + 2;
+      return s;
+    }
+    case DT_UShort:
+    {
+      unsigned short us;
+      memcpy(&us, ptr, sizeof(unsigned short));
+      *ppByte = ptr + 2;
+      return us;
+    }
+    case DT_Int:
+    {
+      int i;
+      memcpy(&i, ptr, sizeof(int));
+      *ppByte = ptr + 4;
+      return i;
+    }
+    case DT_UInt:
+    {
+      unsigned int n;
+      memcpy(&n, ptr, sizeof(unsigned int));
+      *ppByte = ptr + 4;
+      return n;
+    }
+    case DT_Float:
+    {
+      float f;
+      memcpy(&f, ptr, sizeof(float));
+      *ppByte = ptr + 4;
+      return f;
+    }
+    case DT_Double:
+    {
+      double d;
+      memcpy(&d, ptr, sizeof(double));
+      *ppByte = ptr + 8;
+      return d;
+    }
+    default:
+      return 0;
+  }
+}
+
+// -------------------------------------------------------------------------- ;
+
+template<class T>
+Lerc2::DataType Lerc2::GetDataType(T z) const
+{
+  const std::type_info& ti = typeid(z);
+
+       if (ti == typeid(char))            return DT_Char;
+  else if (ti == typeid(Byte))            return DT_Byte;
+  else if (ti == typeid(short))           return DT_Short;
+  else if (ti == typeid(unsigned short))  return DT_UShort;
+  else if (ti == typeid(int))             return DT_Int;
+  else if (ti == typeid(long)
+       && sizeof(long) == 4)              return DT_Int;
+  else if (ti == typeid(unsigned int))    return DT_UInt;
+  else if (ti == typeid(unsigned long)
+       && sizeof(unsigned long) == 4)     return DT_UInt;
+  else if (ti == typeid(float))           return DT_Float;
+  else if (ti == typeid(double))          return DT_Double;
+  else
+    return DT_Undefined;
+}
+
+// -------------------------------------------------------------------------- ;
+
+inline
+unsigned int Lerc2::GetMaxValToQuantize(Lerc2::DataType dt) const
+{
+  switch (dt)
+  {
+    case DT_Char:
+    case DT_Byte:    //return (1 <<  7) - 1;    // disabled: allow LUT mode for 8 bit segmented
+    case DT_Short:
+    case DT_UShort:  return (1 << 15) - 1;
+
+    case DT_Int:
+    case DT_UInt:
+    case DT_Float:
+    case DT_Double:  return (1 << 30) - 1;
+
+    default:
+      return 0;
+  }
+}
+
+// -------------------------------------------------------------------------- ;
+
+template<class T>
+bool Lerc2::ComputeHistoForHuffman(const T* data, std::vector<int>& histo) const
+{
+  if (!data)
+    return false;
+
+  histo.resize(256);
+  memset(&histo[0], 0, histo.size() * sizeof(histo[0]));
+
+  int offset = (m_headerInfo.dt == DT_Char) ? 128 : 0;
+  int height = m_headerInfo.nRows;
+  int width = m_headerInfo.nCols;
+  T prevVal = 0;
+
+  if (m_headerInfo.numValidPixel == width * height)    // all valid
+  {
+    for (int k = 0, i = 0; i < height; i++)
+      for (int j = 0; j < width; j++, k++)
+      {
+        T val = data[k];
+        T delta = val;
+
+        if (j > 0)
+          delta -= prevVal;    // use overflow
+        else if (i > 0)
+          delta -= data[k - width];
+        else
+          delta -= prevVal;
+
+        prevVal = val;
+        histo[offset + (int)delta]++;
+      }
+  }
+  else    // not all valid
+  {
+    for (int k = 0, i = 0; i < height; i++)
+      for (int j = 0; j < width; j++, k++)
+        if (m_bitMask.IsValid(k))
+        {
+          T val = data[k];
+          T delta = val;
+
+          if (j > 0 && m_bitMask.IsValid(k - 1))
+          {
+            delta -= prevVal;    // use overflow
+          }
+          else if (i > 0 && m_bitMask.IsValid(k - width))
+          {
+            delta -= data[k - width];
+          }
+          else
+            delta -= prevVal;
+
+          prevVal = val;
+          histo[offset + (int)delta]++;
+        }
+  }
+
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+template<class T>
+bool Lerc2::EncodeHuffman(const T* data, Byte** ppByte, T& zMinA, T& zMaxA) const
+{
+  if (!data || !ppByte)
+    return false;
+
+  int offset = (m_headerInfo.dt == DT_Char) ? 128 : 0;
+  zMinA = (T)(offset - 1);
+  zMaxA = (T)(-offset);
+  int height = m_headerInfo.nRows;
+  int width = m_headerInfo.nCols;
+  T prevVal = 0;
+
+  unsigned int* arr = (unsigned int*)(*ppByte);
+  unsigned int* dstPtr = arr;
+  int bitPos = 0;
+
+  for (int k = 0, i = 0; i < height; i++)
+  {
+    for (int j = 0; j < width; j++, k++)
+      if (m_bitMask.IsValid(k))
+      {
+        T val = data[k];
+        T delta = val;
+
+        if (val < zMinA)
+	    zMinA = val;
+        if (val > zMaxA)
+	    zMaxA = val;
+
+        if (j > 0 && m_bitMask.IsValid(k - 1))
+        {
+          delta -= prevVal;    // use overflow
+        }
+        else if (i > 0 && m_bitMask.IsValid(k - width))
+        {
+          delta -= data[k - width];
+        }
+        else
+          delta -= prevVal;
+
+        prevVal = val;
+
+        // bit stuff the huffman code for this delta
+        int len = m_huffmanCodes[offset + (int)delta].first;
+        if (len <= 0)
+          return false;
+
+        unsigned int code = m_huffmanCodes[offset + (int)delta].second;
+
+        if (32 - bitPos >= len)
+        {
+          if (bitPos == 0)
+            *dstPtr = 0;
+
+          *dstPtr |= code << (32 - bitPos - len);
+          bitPos += len;
+          if (bitPos == 32)
+          {
+            bitPos = 0;
+            dstPtr++;
+          }
+        }
+        else
+        {
+          bitPos += len - 32;
+          *dstPtr++ |= code >> bitPos;
+          *dstPtr = code << (32 - bitPos);
+        }
+      }
+  }
+
+  size_t numUInts = dstPtr - arr + (bitPos > 0 ? 1 : 0) + 1;    // add one more as the decode LUT can read ahead
+  *ppByte += numUInts * sizeof(unsigned int);
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+template<class T>
+bool Lerc2::DecodeHuffman(const Byte** ppByte, T* data) const
+{
+  if (!data || !ppByte || !(*ppByte))
+    return false;
+
+  int offset = (m_headerInfo.dt == DT_Char) ? 128 : 0;
+  int height = m_headerInfo.nRows;
+  int width = m_headerInfo.nCols;
+  T prevVal = 0;
+
+  const unsigned int* arr = (const unsigned int*)(*ppByte);
+  const unsigned int* srcPtr = arr;
+  int bitPos = 0;
+  int numBitsLUT = 0;
+
+  Huffman huffman;
+  if (!huffman.SetCodes(m_huffmanCodes) || !huffman.BuildTreeFromCodes(numBitsLUT))
+    return false;
+
+  if (m_headerInfo.numValidPixel == width * height)    // all valid
+  {
+    for (int k = 0, i = 0; i < height; i++)
+      for (int j = 0; j < width; j++, k++)
+      {
+        int val = 0;
+        if (!huffman.DecodeOneValue(&srcPtr, bitPos, numBitsLUT, val))
+          return false;
+
+        T delta = (T)(val - offset);
+
+        if (j > 0)
+          delta += prevVal;    // use overflow
+        else if (i > 0)
+          delta += data[k - width];
+        else
+          delta += prevVal;
+
+        data[k] = delta;
+        prevVal = delta;
+      }
+  }
+  else    // not all valid
+  {
+    for (int k = 0, i = 0; i < height; i++)
+      for (int j = 0; j < width; j++, k++)
+        if (m_bitMask.IsValid(k))
+        {
+          int val = 0;
+          if (!huffman.DecodeOneValue(&srcPtr, bitPos, numBitsLUT, val))
+            return false;
+
+          T delta = (T)(val - offset);
+
+          if (j > 0 && m_bitMask.IsValid(k - 1))
+          {
+            delta += prevVal;    // use overflow
+          }
+          else if (i > 0 && m_bitMask.IsValid(k - width))
+          {
+            delta += data[k - width];
+          }
+          else
+            delta += prevVal;
+
+          data[k] = delta;
+          prevVal = delta;
+        }
+  }
+
+  size_t numUInts = srcPtr - arr + (bitPos > 0 ? 1 : 0) + 1;    // add one more as the decode LUT can read ahead
+  *ppByte += numUInts * sizeof(unsigned int);
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+
+NAMESPACE_LERC_END
+#endif
diff --git a/frmts/mrf/libLERC/NOTICE.TXT b/frmts/mrf/libLERC/NOTICE.TXT
new file mode 100644
index 0000000..56b82e6
--- /dev/null
+++ b/frmts/mrf/libLERC/NOTICE.TXT
@@ -0,0 +1,23 @@
+
+LERC 
+Copyright 2015 Esri
+
+This software embodiment is an implementation of 
+
+United States Patent 9,002,126, Limited Error Raster Compression (LERC). 
+Assignee: Esri. 
+Assignors/Inventors: Maurer, Thomas (Redlands, CA); Gao, Peng (Redlands, CA); Becker, Peter (Redlands, CA). 
+
+The right to practice this patent is hereby granted under the Apache V2.0 License Agreement, Clause 3 - Grant of Patent License for the following fields of use: 
+GIS, terrestrial and extra-terrestrial mapping, and other related earth sciences applications. 
+
+The license is available at 
+http://github.com/Esri/lerc/
+
+For additional information, contact:
+
+Environmental Systems Research Institute, Inc.
+Attn: Contracts and Legal Department
+380 New York Street
+Redlands, CA 92373
+E-mail: contracts at esri.com
diff --git a/frmts/mrf/libLERC/RLE.cpp b/frmts/mrf/libLERC/RLE.cpp
new file mode 100644
index 0000000..f014660
--- /dev/null
+++ b/frmts/mrf/libLERC/RLE.cpp
@@ -0,0 +1,326 @@
+/*
+Copyright 2015 Esri
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+A local copy of the license and additional notices are located with the
+source distribution at:
+
+http://github.com/Esri/lerc/
+
+Contributors:  Thomas Maurer
+*/
+#include "RLE.h"
+#include <cstring>
+
+NAMESPACE_LERC_START
+
+// -------------------------------------------------------------------------- ;
+
+size_t RLE::computeNumBytesRLE(const Byte* arr, size_t numBytes) const
+{
+  if (arr == NULL || numBytes == 0)
+    return 0;
+
+  const Byte* ptr = arr;
+  size_t sum = 0;
+  size_t cntOdd = 0;
+  size_t cntEven = 0;
+  size_t cntTotal = 0;
+  bool bOdd = true;
+
+  while (cntTotal < numBytes - 1)
+  {
+    if (*ptr != *(ptr + 1))
+    {
+      if (bOdd)
+      {
+        cntOdd++;
+      }
+      else    // switch to odd mode
+      {
+        cntEven++;
+        sum += 2 + 1;
+        bOdd = true;
+        cntOdd = 0;
+        cntEven = 0;
+      }
+    }
+    else
+    {
+      if (!bOdd)
+      {
+        cntEven++;
+      }
+      else
+      {
+        // count if we have enough equal bytes so it is worth switching to even
+        bool foundEnough = false;
+        if (cntTotal + m_minNumEven < numBytes)
+        {
+          int i = 1;
+          while (i < m_minNumEven && ptr[i] == ptr[0]) i++;
+          foundEnough = i < m_minNumEven ? false : true;
+        }
+
+        if (!foundEnough)    // stay in odd mode
+        {
+          cntOdd++;
+        }
+        else    // switch to even mode
+        {
+          if (cntOdd > 0)
+            sum += 2 + cntOdd;
+          bOdd = false;
+          cntOdd = 0;
+          cntEven = 0;
+          cntEven++;
+        }
+      }
+    }
+    ptr++;
+    cntTotal++;
+
+    if (cntOdd == 32767)    // prevent short counters from overflow
+    {
+      sum += 2 + 32767;
+      cntOdd = 0;
+    }
+    if (cntEven == 32767)
+    {
+      sum += 2 + 1;
+      cntEven = 0;
+    }
+  }
+
+  // don't forget the last byte
+  if (bOdd)
+  {
+    cntOdd++;
+    sum += 2 + cntOdd;
+  }
+  else
+  {
+    cntEven++;
+    sum += 2 + 1;
+  }
+
+  return sum + 2;    // EOF short
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool RLE::compress(const Byte* arr, size_t numBytes,
+                   Byte** arrRLE, size_t& numBytesRLE, bool verify) const
+{
+  if (arr == NULL || numBytes == 0)
+    return false;
+
+  numBytesRLE = computeNumBytesRLE(arr, numBytes);
+
+  *arrRLE = new Byte[numBytesRLE];
+  if (!*arrRLE)
+    return false;
+
+  const Byte* srcPtr = arr;
+  Byte* cntPtr = *arrRLE;
+  Byte* dstPtr = cntPtr + 2;
+  size_t cntOdd = 0;
+  size_t cntEven = 0;
+  size_t cntTotal = 0;
+  bool bOdd = true;
+
+  while (cntTotal < numBytes - 1)
+  {
+    if (*srcPtr != *(srcPtr + 1))
+    {
+      *dstPtr++ = *srcPtr;
+      if (bOdd)
+      {
+        cntOdd++;
+      }
+      else    // switch to odd mode
+      {
+        cntEven++;
+        writeCount(-(short)cntEven, &cntPtr, &dstPtr);    // - sign for even cnts
+        bOdd = true;
+        cntOdd = 0;
+        cntEven = 0;
+      }
+    }
+    else
+    {
+      if (!bOdd)
+      {
+        cntEven++;
+      }
+      else
+      {
+        // count if we have enough equal bytes so it is worth switching to even
+        bool foundEnough = false;
+        if (cntTotal + m_minNumEven < numBytes)
+        {
+          int i = 1;
+          while (i < m_minNumEven && srcPtr[i] == srcPtr[0]) i++;
+          foundEnough = i < m_minNumEven ? false : true;
+        }
+
+        if (!foundEnough)    // stay in odd mode
+        {
+          *dstPtr++ = *srcPtr;
+          cntOdd++;
+        }
+        else    // switch to even mode
+        {
+          if (cntOdd > 0)
+          {
+            writeCount((short)cntOdd, &cntPtr, &dstPtr);    // + sign for odd cnts
+          }
+          bOdd = false;
+          cntOdd = 0;
+          cntEven = 0;
+          cntEven++;
+        }
+      }
+    }
+
+    if (cntOdd == 32767)    // prevent short counters from overflow
+    {
+      writeCount((short)cntOdd, &cntPtr, &dstPtr);
+      cntOdd = 0;
+    }
+    if (cntEven == 32767)
+    {
+      *dstPtr++ = *srcPtr;
+      writeCount(-(short)cntEven, &cntPtr, &dstPtr);
+      cntEven = 0;
+    }
+
+    srcPtr++;
+    cntTotal++;
+  }
+
+  // don't forget the last byte
+  *dstPtr++ = *srcPtr;
+  if (bOdd)
+  {
+    cntOdd++;
+    writeCount((short)cntOdd, &cntPtr, &dstPtr);
+  }
+  else
+  {
+    cntEven++;
+    writeCount(-(short)cntEven, &cntPtr, &dstPtr);
+  }
+
+  writeCount(-32768, &cntPtr, &dstPtr);    // write end of stream symbol
+
+  if (verify)
+  {
+    Byte* arr2 = NULL;
+    size_t numBytes2 = 0;
+    if (!decompress(*arrRLE, &arr2, numBytes2) || numBytes2 != numBytes)
+    {
+      delete[] arr2;
+      return false;
+    }
+    int nCheck = memcmp(arr, arr2, numBytes);
+    delete[] arr2;
+    if (nCheck != 0)
+      return false;
+  }
+
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool RLE::decompress(const Byte* arrRLE, Byte** arr, size_t& numBytes) const
+{
+  if (!arrRLE)
+    return false;
+
+  // first count the encoded bytes
+  const Byte* srcPtr = arrRLE;
+  size_t sum = 0;
+  short cnt = readCount(&srcPtr);
+  while (cnt != -32768)
+  {
+    sum += (cnt < 0) ? -cnt : cnt;
+    srcPtr += (cnt > 0) ? cnt : 1;
+    cnt = readCount(&srcPtr);
+  }
+
+  numBytes = sum;
+  if( numBytes == 0 )
+  {
+    *arr = NULL;
+    return true;
+  }
+  *arr = new Byte[numBytes];
+  if (!*arr)
+    return false;
+
+  return decompress(arrRLE, *arr);
+}
+
+// -------------------------------------------------------------------------- ;
+
+bool RLE::decompress(const Byte* arrRLE, Byte* arr) const
+{
+  if (!arrRLE || !arr)
+    return false;
+
+  const Byte* srcPtr = arrRLE;
+  Byte* dstPtr = arr;
+  short cnt = readCount(&srcPtr);
+  while (cnt != -32768)
+  {
+    int i = (cnt < 0) ? -cnt: cnt ;
+    if (cnt > 0)
+      while (i--) *dstPtr++ = *srcPtr++;
+    else
+    {
+      Byte b = *srcPtr++;
+      while (i--) *dstPtr++ = b;
+    }
+    cnt = readCount(&srcPtr);
+  }
+
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+void RLE::writeCount(short cnt, Byte** ppCnt, Byte** ppDst) const
+{
+  SWAP_2(cnt);    // write short's in little endian byte order, always
+  memcpy(*ppCnt, &cnt, sizeof(short));
+  *ppCnt = *ppDst;
+  *ppDst += 2;
+}
+
+// -------------------------------------------------------------------------- ;
+
+short RLE::readCount(const Byte** ppCnt) const
+{
+  short cnt;
+  memcpy(&cnt, *ppCnt, sizeof(short));
+  SWAP_2(cnt);
+  *ppCnt += 2;
+  return cnt;
+}
+
+// -------------------------------------------------------------------------- ;
+
+NAMESPACE_LERC_END
diff --git a/frmts/mrf/libLERC/RLE.h b/frmts/mrf/libLERC/RLE.h
new file mode 100644
index 0000000..89168be
--- /dev/null
+++ b/frmts/mrf/libLERC/RLE.h
@@ -0,0 +1,72 @@
+/*
+Copyright 2015 Esri
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+A local copy of the license and additional notices are located with the
+source distribution at:
+
+http://github.com/Esri/lerc/
+
+Contributors:  Thomas Maurer
+*/
+
+#ifndef RLE_H
+#define RLE_H
+
+#include "Defines.h"
+
+NAMESPACE_LERC_START
+
+/** RLE:
+ *  run length encode a byte array
+ *
+ *  best case resize factor (all bytes are the same):
+ *    (n + 1) * 3 / 32767 + 2  ~= 0.00009
+ *
+ *  worst case resize factor (no stretch of same bytes):
+ *    n + 4 + 2 * (n - 1) / 32767 ~= 1.00006
+ */
+
+class RLE
+{
+public:
+  RLE() : m_minNumEven(5) {};
+  virtual ~RLE() {};
+
+  size_t computeNumBytesRLE(const Byte* arr, size_t numBytes) const;
+
+  // when done, call
+  // delete[] *arrRLE;
+  bool compress(const Byte* arr, size_t numBytes,
+                Byte** arrRLE, size_t& numBytesRLE, bool verify = false) const;
+
+  // when done, call
+  // delete[] *arr;
+  bool decompress(const Byte* arrRLE, Byte** arr, size_t& numBytes) const;
+
+  // arr already allocated, just fill
+  bool decompress(const Byte* arrRLE, Byte* arr) const;
+
+protected:
+  int m_minNumEven;
+
+  void writeCount(short cnt, Byte** ppCnt, Byte** ppDst) const;
+  short readCount(const Byte** ppCnt) const;
+
+};
+
+// -------------------------------------------------------------------------- ;
+
+NAMESPACE_LERC_END
+#endif
diff --git a/frmts/mrf/libLERC/TImage.hpp b/frmts/mrf/libLERC/TImage.hpp
new file mode 100644
index 0000000..34caa9c
--- /dev/null
+++ b/frmts/mrf/libLERC/TImage.hpp
@@ -0,0 +1,198 @@
+/*
+Copyright 2015 Esri
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+A local copy of the license and additional notices are located with the
+source distribution at:
+
+http://github.com/Esri/lerc/
+
+Contributors:  Thomas Maurer
+*/
+
+#ifndef TIMAGE_HPP
+#define TIMAGE_HPP
+
+// ---- includes ------------------------------------------------------------ ;
+
+#include <vector>
+#include <cassert>
+#include <cstdlib>
+#include "Image.h"
+
+NAMESPACE_LERC_START
+
+class CntZ
+{
+public:
+  float cnt, z;
+  bool operator == (const CntZ& cz) const    { return cnt == cz.cnt && z == cz.z; }
+  bool operator != (const CntZ& cz) const    { return cnt != cz.cnt || z != cz.z; }
+  void operator += (const CntZ& cz)          { cnt += cz.cnt;  z += cz.z; }
+};
+
+template< class Element >
+class TImage : public Image
+{
+public:
+  TImage() : data_(NULL) {}
+  TImage(const TImage& tImg) : data_(NULL) { *this = tImg;  }
+  virtual ~TImage() {
+      clear();
+  };
+
+  /// assignment
+  TImage& operator=(const TImage& tImg);
+
+  bool resize(int width, int height);
+  virtual void clear();
+
+  /// get data
+  Element getPixel(int row, int col) const;
+  const Element& operator() (int row, int col) const;
+  const Element* getData() const;
+
+  /// set data
+  void setPixel(int row, int col, Element element);
+  Element& operator() (int row, int col);
+  Element* getData();
+
+  /// compare
+  bool operator == (const Image& img) const;
+  bool operator != (const Image& img) const	{ return !operator==(img); };
+
+protected:
+  Element* data_;
+};
+
+// -------------------------------------------------------------------------- ;
+// -------------------------------------------------------------------------- ;
+
+template< class Element >
+inline Element TImage< Element >::getPixel(int i, int j) const
+{
+  assert(isInside(i, j));
+  return data_[i * width_ + j];
+}
+
+template< class Element >
+inline const Element& TImage< Element >::operator () (int i, int j) const
+{
+  assert(isInside(i, j));
+  return data_[i * width_ + j];
+}
+
+template< class Element >
+inline const Element* TImage< Element >::getData() const
+{
+  return data_;
+}
+
+template< class Element >
+inline void TImage< Element >::setPixel(int i, int j, Element element)
+{
+  assert(isInside(i, j));
+  data_[i * width_ + j] = element;
+}
+
+template< class Element >
+inline Element& TImage< Element >::operator () (int i, int j)
+{
+  assert(isInside(i, j));
+  return data_[i * width_ + j];
+}
+
+template< class Element >
+inline Element* TImage< Element >::getData()
+{
+  return data_;
+}
+
+// -------------------------------------------------------------------------- ;
+
+template< class Element >
+bool TImage< Element >::resize(int width, int height)
+{
+  if (width <= 0 || height <= 0)
+    return false;
+
+  if (width == width_ && height == height_)
+    return true;
+
+  free(data_);
+  width_ = 0;
+  height_ = 0;
+
+  data_ = (Element*) malloc(width * height * sizeof(Element));
+  if (!data_)
+    return false;
+
+  width_ = width;
+  height_ = height;
+  
+  return true;
+}
+
+// -------------------------------------------------------------------------- ;
+
+template< class Element >
+void TImage< Element >::clear()
+{
+  free(data_);
+  data_ = NULL;
+  width_ = 0;
+  height_ = 0;
+}
+
+// -------------------------------------------------------------------------- ;
+
+template< class Element >
+TImage< Element >& TImage< Element >::operator = (const TImage& tImg)
+{
+  // allow copying image to itself
+  if (this == &tImg) return *this;
+
+  // only for images of the same type!
+  // conversions are implemented in the derived classes
+  assert(type_ == tImg.getType());
+
+  if (!resize(tImg.getWidth(), tImg.getHeight()))
+    return *this;    // return empty image if resize fails
+
+  memcpy(getData(), tImg.getData(), getSize() * sizeof(Element));
+
+  Image::operator=(tImg);
+  
+  return *this;
+}
+
+// -------------------------------------------------------------------------- ;
+
+template< class Element >
+bool TImage< Element >::operator == (const Image& img) const
+{
+  if (! Image::operator == (img)) return false;
+
+  const Element* ptr0 = getData();
+  const Element* ptr1 = ((const TImage&)img).getData();
+  int cnt = getSize();
+  while (cnt--)
+    if (*ptr0++ != *ptr1++)
+      return false;
+
+  return true;
+}
+
+NAMESPACE_LERC_END
+#endif
diff --git a/frmts/mrf/libLERC/makefile.vc b/frmts/mrf/libLERC/makefile.vc
new file mode 100644
index 0000000..0d15b0c
--- /dev/null
+++ b/frmts/mrf/libLERC/makefile.vc
@@ -0,0 +1,27 @@
+GDAL_ROOT	=	..\..\..
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+
+OBJ	= \
+	BitMask.obj BitMask2.obj BitStuffer.obj BitStuffer2.obj \
+	CntZImage.obj Huffman.obj Lerc2.obj RLE.obj
+
+HEADERS = \
+	BitMask.h Huffman.h BitStuffer.h CntZImage.h Defines.h Image.h \
+	TImage.hpp Lerc2.h BitStuffer2.h BitMask2.h RLE.h
+
+LIBLERC = libLERC.obj
+
+GDAL_ROOT	=	..\..\..
+
+EXTRAFLAGS      = -DLERC
+
+default:    $(LIBLERC)
+
+$(OBJ):	$(HEADERS)
+
+$(LIBLERC):	$(OBJ)
+        lib /out:..\$(LIBLERC) $(OBJ)
+
+clean:
+	-del ..\$(LIBLERC) $(OBJ)
diff --git a/frmts/mrf/makefile.vc b/frmts/mrf/makefile.vc
new file mode 100644
index 0000000..1edb422
--- /dev/null
+++ b/frmts/mrf/makefile.vc
@@ -0,0 +1,98 @@
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+# 
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+GDAL_ROOT	=	..\..
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+OBJ	=	Tif_band.obj Raw_band.obj PNG_band.obj JPEG_band.obj \
+    mrf_band.obj mrf_overview.obj mrf_util.obj marfa_dataset.obj
+
+PLUGIN_DLL =	gdal_mrf.dll
+
+# If the LERC folder exists, build LERC support
+!IF EXIST(libLERC)
+LIBLERC = libLERC.obj
+EXTRAFLAGS	= -DLERC -IlibLERC $(EXTRAFLAGS)
+OBJ = $(LIBLERC) LERC_Band.obj $(OBJ)
+!ENDIF
+
+!IFDEF JPEG_EXTERNAL_LIB
+EXTRAFLAGS =	-I$(JPEGDIR) $(EXTRAFLAGS)
+!ELSE
+
+EXTRAFLAGS =	/wd4611 -I../jpeg/libjpeg $(JPEG12_FLAGS) $(EXTRAFLAGS)
+EXTRA_LINK_FLAGS =  $(EXTRA_LINK_FLAGS) ../jpeg/libjpeg/libjpeg.lib
+
+# Only consider 12bit JPEG when using internal JPEG
+!IFDEF JPEG12_SUPPORTED
+OBJ	=	$(OBJ) JPEG12_band.obj
+EXTRAFLAGS	= -DJPEG12_SUPPORTED $(EXTRAFLAGS)
+EXTRA_LINK_FLAGS =  $(EXTRA_LINK_FLAGS) ../jpeg/libjpeg12/libjpeg12.lib
+!ENDIF
+
+!ENDIF
+
+!IFDEF PNG_EXTERNAL_LIB
+EXTRAFLAGS = 	-I../zlib -I$(PNGDIR) $(EXTRAFLAGS)
+!ELSE
+EXTRAFLAGS = 	/wd4611 -I../zlib -I../png/libpng -DINTERNAL_PNG $(EXTRAFLAGS)
+!ENDIF
+EXTRA_LINK_FLAGS =  $(EXTRA_LINK_FLAGS) ../png/libpng/libpng.lib ../zlib/libz.lib
+
+default:	$(OBJ)
+	xcopy /D  /Y *.obj ..\o
+
+$(OBJ): marfa.h
+
+!IFDEF LIBLERC
+$(LIBLERC):
+	cd libLERC
+	nmake /f makefile.vc
+	cd ..
+!ENDIF
+
+clean:
+	-del *.obj
+	-del *.dll
+	-del *.exp
+	-del *.lib
+	-del *.manifest
+	-del *.exe
+!IFDEF LIBLERC
+	cd libLERC
+	nmake /f makefile.vc clean
+	cd ..
+!ENDIF
+
+#
+# Building the MRF as a windows plugin works only then the internal jpeg and png are used
+# It also requires these custom steps:
+# 
+# - building static libraries: 
+#	../jpeg/jpeglib/libjpeg.lib
+#	Optional ../jpeg/jpeglib12/libjpeg12.lib
+#	../zlib/libz.lib
+#	../png/libpng/libpng.lib
+#
+# - exporting the GDALRegenerateOverviewsMultiBand by marking it CPL_DLL in gdal_priv.h
+#
+#
+
+plugin:	$(PLUGIN_DLL)
+
+$(PLUGIN_DLL): $(OBJ)
+	link /dll $(LDEBUG) /out:$(PLUGIN_DLL) $(OBJ) $(GDALLIB) $(EXTRA_LINK_FLAGS)
+	if exist $(PLUGIN_DLL).manifest mt -manifest $(PLUGIN_DLL).manifest -outputresource:$(PLUGIN_DLL);2
+
+plugin-install:
+	-mkdir $(PLUGINDIR)
+	$(INSTALL) $(PLUGIN_DLL) $(PLUGINDIR)
diff --git a/frmts/mrf/marfa.h b/frmts/mrf/marfa.h
new file mode 100644
index 0000000..447cc76
--- /dev/null
+++ b/frmts/mrf/marfa.h
@@ -0,0 +1,716 @@
+/*
+* Copyright (c) 2002-2012, California Institute of Technology.
+* All rights reserved.  Based on Government Sponsored Research under contracts NAS7-1407 and/or NAS7-03001.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+*   1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+*   2. Redistributions in binary form must reproduce the above copyright notice,
+*      this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+*   3. Neither the name of the California Institute of Technology (Caltech), its operating division the Jet Propulsion Laboratory (JPL),
+*      the National Aeronautics and Space Administration (NASA), nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE CALIFORNIA INSTITUTE OF TECHNOLOGY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* Copyright 2014-2015 Esri
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  Meta Raster Format
+ * Purpose:  MRF structures
+ * Author:   Lucian Plesea
+ *
+ ******************************************************************************
+ *
+ *
+ *
+ ****************************************************************************/
+
+#ifndef GDAL_FRMTS_MRF_MARFA_H_INCLUDED
+#define GDAL_FRMTS_MRF_MARFA_H_INCLUDED
+
+#include <gdal_pam.h>
+#include <ogr_srs_api.h>
+#include <ogr_spatialref.h>
+
+// For printing values
+#include <ostream>
+#include <iostream>
+#include <sstream>
+
+#ifdef GDAL_COMPILATION
+#define NAMESPACE_MRF_START namespace GDAL_MRF {
+#define NAMESPACE_MRF_END   }
+#define USING_NAMESPACE_MRF using namespace GDAL_MRF;
+#else
+#define NAMESPACE_MRF_START
+#define NAMESPACE_MRF_END
+#define USING_NAMESPACE_MRF
+#endif
+
+NAMESPACE_MRF_START
+
+// ZLIB Bit flag fields
+// 0:3 - level, 4 - GZip, 5 RAW zlib, 6:9 strategy
+#define ZFLAG_LMASK 0xF
+// GZ and RAW are mutually exclusive, GZ has higher priority
+// If neither is set, use zlib stream format
+#define ZFLAG_GZ 0x10
+#define ZFLAG_RAW 0x20
+
+// Mask for zlib strategy, valid values are 0 to 4 shifted six bits, see zlib for meaning
+// Can use one of:
+// Z_DEFAULT : whatever zlib decides
+// Z_FILTERED : optimized for delta encoding
+// Z_HUFFMAN_ONLY : Only huffman encoding (adaptive)
+// Z_RLE : Only next character matches
+// Z_FIXED : Static huffman, faster decoder
+//
+#define ZFLAG_SMASK 0x1c0
+
+// Force LERC to be included, normally off, detected in the makefile
+// #define LERC
+
+// These are a pain to maintain in sync.  They should be replaced with
+// C++11 uniform initializers.  The externs reside in util.cpp
+enum ILCompression {
+    IL_PNG = 0, IL_PPNG, IL_JPEG, IL_NONE, IL_ZLIB, IL_TIF,
+#if defined(LERC)
+    IL_LERC,
+#endif
+    IL_ERR_COMP
+};
+
+// Sequential is not supported by GDAL
+enum ILOrder { IL_Interleaved = 0, IL_Separate, IL_Sequential, IL_ERR_ORD };
+extern char const * const * ILComp_Name;
+extern char const * const * ILComp_Ext;
+extern char const * const * ILOrder_Name;
+
+class GDALMRFDataset;
+class GDALMRFRasterBand;
+
+typedef struct {
+    char   *buffer;
+    size_t size;
+} buf_mgr;
+
+// A tile index record, 16 bytes, big endian
+typedef struct {
+    GIntBig offset;
+    GIntBig size;
+} ILIdx;
+
+// Size of an image, also used as a tile or pixel location
+struct ILSize {
+    GInt32 x, y, z, c, l;
+    ILSize(const int x_ = -1, const int y_ = -1, const int z_ = -1,
+	const int c_ = -1, const int l_ = -1)
+    {
+	x = x_; y = y_; z = z_; c = c_; l = l_;
+    }
+
+    bool operator==(const ILSize& other)
+    {
+	return ((x == other.x) && (y == other.y) && (z == other.z) &&
+	    (c == other.c) && (l == other.l));
+    }
+
+    bool operator!=(const ILSize& other) { return !(*this == other); }
+};
+
+std::ostream& operator<<(std::ostream &out, const ILSize& sz);
+std::ostream& operator<<(std::ostream &out, const ILIdx& t);
+
+bool is_Endianess_Dependent(GDALDataType dt, ILCompression comp);
+
+// Debugging support
+// #define PPMW
+#ifdef PPMW
+void ppmWrite(const char *fname, const char *data, const ILSize &sz);
+#endif
+
+/**
+ * Collects information pertaining to a single raster
+ * This structure is being shallow copied, no pointers allowed
+ *
+ */
+
+typedef struct ILImage {
+    ILImage();
+    GIntBig dataoffset;
+    GIntBig idxoffset;
+    GInt32 quality;
+    GInt32 pageSizeBytes;
+    ILSize size;
+    ILSize pagesize;
+    ILSize pagecount;
+    ILCompression comp;
+    ILOrder order;
+    int nbo;
+    int hasNoData;
+    double NoDataValue;
+    CPLString datfname;
+    CPLString idxfname;
+    GDALDataType dt;
+    GDALColorInterp ci;
+} ILImage;
+
+// Delarations of utility functions
+
+/**
+ *
+ *\brief  Converters between endianness
+ *  Call netXX() to guarantee big endian
+ *
+ */
+static inline unsigned short int swab16(const unsigned short int val)
+{
+    return (val << 8) | (val >> 8);
+}
+
+static inline unsigned int swab32(unsigned int val)
+{
+    return (unsigned int)(swab16((unsigned short int) val)) << 16
+	| swab16((unsigned short int) (val >> 16));
+}
+
+static inline unsigned long long int swab64(const unsigned long long int val)
+{
+    return (unsigned long long int) (swab32((unsigned int)val)) << 32
+	| swab32((unsigned int)(val >> 32));
+}
+
+// NET_ORDER is true if machine is BE, false otherwise
+// Call netxx() if network (big) order is needed
+
+#ifdef WORDS_BIGENDIAN
+#define NET_ORDER true
+// These could be macros, but for the side effects related to type
+static inline unsigned short net16(const unsigned short x)
+{
+    return (x);
+}
+static inline unsigned int net32(const unsigned int x)
+{
+    return (x);
+}
+static inline unsigned long long net64(const unsigned long long x)
+{
+    return (x);
+}
+#else
+#define NET_ORDER false
+#define net16(x) swab16(x)
+#define net32(x) swab32(x)
+#define net64(x) swab64(x)
+#endif
+
+const char *CompName(ILCompression comp);
+const char *OrderName(ILOrder val);
+ILCompression CompToken(const char *, ILCompression def = IL_ERR_COMP);
+ILOrder OrderToken(const char *, ILOrder def = IL_ERR_ORD);
+CPLString getFname(CPLXMLNode *, const char *, const CPLString &, const char *);
+CPLString getFname(const CPLString &, const char *);
+double getXMLNum(CPLXMLNode *, const char *, double);
+GIntBig IdxOffset(const ILSize &, const ILImage &);
+double logb(double val, double base);
+int IsPower(double value, double base);
+CPLXMLNode *SearchXMLSiblings(CPLXMLNode *psRoot, const char *pszElement);
+CPLString PrintDouble(double d, const char *frmt = "%12.8f");
+void XMLSetAttributeVal(CPLXMLNode *parent, const char* pszName,
+    const double val, const char *frmt = "%12.8f");
+CPLXMLNode *XMLSetAttributeVal(CPLXMLNode *parent,
+    const char*pszName, const ILSize &sz, const char *frmt = NULL);
+void XMLSetAttributeVal(CPLXMLNode *parent,
+    const char*pszName, std::vector<double> const &values);
+//
+// Extension to CSL, set an entry only if it doesn't already exist
+//
+char **CSLAddIfMissing(char **papszList,
+    const char *pszName, const char *pszValue);
+
+GDALColorEntry GetXMLColorEntry(CPLXMLNode *p);
+GIntBig IdxSize(const ILImage &full, const int scale = 0);
+// Similar to uncompress() from zlib, accepts the ZFLAG_RAW
+// Return true if it worked
+int ZUnPack(const buf_mgr &src, buf_mgr &dst, int flags);
+// Similar to compress2() but with flags to control zlib features
+// Returns true if it worked
+int ZPack(const buf_mgr &src, buf_mgr &dst, int flags);
+// checks that the file exists and is at least sz, if access is update it extends it
+int CheckFileSize(const char *fname, GIntBig sz, GDALAccess eAccess);
+
+// Number of pages of size psz needed to hold n elements
+static inline int pcount(const int n, const int sz) {
+    return 1 + (n - 1) / sz;
+}
+
+// Returns a pagecount per dimension, .l will have the total number
+static inline const ILSize pcount(const ILSize &size, const ILSize &psz) {
+    ILSize pcnt;
+    pcnt.x = pcount(size.x, psz.x);
+    pcnt.y = pcount(size.y, psz.y);
+    pcnt.z = pcount(size.z, psz.z);
+    pcnt.c = pcount(size.c, psz.c);
+    pcnt.l = pcnt.x*pcnt.y*pcnt.z*pcnt.c;
+    return pcnt;
+}
+
+// Wrapper around the VISFile, remembers how the file was opened
+typedef struct {
+    VSILFILE *FP;
+    GDALRWFlag acc;
+} VF;
+
+// Offset of index, pos is in pages
+GIntBig IdxOffset(const ILSize &pos, const ILImage &img);
+
+enum { SAMPLING_ERR, SAMPLING_Avg, SAMPLING_Near };
+
+GDALMRFRasterBand *newMRFRasterBand(GDALMRFDataset *, const ILImage &, int, int level = 0);
+
+class GDALMRFDataset : public GDALPamDataset {
+
+
+    friend class GDALMRFRasterBand;
+    friend GDALMRFRasterBand *newMRFRasterBand(GDALMRFDataset *, const ILImage &, int, int level);
+
+public:
+    GDALMRFDataset();
+    virtual ~GDALMRFDataset();
+
+    static GDALDataset *Open(GDALOpenInfo *);
+    static int Identify(GDALOpenInfo *);
+    void Crystalize();
+
+    static GDALDataset *CreateCopy(const char *pszFilename, GDALDataset *poSrcDS,
+	int bStrict, char **papszOptions, GDALProgressFunc pfnProgress,
+	void *pProgressData);
+
+    static GDALDataset *Create(const char * pszName,
+	int nXSize, int nYSize, int nBands,
+	GDALDataType eType, char ** papszOptions);
+
+    // Stub for delete, GDAL should only overwrite the XML
+    static CPLErr Delete(const char *) {
+	return CE_None;
+    }
+
+    virtual const char *GetProjectionRef() { return projection; }
+    virtual CPLErr SetProjection(const char *proj) {
+	projection = proj;
+	return CE_None;
+    }
+
+    virtual CPLString const &GetPhotometricInterpretation() { return photometric; }
+    virtual CPLErr SetPhotometricInterpretation(const char *photo) {
+	photometric = photo;
+	return CE_None;
+    }
+
+    virtual CPLErr GetGeoTransform(double *gt);
+    virtual CPLErr SetGeoTransform(double *gt);
+
+#ifdef unused
+    virtual CPLErr AdviseRead(int nXOff, int nYOff, int nXSize, int nYSize,
+	int nBufXSize, int nBufYSize,
+	GDALDataType eDT,
+	int nBandCount, int *panBandList,
+	char **papszOptions);
+#endif
+
+    virtual char **GetFileList();
+
+    void SetColorTable(GDALColorTable *pct) { poColorTable = pct; };
+    const GDALColorTable *GetColorTable() { return poColorTable; };
+    void SetNoDataValue(const char*);
+    void SetMinValue(const char*);
+    void SetMaxValue(const char*);
+    CPLErr SetVersion(int version);
+
+    const CPLString GetFname() { return fname; };
+    // Patches a region of all the next overview, argument counts are in blocks
+    virtual CPLErr PatchOverview(int BlockX, int BlockY, int Width, int Height,
+	int srcLevel = 0, int recursive = false, int sampling_mode = SAMPLING_Avg);
+
+    // Creates an XML tree from the current MRF.  If written to a file it becomes an MRF
+    CPLXMLNode *BuildConfig();
+
+    void SetPBufferSize(unsigned int sz) {
+	pbsize = sz;
+    }
+    unsigned int GetPBufferSize() {
+	return pbsize;
+    }
+
+protected:
+    CPLErr LevelInit(const int l);
+
+    // Reads the XML metadata and returns the XML
+    CPLXMLNode *ReadConfig() const;
+
+    // Apply create options to the current dataset
+    void ProcessCreateOptions(char **papszOptions);
+
+    // Writes the XML tree as MRF.  It does not check the content
+    int WriteConfig(CPLXMLNode *);
+
+    // Initializes the dataset from an MRF metadata XML
+    CPLErr Initialize(CPLXMLNode *);
+
+    // Do nothing, this is not possible in an MRF
+    CPLErr CleanOverviews(void) { return CE_None; }
+
+    // Add uniform scale overlays, returns the new size of the index file
+    GIntBig AddOverviews(int scale);
+
+    // Late allocation buffer
+    bool SetPBuffer(unsigned int sz);
+    void *GetPBuffer() {
+	if (!pbuffer && pbsize)
+	    SetPBuffer(pbsize);
+	return pbuffer;
+    }
+
+#if GDAL_VERSION_MAJOR >= 2
+    virtual CPLErr IRasterIO(GDALRWFlag, int, int, int, int,
+        void *, int, int, GDALDataType,
+        int, int *, GSpacing, GSpacing, GSpacing, GDALRasterIOExtraArg*);
+#else
+    virtual CPLErr IRasterIO(GDALRWFlag, int, int, int, int,
+	void *, int, int, GDALDataType,
+	int, int *, int, int, int);
+#endif
+
+    virtual CPLErr IBuildOverviews(const char*, int, int*, int, int*,
+	GDALProgressFunc, void*);
+
+
+    // Write a tile, the infooffset is the relative position in the index file
+    virtual CPLErr WriteTile(void *buff, GUIntBig infooffset, GUIntBig size = 0);
+
+    // For versioned MRFs, add a version
+    CPLErr AddVersion();
+
+    // Read the index record itself
+    CPLErr ReadTileIdx(ILIdx &tinfo, const ILSize &pos, const ILImage &img, const GIntBig bias = 0);
+
+    VSILFILE *IdxFP();
+    VSILFILE *DataFP();
+    GDALRWFlag IdxMode() {
+	if (!ifp.FP) IdxFP();
+	return ifp.acc;
+    };
+    GDALRWFlag DataMode() {
+	if (!dfp.FP) DataFP();
+	return dfp.acc;
+    };
+    GDALDataset *GetSrcDS();
+
+    /*
+     *  There are two images defined to allow for morphing on use, in the future
+     *  For example storing a multispectral image and opening it as RGB
+     *
+     *  Support for this feature is not yet implemented.
+     *
+     */
+
+    // What the image is on disk
+    ILImage full;
+    // How we use it currently
+    ILImage current;
+    // The third dimension slice in use
+    int zslice;
+
+    // MRF file name
+    CPLString fname;
+
+    // The source to be cached in this MRF
+    CPLString source;
+    GIntBig idxSize; // The size of each version index, or the size of the cloned index
+
+    int clonedSource; // Is it a cloned source
+    int bypass_cache; // Do we alter disk cache
+    int mp_safe;      // Not thread safe, only multiple writers
+    int hasVersions;  // Does it support versions
+    int verCount;     // The last version
+    int bCrystalized; // Unset only during the create process
+
+    // Freeform sticky dataset options, as a list of key-value pairs
+    CPLStringList optlist;
+
+    // If caching data, the parent dataset
+    GDALDataset *poSrcDS;
+
+    // Level picked, or -1 for native
+    int level;
+
+    // Child dataset, if picking a specific level
+    GDALMRFDataset *cds;
+    // A small int actually due to GDAL limitations
+    double scale;
+
+    // A place to keep an uncompressed block, to keep from allocating it all the time
+    void *pbuffer;
+    unsigned int pbsize;
+    ILSize tile; // ID of tile present in buffer
+    GIntBig bdirty;    // Holds bits, to be used in pixel interleaved (up to 64 bands)
+
+    // GeoTransform support
+    double GeoTransform[6];
+    int bGeoTransformValid;
+
+    // Projection string, WKT
+    CPLString projection;
+
+    // Photometric interpretation
+    CPLString photometric;
+
+    GDALColorTable *poColorTable;
+    int Quality;
+
+    VF dfp;  // Data file handle
+    VF ifp;  // Index file handle
+
+    // statistical values
+    std::vector<double> vNoData, vMin, vMax;
+};
+
+class GDALMRFRasterBand : public GDALPamRasterBand {
+    friend class GDALMRFDataset;
+public:
+    GDALMRFRasterBand(GDALMRFDataset *, const ILImage &, int, int);
+    virtual ~GDALMRFRasterBand();
+    virtual CPLErr IReadBlock(int xblk, int yblk, void *buffer);
+    virtual CPLErr IWriteBlock(int xblk, int yblk, void *buffer);
+
+    virtual GDALColorTable *GetColorTable() { return poDS->poColorTable; }
+
+    CPLErr SetColorInterpretation(GDALColorInterp ci) { img.ci = ci; return CE_None; }
+    virtual GDALColorInterp GetColorInterpretation() { return img.ci; }
+
+    // Get works within MRF or with PAM
+    virtual double  GetNoDataValue(int *);
+    virtual CPLErr  SetNoDataValue(double);
+
+    // These get set with SetStatistics.  Let PAM handle it
+    virtual double  GetMinimum(int *);
+    virtual double  GetMaximum(int *);
+
+
+    // MRF specific, fetch is from a remote source
+    CPLErr FetchBlock(int xblk, int yblk, void *buffer = NULL);
+    // Fetch a block from a cloned MRF
+    CPLErr FetchClonedBlock(int xblk, int yblk, void *buffer = NULL);
+
+    // Block not stored on disk
+    CPLErr FillBlock(void *buffer);
+
+    // de-interlace a buffer in pixel blocks
+    CPLErr RB(int xblk, int yblk, buf_mgr src, void *buffer);
+
+    const char *GetOptionValue(const char *opt, const char *def) const;
+    void SetAccess(GDALAccess eA) { eAccess = eA; }
+    void SetDeflate(int v) { deflatep = (v != 0); }
+
+protected:
+    // Pointer to the GDALMRFDataset
+    GDALMRFDataset *poDS;
+    // 0 based
+    GInt32 m_band;
+    int deflatep;
+    int deflate_flags;
+    // Level count of this band
+    GInt32 m_l;
+    // The info about the current image, to enable R-sets
+    ILImage img;
+    std::vector<GDALMRFRasterBand *> overviews;
+    int overview;
+
+    VSILFILE *IdxFP() { return poDS->IdxFP(); }
+    GDALRWFlag IdxMode() { return poDS->IdxMode(); }
+    VSILFILE *DataFP() { return poDS->DataFP(); }
+    GDALRWFlag DataMode() { return poDS->DataMode(); }
+
+    // How many bytes are in a band block (not a page, a single band block)
+    // Easiest is to calculate it from the pageSizeBytes
+    GUInt32 blockSizeBytes() {
+	return poDS->current.pageSizeBytes / poDS->current.pagesize.c;
+    }
+
+    const CPLStringList & GetOptlist() const { return poDS->optlist; }
+
+    // Compression and decompression functions.  To be overwritten by specific implementations
+    virtual CPLErr Compress(buf_mgr &dst, buf_mgr &src) = 0;
+    virtual CPLErr Decompress(buf_mgr &dst, buf_mgr &src) = 0;
+
+    // Read the index record itself, can be overwritten
+    //    virtual CPLErr ReadTileIdx(const ILSize &, ILIdx &, GIntBig bias = 0);
+
+    GIntBig bandbit(int b) { return ((GIntBig)1) << b; }
+    GIntBig bandbit() { return bandbit(m_band); }
+    GIntBig AllBandMask() { return bandbit(poDS->nBands) - 1; }
+
+    // Overview Support
+    // Inherited from GDALRasterBand
+    // These are called only in the base level RasterBand
+    virtual int GetOverviewCount();
+    virtual GDALRasterBand *GetOverview(int n);
+    void AddOverview(GDALMRFRasterBand *b) { overviews.push_back(b); }
+};
+
+/**
+ * Each type of compression needs to define at least two methods, a compress and a
+ * decompress, which take as arguments a dest and a source buffer, plus an image structure
+ * that holds the information about the compression type.
+ * Filtering is needed, probably in the form of pack and unpack functions
+ *
+ */
+
+class PNG_Band : public GDALMRFRasterBand {
+    friend class GDALMRFDataset;
+public:
+    PNG_Band(GDALMRFDataset *pDS, const ILImage &image, int b, int level);
+    virtual ~PNG_Band();
+protected:
+    virtual CPLErr Decompress(buf_mgr &dst, buf_mgr &src);
+    virtual CPLErr Compress(buf_mgr &dst, buf_mgr &src);
+
+    CPLErr CompressPNG(buf_mgr &dst, buf_mgr &src);
+    CPLErr DecompressPNG(buf_mgr &dst, buf_mgr &src);
+    CPLErr ResetPalette();
+    void *PNGColors;
+    void *PNGAlpha;
+    int PalSize, TransSize;
+};
+
+class JPEG_Band : public GDALMRFRasterBand {
+    friend class GDALMRFDataset;
+public:
+    JPEG_Band(GDALMRFDataset *pDS, const ILImage &image, int b, int level);
+    virtual ~JPEG_Band() {};
+protected:
+    virtual CPLErr Decompress(buf_mgr &dst, buf_mgr &src);
+    virtual CPLErr Compress(buf_mgr &dst, buf_mgr &src);
+
+    CPLErr CompressJPEG(buf_mgr &dst, buf_mgr &src);
+    CPLErr DecompressJPEG(buf_mgr &dst, buf_mgr &src);
+
+#if defined(JPEG12_SUPPORTED) // Internal only
+#define LIBJPEG_12_H "../jpeg/libjpeg12/jpeglib.h"
+    CPLErr CompressJPEG12(buf_mgr &dst, buf_mgr &src);
+    CPLErr DecompressJPEG12(buf_mgr &dst, buf_mgr &src);
+#endif
+
+    // Stored format flags, significant only for 3 band data
+    bool sameres;
+    bool rgb;
+    bool optimize;
+};
+
+class Raw_Band : public GDALMRFRasterBand {
+    friend class GDALMRFDataset;
+public:
+    Raw_Band(GDALMRFDataset *pDS, const ILImage &image, int b, int level) :
+	GDALMRFRasterBand(pDS, image, b, int(level)) {};
+    virtual ~Raw_Band() {};
+protected:
+    virtual CPLErr Decompress(buf_mgr &dst, buf_mgr &src);
+    virtual CPLErr Compress(buf_mgr &dst, buf_mgr &src);
+};
+
+class TIF_Band : public GDALMRFRasterBand {
+    friend class GDALMRFDataset;
+public:
+    TIF_Band(GDALMRFDataset *pDS, const ILImage &image, int b, int level);
+    virtual ~TIF_Band();
+protected:
+    virtual CPLErr Decompress(buf_mgr &dst, buf_mgr &src);
+    virtual CPLErr Compress(buf_mgr &dst, buf_mgr &src);
+
+    // Create options for TIF pages
+    char **papszOptions;
+};
+
+#if defined(LERC)
+class LERC_Band : public GDALMRFRasterBand {
+    friend class GDALMRFDataset;
+public:
+    LERC_Band(GDALMRFDataset *pDS, const ILImage &image, int b, int level);
+    virtual ~LERC_Band();
+protected:
+    virtual CPLErr Decompress(buf_mgr &dst, buf_mgr &src);
+    virtual CPLErr Compress(buf_mgr &dst, buf_mgr &src);
+    double precision;
+    int version;
+};
+#endif
+
+/*\brief band for level mrf
+ *
+ * Stand alone definition of a derived band, used in access to a specific level in an MRF
+ *
+ */
+class GDALMRFLRasterBand : public GDALPamRasterBand {
+public:
+    GDALMRFLRasterBand(GDALMRFRasterBand *b) {
+	pBand = b;
+	eDataType = b->GetRasterDataType();
+	b->GetBlockSize(&nBlockXSize, &nBlockYSize);
+	eAccess = b->GetAccess();
+	nRasterXSize = b->GetXSize();
+	nRasterYSize = b->GetYSize();
+    }
+    virtual CPLErr IReadBlock(int xblk, int yblk, void *buffer) {
+	return pBand->IReadBlock(xblk, yblk, buffer);
+    }
+    virtual CPLErr IWriteBlock(int xblk, int yblk, void *buffer) {
+	return pBand->IWriteBlock(xblk, yblk, buffer);
+    }
+    virtual GDALColorTable *GetColorTable() {
+	return pBand->GetColorTable();
+    }
+    virtual GDALColorInterp GetColorInterpretation() {
+	return pBand->GetColorInterpretation();
+    }
+    virtual double  GetNoDataValue(int * pbSuccess) {
+	return pBand->GetNoDataValue(pbSuccess);
+    }
+    virtual double  GetMinimum(int *b) {
+	return pBand->GetMinimum(b);
+    }
+    virtual double  GetMaximum(int *b) {
+	return pBand->GetMaximum(b);
+    }
+
+protected:
+    virtual int GetOverviewCount() { return 0; }
+    virtual GDALRasterBand *GetOverview(int ) { return NULL; }
+
+    GDALMRFRasterBand *pBand;
+};
+
+NAMESPACE_MRF_END
+
+#endif // GDAL_FRMTS_MRF_MARFA_H_INCLUDED
diff --git a/frmts/mrf/marfa_dataset.cpp b/frmts/mrf/marfa_dataset.cpp
new file mode 100644
index 0000000..991cd8e
--- /dev/null
+++ b/frmts/mrf/marfa_dataset.cpp
@@ -0,0 +1,1983 @@
+/*
+* Copyright (c) 2002-2012, California Institute of Technology.
+* All rights reserved.  Based on Government Sponsored Research under contracts NAS7-1407 and/or NAS7-03001.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+*   1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+*   2. Redistributions in binary form must reproduce the above copyright notice,
+*      this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+*   3. Neither the name of the California Institute of Technology (Caltech), its operating division the Jet Propulsion Laboratory (JPL),
+*      the National Aeronautics and Space Administration (NASA), nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE CALIFORNIA INSTITUTE OF TECHNOLOGY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* Copyright 2014-2015 Esri
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/******************************************************************************
+*
+* Project:  Meta Raster File Format Driver Implementation, Dataset
+* Purpose:  Implementation of GDAL dataset
+*
+* Author:   Lucian Plesea, Lucian.Plesea at jpl.nasa.gov, lplesea at esri.com
+*
+******************************************************************************
+*
+*   Since the MRF dataset and the band are so closely tied together, they should be
+*   considered a single class, or a class (dataset) with extensions (bands).
+*
+*
+****************************************************************************/
+
+#include "marfa.h"
+#include "cpl_multiproc.h" /* for CPLSleep() */
+#include <gdal_priv.h>
+#include <assert.h>
+
+#include <vector>
+
+using std::vector;
+using std::string;
+
+NAMESPACE_MRF_START
+
+// Initialize as invalid
+GDALMRFDataset::GDALMRFDataset()
+{   //		     X0   Xx   Xy  Y0    Yx   Yy
+    double gt[6] = { 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 };
+
+    ILImage img;
+
+    memcpy(GeoTransform, gt, sizeof(gt));
+    bGeoTransformValid = TRUE;
+    ifp.FP = dfp.FP = NULL;
+    pbuffer = NULL;
+    pbsize = 0;
+    bdirty = 0;
+    scale = 0;
+    zslice = 0;
+    hasVersions = FALSE;
+    clonedSource = FALSE;
+    mp_safe = FALSE;
+    level = -1;
+    tile = ILSize();
+    cds = NULL;
+    poSrcDS = NULL;
+    poColorTable = NULL;
+    bCrystalized = FALSE; // Assume not in create mode
+    bypass_cache = CSLTestBoolean(CPLGetConfigOption("MRF_BYPASSCACHING", "FALSE"));
+    idxSize = 0;
+    verCount = 0;
+    Quality = 0;
+    dfp.acc = GF_Read;
+    ifp.acc = GF_Read;
+}
+
+bool GDALMRFDataset::SetPBuffer(unsigned int sz)
+{
+    if (sz == 0) {
+	CPLFree(pbuffer);
+	pbuffer = NULL;
+    }
+    void* pbufferNew = VSIRealloc(pbuffer, sz);
+    if( pbufferNew == NULL )
+    {
+        CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate %u bytes",
+                 sz);
+        return false;
+    }
+    pbuffer = pbufferNew;
+    pbsize = (pbuffer == NULL) ? 0 : sz;
+    return true;
+}
+
+GDALMRFDataset::~GDALMRFDataset()
+
+{   // Make sure everything gets written
+    FlushCache();
+    if (ifp.FP)
+	VSIFCloseL(ifp.FP);
+    if (dfp.FP)
+	VSIFCloseL(dfp.FP);
+    delete cds;
+    delete poSrcDS;
+    delete poColorTable;
+
+    // CPLFree ignores being called with NULL
+    CPLFree(pbuffer);
+    pbsize = 0;
+}
+
+#ifdef unused
+/*
+ *\brief Called before the IRaster IO gets called
+ *
+ *
+ *
+ */
+CPLErr GDALMRFDataset::AdviseRead(int nXOff, int nYOff, int nXSize, int nYSize,
+    int nBufXSize, int nBufYSize,
+    GDALDataType eDT,
+    int nBandCount, int *panBandList,
+    char **papszOptions)
+{
+    CPLDebug("MRF_IO", "AdviseRead %d, %d, %d, %d, bufsz %d,%d,%d\n",
+	nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, nBandCount);
+    return CE_None;
+}
+#endif
+
+/*
+ *\brief Format specifc RasterIO, may be bypassed by BlockBasedRasterIO by setting
+ * GDAL_FORCE_CACHING to Yes, in which case the band ReadBlock and WriteBLock are called
+ * directly
+ *
+ *
+ */
+CPLErr GDALMRFDataset::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize,
+    void *pData, int nBufXSize, int nBufYSize, GDALDataType eBufType,
+    int nBandCount, int *panBandMap,
+#if GDAL_VERSION_MAJOR >= 2
+    GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace, GDALRasterIOExtraArg* psExtraArgs
+#else
+    int nPixelSpace, int nLineSpace, int nBandSpace
+#endif
+    )
+{
+    CPLDebug("MRF_IO", "IRasterIO %s, %d, %d, %d, %d, bufsz %d,%d,%d strides P %d, L %d, B %d \n",
+	eRWFlag == GF_Write ? "Write" : "Read",
+	nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, nBandCount,
+	static_cast<int>(nPixelSpace), static_cast<int>(nLineSpace),
+        static_cast<int>(nBandSpace));
+
+    // Finish the Create call
+    if (!bCrystalized)
+	Crystalize();
+
+    //
+    // Call the parent implementation, which splits it into bands and calls their IRasterIO
+    //
+    return GDALPamDataset::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
+	eBufType, nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace
+#if GDAL_VERSION_MAJOR >= 2
+        ,psExtraArgs
+#endif
+	);
+}
+
+
+/**
+*\brief Build some overviews
+*
+*  if nOverviews is 0, erase the overviews (reduce to base image only)
+*/
+
+CPLErr GDALMRFDataset::IBuildOverviews(
+    const char * pszResampling,
+    int nOverviews, int * panOverviewList,
+    int nBandsIn, int * panBandList,
+    GDALProgressFunc pfnProgress, void * pProgressData)
+
+{
+    CPLErr       eErr = CE_None;
+
+    CPLDebug("MRF_OVERLAY", "IBuildOverviews %d, bands %d\n", nOverviews, nBandsIn);
+
+    if( nBands != nBandsIn )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, "nBands = %d not supported", nBandsIn);
+        return CE_Failure;
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      If we don't have write access, then create the overviews        */
+    /*      externally.                                                     */
+    /* -------------------------------------------------------------------- */
+    if (GetAccess() != GA_Update)
+    {
+	CPLDebug("MRF", "File open read-only, creating overviews externally.");
+
+	return GDALDataset::IBuildOverviews(
+	    pszResampling, nOverviews, panOverviewList,
+	    nBands, panBandList, pfnProgress, pProgressData);
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      If zero overviews were requested, we need to clear all          */
+    /*      existing overviews.                                             */
+    /*      This should just clear the index file                           */
+    /*      Right now it just fails or does nothing                         */
+    /* -------------------------------------------------------------------- */
+
+    if (nOverviews == 0)
+    {
+	if (current.size.l == 0)
+	    return GDALDataset::IBuildOverviews(pszResampling,
+		nOverviews, panOverviewList,
+		nBands, panBandList, pfnProgress, pProgressData);
+	else
+	    return CleanOverviews();
+    }
+
+    // Array of source bands
+    GDALRasterBand **papoBandList =
+	(GDALRasterBand **)CPLCalloc(sizeof(void*), nBands);
+    // Array of destination bands
+    GDALRasterBand **papoOverviewBandList =
+	(GDALRasterBand **)CPLCalloc(sizeof(void*), nBands);
+    // Triple level pointer, that's what GDAL ROMB wants
+    GDALRasterBand ***papapoOverviewBands =
+	(GDALRasterBand ***)CPLCalloc(sizeof(void*), nBands);
+
+    int* panOverviewListNew = (int*)CPLMalloc( sizeof(int) * nOverviews );
+    memcpy( panOverviewListNew, panOverviewList, sizeof(int) * nOverviews );
+
+    try {  // Throw an error code, to make sure memory gets freed properly
+	// Modify the metadata file if it doesn't already have the Rset model set
+	if (0.0 == scale) {
+	    CPLXMLNode *config = ReadConfig();
+	    try {
+		const char* model = CPLGetXMLValue(config, "Rsets.model", "uniform");
+		if (!EQUAL(model, "uniform")) {
+		    CPLError(CE_Failure, CPLE_AppDefined,
+			"MRF:IBuildOverviews, Overviews not implemented for model %s", model);
+		    throw CE_Failure;
+		}
+
+		// The scale value is the same as first overview
+		scale = strtod(CPLGetXMLValue(config, "Rsets.scale",
+		    CPLString().Printf("%d", panOverviewList[0]).c_str()), NULL);
+
+		// Initialize the empty overlays, all of them for a given scale
+		// They could already exist, in which case they are not erased
+		idxSize = AddOverviews(int(scale));
+		if (!CheckFileSize(current.idxfname, idxSize, GA_Update)) {
+		    CPLError(CE_Failure, CPLE_AppDefined, "MRF: Can't extend index file");
+		    throw CE_Failure;
+		}
+
+		//  Set the uniform node, in case it was not set before, and save the new configuration
+		CPLSetXMLValue(config, "Rsets.#model", "uniform");
+		CPLSetXMLValue(config, "Rsets.#scale", CPLString().Printf("%g", scale).c_str());
+
+		if (!WriteConfig(config)) {
+		    CPLError(CE_Failure, CPLE_AppDefined, "MRF: Can't rewrite the metadata file");
+		    throw CE_Failure;
+		}
+		CPLDestroyXMLNode(config);
+		config = NULL;
+	    }
+	    catch (CPLErr e) {
+		if (config)
+		    CPLDestroyXMLNode(config);
+		throw e; // Rethrow
+	    }
+
+            // To avoid issues with blacks overviews, if the user asked to
+            // generate overviews 2, 4, ..., we finish the sequence until the
+            // last level that will be otherwised initialized to black
+	    if( !EQUAL(pszResampling, "NONE") &&
+                nOverviews != GetRasterBand(1)->GetOverviewCount() &&
+                CSLTestBoolean(CPLGetConfigOption("MRF_ALL_OVERVIEW_LEVELS", "YES")) )
+            {
+                bool bIncreasingPowers = true;
+                for (int i = 1; i < nOverviews; i++) {
+                    if (panOverviewList[i] != (panOverviewList[0] << i)) {
+                        bIncreasingPowers = false;
+                    }
+                }
+                if( bIncreasingPowers )
+                {
+                    CPLDebug("MRF", "Generating %d levels instead of the %d required",
+                             GetRasterBand(1)->GetOverviewCount(), nOverviews);
+                    nOverviews = GetRasterBand(1)->GetOverviewCount();
+                    panOverviewListNew = (int*) CPLRealloc(panOverviewListNew,
+                                                    sizeof(int) * nOverviews );
+                    for (int i = 1; i < nOverviews; i++) {
+                        panOverviewListNew[i] = panOverviewListNew[0] << i;
+                    }
+                }
+            }
+	}
+
+	for (int i = 0; i < nOverviews; i++) {
+
+	    // Verify that scales are reasonable, val/scale has to be an integer
+	    if (!IsPower(panOverviewListNew[i], scale)) {
+		CPLError(CE_Warning, CPLE_AppDefined,
+		    "MRF:IBuildOverviews, overview factor %d is not a power of %f",
+		    panOverviewListNew[i], scale);
+		continue;
+	    };
+
+	    int srclevel = int(-0.5 + logb(panOverviewListNew[i], scale));
+	    GDALMRFRasterBand *b = static_cast<GDALMRFRasterBand *>(GetRasterBand(1));
+
+	    // Warn for requests for invalid levels
+	    if (srclevel >= b->GetOverviewCount()) {
+		CPLError(CE_Warning, CPLE_AppDefined,
+		    "MRF:IBuildOverviews, overview factor %d is not valid for this dataset",
+		    panOverviewListNew[i]);
+		continue;
+	    }
+
+	    // Generate the overview using the previous level as the source
+
+	    // Use "avg" flag to trigger the internal average sampling
+	    if (EQUALN("Avg", pszResampling, 3) || EQUALN("NearNb", pszResampling, 4)) {
+
+		int sampling = EQUALN("Avg", pszResampling, 3) ? SAMPLING_Avg : SAMPLING_Near;
+		// Internal, using PatchOverview
+		if (srclevel > 0)
+		    b = static_cast<GDALMRFRasterBand *>(b->GetOverview(srclevel - 1));
+
+		eErr = PatchOverview(0, 0, b->nBlocksPerRow, b->nBlocksPerColumn, srclevel,
+		    0, sampling);
+		if (eErr == CE_Failure)
+		    throw eErr;
+
+	    }
+	    else {
+		//
+		// Use the GDAL method, which is slightly different for bilinear interpolation
+		// and also handles nearest mode
+		//
+		//
+		for (int iBand = 0; iBand < nBands; iBand++) {
+		    // This is the base level
+		    papoBandList[iBand] = GetRasterBand(panBandList[iBand]);
+		    // Set up the destination
+		    papoOverviewBandList[iBand] =
+			papoBandList[iBand]->GetOverview(srclevel);
+
+		    // Use the previous level as the source, the overviews are 0 based
+		    // thus an extra -1
+		    if (srclevel > 0)
+			papoBandList[iBand] = papoBandList[iBand]->GetOverview(srclevel - 1);
+
+		    // Hook it up, via triple pointer level
+		    papapoOverviewBands[iBand] = &(papoOverviewBandList[iBand]);
+		}
+
+		//
+		// Ready, generate this overview
+		// Note that this function has a bug in GDAL, the block stepping is incorect
+		// It can generate multiple overview in one call,
+		// Could rewrite this loop so this function only gets called once
+		//
+		GDALRegenerateOverviewsMultiBand(nBands, papoBandList,
+		    1, papapoOverviewBands,
+		    pszResampling, pfnProgress, pProgressData);
+	    }
+	}
+    }
+    catch (CPLErr e) {
+	eErr = e;
+    }
+
+    CPLFree(panOverviewListNew);
+    CPLFree(papapoOverviewBands);
+    CPLFree(papoOverviewBandList);
+    CPLFree(papoBandList);
+
+    return eErr;
+}
+
+/*
+*\brief blank separated list to vector of doubles
+*/
+static void list2vec(std::vector<double> &v, const char *pszList) {
+    if ((pszList == NULL) || (pszList[0] == 0)) return;
+    char **papszTokens = CSLTokenizeString2(pszList, " \t\n\r",
+	CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES);
+    v.clear();
+    for (int i = 0; i < CSLCount(papszTokens); i++)
+	v.push_back(CPLStrtod(papszTokens[i], NULL));
+    CSLDestroy(papszTokens);
+}
+
+void GDALMRFDataset::SetNoDataValue(const char *pszVal) {
+    list2vec(vNoData, pszVal);
+}
+
+void GDALMRFDataset::SetMinValue(const char *pszVal) {
+    list2vec(vMin, pszVal);
+}
+
+void GDALMRFDataset::SetMaxValue(const char *pszVal) {
+    list2vec(vMax, pszVal);
+}
+
+/**
+*\brief Idenfity a MRF file, lightweight
+*
+* Lightweight test, otherwise Open gets called.
+*
+*/
+int GDALMRFDataset::Identify(GDALOpenInfo *poOpenInfo)
+
+{
+    CPLString fn(poOpenInfo->pszFilename);
+    if (fn.find(":MRF:") != string::npos)
+	return TRUE;
+    if (poOpenInfo->nHeaderBytes >= 10)
+	fn = (char *)poOpenInfo->pabyHeader;
+    return EQUALN(fn.c_str(), "<MRF_META>", 10);
+}
+
+/**
+*
+*\Brief Read the XML config tree, from file
+*  Caller is responsible for freeing the memory
+*
+* @param pszFilename the file to open.
+* @return NULL on failure, or the document tree on success.
+*
+*/
+CPLXMLNode *GDALMRFDataset::ReadConfig() const
+{
+    if (fname[0] == '<')
+	return CPLParseXMLString(fname);
+    else
+	return CPLParseXMLFile(fname);
+}
+
+/**
+*\Brief Write the XML config tree
+* Caller is responsible for correctness of data
+* and for freeing the memory
+*
+* @param config The document tree to write
+* @return TRUE on success, FALSE otherwise
+*/
+int GDALMRFDataset::WriteConfig(CPLXMLNode *config)
+{
+    if (fname[0] == '<') return FALSE;
+    return CPLSerializeXMLTreeToFile(config, fname);
+}
+
+static void
+stringSplit(vector<string> & theStringVector,  // Altered/returned value
+const string &theString,
+size_t start = 0,
+const  char theDelimiter = ' ')
+{
+    size_t end = theString.find(theDelimiter, start);
+    if (string::npos == end) {
+	theStringVector.push_back(theString.substr(start));
+	return;
+    }
+    theStringVector.push_back(theString.substr(start, end - start));
+    stringSplit(theStringVector, theString, end + 1, theDelimiter);
+}
+
+// Returns the number following the prefix if it exists in one of the vector strings
+// Otherwise it returns the default
+static int getnum(const vector<string> &theStringVector, const char prefix, int def) {
+    for (unsigned int i = 0; i < theStringVector.size(); i++)
+	if (theStringVector[i][0] == prefix)
+	    return atoi(theStringVector[i].c_str() + 1);
+    return def;
+}
+
+/**
+*\Brief Open a MRF file
+*
+*/
+GDALDataset *GDALMRFDataset::Open(GDALOpenInfo *poOpenInfo)
+
+{
+    CPLXMLNode *config = NULL;
+    CPLErr ret = CE_None;
+    const char* pszFileName = poOpenInfo->pszFilename;
+
+    int level = -1; // All levels
+    int version = 0; // Current
+    int zslice = 0;
+    string fn; // Used to parse and adjust the file name
+
+    // Different ways to open it
+    if (poOpenInfo->nHeaderBytes >= 10 &&
+	EQUALN((const char *)poOpenInfo->pabyHeader, "<MRF_META>", 10)) // Regular file name
+	config = CPLParseXMLFile(pszFileName);
+    else {
+	if (EQUALN(pszFileName, "<MRF_META>", 10)) // Content as file name
+	    config = CPLParseXMLString(pszFileName);
+	else
+	{ // Try Ornate file name
+	    fn = pszFileName;
+	    size_t pos = fn.find(":MRF:");
+	    if (string::npos != pos) { // Tokenize and pick known options
+		vector<string> tokens;
+		stringSplit(tokens, fn, pos + 5, ':');
+		level = getnum(tokens, 'L', -1);
+		version = getnum(tokens, 'V', 0);
+		zslice = getnum(tokens, 'Z', 0);
+		fn.resize(pos); // Cut the ornamentations
+		pszFileName = fn.c_str();
+		config = CPLParseXMLFile(pszFileName);
+	    }
+	}
+    }
+
+    if (!config)
+	return NULL;
+
+    GDALMRFDataset *ds = new GDALMRFDataset();
+    ds->fname = pszFileName;
+    ds->eAccess = poOpenInfo->eAccess;
+    ds->level = level;
+    ds->zslice = zslice;
+
+    if (level != -1) {
+	// Open the whole dataset, then pick one level
+	ds->cds = new GDALMRFDataset();
+	ds->cds->fname = pszFileName;
+	ds->cds->eAccess = ds->eAccess;
+	ret = ds->cds->Initialize(config);
+	if (ret == CE_None)
+	    ret = ds->LevelInit(level);
+    }
+    else
+    {
+	ret = ds->Initialize(config);
+    }
+
+    CPLDestroyXMLNode(config);
+
+    if (ret != CE_None) {
+	delete ds;
+	return NULL;
+    }
+
+    // Open a single version
+    if (version != 0)
+	ret = ds->SetVersion(version);
+
+    if (ret != CE_None) {
+	delete ds;
+	return NULL;
+    }
+
+    // Tell PAM what our real file name is, to help it find the aux.xml
+    ds->SetPhysicalFilename(pszFileName);
+    // Don't mess with metadata after this, otherwise PAM will re-write the aux.xml
+    ds->TryLoadXML();
+
+/* -------------------------------------------------------------------- */
+/*      Open external overviews.                                        */
+/* -------------------------------------------------------------------- */
+    ds->oOvManager.Initialize( ds, pszFileName );
+
+
+    return ds;
+}
+
+// Adjust the band images with the right offset, then adjust the sizes
+CPLErr GDALMRFDataset::SetVersion(int version) {
+    if (!hasVersions || version > verCount) {
+	CPLError(CE_Failure, CPLE_AppDefined, "GDAL MRF: Version number error!");
+	return CE_Failure;
+    }
+    // Size of one version index
+    for (int bcount = 1; bcount <= nBands; bcount++) {
+	GDALMRFRasterBand *srcband = (GDALMRFRasterBand *)GetRasterBand(bcount);
+	srcband->img.idxoffset += idxSize*verCount;
+	for (int l = 0; l < srcband->GetOverviewCount(); l++) {
+	    GDALMRFRasterBand *band = (GDALMRFRasterBand *)srcband->GetOverview(l);
+            if( band != NULL )
+                band->img.idxoffset += idxSize*verCount;
+	}
+    }
+    hasVersions = 0;
+    return CE_None;
+}
+
+CPLErr GDALMRFDataset::LevelInit(const int l) {
+    // Test that this level does exist
+    if (l < 0 || l >= cds->GetRasterBand(1)->GetOverviewCount()) {
+	CPLError(CE_Failure, CPLE_AppDefined, "GDAL MRF: Overview not present!");
+	return CE_Failure;
+    }
+
+    GDALMRFRasterBand *srcband = (GDALMRFRasterBand *)cds->GetRasterBand(1)->GetOverview(l);
+    // Copy the sizes from this level
+    current = full = srcband->img;
+    current.size.c = cds->current.size.c;
+    scale = cds->scale;
+    SetProjection(cds->GetProjectionRef());
+
+    SetMetadataItem("INTERLEAVE", OrderName(current.order), "IMAGE_STRUCTURE");
+    SetMetadataItem("COMPRESSION", CompName(current.comp), "IMAGE_STRUCTURE");
+
+    bGeoTransformValid = (CE_None == cds->GetGeoTransform(GeoTransform));
+    for (int i = 0; i < l; i++) {
+	GeoTransform[1] /= scale;
+	GeoTransform[5] /= scale;
+    }
+
+    nRasterXSize = current.size.x;
+    nRasterYSize = current.size.y;
+    nBands = current.size.c;
+
+    // Add the bands, copy constructor so they can be closed independently
+    for (int i = 1; i <= nBands; i++) {
+	GDALMRFLRasterBand *band = new GDALMRFLRasterBand((GDALMRFRasterBand *)
+	    cds->GetRasterBand(i)->GetOverview(l));
+	SetBand(i, band);
+    }
+    return CE_None;
+}
+
+// Is the string positive or not
+inline bool on(const char *pszValue) {
+    if (!pszValue || pszValue[0] == 0)
+	return false;
+    return (EQUAL(pszValue, "ON") || EQUAL(pszValue, "TRUE") || EQUAL(pszValue, "YES"));
+}
+
+/**
+*\brief Initialize the image structure and the dataset from the XML Raster node
+*
+* @param image, the structure to be initialized
+* @param config, the Raster node of the xml structure
+* @param ds, the parent dataset, some things get inherited
+*
+* The structure should be initialized with the default values as much as possible
+*
+*/
+
+static CPLErr Init_Raster(ILImage &image, GDALMRFDataset *ds, CPLXMLNode *defimage)
+{
+    CPLXMLNode *node; // temporary
+    if (!defimage) {
+	CPLError(CE_Failure, CPLE_AppDefined, "GDAL MRF: Can't find raster info");
+	return CE_Failure;
+    }
+
+    // Size is mandatory
+    node = CPLGetXMLNode(defimage, "Size");
+
+    if (node) {
+	image.size = ILSize(
+	    static_cast<int>(getXMLNum(node, "x", -1)),
+	    static_cast<int>(getXMLNum(node, "y", -1)),
+	    static_cast<int>(getXMLNum(node, "z", 1)),
+	    static_cast<int>(getXMLNum(node, "c", 1)),
+	    0);
+    }
+
+    // Basic checks
+    if (!node || image.size.x < 1 || image.size.y < 1 ||
+        !GDALCheckBandCount(image.size.c, FALSE)) {
+	CPLError(CE_Failure, CPLE_AppDefined, "Raster size missing or invalid");
+	return CE_Failure;
+    }
+
+    //  Pagesize, defaults to 512,512,1,c
+    image.pagesize = ILSize(
+	MIN(512, image.size.x),
+	MIN(512, image.size.y),
+	1,
+	image.size.c);
+
+    node = CPLGetXMLNode(defimage, "PageSize");
+    if (node)
+    {
+	image.pagesize = ILSize(
+	static_cast<int>(getXMLNum(node, "x", image.pagesize.x)),
+	static_cast<int>(getXMLNum(node, "y", image.pagesize.y)),
+	1, // One z at a time, forced
+	static_cast<int>(getXMLNum(node, "c", image.pagesize.c)));
+        if( image.pagesize.x < 1 ||
+            image.pagesize.y < 1 ||
+            image.pagesize.c <= 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Invalid PageSize");
+            return CE_Failure;
+        }
+    }
+
+    // Orientation, some other systems might support something
+    //   if (!EQUAL(CPLGetXMLValue(defimage,"Orientation","TL"), "TL")) {
+    //// GDAL only handles Top Left Images
+    //CPLError(CE_Failure, CPLE_AppDefined, "GDAL MRF: Only Top-Left orientation is supported");
+    //return CE_Failure;
+    //   }
+
+    // Page Encoding, defaults to PNG
+    image.comp = CompToken(CPLGetXMLValue(defimage, "Compression", "PNG"));
+
+    if (image.comp == IL_ERR_COMP) {
+	CPLError(CE_Failure, CPLE_AppDefined,
+	    "GDAL MRF: Compression %s is unknown",
+	    CPLGetXMLValue(defimage, "Compression", NULL));
+	return CE_Failure;
+    }
+
+    // Is there a palette?
+    //
+    // GDAL only supports RGB+A palette, the other modes don't work
+    //
+    // Format is
+    // <Palette>
+    //   <Size>N</Size> : Optional
+    //   <Model>RGBA|RGB|CMYK|HSV|HLS|L</Model> :mandatory
+    //   <Entry idx=i c1=v1 c2=v2 c3=v3 c4=v4/> :Optional
+    //   <Entry .../>
+    // </Palette>
+    // the idx attribute is optional, it autoincrements
+    // The entries are actually vertices, interpolation takes place inside
+    // The palette starts initialized with zeros
+    // HSV and HLS are the similar, with c2 and c3 swapped
+    // RGB or RGBA are same
+    //
+
+    if ((image.pagesize.c == 1) && (NULL != (node = CPLGetXMLNode(defimage, "Palette")))) {
+	int entries = static_cast<int>(getXMLNum(node, "Size", 255));
+	GDALPaletteInterp eInterp = GPI_RGB;
+	// A flag to convert from HLS to HSV
+	CPLString pModel = CPLGetXMLValue(node, "Model", "RGB");
+
+	if ((entries > 0) && (entries < 257)) {
+	    int start_idx, end_idx;
+	    GDALColorEntry ce_start = { 0, 0, 0, 255 }, ce_end = { 0, 0, 0, 255 };
+
+	    // Create it and initialize it to nothing
+	    GDALColorTable *poColorTable = new GDALColorTable(eInterp);
+	    poColorTable->CreateColorRamp(0, &ce_start, entries - 1, &ce_end);
+	    // Read the values
+	    CPLXMLNode *p = CPLGetXMLNode(node, "Entry");
+	    if (p) {
+		// Initialize the first entry
+		ce_start = GetXMLColorEntry(p);
+		start_idx = static_cast<int>(getXMLNum(p, "idx", 0));
+		if (start_idx < 0) {
+		    CPLError(CE_Failure, CPLE_AppDefined,
+			"GDAL MRF: Palette index %d not allowed", start_idx);
+		    delete poColorTable;
+		    return CE_Failure;
+		}
+		poColorTable->SetColorEntry(start_idx, &ce_start);
+		while (NULL != (p = SearchXMLSiblings(p, "Entry"))) {
+		    // For every entry, create a ramp
+		    ce_end = GetXMLColorEntry(p);
+		    end_idx = static_cast<int>(getXMLNum(p, "idx", start_idx + 1));
+		    if ((end_idx <= start_idx) || (start_idx >= entries)) {
+			CPLError(CE_Failure, CPLE_AppDefined,
+			    "GDAL MRF: Index Error at index %d", end_idx);
+			delete poColorTable;
+			return CE_Failure;
+		    }
+		    poColorTable->CreateColorRamp(start_idx, &ce_start,
+			end_idx, &ce_end);
+ce_start = ce_end;
+start_idx = end_idx;
+		}
+	    }
+
+	    ds->SetColorTable(poColorTable);
+	}
+	else {
+	    CPLError(CE_Failure, CPLE_AppDefined, "GDAL MRF: Palette definition error");
+	    return CE_Failure;
+	}
+    }
+
+    // Order of increment
+    image.order = OrderToken(CPLGetXMLValue(defimage, "Order",
+	(image.pagesize.c != image.size.c) ? "BAND" : "PIXEL"));
+    if (image.order == IL_ERR_ORD) {
+	CPLError(CE_Failure, CPLE_AppDefined, "GDAL MRF: Order %s is unknown",
+	    CPLGetXMLValue(defimage, "Order", NULL));
+	return CE_Failure;
+    }
+
+    image.quality = atoi(CPLGetXMLValue(defimage, "Quality", "85"));
+
+    const char * photo_val = CPLGetXMLValue(defimage, "Photometric", NULL);
+    if (photo_val)
+	ds->SetPhotometricInterpretation(photo_val);
+
+    if (image.quality < 0 || image.quality>99) {
+	CPLError(CE_Warning, CPLE_AppDefined, "GDAL MRF: Quality setting error, using default of 85");
+	image.quality = 85;
+    }
+
+    // Data Type, use GDAL Names
+    image.dt = GDALGetDataTypeByName(
+	CPLGetXMLValue(defimage, "DataType", GDALGetDataTypeName(image.dt)));
+    if (image.dt == GDT_Unknown || GDALGetDataTypeSize(image.dt) == 0 ) {
+	CPLError(CE_Failure, CPLE_AppDefined, "GDAL MRF: Image has wrong type");
+	return CE_Failure;
+    }
+
+    // Check the endianness if needed, assume host order
+    if (is_Endianess_Dependent(image.dt, image.comp))
+	image.nbo = on(CPLGetXMLValue(defimage, "NetByteOrder", "No"));
+
+    CPLXMLNode *DataValues = CPLGetXMLNode(defimage, "DataValues");
+    if (NULL != DataValues) {
+	const char *pszValue;
+	pszValue = CPLGetXMLValue(DataValues, "NoData", NULL);
+	if (pszValue) ds->SetNoDataValue(pszValue);
+	pszValue = CPLGetXMLValue(DataValues, "min", NULL);
+	if (pszValue) ds->SetMinValue(pszValue);
+	pszValue = CPLGetXMLValue(DataValues, "max", NULL);
+	if (pszValue) ds->SetMaxValue(pszValue);
+    }
+
+    // Calculate the page size in bytes
+    if( image.pagesize.z <= 0 ||
+        image.pagesize.x > INT_MAX / image.pagesize.y ||
+        image.pagesize.x * image.pagesize.y > INT_MAX / image.pagesize.z ||
+        image.pagesize.x * image.pagesize.y * image.pagesize.z > INT_MAX / image.pagesize.c ||
+        image.pagesize.x * image.pagesize.y * image.pagesize.z* image.pagesize.c  > INT_MAX / (GDALGetDataTypeSize(image.dt) / 8) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "MRF page size too big");
+        return CE_Failure;
+    }
+    image.pageSizeBytes = (GDALGetDataTypeSize(image.dt) / 8) *
+	image.pagesize.x * image.pagesize.y * image.pagesize.z * image.pagesize.c;
+
+    // Calculate the page count, including the total for the level
+    image.pagecount = pcount(image.size, image.pagesize);
+
+    // Data File Name and base offset
+    image.datfname = getFname(defimage, "DataFile", ds->GetFname(), ILComp_Ext[image.comp]);
+    image.dataoffset = static_cast<int>(
+	getXMLNum(CPLGetXMLNode(defimage, "DataFile"), "offset", 0.0));
+
+    // Index File Name and base offset
+    image.idxfname = getFname(defimage, "IndexFile", ds->GetFname(), ".idx");
+    image.idxoffset = static_cast<int>(
+	getXMLNum(CPLGetXMLNode(defimage, "IndexFile"), "offset", 0.0));
+
+    return CE_None;
+}
+
+char      **GDALMRFDataset::GetFileList()
+{
+    char** papszFileList = NULL;
+
+    // Add the header file name if it is real
+    VSIStatBufL  sStat;
+    if (VSIStatExL(fname, &sStat, VSI_STAT_EXISTS_FLAG) == 0)
+	papszFileList = CSLAddString(papszFileList, fname);
+
+    // These two should be real
+    // We don't really want to add these files, since they will be erased when an mrf is overwritten
+    // This collides with the concept that the data file never shrinks.  Same goes with the index, in case
+    // we just want to add things to it.
+    //    papszFileList = CSLAddString( papszFileList, full.datfname);
+    //    papszFileList = CSLAddString( papszFileList, full.idxfname);
+    //    if (!source.empty())
+    //	papszFileList = CSLAddString( papszFileList, source);
+
+    return papszFileList;
+}
+
+// Try to create all the folders in the path in sequence, ignore errors
+static void mkdir_r(string const &fname) {
+    size_t loc = fname.find_first_of("\\/");
+    if( loc == string::npos )
+        return;
+    while (true) {
+        ++ loc;
+	loc = fname.find_first_of("\\/", loc);
+        if( loc == string::npos )
+            break;
+	VSIMkdir(fname.substr(0, loc).c_str(), 0);
+    }
+}
+
+// Returns the dataset index file or null
+VSILFILE *GDALMRFDataset::IdxFP() {
+    if (ifp.FP != NULL)
+	return ifp.FP;
+
+    const char *mode = "rb";
+    ifp.acc = GF_Read;
+
+    if (eAccess == GA_Update || !source.empty()) {
+	mode = "r+b";
+	ifp.acc = GF_Write;
+    }
+
+    ifp.FP = VSIFOpenL(current.idxfname, mode);
+
+    // need to create the index file
+    if (ifp.FP == NULL && !bCrystalized && (eAccess == GA_Update || !source.empty())) {
+	mode = "w+b";
+	ifp.FP = VSIFOpenL(current.idxfname, mode);
+    }
+
+    if (NULL == ifp.FP && !source.empty()) {
+	// caching and cloning, try making the folder and attempt again
+	mkdir_r(current.idxfname);
+	ifp.FP = VSIFOpenL(current.idxfname, mode);
+    }
+
+    GIntBig expected_size = idxSize;
+    if (clonedSource) expected_size *= 2;
+
+    if (NULL != ifp.FP) {
+	if (!bCrystalized && !CheckFileSize(current.idxfname, expected_size, GA_Update)) {
+	    CPLError(CE_Failure, CPLE_AppDefined, "Can't extend the cache index file %s",
+		current.idxfname.c_str());
+	    return NULL;
+	}
+
+	if (source.empty())
+	    return ifp.FP;
+
+	// Make sure the index is large enough before proceeding
+	// Timeout in .1 seconds, can't really guarantee the accuracy
+	// So this is about half second, should be sufficient
+	int timeout = 5;
+	do {
+	    if (CheckFileSize(current.idxfname, expected_size, GA_ReadOnly))
+		return ifp.FP;
+	    CPLSleep(0.100); /* 100 ms */
+	} while (--timeout);
+
+	// If we get here it is a time-out
+	CPLError(CE_Failure, CPLE_AppDefined,
+	    "GDAL MRF: Timeout on fetching cloned index file %s\n", current.idxfname.c_str());
+	return NULL;
+    }
+
+    // Error if this is not a caching MRF
+    if (source.empty()) {
+	CPLError(CE_Failure, CPLE_AppDefined,
+	    "GDAL MRF: Can't open index file %s\n", current.idxfname.c_str());
+	return NULL;
+    }
+
+    // Caching/Cloning MRF and index could be read only
+    // Is this actually works, we should try again, maybe somebody else just created the file?
+    mode = "rb";
+    ifp.acc = GF_Read;
+    ifp.FP = VSIFOpenL(current.idxfname, mode);
+    if (NULL != ifp.FP)
+	return ifp.FP;
+
+    // Caching and index file absent, create it
+    // Due to a race, multiple processes might do this at the same time, but that is fine
+    ifp.FP = VSIFOpenL(current.idxfname, "wb");
+    if (NULL == ifp.FP) {
+	CPLError(CE_Failure, CPLE_AppDefined, "Can't create the MRF cache index file %s",
+	    current.idxfname.c_str());
+	return NULL;
+    }
+    VSIFCloseL(ifp.FP);
+    ifp.FP = NULL;
+
+    // Make it large enough for caching and for cloning
+    if (!CheckFileSize(current.idxfname, expected_size, GA_Update)) {
+	CPLError(CE_Failure, CPLE_AppDefined, "Can't extend the cache index file %s",
+	    current.idxfname.c_str());
+	return NULL;
+    }
+
+    // Try opening it again in rw mode so we can read and write
+    mode = "r+b";
+    ifp.acc = GF_Write;
+    ifp.FP = VSIFOpenL(current.idxfname.c_str(), mode);
+
+    if (NULL == ifp.FP) {
+	CPLError(CE_Failure, CPLE_AppDefined,
+	    "GDAL MRF: Can't reopen cache index file %s\n", full.idxfname.c_str());
+	return NULL;
+    }
+    return ifp.FP;
+}
+
+//
+// Returns the dataset data file or null
+// Data file is opened either in Read or Append mode, never in straight write
+//
+VSILFILE *GDALMRFDataset::DataFP() {
+    if (dfp.FP != NULL)
+	return dfp.FP;
+    const char *mode = "rb";
+    dfp.acc = GF_Read;
+
+    // Open it for writing if updating or if caching
+    if (eAccess == GA_Update || !source.empty()) {
+	mode = "a+b";
+	dfp.acc = GF_Write;
+    }
+
+    dfp.FP = VSIFOpenL(current.datfname, mode);
+    if (dfp.FP)
+	return dfp.FP;
+
+    // It could be a caching MRF
+    if (source.empty())
+	goto io_error;
+
+    // Cloud be there but read only, remember that it was open that way
+    mode = "rb";
+    dfp.acc = GF_Read;
+    dfp.FP = VSIFOpenL(current.datfname, mode);
+    if (NULL != dfp.FP) {
+	CPLDebug("MRF_IO", "Opened %s RO mode %s\n", current.datfname.c_str(), mode);
+	return dfp.FP;
+    }
+
+    if (source.empty())
+	goto io_error;
+
+    // caching, maybe the folder didn't exist
+    mkdir_r(current.datfname);
+    mode = "a+b";
+    dfp.acc = GF_Write;
+    dfp.FP = VSIFOpenL(current.datfname, mode);
+    if (dfp.FP)
+	return dfp.FP;
+
+io_error:
+    dfp.FP = NULL;
+    CPLError(CE_Failure, CPLE_FileIO,
+	"GDAL MRF: %s : %s", strerror(errno), current.datfname.c_str());
+    return NULL;
+};
+
+// Builds an XML tree from the current MRF.  If written to a file it becomes an MRF
+CPLXMLNode * GDALMRFDataset::BuildConfig()
+{
+    CPLXMLNode *config = CPLCreateXMLNode(NULL, CXT_Element, "MRF_META");
+
+    if (!source.empty()) {
+	CPLXMLNode *CS = CPLCreateXMLNode(config, CXT_Element, "CachedSource");
+	// Should wrap the string in CDATA, in case it is XML
+	CPLXMLNode *S = CPLCreateXMLElementAndValue(CS, "Source", source);
+	if (clonedSource)
+	    CPLSetXMLValue(S, "#clone", "true");
+    }
+
+    // Use the full size
+    CPLXMLNode *raster = CPLCreateXMLNode(config, CXT_Element, "Raster");
+    XMLSetAttributeVal(raster, "Size", full.size, "%.0f");
+    XMLSetAttributeVal(raster, "PageSize", full.pagesize, "%.0f");
+
+    if (full.comp != IL_PNG)
+	CPLCreateXMLElementAndValue(raster, "Compression", CompName(full.comp));
+
+    if (full.dt != GDT_Byte)
+	CPLCreateXMLElementAndValue(raster, "DataType", GDALGetDataTypeName(full.dt));
+
+    // special photometric interpretation
+    if (!photometric.empty())
+	CPLCreateXMLElementAndValue(raster, "Photometric", photometric);
+
+    if (vNoData.size() || vMin.size() || vMax.size()) {
+	CPLXMLNode *values = CPLCreateXMLNode(raster, CXT_Element, "DataValues");
+	XMLSetAttributeVal(values, "NoData", vNoData);
+	XMLSetAttributeVal(values, "min", vMin);
+	XMLSetAttributeVal(values, "max", vMax);
+    }
+
+    // palette, if we have one
+    if (poColorTable != NULL) {
+	const char *pfrmt = "%.0f";
+	CPLXMLNode *pal = CPLCreateXMLNode(raster, CXT_Element, "Palette");
+	int sz = poColorTable->GetColorEntryCount();
+	if (sz != 256)
+	    XMLSetAttributeVal(pal, "Size", poColorTable->GetColorEntryCount());
+	// RGB or RGBA for now
+	for (int i = 0; i < sz; i++) {
+	    CPLXMLNode *entry = CPLCreateXMLNode(pal, CXT_Element, "Entry");
+	    const GDALColorEntry *ent = poColorTable->GetColorEntry(i);
+	    // No need to set the index, it is always from 0 no size-1
+	    XMLSetAttributeVal(entry, "c1", ent->c1, pfrmt);
+	    XMLSetAttributeVal(entry, "c2", ent->c2, pfrmt);
+	    XMLSetAttributeVal(entry, "c3", ent->c3, pfrmt);
+	    if (ent->c4 != 255)
+		XMLSetAttributeVal(entry, "c4", ent->c4, pfrmt);
+	}
+    }
+
+    if (is_Endianess_Dependent(full.dt, full.comp)) // Need to set the order
+	CPLCreateXMLElementAndValue(raster, "NetByteOrder",
+	(full.nbo || NET_ORDER) ? "TRUE" : "FALSE");
+
+    if (full.quality > 0 && full.quality != 85)
+	CPLCreateXMLElementAndValue(raster, "Quality",
+	    CPLString().Printf("%d", full.quality));
+
+    // Done with the raster node
+
+    if (scale) {
+	CPLCreateXMLNode(config, CXT_Element, "Rsets");
+	CPLSetXMLValue(config, "Rsets.#model", "uniform");
+	CPLSetXMLValue(config, "Rsets.#scale", PrintDouble(scale));
+    }
+    CPLXMLNode *gtags = CPLCreateXMLNode(config, CXT_Element, "GeoTags");
+
+    // Do we have an affine transform different from identity?
+    double gt[6];
+    if ((GetGeoTransform(gt) == CE_None) &&
+	(gt[0] != 0 || gt[1] != 1 || gt[2] != 0 ||
+	gt[3] != 0 || gt[4] != 0 || gt[5] != 1))
+    {
+	double minx = gt[0];
+	double maxx = gt[1] * full.size.x + minx;
+	double maxy = gt[3];
+	double miny = gt[5] * full.size.y + maxy;
+	CPLXMLNode *bbox = CPLCreateXMLNode(gtags, CXT_Element, "BoundingBox");
+	XMLSetAttributeVal(bbox, "minx", minx);
+	XMLSetAttributeVal(bbox, "miny", miny);
+	XMLSetAttributeVal(bbox, "maxx", maxx);
+	XMLSetAttributeVal(bbox, "maxy", maxy);
+    }
+
+    const char *pszProj = GetProjectionRef();
+    if (pszProj && (!EQUAL(pszProj, "")))
+	CPLCreateXMLElementAndValue(gtags, "Projection", pszProj);
+
+    if (optlist.size()) {
+	CPLString options;
+	for (int i = 0; i < optlist.size(); i++) {
+	    options += optlist[i];
+	    options += ' ';
+	}
+	options.resize(options.size() - 1);
+	CPLCreateXMLElementAndValue(config, "Options", options);
+    }
+
+    return config;
+}
+
+
+/**
+* \Brief Populates the dataset variables from the XML definition
+*
+*
+*/
+CPLErr GDALMRFDataset::Initialize(CPLXMLNode *config)
+
+{
+    // We only need a basic initialization here, usually gets overwritten by the image params
+    full.dt = GDT_Byte;
+    full.hasNoData = false;
+    full.NoDataValue = 0;
+    Quality = 85;
+
+    CPLErr ret = Init_Raster(full, this, CPLGetXMLNode(config, "Raster"));
+
+    hasVersions = on(CPLGetXMLValue(config, "Raster.versioned", "no"));
+    mp_safe = on(CPLGetXMLValue(config, "Raster.mp_safe", "no"));
+
+    Quality = full.quality;
+    if (CE_None != ret)
+	return ret;
+
+    // Bounding box
+    CPLXMLNode *bbox = CPLGetXMLNode(config, "GeoTags.BoundingBox");
+    if (NULL != bbox) {
+	double x0, x1, y0, y1;
+
+	x0 = atof(CPLGetXMLValue(bbox, "minx", "0"));
+	x1 = atof(CPLGetXMLValue(bbox, "maxx", "1"));
+	y1 = atof(CPLGetXMLValue(bbox, "maxy", "1"));
+	y0 = atof(CPLGetXMLValue(bbox, "miny", "0"));
+
+	GeoTransform[0] = x0;
+	GeoTransform[1] = (x1 - x0) / full.size.x;
+	GeoTransform[2] = 0;
+	GeoTransform[3] = y1;
+	GeoTransform[4] = 0;
+	GeoTransform[5] = (y0 - y1) / full.size.y;
+	bGeoTransformValid = TRUE;
+    }
+
+    SetProjection(CPLGetXMLValue(config, "GeoTags.Projection", ""));
+
+    // Copy the full size to current, data and index are not yet open
+    current = full;
+    if (current.size.z != 1) {
+	SetMetadataItem("ZSIZE", CPLString().Printf("%d", current.size.z), "IMAGE_STRUCTURE");
+	SetMetadataItem("ZSLICE", CPLString().Printf("%d", zslice), "IMAGE_STRUCTURE");
+	// Capture the zslice in pagesize.l
+	current.pagesize.l = zslice;
+	// Adjust offset for base image
+        if( full.size.z <= 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "GDAL MRF: Invalid Raster.z value");
+            return CE_Failure;
+        }
+	current.idxoffset += sizeof(ILIdx) * current.pagecount.l / full.size.z * zslice;
+    }
+
+    // Dataset metadata setup
+    SetMetadataItem("INTERLEAVE", OrderName(current.order), "IMAGE_STRUCTURE");
+    SetMetadataItem("COMPRESSION", CompName(current.comp), "IMAGE_STRUCTURE");
+
+    if (is_Endianess_Dependent(current.dt, current.comp))
+	SetMetadataItem("NETBYTEORDER", current.nbo ? "TRUE" : "FALSE", "IMAGE_STRUCTURE");
+
+    // Open the files for the current image, either RW or RO
+    nRasterXSize = current.size.x;
+    nRasterYSize = current.size.y;
+    nBands = current.size.c;
+
+    if (!nBands || !nRasterXSize || !nRasterYSize) {
+	CPLError(CE_Failure, CPLE_AppDefined, "GDAL MRF: Image size missing");
+	return CE_Failure;
+    }
+
+    // Pick up the source data image, if there is one
+    source = CPLGetXMLValue(config, "CachedSource.Source", "");
+    // Is it a clone?
+    clonedSource = on(CPLGetXMLValue(config, "CachedSource.Source.clone", "no"));
+    // Pick up the options, if any
+    optlist.Assign(CSLTokenizeString2(CPLGetXMLValue(config, "Options", NULL),
+	" \t\n\r", CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES));
+
+    // Load all the options in the IMAGE_STRUCTURE metadata
+    for (int i = 0; i < optlist.Count(); i++) {
+	CPLString s(optlist[i]);
+        size_t nSepPos = s.find_first_of(":=");
+        if( nSepPos != std::string::npos )
+        {
+            s.resize(nSepPos);
+            const char *key = s.c_str();
+            SetMetadataItem(key, optlist.FetchNameValue(key), "IMAGE_STRUCTURE");
+        }
+    }
+
+    // We have the options, so we can call rasterband
+    for (int i = 1; i <= nBands; i++) {
+	// The overviews are low resolution copies of the current one.
+	GDALMRFRasterBand *band = newMRFRasterBand(this, current, i);
+	if (!band)
+	    return CE_Failure;
+
+	GDALColorInterp ci = GCI_Undefined;
+
+	// Default color interpretation
+	switch (nBands) {
+	case 1:
+	case 2:
+	    ci = (i == 1) ? GCI_GrayIndex : GCI_AlphaBand;
+	    break;
+	case 3:
+	case 4:
+	    if (i < 3)
+		ci = (i == 1) ? GCI_RedBand : GCI_GreenBand;
+	    else
+		ci = (i == 3) ? GCI_BlueBand : GCI_AlphaBand;
+	}
+
+	if (GetColorTable())
+	    ci = GCI_PaletteIndex;
+
+	// Legacy, deprecated
+	if (optlist.FetchBoolean("MULTISPECTRAL", FALSE))
+	    ci = GCI_Undefined;
+
+	// New style
+	if (photometric.size()) {
+	    if ("MULTISPECTRAL" == photometric)
+		ci = GCI_Undefined;
+	}
+
+	band->SetColorInterpretation(ci);
+	SetBand(i, band);
+    }
+
+    CPLXMLNode *rsets = CPLGetXMLNode(config, "Rsets");
+    if (NULL != rsets && NULL != rsets->psChild) {
+	// We have rsets
+
+	// Regular spaced overlays, until everything fits in a single tile
+	if (EQUAL("uniform", CPLGetXMLValue(rsets, "model", "uniform"))) {
+	    scale = getXMLNum(rsets, "scale", 2.0);
+	    if (scale <= 1) {
+		CPLError(CE_Failure, CPLE_AppDefined, "MRF: zoom factor less than unit not allowed");
+		return CE_Failure;
+	    }
+	    // Looks like there are overlays
+	    AddOverviews(int(scale));
+	}
+	else {
+	    CPLError(CE_Failure, CPLE_AppDefined, "Unknown Rset definition");
+	    return CE_Failure;
+	}
+
+    }
+
+    idxSize = IdxSize(full, int(scale));
+
+    // If not set by the bands, get a pageSizeBytes buffer
+    if (GetPBufferSize() == 0)
+    {
+        if( !SetPBuffer(current.pageSizeBytes) )
+        {
+            return CE_Failure;
+        }
+    }
+
+    if (hasVersions) { // It has versions, but how many?
+	verCount = 0; // Assume it only has one
+	VSIStatBufL statb;
+	//  If the file exists, compute the last version number
+	if (0 == VSIStatL(full.idxfname, &statb))
+	    verCount = int(statb.st_size / idxSize - 1);
+    }
+
+    return CE_None;
+}
+
+static inline bool has_path(const CPLString &name)
+{
+    return name.find_first_of("/\\") != string::npos;
+}
+
+static inline bool is_absolute(const CPLString &name)
+{
+    return (name.find_first_of("/\\") == 0) ||
+	(name[1] == ':' && isalpha(name[0])) ||
+	name.find("<MRF_META>") != string::npos;
+}
+
+// Add the folder part of path to the beginning of the source, if it is relative
+static inline void make_absolute(CPLString &name, const CPLString &path)
+{
+    if (!is_absolute(path) && (path.find_first_of("/\\") != string::npos))
+	name = path.substr(0, path.find_last_of("/\\") + 1) + name;
+}
+
+/**
+*\Brief Get the source dataset, open it if necessary
+*/
+GDALDataset *GDALMRFDataset::GetSrcDS() {
+    if (poSrcDS) return poSrcDS;
+    if (source.empty())	return NULL;
+    // Make the source absolute path
+    if (has_path(fname)) make_absolute(source, fname);
+    poSrcDS = (GDALDataset *)GDALOpenShared(source.c_str(), GA_ReadOnly);
+    if (0 == source.find("<MRF_META>") && has_path(fname))
+    {// XML MRF source, might need to patch the file names with the current one
+	GDALMRFDataset *psDS = reinterpret_cast<GDALMRFDataset *>(poSrcDS);
+	make_absolute(psDS->current.datfname, fname);
+	make_absolute(psDS->current.idxfname, fname);
+    }
+    mp_safe = true; // Turn on MP safety
+    return poSrcDS;
+}
+
+/**
+*\Brief Add or verify that all overlays exits
+*
+* @return size of the index file
+*/
+
+GIntBig GDALMRFDataset::AddOverviews(int scaleIn) {
+    // Fit the overlays
+    ILImage img = current;
+    while (1 != img.pagecount.x*img.pagecount.y)
+    {
+	// Adjust raster data for next level
+	// Adjust the offsets for indices left at this level
+	img.idxoffset += sizeof(ILIdx) * img.pagecount.l / img.size.z * (img.size.z - zslice);
+
+	// Next overview size
+	img.size.x = pcount(img.size.x, scaleIn);
+	img.size.y = pcount(img.size.y, scaleIn);
+	img.size.l++; // Increment the level
+	img.pagecount = pcount(img.size, img.pagesize);
+
+	// And adjust the offset again, within next level
+	img.idxoffset += sizeof(ILIdx) * img.pagecount.l / img.size.z * zslice;
+
+	// Create and register the the overviews for each band
+	for (int i = 1; i <= nBands; i++) {
+	    GDALMRFRasterBand *b = (GDALMRFRasterBand *)GetRasterBand(i);
+	    if (!(b->GetOverview(img.size.l - 1)))
+		b->AddOverview(newMRFRasterBand(this, img, i, img.size.l));
+	}
+    }
+
+    // Last adjustment, should be a single set of c and leftover z tiles
+    return img.idxoffset + sizeof(ILIdx) * img.pagecount.l / img.size.z * (img.size.z - zslice);
+}
+
+// Try to implement CreateCopy using Create
+GDALDataset *GDALMRFDataset::CreateCopy(const char *pszFilename,
+    GDALDataset *poSrcDS, int /*bStrict*/, char **papszOptions,
+    GDALProgressFunc pfnProgress, void *pProgressData)
+{
+    ILImage img;
+
+    int x = poSrcDS->GetRasterXSize();
+    int y = poSrcDS->GetRasterYSize();
+    int nBands = poSrcDS->GetRasterCount();
+    if( nBands == 0 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, "nBands == 0 not supported");
+        return NULL;
+    }
+    GDALRasterBand *poSrcBand1 = poSrcDS->GetRasterBand(1);
+
+    GDALDataType dt = poSrcBand1->GetRasterDataType();
+    GDALMRFDataset *poDS = NULL;
+
+    // Have our own options, to modify as we want
+    char **options = CSLDuplicate(papszOptions);
+
+    const char *pszValue = poSrcDS->GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE");
+    options = CSLAddIfMissing(options, "INTERLEAVE", pszValue ? pszValue : "PIXEL");
+
+    try {
+	poDS = reinterpret_cast<GDALMRFDataset *>(
+	    Create(pszFilename, x, y, nBands, dt, options));
+
+	if (poDS == NULL || poDS->bCrystalized)
+	    throw CPLString().Printf("Can't create %s",pszFilename);
+
+	img = poDS->current; // Deal with the current one here
+
+	// Copy data values from source
+	for (int i = 0; i < poDS->nBands; i++) {
+	    int bHas;
+	    double dfData;
+	    GDALRasterBand *srcBand = poSrcDS->GetRasterBand(i + 1);
+	    GDALRasterBand *mBand = poDS->GetRasterBand(i + 1);
+	    dfData = srcBand->GetNoDataValue(&bHas);
+	    if (bHas) {
+		poDS->vNoData.push_back(dfData);
+		mBand->SetNoDataValue(dfData);
+	    }
+	    dfData = srcBand->GetMinimum(&bHas);
+	    if (bHas)
+		poDS->vMin.push_back(dfData);
+	    dfData = srcBand->GetMaximum(&bHas);
+	    if (bHas)
+		poDS->vMax.push_back(dfData);
+
+	    // Copy the band metadata, PAM will handle it
+	    char **meta = srcBand->GetMetadata("IMAGE_STRUCTURE");
+	    if (CSLCount(meta))
+		mBand->SetMetadata(meta,"IMAGE_STRUCTURE");
+
+	    meta = srcBand->GetMetadata();
+	    if (CSLCount(meta))
+		mBand->SetMetadata(meta);
+	}
+
+	// Geotags
+	double gt[6];
+	if (CE_None == poSrcDS->GetGeoTransform(gt))
+	    poDS->SetGeoTransform(gt);
+
+	const char *pszProj = poSrcDS->GetProjectionRef();
+	if (pszProj && pszProj[0])
+	    poDS->SetProjection(pszProj);
+
+	// Color palette if we only have one band
+	if (1 == nBands && GCI_PaletteIndex == poSrcBand1->GetColorInterpretation())
+	    poDS->SetColorTable(poSrcBand1->GetColorTable()->Clone());
+
+	// Copy input GCPs, PAM handles it
+	if (poSrcDS->GetGCPCount())
+	    poDS->SetGCPs(poSrcDS->GetGCPCount(), poSrcDS->GetGCPs(), poSrcDS->GetGCPProjection());
+
+
+	// Finally write the XML in the right file name
+	poDS->Crystalize();
+    }
+    catch (CPLString(e)) {
+	if (poDS)
+	    delete poDS;
+	CPLError(CE_Failure, CPLE_ObjectNull, "%s", e.c_str());
+	poDS = NULL;
+    }
+
+    CSLDestroy(options);
+
+    char **meta = poSrcDS->GetMetadata();
+    if (poDS && CSLCount(meta))
+	poDS->SetMetadata(meta);
+
+    meta = poSrcDS->GetMetadata("RPC");
+    if (poDS && CSLCount(meta))
+	poDS->SetMetadata(meta, "RPC");
+
+    // If copy is disabled, we're done, we just created an empty MRF
+    if (!poDS || on(CSLFetchNameValue(papszOptions, "NOCOPY")))
+	return poDS;
+
+    // Use the GDAL copy call
+    // Need to flag the dataset as compressed (COMPRESSED=TRUE) to force block writes
+    // This might not be what we want, if the input and out order is truly separate
+    char **papszCWROptions = NULL;
+    papszCWROptions = CSLAddNameValue(papszCWROptions, "COMPRESSED", "TRUE");
+    CPLErr err = GDALDatasetCopyWholeRaster((GDALDatasetH)poSrcDS,
+	(GDALDatasetH)poDS, papszCWROptions, pfnProgress, pProgressData);
+
+    CSLDestroy(papszCWROptions);
+
+    if (CE_Failure == err) {
+	delete poDS;
+	return NULL;
+    }
+
+    return poDS;
+}
+
+// Apply create options to the current dataset, only valid during creation
+void GDALMRFDataset::ProcessCreateOptions(char **papszOptions)
+{
+    assert(!bCrystalized);
+    CPLStringList opt(papszOptions, FALSE);
+    ILImage &img(full);
+
+    const char *val;
+
+    val = opt.FetchNameValue("COMPRESS");
+    if (val && IL_ERR_COMP == (img.comp = CompToken(val)))
+	throw CPLString("GDAL MRF: Error setting compression");
+
+    val = opt.FetchNameValue("INTERLEAVE");
+    if (val && IL_ERR_ORD == (img.order = OrderToken(val)))
+	throw CPLString("GDAL MRF: Error setting interleave");
+
+    val = opt.FetchNameValue("QUALITY");
+    if (val) img.quality = atoi(val);
+
+    val = opt.FetchNameValue("ZSIZE");
+    if (val) img.size.z = atoi(val);
+
+    val = opt.FetchNameValue("BLOCKXSIZE");
+    if (val) img.pagesize.x = atoi(val);
+
+    val = opt.FetchNameValue("BLOCKYSIZE");
+    if (val) img.pagesize.y = atoi(val);
+
+    val = opt.FetchNameValue("BLOCKSIZE");
+    if (val) img.pagesize.x = img.pagesize.y = atoi(val);
+
+    img.nbo = opt.FetchBoolean("NETBYTEORDER", FALSE);
+
+    val = opt.FetchNameValue("CACHEDSOURCE");
+    if (val) source = val;
+
+    val = opt.FetchNameValue("UNIFORM_SCALE");
+    if (val) scale = atoi(val);
+
+    val = opt.FetchNameValue("PHOTOMETRIC");
+    if (val) photometric = val;
+
+    optlist.Assign(CSLTokenizeString2(opt.FetchNameValue("OPTIONS"),
+	" \t\n\r", CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES));
+
+    // General Fixups
+    if (img.order == IL_Interleaved)
+	img.pagesize.c = img.size.c;
+
+    // Compression dependent fixups
+#if defined(LERC)
+    if (IL_LERC == img.comp)
+	img.pagesize.c = 1;
+#endif
+
+}
+
+/**
+ *\Brief Create an MRF dataset, some settings can be changed later
+ * papszOptions might be anything that an MRF might take
+ * Still missing are the georeference ...
+ *
+ */
+
+GDALDataset *
+GDALMRFDataset::Create(const char * pszName,
+    int nXSize, int nYSize, int nBands,
+    GDALDataType eType, char ** papszOptions)
+
+{   // Pending create
+    if( nBands == 0 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, "nBands == 0 not supported");
+        return NULL;
+    }
+
+    GDALMRFDataset *poDS = new GDALMRFDataset();
+    CPLErr err = CE_None;
+    poDS->fname = pszName;
+    poDS->nBands = nBands;
+
+    // Don't know what to do with these in this call
+    //int level = -1;
+    //int version = 0;
+
+    size_t pos = poDS->fname.find(":MRF:");
+    if (string::npos != pos) { // Tokenize and pick known options
+	vector<string> tokens;
+	stringSplit(tokens, poDS->fname, pos + 5, ':');
+	//level = getnum(tokens, 'L', -1);
+	//version = getnum(tokens, 'V', 0);
+	poDS->zslice = getnum(tokens, 'Z', 0);
+	poDS->fname.resize(pos); // Cut the ornamentations
+    }
+
+    // Use the full, set some initial parameters
+    ILImage &img = poDS->full;
+    img.size = ILSize(nXSize, nYSize, 1, nBands);
+    img.comp = IL_PNG;
+    img.order = (nBands < 5) ? IL_Interleaved : IL_Separate;
+    img.pagesize = ILSize(512, 512, 1, 1);
+    img.quality = 85;
+    img.dt = eType;
+    img.dataoffset = 0;
+    img.idxoffset = 0;
+    img.hasNoData = false;
+    img.nbo = FALSE;
+
+    // Set the guard that tells us it needs saving before IO can take place
+    poDS->bCrystalized = 0;
+
+    // Process the options, anything that an MRF might take
+
+    try {
+	// Adjust the dataset and the full image
+	poDS->ProcessCreateOptions(papszOptions);
+
+	// Set default file names
+	img.datfname = getFname(poDS->GetFname(), ILComp_Ext[img.comp]);
+	img.idxfname = getFname(poDS->GetFname(), ".idx");
+
+	poDS->eAccess = GA_Update;
+    }
+
+    catch (CPLString e) {
+	CPLError(CE_Failure, CPLE_OpenFailed, "%s", e.c_str());
+	delete poDS;
+	return NULL;
+    }
+
+    poDS->current = poDS->full;
+    poDS->SetDescription(poDS->GetFname());
+
+    // Build a MRF XML and initialize from it, this creates the bands
+    CPLXMLNode *config = poDS->BuildConfig();
+    err = poDS->Initialize(config);
+    CPLDestroyXMLNode(config);
+
+    if (CPLE_None != err) {
+	delete poDS;
+	return NULL;
+    }
+
+    // If not set by the band, get a pageSizeBytes buffer
+    if (poDS->GetPBufferSize() == 0)
+    {
+        if( !poDS->SetPBuffer(poDS->current.pageSizeBytes) )
+        {
+            delete poDS;
+            return NULL;
+        }
+    }
+
+    // Tell PAM what our real file name is, to help it find the aux.xml
+    poDS->SetPhysicalFilename(poDS->GetFname());
+
+    return poDS;
+}
+
+void GDALMRFDataset::Crystalize()
+
+{
+    if (bCrystalized || eAccess != GA_Update)
+	return;
+
+    // No need to write to disk if there is no filename.  This is a
+    // memory only dataset.
+    if (strlen(GetDescription()) == 0
+	|| EQUALN(GetDescription(), "<MRF_META>", 10))
+	return;
+
+    CPLXMLNode *config = BuildConfig();
+    WriteConfig(config);
+    CPLDestroyXMLNode(config);
+    if (!IdxFP() || !DataFP())
+	throw CPLString().Printf("MRF: Can't create file %s", strerror(errno));
+
+    bCrystalized = TRUE;
+}
+
+// Copy the first index at the end of the file and bump the version count
+CPLErr GDALMRFDataset::AddVersion()
+{
+    VSILFILE *l_ifp = IdxFP();
+
+    void *tbuff = CPLMalloc(static_cast<size_t>(idxSize));
+    VSIFSeekL(l_ifp, 0, SEEK_SET);
+    VSIFReadL(tbuff, 1, static_cast<size_t>(idxSize), l_ifp);
+    verCount++; // The one we write
+    VSIFSeekL(l_ifp, idxSize * verCount, SEEK_SET); // At the end, this can mess things up royally
+    VSIFWriteL(tbuff, 1, static_cast<size_t>(idxSize), l_ifp);
+    CPLFree(tbuff);
+    return CE_None;
+}
+
+//
+// Write a tile at the end of the data file
+// If buff and size are zero, it is equivalent to erasing the tile
+// If only size is zero, it is a special empty tile,
+// when used for caching, offset should be 1
+//
+// To make it multi-processor safe, open the file in append mode
+// and verify after write
+//
+CPLErr GDALMRFDataset::WriteTile(void *buff, GUIntBig infooffset, GUIntBig size)
+{
+    CPLErr ret = CE_None;
+    ILIdx tinfo = { 0, 0 };
+
+    VSILFILE *l_dfp = DataFP();
+    VSILFILE *l_ifp = IdxFP();
+
+    // Pointer to verfiy buffer, if it doesn't exist everything worked fine
+    void *tbuff = NULL;
+
+    if (l_ifp == NULL || l_dfp == NULL)
+	return CE_Failure;
+
+    if (hasVersions) {
+	int new_version = false; // Assume no need to build new version
+	int new_tile = false;
+
+	// Read the current tile info
+	VSIFSeekL(l_ifp, infooffset, SEEK_SET);
+	VSIFReadL(&tinfo, 1, sizeof(ILIdx), l_ifp);
+
+	if (verCount != 0) { // We have at least two versions before we test buffers
+	    ILIdx prevtinfo = { 0, 0 };
+
+	    // Read the previous one
+	    VSIFSeekL(l_ifp, infooffset + verCount * idxSize, SEEK_SET);
+	    VSIFReadL(&prevtinfo, 1, sizeof(ILIdx), l_ifp);
+
+	    // current and previous tiles are different, might create version
+	    if (tinfo.size != prevtinfo.size || tinfo.offset != prevtinfo.offset)
+		new_version = true;
+	}
+	else
+	    new_version = true; // No previous, might create version
+
+	// tinfo contains the current info or 0,0
+	if (tinfo.size == GIntBig(net64(size))) { // Might be the same, read and compare
+	    if (size != 0) {
+		tbuff = CPLMalloc(static_cast<size_t>(size));
+		// Use the temporary buffer, we can't have a versioned cache !!
+		VSIFSeekL(l_dfp, infooffset, SEEK_SET);
+		VSIFReadL(tbuff, 1, static_cast<size_t>(size), l_dfp);
+		// Need to write it if not the same
+		new_tile = (0 != memcmp(buff, tbuff, static_cast<size_t>(size)));
+		CPLFree(tbuff);
+                tbuff = NULL;
+	    }
+	    else {
+		// Writing a null tile on top of a null tile, does it count?
+		if (tinfo.offset != GIntBig(net64(GUIntBig(buff))))
+		    new_tile = true;
+	    }
+	}
+	else {
+	    new_tile = true; // Need to write it because it is different
+	    if (verCount == 0 && tinfo.size == 0)
+		new_version = false; // Don't create a version if current is empty and there is no previous
+	}
+
+	if (!new_tile)
+	    return CE_None; // No reason to write
+
+	// Do we need to start a new version before writing the tile?
+	if (new_version)
+	    AddVersion();
+    }
+
+    // Convert to net format
+    tinfo.size = net64(size);
+
+    if (size) do {
+	// These statements are the critical MP section for the data file
+	VSIFSeekL(l_dfp, 0, SEEK_END);
+	GUIntBig offset = VSIFTellL(l_dfp);
+	if (static_cast<size_t>(size) != VSIFWriteL(buff, 1, static_cast<size_t>(size), l_dfp))
+	    ret = CE_Failure;
+
+	tinfo.offset = net64(offset);
+	//
+	// For MP ops, check that we can read it back properly, otherwise we're done
+	// This makes the caching MRF MP safe, without using explicit locks
+	//
+	if (mp_safe) {
+	    // Allocate the temp buffer if we haven't done so already
+	    if (!tbuff)
+		tbuff = CPLMalloc(static_cast<size_t>(size));
+	    VSIFSeekL(l_dfp, offset, SEEK_SET);
+	    VSIFReadL(tbuff, 1, static_cast<size_t>(size), l_dfp);
+	    // If memcmp returns zero, verify passed
+	    if (!memcmp(buff, tbuff, static_cast<size_t>(size))) {
+		CPLFree(tbuff);
+		tbuff = NULL; // Triggers the loop termination
+	    }
+	    // Otherwise the tbuf stays allocated and try to write again
+	    // This works only if the file is opened in append mode
+	}
+    } while (tbuff);
+
+    // At this point, the data is in the datafile
+
+    // Special case
+    // Any non-zero will do, use 1 to only consume one bit
+    if (NULL != buff && 0 == size)
+	tinfo.offset = net64(GUIntBig(buff));
+
+    VSIFSeekL(l_ifp, infooffset, SEEK_SET);
+    if (sizeof(tinfo) != VSIFWriteL(&tinfo, 1, sizeof(tinfo), l_ifp))
+	ret = CE_Failure;
+
+    return ret;
+}
+
+CPLErr GDALMRFDataset::SetGeoTransform(double *gt)
+
+{
+    if (GetAccess() == GA_Update)
+    {
+	memcpy(GeoTransform, gt, 6 * sizeof(double));
+	bGeoTransformValid = TRUE;
+	return CE_None;
+    }
+    CPLError(CE_Failure, CPLE_NotSupported,
+	"SetGeoTransform called on read only file");
+    return CE_Failure;
+}
+
+/*
+*  Returns 0,1,0,0,0,1 even if it was not set
+*/
+CPLErr GDALMRFDataset::GetGeoTransform(double *gt)
+{
+    memcpy(gt, GeoTransform, 6 * sizeof(double));
+    if (!bGeoTransformValid) return CE_Failure;
+    return CE_None;
+}
+
+/**
+*\brief Read a tile index
+*
+* It handles the non-existent index case, for no compression
+* The bias is non-zero only when the cloned index is read
+*/
+
+CPLErr GDALMRFDataset::ReadTileIdx(ILIdx &tinfo, const ILSize &pos, const ILImage &img, const GIntBig bias)
+
+{
+    VSILFILE *l_ifp = IdxFP();
+    GIntBig offset = bias + IdxOffset(pos, img);
+    if (l_ifp == NULL && img.comp == IL_NONE) {
+	tinfo.size = current.pageSizeBytes;
+	tinfo.offset = offset * tinfo.size;
+	return CE_None;
+    }
+
+    if (l_ifp == NULL) {
+	CPLError(CE_Failure, CPLE_FileIO, "Can't open index file");
+	return CE_Failure;
+    }
+
+    VSIFSeekL(l_ifp, offset, SEEK_SET);
+    if (1 != VSIFReadL(&tinfo, sizeof(ILIdx), 1, l_ifp))
+	return CE_Failure;
+    // Convert them to native form
+    tinfo.offset = net64(tinfo.offset);
+    tinfo.size = net64(tinfo.size);
+
+    if (0 == bias || 0 != tinfo.size || 0 != tinfo.offset)
+	return CE_None;
+
+    // zero size and zero offset in sourced index means that this portion is un-initialized
+
+    // Should be cloned and the offset within the cloned index
+    offset -= bias;
+    assert(offset < bias);
+    assert(clonedSource);
+
+
+    // Read this block from the remote index, prepare it and store it in the right place
+    // The block size in bytes, should be a multiple of 16, to have full index entries
+    const int CPYSZ = 32768;
+    // Adjust offset to the start of the block
+    offset = (offset / CPYSZ) * CPYSZ;
+    GIntBig size = MIN(size_t(CPYSZ), size_t(bias - offset));
+    size /= sizeof(ILIdx); // In records
+    vector<ILIdx> buf(static_cast<size_t>(size));
+    ILIdx *buffer = &buf[0]; // Buffer to copy the source to the clone index
+
+
+    // Fetch the data from the cloned index
+    GDALMRFDataset *pSrc = static_cast<GDALMRFDataset *>(GetSrcDS());
+    if( pSrc == NULL )
+    {
+        CPLError(CE_Failure, CPLE_FileIO, "Can't open cloned source index");
+        return CE_Failure; // Source reported the error
+    }
+
+    VSILFILE *srcidx = pSrc->IdxFP();
+    if (!srcidx) {
+	CPLError(CE_Failure, CPLE_FileIO, "Can't open cloned source index");
+	return CE_Failure; // Source reported the error
+    }
+
+    VSIFSeekL(srcidx, offset, SEEK_SET);
+    size = VSIFReadL(buffer, sizeof(ILIdx), static_cast<size_t>(size), srcidx);
+    if (size != GIntBig(buf.size())) {
+	CPLError(CE_Failure, CPLE_FileIO, "Can't read cloned source index");
+	return CE_Failure; // Source reported the error
+    }
+
+    // Mark the empty records as checked, by making the offset non-zero
+    for (vector<ILIdx>::iterator it = buf.begin(); it != buf.end(); it++) {
+	if (it->offset == 0 && it->size == 0)
+	    it->offset = net64(1);
+    }
+
+    // Write it in the right place in the local index file
+    VSIFSeekL(l_ifp, bias + offset, SEEK_SET);
+    size = VSIFWriteL(&buf[0], sizeof(ILIdx), static_cast<size_t>(size), l_ifp);
+    if (size != GIntBig(buf.size())) {
+	CPLError(CE_Failure, CPLE_FileIO, "Can't write to cloning MRF index");
+	return CE_Failure; // Source reported the error
+    }
+
+    // Cloned index updated, restart this function, it will work now
+    return ReadTileIdx(tinfo, pos, img, bias);
+}
+
+NAMESPACE_MRF_END
diff --git a/frmts/mrf/mrf_band.cpp b/frmts/mrf/mrf_band.cpp
new file mode 100644
index 0000000..59d4d22
--- /dev/null
+++ b/frmts/mrf/mrf_band.cpp
@@ -0,0 +1,989 @@
+/*
+* Copyright (c) 2002-2012, California Institute of Technology.
+* All rights reserved.  Based on Government Sponsored Research under contracts NAS7-1407 and/or NAS7-03001.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+*   1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+*   2. Redistributions in binary form must reproduce the above copyright notice,
+*      this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+*   3. Neither the name of the California Institute of Technology (Caltech), its operating division the Jet Propulsion Laboratory (JPL),
+*      the National Aeronautics and Space Administration (NASA), nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE CALIFORNIA INSTITUTE OF TECHNOLOGY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* Copyright 2014-2015 Esri
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+
+/******************************************************************************
+* $Id$
+*
+* Project:  Meta Raster File Format Driver Implementation, RasterBand
+* Purpose:  Implementation of Pile of Tile Format
+*
+* Author:   Lucian Plesea, Lucian.Plesea at jpl.nasa.gov, lplesea at esri.com
+*
+******************************************************************************
+*
+*
+*
+*
+*
+****************************************************************************/
+
+#include "marfa.h"
+#include <gdal_priv.h>
+#include <ogr_srs_api.h>
+#include <ogr_spatialref.h>
+
+#include <vector>
+#include <assert.h>
+#include "../zlib/zlib.h"
+
+using std::vector;
+using std::string;
+
+NAMESPACE_MRF_START
+
+// packs a block of a given type, with a stride
+// Count is the number of items that need to be copied
+// These are separate to allow for optimization
+
+template <typename T> void cpy_stride_in(void *dst,
+	const void *src, int c, int stride)
+{
+    T *s=(T *)src;
+    T *d=(T *)dst;
+
+    while (c--) {
+	*d++=*s;
+	s+=stride;
+    }
+}
+
+template <typename T> void cpy_stride_out(void *dst,
+	const void *src, int c, int stride)
+{
+    T *s=(T *)src;
+    T *d=(T *)dst;
+
+    while (c--) {
+	*d=*s++;
+	d+=stride;
+    }
+}
+
+// Does every value in the buffer have the same value, using strict comparison
+template<typename T> inline int isAllVal(const T *b, size_t bytecount, double ndv)
+
+{
+    T val = (T)(ndv);
+    size_t count = bytecount / sizeof(T);
+    while (count--) {
+    	if (*b) {
+			if (*(b++)!=val) {
+				return FALSE;
+			}
+    	} else {
+    		return FALSE;
+    	}
+	}
+    return TRUE;
+}
+
+// Dispatcher based on gdal data type
+static int isAllVal(GDALDataType gt, void *b, size_t bytecount, double ndv)
+{
+    // Test to see if it has data
+    int isempty = false;
+
+    // A case branch in a temporary macro, conversion from gdal enum to type
+#define TEST_T(GType, type)\
+    case GType: \
+	isempty = isAllVal((type *)b, bytecount, ndv);\
+	break
+
+    switch (gt) {
+	TEST_T(GDT_Byte, GByte);
+	TEST_T(GDT_UInt16, GUInt16);
+	TEST_T(GDT_Int16, GInt16);
+	TEST_T(GDT_UInt32, GUInt32);
+	TEST_T(GDT_Int32, GInt32);
+	TEST_T(GDT_Float32, float);
+	TEST_T(GDT_Float64, double);
+	default : break;
+    }
+#undef TEST_T
+
+    return isempty;
+}
+
+// Swap bytes in place, unconditional
+static void swab_buff(buf_mgr &src, const ILImage &img)
+{
+    size_t i;
+    switch (GDALGetDataTypeSize(img.dt)) {
+    case 16: {
+	short int *b = (short int*)src.buffer;
+	for (i = src.size / 2; i; b++, i--)
+	    *b = swab16(*b);
+	break;
+    }
+    case 32: {
+	int *b = (int*)src.buffer;
+	for (i = src.size / 4; i; b++, i--)
+	    *b = swab32(*b);
+	break;
+    }
+    case 64: {
+	long long *b = (long long*)src.buffer;
+	for (i = src.size / 8; i; b++, i--)
+	    *b = swab64(*b);
+	break;
+    }
+    }
+}
+
+/**
+*\brief Deflates a buffer, extrasize is the available size in the buffer past the input
+*  If the output fits past the data, it uses that area
+* otherwise it uses a temporary buffer and copies the data over the input on return, returning a pointer to it
+*/
+static void *DeflateBlock(buf_mgr &src, size_t extrasize, int flags) {
+    // The one we might need to allocate
+    void *dbuff = NULL;
+    buf_mgr dst;
+    // The one we could use, after the packed data
+    dst.buffer = src.buffer + src.size;
+    dst.size = extrasize;
+
+    // Allocate a temp buffer if there is not sufficient space,
+    // We need to have a bit more than half the buffer available
+    if (extrasize < (src.size + 64)) {
+	dst.size = src.size + 64;
+
+	dbuff = VSIMalloc(dst.size);
+	dst.buffer = (char *)dbuff;
+	if (!dst.buffer)
+	    return NULL;
+    }
+
+    if (!ZPack(src, dst, flags)) {
+	CPLFree(dbuff); // Safe to call with NULL
+	return NULL;
+    }
+
+    // source size is used to hold the output size
+    src.size = dst.size;
+    // If we didn't allocate a buffer, the receiver can use it already
+    if (!dbuff)
+	return dst.buffer;
+
+    // If we allocated a buffer, we need to copy the data to the input buffer
+    memcpy(src.buffer, dbuff, src.size);
+    CPLFree(dbuff);
+    return src.buffer;
+}
+
+//
+// The deflate_flags are available in all bands even if the DEFLATE option
+// itself is not set.  This allows for PNG features to be controlled, as well
+// as any other bands that use zlib by itself
+//
+GDALMRFRasterBand::GDALMRFRasterBand(GDALMRFDataset *parent_dataset,
+					const ILImage &image, int band, int ov)
+{
+    poDS=parent_dataset;
+    nBand=band;
+    m_band=band-1;
+    m_l=ov;
+    img=image;
+    eDataType=parent_dataset->current.dt;
+    nRasterXSize = img.size.x;
+    nRasterYSize = img.size.y;
+    nBlockXSize = img.pagesize.x;
+    nBlockYSize = img.pagesize.y;
+    nBlocksPerRow = img.pagecount.x;
+    nBlocksPerColumn = img.pagecount.y;
+    img.NoDataValue = GetNoDataValue(&img.hasNoData);
+
+    deflatep = GetOptlist().FetchBoolean("DEFLATE", FALSE);
+    // Bring the quality to 0 to 9
+    deflate_flags = img.quality / 10;
+    // Pick up the twists, aka GZ, RAWZ headers
+    if (GetOptlist().FetchBoolean("GZ", FALSE))
+	deflate_flags |= ZFLAG_GZ;
+    else if (GetOptlist().FetchBoolean("RAWZ", FALSE))
+	deflate_flags |= ZFLAG_RAW;
+    // And Pick up the ZLIB strategy, if any
+    const char *zstrategy = GetOptlist().FetchNameValueDef("Z_STRATEGY", NULL);
+    if (zstrategy) {
+	int zv = Z_DEFAULT_STRATEGY;
+	if (EQUAL(zstrategy, "Z_HUFFMAN_ONLY"))
+	    zv = Z_HUFFMAN_ONLY;
+	else if (EQUAL(zstrategy, "Z_RLE"))
+	    zv = Z_RLE;
+	else if (EQUAL(zstrategy, "Z_FILTERED"))
+	    zv = Z_FILTERED;
+	else if (EQUAL(zstrategy, "Z_FIXED"))
+	    zv = Z_FIXED;
+	deflate_flags |= (zv << 6);
+    }
+    overview = 0;
+}
+
+// Clean up the overviews if they exist
+GDALMRFRasterBand::~GDALMRFRasterBand()
+{
+    while (0!=overviews.size()) {
+	delete overviews[overviews.size()-1];
+	overviews.pop_back();
+    };
+}
+
+// Look for a string from the dataset options or from the environment
+const char * GDALMRFRasterBand::GetOptionValue(const char *opt, const char *def) const
+{
+    const char *optValue = poDS->optlist.FetchNameValue(opt);
+    if (optValue) return optValue;
+    return CPLGetConfigOption(opt, def);
+}
+
+// Utility function, returns a value from a vector corresponding to the band index
+// or the first entry
+static double getBandValue(std::vector<double> &v,int idx)
+{
+    if (static_cast<int>(v.size()) > idx)
+	return v[idx];
+    return v[0];
+}
+
+// Maybe we should check against the type range?
+// It is not keeping track of how many values have been set,
+// so the application should set none or all the bands
+// This call is only valid during Create
+CPLErr  GDALMRFRasterBand::SetNoDataValue(double val)
+{
+    if (poDS->bCrystalized) {
+	CPLError(CE_Failure, CPLE_AssertionFailed, "MRF: NoData can be set only during file create");
+	return CE_Failure;
+    }
+    if (GInt32(poDS->vNoData.size()) < m_band)
+	poDS->vNoData.resize(nBand);
+    poDS->vNoData[m_band] = val;
+    // We also need to set it for this band
+    img.NoDataValue = val;
+    img.hasNoData = true;
+    return CE_None;
+}
+
+double GDALMRFRasterBand::GetNoDataValue(int *pbSuccess)
+{
+    std::vector<double> &v=poDS->vNoData;
+    if (v.size() == 0)
+	return GDALPamRasterBand::GetNoDataValue(pbSuccess);
+    if (pbSuccess) *pbSuccess=TRUE;
+    return getBandValue(v, m_band);
+}
+
+double GDALMRFRasterBand::GetMinimum(int *pbSuccess)
+{
+    std::vector<double> &v=poDS->vMin;
+    if (v.size() == 0)
+	return GDALPamRasterBand::GetMinimum(pbSuccess);
+    if (pbSuccess) *pbSuccess=TRUE;
+    return getBandValue(v, m_band);
+}
+
+double GDALMRFRasterBand::GetMaximum(int *pbSuccess)
+{
+    std::vector<double> &v=poDS->vMax;
+    if (v.size() == 0)
+	return GDALPamRasterBand::GetMaximum(pbSuccess);
+    if (pbSuccess) *pbSuccess=TRUE;
+    return getBandValue(v, m_band);
+}
+
+// Fill, with ndv
+template<typename T> CPLErr buff_fill(void *b, size_t count, const T ndv)
+{
+    T *buffer = static_cast<T*>(b);
+    count /= sizeof(T);
+    while (count--)
+	*buffer++ = ndv;
+    return CE_None;
+}
+
+/**
+*\brief Fills a buffer with no data
+*
+*/
+CPLErr GDALMRFRasterBand::FillBlock(void *buffer)
+{
+    int success;
+    double ndv = GetNoDataValue(&success);
+    if (!success) ndv = 0.0;
+
+    size_t bsb = blockSizeBytes();
+
+    // use memset for speed for bytes, or if nodata is zeros
+    if (eDataType == GDT_Byte || 0.0L == ndv ) {
+	memset(buffer, int(ndv), bsb);
+	return CE_None;
+    }
+
+#define bf(T) buff_fill<T>(buffer, bsb, T(ndv));
+    switch(eDataType) {
+	case GDT_UInt16:    return bf(GUInt16);
+	case GDT_Int16:     return bf(GInt16);
+	case GDT_UInt32:    return bf(GUInt32);
+	case GDT_Int32:     return bf(GInt32);
+	case GDT_Float32:   return bf(float);
+	case GDT_Float64:   return bf(double);
+	default: break;
+    }
+#undef bf
+    // Should exit before
+    return CE_Failure;
+}
+
+/*\brief Interleave block read
+ *
+ *  Acquire space for all the other bands, unpack there, then drop the locks
+ *  The current band output goes directly into the buffer
+ */
+
+CPLErr GDALMRFRasterBand::RB(int xblk, int yblk, buf_mgr /*src*/, void *buffer) {
+    vector<GDALRasterBlock *> blocks;
+
+    for (int i = 0; i < poDS->nBands; i++) {
+	GDALRasterBand *b = poDS->GetRasterBand(i+1);
+	if (b->GetOverviewCount() && m_l)
+	    b = b->GetOverview(m_l-1);
+
+	void *ob = buffer;
+	// Get the other band blocks, keep them around until later
+	if (b != this)
+	{
+	    GDALRasterBlock *poBlock = b->GetLockedBlockRef(xblk, yblk, 1);
+            if( poBlock == NULL )
+                break;
+	    ob = poBlock->GetDataRef();
+	    blocks.push_back(poBlock);
+	}
+
+// Just the right mix of templates and macros make deinterleaving tidy
+#define CpySI(T) cpy_stride_in<T> (ob, (T *)poDS->GetPBuffer() + i,\
+    blockSizeBytes()/sizeof(T), img.pagesize.c)
+
+	// Page is already in poDS->pbuffer, not empty
+	// There are only four cases, since only the real data type matters
+	switch (GDALGetDataTypeSize(eDataType)/8)
+	{
+	case 1: CpySI(GByte); break;
+	case 2: CpySI(GInt16); break;
+	case 4: CpySI(GInt32); break;
+	case 8: CpySI(GIntBig); break;
+	}
+    }
+
+#undef CpySI
+
+    // Drop the locks we acquired
+    for (int i=0; i < int(blocks.size()); i++)
+	blocks[i]->DropLock();
+
+    return CE_None;
+}
+
+
+/**
+*\brief Fetch a block from the backing store dataset and keep a copy in the cache
+*
+* @xblk The X block number, zero based
+* @yblk The Y block number, zero based
+* @param tinfo The return, updated tinfo for this specific tile
+*
+*/
+CPLErr GDALMRFRasterBand::FetchBlock(int xblk, int yblk, void *buffer)
+
+{
+    assert(!poDS->source.empty());
+    CPLDebug("MRF_IB", "FetchBlock %d,%d,0,%d, level  %d\n", xblk, yblk, m_band, m_l);
+
+    if (poDS->clonedSource)  // This is a clone
+	return FetchClonedBlock(xblk, yblk, buffer);
+
+    GDALDataset *poSrcDS;
+    const GInt32 cstride = img.pagesize.c; // 1 if pixel interleaved
+    ILSize req(xblk, yblk, 0, m_band/cstride, m_l);
+    GUIntBig infooffset = IdxOffset(req, img);
+
+    if ( NULL == (poSrcDS = poDS->GetSrcDS())) {
+	CPLError( CE_Failure, CPLE_AppDefined, "MRF: Can't open source file %s", poDS->source.c_str());
+	return CE_Failure;
+    }
+
+    // Scale to base resolution
+    double scl = pow(poDS->scale, m_l);
+    if ( 0 == m_l )
+	scl = 1; // To allow for precision issues
+
+    // Prepare parameters for RasterIO, they might be different from a full page
+    int vsz = GDALGetDataTypeSize(eDataType)/8;
+    int Xoff = int(xblk * img.pagesize.x * scl + 0.5);
+    int Yoff = int(yblk * img.pagesize.y * scl + 0.5);
+    int readszx = int(img.pagesize.x * scl + 0.5);
+    int readszy = int(img.pagesize.y * scl + 0.5);
+
+    // Compare with the full size and clip to the right and bottom if needed
+    int clip=0;
+    if (Xoff + readszx > poDS->full.size.x) {
+	clip |= 1;
+	readszx = poDS->full.size.x - Xoff;
+    }
+    if (Yoff + readszy > poDS->full.size.y) {
+	clip |= 1;
+	readszy = poDS->full.size.y - Yoff;
+    }
+
+    // This is where the whole page fits
+    void *ob = buffer;
+    if (cstride != 1)
+	ob = poDS->GetPBuffer();
+
+    // Fill buffer with NoData if clipping
+    if (clip)
+	FillBlock(ob);
+
+    // Use the dataset RasterIO to read all bands
+    CPLErr ret = poSrcDS->RasterIO(GF_Read, Xoff, Yoff, readszx, readszy,
+	ob, pcount(readszx, int(scl)), pcount(readszy, int(scl)),
+	eDataType, cstride, (1 == cstride)? &nBand: NULL,
+	vsz * cstride, 	// pixel, line, band stride
+	vsz * cstride * img.pagesize.x,
+	(cstride != 1) ? vsz : vsz * img.pagesize.x * img.pagesize.y
+#if GDAL_VERSION_MAJOR >= 2
+	,NULL
+#endif
+	);
+
+    if (ret != CE_None) return ret;
+
+    // Might have the block in the pbuffer, mark it anyhow
+    poDS->tile = req;
+    buf_mgr filesrc;
+    filesrc.buffer = (char *)ob;
+    filesrc.size = static_cast<size_t>(img.pageSizeBytes);
+
+    if (poDS->bypass_cache) { // No local caching, just return the data
+	if (1 == cstride)
+	    return CE_None;
+	return RB(xblk, yblk, filesrc, buffer);
+    }
+
+    // Test to see if it need to be written, or just marked
+    int success;
+    double val = GetNoDataValue(&success);
+    if (!success) val = 0.0;
+    if (isAllVal(eDataType, ob, img.pageSizeBytes, val)) {
+	// Mark it empty and checked, ignore the possible write error
+	poDS->WriteTile((void *)1, infooffset, 0);
+	return CE_None;
+    }
+
+    // Write the page in the local cache
+
+    // Have to use a separate buffer for compression output.
+    void *outbuff = VSIMalloc(poDS->pbsize);
+
+    if (!outbuff) {
+	CPLError(CE_Failure, CPLE_AppDefined,
+	    "Can't get buffer for writing page");
+	// This is not really an error for a cache, the data is fine
+	return CE_Failure;
+    }
+
+    buf_mgr filedst={(char *)outbuff, poDS->pbsize};
+    Compress(filedst, filesrc);
+
+    // Where the output is, in case we deflate
+    void *usebuff = outbuff;
+    if (deflatep) {
+	usebuff = DeflateBlock( filedst, poDS->pbsize - filedst.size, deflate_flags);
+	if (!usebuff) {
+	    CPLError(CE_Failure,CPLE_AppDefined, "MRF: Deflate error");
+	    return CE_Failure;
+	}
+    }
+
+    // Write and update the tile index
+    ret = poDS->WriteTile(usebuff, infooffset, filedst.size);
+    CPLFree(outbuff);
+
+    // If we hit an error or if unpaking is not needed
+    if (ret != CE_None || cstride == 1)
+	return ret;
+
+    // data is already in filesrc buffer, deinterlace it in pixel blocks
+    return RB(xblk, yblk, filesrc, buffer);
+}
+
+
+/**
+*\brief Fetch for a cloned MRF
+*
+* @xblk The X block number, zero based
+* @yblk The Y block number, zero based
+* @param tinfo The return, updated tinfo for this specific tile
+*
+*/
+
+CPLErr GDALMRFRasterBand::FetchClonedBlock(int xblk, int yblk, void *buffer)
+{
+    CPLDebug("MRF_IB","FetchClonedBlock %d,%d,0,%d, level  %d\n", xblk, yblk, m_band, m_l);
+
+    VSILFILE *srcfd;
+    // Paranoid check
+    assert(poDS->clonedSource);
+
+    GDALMRFDataset *poSrc;
+    if ( NULL == (poSrc = static_cast<GDALMRFDataset *>(poDS->GetSrcDS()))) {
+	CPLError( CE_Failure, CPLE_AppDefined, "MRF: Can't open source file %s", poDS->source.c_str());
+	return CE_Failure;
+    }
+
+    if (poDS->bypass_cache || GF_Read == DataMode()) {
+	// Can't store, so just fetch from source, which is an MRF with identical structure
+	GDALMRFRasterBand *b = static_cast<GDALMRFRasterBand *>(poSrc->GetRasterBand(nBand));
+	if (b->GetOverviewCount() && m_l)
+	    b = static_cast<GDALMRFRasterBand *>(b->GetOverview(m_l-1));
+        if( b == NULL )
+            return CE_Failure;
+	return b->IReadBlock(xblk,yblk,buffer);
+    }
+
+    ILSize req(xblk, yblk, 0, m_band/img.pagesize.c , m_l);
+    ILIdx tinfo;
+
+    // Get the cloned source tile info
+    // The cloned source index is after the current one
+    if (CE_None != poDS->ReadTileIdx(tinfo, req, img, poDS->idxSize)) {
+	CPLError(CE_Failure, CPLE_AppDefined, "MRF: Unable to read cloned index entry");
+	return CE_Failure;
+    }
+
+    GUIntBig infooffset = IdxOffset(req, img);
+    CPLErr err;
+
+    // Does the source have this tile?
+    if (tinfo.size == 0) { // Nope, mark it empty and return fill
+	err = poDS->WriteTile((void *)1, infooffset, 0);
+	if (CE_None != err)
+	    return err;
+	return FillBlock(buffer);
+    }
+
+    srcfd = poSrc->DataFP();
+    if (NULL == srcfd) {
+	CPLError( CE_Failure, CPLE_AppDefined, "MRF: Can't open source data file %s",
+	    poDS->source.c_str());
+	return CE_Failure;
+    }
+
+    // Need to read the tile from the source
+    if( tinfo.size <= 0 || tinfo.size > INT_MAX )
+    {
+        CPLError(CE_Failure, CPLE_OutOfMemory, "Invalid tile size " CPL_FRMT_GIB,
+                 tinfo.size);
+        return CE_Failure;
+    }
+    char *buf = static_cast<char *>(VSIMalloc(static_cast<size_t>(tinfo.size)));
+    if( buf == NULL )
+    {
+        CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate " CPL_FRMT_GIB " bytes",
+                 tinfo.size);
+        return CE_Failure;
+    }
+
+    VSIFSeekL(srcfd, tinfo.offset, SEEK_SET);
+    if (tinfo.size != GIntBig(VSIFReadL( buf, 1, static_cast<size_t>(tinfo.size), srcfd))) {
+	CPLFree(buf);
+	CPLError( CE_Failure, CPLE_AppDefined, "MRF: Can't read data from source %s",
+	    poSrc->current.datfname.c_str() );
+	return CE_Failure;
+    }
+
+    // Write it then reissue the read
+    err = poDS->WriteTile(buf, infooffset, tinfo.size);
+    CPLFree(buf);
+    if ( CE_None != err )
+	return err;
+    // Reissue read, it will work from the cloned data
+    return IReadBlock(xblk, yblk, buffer);
+}
+
+
+/**
+*\brief read a block in the provided buffer
+*
+*  For separate band model, the DS buffer is not used, the read is direct in the buffer
+*  For pixel interleaved model, the DS buffer holds the temp copy
+*  and all the other bands are force read
+*
+*/
+
+CPLErr GDALMRFRasterBand::IReadBlock(int xblk, int yblk, void *buffer)
+{
+    ILIdx tinfo;
+    GInt32 cstride = img.pagesize.c;
+    ILSize req(xblk, yblk, 0, m_band / cstride, m_l);
+    CPLDebug("MRF_IB", "IReadBlock %d,%d,0,%d, level %d, idxoffset " CPL_FRMT_GIB "\n",
+	xblk, yblk, m_band, m_l, IdxOffset(req,img));
+
+    // If this is a caching file and bypass is on, just do the fetch
+    if (poDS->bypass_cache && !poDS->source.empty())
+	return FetchBlock(xblk, yblk, buffer);
+
+    if (CE_None != poDS->ReadTileIdx(tinfo, req, img)) {
+	CPLError( CE_Failure, CPLE_AppDefined,
+	    "MRF: Unable to read index at offset " CPL_FRMT_GIB, IdxOffset(req, img));
+	return CE_Failure;
+    }
+
+    if (0 == tinfo.size) { // Could be missing or it could be caching
+	// Offset != 0 means no data, Update mode is for local MRFs only
+	// if caching index mode is RO don't try to fetch
+	// Also, caching MRFs can't be opened in update mode
+	if ( 0 != tinfo.offset || GA_Update == poDS->eAccess
+	    || poDS->source.empty() || IdxMode() == GF_Read )
+	    return FillBlock(buffer);
+
+	// caching MRF, need to fetch a block
+	return FetchBlock(xblk, yblk, buffer);
+    }
+
+    CPLDebug("MRF_IB","Tinfo offset " CPL_FRMT_GIB ", size  " CPL_FRMT_GIB "\n", tinfo.offset, tinfo.size);
+    // If we have a tile, read it
+
+    // Should use a permanent buffer, like the pbuffer mechanism
+    // Get a large buffer, in case we need to unzip
+
+    // We add a padding of 3 bytes since in LERC1 decompression, we can
+    // dereference a unsigned int at the end of the buffer, that can be
+    // partially out of the buffer.
+    // Can be reproduced with :
+    // gdal_translate ../autotest/gcore/data/byte.tif out.mrf -of MRF -co COMPRESS=LERC -co OPTIONS=V1:YES -ot Float32
+    // valgrind gdalinfo -checksum out.mrf
+    // Invalid read of size 4
+    // at BitStuffer::read(unsigned char**, std::vector<unsigned int, std::allocator<unsigned int> >&) const (BitStuffer.cpp:153)
+    if( tinfo.size <= 0 || tinfo.size > INT_MAX - 3 )
+    {
+        CPLError(CE_Failure, CPLE_OutOfMemory,
+                 "Too big tile size: " CPL_FRMT_GIB, tinfo.size);
+        return CE_Failure;
+    }
+    void *data = VSIMalloc(static_cast<size_t>(tinfo.size + 3));
+    if( data == NULL )
+    {
+        CPLError(CE_Failure, CPLE_OutOfMemory,
+                 "Could not allocate memory for tile size: " CPL_FRMT_GIB, tinfo.size);
+        return CE_Failure;
+    }
+
+    VSILFILE *dfp = DataFP();
+
+    // No data file to read from
+    if (dfp == NULL)
+    {
+        CPLFree(data);
+	return CE_Failure;
+    }
+
+    // This part is not thread safe, but it is what GDAL expects
+    VSIFSeekL(dfp, tinfo.offset, SEEK_SET);
+    if (1 != VSIFReadL(data, static_cast<size_t>(tinfo.size), 1, dfp)) {
+	CPLFree(data);
+	CPLError(CE_Failure, CPLE_AppDefined, "Unable to read data page, %d@%x",
+	    int(tinfo.size), int(tinfo.offset));
+	return CE_Failure;
+    }
+
+    /* initialize padding bytes */
+    memset(((char*)data) + static_cast<size_t>(tinfo.size), 0, 3);
+
+    buf_mgr src = {(char *)data, static_cast<size_t>(tinfo.size)};
+    buf_mgr dst;
+
+    // We got the data, do we need to decompress it before decoding?
+    if (deflatep) {
+        if( img.pageSizeBytes > INT_MAX - 1440 )
+        {
+            CPLFree(data);
+            CPLError(CE_Failure, CPLE_AppDefined, "Too big page size %d",
+                     img.pageSizeBytes);
+            return CE_Failure;
+        }
+	dst.size = img.pageSizeBytes + 1440; // in case the packed page is a bit larger than the raw one
+	dst.buffer = (char *)VSIMalloc(dst.size);
+        if( dst.buffer == NULL )
+        {
+            CPLFree(data);
+            CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate %d bytes",
+                     static_cast<int>(dst.size));
+            return CE_Failure;
+        }
+
+	if (ZUnPack(src, dst, deflate_flags)) {
+	    // Got it unpacked, update the pointers
+	    CPLFree(data);
+	    tinfo.size = dst.size;
+	    data = dst.buffer;
+	} else { // Warn and assume the data was not deflated
+	    CPLError(CE_Warning, CPLE_AppDefined, "Can't inflate page!");
+	    CPLFree(dst.buffer);
+	}
+    }
+
+    src.buffer = (char *)data;
+    src.size = static_cast<size_t>(tinfo.size);
+
+    // After unpacking, the size has to be pageSizeBytes
+    dst.buffer = (char *)buffer;
+    dst.size = img.pageSizeBytes;
+
+    // If pages are interleaved, use the dataset page buffer instead
+    if (1!=cstride)
+	dst.buffer = (char *)poDS->GetPBuffer();
+
+    CPLErr ret = Decompress(dst, src);
+    dst.size = img.pageSizeBytes; // In case the decompress failed, force it back
+    CPLFree(data);
+
+    // Swap whatever we decompressed if we need to
+    if (is_Endianess_Dependent(img.dt,img.comp) && (img.nbo != NET_ORDER) )
+	swab_buff(dst, img);
+
+    // If pages are separate, we're done, the read was in the output buffer
+    if ( 1 == cstride || CE_None != ret)
+	return ret;
+
+    // De-interleave page and return
+    return RB(xblk, yblk, dst, buffer);
+}
+
+
+/**
+*\brief Write a block from the provided buffer
+*
+* Same trick as read, use a temporary tile buffer for pixel interleave
+* For band separate, use a
+* Write the block once it has all the bands, report
+* if a new block is started before the old one was completed
+*
+*/
+
+CPLErr GDALMRFRasterBand::IWriteBlock(int xblk, int yblk, void *buffer)
+
+{
+    GInt32 cstride = img.pagesize.c;
+    ILSize req(xblk, yblk, 0, m_band/cstride, m_l);
+    GUIntBig infooffset = IdxOffset(req, img);
+
+    CPLDebug("MRF_IB", "IWriteBlock %d,%d,0,%d, level  %d, stride %d\n", xblk, yblk,
+	m_band, m_l, cstride);
+
+    if (1 == cstride) {     // Separate bands, we can write it as is
+	// Empty page skip
+
+	int success;
+	double val = GetNoDataValue(&success);
+	if (!success) val = 0.0;
+	if (isAllVal(eDataType, buffer, img.pageSizeBytes, val))
+	    return poDS->WriteTile(NULL, infooffset, 0);
+
+	// Use the pbuffer to hold the compressed page before writing it
+	poDS->tile = ILSize(); // Mark it corrupt
+
+	buf_mgr src;
+        src.buffer = (char *)buffer;
+        src.size = static_cast<size_t>(img.pageSizeBytes);
+	buf_mgr dst = {(char *)poDS->GetPBuffer(), poDS->GetPBufferSize()};
+
+	// Swab the source before encoding if we need to
+	if (is_Endianess_Dependent(img.dt, img.comp) && (img.nbo != NET_ORDER))
+	    swab_buff(src, img);
+
+	// Compress functions need to return the compressed size in
+	// the bytes in buffer field
+	Compress(dst, src);
+	void *usebuff = dst.buffer;
+	if (deflatep) {
+	    usebuff = DeflateBlock(dst, poDS->pbsize - dst.size, deflate_flags);
+	    if (!usebuff) {
+		CPLError(CE_Failure,CPLE_AppDefined, "MRF: Deflate error");
+		return CE_Failure;
+	    }
+	}
+	return poDS->WriteTile(usebuff, infooffset , dst.size);
+    }
+
+    // Multiple bands per page, use a temporary to assemble the page
+    // Temporary is large because we use it to hold both the uncompressed and the compressed
+    poDS->tile=req; poDS->bdirty=0;
+
+    // Keep track of what bands are empty
+    GUIntBig empties=0;
+
+    void *tbuffer = VSIMalloc(img.pageSizeBytes + poDS->pbsize);
+
+    if (!tbuffer) {
+	CPLError(CE_Failure,CPLE_AppDefined, "MRF: Can't allocate write buffer");
+	return CE_Failure;
+    }
+
+    // Get the other bands from the block cache
+    for (int iBand=0; iBand < poDS->nBands; iBand++ )
+    {
+	const char *pabyThisImage=NULL;
+	GDALRasterBlock *poBlock=NULL;
+
+	if (iBand == m_band)
+	{
+	    pabyThisImage = (char *) buffer;
+	    poDS->bdirty |= bandbit();
+	} else {
+	    GDALRasterBand *band = poDS->GetRasterBand(iBand +1);
+	    // Pick the right overview
+	    if (m_l) band = band->GetOverview(m_l -1);
+	    poBlock = ((GDALMRFRasterBand *)band)
+		->TryGetLockedBlockRef(xblk, yblk);
+	    if (NULL==poBlock) continue;
+	    // This is where the image data is for this band
+
+	    pabyThisImage = (char*) poBlock->GetDataRef();
+	    poDS->bdirty |= bandbit(iBand);
+	}
+
+	// Keep track of empty bands, but encode them anyhow, in case some are not empty
+	int success;
+	double val = GetNoDataValue(&success);
+	if (!success) val = 0.0;
+	if (isAllVal(eDataType, buffer, img.pageSizeBytes, val))
+	    empties |= bandbit(iBand);
+
+	// Copy the data into the dataset buffer here
+	// Just the right mix of templates and macros make this real tidy
+#define CpySO(T) cpy_stride_out<T> (((T *)tbuffer)+iBand, pabyThisImage,\
+		blockSizeBytes()/sizeof(T), cstride)
+
+	// Build the page in tbuffer
+	switch (GDALGetDataTypeSize(eDataType)/8)
+	{
+	    case 1: CpySO(GByte); break;
+	    case 2: CpySO(GInt16); break;
+	    case 4: CpySO(GInt32); break;
+	    case 8: CpySO(GIntBig); break;
+	    default:
+            {
+		CPLError(CE_Failure,CPLE_AppDefined, "MRF: Write datatype of %d bytes "
+			"not implemented", GDALGetDataTypeSize(eDataType)/8);
+                if (poBlock != NULL)
+                {
+                    poBlock->MarkClean();
+                    poBlock->DropLock();
+                }
+                CPLFree(tbuffer);
+		return CE_Failure;
+            }
+	}
+
+	if (poBlock != NULL)
+	{
+	    poBlock->MarkClean();
+	    poBlock->DropLock();
+	}
+    }
+
+    if (GIntBig(empties) == AllBandMask()) {
+	CPLFree(tbuffer);
+	return poDS->WriteTile(NULL, infooffset, 0);
+    }
+
+    if (poDS->bdirty != AllBandMask())
+	CPLError(CE_Warning, CPLE_AppDefined,
+	"MRF: IWrite, band dirty mask is " CPL_FRMT_GIB " instead of " CPL_FRMT_GIB,
+	poDS->bdirty, AllBandMask());
+
+//    ppmWrite("test.ppm",(char *)tbuffer, ILSize(nBlockXSize,nBlockYSize,0,poDS->nBands));
+
+    buf_mgr src;
+    src.buffer = (char *)tbuffer;
+    src.size = static_cast<size_t>(img.pageSizeBytes);
+
+    // Use the space after pagesizebytes for compressed output, it is of pbsize
+    char *outbuff = (char *)tbuffer + img.pageSizeBytes;
+
+    buf_mgr dst = {outbuff, poDS->pbsize};
+    Compress(dst, src);
+
+    // Where the output is, in case we deflate
+    void *usebuff = outbuff;
+    if (deflatep) {
+	// Move the packed part at the start of tbuffer, to make more space available
+	memcpy(tbuffer, outbuff, dst.size);
+	dst.buffer = (char *)tbuffer;
+	usebuff = DeflateBlock(dst, img.pageSizeBytes + poDS->pbsize - dst.size, deflate_flags);
+	if (!usebuff) {
+	    CPLError(CE_Failure,CPLE_AppDefined, "MRF: Deflate error");
+	    CPLFree(tbuffer);
+	    return CE_Failure;
+	}
+    }
+
+    CPLErr ret = poDS->WriteTile(usebuff, infooffset, dst.size);
+    CPLFree(tbuffer);
+
+    poDS->bdirty = 0;
+    return ret;
+}
+
+int GDALMRFRasterBand::GetOverviewCount()
+{
+    // First try internal overviews
+    int nInternalOverviewCount = static_cast<int>(overviews.size());
+    if( nInternalOverviewCount > 0 )
+        return nInternalOverviewCount;
+    // Fallback to PAM external overviews
+    return GDALPamRasterBand::GetOverviewCount();
+}
+
+GDALRasterBand* GDALMRFRasterBand::GetOverview(int n)
+{
+    // First try internal overviews
+    if( n >= 0 && n < (int)overviews.size() )
+        return overviews[n];
+    // Fallback to PAM external overviews
+    return GDALPamRasterBand::GetOverview(n);
+}
+
+NAMESPACE_MRF_END
diff --git a/frmts/mrf/mrf_overview.cpp b/frmts/mrf/mrf_overview.cpp
new file mode 100644
index 0000000..4db41bc
--- /dev/null
+++ b/frmts/mrf/mrf_overview.cpp
@@ -0,0 +1,454 @@
+/*
+* Copyright 2014-2015 Esri
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/******************************************************************************
+* $Id$
+*
+* Project:  Meta Raster File Format Driver Implementation, overlay support
+* Purpose:  Implementation overlay support for MRF
+*
+* Author:   Lucian Plesea, Lucian.Plesea at jpl.nasa.gov, lplesea at esri.com
+*
+******************************************************************************
+*  This source file contains the non GDAL standard part of the MRF overview building
+*  The PatchOverview method only handles powers of 2 overviews!!
+****************************************************************************/
+
+#include "marfa.h"
+#include <vector>
+
+using std::vector;
+
+NAMESPACE_MRF_START
+
+// Count the values in a buffer that match a specific value
+template<typename T> int MatchCount(T *buff, int sz, T val) {
+    int ncount=0;
+    for (int i=0; i < sz; i++)
+	if (buff[i] == val)
+	    ncount++;
+    return ncount;
+}
+
+//
+// Scales by 2x2 a buffer in place, using Nearest resampling
+// Always pick the top-left corner
+//
+template<typename T> void NearByFour(T *buff, int xsz, int ysz) {
+    T *obuff = buff;
+    for (int line = 0; line < ysz; line++) {
+		// Copy every other pixel
+		for (int col = 0; col < xsz; col++, buff++) {
+			*obuff++ = *buff++;
+		}
+		// Skip every other line
+		buff += xsz * 2;
+    }
+}
+
+//
+// If the NoData value exists, pick a valid pixel if possible
+//
+template<typename T> void NearByFour(T *buff, int xsz, int ysz, T ndv) {
+    T *obuff = buff;
+    T *evenline = buff;
+
+    for (int line = 0; line<ysz; line++) {
+	T *oddline = evenline + xsz * 2;
+	for (int col = 0; col<xsz; col++) {
+
+	    if (evenline[0] != ndv)
+		*obuff++ = evenline[0];
+	    else if (evenline[1] != ndv)
+		*obuff++ = evenline[1];
+	    else if (oddline[0] != ndv)
+		*obuff++ = oddline[0];
+	    else
+		*obuff++ = oddline[1];
+
+	    evenline += 2; oddline += 2;
+	}
+	evenline += xsz * 2;  // Skips the other input line
+    }
+}
+
+// Scales by 2x2 using averaging
+// There are lots of these AverageByFour templates, because some types have to be treated
+// slightly different than others.  Some could be folded by using is_integral(),
+// but support is not universal
+// There are two categories, depending on NoData presence
+//
+
+// Integer data types shorter than 32 bit use integer math safely
+template<typename T> void AverageByFour(T *buff, int xsz, int ysz) {
+    T *obuff=buff;
+    T *evenline=buff;
+
+    for (int line=0; line<ysz; line++) {
+	T *oddline=evenline+xsz*2;
+	for (int col=0; col<xsz; col++) {
+	    *obuff++ = (2 + evenline[0] + evenline[1] + oddline[0] + oddline[1]) / 4;
+	    evenline +=2; oddline +=2;
+	}
+	evenline += xsz*2;  // Skips the other line
+    }
+}
+
+// 32bit int specialization, avoiding overflow by using 64bit int math
+template<> void AverageByFour<GInt32>(GInt32 *buff, int xsz, int ysz) {
+    GInt32 *obuff=buff;
+    GInt32 *evenline=buff;
+
+    for (int line=0; line<ysz; line++) {
+	GInt32 *oddline=evenline+xsz*2;
+	for (int col=0; col<xsz; col++) {
+	    *obuff++ = (GIntBig(2) + evenline[0] + evenline[1] + oddline[0] + oddline[1]) / 4;
+	    evenline +=2; oddline +=2;
+	}
+	evenline += xsz*2;  // Skips the other line
+    }
+}
+
+// Same for 32bit unsigned int specialization
+template<> void AverageByFour<GUInt32>(GUInt32 *buff, int xsz, int ysz) {
+    GUInt32 *obuff=buff;
+    GUInt32 *evenline=buff;
+
+    for (int line=0; line<ysz; line++) {
+	GUInt32 *oddline=evenline+xsz*2;
+	for (int col=0; col<xsz; col++) {
+	    *obuff++ = (GIntBig(2) + evenline[0] + evenline[1] + oddline[0] + oddline[1]) / 4;
+	    evenline +=2; oddline +=2;
+	}
+	evenline += xsz*2;  // Skips the other line
+    }
+}
+
+// float specialization
+template<> void AverageByFour<float>(float *buff, int xsz, int ysz) {
+    float *obuff=buff;
+    float *evenline=buff;
+
+    for (int line=0; line<ysz; line++) {
+	float *oddline = evenline + xsz*2;
+	for (int col=0; col<xsz; col++) {
+	    *obuff++ = (evenline[0] + evenline[1] + oddline[0] + oddline[1]) * 0.25f;
+	    evenline +=2; oddline +=2;
+	}
+	evenline += xsz*2;  // Skips the other line
+    }
+}
+
+// double specialization
+template<> void AverageByFour<double>(double *buff, int xsz, int ysz) {
+    double *obuff=buff;
+    double *evenline=buff;
+
+    for (int line=0; line<ysz; line++) {
+	double *oddline = evenline + xsz*2;
+	for (int col=0; col<xsz; col++) {
+	    *obuff++ = (evenline[0] + evenline[1] + oddline[0] + oddline[1]) * 0.25;
+	    evenline +=2; oddline +=2;
+	}
+	evenline += xsz*2;  // Skips the other line
+    }
+}
+
+//
+// Integer type specialization, with roundup and integer math, avoids overflow using GIntBig accumulator
+// Speedup by specialization for smaller byte count int types is probably not worth much
+// since there are so many conditions here
+//
+template<typename T> void AverageByFour(T *buff, int xsz, int ysz, T ndv) {
+    T *obuff=buff;
+    T *evenline=buff;
+
+    for (int line=0; line<ysz; line++) {
+	T *oddline=evenline+xsz*2;
+	for (int col=0; col<xsz; col++) {
+	    GIntBig acc = 0;
+	    int count = 0;
+
+// Temporary macro to accumulate the sum, uses the value, increments the pointer
+// Careful with this one, it has side effects
+#define use(valp) if (*valp != ndv) { acc += *valp; count++; }; valp++;
+	    use(evenline); use(evenline); use(oddline); use(oddline);
+#undef use
+	    // The count/2 is the bias to obtain correct rounding
+	    *obuff++ = T((count != 0) ? ((acc + count/2) / count) : ndv);
+
+	}
+	evenline += xsz*2;  // Skips every other line
+    }
+}
+
+// float specialization
+template<> void AverageByFour<float>(float *buff, int xsz, int ysz, float ndv) {
+    float *obuff=buff;
+    float *evenline=buff;
+
+    for (int line=0; line<ysz; line++) {
+	float *oddline=evenline+xsz*2;
+	for (int col=0; col<xsz; col++) {
+	    double acc = 0;
+	    double count = 0;
+
+// Temporary macro to accumulate the sum, uses the value, increments the pointer
+// Careful with this one, it has side effects
+#define use(valp) if (*valp != ndv) { acc += *valp; count += 1.0; }; valp++;
+	    use(evenline); use(evenline); use(oddline); use(oddline);
+#undef use
+	    // Output value is eiher accumulator divided by count or the NoDataValue
+	    *obuff++ = float((count != 0.0) ? acc/count : ndv);
+	}
+	evenline += xsz*2;  // Skips every other line
+    }
+}
+
+// double specialization, same as above
+template<> void AverageByFour<double>(double *buff, int xsz, int ysz, double ndv) {
+    double *obuff=buff;
+    double *evenline=buff;
+
+    for (int line=0; line<ysz; line++) {
+	double *oddline=evenline+xsz*2;
+	for (int col=0; col<xsz; col++) {
+	    double acc = 0;
+	    double count = 0;
+
+// Temporary macro to accumulate the sum, uses the value, increments the pointer
+// Careful with this one, it has side effects
+#define use(valp) if (*valp != ndv) { acc += *valp; count += 1.0; }; valp++;
+	    use(evenline); use(evenline); use(oddline); use(oddline);
+#undef use
+	    // Output value is eiher accumulator divided by count or the NoDataValue
+	    *obuff++ = ((count != 0.0) ? acc/count : ndv);
+	}
+	evenline += xsz*2;  // Skips every other line
+    }
+}
+
+/*
+ *\brief Patches an overview for the selected area
+ * arguments are in blocks in the source level, if toTheTop is false it only does the next level
+ * It will read adjacent blocks if they are needed, so actual area read might be padded by one block in
+ * either side
+ */
+
+CPLErr GDALMRFDataset::PatchOverview(int BlockX,int BlockY,
+				      int Width,int Height,
+				      int srcLevel, int recursive,
+				      int sampling_mode)
+{
+    GDALRasterBand *b0=GetRasterBand(1);
+    if ( b0->GetOverviewCount() <= srcLevel)
+	return CE_None;
+
+    int BlockXOut = BlockX/2 ; // Round down
+    Width += BlockX & 1; // Increment width if rounding down
+    int BlockYOut = BlockY/2 ; // Round down
+    Height += BlockY & 1; // Increment height if rounding down
+
+    int WidthOut = Width/2 + (Width & 1); // Round up
+    int HeightOut = Height/2 + (Height & 1); // Round up
+
+    int bands = GetRasterCount();
+    int tsz_x,tsz_y;
+    b0->GetBlockSize(&tsz_x, &tsz_y);
+    GDALDataType eDataType = b0->GetRasterDataType();
+
+    int pixel_size = GDALGetDataTypeSize(eDataType)/8; // Bytes per pixel per band
+    int line_size = tsz_x * pixel_size; // A line has this many bytes
+    int buffer_size = line_size * tsz_y; // A block size in bytes
+
+    // Build a vector of input and output bands
+    vector<GDALRasterBand *> src_b;
+    vector<GDALRasterBand *> dst_b;
+
+    for (int band=1; band<=bands; band++) {
+	if (srcLevel==0)
+	    src_b.push_back(GetRasterBand(band));
+	else
+	    src_b.push_back(GetRasterBand(band)->GetOverview(srcLevel-1));
+	dst_b.push_back(GetRasterBand(band)->GetOverview(srcLevel));
+    }
+
+    // Allocate space for four blocks
+    void *buffer = CPLMalloc(buffer_size *4 );
+
+    //
+    // The inner loop is the band, so it is efficient for interleaved data.
+    // There is no penalty for separate bands either.
+    //
+    for (int y=0; y<HeightOut; y++) {
+	int dst_offset_y = BlockYOut+y;
+	int src_offset_y = dst_offset_y *2;
+	for (int x=0; x<WidthOut; x++) {
+	    int dst_offset_x = BlockXOut + x;
+	    int src_offset_x = dst_offset_x * 2;
+
+	    // Do it band at a time so we can work in grayscale
+	    for (int band=0; band<bands; band++) { // Counting from zero in a vector
+
+		int sz_x = 2*tsz_x ,sz_y = 2*tsz_y ;
+		GDALMRFRasterBand *bsrc = static_cast<GDALMRFRasterBand *>(src_b[band]);
+		GDALMRFRasterBand *bdst = static_cast<GDALMRFRasterBand *>(dst_b[band]);
+
+		//
+		// Clip to the size to the input image
+		// This is one of the worst features of GDAL, it doesn't tolerate any padding
+		//
+		bool adjusted = false;
+		if (bsrc->GetXSize() < (src_offset_x + 2) * tsz_x) {
+		    sz_x = bsrc->GetXSize() - src_offset_x * tsz_x;
+		    adjusted = true;
+		}
+		if (bsrc->GetYSize() < (src_offset_y + 2) * tsz_y) {
+		    sz_y = bsrc->GetYSize() - src_offset_y * tsz_y;
+		    adjusted = true;
+		}
+
+		if (adjusted) { // Fill with no data for partial buffer, instead of padding afterwards
+		    size_t bsb = bsrc->blockSizeBytes();
+		    char *b=static_cast<char *>(buffer);
+		    bsrc->FillBlock(b);
+		    bsrc->FillBlock(b + bsb);
+		    bsrc->FillBlock(b + 2*bsb);
+		    bsrc->FillBlock(b + 3*bsb);
+		}
+
+		int hasNoData = 0;
+		double ndv = bsrc->GetNoDataValue(&hasNoData);
+
+		CPLErr eErr = bsrc->RasterIO( GF_Read,
+		    src_offset_x*tsz_x, src_offset_y*tsz_y, // offset in input image
+		    sz_x, sz_y, // Size in output image
+		    buffer, sz_x, sz_y, // Buffer and size in buffer
+		    eDataType, // Requested type
+		    pixel_size, 2 * line_size
+#if GDAL_VERSION_MAJOR >= 2
+		    ,NULL
+#endif
+		    ); // Pixel and line space
+                if( eErr != CE_None )
+                {
+                    // TODO ?
+                    CPLError(CE_Failure, CPLE_AppDefined, "RasterIO() failed");
+                }
+
+		// Count the NoData values
+		int count = 0; // Assume all points are data
+		if (sampling_mode == SAMPLING_Avg) {
+
+// Dispatch based on data type
+// Use an ugly temporary macro to make it look easy
+// Runs the optimized version if the page is full with data
+#define resample(T)\
+    if (hasNoData) {\
+	count = MatchCount((T *)buffer, 4 * tsz_x * tsz_y, T(ndv));\
+	if (4 * tsz_x * tsz_y == count)\
+	    bdst->FillBlock(buffer);\
+	else if (0 != count)\
+	    AverageByFour((T *)buffer, tsz_x, tsz_y, T(ndv));\
+	}\
+    if (0 == count)\
+	AverageByFour((T *)buffer, tsz_x, tsz_y);\
+    break;
+
+		    switch (eDataType) {
+		    case GDT_Byte:	resample(GByte);
+		    case GDT_UInt16:    resample(GUInt16);
+		    case GDT_Int16:     resample(GInt16);
+		    case GDT_UInt32:    resample(GUInt32);
+		    case GDT_Int32:     resample(GInt32);
+		    case GDT_Float32:   resample(float);
+		    case GDT_Float64:   resample(double);
+                    default: CPLAssert(FALSE); break;
+		    }
+#undef resample
+
+		}
+		else if (sampling_mode == SAMPLING_Near) {
+
+#define resample(T)\
+    if (hasNoData) {\
+	count = MatchCount((T *)buffer, 4 * tsz_x * tsz_y, T(ndv));\
+	if (4 * tsz_x * tsz_y == count)\
+	    bdst->FillBlock(buffer);\
+	else if (0 != count)\
+	    NearByFour((T *)buffer, tsz_x, tsz_y, T(ndv));\
+    	}\
+    if (0 == count)\
+	NearByFour((T *)buffer, tsz_x, tsz_y);\
+    break;
+		    switch (eDataType) {
+		    case GDT_Byte:	resample(GByte);
+		    case GDT_UInt16:    resample(GUInt16);
+		    case GDT_Int16:     resample(GInt16);
+		    case GDT_UInt32:    resample(GUInt32);
+		    case GDT_Int32:     resample(GInt32);
+		    case GDT_Float32:   resample(float);
+		    case GDT_Float64:   resample(double);
+                    default: CPLAssert(FALSE); break;
+		    }
+#undef resample
+
+		}
+
+		// Done filling the buffer
+		// Argh, still need to clip the output to the band size on the right and bottom
+		// The offset should be fine, just the size might need adjustments
+		sz_x = tsz_x;
+		sz_y = tsz_y ;
+
+		if ( bdst->GetXSize() < dst_offset_x * sz_x + sz_x )
+		    sz_x = bdst->GetXSize() - dst_offset_x * sz_x;
+		if ( bdst->GetYSize() < dst_offset_y * sz_y + sz_y )
+		    sz_y = bdst->GetYSize() - dst_offset_y * sz_y;
+
+		eErr = bdst->RasterIO( GF_Write,
+		    dst_offset_x*tsz_x, dst_offset_y*tsz_y, // offset in output image
+		    sz_x, sz_y, // Size in output image
+		    buffer, sz_x, sz_y, // Buffer and size in buffer
+		    eDataType, // Requested type
+		    pixel_size, line_size
+#if GDAL_VERSION_MAJOR >= 2
+                    ,NULL
+#endif
+                ); // Pixel and line space
+                if( eErr != CE_None )
+                {
+                    // TODO ?
+                    CPLError(CE_Failure, CPLE_AppDefined, "RasterIO() failed");
+                }
+	    }
+
+	    // Mark the input data as no longer needed, saves RAM
+	    for (int band=0; band<bands; band++)
+		src_b[band]->FlushCache();
+	}
+    }
+
+    CPLFree(buffer);
+
+    for (int band=0; band<bands; band++)
+	dst_b[band]->FlushCache(); // Commit the output to disk
+
+    if (!recursive)
+	return CE_None;
+    return PatchOverview( BlockXOut, BlockYOut, WidthOut, HeightOut, srcLevel+1, true);
+}
+
+NAMESPACE_MRF_END
diff --git a/frmts/mrf/mrf_util.cpp b/frmts/mrf/mrf_util.cpp
new file mode 100644
index 0000000..18152d2
--- /dev/null
+++ b/frmts/mrf/mrf_util.cpp
@@ -0,0 +1,635 @@
+/*
+* Copyright (c) 2002-2012, California Institute of Technology.
+* All rights reserved.  Based on Government Sponsored Research under contracts NAS7-1407 and/or NAS7-03001.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+*   1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+*   2. Redistributions in binary form must reproduce the above copyright notice,
+*      this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+*   3. Neither the name of the California Institute of Technology (Caltech), its operating division the Jet Propulsion Laboratory (JPL),
+*      the National Aeronautics and Space Administration (NASA), nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE CALIFORNIA INSTITUTE OF TECHNOLOGY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* Copyright 2014-2015 Esri
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+
+/**
+ *  $Id$
+ *
+ *  Functions used by the driver, should all have prototypes in the header file
+ *
+ *  Author: Lucian Plesea, Lucian.Plesea at jpl.nasa.gov
+ */
+
+#include "marfa.h"
+#include <zlib.h>
+#include <algorithm>
+
+// LERC is not ready for big endian hosts for now
+#if defined(LERC) && defined(WORDS_BIGENDIAN)
+#undef LERC
+#endif
+
+CPL_C_START
+void GDALRegister_mrf(void);
+CPL_C_END
+
+NAMESPACE_MRF_START
+
+static const char * const ILC_N[]={ "PNG", "PPNG", "JPEG", "NONE", "DEFLATE", "TIF",
+#if defined(LERC)
+	"LERC",
+#endif
+	"Unknown" };
+static const char * const ILC_E[]={ ".ppg", ".ppg", ".pjg", ".til", ".pzp", ".ptf",
+#if defined(LERC)
+	".lrc" ,
+#endif
+	"" };
+static const char * const ILO_N[]={ "PIXEL", "BAND", "LINE", "Unknown" };
+
+char const * const * ILComp_Name=ILC_N;
+char const * const * ILComp_Ext=ILC_E;
+char const * const * ILOrder_Name=ILO_N;
+/**
+ *  Get the string for a compression type
+ */
+
+const char *CompName(ILCompression comp)
+{
+    if (comp>=IL_ERR_COMP) return ILComp_Name[IL_ERR_COMP];
+    return ILComp_Name[comp];
+}
+
+/**
+ *  Get the string for an order type
+ */
+
+const char *OrderName(ILOrder val)
+{
+    if (val>=IL_ERR_ORD) return ILOrder_Name[IL_ERR_ORD];
+    return ILOrder_Name[val];
+}
+
+ILCompression CompToken(const char *opt, ILCompression def)
+{
+    int i;
+    if (NULL==opt) return def;
+    for (i=0; ILCompression(i)<IL_ERR_COMP; i++)
+	if (EQUAL(opt,ILComp_Name[i]))
+	    break;
+    if (IL_ERR_COMP==ILCompression(i))
+	return def;
+    return ILCompression(i);
+}
+
+/**
+ *  Find a compression token
+ */
+
+ILOrder OrderToken(const char *opt, ILOrder def)
+{
+    int i;
+    if (NULL==opt) return def;
+    for (i=0; ILOrder(i)<IL_ERR_ORD; i++)
+	if (EQUAL(opt,ILOrder_Name[i]))
+	    break;
+    if (IL_ERR_ORD==ILOrder(i))
+	return def;
+    return ILOrder(i);
+}
+
+//
+//  Inserters for ILSize and ILIdx types
+//
+
+std::ostream& operator<<(std::ostream &out, const ILSize& sz)
+{
+    out << "X=" << sz.x << ",Y=" << sz.y << ",Z=" << sz.z
+	<< ",C=" << sz.c << ",L=" << sz.l;
+    return out;
+}
+
+std::ostream& operator<<(std::ostream &out, const ILIdx& t) {
+    out << "offset=" << t.offset << ",size=" << t.size;
+    return out;
+}
+
+// Define PPMW in marfa.h to enable this handy debug function
+
+#ifdef PPMW
+void ppmWrite(const char *fname, const char *data, const ILSize &sz) {
+    FILE *fp=fopen(fname,"wb");
+    switch(sz.c) {
+    case 4:
+	fprintf(fp,"P6 %d %d 255\n",sz.x,sz.y);
+	char *d=(char *)data;
+	for(int i=sz.x*sz.y;i;i--) {
+	    fwrite(d,3,1,fp);
+	    d+=4;
+	}
+	break;
+    case 3:
+	fprintf(fp,"P6 %d %d 255\n",sz.x,sz.y);
+	fwrite(data,sz.x*sz.y,3,fp);
+	break;
+    case 1:
+	fprintf(fp,"P5 %d %d 255\n",sz.x,sz.y);
+	fwrite(data,sz.x,sz.y,fp);
+	break;
+    default:
+	fprintf(stderr,"Can't write ppm file with %d bands\n",sz.c);
+	return;
+    }
+    fclose(fp);
+}
+#endif
+
+// Returns the size of the index for image and overlays
+// If scale is zero, only base image
+GIntBig IdxSize(const ILImage &full, const int scale) {
+    ILImage img = full;
+    img.pagecount = pcount(img.size, img.pagesize);
+    GIntBig sz = img.pagecount.l;
+    while (scale != 0 && 1 != img.pagecount.x * img.pagecount.y)
+    {
+	img.size.x = pcount(img.size.x, scale);
+	img.size.y = pcount(img.size.y, scale);
+	img.pagecount = pcount(img.size, img.pagesize);
+	sz += img.pagecount.l;
+    }
+    return sz*sizeof(ILIdx);
+}
+
+ILImage::ILImage()
+{
+    dataoffset = idxoffset = 0;
+    quality = 85;
+    size = ILSize(1, 1, 1, 1, 0);
+    pagesize = ILSize(384, 384, 1, 1, 0);
+    pagecount = pcount(size, pagesize);
+    comp = IL_PNG;
+    order = IL_Interleaved;
+    ci = GCI_Undefined;
+    pageSizeBytes = 0;
+    nbo = 0;
+    hasNoData = FALSE;
+    NoDataValue = 0.0;
+    dt = GDT_Unknown;
+}
+
+/**
+ *\brief Get a file name by replacing the extension.
+ * pass the data file name and the default extension starting with .
+ * If name length is not sufficient, it returns the extension
+ * If the input name is curl with parameters, the base file extension gets changed and
+ * parameters are preserved.
+ */
+
+CPLString getFname(const CPLString &in, const char *ext)
+{
+    if (strlen(in) < strlen(ext))
+	return CPLString(ext);
+
+    CPLString ret(in);
+    // Is it a web file with parameters?
+    size_t extlen = strlen(ext);
+    size_t qmark = ret.find_first_of('?');
+    if (!(qmark != std::string::npos && 0 == in.find("/vsicurl/http") && qmark >= extlen))
+	qmark = ret.size();
+    return ret.replace(qmark - extlen, extlen, ext);
+}
+
+/**
+ *\brief Get a file name, either from the configuration or from the default file name
+ * If the token is not defined by CPLGetXMLValue, if the extension of the in name is .xml,
+ * it returns the token with the extension changed to defext.
+ * Otherwise it returns the token itself
+ * It is pretty hard to separate local vs remote due to the gdal file name ornaments
+ * Absolute file names start with: ?:/ or /
+ *
+ */
+
+CPLString getFname(CPLXMLNode *node, const char *token, const CPLString &in, const char *def)
+{
+    CPLString fn = CPLGetXMLValue(node, token, "");
+    if (fn.size() == 0) // Not provided
+	return getFname(in, def);
+    size_t slashPos = fn.find_first_of("\\/");
+
+    // Does it look like an absolute path or we wont't find the basename of in
+    if (slashPos == 0				    // Starts with slash
+	|| (slashPos == 2 && fn[1] == ':')	    // Starts with disk letter column
+	|| !(slashPos == fn.find_first_not_of('.')) // Does not start with dots and then slash
+	|| in.find_first_of("\\/") == in.npos)      // We con't get a basename from in
+	return fn;
+
+    // Relative path, prepand the path from the in file name
+    return in.substr(0, in.find_last_of("\\/")+1) + fn;
+}
+
+
+/**
+ *\Brief Extracts a numerical value from a XML node
+ * It works like CPLGetXMLValue except for the default value being
+ * a number instead of a string
+ */
+
+double getXMLNum(CPLXMLNode *node, const char *pszPath, double def)
+{
+    const char *textval=CPLGetXMLValue(node,pszPath,NULL);
+    if (textval) return atof(textval);
+    return def;
+}
+
+//
+// Calculate offset of index, pos is in pages
+//
+
+GIntBig IdxOffset(const ILSize &pos, const ILImage &img)
+{
+    return img.idxoffset+sizeof(ILIdx)*
+	((GIntBig)pos.c+img.pagecount.c*(pos.x+img.pagecount.x*
+	(pos.y+img.pagecount.y*pos.z)));
+}
+
+// Is compression type endianness dependent?
+bool is_Endianess_Dependent(GDALDataType dt, ILCompression comp) {
+    // Add here all endianness dependent compressions
+    if (IL_ZLIB == comp || IL_NONE == comp)
+	if (GDALGetDataTypeSize( dt ) > 8)
+	    return true;
+    return false;
+}
+
+NAMESPACE_MRF_END
+
+/************************************************************************/
+/*                          GDALRegister_mrf()                          */
+/************************************************************************/
+
+USING_NAMESPACE_MRF
+
+void GDALRegister_mrf(void)
+
+{
+    GDALDriver *driver;
+
+    if (GDALGetDriverByName("MRF") == NULL) {
+	driver = new GDALDriver();
+	driver->SetDescription("MRF");
+	driver->SetMetadataItem(GDAL_DMD_LONGNAME, "Meta Raster Format");
+	driver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "frmt_marfa.html");
+		driver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES" );
+
+#if GDAL_VERSION_MAJOR >= 2
+        driver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+#endif
+
+	// These will need to be revisited, do we support complex data types too?
+	driver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES,
+				"Byte UInt16 Int16 Int32 UInt32 Float32 Float64");
+
+	driver->SetMetadataItem(GDAL_DMD_CREATIONOPTIONLIST,
+	    "<CreationOptionList>"
+	    "   <Option name='COMPRESS' type='string-select' default='PNG' description='PPNG = Palette PNG; DEFLATE = zlib '>"
+	    "	    <Value>JPEG</Value><Value>PNG</Value><Value>PPNG</Value>"
+	    "	    <Value>TIF</Value><Value>DEFLATE</Value><Value>NONE</Value>"
+#if defined(LERC)
+	    "	    <Value>LERC</Value>"
+#endif
+	    "   </Option>"
+	    "   <Option name='INTERLEAVE' type='string-select' default='PIXEL'>"
+	    "       <Value>PIXEL</Value>"
+	    "       <Value>BAND</Value>"
+	    "   </Option>\n"
+	    "	<Option name='ZSIZE' type='int' description='Third dimension size' default='1'/>"
+	    "   <Option name='QUALITY' type='int' description='best=99, bad=0, default=85'/>\n"
+	    "	<Option name='OPTIONS' type='string' description='Freeform dataset parameters'/>\n"
+	    "   <Option name='BLOCKSIZE' type='int' description='Block size, both x and y, default 512'/>\n"
+	    "   <Option name='BLOCKXSIZE' type='int' description='Block x size, default=512'/>\n"
+	    "   <Option name='BLOCKYSIZE' type='int' description='Block y size, default=512'/>\n"
+	    "   <Option name='NETBYTEORDER' type='boolean' description='Force endian for certain compress options, default is host order'/>\n"
+	    "	<Option name='CACHEDSOURCE' type='string' description='The source raster, if this is a cache'/>\n"
+	    "	<Option name='UNIFORM_SCALE' type='int' description='Scale of overlays in MRF, usually 2'/>\n"
+	    "	<Option name='NOCOPY' type='boolean' description='Leave created MRF empty, default=no'/>\n"
+	    "   <Option name='PHOTOMETRIC' type='string-select' default='DEFAULT' description='Band interpretation, may affect block encoding'>\n"
+	    "	    <Value>MULTISPECTRAL</Value>"
+	    "	    <Value>RGB</Value>"
+	    "	    <Value>YCC</Value>"
+	    "   </Option>\n"
+	    "</CreationOptionList>\n"
+	    );
+
+	driver->pfnOpen = GDALMRFDataset::Open;
+	driver->pfnIdentify = GDALMRFDataset::Identify;
+	driver->pfnCreateCopy = GDALMRFDataset::CreateCopy;
+	driver->pfnCreate = GDALMRFDataset::Create;
+	driver->pfnDelete = GDALMRFDataset::Delete;
+	GetGDALDriverManager()->RegisterDriver(driver);
+    }
+}
+
+NAMESPACE_MRF_START
+
+GDALMRFRasterBand *newMRFRasterBand(GDALMRFDataset *pDS, const ILImage &image, int b, int level)
+
+{
+    GDALMRFRasterBand *bnd;
+    switch(pDS->current.comp)
+    {
+    case IL_PPNG: // Uses the PNG code, just has a palette in each PNG
+    case IL_PNG:  bnd = new PNG_Band(pDS,image,b,level);  break;
+    case IL_JPEG: bnd = new JPEG_Band(pDS,image,b,level); break;
+    case IL_NONE: bnd = new Raw_Band(pDS,image,b,level);  break;
+    // ZLIB is a just raw, deflated band
+    case IL_ZLIB: bnd = new Raw_Band(pDS,image,b,level);  bnd->SetDeflate(1); break;
+    case IL_TIF:  bnd = new TIF_Band(pDS,image,b,level);  break;
+#if defined(LERC)
+    case IL_LERC: bnd = new LERC_Band(pDS,image,b,level); break;
+#endif
+    default:
+	return NULL;
+    }
+
+    // If something was flagged during band creation
+    if (CPLGetLastErrorNo() != CE_None) {
+	delete bnd;
+	return NULL;
+    }
+
+    // Copy the RW mode from the dataset
+    bnd->SetAccess(pDS->eAccess);
+    return bnd;
+}
+
+/**
+ *\Brief log in a given base
+ */
+double logb(double val, double base) {
+    return log(val)/log(base);
+}
+
+/**
+ *\Brief Is logb(val) an integer?
+ *
+ */
+
+int IsPower(double value, double base) {
+    double v=logb(value, base);
+    return CPLIsEqual(v,int(v+0.5));
+}
+
+/************************************************************************/
+/*                           SearchXMLSiblings()                        */
+/************************************************************************/
+
+/**
+ *\Brief Search for a sibling of the root node with a given name.
+ *
+ * Searches only the next siblings of the node passed in for the named element or attribute.
+ * If the first character of the pszElement is '=', the search includes the psRoot node
+ *
+ * @param psRoot the root node to search.  This should be a node of type
+ * CXT_Element.  NULL is safe.
+ *
+ * @param pszElement the name of the element or attribute to search for.
+ *
+ *
+ * @return The first matching node or NULL on failure.
+ */
+
+CPLXMLNode *SearchXMLSiblings( CPLXMLNode *psRoot, const char *pszElement )
+
+{
+    if( psRoot == NULL || pszElement == NULL )
+	return NULL;
+
+    // If the strings starts with '=', skip it and test the root
+    // If not, start testing with the next sibling
+    if (pszElement[0]=='=') pszElement++;
+    else psRoot=psRoot->psNext;
+
+    for (;psRoot!=NULL;psRoot=psRoot->psNext)
+	if ((psRoot->eType == CXT_Element ||
+	     psRoot->eType == CXT_Attribute)
+	     && EQUAL(pszElement,psRoot->pszValue))
+	    return psRoot;
+
+    return NULL;
+}
+
+//
+// Extension to CSL, set an entry if it doesn't already exist
+//
+char **CSLAddIfMissing(char **papszList,
+    const char *pszName, const char *pszValue)
+{
+    if (CSLFetchNameValue(papszList, pszName))
+	return papszList;
+    return CSLSetNameValue(papszList, pszName, pszValue);
+}
+
+//
+// Print a double in way when read with strtod
+//
+CPLString PrintDouble(double d, const char *frmt)
+{
+    CPLString res;
+    res.FormatC(d, NULL);
+    double v = CPLStrtod(res.c_str(), NULL);
+    if (d == v) return res;
+
+    //  This would be the right code with a C99 compiler that supports %a readback in strod()
+    //    return CPLString().Printf("%a",d);
+
+    return CPLString().FormatC(d, frmt);
+}
+
+static void XMLSetAttributeVal(CPLXMLNode *parent, const char* pszName,
+    const char *val)
+{
+    CPLCreateXMLNode(parent, CXT_Attribute, pszName);
+    CPLSetXMLValue(parent, pszName, val);
+}
+
+void XMLSetAttributeVal(CPLXMLNode *parent, const char* pszName,
+    const double val, const char *frmt)
+{
+    XMLSetAttributeVal(parent, pszName, CPLString().FormatC(val, frmt));
+
+    //  Unfortunately the %a doesn't work in VisualStudio scanf or strtod
+    //    if (strtod(sVal.c_str(),0) != val)
+    //	sVal.Printf("%a",val);
+}
+
+CPLXMLNode *XMLSetAttributeVal(CPLXMLNode *parent,
+    const char*pszName, const ILSize &sz, const char *frmt)
+{
+    CPLXMLNode *node = CPLCreateXMLNode(parent, CXT_Element, pszName);
+    XMLSetAttributeVal(node, "x", sz.x, frmt);
+    XMLSetAttributeVal(node, "y", sz.y, frmt);
+    if (sz.z != 1)
+	XMLSetAttributeVal(node, "z", sz.z, frmt);
+    XMLSetAttributeVal(node, "c", sz.c, frmt);
+    return node;
+}
+
+//
+// Prints a vector of doubles into a string and sets that string as the value of an XML attribute
+// If all values are the same, it only prints one
+//
+void XMLSetAttributeVal(CPLXMLNode *parent,
+    const char*pszName, std::vector<double> const &values)
+{
+    if (values.empty())
+	return;
+
+    CPLString value;
+    double val = values[0];
+    int single_val = true;
+    for (int i = 0; i < int(values.size()); i++) {
+	if (val != values[i])
+	    single_val = false;
+	value.append(PrintDouble(values[i]) + " ");
+	value.resize(value.size() - 1); // Cut the last space
+    }
+    if (single_val)
+	value = PrintDouble(values[0]);
+    CPLCreateXMLNode(parent, CXT_Attribute, pszName);
+    CPLSetXMLValue(parent, pszName, value);
+}
+
+/**
+ *\brief Read a ColorEntry XML node, return a GDALColorEntry structure
+ *
+ */
+
+GDALColorEntry GetXMLColorEntry(CPLXMLNode *p) {
+    GDALColorEntry ce;
+    ce.c1 = static_cast<short>(getXMLNum(p, "c1", 0));
+    ce.c2 = static_cast<short>(getXMLNum(p, "c2", 0));
+    ce.c3 = static_cast<short>(getXMLNum(p, "c3", 0));
+    ce.c4 = static_cast<short>(getXMLNum(p, "c4", 255));
+    return ce;
+}
+
+/**
+ *\Brief Verify or make a file that big
+ *
+ * @return true if size is OK or if extend succeeded
+ */
+
+int CheckFileSize(const char *fname, GIntBig sz, GDALAccess eAccess) {
+
+    VSIStatBufL statb;
+    if (VSIStatL(fname, &statb))
+	return false;
+    if (statb.st_size >= sz)
+	return true;
+
+    // Don't change anything unless updating
+    if (eAccess != GA_Update)
+	return false;
+
+    // There is no ftruncate in VSI, only truncate()
+    VSILFILE *ifp = VSIFOpenL(fname, "r+b");
+    if( ifp == NULL )
+        return false;
+
+// There is no VSIFTruncateL in gdal 1.8 and lower, seek and write something at the end
+#if GDAL_VERSION_MAJOR == 1 && GDAL_VERSION_MINOR <= 8
+    int zero = 0;
+    VSIFSeekL(ifp, sz - sizeof(zero), SEEK_SET);
+    int ret = (sizeof(zero) == VSIFWriteL(&zero, sizeof(zero), 1,ifp));
+#else
+    int ret = VSIFTruncateL(ifp, sz);
+#endif
+    VSIFCloseL(ifp);
+    return !ret;
+};
+
+// Similar to compress2() but with flags to control zlib features
+// Returns true if it worked
+int ZPack(const buf_mgr &src, buf_mgr &dst, int flags) {
+    z_stream stream;
+    int err;
+
+    memset(&stream, 0, sizeof(stream));
+    stream.next_in = (Bytef*)src.buffer;
+    stream.avail_in = (uInt)src.size;
+    stream.next_out = (Bytef*)dst.buffer;
+    stream.avail_out = (uInt)dst.size;
+
+    int level = std::min(9, flags & ZFLAG_LMASK);
+    int wb = MAX_WBITS;
+    // if gz flag is set, ignore raw request
+    if (flags & ZFLAG_GZ) wb += 16;
+    else if (flags & ZFLAG_RAW) wb = -wb;
+    int memlevel = 8; // Good compromise
+    int strategy = (flags & ZFLAG_SMASK) >> 6;
+    if (strategy > 4) strategy = 0;
+
+    err = deflateInit2(&stream, level, Z_DEFLATED, wb, memlevel, strategy);
+    if (err != Z_OK) return err;
+
+    err = deflate(&stream, Z_FINISH);
+    if (err != Z_STREAM_END) {
+	deflateEnd(&stream);
+	return false;
+    }
+    dst.size = stream.total_out;
+    err = deflateEnd(&stream);
+    return err == Z_OK;
+}
+
+// Similar to uncompress() from zlib, accepts the ZFLAG_RAW
+// Return true if it worked
+int ZUnPack(const buf_mgr &src, buf_mgr &dst, int flags) {
+
+    z_stream stream;
+    int err;
+
+    memset(&stream, 0, sizeof(stream));
+    stream.next_in = (Bytef*)src.buffer;
+    stream.avail_in = (uInt)src.size;
+    stream.next_out = (Bytef*)dst.buffer;
+    stream.avail_out = (uInt)dst.size;
+
+    // 32 means autodetec gzip or zlib header, negative 15 is for raw
+    int wb = (ZFLAG_RAW & flags) ? -MAX_WBITS: 32 + MAX_WBITS;
+    err = inflateInit2(&stream, wb);
+    if (err != Z_OK) return false;
+
+    err = inflate(&stream, Z_FINISH);
+    if (err != Z_STREAM_END) {
+	inflateEnd(&stream);
+	return false;
+    }
+    dst.size = stream.total_out;
+    err = inflateEnd(&stream);
+    return err == Z_OK;
+}
+
+NAMESPACE_MRF_END
diff --git a/frmts/mrsid/frmt_jp2mrsid.html b/frmts/mrsid/frmt_jp2mrsid.html
index dbb4327..c95e756 100644
--- a/frmts/mrsid/frmt_jp2mrsid.html
+++ b/frmts/mrsid/frmt_jp2mrsid.html
@@ -20,7 +20,7 @@ files.  The following creation options are supported.
 
 <ul>
 <li> <strong>WORLDFILE=YES</strong>: to write an ESRI world file (with the extension
-  .j2w). 
+  .j2w).
   <p>
 <li> <b>COMPRESSION=n</b>: Indicates the desired compression ratio.  Zero indicates
 lossless compression.  Twenty would indicate a 20:1 compression ratio (the
@@ -38,7 +38,7 @@ a template:
 <?xml version="1.0"?>
 <Jp2Profile version="1.0">
   <Header>
-    <name>Default</name> 
+    <name>Default</name>
     <description>LizardTech preferred settings (20051216)</description>
   </Header>
   <Codestream>
diff --git a/frmts/mrsid/frmt_mrsid.html b/frmts/mrsid/frmt_mrsid.html
index 36125dd..5f9b577 100644
--- a/frmts/mrsid/frmt_mrsid.html
+++ b/frmts/mrsid/frmt_mrsid.html
@@ -7,11 +7,11 @@
 
 <h1>MrSID --- Multi-resolution Seamless Image Database</h1>
 
-MrSID is a wavelet-based image compression technology which can utilise both
+MrSID is a wavelet-based image compression technology which can utilize both
 lossy and lossless encoding. This technology was acquired in its original
 form from Los Alamos National Laboratories (LANL), where it was developed
 under the aegis of the U.S. government for storing fingerprints for the FBI.
-Now is is developed and distributed by the LizardTech, Inc.<p>
+Now it is developed and distributed by the LizardTech, Inc.<p>
 
 This driver supports reading of MrSID image files using LizardTech's decoding
 software development kit (DSDK). <b>This DSDK is not free software, you should
diff --git a/frmts/mrsid/mrsiddataset.cpp b/frmts/mrsid/mrsiddataset.cpp
index 2c5caa7..0074a83 100644
--- a/frmts/mrsid/mrsiddataset.cpp
+++ b/frmts/mrsid/mrsiddataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: mrsiddataset.cpp 28785 2015-03-26 20:46:45Z goatbar $
+ * $Id: mrsiddataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  Multi-resolution Seamless Image Database (MrSID)
  * Purpose:  Read/write LizardTech's MrSID file format - Version 4+ SDK.
@@ -28,18 +28,23 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#ifdef DEBUG_BOOL
+#define DO_NOT_USE_DEBUG_BOOL
+#endif
+
 #define NO_DELETE
 
-#include "gdaljp2abstractdataset.h"
-#include "ogr_spatialref.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "gdaljp2abstractdataset.h"
 #include "gdaljp2metadata.h"
+#include "ogr_spatialref.h"
 #include <string>
 
 #include <geo_normalize.h>
 #include <geovalues.h>
 
-CPL_CVSID("$Id: mrsiddataset.cpp 28785 2015-03-26 20:46:45Z goatbar $");
+CPL_CVSID("$Id: mrsiddataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 CPL_C_START
 double GTIFAngleToDD( double dfAngle, int nUOMAngle );
@@ -48,7 +53,7 @@ CPL_C_END
 
 // Key Macros from Makefile:
 //   MRSID_ESDK: Means we have the encoding SDK (version 5 or newer required)
-//   MRSID_J2K: Means we are enabling MrSID SDK JPEG2000 support. 
+//   MRSID_J2K: Means we are enabling MrSID SDK JPEG2000 support.
 
 #include "lt_types.h"
 #include "lt_base.h"
@@ -105,13 +110,20 @@ CPL_C_END
 #  define MRSID_HAVE_GETWKT
 #endif
 
+/* getTotalBandData is deprecated by getBandData, at least starting with 8.5 */
+#if defined(LTI_SDK_MAJOR) && (LTI_SDK_MAJOR > 8 || (LTI_SDK_MAJOR >= 8 && LTI_SDK_MINOR >= 5))
+#  define myGetTotalBandData getBandData
+#else
+#  define myGetTotalBandData getTotalBandData
+#endif
+
 #include "mrsidstream.h"
 
 LT_USE_NAMESPACE(LizardTech)
 
 /* -------------------------------------------------------------------- */
 /*      Various wrapper templates used to force new/delete to happen    */
-/*      in the same heap.  See bug 1213 and MSDN knowledgebase          */
+/*      in the same heap.  See bug 1213 and MSDN knowledge base         */
 /*      article 122675.                                                 */
 /* -------------------------------------------------------------------- */
 
@@ -232,7 +244,8 @@ class MrSIDDataset : public GDALJP2AbstractDataset
     const LTIPixel      *poNDPixel;
 
     LTIDLLBuffer<LTISceneBuffer>  *poBuffer;
-    int                 nBlockXSize, nBlockYSize;
+    int                 nBlockXSize;
+    int                 nBlockYSize;
     int                 bPrevBlockRead;
     int                 nPrevBlockXOff, nPrevBlockYOff;
 
@@ -325,7 +338,7 @@ class MrSIDRasterBand : public GDALPamRasterBand
     virtual GDALRasterBand  *GetOverview( int );
 
     virtual CPLErr GetStatistics( int bApproxOK, int bForce,
-                                  double *pdfMin, double *pdfMax, 
+                                  double *pdfMin, double *pdfMax,
                                   double *pdfMean, double *pdfStdDev );
 
 #ifdef MRSID_ESDK
@@ -337,18 +350,18 @@ class MrSIDRasterBand : public GDALPamRasterBand
 /*                           MrSIDRasterBand()                          */
 /************************************************************************/
 
-MrSIDRasterBand::MrSIDRasterBand( MrSIDDataset *poDS, int nBand )
+MrSIDRasterBand::MrSIDRasterBand( MrSIDDataset *poDSIn, int nBandIn )
 {
-    this->poDS = poDS;
-    poGDS = poDS;
-    this->nBand = nBand;
-    this->eDataType = poDS->eDataType;
+    this->poDS = poDSIn;
+    poGDS = poDSIn;
+    this->nBand = nBandIn;
+    this->eDataType = poDSIn->eDataType;
 
 /* -------------------------------------------------------------------- */
 /*      Set the block sizes and buffer parameters.                      */
 /* -------------------------------------------------------------------- */
-    nBlockXSize = poDS->nBlockXSize;
-    nBlockYSize = poDS->nBlockYSize;
+    nBlockXSize = poDSIn->nBlockXSize;
+    nBlockYSize = poDSIn->nBlockYSize;
 //#ifdef notdef
     if( poDS->GetRasterXSize() > 2048 )
         nBlockXSize = 1024;
@@ -359,8 +372,9 @@ MrSIDRasterBand::MrSIDRasterBand( MrSIDDataset *poDS, int nBand )
 //#endif
 
     nBlockSize = nBlockXSize * nBlockYSize;
-    poPixel = new LTIDLLPixel<LTIPixel>( poDS->eColorSpace, poDS->nBands,
-                                         poDS->eSampleType );
+    poPixel = new LTIDLLPixel<LTIPixel>( poDSIn->eColorSpace,
+                                         static_cast<lt_uint16>(poDSIn->nBands),
+                                         poDSIn->eSampleType );
 
 
 /* -------------------------------------------------------------------- */
@@ -490,7 +504,7 @@ CPLErr MrSIDRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 #ifdef MRSID_ESDK
     if( poGDS->eAccess == GA_Update )
     {
-        CPLDebug( "MrSID", 
+        CPLDebug( "MrSID",
                   "IReadBlock() - DSDK - read on updatable file fails." );
         memset( pImage, 0, nBlockSize * GDALGetDataTypeSize(eDataType) / 8 );
         return CE_None;
@@ -509,10 +523,10 @@ CPLErr MrSIDRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         // XXX: The scene, passed to LTIImageStage::read() call must be
         // inside the image boundaries. So we should detect the last strip and
         // form the scene properly.
-        CPLDebug( "MrSID", 
-                  "IReadBlock - read() %dx%d block at %d,%d.", 
+        CPLDebug( "MrSID",
+                  "IReadBlock - read() %dx%d block at %d,%d.",
                   nBlockXSize, nBlockYSize, nCol, nLine );
-                  
+
         if(!LT_SUCCESS( poGDS->poLTINav->setSceneAsULWH(
                             nCol, nLine,
                             (nCol+nBlockXSize>poGDS->GetRasterXSize())?
@@ -520,7 +534,6 @@ CPLErr MrSIDRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                             (nLine+nBlockYSize>poGDS->GetRasterYSize())?
                             (poGDS->GetRasterYSize()-nLine):nBlockYSize,
                             poGDS->dfCurrentMag) ))
-            
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "MrSIDRasterBand::IReadBlock(): Failed to set scene position." );
@@ -548,7 +561,7 @@ CPLErr MrSIDRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         poGDS->nPrevBlockYOff = nBlockYOff;
     }
 
-    memcpy( pImage, poGDS->poBuffer->getTotalBandData(nBand - 1), 
+    memcpy( pImage, poGDS->poBuffer->myGetTotalBandData(static_cast<lt_uint16>(nBand - 1)),
             nBlockSize * (GDALGetDataTypeSize(poGDS->eDataType) / 8) );
 
     return CE_None;
@@ -615,7 +628,7 @@ CPLErr MrSIDRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                                    GDALDataType eBufType,
                                    GSpacing nPixelSpace, GSpacing nLineSpace,
                                    GDALRasterIOExtraArg* psExtraArg)
-    
+
 {
 /* -------------------------------------------------------------------- */
 /*      Fallback to default implementation if the whole scanline        */
@@ -634,8 +647,8 @@ CPLErr MrSIDRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 /* -------------------------------------------------------------------- */
 /*      Handle via the dataset level IRasterIO()                        */
 /* -------------------------------------------------------------------- */
-    return poGDS->IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, 
-                             nBufXSize, nBufYSize, eBufType, 
+    return poGDS->IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
+                             nBufXSize, nBufYSize, eBufType,
                              1, &nBand, nPixelSpace, nLineSpace, 0, psExtraArg );
 }
 
@@ -676,15 +689,15 @@ CPLErr MrSIDRasterBand::SetColorInterpretation( GDALColorInterp eNewInterp )
 /************************************************************************/
 
 CPLErr MrSIDRasterBand::GetStatistics( int bApproxOK, int bForce,
-                                       double *pdfMin, double *pdfMax, 
+                                       double *pdfMin, double *pdfMax,
                                        double *pdfMean, double *pdfStdDev )
 
 {
     if( bApproxOK )
         bForce = TRUE;
 
-    return GDALPamRasterBand::GetStatistics( bApproxOK, bForce, 
-                                             pdfMin, pdfMax, 
+    return GDALPamRasterBand::GetStatistics( bApproxOK, bForce,
+                                             pdfMin, pdfMax,
                                              pdfMean, pdfStdDev );
 }
 
@@ -733,7 +746,10 @@ GDALRasterBand *MrSIDRasterBand::GetOverview( int i )
 /*                           MrSIDDataset()                             */
 /************************************************************************/
 
-MrSIDDataset::MrSIDDataset(int bIsJPEG2000)
+MrSIDDataset::MrSIDDataset(int bIsJPEG2000) :
+    nBlockXSize(0),
+    nBlockYSize(0),
+    eColorSpace(LTI_COLORSPACE_INVALID)
 {
     poStream = NULL;
     poImageReader = NULL;
@@ -746,20 +762,20 @@ MrSIDDataset::MrSIDDataset(int bIsJPEG2000)
     eSampleType = LTI_DATATYPE_UINT8;
     nBands = 0;
     eDataType = GDT_Byte;
-    
+
     poBuffer = NULL;
     bPrevBlockRead = FALSE;
     nPrevBlockXOff = 0;
     nPrevBlockYOff = 0;
-    
+
     psDefn = NULL;
-    
+
     dfCurrentMag = 1.0;
     bIsOverview = FALSE;
     poParentDS = this;
     nOverviewCount = 0;
     papoOverviewDS = NULL;
-    
+
     poDriver = (GDALDriver*) GDALGetDriverByName( bIsJPEG2000 ? "JP2MrSID" : "MrSID" );
 }
 
@@ -825,7 +841,7 @@ int MrSIDDataset::CloseDependentDatasets()
 CPLErr MrSIDDataset::IRasterIO( GDALRWFlag eRWFlag,
                                 int nXOff, int nYOff, int nXSize, int nYSize,
                                 void * pData, int nBufXSize, int nBufYSize,
-                                GDALDataType eBufType, 
+                                GDALDataType eBufType,
                                 int nBandCount, int *panBandMap,
                                 GSpacing nPixelSpace, GSpacing nLineSpace,
                                 GSpacing nBandSpace,
@@ -843,16 +859,16 @@ CPLErr MrSIDDataset::IRasterIO( GDALRWFlag eRWFlag,
     if( nBufYSize == 1 || nBufXSize * ((double) nBufYSize) < 100.0 )
         bUseBlockedIO = TRUE;
 
-    if( CSLTestBoolean( CPLGetConfigOption( "GDAL_ONE_BIG_READ", "NO") ) )
+    if( CPLTestBool( CPLGetConfigOption( "GDAL_ONE_BIG_READ", "NO") ) )
         bUseBlockedIO = FALSE;
 
     if( bUseBlockedIO )
-        return GDALDataset::BlockBasedRasterIO( 
+        return GDALDataset::BlockBasedRasterIO(
             eRWFlag, nXOff, nYOff, nXSize, nYSize,
-            pData, nBufXSize, nBufYSize, eBufType, 
+            pData, nBufXSize, nBufYSize, eBufType,
             nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace, psExtraArg );
     CPLDebug( "MrSID", "RasterIO() - using optimized dataset level IO." );
-    
+
 /* -------------------------------------------------------------------- */
 /*      What is our requested window relative to the base dataset.      */
 /*      We want to operate from here on as if we were operating on      */
@@ -872,12 +888,12 @@ CPLErr MrSIDDataset::IRasterIO( GDALRWFlag eRWFlag,
 /*      not force us to the next level.                                 */
 /* -------------------------------------------------------------------- */
     int iOverview = 0;
-    double dfZoomMag = MIN((nXSize / (double)nBufXSize), 
+    double dfZoomMag = MIN((nXSize / (double)nBufXSize),
                            (nYSize / (double)nBufYSize));
 
-    for( nZoomMag = 1; 
-         nZoomMag * 2 < (dfZoomMag + 0.1) 
-             && iOverview < poParentDS->nOverviewCount; 
+    for( nZoomMag = 1;
+         nZoomMag * 2 < (dfZoomMag + 0.1)
+             && iOverview < poParentDS->nOverviewCount;
          nZoomMag *= 2, iOverview++ ) {}
 
 /* -------------------------------------------------------------------- */
@@ -886,8 +902,8 @@ CPLErr MrSIDDataset::IRasterIO( GDALRWFlag eRWFlag,
 /*      higher resolution than the buffer of data requested.            */
 /* -------------------------------------------------------------------- */
     int  nTmpPixelSize;
-    LTIPixel       oPixel( eColorSpace, nBands, eSampleType );
-    
+    LTIPixel       oPixel( eColorSpace, static_cast<lt_uint16>(nBands), eSampleType );
+
     LT_STATUS eLTStatus;
     unsigned int maxWidth;
     unsigned int maxHeight;
@@ -923,9 +939,9 @@ CPLErr MrSIDDataset::IRasterIO( GDALRWFlag eRWFlag,
 /*      Create navigator, and move to the requested scene area.         */
 /* -------------------------------------------------------------------- */
     LTINavigator oNav( *poImageReader );
-    
-    if( !LT_SUCCESS(oNav.setSceneAsULWH( sceneUlXOff, sceneUlYOff, 
-                                         sceneWidth, sceneHeight, 
+
+    if( !LT_SUCCESS(oNav.setSceneAsULWH( sceneUlXOff, sceneUlYOff,
+                                         sceneWidth, sceneHeight,
                                          1.0 / nZoomMag )) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -934,11 +950,11 @@ CPLErr MrSIDDataset::IRasterIO( GDALRWFlag eRWFlag,
         return CE_Failure;
     }
 
-    CPLDebug( "MrSID", 
+    CPLDebug( "MrSID",
               "Dataset:IRasterIO(%d,%d %dx%d -> %dx%d -> %dx%d, zoom=%d)",
-              nXOff, nYOff, nXSize, nYSize, 
+              nXOff, nYOff, nXSize, nYSize,
               sceneWidth, sceneHeight,
-              nBufXSize, nBufYSize, 
+              nBufXSize, nBufYSize,
               nZoomMag );
 
     if( !oNav.isSceneValid() )
@@ -967,16 +983,16 @@ CPLErr MrSIDDataset::IRasterIO( GDALRWFlag eRWFlag,
     {
         for( int iBand = 0; iBand < nBandCount; iBand++ )
         {
-            GByte *pabySrcBand = (GByte *) 
-                oLTIBuffer.getTotalBandData( panBandMap[iBand] - 1 );
-	  
+            GByte *pabySrcBand = (GByte *)
+                oLTIBuffer.myGetTotalBandData( static_cast<lt_uint16>(panBandMap[iBand] - 1) );
+
             for( int iLine = 0; iLine < nBufYSize; iLine++ )
 	    {
                 GDALCopyWords( pabySrcBand + iLine*nTmpPixelSize*sceneWidth,
-                               eDataType, nTmpPixelSize, 
-                               ((GByte *)pData) + iLine*nLineSpace 
-                               + iBand * nBandSpace, 
-                               eBufType, nPixelSpace,
+                               eDataType, nTmpPixelSize,
+                               ((GByte *)pData) + iLine*nLineSpace
+                               + iBand * nBandSpace,
+                               eBufType, static_cast<int>(nPixelSpace),
                                nBufXSize );
 	    }
 	}
@@ -993,26 +1009,26 @@ CPLErr MrSIDDataset::IRasterIO( GDALRWFlag eRWFlag,
 
             for( iBufPixel = 0; iBufPixel < nBufXSize; iBufPixel++ )
 	    {
-                int iTmpPixel = (int) 
+                int iTmpPixel = (int)
                     floor(((iBufPixel+0.5) / nBufXSize) * sceneWidth);
 
                 for( int iBand = 0; iBand < nBandCount; iBand++ )
 		{
                     GByte *pabySrc, *pabyDst;
 
-                    pabyDst = ((GByte *) pData) 
+                    pabyDst = ((GByte *) pData)
                         + nPixelSpace * iBufPixel
                         + nLineSpace * iBufLine
                         + nBandSpace * iBand;
 
-                    pabySrc = (GByte *) oLTIBuffer.getTotalBandData( 
-                        panBandMap[iBand] - 1 );
+                    pabySrc = (GByte *) oLTIBuffer.myGetTotalBandData(
+                        static_cast<lt_uint16>(panBandMap[iBand] - 1) );
                     pabySrc += (iTmpLine * sceneWidth + iTmpPixel) * nTmpPixelSize;
 
                     if( eDataType == eBufType )
                         memcpy( pabyDst, pabySrc, nTmpPixelSize );
                     else
-                        GDALCopyWords( pabySrc, eDataType, 0, 
+                        GDALCopyWords( pabySrc, eDataType, 0,
                                        pabyDst, eBufType, 0, 1 );
 		}
 	    }
@@ -1052,7 +1068,7 @@ char *MrSIDDataset::SerializeMetadataRec( const LTIMetadataRecord *poMetadataRec
     for ( i = 0; i < iNumDims; i++ )
     {
         // stops on large binary data
-        if ( poMetadataRec->getDataType() == LTI_METADATA_DATATYPE_UINT8 
+        if ( poMetadataRec->getDataType() == LTI_METADATA_DATATYPE_UINT8
              && paiDims[i] > 1024 )
             return pszMetadata;
 
@@ -1092,12 +1108,12 @@ char *MrSIDDataset::SerializeMetadataRec( const LTIMetadataRecord *poMetadataRec
                     break;
             }
 
-            iLength = strlen(pszMetadata) + strlen(osTemp) + 2;
+            iLength = static_cast<int>(strlen(pszMetadata) + strlen(osTemp) + 2);
 
             pszMetadata = (char *)CPLRealloc( pszMetadata, iLength );
             if ( !EQUAL( pszMetadata, "" ) )
                 strncat( pszMetadata, ",", 1 );
-            strncat( pszMetadata, osTemp, iLength );
+            CPLStrlcat( pszMetadata, osTemp, iLength );
         }
     }
 
@@ -1258,20 +1274,20 @@ CPLErr MrSIDDataset::OpenZoomLevel( lt_int32 iZoom )
         oGeo.get( adfGeoTransform[0], adfGeoTransform[3],
                   adfGeoTransform[1], adfGeoTransform[5],
                   adfGeoTransform[2], adfGeoTransform[4] );
-        
+
         adfGeoTransform[0] = adfGeoTransform[0] - adfGeoTransform[1] / 2;
         adfGeoTransform[3] = adfGeoTransform[3] - adfGeoTransform[5] / 2;
         bGeoTransformValid = TRUE;
     }
     else if( iZoom == 0 )
     {
-        bGeoTransformValid = 
+        bGeoTransformValid =
             GDALReadWorldFile( GetDescription(), NULL,
                                adfGeoTransform )
             || GDALReadWorldFile( GetDescription(), ".wld",
                                   adfGeoTransform );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read wkt.                                                       */
 /* -------------------------------------------------------------------- */
@@ -1279,12 +1295,12 @@ CPLErr MrSIDDataset::OpenZoomLevel( lt_int32 iZoom )
     if( !poImageReader->isGeoCoordImplicit() )
     {
         const LTIGeoCoord& oGeo = poImageReader->getGeoCoord();
-        
+
         if( oGeo.getWKT() )
         {
             /* Workaround probable issue with GeoDSK 7 on 64bit Linux */
-            if (!(pszProjection != NULL && !EQUALN(pszProjection, "LOCAL_CS", 8)
-                && EQUALN( oGeo.getWKT(), "LOCAL_CS", 8)))
+            if (!(pszProjection != NULL && !STARTS_WITH_CI(pszProjection, "LOCAL_CS")
+                && STARTS_WITH_CI(oGeo.getWKT(), "LOCAL_CS")))
             {
                 CPLFree( pszProjection );
                 pszProjection =  CPLStrdup( oGeo.getWKT() );
@@ -1315,7 +1331,7 @@ CPLErr MrSIDDataset::OpenZoomLevel( lt_int32 iZoom )
             {
                 if (nCountLine == 1 && strcmp(pszLine, "::MetadataFile") != 0)
                     break;
-                if (EQUALN(pszLine, "Projection UTM ", 15))
+                if (STARTS_WITH_CI(pszLine, "Projection UTM "))
                     nUTMZone = atoi(pszLine + 15);
                 else if (EQUAL(pszLine, "Datum WGS84"))
                     bWGS84 = TRUE;
@@ -1330,7 +1346,7 @@ CPLErr MrSIDDataset::OpenZoomLevel( lt_int32 iZoom )
             if (nUTMZone >= 1 && nUTMZone <= 60 && bWGS84 && bUnitsMeter)
             {
                 osMETFilename = pszMETFilename;
-                
+
                 OGRSpatialReference oSRS;
                 oSRS.importFromEPSG(32600 + nUTMZone);
                 CPLFree(pszProjection);
@@ -1367,7 +1383,7 @@ static int MrSIDIdentify( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->nHeaderBytes < 32 )
         return FALSE;
 
-    if ( !EQUALN((const char *) poOpenInfo->pabyHeader, "msid", 4) )
+    if ( !STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "msid") )
         return FALSE;
 
 #if defined(LTI_SDK_MAJOR) && LTI_SDK_MAJOR >= 8
@@ -1392,14 +1408,14 @@ static GDALDataset* MrSIDOpen( GDALOpenInfo *poOpenInfo )
 {
     if (!MrSIDIdentify(poOpenInfo))
         return NULL;
-        
+
     return MrSIDDataset::Open( poOpenInfo, FALSE );
 }
 
 
 #ifdef MRSID_J2K
 
-static const unsigned char jpc_header[] = 
+static const unsigned char jpc_header[] =
 {0xff,0x4f};
 
 /************************************************************************/
@@ -1418,13 +1434,13 @@ static int JP2Identify( GDALOpenInfo *poOpenInfo )
         const char *pszExtension;
 
         pszExtension = CPLGetExtension( poOpenInfo->pszFilename );
-        
-        if( !EQUAL(pszExtension,"jpc") && !EQUAL(pszExtension,"j2k") 
-            && !EQUAL(pszExtension,"jp2") && !EQUAL(pszExtension,"jpx") 
+
+        if( !EQUAL(pszExtension,"jpc") && !EQUAL(pszExtension,"j2k")
+            && !EQUAL(pszExtension,"jp2") && !EQUAL(pszExtension,"jpx")
             && !EQUAL(pszExtension,"j2c") && !EQUAL(pszExtension,"ntf"))
             return FALSE;
     }
-    else if( !EQUALN((const char *) poOpenInfo->pabyHeader + 4, "jP  ", 4) )
+    else if( !STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader + 4, "jP  ") )
         return FALSE;
 
     return TRUE;
@@ -1440,7 +1456,7 @@ static GDALDataset* JP2Open( GDALOpenInfo *poOpenInfo )
 {
     if (!JP2Identify(poOpenInfo))
         return NULL;
-        
+
     return MrSIDDataset::Open( poOpenInfo, TRUE );
 }
 
@@ -1522,7 +1538,7 @@ GDALDataset *MrSIDDataset::Open( GDALOpenInfo * poOpenInfo, int bIsJP2 )
     {
         MrSIDImageReader    *reader = MrSIDImageReader::create();
         eStat = reader->initialize( poDS->poStream, NULL );
-        poDS->poImageReader = reader;           
+        poDS->poImageReader = reader;
     }
 
 #else /* LTI_SDK_MAJOR < 7 */
@@ -1560,9 +1576,8 @@ GDALDataset *MrSIDDataset::Open( GDALOpenInfo * poOpenInfo, int bIsJP2 )
     poDS->poMetadata = new LTIDLLCopy<LTIMetadataDatabase>(
         poDS->poImageReader->getMetadata() );
     const GUInt32       iNumRecs = poDS->poMetadata->getIndexCount();
-    GUInt32             i;
 
-    for ( i = 0; i < iNumRecs; i++ )
+    for ( GUInt32 i = 0; i < iNumRecs; i++ )
     {
         const LTIMetadataRecord *poMetadataRec = NULL;
         if ( LT_SUCCESS(poDS->poMetadata->getDataByIndex(i, poMetadataRec)) )
@@ -1605,14 +1620,14 @@ GDALDataset *MrSIDDataset::Open( GDALOpenInfo * poOpenInfo, int bIsJP2 )
         char letter;
         MrSIDImageReader* poMrSIDImageReader = (MrSIDImageReader*)poDS->poImageReader;
         poMrSIDImageReader->getVersion(major, minor, minor, letter);
-        if (major < 2) 
+        if (major < 2)
             major = 2;
         poDS->SetMetadataItem( "VERSION", CPLString().Printf("MG%d", major) );
 #endif
     }
 
     poDS->GetGTIFDefn();
-    
+
 /* -------------------------------------------------------------------- */
 /*      Get number of resolution levels (we will use them as overviews).*/
 /* -------------------------------------------------------------------- */
@@ -1685,7 +1700,7 @@ static int EPSGProjMethodToCTProjMethod( int nEPSG )
 
 {
     /* see trf_method.csv for list of EPSG codes */
-    
+
     switch( nEPSG )
     {
       case 9801:
@@ -1778,8 +1793,8 @@ static int EPSGProjMethodToCTProjMethod( int nEPSG )
 /*      Explicitly copied from geo_normalize.c of the GeoTIFF package.  */
 /************************************************************************/
 
-static int SetGTParmIds( int nCTProjection, 
-                         int *panProjParmId, 
+static int SetGTParmIds( int nCTProjection,
+                         int *panProjParmId,
                          int *panEPSGCodes )
 
 {
@@ -1793,7 +1808,7 @@ static int SetGTParmIds( int nCTProjection,
     memset( panEPSGCodes, 0, sizeof(int) * 7 );
 
     /* psDefn->nParms = 7; */
-    
+
     switch( nCTProjection )
     {
       case CT_CassiniSoldner:
@@ -1842,7 +1857,7 @@ static int SetGTParmIds( int nCTProjection,
         panEPSGCodes[5] = EPSGProjCenterEasting;
         panEPSGCodes[6] = EPSGProjCenterNorthing;
         return TRUE;
-        
+
       case CT_LambertConfConic_1SP:
       case CT_Mercator:
       case CT_ObliqueStereographic:
@@ -1892,7 +1907,7 @@ static int SetGTParmIds( int nCTProjection,
     }
 }
 
-static const char *papszDatumEquiv[] =
+static const char * const papszDatumEquiv[] =
 {
     "Militar_Geographische_Institut",
     "Militar_Geographische_Institute",
@@ -1951,9 +1966,9 @@ static void WKTMassageDatum( char ** ppszDatum )
         pszDatum[j] = '\0';
     else
         pszDatum[j+1] = '\0';
-    
+
 /* -------------------------------------------------------------------- */
-/*      Search for datum equivelences.  Specific massaged names get     */
+/*      Search for datum equivalences.  Specific massaged names get     */
 /*      mapped to OpenGIS specified names.                              */
 /* -------------------------------------------------------------------- */
     for( i = 0; papszDatumEquiv[i] != NULL; i += 2 )
@@ -1990,7 +2005,7 @@ void MrSIDDataset::FetchProjParms()
         && !GetMetadataElement( "GEOTIFF_NUM::3090:ProjCenterEastingGeoKey",
                                 &dfFalseEasting ) )
         dfFalseEasting = 0.0;
-        
+
     if( !GetMetadataElement( "GEOTIFF_NUM::3083::ProjFalseNorthingGeoKey",
                              &dfFalseNorthing )
         && !GetMetadataElement( "GEOTIFF_NUM::3091::ProjCenterNorthingGeoKey",
@@ -2021,7 +2036,7 @@ void MrSIDDataset::FetchProjParms()
         if( GetMetadataElement( "GEOTIFF_NUM::3092::ProjScaleAtNatOriginGeoKey",
                                 &dfNatOriginScale ) == 0 )
             dfNatOriginScale = 1.0;
-            
+
         /* notdef: should transform to decimal degrees at this point */
 
         psDefn->ProjParm[0] = dfNatOriginLat;
@@ -2049,7 +2064,7 @@ void MrSIDDataset::FetchProjParms()
                                 &dfNatOriginLong ) == 0
             && GetMetadataElement( "GEOTIFF_NUM::3084::ProjFalseOriginLongGeoKey",
                                    &dfNatOriginLong ) == 0
-            && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey", 
+            && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey",
                                    &dfNatOriginLong ) == 0 )
             dfNatOriginLong = 0.0;
 
@@ -2088,7 +2103,7 @@ void MrSIDDataset::FetchProjParms()
                                 &dfNatOriginLong ) == 0
             && GetMetadataElement( "GEOTIFF_NUM::3084::ProjFalseOriginLongGeoKey",
                                    &dfNatOriginLong ) == 0
-            && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey", 
+            && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey",
                                    &dfNatOriginLong ) == 0 )
             dfNatOriginLong = 0.0;
 
@@ -2113,7 +2128,7 @@ void MrSIDDataset::FetchProjParms()
             && GetMetadataElement( "GEOTIFF_NUM::3093::ProjScaleAtCenterGeoKey",
                                    &dfNatOriginScale ) == 0 )
             dfNatOriginScale = 1.0;
-            
+
         /* notdef: should transform to decimal degrees at this point */
 
         psDefn->ProjParm[0] = dfNatOriginLat;
@@ -2142,7 +2157,7 @@ void MrSIDDataset::FetchProjParms()
                                 &dfNatOriginLong ) == 0
             && GetMetadataElement( "GEOTIFF_NUM::3084::ProjFalseOriginLongGeoKey",
                                    &dfNatOriginLong ) == 0
-            && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey", 
+            && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey",
                                    &dfNatOriginLong ) == 0 )
             dfNatOriginLong = 0.0;
 
@@ -2160,7 +2175,7 @@ void MrSIDDataset::FetchProjParms()
             && GetMetadataElement( "GEOTIFF_NUM::3093::ProjScaleAtCenterGeoKey",
                                    &dfNatOriginScale ) == 0 )
             dfNatOriginScale = 1.0;
-            
+
         /* notdef: should transform to decimal degrees at this point */
 
         psDefn->ProjParm[0] = dfNatOriginLat;
@@ -2189,7 +2204,7 @@ void MrSIDDataset::FetchProjParms()
                                 &dfNatOriginLong ) == 0
             && GetMetadataElement( "GEOTIFF_NUM::3084::ProjFalseOriginLongGeoKey",
                                    &dfNatOriginLong ) == 0
-            && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey", 
+            && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey",
                                    &dfNatOriginLong ) == 0 )
             dfNatOriginLong = 0.0;
 
@@ -2224,7 +2239,7 @@ void MrSIDDataset::FetchProjParms()
                                 &dfNatOriginLong ) == 0
             && GetMetadataElement( "GEOTIFF_NUM::3084::ProjFalseOriginLongGeoKey",
                                    &dfNatOriginLong ) == 0
-            && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey", 
+            && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey",
                                    &dfNatOriginLong ) == 0 )
             dfNatOriginLong = 0.0;
 
@@ -2266,7 +2281,7 @@ void MrSIDDataset::FetchProjParms()
             && GetMetadataElement( "GEOTIFF_NUM::3093::ProjScaleAtCenterGeoKey",
                                    &dfNatOriginScale ) == 0 )
             dfNatOriginScale = 1.0;
-            
+
         /* notdef: should transform to decimal degrees at this point */
 
         psDefn->ProjParm[0] = dfNatOriginLat;
@@ -2298,7 +2313,7 @@ void MrSIDDataset::FetchProjParms()
                                 &dfNatOriginLong ) == 0
             && GetMetadataElement( "GEOTIFF_NUM::3084::ProjFalseOriginLongGeoKey",
                                    &dfNatOriginLong ) == 0
-            && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey", 
+            && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey",
                                    &dfNatOriginLong ) == 0 )
             dfNatOriginLong = 0.0;
 
@@ -2344,7 +2359,7 @@ void MrSIDDataset::FetchProjParms()
                                 &dfNatOriginLong ) == 0
             && GetMetadataElement( "GEOTIFF_NUM::3084::ProjFalseOriginLongGeoKey",
                                    &dfNatOriginLong ) == 0
-            && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey", 
+            && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey",
                                    &dfNatOriginLong ) == 0 )
             dfNatOriginLong = 0.0;
 
@@ -2460,14 +2475,14 @@ void MrSIDDataset::GetGTIFDefn()
             psDefn->GCS = (short) nGCS;
         }
     }
-   
+
 /* -------------------------------------------------------------------- */
 /*      If the Proj_ code is specified directly, use that.              */
 /* -------------------------------------------------------------------- */
     if( psDefn->ProjCode == KvUserDefined )
         GetMetadataElement( "GEOTIFF_NUM::3074::ProjectionGeoKey",
                             &(psDefn->ProjCode) );
-    
+
     if( psDefn->ProjCode != KvUserDefined )
     {
         /*
@@ -2479,7 +2494,7 @@ void MrSIDDataset::GetGTIFDefn()
          */
         GTIFGetProjTRFInfo( psDefn->ProjCode, NULL, &(psDefn->Projection),
                             psDefn->ProjParm );
-        
+
         /*
          * Set the GeoTIFF identity of the parameters.
          */
@@ -2505,7 +2520,7 @@ void MrSIDDataset::GetGTIFDefn()
         GTIFGetGCSInfo( psDefn->GCS, NULL, &(psDefn->Datum), &(psDefn->PM),
                         &(psDefn->UOMAngle) );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Handle the GCS angular units.  GeogAngularUnitsGeoKey           */
 /*      overrides the GCS or PCS setting.                               */
@@ -2552,7 +2567,7 @@ void MrSIDDataset::GetGTIFDefn()
                         &(psDefn->SemiMajor) );
     GetMetadataElement( "GEOTIFF_NUM::2058::GeogSemiMinorAxisGeoKey",
                         &(psDefn->SemiMinor) );
-    
+
     if( GetMetadataElement( "GEOTIFF_NUM::2059::GeogInvFlatteningGeoKey",
                             &dfInvFlattening ) == 1 )
     {
@@ -2622,16 +2637,16 @@ void MrSIDDataset::GetGTIFDefn()
         psDefn->nParms = 7;
         psDefn->ProjParmId[0] = ProjNatOriginLatGeoKey;
         psDefn->ProjParm[0] = 0.0;
-            
+
         psDefn->ProjParmId[1] = ProjNatOriginLongGeoKey;
         psDefn->ProjParm[1] = psDefn->Zone*6 - 183.0;
-        
+
         psDefn->ProjParmId[4] = ProjScaleAtNatOriginGeoKey;
         psDefn->ProjParm[4] = 0.9996;
-        
+
         psDefn->ProjParmId[5] = ProjFalseEastingGeoKey;
         psDefn->ProjParm[5] = 500000.0;
-        
+
         psDefn->ProjParmId[6] = ProjFalseNorthingGeoKey;
 
         if( psDefn->MapSys == MapSys_UTM_North )
@@ -2669,34 +2684,34 @@ static void GTIFToCPLRecycleString( char **ppszTarget )
 /*  Copied from the gt_wkt_srs.cpp.                                     */
 /************************************************************************/
 
-char *MrSIDDataset::GetOGISDefn( GTIFDefn *psDefn )
+char *MrSIDDataset::GetOGISDefn( GTIFDefn *psDefnIn )
 {
     OGRSpatialReference oSRS;
 
-    if( psDefn->Model != ModelTypeProjected 
-        && psDefn->Model != ModelTypeGeographic )
+    if( psDefnIn->Model != ModelTypeProjected
+        && psDefnIn->Model != ModelTypeGeographic )
         return CPLStrdup("");
-    
+
 /* -------------------------------------------------------------------- */
 /*      If this is a projected SRS we set the PROJCS keyword first      */
 /*      to ensure that the GEOGCS will be a child.                      */
 /* -------------------------------------------------------------------- */
-    if( psDefn->Model == ModelTypeProjected )
+    if( psDefnIn->Model == ModelTypeProjected )
     {
         char    *pszPCSName;
         int     bPCSNameSet = FALSE;
 
-        if( psDefn->PCS != KvUserDefined )
+        if( psDefnIn->PCS != KvUserDefined )
         {
 
-            if( GTIFGetPCSInfo( psDefn->PCS, &pszPCSName, NULL, NULL, NULL ) )
+            if( GTIFGetPCSInfo( psDefnIn->PCS, &pszPCSName, NULL, NULL, NULL ) )
                 bPCSNameSet = TRUE;
-            
+
             oSRS.SetNode( "PROJCS", bPCSNameSet ? pszPCSName : "unnamed" );
             if( bPCSNameSet )
                 GTIFFreeMemory( pszPCSName );
 
-            oSRS.SetAuthority( "PROJCS", "EPSG", psDefn->PCS );
+            oSRS.SetAuthority( "PROJCS", "EPSG", psDefnIn->PCS );
         }
         else
         {
@@ -2707,7 +2722,7 @@ char *MrSIDDataset::GetOGISDefn( GTIFDefn *psDefn )
                 oSRS.SetNode( "PROJCS", szPCSName );
         }
     }
-    
+
 /* ==================================================================== */
 /*      Setup the GeogCS                                                */
 /* ==================================================================== */
@@ -2718,23 +2733,23 @@ char *MrSIDDataset::GetOGISDefn( GTIFDefn *psDefn )
     char        *pszAngularUnits = NULL;
     double      dfInvFlattening, dfSemiMajor;
     char        szGCSName[200];
-    
+
     if( GetMetadataElement( "GEOTIFF_NUM::2049::GeogCitationGeoKey",
                             szGCSName, sizeof(szGCSName) ) )
         pszGeogName = CPLStrdup(szGCSName);
     else
     {
-        GTIFGetGCSInfo( psDefn->GCS, &pszGeogName, NULL, NULL, NULL );
+        GTIFGetGCSInfo( psDefnIn->GCS, &pszGeogName, NULL, NULL, NULL );
         GTIFToCPLRecycleString(&pszGeogName);
     }
-    GTIFGetDatumInfo( psDefn->Datum, &pszDatumName, NULL );
+    GTIFGetDatumInfo( psDefnIn->Datum, &pszDatumName, NULL );
     GTIFToCPLRecycleString(&pszDatumName);
-    GTIFGetPMInfo( psDefn->PM, &pszPMName, NULL );
+    GTIFGetPMInfo( psDefnIn->PM, &pszPMName, NULL );
     GTIFToCPLRecycleString(&pszPMName);
-    GTIFGetEllipsoidInfo( psDefn->Ellipsoid, &pszSpheroidName, NULL, NULL );
+    GTIFGetEllipsoidInfo( psDefnIn->Ellipsoid, &pszSpheroidName, NULL, NULL );
     GTIFToCPLRecycleString(&pszSpheroidName);
-    
-    GTIFGetUOMAngleInfo( psDefn->UOMAngle, &pszAngularUnits, NULL );
+
+    GTIFGetUOMAngleInfo( psDefnIn->UOMAngle, &pszAngularUnits, NULL );
     GTIFToCPLRecycleString(&pszAngularUnits);
     if( pszAngularUnits == NULL )
         pszAngularUnits = CPLStrdup("unknown");
@@ -2742,42 +2757,42 @@ char *MrSIDDataset::GetOGISDefn( GTIFDefn *psDefn )
     if( pszDatumName != NULL )
         WKTMassageDatum( &pszDatumName );
 
-    dfSemiMajor = psDefn->SemiMajor;
-    if( psDefn->SemiMajor == 0.0 )
+    dfSemiMajor = psDefnIn->SemiMajor;
+    if( psDefnIn->SemiMajor == 0.0 )
     {
         pszSpheroidName = CPLStrdup("unretrievable - using WGS84");
         dfSemiMajor = SRS_WGS84_SEMIMAJOR;
         dfInvFlattening = SRS_WGS84_INVFLATTENING;
     }
     else
-        dfInvFlattening = OSRCalcInvFlattening(psDefn->SemiMajor,psDefn->SemiMinor);
+        dfInvFlattening = OSRCalcInvFlattening(psDefnIn->SemiMajor,psDefnIn->SemiMinor);
 
-    oSRS.SetGeogCS( pszGeogName, pszDatumName, 
+    oSRS.SetGeogCS( pszGeogName, pszDatumName,
                     pszSpheroidName, dfSemiMajor, dfInvFlattening,
                     pszPMName,
-                    psDefn->PMLongToGreenwich / psDefn->UOMAngleInDegrees,
+                    psDefnIn->PMLongToGreenwich / psDefnIn->UOMAngleInDegrees,
                     pszAngularUnits,
-                    psDefn->UOMAngleInDegrees * 0.0174532925199433 );
+                    psDefnIn->UOMAngleInDegrees * 0.0174532925199433 );
 
-    if( psDefn->GCS != KvUserDefined )
-        oSRS.SetAuthority( "GEOGCS", "EPSG", psDefn->GCS );
+    if( psDefnIn->GCS != KvUserDefined )
+        oSRS.SetAuthority( "GEOGCS", "EPSG", psDefnIn->GCS );
 
-    if( psDefn->Datum != KvUserDefined )
-        oSRS.SetAuthority( "DATUM", "EPSG", psDefn->Datum );
+    if( psDefnIn->Datum != KvUserDefined )
+        oSRS.SetAuthority( "DATUM", "EPSG", psDefnIn->Datum );
 
-    if( psDefn->Ellipsoid != KvUserDefined )
-        oSRS.SetAuthority( "SPHEROID", "EPSG", psDefn->Ellipsoid );
+    if( psDefnIn->Ellipsoid != KvUserDefined )
+        oSRS.SetAuthority( "SPHEROID", "EPSG", psDefnIn->Ellipsoid );
 
     CPLFree( pszGeogName );
     CPLFree( pszDatumName );
     CPLFree( pszPMName );
     CPLFree( pszSpheroidName );
     CPLFree( pszAngularUnits );
-        
+
 /* ==================================================================== */
 /*      Handle projection parameters.                                   */
 /* ==================================================================== */
-    if( psDefn->Model == ModelTypeProjected )
+    if( psDefnIn->Model == ModelTypeProjected )
     {
 /* -------------------------------------------------------------------- */
 /*      Make a local copy of parms, and convert back into the           */
@@ -2787,21 +2802,23 @@ char *MrSIDDataset::GetOGISDefn( GTIFDefn *psDefn )
         double          adfParm[10];
         int             i;
 
-        for( i = 0; i < MIN(10,psDefn->nParms); i++ )
-            adfParm[i] = psDefn->ProjParm[i];
+        for( i = 0; i < MIN(10,psDefnIn->nParms); i++ )
+            adfParm[i] = psDefnIn->ProjParm[i];
+        for( ; i < 10; i++)
+            adfParm[i] = 0;
+
+        adfParm[0] /= psDefnIn->UOMAngleInDegrees;
+        adfParm[1] /= psDefnIn->UOMAngleInDegrees;
+        adfParm[2] /= psDefnIn->UOMAngleInDegrees;
+        adfParm[3] /= psDefnIn->UOMAngleInDegrees;
+
+        adfParm[5] /= psDefnIn->UOMLengthInMeters;
+        adfParm[6] /= psDefnIn->UOMLengthInMeters;
 
-        adfParm[0] /= psDefn->UOMAngleInDegrees;
-        adfParm[1] /= psDefn->UOMAngleInDegrees;
-        adfParm[2] /= psDefn->UOMAngleInDegrees;
-        adfParm[3] /= psDefn->UOMAngleInDegrees;
-        
-        adfParm[5] /= psDefn->UOMLengthInMeters;
-        adfParm[6] /= psDefn->UOMLengthInMeters;
-        
 /* -------------------------------------------------------------------- */
 /*      Translation the fundamental projection.                         */
 /* -------------------------------------------------------------------- */
-        switch( psDefn->CTProjection )
+        switch( psDefnIn->CTProjection )
         {
           case CT_TransverseMercator:
             oSRS.SetTM( adfParm[0], adfParm[1],
@@ -2839,18 +2856,18 @@ char *MrSIDDataset::GetOGISDefn( GTIFDefn *psDefn )
                          adfParm[4],
                          adfParm[5], adfParm[6] );
             break;
-        
-          case CT_EquidistantConic: 
+
+          case CT_EquidistantConic:
             oSRS.SetEC( adfParm[0], adfParm[1],
                         adfParm[2], adfParm[3],
                         adfParm[5], adfParm[6] );
             break;
-        
+
           case CT_CassiniSoldner:
             oSRS.SetCS( adfParm[0], adfParm[1],
                         adfParm[5], adfParm[6] );
             break;
-        
+
           case CT_Polyconic:
             oSRS.SetPolyconic( adfParm[0], adfParm[1],
                                adfParm[5], adfParm[6] );
@@ -2860,42 +2877,42 @@ char *MrSIDDataset::GetOGISDefn( GTIFDefn *psDefn )
             oSRS.SetAE( adfParm[0], adfParm[1],
                         adfParm[5], adfParm[6] );
             break;
-        
+
           case CT_MillerCylindrical:
             oSRS.SetMC( adfParm[0], adfParm[1],
                         adfParm[5], adfParm[6] );
             break;
-        
+
           case CT_Equirectangular:
             oSRS.SetEquirectangular( adfParm[0], adfParm[1],
                                      adfParm[5], adfParm[6] );
             break;
-        
+
           case CT_Gnomonic:
             oSRS.SetGnomonic( adfParm[0], adfParm[1],
                               adfParm[5], adfParm[6] );
             break;
-        
+
           case CT_LambertAzimEqualArea:
             oSRS.SetLAEA( adfParm[0], adfParm[1],
                           adfParm[5], adfParm[6] );
             break;
-        
+
           case CT_Orthographic:
             oSRS.SetOrthographic( adfParm[0], adfParm[1],
                                   adfParm[5], adfParm[6] );
             break;
-        
+
           case CT_Robinson:
             oSRS.SetRobinson( adfParm[1],
                               adfParm[5], adfParm[6] );
             break;
-        
+
           case CT_Sinusoidal:
             oSRS.SetSinusoidal( adfParm[1],
                                 adfParm[5], adfParm[6] );
             break;
-        
+
           case CT_VanDerGrinten:
             oSRS.SetVDG( adfParm[1],
                          adfParm[5], adfParm[6] );
@@ -2906,7 +2923,7 @@ char *MrSIDDataset::GetOGISDefn( GTIFDefn *psDefn )
                         adfParm[4],
                         adfParm[5], adfParm[6] );
             break;
-        
+
           case CT_LambertConfConic_2SP:
             oSRS.SetLCC( adfParm[2], adfParm[3],
                          adfParm[0], adfParm[1],
@@ -2918,7 +2935,7 @@ char *MrSIDDataset::GetOGISDefn( GTIFDefn *psDefn )
                             adfParm[4],
                             adfParm[5], adfParm[6] );
             break;
-        
+
           case CT_AlbersEqualArea:
             oSRS.SetACEA( adfParm[0], adfParm[1],
                           adfParm[2], adfParm[3],
@@ -2935,20 +2952,20 @@ char *MrSIDDataset::GetOGISDefn( GTIFDefn *psDefn )
 /*      Set projection units.                                           */
 /* -------------------------------------------------------------------- */
         char    *pszUnitsName = NULL;
-        
-        GTIFGetUOMLengthInfo( psDefn->UOMLength, &pszUnitsName, NULL );
 
-        if( pszUnitsName != NULL && psDefn->UOMLength != KvUserDefined )
+        GTIFGetUOMLengthInfo( psDefnIn->UOMLength, &pszUnitsName, NULL );
+
+        if( pszUnitsName != NULL && psDefnIn->UOMLength != KvUserDefined )
         {
-            oSRS.SetLinearUnits( pszUnitsName, psDefn->UOMLengthInMeters );
-            oSRS.SetAuthority( "PROJCS|UNIT", "EPSG", psDefn->UOMLength );
+            oSRS.SetLinearUnits( pszUnitsName, psDefnIn->UOMLengthInMeters );
+            oSRS.SetAuthority( "PROJCS|UNIT", "EPSG", psDefnIn->UOMLength );
         }
         else
-            oSRS.SetLinearUnits( "unknown", psDefn->UOMLengthInMeters );
+            oSRS.SetLinearUnits( "unknown", psDefnIn->UOMLengthInMeters );
 
         GTIFFreeMemory( pszUnitsName );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Return the WKT serialization of the object.                     */
 /* -------------------------------------------------------------------- */
@@ -2986,7 +3003,7 @@ class MrSIDDummyImageReader : public LTIImageReader
     GDALDataType        eDataType;
     LTIDataType         eSampleType;
     const LTIPixel      *poPixel;
-    
+
     double              adfGeoTransform[6];
 
     virtual LT_STATUS   decodeStrip( LTISceneBuffer& stripBuffer,
@@ -3030,7 +3047,7 @@ LT_STATUS MrSIDDummyImageReader::initialize()
     if ( !LT_SUCCESS(eStat = LTIImageReader::initialize()) )
         return eStat;
 #endif
-    
+
     lt_uint16 nBands = (lt_uint16)poDS->GetRasterCount();
     LTIColorSpace eColorSpace = LTI_COLORSPACE_RGB;
     switch ( nBands )
@@ -3045,7 +3062,7 @@ LT_STATUS MrSIDDummyImageReader::initialize()
             eColorSpace = LTI_COLORSPACE_MULTISPECTRAL;
             break;
     }
-    
+
     eDataType = poDS->GetRasterBand(1)->GetRasterDataType();
     switch ( eDataType )
     {
@@ -3093,7 +3110,7 @@ LT_STATUS MrSIDDummyImageReader::initialize()
         LTIGeoCoord oGeo( adfGeoTransform[0] + adfGeoTransform[1] / 2,
                           adfGeoTransform[3] + adfGeoTransform[5] / 2,
                           adfGeoTransform[1], adfGeoTransform[5],
-                          adfGeoTransform[2], adfGeoTransform[4], 
+                          adfGeoTransform[2], adfGeoTransform[4],
                           poDS->GetProjectionRef() );
 #endif
         if ( !LT_SUCCESS(setGeoCoord( oGeo )) )
@@ -3146,8 +3163,8 @@ LT_STATUS MrSIDDummyImageReader::decodeStrip(LTISceneBuffer& stripData,
         return LT_STS_Failure;
     }
 
-    poDS->RasterIO( GF_Read, nXOff, nYOff, nBufXSize, nBufYSize, 
-                    pData, nBufXSize, nBufYSize, eDataType, nBands, NULL, 
+    poDS->RasterIO( GF_Read, nXOff, nYOff, nBufXSize, nBufYSize,
+                    pData, nBufXSize, nBufYSize, eDataType, nBands, NULL,
                     0, 0, 0, NULL );
 
     stripData.importDataBSQ( pData );
@@ -3171,10 +3188,10 @@ void MrSIDDataset::FlushCache()
 
 static GDALDataset *
 MrSIDCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
-                 int bStrict, char ** papszOptions, 
+                 int bStrict, char ** papszOptions,
                  GDALProgressFunc pfnProgress, void * pProgressData )
 
-{ 
+{
     const char* pszVersion = CSLFetchNameValue(papszOptions, "VERSION");
 #ifdef MRSID_HAVE_MG4WRITE
     int iVersion = pszVersion ? atoi(pszVersion) : 4;
@@ -3187,11 +3204,11 @@ MrSIDCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     bool bMeter = false;
 #else
     bool bMeter = true;
-#endif    
-    
+#endif
+
     if (poSrcDS->GetRasterBand(1)->GetColorTable() != NULL)
     {
-        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, 
+        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
                   "MrSID driver ignores color table. "
                   "The source raster band will be considered as grey level.\n"
                   "Consider using color table expansion (-expand option in gdal_translate)\n");
@@ -3208,7 +3225,7 @@ MrSIDCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         return NULL;
     }
 
-    // Create the file.                                               
+    // Create the file.
     MrSIDDummyImageReader oImageReader( poSrcDS );
     if( LT_FAILURE( eStat = oImageReader.initialize() ) )
     {
@@ -3414,23 +3431,23 @@ MrSIDCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
 static GDALDataset *
 JP2CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
-                 int bStrict, char ** papszOptions, 
+                 int bStrict, char ** papszOptions,
                  GDALProgressFunc pfnProgress, void * pProgressData )
 
-{ 
+{
 #ifdef DEBUG
     bool bMeter = false;
 #else
     bool bMeter = true;
-#endif    
+#endif
 
     int nXSize = poSrcDS->GetRasterXSize();
     int nYSize = poSrcDS->GetRasterYSize();
     LT_STATUS  eStat;
-    
+
     if (poSrcDS->GetRasterBand(1)->GetColorTable() != NULL)
     {
-        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, 
+        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
                   "MrSID driver ignores color table. "
                   "The source raster band will be considered as grey level.\n"
                   "Consider using color table expansion (-expand option in gdal_translate)\n");
@@ -3447,7 +3464,7 @@ JP2CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         return NULL;
     }
 
-    // Create the file.   
+    // Create the file.
     MrSIDDummyImageReader oImageReader( poSrcDS );
     eStat = oImageReader.initialize();
     if( eStat != LT_STS_Success )
@@ -3457,7 +3474,7 @@ JP2CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                   getLastStatusString( eStat ) );
         return NULL;
     }
-      
+
 #if !defined(MRSID_POST5)
     J2KImageWriter oImageWriter(&oImageReader);
     eStat = oImageWriter.initialize();
@@ -3482,7 +3499,7 @@ JP2CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 #endif
 
     oImageWriter.setUsageMeterEnabled(bMeter);
-      
+
     // set output filename
     oImageWriter.setOutputFileSpec( pszFilename );
 
@@ -3495,12 +3512,12 @@ JP2CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     // set MrSID world file
     if( CSLFetchNameValue(papszOptions, "WORLDFILE") != NULL )
         oImageWriter.setWorldFileSupport( true );
-      
+
     // check for compression option
     const char* pszValue = CSLFetchNameValue(papszOptions, "COMPRESSION");
     if( pszValue != NULL )
         oImageWriter.params().setCompressionRatio( (float)CPLAtof(pszValue) );
-        
+
     pszValue = CSLFetchNameValue(papszOptions, "XMLPROFILE");
     if( pszValue != NULL )
     {
@@ -3532,7 +3549,7 @@ JP2CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly);
     GDALPamDataset *poDS = (GDALPamDataset*) JP2Open(&oOpenInfo);
 
-    if( poDS )  
+    if( poDS )
         poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
 
     return poDS;
@@ -3547,29 +3564,30 @@ JP2CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 void GDALRegister_MrSID()
 
 {
-    GDALDriver  *poDriver;
-    
-    if (! GDAL_CHECK_VERSION("MrSID driver"))
+    if( !GDAL_CHECK_VERSION( "MrSID driver" ) )
         return;
 
 /* -------------------------------------------------------------------- */
 /*      MrSID driver.                                                   */
 /* -------------------------------------------------------------------- */
-    if( GDALGetDriverByName( "MrSID" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    if( GDALGetDriverByName( "MrSID" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "MrSID" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                        "Multi-resolution Seamless Image Database (MrSID)" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_mrsid.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "sid" );
+    poDriver->SetDescription( "MrSID" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Multi-resolution Seamless Image Database "
+                               "(MrSID)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_mrsid.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "sid" );
 
 #ifdef MRSID_ESDK
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte Int16 UInt16 Int32 UInt32 Float32 Float64" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte Int16 UInt16 Int32 UInt32 "
+                               "Float32 Float64" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 // Version 2 Options
 "   <Option name='COMPRESSION' type='double' description='Set compression ratio (0.0 default is meant to be lossless)'/>"
@@ -3582,55 +3600,50 @@ void GDALRegister_MrSID()
 "   <Option name='VERSION' type='int' description='Valid versions are 2 and 3, default = 3'/>"
 "</CreationOptionList>" );
 
-        poDriver->pfnCreateCopy = MrSIDCreateCopy;
+    poDriver->pfnCreateCopy = MrSIDCreateCopy;
 
 #else
-        /* In read-only mode, we support VirtualIO. I don't think this is the case */
-        /* for MrSIDCreateCopy() */
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    // In read-only mode, we support VirtualIO. I don't think this is the case
+    // for MrSIDCreateCopy().
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 #endif
-        poDriver->pfnIdentify = MrSIDIdentify;
-        poDriver->pfnOpen = MrSIDOpen;
+    poDriver->pfnIdentify = MrSIDIdentify;
+    poDriver->pfnOpen = MrSIDOpen;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 
 /* -------------------------------------------------------------------- */
 /*      JP2MRSID driver.                                                */
 /* -------------------------------------------------------------------- */
 #ifdef MRSID_J2K
-    if( GDALGetDriverByName( "JP2MrSID" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "JP2MrSID" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                        "MrSID JPEG2000" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_jp2mrsid.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jp2" );
+    poDriver->SetDescription( "JP2MrSID" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "MrSID JPEG2000" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_jp2mrsid.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jp2" );
 
 #ifdef MRSID_ESDK
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte Int16 UInt16" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte Int16 UInt16" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "   <Option name='COMPRESSION' type='double' description='Set compression ratio (0.0 default is meant to be lossless)'/>"
 "   <Option name='WORLDFILE' type='boolean' description='Write out world file'/>"
 "   <Option name='XMLPROFILE' type='string' description='Use named xml profile file'/>"
 "</CreationOptionList>" );
 
-        poDriver->pfnCreateCopy = JP2CreateCopy;
+    poDriver->pfnCreateCopy = JP2CreateCopy;
 #else
         /* In read-only mode, we support VirtualIO. I don't think this is the case */
         /* for JP2CreateCopy() */
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 #endif
-        poDriver->pfnIdentify = JP2Identify;
-        poDriver->pfnOpen = JP2Open;
+    poDriver->pfnIdentify = JP2Identify;
+    poDriver->pfnOpen = JP2Open;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 #endif /* def MRSID_J2K */
 }
 
diff --git a/frmts/mrsid/mrsidstream.cpp b/frmts/mrsid/mrsidstream.cpp
index 2915d59..b0dbedc 100644
--- a/frmts/mrsid/mrsidstream.cpp
+++ b/frmts/mrsid/mrsidstream.cpp
@@ -1,9 +1,9 @@
 /******************************************************************************
- * $Id: mrsidstream.cpp 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: mrsidstream.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  Multi-resolution Seamless Image Database (MrSID)
  * Purpose:  Input/output stream wrapper for usage with LizardTech's
- *           MrSID SDK, implemenattion of the wrapper class methods.
+ *           MrSID SDK, implementation of the wrapper class methods.
  * Author:   Andrey Kiselev, dron at ak4719.spb.edu
  *
  ******************************************************************************
@@ -29,10 +29,14 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#ifdef DEBUG_BOOL
+#define DO_NOT_USE_DEBUG_BOOL
+#endif
+
 #include "cpl_error.h"
 #include "mrsidstream.h"
 
-CPL_CVSID("$Id: mrsidstream.cpp 27044 2014-03-16 23:41:27Z rouault $");
+CPL_CVSID("$Id: mrsidstream.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 LT_USE_NAMESPACE(LizardTech)
 
@@ -42,7 +46,7 @@ LT_USE_NAMESPACE(LizardTech)
 /* ==================================================================== */
 /************************************************************************/
 
-LTIVSIStream::LTIVSIStream() : poFileHandle(NULL), nError(0), pnRefCount(NULL), 
+LTIVSIStream::LTIVSIStream() : poFileHandle(NULL), nError(0), pnRefCount(NULL),
 bIsOpen(FALSE)
 {
 }
@@ -203,7 +207,7 @@ LT_STATUS LTIVSIStream::seek( lt_int64 nOffset, LTIOSeekDir nOrigin )
         case (LTIO_SEEK_DIR_BEG):
             nWhence = SEEK_SET;
             break;
-      
+
         case (LTIO_SEEK_DIR_CUR):
         {
             nWhence =  SEEK_CUR;
@@ -214,11 +218,11 @@ LT_STATUS LTIVSIStream::seek( lt_int64 nOffset, LTIOSeekDir nOrigin )
             }
             break;
         }
-      
+
         case (LTIO_SEEK_DIR_END):
             nWhence = SEEK_END;
             break;
-      
+
         default:
             return LT_STS_Failure;
     }
@@ -276,4 +280,3 @@ const char *LTIVSIStream::getID() const
 {
     return "LTIVSIStream:";
 }
-
diff --git a/frmts/mrsid/mrsidstream.h b/frmts/mrsid/mrsidstream.h
index d9fd91b..34fac2a 100644
--- a/frmts/mrsid/mrsidstream.h
+++ b/frmts/mrsid/mrsidstream.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: mrsidstream.h 16078 2009-01-14 05:43:02Z warmerdam $
+ * $Id: mrsidstream.h 32179 2015-12-14 16:22:34Z goatbar $
  *
  * Project:  Multi-resolution Seamless Image Database (MrSID)
  * Purpose:  Input/output stream wrapper for usage with LizardTech's
@@ -47,20 +47,20 @@ class LTIVSIStream : public LTIOStreamInf
 
     bool isEOF();
     bool isOpen();
-    
+
     LT_STATUS open();
     LT_STATUS close();
-    
+
     lt_uint32 read( lt_uint8 *, lt_uint32 );
     lt_uint32 write( const lt_uint8 *, lt_uint32 );
-    
+
     LT_STATUS seek( lt_int64, LTIOSeekDir );
     lt_int64 tell();
-    
+
     LTIOStreamInf* duplicate();
-    
+
     LT_STATUS getLastError() const;
-    
+
     const char* getID() const;
 
   private:
diff --git a/frmts/mrsid_lidar/frmt_mrsid_lidar.html b/frmts/mrsid_lidar/frmt_mrsid_lidar.html
index 36ab0c7..7c6e693 100644
--- a/frmts/mrsid_lidar/frmt_mrsid_lidar.html
+++ b/frmts/mrsid_lidar/frmt_mrsid_lidar.html
@@ -66,7 +66,7 @@ the Z direction as well.</p>
 <h3>Expose as a bare earth (Max) DEM</h3>
 
 <p>Here, we expose a single band (elevation) but we want only those points that
-have been classified as "Ground".  The ClassificationFitler specifies a value
+have been classified as "Ground".  The ClassificationFilter specifies a value
 of 2 - the ASPRS Point Class code that stipulates "Ground" points.
  Additionally, instead of the default "Mean" aggregation method, we specify
 "Max". This means that if two (or more) points land on a single cell, we expose
@@ -114,7 +114,7 @@ a .view file like this to expose that data.</p>
    <Band>
       <Channel>Blue</Channel>
    </Band>
-</PointCloudView> 
+</PointCloudView>
 </pre>
 
 <h2>Writing not supported</h2>
diff --git a/frmts/mrsid_lidar/frmt_mrsid_lidar_view_point_cloud.html b/frmts/mrsid_lidar/frmt_mrsid_lidar_view_point_cloud.html
index 6bfac2c..13d6956 100644
--- a/frmts/mrsid_lidar/frmt_mrsid_lidar_view_point_cloud.html
+++ b/frmts/mrsid_lidar/frmt_mrsid_lidar_view_point_cloud.html
@@ -6,7 +6,7 @@ xmlns:st1="urn:schemas-microsoft-com:office:smarttags"
 xmlns="http://www.w3.org/TR/REC-html40">
 
 <head>
-<meta http-equiv=Content-Type content="text/html; charset=windows-1252">
+<meta http-equiv=Content-Type content="text/html; charset=utf-8">
 <meta name=ProgId content=Word.Document>
 <meta name=Generator content="Microsoft Word 12">
 <meta name=Originator content="Microsoft Word 12">
@@ -781,11 +781,11 @@ View Documents</p>
 Introduction<o:p></o:p></span></h1>
 
 <p class=MsoNormal>This document specifies the contents of an XML document used
-as a �view� into a <span class=SpellE>LiDAR</span> point cloud.<span
-style='mso-spacerun:yes'>� </span>It is intended to be a rigorous definition of
+as a “view” into a <span class=SpellE>LiDAR</span> point cloud.<span
+style='mso-spacerun:yes'>  </span>It is intended to be a rigorous definition of
 an XML-based format for specifying <span class=SpellE>rasterization</span> of
-point cloud data.<span style='mso-spacerun:yes'>� </span>If you are looking for
-�something to get me started very quickly,� please see the examples below.</p>
+point cloud data.<span style='mso-spacerun:yes'>  </span>If you are looking for
+“something to get me started very quickly,” please see the examples below.</p>
 
 <h1><span style='mso-fareast-font-family:"Times New Roman"'>2.  Document
 Structure <i>(informative)</i><o:p></o:p></span></h1>
@@ -859,27 +859,27 @@ class=GramE> ?</span></span></p>
 <p class=MsoNormal style='text-indent:.5in'><span class=SpellE><b>ElementName</b></span></p>
 
 <p class=MsoListParagraph style='margin-left:.75in;text-indent:-.25in'><span
-style='font-family:Symbol'>�</span><span style='font-size:7.0pt;line-height:
+style='font-family:Symbol'>·</span><span style='font-size:7.0pt;line-height:
 115%;font-family:"Times New Roman","serif"'>       
 </span><b>Cardinality: </b> number of occurrences allowed</p>
 
 <p class=MsoListParagraph style='margin-left:.75in;text-indent:-.25in'><span
-style='font-family:Symbol'>�</span><span style='font-size:7.0pt;line-height:
+style='font-family:Symbol'>·</span><span style='font-size:7.0pt;line-height:
 115%;font-family:"Times New Roman","serif"'>       
 </span><b>Parents:  </b>what element(s) may contain this element</p>
 
 <p class=MsoListParagraph style='margin-left:.75in;text-indent:-.25in'><span
-style='font-family:Symbol'>�</span><span style='font-size:7.0pt;line-height:
+style='font-family:Symbol'>·</span><span style='font-size:7.0pt;line-height:
 115%;font-family:"Times New Roman","serif"'>       
 </span><b>Contents:</b> what may be placed inside the element</p>
 
 <p class=MsoListParagraph style='margin-left:.75in;text-indent:-.25in'><span
-style='font-family:Symbol'>�</span><span style='font-size:7.0pt;line-height:
+style='font-family:Symbol'>·</span><span style='font-size:7.0pt;line-height:
 115%;font-family:"Times New Roman","serif"'>       
 </span><b>Attributes:  </b>what attributes are allowed, if any</p>
 
 <p class=MsoListParagraph style='margin-left:.75in;text-indent:-.25in'><span
-style='font-family:Symbol'>�</span><span style='font-size:7.0pt;line-height:
+style='font-family:Symbol'>·</span><span style='font-size:7.0pt;line-height:
 115%;font-family:"Times New Roman","serif"'>       
 </span><b>Notes:  </b>additional usage information or restriction</p>
 
@@ -895,51 +895,51 @@ class=GramE>  <span class=SpellE>PointClouldView</span></span><o:p></o:p></
 <p class=MsoNormal><b>Contents:  </b>child elements as specified below:</p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=SpellE><span style='font-family:"Courier New"'>InputFile</span></span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=SpellE><span style='font-family:"Courier New"'>Datatype</span></span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span style='font-family:"Courier New"'>Band</span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=SpellE><span style='font-family:"Courier New"'>ClassificationFilter</span></span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=SpellE><span style='font-family:"Courier New"'>ReturnNumberFilter</span></span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=SpellE><span style='font-family:"Courier New"'>AggregationMethod</span></span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=SpellE><span style='font-family:"Courier New"'>InterpolationMethod</span></span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=SpellE><span style='font-family:"Courier New"'>ClipBox</span></span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=SpellE><span style='font-family:"Courier New"'>CellSize</span></span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=SpellE><span style='font-family:"Courier New"'>GeoReference</span></span></p>
 
 <p class=MsoNormal><b>Attributes:</b></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=GramE><span style='font-family:"Courier New"'>version</span></span>
-� this attribute must be present and set to the value <span style='font-family:
+– this attribute must be present and set to the value <span style='font-family:
 "Courier New"'>1.0</span></p>
 
 <p class=MsoNormal><b>Notes</b>:  <i>(none)</i></p>
@@ -962,13 +962,13 @@ style='font-family:"Courier New"'>PointClouldView</span></span></p>
 <p class=MsoNormal><b>Notes:</b></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=GramE>Typically</span> the file will be a <span
 class=SpellE>MrSID</span>/MG4 <span class=SpellE>LiDAR</span> file, but may
 also be a LAS file.</p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=GramE>The</span> file name given may have a relative or
 absolute path.  If relative, the path is to be expanded relative to the
 directory containing this View document.</p>
@@ -992,12 +992,12 @@ class=SpellE>datatype</span> name)</p>
 <p class=MsoNormal><b>Notes:</b></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span>If this element is not present, the native <span class=SpellE>datatype</span>
 of the channel is used.</p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span>Legal values are derived from those returned by <span class=SpellE><span
 style='font-family:"Courier New"'>GDALGetDataTypeByName</span></span>, as
 follows:</p>
@@ -1038,7 +1038,7 @@ style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>&
 </span><span style='font-family:"Courier New"'>Float64</span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span>Channel data will be coerced via a c-style cast, truncating data as
 necessary.</p>
 
@@ -1057,26 +1057,26 @@ style='font-family:"Courier New"'>PointClouldView</span></span></p>
 <p class=MsoNormal><b>Contents:  </b>child elements as follows:</p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span>0 or 1 <span style='font-family:"Courier New"'>Channel</span> element</p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span>0 or 1 <span class=SpellE><span style='font-family:"Courier New"'>ClassificationFilter</span></span>
 element</p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span>0 or 1 <span class=SpellE><span style='font-family:"Courier New"'>ReturnNumberFilter</span></span>
 element</p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span>0 or 1 <span class=SpellE><span style='font-family:"Courier New"'>InterpolationMethod</span></span>
 element</p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span>0 or 1 <span class=SpellE><span style='font-family:"Courier New"'>AggregationMethod</span></span>
 element</p>
 
@@ -1085,7 +1085,7 @@ element</p>
 <p class=MsoNormal><b>Notes:</b></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=GramE>Not</span> specifying any bands is the same as
 specifying only one with all default values.</p>
 
@@ -1104,67 +1104,67 @@ input file</p>
 of channels</p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span style='font-family:"Courier New"'>X</span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span style='font-family:"Courier New"'>Y</span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span style='font-family:"Courier New"'>Z</span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span style='font-family:"Courier New"'>Intensity</span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=SpellE><span style='font-family:"Courier New"'>ReturnNum</span></span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=SpellE><span style='font-family:"Courier New"'>NumReturns</span></span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=SpellE><span style='font-family:"Courier New"'>ScanDir</span></span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=SpellE><span style='font-family:"Courier New"'>EdgeFlightLine</span></span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=SpellE><span style='font-family:"Courier New"'>ClassId</span></span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=SpellE><span style='font-family:"Courier New"'>ScanAngle</span></span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=SpellE><span style='font-family:"Courier New"'>UserData</span></span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=SpellE><span style='font-family:"Courier New"'>SourceId</span></span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=SpellE><span style='font-family:"Courier New"'>GPSTime</span></span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span style='font-family:"Courier New"'>Red</span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span style='font-family:"Courier New"'>Green</span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span style='font-family:"Courier New"'>Blue</span></p>
 
 <p class=MsoNormal><b>Attributes:  </b><i>(none)</i></p>
@@ -1172,19 +1172,19 @@ Symbol'>
 <p class=MsoNormal><b>Notes</b></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span>Custom channels have non-canonical names, are supported, and may be
 specified.</p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=GramE>If</span> this element is omitted, the <span
 style='font-family:"Courier New"'>Channel</span> for the <span
 style='font-family:"Courier New"'>Band</span> shall default to <span
 style='font-family:"Courier New"'>Z</span>.</p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=GramE>The</span> channel names are derived from <span
 class=SpellE><span style='font-family:"Courier New"'>PointData.h</span></span>
 of the MG4 Decode SDK.</p>
@@ -1202,7 +1202,7 @@ classification code is one of the specified values.</p>
 or<span style='font-family:"Courier New"'> <span class=SpellE>PointCloudView</span></span></p>
 
 <p class=MsoNormal><b>Contents:  </b><span style='mso-bidi-font-weight:
-bold'>s</span>pace-separated �Classification Values� (0-31) as defined by ASPRS
+bold'>s</span>pace-separated “Classification Values” (0-31) as defined by ASPRS
 Standard <span class=SpellE>LIDAR</span> Point Classes in the LAS 1.3
 Specification. </p>
 
@@ -1211,24 +1211,24 @@ Specification. </p>
 <p class=MsoNormal><b>Notes:</b></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=GramE>If</span> this element is omitted, the band shall have
 no classification filter applied.</p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=GramE>If</span> this element is a child of the <span
 class=SpellE><span style='font-family:"Courier New"'>PointCloudView</span></span>
 element, it applies to all bands (unless overridden for a specific band)</p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span>If this element is a child of a <span style='font-family:"Courier New"'>Band</span>
 elemen<a name="_GoBack"></a>t, it applies to this band only and overrides any
 other setting</p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span>Note that numbers are used to represent the filters, rather than
 strings.  This is because there is no canonical, simple naming convention
 for them, and is also in keeping with existing practice in certain existing
@@ -1247,26 +1247,26 @@ number is one of the specified values.</p>
 or <span class=SpellE><span style='font-family:"Courier New"'>PointCloudView</span></span></p>
 
 <p class=MsoNormal><b>Contents:</b><span style='mso-bidi-font-weight:bold'><span
-style='mso-spacerun:yes'>� </span>space-separated </span>numbers (1, <span
-class=GramE>2, �)</span> or the string <span style='font-family:"Courier New"'>LAST</span></p>
+style='mso-spacerun:yes'>  </span>space-separated </span>numbers (1, <span
+class=GramE>2, …)</span> or the string <span style='font-family:"Courier New"'>LAST</span></p>
 
 <p class=MsoNormal><b>Attributes:  </b><i>(none)</i></p>
 
 <p class=MsoNormal><b>Notes:</b></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=GramE>If</span> this element is omitted, the band shall have
 no return number filter applied</p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=GramE>If</span> this element is a child of the <span
 class=SpellE><span style='font-family:"Courier New"'>PointCloudView</span></span>
 element, it applies to all bands (unless overridden for a specific band)</p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span>If this element is a child of a <span style='font-family:"Courier New"'>Band</span>
 element, it applies to this band only and overrides any other setting</p>
 
@@ -1292,18 +1292,18 @@ or <span style='font-family:"Courier New"'>Mean</span></p>
 <p class=MsoNormal><b>Notes:</b></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=GramE>If</span> this element is omitted, the band shall have
-the �Mean� aggregation method applied</p>
+the “Mean” aggregation method applied</p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=GramE>If</span> this element is a child of the <span
 class=SpellE><span style='font-family:"Courier New"'>PointCloudView</span></span>
 element, it applies to all bands (unless overridden for a specific band)</p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span>If this element is a child of a <span style='font-family:"Courier New"'>Band</span>
 element, it applies to this band only and overrides any other setting</p>
 
@@ -1322,31 +1322,31 @@ or <span class=SpellE><span style='font-family:"Courier New"'>PointCloudView</sp
 elements:</p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span style='font-family:"Courier New"'>None</span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=SpellE><span style='font-family:"Courier New"'>InverseDistanceToAPower</span></span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=SpellE><span style='font-family:"Courier New"'>MovingAverage</span></span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=SpellE><span style='font-family:"Courier New"'>NearestNeighbor</span></span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span style='font-family:"Courier New"'>Minimum</span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span style='font-family:"Courier New"'>Maximum</span></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span style='font-family:"Courier New"'>Range</span></p>
 
 <p class=MsoNormal><b>Attributes:  </b><i>(none)</i></p>
@@ -1354,7 +1354,7 @@ Symbol'>
 <p class=MsoNormal><b>Notes</b></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=GramE>Each</span> of the interpolation methods (<span
 class=SpellE><span style='font-family:"Courier New"'>MovingAverage</span></span>,
 etc.) is an element whose content is a text string corresponding to the
@@ -1363,7 +1363,7 @@ href="http://www.gdal.org/grid_tutorial.html">http://www.gdal.org/grid_tutorial.
 for a description of the methods and their parameter strings.</p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=GramE>In</span> the parameter descriptions, <span
 style='font-family:"Courier New"'>MAX</span> is used to indicate the value
 defined by <span class=SpellE>libc</span> which is the largest supportable
@@ -1372,18 +1372,18 @@ override this default be sure that the number you specify will fit in the <span
 class=SpellE>datatype</span> you specify.</p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=GramE>If</span> this element is omitted, the band shall have
-the �None� interpolation method applied.</p>
+the “None” interpolation method applied.</p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=GramE>If</span> this element is a child of the <span
 class=SpellE><span style='font-family:"Courier New"'>PointCloudView</span></span>
 element, it applies to all bands (unless overridden for a specific band)</p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span>If this element is a child of a <span style='font-family:"Courier New"'>Band</span>
 element, it applies to this band only and overrides any other setting</p>
 
@@ -1407,25 +1407,25 @@ a double value</p>
 <p class=MsoNormal><b>Notes:</b></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=GramE>The</span> full 6 values are (in order): <span
 class=SpellE>xmin</span>, <span class=SpellE>xmax</span>, <span class=SpellE>ymin</span>,
 <span class=SpellE>ymax</span>, <span class=SpellE>zmin</span>, <span
 class=SpellE>zmax</span>.</p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=GramE>The</span> string <span style='font-family:"Courier New"'>NOFILTER</span>
 means to use the corresponding value of the Minimum Bounding Rectangle (MBR) of
 the input files.  The point is not filtered by that value. </p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span>If only 4 double are present, the <span class=SpellE>zmin</span> and <span
 class=SpellE>zmax</span> are assumed to be <span style='font-family:"Courier New"'>NOFILTER</span>.</p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=GramE>If</span> this element is not present, the clip box is
 assumed to be the MBR of the input files.</p>
 
@@ -1447,12 +1447,12 @@ style='font-family:"Courier New"'>PointClouldView</span></span></p>
 <p class=MsoNormal><b>Notes:</b></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=GramE>This</span> element is used to determine the size of
 the resulting raster.</p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=GramE>If</span> this element is omitted, the default cell
 size is the average (linear) point spacing (assuming a uniform distribution
 over the entire extent).</p>
@@ -1475,13 +1475,13 @@ style='font-family:"Courier New"'>PointClouldView</span></span></p>
 <p class=MsoNormal><b>Notes:</b></p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span>If this element is omitted, the WKT of the input files is used.  If
 two or more files have different WKTs, then no <span class=SpellE>GeoReference</span>
 is defined.</p>
 
 <p class=MsoListParagraph style='text-indent:-.25in'><span style='font-family:
-Symbol'>�</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
+Symbol'>·</span><span style='font-size:7.0pt;line-height:115%;font-family:"Times New Roman","serif"'>       
 </span><span class=GramE>A</span> typical use of this element is for when the
 MG4 file was created without adequate <span class=SpellE>GeoReference</span>
 information: cases where some combination of UOM, <span class=SpellE>HorizCS</span>
@@ -1503,17 +1503,17 @@ the child elements within a given parent.</p>
 class=GramE>  Simplest</span> possible .view file<o:p></o:p></span></h3>
 
 <p class=MsoNormal>The simplest way to view an MG4 file is to wrap it in a
-View (.view) file like this.<span style='mso-spacerun:yes'>� </span>Here, the relative
+View (.view) file like this.<span style='mso-spacerun:yes'>  </span>Here, the relative
 reference to the MG4 file means that the file must exist in the same directory
-as the .view file.<span style='mso-spacerun:yes'>� </span>Since we�re not
+as the .view file.<span style='mso-spacerun:yes'>  </span>Since we’re not
 mapping any bands explicitly, we get the default, which is elevation only.<span
-style='mso-spacerun:yes'>� </span>By default, we aggregate based on mean.<span
-style='mso-spacerun:yes'>� </span>That is, if two (or more) points land on a
+style='mso-spacerun:yes'>  </span>By default, we aggregate based on mean.<span
+style='mso-spacerun:yes'>  </span>That is, if two (or more) points land on a
 single cell, we will expose the average of the two.<span
-style='mso-spacerun:yes'>� </span>There�s no filtering here so we�ll get all
+style='mso-spacerun:yes'>  </span>There’s no filtering here so we’ll get all
 the points regardless of classification code or return number.<span
-style='mso-spacerun:yes'>� </span>Since the native <span class=SpellE>datatype</span>
-of elevation is �Float64�, that is the <span class=SpellE>datatype</span> of the
+style='mso-spacerun:yes'>  </span>Since the native <span class=SpellE>datatype</span>
+of elevation is “Float64”, that is the <span class=SpellE>datatype</span> of the
 band we will expose.</p>
 
 <p class=MsoNoSpacing style='margin-left:.5in'><span style='font-family:"Courier New"'><<span
@@ -1531,9 +1531,9 @@ class=SpellE>PointCloudView</span>></span></p>
 
 <p class=MsoNormal>This is similar to the example above but we are using the optional
 <span class=SpellE>ClipBox</span> tag to select a 300 meter North-South swatch
-through the cloud.<span style='mso-spacerun:yes'>� </span>If we wanted to crop
+through the cloud.<span style='mso-spacerun:yes'>  </span>If we wanted to crop
 in the East-West directions, we could have specified that explicitly instead of
-using NOFITLER for those.<span style='mso-spacerun:yes'>� </span>Similarly, we
+using NOFITLER for those.<span style='mso-spacerun:yes'>  </span>Similarly, we
 could also have cropped in the Z direction as well.</p>
 
 <p class=MsoNoSpacing style='margin-left:.5in'><span style='font-family:"Courier New"'><<span
@@ -1555,12 +1555,12 @@ class=SpellE>PointCloudView</span>></span></p>
 class=GramE>  Expose</span> as a bare earth (Max) DEM<o:p></o:p></span></h3>
 
 <p class=MsoNormal>Here, we expose a single band (elevation) but we want only <span
-class=GramE>those points</span> that have been classified as �Ground.�<span
-style='mso-spacerun:yes'>� </span>The <span class=SpellE>ClassificationFitler</span>
-specifies a value of 2 � the ASPRS Point Class code that stipulates �Ground�
-points.<span style='mso-spacerun:yes'>� </span>Additionally, instead of the
-default �Mean� aggregation method, we specify �Max.�<span
-style='mso-spacerun:yes'>� </span>This means that if two (or more) points land
+class=GramE>those points</span> that have been classified as “Ground.”<span
+style='mso-spacerun:yes'>  </span>The <span class=SpellE>ClassificationFilter</span>
+specifies a value of 2 – the ASPRS Point Class code that stipulates “Ground”
+points.<span style='mso-spacerun:yes'>  </span>Additionally, instead of the
+default “Mean” aggregation method, we specify “Max.”<span
+style='mso-spacerun:yes'>  </span>This means that if two (or more) points land
 on a single cell, we expose the larger of the two elevation values.</p>
 
 <p class=MsoNoSpacing style='margin-left:.5in'><span style='font-family:"Courier New"'><<span
@@ -1623,7 +1623,7 @@ style='mso-fareast-font-family:"MS Mincho"'>RGB</span></span><span
 style='mso-fareast-font-family:"MS Mincho"'> image<o:p></o:p></span></h3>
 
 <p class=MsoNormal><span style='mso-fareast-font-family:"MS Mincho"'>Some point
-cloud images include RGB data.<span style='mso-spacerun:yes'>� </span>If that�s
+cloud images include RGB data.<span style='mso-spacerun:yes'>  </span>If that’s
 the case, you can use a .view file like this to expose that data.</span></p>
 
 <p class=MsoNoSpacing style='margin-left:.5in'><span style='font-family:"Courier New"'><<span
diff --git a/frmts/mrsid_lidar/gdal_MG4Lidar.cpp b/frmts/mrsid_lidar/gdal_MG4Lidar.cpp
index 6b3f5db..a9bb3db 100644
--- a/frmts/mrsid_lidar/gdal_MG4Lidar.cpp
+++ b/frmts/mrsid_lidar/gdal_MG4Lidar.cpp
@@ -8,47 +8,46 @@
 * Copyright (c) 2010, LizardTech
 * All rights reserved.
 
-* Redistribution and use in source and binary forms, with or without 
+* Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
-*   Redistributions of source code must retain the above copyright notice, 
+*   Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
-* 
-*   Redistributions in binary form must reproduce the above copyright notice, 
+*
+*   Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
-*   Neither the name of the LizardTech nor the names of its contributors may 
-*   be used to endorse or promote products derived from this software without 
+*   Neither the name of the LizardTech nor the names of its contributors may
+*   be used to endorse or promote products derived from this software without
 *   specific prior written permission.
 *
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
-* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
-* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
-* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
-* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
-* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
-* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/
-#include "lidar/MG4PointReader.h"
-#include "lidar/FileIO.h"
-#include "lidar/Error.h"
-#include "lidar/Version.h"
+
+#ifdef DEBUG_BOOL
+#define DO_NOT_USE_DEBUG_BOOL
+#endif
+
+#include "mg4lidar_headers.h"
+
 #include <float.h>
 LT_USE_LIDAR_NAMESPACE
 
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 // #include "gdal_alg.h" // 1.6 and later have gridding algorithms
 
-CPL_C_START
-//void __declspec(dllexport) GDALRegister_MG4Lidar(void);
-void CPL_DLL GDALRegister_MG4Lidar(void);
-CPL_C_END
-
 /************************************************************************/
 /* ==================================================================== */
 /*				MG4LidarDataset				*/
@@ -69,8 +68,8 @@ class CropableMG4PointReader : public MG4PointReader
          setBounds(*bounds);
    }
 };
-CropableMG4PointReader::CropableMG4PointReader() : MG4PointReader() {};   
-CropableMG4PointReader::~CropableMG4PointReader() {};   
+CropableMG4PointReader::CropableMG4PointReader() : MG4PointReader() {};
+CropableMG4PointReader::~CropableMG4PointReader() {};
 
 IMPLEMENT_OBJECT_CREATE(CropableMG4PointReader);
 
@@ -79,12 +78,14 @@ static double MaxBlockSideSize = 1024.0;
 class MG4LidarDataset : public GDALPamDataset
 {
 friend class MG4LidarRasterBand;
+
 public:
    MG4LidarDataset();
    ~MG4LidarDataset();
    static GDALDataset *Open( GDALOpenInfo * );
    CPLErr 	GetGeoTransform( double * padfTransform );
    const char *GetProjectionRef();
+
 protected:
    MG4PointReader *reader;
    FileIO *fileIO;
@@ -94,7 +95,8 @@ protected:
    MG4LidarDataset **papoOverviewDS;
    CPLXMLNode *poXMLPCView;
    bool ownsXML;
-   int nBlockXSize, nBlockYSize;
+   int nBlockXSize;
+   int nBlockYSize;
    int iLevel;
 };
 
@@ -120,7 +122,7 @@ public:
    protected:
    double getMaxValue();
    double nodatavalue;
-   virtual const bool ElementPassesFilter(const PointData &, size_t);
+   virtual bool ElementPassesFilter(const PointData &, size_t);
    template<typename DTYPE>
    CPLErr   doReadBlock(int, int, void *);
    CPLXMLNode *poxmlBand;
@@ -160,7 +162,7 @@ default:
    CPLError(CE_Failure, CPLE_AssertionFailed,
       "Invalid datatype in MG4 file");
    break;
-#undef DO_CASE      
+#undef DO_CASE
    }
    // Coerce datatypes as required.
    const char * ForceDataType =  CPLGetXMLValue(pods->poXMLPCView, "Datatype", NULL);
@@ -190,7 +192,6 @@ default:
    else
       papszFilterReturnNums = CSLTokenizeString(poxmlFilter->psChild->pszValue);
 
-   
    CPLXMLNode * poxmlAggregation = CPLGetXMLNode(poxmlBand, "AggregationMethod");
    if( poxmlAggregation == NULL )
       poxmlAggregation = CPLGetXMLNode(pods->poXMLPCView, "AggregationMethod");
@@ -308,7 +309,7 @@ const DTYPE GetChannelElement(const ChannelData &channel, size_t idx)
 }
 
 
-const bool MG4LidarRasterBand::ElementPassesFilter(const PointData &pointdata, size_t i)
+bool MG4LidarRasterBand::ElementPassesFilter(const PointData &pointdata, size_t i)
 {
    bool bClassificationOK = true;
    bool bReturnNumOK = true;
@@ -316,7 +317,7 @@ const bool MG4LidarRasterBand::ElementPassesFilter(const PointData &pointdata, s
    // Check if classification code is ok:  it was requested and it does match one of the requested codes
    const int classcode = GetChannelElement<int>(*pointdata.getChannel(CHANNEL_NAME_ClassId), i);
    char bufCode[16];
-   sprintf(bufCode, "%d", classcode);
+   snprintf(bufCode, sizeof(bufCode), "%d", classcode);
    bClassificationOK = (papszFilterClassCodes == NULL ? true :
       (CSLFindString(papszFilterClassCodes,bufCode)!=-1));
 
@@ -324,7 +325,7 @@ const bool MG4LidarRasterBand::ElementPassesFilter(const PointData &pointdata, s
    {
       // Check if return num is ok:  it was requested and it does match one of the requested return numbers
       const long returnnum= static_cast<const unsigned char *>(pointdata.getChannel(CHANNEL_NAME_ReturnNum)->getData())[i];
-      sprintf(bufCode, "%d", (int)returnnum);
+      snprintf(bufCode, sizeof(bufCode), "%d", (int)returnnum);
       bReturnNumOK = (papszFilterReturnNums == NULL ? true :
          (CSLFindString(papszFilterReturnNums, bufCode)!=-1));
       if (!bReturnNumOK && CSLFindString(papszFilterReturnNums, "Last")!=-1)
@@ -365,7 +366,7 @@ CPLErr   MG4LidarRasterBand::doReadBlock(int nBlockXOff, int nBlockYOff, void *
    }
 
    double geoTrans[6];
-   poGDS->GetGeoTransform(geoTrans);   
+   poGDS->GetGeoTransform(geoTrans);
    double xres = geoTrans[1];
    double yres = geoTrans[5];
 
@@ -374,7 +375,7 @@ CPLErr   MG4LidarRasterBand::doReadBlock(int nBlockXOff, int nBlockYOff, void *
    double xmax = xmin + nBlockXSize* xres;
    double ymax = reader->getBounds().y.max - (nBlockYOff * nBlockYSize* -yres);
    double ymin = ymax - nBlockYSize* -yres;
-   Bounds bounds(xmin, xmax,  ymin, ymax, -HUGE_VAL, +HUGE_VAL); 
+   Bounds bounds(xmin, xmax,  ymin, ymax, -HUGE_VAL, +HUGE_VAL);
    PointData pointdata;
    pointdata.init(reader->getPointInfo(), 4096);
    double fraction = 1.0/pow(RESOLUTION_RATIO, poGDS->iLevel);
@@ -399,13 +400,13 @@ CPLErr   MG4LidarRasterBand::doReadBlock(int nBlockXOff, int nBlockYOff, void *
          col = floor (col);
          row = floor (row);
 
-         if (row < 0) 
+         if (row < 0)
             row = 0;
-         else if (row >= nBlockYSize) 
+         else if (row >= nBlockYSize)
             row = nBlockYSize - 1;
-         if (col < 0) 
+         if (col < 0)
             col = 0;
-         else if (col >= nBlockXSize ) 
+         else if (col >= nBlockXSize )
             col = nBlockXSize - 1;
 
          int iCol = (int) (col);
@@ -425,7 +426,7 @@ CPLErr   MG4LidarRasterBand::doReadBlock(int nBlockXOff, int nBlockYOff, void *
                static_cast<DTYPE *>(pImage)[offset] > value)
                static_cast<DTYPE *>(pImage)[offset] = value;
          }
-         else if (EQUAL(Aggregation, "Mean"))
+         else if (EQUAL(Aggregation, "Mean") && Accumulator != NULL)
          {
             DTYPE value = GetChannelElement<DTYPE>(*channel, i);
             Accumulator[offset].count++;
@@ -434,7 +435,7 @@ CPLErr   MG4LidarRasterBand::doReadBlock(int nBlockXOff, int nBlockYOff, void *
          }
       }
    }
-   
+
    delete[] Accumulator;
    return CE_None;
 }
@@ -497,16 +498,16 @@ CPLErr MG4LidarRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /************************************************************************/
 
 CPLErr MG4LidarRasterBand::GetStatistics( int bApproxOK, int bForce,
-                                         double *pdfMin, double *pdfMax, 
+                                         double *pdfMin, double *pdfMax,
                                          double *pdfMean, double *pdfStdDev )
 
 {
-   bApproxOK = TRUE; 
+   bApproxOK = TRUE;
    bForce = TRUE;
 
-   return GDALPamRasterBand::GetStatistics( bApproxOK, bForce, 
-      pdfMin, pdfMax, 
-      pdfMean, pdfStdDev );   
+   return GDALPamRasterBand::GetStatistics( bApproxOK, bForce,
+      pdfMin, pdfMax,
+      pdfMean, pdfStdDev );
 
 }
 /************************************************************************/
@@ -520,11 +521,14 @@ double MG4LidarRasterBand::GetNoDataValue( int *pbSuccess )
    return nodatavalue;
 }
 
-
 /************************************************************************/
 /*                            MG4LidarDataset()                             */
 /************************************************************************/
-MG4LidarDataset::MG4LidarDataset()
+
+MG4LidarDataset::MG4LidarDataset() :
+    nBlockXSize(0),
+    nBlockYSize(0),
+    iLevel(0)
 {
    reader = NULL;
    fileIO = NULL;
@@ -533,8 +537,8 @@ MG4LidarDataset::MG4LidarDataset()
    ownsXML = false;
    nOverviewCount = 0;
    papoOverviewDS = NULL;
-
 }
+
 /************************************************************************/
 /*                            ~MG4LidarDataset()                             */
 /************************************************************************/
@@ -564,7 +568,7 @@ CPLErr MG4LidarDataset::GetGeoTransform( double * padfTransform )
 
 {
    padfTransform[0] = reader->getBounds().x.min ;// Upper left X, Y
-   padfTransform[3] = reader->getBounds().y.max; // 
+   padfTransform[3] = reader->getBounds().y.max; //
    padfTransform[1] = reader->getBounds().x.length()/GetRasterXSize(); //xRes
    padfTransform[2] = 0.0;
 
@@ -583,7 +587,7 @@ const char *MG4LidarDataset::GetProjectionRef()
 {
    const char * wkt = CPLGetXMLValue(poXMLPCView, "GeoReference", NULL);
    if (wkt == NULL)
-      wkt = reader->getWKT(); 
+      wkt = reader->getWKT();
    return(wkt);
 }
 
@@ -612,7 +616,7 @@ CPLErr MG4LidarDataset::OpenZoomLevel( int iZoom )
    nRasterYSize  = static_cast<int>(gHeight / yRes + 0.5);
 
    nBlockXSize = static_cast<int>(MIN(MaxBlockSideSize , GetRasterXSize()));
-   nBlockYSize = static_cast<int>(MIN(MaxBlockSideSize , GetRasterYSize())); 
+   nBlockYSize = static_cast<int>(MIN(MaxBlockSideSize , GetRasterYSize()));
 
    CPLDebug( "MG4Lidar", "Opened zoom level %d with size %dx%d.\n",
       iZoom, nRasterXSize, nRasterYSize );
@@ -626,7 +630,7 @@ CPLErr MG4LidarDataset::OpenZoomLevel( int iZoom )
    /* -------------------------------------------------------------------- */
    /*      Create band information objects.                                */
    /* -------------------------------------------------------------------- */
-   size_t BandCount = 0;
+   int BandCount = 0;
    CPLXMLNode* xmlBand = poXMLPCView;
    bool bClass = false;
    bool bNumRets = false;
@@ -637,7 +641,7 @@ CPLErr MG4LidarDataset::OpenZoomLevel( int iZoom )
       const char * name = "Z";
       if (xmlChannel && xmlChannel->psChild && xmlChannel->psChild->pszValue)
          name = xmlChannel->psChild->pszValue;
-      
+
       BandCount++;
       MG4LidarRasterBand *band = new MG4LidarRasterBand(this, BandCount, xmlBand, name);
       SetBand(BandCount, band);
@@ -659,7 +663,7 @@ CPLErr MG4LidarDataset::OpenZoomLevel( int iZoom )
    const ChannelInfo *ci = NULL;
    for (int i=0; i<nBands; i++)
    {
-      ci = reader->getChannel(dynamic_cast<MG4LidarRasterBand*>(papoBands[i])->ChannelName);
+      ci = reader->getChannel(static_cast<MG4LidarRasterBand*>(papoBands[i])->ChannelName);
       requiredChannels.getChannel(i).init(*ci);
    }
    int iSDKChannels = nBands;
@@ -701,7 +705,7 @@ GDALDataset *MG4LidarDataset::Open( GDALOpenInfo * poOpenInfo )
    CPLXMLNode *pxmlPCView;
 
    // do something sensible for .sid files without a .view
-   if( EQUALN((const char *) poOpenInfo->pabyHeader, "msid", 4) )
+   if( STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "msid") )
    {
       int gen;
       bool raster;
@@ -719,7 +723,7 @@ GDALDataset *MG4LidarDataset::Open( GDALOpenInfo * poOpenInfo )
    else
    {
       // support .view xml
-      if( !EQUALN((const char *) poOpenInfo->pabyHeader, "<PointCloudView", 15 ) )
+      if( !STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "<PointCloudView") )
          return NULL;
 
       pxmlPCView = CPLParseXMLFile( poOpenInfo->pszFilename );
@@ -730,7 +734,7 @@ GDALDataset *MG4LidarDataset::Open( GDALOpenInfo * poOpenInfo )
    CPLXMLNode *psInputFile = CPLGetXMLNode( pxmlPCView, "InputFile" );
    if( psInputFile == NULL )
    {
-      CPLError( CE_Failure, CPLE_OpenFailed, 
+      CPLError( CE_Failure, CPLE_OpenFailed,
          "Failed to find <InputFile> in document." );
       CPLDestroyXMLNode(pxmlPCView);
       return NULL;
@@ -755,7 +759,7 @@ GDALDataset *MG4LidarDataset::Open( GDALOpenInfo * poOpenInfo )
 
    /* check magic */
    // to do:  SDK should provide an API for this.
-   if(  !EQUALN((const char *) openinfo.pabyHeader, "msid", 4)
+   if(  !STARTS_WITH_CI((const char *) openinfo.pabyHeader, "msid")
       || (*(openinfo.pabyHeader+4) != 0x4 )) // Generation 4.  ... is there more we can check?
    {
       CPLDestroyXMLNode(pxmlPCView);
@@ -778,7 +782,8 @@ GDALDataset *MG4LidarDataset::Open( GDALOpenInfo * poOpenInfo )
    FileIO* io = FileIO::create();
 
 #if (defined(WIN32) && _MSC_VER >= 1310) || __MSVCRT_VERSION__ >= 0x0601
-   bool bIsUTF8 = CSLTestBoolean( CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) );
+   bool bIsUTF8 =
+       CPLTestBool( CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) );
    wchar_t *pwszFilename = NULL;
    if (bIsUTF8)
    {
@@ -804,14 +809,14 @@ GDALDataset *MG4LidarDataset::Open( GDALOpenInfo * poOpenInfo )
       int cslcount = CSLCount(papszClipExtent);
       if (cslcount != 4 && cslcount != 6)
       {
-         CPLError( CE_Failure, CPLE_OpenFailed, 
+         CPLError( CE_Failure, CPLE_OpenFailed,
             "Invalid ClipBox.  Must contain 4 or 6 floats." );
          CSLDestroy(papszClipExtent);
          delete poDS;
          RELEASE(r);
          RELEASE(io);
 #if (defined(WIN32) && _MSC_VER >= 1310) || __MSVCRT_VERSION__ >= 0x0601
-         if ( pwszFilename ) 
+         if ( pwszFilename )
             CPLFree( pwszFilename );
 #endif
          return NULL;
@@ -847,7 +852,7 @@ GDALDataset *MG4LidarDataset::Open( GDALOpenInfo * poOpenInfo )
 #endif
    dynamic_cast<CropableMG4PointReader *>(poDS->reader)->init(poDS->fileIO, &bounds);
    poDS->SetDescription(poOpenInfo->pszFilename);
-   poDS->TryLoadXML(); 
+   poDS->TryLoadXML();
 
    double pts_per_area = ((double)r->getNumPoints())/(r->getBounds().x.length()*r->getBounds().y.length());
    double average_pt_spacing = sqrt(1.0 / pts_per_area) ;
@@ -860,8 +865,8 @@ GDALDataset *MG4LidarDataset::Open( GDALOpenInfo * poOpenInfo )
    RELEASE(r);
    RELEASE(io);
 
-   // Calculate the number of levels to expose.  The highest level correpsonds to a
-   // raster size of 256 on the longest side.
+   // Calculate the number of levels to expose.  The highest level corresponds
+   // to a raster size of 256 on the longest side.
    double blocksizefactor = MaxRasterSize/256.0;
    poDS->nOverviewCount = MAX(0, (int)(log(blocksizefactor)/log(RESOLUTION_RATIO) + 0.5));
    if ( poDS->nOverviewCount > 0 )
@@ -878,7 +883,7 @@ GDALDataset *MG4LidarDataset::Open( GDALOpenInfo * poOpenInfo )
          poDS->papoOverviewDS[i]->SetMetadata(poDS->GetMetadata("MG4Lidar"), "MG4Lidar");
          poDS->papoOverviewDS[i]->poXMLPCView = pxmlPCView;
          poDS->papoOverviewDS[i]->OpenZoomLevel( i+1 );
-      }       
+      }
    }
 
    /* -------------------------------------------------------------------- */
@@ -908,35 +913,30 @@ GDALDataset *MG4LidarDataset::Open( GDALOpenInfo * poOpenInfo )
 }
 
 /************************************************************************/
-/*                          GDALRegister_MG4Lidar()                        */
+/*                          GDALRegister_MG4Lidar()                     */
 /************************************************************************/
 
 void GDALRegister_MG4Lidar()
 
 {
-   GDALDriver	*poDriver;
+    if( !GDAL_CHECK_VERSION( "MG4Lidar driver" ) )
+        return;
 
-    if (! GDAL_CHECK_VERSION("MG4Lidar driver"))
+    if( GDALGetDriverByName( "MG4Lidar" ) != NULL )
         return;
 
-   if( GDALGetDriverByName( "MG4Lidar" ) == NULL )
-   {
-      poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
 
-      poDriver->SetDescription( "MG4Lidar" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-      poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-         "MrSID Generation 4 / Lidar (.sid)" );
-      // To do:  update this help file in gdal.org
-      poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-         "frmt_mrsid_lidar.html" );
+    poDriver->SetDescription( "MG4Lidar" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "MrSID Generation 4 / Lidar (.sid)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,  "frmt_mrsid_lidar.html" );
 
-      poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "view" );
-      poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-         "Float64" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "view" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Float64" );
 
-      poDriver->pfnOpen = MG4LidarDataset::Open;
+    poDriver->pfnOpen = MG4LidarDataset::Open;
 
-      GetGDALDriverManager()->RegisterDriver( poDriver );
-   }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/mrsid_lidar/mg4lidar_headers.h b/frmts/mrsid_lidar/mg4lidar_headers.h
new file mode 100644
index 0000000..3f0757c
--- /dev/null
+++ b/frmts/mrsid_lidar/mg4lidar_headers.h
@@ -0,0 +1,43 @@
+/******************************************************************************
+ *
+ * Project:  GDAL
+ * Purpose:  Includes MG4Lida headers
+ * Author:   Even Rouault <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+#ifndef MG4LIDAR_HEADERS_H
+#define MG4LIDAR_HEADERS_H
+
+#include "cpl_port.h"
+
+#ifdef HAVE_GCC_SYSTEM_HEADER
+#pragma GCC system_header
+#endif
+
+#include "lidar/MG4PointReader.h"
+#include "lidar/FileIO.h"
+#include "lidar/Error.h"
+#include "lidar/Version.h"
+
+#endif
diff --git a/frmts/msg/frmt_msg.html b/frmts/msg/frmt_msg.html
index 7dcf696..cfac889 100644
--- a/frmts/msg/frmt_msg.html
+++ b/frmts/msg/frmt_msg.html
@@ -8,14 +8,14 @@
 
 <h1>MSG -- Meteosat Second Generation</h1>
 
-<p>This driver implemets reading support for Meteosat Second
+<p>This driver implements reading support for Meteosat Second
 Generation files. These are files with names like
 H-000-MSG1__-MSG1________-HRV______-000007___-200405311115-C_, commonly
 distributed into a folder structure with dates (e.g. 2004\05\31 for the file mentioned).</p>
 
-<p>The MSG files are wavelet-compressed. A decompression library licensed from <a href="http://www.eumetsat.int/">EUMETSAT</a> is needed 
-(<a href="http://www.eumetsat.int/Home/Main/Access_to_Data/User_Support/SP_1117714787347">Public Wavelet Transform Decompression Library Software</a>, 
-shorter <em>Wavelet Transform Software</em>). 
+<p>The MSG files are wavelet-compressed. A decompression library licensed from <a href="http://www.eumetsat.int/">EUMETSAT</a> is needed
+(<a href="http://www.eumetsat.int/Home/Main/Access_to_Data/User_Support/SP_1117714787347">Public Wavelet Transform Decompression Library Software</a>,
+shorter <em>Wavelet Transform Software</em>).
 The software is compilable on Microsoft Windows, Linux and Solaris Operating Systems, and it works on 32 bits and 64 bits as well as mixed architectures.
 It is a licensed software and available free to download upon acceptance of the WaveLet Transform Software Licence during electronic registration process.
 </p>
@@ -45,7 +45,7 @@ PublicDecompWTMakefiles.zip.</p>
 
 <p>If find that some adjustments are needed in the makefile and/or the msg
 source files, please "commit" them. The Eumetsat library promises to be
-"platform indepentent", but as we are working with Microsoft Windows
+"platform independent", but as we are working with Microsoft Windows
 and Visual Studio 6.0, we did not have the facilities to check if the
 rest of the msg driver is. Furthermore, apply steps 4 to 7 from the <a href="http://www.gdal.org/gdal_drivertut.html">GDAL Driver Implementation Tutorial</a>, section "Adding Driver to GDAL Tree".
 </p>
@@ -85,7 +85,7 @@ gdal_translate
               <li>B to convert to 8 bits (handy for GIF and JPEG images). The result is Byte.</li>
               <li>R to perform radiometric calibration and get the result in mW/m2/sr/(cm-1)-1. The result is Float32.</li>
               <li>L to perform radiometric calibration and get the result in W/m2/sr/um. The result is Float32.</li>
-              <li>T to get the reflectance for the visible bands (1, 2, 3 and 12) and the temprature in degrees Kelvin for the infrared bands (all other bands). The result is Float32.</li>
+              <li>T to get the reflectance for the visible bands (1, 2, 3 and 12) and the temperature in degrees Kelvin for the infrared bands (all other bands). The result is Float32.</li>
             </ul>
         </li>
         <li>nr_cycles: a number that indicates the number of consecutive cycles to be included in the same file (time series). These are appended as additional bands.</li>
diff --git a/frmts/msg/msgcommand.cpp b/frmts/msg/msgcommand.cpp
index 84640a9..afc3aea 100644
--- a/frmts/msg/msgcommand.cpp
+++ b/frmts/msg/msgcommand.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: msgcommand.cpp 27370 2014-05-21 09:34:50Z rouault $
+ * $Id: msgcommand.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Purpose:  Implementation of MSGCommand class. Parse the src_dataset
  *           string that is meant for the MSG driver.
@@ -392,7 +392,7 @@ std::string MSGCommand::sCycle(int iCycle)
   // 200405311115 should result in 200405311130
   // 200405311101 should result in 200405311115
   // 200412312345 should result in 200501010000
-  
+
   std::string sYear (sTimeStamp.substr(0, 4));
   std::string sMonth (sTimeStamp.substr(4, 2));
   std::string sDay (sTimeStamp.substr(6, 2));
@@ -432,9 +432,9 @@ std::string MSGCommand::sCycle(int iCycle)
   }
 
   char sRet [100];
-  sprintf(sRet, "%.4d%.2d%.2d%.2d%.2d", iYear, iMonth, iDay, iHours, iMins);
+  snprintf(sRet, sizeof(sRet), "%.4d%.2d%.2d%.2d%.2d", iYear, iMonth, iDay, iHours, iMins);
 
-  return sRet;  
+  return sRet;
 }
 
 std::string MSGCommand::sFileName(int iSatellite, int iSequence, int iStrip)
@@ -445,9 +445,9 @@ std::string MSGCommand::sFileName(int iSatellite, int iSequence, int iStrip)
   char sRet [4096];
   std::string siThCycle (sCycle(iCycle));
   if (fUseTimestampFolder)
-    sprintf(sRet, "%s%sH-000-MSG%d__-MSG%d________-%s-%.6d___-%s-C_", sRootFolder.c_str(), sTimeStampToFolder(siThCycle).c_str(), iSatellite, iSatellite, sChannel(iChannel(iChannelNumber)).c_str(), iStrip, siThCycle.c_str());
+    snprintf(sRet, sizeof(sRet), "%s%sH-000-MSG%d__-MSG%d________-%s-%.6d___-%s-C_", sRootFolder.c_str(), sTimeStampToFolder(siThCycle).c_str(), iSatellite, iSatellite, sChannel(iChannel(iChannelNumber)).c_str(), iStrip, siThCycle.c_str());
   else
-    sprintf(sRet, "%sH-000-MSG%d__-MSG%d________-%s-%.6d___-%s-C_", sRootFolder.c_str(), iSatellite, iSatellite, sChannel(iChannel(iChannelNumber)).c_str(), iStrip, siThCycle.c_str());
+    snprintf(sRet, sizeof(sRet), "%sH-000-MSG%d__-MSG%d________-%s-%.6d___-%s-C_", sRootFolder.c_str(), iSatellite, iSatellite, sChannel(iChannel(iChannelNumber)).c_str(), iStrip, siThCycle.c_str());
   return sRet;
 }
 
@@ -457,9 +457,8 @@ std::string MSGCommand::sPrologueFileName(int iSatellite, int iSequence)
   char sRet [4096];
   std::string siThCycle (sCycle(iCycle));
   if (fUseTimestampFolder)
-    sprintf(sRet, "%s%sH-000-MSG%d__-MSG%d________-_________-PRO______-%s-__", sRootFolder.c_str(), sTimeStampToFolder(siThCycle).c_str(), iSatellite, iSatellite, siThCycle.c_str());
+    snprintf(sRet, sizeof(sRet), "%s%sH-000-MSG%d__-MSG%d________-_________-PRO______-%s-__", sRootFolder.c_str(), sTimeStampToFolder(siThCycle).c_str(), iSatellite, iSatellite, siThCycle.c_str());
   else
-    sprintf(sRet, "%sH-000-MSG%d__-MSG%d________-_________-PRO______-%s-__", sRootFolder.c_str(), iSatellite, iSatellite, siThCycle.c_str());
+    snprintf(sRet, sizeof(sRet), "%sH-000-MSG%d__-MSG%d________-_________-PRO______-%s-__", sRootFolder.c_str(), iSatellite, iSatellite, siThCycle.c_str());
   return sRet;
 }
-
diff --git a/frmts/msg/msgcommand.h b/frmts/msg/msgcommand.h
index 2df7ca0..f8114fe 100644
--- a/frmts/msg/msgcommand.h
+++ b/frmts/msg/msgcommand.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: msgcommand.h 15085 2008-07-31 13:41:31Z mloskot $
+ * $Id: msgcommand.h 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Purpose:  Interface of MSGCommand class. Parse the src_dataset string
  *           that is meant for the MSG driver.
@@ -32,7 +32,7 @@
 
 #include <string>
 
-class MSGCommand  
+class MSGCommand
 {
 public:
   MSGCommand();
@@ -65,4 +65,3 @@ private:
 };
 
 #endif // GDAL_MSG_MSGCOMMAND_H_INCLUDED
-
diff --git a/frmts/msg/msgdataset.cpp b/frmts/msg/msgdataset.cpp
index 0f0271e..68f771a 100644
--- a/frmts/msg/msgdataset.cpp
+++ b/frmts/msg/msgdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: msgdataset.cpp 27477 2014-06-28 15:23:40Z rouault $
+ * $Id: msgdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  MSG Driver
  * Purpose:  GDALDataset driver for MSG translator for read support.
@@ -28,6 +28,7 @@
  * DEALINGS IN THE SOFTWARE.
  ******************************************************************************/
 
+#include "gdal_frmts.h"
 #include "msgdataset.h"
 #include "prologue.h"
 #include "xritheaderparser.h"
@@ -185,14 +186,14 @@ GDALDataset *MSGDataset::Open( GDALOpenInfo * poOpenInfo )
                   sErr.c_str() );
         return FALSE;
     }
-      
+
 
 // We're confident the string is formatted as an MSG command_line
 
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    
+
     MSGDataset   *poDS;
     poDS = new MSGDataset();
     poDS->command = command; // copy it
@@ -254,11 +255,11 @@ GDALDataset *MSGDataset::Open( GDALOpenInfo * poOpenInfo )
     // The following are 3 different try-outs for also setting the ellips a and b parameters.
     // We leave them out for now however because this does not work. In gdalwarp, when choosing some
     // specific target SRS, the result is an error message:
-    // 
+    //
     // ERROR 1: geocentric transformation missing z or ellps
     // ERROR 1: GDALWarperOperation::ComputeSourceWindow() failed because
     // the pfnTransformer failed.
-    // 
+    //
     // I can't explain the reason for the message at this time (could be a problem in the way the SRS is set here,
     // but also a bug in Proj.4 or GDAL.
     /*
@@ -301,19 +302,19 @@ GDALDataset *MSGDataset::Open( GDALOpenInfo * poOpenInfo )
     {
         poDS->SetBand( iBand+1, new MSGRasterBand( poDS, iBand+1 ) );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The MSG driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
     }
-    
+
     return( poDS );
 }
 
@@ -332,7 +333,7 @@ MSGRasterBand::MSGRasterBand( MSGDataset *poDS, int nBand )
 {
     this->poDS = poDS;
     this->nBand = nBand;
-		
+
     // Find if we're dealing with MSG1, MSG2, MSG3 or MSG4
     // Doing this per band is the only way to guarantee time-series when the satellite is changed
 
@@ -475,9 +476,8 @@ CPLErr MSGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                   void * pImage )
 
 {
-        
-    MSGDataset  *poGDS = (MSGDataset *) poDS;
 
+    MSGDataset  *poGDS = (MSGDataset *) poDS;
 
     int iBytesPerPixel = 1;
     if (eDataType == GDT_UInt16)
@@ -497,7 +497,7 @@ CPLErr MSGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
       strip_number = poGDS->command.iNrStrips(iChannel) - nBlockYOff;
 
     std::string strip_input_file = poGDS->command.sFileName(iSatellite, nBand, strip_number);
-    
+
 /* -------------------------------------------------------------------- */
 /*      Open the input file                                             */
 /* -------------------------------------------------------------------- */
@@ -512,10 +512,10 @@ CPLErr MSGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         if (xhp.isValid())
         {
           std::vector <short> QualityInfo;
-          unsigned short chunck_height = xhp.nrRows();
-          unsigned short chunck_bpp = xhp.nrBitsPerPixel();
-          unsigned short chunck_width = xhp.nrColumns();
-          unsigned __int8 NR = (unsigned __int8)chunck_bpp;
+          unsigned short chunk_height = xhp.nrRows();
+          unsigned short chunk_bpp = xhp.nrBitsPerPixel();
+          unsigned short chunk_width = xhp.nrColumns();
+          unsigned __int8 NR = (unsigned __int8)chunk_bpp;
           unsigned int nb_ibytes = xhp.dataSize();
           int iShift = 0;
           bool fSplitStrip = false; // in the split strip the "shift" only happens before the split "row"
@@ -529,30 +529,30 @@ CPLErr MSGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             // When iLowerShift > 0, the lower HRV image is shifted to the right
             // When iLowerShift < 0, the lower HRV image is shifted to the left
             // The available raster may be wider than needed, so that time series don't fall outside the raster.
-            
+
             if (nBlockYOff <= iSplitBlock)
               iShift = -iLowerShift;
             // iShift < 0 means upper image moves to the left
             // iShift > 0 means upper image moves to the right
           }
-          
+
           std::auto_ptr< unsigned char > ibuf( new unsigned char[nb_ibytes]);
-          
+
           if (ibuf.get() == 0)
           {
-             CPLError( CE_Failure, CPLE_AppDefined, 
+             CPLError( CE_Failure, CPLE_AppDefined,
                   "Not enough memory to perform wavelet decompression\n");
             return CE_Failure;
           }
 
           i_file.read( (char *)(ibuf.get()), nb_ibytes);
-          
+
           Util::CDataFieldCompressedImage  img_compressed(ibuf.release(),
                                   nb_ibytes*8,
-                                  (unsigned char)chunck_bpp,
-                                  chunck_width,
-                                  chunck_height      );
-          
+                                  (unsigned char)chunk_bpp,
+                                  chunk_width,
+                                  chunk_height      );
+
           Util::CDataFieldUncompressedImage img_uncompressed;
 
           //****************************************************
@@ -565,20 +565,20 @@ CPLErr MSGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
           // 8 bits -> 8 bits
           // 10 bits -> 16 bits (img_uncompressed contains the 10 bits data in packed form)
           // Geometry:
-          // chunck_width x chunck_height to nBlockXSize x nBlockYSize
+          // chunk_width x chunk_height to nBlockXSize x nBlockYSize
 
           // cases:
           // combination of the following:
           // - scan direction can be north or south
           // - eDataType can be GDT_Byte, GDT_UInt16 or GDT_Float32
-          // - nBlockXSize == chunck_width or nBlockXSize > chunck_width
-          // - when nBlockXSize > chunck_width, fSplitStrip can be true or false
+          // - nBlockXSize == chunk_width or nBlockXSize > chunk_width
+          // - when nBlockXSize > chunk_width, fSplitStrip can be true or false
           // we won't distinguish the following cases:
           // - NR can be == 8 or != 8
-          // - when nBlockXSize > chunck_width, iShift iMinCOff-iMaxCOff <= iShift <= 0
+          // - when nBlockXSize > chunk_width, iShift iMinCOff-iMaxCOff <= iShift <= 0
 
           int nBlockSize = nBlockXSize * nBlockYSize;
-          int y = chunck_width * chunck_height;
+          int y = chunk_width * chunk_height;
           int iStep = -1;
           if (fScanNorth) // image is the other way around
           {
@@ -589,7 +589,7 @@ CPLErr MSGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
           COMP::CImage cimg (img_uncompressed); // unpack
           if (eDataType == GDT_Byte)
           {
-            if (nBlockXSize == chunck_width) // optimized version
+            if (nBlockXSize == chunk_width) // optimized version
             {
               if (poGDS->command.cDataConversion == 'B')
               {
@@ -608,25 +608,25 @@ CPLErr MSGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
               memset(pImage, 0, nBlockXSize * nBlockYSize * iBytesPerPixel);
               if (poGDS->command.cDataConversion == 'B')
               {
-                for( int j = 0; j < chunck_height; ++j ) // assumption: nBlockYSize == chunck_height
-                { 
+                for( int j = 0; j < chunk_height; ++j ) // assumption: nBlockYSize == chunk_height
+                {
                   int iXOffset = j * nBlockXSize + iShift;
                   iXOffset += nBlockXSize - iLowerWestColumnPlanned - 1; // Position the HRV part in the frame; -1 to compensate the pre-increment in the for-loop
                   if (fSplitStrip && (j >= iSplitRow)) // In splitstrip, below splitline, thus do not shift!!
                     iXOffset -= iShift;
-                  for (int i = 0; i < chunck_width; ++i)
+                  for (int i = 0; i < chunk_width; ++i)
                     ((GByte *)pImage)[++iXOffset] = cimg.Get()[y+=iStep] / 4;
                 }
               }
               else
               {
-                for( int j = 0; j < chunck_height; ++j ) // assumption: nBlockYSize == chunck_height
-                { 
+                for( int j = 0; j < chunk_height; ++j ) // assumption: nBlockYSize == chunk_height
+                {
                   int iXOffset = j * nBlockXSize + iShift;
                   iXOffset += nBlockXSize - iLowerWestColumnPlanned - 1; // Position the HRV part in the frame; -1 to compensate the pre-increment in the for-loop
                   if (fSplitStrip && (j >= iSplitRow)) // In splitstrip, below splitline, thus do not shift!!
                     iXOffset -= iShift;
-                  for (int i = 0; i < chunck_width; ++i)
+                  for (int i = 0; i < chunk_width; ++i)
                     ((GByte *)pImage)[++iXOffset] = cimg.Get()[y+=iStep];
                 }
               }
@@ -634,7 +634,7 @@ CPLErr MSGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
           }
           else if (eDataType == GDT_UInt16) // this is our "normal case" if scan direction is South: 10 bit MSG data became 2 bytes per pixel
           {
-            if (nBlockXSize == chunck_width) // optimized version
+            if (nBlockXSize == chunk_width) // optimized version
             {
               for( int i = 0; i < nBlockSize; ++i )
                   ((GUInt16 *)pImage)[i] = cimg.Get()[y+=iStep];
@@ -643,20 +643,20 @@ CPLErr MSGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             {
               // initialize to 0's (so that it does not have to be done in an 'else' statement <performance>)
               memset(pImage, 0, nBlockXSize * nBlockYSize * iBytesPerPixel);
-              for( int j = 0; j < chunck_height; ++j ) // assumption: nBlockYSize == chunck_height
+              for( int j = 0; j < chunk_height; ++j ) // assumption: nBlockYSize == chunk_height
               {
                 int iXOffset = j * nBlockXSize + iShift;
                 iXOffset += nBlockXSize - iLowerWestColumnPlanned - 1; // Position the HRV part in the frame; -1 to compensate the pre-increment in the for-loop
                 if (fSplitStrip && (j >= iSplitRow)) // In splitstrip, below splitline, thus do not shift!!
                   iXOffset -= iShift;
-                for (int i = 0; i < chunck_width; ++i)
+                for (int i = 0; i < chunk_width; ++i)
                   ((GUInt16 *)pImage)[++iXOffset] = cimg.Get()[y+=iStep];
               }
             }
           }
           else if (eDataType == GDT_Float32) // radiometric calibration is requested
           {
-            if (nBlockXSize == chunck_width) // optimized version
+            if (nBlockXSize == chunk_width) // optimized version
             {
               for( int i = 0; i < nBlockSize; ++i )
                 ((float *)pImage)[i] = (float)rRadiometricCorrection(cimg.Get()[y+=iStep], iChannel, nBlockYOff * nBlockYSize + i / nBlockXSize, i % nBlockXSize, poGDS);
@@ -665,15 +665,15 @@ CPLErr MSGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             {
               // initialize to 0's (so that it does not have to be done in an 'else' statement <performance>)
               memset(pImage, 0, nBlockXSize * nBlockYSize * iBytesPerPixel);
-              for( int j = 0; j < chunck_height; ++j ) // assumption: nBlockYSize == chunck_height
+              for( int j = 0; j < chunk_height; ++j ) // assumption: nBlockYSize == chunk_height
               {
                 int iXOffset = j * nBlockXSize + iShift;
                 iXOffset += nBlockXSize - iLowerWestColumnPlanned - 1; // Position the HRV part in the frame; -1 to compensate the pre-increment in the for-loop
                 if (fSplitStrip && (j >= iSplitRow)) // In splitstrip, below splitline, thus do not shift!!
                   iXOffset -= iShift;
                 int iXFrom = nBlockXSize - iLowerWestColumnPlanned + iShift; // i is used as the iCol parameter in rRadiometricCorrection
-                int iXTo = nBlockXSize - iLowerWestColumnPlanned + chunck_width + iShift;
-                for (int i = iXFrom; i < iXTo; ++i) // range always equal to chunck_width .. this is to utilize i to get iCol
+                int iXTo = nBlockXSize - iLowerWestColumnPlanned + chunk_width + iShift;
+                for (int i = iXFrom; i < iXTo; ++i) // range always equal to chunk_width .. this is to utilize i to get iCol
                   ((float *)pImage)[++iXOffset] = (float)rRadiometricCorrection(cimg.Get()[y+=iStep], iChannel, nBlockYOff * nBlockYSize + j, (fSplitStrip && (j >= iSplitRow))?(i - iShift):i, poGDS);
               }
             }
@@ -695,12 +695,13 @@ CPLErr MSGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
 double MSGRasterBand::rRadiometricCorrection(unsigned int iDN, int iChannel, int iRow, int iCol, MSGDataset* poGDS)
 {
-	int iIndex = iChannel - 1; // just for speed optimization
+  int iIndex = iChannel - 1; // just for speed optimization
 
   double rSlope = poGDS->rCalibrationSlope[iIndex];
   double rOffset = poGDS->rCalibrationOffset[iIndex];
-  
-  if (poGDS->command.cDataConversion == 'T') // reflectance for visual bands, temperatore for IR bands
+
+  // Reflectance for visual bands, temperature for IR bands.
+  if (poGDS->command.cDataConversion == 'T')
   {
     double rRadiance = rOffset + (iDN * rSlope);
 
@@ -743,20 +744,16 @@ double MSGRasterBand::rRadiometricCorrection(unsigned int iDN, int iChannel, int
 void GDALRegister_MSG()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "MSG" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "MSG" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "MSG" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "MSG HRIT Data" );
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->pfnOpen = MSGDataset::Open;
+    poDriver->SetDescription( "MSG" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,  "MSG HRIT Data" );
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
-}
+    poDriver->pfnOpen = MSGDataset::Open;
 
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/frmts/msg/msgdataset.h b/frmts/msg/msgdataset.h
index 2e45dbe..f892e99 100644
--- a/frmts/msg/msgdataset.h
+++ b/frmts/msg/msgdataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: msgdataset.h 15064 2008-07-28 19:10:23Z mloskot $
+ * $Id: msgdataset.h 32190 2015-12-16 13:50:27Z goatbar $
  *
  * Project:  MSG Driver
  * Purpose:  GDALDataset driver for MSG translator for read support.
@@ -36,7 +36,7 @@
 #include <fstream>
 
 CPL_C_START
-void  GDALRegister_MSG(void);
+void GDALRegister_MSG();
 CPL_C_END
 
 /************************************************************************/
@@ -72,7 +72,7 @@ class MSGRasterBand : public GDALRasterBand
 class MSGDataset : public GDALDataset
 {
   friend class MSGRasterBand;
-  
+
   public:
     MSGDataset();
     ~MSGDataset();
diff --git a/frmts/msg/prologue.cpp b/frmts/msg/prologue.cpp
index 7e64bdc..514b604 100644
--- a/frmts/msg/prologue.cpp
+++ b/frmts/msg/prologue.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: prologue.cpp 15064 2008-07-28 19:10:23Z mloskot $
+ * $Id: prologue.cpp 32179 2015-12-14 16:22:34Z goatbar $
  *
  * Purpose:  Implementation of Prologue class. Parse the prologue of one
  *           repeat cycle and keep the interesting info.
@@ -39,7 +39,7 @@ int size_SatelliteStatus()
   int iSizeAttitude = 4 + 4 + 8 + 100*iSizeAttitudeCoef;
   int iSizeSpinRateatRCStart = 8;
   int iSizeUTCCorrelation = 4 + 4 + 4*4*3 + 8 + 8 + 8 + 8 + 8;
-  
+
   int iTotalSize = iSizePrimary + iSizeOrbit + iSizeAttitude + iSizeSpinRateatRCStart + iSizeUTCCorrelation;
 
   return iTotalSize;
@@ -53,7 +53,7 @@ int size_ImageAcquisition()
   int iSize2 = 42*2 + 42 + 42*2 + 42*2 + 42*2 + 27*2 + 15*2 + 6*2 + 1 + 2 + 1;
   // to end
   int iSize3 = 2 + 1 + 2 + 4 + 2 + 2 + 2 + 1 + 4 + 1 + 4 + 4 + 1 + 1 + 2 + 2 + 2 + 2;
-    
+
   int iTotalSize = iSize1 + iSize2 + iSize3;
 
   return iTotalSize;
@@ -64,7 +64,7 @@ int size_CelestialEvents()
   int iSizeCelestialBodies = 2 + 2 + 4 + 4 + 3*100*(2 + 2 + 8*8 + 8*8) + 100*(20*(2 + 2 + 2 + 8*8 + 8*8));
 
   int iSizeRelationToImage = 1 + 2 + 2 + 1 + 1 + 1;
-    
+
   int iTotalSize = iSizeCelestialBodies + iSizeRelationToImage;
 
   return iTotalSize;
@@ -79,7 +79,7 @@ double iReadDouble(std::ifstream & ifile)
 {
   // will use 8 bytes from the file to read a DOUBLE (according to the MSG definition of DOUBLE)
     unsigned char buf [8];
-    
+
     ifile.read((char*)buf, 8);
     double rVal;
     ((char*)(&rVal))[0] = buf[7];
@@ -90,7 +90,7 @@ double iReadDouble(std::ifstream & ifile)
     ((char*)(&rVal))[5] = buf[2];
     ((char*)(&rVal))[6] = buf[1];
     ((char*)(&rVal))[7] = buf[0];
-    
+
     return rVal;
 }
 
@@ -98,14 +98,14 @@ double iReadReal(std::ifstream & ifile)
 {
   // will use 4 bytes from the file to read a REAL (according to the MSG definition of REAL)
     unsigned char buf [4];
-    
+
     ifile.read((char*)buf, 4);
     float rVal;
     ((char*)(&rVal))[0] = buf[3];
     ((char*)(&rVal))[1] = buf[2];
     ((char*)(&rVal))[2] = buf[1];
     ((char*)(&rVal))[3] = buf[0];
-    
+
     return rVal;
 }
 
@@ -113,7 +113,7 @@ int iReadInt(std::ifstream & ifile)
 {
   // will use 4 bytes from the file to read an int (according to the MSG definition of int)
     unsigned char buf [4];
-    
+
     ifile.read((char*)buf, 4);
     int iResult = (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+buf[3];
 
@@ -124,7 +124,7 @@ unsigned char iReadByte (std::ifstream & ifile)
 {
   // will read 1 byte from the file
     char b;
-    
+
     ifile.read(&b, 1);
 
     return b;
diff --git a/frmts/msg/prologue.h b/frmts/msg/prologue.h
index eed344d..1e2fe70 100644
--- a/frmts/msg/prologue.h
+++ b/frmts/msg/prologue.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: prologue.h 15064 2008-07-28 19:10:23Z mloskot $
+ * $Id: prologue.h 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Purpose:  Interface of Prologue class. Parse the prologue of one repeat
  *           cycle and keep the interesting info.
@@ -99,7 +99,7 @@ public:
   double Cal_Offset [12];
 };
 
-class Prologue  
+class Prologue
 {
 public:
   Prologue();
diff --git a/frmts/msg/reflectancecalculator.cpp b/frmts/msg/reflectancecalculator.cpp
index 1de0cba..b2ed993 100644
--- a/frmts/msg/reflectancecalculator.cpp
+++ b/frmts/msg/reflectancecalculator.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: reflectancecalculator.cpp 15066 2008-07-28 20:21:59Z mloskot $
+ * $Id: reflectancecalculator.cpp 32179 2015-12-14 16:22:34Z goatbar $
  *
  * Purpose:  Implementation of ReflectanceCalculator class. Calculate
  *           reflectance values from radiance, for visual bands.
@@ -32,8 +32,6 @@
 #include <cstdlib>
 using namespace std;
 
-#define M_PI        3.14159265358979323846
-
 //////////////////////////////////////////////////////////////////////
 // Construction/Destruction
 //////////////////////////////////////////////////////////////////////
@@ -88,7 +86,7 @@ const double ReflectanceCalculator::rDeclination() const
   double rJulianDay = m_iDay - 1;
   double yearFraction = (rJulianDay + m_rHours / 24) / iDaysInYear(m_iYear);
   double T = 2 * M_PI * yearFraction;
-  
+
   double declin = 0.006918 - 0.399912 * cos(T) + 0.070257 * sin(T)
           - 0.006758 * cos(2 * T) + 0.000907 * sin(2 * T)
           - 0.002697 * cos(3 * T) + 0.00148 * sin(3 * T);
@@ -97,8 +95,8 @@ const double ReflectanceCalculator::rDeclination() const
 
 double ReflectanceCalculator::rHourAngle(double rLon) const
 {
-	// In: rLon (in degrees)
-	// Out: hourAngle (in radians)
+  // In: rLon (in degrees)
+  // Out: hourAngle (in radians)
   double rJulianDay = m_iDay - 1;
   double yearFraction = (rJulianDay + m_rHours / 24) / iDaysInYear(m_iYear);
   double T = 2 * M_PI * yearFraction;
@@ -128,7 +126,7 @@ const double ReflectanceCalculator::rSunDistance() const
 int ReflectanceCalculator::iDaysInYear(int iYear) const
 {
   bool fLeapYear = iDaysInMonth(2, iYear) == 29;
-  
+
   if (fLeapYear)
       return 366;
   else
diff --git a/frmts/msg/reflectancecalculator.h b/frmts/msg/reflectancecalculator.h
index e1a9126..d5a59bf 100644
--- a/frmts/msg/reflectancecalculator.h
+++ b/frmts/msg/reflectancecalculator.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: reflectancecalculator.h 15064 2008-07-28 19:10:23Z mloskot $
+ * $Id: reflectancecalculator.h 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Purpose:  Interface of ReflectanceCalculator class. Calculate reflectance
  *           values from radiance, for visual bands.
@@ -36,7 +36,7 @@
 
 #include <string>
 
-class ReflectanceCalculator  
+class ReflectanceCalculator
 {
 public:
 	ReflectanceCalculator(std::string sTimeStamp, double rRTOA);
diff --git a/frmts/msg/xritheaderparser.cpp b/frmts/msg/xritheaderparser.cpp
index df16426..94868c5 100644
--- a/frmts/msg/xritheaderparser.cpp
+++ b/frmts/msg/xritheaderparser.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: xritheaderparser.cpp 15066 2008-07-28 20:21:59Z mloskot $
+ * $Id: xritheaderparser.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Purpose:  Implementation of XRITHeaderParser class. Parse the header
  *           of the combined XRIT header/data files.
@@ -35,7 +35,7 @@
 // Construction/Destruction
 //
 // Upon successful parsing of a header in ifile, isValid() returns true
-// and ifile is seeked to the beginning of the image data
+// and ifile is sought to the beginning of the image data
 //////////////////////////////////////////////////////////////////////
 
 XRITHeaderParser::XRITHeaderParser(std::ifstream & ifile)
@@ -48,7 +48,7 @@ XRITHeaderParser::XRITHeaderParser(std::ifstream & ifile)
 , m_scanNorth(false)
 {
   const unsigned int probeSize = 8;
- 
+
   unsigned char probeBuf[probeSize];
   ifile.read((char*)probeBuf, probeSize); // Probe file by reading first 8 bytes
 
@@ -59,17 +59,17 @@ XRITHeaderParser::XRITHeaderParser(std::ifstream & ifile)
     {
       unsigned char * buf = (unsigned char*)std::malloc(totalHeaderLength);
       std::memcpy(buf, probeBuf, probeSize); // save what we have already read when probing
-      ifile.read((char*)buf + probeSize, totalHeaderLength - probeSize); // read the rest of the header section  
+      ifile.read((char*)buf + probeSize, totalHeaderLength - probeSize); // read the rest of the header section
       parseHeader(buf, totalHeaderLength);
       std::free(buf);
 
       m_isValid = true;
     }
   }
-  
+
   if (!m_isValid) // seek back to original position
   {
-#if _MSC_VER > 1000 && _MSC_VER < 1300  
+#if _MSC_VER > 1000 && _MSC_VER < 1300
     ifile.seekg(-probeSize, std::ios_base::seekdir::cur);
 #else
     ifile.seekg(-probeSize, std::ios_base::cur);
diff --git a/frmts/msgn/frmt_msgn.html b/frmts/msgn/frmt_msgn.html
index 6c52e31..5724dfe 100644
--- a/frmts/msgn/frmt_msgn.html
+++ b/frmts/msgn/frmt_msgn.html
@@ -22,7 +22,7 @@ prefixing the filename with the tag "RAD:".
 <p>Georeferencing is currently supported, but the results may not be
 acceptable (accurate enough), depending on your requirements. The current
 workaround is to implement the CGMS Geostationary projection directly, using
-the code available from EUMETSAT. 
+the code available from EUMETSAT.
 
 </body>
 </html>
diff --git a/frmts/msgn/makefile.vc b/frmts/msgn/makefile.vc
index 6771dcb..c5df738 100644
--- a/frmts/msgn/makefile.vc
+++ b/frmts/msgn/makefile.vc
@@ -1,7 +1,7 @@
 
 OBJ    =        msgndataset.obj msg_basic_types.obj msg_reader_core.obj
 
-EXTRAFLAGS =   -I..\iso8211 -I. -DGDAL_SUPPORT
+EXTRAFLAGS =   -I. -DGDAL_SUPPORT
 
 GDAL_ROOT      =       ..\..
 
diff --git a/frmts/msgn/msg_basic_types.cpp b/frmts/msgn/msg_basic_types.cpp
index 93e15ad..339a1a8 100644
--- a/frmts/msgn/msg_basic_types.cpp
+++ b/frmts/msgn/msg_basic_types.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: msg_basic_types.cpp 28435 2015-02-07 14:35:34Z rouault $
+ * $Id: msg_basic_types.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  MSG Native Reader
  * Purpose:  Basic types implementation.
@@ -27,16 +27,16 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "msg_basic_types.h"
 #include "cpl_port.h"
+#include "msg_basic_types.h"
 
-CPL_CVSID("$Id: msg_basic_types.cpp 28435 2015-02-07 14:35:34Z rouault $");
+CPL_CVSID("$Id: msg_basic_types.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 #include <stdio.h>
 
 namespace msg_native_format {
 
-#ifndef SQR 
+#ifndef SQR
 #define SQR(x) ((x)*(x))
 #endif
 
@@ -64,7 +64,7 @@ static void swap_64_bits(unsigned char* b) {
     }
 }
 
-void to_native(RADIOMETRIC_PROCCESSING_RECORD& r) {
+void to_native(RADIOMETRIC_PROCESSING_RECORD& r) {
     for (int i=0; i < 12; i++) {
         swap_64_bits((unsigned char*)&r.level1_5ImageCalibration[i].cal_slope);
         swap_64_bits((unsigned char*)&r.level1_5ImageCalibration[i].cal_offset);
@@ -123,8 +123,8 @@ const double Conversions::altitude      =   42164;          // from origin
 const double Conversions::req           =   6378.1690;       // earthequatorial radius
 const double Conversions::rpol          =   6356.5838;       // earth polar radius
 const double Conversions::oblate        =   1.0/298.257;    // oblateness of earth
-const double Conversions::deg_to_rad    =   M_PI/180.0; 
-const double Conversions::rad_to_deg    =   180.0/M_PI; 
+const double Conversions::deg_to_rad    =   M_PI/180.0;
+const double Conversions::rad_to_deg    =   180.0/M_PI;
 const double Conversions::nlines        =   3712;           // number of lines in an image
 const double Conversions::step          =   17.83/nlines;    // pixel / line step in degrees
 
@@ -138,17 +138,17 @@ const int Conversions::LOFF    = 1856;
 void Conversions::convert_pixel_to_geo(double line, double column, double&longitude, double& latitude) {
     double x = (column - COFF - 0.0) / double(CFAC >> 16);
     double y = (line - LOFF - 0.0) / double(LFAC >> 16);
-    
-    double sd = sqrt(SQR(altitude*cos(x)*cos(y)) - (SQR(cos(y)) + 1.006803*SQR(sin(y)))*1737121856); 
+
+    double sd = sqrt(SQR(altitude*cos(x)*cos(y)) - (SQR(cos(y)) + 1.006803*SQR(sin(y)))*1737121856);
     double sn = (altitude*cos(x)*cos(y) - sd)/(SQR(cos(y)) + 1.006803*SQR(sin(y)));
     double s1 = altitude - sn*cos(x)*cos(y);
     double s2 = sn*sin(x)*cos(y);
     double s3 = -sn*sin(y);
     double sxy = sqrt(s1*s1 + s2*s2);
-    
+
     longitude = atan(s2/s1);
     latitude  = atan(1.006803*s3/sxy);
-    
+
     longitude = longitude / M_PI * 180.0;
     latitude  = latitude  / M_PI * 180.0;
 }
@@ -156,30 +156,30 @@ void Conversions::convert_pixel_to_geo(double line, double column, double&longit
 void Conversions::compute_pixel_xyz(double line, double column, double& x,double& y, double& z) {
     double asamp = -(column - (nlines/2.0 + 0.5)) * step;
     double aline = (line - (nlines/2.0 + 0.5)) * step;
-    
+
     asamp *= deg_to_rad;
     aline *= deg_to_rad;
-    
+
     double tanal = tan(aline);
     double tanas = tan(asamp);
-    
+
     double p = -1;
     double q = tanas;
     double r = tanal * sqrt(1 + q*q);
-    
+
    double a = q*q + (r*req/rpol)*(r*req/rpol) + p*p;
     double b = 2 * altitude * p;
     double c = altitude * altitude  - req*req;
-    
+
     double det = b*b - 4*a*c;
-     
+
     if (det > 0) {
         double k = (-b - sqrt(det))/(2*a);
         x = altitude + k*p;
         y = k * q;
         z = k * r;
-        
     } else {
+        x = y = z = 0;
         fprintf(stderr, "Warning: pixel not visible\n");
     }
 }
@@ -191,13 +191,13 @@ double Conversions::compute_pixel_area_sqkm(double line, double column) {
 
     compute_pixel_xyz(line-0.5, column-0.5, x1, y1, z1);
     compute_pixel_xyz(line+0.5, column-0.5, x2, y2, z2);
-    
+
     double xlen = sqrt(SQR(x1 - x2) + SQR(y1 - y2) + SQR(z1 - z2));
-    
+
     compute_pixel_xyz(line-0.5, column+0.5, x2, y2, z2);
-    
+
     double ylen = sqrt(SQR(x1 - x2) + SQR(y1 - y2) + SQR(z1 - z2));
-    
+
     return xlen*ylen;
 }
 
@@ -212,10 +212,10 @@ void Conversions::convert_geo_to_pixel(double longitude, double latitude,unsigne
     double r2 = -r_l*cos(c_lat)*sin(longitude);
     double r3 = r_l*sin(c_lat);
     double rn = sqrt(r1*r1 + r2*r2 + r3*r3);
-    
+
     double x = atan(-r2/r1) * (CFAC >> 16) + COFF;
     double y = asin(-r3/rn) * (LFAC >> 16) + LOFF;
-    
+
     line = (unsigned int)floor(x + 0.5);
     column = (unsigned int)floor(y + 0.5);
 }
diff --git a/frmts/msgn/msg_basic_types.h b/frmts/msgn/msg_basic_types.h
index c02b3a4..acfe793 100644
--- a/frmts/msgn/msg_basic_types.h
+++ b/frmts/msgn/msg_basic_types.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: msg_basic_types.h 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: msg_basic_types.h 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  MSG Native Reader
  * Purpose:  Basic types implementation.
@@ -32,10 +32,6 @@
 
 #include <math.h>
 
-#ifndef M_PI
-#define M_PI  3.1415926535897932384626433832795
-#endif
-
 namespace msg_native_format {
 
 const unsigned int      SATELLITESTATUS_RECORD_LENGTH   = 60134;
@@ -43,9 +39,9 @@ const unsigned int      IMAGEACQUISITION_RECORD_LENGTH  = 700;
 const unsigned int      CELESTIALEVENTS_RECORD_LENGTH   = 326058; // should be 56258 according to ICD105 ??
 const unsigned int      IMAGEDESCRIPTION_RECORD_LENGTH  = 101;
 
-const unsigned int      RADIOMETRICPROCESSING_RECORD_OFFSET = 
-    SATELLITESTATUS_RECORD_LENGTH + 
-    IMAGEACQUISITION_RECORD_LENGTH + 
+const unsigned int      RADIOMETRICPROCESSING_RECORD_OFFSET =
+    SATELLITESTATUS_RECORD_LENGTH +
+    IMAGEACQUISITION_RECORD_LENGTH +
     CELESTIALEVENTS_RECORD_LENGTH +
     IMAGEDESCRIPTION_RECORD_LENGTH;
 
@@ -148,7 +144,7 @@ typedef struct {
 
 typedef struct {
     UBYTE       headerVersionNo;
-    EBYTE       packetType;         // 2 = mission data 
+    EBYTE       packetType;         // 2 = mission data
     EBYTE       subHeaderType;      // 0 = no subheader, 1 = GP_PK_SH1, 2 = GP_PK_SH2
     GP_FAC_ID   sourceFacilityId;
     GP_FAC_ENV  sourceEnvId;
@@ -158,7 +154,7 @@ typedef struct {
     GP_FAC_ID   destFacilityId;
     GP_FAC_ENV  destEnvId;
     USHORT      sequenceCount;
-    UNSIGNED    packetLength;      
+    UNSIGNED    packetLength;
 } GP_PK_HEADER;
 
 typedef struct {
@@ -174,7 +170,7 @@ typedef struct {
 typedef struct {
     double  cal_slope;
     double  cal_offset;
-} CALIBRATION; 
+} CALIBRATION;
 
 typedef struct {
     EBYTE       radianceLinearisation[12];
@@ -185,7 +181,7 @@ typedef struct {
     EBYTE       straylightCorrectionFlag[12];
     CALIBRATION level1_5ImageCalibration[12];
     // rest of structure omitted for now
-} RADIOMETRIC_PROCCESSING_RECORD;
+} RADIOMETRIC_PROCESSING_RECORD;
 
 typedef struct {
     INTEGER     numberOfLines;
@@ -202,14 +198,14 @@ typedef struct {
     // rest of record omitted, for now
 } IMAGE_DESCRIPTION_RECORD;
 
-// disable byte-packing 
+// disable byte-packing
 #pragma pack()
 
 // endian conversion routines
 void to_native(GP_PK_HEADER& h);
 void to_native(GP_PK_SH1& h);
 void to_native(SUB_VISIRLINE& v);
-void to_native(RADIOMETRIC_PROCCESSING_RECORD& r);
+void to_native(RADIOMETRIC_PROCESSING_RECORD& r);
 void to_native(IMAGE_DESCRIPTION_RECORD& r);
 
 // utility function, alters string fields permanently
@@ -222,7 +218,7 @@ class Conversions {
 public:
     static void convert_pixel_to_geo(double line, double column, double& longitude, double& latitude);
     static void convert_geo_to_pixel(double longitude, double latitude, unsigned int& line, unsigned int& column);
-    
+
     static void compute_pixel_xyz(double line, double column, double& x, double& y, double& z);
     static double compute_pixel_area_sqkm(double line, double column);
 
@@ -230,19 +226,17 @@ public:
     static const double req;        // earth equatorial radius
     static const double rpol;       // earth polar radius
     static const double oblate;     // oblateness of earth
-    static const double deg_to_rad; 
-    static const double rad_to_deg; 
+    static const double deg_to_rad;
+    static const double rad_to_deg;
     static const double step;       // pixel / line step in degrees
     static const double nlines;     // number of lines in an image
-    
+
     static const int CFAC;     // Column scale factor
     static const int LFAC;     // Line scale factor
     static const int COFF;     // Column offset
     static const int LOFF;     // Line offset
-    
 };
 
 } // msg_native_format
 
 #endif
-
diff --git a/frmts/msgn/msg_reader_core.cpp b/frmts/msgn/msg_reader_core.cpp
index 4a00ea8..df75c47 100644
--- a/frmts/msgn/msg_reader_core.cpp
+++ b/frmts/msgn/msg_reader_core.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: msg_reader_core.cpp 24910 2012-09-05 17:52:18Z rouault $
+ * $Id: msg_reader_core.cpp 33138 2016-01-24 11:18:11Z rouault $
  *
  * Project:  MSG Native Reader
  * Purpose:  Base class for reading in the headers of MSG native images
@@ -27,6 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+
 #include "msg_reader_core.h"
 #include "msg_basic_types.h"
 #include <stdio.h>
@@ -42,11 +44,11 @@
 #ifdef GDAL_SUPPORT
 #include "cpl_vsi.h"
 
-CPL_CVSID("$Id: msg_reader_core.cpp 24910 2012-09-05 17:52:18Z rouault $");
+CPL_CVSID("$Id: msg_reader_core.cpp 33138 2016-01-24 11:18:11Z rouault $");
 
 #else
-#define VSIFSeek(fp, pos, ref)    fseek(fp, pos, ref)
-#define VSIFRead(p, bs, nb, fp)   fread(p, bs, nb, fp)
+#define VSIFSeek(fp, pos, ref)    CPL_IGNORE_RET_VAL(fseek(fp, pos, ref))
+#define VSIFRead(p, bs, nb, fp)   CPL_IGNORE_RET_VAL(fread(p, bs, nb, fp))
 #endif
 
 namespace msg_native_format {
@@ -67,8 +69,61 @@ const Blackbody_lut_type Msg_reader_core::Blackbody_LUT[MSG_NUM_CHANNELS+1] = {
     {0,0,0}   // N/A
 };
 
+static
+void PhDataInit(PH_DATA *data)
+{
+  data->name[0] = '\0';
+  data->value[0] = '\0';
+}
+
+static
+void SecondaryProdHeaderInit(SECONDARY_PROD_HEADER *header)
+{
+  PhDataInit(&header->abid);
+  PhDataInit(&header->smod);
+  PhDataInit(&header->apxs);
+  PhDataInit(&header->avpa);
+  PhDataInit(&header->lscd);
+  PhDataInit(&header->lmap);
+  PhDataInit(&header->qdlc);
+  PhDataInit(&header->qdlp);
+  PhDataInit(&header->qqai);
+  PhDataInit(&header->selectedBandIds);
+  PhDataInit(&header->southLineSelectedRectangle);
+  PhDataInit(&header->northLineSelectedRectangle);
+  PhDataInit(&header->eastColumnSelectedRectangle);
+  PhDataInit(&header->westColumnSelectedRectangle);
+}
 
-Msg_reader_core::Msg_reader_core(const char* fname) {
+Msg_reader_core::Msg_reader_core(const char* fname) :
+    _lines(0),
+    _columns(0),
+    _line_start(0),
+    _col_start(0),
+    _col_dir_step(0.0f),
+    _line_dir_step(0.0f),
+    _f_data_offset(0),
+    _f_data_size(0),
+    _f_header_offset(0),
+    _f_header_size(0),
+    _visir_bytes_per_line(0),
+    _visir_packet_size(0),
+    _hrv_bytes_per_line(0),
+    _hrv_packet_size(0),
+    _interline_spacing(0),
+    _year(0),
+    _month(0),
+    _day(0),
+    _hour(0),
+    _minute(0),
+    _open_success(false)
+{
+    memset(&_main_header, 0, sizeof(_main_header));
+    SecondaryProdHeaderInit(&_sec_header);
+    for (size_t i=0; i < MSG_NUM_CHANNELS; ++i) {
+      _calibration[i].cal_slope = 0.0;
+      _calibration[i].cal_offset = 0.0;
+    }
 
     FILE* fin = fopen(fname, "rb");
     if (!fin) {
@@ -76,9 +131,40 @@ Msg_reader_core::Msg_reader_core(const char* fname) {
         return;
     }
     read_metadata_block(fin);
+    fclose(fin);
 }
 
-Msg_reader_core::Msg_reader_core(FILE* fp) {
+Msg_reader_core::Msg_reader_core(FILE* fp) :
+    _lines(0),
+    _columns(0),
+    _line_start(0),
+    _col_start(0),
+    _col_dir_step(0.0f),
+    _line_dir_step(0.0f),
+    _f_data_offset(0),
+    _f_data_size(0),
+    _f_header_offset(0),
+    _f_header_size(0),
+    _visir_bytes_per_line(0),
+    _visir_packet_size(0),
+    _hrv_bytes_per_line(0),
+    _hrv_packet_size(0),
+    _interline_spacing(0),
+    _year(0),
+    _month(0),
+    _day(0),
+    _hour(0),
+    _minute(0),
+    _open_success(false)
+{
+    memset(&_main_header, 0, sizeof(_main_header));
+
+    SecondaryProdHeaderInit(&_sec_header);
+    for (size_t i=0; i < MSG_NUM_CHANNELS; ++i) {
+      _calibration[i].cal_slope = 0.0;
+      _calibration[i].cal_offset = 0.0;
+    }
+
     read_metadata_block(fp);
 }
 
@@ -88,8 +174,8 @@ void Msg_reader_core::read_metadata_block(FILE* fin) {
 
     unsigned int i;
 
-    VSIFRead(&_main_header, sizeof(_main_header), 1, fin);
-    VSIFRead(&_sec_header, sizeof(_sec_header), 1, fin);
+    CPL_IGNORE_RET_VAL(VSIFRead(&_main_header, sizeof(_main_header), 1, fin));
+    CPL_IGNORE_RET_VAL(VSIFRead(&_sec_header, sizeof(_sec_header), 1, fin));
 
 #ifdef DEBUG
     // print out all the fields in the header
@@ -117,13 +203,13 @@ void Msg_reader_core::read_metadata_block(FILE* fin) {
 
     for (i=0; i < 5; i++) {
         PH_DATA_ID* hdi = (PH_DATA_ID*)&_main_header.dataSetIdentification[i];
-        if (strncmp(hdi->name, "15Header", strlen("15Header")) == 0) {
-            sscanf(hdi->size, "%d", &_f_header_size);
-            sscanf(hdi->address, "%d", &_f_header_offset);
+        if (STARTS_WITH(hdi->name, "15Header")) {
+            sscanf(hdi->size, "%u", &_f_header_size);
+            sscanf(hdi->address, "%u", &_f_header_offset);
         } else
-            if (strncmp(hdi->name, "15Data", strlen("15Data")) == 0) {
-            sscanf(hdi->size, "%d", &_f_data_size);
-            sscanf(hdi->address, "%d", &_f_data_offset);
+            if (STARTS_WITH(hdi->name, "15Data")) {
+            sscanf(hdi->size, "%u", &_f_data_size);
+            sscanf(hdi->address, "%u", &_f_data_offset);
         }
     }
 #ifdef DEBUG
@@ -132,14 +218,14 @@ void Msg_reader_core::read_metadata_block(FILE* fin) {
 #endif // DEBUG
 
     unsigned int lines;
-    sscanf(_sec_header.northLineSelectedRectangle.value, "%d", &_lines);
-    sscanf(_sec_header.southLineSelectedRectangle.value, "%d", &lines);
+    sscanf(_sec_header.northLineSelectedRectangle.value, "%u", &_lines);
+    sscanf(_sec_header.southLineSelectedRectangle.value, "%u", &lines);
     _line_start = lines;
     _lines -= lines - 1;
 
     unsigned int cols;
-    sscanf(_sec_header.westColumnSelectedRectangle.value, "%d", &_columns);
-    sscanf(_sec_header.eastColumnSelectedRectangle.value, "%d", &cols);
+    sscanf(_sec_header.westColumnSelectedRectangle.value, "%u", &_columns);
+    sscanf(_sec_header.eastColumnSelectedRectangle.value, "%u", &cols);
     _col_start = cols;
     _columns -= cols - 1;
 
@@ -162,17 +248,17 @@ void Msg_reader_core::read_metadata_block(FILE* fin) {
 #endif // DEBUG
 
     // extract time fields, assume that SNIT is the correct field:
-    sscanf(_main_header.snit.value +  0, "%04d", &_year);
-    sscanf(_main_header.snit.value +  4, "%02d", &_month);
-    sscanf(_main_header.snit.value +  6, "%02d", &_day);
-    sscanf(_main_header.snit.value +  8, "%02d", &_hour);
-    sscanf(_main_header.snit.value + 10, "%02d", &_minute);
+    sscanf(_main_header.snit.value +  0, "%04u", &_year);
+    sscanf(_main_header.snit.value +  4, "%02u", &_month);
+    sscanf(_main_header.snit.value +  6, "%02u", &_day);
+    sscanf(_main_header.snit.value +  8, "%02u", &_hour);
+    sscanf(_main_header.snit.value + 10, "%02u", &_minute);
 
     // read radiometric block
-    RADIOMETRIC_PROCCESSING_RECORD rad;
+    RADIOMETRIC_PROCESSING_RECORD rad;
     off_t offset = RADIOMETRICPROCESSING_RECORD_OFFSET + _f_header_offset + sizeof(GP_PK_HEADER) + sizeof(GP_PK_SH1) + 1;
-    VSIFSeek(fin, offset, SEEK_SET);
-    VSIFRead(&rad, sizeof(RADIOMETRIC_PROCCESSING_RECORD), 1, fin);
+    CPL_IGNORE_RET_VAL(VSIFSeek(fin, offset, SEEK_SET));
+    CPL_IGNORE_RET_VAL(VSIFRead(&rad, sizeof(RADIOMETRIC_PROCESSING_RECORD), 1, fin));
     to_native(rad);
     memcpy((void*)_calibration, (void*)&rad.level1_5ImageCalibration,sizeof(_calibration));
 
@@ -191,8 +277,8 @@ void Msg_reader_core::read_metadata_block(FILE* fin) {
     // read image description block
     IMAGE_DESCRIPTION_RECORD idr;
     offset = RADIOMETRICPROCESSING_RECORD_OFFSET  - IMAGEDESCRIPTION_RECORD_LENGTH + _f_header_offset + sizeof(GP_PK_HEADER) + sizeof(GP_PK_SH1) + 1;
-    VSIFSeek(fin, offset, SEEK_SET);
-    VSIFRead(&idr, sizeof(IMAGE_DESCRIPTION_RECORD), 1, fin);
+    CPL_IGNORE_RET_VAL(VSIFSeek(fin, offset, SEEK_SET));
+    CPL_IGNORE_RET_VAL(VSIFRead(&idr, sizeof(IMAGE_DESCRIPTION_RECORD), 1, fin));
     to_native(idr);
     _line_dir_step = idr.referencegrid_visir.lineDirGridStep;
     _col_dir_step = idr.referencegrid_visir.columnDirGridStep;
@@ -204,7 +290,7 @@ void Msg_reader_core::read_metadata_block(FILE* fin) {
     GP_PK_SH1    sub_header;
     SUB_VISIRLINE visir_line;
 
-    VSIFSeek(fin, _f_data_offset, SEEK_SET);
+    CPL_IGNORE_RET_VAL(VSIFSeek(fin, _f_data_offset, SEEK_SET));
 
     _hrv_packet_size = 0;
     _interline_spacing = 0;
@@ -218,17 +304,17 @@ void Msg_reader_core::read_metadata_block(FILE* fin) {
     }
 
     do {
-        VSIFRead(&gp_header, sizeof(GP_PK_HEADER), 1, fin);
-        VSIFRead(&sub_header, sizeof(GP_PK_SH1), 1, fin);
-        VSIFRead(&visir_line, sizeof(SUB_VISIRLINE), 1, fin);
+        CPL_IGNORE_RET_VAL(VSIFRead(&gp_header, sizeof(GP_PK_HEADER), 1, fin));
+        CPL_IGNORE_RET_VAL(VSIFRead(&sub_header, sizeof(GP_PK_SH1), 1, fin));
+        CPL_IGNORE_RET_VAL(VSIFRead(&visir_line, sizeof(SUB_VISIRLINE), 1, fin));
         to_native(visir_line);
         to_native(gp_header);
 
         // skip over the actual line data
-        VSIFSeek(fin,
+        CPL_IGNORE_RET_VAL(VSIFSeek(fin,
             gp_header.packetLength - (sizeof(GP_PK_SH1) + sizeof(SUB_VISIRLINE) - 1),
             SEEK_CUR
-        );
+        ));
 
         if (visir_line.channelId == 0 || visir_line.channelId > MSG_NUM_CHANNELS) {
             _open_success = false;
@@ -240,14 +326,14 @@ void Msg_reader_core::read_metadata_block(FILE* fin) {
             band_count--;
 
             if (visir_line.channelId != 12) { // not the HRV channel
-                _visir_bytes_per_line = gp_header.packetLength - (sizeof(GP_PK_SH1) + sizeof(SUB_VISIRLINE) - 1);
-                _visir_packet_size = gp_header.packetLength + sizeof(GP_PK_HEADER) + 1;
+                _visir_bytes_per_line = gp_header.packetLength - (unsigned int)(sizeof(GP_PK_SH1) + sizeof(SUB_VISIRLINE) - 1);
+                _visir_packet_size = gp_header.packetLength + (unsigned int)sizeof(GP_PK_HEADER) + 1;
                 _interline_spacing += _visir_packet_size;
             } else {
-                _hrv_bytes_per_line = gp_header.packetLength - (sizeof(GP_PK_SH1) + sizeof(SUB_VISIRLINE) - 1);
-                _hrv_packet_size = gp_header.packetLength + sizeof(GP_PK_HEADER) + 1;
+                _hrv_bytes_per_line = gp_header.packetLength - (unsigned int)(sizeof(GP_PK_SH1) + sizeof(SUB_VISIRLINE) - 1);
+                _hrv_packet_size = gp_header.packetLength + (unsigned int)sizeof(GP_PK_HEADER) + 1;
                 _interline_spacing +=  3*_hrv_packet_size;
-                VSIFSeek(fin, 2*gp_header.packetLength, SEEK_CUR );
+                CPL_IGNORE_RET_VAL(VSIFSeek(fin, 2*gp_header.packetLength, SEEK_CUR ));
             }
         }
     } while (band_count > 0);
@@ -281,4 +367,3 @@ double Msg_reader_core::compute_pixel_area_sqkm(double line, double column) {
 #endif // GDAL_SUPPORT
 
 } // namespace msg_native_format
-
diff --git a/frmts/msgn/msgndataset.cpp b/frmts/msgn/msgndataset.cpp
index 2446525..7d05d2f 100644
--- a/frmts/msgn/msgndataset.cpp
+++ b/frmts/msgn/msgndataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: msgndataset.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: msgndataset.cpp 33105 2016-01-23 15:27:32Z rouault $
  *
  * Project:  MSG Native Reader
  * Purpose:  All code for EUMETSAT Archive format reader
@@ -28,17 +28,14 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "gdal_frmts.h"
 #include "gdal_priv.h"
 #include "ogr_spatialref.h"
 
 #include "msg_reader_core.h"
 using namespace msg_native_format;
 
-CPL_CVSID("$Id: msgndataset.cpp 27745 2014-09-27 16:38:57Z goatbar $");
-
-CPL_C_START
-void   GDALRegister_MSGN(void);
-CPL_C_END
+CPL_CVSID("$Id: msgndataset.cpp 33105 2016-01-23 15:27:32Z rouault $");
 
 typedef enum {
     MODE_VISIR,     // Visible and Infrared bands (1 through 11) in 10-bit raw mode
@@ -118,16 +115,16 @@ class MSGNRasterBand : public GDALRasterBand
 /*                           MSGNRasterBand()                            */
 /************************************************************************/
 
-MSGNRasterBand::MSGNRasterBand( MSGNDataset *poDS, int nBand , open_mode_type mode, int orig_band_no, int band_in_file)
+MSGNRasterBand::MSGNRasterBand( MSGNDataset *poDSIn, int nBandIn , open_mode_type mode, int orig_band_noIn, int band_in_fileIn)
 
 {
-    this->poDS = poDS;
-    this->nBand = nBand;                // GDAL's band number, i.e. always starts at 1
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;                // GDAL's band number, i.e. always starts at 1
     this->open_mode = mode;
-    this->orig_band_no = orig_band_no;
-    this->band_in_file = band_in_file;
+    this->orig_band_no = orig_band_noIn;
+    this->band_in_file = band_in_fileIn;
 
-    sprintf(band_description, "band %02d", orig_band_no);
+    snprintf(band_description, sizeof(band_description), "band %02d", orig_band_no);
 
     if (mode != MODE_RAD) {
         eDataType = GDT_UInt16;
@@ -141,14 +138,14 @@ MSGNRasterBand::MSGNRasterBand( MSGNDataset *poDS, int nBand , open_mode_type mo
     nBlockYSize = 1;
 
     if (mode != MODE_HRV) {
-        packet_size = poDS->msg_reader_core->get_visir_packet_size();
-        bytes_per_line = poDS->msg_reader_core->get_visir_bytes_per_line();
+        packet_size = poDSIn->msg_reader_core->get_visir_packet_size();
+        bytes_per_line = poDSIn->msg_reader_core->get_visir_bytes_per_line();
     } else {
-        packet_size = poDS->msg_reader_core->get_hrv_packet_size();
-        bytes_per_line = poDS->msg_reader_core->get_hrv_bytes_per_line();
+        packet_size = poDSIn->msg_reader_core->get_hrv_packet_size();
+        bytes_per_line = poDSIn->msg_reader_core->get_hrv_bytes_per_line();
     }
 
-    interline_spacing = poDS->msg_reader_core->get_interline_spacing();
+    interline_spacing = poDSIn->msg_reader_core->get_interline_spacing();
 }
 
 /************************************************************************/
@@ -167,7 +164,7 @@ CPLErr MSGNRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 
     char       *pszRecord;
 
-    unsigned int data_length =  bytes_per_line + sizeof(SUB_VISIRLINE);
+    unsigned int data_length =  bytes_per_line + (unsigned int)sizeof(SUB_VISIRLINE);
     unsigned int data_offset = 0;
 
     if (open_mode != MODE_HRV) {
@@ -180,7 +177,8 @@ CPLErr MSGNRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
             packet_size*(3 - (i_nBlockYOff % 3)) + (packet_size - data_length);
     }
 
-    VSIFSeek( poGDS->fp, data_offset, SEEK_SET );
+    if( VSIFSeek( poGDS->fp, data_offset, SEEK_SET ) != 0 )
+        return CE_Failure;
 
     pszRecord = (char *) CPLMalloc(data_length);
     size_t nread = VSIFRead( pszRecord, 1, data_length, poGDS->fp );
@@ -248,8 +246,7 @@ CPLErr MSGNRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                 }
             }
             double dvalue = double(value);
-            double bbvalue = MSGN_NODATA_VALUE;
-            bbvalue = dvalue * poGDS->msg_reader_core->get_calibration_parameters()[orig_band_no-1].cal_slope +
+            double bbvalue = dvalue * poGDS->msg_reader_core->get_calibration_parameters()[orig_band_no-1].cal_slope +
                 poGDS->msg_reader_core->get_calibration_parameters()[orig_band_no-1].cal_offset;
 
             ((double *)pImage)[nBlockXSize-1 -c] = bbvalue;
@@ -285,9 +282,11 @@ double MSGNRasterBand::GetMaximum(int *pbSuccess ) {
 /* ==================================================================== */
 /************************************************************************/
 
-MSGNDataset::MSGNDataset() {
+MSGNDataset::MSGNDataset() :
+    fp(NULL)
+{
     pszProjection = CPLStrdup("");
-    msg_reader_core = 0;
+    msg_reader_core = NULL;
 }
 
 /************************************************************************/
@@ -343,11 +342,11 @@ GDALDataset *MSGNDataset::Open( GDALOpenInfo * poOpenInfo )
     GDALOpenInfo* open_info = poOpenInfo;
 
     if (!poOpenInfo->bStatOK) {
-        if ( EQUALN(poOpenInfo->pszFilename, "HRV:", 4) ) {
+        if ( STARTS_WITH_CI(poOpenInfo->pszFilename, "HRV:") ) {
             open_info = new GDALOpenInfo(&poOpenInfo->pszFilename[4], poOpenInfo->eAccess);
             open_mode = MODE_HRV;
         } else
-        if ( EQUALN(poOpenInfo->pszFilename, "RAD:", 4 ) ) {
+        if ( STARTS_WITH_CI(poOpenInfo->pszFilename, "RAD:") ) {
             open_info = new GDALOpenInfo(&poOpenInfo->pszFilename[4], poOpenInfo->eAccess);
             open_mode = MODE_RAD;
         }
@@ -358,34 +357,47 @@ GDALDataset *MSGNDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      least one "\n#keyword" type signature in the first chunk of     */
 /*      the file.                                                       */
 /* -------------------------------------------------------------------- */
-    if( open_info->fpL == NULL || open_info->nHeaderBytes < 50 )
+    if( open_info->fpL == NULL || open_info->nHeaderBytes < 50 ) {
+        if (open_info != poOpenInfo) {
+            delete open_info;
+        }
         return NULL;
+    }
 
     /* check if this is a "NATIVE" MSG format image */
-    if( !EQUALN((char *)open_info->pabyHeader,
-                "FormatName                  : NATIVE", 36) )
+    if( !STARTS_WITH_CI((char *)open_info->pabyHeader, "FormatName                  : NATIVE") )
     {
+        if (open_info != poOpenInfo) {
+            delete open_info;
+        }
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The MSGN driver does not support update access to existing"
                   " datasets.\n" );
+        if (open_info != poOpenInfo) {
+            delete open_info;
+        }
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
     MSGNDataset        *poDS;
     FILE* fp = VSIFOpen( open_info->pszFilename, "rb" );
-    if( fp == NULL )
+    if( fp == NULL ) {
+        if (open_info != poOpenInfo) {
+            delete open_info;
+        }
         return NULL;
+    }
 
     poDS = new MSGNDataset();
 
@@ -395,11 +407,14 @@ GDALDataset *MSGNDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Read the header.                                                */
 /* -------------------------------------------------------------------- */
     // first reset the file pointer, then hand over to the msg_reader_core
-    VSIFSeek( poDS->fp, 0, SEEK_SET );
+    CPL_IGNORE_RET_VAL(VSIFSeek( poDS->fp, 0, SEEK_SET ));
 
     poDS->msg_reader_core = new Msg_reader_core(poDS->fp);
 
     if (!poDS->msg_reader_core->get_open_success()) {
+        if (open_info != poOpenInfo) {
+            delete open_info;
+        }
         delete poDS;
         return NULL;
     }
@@ -490,12 +505,12 @@ GDALDataset *MSGNDataset::Open( GDALOpenInfo * poOpenInfo )
 
     poDS->SetMetadataItem("Radiometric parameters format", "offset slope");
     for (i=1; i < band_count; i++) {
-        sprintf(tagname, "ch%02d_cal", band_map[i]);
-        sprintf(field, "%.12e %.12e", cal[band_map[i]-1].cal_offset, cal[band_map[i]-1].cal_slope);
+        snprintf(tagname, sizeof(tagname), "ch%02d_cal", band_map[i]);
+        CPLsnprintf(field, sizeof(field), "%.12e %.12e", cal[band_map[i]-1].cal_offset, cal[band_map[i]-1].cal_slope);
         poDS->SetMetadataItem(tagname, field);
     }
 
-    sprintf(field, "%04d%02d%02d/%02d:%02d",
+    snprintf(field, sizeof(field), "%04d%02d%02d/%02d:%02d",
         poDS->msg_reader_core->get_year(),
         poDS->msg_reader_core->get_month(),
         poDS->msg_reader_core->get_day(),
@@ -504,13 +519,12 @@ GDALDataset *MSGNDataset::Open( GDALOpenInfo * poOpenInfo )
     );
     poDS->SetMetadataItem("Date/Time", field);
 
-    sprintf(field, "%d %d",
+    snprintf(field, sizeof(field), "%d %d",
          poDS->msg_reader_core->get_line_start(),
          poDS->msg_reader_core->get_col_start()
     );
     poDS->SetMetadataItem("Origin", field);
 
-
     if (open_info != poOpenInfo) {
         delete open_info;
     }
@@ -519,28 +533,25 @@ GDALDataset *MSGNDataset::Open( GDALOpenInfo * poOpenInfo )
 }
 
 /************************************************************************/
-/*                          GDALRegister_MSGN()                          */
+/*                          GDALRegister_MSGN()                         */
 /************************************************************************/
 
 void GDALRegister_MSGN()
 
 {
-    GDALDriver *poDriver;
+    if( GDALGetDriverByName( "MSGN" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "MSGN" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "MSGN" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "EUMETSAT Archive native (.nat)" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "frmt_msgn.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "nat" );
+    poDriver->SetDescription( "MSGN" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "EUMETSAT Archive native (.nat)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_msgn.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "nat" );
 
-        poDriver->pfnOpen = MSGNDataset::Open;
+    poDriver->pfnOpen = MSGNDataset::Open;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/netcdf/GNUmakefile b/frmts/netcdf/GNUmakefile
index e069067..78614e2 100644
--- a/frmts/netcdf/GNUmakefile
+++ b/frmts/netcdf/GNUmakefile
@@ -1,7 +1,7 @@
 
 include ../../GDALmake.opt
 
-OBJ	=	netcdfdataset.o gmtdataset.o
+OBJ	=	netcdfdataset.o netcdflayer.o netcdfwriterconfig.o gmtdataset.o
 
 XTRA_OPT = 
 ifeq ($(NETCDF_HAS_NC4),yes)
diff --git a/frmts/netcdf/frmt_netcdf.html b/frmts/netcdf/frmt_netcdf.html
index b595e6a..838e20e 100644
--- a/frmts/netcdf/frmt_netcdf.html
+++ b/frmts/netcdf/frmt_netcdf.html
@@ -7,14 +7,14 @@
 
 <h1>NetCDF: Network Common Data Form</h1>
 
+This format is supported for read and write access. This page only describes
+the raster support (you can find documentation for the
+<a href="frmt_netcdf_vector.html">vector side</a>)
 
-This format is supported for read and write access. 
-
-NetCDF is an interface for 
+NetCDF is an interface for
 array-oriented data access and is used for representing scientific data.<p>
 
-
-The fill value metadata or missing_value backward compatibililty is preserved 
+The fill value metadata or missing_value backward compatibility is preserved
 as NODATA value when available.
 <p>
 
@@ -22,35 +22,35 @@ NOTE: Implemented as <tt>gdal/frmts/netcdf/netcdfdataset.cpp</tt>.<p>
 
 <h2> Multiple Image Handling (Subdatasets)</h2>
 
-Nework Command Data Form is a container for several different arrays most
-used for storing scientific dataset. One netCDF file may 
-contain several datasets. They may differ in size, number of dimensions and 
+Network Command Data Form is a container for several different arrays most
+used for storing scientific dataset. One NetCDF file may
+contain several datasets. They may differ in size, number of dimensions and
 may represent data for different regions.
 <p>
-If the file contains only one netCDF array which appears to be an image, 
-it may be accessed directly, but if the file contains multiple images it may 
+If the file contains only one NetCDF array which appears to be an image,
+it may be accessed directly, but if the file contains multiple images it may
 be necessary to import the file via a two step process. <p>
 <p>
-The first step is to get a report of the components images (dataset) in the 
-file using gdalinfo, and then to import the desired images using 
-gdal_translate.  The gdalinfo utility lists all multidimensional subdatasets 
-from the input netCDF file. 
+The first step is to get a report of the components images (dataset) in the
+file using gdalinfo, and then to import the desired images using
+gdal_translate.  The gdalinfo utility lists all multidimensional subdatasets
+from the input NetCDF file.
 <p>
-The name of individual images are assigned to the SUBDATASET_n_NAME 
-metadata item. The description for each image is found in the 
-SUBDATASET_n_DESC metadata item. For netCDF images will follow this format:
+The name of individual images are assigned to the SUBDATASET_n_NAME
+metadata item. The description for each image is found in the
+SUBDATASET_n_DESC metadata item. For NetCDF images will follow this format:
 
 <i>NETCDF:filename:variable_name</i><p>
 
 where <i>filename</i> is the name of the input file, and
-<i>variable_name</i> is the dataset selected withing the file.<p>
+<i>variable_name</i> is the dataset selected within the file.<p>
 
 On the second step you provide this name for <b>gdalinfo</b> to get information
 about the dataset or
 
 <b>gdal_translate</b> to read dataset.<p>
 
-For example, we want to read data from a netCDF file:<p>
+For example, we want to read data from a NetCDF file:<p>
 <pre>
 $ gdalinfo sst.nc
 Driver: netCDF/Network Common Data Format
@@ -86,13 +86,13 @@ Lower Right (  512.0,  512.0)
 Center      (  256.0,  256.0)
 </pre>
 
-This netCDF files contain 4 datasets, lon_bnds, lat_bnds, tim_bnds and tos.
+This NetCDF files contain 4 datasets, lon_bnds, lat_bnds, tim_bnds and tos.
 
 Now select the subdataset, described as:
 
 <tt><p>NETCDF:"sst.nc":tos<p>
 [24x17x180]  sea_surface_temperature (32-bit floating-point) </tt><p>
-and get the information about the number of bands there is inside this 
+and get the information about the number of bands there is inside this
 variable.
 
 <pre>
@@ -156,50 +156,50 @@ Band 24 Block=180x1 Type=Float32, ColorInterp=Undefined
     NETCDF_time_units=days since 2001-1-1
 </pre>
 
-gdalinfo display the number of bands into this subdataset.  
-There are metadata attached to each band. 
+gdalinfo displays the number of bands into this subdataset.
+There are metadata attached to each band.
 
 In this example, the metadata informs us
-that each band correspond to an array of monthly sea surface temperature 
+that each band correspond to an array of monthly sea surface temperature
 from January 2001.  There are 24 months of data in this subdataset.
 
 You may also use <b>gdal_translate</b> for reading the subdataset.<p>
 
-Note that you should provide exactly the contents of the line marked 
+Note that you should provide exactly the contents of the line marked
 <b>SUBDATASET_n_NAME</b> to GDAL, including the <b>NETCDF:</b> prefix.<p>
 
-The <b>NETCDF</b> prefix must be first.  It triggers the subdataset netCDF driver.
+The <b>NETCDF</b> prefix must be first.  It triggers the subdataset NetCDF driver.
 
-This driver is intended only for importing remote sensing and geospatial 
-datasets in form of raster images. If you want explore all data contained in 
-netCDF file you should use another tools. 
+This driver is intended only for importing remote sensing and geospatial
+datasets in form of raster images. If you want explore all data contained in
+NetCDF file you should use another tools.
 
 <h2>Dimension</h2>
 
-The netCDF driver assume that data follows the CF-1 convention from 
+The NetCDF driver assume that data follows the CF-1 convention from
 <a href="http://www.unidata.ucar.edu/software/netcdf/docs/conventions.html">UNIDATA </A>
 
-The dimensions inside the NetCDF file use the following rules: (Z,Y,X).  
-If there are more than 3 
+The dimensions inside the NetCDF file use the following rules: (Z,Y,X).
+If there are more than 3
 dimensions, the driver will merge them into bands. For example if you have
 an 4 dimension arrays of the type (P, T, Y, X).  The driver will multiply the
 last 2 dimensions (P*T).  The driver will display the bands in the following
-order.  It will first increment T and then P. Metadata 
+order.  It will first increment T and then P. Metadata
 will be displayed on each band with its corresponding T and P values.
 
 <h2>Georeference</h2>
 
-There is no universal way of storing georeferencing in netCDF files. 
+There is no universal way of storing georeferencing in NetCDF files.
 
 The driver first tries to follow the CF-1 Convention from UNIDATA looking for
-the Metadata named "grid_mapping". 
+the Metadata named "grid_mapping".
 
-If "grid_mapping" is not present, the driver will try to find an 
-lat/lon grid array to set geotransform array.  The NetCDF driver verifies 
+If "grid_mapping" is not present, the driver will try to find an
+lat/lon grid array to set geotransform array.  The NetCDF driver verifies
 that the Lat/Lon array is equally space.<p>
 
-If those 2 mehtods fail, NetCDF driver will try to read the following 
-metadata directly and set up georefenrencing.
+If those 2 methods fail, NetCDF driver will try to read the following
+metadata directly and set up georeferencing.
 <ul>
     <li>spatial_ref (Well Known Text)
 </ul>
@@ -216,20 +216,20 @@ or,
 
 <h2>Creation Issues</h2>
 
-This driver supports creation of netCDF file following the CF-1 convention. 
+This driver supports creation of NetCDF file following the CF-1 convention.
 You may create set of 2D datasets.  Each variable array is named
 Band1, Band2, ... BandN. <p>
 
 Each band will have metadata tied to it giving a short description of
-the data it contains. 
+the data it contains.
 
 
 <h2>GDAL NetCDF Metadata</h2>
 
-All netCDF attributes are transparently translated as GDAL metadata. <p>
+All NetCDF attributes are transparently translated as GDAL metadata. <p>
 The translation follow these directives:<p>
 <ul>
-<li>Global NetCDF metatadata have a <b>NC_GLOBAL</b> tag prefixed.<p>
+<li>Global NetCDF metadata have a <b>NC_GLOBAL</b> tag prefixed.<p>
 <li>Dataset metadata have their <b>variable name</b> prefixed.<p>
 <li>Each prefix is followed by a <b>#</b> sign. <p>
 <li>The NetCDF attribute follows the form: <b>name=value</b>.<p>
@@ -304,7 +304,7 @@ The driver has undergone significant changes in GDAL 1.9.0, see NEWS file and <a
 <li><p>Added support for DEFLATE compression (reading and writing) and szip (reading) - requires NetCDF-4 support</p></li>
 <li><p>Added support for valid_range/valid_min/valid_max</p></li>
 <li><p>Proper handling of signed/unsigned byte data</p></li>
-<li><p>Added support for Create() function - enables to use netcdf directly with gdalwarp</p></li>
+<li><p>Added support for Create() function - enables to use NetCDF directly with gdalwarp</p></li>
 <li><p>Added support for CF two-dimensional coordinate variables (see <a href="http://cfconventions.org/1.6.html#idp5559280">CF Conventions</a>) via GDAL GEOLOCATION arrays (see <a href="https://trac.osgeo.org/gdal/wiki/rfc4_geolocate">RFC 4: Geolocation Arrays</a>) (GDAL >= 1.10)</p></li>
 </ul>
 
@@ -312,10 +312,10 @@ The driver has undergone significant changes in GDAL 1.9.0, see NEWS file and <a
 
 <ul>
 
-<li><p><b>FORMAT=[NC/NC2/NC4/NC4C]</b>: Set the netcdf file format to use, NC is the default. NC2 is normally supported by recent netcdf installations, but NC4 and NC4C are available if netcdf was compiled with NetCDF-4 (and HDF5) support. 
-<li><p><b>COMPRESS=[NONE/DEFLATE]</b>: Set the compression to use.  DEFLATE is only available if netcdf has been compiled with NetCDF-4 support. NC4C format is the default if DEFLATE compression is used.</p></li>
+<li><p><b>FORMAT=[NC/NC2/NC4/NC4C]</b>: Set the NetCDF file format to use, NC is the default. NC2 is normally supported by recent NetCDF installations, but NC4 and NC4C are available if NetCDF was compiled with NetCDF-4 (and HDF5) support.
+<li><p><b>COMPRESS=[NONE/DEFLATE]</b>: Set the compression to use.  DEFLATE is only available if NetCDF has been compiled with NetCDF-4 support. NC4C format is the default if DEFLATE compression is used.</p></li>
 <li><p><b>ZLEVEL=[1-9]</b>: Set the level of compression when using DEFLATE compression. A value of 9 is best, and 1 is least compression. The default is 1, which offers the best time/compression ratio.</p></li>
-<li><p><b>WRITE_BOTTOMUP=[YES/NO]</b>: Set the y-axis order for export, overriding the order detected by the driver. NetCDF files are usually assumed "bottom-up", contrary to GDAL's model which is "north up". This normally does not create a problem in the y-axis order, unless there is no y axis geo-referencing. Files without geo-referencing information will be exported in the netcdf default "bottom-up" order, and the contrary for files with geo-referencing. For import see Configuration O [...]
+<li><p><b>WRITE_BOTTOMUP=[YES/NO]</b>: Set the y-axis order for export, overriding the order detected by the driver. NetCDF files are usually assumed "bottom-up", contrary to GDAL's model which is "north up". This normally does not create a problem in the y-axis order, unless there is no y axis geo-referencing. Files without geo-referencing information will be exported in the NetCDF default "bottom-up" order, and the contrary for files with geo-referencing. For import see Configuration O [...]
 <li><p><b>WRITE_GDAL_TAGS=[YES/NO]</b>: Define if GDAL tags used for georeferencing (spatial_ref and GeoTransform) should be exported, in addition to CF tags. Not all information is stored in the CF tags (such as named datums and EPSG codes), therefore the driver exports these variables by default.  In import the CF "grid_mapping" variable takes precedence and the GDAL tags are used if they do not conflict with CF metadata.</p></li>
 <li><p><b>WRITE_LONLAT=[YES/NO/IF_NEEDED]</b>: Define if CF lon/lat variables are written to file. Default is YES for geographic SRS and NO for projected SRS. This is normally not necessary for projected SRS as GDAL and many applications use the X/Y dimension variables and CF projection information.  Use of IF_NEEDED option creates lon/lat variables if the projection is not part of the CF-1.5 standard.</p></li>
 <li><p><b>TYPE_LONLAT=[float/double]</b>: Set the variable type to use for lon/lat variables. Default is double for geographic SRS and float for projected SRS. If lon/lat variables are written for a projected SRS, the file is considerably large (each variable uses X*Y space), therefore TYPE_LONLAT=float and COMPRESS=DEFLATE are advisable in order to save space.</p></li>
@@ -331,15 +331,15 @@ The driver has undergone significant changes in GDAL 1.9.0, see NEWS file and <a
 
 <h2>Driver building</h2>
 
-This driver is compiled with the UNIDATA netCDF library.<p>
+This driver is compiled with the UNIDATA NetCDF library.<p>
 
-You need to download or compile the netCDF library before configuring  GDAL with netCDF support. <p>
-
-See <a href="http://trac.osgeo.org/gdal/wiki/NetCDF">NetCDF GDAL wiki</a> for build instructions and information regarding HDF4, NetCDF-4 and HDF5. 
+You need to download or compile the NetCDF library before configuring GDAL with NetCDF support. <p>
 
+See <a href="http://trac.osgeo.org/gdal/wiki/NetCDF">NetCDF GDAL wiki</a> for build instructions and information regarding HDF4, NetCDF-4 and HDF5.
 
 <h2>See Also:</h2>
 <ul>
+<li><a href="frmts_netcdf_vector.html">Vector side of the netCDF driver.</a></li>
 <li>
 <a href="http://cf-pcmdi.llnl.gov/documents/cf-conventions/1.5/cf-conventions.html">NetCDF CF-1.5 convention</a>
 <li><a href="http://www.unidata.ucar.edu/downloads/netcdf/index.jsp">NetCDF compiled libraries</a>
@@ -348,7 +348,6 @@ See <a href="http://trac.osgeo.org/gdal/wiki/NetCDF">NetCDF GDAL wiki</a> for bu
 <hr>
 <a href="formats_list.html">Full list of GDAL Raster Formats</a>
 
-
 </body>
 </html>
 
diff --git a/frmts/netcdf/frmt_netcdf_vector.html b/frmts/netcdf/frmt_netcdf_vector.html
new file mode 100644
index 0000000..733ee97
--- /dev/null
+++ b/frmts/netcdf/frmt_netcdf_vector.html
@@ -0,0 +1,293 @@
+<html>
+<head>
+<title>NetCDF network Common Data Form - Vector</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>NetCDF: Network Common Data Form - Vector</h1>
+
+Starting with GDAL 2.1, the netCDF driver support read and write (creation from
+scratch and append operations) to vector datasets (you can find documentation for the
+<a href="frmt_netcdf.html">raster side</a>)<p>
+
+NetCDF is an interface for
+array-oriented data access and is used for representing scientific data.<p>
+
+The driver handles the "point" and "profile"
+<a href="http://cfconventions.org/cf-conventions/v1.6.0/cf-conventions.html#_features_and_feature_types">feature types</a>
+of the CF 1.6 convention. It also supports a more custom approach for non-point
+geometries.<p>
+
+<h2>Mapping of concepts</h2>
+
+<h3>Field types</h3>
+
+On creation of netCDF files, the mapping between OGR field types and netCDF type is the following :<p>
+
+<table border="1">
+<tr><th>OGR field type</th>     <th>netCDF type</th></tr>
+<tr><td>String(1)</td>          <td>char</td></tr>
+<tr><td>String</td>             <td>char (bi-dimensional), or string for NC4</td></tr>
+<tr><td>Integer</td>            <td>int</td></tr>
+<tr><td>Integer(Boolean)</td>   <td>byte</td></tr>
+<tr><td>Integer(Int16)</td>     <td>short</td></tr>
+<tr><td>Integer64</td>          <td>int64 for NC4, or double for NC3 as a fallback</td></tr>
+<tr><td>Real</td>               <td>double</td></tr>
+<tr><td>Real(Float32)</td>      <td>float</td></tr>
+<tr><td>Date</td>               <td>int (with units="days since 1970-1-1")</td></tr>
+<tr><td>DateTime</td>           <td>double (with units="seconds since 1970-1-1 0:0:0")</td></tr>
+</table>
+
+<p>The driver also writes the following attributes for each OGR fields / netCDF variables.</p>
+<ul>
+<li><i>ogr_field_name</i>: OGR field name (useful if the netCDF variable name is different, due to collision)</li>
+<li><i>ogr_field_type</i>: OGR field type (such as String,Integer,Date,DateTime,etc...)</li>
+<li><i>ogr_field_width</i>: OGR field width. Only set if it is non-zero, except for strings</li>
+<li><i>ogr_field_precision</i>: OGR field precision. Only set if it is non-zero</li>
+</ul>
+<p>
+They are written by default (unless the <a href="#WRITE_GDAL_TAGS">WRITE_GDAL_TAGS</a>
+dataset creation option is set to NO). They are not required for reading, but
+may help to better identify field characteristics
+<p>
+On reading, the mapping is the following :
+</p>
+
+<table border="1">
+<tr><th>netCDF type</th>        <th>OGR field type</th></tr>
+<tr><td>byte</td>               <td>Integer</td></tr>
+<tr><td>ubyte (NC4 only)</td>   <td>Integer</td></tr>
+<tr><td>char (mono dimensional) <td>String(1)</td></tr>
+<tr><td>char (bi dimensional)   <td>String</td></tr>
+<tr><td>string (NC4 only)       <td>String</td></tr>
+<tr><td>short</td>              <td>Integer(Int16)</td></tr>
+<tr><td>ushort (NC4 only)</td>  <td>Integer</td></tr>
+<tr><td>int</td>                <td>Integer</td></tr>
+<tr><td>int or double (with units="days since 1970-1-1")</td><td>Date</td>
+<tr><td>uint (NC4 only)</td>    <td>Integer64</td></tr>
+<tr><td>int64 (NC4 only)</td>   <td>Integer64</td></tr>
+<tr><td>uint64 (NC4 only)</td>  <td>Real</td></tr>
+<tr><td>float</td>              <td>Real(Float32)</td>
+<tr><td>double</td>             <td>Real</td>
+<tr><td>double (with units="seconds since 1970-1-1 0:0:0")</td><td>DateTime</td>
+</table>
+
+<h3>Layers</h3>
+
+<p>
+Generally a single netCDF file is viewed as a single OGR layer, provided that
+it contains only mon-dimensional variables, indexed by the same dimension (or
+bi-dimensional variables of type char). For netCDF v4 files with multiple groups,
+each group may be seen as a separate OGR layer.</p>
+
+<p>On writing, the <a href="#MULTIPLE_LAYERS">MULTIPLE_LAYERS</a> dataset creation
+option can be used to control whether multiple layers is disabled, or if multiple
+layers should go in separate files, or separate groups.</p>
+
+<h3>Strings</h3>
+
+<p>Variable length strings are not natively supported in netCDF v3 format. To work around that,
+OGR uses bi-dimensional char variables, whose first dimension is the record dimension,
+and second dimension the maximum width of the string. By default, OGR implements a
+"auto-grow" mode in writing, where the maximum width of the variable used to store a
+OGR string field is extended when needed. Note that this leads to a full rewrite of
+already written records : this is transparent for the user, but can slow down the
+creation process in non-linear ways. A similar mechanism is used to handle layers
+with geometry types other than point to store the ISO WKT representation of the geometries.</p>
+
+<p>When using a netCDF v4 output format (NC4), strings will be by default written
+as netCDF v4 variable length strings.</p>
+
+<h3>Geometry</h3>
+
+<p>Layers with a geometry type of Point or Point25D will cause the implicit creation of
+x,y(,z) variables for projected coordinate system, or lon,lat(,z) variables for
+geographic coordinate systems. For other geometry type, a variable "ogc_wkt" (
+bi-dimensional char for NC3 output, or string for NC4 output) is created and
+used to store the geometry as a ISO WKT string.</p>
+
+<h3><a name="profile">"Profile" feature type</a></h3>
+
+<p>The driver can handle "profile" feature type, i.e. phenomenons that happen at
+a few positions along a vertical line at a fixed horizontal position. In that representation,
+some variables are indexed by the profile, and others by the observation.<p>
+
+<p>More precisely, the driver supports reading and writing profiles organized accordingly
+with the "<a href="http://cfconventions.org/cf-conventions/v1.6.0/cf-conventions.html#_indexed_ragged_array_representation_of_profiles">Indexed ragged array representation</a>"
+of profiles.</p>
+
+<p>On reading, the driver will collect values of variables indexed by the profile
+dimension and expose them as long as variables indexed by the observation dimension,
+based on a variable such as "parentIndex" with an attribute "instance_dimension"
+pointing to the profile dimension.</p>
+
+<p>On writing, the <a href="#FEATURE_TYPE">FEATURE_TYPE</a>=PROFILE layer creation
+option must be set and the driver will need to be instructed which OGR fields are indexed
+either by the profile or by the observation dimension. The list of fields indexed by the
+profile can be specified with the <a href="#PROFILE_VARIABLES">PROFILE_VARIABLES</a>
+layer creation options (other fields are assumed to be indexed by the observation dimension).
+Fields indexed by the profile are the horizontal geolocation (created implicitly), and
+other user attributes such as the location name, etc. Care should be taken into selecting
+which variables are indexed by the profile dimension: given 2 OGR features (taking into
+account only the variables indexed by the profile dimension), if they have different
+values for such variables, they will be considered to belong to different profiles.</p>
+
+<p>In the below example, the station_name and time variables may be indexed by the
+profile dimension (the geometry is assumed to be also indexed by the profile dimension),
+since all records that have the same value for one of those variables have same values
+for the other ones, whereas temparature and Z should be indexed by the default dimension.
+</p>
+
+<p>
+<table border="1">
+<tr><th>station_name</th> <th>time</th>                  <th>geometry</th>            <th>temperature</th> <th>Z</th></tr>
+<tr><td>Paris</td>        <td>2016-03-01T00:00:00Z</td>  <td>POINT (2 49)</td>        <td>25</td>          <td>100</td></tr>
+<tr><td>Vancouver</td>    <td>2016-04-01T12:00:00Z</td>  <td>POINT (-123 49.25)</td>  <td>5</td>           <td>100</td></tr>
+<tr><td>Paris</td>        <td>2016-03-01T00:00:00Z</td>  <td>POINT (2 49)</td>        <td>3</td>           <td>500</td></tr>
+<tr><td>Vancouver</td>    <td>2016-04-01T12:00:00Z</td>  <td>POINT (-123 49.25)</td>  <td>-15</td>         <td>500</td></tr>
+</table>
+</p>
+
+<p>An integer field, with the name of the profile dimension (whose default name is "profile", which
+can be altered with the <a href="#PROFILE_DIM_NAME">PROFILE_DIM_NAME</a> layer creation option),
+will be used to store the automatically computed id of profile sites (unless a integer OGR field with the
+same name exits).</p>
+
+<p>The size of the profile dimension defaults to 100 for non-NC4 output format,
+and is extended automatically in case of additional profiles (with similar performance
+issues as growing strings). For NC4 output format, the profile dimension is of
+unlimited size by default.</p>
+
+<h2>Dataset creation options</h2>
+
+<ul>
+<li><b>FORMAT</b>=NC/NC2/NC4/NC4C: netCDF format. NC is the classic netCDF format
+(compatible of netCDF v3.X and 4.X libraries). NC2 is the extension of NC for
+files larger than 4 GB. NC4 is the netCDF v4 format, using a HDF5 container, offering
+new capabilities (new types, concept of groups, etc...) only available in netCDF v4 library.
+NC4C is a restriction of the NC4 format to the concepts supported by the classic netCDF
+format. Default is NC.</li>
+<li><b><a name="WRITE_GDAL_TAGS">WRITE_GDAL_TAGS</a></b>=YES/NO: Whether to write GDAL specific information as
+netCDF attributes. Default is YES.</li>
+<li><b><a name="MULTIPLE_LAYERS">MULTIPLE_LAYERS</a></b>=NO/SEPARATE_FILES/SEPARATE_GROUPS. Default is NO, i.e a
+dataset can contain only a single OGR layer. SEPARATE_FILES can be used to put the content
+of each OGR layer in a single netCDF file, in which case the name passed at dataset
+creation is used as the directory, and the layer name is used as the basename of the netCDF
+file. SEPARATE_GROUPS may be used when FORMAT=NC4 to put each OGR layer in a separate
+netCDF group, inside the same file.</li>
+<li><b>CONFIG_FILE</b>=string. Path to a <a href="#XML_config">XML configuration file</a>
+(or its content inlined) for precise control of the output</li>
+</ul>
+
+<h2>Layer creation options</h2>
+
+<ul>
+<li><b>RECORD_DIM_NAME</b>=string. Name of the unlimited dimension that index features.
+Defaults to "record"</li>
+<li><b>STRING_DEFAULT_WIDTH</b>=int. Default width of strings (when using
+bi-dimensional char variables). Default is 10 in autogrow mode, 80 otherwise.</li>
+<li><b>USE_STRING_IN_NC4</b>=YES/NO. Whether to use NetCDF string type for strings
+in NC4 format. If NO, bidimensional char variable are used. Default to YES when
+FORMAT=NC4.</li>
+<li><b>WKT_DEFAULT_WIDTH</b>=int. Default width of WKT strings (when using
+bi-dimensional char variables). Default is 1000 in autogrow mode, 10000 otherwise.</li>
+<li><b>AUTOGROW_STRINGS</b>=YES/NO. Whether to auto-grow string fields of non-fixed width,
+or ogc_wkt special field, when serialized as bidimensional char variables.
+Default is YES. When set to NO, if the string is larger than its maximum initial
+width (set by STRING_DEFAULT_WIDTH), it is truncated. For a geometry, it is completely
+discarded.</li>
+<li><b><a name="FEATURE_TYPE">FEATURE_TYPE</a></b>=AUTO/POINT/PROFILE. Select the CF FeatureType. Defaults to
+AUTO where FeatureType=Point is selected if the layer geometry type is Point, otherwise
+the custom approach involving the "ogc_wkt" field is used. Can be set to <a href="#profile">PROFILE</a> so
+as to select the creation of an indexed ragged array representation of profiles.</li>
+<li><b><a name="PROFILE_DIM_NAME">PROFILE_DIM_NAME</a></b>=string. Name of the
+profile dimension and variable. Defaults to "profile". Only used when FEATURE_TYPE=PROFILE.</li>
+<li><b>PROFILE_DIM_INIT_SIZE</b>=int or string. Initial size of profile dimension,
+or UNLIMITED for NC4 files. Defaults to 100 when FORMAT != NC4 and to UNLIMITED when
+FORMAT = NC4. Only used when FEATURE_TYPE=PROFILE.</li>
+<li><b><a name="PROFILE_VARIABLES">PROFILE_VARIABLES</a></b>=string. Comma separated
+list of field names that must be indexed by the profile dimension. Only used when FEATURE_TYPE=PROFILE.</li>
+</ul>
+
+<h2><a name="XML_config">XML configuration file</a></h2>
+
+<p>
+A XML configuration file conforming to the following
+<a href="https://svn.osgeo.org/gdal/trunk/gdal/data/netcdf_config.xsd">schema</a>
+can be used for very precise control on the output format, in particular to set
+all needed attributes (such as units) to conform to the
+<a href="http://cfconventions.org/cf-conventions/v1.6.0/cf-conventions.html">NetCDF CF-1.6 convention</a>.</p>
+
+<p>It has been designed in particular, but not exclusively, to be usable in use cases involving the
+<a href="http://mapserver.org/output/ogr_output.html">MapServer OGR output</a>.</p>
+
+<p>Such a file can be used to :
+<ul>
+<li>set dataset and layer creation options.</li>
+<li>set global netCDF attributes.</li>
+<li>map OGR field names to netCDF variable names.</li>
+<li>set netCDF attributes attached to netCDF variables.</li>
+</ul>
+</p>
+
+<p>The scope of effect is either globally, when elements are defined as direct
+children of the root <Configuration> node, or specifically to a given layer,
+when defined as children of a <Layer> node.<p>
+
+<p>The filename is specified with the CONFIG_FILE dataset creation option. Alternatively,
+the content of the file can be specifid inline as the value of the option (it must
+then begin strictly with the "<Configuration" characters)</p>
+
+<p>The following example shows all possibilities and precedence rules:</p>
+<pre>
+<Configuration>
+    <DatasetCreationOption name="FORMAT" value="NC4"/>
+    <DatasetCreationOption name="MULTIPLE_LAYERS" value="SEPARATE_GROUPS"/>
+    <LayerCreationOption name="RECORD_DIM_NAME" value="observation"/>
+<!-- applies to all layers -->
+    <Attribute name="copyright" value="Copyright(C) 2016 Example"/>
+    <Field name="weight">  <!-- edit user field/variable -->
+        <Attribute name="units" value="kg"/> <!-- sets a unit -->
+        <Attribute name="maximum" value="10" type="double"/>
+    </Field>
+    <Field netcdf_name="z"> <!-- edit predefined variable -->
+        <Attribute name="long_name" value="Elevation"/> <!-- overrides the default long_name of the z variable -->
+    </Field>
+<!-- start of layer specific definitions -->
+    <Layer name="1st_layer" netcdf_name="firstlayer"> <!-- OGR layer "1st_layer" is renamed as "firstlayer" netCDF group -->
+        <LayerCreationOption name="FEATURE_TYPE" value="POINT"/>
+        <Attribute name="copyright" value="Public domain"/> <!-- override global one -->
+        <Attribute name="description" value="This is my first layer"/> <!-- additional attribute -->
+        <Field name="1st_field" netcdf_name="firstfield"/> <!-- rename OGR field "1st_field" as the "firstfield" netCDF variable -->
+        <Field name="weight"/> <!-- cancel above global customization -->
+        <Field netcdf_name="lat"> <!-- edit predefined variable -->
+            <Attribute name="long_name" value=""/> <!-- remove predefined attribute -->
+        </Field>
+    </Layer>
+    <Layer name="sounding">
+        <LayerCreationOption name="FEATURE_TYPE" value="PROFILE"/>
+        <Field name="station_name" main_dim="profile"/> <!-- the corresponding netCDF variable will be indexed against the profile dimension, instead of the observation dimension -->
+        <Field name="time" main_dim="profile"/> <!-- the corresponding netCDF variable will be indexed against the profile dimension, instead of the observation dimension -->
+    </Layer>
+</Configuration>
+</pre>
+
+<p>The effect on the output can be checked by running the <b>ncdump</b> utility</p>
+
+<h2>See Also:</h2>
+<ul>
+<li><a href="frmts_netcdf.html">Raster side of the netCDF driver.</a></li>
+<li><a href="http://cfconventions.org/cf-conventions/v1.6.0/cf-conventions.html">NetCDF CF-1.6 convention</a></li>
+<li><a href="http://www.unidata.ucar.edu/downloads/netcdf/index.jsp">NetCDF compiled libraries</a></li>
+<li><a href="http://www.unidata.ucar.edu/software/netcdf/docs/">NetCDF Documentation</a></li>
+</ul>
+
+<h2>Credits</h2>
+
+<p>Development of the read/write vector capabilities for netCDF was funded by
+<a href="https://www.ec.gc.ca/meteo-weather/">Meteorological Service of Canada</a>
+and <a href="http://woudc.org">World Ozone and Ultraviolet Radiation Data Centre</a>.</p>
+
+</body>
+</html>
diff --git a/frmts/netcdf/gmtdataset.cpp b/frmts/netcdf/gmtdataset.cpp
index 0148456..3b74888 100644
--- a/frmts/netcdf/gmtdataset.cpp
+++ b/frmts/netcdf/gmtdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmtdataset.cpp 28785 2015-03-26 20:46:45Z goatbar $
+ * $Id: gmtdataset.cpp 33794 2016-03-26 13:19:07Z goatbar $
  *
  * Project:  netCDF read/write Driver
  * Purpose:  GDAL bindings over netCDF library for GMT Grids.
@@ -28,12 +28,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
+#include "cpl_multiproc.h"
 #include "gdal_frmts.h"
+#include "gdal_pam.h"
 #include "netcdf.h"
-#include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: gmtdataset.cpp 28785 2015-03-26 20:46:45Z goatbar $");
+CPL_CVSID("$Id: gmtdataset.cpp 33794 2016-03-26 13:19:07Z goatbar $");
 
 extern CPLMutex *hNCMutex; /* shared with netcdf. See netcdfdataset.cpp */
 
@@ -53,8 +53,9 @@ class GMTDataset : public GDALPamDataset
   public:
     int         cdfid;
 
+                GMTDataset() : z_id(0), cdfid(0) { }
 		~GMTDataset();
-    
+
     static GDALDataset *Open( GDALOpenInfo * );
 
     CPLErr 	GetGeoTransform( double * padfTransform );
@@ -73,8 +74,9 @@ class GMTRasterBand : public GDALPamRasterBand
 
   public:
 
-    		GMTRasterBand( GMTDataset *poDS, int nZId, int nBand );
-    
+    GMTRasterBand( GMTDataset *poDS, int nZId, int nBand );
+    virtual ~GMTRasterBand() {}
+
     virtual CPLErr IReadBlock( int, int, void * );
 };
 
@@ -83,23 +85,23 @@ class GMTRasterBand : public GDALPamRasterBand
 /*                           GMTRasterBand()                            */
 /************************************************************************/
 
-GMTRasterBand::GMTRasterBand( GMTDataset *poDS, int nZId, int nBand )
+GMTRasterBand::GMTRasterBand( GMTDataset *poDSIn, int nZIdIn, int nBandIn )
 
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
-    this->nZId = nZId;
-    
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
+    this->nZId = nZIdIn;
+
     nBlockXSize = poDS->GetRasterXSize();
     nBlockYSize = 1;
 
 /* -------------------------------------------------------------------- */
 /*      Get the type of the "z" variable, our target raster array.      */
 /* -------------------------------------------------------------------- */
-    if( nc_inq_var( poDS->cdfid, nZId, NULL, &nc_datatype, NULL, NULL,
+    if( nc_inq_var( poDSIn->cdfid, nZId, NULL, &nc_datatype, NULL, NULL,
                     NULL ) != NC_NOERR )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Error in nc_var_inq() on 'z'." );
         return;
     }
@@ -117,8 +119,8 @@ GMTRasterBand::GMTRasterBand( GMTDataset *poDS, int nZId, int nBand )
     else
     {
         if( nBand == 1 )
-            CPLError( CE_Warning, CPLE_AppDefined, 
-                      "Unsupported GMT datatype (%d), treat as Float32.", 
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Unsupported GMT datatype (%d), treat as Float32.",
                       (int) nc_datatype );
         eDataType = GDT_Float32;
     }
@@ -131,46 +133,45 @@ GMTRasterBand::GMTRasterBand( GMTDataset *poDS, int nZId, int nBand )
 CPLErr GMTRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff, int nBlockYOff,
                                   void * pImage )
 {
-    size_t start[2], edge[2];
-    int    nErr = NC_NOERR;
-    int    cdfid = ((GMTDataset *) poDS)->cdfid;
-    
+
     CPLMutexHolderD(&hNCMutex);
 
-    start[0] = nBlockYOff * nBlockXSize;
-    edge[0] = nBlockXSize;
+    size_t start[2] = {static_cast<size_t>(nBlockYOff * nBlockXSize), 0};
+    size_t edge[2] = {static_cast<size_t>(nBlockXSize), 0};
 
+    int nErr = NC_NOERR;
+    int cdfid = ((GMTDataset *) poDS)->cdfid;
     if( eDataType == GDT_Byte )
-        nErr = nc_get_vara_uchar( cdfid, nZId, start, edge, 
+        nErr = nc_get_vara_uchar( cdfid, nZId, start, edge,
                                   (unsigned char *) pImage );
     else if( eDataType == GDT_Int16 )
-        nErr = nc_get_vara_short( cdfid, nZId, start, edge, 
+        nErr = nc_get_vara_short( cdfid, nZId, start, edge,
                                   (short int *) pImage );
     else if( eDataType == GDT_Int32 )
     {
         if( sizeof(long) == 4 )
-            nErr = nc_get_vara_long( cdfid, nZId, start, edge, 
+            nErr = nc_get_vara_long( cdfid, nZId, start, edge,
                                      (long *) pImage );
         else
-            nErr = nc_get_vara_int( cdfid, nZId, start, edge, 
+            nErr = nc_get_vara_int( cdfid, nZId, start, edge,
                                     (int *) pImage );
     }
     else if( eDataType == GDT_Float32 )
-        nErr = nc_get_vara_float( cdfid, nZId, start, edge, 
+        nErr = nc_get_vara_float( cdfid, nZId, start, edge,
                                   (float *) pImage );
     else if( eDataType == GDT_Float64 )
-        nErr = nc_get_vara_double( cdfid, nZId, start, edge, 
+        nErr = nc_get_vara_double( cdfid, nZId, start, edge,
                                    (double *) pImage );
 
     if( nErr != NC_NOERR )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "GMT scanline fetch failed: %s", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "GMT scanline fetch failed: %s",
                   nc_strerror( nErr ) );
         return CE_Failure;
     }
-    else
-        return CE_None;
+
+    return CE_None;
 }
 
 /************************************************************************/
@@ -186,6 +187,7 @@ CPLErr GMTRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff, int nBlockYOff,
 GMTDataset::~GMTDataset()
 
 {
+    CPLMutexHolderD(&hNCMutex);
     FlushCache();
     nc_close (cdfid);
 }
@@ -214,27 +216,28 @@ GDALDataset *GMTDataset::Open( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->fpL == NULL || poOpenInfo->nHeaderBytes < 50 )
         return NULL;
 
-    if( poOpenInfo->pabyHeader[0] != 'C' 
-        || poOpenInfo->pabyHeader[1] != 'D' 
-        || poOpenInfo->pabyHeader[2] != 'F' 
+    if( poOpenInfo->pabyHeader[0] != 'C'
+        || poOpenInfo->pabyHeader[1] != 'D'
+        || poOpenInfo->pabyHeader[2] != 'F'
         || poOpenInfo->pabyHeader[3] != 1 )
         return NULL;
-    
+
     CPLMutexHolderD(&hNCMutex);
 
 /* -------------------------------------------------------------------- */
 /*      Try opening the dataset.                                        */
 /* -------------------------------------------------------------------- */
-    int cdfid, nm_id, dim_count, z_id;
-
+    int cdfid;
     if( nc_open( poOpenInfo->pszFilename, NC_NOWRITE, &cdfid ) != NC_NOERR )
         return NULL;
 
-    if( nc_inq_varid( cdfid, "dimension", &nm_id ) != NC_NOERR 
+    int nm_id;
+    int z_id;
+    if( nc_inq_varid( cdfid, "dimension", &nm_id ) != NC_NOERR
         || nc_inq_varid( cdfid, "z", &z_id ) != NC_NOERR )
     {
 #ifdef notdef
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "%s is a GMT file, but not in GMT configuration.",
                   poOpenInfo->pszFilename );
 #endif
@@ -242,48 +245,51 @@ GDALDataset *GMTDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
+    int dim_count;
     if( nc_inq_ndims( cdfid, &dim_count ) != NC_NOERR || dim_count < 2 )
     {
         nc_close( cdfid );
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
         nc_close( cdfid );
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The GMT driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
-/*      Create a corresponding GDALDataset.                             */
+/*      Get dimensions.  If we can't find this, then this is a          */
+/*      GMT file, but not a normal grid product.                     */
 /* -------------------------------------------------------------------- */
-    GMTDataset 	*poDS;
+    int    nm[2];
+    size_t start[2] = {0, 0};
+    size_t edge[2] = {2, 0};
+
+    nc_get_vara_int(cdfid, nm_id, start, edge, nm);
+    if( !GDALCheckDatasetDimensions(nm[0], nm[1]) )
+    {
+        nc_close( cdfid );
+        return NULL;
+    }
 
+/* -------------------------------------------------------------------- */
+/*      Create a corresponding GDALDataset.                             */
+/* -------------------------------------------------------------------- */
     CPLReleaseMutex(hNCMutex);  // Release mutex otherwise we'll deadlock with GDALDataset own mutex
-    poDS = new GMTDataset();
+
+    GMTDataset 	*poDS = new GMTDataset();
     CPLAcquireMutex(hNCMutex, 1000.0);
 
     poDS->cdfid = cdfid;
     poDS->z_id = z_id;
-    
-/* -------------------------------------------------------------------- */
-/*      Get dimensions.  If we can't find this, then this is a          */
-/*      GMT file, but not a normal grid product.                     */
-/* -------------------------------------------------------------------- */
-    size_t start[2], edge[2];
-    int    nm[2];
-
-    start[0] = 0;
-    edge[0] = 2;
 
-    nc_get_vara_int(cdfid, nm_id, start, edge, nm);
-    
     poDS->nRasterXSize = nm[0];
     poDS->nRasterYSize = nm[1];
 
@@ -291,11 +297,13 @@ GDALDataset *GMTDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Fetch "z" attributes scale_factor, add_offset, and              */
 /*      node_offset.                                                    */
 /* -------------------------------------------------------------------- */
-    double scale_factor=1.0, add_offset=0.0;
-    int node_offset = 1;
-
+    double scale_factor=1.0;
     nc_get_att_double( cdfid, z_id, "scale_factor", &scale_factor );
+
+    double add_offset=0.0;
     nc_get_att_double( cdfid, z_id, "add_offset", &add_offset );
+
+    int node_offset = 1;
     nc_get_att_int( cdfid, z_id, "node_offset", &node_offset );
 
 /* -------------------------------------------------------------------- */
@@ -303,39 +311,40 @@ GDALDataset *GMTDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     int x_range_id, y_range_id;
 
-    if( nc_inq_varid (cdfid, "x_range", &x_range_id) == NC_NOERR 
+    if( nc_inq_varid (cdfid, "x_range", &x_range_id) == NC_NOERR
         && nc_inq_varid (cdfid, "y_range", &y_range_id) == NC_NOERR )
     {
-        double x_range[2], y_range[2];
-
+        double x_range[2];
         nc_get_vara_double( cdfid, x_range_id, start, edge, x_range );
+
+        double y_range[2];
         nc_get_vara_double( cdfid, y_range_id, start, edge, y_range );
 
         // Pixel is area
         if( node_offset == 1 )
         {
             poDS->adfGeoTransform[0] = x_range[0];
-            poDS->adfGeoTransform[1] = 
+            poDS->adfGeoTransform[1] =
                 (x_range[1] - x_range[0]) / poDS->nRasterXSize;
             poDS->adfGeoTransform[2] = 0.0;
             poDS->adfGeoTransform[3] = y_range[1];
             poDS->adfGeoTransform[4] = 0.0;
-            poDS->adfGeoTransform[5] = 
+            poDS->adfGeoTransform[5] =
                 (y_range[0] - y_range[1]) / poDS->nRasterYSize;
         }
 
-        // Pixel is point - offset by half pixel. 
-        else /* node_offset == 0 */ 
+        // Pixel is point - offset by half pixel.
+        else /* node_offset == 0 */
         {
-            poDS->adfGeoTransform[1] = 
+            poDS->adfGeoTransform[1] =
                 (x_range[1] - x_range[0]) / (poDS->nRasterXSize-1);
-            poDS->adfGeoTransform[0] = 
+            poDS->adfGeoTransform[0] =
                 x_range[0] - poDS->adfGeoTransform[1]*0.5;
             poDS->adfGeoTransform[2] = 0.0;
             poDS->adfGeoTransform[4] = 0.0;
-            poDS->adfGeoTransform[5] = 
+            poDS->adfGeoTransform[5] =
                 (y_range[0] - y_range[1]) / (poDS->nRasterYSize-1);
-            poDS->adfGeoTransform[3] = 
+            poDS->adfGeoTransform[3] =
                 y_range[1] - poDS->adfGeoTransform[5]*0.5;
         }
     }
@@ -393,9 +402,6 @@ GMTCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Figure out general characteristics.                             */
 /* -------------------------------------------------------------------- */
-    nc_type nc_datatype;
-    GDALRasterBand *poBand;
-    int nXSize, nYSize;
 
     CPLMutexHolderD(&hNCMutex);
 
@@ -406,11 +412,13 @@ GMTCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         return NULL;
     }
 
-    poBand = poSrcDS->GetRasterBand(1);
+    GDALRasterBand *poBand = poSrcDS->GetRasterBand(1);
+
+    const int nXSize = poSrcDS->GetRasterXSize();
+    const int nYSize = poSrcDS->GetRasterYSize();
+
+    nc_type nc_datatype;
 
-    nXSize = poSrcDS->GetRasterXSize();
-    nYSize = poSrcDS->GetRasterYSize();
-    
     if( poBand->GetRasterDataType() == GDT_Int16 )
         nc_datatype = NC_SHORT;
     else if( poBand->GetRasterDataType() == GDT_Int32 )
@@ -421,7 +429,7 @@ GMTCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         nc_datatype = NC_DOUBLE;
     else if( bStrict )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Band data type %s not supported in GMT, giving up.",
                   GDALGetDataTypeName( poBand->GetRasterDataType() ) );
         return NULL;
@@ -432,38 +440,37 @@ GMTCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         nc_datatype = NC_INT;
     else if( poBand->GetRasterDataType() == GDT_UInt32 )
         nc_datatype = NC_INT;
-    else 
+    else
         nc_datatype = NC_FLOAT;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Establish bounds from geotransform.                             */
 /* -------------------------------------------------------------------- */
     double adfGeoTransform[6];
-    double dfXMax, dfYMin;
 
     poSrcDS->GetGeoTransform( adfGeoTransform );
-    
+
     if( adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0 )
     {
-        CPLError( bStrict ? CE_Failure : CE_Warning, CPLE_AppDefined, 
+        CPLError( bStrict ? CE_Failure : CE_Warning, CPLE_AppDefined,
                   "Geotransform has rotational coefficients not supported in GMT." );
         if( bStrict )
             return NULL;
     }
 
-    dfXMax = adfGeoTransform[0] + adfGeoTransform[1] * nXSize;
-    dfYMin = adfGeoTransform[3] + adfGeoTransform[5] * nYSize;
-    
+    const double dfXMax = adfGeoTransform[0] + adfGeoTransform[1] * nXSize;
+    const double dfYMin = adfGeoTransform[3] + adfGeoTransform[5] * nYSize;
+
 /* -------------------------------------------------------------------- */
 /*      Create base file.                                               */
 /* -------------------------------------------------------------------- */
-    int cdfid, err;
+    int cdfid;
 
-    err = nc_create (pszFilename, NC_CLOBBER,&cdfid);
+    int err = nc_create (pszFilename, NC_CLOBBER, &cdfid);
     if( err != NC_NOERR )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "nc_create(%s): %s", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "nc_create(%s): %s",
                   pszFilename, nc_strerror( err ) );
         return NULL;
     }
@@ -471,43 +478,45 @@ GMTCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Define the dimensions and so forth.                             */
 /* -------------------------------------------------------------------- */
-    int side_dim, xysize_dim, dims[1];
-    int x_range_id, y_range_id, z_range_id, inc_id, nm_id, z_id;
+    int side_dim, xysize_dim;
+
+    CPL_IGNORE_RET_VAL(nc_def_dim(cdfid, "side", 2, &side_dim));
+    CPL_IGNORE_RET_VAL(nc_def_dim(cdfid, "xysize", (int) (nXSize * nYSize), &xysize_dim));
+
+    int dims[1] = {side_dim};
 
-    nc_def_dim(cdfid, "side", 2, &side_dim);
-    nc_def_dim(cdfid, "xysize", (int) (nXSize * nYSize), &xysize_dim);
+    int x_range_id, y_range_id, z_range_id;
+    CPL_IGNORE_RET_VAL(nc_def_var (cdfid, "x_range", NC_DOUBLE, 1, dims, &x_range_id));
+    CPL_IGNORE_RET_VAL(nc_def_var (cdfid, "y_range", NC_DOUBLE, 1, dims, &y_range_id));
+    CPL_IGNORE_RET_VAL(nc_def_var (cdfid, "z_range", NC_DOUBLE, 1, dims, &z_range_id));
 
-    dims[0]		= side_dim;
-    nc_def_var (cdfid, "x_range", NC_DOUBLE, 1, dims, &x_range_id);
-    nc_def_var (cdfid, "y_range", NC_DOUBLE, 1, dims, &y_range_id);
-    nc_def_var (cdfid, "z_range", NC_DOUBLE, 1, dims, &z_range_id);
-    nc_def_var (cdfid, "spacing", NC_DOUBLE, 1, dims, &inc_id);
-    nc_def_var (cdfid, "dimension", NC_LONG, 1, dims, &nm_id);
+    int inc_id, nm_id, z_id;
+    CPL_IGNORE_RET_VAL(nc_def_var (cdfid, "spacing", NC_DOUBLE, 1, dims, &inc_id));
+    CPL_IGNORE_RET_VAL(nc_def_var (cdfid, "dimension", NC_LONG, 1, dims, &nm_id));
 
     dims[0]		= xysize_dim;
-    nc_def_var (cdfid, "z", nc_datatype, 1, dims, &z_id);
+    CPL_IGNORE_RET_VAL(nc_def_var (cdfid, "z", nc_datatype, 1, dims, &z_id));
 
 /* -------------------------------------------------------------------- */
 /*      Assign attributes.                                              */
 /* -------------------------------------------------------------------- */
-    double default_scale = 1.0;
-    double default_offset = 0.0;
-    int default_node_offset = 1; // pixel is area
-
-    nc_put_att_text (cdfid, x_range_id, "units", 7, "meters");
-    nc_put_att_text (cdfid, y_range_id, "units", 7, "meters");
-    nc_put_att_text (cdfid, z_range_id, "units", 7, "meters");
+    CPL_IGNORE_RET_VAL(nc_put_att_text (cdfid, x_range_id, "units", 7, "meters"));
+    CPL_IGNORE_RET_VAL(nc_put_att_text (cdfid, y_range_id, "units", 7, "meters"));
+    CPL_IGNORE_RET_VAL(nc_put_att_text (cdfid, z_range_id, "units", 7, "meters"));
 
-    nc_put_att_double (cdfid, z_id, "scale_factor", NC_DOUBLE, 1, 
+    double default_scale = 1.0;
+    nc_put_att_double (cdfid, z_id, "scale_factor", NC_DOUBLE, 1,
                        &default_scale );
-    nc_put_att_double (cdfid, z_id, "add_offset", NC_DOUBLE, 1, 
+    double default_offset = 0.0;
+    nc_put_att_double (cdfid, z_id, "add_offset", NC_DOUBLE, 1,
                        &default_offset );
 
-    nc_put_att_int (cdfid, z_id, "node_offset", NC_LONG, 1, 
-                    &default_node_offset );
-    nc_put_att_text (cdfid, NC_GLOBAL, "title", 1, "");
-    nc_put_att_text (cdfid, NC_GLOBAL, "source", 1, "");
-	
+    int default_node_offset = 1; // pixel is area
+    CPL_IGNORE_RET_VAL(nc_put_att_int (cdfid, z_id, "node_offset", NC_LONG, 1,
+                    &default_node_offset ));
+    CPL_IGNORE_RET_VAL(nc_put_att_text (cdfid, NC_GLOBAL, "title", 1, ""));
+    CPL_IGNORE_RET_VAL(nc_put_att_text (cdfid, NC_GLOBAL, "source", 1, ""));
+
     /* leave define mode */
     nc_enddef (cdfid);
 
@@ -516,18 +525,13 @@ GMTCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
     double adfMinMax[2];
     GDALComputeRasterMinMax( (GDALRasterBandH) poBand, FALSE, adfMinMax );
-	
+
 /* -------------------------------------------------------------------- */
 /*      Set range variables.                                            */
 /* -------------------------------------------------------------------- */
-    size_t start[2], edge[2];
-    double dummy[2];
-    int nm[2];
-	
-    start[0] = 0;
-    edge[0] = 2;
-    dummy[0] = adfGeoTransform[0];
-    dummy[1] = dfXMax;
+    size_t start[2] = {0, 0};
+    size_t edge[2] = {2, 0};
+    double dummy[2] = {adfGeoTransform[0], dfXMax};
     nc_put_vara_double(cdfid, x_range_id, start, edge, dummy);
 
     dummy[0] = dfYMin;
@@ -538,8 +542,7 @@ GMTCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     dummy[1] = -adfGeoTransform[5];
     nc_put_vara_double(cdfid, inc_id, start, edge, dummy);
 
-    nm[0] = nXSize;
-    nm[1] = nYSize;
+    int nm[2] = {nXSize, nYSize};
     nc_put_vara_int(cdfid, nm_id, start, edge, nm);
 
     nc_put_vara_double(cdfid, z_range_id, start, edge, adfMinMax);
@@ -547,28 +550,31 @@ GMTCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Write out the image one scanline at a time.                     */
 /* -------------------------------------------------------------------- */
-    double *padfData;
-    int  iLine;
-
-    padfData = (double *) CPLMalloc( sizeof(double) * nXSize );
+    double *padfData = (double *) CPLMalloc( sizeof(double) * nXSize );
 
     edge[0] = nXSize;
-    for( iLine = 0; iLine < nYSize; iLine++ )
+    for( int iLine = 0; iLine < nYSize; iLine++ )
     {
         start[0] = iLine * nXSize;
-        poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, 
-                          padfData, nXSize, 1, GDT_Float64, 0, 0, NULL );
+        if( poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1,
+                          padfData, nXSize, 1, GDT_Float64, 0, 0, NULL ) != CE_None )
+        {
+            nc_close (cdfid);
+            CPLFree( padfData );
+            return( NULL );
+        }
         err = nc_put_vara_double( cdfid, z_id, start, edge, padfData );
         if( err != NC_NOERR )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "nc_put_vara_double(%s): %s", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "nc_put_vara_double(%s): %s",
                       pszFilename, nc_strerror( err ) );
             nc_close (cdfid);
+            CPLFree( padfData );
             return( NULL );
         }
     }
-    
+
     CPLFree( padfData );
 
 /* -------------------------------------------------------------------- */
@@ -595,29 +601,24 @@ GMTCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 void GDALRegister_GMT()
 
 {
-    GDALDriver	*poDriver;
-    
-    if (! GDAL_CHECK_VERSION("GMT driver"))
+    if( !GDAL_CHECK_VERSION( "GMT driver" ) )
         return;
 
-    if( GDALGetDriverByName( "GMT" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "GMT" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "GMT NetCDF Grid Format" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#GMT" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "nc" );
-
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Int16 Int32 Float32 Float64" );
-
-        poDriver->pfnOpen = GMTDataset::Open;
-        poDriver->pfnCreateCopy = GMTCreateCopy;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    if( GDALGetDriverByName( "GMT" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "GMT" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "GMT NetCDF Grid Format" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#GMT" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "nc" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Int16 Int32 Float32 Float64" );
+
+    poDriver->pfnOpen = GMTDataset::Open;
+    poDriver->pfnCreateCopy = GMTCreateCopy;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/netcdf/makefile.vc b/frmts/netcdf/makefile.vc
index cd3ccd7..776befb 100644
--- a/frmts/netcdf/makefile.vc
+++ b/frmts/netcdf/makefile.vc
@@ -3,7 +3,7 @@ GDAL_ROOT	=	..\..
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
-OBJ		=	netcdfdataset.obj gmtdataset.obj
+OBJ		=	netcdfdataset.obj netcdflayer.obj netcdfwriterconfig.obj gmtdataset.obj
 
 PLUGIN_DLL 	=	gdal_netCDF.dll
 
diff --git a/frmts/netcdf/netcdfdataset.cpp b/frmts/netcdf/netcdfdataset.cpp
index 74ed3b6..8068530 100644
--- a/frmts/netcdf/netcdfdataset.cpp
+++ b/frmts/netcdf/netcdfdataset.cpp
@@ -1,13 +1,15 @@
+
 /******************************************************************************
- * $Id: netcdfdataset.cpp 31864 2015-12-01 10:08:27Z rouault $
+ * $Id: netcdfdataset.cpp 33794 2016-03-26 13:19:07Z goatbar $
  *
  * Project:  netCDF read/write Driver
  * Purpose:  GDAL bindings over netCDF library.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *           Even Rouault <even.rouault at spatialys.com>
  *
  ******************************************************************************
  * Copyright (c) 2004, Frank Warmerdam
- * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ * Copyright (c) 2007-2016, Even Rouault <even.rouault at spatialys.com>
  * Copyright (c) 2010, Kyle Shannon <kyle at pobox dot com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -29,58 +31,57 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "netcdfdataset.h"
 #include "cpl_error.h"
 #include "cpl_multiproc.h"
-
-CPL_CVSID("$Id: netcdfdataset.cpp 31864 2015-12-01 10:08:27Z rouault $");
+#include "cpl_time.h"
+#include "gdal_frmts.h"
+#include "netcdfdataset.h"
 
 #include <map> //for NCDFWriteProjAttribs()
+#include <limits>
+
+CPL_CVSID("$Id: netcdfdataset.cpp 33794 2016-03-26 13:19:07Z goatbar $");
 
 /* Internal function declarations */
 
-int NCDFIsGDALVersionGTE(const char* pszVersion, int nTarget);
+static bool NCDFIsGDALVersionGTE(const char* pszVersion, int nTarget);
 
-void NCDFAddGDALHistory( int fpImage, 
+static void NCDFAddGDALHistory( int fpImage,
                          const char * pszFilename, const char *pszOldHist,
-                         const char * pszFunctionName );
+                         const char * pszFunctionName,
+                         const char * pszCFVersion = NCDF_CONVENTIONS_CF_V1_5 );
 
-void NCDFAddHistory(int fpImage, const char *pszAddHist, const char *pszOldHist);
+static void NCDFAddHistory(int fpImage, const char *pszAddHist, const char *pszOldHist);
 
-int NCDFIsCfProjection( const char* pszProjection );
+static bool NCDFIsCfProjection( const char* pszProjection );
 
-void NCDFWriteProjAttribs(const OGR_SRSNode *poPROJCS,
+static void NCDFWriteProjAttribs(const OGR_SRSNode *poPROJCS,
                             const char* pszProjection,
                             const int fpImage, const int NCDFVarID);
 
-CPLErr NCDFSafeStrcat(char** ppszDest, char* pszSrc, size_t* nDestSize);
-CPLErr NCDFSafeStrcpy(char** ppszDest, char* pszSrc, size_t* nDestSize);
+static CPLErr NCDFSafeStrcat(char** ppszDest, const char* pszSrc, size_t* nDestSize);
 
 /* var / attribute helper functions */
-CPLErr NCDFGetAttr( int nCdfId, int nVarId, const char *pszAttrName, 
-                    double *pdfValue );
-CPLErr NCDFGetAttr( int nCdfId, int nVarId, const char *pszAttrName, 
-                    char **pszValue );
-CPLErr NCDFPutAttr( int nCdfId, int nVarId, 
+static CPLErr NCDFPutAttr( int nCdfId, int nVarId,
                     const char *pszAttrName, const char *pszValue );
-CPLErr NCDFGet1DVar( int nCdfId, int nVarId, char **pszValue );//replace this where used
-CPLErr NCDFPut1DVar( int nCdfId, int nVarId, const char *pszValue );
+static CPLErr NCDFGet1DVar( int nCdfId, int nVarId, char **pszValue );//replace this where used
+static CPLErr NCDFPut1DVar( int nCdfId, int nVarId, const char *pszValue );
 
-double NCDFGetDefaultNoDataValue( int nVarType );
+static double NCDFGetDefaultNoDataValue( int nVarType );
 
 /* dimension check functions */
-int NCDFIsVarLongitude(int nCdfId, int nVarId=-1, const char * nVarName=NULL );
-int NCDFIsVarLatitude(int nCdfId, int nVarId=-1, const char * nVarName=NULL );
-int NCDFIsVarProjectionX( int nCdfId, int nVarId=-1, const char * pszVarName=NULL );
-int NCDFIsVarProjectionY( int nCdfId, int nVarId=-1, const char * pszVarName=NULL );
-int NCDFIsVarVerticalCoord(int nCdfId, int nVarId=-1, const char * nVarName=NULL );
-int NCDFIsVarTimeCoord(int nCdfId, int nVarId=-1, const char * nVarName=NULL );
-
-char **NCDFTokenizeArray( const char *pszValue );//replace this where used
-void CopyMetadata( void  *poDS, int fpImage, int CDFVarID, 
-                   const char *pszMatchPrefix=NULL, int bIsBand=TRUE );
-
-// uncomment this for more debug ouput
+static bool NCDFIsVarLongitude(int nCdfId, int nVarId=-1, const char * nVarName=NULL );
+static bool NCDFIsVarLatitude(int nCdfId, int nVarId=-1, const char * nVarName=NULL );
+static bool NCDFIsVarProjectionX( int nCdfId, int nVarId=-1, const char * pszVarName=NULL );
+static bool NCDFIsVarProjectionY( int nCdfId, int nVarId=-1, const char * pszVarName=NULL );
+static bool NCDFIsVarVerticalCoord(int nCdfId, int nVarId=-1, const char * nVarName=NULL );
+static bool NCDFIsVarTimeCoord(int nCdfId, int nVarId=-1, const char * nVarName=NULL );
+
+static char **NCDFTokenizeArray( const char *pszValue ); //replace this where used
+static void CopyMetadata( void  *poDS, int fpImage, int CDFVarID,
+                   const char *pszMatchPrefix=NULL, bool bIsBand=true );
+
+// uncomment this for more debug output
 // #define NCDF_DEBUG 1
 
 CPLMutex *hNCMutex = NULL;
@@ -107,103 +108,100 @@ class netCDFRasterBand : public GDALPamRasterBand
     int         bNoDataSet;
     double      dfNoDataValue;
     double      adfValidRange[2];
+    int         bHaveScale;
+    int         bHaveOffset;
     double      dfScale;
     double      dfOffset;
-    int         bSignedData;
-    int         status;
-    int         bCheckLongitude;
+    CPLString   osUnitType;
+    bool        bSignedData;
+    bool        bCheckLongitude;
 
-    CPLErr	    CreateBandMetadata( int *paDimIds ); 
-    template <class T> void CheckData ( void * pImage, 
-                                        int nTmpBlockXSize, int nTmpBlockYSize,
-                                        int bCheckIsNan=FALSE ) ;
+    CPLErr	    CreateBandMetadata( const int *paDimIds );
+    template <class T> void CheckData ( void * pImage, void * pImageNC,
+                                        size_t nTmpBlockXSize, size_t nTmpBlockYSize,
+                                        bool bCheckIsNan=false ) ;
 
   protected:
-
     CPLXMLNode *SerializeToXML( const char *pszVRTPath );
-    
-  public:
 
-    netCDFRasterBand( netCDFDataset *poDS, 
-                      int nZId, 
+  public:
+    netCDFRasterBand( netCDFDataset *poDS,
+                      int nZId,
                       int nZDim,
-                      int nLevel, 
-                      int *panBandZLen,
-                      int *panBandPos,
-                      int *paDimIds,
+                      int nLevel,
+                      const int *panBandZLen,
+                      const int *panBandPos,
+                      const int *paDimIds,
                       int nBand );
-    netCDFRasterBand( netCDFDataset *poDS, 
+    netCDFRasterBand( netCDFDataset *poDS,
                       GDALDataType eType,
                       int nBand,
-                      int bSigned=TRUE,
-                      char *pszBandName=NULL,
-                      char *pszLongName=NULL, 
-                      int nZId=-1, 
+                      bool bSigned=true,
+                      const char *pszBandName=NULL,
+                      const char *pszLongName=NULL,
+                      int nZId=-1,
                       int nZDim=2,
-                      int nLevel=0, 
-                      int *panBandZLev=NULL, 
-                      int *panBandZPos=NULL, 
-                      int *paDimIds=NULL );
-    ~netCDFRasterBand( );
+                      int nLevel=0,
+                      const int *panBandZLev=NULL,
+                      const int *panBandZPos=NULL,
+                      const int *paDimIds=NULL );
+    virtual ~netCDFRasterBand();
 
     virtual double GetNoDataValue( int * );
     virtual CPLErr SetNoDataValue( double );
+    //virtual CPLErr DeleteNoDataValue();
     virtual double GetOffset( int * );
     virtual CPLErr SetOffset( double );
     virtual double GetScale( int * );
     virtual CPLErr SetScale( double );
+    virtual const char *GetUnitType();
+    virtual CPLErr SetUnitType( const char * );
     virtual CPLErr IReadBlock( int, int, void * );
     virtual CPLErr IWriteBlock( int, int, void * );
-
 };
 
 /************************************************************************/
 /*                          netCDFRasterBand()                          */
 /************************************************************************/
 
-netCDFRasterBand::netCDFRasterBand( netCDFDataset *poNCDFDS, 
-                                    int nZId, 
-                                    int nZDim,
-                                    int nLevel, 
-                                    int *panBandZLev, 
-                                    int *panBandZPos, 
-                                    int *paDimIds,
-                                    int nBand )
-
+netCDFRasterBand::netCDFRasterBand( netCDFDataset *poNCDFDS,
+                                    int nZIdIn,
+                                    int nZDimIn,
+                                    int nLevelIn,
+                                    const int *panBandZLevIn,
+                                    const int *panBandZPosIn,
+                                    const int *paDimIds,
+                                    int nBandIn ) :
+    cdfid(poNCDFDS->GetCDFID()),
+    nBandXPos(panBandZPosIn[0]),
+    nBandYPos(panBandZPosIn[1]),
+    bHaveScale(false),
+    bHaveOffset(false),
+    dfScale(1.0),
+    dfOffset(0.0),
+    bSignedData(true),   // Default signed, except for Byte.
+    bCheckLongitude(false)
 {
-    double   dfNoData = 0.0;
-    int      bGotNoData = FALSE;
-    nc_type  vartype=NC_NAT;
-    nc_type  atttype=NC_NAT;
-    size_t   attlen;
-    char     szNoValueName[NCDF_MAX_STR_LEN];
-
     this->poDS = poNCDFDS;
     this->panBandZPos = NULL;
     this->panBandZLev = NULL;
-    this->nBand = nBand;
-    this->nZId = nZId;
-    this->nZDim = nZDim;
-    this->nLevel = nLevel;
-    this->nBandXPos = panBandZPos[0];
-    this->nBandYPos = panBandZPos[1];
-    this->bSignedData = TRUE; //default signed, except for Byte 
-    this->cdfid = poNCDFDS->GetCDFID();
-    this->status = NC_NOERR;
-    this->bCheckLongitude = FALSE;
-
-/* -------------------------------------------------------------------- */
-/*      Take care of all other dimmensions                              */
-/* ------------------------------------------------------------------ */
+    this->nBand = nBandIn;
+    this->nZId = nZIdIn;
+    this->nZDim = nZDimIn;
+    this->nLevel = nLevelIn;
+
+/* ------------------------------------------------------------------- */
+/*      Take care of all other dimensions                              */
+/* ------------------------------------------------------------------- */
     if( nZDim > 2 ) {
-        this->panBandZPos = 
+        this->panBandZPos =
             (int *) CPLCalloc( nZDim-1, sizeof( int ) );
-        this->panBandZLev = 
+        this->panBandZLev =
             (int *) CPLCalloc( nZDim-1, sizeof( int ) );
 
         for ( int i=0; i < nZDim - 2; i++ ){
-            this->panBandZPos[i] = panBandZPos[i+2];
-            this->panBandZLev[i] = panBandZLev[i];
+            this->panBandZPos[i] = panBandZPosIn[i+2];
+            this->panBandZLev[i] = panBandZLevIn[i];
         }
     }
 
@@ -220,20 +218,15 @@ netCDFRasterBand::netCDFRasterBand( netCDFDataset *poNCDFDS,
 /* -------------------------------------------------------------------- */
     if( nc_inq_var( cdfid, nZId, NULL, &nc_datatype, NULL, NULL,
                     NULL ) != NC_NOERR ){
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Error in nc_var_inq() on 'z'." );
         return;
     }
 
     if( nc_datatype == NC_BYTE )
         eDataType = GDT_Byte;
-#ifdef NETCDF_HAS_NC4
-    /* NC_UBYTE (unsigned byte) is only available for NC4 */
-    else if( nc_datatype == NC_UBYTE )
-        eDataType = GDT_Byte;
-#endif    
     else if( nc_datatype == NC_CHAR )
-        eDataType = GDT_Byte;        
+        eDataType = GDT_Byte;
     else if( nc_datatype == NC_SHORT )
         eDataType = GDT_Int16;
     else if( nc_datatype == NC_INT )
@@ -242,55 +235,66 @@ netCDFRasterBand::netCDFRasterBand( netCDFDataset *poNCDFDS,
         eDataType = GDT_Float32;
     else if( nc_datatype == NC_DOUBLE )
         eDataType = GDT_Float64;
+#ifdef NETCDF_HAS_NC4
+    /* NC_UBYTE (unsigned byte) is only available for NC4 */
+    else if( nc_datatype == NC_UBYTE )
+        eDataType = GDT_Byte;
+    else if( nc_datatype == NC_USHORT )
+        eDataType = GDT_UInt16;
+    else if( nc_datatype == NC_UINT )
+        eDataType = GDT_UInt32;
+#endif
     else
     {
         if( nBand == 1 )
-            CPLError( CE_Warning, CPLE_AppDefined, 
-                      "Unsupported netCDF datatype (%d), treat as Float32.", 
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Unsupported netCDF datatype (%d), treat as Float32.",
                       (int) nc_datatype );
         eDataType = GDT_Float32;
+        nc_datatype = NC_FLOAT;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Find and set No Data for this variable                          */
 /* -------------------------------------------------------------------- */
+    nc_type atttype=NC_NAT;
+    size_t attlen;
+    const char* pszNoValueName = NULL;
 
     /* find attribute name, either _FillValue or missing_value */
-    status = nc_inq_att( cdfid, nZId, 
-                         _FillValue, &atttype, &attlen);
+    int status = nc_inq_att( cdfid, nZId, _FillValue, &atttype, &attlen);
     if( status == NC_NOERR ) {
-        strcpy(szNoValueName, _FillValue );
+        pszNoValueName = _FillValue;
     }
     else {
-        status = nc_inq_att( cdfid, nZId, 
+        status = nc_inq_att( cdfid, nZId,
                              "missing_value", &atttype, &attlen );
         if( status == NC_NOERR ) {
-            strcpy( szNoValueName, "missing_value" );
+            pszNoValueName = "missing_value";
         }
     }
 
     /* fetch missing value */
+    double dfNoData = 0.0;
+    bool bGotNoData = false;
     if( status == NC_NOERR ) {
-        if ( NCDFGetAttr( cdfid, nZId, szNoValueName, 
+        if ( NCDFGetAttr( cdfid, nZId, pszNoValueName,
                           &dfNoData ) == CE_None )
-            bGotNoData = TRUE;
+        {
+            bGotNoData = true;
+        }
     }
-    
+
     /* if NoData was not found, use the default value */
-    if ( ! bGotNoData ) { 
+    nc_type vartype=NC_NAT;
+    if ( ! bGotNoData ) {
         nc_inq_vartype( cdfid, nZId, &vartype );
         dfNoData = NCDFGetDefaultNoDataValue( vartype );
-        bGotNoData = TRUE;
-        CPLDebug( "GDAL_netCDF", 
-                  "did not get nodata value for variable #%d, using default %f", 
+        /*bGotNoData = true;*/
+        CPLDebug( "GDAL_netCDF",
+                  "did not get nodata value for variable #%d, using default %f",
                   nZId, dfNoData );
-    } 
-    
-    /* set value */
-#ifdef NCDF_DEBUG
-    CPLDebug( "GDAL_netCDF", "SetNoDataValue(%f) read", dfNoData );
-#endif
-    SetNoDataValue( dfNoData );
+    }
 
 /* -------------------------------------------------------------------- */
 /*  Look for valid_range or valid_min/valid_max                         */
@@ -299,30 +303,27 @@ netCDFRasterBand::netCDFRasterBand( netCDFDataset *poNCDFDS,
     adfValidRange[0] = dfNoData;
     adfValidRange[1] = dfNoData;
     /* first look for valid_range */
-    int bGotValidRange = FALSE;
-    status = nc_inq_att( cdfid, nZId, 
-                         "valid_range", &atttype, &attlen);
+    bool bGotValidRange = false;
+    status = nc_inq_att( cdfid, nZId, "valid_range", &atttype, &attlen);
     if( (status == NC_NOERR) && (attlen == 2)) {
         int vrange[2];
         int vmin, vmax;
-        status = nc_get_att_int( cdfid, nZId,
-                                 "valid_range", vrange ); 
+        status = nc_get_att_int( cdfid, nZId, "valid_range", vrange );
         if( status == NC_NOERR ) {
-            bGotValidRange = TRUE;
+            bGotValidRange = true;
             adfValidRange[0] = vrange[0];
             adfValidRange[1] = vrange[1];
         }
         /* if not found look for valid_min and valid_max */
         else {
-            status = nc_get_att_int( cdfid, nZId,
-                                     "valid_min", &vmin );
+            status = nc_get_att_int( cdfid, nZId, "valid_min", &vmin );
             if( status == NC_NOERR ) {
                 adfValidRange[0] = vmin;
                 status = nc_get_att_int( cdfid, nZId,
                                          "valid_max", &vmax );
                 if( status == NC_NOERR ) {
                     adfValidRange[1] = vmax;
-                    bGotValidRange = TRUE;
+                    bGotValidRange = true;
                 }
             }
         }
@@ -336,28 +337,28 @@ netCDFRasterBand::netCDFRasterBand( netCDFDataset *poNCDFDS,
         /* netcdf uses signed byte by default, but GDAL uses unsigned by default */
         /* This may cause unexpected results, but is needed for back-compat */
         if ( poNCDFDS->bIsGdalFile )
-            this->bSignedData = FALSE;
-        else 
-            this->bSignedData = TRUE;
+            bSignedData = false;
+        else
+            bSignedData = true;
 
         /* For NC4 format NC_BYTE is signed, NC_UBYTE is unsigned */
-        if ( poNCDFDS->nFormat == NCDF_FORMAT_NC4 ) {
-            this->bSignedData = TRUE;
-        }   
+        if ( poNCDFDS->eFormat == NCDF_FORMAT_NC4 ) {
+            bSignedData = true;
+        }
         else  {
             /* if we got valid_range, test for signed/unsigned range */
             /* http://www.unidata.ucar.edu/software/netcdf/docs/netcdf/Attribute-Conventions.html */
-            if ( bGotValidRange == TRUE ) {
+            if ( bGotValidRange ) {
                 /* If we got valid_range={0,255}, treat as unsigned */
                 if ( (adfValidRange[0] == 0) && (adfValidRange[1] == 255) ) {
-                    bSignedData = FALSE;
+                    bSignedData = false;
                     /* reset valid_range */
                     adfValidRange[0] = dfNoData;
                     adfValidRange[1] = dfNoData;
                 }
                 /* If we got valid_range={-128,127}, treat as signed */
                 else if ( (adfValidRange[0] == -128) && (adfValidRange[1] == 127) ) {
-                    bSignedData = TRUE;
+                    bSignedData = true;
                     /* reset valid_range */
                     adfValidRange[0] = dfNoData;
                     adfValidRange[1] = dfNoData;
@@ -367,13 +368,12 @@ netCDFRasterBand::netCDFRasterBand( netCDFDataset *poNCDFDS,
             /* http://www.unidata.ucar.edu/software/netcdf/docs/BestPractices.html */
             else {
                 char *pszTemp = NULL;
-                if ( NCDFGetAttr( cdfid, nZId, "_Unsigned", &pszTemp ) 
-
+                if ( NCDFGetAttr( cdfid, nZId, "_Unsigned", &pszTemp )
                      == CE_None ) {
                     if ( EQUAL(pszTemp,"true"))
-                        bSignedData = FALSE;
+                        bSignedData = false;
                     else if ( EQUAL(pszTemp,"false"))
-                        bSignedData = TRUE;
+                        bSignedData = true;
                     CPLFree( pszTemp );
                 }
             }
@@ -383,18 +383,31 @@ netCDFRasterBand::netCDFRasterBand( netCDFDataset *poNCDFDS,
         {
             /* set PIXELTYPE=SIGNEDBYTE */
             /* See http://trac.osgeo.org/gdal/wiki/rfc14_imagestructure */
-            SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" );    
+            SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" );
+        }
+        else
+        {
+            // Fix nodata value as it was stored signed
+            if( dfNoData < 0 )
+                dfNoData += 256;
         }
-
     }
 
 #ifdef NETCDF_HAS_NC4
-    if ( nc_datatype == NC_UBYTE )
-        this->bSignedData = FALSE;
+    if ( nc_datatype == NC_UBYTE
+         || nc_datatype == NC_USHORT
+         || nc_datatype == NC_UINT )
+        bSignedData = false;
 #endif
-    
+
     CPLDebug( "GDAL_netCDF", "netcdf type=%d gdal type=%d signedByte=%d",
-              nc_datatype, eDataType, bSignedData );
+              nc_datatype, eDataType, static_cast<int>(bSignedData) );
+
+    /* set nodata value */
+#ifdef NCDF_DEBUG
+    CPLDebug( "GDAL_netCDF", "SetNoDataValue(%f) read", dfNoData );
+#endif
+    SetNoDataValue( dfNoData );
 
 /* -------------------------------------------------------------------- */
 /*      Create Band Metadata                                            */
@@ -406,27 +419,30 @@ netCDFRasterBand::netCDFRasterBand( netCDFDataset *poNCDFDS,
 /* variable and set them.  If these values are not available, set       */
 /* offset to 0 and scale to 1                                           */
 /* -------------------------------------------------------------------- */
-    double dfOff = 0.0; 
-    double dfScale = 1.0; 
-    
-    if ( nc_inq_attid ( cdfid, nZId, CF_ADD_OFFSET, NULL) == NC_NOERR ) { 
-        status = nc_get_att_double( cdfid, nZId, CF_ADD_OFFSET, &dfOff );
-        CPLDebug( "GDAL_netCDF", "got add_offset=%.16g, status=%d", dfOff, status );
+    if ( nc_inq_attid ( cdfid, nZId, CF_ADD_OFFSET, NULL) == NC_NOERR ) {
+        status = nc_get_att_double( cdfid, nZId, CF_ADD_OFFSET, &dfOffset );
+        CPLDebug( "GDAL_netCDF", "got add_offset=%.16g, status=%d", dfOffset, status );
+        SetOffset( dfOffset );
     }
-    if ( nc_inq_attid ( cdfid, nZId, 
-                        CF_SCALE_FACTOR, NULL) == NC_NOERR ) { 
-        status = nc_get_att_double( cdfid, nZId, CF_SCALE_FACTOR, &dfScale ); 
+
+    if ( nc_inq_attid ( cdfid, nZId,
+                        CF_SCALE_FACTOR, NULL) == NC_NOERR ) {
+        status = nc_get_att_double( cdfid, nZId, CF_SCALE_FACTOR, &dfScale );
         CPLDebug( "GDAL_netCDF", "got scale_factor=%.16g, status=%d", dfScale, status );
+        SetScale( dfScale );
     }
-    SetOffset( dfOff );
-    SetScale( dfScale );
 
     /* should we check for longitude values > 360 ? */
-    this->bCheckLongitude = 
-        CSLTestBoolean(CPLGetConfigOption("GDAL_NETCDF_CENTERLONG_180", "YES"))
+    bCheckLongitude =
+        CPLTestBool(CPLGetConfigOption("GDAL_NETCDF_CENTERLONG_180", "YES"))
         && NCDFIsVarLongitude( cdfid, nZId, NULL );
 
 /* -------------------------------------------------------------------- */
+/* Attempt to fetch the units attribute for the variable and set it.    */
+/* -------------------------------------------------------------------- */
+    SetUnitType( GetMetadataItem( CF_UNITS ) );
+
+/* -------------------------------------------------------------------- */
 /*      Check for variable chunking (netcdf-4 only)                     */
 /*      GDAL block size should be set to hdf5 chunk size                */
 /* -------------------------------------------------------------------- */
@@ -434,18 +450,19 @@ netCDFRasterBand::netCDFRasterBand( netCDFDataset *poNCDFDS,
     int nTmpFormat = 0;
     size_t chunksize[ MAX_NC_DIMS ];
     status = nc_inq_format( cdfid, &nTmpFormat);
-    if( ( status == NC_NOERR ) && ( ( nTmpFormat == NCDF_FORMAT_NC4 ) ||
-          ( nTmpFormat == NCDF_FORMAT_NC4C ) ) ) {
+    NetCDFFormatEnum eTmpFormat = static_cast<NetCDFFormatEnum>(nTmpFormat);
+    if( ( status == NC_NOERR ) && ( ( eTmpFormat == NCDF_FORMAT_NC4 ) ||
+          ( eTmpFormat == NCDF_FORMAT_NC4C ) ) ) {
         /* check for chunksize and set it as the blocksize (optimizes read) */
         status = nc_inq_var_chunking( cdfid, nZId, &nTmpFormat, chunksize );
         if( ( status == NC_NOERR ) && ( nTmpFormat == NC_CHUNKED ) ) {
-            CPLDebug( "GDAL_netCDF", 
+            CPLDebug( "GDAL_netCDF",
                       "setting block size to chunk size : %ld x %ld\n",
-                      chunksize[nZDim-1], chunksize[nZDim-2]);
+                      static_cast<long>(chunksize[nZDim-1]), static_cast<long>(chunksize[nZDim-2]));
             nBlockXSize = (int) chunksize[nZDim-1];
             nBlockYSize = (int) chunksize[nZDim-2];
         }
-	} 		
+	}
 #endif
 
 /* -------------------------------------------------------------------- */
@@ -461,41 +478,38 @@ netCDFRasterBand::netCDFRasterBand( netCDFDataset *poNCDFDS,
 /* constructor in create mode */
 /* if nZId and following variables are not passed, the band will have 2 dimensions */
 /* TODO get metadata, missing val from band #1 if nZDim>2 */
-netCDFRasterBand::netCDFRasterBand( netCDFDataset *poNCDFDS, 
+netCDFRasterBand::netCDFRasterBand( netCDFDataset *poNCDFDS,
                                     GDALDataType eType,
-                                    int nBand,
-                                    int bSigned,
-                                    char *pszBandName,
-                                    char *pszLongName, 
-                                    int nZId, 
-                                    int nZDim,
-                                    int nLevel, 
-                                    int *panBandZLev, 
-                                    int *panBandZPos, 
-                                    int *paDimIds )
+                                    int nBandIn,
+                                    bool bSigned,
+                                    const char *pszBandName,
+                                    const char *pszLongName,
+                                    int nZIdIn,
+                                    int nZDimIn,
+                                    int nLevelIn,
+                                    const int *panBandZLevIn,
+                                    const int *panBandZPosIn,
+                                    const int *paDimIds ) :
+    nc_datatype(NC_NAT),
+    cdfid(poNCDFDS->GetCDFID()),
+    nBandXPos(1),
+    nBandYPos(0),
+    bNoDataSet(FALSE),
+    dfNoDataValue(0.0),
+    bHaveScale(false),
+    bHaveOffset(false),
+    dfScale(0.0),
+    dfOffset(0.0),
+    bSignedData(bSigned),
+    bCheckLongitude(false)
 {
-    int      status;  
-    double   dfNoData = 0.0;
-    char szTemp[NCDF_MAX_STR_LEN];
-    int bDefineVar = FALSE;
-
     this->poDS = poNCDFDS;
-    this->nBand = nBand;
-    this->nZId = nZId;
-    this->nZDim = nZDim;
-    this->nLevel = nLevel;
+    this->nBand = nBandIn;
+    this->nZId = nZIdIn;
+    this->nZDim = nZDimIn;
+    this->nLevel = nLevelIn;
     this->panBandZPos = NULL;
     this->panBandZLev = NULL;
-    this->nBandXPos = 1;
-    this->nBandYPos = 0; 
-    this->bSignedData = bSigned;  
-
-    this->status = NC_NOERR;
-    this->cdfid = poNCDFDS->GetCDFID();
-    this->bCheckLongitude = FALSE;
-
-    this->bNoDataSet    = FALSE;
-    this->dfNoDataValue = 0.0;
 
     nRasterXSize   = poDS->GetRasterXSize( );
     nRasterYSize   = poDS->GetRasterYSize( );
@@ -503,27 +517,24 @@ netCDFRasterBand::netCDFRasterBand( netCDFDataset *poNCDFDS,
     nBlockYSize   = 1;
 
     if ( poDS->GetAccess() != GA_Update ) {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "Dataset is not in update mode, wrong netCDFRasterBand constructor" );
         return;
     }
-    
-/* -------------------------------------------------------------------- */
-/*      Take care of all other dimmensions                              */
+
+/* ------------------------------------------------------------------ */
+/*      Take care of all other dimensions                             */
 /* ------------------------------------------------------------------ */
     if ( nZDim > 2 && paDimIds != NULL ) {
+        nBandXPos = panBandZPosIn[0];
+        nBandYPos = panBandZPosIn[1];
 
-        this->nBandXPos = panBandZPos[0];
-        this->nBandYPos = panBandZPos[1];
-
-        this->panBandZPos = 
-            (int *) CPLCalloc( nZDim-1, sizeof( int ) );
-        this->panBandZLev = 
-            (int *) CPLCalloc( nZDim-1, sizeof( int ) );
+        this->panBandZPos = (int *) CPLCalloc( nZDim-1, sizeof( int ) );
+        this->panBandZLev = (int *) CPLCalloc( nZDim-1, sizeof( int ) );
 
         for ( int i=0; i < nZDim - 2; i++ ){
-            this->panBandZPos[i] = panBandZPos[i+2];
-            this->panBandZLev[i] = panBandZLev[i];
+            this->panBandZPos[i] = panBandZPosIn[i+2];
+            this->panBandZLev[i] = panBandZLevIn[i];
         }
     }
 
@@ -532,15 +543,15 @@ netCDFRasterBand::netCDFRasterBand( netCDFDataset *poNCDFDS,
 /* -------------------------------------------------------------------- */
     eDataType = eType;
 
-    switch ( eDataType ) 
+    switch ( eDataType )
     {
         case GDT_Byte:
             nc_datatype = NC_BYTE;
 #ifdef NETCDF_HAS_NC4
             /* NC_UBYTE (unsigned byte) is only available for NC4 */
-            if ( ! bSignedData && (poNCDFDS->nFormat == NCDF_FORMAT_NC4) )
+            if ( ! bSignedData && (poNCDFDS->eFormat == NCDF_FORMAT_NC4) )
                 nc_datatype = NC_UBYTE;
-#endif    
+#endif
             break;
         case GDT_Int16:
             nc_datatype = NC_SHORT;
@@ -554,94 +565,117 @@ netCDFRasterBand::netCDFRasterBand( netCDFDataset *poNCDFDS,
         case GDT_Float64:
             nc_datatype = NC_DOUBLE;
             break;
+#ifdef NETCDF_HAS_NC4
+        case GDT_UInt16:
+            if ( poNCDFDS->eFormat == NCDF_FORMAT_NC4 ) {
+                nc_datatype = NC_USHORT;
+                break;
+            }
+        case GDT_UInt32:
+            if ( poNCDFDS->eFormat == NCDF_FORMAT_NC4 ) {
+                nc_datatype = NC_UINT;
+                break;
+            }
+#endif
         default:
             if( nBand == 1 )
-                CPLError( CE_Warning, CPLE_AppDefined, 
-                          "Unsupported GDAL datatype (%d), treat as NC_FLOAT.", 
+                CPLError( CE_Warning, CPLE_AppDefined,
+                          "Unsupported GDAL datatype (%d), treat as NC_FLOAT.",
                           (int) eDataType );
             nc_datatype = NC_FLOAT;
+            eDataType = eType = GDT_Float32;
             break;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Define the variable if necessary (if nZId==-1)                  */
 /* -------------------------------------------------------------------- */
-    if ( nZId == -1 ) {
+    bool bDefineVar = false;
 
-        bDefineVar = TRUE;
+    if ( nZId == -1 ) {
+        bDefineVar = true;
 
         /* make sure we are in define mode */
-        ( ( netCDFDataset * ) poDS )->SetDefineMode( TRUE );
-        
+        ( ( netCDFDataset * ) poDS )->SetDefineMode( true );
+
+        char szTempPrivate[256+1];
+        const char* pszTemp;
         if ( !pszBandName || EQUAL(pszBandName,"")  )
-            sprintf( szTemp, "Band%d", nBand );
-        else 
-            strcpy( szTemp, pszBandName );
-        
+        {
+            snprintf( szTempPrivate, sizeof(szTempPrivate), "Band%d", nBand );
+            pszTemp = szTempPrivate;
+        }
+        else
+            pszTemp = pszBandName;
+
+        int status;
         if ( nZDim > 2 && paDimIds != NULL ) {
-            status = nc_def_var( cdfid, szTemp, nc_datatype, 
+            status = nc_def_var( cdfid, pszTemp, nc_datatype,
                                  nZDim, paDimIds, &nZId );
         }
         else {
-            int anBandDims[ 2 ]; 
-            anBandDims[0] = poNCDFDS->nYDimID;
-            anBandDims[1] = poNCDFDS->nXDimID;
-            status = nc_def_var( cdfid, szTemp, nc_datatype, 
+            int anBandDims[2] = {poNCDFDS->nYDimID, poNCDFDS->nXDimID};
+            status = nc_def_var( cdfid, pszTemp, nc_datatype,
                                  2, anBandDims, &nZId );
         }
         NCDF_ERR(status);
         CPLDebug( "GDAL_netCDF", "nc_def_var(%d,%s,%d) id=%d",
-                  cdfid, szTemp, nc_datatype, nZId );
-        this->nZId = nZId;
-        
+                  cdfid, pszTemp, nc_datatype, nZId );
+
         if ( !pszLongName || EQUAL(pszLongName,"")  )
-            sprintf( szTemp, "GDAL Band Number %d", nBand );
-        else 
-            strcpy( szTemp, pszLongName );
-        status =  nc_put_att_text( cdfid, nZId, CF_LNG_NAME, 
-                                   strlen( szTemp ), szTemp );
+        {
+            snprintf( szTempPrivate, sizeof(szTempPrivate), "GDAL Band Number %d", nBand );
+            pszTemp = szTempPrivate;
+        }
+        else
+            pszTemp = pszLongName;
+        status =  nc_put_att_text( cdfid, nZId, CF_LNG_NAME,
+                                   strlen( pszTemp ), pszTemp );
         NCDF_ERR(status);
-        
-        poNCDFDS->DefVarDeflate(nZId, TRUE);
+
+        poNCDFDS->DefVarDeflate(nZId, true);
     }
 
     /* for Byte data add signed/unsigned info */
     if ( eDataType == GDT_Byte ) {
 
         if ( bDefineVar ) { //only add attributes if creating variable
-        CPLDebug( "GDAL_netCDF", "adding valid_range attributes for Byte Band" );
-        /* For unsigned NC_BYTE (except NC4 format) */
-        /* add valid_range and _Unsigned ( defined in CF-1 and NUG ) */
-        if ( (nc_datatype == NC_BYTE) && (poNCDFDS->nFormat != NCDF_FORMAT_NC4) ) {
-            short int adfValidRange[2]; 
+          /* For unsigned NC_BYTE (except NC4 format) */
+          /* add valid_range and _Unsigned ( defined in CF-1 and NUG ) */
+          int status = NC_NOERR;
+          if ( (nc_datatype == NC_BYTE) && (poNCDFDS->eFormat != NCDF_FORMAT_NC4) ) {
+            CPLDebug( "GDAL_netCDF", "adding valid_range attributes for Byte Band" );
+            short l_adfValidRange[2];
             if  ( bSignedData ) {
-                adfValidRange[0] = -128;
-                adfValidRange[1] = 127;
-                status = nc_put_att_text( cdfid,nZId, 
+                l_adfValidRange[0] = -128;
+                l_adfValidRange[1] = 127;
+                status = nc_put_att_text( cdfid,nZId,
                                           "_Unsigned", 5, "false" );
             }
             else {
-                adfValidRange[0] = 0;
-                adfValidRange[1] = 255;
-                    status = nc_put_att_text( cdfid,nZId, 
+                l_adfValidRange[0] = 0;
+                l_adfValidRange[1] = 255;
+                    status = nc_put_att_text( cdfid,nZId,
                                               "_Unsigned", 4, "true" );
             }
+            NCDF_ERR(status);
             status=nc_put_att_short( cdfid,nZId, "valid_range",
-                                     NC_SHORT, 2, adfValidRange );
-        }         
+                                     NC_SHORT, 2, l_adfValidRange );
+            NCDF_ERR(status);
+          }
         }
         /* for unsigned byte set PIXELTYPE=SIGNEDBYTE */
         /* See http://trac.osgeo.org/gdal/wiki/rfc14_imagestructure */
-        if  ( bSignedData ) 
-            SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" );    
+        if  ( bSignedData )
+            SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" );
 
     }
 
     /* set default nodata */
+    double dfNoData = NCDFGetDefaultNoDataValue( nc_datatype );
 #ifdef NCDF_DEBUG
     CPLDebug( "GDAL_netCDF", "SetNoDataValue(%f) default", dfNoData );
 #endif
-    dfNoData = NCDFGetDefaultNoDataValue( nc_datatype );
     SetNoDataValue( dfNoData );
 }
 
@@ -652,86 +686,131 @@ netCDFRasterBand::netCDFRasterBand( netCDFDataset *poNCDFDS,
 netCDFRasterBand::~netCDFRasterBand()
 {
     FlushCache();
-    if( panBandZPos ) 
-        CPLFree( panBandZPos );
-    if( panBandZLev )
-        CPLFree( panBandZLev );
+    CPLFree( panBandZPos );
+    CPLFree( panBandZLev );
 }
 
-/************************************************************************/ 
-/*                             GetOffset()                              */ 
-/************************************************************************/ 
-double netCDFRasterBand::GetOffset( int *pbSuccess ) 
-{ 
-    if( pbSuccess != NULL ) 
-        *pbSuccess = TRUE; 
-	 
-    return dfOffset; 
+/************************************************************************/
+/*                             GetOffset()                              */
+/************************************************************************/
+double netCDFRasterBand::GetOffset( int *pbSuccess )
+{
+    if( pbSuccess != NULL )
+        *pbSuccess = bHaveOffset;
+
+    return dfOffset;
 }
 
-/************************************************************************/ 
-/*                             SetOffset()                              */ 
-/************************************************************************/ 
-CPLErr netCDFRasterBand::SetOffset( double dfNewOffset ) 
-{ 
+/************************************************************************/
+/*                             SetOffset()                              */
+/************************************************************************/
+CPLErr netCDFRasterBand::SetOffset( double dfNewOffset )
+{
     CPLMutexHolderD(&hNCMutex);
 
-    dfOffset = dfNewOffset; 
+    dfOffset = dfNewOffset;
+    bHaveOffset = true;
 
     /* write value if in update mode */
     if ( poDS->GetAccess() == GA_Update ) {
 
         /* make sure we are in define mode */
-        ( ( netCDFDataset * ) poDS )->SetDefineMode( TRUE );
+        ( ( netCDFDataset * ) poDS )->SetDefineMode( true );
 
-        status = nc_put_att_double( cdfid, nZId, CF_ADD_OFFSET,
+        int status = nc_put_att_double( cdfid, nZId, CF_ADD_OFFSET,
                                     NC_DOUBLE, 1, &dfOffset );
 
         NCDF_ERR(status);
         if ( status == NC_NOERR )
             return CE_None;
-        else
-            return CE_Failure;
 
+        return CE_Failure;
     }
 
-    return CE_None; 
+    return CE_None;
 }
 
-/************************************************************************/ 
-/*                              GetScale()                              */ 
-/************************************************************************/ 
-double netCDFRasterBand::GetScale( int *pbSuccess ) 
-{ 
-    if( pbSuccess != NULL ) 
-        *pbSuccess = TRUE; 
-    return dfScale; 
+/************************************************************************/
+/*                              GetScale()                              */
+/************************************************************************/
+double netCDFRasterBand::GetScale( int *pbSuccess )
+{
+    if( pbSuccess != NULL )
+        *pbSuccess = bHaveScale;
+
+    return dfScale;
 }
 
-/************************************************************************/ 
-/*                              SetScale()                              */ 
-/************************************************************************/ 
-CPLErr netCDFRasterBand::SetScale( double dfNewScale )  
-{ 
+/************************************************************************/
+/*                              SetScale()                              */
+/************************************************************************/
+CPLErr netCDFRasterBand::SetScale( double dfNewScale )
+{
     CPLMutexHolderD(&hNCMutex);
 
-    dfScale = dfNewScale; 
+    dfScale = dfNewScale;
+    bHaveScale = true;
 
     /* write value if in update mode */
     if ( poDS->GetAccess() == GA_Update ) {
 
         /* make sure we are in define mode */
-        ( ( netCDFDataset * ) poDS )->SetDefineMode( TRUE );
+        ( ( netCDFDataset * ) poDS )->SetDefineMode( true );
 
-        status = nc_put_att_double( cdfid, nZId, CF_SCALE_FACTOR,
+        int status = nc_put_att_double( cdfid, nZId, CF_SCALE_FACTOR,
                                     NC_DOUBLE, 1, &dfScale );
 
         NCDF_ERR(status);
         if ( status == NC_NOERR )
             return CE_None;
-        else
-            return CE_Failure;
 
+        return CE_Failure;
+    }
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                            GetUnitType()                             */
+/************************************************************************/
+
+const char *netCDFRasterBand::GetUnitType()
+
+{
+    if( osUnitType.size() > 0 )
+        return osUnitType;
+    else
+        return GDALRasterBand::GetUnitType();
+}
+
+/************************************************************************/
+/*                           SetUnitType()                              */
+/************************************************************************/
+
+CPLErr netCDFRasterBand::SetUnitType( const char* pszNewValue )
+
+{
+    CPLMutexHolderD(&hNCMutex);
+
+    osUnitType = (pszNewValue != NULL ? pszNewValue : "");
+
+    if ( osUnitType.size() > 0 ) {
+        /* write value if in update mode */
+        if ( poDS->GetAccess() == GA_Update ) {
+
+            /* make sure we are in define mode */
+            ( ( netCDFDataset * ) poDS )->SetDefineMode( TRUE );
+
+            int status = nc_put_att_text( cdfid, nZId, CF_UNITS,
+                                          osUnitType.size(),
+                                          osUnitType.c_str() );
+
+            NCDF_ERR(status);
+            if ( status == NC_NOERR )
+                return CE_None;
+
+            return CE_Failure;
+        }
     }
 
     return CE_None;
@@ -749,11 +828,10 @@ double netCDFRasterBand::GetNoDataValue( int * pbSuccess )
 
     if( bNoDataSet )
         return dfNoDataValue;
-    else
-        return GDALPamRasterBand::GetNoDataValue( pbSuccess );
+
+    return GDALPamRasterBand::GetNoDataValue( pbSuccess );
 }
 
-    
 /************************************************************************/
 /*                           SetNoDataValue()                           */
 /************************************************************************/
@@ -773,36 +851,36 @@ CPLErr netCDFRasterBand::SetNoDataValue( double dfNoData )
         /* netcdf-4 does not allow to set _FillValue after leaving define mode */
         /* but it's ok if variable has not been written to, so only print debug */
         /* see bug #4484 */
-        if ( bNoDataSet && 
-             ( ((netCDFDataset *)poDS)->GetDefineMode() == FALSE ) ) {
-            CPLDebug( "GDAL_netCDF", 
+        if ( bNoDataSet && !reinterpret_cast<netCDFDataset *>(poDS)->GetDefineMode() ) {
+            CPLDebug( "GDAL_netCDF",
                       "Setting NoDataValue to %.18g (previously set to %.18g) "
-                      "but file is no longer in define mode (id #%d, band #%d)", 
+                      "but file is no longer in define mode (id #%d, band #%d)",
                       dfNoData, dfNoDataValue, cdfid, nBand );
         }
 #ifdef NCDF_DEBUG
         else {
-            CPLDebug( "GDAL_netCDF", "Setting NoDataValue to %.18g (id #%d, band #%d)", 
+            CPLDebug( "GDAL_netCDF", "Setting NoDataValue to %.18g (id #%d, band #%d)",
                       dfNoData, cdfid, nBand );
         }
-#endif        
+#endif
         /* make sure we are in define mode */
-        ( ( netCDFDataset * ) poDS )->SetDefineMode( TRUE );
+        reinterpret_cast<netCDFDataset *>( poDS )->SetDefineMode( true );
 
+        int status;
         if ( eDataType == GDT_Byte) {
             if ( bSignedData ) {
                 signed char cNoDataValue = (signed char) dfNoData;
                 status = nc_put_att_schar( cdfid, nZId, _FillValue,
-                                           nc_datatype, 1, &cNoDataValue );            
+                                           nc_datatype, 1, &cNoDataValue );
             }
             else {
                 unsigned char ucNoDataValue = (unsigned char) dfNoData;
                 status = nc_put_att_uchar( cdfid, nZId, _FillValue,
-                                           nc_datatype, 1, &ucNoDataValue );            
+                                           nc_datatype, 1, &ucNoDataValue );
             }
         }
         else if ( eDataType == GDT_Int16 ) {
-            short int nsNoDataValue = (short int) dfNoData;
+            short nsNoDataValue = (short) dfNoData;
             status = nc_put_att_short( cdfid, nZId, _FillValue,
                                        nc_datatype, 1, &nsNoDataValue );
         }
@@ -816,7 +894,21 @@ CPLErr netCDFRasterBand::SetNoDataValue( double dfNoData )
             status = nc_put_att_float( cdfid, nZId, _FillValue,
                                        nc_datatype, 1, &fNoDataValue );
         }
-        else 
+#ifdef NETCDF_HAS_NC4
+        else if ( eDataType == GDT_UInt16
+                  && reinterpret_cast<netCDFDataset *>( poDS )->eFormat == NCDF_FORMAT_NC4 ) {
+            unsigned short usNoDataValue = (unsigned short) dfNoData;
+            status = nc_put_att_ushort( cdfid, nZId, _FillValue,
+                                        nc_datatype, 1, &usNoDataValue );
+        }
+        else if ( eDataType == GDT_UInt32
+                  && reinterpret_cast<netCDFDataset *>( poDS )->eFormat == NCDF_FORMAT_NC4 ) {
+            unsigned int unNoDataValue = (unsigned int) dfNoData;
+            status = nc_put_att_uint( cdfid, nZId, _FillValue,
+                                      nc_datatype, 1, &unNoDataValue );
+        }
+#endif
+        else
             status = nc_put_att_double( cdfid, nZId, _FillValue,
                                         nc_datatype, 1, &dfNoData );
 
@@ -828,8 +920,8 @@ CPLErr netCDFRasterBand::SetNoDataValue( double dfNoData )
             bNoDataSet = TRUE;
             return CE_None;
         }
-        else
-            return CE_Failure;
+
+        return CE_Failure;
 
     }
 
@@ -839,30 +931,67 @@ CPLErr netCDFRasterBand::SetNoDataValue( double dfNoData )
 }
 
 /************************************************************************/
+/*                        DeleteNoDataValue()                           */
+/************************************************************************/
+
+#ifdef notdef
+CPLErr netCDFRasterBand::DeleteNoDataValue()
+
+{
+    CPLMutexHolderD(&hNCMutex);
+
+    if ( !bNoDataSet )
+        return CE_None;
+
+    /* write value if in update mode */
+    if ( poDS->GetAccess() == GA_Update ) {
+
+        /* make sure we are in define mode */
+        ( ( netCDFDataset * ) poDS )->SetDefineMode( true );
+
+        status = nc_del_att( cdfid, nZId, _FillValue );
+
+        NCDF_ERR(status);
+
+        /* update status if write worked */
+        if ( status == NC_NOERR ) {
+            dfNoDataValue = 0.0;
+            bNoDataSet = FALSE;
+            return CE_None;
+        }
+
+        return CE_Failure;
+    }
+
+    dfNoDataValue = 0.0;
+    bNoDataSet = FALSE;
+    return CE_None;
+}
+#endif
+
+/************************************************************************/
 /*                           SerializeToXML()                           */
 /************************************************************************/
 
 CPLXMLNode *netCDFRasterBand::SerializeToXML( CPL_UNUSED const char *pszUnused )
 {
 /* -------------------------------------------------------------------- */
-/*      Overriden from GDALPamDataset to add only band histogram        */
+/*      Overridden from GDALPamDataset to add only band histogram        */
 /*      and statistics. See bug #4244.                                  */
 /* -------------------------------------------------------------------- */
-
     if( psPam == NULL )
         return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Setup root node and attributes.                                 */
 /* -------------------------------------------------------------------- */
-    CPLString oFmt;
-
-    CPLXMLNode *psTree;
-
-    psTree = CPLCreateXMLNode( NULL, CXT_Element, "PAMRasterBand" );
+    CPLXMLNode *psTree = CPLCreateXMLNode( NULL, CXT_Element, "PAMRasterBand" );
 
     if( GetBand() > 0 )
+    {
+        CPLString oFmt;
         CPLSetXMLValue( psTree, "#band", oFmt.Printf( "%d", GetBand() ) );
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Histograms.                                                     */
@@ -873,24 +1002,22 @@ CPLXMLNode *netCDFRasterBand::SerializeToXML( CPL_UNUSED const char *pszUnused )
 /* -------------------------------------------------------------------- */
 /*      Metadata (statistics only).                                     */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psMD;
-
-    GDALMultiDomainMetadata oMDMDStats; 
+    GDALMultiDomainMetadata oMDMDStats;
     const char* papszMDStats[] = { "STATISTICS_MINIMUM", "STATISTICS_MAXIMUM",
-                                   "STATISTICS_MEAN", "STATISTICS_STDDEV", 
-                                   NULL }; 
+                                   "STATISTICS_MEAN", "STATISTICS_STDDEV",
+                                   NULL };
     for ( int i=0; i<CSLCount((char**)papszMDStats); i++ ) {
         if ( GetMetadataItem( papszMDStats[i] ) != NULL )
             oMDMDStats.SetMetadataItem( papszMDStats[i],
                                        GetMetadataItem(papszMDStats[i]) );
     }
-    psMD = oMDMDStats.Serialize();
+    CPLXMLNode *psMD = oMDMDStats.Serialize();
 
     if( psMD != NULL )
     {
         if( psMD->psChild == NULL )
             CPLDestroyXMLNode( psMD );
-        else 
+        else
             CPLAddXMLChild( psTree, psMD );
     }
 
@@ -911,35 +1038,20 @@ CPLXMLNode *netCDFRasterBand::SerializeToXML( CPL_UNUSED const char *pszUnused )
 /*                         CreateBandMetadata()                         */
 /************************************************************************/
 
-CPLErr netCDFRasterBand::CreateBandMetadata( int *paDimIds ) 
+CPLErr netCDFRasterBand::CreateBandMetadata( const int *paDimIds )
 
 {
-    char     szVarName[NC_MAX_NAME+1];
-    char     szMetaName[NC_MAX_NAME+1];
-    char     szMetaTemp[NCDF_MAX_STR_LEN];
-    char     *pszMetaValue = NULL;
-    char     szTemp[NC_MAX_NAME+1];
-
-    int      nd;
-    int      i,j;
-    int      Sum  = 1;
-    int      Taken = 0;
-    int      result = 0;
-    int      status;
-    int      nVarID = -1;
-    int      nDims;
-    size_t   start[1];
-    size_t   count[1];
-    nc_type  nVarType = NC_NAT;
-    int      nAtt=0;
-
-    netCDFDataset *poDS = (netCDFDataset *) this->poDS;
-  
+    netCDFDataset *l_poDS = reinterpret_cast<netCDFDataset *>( this->poDS );
+
 /* -------------------------------------------------------------------- */
 /*      Compute all dimensions from Band number and save in Metadata    */
 /* -------------------------------------------------------------------- */
+    char szVarName[NC_MAX_NAME+1];
     szVarName[0] = '\0';
-    nc_inq_varname( cdfid, nZId, szVarName );
+    int status = nc_inq_varname( cdfid, nZId, szVarName );
+    NCDF_ERR(status);
+
+    int nd;
     nc_inq_varndims( cdfid, nZId, &nd );
 /* -------------------------------------------------------------------- */
 /*      Compute multidimention band position                            */
@@ -952,9 +1064,8 @@ CPLErr netCDFRasterBand::CreateBandMetadata( int *paDimIds )
 /*  BandPos2 = (nBand - BandPos0*(3*4) ) % (4)                          */
 /* -------------------------------------------------------------------- */
 
-    sprintf( szMetaName,"NETCDF_VARNAME");
-    sprintf( szMetaTemp,"%s",szVarName);
-    SetMetadataItem( szMetaName, szMetaTemp );
+    SetMetadataItem( "NETCDF_VARNAME", szVarName );
+    int Sum = 1;
     if( nd == 3 ) {
         Sum *= panBandZLev[0];
     }
@@ -962,11 +1073,15 @@ CPLErr netCDFRasterBand::CreateBandMetadata( int *paDimIds )
 /* -------------------------------------------------------------------- */
 /*      Loop over non-spatial dimensions                                */
 /* -------------------------------------------------------------------- */
-    for( i=0; i < nd-2 ; i++ ) {
+    int nVarID = -1;
+    int result = 0;
+    int Taken = 0;
+
+    for( int i=0; i < nd-2 ; i++ ) {
 
         if( i != nd - 2 -1 ) {
             Sum = 1;
-            for( j=i+1; j < nd-2; j++ ) {
+            for( int j=i+1; j < nd-2; j++ ) {
                 Sum *= panBandZLev[j];
             }
             result = (int) ( ( nLevel-Taken) / Sum );
@@ -974,69 +1089,107 @@ CPLErr netCDFRasterBand::CreateBandMetadata( int *paDimIds )
         else {
             result = (int) ( ( nLevel-Taken) % Sum );
         }
-        
-        strcpy(szVarName, 
-               poDS->papszDimName[paDimIds[panBandZPos[i]]] );
 
-        status=nc_inq_varid( cdfid, szVarName, &nVarID );
+        snprintf(szVarName,sizeof(szVarName),"%s",
+               l_poDS->papszDimName[paDimIds[panBandZPos[i]]] );
+
+        // TODO: Make sure all the status checks make sense.
+
+        status = nc_inq_varid( cdfid, szVarName, &nVarID );
         if( status != NC_NOERR ) {
             /* Try to uppercase the first letter of the variable */
             /* Note: why is this needed? leaving for safety */
-            szVarName[0]=(char) toupper(szVarName[0]);
-            status=nc_inq_varid( cdfid, szVarName, &nVarID );
+            szVarName[0] = (char) toupper(szVarName[0]);
+            /* status = */nc_inq_varid( cdfid, szVarName, &nVarID );
         }
 
-        status = nc_inq_vartype( cdfid, nVarID, &nVarType );
+        nc_type nVarType = NC_NAT;
+        /* status = */ nc_inq_vartype( cdfid, nVarID, &nVarType );
 
-        nDims = 0;
-        status = nc_inq_varndims( cdfid, nVarID, &nDims );
+        int nDims = 0;
+        /* status = */ nc_inq_varndims( cdfid, nVarID, &nDims );
 
+        char szMetaTemp[256];
         if( nDims == 1 ) {
-            count[0]=1;
-            start[0]=result;
+            size_t count[1] = {1};
+            size_t start[1] = {static_cast<size_t>(result)};
+
             switch( nVarType ) {
+                case NC_BYTE:
+                    /* TODO: we should check for signed/unsigned byte */
+                    signed char cData;
+                    /* status = */ nc_get_vara_schar( cdfid, nVarID,
+                                                 start,
+                                                 count, &cData);
+                    snprintf( szMetaTemp, sizeof(szMetaTemp), "%d", cData );
+                    break;
                 case NC_SHORT:
                     short sData;
-                    status =  nc_get_vara_short( cdfid, nVarID, 
+                    /* status = */ nc_get_vara_short( cdfid, nVarID,
                                                  start,
                                                  count, &sData );
-                    sprintf( szMetaTemp,"%d", sData );
+                    snprintf( szMetaTemp, sizeof(szMetaTemp), "%d", sData );
                     break;
                 case NC_INT:
                     int nData;
-                    status =  nc_get_vara_int( cdfid, nVarID, 
+                    /* status = */ nc_get_vara_int( cdfid, nVarID,
                                                start,
                                                count, &nData );
-                    sprintf( szMetaTemp,"%d", nData );
+                    snprintf( szMetaTemp, sizeof(szMetaTemp), "%d", nData );
                     break;
                 case NC_FLOAT:
                     float fData;
-                    status =  nc_get_vara_float( cdfid, nVarID, 
+                    /* status = */ nc_get_vara_float( cdfid, nVarID,
                                                  start,
                                                  count, &fData );
-                    CPLsprintf( szMetaTemp,"%.8g", fData );
+                    CPLsnprintf( szMetaTemp, sizeof(szMetaTemp), "%.8g", fData );
                     break;
                 case NC_DOUBLE:
                     double dfData;
-                    status =  nc_get_vara_double( cdfid, nVarID, 
+                    /* status = */ nc_get_vara_double( cdfid, nVarID,
                                                   start,
                                                   count, &dfData);
-                    CPLsprintf( szMetaTemp,"%.16g", dfData );
+                    CPLsnprintf( szMetaTemp, sizeof(szMetaTemp), "%.16g", dfData );
+                    break;
+#ifdef NETCDF_HAS_NC4
+                case NC_UBYTE:
+                    unsigned char ucData;
+                    /* status = */ nc_get_vara_uchar( cdfid, nVarID,
+                                                 start,
+                                                 count, &ucData);
+                    snprintf( szMetaTemp, sizeof(szMetaTemp), "%u", ucData );
                     break;
-                default: 
-                    CPLDebug( "GDAL_netCDF", "invalid dim %s, type=%d", 
+                case NC_USHORT:
+                    unsigned short usData;
+                    /* status = */ nc_get_vara_ushort( cdfid, nVarID,
+                                                  start,
+                                                  count, &usData);
+                    snprintf( szMetaTemp, sizeof(szMetaTemp), "%u", usData );
+                    break;
+                case NC_UINT:
+                    unsigned int unData;
+                    /* status = */ nc_get_vara_uint( cdfid, nVarID,
+                                                start,
+                                                count, &unData);
+                    snprintf( szMetaTemp, sizeof(szMetaTemp), "%u", unData );
+                    break;
+#endif
+                default:
+                    CPLDebug( "GDAL_netCDF", "invalid dim %s, type=%d",
                               szMetaTemp, nVarType);
                     break;
             }
         }
         else
-            sprintf( szMetaTemp,"%d", result+1);
-	
+            snprintf( szMetaTemp, sizeof(szMetaTemp), "%d", result+1);
+
 /* -------------------------------------------------------------------- */
 /*      Save dimension value                                            */
 /* -------------------------------------------------------------------- */
         /* NOTE: removed #original_units as not part of CF-1 */
-        sprintf( szMetaName,"NETCDF_DIM_%s",  szVarName );
+
+        char szMetaName[NC_MAX_NAME+1+32];
+        snprintf( szMetaName, sizeof(szMetaName), "NETCDF_DIM_%s",  szVarName );
         SetMetadataItem( szMetaName, szMetaTemp );
 
         Taken += result * Sum;
@@ -1046,17 +1199,19 @@ CPLErr netCDFRasterBand::CreateBandMetadata( int *paDimIds )
 /* -------------------------------------------------------------------- */
 /*      Get all other metadata                                          */
 /* -------------------------------------------------------------------- */
+    int nAtt=0;
     nc_inq_varnatts( cdfid, nZId, &nAtt );
 
-    for( i=0; i < nAtt ; i++ ) {
+    for( int i=0; i < nAtt ; i++ ) {
 
-        szTemp[0] = '\0';
-    	status = nc_inq_attname( cdfid, nZId, i, szTemp);
-    	// if(strcmp(szTemp,_FillValue) ==0) continue;
-    	sprintf( szMetaName,"%s",szTemp);       
+        char szMetaName[NC_MAX_NAME+1];
+        szMetaName[0] = 0;
+        status = nc_inq_attname( cdfid, nZId, i, szMetaName);
+        if ( status != NC_NOERR )
+            continue;
 
-        if ( NCDFGetAttr( cdfid, nZId, szMetaName, &pszMetaValue) 
-             == CE_None ) {
+        char *pszMetaValue = NULL;
+        if ( NCDFGetAttr( cdfid, nZId, szMetaName, &pszMetaValue) == CE_None ) {
             SetMetadataItem( szMetaName, pszMetaValue );
         }
         else {
@@ -1077,49 +1232,42 @@ CPLErr netCDFRasterBand::CreateBandMetadata( int *paDimIds )
 /*                             CheckData()                              */
 /************************************************************************/
 template <class T>
-void  netCDFRasterBand::CheckData ( void * pImage, 
-                                    int nTmpBlockXSize, int nTmpBlockYSize,
-                                    int bCheckIsNan ) 
+void  netCDFRasterBand::CheckData ( void * pImage, void * pImageNC,
+                                    size_t nTmpBlockXSize, size_t nTmpBlockYSize,
+                                    bool bCheckIsNan )
 {
-  int i, j, k;
-
-  CPLAssert( pImage != NULL );
+  CPLAssert( pImage != NULL && pImageNC != NULL );
 
-  /* if this block is not a full block (in the x axis), we need to re-arrange the data 
+  /* if this block is not a full block (in the x axis), we need to re-arrange the data
      this is because partial blocks are not arranged the same way in netcdf and gdal */
-  if ( nTmpBlockXSize != nBlockXSize ) {
-    T* ptr = (T *) CPLCalloc( nTmpBlockXSize*nTmpBlockYSize, sizeof( T ) );
-    memcpy( ptr, pImage, nTmpBlockXSize*nTmpBlockYSize*sizeof( T ) );
-    for( j=0; j<nTmpBlockYSize; j++) {
-      k = j*nBlockXSize;
-      for( i=0; i<nTmpBlockXSize; i++,k++)
-        ((T *) pImage)[k] = ptr[j*nTmpBlockXSize+i];
-      for( i=nTmpBlockXSize; i<nBlockXSize; i++,k++)
-        ((T *) pImage)[k] = (T)dfNoDataValue;
-    }
-    CPLFree( ptr );
+  if ( nTmpBlockXSize != static_cast<size_t>(nBlockXSize) ) {
+    T* ptrWrite = (T *) pImage;
+    T* ptrRead = (T *) pImageNC;
+    for( size_t j=0; j<nTmpBlockYSize; j++, ptrWrite += nBlockXSize, ptrRead += nTmpBlockXSize) {
+        memmove( ptrWrite, ptrRead, nTmpBlockXSize * sizeof(T) );
+    }
   }
-  
+
   /* is valid data checking needed or requested? */
-  if ( (adfValidRange[0] != dfNoDataValue) || 
+  if ( (adfValidRange[0] != dfNoDataValue) ||
        (adfValidRange[1] != dfNoDataValue) ||
        bCheckIsNan ) {
-    for( j=0; j<nTmpBlockYSize; j++) {
+    for( size_t j=0; j<nTmpBlockYSize; j++) {
       // k moves along the gdal block, skipping the out-of-range pixels
-      k = j*nBlockXSize;
-      for( i=0; i<nTmpBlockXSize; i++,k++) {
+      size_t k = j*nBlockXSize;
+      for( size_t i=0; i<nTmpBlockXSize; i++,k++) {
         /* check for nodata and nan */
         if ( CPLIsEqual( (double) ((T *)pImage)[k], dfNoDataValue ) )
           continue;
-        if( bCheckIsNan && CPLIsNan( (double) (( (T *) pImage))[k] ) ) { 
+        if( bCheckIsNan && CPLIsNan( (double) (( (T *) pImage))[k] ) ) {
           ( (T *)pImage )[k] = (T)dfNoDataValue;
           continue;
         }
         /* check for valid_range */
-        if ( ( ( adfValidRange[0] != dfNoDataValue ) && 
-               ( ((T *)pImage)[k] < (T)adfValidRange[0] ) ) 
-             || 
-             ( ( adfValidRange[1] != dfNoDataValue ) && 
+        if ( ( ( adfValidRange[0] != dfNoDataValue ) &&
+               ( ((T *)pImage)[k] < (T)adfValidRange[0] ) )
+             ||
+             ( ( adfValidRange[1] != dfNoDataValue ) &&
                ( ((T *)pImage)[k] > (T)adfValidRange[1] ) ) ) {
           ( (T *)pImage )[k] = (T)dfNoDataValue;
         }
@@ -1127,22 +1275,22 @@ void  netCDFRasterBand::CheckData ( void * pImage,
     }
   }
 
-  /* if mininum longitude is > 180, subtract 360 from all 
-     if not, disable checking for further calls (check just once) 
-     only check first and last block elements since lon must be monotonic */
-  if ( bCheckLongitude && 
+  /* If minimum longitude is > 180, subtract 360 from all.
+     If not, disable checking for further calls (check just once).
+     Only check first and last block elements since lon must be monotonic. */
+  const bool bIsSigned = std::numeric_limits<T>::is_signed;
+  if ( bCheckLongitude && bIsSigned &&
        MIN( ((T *)pImage)[0], ((T *)pImage)[nTmpBlockXSize-1] ) > 180.0 ) {
-    for( j=0; j<nTmpBlockYSize; j++) {
-      k = j*nBlockXSize;
-      for( i=0; i<nTmpBlockXSize; i++,k++) {
+    for( size_t j=0; j<nTmpBlockYSize; j++) {
+      size_t k = j*nBlockXSize;
+      for( size_t i=0; i<nTmpBlockXSize; i++,k++) {
         if ( ! CPLIsEqual( (double) ((T *)pImage)[k], dfNoDataValue ) )
-          ((T *)pImage )[k] -= 360.0;
+          ((T *)pImage )[k] = static_cast<T>(((T *)pImage )[k] - 360);
       }
     }
   }
-  else 
-    bCheckLongitude = FALSE;
-  
+  else
+    bCheckLongitude = false;
 }
 
 /************************************************************************/
@@ -1153,21 +1301,11 @@ CPLErr netCDFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                      void * pImage )
 
 {
-    size_t start[ MAX_NC_DIMS ];
-    size_t edge[ MAX_NC_DIMS ];
-    char   pszName[ NCDF_MAX_STR_LEN ];
-    int    i,j;
-    int    Sum=-1;
-    int    Taken=-1;
-    int    nd=0;
-
     CPLMutexHolderD(&hNCMutex);
 
-    *pszName='\0';
-    memset( start, 0, sizeof( start ) );
-    memset( edge,  0, sizeof( edge )  );
+    int nd = 0;
     nc_inq_varndims ( cdfid, nZId, &nd );
-    
+
 #ifdef NCDF_DEBUG
     if ( (nBlockYOff == 0) || (nBlockYOff == nRasterYSize-1) )
         CPLDebug( "GDAL_netCDF", "netCDFRasterBand::IReadBlock( %d, %d, ... ) nBand=%d nd=%d",
@@ -1177,14 +1315,16 @@ CPLErr netCDFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
 /*      Locate X, Y and Z position in the array                         */
 /* -------------------------------------------------------------------- */
-	
+
+    size_t start[ MAX_NC_DIMS ];
+    memset( start, 0, sizeof( start ) );
     start[nBandXPos] = nBlockXOff * nBlockXSize;
 
     // check y order
     if( ( ( netCDFDataset *) poDS )->bBottomUp ) {
 #ifdef NCDF_DEBUG
       if ( (nBlockYOff == 0) || (nBlockYOff == nRasterYSize-1) )
-        CPLDebug( "GDAL_netCDF", 
+        CPLDebug( "GDAL_netCDF",
                   "reading bottom-up dataset, nBlockYSize=%d nRasterYSize=%d",
                   nBlockYSize, nRasterYSize );
 #endif
@@ -1192,17 +1332,20 @@ CPLErr netCDFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
       // reading upside-down rasters with nBlockYSize!=1 needs further development
       // perhaps a simple solution is to invert geotransform and not use bottom-up
       if ( nBlockYSize == 1 ) {
-        start[nBandYPos] = nRasterYSize - 1 - nBlockYOff;       
+        start[nBandYPos] = nRasterYSize - 1 - nBlockYOff;
       }
       else {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "nBlockYSize = %d, only 1 supported when reading bottom-up dataset", nBlockYSize );
         return CE_Failure;
-      }      
+      }
     } else {
       start[nBandYPos] = nBlockYOff * nBlockYSize;
     }
-        
+
+    size_t edge[ MAX_NC_DIMS ];
+    memset( edge,  0, sizeof( edge )  );
+
     edge[nBandXPos] = nBlockXSize;
     if ( ( start[nBandXPos] + edge[nBandXPos] ) > (size_t)nRasterXSize )
        edge[nBandXPos] = nRasterXSize - start[nBandXPos];
@@ -1213,10 +1356,10 @@ CPLErr netCDFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 #ifdef NCDF_DEBUG
     if ( (nBlockYOff == 0) || (nBlockYOff == nRasterYSize-1) )
       CPLDebug( "GDAL_netCDF", "start={%ld,%ld} edge={%ld,%ld} bBottomUp=%d",
-                start[nBandXPos], start[nBandYPos], edge[nBandXPos], edge[nBandYPos], 
+                start[nBandXPos], start[nBandYPos], edge[nBandXPos], edge[nBandYPos],
                 ( ( netCDFDataset *) poDS )->bBottomUp );
 #endif
-     
+
     if( nd == 3 ) {
         start[panBandZPos[0]]  = nLevel;     // z
         edge [panBandZPos[0]]  = 1;
@@ -1232,14 +1375,15 @@ CPLErr netCDFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /*  BandPos1 = (nBand - (3*4) ) / (4)                                   */
 /*  BandPos2 = (nBand - (3*4) ) % (4)                                   */
 /* -------------------------------------------------------------------- */
-    if (nd > 3) 
+    if (nd > 3)
     {
-        Taken = 0;
-        for( i=0; i < nd-2 ; i++ ) 
+        int Sum = -1;
+        int Taken = 0;
+        for( int i=0; i < nd-2 ; i++ )
         {
             if( i != nd - 2 -1 ) {
                 Sum = 1;
-                for( j=i+1; j < nd-2; j++ ) {
+                for( int j=i+1; j < nd-2; j++ ) {
                     Sum *= panBandZLev[j];
                 }
                 start[panBandZPos[i]] = (int) ( ( nLevel-Taken) / Sum );
@@ -1248,88 +1392,121 @@ CPLErr netCDFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                 start[panBandZPos[i]] = (int) ( ( nLevel-Taken) % Sum );
                 edge[panBandZPos[i]] = 1;
             }
-            Taken += start[panBandZPos[i]] * Sum;
+            Taken += static_cast<int>(start[panBandZPos[i]]) * Sum;
         }
     }
 
     /* make sure we are in data mode */
-    ( ( netCDFDataset * ) poDS )->SetDefineMode( FALSE );
+    ( ( netCDFDataset * ) poDS )->SetDefineMode( false );
+
+    /*
+     * If this block is not a full block in the x axis, we need to
+     * re-arrange the data because partial blocks are not arranged the
+     * same way in netcdf and gdal, so we first we read the netcdf data at
+     * the end of the gdal block buffer then re-arrange rows in CheckData().
+     */
+    void *pImageNC = pImage;
+    if( edge[nBandXPos] != (size_t) nBlockXSize )
+    {
+        pImageNC = (GByte *) pImage
+            + ( (nBlockXSize * nBlockYSize - edge[nBandXPos] * edge[nBandYPos])
+                * (GDALGetDataTypeSize(eDataType) / 8) );
+    }
 
     /* read data according to type */
-    if( eDataType == GDT_Byte ) 
+    int status;
+    if( eDataType == GDT_Byte )
     {
-        if (this->bSignedData) 
+        if (this->bSignedData)
         {
-            status = nc_get_vara_schar( cdfid, nZId, start, edge, 
-                                        (signed char *) pImage );
-            if ( status == NC_NOERR ) 
-                CheckData<signed char>( pImage, edge[nBandXPos], edge[nBandYPos], 
-                                        FALSE );           
+            status = nc_get_vara_schar( cdfid, nZId, start, edge,
+                                        (signed char *) pImageNC );
+            if ( status == NC_NOERR )
+                CheckData<signed char>( pImage, pImageNC, edge[nBandXPos], edge[nBandYPos],
+                                        false );
         }
         else {
-            status = nc_get_vara_uchar( cdfid, nZId, start, edge, 
-                                        (unsigned char *) pImage );
-            if ( status == NC_NOERR ) 
-                CheckData<unsigned char>( pImage, edge[nBandXPos], edge[nBandYPos], 
-                                          FALSE ); 
+            status = nc_get_vara_uchar( cdfid, nZId, start, edge,
+                                        (unsigned char *) pImageNC );
+            if ( status == NC_NOERR )
+                CheckData<unsigned char>( pImage, pImageNC, edge[nBandXPos], edge[nBandYPos],
+                                          false );
         }
     }
 
     else if( eDataType == GDT_Int16 )
     {
-        status = nc_get_vara_short( cdfid, nZId, start, edge, 
-                                    (short int *) pImage );
-        if ( status == NC_NOERR ) 
-            CheckData<short int>( pImage, edge[nBandXPos], edge[nBandYPos], 
-                                  FALSE ); 
+        status = nc_get_vara_short( cdfid, nZId, start, edge,
+                                    (short *) pImageNC );
+        if ( status == NC_NOERR )
+            CheckData<short>( pImage, pImageNC, edge[nBandXPos], edge[nBandYPos],
+                              false );
     }
     else if( eDataType == GDT_Int32 )
     {
         if( sizeof(long) == 4 )
         {
-            status = nc_get_vara_long( cdfid, nZId, start, edge, 
-                                       (long int *) pImage );
-            if ( status == NC_NOERR ) 
-                CheckData<long int>( pImage, edge[nBandXPos], edge[nBandYPos], 
-                                     FALSE ); 
+            status = nc_get_vara_long( cdfid, nZId, start, edge,
+                                       (long *) pImageNC );
+            if ( status == NC_NOERR )
+                CheckData<long>( pImage, pImageNC, edge[nBandXPos], edge[nBandYPos],
+                                 false );
         }
         else
         {
-            status = nc_get_vara_int( cdfid, nZId, start, edge, 
-                                      (int *) pImage );
-            if ( status == NC_NOERR ) 
-                CheckData<int>( pImage, edge[nBandXPos], edge[nBandYPos], 
-                                FALSE ); 
+            status = nc_get_vara_int( cdfid, nZId, start, edge,
+                                      (int *) pImageNC );
+            if ( status == NC_NOERR )
+                CheckData<int>( pImage, pImageNC, edge[nBandXPos], edge[nBandYPos],
+                                false );
         }
     }
     else if( eDataType == GDT_Float32 )
     {
-        status = nc_get_vara_float( cdfid, nZId, start, edge, 
-                                    (float *) pImage );
-        if ( status == NC_NOERR ) 
-            CheckData<float>( pImage, edge[nBandXPos], edge[nBandYPos], 
-                              TRUE ); 
+        status = nc_get_vara_float( cdfid, nZId, start, edge,
+                                    (float *) pImageNC );
+        if ( status == NC_NOERR )
+            CheckData<float>( pImage, pImageNC, edge[nBandXPos], edge[nBandYPos],
+                              true );
     }
     else if( eDataType == GDT_Float64 )
     {
-        status = nc_get_vara_double( cdfid, nZId, start, edge, 
-                                     (double *) pImage ); 
-        if ( status == NC_NOERR ) 
-            CheckData<double>( pImage, edge[nBandXPos], edge[nBandYPos], 
-                               TRUE ); 
-    } 
+        status = nc_get_vara_double( cdfid, nZId, start, edge,
+                                     (double *) pImageNC );
+        if ( status == NC_NOERR )
+            CheckData<double>( pImage, pImageNC, edge[nBandXPos], edge[nBandYPos],
+                               true );
+    }
+#ifdef NETCDF_HAS_NC4
+    else if( eDataType == GDT_UInt16 )
+    {
+        status = nc_get_vara_ushort( cdfid, nZId, start, edge,
+                                    (unsigned short *) pImageNC );
+        if ( status == NC_NOERR )
+            CheckData<unsigned short>( pImage, pImageNC, edge[nBandXPos], edge[nBandYPos],
+                                       false );
+    }
+    else if( eDataType == GDT_UInt32 )
+    {
+        status = nc_get_vara_uint( cdfid, nZId, start, edge,
+                                   (unsigned int *) pImageNC );
+        if ( status == NC_NOERR )
+            CheckData<unsigned int>( pImage, pImageNC, edge[nBandXPos], edge[nBandYPos],
+                                     false );
+    }
+#endif
     else
         status = NC_EBADTYPE;
 
     if( status != NC_NOERR )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "netCDF scanline fetch failed: #%d (%s)", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "netCDF scanline fetch failed: #%d (%s)",
                   status, nc_strerror( status ) );
         return CE_Failure;
     }
-    else
-        return CE_None;
+
+    return CE_None;
 }
 
 /************************************************************************/
@@ -1340,14 +1517,6 @@ CPLErr netCDFRasterBand::IWriteBlock( CPL_UNUSED int nBlockXOff,
                                       int nBlockYOff,
                                       void * pImage )
 {
-    size_t start[ MAX_NC_DIMS];
-    size_t edge[ MAX_NC_DIMS ];
-    char   pszName[ NCDF_MAX_STR_LEN ];
-    int    i,j;
-    int    Sum=-1;
-    int    Taken=-1;
-    int    nd;
-
     CPLMutexHolderD(&hNCMutex);
 
 #ifdef NCDF_DEBUG
@@ -1356,31 +1525,35 @@ CPLErr netCDFRasterBand::IWriteBlock( CPL_UNUSED int nBlockXOff,
                   nBlockXOff, nBlockYOff, nBand );
 #endif
 
-    *pszName='\0';
-    memset( start, 0, sizeof( start ) );
-    memset( edge,  0, sizeof( edge )  );
+    int nd;
     nc_inq_varndims ( cdfid, nZId, &nd );
-  
+
 /* -------------------------------------------------------------------- */
 /*      Locate X, Y and Z position in the array                         */
 /* -------------------------------------------------------------------- */
-	
-    start[nBandXPos] = 0;          // x dim can move arround in array
+
+    size_t start[ MAX_NC_DIMS];
+    memset( start, 0, sizeof( start ) );
+
+    start[nBandXPos] = 0;          // x dim can move around in array
     // check y order
     if( ( ( netCDFDataset *) poDS )->bBottomUp ) {
         start[nBandYPos] = nRasterYSize - 1 - nBlockYOff;
     } else {
         start[nBandYPos] = nBlockYOff; // y
     }
-        
-    edge[nBandXPos] = nBlockXSize; 
-    edge[nBandYPos] = 1;
+
+    size_t edge[ MAX_NC_DIMS ];
+    memset( edge,  0, sizeof( edge )  );
+
+    edge[nBandXPos] = nBlockXSize;
+    edge[nBandYPos] = 1;
 
     if( nd == 3 ) {
         start[panBandZPos[0]]  = nLevel;     // z
         edge [panBandZPos[0]]  = 1;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Compute multidimention band position                            */
 /*                                                                      */
@@ -1391,14 +1564,15 @@ CPLErr netCDFRasterBand::IWriteBlock( CPL_UNUSED int nBlockXOff,
 /*  BandPos1 = (nBand - (3*4) ) / (4)                                   */
 /*  BandPos2 = (nBand - (3*4) ) % (4)                                   */
 /* -------------------------------------------------------------------- */
-    if (nd > 3) 
+    if (nd > 3)
     {
-        Taken = 0;
-        for( i=0; i < nd-2 ; i++ ) 
+        int Sum = -1;
+        int Taken = 0;
+        for( int i=0; i < nd-2 ; i++ )
         {
             if( i != nd - 2 -1 ) {
                 Sum = 1;
-                for( j=i+1; j < nd-2; j++ ) {
+                for( int j=i+1; j < nd-2; j++ ) {
                     Sum *= panBandZLev[j];
                 }
                 start[panBandZPos[i]] = (int) ( ( nLevel-Taken) / Sum );
@@ -1407,38 +1581,51 @@ CPLErr netCDFRasterBand::IWriteBlock( CPL_UNUSED int nBlockXOff,
                 start[panBandZPos[i]] = (int) ( ( nLevel-Taken) % Sum );
                 edge[panBandZPos[i]] = 1;
             }
-            Taken += start[panBandZPos[i]] * Sum;
+            Taken += static_cast<int>(start[panBandZPos[i]]) * Sum;
         }
     }
-    
+
     /* make sure we are in data mode */
-    ( ( netCDFDataset * ) poDS )->SetDefineMode( FALSE );
+    ( ( netCDFDataset * ) poDS )->SetDefineMode( false );
 
     /* copy data according to type */
+    int status;
     if( eDataType == GDT_Byte ) {
-        if ( this->bSignedData ) 
-            status = nc_put_vara_schar( cdfid, nZId, start, edge, 
+        if ( this->bSignedData )
+            status = nc_put_vara_schar( cdfid, nZId, start, edge,
                                          (signed char*) pImage);
         else
-            status = nc_put_vara_uchar( cdfid, nZId, start, edge, 
+            status = nc_put_vara_uchar( cdfid, nZId, start, edge,
                                          (unsigned char*) pImage);
     }
-    else if( ( eDataType == GDT_UInt16 ) || ( eDataType == GDT_Int16 ) ) {
-        status = nc_put_vara_short( cdfid, nZId, start, edge, 
-                                     (short int *) pImage);
+    else if( eDataType == GDT_Int16 ) {
+        status = nc_put_vara_short( cdfid, nZId, start, edge,
+                                    (short *) pImage);
     }
     else if( eDataType == GDT_Int32 ) {
-        status = nc_put_vara_int( cdfid, nZId, start, edge, 
+        status = nc_put_vara_int( cdfid, nZId, start, edge,
                                    (int *) pImage);
     }
     else if( eDataType == GDT_Float32 ) {
-        status = nc_put_vara_float( cdfid, nZId, start, edge, 
+        status = nc_put_vara_float( cdfid, nZId, start, edge,
                                     (float *) pImage);
     }
     else if( eDataType == GDT_Float64 ) {
-        status = nc_put_vara_double( cdfid, nZId, start, edge, 
+        status = nc_put_vara_double( cdfid, nZId, start, edge,
                                      (double *) pImage);
     }
+#ifdef NETCDF_HAS_NC4
+    else if( eDataType == GDT_UInt16
+             && ((netCDFDataset *) poDS)->eFormat == NCDF_FORMAT_NC4 ) {
+        status = nc_put_vara_ushort( cdfid, nZId, start, edge,
+                                     (unsigned short *) pImage);
+    }
+    else if( eDataType == GDT_UInt32
+             && ((netCDFDataset *) poDS)->eFormat == NCDF_FORMAT_NC4 ) {
+        status = nc_put_vara_uint( cdfid, nZId, start, edge,
+                                   (unsigned int *) pImage);
+    }
+#endif
     else {
         CPLError( CE_Failure, CPLE_NotSupported,
                   "The NetCDF driver does not support GDAL data type %d",
@@ -1449,19 +1636,18 @@ CPLErr netCDFRasterBand::IWriteBlock( CPL_UNUSED int nBlockXOff,
 
     if( status != NC_NOERR )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "netCDF scanline write failed: %s", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "netCDF scanline write failed: %s",
                   nc_strerror( status ) );
         return CE_Failure;
     }
-    else 
-        return CE_None;
 
+    return CE_None;
 }
 
 /************************************************************************/
 /* ==================================================================== */
-/*				netCDFDataset				                            */
+/*                              netCDFDataset                           */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -1469,18 +1655,46 @@ CPLErr netCDFRasterBand::IWriteBlock( CPL_UNUSED int nBlockXOff,
 /*                           netCDFDataset()                            */
 /************************************************************************/
 
-netCDFDataset::netCDFDataset()
-
+netCDFDataset::netCDFDataset() :
+    // Basic dataset vars.
+    cdfid(-1),
+    papszSubDatasets(NULL),
+    papszMetadata(NULL),
+    bBottomUp(true),
+    eFormat(NCDF_FORMAT_NONE),
+    bIsGdalFile(false),
+    bIsGdalCfFile(false),
+
+    pszCFProjection(NULL),
+    pszCFCoordinates(NULL),
+    eMultipleLayerBehaviour(SINGLE_LAYER),
+
+    // projection/GT.
+    pszProjection(NULL),
+    nXDimID(-1),
+    nYDimID(-1),
+    bIsProjected(false),
+    bIsGeographic(false),  // Can be not projected, and also not geographic
+
+    // State vars.
+    bDefineMode(true),
+    bSetProjection(false),
+    bSetGeoTransform(false),
+    bAddedProjectionVars(false),
+    bAddedGridMappingRef(false),
+
+    // Create vars.
+    papszCreationOptions(NULL),
+    eCompress(NCDF_COMPRESS_NONE),
+    nZLevel(NCDF_DEFLATE_LEVEL),
+#ifdef NETCDF_HAS_NC4
+    bChunking(false),
+#endif
+    nCreateMode(NC_CLOBBER),
+    bSignedData(true),
+    nLayers(0),
+    papoLayers(NULL)
 {
-    /* basic dataset vars */
-    cdfid            = -1;
-    papszSubDatasets = NULL;
-    papszMetadata    = NULL;	
-    bBottomUp        = TRUE;
-    nFormat          = NCDF_FORMAT_NONE;
-    bIsGdalFile      = FALSE;
-    bIsGdalCfFile    = FALSE;
-
     /* projection/GT */
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
@@ -1488,31 +1702,8 @@ netCDFDataset::netCDFDataset()
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
-    pszProjection    = NULL;
-    nXDimID = -1;
-    nYDimID = -1;
-    bIsProjected = FALSE;
-    bIsGeographic = FALSE; /* can be not projected, and also not geographic */
-    pszCFProjection = NULL;
-    pszCFCoordinates = NULL;
-
-    /* state vars */
-    status = NC_NOERR;
-    bDefineMode = TRUE;    
-    bSetProjection = FALSE;
-    bSetGeoTransform = FALSE;    
-    bAddedProjectionVars = FALSE;
-    bAddedGridMappingRef = FALSE;
-
-    /* create vars */
-    papszCreationOptions = NULL;
-    nCompress = NCDF_COMPRESS_NONE;
-    nZLevel = NCDF_DEFLATE_LEVEL;
-    nCreateMode = NC_CLOBBER;
-    bSignedData = TRUE;
 }
 
-
 /************************************************************************/
 /*                           ~netCDFDataset()                           */
 /************************************************************************/
@@ -1532,12 +1723,19 @@ netCDFDataset::~netCDFDataset()
             AddProjectionVars();
         else if ( bSetGeoTransform && ! bSetProjection )
             AddProjectionVars();
-            // CPLError( CE_Warning, CPLE_AppDefined, 
+            // CPLError( CE_Warning, CPLE_AppDefined,
             //           "netCDFDataset::~netCDFDataset() Projection was not defined, projection will be missing" );
     }
 
     FlushCache();
 
+    for(int i=0;i<nLayers;i++)
+        delete papoLayers[i];
+    CPLFree(papoLayers);
+
+    for(size_t i=0; i<apoVectorDatasets.size();i++)
+        delete apoVectorDatasets[i];
+
     /* make sure projection variable is written to band variable */
     if( (GetAccess() == GA_Update) && ! bAddedGridMappingRef )
         AddGridMappingRef();
@@ -1546,46 +1744,43 @@ netCDFDataset::~netCDFDataset()
     CSLDestroy( papszSubDatasets );
     CSLDestroy( papszCreationOptions );
 
-    if( pszProjection )
-        CPLFree( pszProjection );
-    if( pszCFProjection )
-        CPLFree( pszCFProjection );
-    if( pszCFCoordinates )
-        CPLFree( pszCFCoordinates );
+    CPLFree( pszProjection );
+    CPLFree( pszCFProjection );
+    CPLFree( pszCFCoordinates );
 
     if( cdfid > 0 ) {
 #ifdef NCDF_DEBUG
         CPLDebug( "GDAL_netCDF", "calling nc_close( %d )", cdfid );
 #endif
-        status = nc_close( cdfid );
+        int status = nc_close( cdfid );
         NCDF_ERR(status);
     }
-
 }
 
 /************************************************************************/
 /*                            SetDefineMode()                           */
 /************************************************************************/
-int netCDFDataset::SetDefineMode( int bNewDefineMode )
+bool netCDFDataset::SetDefineMode( bool bNewDefineMode )
 {
     /* do nothing if already in new define mode
        or if dataset is in read-only mode */
-    if ( ( bDefineMode == bNewDefineMode ) || 
-         ( GetAccess() == GA_ReadOnly ) ) 
-        return CE_None;
+    if ( ( bDefineMode == bNewDefineMode ) ||
+         ( GetAccess() == GA_ReadOnly ) )
+        return true;
 
     CPLDebug( "GDAL_netCDF", "SetDefineMode(%d) old=%d",
-              bNewDefineMode, bDefineMode );
+              static_cast<int>(bNewDefineMode), static_cast<int>(bDefineMode) );
 
     bDefineMode = bNewDefineMode;
-    
-    if ( bDefineMode == TRUE ) 
+
+    int status;
+    if ( bDefineMode )
         status = nc_redef( cdfid );
     else
         status = nc_enddef( cdfid );
 
     NCDF_ERR(status);
-    return status;
+    return (status == NC_NOERR);
 }
 
 /************************************************************************/
@@ -1604,10 +1799,10 @@ char **netCDFDataset::GetMetadataDomainList()
 /************************************************************************/
 char **netCDFDataset::GetMetadata( const char *pszDomain )
 {
-    if( pszDomain != NULL && EQUALN( pszDomain, "SUBDATASETS", 11 ) )
+    if( pszDomain != NULL && STARTS_WITH_CI(pszDomain, "SUBDATASETS") )
         return papszSubDatasets;
-    else
-        return GDALDataset::GetMetadata( pszDomain );
+
+    return GDALDataset::GetMetadata( pszDomain );
 }
 
 /************************************************************************/
@@ -1618,8 +1813,8 @@ const char * netCDFDataset::GetProjectionRef()
 {
     if( bSetProjection )
         return pszProjection;
-    else
-        return GDALPamDataset::GetProjectionRef();
+
+    return GDALPamDataset::GetProjectionRef();
 }
 
 /************************************************************************/
@@ -1630,38 +1825,30 @@ CPLXMLNode *netCDFDataset::SerializeToXML( const char *pszUnused )
 
 {
 /* -------------------------------------------------------------------- */
-/*      Overriden from GDALPamDataset to add only band histogram        */
+/*      Overridden from GDALPamDataset to add only band histogram        */
 /*      and statistics. See bug #4244.                                  */
 /* -------------------------------------------------------------------- */
 
-    CPLString oFmt;
-
     if( psPam == NULL )
         return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Setup root node and attributes.                                 */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psDSTree;
-
-    psDSTree = CPLCreateXMLNode( NULL, CXT_Element, "PAMDataset" );
+    CPLXMLNode *psDSTree = CPLCreateXMLNode( NULL, CXT_Element, "PAMDataset" );
 
 /* -------------------------------------------------------------------- */
 /*      Process bands.                                                  */
 /* -------------------------------------------------------------------- */
-    int iBand;
-
-    for( iBand = 0; iBand < GetRasterCount(); iBand++ )
+    for( int iBand = 0; iBand < GetRasterCount(); iBand++ )
     {
-        CPLXMLNode *psBandTree;
-
-        netCDFRasterBand *poBand = (netCDFRasterBand *) 
+        netCDFRasterBand *poBand = (netCDFRasterBand *)
             GetRasterBand(iBand+1);
 
         if( poBand == NULL || !(poBand->GetMOFlags() & GMO_PAM_CLASS) )
             continue;
 
-        psBandTree = poBand->SerializeToXML( pszUnused );
+        CPLXMLNode *psBandTree = poBand->SerializeToXML( pszUnused );
 
         if( psBandTree != NULL )
             CPLAddXMLChild( psDSTree, psBandTree );
@@ -1684,24 +1871,20 @@ CPLXMLNode *netCDFDataset::SerializeToXML( const char *pszUnused )
 /*                           FetchCopyParm()                            */
 /************************************************************************/
 
-double netCDFDataset::FetchCopyParm( const char *pszGridMappingValue, 
+double netCDFDataset::FetchCopyParm( const char *pszGridMappingValue,
                                      const char *pszParm, double dfDefault )
 
 {
-    char         szTemp[ MAX_NC_NAME ];
-    const char  *pszValue;
-
-    strcpy(szTemp,pszGridMappingValue);
-    strcat( szTemp, "#" );
-    strcat( szTemp, pszParm );
-    pszValue = CSLFetchNameValue(papszMetadata, szTemp);
+    char szTemp[ 256 ];
+    snprintf(szTemp, sizeof(szTemp), "%s#%s", pszGridMappingValue, pszParm);
+    const char *pszValue = CSLFetchNameValue(papszMetadata, szTemp);
 
     if( pszValue )
     {
         return CPLAtofM(pszValue);
     }
-    else
-        return dfDefault;
+
+    return dfDefault;
 }
 
 /************************************************************************/
@@ -1710,56 +1893,41 @@ double netCDFDataset::FetchCopyParm( const char *pszGridMappingValue,
 
 char** netCDFDataset::FetchStandardParallels( const char *pszGridMappingValue )
 {
-    char         szTemp[ MAX_NC_NAME ];
-    const char   *pszValue;
-    char         **papszValues = NULL;
+    char         szTemp[256 ];
     //cf-1.0 tags
-    strcpy( szTemp,pszGridMappingValue );
-    strcat( szTemp, "#" );
-    strcat( szTemp, CF_PP_STD_PARALLEL );
-    pszValue = CSLFetchNameValue( papszMetadata, szTemp );
+    snprintf(szTemp, sizeof(szTemp), "%s#%s", pszGridMappingValue, CF_PP_STD_PARALLEL);
+    const char *pszValue = CSLFetchNameValue( papszMetadata, szTemp );
+
+    char **papszValues = NULL;
     if( pszValue != NULL ) {
         papszValues = NCDFTokenizeArray( pszValue );
     }
     //try gdal tags
     else
     {
-        strcpy( szTemp, pszGridMappingValue );
-        strcat( szTemp, "#" );
-        strcat( szTemp, CF_PP_STD_PARALLEL_1 );
+        snprintf(szTemp, sizeof(szTemp), "%s#%s", pszGridMappingValue, CF_PP_STD_PARALLEL_1);
 
         pszValue = CSLFetchNameValue( papszMetadata, szTemp );
-	
+
         if ( pszValue != NULL )
             papszValues = CSLAddString( papszValues, pszValue );
-				    
-        strcpy( szTemp,pszGridMappingValue );
-        strcat( szTemp, "#" );
-        strcat( szTemp, CF_PP_STD_PARALLEL_2 );
+
+        snprintf(szTemp, sizeof(szTemp), "%s#%s", pszGridMappingValue, CF_PP_STD_PARALLEL_2);
 
         pszValue = CSLFetchNameValue( papszMetadata, szTemp );
-	
-        if( pszValue != NULL )	
+
+        if( pszValue != NULL )
             papszValues = CSLAddString( papszValues, pszValue );
     }
-    
+
     return papszValues;
 }
 
 /************************************************************************/
 /*                      SetProjectionFromVar()                          */
 /************************************************************************/
-void netCDFDataset::SetProjectionFromVar( int nVarId )
+void netCDFDataset::SetProjectionFromVar( int nVarId, bool bReadSRSOnly )
 {
-    size_t       start[2], edge[2];
-    unsigned int i=0;
-    const char   *pszValue = NULL;
-    int          nVarProjectionID = -1;
-    char         szVarName[ MAX_NC_NAME+1 ];
-    char         szTemp[ MAX_NC_NAME ];
-    char         szGridMappingName[ MAX_NC_NAME ];
-    char         szGridMappingValue[ MAX_NC_NAME ];
-
     double       dfStdP1=0.0;
     double       dfStdP2=0.0;
     double       dfCenterLat=0.0;
@@ -1774,27 +1942,24 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
     const char   *pszPMName=NULL;
     double       dfSemiMajorAxis=0.0;
     double       dfSemiMinorAxis=0.0;
-    
-    int          bGotGeogCS = FALSE;
-    int          bGotCfSRS = FALSE;
-    int          bGotGdalSRS = FALSE;
-    int          bGotCfGT = FALSE;
-    int          bGotGdalGT = FALSE;
-    int          bLookForWellKnownGCS = FALSE;  //this could be a Config Option
+
+    bool         bGotGeogCS = false;
+    bool         bGotCfSRS = false;
+    bool         bGotGdalSRS = false;
+    bool         bGotCfGT = false;
+    bool         bGotGdalGT = false;
 
     /* These values from CF metadata */
     OGRSpatialReference oSRS;
-    int          nVarDimXID = -1;
-    int          nVarDimYID = -1;
     double       *pdfXCoord = NULL;
     double       *pdfYCoord = NULL;
-    char         szDimNameX[ MAX_NC_NAME+1 ];
-    char         szDimNameY[ MAX_NC_NAME+1 ];
+    char         szDimNameX[ NC_MAX_NAME+1 ];
+    //char         szDimNameY[ NC_MAX_NAME+1 ];
     int          nSpacingBegin=0;
     int          nSpacingMiddle=0;
     int          nSpacingLast=0;
-    int          bLatSpacingOK=FALSE;
-    int          bLonSpacingOK=FALSE;
+    bool         bLatSpacingOK=false;
+    bool         bLonSpacingOK=false;
     size_t       xdim = nRasterXSize;
     size_t       ydim = nRasterYSize;
 
@@ -1806,26 +1971,19 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
 
     netCDFDataset * poDS = this; /* perhaps this should be removed for clarity */
 
-    /* temp variables to use in SetGeoTransform() and SetProjection() */
-    double      adfTempGeoTransform[6];
-    char        *pszTempProjection;
-
     CPLDebug( "GDAL_netCDF", "\n=====\nSetProjectionFromVar( %d )\n", nVarId );
 
 /* -------------------------------------------------------------------- */
 /*      Get x/y range information.                                      */
 /* -------------------------------------------------------------------- */
 
-    adfTempGeoTransform[0] = 0.0;
-    adfTempGeoTransform[1] = 1.0;
-    adfTempGeoTransform[2] = 0.0;
-    adfTempGeoTransform[3] = 0.0;
-    adfTempGeoTransform[4] = 0.0;
-    adfTempGeoTransform[5] = 1.0;
-    pszTempProjection = NULL;
+    /* temp variables to use in SetGeoTransform() and SetProjection() */
+    double adfTempGeoTransform[6] = {0.0, 1.0, 0.0, 0.0, 0.0, 1.0};
+
+    char *pszTempProjection = NULL;
 
-    if ( xdim == 1 || ydim == 1 ) {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+    if ( !bReadSRSOnly && (xdim == 1 || ydim == 1) ) {
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "1-pixel width/height files not supported, xdim: %ld ydim: %ld",
                   (long)xdim, (long)ydim );
         return;
@@ -1835,42 +1993,45 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
 /*      Look for grid_mapping metadata                                  */
 /* -------------------------------------------------------------------- */
 
-    strcpy( szGridMappingValue, "" );
+    char szGridMappingName[ NC_MAX_NAME+1 ];
     strcpy( szGridMappingName, "" );
 
+    char szGridMappingValue[ NC_MAX_NAME+1 ];
+    strcpy( szGridMappingValue, "" );
+
+    char szVarName[ NC_MAX_NAME+1 ];
     szVarName[0] = '\0';
-    nc_inq_varname( cdfid, nVarId, szVarName );
-    strcpy(szTemp,szVarName);
-    strcat(szTemp,"#");
-    strcat(szTemp,CF_GRD_MAPPING);
+    {
+    int status = nc_inq_varname( cdfid, nVarId, szVarName );
+    NCDF_ERR(status);
+    }
+    char szTemp[ NC_MAX_NAME+1 ];
+    snprintf(szTemp,sizeof(szTemp), "%s#%s", szVarName,CF_GRD_MAPPING);
 
-    pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);
+    const char *pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);
     if( pszValue ) {
-        strcpy(szGridMappingName,szTemp);
-        strcpy(szGridMappingValue,pszValue);
+        snprintf(szGridMappingName,sizeof(szGridMappingName), "%s", szTemp);
+        snprintf(szGridMappingValue,sizeof(szGridMappingValue), "%s", pszValue);
     }
 
     if( !EQUAL( szGridMappingValue, "" )  ) {
 
         /*  Read grid_mapping metadata */
+        int nVarProjectionID = -1;
         nc_inq_varid( cdfid, szGridMappingValue, &nVarProjectionID );
         poDS->ReadAttributes( cdfid, nVarProjectionID );
-        
+
 /* -------------------------------------------------------------------- */
 /*      Look for GDAL spatial_ref and GeoTransform within grid_mapping  */
 /* -------------------------------------------------------------------- */
         CPLDebug( "GDAL_netCDF", "got grid_mapping %s", szGridMappingValue );
-        strcpy( szTemp,szGridMappingValue);
-        strcat( szTemp, "#" );
-        strcat( szTemp, NCDF_SPATIAL_REF);
+        snprintf(szTemp,sizeof(szTemp), "%s#%s", szGridMappingValue,NCDF_SPATIAL_REF);
 
         pszWKT = CSLFetchNameValue(poDS->papszMetadata, szTemp);
-	
+
         if( pszWKT != NULL ) {
-            strcpy( szTemp,szGridMappingValue);
-            strcat( szTemp, "#" );
-            strcat( szTemp, NCDF_GEOTRANSFORM);
-            pszGeoTransform = CSLFetchNameValue(poDS->papszMetadata, szTemp);	    
+            snprintf(szTemp,sizeof(szTemp), "%s#%s", szGridMappingValue,NCDF_GEOTRANSFORM);
+            pszGeoTransform = CSLFetchNameValue(poDS->papszMetadata, szTemp);
         }
     }
 
@@ -1887,57 +2048,59 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
 /* -------------------------------------------------------------------- */
     pszValue = CSLFetchNameValue(poDS->papszMetadata, "NC_GLOBAL#GDAL");
 
-   if( pszValue && NCDFIsGDALVersionGTE(pszValue, 1900)) {
-        bIsGdalFile = TRUE;
-        bIsGdalCfFile = TRUE;
+    if( pszValue && NCDFIsGDALVersionGTE(pszValue, 1900)) {
+        bIsGdalFile = true;
+        bIsGdalCfFile = true;
     }
     else  if( pszWKT != NULL && pszGeoTransform != NULL ) {
-        bIsGdalFile = TRUE;
-        bIsGdalCfFile = FALSE;
+        bIsGdalFile = true;
+        bIsGdalCfFile = false;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Set default bottom-up default value                             */
 /*      Y axis dimension and absence of GT can modify this value        */
-/*      Override with Config option GDAL_NETCDF_BOTTOMUP                */ 
+/*      Override with Config option GDAL_NETCDF_BOTTOMUP                */
 /* -------------------------------------------------------------------- */
    /* new driver is bottom-up by default */
    if ( bIsGdalFile && ! bIsGdalCfFile )
-       poDS->bBottomUp = FALSE;
+       poDS->bBottomUp = false;
    else
-       poDS->bBottomUp = TRUE;
+       poDS->bBottomUp = true;
+
+    CPLDebug( "GDAL_netCDF",
+              "bIsGdalFile=%d bIsGdalCfFile=%d bBottomUp=%d",
+              static_cast<int>(bIsGdalFile), static_cast<int>(bIsGdalCfFile),
+              static_cast<int>(bBottomUp) );
 
-    CPLDebug( "GDAL_netCDF", 
-              "bIsGdalFile=%d bIsGdalCfFile=%d bBottomUp=%d", 
-              bIsGdalFile, bIsGdalCfFile, bBottomUp );
- 
 /* -------------------------------------------------------------------- */
 /*      Look for dimension: lon                                         */
 /* -------------------------------------------------------------------- */
 
     memset( szDimNameX, '\0', sizeof(szDimNameX) );
-    memset( szDimNameY, '\0', sizeof(szDimNameY) );
+    //memset( szDimNameY, '\0', sizeof(szDimNameY) );
 
-    for( i = 0; (i < strlen( poDS->papszDimName[ poDS->nXDimID ] )  && 
-                 i < 3 ); i++ ) {
-        szDimNameX[i]=(char)tolower( ( poDS->papszDimName[poDS->nXDimID] )[i] );
-    }
-    szDimNameX[3] = '\0';
-    for( i = 0; (i < strlen( poDS->papszDimName[ poDS->nYDimID ] )  && 
-                 i < 3 ); i++ ) {
-        szDimNameY[i]=(char)tolower( ( poDS->papszDimName[poDS->nYDimID] )[i] );
+    if( !bReadSRSOnly )
+    {
+        for( unsigned int i = 0; (i < strlen( poDS->papszDimName[ poDS->nXDimID ] )
+                                && i < 3 ); i++ ) {
+            szDimNameX[i]=(char)tolower( ( poDS->papszDimName[poDS->nXDimID] )[i] );
+        }
+        szDimNameX[3] = '\0';
+        /*for( unsigned int i = 0; (i < strlen( poDS->papszDimName[ poDS->nYDimID ] )
+                                && i < 3 ); i++ ) {
+            szDimNameY[i]=(char)tolower( ( poDS->papszDimName[poDS->nYDimID] )[i] );
+        }
+        szDimNameY[3] = '\0';*/
     }
-    szDimNameY[3] = '\0';
 
 /* -------------------------------------------------------------------- */
 /*      Read grid_mapping information and set projections               */
 /* -------------------------------------------------------------------- */
 
     if( !( EQUAL(szGridMappingName,"" ) ) ) {
-     
-        strcpy( szTemp, szGridMappingValue );
-        strcat( szTemp, "#" );
-        strcat( szTemp, CF_GRD_MAPPING_NAME );
+
+        snprintf(szTemp,sizeof(szTemp), "%s#%s", szGridMappingValue,CF_GRD_MAPPING_NAME);
         pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);
 
         if( pszValue != NULL ) {
@@ -1945,41 +2108,41 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
 /* -------------------------------------------------------------------- */
 /*      Check for datum/spheroid information                            */
 /* -------------------------------------------------------------------- */
-            dfEarthRadius = 
-                poDS->FetchCopyParm( szGridMappingValue, 
-                                     CF_PP_EARTH_RADIUS, 
+            dfEarthRadius =
+                poDS->FetchCopyParm( szGridMappingValue,
+                                     CF_PP_EARTH_RADIUS,
                                      -1.0 );
 
-            dfLonPrimeMeridian = 
+            dfLonPrimeMeridian =
                 poDS->FetchCopyParm( szGridMappingValue,
-                                     CF_PP_LONG_PRIME_MERIDIAN, 
+                                     CF_PP_LONG_PRIME_MERIDIAN,
                                      0.0 );
             // should try to find PM name from its value if not Greenwich
             if ( ! CPLIsEqual(dfLonPrimeMeridian,0.0) )
                 pszPMName = "unknown";
 
-            dfInverseFlattening = 
-                poDS->FetchCopyParm( szGridMappingValue, 
-                                     CF_PP_INVERSE_FLATTENING, 
+            dfInverseFlattening =
+                poDS->FetchCopyParm( szGridMappingValue,
+                                     CF_PP_INVERSE_FLATTENING,
                                      -1.0 );
-	    
-            dfSemiMajorAxis = 
-                poDS->FetchCopyParm( szGridMappingValue, 
-                                     CF_PP_SEMI_MAJOR_AXIS, 
+
+            dfSemiMajorAxis =
+                poDS->FetchCopyParm( szGridMappingValue,
+                                     CF_PP_SEMI_MAJOR_AXIS,
                                      -1.0 );
-	    
-            dfSemiMinorAxis = 
-                poDS->FetchCopyParm( szGridMappingValue, 
-                                     CF_PP_SEMI_MINOR_AXIS, 
+
+            dfSemiMinorAxis =
+                poDS->FetchCopyParm( szGridMappingValue,
+                                     CF_PP_SEMI_MINOR_AXIS,
                                      -1.0 );
 
             //see if semi-major exists if radius doesn't
             if( dfEarthRadius < 0.0 )
                 dfEarthRadius = dfSemiMajorAxis;
-	    
+
             //if still no radius, check old tag
             if( dfEarthRadius < 0.0 )
-                dfEarthRadius = poDS->FetchCopyParm( szGridMappingValue, 
+                dfEarthRadius = poDS->FetchCopyParm( szGridMappingValue,
                                                      CF_PP_EARTH_RADIUS_OLD,
                                                      -1.0 );
 
@@ -1990,12 +2153,12 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
                     //no inv_flat tag, check for semi_minor
                     if( dfSemiMinorAxis < 0.0 ) {
                         //no way to get inv_flat, use sphere
-                        oSRS.SetGeogCS( "unknown", 
-                                        NULL, 
-                                        "Sphere", 
+                        oSRS.SetGeogCS( "unknown",
+                                        NULL,
+                                        "Sphere",
                                         dfEarthRadius, 0.0,
                                         pszPMName, dfLonPrimeMeridian );
-                        bGotGeogCS = TRUE;
+                        bGotGeogCS = true;
                     }
                     else {
                         if( dfSemiMajorAxis < 0.0 )
@@ -2003,22 +2166,22 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
                         //set inv_flat using semi_minor/major
                         dfInverseFlattening = OSRCalcInvFlattening(dfSemiMajorAxis, dfSemiMinorAxis);
 
-                        oSRS.SetGeogCS( "unknown", 
-                                        NULL, 
-                                        "Spheroid", 
+                        oSRS.SetGeogCS( "unknown",
+                                        NULL,
+                                        "Spheroid",
                                         dfEarthRadius, dfInverseFlattening,
                                         pszPMName, dfLonPrimeMeridian );
-                        bGotGeogCS = TRUE;
+                        bGotGeogCS = true;
                     }
                 }
                 else {
-                    oSRS.SetGeogCS( "unknown", 
-                                    NULL, 
-                                    "Spheroid", 
+                    oSRS.SetGeogCS( "unknown",
+                                    NULL,
+                                    "Spheroid",
                                     dfEarthRadius, dfInverseFlattening,
                                         pszPMName, dfLonPrimeMeridian );
-                    bGotGeogCS = TRUE;
-                }  
+                    bGotGeogCS = true;
+                }
 
                 if ( bGotGeogCS )
                     CPLDebug( "GDAL_netCDF", "got spheroid from CF: (%f , %f)", dfEarthRadius, dfInverseFlattening );
@@ -2026,39 +2189,39 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
             }
             //no radius, set as wgs84 as default?
             else {
-                // This would be too indiscrimant.  But we should set
+                // This would be too indiscriminate.  But we should set
                 // it if we know the data is geographic.
-                //oSRS.SetWellKnownGeogCS( "WGS84" );
+                // oSRS.SetWellKnownGeogCS( "WGS84" );
             }
-	    		
+
 /* -------------------------------------------------------------------- */
 /*      Transverse Mercator                                             */
 /* -------------------------------------------------------------------- */
 
             if( EQUAL( pszValue, CF_PT_TM ) ) {
 
-                dfScale = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfScale =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_SCALE_FACTOR_MERIDIAN, 1.0 );
 
-                dfCenterLon = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfCenterLon =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_LONG_CENTRAL_MERIDIAN, 0.0 );
 
-                dfCenterLat = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfCenterLat =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_LAT_PROJ_ORIGIN, 0.0 );
 
-                dfFalseEasting = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfFalseEasting =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_FALSE_EASTING, 0.0 );
 
-                dfFalseNorthing = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfFalseNorthing =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_FALSE_NORTHING, 0.0 );
- 
-                bGotCfSRS = TRUE;
-                oSRS.SetTM( dfCenterLat, 
+
+                bGotCfSRS = true;
+                oSRS.SetTM( dfCenterLat,
                             dfCenterLon,
                             dfScale,
                             dfFalseEasting,
@@ -2075,38 +2238,33 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
             if( EQUAL( pszValue, CF_PT_AEA ) ) {
 
                 char **papszStdParallels = NULL;
-		
-                dfCenterLon = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         CF_PP_LONG_CENTRAL_MERIDIAN, 0.0 );
 
-                dfCenterLat = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         CF_PP_LAT_PROJ_ORIGIN, 0.0 );
+                dfCenterLon =
+                    poDS->FetchCopyParm( szGridMappingValue,
+                                         CF_PP_LONG_CENTRAL_MERIDIAN, 0.0 );
 
-                dfFalseEasting = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfFalseEasting =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_FALSE_EASTING, 0.0 );
 
-                dfFalseNorthing = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfFalseNorthing =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_FALSE_NORTHING, 0.0 );
-		
-                papszStdParallels = 
+
+                papszStdParallels =
                     FetchStandardParallels( szGridMappingValue );
 
                 if( papszStdParallels != NULL ) {
-		  
+
                     if ( CSLCount( papszStdParallels ) == 1 ) {
                         /* TODO CF-1 standard says it allows AEA to be encoded with only 1 standard parallel */
                         /* how should this actually map to a 2StdP OGC WKT version? */
-                        CPLError( CE_Warning, CPLE_NotSupported, 
+                        CPLError( CE_Warning, CPLE_NotSupported,
                                   "NetCDF driver import of AEA-1SP is not tested, using identical std. parallels\n" );
                         dfStdP1 = CPLAtofM( papszStdParallels[0] );
                         dfStdP2 = dfStdP1;
 
                     }
-		
                     else if( CSLCount( papszStdParallels ) == 2 ) {
                         dfStdP1 = CPLAtofM( papszStdParallels[0] );
                         dfStdP2 = CPLAtofM( papszStdParallels[1] );
@@ -2114,20 +2272,20 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
                 }
                 //old default
                 else {
-                    dfStdP1 = 
-                        poDS->FetchCopyParm( szGridMappingValue, 
+                    dfStdP1 =
+                        poDS->FetchCopyParm( szGridMappingValue,
                                              CF_PP_STD_PARALLEL_1, 0.0 );
 
-                    dfStdP2 = 
-                        poDS->FetchCopyParm( szGridMappingValue, 
+                    dfStdP2 =
+                        poDS->FetchCopyParm( szGridMappingValue,
                                              CF_PP_STD_PARALLEL_2, 0.0 );
                 }
 
-                dfCenterLat = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfCenterLat =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_LAT_PROJ_ORIGIN, 0.0 );
 
-                bGotCfSRS = TRUE;
+                bGotCfSRS = true;
                 oSRS.SetACEA( dfStdP1, dfStdP2, dfCenterLat, dfCenterLon,
                               dfFalseEasting, dfFalseNorthing );
 
@@ -2145,7 +2303,7 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
 
                 char **papszStdParallels = NULL;
 
-                papszStdParallels = 
+                papszStdParallels =
                     FetchStandardParallels( szGridMappingValue );
 
                 if( papszStdParallels != NULL ) {
@@ -2154,30 +2312,30 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
                 else {
                     //TODO: add support for 'scale_factor_at_projection_origin' variant to standard parallel
                     //Probably then need to calc a std parallel equivalent
-                    CPLError( CE_Failure, CPLE_NotSupported, 
+                    CPLError( CE_Failure, CPLE_NotSupported,
                               "NetCDF driver does not support import of CF-1 LCEA "
                               "'scale_factor_at_projection_origin' variant yet.\n" );
                 }
 
-                dfCentralMeridian = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfCentralMeridian =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_LONG_CENTRAL_MERIDIAN, 0.0 );
 
-                dfFalseEasting = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfFalseEasting =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_FALSE_EASTING, 0.0 );
 
-                dfFalseNorthing = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfFalseNorthing =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_FALSE_NORTHING, 0.0 );
-		
-                bGotCfSRS = TRUE;
+
+                bGotCfSRS = true;
                 oSRS.SetCEA( dfStdP1, dfCentralMeridian,
                              dfFalseEasting, dfFalseNorthing );
 
                 if( !bGotGeogCS )
                     oSRS.SetWellKnownGeogCS( "WGS84" );
-		
+
                 CSLDestroy( papszStdParallels );
             }
 
@@ -2185,86 +2343,85 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
 /*      lambert_azimuthal_equal_area                                    */
 /* -------------------------------------------------------------------- */
             else if( EQUAL( pszValue, CF_PT_LAEA ) ) {
-                dfCenterLon = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfCenterLon =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_LON_PROJ_ORIGIN, 0.0 );
 
-                dfCenterLat = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfCenterLat =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_LAT_PROJ_ORIGIN, 0.0 );
 
-                dfFalseEasting = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfFalseEasting =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_FALSE_EASTING, 0.0 );
 
-                dfFalseNorthing = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfFalseNorthing =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_FALSE_NORTHING, 0.0 );
 
                 oSRS.SetProjCS( "LAEA (WGS84) " );
-		
-                bGotCfSRS = TRUE;
+
+                bGotCfSRS = true;
                 oSRS.SetLAEA( dfCenterLat, dfCenterLon,
                               dfFalseEasting, dfFalseNorthing );
 
                 if( !bGotGeogCS )
                     oSRS.SetWellKnownGeogCS( "WGS84" );
-		
             }
 
 /* -------------------------------------------------------------------- */
 /*      Azimuthal Equidistant                                           */
 /* -------------------------------------------------------------------- */
             else if( EQUAL( pszValue, CF_PT_AE ) ) {
-                dfCenterLon = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfCenterLon =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_LON_PROJ_ORIGIN, 0.0 );
 
-                dfCenterLat = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfCenterLat =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_LAT_PROJ_ORIGIN, 0.0 );
 
-                dfFalseEasting = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfFalseEasting =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_FALSE_EASTING, 0.0 );
 
-                dfFalseNorthing = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfFalseNorthing =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_FALSE_NORTHING, 0.0 );
 
-                bGotCfSRS = TRUE;
+                bGotCfSRS = true;
                 oSRS.SetAE( dfCenterLat, dfCenterLon,
                             dfFalseEasting, dfFalseNorthing );
 
                 if( !bGotGeogCS )
                     oSRS.SetWellKnownGeogCS( "WGS84" );
-		
+
             }
 
 /* -------------------------------------------------------------------- */
 /*      Lambert conformal conic                                         */
 /* -------------------------------------------------------------------- */
             else if( EQUAL( pszValue, CF_PT_LCC ) ) {
-		
+
                 char **papszStdParallels = NULL;
-		
-                dfCenterLon = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+
+                dfCenterLon =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_LONG_CENTRAL_MERIDIAN, 0.0 );
 
-                dfCenterLat = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfCenterLat =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_LAT_PROJ_ORIGIN, 0.0 );
 
-                dfFalseEasting = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfFalseEasting =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_FALSE_EASTING, 0.0 );
 
-                dfFalseNorthing = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfFalseNorthing =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_FALSE_NORTHING, 0.0 );
-		
-                papszStdParallels = 
+
+                papszStdParallels =
                     FetchStandardParallels( szGridMappingValue );
 
                 /* 2SP variant */
@@ -2278,10 +2435,10 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
                 /* See comments in netcdfdataset.h for this projection. */
                 else {
 
-                    dfScale = 
-                        poDS->FetchCopyParm( szGridMappingValue, 
+                    dfScale =
+                        poDS->FetchCopyParm( szGridMappingValue,
                                              CF_PP_SCALE_FACTOR_ORIGIN, -1.0 );
-                    
+
                     /* CF definition, without scale factor */
                     if( CPLIsEqual(dfScale, -1.0) ) {
 
@@ -2289,114 +2446,113 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
                         if( CSLCount( papszStdParallels ) == 1 )
                             dfStdP1 = CPLAtofM( papszStdParallels[0] );
                         /* with center lon instead */
-                        else 
+                        else
                             dfStdP1 = dfCenterLat;
-                        dfStdP2 = dfStdP1;
-                        
+                        /*dfStdP2 = dfStdP1;*/
+
                         /* test if we should actually compute scale factor */
                         if ( ! CPLIsEqual( dfStdP1, dfCenterLat ) ) {
-                            CPLError( CE_Warning, CPLE_NotSupported, 
+                            CPLError( CE_Warning, CPLE_NotSupported,
                                       "NetCDF driver import of LCC-1SP with standard_parallel1 != latitude_of_projection_origin\n"
                                       "(which forces a computation of scale_factor) is experimental (bug #3324)\n" );
                             /* use Snyder eq. 15-4 to compute dfScale from dfStdP1 and dfCenterLat */
                             /* only tested for dfStdP1=dfCenterLat and (25,26), needs more data for testing */
                             /* other option: use the 2SP variant - how to compute new standard parallels? */
-                            dfScale = ( cos(dfStdP1) * pow( tan(NCDF_PI/4 + dfStdP1/2), sin(dfStdP1) ) ) /
-                                ( cos(dfCenterLat) * pow( tan(NCDF_PI/4 + dfCenterLat/2), sin(dfCenterLat) ) );
+                            dfScale = ( cos(dfStdP1) * pow( tan(M_PI/4 + dfStdP1/2), sin(dfStdP1) ) ) /
+                                ( cos(dfCenterLat) * pow( tan(M_PI/4 + dfCenterLat/2), sin(dfCenterLat) ) );
                         }
                         /* default is 1.0 */
-                        else                    
+                        else
                             dfScale = 1.0;
-                        
-                        oSRS.SetLCC1SP( dfCenterLat, dfCenterLon, dfScale, 
+
+                        oSRS.SetLCC1SP( dfCenterLat, dfCenterLon, dfScale,
                                         dfFalseEasting, dfFalseNorthing );
                         /* store dfStdP1 so we can output it to CF later */
                         oSRS.SetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, dfStdP1 );
                     }
                     /* OGC/PROJ.4 definition with scale factor */
                     else {
-                        oSRS.SetLCC1SP( dfCenterLat, dfCenterLon, dfScale, 
+                        oSRS.SetLCC1SP( dfCenterLat, dfCenterLon, dfScale,
                                         dfFalseEasting, dfFalseNorthing );
                     }
                 }
-		
 
-                bGotCfSRS = TRUE;
+                bGotCfSRS = true;
                 if( !bGotGeogCS )
                     oSRS.SetWellKnownGeogCS( "WGS84" );
 
                 CSLDestroy( papszStdParallels );
             }
-		
+
 /* -------------------------------------------------------------------- */
 /*      Is this Latitude/Longitude Grid explicitly                      */
 /* -------------------------------------------------------------------- */
-	    
+
             else if ( EQUAL ( pszValue, CF_PT_LATITUDE_LONGITUDE ) ) {
-                bGotCfSRS = TRUE;
+                bGotCfSRS = true;
                 if( !bGotGeogCS )
                     oSRS.SetWellKnownGeogCS( "WGS84" );
             }
 /* -------------------------------------------------------------------- */
 /*      Mercator                                                        */
 /* -------------------------------------------------------------------- */
-		  
+
             else if ( EQUAL ( pszValue, CF_PT_MERCATOR ) ) {
 
                 char **papszStdParallels = NULL;
 
                 /* If there is a standard_parallel, know it is Mercator 2SP */
-                papszStdParallels = 
+                papszStdParallels =
                     FetchStandardParallels( szGridMappingValue );
-                
+
                 if (NULL != papszStdParallels) {
                     /* CF-1 Mercator 2SP always has lat centered at equator */
                     dfStdP1 = CPLAtofM( papszStdParallels[0] );
 
                     dfCenterLat = 0.0;
 
-                    dfCenterLon = 
-                        poDS->FetchCopyParm( szGridMappingValue, 
+                    dfCenterLon =
+                        poDS->FetchCopyParm( szGridMappingValue,
                                              CF_PP_LON_PROJ_ORIGIN, 0.0 );
-              
-                    dfFalseEasting = 
-                        poDS->FetchCopyParm( szGridMappingValue, 
+
+                    dfFalseEasting =
+                        poDS->FetchCopyParm( szGridMappingValue,
                                              CF_PP_FALSE_EASTING, 0.0 );
 
-                    dfFalseNorthing = 
-                        poDS->FetchCopyParm( szGridMappingValue, 
+                    dfFalseNorthing =
+                        poDS->FetchCopyParm( szGridMappingValue,
                                              CF_PP_FALSE_NORTHING, 0.0 );
 
-                    oSRS.SetMercator2SP( dfStdP1, dfCenterLat, dfCenterLon, 
+                    oSRS.SetMercator2SP( dfStdP1, dfCenterLat, dfCenterLon,
                                       dfFalseEasting, dfFalseNorthing );
                 }
                 else {
-                    dfCenterLon = 
-                        poDS->FetchCopyParm( szGridMappingValue, 
+                    dfCenterLon =
+                        poDS->FetchCopyParm( szGridMappingValue,
                                              CF_PP_LON_PROJ_ORIGIN, 0.0 );
-              
-                    dfCenterLat = 
-                        poDS->FetchCopyParm( szGridMappingValue, 
+
+                    dfCenterLat =
+                        poDS->FetchCopyParm( szGridMappingValue,
                                              CF_PP_LAT_PROJ_ORIGIN, 0.0 );
 
-                    dfScale = 
-                        poDS->FetchCopyParm( szGridMappingValue, 
+                    dfScale =
+                        poDS->FetchCopyParm( szGridMappingValue,
                                              CF_PP_SCALE_FACTOR_ORIGIN,
                                              1.0 );
 
-                    dfFalseEasting = 
-                        poDS->FetchCopyParm( szGridMappingValue, 
+                    dfFalseEasting =
+                        poDS->FetchCopyParm( szGridMappingValue,
                                              CF_PP_FALSE_EASTING, 0.0 );
 
-                    dfFalseNorthing = 
-                        poDS->FetchCopyParm( szGridMappingValue, 
+                    dfFalseNorthing =
+                        poDS->FetchCopyParm( szGridMappingValue,
                                              CF_PP_FALSE_NORTHING, 0.0 );
 
-                    oSRS.SetMercator( dfCenterLat, dfCenterLon, dfScale, 
+                    oSRS.SetMercator( dfCenterLat, dfCenterLon, dfScale,
                                       dfFalseEasting, dfFalseNorthing );
-                }                      
+                }
 
-                bGotCfSRS = TRUE;
+                bGotCfSRS = true;
 
                 if( !bGotGeogCS )
                     oSRS.SetWellKnownGeogCS( "WGS84" );
@@ -2407,28 +2563,27 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
 /* -------------------------------------------------------------------- */
 /*      Orthographic                                                    */
 /* -------------------------------------------------------------------- */
-		  
 
             else if ( EQUAL ( pszValue, CF_PT_ORTHOGRAPHIC ) ) {
-                dfCenterLon = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfCenterLon =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_LON_PROJ_ORIGIN, 0.0 );
-	      
-                dfCenterLat = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+
+                dfCenterLat =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_LAT_PROJ_ORIGIN, 0.0 );
 
-                dfFalseEasting = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfFalseEasting =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_FALSE_EASTING, 0.0 );
 
-                dfFalseNorthing = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfFalseNorthing =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_FALSE_NORTHING, 0.0 );
 
-                bGotCfSRS = TRUE;
+                bGotCfSRS = true;
 
-                oSRS.SetOrthographic( dfCenterLat, dfCenterLon, 
+                oSRS.SetOrthographic( dfCenterLat, dfCenterLon,
                                       dfFalseEasting, dfFalseNorthing );
 
                 if( !bGotGeogCS )
@@ -2438,43 +2593,43 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
 /* -------------------------------------------------------------------- */
 /*      Polar Stereographic                                             */
 /* -------------------------------------------------------------------- */
-		  
+
             else if ( EQUAL ( pszValue, CF_PT_POLAR_STEREO ) ) {
 
                 char **papszStdParallels = NULL;
 
-                dfScale = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         CF_PP_SCALE_FACTOR_ORIGIN, 
+                dfScale =
+                    poDS->FetchCopyParm( szGridMappingValue,
+                                         CF_PP_SCALE_FACTOR_ORIGIN,
                                          -1.0 );
-                
-                papszStdParallels = 
+
+                papszStdParallels =
                     FetchStandardParallels( szGridMappingValue );
-                
+
                 /* CF allows the use of standard_parallel (lat_ts) OR scale_factor (k0),
                    make sure we have standard_parallel, using Snyder eq. 22-7
                    with k=1 and lat=standard_parallel */
                 if ( papszStdParallels != NULL ) {
                     dfStdP1 = CPLAtofM( papszStdParallels[0] );
                     /* compute scale_factor from standard_parallel */
-                    /* this creates WKT that is inconsistent, don't write for now 
-                       also proj4 does not seem to use this parameter */                    
-                    // dfScale = ( 1.0 + fabs( sin( dfStdP1 * NCDF_PI / 180.0 ) ) ) / 2.0;
+                    /* this creates WKT that is inconsistent, don't write for now
+                       also proj4 does not seem to use this parameter */
+                    // dfScale = ( 1.0 + fabs( sin( dfStdP1 * M_PI / 180.0 ) ) ) / 2.0;
                 }
                 else {
                     if ( ! CPLIsEqual(dfScale,-1.0) ) {
                         /* compute standard_parallel from scale_factor */
-                        dfStdP1 = asin( 2*dfScale - 1 ) * 180.0 / NCDF_PI;
+                        dfStdP1 = asin( 2*dfScale - 1 ) * 180.0 / M_PI;
 
-                        /* fetch latitude_of_projection_origin (+90/-90) 
+                        /* fetch latitude_of_projection_origin (+90/-90)
                            used here for the sign of standard_parallel */
-                        double dfLatProjOrigin = 
-                            poDS->FetchCopyParm( szGridMappingValue, 
-                                                 CF_PP_LAT_PROJ_ORIGIN, 
+                        double dfLatProjOrigin =
+                            poDS->FetchCopyParm( szGridMappingValue,
+                                                 CF_PP_LAT_PROJ_ORIGIN,
                                                  0.0 );
                         if ( ! CPLIsEqual(dfLatProjOrigin,90.0)  &&
                              ! CPLIsEqual(dfLatProjOrigin,-90.0) ) {
-                            CPLError( CE_Failure, CPLE_NotSupported, 
+                            CPLError( CE_Failure, CPLE_NotSupported,
                                       "Polar Stereographic must have a %s parameter equal to +90 or -90\n.",
                                       CF_PP_LAT_PROJ_ORIGIN );
                             dfLatProjOrigin = 90.0;
@@ -2484,7 +2639,7 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
                     }
                     else {
                         dfStdP1 = 0.0; //just to avoid warning at compilation
-                        CPLError( CE_Failure, CPLE_NotSupported, 
+                        CPLError( CE_Failure, CPLE_NotSupported,
                                   "The NetCDF driver does not support import of CF-1 Polar stereographic "
                                   "without standard_parallel and scale_factor_at_projection_origin parameters.\n" );
                     }
@@ -2494,21 +2649,21 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
                 if ( CPLIsEqual(dfScale,-1.0) )
                     dfScale = 1.0;
 
-                dfCenterLon = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfCenterLon =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_VERT_LONG_FROM_POLE, 0.0 );
 
-                dfFalseEasting = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfFalseEasting =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_FALSE_EASTING, 0.0 );
 
-                dfFalseNorthing = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfFalseNorthing =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_FALSE_NORTHING, 0.0 );
 
-                bGotCfSRS = TRUE;
+                bGotCfSRS = true;
                 /* map CF CF_PP_STD_PARALLEL_1 to WKT SRS_PP_LATITUDE_OF_ORIGIN */
-                oSRS.SetPS( dfStdP1, dfCenterLon, dfScale, 
+                oSRS.SetPS( dfStdP1, dfCenterLon, dfScale,
                             dfFalseEasting, dfFalseNorthing );
 
                 if( !bGotGeogCS )
@@ -2520,90 +2675,138 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
 /* -------------------------------------------------------------------- */
 /*      Stereographic                                                   */
 /* -------------------------------------------------------------------- */
-		  
+
             else if ( EQUAL ( pszValue, CF_PT_STEREO ) ) {
-	        
-                dfCenterLon = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+
+                dfCenterLon =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_LON_PROJ_ORIGIN, 0.0 );
-	      
-                dfCenterLat = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+
+                dfCenterLat =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_LAT_PROJ_ORIGIN, 0.0 );
 
-                dfScale = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfScale =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_SCALE_FACTOR_ORIGIN,
                                          1.0 );
 
-                dfFalseEasting = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfFalseEasting =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_FALSE_EASTING, 0.0 );
 
-                dfFalseNorthing = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
+                dfFalseNorthing =
+                    poDS->FetchCopyParm( szGridMappingValue,
                                          CF_PP_FALSE_NORTHING, 0.0 );
 
-                bGotCfSRS = TRUE;
-                oSRS.SetStereographic( dfCenterLat, dfCenterLon, dfScale, 
+                bGotCfSRS = true;
+                oSRS.SetStereographic( dfCenterLat, dfCenterLon, dfScale,
                                        dfFalseEasting, dfFalseNorthing );
 
                 if( !bGotGeogCS )
                     oSRS.SetWellKnownGeogCS( "WGS84" );
             }
-  
+
+/* -------------------------------------------------------------------- */
+/*      Geostationary                                                   */
+/* -------------------------------------------------------------------- */
+            else if( EQUAL( pszValue, CF_PT_GEOS ) ) {
+                dfCenterLon =
+                    poDS->FetchCopyParm( szGridMappingValue,
+                                         CF_PP_LON_PROJ_ORIGIN, 0.0 );
+
+                double dfSatelliteHeight =
+                    poDS->FetchCopyParm( szGridMappingValue,
+                                         CF_PP_PERSPECTIVE_POINT_HEIGHT, 35785831.0 );
+
+                snprintf(szTemp, sizeof(szTemp), "%s#%s", szGridMappingValue, CF_PP_SWEEP_ANGLE_AXIS);
+                const char *pszSweepAxisAngle = CSLFetchNameValue(papszMetadata, szTemp);
+
+                dfFalseEasting =
+                    poDS->FetchCopyParm( szGridMappingValue,
+                                         CF_PP_FALSE_EASTING, 0.0 );
+
+                dfFalseNorthing =
+                    poDS->FetchCopyParm( szGridMappingValue,
+                                         CF_PP_FALSE_NORTHING, 0.0 );
+
+                bGotCfSRS = true;
+                oSRS.SetGEOS( dfCenterLon, dfSatelliteHeight,
+                              dfFalseEasting, dfFalseNorthing );
+
+                if( !bGotGeogCS )
+                    oSRS.SetWellKnownGeogCS( "WGS84" );
+
+                if( pszSweepAxisAngle != NULL && EQUAL(pszSweepAxisAngle, "x") )
+                {
+                    char* pszProj4 = NULL;
+                    oSRS.exportToProj4(&pszProj4);
+                    CPLString osProj4 = pszProj4;
+                    osProj4 += " +sweep=x";
+                    oSRS.SetExtension( oSRS.GetRoot()->GetValue(), "PROJ4", osProj4 );
+                    CPLFree(pszProj4);
+                }
+
+            }
+
 /* -------------------------------------------------------------------- */
 /*      Is this Latitude/Longitude Grid, default                        */
 /* -------------------------------------------------------------------- */
-	    
-        } else if( EQUAL( szDimNameX,"lon" ) ) {
+
+        } else if( EQUAL( szDimNameX, NCDF_DIMNAME_LON ) ) {
             oSRS.SetWellKnownGeogCS( "WGS84" );
 
         } else {
-            // This would be too indiscrimant.  But we should set
+            // This would be too indiscriminate.  But we should set
             // it if we know the data is geographic.
-            //oSRS.SetWellKnownGeogCS( "WGS84" );
+            // oSRS.SetWellKnownGeogCS( "WGS84" );
         }
     }
 /* -------------------------------------------------------------------- */
 /*      Read projection coordinates                                     */
 /* -------------------------------------------------------------------- */
 
-    nc_inq_varid( cdfid, poDS->papszDimName[nXDimID], &nVarDimXID );
-    nc_inq_varid( cdfid, poDS->papszDimName[nYDimID], &nVarDimYID );
-    
-    if( ( nVarDimXID != -1 ) && ( nVarDimYID != -1 ) ) {
+    int nVarDimXID = -1;
+    int nVarDimYID = -1;
+    if( !bReadSRSOnly )
+    {
+        nc_inq_varid( cdfid, poDS->papszDimName[nXDimID], &nVarDimXID );
+        nc_inq_varid( cdfid, poDS->papszDimName[nYDimID], &nVarDimYID );
+    }
+
+    size_t start[2], edge[2];
+    if( !bReadSRSOnly && ( nVarDimXID != -1 ) && ( nVarDimYID != -1 ) ) {
         pdfXCoord = (double *) CPLCalloc( xdim, sizeof(double) );
         pdfYCoord = (double *) CPLCalloc( ydim, sizeof(double) );
 
         start[0] = 0;
         edge[0]  = xdim;
-        status = nc_get_vara_double( cdfid, nVarDimXID, 
+        int status = nc_get_vara_double( cdfid, nVarDimXID,
                                      start, edge, pdfXCoord);
-        
+        NCDF_ERR(status);
+
         edge[0]  = ydim;
-        status = nc_get_vara_double( cdfid, nVarDimYID, 
+        status = nc_get_vara_double( cdfid, nVarDimYID,
                                      start, edge, pdfYCoord);
+        NCDF_ERR(status);
 
 /* -------------------------------------------------------------------- */
 /*      Check for bottom-up from the Y-axis order                       */
 /*      see bugs #4284 and #4251                                        */
 /* -------------------------------------------------------------------- */
 
-        if ( pdfYCoord[0] > pdfYCoord[1] )
-            poDS->bBottomUp = FALSE;
-        else
-            poDS->bBottomUp = TRUE;
+        poDS->bBottomUp = (pdfYCoord[0] <= pdfYCoord[1]);
 
-        CPLDebug( "GDAL_netCDF", "set bBottomUp = %d from Y axis", poDS->bBottomUp );
+        CPLDebug( "GDAL_netCDF", "set bBottomUp = %d from Y axis",
+                  static_cast<int>(poDS->bBottomUp) );
 
 /* -------------------------------------------------------------------- */
 /*      convert ]180,360] longitude values to [-180,180]                */
 /* -------------------------------------------------------------------- */
 
         if ( NCDFIsVarLongitude( cdfid, nVarDimXID, NULL ) &&
-             CSLTestBoolean(CPLGetConfigOption("GDAL_NETCDF_CENTERLONG_180", "YES")) ) {
-            /* if mininum longitude is > 180, subtract 360 from all */
+             CPLTestBool(CPLGetConfigOption("GDAL_NETCDF_CENTERLONG_180", "YES"))) {
+            // If minimum longitude is > 180, subtract 360 from all.
             if ( MIN( pdfXCoord[0], pdfXCoord[xdim-1] ) > 180.0 ) {
                 for ( size_t i=0; i<xdim ; i++ )
                         pdfXCoord[i] -= 360;
@@ -2618,31 +2821,22 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
 
         /* check units for x and y */
         if( oSRS.IsProjected( ) ) {
-            const char *pszUnitsX = NULL;
-            const char *pszUnitsY = NULL;
-
-            strcpy( szTemp, poDS->papszDimName[nXDimID] );
-            strcat( szTemp, "#units" );
-            pszValue = CSLFetchNameValue( poDS->papszMetadata, 
+            snprintf(szTemp,sizeof(szTemp), "%s#units", poDS->papszDimName[nXDimID]);
+            const char *pszUnitsX = CSLFetchNameValue( poDS->papszMetadata,
                                           szTemp );
-            if( pszValue != NULL ) 
-                pszUnitsX = pszValue;
 
-            strcpy( szTemp, poDS->papszDimName[nYDimID] );
-            strcat( szTemp, "#units" );
-            pszValue = CSLFetchNameValue( poDS->papszMetadata, 
+            snprintf(szTemp,sizeof(szTemp), "%s#units", poDS->papszDimName[nYDimID]);
+            const char *pszUnitsY = CSLFetchNameValue( poDS->papszMetadata,
                                           szTemp );
-            if( pszValue != NULL )
-                pszUnitsY = pszValue;
 
             /* TODO: what to do if units are not equal in X and Y */
-            if ( (pszUnitsX != NULL) && (pszUnitsY != NULL) && 
+            if ( (pszUnitsX != NULL) && (pszUnitsY != NULL) &&
                  EQUAL(pszUnitsX,pszUnitsY) )
                 pszUnits = pszUnitsX;
 
             /* add units to PROJCS */
             if ( pszUnits != NULL && ! EQUAL(pszUnits,"") ) {
-                CPLDebug( "GDAL_netCDF", 
+                CPLDebug( "GDAL_netCDF",
                           "units=%s", pszUnits );
                 if ( EQUAL(pszUnits,"m") ) {
                     oSRS.SetLinearUnits( "metre", 1.0 );
@@ -2653,7 +2847,7 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
                     oSRS.SetAuthority( "PROJCS|UNIT", "EPSG", 9036 );
                 }
                 /* TODO check for other values */
-                // else 
+                // else
                 //     oSRS.SetLinearUnits(pszUnits, 1.0);
             }
         }
@@ -2661,7 +2855,7 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
             oSRS.SetAngularUnits( CF_UNITS_D, CPLAtof(SRS_UA_DEGREE_CONV) );
             oSRS.SetAuthority( "GEOGCS|UNIT", "EPSG", 9122 );
         }
-        
+
         /* Set Projection */
         oSRS.exportToWkt( &(pszTempProjection) );
         CPLDebug( "GDAL_netCDF", "setting WKT from CF" );
@@ -2673,7 +2867,7 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
     }
 
 /* -------------------------------------------------------------------- */
-/*      Is pixel spacing uniform accross the map?                       */
+/*      Is pixel spacing uniform across the map?                       */
 /* -------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------- */
@@ -2681,64 +2875,64 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
 /* -------------------------------------------------------------------- */
 
         if( xdim == 2 ) {
-            bLonSpacingOK = TRUE;
+            bLonSpacingOK = true;
         }
         else
         {
             nSpacingBegin   = (int) poDS->rint((pdfXCoord[1] - pdfXCoord[0]) * 1000);
-            
-            nSpacingMiddle  = (int) poDS->rint((pdfXCoord[xdim/2+1] - 
+
+            nSpacingMiddle  = (int) poDS->rint((pdfXCoord[xdim/2+1] -
                                                 pdfXCoord[xdim/2]) * 1000);
-            
-            nSpacingLast    = (int) poDS->rint((pdfXCoord[xdim-1] - 
-                                                pdfXCoord[xdim-2]) * 1000);       
-            
-            CPLDebug("GDAL_netCDF", 
+
+            nSpacingLast    = (int) poDS->rint((pdfXCoord[xdim-1] -
+                                                pdfXCoord[xdim-2]) * 1000);
+
+            CPLDebug("GDAL_netCDF",
                      "xdim: %ld nSpacingBegin: %d nSpacingMiddle: %d nSpacingLast: %d",
                      (long)xdim, nSpacingBegin, nSpacingMiddle, nSpacingLast );
 #ifdef NCDF_DEBUG
-            CPLDebug("GDAL_netCDF", 
+            CPLDebug("GDAL_netCDF",
                      "xcoords: %f %f %f %f %f %f",
                      pdfXCoord[0], pdfXCoord[1], pdfXCoord[xdim / 2], pdfXCoord[(xdim / 2) + 1],
                      pdfXCoord[xdim - 2], pdfXCoord[xdim-1]);
 #endif
-           
+
             if( ( abs( abs( nSpacingBegin ) - abs( nSpacingLast ) )  <= 1   ) &&
                 ( abs( abs( nSpacingBegin ) - abs( nSpacingMiddle ) ) <= 1 ) &&
                 ( abs( abs( nSpacingMiddle ) - abs( nSpacingLast ) ) <= 1   ) ) {
-                bLonSpacingOK = TRUE;
+                bLonSpacingOK = true;
             }
         }
 
-        if ( bLonSpacingOK == FALSE ) {
-            CPLDebug( "GDAL_netCDF", 
+        if ( bLonSpacingOK == false ) {
+            CPLDebug( "GDAL_netCDF",
                       "Longitude is not equally spaced." );
         }
-                
+
 /* -------------------------------------------------------------------- */
 /*      Check Latitude                                                  */
 /* -------------------------------------------------------------------- */
         if( ydim == 2 ) {
-            bLatSpacingOK = TRUE;
+            bLatSpacingOK = true;
         }
         else
         {
-            nSpacingBegin   = (int) poDS->rint((pdfYCoord[1] - pdfYCoord[0]) * 
-                                               1000); 	    
+            nSpacingBegin   = (int) poDS->rint((pdfYCoord[1] - pdfYCoord[0]) *
+                                               1000);
 
-            nSpacingMiddle  = (int) poDS->rint((pdfYCoord[ydim/2+1] - 
-                                                pdfYCoord[ydim/2]) * 
+            nSpacingMiddle  = (int) poDS->rint((pdfYCoord[ydim/2+1] -
+                                                pdfYCoord[ydim/2]) *
                                                1000);
 
-            nSpacingLast    = (int) poDS->rint((pdfYCoord[ydim-1] - 
-                                                pdfYCoord[ydim-2]) * 
+            nSpacingLast    = (int) poDS->rint((pdfYCoord[ydim-1] -
+                                                pdfYCoord[ydim-2]) *
                                                1000);
 
-            CPLDebug("GDAL_netCDF", 
+            CPLDebug("GDAL_netCDF",
                      "ydim: %ld nSpacingBegin: %d nSpacingMiddle: %d nSpacingLast: %d",
                      (long)ydim, nSpacingBegin, nSpacingMiddle, nSpacingLast );
 #ifdef NCDF_DEBUG
-            CPLDebug("GDAL_netCDF", 
+            CPLDebug("GDAL_netCDF",
                      "ycoords: %f %f %f %f %f %f",
                      pdfYCoord[0], pdfYCoord[1], pdfYCoord[ydim / 2], pdfYCoord[(ydim / 2) + 1],
                      pdfYCoord[ydim - 2], pdfYCoord[ydim-1]);
@@ -2752,27 +2946,27 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
             if( ( abs( abs( nSpacingBegin )  - abs( nSpacingLast ) )  <= 1   ) &&
                 ( abs( abs( nSpacingBegin )  - abs( nSpacingMiddle ) ) <= 1 ) &&
                 ( abs( abs( nSpacingMiddle ) - abs( nSpacingLast ) ) <= 1   ) ) {
-                bLatSpacingOK = TRUE;
+                bLatSpacingOK = true;
             }
             else if( !oSRS.IsProjected() &&
                      ( (( abs( abs(nSpacingBegin)  - abs(nSpacingLast) ) )   <= 100 ) &&
                        (( abs( abs(nSpacingBegin)  - abs(nSpacingMiddle) ) ) <= 100 ) &&
                        (( abs( abs(nSpacingMiddle) - abs(nSpacingLast) ) )   <= 100 ) ) ) {
-                bLatSpacingOK = TRUE;
-                CPLError(CE_Warning, 1,"Latitude grid not spaced evenly.\nSeting projection for grid spacing is within 0.1 degrees threshold.\n");
-                
-                CPLDebug("GDAL_netCDF", 
+                bLatSpacingOK = true;
+                CPLError(CE_Warning, 1,"Latitude grid not spaced evenly.\nSetting projection for grid spacing is within 0.1 degrees threshold.\n");
+
+                CPLDebug("GDAL_netCDF",
                          "Latitude grid not spaced evenly, but within 0.1 degree threshold (probably a Gaussian grid).\n"
                          "Saving original latitude values in Y_VALUES geolocation metadata" );
                 Set1DGeolocation( nVarDimYID, "Y" );
             }
-            
-            if ( bLatSpacingOK == FALSE ) {
-                CPLDebug( "GDAL_netCDF", 
+
+            if ( bLatSpacingOK == false ) {
+                CPLDebug( "GDAL_netCDF",
                           "Latitude is not equally spaced." );
             }
         }
-        if ( ( bLonSpacingOK == TRUE ) && ( bLatSpacingOK == TRUE ) ) {      
+        if ( ( bLonSpacingOK ) && ( bLatSpacingOK ) ) {
 
 /* -------------------------------------------------------------------- */
 /*      We have gridded data so we can set the Gereferencing info.      */
@@ -2787,15 +2981,15 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
                 /*    If we find them we know how to proceed. Else, use      */
                 /*    the original algorithm.                                */
                 /* --------------------------------------------------------- */
-                double	dummy[2], xMinMax[2], yMinMax[2];
-                int	node_offset = 0;
+                bGotCfGT = true;
 
-                bGotCfGT = TRUE;
-                
+                int node_offset = 0;
                 nc_get_att_int (cdfid, NC_GLOBAL, "node_offset", &node_offset);
-                
+
+                double	dummy[2], xMinMax[2], yMinMax[2];
+
                 if (!nc_get_att_double (cdfid, nVarDimXID, "actual_range", dummy)) {
-                    xMinMax[0] = dummy[0];		
+                    xMinMax[0] = dummy[0];
                     xMinMax[1] = dummy[1];
                 }
                 else {
@@ -2805,11 +2999,11 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
                 }
 
                 if (!nc_get_att_double (cdfid, nVarDimYID, "actual_range", dummy)) {
-                    yMinMax[0] = dummy[0];		
+                    yMinMax[0] = dummy[0];
                     yMinMax[1] = dummy[1];
                 }
                 else {
-                    yMinMax[0] = pdfYCoord[0];	
+                    yMinMax[0] = pdfYCoord[0];
                     yMinMax[1] = pdfYCoord[ydim-1];
                     node_offset = 0;
                 }
@@ -2821,14 +3015,14 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
                     yMinMax[0] = dummy[0];
                     yMinMax[1] = dummy[1];
                 }
-                
+
                 adfTempGeoTransform[0] = xMinMax[0];
                 adfTempGeoTransform[2] = 0;
                 adfTempGeoTransform[3] = yMinMax[1];
                 adfTempGeoTransform[4] = 0;
-                adfTempGeoTransform[1] = ( xMinMax[1] - xMinMax[0] ) / 
+                adfTempGeoTransform[1] = ( xMinMax[1] - xMinMax[0] ) /
                     ( poDS->nRasterXSize + (node_offset - 1) );
-                adfTempGeoTransform[5] = ( yMinMax[0] - yMinMax[1] ) / 
+                adfTempGeoTransform[5] = ( yMinMax[0] - yMinMax[1] ) /
                     ( poDS->nRasterYSize + (node_offset - 1) );
 
 /* -------------------------------------------------------------------- */
@@ -2849,16 +3043,16 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
 /*      Process custom GDAL values (spatial_ref, GeoTransform)          */
 /* -------------------------------------------------------------------- */
     if( !EQUAL( szGridMappingValue, "" )  ) {
-        
+
         if( pszWKT != NULL ) {
-            
+
 /* -------------------------------------------------------------------- */
 /*      Compare SRS obtained from CF attributes and GDAL WKT            */
 /*      If possible use the more complete GDAL WKT                      */
 /* -------------------------------------------------------------------- */
             /* Set the SRS to the one written by GDAL */
-            if ( ! bGotCfSRS || poDS->pszProjection == NULL || ! bIsGdalCfFile ) {   
-                bGotGdalSRS = TRUE;
+            if ( ! bGotCfSRS || poDS->pszProjection == NULL || ! bIsGdalCfFile ) {
+                bGotGdalSRS = true;
                 CPLDebug( "GDAL_netCDF", "setting WKT from GDAL" );
                 SetProjection( pszWKT );
             }
@@ -2869,21 +3063,21 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
                 /* set datum to unknown or else datums will not match, see bug #4281 */
                 if ( oSRSGDAL.GetAttrNode( "DATUM" ) )
                     oSRSGDAL.GetAttrNode( "DATUM" )->GetChild(0)->SetValue( "unknown" );
-                /* need this for setprojection autotest */ 
+                /* need this for setprojection autotest */
                 if ( oSRSGDAL.GetAttrNode( "PROJCS" ) )
                     oSRSGDAL.GetAttrNode( "PROJCS" )->GetChild(0)->SetValue( "unnamed" );
                 if ( oSRSGDAL.GetAttrNode( "GEOGCS" ) )
-                    oSRSGDAL.GetAttrNode( "GEOGCS" )->GetChild(0)->SetValue( "unknown" );   
+                    oSRSGDAL.GetAttrNode( "GEOGCS" )->GetChild(0)->SetValue( "unknown" );
                 oSRSGDAL.GetRoot()->StripNodes( "UNIT" );
                 if ( oSRS.IsSame(&oSRSGDAL) ) {
                     // printf("ARE SAME, using GDAL WKT\n");
-                    bGotGdalSRS = TRUE;
+                    bGotGdalSRS = true;
                     CPLDebug( "GDAL_netCDF", "setting WKT from GDAL" );
                     SetProjection( pszWKT );
                 }
                 else {
-                    CPLDebug( "GDAL_netCDF", 
-                              "got WKT from GDAL \n[%s]\nbut not using it because conflicts with CF\n[%s]\n", 
+                    CPLDebug( "GDAL_netCDF",
+                              "got WKT from GDAL \n[%s]\nbut not using it because conflicts with CF\n[%s]\n",
                               pszWKT, poDS->pszProjection );
                 }
             }
@@ -2899,108 +3093,110 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
                 if( pszGeoTransform != NULL ) {
 
                     char** papszGeoTransform = CSLTokenizeString2( pszGeoTransform,
-                                                            " ", 
+                                                            " ",
                                                             CSLT_HONOURSTRINGS );
                     if( CSLCount(papszGeoTransform) == 6 )
                     {
-                        bGotGdalGT = TRUE;
+                        bGotGdalGT = true;
                         for(int i=0;i<6;i++)
                             adfTempGeoTransform[i] = CPLAtof( papszGeoTransform[i] );
                     }
                     CSLDestroy( papszGeoTransform );
-                    
 /* -------------------------------------------------------------------- */
 /*      Look for corner array values                                    */
 /* -------------------------------------------------------------------- */
                 } else {
-                    double dfNN=0.0, dfSN=0.0, dfEE=0.0, dfWE=0.0;
-                    int bGotNN=FALSE, bGotSN=FALSE, bGotEE=FALSE, bGotWE=FALSE;
                     // CPLDebug( "GDAL_netCDF", "looking for geotransform corners\n" );
 
-                    strcpy(szTemp,szGridMappingValue);
-                    strcat( szTemp, "#" );
-                    strcat( szTemp, "Northernmost_Northing");
-                    pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);                    
+                    snprintf(szTemp,sizeof(szTemp), "%s#Northernmost_Northing", szGridMappingValue);
+                    pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);
+                    bool bGotNN = false;
+                    double dfNN = 0.0;
                     if( pszValue != NULL ) {
                         dfNN = CPLAtof( pszValue );
-                        bGotNN = TRUE;
+                        bGotNN = true;
                     }
 
-                    strcpy(szTemp,szGridMappingValue);
-                    strcat( szTemp, "#" );
-                    strcat( szTemp, "Southernmost_Northing");
-                    pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);                    
+                    snprintf(szTemp,sizeof(szTemp), "%s#Southernmost_Northing", szGridMappingValue);
+                    pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);
+                    bool bGotSN = false;
+                    double dfSN = 0.0;
                     if( pszValue != NULL ) {
                         dfSN = CPLAtof( pszValue );
-                        bGotSN = TRUE;
+                        bGotSN = true;
                     }
-                    
-                    strcpy(szTemp,szGridMappingValue);
-                    strcat( szTemp, "#" );
-                    strcat( szTemp, "Easternmost_Easting");
-                    pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);                    
+
+                    snprintf(szTemp,sizeof(szTemp), "%s#Easternmost_Easting", szGridMappingValue);
+                    pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);
+                    bool bGotEE = false;
+                    double dfEE = 0.0;
                     if( pszValue != NULL ) {
                         dfEE = CPLAtof( pszValue );
-                        bGotEE = TRUE;
+                        bGotEE = true;
                     }
-                    
-                    strcpy(szTemp,szGridMappingValue);
-                    strcat( szTemp, "#" );
-                    strcat( szTemp, "Westernmost_Easting");
-                    pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);                    
+
+                    snprintf(szTemp,sizeof(szTemp), "%s#Westernmost_Easting", szGridMappingValue);
+                    pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);
+                    bool bGotWE = false;
+                    double dfWE = 0.0;
                     if( pszValue != NULL ) {
-                        dfWE = CPLAtof( pszValue ); 
-                        bGotWE = TRUE;
+                        dfWE = CPLAtof( pszValue );
+                        bGotWE = true;
                     }
-                    
+
                     /* Only set the GeoTransform if we got all the values */
-                    if (  bGotNN && bGotSN && bGotEE && bGotWE ) {
+                    if ( bGotNN && bGotSN && bGotEE && bGotWE ) {
 
-                        bGotGdalGT = TRUE;
+                        bGotGdalGT = true;
 
                         adfTempGeoTransform[0] = dfWE;
-                        adfTempGeoTransform[1] = (dfEE - dfWE) / 
+                        adfTempGeoTransform[1] = (dfEE - dfWE) /
                             ( poDS->GetRasterXSize() - 1 );
                         adfTempGeoTransform[2] = 0.0;
                         adfTempGeoTransform[3] = dfNN;
                         adfTempGeoTransform[4] = 0.0;
-                        adfTempGeoTransform[5] = (dfSN - dfNN) / 
+                        adfTempGeoTransform[5] = (dfSN - dfNN) /
                             ( poDS->GetRasterYSize() - 1 );
                         /* compute the center of the pixel */
                         adfTempGeoTransform[0] = dfWE
-                            - (adfTempGeoTransform[1] / 2);                        
+                            - (adfTempGeoTransform[1] / 2);
                         adfTempGeoTransform[3] = dfNN
                             - (adfTempGeoTransform[5] / 2);
                     }
                 } // (pszGeoTransform != NULL)
 
                 if ( bGotGdalSRS && ! bGotGdalGT )
-                    CPLDebug( "GDAL_netCDF", "got SRS but not geotransform from GDAL!");
+                    CPLDebug( "GDAL_netCDF",
+                              "Got SRS but no geotransform from GDAL!");
 
             } // if ( !bGotCfGT )
 
         }
     }
 
-    /* Set GeoTransform if we got a complete one - after projection has been set */
+    // Set GeoTransform if we got a complete one - after projection has been set
     if ( bGotCfGT || bGotGdalGT ) {
         SetGeoTransform( adfTempGeoTransform );
     }
 
-    /* Process geolocation arrays from CF "coordinates" attribute */
-    /* perhaps we should only add if is not a (supported) CF projection (bIsCfProjection */
-    ProcessCFGeolocation( nVarId ); 
+    // Process geolocation arrays from CF "coordinates" attribute.
+    // Perhaps we should only add if is not a (supported) CF projection
+    // (bIsCfProjection).
+    ProcessCFGeolocation( nVarId );
 
-    /* debuging reports */
-    CPLDebug( "GDAL_netCDF", 
-              "bGotGeogCS=%d bGotCfSRS=%d bGotCfGT=%d bGotGdalSRS=%d bGotGdalGT=%d",
-              bGotGeogCS, bGotCfSRS, bGotCfGT, bGotGdalSRS, bGotGdalGT );
+    // Debugging reports.
+    CPLDebug( "GDAL_netCDF",
+              "bGotGeogCS=%d bGotCfSRS=%d bGotCfGT=%d bGotGdalSRS=%d "
+              "bGotGdalGT=%d",
+              static_cast<int>(bGotGeogCS), static_cast<int>(bGotCfSRS),
+              static_cast<int>(bGotCfGT), static_cast<int>(bGotGdalSRS),
+              static_cast<int>(bGotGdalGT) );
 
     if ( !bGotCfGT && !bGotGdalGT )
-        CPLDebug( "GDAL_netCDF", "did not get geotransform from CF nor GDAL!");      
+        CPLDebug( "GDAL_netCDF", "did not get geotransform from CF nor GDAL!");
 
     if ( !bGotGeogCS && !bGotCfSRS && !bGotGdalSRS && !bGotCfGT)
-        CPLDebug( "GDAL_netCDF",  "did not get projection from CF nor GDAL!");   
+        CPLDebug( "GDAL_netCDF",  "did not get projection from CF nor GDAL!");
 
 /* -------------------------------------------------------------------- */
 /*     Search for Well-known GeogCS if got only CF WKT                  */
@@ -3009,12 +3205,14 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
 /*     For example, WGS84 vs. GDA94 (EPSG:3577) - AEA in netcdf_cf.py   */
 /* -------------------------------------------------------------------- */
     /* disabled for now, but could be set in a config option */
-    bLookForWellKnownGCS = FALSE; 
+#if 0
+    bool bLookForWellKnownGCS = false;  // This could be a Config Option.
+
     if ( bLookForWellKnownGCS && bGotCfSRS && ! bGotGdalSRS ) {
         /* ET - could use a more exhaustive method by scanning all EPSG codes in data/gcs.csv */
         /* as proposed by Even in the gdal-dev mailing list "help for comparing two WKT" */
         /* this code could be contributed to a new function */
-        /* OGRSpatialReference * OGRSpatialReference::FindMatchingGeogCS( const OGRSpatialReference *poOther ) */ 
+        /* OGRSpatialReference * OGRSpatialReference::FindMatchingGeogCS( const OGRSpatialReference *poOther ) */
         CPLDebug( "GDAL_netCDF", "Searching for Well-known GeogCS" );
         const char *pszWKGCSList[] = { "WGS84", "WGS72", "NAD27", "NAD83" };
         char *pszWKGCS = NULL;
@@ -3040,40 +3238,42 @@ void netCDFDataset::SetProjectionFromVar( int nVarId )
             }
         }
     }
+#endif
 }
 
 
 int netCDFDataset::ProcessCFGeolocation( int nVarId )
 {
-    int bAddGeoloc = FALSE;
+    bool bAddGeoloc = false;
     char *pszTemp = NULL;
-    char **papszTokens = NULL;
-    CPLString osTMP;
-    char szGeolocXName[NC_MAX_NAME+1];
-    char szGeolocYName[NC_MAX_NAME+1];
-    szGeolocXName[0] = '\0';
-    szGeolocYName[0] = '\0';
-
-    if ( NCDFGetAttr( cdfid, nVarId, "coordinates", &pszTemp ) == CE_None ) { 
+
+    if ( NCDFGetAttr( cdfid, nVarId, "coordinates", &pszTemp ) == CE_None ) {
         /* get X and Y geolocation names from coordinates attribute */
-        papszTokens = CSLTokenizeString2( pszTemp, " ", 0 );
+        char **papszTokens = CSLTokenizeString2( pszTemp, " ", 0 );
         if ( CSLCount(papszTokens) >= 2 ) {
+
+            char szGeolocXName[NC_MAX_NAME+1];
+            char szGeolocYName[NC_MAX_NAME+1];
+            szGeolocXName[0] = '\0';
+            szGeolocYName[0] = '\0';
+
             /* test that each variable is longitude/latitude */
             for ( int i=0; i<CSLCount(papszTokens); i++ ) {
-                if ( NCDFIsVarLongitude(cdfid, -1, papszTokens[i]) ) 
-                    strcpy( szGeolocXName, papszTokens[i] );
-                else if ( NCDFIsVarLatitude(cdfid, -1, papszTokens[i]) ) 
-                    strcpy( szGeolocYName, papszTokens[i] );  
-            }        
+                if ( NCDFIsVarLongitude(cdfid, -1, papszTokens[i]) )
+                    snprintf(szGeolocXName,sizeof(szGeolocXName),"%s",papszTokens[i] );
+                else if ( NCDFIsVarLatitude(cdfid, -1, papszTokens[i]) )
+                    snprintf(szGeolocYName,sizeof(szGeolocYName),"%s",papszTokens[i] );
+            }
             /* add GEOLOCATION metadata */
             if ( !EQUAL(szGeolocXName,"") && !EQUAL(szGeolocYName,"") ) {
-                bAddGeoloc = TRUE;
-                CPLDebug( "GDAL_netCDF", 
+                bAddGeoloc = true;
+                CPLDebug( "GDAL_netCDF",
                           "using variables %s and %s for GEOLOCATION",
                           szGeolocXName, szGeolocYName );
-                
+
                 SetMetadataItem( "SRS", SRS_WKT_WGS84, "GEOLOCATION" );
-                
+
+                CPLString osTMP;
                 osTMP.Printf( "NETCDF:\"%s\":%s",
                               osFilename.c_str(), szGeolocXName );
                 SetMetadataItem( "X_DATASET", osTMP, "GEOLOCATION" );
@@ -3082,44 +3282,42 @@ int netCDFDataset::ProcessCFGeolocation( int nVarId )
                               osFilename.c_str(), szGeolocYName );
                 SetMetadataItem( "Y_DATASET", osTMP, "GEOLOCATION" );
                 SetMetadataItem( "Y_BAND", "1" , "GEOLOCATION" );
-                
+
                 SetMetadataItem( "PIXEL_OFFSET", "0", "GEOLOCATION" );
                 SetMetadataItem( "PIXEL_STEP", "1", "GEOLOCATION" );
-                
+
                 SetMetadataItem( "LINE_OFFSET", "0", "GEOLOCATION" );
                 SetMetadataItem( "LINE_STEP", "1", "GEOLOCATION" );
             }
             else {
-                CPLDebug( "GDAL_netCDF", 
+                CPLDebug( "GDAL_netCDF",
                           "coordinates attribute [%s] is unsupported",
                           pszTemp );
-            }                          
+            }
         }
         else {
-            CPLDebug( "GDAL_netCDF", 
+            CPLDebug( "GDAL_netCDF",
                       "coordinates attribute [%s] with %d element(s) is unsupported",
                       pszTemp, CSLCount(papszTokens) );
         }
         if (papszTokens) CSLDestroy(papszTokens);
         CPLFree( pszTemp );
     }
-    
+
     return bAddGeoloc;
 }
 
 CPLErr netCDFDataset::Set1DGeolocation( int nVarId, const char *szDimName )
 {
-    char    szTemp[ NCDF_MAX_STR_LEN ];
-    char    *pszVarValues = NULL;
-    CPLErr eErr;
-
     /* get values */
-    eErr = NCDFGet1DVar( cdfid, nVarId, &pszVarValues );
+    char    *pszVarValues = NULL;
+    CPLErr eErr = NCDFGet1DVar( cdfid, nVarId, &pszVarValues );
     if ( eErr != CE_None )
         return eErr;
-    
+
     /* write metadata */
-    sprintf( szTemp, "%s_VALUES", szDimName );
+    char szTemp[ NC_MAX_NAME + 1 + 32 ];
+    snprintf( szTemp, sizeof(szTemp), "%s_VALUES", szDimName );
     SetMetadataItem( szTemp, pszVarValues, "GEOLOCATION2" );
 
     CPLFree( pszVarValues );
@@ -3130,23 +3328,22 @@ CPLErr netCDFDataset::Set1DGeolocation( int nVarId, const char *szDimName )
 
 double *netCDFDataset::Get1DGeolocation( CPL_UNUSED const char *szDimName, int &nVarLen )
 {
-    char   **papszValues = NULL;
-    char   *pszTemp = NULL;
-    double *pdfVarValues = NULL;
-
     nVarLen = 0;
 
     /* get Y_VALUES as tokens */
-    papszValues = NCDFTokenizeArray( GetMetadataItem( "Y_VALUES", "GEOLOCATION2" ) );
+    char **papszValues
+        = NCDFTokenizeArray( GetMetadataItem( "Y_VALUES", "GEOLOCATION2" ) );
     if ( papszValues == NULL )
         return NULL;
 
     /* initialize and fill array */
     nVarLen = CSLCount(papszValues);
-    pdfVarValues = (double *) CPLCalloc( nVarLen, sizeof( double ) );
-    for(int i=0, j=0; i < nVarLen; i++) { 
+    double *pdfVarValues = (double *) CPLCalloc( nVarLen, sizeof( double ) );
+
+    for(int i=0, j=0; i < nVarLen; i++) {
         if ( ! bBottomUp ) j=nVarLen - 1 - i;
         else j=i; /* invert latitude values */
+        char *pszTemp = NULL;
         pdfVarValues[j] = CPLStrtod( papszValues[i], &pszTemp );
     }
     CSLDestroy( papszValues );
@@ -3163,13 +3360,13 @@ CPLErr 	netCDFDataset::SetProjection( const char * pszNewProjection )
     CPLMutexHolderD(&hNCMutex);
 
 /* TODO look if proj. already defined, like in geotiff */
-    if( pszNewProjection == NULL ) 
+    if( pszNewProjection == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined, "NULL projection." );
         return CE_Failure;
     }
 
-    if( bSetProjection && (GetAccess() == GA_Update) ) 
+    if( bSetProjection && (GetAccess() == GA_Update) )
     {
         CPLError( CE_Warning, CPLE_AppDefined,
                   "netCDFDataset::SetProjection() should only be called once "
@@ -3179,33 +3376,32 @@ CPLErr 	netCDFDataset::SetProjection( const char * pszNewProjection )
 
     CPLDebug( "GDAL_netCDF", "SetProjection, WKT = %s", pszNewProjection );
 
-    if( !EQUALN(pszNewProjection,"GEOGCS",6)
-        && !EQUALN(pszNewProjection,"PROJCS",6)
+    if( !STARTS_WITH_CI(pszNewProjection, "GEOGCS")
+        && !STARTS_WITH_CI(pszNewProjection, "PROJCS")
         && !EQUAL(pszNewProjection,"") )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Only OGC WKT GEOGCS and PROJCS Projections supported for writing to NetCDF.\n"
                   "%s not supported.",
                   pszNewProjection );
-        
+
         return CE_Failure;
     }
-        
+
     CPLFree( pszProjection );
     pszProjection = CPLStrdup( pszNewProjection );
 
     if( GetAccess() == GA_Update )
     {
         if ( bSetGeoTransform && ! bSetProjection ) {
-            bSetProjection = TRUE;
+            bSetProjection = true;
             return AddProjectionVars();
         }
     }
 
-    bSetProjection = TRUE;
+    bSetProjection = true;
 
     return CE_None;
-
 }
 
 /************************************************************************/
@@ -3219,139 +3415,335 @@ CPLErr 	netCDFDataset::SetGeoTransform ( double * padfTransform )
     memcpy( adfGeoTransform, padfTransform, sizeof(double)*6 );
     // bGeoTransformValid = TRUE;
     // bGeoTIFFInfoChanged = TRUE;
-    
-    CPLDebug( "GDAL_netCDF", 
+
+    CPLDebug( "GDAL_netCDF",
               "SetGeoTransform(%f,%f,%f,%f,%f,%f)",
               padfTransform[0],padfTransform[1],padfTransform[2],
               padfTransform[3],padfTransform[4],padfTransform[5]);
-    
+
     if( GetAccess() == GA_Update )
     {
         if ( bSetProjection && ! bSetGeoTransform ) {
-            bSetGeoTransform = TRUE;
+            bSetGeoTransform = true;
             return AddProjectionVars();
         }
     }
 
-    bSetGeoTransform = TRUE;
+    bSetGeoTransform = true;
 
     return CE_None;
-
 }
 
+
 /************************************************************************/
-/*                          AddProjectionVars()                         */
+/*                         NCDFWriteSRSVariable()                       */
 /************************************************************************/
 
-CPLErr netCDFDataset::AddProjectionVars( GDALProgressFunc pfnProgress, 
-                                         void * pProgressData )
+int NCDFWriteSRSVariable(int cdfid, OGRSpatialReference* poSRS,
+                                char** ppszCFProjection, bool bWriteGDALTags)
 {
-    OGRSpatialReference oSRS;
+    int status;
     int NCDFVarID = -1;
-    double dfTemp = 0.0;
-    const char  *pszValue = NULL;
-    char       szTemp[ NCDF_MAX_STR_LEN ];
-    CPLErr eErr = CE_None;
+    char* pszCFProjection = NULL;
 
-    char   szGeoTransform[ NCDF_MAX_STR_LEN ];
-    *szGeoTransform = '\0';
-    char *pszWKT = NULL;    
-    const char *pszUnits = NULL;
-    char   szUnits[ NCDF_MAX_STR_LEN ];    
-    szUnits[0]='\0';
+    *ppszCFProjection = NULL;
 
-    int  bWriteGridMapping = FALSE;
-    int  bWriteLonLat = FALSE;
-    int  bHasGeoloc = FALSE;
-    int  bWriteGDALTags = FALSE;
-    int  bWriteGeoTransform = FALSE;
+    if( poSRS->IsProjected() )
+    {
+/* -------------------------------------------------------------------- */
+/*      Write CF-1.5 compliant Projected attributes                     */
+/* -------------------------------------------------------------------- */
 
-    nc_type eLonLatType = NC_NAT;
-    int nVarLonID=-1, nVarLatID=-1;
-    int nVarXID=-1, nVarYID=-1;
+        const OGR_SRSNode *poPROJCS = poSRS->GetAttrNode( "PROJCS" );
+        const char  *pszProjName;
+        pszProjName = poSRS->GetAttrValue( "PROJECTION" );
+        if( pszProjName == NULL )
+            return -1;
+
+        /* Basic Projection info (grid_mapping and datum) */
+        for( int i=0; poNetcdfSRS_PT[i].WKT_SRS != NULL; i++ ) {
+            if( EQUAL( poNetcdfSRS_PT[i].WKT_SRS, pszProjName ) ) {
+                CPLDebug( "GDAL_netCDF", "GDAL PROJECTION = %s , NCDF PROJECTION = %s",
+                            poNetcdfSRS_PT[i].WKT_SRS,
+                            poNetcdfSRS_PT[i].CF_SRS);
+                pszCFProjection = CPLStrdup( poNetcdfSRS_PT[i].CF_SRS );
+                CPLDebug( "GDAL_netCDF", "nc_def_var(%d,%s,%d)",
+                            cdfid, poNetcdfSRS_PT[i].CF_SRS, NC_CHAR );
+                status = nc_def_var( cdfid,
+                                        poNetcdfSRS_PT[i].CF_SRS,
+                                        NC_CHAR,
+                                        0, NULL, &NCDFVarID );
+                NCDF_ERR(status);
+                break;
+            }
+        }
+        if( pszCFProjection == NULL )
+            return -1;
 
-    /* For GEOLOCATION information */
-    char ** papszGeolocationInfo = NULL;
-    const char *pszDSName = NULL;
-    GDALDatasetH     hDS_X = NULL;
-    GDALRasterBandH  hBand_X = NULL;
-    GDALDatasetH     hDS_Y = NULL;
-    GDALRasterBandH  hBand_Y = NULL;
-    int nBand;
+        status = nc_put_att_text( cdfid, NCDFVarID, CF_GRD_MAPPING_NAME,
+                                    strlen( pszCFProjection ),
+                                    pszCFProjection );
+        NCDF_ERR(status);
 
-    bAddedProjectionVars = TRUE;
+        /* Various projection attributes */
+        // PDS: keep in sync with SetProjection function
+        NCDFWriteProjAttribs(poPROJCS, pszProjName, cdfid, NCDFVarID);
 
-    pszWKT = (char *) pszProjection;
-    oSRS.importFromWkt( &pszWKT );
+        if( EQUAL( pszProjName, SRS_PT_GEOSTATIONARY_SATELLITE ) )
+        {
+            const char *pszPredefProj4 = poSRS->GetExtension(
+                        poSRS->GetRoot()->GetValue(), "PROJ4", NULL );
+            const char* pszSweepAxisAngle =
+             ( pszPredefProj4 != NULL && strstr(pszPredefProj4, "+sweep=x") ) ? "x" : "y";
+            status = nc_put_att_text( cdfid, NCDFVarID, CF_PP_SWEEP_ANGLE_AXIS,
+                             strlen(pszSweepAxisAngle), pszSweepAxisAngle );
+            NCDF_ERR(status);
+        }
+    }
+    else
+    {
+/* -------------------------------------------------------------------- */
+/*      Write CF-1.5 compliant Geographics attributes                   */
+/*      Note: WKT information will not be preserved (e.g. WGS84)        */
+/* -------------------------------------------------------------------- */
 
-    if( oSRS.IsProjected() )
-        bIsProjected = TRUE;
-    else if( oSRS.IsGeographic() )
-        bIsGeographic = TRUE;
+        pszCFProjection = CPLStrdup( "crs" );
+        CPLDebug( "GDAL_netCDF", "nc_def_var(%d,%s,%d)",
+                    cdfid, pszCFProjection, NC_CHAR );
+        status = nc_def_var( cdfid, pszCFProjection, NC_CHAR,
+                                0, NULL, &NCDFVarID );
+        NCDF_ERR(status);
+        status = nc_put_att_text( cdfid, NCDFVarID, CF_GRD_MAPPING_NAME,
+                                    strlen(CF_PT_LATITUDE_LONGITUDE),
+                                    CF_PT_LATITUDE_LONGITUDE );
+        NCDF_ERR(status);
+    }
 
-    CPLDebug( "GDAL_netCDF", "SetProjection, WKT now = [%s]\nprojected: %d geographic: %d", 
-              pszProjection,bIsProjected,bIsGeographic );
+    status = nc_put_att_text( cdfid, NCDFVarID, CF_LNG_NAME,
+                              strlen("CRS definition"),
+                             "CRS definition" );
+    NCDF_ERR(status);
 
-    if ( ! bSetGeoTransform )
-        CPLDebug( "GDAL_netCDF", "netCDFDataset::AddProjectionVars() called, "
-                  "but GeoTransform has not yet been defined!" );
+    *ppszCFProjection = pszCFProjection;
 
-    if ( ! bSetProjection )
-        CPLDebug( "GDAL_netCDF", "netCDFDataset::AddProjectionVars() called, "
-                  "but Projection has not yet been defined!" );
+/* -------------------------------------------------------------------- */
+/*      Write CF-1.5 compliant common attributes                        */
+/* -------------------------------------------------------------------- */
 
-    /* check GEOLOCATION information */
-    papszGeolocationInfo = GetMetadata("GEOLOCATION");
-    if ( papszGeolocationInfo != NULL ) {
+    /* DATUM information */
+    double dfTemp = poSRS->GetPrimeMeridian();
+    nc_put_att_double( cdfid, NCDFVarID, CF_PP_LONG_PRIME_MERIDIAN,
+                        NC_DOUBLE, 1, &dfTemp );
+    dfTemp = poSRS->GetSemiMajor();
+    nc_put_att_double( cdfid, NCDFVarID, CF_PP_SEMI_MAJOR_AXIS,
+                        NC_DOUBLE, 1, &dfTemp );
+    dfTemp = poSRS->GetInvFlattening();
+    nc_put_att_double( cdfid, NCDFVarID, CF_PP_INVERSE_FLATTENING,
+                        NC_DOUBLE, 1, &dfTemp );
 
-        /* look for geolocation datasets */
-        pszDSName = CSLFetchNameValue( papszGeolocationInfo, "X_DATASET" );
-        if( pszDSName != NULL )
-            hDS_X = GDALOpenShared( pszDSName, GA_ReadOnly );
-        pszDSName = CSLFetchNameValue( papszGeolocationInfo, "Y_DATASET" );
-        if( pszDSName != NULL )
-            hDS_Y = GDALOpenShared( pszDSName, GA_ReadOnly );
+    if( bWriteGDALTags )
+    {
+        char* pszSpatialRef = NULL;
+        poSRS->exportToWkt(&pszSpatialRef);
+        status = nc_put_att_text( cdfid, NCDFVarID, NCDF_SPATIAL_REF,
+                                  strlen( pszSpatialRef ), pszSpatialRef );
+        NCDF_ERR(status);
+        CPLFree(pszSpatialRef);
+    }
 
-        if ( hDS_X != NULL && hDS_Y != NULL ) {
-            nBand = MAX(1,atoi(CSLFetchNameValue( papszGeolocationInfo, "X_BAND" )));
-            hBand_X = GDALGetRasterBand( hDS_X, nBand );
-            nBand = MAX(1,atoi(CSLFetchNameValue( papszGeolocationInfo, "Y_BAND" )));
-            hBand_Y = GDALGetRasterBand( hDS_Y, nBand );
-            
-            /* if geoloc bands are found do basic vaidation based on their dimensions */
-            if ( hDS_X != NULL && hDS_Y != NULL ) {
-                
-                int nXSize_XBand = GDALGetRasterXSize( hDS_X );
-                int nYSize_XBand = GDALGetRasterYSize( hDS_X );
-                int nXSize_YBand = GDALGetRasterXSize( hDS_Y );
-                int nYSize_YBand = GDALGetRasterYSize( hDS_Y );
-                
-                /* TODO 1D geolocation arrays not implemented */
-                if ( (nYSize_XBand == 1) && (nYSize_YBand == 1) ) {
-                    bHasGeoloc = FALSE;
-                    CPLDebug( "GDAL_netCDF", 
+    return NCDFVarID;
+}
+
+/************************************************************************/
+/*                   NCDFWriteLonLatVarsAttributes()                    */
+/************************************************************************/
+
+void NCDFWriteLonLatVarsAttributes(int cdfid,
+                                          int nVarLonID,
+                                          int nVarLatID)
+{
+    int status;
+
+    status = nc_put_att_text( cdfid, nVarLatID, CF_STD_NAME,
+                     strlen(CF_LATITUDE_STD_NAME), CF_LATITUDE_STD_NAME );
+    NCDF_ERR(status);
+
+    status = nc_put_att_text( cdfid, nVarLatID, CF_LNG_NAME,
+                     strlen(CF_LATITUDE_LNG_NAME), CF_LATITUDE_LNG_NAME );
+    NCDF_ERR(status);
+
+    status = nc_put_att_text( cdfid, nVarLatID, CF_UNITS,
+                     strlen(CF_DEGREES_NORTH), CF_DEGREES_NORTH );
+    NCDF_ERR(status);
+
+    status = nc_put_att_text( cdfid, nVarLonID, CF_STD_NAME,
+                     strlen(CF_LONGITUDE_STD_NAME), CF_LONGITUDE_STD_NAME );
+    NCDF_ERR(status);
+
+    status = nc_put_att_text( cdfid, nVarLonID, CF_LNG_NAME,
+                     strlen(CF_LONGITUDE_LNG_NAME), CF_LONGITUDE_LNG_NAME );
+    NCDF_ERR(status);
+
+    status = nc_put_att_text( cdfid, nVarLonID, CF_UNITS,
+                     strlen(CF_DEGREES_EAST), CF_DEGREES_EAST );
+    NCDF_ERR(status);
+}
+
+/************************************************************************/
+/*                     NCDFWriteXYVarsAttributes()                      */
+/************************************************************************/
+
+void NCDFWriteXYVarsAttributes(int cdfid, int nVarXID, int nVarYID,
+                                      OGRSpatialReference* poSRS)
+{
+    int status;
+    const char *pszUnits = NULL;
+    const char *pszUnitsToWrite = "";
+
+    pszUnits = poSRS->GetAttrValue("PROJCS|UNIT",1);
+    if ( pszUnits == NULL || EQUAL(pszUnits,"1") )
+        pszUnitsToWrite = "m";
+    else if ( EQUAL(pszUnits,"1000") )
+        pszUnitsToWrite = "km";
+
+    status = nc_put_att_text( cdfid, nVarXID, CF_STD_NAME,
+                        strlen(CF_PROJ_X_COORD),
+                        CF_PROJ_X_COORD );
+    NCDF_ERR(status);
+
+    status = nc_put_att_text( cdfid, nVarXID, CF_LNG_NAME,
+                        strlen(CF_PROJ_X_COORD_LONG_NAME),
+                        CF_PROJ_X_COORD_LONG_NAME );
+    NCDF_ERR(status);
+
+    status = nc_put_att_text( cdfid, nVarXID, CF_UNITS,
+                        strlen(pszUnitsToWrite), pszUnitsToWrite );
+    NCDF_ERR(status);
+
+    status = nc_put_att_text( cdfid, nVarYID, CF_STD_NAME,
+                        strlen(CF_PROJ_Y_COORD),
+                        CF_PROJ_Y_COORD );
+    NCDF_ERR(status);
+
+    status = nc_put_att_text( cdfid, nVarYID, CF_LNG_NAME,
+                        strlen(CF_PROJ_Y_COORD_LONG_NAME),
+                        CF_PROJ_Y_COORD_LONG_NAME );
+    NCDF_ERR(status);
+
+    status = nc_put_att_text( cdfid, nVarYID, CF_UNITS,
+                        strlen(pszUnitsToWrite), pszUnitsToWrite );
+    NCDF_ERR(status);
+}
+
+/************************************************************************/
+/*                          AddProjectionVars()                         */
+/************************************************************************/
+
+CPLErr netCDFDataset::AddProjectionVars( GDALProgressFunc pfnProgress,
+                                         void * pProgressData )
+{
+    int NCDFVarID = -1;
+    const char  *pszValue = NULL;
+    CPLErr eErr = CE_None;
+
+    bool bWriteGridMapping = false;
+    bool bWriteLonLat = false;
+    bool bHasGeoloc = false;
+    bool bWriteGDALTags = false;
+    bool bWriteGeoTransform = false;
+
+    nc_type eLonLatType = NC_NAT;
+    int nVarLonID=-1, nVarLatID=-1;
+    int nVarXID=-1, nVarYID=-1;
+
+    /* For GEOLOCATION information */
+    const char *pszDSName = NULL;
+    GDALDatasetH     hDS_X = NULL;
+    GDALRasterBandH  hBand_X = NULL;
+    GDALDatasetH     hDS_Y = NULL;
+    GDALRasterBandH  hBand_Y = NULL;
+    int nBand;
+
+    bAddedProjectionVars = true;
+
+    char *pszWKT = (char *) pszProjection;
+    OGRSpatialReference oSRS;
+    oSRS.importFromWkt( &pszWKT );
+
+    if( oSRS.IsProjected() )
+        bIsProjected = true;
+    else if( oSRS.IsGeographic() )
+        bIsGeographic = true;
+
+    CPLDebug( "GDAL_netCDF", "SetProjection, WKT now = [%s]\nprojected: %d geographic: %d",
+              pszProjection ? pszProjection : "(null)",
+              static_cast<int>(bIsProjected),
+              static_cast<int>(bIsGeographic) );
+
+    if ( ! bSetGeoTransform )
+        CPLDebug( "GDAL_netCDF", "netCDFDataset::AddProjectionVars() called, "
+                  "but GeoTransform has not yet been defined!" );
+
+    if ( ! bSetProjection )
+        CPLDebug( "GDAL_netCDF", "netCDFDataset::AddProjectionVars() called, "
+                  "but Projection has not yet been defined!" );
+
+    /* check GEOLOCATION information */
+    char **papszGeolocationInfo = GetMetadata("GEOLOCATION");
+    if ( papszGeolocationInfo != NULL ) {
+
+        /* look for geolocation datasets */
+        pszDSName = CSLFetchNameValue( papszGeolocationInfo, "X_DATASET" );
+        if( pszDSName != NULL )
+            hDS_X = GDALOpenShared( pszDSName, GA_ReadOnly );
+        pszDSName = CSLFetchNameValue( papszGeolocationInfo, "Y_DATASET" );
+        if( pszDSName != NULL )
+            hDS_Y = GDALOpenShared( pszDSName, GA_ReadOnly );
+
+        if ( hDS_X != NULL && hDS_Y != NULL ) {
+            nBand = MAX(1,atoi(CSLFetchNameValueDef( papszGeolocationInfo,
+                                                     "X_BAND", "0" )));
+            hBand_X = GDALGetRasterBand( hDS_X, nBand );
+            nBand = MAX(1,atoi(CSLFetchNameValueDef( papszGeolocationInfo,
+                                                     "Y_BAND", "0" )));
+            hBand_Y = GDALGetRasterBand( hDS_Y, nBand );
+
+            // If geoloc bands are found, do basic validation based on their
+            // dimensions.
+            if ( hBand_X != NULL && hBand_Y != NULL ) {
+
+                int nXSize_XBand = GDALGetRasterXSize( hDS_X );
+                int nYSize_XBand = GDALGetRasterYSize( hDS_X );
+                int nXSize_YBand = GDALGetRasterXSize( hDS_Y );
+                int nYSize_YBand = GDALGetRasterYSize( hDS_Y );
+
+                /* TODO 1D geolocation arrays not implemented */
+                if ( (nYSize_XBand == 1) && (nYSize_YBand == 1) ) {
+                    bHasGeoloc = false;
+                    CPLDebug( "GDAL_netCDF",
                               "1D GEOLOCATION arrays not supported yet" );
                 }
                 /* 2D bands must have same sizes as the raster bands */
-                else if ( (nXSize_XBand != nRasterXSize) ||                              
+                else if ( (nXSize_XBand != nRasterXSize) ||
                           (nYSize_XBand != nRasterYSize) ||
                           (nXSize_YBand != nRasterXSize) ||
-                          (nYSize_YBand != nRasterYSize) ) {                         
-                    bHasGeoloc = FALSE;
-                    CPLDebug( "GDAL_netCDF", 
-                              "GEOLOCATION array sizes (%dx%d %dx%d) differ from raster (%dx%d), not supported",
+                          (nYSize_YBand != nRasterYSize) ) {
+                    bHasGeoloc = false;
+                    CPLDebug( "GDAL_netCDF",
+                              "GEOLOCATION array sizes (%dx%d %dx%d) differ "
+                              "from raster (%dx%d), not supported",
                               nXSize_XBand, nYSize_XBand, nXSize_YBand, nYSize_YBand,
                               nRasterXSize, nRasterYSize );
                 }
                 /* 2D bands are only supported for projected SRS (see CF 5.6) */
-                else if ( ! bIsProjected ) {                       
-                    bHasGeoloc = FALSE;
-                    CPLDebug( "GDAL_netCDF", 
+                else if ( ! bIsProjected ) {
+                    bHasGeoloc = false;
+                    CPLDebug( "GDAL_netCDF",
                               "2D GEOLOCATION arrays only supported for projected SRS" );
                 }
-                else {                       
-                    bHasGeoloc = TRUE;
-                    CPLDebug( "GDAL_netCDF", 
+                else {
+                    bHasGeoloc = true;
+                    CPLDebug( "GDAL_netCDF",
                               "dataset has GEOLOCATION information, will try to write it" );
                 }
             }
@@ -3359,86 +3751,91 @@ CPLErr netCDFDataset::AddProjectionVars( GDALProgressFunc pfnProgress,
     }
 
     /* process projection options */
-    if( bIsProjected ) 
+    if( bIsProjected )
     {
-        int bIsCfProjection = NCDFIsCfProjection( oSRS.GetAttrValue( "PROJECTION" ) );
-        bWriteGridMapping = TRUE;
-        bWriteGDALTags = CSLFetchBoolean( papszCreationOptions, "WRITE_GDAL_TAGS", TRUE );
+        bool bIsCfProjection = NCDFIsCfProjection( oSRS.GetAttrValue( "PROJECTION" ) );
+        bWriteGridMapping = true;
+        bWriteGDALTags = CPL_TO_BOOL(CSLFetchBoolean( papszCreationOptions, "WRITE_GDAL_TAGS", TRUE ));
         /* force WRITE_GDAL_TAGS if is not a CF projection */
         if ( ! bWriteGDALTags && ! bIsCfProjection )
-            bWriteGDALTags = TRUE;
-        if ( bWriteGDALTags ) 
-            bWriteGeoTransform = TRUE;
+            bWriteGDALTags = true;
+        if ( bWriteGDALTags )
+            bWriteGeoTransform = true;
 
         /* write lon/lat : default is NO, except if has geolocation */
-        /* with IF_NEEDED : write if has geoloc or is not CF projection */ 
+        /* with IF_NEEDED : write if has geoloc or is not CF projection */
         pszValue = CSLFetchNameValue( papszCreationOptions,"WRITE_LONLAT" );
         if ( pszValue ) {
             if ( EQUAL( pszValue, "IF_NEEDED" ) ) {
-                if ( bHasGeoloc || ! bIsCfProjection ) 
-                    bWriteLonLat = TRUE;
-                else
-                    bWriteLonLat = FALSE;
+                bWriteLonLat = ( bHasGeoloc || ! bIsCfProjection );
             }
-            else bWriteLonLat = CSLTestBoolean( pszValue );
+            else bWriteLonLat = CPLTestBool( pszValue );
         }
         else
             bWriteLonLat = bHasGeoloc;
 
         /* save value of pszCFCoordinates for later */
-        if ( bWriteLonLat == TRUE ) {
+        if ( bWriteLonLat ) {
             pszCFCoordinates = CPLStrdup( NCDF_LONLAT );
         }
 
         eLonLatType = NC_FLOAT;
         pszValue =  CSLFetchNameValueDef(papszCreationOptions,"TYPE_LONLAT", "FLOAT");
-        if ( EQUAL(pszValue, "DOUBLE" ) ) 
+        if ( EQUAL(pszValue, "DOUBLE" ) )
             eLonLatType = NC_DOUBLE;
     }
-    else 
-    { 
+    else
+    {
         /* files without a Datum will not have a grid_mapping variable and geographic information */
-        if ( bIsGeographic )  bWriteGridMapping = TRUE;
-        else  bWriteGridMapping = FALSE;
-        bWriteGDALTags = CSLFetchBoolean( papszCreationOptions, "WRITE_GDAL_TAGS", bWriteGridMapping );        
-        if ( bWriteGDALTags ) 
-            bWriteGeoTransform = TRUE;
+        bWriteGridMapping = bIsGeographic;
+
+        bWriteGDALTags = CPL_TO_BOOL(CSLFetchBoolean( papszCreationOptions, "WRITE_GDAL_TAGS", bWriteGridMapping ));
+        if ( bWriteGDALTags )
+            bWriteGeoTransform = true;
 
         pszValue =  CSLFetchNameValueDef(papszCreationOptions,"WRITE_LONLAT", "YES");
-        if ( EQUAL( pszValue, "IF_NEEDED" ) )  
-            bWriteLonLat = TRUE;
-        else bWriteLonLat = CSLTestBoolean( pszValue );
+        if ( EQUAL( pszValue, "IF_NEEDED" ) )
+            bWriteLonLat = true;
+        else
+            bWriteLonLat = CPLTestBool( pszValue );
         /*  Don't write lon/lat if no source geotransform */
         if ( ! bSetGeoTransform )
-            bWriteLonLat = FALSE;
+            bWriteLonLat = false;
         /* If we don't write lon/lat, set dimnames to X/Y and write gdal tags*/
         if ( ! bWriteLonLat ) {
-            CPLError( CE_Warning, CPLE_AppDefined, 
+            CPLError( CE_Warning, CPLE_AppDefined,
                       "creating geographic file without lon/lat values!");
             if ( bSetGeoTransform ) {
-                bWriteGDALTags = TRUE; //not desireable if no geotransform
-                bWriteGeoTransform = TRUE;
+                bWriteGDALTags = true; // Not desirable if no geotransform.
+                bWriteGeoTransform = true;
             }
         }
 
         eLonLatType = NC_DOUBLE;
-        pszValue =  CSLFetchNameValueDef(papszCreationOptions,"TYPE_LONLAT", "DOUBLE");
-        if ( EQUAL(pszValue, "FLOAT" ) ) 
+        pszValue
+            = CSLFetchNameValueDef(
+                papszCreationOptions, "TYPE_LONLAT", "DOUBLE");
+        if ( EQUAL(pszValue, "FLOAT" ) )
             eLonLatType = NC_FLOAT;
     }
 
     /* make sure we write grid_mapping if we need to write GDAL tags */
-    if ( bWriteGDALTags ) bWriteGridMapping = TRUE;
+    if ( bWriteGDALTags ) bWriteGridMapping = true;
 
     /* bottom-up value: new driver is bottom-up by default */
     /* override with WRITE_BOTTOMUP */
-    bBottomUp = CSLFetchBoolean( papszCreationOptions, "WRITE_BOTTOMUP", TRUE );       
-    
-    CPLDebug( "GDAL_netCDF", 
+    bBottomUp = CPL_TO_BOOL(CSLFetchBoolean( papszCreationOptions, "WRITE_BOTTOMUP", TRUE ));
+
+    CPLDebug( "GDAL_netCDF",
               "bIsProjected=%d bIsGeographic=%d bWriteGridMapping=%d "
               "bWriteGDALTags=%d bWriteLonLat=%d bBottomUp=%d bHasGeoloc=%d",
-              bIsProjected,bIsGeographic,bWriteGridMapping,
-              bWriteGDALTags,bWriteLonLat,bBottomUp,bHasGeoloc );
+              static_cast<int>(bIsProjected),
+              static_cast<int>(bIsGeographic),
+              static_cast<int>(bWriteGridMapping),
+              static_cast<int>(bWriteGDALTags),
+              static_cast<int>(bWriteLonLat),
+              static_cast<int>(bBottomUp),
+              static_cast<int>(bHasGeoloc) );
 
     /* exit if nothing to do */
     if ( !bIsProjected && !bWriteLonLat )
@@ -3448,20 +3845,20 @@ CPLErr netCDFDataset::AddProjectionVars( GDALProgressFunc pfnProgress,
 /*      Define dimension names                                          */
 /* -------------------------------------------------------------------- */
     /* make sure we are in define mode */
-    SetDefineMode( TRUE );
+    SetDefineMode( true );
 
 
 /* -------------------------------------------------------------------- */
 /*      Rename dimensions if lon/lat                                    */
 /* -------------------------------------------------------------------- */
-    if( ! bIsProjected ) 
+    if( ! bIsProjected )
     {
         /* rename dims to lat/lon */
         papszDimName.Clear(); //if we add other dims one day, this has to change
         papszDimName.AddString( NCDF_DIMNAME_LAT );
         papszDimName.AddString( NCDF_DIMNAME_LON );
 
-        status = nc_rename_dim(cdfid, nYDimID, NCDF_DIMNAME_LAT );
+        int status = nc_rename_dim(cdfid, nYDimID, NCDF_DIMNAME_LAT );
         NCDF_ERR(status);
         status = nc_rename_dim(cdfid, nXDimID, NCDF_DIMNAME_LON );
         NCDF_ERR(status);
@@ -3470,115 +3867,48 @@ CPLErr netCDFDataset::AddProjectionVars( GDALProgressFunc pfnProgress,
 /* -------------------------------------------------------------------- */
 /*      Write projection attributes                                     */
 /* -------------------------------------------------------------------- */
-    if( bWriteGridMapping == TRUE ) 
+    if( bWriteGridMapping )
     {
-    
-        if( bIsProjected ) 
-        {
-/* -------------------------------------------------------------------- */
-/*      Write CF-1.5 compliant Projected attributes                     */
-/* -------------------------------------------------------------------- */
- 
-            const OGR_SRSNode *poPROJCS = oSRS.GetAttrNode( "PROJCS" );
-            const char  *pszProjName;
-            pszProjName = oSRS.GetAttrValue( "PROJECTION" );
-
-            /* Basic Projection info (grid_mapping and datum) */
-            for( int i=0; poNetcdfSRS_PT[i].WKT_SRS != NULL; i++ ) {
-                if( EQUAL( poNetcdfSRS_PT[i].WKT_SRS, pszProjName ) ) {
-                    CPLDebug( "GDAL_netCDF", "GDAL PROJECTION = %s , NCDF PROJECTION = %s", 
-                              poNetcdfSRS_PT[i].WKT_SRS, 
-                              poNetcdfSRS_PT[i].CF_SRS);
-                    pszCFProjection = CPLStrdup( poNetcdfSRS_PT[i].CF_SRS );
-                    CPLDebug( "GDAL_netCDF", "nc_def_var(%d,%s,%d)",
-                              cdfid, poNetcdfSRS_PT[i].CF_SRS, NC_CHAR ); 
-                    status = nc_def_var( cdfid, 
-                                         poNetcdfSRS_PT[i].CF_SRS,
-                                         NC_CHAR, 
-                                         0, NULL, &NCDFVarID );
-                    NCDF_ERR(status);
-                    break;
-                }
-            }
-            status = nc_put_att_text( cdfid, NCDFVarID, CF_GRD_MAPPING_NAME,
-                                      strlen( pszCFProjection ),
-                                      pszCFProjection );
-            NCDF_ERR(status);
-            
-            /* Various projection attributes */
-            // PDS: keep in synch with SetProjection function
-            NCDFWriteProjAttribs(poPROJCS, pszProjName, cdfid, NCDFVarID);
-            
-        }
-        else 
-        {
-/* -------------------------------------------------------------------- */
-/*      Write CF-1.5 compliant Geographics attributes                   */
-/*      Note: WKT information will not be preserved (e.g. WGS84)        */
-/* -------------------------------------------------------------------- */
-
-            pszCFProjection = CPLStrdup( "crs" );
-            CPLDebug( "GDAL_netCDF", "nc_def_var(%d,%s,%d)",
-                      cdfid, pszCFProjection, NC_CHAR );
-            status = nc_def_var( cdfid, pszCFProjection, NC_CHAR, 
-                                 0, NULL, &NCDFVarID );
-            NCDF_ERR(status);
-            status = nc_put_att_text( cdfid, NCDFVarID, CF_GRD_MAPPING_NAME,
-                                      strlen(CF_PT_LATITUDE_LONGITUDE),
-                                      CF_PT_LATITUDE_LONGITUDE );
-            NCDF_ERR(status);
-        }
-        
-/* -------------------------------------------------------------------- */
-/*      Write CF-1.5 compliant common attributes                        */
-/* -------------------------------------------------------------------- */
-
-        /* DATUM information */
-        dfTemp = oSRS.GetPrimeMeridian();
-        nc_put_att_double( cdfid, NCDFVarID, CF_PP_LONG_PRIME_MERIDIAN,
-                           NC_DOUBLE, 1, &dfTemp );
-        dfTemp = oSRS.GetSemiMajor();
-        nc_put_att_double( cdfid, NCDFVarID, CF_PP_SEMI_MAJOR_AXIS,
-                           NC_DOUBLE, 1, &dfTemp );
-        dfTemp = oSRS.GetInvFlattening();
-        nc_put_att_double( cdfid, NCDFVarID, CF_PP_INVERSE_FLATTENING,
-                           NC_DOUBLE, 1, &dfTemp );
+        NCDFVarID = NCDFWriteSRSVariable(cdfid, &oSRS, &pszCFProjection,
+                                         bWriteGDALTags);
+        if( NCDFVarID < 0 )
+            return CE_Failure;
 
         /*  Optional GDAL custom projection tags */
-        if ( bWriteGDALTags == TRUE ) {
-            
-            *szGeoTransform = '\0';
+        if ( bWriteGDALTags ) {
+            CPLString osGeoTransform;
             for( int i=0; i<6; i++ ) {
-                CPLsprintf( szTemp, "%.16g ",
+                osGeoTransform += CPLSPrintf("%.16g ",
                          adfGeoTransform[i] );
-                strcat( szGeoTransform, szTemp );
             }
-            CPLDebug( "GDAL_netCDF", "szGeoTranform = %s", szGeoTransform );
-            
+            CPLDebug( "GDAL_netCDF", "szGeoTransform = %s", osGeoTransform.c_str() );
+
             // if ( strlen(pszProj4Defn) > 0 ) {
             //     nc_put_att_text( cdfid, NCDFVarID, "proj4",
             //                      strlen( pszProj4Defn ), pszProj4Defn );
             // }
-            nc_put_att_text( cdfid, NCDFVarID, NCDF_SPATIAL_REF,
-                             strlen( pszProjection ), pszProjection );
-            /* for now write the geotransform for back-compat or else 
-               the old (1.8.1) driver overrides the CF geotransform with 
+
+            /* for now write the geotransform for back-compat or else
+               the old (1.8.1) driver overrides the CF geotransform with
                empty values from dfNN, dfSN, dfEE, dfWE; */
             /* TODO: fix this in 1.8 branch, and then remove this here */
             if ( bWriteGeoTransform && bSetGeoTransform ) {
-                nc_put_att_text( cdfid, NCDFVarID, NCDF_GEOTRANSFORM,
-                                 strlen( szGeoTransform ),
-                                 szGeoTransform );
+              {
+                int status = nc_put_att_text( cdfid, NCDFVarID, NCDF_GEOTRANSFORM,
+                                 osGeoTransform.size(),
+                                 osGeoTransform.c_str() );
+                NCDF_ERR(status);
+              }
             }
         }
-        
+
         /* write projection variable to band variable */
         /* need to call later if there are no bands */
         AddGridMappingRef();
 
     }  /* end if( bWriteGridMapping ) */
 
-    pfnProgress( 0.10, NULL, pProgressData );    
+    pfnProgress( 0.10, NULL, pProgressData );
 
 /* -------------------------------------------------------------------- */
 /*      Write CF Projection vars                                        */
@@ -3589,52 +3919,32 @@ CPLErr netCDFDataset::AddProjectionVars( GDALProgressFunc pfnProgress,
 /* -------------------------------------------------------------------- */
     if( bIsProjected )
     {
-        pszUnits = oSRS.GetAttrValue("PROJCS|UNIT",1);
-        if ( pszUnits == NULL || EQUAL(pszUnits,"1") ) 
-            strcpy(szUnits,"m");
-        else if ( EQUAL(pszUnits,"1000") ) 
-            strcpy(szUnits,"km");
-
         /* X */
         int anXDims[1];
         anXDims[0] = nXDimID;
         CPLDebug( "GDAL_netCDF", "nc_def_var(%d,%s,%d)",
-                  cdfid, NCDF_DIMNAME_X, NC_DOUBLE );
-        status = nc_def_var( cdfid, NCDF_DIMNAME_X, NC_DOUBLE, 
-                             1, anXDims, &NCDFVarID );
+                  cdfid, CF_PROJ_X_VAR_NAME, NC_DOUBLE );
+        int status = nc_def_var( cdfid, CF_PROJ_X_VAR_NAME, NC_DOUBLE,
+                             1, anXDims, &nVarXID );
         NCDF_ERR(status);
-        nVarXID=NCDFVarID;
-        nc_put_att_text( cdfid, NCDFVarID, CF_STD_NAME,
-                         strlen(CF_PROJ_X_COORD),
-                         CF_PROJ_X_COORD );
-        nc_put_att_text( cdfid, NCDFVarID, CF_LNG_NAME,
-                         strlen(CF_PROJ_X_COORD_LONG_NAME),
-                         CF_PROJ_X_COORD_LONG_NAME );
-        nc_put_att_text( cdfid, NCDFVarID, CF_UNITS, strlen(szUnits), szUnits ); 
 
         /* Y */
         int anYDims[1];
         anYDims[0] = nYDimID;
         CPLDebug( "GDAL_netCDF", "nc_def_var(%d,%s,%d)",
-                  cdfid, NCDF_DIMNAME_Y, NC_DOUBLE );
-        status = nc_def_var( cdfid, NCDF_DIMNAME_Y, NC_DOUBLE, 
-                             1, anYDims, &NCDFVarID );
+                  cdfid, CF_PROJ_Y_VAR_NAME, NC_DOUBLE );
+        status = nc_def_var( cdfid, CF_PROJ_Y_VAR_NAME, NC_DOUBLE,
+                             1, anYDims, &nVarYID );
         NCDF_ERR(status);
-        nVarYID=NCDFVarID;
-        nc_put_att_text( cdfid, NCDFVarID, CF_STD_NAME,
-                         strlen(CF_PROJ_Y_COORD),
-                         CF_PROJ_Y_COORD );
-        nc_put_att_text( cdfid, NCDFVarID, CF_LNG_NAME,
-                         strlen(CF_PROJ_Y_COORD_LONG_NAME),
-                         CF_PROJ_Y_COORD_LONG_NAME );
-        nc_put_att_text( cdfid, NCDFVarID, CF_UNITS, strlen(szUnits), szUnits ); 
+
+        NCDFWriteXYVarsAttributes(cdfid, nVarXID, nVarYID, &oSRS);
     }
 
 /* -------------------------------------------------------------------- */
 /*      Write lat/lon attributes if needed                              */
 /* -------------------------------------------------------------------- */
     if ( bWriteLonLat ) {
-        int *panLatDims=NULL; 
+        int *panLatDims=NULL;
         int *panLonDims=NULL;
         int nLatDims=-1;
         int nLonDims=-1;
@@ -3668,61 +3978,49 @@ CPLErr netCDFDataset::AddProjectionVars( GDALProgressFunc pfnProgress,
             panLonDims = (int *) CPLCalloc( nLonDims, sizeof( int ) );
             panLonDims[0] = nXDimID;
         }
-        
+
         /* def vars and attributes */
-        status = nc_def_var( cdfid, NCDF_DIMNAME_LAT, eLonLatType, 
-                             nLatDims, panLatDims, &NCDFVarID );
+        int status = nc_def_var( cdfid, CF_LATITUDE_VAR_NAME, eLonLatType,
+                             nLatDims, panLatDims, &nVarLatID );
         CPLDebug( "GDAL_netCDF", "nc_def_var(%d,%s,%d,%d,-,-) got id %d",
-                  cdfid, NCDF_DIMNAME_LAT, eLonLatType, nLatDims, NCDFVarID );
+                  cdfid, CF_LATITUDE_VAR_NAME, eLonLatType, nLatDims, nVarLatID );
         NCDF_ERR(status);
-        DefVarDeflate( NCDFVarID, FALSE ); // don't set chunking
-        nVarLatID = NCDFVarID;
-        nc_put_att_text( cdfid, NCDFVarID, CF_STD_NAME,
-                         8,"latitude" );
-        nc_put_att_text( cdfid, NCDFVarID, CF_LNG_NAME,
-                         8, "latitude" );
-        nc_put_att_text( cdfid, NCDFVarID, CF_UNITS,
-                         13, "degrees_north" );
-
-        status = nc_def_var( cdfid, NCDF_DIMNAME_LON, eLonLatType, 
-                             nLonDims, panLonDims, &NCDFVarID );
+        DefVarDeflate( nVarLatID, false ); // don't set chunking
+
+        status = nc_def_var( cdfid, CF_LONGITUDE_VAR_NAME, eLonLatType,
+                             nLonDims, panLonDims, &nVarLonID );
         CPLDebug( "GDAL_netCDF", "nc_def_var(%d,%s,%d,%d,-,-) got id %d",
-                  cdfid, NCDF_DIMNAME_LON, eLonLatType, nLatDims, NCDFVarID );
+                  cdfid, CF_LONGITUDE_VAR_NAME, eLonLatType, nLatDims, nVarLonID );
         NCDF_ERR(status);
-        DefVarDeflate( NCDFVarID, FALSE ); // don't set chunking
-        nVarLonID = NCDFVarID;
-        nc_put_att_text( cdfid, NCDFVarID, CF_STD_NAME,
-                         9, "longitude" );
-        nc_put_att_text( cdfid, NCDFVarID, CF_LNG_NAME,
-                         9, "longitude" );
-        nc_put_att_text( cdfid, NCDFVarID, CF_UNITS,
-                         12, "degrees_east" );
+        DefVarDeflate( nVarLonID, false ); // don't set chunking
+
+        NCDFWriteLonLatVarsAttributes(cdfid, nVarLonID, nVarLatID);
+
         /* free data */
         CPLFree( panLatDims );
         CPLFree( panLonDims );
-       
     }
 
-    pfnProgress( 0.50, NULL, pProgressData );
-
 /* -------------------------------------------------------------------- */
 /*      Get projection values                                           */
 /* -------------------------------------------------------------------- */
 
-    double dfX0, dfDX, dfY0, dfDY;
-    dfX0=0.0, dfDX=0.0, dfY0=0.0, dfDY=0.0;
+    double dfX0 = 0.0;
+    double dfDX = 0.0;
+    double dfY0 = 0.0;
+    double dfDY = 0.0;
     double *padLonVal = NULL;
     double *padLatVal = NULL; /* should use float for projected, save space */
 
     if( bIsProjected )
     {
         // const char  *pszProjection;
-        OGRSpatialReference oSRS;
         OGRSpatialReference *poLatLonSRS = NULL;
         OGRCoordinateTransformation *poTransform = NULL;
 
-        char *pszWKT = (char *) pszProjection;
-        oSRS.importFromWkt( &pszWKT );
+        char *pszWKT2 = (char *) pszProjection;
+        OGRSpatialReference oSRS2;
+        oSRS2.importFromWkt( &pszWKT2 );
 
         double *padYVal = NULL;
         double *padXVal = NULL;
@@ -3741,16 +4039,16 @@ CPLErr netCDFDataset::AddProjectionVars( GDALProgressFunc pfnProgress,
 /* -------------------------------------------------------------------- */
         if ( ! bBottomUp )
             dfY0 = adfGeoTransform[3];
-        else /* invert latitude values */ 
+        else /* invert latitude values */
             dfY0 = adfGeoTransform[3] + ( adfGeoTransform[5] * nRasterYSize );
         dfDY = adfGeoTransform[5];
-        
+
         for( int j=0; j<nRasterYSize; j++ ) {
             /* The data point is centered inside the pixel */
             if ( ! bBottomUp )
                 padYVal[j] = dfY0 + (j+0.5)*dfDY ;
-            else /* invert latitude values */ 
-                padYVal[j] = dfY0 - (j+0.5)*dfDY ;            
+            else /* invert latitude values */
+                padYVal[j] = dfY0 - (j+0.5)*dfDY ;
         }
         startX[0] = 0;
         countX[0] = nRasterXSize;
@@ -3772,10 +4070,10 @@ CPLErr netCDFDataset::AddProjectionVars( GDALProgressFunc pfnProgress,
 /*      Write X/Y values                                                */
 /* -------------------------------------------------------------------- */
         /* make sure we are in data mode */
-        SetDefineMode( FALSE );
+        SetDefineMode( false );
 
         CPLDebug("GDAL_netCDF", "Writing X values" );
-        status = nc_put_vara_double( cdfid, nVarXID, startX,
+        int status = nc_put_vara_double( cdfid, nVarXID, startX,
                                      countX, padXVal);
         NCDF_ERR(status);
 
@@ -3793,71 +4091,70 @@ CPLErr netCDFDataset::AddProjectionVars( GDALProgressFunc pfnProgress,
 
         /* Get OGR transform if GEOLOCATION is not available */
         if ( bWriteLonLat && !bHasGeoloc ) {
-            poLatLonSRS = oSRS.CloneGeogCS();
+            poLatLonSRS = oSRS2.CloneGeogCS();
             if ( poLatLonSRS != NULL )
-                poTransform = OGRCreateCoordinateTransformation( &oSRS, poLatLonSRS );
+                poTransform = OGRCreateCoordinateTransformation( &oSRS2, poLatLonSRS );
             /* if no OGR transform, then don't write CF lon/lat */
             if( poTransform == NULL ) {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "Unable to get Coordinate Transform" );
-                bWriteLonLat = FALSE;
+                bWriteLonLat = false;
             }
         }
-            
+
         if ( bWriteLonLat )  {
-            
+
             if ( ! bHasGeoloc )
                 CPLDebug("GDAL_netCDF", "Transforming (X,Y)->(lon,lat)" );
-            else 
+            else
                 CPLDebug("GDAL_netCDF", "writing (lon,lat) from GEOLOCATION arrays" );
- 
-            int bOK = TRUE;
+
+            bool bOK = true;
             double dfProgress = 0.2;
-            int i,j;
-            
+
             size_t start[]={ 0, 0 };
             size_t count[]={ 1, (size_t)nRasterXSize };
             padLatVal = (double *) CPLMalloc( nRasterXSize * sizeof( double ) );
             padLonVal = (double *) CPLMalloc( nRasterXSize * sizeof( double ) );
 
-            for( j = 0; (j < nRasterYSize) && bOK && (status == NC_NOERR); j++ ) {
-                
+            for( int j = 0; (j < nRasterYSize) && bOK && (status == NC_NOERR); j++ ) {
+
                 start[0] = j;
-                
+
                 /* get values from geotransform */
                 if ( ! bHasGeoloc ) {
                     /* fill values to transform */
-                    for( i=0; i<nRasterXSize; i++ ) {
+                    for( int i=0; i<nRasterXSize; i++ ) {
                         padLatVal[i] = padYVal[j];
                         padLonVal[i] = padXVal[i];
                     }
-                    
+
                     /* do the transform */
-                    bOK = poTransform->Transform( nRasterXSize, 
-                                                  padLonVal, padLatVal, NULL );
+                    bOK = CPL_TO_BOOL(poTransform->Transform( nRasterXSize,
+                                                  padLonVal, padLatVal, NULL ));
                     if ( ! bOK ) {
-                        CPLError( CE_Failure, CPLE_AppDefined, 
+                        CPLError( CE_Failure, CPLE_AppDefined,
                                   "Unable to Transform (X,Y) to (lon,lat).\n" );
                     }
                 }
                 /* get values from geoloc arrays */
                 else {
-                    eErr = GDALRasterIO( hBand_Y, GF_Read, 
+                    eErr = GDALRasterIO( hBand_Y, GF_Read,
                                          0, j, nRasterXSize, 1,
-                                         padLatVal, nRasterXSize, 1, 
+                                         padLatVal, nRasterXSize, 1,
                                          GDT_Float64, 0, 0 );
                     if ( eErr == CE_None ) {
-                        eErr = GDALRasterIO( hBand_X, GF_Read, 
+                        eErr = GDALRasterIO( hBand_X, GF_Read,
                                              0, j, nRasterXSize, 1,
-                                             padLonVal, nRasterXSize, 1, 
+                                             padLonVal, nRasterXSize, 1,
                                              GDT_Float64, 0, 0 );
                     }
-                    
+
                     if ( eErr == CE_None )
-                        bOK = TRUE;
+                        bOK = true;
                     else {
-                        bOK = FALSE;
-                        CPLError( CE_Failure, CPLE_AppDefined, 
+                        bOK = false;
+                        CPLError( CE_Failure, CPLE_AppDefined,
                                   "Unable to get scanline %d\n",j );
                     }
                 }
@@ -3872,17 +4169,17 @@ CPLErr netCDFDataset::AddProjectionVars( GDALProgressFunc pfnProgress,
                     NCDF_ERR(status);
                 }
 
-                if ( j % (nRasterYSize/10) == 0 ) {
+                if ( (nRasterYSize/10) >0 && (j % (nRasterYSize/10) == 0) ) {
                     dfProgress += 0.08;
                     pfnProgress( dfProgress , NULL, pProgressData );
                 }
             }
-            
+
         }
 
         /* Free the srs and transform objects */
-        if ( poLatLonSRS != NULL ) CPLFree( poLatLonSRS );
-        if ( poTransform != NULL ) CPLFree( poTransform );
+        if ( poLatLonSRS != NULL ) delete poLatLonSRS;
+        if ( poTransform != NULL ) delete poTransform;
 
         /* Free data */
         CPLFree( padXVal );
@@ -3893,17 +4190,17 @@ CPLErr netCDFDataset::AddProjectionVars( GDALProgressFunc pfnProgress,
     } // projected
 
     /* If not Projected assume Geographic to catch grids without Datum */
-    else if ( bWriteLonLat == TRUE )  {  
-        	
+    else if ( bWriteLonLat )  {
+
 /* -------------------------------------------------------------------- */
 /*      Get latitude values                                             */
 /* -------------------------------------------------------------------- */
         if ( ! bBottomUp )
             dfY0 = adfGeoTransform[3];
-        else /* invert latitude values */ 
+        else /* invert latitude values */
             dfY0 = adfGeoTransform[3] + ( adfGeoTransform[5] * nRasterYSize );
         dfDY = adfGeoTransform[5];
-        
+
         /* override lat values with the ones in GEOLOCATION/Y_VALUES */
         if ( GetMetadataItem( "Y_VALUES", "GEOLOCATION" ) != NULL ) {
             int nTemp = 0;
@@ -3914,13 +4211,13 @@ CPLErr netCDFDataset::AddProjectionVars( GDALProgressFunc pfnProgress,
                 CPLDebug("GDAL_netCDF", "Using Y_VALUES geolocation metadata for lat values" );
             }
             else {
-                CPLDebug("GDAL_netCDF", 
+                CPLDebug("GDAL_netCDF",
                          "Got %d elements from Y_VALUES geolocation metadata, need %d",
                          nTemp, nRasterYSize );
                 if ( padLatVal ) {
                     CPLFree( padLatVal );
                     padLatVal = NULL;
-                } 
+                }
             }
         }
 
@@ -3930,16 +4227,14 @@ CPLErr netCDFDataset::AddProjectionVars( GDALProgressFunc pfnProgress,
                 /* The data point is centered inside the pixel */
                 if ( ! bBottomUp )
                     padLatVal[i] = dfY0 + (i+0.5)*dfDY ;
-                else /* invert latitude values */ 
+                else /* invert latitude values */
                     padLatVal[i] = dfY0 - (i+0.5)*dfDY ;
             }
         }
 
-        size_t startLat[1];
-        size_t countLat[1];
-        startLat[0] = 0;
-        countLat[0] = nRasterYSize;
-                
+        size_t startLat[1] = {0};
+        size_t countLat[1] = {static_cast<size_t>(nRasterYSize)};
+
 /* -------------------------------------------------------------------- */
 /*      Get longitude values                                            */
 /* -------------------------------------------------------------------- */
@@ -3951,22 +4246,20 @@ CPLErr netCDFDataset::AddProjectionVars( GDALProgressFunc pfnProgress,
             /* The data point is centered inside the pixel */
             padLonVal[i] = dfX0 + (i+0.5)*dfDX ;
         }
-        
-        size_t startLon[1];
-        size_t countLon[1];
-        startLon[0] = 0;
-        countLon[0] = nRasterXSize;
+
+        size_t startLon[1] = {0};
+        size_t countLon[1] = {static_cast<size_t>(nRasterXSize)};
 
 /* -------------------------------------------------------------------- */
 /*      Write latitude and longitude values                             */
 /* -------------------------------------------------------------------- */
         /* make sure we are in data mode */
-        SetDefineMode( FALSE );
+        SetDefineMode( false );
 
         /* write values */
         CPLDebug("GDAL_netCDF", "Writing lat values" );
-    
-        status = nc_put_vara_double( cdfid, nVarLatID, startLat,
+
+        int status = nc_put_vara_double( cdfid, nVarLatID, startLat,
                                      countLat, padLatVal);
         NCDF_ERR(status);
 
@@ -3974,19 +4267,20 @@ CPLErr netCDFDataset::AddProjectionVars( GDALProgressFunc pfnProgress,
         status = nc_put_vara_double( cdfid, nVarLonID, startLon,
                                      countLon, padLonVal);
         NCDF_ERR(status);
-        
+
         /* free values */
-        CPLFree( padLatVal );  
-        CPLFree( padLonVal );  
-        
-    }// not projected 
-            
+        CPLFree( padLatVal );
+        CPLFree( padLonVal );
+    }// not projected
+
     /* close geoloc datasets */
-    if ( bHasGeoloc ) {
-        GDALClose( hDS_X ); 
-        GDALClose( hDS_Y ); 
-    }        
- 
+    if( hDS_X != NULL ) {
+        GDALClose( hDS_X );
+    }
+    if( hDS_Y != NULL ) {
+        GDALClose( hDS_Y );
+    }
+
     pfnProgress( 1.00, NULL, pProgressData );
 
     return CE_None;
@@ -3997,36 +4291,35 @@ CPLErr netCDFDataset::AddProjectionVars( GDALProgressFunc pfnProgress,
 void netCDFDataset::AddGridMappingRef( )
 {
     int nVarId = -1;
-    int bOldDefineMode = bDefineMode;
+    bool bOldDefineMode = bDefineMode;
 
-    if( (GetAccess() == GA_Update) && 
+    if( (GetAccess() == GA_Update) &&
         (nBands >= 1) && (GetRasterBand( 1 )) &&
         pszCFProjection != NULL && ! EQUAL( pszCFProjection, "" ) ) {
 
         nVarId = ( (netCDFRasterBand *) GetRasterBand( 1 ) )->nZId;
-        bAddedGridMappingRef = TRUE;
+        bAddedGridMappingRef = true;
 
         /* make sure we are in define mode */
-        SetDefineMode( TRUE );
-        status = nc_put_att_text( cdfid, nVarId, 
+        SetDefineMode( true );
+        int status = nc_put_att_text( cdfid, nVarId,
                                   CF_GRD_MAPPING,
                                   strlen( pszCFProjection ),
                                   pszCFProjection );
         NCDF_ERR(status);
         if ( pszCFCoordinates != NULL && ! EQUAL( pszCFCoordinates, "" ) ) {
-            status = nc_put_att_text( cdfid, nVarId, 
+            status = nc_put_att_text( cdfid, nVarId,
                                       CF_COORDINATES,
-                                      strlen( pszCFCoordinates ), 
+                                      strlen( pszCFCoordinates ),
                                       pszCFCoordinates );
             NCDF_ERR(status);
         }
 
         /* go back to previous define mode */
         SetDefineMode( bOldDefineMode );
-    }           
+    }
 }
 
-
 /************************************************************************/
 /*                          GetGeoTransform()                           */
 /************************************************************************/
@@ -4037,8 +4330,8 @@ CPLErr netCDFDataset::GetGeoTransform( double * padfTransform )
     memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
     if( bSetGeoTransform )
         return CE_None;
-    else
-        return GDALPamDataset::GetGeoTransform( padfTransform );
+
+    return GDALPamDataset::GetGeoTransform( padfTransform );
 }
 
 /************************************************************************/
@@ -4056,7 +4349,7 @@ double netCDFDataset::rint( double dfX)
         }
         return double( nX );
     } else {
-        int nX= (int) (dfX-0.5);
+        int nX = (int) (dfX-0.5);
         if( nX % 2 ) {
             double dfDiff = dfX - (double)nX;
             if( dfDiff == 0.5 )
@@ -4069,34 +4362,35 @@ double netCDFDataset::rint( double dfX)
 /************************************************************************/
 /*                        ReadAttributes()                              */
 /************************************************************************/
-CPLErr netCDFDataset::ReadAttributes( int cdfid, int var)
+CPLErr netCDFDataset::ReadAttributes( int cdfidIn, int var)
 
 {
-    char    szAttrName[ NC_MAX_NAME+1 ];
     char    szVarName [ NC_MAX_NAME+1 ];
-    char    szMetaName[ NC_MAX_NAME * 2+1+1 ];
-    char    *pszMetaTemp = NULL;
     int     nbAttr;
 
-    nc_inq_varnatts( cdfid, var, &nbAttr );
+    nc_inq_varnatts( cdfidIn, var, &nbAttr );
     if( var == NC_GLOBAL ) {
-        strcpy( szVarName,"NC_GLOBAL" );
+        strcpy( szVarName, "NC_GLOBAL" );
     }
     else {
         szVarName[0] = '\0';
-        nc_inq_varname( cdfid, var, szVarName );
+        int status = nc_inq_varname( cdfidIn, var, szVarName );
+        NCDF_ERR(status);
     }
 
     for( int l=0; l < nbAttr; l++) {
-	
-        szAttrName[0] = '\0';
-        nc_inq_attname( cdfid, var, l, szAttrName);
-        sprintf( szMetaName, "%s#%s", szVarName, szAttrName  );
+        char szAttrName[ NC_MAX_NAME+1 ];
+        szAttrName[0] = 0;
+        int status = nc_inq_attname( cdfidIn, var, l, szAttrName);
+        NCDF_ERR(status);
+        char szMetaName[ NC_MAX_NAME * 2 + 1 + 1 ];
+        snprintf( szMetaName, sizeof(szMetaName), "%s#%s", szVarName, szAttrName  );
 
-        if ( NCDFGetAttr( cdfid, var, szAttrName, &pszMetaTemp )
+        char *pszMetaTemp = NULL;
+        if ( NCDFGetAttr( cdfidIn, var, szAttrName, &pszMetaTemp )
              == CE_None ) {
-            papszMetadata = CSLSetNameValue(papszMetadata, 
-                                            szMetaName, 
+            papszMetadata = CSLSetNameValue(papszMetadata,
+                                            szMetaName,
                                             pszMetaTemp);
             CPLFree(pszMetaTemp);
             pszMetaTemp = NULL;
@@ -4104,11 +4398,9 @@ CPLErr netCDFDataset::ReadAttributes( int cdfid, int var)
         else {
             CPLDebug( "GDAL_netCDF", "invalid global metadata %s", szMetaName );
         }
-
     }
-	
-    return CE_None;
 
+    return CE_None;
 }
 
 
@@ -4117,165 +4409,157 @@ CPLErr netCDFDataset::ReadAttributes( int cdfid, int var)
 /************************************************************************/
 void netCDFDataset::CreateSubDatasetList( )
 {
-
-    char         szDim[ MAX_NC_NAME ];
-    char         szTemp[ MAX_NC_NAME ];
-    char         szType[ MAX_NC_NAME ];
-    char         szName[ MAX_NC_NAME+1 ];
-    char         szVarStdName[ MAX_NC_NAME+1 ];
-    int          nDims;
-    int          nVar;
-    int          nVarCount;
-    int          i;
-    nc_type      nVarType;
+    char         szName[ NC_MAX_NAME+1 ];
+    char         szVarStdName[ NC_MAX_NAME+1 ];
     int          *ponDimIds;
-    size_t       nDimLen;
-    int          nSub;
     nc_type      nAttype;
     size_t       nAttlen;
 
-    netCDFDataset 	*poDS;
-    poDS = this;
+    netCDFDataset *poDS = this;
 
-    nSub=1;
+    int nSub = 1;
+    int nVarCount;
     nc_inq_nvars ( cdfid, &nVarCount );
 
-    for ( nVar = 0; nVar < nVarCount; nVar++ ) {
+    for ( int nVar = 0; nVar < nVarCount; nVar++ ) {
 
+        int nDims;
         nc_inq_varndims ( cdfid, nVar, &nDims );
 
         if( nDims >= 2 ) {
             ponDimIds = (int *) CPLCalloc( nDims, sizeof( int ) );
             nc_inq_vardimid ( cdfid, nVar, ponDimIds );
-	    
+
 /* -------------------------------------------------------------------- */
 /*      Create Sub dataset list                                         */
 /* -------------------------------------------------------------------- */
-            szDim[0]='\0';
-            for( i = 0; i < nDims; i++ ) {
+            CPLString osDim;
+            for( int i = 0; i < nDims; i++ ) {
+                size_t nDimLen;
                 nc_inq_dimlen ( cdfid, ponDimIds[i], &nDimLen );
-                sprintf(szTemp, "%d", (int) nDimLen);
-                strcat(szTemp,  "x" );
-                strcat(szDim,   szTemp);
+                osDim += CPLSPrintf("%dx", (int) nDimLen);
             }
 
+            nc_type nVarType;
             nc_inq_vartype( cdfid, nVar, &nVarType );
 /* -------------------------------------------------------------------- */
 /*      Get rid of the last "x" character                               */
 /* -------------------------------------------------------------------- */
-            szDim[strlen(szDim) - 1] = '\0';
+            osDim.resize(osDim.size()-1);
+            const char* pszType = "";
             switch( nVarType ) {
-		
                 case NC_BYTE:
-                    strcpy(szType, "8-bit integer");
+                    pszType = "8-bit integer";
                     break;
                 case NC_CHAR:
-                    strcpy(szType, "8-bit character");
+                    pszType = "8-bit character";
                     break;
-                case NC_SHORT: 
-                    strcpy(szType, "16-bit integer");
+                case NC_SHORT:
+                    pszType = "16-bit integer";
                     break;
                 case NC_INT:
-                    strcpy(szType, "32-bit integer");
+                    pszType = "32-bit integer";
                     break;
                 case NC_FLOAT:
-                    strcpy(szType, "32-bit floating-point");
+                    pszType = "32-bit floating-point";
                     break;
                 case NC_DOUBLE:
-                    strcpy(szType, "64-bit floating-point");
+                    pszType = "64-bit floating-point";
                     break;
 #ifdef NETCDF_HAS_NC4
                 case NC_UBYTE:
-                    strcpy(szType, "8-bit unsigned integer");
+                    pszType = "8-bit unsigned integer";
                     break;
-                case NC_USHORT: 
-                    strcpy(szType, "16-bit unsigned integer");
+                case NC_USHORT:
+                    pszType = "16-bit unsigned integer";
                     break;
                 case NC_UINT:
-                    strcpy(szType, "32-bit unsigned integer");
+                    pszType = "32-bit unsigned integer";
                     break;
                 case NC_INT64:
-                    strcpy(szType, "64-bit integer");
+                    pszType = "64-bit integer";
                     break;
                 case NC_UINT64:
-                    strcpy(szType, "64-bit unsigned integer");
+                    pszType = "64-bit unsigned integer";
                     break;
-#endif    
+#endif
                 default:
                     break;
             }
             szName[0] = '\0';
-            nc_inq_varname( cdfid, nVar, szName);
+            int status = nc_inq_varname( cdfid, nVar, szName);
+            NCDF_ERR(status);
             nAttlen = 0;
             nc_inq_att( cdfid, nVar, CF_STD_NAME, &nAttype, &nAttlen);
             if( nAttlen < sizeof(szVarStdName) &&
-                nc_get_att_text ( cdfid, nVar, CF_STD_NAME, 
+                nc_get_att_text ( cdfid, nVar, CF_STD_NAME,
                                   szVarStdName ) == NC_NOERR ) {
                 szVarStdName[nAttlen] = '\0';
             }
             else {
-                strcpy( szVarStdName, szName );
+                snprintf( szVarStdName, sizeof(szVarStdName), "%s", szName );
             }
-    
-            sprintf( szTemp, "SUBDATASET_%d_NAME", nSub);
-            
+
+            char szTemp[ NC_MAX_NAME+1 ];
+            snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_NAME", nSub);
+
             poDS->papszSubDatasets =
                 CSLSetNameValue( poDS->papszSubDatasets, szTemp,
                                  CPLSPrintf( "NETCDF:\"%s\":%s",
                                              poDS->osFilename.c_str(),
                                              szName)  ) ;
 
-            sprintf(  szTemp, "SUBDATASET_%d_DESC", nSub++ );
+            snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_DESC", nSub++ );
 
             poDS->papszSubDatasets =
                 CSLSetNameValue( poDS->papszSubDatasets, szTemp,
-                                 CPLSPrintf( "[%s] %s (%s)", 
-                                             szDim,
+                                 CPLSPrintf( "[%s] %s (%s)",
+                                             osDim.c_str(),
                                              szVarStdName,
-                                             szType ) );
+                                             pszType ) );
 
             CPLFree(ponDimIds);
         }
     }
-
 }
-    
+
 /************************************************************************/
 /*                              IdentifyFormat()                      */
 /************************************************************************/
 
-int netCDFDataset::IdentifyFormat( GDALOpenInfo * poOpenInfo, 
+NetCDFFormatEnum netCDFDataset::IdentifyFormat( GDALOpenInfo * poOpenInfo,
 #ifndef HAVE_HDF5
 CPL_UNUSED
 #endif
-                                   bool bCheckExt = TRUE )
+                                   bool bCheckExt = true )
 {
 /* -------------------------------------------------------------------- */
 /*      Does this appear to be a netcdf file? If so, which format?      */
 /*      http://www.unidata.ucar.edu/software/netcdf/docs/faq.html#fv1_5 */
 /* -------------------------------------------------------------------- */
 
-    if( EQUALN(poOpenInfo->pszFilename,"NETCDF:",7) )
+    if( STARTS_WITH_CI(poOpenInfo->pszFilename, "NETCDF:") )
         return NCDF_FORMAT_UNKNOWN;
     if ( poOpenInfo->nHeaderBytes < 4 )
         return NCDF_FORMAT_NONE;
-    if ( EQUALN((char*)poOpenInfo->pabyHeader,"CDF\001",4) )
+    if ( STARTS_WITH_CI((char*)poOpenInfo->pabyHeader, "CDF\001") )
     {
         /* In case the netCDF driver is registered before the GMT driver, */
         /* avoid opening GMT files */
         if( GDALGetDriverByName("GMT") != NULL )
         {
-            int bFoundZ = FALSE, bFoundDimension = FALSE;
+            bool bFoundZ = false;
+            bool bFoundDimension = false;
             for(int i=0;i<poOpenInfo->nHeaderBytes - 11;i++)
             {
                 if( poOpenInfo->pabyHeader[i] == 1 &&
                     poOpenInfo->pabyHeader[i+1] == 'z' &&
                     poOpenInfo->pabyHeader[i+2] == 0  )
-                    bFoundZ = TRUE;
+                    bFoundZ = true;
                 else if( poOpenInfo->pabyHeader[i] == 9 &&
                         memcmp((const char*)poOpenInfo->pabyHeader + i + 1, "dimension", 9) == 0 &&
                         poOpenInfo->pabyHeader[i+10] == 0 )
-                    bFoundDimension = TRUE;
+                    bFoundDimension = true;
             }
             if( bFoundZ && bFoundDimension )
                 return NCDF_FORMAT_UNKNOWN;
@@ -4283,21 +4567,21 @@ CPL_UNUSED
 
         return NCDF_FORMAT_NC;
     }
-    else if ( EQUALN((char*)poOpenInfo->pabyHeader,"CDF\002",4) )
+    else if ( STARTS_WITH_CI((char*)poOpenInfo->pabyHeader, "CDF\002") )
         return NCDF_FORMAT_NC2;
-    else if ( EQUALN((char*)poOpenInfo->pabyHeader,"\211HDF\r\n\032\n",8) ) {
+    else if ( STARTS_WITH_CI((char*)poOpenInfo->pabyHeader, "\211HDF\r\n\032\n") ) {
         /* Requires netCDF-4/HDF5 support in libnetcdf (not just libnetcdf-v4).
-           If HDF5 is not supported in GDAL, this driver will try to open the file 
-           Else, make sure this driver does not try to open HDF5 files 
-           If user really wants to open with this driver, use NETCDF:file.h5 format. 
-           This check should be relaxed, but there is no clear way to make a difference. 
+           If HDF5 is not supported in GDAL, this driver will try to open the file
+           Else, make sure this driver does not try to open HDF5 files
+           If user really wants to open with this driver, use NETCDF:file.h5 format.
+           This check should be relaxed, but there is no clear way to make a difference.
         */
 
         /* Check for HDF5 support in GDAL */
 #ifdef HAVE_HDF5
         if ( bCheckExt ) { /* Check by default */
             const char* pszExtension = CPLGetExtension( poOpenInfo->pszFilename );
-            if ( ! ( EQUAL( pszExtension, "nc")  || EQUAL( pszExtension, "cdf") 
+            if ( ! ( EQUAL( pszExtension, "nc")  || EQUAL( pszExtension, "cdf")
                      || EQUAL( pszExtension, "nc2") || EQUAL( pszExtension, "nc4")
 					 || EQUAL( pszExtension, "nc3") || EQUAL( pszExtension, "grd") ) )
                 return NCDF_FORMAT_HDF5;
@@ -4312,7 +4596,7 @@ CPL_UNUSED
 #endif
 
     }
-    else if ( EQUALN((char*)poOpenInfo->pabyHeader,"\016\003\023\001",4) ) {
+    else if ( STARTS_WITH_CI((char*)poOpenInfo->pabyHeader, "\016\003\023\001") ) {
         /* Requires HDF4 support in libnetcdf, but if HF4 is supported by GDAL don't try to open. */
         /* If user really wants to open with this driver, use NETCDF:file.hdf syntax. */
 
@@ -4326,141 +4610,759 @@ CPL_UNUSED
 
         /* Check for HDF4 support in libnetcdf */
 #ifdef NETCDF_HAS_HDF4
-        return NCDF_FORMAT_NC4; 
+        return NCDF_FORMAT_NC4;
 #else
         return NCDF_FORMAT_HDF4;
 #endif
     }
 
     return NCDF_FORMAT_NONE;
-} 
+}
 
 /************************************************************************/
-/*                              Identify()                              */
+/*                            TestCapability()                          */
 /************************************************************************/
 
-int netCDFDataset::Identify( GDALOpenInfo * poOpenInfo )
-
+int netCDFDataset::TestCapability(const char* pszCap)
 {
-    if( EQUALN(poOpenInfo->pszFilename,"NETCDF:",7) ) {
-        return TRUE;
+    if( EQUAL(pszCap, ODsCCreateLayer) )
+    {
+        return eAccess == GA_Update && nBands == 0 &&
+               (eMultipleLayerBehaviour != SINGLE_LAYER || nLayers == 0);
     }
-    int nTmpFormat = IdentifyFormat( poOpenInfo );
-    if( NCDF_FORMAT_NC  == nTmpFormat ||
-        NCDF_FORMAT_NC2  == nTmpFormat ||
-        NCDF_FORMAT_NC4  == nTmpFormat ||
-        NCDF_FORMAT_NC4C  == nTmpFormat )
-        return TRUE;
-    else
-        return FALSE;
-} 
+    return FALSE;
+}
 
 /************************************************************************/
-/*                                Open()                                */
+/*                            GetLayer()                                */
 /************************************************************************/
 
-GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
-    
+OGRLayer* netCDFDataset::GetLayer(int nIdx)
 {
-    int          j;
-    unsigned int k;
-    int          nd;
-    int          cdfid, dim_count, var, var_count;
-    int          i = 0;
-    size_t       lev_count;
-    size_t       nTotLevCount = 1;
-    int          nDim = 2;
-    int          status;
-    int          nDimID;
-    char         szConventions[NC_MAX_NAME];
-    int          ndims, nvars, ngatts, unlimdimid;
-    int          nCount=0;
-    int          nVarID=-1;
-
-    int          nTmpFormat=NCDF_FORMAT_NONE;
-    int          *panBandDimPos=NULL;         // X, Y, Z postion in array
-    int          *panBandZLev=NULL;
-    int          *paDimIds=NULL;
-    size_t       xdim, ydim;
-    char         szTemp[NC_MAX_NAME+1];
-
-    CPLString    osSubdatasetName;
-    int          bTreatAsSubdataset;
-
-    char         **papszIgnoreVars = NULL;
-    char         *pszTemp = NULL;
-    int          nIgnoredVars = 0;
-
-    char         szDimName[NC_MAX_NAME+1];
-    char         szExtraDimNames[NC_MAX_NAME];
-    char         szExtraDimDef[NC_MAX_NAME];
-    nc_type      nType=NC_NAT;
+    if( nIdx < 0 || nIdx >= nLayers )
+        return NULL;
+    return papoLayers[nIdx];
+}
 
-#ifdef NCDF_DEBUG
-    CPLDebug( "GDAL_netCDF", "\n=====\nOpen(), filename=[%s]", poOpenInfo->pszFilename );
-#endif
+/************************************************************************/
+/*                            ICreateLayer()                            */
+/************************************************************************/
 
-/* -------------------------------------------------------------------- */
-/*      Does this appear to be a netcdf file?                           */
-/* -------------------------------------------------------------------- */
-    if( ! EQUALN(poOpenInfo->pszFilename,"NETCDF:",7) ) {
-        nTmpFormat = IdentifyFormat( poOpenInfo );
-#ifdef NCDF_DEBUG
-    CPLDebug( "GDAL_netCDF", "identified format %d", nTmpFormat );
-#endif
-        /* Note: not calling Identify() directly, because we want the file type */
-        /* Only support NCDF_FORMAT* formats */
-        if( ! ( NCDF_FORMAT_NC  == nTmpFormat ||
-                NCDF_FORMAT_NC2  == nTmpFormat ||
-                NCDF_FORMAT_NC4  == nTmpFormat ||
-                NCDF_FORMAT_NC4C  == nTmpFormat ) )
+OGRLayer* netCDFDataset::ICreateLayer( const char *pszName,
+                                       OGRSpatialReference *poSpatialRef,
+                                       OGRwkbGeometryType eGType,
+                                       char ** papszOptions )
+{
+    int nLayerCDFId = cdfid;
+    if( !TestCapability(ODsCCreateLayer) )
+        return NULL;
+
+    CPLString osNetCDFLayerName(pszName);
+    const netCDFWriterConfigLayer* poLayerConfig = NULL;
+    if( oWriterConfig.m_bIsValid )
+    {
+        std::map<CPLString, netCDFWriterConfigLayer>::const_iterator oLayerIter =
+                                        oWriterConfig.m_oLayers.find(pszName);
+        if( oLayerIter != oWriterConfig.m_oLayers.end() )
+        {
+            poLayerConfig = &(oLayerIter->second);
+            osNetCDFLayerName = poLayerConfig->m_osNetCDFName;
+        }
+    }
+
+    netCDFDataset* poLayerDataset = NULL;
+    if( eMultipleLayerBehaviour == SEPARATE_FILES )
+    {
+        char** papszDatasetOptions = NULL;
+        papszDatasetOptions = CSLSetNameValue(papszDatasetOptions, "CONFIG_FILE",
+                                       CSLFetchNameValue(papszCreationOptions, "CONFIG_FILE"));
+        papszDatasetOptions = CSLSetNameValue(papszDatasetOptions, "FORMAT",
+                                       CSLFetchNameValue(papszCreationOptions, "FORMAT"));
+        papszDatasetOptions = CSLSetNameValue(papszDatasetOptions, "WRITE_GDAL_TAGS",
+                                       CSLFetchNameValue(papszCreationOptions, "WRITE_GDAL_TAGS"));
+        CPLString osLayerFilename(CPLFormFilename( osFilename, osNetCDFLayerName, "nc" ));
+        CPLAcquireMutex(hNCMutex, 1000.0);
+        poLayerDataset = CreateLL( osLayerFilename, 0, 0, 0, papszDatasetOptions );
+        CPLReleaseMutex(hNCMutex);
+        CSLDestroy(papszDatasetOptions);
+        if( poLayerDataset == NULL )
             return NULL;
+
+        nLayerCDFId = poLayerDataset->cdfid;
+        NCDFAddGDALHistory( nLayerCDFId, osLayerFilename, "", "Create",
+                            NCDF_CONVENTIONS_CF_V1_6 );
     }
+#ifdef NETCDF_HAS_NC4
+    else if( eMultipleLayerBehaviour == SEPARATE_GROUPS )
+    {
+        SetDefineMode(true);
 
-    CPLMutexHolderD(&hNCMutex);
+        nLayerCDFId = -1;
+        int status = nc_def_grp (cdfid, osNetCDFLayerName, &nLayerCDFId);
+        NCDF_ERR(status);
+        if( status != NC_NOERR )
+            return NULL;
 
-    netCDFDataset 	*poDS;
-    CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
-    poDS = new netCDFDataset();
-    CPLAcquireMutex(hNCMutex, 1000.0);
+        NCDFAddGDALHistory( nLayerCDFId, osFilename, "", "Create",
+                            NCDF_CONVENTIONS_CF_V1_6 );
+    }
+#endif
 
-    poDS->SetDescription( poOpenInfo->pszFilename );
-    
-/* -------------------------------------------------------------------- */
-/*       Check if filename start with NETCDF: tag                       */
-/* -------------------------------------------------------------------- */
-    if( EQUALN( poOpenInfo->pszFilename,"NETCDF:",7) )
+    /* Make a clone to workaround a bug in released MapServer versions */
+    /* that destroys the passed SRS instead of releasing it */
+    OGRSpatialReference* poSRS = poSpatialRef;
+    if( poSRS != NULL )
+        poSRS = poSRS->Clone();
+    netCDFLayer* poLayer = new netCDFLayer( poLayerDataset ? poLayerDataset : this,
+                                            nLayerCDFId,
+                                            osNetCDFLayerName, eGType, poSRS );
+    if( poSRS != NULL )
+        poSRS->Release();
+
+    // Fetch layer creation options coming from config file
+    char** papszNewOptions = CSLDuplicate(papszOptions);
+    if( oWriterConfig.m_bIsValid )
     {
-        char **papszName =
-            CSLTokenizeString2( poOpenInfo->pszFilename,
-                                ":", CSLT_HONOURSTRINGS|CSLT_PRESERVEESCAPES );
-        
-        /* -------------------------------------------------------------------- */
-        /*    Check for drive name in windows NETCDF:"D:\...                    */
-        /* -------------------------------------------------------------------- */
-        if ( CSLCount(papszName) == 4 &&
-             strlen(papszName[1]) == 1 &&
-             (papszName[2][0] == '/' || papszName[2][0] == '\\') )
+        std::map<CPLString, CPLString>::const_iterator oIter;
+        for( oIter = oWriterConfig.m_oLayerCreationOptions.begin();
+             oIter != oWriterConfig.m_oLayerCreationOptions.end(); ++oIter )
         {
-            poDS->osFilename = papszName[1];
-            poDS->osFilename += ':';
-            poDS->osFilename += papszName[2];
-            osSubdatasetName = papszName[3];
-            bTreatAsSubdataset = TRUE;
-            CSLDestroy( papszName );
+            papszNewOptions = CSLSetNameValue(papszNewOptions, oIter->first, oIter->second);
         }
-        else if( CSLCount(papszName) == 3 )
+        if( poLayerConfig != NULL )
         {
-            poDS->osFilename = papszName[1];
-            osSubdatasetName = papszName[2];
-            bTreatAsSubdataset = TRUE;
-            CSLDestroy( papszName );
+            for( oIter = poLayerConfig->m_oLayerCreationOptions.begin();
+                 oIter != poLayerConfig->m_oLayerCreationOptions.end(); ++oIter )
+            {
+                papszNewOptions = CSLSetNameValue(papszNewOptions, oIter->first, oIter->second);
+            }
+        }
+    }
+
+    const bool bRet = poLayer->Create(papszNewOptions, poLayerConfig);
+    CSLDestroy(papszNewOptions);
+
+    if( !bRet )
+    {
+        delete poLayer;
+        return NULL;
+    }
+
+    if( poLayerDataset != NULL )
+        apoVectorDatasets.push_back(poLayerDataset);
+
+    papoLayers = static_cast<netCDFLayer**>(CPLRealloc(papoLayers, (nLayers + 1) * sizeof(netCDFLayer*)));
+    papoLayers[nLayers++] = poLayer;
+    return poLayer;
+}
+
+/************************************************************************/
+/*                           CloneAttributes()                          */
+/************************************************************************/
+
+bool netCDFDataset::CloneAttributes(int old_cdfid, int new_cdfid, int nSrcVarId, int nDstVarId)
+{
+    int nAttCount = -1;
+    int status = nc_inq_varnatts( old_cdfid, nSrcVarId, &nAttCount);
+    NCDF_ERR(status);
+
+    for( int i=0; i < nAttCount; i++ )
+    {
+        char szName[ NC_MAX_NAME + 1 ];
+        szName[0] = 0;
+        status = nc_inq_attname(old_cdfid, nSrcVarId, i, szName);
+        NCDF_ERR(status);
+
+        status = nc_copy_att(old_cdfid, nSrcVarId, szName, new_cdfid, nDstVarId);
+        NCDF_ERR(status);
+        if( status != NC_NOERR )
+            return false;
+    }
+
+    return true;
+}
+
+/************************************************************************/
+/*                          CloneVariableContent()                      */
+/************************************************************************/
+
+bool netCDFDataset::CloneVariableContent(int old_cdfid, int new_cdfid, int nSrcVarId, int nDstVarId)
+{
+    int nVarDimCount = -1;
+    int status = nc_inq_varndims( old_cdfid, nSrcVarId, &nVarDimCount );
+    NCDF_ERR(status);
+    int anDimIds[] = { -1, 1 };
+    status = nc_inq_vardimid( old_cdfid, nSrcVarId, anDimIds );
+    NCDF_ERR(status);
+    nc_type nc_datatype = NC_NAT;
+    status = nc_inq_vartype( old_cdfid, nSrcVarId, &nc_datatype );
+    NCDF_ERR(status);
+    size_t nTypeSize = 0;
+    switch (nc_datatype)
+    {
+        case NC_BYTE:
+        case NC_CHAR:
+            nTypeSize = 1;
+            break;
+        case NC_SHORT:
+            nTypeSize = 2;
+            break;
+        case NC_INT:
+            nTypeSize = 4;
+            break;
+        case NC_FLOAT:
+            nTypeSize = 4;
+            break;
+        case NC_DOUBLE:
+            nTypeSize = 8;
+            break;
+#ifdef NETCDF_HAS_NC4
+        case NC_UBYTE:
+            nTypeSize = 1;
+            break;
+        case NC_USHORT:
+            nTypeSize = 2;
+            break;
+        case NC_UINT:
+            nTypeSize = 4;
+            break;
+        case NC_INT64:
+        case NC_UINT64:
+            nTypeSize = 8;
+            break;
+        case NC_STRING:
+            nTypeSize = sizeof(char*);
+            break;
+#endif
+        default:
+        {
+            CPLError(CE_Failure, CPLE_NotSupported, "Unsupported data type: %d",
+                     nc_datatype);
+            return false;
+        }
+    }
+
+    size_t nElems = 1;
+    size_t anStart[NC_MAX_DIMS];
+    size_t anCount[NC_MAX_DIMS];
+    size_t nRecords = 1;
+    for( int i=0; i < nVarDimCount; i++)
+    {
+        anStart[i] = 0;
+        if( i == 0 )
+        {
+            anCount[i] = 1;
+            status = nc_inq_dimlen(old_cdfid, anDimIds[i], &nRecords);
+            NCDF_ERR(status);
+        }
+        else
+        {
+            anCount[i] = 0;
+            status = nc_inq_dimlen(old_cdfid, anDimIds[i], &anCount[i]);
+            NCDF_ERR(status);
+            nElems *= anCount[i];
+        }
+    }
+
+    void* pBuffer = VSI_MALLOC2_VERBOSE( nElems, nTypeSize );
+    if( pBuffer == NULL )
+        return false;
+
+    for(size_t iRecord = 0; iRecord < nRecords; iRecord ++ )
+    {
+        anStart[0] = iRecord;
+
+        switch (nc_datatype)
+        {
+            case NC_BYTE:
+                status = nc_get_vara_schar(old_cdfid, nSrcVarId, anStart, anCount,
+                                            (signed char *)pBuffer);
+                if (!status)
+                    status = nc_put_vara_schar(new_cdfid, nDstVarId, anStart, anCount,
+                                                (const signed char *)pBuffer);
+                break;
+            case NC_CHAR:
+                status = nc_get_vara_text(old_cdfid, nSrcVarId, anStart, anCount,
+                                            (char *)pBuffer);
+                if (!status)
+                    status = nc_put_vara_text(new_cdfid, nDstVarId, anStart, anCount,
+                                                (char *)pBuffer);
+                break;
+            case NC_SHORT:
+                status = nc_get_vara_short(old_cdfid, nSrcVarId, anStart, anCount,
+                                            (short *)pBuffer);
+                if (!status)
+                    status = nc_put_vara_short(new_cdfid, nDstVarId, anStart, anCount,
+                                                (short *)pBuffer);
+                break;
+            case NC_INT:
+                status = nc_get_vara_int(old_cdfid, nSrcVarId, anStart, anCount,
+                                            (int *)pBuffer);
+                if (!status)
+                    status = nc_put_vara_int(new_cdfid, nDstVarId, anStart, anCount,
+                                            (int *)pBuffer);
+                break;
+            case NC_FLOAT:
+                status = nc_get_vara_float(old_cdfid, nSrcVarId, anStart, anCount,
+                                            (float *)pBuffer);
+                if (!status)
+                    status = nc_put_vara_float(new_cdfid, nDstVarId, anStart, anCount,
+                                                (float *)pBuffer);
+                break;
+            case NC_DOUBLE:
+                status = nc_get_vara_double(old_cdfid, nSrcVarId, anStart, anCount,
+                                            (double *)pBuffer);
+                if (!status)
+                    status = nc_put_vara_double(new_cdfid, nDstVarId, anStart, anCount,
+                                                (double *)pBuffer);
+            break;
+#ifdef NETCDF_HAS_NC4
+            case NC_STRING:
+                status = nc_get_vara_string( old_cdfid, nSrcVarId, anStart, anCount,
+                                             (char**) pBuffer );
+                if( !status )
+                {
+                    status = nc_put_vara_string( new_cdfid, nDstVarId, anStart, anCount,
+                                                 (const char**) pBuffer );
+                    nc_free_string(nElems, (char**) pBuffer);
+                }
+                break;
+
+            case NC_UBYTE:
+                status = nc_get_vara_uchar(old_cdfid, nSrcVarId, anStart, anCount,
+                                            (unsigned char *)pBuffer);
+                if (!status)
+                    status = nc_put_vara_uchar(new_cdfid, nDstVarId, anStart, anCount,
+                                                (unsigned char *)pBuffer);
+                break;
+            case NC_USHORT:
+                status = nc_get_vara_ushort(old_cdfid, nSrcVarId, anStart, anCount,
+                                            (unsigned short *)pBuffer);
+                if (!status)
+                    status = nc_put_vara_ushort(new_cdfid, nDstVarId, anStart, anCount,
+                                                (unsigned short *)pBuffer);
+                break;
+            case NC_UINT:
+                status = nc_get_vara_uint(old_cdfid, nSrcVarId, anStart, anCount,
+                                            (unsigned int *)pBuffer);
+                if (!status)
+                    status = nc_put_vara_uint(new_cdfid, nDstVarId, anStart, anCount,
+                                                (unsigned int *)pBuffer);
+                break;
+            case NC_INT64:
+                status = nc_get_vara_longlong(old_cdfid, nSrcVarId, anStart, anCount,
+                                                (long long *)pBuffer);
+                if (!status)
+                    status = nc_put_vara_longlong(new_cdfid, nDstVarId, anStart, anCount,
+                                                    (long long *)pBuffer);
+                break;
+            case NC_UINT64:
+                status = nc_get_vara_ulonglong(old_cdfid, nSrcVarId, anStart, anCount,
+                                                (unsigned long long *)pBuffer);
+                if (!status)
+                    status = nc_put_vara_ulonglong(new_cdfid, nDstVarId, anStart, anCount,
+                                                    (unsigned long long *)pBuffer);
+                break;
+#endif
+            default:
+                status = NC_EBADTYPE;
+        }
+
+        NCDF_ERR(status);
+        if( status != NC_NOERR )
+        {
+            VSIFree(pBuffer);
+            return false;
+        }
+    }
+
+    VSIFree(pBuffer);
+    return true;
+}
+
+/************************************************************************/
+/*                         NCDFIsUnlimitedDim()                         */
+/************************************************************************/
+
+bool NCDFIsUnlimitedDim(bool
+#ifdef NETCDF_HAS_NC4
+                                            bIsNC4
+#endif
+                            , int cdfid, int nDimId)
+{
+#ifdef NETCDF_HAS_NC4
+    if( bIsNC4 )
+    {
+        int nUnlimitedDims = 0;
+        nc_inq_unlimdims( cdfid, &nUnlimitedDims, NULL );
+        bool bFound = false;
+        if( nUnlimitedDims )
+        {
+            int* panUnlimitedDimIds = static_cast<int*>(CPLMalloc(sizeof(int) * nUnlimitedDims));
+            nc_inq_unlimdims( cdfid, NULL, panUnlimitedDimIds );
+            for(int i=0;i<nUnlimitedDims;i++)
+            {
+                if( panUnlimitedDimIds[i] == nDimId )
+                {
+                    bFound = true;
+                    break;
+                }
+            }
+            CPLFree(panUnlimitedDimIds);
+        }
+        return bFound;
+    }
+    else
+#endif
+    {
+        int nUnlimitedDimId = -1;
+        nc_inq(cdfid, NULL, NULL, NULL, &nUnlimitedDimId);
+        return nDimId == nUnlimitedDimId;
+    }
+}
+
+/************************************************************************/
+/*                              CloneGrp()                              */
+/************************************************************************/
+
+bool netCDFDataset::CloneGrp(int nOldGrpId, int nNewGrpId,
+                             bool bIsNC4, int nLayerId,
+                             int nDimIdToGrow, size_t nNewSize)
+{
+    // Clone dimensions
+    int nDimCount = -1;
+    int status = nc_inq_ndims( nOldGrpId, &nDimCount );
+    NCDF_ERR(status)
+    int* panDimIds = static_cast<int*>(CPLMalloc(sizeof(int) * nDimCount));
+    int nUnlimiDimID = -1;
+    status = nc_inq_unlimdim (nOldGrpId, &nUnlimiDimID);
+    NCDF_ERR(status);
+#ifdef NETCDF_HAS_NC4
+    if( bIsNC4 )
+    {
+        // In NC4, the dimension ids of a group are not necessarily in [0,nDimCount-1] range
+        int nDimCount2 = -1;
+        status = nc_inq_dimids(nOldGrpId, &nDimCount2, panDimIds, FALSE);
+        NCDF_ERR(status);
+        CPLAssert(nDimCount == nDimCount2);
+    }
+    else
+#endif
+    {
+        for( int i=0; i < nDimCount; i++ )
+            panDimIds[i] = i;
+    }
+    for( int i=0; i < nDimCount; i++ )
+    {
+        char szDimName[ NC_MAX_NAME + 1 ];
+        szDimName[0] = 0;
+        size_t nLen = 0;
+        const int nDimId = panDimIds[i];
+        status = nc_inq_dim (nOldGrpId, nDimId, szDimName, &nLen);
+        NCDF_ERR(status);
+        if( NCDFIsUnlimitedDim(bIsNC4, nOldGrpId, nDimId) )
+            nLen = NC_UNLIMITED;
+        else if( nDimId == nDimIdToGrow && nOldGrpId == nLayerId )
+            nLen = nNewSize;
+        int nNewDimId = -1;
+        status = nc_def_dim (nNewGrpId, szDimName, nLen, &nNewDimId);
+        NCDF_ERR(status);
+        CPLAssert( nDimId == nNewDimId );
+        if( status != NC_NOERR )
+        {
+            CPLFree(panDimIds);
+            return false;
+        }
+    }
+    CPLFree(panDimIds);
+
+    // Clone main attributes
+    if( !CloneAttributes(nOldGrpId, nNewGrpId, NC_GLOBAL, NC_GLOBAL) )
+    {
+        return false;
+    }
+
+    // Clone variable definitions
+    int nVarCount = -1;
+    status = nc_inq_nvars(nOldGrpId, &nVarCount);
+    NCDF_ERR(status);
+
+    for( int i=0; i < nVarCount; i++ )
+    {
+        char szVarName[ NC_MAX_NAME + 1 ];
+        szVarName[0] = 0;
+        status = nc_inq_varname( nOldGrpId, i, szVarName );
+        NCDF_ERR(status);
+        nc_type nc_datatype = NC_NAT;
+        status = nc_inq_vartype( nOldGrpId, i, &nc_datatype );
+        NCDF_ERR(status);
+        int nVarDimCount = -1;
+        status = nc_inq_varndims( nOldGrpId, i, &nVarDimCount );
+        NCDF_ERR(status);
+        int anDimIds[NC_MAX_DIMS];
+        status = nc_inq_vardimid( nOldGrpId, i, anDimIds );
+        NCDF_ERR(status);
+        int nNewVarId = -1;
+        status = nc_def_var( nNewGrpId, szVarName, nc_datatype,
+                             nVarDimCount, anDimIds, &nNewVarId );
+        NCDF_ERR(status);
+        CPLAssert( i == nNewVarId );
+        if( status != NC_NOERR )
+        {
+            return false;
+        }
+
+        if( !CloneAttributes(nOldGrpId, nNewGrpId, i, i) )
+        {
+            return false;
+        }
+    }
+
+    status = nc_enddef( nNewGrpId );
+    NCDF_ERR(status);
+    if( status != NC_NOERR )
+    {
+        return false;
+    }
+
+    // Clone variable content
+    for( int i=0; i < nVarCount; i++ )
+    {
+        if( !CloneVariableContent(nOldGrpId, nNewGrpId, i, i) )
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+/************************************************************************/
+/*                              GrowDim()                               */
+/************************************************************************/
+
+bool netCDFDataset::GrowDim(int nLayerId, int nDimIdToGrow, size_t nNewSize)
+{
+    int nCreationMode;
+    /* set nCreationMode based on eFormat */
+    switch ( eFormat ) {
+#ifdef NETCDF_HAS_NC2
+        case NCDF_FORMAT_NC2:
+            nCreationMode = NC_CLOBBER|NC_64BIT_OFFSET;
+            break;
+#endif
+#ifdef NETCDF_HAS_NC4
+        case NCDF_FORMAT_NC4:
+            nCreationMode = NC_CLOBBER|NC_NETCDF4;
+            break;
+        case NCDF_FORMAT_NC4C:
+            nCreationMode = NC_CLOBBER|NC_NETCDF4|NC_CLASSIC_MODEL;
+            break;
+#endif
+        case NCDF_FORMAT_NC:
+        default:
+            nCreationMode = NC_CLOBBER;
+            break;
+    }
+
+    int new_cdfid = -1;
+    CPLString osTmpFilename( osFilename + ".tmp" );
+    int status = nc_create( osTmpFilename, nCreationMode, &new_cdfid );
+    NCDF_ERR(status)
+    if( status != NC_NOERR )
+        return false;
+
+    if( !CloneGrp(cdfid, new_cdfid,
+                  eFormat == NCDF_FORMAT_NC4,
+                  nLayerId, nDimIdToGrow, nNewSize) )
+    {
+        nc_close(new_cdfid);
+        return false;
+    }
+
+#ifdef NETCDF_HAS_NC4
+    int nGroupCount = 0;
+    std::vector<CPLString> oListGrpName;
+    if( eFormat == NCDF_FORMAT_NC4 &&
+        nc_inq_grps(cdfid, &nGroupCount, NULL) == NC_NOERR &&
+        nGroupCount > 0 )
+    {
+        int* panGroupIds = static_cast<int*>(CPLMalloc(sizeof(int) * nGroupCount));
+        status = nc_inq_grps(cdfid, NULL, panGroupIds);
+        NCDF_ERR(status)
+        for(int i=0;i<nGroupCount;i++)
+        {
+            char szGroupName[NC_MAX_NAME + 1];
+            szGroupName[0] = 0;
+            nc_inq_grpname(panGroupIds[i], szGroupName);
+            int nNewGrpId = -1;
+            status = nc_def_grp(new_cdfid, szGroupName, &nNewGrpId);
+            NCDF_ERR(status)
+            if( status != NC_NOERR )
+            {
+                CPLFree(panGroupIds);
+                nc_close(new_cdfid);
+                return false;
+            }
+            if( !CloneGrp(panGroupIds[i], nNewGrpId,
+                          eFormat == NCDF_FORMAT_NC4,
+                          nLayerId, nDimIdToGrow, nNewSize) )
+            {
+                CPLFree(panGroupIds);
+                nc_close(new_cdfid);
+                return false;
+            }
+        }
+        CPLFree(panGroupIds);
+
+        for(int i=0;i<nLayers;i++)
+        {
+            char szGroupName[NC_MAX_NAME + 1];
+            szGroupName[0] = 0;
+            status = nc_inq_grpname(papoLayers[i]->GetCDFID(), szGroupName);
+            NCDF_ERR(status)
+            oListGrpName.push_back(szGroupName);
+        }
+    }
+#endif
+
+    nc_close(cdfid);
+    cdfid = -1;
+    nc_close(new_cdfid);
+
+    CPLString osOriFilename( osFilename + ".ori" );
+    if( VSIRename( osFilename, osOriFilename ) != 0 ||
+        VSIRename( osTmpFilename, osFilename ) != 0 )
+    {
+        CPLError(CE_Failure, CPLE_FileIO, "Renaming of files failed");
+        return false;
+    }
+    VSIUnlink( osOriFilename );
+
+    status = nc_open( osFilename, NC_WRITE, &cdfid );
+    NCDF_ERR(status);
+    if( status != NC_NOERR )
+        return false;
+    bDefineMode = false;
+
+#ifdef NETCDF_HAS_NC4
+    if( oListGrpName.size() )
+    {
+        for(int i=0;i<nLayers;i++)
+        {
+            int nNewLayerCDFID = -1;
+            status = nc_inq_ncid(cdfid, oListGrpName[i].c_str(), &nNewLayerCDFID);
+            NCDF_ERR(status);
+            papoLayers[i]->SetCDFID( nNewLayerCDFID );
+        }
+    }
+    else
+#endif
+    {
+        for(int i=0;i<nLayers;i++)
+        {
+            papoLayers[i]->SetCDFID( cdfid );
+        }
+    }
+
+    return true;
+}
+
+/************************************************************************/
+/*                              Identify()                              */
+/************************************************************************/
+
+int netCDFDataset::Identify( GDALOpenInfo * poOpenInfo )
+
+{
+    if( STARTS_WITH_CI(poOpenInfo->pszFilename, "NETCDF:") ) {
+        return TRUE;
+    }
+    const NetCDFFormatEnum eTmpFormat = IdentifyFormat( poOpenInfo );
+    if( NCDF_FORMAT_NC == eTmpFormat ||
+        NCDF_FORMAT_NC2 == eTmpFormat ||
+        NCDF_FORMAT_NC4 == eTmpFormat ||
+        NCDF_FORMAT_NC4C == eTmpFormat )
+        return TRUE;
+
+    return FALSE;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
+
+{
+#ifdef NCDF_DEBUG
+    CPLDebug( "GDAL_netCDF", "\n=====\nOpen(), filename=[%s]", poOpenInfo->pszFilename );
+#endif
+
+/* -------------------------------------------------------------------- */
+/*      Does this appear to be a netcdf file?                           */
+/* -------------------------------------------------------------------- */
+    NetCDFFormatEnum eTmpFormat = NCDF_FORMAT_NONE;
+    if( ! STARTS_WITH_CI(poOpenInfo->pszFilename, "NETCDF:") ) {
+        eTmpFormat = IdentifyFormat( poOpenInfo );
+#ifdef NCDF_DEBUG
+    CPLDebug( "GDAL_netCDF", "identified format %d", eTmpFormat );
+#endif
+        /* Note: not calling Identify() directly, because we want the file type */
+        /* Only support NCDF_FORMAT* formats */
+        if( ! ( NCDF_FORMAT_NC  == eTmpFormat ||
+                NCDF_FORMAT_NC2  == eTmpFormat ||
+                NCDF_FORMAT_NC4  == eTmpFormat ||
+                NCDF_FORMAT_NC4C  == eTmpFormat ) )
+            return NULL;
+    }
+
+    CPLMutexHolderD(&hNCMutex);
+
+    CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+    netCDFDataset *poDS = new netCDFDataset();
+    CPLAcquireMutex(hNCMutex, 1000.0);
+
+    poDS->SetDescription( poOpenInfo->pszFilename );
+
+/* -------------------------------------------------------------------- */
+/*       Check if filename start with NETCDF: tag                       */
+/* -------------------------------------------------------------------- */
+    bool bTreatAsSubdataset = false;
+    CPLString osSubdatasetName;
+
+    if( STARTS_WITH_CI(poOpenInfo->pszFilename, "NETCDF:") )
+    {
+        char **papszName =
+            CSLTokenizeString2( poOpenInfo->pszFilename,
+                                ":", CSLT_HONOURSTRINGS|CSLT_PRESERVEESCAPES );
+
+        /* -------------------------------------------------------------------- */
+        /*    Check for drive name in windows NETCDF:"D:\...                    */
+        /* -------------------------------------------------------------------- */
+        if ( CSLCount(papszName) == 4 &&
+             strlen(papszName[1]) == 1 &&
+             (papszName[2][0] == '/' || papszName[2][0] == '\\') )
+        {
+            poDS->osFilename = papszName[1];
+            poDS->osFilename += ':';
+            poDS->osFilename += papszName[2];
+            osSubdatasetName = papszName[3];
+            bTreatAsSubdataset = true;
+            CSLDestroy( papszName );
+        }
+        else if( CSLCount(papszName) == 3 )
+        {
+            poDS->osFilename = papszName[1];
+            osSubdatasetName = papszName[2];
+            bTreatAsSubdataset = true;
+            CSLDestroy( papszName );
     	}
         else if( CSLCount(papszName) == 2 )
         {
             poDS->osFilename = papszName[1];
             osSubdatasetName = "";
-            bTreatAsSubdataset = FALSE;
+            bTreatAsSubdataset = false;
             CSLDestroy( papszName );
     	}
         else
@@ -4473,23 +5375,23 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
                       "Failed to parse NETCDF: prefix string into expected 2, 3 or 4 fields." );
             return NULL;
         }
-        /* Identify Format from real file, with bCheckExt=FALSE */ 
+        /* Identify Format from real file, with bCheckExt=FALSE */
         GDALOpenInfo* poOpenInfo2 = new GDALOpenInfo(poDS->osFilename.c_str(), GA_ReadOnly );
-        poDS->nFormat = IdentifyFormat( poOpenInfo2, FALSE );
+        poDS->eFormat = IdentifyFormat( poOpenInfo2, FALSE );
         delete poOpenInfo2;
-        if( NCDF_FORMAT_NONE == poDS->nFormat ||
-            NCDF_FORMAT_UNKNOWN == poDS->nFormat ) {
+        if( NCDF_FORMAT_NONE == poDS->eFormat ||
+            NCDF_FORMAT_UNKNOWN == poDS->eFormat ) {
             CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
             delete poDS;
             CPLAcquireMutex(hNCMutex, 1000.0);
             return NULL;
-        }        
+        }
     }
-    else 
+    else
     {
         poDS->osFilename = poOpenInfo->pszFilename;
-        bTreatAsSubdataset = FALSE;
-        poDS->nFormat = nTmpFormat;
+        bTreatAsSubdataset = false;
+        poDS->eFormat = eTmpFormat;
     }
 
 /* -------------------------------------------------------------------- */
@@ -4498,7 +5400,10 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
 #ifdef NCDF_DEBUG
     CPLDebug( "GDAL_netCDF", "calling nc_open( %s )", poDS->osFilename.c_str() );
 #endif
-    if( nc_open( poDS->osFilename, NC_NOWRITE, &cdfid ) != NC_NOERR ) {
+    int cdfid;
+    const int nMode = ((poOpenInfo->nOpenFlags & (GDAL_OF_UPDATE | GDAL_OF_VECTOR)) ==
+                (GDAL_OF_UPDATE | GDAL_OF_VECTOR)) ? NC_WRITE : NC_NOWRITE;
+    if( nc_open( poDS->osFilename, nMode, &cdfid ) != NC_NOERR ) {
 #ifdef NCDF_DEBUG
         CPLDebug( "GDAL_netCDF", "error opening" );
 #endif
@@ -4514,45 +5419,50 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Is this a real netCDF file?                                     */
 /* -------------------------------------------------------------------- */
-    status = nc_inq(cdfid, &ndims, &nvars, &ngatts, &unlimdimid);
+    int ndims;
+    int ngatts;
+    int nvars;
+    int unlimdimid;
+    int status = nc_inq(cdfid, &ndims, &nvars, &ngatts, &unlimdimid);
     if( status != NC_NOERR ) {
         CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
         delete poDS;
         CPLAcquireMutex(hNCMutex, 1000.0);
         return NULL;
-    }   
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Get file type from netcdf                                       */
 /* -------------------------------------------------------------------- */
+    int nTmpFormat = NCDF_FORMAT_NONE;
     status = nc_inq_format (cdfid, &nTmpFormat);
     if ( status != NC_NOERR ) {
         NCDF_ERR(status);
     }
     else {
-        CPLDebug( "GDAL_netCDF", 
+        CPLDebug( "GDAL_netCDF",
                   "driver detected file type=%d, libnetcdf detected type=%d",
-                  poDS->nFormat, nTmpFormat );
-        if ( nTmpFormat != poDS->nFormat ) {
+                  poDS->eFormat, nTmpFormat );
+        if ( static_cast<NetCDFFormatEnum>(nTmpFormat) != poDS->eFormat ) {
             /* warn if file detection conflicts with that from libnetcdf */
             /* except for NC4C, which we have no way of detecting initially */
             if ( nTmpFormat != NCDF_FORMAT_NC4C ) {
-                CPLError( CE_Warning, CPLE_AppDefined, 
+                CPLError( CE_Warning, CPLE_AppDefined,
                           "NetCDF driver detected file type=%d, but libnetcdf detected type=%d",
-                          poDS->nFormat, nTmpFormat );
+                          poDS->eFormat, nTmpFormat );
             }
-            CPLDebug( "GDAL_netCDF", "seting file type to %d, was %d", 
-                      nTmpFormat, poDS->nFormat );
-            poDS->nFormat = nTmpFormat;
+            CPLDebug( "GDAL_netCDF", "setting file type to %d, was %d",
+                      nTmpFormat, poDS->eFormat );
+            poDS->eFormat = static_cast<NetCDFFormatEnum>(nTmpFormat);
         }
     }
 
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
-    if( poOpenInfo->eAccess == GA_Update )
+    if( poOpenInfo->eAccess == GA_Update && (poOpenInfo->nOpenFlags & GDAL_OF_VECTOR) == 0 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The NETCDF driver does not support update access to existing"
                   " datasets.\n" );
         nc_close( cdfid );
@@ -4561,19 +5471,20 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
         CPLAcquireMutex(hNCMutex, 1000.0);
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Does the request variable exist?                                */
 /* -------------------------------------------------------------------- */
     if( bTreatAsSubdataset )
     {
+        int var;
         status = nc_inq_varid( cdfid, osSubdatasetName, &var);
         if( status != NC_NOERR ) {
-            CPLError( CE_Warning, CPLE_AppDefined, 
+            CPLError( CE_Warning, CPLE_AppDefined,
                       "%s is a netCDF file, but %s is not a variable.",
-                      poOpenInfo->pszFilename, 
+                      poOpenInfo->pszFilename,
                       osSubdatasetName.c_str() );
-            
+
             nc_close( cdfid );
             CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
             delete poDS;
@@ -4582,10 +5493,10 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
         }
     }
 
-    if( nc_inq_ndims( cdfid, &dim_count ) != NC_NOERR || dim_count < 2 )
+    if( ndims < 2 && (poOpenInfo->nOpenFlags & GDAL_OF_VECTOR) == 0 )
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
-                  "%s is a netCDF file, but not in GMT configuration.",
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "%s is a netCDF file, but without any dimensions >= 2.",
                   poOpenInfo->pszFilename );
 
         nc_close( cdfid );
@@ -4595,8 +5506,9 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    CPLDebug( "GDAL_netCDF", "dim_count = %d", dim_count );
+    CPLDebug( "GDAL_netCDF", "dim_count = %d", ndims );
 
+    char szConventions[NC_MAX_NAME+1];
     szConventions[0] = '\0';
     nc_type nAttype=NC_NAT;
     size_t nAttlen = 0;
@@ -4604,7 +5516,7 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
     if( nAttlen >= sizeof(szConventions) ||
         (status = nc_get_att_text( cdfid, NC_GLOBAL, "Conventions",
                                    szConventions )) != NC_NOERR ) {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "No UNIDATA NC_GLOBAL:Conventions attribute");
         /* note that 'Conventions' is always capital 'C' in CF spec*/
     }
@@ -4613,73 +5525,477 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
         szConventions[nAttlen] = '\0';
     }
 
+
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    if ( nc_inq_nvars ( cdfid, &var_count) != NC_NOERR )
-    {
-        CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
-        delete poDS;
-        CPLAcquireMutex(hNCMutex, 1000.0);
-        return NULL;
-    }    
-    
-    CPLDebug( "GDAL_netCDF", "var_count = %d", var_count );
+    CPLDebug( "GDAL_netCDF", "var_count = %d", nvars );
 
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /*      Create Netcdf Subdataset if filename as NETCDF tag              */
 /* -------------------------------------------------------------------- */
     poDS->cdfid = cdfid;
+    poDS->eAccess = poOpenInfo->eAccess;
+    poDS->bDefineMode = false;
 
-    poDS->ReadAttributes( cdfid, NC_GLOBAL );	
+    poDS->ReadAttributes( cdfid, NC_GLOBAL );
+
+    int nCount = 0;
+    int nVarID = -1;
+    int nIgnoredVars = 0;
+    char *pszTemp = NULL;
+
+    // In vector only mode, if the file is NC4, if the main group has no
+    // variables but there are sub-groups, then iterate over the subgroups to
+    // check if there are vector layers.
+#ifdef NETCDF_HAS_NC4
+    int nGroupCount = 0;
+    int* panGroupIds = NULL;
+    if( nvars == 0 &&
+        poDS->eFormat == NCDF_FORMAT_NC4 &&
+        (poOpenInfo->nOpenFlags & GDAL_OF_RASTER) == 0 &&
+        (poOpenInfo->nOpenFlags & GDAL_OF_VECTOR) != 0 )
+    {
+        nc_inq_grps(cdfid, &nGroupCount, NULL);
+    }
+    if( nGroupCount > 0 )
+    {
+        panGroupIds = static_cast<int*>(CPLMalloc(sizeof(int) * nGroupCount));
+        nc_inq_grps(cdfid, NULL, panGroupIds);
+    }
+    for( int iGrp = 0; iGrp < ((nGroupCount) ? nGroupCount : 1); iGrp ++ )
+    {
+    char szGroupName[NC_MAX_NAME + 1];
+    szGroupName[0] = 0;
+    int iGrpId = (nGroupCount) ? panGroupIds[iGrp] : cdfid;
+    if( nGroupCount )
+    {
+        nc_inq_grpname (iGrpId, szGroupName);
+        ndims = 0;
+        ngatts = 0;
+        nvars = 0;
+        unlimdimid = -1;
+        status = nc_inq(iGrpId, &ndims, &nvars, &ngatts, &unlimdimid);
+        NCDF_ERR(status);
+
+        CSLDestroy(poDS->papszMetadata);
+        poDS->papszMetadata = NULL;
+        poDS->ReadAttributes( cdfid, NC_GLOBAL );
+        poDS->ReadAttributes( iGrpId, NC_GLOBAL );
+
+    }
+    else
+        snprintf( szGroupName, sizeof(szGroupName), "%s", CPLGetBasename(poDS->osFilename) );
+    poDS->cdfid = iGrpId;
+#else
+    char szGroupName[NC_MAX_NAME + 1];
+    snprintf( szGroupName, sizeof(szGroupName), "%s", CPLGetBasename(poDS->osFilename) );
+#endif
+
+/* -------------------------------------------------------------------- */
+/*  Identify variables that we should ignore as Raster Bands.           */
+/*  Variables that are identified in other variable's "coordinate" and  */
+/*  "bounds" attribute should not be treated as Raster Bands.           */
+/*  See CF sections 5.2, 5.6 and 7.1                                    */
+/* -------------------------------------------------------------------- */
+    char **papszIgnoreVars = NULL;
+
+    for ( int j = 0; j < nvars; j++ ) {
+        char **papszTokens = NULL;
+        if ( NCDFGetAttr( poDS->cdfid, j, "coordinates", &pszTemp ) == CE_None ) {
+            papszTokens = CSLTokenizeString2( pszTemp, " ", 0 );
+            for ( int i=0; i<CSLCount(papszTokens); i++ ) {
+                papszIgnoreVars = CSLAddString( papszIgnoreVars, papszTokens[i] );
+            }
+            if ( papszTokens) CSLDestroy( papszTokens );
+            CPLFree( pszTemp );
+        }
+        if ( NCDFGetAttr( poDS->cdfid, j, "bounds", &pszTemp ) == CE_None &&
+             pszTemp != NULL ) {
+            if ( !EQUAL( pszTemp, "" ) )
+                papszIgnoreVars = CSLAddString( papszIgnoreVars, pszTemp );
+            CPLFree( pszTemp );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*  Filter variables (valid 2D raster bands and vector fields)          */
+/* -------------------------------------------------------------------- */
+    nIgnoredVars = 0;
+    std::vector<int> anPotentialVectorVarID;
+    // oMapDimIdToCount[x] = number of times dim x is the first dimension of potential vector variables
+    std::map<int, int> oMapDimIdToCount;
+    int nVarXId = -1;
+    int nVarYId = -1;
+    int nVarZId = -1;
+    bool bIsVectorOnly = true;
+    int nProfileDimId = -1;
+    int nParentIndexVarID = -1;
+
+    for ( int j = 0; j < nvars; j++ ) {
+        int ndimsForVar = -1;
+        char szTemp[NC_MAX_NAME+1];
+        nc_inq_varndims ( poDS->cdfid, j, &ndimsForVar );
+        /* should we ignore this variable ? */
+        szTemp[0] = '\0';
+        status = nc_inq_varname( poDS->cdfid, j, szTemp );
+        if ( status != NC_NOERR )
+            continue;
+
+        nc_type atttype=NC_NAT;
+        size_t attlen = 0;
+
+        if( ndimsForVar == 1 &&
+            (NCDFIsVarLongitude( poDS->cdfid, -1, szTemp) ||
+             NCDFIsVarProjectionX( poDS->cdfid, -1, szTemp)) )
+        {
+            nVarXId = j;
+        }
+        else if( ndimsForVar == 1 &&
+            (NCDFIsVarLatitude( poDS->cdfid, -1, szTemp) ||
+             NCDFIsVarProjectionY( poDS->cdfid, -1, szTemp)) )
+        {
+            nVarYId = j;
+        }
+        else if( ndimsForVar == 1 &&
+            NCDFIsVarVerticalCoord( poDS->cdfid, -1, szTemp) )
+        {
+            nVarZId = j;
+        }
+        else if ( CSLFindString( papszIgnoreVars, szTemp ) != -1 ) {
+            nIgnoredVars++;
+            CPLDebug( "GDAL_netCDF", "variable #%d [%s] was ignored",j, szTemp);
+        }
+        /* only accept 2+D vars */
+        else if( ndimsForVar >= 2 ) {
+
+            // Identify variables that might be vector variables
+            if( ndimsForVar == 2 )
+            {
+                int anDimIds[2] = { -1, -1 };
+                nc_inq_vardimid( poDS->cdfid, j, anDimIds );
+                char szDimNameX[NC_MAX_NAME+1], szDimNameY[NC_MAX_NAME+1];
+                szDimNameX[0]='\0';
+                szDimNameY[0]='\0';
+                if ( nc_inq_dimname( poDS->cdfid, anDimIds[0], szDimNameY ) == NC_NOERR &&
+                     nc_inq_dimname( poDS->cdfid, anDimIds[1], szDimNameX ) == NC_NOERR &&
+                     NCDFIsVarLongitude( poDS->cdfid, -1, szDimNameX )==false &&
+                     NCDFIsVarProjectionX( poDS->cdfid, -1, szDimNameX )==false &&
+                     NCDFIsVarLatitude( poDS->cdfid, -1, szDimNameY )==false &&
+                     NCDFIsVarProjectionY( poDS->cdfid, -1, szDimNameY )==false )
+                {
+                    anPotentialVectorVarID.push_back(j);
+                    oMapDimIdToCount[ anDimIds[0] ] ++;
+                }
+                else
+                    bIsVectorOnly = false;
+            }
+            else
+                bIsVectorOnly = false;
+
+            if( (poOpenInfo->nOpenFlags & GDAL_OF_RASTER) != 0 )
+            {
+                nVarID=j;
+                nCount++;
+            }
+        }
+        else if( ndimsForVar == 1 )
+        {
+            if( nc_inq_att( poDS->cdfid, j, "instance_dimension", &atttype, &attlen) == NC_NOERR &&
+                atttype == NC_CHAR && attlen < NC_MAX_NAME )
+            {
+                char szInstanceDimension[NC_MAX_NAME+1];
+                if( nc_get_att_text ( poDS->cdfid, j, "instance_dimension",
+                                      szInstanceDimension ) == NC_NOERR )
+                {
+                    szInstanceDimension[attlen] = 0;
+                    for(int idim = 0; idim < ndims; idim ++)
+                    {
+                        char szDimName[NC_MAX_NAME+1];
+                        szDimName[0] = 0;
+                        status = nc_inq_dimname( poDS->cdfid, idim, szDimName);
+                        NCDF_ERR(status);
+                        if( strcmp(szInstanceDimension, szDimName) == 0 )
+                        {
+                            nParentIndexVarID = j;
+                            nProfileDimId = idim;
+                            break;
+                        }
+                    }
+                    if( nProfileDimId < 0 )
+                    {
+                        CPLError(CE_Warning, CPLE_AppDefined,
+                                "Attribute instance_dimension='%s' refers to a non existing dimension",
+                                szInstanceDimension);
+                    }
+                }
+            }
+            if( j != nParentIndexVarID )
+            {
+                anPotentialVectorVarID.push_back(j);
+                int nDimId = -1;
+                nc_inq_vardimid( poDS->cdfid, j, &nDimId );
+                oMapDimIdToCount[ nDimId ] ++;
+            }
+        }
+    }
+
+    CSLDestroy( papszIgnoreVars );
+
+    CPLString osFeatureType(
+        CSLFetchNameValueDef(poDS->papszMetadata, "NC_GLOBAL#featureType", ""));
+
+    // If we are opened in raster-only mode and that there are only 1D or 2D
+    // variables and that the 2D variables have no X/Y dim, and all variables
+    // refer to the same main dimension (or 2 dimensions for featureType=profile),
+    // then it is a pure vector dataset
+    if( (poOpenInfo->nOpenFlags & GDAL_OF_RASTER) != 0 &&
+        (poOpenInfo->nOpenFlags & GDAL_OF_VECTOR) == 0 &&
+        bIsVectorOnly && nCount > 0 &&
+        anPotentialVectorVarID.size() != 0 &&
+        (oMapDimIdToCount.size() == 1 ||
+         (EQUAL(osFeatureType, "profile") && oMapDimIdToCount.size() == 2 && nProfileDimId >= 0)) )
+    {
+        anPotentialVectorVarID.resize(0);
+        nCount = 0;
+    }
+
+    if( anPotentialVectorVarID.size() != 0 &&
+        (poOpenInfo->nOpenFlags & GDAL_OF_VECTOR) != 0 )
+    {
+        // Take the dimension that is referenced the most times
+        if( !(oMapDimIdToCount.size() == 1 ||
+              (EQUAL(osFeatureType, "profile") && oMapDimIdToCount.size() == 2 && nProfileDimId >= 0)) )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "The dataset has several variables that could be identified "
+                     "as vector fields, but not all share the same primary dimension. "
+                     "Consequently they will be ignored.");
+        }
+        else
+        {
+            OGRwkbGeometryType eGType = wkbUnknown;
+            CPLString osLayerName = CSLFetchNameValueDef(
+                poDS->papszMetadata, "NC_GLOBAL#ogr_layer_name", szGroupName);
+            poDS->papszMetadata = CSLSetNameValue(poDS->papszMetadata, "NC_GLOBAL#ogr_layer_name", NULL);
+
+            if( EQUAL(osFeatureType, "point") || EQUAL(osFeatureType, "profile") )
+            {
+                poDS->papszMetadata = CSLSetNameValue(poDS->papszMetadata, "NC_GLOBAL#featureType", NULL);
+                eGType = wkbPoint;
+            }
+
+            const char* pszLayerType = CSLFetchNameValue(poDS->papszMetadata, "NC_GLOBAL#ogr_layer_type");
+            if( pszLayerType != NULL )
+            {
+                eGType = OGRFromOGCGeomType(pszLayerType);
+                poDS->papszMetadata = CSLSetNameValue(poDS->papszMetadata, "NC_GLOBAL#ogr_layer_type", NULL);
+            }
+
+            CPLString osGeometryField = CSLFetchNameValueDef(poDS->papszMetadata, "NC_GLOBAL#ogr_geometry_field", "");
+            poDS->papszMetadata = CSLSetNameValue(poDS->papszMetadata, "NC_GLOBAL#ogr_geometry_field", NULL);
+
+            int nFirstVarId = -1;
+            int nVectorDim = oMapDimIdToCount.rbegin()->first;
+            if( EQUAL(osFeatureType, "profile") && oMapDimIdToCount.size() == 2 )
+            {
+                if( nVectorDim == nProfileDimId )
+                    nVectorDim = oMapDimIdToCount.begin()->first;
+            }
+            else
+                nProfileDimId = -1;
+            for( size_t j = 0; j < anPotentialVectorVarID.size(); j++ )
+            {
+                int anDimIds[2] = { -1, -1 };
+                nc_inq_vardimid( poDS->cdfid, anPotentialVectorVarID[j], anDimIds );
+                if( nVectorDim == anDimIds[0] )
+                {
+                    nFirstVarId = anPotentialVectorVarID[j];
+                    break;
+                }
+            }
+
+            // In case where coordinates are explicitly specified for one of the field/variable,
+            // use them in priority over the ones that might have been identified above
+            char* pszCoordinates = NULL;
+            if( NCDFGetAttr( poDS->cdfid, nFirstVarId, "coordinates", &pszCoordinates) == CE_None )
+            {
+                char** papszTokens = CSLTokenizeString2( pszCoordinates, " ", 0 );
+                for ( int i=0; papszTokens != NULL && papszTokens[i] != NULL; i++ )
+                {
+                    if( NCDFIsVarLongitude( poDS->cdfid, -1, papszTokens[i] ) ||
+                        NCDFIsVarProjectionX( poDS->cdfid, -1, papszTokens[i] ) )
+                    {
+                        nVarXId = -1;
+                        CPL_IGNORE_RET_VAL(nc_inq_varid(poDS->cdfid, papszTokens[i], &nVarXId));
+                    }
+                    else if( NCDFIsVarLatitude( poDS->cdfid, -1, papszTokens[i] ) ||
+                             NCDFIsVarProjectionY( poDS->cdfid, -1, papszTokens[i] ) )
+                    {
+                        nVarYId = -1;
+                        CPL_IGNORE_RET_VAL(nc_inq_varid(poDS->cdfid, papszTokens[i], &nVarYId));
+                    }
+                    else if( NCDFIsVarVerticalCoord( poDS->cdfid, -1, papszTokens[i] ) )
+                    {
+                        nVarZId = -1;
+                        CPL_IGNORE_RET_VAL(nc_inq_varid(poDS->cdfid, papszTokens[i], &nVarZId));
+                    }
+                }
+                CSLDestroy(papszTokens);
+            }
+            CPLFree(pszCoordinates);
+
+            // Check that the X,Y,Z vars share 1D and share the same dimension
+            // as attribute variables
+            if( nVarXId >= 0 && nVarYId >= 0 )
+            {
+                int nVarDimCount = -1, nVarDimId = -1;
+                if( nc_inq_varndims( poDS->cdfid, nVarXId, &nVarDimCount ) != NC_NOERR ||
+                    nVarDimCount != 1 ||
+                    nc_inq_vardimid( poDS->cdfid, nVarXId, &nVarDimId ) != NC_NOERR ||
+                    nVarDimId != ((nProfileDimId >= 0) ? nProfileDimId : nVectorDim) ||
+                    nc_inq_varndims( poDS->cdfid, nVarYId, &nVarDimCount ) != NC_NOERR ||
+                    nVarDimCount != 1 ||
+                    nc_inq_vardimid( poDS->cdfid, nVarYId, &nVarDimId ) != NC_NOERR ||
+                    nVarDimId != ((nProfileDimId >= 0) ? nProfileDimId : nVectorDim) )
+                {
+                    nVarXId = nVarYId = -1;
+                }
+                else if( nVarZId >= 0 &&
+                         (nc_inq_varndims( poDS->cdfid, nVarZId, &nVarDimCount ) != NC_NOERR ||
+                          nVarDimCount != 1 ||
+                          nc_inq_vardimid( poDS->cdfid, nVarZId, &nVarDimId ) != NC_NOERR ||
+                          nVarDimId != nVectorDim) )
+                {
+                    nVarZId = -1;
+                }
+            }
+
+            if( eGType == wkbUnknown && nVarXId >= 0 && nVarYId >= 0 )
+            {
+                eGType = wkbPoint;
+            }
+            if( eGType == wkbPoint && nVarXId >= 0 && nVarYId >= 0 && nVarZId >= 0 )
+            {
+                eGType = wkbPoint25D;
+            }
+            if( eGType == wkbUnknown && osGeometryField.size() == 0 )
+            {
+                eGType = wkbNone;
+            }
+
+            // Read projection info
+            char** papszMetadataBackup = CSLDuplicate(poDS->papszMetadata);
+            poDS->ReadAttributes( poDS->cdfid, nFirstVarId );
+            poDS->SetProjectionFromVar( nFirstVarId, true );
+
+            char szVarName[ NC_MAX_NAME+1 ];
+            szVarName[0] = '\0';
+            CPL_IGNORE_RET_VAL(nc_inq_varname( poDS->cdfid, nFirstVarId, szVarName ));
+            char szTemp[ NC_MAX_NAME+1 ];
+            snprintf(szTemp,sizeof(szTemp), "%s#%s", szVarName,CF_GRD_MAPPING);
+            CPLString osGridMapping = CSLFetchNameValueDef(poDS->papszMetadata,
+                                                           szTemp, "");
+
+            CSLDestroy(poDS->papszMetadata);
+            poDS->papszMetadata = papszMetadataBackup;
+
+            OGRSpatialReference* poSRS = NULL;
+            if( poDS->pszProjection != NULL )
+            {
+                poSRS = new OGRSpatialReference();
+                char* pszWKT = poDS->pszProjection;
+                if( poSRS->importFromWkt(&pszWKT) != OGRERR_NONE )
+                {
+                    delete poSRS;
+                    poSRS = NULL;
+                }
+                CPLFree(poDS->pszProjection);
+                poDS->pszProjection = NULL;
+            }
+            // Reset if there's a 2D raster
+            poDS->bSetProjection = false;
+            poDS->bSetGeoTransform = false;
+
+            if( (poOpenInfo->nOpenFlags & GDAL_OF_RASTER) == 0 )
+            {
+                // Strip out uninteresting metadata
+                poDS->papszMetadata = CSLSetNameValue(poDS->papszMetadata, "NC_GLOBAL#Conventions", NULL);
+                poDS->papszMetadata = CSLSetNameValue(poDS->papszMetadata, "NC_GLOBAL#GDAL", NULL);
+                poDS->papszMetadata = CSLSetNameValue(poDS->papszMetadata, "NC_GLOBAL#history", NULL);
+            }
+
+            netCDFLayer* poLayer = new netCDFLayer(poDS, poDS->cdfid, osLayerName, eGType, poSRS);
+            if( poSRS != NULL )
+                poSRS->Release();
+            poLayer->SetRecordDimID(nVectorDim);
+            if( wkbFlatten(eGType) == wkbPoint && nVarXId >= 0 && nVarYId >= 0 )
+            {
+                poLayer->SetXYZVars( nVarXId, nVarYId, nVarZId );
+            }
+            else if( osGeometryField.size() )
+            {
+                poLayer->SetWKTGeometryField( osGeometryField );
+            }
+            if( osGridMapping.size() )
+            {
+                poLayer->SetGridMapping( osGridMapping );
+            }
+            poLayer->SetProfile( nProfileDimId, nParentIndexVarID );
+            poDS->papoLayers = static_cast<netCDFLayer**>(
+                CPLRealloc(poDS->papoLayers, (poDS->nLayers + 1) * sizeof(netCDFLayer*)));
+            poDS->papoLayers[poDS->nLayers++] = poLayer;
 
-/* -------------------------------------------------------------------- */
-/*  Identify variables that we should ignore as Raster Bands.           */
-/*  Variables that are identified in other variable's "coordinate" and  */
-/*  "bounds" attribute should not be treated as Raster Bands.           */
-/*  See CF sections 5.2, 5.6 and 7.1                                    */
-/* -------------------------------------------------------------------- */
-    for ( j = 0; j < nvars; j++ ) {
-        char **papszTokens = NULL;
-        if ( NCDFGetAttr( cdfid, j, "coordinates", &pszTemp ) == CE_None ) { 
-            papszTokens = CSLTokenizeString2( pszTemp, " ", 0 );
-            for ( i=0; i<CSLCount(papszTokens); i++ ) {
-                papszIgnoreVars = CSLAddString( papszIgnoreVars, papszTokens[i] );
+            for( size_t j = 0; j < anPotentialVectorVarID.size(); j++ )
+            {
+                int anDimIds[2] = { -1, -1 };
+                nc_inq_vardimid( poDS->cdfid, anPotentialVectorVarID[j], anDimIds );
+                if( anDimIds[0] == nVectorDim || (nProfileDimId >= 0 &&  anDimIds[0] == nProfileDimId) )
+                {
+#ifdef NCDF_DEBUG
+                    char szTemp[NC_MAX_NAME+1];
+                    szTemp[0] = '\0';
+                    CPL_IGNORE_RET_VAL(nc_inq_varname( poDS->cdfid, anPotentialVectorVarID[j], szTemp ));
+                    CPLDebug("GDAL_netCDF", "Variable %s is a vector field", szTemp);
+#endif
+                    poLayer->AddField( anPotentialVectorVarID[j] );
+                }
             }
-            if ( papszTokens) CSLDestroy( papszTokens );
-            CPLFree( pszTemp );
-        }
-        if ( NCDFGetAttr( cdfid, j, "bounds", &pszTemp ) == CE_None &&
-             pszTemp != NULL ) { 
-            if ( !EQUAL( pszTemp, "" ) )
-                papszIgnoreVars = CSLAddString( papszIgnoreVars, pszTemp );
-            CPLFree( pszTemp );
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*  Filter variables (valid 2D raster bands)                            */
-/* -------------------------------------------------------------------- */
-    for ( j = 0; j < nvars; j++ ) {
-        nc_inq_varndims ( cdfid, j, &ndims );
-        /* should we ignore this variable ? */
-        szTemp[0] = '\0';
-        status = nc_inq_varname( cdfid, j, szTemp );
-        if ( status == NC_NOERR && 
-             ( CSLFindString( papszIgnoreVars, szTemp ) != -1 ) ) {
-            nIgnoredVars++;
-            CPLDebug( "GDAL_netCDF", "variable #%d [%s] was ignored",j, szTemp);
+#ifdef NETCDF_HAS_NC4
+    } /* end for group */
+    CPLFree(panGroupIds);
+    poDS->cdfid = cdfid;
+#endif
+
+    // Case where there is no raster variable
+    if( nCount == 0 && !bTreatAsSubdataset )
+    {
+        poDS->SetMetadata( poDS->papszMetadata );
+        CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+        poDS->TryLoadXML();
+        // If the dataset has been opened in raster mode only, exit
+        if( (poOpenInfo->nOpenFlags & GDAL_OF_RASTER) != 0 &&
+            (poOpenInfo->nOpenFlags & GDAL_OF_VECTOR) == 0 )
+        {
+            delete poDS;
+            poDS = NULL;
         }
-        /* only accept 2+D vars */
-        else if( ndims >= 2 ) {
-            nVarID=j;
-            nCount++;
+        // Otherwise if the dataset is opened in vector mode, that there is
+        // no vector layer and we are in read-only, exit too.
+        else if( poDS->nLayers == 0 &&
+                 (poOpenInfo->nOpenFlags & GDAL_OF_VECTOR) != 0 &&
+                 poOpenInfo->eAccess == GA_ReadOnly )
+        {
+            delete poDS;
+            poDS = NULL;
         }
+        CPLAcquireMutex(hNCMutex, 1000.0);
+        return( poDS );
     }
-    
-    if ( papszIgnoreVars )
-        CSLDestroy( papszIgnoreVars );
 
 /* -------------------------------------------------------------------- */
 /*      We have more than one variable with 2 dimensions in the         */
@@ -4699,11 +6015,12 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      If we are not treating things as a subdataset, then capture     */
 /*      the name of the single available variable as the subdataset.    */
 /* -------------------------------------------------------------------- */
-    if( !bTreatAsSubdataset ) // nCount must be 1!
+    if( !bTreatAsSubdataset )
     {
         char szVarName[NC_MAX_NAME+1];
         szVarName[0] = '\0';
-        nc_inq_varname( cdfid, nVarID, szVarName);
+        status = nc_inq_varname( cdfid, nVarID, szVarName);
+        NCDF_ERR(status);
         osSubdatasetName = szVarName;
     }
 
@@ -4713,9 +6030,9 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( (nIgnoredVars > 0) && !bTreatAsSubdataset )
     {
-        CPLDebug( "GDAL_netCDF", 
+        CPLDebug( "GDAL_netCDF",
                   "As %d variables were ignored, creating subdataset list "
-                  "for reference. Variable #%d [%s] is the main variable", 
+                  "for reference. Variable #%d [%s] is the main variable",
                   nIgnoredVars, nVarID, osSubdatasetName.c_str() );
         poDS->CreateSubDatasetList();
     }
@@ -4723,21 +6040,24 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Open the NETCDF subdataset NETCDF:"filename":subdataset         */
 /* -------------------------------------------------------------------- */
-    var=-1;
+    int var=-1;
     nc_inq_varid( cdfid, osSubdatasetName, &var);
-    nd = 0;
+    int nd = 0;
     nc_inq_varndims ( cdfid, var, &nd );
 
-    paDimIds = (int *)CPLCalloc(nd, sizeof( int ) );
-    panBandDimPos = ( int * ) CPLCalloc( nd, sizeof( int ) );
+    int *paDimIds  = reinterpret_cast<int *>( CPLCalloc(nd, sizeof( int ) ) );
+
+    // X, Y, Z position in array
+    int *panBandDimPos
+        = reinterpret_cast<int *>( CPLCalloc( nd, sizeof( int ) ) );
 
     nc_inq_vardimid( cdfid, var, paDimIds );
-	
+
 /* -------------------------------------------------------------------- */
 /*      Check if somebody tried to pass a variable with less than 2D    */
 /* -------------------------------------------------------------------- */
     if ( nd < 2 ) {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "Variable has %d dimension(s) - not supported.", nd );
         CPLFree( paDimIds );
         CPLFree( panBandDimPos );
@@ -4762,53 +6082,58 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      To disable set GDAL_NETCDF_VERIFY_DIMS=NO and to use only       */
 /*      attributes (not varnames) set GDAL_NETCDF_VERIFY_DIMS=STRICT    */
 /* -------------------------------------------------------------------- */
-    
-    int bCheckDims = FALSE;
-    bCheckDims = 
-        ( CSLTestBoolean( CPLGetConfigOption( "GDAL_NETCDF_VERIFY_DIMS", "YES" ) )
-          != FALSE ) && EQUALN( szConventions, "CF", 2 );
+
+    bool bCheckDims =
+        CPLTestBool( CPLGetConfigOption( "GDAL_NETCDF_VERIFY_DIMS", "YES" ) )
+        && STARTS_WITH_CI(szConventions, "CF");
+
+    char szDimName[NC_MAX_NAME+1];
 
     if ( bCheckDims ) {
-        char szDimName1[NC_MAX_NAME+1], szDimName2[NC_MAX_NAME+1], 
+        char szDimName1[NC_MAX_NAME+1], szDimName2[NC_MAX_NAME+1],
             szDimName3[NC_MAX_NAME+1], szDimName4[NC_MAX_NAME+1];
         szDimName1[0]='\0';
         szDimName2[0]='\0';
         szDimName3[0]='\0';
         szDimName4[0]='\0';
-        nc_inq_dimname( cdfid, paDimIds[nd-1], szDimName1 );
-        nc_inq_dimname( cdfid, paDimIds[nd-2], szDimName2 );
-        if (  NCDFIsVarLongitude( cdfid, -1, szDimName1 )==FALSE && 
-              NCDFIsVarProjectionX( cdfid, -1, szDimName1 )==FALSE ) {
-            CPLError( CE_Warning, CPLE_AppDefined, 
-                      "dimension #%d (%s) is not a Longitude/X dimension.", 
+        status = nc_inq_dimname( cdfid, paDimIds[nd-1], szDimName1 );
+        NCDF_ERR(status);
+        status = nc_inq_dimname( cdfid, paDimIds[nd-2], szDimName2 );
+        NCDF_ERR(status);
+        if (  NCDFIsVarLongitude( cdfid, -1, szDimName1 )==false &&
+              NCDFIsVarProjectionX( cdfid, -1, szDimName1 )==false ) {
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "dimension #%d (%s) is not a Longitude/X dimension.",
                       nd-1, szDimName1 );
         }
-        if ( NCDFIsVarLatitude( cdfid, -1, szDimName2 )==FALSE &&
-             NCDFIsVarProjectionY( cdfid, -1, szDimName2 )==FALSE ) {
-            CPLError( CE_Warning, CPLE_AppDefined, 
-                      "dimension #%d (%s) is not a Latitude/Y dimension.", 
+        if ( NCDFIsVarLatitude( cdfid, -1, szDimName2 )==false &&
+             NCDFIsVarProjectionY( cdfid, -1, szDimName2 )==false ) {
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "dimension #%d (%s) is not a Latitude/Y dimension.",
                       nd-2, szDimName2 );
         }
         if ( nd >= 3 ) {
-            nc_inq_dimname( cdfid, paDimIds[nd-3], szDimName3 );
+            status = nc_inq_dimname( cdfid, paDimIds[nd-3], szDimName3 );
+            NCDF_ERR(status);
             if ( nd >= 4 ) {
-                nc_inq_dimname( cdfid, paDimIds[nd-4], szDimName4 );
-                if ( NCDFIsVarVerticalCoord( cdfid, -1, szDimName3 )==FALSE ) {
-                    CPLError( CE_Warning, CPLE_AppDefined, 
-                              "dimension #%d (%s) is not a Time  dimension.", 
+                status = nc_inq_dimname( cdfid, paDimIds[nd-4], szDimName4 );
+                NCDF_ERR(status);
+                if ( NCDFIsVarVerticalCoord( cdfid, -1, szDimName3 )==false ) {
+                    CPLError( CE_Warning, CPLE_AppDefined,
+                              "dimension #%d (%s) is not a Time  dimension.",
                               nd-3, szDimName3 );
                 }
-                if ( NCDFIsVarTimeCoord( cdfid, -1, szDimName4 )==FALSE ) {
-                    CPLError( CE_Warning, CPLE_AppDefined, 
-                              "dimension #%d (%s) is not a Time  dimension.", 
+                if ( NCDFIsVarTimeCoord( cdfid, -1, szDimName4 )==false ) {
+                    CPLError( CE_Warning, CPLE_AppDefined,
+                              "dimension #%d (%s) is not a Time  dimension.",
                               nd-4, szDimName4 );
                 }
             }
             else {
-                if ( NCDFIsVarVerticalCoord( cdfid, -1, szDimName3 )==FALSE && 
-                     NCDFIsVarTimeCoord( cdfid, -1, szDimName3 )==FALSE ) {
-                    CPLError( CE_Warning, CPLE_AppDefined, 
-                              "dimension #%d (%s) is not a Time or Vertical dimension.", 
+                if ( NCDFIsVarVerticalCoord( cdfid, -1, szDimName3 )==false &&
+                     NCDFIsVarTimeCoord( cdfid, -1, szDimName3 )==false ) {
+                    CPLError( CE_Warning, CPLE_AppDefined,
+                              "dimension #%d (%s) is not a Time or Vertical dimension.",
                               nd-3, szDimName3 );
                 }
             }
@@ -4818,20 +6143,37 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Get X dimensions information                                    */
 /* -------------------------------------------------------------------- */
+    size_t xdim;
     poDS->nXDimID = paDimIds[nd-1];
     nc_inq_dimlen ( cdfid, poDS->nXDimID, &xdim );
-    poDS->nRasterXSize = xdim;
 
 /* -------------------------------------------------------------------- */
 /*      Get Y dimension information                                     */
 /* -------------------------------------------------------------------- */
+    size_t ydim;
     poDS->nYDimID = paDimIds[nd-2];
     nc_inq_dimlen ( cdfid, poDS->nYDimID, &ydim );
-    poDS->nRasterYSize = ydim;
 
+    if( xdim > INT_MAX || ydim > INT_MAX )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Invalid raster dimensions: " CPL_FRMT_GUIB "x" CPL_FRMT_GUIB,
+                 static_cast<GUIntBig>(xdim),
+                 static_cast<GUIntBig>(ydim));
+        CPLFree( paDimIds );
+        CPLFree( panBandDimPos );
+        CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+        delete poDS;
+        CPLAcquireMutex(hNCMutex, 1000.0);
+        return NULL;
+    }
+
+    poDS->nRasterXSize = static_cast<int>(xdim);
+    poDS->nRasterYSize = static_cast<int>(ydim);
 
-    for( j=0,k=0; j < nd; j++ ){
-        if( paDimIds[j] == poDS->nXDimID ){ 
+    unsigned int k = 0;
+    for( int j=0; j < nd; j++ ){
+        if( paDimIds[j] == poDS->nXDimID ){
             panBandDimPos[0] = j;         // Save Position of XDim
             k++;
         }
@@ -4846,23 +6188,28 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
     if( k != 2 ) {
         CPLFree( paDimIds );
         CPLFree( panBandDimPos );
+        CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+        delete poDS;
+        CPLAcquireMutex(hNCMutex, 1000.0);
         return NULL;
     }
-	    
+
 /* -------------------------------------------------------------------- */
 /*      Read Metadata for this variable                                 */
 /* -------------------------------------------------------------------- */
-/* should disable as is also done at band level, except driver needs the 
+/* should disable as is also done at band level, except driver needs the
    variables as metadata (e.g. projection) */
     poDS->ReadAttributes( cdfid, var );
-	
+
 /* -------------------------------------------------------------------- */
 /*      Read Metadata for each dimension                                */
 /* -------------------------------------------------------------------- */
-    
-    for( j=0; j < dim_count; j++ ){
-        nc_inq_dimname( cdfid, j, szTemp );
+    for( int j=0; j < ndims; j++ ){
+        char szTemp[NC_MAX_NAME+1];
+        status = nc_inq_dimname( cdfid, j, szTemp );
+        NCDF_ERR(status);
         poDS->papszDimName.AddString( szTemp );
+        int nDimID;
         status = nc_inq_varid( cdfid, poDS->papszDimName[j], &nDimID );
         if( status == NC_NOERR ) {
             poDS->ReadAttributes( cdfid, nDimID );
@@ -4872,62 +6219,71 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Set projection info                                             */
 /* -------------------------------------------------------------------- */
-    poDS->SetProjectionFromVar( var );
+    poDS->SetProjectionFromVar( var, false );
 
     /* override bottom-up with GDAL_NETCDF_BOTTOMUP config option */
     const char *pszValue = CPLGetConfigOption( "GDAL_NETCDF_BOTTOMUP", NULL );
     if ( pszValue ) {
-        poDS->bBottomUp = CSLTestBoolean( pszValue ) != FALSE; 
-        CPLDebug( "GDAL_netCDF", 
+        poDS->bBottomUp = CPLTestBool( pszValue );
+        CPLDebug( "GDAL_netCDF",
                   "set bBottomUp=%d because GDAL_NETCDF_BOTTOMUP=%s",
-                  poDS->bBottomUp, pszValue );
+                  static_cast<int>(poDS->bBottomUp), pszValue );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Save non-spatial dimension info                                 */
 /* -------------------------------------------------------------------- */
 
-    nTotLevCount = 1;
+    int *panBandZLev = NULL;
+    int nDim = 2;
+    size_t lev_count;
+    size_t nTotLevCount = 1;
+    nc_type nType = NC_NAT;
+
+    CPLString osExtraDimNames;
+
     if ( nd > 2 ) {
         nDim=2;
         panBandZLev = (int *)CPLCalloc( nd-2, sizeof( int ) );
 
-        strcpy( szExtraDimNames, (char*)"{");
+        osExtraDimNames = "{";
 
-        for( j=0; j < nd; j++ ){
-            if( ( paDimIds[j] != poDS->nXDimID ) && 
+        for( int j=0; j < nd; j++ ){
+            if( ( paDimIds[j] != poDS->nXDimID ) &&
                 ( paDimIds[j] != poDS->nYDimID ) ){
                 nc_inq_dimlen ( cdfid, paDimIds[j], &lev_count );
                 nTotLevCount *= lev_count;
-                panBandZLev[ nDim-2 ] = lev_count;
+                panBandZLev[ nDim-2 ] = static_cast<int>(lev_count);
                 panBandDimPos[ nDim++ ] = j; //Save Position of ZDim
                 //Save non-spatial dimension names
-                if ( nc_inq_dimname( cdfid, paDimIds[j], szDimName ) 
+                if ( nc_inq_dimname( cdfid, paDimIds[j], szDimName )
                      == NC_NOERR ) {
-                    strcat( szExtraDimNames, szDimName );
+                    osExtraDimNames += szDimName;
                     if ( j < nd-3 ) {
-                        strcat( szExtraDimNames, (char *)"," );
+                        osExtraDimNames += ",";
                     }
                     nc_inq_varid( cdfid, szDimName, &nVarID );
                     nc_inq_vartype( cdfid, nVarID, &nType );
-                    sprintf( szExtraDimDef, "{%ld,%d}", (long)lev_count, nType );
-                    sprintf( szTemp, "NETCDF_DIM_%s_DEF", szDimName );
-                    poDS->papszMetadata = CSLSetNameValue( poDS->papszMetadata, 
+                    char szExtraDimDef[NC_MAX_NAME+1];
+                    snprintf( szExtraDimDef, sizeof(szExtraDimDef), "{%ld,%d}", (long)lev_count, nType );
+                    char szTemp[NC_MAX_NAME+32+1];
+                    snprintf( szTemp, sizeof(szTemp), "NETCDF_DIM_%s_DEF", szDimName );
+                    poDS->papszMetadata = CSLSetNameValue( poDS->papszMetadata,
                                                            szTemp, szExtraDimDef );
                     if ( NCDFGet1DVar( cdfid, nVarID, &pszTemp ) == CE_None ) {
-                        sprintf( szTemp, "NETCDF_DIM_%s_VALUES", szDimName );
-                        poDS->papszMetadata = CSLSetNameValue( poDS->papszMetadata, 
+                        snprintf( szTemp, sizeof(szTemp), "NETCDF_DIM_%s_VALUES", szDimName );
+                        poDS->papszMetadata = CSLSetNameValue( poDS->papszMetadata,
                                                               szTemp, pszTemp );
                         CPLFree( pszTemp );
                     }
                 }
             }
         }
-        strcat( szExtraDimNames, (char *)"}" );
-        poDS->papszMetadata = CSLSetNameValue( poDS->papszMetadata, 
-                                               "NETCDF_DIM_EXTRA", szExtraDimNames );
+        osExtraDimNames += "}";
+        poDS->papszMetadata = CSLSetNameValue( poDS->papszMetadata,
+                                               "NETCDF_DIM_EXTRA",
+                                               osExtraDimNames );
     }
-    i=0;
 
 /* -------------------------------------------------------------------- */
 /*      Store Metadata                                                  */
@@ -4937,22 +6293,31 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create bands                                                    */
 /* -------------------------------------------------------------------- */
+
+    /* Arbitrary threshold */
+    int nMaxBandCount = atoi(CPLGetConfigOption("GDAL_MAX_BAND_COUNT", "32768"));
+    if( nMaxBandCount <= 0 )
+        nMaxBandCount = 32768;
+    if( nTotLevCount > static_cast<unsigned int>(nMaxBandCount) )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Limiting number of bands to %d instead of %u",
+                 nMaxBandCount,
+                 static_cast<unsigned int>(nTotLevCount));
+        nTotLevCount = static_cast<unsigned int>(nMaxBandCount);
+    }
     for ( unsigned int lev = 0; lev < nTotLevCount ; lev++ ) {
         netCDFRasterBand *poBand =
             new netCDFRasterBand(poDS, var, nDim, lev,
-                                 panBandZLev, panBandDimPos, 
-                                 paDimIds, i+1 );
-        poDS->SetBand( i+1, poBand );
-        i++;
-    } 
+                                 panBandZLev, panBandDimPos,
+                                 paDimIds, lev+1 );
+        poDS->SetBand( lev+1, poBand );
+    }
 
     CPLFree( paDimIds );
     CPLFree( panBandDimPos );
     if ( panBandZLev )
         CPLFree( panBandZLev );
-    
-    poDS->nBands = i;
-
     // Handle angular geographic coordinates here
 
 /* -------------------------------------------------------------------- */
@@ -4977,151 +6342,134 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
     return( poDS );
 }
 
-
 /************************************************************************/
 /*                            CopyMetadata()                            */
 /*                                                                      */
 /*      Create a copy of metadata for NC_GLOBAL or a variable           */
 /************************************************************************/
 
-void CopyMetadata( void  *poDS, int fpImage, int CDFVarID, 
-                   const char *pszPrefix, int bIsBand ) {
+static void CopyMetadata( void  *poDS, int fpImage, int CDFVarID,
+                   const char *pszPrefix, bool bIsBand ) {
 
-    char       **papszMetadata=NULL;
     char       **papszFieldData=NULL;
-    const char *pszField;
-    char       szMetaName[ NCDF_MAX_STR_LEN ];
-    size_t     nAttrValueSize =  NCDF_MAX_STR_LEN;
-    char       *pszMetaValue = (char *) CPLMalloc(sizeof(char) * nAttrValueSize);
-    *pszMetaValue = '\0';
-    char       szTemp[ NCDF_MAX_STR_LEN ];
-    int        nItems;
 
     /* Remove the following band meta but set them later from band data */
-    const char *papszIgnoreBand[] = { CF_ADD_OFFSET, CF_SCALE_FACTOR, 
-                                      "valid_range", "_Unsigned", 
-                                      _FillValue, "coordinates", 
+    const char *papszIgnoreBand[] = { CF_ADD_OFFSET, CF_SCALE_FACTOR,
+                                      "valid_range", "_Unsigned",
+                                      _FillValue, "coordinates",
                                       NULL };
     const char *papszIgnoreGlobal[] = { "NETCDF_DIM_EXTRA", NULL };
 
+    char **papszMetadata = NULL;
     if( CDFVarID == NC_GLOBAL ) {
         papszMetadata = GDALGetMetadata( (GDALDataset *) poDS,"");
     } else {
         papszMetadata = GDALGetMetadata( (GDALRasterBandH) poDS, NULL );
     }
 
-    nItems = CSLCount( papszMetadata );             
-    
+    const int nItems = CSLCount( papszMetadata );
+
     for(int k=0; k < nItems; k++ ) {
-        pszField = CSLGetField( papszMetadata, k );
+        const char *pszField = CSLGetField( papszMetadata, k );
         if ( papszFieldData ) CSLDestroy( papszFieldData );
-        papszFieldData = CSLTokenizeString2 (pszField, "=", 
+        papszFieldData = CSLTokenizeString2 (pszField, "=",
                                              CSLT_HONOURSTRINGS );
         if( papszFieldData[1] != NULL ) {
 
 #ifdef NCDF_DEBUG
-            CPLDebug( "GDAL_netCDF", "copy metadata [%s]=[%s]", 
+            CPLDebug( "GDAL_netCDF", "copy metadata [%s]=[%s]",
                       papszFieldData[ 0 ], papszFieldData[ 1 ] );
 #endif
 
-            strcpy( szMetaName,  papszFieldData[ 0 ] );
-            NCDFSafeStrcpy(&pszMetaValue, papszFieldData[ 1 ], &nAttrValueSize);
+            CPLString osMetaName(papszFieldData[ 0 ]);
+            CPLString osMetaValue(papszFieldData[ 1 ]);
 
             /* check for items that match pszPrefix if applicable */
             if ( ( pszPrefix != NULL ) && ( !EQUAL( pszPrefix, "" ) ) ) {
                     /* remove prefix */
-                    if ( EQUALN( szMetaName, pszPrefix, strlen(pszPrefix) ) ) {
-                        strcpy( szTemp, szMetaName+strlen(pszPrefix) );
-                        strcpy( szMetaName, szTemp );
+                    if ( EQUALN( osMetaName, pszPrefix, strlen(pszPrefix) ) ) {
+                        osMetaName = osMetaName.substr(strlen(pszPrefix));
                     }
                     /* only copy items that match prefix */
                     else
                         continue;
             }
 
-            /* Fix various issues with metadata translation */ 
+            /* Fix various issues with metadata translation */
             if( CDFVarID == NC_GLOBAL ) {
                 /* Do not copy items in papszIgnoreGlobal and NETCDF_DIM_* */
-                if ( ( CSLFindString( (char **)papszIgnoreGlobal, szMetaName ) != -1 ) ||
-                     ( strncmp( szMetaName, "NETCDF_DIM_", 11 ) == 0 ) )
+                if ( ( CSLFindString( (char **)papszIgnoreGlobal, osMetaName ) != -1 ) ||
+                     ( STARTS_WITH(osMetaName, "NETCDF_DIM_") ) )
                     continue;
-                /* Remove NC_GLOBAL prefix for netcdf global Metadata */ 
-                else if( strncmp( szMetaName, "NC_GLOBAL#", 10 ) == 0 ) {
-                    strcpy( szTemp, szMetaName+10 );
-                    strcpy( szMetaName, szTemp );
-                } 
+                /* Remove NC_GLOBAL prefix for netcdf global Metadata */
+                else if( STARTS_WITH(osMetaName, "NC_GLOBAL#") ) {
+                    osMetaName = osMetaName.substr(strlen("NC_GLOBAL#"));
+                }
                 /* GDAL Metadata renamed as GDAL-[meta] */
-                else if ( strstr( szMetaName, "#" ) == NULL ) {
-                    strcpy( szTemp, "GDAL_" );
-                    strcat( szTemp, szMetaName );
-                    strcpy( szMetaName, szTemp );
+                else if ( strstr( osMetaName, "#" ) == NULL ) {
+                    osMetaName = "GDAL_" + osMetaName;
                 }
                 /* Keep time, lev and depth information for safe-keeping */
                 /* Time and vertical coordinate handling need improvements */
                 /*
-                else if( strncmp( szMetaName, "time#", 5 ) == 0 ) {
+                else if( STARTS_WITH(szMetaName, "time#") ) {
                     szMetaName[4] = '-';
                 }
-                else if( strncmp( szMetaName, "lev#", 4 ) == 0 ) {
+                else if( STARTS_WITH(szMetaName, "lev#") ) {
                     szMetaName[3] = '-';
                 }
-                else if( strncmp( szMetaName, "depth#", 6 ) == 0 ) {
+                else if( STARTS_WITH(szMetaName, "depth#") ) {
                     szMetaName[5] = '-';
                 }
                 */
                 /* Only copy data without # (previously all data was copied)  */
-                if ( strstr( szMetaName, "#" ) != NULL )
+                if ( strstr( osMetaName, "#" ) != NULL )
                     continue;
                 // /* netCDF attributes do not like the '#' character. */
                 // for( unsigned int h=0; h < strlen( szMetaName ) -1 ; h++ ) {
-                //     if( szMetaName[h] == '#' ) szMetaName[h] = '-'; 
-                // }             
+                //     if( szMetaName[h] == '#' ) szMetaName[h] = '-';
+                // }
             }
             else {
-                /* Do not copy varname, stats, NETCDF_DIM_*, nodata 
+                /* Do not copy varname, stats, NETCDF_DIM_*, nodata
                    and items in papszIgnoreBand */
-                if ( ( strncmp( szMetaName, "NETCDF_VARNAME", 14) == 0 ) ||
-                     ( strncmp( szMetaName, "STATISTICS_", 11) == 0 ) ||
-                     ( strncmp( szMetaName, "NETCDF_DIM_", 11 ) == 0 ) ||
-                     ( strncmp( szMetaName, "missing_value", 13 ) == 0 ) ||
-                     ( strncmp( szMetaName, "_FillValue", 10 ) == 0 ) ||
-                     ( CSLFindString( (char **)papszIgnoreBand, szMetaName ) != -1 ) )
+                if ( ( STARTS_WITH(osMetaName, "NETCDF_VARNAME") ) ||
+                     ( STARTS_WITH(osMetaName, "STATISTICS_") ) ||
+                     ( STARTS_WITH(osMetaName, "NETCDF_DIM_") ) ||
+                     ( STARTS_WITH(osMetaName, "missing_value") ) ||
+                     ( STARTS_WITH(osMetaName, "_FillValue") ) ||
+                     ( CSLFindString( (char **)papszIgnoreBand, osMetaName ) != -1 ) )
                     continue;
             }
 
-
 #ifdef NCDF_DEBUG
             CPLDebug( "GDAL_netCDF", "copy name=[%s] value=[%s]",
-                      szMetaName, pszMetaValue );
+                      osMetaName.c_str(), osMetaValue.c_str() );
 #endif
-            if ( NCDFPutAttr( fpImage, CDFVarID,szMetaName, 
-                              pszMetaValue ) != CE_None )
-                CPLDebug( "GDAL_netCDF", "NCDFPutAttr(%d, %d, %s, %s) failed", 
-                          fpImage, CDFVarID,szMetaName, pszMetaValue );
+            if ( NCDFPutAttr( fpImage, CDFVarID,osMetaName,
+                              osMetaValue ) != CE_None )
+                CPLDebug( "GDAL_netCDF", "NCDFPutAttr(%d, %d, %s, %s) failed",
+                          fpImage, CDFVarID,osMetaName.c_str(), osMetaValue.c_str() );
         }
     }
 
     if ( papszFieldData ) CSLDestroy( papszFieldData );
-    CPLFree( pszMetaValue );
 
     /* Set add_offset and scale_factor here if present */
     if( ( CDFVarID != NC_GLOBAL ) && ( bIsBand ) ) {
 
         int bGotAddOffset, bGotScale;
         GDALRasterBandH poRB = (GDALRasterBandH) poDS;
-        double dfAddOffset = GDALGetRasterOffset( poRB , &bGotAddOffset );
-        double dfScale = GDALGetRasterScale( poRB, &bGotScale );
+        const double dfAddOffset = GDALGetRasterOffset( poRB , &bGotAddOffset );
+        const double dfScale = GDALGetRasterScale( poRB, &bGotScale );
 
-        if ( bGotAddOffset && dfAddOffset != 0.0 && bGotScale && dfScale != 1.0 ) {
+        if ( bGotAddOffset && dfAddOffset != 0.0 )
             GDALSetRasterOffset( poRB, dfAddOffset );
+        if ( bGotScale && dfScale != 1.0 )
             GDALSetRasterScale( poRB, dfScale );
-        }
-
     }
-
 }
 
-
 /************************************************************************/
 /*                            CreateLL()                                */
 /*                                                                      */
@@ -5132,14 +6480,17 @@ void CopyMetadata( void  *poDS, int fpImage, int CDFVarID,
 
 netCDFDataset *
 netCDFDataset::CreateLL( const char * pszFilename,
-                         int nXSize, int nYSize, CPL_UNUSED int nBands,
+                         int nXSize, int nYSize, int nBands,
                          char ** papszOptions )
 {
-    int status = NC_NOERR;
-    netCDFDataset *poDS;
+    if( !((nXSize == 0 && nYSize == 0 && nBands == 0) ||
+          (nXSize > 0 && nYSize > 0 && nBands > 0)) )
+    {
+        return NULL;
+    }
 
     CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
-    poDS = new netCDFDataset();
+    netCDFDataset *poDS = new netCDFDataset();
     CPLAcquireMutex(hNCMutex, 1000.0);
 
     poDS->nRasterXSize = nXSize;
@@ -5160,18 +6511,46 @@ netCDFDataset::CreateLL( const char * pszFilename,
     poDS->papszCreationOptions = CSLDuplicate( papszOptions );
     poDS->ProcessCreationOptions( );
 
+    if( poDS->eMultipleLayerBehaviour == SEPARATE_FILES )
+    {
+        VSIStatBuf sStat;
+        if( VSIStat( pszFilename, &sStat ) == 0 )
+        {
+            if( !VSI_ISDIR(sStat.st_mode) )
+            {
+                CPLError(CE_Failure, CPLE_FileIO, "%s is an existing file, but not a directory",
+                        pszFilename);
+                CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+                delete poDS;
+                CPLAcquireMutex(hNCMutex, 1000.0);
+                return NULL;
+            }
+        }
+        else if( VSIMkdir( pszFilename, 0755 ) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "Cannot create %s directory",
+                     pszFilename);
+            CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+            delete poDS;
+            CPLAcquireMutex(hNCMutex, 1000.0);
+            return NULL;
+        }
+
+        return poDS;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Create the dataset.                                             */
 /* -------------------------------------------------------------------- */
-    status = nc_create( pszFilename, poDS->nCreateMode,  &(poDS->cdfid) );
+    int status = nc_create( pszFilename, poDS->nCreateMode,  &(poDS->cdfid) );
 
     /* put into define mode */
-    poDS->SetDefineMode(TRUE);
+    poDS->SetDefineMode(true);
 
     if( status != NC_NOERR )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Unable to create netCDF file %s (Error code %d): %s .\n", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Unable to create netCDF file %s (Error code %d): %s .\n",
                   pszFilename, status, nc_strerror(status) );
         CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
         delete poDS;
@@ -5182,22 +6561,24 @@ netCDFDataset::CreateLL( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Define dimensions                                               */
 /* -------------------------------------------------------------------- */
-    poDS->papszDimName.AddString( NCDF_DIMNAME_X );
-    status = nc_def_dim( poDS->cdfid, NCDF_DIMNAME_X, nXSize, 
-                         &(poDS->nXDimID) );
-    NCDF_ERR(status);
-    CPLDebug( "GDAL_netCDF", "status nc_def_dim( %d, %s, %d, -) got id %d", 
-              poDS->cdfid, NCDF_DIMNAME_X, nXSize, poDS->nXDimID );   
+    if( nXSize > 0 && nYSize > 0 )
+    {
+        poDS->papszDimName.AddString( NCDF_DIMNAME_X );
+        status = nc_def_dim( poDS->cdfid, NCDF_DIMNAME_X, nXSize,
+                            &(poDS->nXDimID) );
+        NCDF_ERR(status);
+        CPLDebug( "GDAL_netCDF", "status nc_def_dim( %d, %s, %d, -) got id %d",
+                poDS->cdfid, NCDF_DIMNAME_X, nXSize, poDS->nXDimID );
 
-    poDS->papszDimName.AddString( NCDF_DIMNAME_Y );
-    status = nc_def_dim( poDS->cdfid, NCDF_DIMNAME_Y, nYSize, 
-                         &(poDS->nYDimID) );
-    NCDF_ERR(status);
-    CPLDebug( "GDAL_netCDF", "status nc_def_dim( %d, %s, %d, -) got id %d", 
-              poDS->cdfid, NCDF_DIMNAME_Y, nYSize, poDS->nYDimID );   
+        poDS->papszDimName.AddString( NCDF_DIMNAME_Y );
+        status = nc_def_dim( poDS->cdfid, NCDF_DIMNAME_Y, nYSize,
+                            &(poDS->nYDimID) );
+        NCDF_ERR(status);
+        CPLDebug( "GDAL_netCDF", "status nc_def_dim( %d, %s, %d, -) got id %d",
+                poDS->cdfid, NCDF_DIMNAME_Y, nYSize, poDS->nYDimID );
+    }
 
     return poDS;
-
 }
 
 /************************************************************************/
@@ -5210,35 +6591,34 @@ netCDFDataset::Create( const char * pszFilename,
                        GDALDataType eType,
                        char ** papszOptions )
 {
-    netCDFDataset *poDS;
-
-    CPLDebug( "GDAL_netCDF", 
-              "\n=====\nnetCDFDataset::Create( %s, ... )\n", 
+    CPLDebug( "GDAL_netCDF",
+              "\n=====\nnetCDFDataset::Create( %s, ... )\n",
               pszFilename );
 
     CPLMutexHolderD(&hNCMutex);
 
-    poDS =  netCDFDataset::CreateLL( pszFilename,
-                                     nXSize, nYSize, nBands,
-                                     papszOptions );
-
-    if ( ! poDS ) 
+    netCDFDataset *poDS =  netCDFDataset::CreateLL( pszFilename,
+                                                    nXSize, nYSize, nBands,
+                                                    papszOptions );
+    if ( ! poDS )
         return NULL;
 
     /* should we write signed or unsigned byte? */
     /* TODO should this only be done in Create() */
-    poDS->bSignedData = TRUE;
+    poDS->bSignedData = true;
     const char *pszValue  =
-        CSLFetchNameValue( papszOptions, "PIXELTYPE" );
-    if( pszValue == NULL )
-        pszValue = "";
+        CSLFetchNameValueDef( papszOptions, "PIXELTYPE", "" );
     if( eType == GDT_Byte && ( ! EQUAL(pszValue,"SIGNEDBYTE") ) )
-        poDS->bSignedData = FALSE;
+        poDS->bSignedData = false;
 
 /* -------------------------------------------------------------------- */
 /*      Add Conventions, GDAL info and history                          */
 /* -------------------------------------------------------------------- */
-    NCDFAddGDALHistory( poDS->cdfid, pszFilename, "", "Create" );
+    if( poDS->cdfid >= 0 )
+    {
+        NCDFAddGDALHistory( poDS->cdfid, pszFilename, "", "Create",
+                            (nBands == 0) ? NCDF_CONVENTIONS_CF_V1_6 : NCDF_CONVENTIONS_CF_V1_5);
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Define bands                                                    */
@@ -5249,40 +6629,39 @@ netCDFDataset::Create( const char * pszFilename,
                                                     poDS->bSignedData ) );
     }
 
-    CPLDebug( "GDAL_netCDF", 
-              "netCDFDataset::Create( %s, ... ) done", 
+    CPLDebug( "GDAL_netCDF",
+              "netCDFDataset::Create( %s, ... ) done",
               pszFilename );
 /* -------------------------------------------------------------------- */
 /*      Return same dataset                                             */
 /* -------------------------------------------------------------------- */
      return( poDS );
-
 }
 
 
 template <class T>
-CPLErr  NCDFCopyBand( GDALRasterBand *poSrcBand, GDALRasterBand *poDstBand,
+static CPLErr  NCDFCopyBand( GDALRasterBand *poSrcBand, GDALRasterBand *poDstBand,
                       int nXSize, int nYSize,
                       GDALProgressFunc pfnProgress, void * pProgressData )
 {
     GDALDataType eDT = poSrcBand->GetRasterDataType();
     CPLErr eErr = CE_None;
     T *patScanline = (T *) CPLMalloc( nXSize * sizeof(T) );
-        
-    for( int iLine = 0; iLine < nYSize && eErr == CE_None; iLine++ )  {                
-        eErr = poSrcBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, 
+
+    for( int iLine = 0; iLine < nYSize && eErr == CE_None; iLine++ )  {
+        eErr = poSrcBand->RasterIO( GF_Read, 0, iLine, nXSize, 1,
                                     patScanline, nXSize, 1, eDT,
                                     0,0, NULL);
         if ( eErr != CE_None )
-            CPLDebug( "GDAL_netCDF", 
+            CPLDebug( "GDAL_netCDF",
                       "NCDFCopyBand(), poSrcBand->RasterIO() returned error code %d",
                       eErr );
-        else { 
-            eErr = poDstBand->RasterIO( GF_Write, 0, iLine, nXSize, 1, 
+        else {
+            eErr = poDstBand->RasterIO( GF_Write, 0, iLine, nXSize, 1,
                                         patScanline, nXSize, 1, eDT,
                                         0,0, NULL);
             if ( eErr != CE_None )
-                CPLDebug( "GDAL_netCDF", 
+                CPLDebug( "GDAL_netCDF",
                           "NCDFCopyBand(), poDstBand->RasterIO() returned error code %d",
                           eErr );
         }
@@ -5296,7 +6675,7 @@ CPLErr  NCDFCopyBand( GDALRasterBand *poSrcBand, GDALRasterBand *poDstBand,
             }
         }
     }
-           
+
     CPLFree( patScanline );
 
     pfnProgress( 1.0, NULL, pProgressData );
@@ -5304,7 +6683,6 @@ CPLErr  NCDFCopyBand( GDALRasterBand *poSrcBand, GDALRasterBand *poDstBand,
     return eErr;
 }
 
-
 /************************************************************************/
 /*                            CreateCopy()                              */
 /************************************************************************/
@@ -5314,39 +6692,16 @@ netCDFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                            CPL_UNUSED int bStrict, char ** papszOptions,
                            GDALProgressFunc pfnProgress, void * pProgressData )
 {
-    netCDFDataset *poDS;
-    void *pScaledProgress;
-    GDALDataType eDT;
-    CPLErr eErr = CE_None;
-    int nBands, nXSize, nYSize;
-    double adfGeoTransform[6];
-    const char *pszWKT;
-    int iBand;
-    int status = NC_NOERR;
-
-    int nDim = 2;
-    int          *panBandDimPos=NULL;         // X, Y, Z postion in array
-    int          *panBandZLev=NULL;
-    int          *panDimIds=NULL;
-    int          *panDimVarIds=NULL;
-    nc_type nVarType;
-    char       szTemp[ NCDF_MAX_STR_LEN ];
-    double dfTemp,dfTemp2;
-    netCDFRasterBand *poBand = NULL;
-    GDALRasterBand *poSrcBand = NULL;
-    GDALRasterBand *poDstBand = NULL;
-    int nBandID = -1;
-
     CPLMutexHolderD(&hNCMutex);
 
-    CPLDebug( "GDAL_netCDF", 
-              "\n=====\nnetCDFDataset::CreateCopy( %s, ... )\n", 
+    CPLDebug( "GDAL_netCDF",
+              "\n=====\nnetCDFDataset::CreateCopy( %s, ... )\n",
               pszFilename );
 
-    nBands = poSrcDS->GetRasterCount();
-    nXSize = poSrcDS->GetRasterXSize();
-    nYSize = poSrcDS->GetRasterYSize();
-    pszWKT = poSrcDS->GetProjectionRef();
+    const int nBands = poSrcDS->GetRasterCount();
+    const int nXSize = poSrcDS->GetRasterXSize();
+    const int nYSize = poSrcDS->GetRasterYSize();
+    const char *pszWKT = poSrcDS->GetProjectionRef();
 
 /* -------------------------------------------------------------------- */
 /*      Check input bands for errors                                    */
@@ -5354,18 +6709,20 @@ netCDFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
     if (nBands == 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "NetCDF driver does not support source dataset with zero band.\n");
         return NULL;
     }
 
-    for( iBand=1; iBand <= nBands; iBand++ )
+    GDALDataType eDT;
+    GDALRasterBand *poSrcBand = NULL;
+    for( int iBand=1; iBand <= nBands; iBand++ )
     {
         poSrcBand = poSrcDS->GetRasterBand( iBand );
         eDT = poSrcBand->GetRasterDataType();
         if (eDT == GDT_Unknown || GDALDataTypeIsComplex(eDT))
         {
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                       "NetCDF driver does not support source dataset with band of complex type.");
             return NULL;
         }
@@ -5375,37 +6732,39 @@ netCDFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         return NULL;
 
     /* same as in Create() */
-    poDS = netCDFDataset::CreateLL( pszFilename,
-                                    nXSize, nYSize, nBands,
-                                    papszOptions );
-    if ( ! poDS ) 
+    netCDFDataset *poDS = netCDFDataset::CreateLL( pszFilename,
+                                                   nXSize, nYSize, nBands,
+                                                   papszOptions );
+    if ( ! poDS )
         return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Copy global metadata                                            */
 /*      Add Conventions, GDAL info and history                          */
 /* -------------------------------------------------------------------- */
-    CopyMetadata((void *) poSrcDS, poDS->cdfid, NC_GLOBAL, NULL, FALSE );
+    CopyMetadata((void *) poSrcDS, poDS->cdfid, NC_GLOBAL, NULL, false );
     NCDFAddGDALHistory( poDS->cdfid, pszFilename,
                         poSrcDS->GetMetadataItem("NC_GLOBAL#history",""),
                         "CreateCopy" );
 
     pfnProgress( 0.1, NULL, pProgressData );
 
-
 /* -------------------------------------------------------------------- */
 /*      Check for extra dimensions                                      */
 /* -------------------------------------------------------------------- */
-    char **papszExtraDimNames =  
+    int nDim = 2;
+    char **papszExtraDimNames =
         NCDFTokenizeArray( poSrcDS->GetMetadataItem("NETCDF_DIM_EXTRA","") );
     char **papszExtraDimValues = NULL;
-    size_t nDimSize = -1;
-    size_t nDimSizeTot = 1;
+
     if ( papszExtraDimNames != NULL && ( CSLCount( papszExtraDimNames )> 0 ) ) {
+        size_t nDimSize = 0;
+        size_t nDimSizeTot = 1;
         // first make sure dimensions lengths compatible with band count
         // for ( int i=0; i<CSLCount( papszExtraDimNames ); i++ ) {
         for ( int i=CSLCount( papszExtraDimNames )-1; i>=0; i-- ) {
-            sprintf( szTemp, "NETCDF_DIM_%s_DEF", papszExtraDimNames[i] );
+            char szTemp[ NC_MAX_NAME + 32 + 1 ];
+            snprintf( szTemp, sizeof(szTemp), "NETCDF_DIM_%s_DEF", papszExtraDimNames[i] );
             papszExtraDimValues = NCDFTokenizeArray( poSrcDS->GetMetadataItem(szTemp,"") );
             nDimSize = atol( papszExtraDimValues[0] );
             CSLDestroy( papszExtraDimValues );
@@ -5426,41 +6785,47 @@ netCDFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         }
     }
 
-    panDimIds = (int *)CPLCalloc( nDim, sizeof( int ) );
-    panBandDimPos = (int *) CPLCalloc( nDim, sizeof( int ) );
-    
-    if ( nDim > 2 ) { 
-        panBandZLev = (int *)CPLCalloc( nDim-2, sizeof( int ) );
-        panDimVarIds = (int *)CPLCalloc( nDim-2, sizeof( int ) );
+    int *panDimIds = reinterpret_cast<int *>( CPLCalloc( nDim, sizeof( int ) ) );
+    int *panBandDimPos = reinterpret_cast<int *>( CPLCalloc( nDim, sizeof( int ) ) );
+
+    nc_type nVarType;
+    int status = NC_NOERR;
+    int *panBandZLev = NULL;
+    int *panDimVarIds = NULL;
+
+    if ( nDim > 2 ) {
+        panBandZLev = reinterpret_cast<int *>( CPLCalloc( nDim-2, sizeof( int ) ) );
+        panDimVarIds = reinterpret_cast<int *>( CPLCalloc( nDim-2, sizeof( int ) ) );
 
         /* define all dims */
         for ( int i=CSLCount( papszExtraDimNames )-1; i>=0; i-- ) {
             poDS->papszDimName.AddString( papszExtraDimNames[i] );
-            sprintf( szTemp, "NETCDF_DIM_%s_DEF", papszExtraDimNames[i] );
+            char szTemp[ NC_MAX_NAME + 32 + 1 ];
+            snprintf( szTemp, sizeof(szTemp), "NETCDF_DIM_%s_DEF", papszExtraDimNames[i] );
             papszExtraDimValues = NCDFTokenizeArray( poSrcDS->GetMetadataItem(szTemp,"") );
-            nDimSize = atol( papszExtraDimValues[0] );
+            int nDimSize = atoi( papszExtraDimValues[0] );
             /* nc_type is an enum in netcdf-3, needs casting */
             nVarType = (nc_type) atol( papszExtraDimValues[1] );
             CSLDestroy( papszExtraDimValues );
             panBandZLev[ i ] = nDimSize;
             panBandDimPos[ i+2 ] = i; //Save Position of ZDim
-           
+
             /* define dim */
-            status = nc_def_dim( poDS->cdfid, papszExtraDimNames[i], nDimSize, 
+            status = nc_def_dim( poDS->cdfid, papszExtraDimNames[i], nDimSize,
                                  &(panDimIds[i]) );
             NCDF_ERR(status);
 
             /* define dim var */
             int anDim[1];
             anDim[0] = panDimIds[i];
-            status = nc_def_var( poDS->cdfid, papszExtraDimNames[i],  
-                                 nVarType, 1, anDim, 
+            status = nc_def_var( poDS->cdfid, papszExtraDimNames[i],
+                                 nVarType, 1, anDim,
                                  &(panDimVarIds[i]) );
             NCDF_ERR(status);
 
             /* add dim metadata, using global var# items */
-            sprintf( szTemp, "%s#", papszExtraDimNames[i] );
-            CopyMetadata((void *) poSrcDS, poDS->cdfid, panDimVarIds[i], szTemp, FALSE );
+            snprintf( szTemp, sizeof(szTemp), "%s#", papszExtraDimNames[i] );
+            CopyMetadata((void *) poSrcDS, poDS->cdfid, panDimVarIds[i], szTemp, false );
         }
     }
 
@@ -5470,42 +6835,45 @@ netCDFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     /* copy geolocation info */
     if ( poSrcDS->GetMetadata("GEOLOCATION") != NULL )
         poDS->SetMetadata( poSrcDS->GetMetadata("GEOLOCATION"), "GEOLOCATION" );
-    
+
     /* copy geotransform */
-    int bGotGeoTransform = FALSE;
-    eErr = poSrcDS->GetGeoTransform( adfGeoTransform );
+    bool bGotGeoTransform = false;
+    double adfGeoTransform[6];
+    CPLErr eErr = poSrcDS->GetGeoTransform( adfGeoTransform );
     if ( eErr == CE_None ) {
         poDS->SetGeoTransform( adfGeoTransform );
         /* disable AddProjectionVars() from being called */
-        bGotGeoTransform = TRUE;
-        poDS->bSetGeoTransform = FALSE;
+        bGotGeoTransform = true;
+        poDS->bSetGeoTransform = false;
     }
 
     /* copy projection */
+    void *pScaledProgress;
     if ( pszWKT ) {
         poDS->SetProjection( pszWKT );
         /* now we can call AddProjectionVars() directly */
         poDS->bSetGeoTransform = bGotGeoTransform;
-        pScaledProgress = GDALCreateScaledProgress( 0.20, 0.50, pfnProgress, 
+        pScaledProgress = GDALCreateScaledProgress( 0.1, 0.25, pfnProgress,
                                                     pProgressData );
         poDS->AddProjectionVars( GDALScaledProgress, pScaledProgress );
         /* save X,Y dim positions */
         panDimIds[nDim-1] = poDS->nXDimID;
-        panBandDimPos[0] = nDim-1; 
+        panBandDimPos[0] = nDim-1;
         panDimIds[nDim-2] = poDS->nYDimID;
-        panBandDimPos[1] = nDim-2; 
+        panBandDimPos[1] = nDim-2;
         GDALDestroyScaledProgress( pScaledProgress );
 
     }
 
     /* write extra dim values - after projection for optimization */
-    if ( nDim > 2 ) { 
+    if ( nDim > 2 ) {
         /* make sure we are in data mode */
-        ( ( netCDFDataset * ) poDS )->SetDefineMode( FALSE );
+        reinterpret_cast<netCDFDataset *>( poDS )->SetDefineMode( false );
         for ( int i=CSLCount( papszExtraDimNames )-1; i>=0; i-- ) {
-            sprintf( szTemp, "NETCDF_DIM_%s_VALUES", papszExtraDimNames[i] );
+            char szTemp[ NC_MAX_NAME + 32 + 1 ];
+            snprintf( szTemp, sizeof(szTemp), "NETCDF_DIM_%s_VALUES", papszExtraDimNames[i] );
             if ( poSrcDS->GetMetadataItem( szTemp ) != NULL ) {
-                NCDFPut1DVar( poDS->cdfid, panDimVarIds[i], 
+                NCDFPut1DVar( poDS->cdfid, panDimVarIds[i],
                               poSrcDS->GetMetadataItem( szTemp ) );
             }
         }
@@ -5517,56 +6885,57 @@ netCDFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      Define Bands                                                    */
 /* -------------------------------------------------------------------- */
 
-    for( iBand=1; iBand <= nBands; iBand++ ) {
+    netCDFRasterBand *poBand = NULL;
+    int nBandID = -1;
+
+    for( int iBand=1; iBand <= nBands; iBand++ ) {
         CPLDebug( "GDAL_netCDF", "creating band # %d/%d nDim = %d",
                   iBand, nBands, nDim );
 
-        char szBandName[ NC_MAX_NAME+1 ];
-        char szLongName[ NC_MAX_NAME+1 ];
-        const char *tmpMetadata;
-        int bSignedData = TRUE;
-        int  bNoDataSet;
-        double dfNoDataValue;
-
         poSrcBand = poSrcDS->GetRasterBand( iBand );
         eDT = poSrcBand->GetRasterDataType();
 
         /* Get var name from NETCDF_VARNAME */
-        tmpMetadata = poSrcBand->GetMetadataItem("NETCDF_VARNAME");
-       	if( tmpMetadata != NULL) {
-            if( nBands > 1 && papszExtraDimNames == NULL ) 
-                sprintf(szBandName,"%s%d",tmpMetadata,iBand);
-            else strcpy( szBandName, tmpMetadata );
+        const char *tmpMetadata = poSrcBand->GetMetadataItem("NETCDF_VARNAME");
+        char szBandName[ NC_MAX_NAME+1 ];
+        if( tmpMetadata != NULL)
+        {
+            if( nBands > 1 && papszExtraDimNames == NULL )
+                snprintf(szBandName,sizeof(szBandName),"%s%d",tmpMetadata,iBand);
+            else
+                snprintf(szBandName,sizeof(szBandName),"%s",tmpMetadata);
         }
-        else 
+        else
             szBandName[0]='\0';
-        
+
         /* Get long_name from <var>#long_name */
-        sprintf(szLongName,"%s#%s",
+        char szLongName[ NC_MAX_NAME+1 ];
+        snprintf(szLongName, sizeof(szLongName),"%s#%s",
                 poSrcBand->GetMetadataItem("NETCDF_VARNAME"),
                 CF_LNG_NAME);
         tmpMetadata = poSrcDS->GetMetadataItem(szLongName);
-        if( tmpMetadata != NULL) 
-            strcpy( szLongName, tmpMetadata);
-        else 
+        if( tmpMetadata != NULL)
+            snprintf( szLongName, sizeof(szLongName), "%s", tmpMetadata);
+        else
             szLongName[0]='\0';
 
+        bool bSignedData = true;
         if ( eDT == GDT_Byte ) {
             /* GDAL defaults to unsigned bytes, but check if metadata says its
                signed, as NetCDF can support this for certain formats. */
-            bSignedData = FALSE;
+            bSignedData = false;
             tmpMetadata = poSrcBand->GetMetadataItem("PIXELTYPE",
                                                      "IMAGE_STRUCTURE");
             if ( tmpMetadata && EQUAL(tmpMetadata,"SIGNEDBYTE") )
-                bSignedData = TRUE;
+                bSignedData = true;
         }
 
         if ( nDim > 2 )
             poBand = new netCDFRasterBand( poDS, eDT, iBand,
                                            bSignedData,
                                            szBandName, szLongName,
-                                           nBandID, nDim, iBand-1,  
-                                           panBandZLev, panBandDimPos, 
+                                           nBandID, nDim, iBand-1,
+                                           panBandZLev, panBandDimPos,
                                            panDimIds );
         else
             poBand = new netCDFRasterBand( poDS, eDT, iBand,
@@ -5574,44 +6943,45 @@ netCDFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                                            szBandName, szLongName );
 
         poDS->SetBand( iBand, poBand );
-        
+
         /* set nodata value, if any */
         // poBand->SetNoDataValue( poSrcBand->GetNoDataValue(0) );
-        dfNoDataValue = poSrcBand->GetNoDataValue( &bNoDataSet );
+        int bNoDataSet;
+        double dfNoDataValue = poSrcBand->GetNoDataValue( &bNoDataSet );
         if ( bNoDataSet ) {
             CPLDebug( "GDAL_netCDF", "SetNoDataValue(%f) source", dfNoDataValue );
             poBand->SetNoDataValue( dfNoDataValue );
         }
 
         /* Copy Metadata for band */
-        CopyMetadata( (void *) GDALGetRasterBand( poSrcDS, iBand ), 
+        CopyMetadata( (void *) GDALGetRasterBand( poSrcDS, iBand ),
                       poDS->cdfid, poBand->nZId );
 
         /* if more than 2D pass the first band's netcdf var ID to subsequent bands */
         if ( nDim > 2 )
             nBandID = poBand->nZId;
     }
-    
+
     /* write projection variable to band variable */
     poDS->AddGridMappingRef();
 
     pfnProgress( 0.5, NULL, pProgressData );
 
-    
 /* -------------------------------------------------------------------- */
 /*      Write Bands                                                     */
 /* -------------------------------------------------------------------- */
     /* make sure we are in data mode */
-    poDS->SetDefineMode( FALSE );
+    poDS->SetDefineMode( false );
 
-    dfTemp = dfTemp2 = 0.5;
+    double dfTemp = 0.5;
+    double dfTemp2 = 0.5;
 
     eErr = CE_None;
+    GDALRasterBand *poDstBand = NULL;
 
-    for( iBand=1; iBand <= nBands && eErr == CE_None; iBand++ ) {
-        
-        dfTemp2 = dfTemp + 0.4/nBands; 
-        pScaledProgress = 
+    for( int iBand=1; iBand <= nBands && eErr == CE_None; iBand++ ) {
+        dfTemp2 = dfTemp + 0.4/nBands;
+        pScaledProgress =
             GDALCreateScaledProgress( dfTemp, dfTemp2,
                                       pfnProgress, pProgressData );
         dfTemp = dfTemp2;
@@ -5621,9 +6991,8 @@ netCDFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
         poSrcBand = poSrcDS->GetRasterBand( iBand );
         eDT = poSrcBand->GetRasterDataType();
-        
-        poDstBand = poDS->GetRasterBand( iBand );
 
+        poDstBand = poDS->GetRasterBand( iBand );
 
 /* -------------------------------------------------------------------- */
 /*      Copy Band data                                                  */
@@ -5632,12 +7001,12 @@ netCDFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             CPLDebug( "GDAL_netCDF", "GByte Band#%d", iBand );
             eErr = NCDFCopyBand<GByte>( poSrcBand, poDstBand, nXSize, nYSize,
                                  GDALScaledProgress, pScaledProgress );
-        } 
+        }
         else if( ( eDT == GDT_UInt16 ) || ( eDT == GDT_Int16 ) ) {
             CPLDebug( "GDAL_netCDF", "GInt16 Band#%d", iBand );
             eErr = NCDFCopyBand<GInt16>( poSrcBand, poDstBand, nXSize, nYSize,
                                  GDALScaledProgress, pScaledProgress );
-        } 
+        }
         else if( (eDT == GDT_UInt32) || (eDT == GDT_Int32) ) {
             CPLDebug( "GDAL_netCDF", "GInt16 Band#%d", iBand );
             eErr = NCDFCopyBand<GInt32>( poSrcBand, poDstBand, nXSize, nYSize,
@@ -5658,7 +7027,7 @@ netCDFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                       "The NetCDF driver does not support GDAL data type %d",
                       eDT );
         }
-        
+
         GDALDestroyScaledProgress( pScaledProgress );
     }
 
@@ -5666,16 +7035,11 @@ netCDFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      Cleanup and close.                                              */
 /* -------------------------------------------------------------------- */
     delete( poDS );
-// CPLFree(pszProj4Defn );
- 
-    if ( panDimIds )
-        CPLFree( panDimIds );
-    if( panBandDimPos )
-        CPLFree( panBandDimPos );
-    if ( panBandZLev )
-        CPLFree( panBandZLev );
-    if( panDimVarIds )
-        CPLFree( panDimVarIds );
+
+    CPLFree( panDimIds );
+    CPLFree( panBandDimPos );
+    CPLFree( panBandZLev );
+    CPLFree( panDimVarIds );
     if ( papszExtraDimNames )
         CSLDestroy( papszExtraDimNames );
 
@@ -5687,14 +7051,15 @@ netCDFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Re-open dataset so we can return it.                            */
 /* -------------------------------------------------------------------- */
-    poDS = (netCDFDataset *) GDALOpen( pszFilename, GA_ReadOnly );
+    poDS = reinterpret_cast<netCDFDataset *>(
+        GDALOpen( pszFilename, GA_ReadOnly ) );
 
 /* -------------------------------------------------------------------- */
 /*      PAM cloning is disabled. See bug #4244.                         */
 /* -------------------------------------------------------------------- */
     // if( poDS )
     //     poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
-    
+
     pfnProgress( 1.0, NULL, pProgressData );
 
     return poDS;
@@ -5704,32 +7069,48 @@ netCDFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* which may not be known when Create() is called, see AddProjectionVars() */
 void
 netCDFDataset::ProcessCreationOptions( )
-{ 
-    const char *pszValue;
+{
+    const char* pszConfig = CSLFetchNameValue( papszCreationOptions, "CONFIG_FILE" );
+    if( pszConfig != NULL )
+    {
+        if( oWriterConfig.Parse(pszConfig) )
+        {
+            // Override dataset creation options from the config file
+            std::map<CPLString,CPLString>::iterator oIter;
+            for( oIter = oWriterConfig.m_oDatasetCreationOptions.begin();
+                 oIter != oWriterConfig.m_oDatasetCreationOptions.end();
+                 ++ oIter )
+            {
+                papszCreationOptions = CSLSetNameValue(papszCreationOptions,
+                                                       oIter->first,
+                                                       oIter->second);
+            }
+        }
+    }
 
     /* File format */
-    nFormat = NCDF_FORMAT_NC;
-    pszValue = CSLFetchNameValue( papszCreationOptions, "FORMAT" );
+    eFormat = NCDF_FORMAT_NC;
+    const char *pszValue = CSLFetchNameValue( papszCreationOptions, "FORMAT" );
     if ( pszValue != NULL ) {
         if ( EQUAL( pszValue, "NC" ) ) {
-            nFormat = NCDF_FORMAT_NC;
+            eFormat = NCDF_FORMAT_NC;
         }
 #ifdef NETCDF_HAS_NC2
         else if ( EQUAL( pszValue, "NC2" ) ) {
-            nFormat = NCDF_FORMAT_NC2;
+            eFormat = NCDF_FORMAT_NC2;
         }
 #endif
 #ifdef NETCDF_HAS_NC4
         else if ( EQUAL( pszValue, "NC4" ) ) {
-            nFormat = NCDF_FORMAT_NC4;
-        }    
+            eFormat = NCDF_FORMAT_NC4;
+        }
         else if ( EQUAL( pszValue, "NC4C" ) ) {
-            nFormat = NCDF_FORMAT_NC4C;
-        }    
+            eFormat = NCDF_FORMAT_NC4C;
+        }
 #endif
         else {
             CPLError( CE_Failure, CPLE_NotSupported,
-                      "FORMAT=%s in not supported, using the default NC format.", pszValue );        
+                      "FORMAT=%s in not supported, using the default NC format.", pszValue );
         }
     }
 
@@ -5740,14 +7121,14 @@ netCDFDataset::ProcessCreationOptions( )
     pszValue = CSLFetchNameValue( papszCreationOptions, "COMPRESS" );
     if ( pszValue != NULL ) {
         if ( EQUAL( pszValue, "NONE" ) ) {
-            nCompress = NCDF_COMPRESS_NONE;
-        }       
+            eCompress = NCDF_COMPRESS_NONE;
+        }
         else if ( EQUAL( pszValue, "DEFLATE" ) ) {
-            nCompress = NCDF_COMPRESS_DEFLATE;
-            if ( !((nFormat == NCDF_FORMAT_NC4) || (nFormat == NCDF_FORMAT_NC4C)) ) {
+            eCompress = NCDF_COMPRESS_DEFLATE;
+            if ( !((eFormat == NCDF_FORMAT_NC4) || (eFormat == NCDF_FORMAT_NC4C)) ) {
                 CPLError( CE_Warning, CPLE_IllegalArg,
                           "NOTICE: Format set to NC4C because compression is set to DEFLATE." );
-                nFormat = NCDF_FORMAT_NC4C;
+                eFormat = NCDF_FORMAT_NC4C;
             }
         }
         else {
@@ -5763,7 +7144,7 @@ netCDFDataset::ProcessCreationOptions( )
         nZLevel =  atoi( pszValue );
         if (!(nZLevel >= 1 && nZLevel <= 9))
         {
-            CPLError( CE_Warning, CPLE_IllegalArg, 
+            CPLError( CE_Warning, CPLE_IllegalArg,
                     "ZLEVEL=%s value not recognised, ignoring.",
                     pszValue );
             nZLevel = NCDF_DEFLATE_LEVEL;
@@ -5771,12 +7152,40 @@ netCDFDataset::ProcessCreationOptions( )
     }
 
     /* CHUNKING option */
-    bChunking = CSLFetchBoolean( papszCreationOptions, "CHUNKING", TRUE );
+    bChunking = CPL_TO_BOOL(CSLFetchBoolean( papszCreationOptions, "CHUNKING", TRUE ));
+
+#endif
 
+    /* MULTIPLE_LAYERS option */
+    const char* pszMultipleLayerBehaviour = CSLFetchNameValueDef(
+                            papszCreationOptions, "MULTIPLE_LAYERS", "NO");
+    if( EQUAL(pszMultipleLayerBehaviour, "NO") )
+        eMultipleLayerBehaviour = SINGLE_LAYER;
+    else if( EQUAL(pszMultipleLayerBehaviour, "SEPARATE_FILES") )
+        eMultipleLayerBehaviour = SEPARATE_FILES;
+#ifdef NETCDF_HAS_NC4
+    else if( EQUAL(pszMultipleLayerBehaviour, "SEPARATE_GROUPS") )
+    {
+        if( eFormat == NCDF_FORMAT_NC4 )
+        {
+            eMultipleLayerBehaviour = SEPARATE_GROUPS;
+        }
+        else
+        {
+            CPLError( CE_Warning, CPLE_IllegalArg,
+                      "MULTIPLE_LAYERS=%s is recognised only with FORMAT=NC4",
+                      pszMultipleLayerBehaviour );
+        }
+    }
 #endif
+    else
+    {
+        CPLError( CE_Warning, CPLE_IllegalArg, "MULTIPLE_LAYERS=%s not recognised",
+                  pszMultipleLayerBehaviour );
+    }
 
-    /* set nCreateMode based on nFormat */
-    switch ( nFormat ) {        
+    /* set nCreateMode based on eFormat */
+    switch ( eFormat ) {
 #ifdef NETCDF_HAS_NC2
         case NCDF_FORMAT_NC2:
             nCreateMode = NC_CLOBBER|NC_64BIT_OFFSET;
@@ -5796,61 +7205,62 @@ netCDFDataset::ProcessCreationOptions( )
             break;
     }
 
-    CPLDebug( "GDAL_netCDF", 
+    CPLDebug( "GDAL_netCDF",
               "file options: format=%d compress=%d zlevel=%d",
-              nFormat, nCompress, nZLevel );
-
+              eFormat, eCompress, nZLevel );
 }
 
 int netCDFDataset::DefVarDeflate(
 #ifdef NETCDF_HAS_NC4
-            int nVarId, int bChunkingArg
+            int nVarId, bool bChunkingArg
 #else
-            CPL_UNUSED int nVarId, CPL_UNUSED int bChunkingArg
+            int /* nVarId */ , bool /* bChunkingArg */
 #endif
             )
 {
 #ifdef NETCDF_HAS_NC4
-    if ( nCompress == NCDF_COMPRESS_DEFLATE ) {                         
-        // must set chunk size to avoid huge performace hit (set bChunkingArg=TRUE)             
+    if ( eCompress == NCDF_COMPRESS_DEFLATE ) {
+        // Must set chunk size to avoid huge performance hit (set bChunkingArg=TRUE)
         // perhaps another solution it to change the chunk cache?
-        // http://www.unidata.ucar.edu/software/netcdf/docs/netcdf.html#Chunk-Cache   
-        // TODO make sure this is ok
-        CPLDebug( "GDAL_netCDF", 
+        // http://www.unidata.ucar.edu/software/netcdf/docs/netcdf.html#Chunk-Cache
+        // TODO: make sure this is okay.
+        CPLDebug( "GDAL_netCDF",
                   "DefVarDeflate( %d, %d ) nZlevel=%d",
-                  nVarId, bChunkingArg, nZLevel );
+                  nVarId, static_cast<int>(bChunkingArg), nZLevel );
 
-        status = nc_def_var_deflate(cdfid,nVarId,1,1,nZLevel);
+        int status = nc_def_var_deflate(cdfid,nVarId,1,1,nZLevel);
         NCDF_ERR(status);
 
         if ( (status == NC_NOERR) && bChunkingArg && bChunking ) {
 
             // set chunking to be 1 for all dims, except X dim
-            // size_t chunksize[] = { 1, (size_t)nRasterXSize };                   
+            // size_t chunksize[] = { 1, (size_t)nRasterXSize };
             size_t chunksize[ MAX_NC_DIMS ];
             int nd;
             nc_inq_varndims( cdfid, nVarId, &nd );
-            for( int i=0; i<nd; i++ ) chunksize[i] = (size_t)1;
+            chunksize[0] = (size_t)1;
+            chunksize[1] = (size_t)1;
+            for( int i=2; i<nd; i++ ) chunksize[i] = (size_t)1;
             chunksize[nd-1] = (size_t)nRasterXSize;
 
-            CPLDebug( "GDAL_netCDF", 
+            CPLDebug( "GDAL_netCDF",
                       "DefVarDeflate() chunksize={%ld, %ld} chunkX=%ld nd=%d",
                       (long)chunksize[0], (long)chunksize[1], (long)chunksize[nd-1], nd );
 #ifdef NCDF_DEBUG
-            for( int i=0; i<nd; i++ ) 
+            for( int i=0; i<nd; i++ )
                 CPLDebug( "GDAL_netCDF","DefVarDeflate() chunk[%d]=%ld", i, chunksize[i] );
 #endif
 
-            status = nc_def_var_chunking( cdfid, nVarId,          
+            status = nc_def_var_chunking( cdfid, nVarId,
                                           NC_CHUNKED, chunksize );
             NCDF_ERR(status);
         }
         else {
-            CPLDebug( "GDAL_netCDF", 
+            CPLDebug( "GDAL_netCDF",
                       "chunksize not set" );
         }
         return status;
-    } 
+    }
 #endif
     return NC_NOERR;
 }
@@ -5873,20 +7283,26 @@ static void NCDFUnloadDriver(CPL_UNUSED GDALDriver* poDriver)
 void GDALRegister_netCDF()
 
 {
-    if (! GDAL_CHECK_VERSION("netCDF driver"))
+    if( !GDAL_CHECK_VERSION( "netCDF driver" ) )
         return;
 
-    if( GDALGetDriverByName( "netCDF" ) == NULL )
-    {
-        GDALDriver	*poDriver;
-        char szCreateOptions[3072];
+    if( GDALGetDriverByName( "netCDF" ) != NULL )
+        return;
 
-        poDriver = new GDALDriver( );
+    GDALDriver *poDriver = new GDALDriver( );
 
 /* -------------------------------------------------------------------- */
-/*      Build full creation option list.                                */
+/*      Set the driver details.                                         */
 /* -------------------------------------------------------------------- */
-    sprintf( szCreateOptions, "%s", 
+    poDriver->SetDescription( "netCDF" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Network Common Data Format" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_netcdf.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "nc" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "   <Option name='FORMAT' type='string-select' default='NC'>"
 "     <Value>NC</Value>"
@@ -5922,53 +7338,79 @@ void GDALRegister_netCDF()
 "       <Value>DEFAULT</Value>"
 "       <Value>SIGNEDBYTE</Value>"
 "   </Option>"
-"   <Option name='CHUNKING' type='boolean' default='YES' description='define chunking when creating netcdf4 file'>"
+"   <Option name='CHUNKING' type='boolean' default='YES' description='define chunking when creating netcdf4 file'/>"
+"   <Option name='MULTIPLE_LAYERS' type='string-select' description='Behaviour regarding multiple vector layer creation' default='NO'>"
+"       <Value>NO</Value>"
+"       <Value>SEPARATE_FILES</Value>"
+#ifdef NETCDF_HAS_NC4
+"       <Value>SEPARATE_GROUPS</Value>"
+#endif
 "   </Option>"
-"</CreationOptionList>" );
-
-        
-/* -------------------------------------------------------------------- */
-/*      Set the driver details.                                         */
-/* -------------------------------------------------------------------- */
-        poDriver->SetDescription( "netCDF" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Network Common Data Format" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_netcdf.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "nc" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
-                                   szCreateOptions );
-        poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
-
-        /* make driver config and capabilities available */
-        poDriver->SetMetadataItem( "NETCDF_VERSION", nc_inq_libvers() );
-        poDriver->SetMetadataItem( "NETCDF_CONVENTIONS", NCDF_CONVENTIONS_CF );
+"   <Option name='CONFIG_FILE' type='string' description='Path to a XML configuration file (or content inlined)'/>"
+"</CreationOptionList>"
+                               );
+    poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
+
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+"<LayerCreationOptionList>"
+"   <Option name='RECORD_DIM_NAME' type='string' description='Name of the unlimited dimension' default='record'/>"
+"   <Option name='STRING_DEFAULT_WIDTH' type='int' description='"
+#ifdef NETCDF_HAS_NC4
+"For non-NC4 format, "
+#endif
+"default width of strings. Default is 10 in autogrow mode, 80 otherwise.'/>"
+"   <Option name='WKT_DEFAULT_WIDTH' type='int' description='"
+#ifdef NETCDF_HAS_NC4
+"For non-NC4 format, "
+#endif
+"default width of WKT strings. Default is 1000 in autogrow mode, 10000 otherwise.'/>"
+"   <Option name='AUTOGROW_STRINGS' type='boolean' description='Whether to auto-grow non-bounded string fields of bidimensional char variable' default='YES'/>"
+#ifdef NETCDF_HAS_NC4
+"   <Option name='USE_STRING_IN_NC4' type='boolean' description='Whether to use NetCDF string type for strings in NC4 format. If NO, bidimensional char variable are used' default='YES'/>"
+#if 0
+"   <Option name='NCDUMP_COMPAT' type='boolean' description='When USE_STRING_IN_NC4=YEs, whether to use empty string instead of null string to avoid crashes with ncdump' default='NO'/>"
+#endif
+#endif
+"   <Option name='FEATURE_TYPE' type='string-select' description='CF FeatureType' default='AUTO'>"
+"       <Value>AUTO</Value>"
+"       <Value>POINT</Value>"
+"       <Value>PROFILE</Value>"
+"   </Option>"
+"   <Option name='PROFILE_DIM_NAME' type='string' description='Name of the profile dimension and variable' default='profile'/>"
+"   <Option name='PROFILE_DIM_INIT_SIZE' type='string' description='Initial size of profile dimension (default 100), or UNLIMITED for NC4 files'/>"
+"   <Option name='PROFILE_VARIABLES' type='string' description='Comma separated list of field names that must be indexed by the profile dimension'/>"
+"</LayerCreationOptionList>" );
+
+    /* make driver config and capabilities available */
+    poDriver->SetMetadataItem( "NETCDF_VERSION", nc_inq_libvers() );
+    poDriver->SetMetadataItem( "NETCDF_CONVENTIONS", NCDF_CONVENTIONS_CF_V1_5 );
 #ifdef NETCDF_HAS_NC2
-        poDriver->SetMetadataItem( "NETCDF_HAS_NC2", "YES" );
+    poDriver->SetMetadataItem( "NETCDF_HAS_NC2", "YES" );
 #endif
 #ifdef NETCDF_HAS_NC4
-        poDriver->SetMetadataItem( "NETCDF_HAS_NC4", "YES" );
+    poDriver->SetMetadataItem( "NETCDF_HAS_NC4", "YES" );
 #endif
 #ifdef NETCDF_HAS_HDF4
-        poDriver->SetMetadataItem( "NETCDF_HAS_HDF4", "YES" );
+    poDriver->SetMetadataItem( "NETCDF_HAS_HDF4", "YES" );
 #endif
 #ifdef HAVE_HDF4
-        poDriver->SetMetadataItem( "GDAL_HAS_HDF4", "YES" );
+    poDriver->SetMetadataItem( "GDAL_HAS_HDF4", "YES" );
 #endif
 #ifdef HAVE_HDF5
-        poDriver->SetMetadataItem( "GDAL_HAS_HDF5", "YES" );
+    poDriver->SetMetadataItem( "GDAL_HAS_HDF5", "YES" );
 #endif
- 
-        /* set pfns and register driver */
-        poDriver->pfnOpen = netCDFDataset::Open;
-        poDriver->pfnCreateCopy = netCDFDataset::CreateCopy;
-        poDriver->pfnCreate = netCDFDataset::Create;
-        poDriver->pfnIdentify = netCDFDataset::Identify;
-        poDriver->pfnUnloadDriver = NCDFUnloadDriver;
 
-        GetGDALDriverManager( )->RegisterDriver( poDriver );
-    }
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
+                               "Integer Integer64 Real String Date DateTime" );
+
+    /* set pfns and register driver */
+    poDriver->pfnOpen = netCDFDataset::Open;
+    poDriver->pfnCreateCopy = netCDFDataset::CreateCopy;
+    poDriver->pfnCreate = netCDFDataset::Create;
+    poDriver->pfnIdentify = netCDFDataset::Identify;
+    poDriver->pfnUnloadDriver = NCDFUnloadDriver;
+
+    GetGDALDriverManager( )->RegisterDriver( poDriver );
 
 #ifdef NETCDF_PLUGIN
     GDALRegister_GMT();
@@ -5980,134 +7422,128 @@ void GDALRegister_netCDF()
 /************************************************************************/
 
 /* Test for GDAL version string >= target */
-int NCDFIsGDALVersionGTE(const char* pszVersion, int nTarget)
+static bool NCDFIsGDALVersionGTE(const char* pszVersion, int nTarget)
 {
-    int nVersion = 0;
-    int nVersions [] = {0,0,0,0};
-    char **papszTokens;
 
     /* Valid strings are "GDAL 1.9dev, released 2011/01/18" and "GDAL 1.8.1 " */
     if ( pszVersion == NULL || EQUAL( pszVersion, "" ) )
-        return FALSE;
-    else if ( ! EQUALN("GDAL ", pszVersion, 5) )
-        return FALSE;
+        return false;
+    else if ( ! STARTS_WITH_CI(pszVersion, "GDAL ") )
+        return false;
     /* 2.0dev of 2011/12/29 has been later renamed as 1.10dev */
     else if ( EQUAL("GDAL 2.0dev, released 2011/12/29", pszVersion) )
         return nTarget <= GDAL_COMPUTE_VERSION(1,10,0);
-    else if ( EQUALN("GDAL 1.9dev", pszVersion,11 ) )
+    else if ( STARTS_WITH_CI(pszVersion, "GDAL 1.9dev") )
         return nTarget <= 1900;
-    else if ( EQUALN("GDAL 1.8dev", pszVersion,11 ) )
+    else if ( STARTS_WITH_CI(pszVersion, "GDAL 1.8dev") )
         return nTarget <= 1800;
 
-    papszTokens = CSLTokenizeString2( pszVersion+5, ".", 0 );
+    char **papszTokens = CSLTokenizeString2( pszVersion+5, ".", 0 );
 
+    int nVersions [] = {0, 0, 0, 0};
     for ( int iToken = 0; papszTokens && iToken < 4 && papszTokens[iToken]; iToken++ )  {
         nVersions[iToken] = atoi( papszTokens[iToken] );
     }
+
+    int nVersion = 0;
     if( nVersions[0] > 1 || nVersions[1] >= 10 )
         nVersion = GDAL_COMPUTE_VERSION( nVersions[0], nVersions[1], nVersions[2] );
     else
-        nVersion = nVersions[0]*1000 + nVersions[1]*100 + 
-            nVersions[2]*10 + nVersions[3]; 
-    
+        nVersion = nVersions[0]*1000 + nVersions[1]*100 +
+            nVersions[2]*10 + nVersions[3];
+
     CSLDestroy( papszTokens );
     return nTarget <= nVersion;
 }
 
-/* Add Conventions, GDAL version and history  */ 
-void NCDFAddGDALHistory( int fpImage, 
+/* Add Conventions, GDAL version and history  */
+static void NCDFAddGDALHistory( int fpImage,
                          const char * pszFilename, const char *pszOldHist,
-                         const char * pszFunctionName)
+                         const char * pszFunctionName,
+                                const char * pszCFVersion )
 {
-    char     szTemp[NC_MAX_NAME+1];
-
-    nc_put_att_text( fpImage, NC_GLOBAL, "Conventions", 
-                     strlen(NCDF_CONVENTIONS_CF),
-                     NCDF_CONVENTIONS_CF ); 
+    int status = nc_put_att_text( fpImage, NC_GLOBAL, "Conventions",
+                     strlen(pszCFVersion),
+                     pszCFVersion );
+    NCDF_ERR(status);
 
     const char* pszNCDF_GDAL = GDALVersionInfo("--version");
-    nc_put_att_text( fpImage, NC_GLOBAL, "GDAL", 
+    status = nc_put_att_text( fpImage, NC_GLOBAL, "GDAL",
                      strlen(pszNCDF_GDAL), pszNCDF_GDAL );
+    NCDF_ERR(status);
 
     /* Add history */
+    CPLString osTmp;
 #ifdef GDAL_SET_CMD_LINE_DEFINED_TMP
     if ( ! EQUAL(GDALGetCmdLine(), "" ) )
-        strcpy( szTemp, GDALGetCmdLine() );
+        osTmp = GDALGetCmdLine();
     else
-        sprintf( szTemp, "GDAL %s( %s, ... )",pszFunctionName,pszFilename );
+        osTmp = CPLSPrintf("GDAL %s( %s, ... )",pszFunctionName,pszFilename );
 #else
-    sprintf( szTemp, "GDAL %s( %s, ... )",pszFunctionName,pszFilename );
+    osTmp = CPLSPrintf("GDAL %s( %s, ... )",pszFunctionName,pszFilename );
 #endif
-    
-    NCDFAddHistory( fpImage, szTemp, pszOldHist );
 
+    NCDFAddHistory( fpImage, osTmp.c_str(), pszOldHist );
 }
 
 /* code taken from cdo and libcdi, used for writing the history attribute */
 //void cdoDefHistory(int fileID, char *histstring)
-void NCDFAddHistory(int fpImage, const char *pszAddHist, const char *pszOldHist)
+static void NCDFAddHistory(int fpImage, const char *pszAddHist, const char *pszOldHist)
 {
-    char strtime[32];
-    time_t tp;
-    struct tm *ltime;
-
-    char *pszNewHist = NULL;
-    size_t nNewHistSize = 0;
-    int disableHistory = FALSE;
-    int status;
-
     /* Check pszOldHist - as if there was no previous history, it will be
        a null pointer - if so set as empty. */
     if (NULL == pszOldHist) {
         pszOldHist = "";
     }
 
-    tp = time(NULL);
+    char strtime[32];
+    strtime[0] = '\0';
+
+    time_t tp = time(NULL);
     if ( tp != -1 )
     {
-        ltime = localtime(&tp);
+        struct tm *ltime = localtime(&tp);
         (void) strftime(strtime, sizeof(strtime), "%a %b %d %H:%M:%S %Y: ", ltime);
     }
 
-    // status = nc_get_att_text( fpImage, NC_GLOBAL, 
+    // status = nc_get_att_text( fpImage, NC_GLOBAL,
     //                           "history", pszOldHist );
     // printf("status: %d pszOldHist: [%s]\n",status,pszOldHist);
-    
-    nNewHistSize = strlen(pszOldHist)+strlen(strtime)+strlen(pszAddHist)+1+1;
-    pszNewHist = (char *) CPLMalloc(nNewHistSize * sizeof(char));
-    
+
+    size_t nNewHistSize
+        = strlen(pszOldHist)+strlen(strtime)+strlen(pszAddHist)+1+1;
+    char *pszNewHist
+        = reinterpret_cast<char *>( CPLMalloc(nNewHistSize * sizeof(char)) );
+
     strcpy(pszNewHist, strtime);
     strcat(pszNewHist, pszAddHist);
 
-    if ( disableHistory == FALSE && pszNewHist )
+    // int disableHistory = FALSE;
+    //if ( !disableHistory )
     {
         if ( ! EQUAL(pszOldHist,"") )
             strcat(pszNewHist, "\n");
         strcat(pszNewHist, pszOldHist);
     }
 
-    status = nc_put_att_text( fpImage, NC_GLOBAL, 
-                              "history", strlen(pszNewHist),
-                              pszNewHist ); 
+    int status = nc_put_att_text( fpImage, NC_GLOBAL,
+                                  "history", strlen(pszNewHist),
+                                  pszNewHist );
     NCDF_ERR(status);
 
     CPLFree(pszNewHist);
 }
 
-
-int NCDFIsCfProjection( const char* pszProjection ) 
+static bool NCDFIsCfProjection( const char* pszProjection )
 {
     /* Find the appropriate mapping */
     for (int iMap = 0; poNetcdfSRS_PT[iMap].WKT_SRS != NULL; iMap++ ) {
         // printf("now at %d, proj=%s\n",i, poNetcdfSRS_PT[i].GDAL_SRS);
         if ( EQUAL( pszProjection, poNetcdfSRS_PT[iMap].WKT_SRS ) )  {
-            if ( poNetcdfSRS_PT[iMap].mappings != NULL )
-                return TRUE;            
-            else 
-                return FALSE;
+            return poNetcdfSRS_PT[iMap].mappings != NULL;
         }
     }
-    return FALSE;
+    return false;
 }
 
 
@@ -6122,34 +7558,20 @@ int NCDFIsCfProjection( const char* pszProjection )
  * the generic mapping is used.  In the case of specific mappings,
  * the driver looks for each attribute listed in the mapping object
  * and then looks up the value within the OGR_SRSNode. In the case
- * of the generic mapping, the lookup is reversed (projection params, 
- * then mapping).  For more generic code, GDAL->NETCDF 
+ * of the generic mapping, the lookup is reversed (projection params,
+ * then mapping).  For more generic code, GDAL->NETCDF
  * mappings and the associated value are saved in std::map objects.
  */
 
 /* NOTE modifications by ET to combine the specific and generic mappings */
 
-void NCDFWriteProjAttribs( const OGR_SRSNode *poPROJCS,
+static void NCDFWriteProjAttribs( const OGR_SRSNode *poPROJCS,
                            const char* pszProjection,
-                           const int fpImage, const int NCDFVarID ) 
-{                            
-    double dfStdP[2];
-    int bFoundStdP1=FALSE,bFoundStdP2=FALSE;
-    double dfValue=0.0;
-    const char *pszParamStr, *pszParamVal;
-    const std::string *pszNCDFAtt, *pszGDALAtt;
-    static const oNetcdfSRS_PP *poMap = NULL;
+                           const int fpImage, const int NCDFVarID )
+{
+    const oNetcdfSRS_PP *poMap = NULL;
     int nMapIndex = -1;
-    int bWriteVal = FALSE;
 
-    //Attribute <GDAL,NCDF> and Value <NCDF,value> mappings
-    std::map< std::string, std::string > oAttMap;
-    std::map< std::string, std::string >::iterator oAttIter;
-    std::map< std::string, double > oValMap;
-    std::map< std::string, double >::iterator oValIter, oValIter2;
-    //results to write
-    std::vector< std::pair<std::string,double> > oOutList;
- 
     /* Find the appropriate mapping */
     for (int iMap = 0; poNetcdfSRS_PT[iMap].WKT_SRS != NULL; iMap++ ) {
         if ( EQUAL( pszProjection, poNetcdfSRS_PT[iMap].WKT_SRS ) ) {
@@ -6161,29 +7583,33 @@ void NCDFWriteProjAttribs( const OGR_SRSNode *poPROJCS,
 
     //ET TODO if projection name is not found, should we do something special?
     if ( nMapIndex == -1 ) {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "projection name %s not found in the lookup tables!!!",
                   pszProjection);
     }
     /* if no mapping was found or assigned, set the generic one */
     if ( !poMap ) {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "projection name %s in not part of the CF standard, will not be supported by CF!",
                   pszProjection);
         poMap = poGenericMappings;
     }
 
     /* initialize local map objects */
+
+    // Attribute <GDAL,NCDF> and Value <NCDF,value> mappings
+    std::map< std::string, std::string > oAttMap;
     for ( int iMap = 0; poMap[iMap].WKT_ATT != NULL; iMap++ ) {
         oAttMap[poMap[iMap].WKT_ATT] = poMap[iMap].CF_ATT;
     }
 
+    const char *pszParamStr;
+    const char *pszParamVal;
+    std::map< std::string, double > oValMap;
     for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ ) {
 
-        const OGR_SRSNode *poNode;
-
-        poNode = poPROJCS->GetChild( iChild );
-        if( !EQUAL(poNode->GetValue(),"PARAMETER") 
+        const OGR_SRSNode *poNode = poPROJCS->GetChild( iChild );
+        if( !EQUAL(poNode->GetValue(),"PARAMETER")
             || poNode->GetChildCount() != 2 )
             continue;
         pszParamStr = poNode->GetChild(0)->GetValue();
@@ -6192,84 +7618,94 @@ void NCDFWriteProjAttribs( const OGR_SRSNode *poPROJCS,
         oValMap[pszParamStr] = CPLAtof(pszParamVal);
     }
 
+    double dfValue = 0.0;
+    const std::string *posNCDFAtt;
+    const std::string *posGDALAtt;
+    bool bWriteVal = false;
+    std::map< std::string, std::string >::iterator oAttIter;
+    std::map< std::string, double >::iterator oValIter, oValIter2;
+
+    // Results to write.
+    std::vector< std::pair<std::string,double> > oOutList;
+
     /* Lookup mappings and fill output vector */
     if ( poMap != poGenericMappings ) { /* specific mapping, loop over mapping values */
 
         for ( oAttIter = oAttMap.begin(); oAttIter != oAttMap.end(); oAttIter++ ) {
 
-            pszGDALAtt = &(oAttIter->first);
-            pszNCDFAtt = &(oAttIter->second);
-            oValIter = oValMap.find( *pszGDALAtt );
+            posGDALAtt = &(oAttIter->first);
+            posNCDFAtt = &(oAttIter->second);
+            oValIter = oValMap.find( *posGDALAtt );
 
             if ( oValIter != oValMap.end() ) {
 
                 dfValue = oValIter->second;
-                bWriteVal = TRUE;
+                bWriteVal = true;
 
                 /* special case for PS (Polar Stereographic) grid
                    See comments in netcdfdataset.h for this projection. */
-                if ( EQUAL( SRS_PP_LATITUDE_OF_ORIGIN, pszGDALAtt->c_str() ) &&
+                if ( EQUAL( SRS_PP_LATITUDE_OF_ORIGIN, posGDALAtt->c_str() ) &&
                      EQUAL(pszProjection, SRS_PT_POLAR_STEREOGRAPHIC) ) {
                     double dfLatPole = 0.0;
                     if ( dfValue > 0.0) dfLatPole = 90.0;
                     else dfLatPole = -90.0;
-                        oOutList.push_back( std::make_pair( std::string(CF_PP_LAT_PROJ_ORIGIN), 
+                        oOutList.push_back( std::make_pair( std::string(CF_PP_LAT_PROJ_ORIGIN),
                                                             dfLatPole ) );
-                }              
+                }
 
                 /* special case for LCC-1SP
                    See comments in netcdfdataset.h for this projection. */
-                else if ( EQUAL( SRS_PP_SCALE_FACTOR, pszGDALAtt->c_str() ) &&
+                else if ( EQUAL( SRS_PP_SCALE_FACTOR, posGDALAtt->c_str() ) &&
                           EQUAL(pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP) ) {
                     /* default is to not write as it is not CF-1 */
-                    bWriteVal = FALSE;
+                    bWriteVal = false;
                     /* test if there is no standard_parallel1 */
                     if ( oValMap.find( std::string(CF_PP_STD_PARALLEL_1) ) == oValMap.end() ) {
                         /* if scale factor != 1.0  write value for GDAL, but this is not supported by CF-1 */
                         if ( !CPLIsEqual(dfValue,1.0) ) {
-                            CPLError( CE_Failure, CPLE_NotSupported, 
+                            CPLError( CE_Failure, CPLE_NotSupported,
                                       "NetCDF driver export of LCC-1SP with scale factor != 1.0 "
-                                      "and no standard_parallel1 is not CF-1 (bug #3324).\n" 
-                                      "Use the 2SP variant which is supported by CF." );   
-                            bWriteVal = TRUE;
+                                      "and no standard_parallel1 is not CF-1 (bug #3324).\n"
+                                      "Use the 2SP variant which is supported by CF." );
+                            bWriteVal = true;
                         }
                         /* else copy standard_parallel1 from latitude_of_origin, because scale_factor=1.0 */
-                        else {                      
+                        else {
                             oValIter2 = oValMap.find( std::string(SRS_PP_LATITUDE_OF_ORIGIN) );
                             if (oValIter2 != oValMap.end() ) {
-                                oOutList.push_back( std::make_pair( std::string(CF_PP_STD_PARALLEL_1), 
+                                oOutList.push_back( std::make_pair( std::string(CF_PP_STD_PARALLEL_1),
                                                                     oValIter2->second) );
                             }
                             else {
-                                CPLError( CE_Failure, CPLE_NotSupported, 
+                                CPLError( CE_Failure, CPLE_NotSupported,
                                           "NetCDF driver export of LCC-1SP with no standard_parallel1 "
-                                          "and no latitude_of_origin is not suported (bug #3324).");
+                                          "and no latitude_of_origin is not supported (bug #3324).");
                             }
-                        }                      
+                        }
                     }
                 }
                 if ( bWriteVal )
-                    oOutList.push_back( std::make_pair( *pszNCDFAtt, dfValue ) );
+                    oOutList.push_back( std::make_pair( *posNCDFAtt, dfValue ) );
 
             }
             // else printf("NOT FOUND!!!\n");
         }
-    
+
     }
     else { /* generic mapping, loop over projected values */
 
         for ( oValIter = oValMap.begin(); oValIter != oValMap.end(); oValIter++ ) {
 
-            pszGDALAtt = &(oValIter->first);
+            posGDALAtt = &(oValIter->first);
             dfValue = oValIter->second;
 
-            oAttIter = oAttMap.find( *pszGDALAtt );
+            oAttIter = oAttMap.find( *posGDALAtt );
 
             if ( oAttIter != oAttMap.end() ) {
                 oOutList.push_back( std::make_pair( oAttIter->second, dfValue ) );
             }
             /* for SRS_PP_SCALE_FACTOR write 2 mappings */
-            else if (  EQUAL(pszGDALAtt->c_str(), SRS_PP_SCALE_FACTOR) ) {
+            else if (  EQUAL(posGDALAtt->c_str(), SRS_PP_SCALE_FACTOR) ) {
                 oOutList.push_back( std::make_pair( std::string(CF_PP_SCALE_FACTOR_MERIDIAN),
                                                     dfValue ) );
                 oOutList.push_back( std::make_pair( std::string(CF_PP_SCALE_FACTOR_ORIGIN),
@@ -6277,7 +7713,7 @@ void NCDFWriteProjAttribs( const OGR_SRSNode *poPROJCS,
             }
             /* if not found insert the GDAL name */
             else {
-                oOutList.push_back( std::make_pair( *pszGDALAtt, dfValue ) );
+                oOutList.push_back( std::make_pair( *posGDALAtt, dfValue ) );
             }
         }
     }
@@ -6286,64 +7722,53 @@ void NCDFWriteProjAttribs( const OGR_SRSNode *poPROJCS,
     // std::vector< std::pair<std::string,double> >::reverse_iterator it;
     // for (it = oOutList.rbegin();  it != oOutList.rend(); it++ ) {
     std::vector< std::pair<std::string,double> >::iterator it;
+    double dfStdP[2];
+    bool bFoundStdP1 = false;
+    bool bFoundStdP2 = false;
     for (it = oOutList.begin();  it != oOutList.end(); it++ ) {
         pszParamVal = (it->first).c_str();
         dfValue = it->second;
         /* Handle the STD_PARALLEL attrib */
         if( EQUAL( pszParamVal, CF_PP_STD_PARALLEL_1 ) ) {
-            bFoundStdP1 = TRUE;
+            bFoundStdP1 = true;
             dfStdP[0] = dfValue;
         }
         else if( EQUAL( pszParamVal, CF_PP_STD_PARALLEL_2 ) ) {
-            bFoundStdP2 = TRUE;
+            bFoundStdP2 = true;
             dfStdP[1] = dfValue;
-        } 
+        }
         else {
             nc_put_att_double( fpImage, NCDFVarID, pszParamVal,
                                NC_DOUBLE, 1,&dfValue );
         }
     }
     /* Now write the STD_PARALLEL attrib */
-    if ( bFoundStdP1 ) { 
+    if ( bFoundStdP1 ) {
         /* one value or equal values */
         if ( !bFoundStdP2 || dfStdP[0] ==  dfStdP[1] ) {
-            nc_put_att_double( fpImage, NCDFVarID, CF_PP_STD_PARALLEL, 
+            nc_put_att_double( fpImage, NCDFVarID, CF_PP_STD_PARALLEL,
                                NC_DOUBLE, 1, &dfStdP[0] );
         }
         else { /* two values */
-            nc_put_att_double( fpImage, NCDFVarID, CF_PP_STD_PARALLEL, 
+            nc_put_att_double( fpImage, NCDFVarID, CF_PP_STD_PARALLEL,
                                NC_DOUBLE, 2, dfStdP );
         }
     }
 }
 
-CPLErr NCDFSafeStrcat(char** ppszDest, char* pszSrc, size_t* nDestSize)
+static CPLErr NCDFSafeStrcat(char** ppszDest, const char* pszSrc, size_t* nDestSize)
 {
     /* Reallocate the data string until the content fits */
     while(*nDestSize < (strlen(*ppszDest) + strlen(pszSrc) + 1)) {
         (*nDestSize) *= 2;
-        *ppszDest = (char*) CPLRealloc((void*) *ppszDest, *nDestSize);
+        *ppszDest = reinterpret_cast<char *>(
+            CPLRealloc( reinterpret_cast<void *>( *ppszDest ), *nDestSize) );
 #ifdef NCDF_DEBUG
         CPLDebug( "GDAL_netCDF", "NCDFSafeStrcat() resized str from %ld to %ld", (*nDestSize)/2, *nDestSize );
 #endif
     }
     strcat(*ppszDest, pszSrc);
-    
-    return CE_None;
-}
 
-CPLErr NCDFSafeStrcpy(char** ppszDest, char* pszSrc, size_t* nDestSize)
-{
-    /* Reallocate the data string until the content fits */
-    while(*nDestSize < (strlen(*ppszDest) + strlen(pszSrc) + 1)) {
-        (*nDestSize) *= 2;
-        *ppszDest = (char*) CPLRealloc((void*) *ppszDest, *nDestSize);
-#ifdef NCDF_DEBUG
-        CPLDebug( "GDAL_netCDF", "NCDFSafeStrcpy() resized str from %ld to %ld", (*nDestSize)/2, *nDestSize );
-#endif
-    }
-    strcpy(*ppszDest, pszSrc);
-    
     return CE_None;
 }
 
@@ -6351,19 +7776,13 @@ CPLErr NCDFSafeStrcpy(char** ppszDest, char* pszSrc, size_t* nDestSize)
 /* sets pdfValue to first value returned */
 /* and if bSetPszValue=True sets pszValue with all attribute values */
 /* pszValue is the responsibility of the caller and must be freed */
-CPLErr NCDFGetAttr1( int nCdfId, int nVarId, const char *pszAttrName, 
+static CPLErr NCDFGetAttr1( int nCdfId, int nVarId, const char *pszAttrName,
                      double *pdfValue, char **pszValue, int bSetPszValue )
 {
     nc_type nAttrType = NC_NAT;
     size_t  nAttrLen = 0;
-    size_t  nAttrValueSize;
-    int     status = 0; /*rename this */
-    size_t  m;
-    char    szTemp[ NCDF_MAX_STR_LEN ];
-    char    *pszAttrValue = NULL;
-    double  dfValue = 0.0;
-
-    status = nc_inq_att( nCdfId, nVarId, pszAttrName, &nAttrType, &nAttrLen);
+
+    int status = nc_inq_att( nCdfId, nVarId, pszAttrName, &nAttrType, &nAttrLen);
     if ( status != NC_NOERR )
         return CE_Failure;
 
@@ -6372,16 +7791,24 @@ CPLErr NCDFGetAttr1( int nCdfId, int nVarId, const char *pszAttrName,
 #endif
 
     /* Allocate guaranteed minimum size (use 10 or 20 if not a string) */
-    nAttrValueSize = nAttrLen + 1;
+    size_t  nAttrValueSize = nAttrLen + 1;
     if ( nAttrType != NC_CHAR && nAttrValueSize < 10 )
         nAttrValueSize = 10;
     if ( nAttrType == NC_DOUBLE && nAttrValueSize < 20 )
         nAttrValueSize = 20;
-    pszAttrValue = (char *) CPLCalloc( nAttrValueSize, sizeof( char ));
+#ifdef NETCDF_HAS_NC4
+    if ( nAttrType == NC_INT64 && nAttrValueSize < 20 )
+        nAttrValueSize = 22;
+#endif
+    char *pszAttrValue = (char *) CPLCalloc( nAttrValueSize, sizeof( char ));
     *pszAttrValue = '\0';
 
-    if ( nAttrLen > 1  && nAttrType != NC_CHAR )    
-        NCDFSafeStrcat(&pszAttrValue, (char *)"{", &nAttrValueSize);
+    if ( nAttrLen > 1 && nAttrType != NC_CHAR )
+        NCDFSafeStrcat(&pszAttrValue, "{", &nAttrValueSize);
+
+    double dfValue = 0.0;
+    size_t m;
+    char szTemp[ 256 ];
 
     switch (nAttrType) {
         case NC_CHAR:
@@ -6390,224 +7817,363 @@ CPLErr NCDFGetAttr1( int nCdfId, int nVarId, const char *pszAttrName,
             dfValue = 0.0;
             break;
         case NC_BYTE:
-            signed char *pscTemp;
-            pscTemp = (signed char *) CPLCalloc( nAttrLen, sizeof( signed char ) );
+        {
+            signed char *pscTemp
+                = reinterpret_cast<signed char *>(
+                    CPLCalloc( nAttrLen, sizeof( signed char ) ) );
             nc_get_att_schar( nCdfId, nVarId, pszAttrName, pscTemp );
-            dfValue = (double)pscTemp[0];
+            dfValue = static_cast<double>( pscTemp[0] );
             for(m=0; m < nAttrLen-1; m++) {
-                sprintf( szTemp, "%d,", pscTemp[m] );
+                snprintf( szTemp, sizeof(szTemp), "%d,", pscTemp[m] );
                 NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
             }
-            sprintf( szTemp, "%d", pscTemp[m] );
+            snprintf( szTemp, sizeof(szTemp), "%d", pscTemp[m] );
             NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
             CPLFree(pscTemp);
             break;
-#ifdef NETCDF_HAS_NC4
-        case NC_UBYTE:
-            unsigned char *pucTemp;
-            pucTemp = (unsigned char *) CPLCalloc( nAttrLen, sizeof( unsigned char ) );
-            nc_get_att_uchar( nCdfId, nVarId, pszAttrName, pucTemp );
-            dfValue = (double)pucTemp[0];
-            for(m=0; m < nAttrLen-1; m++) {
-                sprintf( szTemp, "%d,", pucTemp[m] );
-                NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
-            }
-            sprintf( szTemp, "%d", pucTemp[m] );
-            NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
-            CPLFree(pucTemp);
-            break;
-#endif
+        }
         case NC_SHORT:
-            short *psTemp;
-            psTemp = (short *) CPLCalloc( nAttrLen, sizeof( short ) );
+        {
+            short *psTemp
+                = reinterpret_cast<short *>(
+                    CPLCalloc( nAttrLen, sizeof( short ) ) );
             nc_get_att_short( nCdfId, nVarId, pszAttrName, psTemp );
-            dfValue = (double)psTemp[0];
+            dfValue = static_cast<double>( psTemp[0] );
             for(m=0; m < nAttrLen-1; m++) {
-                sprintf( szTemp, "%hd,", psTemp[m] );
+                snprintf( szTemp, sizeof(szTemp), "%d,", psTemp[m] );
                 NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
             }
-            sprintf( szTemp, "%hd", psTemp[m] );
+            snprintf( szTemp, sizeof(szTemp), "%d", psTemp[m] );
             NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
             CPLFree(psTemp);
             break;
+        }
         case NC_INT:
-            int *pnTemp;
-            pnTemp = (int *) CPLCalloc( nAttrLen, sizeof( int ) );
+        {
+            int *pnTemp
+                = static_cast<int *>( CPLCalloc( nAttrLen, sizeof( int ) ) );
             nc_get_att_int( nCdfId, nVarId, pszAttrName, pnTemp );
-            dfValue = (double)pnTemp[0];
+            dfValue = static_cast<double>( pnTemp[0] );
             for(m=0; m < nAttrLen-1; m++) {
-                sprintf( szTemp, "%d,", pnTemp[m] );
+                snprintf( szTemp, sizeof(szTemp), "%d,", pnTemp[m] );
                 NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
             }
-            sprintf( szTemp, "%d", pnTemp[m] );
+            snprintf( szTemp, sizeof(szTemp), "%d", pnTemp[m] );
             NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
             CPLFree(pnTemp);
             break;
+        }
         case NC_FLOAT:
-            float *pfTemp;
-            pfTemp = (float *) CPLCalloc( nAttrLen, sizeof( float ) );
+        {
+            float *pfTemp
+                = reinterpret_cast<float *>(
+                    CPLCalloc( nAttrLen, sizeof( float ) ) );
             nc_get_att_float( nCdfId, nVarId, pszAttrName, pfTemp );
-            dfValue = (double)pfTemp[0];
+            dfValue = static_cast<double>( pfTemp[0] );
             for(m=0; m < nAttrLen-1; m++) {
-                CPLsprintf( szTemp, "%.8g,", pfTemp[m] );
+                CPLsnprintf( szTemp, sizeof(szTemp), "%.8g,", pfTemp[m] );
                 NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
             }
-            CPLsprintf( szTemp, "%.8g", pfTemp[m] );
-            NCDFSafeStrcat(&pszAttrValue,szTemp, &nAttrValueSize);
+            CPLsnprintf( szTemp, sizeof(szTemp), "%.8g", pfTemp[m] );
+            NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
             CPLFree(pfTemp);
             break;
+        }
         case NC_DOUBLE:
-            double *pdfTemp;
-            pdfTemp = (double *) CPLCalloc(nAttrLen, sizeof(double));
+        {
+            double *pdfTemp
+                = reinterpret_cast<double *>(
+                    CPLCalloc( nAttrLen, sizeof(double) ) );
             nc_get_att_double( nCdfId, nVarId, pszAttrName, pdfTemp );
             dfValue = pdfTemp[0];
             for(m=0; m < nAttrLen-1; m++) {
-                CPLsprintf( szTemp, "%.16g,", pdfTemp[m] );
+                CPLsnprintf( szTemp, sizeof(szTemp), "%.16g,", pdfTemp[m] );
                 NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
             }
-            CPLsprintf( szTemp, "%.16g", pdfTemp[m] );
+            CPLsnprintf( szTemp, sizeof(szTemp), "%.16g", pdfTemp[m] );
             NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
             CPLFree(pdfTemp);
             break;
+        }
+#ifdef NETCDF_HAS_NC4
+        case NC_STRING:
+        {
+            char **ppszTemp
+                = reinterpret_cast<char **>(
+                    CPLCalloc( nAttrLen, sizeof( char * ) ) );
+            nc_get_att_string( nCdfId, nVarId, pszAttrName, ppszTemp );
+            dfValue = 0.0;
+            for(m=0; m < nAttrLen-1; m++) {
+                NCDFSafeStrcat(&pszAttrValue, ppszTemp[m], &nAttrValueSize);
+                NCDFSafeStrcat(&pszAttrValue, ",", &nAttrValueSize);
+            }
+            NCDFSafeStrcat(&pszAttrValue, ppszTemp[m], &nAttrValueSize);
+            nc_free_string(nAttrLen, ppszTemp);
+            CPLFree(ppszTemp);
+            break;
+        }
+        case NC_UBYTE:
+        {
+            unsigned char *pucTemp
+                = reinterpret_cast<unsigned char *>(
+                    CPLCalloc( nAttrLen, sizeof( unsigned char ) ) );
+            nc_get_att_uchar( nCdfId, nVarId, pszAttrName, pucTemp );
+            dfValue = static_cast<double>( pucTemp[0] );
+            for(m=0; m < nAttrLen-1; m++) {
+                CPLsnprintf( szTemp, sizeof(szTemp), "%u,", pucTemp[m] );
+                NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
+            }
+            CPLsnprintf( szTemp, sizeof(szTemp), "%u", pucTemp[m] );
+            NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
+            CPLFree(pucTemp);
+            break;
+        }
+        case NC_USHORT:
+        {
+            unsigned short *pusTemp;
+            pusTemp = reinterpret_cast<unsigned short *>(
+                    CPLCalloc( nAttrLen, sizeof( unsigned short ) ) );
+            nc_get_att_ushort( nCdfId, nVarId, pszAttrName, pusTemp );
+            dfValue = static_cast<double>(pusTemp[0]);
+            for(m=0; m < nAttrLen-1; m++) {
+                CPLsnprintf( szTemp, sizeof(szTemp), "%u,", pusTemp[m] );
+                NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
+            }
+            CPLsnprintf( szTemp, sizeof(szTemp), "%u", pusTemp[m] );
+            NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
+            CPLFree(pusTemp);
+            break;
+        }
+        case NC_UINT:
+        {
+            unsigned int *punTemp
+                = static_cast<unsigned int *>( CPLCalloc( nAttrLen, sizeof( int ) ) );
+            nc_get_att_uint( nCdfId, nVarId, pszAttrName, punTemp );
+            dfValue = static_cast<double>( punTemp[0] );
+            for(m=0; m < nAttrLen-1; m++) {
+                CPLsnprintf( szTemp, sizeof(szTemp), "%u,", punTemp[m] );
+                NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
+            }
+            CPLsnprintf( szTemp, sizeof(szTemp), "%u", punTemp[m] );
+            NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
+            CPLFree(punTemp);
+            break;
+        }
+        case NC_INT64:
+        {
+            GIntBig *panTemp
+                = reinterpret_cast<GIntBig *>(
+                    CPLCalloc( nAttrLen, sizeof( GIntBig ) ) );
+            nc_get_att_longlong( nCdfId, nVarId, pszAttrName, panTemp );
+            dfValue = static_cast<double>( panTemp[0] );
+            for(m=0; m < nAttrLen-1; m++) {
+                CPLsnprintf( szTemp, sizeof(szTemp), CPL_FRMT_GIB ",", panTemp[m] );
+                NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
+            }
+            CPLsnprintf( szTemp, sizeof(szTemp), CPL_FRMT_GIB, panTemp[m] );
+            NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
+            CPLFree(panTemp);
+            break;
+        }
+        case NC_UINT64:
+        {
+            GUIntBig *panTemp
+                = reinterpret_cast<GUIntBig *>(
+                    CPLCalloc( nAttrLen, sizeof( GUIntBig ) ) );
+            nc_get_att_ulonglong( nCdfId, nVarId, pszAttrName, panTemp );
+            dfValue = static_cast<double>( panTemp[0] );
+            for(m=0; m < nAttrLen-1; m++) {
+                CPLsnprintf( szTemp, sizeof(szTemp), CPL_FRMT_GUIB ",", panTemp[m] );
+                NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
+            }
+            CPLsnprintf( szTemp, sizeof(szTemp), CPL_FRMT_GUIB, panTemp[m] );
+            NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
+            CPLFree(panTemp);
+            break;
+        }
+#endif
         default:
             CPLDebug( "GDAL_netCDF", "NCDFGetAttr unsupported type %d for attribute %s",
                       nAttrType,pszAttrName);
-            CPLFree( pszAttrValue );
-            pszAttrValue = NULL;
             break;
     }
 
-    if ( nAttrLen > 1  && nAttrType!= NC_CHAR )    
-        NCDFSafeStrcat(&pszAttrValue, (char *)"}", &nAttrValueSize);
+    if ( nAttrLen > 1  && nAttrType!= NC_CHAR )
+        NCDFSafeStrcat(&pszAttrValue, "}", &nAttrValueSize);
 
     /* set return values */
-    if ( bSetPszValue == TRUE ) *pszValue = pszAttrValue;
+    if ( bSetPszValue ) *pszValue = pszAttrValue;
     else CPLFree ( pszAttrValue );
     if ( pdfValue ) *pdfValue = dfValue;
 
     return CE_None;
 }
 
-
 /* sets pdfValue to first value found */
-CPLErr NCDFGetAttr( int nCdfId, int nVarId, const char *pszAttrName, 
+CPLErr NCDFGetAttr( int nCdfId, int nVarId, const char *pszAttrName,
                     double *pdfValue )
 {
-    return NCDFGetAttr1( nCdfId, nVarId, pszAttrName, pdfValue, NULL, FALSE );
+    return NCDFGetAttr1( nCdfId, nVarId, pszAttrName, pdfValue, NULL, false );
 }
 
 
 /* pszValue is the responsibility of the caller and must be freed */
-CPLErr NCDFGetAttr( int nCdfId, int nVarId, const char *pszAttrName, 
+CPLErr NCDFGetAttr( int nCdfId, int nVarId, const char *pszAttrName,
                     char **pszValue )
 {
-    return NCDFGetAttr1( nCdfId, nVarId, pszAttrName, FALSE, pszValue, TRUE );
+    return NCDFGetAttr1( nCdfId, nVarId, pszAttrName, NULL, pszValue, true );
 }
 
 
-/* By default write NC_CHAR, but detect for int/float/double */
-CPLErr NCDFPutAttr( int nCdfId, int nVarId, 
+/* By default write NC_CHAR, but detect for int/float/double and */
+/* NC4 string arrays */
+static CPLErr NCDFPutAttr( int nCdfId, int nVarId,
                  const char *pszAttrName, const char *pszValue )
 {
-    nc_type nAttrType = NC_CHAR;
-    nc_type nTmpAttrType = NC_CHAR;
-    size_t  nAttrLen = 0;
     int     status = 0;
-    size_t  i;
-    char    szTemp[ NCDF_MAX_STR_LEN ];
     char    *pszTemp = NULL;
-    char    **papszValues = NULL;
-    
-    int     nValue = 0;
-    float   fValue = 0.0f;
-    double  dfValue = 0.0;
 
     /* get the attribute values as tokens */
-    papszValues = NCDFTokenizeArray( pszValue );
-    if ( papszValues == NULL ) 
+    char **papszValues = NCDFTokenizeArray( pszValue );
+    if ( papszValues == NULL )
         return CE_Failure;
 
-    nAttrLen = CSLCount(papszValues);
-    
+    size_t nAttrLen = CSLCount(papszValues);
+
     /* first detect type */
-    nAttrType = NC_CHAR;
-    for ( i=0; i<nAttrLen; i++ ) {
+    nc_type nAttrType = NC_CHAR;
+    nc_type nTmpAttrType = NC_CHAR;
+    for ( size_t i=0; i<nAttrLen; i++ ) {
         nTmpAttrType = NC_CHAR;
+        bool bFoundType = false;
         errno = 0;
-        nValue = strtol( papszValues[i], &pszTemp, 10 );
-        dfValue = (double) nValue;
+        int nValue = static_cast<int>(strtol( papszValues[i], &pszTemp, 10 ));
         /* test for int */
         /* TODO test for Byte and short - can this be done safely? */
         if ( (errno == 0) && (papszValues[i] != pszTemp) && (*pszTemp == 0) ) {
-            nTmpAttrType = NC_INT;
+            char    szTemp[ 256 ];
+            CPLsnprintf( szTemp, sizeof(szTemp), "%d", nValue );
+            if ( EQUAL( szTemp, papszValues[i] ) ) {
+                bFoundType = true;
+                nTmpAttrType = NC_INT;
+            }
+#ifdef NETCDF_HAS_NC4
+            else {
+                unsigned int unValue = static_cast<unsigned int>(
+                    strtoul( papszValues[i], &pszTemp, 10 ));
+                CPLsnprintf( szTemp, sizeof(szTemp), "%u", unValue );
+                if ( EQUAL( szTemp, papszValues[i] ) ) {
+                    bFoundType = true;
+                    nTmpAttrType = NC_UINT;
+                }
+            }
+#endif
         }
-        else {
+        if ( ! bFoundType ) {
             /* test for double */
             errno = 0;
-            dfValue = CPLStrtod( papszValues[i], &pszTemp );
+            double dfValue = CPLStrtod( papszValues[i], &pszTemp );
             if ( (errno == 0) && (papszValues[i] != pszTemp) && (*pszTemp == 0) ) {
                 /* test for float instead of double */
                 /* strtof() is C89, which is not available in MSVC */
                 /* see if we loose precision if we cast to float and write to char* */
-                fValue = (float)dfValue; 
-                CPLsprintf( szTemp,"%.8g",fValue); 
-                if ( EQUAL(szTemp, papszValues[i] ) )
+                float fValue = float(dfValue);
+                char    szTemp[ 256 ];
+                CPLsnprintf( szTemp, sizeof(szTemp), "%.8g", fValue );
+                if ( EQUAL( szTemp, papszValues[i] ) )
                     nTmpAttrType = NC_FLOAT;
                 else
-                    nTmpAttrType = NC_DOUBLE;                   
+                    nTmpAttrType = NC_DOUBLE;
             }
         }
-        if ( nTmpAttrType > nAttrType )
+        if ( (nTmpAttrType <= NC_DOUBLE && nAttrType <= NC_DOUBLE
+              && nTmpAttrType > nAttrType)
+#ifdef NETCDF_HAS_NC4
+             || (nTmpAttrType == NC_UINT && nAttrType < NC_FLOAT)
+             || (nTmpAttrType >= NC_FLOAT && nAttrType == NC_UINT)
+#endif
+            )
             nAttrType = nTmpAttrType;
     }
 
     /* now write the data */
     if ( nAttrType == NC_CHAR ) {
-        status = nc_put_att_text( nCdfId, nVarId, pszAttrName,
-                                  strlen( pszValue ), pszValue );
-        NCDF_ERR(status);                        
+#ifdef NETCDF_HAS_NC4
+        int nTmpFormat = 0;
+        if ( nAttrLen > 1 ) {
+            status = nc_inq_format( nCdfId, &nTmpFormat );
+            NCDF_ERR(status);
+        }
+        if ( nAttrLen > 1 && nTmpFormat == NCDF_FORMAT_NC4 )
+            status = nc_put_att_string( nCdfId, nVarId, pszAttrName,
+                                        nAttrLen, (const char **) papszValues );
+        else
+#endif
+            status = nc_put_att_text( nCdfId, nVarId, pszAttrName,
+                                      strlen( pszValue ), pszValue );
+        NCDF_ERR(status);
     }
     else {
-        
         switch( nAttrType ) {
             case  NC_INT:
-                int *pnTemp;
-                pnTemp = (int *) CPLCalloc( nAttrLen, sizeof( int ) );
-                for(i=0; i < nAttrLen; i++) {
-                    pnTemp[i] = strtol( papszValues[i], &pszTemp, 10 );
+            {
+                int *pnTemp = reinterpret_cast<int *> (
+                    CPLCalloc( nAttrLen, sizeof( int ) ) );
+                for( size_t i=0; i < nAttrLen; i++) {
+                    pnTemp[i] = static_cast<int>(strtol( papszValues[i], &pszTemp, 10 ));
                 }
-                status = nc_put_att_int( nCdfId, nVarId, pszAttrName, 
-                                         NC_INT, nAttrLen, pnTemp );  
+                status = nc_put_att_int( nCdfId, nVarId, pszAttrName,
+                                         NC_INT, nAttrLen, pnTemp );
                 NCDF_ERR(status);
                 CPLFree(pnTemp);
-            break;
+                break;
+            }
+#ifdef NETCDF_HAS_NC4
+            case  NC_UINT:
+            {
+                unsigned int *punTemp = reinterpret_cast<unsigned int *> (
+                    CPLCalloc( nAttrLen, sizeof( unsigned int ) ) );
+                for( size_t i=0; i < nAttrLen; i++) {
+                    punTemp[i] = static_cast<unsigned int>(strtol( papszValues[i], &pszTemp, 10 ));
+                }
+                status = nc_put_att_uint( nCdfId, nVarId, pszAttrName,
+                                          NC_UINT, nAttrLen, punTemp );
+                NCDF_ERR(status);
+                CPLFree(punTemp);
+                break;
+            }
+#endif
             case  NC_FLOAT:
-                float *pfTemp;
-                pfTemp = (float *) CPLCalloc( nAttrLen, sizeof( float ) );
-                for(i=0; i < nAttrLen; i++) {
+            {
+                float *pfTemp = reinterpret_cast<float *> (
+                    CPLCalloc( nAttrLen, sizeof( float ) ) );
+                for( size_t i=0; i < nAttrLen; i++) {
                     pfTemp[i] = (float)CPLStrtod( papszValues[i], &pszTemp );
                 }
-                status = nc_put_att_float( nCdfId, nVarId, pszAttrName, 
-                                           NC_FLOAT, nAttrLen, pfTemp );  
+                status = nc_put_att_float( nCdfId, nVarId, pszAttrName,
+                                           NC_FLOAT, nAttrLen, pfTemp );
                 NCDF_ERR(status);
                 CPLFree(pfTemp);
-            break;
+                break;
+            }
             case  NC_DOUBLE:
-                double *pdfTemp;
-                pdfTemp = (double *) CPLCalloc( nAttrLen, sizeof( double ) );
-                for(i=0; i < nAttrLen; i++) {
+            {
+                double *pdfTemp = reinterpret_cast<double *> (
+                    CPLCalloc( nAttrLen, sizeof( double ) ) );
+                for(size_t i=0; i < nAttrLen; i++) {
                     pdfTemp[i] = CPLStrtod( papszValues[i], &pszTemp );
                 }
-                status = nc_put_att_double( nCdfId, nVarId, pszAttrName, 
+                status = nc_put_att_double( nCdfId, nVarId, pszAttrName,
                                             NC_DOUBLE, nAttrLen, pdfTemp );
                 NCDF_ERR(status);
                 CPLFree(pdfTemp);
-            break;
+                break;
+            }
         default:
             if ( papszValues ) CSLDestroy( papszValues );
             return CE_Failure;
             break;
-        }   
+        }
     }
 
     if ( papszValues ) CSLDestroy( papszValues );
@@ -6615,108 +8181,190 @@ CPLErr NCDFPutAttr( int nCdfId, int nVarId,
      return CE_None;
 }
 
-CPLErr NCDFGet1DVar( int nCdfId, int nVarId, char **pszValue )
+static CPLErr NCDFGet1DVar( int nCdfId, int nVarId, char **pszValue )
 {
-    nc_type nVarType = NC_NAT;
-    size_t  nVarLen = 0;
-    int     status = 0;
-    size_t  m;
-    char    szTemp[ NCDF_MAX_STR_LEN ];
-    char    *pszVarValue = NULL;
-    size_t  nVarValueSize;
-    int     nVarDimId=-1;
-    size_t start[1], count[1];
-
     /* get var information */
-    status = nc_inq_varndims( nCdfId, nVarId, &nVarDimId );
+    int nVarDimId = -1;
+    int status = nc_inq_varndims( nCdfId, nVarId, &nVarDimId );
     if ( status != NC_NOERR || nVarDimId != 1)
         return CE_Failure;
+
     status = nc_inq_vardimid( nCdfId, nVarId, &nVarDimId );
     if ( status != NC_NOERR )
         return CE_Failure;
+
+    nc_type nVarType = NC_NAT;
     status = nc_inq_vartype( nCdfId, nVarId, &nVarType );
     if ( status != NC_NOERR )
         return CE_Failure;
+
+    size_t nVarLen = 0;
     status = nc_inq_dimlen( nCdfId, nVarDimId, &nVarLen );
     if ( status != NC_NOERR )
         return CE_Failure;
-    start[0] = 0;
-    count[0] = nVarLen;
+
+    size_t start[1] = {0};
+    size_t count[1] = {nVarLen};
 
     /* Allocate guaranteed minimum size */
-    nVarValueSize = NCDF_MAX_STR_LEN;
-    pszVarValue = (char *) CPLCalloc( nVarValueSize, sizeof( char ));
+    size_t nVarValueSize = NCDF_MAX_STR_LEN;
+    char *pszVarValue = reinterpret_cast<char *> (
+        CPLCalloc( nVarValueSize, sizeof( char ) ) );
     *pszVarValue = '\0';
 
-    if ( nVarLen > 1 && nVarType != NC_CHAR )    
-        NCDFSafeStrcat(&pszVarValue, (char *)"{", &nVarValueSize);
+    if ( nVarLen > 1 && nVarType != NC_CHAR )
+        NCDFSafeStrcat(&pszVarValue, "{", &nVarValueSize);
 
     switch (nVarType) {
         case NC_CHAR:
             nc_get_vara_text( nCdfId, nVarId, start, count, pszVarValue );
             pszVarValue[nVarLen]='\0';
             break;
-        /* TODO support NC_UBYTE */
         case NC_BYTE:
-            signed char *pscTemp;
-            pscTemp = (signed char *) CPLCalloc( nVarLen, sizeof( signed char ) );
+        {
+            signed char *pscTemp = reinterpret_cast<signed char *> (
+                CPLCalloc( nVarLen, sizeof( signed char ) ) );
             nc_get_vara_schar( nCdfId, nVarId, start, count, pscTemp );
-            for(m=0; m < nVarLen-1; m++) {
-                sprintf( szTemp, "%d,", pscTemp[m] );
+            char szTemp[ 256 ];
+            size_t m = 0;
+            for( ; m < nVarLen-1; m++) {
+                snprintf( szTemp, sizeof(szTemp), "%d,", pscTemp[m] );
                 NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
             }
-            sprintf( szTemp, "%d", pscTemp[m] );
+            snprintf( szTemp, sizeof(szTemp), "%d", pscTemp[m] );
             NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
             CPLFree(pscTemp);
             break;
+        }
         case NC_SHORT:
-            short *psTemp;
-            psTemp = (short *) CPLCalloc( nVarLen, sizeof( short ) );
+        {
+            short *psTemp = reinterpret_cast<short *> (
+                CPLCalloc( nVarLen, sizeof( short ) ) );
             nc_get_vara_short( nCdfId, nVarId, start, count, psTemp );
-            for(m=0; m < nVarLen-1; m++) {
-                sprintf( szTemp, "%hd,", psTemp[m] );
+            char szTemp[ 256 ];
+            size_t m = 0;
+            for( ; m < nVarLen-1; m++) {
+                snprintf( szTemp, sizeof(szTemp), "%d,", psTemp[m] );
                 NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
             }
-            sprintf( szTemp, "%hd", psTemp[m] );
+            snprintf( szTemp, sizeof(szTemp),  "%d", psTemp[m] );
             NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
             CPLFree(psTemp);
             break;
+        }
         case NC_INT:
-            int *pnTemp;
-            pnTemp = (int *) CPLCalloc( nVarLen, sizeof( int ) );
+        {
+            int *pnTemp = reinterpret_cast<int *> (
+                CPLCalloc( nVarLen, sizeof( int ) ) );
             nc_get_vara_int( nCdfId, nVarId, start, count, pnTemp );
-            for(m=0; m < nVarLen-1; m++) {
-                sprintf( szTemp, "%d,", pnTemp[m] );
+            char szTemp[ 256 ];
+            size_t m = 0;
+            for( ; m < nVarLen-1; m++) {
+                snprintf( szTemp, sizeof(szTemp), "%d,", pnTemp[m] );
                 NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
             }
-            sprintf( szTemp, "%d", pnTemp[m] );
+            snprintf( szTemp, sizeof(szTemp), "%d", pnTemp[m] );
             NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
             CPLFree(pnTemp);
             break;
+        }
         case NC_FLOAT:
-            float *pfTemp;
-            pfTemp = (float *) CPLCalloc( nVarLen, sizeof( float ) );
+        {
+            float *pfTemp = reinterpret_cast<float *> (
+                CPLCalloc( nVarLen, sizeof( float ) ) );
             nc_get_vara_float( nCdfId, nVarId, start, count, pfTemp );
-            for(m=0; m < nVarLen-1; m++) {
-                CPLsprintf( szTemp, "%.8g,", pfTemp[m] );
+            char szTemp[ 256 ];
+            size_t m = 0;
+            for( ; m < nVarLen-1; m++) {
+                CPLsnprintf( szTemp, sizeof(szTemp), "%.8g,", pfTemp[m] );
                 NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
             }
-            CPLsprintf( szTemp, "%.8g", pfTemp[m] );
+            CPLsnprintf( szTemp, sizeof(szTemp), "%.8g", pfTemp[m] );
             NCDFSafeStrcat(&pszVarValue,szTemp, &nVarValueSize);
             CPLFree(pfTemp);
             break;
+        }
         case NC_DOUBLE:
-            double *pdfTemp;
-            pdfTemp = (double *) CPLCalloc(nVarLen, sizeof(double));
+        {
+            double *pdfTemp = reinterpret_cast<double *> (
+                CPLCalloc( nVarLen, sizeof(double) ) );
             nc_get_vara_double( nCdfId, nVarId, start, count, pdfTemp );
-            for(m=0; m < nVarLen-1; m++) {
-                CPLsprintf( szTemp, "%.16g,", pdfTemp[m] );
+            char szTemp[ 256 ];
+            size_t m = 0;
+            for( ; m < nVarLen-1; m++) {
+                CPLsnprintf( szTemp, sizeof(szTemp), "%.16g,", pdfTemp[m] );
                 NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
             }
-            CPLsprintf( szTemp, "%.16g", pdfTemp[m] );
+            CPLsnprintf( szTemp, sizeof(szTemp), "%.16g", pdfTemp[m] );
             NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
             CPLFree(pdfTemp);
             break;
+        }
+#ifdef NETCDF_HAS_NC4
+        case NC_STRING:
+        {
+            char **ppszTemp = reinterpret_cast<char **> (
+                CPLCalloc( nVarLen, sizeof( char * ) ) );
+            nc_get_vara_string( nCdfId, nVarId, start, count, ppszTemp );
+            size_t m = 0;
+            for( ; m < nVarLen-1; m++) {
+                NCDFSafeStrcat(&pszVarValue, ppszTemp[m], &nVarValueSize);
+                NCDFSafeStrcat(&pszVarValue, ",", &nVarValueSize);
+            }
+            NCDFSafeStrcat(&pszVarValue, ppszTemp[m], &nVarValueSize);
+            nc_free_string(nVarLen, ppszTemp);
+            CPLFree(ppszTemp);
+            break;
+        }
+        case NC_UBYTE:
+        {
+            unsigned char *pucTemp;
+            pucTemp = (unsigned char *) CPLCalloc( nVarLen, sizeof( unsigned char ) );
+            nc_get_vara_uchar( nCdfId, nVarId, start, count, pucTemp );
+            char szTemp[ 256 ];
+            size_t m = 0;
+            for( ; m < nVarLen-1; m++) {
+                CPLsnprintf( szTemp, sizeof(szTemp), "%u,", pucTemp[m] );
+                NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
+            }
+            CPLsnprintf( szTemp, sizeof(szTemp), "%u", pucTemp[m] );
+            NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
+            CPLFree(pucTemp);
+            break;
+        }
+        case NC_USHORT:
+        {
+            unsigned short *pusTemp;
+            pusTemp = (unsigned short *) CPLCalloc( nVarLen, sizeof( unsigned short ) );
+            nc_get_vara_ushort( nCdfId, nVarId, start, count, pusTemp );
+            char szTemp[ 256 ];
+            size_t m = 0;
+            for( ; m < nVarLen-1; m++) {
+                CPLsnprintf( szTemp, sizeof(szTemp), "%u,", pusTemp[m] );
+                NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
+            }
+            CPLsnprintf( szTemp, sizeof(szTemp), "%u", pusTemp[m] );
+            NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
+            CPLFree(pusTemp);
+            break;
+        }
+        case NC_UINT:
+        {
+            unsigned int *punTemp;
+            punTemp = (unsigned int *) CPLCalloc( nVarLen, sizeof( unsigned int ) );
+            nc_get_vara_uint( nCdfId, nVarId, start, count, punTemp );
+            char szTemp[ 256 ];
+            size_t m = 0;
+            for( ; m < nVarLen-1; m++) {
+                CPLsnprintf( szTemp, sizeof(szTemp), "%u,", punTemp[m] );
+                NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
+            }
+            CPLsnprintf( szTemp, sizeof(szTemp), "%u", punTemp[m] );
+            NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
+            CPLFree(punTemp);
+            break;
+        }
+#endif
         default:
             CPLDebug( "GDAL_netCDF", "NCDFGetVar1D unsupported type %d",
                       nVarType );
@@ -6725,8 +8373,8 @@ CPLErr NCDFGet1DVar( int nCdfId, int nVarId, char **pszValue )
             break;
     }
 
-    if ( nVarLen > 1  && nVarType!= NC_CHAR )    
-        NCDFSafeStrcat(&pszVarValue, (char *)"}", &nVarValueSize);
+    if ( nVarLen > 1  && nVarType!= NC_CHAR )
+        NCDFSafeStrcat(&pszVarValue, "}", &nVarValueSize);
 
     /* set return values */
     *pszValue = pszVarValue;
@@ -6734,40 +8382,37 @@ CPLErr NCDFGet1DVar( int nCdfId, int nVarId, char **pszValue )
     return CE_None;
 }
 
-CPLErr NCDFPut1DVar( int nCdfId, int nVarId, const char *pszValue )
+static CPLErr NCDFPut1DVar( int nCdfId, int nVarId, const char *pszValue )
 {
-    nc_type nVarType = NC_CHAR;
-    size_t  nVarLen = 0;
-    int     status = 0;
-    size_t  i;
-    char    *pszTemp = NULL;
-    char    **papszValues = NULL;
-    
-    int     nVarDimId=-1;
-    size_t start[1], count[1];
-
     if ( EQUAL( pszValue, "" ) )
         return CE_Failure;
 
     /* get var information */
-    status = nc_inq_varndims( nCdfId, nVarId, &nVarDimId );
+    int nVarDimId = -1;
+    int status = nc_inq_varndims( nCdfId, nVarId, &nVarDimId );
     if ( status != NC_NOERR || nVarDimId != 1)
         return CE_Failure;
+
     status = nc_inq_vardimid( nCdfId, nVarId, &nVarDimId );
     if ( status != NC_NOERR )
         return CE_Failure;
+
+    nc_type nVarType = NC_CHAR;
     status = nc_inq_vartype( nCdfId, nVarId, &nVarType );
     if ( status != NC_NOERR )
         return CE_Failure;
+
+    size_t  nVarLen = 0;
     status = nc_inq_dimlen( nCdfId, nVarDimId, &nVarLen );
     if ( status != NC_NOERR )
         return CE_Failure;
-    start[0] = 0;
-    count[0] = nVarLen;
+
+    size_t start[1] = {0};
+    size_t count[1] = {nVarLen};
 
     /* get the values as tokens */
-    papszValues = NCDFTokenizeArray( pszValue );
-    if ( papszValues == NULL ) 
+    char **papszValues = NCDFTokenizeArray( pszValue );
+    if ( papszValues == NULL )
         return CE_Failure;
 
     nVarLen = CSLCount(papszValues);
@@ -6776,54 +8421,147 @@ CPLErr NCDFPut1DVar( int nCdfId, int nVarId, const char *pszValue )
     if ( nVarType == NC_CHAR ) {
         status = nc_put_vara_text( nCdfId, nVarId, start, count,
                                   pszValue );
-        NCDF_ERR(status);                        
+        NCDF_ERR(status);
     }
     else {
-        
+
         switch( nVarType ) {
-            /* TODO add other types */
+            case  NC_BYTE:
+            {
+                signed char *pscTemp = reinterpret_cast<signed char *> (
+                    CPLCalloc( nVarLen, sizeof( signed char ) ) );
+                for(size_t i=0; i < nVarLen; i++) {
+                    char *pszTemp = NULL;
+                    pscTemp[i] = static_cast<signed char>(strtol( papszValues[i], &pszTemp, 10 ));
+                }
+                status = nc_put_vara_schar( nCdfId, nVarId, start, count, pscTemp );
+                NCDF_ERR(status);
+                CPLFree(pscTemp);
+                break;
+            }
+            case  NC_SHORT:
+            {
+                short *psTemp = reinterpret_cast<short *> (
+                    CPLCalloc( nVarLen, sizeof( short ) ) );
+                for(size_t i=0; i < nVarLen; i++) {
+                    char *pszTemp = NULL;
+                    psTemp[i] = static_cast<short>(strtol( papszValues[i], &pszTemp, 10 ));
+                }
+                status = nc_put_vara_short( nCdfId, nVarId, start, count, psTemp );
+                NCDF_ERR(status);
+                CPLFree(psTemp);
+                break;
+            }
             case  NC_INT:
-                int *pnTemp;
-                pnTemp = (int *) CPLCalloc( nVarLen, sizeof( int ) );
-                for(i=0; i < nVarLen; i++) {
-                    pnTemp[i] = strtol( papszValues[i], &pszTemp, 10 );
+            {
+                int *pnTemp = reinterpret_cast<int *> (
+                    CPLCalloc( nVarLen, sizeof( int ) ) );
+                for(size_t i=0; i < nVarLen; i++) {
+                    char *pszTemp = NULL;
+                    pnTemp[i] = static_cast<int>(strtol( papszValues[i], &pszTemp, 10 ));
                 }
-                status = nc_put_vara_int( nCdfId, nVarId, start, count, pnTemp );  
+                status = nc_put_vara_int( nCdfId, nVarId, start, count, pnTemp );
                 NCDF_ERR(status);
                 CPLFree(pnTemp);
-            break;
+                break;
+            }
             case  NC_FLOAT:
-                float *pfTemp;
-                pfTemp = (float *) CPLCalloc( nVarLen, sizeof( float ) );
-                for(i=0; i < nVarLen; i++) {
+            {
+                float *pfTemp = reinterpret_cast<float *> (
+                    CPLCalloc( nVarLen, sizeof( float ) ) );
+                for(size_t i=0; i < nVarLen; i++) {
+                    char *pszTemp = NULL;
                     pfTemp[i] = (float)CPLStrtod( papszValues[i], &pszTemp );
                 }
-                status = nc_put_vara_float( nCdfId, nVarId, start, count, 
-                                            pfTemp );  
+                status = nc_put_vara_float( nCdfId, nVarId, start, count,
+                                            pfTemp );
                 NCDF_ERR(status);
                 CPLFree(pfTemp);
-            break;
+                break;
+            }
             case  NC_DOUBLE:
-                double *pdfTemp;
-                pdfTemp = (double *) CPLCalloc( nVarLen, sizeof( double ) );
-                for(i=0; i < nVarLen; i++) {
+            {
+                double *pdfTemp = reinterpret_cast<double *> (
+                    CPLCalloc( nVarLen, sizeof( double ) ) );
+                for(size_t i=0; i < nVarLen; i++) {
+                    char *pszTemp = NULL;
                     pdfTemp[i] = CPLStrtod( papszValues[i], &pszTemp );
                 }
-                status = nc_put_vara_double( nCdfId, nVarId, start, count, 
+                status = nc_put_vara_double( nCdfId, nVarId, start, count,
                                              pdfTemp );
                 NCDF_ERR(status);
                 CPLFree(pdfTemp);
-            break;
+                break;
+            }
         default:
-            if ( papszValues ) CSLDestroy( papszValues );
-            return CE_Failure;
-            break;
-        }   
+#ifdef NETCDF_HAS_NC4
+            int nTmpFormat = 0;
+            status = nc_inq_format( nCdfId, &nTmpFormat );
+            NCDF_ERR(status);
+            if ( nTmpFormat == NCDF_FORMAT_NC4 ) {
+                switch ( nVarType ) {
+                    case NC_STRING:
+                    {
+                        status = nc_put_vara_string( nCdfId, nVarId, start, count,
+                                                     (const char **) papszValues );
+                        NCDF_ERR(status);
+                        break;
+                    }
+                    case NC_UBYTE:
+                    {
+                        unsigned char *pucTemp = reinterpret_cast<unsigned char *> (
+                            CPLCalloc( nVarLen, sizeof( unsigned char ) ) );
+                        for(size_t i=0; i < nVarLen; i++) {
+                            char *pszTemp = NULL;
+                            pucTemp[i] = static_cast<unsigned char>(strtoul( papszValues[i], &pszTemp, 10 ));
+                        }
+                        status = nc_put_vara_uchar( nCdfId, nVarId, start, count, pucTemp );
+                        NCDF_ERR(status);
+                        CPLFree(pucTemp);
+                        break;
+                    }
+                    case NC_USHORT:
+                    {
+                        unsigned short *pusTemp = reinterpret_cast<unsigned short *> (
+                            CPLCalloc( nVarLen, sizeof( unsigned short ) ) );
+                        for(size_t i=0; i < nVarLen; i++) {
+                            char *pszTemp = NULL;
+                            pusTemp[i] = static_cast<unsigned short>(strtoul( papszValues[i], &pszTemp, 10 ));
+                        }
+                        status = nc_put_vara_ushort( nCdfId, nVarId, start, count, pusTemp );
+                        NCDF_ERR(status);
+                        CPLFree(pusTemp);
+                        break;
+                    }
+                    case NC_UINT:
+                    {
+                        unsigned int *punTemp = reinterpret_cast<unsigned int *> (
+                            CPLCalloc( nVarLen, sizeof( unsigned int ) ) );
+                        for(size_t i=0; i < nVarLen; i++) {
+                            char *pszTemp = NULL;
+                            punTemp[i] = static_cast<unsigned int>(strtoul( papszValues[i], &pszTemp, 10 ));
+                        }
+                        status = nc_put_vara_uint( nCdfId, nVarId, start, count, punTemp );
+                        NCDF_ERR(status);
+                        CPLFree(punTemp);
+                        break;
+                    }
+                    default:
+#endif
+                        if ( papszValues ) CSLDestroy( papszValues );
+                        return CE_Failure;
+                        break;
+#ifdef NETCDF_HAS_NC4
+                }
+            }
+#endif
+        }
     }
 
-    if ( papszValues ) CSLDestroy( papszValues );
+    if ( papszValues )
+        CSLDestroy( papszValues );
 
-     return CE_None;
+    return CE_None;
 }
 
 
@@ -6840,7 +8578,7 @@ double NCDFGetDefaultNoDataValue( int nVarType )
         case NC_BYTE:
 #ifdef NETCDF_HAS_NC4
         case NC_UBYTE:
-#endif    
+#endif
             /* don't do default fill-values for bytes, too risky */
             dfNoData = 0.0;
             break;
@@ -6859,40 +8597,47 @@ double NCDFGetDefaultNoDataValue( int nVarType )
         case NC_DOUBLE:
             dfNoData = NC_FILL_DOUBLE;
             break;
+#ifdef NETCDF_HAS_NC4
+        case NC_USHORT:
+            dfNoData = NC_FILL_USHORT;
+            break;
+        case NC_UINT:
+            dfNoData = NC_FILL_UINT;
+            break;
+#endif
         default:
             dfNoData = 0.0;
             break;
     }
 
     return dfNoData;
-} 
+}
 
 
-int NCDFDoesVarContainAttribVal( int nCdfId,
-                                 const char ** papszAttribNames, 
-                                 const char ** papszAttribValues,
+static int NCDFDoesVarContainAttribVal( int nCdfId,
+                                 const char * const* papszAttribNames,
+                                 const char * const* papszAttribValues,
                                  int nVarId,
                                  const char * pszVarName,
-                                 int bStrict=TRUE )
+                                 bool bStrict=true )
 {
-    char *pszTemp = NULL;
-    int bFound = FALSE;
-
     if ( (nVarId == -1) && (pszVarName != NULL) )
         nc_inq_varid( nCdfId, pszVarName, &nVarId );
-    
+
     if ( nVarId == -1 ) return -1;
 
+    bool bFound = false;
     for( int i=0; !bFound && i<CSLCount((char**)papszAttribNames); i++ ) {
-        if ( NCDFGetAttr( nCdfId, nVarId, papszAttribNames[i], &pszTemp ) 
-             == CE_None && pszTemp != NULL ) { 
+        char *pszTemp = NULL;
+        if ( NCDFGetAttr( nCdfId, nVarId, papszAttribNames[i], &pszTemp )
+             == CE_None && pszTemp != NULL ) {
             if ( bStrict ) {
                 if ( EQUAL( pszTemp, papszAttribValues[i] ) )
-                    bFound=TRUE;
+                    bFound = true;
             }
             else {
                 if ( EQUALN( pszTemp, papszAttribValues[i], strlen(papszAttribValues[i]) ) )
-                    bFound=TRUE;
+                    bFound = true;
             }
             CPLFree( pszTemp );
         }
@@ -6900,32 +8645,31 @@ int NCDFDoesVarContainAttribVal( int nCdfId,
     return bFound;
 }
 
-int NCDFDoesVarContainAttribVal2( int nCdfId,
-                                  const char * papszAttribName, 
-                                  const char ** papszAttribValues,
+static int NCDFDoesVarContainAttribVal2( int nCdfId,
+                                  const char * papszAttribName,
+                                  const char * const* papszAttribValues,
                                   int nVarId,
                                   const char * pszVarName,
-                                  int bStrict=TRUE )
+                                  int bStrict=true )
 {
-    char *pszTemp = NULL;
-    int bFound = FALSE;
-
     if ( (nVarId == -1) && (pszVarName != NULL) )
         nc_inq_varid( nCdfId, pszVarName, &nVarId );
-    
+
     if ( nVarId == -1 ) return -1;
 
-    if ( NCDFGetAttr( nCdfId, nVarId, papszAttribName, &pszTemp ) 
+    bool bFound = false;
+    char *pszTemp = NULL;
+    if ( NCDFGetAttr( nCdfId, nVarId, papszAttribName, &pszTemp )
          != CE_None || pszTemp == NULL ) return FALSE;
 
     for( int i=0; !bFound && i<CSLCount((char**)papszAttribValues); i++ ) {
         if ( bStrict ) {
             if ( EQUAL( pszTemp, papszAttribValues[i] ) )
-                bFound=TRUE;
+                bFound = true;
         }
         else {
             if ( EQUALN( pszTemp, papszAttribValues[i], strlen(papszAttribValues[i]) ) )
-                bFound=TRUE;
+                bFound = true;
         }
     }
 
@@ -6934,163 +8678,159 @@ int NCDFDoesVarContainAttribVal2( int nCdfId,
     return bFound;
 }
 
-int NCDFEqual( const char * papszName, const char ** papszValues )
+static bool NCDFEqual( const char * papszName, const char * const* papszValues )
 {
-    int bFound = FALSE;
-
     if ( papszName == NULL || EQUAL(papszName,"") )
-        return FALSE;
+        return false;
 
-    for( int i=0; i<CSLCount((char**)papszValues); i++ ) {
+    for( int i=0; i<CSLCount((char**)papszValues); ++i ) {
         if( EQUAL( papszName, papszValues[i] ) )
-            bFound = TRUE;
-        break;
+            return true;
     }
-     
-    return bFound;
+
+    return false;
 }
 
 /* test that a variable is longitude/latitude coordinate, following CF 4.1 and 4.2 */
-int NCDFIsVarLongitude( int nCdfId, int nVarId,
+static bool NCDFIsVarLongitude( int nCdfId, int nVarId,
                         const char * pszVarName )
 {
     /* check for matching attributes */
     int bVal = NCDFDoesVarContainAttribVal( nCdfId,
-                                            papszCFLongitudeAttribNames, 
+                                            papszCFLongitudeAttribNames,
                                             papszCFLongitudeAttribValues,
                                             nVarId, pszVarName );
     /* if not found using attributes then check using var name */
     /* unless GDAL_NETCDF_VERIFY_DIMS=STRICT */
     if ( bVal == -1 ) {
-        if ( ! EQUAL( CPLGetConfigOption( "GDAL_NETCDF_VERIFY_DIMS", "YES" ), 
+        if ( ! EQUAL( CPLGetConfigOption( "GDAL_NETCDF_VERIFY_DIMS", "YES" ),
                       "STRICT" ) )
-            bVal = NCDFEqual(pszVarName, papszCFLongitudeVarNames );
+            bVal = NCDFEqual( pszVarName, papszCFLongitudeVarNames );
         else
             bVal = FALSE;
     }
-    return bVal;
+    return CPL_TO_BOOL(bVal);
 }
- 
-int NCDFIsVarLatitude( int nCdfId, int nVarId, const char * pszVarName )
+
+static bool NCDFIsVarLatitude( int nCdfId, int nVarId, const char * pszVarName )
 {
     int bVal = NCDFDoesVarContainAttribVal( nCdfId,
-                                            papszCFLatitudeAttribNames, 
+                                            papszCFLatitudeAttribNames,
                                             papszCFLatitudeAttribValues,
                                             nVarId, pszVarName );
     if ( bVal == -1 ) {
-        if ( ! EQUAL( CPLGetConfigOption( "GDAL_NETCDF_VERIFY_DIMS", "YES" ), 
+        if ( ! EQUAL( CPLGetConfigOption( "GDAL_NETCDF_VERIFY_DIMS", "YES" ),
                       "STRICT" ) )
-            bVal = NCDFEqual(pszVarName, papszCFLatitudeVarNames );
+            bVal = NCDFEqual( pszVarName, papszCFLatitudeVarNames );
         else
             bVal = FALSE;
     }
-    return bVal;
+    return CPL_TO_BOOL(bVal);
 }
 
-int NCDFIsVarProjectionX( int nCdfId, int nVarId, const char * pszVarName )
+static bool NCDFIsVarProjectionX( int nCdfId, int nVarId, const char * pszVarName )
 {
     int bVal = NCDFDoesVarContainAttribVal( nCdfId,
-                                            papszCFProjectionXAttribNames, 
+                                            papszCFProjectionXAttribNames,
                                             papszCFProjectionXAttribValues,
                                             nVarId, pszVarName );
     if ( bVal == -1 ) {
-        if ( ! EQUAL( CPLGetConfigOption( "GDAL_NETCDF_VERIFY_DIMS", "YES" ), 
+        if ( ! EQUAL( CPLGetConfigOption( "GDAL_NETCDF_VERIFY_DIMS", "YES" ),
                       "STRICT" ) )
-            bVal = NCDFEqual(pszVarName, papszCFProjectionXVarNames );
+            bVal = NCDFEqual( pszVarName, papszCFProjectionXVarNames );
         else
             bVal = FALSE;
 
     }
-    return bVal;
+    return CPL_TO_BOOL(bVal);
 }
 
-int NCDFIsVarProjectionY( int nCdfId, int nVarId, const char * pszVarName )
+static bool NCDFIsVarProjectionY( int nCdfId, int nVarId, const char * pszVarName )
 {
     int bVal = NCDFDoesVarContainAttribVal( nCdfId,
-                                            papszCFProjectionYAttribNames, 
+                                            papszCFProjectionYAttribNames,
                                             papszCFProjectionYAttribValues,
                                             nVarId, pszVarName );
     if ( bVal == -1 ) {
-        if ( ! EQUAL( CPLGetConfigOption( "GDAL_NETCDF_VERIFY_DIMS", "YES" ), 
+        if ( ! EQUAL( CPLGetConfigOption( "GDAL_NETCDF_VERIFY_DIMS", "YES" ),
                       "STRICT" ) )
-            bVal = NCDFEqual(pszVarName, papszCFProjectionYVarNames );
+            bVal = NCDFEqual( pszVarName, papszCFProjectionYVarNames );
         else
             bVal = FALSE;
     }
-    return bVal;
+    return CPL_TO_BOOL(bVal);
 }
 
 /* test that a variable is a vertical coordinate, following CF 4.3 */
-int NCDFIsVarVerticalCoord( int nCdfId, int nVarId,
+static bool NCDFIsVarVerticalCoord( int nCdfId, int nVarId,
                             const char * pszVarName )
 {
-    /* check for matching attributes */ 
+    /* check for matching attributes */
     if ( NCDFDoesVarContainAttribVal( nCdfId,
                                       papszCFVerticalAttribNames,
                                       papszCFVerticalAttribValues,
-                                      nVarId, pszVarName ) == TRUE )
-        return TRUE;
-    /* check for matching units */ 
+                                      nVarId, pszVarName ) )
+        return true;
+    /* check for matching units */
     else if ( NCDFDoesVarContainAttribVal2( nCdfId,
-                                            CF_UNITS, 
+                                            CF_UNITS,
                                             papszCFVerticalUnitsValues,
-                                            nVarId, pszVarName ) == TRUE )
-        return TRUE;
-    /* check for matching standard name */ 
+                                            nVarId, pszVarName ) )
+        return true;
+    /* check for matching standard name */
     else if ( NCDFDoesVarContainAttribVal2( nCdfId,
-                                            CF_STD_NAME, 
+                                            CF_STD_NAME,
                                             papszCFVerticalStandardNameValues,
-                                            nVarId, pszVarName ) == TRUE )
-        return TRUE;
-    else 
-        return FALSE;
+                                            nVarId, pszVarName ) )
+        return true;
+    else
+        return false;
 }
 
 /* test that a variable is a time coordinate, following CF 4.4 */
-int NCDFIsVarTimeCoord( int nCdfId, int nVarId,
+static bool NCDFIsVarTimeCoord( int nCdfId, int nVarId,
                         const char * pszVarName )
 {
-    /* check for matching attributes */ 
+    /* check for matching attributes */
     if ( NCDFDoesVarContainAttribVal( nCdfId,
-                                      papszCFTimeAttribNames, 
+                                      papszCFTimeAttribNames,
                                       papszCFTimeAttribValues,
-                                      nVarId, pszVarName ) == TRUE )
-        return TRUE;
-    /* check for matching units */ 
+                                      nVarId, pszVarName ) )
+        return true;
+    /* check for matching units */
     else if ( NCDFDoesVarContainAttribVal2( nCdfId,
-                                            CF_UNITS, 
+                                            CF_UNITS,
                                             papszCFTimeUnitsValues,
-                                            nVarId, pszVarName, FALSE ) == TRUE )
-        return TRUE;
+                                            nVarId, pszVarName, false ) )
+        return true;
     else
-        return FALSE;
+        return false;
 }
 
 /* parse a string, and return as a string list */
 /* if it an array of the form {a,b} then tokenize it */
 /* else return a copy */
-char **NCDFTokenizeArray( const char *pszValue )
+static char **NCDFTokenizeArray( const char *pszValue )
 {
-    char **papszValues = NULL;
-    int nLen = 0;
-
-    if ( pszValue==NULL || EQUAL( pszValue, "" ) ) 
+    if ( pszValue==NULL || EQUAL( pszValue, "" ) )
         return NULL;
 
-    nLen = strlen(pszValue);
+    char **papszValues = NULL;
+    const int nLen = static_cast<int>(strlen(pszValue));
 
     if ( pszValue[0] == '{' && nLen > 2 && pszValue[nLen-1] == '}' ) {
         char *pszTemp = reinterpret_cast<char *> (CPLMalloc( (nLen-2) + 1 ) );
         strncpy( pszTemp, pszValue+1, nLen-2);
         pszTemp[nLen-2] = '\0';
         papszValues = CSLTokenizeString2( pszTemp, ",", CSLT_ALLOWEMPTYTOKENS );
-        CPLFree( pszTemp);
+        CPLFree( pszTemp );
     }
     else {
-        papszValues = (char**) CPLCalloc(2,sizeof(char*));
+        papszValues = reinterpret_cast<char**> (
+            CPLCalloc( 2, sizeof(char*) ) );
         papszValues[0] = CPLStrdup( pszValue );
         papszValues[1] = NULL;
     }
-    
+
     return papszValues;
 }
diff --git a/frmts/netcdf/netcdfdataset.h b/frmts/netcdf/netcdfdataset.h
index a22c9e7..0eea212 100644
--- a/frmts/netcdf/netcdfdataset.h
+++ b/frmts/netcdf/netcdfdataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: netcdfdataset.h 26612 2013-11-14 17:35:56Z goatbar $
+ * $Id: netcdfdataset.h 33794 2016-03-26 13:19:07Z goatbar $
  *
  * Project:  netCDF read/write Driver
  * Purpose:  GDAL bindings over netCDF library.
@@ -27,17 +27,18 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _NETCDFDATASET_H_INCLUDED_
-#define _NETCDFDATASET_H_INCLUDED_
+#ifndef NETCDFDATASET_H_INCLUDED_
+#define NETCDFDATASET_H_INCLUDED_
 
-#include <float.h>
+#include <cfloat>
+
+#include "cpl_string.h"
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 #include "gdal_priv.h"
-#include "gdal_frmts.h"
-#include "cpl_string.h"
-#include "ogr_spatialref.h"
 #include "netcdf.h"
-
+#include "ogr_spatialref.h"
+#include "ogrsf_frmts.h"
 
 /************************************************************************/
 /* ==================================================================== */
@@ -72,8 +73,9 @@
 /* -------------------------------------------------------------------- */
 
 /* NETCDF driver defs */
-#define NCDF_MAX_STR_LEN     8192
-#define NCDF_CONVENTIONS_CF  "CF-1.5"
+static const size_t NCDF_MAX_STR_LEN = 8192;
+#define NCDF_CONVENTIONS_CF_V1_5  "CF-1.5"
+#define NCDF_CONVENTIONS_CF_V1_6  "CF-1.6"
 #define NCDF_SPATIAL_REF     "spatial_ref"
 #define NCDF_GEOTRANSFORM    "GeoTransform"
 #define NCDF_DIMNAME_X       "x"
@@ -81,28 +83,34 @@
 #define NCDF_DIMNAME_LON     "lon"
 #define NCDF_DIMNAME_LAT     "lat"
 #define NCDF_LONLAT          "lon lat"
-#define NCDF_PI              3.14159265358979323846
 
 /* netcdf file types, as in libcdi/cdo and compat w/netcdf.h */
-#define NCDF_FORMAT_NONE            0   /* Not a netCDF file */
-#define NCDF_FORMAT_NC              1   /* netCDF classic format */
-#define NCDF_FORMAT_NC2             2   /* netCDF version 2 (64-bit)  */
-#define NCDF_FORMAT_NC4             3   /* netCDF version 4 */
-#define NCDF_FORMAT_NC4C            4   /* netCDF version 4 (classic) */
-#define NCDF_FORMAT_UNKNOWN         10  /* Format not determined (yet) */
+typedef enum
+{
+    NCDF_FORMAT_NONE    = 0,   /* Not a netCDF file */
+    NCDF_FORMAT_NC      = 1,   /* netCDF classic format */
+    NCDF_FORMAT_NC2     = 2,   /* netCDF version 2 (64-bit)  */
+    NCDF_FORMAT_NC4     = 3,   /* netCDF version 4 */
+    NCDF_FORMAT_NC4C    = 4,   /* netCDF version 4 (classic) */
 /* HDF files (HDF5 or HDF4) not supported because of lack of support */
 /* in libnetcdf installation or conflict with other drivers */
-#define NCDF_FORMAT_HDF5            5   /* HDF4 file, not supported */
-#define NCDF_FORMAT_HDF4            6   /* HDF4 file, not supported */
+    NCDF_FORMAT_HDF5    = 5,   /* HDF4 file, not supported */
+    NCDF_FORMAT_HDF4    = 6,   /* HDF4 file, not supported */
+    NCDF_FORMAT_UNKNOWN = 10  /* Format not determined (yet) */
+} NetCDFFormatEnum;
 
 /* compression parameters */
-#define NCDF_COMPRESS_NONE            0   
+typedef enum
+{
+    NCDF_COMPRESS_NONE    = 0,
 /* TODO */
 /* http://www.unidata.ucar.edu/software/netcdf/docs/BestPractices.html#Packed%20Data%20Values */
-#define NCDF_COMPRESS_PACKED          1  
-#define NCDF_COMPRESS_DEFLATE         2   
-#define NCDF_DEFLATE_LEVEL            1  /* best time/size ratio */  
-#define NCDF_COMPRESS_SZIP            3  /* no support for writting */ 
+    NCDF_COMPRESS_PACKED  = 1,
+    NCDF_COMPRESS_DEFLATE = 2,
+    NCDF_COMPRESS_SZIP    = 3  /* no support for writing */
+} NetCDFCompressEnum;
+
+static const int NCDF_DEFLATE_LEVEL    = 1;  /* best time/size ratio */
 
 /* helper for libnetcdf errors */
 #define NCDF_ERR(status) if ( status != NC_NOERR ){ \
@@ -110,8 +118,8 @@ CPLError( CE_Failure,CPLE_AppDefined, \
 "netcdf error #%d : %s .\nat (%s,%s,%d)\n",status, nc_strerror(status), \
 __FILE__, __FUNCTION__, __LINE__ ); }
 
-/* check for NC2 support in case it wasn't enabled at compile time */
-/* NC4 has to be detected at compile as it requires a special build of netcdf-4 */
+/* Check for NC2 support in case it was not enabled at compile time. */
+/* NC4 has to be detected at compile as it requires a special build of netcdf-4. */
 #ifndef NETCDF_HAS_NC2
 #ifdef NC_64BIT_OFFSET
 #define NETCDF_HAS_NC2 1
@@ -133,6 +141,8 @@ __FILE__, __FUNCTION__, __LINE__ ); }
 /* should be SRS_UL_METER but use meter now for compat with gtiff files */
 #define CF_UNITS_M           "metre"
 #define CF_UNITS_D           SRS_UA_DEGREE
+#define CF_PROJ_X_VAR_NAME   "x"
+#define CF_PROJ_Y_VAR_NAME   "y"
 #define CF_PROJ_X_COORD      "projection_x_coordinate"
 #define CF_PROJ_Y_COORD      "projection_y_coordinate"
 #define CF_PROJ_X_COORD_LONG_NAME "x coordinate of projection"
@@ -140,7 +150,17 @@ __FILE__, __FUNCTION__, __LINE__ ); }
 #define CF_GRD_MAPPING_NAME  "grid_mapping_name"
 #define CF_GRD_MAPPING       "grid_mapping"
 #define CF_COORDINATES       "coordinates"
-/* #define CF_AXIS            "axis" */
+
+#define CF_LONGITUDE_VAR_NAME      "lon"
+#define CF_LONGITUDE_STD_NAME      "longitude"
+#define CF_LONGITUDE_LNG_NAME      "longitude"
+#define CF_LATITUDE_VAR_NAME       "lat"
+#define CF_LATITUDE_STD_NAME       "latitude"
+#define CF_LATITUDE_LNG_NAME       "latitude"
+#define CF_DEGREES_NORTH           "degrees_north"
+#define CF_DEGREES_EAST            "degrees_east"
+
+#define CF_AXIS            "axis"
 /* #define CF_BOUNDS          "bounds" */
 /* #define CF_ORIG_UNITS      "original_units" */
 
@@ -163,6 +183,7 @@ __FILE__, __FUNCTION__, __LINE__ ); }
 #define CF_PT_ORTHOGRAPHIC           "orthographic"
 #define CF_PT_POLAR_STEREO           "polar_stereographic"
 #define CF_PT_STEREO                 "stereographic"
+#define CF_PT_GEOS                   "geostationary"
 
 /* projection parameters */
 #define CF_PP_STD_PARALLEL           "standard_parallel"
@@ -191,58 +212,60 @@ __FILE__, __FUNCTION__, __LINE__ ); }
 #define CF_PP_SEMI_MAJOR_AXIS        "semi_major_axis"
 #define CF_PP_SEMI_MINOR_AXIS        "semi_minor_axis"
 #define CF_PP_VERT_PERSP             "vertical_perspective" /*not used yet */
+#define CF_PP_PERSPECTIVE_POINT_HEIGHT "perspective_point_height"
+#define CF_PP_SWEEP_ANGLE_AXIS        "sweep_angle_axis"
 
 
 /* -------------------------------------------------------------------- */
 /*         CF-1 Coordinate Type Naming (Chapter 4.  Coordinate Types )  */
 /* -------------------------------------------------------------------- */
-static const char* papszCFLongitudeVarNames[] = { "lon", "longitude", NULL };
-static const char* papszCFLongitudeAttribNames[] = { "units", CF_STD_NAME, "axis", NULL };
-static const char* papszCFLongitudeAttribValues[] = { "degrees_east", "longitude", "X", NULL };
-static const char* papszCFLatitudeVarNames[] = { "lat", "latitude", NULL };
-static const char* papszCFLatitudeAttribNames[] = { "units", CF_STD_NAME, "axis", NULL };
-static const char* papszCFLatitudeAttribValues[] = { "degrees_north", "latitude", "Y", NULL };
- 
-static const char* papszCFProjectionXVarNames[] = { "x", "xc", NULL };
-static const char* papszCFProjectionXAttribNames[] = { CF_STD_NAME, NULL };
-static const char* papszCFProjectionXAttribValues[] = { CF_PROJ_X_COORD, NULL };
-static const char* papszCFProjectionYVarNames[] = { "y", "yc", NULL };
-static const char* papszCFProjectionYAttribNames[] = { CF_STD_NAME, NULL };
-static const char* papszCFProjectionYAttribValues[] = { CF_PROJ_Y_COORD, NULL };
-
-static const char* papszCFVerticalAttribNames[] = { "axis", "positive", "positive", NULL };
-static const char* papszCFVerticalAttribValues[] = { "Z", "up", "down", NULL };
-static const char* papszCFVerticalUnitsValues[] = { 
+static const char* const papszCFLongitudeVarNames[] = { CF_LONGITUDE_VAR_NAME, "longitude", NULL };
+static const char* const papszCFLongitudeAttribNames[] = { CF_UNITS, CF_STD_NAME, CF_AXIS, NULL };
+static const char* const papszCFLongitudeAttribValues[] = { CF_DEGREES_EAST, CF_LONGITUDE_STD_NAME, "X", NULL };
+static const char* const papszCFLatitudeVarNames[] = { CF_LATITUDE_VAR_NAME, "latitude", NULL };
+static const char* const papszCFLatitudeAttribNames[] = { CF_UNITS, CF_STD_NAME, CF_AXIS, NULL };
+static const char* const papszCFLatitudeAttribValues[] = { CF_DEGREES_NORTH, CF_LATITUDE_STD_NAME, "Y", NULL };
+
+static const char* const papszCFProjectionXVarNames[] = { CF_PROJ_X_VAR_NAME, "xc", NULL };
+static const char* const papszCFProjectionXAttribNames[] = { CF_STD_NAME, NULL };
+static const char* const papszCFProjectionXAttribValues[] = { CF_PROJ_X_COORD, NULL };
+static const char* const papszCFProjectionYVarNames[] = { CF_PROJ_Y_VAR_NAME, "yc", NULL };
+static const char* const papszCFProjectionYAttribNames[] = { CF_STD_NAME, NULL };
+static const char* const papszCFProjectionYAttribValues[] = { CF_PROJ_Y_COORD, NULL };
+
+static const char* const papszCFVerticalAttribNames[] = { CF_AXIS, "positive", "positive", NULL };
+static const char* const papszCFVerticalAttribValues[] = { "Z", "up", "down", NULL };
+static const char* const papszCFVerticalUnitsValues[] = {
     /* units of pressure */
-    "bar", "bars", "millibar", "millibars", "decibar", "decibars", 
+    "bar", "bars", "millibar", "millibars", "decibar", "decibars",
     "atmosphere", "atmospheres", "atm", "pascal", "pascals", "Pa", "hPa",
     /* units of length */
-    "meter", "meters", "m", "kilometer", "kilometers", "km", 
+    "meter", "meters", "m", "kilometer", "kilometers", "km",
     /* dimensionless vertical coordinates */
     "level", "layer", "sigma_level",
     NULL };
 /* dimensionless vertical coordinates */
-static const char* papszCFVerticalStandardNameValues[] = { 
+static const char* const papszCFVerticalStandardNameValues[] = {
     "atmosphere_ln_pressure_coordinate", "atmosphere_sigma_coordinate",
-    "atmosphere_hybrid_sigma_pressure_coordinate", 
+    "atmosphere_hybrid_sigma_pressure_coordinate",
     "atmosphere_hybrid_height_coordinate",
     "atmosphere_sleve_coordinate", "ocean_sigma_coordinate",
     "ocean_s_coordinate", "ocean_sigma_z_coordinate",
     "ocean_double_sigma_coordinate", "atmosphere_ln_pressure_coordinate",
-    "atmosphere_sigma_coordinate", 
+    "atmosphere_sigma_coordinate",
     "atmosphere_hybrid_sigma_pressure_coordinate",
     "atmosphere_hybrid_height_coordinate",
     "atmosphere_sleve_coordinate", "ocean_sigma_coordinate",
     "ocean_s_coordinate", "ocean_sigma_z_coordinate",
     "ocean_double_sigma_coordinate", NULL };
 
-static const char* papszCFTimeAttribNames[] = { "axis", NULL };
-static const char* papszCFTimeAttribValues[] = { "T", NULL };
-static const char* papszCFTimeUnitsValues[] = { 
-    "days since", "day since", "d since", 
-    "hours since", "hour since", "h since", "hr since", 
-    "minutes since", "minute since", "min since", 
-    "seconds since", "second since", "sec since", "s since", 
+static const char* const papszCFTimeAttribNames[] = { CF_AXIS, NULL };
+static const char* const papszCFTimeAttribValues[] = { "T", NULL };
+static const char* const papszCFTimeUnitsValues[] = {
+    "days since", "day since", "d since",
+    "hours since", "hour since", "h since", "hr since",
+    "minutes since", "minute since", "min since",
+    "seconds since", "second since", "sec since", "s since",
     NULL };
 
 
@@ -258,41 +281,41 @@ static const char* papszCFTimeUnitsValues[] = {
 /* A struct allowing us to map between GDAL(OGC WKT) and CF-1 attributes */
 typedef struct {
     const char *CF_ATT;
-    const char *WKT_ATT; 
+    const char *WKT_ATT;
     // TODO: mappings may need default values, like scale factor?
     //double defval;
 } oNetcdfSRS_PP;
 
 // default mappings, for the generic case
-/* These 'generic' mappings are based on what was previously in the  
-   poNetCDFSRS struct. They will be used as a fallback in case none 
-   of the others match (ie you are exporting a projection that has 
-   no CF-1 equivalent). 
-   They are not used for known CF-1 projections since there is not a 
-   unique 2-way projection-independent 
-   mapping between OGC WKT params and CF-1 ones: it varies per-projection. 
-*/ 
+/* These 'generic' mappings are based on what was previously in the
+   poNetCDFSRS struct. They will be used as a fallback in case none
+   of the others match (i.e. you are exporting a projection that has
+   no CF-1 equivalent).
+   They are not used for known CF-1 projections since there is not a
+   unique 2-way projection-independent
+   mapping between OGC WKT params and CF-1 ones: it varies per-projection.
+*/
 
 static const oNetcdfSRS_PP poGenericMappings[] = {
     /* scale_factor is handled as a special case, write 2 values */
-    {CF_PP_STD_PARALLEL_1, SRS_PP_STANDARD_PARALLEL_1 }, 
-    {CF_PP_STD_PARALLEL_2, SRS_PP_STANDARD_PARALLEL_2 }, 
-    {CF_PP_LONG_CENTRAL_MERIDIAN, SRS_PP_CENTRAL_MERIDIAN }, 
-    {CF_PP_LONG_CENTRAL_MERIDIAN, SRS_PP_LONGITUDE_OF_CENTER }, 
-    {CF_PP_LON_PROJ_ORIGIN, SRS_PP_LONGITUDE_OF_ORIGIN },  
-    //Multiple mappings to LAT_PROJ_ORIGIN 
-    {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_ORIGIN },  
-    {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_CENTER },  
-    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },   
-    {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },        
+    {CF_PP_STD_PARALLEL_1, SRS_PP_STANDARD_PARALLEL_1 },
+    {CF_PP_STD_PARALLEL_2, SRS_PP_STANDARD_PARALLEL_2 },
+    {CF_PP_LONG_CENTRAL_MERIDIAN, SRS_PP_CENTRAL_MERIDIAN },
+    {CF_PP_LONG_CENTRAL_MERIDIAN, SRS_PP_LONGITUDE_OF_CENTER },
+    {CF_PP_LON_PROJ_ORIGIN, SRS_PP_LONGITUDE_OF_ORIGIN },
+    //Multiple mappings to LAT_PROJ_ORIGIN
+    {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_ORIGIN },
+    {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_CENTER },
+    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },
+    {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
     {NULL, NULL },
 };
 
-// Albers equal area 
+// Albers equal area
 //
 // grid_mapping_name = albers_conical_equal_area
 // WKT: Albers_Conic_Equal_Area
-// ESPG:9822 
+// ESPG:9822
 //
 // Map parameters:
 //
@@ -307,7 +330,7 @@ static const oNetcdfSRS_PP poAEAMappings[] = {
     {CF_PP_STD_PARALLEL_2, SRS_PP_STANDARD_PARALLEL_2},
     {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_CENTER},
     {CF_PP_LONG_CENTRAL_MERIDIAN, SRS_PP_LONGITUDE_OF_CENTER},
-    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },  
+    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },
     {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
     {NULL, NULL}
  };
@@ -327,7 +350,7 @@ static const oNetcdfSRS_PP poAEAMappings[] = {
 static const oNetcdfSRS_PP poAEMappings[] = {
     {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_CENTER},
     {CF_PP_LON_PROJ_ORIGIN, SRS_PP_LONGITUDE_OF_CENTER},
-    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },  
+    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },
     {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
     {NULL, NULL}
  };
@@ -347,7 +370,7 @@ static const oNetcdfSRS_PP poAEMappings[] = {
 static const oNetcdfSRS_PP poLAEAMappings[] = {
     {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_CENTER},
     {CF_PP_LON_PROJ_ORIGIN, SRS_PP_LONGITUDE_OF_CENTER},
-    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },  
+    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },
     {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
     {NULL, NULL}
  };
@@ -365,7 +388,7 @@ static const oNetcdfSRS_PP poLAEAMappings[] = {
 //    * false_easting
 //    * false_northing
 //
-// See http://www.remotesensing.org/geotiff/proj_list/lambert_conic_conformal_1sp.html 
+// See http://www.remotesensing.org/geotiff/proj_list/lambert_conic_conformal_1sp.html
 
 // Lambert conformal conic - 1SP
 /* See bug # 3324
@@ -380,7 +403,7 @@ static const oNetcdfSRS_PP poLCC1SPMappings[] = {
     {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_ORIGIN},
     {CF_PP_LONG_CENTRAL_MERIDIAN, SRS_PP_CENTRAL_MERIDIAN},
     {CF_PP_SCALE_FACTOR_ORIGIN, SRS_PP_SCALE_FACTOR}, /* special case */
-    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },  
+    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },
     {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
     {NULL, NULL}
  };
@@ -391,7 +414,7 @@ static const oNetcdfSRS_PP poLCC2SPMappings[] = {
     {CF_PP_STD_PARALLEL_2, SRS_PP_STANDARD_PARALLEL_2},
     {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_ORIGIN},
     {CF_PP_LONG_CENTRAL_MERIDIAN, SRS_PP_CENTRAL_MERIDIAN},
-    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },  
+    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },
     {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
     {NULL, NULL}
  };
@@ -400,7 +423,7 @@ static const oNetcdfSRS_PP poLCC2SPMappings[] = {
 //
 // grid_mapping_name = lambert_cylindrical_equal_area
 // WKT: Cylindrical_Equal_Area
-// EPSG:9834 (Spherical) and EPSG:9835 
+// EPSG:9834 (Spherical) and EPSG:9835
 //
 // Map parameters:
 //
@@ -409,14 +432,14 @@ static const oNetcdfSRS_PP poLCC2SPMappings[] = {
 //    * false_easting
 //    * false_northing
 //
-// NB: CF-1 specifies a 'scale_factor_at_projection' alternative  
-//  to std_parallel ... but no reference to this in EPSG/remotesensing.org 
-//  ignore for now. 
+// NB: CF-1 specifies a 'scale_factor_at_projection' alternative
+//  to std_parallel ... but no reference to this in EPSG/remotesensing.org
+//  ignore for now.
 //
 static const oNetcdfSRS_PP poLCEAMappings[] = {
     {CF_PP_STD_PARALLEL_1, SRS_PP_STANDARD_PARALLEL_1},
     {CF_PP_LONG_CENTRAL_MERIDIAN, SRS_PP_CENTRAL_MERIDIAN},
-    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },  
+    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },
     {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
     {NULL, NULL}
  };
@@ -444,12 +467,12 @@ static const oNetcdfSRS_PP poLCEAMappings[] = {
 //    * false_easting
 //    * false_northing
 
-// Mercator 1 Standard Parallel (EPSG:9804) 
+// Mercator 1 Standard Parallel (EPSG:9804)
 static const oNetcdfSRS_PP poM1SPMappings[] = {
     {CF_PP_LON_PROJ_ORIGIN, SRS_PP_CENTRAL_MERIDIAN},
-    //LAT_PROJ_ORIGIN is always equator (0) in CF-1 
+    //LAT_PROJ_ORIGIN is always equator (0) in CF-1
     {CF_PP_SCALE_FACTOR_ORIGIN, SRS_PP_SCALE_FACTOR},
-    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },  
+    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },
     {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
     {NULL, NULL}
  };
@@ -458,10 +481,10 @@ static const oNetcdfSRS_PP poM1SPMappings[] = {
 static const oNetcdfSRS_PP poM2SPMappings[] = {
     {CF_PP_LON_PROJ_ORIGIN, SRS_PP_CENTRAL_MERIDIAN},
     {CF_PP_STD_PARALLEL_1, SRS_PP_STANDARD_PARALLEL_1},
-    //From best understanding of this projection, only  
- 	// actually specify one SP - it is the same N/S of equator. 
-    //{CF_PP_STD_PARALLEL_2, SRS_PP_LATITUDE_OF_ORIGIN}, 
-    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },  
+    //From best understanding of this projection, only
+ 	// actually specify one SP - it is the same N/S of equator.
+    //{CF_PP_STD_PARALLEL_2, SRS_PP_LATITUDE_OF_ORIGIN},
+    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },
     {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
     {NULL, NULL}
  };
@@ -480,10 +503,10 @@ static const oNetcdfSRS_PP poM2SPMappings[] = {
 static const oNetcdfSRS_PP poOrthoMappings[] = {
     {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_ORIGIN},
     {CF_PP_LON_PROJ_ORIGIN, SRS_PP_CENTRAL_MERIDIAN},
-    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },  
+    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },
     {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
     {NULL, NULL}
- }; 
+ };
 
 // Polar stereographic
 //
@@ -498,7 +521,7 @@ static const oNetcdfSRS_PP poOrthoMappings[] = {
 //    * false_easting
 //    * false_northing
 
-/* 
+/*
    (http://www.remotesensing.org/geotiff/proj_list/polar_stereographic.html)
 
    Note: Projection parameters for this projection are quite different in CF-1 from
@@ -510,16 +533,16 @@ static const oNetcdfSRS_PP poOrthoMappings[] = {
        depending on the sign of 'latitude_of_origin' in WKT.
    CF allows the use of standard_parallel (lat_ts in proj4) OR scale_factor (k0 in proj4).
    This is analogous to the B and A variants (resp.) in EPSG guidelines.
-   When importing a CF file with scale_factor, we compute standard_parallel using 
+   When importing a CF file with scale_factor, we compute standard_parallel using
      Snyder eq. 22-7 with k=1 and lat=standard_parallel.
-   Currently OGR does NOT relate the scale factor with the standard parallel, so we 
+   Currently OGR does NOT relate the scale factor with the standard parallel, so we
    use the default. It seems that proj4 uses lat_ts (standard_parallel) and not k0.
 */
 static const oNetcdfSRS_PP poPSmappings[] = {
     {CF_PP_STD_PARALLEL_1, SRS_PP_LATITUDE_OF_ORIGIN},
     /* {CF_PP_SCALE_FACTOR_ORIGIN, SRS_PP_SCALE_FACTOR},   */
     {CF_PP_VERT_LONG_FROM_POLE, SRS_PP_CENTRAL_MERIDIAN},
-    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },  
+    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },
     {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
     {NULL, NULL}
 };
@@ -536,7 +559,7 @@ static const oNetcdfSRS_PP poPSmappings[] = {
 //    * north_pole_grid_longitude - This parameter is optional (default is 0.).
 
 /* TODO: No GDAL equivalent of rotated pole? Doesn't seem to have an EPSG
-   code or WKT ... so unless some advanced proj4 features can be used 
+   code or WKT ... so unless some advanced proj4 features can be used
    seems to rule out.
    see GDAL bug #4285 for a possible fix or workaround
 */
@@ -559,8 +582,8 @@ static const oNetcdfSRS_PP poPSmappings[] = {
 static const oNetcdfSRS_PP poStMappings[] = {
     {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_ORIGIN},
     {CF_PP_LON_PROJ_ORIGIN, SRS_PP_CENTRAL_MERIDIAN},
-    {CF_PP_SCALE_FACTOR_ORIGIN, SRS_PP_SCALE_FACTOR},  
-    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },  
+    {CF_PP_SCALE_FACTOR_ORIGIN, SRS_PP_SCALE_FACTOR},
+    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },
     {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
     {NULL, NULL}
   };
@@ -579,10 +602,10 @@ static const oNetcdfSRS_PP poStMappings[] = {
 //    * false_northing
 //
 static const oNetcdfSRS_PP poTMMappings[] = {
-    {CF_PP_SCALE_FACTOR_MERIDIAN, SRS_PP_SCALE_FACTOR},  
+    {CF_PP_SCALE_FACTOR_MERIDIAN, SRS_PP_SCALE_FACTOR},
     {CF_PP_LONG_CENTRAL_MERIDIAN, SRS_PP_CENTRAL_MERIDIAN},
     {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_ORIGIN},
-    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },  
+    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },
     {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
     {NULL, NULL}
   };
@@ -603,13 +626,24 @@ static const oNetcdfSRS_PP poTMMappings[] = {
 // TODO: see how to map this to OGR
 
 
-/* Mappings for various projections, including netcdf and GDAL projection names 
-   and corresponding oNetcdfSRS_PP mapping struct. 
+static const oNetcdfSRS_PP poGEOSMappings[] = {
+    {CF_PP_LON_PROJ_ORIGIN, SRS_PP_CENTRAL_MERIDIAN},
+    {CF_PP_PERSPECTIVE_POINT_HEIGHT, SRS_PP_SATELLITE_HEIGHT},
+    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },
+    {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
+    /* { CF_PP_SWEEP_ANGLE_AXIS, .... } handled as a proj.4 extension */
+    {NULL, NULL}
+  };
+
+
+
+/* Mappings for various projections, including netcdf and GDAL projection names
+   and corresponding oNetcdfSRS_PP mapping struct.
    A NULL mappings value means that the projection is not included in the CF
    standard and the generic mapping (poGenericMappings) will be used. */
 typedef struct {
     const char *CF_SRS;
-    const char *WKT_SRS; 
+    const char *WKT_SRS;
     const oNetcdfSRS_PP* mappings;
 } oNetcdfSRS_PT;
 
@@ -618,16 +652,16 @@ static const oNetcdfSRS_PT poNetcdfSRS_PT[] = {
     {CF_PT_AE, SRS_PT_AZIMUTHAL_EQUIDISTANT, poAEMappings },
     {"cassini_soldner", SRS_PT_CASSINI_SOLDNER, NULL },
     {CF_PT_LCEA, SRS_PT_CYLINDRICAL_EQUAL_AREA, poLCEAMappings },
-    {"eckert_iv", SRS_PT_ECKERT_IV, NULL },      
-    {"eckert_vi", SRS_PT_ECKERT_VI, NULL },  
+    {"eckert_iv", SRS_PT_ECKERT_IV, NULL },
+    {"eckert_vi", SRS_PT_ECKERT_VI, NULL },
     {"equidistant_conic", SRS_PT_EQUIDISTANT_CONIC, NULL },
     {"equirectangular", SRS_PT_EQUIRECTANGULAR, NULL },
     {"gall_stereographic", SRS_PT_GALL_STEREOGRAPHIC, NULL },
-    {"geostationary_satellite", SRS_PT_GEOSTATIONARY_SATELLITE, NULL },
+    {CF_PT_GEOS, SRS_PT_GEOSTATIONARY_SATELLITE, poGEOSMappings },
     {"goode_homolosine", SRS_PT_GOODE_HOMOLOSINE, NULL },
     {"gnomonic", SRS_PT_GNOMONIC, NULL },
     {"hotine_oblique_mercator", SRS_PT_HOTINE_OBLIQUE_MERCATOR, NULL },
-    {"hotine_oblique_mercator_2P", 
+    {"hotine_oblique_mercator_2P",
      SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN, NULL },
     {"laborde_oblique_mercator", SRS_PT_LABORDE_OBLIQUE_MERCATOR, NULL },
     {CF_PT_LCC, SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP, poLCC1SPMappings },
@@ -639,13 +673,13 @@ static const oNetcdfSRS_PT poNetcdfSRS_PT[] = {
     {"mollweide", SRS_PT_MOLLWEIDE, NULL },
     {"new_zealand_map_grid", SRS_PT_NEW_ZEALAND_MAP_GRID, NULL },
     /* for now map to STEREO, see bug #4267 */
-    {"oblique_stereographic", SRS_PT_OBLIQUE_STEREOGRAPHIC, NULL }, 
+    {"oblique_stereographic", SRS_PT_OBLIQUE_STEREOGRAPHIC, NULL },
     /* {STEREO, SRS_PT_OBLIQUE_STEREOGRAPHIC, poStMappings },  */
     {CF_PT_ORTHOGRAPHIC, SRS_PT_ORTHOGRAPHIC, poOrthoMappings },
     {CF_PT_POLAR_STEREO, SRS_PT_POLAR_STEREOGRAPHIC, poPSmappings },
     {"polyconic", SRS_PT_POLYCONIC, NULL },
-    {"robinson", SRS_PT_ROBINSON, NULL }, 
-    {"sinusoidal", SRS_PT_SINUSOIDAL, NULL },  
+    {"robinson", SRS_PT_ROBINSON, NULL },
+    {"sinusoidal", SRS_PT_SINUSOIDAL, NULL },
     {CF_PT_STEREO, SRS_PT_STEREOGRAPHIC, poStMappings },
     {"swiss_oblique_cylindrical", SRS_PT_SWISS_OBLIQUE_CYLINDRICAL, NULL },
     {CF_PT_TM, SRS_PT_TRANSVERSE_MERCATOR, poTMMappings },
@@ -655,15 +689,80 @@ static const oNetcdfSRS_PT poNetcdfSRS_PT[] = {
 
 /************************************************************************/
 /* ==================================================================== */
-/*			     netCDFDataset		                             		*/
+/*                        netCDFWriterConfig classes                    */
+/* ==================================================================== */
+/************************************************************************/
+
+class netCDFWriterConfigAttribute
+{
+    public:
+        CPLString m_osName;
+        CPLString m_osType;
+        CPLString m_osValue;
+
+        bool Parse(CPLXMLNode* psNode);
+};
+
+class netCDFWriterConfigField
+{
+    public:
+        CPLString m_osName;
+        CPLString m_osNetCDFName;
+        CPLString m_osMainDim;
+        std::vector<netCDFWriterConfigAttribute> m_aoAttributes;
+
+        bool Parse(CPLXMLNode* psNode);
+};
+
+class netCDFWriterConfigLayer
+{
+    public:
+        CPLString m_osName;
+        CPLString m_osNetCDFName;
+        std::map<CPLString, CPLString> m_oLayerCreationOptions;
+        std::vector<netCDFWriterConfigAttribute> m_aoAttributes;
+        std::map<CPLString, netCDFWriterConfigField> m_oFields;
+
+        bool Parse(CPLXMLNode* psNode);
+};
+
+class netCDFWriterConfiguration
+{
+    public:
+        bool m_bIsValid;
+        std::map<CPLString, CPLString> m_oDatasetCreationOptions;
+        std::map<CPLString, CPLString> m_oLayerCreationOptions;
+        std::vector<netCDFWriterConfigAttribute> m_aoAttributes;
+        std::map<CPLString, netCDFWriterConfigField> m_oFields;
+        std::map<CPLString, netCDFWriterConfigLayer> m_oLayers;
+
+        netCDFWriterConfiguration() : m_bIsValid(false) {}
+
+        bool Parse(const char* pszFilename);
+        static bool SetNameValue(CPLXMLNode* psNode,
+                                 std::map<CPLString,CPLString>& oMap);
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                           netCDFDataset                              */
 /* ==================================================================== */
 /************************************************************************/
 
 class netCDFRasterBand;
+class netCDFLayer;
 
 class netCDFDataset : public GDALPamDataset
 {
     friend class netCDFRasterBand; //TMP
+    friend class netCDFLayer;
+
+    typedef enum
+    {
+        SINGLE_LAYER,
+        SEPARATE_FILES,
+        SEPARATE_GROUPS
+    } MultipleLayerBehaviour;
 
     /* basic dataset vars */
     CPLString     osFilename;
@@ -672,73 +771,92 @@ class netCDFDataset : public GDALPamDataset
     char          **papszMetadata;
     CPLStringList papszDimName;
     bool          bBottomUp;
-    int           nFormat;
-    int           bIsGdalFile; /* was this file created by GDAL? */
-    int           bIsGdalCfFile; /* was this file created by the (new) CF-compliant driver? */
+    NetCDFFormatEnum eFormat;
+    bool          bIsGdalFile; /* was this file created by GDAL? */
+    bool          bIsGdalCfFile; /* was this file created by the (new) CF-compliant driver? */
     char         *pszCFProjection;
     char         *pszCFCoordinates;
+    MultipleLayerBehaviour eMultipleLayerBehaviour;
+    std::vector<netCDFDataset*> apoVectorDatasets;
 
     /* projection/GT */
     double       adfGeoTransform[6];
     char         *pszProjection;
     int          nXDimID;
     int          nYDimID;
-    int          bIsProjected;
-    int          bIsGeographic;
+    bool         bIsProjected;
+    bool         bIsGeographic;
 
     /* state vars */
-    int          status;
-    int          bDefineMode;
-    int          bSetProjection; 
-    int          bSetGeoTransform;
-    int          bAddedProjectionVars;
-    int          bAddedGridMappingRef;
+    bool         bDefineMode;
+    bool         bSetProjection;
+    bool         bSetGeoTransform;
+    bool         bAddedProjectionVars;
+    bool         bAddedGridMappingRef;
 
     /* create vars */
     char         **papszCreationOptions;
-    int          nCompress;
+    NetCDFCompressEnum eCompress;
     int          nZLevel;
-    int          bChunking;
+#ifdef NETCDF_HAS_NC4
+    bool         bChunking;
+#endif
     int          nCreateMode;
-    int          bSignedData;
+    bool         bSignedData;
+
+    int          nLayers;
+    netCDFLayer   **papoLayers;
 
-    double       rint( double );
+    netCDFWriterConfiguration oWriterConfig;
 
-    double       FetchCopyParm( const char *pszGridMappingValue, 
+    static double       rint( double );
+
+    double       FetchCopyParm( const char *pszGridMappingValue,
                                 const char *pszParm, double dfDefault );
 
     char **      FetchStandardParallels( const char *pszGridMappingValue );
 
     void ProcessCreationOptions( );
-    int DefVarDeflate( int nVarId, int bChunkingArg=TRUE );
-    CPLErr AddProjectionVars( GDALProgressFunc pfnProgress=GDALDummyProgress, 
+    int DefVarDeflate( int nVarId, bool bChunkingArg=true );
+    CPLErr AddProjectionVars( GDALProgressFunc pfnProgress=GDALDummyProgress,
                               void * pProgressData=NULL );
-    void AddGridMappingRef(); 
+    void AddGridMappingRef();
 
-    int GetDefineMode() { return bDefineMode; }
-    int SetDefineMode( int bNewDefineMode );
+    bool GetDefineMode() { return bDefineMode; }
+    bool SetDefineMode( bool bNewDefineMode );
 
     CPLErr      ReadAttributes( int, int );
 
     void  CreateSubDatasetList( );
 
-    void  SetProjectionFromVar( int );
+    void  SetProjectionFromVar( int, bool bReadSRSOnly );
 
     int ProcessCFGeolocation( int );
     CPLErr Set1DGeolocation( int nVarId, const char *szDimName );
     double * Get1DGeolocation( const char *szDimName, int &nVarLen );
 
+    static bool CloneAttributes(int old_cdfid, int new_cdfid, int nSrcVarId, int nDstVarId);
+    static bool CloneVariableContent(int old_cdfid, int new_cdfid, int nSrcVarId, int nDstVarId);
+    static bool CloneGrp(int nOldGrpId, int nNewGrpId, bool bIsNC4, int nLayerId,
+                         int nDimIdToGrow, size_t nNewSize);
+    bool GrowDim(int nLayerId, int nDimIdToGrow, size_t nNewSize);
+
   protected:
 
     CPLXMLNode *SerializeToXML( const char *pszVRTPath );
 
+    virtual OGRLayer   *ICreateLayer( const char *pszName,
+                                     OGRSpatialReference *poSpatialRef,
+                                     OGRwkbGeometryType eGType,
+                                     char ** papszOptions );
+
   public:
 
-    netCDFDataset( );
-    ~netCDFDataset( );
-    
+    netCDFDataset();
+    virtual ~netCDFDataset();
+
     /* Projection/GT */
-    CPLErr 	GetGeoTransform( double * );    
+    CPLErr 	GetGeoTransform( double * );
     CPLErr 	SetGeoTransform (double *);
     const char * GetProjectionRef();
     CPLErr 	SetProjection (const char *);
@@ -746,11 +864,16 @@ class netCDFDataset : public GDALPamDataset
     virtual char      **GetMetadataDomainList();
     char ** GetMetadata( const char * );
 
+    virtual int  TestCapability(const char* pszCap);
+
+    virtual int  GetLayerCount() { return nLayers; }
+    virtual OGRLayer* GetLayer(int nIdx);
+
     int GetCDFID() { return cdfid; }
 
     /* static functions */
     static int Identify( GDALOpenInfo * );
-    static int IdentifyFormat( GDALOpenInfo *, bool );
+    static NetCDFFormatEnum IdentifyFormat( GDALOpenInfo *, bool );
     static GDALDataset *Open( GDALOpenInfo * );
 
     static netCDFDataset *CreateLL( const char * pszFilename,
@@ -760,10 +883,132 @@ class netCDFDataset : public GDALPamDataset
                                 int nXSize, int nYSize, int nBands,
                                 GDALDataType eType,
                                 char ** papszOptions );
-    static GDALDataset* CreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
-                                    int bStrict, char ** papszOptions, 
+    static GDALDataset* CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
+                                    int bStrict, char ** papszOptions,
                                     GDALProgressFunc pfnProgress, void * pProgressData );
-        
 };
 
+class netCDFLayer: public OGRLayer
+{
+        typedef union
+        {
+            signed char chVal;
+            unsigned char uchVal;
+            short   sVal;
+            unsigned short usVal;
+            int     nVal;
+            unsigned int unVal;
+            GIntBig nVal64;
+            GUIntBig unVal64;
+            float   fVal;
+            double  dfVal;
+        } NCDFNoDataUnion;
+
+        typedef struct
+        {
+            NCDFNoDataUnion uNoData;
+            nc_type         nType;
+            int             nVarId;
+            int             nDimCount;
+            bool            bHasWarnedAboutTruncation;
+            int             nMainDimId;
+            int             nSecDimId;
+            bool            bIsDays;
+        } FieldDesc;
+
+        netCDFDataset  *m_poDS;
+        int             m_nLayerCDFId;
+        OGRFeatureDefn *m_poFeatureDefn;
+        CPLString       m_osRecordDimName;
+        int             m_nRecordDimID;
+        int             m_nDefaultWidth;
+        bool            m_bAutoGrowStrings;
+        int             m_nDefaultMaxWidthDimId;
+        int             m_nXVarID;
+        int             m_nYVarID;
+        int             m_nZVarID;
+        nc_type         m_nXVarNCDFType;
+        nc_type         m_nYVarNCDFType;
+        nc_type         m_nZVarNCDFType;
+        NCDFNoDataUnion m_uXVarNoData;
+        NCDFNoDataUnion m_uYVarNoData;
+        NCDFNoDataUnion m_uZVarNoData;
+        CPLString       m_osWKTVarName;
+        int             m_nWKTMaxWidth;
+        int             m_nWKTMaxWidthDimId;
+        int             m_nWKTVarID;
+        nc_type         m_nWKTNCDFType;
+        CPLString       m_osCoordinatesValue;
+        std::vector<FieldDesc> m_aoFieldDesc;
+        int             m_nCurFeatureId;
+        CPLString       m_osGridMapping;
+        bool            m_bWriteGDALTags;
+        bool            m_bUseStringInNC4;
+        bool            m_bNCDumpCompat;
+
+        CPLString       m_osProfileDimName;
+        int             m_nProfileDimID;
+        CPLString       m_osProfileVariables;
+        int             m_nProfileVarID;
+        bool            m_bProfileVarUnlimited;
+        int             m_nParentIndexVarID;
+
+        const netCDFWriterConfigLayer* m_poLayerConfig;
+
+        OGRFeature     *GetNextRawFeature();
+        double          Get1DVarAsDouble( int nVarId, nc_type nVarType,
+                                          size_t nIndex,
+                                          NCDFNoDataUnion noDataVal,
+                                          bool* pbIsNoData );
+        CPLErr          GetFillValue( int nVarID, char **ppszValue );
+        CPLErr          GetFillValue( int nVarID, double *pdfValue );
+        void            GetNoDataValueForFloat( int nVarId, NCDFNoDataUnion* puNoData );
+        void            GetNoDataValueForDouble( int nVarId, NCDFNoDataUnion* puNoData );
+        void            GetNoDataValue( int nVarId, nc_type nVarType, NCDFNoDataUnion* puNoData );
+        bool            FillFeatureFromVar(OGRFeature* poFeature, int nMainDimId, size_t nIndex);
+        bool            FillVarFromFeature(OGRFeature* poFeature, int nMainDimId, size_t nIndex);
+
+    public:
+                netCDFLayer(netCDFDataset* poDS,
+                            int nLayerCDFId,
+                            const char* pszName,
+                            OGRwkbGeometryType eGeomType,
+                            OGRSpatialReference* poSRS);
+        virtual ~netCDFLayer();
+
+        bool            Create(char** papszOptions, const netCDFWriterConfigLayer* poLayerConfig);
+        void            SetRecordDimID(int nRecordDimID);
+        void            SetXYZVars(int nXVarId, int nYVarId, int nZVarId);
+        void            SetWKTGeometryField(const char* pszWKTVarName);
+        void            SetGridMapping(const char* pszGridMapping);
+        void            SetProfile(int nProfileDimID, int nParentIndexVarID);
+        bool            AddField(int nVarId);
+
+        int             GetCDFID() const { return m_nLayerCDFId; }
+        void            SetCDFID(int nId) { m_nLayerCDFId = nId; }
+
+        virtual void ResetReading();
+        virtual OGRFeature* GetNextFeature();
+
+        virtual GIntBig GetFeatureCount(int bForce);
+
+        virtual int  TestCapability(const char* pszCap);
+
+        virtual OGRFeatureDefn* GetLayerDefn();
+
+        virtual OGRErr ICreateFeature(OGRFeature* poFeature);
+        virtual OGRErr CreateField(OGRFieldDefn* poFieldDefn, int bApproxOK);
+};
+
+void NCDFWriteLonLatVarsAttributes(int cdfid, int nVarLonID, int nVarLatID);
+void NCDFWriteXYVarsAttributes(int cdfid, int nVarXID, int nVarYID,
+                                      OGRSpatialReference* poSRS);
+int NCDFWriteSRSVariable(int cdfid, OGRSpatialReference* poSRS,
+                                char** ppszCFProjection, bool bWriteGDALTags);
+CPLErr NCDFGetAttr( int nCdfId, int nVarId, const char *pszAttrName,
+                    double *pdfValue );
+CPLErr NCDFGetAttr( int nCdfId, int nVarId, const char *pszAttrName,
+                    char **pszValue );
+bool NCDFIsUnlimitedDim(bool bIsNC4, int cdfid, int nDimId);
+
 #endif
diff --git a/frmts/netcdf/netcdflayer.cpp b/frmts/netcdf/netcdflayer.cpp
new file mode 100644
index 0000000..af438c9
--- /dev/null
+++ b/frmts/netcdf/netcdflayer.cpp
@@ -0,0 +1,2359 @@
+/******************************************************************************
+ * $Id: netcdflayer.cpp 33720 2016-03-15 00:39:53Z goatbar $
+ *
+ * Project:  netCDF read/write Driver
+ * Purpose:  GDAL bindings over netCDF library.
+ * Author:   Even Rouault <even.rouault at spatialys.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "netcdfdataset.h"
+#include "cpl_time.h"
+
+CPL_CVSID("$Id: netcdflayer.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+
+/************************************************************************/
+/*                            netCDFLayer()                             */
+/************************************************************************/
+
+netCDFLayer::netCDFLayer(netCDFDataset* poDS,
+                         int nLayerCDFId,
+                         const char* pszName,
+                         OGRwkbGeometryType eGeomType,
+                         OGRSpatialReference* poSRS) :
+        m_poDS(poDS),
+        m_nLayerCDFId(nLayerCDFId),
+        m_poFeatureDefn(new OGRFeatureDefn(pszName)),
+        m_osRecordDimName("record"),
+        m_nRecordDimID(-1),
+        m_nDefaultWidth(10),
+        m_bAutoGrowStrings(true),
+        m_nDefaultMaxWidthDimId(-1),
+        m_nXVarID(-1),
+        m_nYVarID(-1),
+        m_nZVarID(-1),
+        m_nXVarNCDFType(NC_NAT),
+        m_nYVarNCDFType(NC_NAT),
+        m_nZVarNCDFType(NC_NAT),
+        m_osWKTVarName("ogc_wkt"),
+        m_nWKTMaxWidth(10000),
+        m_nWKTMaxWidthDimId(-1),
+        m_nWKTVarID(-1),
+        m_nWKTNCDFType(NC_NAT),
+        m_nCurFeatureId(1),
+        m_bWriteGDALTags(true),
+        m_bUseStringInNC4(true),
+        m_bNCDumpCompat(true),
+        m_nProfileDimID(-1),
+        m_nProfileVarID(-1),
+        m_bProfileVarUnlimited(false),
+        m_nParentIndexVarID(-1),
+        m_poLayerConfig(NULL)
+{
+    m_uXVarNoData.nVal64 = 0;
+    m_uYVarNoData.nVal64 = 0;
+    m_uZVarNoData.nVal64 = 0;
+    m_poFeatureDefn->SetGeomType(eGeomType);
+    if( eGeomType != wkbNone )
+        m_poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
+    m_poFeatureDefn->Reference();
+    SetDescription(pszName);
+}
+
+/************************************************************************/
+/*                           ~netCDFLayer()                             */
+/************************************************************************/
+
+netCDFLayer::~netCDFLayer()
+{
+    m_poFeatureDefn->Release();
+}
+
+/************************************************************************/
+/*                   netCDFWriteAttributesFromConf()                    */
+/************************************************************************/
+
+static void netCDFWriteAttributesFromConf( int cdfid, int varid,
+                    const std::vector<netCDFWriterConfigAttribute>& aoAttributes)
+{
+    for(size_t i=0; i < aoAttributes.size(); i++)
+    {
+        const netCDFWriterConfigAttribute& oAtt = aoAttributes[i];
+        int status = NC_NOERR;
+        if( oAtt.m_osValue.size() == 0 )
+        {
+            int attid = -1;
+            status = nc_inq_attid( cdfid, varid, oAtt.m_osName, &attid );
+            if( status == NC_NOERR )
+                status = nc_del_att( cdfid, varid, oAtt.m_osName );
+            else
+                status = NC_NOERR;
+        }
+        else if( EQUAL(oAtt.m_osType, "string") )
+        {
+            status = nc_put_att_text( cdfid, varid, oAtt.m_osName,
+                                        oAtt.m_osValue.size(), oAtt.m_osValue );
+        }
+        else if( EQUAL(oAtt.m_osType, "integer") )
+        {
+            int nVal = atoi( oAtt.m_osValue );
+            status = nc_put_att_int( cdfid, varid, oAtt.m_osName,
+                                        NC_INT, 1, &nVal );
+        }
+        else if( EQUAL(oAtt.m_osType, "double") )
+        {
+            double dfVal = CPLAtof( oAtt.m_osValue );
+            status = nc_put_att_double( cdfid, varid, oAtt.m_osName,
+                                        NC_DOUBLE, 1, &dfVal );
+        }
+        NCDF_ERR(status);
+    }
+}
+
+/************************************************************************/
+/*                               Create()                               */
+/************************************************************************/
+
+bool netCDFLayer::Create(char** papszOptions,
+                         const netCDFWriterConfigLayer* poLayerConfig)
+{
+    m_osRecordDimName = CSLFetchNameValueDef(papszOptions, "RECORD_DIM_NAME",
+                                             m_osRecordDimName.c_str());
+    m_bAutoGrowStrings = CPL_TO_BOOL(CSLFetchBoolean(papszOptions, "AUTOGROW_STRINGS", TRUE ));
+    m_nDefaultWidth = atoi(CSLFetchNameValueDef(papszOptions,
+                                                "STRING_DEFAULT_WIDTH",
+                                                CPLSPrintf("%d", m_bAutoGrowStrings ? 10 : 80)));
+    m_bWriteGDALTags = CPL_TO_BOOL(CSLFetchBoolean(
+                    m_poDS->papszCreationOptions, "WRITE_GDAL_TAGS", TRUE ));
+    m_bUseStringInNC4 = CPL_TO_BOOL(CSLFetchBoolean(
+                                papszOptions, "USE_STRING_IN_NC4", TRUE ));
+    m_bNCDumpCompat = CPL_TO_BOOL(CSLFetchBoolean(
+                                papszOptions, "NCDUMP_COMPAT", TRUE ));
+
+    std::vector< std::pair<CPLString, int> > aoAutoVariables;
+
+    const char* pszFeatureType = CSLFetchNameValue(papszOptions,"FEATURE_TYPE");
+    if( pszFeatureType != NULL )
+    {
+        if( EQUAL(pszFeatureType, "POINT") )
+        {
+            if( wkbFlatten(m_poFeatureDefn->GetGeomType()) != wkbPoint )
+            {
+                CPLError(CE_Warning, CPLE_NotSupported,
+                         "FEATURE_TYPE=POINT only supported for Point layer geometry type.");
+            }
+        }
+        else if( EQUAL(pszFeatureType, "PROFILE") )
+        {
+            if( wkbFlatten(m_poFeatureDefn->GetGeomType()) != wkbPoint )
+            {
+                CPLError(CE_Warning, CPLE_NotSupported,
+                         "FEATURE_TYPE=PROFILE only supported for Point layer geometry type.");
+            }
+            else
+            {
+                /* Cf http://cfconventions.org/cf-conventions/v1.6.0/cf-conventions.html#_indexed_ragged_array_representation_of_profiles */
+
+                m_osProfileDimName = CSLFetchNameValueDef(papszOptions, "PROFILE_DIM_NAME", "profile");
+                m_osProfileVariables = CSLFetchNameValueDef(papszOptions, "PROFILE_VARIABLES", "");
+
+                const char* pszProfileInitSize = CSLFetchNameValueDef(
+                        papszOptions, "PROFILE_DIM_INIT_SIZE",
+                        (m_poDS->eFormat == NCDF_FORMAT_NC4 ) ? "UNLIMITED" : "100");
+                m_bProfileVarUnlimited = EQUAL(pszProfileInitSize, "UNLIMITED");
+                size_t nProfileInitSize = m_bProfileVarUnlimited ?
+                    NC_UNLIMITED : static_cast<size_t>(atoi(pszProfileInitSize));
+                int status = nc_def_dim( m_nLayerCDFId, m_osProfileDimName,
+                                         nProfileInitSize, &m_nProfileDimID );
+                NCDF_ERR(status);
+                if( status != NC_NOERR )
+                    return false;
+
+                status = nc_def_var( m_nLayerCDFId, m_osProfileDimName, NC_INT,
+                                     1, &m_nProfileDimID,
+                                     &m_nProfileVarID);
+                NCDF_ERR(status);
+                if( status != NC_NOERR )
+                    return false;
+
+                aoAutoVariables.push_back(
+                    std::pair<CPLString,int>(m_osProfileDimName, m_nProfileVarID) );
+
+                status = nc_put_att_text( m_nLayerCDFId, m_nProfileVarID, "cf_role",
+                                          strlen("profile_id"), "profile_id" );
+                NCDF_ERR(status);
+            }
+        }
+        else if( !EQUAL(pszFeatureType, "AUTO") )
+        {
+            CPLError(CE_Warning, CPLE_NotSupported,
+                     "FEATURE_TYPE=%s not supported.", pszFeatureType);
+        }
+    }
+
+    int status;
+    if( m_bWriteGDALTags )
+    {
+        status = nc_put_att_text( m_nLayerCDFId, NC_GLOBAL, "ogr_layer_name",
+                        strlen(m_poFeatureDefn->GetName()), m_poFeatureDefn->GetName());
+        NCDF_ERR(status);
+    }
+
+    status = nc_def_dim( m_nLayerCDFId, m_osRecordDimName,
+                             NC_UNLIMITED, &m_nRecordDimID );
+    NCDF_ERR(status);
+    if( status != NC_NOERR )
+        return false;
+
+    if( m_osProfileDimName.size() )
+    {
+        status = nc_def_var( m_nLayerCDFId, "parentIndex", NC_INT,
+                             1, &m_nRecordDimID, &m_nParentIndexVarID );
+        NCDF_ERR(status);
+        if( status != NC_NOERR )
+            return false;
+
+        aoAutoVariables.push_back( std::pair<CPLString,int>("parentIndex", m_nParentIndexVarID) );
+
+        status = nc_put_att_text( m_nLayerCDFId, m_nParentIndexVarID, CF_LNG_NAME,
+                                  strlen("index of profile"), "index of profile" );
+        NCDF_ERR(status);
+
+        status = nc_put_att_text( m_nLayerCDFId, m_nParentIndexVarID, "instance_dimension",
+                                  m_osProfileDimName.size(), m_osProfileDimName.c_str() );
+        NCDF_ERR(status);
+    }
+
+    OGRSpatialReference* poSRS = NULL;
+    if( m_poFeatureDefn->GetGeomFieldCount() )
+        poSRS = m_poFeatureDefn->GetGeomFieldDefn(0)->GetSpatialRef();
+
+    if( wkbFlatten(m_poFeatureDefn->GetGeomType()) == wkbPoint )
+    {
+        const int nPointDim = m_osProfileDimName.size() ? m_nProfileDimID : m_nRecordDimID;
+        const bool bIsGeographic = (poSRS == NULL || poSRS->IsGeographic());
+
+        const char* pszXVarName =
+                bIsGeographic ? CF_LONGITUDE_VAR_NAME : CF_PROJ_X_VAR_NAME;
+        status = nc_def_var( m_nLayerCDFId,
+                             pszXVarName,
+                             NC_DOUBLE, 1, &nPointDim, &m_nXVarID);
+        NCDF_ERR(status);
+        if ( status != NC_NOERR ) {
+            return false;
+        }
+
+        const char* pszYVarName =
+                bIsGeographic ? CF_LATITUDE_VAR_NAME : CF_PROJ_Y_VAR_NAME;
+        status = nc_def_var( m_nLayerCDFId,
+                             pszYVarName,
+                             NC_DOUBLE, 1, &nPointDim, &m_nYVarID);
+        NCDF_ERR(status);
+        if ( status != NC_NOERR ) {
+            return false;
+        }
+
+        aoAutoVariables.push_back( std::pair<CPLString,int>(pszXVarName, m_nXVarID) );
+        aoAutoVariables.push_back( std::pair<CPLString,int>(pszYVarName, m_nYVarID) );
+
+        m_nXVarNCDFType = NC_DOUBLE;
+        m_nYVarNCDFType = NC_DOUBLE;
+        m_uXVarNoData.dfVal = NC_FILL_DOUBLE;
+        m_uYVarNoData.dfVal = NC_FILL_DOUBLE;
+
+        m_osCoordinatesValue = pszXVarName;
+        m_osCoordinatesValue += " ";
+        m_osCoordinatesValue += pszYVarName;
+
+        if (poSRS == NULL || poSRS->IsGeographic() )
+        {
+            NCDFWriteLonLatVarsAttributes(m_nLayerCDFId, m_nXVarID, m_nYVarID);
+        }
+        else if (poSRS != NULL && poSRS->IsProjected() )
+        {
+            NCDFWriteXYVarsAttributes(m_nLayerCDFId, m_nXVarID, m_nYVarID, poSRS);
+        }
+
+        if( m_poFeatureDefn->GetGeomType() == wkbPoint25D )
+        {
+            const char* pszZVarName = "z";
+            status = nc_def_var( m_nLayerCDFId,
+                                 pszZVarName, NC_DOUBLE,
+                                 1, &m_nRecordDimID, &m_nZVarID);
+            NCDF_ERR(status);
+            if ( status != NC_NOERR ) {
+                return false;
+            }
+
+            aoAutoVariables.push_back( std::pair<CPLString,int>(pszZVarName, m_nZVarID) );
+
+            m_nZVarNCDFType = NC_DOUBLE;
+            m_uZVarNoData.dfVal = NC_FILL_DOUBLE;
+
+            status = nc_put_att_text( m_nLayerCDFId, m_nZVarID, CF_LNG_NAME,
+                             strlen("z coordinate"), "z coordinate");
+            NCDF_ERR(status);
+
+            status = nc_put_att_text( m_nLayerCDFId, m_nZVarID, CF_STD_NAME,
+                             strlen("height"), "height");
+            NCDF_ERR(status);
+
+            status = nc_put_att_text( m_nLayerCDFId, m_nZVarID, CF_AXIS,
+                             strlen("Z"), "Z");
+            NCDF_ERR(status);
+
+            status = nc_put_att_text( m_nLayerCDFId, m_nZVarID, CF_UNITS,
+                             strlen("m"), "m");
+            NCDF_ERR(status);
+
+            m_osCoordinatesValue += " ";
+            m_osCoordinatesValue += pszZVarName;
+
+        }
+
+        const char* pszFeatureTypeVal = m_osProfileDimName.size() ? "profile" : "point";
+        status = nc_put_att_text( m_nLayerCDFId, NC_GLOBAL, "featureType",
+                                  strlen(pszFeatureTypeVal), pszFeatureTypeVal);
+        NCDF_ERR(status);
+    }
+    else if( m_poFeatureDefn->GetGeomType() != wkbNone )
+    {
+#ifdef NETCDF_HAS_NC4
+        if( m_poDS->eFormat == NCDF_FORMAT_NC4 && m_bUseStringInNC4 )
+        {
+            m_nWKTNCDFType = NC_STRING;
+            status = nc_def_var( m_nLayerCDFId,
+                                 m_osWKTVarName.c_str(), NC_STRING, 1,
+                                 &m_nRecordDimID, &m_nWKTVarID);
+        }
+        else
+#endif
+        {
+            m_nWKTNCDFType = NC_CHAR;
+            m_nWKTMaxWidth = atoi(CSLFetchNameValueDef(papszOptions, "WKT_DEFAULT_WIDTH",
+                                        CPLSPrintf("%d", m_bAutoGrowStrings ? 1000 : 10000)));
+            status = nc_def_dim( m_nLayerCDFId,
+                                 CPLSPrintf("%s_max_width", m_osWKTVarName.c_str()),
+                                 m_nWKTMaxWidth,
+                                 &m_nWKTMaxWidthDimId );
+            NCDF_ERR(status);
+            if ( status != NC_NOERR ) {
+                return false;
+            }
+
+            int anDims[] = { m_nRecordDimID, m_nWKTMaxWidthDimId };
+            status = nc_def_var( m_nLayerCDFId,
+                                 m_osWKTVarName.c_str(), NC_CHAR, 2,
+                                 anDims, &m_nWKTVarID );
+        }
+        NCDF_ERR(status);
+        if ( status != NC_NOERR ) {
+            return false;
+        }
+
+        aoAutoVariables.push_back( std::pair<CPLString,int>(m_osWKTVarName, m_nWKTVarID) );
+
+        status = nc_put_att_text( m_nLayerCDFId, m_nWKTVarID, CF_LNG_NAME,
+                         strlen("Geometry as ISO WKT"), "Geometry as ISO WKT" );
+        NCDF_ERR(status);
+
+        //nc_put_att_text( m_nLayerCDFId, m_nWKTVarID, CF_UNITS,
+        //                 strlen("none"), "none" );
+
+        if( m_bWriteGDALTags )
+        {
+            status = nc_put_att_text( m_nLayerCDFId, NC_GLOBAL, "ogr_geometry_field",
+                             m_osWKTVarName.size(), m_osWKTVarName.c_str() );
+            NCDF_ERR(status);
+
+            CPLString osGeometryType = OGRToOGCGeomType(m_poFeatureDefn->GetGeomType());
+            if( wkbHasZ(m_poFeatureDefn->GetGeomType()) )
+                osGeometryType += " Z";
+            status = nc_put_att_text( m_nLayerCDFId, NC_GLOBAL, "ogr_layer_type",
+                                      osGeometryType.size(), osGeometryType.c_str());
+            NCDF_ERR(status);
+        }
+    }
+
+    if( poSRS != NULL )
+    {
+        char* pszCFProjection = NULL;
+        int nSRSVarId = NCDFWriteSRSVariable(m_nLayerCDFId, poSRS,
+                                             &pszCFProjection,
+                                             m_bWriteGDALTags);
+        if( nSRSVarId < 0 )
+            return false;
+        if( pszCFProjection != NULL )
+        {
+            aoAutoVariables.push_back( std::pair<CPLString,int>(pszCFProjection, nSRSVarId) );
+
+            m_osGridMapping = pszCFProjection;
+            CPLFree(pszCFProjection);
+        }
+
+        if( m_nWKTVarID >= 0 && m_osGridMapping.size() != 0 )
+        {
+            status = nc_put_att_text( m_nLayerCDFId, m_nWKTVarID, CF_GRD_MAPPING,
+                                      m_osGridMapping.size(), m_osGridMapping.c_str() );
+            NCDF_ERR(status);
+        }
+    }
+
+    if( m_poDS->oWriterConfig.m_bIsValid )
+    {
+        m_poLayerConfig = poLayerConfig;
+
+        netCDFWriteAttributesFromConf(m_nLayerCDFId, NC_GLOBAL,
+                                      m_poDS->oWriterConfig.m_aoAttributes);
+        if( poLayerConfig != NULL )
+        {
+            netCDFWriteAttributesFromConf(m_nLayerCDFId, NC_GLOBAL,
+                                          poLayerConfig->m_aoAttributes);
+        }
+
+        for(size_t i=0; i<aoAutoVariables.size(); i++)
+        {
+            const netCDFWriterConfigField* poConfig = NULL;
+            CPLString osLookup = "__" + aoAutoVariables[i].first;
+            std::map<CPLString, netCDFWriterConfigField>::const_iterator oIter;
+            if( m_poLayerConfig != NULL &&
+                (oIter = m_poLayerConfig->m_oFields.find(osLookup)) !=
+                m_poLayerConfig->m_oFields.end() )
+            {
+                poConfig = &(oIter->second);
+            }
+            else if( (oIter = m_poDS->oWriterConfig.m_oFields.find(osLookup)) !=
+                    m_poDS->oWriterConfig.m_oFields.end() )
+            {
+                poConfig = &(oIter->second);
+            }
+
+            if( poConfig != NULL )
+            {
+                netCDFWriteAttributesFromConf(m_nLayerCDFId, aoAutoVariables[i].second,
+                                              poConfig->m_aoAttributes);
+            }
+        }
+    }
+
+    return true;
+}
+
+/************************************************************************/
+/*                          SetRecordDimID()                            */
+/************************************************************************/
+
+void netCDFLayer::SetRecordDimID(int nRecordDimID)
+{
+    m_nRecordDimID = nRecordDimID;
+    char szTemp[NC_MAX_NAME+1];
+    szTemp[0] = 0;
+    int status = nc_inq_dimname( m_nLayerCDFId, m_nRecordDimID, szTemp);
+    NCDF_ERR(status);
+    m_osRecordDimName = szTemp;
+}
+
+
+/************************************************************************/
+/*                            GetFillValue()                            */
+/************************************************************************/
+
+CPLErr netCDFLayer::GetFillValue( int nVarId, char **ppszValue )
+{
+    if( NCDFGetAttr( m_nLayerCDFId, nVarId, _FillValue, ppszValue) == CE_None )
+        return CE_None;
+    return NCDFGetAttr( m_nLayerCDFId, nVarId, "missing_value", ppszValue);
+}
+
+CPLErr netCDFLayer::GetFillValue( int nVarId, double *pdfValue )
+{
+    if( NCDFGetAttr( m_nLayerCDFId, nVarId, _FillValue, pdfValue) == CE_None )
+        return CE_None;
+    return NCDFGetAttr( m_nLayerCDFId, nVarId, "missing_value", pdfValue);
+}
+
+/************************************************************************/
+/*                         GetNoDataValueForFloat()                     */
+/************************************************************************/
+
+void netCDFLayer::GetNoDataValueForFloat( int nVarId, NCDFNoDataUnion* puNoData )
+{
+    double dfValue;
+    if( GetFillValue( nVarId, &dfValue) == CE_None )
+        puNoData->fVal = static_cast<float>(dfValue);
+    else
+        puNoData->fVal = NC_FILL_FLOAT;
+}
+
+/************************************************************************/
+/*                        GetNoDataValueForDouble()                     */
+/************************************************************************/
+
+void netCDFLayer::GetNoDataValueForDouble( int nVarId, NCDFNoDataUnion* puNoData )
+{
+    double dfValue;
+    if( GetFillValue( nVarId, &dfValue) == CE_None )
+        puNoData->dfVal = dfValue;
+    else
+        puNoData->dfVal = NC_FILL_DOUBLE;
+}
+
+/************************************************************************/
+/*                            GetNoDataValue()                          */
+/************************************************************************/
+
+void netCDFLayer::GetNoDataValue( int nVarId, nc_type nVarType, NCDFNoDataUnion* puNoData )
+{
+    if( nVarType == NC_DOUBLE )
+        GetNoDataValueForDouble( nVarId, puNoData );
+    else if( nVarType == NC_FLOAT )
+        GetNoDataValueForFloat( nVarId, puNoData );
+}
+
+/************************************************************************/
+/*                             SetXYZVars()                             */
+/************************************************************************/
+
+void netCDFLayer::SetXYZVars(int nXVarId, int nYVarId, int nZVarId)
+{
+    m_nXVarID = nXVarId;
+    m_nYVarID = nYVarId;
+    m_nZVarID = nZVarId;
+
+    nc_inq_vartype( m_nLayerCDFId, m_nXVarID, &m_nXVarNCDFType );
+    nc_inq_vartype( m_nLayerCDFId, m_nYVarID, &m_nYVarNCDFType );
+    if( (m_nXVarNCDFType != NC_FLOAT && m_nXVarNCDFType != NC_DOUBLE) ||
+        (m_nYVarNCDFType != NC_FLOAT && m_nYVarNCDFType != NC_DOUBLE) )
+    {
+        CPLError(CE_Warning, CPLE_NotSupported,
+                 "X or Y variable of type X=%d,Y=%d not handled",
+                 m_nXVarNCDFType, m_nYVarNCDFType);
+        m_nXVarID = -1;
+        m_nYVarID = -1;
+    }
+    if( m_nZVarID >= 0 )
+    {
+        nc_inq_vartype( m_nLayerCDFId, m_nZVarID, &m_nZVarNCDFType );
+        if( m_nZVarNCDFType != NC_FLOAT && m_nZVarNCDFType != NC_DOUBLE )
+        {
+            CPLError(CE_Warning, CPLE_NotSupported,
+                      "Z variable of type %d not handled", m_nZVarNCDFType);
+            m_nZVarID = -1;
+        }
+    }
+
+    if( m_nXVarID >= 0 && m_nYVarID >= 0 )
+    {
+        char szVarName[NC_MAX_NAME+1];
+        szVarName[0] = '\0';
+        CPL_IGNORE_RET_VAL(nc_inq_varname( m_nLayerCDFId, m_nXVarID, szVarName ));
+        m_osCoordinatesValue = szVarName;
+
+        szVarName[0] = '\0';
+        CPL_IGNORE_RET_VAL(nc_inq_varname( m_nLayerCDFId, m_nYVarID, szVarName ));
+        m_osCoordinatesValue += " ";
+        m_osCoordinatesValue += szVarName;
+
+        if( m_nZVarID >= 0 )
+        {
+            szVarName[0] = '\0';
+            CPL_IGNORE_RET_VAL(nc_inq_varname( m_nLayerCDFId, m_nZVarID, szVarName ));
+            m_osCoordinatesValue += " ";
+            m_osCoordinatesValue += szVarName;
+        }
+    }
+
+    if( m_nXVarID >= 0 )
+        GetNoDataValue( m_nXVarID, m_nXVarNCDFType, &m_uXVarNoData);
+    if( m_nYVarID >= 0 )
+        GetNoDataValue( m_nYVarID, m_nYVarNCDFType, &m_uYVarNoData);
+    if( m_nZVarID >= 0 )
+        GetNoDataValue( m_nZVarID, m_nZVarNCDFType, &m_uZVarNoData);
+}
+
+/************************************************************************/
+/*                       SetWKTGeometryField()                          */
+/************************************************************************/
+
+void netCDFLayer::SetWKTGeometryField(const char* pszWKTVarName)
+{
+    m_nWKTVarID = -1;
+    nc_inq_varid( m_nLayerCDFId, pszWKTVarName, &m_nWKTVarID);
+    if( m_nWKTVarID < 0 )
+        return;
+    int nd;
+    nc_inq_varndims( m_nLayerCDFId, m_nWKTVarID, &nd );
+    nc_inq_vartype( m_nLayerCDFId, m_nWKTVarID, &m_nWKTNCDFType );
+#ifdef NETCDF_HAS_NC4
+    if( nd == 1 && m_nWKTNCDFType == NC_STRING )
+    {
+        int nDimID;
+        if( nc_inq_vardimid( m_nLayerCDFId, m_nWKTVarID, &nDimID ) != NC_NOERR ||
+            nDimID != m_nRecordDimID )
+        {
+            m_nWKTVarID = -1;
+            return;
+        }
+    }
+    else
+#endif
+    if (nd == 2 && m_nWKTNCDFType == NC_CHAR )
+    {
+        int anDimIds [] = { -1, -1 };
+        size_t nLen = 0;
+        if( nc_inq_vardimid( m_nLayerCDFId, m_nWKTVarID, anDimIds ) != NC_NOERR ||
+            anDimIds[0] != m_nRecordDimID ||
+            nc_inq_dimlen( m_nLayerCDFId, anDimIds[1], &nLen ) != NC_NOERR )
+        {
+            m_nWKTVarID = -1;
+            return;
+        }
+        m_nWKTMaxWidth = static_cast<int>(nLen);
+        m_nWKTMaxWidthDimId = anDimIds[1];
+    }
+    else
+    {
+        m_nWKTVarID = -1;
+        return;
+    }
+
+    m_osWKTVarName = pszWKTVarName;
+}
+
+/************************************************************************/
+/*                          SetGridMapping()                            */
+/************************************************************************/
+
+void netCDFLayer::SetGridMapping(const char* pszGridMapping)
+{
+    m_osGridMapping = pszGridMapping;
+}
+
+/************************************************************************/
+/*                            SetProfile()                              */
+/************************************************************************/
+
+void netCDFLayer::SetProfile(int nProfileDimID, int nParentIndexVarID)
+{
+    m_nProfileDimID = nProfileDimID;
+    m_nParentIndexVarID = nParentIndexVarID;
+    if( m_nProfileDimID >= 0 )
+    {
+        char szTemp[NC_MAX_NAME+1];
+        szTemp[0] = 0;
+        int status = nc_inq_dimname( m_nLayerCDFId, m_nProfileDimID, szTemp);
+        NCDF_ERR(status);
+        m_osProfileDimName = szTemp;
+
+        nc_inq_varid( m_nLayerCDFId, m_osProfileDimName, &m_nProfileVarID);
+        m_bProfileVarUnlimited = NCDFIsUnlimitedDim(m_poDS->eFormat == NCDF_FORMAT_NC4,
+                                                m_nLayerCDFId, m_nProfileVarID);
+    }
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void netCDFLayer::ResetReading()
+{
+    m_nCurFeatureId = 1;
+}
+
+/************************************************************************/
+/*                           Get1DVarAsDouble()                         */
+/************************************************************************/
+
+double netCDFLayer::Get1DVarAsDouble( int nVarId, nc_type nVarType,
+                                      size_t nIndex,
+                                      NCDFNoDataUnion noDataVal,
+                                      bool* pbIsNoData )
+{
+    double dfVal = 0;
+    if( nVarType == NC_DOUBLE )
+    {
+        nc_get_var1_double( m_nLayerCDFId, nVarId, &nIndex, &dfVal );
+        if( pbIsNoData)
+            *pbIsNoData = ( dfVal == noDataVal.dfVal );
+    }
+    else if( nVarType == NC_FLOAT )
+    {
+        float fVal = 0.f;
+        nc_get_var1_float( m_nLayerCDFId, nVarId, &nIndex, &fVal );
+        if( pbIsNoData)
+            *pbIsNoData = ( fVal == noDataVal.fVal );
+        dfVal = fVal;
+    }
+    else if( pbIsNoData)
+        *pbIsNoData = true;
+    return dfVal;
+}
+
+/************************************************************************/
+/*                        GetNextRawFeature()                           */
+/************************************************************************/
+
+OGRFeature* netCDFLayer::GetNextRawFeature()
+{
+    m_poDS->SetDefineMode(false);
+
+    // In update mode, nc_get_varXXX() doesn't return error if we are
+    // beyond the end of dimension
+    size_t nDimLen = 0;
+    nc_inq_dimlen ( m_nLayerCDFId, m_nRecordDimID, &nDimLen );
+    if( m_nCurFeatureId > static_cast<GIntBig>(nDimLen) )
+        return NULL;
+
+    OGRFeature* poFeature = new OGRFeature(m_poFeatureDefn);
+
+    if( m_nParentIndexVarID >= 0 )
+    {
+        int nProfileIdx = 0;
+        size_t nIdx = static_cast<size_t>(m_nCurFeatureId-1);
+        int status = nc_get_var1_int( m_nLayerCDFId, m_nParentIndexVarID,
+                                      &nIdx, &nProfileIdx );
+        if( status == NC_NOERR && nProfileIdx >= 0 )
+        {
+            nIdx = static_cast<size_t>(nProfileIdx);
+            FillFeatureFromVar(poFeature, m_nProfileDimID, nIdx);
+        }
+    }
+
+    if( !FillFeatureFromVar(poFeature, m_nRecordDimID,
+                     static_cast<size_t>(m_nCurFeatureId-1)) )
+    {
+        m_nCurFeatureId ++;
+        delete poFeature;
+        return NULL;
+    }
+
+    poFeature->SetFID(m_nCurFeatureId);
+    m_nCurFeatureId ++;
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                           FillFeatureFromVar()                       */
+/************************************************************************/
+
+bool netCDFLayer::FillFeatureFromVar(OGRFeature* poFeature, int nMainDimId, size_t nIndex)
+{
+    size_t anIndex[2];
+    anIndex[0] = nIndex;
+    anIndex[1] = 0;
+
+    for(int i=0;i<m_poFeatureDefn->GetFieldCount();i++)
+    {
+        if( m_aoFieldDesc[i].nMainDimId != nMainDimId )
+            continue;
+
+        switch( m_aoFieldDesc[i].nType )
+        {
+            case NC_CHAR:
+            {
+                if( m_aoFieldDesc[i].nDimCount == 1 )
+                {
+                    char szVal[] = {0,0};
+                    int status = nc_get_var1_text( m_nLayerCDFId,
+                                        m_aoFieldDesc[i].nVarId,
+                                        anIndex,
+                                        szVal );
+                    if( status != NC_NOERR )
+                    {
+                        NCDF_ERR(status);
+                        continue;
+                    }
+                    poFeature->SetField(i, szVal);
+                }
+                else
+                {
+                    size_t anCount[2];
+                    anCount[0] = 1;
+                    anCount[1] = 0;
+                    nc_inq_dimlen( m_nLayerCDFId, m_aoFieldDesc[i].nSecDimId, &(anCount[1]) );
+                    char* pszVal = (char*) CPLCalloc( 1, anCount[1] + 1 );
+                    int status = nc_get_vara_text( m_nLayerCDFId,
+                                        m_aoFieldDesc[i].nVarId,
+                                        anIndex, anCount,
+                                        pszVal );
+                    if( status != NC_NOERR )
+                    {
+                        NCDF_ERR(status);
+                        CPLFree(pszVal);
+                        continue;
+                    }
+                    poFeature->SetField(i, pszVal);
+                    CPLFree(pszVal);
+                }
+                break;
+            }
+
+#ifdef NETCDF_HAS_NC4
+            case NC_STRING:
+            {
+                char* pszVal = NULL;
+                int status = nc_get_var1_string( m_nLayerCDFId,
+                                    m_aoFieldDesc[i].nVarId,
+                                    anIndex,
+                                    &pszVal );
+                if( status != NC_NOERR )
+                {
+                    NCDF_ERR(status);
+                    continue;
+                }
+                if( pszVal != NULL )
+                {
+                    poFeature->SetField(i, pszVal);
+                    nc_free_string(1, &pszVal);
+                }
+                break;
+            }
+#endif
+
+            case NC_BYTE:
+            {
+                signed char chVal = 0;
+                int status = nc_get_var1_schar( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                                anIndex, &chVal );
+                if( status != NC_NOERR )
+                {
+                    NCDF_ERR(status);
+                    continue;
+                }
+                if( chVal == m_aoFieldDesc[i].uNoData.chVal )
+                    continue;
+                poFeature->SetField(i, static_cast<int>(chVal));
+                break;
+            }
+
+#ifdef NETCDF_HAS_NC4
+            case NC_UBYTE:
+            {
+                unsigned char uchVal = 0;
+                int status = nc_get_var1_uchar( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                                anIndex, &uchVal );
+                if( status != NC_NOERR )
+                {
+                    NCDF_ERR(status);
+                    continue;
+                }
+                if( uchVal == m_aoFieldDesc[i].uNoData.uchVal )
+                    continue;
+                poFeature->SetField(i, static_cast<int>(uchVal));
+                break;
+            }
+#endif
+
+            case NC_SHORT:
+            {
+                short sVal = 0;
+                int status = nc_get_var1_short( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                    anIndex, &sVal );
+
+                if( status != NC_NOERR )
+                {
+                    NCDF_ERR(status);
+                    continue;
+                }
+                if( sVal == m_aoFieldDesc[i].uNoData.sVal )
+                    continue;
+                poFeature->SetField(i, static_cast<int>(sVal));
+                break;
+            }
+
+#ifdef NETCDF_HAS_NC4
+            case NC_USHORT:
+            {
+                unsigned short usVal = 0;
+                int status = nc_get_var1_ushort( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                                 anIndex, &usVal );
+                if( status != NC_NOERR )
+                {
+                    NCDF_ERR(status);
+                    continue;
+                }
+                if( usVal == m_aoFieldDesc[i].uNoData.usVal )
+                    continue;
+                poFeature->SetField(i, static_cast<int>(usVal));
+                break;
+            }
+#endif
+
+            case NC_INT:
+            {
+                int nVal = 0;
+                int status = nc_get_var1_int( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                    anIndex, &nVal );
+                if( status != NC_NOERR )
+                {
+                    NCDF_ERR(status);
+                    continue;
+                }
+                if( nVal == m_aoFieldDesc[i].uNoData.nVal )
+                    continue;
+                if( m_poFeatureDefn->GetFieldDefn(i)->GetType() == OFTDate ||
+                    m_poFeatureDefn->GetFieldDefn(i)->GetType() == OFTDateTime )
+                {
+                    struct tm brokendowntime;
+                    GIntBig nVal64 = static_cast<GIntBig>(nVal);
+                    if( m_aoFieldDesc[i].bIsDays )
+                        nVal64 *= 86400;
+                    CPLUnixTimeToYMDHMS( nVal64, &brokendowntime );
+                    poFeature->SetField( i,
+                                        brokendowntime.tm_year + 1900,
+                                        brokendowntime.tm_mon + 1,
+                                        brokendowntime.tm_mday,
+                                        brokendowntime.tm_hour,
+                                        brokendowntime.tm_min,
+                                        static_cast<float>(brokendowntime.tm_sec),
+                                        0);
+                }
+                else
+                {
+                    poFeature->SetField(i, nVal);
+                }
+                break;
+            }
+
+#ifdef NETCDF_HAS_NC4
+            case NC_UINT:
+            {
+                unsigned int unVal = 0;
+                // nc_get_var1_uint() doesn't work on old netCDF version when
+                // the returned value is > INT_MAX
+                // https://bugtracking.unidata.ucar.edu/browse/NCF-226
+                // nc_get_vara_uint() has not this bug
+                size_t nCount = 1;
+                int status = nc_get_vara_uint( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                               anIndex, &nCount, &unVal );
+                if( status != NC_NOERR )
+                {
+                    NCDF_ERR(status);
+                    continue;
+                }
+                if( unVal == m_aoFieldDesc[i].uNoData.unVal )
+                    continue;
+                poFeature->SetField(i, static_cast<GIntBig>(unVal));
+                break;
+            }
+#endif
+
+#ifdef NETCDF_HAS_NC4
+            case NC_INT64:
+            {
+                GIntBig nVal = 0;
+                int status = nc_get_var1_longlong( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                        anIndex, &nVal );
+                if( status != NC_NOERR )
+                {
+                    NCDF_ERR(status);
+                    continue;
+                }
+                if( nVal == m_aoFieldDesc[i].uNoData.nVal64 )
+                    continue;
+                poFeature->SetField(i, nVal);
+                break;
+            }
+
+            case NC_UINT64:
+            {
+                GUIntBig nVal = 0;
+                int status = nc_get_var1_ulonglong( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                        anIndex, &nVal );
+                if( status != NC_NOERR )
+                {
+                    NCDF_ERR(status);
+                    continue;
+                }
+                if( nVal == m_aoFieldDesc[i].uNoData.unVal64 )
+                    continue;
+                poFeature->SetField(i, static_cast<double>(nVal));
+                break;
+            }
+#endif
+
+            case NC_FLOAT:
+            {
+                float fVal = 0.f;
+                int status = nc_get_var1_float( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                    anIndex, &fVal );
+                if( status != NC_NOERR )
+                {
+                    NCDF_ERR(status);
+                    continue;
+                }
+                if( fVal == m_aoFieldDesc[i].uNoData.fVal )
+                    continue;
+                poFeature->SetField(i, static_cast<double>(fVal));
+                break;
+            }
+
+            case NC_DOUBLE:
+            {
+                double dfVal = 0.0;
+                int status = nc_get_var1_double( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                    anIndex, &dfVal );
+                if( status != NC_NOERR )
+                {
+                    NCDF_ERR(status);
+                    continue;
+                }
+                if( dfVal == m_aoFieldDesc[i].uNoData.dfVal )
+                    continue;
+                if( m_poFeatureDefn->GetFieldDefn(i)->GetType() == OFTDate ||
+                    m_poFeatureDefn->GetFieldDefn(i)->GetType() == OFTDateTime )
+                {
+                    if( m_aoFieldDesc[i].bIsDays )
+                        dfVal *= 86400.0;
+                    struct tm brokendowntime;
+                    GIntBig nVal = static_cast<GIntBig>(floor(dfVal));
+                    CPLUnixTimeToYMDHMS( nVal, &brokendowntime );
+                    poFeature->SetField( i,
+                                        brokendowntime.tm_year + 1900,
+                                        brokendowntime.tm_mon + 1,
+                                        brokendowntime.tm_mday,
+                                        brokendowntime.tm_hour,
+                                        brokendowntime.tm_min,
+                                        static_cast<float>(brokendowntime.tm_sec + (dfVal - nVal)),
+                                     0 );
+                }
+                else
+                {
+                    poFeature->SetField(i, dfVal);
+                }
+                break;
+            }
+
+            default:
+                break;
+        }
+    }
+
+    if( m_nXVarID >= 0 && m_nYVarID >= 0 &&
+        ( m_osProfileDimName.size() == 0 || nMainDimId == m_nProfileDimID ) )
+    {
+        bool bXIsNoData = false;
+        const double dfX = Get1DVarAsDouble( m_nXVarID, m_nXVarNCDFType,
+                                             anIndex[0], m_uXVarNoData,
+                                             &bXIsNoData );
+        bool bYIsNoData = false;
+        const double dfY = Get1DVarAsDouble( m_nYVarID, m_nYVarNCDFType,
+                                             anIndex[0], m_uYVarNoData,
+                                             &bYIsNoData );
+
+        if( !bXIsNoData && !bYIsNoData )
+        {
+            OGRPoint* poPoint;
+            if( m_nZVarID >= 0 && m_osProfileDimName.size() == 0 )
+            {
+                bool bZIsNoData = false;
+                const double dfZ = Get1DVarAsDouble( m_nZVarID, m_nZVarNCDFType,
+                                                    anIndex[0], m_uZVarNoData,
+                                                    &bZIsNoData );
+                if( bZIsNoData )
+                    poPoint = new OGRPoint(dfX, dfY);
+                else
+                    poPoint = new OGRPoint(dfX, dfY, dfZ);
+            }
+            else
+                poPoint = new OGRPoint(dfX, dfY);
+            poPoint->assignSpatialReference( GetSpatialRef() );
+            poFeature->SetGeometryDirectly(poPoint);
+        }
+    }
+    else if( m_nXVarID >= 0 && m_nYVarID >= 0 && m_nZVarID >= 0 &&
+             m_osProfileDimName.size() &&
+             nMainDimId == m_nRecordDimID )
+    {
+        OGRGeometry* poGeom = poFeature->GetGeometryRef();
+        if( poGeom != NULL && wkbFlatten(poGeom->getGeometryType()) == wkbPoint )
+        {
+            bool bZIsNoData = false;
+            const double dfZ = Get1DVarAsDouble( m_nZVarID, m_nZVarNCDFType,
+                                                anIndex[0], m_uZVarNoData,
+                                                &bZIsNoData );
+            if( !bZIsNoData )
+                ((OGRPoint*)poGeom)->setZ( dfZ );
+        }
+    }
+    else if( m_nWKTVarID >= 0 )
+    {
+        char* pszWKT = NULL;
+        if( m_nWKTNCDFType == NC_CHAR )
+        {
+            size_t anCount[2];
+            anCount[0] = 1;
+            anCount[1] = m_nWKTMaxWidth;
+            pszWKT = (char*) CPLCalloc( 1, anCount[1] + 1 );
+            int status = nc_get_vara_text( m_nLayerCDFId, m_nWKTVarID,
+                                           anIndex, anCount, pszWKT );
+            if( status == NC_EINVALCOORDS || status == NC_EEDGE )
+            {
+                CPLFree(pszWKT);
+                return false;
+            }
+            if( status != NC_NOERR )
+            {
+                NCDF_ERR(status);
+                CPLFree(pszWKT);
+                pszWKT = NULL;
+            }
+        }
+#ifdef NETCDF_HAS_NC4
+        else if( m_nWKTNCDFType == NC_STRING )
+        {
+            char* pszVal = NULL;
+            int status = nc_get_var1_string( m_nLayerCDFId, m_nWKTVarID,
+                                             anIndex, &pszVal );
+            if( status == NC_EINVALCOORDS || status == NC_EEDGE )
+            {
+                return false;
+            }
+            if( status != NC_NOERR )
+            {
+                NCDF_ERR(status);
+            }
+            else if( pszVal != NULL )
+            {
+                pszWKT = CPLStrdup(pszVal);
+                nc_free_string(1, &pszVal);
+            }
+        }
+#endif
+        if( pszWKT != NULL )
+        {
+            char* pszWKTTmp = pszWKT;
+            OGRGeometry* poGeom = NULL;
+            CPL_IGNORE_RET_VAL( OGRGeometryFactory::createFromWkt( &pszWKTTmp, NULL, &poGeom ) );
+            if( poGeom != NULL )
+            {
+                poGeom->assignSpatialReference( GetSpatialRef() );
+                poFeature->SetGeometryDirectly(poGeom);
+            }
+            CPLFree(pszWKT);
+        }
+    }
+
+    return true;
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature* netCDFLayer::GetNextFeature()
+{
+    while( true )
+    {
+        OGRFeature      *poFeature;
+
+        poFeature = GetNextRawFeature();
+        if( poFeature == NULL )
+            return NULL;
+
+        if( (m_poFilterGeom == NULL
+            || FilterGeometry( poFeature->GetGeomFieldRef(m_iGeomFieldFilter) ) )
+            && (m_poAttrQuery == NULL
+                || m_poAttrQuery->Evaluate( poFeature )) )
+            return poFeature;
+
+        delete poFeature;
+    }
+}
+
+/************************************************************************/
+/*                            GetLayerDefn()                            */
+/************************************************************************/
+
+OGRFeatureDefn* netCDFLayer::GetLayerDefn()
+{
+    return m_poFeatureDefn;
+}
+
+/************************************************************************/
+/*                           ICreateFeature()                           */
+/************************************************************************/
+
+OGRErr netCDFLayer::ICreateFeature(OGRFeature* poFeature)
+{
+    m_poDS->SetDefineMode(false);
+
+    size_t nFeatureIdx = 0;
+    nc_inq_dimlen ( m_nLayerCDFId, m_nRecordDimID, &nFeatureIdx );
+
+    if( m_nProfileDimID >= 0 )
+    {
+        size_t nProfileCount = 0;
+        nc_inq_dimlen ( m_nLayerCDFId, m_nProfileDimID, &nProfileCount );
+
+        OGRFeature* poProfileToLookup = poFeature->Clone();
+        poProfileToLookup->SetFID(-1);
+        for(int i=0;i<m_poFeatureDefn->GetFieldCount();i++)
+        {
+            if( !(poProfileToLookup->IsFieldSet(i)) ||
+                m_aoFieldDesc[i].nMainDimId != m_nProfileDimID )
+            {
+                poProfileToLookup->UnsetField(i);
+                continue;
+            }
+        }
+        OGRGeometry* poGeom = poProfileToLookup->GetGeometryRef();
+        if( poGeom != NULL && wkbFlatten(poGeom->getGeometryType()) == wkbPoint )
+        {
+            ((OGRPoint*)poGeom)->setZ(0);
+        }
+
+        size_t nProfileIdx = 0;
+        bool bFoundProfile = false;
+        for( ; nProfileIdx < nProfileCount; nProfileIdx++ )
+        {
+            int nId = NC_FILL_INT;
+            int status = nc_get_var1_int( m_nLayerCDFId, m_nProfileVarID,
+                                          &nProfileIdx, &nId );
+            NCDF_ERR(status);
+            if( nId == NC_FILL_INT )
+                break;
+
+            OGRFeature* poIterFeature = new OGRFeature(m_poFeatureDefn);
+            if( FillFeatureFromVar(poIterFeature, m_nProfileDimID, nProfileIdx) )
+            {
+                poGeom = poIterFeature->GetGeometryRef();
+                if( poGeom != NULL && wkbFlatten(poGeom->getGeometryType()) == wkbPoint )
+                {
+                    ((OGRPoint*)poGeom)->setZ(0);
+                }
+                if( poIterFeature->Equal(poProfileToLookup) )
+                {
+                    bFoundProfile = true;
+                    delete poIterFeature;
+                    break;
+                }
+            }
+            delete poIterFeature;
+        }
+
+        if( !bFoundProfile )
+        {
+            if( !m_bProfileVarUnlimited && nProfileIdx == nProfileCount )
+            {
+                size_t nNewSize = 1 + nProfileCount + nProfileCount / 3;
+                m_poDS->GrowDim( m_nLayerCDFId, m_nProfileDimID, nNewSize );
+            }
+
+            if( !FillVarFromFeature(poProfileToLookup, m_nProfileDimID, nProfileIdx) )
+            {
+                delete poProfileToLookup;
+                return OGRERR_FAILURE;
+            }
+        }
+
+        int nProfileIdIdx = m_poFeatureDefn->GetFieldIndex( m_osProfileDimName );
+        if( nProfileIdIdx < 0 ||
+            m_poFeatureDefn->GetFieldDefn(nProfileIdIdx)->GetType() != OFTInteger )
+        {
+            int nVal = static_cast<int>(nProfileIdx);
+            int status = nc_put_var1_int( m_nLayerCDFId, m_nProfileVarID,
+                                          &nProfileIdx, &nVal );
+            NCDF_ERR(status);
+        }
+
+        int nVal = static_cast<int>(nProfileIdx);
+        int status = nc_put_var1_int( m_nLayerCDFId, m_nParentIndexVarID,
+                                      &nFeatureIdx, &nVal );
+        NCDF_ERR(status);
+
+        delete poProfileToLookup;
+    }
+
+    if( !FillVarFromFeature(poFeature, m_nRecordDimID, nFeatureIdx) )
+        return OGRERR_FAILURE;
+
+    poFeature->SetFID( nFeatureIdx + 1 );
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           FillVarFromFeature()                       */
+/************************************************************************/
+
+bool netCDFLayer::FillVarFromFeature(OGRFeature* poFeature, int nMainDimId, size_t nIndex)
+{
+    size_t anIndex[2];
+    anIndex[0] = nIndex;
+    anIndex[1] = 0;
+
+    for(int i=0;i<m_poFeatureDefn->GetFieldCount();i++)
+    {
+        if( m_aoFieldDesc[i].nMainDimId != nMainDimId )
+            continue;
+
+        if( !(poFeature->IsFieldSet(i)) )
+        {
+#ifdef NETCDF_HAS_NC4
+            if( m_bNCDumpCompat && m_aoFieldDesc[i].nType == NC_STRING )
+            {
+                const char* pszVal =  "";
+                int status = nc_put_var1_string( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                             anIndex, &pszVal );
+                NCDF_ERR(status);
+            }
+#endif
+            continue;
+        }
+
+        int status = NC_NOERR;
+        switch( m_aoFieldDesc[i].nType )
+        {
+            case NC_CHAR:
+            {
+                const char* pszVal = poFeature->GetFieldAsString(i);
+                if( m_aoFieldDesc[i].nDimCount == 1 )
+                {
+                    if( strlen(pszVal) > 1 && !m_aoFieldDesc[i].bHasWarnedAboutTruncation )
+                    {
+                        CPLError(CE_Warning, CPLE_AppDefined,
+                                "Content of field %s exceeded the 1 character limit and will be truncated",
+                                m_poFeatureDefn->GetFieldDefn(i)->GetNameRef());
+                        m_aoFieldDesc[i].bHasWarnedAboutTruncation = true;
+                    }
+                    status = nc_put_var1_text( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                               anIndex, pszVal );
+                }
+                else
+                {
+                    size_t anCount[2];
+                    anCount[0] = 1;
+                    anCount[1] = strlen(pszVal);
+                    size_t nWidth = 0;
+                    nc_inq_dimlen( m_nLayerCDFId, m_aoFieldDesc[i].nSecDimId, &nWidth );
+                    if( anCount[1] > nWidth )
+                    {
+                        if( m_bAutoGrowStrings && m_poFeatureDefn->GetFieldDefn(i)->GetWidth() == 0 )
+                        {
+                            size_t nNewSize = anCount[1] + anCount[1] / 3;
+
+                            CPLDebug("GDAL_netCDF", "Growing %s from %u to %u",
+                                    m_poFeatureDefn->GetFieldDefn(i)->GetNameRef(),
+                                    static_cast<unsigned>(nWidth),
+                                    static_cast<unsigned>(nNewSize) );
+                            m_poDS->GrowDim( m_nLayerCDFId, m_aoFieldDesc[i].nSecDimId, nNewSize );
+
+                            pszVal = poFeature->GetFieldAsString(i);
+                        }
+                        else
+                        {
+                            anCount[1] = nWidth;
+                            if( !m_aoFieldDesc[i].bHasWarnedAboutTruncation )
+                            {
+                                CPLError(CE_Warning, CPLE_AppDefined,
+                                         "Content of field %s exceeded the %u character limit and will be truncated",
+                                         m_poFeatureDefn->GetFieldDefn(i)->GetNameRef(),
+                                         static_cast<unsigned int>(nWidth));
+                                m_aoFieldDesc[i].bHasWarnedAboutTruncation = true;
+                            }
+                        }
+                    }
+                    status = nc_put_vara_text( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                                anIndex, anCount, pszVal );
+                }
+                break;
+            }
+
+#ifdef NETCDF_HAS_NC4
+            case NC_STRING:
+            {
+                const char* pszVal = poFeature->GetFieldAsString(i);
+                status = nc_put_var1_string( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                             anIndex, &pszVal );
+                break;
+            }
+#endif
+
+            case NC_BYTE:
+            {
+                int nVal = poFeature->GetFieldAsInteger(i);
+                signed char chVal = static_cast<signed char>(nVal);
+                status = nc_put_var1_schar( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                            anIndex, &chVal );
+                break;
+            }
+
+#ifdef NETCDF_HAS_NC4
+            case NC_UBYTE:
+            {
+                int nVal = poFeature->GetFieldAsInteger(i);
+                unsigned char uchVal = static_cast<unsigned char>(nVal);
+                status = nc_put_var1_uchar( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                            anIndex, &uchVal );
+                break;
+            }
+#endif
+
+            case NC_SHORT:
+            {
+                int nVal = poFeature->GetFieldAsInteger(i);
+                short sVal = static_cast<short>(nVal);
+                status = nc_put_var1_short( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                            anIndex, &sVal );
+                break;
+            }
+
+#ifdef NETCDF_HAS_NC4
+            case NC_USHORT:
+            {
+                int nVal = poFeature->GetFieldAsInteger(i);
+                unsigned short usVal = static_cast<unsigned short>(nVal);
+                status = nc_put_var1_ushort( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                            anIndex, &usVal );
+                break;
+            }
+#endif
+
+            case NC_INT:
+            {
+                int nVal;
+                if( m_poFeatureDefn->GetFieldDefn(i)->GetType() == OFTDate )
+                {
+                    int nYear;
+                    int nMonth;
+                    int nDay;
+                    int nHour;
+                    int nMinute;
+                    float fSecond;
+                    int nTZ;
+                    poFeature->GetFieldAsDateTime( i, &nYear, &nMonth, &nDay,
+                                                &nHour, &nMinute, &fSecond, &nTZ );
+                    struct tm brokendowntime;
+                    brokendowntime.tm_year = nYear - 1900;
+                    brokendowntime.tm_mon= nMonth - 1;
+                    brokendowntime.tm_mday = nDay;
+                    brokendowntime.tm_hour = 0;
+                    brokendowntime.tm_min = 0;
+                    brokendowntime.tm_sec = 0;
+                    GIntBig nVal64 = CPLYMDHMSToUnixTime(&brokendowntime);
+                    if( m_aoFieldDesc[i].bIsDays )
+                        nVal64 /= 86400;
+                    nVal = static_cast<int>(nVal64);
+                }
+                else
+                {
+                    nVal = poFeature->GetFieldAsInteger(i);
+                }
+                status = nc_put_var1_int( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                          anIndex, &nVal );
+                break;
+            }
+
+#ifdef NETCDF_HAS_NC4
+            case NC_UINT:
+            {
+                GIntBig nVal = poFeature->GetFieldAsInteger64(i);
+                unsigned int unVal = static_cast<unsigned int>(nVal);
+                status = nc_put_var1_uint( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                            anIndex, &unVal );
+                break;
+            }
+#endif
+
+#ifdef NETCDF_HAS_NC4
+            case NC_INT64:
+            {
+                GIntBig nVal = poFeature->GetFieldAsInteger64(i);
+                status = nc_put_var1_longlong( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                               anIndex, &nVal );
+                break;
+            }
+
+            case NC_UINT64:
+            {
+                double dfVal = poFeature->GetFieldAsDouble(i);
+                GUIntBig nVal = static_cast<GUIntBig>(dfVal);
+                status = nc_put_var1_ulonglong( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                                anIndex, &nVal );
+                break;
+            }
+#endif
+
+            case NC_FLOAT:
+            {
+                double dfVal = poFeature->GetFieldAsDouble(i);
+                float fVal = static_cast<float>(dfVal);
+                status = nc_put_var1_float( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                            anIndex, &fVal );
+                break;
+            }
+
+            case NC_DOUBLE:
+            {
+                double dfVal;
+                if( m_poFeatureDefn->GetFieldDefn(i)->GetType() == OFTDate ||
+                    m_poFeatureDefn->GetFieldDefn(i)->GetType() == OFTDateTime )
+                {
+                    int nYear;
+                    int nMonth;
+                    int nDay;
+                    int nHour;
+                    int nMinute;
+                    float fSecond;
+                    int nTZ;
+                    poFeature->GetFieldAsDateTime( i, &nYear, &nMonth, &nDay,
+                                                &nHour, &nMinute, &fSecond, &nTZ );
+                    struct tm brokendowntime;
+                    brokendowntime.tm_year = nYear - 1900;
+                    brokendowntime.tm_mon= nMonth - 1;
+                    brokendowntime.tm_mday = nDay;
+                    brokendowntime.tm_hour = nHour;
+                    brokendowntime.tm_min = nMinute;
+                    brokendowntime.tm_sec = static_cast<int>(fSecond);
+                    GIntBig nVal = CPLYMDHMSToUnixTime(&brokendowntime);
+                    dfVal = static_cast<double>(nVal) + fmod(fSecond, 1.0f);
+                    if( m_aoFieldDesc[i].bIsDays )
+                        dfVal /= 86400.0;
+                }
+                else
+                {
+                    dfVal = poFeature->GetFieldAsDouble(i);
+                }
+                status = nc_put_var1_double( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                             anIndex, &dfVal );
+                break;
+            }
+
+            default:
+                break;
+        }
+
+        NCDF_ERR(status);
+        if ( status != NC_NOERR ) {
+            return false;
+        }
+    }
+
+    OGRGeometry* poGeom = poFeature->GetGeometryRef();
+    if( wkbFlatten(m_poFeatureDefn->GetGeomType()) == wkbPoint &&
+        poGeom != NULL &&
+        wkbFlatten(poGeom->getGeometryType()) == wkbPoint )
+    {
+        if( m_osProfileDimName.size() == 0 || nMainDimId == m_nProfileDimID )
+        {
+            double dfX = static_cast<OGRPoint*>(poGeom)->getX();
+            double dfY = static_cast<OGRPoint*>(poGeom)->getY();
+
+            int status;
+
+            if( m_nXVarNCDFType == NC_DOUBLE )
+                status = nc_put_var1_double( m_nLayerCDFId, m_nXVarID, anIndex, &dfX );
+            else
+            {
+                float fX = static_cast<float>(dfX);
+                status = nc_put_var1_float( m_nLayerCDFId, m_nXVarID, anIndex, &fX );
+            }
+            NCDF_ERR(status);
+            if ( status != NC_NOERR ) {
+                return false;
+            }
+
+            if( m_nYVarNCDFType == NC_DOUBLE )
+                status = nc_put_var1_double( m_nLayerCDFId, m_nYVarID, anIndex, &dfY );
+            else
+            {
+                float fY = static_cast<float>(dfY);
+                status = nc_put_var1_float( m_nLayerCDFId, m_nYVarID, anIndex, &fY );
+            }
+            NCDF_ERR(status);
+            if ( status != NC_NOERR ) {
+                return false;
+            }
+        }
+
+        if( m_poFeatureDefn->GetGeomType() == wkbPoint25D &&
+            (m_osProfileDimName.size() == 0 || nMainDimId == m_nRecordDimID) )
+        {
+            int status;
+            double dfZ = static_cast<OGRPoint*>(poGeom)->getZ();
+            if( m_nZVarNCDFType == NC_DOUBLE )
+                status = nc_put_var1_double( m_nLayerCDFId, m_nZVarID, anIndex, &dfZ );
+            else
+            {
+                float fZ = static_cast<float>(dfZ);
+                status = nc_put_var1_float( m_nLayerCDFId, m_nZVarID, anIndex, &fZ );
+            }
+            NCDF_ERR(status);
+            if ( status != NC_NOERR ) {
+                return false;
+            }
+        }
+    }
+    else if( m_poFeatureDefn->GetGeomType() != wkbNone && m_nWKTVarID >= 0 &&
+             poGeom != NULL )
+    {
+        char* pszWKT = NULL;
+        poGeom->exportToWkt( &pszWKT, wkbVariantIso );
+        int status;
+#ifdef NETCDF_HAS_NC4
+        if( m_nWKTNCDFType == NC_STRING )
+        {
+            const char* pszWKTConst = pszWKT;
+            status = nc_put_var1_string( m_nLayerCDFId, m_nWKTVarID,
+                                         anIndex, &pszWKTConst );
+        }
+        else
+#endif
+        {
+            size_t anCount[2];
+            anCount[0] = 1;
+            anCount[1] = strlen(pszWKT);
+            if( anCount[1] > static_cast<unsigned int>(m_nWKTMaxWidth) )
+            {
+                if( m_bAutoGrowStrings )
+                {
+                    size_t nNewSize = anCount[1] + anCount[1] / 3;
+
+                    CPLDebug("GDAL_netCDF", "Growing %s from %u to %u",
+                             m_osWKTVarName.c_str(),
+                             static_cast<unsigned>(m_nWKTMaxWidth),
+                             static_cast<unsigned>(nNewSize) );
+                    m_poDS->GrowDim( m_nLayerCDFId, m_nWKTMaxWidthDimId, nNewSize );
+
+                    m_nWKTMaxWidth = static_cast<int>(nNewSize);
+
+                    status = nc_put_vara_text( m_nLayerCDFId, m_nWKTVarID,
+                                               anIndex, anCount, pszWKT );
+                }
+                else
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                            "Cannot write geometry as WKT. Would require %d "
+                            "characters but field width is %d",
+                            static_cast<int>(anCount[1]),
+                            m_nWKTMaxWidth);
+                    status = NC_NOERR;
+                }
+            }
+            else
+            {
+                status = nc_put_vara_text( m_nLayerCDFId, m_nWKTVarID,
+                                           anIndex, anCount, pszWKT );
+            }
+        }
+        CPLFree(pszWKT);
+        NCDF_ERR(status);
+        if ( status != NC_NOERR ) {
+            return false;
+        }
+    }
+#ifdef NETCDF_HAS_NC4
+    else if( m_poFeatureDefn->GetGeomType() != wkbNone && m_nWKTVarID >= 0 &&
+             poGeom == NULL && m_nWKTNCDFType == NC_STRING && m_bNCDumpCompat )
+    {
+        const char* pszWKTConst = "";
+        int status = nc_put_var1_string( m_nLayerCDFId, m_nWKTVarID,
+                                     anIndex, &pszWKTConst );
+        NCDF_ERR(status);
+    }
+#endif
+
+    return true;
+}
+
+/************************************************************************/
+/*                              AddField()                              */
+/************************************************************************/
+
+bool netCDFLayer::AddField(int nVarID)
+{
+    if( nVarID == m_nWKTVarID )
+        return false;
+
+    char szName[NC_MAX_NAME+1];
+    szName[0] = '\0';
+    CPL_IGNORE_RET_VAL(nc_inq_varname( m_nLayerCDFId, nVarID, szName ));
+
+    nc_type vartype=NC_NAT;
+    nc_inq_vartype( m_nLayerCDFId, nVarID, &vartype );
+
+    OGRFieldType eType = OFTString;
+    OGRFieldSubType eSubType = OFSTNone;
+    int nWidth = 0;
+
+    NCDFNoDataUnion nodata;
+    memset(&nodata, 0, sizeof(nodata));
+    int nDimCount = 1;
+    nc_inq_varndims( m_nLayerCDFId, nVarID, &nDimCount );
+    int anDimIds[2] = { -1, -1 };
+    if( nDimCount <= 2 )
+        nc_inq_vardimid( m_nLayerCDFId, nVarID, anDimIds );
+
+    switch( vartype )
+    {
+        case NC_BYTE:
+        {
+            eType = OFTInteger;
+            char* pszValue = NULL;
+            if( GetFillValue( nVarID, &pszValue) == CE_None )
+                nodata.chVal = static_cast<signed char>(atoi(pszValue));
+            else
+                nodata.chVal = NC_FILL_BYTE;
+            CPLFree(pszValue);
+            break;
+        }
+
+#ifdef NETCDF_HAS_NC4
+        case NC_UBYTE:
+        {
+            eType = OFTInteger;
+            char* pszValue = NULL;
+            if( GetFillValue( nVarID, &pszValue) == CE_None )
+                nodata.uchVal = static_cast<unsigned char>(atoi(pszValue));
+            else
+                nodata.uchVal = NC_FILL_UBYTE;
+            CPLFree(pszValue);
+            break;
+        }
+#endif
+
+        case NC_CHAR:
+        {
+            eType = OFTString;
+            if( nDimCount == 1 )
+            {
+                nWidth = 1;
+            }
+            else if( nDimCount == 2 )
+            {
+                size_t nDimLen = 0;
+                nc_inq_dimlen( m_nLayerCDFId, anDimIds[1], &nDimLen );
+                nWidth = static_cast<int>(nDimLen);
+            }
+            break;
+        }
+
+#ifdef NETCDF_HAS_NC4
+        case NC_STRING:
+        {
+            eType = OFTString;
+            break;
+        }
+#endif
+
+        case NC_SHORT:
+        {
+            eType = OFTInteger;
+            eSubType = OFSTInt16;
+            char* pszValue = NULL;
+            if( GetFillValue( nVarID, &pszValue) == CE_None )
+                nodata.sVal = static_cast<short>(atoi(pszValue));
+            else
+                nodata.sVal = NC_FILL_SHORT;
+            CPLFree(pszValue);
+            break;
+        }
+
+#ifdef NETCDF_HAS_NC4
+        case NC_USHORT:
+        {
+            eType = OFTInteger;
+            char* pszValue = NULL;
+            if( GetFillValue( nVarID, &pszValue) == CE_None )
+                nodata.usVal = static_cast<unsigned short>(atoi(pszValue));
+            else
+                nodata.usVal = NC_FILL_USHORT;
+            CPLFree(pszValue);
+            break;
+        }
+#endif
+
+        case NC_INT:
+        {
+            eType = OFTInteger;
+            char* pszValue = NULL;
+            if( GetFillValue( nVarID, &pszValue) == CE_None )
+                nodata.nVal = atoi(pszValue);
+            else
+                nodata.nVal = NC_FILL_INT;
+            CPLFree(pszValue);
+            break;
+        }
+
+#ifdef NETCDF_HAS_NC4
+        case NC_UINT:
+        {
+            eType = OFTInteger64;
+            char* pszValue = NULL;
+            if( GetFillValue( nVarID, &pszValue) == CE_None )
+                nodata.unVal = static_cast<unsigned int>(CPLAtoGIntBig(pszValue));
+            else
+                nodata.unVal = NC_FILL_UINT;
+            CPLFree(pszValue);
+            break;
+        }
+#endif
+
+#ifdef NETCDF_HAS_NC4
+        case NC_INT64:
+        {
+            eType = OFTInteger64;
+            char* pszValue = NULL;
+            if( GetFillValue( nVarID, &pszValue) == CE_None )
+                nodata.nVal64 = CPLAtoGIntBig(pszValue);
+            else
+                nodata.nVal64 = NC_FILL_INT64;
+            CPLFree(pszValue);
+            break;
+        }
+
+        case NC_UINT64:
+        {
+            eType = OFTReal;
+            char* pszValue = NULL;
+            if( GetFillValue( nVarID, &pszValue) == CE_None )
+            {
+                nodata.unVal64 = 0;
+                for(int i=0; pszValue[i] != '\0'; i++)
+                {
+                    nodata.unVal64 = nodata.unVal64 * 10 + (pszValue[i] - '0');
+                }
+            }
+            else
+                nodata.unVal64 = NC_FILL_UINT64;
+            CPLFree(pszValue);
+            break;
+        }
+#endif
+
+        case NC_FLOAT:
+        {
+            eType = OFTReal;
+            eSubType = OFSTFloat32;
+            double dfValue;
+            if( GetFillValue( nVarID, &dfValue) == CE_None )
+                nodata.fVal = static_cast<float>(dfValue);
+            else
+                nodata.fVal = NC_FILL_FLOAT;
+            break;
+        }
+
+        case NC_DOUBLE:
+        {
+            eType = OFTReal;
+            double dfValue;
+            if( GetFillValue( nVarID, &dfValue) == CE_None )
+                nodata.dfVal = dfValue;
+            else
+                nodata.dfVal = NC_FILL_DOUBLE;
+            break;
+        }
+
+        default:
+        {
+            CPLDebug("GDAL_netCDF", "Variable %s has type %d, which is unhandled",
+                     szName, vartype);
+            return false;
+        }
+    }
+
+    bool bIsDays = false;
+
+    char* pszValue = NULL;
+    if( NCDFGetAttr( m_nLayerCDFId, nVarID, "ogr_field_type", &pszValue ) == CE_None )
+    {
+        if( (eType == OFTInteger || eType == OFTReal) && EQUAL(pszValue, "Date") )
+        {
+            eType = OFTDate;
+            bIsDays = (eType == OFTInteger);
+        }
+        else if( (eType == OFTInteger || eType == OFTReal) && EQUAL(pszValue, "DateTime") )
+            eType = OFTDateTime;
+        else if( eType == OFTReal && EQUAL(pszValue, "Integer64") )
+            eType = OFTInteger64;
+        else if( eType == OFTInteger && EQUAL(pszValue, "Integer(Boolean)") )
+            eSubType = OFSTBoolean;
+    }
+    CPLFree(pszValue);
+    pszValue = NULL;
+
+    if( NCDFGetAttr( m_nLayerCDFId, nVarID, "units", &pszValue ) == CE_None )
+    {
+        if( (eType == OFTInteger || eType == OFTReal || eType == OFTDate) &&
+                                (EQUAL(pszValue, "seconds since 1970-1-1 0:0:0") ||
+                                 EQUAL(pszValue, "seconds since 1970-01-01 00:00:00")) )
+        {
+            if( eType != OFTDate )
+                eType = OFTDateTime;
+            bIsDays = false;
+        }
+        else if( (eType == OFTInteger || eType == OFTReal || eType == OFTDate) &&
+                    (EQUAL(pszValue, "days since 1970-1-1") ||
+                     EQUAL(pszValue, "days since 1970-01-01")) )
+        {
+            eType = OFTDate;
+            bIsDays = true;
+        }
+    }
+    CPLFree(pszValue);
+    pszValue = NULL;
+
+    if( NCDFGetAttr( m_nLayerCDFId, nVarID, "ogr_field_name", &pszValue ) == CE_None )
+    {
+        snprintf(szName, sizeof(szName), "%s", pszValue);
+    }
+    CPLFree(pszValue);
+    pszValue = NULL;
+
+    if( NCDFGetAttr( m_nLayerCDFId, nVarID, "ogr_field_width", &pszValue ) == CE_None )
+    {
+        nWidth = atoi(pszValue);
+    }
+    CPLFree(pszValue);
+    pszValue = NULL;
+
+    int nPrecision = 0;
+    if( NCDFGetAttr( m_nLayerCDFId, nVarID, "ogr_field_precision", &pszValue ) == CE_None )
+    {
+        nPrecision = atoi(pszValue);
+    }
+    CPLFree(pszValue);
+    /* pszValue = NULL; */
+
+    OGRFieldDefn oFieldDefn(szName, eType);
+    oFieldDefn.SetSubType(eSubType);
+    oFieldDefn.SetWidth(nWidth);
+    oFieldDefn.SetPrecision(nPrecision);
+
+    FieldDesc fieldDesc;
+    fieldDesc.uNoData = nodata;
+    fieldDesc.nType = vartype;
+    fieldDesc.nVarId = nVarID;
+    fieldDesc.nDimCount = nDimCount;
+    fieldDesc.nMainDimId = anDimIds[0];
+    fieldDesc.nSecDimId = anDimIds[1];
+    fieldDesc.bHasWarnedAboutTruncation = false;
+    fieldDesc.bIsDays = bIsDays;
+    m_aoFieldDesc.push_back(fieldDesc);
+
+    m_poFeatureDefn->AddFieldDefn(&oFieldDefn);
+
+    return true;
+}
+
+/************************************************************************/
+/*                             CreateField()                            */
+/************************************************************************/
+
+OGRErr netCDFLayer::CreateField(OGRFieldDefn* poFieldDefn, int /* bApproxOK */)
+{
+    int nSecDimId = -1;
+    int nVarID = -1;
+    int status;
+
+    const netCDFWriterConfigField* poConfig = NULL;
+    if( m_poDS->oWriterConfig.m_bIsValid )
+    {
+        std::map<CPLString, netCDFWriterConfigField>::const_iterator oIter;
+        if( m_poLayerConfig != NULL &&
+            (oIter = m_poLayerConfig->m_oFields.find( poFieldDefn->GetNameRef() )) !=
+            m_poLayerConfig->m_oFields.end() )
+        {
+            poConfig = &(oIter->second);
+        }
+        else if( (oIter = m_poDS->oWriterConfig.m_oFields.find(  poFieldDefn->GetNameRef() )) !=
+                 m_poDS->oWriterConfig.m_oFields.end() )
+        {
+            poConfig = &(oIter->second);
+        }
+    }
+
+    if( m_osProfileDimName.size() &&
+        EQUAL(poFieldDefn->GetNameRef(), m_osProfileDimName) &&
+        poFieldDefn->GetType() == OFTInteger )
+    {
+        FieldDesc fieldDesc;
+        fieldDesc.uNoData.nVal = NC_FILL_INT;
+        fieldDesc.nType = NC_INT;
+        fieldDesc.nVarId = m_nProfileVarID;
+        fieldDesc.nDimCount = 1;
+        fieldDesc.nMainDimId = m_nProfileDimID;
+        fieldDesc.nSecDimId = -1;
+        fieldDesc.bHasWarnedAboutTruncation = false;
+        fieldDesc.bIsDays = false;
+        m_aoFieldDesc.push_back(fieldDesc);
+        m_poFeatureDefn->AddFieldDefn(poFieldDefn);
+        return OGRERR_NONE;
+    }
+
+    m_poDS->SetDefineMode(true);
+
+    // Try to use the field name as variable name, but detects conflict first
+    CPLString osVarName(( poConfig != NULL ) ? poConfig->m_osNetCDFName :
+                                        CPLString(poFieldDefn->GetNameRef()));
+
+    status = nc_inq_varid( m_nLayerCDFId, osVarName, &nVarID );
+    if( status == NC_NOERR )
+    {
+        for(int i=1;i<=100;i++)
+        {
+            osVarName = CPLSPrintf("%s%d", poFieldDefn->GetNameRef(), i);
+            status = nc_inq_varid( m_nLayerCDFId, osVarName, &nVarID );
+            if( status != NC_NOERR )
+                break;
+        }
+        CPLDebug("netCDF", "Field %s is written in variable %s",
+                 poFieldDefn->GetNameRef(), osVarName.c_str());
+    }
+
+    const char* pszVarName = osVarName.c_str();
+
+    NCDFNoDataUnion nodata;
+    memset(&nodata, 0, sizeof(nodata));
+
+    const OGRFieldType eType = poFieldDefn->GetType();
+    const OGRFieldSubType eSubType = poFieldDefn->GetSubType();
+    nc_type nType = NC_NAT;
+    int nDimCount = 1;
+
+    // Find which is the dimension that this variable should be indexed against
+    int nMainDimId = m_nRecordDimID;
+    if( m_osProfileVariables.size() )
+    {
+        char** papszTokens = CSLTokenizeString2( m_osProfileVariables,",",
+                                                            CSLT_HONOURSTRINGS );
+        if( CSLFindString( papszTokens, poFieldDefn->GetNameRef() ) >= 0 )
+            nMainDimId = m_nProfileDimID;
+        CSLDestroy(papszTokens);
+    }
+    if( poConfig != NULL && poConfig->m_osMainDim.size() )
+    {
+        int ndims = 0;
+        status = nc_inq_ndims( m_nLayerCDFId, &ndims );
+        NCDF_ERR(status);
+        bool bFound = false;
+        for(int idim = 0; idim < ndims; idim ++)
+        {
+            char szDimName[NC_MAX_NAME+1];
+            szDimName[0] = 0;
+            status = nc_inq_dimname( m_poDS->cdfid, idim, szDimName);
+            NCDF_ERR(status);
+            if( strcmp(poConfig->m_osMainDim, szDimName) == 0 )
+            {
+                nMainDimId = idim;
+                bFound = true;
+                break;
+            }
+        }
+        if( !bFound )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Dimension '%s' does not exist",
+                     poConfig->m_osMainDim.c_str());
+        }
+    }
+
+    switch( eType )
+    {
+        case OFTString:
+        case OFTStringList:
+        case OFTIntegerList:
+        case OFTRealList:
+        {
+            if( poFieldDefn->GetWidth() == 1 )
+            {
+                nType = NC_CHAR;
+                status = nc_def_var( m_nLayerCDFId,
+                                    pszVarName,
+                                    nType, 1, &nMainDimId, &nVarID );
+            }
+#ifdef NETCDF_HAS_NC4
+            else if( m_poDS->eFormat == NCDF_FORMAT_NC4 && m_bUseStringInNC4 )
+            {
+                nType = NC_STRING;
+                status = nc_def_var( m_nLayerCDFId,
+                                     pszVarName,
+                                     nType, 1, &nMainDimId, &nVarID );
+            }
+#endif
+            else
+            {
+                if( poFieldDefn->GetWidth() == 0 && !m_bAutoGrowStrings )
+                {
+                    if( m_nDefaultMaxWidthDimId < 0 )
+                    {
+                        status = nc_def_dim( m_nLayerCDFId,
+                                            "string_default_max_width",
+                                            m_nDefaultWidth,
+                                            &m_nDefaultMaxWidthDimId );
+                        NCDF_ERR(status);
+                        if ( status != NC_NOERR ) {
+                            return OGRERR_FAILURE;
+                        }
+                    }
+                    nSecDimId = m_nDefaultMaxWidthDimId;
+                }
+                else
+                {
+                    size_t nDim = ( poFieldDefn->GetWidth() == 0 ) ?
+                                    m_nDefaultWidth : poFieldDefn->GetWidth();
+                    status = nc_def_dim( m_nLayerCDFId,
+                                        CPLSPrintf("%s_max_width", pszVarName),
+                                        nDim, &nSecDimId );
+                    NCDF_ERR(status);
+                    if ( status != NC_NOERR ) {
+                        return OGRERR_FAILURE;
+                    }
+                }
+
+                nDimCount = 2;
+                int anDims[] = { nMainDimId, nSecDimId };
+                nType = NC_CHAR;
+                status = nc_def_var( m_nLayerCDFId,
+                                    pszVarName,
+                                    nType, 2, anDims, &nVarID );
+            }
+            NCDF_ERR(status);
+            if ( status != NC_NOERR ) {
+                return OGRERR_FAILURE;
+            }
+
+            break;
+        }
+
+        case OFTInteger:
+        {
+            nType = (eSubType == OFSTBoolean) ? NC_BYTE :
+                    (eSubType == OFSTInt16) ?   NC_SHORT :
+                                                NC_INT;
+
+            if( nType == NC_BYTE )
+                nodata.chVal = NC_FILL_BYTE;
+            else if( nType == NC_SHORT )
+                nodata.sVal = NC_FILL_SHORT;
+            else if( nType == NC_INT )
+                nodata.nVal = NC_FILL_INT;
+
+            status = nc_def_var( m_nLayerCDFId,
+                                 pszVarName,
+                                 nType, 1, &nMainDimId, &nVarID );
+            NCDF_ERR(status);
+            if ( status != NC_NOERR ) {
+                return OGRERR_FAILURE;
+            }
+
+            if( eSubType == OFSTBoolean )
+            {
+                signed char anRange[] = { 0, 1 };
+                nc_put_att_schar( m_nLayerCDFId,nVarID, "valid_range",
+                                  NC_BYTE, 2, anRange );
+            }
+
+            break;
+        }
+
+        case OFTInteger64:
+        {
+            nType = NC_DOUBLE;
+            nodata.dfVal = NC_FILL_DOUBLE;
+#ifdef NETCDF_HAS_NC4
+            if( m_poDS->eFormat == NCDF_FORMAT_NC4 )
+            {
+                nType = NC_INT64;
+                nodata.nVal64 = NC_FILL_INT64;
+            }
+#endif
+            status = nc_def_var( m_nLayerCDFId,
+                                 pszVarName,
+                                 nType, 1, &nMainDimId, &nVarID );
+            NCDF_ERR(status);
+            if ( status != NC_NOERR ) {
+                return OGRERR_FAILURE;
+            }
+            break;
+        }
+
+        case OFTReal:
+        {
+            nType = ( eSubType == OFSTFloat32 ) ? NC_FLOAT : NC_DOUBLE;
+            if( eSubType == OFSTFloat32 )
+                nodata.fVal = NC_FILL_FLOAT;
+            else
+                nodata.dfVal = NC_FILL_DOUBLE;
+            status = nc_def_var( m_nLayerCDFId,
+                                 pszVarName,
+                                 nType, 1, &nMainDimId, &nVarID );
+            NCDF_ERR(status);
+            if ( status != NC_NOERR ) {
+                return OGRERR_FAILURE;
+            }
+
+            break;
+        }
+
+        case OFTDate:
+        {
+            nType = NC_INT;
+            status = nc_def_var( m_nLayerCDFId,
+                                 pszVarName,
+                                 nType, 1, &nMainDimId, &nVarID );
+            NCDF_ERR(status);
+            if ( status != NC_NOERR ) {
+                return OGRERR_FAILURE;
+            }
+            nodata.nVal = NC_FILL_INT;
+
+            status = nc_put_att_text( m_nLayerCDFId, nVarID, CF_UNITS,
+                                      strlen("days since 1970-1-1"),
+                                      "days since 1970-1-1" );
+            NCDF_ERR(status);
+
+            break;
+        }
+
+        case OFTDateTime:
+        {
+            nType = NC_DOUBLE;
+            status = nc_def_var( m_nLayerCDFId,
+                                 pszVarName,
+                                 nType, 1, &nMainDimId, &nVarID );
+            NCDF_ERR(status);
+            if ( status != NC_NOERR ) {
+                return OGRERR_FAILURE;
+            }
+            nodata.dfVal = NC_FILL_DOUBLE;
+
+            status = nc_put_att_text( m_nLayerCDFId, nVarID, CF_UNITS,
+                             strlen("seconds since 1970-1-1 0:0:0"),
+                             "seconds since 1970-1-1 0:0:0" );
+            NCDF_ERR(status);
+
+            break;
+        }
+
+        default:
+            return OGRERR_FAILURE;
+    }
+
+
+    FieldDesc fieldDesc;
+    fieldDesc.uNoData = nodata;
+    fieldDesc.nType = nType;
+    fieldDesc.nVarId = nVarID;
+    fieldDesc.nDimCount = nDimCount;
+    fieldDesc.nMainDimId = nMainDimId;
+    fieldDesc.nSecDimId = nSecDimId;
+    fieldDesc.bHasWarnedAboutTruncation = false;
+    fieldDesc.bIsDays = (eType == OFTDate);
+    m_aoFieldDesc.push_back(fieldDesc);
+
+    const char* pszLongName = CPLSPrintf("Field %s", poFieldDefn->GetNameRef());
+    status = nc_put_att_text( m_nLayerCDFId, nVarID, CF_LNG_NAME,
+                     strlen(pszLongName), pszLongName);
+    NCDF_ERR(status);
+
+    if( m_bWriteGDALTags )
+    {
+        status = nc_put_att_text( m_nLayerCDFId, nVarID, "ogr_field_name",
+                        strlen(poFieldDefn->GetNameRef()), poFieldDefn->GetNameRef());
+        NCDF_ERR(status);
+
+        const char* pszType = OGRFieldDefn::GetFieldTypeName(eType);
+        if( eSubType != OFSTNone )
+        {
+            pszType = CPLSPrintf("%s(%s)", pszType,
+                                 OGRFieldDefn::GetFieldSubTypeName(eSubType));
+        }
+        status = nc_put_att_text( m_nLayerCDFId, nVarID, "ogr_field_type",
+                         strlen(pszType), pszType );
+        NCDF_ERR(status);
+
+        const int nWidth = poFieldDefn->GetWidth();
+        if( nWidth || nType == NC_CHAR )
+        {
+            status = nc_put_att_int( m_nLayerCDFId, nVarID, "ogr_field_width",
+                            NC_INT, 1, &nWidth );
+            NCDF_ERR(status);
+
+            const int nPrecision = poFieldDefn->GetPrecision();
+            if( nPrecision )
+            {
+                status = nc_put_att_int( m_nLayerCDFId, nVarID, "ogr_field_precision",
+                                NC_INT, 1, &nPrecision );
+                NCDF_ERR(status);
+            }
+        }
+    }
+
+    //nc_put_att_text( m_nLayerCDFId, nVarID, CF_UNITS,
+    //                 strlen("none"), "none");
+
+    if( m_osGridMapping.size() != 0 && nMainDimId == m_nRecordDimID )
+    {
+        status = nc_put_att_text( m_nLayerCDFId, nVarID, CF_GRD_MAPPING,
+                         m_osGridMapping.size(), m_osGridMapping.c_str() );
+        NCDF_ERR(status);
+    }
+
+    if( m_osCoordinatesValue.size() && nMainDimId == m_nRecordDimID )
+    {
+        status = nc_put_att_text( m_nLayerCDFId, nVarID, CF_COORDINATES,
+                        m_osCoordinatesValue.size(), m_osCoordinatesValue.c_str() );
+        NCDF_ERR(status);
+    }
+
+    if( poConfig != NULL )
+    {
+        netCDFWriteAttributesFromConf(m_nLayerCDFId, nVarID,
+                                      poConfig->m_aoAttributes);
+    }
+
+    m_poFeatureDefn->AddFieldDefn(poFieldDefn);
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                         GetFeatureCount()                            */
+/************************************************************************/
+
+GIntBig netCDFLayer::GetFeatureCount(int bForce)
+{
+    if( m_poFilterGeom == NULL && m_poAttrQuery == NULL )
+    {
+        size_t nDimLen;
+        nc_inq_dimlen ( m_nLayerCDFId, m_nRecordDimID, &nDimLen );
+        return static_cast<GIntBig>(nDimLen);
+    }
+    return OGRLayer::GetFeatureCount(bForce);
+}
+
+/************************************************************************/
+/*                          TestCapability()                            */
+/************************************************************************/
+
+int netCDFLayer::TestCapability(const char* pszCap)
+{
+    if( EQUAL(pszCap, OLCSequentialWrite) )
+        return m_poDS->GetAccess() == GA_Update;
+    if( EQUAL(pszCap, OLCCreateField) )
+        return m_poDS->GetAccess() == GA_Update;
+    if( EQUAL(pszCap, OLCFastFeatureCount) )
+        return( m_poFilterGeom == NULL && m_poAttrQuery == NULL );
+    return FALSE;
+}
diff --git a/frmts/netcdf/netcdfwriterconfig.cpp b/frmts/netcdf/netcdfwriterconfig.cpp
new file mode 100644
index 0000000..a3a0c8c
--- /dev/null
+++ b/frmts/netcdf/netcdfwriterconfig.cpp
@@ -0,0 +1,194 @@
+/******************************************************************************
+ * $Id: netcdfwriterconfig.cpp 33500 2016-02-18 12:01:47Z rouault $
+ *
+ * Project:  netCDF read/write Driver
+ * Purpose:  GDAL bindings over netCDF library.
+ * Author:   Even Rouault <even.rouault at spatialys.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "netcdfdataset.h"
+
+CPL_CVSID("$Id: netcdfwriterconfig.cpp 33500 2016-02-18 12:01:47Z rouault $");
+
+bool netCDFWriterConfiguration::SetNameValue(CPLXMLNode* psNode,
+                                             std::map<CPLString,CPLString>& oMap)
+{
+    const char* pszName = CPLGetXMLValue(psNode, "name", NULL);
+    const char* pszValue = CPLGetXMLValue(psNode, "value", NULL);
+    if( pszName != NULL && pszValue != NULL )
+    {
+        oMap[pszName] = pszValue;
+        return true;
+    }
+    CPLError(CE_Failure, CPLE_IllegalArg, "Missing name/value");
+    return false;
+}
+
+bool netCDFWriterConfiguration::Parse(const char* pszFilename)
+{
+    CPLXMLNode* psRoot;
+    if( STARTS_WITH(pszFilename, "<Configuration") )
+        psRoot = CPLParseXMLString(pszFilename);
+    else
+        psRoot = CPLParseXMLFile(pszFilename);
+    if( psRoot == NULL )
+        return false;
+    CPLXMLTreeCloser oCloser(psRoot);
+
+    for(CPLXMLNode* psIter = psRoot->psChild;
+                    psIter != NULL; psIter = psIter->psNext )
+    {
+        if( psIter->eType != CXT_Element )
+            continue;
+        if( EQUAL(psIter->pszValue, "DatasetCreationOption") )
+        {
+            SetNameValue(psIter, m_oDatasetCreationOptions);
+        }
+        else if( EQUAL(psIter->pszValue, "LayerCreationOption") )
+        {
+            SetNameValue(psIter, m_oLayerCreationOptions);
+        }
+        else if( EQUAL(psIter->pszValue, "Attribute") )
+        {
+            netCDFWriterConfigAttribute oAtt;
+            if( oAtt.Parse(psIter) )
+                m_aoAttributes.push_back(oAtt);
+        }
+        else if( EQUAL(psIter->pszValue, "Field") )
+        {
+            netCDFWriterConfigField oField;
+            if( oField.Parse(psIter) )
+                m_oFields[oField.m_osName.size() ? oField.m_osName : CPLString("__") +  oField.m_osNetCDFName] = oField;
+        }
+        else if( EQUAL(psIter->pszValue, "Layer") )
+        {
+            netCDFWriterConfigLayer oLayer;
+            if( oLayer.Parse(psIter) )
+                m_oLayers[oLayer.m_osName] = oLayer;
+        }
+        else
+            CPLDebug("GDAL_netCDF", "Ignoring %s", psIter->pszValue);
+    }
+
+    m_bIsValid = true;
+
+    return true;
+}
+
+bool netCDFWriterConfigAttribute::Parse(CPLXMLNode* psNode)
+{
+    const char* pszName = CPLGetXMLValue(psNode, "name", NULL);
+    const char* pszValue = CPLGetXMLValue(psNode, "value", NULL);
+    const char* pszType = CPLGetXMLValue(psNode, "type", "string");
+    if( !EQUAL(pszType, "string") && !EQUAL(pszType, "integer") && !EQUAL(pszType, "double") )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, "type='%s' unsupported", pszType);
+        return false;
+    }
+    if( pszName == NULL || pszValue == NULL )
+    {
+        CPLError(CE_Failure, CPLE_IllegalArg, "Missing name/value");
+        return false;
+    }
+    m_osName = pszName;
+    m_osValue = pszValue;
+    m_osType = pszType;
+    return true;
+}
+
+bool netCDFWriterConfigField::Parse(CPLXMLNode* psNode)
+{
+    const char* pszName = CPLGetXMLValue(psNode, "name", NULL);
+    const char* pszNetCDFName = CPLGetXMLValue(psNode, "netcdf_name", pszName);
+    const char* pszMainDim = CPLGetXMLValue(psNode, "main_dim", NULL);
+    if( pszName == NULL && pszNetCDFName == NULL )
+    {
+        CPLError(CE_Failure, CPLE_IllegalArg, "Bot name and netcdf_name are missing");
+        return false;
+    }
+    if( pszName != NULL )
+        m_osName = pszName;
+    if( pszNetCDFName != NULL )
+        m_osNetCDFName = pszNetCDFName;
+    if( pszMainDim != NULL )
+        m_osMainDim = pszMainDim;
+
+    for(CPLXMLNode* psIter = psNode->psChild;
+                    psIter != NULL; psIter = psIter->psNext )
+    {
+        if( psIter->eType != CXT_Element )
+            continue;
+        if( EQUAL(psIter->pszValue, "Attribute") )
+        {
+            netCDFWriterConfigAttribute oAtt;
+            if( oAtt.Parse(psIter) )
+                m_aoAttributes.push_back(oAtt);
+        }
+        else
+            CPLDebug("GDAL_netCDF", "Ignoring %s", psIter->pszValue);
+    }
+
+    return true;
+}
+
+bool netCDFWriterConfigLayer::Parse(CPLXMLNode* psNode)
+{
+    const char* pszName = CPLGetXMLValue(psNode, "name", NULL);
+    const char* pszNetCDFName = CPLGetXMLValue(psNode, "netcdf_name", pszName);
+    if( pszName == NULL  )
+    {
+        CPLError(CE_Failure, CPLE_IllegalArg, "Missing name");
+        return false;
+    }
+    m_osName = pszName;
+    if( pszNetCDFName != NULL )
+        m_osNetCDFName = pszNetCDFName;
+
+    for(CPLXMLNode* psIter = psNode->psChild;
+                    psIter != NULL; psIter = psIter->psNext )
+    {
+        if( psIter->eType != CXT_Element )
+            continue;
+        if( EQUAL(psIter->pszValue, "LayerCreationOption") )
+        {
+            netCDFWriterConfiguration::SetNameValue(psIter, m_oLayerCreationOptions);
+        }
+        else if( EQUAL(psIter->pszValue, "Attribute") )
+        {
+            netCDFWriterConfigAttribute oAtt;
+            if( oAtt.Parse(psIter) )
+                m_aoAttributes.push_back(oAtt);
+        }
+        else if( EQUAL(psIter->pszValue, "Field") )
+        {
+            netCDFWriterConfigField oField;
+            if( oField.Parse(psIter) )
+                m_oFields[oField.m_osName.size() ? oField.m_osName : CPLString("__") +  oField.m_osNetCDFName] = oField;
+        }
+        else
+            CPLDebug("GDAL_netCDF", "Ignoring %s", psIter->pszValue);
+    }
+
+    return true;
+}
diff --git a/frmts/ngsgeoid/ngsgeoiddataset.cpp b/frmts/ngsgeoid/ngsgeoiddataset.cpp
index 2ca4d68..429960e 100644
--- a/frmts/ngsgeoid/ngsgeoiddataset.cpp
+++ b/frmts/ngsgeoid/ngsgeoiddataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ngsgeoiddataset.cpp 28202 2014-12-23 20:12:45Z rouault $
+ * $Id: ngsgeoiddataset.cpp 32538 2015-12-30 13:12:08Z rouault $
  *
  * Project:  NGSGEOID driver
  * Purpose:  GDALDataset driver for NGSGEOID dataset.
@@ -27,16 +27,13 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_vsi_virtual.h"
 #include "cpl_string.h"
+#include "cpl_vsi_virtual.h"
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ngsgeoiddataset.cpp 28202 2014-12-23 20:12:45Z rouault $");
-
-CPL_C_START
-void    GDALRegister_NGSGEOID(void);
-CPL_C_END
+CPL_CVSID("$Id: ngsgeoiddataset.cpp 32538 2015-12-30 13:12:08Z rouault $");
 
 #define HEADER_SIZE (4 * 8 + 3 * 4)
 
@@ -85,7 +82,7 @@ class NGSGEOIDRasterBand : public GDALPamRasterBand
 
   public:
 
-                NGSGEOIDRasterBand( NGSGEOIDDataset * );
+                explicit NGSGEOIDRasterBand( NGSGEOIDDataset * );
 
     virtual CPLErr IReadBlock( int, int, void * );
 
@@ -97,10 +94,10 @@ class NGSGEOIDRasterBand : public GDALPamRasterBand
 /*                        NGSGEOIDRasterBand()                          */
 /************************************************************************/
 
-NGSGEOIDRasterBand::NGSGEOIDRasterBand( NGSGEOIDDataset *poDS )
+NGSGEOIDRasterBand::NGSGEOIDRasterBand( NGSGEOIDDataset *poDSIn )
 
 {
-    this->poDS = poDS;
+    this->poDS = poDSIn;
     this->nBand = 1;
 
     eDataType = GDT_Float32;
@@ -118,28 +115,30 @@ CPLErr NGSGEOIDRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                                        void * pImage )
 
 {
-    NGSGEOIDDataset *poGDS = (NGSGEOIDDataset *) poDS;
+    NGSGEOIDDataset *poGDS = reinterpret_cast<NGSGEOIDDataset *>( poDS );
 
     /* First values in the file corresponds to the south-most line of the imagery */
     VSIFSeekL(poGDS->fp,
-              HEADER_SIZE + (nRasterYSize - 1 - nBlockYOff) * nRasterXSize * 4,
+              HEADER_SIZE + static_cast<vsi_l_offset>(nRasterYSize - 1 - nBlockYOff) * nRasterXSize * 4,
               SEEK_SET);
 
-    if ((int)VSIFReadL(pImage, 4, nRasterXSize, poGDS->fp) != nRasterXSize)
+    if (static_cast<int>(
+            VSIFReadL(pImage, 4, nRasterXSize, poGDS->fp)) != nRasterXSize )
         return CE_Failure;
 
+#ifdef CPL_MSB
     if (poGDS->bIsLittleEndian)
     {
-#ifdef CPL_MSB
         GDALSwapWords( pImage, 4, nRasterXSize, 4 );
-#endif
     }
-    else
-    {
+#endif
+
 #ifdef CPL_LSB
+    if ( !poGDS->bIsLittleEndian )
+    {
         GDALSwapWords( pImage, 4, nRasterXSize, 4 );
-#endif
     }
+#endif
 
     return CE_None;
 }
@@ -148,16 +147,16 @@ CPLErr NGSGEOIDRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /*                          ~NGSGEOIDDataset()                          */
 /************************************************************************/
 
-NGSGEOIDDataset::NGSGEOIDDataset()
+NGSGEOIDDataset::NGSGEOIDDataset() :
+    fp(NULL),
+    bIsLittleEndian(TRUE)
 {
-    fp = NULL;
     adfGeoTransform[0] = 0;
     adfGeoTransform[1] = 1;
     adfGeoTransform[2] = 0;
     adfGeoTransform[3] = 0;
     adfGeoTransform[4] = 0;
     adfGeoTransform[5] = 1;
-    bIsLittleEndian = TRUE;
 }
 
 /************************************************************************/
@@ -182,17 +181,10 @@ int NGSGEOIDDataset::GetHeaderInfo( const GByte* pBuffer,
                                     int* pnCols,
                                     int* pbIsLittleEndian )
 {
-    double dfSLAT;
-    double dfWLON;
-    double dfDLAT;
-    double dfDLON;
-    int nNLAT;
-    int nNLON;
-    int nIKIND;
-
     /* First check IKIND marker to determine if the file */
     /* is in little or big-endian order, and if it is a valid */
     /* NGSGEOID dataset */
+    int nIKIND;
     memcpy(&nIKIND, pBuffer + HEADER_SIZE - 4, 4);
     CPL_LSBPTR32(&nIKIND);
     if (nIKIND == 1)
@@ -213,6 +205,7 @@ int NGSGEOIDDataset::GetHeaderInfo( const GByte* pBuffer,
         }
     }
 
+    double dfSLAT;
     memcpy(&dfSLAT, pBuffer, 8);
     if (*pbIsLittleEndian)
     {
@@ -223,6 +216,8 @@ int NGSGEOIDDataset::GetHeaderInfo( const GByte* pBuffer,
         CPL_MSBPTR64(&dfSLAT);
     }
     pBuffer += 8;
+
+    double dfWLON;
     memcpy(&dfWLON, pBuffer, 8);
     if (*pbIsLittleEndian)
     {
@@ -233,6 +228,8 @@ int NGSGEOIDDataset::GetHeaderInfo( const GByte* pBuffer,
         CPL_MSBPTR64(&dfWLON);
     }
     pBuffer += 8;
+
+    double dfDLAT;
     memcpy(&dfDLAT, pBuffer, 8);
     if (*pbIsLittleEndian)
     {
@@ -243,6 +240,8 @@ int NGSGEOIDDataset::GetHeaderInfo( const GByte* pBuffer,
         CPL_MSBPTR64(&dfDLAT);
     }
     pBuffer += 8;
+
+    double dfDLON;
     memcpy(&dfDLON, pBuffer, 8);
     if (*pbIsLittleEndian)
     {
@@ -253,6 +252,8 @@ int NGSGEOIDDataset::GetHeaderInfo( const GByte* pBuffer,
         CPL_MSBPTR64(&dfDLON);
     }
     pBuffer += 8;
+
+    int nNLAT;
     memcpy(&nNLAT, pBuffer, 4);
     if (*pbIsLittleEndian)
     {
@@ -263,6 +264,8 @@ int NGSGEOIDDataset::GetHeaderInfo( const GByte* pBuffer,
         CPL_MSBPTR32(&nNLAT);
     }
     pBuffer += 4;
+
+    int nNLON;
     memcpy(&nNLON, pBuffer, 4);
     if (*pbIsLittleEndian)
     {
@@ -272,7 +275,7 @@ int NGSGEOIDDataset::GetHeaderInfo( const GByte* pBuffer,
     {
         CPL_MSBPTR32(&nNLON);
     }
-    pBuffer += 4;
+    /*pBuffer += 4;*/
 
     /*CPLDebug("NGSGEOID", "SLAT=%f, WLON=%f, DLAT=%f, DLON=%f, NLAT=%d, NLON=%d, IKIND=%d",
              dfSLAT, dfWLON, dfDLAT, dfDLON, nNLAT, nNLON, nIKIND);*/
@@ -344,9 +347,7 @@ GDALDataset *NGSGEOIDDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    NGSGEOIDDataset         *poDS;
-
-    poDS = new NGSGEOIDDataset();
+    NGSGEOIDDataset *poDS = new NGSGEOIDDataset();
     poDS->fp = fp;
 
     int nRows, nCols;
@@ -405,25 +406,22 @@ const char* NGSGEOIDDataset::GetProjectionRef()
 void GDALRegister_NGSGEOID()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "NGSGEOID" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "NGSGEOID" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "NGSGEOID" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "NOAA NGS Geoid Height Grids" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "frmt_ngsgeoid.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "bin" );
+    poDriver->SetDescription( "NGSGEOID" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "NOAA NGS Geoid Height Grids" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_ngsgeoid.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "bin" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = NGSGEOIDDataset::Open;
-        poDriver->pfnIdentify = NGSGEOIDDataset::Identify;
+    poDriver->pfnOpen = NGSGEOIDDataset::Open;
+    poDriver->pfnIdentify = NGSGEOIDDataset::Identify;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/nitf/ecrgtocdataset.cpp b/frmts/nitf/ecrgtocdataset.cpp
index 26af804..b461d0f 100644
--- a/frmts/nitf/ecrgtocdataset.cpp
+++ b/frmts/nitf/ecrgtocdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ecrgtocdataset.cpp 32232 2015-12-18 12:30:37Z rouault $
+ * $Id: ecrgtocdataset.cpp 33794 2016-03-26 13:19:07Z goatbar $
  *
  * Project:  ECRG TOC read Translator
  * Purpose:  Implementation of ECRGTOCDataset and ECRGTOCSubDataset.
@@ -29,13 +29,15 @@
 
 // g++ -g -Wall -fPIC frmts/nitf/ecrgtocdataset.cpp -shared -o gdal_ECRGTOC.so -Iport -Igcore -Iogr -Ifrmts/vrt -L. -lgdal
 
+#include "cpl_minixml.h"
+#include "gdal_frmts.h"
 #include "gdal_proxy.h"
 #include "ogr_srs_api.h"
 #include "vrtdataset.h"
-#include "cpl_minixml.h"
+
 #include <vector>
 
-CPL_CVSID("$Id: ecrgtocdataset.cpp 32232 2015-12-18 12:30:37Z rouault $");
+CPL_CVSID("$Id: ecrgtocdataset.cpp 33794 2016-03-26 13:19:07Z goatbar $");
 
 /** Overview of used classes :
    - ECRGTOCDataset : lists the different subdatasets, listed in the .xml,
@@ -63,7 +65,7 @@ class ECRGTOCDataset : public GDALPamDataset
 {
   char	    **papszSubDatasets;
   double      adfGeoTransform[6];
-  
+
   char      **papszFileList;
 
   public:
@@ -73,7 +75,7 @@ class ECRGTOCDataset : public GDALPamDataset
         papszFileList = NULL;
     }
 
-    ~ECRGTOCDataset()
+    virtual ~ECRGTOCDataset()
     {
         CSLDestroy( papszSubDatasets );
         CSLDestroy(papszFileList);
@@ -98,14 +100,14 @@ class ECRGTOCDataset : public GDALPamDataset
     {
         return SRS_WKT_WGS84;
     }
-    
+
     static GDALDataset* Build(  const char* pszTOCFilename,
                                 CPLXMLNode* psXML,
                                 CPLString osProduct,
                                 CPLString osDiscId,
                                 CPLString osScale,
                                 const char* pszFilename);
-    
+
     static int Identify( GDALOpenInfo * poOpenInfo );
     static GDALDataset* Open( GDALOpenInfo * poOpenInfo );
 };
@@ -128,11 +130,12 @@ class ECRGTOCSubDataset : public VRTDataset
 
         /* The driver is set to VRT in VRTDataset constructor. */
         /* We have to set it to the expected value ! */
-        poDriver = (GDALDriver *) GDALGetDriverByName( "ECRGTOC" );
+        poDriver = reinterpret_cast<GDALDriver *>(
+            GDALGetDriverByName( "ECRGTOC" ) );
 
         papszFileList = NULL;
     }
-    
+
     ~ECRGTOCSubDataset()
     {
         CSLDestroy(papszFileList);
@@ -180,17 +183,17 @@ void ECRGTOCDataset::AddSubDataset( const char* pszFilename,
 
 {
     char	szName[80];
-    int		nCount = CSLCount(papszSubDatasets ) / 2;
+    const int nCount = CSLCount(papszSubDatasets ) / 2;
 
-    sprintf( szName, "SUBDATASET_%d_NAME", nCount+1 );
-    papszSubDatasets = 
-        CSLSetNameValue( papszSubDatasets, szName, 
+    snprintf( szName, sizeof(szName), "SUBDATASET_%d_NAME", nCount+1 );
+    papszSubDatasets =
+        CSLSetNameValue( papszSubDatasets, szName,
               CPLSPrintf( "ECRG_TOC_ENTRY:%s:%s:%s:%s",
                           LaunderString(pszProductTitle).c_str(),
                           LaunderString(pszDiscId).c_str(),
                           LaunderString(pszScale).c_str(), pszFilename ) );
 
-    sprintf( szName, "SUBDATASET_%d_DESC", nCount+1 );
+    snprintf( szName, sizeof(szName), "SUBDATASET_%d_DESC", nCount+1 );
     papszSubDatasets =
         CSLSetNameValue( papszSubDatasets, szName,
             CPLSPrintf( "Product %s, disc %s, scale %s", pszProductTitle, pszDiscId, pszScale));
@@ -246,9 +249,8 @@ static int GetScaleFromString(const char* pszScale)
 
 static GIntBig GetFromBase34(const char* pszVal, int nMaxSize)
 {
-    int i;
     GIntBig nFrameNumber = 0;
-    for(i=0;i<nMaxSize;i++)
+    for(int i=0;i<nMaxSize;i++)
     {
         char ch = pszVal[i];
         if (ch == '\0')
@@ -281,7 +283,7 @@ static GIntBig GetFromBase34(const char* pszVal, int nMaxSize)
 /************************************************************************/
 
 /* MIL-PRF-32283 - Table II. ECRG zone limits. */
-/* starting with a fake zone 0 for conveniency */
+/* starting with a fake zone 0 for convenience. */
 static const int anZoneUpperLat[] = { 0, 32, 48, 56, 64, 68, 72, 76, 80 };
 
 /* APPENDIX 70, TABLE III of MIL-A-89007 */
@@ -289,73 +291,84 @@ static const int anACst_ADRG[] =
     { 369664, 302592, 245760, 199168, 163328, 137216, 110080, 82432 };
 static const int nBCst_ADRG = 400384;
 
-#define CEIL_ROUND(a, b)  (int)(ceil((double)(a)/(b))*(b))
-#define NEAR_ROUND(a, b)  (int)(floor((double)(a)/(b) + 0.5)*(b))
+// TODO: Why are these two functions done this way?
+static int CEIL_ROUND(double a, double b)
+{
+    return static_cast<int>( ceil( a / b ) * b );
+}
+
+static int NEAR_ROUND(double a, double b)
+{
+    return static_cast<int>( floor( ( a / b ) + 0.5 ) * b );
+}
 
-#define ECRG_PIXELS         2304
+static const int ECRG_PIXELS = 2304;
 
 static
 int GetExtent(const char* pszFrameName, int nScale, int nZone,
               double& dfMinX, double& dfMaxX, double& dfMinY, double& dfMaxY,
               double& dfPixelXSize, double& dfPixelYSize)
 {
-    int nAbsZone = abs(nZone);
+    const int nAbsZone = abs(nZone);
 
 /************************************************************************/
 /*  Compute east-west constant                                          */
 /************************************************************************/
     /* MIL-PRF-89038 - 60.1.2 - East-west pixel constant. */
-    int nEW_ADRG = CEIL_ROUND(anACst_ADRG[nAbsZone-1] * (1e6 / nScale), 512);
-    int nEW_CADRG = NEAR_ROUND(nEW_ADRG / (150. / 100.), 256);
+    const int nEW_ADRG = CEIL_ROUND(anACst_ADRG[nAbsZone-1] * (1e6 / nScale), 512);
+    const int nEW_CADRG = NEAR_ROUND(nEW_ADRG / (150. / 100.), 256);
     /* MIL-PRF-32283 - D.2.1.2 - East-west pixel constant. */
-    int nEW = nEW_CADRG / 256 * 384;
+    const int nEW = nEW_CADRG / 256 * 384;
 
 /************************************************************************/
 /*  Compute number of longitudinal frames                               */
 /************************************************************************/
     /* MIL-PRF-32283 - D.2.1.7 - Longitudinal frames and subframes */
-    int nCols = (int)ceil((double)nEW / ECRG_PIXELS);
+    const int nCols = static_cast<int>(
+        ceil(static_cast<double>(nEW) / ECRG_PIXELS) );
 
 /************************************************************************/
 /*  Compute north-south constant                                        */
 /************************************************************************/
     /* MIL-PRF-89038 - 60.1.1 -  North-south. pixel constant */
-    int nNS_ADRG = CEIL_ROUND(nBCst_ADRG * (1e6 / nScale), 512) / 4;
-    int nNS_CADRG = NEAR_ROUND(nNS_ADRG / (150. / 100.), 256);
+    const int nNS_ADRG = CEIL_ROUND(nBCst_ADRG * (1e6 / nScale), 512) / 4;
+    const int nNS_CADRG = NEAR_ROUND(nNS_ADRG / (150. / 100.), 256);
     /* MIL-PRF-32283 - D.2.1.1 - North-south. pixel constant and Frame Width/Height */
-    int nNS = nNS_CADRG / 256 * 384;
+    const int nNS = nNS_CADRG / 256 * 384;
 
 /************************************************************************/
 /*  Compute number of latitudinal frames and latitude of top of zone    */
 /************************************************************************/
     dfPixelYSize = 90.0 / nNS;
 
-    double dfFrameLatHeight = dfPixelYSize * ECRG_PIXELS;
+    const double dfFrameLatHeight = dfPixelYSize * ECRG_PIXELS;
 
     /* MIL-PRF-32283 - D.2.1.5 - Equatorward and poleward zone extents. */
-    int nUpperZoneFrames = (int)ceil(anZoneUpperLat[nAbsZone] / dfFrameLatHeight);
-    int nBottomZoneFrames = (int)floor(anZoneUpperLat[nAbsZone-1] / dfFrameLatHeight);
-    int nRows = nUpperZoneFrames - nBottomZoneFrames;
+    int nUpperZoneFrames = static_cast<int>(
+        ceil(anZoneUpperLat[nAbsZone] / dfFrameLatHeight) );
+    int nBottomZoneFrames = static_cast<int>(
+        floor(anZoneUpperLat[nAbsZone-1] / dfFrameLatHeight) );
+    const int nRows = nUpperZoneFrames - nBottomZoneFrames;
 
     /* Not sure to really understand D.2.1.5.a. Testing needed */
     if (nZone < 0)
     {
         nUpperZoneFrames = -nBottomZoneFrames;
-        nBottomZoneFrames = nUpperZoneFrames - nRows;
+        /*nBottomZoneFrames = nUpperZoneFrames - nRows;*/
     }
 
-    double dfUpperZoneTopLat = dfFrameLatHeight * nUpperZoneFrames;
+    const double dfUpperZoneTopLat = dfFrameLatHeight * nUpperZoneFrames;
 
 /************************************************************************/
 /*  Compute coordinates of the frame in the zone                        */
 /************************************************************************/
 
     /* Converts the first 10 characters into a number from base 34 */
-    GIntBig nFrameNumber = GetFromBase34(pszFrameName, 10);
+    const GIntBig nFrameNumber = GetFromBase34(pszFrameName, 10);
 
     /*  MIL-PRF-32283 - A.2.6.1 */
-    GIntBig nY = nFrameNumber / nCols;
-    GIntBig nX = nFrameNumber % nCols;
+    const GIntBig nY = nFrameNumber / nCols;
+    const GIntBig nX = nFrameNumber % nCols;
 
 /************************************************************************/
 /*  Compute extent of the frame                                         */
@@ -367,12 +380,14 @@ int GetExtent(const char* pszFrameName, int nScale, int nZone,
 
     dfPixelXSize = 360.0 / nEW;
 
-    double dfFrameLongWidth = dfPixelXSize * ECRG_PIXELS;
+    const double dfFrameLongWidth = dfPixelXSize * ECRG_PIXELS;
     dfMinX = -180.0 + nX * dfFrameLongWidth;
     dfMaxX = dfMinX + dfFrameLongWidth;
 
-    //CPLDebug("ECRG", "Frame %s : minx=%.16g, maxy=%.16g, maxx=%.16g, miny=%.16g",
-    //         pszFrameName, dfMinX, dfMaxY, dfMaxX, dfMinY);
+#ifdef DEBUG_VERBOSE
+    CPLDebug("ECRG", "Frame %s : minx=%.16g, maxy=%.16g, maxx=%.16g, miny=%.16g",
+             pszFrameName, dfMinX, dfMaxY, dfMaxX, dfMinY);
+#endif
 
     return TRUE;
 }
@@ -430,27 +445,25 @@ class ECRGTOCProxyRasterDataSet : public GDALProxyPoolDataset
 /************************************************************************/
 
 ECRGTOCProxyRasterDataSet::ECRGTOCProxyRasterDataSet
-        (ECRGTOCSubDataset* poSubDataset,
-         const char* fileName,
-         int nXSize, int nYSize,
-         double dfMinX, double dfMaxY,
-         double dfPixelXSize, double dfPixelYSize) :
-            /* Mark as shared since the VRT will take several references if we are in RGBA mode (4 bands for this dataset) */
-                GDALProxyPoolDataset(fileName, nXSize, nYSize, GA_ReadOnly, TRUE, SRS_WKT_WGS84)
+        (ECRGTOCSubDataset* poSubDatasetIn,
+         const char* fileNameIn,
+         int nXSizeIn, int nYSizeIn,
+         double dfMinXIn, double dfMaxYIn,
+         double dfPixelXSizeIn, double dfPixelYSizeIn) :
+    /* Mark as shared since the VRT will take several references if we are in RGBA mode (4 bands for this dataset) */
+    GDALProxyPoolDataset(fileNameIn, nXSizeIn, nYSizeIn, GA_ReadOnly, TRUE, SRS_WKT_WGS84),
+    checkDone(FALSE),
+    checkOK(FALSE)
 {
-    int i;
-    this->poSubDataset = poSubDataset;
-    this->dfMinX = dfMinX;
-    this->dfMaxY = dfMaxY;
-    this->dfPixelXSize = dfPixelXSize;
-    this->dfPixelYSize = dfPixelYSize;
+    this->poSubDataset = poSubDatasetIn;
+    this->dfMinX = dfMinXIn;
+    this->dfMaxY = dfMaxYIn;
+    this->dfPixelXSize = dfPixelXSizeIn;
+    this->dfPixelYSize = dfPixelYSizeIn;
 
-    checkDone = FALSE;
-    checkOK = FALSE;
-
-    for(i=0;i<3;i++)
+    for(int i=0;i<3;i++)
     {
-        SetBand(i + 1, new GDALProxyPoolRasterBand(this, i+1, GDT_Byte, nXSize, 1));
+        SetBand(i + 1, new GDALProxyPoolRasterBand(this, i+1, GDT_Byte, nXSizeIn, 1));
     }
 }
 
@@ -465,20 +478,20 @@ int ECRGTOCProxyRasterDataSet::SanityCheckOK(GDALDataset* poSourceDS)
 {
     /*int nSrcBlockXSize, nSrcBlockYSize;
     int nBlockXSize, nBlockYSize;*/
-    double adfGeoTransform[6];
+    double l_adfGeoTransform[6];
     if (checkDone)
         return checkOK;
 
     checkOK = TRUE;
     checkDone = TRUE;
 
-    poSourceDS->GetGeoTransform(adfGeoTransform);
-    WARN_CHECK_DS(fabs(adfGeoTransform[0] - dfMinX) < 1e-10);
-    WARN_CHECK_DS(fabs(adfGeoTransform[3] - dfMaxY) < 1e-10);
-    WARN_CHECK_DS(fabs(adfGeoTransform[1] - dfPixelXSize) < 1e-10);
-    WARN_CHECK_DS(fabs(adfGeoTransform[5] - (-dfPixelYSize)) < 1e-10);
-    WARN_CHECK_DS(adfGeoTransform[2] == 0 &&
-                  adfGeoTransform[4] == 0); /* No rotation */
+    poSourceDS->GetGeoTransform(l_adfGeoTransform);
+    WARN_CHECK_DS(fabs(l_adfGeoTransform[0] - dfMinX) < 1e-10);
+    WARN_CHECK_DS(fabs(l_adfGeoTransform[3] - dfMaxY) < 1e-10);
+    WARN_CHECK_DS(fabs(l_adfGeoTransform[1] - dfPixelXSize) < 1e-10);
+    WARN_CHECK_DS(fabs(l_adfGeoTransform[5] - (-dfPixelYSize)) < 1e-10);
+    WARN_CHECK_DS(l_adfGeoTransform[2] == 0 &&
+                  l_adfGeoTransform[4] == 0); /* No rotation */
     WARN_CHECK_DS(poSourceDS->GetRasterCount() == 3);
     WARN_CHECK_DS(poSourceDS->GetRasterXSize() == nRasterXSize);
     WARN_CHECK_DS(poSourceDS->GetRasterYSize() == nRasterYSize);
@@ -518,8 +531,8 @@ static const char* BuildFullName(const char* pszTOCFilename,
     const char* pszFirstSlashInName = strchr(pszName, '/');
     if (pszFirstSlashInName != NULL)
     {
-        int nFirstDirLen = pszFirstSlashInName - pszName;
-        if ((int)strlen(pszTOCPath) >= nFirstDirLen + 1 &&
+        int nFirstDirLen = static_cast<int>(pszFirstSlashInName - pszName);
+        if (static_cast<int>( strlen(pszTOCPath) ) >= nFirstDirLen + 1 &&
             (pszTOCPath[strlen(pszTOCPath) - (nFirstDirLen + 1)] == '/' ||
                 pszTOCPath[strlen(pszTOCPath) - (nFirstDirLen + 1)] == '\\') &&
             strncmp(pszTOCPath + strlen(pszTOCPath) - nFirstDirLen, pszName, nFirstDirLen) == 0)
@@ -547,36 +560,34 @@ GDALDataset* ECRGTOCSubDataset::Build(  const char* pszProductTitle,
                                         double dfGlobalMaxY,
                                         double dfGlobalPixelXSize,
                                         double dfGlobalPixelYSize)
-    {
-    int i, j;
-    GDALDriver *poDriver;
-    ECRGTOCSubDataset *poVirtualDS;
-    int nSizeX, nSizeY;
-    double adfGeoTransform[6];
-
-    poDriver = GetGDALDriverManager()->GetDriverByName("VRT");
+{
+    GDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName("VRT");
     if( poDriver == NULL )
         return NULL;
 
-    nSizeX = (int)((dfGlobalMaxX - dfGlobalMinX) / dfGlobalPixelXSize + 0.5);
-    nSizeY = (int)((dfGlobalMaxY - dfGlobalMinY) / dfGlobalPixelYSize + 0.5);
+    const int nSizeX = static_cast<int>(
+        (dfGlobalMaxX - dfGlobalMinX) / dfGlobalPixelXSize + 0.5);
+    const int nSizeY = static_cast<int>(
+        (dfGlobalMaxY - dfGlobalMinY) / dfGlobalPixelYSize + 0.5);
 
     /* ------------------------------------ */
     /* Create the VRT with the overall size */
     /* ------------------------------------ */
-    poVirtualDS = new ECRGTOCSubDataset( nSizeX, nSizeY );
+    ECRGTOCSubDataset *poVirtualDS = new ECRGTOCSubDataset( nSizeX, nSizeY );
 
     poVirtualDS->SetProjection(SRS_WKT_WGS84);
 
-    adfGeoTransform[0] = dfGlobalMinX;
-    adfGeoTransform[1] = dfGlobalPixelXSize;
-    adfGeoTransform[2] = 0;
-    adfGeoTransform[3] = dfGlobalMaxY;
-    adfGeoTransform[4] = 0;
-    adfGeoTransform[5] = -dfGlobalPixelYSize;
+    double adfGeoTransform[6] = {
+      dfGlobalMinX,
+      dfGlobalPixelXSize,
+      0,
+      dfGlobalMaxY,
+      0,
+      -dfGlobalPixelYSize
+    };
     poVirtualDS->SetGeoTransform(adfGeoTransform);
 
-    for (i=0;i<3;i++)
+    for (int i=0;i<3;i++)
     {
         poVirtualDS->AddBand(GDT_Byte, NULL);
         GDALRasterBand *poBand = poVirtualDS->GetRasterBand( i + 1 );
@@ -599,7 +610,7 @@ GDALDataset* ECRGTOCSubDataset::Build(  const char* pszProductTitle,
 
     poVirtualDS->papszFileList = poVirtualDS->GDALDataset::GetFileList();
 
-    for(i=0;i<(int)aosFrameDesc.size(); i++)
+    for( int i=0; i < static_cast<int>( aosFrameDesc.size() ); i++)
     {
         const char* pszName = BuildFullName(pszTOCFilename,
                                             aosFrameDesc[i].pszPath,
@@ -611,8 +622,10 @@ GDALDataset* ECRGTOCSubDataset::Build(  const char* pszProductTitle,
                   aosFrameDesc[i].nScale, aosFrameDesc[i].nZone,
                   dfMinX, dfMaxX, dfMinY, dfMaxY, dfPixelXSize, dfPixelYSize);
 
-        int nFrameXSize = (int)((dfMaxX - dfMinX) / dfPixelXSize + 0.5);
-        int nFrameYSize = (int)((dfMaxY - dfMinY) / dfPixelYSize + 0.5);
+        const int nFrameXSize = static_cast<int>(
+            (dfMaxX - dfMinX) / dfPixelXSize + 0.5);
+        const int nFrameYSize = static_cast<int>(
+            (dfMaxY - dfMinY) / dfPixelYSize + 0.5);
 
         poVirtualDS->papszFileList = CSLAddString(poVirtualDS->papszFileList, pszName);
 
@@ -624,20 +637,22 @@ GDALDataset* ECRGTOCSubDataset::Build(  const char* pszProductTitle,
         /* needed (IRasterIO operation). To improve a bit efficiency, we have a cache of opened */
         /* underlying datasets */
         ECRGTOCProxyRasterDataSet* poDS = new ECRGTOCProxyRasterDataSet(
-                (ECRGTOCSubDataset*)poVirtualDS, pszName, nFrameXSize, nFrameYSize,
-                dfMinX, dfMaxY, dfPixelXSize, dfPixelYSize);
+            reinterpret_cast<ECRGTOCSubDataset *>( poVirtualDS), pszName,
+            nFrameXSize, nFrameYSize,
+            dfMinX, dfMaxY, dfPixelXSize, dfPixelYSize);
 
-        for(j=0;j<3;j++)
+        for( int j=0; j<3; j++)
         {
-            VRTSourcedRasterBand *poBand = (VRTSourcedRasterBand*)
-                                        poVirtualDS->GetRasterBand( j + 1 );
+            VRTSourcedRasterBand *poBand = reinterpret_cast<VRTSourcedRasterBand *>(
+                poVirtualDS->GetRasterBand( j + 1 ) );
             /* Place the raster band at the right position in the VRT */
-            poBand->AddSimpleSource(poDS->GetRasterBand(j + 1),
-                                    0, 0, nFrameXSize, nFrameYSize,
-                                    (int)((dfMinX - dfGlobalMinX) / dfGlobalPixelXSize + 0.5),
-                                    (int)((dfGlobalMaxY - dfMaxY) / dfGlobalPixelYSize + 0.5),
-                                    (int)((dfMaxX - dfMinX) / dfGlobalPixelXSize + 0.5),
-                                    (int)((dfMaxY - dfMinY) / dfGlobalPixelYSize + 0.5));
+            poBand->AddSimpleSource(
+                poDS->GetRasterBand(j + 1),
+                0, 0, nFrameXSize, nFrameYSize,
+                static_cast<int>((dfMinX - dfGlobalMinX) / dfGlobalPixelXSize + 0.5),
+                static_cast<int>((dfGlobalMaxY - dfMaxY) / dfGlobalPixelYSize + 0.5),
+                static_cast<int>((dfMaxX - dfMinX) / dfGlobalPixelXSize + 0.5),
+                static_cast<int>((dfMaxY - dfMinY) / dfGlobalPixelYSize + 0.5));
         }
 
         /* The ECRGTOCProxyRasterDataSet will be destroyed when its last raster band will be */
@@ -671,7 +686,7 @@ GDALDataset* ECRGTOCDataset::Build(const char* pszTOCFilename,
 
     double dfGlobalMinX = 0, dfGlobalMinY = 0, dfGlobalMaxX = 0, dfGlobalMaxY= 0;
     double dfGlobalPixelXSize = 0, dfGlobalPixelYSize = 0;
-    int bGlobalExtentValid = FALSE;
+    bool bGlobalExtentValid = false;
 
     ECRGTOCDataset* poDS = new ECRGTOCDataset();
     int nSubDatasets = 0;
@@ -779,9 +794,10 @@ GDALDataset* ECRGTOCDataset::Build(const char* pszTOCFilename,
                         }
                         if( nCountScales > 1 )
                         {
-                            CPLError(CE_Failure, CPLE_AppDefined,
-                                     "Scale should be mentionned in subdatasets "
-                                     "syntax since this disk contains several scales");
+                            CPLError( CE_Failure, CPLE_AppDefined,
+                                      "Scale should be mentioned in "
+                                      "subdatasets syntax since this disk "
+                                      "contains several scales" );
                             delete poDS;
                             return NULL;
                         }
@@ -892,7 +908,7 @@ GDALDataset* ECRGTOCDataset::Build(const char* pszTOCFilename,
                         dfGlobalMaxY = dfMaxY;
                         dfGlobalPixelXSize = dfPixelXSize;
                         dfGlobalPixelYSize = dfPixelYSize;
-                        bGlobalExtentValid = TRUE;
+                        bGlobalExtentValid = true;
                     }
                     else
                     {
@@ -973,8 +989,10 @@ GDALDataset* ECRGTOCDataset::Build(const char* pszTOCFilename,
     poDS->adfGeoTransform[4] = 0.0;
     poDS->adfGeoTransform[5] = - dfGlobalPixelYSize;
 
-    poDS->nRasterXSize = (int)(0.5 + (dfGlobalMaxX - dfGlobalMinX) / dfGlobalPixelXSize);
-    poDS->nRasterYSize = (int)(0.5 + (dfGlobalMaxY - dfGlobalMinY) / dfGlobalPixelYSize);
+    poDS->nRasterXSize = static_cast<int>(
+        0.5 + (dfGlobalMaxX - dfGlobalMinX) / dfGlobalPixelXSize);
+    poDS->nRasterYSize = static_cast<int>(
+        0.5 + (dfGlobalMaxY - dfGlobalMinY) / dfGlobalPixelYSize);
 
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
@@ -992,18 +1010,19 @@ int ECRGTOCDataset::Identify( GDALOpenInfo * poOpenInfo )
 
 {
     const char *pszFilename = poOpenInfo->pszFilename;
-    const char *pabyHeader = (const char *) poOpenInfo->pabyHeader;
 
 /* -------------------------------------------------------------------- */
 /*      Is this a sub-dataset selector? If so, it is obviously ECRGTOC. */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszFilename, "ECRG_TOC_ENTRY:",strlen("ECRG_TOC_ENTRY:")))
+    if( STARTS_WITH_CI(pszFilename, "ECRG_TOC_ENTRY:"))
         return TRUE;
 
 /* -------------------------------------------------------------------- */
 /*  First we check to see if the file has the expected header           */
 /*  bytes.                                                              */
 /* -------------------------------------------------------------------- */
+    const char *pabyHeader
+        = reinterpret_cast<const char *>( poOpenInfo->pabyHeader );
     if( pabyHeader == NULL )
         return FALSE;
 
@@ -1024,17 +1043,17 @@ int ECRGTOCDataset::Identify( GDALOpenInfo * poOpenInfo )
 GDALDataset *ECRGTOCDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
+    if( !Identify( poOpenInfo ) )
+        return NULL;
+
     const char *pszFilename = poOpenInfo->pszFilename;
     CPLString osFilename;
     CPLString osProduct, osDiscId, osScale;
 
-    if( !Identify( poOpenInfo ) )
-        return NULL;
-
-    if( EQUALN(pszFilename, "ECRG_TOC_ENTRY:",strlen("ECRG_TOC_ENTRY:")))
+    if( STARTS_WITH_CI(pszFilename, "ECRG_TOC_ENTRY:") )
     {
         pszFilename += strlen("ECRG_TOC_ENTRY:");
-        
+
         /* PRODUCT:DISK:SCALE:FILENAME (or PRODUCT:DISK:FILENAME historically) */
         /* with FILENAME potentially C:\BLA... */
         char** papszTokens = CSLTokenizeString2(pszFilename, ":", 0);
@@ -1044,7 +1063,7 @@ GDALDataset *ECRGTOCDataset::Open( GDALOpenInfo * poOpenInfo )
             CSLDestroy(papszTokens);
             return NULL;
         }
-        
+
         osProduct = papszTokens[0];
         osDiscId = papszTokens[1];
 
@@ -1118,26 +1137,23 @@ GDALDataset *ECRGTOCDataset::Open( GDALOpenInfo * poOpenInfo )
 void GDALRegister_ECRGTOC()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "ECRGTOC" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "ECRGTOC" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "ECRGTOC" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "ECRG TOC format" );
-        
-        poDriver->pfnIdentify = ECRGTOCDataset::Identify;
-        poDriver->pfnOpen = ECRGTOCDataset::Open;
-
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#ECRGTOC" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "xml" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "ECRGTOC" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "ECRG TOC format" );
+
+    poDriver->pfnIdentify = ECRGTOCDataset::Identify;
+    poDriver->pfnOpen = ECRGTOCDataset::Open;
+
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_various.html#ECRGTOC" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "xml" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/nitf/frmt_nitf.html b/frmts/nitf/frmt_nitf.html
index 45af366..8d79d3c 100644
--- a/frmts/nitf/frmt_nitf.html
+++ b/frmts/nitf/frmt_nitf.html
@@ -18,13 +18,13 @@ including CIB and CADRG frames from RPF products, ECRG frames, HRE products.<p>
 Color tables for pseudocolored images are read.  In some cases nodata values
 may be identified.<p>
 
-Lat/Long extents are read from the IGEOLO information in 
-the image header if available.  If high precision lat/long georeferencing 
-information is available in RPF auxiliary data it will be used in preference 
-to the low precision IGEOLO information.  In case a BLOCKA instance is found, 
-the higher precision coordinates of BLOCKA are used if the block data covers 
-the complete image - that is the L_LINES field with the row count for that 
-block is equal to the row count of the image. Additionally, all BLOCKA 
+Lat/Long extents are read from the IGEOLO information in
+the image header if available.  If high precision lat/long georeferencing
+information is available in RPF auxiliary data it will be used in preference
+to the low precision IGEOLO information.  In case a BLOCKA instance is found,
+the higher precision coordinates of BLOCKA are used if the block data covers
+the complete image - that is the L_LINES field with the row count for that
+block is equal to the row count of the image. Additionally, all BLOCKA
 instances are returned as metadata. If GeoSDE TRE are available, they will be
 used to provide higher precision coordinates.
 <p>
@@ -36,14 +36,14 @@ metadata.<p>
 
 On export NITF files are always written as NITF 2.1 with one image
 and no other auxiliary layers. Images are uncompressed by default, but JPEG
-and JPEG2000 compression are also available. Georeferencing can only be written for 
-images using a geographic coordinate system or a UTM WGS84 projection.  Coordinates are implicitly 
+and JPEG2000 compression are also available. Georeferencing can only be written for
+images using a geographic coordinate system or a UTM WGS84 projection.  Coordinates are implicitly
 treated as WGS84 even if they are actually in a different geographic coordinate
 system.  Pseudo-color tables may be written for 8bit images.<P>
 
 In addition to the export oriented CreateCopy() API, it is also possible to
 create a blank NITF file using Create() and write imagery on demand.  However,
-using this methology writing of pseudocolor tables and georeferencing is
+using this methodology writing of pseudocolor tables and georeferencing is
 not supported unless appropriate IREP and ICORDS creation options are supplied.
 <p>
 
@@ -53,10 +53,10 @@ Creation Options:<p>
 
 <li> Most file header, imagery header metadata and security fields can
 be set with appropriate <b>creation options</b> (although they are reported as metadata
-item, but must not be set as metadata).  For instance setting 
-<tt>"FTITLE=Image of abandoned missle silo south west of Karsk"</tt> in the
+item, but must not be set as metadata).  For instance setting
+<tt>"FTITLE=Image of abandoned missile silo south west of Karsk"</tt> in the
 creation option list would result in setting of the FTITLE field in the NITF
-file header.  Use the official field names from the NITF specification 
+file header.  Use the official field names from the NITF specification
 document; do not put the "NITF_" prefix that is reported when asking the metadata
 list.<p>
 
@@ -69,7 +69,7 @@ creation options can be used. See the <a href="frmt_jpeg.html">JPEG driver
 documentation</a>. Starting with GDAL 1.7.0, multi-block images can be written.
 <li>M3 is a variation of C3. The only difference is that a block map is written,
 which allow for fast seeking to any block. (Starting with GDAL 1.7.0.)
-<li>C8 means JPEG2000 compression (one block) and is available for 
+<li>C8 means JPEG2000 compression (one block) and is available for
 CreateCopy() and/or Create() methods. JPEG2000 compression is only available
 if the JP2ECW, JP2KAK or Jasper driver is available :
 <ul>
@@ -98,7 +98,7 @@ If you Create() a new NITF file and have specified "N" or "S" for ICORDS,
 you need to call later the SetProjection method with a consistent
 UTM SRS to set the UTM zone number (otherwise it will default to zone 0).<p>
 
-<li> <b>FHDR</b>: File version can be selected though currently the only 
+<li> <b>FHDR</b>: File version can be selected though currently the only
 two variations supported are "NITF02.10" (the default), and "NSIF01.00". <p>
 
 <li> <b>IREP</b>: Set to "RGB/LUT" to reserve space for a color table for
@@ -122,15 +122,15 @@ file (.tfw).<p>
 
 <li> <b>BLOCKYSIZE=n</b>: Set the block height.<p>
 
-<li> <b>BLOCKA_*=</b>: If a complete set of BLOCKA options is provided with 
-exactly the same organization as the NITF_BLOCKA metadata reported when 
-reading an NITF file with BLOCKA TREs then a file will be created with BLOCKA 
+<li> <b>BLOCKA_*=</b>: If a complete set of BLOCKA options is provided with
+exactly the same organization as the NITF_BLOCKA metadata reported when
+reading an NITF file with BLOCKA TREs then a file will be created with BLOCKA
 TREs. <p>
 
-<li> <b>TRE=tre-name=tre-contents</b>: One or more TRE creation options may 
+<li> <b>TRE=tre-name=tre-contents</b>: One or more TRE creation options may
 be used provided to write arbitrary user defined TREs to the image header.  The
-tre-name should be at most six characters, and the tre-contents should be 
-"backslash escaped" if it contains blackslashes or zero bytes.  The argument
+tre-name should be at most six characters, and the tre-contents should be
+"backslash escaped" if it contains backslashes or zero bytes.  The argument
 is the same format as returned in the TRE metadata domain when reading.<p>
 
 <li> <b>FILE_TRE=tre-name=tre-contents</b>: (GDAL >= 1.8.0) Similar to above options,
@@ -162,6 +162,3 @@ Steve Rawlinson (JPEG), Reiner Beck (BLOCKA) for assistance adding features.<p>
 
 </body>
 </html>
-
-
-
diff --git a/frmts/nitf/frmt_nitf_advanced.html b/frmts/nitf/frmt_nitf_advanced.html
index 2d8b901..df23b85 100644
--- a/frmts/nitf/frmt_nitf_advanced.html
+++ b/frmts/nitf/frmt_nitf_advanced.html
@@ -7,7 +7,7 @@
 
 <h1>NITF -- Advanced Driver Information</h1>
 
-The NITF (National Imagery Transmission Format) driver in GDAL includes a 
+The NITF (National Imagery Transmission Format) driver in GDAL includes a
 number of advanced, and somewhat esoteric options not suitable for the
 <a href="frmt_nitf.html">general end user documentation</a> for the driver.
 This information is collected here, and is primarily aimed at developers and
@@ -16,7 +16,7 @@ advanced users.
 <h2>CGM Segments</h2>
 
 NITF files that have CGM data (that is segment type GR - graphics, or SY with
-an STYPE value of 'C') will make that information available as metadata in the 
+an STYPE value of 'C') will make that information available as metadata in the
 CGM domain.  The returned metadata will look something like:
 
 <pre>
@@ -30,12 +30,12 @@ CGM domain.  The returned metadata will look something like:
   SEGMENT_0_DATA=\0!\0...
 </pre>
 
-The SLOC_ROW and SLOC_COL values are the placement of the CGM object relative 
+The SLOC_ROW and SLOC_COL values are the placement of the CGM object relative
 to the base (SALVL) image.  The CCS_ROW/COL values are relative to the common
-coordinate system.  The _SDLVL is the display level.  
-The DATA is the raw CGM data with "backslash quotable" escaping 
-applied.  All occurances of ASCII zero will be translated to '\0', and all 
-backslashes and double quotes will be backslashed escaped.  The 
+coordinate system.  The _SDLVL is the display level.
+The DATA is the raw CGM data with "backslash quotable" escaping
+applied.  All occurrences of ASCII zero will be translated to '\0', and all
+backslashes and double quotes will be backslashed escaped.  The
 CPLUnescapeString() function can be used to unescape the data into binary
 format using scheme CPLES_BackslashQuotable. <p>
 
@@ -48,15 +48,13 @@ Since GDAL 1.8.0, to add CGM data to a NITF image, you can pass creation options
   CGM=SEGMENT_0_SDLVL=2
   CGM=SEGMENT_0_SALVL=1
   CGM=SEGMENT_0_DATA=\0!\0...
-</pre> 
+</pre>
 
 Notice that passing CGM as creation options will overwrite existing CGM segment read in the CGM metadata domain.
-
 <p>
 
-
-While GDAL does not support parsing or rendering CGM data, at least one user 
-has found the <a href="http://sk1project.org/modules.php?name=Products&product=uniconvertor">UniConverter</a> 
+While GDAL does not support parsing or rendering CGM data, at least one user
+has found the <a href="http://sk1project.org/modules.php?name=Products&product=uniconvertor">UniConverter</a>
 library useful for this purpose.
 
 <h2>Multi-Image NITF Files</h2>
@@ -78,15 +76,15 @@ Subdatasets:
 
 In this case opening "multi_image_jpeg_2.0.ntf" directly will give
 access to "NITF_IM:0:multi_image_jpeg_2.0.ntf".  To open the others
-use the corresponding subdataset names.  The Subdataset mechanism is 
-generic GDAL concept discussed in the 
-<a href="http://www.gdal.org/gdal_datamodel.html">GDAL Data Model</a> 
+use the corresponding subdataset names.  The Subdataset mechanism is
+generic GDAL concept discussed in the
+<a href="http://www.gdal.org/gdal_datamodel.html">GDAL Data Model</a>
 document.<p>
 
 <h2>Text Segments</h2>
 
-NITF files that have text segments (that is segment type TX) will make that 
-information available as metadata in the TEXT domain. 
+NITF files that have text segments (that is segment type TX) will make that
+information available as metadata in the TEXT domain.
 The returned metadata will look something like:
 
 <pre>
@@ -110,9 +108,9 @@ The argument to DATA_n
 is the raw text of the n'th (zero based) text segment with no escaping of any
 kind applied. <p>
 
-Since GDAL 1.8.0, the TEXT segment header data is preserved in HEADER_n metdata item.
+Since GDAL 1.8.0, the TEXT segment header data is preserved in HEADER_n metadata item.
 
-The CreateCopy() method on the NITF driver also supports creating 
+The CreateCopy() method on the NITF driver also supports creating
 text segments on the output file as long as the input file has metadata
 in the TEXT domain as defined above.<p>
 
@@ -123,31 +121,31 @@ Since GDAL 1.8.0, to add TEXT data to a NITF image, you can also pass creation o
   TEXT=DATA_0=This is test text file 01.
   TEXT=HEADER_1=TE       00020021216151629xxxxxxxxxxxxxxxxxxxxxxxxxxx
   TEXT=DATA_1=This is test text file 02.
-</pre> 
+</pre>
 
 Notice that passing TEXT as creation options will overwrite existing text segment read in the TEXT metadata domain.
 
 <h2>TREs</h2>
 
-NITF files with registered (or unregistered?) extensions on the file header, 
+NITF files with registered (or unregistered?) extensions on the file header,
 or the referenced image header will make them available in a raw form in
 metadata via the TRE domain.  The TRE domain will hold one metadata item per
 TRE which will have the name of the TRE as the name, and the data of the TRE
 as the contents.  The data contents will be "backslash escaped" like CGM
 data above. <p>
 
-In case of multiple occurences of the same TRE, the second occurence will be
+In case of multiple occurrences of the same TRE, the second occurrence will be
 named "TRENAME_2", the third "TRENAME_3" where TRENAME is the TRE name.<p>
 
 <pre>
 Metadata (TRE):
-  GEOPSB=MAPM  World Geodetic System 1984                                       
-               WGE World Geodetic System 1984                                   
-                   WE Geodetic                                                  
-                      GEODMean Sea                                              
-                          MSL 000000000000000                                   
+  GEOPSB=MAPM  World Geodetic System 1984
+               WGE World Geodetic System 1984
+                   WE Geodetic
+                      GEODMean Sea
+                          MSL 000000000000000
                                                 0000
-  PRJPSB=Polar Stereographic                                                    
+  PRJPSB=Polar Stereographic
          PG2-00090.00000250000039.99999884000000000000000000000000000000
   MAPLOB=M  0598005958-000003067885.8-000002163353.8
 </pre>
@@ -213,8 +211,8 @@ Metadata (xml:TRE):
 
 In some cases application may need to recover very specific information
 from the image or file headers that isn't normally available as metadata.
-In this case it is possible to query the "NITF_METADATA" metadata domain.  
-The complete file and image headers will be returned as metadata in base64 
+In this case it is possible to query the "NITF_METADATA" metadata domain.
+The complete file and image headers will be returned as metadata in base64
 encoded format.  Something like:<p>
 
 <pre>
@@ -228,6 +226,3 @@ header is the length (decoded) in bytes, followed by one space.  <p>
 
 </body>
 </html>
-
-
-
diff --git a/frmts/nitf/mgrs.c b/frmts/nitf/mgrs.c
index c4bd57c..d0944e2 100644
--- a/frmts/nitf/mgrs.c
+++ b/frmts/nitf/mgrs.c
@@ -1,5 +1,5 @@
 /***************************************************************************
- * $Id: mgrs.c 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: mgrs.c 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  MGRS Converter
  * Purpose:  Geotrans code for MGRS translation (slightly adapted)
@@ -11,24 +11,24 @@
  *
  * ABSTRACT
  *
- *    This component converts between geodetic coordinates (latitude and 
- *    longitude) and Military Grid Reference System (MGRS) coordinates. 
+ *    This component converts between geodetic coordinates (latitude and
+ *    longitude) and Military Grid Reference System (MGRS) coordinates.
  *
  * ERROR HANDLING
  *
  *    This component checks parameters for valid values.  If an invalid value
- *    is found, the error code is combined with the current error code using 
+ *    is found, the error code is combined with the current error code using
  *    the bitwise or.  This combining allows multiple error codes to be
  *    returned. The possible error codes are:
  *
  *          MGRS_NO_ERROR          : No errors occurred in function
- *          MGRS_LAT_ERROR         : Latitude outside of valid range 
+ *          MGRS_LAT_ERROR         : Latitude outside of valid range
  *                                    (-90 to 90 degrees)
  *          MGRS_LON_ERROR         : Longitude outside of valid range
  *                                    (-180 to 360 degrees)
  *          MGRS_STR_ERROR         : An MGRS string error: string too long,
  *                                    too short, or badly formed
- *          MGRS_PRECISION_ERROR   : The precision must be between 0 and 5 
+ *          MGRS_PRECISION_ERROR   : The precision must be between 0 and 5
  *                                    inclusive.
  *          MGRS_A_ERROR           : Semi-major axis less than or equal to zero
  *          MGRS_INV_F_ERROR       : Inverse flattening outside of valid range
@@ -76,7 +76,7 @@
  *    ----              -----------
  *    16-11-94          Original Code
  *    15-09-99          Reengineered upper layers
- *    02-05-03          Corrected latitude band bug in GRID_UTM 
+ *    02-05-03          Corrected latitude band bug in GRID_UTM
  *    08-20-03          Reengineered lower layers
  */
 
@@ -139,50 +139,51 @@
 #define TWOMIL        2000000.e0    /* TWO MILLION                           */
 #define TRUE                      1  /* CONSTANT VALUE FOR TRUE VALUE  */
 #define FALSE                     0  /* CONSTANT VALUE FOR FALSE VALUE */
-#define PI    3.14159265358979323e0  /* PI                             */
-#define PI_OVER_2  (PI / 2.0e0)
+#define PI_OVER_2  (M_PI / 2.0e0)
 
 #define MIN_EASTING  100000
 #define MAX_EASTING  900000
 #define MIN_NORTHING 0
 #define MAX_NORTHING 10000000
 #define MAX_PRECISION           5   /* Maximum precision of easting & northing */
-#define MIN_UTM_LAT      ( (-80 * PI) / 180.0 ) /* -80 degrees in radians    */
-#define MAX_UTM_LAT      ( (84 * PI) / 180.0 )  /* 84 degrees in radians     */
+#define MIN_UTM_LAT      ( (-80 * M_PI) / 180.0 ) /* -80 degrees in radians    */
+#define MAX_UTM_LAT      ( (84 * M_PI) / 180.0 )  /* 84 degrees in radians     */
 
 #define MIN_EAST_NORTH 0
 #define MAX_EAST_NORTH 4000000
 
 
 /* Ellipsoid parameters, default to WGS 84 */
-double MGRS_a = 6378137.0;    /* Semi-major axis of ellipsoid in meters */
-double MGRS_f = 1 / 298.257223563; /* Flattening of ellipsoid           */
-double MGRS_recpf = 298.257223563;
-char   MGRS_Ellipsoid_Code[3] = {'W','E',0};
+static const double MGRS_a = 6378137.0;    /* Semi-major axis of ellipsoid in meters */
+static const double MGRS_f = 1 / 298.257223563; /* Flattening of ellipsoid           */
+#ifdef unused
+static const double MGRS_recpf = 298.257223563;
+#endif
+static const char   MGRS_Ellipsoid_Code[3] = {'W','E',0};
 
 
-/* 
+/*
  *    CLARKE_1866 : Ellipsoid code for CLARKE_1866
  *    CLARKE_1880 : Ellipsoid code for CLARKE_1880
  *    BESSEL_1841 : Ellipsoid code for BESSEL_1841
  *    BESSEL_1841_NAMIBIA : Ellipsoid code for BESSEL 1841 (NAMIBIA)
  */
-const char* CLARKE_1866 = "CC";
-const char* CLARKE_1880 = "CD";
-const char* BESSEL_1841 = "BR";
-const char* BESSEL_1841_NAMIBIA = "BN";
+static const char* const CLARKE_1866 = "CC";
+static const char* const CLARKE_1880 = "CD";
+static const char* const BESSEL_1841 = "BR";
+static const char* const BESSEL_1841_NAMIBIA = "BN";
 
 
 typedef struct Latitude_Band_Value
 {
   long letter;            /* letter representing latitude band  */
-  double min_northing;    /* minimum northing for latitude band */       
+  double min_northing;    /* minimum northing for latitude band */
   double north;           /* upper latitude for latitude band   */
   double south;           /* lower latitude for latitude band   */
-} Latitude_Band; 
+} Latitude_Band;
 
-static const Latitude_Band Latitude_Band_Table[20] = 
-  {{LETTER_C, 1100000.0, -72.0, -80.5}, 
+static const Latitude_Band Latitude_Band_Table[20] =
+  {{LETTER_C, 1100000.0, -72.0, -80.5},
   {LETTER_D, 2000000.0, -64.0, -72.0},
   {LETTER_E, 2800000.0, -56.0, -64.0},
   {LETTER_F, 3700000.0, -48.0, -56.0},
@@ -203,7 +204,7 @@ static const Latitude_Band Latitude_Band_Table[20] =
   {LETTER_W, 7000000.0, 72.0, 64.0},
   {LETTER_X, 7900000.0, 84.5, 72.0}};
 
- 
+
 typedef struct UPS_Constant_Value
 {
   long letter;            /* letter representing latitude band      */
@@ -212,9 +213,9 @@ typedef struct UPS_Constant_Value
   long ltr3_high_value;   /* 3rd letter range - high number (UPS)   */
   double false_easting;   /* False easting based on 2nd letter      */
   double false_northing;  /* False northing based on 3rd letter     */
-} UPS_Constant; 
+} UPS_Constant;
 
-static const UPS_Constant UPS_Constant_Table[4] = 
+static const UPS_Constant UPS_Constant_Table[4] =
   {{LETTER_A, LETTER_J, LETTER_Z, LETTER_Z, 800000.0, 800000.0},
   {LETTER_B, LETTER_A, LETTER_R, LETTER_Z, 2000000.0, 800000.0},
   {LETTER_Y, LETTER_J, LETTER_Z, LETTER_P, 800000.0, 1300000.0},
@@ -222,10 +223,10 @@ static const UPS_Constant UPS_Constant_Table[4] =
 
 /***************************************************************************/
 /*
- *                              FUNCTIONS     
+ *                              FUNCTIONS
  */
 
-long Get_Latitude_Band_Min_Northing(long letter, double* min_northing)
+static long Get_Latitude_Band_Min_Northing(long letter, double* min_northing)
 /*
  * The function Get_Latitude_Band_Min_Northing receives a latitude band letter
  * and uses the Latitude_Band_Table to determine the minimum northing for that
@@ -249,11 +250,11 @@ long Get_Latitude_Band_Min_Northing(long letter, double* min_northing)
   return error_code;
 } /* Get_Latitude_Band_Min_Northing */
 
-
-long Get_Latitude_Range(long letter, double* north, double* south)
+#ifdef unused
+static long Get_Latitude_Range(long letter, double* north, double* south)
 /*
  * The function Get_Latitude_Range receives a latitude band letter
- * and uses the Latitude_Band_Table to determine the latitude band 
+ * and uses the Latitude_Band_Table to determine the latitude band
  * boundaries for that latitude band letter.
  *
  *   letter   : Latitude band letter                        (input)
@@ -283,12 +284,13 @@ long Get_Latitude_Range(long letter, double* north, double* south)
 
   return error_code;
 } /* Get_Latitude_Range */
+#endif
 
-
-long Get_Latitude_Letter(double latitude, int* letter)
+#ifdef unusued
+static long Get_Latitude_Letter(double latitude, int* letter)
 /*
  * The function Get_Latitude_Letter receives a latitude value
- * and uses the Latitude_Band_Table to determine the latitude band 
+ * and uses the Latitude_Band_Table to determine the latitude band
  * letter for that latitude.
  *
  *   latitude   : Latitude              (input)
@@ -311,16 +313,17 @@ long Get_Latitude_Letter(double latitude, int* letter)
 
   return error_code;
 } /* Get_Latitude_Letter */
+#endif
 
-
-long Check_Zone(char* MGRS, long* zone_exists)
+#ifdef unused
+static long Check_Zone(char* MGRS, long* zone_exists)
 /*
  * The function Check_Zone receives an MGRS coordinate string.
  * If a zone is given, TRUE is returned. Otherwise, FALSE
  * is returned.
  *
  *   MGRS           : MGRS coordinate string        (input)
- *   zone_exists    : TRUE if a zone is given, 
+ *   zone_exists    : TRUE if a zone is given,
  *                    FALSE if a zone is not given  (output)
  */
 { /* Check_Zone */
@@ -329,9 +332,9 @@ long Check_Zone(char* MGRS, long* zone_exists)
   int num_digits = 0;
   long error_code = MGRS_NO_ERROR;
 
-  /* skip any leading blanks */  
+  /* skip any leading blanks */
   while (MGRS[i] == ' ')
-    i++;  
+    i++;
   j = i;
   while (isdigit(MGRS[i]))
     i++;
@@ -346,11 +349,11 @@ long Check_Zone(char* MGRS, long* zone_exists)
 
   return error_code;
 } /* Check_Zone */
+#endif
 
-
-long Round_MGRS (double value)
+static long Round_MGRS (double value)
 /*
- * The function Round_MGRS rounds the input value to the 
+ * The function Round_MGRS rounds the input value to the
  * nearest integer, using the standard engineering rule.
  * The rounded integer value is then returned.
  *
@@ -367,14 +370,14 @@ long Round_MGRS (double value)
 } /* Round_MGRS */
 
 
-long Make_MGRS_String (char* MGRS, 
-                       long Zone, 
-                       int Letters[MGRS_LETTERS], 
-                       double Easting, 
+static long Make_MGRS_String (char* MGRS,
+                       long Zone,
+                       int Letters[MGRS_LETTERS],
+                       double Easting,
                        double Northing,
                        long Precision)
 /*
- * The function Make_MGRS_String constructs an MGRS string 
+ * The function Make_MGRS_String constructs an MGRS string
  * from its component parts.
  *
  *   MGRS           : MGRS coordinate string          (output)
@@ -411,19 +414,19 @@ long Make_MGRS_String (char* MGRS,
   if (Northing >= 99999.5)
     Northing = 99999.0;
   north = (long)(Northing/divisor);
-  i += sprintf (MGRS+i, "%*.*ld", (int) Precision, (int) Precision, north);
+  /*i += */sprintf (MGRS+i, "%*.*ld", (int) Precision, (int) Precision, north);
   return (error_code);
 } /* Make_MGRS_String */
 
 
-long Break_MGRS_String (char* MGRS,
+static long Break_MGRS_String (char* MGRS,
                         long* Zone,
                         long Letters[MGRS_LETTERS],
                         double* Easting,
                         double* Northing,
                         long* Precision)
 /*
- * The function Break_MGRS_String breaks down an MGRS  
+ * The function Break_MGRS_String breaks down an MGRS
  * coordinate string into its component parts.
  *
  *   MGRS           : MGRS coordinate string          (input)
@@ -453,7 +456,7 @@ long Break_MGRS_String (char* MGRS,
       /* get zone */
       strncpy (zone_string, MGRS+j, 2);
       zone_string[2] = 0;
-      sscanf (zone_string, "%ld", Zone);  
+      sscanf (zone_string, "%ld", Zone);
       if ((*Zone < 1) || (*Zone > 60))
         error_code |= MGRS_STRING_ERROR;
     }
@@ -521,15 +524,15 @@ long Break_MGRS_String (char* MGRS,
 } /* Break_MGRS_String */
 
 
-void Get_Grid_Values (long zone, 
-                      long* ltr2_low_value, 
-                      long* ltr2_high_value, 
+static void Get_Grid_Values (long zone,
+                      long* ltr2_low_value,
+                      long* ltr2_high_value,
                       double *false_northing)
 /*
- * The function Get_Grid_Values sets the letter range used for 
- * the 2nd letter in the MGRS coordinate string, based on the set 
+ * The function Get_Grid_Values sets the letter range used for
+ * the 2nd letter in the MGRS coordinate string, based on the set
  * number of the utm zone. It also sets the false northing using a
- * value of A for the second letter of the grid square, based on 
+ * value of A for the second letter of the grid square, based on
  * the grid pattern and set number of the utm zone.
  *
  *    zone            : Zone number             (input)
@@ -546,7 +549,7 @@ void Get_Grid_Values (long zone,
   if (!set_number)
     set_number = 6;
 
-  if (!strcmp(MGRS_Ellipsoid_Code,CLARKE_1866) || !strcmp(MGRS_Ellipsoid_Code, CLARKE_1880) || 
+  if (!strcmp(MGRS_Ellipsoid_Code,CLARKE_1866) || !strcmp(MGRS_Ellipsoid_Code, CLARKE_1880) ||
       !strcmp(MGRS_Ellipsoid_Code,BESSEL_1841) || !strcmp(MGRS_Ellipsoid_Code,BESSEL_1841_NAMIBIA))
     aa_pattern = FALSE;
   else
@@ -585,12 +588,12 @@ void Get_Grid_Values (long zone,
   }
 } /* END OF Get_Grid_Values */
 
-
-long UTM_To_MGRS (long Zone,
+#ifdef unused
+static long UTM_To_MGRS (long Zone,
                   double Latitude,
                   double Easting,
                   double Northing,
-                  long Precision, 
+                  long Precision,
                   char *MGRS)
 /*
  * The function UTM_To_MGRS calculates an MGRS coordinate string
@@ -621,23 +624,23 @@ long UTM_To_MGRS (long Zone,
   Get_Grid_Values(Zone, &ltr2_low_value, &ltr2_high_value, &false_northing);
 
   error_code = Get_Latitude_Letter(Latitude, &letters[0]);
-   
+
   if (!error_code)
   {
     grid_northing = Northing;
     if (grid_northing == 1.e7)
-      grid_northing = grid_northing - 1.0; 
+      grid_northing = grid_northing - 1.0;
 
     while (grid_northing >= TWOMIL)
     {
-      grid_northing = grid_northing - TWOMIL; 
+      grid_northing = grid_northing - TWOMIL;
     }
     grid_northing = grid_northing - false_northing;
 
     if (grid_northing < 0.0)
       grid_northing = grid_northing + TWOMIL;
 
-    letters[2] = (long)(grid_northing / ONEHT); 
+    letters[2] = (long)(grid_northing / ONEHT);
     if (letters[2] > LETTER_H)
       letters[2] = letters[2] + 1;
 
@@ -648,7 +651,7 @@ long UTM_To_MGRS (long Zone,
     if (((letters[0] == LETTER_V) && (Zone == 31)) && (grid_easting == 500000.0))
       grid_easting = grid_easting - 1.0; /* SUBTRACT 1 METER */
 
-    letters[1] = ltr2_low_value + ((long)(grid_easting / ONEHT) -1); 
+    letters[1] = ltr2_low_value + ((long)(grid_easting / ONEHT) -1);
     if ((ltr2_low_value == LETTER_J) && (letters[1] > LETTER_N))
       letters[1] = letters[1] + 1;
 
@@ -656,8 +659,9 @@ long UTM_To_MGRS (long Zone,
   }
   return error_code;
 } /* END UTM_To_MGRS */
+#endif
 
-
+#ifdef unused
 long Set_MGRS_Parameters (double a,
                           double f,
                           char   *Ellipsoid_Code)
@@ -688,11 +692,12 @@ long Set_MGRS_Parameters (double a,
     MGRS_a = a;
     MGRS_f = f;
     MGRS_recpf = inv_f;
-    strcpy (MGRS_Ellipsoid_Code, Ellipsoid_Code);
+    strncpy (MGRS_Ellipsoid_Code, Ellipsoid_Code, sizeof(MGRS_Ellipsoid_Code));
+    MGRS_Ellipsoid_Code[sizeof(MGRS_Ellipsoid_Code) - 1] = '\0';
   }
   return (Error_Code);
 }  /* Set_MGRS_Parameters  */
-
+#endif
 
 void Get_MGRS_Parameters (double *a,
                           double *f,
@@ -712,7 +717,7 @@ void Get_MGRS_Parameters (double *a,
   return;
 } /* Get_MGRS_Parameters */
 
-#ifdef notdef
+#ifndef GDAL_COMPILATION
 long Convert_UTM_To_MGRS (long Zone,
                           char Hemisphere,
                           double Easting,
@@ -721,8 +726,8 @@ long Convert_UTM_To_MGRS (long Zone,
                           char* MGRS)
 /*
  * The function Convert_UTM_To_MGRS converts UTM (zone, easting, and
- * northing) coordinates to an MGRS coordinate string, according to the 
- * current ellipsoid parameters.  If any errors occur, the error code(s) 
+ * northing) coordinates to an MGRS coordinate string, according to the
+ * current ellipsoid parameters.  If any errors occur, the error code(s)
  * are returned by the function, otherwise MGRS_NO_ERROR is returned.
  *
  *    Zone       : UTM zone                         (input)
@@ -754,7 +759,7 @@ long Convert_UTM_To_MGRS (long Zone,
     temp_error = Convert_UTM_To_Geodetic (Zone, Hemisphere, Easting, Northing, &latitude, &longitude);
 
 	  /* Special check for rounding to (truncated) eastern edge of zone 31V */
-	  if ((Zone == 31) && (latitude >= 56.0 * DEG_TO_RAD) && (latitude < 64.0 * DEG_TO_RAD) && 
+	  if ((Zone == 31) && (latitude >= 56.0 * DEG_TO_RAD) && (latitude < 64.0 * DEG_TO_RAD) &&
         (longitude >= 3.0 * DEG_TO_RAD))
 	  { /* Reconvert to UTM zone 32 */
       Set_UTM_Parameters (MGRS_a, MGRS_f, 32);
@@ -774,9 +779,9 @@ long Convert_MGRS_To_UTM (char   *MGRS,
                           double *Northing)
 /*
  * The function Convert_MGRS_To_UTM converts an MGRS coordinate string
- * to UTM projection (zone, hemisphere, easting and northing) coordinates 
- * according to the current ellipsoid parameters.  If any errors occur, 
- * the error code(s) are returned by the function, otherwise UTM_NO_ERROR 
+ * to UTM projection (zone, hemisphere, easting and northing) coordinates
+ * according to the current ellipsoid parameters.  If any errors occur,
+ * the error code(s) are returned by the function, otherwise UTM_NO_ERROR
  * is returned.
  *
  *    MGRS       : MGRS coordinate string           (input)
@@ -788,14 +793,14 @@ long Convert_MGRS_To_UTM (char   *MGRS,
 { /* Convert_MGRS_To_UTM */
   double scaled_min_northing;
   double min_northing;
-  long ltr2_low_value;
-  long ltr2_high_value;
+  long ltr2_low_value = 0;
+  long ltr2_high_value = 0;
   double false_northing;
   double grid_easting;        /* Easting for 100,000 meter grid square      */
   double grid_northing;       /* Northing for 100,000 meter grid square     */
   long letters[MGRS_LETTERS];
   long in_precision;
-#ifdef notdef
+#ifndef GDAL_COMPILATION
   double upper_lat_limit;     /* North latitude limits based on 1st letter  */
   double lower_lat_limit;     /* South latitude limits based on 1st letter  */
   double latitude = 0.0;
@@ -823,7 +828,7 @@ long Convert_MGRS_To_UTM (char   *MGRS,
         Get_Grid_Values(*Zone, &ltr2_low_value, &ltr2_high_value, &false_northing);
 
         /* Check that the second letter of the MGRS string is within
-         * the range of valid second letter values 
+         * the range of valid second letter values
          * Also check that the third letter is valid */
         if ((letters[1] < ltr2_low_value) || (letters[1] > ltr2_high_value) || (letters[2] > LETTER_V))
           error_code |= MGRS_STRING_ERROR;
@@ -839,7 +844,7 @@ long Convert_MGRS_To_UTM (char   *MGRS,
             grid_northing = grid_northing - ONEHT;
 
           if (letters[2] > LETTER_I)
-            grid_northing = grid_northing - ONEHT; 
+            grid_northing = grid_northing - ONEHT;
 
           if (grid_northing >= TWOMIL)
             grid_northing = grid_northing - TWOMIL;
@@ -861,7 +866,7 @@ long Convert_MGRS_To_UTM (char   *MGRS,
 
             *Easting = grid_easting + *Easting;
             *Northing = grid_northing + *Northing;
-#ifdef notdef
+#ifndef GDAL_COMPILATION
             /* check that point is within Zone Letter bounds */
             error_code = Set_UTM_Parameters(MGRS_a,MGRS_f,*Zone);
             if (!error_code)
@@ -894,10 +899,10 @@ long Convert_UPS_To_MGRS (char   Hemisphere,
                           long   Precision,
                           char*  MGRS)
 /*
- *  The function Convert_UPS_To_MGRS converts UPS (hemisphere, easting, 
- *  and northing) coordinates to an MGRS coordinate string according to 
+ *  The function Convert_UPS_To_MGRS converts UPS (hemisphere, easting,
+ *  and northing) coordinates to an MGRS coordinate string according to
  *  the current ellipsoid parameters.  If any errors occur, the error
- *  code(s) are returned by the function, otherwise UPS_NO_ERROR is 
+ *  code(s) are returned by the function, otherwise UPS_NO_ERROR is
  *  returned.
  *
  *    Hemisphere    : Hemisphere either 'N' or 'S'     (input)
@@ -914,7 +919,7 @@ long Convert_UPS_To_MGRS (char   Hemisphere,
   long ltr2_low_value;        /* 2nd letter range - low number                */
   int letters[MGRS_LETTERS];  /* Number location of 3 letters in alphabet     */
   double divisor;
-  int index = 0;
+  int l_index = 0;
   long error_code = MGRS_NO_ERROR;
 
   if ((Hemisphere != 'N') && (Hemisphere != 'S'))
@@ -934,14 +939,14 @@ long Convert_UPS_To_MGRS (char   Hemisphere,
     if (Hemisphere == 'N')
     {
       if (Easting >= TWOMIL)
-        letters[0] = LETTER_Z; 
+        letters[0] = LETTER_Z;
       else
         letters[0] = LETTER_Y;
 
-      index = letters[0] - 22;
-      ltr2_low_value = UPS_Constant_Table[index].ltr2_low_value;
-      false_easting = UPS_Constant_Table[index].false_easting;
-      false_northing = UPS_Constant_Table[index].false_northing;
+      l_index = letters[0] - 22;
+      ltr2_low_value = UPS_Constant_Table[l_index].ltr2_low_value;
+      false_easting = UPS_Constant_Table[l_index].false_easting;
+      false_northing = UPS_Constant_Table[l_index].false_northing;
     }
     else
     {
@@ -957,7 +962,7 @@ long Convert_UPS_To_MGRS (char   Hemisphere,
 
     grid_northing = Northing;
     grid_northing = grid_northing - false_northing;
-    letters[2] = (long)(grid_northing / ONEHT);
+    letters[2] = (int)(grid_northing / ONEHT);
 
     if (letters[2] > LETTER_H)
       letters[2] = letters[2] + 1;
@@ -967,26 +972,26 @@ long Convert_UPS_To_MGRS (char   Hemisphere,
 
     grid_easting = Easting;
     grid_easting = grid_easting - false_easting;
-    letters[1] = ltr2_low_value + ((long)(grid_easting / ONEHT)); 
+    letters[1] = (int)(ltr2_low_value + ((long)(grid_easting / ONEHT)));
 
     if (Easting < TWOMIL)
     {
       if (letters[1] > LETTER_L)
-        letters[1] = letters[1] + 3; 
+        letters[1] = letters[1] + 3;
 
       if (letters[1] > LETTER_U)
-        letters[1] = letters[1] + 2; 
+        letters[1] = letters[1] + 2;
     }
     else
     {
       if (letters[1] > LETTER_C)
-        letters[1] = letters[1] + 2; 
+        letters[1] = letters[1] + 2;
 
       if (letters[1] > LETTER_H)
         letters[1] = letters[1] + 1;
-      
+
       if (letters[1] > LETTER_L)
-        letters[1] = letters[1] + 3; 
+        letters[1] = letters[1] + 3;
     }
 
     Make_MGRS_String (MGRS, 0, letters, Easting, Northing, Precision);
@@ -1001,9 +1006,9 @@ long Convert_MGRS_To_UPS ( char   *MGRS,
                            double *Northing)
 /*
  *  The function Convert_MGRS_To_UPS converts an MGRS coordinate string
- *  to UPS (hemisphere, easting, and northing) coordinates, according 
- *  to the current ellipsoid parameters. If any errors occur, the error 
- *  code(s) are returned by the function, otherwide UPS_NO_ERROR is returned.
+ *  to UPS (hemisphere, easting, and northing) coordinates, according
+ *  to the current ellipsoid parameters. If any errors occur, the error
+ *  code(s) are returned by the function, otherwise UPS_NO_ERROR is returned.
  *
  *    MGRS          : MGRS coordinate string           (input)
  *    Hemisphere    : Hemisphere either 'N' or 'S'     (output)
@@ -1018,10 +1023,10 @@ long Convert_MGRS_To_UPS ( char   *MGRS,
   double false_northing;      /* False northing for 3rd letter              */
   double grid_easting;        /* easting for 100,000 meter grid square      */
   double grid_northing;       /* northing for 100,000 meter grid square     */
-  long zone;
+  long zone = 0;
   long letters[MGRS_LETTERS];
   long in_precision;
-  int index = 0;
+  int l_index = 0;
   long error_code = MGRS_NO_ERROR;
 
   error_code = Break_MGRS_String (MGRS, &zone, letters, Easting, Northing, &in_precision);
@@ -1035,12 +1040,12 @@ long Convert_MGRS_To_UPS ( char   *MGRS,
       {
         *Hemisphere = 'N';
 
-        index = letters[0] - 22;
-        ltr2_low_value = UPS_Constant_Table[index].ltr2_low_value;
-        ltr2_high_value = UPS_Constant_Table[index].ltr2_high_value;
-        ltr3_high_value = UPS_Constant_Table[index].ltr3_high_value;
-        false_easting = UPS_Constant_Table[index].false_easting;
-        false_northing = UPS_Constant_Table[index].false_northing;
+        l_index = (int)(letters[0] - 22);
+        ltr2_low_value = UPS_Constant_Table[l_index].ltr2_low_value;
+        ltr2_high_value = UPS_Constant_Table[l_index].ltr2_high_value;
+        ltr3_high_value = UPS_Constant_Table[l_index].ltr3_high_value;
+        false_easting = UPS_Constant_Table[l_index].false_easting;
+        false_northing = UPS_Constant_Table[l_index].false_northing;
       }
       else
       {
@@ -1054,7 +1059,7 @@ long Convert_MGRS_To_UPS ( char   *MGRS,
       }
 
       /* Check that the second letter of the MGRS string is within
-       * the range of valid second letter values 
+       * the range of valid second letter values
        * Also check that the third letter is valid */
       if ((letters[1] < ltr2_low_value) || (letters[1] > ltr2_high_value) ||
           ((letters[1] == LETTER_D) || (letters[1] == LETTER_E) ||
@@ -1065,14 +1070,14 @@ long Convert_MGRS_To_UPS ( char   *MGRS,
 
       if (!error_code)
       {
-        grid_northing = (double)letters[2] * ONEHT + false_northing; 
+        grid_northing = (double)letters[2] * ONEHT + false_northing;
         if (letters[2] > LETTER_I)
           grid_northing = grid_northing - ONEHT;
 
         if (letters[2] > LETTER_O)
           grid_northing = grid_northing - ONEHT;
 
-        grid_easting = (double)((letters[1]) - ltr2_low_value) * ONEHT + false_easting; 
+        grid_easting = (double)((letters[1]) - ltr2_low_value) * ONEHT + false_easting;
         if (ltr2_low_value != LETTER_A)
         {
           if (letters[1] > LETTER_L)
@@ -1100,6 +1105,3 @@ long Convert_MGRS_To_UPS ( char   *MGRS,
   }
   return (error_code);
 } /* Convert_MGRS_To_UPS */
-
-
-
diff --git a/frmts/nitf/mgrs.h b/frmts/nitf/mgrs.h
index 4ffd1c4..31b82cd 100644
--- a/frmts/nitf/mgrs.h
+++ b/frmts/nitf/mgrs.h
@@ -2,7 +2,7 @@
   #define MGRS_H
 
 /***************************************************************************
- * $Id: mgrs.h 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: mgrs.h 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  MGRS Converter
  * Purpose:  Geotrans declarations for MGRS translation (slightly adapted)
@@ -14,24 +14,24 @@
  *
  * ABSTRACT
  *
- *    This component converts between geodetic coordinates (latitude and 
- *    longitude) and Military Grid Reference System (MGRS) coordinates. 
+ *    This component converts between geodetic coordinates (latitude and
+ *    longitude) and Military Grid Reference System (MGRS) coordinates.
  *
  * ERROR HANDLING
  *
  *    This component checks parameters for valid values.  If an invalid value
- *    is found, the error code is combined with the current error code using 
+ *    is found, the error code is combined with the current error code using
  *    the bitwise or.  This combining allows multiple error codes to be
  *    returned. The possible error codes are:
  *
  *          MGRS_NO_ERROR          : No errors occurred in function
- *          MGRS_LAT_ERROR         : Latitude outside of valid range 
+ *          MGRS_LAT_ERROR         : Latitude outside of valid range
  *                                    (-90 to 90 degrees)
  *          MGRS_LON_ERROR         : Longitude outside of valid range
  *                                    (-180 to 360 degrees)
  *          MGRS_STR_ERROR         : An MGRS string error: string too long,
  *                                    too short, or badly formed
- *          MGRS_PRECISION_ERROR   : The precision must be between 0 and 5 
+ *          MGRS_PRECISION_ERROR   : The precision must be between 0 and 5
  *                                    inclusive.
  *          MGRS_A_ERROR           : Semi-major axis less than or equal to zero
  *          MGRS_INV_F_ERROR       : Inverse flattening outside of valid range
@@ -111,10 +111,11 @@
 extern "C" {
   #endif
 
-
+#ifdef unused
   long Set_MGRS_Parameters(double a,
                            double f,
                            char   *Ellipsoid_Code);
+#endif
 /*
  * The function Set_MGRS_Parameters receives the ellipsoid parameters and sets
  * the corresponding state variables. If any errors occur, the error code(s)
@@ -145,15 +146,15 @@ extern "C" {
                                  char *MGRS);
 /*
  * The function Convert_Geodetic_To_MGRS converts geodetic (latitude and
- * longitude) coordinates to an MGRS coordinate string, according to the 
- * current ellipsoid parameters.  If any errors occur, the error code(s) 
+ * longitude) coordinates to an MGRS coordinate string, according to the
+ * current ellipsoid parameters.  If any errors occur, the error code(s)
  * are returned by the  function, otherwise MGRS_NO_ERROR is returned.
  *
  *    Latitude   : Latitude in radians              (input)
  *    Longitude  : Longitude in radians             (input)
  *    Precision  : Precision level of MGRS string   (input)
  *    MGRS       : MGRS coordinate string           (output)
- *  
+ *
  */
 
 
@@ -162,13 +163,13 @@ extern "C" {
                                  double *Longitude);
 /*
  * This function converts an MGRS coordinate string to Geodetic (latitude
- * and longitude in radians) coordinates.  If any errors occur, the error 
- * code(s) are returned by the  function, otherwise MGRS_NO_ERROR is returned.  
+ * and longitude in radians) coordinates.  If any errors occur, the error
+ * code(s) are returned by the  function, otherwise MGRS_NO_ERROR is returned.
  *
  *    MGRS       : MGRS coordinate string           (input)
  *    Latitude   : Latitude in radians              (output)
  *    Longitude  : Longitude in radians             (output)
- *  
+ *
  */
 
 
@@ -180,8 +181,8 @@ extern "C" {
                             char *MGRS);
 /*
  * The function Convert_UTM_To_MGRS converts UTM (zone, easting, and
- * northing) coordinates to an MGRS coordinate string, according to the 
- * current ellipsoid parameters.  If any errors occur, the error code(s) 
+ * northing) coordinates to an MGRS coordinate string, according to the
+ * current ellipsoid parameters.  If any errors occur, the error code(s)
  * are returned by the  function, otherwise MGRS_NO_ERROR is returned.
  *
  *    Zone       : UTM zone                         (input)
@@ -197,12 +198,12 @@ extern "C" {
                             long   *Zone,
                             char   *Hemisphere,
                             double *Easting,
-                            double *Northing); 
+                            double *Northing);
 /*
  * The function Convert_MGRS_To_UTM converts an MGRS coordinate string
- * to UTM projection (zone, hemisphere, easting and northing) coordinates 
- * according to the current ellipsoid parameters.  If any errors occur, 
- * the error code(s) are returned by the function, otherwise UTM_NO_ERROR 
+ * to UTM projection (zone, hemisphere, easting and northing) coordinates
+ * according to the current ellipsoid parameters.  If any errors occur,
+ * the error code(s) are returned by the function, otherwise UTM_NO_ERROR
  * is returned.
  *
  *    MGRS       : MGRS coordinate string           (input)
@@ -221,10 +222,10 @@ extern "C" {
                              char *MGRS);
 
 /*
- *  The function Convert_UPS_To_MGRS converts UPS (hemisphere, easting, 
- *  and northing) coordinates to an MGRS coordinate string according to 
+ *  The function Convert_UPS_To_MGRS converts UPS (hemisphere, easting,
+ *  and northing) coordinates to an MGRS coordinate string according to
  *  the current ellipsoid parameters.  If any errors occur, the error
- *  code(s) are returned by the function, otherwise UPS_NO_ERROR is 
+ *  code(s) are returned by the function, otherwise UPS_NO_ERROR is
  *  returned.
  *
  *    Hemisphere    : Hemisphere either 'N' or 'S'     (input)
@@ -241,9 +242,9 @@ extern "C" {
                              double *Northing);
 /*
  *  The function Convert_MGRS_To_UPS converts an MGRS coordinate string
- *  to UPS (hemisphere, easting, and northing) coordinates, according 
- *  to the current ellipsoid parameters. If any errors occur, the error 
- *  code(s) are returned by the function, otherwide UPS_NO_ERROR is returned.
+ *  to UPS (hemisphere, easting, and northing) coordinates, according
+ *  to the current ellipsoid parameters. If any errors occur, the error
+ *  code(s) are returned by the function, otherwise UPS_NO_ERROR is returned.
  *
  *    MGRS          : MGRS coordinate string           (input)
  *    Hemisphere    : Hemisphere either 'N' or 'S'     (output)
diff --git a/frmts/nitf/nitf_gcprpc.cpp b/frmts/nitf/nitf_gcprpc.cpp
index 3c39386..d950659 100644
--- a/frmts/nitf/nitf_gcprpc.cpp
+++ b/frmts/nitf/nitf_gcprpc.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: nitf_gcprpc.cpp 22701 2011-07-11 18:37:31Z rouault $
+ * $Id: nitf_gcprpc.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  NITF Read/Write Translator
  * Purpose:  GCP / RPC Georeferencing Model (custom by/for ESRI)
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
- * Copyright (c) 2010, ESRI 
+ * Copyright (c) 2010, ESRI
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -41,17 +41,16 @@ CPL_CVSID("$Id");
 static double Apply( double *C, double P, double L, double H )
 {
     // Polynomial equation for RPC00B.
-
-    double H2 = H * H;
-    double L2 = L * L;
-    double P2 = P * P;
+    const double H2 = H * H;
+    const double L2 = L * L;
+    const double P2 = P * P;
 
     return  C[0]
-        + C[1]*L     + C[2]*P     + C[3]*H     + C[4]*L*P   + C[5]*L*H  
+        + C[1]*L     + C[2]*P     + C[3]*H     + C[4]*L*P   + C[5]*L*H
         + C[6]*P*H   + C[7]*L2    + C[8]*P2    + C[9]*H2    + C[10]*P*L*H
         + C[11]*L*L2 + C[12]*L*P2 + C[13]*L*H2 + C[14]*L2*P + C[15]*P*P2
         + C[16]*P*H2 + C[17]*L2*H + C[18]*P2*H + C[19]*H*H2;
-} 
+}
 
 /************************************************************************/
 /*                          NITFDensifyGCPs()                           */
@@ -65,7 +64,8 @@ void NITFDensifyGCPs( GDAL_GCP **psGCPs, int *pnGCPCount )
     if ( (*pnGCPCount != 4) || (psGCPs == NULL) ) return;
 
     const int  nDensifiedGCPs  = 16;
-    GDAL_GCP  *psDensifiedGCPs = (GDAL_GCP*) CPLMalloc(sizeof(GDAL_GCP)*nDensifiedGCPs);
+    GDAL_GCP  *psDensifiedGCPs = reinterpret_cast<GDAL_GCP *>(
+        CPLMalloc( sizeof( GDAL_GCP ) * nDensifiedGCPs) );
 
     GDALInitGCPs( nDensifiedGCPs, psDensifiedGCPs );
 
@@ -134,7 +134,7 @@ void NITFDensifyGCPs( GDAL_GCP **psGCPs, int *pnGCPCount )
 /*                            RPCTransform()                            */
 /************************************************************************/
 
-static bool RPCTransform( NITFRPC00BInfo *psRPCInfo, 
+static bool RPCTransform( NITFRPC00BInfo *psRPCInfo,
                           double         *pGCPXCoord,
                           double         *pGCPYCoord,
                           int             nGCPCount )
@@ -246,4 +246,4 @@ void NITFUpdateGCPsWithRPC( NITFRPC00BInfo *psRPCInfo,
     pGCPYCoord = NULL;
 }
 
-#endif
+#endif  // ESRI_BUILD
diff --git a/frmts/nitf/nitfaridpcm.cpp b/frmts/nitf/nitfaridpcm.cpp
index eea2f16..aebfd2e 100644
--- a/frmts/nitf/nitfaridpcm.cpp
+++ b/frmts/nitf/nitfaridpcm.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: nitfaridpcm.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: nitfaridpcm.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  NITF Read/Write Library
  * Purpose:  ARIDPCM reading code.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  **********************************************************************
- * Copyright (c) 2007, Frank Warmerdam 
+ * Copyright (c) 2007, Frank Warmerdam
  * Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -28,26 +28,26 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_conv.h"
 #include "gdal.h"
 #include "nitflib.h"
-#include "cpl_conv.h"
 
-CPL_CVSID("$Id: nitfaridpcm.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: nitfaridpcm.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 static const int neighbourhood_size_75[4] = { 23, 47, 74, 173 };
-static const int bits_per_level_by_busycode_75[4/*busy code*/][4/*level*/] = { 
+static const int bits_per_level_by_busycode_75[4/*busy code*/][4/*level*/] = {
     { 8, 5, 0, 0 }, // BC = 00
     { 8, 5, 2, 0 }, // BC = 01
     { 8, 6, 4, 0 }, // BC = 10
     { 8, 7, 4, 2 }};// BC = 11
 
-#define CR075  1
+static const int CR075 = 1;
 
 // Level for each index value.
-static const int level_index_table[64] = 
+static const int level_index_table[64] =
 { 0,
   1, 1, 1,
-  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 };
@@ -77,7 +77,7 @@ static const int ij_index[64] = {
     43, // 5, 1
     53, // 6, 1
     55, // 7, 1
-    
+
      5, // 0, 2
     21, // 1, 2
      7, // 2, 2
@@ -86,7 +86,7 @@ static const int ij_index[64] = {
     45, // 5, 2
     13, // 6, 2
     57, // 7, 2
-    
+
     20, // 0, 3
     22, // 1, 3
     32, // 2, 3
@@ -95,7 +95,7 @@ static const int ij_index[64] = {
     46, // 5, 3
     56, // 6, 3
     58, // 7, 3
-    
+
      2, // 0, 4
     24, // 1, 4
      9, // 2, 4
@@ -104,7 +104,7 @@ static const int ij_index[64] = {
     48, // 5, 4
     15, // 6, 4
     60, // 7, 4
-    
+
     23, // 0, 5
     25, // 1, 5
     35, // 2, 5
@@ -113,7 +113,7 @@ static const int ij_index[64] = {
     49, // 5, 5
     59, // 6, 5
     61, // 7, 5
-    
+
      8, // 0, 6
     27, // 1, 6
     10, // 2, 6
@@ -122,7 +122,7 @@ static const int ij_index[64] = {
     51, // 5, 6
     16, // 6, 6
     63, // 7, 6
-    
+
     26, // 0, 7
     28, // 1, 7
     38, // 2, 7
@@ -132,19 +132,19 @@ static const int ij_index[64] = {
     62, // 6, 7
     64};// 7, 7
 
-static const int delta_075_level_2_bc_0[32] = 
+static const int delta_075_level_2_bc_0[32] =
 {-71, -49, -38, -32, -27, -23, -20, -17, -14, -12, -10, -8, -6, -4, -3, -1,
  1, 2, 4, 6, 8, 12, 14, 16, 19, 22, 26, 31, 37, 46, 72 };
-static const int delta_075_level_2_bc_1[32] = 
+static const int delta_075_level_2_bc_1[32] =
 {-71, -49, -38, -32, -27, -23, -20, -17, -14, -12, -10, -8, -6, -4, -3, -1,
  1, 2, 4, 6, 8, 12, 14, 16, 19, 22, 26, 31, 37, 46, 72 };
-static const int delta_075_level_2_bc_2[64] = 
+static const int delta_075_level_2_bc_2[64] =
 { -109, -82, -68, -59, -52, -46, -41, -37, -33, -30, -27, -25, -22, -20,
   -18, -16, -15, -13, -11, -10, -9, -8, -7, -6, -5,
   -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,
   13,14,15,16,17,18,19,20,21,24,26,28,31,35,38,
   42,47,52,60,69,85,118};
-static const int delta_075_level_2_bc_3[128] = 
+static const int delta_075_level_2_bc_3[128] =
 {-159,-134,-122,-113,-106,-100,-94,-88,-83,-79,-76,-72,-69,-66,-63,-61,
  -58,-56,-54,-52,-50,-48,-47,-45,-43,-42,-40,-39,-37,-36,-35,-33,-32,-31,
  -30,-29,-28,-27,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,
@@ -152,40 +152,38 @@ static const int delta_075_level_2_bc_3[128] =
  12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,
  35,36,37,38,39,40,41,42,43,45,48,52,56,60,64,68,73,79,85,92,100,109,
  118,130,144,159,177,196,217,236};
-static const int *delta_075_level_2[4] = 
-{ delta_075_level_2_bc_0, delta_075_level_2_bc_1, 
+static const int * const delta_075_level_2[4] =
+{ delta_075_level_2_bc_0, delta_075_level_2_bc_1,
   delta_075_level_2_bc_2, delta_075_level_2_bc_3 };
 
-
 static const int delta_075_level_3_bc_1[4] = { -24, -6, 6, 24 };
-static const int delta_075_level_3_bc_2[16] = 
+static const int delta_075_level_3_bc_2[16] =
 {-68,-37,-23,-15, -9, -6, -3, -1, 1, 4, 7,10,16,24,37,70 };
-static const int delta_075_level_3_bc_3[16] = 
+static const int delta_075_level_3_bc_3[16] =
 {-117,-72, -50, -36, -25, -17, -10, -5,-1, 3, 7,14,25,45,82,166};
-static const int *delta_075_level_3[4] = 
-{ NULL, delta_075_level_3_bc_1, 
+static const int *const delta_075_level_3[4] =
+{ NULL, delta_075_level_3_bc_1,
   delta_075_level_3_bc_2, delta_075_level_3_bc_3 };
 
 static const int delta_075_level_4_bc_3[4] = {-47,-8,4,43};
-static const int *delta_075_level_4[4] = { NULL, NULL, NULL, delta_075_level_4_bc_3 };
+static const int *const delta_075_level_4[4] = { NULL, NULL, NULL, delta_075_level_4_bc_3 };
 
-static const int **delta_075_by_level_by_bc[4] = 
+static const int *const * const delta_075_by_level_by_bc[4] =
 { NULL, delta_075_level_2, delta_075_level_3, delta_075_level_4 };
 
 /************************************************************************/
 /*                              get_bits()                              */
 /************************************************************************/
 
-static int 
+static int
 get_bits( unsigned char *buffer, int first_bit, int num_bits )
 
 {
-    int i;
     int total =0;
 
-    for( i = first_bit; i < first_bit+num_bits; i++ )
+    for( int i = first_bit; i < first_bit+num_bits; i++ )
     {
-        total = total * 2;
+        total *= 2;
         if( buffer[i>>3] & (0x80 >> (i&7)) )
             total++;
     }
@@ -211,10 +209,10 @@ get_delta( unsigned char *srcdata,
 
 {
     CPLAssert( comrat == CR075 );
-    int pixel_index = IND(i,j);
-    int level_index = level_index_table[pixel_index];
+    const int pixel_index = IND(i,j);
+    const int level_index = level_index_table[pixel_index];
     const int *bits_per_level = bits_per_level_by_busycode_75[busy_code];
-    int delta_bits = bits_per_level[level_index];
+    const int delta_bits = bits_per_level[level_index];
     int delta_offset = 0;
 
     *pbError = FALSE;
@@ -223,10 +221,10 @@ get_delta( unsigned char *srcdata,
         return 0;
 
     if( level_index == 3 )
-        delta_offset = bits_per_level[0] + bits_per_level[1] * 3 
+        delta_offset = bits_per_level[0] + bits_per_level[1] * 3
             + bits_per_level[2] * 12 + (pixel_index - 16) * bits_per_level[3];
     else if( level_index == 2 )
-        delta_offset = bits_per_level[0] + bits_per_level[1] * 3 
+        delta_offset = bits_per_level[0] + bits_per_level[1] * 3
             + (pixel_index - 4) * bits_per_level[2];
     else if( level_index == 1 )
         delta_offset = bits_per_level[0] + (pixel_index-1)*bits_per_level[1];
@@ -238,8 +236,7 @@ get_delta( unsigned char *srcdata,
         return 0;
     }
 
-    int delta_raw = get_bits( srcdata, block_offset+delta_offset, delta_bits );
-    int delta = delta_raw;
+    const int delta_raw = get_bits( srcdata, block_offset+delta_offset, delta_bits );
 
     /* Should not happen as delta_075_by_level_by_bc[level_index] == NULL if and
        only if level_index == 0, which means that pixel_index == 0, which means
@@ -250,7 +247,7 @@ get_delta( unsigned char *srcdata,
     const int *lookup_table = delta_075_by_level_by_bc[level_index][busy_code];
 
     CPLAssert( lookup_table != NULL );
-    delta = lookup_table[delta_raw];
+    int delta = lookup_table[delta_raw];
 
     return delta;
 }
@@ -261,24 +258,23 @@ get_delta( unsigned char *srcdata,
 /*      Decode one 8x8 block.  The 9x9 L buffer is pre-loaded with      */
 /*      the left and top values from previous blocks.                   */
 /************************************************************************/
-static int 
+static int
 decode_block( unsigned char *srcdata, int nInputBytes,
               int busy_code, int comrat,
-              int block_offset, int block_size, 
+              int block_offset, int block_size,
               int left_side, int top_side, int L[9][9] )
 
 {
-    int i, j;
     int bError;
 
     // Level 2
-    L[0][4] = (L[0][0] + L[0][8])/2 
+    L[0][4] = (L[0][0] + L[0][8])/2
         + get_delta(srcdata,nInputBytes,busy_code,comrat,block_offset,block_size,0,4,&bError);
     if (bError) return FALSE;
-    L[4][0] = (L[0][0] + L[8][0])/2 
+    L[4][0] = (L[0][0] + L[8][0])/2
         + get_delta(srcdata,nInputBytes,busy_code,comrat,block_offset,block_size,4,0,&bError);
     if (bError) return FALSE;
-    L[4][4] = (L[0][0] + L[8][0] + L[0][8] + L[8][8])/4 
+    L[4][4] = (L[0][0] + L[8][0] + L[0][8] + L[8][8])/4
         + get_delta(srcdata,nInputBytes,busy_code,comrat,block_offset,block_size,4,4,&bError);
     if (bError) return FALSE;
 
@@ -288,22 +284,22 @@ decode_block( unsigned char *srcdata, int nInputBytes,
         L[8][4] = L[0][4];
 
     // Level 3
-    for( i = 0; i < 8; i += 4 )
+    for( int i = 0; i < 8; i += 4 )
     {
-        for( j = 0; j < 8; j += 4 )
+        for( int j = 0; j < 8; j += 4 )
         {
             // above
-            L[i+2][j] = (L[i][j]+L[i+4][j])/2 
+            L[i+2][j] = (L[i][j]+L[i+4][j])/2
                 + get_delta(srcdata,nInputBytes,busy_code,comrat,
                             block_offset,block_size,i+2,j,&bError);
             if (bError) return FALSE;
             // left
-            L[i][j+2] = (L[i][j]+L[i][j+4])/2 
+            L[i][j+2] = (L[i][j]+L[i][j+4])/2
                 + get_delta(srcdata,nInputBytes,busy_code,comrat,
                             block_offset,block_size,i,j+2,&bError);
             if (bError) return FALSE;
             // up-left
-            L[i+2][j+2] = (L[i][j]+L[i][j+4]+L[i+4][j]+L[i+4][j+4])/4 
+            L[i+2][j+2] = (L[i][j]+L[i][j+4]+L[i+4][j]+L[i+4][j+4])/4
                 + get_delta(srcdata,nInputBytes,busy_code,comrat,
                             block_offset,block_size,i+2,j+2,&bError);
             if (bError) return FALSE;
@@ -322,22 +318,22 @@ decode_block( unsigned char *srcdata, int nInputBytes,
     }
 
     // Level 4
-    for( i = 0; i < 8; i += 2 )
+    for( int i = 0; i < 8; i += 2 )
     {
-        for( j = 0; j < 8; j += 2 )
+        for( int j = 0; j < 8; j += 2 )
         {
             // above
-            L[i+1][j] = (L[i][j]+L[i+2][j])/2 
+            L[i+1][j] = (L[i][j]+L[i+2][j])/2
                 + get_delta(srcdata,nInputBytes,busy_code,comrat,
                             block_offset,block_size,i+1,j,&bError);
             if (bError) return FALSE;
             // left
-            L[i][j+1] = (L[i][j]+L[i][j+2])/2 
+            L[i][j+1] = (L[i][j]+L[i][j+2])/2
                 + get_delta(srcdata,nInputBytes,busy_code,comrat,
                             block_offset,block_size,i,j+1,&bError);
             if (bError) return FALSE;
             // up-left
-            L[i+1][j+1] = (L[i][j]+L[i][j+2]+L[i+2][j]+L[i+2][j+2])/4 
+            L[i+1][j+1] = (L[i][j]+L[i][j+2]+L[i+2][j]+L[i+2][j+2])/4
                 + get_delta(srcdata,nInputBytes,busy_code,comrat,
                             block_offset,block_size,i+1,j+1,&bError);
             if (bError) return FALSE;
@@ -351,22 +347,21 @@ decode_block( unsigned char *srcdata, int nInputBytes,
 /*                       NITFUncompressARIDPCM()                        */
 /************************************************************************/
 
-int NITFUncompressARIDPCM( NITFImage *psImage, 
+int NITFUncompressARIDPCM( NITFImage *psImage,
                            GByte *pabyInputData,
                            int nInputBytes,
                            GByte *pabyOutputImage )
 
 {
-
 /* -------------------------------------------------------------------- */
 /*      First, verify that we are a COMRAT 0.75 image, which is all     */
 /*      we currently support.                                           */
 /* -------------------------------------------------------------------- */
     if( !EQUAL(psImage->szCOMRAT,"0.75") )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "COMRAT=%s ARIDPCM is not supported.\n"
-                  "Currently only 0.75 is supported.", 
+                  "Currently only 0.75 is supported.",
                   psImage->szCOMRAT );
         return FALSE;
     }
@@ -375,10 +370,10 @@ int NITFUncompressARIDPCM( NITFImage *psImage,
 /*      Setup up the various info we need for each 8x8 neighbourhood    */
 /*      (which we call blocks in this context).                         */
 /* -------------------------------------------------------------------- */
-    int blocks_x = (psImage->nBlockWidth + 7) / 8;
-    int blocks_y = (psImage->nBlockHeight + 7) / 8;
-    int block_count = blocks_x * blocks_y;
-    int  rowlen = blocks_x * 8;
+    const int blocks_x = (psImage->nBlockWidth + 7) / 8;
+    const int blocks_y = (psImage->nBlockHeight + 7) / 8;
+    const int block_count = blocks_x * blocks_y;
+    const int rowlen = blocks_x * 8;
 
     if( psImage->nBlockWidth > 1000 || /* to detect int overflow above */
         psImage->nBlockHeight > 1000 ||
@@ -391,23 +386,34 @@ int NITFUncompressARIDPCM( NITFImage *psImage,
     int block_offset[1000];
     int block_size[1000];
     int busy_code[1000];
-    int busy_code_table_size = blocks_x * blocks_y * 2;
+    const int busy_code_table_size = blocks_x * blocks_y * 2;
     unsigned char L00[1000];
 
+    /* to make clang static analyzer happy */
+    block_offset[0] = 0;
+    block_size[0] = 0;
+    busy_code[0] = 0;
+    L00[0] = 0;
+    CPL_IGNORE_RET_VAL(busy_code[0]);
+    CPL_IGNORE_RET_VAL(block_size[0]);
+    CPL_IGNORE_RET_VAL(busy_code[0]);
+    CPL_IGNORE_RET_VAL(L00[0]);
+
 /* -------------------------------------------------------------------- */
 /*      We allocate a working copy of the full image that may be a      */
 /*      bit larger than the output buffer if the width or height is     */
 /*      not divisible by 8.                                             */
 /* -------------------------------------------------------------------- */
-    GByte *full_image = (GByte *) CPLMalloc(blocks_x * blocks_y * 8 * 8 );
+    GByte *full_image = reinterpret_cast<GByte *>(
+        CPLMalloc(blocks_x * blocks_y * 8 * 8 ) );
 
 /* -------------------------------------------------------------------- */
 /*      Scan through all the neighbourhoods determining the busyness    */
 /*      code, and the offset to each's data as well as the L00 value.   */
 /* -------------------------------------------------------------------- */
-    int i, j, total = busy_code_table_size;
+    int total = busy_code_table_size;
 
-    for( i = 0; i < blocks_x * blocks_y; i++ )
+    for( int i = 0; i < blocks_x * blocks_y; i++ )
     {
         if (nInputBytes * 8 < i * 2 + 2)
         {
@@ -434,11 +440,9 @@ int NITFUncompressARIDPCM( NITFImage *psImage,
 /* -------------------------------------------------------------------- */
 /*      Process all the blocks, forming into a final image.             */
 /* -------------------------------------------------------------------- */
-    int iX, iY;
-
-    for( iY = 0; iY < blocks_y; iY++ )
+    for( int iY = 0; iY < blocks_y; iY++ )
     {
-        for( iX = 0; iX < blocks_x; iX++ )
+        for( int iX = 0; iX < blocks_x; iX++ )
         {
             int iBlock = iX + iY * blocks_x;
             int L[9][9];
@@ -459,7 +463,7 @@ int NITFUncompressARIDPCM( NITFImage *psImage,
                 L[4][8] = L[0][8];
                 L[6][8] = L[0][8];
             }
-            
+
             if( iY > 0 )
             {
                 L[8][0] = full_tl[7 - rowlen];
@@ -479,7 +483,7 @@ int NITFUncompressARIDPCM( NITFImage *psImage,
                 L[8][8] = L[0][0];
             else
                 L[8][8] = full_tl[-1-rowlen];
-            
+
             if (!(decode_block( pabyInputData, nInputBytes, busy_code[iBlock], CR075,
                           block_offset[iBlock], block_size[iBlock],
                           iX == 0, iY == 0, L )))
@@ -488,17 +492,17 @@ int NITFUncompressARIDPCM( NITFImage *psImage,
                 return FALSE;
             }
 
-            // Assign to output matrix. 
-            for( i = 0; i < 8; i++ )
+            // Assign to output matrix.
+            for( int i = 0; i < 8; i++ )
             {
-                for( j = 0; j < 8; j++ )
+                for( int j = 0; j < 8; j++ )
                 {
                     int value = L[i][j];
                     if( value < 0 )
                         value = 0;
                     if( value > 255 )
                         value = 255;
-                    
+
                     full_tl[8-j-1 + (8-i-1) * rowlen] = (unsigned char) value;
                 }
             }
@@ -508,7 +512,7 @@ int NITFUncompressARIDPCM( NITFImage *psImage,
 /* -------------------------------------------------------------------- */
 /*      Copy full image back into target buffer, and free.              */
 /* -------------------------------------------------------------------- */
-    for( iY = 0; iY < psImage->nBlockHeight; iY++ )
+    for( int iY = 0; iY < psImage->nBlockHeight; iY++ )
     {
         memcpy( pabyOutputImage + iY * psImage->nBlockWidth,
                 full_image + iY * rowlen,
diff --git a/frmts/nitf/nitfbilevel.cpp b/frmts/nitf/nitfbilevel.cpp
index 115e764..7cc3bf8 100644
--- a/frmts/nitf/nitfbilevel.cpp
+++ b/frmts/nitf/nitfbilevel.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nitfbilevel.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: nitfbilevel.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  NITF Read/Write Library
  * Purpose:  Module implement BILEVEL (C1) compressed image reading.
@@ -28,11 +28,11 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal.h"
-#include "nitflib.h"
 #include "cpl_conv.h"
-#include "cpl_string.h"
 #include "cpl_multiproc.h"
+#include "cpl_string.h"
+#include "gdal.h"
+#include "nitflib.h"
 
 CPL_C_START
 #include "tiffio.h"
@@ -40,22 +40,22 @@ CPL_C_END
 
 #include "tifvsi.h"
 
-CPL_CVSID("$Id: nitfbilevel.cpp 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: nitfbilevel.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 /************************************************************************/
 /*                       NITFUncompressBILEVEL()                        */
 /************************************************************************/
 
-int NITFUncompressBILEVEL( NITFImage *psImage, 
+int NITFUncompressBILEVEL( NITFImage *psImage,
                            GByte *pabyInputData, int nInputBytes,
                            GByte *pabyOutputImage )
 
 {
-    int nOutputBytes= (psImage->nBlockWidth * psImage->nBlockHeight + 7)/8;
-
 /* -------------------------------------------------------------------- */
 /*      Write memory TIFF with the bilevel data.                        */
 /* -------------------------------------------------------------------- */
+    const int nOutputBytes= (psImage->nBlockWidth * psImage->nBlockHeight + 7)/8;
+
     CPLString osFilename;
 
     osFilename.Printf( "/vsimem/nitf-wrk-%ld.tif", (long) CPLGetPID() );
@@ -66,7 +66,7 @@ int NITFUncompressBILEVEL( NITFImage *psImage,
     TIFF *hTIFF = VSI_TIFFOpen( osFilename, "w+", fpL );
     if (hTIFF == NULL)
     {
-        VSIFCloseL(fpL);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpL));
         return FALSE;
     }
 
@@ -81,7 +81,7 @@ int NITFUncompressBILEVEL( NITFImage *psImage,
     TIFFSetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL, 1 );
     TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK );
     TIFFSetField( hTIFF, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX3 );
-    
+
     if( psImage->szCOMRAT[0] == '2' )
         TIFFSetField( hTIFF, TIFFTAG_GROUP3OPTIONS, GROUP3OPT_2DENCODING );
 
@@ -93,24 +93,23 @@ int NITFUncompressBILEVEL( NITFImage *psImage,
 /* -------------------------------------------------------------------- */
 /*      Now open and read it back.                                      */
 /* -------------------------------------------------------------------- */
-    int bResult = TRUE;
+    bool bResult = true;
 
     hTIFF = VSI_TIFFOpen( osFilename, "r", fpL );
     if (hTIFF == NULL)
     {
-        VSIFCloseL(fpL);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpL));
         return FALSE;
     }
 
-
     if( TIFFReadEncodedStrip( hTIFF, 0, pabyOutputImage, nOutputBytes ) == -1 )
     {
         memset( pabyOutputImage, 0, nOutputBytes );
-        bResult = FALSE;
+        bResult = false;
     }
 
     TIFFClose( hTIFF );
-    VSIFCloseL(fpL);
+    CPL_IGNORE_RET_VAL(VSIFCloseL(fpL));
 
     VSIUnlink( osFilename );
 
diff --git a/frmts/nitf/nitfdataset.cpp b/frmts/nitf/nitfdataset.cpp
index 3e3a0f5..a9b103f 100644
--- a/frmts/nitf/nitfdataset.cpp
+++ b/frmts/nitf/nitfdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nitfdataset.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: nitfdataset.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  NITF Read/Write Translator
  * Purpose:  NITFDataset and driver related implementations.
@@ -31,21 +31,22 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "nitfdataset.h"
-#include "cpl_string.h"
 #include "cpl_csv.h"
+#include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "nitfdataset.h"
 
-CPL_CVSID("$Id: nitfdataset.cpp 28053 2014-12-04 09:31:07Z rouault $");
+CPL_CVSID("$Id: nitfdataset.cpp 33808 2016-03-29 21:15:28Z goatbar $");
 
-static void NITFPatchImageLength( const char *pszFilename,
-                                  GUIntBig nImageOffset, 
+static bool NITFPatchImageLength( const char *pszFilename,
+                                  GUIntBig nImageOffset,
                                   GIntBig nPixelCount, const char *pszIC );
-static int NITFWriteCGMSegments( const char *pszFilename, char **papszList );
-static void NITFWriteTextSegments( const char *pszFilename, char **papszList );
+static bool NITFWriteCGMSegments( const char *pszFilename, char **papszList );
+static bool NITFWriteTextSegments( const char *pszFilename, char **papszList );
 
 #ifdef JPEG_SUPPORTED
-static int NITFWriteJPEGImage( GDALDataset *, VSILFILE *, vsi_l_offset, char **,
-                               GDALProgressFunc pfnProgress, 
+static bool NITFWriteJPEGImage( GDALDataset *, VSILFILE *, vsi_l_offset, char **,
+                               GDALProgressFunc pfnProgress,
                                void * pProgressData );
 #endif
 
@@ -63,24 +64,15 @@ static void SetBandMetadata( NITFImage *psImage, GDALRasterBand *poBand, int nBa
 /*                            NITFDataset()                             */
 /************************************************************************/
 
-NITFDataset::NITFDataset()
-
+NITFDataset::NITFDataset() :
+    psFile(NULL), psImage(NULL), poJ2KDataset(NULL), bJP2Writing(FALSE),
+    poJPEGDataset(NULL), bGotGeoTransform(FALSE), nGCPCount(0),
+    pasGCPList(NULL), pszGCPProjection(NULL), panJPEGBlockOffset(NULL),
+    pabyJPEGBlock(NULL), nQLevel(0), nIMIndex(0), papszTextMDToWrite(NULL),
+    papszCgmMDToWrite(NULL), bInLoadXML(FALSE),
+    bExposeUnderlyingJPEGDatasetOverviews(FALSE)
 {
-    psFile = NULL;
-    psImage = NULL;
-    bGotGeoTransform = FALSE;
     pszProjection = CPLStrdup("");
-    poJ2KDataset = NULL;
-    bJP2Writing = FALSE;
-    poJPEGDataset = NULL;
-
-    panJPEGBlockOffset = NULL;
-    pabyJPEGBlock = NULL;
-    nQLevel = 0;
-
-    nGCPCount = 0;
-    pasGCPList = NULL;
-    pszGCPProjection = NULL;
 
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
@@ -88,14 +80,8 @@ NITFDataset::NITFDataset()
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
-    
-    poDriver = (GDALDriver*) GDALGetDriverByName("NITF");
 
-    papszTextMDToWrite = NULL;
-    papszCgmMDToWrite = NULL;
-    
-    bInLoadXML = FALSE;
-    bExposeUnderlyingJPEGDatasetOverviews = FALSE;
+    poDriver = reinterpret_cast<GDALDriver *>( GDALGetDriverByName("NITF") );
 }
 
 /************************************************************************/
@@ -137,12 +123,10 @@ int NITFDataset::CloseDependentDatasets()
 /* -------------------------------------------------------------------- */
     if( poJ2KDataset != NULL && bJP2Writing )
     {
-        int i;
-
-        for( i = 0; i < nBands && papoBands != NULL; i++ )
+        for( int i = 0; i < nBands && papoBands != NULL; i++ )
         {
             if( papoBands[i]->GetColorInterpretation() != GCI_Undefined )
-                NITFSetColorInterpretation( psImage, i+1, 
+                NITFSetColorInterpretation( psImage, i+1,
                                 papoBands[i]->GetColorInterpretation() );
         }
     }
@@ -177,11 +161,12 @@ int NITFDataset::CloseDependentDatasets()
 /* -------------------------------------------------------------------- */
     if( bJP2Writing )
     {
-        GIntBig nPixelCount = nRasterXSize * ((GIntBig) nRasterYSize) * 
+        GIntBig nPixelCount = nRasterXSize * ((GIntBig) nRasterYSize) *
             nBands;
 
-        NITFPatchImageLength( GetDescription(), nImageStart, nPixelCount, 
-                              "C8" );
+        CPL_IGNORE_RET_VAL(
+            NITFPatchImageLength( GetDescription(), nImageStart, nPixelCount,
+                              "C8" ));
     }
 
     bJP2Writing = FALSE;
@@ -201,8 +186,8 @@ int NITFDataset::CloseDependentDatasets()
 /*      If the dataset was opened by Create(), we may need to write     */
 /*      the CGM and TEXT segments                                       */
 /* -------------------------------------------------------------------- */
-    NITFWriteCGMSegments( GetDescription(), papszCgmMDToWrite );
-    NITFWriteTextSegments( GetDescription(), papszTextMDToWrite );
+    CPL_IGNORE_RET_VAL(NITFWriteCGMSegments( GetDescription(), papszCgmMDToWrite ));
+    CPL_IGNORE_RET_VAL(NITFWriteTextSegments( GetDescription(), papszTextMDToWrite ));
 
     CSLDestroy(papszTextMDToWrite);
     papszTextMDToWrite = NULL;
@@ -233,13 +218,16 @@ int NITFDataset::CloseDependentDatasets()
 void NITFDataset::FlushCache()
 
 {
-    // If the JPEG/JP2K dataset has dirty pam info, then we should consider 
+    // If the JPEG/JP2K dataset has dirty pam info, then we should consider
     // ourselves to as well.
-    if( poJPEGDataset != NULL 
-        && (poJPEGDataset->GetPamFlags() & GPF_DIRTY) )
+    if( poJPEGDataset != NULL
+        && (poJPEGDataset->GetMOFlags() & GMO_PAM_CLASS)
+        && (reinterpret_cast<GDALPamDataset *>( poJPEGDataset )->GetPamFlags() & GPF_DIRTY) )
         MarkPamDirty();
-    if( poJ2KDataset != NULL 
-        && (poJ2KDataset->GetPamFlags() & GPF_DIRTY) )
+
+    if( poJ2KDataset != NULL
+        && (poJ2KDataset->GetMOFlags() & GMO_PAM_CLASS)
+        && (reinterpret_cast<GDALPamDataset *>( poJ2KDataset )->GetPamFlags() & GPF_DIRTY) )
         MarkPamDirty();
 
     if( poJ2KDataset != NULL && bJP2Writing)
@@ -279,13 +267,12 @@ static char **ExtractEsriMD( char **papszMD )
         const char *const pEsriMDSunAzimuth        = "ESRI_MD_SUN_AZIMUTH";
         const char *const pEsriMDSunElevation      = "ESRI_MD_SUN_ELEVATION";
 
-        char         szField[11];
         const char  *pCCImageSegment = CSLFetchNameValue( papszMD, "NITF_IID1" );
         std::string  ccSegment("false");
 
         if( ( pCCImageSegment != NULL ) && ( strlen(pCCImageSegment) <= 10 ) )
         {
-            szField[0] = '\0';
+            char szField[11] = { 0 };
             strncpy( szField, pCCImageSegment, strlen(pCCImageSegment) );
             szField[strlen(pCCImageSegment)] = '\0';
 
@@ -293,7 +280,7 @@ static char **ExtractEsriMD( char **papszMD )
             while( ( strlen(szField) > 0 ) && ( szField[strlen(szField)-1] == ' ' ) )
                 szField[strlen(szField)-1] = '\0';
 
-            if ((strlen(szField) == 2) && (EQUALN(szField, "CC", 2))) ccSegment.assign("true");
+            if ((strlen(szField) == 2) && (STARTS_WITH_CI(szField, "CC"))) ccSegment.assign("true");
         }
 
         const char *pAcquisitionDate   = CSLFetchNameValue( papszMD, "NITF_FDT" );
@@ -307,10 +294,10 @@ static char **ExtractEsriMD( char **papszMD )
         const char *pSunElevation      = CSLFetchNameValue( papszMD, "NITF_CSEXRA_SUN_ELEVATION" );
 
         // Get ESRI_MD_DATA_TYPE.
-        const char *pDataType        = NULL;
         const char *pImgSegFieldICAT = CSLFetchNameValue( papszMD, "NITF_ICAT" );
 
-        if( ( pImgSegFieldICAT != NULL ) && ( EQUALN(pImgSegFieldICAT, "DTEM", 4) ) )
+        const char *pDataType = NULL;
+        if( ( pImgSegFieldICAT != NULL ) && ( STARTS_WITH_CI(pImgSegFieldICAT, "DTEM") ) )
             pDataType = "Elevation";
         else
             pDataType = "Generic";
@@ -319,7 +306,7 @@ static char **ExtractEsriMD( char **papszMD )
             pAngleToNorth = CSLFetchNameValue( papszMD, "NITF_USE00A_ANGLE_TO_NORTH" );
 
         // Percent cloud cover == 999 means that the information is not available.
-        if( (pPercentCloudCover != NULL) &&  (EQUALN(pPercentCloudCover, "999", 3)) )
+        if( (pPercentCloudCover != NULL) &&  (STARTS_WITH_CI(pPercentCloudCover, "999")) )
             pPercentCloudCover = NULL;
 
         pAngleToNorth = CSLFetchNameValue( papszMD, "NITF_USE00A_ANGLE_TO_NORTH" );
@@ -419,7 +406,7 @@ int NITFDataset::Identify( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Is this a dataset selector? If so, it is obviously NITF.        */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszFilename, "NITF_IM:",8) )
+    if( STARTS_WITH_CI(pszFilename, "NITF_IM:") )
         return TRUE;
 
 /* -------------------------------------------------------------------- */
@@ -428,32 +415,34 @@ int NITFDataset::Identify( GDALOpenInfo * poOpenInfo )
 /*      'JPEG_SUBFILE:x,y,z,data' is considered as a (valid) directory  */
 /*      and thus the whole filename is evaluated as tmp/foo.ntf         */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszFilename,"JPEG_SUBFILE:",13) )
+    if( STARTS_WITH_CI(pszFilename, "JPEG_SUBFILE:") )
         return FALSE;
-        
+
 /* -------------------------------------------------------------------- */
 /*	First we check to see if the file has the expected header	*/
-/*	bytes.								*/    
+/*	bytes.								*/
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->nHeaderBytes < 4 )
         return FALSE;
-    
-    if( !EQUALN((char *) poOpenInfo->pabyHeader,"NITF",4) 
-        && !EQUALN((char *) poOpenInfo->pabyHeader,"NSIF",4)
-        && !EQUALN((char *) poOpenInfo->pabyHeader,"NITF",4) )
+
+    if( !STARTS_WITH_CI((char *) poOpenInfo->pabyHeader, "NITF")
+        && !STARTS_WITH_CI((char *) poOpenInfo->pabyHeader, "NSIF")
+        && !STARTS_WITH_CI((char *) poOpenInfo->pabyHeader, "NITF") )
         return FALSE;
 
-    int i;
     /* Check that it's not in fact a NITF A.TOC file, which is handled by the RPFTOC driver */
-    for(i=0;i<(int)poOpenInfo->nHeaderBytes-(int)strlen("A.TOC");i++)
+    for( int i=0;
+         i < static_cast<int>(poOpenInfo->nHeaderBytes)
+             - static_cast<int>( strlen("A.TOC") );
+         i++ )
     {
-        if (EQUALN((const char*)poOpenInfo->pabyHeader + i, "A.TOC", strlen("A.TOC")))
+        if (STARTS_WITH_CI((const char*)poOpenInfo->pabyHeader + i, "A.TOC"))
             return FALSE;
     }
 
     return TRUE;
 }
-        
+
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
@@ -468,20 +457,20 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
                                 int bOpenForCreate)
 
 {
+    if( !Identify( poOpenInfo ) )
+        return NULL;
+
     int nIMIndex = -1;
     const char *pszFilename = poOpenInfo->pszFilename;
 
-    if( !Identify( poOpenInfo ) )
-        return NULL;
-        
 /* -------------------------------------------------------------------- */
 /*      Select a specific subdataset.                                   */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszFilename, "NITF_IM:",8) )
+    if( STARTS_WITH_CI(pszFilename, "NITF_IM:") )
     {
         pszFilename += 8;
         nIMIndex = atoi(pszFilename);
-        
+
         while( *pszFilename != '\0' && *pszFilename != ':' )
             pszFilename++;
 
@@ -492,7 +481,7 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
 /* -------------------------------------------------------------------- */
 /*      Open the file with library.                                     */
 /* -------------------------------------------------------------------- */
-    NITFFile *psFile;
+    NITFFile *psFile = NULL;
 
     if( poOpenInfo->fpL )
     {
@@ -516,12 +505,13 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
 /* -------------------------------------------------------------------- */
 /*      Is there an image to operate on?                                */
 /* -------------------------------------------------------------------- */
-    int iSegment, nThisIM = 0;
+    int nThisIM = 0;
     NITFImage *psImage = NULL;
 
-    for( iSegment = 0; iSegment < psFile->nSegmentCount; iSegment++ )
+    int iSegment = 0;  // Used after for loop.
+    for( ; iSegment < psFile->nSegmentCount; iSegment++ )
     {
-        if( EQUAL(psFile->pasSegmentInfo[iSegment].szSegmentType,"IM") 
+        if( EQUAL(psFile->pasSegmentInfo[iSegment].szSegmentType,"IM")
             && (nThisIM++ == nIMIndex || nIMIndex == -1) )
         {
             psImage = NITFImageAccess( psFile, iSegment );
@@ -539,18 +529,16 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
 /* -------------------------------------------------------------------- */
     if( psImage == NULL )
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
-                  "The file %s appears to be an NITF file, but no image\n"
-                  "blocks were found on it.", 
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "The file %s appears to be an NITF file, but no image "
+                  "blocks were found on it.",
                   poOpenInfo->pszFilename );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    NITFDataset 	*poDS;
-
-    poDS = new NITFDataset();
+    NITFDataset *poDS = new NITFDataset();
 
     poDS->psFile = psFile;
     poDS->psImage = psImage;
@@ -560,15 +548,17 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
 
     if( psImage )
     {
-        if (psImage->nCols <= 0 || psImage->nRows <= 0 || 
-            psImage->nBlockWidth <= 0 || psImage->nBlockHeight <= 0) 
-        { 
-            CPLError( CE_Failure, CPLE_AppDefined,  
-                      "Bad values in NITF image : nCols=%d, nRows=%d, nBlockWidth=%d, nBlockHeight=%d", 
-                      psImage->nCols, psImage->nRows, psImage->nBlockWidth, psImage->nBlockHeight); 
-            delete poDS; 
-            return NULL; 
-        } 
+        if (psImage->nCols <= 0 || psImage->nRows <= 0 ||
+            psImage->nBlockWidth <= 0 || psImage->nBlockHeight <= 0)
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Bad values in NITF image : nCols=%d, nRows=%d, "
+                      "nBlockWidth=%d, nBlockHeight=%d",
+                      psImage->nCols, psImage->nRows,
+                      psImage->nBlockWidth, psImage->nBlockHeight );
+            delete poDS;
+            return NULL;
+        }
 
         poDS->nRasterXSize = psImage->nCols;
         poDS->nRasterYSize = psImage->nRows;
@@ -578,20 +568,19 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
         poDS->nRasterXSize = 1;
         poDS->nRasterYSize = 1;
     }
-        
+
     /* Can be set to NO to avoid opening the underlying JPEG2000/JPEG */
     /* stream. Might speed up operations when just metadata is needed */
-    int bOpenUnderlyingDS = CSLTestBoolean(
-            CPLGetConfigOption("NITF_OPEN_UNDERLYING_DS", "YES"));
+    bool bOpenUnderlyingDS = CPLTestBool(
+            CPLGetConfigOption("NITF_OPEN_UNDERLYING_DS", "YES") );
 
 /* -------------------------------------------------------------------- */
 /*      If the image is JPEG2000 (C8) compressed, we will need to       */
 /*      open the image data as a JPEG2000 dataset.                      */
 /* -------------------------------------------------------------------- */
     int nUsableBands = 0;
-    int iBand;
-    int bSetColorInterpretation = TRUE;
-    int bSetColorTable = FALSE;
+    bool bSetColorInterpretation = true;
+    bool bSetColorTable = false;
 
     if( psImage )
         nUsableBands = psImage->nBands;
@@ -600,91 +589,102 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
     {
         CPLString osDSName;
 
-        osDSName.Printf( "/vsisubfile/" CPL_FRMT_GUIB "_" CPL_FRMT_GUIB ",%s", 
+        osDSName.Printf( "/vsisubfile/" CPL_FRMT_GUIB "_" CPL_FRMT_GUIB ",%s",
                          psFile->pasSegmentInfo[iSegment].nSegmentStart,
                          psFile->pasSegmentInfo[iSegment].nSegmentSize,
                          pszFilename );
-    
+
         if( poWritableJ2KDataset != NULL )
         {
-            poDS->poJ2KDataset = (GDALPamDataset *) poWritableJ2KDataset; 
+            poDS->poJ2KDataset = poWritableJ2KDataset;
             poDS->bJP2Writing = TRUE;
             poWritableJ2KDataset = NULL;
         }
         else
         {
-            /* We explicitly list the allowed drivers to avoid hostile content */
-            /* to be opened by a random driver, and also to make sure that */
-            /* a future new JPEG2000 compatible driver derives from GDALPamDataset */
-            static const char * const apszDrivers[] = { "JP2KAK", "JP2ECW", "JP2MRSID",
-                                                        "JPEG2000", "JP2OPENJPEG", NULL };
-            poDS->poJ2KDataset = (GDALPamDataset *)
-                GDALOpenEx( osDSName, GDAL_OF_RASTER, apszDrivers, NULL, NULL);
+            // We explicitly list the allowed drivers to avoid hostile content
+            // to be opened by a random driver.
+            static const char * const apszDrivers[] = {
+                "JP2KAK", "JP2ECW", "JP2MRSID",
+                "JPEG2000", "JP2OPENJPEG", NULL };
+            poDS->poJ2KDataset = reinterpret_cast<GDALDataset*>(
+                GDALOpenEx( osDSName, GDAL_OF_RASTER, apszDrivers, NULL, NULL) );
 
             if( poDS->poJ2KDataset == NULL )
             {
-                int bFoundJPEG2000Driver = FALSE;
+                bool bFoundJPEG2000Driver = false;
                 for(int iDriver=0;apszDrivers[iDriver]!=NULL;iDriver++)
                 {
                     if (GDALGetDriverByName(apszDrivers[iDriver]) != NULL)
-                        bFoundJPEG2000Driver = TRUE;
+                        bFoundJPEG2000Driver = true;
                 }
 
-                CPLError( CE_Failure, CPLE_AppDefined,
-                        "Unable to open JPEG2000 image within NITF file.\n%s\n%s",
-                         (!bFoundJPEG2000Driver) ?
-                            "No JPEG2000 capable driver (JP2KAK, JP2ECW, JP2MRSID, JP2OPENJPEG, etc...) is available." :
-                            "One or several JPEG2000 capable drivers are available but the datastream could not be opened successfully.",
-                         "You can define the NITF_OPEN_UNDERLYING_DS configuration option to NO, in order to just get the metadata.");
+                CPLError(
+                    CE_Failure, CPLE_AppDefined,
+                    "Unable to open JPEG2000 image within NITF file.\n%s\n%s",
+                    !bFoundJPEG2000Driver ?
+                    "No JPEG2000 capable driver (JP2KAK, JP2ECW, JP2MRSID, "
+                    "JP2OPENJPEG, etc...) is available." :
+                    "One or several JPEG2000 capable drivers are available but "
+                    "the datastream could not be opened successfully.",
+                    "You can define the NITF_OPEN_UNDERLYING_DS configuration "
+                    "option to NO, in order to just get the metadata." );
                 delete poDS;
                 return NULL;
             }
 
-            poDS->poJ2KDataset->SetPamFlags( 
-                poDS->poJ2KDataset->GetPamFlags() | GPF_NOSAVE );
+            if (poDS->poJ2KDataset->GetMOFlags() & GMO_PAM_CLASS)
+            {
+                reinterpret_cast<GDALPamDataset *>(poDS->poJ2KDataset)->SetPamFlags(
+                    reinterpret_cast<GDALPamDataset *>( poDS->poJ2KDataset)->GetPamFlags() | GPF_NOSAVE );
+            }
         }
 
         if( poDS->GetRasterXSize() != poDS->poJ2KDataset->GetRasterXSize()
             || poDS->GetRasterYSize() != poDS->poJ2KDataset->GetRasterYSize())
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "JPEG2000 data stream has not the same dimensions as the NITF file.");
+                      "JPEG2000 data stream has not the same dimensions as "
+                      "the NITF file." );
             delete poDS;
             return NULL;
         }
-        
+
         if ( nUsableBands == 1)
         {
-            const char* pszIREP = CSLFetchNameValue(psImage->papszMetadata, "NITF_IREP");
+            const char* pszIREP =
+                CSLFetchNameValue(psImage->papszMetadata, "NITF_IREP");
             if (pszIREP != NULL && EQUAL(pszIREP, "RGB/LUT"))
             {
                 if (poDS->poJ2KDataset->GetRasterCount() == 3)
                 {
-/* Test case : http://www.gwg.nga.mil/ntb/baseline/software/testfile/Jpeg2000/jp2_09/file9_jp2_2places.ntf */
+// Test case: http://www.gwg.nga.mil/ntb/baseline/software/testfile/Jpeg2000/jp2_09/file9_jp2_2places.ntf
 /* 256-entry palette/LUT in both JP2 Header and image Subheader */
-/* In this case, the JPEG2000 driver will probably do the RGB expension */
+/* In this case, the JPEG2000 driver will probably do the RGB expansion. */
                     nUsableBands = 3;
-                    bSetColorInterpretation = FALSE;
+                    bSetColorInterpretation = false;
                 }
                 else if (poDS->poJ2KDataset->GetRasterCount() == 1 &&
                          psImage->pasBandInfo[0].nSignificantLUTEntries > 0)
                 {
-/* Test case : http://www.gwg.nga.mil/ntb/baseline/software/testfile/Jpeg2000/jp2_09/file9_j2c.ntf */
-/* 256-entry/LUT in Image Subheader, JP2 header completely removed */
-/* The JPEG2000 driver will decode it as a grey band */
-/* So we must set the color table on the wrapper band */
-/* or for file9_jp2_2places.ntf as well if the J2K driver does do RGB expension */
-                    bSetColorTable = TRUE;
+// Test case: http://www.gwg.nga.mil/ntb/baseline/software/testfile/Jpeg2000/jp2_09/file9_j2c.ntf
+
+// 256-entry/LUT in Image Subheader, JP2 header completely removed.
+// The JPEG2000 driver will decode it as a grey band So we must set
+// the color table on the wrapper band or for file9_jp2_2places.ntf as
+// well if the J2K driver does do RGB expansion
+                    bSetColorTable = true;
                 }
             }
         }
 
         if( poDS->poJ2KDataset->GetRasterCount() < nUsableBands )
         {
-            CPLError( CE_Warning, CPLE_AppDefined, 
-                      "JPEG2000 data stream has less useful bands than expected, likely\n"
-                      "because some channels have differing resolutions." );
-            
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "JPEG2000 data stream has less useful bands than "
+                      "expected, likely because some channels have "
+                      "differing resolutions." );
+
             nUsableBands = poDS->poJ2KDataset->GetRasterCount();
         }
     }
@@ -694,7 +694,7 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
 /*      the image data as a JPEG dataset.                               */
 /* -------------------------------------------------------------------- */
     else if( bOpenUnderlyingDS && psImage != NULL
-             && EQUAL(psImage->szIC,"C3") 
+             && EQUAL(psImage->szIC,"C3")
              && psImage->nBlocksPerRow == 1
              && psImage->nBlocksPerColumn == 1 )
     {
@@ -704,16 +704,19 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
 
         CPLString osDSName;
 
-        osDSName.Printf( "JPEG_SUBFILE:Q%d," CPL_FRMT_GUIB "," CPL_FRMT_GUIB ",%s", 
+        osDSName.Printf( "JPEG_SUBFILE:Q%d," CPL_FRMT_GUIB ","
+                         CPL_FRMT_GUIB ",%s",
                          poDS->nQLevel, nJPEGStart,
                          psFile->pasSegmentInfo[iSegment].nSegmentSize
-                         - (nJPEGStart - psFile->pasSegmentInfo[iSegment].nSegmentStart),
+                         - (nJPEGStart -
+                            psFile->pasSegmentInfo[iSegment].nSegmentStart),
                          pszFilename );
 
-        CPLDebug( "GDAL", 
+        CPLDebug( "GDAL",
                   "NITFDataset::Open() as IC=C3 (JPEG compressed)\n");
 
-        poDS->poJPEGDataset = (GDALPamDataset*) GDALOpen(osDSName,GA_ReadOnly);
+        poDS->poJPEGDataset = reinterpret_cast<GDALDataset *>(
+            GDALOpen( osDSName, GA_ReadOnly ) );
         if( poDS->poJPEGDataset == NULL )
         {
             int bFoundJPEGDriver = GDALGetDriverByName("JPEG") != NULL;
@@ -739,15 +742,19 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
             return NULL;
         }
 
-        poDS->poJPEGDataset->SetPamFlags( 
-            poDS->poJPEGDataset->GetPamFlags() | GPF_NOSAVE );
+        if (poDS->poJPEGDataset->GetMOFlags() & GMO_PAM_CLASS)
+        {
+            (reinterpret_cast<GDALPamDataset *>( poDS->poJPEGDataset ) )->SetPamFlags(
+                (reinterpret_cast<GDALPamDataset *>( poDS->poJPEGDataset ) )->GetPamFlags()
+                | GPF_NOSAVE );
+        }
 
         if( poDS->poJPEGDataset->GetRasterCount() < nUsableBands )
         {
-            CPLError( CE_Warning, CPLE_AppDefined, 
+            CPLError( CE_Warning, CPLE_AppDefined,
                       "JPEG data stream has less useful bands than expected, likely\n"
                       "because some channels have differing resolutions." );
-            
+
             nUsableBands = poDS->poJPEGDataset->GetRasterCount();
         }
     }
@@ -756,13 +763,13 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
 
-    GDALDataset*    poBaseDS = NULL;
+    GDALDataset* poBaseDS = NULL;
     if (poDS->poJ2KDataset != NULL)
         poBaseDS = poDS->poJ2KDataset;
     else if (poDS->poJPEGDataset != NULL)
         poBaseDS = poDS->poJPEGDataset;
 
-    for( iBand = 0; iBand < nUsableBands; iBand++ )
+    for( int iBand = 0; iBand < nUsableBands; iBand++ )
     {
         if( poBaseDS != NULL)
         {
@@ -775,7 +782,7 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
 
             NITFWrapperRasterBand* poBand =
                 new NITFWrapperRasterBand(poDS, poBaseBand, iBand+1 );
-                
+
             NITFBandInfo *psBandInfo = psImage->pasBandInfo + iBand;
             if (bSetColorInterpretation)
             {
@@ -802,7 +809,7 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
                 poBand->SetColorTableFromNITFBandInfo();
                 poBand->SetColorInterpretation( GCI_PaletteIndex );
             }
-            
+
             poDS->SetBand( iBand+1, poBand );
         }
         else
@@ -827,13 +834,13 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
 /*      Report problems with odd bit sizes.                             */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update &&
-        psImage != NULL 
-        && (psImage->nBitsPerSample % 8 != 0) 
+        psImage != NULL
+        && (psImage->nBitsPerSample % 8 != 0)
         && poDS->poJPEGDataset == NULL
         && poDS->poJ2KDataset == NULL )
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
-                  "Image with %d bits per sample cannot be opened in update mode.", 
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Image with %d bits per sample cannot be opened in update mode.",
                   psImage->nBitsPerSample );
         delete poDS;
         return NULL;
@@ -852,7 +859,7 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
     {
         CPLFree( poDS->pszProjection );
         poDS->pszProjection = NULL;
-        
+
         oSRSWork.SetWellKnownGeogCS( "WGS84" );
         oSRSWork.exportToWkt( &(poDS->pszProjection) );
     }
@@ -860,23 +867,23 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
     {
         CPLFree( poDS->pszProjection );
         poDS->pszProjection = NULL;
-        
+
         oSRSWork.SetWellKnownGeogCS( "WGS84" );
         oSRSWork.exportToWkt( &(poDS->pszProjection) );
 
         /* convert latitudes from geocentric to geodetic form. */
-        
-        psImage->dfULY = 
-            NITF_WGS84_Geocentric_Latitude_To_Geodetic_Latitude( 
+
+        psImage->dfULY =
+            NITF_WGS84_Geocentric_Latitude_To_Geodetic_Latitude(
                 psImage->dfULY );
-        psImage->dfLLY = 
-            NITF_WGS84_Geocentric_Latitude_To_Geodetic_Latitude( 
+        psImage->dfLLY =
+            NITF_WGS84_Geocentric_Latitude_To_Geodetic_Latitude(
                 psImage->dfLLY );
-        psImage->dfURY = 
-            NITF_WGS84_Geocentric_Latitude_To_Geodetic_Latitude( 
+        psImage->dfURY =
+            NITF_WGS84_Geocentric_Latitude_To_Geodetic_Latitude(
                 psImage->dfURY );
-        psImage->dfLRY = 
-            NITF_WGS84_Geocentric_Latitude_To_Geodetic_Latitude( 
+        psImage->dfLRY =
+            NITF_WGS84_Geocentric_Latitude_To_Geodetic_Latitude(
                 psImage->dfLRY );
     }
     else if( psImage->chICORDS == 'S' || psImage->chICORDS == 'N' )
@@ -898,37 +905,35 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
         oSRSWork.exportToWkt( &(poDS->pszProjection) );
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Try looking for a .nfw file.                                    */
 /* -------------------------------------------------------------------- */
     if( psImage
-        && GDALReadWorldFile2( pszFilename, "nfw", 
+        && GDALReadWorldFile2( pszFilename, "nfw",
                               poDS->adfGeoTransform, poOpenInfo->GetSiblingFiles(), NULL ) )
     {
-        const char *pszHDR;
-        VSILFILE *fpHDR;
-        char **papszLines;
         int isNorth;
         int zone;
-        
+
         poDS->bGotGeoTransform = TRUE;
 
         /* If nfw found, try looking for a header with projection info */
         /* in space imaging style format                               */
-        pszHDR = CPLResetExtension( pszFilename, "hdr" );
-        
-        fpHDR = VSIFOpenL( pszHDR, "rt" );
+        const char *pszHDR = CPLResetExtension( pszFilename, "hdr" );
+
+        VSILFILE *fpHDR = VSIFOpenL( pszHDR, "rt" );
 
         if( fpHDR == NULL && VSIIsCaseSensitiveFS(pszHDR) )
         {
             pszHDR = CPLResetExtension( pszFilename, "HDR" );
             fpHDR = VSIFOpenL( pszHDR, "rt" );
         }
-    
+
+        char **papszLines;
+
         if( fpHDR != NULL )
         {
-            VSIFCloseL( fpHDR );
+            CPL_IGNORE_RET_VAL(VSIFCloseL( fpHDR ));
             papszLines=CSLLoad2(pszHDR, 16, 200, NULL);
             if (CSLCount(papszLines) == 16)
             {
@@ -950,7 +955,8 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
                 }
                 else
                 {
-                    isNorth = 1; /* arbitrarly suppose we are in northern hemisphere */
+                    // Arbitrarily suppose we are in northern hemisphere.
+                    isNorth = 1;
 
                     /* unless we have other information to determine the hemisphere */
                     char** papszUSE00A_MD = NITFReadSTDIDC( psImage );
@@ -973,9 +979,8 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
                     }
                 }
 
-                if( (EQUALN(papszLines[7],
-                            "Selected Projection: Universal Transverse Mercator",50)) &&
-                    (EQUALN(papszLines[8],"Zone: ",6)) &&
+                if( (STARTS_WITH_CI(papszLines[7], "Selected Projection: Universal Transverse Mercator")) &&
+                    (STARTS_WITH_CI(papszLines[8], "Zone: ")) &&
                     (strlen(papszLines[8]) >= 7))
                 {
                     CPLFree( poDS->pszProjection );
@@ -1010,8 +1015,8 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
     if( psImage != NULL && !poDS->bGotGeoTransform &&
         (psImage->chICORDS == 'G' || psImage->chICORDS == 'D') &&
         pszIID1 != NULL && EQUAL(pszIID1, "CADRG") &&
-        pszITITLE != NULL && strlen(pszITITLE) >= 12 
-        && (pszITITLE[strlen(pszITITLE) - 1] == '9' 
+        pszITITLE != NULL && strlen(pszITITLE) >= 12
+        && (pszITITLE[strlen(pszITITLE) - 1] == '9'
             || pszITITLE[strlen(pszITITLE) - 1] == 'J') )
     {
         /* To get a perfect rectangle in Azimuthal Equidistant projection, we must use */
@@ -1073,7 +1078,7 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
         {
             // if we cannot instantiate the transformer, then we
             // will at least attempt to record what we believe the
-            // natural coordinate system of the image is.  This is 
+            // natural coordinate system of the image is.  This is
             // primarily used by ArcGIS (#3337)
 
             CPLErrorReset();
@@ -1091,13 +1096,13 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
 /* -------------------------------------------------------------------- */
 /*      Do we have RPCs?                                                */
 /* -------------------------------------------------------------------- */
-    int            bHasRPC00 = FALSE;
+    bool bHasRPC00 = false;
     NITFRPC00BInfo sRPCInfo;
     memset(&sRPCInfo, 0, sizeof(sRPCInfo)); /* To avoid warnings from not clever compilers */
 
     if( psImage && NITFReadRPC00B( psImage, &sRPCInfo ) && sRPCInfo.SUCCESS )
-        bHasRPC00 = TRUE;
-        
+        bHasRPC00 = true;
+
 /* -------------------------------------------------------------------- */
 /*      Do we have IGEOLO data that can be treated as a                 */
 /*      geotransform?  Our approach should support images in an         */
@@ -1110,10 +1115,11 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
     {
         nGCPCount = 4;
 
-        psGCPs = (GDAL_GCP *) CPLMalloc(sizeof(GDAL_GCP) * nGCPCount);
+        psGCPs = reinterpret_cast<GDAL_GCP *>(
+            CPLMalloc( sizeof(GDAL_GCP) * nGCPCount ) );
         GDALInitGCPs( nGCPCount, psGCPs );
 
-        if( psImage->bIsBoxCenterOfPixel ) 
+        if( psImage->bIsBoxCenterOfPixel )
         {
             psGCPs[0].dfGCPPixel	= 0.5;
             psGCPs[0].dfGCPLine		= 0.5;
@@ -1172,25 +1178,25 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
     {
         /* nothing */
     }
-    else if( poDS->bGotGeoTransform == FALSE 
-             && nGCPCount > 0 
-             && GDALGCPsToGeoTransform( nGCPCount, psGCPs, 
+    else if( poDS->bGotGeoTransform == FALSE
+             && nGCPCount > 0
+             && GDALGCPsToGeoTransform( nGCPCount, psGCPs,
                                         poDS->adfGeoTransform, FALSE ) )
-    {	
+    {
         poDS->bGotGeoTransform = TRUE;
-    } 
+    }
 
 /* -------------------------------------------------------------------- */
 /*      If we have IGEOLO that isn't north up, return it as GCPs.       */
 /* -------------------------------------------------------------------- */
-    else if( (psImage->dfULX != 0 || psImage->dfURX != 0 
+    else if( (psImage->dfULX != 0 || psImage->dfURX != 0
               || psImage->dfLRX != 0 || psImage->dfLLX != 0)
-             && psImage->chICORDS != ' ' && 
+             && psImage->chICORDS != ' ' &&
              ( poDS->bGotGeoTransform == FALSE ) &&
              nGCPCount >= 4 )
     {
-        CPLDebug( "GDAL", 
-                  "NITFDataset::Open() wasn't able to derive a first order\n"
+        CPLDebug( "GDAL",
+                  "NITFDataset::Open() was not able to derive a first order\n"
                   "geotransform.  It will be returned as GCPs.");
 
         poDS->nGCPCount = nGCPCount;
@@ -1214,7 +1220,7 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
         poDS->pszGCPProjection = CPLStrdup( poDS->pszProjection );
     }
 
-    // This cleans up the original copy of the GCPs used to test if 
+    // This cleans up the original copy of the GCPs used to test if
     // this IGEOLO could be used for a geotransform if we did not
     // steal the to use as primary gcps.
     if( nGCPCount > 0 )
@@ -1233,27 +1239,25 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
 /* -------------------------------------------------------------------- */
 /*      Do we have metadata.                                            */
 /* -------------------------------------------------------------------- */
-    char **papszMergedMD;
-    char **papszTRE_MD;
 
     // File and Image level metadata.
-    papszMergedMD = CSLDuplicate( poDS->psFile->papszMetadata );
+    char **papszMergedMD = CSLDuplicate( poDS->psFile->papszMetadata );
 
     if( psImage )
     {
-        papszMergedMD = CSLInsertStrings( papszMergedMD, 
+        papszMergedMD = CSLInsertStrings( papszMergedMD,
                                           CSLCount( papszMergedMD ),
                                           psImage->papszMetadata );
 
         // Comments.
         if( psImage->pszComments != NULL && strlen(psImage->pszComments) != 0 )
-            papszMergedMD = CSLSetNameValue( 
+            papszMergedMD = CSLSetNameValue(
                 papszMergedMD, "NITF_IMAGE_COMMENTS", psImage->pszComments );
-        
-        // Compression code. 
-        papszMergedMD = CSLSetNameValue( papszMergedMD, "NITF_IC", 
+
+        // Compression code.
+        papszMergedMD = CSLSetNameValue( papszMergedMD, "NITF_IC",
                                          psImage->szIC );
-        
+
         // IMODE
         char szIMODE[2];
         szIMODE[0] = psImage->chIMODE;
@@ -1263,51 +1267,51 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
         // ILOC/Attachment info
         if( psImage->nIDLVL != 0 )
         {
-            NITFSegmentInfo *psSegInfo 
+            NITFSegmentInfo *psSegInfo
                 = psFile->pasSegmentInfo + psImage->iSegment;
 
-            papszMergedMD = 
-                CSLSetNameValue( papszMergedMD, "NITF_IDLVL", 
+            papszMergedMD =
+                CSLSetNameValue( papszMergedMD, "NITF_IDLVL",
                                  CPLString().Printf("%d",psImage->nIDLVL) );
-            papszMergedMD = 
-                CSLSetNameValue( papszMergedMD, "NITF_IALVL", 
+            papszMergedMD =
+                CSLSetNameValue( papszMergedMD, "NITF_IALVL",
                                  CPLString().Printf("%d",psImage->nIALVL) );
-            papszMergedMD = 
-                CSLSetNameValue( papszMergedMD, "NITF_ILOC_ROW", 
+            papszMergedMD =
+                CSLSetNameValue( papszMergedMD, "NITF_ILOC_ROW",
                                  CPLString().Printf("%d",psImage->nILOCRow) );
-            papszMergedMD = 
-                CSLSetNameValue( papszMergedMD, "NITF_ILOC_COLUMN", 
+            papszMergedMD =
+                CSLSetNameValue( papszMergedMD, "NITF_ILOC_COLUMN",
                                  CPLString().Printf("%d",psImage->nILOCColumn));
-            papszMergedMD = 
-                CSLSetNameValue( papszMergedMD, "NITF_CCS_ROW", 
+            papszMergedMD =
+                CSLSetNameValue( papszMergedMD, "NITF_CCS_ROW",
                                  CPLString().Printf("%d",psSegInfo->nCCS_R) );
-            papszMergedMD = 
-                CSLSetNameValue( papszMergedMD, "NITF_CCS_COLUMN", 
+            papszMergedMD =
+                CSLSetNameValue( papszMergedMD, "NITF_CCS_COLUMN",
                                  CPLString().Printf("%d", psSegInfo->nCCS_C));
-            papszMergedMD = 
-                CSLSetNameValue( papszMergedMD, "NITF_IMAG", 
+            papszMergedMD =
+                CSLSetNameValue( papszMergedMD, "NITF_IMAG",
                                  psImage->szIMAG );
         }
 
         papszMergedMD = NITFGenericMetadataRead(papszMergedMD, psFile, psImage, NULL);
 
-        // BLOCKA 
-        papszTRE_MD = NITFReadBLOCKA( psImage );
+        // BLOCKA
+        char **papszTRE_MD = NITFReadBLOCKA( psImage );
         if( papszTRE_MD != NULL )
         {
-            papszMergedMD = CSLInsertStrings( papszMergedMD, 
+            papszMergedMD = CSLInsertStrings( papszMergedMD,
                                               CSLCount( papszTRE_MD ),
                                               papszTRE_MD );
             CSLDestroy( papszTRE_MD );
         }
     }
-        
+
 #ifdef ESRI_BUILD
     // Extract ESRI generic metadata.
     char **papszESRI_MD = ExtractEsriMD( papszMergedMD );
     if( papszESRI_MD != NULL )
     {
-        papszMergedMD = CSLInsertStrings( papszMergedMD, 
+        papszMergedMD = CSLInsertStrings( papszMergedMD,
                                           CSLCount( papszESRI_MD ),
                                           papszESRI_MD );
         CSLDestroy( papszESRI_MD );
@@ -1323,99 +1327,97 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
     if( psImage == NULL )
         /* do nothing */;
     else if( psImage->szIC[1] == '1' )
-        poDS->SetMetadataItem( "COMPRESSION", "BILEVEL", 
+        poDS->SetMetadataItem( "COMPRESSION", "BILEVEL",
                                "IMAGE_STRUCTURE" );
     else if( psImage->szIC[1] == '2' )
-        poDS->SetMetadataItem( "COMPRESSION", "ARIDPCM", 
+        poDS->SetMetadataItem( "COMPRESSION", "ARIDPCM",
                                "IMAGE_STRUCTURE" );
     else if( psImage->szIC[1] == '3' )
-        poDS->SetMetadataItem( "COMPRESSION", "JPEG", 
+        poDS->SetMetadataItem( "COMPRESSION", "JPEG",
                                "IMAGE_STRUCTURE" );
     else if( psImage->szIC[1] == '4' )
-        poDS->SetMetadataItem( "COMPRESSION", "VECTOR QUANTIZATION", 
+        poDS->SetMetadataItem( "COMPRESSION", "VECTOR QUANTIZATION",
                                "IMAGE_STRUCTURE" );
     else if( psImage->szIC[1] == '5' )
-        poDS->SetMetadataItem( "COMPRESSION", "LOSSLESS JPEG", 
+        poDS->SetMetadataItem( "COMPRESSION", "LOSSLESS JPEG",
                                "IMAGE_STRUCTURE" );
     else if( psImage->szIC[1] == '8' )
-        poDS->SetMetadataItem( "COMPRESSION", "JPEG2000", 
+        poDS->SetMetadataItem( "COMPRESSION", "JPEG2000",
                                "IMAGE_STRUCTURE" );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Do we have RPC info.                                            */
 /* -------------------------------------------------------------------- */
     if( psImage && bHasRPC00 )
     {
         char szValue[1280];
-        int  i;
-
-        CPLsprintf( szValue, "%.16g", sRPCInfo.LINE_OFF );
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g", sRPCInfo.LINE_OFF );
         poDS->SetMetadataItem( "LINE_OFF", szValue, "RPC" );
 
-        CPLsprintf( szValue, "%.16g", sRPCInfo.LINE_SCALE );
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g", sRPCInfo.LINE_SCALE );
         poDS->SetMetadataItem( "LINE_SCALE", szValue, "RPC" );
 
-        CPLsprintf( szValue, "%.16g", sRPCInfo.SAMP_OFF );
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g", sRPCInfo.SAMP_OFF );
         poDS->SetMetadataItem( "SAMP_OFF", szValue, "RPC" );
 
-        CPLsprintf( szValue, "%.16g", sRPCInfo.SAMP_SCALE );
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g", sRPCInfo.SAMP_SCALE );
         poDS->SetMetadataItem( "SAMP_SCALE", szValue, "RPC" );
 
-        CPLsprintf( szValue, "%.16g", sRPCInfo.LONG_OFF );
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g", sRPCInfo.LONG_OFF );
         poDS->SetMetadataItem( "LONG_OFF", szValue, "RPC" );
 
-        CPLsprintf( szValue, "%.16g", sRPCInfo.LONG_SCALE );
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g", sRPCInfo.LONG_SCALE );
         poDS->SetMetadataItem( "LONG_SCALE", szValue, "RPC" );
 
-        CPLsprintf( szValue, "%.16g", sRPCInfo.LAT_OFF );
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g", sRPCInfo.LAT_OFF );
         poDS->SetMetadataItem( "LAT_OFF", szValue, "RPC" );
 
-        CPLsprintf( szValue, "%.16g", sRPCInfo.LAT_SCALE );
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g", sRPCInfo.LAT_SCALE );
         poDS->SetMetadataItem( "LAT_SCALE", szValue, "RPC" );
 
-        CPLsprintf( szValue, "%.16g", sRPCInfo.HEIGHT_OFF );
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g", sRPCInfo.HEIGHT_OFF );
         poDS->SetMetadataItem( "HEIGHT_OFF", szValue, "RPC" );
 
-        CPLsprintf( szValue, "%.16g", sRPCInfo.HEIGHT_SCALE );
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g", sRPCInfo.HEIGHT_SCALE );
         poDS->SetMetadataItem( "HEIGHT_SCALE", szValue, "RPC" );
 
-        szValue[0] = '\0'; 
-        for( i = 0; i < 20; i++ )
-            CPLsprintf( szValue+strlen(szValue), "%.16g ",  
+        szValue[0] = '\0';
+        for( int i = 0; i < 20; i++ )
+            CPLsnprintf( szValue+strlen(szValue), sizeof(szValue) - strlen(szValue), "%.16g ",
                      sRPCInfo.LINE_NUM_COEFF[i] );
         poDS->SetMetadataItem( "LINE_NUM_COEFF", szValue, "RPC" );
 
-        szValue[0] = '\0'; 
-        for( i = 0; i < 20; i++ )
-            CPLsprintf( szValue+strlen(szValue), "%.16g ",  
+        szValue[0] = '\0';
+        for( int i = 0; i < 20; i++ )
+            CPLsnprintf( szValue+strlen(szValue), sizeof(szValue) - strlen(szValue), "%.16g ",
                      sRPCInfo.LINE_DEN_COEFF[i] );
         poDS->SetMetadataItem( "LINE_DEN_COEFF", szValue, "RPC" );
-        
-        szValue[0] = '\0'; 
-        for( i = 0; i < 20; i++ )
-            CPLsprintf( szValue+strlen(szValue), "%.16g ",  
+
+        szValue[0] = '\0';
+        for( int i = 0; i < 20; i++ )
+            CPLsnprintf( szValue+strlen(szValue), sizeof(szValue) - strlen(szValue), "%.16g ",
                      sRPCInfo.SAMP_NUM_COEFF[i] );
         poDS->SetMetadataItem( "SAMP_NUM_COEFF", szValue, "RPC" );
-        
-        szValue[0] = '\0'; 
-        for( i = 0; i < 20; i++ )
-            CPLsprintf( szValue+strlen(szValue), "%.16g ",  
+
+        szValue[0] = '\0';
+        for( int i = 0; i < 20; i++ )
+            CPLsnprintf( szValue+strlen(szValue), sizeof(szValue) - strlen(szValue), "%.16g ",
                      sRPCInfo.SAMP_DEN_COEFF[i] );
         poDS->SetMetadataItem( "SAMP_DEN_COEFF", szValue, "RPC" );
 
-        CPLsprintf( szValue, "%.16g", 
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g",
                  sRPCInfo.LONG_OFF - ( sRPCInfo.LONG_SCALE / 2.0 ) );
         poDS->SetMetadataItem( "MIN_LONG", szValue, "RPC" );
 
-        CPLsprintf( szValue, "%.16g",
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g",
                  sRPCInfo.LONG_OFF + ( sRPCInfo.LONG_SCALE / 2.0 ) );
         poDS->SetMetadataItem( "MAX_LONG", szValue, "RPC" );
 
-        CPLsprintf( szValue, "%.16g", 
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g",
                  sRPCInfo.LAT_OFF - ( sRPCInfo.LAT_SCALE / 2.0 ) );
         poDS->SetMetadataItem( "MIN_LAT", szValue, "RPC" );
 
-        CPLsprintf( szValue, "%.16g", 
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g",
                  sRPCInfo.LAT_OFF + ( sRPCInfo.LAT_SCALE / 2.0 ) );
         poDS->SetMetadataItem( "MAX_LAT", szValue, "RPC" );
     }
@@ -1430,71 +1432,73 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
     {
         char szValue[1280];
 
-        CPLsprintf( szValue, "%.16g", sChipInfo.SCALE_FACTOR );
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g", sChipInfo.SCALE_FACTOR );
         poDS->SetMetadataItem( "ICHIP_SCALE_FACTOR", szValue );
 
-        sprintf( szValue, "%d", sChipInfo.ANAMORPH_CORR );
+        // TODO: Why do these two not use CPLsnprintf?
+        snprintf( szValue, sizeof(szValue), "%d", sChipInfo.ANAMORPH_CORR );
         poDS->SetMetadataItem( "ICHIP_ANAMORPH_CORR", szValue );
 
-        sprintf( szValue, "%d", sChipInfo.SCANBLK_NUM );
+        snprintf( szValue, sizeof(szValue), "%d", sChipInfo.SCANBLK_NUM );
         poDS->SetMetadataItem( "ICHIP_SCANBLK_NUM", szValue );
 
-        CPLsprintf( szValue, "%.16g", sChipInfo.OP_ROW_11 );
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g", sChipInfo.OP_ROW_11 );
         poDS->SetMetadataItem( "ICHIP_OP_ROW_11", szValue );
 
-        CPLsprintf( szValue, "%.16g", sChipInfo.OP_COL_11 );
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g", sChipInfo.OP_COL_11 );
         poDS->SetMetadataItem( "ICHIP_OP_COL_11", szValue );
 
-        CPLsprintf( szValue, "%.16g", sChipInfo.OP_ROW_12 );
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g", sChipInfo.OP_ROW_12 );
         poDS->SetMetadataItem( "ICHIP_OP_ROW_12", szValue );
 
-        CPLsprintf( szValue, "%.16g", sChipInfo.OP_COL_12 );
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g", sChipInfo.OP_COL_12 );
         poDS->SetMetadataItem( "ICHIP_OP_COL_12", szValue );
 
-        CPLsprintf( szValue, "%.16g", sChipInfo.OP_ROW_21 );
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g", sChipInfo.OP_ROW_21 );
         poDS->SetMetadataItem( "ICHIP_OP_ROW_21", szValue );
 
-        CPLsprintf( szValue, "%.16g", sChipInfo.OP_COL_21 );
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g", sChipInfo.OP_COL_21 );
         poDS->SetMetadataItem( "ICHIP_OP_COL_21", szValue );
 
-        CPLsprintf( szValue, "%.16g", sChipInfo.OP_ROW_22 );
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g", sChipInfo.OP_ROW_22 );
         poDS->SetMetadataItem( "ICHIP_OP_ROW_22", szValue );
 
-        CPLsprintf( szValue, "%.16g", sChipInfo.OP_COL_22 );
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g", sChipInfo.OP_COL_22 );
         poDS->SetMetadataItem( "ICHIP_OP_COL_22", szValue );
 
-        CPLsprintf( szValue, "%.16g", sChipInfo.FI_ROW_11 );
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g", sChipInfo.FI_ROW_11 );
         poDS->SetMetadataItem( "ICHIP_FI_ROW_11", szValue );
 
-        CPLsprintf( szValue, "%.16g", sChipInfo.FI_COL_11 );
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g", sChipInfo.FI_COL_11 );
         poDS->SetMetadataItem( "ICHIP_FI_COL_11", szValue );
 
-        CPLsprintf( szValue, "%.16g", sChipInfo.FI_ROW_12 );
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g", sChipInfo.FI_ROW_12 );
         poDS->SetMetadataItem( "ICHIP_FI_ROW_12", szValue );
 
-        CPLsprintf( szValue, "%.16g", sChipInfo.FI_COL_12 );
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g", sChipInfo.FI_COL_12 );
         poDS->SetMetadataItem( "ICHIP_FI_COL_12", szValue );
 
-        CPLsprintf( szValue, "%.16g", sChipInfo.FI_ROW_21 );
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g", sChipInfo.FI_ROW_21 );
         poDS->SetMetadataItem( "ICHIP_FI_ROW_21", szValue );
 
-        CPLsprintf( szValue, "%.16g", sChipInfo.FI_COL_21 );
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g", sChipInfo.FI_COL_21 );
         poDS->SetMetadataItem( "ICHIP_FI_COL_21", szValue );
 
-        CPLsprintf( szValue, "%.16g", sChipInfo.FI_ROW_22 );
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g", sChipInfo.FI_ROW_22 );
         poDS->SetMetadataItem( "ICHIP_FI_ROW_22", szValue );
 
-        CPLsprintf( szValue, "%.16g", sChipInfo.FI_COL_22 );
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g", sChipInfo.FI_COL_22 );
         poDS->SetMetadataItem( "ICHIP_FI_COL_22", szValue );
 
-        sprintf( szValue, "%d", sChipInfo.FI_ROW );
+        // Why not CPLsnprintf?
+        snprintf( szValue, sizeof(szValue), "%d", sChipInfo.FI_ROW );
         poDS->SetMetadataItem( "ICHIP_FI_ROW", szValue );
 
-        sprintf( szValue, "%d", sChipInfo.FI_COL );
+        snprintf( szValue, sizeof(szValue), "%d", sChipInfo.FI_COL );
         poDS->SetMetadataItem( "ICHIP_FI_COL", szValue );
 
     }
-    
+
     const NITFSeries* series = NITFGetSeriesInfo(pszFilename);
     if (series)
     {
@@ -1524,12 +1528,12 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
 
                 oName.Printf( "SUBDATASET_%d_NAME", nIMCounter+1 );
                 oValue.Printf( "NITF_IM:%d:%s", nIMCounter, pszFilename );
-                papszSubdatasets = CSLSetNameValue( papszSubdatasets, 
+                papszSubdatasets = CSLSetNameValue( papszSubdatasets,
                                                     oName, oValue );
 
                 oName.Printf( "SUBDATASET_%d_DESC", nIMCounter+1 );
                 oValue.Printf( "Image %d of %s", nIMCounter+1, pszFilename );
-                papszSubdatasets = CSLSetNameValue( papszSubdatasets, 
+                papszSubdatasets = CSLSetNameValue( papszSubdatasets,
                                                     oName, oValue );
 
                 nIMCounter++;
@@ -1538,9 +1542,9 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
 
         nSubDSCount = CSLCount(papszSubdatasets) / 2;
         if( nSubDSCount > 1 )
-            poDS->GDALMajorObject::SetMetadata( papszSubdatasets, 
+            poDS->GDALMajorObject::SetMetadata( papszSubdatasets,
                                                 "SUBDATASETS" );
-        
+
         CSLDestroy( papszSubdatasets );
     }
 
@@ -1548,7 +1552,7 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
     poDS->SetDescription( poOpenInfo->pszFilename );
-    
+
     if( nSubDSCount > 1 || nIMIndex != -1 )
     {
         if( nIMIndex == -1 )
@@ -1566,14 +1570,14 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
 /*      Do we have a special overview file?  If not, do we have         */
 /*      RSets that should be treated as an overview file?               */
 /* -------------------------------------------------------------------- */
-    const char *pszOverviewFile = 
+    const char *pszOverviewFile =
         poDS->GetMetadataItem( "OVERVIEW_FILE", "OVERVIEWS" );
 
     if( pszOverviewFile == NULL )
     {
         if( poDS->CheckForRSets(pszFilename, poOpenInfo->GetSiblingFiles()) )
             pszOverviewFile = poDS->osRSetVRT;
-    }        
+    }
 
 /* -------------------------------------------------------------------- */
 /*      If we have jpeg or jpeg2000 bands we may need to set the        */
@@ -1585,7 +1589,7 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
 
     if( poSubDS && pszOverviewFile != NULL )
     {
-        poSubDS->SetMetadataItem( "OVERVIEW_FILE", 
+        poSubDS->SetMetadataItem( "OVERVIEW_FILE",
                                   pszOverviewFile,
                                   "OVERVIEWS" );
     }
@@ -1594,12 +1598,12 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
 /*      If we have jpeg, or jpeg2000 bands we may need to clear         */
 /*      their PAM dirty flag too.                                       */
 /* -------------------------------------------------------------------- */
-    if( poDS->poJ2KDataset != NULL )
-        poDS->poJ2KDataset->SetPamFlags( 
-            poDS->poJ2KDataset->GetPamFlags() & ~GPF_DIRTY );
-    if( poDS->poJPEGDataset != NULL )
-        poDS->poJPEGDataset->SetPamFlags( 
-            poDS->poJPEGDataset->GetPamFlags() & ~GPF_DIRTY );
+    if( poDS->poJ2KDataset != NULL && (poDS->poJ2KDataset->GetMOFlags() & GMO_PAM_CLASS) )
+        ( reinterpret_cast<GDALPamDataset *>( poDS->poJ2KDataset ) )->SetPamFlags(
+            ( reinterpret_cast<GDALPamDataset *>( poDS->poJ2KDataset ) )->GetPamFlags() & ~GPF_DIRTY );
+    if( poDS->poJPEGDataset != NULL && (poDS->poJPEGDataset->GetMOFlags() & GMO_PAM_CLASS) )
+      ( reinterpret_cast<GDALPamDataset*>( poDS->poJPEGDataset ) )->SetPamFlags(
+            ( reinterpret_cast<GDALPamDataset *> (poDS->poJPEGDataset ) )->GetPamFlags() & ~GPF_DIRTY );
 
 /* -------------------------------------------------------------------- */
 /*      Check for overviews.                                            */
@@ -1613,8 +1617,8 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
     /* overviews (in case of monoblock C3) */
     if( poDS->GetRasterCount() > 0 && poDS->GetRasterBand(1) != NULL )
         poDS->bExposeUnderlyingJPEGDatasetOverviews =
-            ((GDALPamRasterBand*)poDS->GetRasterBand(1))->
-                            GDALPamRasterBand::GetOverviewCount() == 0;
+            ( reinterpret_cast<GDALPamRasterBand *>( poDS->GetRasterBand(1) ) )->
+            GDALPamRasterBand::GetOverviewCount() == 0;
 
     return( poDS );
 }
@@ -1632,7 +1636,7 @@ static OGRErr LoadDODDatum( OGRSpatialReference *poSRS,
 /* -------------------------------------------------------------------- */
 /*      The most common case...                                         */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszDatumName,"WGE ",4) )
+    if( STARTS_WITH_CI(pszDatumName, "WGE ") )
     {
         poSRS->SetWellKnownGeogCS( "WGS84" );
         return OGRERR_NONE;
@@ -1649,14 +1653,14 @@ static OGRErr LoadDODDatum( OGRSpatialReference *poSRS,
     szExpanded[3] = '\0';
     if( pszDatumName[3] != ' ' )
     {
-        int nLen;
+        size_t nLen;
         strcat( szExpanded, "-" );
         nLen = strlen(szExpanded);
         szExpanded[nLen] = pszDatumName[3];
         szExpanded[nLen + 1] = '\0';
     }
 
-    CPLString osDName = CSVGetField( pszGTDatum, "CODE", szExpanded, 
+    CPLString osDName = CSVGetField( pszGTDatum, "CODE", szExpanded,
                                      CC_ApproxString, "NAME" );
     if( strlen(osDName) == 0 )
     {
@@ -1665,21 +1669,21 @@ static OGRErr LoadDODDatum( OGRSpatialReference *poSRS,
                   pszDatumName, szExpanded );
         return OGRERR_FAILURE;
     }
-        
-    CPLString osEllipseCode = CSVGetField( pszGTDatum, "CODE", szExpanded, 
+
+    CPLString osEllipseCode = CSVGetField( pszGTDatum, "CODE", szExpanded,
                                            CC_ApproxString, "ELLIPSOID" );
-    double dfDeltaX = CPLAtof(CSVGetField( pszGTDatum, "CODE", szExpanded, 
+    double dfDeltaX = CPLAtof(CSVGetField( pszGTDatum, "CODE", szExpanded,
                                            CC_ApproxString, "DELTAX" ) );
-    double dfDeltaY = CPLAtof(CSVGetField( pszGTDatum, "CODE", szExpanded, 
+    double dfDeltaY = CPLAtof(CSVGetField( pszGTDatum, "CODE", szExpanded,
                                            CC_ApproxString, "DELTAY" ) );
-    double dfDeltaZ = CPLAtof(CSVGetField( pszGTDatum, "CODE", szExpanded, 
+    double dfDeltaZ = CPLAtof(CSVGetField( pszGTDatum, "CODE", szExpanded,
                                            CC_ApproxString, "DELTAZ" ) );
 
 /* -------------------------------------------------------------------- */
 /*      Lookup the ellipse code.                                        */
 /* -------------------------------------------------------------------- */
     const char *pszGTEllipse = CSVFilename( "gt_ellips.csv" );
-    
+
     CPLString osEName = CSVGetField( pszGTEllipse, "CODE", osEllipseCode,
                                      CC_ApproxString, "NAME" );
     if( strlen(osEName) == 0 )
@@ -1688,8 +1692,8 @@ static OGRErr LoadDODDatum( OGRSpatialReference *poSRS,
                   "Failed to find datum %s in gt_ellips.csv.",
                   osEllipseCode.c_str() );
         return OGRERR_FAILURE;
-    }    
-    
+    }
+
     double dfA = CPLAtof(CSVGetField( pszGTEllipse, "CODE", osEllipseCode,
                                       CC_ApproxString, "A" ));
     double dfInvF = CPLAtof(CSVGetField( pszGTEllipse, "CODE", osEllipseCode,
@@ -1722,14 +1726,11 @@ void NITFDataset::CheckGeoSDEInfo()
 /* -------------------------------------------------------------------- */
 /*      Do we have the required TREs?                                   */
 /* -------------------------------------------------------------------- */
-    const char *pszGEOPSB , *pszPRJPSB, *pszMAPLOB;
-    OGRSpatialReference oSRS;
-    char szName[81];
     int nGEOPSBSize, nPRJPSBSize, nMAPLOBSize;
 
-    pszGEOPSB = NITFFindTRE( psFile->pachTRE, psFile->nTREBytes,"GEOPSB",&nGEOPSBSize);
-    pszPRJPSB = NITFFindTRE( psFile->pachTRE, psFile->nTREBytes,"PRJPSB",&nPRJPSBSize);
-    pszMAPLOB = NITFFindTRE(psImage->pachTRE,psImage->nTREBytes,"MAPLOB",&nMAPLOBSize);
+    const char *pszGEOPSB = NITFFindTRE( psFile->pachTRE, psFile->nTREBytes, "GEOPSB", &nGEOPSBSize);
+    const char *pszPRJPSB = NITFFindTRE( psFile->pachTRE, psFile->nTREBytes, "PRJPSB", &nPRJPSBSize);
+    const char *pszMAPLOB = NITFFindTRE( psImage->pachTRE, psImage->nTREBytes, "MAPLOB", &nMAPLOBSize);
 
     if( pszGEOPSB == NULL || pszPRJPSB == NULL || pszMAPLOB == NULL )
         return;
@@ -1745,106 +1746,108 @@ void NITFDataset::CheckGeoSDEInfo()
                  "Cannot read PRJPSB TRE. Not enough bytes");
         return;
     }
-    int nParmCount = atoi(NITFGetField(szParm,pszPRJPSB,82,1));
-    int i;
-    double adfParm[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
-    double dfFN;
-    double dfFE;
+    const int nParmCount = atoi(NITFGetField(szParm,pszPRJPSB,82,1));
     if (nPRJPSBSize < 83+15*nParmCount+15+15)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot read PRJPSB TRE. Not enough bytes");
         return;
     }
-    for( i = 0; i < nParmCount; i++ )
+
+    double adfParm[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+    for( int i = 0; i < nParmCount; i++ )
         adfParm[i] = CPLAtof(NITFGetField(szParm,pszPRJPSB,83+15*i,15));
 
-    dfFE = CPLAtof(NITFGetField(szParm,pszPRJPSB,83+15*nParmCount,15));
-    dfFN = CPLAtof(NITFGetField(szParm,pszPRJPSB,83+15*nParmCount+15,15));
+    const double dfFE = CPLAtof(NITFGetField(szParm,pszPRJPSB,83+15*nParmCount,15));
+    const double dfFN = CPLAtof(NITFGetField(szParm,pszPRJPSB,83+15*nParmCount+15,15));
 
 /* -------------------------------------------------------------------- */
 /*      Try to handle the projection.                                   */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszPRJPSB+80,"AC",2) )
-        oSRS.SetACEA( adfParm[1], adfParm[2], adfParm[3], adfParm[0], 
+    OGRSpatialReference oSRS;
+    if( STARTS_WITH_CI(pszPRJPSB+80, "AC") )
+        oSRS.SetACEA( adfParm[1], adfParm[2], adfParm[3], adfParm[0],
                       dfFE, dfFN );
 
-    else if( EQUALN(pszPRJPSB+80,"AK",2) )
+    else if( STARTS_WITH_CI(pszPRJPSB+80, "AK") )
         oSRS.SetLAEA( adfParm[1], adfParm[0], dfFE, dfFN );
 
-    else if( EQUALN(pszPRJPSB+80,"AL",2) )
+    else if( STARTS_WITH_CI(pszPRJPSB+80, "AL") )
         oSRS.SetAE( adfParm[1], adfParm[0], dfFE, dfFN );
 
-    else if( EQUALN(pszPRJPSB+80,"BF",2) )
+    else if( STARTS_WITH_CI(pszPRJPSB+80, "BF") )
         oSRS.SetBonne( adfParm[1], adfParm[0], dfFE, dfFN );
 
-    else if( EQUALN(pszPRJPSB+80,"CP",2) )
+    else if( STARTS_WITH_CI(pszPRJPSB+80, "CP") )
         oSRS.SetEquirectangular( adfParm[1], adfParm[0], dfFE, dfFN );
 
-    else if( EQUALN(pszPRJPSB+80,"CS",2) )
+    else if( STARTS_WITH_CI(pszPRJPSB+80, "CS") )
         oSRS.SetCS( adfParm[1], adfParm[0], dfFE, dfFN );
 
-    else if( EQUALN(pszPRJPSB+80,"EF",2) )
+    else if( STARTS_WITH_CI(pszPRJPSB+80, "EF") )
         oSRS.SetEckertIV( adfParm[0], dfFE, dfFN );
 
-    else if( EQUALN(pszPRJPSB+80,"ED",2) )
+    else if( STARTS_WITH_CI(pszPRJPSB+80, "ED") )
         oSRS.SetEckertVI( adfParm[0], dfFE, dfFN );
 
-    else if( EQUALN(pszPRJPSB+80,"GN",2) )
+    else if( STARTS_WITH_CI(pszPRJPSB+80, "GN") )
         oSRS.SetGnomonic( adfParm[1], adfParm[0], dfFE, dfFN );
 
-    else if( EQUALN(pszPRJPSB+80,"HX",2) )
-        oSRS.SetHOM2PNO( adfParm[1], 
+    else if( STARTS_WITH_CI(pszPRJPSB+80, "HX") )
+        oSRS.SetHOM2PNO( adfParm[1],
                          adfParm[3], adfParm[2],
                          adfParm[5], adfParm[4],
                          adfParm[0], dfFE, dfFN );
 
-    else if( EQUALN(pszPRJPSB+80,"KA",2) )
-        oSRS.SetEC( adfParm[1], adfParm[2], adfParm[3], adfParm[0], 
+    else if( STARTS_WITH_CI(pszPRJPSB+80, "KA") )
+        oSRS.SetEC( adfParm[1], adfParm[2], adfParm[3], adfParm[0],
                     dfFE, dfFN );
 
-    else if( EQUALN(pszPRJPSB+80,"LE",2) )
-        oSRS.SetLCC( adfParm[1], adfParm[2], adfParm[3], adfParm[0], 
+    else if( STARTS_WITH_CI(pszPRJPSB+80, "LE") )
+        oSRS.SetLCC( adfParm[1], adfParm[2], adfParm[3], adfParm[0],
                      dfFE, dfFN );
 
-    else if( EQUALN(pszPRJPSB+80,"LI",2) )
+    else if( STARTS_WITH_CI(pszPRJPSB+80, "LI") )
         oSRS.SetCEA( adfParm[1], adfParm[0], dfFE, dfFN );
 
-    else if( EQUALN(pszPRJPSB+80,"MC",2) )
+    else if( STARTS_WITH_CI(pszPRJPSB+80, "MC") )
         oSRS.SetMercator( adfParm[2], adfParm[1], 1.0, dfFE, dfFN );
 
-    else if( EQUALN(pszPRJPSB+80,"MH",2) )
+    else if( STARTS_WITH_CI(pszPRJPSB+80, "MH") )
         oSRS.SetMC( 0.0, adfParm[1], dfFE, dfFN );
 
-    else if( EQUALN(pszPRJPSB+80,"MP",2) )
+    else if( STARTS_WITH_CI(pszPRJPSB+80, "MP") )
         oSRS.SetMollweide( adfParm[0], dfFE, dfFN );
 
-    else if( EQUALN(pszPRJPSB+80,"NT",2) )
+    else if( STARTS_WITH_CI(pszPRJPSB+80, "NT") )
         oSRS.SetNZMG( adfParm[1], adfParm[0], dfFE, dfFN );
 
-    else if( EQUALN(pszPRJPSB+80,"OD",2) )
+    else if( STARTS_WITH_CI(pszPRJPSB+80, "OD") )
         oSRS.SetOrthographic( adfParm[1], adfParm[0], dfFE, dfFN );
 
-    else if( EQUALN(pszPRJPSB+80,"PC",2) )
+    else if( STARTS_WITH_CI(pszPRJPSB+80, "PC") )
         oSRS.SetPolyconic( adfParm[1], adfParm[0], dfFE, dfFN );
 
-    else if( EQUALN(pszPRJPSB+80,"PG",2) )
+    else if( STARTS_WITH_CI(pszPRJPSB+80, "PG") )
         oSRS.SetPS( adfParm[1], adfParm[0], 1.0, dfFE, dfFN );
 
-    else if( EQUALN(pszPRJPSB+80,"RX",2) )
+    else if( STARTS_WITH_CI(pszPRJPSB+80, "RX") )
         oSRS.SetRobinson( adfParm[0], dfFE, dfFN );
 
-    else if( EQUALN(pszPRJPSB+80,"SA",2) )
+    else if( STARTS_WITH_CI(pszPRJPSB+80, "SA") )
         oSRS.SetSinusoidal( adfParm[0], dfFE, dfFN );
 
-    else if( EQUALN(pszPRJPSB+80,"TC",2) )
+    else if( STARTS_WITH_CI(pszPRJPSB+80, "TC") )
         oSRS.SetTM( adfParm[2], adfParm[0], adfParm[1], dfFE, dfFN );
 
-    else if( EQUALN(pszPRJPSB+80,"VA",2) )
+    else if( STARTS_WITH_CI(pszPRJPSB+80, "VA") )
         oSRS.SetVDG( adfParm[0], dfFE, dfFN );
 
     else
+    {
+        char szName[81];
         oSRS.SetLocalCS( NITFGetField(szName,pszPRJPSB,0,80) );
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Try to apply the datum.                                         */
@@ -1860,35 +1863,34 @@ void NITFDataset::CheckGeoSDEInfo()
 /* -------------------------------------------------------------------- */
 /*      Get the geotransform                                            */
 /* -------------------------------------------------------------------- */
-    double adfGT[6];
-    double dfMeterPerUnit = 1.0;
-
     if (nMAPLOBSize < 28 + 15)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot read MAPLOB TRE. Not enough bytes");
         return;
     }
-    
-    if( EQUALN(pszMAPLOB+0,"DM ",3) )
+
+    double dfMeterPerUnit = 1.0;
+    if( STARTS_WITH_CI(pszMAPLOB+0, "DM ") )
         dfMeterPerUnit = 0.1;
-    else if( EQUALN(pszMAPLOB+0,"CM ",3) )
+    else if( STARTS_WITH_CI(pszMAPLOB+0, "CM ") )
         dfMeterPerUnit = 0.01;
-    else if( EQUALN(pszMAPLOB+0,"MM ",3) )
+    else if( STARTS_WITH_CI(pszMAPLOB+0, "MM ") )
         dfMeterPerUnit = 0.001;
-    else if( EQUALN(pszMAPLOB+0,"UM ",3) )
+    else if( STARTS_WITH_CI(pszMAPLOB+0, "UM ") )
         dfMeterPerUnit = 0.000001;
-    else if( EQUALN(pszMAPLOB+0,"KM ",3) )
+    else if( STARTS_WITH_CI(pszMAPLOB+0, "KM ") )
         dfMeterPerUnit = 1000.0;
-    else if( EQUALN(pszMAPLOB+0,"M  ",3) )
+    else if( STARTS_WITH_CI(pszMAPLOB+0, "M  ") )
         dfMeterPerUnit = 1.0;
     else
     {
         CPLError( CE_Warning, CPLE_AppDefined,
-                  "MAPLOB Unit=%3.3s not regonised, geolocation may be wrong.",
+                  "MAPLOB Unit=%3.3s not recognized, geolocation may be wrong.",
                   pszMAPLOB+0 );
     }
-    
+
+    double adfGT[6];
     adfGT[0] = CPLAtof(NITFGetField(szParm,pszMAPLOB,13,15));
     adfGT[1] = CPLAtof(NITFGetField(szParm,pszMAPLOB,3,5)) * dfMeterPerUnit;
     adfGT[2] = 0.0;
@@ -1913,26 +1915,26 @@ void NITFDataset::CheckGeoSDEInfo()
 /************************************************************************/
 
 CPLErr NITFDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
-                                int nBufXSize, int nBufYSize, 
-                                GDALDataType eDT, 
+                                int nBufXSize, int nBufYSize,
+                                GDALDataType eDT,
                                 int nBandCount, int *panBandList,
                                 char **papszOptions )
-    
+
 {
     if( poJ2KDataset == NULL )
-        return GDALDataset::AdviseRead( nXOff, nYOff, nXSize, nYSize, 
-                                        nBufXSize, nBufYSize, eDT, 
-                                        nBandCount, panBandList, 
+        return GDALDataset::AdviseRead( nXOff, nYOff, nXSize, nYSize,
+                                        nBufXSize, nBufYSize, eDT,
+                                        nBandCount, panBandList,
                                         papszOptions);
     else if( poJPEGDataset != NULL )
-        return poJPEGDataset->AdviseRead( nXOff, nYOff, nXSize, nYSize, 
-                                          nBufXSize, nBufYSize, eDT, 
-                                          nBandCount, panBandList, 
+        return poJPEGDataset->AdviseRead( nXOff, nYOff, nXSize, nYSize,
+                                          nBufXSize, nBufYSize, eDT,
+                                          nBandCount, panBandList,
                                           papszOptions);
     else
-        return poJ2KDataset->AdviseRead( nXOff, nYOff, nXSize, nYSize, 
-                                         nBufXSize, nBufYSize, eDT, 
-                                         nBandCount, panBandList, 
+        return poJ2KDataset->AdviseRead( nXOff, nYOff, nXSize, nYSize,
+                                         nBufXSize, nBufYSize, eDT,
+                                         nBandCount, panBandList,
                                          papszOptions);
 }
 
@@ -1943,27 +1945,27 @@ CPLErr NITFDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
 CPLErr NITFDataset::IRasterIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
                                void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType, 
+                               GDALDataType eBufType,
                                int nBandCount, int *panBandMap,
                                GSpacing nPixelSpace, GSpacing nLineSpace,
                                GSpacing nBandSpace,
                                GDALRasterIOExtraArg* psExtraArg)
-    
+
 {
     if( poJ2KDataset != NULL )
         return poJ2KDataset->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
                                        pData, nBufXSize, nBufYSize, eBufType,
-                                       nBandCount, panBandMap, 
+                                       nBandCount, panBandMap,
                                        nPixelSpace, nLineSpace, nBandSpace, psExtraArg );
     else if( poJPEGDataset != NULL )
         return poJPEGDataset->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
                                         pData, nBufXSize, nBufYSize, eBufType,
-                                        nBandCount, panBandMap, 
+                                        nBandCount, panBandMap,
                                         nPixelSpace, nLineSpace, nBandSpace, psExtraArg );
-    else 
+    else
         return GDALDataset::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
                                        pData, nBufXSize, nBufYSize, eBufType,
-                                       nBandCount, panBandMap, 
+                                       nBandCount, panBandMap,
                                        nPixelSpace, nLineSpace, nBandSpace, psExtraArg );
 }
 
@@ -1979,8 +1981,8 @@ CPLErr NITFDataset::GetGeoTransform( double *padfGeoTransform )
 
     if( bGotGeoTransform )
         return CE_None;
-    else
-        return GDALPamDataset::GetGeoTransform( padfGeoTransform );
+
+    return GDALPamDataset::GetGeoTransform( padfGeoTransform );
 }
 
 /************************************************************************/
@@ -1990,35 +1992,32 @@ CPLErr NITFDataset::GetGeoTransform( double *padfGeoTransform )
 CPLErr NITFDataset::SetGeoTransform( double *padfGeoTransform )
 
 {
-    double dfIGEOLOULX, dfIGEOLOULY, dfIGEOLOURX, dfIGEOLOURY, 
-           dfIGEOLOLRX, dfIGEOLOLRY, dfIGEOLOLLX, dfIGEOLOLLY;
-
     bGotGeoTransform = TRUE;
     /* Valgrind would complain because SetGeoTransform() is called */
     /* from SetProjection() with adfGeoTransform as argument */
     if (adfGeoTransform != padfGeoTransform)
         memcpy( adfGeoTransform, padfGeoTransform, sizeof(double) * 6 );
 
-    dfIGEOLOULX = padfGeoTransform[0] + 0.5 * padfGeoTransform[1] 
+    double dfIGEOLOULX = padfGeoTransform[0] + 0.5 * padfGeoTransform[1]
                                       + 0.5 * padfGeoTransform[2];
-    dfIGEOLOULY = padfGeoTransform[3] + 0.5 * padfGeoTransform[4] 
+    double dfIGEOLOULY = padfGeoTransform[3] + 0.5 * padfGeoTransform[4]
                                       + 0.5 * padfGeoTransform[5];
-    dfIGEOLOURX = dfIGEOLOULX + padfGeoTransform[1] * (nRasterXSize - 1);
-    dfIGEOLOURY = dfIGEOLOULY + padfGeoTransform[4] * (nRasterXSize - 1);
-    dfIGEOLOLRX = dfIGEOLOULX + padfGeoTransform[1] * (nRasterXSize - 1)
+    double dfIGEOLOURX = dfIGEOLOULX + padfGeoTransform[1] * (nRasterXSize - 1);
+    double dfIGEOLOURY = dfIGEOLOULY + padfGeoTransform[4] * (nRasterXSize - 1);
+    double dfIGEOLOLRX = dfIGEOLOULX + padfGeoTransform[1] * (nRasterXSize - 1)
                               + padfGeoTransform[2] * (nRasterYSize - 1);
-    dfIGEOLOLRY = dfIGEOLOULY + padfGeoTransform[4] * (nRasterXSize - 1)
+    double dfIGEOLOLRY = dfIGEOLOULY + padfGeoTransform[4] * (nRasterXSize - 1)
                               + padfGeoTransform[5] * (nRasterYSize - 1);
-    dfIGEOLOLLX = dfIGEOLOULX + padfGeoTransform[2] * (nRasterYSize - 1);
-    dfIGEOLOLLY = dfIGEOLOULY + padfGeoTransform[5] * (nRasterYSize - 1);
+    double dfIGEOLOLLX = dfIGEOLOULX + padfGeoTransform[2] * (nRasterYSize - 1);
+    double dfIGEOLOLLY = dfIGEOLOULY + padfGeoTransform[5] * (nRasterYSize - 1);
 
-    if( NITFWriteIGEOLO( psImage, psImage->chICORDS, 
-                         psImage->nZone, 
-                         dfIGEOLOULX, dfIGEOLOULY, dfIGEOLOURX, dfIGEOLOURY, 
+    if( NITFWriteIGEOLO( psImage, psImage->chICORDS,
+                         psImage->nZone,
+                         dfIGEOLOULX, dfIGEOLOULY, dfIGEOLOURX, dfIGEOLOURY,
                          dfIGEOLOLRX, dfIGEOLOLRY, dfIGEOLOLLX, dfIGEOLOLLY ) )
         return CE_None;
-    else
-        return GDALPamDataset::SetGeoTransform( padfGeoTransform );
+
+    return GDALPamDataset::SetGeoTransform( padfGeoTransform );
 }
 
 /************************************************************************/
@@ -2034,15 +2033,15 @@ CPLErr NITFDataset::SetGCPs( int nGCPCountIn, const GDAL_GCP *pasGCPListIn,
                  "NITF only supports writing 4 GCPs.");
         return CE_Failure;
     }
-    
+
     /* Free previous GCPs */
     GDALDeinitGCPs( nGCPCount, pasGCPList );
     CPLFree( pasGCPList );
-    
+
     /* Duplicate in GCPs */
     nGCPCount = nGCPCountIn;
     pasGCPList = GDALDuplicateGCPs(nGCPCount, pasGCPListIn);
-    
+
     CPLFree(pszGCPProjection);
     pszGCPProjection = CPLStrdup(pszGCPProjectionIn);
 
@@ -2095,17 +2094,17 @@ CPLErr NITFDataset::SetGCPs( int nGCPCountIn, const GDAL_GCP *pasGCPListIn,
     CPLErr eErr = SetProjection(pszGCPProjection);
     CPLFree(pszProjection);
     pszProjection = pszProjectionBack;
-    
+
     if (eErr != CE_None)
         return eErr;
-    
-    if( NITFWriteIGEOLO( psImage, psImage->chICORDS, 
-                         psImage->nZone, 
-                         dfIGEOLOULX, dfIGEOLOULY, dfIGEOLOURX, dfIGEOLOURY, 
+
+    if( NITFWriteIGEOLO( psImage, psImage->chICORDS,
+                         psImage->nZone,
+                         dfIGEOLOULX, dfIGEOLOULY, dfIGEOLOURX, dfIGEOLOURY,
                          dfIGEOLOLRX, dfIGEOLOLRY, dfIGEOLOLLX, dfIGEOLOLLY ) )
         return CE_None;
-    else
-        return CE_Failure;
+
+    return CE_Failure;
 }
 
 /************************************************************************/
@@ -2117,8 +2116,8 @@ const char *NITFDataset::GetProjectionRef()
 {
     if( bGotGeoTransform )
         return pszProjection;
-    else
-        return GDALPamDataset::GetProjectionRef();
+
+    return GDALPamDataset::GetProjectionRef();
 }
 
 /************************************************************************/
@@ -2130,7 +2129,7 @@ CPLErr NITFDataset::SetProjection(const char* _pszProjection)
 {
     int    bNorth;
     OGRSpatialReference oSRS, oSRS_WGS84;
-    char *pszWKT = (char *) _pszProjection;
+    char *pszWKT = const_cast<char *>( _pszProjection );
 
     if( pszWKT != NULL )
         oSRS.importFromWkt( &pszWKT );
@@ -2194,12 +2193,13 @@ CPLErr NITFDataset::SetProjection(const char* _pszProjection)
 
 void NITFDataset::InitializeNITFDESMetadata()
 {
-    static const char   *pszDESMetadataDomain       = "NITF_DES_METADATA";
-    static const char   *pszDESsDomain              = "NITF_DES";
-    static const char   *pszMDXmlDataContentDESDATA = "NITF_DES_XML_DATA_CONTENT_DESDATA";
-    static const char   *pszXmlDataContent          = "XML_DATA_CONTENT";
+    static const char   * const pszDESMetadataDomain       = "NITF_DES_METADATA";
+    static const char   * const pszDESsDomain              = "NITF_DES";
+    static const char   * const pszMDXmlDataContentDESDATA = "NITF_DES_XML_DATA_CONTENT_DESDATA";
+    static const char   * const pszXmlDataContent          = "XML_DATA_CONTENT";
     static const int     idxXmlDataContentDESDATA   = 973;
-    static const int     sizeXmlDataContent         = (int)strlen(pszXmlDataContent);
+    static const int     sizeXmlDataContent         =
+        static_cast<int>( strlen( pszXmlDataContent ) );
 
     char **ppszDESMetadataList = oSpecialMD.GetMetadata( pszDESMetadataDomain );
 
@@ -2228,11 +2228,12 @@ void NITFDataset::InitializeNITFDESMetadata()
         if( pszSpace )
         {
             pszData = CPLStrdup( pszSpace+1 );
-            nDataLen = CPLBase64DecodeInPlace((GByte*)pszData);
+            nDataLen = CPLBase64DecodeInPlace(
+                reinterpret_cast<GByte *>( pszData ) );
             pszData[nDataLen] = 0;
         }
 
-        if ( nDataLen > 2 + sizeXmlDataContent && EQUALN(pszData, "DE", 2) )
+        if ( nDataLen > 2 + sizeXmlDataContent && STARTS_WITH_CI(pszData, "DE") )
         {
             // Check to see if this is a XML_DATA_CONTENT DES.
             if ( EQUALN(pszData + 2, pszXmlDataContent, sizeXmlDataContent) &&
@@ -2262,7 +2263,7 @@ void NITFDataset::InitializeNITFDESMetadata()
 
 void NITFDataset::InitializeNITFDESs()
 {
-    static const char *pszDESsDomain = "NITF_DES";
+    static const char * const pszDESsDomain = "NITF_DES";
 
     char **ppszDESsList = oSpecialMD.GetMetadata( pszDESsDomain );
 
@@ -2284,18 +2285,18 @@ void NITFDataset::InitializeNITFDESs()
         if( EQUAL(psSegInfo->szSegmentType,"DE") )
         {
             nDESDataSize = psSegInfo->nSegmentHeaderSize + psSegInfo->nSegmentSize;
-            pachDESData  = (char*) VSIMalloc( nDESDataSize + 1 );
+            pachDESData  = reinterpret_cast<char *>(
+                VSI_MALLOC_VERBOSE( nDESDataSize + 1 ) );
 
             if (pachDESData == NULL)
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory, "Cannot allocate memory for DES segment" );
                 return;
             }
 
             if( VSIFSeekL( psFile->fp, psSegInfo->nSegmentHeaderStart,
                           SEEK_SET ) != 0
-                || (int)VSIFReadL( pachDESData, 1, nDESDataSize,
-                             psFile->fp ) != nDESDataSize )
+                || static_cast<int>( VSIFReadL( pachDESData, 1, nDESDataSize,
+                                                psFile->fp ) ) != nDESDataSize )
             {
                 CPLError( CE_Failure, CPLE_FileIO,
                           "Failed to read %d byte DES subheader from " CPL_FRMT_GUIB ".",
@@ -2329,7 +2330,7 @@ void NITFDataset::InitializeNITFDESs()
 
             char buffer[20];
 
-            sprintf(buffer, "%d", nDESDataSize);
+            snprintf(buffer, sizeof(buffer), "%d", nDESDataSize);
 
             std::string desSubheaderStr(buffer);
             desSubheaderStr.append(" ");
@@ -2349,8 +2350,8 @@ void NITFDataset::InitializeNITFDESs()
 
 void NITFDataset::InitializeNITFTREs()
 {
-    static const char *pszFileHeaderTREsDomain   = "NITF_FILE_HEADER_TRES";
-    static const char *pszImageSegmentTREsDomain = "NITF_IMAGE_SEGMENT_TRES";
+    static const char * const pszFileHeaderTREsDomain   = "NITF_FILE_HEADER_TRES";
+    static const char * const pszImageSegmentTREsDomain = "NITF_IMAGE_SEGMENT_TRES";
 
     char **ppszFileHeaderTREsList   = oSpecialMD.GetMetadata( pszFileHeaderTREsDomain );
     char **ppszImageSegmentTREsList = oSpecialMD.GetMetadata( pszImageSegmentTREsDomain );
@@ -2434,8 +2435,10 @@ void NITFDataset::InitializeNITFTREs()
                                               nThisTRESize + 5,
                                               CPLES_BackslashQuotable );
 
-            char * pszLine = (char *) CPLMalloc( strlen(szTag)+strlen(pszEscapedData)+2 );
-            sprintf( pszLine, "%s=%s", szTag, pszEscapedData );
+            const size_t nLineLen = strlen(szTag)+strlen(pszEscapedData)+2;
+            char * pszLine = reinterpret_cast<char *>(
+                CPLMalloc( nLineLen ) );
+            snprintf( pszLine, nLineLen, "%s=%s", szTag, pszEscapedData );
             aosList.AddString(pszLine);
             CPLFree(pszLine);
             pszLine        = NULL;
@@ -2460,9 +2463,9 @@ void NITFDataset::InitializeNITFTREs()
 void NITFDataset::InitializeNITFMetadata()
 
 {
-    static const char *pszDomainName            = "NITF_METADATA";
-    static const char *pszTagNITFFileHeader     = "NITFFileHeader";
-    static const char *pszTagNITFImageSubheader = "NITFImageSubheader";
+    static const char * const pszDomainName            = "NITF_METADATA";
+    static const char * const pszTagNITFFileHeader     = "NITFFileHeader";
+    static const char * const pszTagNITFImageSubheader = "NITFImageSubheader";
 
     if( oSpecialMD.GetMetadata( pszDomainName ) != NULL )
         return;
@@ -2477,10 +2480,10 @@ void NITFDataset::InitializeNITFMetadata()
 
     if( psFile->pachHeader != NULL )
     {
-        if ( (strncmp(psFile->pachHeader, "NITF02.10", 9) == 0) || (strncmp(psFile->pachHeader, "NSIF01.00", 9) == 0) )
+        if ( (STARTS_WITH(psFile->pachHeader, "NITF02.10")) || (STARTS_WITH(psFile->pachHeader, "NSIF01.00")) )
             nHeaderLenOffset = 354;
-        else if ( (strncmp(psFile->pachHeader, "NITF01.10", 9) == 0) || (strncmp(psFile->pachHeader, "NITF02.00", 9) == 0) )
-            nHeaderLenOffset = ( strncmp((psFile->pachHeader+280), "999998", 6 ) == 0 ) ? 394 : 354;
+        else if ( (STARTS_WITH(psFile->pachHeader, "NITF01.10")) || (STARTS_WITH(psFile->pachHeader, "NITF02.00")) )
+            nHeaderLenOffset = ( STARTS_WITH((psFile->pachHeader+280), "999998") ) ? 394 : 354;
     }
 
     char fieldHL[7];
@@ -2500,13 +2503,15 @@ void NITFDataset::InitializeNITFMetadata()
         return;
     }
 
-    char *encodedHeader = CPLBase64Encode(nHeaderLen, 
-                                          (GByte*)psFile->pachHeader);
+    char *encodedHeader = CPLBase64Encode(
+        nHeaderLen,
+        reinterpret_cast<GByte *>( psFile->pachHeader ) );
 
     if (encodedHeader == NULL || strlen(encodedHeader) == 0 )
     {
-        CPLError(CE_Failure, CPLE_AppDefined, 
+        CPLError(CE_Failure, CPLE_AppDefined,
                  "Failed to encode NITF file header!");
+        CPLFree(encodedHeader);
         return;
     }
 
@@ -2525,10 +2530,10 @@ void NITFDataset::InitializeNITFMetadata()
     // Get the image subheader length.
 
     int nImageSubheaderLen = 0;
-    
+
     for( int i = 0; i < psFile->nSegmentCount; ++i )
     {
-        if (strncmp(psFile->pasSegmentInfo[i].szSegmentType, "IM", 2) == 0)
+        if (STARTS_WITH(psFile->pasSegmentInfo[i].szSegmentType, "IM"))
         {
             nImageSubheaderLen = psFile->pasSegmentInfo[i].nSegmentHeaderSize;
             break;
@@ -2543,21 +2548,24 @@ void NITFDataset::InitializeNITFMetadata()
 
     if( nImageSubheaderLen > 0 )
     {
-        char *encodedImageSubheader = CPLBase64Encode(nImageSubheaderLen,(GByte*) psImage->pachHeader);
-    
-        if( encodedImageSubheader == NULL || strlen(encodedImageSubheader) ==0 )
+        char *encodedImageSubheader
+            = CPLBase64Encode( nImageSubheaderLen,
+                               reinterpret_cast<GByte *>( psImage->pachHeader) );
+
+        if( encodedImageSubheader == NULL || strlen(encodedImageSubheader) == 0 )
         {
-            CPLError(CE_Failure, CPLE_AppDefined, 
+            CPLError(CE_Failure, CPLE_AppDefined,
                      "Failed to encode image subheader!");
+            CPLFree( encodedImageSubheader );
             return;
         }
 
         // The length of the image subheader plus a space is append to the beginning of the encoded string so
         // that we can recover the actual length of the image subheader when we decode it.
-      
+
         char buffer[20];
 
-        sprintf(buffer, "%d", nImageSubheaderLen);
+        snprintf(buffer, sizeof(buffer), "%d", nImageSubheaderLen);
 
         std::string imageSubheaderStr(buffer);
         imageSubheaderStr.append(" ");
@@ -2579,70 +2587,66 @@ void NITFDataset::InitializeCGMMetadata()
     if( oSpecialMD.GetMetadataItem( "SEGMENT_COUNT", "CGM" ) != NULL )
         return;
 
-    int iSegment;
     int iCGM = 0;
-    char **papszCGMMetadata = NULL;
-
-    papszCGMMetadata = 
-        CSLSetNameValue( papszCGMMetadata, "SEGMENT_COUNT", "0" );
+    char **papszCGMMetadata =
+        CSLSetNameValue( NULL, "SEGMENT_COUNT", "0" );
 
 /* ==================================================================== */
 /*      Process all graphics segments.                                  */
 /* ==================================================================== */
-    for( iSegment = 0; iSegment < psFile->nSegmentCount; iSegment++ )
+    for( int iSegment = 0; iSegment < psFile->nSegmentCount; iSegment++ )
     {
         NITFSegmentInfo *psSegment = psFile->pasSegmentInfo + iSegment;
 
-        if( !EQUAL(psSegment->szSegmentType,"GR") 
+        if( !EQUAL(psSegment->szSegmentType,"GR")
             && !EQUAL(psSegment->szSegmentType,"SY") )
             continue;
 
-        papszCGMMetadata = 
-            CSLSetNameValue( papszCGMMetadata, 
-                             CPLString().Printf("SEGMENT_%d_SLOC_ROW", iCGM), 
+        papszCGMMetadata =
+            CSLSetNameValue( papszCGMMetadata,
+                             CPLString().Printf("SEGMENT_%d_SLOC_ROW", iCGM),
                              CPLString().Printf("%d",psSegment->nLOC_R) );
-        papszCGMMetadata = 
-            CSLSetNameValue( papszCGMMetadata, 
-                             CPLString().Printf("SEGMENT_%d_SLOC_COL", iCGM), 
+        papszCGMMetadata =
+            CSLSetNameValue( papszCGMMetadata,
+                             CPLString().Printf("SEGMENT_%d_SLOC_COL", iCGM),
                              CPLString().Printf("%d",psSegment->nLOC_C) );
 
-        papszCGMMetadata = 
-            CSLSetNameValue( papszCGMMetadata, 
-                             CPLString().Printf("SEGMENT_%d_CCS_ROW", iCGM), 
+        papszCGMMetadata =
+            CSLSetNameValue( papszCGMMetadata,
+                             CPLString().Printf("SEGMENT_%d_CCS_ROW", iCGM),
                              CPLString().Printf("%d",psSegment->nCCS_R) );
-        papszCGMMetadata = 
-            CSLSetNameValue( papszCGMMetadata, 
-                             CPLString().Printf("SEGMENT_%d_CCS_COL", iCGM), 
+        papszCGMMetadata =
+            CSLSetNameValue( papszCGMMetadata,
+                             CPLString().Printf("SEGMENT_%d_CCS_COL", iCGM),
                              CPLString().Printf("%d",psSegment->nCCS_C) );
 
-        papszCGMMetadata = 
-            CSLSetNameValue( papszCGMMetadata, 
-                             CPLString().Printf("SEGMENT_%d_SDLVL", iCGM), 
+        papszCGMMetadata =
+            CSLSetNameValue( papszCGMMetadata,
+                             CPLString().Printf("SEGMENT_%d_SDLVL", iCGM),
                              CPLString().Printf("%d",psSegment->nDLVL) );
-        papszCGMMetadata = 
-            CSLSetNameValue( papszCGMMetadata, 
-                             CPLString().Printf("SEGMENT_%d_SALVL", iCGM), 
+        papszCGMMetadata =
+            CSLSetNameValue( papszCGMMetadata,
+                             CPLString().Printf("SEGMENT_%d_SALVL", iCGM),
                              CPLString().Printf("%d",psSegment->nALVL) );
 
 /* -------------------------------------------------------------------- */
 /*      Load the raw CGM data itself.                                   */
 /* -------------------------------------------------------------------- */
-        char *pabyCGMData, *pszEscapedCGMData;
 
-        pabyCGMData = (char *) VSICalloc(1,(size_t)psSegment->nSegmentSize);
+        char *pabyCGMData = reinterpret_cast<char *>(
+            VSI_CALLOC_VERBOSE( 1, static_cast<size_t>( psSegment->nSegmentSize ) ) );
         if (pabyCGMData == NULL)
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
             CSLDestroy( papszCGMMetadata );
             return;
         }
-        if( VSIFSeekL( psFile->fp, psSegment->nSegmentStart, 
-                       SEEK_SET ) != 0 
-            || VSIFReadL( pabyCGMData, 1, (size_t)psSegment->nSegmentSize, 
+        if( VSIFSeekL( psFile->fp, psSegment->nSegmentStart,
+                       SEEK_SET ) != 0
+            || VSIFReadL( pabyCGMData, 1, (size_t)psSegment->nSegmentSize,
                           psFile->fp ) != psSegment->nSegmentSize )
         {
-            CPLError( CE_Warning, CPLE_FileIO, 
-                      "Failed to read " CPL_FRMT_GUIB " bytes of graphic data at " CPL_FRMT_GUIB ".", 
+            CPLError( CE_Warning, CPLE_FileIO,
+                      "Failed to read " CPL_FRMT_GUIB " bytes of graphic data at " CPL_FRMT_GUIB ".",
                       psSegment->nSegmentSize,
                       psSegment->nSegmentStart );
             CPLFree(pabyCGMData);
@@ -2650,20 +2654,20 @@ void NITFDataset::InitializeCGMMetadata()
             return;
         }
 
-        pszEscapedCGMData = CPLEscapeString( pabyCGMData, 
-                                             (int)psSegment->nSegmentSize, 
-                                             CPLES_BackslashQuotable );
+        char *pszEscapedCGMData = CPLEscapeString(
+            pabyCGMData, static_cast<int>( psSegment->nSegmentSize ),
+            CPLES_BackslashQuotable );
+
         if (pszEscapedCGMData == NULL)
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
             CPLFree(pabyCGMData);
             CSLDestroy( papszCGMMetadata );
             return;
         }
 
-        papszCGMMetadata = 
-            CSLSetNameValue( papszCGMMetadata, 
-                             CPLString().Printf("SEGMENT_%d_DATA", iCGM), 
+        papszCGMMetadata =
+            CSLSetNameValue( papszCGMMetadata,
+                             CPLString().Printf("SEGMENT_%d_DATA", iCGM),
                              pszEscapedCGMData );
         CPLFree( pszEscapedCGMData );
         CPLFree( pabyCGMData );
@@ -2674,9 +2678,9 @@ void NITFDataset::InitializeCGMMetadata()
 /* -------------------------------------------------------------------- */
 /*      Record the CGM segment count.                                   */
 /* -------------------------------------------------------------------- */
-    papszCGMMetadata = 
-        CSLSetNameValue( papszCGMMetadata, 
-                         "SEGMENT_COUNT", 
+    papszCGMMetadata =
+        CSLSetNameValue( papszCGMMetadata,
+                         "SEGMENT_COUNT",
                          CPLString().Printf( "%d", iCGM ) );
 
     oSpecialMD.SetMetadata( papszCGMMetadata, "CGM" );
@@ -2694,13 +2698,12 @@ void NITFDataset::InitializeTextMetadata()
     if( oSpecialMD.GetMetadata( "TEXT" ) != NULL )
         return;
 
-    int iSegment;
     int iText = 0;
 
 /* ==================================================================== */
 /*      Process all text segments.                                  */
 /* ==================================================================== */
-    for( iSegment = 0; iSegment < psFile->nSegmentCount; iSegment++ )
+    for( int iSegment = 0; iSegment < psFile->nSegmentCount; iSegment++ )
     {
         NITFSegmentInfo *psSegment = psFile->pasSegmentInfo + iSegment;
 
@@ -2712,8 +2715,9 @@ void NITFDataset::InitializeTextMetadata()
 /* -------------------------------------------------------------------- */
 
         /* Allocate one extra byte for the NULL terminating character */
-        char *pabyHeaderData = (char *) CPLCalloc(1,
-                (size_t) psSegment->nSegmentHeaderSize + 1);
+        char *pabyHeaderData = reinterpret_cast<char *>(
+            CPLCalloc(1, static_cast<size_t>(
+                psSegment->nSegmentHeaderSize + 1) ) );
         if (VSIFSeekL(psFile->fp, psSegment->nSegmentHeaderStart,
                       SEEK_SET) != 0 ||
             VSIFReadL(pabyHeaderData, 1, (size_t) psSegment->nSegmentHeaderSize,
@@ -2734,22 +2738,21 @@ void NITFDataset::InitializeTextMetadata()
 /* -------------------------------------------------------------------- */
 /*      Load the raw TEXT data itself.                                  */
 /* -------------------------------------------------------------------- */
-        char *pabyTextData;
-
         /* Allocate one extra byte for the NULL terminating character */
-        pabyTextData = (char *) VSICalloc(1,(size_t)psSegment->nSegmentSize+1);
+        char *pabyTextData = reinterpret_cast<char *>(
+            VSI_CALLOC_VERBOSE( 1, (size_t)psSegment->nSegmentSize + 1 ) );
         if (pabyTextData == NULL)
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
             return;
         }
-        if( VSIFSeekL( psFile->fp, psSegment->nSegmentStart, 
-                       SEEK_SET ) != 0 
-            || VSIFReadL( pabyTextData, 1, (size_t)psSegment->nSegmentSize, 
+        if( VSIFSeekL( psFile->fp, psSegment->nSegmentStart,
+                       SEEK_SET ) != 0
+            || VSIFReadL( pabyTextData, 1,
+                          static_cast<size_t>( psSegment->nSegmentSize ),
                           psFile->fp ) != psSegment->nSegmentSize )
         {
-            CPLError( CE_Warning, CPLE_FileIO, 
-                      "Failed to read " CPL_FRMT_GUIB " bytes of text data at " CPL_FRMT_GUIB ".", 
+            CPLError( CE_Warning, CPLE_FileIO,
+                      "Failed to read " CPL_FRMT_GUIB " bytes of text data at " CPL_FRMT_GUIB ".",
                       psSegment->nSegmentSize,
                       psSegment->nSegmentStart );
             CPLFree( pabyTextData );
@@ -2779,9 +2782,7 @@ void NITFDataset::InitializeTREMetadata()
 /* -------------------------------------------------------------------- */
 /*      Loop over TRE sources (file and image).                         */
 /* -------------------------------------------------------------------- */
-    int nTRESrc;
-
-    for( nTRESrc = 0; nTRESrc < 2; nTRESrc++ )
+    for( int nTRESrc = 0; nTRESrc < 2; nTRESrc++ )
     {
         int nTREBytes;
         char *pszTREData;
@@ -2793,7 +2794,7 @@ void NITFDataset::InitializeTREMetadata()
         }
         else
         {
-            if( psImage ) 
+            if( psImage )
             {
                 nTREBytes = psImage->nTREBytes;
                 pszTREData = psImage->pachTRE;
@@ -2813,26 +2814,27 @@ void NITFDataset::InitializeTREMetadata()
         {
             char szTemp[100];
             char szTag[7];
-            char *pszEscapedData;
-            int nThisTRESize = atoi(NITFGetField(szTemp, pszTREData, 6, 5 ));
+            const int nThisTRESize = atoi(NITFGetField(szTemp, pszTREData, 6, 5 ));
 
             if (nThisTRESize < 0)
             {
                 NITFGetField(szTemp, pszTREData, 0, 6 );
                 CPLError(CE_Failure, CPLE_AppDefined, "Invalid size (%d) for TRE %s",
                         nThisTRESize, szTemp);
+                CPLDestroyXMLNode(psTresNode);
                 return;
             }
             if (nThisTRESize > nTREBytes - 11)
             {
                 CPLError(CE_Failure, CPLE_AppDefined, "Not enough bytes in TRE");
+                CPLDestroyXMLNode(psTresNode);
                 return;
             }
 
             strncpy( szTag, pszTREData, 6 );
             szTag[6] = '\0';
 
-            // trim white off tag. 
+            // trim white off tag.
             while( strlen(szTag) > 0 && szTag[strlen(szTag)-1] == ' ' )
                 szTag[strlen(szTag)-1] = '\0';
 
@@ -2844,13 +2846,12 @@ void NITFDataset::InitializeTREMetadata()
                 CPLAddXMLChild(psTresNode, psTreNode);
             }
 
-            // escape data. 
-            pszEscapedData = CPLEscapeString( pszTREData + 11,
-                                              nThisTRESize,
-                                              CPLES_BackslashQuotable );
+            // escape data.
+            char *pszEscapedData = CPLEscapeString( pszTREData + 11,
+                                                    nThisTRESize,
+                                                    CPLES_BackslashQuotable );
             if (pszEscapedData == NULL)
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
                 return;
             }
 
@@ -2859,12 +2860,12 @@ void NITFDataset::InitializeTREMetadata()
             int nCountUnique = 2;
             while(oSpecialMD.GetMetadataItem( szUniqueTag, "TRE") != NULL)
             {
-                sprintf(szUniqueTag, "%s_%d", szTag, nCountUnique);
+                snprintf(szUniqueTag, sizeof(szUniqueTag), "%s_%d", szTag, nCountUnique);
                 nCountUnique ++;
             }
             oSpecialMD.SetMetadataItem( szUniqueTag, pszEscapedData, "TRE" );
             CPLFree( pszEscapedData );
-            
+
             nTREBytes -= (nThisTRESize + 11);
             pszTREData += (nThisTRESize + 11);
         }
@@ -2873,37 +2874,33 @@ void NITFDataset::InitializeTREMetadata()
 /* -------------------------------------------------------------------- */
 /*      Loop over TRE in DES                                            */
 /* -------------------------------------------------------------------- */
-    int iSegment;
-    for( iSegment = 0; iSegment < psFile->nSegmentCount; iSegment++ )
+    for( int iSegment = 0; iSegment < psFile->nSegmentCount; iSegment++ )
     {
         NITFSegmentInfo *psSegInfo = psFile->pasSegmentInfo + iSegment;
-        NITFDES *psDES;
-        int nOffset = 0;
-        char szTREName[7];
-        int nThisTRESize;
-
         if( !EQUAL(psSegInfo->szSegmentType,"DE") )
             continue;
 
-        psDES = NITFDESAccess( psFile, iSegment );
+        NITFDES *psDES = NITFDESAccess( psFile, iSegment );
         if( psDES == NULL )
             continue;
 
         char* pabyTREData = NULL;
-        nOffset = 0;
+        int nOffset = 0;
+        char szTREName[7];
+        int nThisTRESize;
+
         while (NITFDESGetTRE( psDES, nOffset, szTREName, &pabyTREData, &nThisTRESize))
         {
             char* pszEscapedData = CPLEscapeString( pabyTREData, nThisTRESize,
                                                 CPLES_BackslashQuotable );
             if (pszEscapedData == NULL)
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
                 NITFDESFreeTREData(pabyTREData);
                 NITFDESDeaccess(psDES);
                 return;
             }
 
-            // trim white off tag. 
+            // trim white off tag.
             while( strlen(szTREName) > 0 && szTREName[strlen(szTREName)-1] == ' ' )
                 szTREName[strlen(szTREName)-1] = '\0';
 
@@ -2921,7 +2918,7 @@ void NITFDataset::InitializeTREMetadata()
             int nCountUnique = 2;
             while(oSpecialMD.GetMetadataItem( szUniqueTag, "TRE") != NULL)
             {
-                sprintf(szUniqueTag, "%s_%d", szTREName, nCountUnique);
+                snprintf(szUniqueTag, sizeof(szUniqueTag), "%s_%d", szTREName, nCountUnique);
                 nCountUnique ++;
             }
             oSpecialMD.SetMetadataItem( szUniqueTag, pszEscapedData, "TRE" );
@@ -2939,9 +2936,7 @@ void NITFDataset::InitializeTREMetadata()
     if (psTresNode->psChild != NULL)
     {
         char* pszXML = CPLSerializeXMLTree(psTresNode);
-        char* apszMD[2];
-        apszMD[0] = pszXML;
-        apszMD[1] = NULL;
+        char* apszMD[2] = { pszXML, NULL };
         oSpecialMD.SetMetadata( apszMD, "xml:TRE" );
         CPLFree(pszXML);
     }
@@ -3105,7 +3100,7 @@ const char *NITFDataset::GetMetadataItem(const char * pszName,
         return oSpecialMD.GetMetadataItem( pszName, pszDomain );
     }
 
-    if( pszDomain != NULL && EQUAL(pszDomain,"OVERVIEWS") 
+    if( pszDomain != NULL && EQUAL(pszDomain,"OVERVIEWS")
         && osRSetVRT.size() > 0 )
         return osRSetVRT;
 
@@ -3132,8 +3127,8 @@ const char *NITFDataset::GetGCPProjection()
 {
     if( nGCPCount > 0 && pszGCPProjection != NULL )
         return pszGCPProjection;
-    else
-        return "";
+
+    return "";
 }
 
 /************************************************************************/
@@ -3164,9 +3159,8 @@ int NITFDataset::CheckForRSets( const char *pszNITFFilename,
 /*      Check to see if we have RSets.                                  */
 /* -------------------------------------------------------------------- */
     std::vector<CPLString> aosRSetFilenames;
-    int i;
 
-    for( i = 1; i <= 5; i++ )
+    for( int i = 1; i <= 5; i++ )
     {
         CPLString osTarget;
         VSIStatBufL sStat;
@@ -3174,7 +3168,7 @@ int NITFDataset::CheckForRSets( const char *pszNITFFilename,
         if ( isR0File )
         {
           osTarget = pszNITFFilename;
-          osTarget[osTarget.size()-1] = (char) ('0' + i );
+          osTarget[osTarget.size()-1] = static_cast<char>( '0' + i );
         }
         else
           osTarget.Printf( "%s.r%d", pszNITFFilename, i );
@@ -3193,38 +3187,37 @@ int NITFDataset::CheckForRSets( const char *pszNITFFilename,
 
         aosRSetFilenames.push_back( osTarget );
     }
-   
+
     if( aosRSetFilenames.size() == 0 )
         return FALSE;
-    
+
 /* -------------------------------------------------------------------- */
 /*      We do, so try to create a wrapping VRT file.                    */
 /* -------------------------------------------------------------------- */
     CPLString osFragment;
-    int iBand;
 
     osRSetVRT.Printf( "<VRTDataset rasterXSize=\"%d\" rasterYSize=\"%d\">\n",
                   GetRasterXSize()/2, GetRasterYSize()/2 );
 
-    for( iBand = 0; iBand < GetRasterCount(); iBand++ )
+    for( int iBand = 0; iBand < GetRasterCount(); iBand++ )
     {
         GDALRasterBand *poBand = GetRasterBand(iBand+1);
 
         osRSetVRT += osFragment.
-            Printf( "  <VRTRasterBand dataType=\"%s\" band=\"%d\">\n", 
+            Printf( "  <VRTRasterBand dataType=\"%s\" band=\"%d\">\n",
                     GDALGetDataTypeName( poBand->GetRasterDataType() ),
                     iBand+1 );
 
-        for( i = 0; i < (int) aosRSetFilenames.size(); i++ )
+        for( int i = 0; i < static_cast<int>( aosRSetFilenames.size() ); i++ )
         {
             char* pszEscaped = CPLEscapeString(aosRSetFilenames[i].c_str(), -1, CPLES_XML);
             if( i == 0 )
                 osRSetVRT += osFragment.Printf(
-                    "    <SimpleSource><SourceFilename>%s</SourceFilename><SourceBand>%d</SourceBand></SimpleSource>\n", 
+                    "    <SimpleSource><SourceFilename>%s</SourceFilename><SourceBand>%d</SourceBand></SimpleSource>\n",
                     pszEscaped, iBand+1 );
             else
                 osRSetVRT += osFragment.Printf(
-                    "    <Overview><SourceFilename>%s</SourceFilename><SourceBand>%d</SourceBand></Overview>\n", 
+                    "    <Overview><SourceFilename>%s</SourceFilename><SourceBand>%d</SourceBand></Overview>\n",
                     pszEscaped, iBand+1 );
             CPLFree(pszEscaped);
         }
@@ -3241,12 +3234,12 @@ int NITFDataset::CheckForRSets( const char *pszNITFFilename,
 /*                          IBuildOverviews()                           */
 /************************************************************************/
 
-CPLErr NITFDataset::IBuildOverviews( const char *pszResampling, 
-                                     int nOverviews, int *panOverviewList, 
+CPLErr NITFDataset::IBuildOverviews( const char *pszResampling,
+                                     int nOverviews, int *panOverviewList,
                                      int nListBands, int *panBandList,
-                                     GDALProgressFunc pfnProgress, 
+                                     GDALProgressFunc pfnProgress,
                                      void * pProgressData )
-    
+
 {
 /* -------------------------------------------------------------------- */
 /*      If we have been using RSets we will need to clear them first.   */
@@ -3264,16 +3257,16 @@ CPLErr NITFDataset::IBuildOverviews( const char *pszResampling,
 /*      JP2KAK) we will try and build zero overviews as a way of        */
 /*      tricking it into clearing existing overviews-from-jpeg2000.     */
 /* -------------------------------------------------------------------- */
-    if( poJ2KDataset != NULL 
+    if( poJ2KDataset != NULL
         && !poJ2KDataset->GetMetadataItem( "OVERVIEW_FILE", "OVERVIEWS" ) )
-        poJ2KDataset->IBuildOverviews( pszResampling, 0, NULL, 
-                                       nListBands, panBandList, 
+        poJ2KDataset->BuildOverviews( pszResampling, 0, NULL,
+                                       nListBands, panBandList,
                                        GDALDummyProgress, NULL );
 
 /* -------------------------------------------------------------------- */
 /*      Use the overview manager to build requested overviews.          */
 /* -------------------------------------------------------------------- */
-    CPLErr eErr = GDALPamDataset::IBuildOverviews( pszResampling, 
+    CPLErr eErr = GDALPamDataset::IBuildOverviews( pszResampling,
                                                    nOverviews, panOverviewList,
                                                    nListBands, panBandList,
                                                    pfnProgress, pProgressData );
@@ -3286,13 +3279,13 @@ CPLErr NITFDataset::IBuildOverviews( const char *pszResampling,
     if( poJPEGDataset )
         poSubDS = poJPEGDataset;
 
-    const char *pszOverviewFile = 
+    const char *pszOverviewFile =
         GetMetadataItem( "OVERVIEW_FILE", "OVERVIEWS" );
 
     if( poSubDS && pszOverviewFile != NULL && eErr == CE_None
         && poSubDS->GetMetadataItem( "OVERVIEW_FILE", "OVERVIEWS") == NULL )
     {
-        poSubDS->SetMetadataItem( "OVERVIEW_FILE", 
+        poSubDS->SetMetadataItem( "OVERVIEW_FILE",
                                   pszOverviewFile,
                                   "OVERVIEWS" );
     }
@@ -3311,20 +3304,19 @@ CPLErr NITFDataset::IBuildOverviews( const char *pszResampling,
 int NITFDataset::ScanJPEGQLevel( GUIntBig *pnDataStart )
 
 {
-    GByte abyHeader[100];
-
     if( VSIFSeekL( psFile->fp, *pnDataStart,
                    SEEK_SET ) != 0 )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   "Seek error to jpeg data stream." );
         return 0;
     }
-        
-    if( VSIFReadL( abyHeader, 1, sizeof(abyHeader), psFile->fp ) 
+
+    GByte abyHeader[100];
+    if( VSIFReadL( abyHeader, 1, sizeof(abyHeader), psFile->fp )
         < sizeof(abyHeader) )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   "Read error to jpeg data stream." );
         return 0;
     }
@@ -3334,7 +3326,7 @@ int NITFDataset::ScanJPEGQLevel( GUIntBig *pnDataStart )
 /*      there seems to be some extra junk before the image data stream. */
 /* -------------------------------------------------------------------- */
     GUInt32 nOffset = 0;
-    while( nOffset < sizeof(abyHeader) - 23 
+    while( nOffset < sizeof(abyHeader) - 23
            && (abyHeader[nOffset+0] != 0xff
                || abyHeader[nOffset+1] != 0xd8
                || abyHeader[nOffset+2] != 0xff) )
@@ -3346,8 +3338,9 @@ int NITFDataset::ScanJPEGQLevel( GUIntBig *pnDataStart )
     *pnDataStart += nOffset;
 
     if( nOffset > 0 )
-        CPLDebug( "NITF", 
-                  "JPEG data stream at offset %d from start of data segement, NSIF?", 
+        CPLDebug( "NITF",
+                  "JPEG data stream at offset %d from start of data segment, "
+                  "NSIF?",
                   nOffset );
 
 /* -------------------------------------------------------------------- */
@@ -3366,21 +3359,18 @@ int NITFDataset::ScanJPEGQLevel( GUIntBig *pnDataStart )
 CPLErr NITFDataset::ScanJPEGBlocks()
 
 {
-    int iBlock;
-    GUIntBig nJPEGStart = 
+    GUIntBig nJPEGStart =
         psFile->pasSegmentInfo[psImage->iSegment].nSegmentStart;
-
     nQLevel = ScanJPEGQLevel( &nJPEGStart );
 
 /* -------------------------------------------------------------------- */
 /*      Allocate offset array                                           */
 /* -------------------------------------------------------------------- */
-    panJPEGBlockOffset = (GIntBig *) 
-        VSICalloc(sizeof(GIntBig),
-                  psImage->nBlocksPerRow*psImage->nBlocksPerColumn);
+    panJPEGBlockOffset = reinterpret_cast<GIntBig *>(
+        VSI_CALLOC_VERBOSE(sizeof(GIntBig),
+                  psImage->nBlocksPerRow*psImage->nBlocksPerColumn) );
     if (panJPEGBlockOffset == NULL)
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
         return CE_Failure;
     }
     panJPEGBlockOffset[0] = nJPEGStart;
@@ -3388,10 +3378,10 @@ CPLErr NITFDataset::ScanJPEGBlocks()
     if ( psImage->nBlocksPerRow * psImage->nBlocksPerColumn == 1)
         return CE_None;
 
-    for( iBlock = psImage->nBlocksPerRow * psImage->nBlocksPerColumn - 1;
+    for( int iBlock = psImage->nBlocksPerRow * psImage->nBlocksPerColumn - 1;
          iBlock > 0; iBlock-- )
         panJPEGBlockOffset[iBlock] = -1;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Scan through the whole image data stream identifying all        */
 /*      block boundaries.  Each block starts with 0xFFD8 (SOI).         */
@@ -3408,46 +3398,45 @@ CPLErr NITFDataset::ScanJPEGBlocks()
     while( iSegOffset < iSegSize-1 )
     {
         size_t nReadSize = MIN((size_t)sizeof(abyBlock),(size_t)(iSegSize - iSegOffset));
-        size_t i;
 
-        if( VSIFSeekL( psFile->fp, panJPEGBlockOffset[0] + iSegOffset, 
+        if( VSIFSeekL( psFile->fp, panJPEGBlockOffset[0] + iSegOffset,
                        SEEK_SET ) != 0 )
         {
-            CPLError( CE_Failure, CPLE_FileIO, 
+            CPLError( CE_Failure, CPLE_FileIO,
                       "Seek error to jpeg data stream." );
             return CE_Failure;
         }
-        
+
         if( VSIFReadL( abyBlock, 1, nReadSize, psFile->fp ) < (size_t)nReadSize)
         {
-            CPLError( CE_Failure, CPLE_FileIO, 
+            CPLError( CE_Failure, CPLE_FileIO,
                       "Read error to jpeg data stream." );
             return CE_Failure;
         }
 
-        for( i = 0; i < nReadSize-1; i++ )
+        for( size_t i = 0; i < nReadSize-1; i++ )
         {
             if (ignoreBytes == 0)
             {
                 if( abyBlock[i] == 0xff )
                 {
-                    /* start-of-image marker */ 
+                    /* start-of-image marker */
                     if ( abyBlock[i+1] == 0xd8 )
                     {
-                        panJPEGBlockOffset[iNextBlock++] 
-                             = panJPEGBlockOffset[0] + iSegOffset + i; 
+                        panJPEGBlockOffset[iNextBlock++]
+                             = panJPEGBlockOffset[0] + iSegOffset + i;
 
-                        if( iNextBlock == psImage->nBlocksPerRow*psImage->nBlocksPerColumn) 
+                        if( iNextBlock == psImage->nBlocksPerRow*psImage->nBlocksPerColumn)
                         {
                             return CE_None;
                         }
                     }
-                    /* Skip application-specific data to avoid false positive while detecting */ 
+                    /* Skip application-specific data to avoid false positive while detecting */
                     /* start-of-image markers (#2927). The size of the application data is */
                     /* found in the two following bytes */
                     /* We need this complex mechanism of ignoreBytes for dealing with */
                     /* application data crossing several abyBlock ... */
-                    else if ( abyBlock[i+1] >= 0xe0 && abyBlock[i+1] < 0xf0 ) 
+                    else if ( abyBlock[i+1] >= 0xe0 && abyBlock[i+1] < 0xf0 )
                     {
                         ignoreBytes = -2;
                     }
@@ -3495,16 +3484,14 @@ CPLErr NITFDataset::ReadJPEGBlock( int iBlockX, int iBlockY )
 /*      When a data mask subheader is present, we don't need to scan    */
 /*      the whole file. We just use the psImage->panBlockStart table    */
 /* -------------------------------------------------------------------- */
-            panJPEGBlockOffset = (GIntBig *) 
-                VSICalloc(sizeof(GIntBig),
-                        psImage->nBlocksPerRow*psImage->nBlocksPerColumn);
+            panJPEGBlockOffset = reinterpret_cast<GIntBig *>(
+                VSI_CALLOC_VERBOSE(sizeof(GIntBig),
+                          psImage->nBlocksPerRow*psImage->nBlocksPerColumn) );
             if (panJPEGBlockOffset == NULL)
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
                 return CE_Failure;
             }
-            int i;
-            for (i=0;i< psImage->nBlocksPerRow*psImage->nBlocksPerColumn;i++)
+            for ( int i=0;i< psImage->nBlocksPerRow*psImage->nBlocksPerColumn;i++)
             {
                 panJPEGBlockOffset[i] = psImage->panBlockStart[i];
                 if (panJPEGBlockOffset[i] != -1 && panJPEGBlockOffset[i] != 0xffffffff)
@@ -3533,19 +3520,18 @@ CPLErr NITFDataset::ReadJPEGBlock( int iBlockX, int iBlockY )
                 return eErr;
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*    Allocate image data block (where the uncompressed image will go)  */
 /* -------------------------------------------------------------------- */
     if( pabyJPEGBlock == NULL )
     {
         /* Allocate enough memory to hold 12bit JPEG data */
-        pabyJPEGBlock = (GByte *) 
-            VSICalloc(psImage->nBands,
-                      psImage->nBlockWidth * psImage->nBlockHeight * 2);
+        pabyJPEGBlock = reinterpret_cast<GByte *>(
+            VSI_CALLOC_VERBOSE(psImage->nBands,
+                      psImage->nBlockWidth * psImage->nBlockHeight * 2) );
         if (pabyJPEGBlock == NULL)
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
             return CE_Failure;
         }
     }
@@ -3554,10 +3540,7 @@ CPLErr NITFDataset::ReadJPEGBlock( int iBlockX, int iBlockY )
 /* -------------------------------------------------------------------- */
 /*      Read JPEG Chunk.                                                */
 /* -------------------------------------------------------------------- */
-    CPLString osFilename;
-    int iBlock = iBlockX + iBlockY * psImage->nBlocksPerRow;
-    GDALDataset *poDS;
-    int anBands[3] = { 1, 2, 3 };
+    const int iBlock = iBlockX + iBlockY * psImage->nBlocksPerRow;
 
     if (panJPEGBlockOffset[iBlock] == -1 || panJPEGBlockOffset[iBlock] == 0xffffffff)
     {
@@ -3565,12 +3548,14 @@ CPLErr NITFDataset::ReadJPEGBlock( int iBlockX, int iBlockY )
         return CE_None;
     }
 
-    osFilename.Printf( "JPEG_SUBFILE:Q%d," CPL_FRMT_GIB ",%d,%s", 
+    CPLString osFilename;
+    osFilename.Printf( "JPEG_SUBFILE:Q%d," CPL_FRMT_GIB ",%d,%s",
                        nQLevel,
-                       panJPEGBlockOffset[iBlock], 0, 
+                       panJPEGBlockOffset[iBlock], 0,
                        osNITFFilename.c_str() );
 
-    poDS = (GDALDataset *) GDALOpen( osFilename, GA_ReadOnly );
+    GDALDataset *poDS = reinterpret_cast<GDALDataset *>(
+        GDALOpen( osFilename, GA_ReadOnly ) );
     if( poDS == NULL )
         return CE_Failure;
 
@@ -3578,7 +3563,7 @@ CPLErr NITFDataset::ReadJPEGBlock( int iBlockX, int iBlockY )
         || poDS->GetRasterYSize() != psImage->nBlockHeight )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "JPEG block %d not same size as NITF blocksize.", 
+                  "JPEG block %d not same size as NITF blocksize.",
                   iBlock );
         delete poDS;
         return CE_Failure;
@@ -3587,7 +3572,7 @@ CPLErr NITFDataset::ReadJPEGBlock( int iBlockX, int iBlockY )
     if( poDS->GetRasterCount() < psImage->nBands )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "JPEG block %d has not enough bands.", 
+                  "JPEG block %d has not enough bands.",
                   iBlock );
         delete poDS;
         return CE_Failure;
@@ -3603,10 +3588,11 @@ CPLErr NITFDataset::ReadJPEGBlock( int iBlockX, int iBlockY )
         return CE_Failure;
     }
 
-    eErr = poDS->RasterIO( GF_Read, 
-                           0, 0, 
+    int anBands[3] = { 1, 2, 3 };
+    eErr = poDS->RasterIO( GF_Read,
+                           0, 0,
                            psImage->nBlockWidth, psImage->nBlockHeight,
-                           pabyJPEGBlock, 
+                           pabyJPEGBlock,
                            psImage->nBlockWidth, psImage->nBlockHeight,
                            GetRasterBand(1)->GetRasterDataType(), psImage->nBands, anBands,
                            0, 0, 0, NULL );
@@ -3657,13 +3643,13 @@ char **NITFDataset::AddFile(char **papszFileList, const char* EXTENSION, const c
     CPLString osTarget = CPLResetExtension( osNITFFilename, EXTENSION );
     if( oOvManager.GetSiblingFiles() != NULL )
     {
-        if( CSLFindStringCaseSensitive( oOvManager.GetSiblingFiles(), 
+        if( CSLFindStringCaseSensitive( oOvManager.GetSiblingFiles(),
                            CPLGetFilename(osTarget) ) >= 0 )
             papszFileList = CSLAddString( papszFileList, osTarget );
         else
         {
             osTarget = CPLResetExtension( osNITFFilename, extension );
-            if( CSLFindStringCaseSensitive( oOvManager.GetSiblingFiles(), 
+            if( CSLFindStringCaseSensitive( oOvManager.GetSiblingFiles(),
                            CPLGetFilename(osTarget) ) >= 0 )
                 papszFileList = CSLAddString( papszFileList, osTarget );
         }
@@ -3712,7 +3698,7 @@ static const char *GDALToNITFDataType( GDALDataType eType )
 
       case GDT_CInt16:
       case GDT_CInt32:
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "NITF format does not support complex integer data." );
         return NULL;
 
@@ -3722,7 +3708,7 @@ static const char *GDALToNITFDataType( GDALDataType eType )
 
       default:
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unsupported raster pixel type (%s).", 
+                  "Unsupported raster pixel type (%s).",
                   GDALGetDataTypeName(eType) );
         return NULL;
     }
@@ -3740,20 +3726,18 @@ static const char *GDALToNITFDataType( GDALDataType eType )
 static char **NITFJP2ECWOptions( char **papszOptions )
 
 {
-    int i;
-    char** papszJP2Options = NULL;
-    
-    papszJP2Options = CSLAddString(papszJP2Options, "PROFILE=NPJE");
+    char** papszJP2Options
+        = CSLAddString(NULL, "PROFILE=NPJE");
     papszJP2Options = CSLAddString(papszJP2Options, "CODESTREAM_ONLY=TRUE");
-    
-    for( i = 0; papszOptions != NULL && papszOptions[i] != NULL; i++ )
+
+    for( int i = 0; papszOptions != NULL && papszOptions[i] != NULL; i++ )
     {
-        if( EQUALN(papszOptions[i],"PROFILE=",8) )
+        if( STARTS_WITH_CI(papszOptions[i], "PROFILE=") )
         {
             CPLFree(papszJP2Options[0]);
             papszJP2Options[0] = CPLStrdup(papszOptions[i]);
         }
-        else if( EQUALN(papszOptions[i],"TARGET=",7) )
+        else if( STARTS_WITH_CI(papszOptions[i], "TARGET=") )
             papszJP2Options = CSLAddString(papszJP2Options, papszOptions[i]);
     }
 
@@ -3769,24 +3753,23 @@ static char **NITFJP2ECWOptions( char **papszOptions )
 static char **NITFJP2KAKOptions( char **papszOptions )
 
 {
-    int i;
     char** papszKAKOptions = NULL;
-    
-    for( i = 0; papszOptions != NULL && papszOptions[i] != NULL; i++ )
+
+    for( int i = 0; papszOptions != NULL && papszOptions[i] != NULL; i++ )
     {
-       if(      EQUALN(papszOptions[i],"QUALITY=", 8) )
+       if(      STARTS_WITH_CI(papszOptions[i], "QUALITY=") )
           papszKAKOptions = CSLAddString(papszKAKOptions, papszOptions[i]);
-       else if (EQUALN(papszOptions[i],"BLOCKXSIZE=", 11) )
+       else if (STARTS_WITH_CI(papszOptions[i], "BLOCKXSIZE=") )
           papszKAKOptions = CSLAddString(papszKAKOptions, papszOptions[i]);
-       else if (EQUALN(papszOptions[i],"BLOCKYSIZE=", 11) )
+       else if (STARTS_WITH_CI(papszOptions[i], "BLOCKYSIZE=") )
           papszKAKOptions = CSLAddString(papszKAKOptions, papszOptions[i]);
-       else if (EQUALN(papszOptions[i],"GMLPJ2=", 7) )
+       else if (STARTS_WITH_CI(papszOptions[i], "GMLPJ2=") )
           papszKAKOptions = CSLAddString(papszKAKOptions, papszOptions[i]);
-       else if (EQUALN(papszOptions[i],"GeoJP2=", 7) )
+       else if (STARTS_WITH_CI(papszOptions[i], "GeoJP2=") )
           papszKAKOptions = CSLAddString(papszKAKOptions, papszOptions[i]);
-       else if (EQUALN(papszOptions[i],"LAYERS=", 7) )
+       else if (STARTS_WITH_CI(papszOptions[i], "LAYERS=") )
           papszKAKOptions = CSLAddString(papszKAKOptions, papszOptions[i]);
-       else if (EQUALN(papszOptions[i],"ROI=", 4) )
+       else if (STARTS_WITH_CI(papszOptions[i], "ROI=") )
           papszKAKOptions = CSLAddString(papszKAKOptions, papszOptions[i]);
     }
 
@@ -3809,7 +3792,6 @@ static char** NITFExtractTEXTAndCGMCreationOption( GDALDataset* poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Prepare for text segments.                                      */
 /* -------------------------------------------------------------------- */
-    int iOpt, nNUMT = 0;
     char **papszTextMD = CSLFetchNameValueMultiple (papszOptions, "TEXT");
     // Notice: CSLFetchNameValueMultiple remove the leading "TEXT=" when
     // returning the list, which is what we want.
@@ -3817,16 +3799,17 @@ static char** NITFExtractTEXTAndCGMCreationOption( GDALDataset* poSrcDS,
     // Use TEXT information from original image if no creation option is passed in.
     if (poSrcDS != NULL && papszTextMD == NULL)
     {
-        // Read CGM adata from original image, duplicate the list becuase
+        // Read CGM adata from original image, duplicate the list because
         // we frees papszCgmMD at end of the function.
         papszTextMD = CSLDuplicate( poSrcDS->GetMetadata( "TEXT" ));
     }
 
-    for( iOpt = 0; 
-         papszTextMD != NULL && papszTextMD[iOpt] != NULL; 
+    int nNUMT = 0;
+    for( int iOpt = 0;
+         papszTextMD != NULL && papszTextMD[iOpt] != NULL;
          iOpt++ )
     {
-        if( !EQUALN(papszTextMD[iOpt],"DATA_",5) )
+        if( !STARTS_WITH_CI(papszTextMD[iOpt], "DATA_") )
             continue;
 
         nNUMT++;
@@ -3834,17 +3817,14 @@ static char** NITFExtractTEXTAndCGMCreationOption( GDALDataset* poSrcDS,
 
     if( nNUMT > 0 )
     {
-        papszFullOptions = CSLAddString( papszFullOptions, 
-                                         CPLString().Printf( "NUMT=%d", 
+        papszFullOptions = CSLAddString( papszFullOptions,
+                                         CPLString().Printf( "NUMT=%d",
                                                              nNUMT ) );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Prepare for CGM segments.                                       */
 /* -------------------------------------------------------------------- */
-    const char *pszNUMS; // graphic segment option string
-    int nNUMS = 0;
-
     char **papszCgmMD = CSLFetchNameValueMultiple (papszOptions, "CGM");
     // Notice: CSLFetchNameValueMultiple remove the leading "CGM=" when
     // returning the list, which is what we want.
@@ -3852,12 +3832,14 @@ static char** NITFExtractTEXTAndCGMCreationOption( GDALDataset* poSrcDS,
     // Use CGM information from original image if no creation option is passed in.
     if (poSrcDS != NULL && papszCgmMD == NULL)
     {
-        // Read CGM adata from original image, duplicate the list becuase
+        // Read CGM adata from original image, duplicate the list because
         // we frees papszCgmMD at end of the function.
         papszCgmMD = CSLDuplicate( poSrcDS->GetMetadata( "CGM" ));
     }
 
     // Set NUMS based on the number of segments
+    const char *pszNUMS; // graphic segment option string
+    int nNUMS = 0;
     if (papszCgmMD != NULL)
     {
         pszNUMS = CSLFetchNameValue(papszCgmMD, "SEGMENT_COUNT");
@@ -3885,11 +3867,11 @@ NITFDataset::NITFDatasetCreate( const char *pszFilename, int nXSize, int nYSize,
 
 {
     const char *pszPVType = GDALToNITFDataType( eType );
-    const char *pszIC = CSLFetchNameValue( papszOptions, "IC" );
-
     if( pszPVType == NULL )
         return NULL;
 
+    const char *pszIC = CSLFetchNameValue( papszOptions, "IC" );
+
 /* -------------------------------------------------------------------- */
 /*      We disallow any IC value except NC when creating this way.      */
 /* -------------------------------------------------------------------- */
@@ -3897,15 +3879,15 @@ NITFDataset::NITFDatasetCreate( const char *pszFilename, int nXSize, int nYSize,
 
     if( pszIC != NULL && EQUAL(pszIC,"C8") )
     {
-        int bHasCreate = FALSE;
-       
+        bool bHasCreate = false;
+
         poJ2KDriver = GetGDALDriverManager()->GetDriverByName( "JP2ECW" );
         if( poJ2KDriver != NULL )
-            bHasCreate = poJ2KDriver->GetMetadataItem( GDAL_DCAP_CREATE, 
+            bHasCreate = poJ2KDriver->GetMetadataItem( GDAL_DCAP_CREATE,
                                                        NULL ) != NULL;
         if( !bHasCreate )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Unable to create JPEG2000 encoded NITF files.  The\n"
                       "JP2ECW driver is unavailable, or missing Create support." );
            return NULL;
@@ -3914,9 +3896,9 @@ NITFDataset::NITFDatasetCreate( const char *pszFilename, int nXSize, int nYSize,
 
     else if( pszIC != NULL && !EQUAL(pszIC,"NC") )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unsupported compression (IC=%s) used in direct\n"
-                  "NITF File creation", 
+                  "NITF File creation",
                   pszIC );
         return NULL;
     }
@@ -3927,7 +3909,6 @@ NITFDataset::NITFDatasetCreate( const char *pszFilename, int nXSize, int nYSize,
         CPLError( CE_Warning, CPLE_AppDefined,
                   "SDE_TRE creation option ignored by Create() method (only valid in CreateCopy())" );
     }
-    
 
 /* -------------------------------------------------------------------- */
 /*      Prepare for text and CGM segments.                              */
@@ -3943,8 +3924,8 @@ NITFDataset::NITFDatasetCreate( const char *pszFilename, int nXSize, int nYSize,
 /*      Create the file.                                                */
 /* -------------------------------------------------------------------- */
 
-    if( !NITFCreate( pszFilename, nXSize, nYSize, nBands, 
-                     GDALGetDataTypeSize( eType ), pszPVType, 
+    if( !NITFCreate( pszFilename, nXSize, nYSize, nBands,
+                     GDALGetDataTypeSize( eType ), pszPVType,
                      papszFullOptions ) )
     {
         CSLDestroy(papszTextMD);
@@ -3978,8 +3959,8 @@ NITFDataset::NITFDatasetCreate( const char *pszFilename, int nXSize, int nYSize,
         NITFClose( psFile );
 
         char** papszJP2Options = NITFJP2ECWOptions(papszOptions);
-        poWritableJ2KDataset = 
-            poJ2KDriver->Create( osDSName, nXSize, nYSize, nBands, eType, 
+        poWritableJ2KDataset =
+            poJ2KDriver->Create( osDSName, nXSize, nYSize, nBands, eType,
                                  papszJP2Options );
         CSLDestroy(papszJP2Options);
 
@@ -3995,8 +3976,8 @@ NITFDataset::NITFDatasetCreate( const char *pszFilename, int nXSize, int nYSize,
 /*      Open the dataset in update mode.                                */
 /* -------------------------------------------------------------------- */
     GDALOpenInfo oOpenInfo( pszFilename, GA_Update );
-    NITFDataset* poDS = (NITFDataset*)
-            NITFDataset::OpenInternal(&oOpenInfo, poWritableJ2KDataset, TRUE);
+    NITFDataset* poDS = reinterpret_cast<NITFDataset *>(
+        NITFDataset::OpenInternal(&oOpenInfo, poWritableJ2KDataset, TRUE) );
     if (poDS)
     {
         poDS->papszTextMDToWrite = papszTextMD;
@@ -4015,20 +3996,14 @@ NITFDataset::NITFDatasetCreate( const char *pszFilename, int nXSize, int nYSize,
 /************************************************************************/
 
 GDALDataset *
-NITFDataset::NITFCreateCopy( 
+NITFDataset::NITFCreateCopy(
     const char *pszFilename, GDALDataset *poSrcDS,
-    int bStrict, char **papszOptions, 
+    int bStrict, char **papszOptions,
     GDALProgressFunc pfnProgress, void * pProgressData )
 
 {
-    GDALDataType eType;
-    GDALRasterBand *poBand1;
-    int   bJPEG2000 = FALSE;
-    int   bJPEG = FALSE;
-    NITFDataset *poDstDS = NULL;
-    GDALDriver *poJ2KDriver = NULL;
 
-    int  nBands = poSrcDS->GetRasterCount();
+    int nBands = poSrcDS->GetRasterCount();
     if( nBands == 0 )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
@@ -4036,7 +4011,7 @@ NITFDataset::NITFCreateCopy(
         return NULL;
     }
 
-    poBand1 = poSrcDS->GetRasterBand(1);
+    GDALRasterBand *poBand1 = poSrcDS->GetRasterBand(1);
     if( poBand1 == NULL )
     {
         return NULL;
@@ -4045,6 +4020,10 @@ NITFDataset::NITFCreateCopy(
 /* -------------------------------------------------------------------- */
 /*      Only allow supported compression values.                        */
 /* -------------------------------------------------------------------- */
+    bool bJPEG2000 = false;
+    bool bJPEG = false;
+    GDALDriver *poJ2KDriver = NULL;
+
     const char* pszIC = CSLFetchNameValue( papszOptions, "IC" );
     if( pszIC != NULL )
     {
@@ -4052,25 +4031,25 @@ NITFDataset::NITFCreateCopy(
             /* ok */;
         else if( EQUAL(pszIC,"C8") )
         {
-            poJ2KDriver = 
+            poJ2KDriver =
                 GetGDALDriverManager()->GetDriverByName( "JP2ECW" );
-            if( poJ2KDriver == NULL || 
+            if( poJ2KDriver == NULL ||
                 poJ2KDriver->GetMetadataItem( GDAL_DCAP_CREATECOPY, NULL ) == NULL )
             {
                 /* Try with  JP2KAK as an alternate driver */
-                poJ2KDriver = 
+                poJ2KDriver =
                     GetGDALDriverManager()->GetDriverByName(  "JP2KAK" );
             }
             if( poJ2KDriver == NULL )
             {
                 /* Try with Jasper as an alternate driver */
-                poJ2KDriver = 
+                poJ2KDriver =
                     GetGDALDriverManager()->GetDriverByName( "JPEG2000" );
             }
             if( poJ2KDriver == NULL )
             {
-                CPLError( 
-                    CE_Failure, CPLE_AppDefined, 
+                CPLError(
+                    CE_Failure, CPLE_AppDefined,
                     "Unable to write JPEG2000 compressed NITF file.\n"
                     "No 'subfile' JPEG2000 write supporting drivers are\n"
                     "configured." );
@@ -4082,8 +4061,8 @@ NITFDataset::NITFCreateCopy(
         {
             bJPEG = TRUE;
 #ifndef JPEG_SUPPORTED
-            CPLError( 
-                CE_Failure, CPLE_AppDefined, 
+            CPLError(
+                CE_Failure, CPLE_AppDefined,
                 "Unable to write JPEG compressed NITF file.\n"
                 "Libjpeg is not configured into build." );
             return NULL;
@@ -4091,7 +4070,7 @@ NITFDataset::NITFCreateCopy(
         }
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Only IC=NC (uncompressed), IC=C3/M3 (JPEG) and IC=C8 (JPEG2000)\n"
                       "allowed with NITF CreateCopy method." );
             return NULL;
@@ -4103,7 +4082,7 @@ NITFDataset::NITFCreateCopy(
 /*      NITF, so map that to complex float if we aren't in strict       */
 /*      mode.                                                           */
 /* -------------------------------------------------------------------- */
-    eType = poBand1->GetRasterDataType();
+    GDALDataType eType = poBand1->GetRasterDataType();
     if( !bStrict && (eType == GDT_CInt16 || eType == GDT_CInt32) )
         eType = GDT_CFloat32;
 
@@ -4122,19 +4101,18 @@ NITFDataset::NITFCreateCopy(
 /*      that seem useful.                                               */
 /* -------------------------------------------------------------------- */
     char **papszSrcMD = poSrcDS->GetMetadata();
-    int iMD;
 
-    for( iMD = 0; papszSrcMD && papszSrcMD[iMD]; iMD++ )
+    for( int iMD = 0; papszSrcMD && papszSrcMD[iMD]; iMD++ )
     {
-        if( EQUALN(papszSrcMD[iMD],"NITF_BLOCKA",11) 
-            || EQUALN(papszSrcMD[iMD],"NITF_FHDR",9) )
+        if( STARTS_WITH_CI(papszSrcMD[iMD], "NITF_BLOCKA")
+            || STARTS_WITH_CI(papszSrcMD[iMD], "NITF_FHDR") )
         {
             char *pszName = NULL;
-            const char *pszValue = CPLParseNameValue( papszSrcMD[iMD], 
+            const char *pszValue = CPLParseNameValue( papszSrcMD[iMD],
                                                       &pszName );
             if( pszName != NULL &&
                 CSLFetchNameValue( papszFullOptions, pszName+5 ) == NULL )
-                papszFullOptions = 
+                papszFullOptions =
                     CSLSetNameValue( papszFullOptions, pszName+5, pszValue );
             CPLFree(pszName);
         }
@@ -4145,13 +4123,13 @@ NITFDataset::NITFCreateCopy(
 /* -------------------------------------------------------------------- */
     papszSrcMD = poSrcDS->GetMetadata( "TRE" );
 
-    for( iMD = 0; papszSrcMD && papszSrcMD[iMD]; iMD++ )
+    for( int iMD = 0; papszSrcMD && papszSrcMD[iMD]; iMD++ )
     {
         CPLString osTRE;
 
-        if (EQUALN(papszSrcMD[iMD], "RPFHDR", 6) ||
-            EQUALN(papszSrcMD[iMD], "RPFIMG", 6) ||
-            EQUALN(papszSrcMD[iMD], "RPFDES", 6))
+        if (STARTS_WITH_CI(papszSrcMD[iMD], "RPFHDR") ||
+            STARTS_WITH_CI(papszSrcMD[iMD], "RPFIMG") ||
+            STARTS_WITH_CI(papszSrcMD[iMD], "RPFDES"))
         {
             /* Do not copy RPF TRE. They contain absolute offsets */
             /* No chance that they make sense in the new NITF file */
@@ -4176,42 +4154,44 @@ NITFDataset::NITFCreateCopy(
              poSrcDS->GetRasterBand(3)->GetColorInterpretation() == GCI_BlueBand)
         {
             if( bJPEG )
-                papszFullOptions = 
+                papszFullOptions =
                     CSLSetNameValue( papszFullOptions, "IREP", "YCbCr601" );
             else
-                papszFullOptions = 
+                papszFullOptions =
                     CSLSetNameValue( papszFullOptions, "IREP", "RGB" );
         }
         else if( poSrcDS->GetRasterCount() == 1 && eType == GDT_Byte
                  && poBand1->GetColorTable() != NULL )
         {
-            papszFullOptions = 
+            papszFullOptions =
                 CSLSetNameValue( papszFullOptions, "IREP", "RGB/LUT" );
-            papszFullOptions = 
-                CSLSetNameValue( papszFullOptions, "LUT_SIZE", 
+            papszFullOptions =
+                CSLSetNameValue( papszFullOptions, "LUT_SIZE",
                                  CPLString().Printf(
                                      "%d", poBand1->GetColorTable()->GetColorEntryCount()) );
         }
         else if( GDALDataTypeIsComplex(eType) )
-            papszFullOptions = 
+            papszFullOptions =
                 CSLSetNameValue( papszFullOptions, "IREP", "NODISPLY" );
-        
+
         else
-            papszFullOptions = 
+            papszFullOptions =
                 CSLSetNameValue( papszFullOptions, "IREP", "MONO" );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Do we have lat/long georeferencing information?                 */
 /* -------------------------------------------------------------------- */
-    double adfGeoTransform[6];
-    int    bWriteGeoTransform = FALSE;
-    int    bWriteGCPs = FALSE;
-    int    bNorth, nZone = 0;
-    OGRSpatialReference oSRS, oSRS_WGS84;
-    char *pszWKT = (char *) poSrcDS->GetProjectionRef();
+    char *pszWKT = const_cast<char *>( poSrcDS->GetProjectionRef() );
     if( pszWKT == NULL || pszWKT[0] == '\0' )
-        pszWKT = (char *) poSrcDS->GetGCPProjection();
+        pszWKT = const_cast<char *>( poSrcDS->GetGCPProjection() );
+
+    double adfGeoTransform[6];
+    bool bWriteGeoTransform = false;
+    bool bWriteGCPs = false;
+    int nZone = 0;
+    OGRSpatialReference oSRS;
+    OGRSpatialReference oSRS_WGS84;
 
     if( pszWKT != NULL && pszWKT[0] != '\0' )
     {
@@ -4238,7 +4218,7 @@ NITFDataset::NITFCreateCopy(
 /*      Should we write DIGEST Spatial Data Extension TRE ?             */
 /* -------------------------------------------------------------------- */
         const char* pszSDE_TRE = CSLFetchNameValue(papszFullOptions, "SDE_TRE");
-        int bSDE_TRE = pszSDE_TRE && CSLTestBoolean(pszSDE_TRE);
+        const bool bSDE_TRE = pszSDE_TRE && CPLTestBool(pszSDE_TRE);
         if (bSDE_TRE)
         {
             if( oSRS.IsGeographic() && oSRS.GetPrimeMeridian() == 0.0
@@ -4259,29 +4239,29 @@ NITFDataset::NITFCreateCopy(
                     /* Code a bit below will complain with other ICORDS value */
                 }
 
-                if (CSLPartialFindString(papszFullOptions, "TRE=GEOLOB=") != - 1)
+                if ( CSLPartialFindString(papszFullOptions, "TRE=GEOLOB=")
+                     != - 1 )
                 {
-                    CPLDebug("NITF", "GEOLOB TRE was explicitly defined before. "
-                             "Overriding it with current georefencing info.");
+                    CPLDebug( "NITF", "GEOLOB TRE was explicitly defined "
+                              "before.  Overriding it with current "
+                              "georeferencing info." );
                 }
 
                 /* Structure of SDE TRE documented here */
-                /*http://www.gwg.nga.mil/ntb/baseline/docs/digest/part2_annex_d.pdf */
+                // http://www.gwg.nga.mil/ntb/baseline/docs/digest/part2_annex_d.pdf
 
 /* -------------------------------------------------------------------- */
 /*      Write GEOLOB TRE                                                */
 /* -------------------------------------------------------------------- */
                 char szGEOLOB[48+1];
-                char* pszGEOLOB = szGEOLOB;
-                double dfARV = 360.0 / adfGeoTransform[1];
-                double dfBRV = 360.0 / -adfGeoTransform[5];
-                double dfLSO = adfGeoTransform[0];
-                double dfPSO = adfGeoTransform[3];
-                sprintf(pszGEOLOB, "%09d", (int)(dfARV + 0.5)); pszGEOLOB += 9;
-                sprintf(pszGEOLOB, "%09d", (int)(dfBRV + 0.5)); pszGEOLOB += 9;
-                sprintf(pszGEOLOB, "%#+015.10f", dfLSO); pszGEOLOB += 15;
-                sprintf(pszGEOLOB, "%#+015.10f", dfPSO); pszGEOLOB += 15;
-                CPLAssert(pszGEOLOB == szGEOLOB + 48);
+                const double dfARV = 360.0 / adfGeoTransform[1];
+                const double dfBRV = 360.0 / -adfGeoTransform[5];
+                const double dfLSO = adfGeoTransform[0];
+                const double dfPSO = adfGeoTransform[3];
+                snprintf(szGEOLOB, sizeof(szGEOLOB), "%09d", static_cast<int>(dfARV + 0.5));
+                snprintf(szGEOLOB + 9, sizeof(szGEOLOB) - (9), "%09d", static_cast<int>(dfBRV + 0.5));
+                snprintf(szGEOLOB + 9+9, sizeof(szGEOLOB) - (9+9), "%#+015.10f", dfLSO);
+                snprintf(szGEOLOB + 9+9+15, sizeof(szGEOLOB) - (9+9+15), "%#+015.10f", dfPSO);
 
                 CPLString osGEOLOB("TRE=GEOLOB=");
                 osGEOLOB += szGEOLOB;
@@ -4331,6 +4311,8 @@ NITFDataset::NITFCreateCopy(
                 if (bStrict)
                 {
                     CSLDestroy(papszFullOptions);
+                    CSLDestroy(papszCgmMD);
+                    CSLDestroy(papszTextMD);
                     return NULL;
                 }
             }
@@ -4339,11 +4321,12 @@ NITFDataset::NITFCreateCopy(
         bWriteGeoTransform = ( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None );
         bWriteGCPs = ( !bWriteGeoTransform && poSrcDS->GetGCPCount() == 4 );
 
+        int bNorth;
         if( oSRS.IsGeographic() && oSRS.GetPrimeMeridian() == 0.0 )
         {
             if (pszICORDS == NULL)
             {
-                papszFullOptions = 
+                papszFullOptions =
                     CSLSetNameValue( papszFullOptions, "ICORDS", "G" );
             }
             else if (EQUAL(pszICORDS, "G") || EQUAL(pszICORDS, "D"))
@@ -4358,9 +4341,11 @@ NITFDataset::NITFCreateCopy(
                 if (bStrict)
                 {
                     CSLDestroy(papszFullOptions);
+                    CSLDestroy(papszCgmMD);
+                    CSLDestroy(papszTextMD);
                     return NULL;
                 }
-                papszFullOptions = 
+                papszFullOptions =
                     CSLSetNameValue( papszFullOptions, "ICORDS", "G" );
             }
         }
@@ -4368,10 +4353,10 @@ NITFDataset::NITFCreateCopy(
         else if( oSRS.GetUTMZone( &bNorth ) > 0 )
         {
             if( bNorth )
-                papszFullOptions = 
+                papszFullOptions =
                     CSLSetNameValue( papszFullOptions, "ICORDS", "N" );
             else
-                papszFullOptions = 
+                papszFullOptions =
                     CSLSetNameValue( papszFullOptions, "ICORDS", "S" );
 
             nZone = oSRS.GetUTMZone( NULL );
@@ -4393,8 +4378,8 @@ NITFDataset::NITFCreateCopy(
 /* -------------------------------------------------------------------- */
 /*      Create the output file.                                         */
 /* -------------------------------------------------------------------- */
-    int nXSize = poSrcDS->GetRasterXSize();
-    int nYSize = poSrcDS->GetRasterYSize();
+    const int nXSize = poSrcDS->GetRasterXSize();
+    const int nYSize = poSrcDS->GetRasterYSize();
     const char *pszPVType = GDALToNITFDataType( eType );
 
     if( pszPVType == NULL )
@@ -4406,7 +4391,7 @@ NITFDataset::NITFCreateCopy(
     }
 
     if (!NITFCreate( pszFilename, nXSize, nYSize, poSrcDS->GetRasterCount(),
-                GDALGetDataTypeSize( eType ), pszPVType, 
+                GDALGetDataTypeSize( eType ), pszPVType,
                 papszFullOptions ))
     {
         CSLDestroy( papszFullOptions );
@@ -4422,6 +4407,8 @@ NITFDataset::NITFCreateCopy(
 /*      JPEG2000 case.  We need to write the data through a J2K         */
 /*      driver in pixel interleaved form.                               */
 /* ==================================================================== */
+    NITFDataset *poDstDS = NULL;
+
     if( bJPEG2000 )
     {
         NITFFile *psFile = NITFOpen( pszFilename, TRUE );
@@ -4432,20 +4419,20 @@ NITFDataset::NITFCreateCopy(
             return NULL;
         }
 
-        GDALDataset *poJ2KDataset = NULL;
         GUIntBig nImageOffset = psFile->pasSegmentInfo[0].nSegmentStart;
-        CPLString osDSName;
 
         NITFClose( psFile );
 
-        osDSName.Printf( "/vsisubfile/" CPL_FRMT_GUIB "_%d,%s", 
+        CPLString osDSName;
+        osDSName.Printf( "/vsisubfile/" CPL_FRMT_GUIB "_%d,%s",
                          nImageOffset, -1,
                          pszFilename );
-                             
+
+        GDALDataset *poJ2KDataset = NULL;
         if (EQUAL(poJ2KDriver->GetDescription(), "JP2ECW"))
         {
             char** papszJP2Options = NITFJP2ECWOptions(papszOptions);
-            poJ2KDataset = 
+            poJ2KDataset =
                 poJ2KDriver->CreateCopy( osDSName, poSrcDS, FALSE,
                                          papszJP2Options,
                                          pfnProgress, pProgressData );
@@ -4454,21 +4441,20 @@ NITFDataset::NITFCreateCopy(
         else if (EQUAL(poJ2KDriver->GetDescription(), "JP2KAK"))
         {
            char** papszKAKOptions = NITFJP2KAKOptions(papszOptions);
-            poJ2KDataset = 
+            poJ2KDataset =
                 poJ2KDriver->CreateCopy( osDSName, poSrcDS, FALSE,
                                          papszKAKOptions,
                                          pfnProgress, pProgressData );
             CSLDestroy(papszKAKOptions);
-            
         }
         else
         {
             /* Jasper case */
             const char* apszOptions[] = { "FORMAT=JPC", NULL };
-            poJ2KDataset = 
-                poJ2KDriver->CreateCopy( osDSName, poSrcDS, FALSE,
-                                         (char **)apszOptions,
-                                         pfnProgress, pProgressData );
+            poJ2KDataset = poJ2KDriver->CreateCopy(
+                osDSName, poSrcDS, FALSE,
+                const_cast<char **>( apszOptions ),
+                pfnProgress, pProgressData );
         }
         if( poJ2KDataset == NULL )
         {
@@ -4481,15 +4467,21 @@ NITFDataset::NITFCreateCopy(
 
         // Now we need to figure out the actual length of the file
         // and correct the image segment size information.
-        GIntBig nPixelCount = nXSize * ((GIntBig) nYSize) * 
+        GIntBig nPixelCount = nXSize * ((GIntBig) nYSize) *
             poSrcDS->GetRasterCount();
 
-        NITFPatchImageLength( pszFilename, nImageOffset, nPixelCount, "C8" );
-        NITFWriteCGMSegments( pszFilename, papszCgmMD );
-        NITFWriteTextSegments( pszFilename, papszTextMD );
+        bool bOK = NITFPatchImageLength( pszFilename, nImageOffset, nPixelCount, "C8" );
+        bOK &= NITFWriteCGMSegments( pszFilename, papszCgmMD );
+        bOK &= NITFWriteTextSegments( pszFilename, papszTextMD );
+        if( !bOK )
+        {
+            CSLDestroy(papszCgmMD);
+            CSLDestroy(papszTextMD);
+            return NULL;
+        }
 
         GDALOpenInfo oOpenInfo( pszFilename, GA_Update );
-        poDstDS = (NITFDataset *) Open( &oOpenInfo );
+        poDstDS = reinterpret_cast<NITFDataset *>( Open( &oOpenInfo ) );
 
         if( poDstDS == NULL )
         {
@@ -4513,13 +4505,12 @@ NITFDataset::NITFCreateCopy(
             return NULL;
         }
         GUIntBig nImageOffset = psFile->pasSegmentInfo[0].nSegmentStart;
-        int bSuccess;
-        
-        bSuccess = 
+
+        const bool bSuccess =
             NITFWriteJPEGImage( poSrcDS, psFile->fp, nImageOffset,
                                 papszOptions,
                                 pfnProgress, pProgressData );
-        
+
         if( !bSuccess )
         {
             NITFClose( psFile );
@@ -4530,19 +4521,25 @@ NITFDataset::NITFCreateCopy(
 
         // Now we need to figure out the actual length of the file
         // and correct the image segment size information.
-        GIntBig nPixelCount = nXSize * ((GIntBig) nYSize) * 
+        GIntBig nPixelCount = nXSize * ((GIntBig) nYSize) *
             poSrcDS->GetRasterCount();
 
         NITFClose( psFile );
 
-        NITFPatchImageLength( pszFilename, nImageOffset,
+        bool bOK = NITFPatchImageLength( pszFilename, nImageOffset,
                               nPixelCount, pszIC );
 
-        NITFWriteCGMSegments( pszFilename, papszCgmMD );
-        NITFWriteTextSegments( pszFilename, papszTextMD );
-        
+        bOK &= NITFWriteCGMSegments( pszFilename, papszCgmMD );
+        bOK &= NITFWriteTextSegments( pszFilename, papszTextMD );
+        if( !bOK )
+        {
+            CSLDestroy(papszCgmMD);
+            CSLDestroy(papszTextMD);
+            return NULL;
+        }
+
         GDALOpenInfo oOpenInfo( pszFilename, GA_Update );
-        poDstDS = (NITFDataset *) Open( &oOpenInfo );
+        poDstDS = reinterpret_cast<NITFDataset *>( Open( &oOpenInfo ) );
 
         if( poDstDS == NULL )
         {
@@ -4558,19 +4555,25 @@ NITFDataset::NITFCreateCopy(
 /* ==================================================================== */
     else
     {
-        NITFWriteCGMSegments( pszFilename, papszCgmMD );
-        NITFWriteTextSegments( pszFilename, papszTextMD );
+        bool bOK = NITFWriteCGMSegments( pszFilename, papszCgmMD );
+        bOK &= NITFWriteTextSegments( pszFilename, papszTextMD );
+        if( !bOK )
+        {
+            CSLDestroy(papszCgmMD);
+            CSLDestroy(papszTextMD);
+            return NULL;
+        }
 
         GDALOpenInfo oOpenInfo( pszFilename, GA_Update );
-        poDstDS = (NITFDataset *) Open( &oOpenInfo );
+        poDstDS = reinterpret_cast<NITFDataset *>( Open( &oOpenInfo ) );
         if( poDstDS == NULL )
         {
             CSLDestroy(papszCgmMD);
             CSLDestroy(papszTextMD);
             return NULL;
         }
-        
-        void  *pData = VSIMalloc2(nXSize, (GDALGetDataTypeSize(eType) / 8));
+
+        void *pData = VSIMalloc2(nXSize, GDALGetDataTypeSizeBytes(eType));
         if (pData == NULL)
         {
             delete poDstDS;
@@ -4578,7 +4581,7 @@ NITFDataset::NITFCreateCopy(
             CSLDestroy(papszTextMD);
             return NULL;
         }
-        
+
         CPLErr eErr = CE_None;
 
         for( int iBand = 0; eErr == CE_None && iBand < poSrcDS->GetRasterCount(); iBand++ )
@@ -4600,20 +4603,21 @@ NITFDataset::NITFCreateCopy(
 /* -------------------------------------------------------------------- */
             for( int iLine = 0; iLine < nYSize; iLine++ )
             {
-                eErr = poSrcBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, 
+                eErr = poSrcBand->RasterIO( GF_Read, 0, iLine, nXSize, 1,
                                             pData, nXSize, 1, eType, 0, 0, NULL );
                 if( eErr != CE_None )
-                    break;   
-                    
-                eErr = poDstBand->RasterIO( GF_Write, 0, iLine, nXSize, 1, 
+                    break;
+
+                eErr = poDstBand->RasterIO( GF_Write, 0, iLine, nXSize, 1,
                                             pData, nXSize, 1, eType, 0, 0, NULL );
 
                 if( eErr != CE_None )
-                    break;   
+                    break;
 
-                if( !pfnProgress( (iBand + (iLine+1) / (double) nYSize)
-                                  / (double) poSrcDS->GetRasterCount(), 
-                                  NULL, pProgressData ) )
+                if( !pfnProgress(
+                       (iBand + (iLine+1) / static_cast<double>( nYSize ) )
+                       / static_cast<double> ( poSrcDS->GetRasterCount() ),
+                       NULL, pProgressData ) )
                 {
                     CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
                     eErr = CE_Failure;
@@ -4623,7 +4627,7 @@ NITFDataset::NITFCreateCopy(
         }
 
         CPLFree( pData );
-        
+
         if ( eErr != CE_None )
         {
             delete poDstDS;
@@ -4665,7 +4669,7 @@ NITFDataset::NITFCreateCopy(
 /*      and the compression ratio achieved.                             */
 /************************************************************************/
 
-static void NITFPatchImageLength( const char *pszFilename,
+static bool NITFPatchImageLength( const char *pszFilename,
                                   GUIntBig nImageOffset,
                                   GIntBig nPixelCount,
                                   const char *pszIC )
@@ -4673,9 +4677,9 @@ static void NITFPatchImageLength( const char *pszFilename,
 {
     VSILFILE *fpVSIL = VSIFOpenL( pszFilename, "r+b" );
     if( fpVSIL == NULL )
-        return;
-    
-    VSIFSeekL( fpVSIL, 0, SEEK_END );
+        return false;
+
+    CPL_IGNORE_RET_VAL(VSIFSeekL( fpVSIL, 0, SEEK_END ));
     GUIntBig nFileLen = VSIFTellL( fpVSIL );
 
 /* -------------------------------------------------------------------- */
@@ -4688,10 +4692,16 @@ static void NITFPatchImageLength( const char *pszFilename,
                  nFileLen);
         nFileLen = (GUIntBig)(1e12 - 2);
     }
-    VSIFSeekL( fpVSIL, 342, SEEK_SET );
     CPLString osLen = CPLString().Printf("%012" CPL_FRMT_GB_WITHOUT_PREFIX "u",nFileLen);
-    VSIFWriteL( (void *) osLen.c_str(), 1, 12, fpVSIL );
-    
+    if( VSIFSeekL( fpVSIL, 342, SEEK_SET ) != 0 ||
+        VSIFWriteL( reinterpret_cast<const void *>( osLen.c_str() ),
+                12, 1, fpVSIL ) != 1 )
+    {
+        CPLError(CE_Failure, CPLE_FileIO, "Write error");
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpVSIL));
+        return false;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Update the image data length.                                   */
 /* -------------------------------------------------------------------- */
@@ -4703,64 +4713,69 @@ static void NITFPatchImageLength( const char *pszFilename,
                  nImageSize);
         nImageSize = (GUIntBig)(1e10 - 2);
     }
-    VSIFSeekL( fpVSIL, 369, SEEK_SET );
     osLen = CPLString().Printf("%010" CPL_FRMT_GB_WITHOUT_PREFIX "u",nImageSize);
-    VSIFWriteL( (void *) osLen.c_str(), 1, 10, fpVSIL );
+    if( VSIFSeekL( fpVSIL, 369, SEEK_SET ) != 0 ||
+        VSIFWriteL( reinterpret_cast<const void *>( osLen.c_str() ),
+                10, 1, fpVSIL ) != 1 )
+    {
+        CPLError(CE_Failure, CPLE_FileIO, "Write error");
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpVSIL));
+        return false;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Update COMRAT, the compression rate variable.  We have to       */
 /*      take into account the presence of graphic and text segments,    */
 /*      the optional presence of IGEOLO and ICOM to find its position.  */
 /* -------------------------------------------------------------------- */
-    char szICBuf[2];
-    char achNUM[4]; // buffer for segment size.  3 digits plus null character
-    achNUM[3] = '\0';
-
     // get number of graphic and text segment so we can calculate offset for
     // image IC.
-    int nNumIOffset = 360;
-    VSIFSeekL( fpVSIL, nNumIOffset, SEEK_SET );
-    VSIFReadL( achNUM, 1, 3, fpVSIL );
-    int nIM = atoi(achNUM); // number of image segment
+    const int nNumIOffset = 360;
+    bool bOK = VSIFSeekL( fpVSIL, nNumIOffset, SEEK_SET ) == 0;
+    char achNUM[4]; // buffer for segment size.  3 digits plus null character
+    achNUM[3] = '\0';
+    bOK &= VSIFReadL( achNUM, 3, 1, fpVSIL ) == 1;
+    const int nIM = atoi(achNUM); // number of image segment
 
-    int nNumSOffset = nNumIOffset + 3 + nIM * 16;
-    VSIFSeekL( fpVSIL,  nNumSOffset, SEEK_SET );
-    VSIFReadL( achNUM, 1, 3, fpVSIL );
-    int nGS = atoi(achNUM); // number of graphic segment
+    const int nNumSOffset = nNumIOffset + 3 + nIM * 16;
+    bOK &= VSIFSeekL( fpVSIL,  nNumSOffset, SEEK_SET ) == 0;
+    bOK &= VSIFReadL( achNUM, 3, 1, fpVSIL ) == 1;
+    const int nGS = atoi(achNUM); // number of graphic segment
 
-    int nNumTOffset = nNumSOffset + 3 + 10 * nGS + 3;
-    VSIFSeekL( fpVSIL, nNumTOffset, SEEK_SET );
-    VSIFReadL( achNUM, 1, 3, fpVSIL );
-    int nTS = atoi(achNUM); // number of text segment
+    const int nNumTOffset = nNumSOffset + 3 + 10 * nGS + 3;
+    bOK &= VSIFSeekL( fpVSIL, nNumTOffset, SEEK_SET ) == 0;
+    bOK &= VSIFReadL( achNUM, 3, 1, fpVSIL ) == 1;
+    const int nTS = atoi(achNUM); // number of text segment
 
-    int nAdditionalOffset = nGS * 10 + nTS * 9;
+    const int nAdditionalOffset = nGS * 10 + nTS * 9;
 
     /* Read ICORDS */
-    VSIFSeekL( fpVSIL, 775 + nAdditionalOffset , SEEK_SET );
+    bOK &= VSIFSeekL( fpVSIL, 775 + nAdditionalOffset , SEEK_SET ) == 0;
     char chICORDS;
-    VSIFReadL( &chICORDS, 1, 1, fpVSIL );
+    bOK &= VSIFReadL( &chICORDS, 1, 1, fpVSIL ) == 1;
     if (chICORDS != ' ')
-        VSIFSeekL( fpVSIL, 60, SEEK_CUR); /* skip IGEOLO */
+        bOK &= VSIFSeekL( fpVSIL, 60, SEEK_CUR) == 0; /* skip IGEOLO */
 
     /* Read NICOM */
     char achNICOM[2];
-    VSIFReadL( achNICOM, 1, 1, fpVSIL );
+    bOK &= VSIFReadL( achNICOM, 1, 1, fpVSIL ) == 1;
     achNICOM[1] = 0;
-    int nNICOM = atoi(achNICOM);
-    VSIFSeekL( fpVSIL, nNICOM * 80, SEEK_CUR); /* skip comments */
+    const int nNICOM = atoi(achNICOM);
+    bOK &= VSIFSeekL( fpVSIL, nNICOM * 80, SEEK_CUR) == 0; /* skip comments */
 
     /* Read IC */
-    VSIFReadL( szICBuf, 2, 1, fpVSIL );
+    char szICBuf[2];
+    bOK &= VSIFReadL( szICBuf, 2, 1, fpVSIL ) == 1;
 
     /* The following line works around a "feature" of *BSD libc (at least PC-BSD 7.1) */
     /* that makes the position of the file offset unreliable when executing a */
     /* "seek, read and write" sequence. After the read(), the file offset seen by */
-    /* the write() is approximatively the size of a block further... */
-    VSIFSeekL( fpVSIL, VSIFTellL( fpVSIL ), SEEK_SET );
-    
+    /* the write() is approximately the size of a block further... */
+    bOK &= VSIFSeekL( fpVSIL, VSIFTellL( fpVSIL ), SEEK_SET ) == 0;
+
     if( !EQUALN(szICBuf,pszIC,2) )
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "Unable to locate COMRAT to update in NITF header." );
     }
     else
@@ -4769,41 +4784,49 @@ static void NITFPatchImageLength( const char *pszFilename,
 
         if( EQUAL(pszIC,"C8") ) /* jpeg2000 */
         {
-            double dfRate = (GIntBig)(nFileLen-nImageOffset) * 8 / (double) nPixelCount;
-            dfRate = MAX(0.01,MIN(99.99,dfRate));
-        
+            double dfRate = static_cast<GIntBig>(nFileLen-nImageOffset) * 8
+                / static_cast<double>( nPixelCount );
+            dfRate = MAX(0.01, MIN(99.99, dfRate));
+
             // We emit in wxyz format with an implicit decimal place
-            // between wx and yz as per spec for lossy compression. 
+            // between wx and yz as per spec for lossy compression.
             // We really should have a special case for lossless compression.
-            sprintf( szCOMRAT, "%04d", (int) (dfRate * 100));
+            snprintf( szCOMRAT, sizeof(szCOMRAT), "%04d", static_cast<int>( dfRate * 100 ));
         }
         else if( EQUAL(pszIC, "C3") || EQUAL(pszIC, "M3") ) /* jpeg */
         {
             strcpy( szCOMRAT, "00.0" );
         }
 
-        VSIFWriteL( szCOMRAT, 4, 1, fpVSIL );
+        bOK &= VSIFWriteL( szCOMRAT, 4, 1, fpVSIL ) == 1;
+    }
+
+    if( VSIFCloseL( fpVSIL ) != 0 )
+        bOK = false;
+
+    if( !bOK )
+    {
+        CPLError(CE_Failure, CPLE_FileIO, "I/O error");
     }
-    
-    VSIFCloseL( fpVSIL );
+
+    return bOK;
 }
 
 /************************************************************************/
 /*                       NITFWriteCGMSegments()                        */
 /************************************************************************/
-static int NITFWriteCGMSegments( const char *pszFilename, char **papszList)
+static bool NITFWriteCGMSegments( const char *pszFilename, char **papszList)
 {
     char errorMessage[255] = "";
 
     // size of each Cgm header entry (LS (4) + LSSH (6))
     const int nCgmHdrEntrySz = 10;
-    
+
     if (papszList == NULL)
-        return TRUE;
+        return true;
 
     int nNUMS = 0;
-    const char *pszNUMS;
-    pszNUMS = CSLFetchNameValue(papszList, "SEGMENT_COUNT");
+    const char *pszNUMS = CSLFetchNameValue(papszList, "SEGMENT_COUNT");
     if (pszNUMS != NULL)
     {
         nNUMS = atoi(pszNUMS);
@@ -4815,23 +4838,23 @@ static int NITFWriteCGMSegments( const char *pszFilename, char **papszList)
     VSILFILE *fpVSIL = VSIFOpenL(pszFilename, "r+b");
 
     if (fpVSIL == NULL)
-        return FALSE;
+        return false;
 
     // Calculates the offset for NUMS so we can update header data
     char achNUMI[4]; // 3 digits plus null character
     achNUMI[3] = '\0';
 
     // NUMI offset is at a fixed offset 363
-    int nNumIOffset = 360;
-    VSIFSeekL(fpVSIL, nNumIOffset, SEEK_SET );
-    VSIFReadL(achNUMI, 1, 3, fpVSIL);
-    int nIM = atoi(achNUMI);
+    const int nNumIOffset = 360;
+    bool bOK = VSIFSeekL(fpVSIL, nNumIOffset, SEEK_SET ) == 0;
+    bOK &= VSIFReadL(achNUMI, 3, 1, fpVSIL) == 1;
+    const int nIM = atoi(achNUMI);
 
     // 6 for size of LISH and 10 for size of LI
     // NUMS offset is NumI offset plus the size of NumI + size taken up each
     // the header data multiply by the number of data
 
-    int nNumSOffset = nNumIOffset + 3+ nIM * (6 + 10);
+    const int nNumSOffset = nNumIOffset + 3+ nIM * (6 + 10);
 
     /* -------------------------------------------------------------------- */
     /*      Confirm that the NUMS in the file header already matches the    */
@@ -4839,25 +4862,26 @@ static int NITFWriteCGMSegments( const char *pszFilename, char **papszList)
     /* -------------------------------------------------------------------- */
     char achNUMS[4];
 
-    VSIFSeekL( fpVSIL, nNumSOffset, SEEK_SET );
-    VSIFReadL( achNUMS, 1, 3, fpVSIL );
+    bOK &= VSIFSeekL( fpVSIL, nNumSOffset, SEEK_SET ) == 0;
+    bOK &= VSIFReadL( achNUMS, 3, 1, fpVSIL ) == 1;
     achNUMS[3] = '\0';
 
-    if( atoi(achNUMS) != nNUMS )
+    if( !bOK || atoi(achNUMS) != nNUMS )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "It appears an attempt was made to add or update graphic\n"
                   "segments on an NITF file with existing segments.  This\n"
                   "is not currently supported by the GDAL NITF driver." );
 
-        VSIFCloseL( fpVSIL );
-        return FALSE;
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fpVSIL ));
+        return false;
     }
 
 
     // allocate space for graphic header.
     // Size of LS = 4, size of LSSH = 6, and 1 for null character
-    char *pachLS = (char *) CPLCalloc(nNUMS * nCgmHdrEntrySz + 1, 1);
+    char *pachLS = reinterpret_cast<char *>(
+        CPLCalloc(nNUMS * nCgmHdrEntrySz + 1, 1) );
 
     /* -------------------------------------------------------------------- */
     /*	Assume no extended data such as SXSHDL, SXSHD						*/
@@ -4867,9 +4891,9 @@ static int NITFWriteCGMSegments( const char *pszFilename, char **papszList)
     /*      Write the Graphics segments at the end of the file.             */
     /* ==================================================================== */
 
-    #define PLACE(location,name,text)  strncpy(location,text,strlen(text))
+    #define PLACE(location,name,text)  memcpy(location,text,strlen(text))
 
-    for (int i = 0; i < nNUMS; i++)
+    for (int i = 0; bOK && i < nNUMS; i++)
     {
 
         // Get all the fields for current CGM segment
@@ -4887,34 +4911,34 @@ static int NITFWriteCGMSegments( const char *pszFilename, char **papszList)
         // Error checking
         if (pszSlocRow == NULL)
         {
-            sprintf(errorMessage, "NITF graphic segment writing error: SLOC_ROW for segment %d is not defined",i);
+            snprintf(errorMessage, sizeof(errorMessage), "NITF graphic segment writing error: SLOC_ROW for segment %d is not defined",i);
             break;
         }
         if (pszSlocCol == NULL)
         {
-            sprintf(errorMessage, "NITF graphic segment writing error: SLOC_COL for segment %d is not defined",i);
+            snprintf(errorMessage, sizeof(errorMessage), "NITF graphic segment writing error: SLOC_COL for segment %d is not defined",i);
             break;
         }
         if (pszSdlvl == NULL)
         {
-            sprintf(errorMessage, "NITF graphic segment writing error: SDLVL for segment %d is not defined", i);
+            snprintf(errorMessage, sizeof(errorMessage), "NITF graphic segment writing error: SDLVL for segment %d is not defined", i);
             break;
         }
         if (pszSalvl == NULL)
         {
-            sprintf(errorMessage, "NITF graphic segment writing error: SALVLfor segment %d is not defined", i);
+            snprintf(errorMessage, sizeof(errorMessage), "NITF graphic segment writing error: SALVLfor segment %d is not defined", i);
             break;
         }
         if (pszData == NULL)
         {
-            sprintf(errorMessage, "NITF graphic segment writing error: DATA for segment %d is not defined", i);
+            snprintf(errorMessage, sizeof(errorMessage), "NITF graphic segment writing error: DATA for segment %d is not defined", i);
             break;
         }
 
-        int nSlocCol = atoi(pszSlocRow);
-        int nSlocRow = atoi(pszSlocCol);
-        int nSdlvl = atoi(pszSdlvl);
-        int nSalvl = atoi(pszSalvl);
+        const int nSlocCol = atoi(pszSlocRow);
+        const int nSlocRow = atoi(pszSlocCol);
+        const int nSdlvl = atoi(pszSdlvl);
+        const int nSalvl = atoi(pszSalvl);
 
         // Create a buffer for graphics segment header, 258 is the size of
         // the header that we will be writing.
@@ -4922,7 +4946,6 @@ static int NITFWriteCGMSegments( const char *pszFilename, char **papszList)
 
         memset(achGSH, ' ', sizeof(achGSH));
 
-
         PLACE( achGSH+ 0, SY , "SY" );
         PLACE( achGSH+ 2, SID ,CPLSPrintf("%010d", i) );
         PLACE( achGSH+ 12, SNAME , "DEFAULT NAME        " );
@@ -4941,12 +4964,12 @@ static int NITFWriteCGMSegments( const char *pszFilename, char **papszList)
         PLACE( achGSH+253, SXSHDL, "00000" );
 
         // Move to the end of the file
-        VSIFSeekL(fpVSIL, 0, SEEK_END );
-        VSIFWriteL(achGSH, 1, sizeof(achGSH), fpVSIL);
+        bOK &= VSIFSeekL(fpVSIL, 0, SEEK_END ) == 0;
+        bOK &= VSIFWriteL(achGSH, sizeof(achGSH), 1, fpVSIL) == 1;
 
-        /* -------------------------------------- ------------------------------ */
-        /*      Prepare and write CGM segment data.                            */
-        /* -------------------------------------------------------------------- */
+        /* ------------------------------------------------------------------ */
+        /*      Prepare and write CGM segment data.                           */
+        /* ------------------------------------------------------------------ */
         int nCGMSize = 0;
         char *pszCgmToWrite = CPLUnescapeString(pszData, &nCGMSize,
                         CPLES_BackslashQuotable);
@@ -4959,12 +4982,13 @@ static int NITFWriteCGMSegments( const char *pszFilename, char **papszList)
             nCGMSize = 999998;
         }
 
-        VSIFWriteL(pszCgmToWrite, 1, nCGMSize, fpVSIL);
+        bOK &= static_cast<int>(VSIFWriteL(pszCgmToWrite, 1, nCGMSize, fpVSIL)) == nCGMSize;
 
         /* -------------------------------------------------------------------- */
         /*      Update the subheader and data size info in the file header.     */
         /* -------------------------------------------------------------------- */
-        sprintf( pachLS + nCgmHdrEntrySz * i, "%04d%06d",(int) sizeof(achGSH), nCGMSize );
+        snprintf( pachLS + nCgmHdrEntrySz * i, nCgmHdrEntrySz + 1, "%04d%06d",
+                 static_cast<int>( sizeof(achGSH) ), nCGMSize );
 
         CPLFree(pszCgmToWrite);
 
@@ -4975,16 +4999,17 @@ static int NITFWriteCGMSegments( const char *pszFilename, char **papszList)
     /*      Write out the graphic segment info.                             */
     /* -------------------------------------------------------------------- */
 
-    VSIFSeekL(fpVSIL, nNumSOffset + 3, SEEK_SET );
-    VSIFWriteL(pachLS, 1, nNUMS * nCgmHdrEntrySz, fpVSIL);
+    bOK &= VSIFSeekL(fpVSIL, nNumSOffset + 3, SEEK_SET ) == 0;
+    bOK &= static_cast<int>(VSIFWriteL(pachLS, 1, nNUMS * nCgmHdrEntrySz, fpVSIL))
+                == nNUMS * nCgmHdrEntrySz;
 
     /* -------------------------------------------------------------------- */
     /*      Update total file length.                                       */
     /* -------------------------------------------------------------------- */
-    VSIFSeekL(fpVSIL, 0, SEEK_END );
+    bOK &= VSIFSeekL(fpVSIL, 0, SEEK_END ) == 0;
     GUIntBig nFileLen = VSIFTellL(fpVSIL);
     // Offset to file length entry
-    VSIFSeekL(fpVSIL, 342, SEEK_SET );
+    bOK &= VSIFSeekL(fpVSIL, 342, SEEK_SET ) == 0;
     if (GUINTBIG_TO_DOUBLE(nFileLen) >= 1e12 - 1)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -4994,26 +5019,33 @@ static int NITFWriteCGMSegments( const char *pszFilename, char **papszList)
     }
     CPLString osLen = CPLString().Printf("%012" CPL_FRMT_GB_WITHOUT_PREFIX "u",
                     nFileLen);
-    VSIFWriteL((void *) osLen.c_str(), 1, 12, fpVSIL);
+    bOK &= VSIFWriteL( reinterpret_cast<const void *>( osLen.c_str() ), 12, 1, fpVSIL) == 1;
 
-    VSIFCloseL(fpVSIL);
+    if( VSIFCloseL(fpVSIL) != 0 )
+        bOK = false;
 
     CPLFree(pachLS);
 
+    if( !bOK )
+    {
+        CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        return false;
+    }
+
     if (strlen(errorMessage) != 0)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "%s", errorMessage);
-        return FALSE;
+        return false;
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                       NITFWriteTextSegments()                        */
 /************************************************************************/
 
-static void NITFWriteTextSegments( const char *pszFilename,
+static bool NITFWriteTextSegments( const char *pszFilename,
                                    char **papszList )
 
 {
@@ -5021,16 +5053,16 @@ static void NITFWriteTextSegments( const char *pszFilename,
 /*      Count the number of apparent text segments to write.  There     */
 /*      is nothing at all to do if there are none to write.             */
 /* -------------------------------------------------------------------- */
-    int iOpt, nNUMT = 0;
+    int nNUMT = 0;
 
-    for( iOpt = 0; papszList != NULL && papszList[iOpt] != NULL; iOpt++ )
+    for( int iOpt = 0; papszList != NULL && papszList[iOpt] != NULL; iOpt++ )
     {
-        if( EQUALN(papszList[iOpt],"DATA_",5) )
+        if( STARTS_WITH_CI(papszList[iOpt], "DATA_") )
             nNUMT++;
     }
 
     if( nNUMT == 0 )
-        return;
+        return true;
 
 /* -------------------------------------------------------------------- */
 /*      Open the target file.                                           */
@@ -5038,7 +5070,7 @@ static void NITFWriteTextSegments( const char *pszFilename,
     VSILFILE *fpVSIL = VSIFOpenL( pszFilename, "r+b" );
 
     if( fpVSIL == NULL )
-        return;
+        return false;
 
     // Get number of text field.  Since there there could be multiple images
     // or graphic segment, the  offset need to be calculated dynamically.
@@ -5047,56 +5079,56 @@ static void NITFWriteTextSegments( const char *pszFilename,
     achNUMI[3] = '\0';
     // NUMI offset is at a fixed offset 363
     int nNumIOffset = 360;
-    VSIFSeekL( fpVSIL, nNumIOffset, SEEK_SET );
-    VSIFReadL( achNUMI, 1, 3, fpVSIL );
+    bool bOK = VSIFSeekL( fpVSIL, nNumIOffset, SEEK_SET ) == 0;
+    bOK &= VSIFReadL( achNUMI, 3, 1, fpVSIL ) == 1;
     int nIM = atoi(achNUMI);
 
     char achNUMG[4]; // 3 digits plus null character
     achNUMG[3] = '\0';
 
     // 3 for size of NUMI.  6 and 10 are the field size for LISH and LI
-    int nNumGOffset = nNumIOffset + 3 + nIM * (6 + 10);
-    VSIFSeekL( fpVSIL, nNumGOffset, SEEK_SET );
-    VSIFReadL( achNUMG, 1, 3, fpVSIL );
-    int nGS = atoi(achNUMG);
+    const int nNumGOffset = nNumIOffset + 3 + nIM * (6 + 10);
+    bOK &= VSIFSeekL( fpVSIL, nNumGOffset, SEEK_SET ) == 0;
+    bOK &= VSIFReadL( achNUMG, 3, 1, fpVSIL ) == 1;
+    const int nGS = atoi(achNUMG);
 
     // NUMT offset
     // 3 for size of NUMG.  4 and 6 are filed size of LSSH and LS.
     // the last + 3 is for NUMX field, which is not used
-    int nNumTOffset = nNumGOffset + 3 + nGS * (4 + 6) + 3;
+    const int nNumTOffset = nNumGOffset + 3 + nGS * (4 + 6) + 3;
 
     /* -------------------------------------------------------------------- */
     /*      Confirm that the NUMT in the file header already matches the    */
-    /*      number of text segements we want to write, and that the         */
+    /*      number of text segments we want to write, and that the          */
     /*      segment header/data size info is blank.                         */
     /* -------------------------------------------------------------------- */
     char achNUMT[4];
-    char *pachLT = (char *) CPLCalloc(nNUMT * 9 + 1, 1);
+    char *pachLT = reinterpret_cast<char *>( CPLCalloc(nNUMT * 9 + 1, 1) );
 
-    VSIFSeekL( fpVSIL, nNumTOffset, SEEK_SET );
-    VSIFReadL( achNUMT, 1, 3, fpVSIL );
+    bOK &= VSIFSeekL( fpVSIL, nNumTOffset, SEEK_SET ) == 0;
+    bOK &= VSIFReadL( achNUMT, 3, 1, fpVSIL ) == 1;
     achNUMT[3] = '\0';
 
-    VSIFReadL( pachLT, 1, nNUMT * 9, fpVSIL );
+    bOK &= VSIFReadL( pachLT, nNUMT * 9, 1, fpVSIL ) == 1;
 
-    if( atoi(achNUMT) != nNUMT )
+    if( !bOK || atoi(achNUMT) != nNUMT )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "It appears an attempt was made to add or update text\n"
                   "segments on an NITF file with existing segments.  This\n"
                   "is not currently supported by the GDAL NITF driver." );
 
-        VSIFCloseL( fpVSIL );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fpVSIL ));
         CPLFree( pachLT );
-        return;
+        return false;
     }
 
-    if( !EQUALN(pachLT,"         ",9) )
+    if( !STARTS_WITH_CI(pachLT, "         ") )
     {
         CPLFree( pachLT );
         // presumably the text segments are already written, do nothing.
-        VSIFCloseL( fpVSIL );
-        return;
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fpVSIL ));
+        return true;
     }
 
 /* -------------------------------------------------------------------- */
@@ -5107,19 +5139,15 @@ static void NITFWriteTextSegments( const char *pszFilename,
 /* ==================================================================== */
 /*      Write the text segments at the end of the file.                 */
 /* ==================================================================== */
-#define PLACE(location,name,text)  strncpy(location,text,strlen(text))
+#define PLACE(location,name,text)  memcpy(location,text,strlen(text))
     int iTextSeg = 0;
-    
-    for( iOpt = 0; papszList != NULL && papszList[iOpt] != NULL; iOpt++ )
-    {
-        const char *pszTextToWrite;
 
-        if( !EQUALN(papszList[iOpt],"DATA_",5) )
+    for( int iOpt = 0; bOK && papszList != NULL && papszList[iOpt] != NULL; iOpt++ )
+    {
+        if( !STARTS_WITH_CI(papszList[iOpt], "DATA_") )
             continue;
 
-        const char *pszHeaderBuffer = NULL;
-
-        pszTextToWrite = CPLParseNameValue( papszList[iOpt], NULL );
+        const char *pszTextToWrite = CPLParseNameValue( papszList[iOpt], NULL );
         if( pszTextToWrite == NULL )
             continue;
 
@@ -5127,12 +5155,14 @@ static void NITFWriteTextSegments( const char *pszFilename,
 /*      Locate corresponding header data in the buffer                  */
 /* -------------------------------------------------------------------- */
 
+        const char *pszHeaderBuffer = NULL;
         for( int iOpt2 = 0; papszList != NULL && papszList[iOpt2] != NULL; iOpt2++ ) {
-            if( !EQUALN(papszList[iOpt2],"HEADER_",7) )
+            if( !STARTS_WITH_CI(papszList[iOpt2], "HEADER_") )
                 continue;
 
-            char *pszHeaderKey = NULL, *pszDataKey = NULL;
+            char *pszHeaderKey = NULL;
             CPLParseNameValue( papszList[iOpt2], &pszHeaderKey );
+            char *pszDataKey = NULL;
             CPLParseNameValue( papszList[iOpt], &pszDataKey );
             if( pszHeaderKey == NULL || pszDataKey == NULL )
             {
@@ -5141,11 +5171,11 @@ static void NITFWriteTextSegments( const char *pszFilename,
                 continue;
             }
 
-            char *pszHeaderId, *pszDataId; //point to header and data number
-            pszHeaderId = pszHeaderKey + 7;
-            pszDataId = pszDataKey + 5;
+            // Point to header and data number.
+            char *pszHeaderId = pszHeaderKey + 7;
+            char *pszDataId = pszDataKey + 5;
 
-            bool bIsSameId = strcmp(pszHeaderId, pszDataId) == 0;
+            const bool bIsSameId = strcmp(pszHeaderId, pszDataId) == 0;
             CPLFree(pszHeaderKey);
             CPLFree(pszDataKey);
 
@@ -5161,13 +5191,13 @@ static void NITFWriteTextSegments( const char *pszFilename,
 /* -------------------------------------------------------------------- */
         char achTSH[282];
         memset( achTSH, ' ', sizeof(achTSH) );
-        VSIFSeekL( fpVSIL, 0, SEEK_END );
+        bOK &= VSIFSeekL( fpVSIL, 0, SEEK_END ) == 0;
 
         if (pszHeaderBuffer!= NULL) {
             memcpy( achTSH, pszHeaderBuffer, MIN(strlen(pszHeaderBuffer), sizeof(achTSH)) );
 
             // Take care NITF2.0 date format changes
-            char chTimeZone = achTSH[20];
+            const char chTimeZone = achTSH[20];
 
             // Check for Zulu time zone character.  IpachLTf that exist, then
             // it's NITF2.0 format.
@@ -5175,19 +5205,18 @@ static void NITFWriteTextSegments( const char *pszFilename,
                 char *achOrigDate=achTSH+12;  // original date string
 
                 // The date value taken from default NITF file date
-                char achNewDate[]="20021216151629";
                 char achYear[3];
-                int nYear;
 
                 // Offset to the year
                 strncpy(achYear,achOrigDate+12, 2);
                 achYear[2] = '\0';
-                nYear = atoi(achYear);
+                const int nYear = atoi(achYear);
 
                 // Set century.
                 // Since NITF2.0 does not track the century, we are going to
                 // assume any year number greater then 94 (the year NITF2.0
                 // spec published), will be 1900s, otherwise, it's 2000s.
+                char achNewDate[] = "20021216151629";
                 if (nYear > 94) strncpy(achNewDate,"19",2);
                 else strncpy(achNewDate,"20",2);
 
@@ -5198,17 +5227,17 @@ static void NITFWriteTextSegments( const char *pszFilename,
                 char *pszOrigMonth = achOrigDate+9;
                 char *pszNewMonth = achNewDate+4;
 
-                if (strncmp(pszOrigMonth,"JAN",3) == 0) strncpy(pszNewMonth,"01",2);
-                else if (strncmp(pszOrigMonth,"FEB",3) == 0) strncpy(pszNewMonth,"02",2);
-                else if (strncmp(pszOrigMonth,"MAR",3) == 0) strncpy(pszNewMonth,"03",2);
-                else if (strncmp(pszOrigMonth,"APR",3) == 0) strncpy(pszNewMonth,"04",2);
-                else if (strncmp(pszOrigMonth,"MAY",3) == 0) strncpy(pszNewMonth,"05",2);
-                else if (strncmp(pszOrigMonth,"JUN",3) == 0) strncpy(pszNewMonth,"07",2);
-                else if (strncmp(pszOrigMonth,"AUG",3) == 0) strncpy(pszNewMonth,"08",2);
-                else if (strncmp(pszOrigMonth,"SEP",3) == 0) strncpy(pszNewMonth,"09",2);
-                else if (strncmp(pszOrigMonth,"OCT",3) == 0) strncpy(pszNewMonth,"10",2);
-                else if (strncmp(pszOrigMonth,"NOV",3) == 0) strncpy(pszNewMonth,"11",2);
-                else if (strncmp(pszOrigMonth,"DEC",3) == 0) strncpy(pszNewMonth,"12",2);
+                if (STARTS_WITH(pszOrigMonth, "JAN")) strncpy(pszNewMonth,"01",2);
+                else if (STARTS_WITH(pszOrigMonth, "FEB")) strncpy(pszNewMonth,"02",2);
+                else if (STARTS_WITH(pszOrigMonth, "MAR")) strncpy(pszNewMonth,"03",2);
+                else if (STARTS_WITH(pszOrigMonth, "APR")) strncpy(pszNewMonth,"04",2);
+                else if (STARTS_WITH(pszOrigMonth, "MAY")) strncpy(pszNewMonth,"05",2);
+                else if (STARTS_WITH(pszOrigMonth, "JUN")) strncpy(pszNewMonth,"07",2);
+                else if (STARTS_WITH(pszOrigMonth, "AUG")) strncpy(pszNewMonth,"08",2);
+                else if (STARTS_WITH(pszOrigMonth, "SEP")) strncpy(pszNewMonth,"09",2);
+                else if (STARTS_WITH(pszOrigMonth, "OCT")) strncpy(pszNewMonth,"10",2);
+                else if (STARTS_WITH(pszOrigMonth, "NOV")) strncpy(pszNewMonth,"11",2);
+                else if (STARTS_WITH(pszOrigMonth, "DEC")) strncpy(pszNewMonth,"12",2);
 
                 PLACE( achTSH+ 12, TXTDT         , achNewDate          		);
 
@@ -5224,13 +5253,13 @@ static void NITFWriteTextSegments( const char *pszFilename,
         }
 
 
-        VSIFWriteL( achTSH, 1, sizeof(achTSH), fpVSIL );
+        bOK &= VSIFWriteL( achTSH, sizeof(achTSH), 1, fpVSIL ) == 1;
 
 /* -------------------------------------------------------------------- */
 /*      Prepare and write text segment data.                            */
 /* -------------------------------------------------------------------- */
 
-        int nTextLength = (int) strlen(pszTextToWrite);
+        int nTextLength = static_cast<int>( strlen(pszTextToWrite) );
         if (nTextLength > 99998)
         {
             CPLError(CE_Warning, CPLE_NotSupported,
@@ -5239,13 +5268,13 @@ static void NITFWriteTextSegments( const char *pszFilename,
             nTextLength = 99998;
         }
 
-        VSIFWriteL( pszTextToWrite, 1, nTextLength, fpVSIL );
-        
+        bOK &= static_cast<int>(VSIFWriteL( pszTextToWrite, 1, nTextLength, fpVSIL )) == nTextLength;
+
 /* -------------------------------------------------------------------- */
 /*      Update the subheader and data size info in the file header.     */
 /* -------------------------------------------------------------------- */
-        sprintf( pachLT + 9*iTextSeg+0, "%04d%05d",
-                 (int) sizeof(achTSH), nTextLength );
+        snprintf( pachLT + 9*iTextSeg+0, 9+1, "%04d%05d",
+                 static_cast<int>( sizeof( achTSH ) ), nTextLength );
 
         iTextSeg++;
     }
@@ -5254,16 +5283,16 @@ static void NITFWriteTextSegments( const char *pszFilename,
 /*      Write out the text segment info.                                */
 /* -------------------------------------------------------------------- */
 
-    VSIFSeekL( fpVSIL, nNumTOffset + 3, SEEK_SET );
-    VSIFWriteL( pachLT, 1, nNUMT * 9, fpVSIL );
+    bOK &= VSIFSeekL( fpVSIL, nNumTOffset + 3, SEEK_SET ) == 0;
+    bOK &= static_cast<int>(VSIFWriteL( pachLT, 1, nNUMT * 9, fpVSIL )) == nNUMT * 9;
 
 /* -------------------------------------------------------------------- */
 /*      Update total file length.                                       */
 /* -------------------------------------------------------------------- */
-    VSIFSeekL( fpVSIL, 0, SEEK_END );
+    bOK &= VSIFSeekL( fpVSIL, 0, SEEK_END ) == 0;
     GUIntBig nFileLen = VSIFTellL( fpVSIL );
 
-    VSIFSeekL( fpVSIL, 342, SEEK_SET );
+    bOK &= VSIFSeekL( fpVSIL, 342, SEEK_SET ) == 0;
     if (GUINTBIG_TO_DOUBLE(nFileLen) >= 1e12 - 1)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -5272,19 +5301,29 @@ static void NITFWriteTextSegments( const char *pszFilename,
         nFileLen = (GUIntBig)(1e12 - 2);
     }
     CPLString osLen = CPLString().Printf("%012" CPL_FRMT_GB_WITHOUT_PREFIX "u",nFileLen);
-    VSIFWriteL( (void *) osLen.c_str(), 1, 12, fpVSIL );
-    
-    VSIFCloseL( fpVSIL );
+    bOK &= VSIFWriteL( reinterpret_cast<const void *>( osLen.c_str() ),
+                12, 1, fpVSIL ) == 1;
+
+    if( VSIFCloseL( fpVSIL ) != 0 )
+        bOK = false;
     CPLFree( pachLT );
+
+    if( !bOK )
+    {
+        CPLError(CE_Failure, CPLE_FileIO,
+                 "I/O error");
+    }
+
+    return bOK;
 }
-        
+
 /************************************************************************/
 /*                         NITFWriteJPEGImage()                         */
 /************************************************************************/
 
 #ifdef JPEG_SUPPORTED
 
-int 
+int
 NITFWriteJPEGBlock( GDALDataset *poSrcDS, VSILFILE *fp,
                     int nBlockXOff, int nBlockYOff,
                     int nBlockXSize, int nBlockYSize,
@@ -5292,31 +5331,25 @@ NITFWriteJPEGBlock( GDALDataset *poSrcDS, VSILFILE *fp,
                     const GByte* pabyAPP6, int nRestartInterval,
                     GDALProgressFunc pfnProgress, void * pProgressData );
 
-static int 
+static bool
 NITFWriteJPEGImage( GDALDataset *poSrcDS, VSILFILE *fp, vsi_l_offset nStartOffset,
                     char **papszOptions,
                     GDALProgressFunc pfnProgress, void * pProgressData )
 {
-    int  nBands = poSrcDS->GetRasterCount();
-    int  nXSize = poSrcDS->GetRasterXSize();
-    int  nYSize = poSrcDS->GetRasterYSize();
-    int  nQuality = 75;
-    int  bProgressive = FALSE;
-    int  nRestartInterval = -1;
-
     if( !pfnProgress( 0.0, NULL, pProgressData ) )
-        return FALSE;
+        return false;
 
 /* -------------------------------------------------------------------- */
 /*      Some some rudimentary checks                                    */
 /* -------------------------------------------------------------------- */
+    const int nBands = poSrcDS->GetRasterCount();
     if( nBands != 1 && nBands != 3 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "JPEG driver doesn't support %d bands.  Must be 1 (grey) "
                   "or 3 (RGB) bands.\n", nBands );
 
-        return FALSE;
+        return false;
     }
 
     GDALDataType eDT = poSrcDS->GetRasterBand(1)->GetRasterDataType();
@@ -5324,13 +5357,13 @@ NITFWriteJPEGImage( GDALDataset *poSrcDS, VSILFILE *fp, vsi_l_offset nStartOffse
 #if defined(JPEG_LIB_MK1) || defined(JPEG_DUAL_MODE_8_12)
     if( eDT != GDT_Byte && eDT != GDT_UInt16 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "JPEG driver doesn't support data type %s. "
                   "Only eight and twelve bit bands supported (Mk1 libjpeg).\n",
-                  GDALGetDataTypeName( 
+                  GDALGetDataTypeName(
                       poSrcDS->GetRasterBand(1)->GetRasterDataType()) );
 
-        return FALSE;
+        return false;
     }
 
     if( eDT == GDT_UInt16 || eDT == GDT_Int16 )
@@ -5341,21 +5374,22 @@ NITFWriteJPEGImage( GDALDataset *poSrcDS, VSILFILE *fp, vsi_l_offset nStartOffse
 #else
     if( eDT != GDT_Byte )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "JPEG driver doesn't support data type %s. "
-                  "Only eight bit byte bands supported.\n", 
-                  GDALGetDataTypeName( 
+                  "Only eight bit byte bands supported.\n",
+                  GDALGetDataTypeName(
                       poSrcDS->GetRasterBand(1)->GetRasterDataType()) );
 
-        return FALSE;
+        return false;
     }
-    
-    eDT = GDT_Byte; // force to 8bit. 
+
+    eDT = GDT_Byte; // force to 8bit.
 #endif
 
 /* -------------------------------------------------------------------- */
 /*      What options has the user selected?                             */
 /* -------------------------------------------------------------------- */
+    int nQuality = 75;
     if( CSLFetchNameValue(papszOptions,"QUALITY") != NULL )
     {
         nQuality = atoi(CSLFetchNameValue(papszOptions,"QUALITY"));
@@ -5364,20 +5398,23 @@ NITFWriteJPEGImage( GDALDataset *poSrcDS, VSILFILE *fp, vsi_l_offset nStartOffse
             CPLError( CE_Failure, CPLE_IllegalArg,
                       "QUALITY=%s is not a legal value in the range 10-100.",
                       CSLFetchNameValue(papszOptions,"QUALITY") );
-            return FALSE;
+            return false;
         }
     }
 
+    int nRestartInterval = -1;
     if( CSLFetchNameValue(papszOptions,"RESTART_INTERVAL") != NULL )
     {
         nRestartInterval = atoi(CSLFetchNameValue(papszOptions,"RESTART_INTERVAL"));
     }
 
-    bProgressive = CSLFetchBoolean( papszOptions, "PROGRESSIVE", FALSE );
+    int bProgressive = CSLFetchBoolean( papszOptions, "PROGRESSIVE", FALSE );
 
 /* -------------------------------------------------------------------- */
 /*      Compute blocking factors                                        */
 /* -------------------------------------------------------------------- */
+    const int nXSize = poSrcDS->GetRasterXSize();
+    const int nYSize = poSrcDS->GetRasterYSize();
     int nNPPBH = nXSize;
     int nNPPBV = nYSize;
 
@@ -5389,34 +5426,31 @@ NITFWriteJPEGImage( GDALDataset *poSrcDS, VSILFILE *fp, vsi_l_offset nStartOffse
 
     if( CSLFetchNameValue( papszOptions, "BLOCKYSIZE" ) != NULL )
         nNPPBV = atoi(CSLFetchNameValue( papszOptions, "BLOCKYSIZE" ));
-    
+
     if( CSLFetchNameValue( papszOptions, "NPPBH" ) != NULL )
         nNPPBH = atoi(CSLFetchNameValue( papszOptions, "NPPBH" ));
-    
+
     if( CSLFetchNameValue( papszOptions, "NPPBV" ) != NULL )
         nNPPBV = atoi(CSLFetchNameValue( papszOptions, "NPPBV" ));
-    
+
     if( nNPPBH <= 0 || nNPPBV <= 0 ||
         nNPPBH > 9999 || nNPPBV > 9999  )
         nNPPBH = nNPPBV = 256;
 
-    int nNBPR = (nXSize + nNPPBH - 1) / nNPPBH;
-    int nNBPC = (nYSize + nNPPBV - 1) / nNPPBV;
+    const int nNBPR = (nXSize + nNPPBH - 1) / nNPPBH;
+    const int nNBPC = (nYSize + nNPPBV - 1) / nNPPBV;
 
 /* -------------------------------------------------------------------- */
 /*  Creates APP6 NITF application segment (required by MIL-STD-188-198) */
 /*  see #3345                                                           */
 /* -------------------------------------------------------------------- */
     GByte abyAPP6[23];
-    GUInt16 nUInt16;
-    int nOffset = 0;
-
     memcpy(abyAPP6, "NITF", 4);
     abyAPP6[4] = 0;
-    nOffset += 5;
+    int nOffset = 5;
 
     /* Version : 2.0 */
-    nUInt16 = 0x0200;
+    GUInt16 nUInt16 = 0x0200;
     CPL_MSBPTR16(&nUInt16);
     memcpy(abyAPP6 + nOffset, &nUInt16, sizeof(nUInt16));
     nOffset += sizeof(nUInt16);
@@ -5442,6 +5476,7 @@ NITFWriteJPEGImage( GDALDataset *poSrcDS, VSILFILE *fp, vsi_l_offset nStartOffse
     nOffset ++;
 
     /* Original sample precision */
+    /* coverity[dead_error_line] */
     abyAPP6[nOffset] = (eDT == GDT_UInt16) ? 12 : 8;
     nOffset ++;
 
@@ -5450,6 +5485,7 @@ NITFWriteJPEGImage( GDALDataset *poSrcDS, VSILFILE *fp, vsi_l_offset nStartOffse
     nOffset ++;
 
     /* JPEG coding process */
+    /* coverity[dead_error_line] */
     abyAPP6[nOffset] = (eDT == GDT_UInt16) ? 4 : 1;
     nOffset ++;
 
@@ -5462,6 +5498,7 @@ NITFWriteJPEGImage( GDALDataset *poSrcDS, VSILFILE *fp, vsi_l_offset nStartOffse
     nOffset ++;
 
     /* Stream bits */
+    /* coverity[dead_error_line] */
     abyAPP6[nOffset] = (eDT == GDT_UInt16) ? 12 : 8;
     nOffset ++;
 
@@ -5485,58 +5522,57 @@ NITFWriteJPEGImage( GDALDataset *poSrcDS, VSILFILE *fp, vsi_l_offset nStartOffse
 /*      Prepare block map if necessary                                  */
 /* -------------------------------------------------------------------- */
 
-    VSIFSeekL( fp, nStartOffset, SEEK_SET );
+    bool bOK = VSIFSeekL( fp, nStartOffset, SEEK_SET ) == 0;
 
     const char* pszIC = CSLFetchNameValue( papszOptions, "IC" );
-    GUInt32  nIMDATOFF = 0;
+    GUInt32 nIMDATOFF = 0;
+    static const GUInt32 BLOCKMAP_HEADER_SIZE = 4 + 2 + 2 + 2;
     if (EQUAL(pszIC, "M3"))
     {
-        GUInt32  nIMDATOFF_MSB;
-        GUInt16  nBMRLNTH, nTMRLNTH, nTPXCDLNTH;
-
         /* Prepare the block map */
-#define BLOCKMAP_HEADER_SIZE    (4 + 2 + 2 + 2)
-        nIMDATOFF_MSB = nIMDATOFF = BLOCKMAP_HEADER_SIZE + nNBPC * nNBPR * 4;
-        nBMRLNTH = 4;
-        nTMRLNTH = 0;
-        nTPXCDLNTH = 0;
+        GUInt32 nIMDATOFF_MSB = BLOCKMAP_HEADER_SIZE + nNBPC * nNBPR * 4;
+        nIMDATOFF = nIMDATOFF_MSB;
+        GUInt16 nBMRLNTH = 4;
+        GUInt16 nTMRLNTH = 0;
+        GUInt16 nTPXCDLNTH = 0;
 
         CPL_MSBPTR32( &nIMDATOFF_MSB );
         CPL_MSBPTR16( &nBMRLNTH );
         CPL_MSBPTR16( &nTMRLNTH );
         CPL_MSBPTR16( &nTPXCDLNTH );
 
-        VSIFWriteL( &nIMDATOFF_MSB, 1, 4, fp );
-        VSIFWriteL( &nBMRLNTH, 1, 2, fp );
-        VSIFWriteL( &nTMRLNTH, 1, 2, fp );
-        VSIFWriteL( &nTPXCDLNTH, 1, 2, fp );
+        bOK &= VSIFWriteL( &nIMDATOFF_MSB, 4, 1, fp ) == 1;
+        bOK &= VSIFWriteL( &nBMRLNTH, 2, 1, fp ) == 1;
+        bOK &= VSIFWriteL( &nTMRLNTH, 2, 1, fp ) == 1;
+        bOK &= VSIFWriteL( &nTPXCDLNTH, 2, 1, fp ) == 1;
 
         /* Reserve space for the table itself */
-        VSIFSeekL( fp, nNBPC * nNBPR * 4, SEEK_CUR );
+        bOK &= VSIFSeekL( fp, nNBPC * nNBPR * 4, SEEK_CUR ) == 0;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Copy each block                                                 */
 /* -------------------------------------------------------------------- */
-    int nBlockXOff, nBlockYOff;
-    for(nBlockYOff=0;nBlockYOff<nNBPC;nBlockYOff++)
+    for( int nBlockYOff=0; bOK && nBlockYOff<nNBPC;nBlockYOff++ )
     {
-        for(nBlockXOff=0;nBlockXOff<nNBPR;nBlockXOff++)
+        for( int nBlockXOff=0; bOK && nBlockXOff<nNBPR;nBlockXOff++ )
         {
-            /*CPLDebug("NITF", "nBlockXOff=%d/%d, nBlockYOff=%d/%d",
-                     nBlockXOff, nNBPR, nBlockYOff, nNBPC);*/
+#ifdef DEBUG_VERBOSE
+            CPLDebug("NITF", "nBlockXOff=%d/%d, nBlockYOff=%d/%d",
+                     nBlockXOff, nNBPR, nBlockYOff, nNBPC);
+#endif
             if (EQUAL(pszIC, "M3"))
             {
                 /* Write block offset for current block */
 
-                GUIntBig nCurPos = VSIFTellL(fp);
-                VSIFSeekL( fp, nStartOffset + BLOCKMAP_HEADER_SIZE + 4 * (nBlockYOff * nNBPR + nBlockXOff), SEEK_SET );
-                GUIntBig nBlockOffset = nCurPos - nStartOffset - nIMDATOFF;
+                const GUIntBig nCurPos = VSIFTellL(fp);
+                bOK &= VSIFSeekL( fp, nStartOffset + BLOCKMAP_HEADER_SIZE + 4 * (nBlockYOff * nNBPR + nBlockXOff), SEEK_SET ) == 0;
+                const GUIntBig nBlockOffset = nCurPos - nStartOffset - nIMDATOFF;
                 GUInt32 nBlockOffset32 = (GUInt32)nBlockOffset;
                 if (nBlockOffset == (GUIntBig)nBlockOffset32)
                 {
                     CPL_MSBPTR32( &nBlockOffset32 );
-                    VSIFWriteL( &nBlockOffset32, 1, 4, fp );
+                    bOK &= VSIFWriteL( &nBlockOffset32, 4, 1, fp ) == 1;
                 }
                 else
                 {
@@ -5545,17 +5581,23 @@ NITFWriteJPEGImage( GDALDataset *poSrcDS, VSILFILE *fp, vsi_l_offset nStartOffse
                             nBlockXOff, nBlockYOff, nBlockOffset);
 
                     nBlockOffset32 = 0xffffffff;
-                    int i;
-                    for(i=nBlockYOff * nNBPR + nBlockXOff; i < nNBPC * nNBPR; i++)
+                    for( int i = nBlockYOff * nNBPR + nBlockXOff;
+                         bOK && i < nNBPC * nNBPR;
+                         i++ )
                     {
-                        VSIFWriteL( &nBlockOffset32, 1, 4, fp );
+                        bOK &= VSIFWriteL( &nBlockOffset32, 4, 1, fp ) == 1;
                     }
-                    return FALSE;
+                    if( !bOK )
+                    {
+                        CPLError(CE_Failure, CPLE_FileIO,
+                                 "I/O error");
+                    }
+                    return bOK;
                 }
-                VSIFSeekL( fp, nCurPos, SEEK_SET );
+                bOK &= VSIFSeekL( fp, nCurPos, SEEK_SET ) == 0;
             }
 
-            if (!NITFWriteJPEGBlock(poSrcDS, fp,
+            if (bOK && !NITFWriteJPEGBlock(poSrcDS, fp,
                                     nBlockXOff, nBlockYOff,
                                     nNPPBH, nNPPBV,
                                     bProgressive, nQuality,
@@ -5563,11 +5605,16 @@ NITFWriteJPEGImage( GDALDataset *poSrcDS, VSILFILE *fp, vsi_l_offset nStartOffse
                                     nRestartInterval,
                                     pfnProgress, pProgressData))
             {
-                return FALSE;
+                return false;
             }
         }
     }
-    return TRUE;
+    if( !bOK )
+    {
+        CPLError(CE_Failure, CPLE_FileIO,
+                    "I/O error");
+    }
+    return true;
 }
 
 #endif /* def JPEG_SUPPORTED */
@@ -5638,7 +5685,7 @@ static const NITFFieldDescription asFieldDescription [] =
 };
 
 /* Keep in sync with NITFWriteBLOCKA */
-static const char *apszFieldsBLOCKA[] = { 
+static const char * const apszFieldsBLOCKA[] = {
         "BLOCK_INSTANCE", "0", "2",
         "N_GRAY",         "2", "5",
         "L_LINES",        "7", "5",
@@ -5654,14 +5701,10 @@ static const char *apszFieldsBLOCKA[] = {
 void GDALRegister_NITF()
 
 {
-    GDALDriver	*poDriver;
-
-    if( GDALGetDriverByName( "NITF" ) == NULL )
-    {
-        unsigned int i;
-        CPLString osCreationOptions;
+    if( GDALGetDriverByName( "NITF" ) != NULL )
+        return;
 
-        osCreationOptions =
+    CPLString osCreationOptions =
 "<CreationOptionList>"
 "   <Option name='IC' type='string-select' default='NC' description='Compression mode. NC=no compression. "
 #ifdef JPEG_SUPPORTED
@@ -5702,7 +5745,7 @@ void GDALRegister_NITF()
 "   </Option>"
 "   <Option name='IREP' type='string' description='Set to RGB/LUT to reserve space for a color table for each output band. (Only needed for Create() method, not CreateCopy())'/>"
 "   <Option name='IREPBAND' type='string' description='Comma separated list of band IREPBANDs in band order'/>"
-"   <Option name='ISUBCAT' type='string' description='Comma separated list of band ISUBCATs in band order'/>" 
+"   <Option name='ISUBCAT' type='string' description='Comma separated list of band ISUBCATs in band order'/>"
 "   <Option name='LUT_SIZE' type='integer' description='Set to control the size of pseudocolor tables for RGB/LUT bands' default='256'/>"
 "   <Option name='BLOCKXSIZE' type='int' description='Set the block width'/>"
 "   <Option name='BLOCKYSIZE' type='int' description='Set the block height'/>"
@@ -5710,49 +5753,52 @@ void GDALRegister_NITF()
 "   <Option name='TEXT' type='string' description='TEXT options as text-option-name=text-option-content'/>"
 "   <Option name='CGM' type='string' description='CGM options in cgm-option-name=cgm-option-content'/>";
 
-        for(i=0;i<sizeof(asFieldDescription) / sizeof(asFieldDescription[0]); i++)
-        {
-            osCreationOptions += CPLString().Printf("   <Option name='%s' type='string' description='%s' maxsize='%d'/>",
-                    asFieldDescription[i].pszName, asFieldDescription[i].pszDescription, asFieldDescription[i].nMaxLen);
-        }
+    for( unsigned int i=0;
+         i < sizeof(asFieldDescription) / sizeof(asFieldDescription[0]);
+         i++)
+    {
+        osCreationOptions += CPLString().Printf(
+            "   <Option name='%s' type='string' description='%s' maxsize='%d'/>",
+            asFieldDescription[i].pszName, asFieldDescription[i].pszDescription, asFieldDescription[i].nMaxLen);
+    }
 
-        osCreationOptions +=
+    osCreationOptions +=
 "   <Option name='TRE' type='string' description='Under the format TRE=tre-name,tre-contents'/>"
 "   <Option name='FILE_TRE' type='string' description='Under the format FILE_TRE=tre-name,tre-contents'/>"
 "   <Option name='BLOCKA_BLOCK_COUNT' type='int'/>";
 
-        for(i=0; apszFieldsBLOCKA[i] != NULL; i+=3)
-        {
-            char szFieldDescription[128];
-            sprintf(szFieldDescription, "   <Option name='BLOCKA_%s_*' type='string' maxsize='%d'/>",
-                    apszFieldsBLOCKA[i], atoi(apszFieldsBLOCKA[i+2]));
-            osCreationOptions += szFieldDescription;
-        }
-        osCreationOptions +=
-"   <Option name='SDE_TRE' type='boolean' description='Write GEOLOB and GEOPSB TREs (only geographic SRS for now)' default='NO'/>";
-        osCreationOptions += "</CreationOptionList>";
-
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "NITF" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "National Imagery Transmission Format" );
-        
-        poDriver->pfnIdentify = NITFDataset::Identify;
-        poDriver->pfnOpen = NITFDataset::Open;
-        poDriver->pfnCreate = NITFDataset::NITFDatasetCreate;
-        poDriver->pfnCreateCopy = NITFDataset::NITFCreateCopy;
-
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_nitf.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "ntf" );
-        poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte UInt16 Int16 UInt32 Int32 Float32" );
-
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, osCreationOptions);
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
+    for( unsigned int i=0; apszFieldsBLOCKA[i] != NULL; i+=3 )
+    {
+        char szFieldDescription[128];
+        snprintf(szFieldDescription, sizeof(szFieldDescription),
+                 "   <Option name='BLOCKA_%s_*' type='string' maxsize='%d'/>",
+                apszFieldsBLOCKA[i], atoi(apszFieldsBLOCKA[i+2]));
+        osCreationOptions += szFieldDescription;
     }
+    osCreationOptions +=
+"   <Option name='SDE_TRE' type='boolean' description='Write GEOLOB and GEOPSB TREs (only geographic SRS for now)' default='NO'/>";
+    osCreationOptions += "</CreationOptionList>";
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "NITF" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "National Imagery Transmission Format" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_nitf.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "ntf" );
+    poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte UInt16 Int16 UInt32 Int32 Float32" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, osCreationOptions);
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnIdentify = NITFDataset::Identify;
+    poDriver->pfnOpen = NITFDataset::Open;
+    poDriver->pfnCreate = NITFDataset::NITFDatasetCreate;
+    poDriver->pfnCreateCopy = NITFDataset::NITFCreateCopy;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/nitf/nitfdataset.h b/frmts/nitf/nitfdataset.h
index c868da2..adeada9 100644
--- a/frmts/nitf/nitfdataset.h
+++ b/frmts/nitf/nitfdataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nitfdataset.h 28899 2015-04-14 09:27:00Z rouault $
+ * $Id: nitfdataset.h 33794 2016-03-26 13:19:07Z goatbar $
  *
  * Project:  NITF Read/Write Translator
  * Purpose:  GDALDataset/GDALRasterBand declarations.
@@ -37,7 +37,7 @@
 #include "gdal_proxy.h"
 #include <map>
 
-CPLErr NITFSetColorInterpretation( NITFImage *psImage, 
+CPLErr NITFSetColorInterpretation( NITFImage *psImage,
                                    int nBand,
                                    GDALColorInterp eInterp );
 
@@ -70,10 +70,10 @@ class NITFDataset : public GDALPamDataset
     NITFFile    *psFile;
     NITFImage   *psImage;
 
-    GDALPamDataset *poJ2KDataset;
+    GDALDataset *poJ2KDataset;
     int         bJP2Writing;
 
-    GDALPamDataset *poJPEGDataset;
+    GDALDataset *poJPEGDataset;
 
     int         bGotGeoTransform;
     double      adfGeoTransform[6];
@@ -114,9 +114,9 @@ class NITFDataset : public GDALPamDataset
 
     char       **papszTextMDToWrite;
     char       **papszCgmMDToWrite;
-    
+
     int          bInLoadXML;
-    
+
     int          bExposeUnderlyingJPEGDatasetOverviews;
     int          ExposeUnderlyingJPEGDatasetOverviews() const { return bExposeUnderlyingJPEGDatasetOverviews; }
 
@@ -125,11 +125,11 @@ class NITFDataset : public GDALPamDataset
 
   public:
                  NITFDataset();
-                 ~NITFDataset();
+    virtual ~NITFDataset();
 
     virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
-                               int nBufXSize, int nBufYSize, 
-                               GDALDataType eDT, 
+                               int nBufXSize, int nBufYSize,
+                               GDALDataType eDT,
                                int nBandCount, int *panBandList,
                                char **papszOptions );
 
@@ -166,7 +166,7 @@ class NITFDataset : public GDALPamDataset
     static GDALDataset *Open( GDALOpenInfo * );
     static GDALDataset *
     NITFCreateCopy( const char *pszFilename, GDALDataset *poSrcDS,
-                    int bStrict, char **papszOptions, 
+                    int bStrict, char **papszOptions,
                     GDALProgressFunc pfnProgress, void * pProgressData );
     static GDALDataset *
              NITFDatasetCreate( const char *pszFilename,
@@ -195,7 +195,7 @@ class NITFRasterBand : public GDALPamRasterBand
 
   public:
                    NITFRasterBand( NITFDataset *, int );
-                  ~NITFRasterBand();
+    virtual ~NITFRasterBand();
 
     virtual CPLErr IReadBlock( int, int, void * );
     virtual CPLErr IWriteBlock( int, int, void * );
@@ -203,7 +203,7 @@ class NITFRasterBand : public GDALPamRasterBand
     virtual GDALColorInterp GetColorInterpretation();
     virtual CPLErr SetColorInterpretation( GDALColorInterp );
     virtual GDALColorTable *GetColorTable();
-    virtual CPLErr SetColorTable( GDALColorTable * ); 
+    virtual CPLErr SetColorTable( GDALColorTable * );
     virtual double GetNoDataValue( int *pbSuccess = NULL );
 
     void Unpack(GByte* pData);
@@ -218,7 +218,7 @@ class NITFRasterBand : public GDALPamRasterBand
 /* This class is potentially of general interest and could be moved to gdal_proxy.h */
 /* We don't proxy all methods. Generally speaking, the getters go to PAM first and */
 /* then to the underlying band if no value exist in PAM. The setters aren't */
-/* overriden, so they go to PAM */
+/* overridden, so they go to PAM */
 
 class NITFProxyPamRasterBand : public GDALPamRasterBand
 {
@@ -237,7 +237,7 @@ class NITFProxyPamRasterBand : public GDALPamRasterBand
                                 GDALRasterIOExtraArg* psExtraArg);
 
     public:
-                         ~NITFProxyPamRasterBand();
+        virtual ~NITFProxyPamRasterBand();
 
         virtual char      **GetMetadata( const char * pszDomain = ""  );
         /*virtual CPLErr      SetMetadata( char ** papszMetadata,
@@ -340,18 +340,17 @@ class NITFWrapperRasterBand : public NITFProxyPamRasterBand
                    NITFWrapperRasterBand( NITFDataset * poDS,
                                           GDALRasterBand* poBaseBand,
                                           int nBand);
-                  ~NITFWrapperRasterBand();
-    
+    virtual ~NITFWrapperRasterBand();
+
     /* Methods from GDALRasterBand we want to override */
     virtual GDALColorInterp GetColorInterpretation();
     virtual CPLErr          SetColorInterpretation( GDALColorInterp );
-    
+
     virtual GDALColorTable *GetColorTable();
 
     virtual int             GetOverviewCount();
     virtual GDALRasterBand *GetOverview(int);
 
     /* Specific method */
-    void                    SetColorTableFromNITFBandInfo(); 
+    void                    SetColorTableFromNITFBandInfo();
 };
-
diff --git a/frmts/nitf/nitfdes.c b/frmts/nitf/nitfdes.c
index 4049063..e264853 100644
--- a/frmts/nitf/nitfdes.c
+++ b/frmts/nitf/nitfdes.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nitfdes.c 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: nitfdes.c 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  NITF Read/Write Library
  * Purpose:  Module responsible for implementation of DE segments.
@@ -33,7 +33,9 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: nitfdes.c 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: nitfdes.c 33717 2016-03-14 06:29:14Z goatbar $");
+
+CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused) {}
 
 /************************************************************************/
 /*                          NITFDESAccess()                             */
@@ -49,7 +51,7 @@ NITFDES *NITFDESAccess( NITFFile *psFile, int iSegment )
     int        nOffset;
     int        bHasDESOFLW;
     int        nDESSHL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Verify segment, and return existing DES accessor if there       */
 /*      is one.                                                         */
@@ -75,21 +77,19 @@ NITFDES *NITFDESAccess( NITFFile *psFile, int iSegment )
         return NULL;
     }
 
-    pachHeader = (char*) VSIMalloc(psSegInfo->nSegmentHeaderSize);
+    pachHeader = (char*) VSI_MALLOC_VERBOSE(psSegInfo->nSegmentHeaderSize);
     if (pachHeader == NULL)
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory,
-                 "Cannot allocate memory for segment header");
         return NULL;
     }
 
 retry:
-    if( VSIFSeekL( psFile->fp, psSegInfo->nSegmentHeaderStart, 
-                  SEEK_SET ) != 0 
-        || VSIFReadL( pachHeader, 1, psSegInfo->nSegmentHeaderSize, 
+    if( VSIFSeekL( psFile->fp, psSegInfo->nSegmentHeaderStart,
+                  SEEK_SET ) != 0
+        || VSIFReadL( pachHeader, 1, psSegInfo->nSegmentHeaderSize,
                      psFile->fp ) != psSegInfo->nSegmentHeaderSize )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   "Failed to read %u byte DES subheader from " CPL_FRMT_GUIB ".",
                   psSegInfo->nSegmentHeaderSize,
                   psSegInfo->nSegmentHeaderStart );
@@ -97,9 +97,9 @@ retry:
         return NULL;
     }
 
-    if (!EQUALN(pachHeader, "DE", 2))
+    if (!STARTS_WITH_CI(pachHeader, "DE"))
     {
-        if (EQUALN(pachHeader + 4, "DERegistered", 12))
+        if (STARTS_WITH_CI(pachHeader + 4, "DERegistered"))
         {
             /* BAO_46_Ed1/rpf/conc/concz10/000fz010.ona and cie are buggy */
             CPLDebug("NITF", "Patching nSegmentHeaderStart and nSegmentStart for DE segment %d", iSegment);
@@ -161,7 +161,7 @@ retry:
     /* For NITF < 02.10, we cannot rely on DESID=TRE_OVERFLOW to detect */
     /* if DESOFLW and DESITEM are present. So if the next 4 bytes are non */
     /* numeric, we'll assume that DESOFLW is there */
-    bHasDESOFLW = EQUALN(szDESID, "TRE_OVERFLOW", strlen("TRE_OVERFLOW")) ||
+    bHasDESOFLW = STARTS_WITH_CI(szDESID, "TRE_OVERFLOW") ||
        (!((pachHeader[nOffset+0] >= '0' && pachHeader[nOffset+0] <= '9') &&
           (pachHeader[nOffset+1] >= '0' && pachHeader[nOffset+1] <= '9') &&
           (pachHeader[nOffset+2] >= '0' && pachHeader[nOffset+2] <= '9') &&
@@ -206,7 +206,7 @@ retry:
         return NULL;
     }
 
-    if (EQUALN(szDESID, "CSSHPA DES", strlen("CSSHPA DES")))
+    if (STARTS_WITH_CI(szDESID, "CSSHPA DES"))
     {
         if ( nDESSHL != 62 && nDESSHL != 80)
         {
@@ -227,7 +227,7 @@ retry:
         GetMD(  3, SHAPE3_NAME );
         GetMD(  6, SHAPE3_START );
     }
-    else if (EQUALN(szDESID, "XML_DATA_CONTENT", strlen("XML_DATA_CONTENT")))
+    else if (STARTS_WITH_CI(szDESID, "XML_DATA_CONTENT"))
     {
         /* TODO : handle nDESSHL = 0005 and 0283 */
         if (nDESSHL >= 5)
@@ -253,7 +253,7 @@ retry:
             }
         }
     }
-    else if (EQUALN(szDESID, "CSATTA DES", strlen("CSATTA DES")) && nDESSHL == 52)
+    else if (STARTS_WITH_CI(szDESID, "CSATTA DES") && nDESSHL == 52)
     {
         GetMD( 12, ATT_TYPE );
         GetMD( 14, DT_ATT );
@@ -267,8 +267,8 @@ retry:
     if ((int)psSegInfo->nSegmentHeaderSize > nOffset)
     {
         char* pszEscapedDESDATA =
-                CPLEscapeString( pachHeader + nOffset, 
-                                 (int)psSegInfo->nSegmentHeaderSize - nOffset, 
+                CPLEscapeString( pachHeader + nOffset,
+                                 (int)psSegInfo->nSegmentHeaderSize - nOffset,
                                  CPLES_BackslashQuotable );
         psDES->papszMetadata = CSLSetNameValue( psDES->papszMetadata,
                                                 "NITF_DESDATA",
@@ -279,27 +279,25 @@ retry:
     {
 
 #define TEN_MEGABYTES 10485760
-            
+
         if (psSegInfo->nSegmentSize > TEN_MEGABYTES)
         {
             const char* pszOffset = CPLSPrintf(CPL_FRMT_GUIB, psFile->pasSegmentInfo[iSegment].nSegmentStart);
             const char* pszSize = CPLSPrintf(CPL_FRMT_GUIB, psFile->pasSegmentInfo[iSegment].nSegmentSize);
-            
+
             psDES->papszMetadata = CSLSetNameValue( psDES->papszMetadata,
                                                     "NITF_DESDATA_OFFSET",
                                                     pszOffset );
             psDES->papszMetadata = CSLSetNameValue( psDES->papszMetadata,
                                                     "NITF_DESDATA_LENGTH",
                                                     pszSize);
-            
         }
         else
         {
-            char* pachData = (char*)VSIMalloc((size_t)psSegInfo->nSegmentSize);
+            char* pachData = (char*)VSI_MALLOC_VERBOSE((size_t)psSegInfo->nSegmentSize);
             if (pachData == NULL )
             {
-                CPLDebug("NITF", "Cannot allocate " CPL_FRMT_GUIB " bytes DES data",
-                         psSegInfo->nSegmentSize);
+                /* nothing */
             }
             else if( VSIFSeekL( psFile->fp, psSegInfo->nSegmentStart,
                         SEEK_SET ) != 0
@@ -321,14 +319,13 @@ retry:
                                                         "NITF_DESDATA",
                                                         pszEscapedDESDATA );
                 CPLFree(pszEscapedDESDATA);
-                
             }
             CPLFree(pachData);
         }
 
 #ifdef notdef
         /* Disabled because might generate a huge amount of elements */
-        if (EQUALN(szDESID, "CSATTA DES", strlen("CSATTA DES")))
+        if (STARTS_WITH_CI(szDESID, "CSATTA DES"))
         {
             int nNumAtt = atoi(CSLFetchNameValueDef(psDES->papszMetadata, "NITF_NUM_ATT", "0"));
             if (nNumAtt * 8 * 4 == psSegInfo->nSegmentSize)
@@ -360,7 +357,6 @@ retry:
         }
 #endif
 
-        
     }
 
     return psDES;
@@ -432,14 +428,13 @@ int   NITFDESGetTRE( NITFDES* psDES,
     if ((size_t)nOffset >= psSegInfo->nSegmentSize)
         return FALSE;
 
-    VSIFSeekL(fp, psSegInfo->nSegmentStart + nOffset, SEEK_SET);
-
-    if (VSIFReadL(szTREHeader, 1, 11, fp) != 11)
+    if( VSIFSeekL(fp, psSegInfo->nSegmentStart + nOffset, SEEK_SET) != 0 ||
+        VSIFReadL(szTREHeader, 1, 11, fp) != 11)
     {
-        /* Some files have a nSegmentSize larger than what is is in reality */
-        /* So exit silently if we're at end of file */ 
-        VSIFSeekL(fp, 0, SEEK_END);
-        if (VSIFTellL(fp) == psSegInfo->nSegmentStart + nOffset)
+        /* Some files have a nSegmentSize larger than what it is in reality */
+        /* So exit silently if we're at end of file */
+        if( VSIFSeekL(fp, 0, SEEK_END) != 0 ||
+            VSIFTellL(fp) == psSegInfo->nSegmentStart + nOffset)
             return FALSE;
 
         CPLError(CE_Failure, CPLE_FileIO,
@@ -472,12 +467,9 @@ int   NITFDESGetTRE( NITFDES* psDES,
     if (ppabyTREData)
     {
         /* Allocate one extra byte for the NULL terminating character */
-        *ppabyTREData = (char*) VSIMalloc(nTRESize + 1);
+        *ppabyTREData = (char*) VSI_MALLOC_VERBOSE(nTRESize + 1);
         if (*ppabyTREData  == NULL)
         {
-            CPLError(CE_Failure, CPLE_OutOfMemory,
-                    "Cannot allocate %d bytes for TRE %s",
-                    nTRESize, szTRETempName);
             return FALSE;
         }
         (*ppabyTREData)[nTRESize] = '\0';
@@ -521,6 +513,7 @@ int NITFDESExtractShapefile(NITFDES* psDES, const char* pszRadixFileName)
     int anOffset[4];
     int iShpFile;
     char* pszFilename;
+    size_t nFilenameLen;
 
     if ( CSLFetchNameValue(psDES->papszMetadata, "NITF_SHAPE_USE") == NULL )
         return FALSE;
@@ -547,7 +540,8 @@ int NITFDESExtractShapefile(NITFDES* psDES, const char* pszRadixFileName)
             return FALSE;
     }
 
-    pszFilename = (char*) VSIMalloc(strlen(pszRadixFileName) + 4 + 1);
+    nFilenameLen = strlen(pszRadixFileName) + 4 + 1;
+    pszFilename = (char*) VSI_MALLOC_VERBOSE(nFilenameLen);
     if (pszFilename == NULL)
         return FALSE;
 
@@ -557,22 +551,22 @@ int NITFDESExtractShapefile(NITFDES* psDES, const char* pszRadixFileName)
         GByte* pabyBuffer;
         int nSize = anOffset[iShpFile+1] - anOffset[iShpFile];
 
-        pabyBuffer = (GByte*) VSIMalloc(nSize);
+        pabyBuffer = (GByte*) VSI_MALLOC_VERBOSE(nSize);
         if (pabyBuffer == NULL)
         {
             VSIFree(pszFilename);
             return FALSE;
         }
 
-        VSIFSeekL(psDES->psFile->fp, psSegInfo->nSegmentStart + anOffset[iShpFile], SEEK_SET);
-        if (VSIFReadL(pabyBuffer, 1, nSize, psDES->psFile->fp) != (size_t)nSize)
+        if( VSIFSeekL(psDES->psFile->fp, psSegInfo->nSegmentStart + anOffset[iShpFile], SEEK_SET) != 0 ||
+            VSIFReadL(pabyBuffer, 1, nSize, psDES->psFile->fp) != (size_t)nSize)
         {
             VSIFree(pabyBuffer);
             VSIFree(pszFilename);
             return FALSE;
         }
 
-        sprintf(pszFilename, "%s.%s", pszRadixFileName, apszExt[iShpFile]);
+        snprintf(pszFilename, nFilenameLen, "%s.%s", pszRadixFileName, apszExt[iShpFile]);
         fp = VSIFOpenL(pszFilename, "wb");
         if (fp == NULL)
         {
@@ -581,8 +575,14 @@ int NITFDESExtractShapefile(NITFDES* psDES, const char* pszRadixFileName)
             return FALSE;
         }
 
-        VSIFWriteL(pabyBuffer, 1, nSize, fp);
-        VSIFCloseL(fp);
+        if( (int) VSIFWriteL(pabyBuffer, 1, nSize, fp) != nSize )
+        {
+            CPL_IGNORE_RET_VAL_INT(VSIFCloseL(fp));
+            VSIFree(pabyBuffer);
+            VSIFree(pszFilename);
+            return FALSE;
+        }
+        CPL_IGNORE_RET_VAL_INT(VSIFCloseL(fp));
         VSIFree(pabyBuffer);
     }
 
diff --git a/frmts/nitf/nitfdump.c b/frmts/nitf/nitfdump.c
index 08472c2..30fe768 100644
--- a/frmts/nitf/nitfdump.c
+++ b/frmts/nitf/nitfdump.c
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: nitfdump.c 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: nitfdump.c 33757 2016-03-20 20:22:33Z goatbar $
  *
  * Project:  NITF Read/Write Library
- * Purpose:  Simple test mainline to dump info about NITF file. 
+ * Purpose:  Simple test mainline to dump info about NITF file.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  **********************************************************************
@@ -33,11 +33,9 @@
 #include "cpl_multiproc.h"
 #include "cpl_vsi.h"
 
-#ifdef OGR_ENABLED
 #include "ogr_api.h"
-#endif
 
-CPL_CVSID("$Id: nitfdump.c 27044 2014-03-16 23:41:27Z rouault $");
+CPL_CVSID("$Id: nitfdump.c 33757 2016-03-20 20:22:33Z goatbar $");
 
 static void DumpRPC( NITFImage *psImage, NITFRPC00BInfo *psRPC );
 static void DumpMetadata( const char *, const char *, char ** );
@@ -55,7 +53,7 @@ static void DumpMetadata( const char *, const char *, char ** );
 /*      buffer and zero terminate it.                                   */
 /************************************************************************/
 
-char *NITFGetField( char *pszTarget, const char *pszSource, 
+char *NITFGetField( char *pszTarget, const char *pszSource,
                     int nStart, int nLength )
 
 {
@@ -140,11 +138,9 @@ NITFLocation* NITFReadRPFLocationTable(VSILFILE* fp, int* pnLocCount)
 
     VSIFSeekL(fp, nCurOffset + nLocSectionOffset, SEEK_SET);
 
-    pasLocations = (NITFLocation *)  VSICalloc(sizeof(NITFLocation), nLocCount);
+    pasLocations = (NITFLocation *)  VSI_CALLOC_VERBOSE(sizeof(NITFLocation), nLocCount);
     if (pasLocations == NULL)
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory,
-                 "Cannot allocate memory for location table");
         return NULL;
     }
 
@@ -206,7 +202,7 @@ static const LocationNameId asLocationTable[] =
     { "ColorTableIndexRecord", 153 }
 };
 
-const char* GetLocationNameFromId(int nID)
+static const char* GetLocationNameFromId(int nID)
 {
     unsigned int i;
     for(i=0;i<sizeof(asLocationTable) / sizeof(asLocationTable[0]);i++)
@@ -235,7 +231,7 @@ int main( int nArgc, char ** papszArgv )
         printf( "Usage: nitfdump [-tre] [-extractshp | -extractshpinmem] <nitf_filename>*\n" );
         exit( 1 );
     }
-    
+
     for( iFile = 1; iFile < nArgc; iFile++ )
     {
         if ( EQUAL(papszArgv[iFile], "-tre") )
@@ -339,18 +335,18 @@ int main( int nArgc, char ** papszArgv )
         {
             NITFSegmentInfo *psSegInfo = psFile->pasSegmentInfo + iSegment;
 
-            printf( "Segment %d (Type=%s):\n", 
+            printf( "Segment %d (Type=%s):\n",
                     iSegment + 1, psSegInfo->szSegmentType );
 
             printf( "  HeaderStart=" CPL_FRMT_GUIB ", HeaderSize=%u, DataStart=" CPL_FRMT_GUIB ", DataSize=" CPL_FRMT_GUIB "\n",
                     psSegInfo->nSegmentHeaderStart,
-                    psSegInfo->nSegmentHeaderSize, 
+                    psSegInfo->nSegmentHeaderSize,
                     psSegInfo->nSegmentStart,
                     psSegInfo->nSegmentSize );
             printf( "  DLVL=%d, ALVL=%d, LOC=C%d,R%d, CCS=C%d,R%d\n",
-                    psSegInfo->nDLVL, 
-                    psSegInfo->nALVL, 
-                    psSegInfo->nLOC_C, 
+                    psSegInfo->nDLVL,
+                    psSegInfo->nALVL,
+                    psSegInfo->nLOC_C,
                     psSegInfo->nLOC_R,
                     psSegInfo->nCCS_C,
                     psSegInfo->nCCS_R );
@@ -370,7 +366,7 @@ int main( int nArgc, char ** papszArgv )
 
             if( !EQUAL(psSegInfo->szSegmentType,"IM") )
                 continue;
-        
+
             psImage = NITFImageAccess( psFile, iSegment );
             if( psImage == NULL )
             {
@@ -378,16 +374,16 @@ int main( int nArgc, char ** papszArgv )
                 continue;
             }
 
-            printf( "Image Segment %d, %dPx%dLx%dB x %dbits:\n", 
-                    iSegment + 1, psImage->nCols, psImage->nRows, 
+            printf( "Image Segment %d, %dPx%dLx%dB x %dbits:\n",
+                    iSegment + 1, psImage->nCols, psImage->nRows,
                     psImage->nBands, psImage->nBitsPerSample );
-            printf( "  PVTYPE=%s, IREP=%s, ICAT=%s, IMODE=%c, IC=%s, COMRAT=%s, ICORDS=%c\n", 
+            printf( "  PVTYPE=%s, IREP=%s, ICAT=%s, IMODE=%c, IC=%s, COMRAT=%s, ICORDS=%c\n",
                     psImage->szPVType, psImage->szIREP, psImage->szICAT,
                     psImage->chIMODE, psImage->szIC, psImage->szCOMRAT,
                     psImage->chICORDS );
             if( psImage->chICORDS != ' ' )
             {
-                printf( "  UL=(%.15g,%.15g), UR=(%.15g,%.15g) Center=%d\n  LL=(%.15g,%.15g), LR=(%.15g,%.15g)\n", 
+                printf( "  UL=(%.15g,%.15g), UR=(%.15g,%.15g) Center=%d\n  LL=(%.15g,%.15g), LR=(%.15g,%.15g)\n",
                         psImage->dfULX, psImage->dfULY,
                         psImage->dfURX, psImage->dfURY,
                         psImage->bIsBoxCenterOfPixel,
@@ -396,22 +392,21 @@ int main( int nArgc, char ** papszArgv )
             }
 
             printf( "  IDLVL=%d, IALVL=%d, ILOC R=%d,C=%d, IMAG=%s\n",
-                    psImage->nIDLVL, psImage->nIALVL, 
-                    psImage->nILOCRow, psImage->nILOCColumn, 
+                    psImage->nIDLVL, psImage->nIALVL,
+                    psImage->nILOCRow, psImage->nILOCColumn,
                     psImage->szIMAG );
 
             printf( "  %d x %d blocks of size %d x %d\n",
                     psImage->nBlocksPerRow, psImage->nBlocksPerColumn,
                     psImage->nBlockWidth, psImage->nBlockHeight );
-        
+
             if( psImage->pachTRE != NULL )
             {
                 int nTREBytes = psImage->nTREBytes;
                 const char *pszTREData = psImage->pachTRE;
-            
-            
+
                 printf( "  Image TREs:" );
-            
+
                 while( nTREBytes > 10 )
                 {
                     int nThisTRESize = atoi(NITFGetField(szTemp, pszTREData, 6, 5 ));
@@ -421,7 +416,7 @@ int main( int nArgc, char ** papszArgv )
                         printf(" Invalid size (%d) for TRE %s", nThisTRESize, szTemp);
                         break;
                     }
-                
+
                     printf( " %6.6s(%d)", pszTREData, nThisTRESize );
                     pszTREData += nThisTRESize + 11;
                     nTREBytes -= (nThisTRESize + 11);
@@ -432,7 +427,7 @@ int main( int nArgc, char ** papszArgv )
                 {
                     nTREBytes = psImage->nTREBytes;
                     pszTREData = psImage->pachTRE;
-    
+
                     while( nTREBytes > 10 )
                     {
                         char *pszEscaped;
@@ -441,12 +436,12 @@ int main( int nArgc, char ** papszArgv )
                         {
                             break;
                         }
-    
+
                         pszEscaped = CPLEscapeString( pszTREData + 11, nThisTRESize,
                                                         CPLES_BackslashQuotable );
                         printf( "  TRE '%6.6s' : %s\n", pszTREData, pszEscaped);
                         CPLFree(pszEscaped);
-    
+
                         pszTREData += nThisTRESize + 11;
                         nTREBytes -= (nThisTRESize + 11);
                     }
@@ -461,7 +456,7 @@ int main( int nArgc, char ** papszArgv )
                 printf( "  Location Table\n" );
                 for( i = 0; i < psImage->nLocCount; i++ )
                 {
-                    printf( "    LocName=%s, LocId=%d, Offset=%d, Size=%d\n", 
+                    printf( "    LocName=%s, LocId=%d, Offset=%d, Size=%d\n",
                             GetLocationNameFromId(psImage->pasLocations[i].nLocId),
                             psImage->pasLocations[i].nLocId,
                             psImage->pasLocations[i].nLocOffset,
@@ -521,35 +516,35 @@ int main( int nArgc, char ** papszArgv )
             char achSubheader[298];
             int  nSTYPEOffset;
 
-            if( !EQUAL(psSegInfo->szSegmentType,"GR") 
+            if( !EQUAL(psSegInfo->szSegmentType,"GR")
                 && !EQUAL(psSegInfo->szSegmentType,"SY") )
                 continue;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Load the graphic subheader.                                     */
 /* -------------------------------------------------------------------- */
-            if( VSIFSeekL( psFile->fp, psSegInfo->nSegmentHeaderStart, 
-                           SEEK_SET ) != 0 
-                || VSIFReadL( achSubheader, 1, sizeof(achSubheader), 
+            if( VSIFSeekL( psFile->fp, psSegInfo->nSegmentHeaderStart,
+                           SEEK_SET ) != 0
+                || VSIFReadL( achSubheader, 1, sizeof(achSubheader),
                               psFile->fp ) < 258 )
             {
-                CPLError( CE_Warning, CPLE_FileIO, 
-                          "Failed to read graphic subheader at " CPL_FRMT_GUIB ".", 
+                CPLError( CE_Warning, CPLE_FileIO,
+                          "Failed to read graphic subheader at " CPL_FRMT_GUIB ".",
                           psSegInfo->nSegmentHeaderStart );
                 continue;
             }
 
             // NITF 2.0. (also works for NITF 2.1)
             nSTYPEOffset = 200;
-            if( EQUALN(achSubheader+193,"999998",6) )
+            if( STARTS_WITH_CI(achSubheader+193, "999998") )
                 nSTYPEOffset += 40;
 
 /* -------------------------------------------------------------------- */
 /*      Report some standard info.                                      */
 /* -------------------------------------------------------------------- */
             printf( "Graphic Segment %d, type=%2.2s, sfmt=%c, sid=%10.10s\n",
-                    iSegment + 1, 
-                    achSubheader + 0, 
+                    iSegment + 1,
+                    achSubheader + 0,
                     achSubheader[nSTYPEOffset],
                     achSubheader + 2 );
 
@@ -602,13 +597,13 @@ int main( int nArgc, char ** papszArgv )
 
             /* Allocate one extra byte for the NULL terminating character */
             pabyTextData = (char *) CPLCalloc(1,(size_t)psSegment->nSegmentSize+1);
-            if( VSIFSeekL( psFile->fp, psSegment->nSegmentStart, 
-                        SEEK_SET ) != 0 
-                || VSIFReadL( pabyTextData, 1, (size_t)psSegment->nSegmentSize, 
+            if( VSIFSeekL( psFile->fp, psSegment->nSegmentStart,
+                        SEEK_SET ) != 0
+                || VSIFReadL( pabyTextData, 1, (size_t)psSegment->nSegmentSize,
                             psFile->fp ) != psSegment->nSegmentSize )
             {
-                CPLError( CE_Warning, CPLE_FileIO, 
-                        "Failed to read " CPL_FRMT_GUIB " bytes of text data at " CPL_FRMT_GUIB ".", 
+                CPLError( CE_Warning, CPLE_FileIO,
+                        "Failed to read " CPL_FRMT_GUIB " bytes of text data at " CPL_FRMT_GUIB ".",
                         psSegment->nSegmentSize,
                         psSegment->nSegmentStart );
                 CPLFree( pabyTextData );
@@ -635,7 +630,7 @@ int main( int nArgc, char ** papszArgv )
 
             if( !EQUAL(psSegInfo->szSegmentType,"DE") )
                 continue;
-        
+
             psDES = NITFDESAccess( psFile, iSegment );
             if( psDES == NULL )
             {
@@ -687,7 +682,7 @@ int main( int nArgc, char ** papszArgv )
                     printf( "  Location Table\n" );
                     for( i = 0; i < nLocCount; i++ )
                     {
-                        printf( "    LocName=%s, LocId=%d, Offset=%d, Size=%d\n", 
+                        printf( "    LocName=%s, LocId=%d, Offset=%d, Size=%d\n",
                                 GetLocationNameFromId(pasLocations[i].nLocId),
                                 pasLocations[i].nLocId,
                                 pasLocations[i].nLocOffset,
@@ -706,16 +701,15 @@ int main( int nArgc, char ** papszArgv )
                 char szFilename[32];
                 char szRadix[32];
                 if (bExtractSHPInMem)
-                    sprintf(szRadix, "/vsimem/nitf_segment_%d", iSegment + 1);
+                    snprintf(szRadix, sizeof(szRadix), "/vsimem/nitf_segment_%d", iSegment + 1);
                 else
-                    sprintf(szRadix, "nitf_segment_%d", iSegment + 1);
+                    snprintf(szRadix, sizeof(szRadix), "nitf_segment_%d", iSegment + 1);
 
                 if (NITFDESExtractShapefile(psDES, szRadix))
                 {
-#ifdef OGR_ENABLED
                     OGRDataSourceH hDS;
                     OGRRegisterAll();
-                    sprintf(szFilename, "%s.SHP", szRadix);
+                    snprintf(szFilename, sizeof(szFilename), "%s.SHP", szRadix);
                     hDS = OGROpen(szFilename, FALSE, NULL);
                     if (hDS)
                     {
@@ -741,16 +735,15 @@ int main( int nArgc, char ** papszArgv )
                         }
                         OGR_DS_Destroy(hDS);
                     }
-#endif
                 }
 
                 if (bExtractSHPInMem)
                 {
-                    sprintf(szFilename, "%s.SHP", szRadix);
+                    snprintf(szFilename, sizeof(szFilename), "%s.SHP", szRadix);
                     VSIUnlink(szFilename);
-                    sprintf(szFilename, "%s.SHX", szRadix);
+                    snprintf(szFilename, sizeof(szFilename), "%s.SHX", szRadix);
                     VSIUnlink(szFilename);
-                    sprintf(szFilename, "%s.DBF", szRadix);
+                    snprintf(szFilename, sizeof(szFilename), "%s.DBF", szRadix);
                     VSIUnlink(szFilename);
                 }
             }
@@ -761,13 +754,11 @@ int main( int nArgc, char ** papszArgv )
 /* -------------------------------------------------------------------- */
         NITFClose( psFile );
     }
-    
+
     CPLFinderClean();
     CPLCleanupTLS();
     VSICleanupFileManager();
-#ifdef OGR_ENABLED
     OGRCleanupAll();
-#endif
 
     exit( 0 );
 }
@@ -776,7 +767,7 @@ int main( int nArgc, char ** papszArgv )
 /*                            DumpMetadata()                            */
 /************************************************************************/
 
-static void DumpMetadata( const char *pszTitle, const char *pszPrefix, 
+static void DumpMetadata( const char *pszTitle, const char *pszPrefix,
                           char ** papszMD )
 {
     int i;
@@ -826,7 +817,7 @@ static void DumpRPC( NITFImage *psImage, NITFRPC00BInfo *psRPC )
         else if( (i%5) == 4  )
             printf( "\n                     " );
     }
-    
+
     printf( "    LINE_DEN_COEFF = " );
     for( i=0; i < 20; i++ )
     {
@@ -837,7 +828,7 @@ static void DumpRPC( NITFImage *psImage, NITFRPC00BInfo *psRPC )
         else if( (i%5) == 4  )
             printf( "\n                     " );
     }
-    
+
     printf( "    SAMP_NUM_COEFF = " );
     for( i=0; i < 20; i++ )
     {
@@ -848,7 +839,7 @@ static void DumpRPC( NITFImage *psImage, NITFRPC00BInfo *psRPC )
         else if( (i%5) == 4  )
             printf( "\n                     " );
     }
-    
+
     printf( "    SAMP_DEN_COEFF = " );
     for( i=0; i < 20; i++ )
     {
@@ -864,23 +855,23 @@ static void DumpRPC( NITFImage *psImage, NITFRPC00BInfo *psRPC )
 /*      Dump some known locations.                                      */
 /* -------------------------------------------------------------------- */
     {
-        double adfLong[] = { psImage->dfULX, psImage->dfURX, 
-                             psImage->dfLLX, psImage->dfLRX, 
+        double adfLong[] = { psImage->dfULX, psImage->dfURX,
+                             psImage->dfLLX, psImage->dfLRX,
                              (psImage->dfULX + psImage->dfLRX) / 2,
                              (psImage->dfULX + psImage->dfLRX) / 2 };
-        double adfLat[] = { psImage->dfULY, psImage->dfURY, 
-                            psImage->dfLLY, psImage->dfLRY, 
+        double adfLat[] = { psImage->dfULY, psImage->dfURY,
+                            psImage->dfLLY, psImage->dfLRY,
                             (psImage->dfULY + psImage->dfLRY) / 2,
                             (psImage->dfULY + psImage->dfLRY) / 2 };
         double adfHeight[] = { 0.0, 0.0, 0.0, 0.0, 0.0, 300.0 };
         double dfPixel, dfLine;
-        
+
         for( i = 0; i < sizeof(adfLong) / sizeof(double); i++ )
         {
-            NITFRPCGeoToImage( psRPC, adfLong[i], adfLat[i], adfHeight[i], 
+            NITFRPCGeoToImage( psRPC, adfLong[i], adfLat[i], adfHeight[i],
                                &dfPixel, &dfLine );
-            
-            printf( "    RPC Transform (%.12g,%.12g,%g) -> (%g,%g)\n", 
+
+            printf( "    RPC Transform (%.12g,%.12g,%g) -> (%g,%g)\n",
                     adfLong[i], adfLat[i], adfHeight[i], dfPixel, dfLine );
         }
     }
diff --git a/frmts/nitf/nitffile.c b/frmts/nitf/nitffile.c
index 11719e7..75dc5f3 100644
--- a/frmts/nitf/nitffile.c
+++ b/frmts/nitf/nitffile.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nitffile.c 32465 2015-12-26 09:11:29Z rouault $
+ * $Id: nitffile.c 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  NITF Read/Write Library
  * Purpose:  Module responsible for opening NITF file, populating NITFFile
@@ -34,7 +34,9 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: nitffile.c 32465 2015-12-26 09:11:29Z rouault $");
+CPL_CVSID("$Id: nitffile.c 33717 2016-03-14 06:29:14Z goatbar $");
+
+CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused) {}
 
 static int NITFWriteBLOCKA( VSILFILE* fp, vsi_l_offset nOffsetUDIDL,
                             int *pnOffset,
@@ -46,10 +48,10 @@ static int NITFWriteTREsFromOptions(
     char **papszOptions,
     const char* pszTREPrefix);
 
-static int 
+static int
 NITFCollectSegmentInfo( NITFFile *psFile, int nFileHeaderLenSize, int nOffset,
                         const char szType[3],
-                        int nHeaderLenSize, int nDataLenSize, 
+                        int nHeaderLenSize, int nDataLenSize,
                         GUIntBig *pnNextData );
 
 /************************************************************************/
@@ -71,8 +73,8 @@ NITFFile *NITFOpen( const char *pszFilename, int bUpdatable )
 
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Failed to open file %s.", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to open file %s.",
                   pszFilename );
         return NULL;
     }
@@ -98,80 +100,79 @@ NITFFile *NITFOpenEx(VSILFILE *fp, const char *pszFilename)
 /* -------------------------------------------------------------------- */
 /*      Check file type.                                                */
 /* -------------------------------------------------------------------- */
-    VSIFSeekL( fp, 0, SEEK_SET );
-    VSIFReadL( szTemp, 1, 9, fp );
-
-    if( !EQUALN(szTemp,"NITF",4) && !EQUALN(szTemp,"NSIF",4) )
+    if( VSIFSeekL( fp, 0, SEEK_SET ) != 0 ||
+        VSIFReadL( szTemp, 1, 9, fp ) != 9 ||
+        (!STARTS_WITH_CI(szTemp, "NITF") && !STARTS_WITH_CI(szTemp, "NSIF")) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "The file %s is not an NITF file.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "The file %s is not an NITF file.",
                   pszFilename );
-        VSIFCloseL(fp);
+        CPL_IGNORE_RET_VAL_INT(VSIFCloseL(fp));
         return NULL;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Read the FSDWNG field.                                          */
 /* -------------------------------------------------------------------- */
-    if( VSIFSeekL( fp, 280, SEEK_SET ) != 0 
+    if( VSIFSeekL( fp, 280, SEEK_SET ) != 0
         || VSIFReadL( achFSDWNG, 1, 6, fp ) != 6 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "Unable to read FSDWNG field from NITF file.  File is either corrupt\n"
                   "or empty." );
-        VSIFCloseL(fp);
+        CPL_IGNORE_RET_VAL_INT(VSIFCloseL(fp));
         return NULL;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Get header length.                                              */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(szTemp,"NITF01.",7) || EQUALN(achFSDWNG,"999998",6) )
+    if( STARTS_WITH_CI(szTemp, "NITF01.") || STARTS_WITH_CI(achFSDWNG, "999998") )
         nHeaderLenOffset = 394;
     else
         nHeaderLenOffset = 354;
 
-    if( VSIFSeekL( fp, nHeaderLenOffset, SEEK_SET ) != 0 
+    if( VSIFSeekL( fp, nHeaderLenOffset, SEEK_SET ) != 0
         || VSIFReadL( szTemp, 1, 6, fp ) != 6 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "Unable to read header length from NITF file.  File is either corrupt\n"
                   "or empty." );
-        VSIFCloseL(fp);
+        CPL_IGNORE_RET_VAL_INT(VSIFCloseL(fp));
         return NULL;
     }
 
     szTemp[6] = '\0';
     nHeaderLen = atoi(szTemp);
 
-    VSIFSeekL( fp, nHeaderLen, SEEK_SET );
-    currentPos = VSIFTellL( fp ) ;
+    if( VSIFSeekL( fp, nHeaderLen, SEEK_SET ) != 0 )
+        currentPos = 0;
+    else
+        currentPos = VSIFTellL( fp ) ;
     if( nHeaderLen < nHeaderLenOffset || nHeaderLen > currentPos )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "NITF Header Length (%d) seems to be corrupt.",
                   nHeaderLen );
-        VSIFCloseL(fp);
+        CPL_IGNORE_RET_VAL_INT(VSIFCloseL(fp));
         return NULL;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Read the whole file header.                                     */
 /* -------------------------------------------------------------------- */
-    pachHeader = (char *) VSIMalloc(nHeaderLen);
+    pachHeader = (char *) VSI_MALLOC_VERBOSE(nHeaderLen);
     if (pachHeader == NULL)
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory, 
-                  "Cannot allocate memory for NITF header");
-        VSIFCloseL(fp);
+        CPL_IGNORE_RET_VAL_INT(VSIFCloseL(fp));
         return NULL;
     }
-    VSIFSeekL( fp, 0, SEEK_SET );
-    if ((int)VSIFReadL( pachHeader, 1, nHeaderLen, fp ) != nHeaderLen)
+    if( VSIFSeekL( fp, 0, SEEK_SET ) != 0 ||
+        (int)VSIFReadL( pachHeader, 1, nHeaderLen, fp ) != nHeaderLen )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   "Cannot read %d bytes for NITF header", (nHeaderLen));
-        VSIFCloseL(fp);
+        CPL_IGNORE_RET_VAL_INT(VSIFCloseL(fp));
         CPLFree(pachHeader);
         return NULL;
     }
@@ -196,8 +197,8 @@ retry_read_header:
     NITFExtractMetadata( &(target->papszMetadata), hdr,       \
                          start, length,                        \
                          "NITF_" #name );
-       
-    if( EQUAL(psFile->szVersion,"NITF02.10") 
+
+    if( EQUAL(psFile->szVersion,"NITF02.10")
         || EQUAL(psFile->szVersion,"NSIF01.00") )
     {
         char szWork[100];
@@ -227,9 +228,9 @@ retry_read_header:
         GetMD( psFile, pachHeader, 286,   5, FSCOP  );
         GetMD( psFile, pachHeader, 291,   5, FSCPYS );
         GetMD( psFile, pachHeader, 296,   1, ENCRYP );
-        sprintf( szWork, "%3d,%3d,%3d", 
-                 ((GByte *)pachHeader)[297], 
-                 ((GByte *)pachHeader)[298], 
+        snprintf( szWork, sizeof(szWork), "%3d,%3d,%3d",
+                 ((GByte *)pachHeader)[297],
+                 ((GByte *)pachHeader)[298],
                  ((GByte *)pachHeader)[299] );
         GetMD( psFile, szWork, 0, 11, FBKGC );
         GetMD( psFile, pachHeader, 300,  24, ONAME  );
@@ -253,7 +254,7 @@ retry_read_header:
         GetMD( psFile, pachHeader, 240,  20, FSCAUT );
         GetMD( psFile, pachHeader, 260,  20, FSCTLN );
         GetMD( psFile, pachHeader, 280,   6, FSDWNG );
-        if( EQUALN(pachHeader+280,"999998",6) )
+        if( STARTS_WITH_CI(pachHeader+280, "999998") )
         {
             GetMD( psFile, pachHeader, 286,  40, FSDEVT );
             nCOff += 40;
@@ -272,26 +273,29 @@ retry_read_header:
         GUIntBig nFileSize;
         GByte abyDELIM2_L2[12];
         GByte abyL1_DELIM1[11];
+        int bOK;
 
         bTriedStreamingFileHeader = TRUE;
         CPLDebug("NITF", "Total file unknown. Trying to get a STREAMING_FILE_HEADER");
 
-        VSIFSeekL( fp, 0, SEEK_END );
+        bOK = VSIFSeekL( fp, 0, SEEK_END ) == 0;
         nFileSize = VSIFTellL(fp);
 
-        VSIFSeekL( fp, nFileSize - 11, SEEK_SET );
+        bOK &= VSIFSeekL( fp, nFileSize - 11, SEEK_SET ) == 0;
         abyDELIM2_L2[11] = '\0';
 
-        if (VSIFReadL( abyDELIM2_L2, 1, 11, fp ) == 11 &&
+        if (bOK &&
+            VSIFReadL( abyDELIM2_L2, 1, 11, fp ) == 11 &&
             abyDELIM2_L2[0] == 0x0E && abyDELIM2_L2[1] == 0xCA &&
             abyDELIM2_L2[2] == 0x14 && abyDELIM2_L2[3] == 0xBF)
         {
             int SFHL2 = atoi((const char*)(abyDELIM2_L2 + 4));
             if (SFHL2 > 0 && (nFileSize > (size_t)(11 + SFHL2 + 11)) )
             {
-                VSIFSeekL( fp, nFileSize - 11 - SFHL2 - 11 , SEEK_SET );
+                bOK &= VSIFSeekL( fp, nFileSize - 11 - SFHL2 - 11 , SEEK_SET ) == 0;
 
-                if ( VSIFReadL( abyL1_DELIM1, 1, 11, fp ) == 11 &&
+                if ( bOK &&
+                     VSIFReadL( abyL1_DELIM1, 1, 11, fp ) == 11 &&
                      abyL1_DELIM1[7] == 0x0A && abyL1_DELIM1[8] == 0x6E &&
                      abyL1_DELIM1[9] == 0x1D && abyL1_DELIM1[10] == 0x97 &&
                      memcmp(abyL1_DELIM1, abyDELIM2_L2 + 4, 7) == 0 )
@@ -303,7 +307,7 @@ retry_read_header:
 
                         if ( (int)VSIFReadL( pachHeader, 1, SFHL2, fp ) != SFHL2 )
                         {
-                            VSIFCloseL(fp);
+                            CPL_IGNORE_RET_VAL_INT(VSIFCloseL(fp));
                             CPLFree(pachHeader);
                             CPLFree(psFile);
                             return NULL;
@@ -314,6 +318,11 @@ retry_read_header:
                 }
             }
         }
+        if( !bOK )
+        {
+            NITFClose(psFile);
+            return NULL;
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -356,7 +365,7 @@ retry_read_header:
         return NULL;
     }
 
-    psFile->nTREBytes = 
+    psFile->nTREBytes =
         atoi(NITFGetField( szTemp, pachHeader, nOffset, 5 ));
     if (psFile->nTREBytes < 0)
     {
@@ -384,15 +393,13 @@ retry_read_header:
             return NULL;
         }
 
-        psFile->pachTRE = (char *) VSIMalloc(psFile->nTREBytes);
+        psFile->pachTRE = (char *) VSI_MALLOC_VERBOSE(psFile->nTREBytes);
         if (psFile->pachTRE == NULL)
         {
-            CPLError(CE_Failure, CPLE_OutOfMemory,
-                     "Cannot allocate %d bytes", psFile->nTREBytes);
             NITFClose(psFile);
             return NULL;
         }
-        memcpy( psFile->pachTRE, pachHeader + nOffset, 
+        memcpy( psFile->pachTRE, pachHeader + nOffset,
                 psFile->nTREBytes );
     }
 
@@ -401,7 +408,7 @@ retry_read_header:
 /* -------------------------------------------------------------------- */
     if( nHeaderLen > nOffset + 8 )
     {
-        int nXHDL = 
+        int nXHDL =
             atoi(NITFGetField( szTemp, pachHeader, nOffset, 5 ));
         if (nXHDL < 0)
         {
@@ -427,13 +434,11 @@ retry_read_header:
                 return NULL;
             }
 
-            pachNewTRE = (char *) 
-                VSIRealloc( psFile->pachTRE, 
+            pachNewTRE = (char *)
+                VSI_REALLOC_VERBOSE( psFile->pachTRE,
                             psFile->nTREBytes + nXHDL );
             if (pachNewTRE == NULL)
             {
-                CPLError(CE_Failure, CPLE_OutOfMemory,
-                     "Cannot allocate %d bytes", psFile->nTREBytes + nXHDL);
                 NITFClose(psFile);
                 return NULL;
             }
@@ -474,7 +479,7 @@ void NITFClose( NITFFile *psFile )
 
     CPLFree( psFile->pasSegmentInfo );
     if( psFile->fp != NULL )
-        VSIFCloseL( psFile->fp );
+        CPL_IGNORE_RET_VAL_INT(VSIFCloseL( psFile->fp ));
     CPLFree( psFile->pachHeader );
     CSLDestroy( psFile->papszMetadata );
     CPLFree( psFile->pachTRE );
@@ -485,8 +490,9 @@ void NITFClose( NITFFile *psFile )
     CPLFree( psFile );
 }
 
-static void NITFGotoOffset(VSILFILE* fp, GUIntBig nLocation)
+static int NITFGotoOffset(VSILFILE* fp, GUIntBig nLocation)
 {
+    int bOK = TRUE;
     GUIntBig nCurrentLocation = VSIFTellL(fp);
     if (nLocation > nCurrentLocation)
     {
@@ -494,21 +500,25 @@ static void NITFGotoOffset(VSILFILE* fp, GUIntBig nLocation)
         size_t iFill;
         char cSpace = ' ';
 
-        VSIFSeekL(fp, 0, SEEK_END);
+        bOK &= VSIFSeekL(fp, 0, SEEK_END) == 0;
         nFileSize = VSIFTellL(fp);
-        if (nLocation > nFileSize)
+        if (bOK && nLocation > nFileSize)
         {
-            for(iFill = 0; iFill < nLocation - nFileSize; iFill++)
-                VSIFWriteL(&cSpace, 1, 1, fp);
+            for(iFill = 0; bOK && iFill < nLocation - nFileSize; iFill++)
+                bOK &= VSIFWriteL(&cSpace, 1, 1, fp) == 1;
         }
         else
-            VSIFSeekL(fp, nLocation, SEEK_SET);
+            bOK &= VSIFSeekL(fp, nLocation, SEEK_SET) == 0;
     }
     else if (nLocation < nCurrentLocation)
     {
-        VSIFSeekL(fp, nLocation, SEEK_SET);
+        bOK &= VSIFSeekL(fp, nLocation, SEEK_SET) == 0;
     }
-
+    if( !bOK )
+    {
+        CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+    }
+    return bOK;
 }
 
 /************************************************************************/
@@ -517,8 +527,8 @@ static void NITFGotoOffset(VSILFILE* fp, GUIntBig nLocation)
 /*      Create a new uncompressed NITF file.                            */
 /************************************************************************/
 
-int NITFCreate( const char *pszFilename, 
-                      int nPixels, int nLines, int nBands, 
+int NITFCreate( const char *pszFilename,
+                      int nPixels, int nLines, int nBands,
                       int nBitsPerSample, const char *pszPVType,
                       char **papszOptions )
 
@@ -539,6 +549,7 @@ int NITFCreate( const char *pszFilename,
     const char *pszNUMI;
     int iGS, nGS = 0; // number of graphic segment
     const char *pszNUMS; // graphic segment option string
+    int bOK;
 
     if (nBands <= 0 || nBands > 99999)
     {
@@ -563,7 +574,7 @@ int NITFCreate( const char *pszFilename,
         nNUMT = atoi(pszNUMT);
         if (nNUMT < 0 || nNUMT > 999)
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                     "Invalid NUMT value : %s", pszNUMT);
             return FALSE;
         }
@@ -575,18 +586,18 @@ int NITFCreate( const char *pszFilename,
         nIM = atoi(pszNUMI);
         if (nIM < 1 || nIM > 999)
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                     "Invalid NUMI value : %s", pszNUMI);
             return FALSE;
         }
         if (nIM != 1 && !EQUAL(pszIC, "NC"))
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                     "Unable to create file with multiple images and compression at the same time");
             return FALSE;
         }
     }
-    
+
     // Reads and validates graphics segment number option
     pszNUMS = CSLFetchNameValue(papszOptions, "NUMS");
     if (pszNUMS != NULL)
@@ -616,16 +627,15 @@ int NITFCreate( const char *pszFilename,
 
     if( CSLFetchNameValue( papszOptions, "BLOCKYSIZE" ) != NULL )
         nNPPBV = atoi(CSLFetchNameValue( papszOptions, "BLOCKYSIZE" ));
-    
+
     if( CSLFetchNameValue( papszOptions, "NPPBH" ) != NULL )
         nNPPBH = atoi(CSLFetchNameValue( papszOptions, "NPPBH" ));
-    
+
     if( CSLFetchNameValue( papszOptions, "NPPBV" ) != NULL )
         nNPPBV = atoi(CSLFetchNameValue( papszOptions, "NPPBV" ));
-        
-        
+
     if (EQUAL(pszIC, "NC") &&
-        (nPixels > 8192 || nLines > 8192) && 
+        (nPixels > 8192 || nLines > 8192) &&
         nNPPBH == nPixels && nNPPBV == nLines)
     {
         /* See MIL-STD-2500-C, paragraph 5.4.2.2-d (#3263) */
@@ -633,9 +643,9 @@ int NITFCreate( const char *pszFilename,
         nNBPC = 1;
         nNPPBH = 0;
         nNPPBV = 0;
-        
-        nImageSize = 
-            ((nBitsPerSample)/8) 
+
+        nImageSize =
+            ((nBitsPerSample)/8)
             * ((GIntBig) nPixels *nLines)
             * nBands;
     }
@@ -693,15 +703,15 @@ int NITFCreate( const char *pszFilename,
         nNBPC = (nLines + nNPPBV - 1) / nNPPBV;
         if ( nNBPR > 9999 || nNBPC > 9999 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Unable to create file %s,\n"
                       "Too many blocks : %d x %d",
                      pszFilename, nNBPR, nNBPC);
             return FALSE;
         }
 
-        nImageSize = 
-            ((nBitsPerSample)/8) 
+        nImageSize =
+            ((nBitsPerSample)/8)
             * ((GIntBig) nNBPR * nNBPC)
             * nNPPBH * nNPPBV * nBands;
     }
@@ -710,7 +720,7 @@ int NITFCreate( const char *pszFilename,
     {
         if ((double)nImageSize >= 1e10 - 1)
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                     "Unable to create file %s,\n"
                     "Too big image size : " CPL_FRMT_GUIB,
                     pszFilename, nImageSize );
@@ -718,7 +728,7 @@ int NITFCreate( const char *pszFilename,
         }
         if ((double)(nImageSize * nIM) >= 1e12 - 1)
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                     "Unable to create file %s,\n"
                     "Too big file size : " CPL_FRMT_GUIB,
                     pszFilename, nImageSize * nIM );
@@ -732,7 +742,7 @@ int NITFCreate( const char *pszFilename,
     fp = VSIFOpenL( pszFilename, "wb+" );
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "Unable to create file %s,\n"
                   "check path and permissions.",
                   pszFilename );
@@ -748,10 +758,10 @@ int NITFCreate( const char *pszFilename,
     pszVersion = CSLFetchNameValue( papszOptions, "FHDR" );
     if( pszVersion == NULL )
         pszVersion = "NITF02.10";
-    else if( !EQUAL(pszVersion,"NITF02.10") 
+    else if( !EQUAL(pszVersion,"NITF02.10")
              && !EQUAL(pszVersion,"NSIF01.00") )
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "FHDR=%s not supported, switching to NITF02.10.",
                   pszVersion );
         pszVersion = "NITF02.10";
@@ -763,24 +773,26 @@ int NITFCreate( const char *pszFilename,
 
 #define PLACE(location,name,text)  { \
     const char* _text = text; \
-    NITFGotoOffset(fp, location); \
-    VSIFWriteL(_text, 1, strlen(_text), fp); }
+    bOK &= NITFGotoOffset(fp, location); \
+    bOK &= VSIFWriteL(_text, 1, strlen(_text), fp) == strlen(_text); }
 
 #define OVR(width,location,name,text) { 				\
     const char* _text = text; \
-    const char *pszParmValue; 						\
-    pszParmValue = CSLFetchNameValue( papszOptions, #name ); 		\
-    if( pszParmValue == NULL )						\
-        pszParmValue = _text;						\
-    NITFGotoOffset(fp, location); \
-    VSIFWriteL(pszParmValue, 1, MIN(width,strlen(pszParmValue)), fp); }
+    const char *pszParmValueMacro; 						\
+    size_t to_write; \
+    pszParmValueMacro = CSLFetchNameValue( papszOptions, #name ); 		\
+    if( pszParmValueMacro == NULL )						\
+        pszParmValueMacro = _text;						\
+    bOK &= NITFGotoOffset(fp, location); \
+    to_write = MIN(width,strlen(pszParmValueMacro)); \
+    bOK &= VSIFWriteL(pszParmValueMacro, 1, to_write, fp) == to_write; }
 
 #define WRITE_BYTE(location, val) { \
     char cVal = val; \
-    NITFGotoOffset(fp, location); \
-    VSIFWriteL(&cVal, 1, 1, fp); }
+    bOK &= NITFGotoOffset(fp, location); \
+    bOK &= VSIFWriteL(&cVal, 1, 1, fp) == 1; }
 
-    VSIFSeekL(fp, 0, SEEK_SET);
+    bOK = VSIFSeekL(fp, 0, SEEK_SET) == 0;
 
     PLACE (  0, FDHR_FVER,    pszVersion                      );
     OVR( 2,  9, CLEVEL,       "03"                            );  /* Patched at the end */
@@ -857,7 +869,7 @@ int NITFCreate( const char *pszFilename,
 
     if( CSLFetchNameValue(papszOptions,"FILE_TRE") != NULL )
     {
-        NITFWriteTREsFromOptions(
+        bOK &= NITFWriteTREsFromOptions(
             fp,
             nHL - 10,
             &nHL,
@@ -868,7 +880,7 @@ int NITFCreate( const char *pszFilename,
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Too big file header length : %d", nHL);
-        VSIFCloseL( fp );
+        CPL_IGNORE_RET_VAL_INT(VSIFCloseL( fp ));
         return FALSE;
     }
 
@@ -906,7 +918,7 @@ int NITFCreate( const char *pszFilename,
         }
     }
 
-    VSIFSeekL(fp, nCur, SEEK_SET);
+    bOK &= VSIFSeekL(fp, nCur, SEEK_SET) == 0;
 
     PLACE (nCur+  0, IM           , "IM"                           );
     OVR(10,nCur+  2, IID1         , "Missing"                      );
@@ -958,15 +970,17 @@ int NITFCreate( const char *pszFilename,
         const char* pszICOM = CSLFetchNameValue( papszOptions, "ICOM");
         if (pszICOM != NULL)
         {
-            int nLenICOM = strlen(pszICOM);
+            int nLenICOM = (int)strlen(pszICOM);
             int nICOM = (79 + nLenICOM) / 80;
+            size_t nToWrite;
             if (nICOM > 9)
             {
                 CPLError(CE_Warning, CPLE_NotSupported, "ICOM will be truncated");
                 nICOM = 9;
             }
             PLACE (nCur+nOffset, NICOM    , CPLSPrintf("%01d",nICOM) );
-            VSIFWriteL(pszICOM, 1, MIN(nICOM * 80, nLenICOM), fp);
+            nToWrite = MIN(nICOM * 80, nLenICOM);
+            bOK &= VSIFWriteL(pszICOM, 1, nToWrite, fp) == nToWrite;
             nOffset += nICOM * 80;
         }
         else
@@ -1025,7 +1039,7 @@ int NITFCreate( const char *pszFilename,
             else if( iBand == 2 )
                 pszIREPBAND = "B";
         }
-        else if( EQUALN(pszIREP,"YCbCr",5) )
+        else if( STARTS_WITH_CI(pszIREP, "YCbCr") )
         {
             if( iBand == 0 )
                 pszIREPBAND = "Y";
@@ -1123,17 +1137,17 @@ int NITFCreate( const char *pszFilename,
     if( CSLFetchNameValue(papszOptions,"BLOCKA_BLOCK_COUNT") != NULL )
     {
         NITFWriteBLOCKA( fp,
-                         nOffsetUDIDL, 
-                         &nOffset, 
+                         nOffsetUDIDL,
+                         &nOffset,
                          papszOptions );
     }
 
     if( CSLFetchNameValue(papszOptions,"TRE") != NULL )
     {
-        NITFWriteTREsFromOptions(
+        bOK &= NITFWriteTREsFromOptions(
             fp,
-            nOffsetUDIDL, 
-            &nOffset, 
+            nOffsetUDIDL,
+            &nOffset,
             papszOptions, "TRE=" );
     }
 
@@ -1146,7 +1160,7 @@ int NITFCreate( const char *pszFilename,
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Too big image header length : %d", nIHSize);
-        VSIFCloseL( fp );
+        CPL_IGNORE_RET_VAL_INT(VSIFCloseL( fp ));
         return FALSE;
     }
 
@@ -1188,7 +1202,7 @@ int NITFCreate( const char *pszFilename,
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Too big file : " CPL_FRMT_GUIB, nCur);
-        VSIFCloseL( fp );
+        CPL_IGNORE_RET_VAL_INT(VSIFCloseL( fp ));
         return FALSE;
     }
 
@@ -1201,13 +1215,14 @@ int NITFCreate( const char *pszFilename,
     if( EQUAL(pszIC,"NC") )
     {
         char cNul = 0;
-        VSIFSeekL( fp, nCur-1, SEEK_SET );
-        VSIFWriteL( &cNul, 1, 1, fp );
+        bOK &= VSIFSeekL( fp, nCur-1, SEEK_SET ) == 0;
+        bOK &= VSIFWriteL( &cNul, 1, 1, fp ) == 1;
     }
 
-    VSIFCloseL( fp );
+    if( VSIFCloseL( fp ) != 0 )
+        bOK = FALSE;
 
-    return TRUE;
+    return bOK;
 }
 
 /************************************************************************/
@@ -1215,19 +1230,20 @@ int NITFCreate( const char *pszFilename,
 /************************************************************************/
 
 static int NITFWriteTRE( VSILFILE* fp,
-                         vsi_l_offset nOffsetUDIDL, 
+                         vsi_l_offset nOffsetUDIDL,
                          int  *pnOffset,
                          const char *pszTREName, char *pabyTREData, int nTREDataSize )
 
 {
     char szTemp[12];
     int  nOldOffset;
+    int bOK = TRUE;
 
 /* -------------------------------------------------------------------- */
 /*      Update IXSHDL.                                                  */
 /* -------------------------------------------------------------------- */
-    VSIFSeekL(fp, nOffsetUDIDL + 5, SEEK_SET);
-    VSIFReadL(szTemp, 1, 5, fp);
+    bOK &= VSIFSeekL(fp, nOffsetUDIDL + 5, SEEK_SET) == 0;
+    bOK &= VSIFReadL(szTemp, 1, 5, fp) == 5;
     szTemp[5] = 0;
     nOldOffset = atoi(szTemp);
 
@@ -1244,24 +1260,24 @@ static int NITFWriteTRE( VSILFILE* fp,
         return FALSE;
     }
 
-    sprintf( szTemp, "%05d", nOldOffset + 11 + nTREDataSize );
+    snprintf( szTemp, sizeof(szTemp), "%05d", nOldOffset + 11 + nTREDataSize );
     PLACE( nOffsetUDIDL + 5, IXSHDL, szTemp );
 
 /* -------------------------------------------------------------------- */
 /*      Create TRE prefix.                                              */
 /* -------------------------------------------------------------------- */
-    sprintf( szTemp, "%-6s%05d", 
+    snprintf( szTemp, sizeof(szTemp), "%-6s%05d",
              pszTREName, nTREDataSize );
-    VSIFSeekL(fp, nOffsetUDIDL + 10 + nOldOffset, SEEK_SET);
-    VSIFWriteL(szTemp, 11, 1, fp);
-    VSIFWriteL(pabyTREData, nTREDataSize, 1, fp);
+    bOK &= VSIFSeekL(fp, nOffsetUDIDL + 10 + nOldOffset, SEEK_SET) == 0;
+    bOK &= VSIFWriteL(szTemp, 11, 1, fp) == 1;
+    bOK &= (int)VSIFWriteL(pabyTREData, 1, nTREDataSize, fp) == nTREDataSize;
 
 /* -------------------------------------------------------------------- */
 /*      Increment values.                                               */
 /* -------------------------------------------------------------------- */
     *pnOffset += nTREDataSize + 11;
 
-    return TRUE;
+    return bOK;
 }
 
 /************************************************************************/
@@ -1272,13 +1288,13 @@ static int NITFWriteTREsFromOptions(
     VSILFILE* fp,
     vsi_l_offset nOffsetUDIDL,
     int *pnOffset,
-    char **papszOptions, const char* pszTREPrefix )    
+    char **papszOptions, const char* pszTREPrefix )
 
 {
-    int bIgnoreBLOCKA = 
+    int bIgnoreBLOCKA =
         CSLFetchNameValue(papszOptions,"BLOCKA_BLOCK_COUNT") != NULL;
     int iOption;
-    int nTREPrefixLen = strlen(pszTREPrefix);
+    int nTREPrefixLen = (int)strlen(pszTREPrefix);
 
     if( papszOptions == NULL )
         return TRUE;
@@ -1294,10 +1310,10 @@ static int NITFWriteTREsFromOptions(
         if( !EQUALN(papszOptions[iOption], pszTREPrefix, nTREPrefixLen) )
             continue;
 
-        if( EQUALN(papszOptions[iOption]+nTREPrefixLen,"BLOCKA=",7)
+        if( STARTS_WITH_CI(papszOptions[iOption]+nTREPrefixLen, "BLOCKA=")
             && bIgnoreBLOCKA )
             continue;
-        
+
         /* We do no longer use CPLParseNameValue() as it removes leading spaces */
         /* from the value (see #3088) */
         pszSpace = strchr(papszOptions[iOption]+nTREPrefixLen, '=');
@@ -1307,26 +1323,26 @@ static int NITFWriteTREsFromOptions(
                      "Could not parse creation options %s", papszOptions[iOption]+nTREPrefixLen);
             return FALSE;
         }
-        
+
         pszTREName = CPLStrdup(papszOptions[iOption]+nTREPrefixLen);
         pszTREName[MIN(6, pszSpace - (papszOptions[iOption]+nTREPrefixLen))] = '\0';
         pszEscapedContents = pszSpace + 1;
 
-        pszUnescapedContents = 
+        pszUnescapedContents =
             CPLUnescapeString( pszEscapedContents, &nContentLength,
                                CPLES_BackslashQuotable );
 
         if( !NITFWriteTRE( fp,
                            nOffsetUDIDL,
                            pnOffset,
-                           pszTREName, pszUnescapedContents, 
+                           pszTREName, pszUnescapedContents,
                            nContentLength ) )
         {
             CPLFree( pszTREName );
             CPLFree( pszUnescapedContents );
             return FALSE;
         }
-        
+
         CPLFree( pszTREName );
         CPLFree( pszUnescapedContents );
 
@@ -1344,7 +1360,7 @@ static int NITFWriteBLOCKA( VSILFILE* fp, vsi_l_offset nOffsetUDIDL,
                             char **papszOptions )
 
 {
-    static const char *apszFields[] = { 
+    static const char * const apszFields[] = {
         "BLOCK_INSTANCE", "0", "2",
         "N_GRAY",         "2", "5",
         "L_LINES",        "7", "5",
@@ -1356,7 +1372,7 @@ static int NITFWriteBLOCKA( VSILFILE* fp, vsi_l_offset nOffsetUDIDL,
         "LRFC_LOC",       "76", "21",
         "FRFC_LOC",       "97", "21",
         NULL,             NULL, NULL };
-    int nBlockCount = 
+    int nBlockCount =
         atoi(CSLFetchNameValue( papszOptions, "BLOCKA_BLOCK_COUNT" ));
     int iBlock;
 
@@ -1378,7 +1394,7 @@ static int NITFWriteBLOCKA( VSILFILE* fp, vsi_l_offset nOffsetUDIDL,
             int  iSize = atoi(apszFields[iField*3+2]);
             const char *pszValue;
 
-            sprintf( szFullFieldName, "BLOCKA_%s_%02d",
+            snprintf( szFullFieldName, sizeof(szFullFieldName), "BLOCKA_%s_%02d",
                      apszFields[iField*3 + 0], iBlock );
 
             pszValue = CSLFetchNameValue( papszOptions, szFullFieldName );
@@ -1422,7 +1438,7 @@ static int NITFWriteBLOCKA( VSILFILE* fp, vsi_l_offset nOffsetUDIDL,
 /*      the segment list in the NITFFile object.                        */
 /************************************************************************/
 
-static int 
+static int
 NITFCollectSegmentInfo( NITFFile *psFile, int nFileHeaderLen, int nOffset, const char szType[3],
                         int nHeaderLenSize, int nDataLenSize, GUIntBig *pnNextData )
 
@@ -1458,7 +1474,7 @@ NITFCollectSegmentInfo( NITFFile *psFile, int nFileHeaderLen, int nOffset, const
             CPLMalloc( sizeof(NITFSegmentInfo) * nCount );
     else
         psFile->pasSegmentInfo = (NITFSegmentInfo *)
-            CPLRealloc( psFile->pasSegmentInfo, 
+            CPLRealloc( psFile->pasSegmentInfo,
                         sizeof(NITFSegmentInfo)
                         * (psFile->nSegmentCount+nCount) );
 
@@ -1468,7 +1484,7 @@ NITFCollectSegmentInfo( NITFFile *psFile, int nFileHeaderLen, int nOffset, const
     for( iSegment = 0; iSegment < nCount; iSegment++ )
     {
         NITFSegmentInfo *psInfo = psFile->pasSegmentInfo+psFile->nSegmentCount;
-        
+
         psInfo->nDLVL = -1;
         psInfo->nALVL = -1;
         psInfo->nLOC_R = -1;
@@ -1477,11 +1493,12 @@ NITFCollectSegmentInfo( NITFFile *psFile, int nFileHeaderLen, int nOffset, const
         psInfo->nCCS_C = -1;
 
         psInfo->hAccess = NULL;
-        strcpy( psInfo->szSegmentType, szType );
-        
-        psInfo->nSegmentHeaderSize = 
-            atoi(NITFGetField(szTemp, psFile->pachHeader, 
-                              nOffset + 3 + iSegment * (nHeaderLenSize+nDataLenSize), 
+        strncpy( psInfo->szSegmentType, szType, sizeof(psInfo->szSegmentType) );
+        psInfo->szSegmentType[sizeof(psInfo->szSegmentType)-1] = '\0';
+
+        psInfo->nSegmentHeaderSize =
+            atoi(NITFGetField(szTemp, psFile->pachHeader,
+                              nOffset + 3 + iSegment * (nHeaderLenSize+nDataLenSize),
                               nHeaderLenSize));
         if (strchr(szTemp, '-') != NULL) /* Avoid negative values being mapped to huge unsigned values */
         {
@@ -1495,9 +1512,9 @@ NITFCollectSegmentInfo( NITFFile *psFile, int nFileHeaderLen, int nOffset, const
             psInfo->nSegmentHeaderSize = 209;
         }
 
-        psInfo->nSegmentSize = 
-            CPLScanUIntBig(NITFGetField(szTemp,psFile->pachHeader, 
-                              nOffset + 3 + iSegment * (nHeaderLenSize+nDataLenSize) 
+        psInfo->nSegmentSize =
+            CPLScanUIntBig(NITFGetField(szTemp,psFile->pachHeader,
+                              nOffset + 3 + iSegment * (nHeaderLenSize+nDataLenSize)
                               + nHeaderLenSize,
                               nDataLenSize), nDataLenSize);
         if (strchr(szTemp, '-') != NULL) /* Avoid negative values being mapped to huge unsigned values */
@@ -1523,7 +1540,7 @@ NITFCollectSegmentInfo( NITFFile *psFile, int nFileHeaderLen, int nOffset, const
 /*      buffer and zero terminate it.                                   */
 /************************************************************************/
 
-char *NITFGetField( char *pszTarget, const char *pszSource, 
+char *NITFGetField( char *pszTarget, const char *pszSource,
                     int nStart, int nLength )
 
 {
@@ -1556,7 +1573,7 @@ const char *NITFFindTRE( const char *pszTREData, int nTREBytes,
         if (nTREBytes - 11 < nThisTRESize)
         {
             NITFGetField(szTemp, pszTREData, 0, 6 );
-            if (EQUALN(szTemp, "RPFIMG",6))
+            if (STARTS_WITH_CI(szTemp, "RPFIMG"))
             {
                 /* See #3848 */
                 CPLDebug("NITF", "Adjusting RPFIMG TRE size from %d to %d, which is the remaining size", nThisTRESize, nTREBytes - 11);
@@ -1610,7 +1627,7 @@ const char *NITFFindTREByIndex( const char *pszTREData, int nTREBytes,
         if (nTREBytes - 11 < nThisTRESize)
         {
             NITFGetField(szTemp, pszTREData, 0, 6 );
-            if (EQUALN(szTemp, "RPFIMG",6))
+            if (STARTS_WITH_CI(szTemp, "RPFIMG"))
             {
                 /* See #3848 */
                 CPLDebug("NITF", "Adjusting RPFIMG TRE size from %d to %d, which is the remaining size", nThisTRESize, nTREBytes - 11);
@@ -1635,7 +1652,7 @@ const char *NITFFindTREByIndex( const char *pszTREData, int nTREBytes,
                 return pszTREData + 11;
             }
 
-            /* Found a prevoius one - skip it ... */
+            /* Found a previous one - skip it ... */
             nTreIndex--;
         }
 
@@ -1657,6 +1674,9 @@ void NITFExtractMetadata( char ***ppapszMetadata, const char *pachHeader,
     char szWork[400];
     char* pszWork;
 
+    if( nLength <= 0 )
+        return;
+
     if (nLength >= (int)(sizeof(szWork) - 1))
         pszWork = (char*)CPLMalloc(nLength + 1);
     else
@@ -1674,7 +1694,7 @@ void NITFExtractMetadata( char ***ppapszMetadata, const char *pachHeader,
     if (szWork != pszWork)
         CPLFree(pszWork);
 }
-                          
+
 /************************************************************************/
 /*        NITF_WGS84_Geocentric_Latitude_To_Geodetic_Latitude()         */
 /*                                                                      */
@@ -1685,7 +1705,7 @@ void NITFExtractMetadata( char ***ppapszMetadata, const char *pachHeader,
 /*
  * "The angle L' is called "geocentric latitude" and is defined as the
  * angle between the equatorial plane and the radius from the geocenter.
- * 
+ *
  * The angle L is called "geodetic latitude" and is defined as the angle
  * between the equatorial plane and the normal to the surface of the
  * ellipsoid.  The word "latitude" usually means geodetic latitude.  This
@@ -1698,18 +1718,17 @@ double NITF_WGS84_Geocentric_Latitude_To_Geodetic_Latitude( double dfLat )
 
 {
     /* WGS84 Ellipsoid */
-    double a = 6378137.0;
-    double b = 6356752.3142;
-    double dfPI = 3.14159265358979323;
+    const double a = 6378137.0;
+    const double b = 6356752.3142;
 
     /* convert to radians */
-    dfLat = dfLat * dfPI / 180.0;
+    dfLat = dfLat * M_PI / 180.0;
 
     /* convert to geodetic */
     dfLat = atan( ((a*a)/(b*b)) * tan(dfLat) );
 
     /* convert back to degrees */
-    dfLat = dfLat * 180.0 / dfPI;
+    dfLat = dfLat * 180.0 / M_PI;
 
     return dfLat;
 }
@@ -1912,7 +1931,7 @@ const NITFSeries* NITFGetSeriesInfo(const char* pszFilename)
     int i;
     char seriesCode[3] = {0,0,0};
     if (pszFilename == NULL) return NULL;
-    for (i=strlen(pszFilename)-1;i>=0;i--)
+    for (i=(int)strlen(pszFilename)-1;i>=0;i--)
     {
         if (pszFilename[i] == '.')
         {
@@ -1961,7 +1980,7 @@ int NITFCollectAttachments( NITFFile *psFile )
             NITFImage *psImage = NITFImageAccess( psFile, iSegment );
             if (psImage == NULL)
                 return FALSE;
-                
+
             psSegInfo->nDLVL = psImage->nIDLVL;
             psSegInfo->nALVL = psImage->nIALVL;
             psSegInfo->nLOC_R = psImage->nILOCRow;
@@ -1980,20 +1999,20 @@ int NITFCollectAttachments( NITFFile *psFile )
 /* -------------------------------------------------------------------- */
 /*      Load the graphic subheader.                                     */
 /* -------------------------------------------------------------------- */
-            if( VSIFSeekL( psFile->fp, psSegInfo->nSegmentHeaderStart, 
-                           SEEK_SET ) != 0 
-                || VSIFReadL( achSubheader, 1, sizeof(achSubheader), 
+            if( VSIFSeekL( psFile->fp, psSegInfo->nSegmentHeaderStart,
+                           SEEK_SET ) != 0
+                || VSIFReadL( achSubheader, 1, sizeof(achSubheader),
                               psFile->fp ) < 258 )
             {
-                CPLError( CE_Warning, CPLE_FileIO, 
-                          "Failed to read graphic subheader at " CPL_FRMT_GUIB ".", 
+                CPLError( CE_Warning, CPLE_FileIO,
+                          "Failed to read graphic subheader at " CPL_FRMT_GUIB ".",
                           psSegInfo->nSegmentHeaderStart );
                 continue;
             }
 
             // NITF 2.0. (also works for NITF 2.1)
             nSTYPEOffset = 200;
-            if( EQUALN(achSubheader+193,"999998",6) )
+            if( STARTS_WITH_CI(achSubheader+193, "999998") )
                 nSTYPEOffset += 40;
 
 /* -------------------------------------------------------------------- */
@@ -2009,7 +2028,7 @@ int NITFCollectAttachments( NITFFile *psFile )
                                                   nSTYPEOffset + 25, 5));
         }
     }
-    
+
     return TRUE;
 }
 
@@ -2050,7 +2069,7 @@ int NITFReconcileAttachments( NITFFile *psFile )
         for( iOther = 0; iOther < psFile->nSegmentCount; iOther++ )
         {
             NITFSegmentInfo *psOtherSegInfo = psFile->pasSegmentInfo + iOther;
-            
+
             if( psSegInfo->nALVL == psOtherSegInfo->nDLVL )
             {
                 if( psOtherSegInfo->nCCS_R != -1 )
@@ -2092,7 +2111,7 @@ static const char* NITFFindValFromEnd(char** papszMD,
                                       const char* pszVar,
                                       CPL_UNUSED const char* pszDefault)
 {
-    int nVarLen = strlen(pszVar);
+    int nVarLen = (int)strlen(pszVar);
     int nIter = nMDSize-1;
     for(;nIter >= 0;nIter--)
     {
@@ -2190,7 +2209,7 @@ static char** NITFGenericMetadataReadTREInternal(char **papszMD,
                 if (*pnMDSize + 1 >= *pnMDAlloc)
                 {
                     *pnMDAlloc = (*pnMDAlloc * 4 / 3) + 32;
-                    papszMD = (char**)CPLRealloc(papszMD, *pnMDAlloc * sizeof(char**));
+                    papszMD = (char**)CPLRealloc(papszMD, *pnMDAlloc * sizeof(char*));
                 }
                 papszMD[*pnMDSize] = papszTmp[0];
                 papszMD[(*pnMDSize) + 1] = NULL;
@@ -2445,9 +2464,9 @@ static char** NITFGenericMetadataReadTREInternal(char **papszMD,
                     {
                         if (bHasValidPercentD)
                         {
-                            char* szTmp = (char*)CPLMalloc(
-                                            strlen(pszMDSubPrefix) + 10 + 1);
-                            sprintf(szTmp, pszMDSubPrefix, iIter + 1);
+                            const size_t nTmpLen = strlen(pszMDSubPrefix) + 10 + 1;
+                            char* szTmp = (char*)CPLMalloc(nTmpLen);
+                            snprintf(szTmp, nTmpLen, pszMDSubPrefix, iIter + 1);
                             pszMDNewPrefix = CPLStrdup(CPLSPrintf("%s%s",
                                                        pszMDPrefix, szTmp));
                             CPLFree(szTmp);
@@ -2747,7 +2766,7 @@ CPLXMLNode* NITFCreateXMLTre(NITFFile* psFile,
     psTreNode = NITFFindTREXMLDescFromName(psFile, pszTREName);
     if (psTreNode == NULL)
     {
-        if (!(EQUALN(pszTREName, "RPF", 3) || strcmp(pszTREName, "XXXXXX") == 0))
+        if (!(STARTS_WITH_CI(pszTREName, "RPF") || strcmp(pszTREName, "XXXXXX") == 0))
         {
             CPLDebug("NITF", "Cannot find definition of TRE %s in %s",
                     pszTREName, NITF_SPEC_FILE);
diff --git a/frmts/nitf/nitfimage.c b/frmts/nitf/nitfimage.c
index 6ba1efa..fa4f9af 100644
--- a/frmts/nitf/nitfimage.c
+++ b/frmts/nitf/nitfimage.c
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: nitfimage.c 28039 2014-11-30 18:24:59Z rouault $
+ * $Id: nitfimage.c 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  NITF Read/Write Library
- * Purpose:  Module responsible for implementation of most NITFImage 
+ * Purpose:  Module responsible for implementation of most NITFImage
  *           implementation.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -36,7 +36,9 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: nitfimage.c 28039 2014-11-30 18:24:59Z rouault $");
+CPL_CVSID("$Id: nitfimage.c 33717 2016-03-14 06:29:14Z goatbar $");
+
+CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused) {}
 
 static int NITFReadIMRFCA( NITFImage *psImage, NITFRPC00BInfo *psRPC );
 static char *NITFTrimWhite( char * );
@@ -99,19 +101,18 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
         return NULL;
     }
 
-    pachHeader = (char*) VSIMalloc(psSegInfo->nSegmentHeaderSize);
+    pachHeader = (char*) VSI_MALLOC_VERBOSE(psSegInfo->nSegmentHeaderSize);
     if (pachHeader == NULL)
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate memory for segment header");
         return NULL;
     }
 
-    if( VSIFSeekL( psFile->fp, psSegInfo->nSegmentHeaderStart, 
-                  SEEK_SET ) != 0 
-        || VSIFReadL( pachHeader, 1, psSegInfo->nSegmentHeaderSize, 
+    if( VSIFSeekL( psFile->fp, psSegInfo->nSegmentHeaderStart,
+                  SEEK_SET ) != 0
+        || VSIFReadL( pachHeader, 1, psSegInfo->nSegmentHeaderSize,
                      psFile->fp ) != psSegInfo->nSegmentHeaderSize )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   "Failed to read %u byte image subheader from " CPL_FRMT_GUIB ".",
                   psSegInfo->nSegmentHeaderSize,
                   psSegInfo->nSegmentHeaderStart );
@@ -137,8 +138,8 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
     NITFExtractMetadata( &(target->papszMetadata), hdr,       \
                          start, length,                        \
                          "NITF_" #name );
-       
-    if( EQUAL(psFile->szVersion,"NITF02.10") 
+
+    if( EQUAL(psFile->szVersion,"NITF02.10")
         || EQUAL(psFile->szVersion,"NSIF01.00") )
     {
         GetMD( psImage, pachHeader,   2,  10, IID1   );
@@ -172,7 +173,7 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
     }
     else if( EQUAL(psFile->szVersion,"NITF02.00") )
     {
-        int nOffset = 0;
+        nOffset = 0;
         GetMD( psImage, pachHeader,   2,  10, IID1   );
         GetMD( psImage, pachHeader,  12,  14, IDATIM );
         GetMD( psImage, pachHeader,  26,  17, TGTID  );
@@ -184,8 +185,8 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
         GetMD( psImage, pachHeader, 244,  20, ISCAUT );
         GetMD( psImage, pachHeader, 264,  20, ISCTLN );
         GetMD( psImage, pachHeader, 284,   6, ISDWNG );
-        
-        if( EQUALN(pachHeader+284,"999998",6) )
+
+        if( STARTS_WITH_CI(pachHeader+284, "999998") )
         {
             if (psSegInfo->nSegmentHeaderSize < 370 + 40 + 1)
                 GOTO_header_too_small();
@@ -208,26 +209,26 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
 /* -------------------------------------------------------------------- */
     nOffset = 333;
 
-    if( EQUALN(psFile->szVersion,"NITF01.",7) 
-        || EQUALN(pachHeader+284,"999998",6) )
+    if( STARTS_WITH_CI(psFile->szVersion, "NITF01.")
+        || STARTS_WITH_CI(pachHeader+284, "999998") )
         nOffset += 40;
 
 /* -------------------------------------------------------------------- */
 /*      Read lots of header fields.                                     */
 /* -------------------------------------------------------------------- */
-    if( !EQUALN(psFile->szVersion,"NITF01.",7) )
+    if( !STARTS_WITH_CI(psFile->szVersion, "NITF01.") )
     {
         if ( (int)psSegInfo->nSegmentHeaderSize < nOffset + 35+2)
             GOTO_header_too_small();
 
         psImage->nRows = atoi(NITFGetField(szTemp,pachHeader,nOffset,8));
         psImage->nCols = atoi(NITFGetField(szTemp,pachHeader,nOffset+8,8));
-        
-        NITFTrimWhite( NITFGetField( psImage->szPVType, pachHeader, 
+
+        NITFTrimWhite( NITFGetField( psImage->szPVType, pachHeader,
                                      nOffset+16, 3) );
-        NITFTrimWhite( NITFGetField( psImage->szIREP, pachHeader, 
+        NITFTrimWhite( NITFGetField( psImage->szIREP, pachHeader,
                                      nOffset+19, 8) );
-        NITFTrimWhite( NITFGetField( psImage->szICAT, pachHeader, 
+        NITFTrimWhite( NITFGetField( psImage->szICAT, pachHeader,
                                      nOffset+27, 8) );
         psImage->nABPP = atoi(NITFGetField(szTemp,pachHeader,nOffset+35,2));
     }
@@ -248,8 +249,8 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
     psImage->chICORDS = pachHeader[nOffset++];
     psImage->bHaveIGEOLO = FALSE;
 
-    if( (EQUALN(psFile->szVersion,"NITF02.0",8)
-         || EQUALN(psFile->szVersion,"NITF01.",7))
+    if( (STARTS_WITH_CI(psFile->szVersion, "NITF02.0")
+         || STARTS_WITH_CI(psFile->szVersion, "NITF01."))
         && psImage->chICORDS == 'N' )
         psImage->chICORDS = ' ';
 
@@ -270,11 +271,11 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
         for( iCoord = 0; iCoord < 4; iCoord++ )
         {
             const char *pszCoordPair = pachHeader + nOffset + iCoord*15;
-            double *pdfXY = &(psImage->dfULX) + iCoord*2; 
-            
+            double *pdfXY = &(psImage->dfULX) + iCoord*2;
+
             if( psImage->chICORDS == 'N' || psImage->chICORDS == 'S' )
             {
-                psImage->nZone = 
+                psImage->nZone =
                     atoi(NITFGetField( szTemp, pszCoordPair, 0, 2 ));
 
                 pdfXY[0] = CPLAtof(NITFGetField( szTemp, pszCoordPair, 2, 6 ));
@@ -329,7 +330,7 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
                 }
                 else if( psImage->nZone == 0 )
                 {
-                    psImage->nZone = nZone;
+                    psImage->nZone = (int)nZone;
                 }
             }
         }
@@ -363,7 +364,7 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
                       nOffset, 80 * nNICOM );
         nOffset += nNICOM * 80;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read more stuff.                                                */
 /* -------------------------------------------------------------------- */
@@ -407,11 +408,10 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
 /* -------------------------------------------------------------------- */
 /*      Read per-band information.                                      */
 /* -------------------------------------------------------------------- */
-    psImage->pasBandInfo = (NITFBandInfo *) 
-        VSICalloc(sizeof(NITFBandInfo),psImage->nBands);
+    psImage->pasBandInfo = (NITFBandInfo *)
+        VSI_CALLOC_VERBOSE(sizeof(NITFBandInfo),psImage->nBands);
     if (psImage->pasBandInfo == NULL)
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate memory for band info");
         NITFImageDeaccess(psImage);
         return NULL;
     }
@@ -440,7 +440,7 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
         if( nLUTS == 0 )
             continue;
 
-        psBandInfo->nSignificantLUTEntries = 
+        psBandInfo->nSignificantLUTEntries =
             atoi(NITFGetField( szTemp, pachHeader, nOffset, 5 ));
         nOffset += 5;
 
@@ -462,22 +462,22 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
              nOffset + nLUTS * psBandInfo->nSignificantLUTEntries )
             GOTO_header_too_small();
 
-        memcpy( psBandInfo->pabyLUT, pachHeader + nOffset, 
+        memcpy( psBandInfo->pabyLUT, pachHeader + nOffset,
                 psBandInfo->nSignificantLUTEntries );
         nOffset += psBandInfo->nSignificantLUTEntries;
 
         if( nLUTS == 3 )
         {
-            memcpy( psBandInfo->pabyLUT+256, pachHeader + nOffset, 
+            memcpy( psBandInfo->pabyLUT+256, pachHeader + nOffset,
                     psBandInfo->nSignificantLUTEntries );
             nOffset += psBandInfo->nSignificantLUTEntries;
 
-            memcpy( psBandInfo->pabyLUT+512, pachHeader + nOffset, 
+            memcpy( psBandInfo->pabyLUT+512, pachHeader + nOffset,
                     psBandInfo->nSignificantLUTEntries );
             nOffset += psBandInfo->nSignificantLUTEntries;
         }
-        else if( (nLUTS == 2) && (EQUALN(psImage->szIREP,"MONO",4)) &&
-          ((EQUALN(psBandInfo->szIREPBAND, "M", 1)) || (EQUALN(psBandInfo->szIREPBAND, "LU", 2))) )
+        else if( (nLUTS == 2) && (STARTS_WITH_CI(psImage->szIREP, "MONO")) &&
+          ((STARTS_WITH_CI(psBandInfo->szIREPBAND, "M")) || (STARTS_WITH_CI(psBandInfo->szIREPBAND, "LU"))) )
         {
             int             iLUTEntry;
             double          scale          = 255.0/65535.0;
@@ -490,7 +490,7 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
           /* In this case, we have two LUTs. The first and second LUTs should map respectively to the most */
           /* significant byte and the least significant byte of the 16 bit values. */
 
-            memcpy( psBandInfo->pabyLUT+256, pachHeader + nOffset, 
+            memcpy( psBandInfo->pabyLUT+256, pachHeader + nOffset,
                     psBandInfo->nSignificantLUTEntries );
             nOffset += psBandInfo->nSignificantLUTEntries;
 
@@ -502,7 +502,7 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
 
             for( iLUTEntry = 0; iLUTEntry < 255; ++iLUTEntry )
             {
-                /* E. Rouault: I don't understand why the following logic is endianness dependant */
+                /* E. Rouault: I don't understand why the following logic is endianness dependent. */
                 pLUTVal[iLUTEntry] = ((pMSB[iLUTEntry] << 8) | pLSB[iLUTEntry]);
 #ifdef CPL_LSB
                 pLUTVal[iLUTEntry] = ((pLUTVal[iLUTEntry] >> 8) | (pLUTVal[iLUTEntry] << 8));
@@ -520,17 +520,17 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
 
             CPLFree(pLUTVal);
         }
-        else 
+        else
         {
             /* morph greyscale lut into RGB LUT. */
             memcpy( psBandInfo->pabyLUT+256, psBandInfo->pabyLUT, 256 );
             memcpy( psBandInfo->pabyLUT+512, psBandInfo->pabyLUT, 256 );
         }
-    }								
+    }
 
 /* -------------------------------------------------------------------- */
-/*      Some files (ie NSIF datasets) have truncated image              */
-/*      headers.  This has been observed with jpeg compressed           */
+/*      Some files (i.e. NSIF datasets) have truncated image              */
+/*      headers.  This has been observed with JPEG compressed           */
 /*      files.  In this case guess reasonable values for these          */
 /*      fields.                                                         */
 /* -------------------------------------------------------------------- */
@@ -557,16 +557,16 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
     else
     {
         psImage->chIMODE = pachHeader[nOffset + 1];
-        
-        psImage->nBlocksPerRow = 
+
+        psImage->nBlocksPerRow =
             atoi(NITFGetField(szTemp, pachHeader, nOffset+2, 4));
-        psImage->nBlocksPerColumn = 
+        psImage->nBlocksPerColumn =
             atoi(NITFGetField(szTemp, pachHeader, nOffset+6, 4));
-        psImage->nBlockWidth = 
+        psImage->nBlockWidth =
             atoi(NITFGetField(szTemp, pachHeader, nOffset+10, 4));
-        psImage->nBlockHeight = 
+        psImage->nBlockHeight =
             atoi(NITFGetField(szTemp, pachHeader, nOffset+14, 4));
-            
+
         /* See MIL-STD-2500-C, paragraph 5.4.2.2-d (#3263) */
         if (EQUAL(psImage->szIC, "NC"))
         {
@@ -583,9 +583,9 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
             }
         }
 
-        psImage->nBitsPerSample = 
+        psImage->nBitsPerSample =
             atoi(NITFGetField(szTemp, pachHeader, nOffset+18, 2));
-        
+
         if( psImage->nABPP == 0 )
             psImage->nABPP = psImage->nBitsPerSample;
 
@@ -596,12 +596,12 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
         psImage->nIDLVL = atoi(NITFGetField(szTemp,pachHeader, nOffset+0, 3));
         psImage->nIALVL = atoi(NITFGetField(szTemp,pachHeader, nOffset+3, 3));
         psImage->nILOCRow = atoi(NITFGetField(szTemp,pachHeader,nOffset+6,5));
-        psImage->nILOCColumn = 
+        psImage->nILOCColumn =
             atoi(NITFGetField(szTemp,pachHeader, nOffset+11,5));
 
         memcpy( psImage->szIMAG, pachHeader+nOffset+16, 4 );
         psImage->szIMAG[4] = '\0';
-        
+
         nOffset += 3;                   /* IDLVL */
         nOffset += 3;                   /* IALVL */
         nOffset += 10;                  /* ILOC */
@@ -628,7 +628,7 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
 /* -------------------------------------------------------------------- */
 /*      Override nCols and nRows for NITF 1.1 (not sure why!)           */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(psFile->szVersion,"NITF01.",7) )
+    if( STARTS_WITH_CI(psFile->szVersion, "NITF01.") )
     {
         psImage->nCols = psImage->nBlocksPerRow * psImage->nBlockWidth;
         psImage->nRows = psImage->nBlocksPerColumn * psImage->nBlockHeight;
@@ -640,7 +640,7 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
     else if( nOffset+10 <= (int)psSegInfo->nSegmentHeaderSize )
     {
         int nUserTREBytes, nExtendedTREBytes;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Are there user TRE bytes to skip?                               */
 /* -------------------------------------------------------------------- */
@@ -678,19 +678,19 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
 
         if( nExtendedTREBytes > 3 )
         {
-            if( (int)psSegInfo->nSegmentHeaderSize < 
+            if( (int)psSegInfo->nSegmentHeaderSize <
                             nOffset + nExtendedTREBytes )
                 GOTO_header_too_small();
 
-            psImage->pachTRE = (char *) 
-                CPLRealloc( psImage->pachTRE, 
+            psImage->pachTRE = (char *)
+                CPLRealloc( psImage->pachTRE,
                             psImage->nTREBytes + nExtendedTREBytes - 3 );
-            memcpy( psImage->pachTRE + psImage->nTREBytes, 
-                    pachHeader + nOffset + 3, 
+            memcpy( psImage->pachTRE + psImage->nTREBytes,
+                    pachHeader + nOffset + 3,
                     nExtendedTREBytes - 3 );
 
             psImage->nTREBytes += (nExtendedTREBytes - 3);
-            nOffset += nExtendedTREBytes;
+            /*nOffset += nExtendedTREBytes;*/
         }
     }
 
@@ -698,7 +698,7 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
 /*      Is there a location table to load?                              */
 /* -------------------------------------------------------------------- */
     NITFLoadLocationTable( psImage );
-    
+
     /* Fix bug #1744 */
     if (psImage->nBands == 1)
         NITFLoadColormapSubSection ( psImage );
@@ -711,16 +711,16 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
     if( psImage->chIMODE == 'S' )
     {
         psImage->nPixelOffset = psImage->nWordSize;
-        psImage->nLineOffset = 
+        psImage->nLineOffset =
             ((GIntBig) psImage->nBlockWidth * psImage->nBitsPerSample) / 8;
         psImage->nBlockOffset = psImage->nLineOffset * psImage->nBlockHeight;
-        psImage->nBandOffset = psImage->nBlockOffset * psImage->nBlocksPerRow 
+        psImage->nBandOffset = psImage->nBlockOffset * psImage->nBlocksPerRow
             * psImage->nBlocksPerColumn;
     }
     else if( psImage->chIMODE == 'P' )
     {
         psImage->nPixelOffset = psImage->nWordSize * psImage->nBands;
-        psImage->nLineOffset = 
+        psImage->nLineOffset =
             ((GIntBig) psImage->nBlockWidth * psImage->nBitsPerSample * psImage->nBands) / 8;
         psImage->nBandOffset = psImage->nWordSize;
         psImage->nBlockOffset = psImage->nLineOffset * psImage->nBlockHeight;
@@ -728,7 +728,7 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
     else if( psImage->chIMODE == 'R' )
     {
         psImage->nPixelOffset = psImage->nWordSize;
-        psImage->nBandOffset = 
+        psImage->nBandOffset =
             ((GIntBig) psImage->nBlockWidth * psImage->nBitsPerSample) / 8;
         psImage->nLineOffset = psImage->nBandOffset * psImage->nBands;
         psImage->nBlockOffset = psImage->nLineOffset * psImage->nBlockHeight;
@@ -736,7 +736,7 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
     else if( psImage->chIMODE == 'B' )
     {
         psImage->nPixelOffset = psImage->nWordSize;
-        psImage->nLineOffset = 
+        psImage->nLineOffset =
             ((GIntBig) psImage->nBlockWidth * psImage->nBitsPerSample) / 8;
         psImage->nBandOffset = psImage->nBlockHeight * psImage->nLineOffset;
         psImage->nBlockOffset = psImage->nBandOffset * psImage->nBands;
@@ -744,7 +744,7 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
     else
     {
         psImage->nPixelOffset = psImage->nWordSize;
-        psImage->nLineOffset = 
+        psImage->nLineOffset =
             ((GIntBig) psImage->nBlockWidth * psImage->nBitsPerSample) / 8;
         psImage->nBandOffset = psImage->nBlockHeight * psImage->nLineOffset;
         psImage->nBlockOffset = psImage->nBandOffset * psImage->nBands;
@@ -755,12 +755,11 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
 /* -------------------------------------------------------------------- */
 
     /* Int overflow already checked above */
-    psImage->panBlockStart = (GUIntBig *) 
-        VSICalloc( psImage->nBlocksPerRow * psImage->nBlocksPerColumn 
+    psImage->panBlockStart = (GUIntBig *)
+        VSI_CALLOC_VERBOSE( psImage->nBlocksPerRow * psImage->nBlocksPerColumn
                    * psImage->nBands, sizeof(GUIntBig) );
     if (psImage->panBlockStart == NULL)
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate block map");
         NITFImageDeaccess(psImage);
         return NULL;
     }
@@ -782,7 +781,7 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
         }
 
         if( nLocBase == psSegInfo->nSegmentStart )
-            CPLError( CE_Warning, CPLE_AppDefined, 
+            CPLError( CE_Warning, CPLE_AppDefined,
                       "Failed to find spatial data location, guessing." );
 
         for( i=0; i < psImage->nBlocksPerRow * psImage->nBlocksPerColumn; i++ )
@@ -796,7 +795,7 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
 /* -------------------------------------------------------------------- */
     else if( psImage->szIC[0] != 'M' && psImage->szIC[1] != 'M' )
     {
-        int iBlockX, iBlockY, iBand;
+        int iBlockX, iBlockY;
 
         for( iBlockY = 0; iBlockY < psImage->nBlocksPerColumn; iBlockY++ )
         {
@@ -807,12 +806,12 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
                     int iBlock;
 
                     iBlock = iBlockX + iBlockY * psImage->nBlocksPerRow
-                        + iBand * psImage->nBlocksPerRow 
+                        + iBand * psImage->nBlocksPerRow
                         * psImage->nBlocksPerColumn;
-                    
-                    psImage->panBlockStart[iBlock] = 
+
+                    psImage->panBlockStart[iBlock] =
                         psSegInfo->nSegmentStart
-                        + ((iBlockX + iBlockY * psImage->nBlocksPerRow) 
+                        + ((iBlockX + iBlockY * psImage->nBlocksPerRow)
                            * psImage->nBlockOffset)
                         + (iBand * psImage->nBandOffset );
                 }
@@ -829,17 +828,18 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
         GUInt32  nIMDATOFF;
         GUInt16  nBMRLNTH, nTMRLNTH, nTPXCDLNTH;
         int nBlockCount;
+        int bOK = TRUE;
 
         nBlockCount = psImage->nBlocksPerRow * psImage->nBlocksPerColumn
             * psImage->nBands;
 
         CPLAssert( psImage->szIC[0] == 'M' || psImage->szIC[1] == 'M' );
 
-        VSIFSeekL( psFile->fp, psSegInfo->nSegmentStart, SEEK_SET );
-        VSIFReadL( &nIMDATOFF, 1, 4, psFile->fp );
-        VSIFReadL( &nBMRLNTH, 1, 2, psFile->fp );
-        VSIFReadL( &nTMRLNTH, 1, 2, psFile->fp );
-        VSIFReadL( &nTPXCDLNTH, 1, 2, psFile->fp );
+        bOK &= VSIFSeekL( psFile->fp, psSegInfo->nSegmentStart, SEEK_SET ) == 0;
+        bOK &= VSIFReadL( &nIMDATOFF, 1, 4, psFile->fp ) == 4;
+        bOK &= VSIFReadL( &nBMRLNTH, 1, 2, psFile->fp ) == 2;
+        bOK &= VSIFReadL( &nTMRLNTH, 1, 2, psFile->fp ) == 2;
+        bOK &= VSIFReadL( &nTPXCDLNTH, 1, 2, psFile->fp ) == 2;
 
         CPL_MSBPTR32( &nIMDATOFF );
         CPL_MSBPTR16( &nBMRLNTH );
@@ -851,40 +851,39 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
             GByte byNodata;
 
             psImage->bNoDataSet = TRUE;
-            VSIFReadL( &byNodata, 1, 1, psFile->fp );
+            bOK &= VSIFReadL( &byNodata, 1, 1, psFile->fp ) == 1;
             psImage->nNoDataValue = byNodata;
         }
         else
-            VSIFSeekL( psFile->fp, (nTPXCDLNTH+7)/8, SEEK_CUR );
+            bOK &= VSIFSeekL( psFile->fp, (nTPXCDLNTH+7)/8, SEEK_CUR ) == 0;
 
         if( nBMRLNTH == 4 && psImage->chIMODE == 'P' )
         {
-            int nStoredBlocks = psImage->nBlocksPerRow 
-                * psImage->nBlocksPerColumn; 
-            int iBand;
+            int nStoredBlocks = psImage->nBlocksPerRow
+                * psImage->nBlocksPerColumn;
 
-            for( i = 0; i < nStoredBlocks; i++ )
+            for( i = 0; bOK && i < nStoredBlocks; i++ )
             {
-                GUInt32 nOffset;
-                VSIFReadL( &nOffset, 4, 1, psFile->fp );
-                CPL_MSBPTR32( &nOffset );
-                psImage->panBlockStart[i] = nOffset;
+                GUInt32 l_nOffset;
+                bOK &= VSIFReadL( &l_nOffset, 4, 1, psFile->fp ) == 1;
+                CPL_MSBPTR32( &l_nOffset );
+                psImage->panBlockStart[i] = l_nOffset;
                 if( psImage->panBlockStart[i] != 0xffffffff )
                 {
-                    psImage->panBlockStart[i] 
+                    psImage->panBlockStart[i]
                         += psSegInfo->nSegmentStart + nIMDATOFF;
 
                     for( iBand = 1; iBand < psImage->nBands; iBand++ )
                     {
-                        psImage->panBlockStart[i + iBand * nStoredBlocks] = 
-                            psImage->panBlockStart[i] 
+                        psImage->panBlockStart[i + iBand * nStoredBlocks] =
+                            psImage->panBlockStart[i]
                             + iBand * psImage->nBandOffset;
                     }
                 }
                 else
                 {
                     for( iBand = 1; iBand < psImage->nBands; iBand++ )
-                        psImage->panBlockStart[i + iBand * nStoredBlocks] = 
+                        psImage->panBlockStart[i + iBand * nStoredBlocks] =
                             0xffffffff;
                 }
             }
@@ -892,19 +891,19 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
         else if( nBMRLNTH == 4 )
         {
             int isM4 = EQUAL(psImage->szIC,"M4");
-            for( i=0; i < nBlockCount; i++ )
+            for( i=0; bOK && i < nBlockCount; i++ )
             {
-                GUInt32 nOffset;
-                VSIFReadL( &nOffset, 4, 1, psFile->fp );
-                CPL_MSBPTR32( &nOffset );
-                psImage->panBlockStart[i] = nOffset;
+                GUInt32 l_nOffset;
+                bOK &= VSIFReadL( &l_nOffset, 4, 1, psFile->fp ) == 1;
+                CPL_MSBPTR32( &l_nOffset );
+                psImage->panBlockStart[i] = l_nOffset;
                 if( psImage->panBlockStart[i] != 0xffffffff )
                 {
                     if (isM4 && (psImage->panBlockStart[i] % 6144) != 0)
                     {
                         break;
                     }
-                    psImage->panBlockStart[i] 
+                    psImage->panBlockStart[i]
                         += psSegInfo->nSegmentStart + nIMDATOFF;
                 }
             }
@@ -920,30 +919,30 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
                 bGotWrongOffset = TRUE;
                 CPLError( CE_Warning, CPLE_AppDefined,
                           "Block start for block %d is wrong. Retrying with one extra byte shift...", i);
-                VSIFSeekL( psFile->fp, psSegInfo->nSegmentStart +
+                bOK &= VSIFSeekL( psFile->fp, psSegInfo->nSegmentStart +
                                        4 + /* nIMDATOFF */
                                        2 + /* nBMRLNTH */
                                        2 + /* nTMRLNTH */
                                        2 + /* nTPXCDLNTH */
                                        (nTPXCDLNTH+7)/8 +
                                        1, /* MAGIC here ! One byte shift... */
-                            SEEK_SET );
+                            SEEK_SET ) == 0;
 
-                for( i=0; i < nBlockCount; i++ )
+                for( i=0; bOK && i < nBlockCount; i++ )
                 {
-                    GUInt32 nOffset;
-                    VSIFReadL( &nOffset, 4, 1, psFile->fp );
-                    CPL_MSBPTR32( &nOffset );
-                    psImage->panBlockStart[i] = nOffset;
+                    GUInt32 l_nOffset;
+                    bOK &= VSIFReadL( &l_nOffset, 4, 1, psFile->fp ) == 1;
+                    CPL_MSBPTR32( &l_nOffset );
+                    psImage->panBlockStart[i] = l_nOffset;
                     if( psImage->panBlockStart[i] != 0xffffffff )
                     {
                         if ((psImage->panBlockStart[i] % 6144) != 0)
                         {
-                            CPLError( CE_Warning, CPLE_AppDefined, 
+                            CPLError( CE_Warning, CPLE_AppDefined,
                                       "Block start for block %d is still wrong. Display will be wrong.", i );
                             break;
                         }
-                        psImage->panBlockStart[i] 
+                        psImage->panBlockStart[i]
                             += psSegInfo->nSegmentStart + nIMDATOFF;
                     }
                 }
@@ -959,7 +958,7 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
             }
             else if( EQUAL(psImage->szIC,"NM") )
             {
-                int iBlockX, iBlockY, iBand;
+                int iBlockX, iBlockY;
 
                 for( iBlockY = 0; iBlockY < psImage->nBlocksPerColumn; iBlockY++ )
                 {
@@ -970,12 +969,12 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
                             int iBlock;
 
                             iBlock = iBlockX + iBlockY * psImage->nBlocksPerRow
-                                + iBand * psImage->nBlocksPerRow 
+                                + iBand * psImage->nBlocksPerRow
                                 * psImage->nBlocksPerColumn;
 
-                            psImage->panBlockStart[iBlock] = 
+                            psImage->panBlockStart[iBlock] =
                                 psSegInfo->nSegmentStart + nIMDATOFF
-                                + ((iBlockX + iBlockY * psImage->nBlocksPerRow) 
+                                + ((iBlockX + iBlockY * psImage->nBlocksPerRow)
                                 * psImage->nBlockOffset)
                                 + (iBand * psImage->nBandOffset );
                         }
@@ -984,11 +983,17 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
             }
             else
             {
-                CPLError( CE_Warning, CPLE_AppDefined, 
+                CPLError( CE_Warning, CPLE_AppDefined,
                           "Unsupported IC value '%s', image access will likely fail.",
                           psImage->szIC );
             }
         }
+        if( !bOK )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+            NITFImageDeaccess(psImage);
+            return NULL;
+        }
     }
 
 
@@ -1004,7 +1009,7 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
 /*      subblocks will be then transparent.                             */
 /* -------------------------------------------------------------------- */
     if( !psImage->bNoDataSet
-        && psImage->nBands == 1 
+        && psImage->nBands == 1
         && psImage->nBitsPerSample == 8 )
     {
         NITFBandInfo *psBandInfo = psImage->pasBandInfo;
@@ -1055,9 +1060,15 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
         {
             double adfTarget[8];
 
-            VSIFSeekL( psFile->fp, psImage->pasLocations[i].nLocOffset,
-                      SEEK_SET );
-            VSIFReadL( adfTarget, 8, 8, psFile->fp );
+            if( VSIFSeekL( psFile->fp, psImage->pasLocations[i].nLocOffset,
+                      SEEK_SET ) != 0 ||
+                VSIFReadL( adfTarget, 8, 8, psFile->fp ) != 8 )
+            {
+                CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+                NITFImageDeaccess(psImage);
+                return NULL;
+            }
+
             for( i = 0; i < 8; i++ )
                 CPL_MSBPTR64( (adfTarget + i) );
 
@@ -1155,7 +1166,7 @@ void NITFImageDeaccess( NITFImage *psImage )
 /*      from OpenMap ... open source means sharing!                     */
 /************************************************************************/
 
-static void NITFUncompressVQTile( NITFImage *psImage, 
+static void NITFUncompressVQTile( NITFImage *psImage,
                                   GByte *pabyVQBuf,
                                   GByte *pabyResult )
 
@@ -1176,19 +1187,19 @@ static void NITFUncompressVQTile( NITFImage *psImage,
              * 4x4 tile compressed is 12 bits )
              * this little code was grabbed from openmap software.
              */
-                  
+
             /* Get first 12-bit value as index into VQ table */
 
             GUInt16 val1 = (firstByte << 4) | (secondByte >> 4);
-                  
+
             /* Get second 12-bit value as index into VQ table*/
 
             GUInt16 val2 = ((secondByte & 0x000F) << 8) | thirdByte;
-                  
+
             for ( t = 0; t < 4; ++t)
             {
                 GByte *pabyTarget = pabyResult + (i+t) * 256 + j;
-                
+
                 memcpy( pabyTarget, psImage->apanVQLUT[t] + val1, 4 );
                 memcpy( pabyTarget+4, psImage->apanVQLUT[t] + val2, 4);
             }
@@ -1200,13 +1211,13 @@ static void NITFUncompressVQTile( NITFImage *psImage,
 /*                         NITFReadImageBlock()                         */
 /************************************************************************/
 
-int NITFReadImageBlock( NITFImage *psImage, int nBlockX, int nBlockY, 
+int NITFReadImageBlock( NITFImage *psImage, int nBlockX, int nBlockY,
                         int nBand, void *pData )
 
 {
     int   nWrkBufSize;
     int   iBaseBlock = nBlockX + nBlockY * psImage->nBlocksPerRow;
-    int   iFullBlock = iBaseBlock 
+    int   iFullBlock = iBaseBlock
         + (nBand-1) * psImage->nBlocksPerRow * psImage->nBlocksPerColumn;
 
 /* -------------------------------------------------------------------- */
@@ -1226,16 +1237,20 @@ int NITFReadImageBlock( NITFImage *psImage, int nBlockX, int nBlockY,
     {
         if (nBlockX != 0 || nBlockY != 0)
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "assert nBlockX == 0 && nBlockY == 0 failed\n");
             return BLKREAD_FAIL;
         }
-        VSIFSeekL( psImage->psFile->fp,
-                   psImage->panBlockStart[0] + 
+        if( VSIFSeekL( psImage->psFile->fp,
+                   psImage->panBlockStart[0] +
                     (psImage->nBlockWidth * psImage->nBlockHeight + 7) / 8 * (nBand-1),
-                   SEEK_SET );
-        VSIFReadL( pData, 1, (psImage->nBlockWidth * psImage->nBlockHeight + 7) / 8, psImage->psFile->fp );
-        return BLKREAD_OK;
+                   SEEK_SET ) == 0 &&
+            VSIFReadL( pData, (psImage->nBlockWidth * psImage->nBlockHeight + 7) / 8, 1, psImage->psFile->fp ) == 1 )
+        {
+            return BLKREAD_OK;
+        }
+        CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        return BLKREAD_FAIL;
     }
 
 /* -------------------------------------------------------------------- */
@@ -1261,14 +1276,14 @@ int NITFReadImageBlock( NITFImage *psImage, int nBlockX, int nBlockY,
         && psImage->szIC[0] != 'C' && psImage->szIC[0] != 'M'
         && psImage->chIMODE != 'P' )
     {
-        if( VSIFSeekL( psImage->psFile->fp, 
-                      psImage->panBlockStart[iFullBlock], 
-                      SEEK_SET ) != 0 
+        if( VSIFSeekL( psImage->psFile->fp,
+                      psImage->panBlockStart[iFullBlock],
+                      SEEK_SET ) != 0
             || (int) VSIFReadL( pData, 1, nWrkBufSize,
                                psImage->psFile->fp ) != nWrkBufSize )
         {
-            CPLError( CE_Failure, CPLE_FileIO, 
-                      "Unable to read %d byte block from " CPL_FRMT_GUIB ".", 
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Unable to read %d byte block from " CPL_FRMT_GUIB ".",
                       nWrkBufSize, psImage->panBlockStart[iFullBlock] );
             return BLKREAD_FAIL;
         }
@@ -1294,12 +1309,12 @@ int NITFReadImageBlock( NITFImage *psImage, int nBlockX, int nBlockY,
             if( psImage->chIMODE == 'S' || (psImage->chIMODE == 'B' && psImage->nBands == 1) )
             {
                 nWrkBufSize = ((psImage->nBlockWidth * psImage->nBlockHeight * psImage->nBitsPerSample) + 7) / 8;
-                if( VSIFSeekL( psImage->psFile->fp, psImage->panBlockStart[iFullBlock], SEEK_SET ) != 0 
+                if( VSIFSeekL( psImage->psFile->fp, psImage->panBlockStart[iFullBlock], SEEK_SET ) != 0
                   || (int) VSIFReadL( pData, 1, nWrkBufSize, psImage->psFile->fp ) != nWrkBufSize )
                 {
-                    CPLError( CE_Failure, CPLE_FileIO, 
-                              "Unable to read %d byte block from %d.", 
-                              (int) nWrkBufSize, 
+                    CPLError( CE_Failure, CPLE_FileIO,
+                              "Unable to read %d byte block from %d.",
+                              (int) nWrkBufSize,
                               (int) psImage->panBlockStart[iFullBlock] );
                     return BLKREAD_FAIL;
                 }
@@ -1315,24 +1330,22 @@ int NITFReadImageBlock( NITFImage *psImage, int nBlockX, int nBlockY,
 /* -------------------------------------------------------------------- */
     if( psImage->szIC[0] == 'N' )
     {
-        GByte *pabyWrkBuf = (GByte *) VSIMalloc(nWrkBufSize);
+        GByte *pabyWrkBuf = (GByte *) VSI_MALLOC_VERBOSE(nWrkBufSize);
         int   iPixel, iLine;
 
         if (pabyWrkBuf == NULL)
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory, 
-                      "Cannot allocate working buffer" );
             return BLKREAD_FAIL;
         }
 
         /* read all the data needed to get our requested band-block */
-        if( VSIFSeekL( psImage->psFile->fp, psImage->panBlockStart[iFullBlock], 
-                      SEEK_SET ) != 0 
+        if( VSIFSeekL( psImage->psFile->fp, psImage->panBlockStart[iFullBlock],
+                      SEEK_SET ) != 0
             || (int) VSIFReadL( pabyWrkBuf, 1, nWrkBufSize,
                                psImage->psFile->fp ) != nWrkBufSize )
         {
-            CPLError( CE_Failure, CPLE_FileIO, 
-                      "Unable to read %d byte block from " CPL_FRMT_GUIB ".", 
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Unable to read %d byte block from " CPL_FRMT_GUIB ".",
                       nWrkBufSize, psImage->panBlockStart[iFullBlock] );
             CPLFree( pabyWrkBuf );
             return BLKREAD_FAIL;
@@ -1343,12 +1356,12 @@ int NITFReadImageBlock( NITFImage *psImage, int nBlockX, int nBlockY,
             GByte *pabySrc, *pabyDst;
 
             pabySrc = pabyWrkBuf + iLine * psImage->nLineOffset;
-            pabyDst = ((GByte *) pData) 
+            pabyDst = ((GByte *) pData)
                 + iLine * (psImage->nWordSize * psImage->nBlockWidth);
 
             for( iPixel = 0; iPixel < psImage->nBlockWidth; iPixel++ )
             {
-                memcpy( pabyDst + iPixel * psImage->nWordSize, 
+                memcpy( pabyDst + iPixel * psImage->nWordSize,
                         pabySrc + iPixel * psImage->nPixelOffset,
                         psImage->nWordSize );
             }
@@ -1375,24 +1388,24 @@ int NITFReadImageBlock( NITFImage *psImage, int nBlockX, int nBlockY,
 
         if( psImage->apanVQLUT[0] == NULL )
         {
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                       "File lacks VQ LUTs, unable to decode imagery." );
             return BLKREAD_FAIL;
         }
 
         /* Read the codewords */
-        if( VSIFSeekL(psImage->psFile->fp, psImage->panBlockStart[iFullBlock], 
-                      SEEK_SET ) != 0 
+        if( VSIFSeekL(psImage->psFile->fp, psImage->panBlockStart[iFullBlock],
+                      SEEK_SET ) != 0
             || VSIFReadL(abyVQCoded, 1, sizeof(abyVQCoded),
                          psImage->psFile->fp ) != sizeof(abyVQCoded) )
         {
-            CPLError( CE_Failure, CPLE_FileIO, 
-                      "Unable to read %d byte block from " CPL_FRMT_GUIB ".", 
-                      (int) sizeof(abyVQCoded), 
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Unable to read %d byte block from " CPL_FRMT_GUIB ".",
+                      (int) sizeof(abyVQCoded),
                       psImage->panBlockStart[iFullBlock] );
             return BLKREAD_FAIL;
         }
-        
+
         NITFUncompressVQTile( psImage, abyVQCoded, pData );
 
         return BLKREAD_OK;
@@ -1403,6 +1416,7 @@ int NITFReadImageBlock( NITFImage *psImage, int nBlockX, int nBlockY,
 /* -------------------------------------------------------------------- */
     else if( EQUAL(psImage->szIC,"C2") || EQUAL(psImage->szIC,"M2") )
     {
+        GIntBig nSignedRawBytes;
         size_t nRawBytes;
         NITFSegmentInfo *psSegInfo;
         int success;
@@ -1410,46 +1424,53 @@ int NITFReadImageBlock( NITFImage *psImage, int nBlockX, int nBlockY,
 
         if (psImage->nBitsPerSample != 8)
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Unsupported bits per sample value (%d) for C2/M2 compression",
                       psImage->nBitsPerSample);
             return BLKREAD_FAIL;
         }
 
-        if( iFullBlock < psImage->nBlocksPerRow * psImage->nBlocksPerColumn-1 )
-            nRawBytes = (size_t)( psImage->panBlockStart[iFullBlock+1] 
-                - psImage->panBlockStart[iFullBlock] );
+        if( iFullBlock < psImage->nBlocksPerRow * psImage->nBlocksPerColumn * psImage->nBands -1 )
+        {
+            nSignedRawBytes = (GIntBig)psImage->panBlockStart[iFullBlock+1]
+                - (GIntBig)psImage->panBlockStart[iFullBlock];
+        }
         else
         {
             psSegInfo = psImage->psFile->pasSegmentInfo + psImage->iSegment;
-            nRawBytes = (size_t)(psSegInfo->nSegmentStart 
-                                + psSegInfo->nSegmentSize 
-                                - psImage->panBlockStart[iFullBlock]);
+            nSignedRawBytes = (GIntBig)psSegInfo->nSegmentStart
+                                + (GIntBig)psSegInfo->nSegmentSize
+                                - (GIntBig)psImage->panBlockStart[iFullBlock];
+        }
+        if( nSignedRawBytes <= 0 || nSignedRawBytes > INT_MAX )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "Invalid block size : " CPL_FRMT_GIB,
+                      nSignedRawBytes );
+            return BLKREAD_FAIL;
         }
 
-        pabyRawData = (GByte *) VSIMalloc( nRawBytes );
+        nRawBytes = (size_t)nSignedRawBytes;
+        pabyRawData = (GByte *) VSI_MALLOC_VERBOSE( nRawBytes );
         if (pabyRawData == NULL)
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory, 
-                      "Cannot allocate working buffer" );
             return BLKREAD_FAIL;
         }
 
         /* Read the codewords */
-        if( VSIFSeekL(psImage->psFile->fp, psImage->panBlockStart[iFullBlock], 
-                      SEEK_SET ) != 0 
-            || VSIFReadL(pabyRawData, 1, nRawBytes, psImage->psFile->fp ) !=  
+        if( VSIFSeekL(psImage->psFile->fp, psImage->panBlockStart[iFullBlock],
+                      SEEK_SET ) != 0
+            || VSIFReadL(pabyRawData, 1, nRawBytes, psImage->psFile->fp ) !=
             nRawBytes )
         {
-            CPLError( CE_Failure, CPLE_FileIO, 
-                      "Unable to read %d byte block from " CPL_FRMT_GUIB ".", 
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Unable to read %d byte block from " CPL_FRMT_GUIB ".",
                       (int) nRawBytes, psImage->panBlockStart[iFullBlock] );
             CPLFree( pabyRawData );
             return BLKREAD_FAIL;
         }
-        
-        success = NITFUncompressARIDPCM( psImage, pabyRawData, nRawBytes, pData );
-        
+
+        success = NITFUncompressARIDPCM( psImage, pabyRawData, (int)nRawBytes, pData );
+
         CPLFree( pabyRawData );
 
         if( success )
@@ -1463,6 +1484,7 @@ int NITFReadImageBlock( NITFImage *psImage, int nBlockX, int nBlockY,
 /* -------------------------------------------------------------------- */
     else if( EQUAL(psImage->szIC,"C1") || EQUAL(psImage->szIC,"M1") )
     {
+        GIntBig nSignedRawBytes;
         size_t nRawBytes;
         NITFSegmentInfo *psSegInfo;
         int success;
@@ -1470,46 +1492,54 @@ int NITFReadImageBlock( NITFImage *psImage, int nBlockX, int nBlockY,
 
         if (psImage->nBitsPerSample != 1)
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Invalid bits per sample value (%d) for C1/M1 compression",
                       psImage->nBitsPerSample);
             return BLKREAD_FAIL;
         }
 
-        if( iFullBlock < psImage->nBlocksPerRow * psImage->nBlocksPerColumn-1 )
-            nRawBytes = (size_t)( psImage->panBlockStart[iFullBlock+1]
-                                  - psImage->panBlockStart[iFullBlock] );
+        if( iFullBlock < psImage->nBlocksPerRow * psImage->nBlocksPerColumn * psImage->nBands -1 )
+        {
+            nSignedRawBytes = (GIntBig)psImage->panBlockStart[iFullBlock+1]
+                - (GIntBig)psImage->panBlockStart[iFullBlock];
+        }
         else
         {
             psSegInfo = psImage->psFile->pasSegmentInfo + psImage->iSegment;
-            nRawBytes = (size_t)( psSegInfo->nSegmentStart 
-                            + psSegInfo->nSegmentSize
-                            - psImage->panBlockStart[iFullBlock] );
+            nSignedRawBytes = (GIntBig)psSegInfo->nSegmentStart
+                                + (GIntBig)psSegInfo->nSegmentSize
+                                - (GIntBig)psImage->panBlockStart[iFullBlock];
+        }
+        if( nSignedRawBytes <= 0 || nSignedRawBytes > INT_MAX )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "Invalid block size : " CPL_FRMT_GIB,
+                      nSignedRawBytes );
+            return BLKREAD_FAIL;
         }
 
-        pabyRawData = (GByte *) VSIMalloc( nRawBytes );
+        nRawBytes = (size_t)nSignedRawBytes;
+        pabyRawData = (GByte *) VSI_MALLOC_VERBOSE( nRawBytes );
         if (pabyRawData == NULL)
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory, 
-                      "Cannot allocate working buffer" );
             return BLKREAD_FAIL;
         }
 
         /* Read the codewords */
-        if( VSIFSeekL(psImage->psFile->fp, psImage->panBlockStart[iFullBlock], 
-                      SEEK_SET ) != 0 
-            || VSIFReadL(pabyRawData, 1, nRawBytes, psImage->psFile->fp ) !=  
+        if( VSIFSeekL(psImage->psFile->fp, psImage->panBlockStart[iFullBlock],
+                      SEEK_SET ) != 0
+            || VSIFReadL(pabyRawData, 1, nRawBytes, psImage->psFile->fp ) !=
             nRawBytes )
         {
-            CPLError( CE_Failure, CPLE_FileIO, 
-                      "Unable to read %d byte block from " CPL_FRMT_GUIB ".", 
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Unable to read %d byte block from " CPL_FRMT_GUIB ".",
                       (int) nRawBytes, psImage->panBlockStart[iFullBlock] );
+            CPLFree( pabyRawData );
             return BLKREAD_FAIL;
         }
-        
-        success = NITFUncompressBILEVEL( psImage, pabyRawData, (int)nRawBytes, 
+
+        success = NITFUncompressBILEVEL( psImage, pabyRawData, (int)nRawBytes,
                                          pData );
-        
+
         CPLFree( pabyRawData );
 
         if( success )
@@ -1523,7 +1553,7 @@ int NITFReadImageBlock( NITFImage *psImage, int nBlockX, int nBlockY,
 /* -------------------------------------------------------------------- */
     else if( atoi(psImage->szIC + 1) > 0 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "Unsupported imagery compression format %s in NITF library.",
                   psImage->szIC );
         return BLKREAD_FAIL;
@@ -1536,13 +1566,13 @@ int NITFReadImageBlock( NITFImage *psImage, int nBlockX, int nBlockY,
 /*                        NITFWriteImageBlock()                         */
 /************************************************************************/
 
-int NITFWriteImageBlock( NITFImage *psImage, int nBlockX, int nBlockY, 
+int NITFWriteImageBlock( NITFImage *psImage, int nBlockX, int nBlockY,
                          int nBand, void *pData )
 
 {
     GUIntBig   nWrkBufSize;
     int   iBaseBlock = nBlockX + nBlockY * psImage->nBlocksPerRow;
-    int   iFullBlock = iBaseBlock 
+    int   iFullBlock = iBaseBlock
         + (nBand-1) * psImage->nBlocksPerRow * psImage->nBlocksPerColumn;
 
     if( nBand == 0 )
@@ -1553,7 +1583,8 @@ int NITFWriteImageBlock( NITFImage *psImage, int nBlockX, int nBlockY,
         + psImage->nWordSize;
 
     if (nWrkBufSize == 0)
-      nWrkBufSize = (psImage->nBlockWidth*psImage->nBlockHeight*psImage->nBitsPerSample+7)/8;
+      nWrkBufSize = ((GUIntBig)psImage->nBlockWidth
+                     * psImage->nBlockHeight * psImage->nBitsPerSample+7)/8;
 
 /* -------------------------------------------------------------------- */
 /*      Can we do a direct read into our buffer?                        */
@@ -1567,13 +1598,13 @@ int NITFWriteImageBlock( NITFImage *psImage, int nBlockX, int nBlockY,
                        psImage->nBlockWidth * psImage->nBlockHeight);
 #endif
 
-        if( VSIFSeekL( psImage->psFile->fp, psImage->panBlockStart[iFullBlock], 
-                      SEEK_SET ) != 0 
+        if( VSIFSeekL( psImage->psFile->fp, psImage->panBlockStart[iFullBlock],
+                      SEEK_SET ) != 0
             || (GUIntBig) VSIFWriteL( pData, 1, (size_t)nWrkBufSize,
                                 psImage->psFile->fp ) != nWrkBufSize )
         {
-            CPLError( CE_Failure, CPLE_FileIO, 
-                      "Unable to write " CPL_FRMT_GUIB " byte block from " CPL_FRMT_GUIB ".", 
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Unable to write " CPL_FRMT_GUIB " byte block from " CPL_FRMT_GUIB ".",
                       nWrkBufSize, psImage->panBlockStart[iFullBlock] );
             return BLKREAD_FAIL;
         }
@@ -1592,7 +1623,7 @@ int NITFWriteImageBlock( NITFImage *psImage, int nBlockX, int nBlockY,
 /* -------------------------------------------------------------------- */
 /*      Other forms not supported at this time.                         */
 /* -------------------------------------------------------------------- */
-    CPLError( CE_Failure, CPLE_NotSupported, 
+    CPLError( CE_Failure, CPLE_NotSupported,
               "Mapped, interleaved and compressed NITF forms not supported\n"
               "for writing at this time." );
 
@@ -1622,14 +1653,14 @@ int NITFReadImageLine( NITFImage *psImage, int nLine, int nBand, void *pData )
 
     if( psImage->nBlockWidth < psImage->nCols)
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "For scanline access, block width cannot be lesser than the number of columns." );
         return BLKREAD_FAIL;
     }
 
     if( !EQUAL(psImage->szIC,"NC") )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Scanline access not supported on compressed NITF files." );
         return BLKREAD_FAIL;
     }
@@ -1641,13 +1672,14 @@ int NITFReadImageLine( NITFImage *psImage, int nLine, int nBand, void *pData )
         + psImage->nLineOffset * nLine
         + psImage->nBandOffset * (nBand-1);
 
-    nLineSize = (size_t)psImage->nPixelOffset * (psImage->nBlockWidth - 1) 
+    nLineSize = (size_t)psImage->nPixelOffset * (psImage->nBlockWidth - 1)
         + psImage->nWordSize;
 
     if (nLineSize == 0 || psImage->nWordSize * 8 != psImage->nBitsPerSample)
       nLineSize = (psImage->nBlockWidth*psImage->nBitsPerSample+7)/8;
 
-    VSIFSeekL( psImage->psFile->fp, nLineOffsetInFile, SEEK_SET );
+    if( VSIFSeekL( psImage->psFile->fp, nLineOffsetInFile, SEEK_SET ) != 0 )
+        return BLKREAD_FAIL;
 
 /* -------------------------------------------------------------------- */
 /*      Can we do a direct read into our buffer.                        */
@@ -1656,10 +1688,10 @@ int NITFReadImageLine( NITFImage *psImage, int nLine, int nBand, void *pData )
         ((size_t)psImage->nWordSize == psImage->nPixelOffset
          && (size_t)(psImage->nWordSize * psImage->nBlockWidth) == psImage->nLineOffset) )
     {
-        if( VSIFReadL( pData, 1, nLineSize, psImage->psFile->fp ) !=  
+        if( VSIFReadL( pData, 1, nLineSize, psImage->psFile->fp ) !=
             nLineSize )
         {
-            CPLError( CE_Failure, CPLE_FileIO, 
+            CPLError( CE_Failure, CPLE_FileIO,
                       "Unable to read %d bytes for line %d.", (int) nLineSize, nLine );
             return BLKREAD_FAIL;
         }
@@ -1675,18 +1707,16 @@ int NITFReadImageLine( NITFImage *psImage, int nLine, int nBand, void *pData )
 /*      Allocate a buffer for all the interleaved data, and read        */
 /*      it.                                                             */
 /* -------------------------------------------------------------------- */
-    pabyLineBuf = (unsigned char *) VSIMalloc(nLineSize);
+    pabyLineBuf = (unsigned char *) VSI_MALLOC_VERBOSE(nLineSize);
     if (pabyLineBuf == NULL)
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory, 
-                "Cannot allocate working buffer" );
         return BLKREAD_FAIL;
     }
 
-    if( VSIFReadL( pabyLineBuf, 1, nLineSize, psImage->psFile->fp ) !=  
+    if( VSIFReadL( pabyLineBuf, 1, nLineSize, psImage->psFile->fp ) !=
         nLineSize )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                     "Unable to read %d bytes for line %d.", (int) nLineSize, nLine );
         CPLFree(pabyLineBuf);
         return BLKREAD_FAIL;
@@ -1698,13 +1728,13 @@ int NITFReadImageLine( NITFImage *psImage, int nLine, int nBand, void *pData )
     {
         GByte *pabySrc, *pabyDst;
         int iPixel;
-        
+
         pabySrc = pabyLineBuf;
         pabyDst = ((GByte *) pData);
-        
+
         for( iPixel = 0; iPixel < psImage->nBlockWidth; iPixel++ )
         {
-            memcpy( pabyDst + iPixel * psImage->nWordSize, 
+            memcpy( pabyDst + iPixel * psImage->nWordSize,
                     pabySrc + iPixel * psImage->nPixelOffset,
                     psImage->nWordSize );
         }
@@ -1735,21 +1765,21 @@ int NITFWriteImageLine( NITFImage *psImage, int nLine, int nBand, void *pData )
 
     if( psImage->nBlocksPerRow != 1 || psImage->nBlocksPerColumn != 1 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Scanline access not supported on tiled NITF files." );
         return BLKREAD_FAIL;
     }
 
     if( psImage->nBlockWidth < psImage->nCols)
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "For scanline access, block width cannot be lesser than the number of columns." );
         return BLKREAD_FAIL;
     }
 
     if( !EQUAL(psImage->szIC,"NC") )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Scanline access not supported on compressed NITF files." );
         return BLKREAD_FAIL;
     }
@@ -1761,10 +1791,14 @@ int NITFWriteImageLine( NITFImage *psImage, int nLine, int nBand, void *pData )
         + psImage->nLineOffset * nLine
         + psImage->nBandOffset * (nBand-1);
 
-    nLineSize = (size_t)psImage->nPixelOffset * (psImage->nBlockWidth - 1) 
+    nLineSize = (size_t)psImage->nPixelOffset * (psImage->nBlockWidth - 1)
         + psImage->nWordSize;
 
-    VSIFSeekL( psImage->psFile->fp, nLineOffsetInFile, SEEK_SET );
+    if( VSIFSeekL( psImage->psFile->fp, nLineOffsetInFile, SEEK_SET ) != 0 )
+    {
+        CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        return BLKREAD_FAIL;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Can we do a direct write into our buffer.                       */
@@ -1776,7 +1810,11 @@ int NITFWriteImageLine( NITFImage *psImage, int nLine, int nBand, void *pData )
         NITFSwapWords( psImage, pData, psImage->nBlockWidth );
 #endif
 
-        VSIFWriteL( pData, 1, nLineSize, psImage->psFile->fp );
+        if( VSIFWriteL( pData, 1, nLineSize, psImage->psFile->fp ) != nLineSize )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+            return BLKREAD_FAIL;
+        }
 
 #ifdef CPL_LSB
         NITFSwapWords( psImage, pData, psImage->nBlockWidth );
@@ -1789,15 +1827,16 @@ int NITFWriteImageLine( NITFImage *psImage, int nLine, int nBand, void *pData )
 /*      Allocate a buffer for all the interleaved data, and read        */
 /*      it.                                                             */
 /* -------------------------------------------------------------------- */
-    pabyLineBuf = (unsigned char *) VSIMalloc(nLineSize);
+    pabyLineBuf = (unsigned char *) VSI_MALLOC_VERBOSE(nLineSize);
     if (pabyLineBuf == NULL)
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory, 
-                "Cannot allocate working buffer" );
         return BLKREAD_FAIL;
     }
 
-    VSIFReadL( pabyLineBuf, 1, nLineSize, psImage->psFile->fp );
+    if( VSIFReadL( pabyLineBuf, 1, nLineSize, psImage->psFile->fp ) != nLineSize )
+    {
+        memset(pabyLineBuf, 0, nLineSize);
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Copy the desired data into the interleaved buffer.              */
@@ -1805,7 +1844,7 @@ int NITFWriteImageLine( NITFImage *psImage, int nLine, int nBand, void *pData )
     {
         GByte *pabySrc, *pabyDst;
         int iPixel;
-        
+
         pabyDst = pabyLineBuf;
         pabySrc = ((GByte *) pData);
 
@@ -1816,7 +1855,7 @@ int NITFWriteImageLine( NITFImage *psImage, int nLine, int nBand, void *pData )
         for( iPixel = 0; iPixel < psImage->nBlockWidth; iPixel++ )
         {
             memcpy( pabyDst + iPixel * psImage->nPixelOffset,
-                    pabySrc + iPixel * psImage->nWordSize, 
+                    pabySrc + iPixel * psImage->nWordSize,
                     psImage->nWordSize );
         }
 
@@ -1828,8 +1867,13 @@ int NITFWriteImageLine( NITFImage *psImage, int nLine, int nBand, void *pData )
 /* -------------------------------------------------------------------- */
 /*      Write the results back out.                                     */
 /* -------------------------------------------------------------------- */
-    VSIFSeekL( psImage->psFile->fp, nLineOffsetInFile, SEEK_SET );
-    VSIFWriteL( pabyLineBuf, 1, nLineSize, psImage->psFile->fp );
+    if( VSIFSeekL( psImage->psFile->fp, nLineOffsetInFile, SEEK_SET ) != 0 ||
+        VSIFWriteL( pabyLineBuf, 1, nLineSize, psImage->psFile->fp ) != nLineSize )
+    {
+        CPLFree( pabyLineBuf );
+        CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        return BLKREAD_FAIL;
+    }
     CPLFree( pabyLineBuf );
 
     return BLKREAD_OK;
@@ -1839,7 +1883,7 @@ int NITFWriteImageLine( NITFImage *psImage, int nLine, int nBand, void *pData )
 /*                          NITFEncodeDMSLoc()                          */
 /************************************************************************/
 
-static void NITFEncodeDMSLoc( char *pszTarget, double dfValue, 
+static void NITFEncodeDMSLoc( char *pszTarget, size_t nTargetLen, double dfValue,
                               const char *pszAxis )
 
 {
@@ -1874,11 +1918,11 @@ static void NITFEncodeDMSLoc( char *pszTarget, double dfValue,
 /*      rolled into minutes and degrees.                                */
 /* -------------------------------------------------------------------- */
     nSeconds = (int) (dfValue + 0.5);
-    if (nSeconds == 60) 
+    if (nSeconds == 60)
     {
         nSeconds = 0;
         nMinutes += 1;
-        if (nMinutes == 60) 
+        if (nMinutes == 60)
         {
             nMinutes = 0;
             nDegrees += 1;
@@ -1886,10 +1930,10 @@ static void NITFEncodeDMSLoc( char *pszTarget, double dfValue,
     }
 
     if( EQUAL(pszAxis,"Lat") )
-        sprintf( pszTarget, "%02d%02d%02d%c", 
+        snprintf( pszTarget, nTargetLen, "%02d%02d%02d%c",
                  nDegrees, nMinutes, nSeconds, chHemisphere );
     else
-        sprintf( pszTarget, "%03d%02d%02d%c", 
+        snprintf( pszTarget, nTargetLen, "%03d%02d%02d%c",
                  nDegrees, nMinutes, nSeconds, chHemisphere );
 }
 
@@ -1916,7 +1960,7 @@ static void NITFEncodeDMSLoc( char *pszTarget, double dfValue,
     }
 
 int NITFWriteIGEOLO( NITFImage *psImage, char chICORDS,
-                     int nZone, 
+                     int nZone,
                      double dfULX, double dfULY,
                      double dfURX, double dfURY,
                      double dfLRX, double dfLRY,
@@ -1930,7 +1974,7 @@ int NITFWriteIGEOLO( NITFImage *psImage, char chICORDS,
 /* -------------------------------------------------------------------- */
     if( psImage->chICORDS == ' ' )
     {
-        CPLError(CE_Failure, CPLE_NotSupported, 
+        CPLError(CE_Failure, CPLE_NotSupported,
                  "Apparently no space reserved for IGEOLO info in NITF file.\n"
                  "NITFWriteIGEOGLO() fails." );
         return FALSE;
@@ -1938,7 +1982,7 @@ int NITFWriteIGEOLO( NITFImage *psImage, char chICORDS,
 
     if( chICORDS != 'G' && chICORDS != 'N' && chICORDS != 'S' && chICORDS != 'D')
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "Invalid ICOORDS value (%c) for NITFWriteIGEOLO().", chICORDS );
         return FALSE;
     }
@@ -1948,44 +1992,44 @@ int NITFWriteIGEOLO( NITFImage *psImage, char chICORDS,
 /* -------------------------------------------------------------------- */
     if( chICORDS == 'G' )
     {
-        if( fabs(dfULX) > 180 || fabs(dfURX) > 180 
-            || fabs(dfLRX) > 180 || fabs(dfLLX) > 180 
+        if( fabs(dfULX) > 180 || fabs(dfURX) > 180
+            || fabs(dfLRX) > 180 || fabs(dfLLX) > 180
             || fabs(dfULY) >  90 || fabs(dfURY) >  90
             || fabs(dfLRY) >  90 || fabs(dfLLY) >  90 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Attempt to write geographic bound outside of legal range." );
             return FALSE;
         }
 
-        NITFEncodeDMSLoc( szIGEOLO +  0, dfULY, "Lat" );
-        NITFEncodeDMSLoc( szIGEOLO +  7, dfULX, "Long" );
-        NITFEncodeDMSLoc( szIGEOLO + 15, dfURY, "Lat" );
-        NITFEncodeDMSLoc( szIGEOLO + 22, dfURX, "Long" );
-        NITFEncodeDMSLoc( szIGEOLO + 30, dfLRY, "Lat" );
-        NITFEncodeDMSLoc( szIGEOLO + 37, dfLRX, "Long" );
-        NITFEncodeDMSLoc( szIGEOLO + 45, dfLLY, "Lat" );
-        NITFEncodeDMSLoc( szIGEOLO + 52, dfLLX, "Long" );
+        NITFEncodeDMSLoc( szIGEOLO +  0, sizeof(szIGEOLO) - 0, dfULY, "Lat" );
+        NITFEncodeDMSLoc( szIGEOLO +  7, sizeof(szIGEOLO) - 7, dfULX, "Long" );
+        NITFEncodeDMSLoc( szIGEOLO + 15, sizeof(szIGEOLO) - 15, dfURY, "Lat" );
+        NITFEncodeDMSLoc( szIGEOLO + 22, sizeof(szIGEOLO) - 22, dfURX, "Long" );
+        NITFEncodeDMSLoc( szIGEOLO + 30, sizeof(szIGEOLO) - 30, dfLRY, "Lat" );
+        NITFEncodeDMSLoc( szIGEOLO + 37, sizeof(szIGEOLO) - 37, dfLRX, "Long" );
+        NITFEncodeDMSLoc( szIGEOLO + 45, sizeof(szIGEOLO) - 45, dfLLY, "Lat" );
+        NITFEncodeDMSLoc( szIGEOLO + 52, sizeof(szIGEOLO) - 52, dfLLX, "Long" );
     }
 /* -------------------------------------------------------------------- */
 /*      Format geographic coordinates in decimal degrees                */
 /* -------------------------------------------------------------------- */
     else if( chICORDS == 'D' )
     {
-        if( fabs(dfULX) > 180 || fabs(dfURX) > 180 
-            || fabs(dfLRX) > 180 || fabs(dfLLX) > 180 
+        if( fabs(dfULX) > 180 || fabs(dfURX) > 180
+            || fabs(dfLRX) > 180 || fabs(dfLLX) > 180
             || fabs(dfULY) >  90 || fabs(dfURY) >  90
             || fabs(dfLRY) >  90 || fabs(dfLLY) >  90 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Attempt to write geographic bound outside of legal range." );
             return FALSE;
         }
 
-        CPLsprintf(szIGEOLO + 0, "%+#07.3f%+#08.3f", dfULY, dfULX);
-        CPLsprintf(szIGEOLO + 15, "%+#07.3f%+#08.3f", dfURY, dfURX);
-        CPLsprintf(szIGEOLO + 30, "%+#07.3f%+#08.3f", dfLRY, dfLRX);
-        CPLsprintf(szIGEOLO + 45, "%+#07.3f%+#08.3f", dfLLY, dfLLX);
+        CPLsnprintf(szIGEOLO + 0, sizeof(szIGEOLO), "%+#07.3f%+#08.3f", dfULY, dfULX);
+        CPLsnprintf(szIGEOLO + 15, sizeof(szIGEOLO) - 15, "%+#07.3f%+#08.3f", dfURY, dfURX);
+        CPLsnprintf(szIGEOLO + 30, sizeof(szIGEOLO) - 30, "%+#07.3f%+#08.3f", dfLRY, dfLRX);
+        CPLsnprintf(szIGEOLO + 45, sizeof(szIGEOLO) - 45, "%+#07.3f%+#08.3f", dfLLY, dfLLX);
     }
 
 /* -------------------------------------------------------------------- */
@@ -2001,20 +2045,20 @@ int NITFWriteIGEOLO( NITFImage *psImage, char chICORDS,
         CHECK_IGEOLO_UTM_Y("dfLRY", dfLRY);
         CHECK_IGEOLO_UTM_X("dfLLX", dfLLX);
         CHECK_IGEOLO_UTM_Y("dfLLY", dfLLY);
-        CPLsprintf( szIGEOLO + 0, "%02d%06d%07d",
+        CPLsnprintf( szIGEOLO + 0, sizeof(szIGEOLO), "%02d%06d%07d",
                  nZone, (int) floor(dfULX+0.5), (int) floor(dfULY+0.5) );
-        CPLsprintf( szIGEOLO + 15, "%02d%06d%07d",
+        CPLsnprintf( szIGEOLO + 15, sizeof(szIGEOLO) - 15, "%02d%06d%07d",
                  nZone, (int) floor(dfURX+0.5), (int) floor(dfURY+0.5) );
-        CPLsprintf( szIGEOLO + 30, "%02d%06d%07d",
+        CPLsnprintf( szIGEOLO + 30, sizeof(szIGEOLO) - 30, "%02d%06d%07d",
                  nZone, (int) floor(dfLRX+0.5), (int) floor(dfLRY+0.5) );
-        CPLsprintf( szIGEOLO + 45, "%02d%06d%07d",
+        CPLsnprintf( szIGEOLO + 45, sizeof(szIGEOLO) - 45, "%02d%06d%07d",
                  nZone, (int) floor(dfLLX+0.5), (int) floor(dfLLY+0.5) );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Write IGEOLO data to disk.                                      */
 /* -------------------------------------------------------------------- */
-    if( VSIFSeekL( psImage->psFile->fp, 
+    if( VSIFSeekL( psImage->psFile->fp,
                   psImage->psFile->pasSegmentInfo[psImage->iSegment].nSegmentHeaderStart + 372, SEEK_SET ) == 0
         && VSIFWriteL( szIGEOLO, 1, 60, psImage->psFile->fp ) == 60 )
     {
@@ -2033,7 +2077,7 @@ int NITFWriteIGEOLO( NITFImage *psImage, char chICORDS,
 /*                            NITFWriteLUT()                            */
 /************************************************************************/
 
-int NITFWriteLUT( NITFImage *psImage, int nBand, int nColors, 
+int NITFWriteLUT( NITFImage *psImage, int nBand, int nColors,
                   unsigned char *pabyLUT )
 
 {
@@ -2054,16 +2098,16 @@ int NITFWriteLUT( NITFImage *psImage, int nBand, int nColors,
         bSuccess = FALSE;
     }
 
-    VSIFSeekL( psImage->psFile->fp, psBandInfo->nLUTLocation, SEEK_SET );
-    VSIFWriteL( pabyLUT, 1, nColors, psImage->psFile->fp );
-    VSIFSeekL( psImage->psFile->fp, 
-              psBandInfo->nLUTLocation + psBandInfo->nSignificantLUTEntries, 
-              SEEK_SET );
-    VSIFWriteL( pabyLUT+256, 1, nColors, psImage->psFile->fp );
-    VSIFSeekL( psImage->psFile->fp, 
-              psBandInfo->nLUTLocation + 2*psBandInfo->nSignificantLUTEntries, 
-              SEEK_SET );
-    VSIFWriteL( pabyLUT+512, 1, nColors, psImage->psFile->fp );
+    bSuccess &= VSIFSeekL( psImage->psFile->fp, psBandInfo->nLUTLocation, SEEK_SET ) == 0;
+    bSuccess &= (int)VSIFWriteL( pabyLUT, 1, nColors, psImage->psFile->fp ) == nColors;
+    bSuccess &= VSIFSeekL( psImage->psFile->fp,
+              psBandInfo->nLUTLocation + psBandInfo->nSignificantLUTEntries,
+              SEEK_SET ) == 0;
+    bSuccess &= (int)VSIFWriteL( pabyLUT+256, 1, nColors, psImage->psFile->fp ) == nColors;
+    bSuccess &= VSIFSeekL( psImage->psFile->fp,
+              psBandInfo->nLUTLocation + 2*psBandInfo->nSignificantLUTEntries,
+              SEEK_SET ) == 0;
+    bSuccess &= (int)VSIFWriteL( pabyLUT+512, 1, nColors, psImage->psFile->fp ) == nColors;
 
     return bSuccess;
 }
@@ -2082,7 +2126,7 @@ char *NITFTrimWhite( char *pszTarget )
 {
     int i;
 
-    i = strlen(pszTarget)-1;
+    i = (int)strlen(pszTarget)-1;
     while( i >= 0 && pszTarget[i] == ' ' )
         pszTarget[i--] = '\0';
 
@@ -2119,7 +2163,7 @@ static void NITFSwapWordsInternal( void *pData, int nWordSize, int nWordCount,
             pabyData += nWordSkip;
         }
         break;
-        
+
       case 4:
         for( i = 0; i < nWordCount; i++ )
         {
@@ -2186,7 +2230,7 @@ static void NITFSwapWords( NITFImage *psImage, void *pData, int nWordCount )
     {
         NITFSwapWordsInternal( pData,
                                psImage->nWordSize,
-                               nWordCount, 
+                               nWordCount,
                                psImage->nWordSize );
     }
 }
@@ -2241,7 +2285,7 @@ int NITFReadRPC00B( NITFImage *psImage, NITFRPC00BInfo *psRPC )
 /* -------------------------------------------------------------------- */
 /*      Do we have the TRE?                                             */
 /* -------------------------------------------------------------------- */
-    pachTRE = NITFFindTRE( psImage->pachTRE, psImage->nTREBytes, 
+    pachTRE = NITFFindTRE( psImage->pachTRE, psImage->nTREBytes,
                            "RPC00B", &nTRESize );
 
     if( pachTRE == NULL )
@@ -2254,7 +2298,7 @@ int NITFReadRPC00B( NITFImage *psImage, NITFRPC00BInfo *psRPC )
 
     if( pachTRE == NULL )
     {
-        /* No RPC00 tag. Check to see if we have the IMASDA and IMRFCA 
+        /* No RPC00 tag. Check to see if we have the IMASDA and IMRFCA
            tags (DPPDB data) before returning. */
         return NITFReadIMRFCA( psImage, psRPC );
     }
@@ -2270,7 +2314,7 @@ int NITFReadRPC00B( NITFImage *psImage, NITFRPC00BInfo *psRPC )
 /*      Parse out field values.                                         */
 /* -------------------------------------------------------------------- */
     psRPC->SUCCESS = atoi(NITFGetField(szTemp, pachTRE, 0, 1 ));
-	
+
     if ( !psRPC->SUCCESS )
 	fprintf( stdout, "RPC Extension not Populated!\n");
 
@@ -2299,13 +2343,13 @@ int NITFReadRPC00B( NITFImage *psImage, NITFRPC00BInfo *psRPC )
         if( bRPC00A )
             iSrcCoef = anRPC00AMap[i];
 
-        psRPC->LINE_NUM_COEFF[i] = 
+        psRPC->LINE_NUM_COEFF[i] =
             CPLAtof(NITFGetField(szTemp, pachTRE, 81+iSrcCoef*12, 12));
-        psRPC->LINE_DEN_COEFF[i] = 
+        psRPC->LINE_DEN_COEFF[i] =
             CPLAtof(NITFGetField(szTemp, pachTRE, 321+iSrcCoef*12, 12));
-        psRPC->SAMP_NUM_COEFF[i] = 
+        psRPC->SAMP_NUM_COEFF[i] =
             CPLAtof(NITFGetField(szTemp, pachTRE, 561+iSrcCoef*12, 12));
-        psRPC->SAMP_DEN_COEFF[i] = 
+        psRPC->SAMP_DEN_COEFF[i] =
             CPLAtof(NITFGetField(szTemp, pachTRE, 801+iSrcCoef*12, 12));
     }
 
@@ -2328,7 +2372,7 @@ int NITFReadICHIPB( NITFImage *psImage, NITFICHIPBInfo *psICHIP )
 /* -------------------------------------------------------------------- */
 /*      Do we have the TRE?                                             */
 /* -------------------------------------------------------------------- */
-    pachTRE = NITFFindTRE( psImage->pachTRE, psImage->nTREBytes, 
+    pachTRE = NITFFindTRE( psImage->pachTRE, psImage->nTREBytes,
                            "ICHIPB", &nTRESize );
 
     if( pachTRE == NULL )
@@ -2395,7 +2439,7 @@ int NITFReadICHIPB( NITFImage *psImage, NITFICHIPBInfo *psICHIP )
     }
     else
     {
-        fprintf( stdout, "Chip is already de-warpped?\n" );
+        fprintf( stdout, "Chip is already de-warped?\n" );
     }
 
     return TRUE;
@@ -2433,7 +2477,7 @@ char **NITFReadBLOCKA( NITFImage *psImage )
 /* -------------------------------------------------------------------- */
 /*      Do we have the TRE?                                             */
 /* -------------------------------------------------------------------- */
-        pachTRE = NITFFindTREByIndex( psImage->pachTRE, psImage->nTREBytes, 
+        pachTRE = NITFFindTREByIndex( psImage->pachTRE, psImage->nTREBytes,
                                       "BLOCKA", nBlockaCount,
                                       &nTRESize );
 
@@ -2442,7 +2486,7 @@ char **NITFReadBLOCKA( NITFImage *psImage )
 
         if( nTRESize != 123 )
         {
-            CPLError( CE_Warning, CPLE_AppDefined, 
+            CPLError( CE_Warning, CPLE_AppDefined,
                       "BLOCKA TRE wrong size, ignoring." );
             break;
         }
@@ -2452,31 +2496,31 @@ char **NITFReadBLOCKA( NITFImage *psImage )
 /* -------------------------------------------------------------------- */
 /*      Parse out field values.                                         */
 /* -------------------------------------------------------------------- */
-        sprintf( szTemp, "NITF_BLOCKA_BLOCK_INSTANCE_%02d", nBlockaCount );
+        snprintf( szTemp, sizeof(szTemp), "NITF_BLOCKA_BLOCK_INSTANCE_%02d", nBlockaCount );
         NITFExtractMetadata( &papszMD, pachTRE,   0,   2, szTemp );
-        sprintf( szTemp, "NITF_BLOCKA_N_GRAY_%02d", nBlockaCount );
+        snprintf( szTemp, sizeof(szTemp), "NITF_BLOCKA_N_GRAY_%02d", nBlockaCount );
         NITFExtractMetadata( &papszMD, pachTRE,   2,   5, szTemp );
-        sprintf( szTemp, "NITF_BLOCKA_L_LINES_%02d",      nBlockaCount );
+        snprintf( szTemp, sizeof(szTemp), "NITF_BLOCKA_L_LINES_%02d",      nBlockaCount );
         NITFExtractMetadata( &papszMD, pachTRE,   7,   5, szTemp );
-        sprintf( szTemp, "NITF_BLOCKA_LAYOVER_ANGLE_%02d",nBlockaCount );
+        snprintf( szTemp, sizeof(szTemp), "NITF_BLOCKA_LAYOVER_ANGLE_%02d",nBlockaCount );
         NITFExtractMetadata( &papszMD, pachTRE,  12,   3, szTemp );
-        sprintf( szTemp, "NITF_BLOCKA_SHADOW_ANGLE_%02d", nBlockaCount );
+        snprintf( szTemp, sizeof(szTemp), "NITF_BLOCKA_SHADOW_ANGLE_%02d", nBlockaCount );
         NITFExtractMetadata( &papszMD, pachTRE,  15,   3, szTemp );
         /* reserved: 16 */
-        sprintf( szTemp, "NITF_BLOCKA_FRLC_LOC_%02d",     nBlockaCount );
+        snprintf( szTemp, sizeof(szTemp), "NITF_BLOCKA_FRLC_LOC_%02d",     nBlockaCount );
         NITFExtractMetadata( &papszMD, pachTRE,  34,  21, szTemp );
-        sprintf( szTemp, "NITF_BLOCKA_LRLC_LOC_%02d",     nBlockaCount );
+        snprintf( szTemp, sizeof(szTemp), "NITF_BLOCKA_LRLC_LOC_%02d",     nBlockaCount );
         NITFExtractMetadata( &papszMD, pachTRE,  55,  21, szTemp );
-        sprintf( szTemp, "NITF_BLOCKA_LRFC_LOC_%02d",     nBlockaCount );
+        snprintf( szTemp, sizeof(szTemp), "NITF_BLOCKA_LRFC_LOC_%02d",     nBlockaCount );
         NITFExtractMetadata( &papszMD, pachTRE,  76,  21, szTemp );
-        sprintf( szTemp, "NITF_BLOCKA_FRFC_LOC_%02d",     nBlockaCount );
+        snprintf( szTemp, sizeof(szTemp), "NITF_BLOCKA_FRFC_LOC_%02d",     nBlockaCount );
         NITFExtractMetadata( &papszMD, pachTRE,  97,  21, szTemp );
         /* reserved: 5 -> 97 + 21 + 5 = 123 -> OK */
     }
 
     if ( nBlockaCount > 0 )
     {
-        sprintf( szTemp, "%02d", nBlockaCount );
+        snprintf( szTemp, sizeof(szTemp), "%02d", nBlockaCount );
         papszMD = CSLSetNameValue( papszMD, "NITF_BLOCKA_BLOCK_COUNT", szTemp );
     }
 
@@ -2498,9 +2542,9 @@ void NITFGetGCP ( const char* pachCoord, double *pdfXYs, int iCoord )
     // offset to selected coordinate.
     pdfXYs += 2 * iCoord;
 
-    if( pachCoord[0] == 'N' || pachCoord[0] == 'n' || 
+    if( pachCoord[0] == 'N' || pachCoord[0] == 'n' ||
         pachCoord[0] == 'S' || pachCoord[0] == 's' )
-    {	
+    {
         /* ------------------------------------------------------------ */
         /*                             0....+....1....+....2            */
         /* Coordinates are in the form Xddmmss.ssYdddmmss.ss:           */
@@ -2512,16 +2556,16 @@ void NITFGetGCP ( const char* pachCoord, double *pdfXYs, int iCoord )
         /* (00 to 99) of longitude, with Y = E for east or W for west.  */
         /* ------------------------------------------------------------ */
 
-        pdfXYs[1] = 
-            CPLAtof(NITFGetField( szTemp, pachCoord, 1, 2 )) 
+        pdfXYs[1] =
+            CPLAtof(NITFGetField( szTemp, pachCoord, 1, 2 ))
           + CPLAtof(NITFGetField( szTemp, pachCoord, 3, 2 )) / 60.0
           + CPLAtof(NITFGetField( szTemp, pachCoord, 5, 5 )) / 3600.0;
 
         if( pachCoord[0] == 's' || pachCoord[0] == 'S' )
             pdfXYs[1] *= -1;
 
-        pdfXYs[0] = 
-            CPLAtof(NITFGetField( szTemp, pachCoord,11, 3 )) 
+        pdfXYs[0] =
+            CPLAtof(NITFGetField( szTemp, pachCoord,11, 3 ))
           + CPLAtof(NITFGetField( szTemp, pachCoord,14, 2 )) / 60.0
           + CPLAtof(NITFGetField( szTemp, pachCoord,16, 5 )) / 3600.0;
 
@@ -2556,11 +2600,11 @@ int NITFReadBLOCKA_GCPs( NITFImage *psImage )
     int        nTRESize;
     int        nBlockaLines;
     char       szTemp[128];
-    
+
 /* -------------------------------------------------------------------- */
 /*      Do we have the TRE?                                             */
 /* -------------------------------------------------------------------- */
-    pachTRE = NITFFindTRE( psImage->pachTRE, psImage->nTREBytes, 
+    pachTRE = NITFFindTRE( psImage->pachTRE, psImage->nTREBytes,
                            "BLOCKA", &nTRESize );
 
     if( pachTRE == NULL )
@@ -2579,7 +2623,7 @@ int NITFReadBLOCKA_GCPs( NITFImage *psImage )
     /* Make sure the BLOCKA geo coordinates are set. Spaces indicate    */
     /* the value of a coordinate is unavailable or inapplicable.        */
     /* ---------------------------------------------------------------- */
-    if( pachTRE[34] == ' ' || pachTRE[55] == ' ' || 
+    if( pachTRE[34] == ' ' || pachTRE[55] == ' ' ||
         pachTRE[76] == ' ' || pachTRE[97] == ' ' )
     {
         return FALSE;
@@ -2608,15 +2652,15 @@ int NITFReadBLOCKA_GCPs( NITFImage *psImage )
     /* ---------------------------------------------------------------- */
     {
         double *pdfXYs = &(psImage->dfULX);
-    
+
         NITFGetGCP ( pachTRE + 34, pdfXYs, 1 );
         NITFGetGCP ( pachTRE + 55, pdfXYs, 2 );
         NITFGetGCP ( pachTRE + 76, pdfXYs, 3 );
         NITFGetGCP ( pachTRE + 97, pdfXYs, 0 );
-        
+
         psImage->bIsBoxCenterOfPixel = TRUE;
     }
-    
+
     /* ---------------------------------------------------------------- */
     /* Regardless of the former value of ICORDS, the values are now in  */
     /* decimal degrees.                                                 */
@@ -2643,13 +2687,13 @@ static int NITFReadGEOLOB( NITFImage *psImage )
 /* -------------------------------------------------------------------- */
 /*      Do we have the TRE?                                             */
 /* -------------------------------------------------------------------- */
-    pachTRE = NITFFindTRE( psImage->pachTRE, psImage->nTREBytes, 
+    pachTRE = NITFFindTRE( psImage->pachTRE, psImage->nTREBytes,
                            "GEOLOB", &nTRESize );
 
     if( pachTRE == NULL )
         return FALSE;
 
-    if( !CSLTestBoolean(CPLGetConfigOption( "NITF_USEGEOLOB", "YES" )) )
+    if( !CPLTestBoolean(CPLGetConfigOption( "NITF_USEGEOLOB", "YES" )) )
     {
         CPLDebug( "NITF", "GEOLOB available, but ignored by request." );
         return FALSE;
@@ -2668,18 +2712,18 @@ static int NITFReadGEOLOB( NITFImage *psImage )
     {
         double dfARV = atoi(NITFGetField( szTemp, pachTRE, 0, 9 ));
         double dfBRV = atoi(NITFGetField( szTemp, pachTRE, 9, 9 ));
-        
+
         double dfLSO = CPLAtof(NITFGetField( szTemp, pachTRE, 18, 15 ));
         double dfPSO = CPLAtof(NITFGetField( szTemp, pachTRE, 33, 15 ));
-        
+
         double dfPixelWidth  = 360.0 / dfARV;
         double dfPixelHeight = 360.0 / dfBRV;
-        
+
         psImage->dfULX = dfLSO;
         psImage->dfURX = psImage->dfULX + psImage->nCols * dfPixelWidth;
         psImage->dfLLX = psImage->dfULX;
         psImage->dfLRX = psImage->dfURX;
-        
+
         psImage->dfULY = dfPSO;
         psImage->dfURY = psImage->dfULY;
         psImage->dfLLY = psImage->dfULY - psImage->nRows * dfPixelHeight;
@@ -2687,7 +2731,7 @@ static int NITFReadGEOLOB( NITFImage *psImage )
 
         psImage->bIsBoxCenterOfPixel = FALSE; // GEOLOB is edge of pixel.
         psImage->chICORDS = 'G';
-        
+
         CPLDebug( "NITF", "IGEOLO bounds overridden by GEOLOB TRE." );
     }
 
@@ -2701,7 +2745,7 @@ static int NITFReadGEOLOB( NITFImage *psImage )
 /*      id and the number of bytes to fetch.                            */
 /************************************************************************/
 
-static int NITFFetchAttribute( GByte *pabyAttributeSubsection, 
+static int NITFFetchAttribute( GByte *pabyAttributeSubsection,
                                GUInt32 nASSSize, int nAttrCount,
                                int nAttrID, int nParamID, GUInt32 nBytesToFetch,
                                GByte *pabyBuffer )
@@ -2776,8 +2820,9 @@ static void NITFLoadAttributeSection( NITFImage *psImage )
 /* -------------------------------------------------------------------- */
 /*      How many attribute records do we have?                          */
 /* -------------------------------------------------------------------- */
-    VSIFSeekL( psImage->psFile->fp, nASHOffset, SEEK_SET );
-    VSIFReadL( &nAttrCount, 2, 1, psImage->psFile->fp );
+    if( VSIFSeekL( psImage->psFile->fp, nASHOffset, SEEK_SET ) != 0 ||
+        VSIFReadL( &nAttrCount, 2, 1, psImage->psFile->fp ) != 1 )
+        return;
 
     CPL_MSBPTR16( &nAttrCount );
 
@@ -2804,7 +2849,7 @@ static void NITFLoadAttributeSection( NITFImage *psImage )
     {
         if( psImage->pasLocations[i].nLocOffset > nASSOffset )
         {
-            if( nNextOffset == 0 
+            if( nNextOffset == 0
                 || nNextOffset > psImage->pasLocations[i].nLocOffset )
                 nNextOffset = psImage->pasLocations[i].nLocOffset;
         }
@@ -2815,7 +2860,7 @@ static void NITFLoadAttributeSection( NITFImage *psImage )
 
 /* -------------------------------------------------------------------- */
 /*      Be sure that the attribute subsection is large enough to        */
-/*      hold the offset table (otherwise NITFFetchAttribute coud        */
+/*      hold the offset table (otherwise NITFFetchAttribute could       */
 /*      read out of the buffer)                                         */
 /* -------------------------------------------------------------------- */
     if (nASSSize < (size_t)(8 * nAttrCount))
@@ -2833,28 +2878,33 @@ static void NITFLoadAttributeSection( NITFImage *psImage )
     if( pabyAttributeSubsection == NULL )
     {
         CPLError( CE_Warning, CPLE_AppDefined,
-                  "Out of memory failure reading %d bytes of attribute subsection. ",
+                  "Out of memory failure reading %d bytes of attribute subsection.",
                   nASSSize );
         return;
     }
-    
-    VSIFSeekL( psImage->psFile->fp, nASSOffset, SEEK_SET );
-    VSIFReadL( pabyAttributeSubsection, nASSSize, 1, psImage->psFile->fp );
+
+    if( VSIFSeekL( psImage->psFile->fp, nASSOffset, SEEK_SET ) != 0 ||
+        VSIFReadL( pabyAttributeSubsection, 1, nASSSize, psImage->psFile->fp ) != nASSSize )
+    {
+        CPLError( CE_Warning, CPLE_FileIO, "I/O error when reading attribute subsection." );
+        CPLFree(pabyAttributeSubsection);
+        return;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Scan for some particular attributes we would like.              */
 /* -------------------------------------------------------------------- */
     if( NITFFetchAttribute( pabyAttributeSubsection, nASSSize, nAttrCount,
                             1, 1, 8, abyBuffer ) )
-        NITFExtractMetadata( &(psImage->papszMetadata), (char*)abyBuffer, 0, 8, 
+        NITFExtractMetadata( &(psImage->papszMetadata), (char*)abyBuffer, 0, 8,
                              "NITF_RPF_CurrencyDate" );
     if( NITFFetchAttribute( pabyAttributeSubsection, nASSSize, nAttrCount,
                             2, 1, 8, abyBuffer ) )
-        NITFExtractMetadata( &(psImage->papszMetadata), (char*)abyBuffer, 0, 8, 
+        NITFExtractMetadata( &(psImage->papszMetadata), (char*)abyBuffer, 0, 8,
                              "NITF_RPF_ProductionDate" );
     if( NITFFetchAttribute( pabyAttributeSubsection, nASSSize, nAttrCount,
                             3, 1, 8, abyBuffer ) )
-        NITFExtractMetadata( &(psImage->papszMetadata), (char*)abyBuffer, 0, 8, 
+        NITFExtractMetadata( &(psImage->papszMetadata), (char*)abyBuffer, 0, 8,
                              "NITF_RPF_SignificantDate" );
 
     CPLFree( pabyAttributeSubsection );
@@ -2874,8 +2924,8 @@ static void NITFLoadAttributeSection( NITFImage *psImage )
  * its documentation for any purpose and without fee is hereby granted,
  * provided that the above copyright notice appear in all copies, that
  * both the copyright notice and this permission notice appear in
- * supporting documentation, and that the name of L.A.S. Inc not be used 
- * in advertising or publicity pertaining to distribution of the software 
+ * supporting documentation, and that the name of L.A.S. Inc not be used
+ * in advertising or publicity pertaining to distribution of the software
  * without specific, written prior permission. L.A.S. Inc. makes no
  * representations about the suitability of this software for any purpose.
  * It is provided "as is" without express or implied warranty.
@@ -2895,6 +2945,7 @@ static void NITFLoadColormapSubSection( NITFImage *psImage )
     NITFColormapRecord* colormapRecords;
     unsigned int colormapOffsetTableOffset;
     unsigned short offsetRecLen;
+    int bOK = TRUE;
 
     NITFBandInfo *psBandInfo = psImage->pasBandInfo;
 
@@ -2921,68 +2972,66 @@ static void NITFLoadColormapSubSection( NITFImage *psImage )
     }
 
     if( VSIFSeekL( psFile->fp, nLocBaseColorGrayscaleSection,
-                  SEEK_SET ) != 0 )
+                  SEEK_SET ) != 0 ||
+        VSIFReadL( &nOffsetRecs, 1, 1, psFile->fp ) != 1 )
     {
         CPLError( CE_Failure, CPLE_FileIO,
                   "Failed to seek to %d.",
                   nLocBaseColorGrayscaleSection );
         return;
     }
-    
-    
-    VSIFReadL( &nOffsetRecs, 1, 1, psFile->fp );
-    
-    if( VSIFSeekL( psFile->fp, nLocBaseColormapSubSection, 
+
+    if( VSIFSeekL( psFile->fp, nLocBaseColormapSubSection,
                   SEEK_SET ) != 0  )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   "Failed to seek to %d.",
                   nLocBaseColormapSubSection );
         return;
     }
-    
+
     colormapRecords = (NITFColormapRecord*)CPLMalloc(nOffsetRecs * sizeof(NITFColormapRecord));
 
      /* colormap offset table offset length */
-    VSIFReadL( &colormapOffsetTableOffset, 1, sizeof(colormapOffsetTableOffset),  psFile->fp );
+    bOK &= VSIFReadL( &colormapOffsetTableOffset, sizeof(colormapOffsetTableOffset), 1,  psFile->fp ) == 1;
     CPL_MSBPTR32( &colormapOffsetTableOffset );
 
      /* offset record length */
-    VSIFReadL( &offsetRecLen, 1, sizeof(offsetRecLen),  psFile->fp );
+    bOK &= VSIFReadL( &offsetRecLen, sizeof(offsetRecLen), 1,  psFile->fp ) == 1;
     CPL_MSBPTR16( &offsetRecLen );
-    
-    for (i = 0; i < nOffsetRecs; i++)
+
+    for (i = 0; bOK && i < nOffsetRecs; i++)
     {
-        VSIFReadL( &colormapRecords[i].tableId, 1, sizeof(colormapRecords[i].tableId),  psFile->fp );
+        bOK &= VSIFReadL( &colormapRecords[i].tableId, sizeof(colormapRecords[i].tableId), 1,  psFile->fp ) == 1;
         CPL_MSBPTR16( &colormapRecords[i].tableId );
-        
-        VSIFReadL( &colormapRecords[i].nRecords, 1, sizeof(colormapRecords[i].nRecords),  psFile->fp );
+
+        bOK &= VSIFReadL( &colormapRecords[i].nRecords, sizeof(colormapRecords[i].nRecords), 1,  psFile->fp ) == 1;
         CPL_MSBPTR32( &colormapRecords[i].nRecords );
-        
-        VSIFReadL( &colormapRecords[i].elementLength, 1, sizeof(colormapRecords[i].elementLength),  psFile->fp );
-    
-        VSIFReadL( &colormapRecords[i].histogramRecordLength, 1, sizeof(colormapRecords[i].histogramRecordLength),  psFile->fp );
+
+        bOK &= VSIFReadL( &colormapRecords[i].elementLength,sizeof(colormapRecords[i].elementLength), 1,  psFile->fp ) == 1;
+
+        bOK &= VSIFReadL( &colormapRecords[i].histogramRecordLength,sizeof(colormapRecords[i].histogramRecordLength), 1,  psFile->fp ) == 1;
         CPL_MSBPTR16( &colormapRecords[i].histogramRecordLength );
-    
-        VSIFReadL( &colormapRecords[i].colorTableOffset, 1, sizeof(colormapRecords[i].colorTableOffset),  psFile->fp );
+
+        bOK &= VSIFReadL( &colormapRecords[i].colorTableOffset, sizeof(colormapRecords[i].colorTableOffset), 1,  psFile->fp ) == 1;
         CPL_MSBPTR32( &colormapRecords[i].colorTableOffset );
-    
-        VSIFReadL( &colormapRecords[i].histogramTableOffset, 1, sizeof(colormapRecords[i].histogramTableOffset),  psFile->fp );
+
+        bOK &= VSIFReadL( &colormapRecords[i].histogramTableOffset, sizeof(colormapRecords[i].histogramTableOffset), 1,  psFile->fp ) == 1;
         CPL_MSBPTR32( &colormapRecords[i].histogramTableOffset );
     }
-    
-    for (i=0; i<nOffsetRecs; i++)
+
+    for (i=0; bOK && i<nOffsetRecs; i++)
     {
-        if( VSIFSeekL( psFile->fp, nLocBaseColormapSubSection + colormapRecords[i].colorTableOffset, 
+        if( VSIFSeekL( psFile->fp, nLocBaseColormapSubSection + colormapRecords[i].colorTableOffset,
                     SEEK_SET ) != 0  )
         {
-            CPLError( CE_Failure, CPLE_FileIO, 
+            CPLError( CE_Failure, CPLE_FileIO,
                     "Failed to seek to %d.",
                     nLocBaseColormapSubSection + colormapRecords[i].colorTableOffset );
             CPLFree(colormapRecords);
             return;
         }
-        
+
         /* This test is very CADRG specific. See MIL-C-89038, paragraph 3.12.5.a */
         if (i == 0 &&
             colormapRecords[i].tableId == 2 &&
@@ -2990,10 +3039,10 @@ static void NITFLoadColormapSubSection( NITFImage *psImage )
             colormapRecords[i].nRecords == 216)   /* read, use colortable */
         {
             GByte* rgbm = (GByte*)CPLMalloc(colormapRecords[i].nRecords * 4);
-            if (VSIFReadL(rgbm, 1, colormapRecords[i].nRecords * 4, 
+            if (VSIFReadL(rgbm, 1, colormapRecords[i].nRecords * 4,
                      psFile->fp ) != colormapRecords[i].nRecords * 4 )
             {
-                CPLError( CE_Failure, CPLE_FileIO, 
+                CPLError( CE_Failure, CPLE_FileIO,
                           "Failed to read %d byte rgbm.",
                            colormapRecords[i].nRecords * 4);
                 CPLFree(rgbm);
@@ -3008,7 +3057,7 @@ static void NITFLoadColormapSubSection( NITFImage *psImage )
             }
             CPLFree(rgbm);
         }
-    } 
+    }
 
     CPLFree(colormapRecords);
 }
@@ -3027,6 +3076,7 @@ static void NITFLoadSubframeMaskTable( NITFImage *psImage )
     GUIntBig  nLocBaseSpatialDataSubsection = psSegInfo->nSegmentStart;
     GUInt32  nLocBaseMaskSubsection = 0;
     GUInt16 subframeSequenceRecordLength, transparencySequenceRecordLength, transparencyOutputPixelCodeLength;
+    int bOK = TRUE;
 
     for( i = 0; i < psImage->nLocCount; i++ )
     {
@@ -3044,25 +3094,25 @@ static void NITFLoadSubframeMaskTable( NITFImage *psImage )
         //fprintf(stderr, "nLocBase(LID_MaskSubsection) == 0\n");
         return;
     }
-    
+
     //fprintf(stderr, "nLocBaseMaskSubsection = %d\n", nLocBaseMaskSubsection);
-    if( VSIFSeekL( psFile->fp, nLocBaseMaskSubsection, 
+    if( VSIFSeekL( psFile->fp, nLocBaseMaskSubsection,
                     SEEK_SET ) != 0  )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                 "Failed to seek to %d.",
                 nLocBaseMaskSubsection );
         return;
     }
-    
-    VSIFReadL( &subframeSequenceRecordLength, 1, sizeof(subframeSequenceRecordLength),  psFile->fp );
+
+    bOK &= VSIFReadL( &subframeSequenceRecordLength, sizeof(subframeSequenceRecordLength), 1,  psFile->fp ) == 1;
     CPL_MSBPTR16( &subframeSequenceRecordLength );
-    
-    VSIFReadL( &transparencySequenceRecordLength, 1, sizeof(transparencySequenceRecordLength),  psFile->fp );
+
+    bOK &= VSIFReadL( &transparencySequenceRecordLength, sizeof(transparencySequenceRecordLength), 1,  psFile->fp ) == 1;
     CPL_MSBPTR16( &transparencySequenceRecordLength );
-    
+
     /* in bits */
-    VSIFReadL( &transparencyOutputPixelCodeLength, 1, sizeof(transparencyOutputPixelCodeLength),  psFile->fp );
+    bOK &= VSIFReadL( &transparencyOutputPixelCodeLength, sizeof(transparencyOutputPixelCodeLength), 1,  psFile->fp ) == 1;
     CPL_MSBPTR16( &transparencyOutputPixelCodeLength );
 
     //fprintf(stderr, "transparencyOutputPixelCodeLength=%d\n", transparencyOutputPixelCodeLength);
@@ -3071,17 +3121,19 @@ static void NITFLoadSubframeMaskTable( NITFImage *psImage )
     {
       GByte byNodata;
 
-      psImage->bNoDataSet = TRUE;
-      VSIFReadL( &byNodata, 1, 1, psFile->fp );
-      psImage->nNoDataValue = byNodata;
+      if( bOK && VSIFReadL( &byNodata, 1, 1, psFile->fp ) == 1 )
+      {
+        psImage->bNoDataSet = TRUE;
+        psImage->nNoDataValue = byNodata;
+      }
     }
     else
     {
-      VSIFSeekL( psFile->fp, (transparencyOutputPixelCodeLength+7)/8, SEEK_CUR );
+      bOK &= VSIFSeekL( psFile->fp, (transparencyOutputPixelCodeLength+7)/8, SEEK_CUR ) == 0;
     }
 
     /* Fix for rpf/cjnc/cjncz01/0001f023.jn1 */
-    if (subframeSequenceRecordLength != 4)
+    if (!bOK || subframeSequenceRecordLength != 4)
     {
       //fprintf(stderr, "subframeSequenceRecordLength=%d\n", subframeSequenceRecordLength);
       return;
@@ -3090,10 +3142,10 @@ static void NITFLoadSubframeMaskTable( NITFImage *psImage )
     for( i=0; i < psImage->nBlocksPerRow * psImage->nBlocksPerColumn; i++ )
     {
         unsigned int offset;
-        VSIFReadL( &offset, 1, sizeof(offset),  psFile->fp );
+        bOK &= VSIFReadL( &offset, sizeof(offset), 1,  psFile->fp ) == 1;
         CPL_MSBPTR32( &offset );
         //fprintf(stderr, "%d : %d\n", i, offset);
-        if (offset == 0xffffffff)
+        if (!bOK || offset == 0xffffffff)
             psImage->panBlockStart[i] = 0xffffffff;
         else
             psImage->panBlockStart[i] = nLocBaseSpatialDataSubsection + offset;
@@ -3173,20 +3225,18 @@ NITFLocation* NITFReadRPFLocationTable(VSILFILE* fp, int* pnLocCount)
 
     /* nLocComponentAggregateLength = */ NITFReadMSBGUInt32(fp, &bSuccess);
 
-    VSIFSeekL(fp, nCurOffset + nLocSectionOffset, SEEK_SET);
+    bSuccess = VSIFSeekL(fp, nCurOffset + nLocSectionOffset, SEEK_SET) == 0;
 
-    pasLocations = (NITFLocation *)  VSICalloc(sizeof(NITFLocation), nLocCount);
+    pasLocations = (NITFLocation *)  VSI_CALLOC_VERBOSE(sizeof(NITFLocation), nLocCount);
     if (pasLocations == NULL)
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory,
-                 "Cannot allocate memory for location table");
         return NULL;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Process the locations.                                          */
 /* -------------------------------------------------------------------- */
-    for( iLoc = 0; iLoc < nLocCount; iLoc++ )
+    for( iLoc = 0; bSuccess && iLoc < nLocCount; iLoc++ )
     {
         pasLocations[iLoc].nLocId = NITFReadMSBGUInt16(fp, &bSuccess);
         pasLocations[iLoc].nLocSize = NITFReadMSBGUInt32(fp, &bSuccess);
@@ -3224,10 +3274,10 @@ static void NITFLoadLocationTable( NITFImage *psImage )
     if( pszTRE == NULL )
         return;
 
-    sprintf(szTempFileName, "/vsimem/%p", pszTRE);
+    snprintf(szTempFileName, sizeof(szTempFileName), "/vsimem/%p", pszTRE);
     fpTemp = VSIFileFromMemBuffer( szTempFileName, (GByte*) pszTRE, nTRESize, FALSE);
     psImage->pasLocations = NITFReadRPFLocationTable(fpTemp, &psImage->nLocCount);
-    VSIFCloseL(fpTemp);
+    CPL_IGNORE_RET_VAL_INT(VSIFCloseL(fpTemp));
     VSIUnlink(szTempFileName);
 
     if (psImage->nLocCount == 0)
@@ -3255,20 +3305,27 @@ static void NITFLoadLocationTable( NITFImage *psImage )
     {
         char achHeaderChunk[1000];
 
-        VSIFSeekL( psImage->psFile->fp, nHeaderOffset - 11, SEEK_SET );
-        VSIFReadL( achHeaderChunk, 1, sizeof(achHeaderChunk), 
-                   psImage->psFile->fp );
+        if( VSIFSeekL( psImage->psFile->fp, nHeaderOffset - 11, SEEK_SET ) != 0 ||
+            VSIFReadL( achHeaderChunk, sizeof(achHeaderChunk), 1,
+                   psImage->psFile->fp ) != 1 )
+        {
+            CPLFree( psImage->pasLocations );
+            psImage->pasLocations = NULL;
+            psImage->nLocCount = 0;
+            return;
+        }
 
         /* You can define NITF_DISABLE_RPF_LOCATION_TABLE_SANITY_TESTS to TRUE */
         /* to blindly trust the RPF location table even if it doesn't look */
         /* sane. Necessary for dataset attached to http://trac.osgeo.org/gdal/ticket/3930 */
-        if( !EQUALN(achHeaderChunk,"RPFHDR",6) &&
-            !CSLTestBoolean(CPLGetConfigOption("NITF_DISABLE_RPF_LOCATION_TABLE_SANITY_TESTS", "FALSE")) )
+        if( !STARTS_WITH_CI(achHeaderChunk, "RPFHDR") &&
+            !CPLTestBoolean(CPLGetConfigOption(
+                "NITF_DISABLE_RPF_LOCATION_TABLE_SANITY_TESTS", "FALSE")) )
         {
             /* Image of http://trac.osgeo.org/gdal/ticket/3848 has incorrect */
             /* RPFHDR offset, but all other locations are correct... */
             /* So if we find LID_CoverageSectionSubheader and LID_CompressionLookupSubsection */
-            /* we check weither their content is valid */
+            /* we check whether their content is valid. */
             int bFoundValidLocation = FALSE;
             for( i = 0; i < psImage->nLocCount; i++ )
             {
@@ -3279,12 +3336,18 @@ static void NITFLoadLocationTable( NITFImage *psImage )
                     /* We test that they are close enough from the values of the IGEOLO record */
                     double adfTarget[8];
 
-                    VSIFSeekL( psImage->psFile->fp, psImage->pasLocations[i].nLocOffset,
-                               SEEK_SET );
-                    VSIFReadL( adfTarget, 8, 8, psImage->psFile->fp );
+                    if( VSIFSeekL( psImage->psFile->fp, psImage->pasLocations[i].nLocOffset,
+                               SEEK_SET ) != 0 ||
+                        VSIFReadL( adfTarget, 8, 8, psImage->psFile->fp ) != 8 )
+                    {
+                        CPLFree( psImage->pasLocations );
+                        psImage->pasLocations = NULL;
+                        psImage->nLocCount = 0;
+                        return;
+                    }
                     for( i = 0; i < 8; i++ )
                         CPL_MSBPTR64( (adfTarget + i) );
-                        
+
                     if ( fabs(psImage->dfULX - adfTarget[1]) < 0.1 &&
                          fabs(psImage->dfULY - adfTarget[0]) < 0.1 &&
                          fabs(psImage->dfLLX - adfTarget[3]) < 0.1 &&
@@ -3376,8 +3439,11 @@ static int NITFLoadVQTables( NITFImage *psImage, int bTryGuessingOffset )
     abySignature[4] = 0x00;
     abySignature[5] = 0x0E;
 
-    VSIFSeekL( psImage->psFile->fp, nVQOffset, SEEK_SET );
-    VSIFReadL( abyTestChunk, 1, sizeof(abyTestChunk), psImage->psFile->fp );
+    if( VSIFSeekL( psImage->psFile->fp, nVQOffset, SEEK_SET ) != 0 ||
+        VSIFReadL( abyTestChunk, sizeof(abyTestChunk), 1, psImage->psFile->fp ) != 1 )
+    {
+        return FALSE;
+    }
 
     if( memcmp(abyTestChunk,abySignature,sizeof(abySignature)) != 0 )
     {
@@ -3400,22 +3466,25 @@ static int NITFLoadVQTables( NITFImage *psImage, int bTryGuessingOffset )
         if (!bFoundSignature)
             return FALSE;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Load the tables.                                                */
 /* -------------------------------------------------------------------- */
     for( i = 0; i < 4; i++ )
     {
         GUInt32 nVQVector;
+        int bOK;
 
         psImage->apanVQLUT[i] = (GUInt32 *) CPLCalloc(4096,sizeof(GUInt32));
 
-        VSIFSeekL( psImage->psFile->fp, nVQOffset + 6 + i*14 + 10, SEEK_SET );
-        VSIFReadL( &nVQVector, 1, 4, psImage->psFile->fp );
+        bOK = VSIFSeekL( psImage->psFile->fp, nVQOffset + 6 + i*14 + 10, SEEK_SET ) == 0;
+        bOK &= VSIFReadL( &nVQVector, 1, 4, psImage->psFile->fp ) == 4;
         nVQVector = CPL_MSBWORD32( nVQVector );
-        
-        VSIFSeekL( psImage->psFile->fp, nVQOffset + nVQVector, SEEK_SET );
-        VSIFReadL( psImage->apanVQLUT[i], 4, 4096, psImage->psFile->fp );
+
+        bOK &= VSIFSeekL( psImage->psFile->fp, nVQOffset + nVQVector, SEEK_SET ) == 0;
+        bOK &= VSIFReadL( psImage->apanVQLUT[i], 4, 4096, psImage->psFile->fp ) == 4096;
+        if( !bOK )
+            return FALSE;
     }
 
     return TRUE;
@@ -3437,12 +3506,12 @@ char **NITFReadSTDIDC( NITFImage *psImage )
 /*                         NITFRPCGeoToImage()                          */
 /************************************************************************/
 
-int NITFRPCGeoToImage( NITFRPC00BInfo *psRPC, 
-                       double dfLong, double dfLat, double dfHeight, 
+int NITFRPCGeoToImage( NITFRPC00BInfo *psRPC,
+                       double dfLong, double dfLat, double dfHeight,
                        double *pdfPixel, double *pdfLine )
 
 {
-    double dfLineNumerator, dfLineDenominator, 
+    double dfLineNumerator, dfLineDenominator,
         dfPixelNumerator, dfPixelDenominator;
     double dfPolyTerm[20];
     int i;
@@ -3479,7 +3548,6 @@ int NITFRPCGeoToImage( NITFRPC00BInfo *psRPC,
     dfPolyTerm[17] = dfLong * dfLong * dfHeight;
     dfPolyTerm[18] = dfLat * dfLat * dfHeight;
     dfPolyTerm[19] = dfHeight * dfHeight * dfHeight;
-    
 
 /* -------------------------------------------------------------------- */
 /*      Compute numerator and denominator sums.                         */
@@ -3496,7 +3564,7 @@ int NITFRPCGeoToImage( NITFRPC00BInfo *psRPC,
         dfLineNumerator += psRPC->LINE_NUM_COEFF[i] * dfPolyTerm[i];
         dfLineDenominator += psRPC->LINE_DEN_COEFF[i] * dfPolyTerm[i];
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Compute normalized pixel and line values.                       */
 /* -------------------------------------------------------------------- */
@@ -3529,7 +3597,7 @@ GUIntBig NITFIHFieldOffset( NITFImage *psImage, const char *pszFieldName )
         psImage->psFile->pasSegmentInfo[psImage->iSegment].nSegmentHeaderStart;
 
     // We only support files we created.
-    if( !EQUALN(psImage->psFile->szVersion,"NITF02.1",8) )
+    if( !STARTS_WITH_CI(psImage->psFile->szVersion, "NITF02.1") )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "NITFIHFieldOffset() only works with NITF 2.1 images");
@@ -3567,10 +3635,10 @@ GUIntBig NITFIHFieldOffset( NITFImage *psImage, const char *pszFieldName )
 /* -------------------------------------------------------------------- */
     nNICOM = atoi(NITFGetField(szTemp,psImage->pachHeader,
                                (int)(nWrkOffset - nIMOffset),1));
-        
+
     if( EQUAL(pszFieldName,"NICOM") )
         return nWrkOffset;
-    
+
     nWrkOffset++;
 
     if( EQUAL(pszFieldName,"ICOM") )
@@ -3629,20 +3697,20 @@ GUIntBig NITFIHFieldOffset( NITFImage *psImage, const char *pszFieldName )
 /*                        NITFDoLinesIntersect()                        */
 /************************************************************************/
 
-static int NITFDoLinesIntersect( double dfL1X1, double dfL1Y1, 
+static int NITFDoLinesIntersect( double dfL1X1, double dfL1Y1,
                                  double dfL1X2, double dfL1Y2,
-                                 double dfL2X1, double dfL2Y1, 
+                                 double dfL2X1, double dfL2Y1,
                                  double dfL2X2, double dfL2Y2 )
 
 {
     double dfL1M, dfL1B, dfL2M, dfL2B;
-    
+
     if( dfL1X1 == dfL1X2 )
     {
         dfL1M = 1e10;
         dfL1B = 0.0;
     }
-    else 
+    else
     {
         dfL1M = (dfL1Y2 - dfL1Y1 ) / (dfL1X2 - dfL1X1);
         dfL1B = dfL1Y2 - dfL1M * dfL1X2;
@@ -3704,7 +3772,7 @@ static void NITFPossibleIGEOLOReorientation( NITFImage *psImage )
     else
         CPLDebug( "NITF", "It appears the IGEOLO corner coordinates were written improperly!" );
 #endif
-    
+
 /* -------------------------------------------------------------------- */
 /*      Divide the lat/long extents of this image into four             */
 /*      quadrants and assign the corners based on which point falls     */
@@ -3714,7 +3782,7 @@ static void NITFPossibleIGEOLOReorientation( NITFImage *psImage )
 /*      90 degrees from simple north up.                                */
 /* -------------------------------------------------------------------- */
     {
-        
+
         double dfXMax = MAX(MAX(psImage->dfULX,psImage->dfURX),
                             MAX(psImage->dfLRX,psImage->dfLLX));
         double dfXMin = MIN(MIN(psImage->dfULX,psImage->dfURX),
@@ -3726,15 +3794,15 @@ static void NITFPossibleIGEOLOReorientation( NITFImage *psImage )
         double dfXPivot = (dfXMax + dfXMin) * 0.5;
         double dfYPivot = (dfYMax + dfYMin) * 0.5;
 
-        double dfNewULX = 0., dfNewULY = 0., dfNewURX = 0., dfNewURY = 0., 
+        double dfNewULX = 0., dfNewULY = 0., dfNewURX = 0., dfNewURY = 0.,
             dfNewLLX = 0., dfNewLLY = 0., dfNewLRX = 0., dfNewLRY = 0.;
-        int bGotUL = FALSE, bGotUR = FALSE, 
+        int bGotUL = FALSE, bGotUR = FALSE,
             bGotLL = FALSE, bGotLR = FALSE;
         int iCoord, bChange = FALSE;
-    
+
         for( iCoord = 0; iCoord < 4; iCoord++ )
         {
-            double *pdfXY = &(psImage->dfULX) + iCoord*2; 
+            double *pdfXY = &(psImage->dfULX) + iCoord*2;
 
             if( pdfXY[0] < dfXPivot && pdfXY[1] < dfYPivot )
             {
@@ -3768,7 +3836,7 @@ static void NITFPossibleIGEOLOReorientation( NITFImage *psImage )
 
         if( !bGotUL || !bGotUR || !bGotLL || !bGotLR )
         {
-            CPLDebug( "NITF", 
+            CPLDebug( "NITF",
                       "Unable to reorient corner points sensibly in NITFPossibleIGEOLOReorganization(), discarding IGEOLO locations." );
             psImage->bHaveIGEOLO = FALSE;
             return;
@@ -3785,8 +3853,8 @@ static void NITFPossibleIGEOLOReorientation( NITFImage *psImage )
         psImage->dfLRY = dfNewLRY;
         psImage->dfLLX = dfNewLLX;
         psImage->dfLLY = dfNewLLY;
-    
-        CPLDebug( "NITF", 
+
+        CPLDebug( "NITF",
                   "IGEOLO corners have been reoriented by NITFPossibleIGEOLOReorientation()." );
     }
 }
@@ -3830,7 +3898,7 @@ int NITFReadIMRFCA( NITFImage *psImage, NITFRPC00BInfo *psRPC )
 
     psRPC->ERR_BIAS = 0.0;
     psRPC->ERR_RAND = 0.0;
-    
+
     psRPC->LONG_OFF     = CPLAtof( NITFGetField(szTemp, pachTreIMASDA, 0,   22) );
     psRPC->LAT_OFF      = CPLAtof( NITFGetField(szTemp, pachTreIMASDA, 22,  22) );
     psRPC->HEIGHT_OFF   = CPLAtof( NITFGetField(szTemp, pachTreIMASDA, 44,  22) );
diff --git a/frmts/nitf/nitflib.h b/frmts/nitf/nitflib.h
index d30c56e..7464868 100644
--- a/frmts/nitf/nitflib.h
+++ b/frmts/nitf/nitflib.h
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: nitflib.h 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: nitflib.h 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  NITF Read/Write Library
- * Purpose:  Main GDAL independent include file for NITF support.  
+ * Purpose:  Main GDAL independent include file for NITF support.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  **********************************************************************
@@ -38,7 +38,7 @@
 
 CPL_C_START
 
-typedef struct { 
+typedef struct {
     char szSegmentType[3]; /* one of "IM", ... */
 
     GUIntBig nSegmentHeaderStart;
@@ -73,7 +73,7 @@ typedef struct {
     char    **papszMetadata;
 
     CPLXMLNode *psNITFSpecNode;
-    
+
 } NITFFile;
 
 /* -------------------------------------------------------------------- */
@@ -83,12 +83,12 @@ NITFFile CPL_DLL *NITFOpen( const char *pszFilename, int bUpdatable );
 NITFFile *NITFOpenEx( VSILFILE *fp, const char *pszFilename );
 void     CPL_DLL  NITFClose( NITFFile * );
 
-int      CPL_DLL  NITFCreate( const char *pszFilename, 
-                              int nPixels, int nLines, int nBands, 
+int      CPL_DLL  NITFCreate( const char *pszFilename,
+                              int nPixels, int nLines, int nBands,
                               int nBitsPerSample, const char *pszPVType,
                               char **papszOptions );
 
-const char CPL_DLL *NITFFindTRE( const char *pszTREData, int nTREBytes, 
+const char CPL_DLL *NITFFindTRE( const char *pszTREData, int nTREBytes,
                                  const char *pszTag, int *pnFoundTRESize );
 const char CPL_DLL *NITFFindTREByIndex( const char *pszTREData, int nTREBytes,
                                 const char *pszTag, int nTreIndex,
@@ -110,7 +110,7 @@ typedef struct {
 
 } NITFBandInfo;
 
-typedef struct { 
+typedef struct {
     GUInt16 nLocId;
     GUInt32 nLocOffset;
     GUInt32 nLocSize;
@@ -138,7 +138,7 @@ typedef struct {
     int        nBitsPerSample;
 
     NITFBandInfo *pasBandInfo;
-    
+
     char       chIMODE;
 
     int        nBlocksPerRow;
@@ -149,7 +149,7 @@ typedef struct {
     char       szPVType[4];
     char       szIREP[9];
     char       szICAT[9];
-    int        nABPP; /* signficant bits per pixel */
+    int        nABPP; /* significant bits per pixel */
 
     char       chICORDS;
     int        bHaveIGEOLO;
@@ -174,7 +174,7 @@ typedef struct {
     int        nIALVL;
     int        nIDLVL;
     char       szIMAG[5];
-    
+
     int        bNoDataSet;
     int        nNoDataValue;
 
@@ -182,7 +182,7 @@ typedef struct {
     char    *pachTRE;
 
     /* Internal information not for application use. */
-    
+
     int        nWordSize;
     GUIntBig   nPixelOffset;
     GUIntBig   nLineOffset;
@@ -192,7 +192,7 @@ typedef struct {
     GUIntBig    *panBlockStart;
 
     char       **papszMetadata;
-    
+
     GUInt32 *apanVQLUT[4];
 
     int     nLocCount;
@@ -205,13 +205,13 @@ void      CPL_DLL  NITFImageDeaccess( NITFImage * );
 
 int       CPL_DLL  NITFReadImageBlock( NITFImage *, int nBlockX, int nBlockY,
                                        int nBand, void *pData );
-int       CPL_DLL  NITFReadImageLine( NITFImage *, int nLine, int nBand, 
+int       CPL_DLL  NITFReadImageLine( NITFImage *, int nLine, int nBand,
                                       void *pData );
 int       CPL_DLL  NITFWriteImageBlock( NITFImage *, int nBlockX, int nBlockY,
                                         int nBand, void *pData );
-int       CPL_DLL  NITFWriteImageLine( NITFImage *, int nLine, int nBand, 
+int       CPL_DLL  NITFWriteImageLine( NITFImage *, int nLine, int nBand,
                                        void *pData );
-int       CPL_DLL  NITFWriteLUT( NITFImage *psImage, int nBand, int nColors, 
+int       CPL_DLL  NITFWriteLUT( NITFImage *psImage, int nBand, int nColors,
                                  unsigned char *pabyLUT );
 int       CPL_DLL  NITFWriteIGEOLO( NITFImage *psImage, char chICORDS,
                                     int nZone,
@@ -225,7 +225,7 @@ char      CPL_DLL **NITFReadUSE00A( NITFImage *psImage );
 char      CPL_DLL **NITFReadSTDIDC( NITFImage *psImage );
 char      CPL_DLL **NITFReadBLOCKA( NITFImage *psImage );
 
-GUIntBig  CPL_DLL NITFIHFieldOffset( NITFImage *psImage, 
+GUIntBig  CPL_DLL NITFIHFieldOffset( NITFImage *psImage,
                                      const char *pszFieldName );
 
 #define BLKREAD_OK    0
@@ -235,7 +235,7 @@ GUIntBig  CPL_DLL NITFIHFieldOffset( NITFImage *psImage,
 int NITFUncompressARIDPCM( NITFImage *psImage,
                            GByte *pabyInputData, int nInputBytes,
                            GByte *pabyOutputImage );
-int NITFUncompressBILEVEL( NITFImage *psImage, 
+int NITFUncompressBILEVEL( NITFImage *psImage,
                            GByte *pabyInputData, int nInputBytes,
                            GByte *pabyOutputImage );
 
@@ -268,7 +268,7 @@ int       CPL_DLL  NITFDESExtractShapefile(NITFDES* psDES, const char* pszRadixF
 /*      These are really intended to be private helper stuff for the    */
 /*      library.                                                        */
 /* -------------------------------------------------------------------- */
-char *NITFGetField( char *pszTarget, const char *pszSource, 
+char *NITFGetField( char *pszTarget, const char *pszSource,
                     int nStart, int nLength );
 void NITFExtractMetadata( char ***ppapszMetadata, const char *pachHeader,
                           int nStart, int nLength, const char *pszName );
@@ -376,7 +376,7 @@ typedef struct {
 
 int CPL_DLL NITFReadICHIPB( NITFImage *psImage, NITFICHIPBInfo * );
 
-double CPL_DLL 
+double CPL_DLL
         NITF_WGS84_Geocentric_Latitude_To_Geodetic_Latitude( double dfLat );
 
 
@@ -411,4 +411,3 @@ CPLXMLNode* NITFCreateXMLTre(NITFFile* psFile,
 CPL_C_END
 
 #endif /* ndef NITFLIB_H_INCLUDED */
-
diff --git a/frmts/nitf/nitfrasterband.cpp b/frmts/nitf/nitfrasterband.cpp
index 63fa7c4..c487a17 100644
--- a/frmts/nitf/nitfrasterband.cpp
+++ b/frmts/nitf/nitfrasterband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nitfrasterband.cpp 28899 2015-04-14 09:27:00Z rouault $
+ * $Id: nitfrasterband.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  NITF Read/Write Translator
  * Purpose:  NITFRasterBand (and related proxy band) implementations.
@@ -35,7 +35,7 @@
 #include "cpl_string.h"
 #include "cpl_csv.h"
 
-CPL_CVSID("$Id: nitfrasterband.cpp 28899 2015-04-14 09:27:00Z rouault $");
+CPL_CVSID("$Id: nitfrasterband.cpp 33808 2016-03-29 21:15:28Z goatbar $");
 
 /************************************************************************/
 /*                       NITFMakeColorTable()                           */
@@ -47,14 +47,11 @@ static GDALColorTable* NITFMakeColorTable(NITFImage* psImage, NITFBandInfo *psBa
 
     if( psBandInfo->nSignificantLUTEntries > 0 )
     {
-        int  iColor;
-
         poColorTable = new GDALColorTable();
 
-        for( iColor = 0; iColor < psBandInfo->nSignificantLUTEntries; iColor++)
+        for( int iColor = 0; iColor < psBandInfo->nSignificantLUTEntries; iColor++)
         {
             GDALColorEntry sEntry;
-
             sEntry.c1 = psBandInfo->pabyLUT[  0 + iColor];
             sEntry.c2 = psBandInfo->pabyLUT[256 + iColor];
             sEntry.c3 = psBandInfo->pabyLUT[512 + iColor];
@@ -76,10 +73,9 @@ static GDALColorTable* NITFMakeColorTable(NITFImage* psImage, NITFBandInfo *psBa
 /* -------------------------------------------------------------------- */
     if( poColorTable == NULL && psImage->nBitsPerSample == 1 )
     {
-        GDALColorEntry sEntry;
-
         poColorTable = new GDALColorTable();
 
+        GDALColorEntry sEntry;
         sEntry.c1 = 0;
         sEntry.c2 = 0;
         sEntry.c3 = 0;
@@ -92,7 +88,7 @@ static GDALColorTable* NITFMakeColorTable(NITFImage* psImage, NITFBandInfo *psBa
         sEntry.c4 = 255;
         poColorTable->SetColorEntry( 1, &sEntry );
     }
-    
+
     return poColorTable;
 }
 
@@ -113,41 +109,6 @@ NITFProxyPamRasterBand::~NITFProxyPamRasterBand()
 }
 
 
-#define RB_PROXY_METHOD_WITH_RET(retType, retErrValue, methodName, argList, argParams) \
-retType NITFProxyPamRasterBand::methodName argList \
-{ \
-    retType ret; \
-    GDALRasterBand* _poSrcBand = RefUnderlyingRasterBand(); \
-    if (_poSrcBand) \
-    { \
-        ret = _poSrcBand->methodName argParams; \
-        UnrefUnderlyingRasterBand(_poSrcBand); \
-    } \
-    else \
-    { \
-        ret = retErrValue; \
-    } \
-    return ret; \
-}
-
-
-#define RB_PROXY_METHOD_WITH_RET_AND_CALL_OTHER_METHOD(retType, retErrValue, methodName, underlyingMethodName, argList, argParams) \
-retType NITFProxyPamRasterBand::methodName argList \
-{ \
-    retType ret; \
-    GDALRasterBand* _poSrcBand = RefUnderlyingRasterBand(); \
-    if (_poSrcBand) \
-    { \
-        ret = _poSrcBand->underlyingMethodName argParams; \
-        UnrefUnderlyingRasterBand(_poSrcBand); \
-    } \
-    else \
-    { \
-        ret = retErrValue; \
-    } \
-    return ret; \
-}
-
 char      **NITFProxyPamRasterBand::GetMetadata( const char * pszDomain  )
 {
     GDALRasterBand* _poSrcBand = RefUnderlyingRasterBand();
@@ -195,8 +156,6 @@ CPLErr NITFProxyPamRasterBand::GetStatistics( int bApproxOK, int bForce,
                                       double *pdfMin, double *pdfMax,
                                       double *pdfMean, double *pdfStdDev )
 {
-    CPLErr ret;
-
 /* -------------------------------------------------------------------- */
 /*      Do we already have metadata items for the requested values?     */
 /* -------------------------------------------------------------------- */
@@ -213,8 +172,9 @@ CPLErr NITFProxyPamRasterBand::GetStatistics( int bApproxOK, int bForce,
     GDALRasterBand* _poSrcBand = RefUnderlyingRasterBand();
     if (_poSrcBand)
     {
-        ret = _poSrcBand->GetStatistics( bApproxOK, bForce,
-                                         pdfMin, pdfMax, pdfMean, pdfStdDev);
+        CPLErr ret = _poSrcBand->GetStatistics( bApproxOK, bForce,
+                                                pdfMin, pdfMax, pdfMean,
+                                                pdfStdDev);
         if (ret == CE_None)
         {
             /* Report underlying statistics at PAM level */
@@ -228,12 +188,10 @@ CPLErr NITFProxyPamRasterBand::GetStatistics( int bApproxOK, int bForce,
                             _poSrcBand->GetMetadataItem("STATISTICS_STDDEV"));
         }
         UnrefUnderlyingRasterBand(_poSrcBand);
+        return ret;
     }
-    else
-    {
-        ret = CE_Failure;
-    }
-    return ret;
+
+    return CE_Failure;
 }
 
 CPLErr NITFProxyPamRasterBand::ComputeStatistics( int bApproxOK,
@@ -241,13 +199,12 @@ CPLErr NITFProxyPamRasterBand::ComputeStatistics( int bApproxOK,
                                         double *pdfMean, double *pdfStdDev,
                                         GDALProgressFunc pfn, void *pProgressData )
 {
-    CPLErr ret;
     GDALRasterBand* _poSrcBand = RefUnderlyingRasterBand();
     if (_poSrcBand)
     {
-        ret = _poSrcBand->ComputeStatistics( bApproxOK, pdfMin, pdfMax,
-                                             pdfMean, pdfStdDev,
-                                             pfn, pProgressData);
+        CPLErr ret = _poSrcBand->ComputeStatistics( bApproxOK, pdfMin, pdfMax,
+                                                    pdfMean, pdfStdDev,
+                                                    pfn, pProgressData);
         if (ret == CE_None)
         {
             /* Report underlying statistics at PAM level */
@@ -261,12 +218,10 @@ CPLErr NITFProxyPamRasterBand::ComputeStatistics( int bApproxOK,
                             _poSrcBand->GetMetadataItem("STATISTICS_STDDEV"));
         }
         UnrefUnderlyingRasterBand(_poSrcBand);
+        return ret;
     }
-    else
-    {
-        ret = CE_Failure;
-    }
-    return ret;
+
+    return CE_Failure;
 }
 
 
@@ -298,6 +253,23 @@ RB_PROXY_METHOD_GET_DBL_WITH_SUCCESS(GetNoDataValue)
 RB_PROXY_METHOD_GET_DBL_WITH_SUCCESS(GetMinimum)
 RB_PROXY_METHOD_GET_DBL_WITH_SUCCESS(GetMaximum)
 
+#define RB_PROXY_METHOD_WITH_RET_AND_CALL_OTHER_METHOD(retType, retErrValue, methodName, underlyingMethodName, argList, argParams) \
+retType NITFProxyPamRasterBand::methodName argList \
+{ \
+    retType ret; \
+    GDALRasterBand* _poSrcBand = RefUnderlyingRasterBand(); \
+    if (_poSrcBand) \
+    { \
+        ret = _poSrcBand->underlyingMethodName argParams; \
+        UnrefUnderlyingRasterBand(_poSrcBand); \
+    } \
+    else \
+    { \
+        ret = retErrValue; \
+    } \
+    return ret; \
+}
+
 RB_PROXY_METHOD_WITH_RET_AND_CALL_OTHER_METHOD(CPLErr, CE_Failure, IReadBlock, ReadBlock,
                                 ( int nXBlockOff, int nYBlockOff, void* pImage),
                                 (nXBlockOff, nYBlockOff, pImage) )
@@ -315,6 +287,23 @@ RB_PROXY_METHOD_WITH_RET_AND_CALL_OTHER_METHOD(CPLErr, CE_Failure, IRasterIO, Ra
                                 pData, nBufXSize, nBufYSize, eBufType,
                                 nPixelSpace, nLineSpace, psExtraArg ) )
 
+#define RB_PROXY_METHOD_WITH_RET(retType, retErrValue, methodName, argList, argParams) \
+retType NITFProxyPamRasterBand::methodName argList \
+{ \
+    retType ret; \
+    GDALRasterBand* _poSrcBand = RefUnderlyingRasterBand(); \
+    if (_poSrcBand) \
+    { \
+        ret = _poSrcBand->methodName argParams; \
+        UnrefUnderlyingRasterBand(_poSrcBand); \
+    } \
+    else \
+    { \
+        ret = retErrValue; \
+    } \
+    return ret; \
+}
+
 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, FlushCache, (), ())
 
 RB_PROXY_METHOD_WITH_RET(GDALColorInterp, GCI_Undefined, GetColorInterpretation, (), ())
@@ -345,17 +334,14 @@ RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, AdviseRead,
 
 RB_PROXY_METHOD_WITH_RET(GDALRasterBand*, NULL, GetMaskBand, (), ())
 RB_PROXY_METHOD_WITH_RET(int, 0, GetMaskFlags, (), ())
-RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, CreateMaskBand, ( int nFlags ), (nFlags))
+RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, CreateMaskBand, ( int nFlagsIn ), (nFlagsIn))
 
 
 /************************************************************************/
 /*                 UnrefUnderlyingRasterBand()                        */
 /************************************************************************/
 
-void NITFProxyPamRasterBand::UnrefUnderlyingRasterBand(CPL_UNUSED GDALRasterBand* poUnderlyingRasterBand)
-{
-}
-
+void NITFProxyPamRasterBand::UnrefUnderlyingRasterBand(CPL_UNUSED GDALRasterBand* poUnderlyingRasterBand) {}
 
 /************************************************************************/
 /* ==================================================================== */
@@ -367,38 +353,38 @@ void NITFProxyPamRasterBand::UnrefUnderlyingRasterBand(CPL_UNUSED GDALRasterBand
 /*                           NITFRasterBand()                           */
 /************************************************************************/
 
-NITFRasterBand::NITFRasterBand( NITFDataset *poDS, int nBand )
+NITFRasterBand::NITFRasterBand( NITFDataset *poDSIn, int nBandIn )
 
 {
-    NITFBandInfo *psBandInfo = poDS->psImage->pasBandInfo + nBand - 1;
+    NITFBandInfo *psBandInfo = poDSIn->psImage->pasBandInfo + nBandIn - 1;
 
-    this->poDS = poDS;
-    this->nBand = nBand;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
 
-    this->eAccess = poDS->eAccess;
-    this->psImage = poDS->psImage;
+    eAccess = poDSIn->eAccess;
+    psImage = poDSIn->psImage;
 
 /* -------------------------------------------------------------------- */
 /*      Translate data type(s).                                         */
 /* -------------------------------------------------------------------- */
     if( psImage->nBitsPerSample <= 8 )
         eDataType = GDT_Byte;
-    else if( psImage->nBitsPerSample == 16 
+    else if( psImage->nBitsPerSample == 16
              && EQUAL(psImage->szPVType,"SI") )
         eDataType = GDT_Int16;
     else if( psImage->nBitsPerSample == 16 )
         eDataType = GDT_UInt16;
     else if( psImage->nBitsPerSample == 12 )
         eDataType = GDT_UInt16;
-    else if( psImage->nBitsPerSample == 32 
+    else if( psImage->nBitsPerSample == 32
              && EQUAL(psImage->szPVType,"SI") )
         eDataType = GDT_Int32;
-    else if( psImage->nBitsPerSample == 32 
+    else if( psImage->nBitsPerSample == 32
              && EQUAL(psImage->szPVType,"R") )
         eDataType = GDT_Float32;
     else if( psImage->nBitsPerSample == 32 )
         eDataType = GDT_UInt32;
-    else if( psImage->nBitsPerSample == 64 
+    else if( psImage->nBitsPerSample == 64
              && EQUAL(psImage->szPVType,"R") )
         eDataType = GDT_Float64;
     else if( psImage->nBitsPerSample == 64
@@ -407,7 +393,7 @@ NITFRasterBand::NITFRasterBand( NITFDataset *poDS, int nBand )
     /* ERO : note I'm not sure if CFloat64 can be transmitted as NBPP is only 2 characters */
     else
     {
-        int bOpenUnderlyingDS = CSLTestBoolean(
+        int bOpenUnderlyingDS = CPLTestBool(
                 CPLGetConfigOption("NITF_OPEN_UNDERLYING_DS", "YES"));
         if (!bOpenUnderlyingDS && psImage->nBitsPerSample > 8 && psImage->nBitsPerSample < 16)
         {
@@ -429,7 +415,7 @@ NITFRasterBand::NITFRasterBand( NITFDataset *poDS, int nBand )
 /*      Work out block size. If the image is all one big block we       */
 /*      handle via the scanline access API.                             */
 /* -------------------------------------------------------------------- */
-    if( psImage->nBlocksPerRow == 1 
+    if( psImage->nBlocksPerRow == 1
         && psImage->nBlocksPerColumn == 1
         && psImage->nBitsPerSample >= 8
         && EQUAL(psImage->szIC,"NC") )
@@ -451,7 +437,7 @@ NITFRasterBand::NITFRasterBand( NITFDataset *poDS, int nBand )
     poColorTable = NITFMakeColorTable(psImage,
                                       psBandInfo);
 
-    if( psImage->nBitsPerSample == 1 
+    if( psImage->nBitsPerSample == 1
     ||  psImage->nBitsPerSample == 3
     ||  psImage->nBitsPerSample == 5
     ||  psImage->nBitsPerSample == 6
@@ -459,12 +445,23 @@ NITFRasterBand::NITFRasterBand( NITFDataset *poDS, int nBand )
     ||  psImage->nBitsPerSample == 12 )
         SetMetadataItem( "NBITS", CPLString().Printf("%d", psImage->nBitsPerSample), "IMAGE_STRUCTURE" );
 
-    pUnpackData = 0;
+    pUnpackData = NULL;
     if (psImage->nBitsPerSample == 3
     ||  psImage->nBitsPerSample == 5
     ||  psImage->nBitsPerSample == 6
     ||  psImage->nBitsPerSample == 7)
-      pUnpackData = new GByte[((nBlockXSize*nBlockYSize+7)/8)*8];
+    {
+        if( nBlockXSize > (INT_MAX - 7) / nBlockYSize )
+        {
+            eDataType = GDT_Unknown;
+        }
+        else
+        {
+            pUnpackData = static_cast<GByte*>(VSI_MALLOC_VERBOSE(((nBlockXSize*nBlockYSize+7)/8)*8));
+            if( pUnpackData == NULL )
+                eDataType = GDT_Unknown;
+        }
+    }
 }
 
 /************************************************************************/
@@ -477,7 +474,7 @@ NITFRasterBand::~NITFRasterBand()
     if( poColorTable != NULL )
         delete poColorTable;
 
-    delete[] pUnpackData;
+    VSIFree(pUnpackData);
 }
 
 /************************************************************************/
@@ -488,8 +485,7 @@ CPLErr NITFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                    void * pImage )
 
 {
-    int  nBlockResult;
-    NITFDataset *poGDS = (NITFDataset *) poDS;
+    NITFDataset *poGDS = reinterpret_cast<NITFDataset *>( poDS );
 
 /* -------------------------------------------------------------------- */
 /*      Special case for JPEG blocks.                                   */
@@ -497,14 +493,15 @@ CPLErr NITFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     if( EQUAL(psImage->szIC,"C3") || EQUAL(psImage->szIC,"M3") )
     {
         CPLErr eErr = poGDS->ReadJPEGBlock( nBlockXOff, nBlockYOff );
-        int nBlockBandSize = psImage->nBlockWidth*psImage->nBlockHeight*
-                             (GDALGetDataTypeSize(eDataType)/8);
+        const int nBlockBandSize =
+            psImage->nBlockWidth * psImage->nBlockHeight *
+            GDALGetDataTypeSizeBytes(eDataType);
 
         if( eErr != CE_None )
             return eErr;
 
-        memcpy( pImage, 
-                poGDS->pabyJPEGBlock + (nBand - 1) * nBlockBandSize, 
+        memcpy( pImage,
+                poGDS->pabyJPEGBlock + (nBand - 1) * nBlockBandSize,
                 nBlockBandSize );
 
         return eErr;
@@ -513,21 +510,23 @@ CPLErr NITFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
 /*      Read the line/block                                             */
 /* -------------------------------------------------------------------- */
+    int nBlockResult;
+
     if( bScanlineAccess )
     {
-        nBlockResult = 
+        nBlockResult =
             NITFReadImageLine(psImage, nBlockYOff, nBand, pImage);
     }
     else
     {
-        nBlockResult = 
+        nBlockResult =
             NITFReadImageBlock(psImage, nBlockXOff, nBlockYOff, nBand, pImage);
     }
 
     if( nBlockResult == BLKREAD_OK )
     {
         if( psImage->nBitsPerSample % 8 )
-            Unpack((GByte*)pImage);
+            Unpack( reinterpret_cast<GByte *>( pImage ) );
 
         return CE_None;
     }
@@ -541,10 +540,10 @@ CPLErr NITFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /*      8bit.                                                           */
 /* -------------------------------------------------------------------- */
     if( psImage->bNoDataSet )
-        memset( pImage, psImage->nNoDataValue, 
+        memset( pImage, psImage->nNoDataValue,
                 psImage->nWordSize*psImage->nBlockWidth*psImage->nBlockHeight);
     else
-        memset( pImage, 0, 
+        memset( pImage, 0,
                 psImage->nWordSize*psImage->nBlockWidth*psImage->nBlockHeight);
 
     return CE_None;
@@ -556,28 +555,28 @@ CPLErr NITFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
 CPLErr NITFRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                                     void * pImage )
-    
-{
-    int  nBlockResult;
 
+{
 /* -------------------------------------------------------------------- */
 /*      Write the line/block                                            */
 /* -------------------------------------------------------------------- */
+    int  nBlockResult;
+
     if( bScanlineAccess )
     {
-        nBlockResult = 
+        nBlockResult =
             NITFWriteImageLine(psImage, nBlockYOff, nBand, pImage);
     }
     else
     {
-        nBlockResult = 
+        nBlockResult =
             NITFWriteImageBlock(psImage, nBlockXOff, nBlockYOff, nBand,pImage);
     }
 
     if( nBlockResult == BLKREAD_OK )
         return CE_None;
-    else
-        return CE_Failure;
+
+    return CE_Failure;
 }
 
 /************************************************************************/
@@ -592,8 +591,8 @@ double NITFRasterBand::GetNoDataValue( int *pbSuccess )
 
     if( psImage->bNoDataSet )
         return psImage->nNoDataValue;
-    else
-        return GDALPamRasterBand::GetNoDataValue( pbSuccess );
+
+    return GDALPamRasterBand::GetNoDataValue( pbSuccess );
 }
 
 /************************************************************************/
@@ -607,7 +606,7 @@ GDALColorInterp NITFRasterBand::GetColorInterpretation()
 
     if( poColorTable != NULL )
         return GCI_PaletteIndex;
-    
+
     if( EQUAL(psBandInfo->szIREPBAND,"R") )
         return GCI_RedBand;
     if( EQUAL(psBandInfo->szIREPBAND,"G") )
@@ -630,14 +629,12 @@ GDALColorInterp NITFRasterBand::GetColorInterpretation()
 /*                     NITFSetColorInterpretation()                     */
 /************************************************************************/
 
-CPLErr NITFSetColorInterpretation( NITFImage *psImage, 
+CPLErr NITFSetColorInterpretation( NITFImage *psImage,
                                    int nBand,
                                    GDALColorInterp eInterp )
-    
+
 {
-    NITFBandInfo *psBandInfo = psImage->pasBandInfo + nBand - 1;
     const char *pszREP = NULL;
-    GUIntBig nOffset;
 
     if( eInterp == GCI_RedBand )
         pszREP = "R";
@@ -658,7 +655,7 @@ CPLErr NITFSetColorInterpretation( NITFImage *psImage,
 
     if( pszREP == NULL )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "Requested color interpretation (%s) not supported in NITF.",
                   GDALGetColorInterpretationName( eInterp ) );
         return CE_Failure;
@@ -667,30 +664,32 @@ CPLErr NITFSetColorInterpretation( NITFImage *psImage,
 /* -------------------------------------------------------------------- */
 /*      Where does this go in the file?                                 */
 /* -------------------------------------------------------------------- */
+    NITFBandInfo *psBandInfo = psImage->pasBandInfo + nBand - 1;
     strcpy( psBandInfo->szIREPBAND, pszREP );
-    nOffset = NITFIHFieldOffset( psImage, "IREPBAND" );
+    GUIntBig nOffset = NITFIHFieldOffset( psImage, "IREPBAND" );
 
     if( nOffset != 0 )
         nOffset += (nBand - 1) * 13;
-    
+
 /* -------------------------------------------------------------------- */
 /*      write it (space padded).                                        */
 /* -------------------------------------------------------------------- */
     char szPadded[4];
     strcpy( szPadded, pszREP );
     strcat( szPadded, " " );
-    
+
     if( nOffset != 0 )
     {
-        if( VSIFSeekL( psImage->psFile->fp, nOffset, SEEK_SET ) != 0 
-            || VSIFWriteL( (void *) szPadded, 1, 2, psImage->psFile->fp ) != 2 )
+        if( VSIFSeekL( psImage->psFile->fp, nOffset, SEEK_SET ) != 0
+            || VSIFWriteL( reinterpret_cast<void *>( szPadded ), 1, 2,
+                           psImage->psFile->fp ) != 2 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "IO failure writing new IREPBAND value to NITF file." );
             return CE_Failure;
         }
     }
-    
+
     return CE_None;
 }
 
@@ -721,19 +720,18 @@ GDALColorTable *NITFRasterBand::GetColorTable()
 CPLErr NITFRasterBand::SetColorTable( GDALColorTable *poNewCT )
 
 {
-    NITFDataset *poGDS = (NITFDataset *) poDS;
+    NITFDataset *poGDS = reinterpret_cast<NITFDataset *>( poDS );
     if( poGDS->bInLoadXML )
         return GDALPamRasterBand::SetColorTable(poNewCT);
-        
+
     if( poNewCT == NULL )
         return CE_Failure;
 
     GByte abyNITFLUT[768];
-    int   i;
-    int   nCount = MIN(256,poNewCT->GetColorEntryCount());
-
     memset( abyNITFLUT, 0, 768 );
-    for( i = 0; i < nCount; i++ )
+
+    const int nCount = MIN(256,poNewCT->GetColorEntryCount());
+    for( int i = 0; i < nCount; i++ )
     {
         GDALColorEntry sEntry;
 
@@ -745,8 +743,8 @@ CPLErr NITFRasterBand::SetColorTable( GDALColorTable *poNewCT )
 
     if( NITFWriteLUT( psImage, nBand, nCount, abyNITFLUT ) )
         return CE_None;
-    else
-        return CE_Failure;
+
+    return CE_Failure;
 }
 
 /************************************************************************/
@@ -755,9 +753,7 @@ CPLErr NITFRasterBand::SetColorTable( GDALColorTable *poNewCT )
 
 void NITFRasterBand::Unpack( GByte* pData )
 {
-  long n = nBlockXSize*nBlockYSize;
-  long i;
-  long k;
+  const int n = nBlockXSize*nBlockYSize;
 
   GByte abyTempData[7] = {0, 0, 0, 0, 0, 0, 0};
   const GByte* pDataSrc = pData;
@@ -773,33 +769,36 @@ void NITFRasterBand::Unpack( GByte* pData )
     case 1:
     {
       // unpack 1-bit in-place in reverse
-      for (i = n; --i >= 0; )
+      // DANGER: Non-standard decrement of counter in the test section of for.
+      for( int i = n; --i >= 0; )
         pData[i] = (pData[i>>3] & (0x80 >> (i&7))) != 0;
-       
+
       break;
     }
     case 2:
     {
       static const int s_Shift2[] = {6, 4, 2, 0};
       // unpack 2-bit in-place in reverse
-      for (i = n; --i >= 0; )
+      // DANGER: Non-standard decrement of counter in the test section of for.
+      for (int i = n; --i >= 0; )
         pData[i] = (pData[i>>2] >> (GByte)s_Shift2[i&3]) & 0x03;
-       
+
       break;
     }
     case 4:
     {
       static const int s_Shift4[] = {4, 0};
       // unpack 4-bit in-place in reverse
-      for (i = n; --i >= 0; )
+      // DANGER: Non-standard decrement of counter in the test section of for.
+      for( int i = n; --i >= 0; )
         pData[i] = (pData[i>>1] >> (GByte)s_Shift4[i&1]) & 0x0f;
-       
+
       break;
     }
     case 3:
     {
       // unpacks 8 pixels (3 bytes) at time
-      for (i = 0, k = 0; i < n; i += 8, k += 3)
+      for( int i = 0, k = 0; i < n; i += 8, k += 3 )
       {
         pUnpackData[i+0] = ((pDataSrc[k+0] >> 5));
         pUnpackData[i+1] = ((pDataSrc[k+0] >> 2) & 0x07);
@@ -817,7 +816,7 @@ void NITFRasterBand::Unpack( GByte* pData )
     case 5:
     {
       // unpacks 8 pixels (5 bytes) at time
-      for (i = 0, k = 0; i < n; i += 8, k += 5)
+      for( int i = 0, k = 0; i < n; i += 8, k += 5 )
       {
         pUnpackData[i+0] = ((pDataSrc[k+0] >> 3));
         pUnpackData[i+1] = ((pDataSrc[k+0] << 2) & 0x1f) | (pDataSrc[k+1] >> 6);
@@ -835,7 +834,7 @@ void NITFRasterBand::Unpack( GByte* pData )
     case 6:
     {
       // unpacks 4 pixels (3 bytes) at time
-      for (i = 0, k = 0; i < n; i += 4, k += 3)
+      for( int i = 0, k = 0; i < n; i += 4, k += 3 )
       {
         pUnpackData[i+0] = ((pDataSrc[k+0] >> 2));
         pUnpackData[i+1] = ((pDataSrc[k+0] << 4) & 0x3f) | (pDataSrc[k+1] >> 4);
@@ -849,7 +848,7 @@ void NITFRasterBand::Unpack( GByte* pData )
     case 7:
     {
       // unpacks 8 pixels (7 bytes) at time
-      for (i = 0, k = 0; i < n; i += 8, k += 7)
+      for( int i = 0, k = 0; i < n; i += 8, k += 7 )
       {
         pUnpackData[i+0] = ((pDataSrc[k+0] >> 1));
         pUnpackData[i+1] = ((pDataSrc[k+0] << 6) & 0x7f) | (pDataSrc[k+1] >> 2);
@@ -866,11 +865,12 @@ void NITFRasterBand::Unpack( GByte* pData )
     }
     case 12:
     {
-      GByte*   pabyImage = (GByte  *)pData;
-      GUInt16* panImage  = (GUInt16*)pData;
-      for (i = n; --i >= 0; )
+      GByte *pabyImage = reinterpret_cast<GByte *>( pData );
+      GUInt16 *panImage  = reinterpret_cast<GUInt16 *>( pData );
+      // DANGER: Non-standard decrement of counter in the test section of for.
+      for( int i = n; --i >= 0; )
       {
-        long iOffset = i*3 / 2;
+        const long iOffset = i*3 / 2;
         if (i % 2 == 0)
           panImage[i] = pabyImage[iOffset] + (pabyImage[iOffset+1] & 0xf0) * 16;
         else
@@ -894,16 +894,16 @@ void NITFRasterBand::Unpack( GByte* pData )
 /*                      NITFWrapperRasterBand()                         */
 /************************************************************************/
 
-NITFWrapperRasterBand::NITFWrapperRasterBand( NITFDataset * poDS,
-                                              GDALRasterBand* poBaseBand,
-                                              int nBand)
+NITFWrapperRasterBand::NITFWrapperRasterBand( NITFDataset * poDSIn,
+                                              GDALRasterBand* poBaseBandIn,
+                                              int nBandIn) :
+    poColorTable(NULL)
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
-    this->poBaseBand = poBaseBand;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
+    this->poBaseBand = poBaseBandIn;
     eDataType = poBaseBand->GetRasterDataType();
     poBaseBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
-    poColorTable = NULL;
     eInterp = poBaseBand->GetColorInterpretation();
     bIsJPEG = poBaseBand->GetDataset() != NULL &&
               poBaseBand->GetDataset()->GetDriver() != NULL &&
@@ -945,7 +945,7 @@ GDALColorTable *NITFWrapperRasterBand::GetColorTable()
 
 void NITFWrapperRasterBand::SetColorTableFromNITFBandInfo()
 {
-    NITFDataset* poGDS = (NITFDataset* )poDS;
+    NITFDataset* poGDS = reinterpret_cast<NITFDataset *>( poDS );
     poColorTable = NITFMakeColorTable(poGDS->psImage,
                                       poGDS->psImage->pasBandInfo + nBand - 1);
 }
@@ -963,9 +963,9 @@ GDALColorInterp NITFWrapperRasterBand::GetColorInterpretation()
 /*                        SetColorInterpretation()                      */
 /************************************************************************/
 
-CPLErr NITFWrapperRasterBand::SetColorInterpretation( GDALColorInterp eInterp)
+CPLErr NITFWrapperRasterBand::SetColorInterpretation( GDALColorInterp eInterpIn)
 {
-    this->eInterp = eInterp;
+    this->eInterp = eInterpIn;
     if( poBaseBand->GetDataset() != NULL &&
         poBaseBand->GetDataset()->GetDriver() != NULL &&
         EQUAL(poBaseBand->GetDataset()->GetDriver()->GetDescription(), "JP2ECW") )
@@ -981,13 +981,13 @@ int NITFWrapperRasterBand::GetOverviewCount()
 {
     if( bIsJPEG )
     {
-        if( ((NITFDataset*)poDS)->ExposeUnderlyingJPEGDatasetOverviews() )
+        if( (reinterpret_cast<NITFDataset *>( poDS) )->ExposeUnderlyingJPEGDatasetOverviews() )
             return NITFProxyPamRasterBand::GetOverviewCount();
-        else
-            return GDALPamRasterBand::GetOverviewCount();
+
+        return GDALPamRasterBand::GetOverviewCount();
     }
-    else
-        return NITFProxyPamRasterBand::GetOverviewCount();
+
+    return NITFProxyPamRasterBand::GetOverviewCount();
 }
 
 /************************************************************************/
@@ -998,11 +998,11 @@ GDALRasterBand * NITFWrapperRasterBand::GetOverview(int iOverview)
 {
     if( bIsJPEG )
     {
-        if( ((NITFDataset*)poDS)->ExposeUnderlyingJPEGDatasetOverviews() )
+        if( (reinterpret_cast<NITFDataset *>( poDS ) )->ExposeUnderlyingJPEGDatasetOverviews() )
             return NITFProxyPamRasterBand::GetOverview(iOverview);
-        else
-            return GDALPamRasterBand::GetOverview(iOverview);
+
+        return GDALPamRasterBand::GetOverview(iOverview);
     }
-    else
-        return NITFProxyPamRasterBand::GetOverview(iOverview);
+
+    return NITFProxyPamRasterBand::GetOverview(iOverview);
 }
diff --git a/frmts/nitf/nitfwritejpeg.cpp b/frmts/nitf/nitfwritejpeg.cpp
index a7a5035..07532dd 100644
--- a/frmts/nitf/nitfwritejpeg.cpp
+++ b/frmts/nitf/nitfwritejpeg.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nitfwritejpeg.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: nitfwritejpeg.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  NITF Read/Write Translator
  * Purpose:  GDALDataset/GDALRasterBand implementation on top of "nitflib".
@@ -37,17 +37,17 @@
 #include "gdal_pam.h"
 
 CPL_C_START
-#ifdef LIBJPEG_12_PATH 
+#ifdef LIBJPEG_12_PATH
 #  include LIBJPEG_12_PATH
 #else
 #  include "jpeglib.h"
 #endif
 CPL_C_END
 
-/*  
-* Do we want to do special processing suitable for when JSAMPLE is a 
-* 16bit value?   
-*/ 
+/*
+* Do we want to do special processing suitable for when JSAMPLE is a
+* 16bit value?
+*/
 #if defined(JPEG_LIB_MK1)
 #  define JPEG_LIB_MK1_OR_12BIT 1
 #elif BITS_IN_JSAMPLE == 12
@@ -55,7 +55,7 @@ CPL_C_END
 #endif
 
 #if defined(JPEG_DUAL_MODE_8_12) && !defined(NITFWriteJPEGBlock)
-int 
+int
 NITFWriteJPEGBlock_12( GDALDataset *poSrcDS, VSILFILE *fp,
                      int nBlockXOff, int nBlockYOff,
                      int nBlockXSize, int nBlockYSize,
@@ -64,14 +64,21 @@ NITFWriteJPEGBlock_12( GDALDataset *poSrcDS, VSILFILE *fp,
                      GDALProgressFunc pfnProgress, void * pProgressData );
 #endif
 
-void jpeg_vsiio_src (j_decompress_ptr cinfo, VSILFILE * infile);
+int
+NITFWriteJPEGBlock( GDALDataset *poSrcDS, VSILFILE *fp,
+                    int nBlockXOff, int nBlockYOff,
+                    int nBlockXSize, int nBlockYSize,
+                    int bProgressive, int nQuality,
+                    const GByte* pabyAPP6, int nRestartInterval,
+                    GDALProgressFunc pfnProgress, void * pProgressData );
+
 void jpeg_vsiio_dest (j_compress_ptr cinfo, VSILFILE * outfile);
 
 /************************************************************************/
 /*                         NITFWriteJPEGBlock()                         */
 /************************************************************************/
 
-int 
+int
 NITFWriteJPEGBlock( GDALDataset *poSrcDS, VSILFILE *fp,
                     int nBlockXOff, int nBlockYOff,
                     int nBlockXSize, int nBlockYSize,
@@ -92,9 +99,6 @@ NITFWriteJPEGBlock( GDALDataset *poSrcDS, VSILFILE *fp,
     }
 #endif
 
-    int  nBands = poSrcDS->GetRasterCount();
-    int  nXSize = poSrcDS->GetRasterXSize();
-    int  nYSize = poSrcDS->GetRasterYSize();
     int  anBandList[3] = {1,2,3};
 
 /* -------------------------------------------------------------------- */
@@ -102,14 +106,17 @@ NITFWriteJPEGBlock( GDALDataset *poSrcDS, VSILFILE *fp,
 /* -------------------------------------------------------------------- */
     struct jpeg_compress_struct sCInfo;
     struct jpeg_error_mgr sJErr;
-    
+
+    memset(&sCInfo, 0, sizeof(sCInfo));
     sCInfo.err = jpeg_std_error( &sJErr );
     jpeg_create_compress( &sCInfo );
 
     jpeg_vsiio_dest( &sCInfo, fp );
-    
+
     sCInfo.image_width = nBlockXSize;
     sCInfo.image_height = nBlockYSize;
+
+    const int nBands = poSrcDS->GetRasterCount();
     sCInfo.input_components = nBands;
 
     if( nBands == 1 )
@@ -122,7 +129,7 @@ NITFWriteJPEGBlock( GDALDataset *poSrcDS, VSILFILE *fp,
     }
 
     jpeg_set_defaults( &sCInfo );
-    
+
 #if defined(JPEG_LIB_MK1_OR_12BIT)
     if( eDT == GDT_UInt16 )
     {
@@ -175,13 +182,15 @@ NITFWriteJPEGBlock( GDALDataset *poSrcDS, VSILFILE *fp,
 /* -------------------------------------------------------------------- */
 /*      Loop over image, copying image data.                            */
 /* -------------------------------------------------------------------- */
-    GByte 	*pabyScanline;
-    CPLErr      eErr = CE_None;
-    int         nWorkDTSize = GDALGetDataTypeSize(eWorkDT) / 8;
+    const int nWorkDTSize = GDALGetDataTypeSizeBytes(eWorkDT);
+
+    GByte *pabyScanline = reinterpret_cast<GByte *>(
+        CPLMalloc( nBands * nBlockXSize * nWorkDTSize ) );
 
-    pabyScanline = (GByte *) CPLMalloc( nBands * nBlockXSize * nWorkDTSize );
+    const int nXSize = poSrcDS->GetRasterXSize();
+    const int nYSize = poSrcDS->GetRasterYSize();
 
-    double nTotalPixels = (double)nXSize * nYSize;
+    const double nTotalPixels = static_cast<double>( nXSize * nYSize );
 
     int nBlockXSizeToRead = nBlockXSize;
     if (nBlockXSize * nBlockXOff + nBlockXSize > nXSize)
@@ -193,17 +202,19 @@ NITFWriteJPEGBlock( GDALDataset *poSrcDS, VSILFILE *fp,
     {
         nBlockYSizeToRead = nYSize - nBlockYSize * nBlockYOff;
     }
-    
+
+#if defined(JPEG_LIB_MK1_OR_12BIT)
     bool bClipWarn = false;
+#endif
+
+    CPLErr eErr = CE_None;
     for( int iLine = 0; iLine < nBlockYSize && eErr == CE_None; iLine++ )
     {
-        JSAMPLE      *ppSamples;
-
         if (iLine < nBlockYSizeToRead)
         {
-            eErr = poSrcDS->RasterIO( GF_Read, nBlockXSize * nBlockXOff, iLine + nBlockYSize * nBlockYOff, nBlockXSizeToRead, 1, 
+            eErr = poSrcDS->RasterIO( GF_Read, nBlockXSize * nBlockXOff, iLine + nBlockYSize * nBlockYOff, nBlockXSizeToRead, 1,
                                     pabyScanline, nBlockXSizeToRead, 1, eWorkDT,
-                                    nBands, anBandList, 
+                                    nBands, anBandList,
                                     nBands*nWorkDTSize, nBands * nBlockXSize * nWorkDTSize, nWorkDTSize, NULL );
 
 #if !defined(JPEG_LIB_MK1_OR_12BIT)
@@ -223,13 +234,13 @@ NITFWriteJPEGBlock( GDALDataset *poSrcDS, VSILFILE *fp,
 #endif
         }
 
+#if defined(JPEG_LIB_MK1_OR_12BIT)
         // clamp 16bit values to 12bit.
         if( eDT == GDT_UInt16 )
         {
-            GUInt16 *panScanline = (GUInt16 *) pabyScanline;
-            int iPixel;
+            GUInt16 *panScanline = reinterpret_cast<GUInt16 *>( pabyScanline );
 
-            for( iPixel = 0; iPixel < nXSize*nBands; iPixel++ )
+            for( int iPixel = 0; iPixel < nXSize*nBands; iPixel++ )
             {
                 if( panScanline[iPixel] > 4095 )
                 {
@@ -243,19 +254,22 @@ NITFWriteJPEGBlock( GDALDataset *poSrcDS, VSILFILE *fp,
                 }
             }
         }
+#endif
 
-        ppSamples = (JSAMPLE *) pabyScanline;
+        JSAMPLE *ppSamples = reinterpret_cast<JSAMPLE *>( pabyScanline );
 
         if( eErr == CE_None )
             jpeg_write_scanlines( &sCInfo, &ppSamples, 1 );
 
-        double nCurPixels = (double)nBlockYOff * nBlockYSize * nXSize +
-                            (double)nBlockXOff * nBlockYSize * nBlockXSize + (iLine + 1) * nBlockXSizeToRead;
-        if( eErr == CE_None 
+        double nCurPixels =
+            static_cast<double>( nBlockYOff ) * nBlockYSize * nXSize +
+            static_cast<double>( nBlockXOff ) * nBlockYSize * nBlockXSize +
+            (iLine + 1) * nBlockXSizeToRead;
+        if( eErr == CE_None
             && !pfnProgress( nCurPixels / nTotalPixels, NULL, pProgressData ) )
         {
             eErr = CE_Failure;
-            CPLError( CE_Failure, CPLE_UserInterrupt, 
+            CPLError( CE_Failure, CPLE_UserInterrupt,
                       "User terminated CreateCopy()" );
         }
     }
diff --git a/frmts/nitf/nitfwritejpeg_12.cpp b/frmts/nitf/nitfwritejpeg_12.cpp
index 0acbfe3..c0b96c1 100644
--- a/frmts/nitf/nitfwritejpeg_12.cpp
+++ b/frmts/nitf/nitfwritejpeg_12.cpp
@@ -1,5 +1,6 @@
 #if defined(JPEG_DUAL_MODE_8_12)
 #  define LIBJPEG_12_PATH "../jpeg/libjpeg12/jpeglib.h"
 #  define NITFWriteJPEGBlock NITFWriteJPEGBlock_12
+#  define jpeg_vsiio_dest jpeg_vsiio_dest_12
 #  include "nitfwritejpeg.cpp"
 #endif /* defined(JPEG_DUAL_MODE_8_12) */
diff --git a/frmts/nitf/rpftocdataset.cpp b/frmts/nitf/rpftocdataset.cpp
index 72d2c6d..1002c36 100644
--- a/frmts/nitf/rpftocdataset.cpp
+++ b/frmts/nitf/rpftocdataset.cpp
@@ -27,23 +27,23 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_multiproc.h"
+#include "cpl_string.h"
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 #include "gdal_proxy.h"
-#include "rpftoclib.h"
 #include "ogr_spatialref.h"
-#include "cpl_string.h"
+#include "rpftoclib.h"
 #include "vrtdataset.h"
-#include "cpl_multiproc.h"
 
-#define GEOTRSFRM_TOPLEFT_X            0
-#define GEOTRSFRM_WE_RES               1
-#define GEOTRSFRM_ROTATION_PARAM1      2
-#define GEOTRSFRM_TOPLEFT_Y            3
-#define GEOTRSFRM_ROTATION_PARAM2      4
-#define GEOTRSFRM_NS_RES               5
-
-CPL_CVSID("$Id: rpftocdataset.cpp 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: rpftocdataset.cpp 33794 2016-03-26 13:19:07Z goatbar $");
 
+static const int GEOTRSFRM_TOPLEFT_X = 0;
+static const int GEOTRSFRM_WE_RES = 1;
+static const int GEOTRSFRM_ROTATION_PARAM1 = 2;
+static const int GEOTRSFRM_TOPLEFT_Y = 3;
+static const int GEOTRSFRM_ROTATION_PARAM2 = 4;
+static const int GEOTRSFRM_NS_RES = 5;
 
 /** Overview of used classes :
    - RPFTOCDataset : lists the different subdatasets, listed in the A.TOC,
@@ -66,23 +66,22 @@ class RPFTOCDataset : public GDALPamDataset
   char       *pszProjection;
   int         bGotGeoTransform;
   double      adfGeoTransform[6];
-  
+
   char      **papszFileList;
 
   public:
-    RPFTOCDataset()
-    {
-        papszSubDatasets = NULL;
-        pszProjection = NULL;
-        bGotGeoTransform = FALSE;
-        papszFileList = NULL;
-    }
-
-    ~RPFTOCDataset()
+    RPFTOCDataset() :
+        papszSubDatasets(NULL),
+        pszProjection(NULL),
+        bGotGeoTransform(FALSE),
+        papszFileList(NULL)
+    {}
+
+    virtual ~RPFTOCDataset()
     {
         CSLDestroy( papszSubDatasets );
-        CPLFree(pszProjection);
-        CSLDestroy(papszFileList);
+        CPLFree( pszProjection );
+        CSLDestroy( papszFileList );
     }
 
     virtual char      **GetMetadata( const char * pszDomain = "" );
@@ -106,33 +105,33 @@ class RPFTOCDataset : public GDALPamDataset
         }
         return CE_Failure;
     }
-    
+
     virtual CPLErr SetGeoTransform( double * padfGeoTransform)
     {
         bGotGeoTransform = TRUE;
         memcpy(adfGeoTransform, padfGeoTransform, 6 * sizeof(double));
         return CE_None;
     }
-    
+
     virtual CPLErr SetProjection( const char * projectionRef )
     {
         CPLFree(pszProjection);
         pszProjection = CPLStrdup(projectionRef);
         return CE_None;
     }
-    
+
     virtual const char *GetProjectionRef(void)
     {
         return (pszProjection) ? pszProjection : "";
     }
-    
+
     static int IsNITFFileTOC(NITFFile *psFile);
     static int IsNonNITFFileTOC(GDALOpenInfo * poOpenInfo, const char* pszFilename );
     static GDALDataset* OpenFileTOC(NITFFile *psFile,
                                     const char* pszFilename,
                                     const char* entryName,
                                     const char* openInformationName);
-    
+
     static int Identify( GDALOpenInfo * poOpenInfo );
     static GDALDataset* Open( GDALOpenInfo * poOpenInfo );
 };
@@ -154,24 +153,25 @@ class RPFTOCSubDataset : public VRTDataset
   char**       papszFileList;
 
   public:
-    RPFTOCSubDataset(int nXSize, int nYSize) : VRTDataset(nXSize, nYSize)
+    RPFTOCSubDataset(int nXSize, int nYSize) :
+        VRTDataset(nXSize, nYSize),
+        cachedTileBlockXOff(-1),
+        cachedTileBlockYOff(-1),
+        cachedTileData(NULL),
+        cachedTileDataSize(0),
+        cachedTileFileName(NULL),
+        papszFileList(NULL)
     {
         /* Don't try to write a VRT file */
         SetWritable(FALSE);
 
         /* The driver is set to VRT in VRTDataset constructor. */
         /* We have to set it to the expected value ! */
-        poDriver = (GDALDriver *) GDALGetDriverByName( "RPFTOC" );
-
-        cachedTileBlockXOff = cachedTileBlockYOff = -1;
-        cachedTileData = NULL;
-        cachedTileDataSize = 0;
-        cachedTileFileName = NULL;
-
-        papszFileList = NULL;
+        poDriver = reinterpret_cast<GDALDriver *>(
+            GDALGetDriverByName( "RPFTOC" ) );
     }
-    
-    ~RPFTOCSubDataset()
+
+    virtual ~RPFTOCSubDataset()
     {
         CSLDestroy(papszFileList);
         CPLFree(cachedTileData);
@@ -187,16 +187,14 @@ class RPFTOCSubDataset : public VRTDataset
         {
             return cachedTileData;
         }
-        else
-        {
-            return NULL;
-        }
+
+        return NULL;
     }
 
     void SetCachedTile(const char* tileFileName, int nBlockXOff, int nBlockYOff,
                        const void* pData, int dataSize)
     {
-        if (dataSize > cachedTileDataSize)
+        if (cachedTileData == NULL || dataSize > cachedTileDataSize)
         {
             cachedTileData = CPLRealloc(cachedTileData, dataSize);
             cachedTileDataSize = dataSize;
@@ -207,7 +205,6 @@ class RPFTOCSubDataset : public VRTDataset
         cachedTileBlockYOff = nBlockYOff;
     }
 
-    
     static GDALDataset* CreateDataSetFromTocEntry(const char* openInformationName,
                                                   const char* pszTOCFileName, int nEntry,
                                                   const RPFTocEntry* entry, int isRGBA,
@@ -239,15 +236,15 @@ class RPFTOCProxyRasterDataSet : public GDALProxyPoolDataset
                                  const char* projectionRef, double nwLong, double nwLat,
                                  int nBands);
 
-        void SetNoDataValue(double noDataValue) {
-            this->noDataValue = noDataValue;
+        void SetNoDataValue(double noDataValueIn) {
+            this->noDataValue = noDataValueIn;
             bHasNoDataValue = TRUE;
         }
 
-        double GetNoDataValue(int* bHasNoDataValue)
+        double GetNoDataValue(int* pbHasNoDataValue)
         {
-            if (bHasNoDataValue)
-                *bHasNoDataValue = this->bHasNoDataValue;
+            if (pbHasNoDataValue)
+                *pbHasNoDataValue = this->bHasNoDataValue;
             return noDataValue;
         }
 
@@ -261,7 +258,7 @@ class RPFTOCProxyRasterDataSet : public GDALProxyPoolDataset
             GDALProxyPoolDataset::UnrefUnderlyingDataset(poUnderlyingDataset);
         }
 
-        void SetReferenceColorTable(GDALColorTable* colorTableRef) { this->colorTableRef = colorTableRef;}
+        void SetReferenceColorTable(GDALColorTable* colorTableRefIn) { this->colorTableRef = colorTableRefIn;}
 
         const GDALColorTable* GetReferenceColorTable() { return colorTableRef; }
 
@@ -286,19 +283,20 @@ class RPFTOCProxyRasterBandRGBA : public GDALPamRasterBand
         void Expand(void* pImage, const void* srcImage);
 
     public:
-        RPFTOCProxyRasterBandRGBA(GDALProxyPoolDataset* poDS, int nBand,
-                                  int nBlockXSize, int nBlockYSize)
+        RPFTOCProxyRasterBandRGBA( GDALProxyPoolDataset* poDSIn, int nBandIn,
+                                   int nBlockXSizeIn, int nBlockYSizeIn):
+            initDone(FALSE)
         {
-            this->poDS = poDS;
-            nRasterXSize = poDS->GetRasterXSize();
-            nRasterYSize = poDS->GetRasterYSize();
-            this->nBlockXSize = nBlockXSize;
-            this->nBlockYSize = nBlockYSize;
+            this->poDS = poDSIn;
+            nRasterXSize = poDSIn->GetRasterXSize();
+            nRasterYSize = poDSIn->GetRasterYSize();
+            this->nBlockXSize = nBlockXSizeIn;
+            this->nBlockYSize = nBlockYSizeIn;
             eDataType = GDT_Byte;
-            this->nBand = nBand;
+            this->nBand = nBandIn;
             blockByteSize = nBlockXSize * nBlockYSize;
-            initDone = FALSE;
         }
+        virtual ~RPFTOCProxyRasterBandRGBA() {}
 
         virtual GDALColorInterp GetColorInterpretation()
         {
@@ -317,10 +315,9 @@ class RPFTOCProxyRasterBandRGBA : public GDALPamRasterBand
 /* Expand the  array or indexed colors to an array of their corresponding R,G,B or A component */
 void  RPFTOCProxyRasterBandRGBA::Expand(void* pImage, const void* srcImage)
 {
-    int i;
     if ((blockByteSize & (~3)) != 0)
     {
-        for(i=0;i<blockByteSize;i++)
+        for( int i = 0; i < blockByteSize; i++ )
         {
             ((unsigned char*)pImage)[i] = colorTable[((unsigned char*)srcImage)[i]];
         }
@@ -328,7 +325,7 @@ void  RPFTOCProxyRasterBandRGBA::Expand(void* pImage, const void* srcImage)
     else
     {
         int nIter = blockByteSize/4;
-        for(i=0;i<nIter;i++)
+        for( int i = 0; i < nIter; i++ )
         {
             unsigned int four_pixels = ((unsigned int*)srcImage)[i];
             ((unsigned int*)pImage)[i] =
@@ -349,7 +346,9 @@ CPLErr RPFTOCProxyRasterBandRGBA::IReadBlock( int nBlockXOff, int nBlockYOff,
                                          void * pImage )
 {
     CPLErr ret;
-    RPFTOCProxyRasterDataSet* proxyDS = (RPFTOCProxyRasterDataSet*)poDS;
+    RPFTOCProxyRasterDataSet* proxyDS
+        = reinterpret_cast<RPFTOCProxyRasterDataSet *>( poDS );
+
     GDALDataset* ds = proxyDS->RefUnderlyingDataset();
     if (ds)
     {
@@ -363,11 +362,11 @@ CPLErr RPFTOCProxyRasterBandRGBA::IReadBlock( int nBlockXOff, int nBlockYOff,
         if (initDone == FALSE)
         {
             GDALColorTable* srcColorTable = srcBand->GetColorTable();
-            int i;
             int bHasNoDataValue;
-            int noDataValue = (int)srcBand->GetNoDataValue(&bHasNoDataValue);
-            int nEntries = srcColorTable->GetColorEntryCount();
-            for(i=0;i<nEntries;i++)
+            int noDataValue = static_cast<int>(
+                srcBand->GetNoDataValue(&bHasNoDataValue) );
+            const int nEntries = srcColorTable->GetColorEntryCount();
+            for( int i = 0; i < nEntries; i++ )
             {
                 const GDALColorEntry* entry = srcColorTable->GetColorEntry(i);
                 if (nBand == 1)
@@ -402,24 +401,22 @@ CPLErr RPFTOCProxyRasterBandRGBA::IReadBlock( int nBlockXOff, int nBlockYOff,
                 Expand(pImage, pImage);
             }
 
-            /* -------------------------------------------------------------------- */
-            /*      Forceably load the other bands associated with this scanline.   */
-            /* -------------------------------------------------------------------- */
-            if(nBand == 1 )
+            /* -------------------------------------------------------------- */
+            /*  Forcibly load the other bands associated with this scanline.  */
+            /* -------------------------------------------------------------- */
+            if( nBand == 1 )
             {
-                GDALRasterBlock *poBlock;
-
-                poBlock = 
-                    poDS->GetRasterBand(2)->GetLockedBlockRef(nBlockXOff,nBlockYOff);
+                GDALRasterBlock *poBlock
+                    = poDS->GetRasterBand(2)->GetLockedBlockRef(nBlockXOff,nBlockYOff);
                 if (poBlock)
                     poBlock->DropLock();
 
-                poBlock = 
+                poBlock =
                     poDS->GetRasterBand(3)->GetLockedBlockRef(nBlockXOff,nBlockYOff);
                 if (poBlock)
                     poBlock->DropLock();
 
-                poBlock = 
+                poBlock =
                     poDS->GetRasterBand(4)->GetLockedBlockRef(nBlockXOff,nBlockYOff);
                 if (poBlock)
                     poBlock->DropLock();
@@ -454,18 +451,19 @@ class RPFTOCProxyRasterBandPalette : public GDALPamRasterBand
     unsigned char remapLUT[256];
 
     public:
-        RPFTOCProxyRasterBandPalette(GDALProxyPoolDataset* poDS, int nBand,
-                                     int nBlockXSize, int nBlockYSize)
+        RPFTOCProxyRasterBandPalette(GDALProxyPoolDataset* poDSIn, int nBandIn,
+                                     int nBlockXSizeIn, int nBlockYSizeIn) :
+            initDone(FALSE),
+            blockByteSize(nBlockXSizeIn * nBlockYSizeIn),
+            samePalette(0)
         {
-            this->poDS = poDS;
-            nRasterXSize = poDS->GetRasterXSize();
-            nRasterYSize = poDS->GetRasterYSize();
-            this->nBlockXSize = nBlockXSize;
-            this->nBlockYSize = nBlockYSize;
+            this->poDS = poDSIn;
+            nRasterXSize = poDSIn->GetRasterXSize();
+            nRasterYSize = poDSIn->GetRasterYSize();
+            this->nBlockXSize = nBlockXSizeIn;
+            this->nBlockYSize = nBlockYSizeIn;
             eDataType = GDT_Byte;
-            this->nBand = nBand;
-            blockByteSize = nBlockXSize * nBlockYSize;
-            initDone = FALSE;
+            this->nBand = nBandIn;
         }
 
         virtual GDALColorInterp GetColorInterpretation()
@@ -475,12 +473,14 @@ class RPFTOCProxyRasterBandPalette : public GDALPamRasterBand
 
         virtual double GetNoDataValue(int* bHasNoDataValue)
         {
-            return ((RPFTOCProxyRasterDataSet*)poDS)->GetNoDataValue(bHasNoDataValue);
+            return ( reinterpret_cast<RPFTOCProxyRasterDataSet *>( poDS ) )->GetNoDataValue(bHasNoDataValue);
         }
 
         virtual GDALColorTable *GetColorTable()
         {
-            return (GDALColorTable *) ((RPFTOCProxyRasterDataSet*)poDS)->GetReferenceColorTable();
+            // TODO: This casting is a bit scary.
+            return const_cast<GDALColorTable *>(
+                reinterpret_cast<RPFTOCProxyRasterDataSet *>( poDS )->GetReferenceColorTable() );
         }
 
     protected:
@@ -496,7 +496,8 @@ CPLErr RPFTOCProxyRasterBandPalette::IReadBlock( int nBlockXOff, int nBlockYOff,
                                                  void * pImage )
 {
     CPLErr ret;
-    RPFTOCProxyRasterDataSet* proxyDS = (RPFTOCProxyRasterDataSet*)poDS;
+    RPFTOCProxyRasterDataSet* proxyDS
+        = reinterpret_cast<RPFTOCProxyRasterDataSet *>( poDS );
     GDALDataset* ds = proxyDS->RefUnderlyingDataset();
     if (ds)
     {
@@ -508,7 +509,7 @@ CPLErr RPFTOCProxyRasterBandPalette::IReadBlock( int nBlockXOff, int nBlockYOff,
 
         GDALRasterBand* srcBand = ds->GetRasterBand(1);
         ret = srcBand->ReadBlock(nBlockXOff, nBlockYOff, pImage);
-        
+
         if (initDone == FALSE)
         {
             int approximateMatching;
@@ -533,8 +534,7 @@ CPLErr RPFTOCProxyRasterBandPalette::IReadBlock( int nBlockXOff, int nBlockYOff,
         if (samePalette == FALSE)
         {
             unsigned char* data = (unsigned char*)pImage;
-            int i;
-            for(i=0;i<blockByteSize;i++)
+            for( int i = 0; i < blockByteSize; i++ )
             {
                 data[i] = remapLUT[data[i]];
             }
@@ -554,34 +554,33 @@ CPLErr RPFTOCProxyRasterBandPalette::IReadBlock( int nBlockXOff, int nBlockYOff,
 /************************************************************************/
 
 RPFTOCProxyRasterDataSet::RPFTOCProxyRasterDataSet
-        (RPFTOCSubDataset* subdataset,
-         const char* fileName,
-         int nRasterXSize, int nRasterYSize,
-         int nBlockXSize, int nBlockYSize,
-         const char* projectionRef, double nwLong, double nwLat,
-         int nBands) :
-            /* Mark as shared since the VRT will take several references if we are in RGBA mode (4 bands for this dataset) */
-                GDALProxyPoolDataset(fileName, nRasterXSize, nRasterYSize, GA_ReadOnly, TRUE, projectionRef)
+        (RPFTOCSubDataset* subdatasetIn,
+         const char* fileNameIn,
+         int nRasterXSizeIn, int nRasterYSizeIn,
+         int nBlockXSizeIn, int nBlockYSizeIn,
+         const char* projectionRefIn, double nwLongIn, double nwLatIn,
+         int nBandsIn) :
+    /* Mark as shared since the VRT will take several references if we are in RGBA mode (4 bands for this dataset) */
+            GDALProxyPoolDataset(fileNameIn, nRasterXSizeIn, nRasterYSizeIn, GA_ReadOnly, TRUE, projectionRefIn),
+    checkDone(FALSE),
+    checkOK(FALSE),
+    colorTableRef(NULL),
+    bHasNoDataValue(FALSE),
+    noDataValue(0)
 {
-    int i;
-    this->subdataset = subdataset;
-    this->nwLong = nwLong;
-    this->nwLat = nwLat;
-    bHasNoDataValue = FALSE;
-    noDataValue = 0;
-    colorTableRef = NULL;
-
-    checkDone = FALSE;
-    checkOK = FALSE;
-    if (nBands == 4)
+    this->subdataset = subdatasetIn;
+    this->nwLong = nwLongIn;
+    this->nwLat = nwLatIn;
+
+    if (nBandsIn == 4)
     {
-        for(i=0;i<4;i++)
+        for( int i = 0; i < 4; i++ )
         {
-            SetBand(i + 1, new RPFTOCProxyRasterBandRGBA(this, i+1, nBlockXSize, nBlockYSize));
+            SetBand(i + 1, new RPFTOCProxyRasterBandRGBA(this, i+1, nBlockXSizeIn, nBlockYSizeIn));
         }
     }
     else
-        SetBand(1, new RPFTOCProxyRasterBandPalette(this, 1, nBlockXSize, nBlockYSize));
+        SetBand(1, new RPFTOCProxyRasterBandPalette(this, 1, nBlockXSizeIn, nBlockYSizeIn));
 }
 
 /************************************************************************/
@@ -595,18 +594,18 @@ int RPFTOCProxyRasterDataSet::SanityCheckOK(GDALDataset* sourceDS)
 {
     int src_nBlockXSize, src_nBlockYSize;
     int nBlockXSize, nBlockYSize;
-    double adfGeoTransform[6];
+    double l_adfGeoTransform[6];
     if (checkDone)
         return checkOK;
-    
+
     checkOK = TRUE;
     checkDone = TRUE;
-    
-    sourceDS->GetGeoTransform(adfGeoTransform);
-    WARN_ON_FAIL(fabs(adfGeoTransform[GEOTRSFRM_TOPLEFT_X] - nwLong) < adfGeoTransform[1] );
-    WARN_ON_FAIL(fabs(adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] - nwLat) < fabs(adfGeoTransform[5]) );
-    WARN_ON_FAIL(adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1] == 0 &&
-                  adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] == 0); /* No rotation */
+
+    sourceDS->GetGeoTransform(l_adfGeoTransform);
+    WARN_ON_FAIL(fabs(l_adfGeoTransform[GEOTRSFRM_TOPLEFT_X] - nwLong) < l_adfGeoTransform[1] );
+    WARN_ON_FAIL(fabs(l_adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] - nwLat) < fabs(l_adfGeoTransform[5]) );
+    WARN_ON_FAIL(l_adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1] == 0 &&
+                  l_adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] == 0); /* No rotation */
     ERROR_ON_FAIL(sourceDS->GetRasterCount() == 1); /* Just 1 band */
     ERROR_ON_FAIL(sourceDS->GetRasterXSize() == nRasterXSize);
     ERROR_ON_FAIL(sourceDS->GetRasterYSize() == nRasterYSize);
@@ -629,9 +628,14 @@ static const char* MakeTOCEntryName(RPFTocEntry* tocEntry )
 {
     char* str;
     if (tocEntry->seriesAbbreviation)
-        str = (char*)CPLSPrintf( "%s_%s_%s_%s_%d", tocEntry->type, tocEntry->seriesAbbreviation, tocEntry->scale, tocEntry->zone, tocEntry->boundaryId );
+        str = const_cast<char *>(
+            CPLSPrintf( "%s_%s_%s_%s_%d", tocEntry->type,
+                        tocEntry->seriesAbbreviation, tocEntry->scale,
+                        tocEntry->zone, tocEntry->boundaryId ) );
     else
-        str = (char*)CPLSPrintf( "%s_%s_%s_%d", tocEntry->type, tocEntry->scale, tocEntry->zone, tocEntry->boundaryId );
+        str = const_cast<char *>(
+            CPLSPrintf( "%s_%s_%s_%d", tocEntry->type, tocEntry->scale,
+                        tocEntry->zone, tocEntry->boundaryId ) );
     char* c = str;
     while(*c)
     {
@@ -650,20 +654,20 @@ void RPFTOCDataset::AddSubDataset( const char* pszFilename,  RPFTocEntry* tocEnt
 
 {
     char	szName[80];
-    int		nCount = CSLCount(papszSubDatasets ) / 2;
+    const int nCount = CSLCount(papszSubDatasets ) / 2;
 
-    sprintf( szName, "SUBDATASET_%d_NAME", nCount+1 );
-    papszSubDatasets = 
-        CSLSetNameValue( papszSubDatasets, szName, 
+    snprintf( szName, sizeof(szName), "SUBDATASET_%d_NAME", nCount+1 );
+    papszSubDatasets =
+        CSLSetNameValue( papszSubDatasets, szName,
               CPLSPrintf( "NITF_TOC_ENTRY:%s:%s", MakeTOCEntryName(tocEntry), pszFilename ) );
 
-    sprintf( szName, "SUBDATASET_%d_DESC", nCount+1 );
+    snprintf( szName, sizeof(szName), "SUBDATASET_%d_DESC", nCount+1 );
     if (tocEntry->seriesName && tocEntry->seriesAbbreviation)
-        papszSubDatasets = 
+        papszSubDatasets =
         CSLSetNameValue( papszSubDatasets, szName,
                CPLSPrintf( "%s:%s:%s:%s:%s:%d", tocEntry->type, tocEntry->seriesAbbreviation, tocEntry->seriesName, tocEntry->scale, tocEntry->zone, tocEntry->boundaryId ));
     else
-        papszSubDatasets = 
+        papszSubDatasets =
             CSLSetNameValue( papszSubDatasets, szName,
                 CPLSPrintf( "%s:%s:%s:%d", tocEntry->type, tocEntry->scale, tocEntry->zone, tocEntry->boundaryId ));
 }
@@ -694,55 +698,56 @@ GDALDataset* RPFTOCSubDataset::CreateDataSetFromTocEntry(const char* openInforma
                                                          const RPFTocEntry* entry, int isRGBA,
                                                          char** papszMetadataRPFTOCFile)
 {
-    int i, j;
-    GDALDriver *poDriver;
-    RPFTOCSubDataset *poVirtualDS;
-    int sizeX, sizeY;
-    int nBlockXSize = 0, nBlockYSize = 0;
-    double geoTransf[6];
-    char* projectionRef = NULL;
-    int N;
-    int index = 0;
-
-    poDriver = GetGDALDriverManager()->GetDriverByName("VRT");
+    GDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName("VRT");
     if( poDriver == NULL )
         return NULL;
 
-    N = entry->nVertFrames * entry->nHorizFrames;
+    const int N = entry->nVertFrames * entry->nHorizFrames;
 
     /* This may not be reliable. See below */
-    sizeX = (int)((entry->seLong - entry->nwLong) / (entry->nHorizFrames * entry->horizInterval) + 0.5);
-    sizeY = (int)((entry->nwLat - entry->seLat) / (entry->nVertFrames * entry->vertInterval) + 0.5);
+    int sizeX = static_cast<int>(
+        (entry->seLong - entry->nwLong)
+        / (entry->nHorizFrames * entry->horizInterval) + 0.5);
 
-    for(i=0;i<N; i++)
+    const int sizeY = static_cast<int>(
+        (entry->nwLat - entry->seLat)
+        / (entry->nVertFrames * entry->vertInterval) + 0.5);
+
+    int nBlockXSize = 0, nBlockYSize = 0;
+    double geoTransf[6];
+    char* projectionRef = NULL;
+    int index = 0;
+
+    for( int i = 0; i < N; i++ )
     {
         if (!entry->frameEntries[i].fileExists)
             continue;
 
         if (index == 0)
         {
-            int ds_sizeX, ds_sizeY;
             /* Open the first available file to get its geotransform, projection ref and block size */
             /* Do a few sanity checks too */
             /* Ideally we should make these sanity checks now on ALL files, but it would be too slow */
             /* for large datasets. So these sanity checks will be done at the time we really need */
             /* to access the file (see SanityCheckOK metho) */
-            GDALDataset *poSrcDS = (GDALDataset *) GDALOpenShared( entry->frameEntries[i].fullFilePath, GA_ReadOnly );
+            GDALDataset *poSrcDS = reinterpret_cast<GDALDataset *>(
+                GDALOpenShared( entry->frameEntries[i].fullFilePath,
+                                GA_ReadOnly ) );
             ASSERT_CREATE_VRT(poSrcDS);
             poSrcDS->GetGeoTransform(geoTransf);
             projectionRef = CPLStrdup(poSrcDS->GetProjectionRef());
             ASSERT_CREATE_VRT(geoTransf[GEOTRSFRM_ROTATION_PARAM1] == 0 &&
                               geoTransf[GEOTRSFRM_ROTATION_PARAM2] == 0); /* No rotation */
             ASSERT_CREATE_VRT(poSrcDS->GetRasterCount() == 1); /* Just 1 band */
-            
+
             /* Tolerance of 1%... This is necessary for CADRG_L22/RPF/A.TOC for example */
             ASSERT_CREATE_VRT((entry->horizInterval - geoTransf[GEOTRSFRM_WE_RES]) /
                                 entry->horizInterval < 0.01); /* X interval same as in TOC */
             ASSERT_CREATE_VRT((entry->vertInterval - (-geoTransf[GEOTRSFRM_NS_RES])) /
                                 entry->horizInterval < 0.01); /* Y interval same as in TOC */
 
-            ds_sizeX = poSrcDS->GetRasterXSize();
-            ds_sizeY = poSrcDS->GetRasterYSize();
+            const int ds_sizeX = poSrcDS->GetRasterXSize();
+            const int ds_sizeY = poSrcDS->GetRasterYSize();
             /* In the case the east longitude is 180, there's a great chance that it is in fact */
             /* truncated in the A.TOC. Thus, the only reliable way to find out the tile width, is to */
             /* read it from the tile dataset itself... */
@@ -767,8 +772,9 @@ GDALDataset* RPFTOCSubDataset::CreateDataSetFromTocEntry(const char* openInforma
     /* ------------------------------------ */
     /* Create the VRT with the overall size */
     /* ------------------------------------ */
-    poVirtualDS = new RPFTOCSubDataset( sizeX * entry->nHorizFrames,
-                                        sizeY * entry->nVertFrames);
+    RPFTOCSubDataset *poVirtualDS
+        = new RPFTOCSubDataset( sizeX * entry->nHorizFrames,
+                                sizeY * entry->nVertFrames);
 
     if (papszMetadataRPFTOCFile)
         poVirtualDS->SetMetadata(papszMetadataRPFTOCFile);
@@ -778,9 +784,9 @@ GDALDataset* RPFTOCSubDataset::CreateDataSetFromTocEntry(const char* openInforma
     geoTransf[GEOTRSFRM_TOPLEFT_X] = entry->nwLong;
     geoTransf[GEOTRSFRM_TOPLEFT_Y] = entry->nwLat;
     poVirtualDS->SetGeoTransform(geoTransf);
-    
+
     int nBands;
-    
+
     /* In most cases, all the files inside a TOC entry share the same */
     /* palette and we could use it for the VRT. */
     /* In other cases like for CADRG801_France_250K (TOC entry CADRG_250K_2_2), */
@@ -795,20 +801,22 @@ GDALDataset* RPFTOCSubDataset::CreateDataSetFromTocEntry(const char* openInforma
         GDALRasterBand *poBand = poVirtualDS->GetRasterBand( 1 );
         poBand->SetColorInterpretation(GCI_PaletteIndex);
         nBands = 1;
-        
-        for(i=0;i<N; i++)
+
+        for( int i = 0; i < N; i++ )
         {
             if (!entry->frameEntries[i].fileExists)
                 continue;
-            
-            int bAllBlack = TRUE;
-            GDALDataset *poSrcDS = (GDALDataset *) GDALOpenShared( entry->frameEntries[i].fullFilePath, GA_ReadOnly );
+
+            bool bAllBlack = true;
+            GDALDataset *poSrcDS = reinterpret_cast<GDALDataset *>(
+                GDALOpenShared( entry->frameEntries[i].fullFilePath,
+                                GA_ReadOnly ) );
             if( poSrcDS != NULL )
             {
                 if( poSrcDS->GetRasterCount() == 1 )
                 {
                     int bHasNoDataValue;
-                    double noDataValue = poSrcDS->GetRasterBand(1)->GetNoDataValue(&bHasNoDataValue);
+                    const double noDataValue = poSrcDS->GetRasterBand(1)->GetNoDataValue(&bHasNoDataValue);
                     if (bHasNoDataValue)
                         poBand->SetNoDataValue(noDataValue);
 
@@ -819,13 +827,14 @@ GDALDataset* RPFTOCSubDataset::CreateDataSetFromTocEntry(const char* openInforma
                     {
                         for(int iC = 0; iC < poCT->GetColorEntryCount(); iC++)
                         {
-                            if( bHasNoDataValue && iC == (int)noDataValue )
+                            if( bHasNoDataValue &&
+                                iC == static_cast<int>( noDataValue ) )
                                 continue;
 
-                            const GDALColorEntry* entry = poCT->GetColorEntry(iC);
-                            if( entry->c1 != 0 || entry->c2 != 0 || entry->c3 != 0)
+                            const GDALColorEntry* psColorEntry = poCT->GetColorEntry(iC);
+                            if( psColorEntry->c1 != 0 || psColorEntry->c2 != 0 || psColorEntry->c3 != 0)
                             {
-                                bAllBlack = FALSE;
+                                bAllBlack = false;
                                 break;
                             }
                         }
@@ -849,7 +858,7 @@ GDALDataset* RPFTOCSubDataset::CreateDataSetFromTocEntry(const char* openInforma
     }
     else
     {
-        for (i=0;i<4;i++)
+        for( int i = 0; i < 4; i++ )
         {
             poVirtualDS->AddBand(GDT_Byte, NULL);
             GDALRasterBand *poBand = poVirtualDS->GetRasterBand( i + 1 );
@@ -873,7 +882,7 @@ GDALDataset* RPFTOCSubDataset::CreateDataSetFromTocEntry(const char* openInforma
     poVirtualDS->SetDescription(openInformationName);
 
     int iFile = 0;
-    for(i=0;i<N; i++)
+    for( int i = 0; i < N; i++ )
     {
         if (! entry->frameEntries[i].fileExists)
             continue;
@@ -890,31 +899,34 @@ GDALDataset* RPFTOCSubDataset::CreateDataSetFromTocEntry(const char* openInforma
         /* needed (IRasterIO operation). To improve a bit efficiency, we have a cache of opened */
         /* underlying datasets */
         RPFTOCProxyRasterDataSet* ds = new RPFTOCProxyRasterDataSet(
-                (RPFTOCSubDataset*)poVirtualDS,
-                entry->frameEntries[i].fullFilePath,
-                sizeX, sizeY,
-                nBlockXSize, nBlockYSize,
-                poVirtualDS->GetProjectionRef(),
-                entry->nwLong + entry->frameEntries[i].frameCol * entry->horizInterval * sizeX, 
-                entry->nwLat - entry->frameEntries[i].frameRow * entry->vertInterval * sizeY,
-                nBands);
+            reinterpret_cast<RPFTOCSubDataset *>( poVirtualDS ),
+            entry->frameEntries[i].fullFilePath,
+            sizeX, sizeY,
+            nBlockXSize, nBlockYSize,
+            poVirtualDS->GetProjectionRef(),
+            entry->nwLong + entry->frameEntries[i].frameCol * entry->horizInterval * sizeX,
+            entry->nwLat - entry->frameEntries[i].frameRow * entry->vertInterval * sizeY,
+            nBands);
+
         if (nBands == 1)
         {
             GDALRasterBand *poBand = poVirtualDS->GetRasterBand( 1 );
             ds->SetReferenceColorTable(poBand->GetColorTable());
             int bHasNoDataValue;
-            double noDataValue = poBand->GetNoDataValue(&bHasNoDataValue);
+            const double noDataValue = poBand->GetNoDataValue(&bHasNoDataValue);
             if (bHasNoDataValue)
                 ds->SetNoDataValue(noDataValue);
         }
 
-        for(j=0;j<nBands;j++)
+        for( int j = 0; j < nBands; j++ )
         {
-            VRTSourcedRasterBand *poBand = (VRTSourcedRasterBand*)poVirtualDS->GetRasterBand( j + 1 );
+            VRTSourcedRasterBand *poBand =
+                reinterpret_cast<VRTSourcedRasterBand *>(
+                    poVirtualDS->GetRasterBand( j + 1 ) );
             /* Place the raster band at the right position in the VRT */
             poBand->AddSimpleSource(ds->GetRasterBand(j + 1),
                                     0, 0, sizeX, sizeY,
-                                    entry->frameEntries[i].frameCol * sizeX, 
+                                    entry->frameEntries[i].frameCol * sizeX,
                                     entry->frameEntries[i].frameRow * sizeY,
                                     sizeX, sizeY);
         }
@@ -949,17 +961,16 @@ int RPFTOCDataset::IsNonNITFFileTOC(GDALOpenInfo * poOpenInfo, const char* pszFi
     }
     else
     {
-        char buffer[48];
-        VSILFILE* fp = NULL;
-        fp = VSIFOpenL( pszFilename, "rb" );
+        VSILFILE* fp = VSIFOpenL( pszFilename, "rb" );
         if( fp == NULL )
         {
             return FALSE;
         }
 
+        char buffer[48];
         int ret = (VSIFReadL(buffer, 1, 48, fp) == 48) &&
                    memcmp(pattern, buffer, 15) == 0;
-        VSIFCloseL(fp);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
         return ret;
     }
 }
@@ -1003,25 +1014,30 @@ GDALDataset* RPFTOCDataset::OpenFileTOC(NITFFile *psFile,
 
         if( fp == NULL )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
-                    "Failed to open file %s.", 
+            CPLError( CE_Failure, CPLE_OpenFailed,
+                    "Failed to open file %s.",
                     pszFilename );
             return NULL;
         }
-        VSIFReadL(buffer, 1, 48, fp);
+        if( VSIFReadL(buffer, 1, 48, fp) != 48 )
+        {
+            CPLError( CE_Failure, CPLE_FileIO, "I/O error" );
+            CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
+            return NULL;
+        }
     }
-    int isRGBA = CSLTestBoolean(CPLGetConfigOption("RPFTOC_FORCE_RGBA", "NO"));
+    const int isRGBA = CPLTestBool(CPLGetConfigOption("RPFTOC_FORCE_RGBA", "NO"));
     RPFToc* toc = (psFile) ? RPFTOCRead( pszFilename, psFile ) :
                               RPFTOCReadFromBuffer( pszFilename, fp, buffer);
-    if (fp) VSIFCloseL(fp);
+    if (fp)
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
     fp = NULL;
 
     if (entryName != NULL)
     {
         if (toc)
         {
-            int i;
-            for(i=0;i<toc->nEntries;i++)
+            for( int i = 0; i < toc->nEntries; i++)
             {
                 if (EQUAL(entryName, MakeTOCEntryName(&toc->entries[i])))
                 {
@@ -1033,7 +1049,7 @@ GDALDataset* RPFTOCDataset::OpenFileTOC(NITFFile *psFile,
                     return ds;
                 }
             }
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                         "The entry %s does not exist in file %s.", entryName, pszFilename );
         }
         RPFTOCFree(toc);
@@ -1046,15 +1062,14 @@ GDALDataset* RPFTOCDataset::OpenFileTOC(NITFFile *psFile,
         if (psFile)
             ds->SetMetadata( psFile->papszMetadata );
 
-        int i;
-        int ok = FALSE;
+        bool ok = false;
         char* projectionRef = NULL;
         double nwLong = 0, nwLat = 0, seLong = 0, seLat = 0;
         double adfGeoTransform[6];
 
         ds->papszFileList = CSLAddString(ds->papszFileList, pszFilename);
 
-        for(i=0;i<toc->nEntries;i++)
+        for( int i = 0; i < toc->nEntries; i++ )
         {
             if (!toc->entries[i].isOverviewOrLegend)
             {
@@ -1070,7 +1085,7 @@ GDALDataset* RPFTOCDataset::OpenFileTOC(NITFFile *psFile,
                     tmpDS->GetGeoTransform(adfGeoTransform);
                     if (projectionRef == NULL)
                     {
-                        ok = TRUE;
+                        ok = true;
                         projectionRef = CPLStrdup(tmpDS->GetProjectionRef());
                         nwLong = adfGeoTransform[GEOTRSFRM_TOPLEFT_X];
                         nwLat = adfGeoTransform[GEOTRSFRM_TOPLEFT_Y];
@@ -1084,7 +1099,7 @@ GDALDataset* RPFTOCDataset::OpenFileTOC(NITFFile *psFile,
                         double _seLong = _nwLong + adfGeoTransform[GEOTRSFRM_WE_RES] * tmpDS->GetRasterXSize();
                         double _seLat = _nwLat + adfGeoTransform[GEOTRSFRM_NS_RES] * tmpDS->GetRasterYSize();
                         if (! EQUAL(projectionRef, tmpDS->GetProjectionRef()) )
-                            ok = FALSE;
+                            ok = false;
                         if (_nwLong < nwLong)
                             nwLong = _nwLong;
                         if (_nwLat > nwLat)
@@ -1103,8 +1118,12 @@ GDALDataset* RPFTOCDataset::OpenFileTOC(NITFFile *psFile,
         {
             adfGeoTransform[GEOTRSFRM_TOPLEFT_X] = nwLong;
             adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] = nwLat;
-            ds->SetSize((int)(0.5 + (seLong - nwLong) / adfGeoTransform[GEOTRSFRM_WE_RES]), 
-                        (int)(0.5 + (seLat - nwLat) / adfGeoTransform[GEOTRSFRM_NS_RES]));
+            ds->SetSize(
+                static_cast<int>( 0.5 + (seLong - nwLong)
+                                  / adfGeoTransform[GEOTRSFRM_WE_RES] ),
+                static_cast<int>( 0.5 + (seLat - nwLat)
+                                  / adfGeoTransform[GEOTRSFRM_NS_RES]) );
+
             ds->SetGeoTransform(adfGeoTransform);
             ds->SetProjection(projectionRef);
         }
@@ -1119,10 +1138,8 @@ GDALDataset* RPFTOCDataset::OpenFileTOC(NITFFile *psFile,
 
         return ds;
     }
-    else
-    {
-        return NULL;
-    }
+
+    return NULL;
 }
 
 /************************************************************************/
@@ -1135,32 +1152,34 @@ int RPFTOCDataset::Identify( GDALOpenInfo * poOpenInfo )
     const char *pszFilename = poOpenInfo->pszFilename;
 
 /* -------------------------------------------------------------------- */
-/*      Is this a sub-dataset selector? If so, it is obviously RPFTOC.        */
+/*      Is this a sub-dataset selector? If so, it is obviously RPFTOC.  */
 /* -------------------------------------------------------------------- */
 
-    if( EQUALN(pszFilename, "NITF_TOC_ENTRY:",strlen("NITF_TOC_ENTRY:")))
+    if( STARTS_WITH_CI(pszFilename, "NITF_TOC_ENTRY:"))
         return TRUE;
 
 /* -------------------------------------------------------------------- */
 /*	First we check to see if the file has the expected header	*/
-/*	bytes.								*/    
+/*	bytes.								*/
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->nHeaderBytes < 48 )
         return FALSE;
-    
+
     if ( IsNonNITFFileTOC( poOpenInfo, pszFilename) )
         return TRUE;
-        
-    if( !EQUALN((char *) poOpenInfo->pabyHeader,"NITF",4) 
-        && !EQUALN((char *) poOpenInfo->pabyHeader,"NSIF",4)
-        && !EQUALN((char *) poOpenInfo->pabyHeader,"NITF",4) )
+
+    if( !STARTS_WITH_CI((char *) poOpenInfo->pabyHeader, "NITF")
+        && !STARTS_WITH_CI((char *) poOpenInfo->pabyHeader, "NSIF")
+        && !STARTS_WITH_CI((char *) poOpenInfo->pabyHeader, "NITF") )
         return FALSE;
-    
-    int i;
+
     /* If it's a NITF A.TOC file, it must contain A.TOC in it's header */
-    for(i=0;i<(int)poOpenInfo->nHeaderBytes-(int)strlen("A.TOC");i++)
+    for( int i = 0;
+         i < static_cast<int>( poOpenInfo->nHeaderBytes )
+             - static_cast<int>( strlen( "A.TOC" ) );
+         i++ )
     {
-        if (EQUALN((const char*)poOpenInfo->pabyHeader + i, "A.TOC", strlen("A.TOC")))
+        if (STARTS_WITH_CI((const char*)poOpenInfo->pabyHeader + i, "A.TOC"))
             return TRUE;
     }
 
@@ -1174,13 +1193,13 @@ int RPFTOCDataset::Identify( GDALOpenInfo * poOpenInfo )
 GDALDataset *RPFTOCDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    const char *pszFilename = poOpenInfo->pszFilename;
-    char* entryName = NULL;
-
     if( !Identify( poOpenInfo ) )
         return NULL;
 
-    if( EQUALN(pszFilename, "NITF_TOC_ENTRY:",strlen("NITF_TOC_ENTRY:")))
+    const char *pszFilename = poOpenInfo->pszFilename;
+    char* entryName = NULL;
+
+    if( STARTS_WITH_CI(pszFilename, "NITF_TOC_ENTRY:"))
     {
         pszFilename += strlen("NITF_TOC_ENTRY:");
         entryName = CPLStrdup(pszFilename);
@@ -1198,11 +1217,11 @@ GDALDataset *RPFTOCDataset::Open( GDALOpenInfo * poOpenInfo )
             pszFilename++;
         pszFilename++;
     }
-    
+
     if (IsNonNITFFileTOC((entryName != NULL) ? NULL : poOpenInfo, pszFilename))
     {
         GDALDataset* poDS = OpenFileTOC(NULL, pszFilename, entryName, poOpenInfo->pszFilename);
-        
+
         CPLFree(entryName);
 
         if (poDS && poOpenInfo->eAccess == GA_Update)
@@ -1211,16 +1230,14 @@ GDALDataset *RPFTOCDataset::Open( GDALOpenInfo * poOpenInfo )
             delete poDS;
             return NULL;
         }
-        
+
         return poDS;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Open the file with library.                                     */
 /* -------------------------------------------------------------------- */
-    NITFFile *psFile;
-
-    psFile = NITFOpen( pszFilename, FALSE );
+    NITFFile *psFile = NITFOpen( pszFilename, FALSE );
     if( psFile == NULL )
     {
         CPLFree(entryName);
@@ -1242,12 +1259,12 @@ GDALDataset *RPFTOCDataset::Open( GDALOpenInfo * poOpenInfo )
             delete poDS;
             return NULL;
         }
-        
+
         return poDS;
     }
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                           "File %s is not a TOC file.", pszFilename );
         NITFClose( psFile );
         CPLFree(entryName);
@@ -1257,32 +1274,30 @@ GDALDataset *RPFTOCDataset::Open( GDALOpenInfo * poOpenInfo )
 }
 
 /************************************************************************/
-/*                          GDALRegister_RPFTOC()                         */
+/*                          GDALRegister_RPFTOC()                       */
 /************************************************************************/
 
 void GDALRegister_RPFTOC()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "RPFTOC" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "RPFTOC" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "RPFTOC" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Raster Product Format TOC format" );
-        
-        poDriver->pfnIdentify = RPFTOCDataset::Identify;
-        poDriver->pfnOpen = RPFTOCDataset::Open;
-
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#RPFTOC" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "toc" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "RPFTOC" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Raster Product Format TOC format" );
+
+    poDriver->pfnIdentify = RPFTOCDataset::Identify;
+    poDriver->pfnOpen = RPFTOCDataset::Open;
+
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_various.html#RPFTOC" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "toc" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/nitf/rpftocfile.cpp b/frmts/nitf/rpftocfile.cpp
index bc2cda2..ffda506 100644
--- a/frmts/nitf/rpftocfile.cpp
+++ b/frmts/nitf/rpftocfile.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rpftocfile.cpp 29260 2015-05-29 09:13:17Z rouault $
+ * $Id: rpftocfile.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  RPF A.TOC read Library
  * Purpose:  Module responsible for opening a RPF TOC file, populating RPFToc
@@ -36,8 +36,8 @@
  * its documentation for any purpose and without fee is hereby granted,
  * provided that the above copyright notice appear in all copies, that
  * both the copyright notice and this permission notice appear in
- * supporting documentation, and that the name of L.A.S. Inc not be used 
- * in advertising or publicity pertaining to distribution of the software 
+ * supporting documentation, and that the name of L.A.S. Inc not be used
+ * in advertising or publicity pertaining to distribution of the software
  * without specific, written prior permission. L.A.S. Inc. makes no
  * representations about the suitability of this software for any purpose.
  * It is provided "as is" without express or implied warranty.
@@ -49,7 +49,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: rpftocfile.cpp 29260 2015-05-29 09:13:17Z rouault $");
+CPL_CVSID("$Id: rpftocfile.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 /************************************************************************/
 /*                        RPFTOCTrim()                                    */
@@ -58,7 +58,6 @@ CPL_CVSID("$Id: rpftocfile.cpp 29260 2015-05-29 09:13:17Z rouault $");
 static void RPFTOCTrim(char* str)
 {
     char* c = str;
-    int i;
     if (str == NULL || *str == 0)
         return;
 
@@ -70,8 +69,8 @@ static void RPFTOCTrim(char* str)
     {
         memmove(str, c, strlen(c)+1);
     }
-    
-    i = strlen(str) - 1;
+
+    int i = static_cast<int>(strlen(str)) - 1;
     while (i >= 0 && str[i] == ' ')
     {
         str[i] = 0;
@@ -83,22 +82,21 @@ static void RPFTOCTrim(char* str)
 /*                        RPFTOCRead()                                 */
 /************************************************************************/
 
- 
 RPFToc* RPFTOCRead(const char* pszFilename, NITFFile* psFile)
 {
     int nTRESize;
-    const char* pachTRE = NITFFindTRE( psFile->pachTRE, psFile->nTREBytes, 
+    const char* pachTRE = NITFFindTRE( psFile->pachTRE, psFile->nTREBytes,
                            "RPFHDR", &nTRESize );
     if (pachTRE == NULL)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "Invalid TOC file. Can't find RPFHDR." );
         return NULL;
     }
 
     if (nTRESize != 48)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "RPFHDR TRE wrong size." );
         return NULL;
     }
@@ -111,27 +109,6 @@ RPFToc* RPFTOCRead(const char* pszFilename, NITFFile* psFile)
 
 RPFToc* RPFTOCReadFromBuffer(const char* pszFilename, VSILFILE* fp, const char* tocHeader)
 {
-    int i, j;
-    unsigned int locationSectionPhysicalLocation;
-    
-    int nSections;
-    unsigned int boundaryRectangleSectionSubHeaderPhysIndex = 0;
-    unsigned int boundaryRectangleTablePhysIndex = 0;
-    unsigned int frameFileIndexSectionSubHeaderPhysIndex = 0;
-    unsigned int frameFileIndexSubsectionPhysIndex = 0;
-    
-    unsigned int boundaryRectangleTableOffset;
-    unsigned short boundaryRectangleCount;
-    
-    unsigned int frameIndexTableOffset;
-    unsigned int nFrameFileIndexRecords;
-    unsigned short nFrameFilePathnameRecords;
-    unsigned short frameFileIndexRecordLength;
-
-    int newBoundaryId = 0;
-
-    RPFToc* toc;
-    
     tocHeader += 1; /* skip endian */
     tocHeader += 2; /* skip header length */
     tocHeader += 12; /* skip file name : this should be A.TOC (padded) */
@@ -141,21 +118,28 @@ RPFToc* RPFTOCReadFromBuffer(const char* pszFilename, VSILFILE* fp, const char*
     tocHeader += 1; /* skip classification  */
     tocHeader += 2; /* skip country  */
     tocHeader += 2; /* skip release  */
-    
+
+    unsigned int locationSectionPhysicalLocation;
     memcpy(&locationSectionPhysicalLocation, tocHeader, sizeof(unsigned int));
     CPL_MSBPTR32(&locationSectionPhysicalLocation);
-    
+
     if( VSIFSeekL( fp, locationSectionPhysicalLocation, SEEK_SET ) != 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "Invalid TOC file. Unable to seek to locationSectionPhysicalLocation at offset %d.",
                    locationSectionPhysicalLocation );
         return NULL;
     }
-    
+
+    int nSections;
     NITFLocation* pasLocations = NITFReadRPFLocationTable(fp, &nSections);
-    
-    for (i = 0; i < nSections; i++)
+
+    unsigned int boundaryRectangleSectionSubHeaderPhysIndex = 0;
+    unsigned int boundaryRectangleTablePhysIndex = 0;
+    unsigned int frameFileIndexSectionSubHeaderPhysIndex = 0;
+    unsigned int frameFileIndexSubsectionPhysIndex = 0;
+
+    for( int i = 0; i < nSections; i++ )
     {
         if (pasLocations[i].nLocId == LID_BoundaryRectangleSectionSubheader)
         {
@@ -176,72 +160,75 @@ RPFToc* RPFTOCReadFromBuffer(const char* pszFilename, VSILFILE* fp, const char*
     }
 
     CPLFree(pasLocations);
-    
+
     if (boundaryRectangleSectionSubHeaderPhysIndex == 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "Invalid TOC file. Can't find LID_BoundaryRectangleSectionSubheader." );
         return NULL;
     }
     if (boundaryRectangleTablePhysIndex == 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "Invalid TOC file. Can't find LID_BoundaryRectangleTable." );
         return NULL;
     }
     if (frameFileIndexSectionSubHeaderPhysIndex == 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "Invalid TOC file. Can't find LID_FrameFileIndexSectionSubHeader." );
         return NULL;
     }
     if (frameFileIndexSubsectionPhysIndex == 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "Invalid TOC file. Can't find LID_FrameFileIndexSubsection." );
         return NULL;
     }
-    
+
     if( VSIFSeekL( fp, boundaryRectangleSectionSubHeaderPhysIndex, SEEK_SET ) != 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "Invalid TOC file. Unable to seek to boundaryRectangleSectionSubHeaderPhysIndex at offset %d.",
                    boundaryRectangleSectionSubHeaderPhysIndex );
         return NULL;
     }
-    
-    VSIFReadL( &boundaryRectangleTableOffset, 1, sizeof(boundaryRectangleTableOffset), fp);
+
+    unsigned int boundaryRectangleTableOffset;
+    bool bOK = VSIFReadL( &boundaryRectangleTableOffset, sizeof(boundaryRectangleTableOffset), 1, fp) == 1;
     CPL_MSBPTR32( &boundaryRectangleTableOffset );
-    
-    VSIFReadL( &boundaryRectangleCount, 1, sizeof(boundaryRectangleCount), fp);
+
+    unsigned short boundaryRectangleCount;
+    bOK &= VSIFReadL( &boundaryRectangleCount, sizeof(boundaryRectangleCount), 1, fp) == 1;
     CPL_MSBPTR16( &boundaryRectangleCount );
-    
-    if( VSIFSeekL( fp, boundaryRectangleTablePhysIndex, SEEK_SET ) != 0)
+
+    if( !bOK || VSIFSeekL( fp, boundaryRectangleTablePhysIndex, SEEK_SET ) != 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "Invalid TOC file. Unable to seek to boundaryRectangleTablePhysIndex at offset %d.",
                    boundaryRectangleTablePhysIndex );
         return NULL;
     }
-    
-    toc = (RPFToc*)CPLMalloc(sizeof(RPFToc));
+
+    RPFToc* toc = reinterpret_cast<RPFToc *>( CPLMalloc( sizeof( RPFToc ) ) );
     toc->nEntries = boundaryRectangleCount;
-    toc->entries = (RPFTocEntry*)CPLMalloc(boundaryRectangleCount * sizeof(RPFTocEntry));
+    toc->entries = reinterpret_cast<RPFTocEntry *>(
+        CPLMalloc( boundaryRectangleCount * sizeof(RPFTocEntry) ) );
     memset(toc->entries, 0, boundaryRectangleCount * sizeof(RPFTocEntry));
-    
-    for(i=0;i<toc->nEntries;i++)
+
+    for( int i = 0; i < toc->nEntries; i++ )
     {
         toc->entries[i].isOverviewOrLegend = 0;
-        
-        VSIFReadL( toc->entries[i].type, 1, 5, fp);
+
+        bOK &= VSIFReadL( toc->entries[i].type, 1, 5, fp) == 5;
         toc->entries[i].type[5] = 0;
         RPFTOCTrim(toc->entries[i].type);
-        
-        VSIFReadL( toc->entries[i].compression, 1, 5, fp);
+
+        bOK &= VSIFReadL( toc->entries[i].compression, 1, 5, fp) == 5;
         toc->entries[i].compression[5] = 0;
         RPFTOCTrim(toc->entries[i].compression);
-        
-        VSIFReadL( toc->entries[i].scale, 1, 12, fp);
+
+        bOK &= VSIFReadL( toc->entries[i].scale, 1, 12, fp) == 12;
         toc->entries[i].scale[12] = 0;
         RPFTOCTrim(toc->entries[i].scale);
         if (toc->entries[i].scale[0] == '1' &&
@@ -251,141 +238,178 @@ RPFToc* RPFTOCReadFromBuffer(const char* pszFilename, VSILFILE* fp, const char*
                     toc->entries[i].scale+2,
                     strlen(toc->entries[i].scale+2)+1);
         }
-        
-        VSIFReadL( toc->entries[i].zone, 1, 1, fp);
+
+        bOK &= VSIFReadL( toc->entries[i].zone, 1, 1, fp) == 1;
         toc->entries[i].zone[1] = 0;
         RPFTOCTrim(toc->entries[i].zone);
-        
-        VSIFReadL( toc->entries[i].producer, 1, 5, fp);
+
+        bOK &= VSIFReadL( toc->entries[i].producer, 1, 5, fp) == 5;
         toc->entries[i].producer[5] = 0;
         RPFTOCTrim(toc->entries[i].producer);
 
-        VSIFReadL( &toc->entries[i].nwLat, 1, sizeof(double), fp);
+        bOK &= VSIFReadL( &toc->entries[i].nwLat, sizeof(double), 1, fp) == 1;
         CPL_MSBPTR64( &toc->entries[i].nwLat);
 
-        VSIFReadL( &toc->entries[i].nwLong, 1, sizeof(double), fp);
+        bOK &= VSIFReadL( &toc->entries[i].nwLong, sizeof(double), 1, fp) == 1;
         CPL_MSBPTR64( &toc->entries[i].nwLong);
 
-        VSIFReadL( &toc->entries[i].swLat, 1, sizeof(double), fp);
+        bOK &= VSIFReadL( &toc->entries[i].swLat, sizeof(double), 1, fp) == 1;
         CPL_MSBPTR64( &toc->entries[i].swLat);
 
-        VSIFReadL( &toc->entries[i].swLong, 1, sizeof(double), fp);
+        bOK &= VSIFReadL( &toc->entries[i].swLong, sizeof(double), 1, fp) == 1;
         CPL_MSBPTR64( &toc->entries[i].swLong);
 
-        VSIFReadL( &toc->entries[i].neLat, 1, sizeof(double), fp);
+        bOK &= VSIFReadL( &toc->entries[i].neLat, sizeof(double), 1, fp) == 1;
         CPL_MSBPTR64( &toc->entries[i].neLat);
 
-        VSIFReadL( &toc->entries[i].neLong, 1, sizeof(double), fp);
+        bOK &= VSIFReadL( &toc->entries[i].neLong, sizeof(double), 1, fp) == 1;
         CPL_MSBPTR64( &toc->entries[i].neLong);
 
-        VSIFReadL( &toc->entries[i].seLat, 1, sizeof(double), fp);
+        bOK &= VSIFReadL( &toc->entries[i].seLat, sizeof(double), 1, fp) == 1;
         CPL_MSBPTR64( &toc->entries[i].seLat);
-        
-        VSIFReadL( &toc->entries[i].seLong, 1, sizeof(double), fp);
+
+        bOK &= VSIFReadL( &toc->entries[i].seLong, sizeof(double), 1, fp) == 1;
         CPL_MSBPTR64( &toc->entries[i].seLong);
-        
-        VSIFReadL( &toc->entries[i].vertResolution, 1, sizeof(double), fp);
+
+        bOK &= VSIFReadL( &toc->entries[i].vertResolution, sizeof(double), 1, fp) == 1;
         CPL_MSBPTR64( &toc->entries[i].vertResolution);
-        
-        VSIFReadL( &toc->entries[i].horizResolution, 1, sizeof(double), fp);
+
+        bOK &= VSIFReadL( &toc->entries[i].horizResolution, sizeof(double), 1, fp) == 1;
         CPL_MSBPTR64( &toc->entries[i].horizResolution);
-        
-        VSIFReadL( &toc->entries[i].vertInterval, 1, sizeof(double), fp);
+
+        bOK &= VSIFReadL( &toc->entries[i].vertInterval, sizeof(double), 1, fp) == 1;
         CPL_MSBPTR64( &toc->entries[i].vertInterval);
 
-        VSIFReadL( &toc->entries[i].horizInterval, 1, sizeof(double), fp);
+        bOK &= VSIFReadL( &toc->entries[i].horizInterval, sizeof(double), 1, fp) == 1;
         CPL_MSBPTR64( &toc->entries[i].horizInterval);
-        
-        VSIFReadL( &toc->entries[i].nVertFrames, 1, sizeof(int), fp);
+
+        bOK &= VSIFReadL( &toc->entries[i].nVertFrames, sizeof(int), 1, fp) == 1;
         CPL_MSBPTR32( &toc->entries[i].nVertFrames );
-        
-        VSIFReadL( &toc->entries[i].nHorizFrames, 1, sizeof(int), fp);
+
+        bOK &= VSIFReadL( &toc->entries[i].nHorizFrames, sizeof(int), 1, fp) == 1;
         CPL_MSBPTR32( &toc->entries[i].nHorizFrames );
-        
-        toc->entries[i].frameEntries = (RPFTocFrameEntry*)
-                VSIMalloc3(toc->entries[i].nVertFrames, toc->entries[i].nHorizFrames, sizeof(RPFTocFrameEntry));
+
+        if( !bOK )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+            toc->entries[i].nVertFrames = 0;
+            toc->entries[i].nHorizFrames = 0;
+            RPFTOCFree(toc);
+            return NULL;
+        }
+
+        if( toc->entries[i].nHorizFrames == 0 ||
+            toc->entries[i].nVertFrames == 0 ||
+            toc->entries[i].nHorizFrames > INT_MAX / toc->entries[i].nVertFrames )
+        {
+            toc->entries[i].frameEntries = NULL;
+        }
+        else
+        {
+            toc->entries[i].frameEntries = reinterpret_cast<RPFTocFrameEntry*>(
+                VSI_CALLOC_VERBOSE( toc->entries[i].nVertFrames * toc->entries[i].nHorizFrames,
+                                    sizeof(RPFTocFrameEntry) ) );
+        }
         if (toc->entries[i].frameEntries == NULL)
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory,
-                      "RPFTOCReadFromBuffer : Out of memory. Probably due to corrupted TOC file.");
+            toc->entries[i].nVertFrames = 0;
+            toc->entries[i].nHorizFrames = 0;
             RPFTOCFree(toc);
             return NULL;
         }
-        memset(toc->entries[i].frameEntries, 0,
-               toc->entries[i].nVertFrames * toc->entries[i].nHorizFrames * sizeof(RPFTocFrameEntry));
-        
+
         CPLDebug("RPFTOC", "[%d] type=%s, compression=%s, scale=%s, zone=%s, producer=%s, nVertFrames=%d, nHorizFrames=%d",
                  i, toc->entries[i].type, toc->entries[i].compression, toc->entries[i].scale,
                  toc->entries[i].zone, toc->entries[i].producer, toc->entries[i].nVertFrames, toc->entries[i].nHorizFrames);
     }
-    
+
     if( VSIFSeekL( fp, frameFileIndexSectionSubHeaderPhysIndex, SEEK_SET ) != 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "Invalid TOC file. Unable to seek to frameFileIndexSectionSubHeaderPhysIndex at offset %d.",
                    frameFileIndexSectionSubHeaderPhysIndex );
         RPFTOCFree(toc);
         return NULL;
     }
-    
+
     /* Skip 1 byte security classification */
-    VSIFSeekL( fp, 1, SEEK_CUR );
-    
-    VSIFReadL( &frameIndexTableOffset, 1, sizeof(frameIndexTableOffset), fp);
+    bOK &= VSIFSeekL( fp, 1, SEEK_CUR ) == 0;
+
+    unsigned int frameIndexTableOffset;
+    bOK &= VSIFReadL( &frameIndexTableOffset, sizeof(frameIndexTableOffset), 1, fp) == 1;
     CPL_MSBPTR32( &frameIndexTableOffset );
-    
-    VSIFReadL( &nFrameFileIndexRecords, 1, sizeof(nFrameFileIndexRecords), fp);
+
+    unsigned int nFrameFileIndexRecords;
+    bOK &= VSIFReadL( &nFrameFileIndexRecords, sizeof(nFrameFileIndexRecords), 1, fp) == 1;
     CPL_MSBPTR32( &nFrameFileIndexRecords );
-    
-    VSIFReadL( &nFrameFilePathnameRecords, 1, sizeof(nFrameFilePathnameRecords), fp);
+
+    unsigned short nFrameFilePathnameRecords;
+    bOK &= VSIFReadL( &nFrameFilePathnameRecords, sizeof(nFrameFilePathnameRecords), 1, fp) == 1;
     CPL_MSBPTR16( &nFrameFilePathnameRecords );
-    
-    VSIFReadL( &frameFileIndexRecordLength, 1, sizeof(frameFileIndexRecordLength), fp);
+
+    unsigned short frameFileIndexRecordLength;
+    bOK &= VSIFReadL( &frameFileIndexRecordLength, sizeof(frameFileIndexRecordLength), 1, fp) == 1;
     CPL_MSBPTR16( &frameFileIndexRecordLength );
-    
-    for (i=0;i<(int)nFrameFileIndexRecords;i++)
+
+    if( !bOK )
+    {
+        CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        RPFTOCFree(toc);
+        return NULL;
+    }
+
+    int newBoundaryId = 0;
+
+    for( int i = 0; i < static_cast<int>( nFrameFileIndexRecords ); i++ )
     {
-        RPFTocEntry* entry;
-        RPFTocFrameEntry* frameEntry;
-        unsigned short boundaryId, frameRow, frameCol;
-        unsigned int offsetFrameFilePathName;
-        unsigned short pathLength;
-        
         if( VSIFSeekL( fp, frameFileIndexSubsectionPhysIndex + frameFileIndexRecordLength * i, SEEK_SET ) != 0)
         {
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                     "Invalid TOC file. Unable to seek to frameFileIndexSubsectionPhysIndex(%d) at offset %d.",
                      i, frameFileIndexSubsectionPhysIndex + frameFileIndexRecordLength * i);
             RPFTOCFree(toc);
             return NULL;
         }
 
-        VSIFReadL( &boundaryId, 1, sizeof(boundaryId), fp);
+        unsigned short boundaryId;
+        if( VSIFReadL( &boundaryId, sizeof(boundaryId), 1, fp) != 1 )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+            RPFTOCFree(toc);
+            return NULL;
+        }
         CPL_MSBPTR16( &boundaryId );
-        
+
         if (i == 0 && boundaryId == 0)
             newBoundaryId = 1;
         if (newBoundaryId == 0)
             boundaryId--;
-        
+
         if (boundaryId >= toc->nEntries)
         {
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                     "Invalid TOC file. Bad boundary id (%d) for frame file index %d.",
                      boundaryId, i);
             RPFTOCFree(toc);
             return NULL;
         }
-        
-        entry = &toc->entries[boundaryId];
+
+        RPFTocEntry* entry = &toc->entries[boundaryId];
         entry->boundaryId = boundaryId;
-        
-        VSIFReadL( &frameRow, 1, sizeof(frameRow), fp);
+
+        unsigned short frameRow;
+        bOK &= VSIFReadL( &frameRow, sizeof(frameRow), 1, fp) == 1;
         CPL_MSBPTR16( &frameRow );
-        
-        VSIFReadL( &frameCol, 1, sizeof(frameCol), fp);
-        CPL_MSBPTR16( &frameCol );
 
+        unsigned short frameCol;
+        bOK &= VSIFReadL( &frameCol, sizeof(frameCol), 1, fp) == 1;
+        CPL_MSBPTR16( &frameCol );
+        if( !bOK )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+            RPFTOCFree(toc);
+            return NULL;
+        }
 
         if (newBoundaryId == 0)
         {
@@ -397,32 +421,33 @@ RPFToc* RPFTOCReadFromBuffer(const char* pszFilename, VSILFILE* fp, const char*
             /* Trick so that frames are numbered north to south */
             frameRow = (unsigned short)((entry->nVertFrames-1) - frameRow);
         }
-   
+
         if (frameRow >= entry->nVertFrames)
         {
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                         "Invalid TOC file. Bad row num (%d) for frame file index %d.",
                         frameRow, i);
             RPFTOCFree(toc);
             return NULL;
         }
-        
+
         if (frameCol >= entry->nHorizFrames)
         {
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                         "Invalid TOC file. Bad col num (%d) for frame file index %d.",
                         frameCol, i);
             RPFTOCFree(toc);
             return NULL;
         }
 
-        frameEntry = &entry->frameEntries[frameRow * entry->nHorizFrames + frameCol ];
+        RPFTocFrameEntry* frameEntry
+            = &entry->frameEntries[frameRow * entry->nHorizFrames + frameCol ];
         frameEntry->frameRow = frameRow;
         frameEntry->frameCol = frameCol;
 
         if (frameEntry->exists)
         {
-            CPLError( CE_Warning, CPLE_AppDefined, 
+            CPLError( CE_Warning, CPLE_AppDefined,
                       "Frame entry(%d,%d) for frame file index %d was already found.",
                       frameRow, frameCol, i);
             CPLFree(frameEntry->directory);
@@ -431,16 +456,22 @@ RPFToc* RPFTOCReadFromBuffer(const char* pszFilename, VSILFILE* fp, const char*
             frameEntry->fullFilePath = NULL;
             frameEntry->exists = 0;
         }
-        
-        VSIFReadL( &offsetFrameFilePathName, 1, sizeof(offsetFrameFilePathName), fp);
+
+        unsigned int offsetFrameFilePathName;
+        bOK &= VSIFReadL( &offsetFrameFilePathName, sizeof(offsetFrameFilePathName), 1, fp) == 1;
         CPL_MSBPTR32( &offsetFrameFilePathName );
-        
 
-        VSIFReadL( frameEntry->filename, 1, 12, fp);
+        bOK &= VSIFReadL( frameEntry->filename, 1, 12, fp) == 12;
+        if( !bOK )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+            RPFTOCFree(toc);
+            return NULL;
+        }
         frameEntry->filename[12] = '\0';
 
         /* Check if the filename is an overview or legend */
-        for (j=0;j<12;j++)
+        for( int j = 0; j < 12; j++ )
         {
             if (strcmp(&(frameEntry->filename[j]),".OVR") == 0 ||
                 strcmp(&(frameEntry->filename[j]),".ovr") == 0 ||
@@ -451,7 +482,7 @@ RPFToc* RPFTOCReadFromBuffer(const char* pszFilename, VSILFILE* fp, const char*
                 break;
             }
         }
-        
+
         /* Extract series code */
         if (entry->seriesAbbreviation == NULL)
         {
@@ -464,36 +495,46 @@ RPFToc* RPFTOCReadFromBuffer(const char* pszFilename, VSILFILE* fp, const char*
         }
 
         /* Get file geo reference */
-        VSIFReadL( frameEntry->georef, 1, 6, fp);
+        bOK &= VSIFReadL( frameEntry->georef, 1, 6, fp) == 6;
         frameEntry->georef[6] = '\0';
 
         /* Go to start of pathname record */
         /* New path_off offset from start of frame file index section of TOC?? */
         /* Add pathoffset wrt frame file index table subsection (loc[3]) */
-        if( VSIFSeekL( fp, frameFileIndexSubsectionPhysIndex + offsetFrameFilePathName, SEEK_SET ) != 0)
+        if( !bOK || VSIFSeekL( fp, frameFileIndexSubsectionPhysIndex + offsetFrameFilePathName, SEEK_SET ) != 0)
         {
-            CPLError( CE_Failure, CPLE_NotSupported, 
-                    "Invalid TOC file. Unable to seek to frameFileIndexSubsectionPhysIndex + offsetFrameFilePathName(%d) at offset %d.",
+            CPLError( CE_Failure, CPLE_NotSupported,
+                      "Invalid TOC file. Unable to seek to "
+                      "frameFileIndexSubsectionPhysIndex + "
+                      "offsetFrameFilePathName(%d) at offset %d.",
                      i, frameFileIndexSubsectionPhysIndex + offsetFrameFilePathName);
             RPFTOCFree(toc);
             return NULL;
         }
 
-        VSIFReadL( &pathLength, 1, sizeof(pathLength), fp);
+        unsigned short pathLength;
+        bOK &= VSIFReadL( &pathLength, sizeof(pathLength), 1, fp) == 1;
         CPL_MSBPTR16( &pathLength );
-        
+
         /* if nFrameFileIndexRecords == 65535 and pathLength == 65535 for each record,
            this leads to 4 GB allocation... Protect against this case */
-        if (pathLength > 256)
+        if (!bOK || pathLength > 256)
         {
             CPLError( CE_Failure, CPLE_NotSupported,
-                      "Path length is big : %d. Probably corrupted TOC file.", (int)pathLength);
+                      "Path length is big : %d. Probably corrupted TOC file.",
+                      static_cast<int>( pathLength ) );
+            RPFTOCFree(toc);
+            return NULL;
+        }
+
+        frameEntry->directory = reinterpret_cast<char *>( CPLMalloc(pathLength+1) );
+        bOK &= VSIFReadL( frameEntry->directory, 1, pathLength, fp) == pathLength;
+        if( !bOK )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
             RPFTOCFree(toc);
             return NULL;
         }
-        
-        frameEntry->directory = (char *)CPLMalloc(pathLength+1);
-        VSIFReadL( frameEntry->directory, 1, pathLength, fp);
         frameEntry->directory[pathLength] = 0;
         if (pathLength > 0 && frameEntry->directory[pathLength-1] == '/')
             frameEntry->directory[pathLength-1] = 0;
@@ -503,7 +544,7 @@ RPFToc* RPFTOCReadFromBuffer(const char* pszFilename, VSILFILE* fp, const char*
             memmove(frameEntry->directory, frameEntry->directory+2, strlen(frameEntry->directory+2)+1);
 
             // Some A.TOC have subdirectory names like ".//X/" ... (#5979)
-            // Check if it wasn't intended to be "./X/" instead
+            // Check if it was not intended to be "./X/" instead.
             VSIStatBufL sStatBuf;
             if( frameEntry->directory[0] == '/' &&
                 VSIStatL(CPLFormFilename(CPLGetDirname(pszFilename), frameEntry->directory+1, NULL), &sStatBuf) == 0 &&
@@ -524,7 +565,7 @@ RPFToc* RPFTOCReadFromBuffer(const char* pszFilename, VSILFILE* fp, const char*
             else
                 subdir = CPLStrdup(CPLFormFilename(baseDir, frameEntry->directory, NULL));
 #if !defined(_WIN32) && !defined(_WIN32_CE)
-            if( VSIStatL( subdir, &sStatBuf ) != 0 && subdir[strlen(baseDir)] != 0)
+            if( VSIStatL( subdir, &sStatBuf ) != 0 && strlen(subdir) > strlen(baseDir) && subdir[strlen(baseDir)] != 0)
             {
                 char* c = subdir + strlen(baseDir)+1;
                 while(*c)
@@ -552,7 +593,7 @@ RPFToc* RPFTOCReadFromBuffer(const char* pszFilename, VSILFILE* fp, const char*
 #endif
                 {
                     frameEntry->fileExists = 0;
-                    CPLError( CE_Warning, CPLE_AppDefined, 
+                    CPLError( CE_Warning, CPLE_AppDefined,
                         "File %s does not exist.", frameEntry->fullFilePath );
                 }
 #if !defined(_WIN32) && !defined(_WIN32_CE)
@@ -574,7 +615,7 @@ RPFToc* RPFTOCReadFromBuffer(const char* pszFilename, VSILFILE* fp, const char*
 
         frameEntry->exists = 1;
     }
-    
+
     return toc;
 }
 
@@ -584,12 +625,15 @@ RPFToc* RPFTOCReadFromBuffer(const char* pszFilename, VSILFILE* fp, const char*
 
 void RPFTOCFree(RPFToc*  toc)
 {
-    int i, j;
-    if (!toc) return;
+    if (!toc)
+        return;
 
-    for(i=0;i<toc->nEntries;i++)
+    for( int i = 0; i < toc->nEntries; i++ )
     {
-        for(j=0;j<(int)(toc->entries[i].nVertFrames * toc->entries[i].nHorizFrames); j++)
+        for( int j = 0;
+             j < static_cast<int>(toc->entries[i].nVertFrames
+                       * toc->entries[i].nHorizFrames);
+             j++)
         {
             CPLFree(toc->entries[i].frameEntries[j].fullFilePath);
             CPLFree(toc->entries[i].frameEntries[j].directory);
diff --git a/frmts/nitf/rpftoclib.h b/frmts/nitf/rpftoclib.h
index 2478de0..1566e4b 100644
--- a/frmts/nitf/rpftoclib.h
+++ b/frmts/nitf/rpftoclib.h
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: rpftoclib.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: rpftoclib.h 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  RPF A.TOC read Library
- * Purpose:  Main GDAL independent include file for RPF TOC support.  
+ * Purpose:  Main GDAL independent include file for RPF TOC support.
  * Author:   Even Rouault, even.rouault at mines-paris.org
  *
  **********************************************************************
@@ -30,13 +30,12 @@
 #ifndef RPFTOCLIB_H_INCLUDED
 #define RPFTOCLIB_H_INCLUDED
 
-#include "nitflib.h"
-
-#include "cpl_port.h"
 #include "cpl_error.h"
+#include "cpl_port.h"
 
-CPL_C_START
+#include "nitflib.h"
 
+CPL_C_START
 
 typedef struct
 {
@@ -50,7 +49,6 @@ typedef struct
   char            *fullFilePath;
 } RPFTocFrameEntry;
 
-
 typedef struct
 {
     char          type[5+1];
@@ -72,10 +70,10 @@ typedef struct
     double        horizInterval;
     unsigned int  nVertFrames;
     unsigned int  nHorizFrames;
-    
+
     int           boundaryId;
     int           isOverviewOrLegend;
-    
+
     const char*   seriesAbbreviation;  /* (may be NULL) eg "GNC" */
     const char*   seriesName;          /* (may be NULL) eg "Global Navigation Chart" */
 
@@ -103,4 +101,3 @@ void       CPL_DLL  RPFTOCFree(RPFToc*  nitfToc);
 CPL_C_END
 
 #endif /* ndef RPFTOCLIB_H_INCLUDED */
-
diff --git a/frmts/northwood/grcdataset.cpp b/frmts/northwood/grcdataset.cpp
index 868e7f7..b3851a6 100644
--- a/frmts/northwood/grcdataset.cpp
+++ b/frmts/northwood/grcdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: grcdataset.cpp 28502 2015-02-16 16:55:20Z rouault $
+ * $Id: grcdataset.cpp 33757 2016-03-20 20:22:33Z goatbar $
  *
  * Project:  GRC Reader
  * Purpose:  GDAL driver for Northwood Classified Format
@@ -28,20 +28,16 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 #include "northwood.h"
 
-#ifdef OGR_ENABLED
 #ifdef MSVC
 #include "..\..\ogr\ogrsf_frmts\mitab\mitab.h"
 #else
 #include "../../ogr/ogrsf_frmts/mitab/mitab.h"
 #endif
-#endif
-
 
-CPL_C_START void GDALRegister_NWT_GRC( void );
-CPL_C_END
 /************************************************************************/
 /* ==================================================================== */
 /*                             NWT_GRCDataset                           */
@@ -102,17 +98,17 @@ class NWT_GRCRasterBand : public GDALPamRasterBand
 /*                           NWT_GRCRasterBand()                        */
 /************************************************************************/
 
-NWT_GRCRasterBand::NWT_GRCRasterBand( NWT_GRCDataset * poDS, int nBand )
+NWT_GRCRasterBand::NWT_GRCRasterBand( NWT_GRCDataset * poDSIn, int nBandIn )
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
-    NWT_GRCDataset *poGDS =( NWT_GRCDataset * ) poDS;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
+    NWT_GRCDataset *poGDS = reinterpret_cast<NWT_GRCDataset *>( poDS );
 
     if( poGDS->pGrd->nBitsPerPixel == 8 )
         eDataType = GDT_Byte;
     else if( poGDS->pGrd->nBitsPerPixel == 16 )
         eDataType = GDT_UInt16;
-    else if( poGDS->pGrd->nBitsPerPixel == 32 )
+    else /* if( poGDS->pGrd->nBitsPerPixel == 32 ) */
         eDataType = GDT_UInt32;        // this would be funny
 
     nBlockXSize = poDS->GetRasterXSize();
@@ -130,25 +126,26 @@ NWT_GRCRasterBand::NWT_GRCRasterBand( NWT_GRCDataset * poDS, int nBand )
 
     poGDS->poColorTable->SetColorEntry( 0, &oEntry );
 
-    int i;
-    for( i=0; i < (int) poGDS->pGrd->stClassDict->nNumClassifiedItems; i++ )
+    for( int i = 0;
+         i < static_cast<int>( poGDS->pGrd->stClassDict->nNumClassifiedItems );
+         i++ )
     {
         oEntry.c1 = poGDS->pGrd->stClassDict->stClassifedItem[i]->r;
         oEntry.c2 = poGDS->pGrd->stClassDict->stClassifedItem[i]->g;
         oEntry.c3 = poGDS->pGrd->stClassDict->stClassifedItem[i]->b;
         oEntry.c4 = 0;            // alpha 0 = solid
 
-        poGDS->poColorTable->SetColorEntry( poDS->pGrd->
+        poGDS->poColorTable->SetColorEntry( poGDS->pGrd->
                                           stClassDict->stClassifedItem[i]->
                                           usPixVal, &oEntry );
     }
 
     // find the max value used in the grc
     int maxValue = 0;
-    for( i=0; i < (int) poDS->pGrd->stClassDict->nNumClassifiedItems; i++ )
+    for( int i=0; i < static_cast<int>( poGDS->pGrd->stClassDict->nNumClassifiedItems ); i++ )
     {
-        if( poDS->pGrd->stClassDict->stClassifedItem[i]->usPixVal > maxValue )
-            maxValue = poDS->pGrd->stClassDict->stClassifedItem[i]->usPixVal;
+        if( poGDS->pGrd->stClassDict->stClassifedItem[i]->usPixVal > maxValue )
+            maxValue = poGDS->pGrd->stClassDict->stClassifedItem[i]->usPixVal;
     }
 
     // load a value for the null value
@@ -158,42 +155,42 @@ NWT_GRCRasterBand::NWT_GRCRasterBand( NWT_GRCDataset * poDS, int nBand )
     // are not defined
     for( int val = 1; val <= maxValue; val++ )
     {
-        int i;
-        // loop throught the GRC dictionary to see if the value is defined
-        for( i=0; i < (int) poDS->pGrd->stClassDict->nNumClassifiedItems; i++ )
+        int i = 0;
+        // Loop through the GRC dictionary to see if the value is defined.
+        for( ;
+             i < static_cast<int>( poGDS->pGrd->stClassDict->nNumClassifiedItems );
+             i++ )
         {
-            if( (int) poDS->pGrd->stClassDict->stClassifedItem[i]->usPixVal ==
+            if( static_cast<int>( poGDS->pGrd->stClassDict->stClassifedItem[i]->usPixVal ) ==
                 val )
             {
                 poGDS->papszCategories =
                     CSLAddString( poGDS->papszCategories,
-                                    poDS->pGrd->stClassDict->
+                                    poGDS->pGrd->stClassDict->
                                     stClassifedItem[i]->szClassName );
                 break;
             }
         }
-        if( i >= (int) poDS->pGrd->stClassDict->nNumClassifiedItems )
+        if( i >= static_cast<int>( poGDS->pGrd->stClassDict->nNumClassifiedItems ) )
             poGDS->papszCategories = CSLAddString( poGDS->papszCategories, "" );
 
     }
 }
 
-NWT_GRCRasterBand::~NWT_GRCRasterBand()
-{
-}
+NWT_GRCRasterBand::~NWT_GRCRasterBand() {}
 
 double NWT_GRCRasterBand::GetNoDataValue( int *pbSuccess )
 {
     if( pbSuccess != NULL )
         *pbSuccess = TRUE;
 
-    return 0;                        //Northwood grid 0 is always null
+    return 0.0;  // Northwood grid 0 is always null.
 }
 
 // return an array of null terminated strings for the class names
 char **NWT_GRCRasterBand::GetCategoryNames()
 {
-    NWT_GRCDataset *poGDS = (NWT_GRCDataset *) poDS;
+    NWT_GRCDataset *poGDS = reinterpret_cast<NWT_GRCDataset *>( poDS );
 
     return poGDS->papszCategories;
 }
@@ -201,7 +198,7 @@ char **NWT_GRCRasterBand::GetCategoryNames()
 // return the color table
 GDALColorTable *NWT_GRCRasterBand::GetColorTable()
 {
-    NWT_GRCDataset *poGDS = (NWT_GRCDataset *) poDS;
+    NWT_GRCDataset *poGDS = reinterpret_cast<NWT_GRCDataset *>( poDS );
 
     return poGDS->poColorTable;
 }
@@ -210,8 +207,8 @@ GDALColorInterp NWT_GRCRasterBand::GetColorInterpretation()
 {
     if( nBand == 1 )
         return GCI_PaletteIndex;
-    else
-        return GCI_Undefined;
+
+    return GCI_Undefined;
 }
 
 /************************************************************************/
@@ -221,13 +218,17 @@ CPLErr NWT_GRCRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                                       int nBlockYOff,
                                       void *pImage )
 {
-    NWT_GRCDataset *poGDS =(NWT_GRCDataset *) poDS;
-    int nRecordSize = nBlockXSize *( poGDS->pGrd->nBitsPerPixel / 8 );
+    NWT_GRCDataset *poGDS = reinterpret_cast<NWT_GRCDataset *>( poDS );
+    const int nBytesPerPixel = poGDS->pGrd->nBitsPerPixel / 8;
+    if( nBytesPerPixel <= 0 || nBlockXSize > INT_MAX / nBytesPerPixel )
+        return CE_Failure;
+    const int nRecordSize = nBlockXSize * nBytesPerPixel;
 
     if( nBand == 1 )
     {                            //grc's are just one band of indices
         VSIFSeekL( poGDS->fp, 1024 + nRecordSize * (vsi_l_offset)nBlockYOff, SEEK_SET );
-        VSIFReadL( pImage, 1, nRecordSize, poGDS->fp );
+        if( (int)VSIFReadL( pImage, 1, nRecordSize, poGDS->fp ) != nRecordSize )
+            return CE_Failure;
     }
     else
     {
@@ -244,12 +245,10 @@ CPLErr NWT_GRCRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /*                          NWT_GRCDataset                              */
 /* ==================================================================== */
 /************************************************************************/
-NWT_GRCDataset::NWT_GRCDataset()
-{
-    poColorTable = NULL;
-    papszCategories = NULL;
-    pszProjection = NULL;
-}
+NWT_GRCDataset::NWT_GRCDataset() :
+    fp(NULL), pGrd(NULL), papszCategories(NULL), pszProjection(NULL),
+    poColorTable(NULL)
+{ }
 
 
 /************************************************************************/
@@ -291,18 +290,16 @@ CPLErr NWT_GRCDataset::GetGeoTransform( double *padfTransform )
 /************************************************************************/
 const char *NWT_GRCDataset::GetProjectionRef()
 {
-#ifdef OGR_ENABLED
     if (pszProjection == NULL)
     {
-        OGRSpatialReference *poSpatialRef;
-        poSpatialRef = MITABCoordSys2SpatialRef( pGrd->cMICoordSys );
+        OGRSpatialReference *poSpatialRef
+          = MITABCoordSys2SpatialRef( pGrd->cMICoordSys );
         if (poSpatialRef)
         {
             poSpatialRef->exportToWkt( &pszProjection );
             poSpatialRef->Release();
         }
     }
-#endif
     return ( (const char *) pszProjection );
 }
 
@@ -315,7 +312,7 @@ int NWT_GRCDataset::Identify( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*  Look for the header                                                 */
 /* -------------------------------------------------------------------- */
-    if( poOpenInfo->nHeaderBytes < 50 )
+    if( poOpenInfo->nHeaderBytes < 1024 )
         return FALSE;
 
     if( poOpenInfo->pabyHeader[0] != 'H' ||
@@ -340,9 +337,7 @@ GDALDataset *NWT_GRCDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    NWT_GRCDataset *poDS;
-
-    poDS = new NWT_GRCDataset();
+    NWT_GRCDataset *poDS = new NWT_GRCDataset();
 
     poDS->fp = VSIFOpenL(poOpenInfo->pszFilename, "rb");
     if (poDS->fp == NULL)
@@ -356,11 +351,11 @@ GDALDataset *NWT_GRCDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     VSIFSeekL( poDS->fp, 0, SEEK_SET );
     VSIFReadL( poDS->abyHeader, 1, 1024, poDS->fp );
-    poDS->pGrd = (NWT_GRID *) malloc( sizeof (NWT_GRID) );
+    poDS->pGrd = reinterpret_cast<NWT_GRID *>( malloc( sizeof (NWT_GRID) ) );
 
     poDS->pGrd->fp = poDS->fp;
 
-    if (!nwt_ParseHeader( poDS->pGrd, (char *) poDS->abyHeader ) ||
+    if (!nwt_ParseHeader( poDS->pGrd, reinterpret_cast<char *>( poDS->abyHeader ) ) ||
         !GDALCheckDatasetDimensions(poDS->pGrd->nXSide, poDS->pGrd->nYSide) ||
         poDS->pGrd->stClassDict == NULL)
     {
@@ -368,6 +363,14 @@ GDALDataset *NWT_GRCDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
+    if( poDS->pGrd->nBitsPerPixel != 8 &&
+        poDS->pGrd->nBitsPerPixel != 16 &&
+        poDS->pGrd->nBitsPerPixel != 32 )
+    {
+        delete poDS;
+        return NULL;
+    }
+
     poDS->nRasterXSize = poDS->pGrd->nXSide;
     poDS->nRasterYSize = poDS->pGrd->nYSide;
 
@@ -385,7 +388,9 @@ GDALDataset *NWT_GRCDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Check for external overviews.                                   */
 /* -------------------------------------------------------------------- */
-    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles() );
+    poDS->oOvManager.Initialize( poDS,
+                                 poOpenInfo->pszFilename,
+                                 poOpenInfo->GetSiblingFiles() );
 
     return (poDS);
 }
@@ -395,27 +400,25 @@ GDALDataset *NWT_GRCDataset::Open( GDALOpenInfo * poOpenInfo )
 /*                          GDALRegister_GRC()                          */
 /************************************************************************/
 
-void
-GDALRegister_NWT_GRC()
+void GDALRegister_NWT_GRC()
+
 {
-    GDALDriver *poDriver;
+    if( GDALGetDriverByName( "NWT_GRC" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "NWT_GRC" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "NWT_GRC" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                 "Northwood Classified Grid Format .grc/.tab");
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                 "frmt_various.html#northwood_grc" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "grc" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetDescription( "NWT_GRC" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Northwood Classified Grid Format .grc/.tab");
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_various.html#northwood_grc" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "grc" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = NWT_GRCDataset::Open;
-        poDriver->pfnIdentify = NWT_GRCDataset::Identify;
+    poDriver->pfnOpen = NWT_GRCDataset::Open;
+    poDriver->pfnIdentify = NWT_GRCDataset::Identify;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/northwood/grddataset.cpp b/frmts/northwood/grddataset.cpp
index 95b0873..832770c 100644
--- a/frmts/northwood/grddataset.cpp
+++ b/frmts/northwood/grddataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: grddataset.cpp 28502 2015-02-16 16:55:20Z rouault $
+ * $Id: grddataset.cpp 33757 2016-03-20 20:22:33Z goatbar $
  *
  * Project:  GRD Reader
  * Purpose:  GDAL driver for Northwood Grid Format
@@ -28,20 +28,16 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 #include "northwood.h"
 
-#ifdef OGR_ENABLED
 #ifdef MSVC
 #include "..\..\ogr\ogrsf_frmts\mitab\mitab.h"
 #else
 #include "../../ogr/ogrsf_frmts/mitab/mitab.h"
 #endif
-#endif
-
 
-CPL_C_START void GDALRegister_NWT_GRD( void );
-CPL_C_END
 /************************************************************************/
 /* ==================================================================== */
 /*                      NWT_GRDDataset                                  */
@@ -98,25 +94,25 @@ class NWT_GRDRasterBand:public GDALPamRasterBand
 /************************************************************************/
 /*                           NWT_GRDRasterBand()                        */
 /************************************************************************/
-NWT_GRDRasterBand::NWT_GRDRasterBand( NWT_GRDDataset * poDS, int nBand )
+NWT_GRDRasterBand::NWT_GRDRasterBand( NWT_GRDDataset * poDSIn, int nBandIn )
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
 
     if( nBand == 4 )
     {
         bHaveOffsetScale = TRUE;
-        dfOffset = poDS->pGrd->fZMin;
+        dfOffset = poDSIn->pGrd->fZMin;
 
-        if( poDS->pGrd->cFormat == 0x01 )
+        if( poDSIn->pGrd->cFormat == 0x01 )
         {
             eDataType = GDT_Float32;
-            dfScale =( poDS->pGrd->fZMax - poDS->pGrd->fZMin ) / 4294967294.0;
+            dfScale =( poDSIn->pGrd->fZMax - poDSIn->pGrd->fZMin ) / 4294967294.0;
         }
         else
         {
             eDataType = GDT_Float32;
-            dfScale =( poDS->pGrd->fZMax - poDS->pGrd->fZMin ) / 65534.0;
+            dfScale =( poDSIn->pGrd->fZMax - poDSIn->pGrd->fZMin ) / 65534.0;
         }
     }
     else
@@ -137,15 +133,13 @@ double NWT_GRDRasterBand::GetNoDataValue( int *pbSuccess )
         if( pbSuccess != NULL )
             *pbSuccess = TRUE;
 
-        return (float)-1.e37;
+        return -1.e37f;
     }
-    else
-    {
-        if( pbSuccess != NULL )
-            *pbSuccess = FALSE;
 
-        return 0;
-    }
+    if( pbSuccess != NULL )
+        *pbSuccess = FALSE;
+
+    return 0;
 }
 
 GDALColorInterp NWT_GRDRasterBand::GetColorInterpretation()
@@ -159,8 +153,8 @@ GDALColorInterp NWT_GRDRasterBand::GetColorInterpretation()
         return GCI_GreenBand;
     else if( nBand == 3 )
         return GCI_BlueBand;
-    else
-        return GCI_Undefined;
+
+    return GCI_Undefined;
 }
 
 /************************************************************************/
@@ -170,58 +164,76 @@ CPLErr NWT_GRDRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                                       int nBlockYOff,
                                       void *pImage )
 {
-    NWT_GRDDataset *poGDS = (NWT_GRDDataset *) poDS;
-    char *pszRecord;
-    int nRecordSize = nBlockXSize * 2;
-    int i;
+    NWT_GRDDataset *poGDS = reinterpret_cast<NWT_GRDDataset *>( poDS );
+    if( nBlockXSize > INT_MAX / 2 )
+        return CE_Failure;
+    const int nRecordSize = nBlockXSize * 2;
     unsigned short raw1;
 
-    VSIFSeekL( poGDS->fp, 1024 + nRecordSize * (vsi_l_offset)nBlockYOff, SEEK_SET );
+    VSIFSeekL( poGDS->fp,
+               1024 + nRecordSize
+               * static_cast<vsi_l_offset>( nBlockYOff ),
+               SEEK_SET );
 
-    pszRecord = (char *) CPLMalloc( nRecordSize );
-    VSIFReadL( pszRecord, 1, nRecordSize, poGDS->fp );
+    GByte *pabyRecord = reinterpret_cast<GByte *>( VSI_MALLOC_VERBOSE( nRecordSize ) );
+	if( pabyRecord == NULL )
+		return CE_Failure;
+    if( (int)VSIFReadL( pabyRecord, 1, nRecordSize, poGDS->fp ) != nRecordSize )
+    {
+        CPLFree( pabyRecord );
+        return CE_Failure;
+    }
 
     if( nBand == 4 )                //Z values
     {
-        for( i = 0; i < nBlockXSize; i++ )
+        for( int i = 0; i < nBlockXSize; i++ )
         {
-            memcpy( (void *) &raw1, (void *)(pszRecord + 2 * i), 2 );
+            memcpy( reinterpret_cast<void *>( &raw1 ),
+                    reinterpret_cast<void *>(pabyRecord + 2 * i), 2 );
             CPL_LSBPTR16(&raw1);
             if( raw1 == 0 )
             {
-                ((float *)pImage)[i] = (float)-1.e37;    // null value
+              reinterpret_cast<float *>( pImage )[i] = -1.e37f;    // null value
             }
             else
             {
-                ((float *)pImage)[i] = (float) (dfOffset + ((raw1 - 1) * dfScale));
+                reinterpret_cast<float *>( pImage )[i]
+                  = static_cast<float>( dfOffset + ((raw1 - 1) * dfScale) );
             }
         }
     }
     else if( nBand == 1 )            // red values
     {
-        for( i = 0; i < nBlockXSize; i++ )
+        for( int i = 0; i < nBlockXSize; i++ )
         {
-            memcpy( (void *) &raw1, (void *)(pszRecord + 2 * i), 2 );
+            memcpy( reinterpret_cast<void *>( &raw1 ),
+                    reinterpret_cast<void *>(pabyRecord + 2 * i),
+                    2 );
             CPL_LSBPTR16(&raw1);
-            ((char *)pImage)[i] = poGDS->ColorMap[raw1 / 16].r;
+            reinterpret_cast<char *>( pImage )[i]
+                = poGDS->ColorMap[raw1 / 16].r;
         }
     }
     else if( nBand == 2 )            // green
     {
-        for( i = 0; i < nBlockXSize; i++ )
+        for( int i = 0; i < nBlockXSize; i++ )
         {
-            memcpy( (void *) &raw1, (void *)(pszRecord + 2 * i), 2 );
+            memcpy( reinterpret_cast<void *> ( &raw1 ),
+                    reinterpret_cast<void *> ( pabyRecord + 2 * i ),
+                    2 );
             CPL_LSBPTR16(&raw1);
-            ((char *) pImage)[i] = poGDS->ColorMap[raw1 / 16].g;
+            reinterpret_cast<char *>( pImage )[i] = poGDS->ColorMap[raw1 / 16].g;
         }
     }
     else if( nBand == 3 )            // blue
     {
-        for( i = 0; i < nBlockXSize; i++ )
+        for( int i = 0; i < nBlockXSize; i++ )
         {
-            memcpy( (void *) &raw1, (void *) (pszRecord + 2 * i), 2 );
+            memcpy( reinterpret_cast<void *>( &raw1 ),
+                    reinterpret_cast<void *>( pabyRecord + 2 * i ),
+                    2 );
             CPL_LSBPTR16(&raw1);
-            ((char *) pImage)[i] = poGDS->ColorMap[raw1 / 16].b;
+            reinterpret_cast<char *>( pImage )[i] = poGDS->ColorMap[raw1 / 16].b;
         }
     }
     else
@@ -229,14 +241,12 @@ CPLErr NWT_GRDRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
         CPLError( CE_Failure, CPLE_IllegalArg,
                   "No band number %d",
                   nBand );
-        if( pszRecord != NULL )
-            CPLFree( pszRecord );
+        CPLFree( pabyRecord );
         return CE_Failure;
     }
-    if( pszRecord != NULL )
-    {
-        CPLFree( pszRecord );
-    }
+
+    CPLFree( pabyRecord );
+
     return CE_None;
 }
 
@@ -245,10 +255,19 @@ CPLErr NWT_GRDRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /*                             NWT_GRDDataset                           */
 /* ==================================================================== */
 /************************************************************************/
-NWT_GRDDataset::NWT_GRDDataset()
+
+NWT_GRDDataset::NWT_GRDDataset() :
+    fp(NULL),
+    pGrd(NULL),
+    pszProjection(NULL)
 {
-    pszProjection = NULL;
     //poCT = NULL;
+    for( size_t i=0; i < CPL_ARRAYSIZE(ColorMap); ++i )
+    {
+        ColorMap[i].r = 0;
+        ColorMap[i].g = 0;
+        ColorMap[i].b = 0;
+    }
 }
 
 
@@ -259,7 +278,7 @@ NWT_GRDDataset::NWT_GRDDataset()
 NWT_GRDDataset::~NWT_GRDDataset()
 {
     FlushCache();
-    pGrd->fp = NULL;       // this prevents nwtCloseGrid from closing the fp 
+    pGrd->fp = NULL;       // this prevents nwtCloseGrid from closing the fp
     nwtCloseGrid( pGrd );
 
     if( fp != NULL )
@@ -276,6 +295,7 @@ NWT_GRDDataset::~NWT_GRDDataset()
 /************************************************************************/
 /*                          GetGeoTransform()                           */
 /************************************************************************/
+
 CPLErr NWT_GRDDataset::GetGeoTransform( double *padfTransform )
 {
     padfTransform[0] = pGrd->dfMinX - ( pGrd->dfStepSize * 0.5 );
@@ -292,9 +312,9 @@ CPLErr NWT_GRDDataset::GetGeoTransform( double *padfTransform )
 /************************************************************************/
 /*                          GetProjectionRef()                          */
 /************************************************************************/
+
 const char *NWT_GRDDataset::GetProjectionRef()
 {
-#ifdef OGR_ENABLED
     if (pszProjection == NULL)
     {
         OGRSpatialReference *poSpatialRef;
@@ -305,8 +325,7 @@ const char *NWT_GRDDataset::GetProjectionRef()
             poSpatialRef->Release();
         }
     }
-#endif
-    return( (const char *)pszProjection );
+    return reinterpret_cast<const char *>( pszProjection );
 }
 
 /************************************************************************/
@@ -318,7 +337,7 @@ int NWT_GRDDataset::Identify( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*  Look for the header                                                 */
 /* -------------------------------------------------------------------- */
-    if( poOpenInfo->nHeaderBytes < 50 )
+    if( poOpenInfo->nHeaderBytes < 1024 )
         return FALSE;
 
     if( poOpenInfo->pabyHeader[0] != 'H' ||
@@ -358,11 +377,11 @@ GDALDataset *NWT_GRDDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     VSIFSeekL( poDS->fp, 0, SEEK_SET );
     VSIFReadL( poDS->abyHeader, 1, 1024, poDS->fp );
-    poDS->pGrd = (NWT_GRID *) malloc(sizeof(NWT_GRID));
+    poDS->pGrd = reinterpret_cast<NWT_GRID *>( malloc( sizeof( NWT_GRID ) ) );
 
     poDS->pGrd->fp = poDS->fp;
 
-    if (!nwt_ParseHeader( poDS->pGrd, (char *) poDS->abyHeader ) ||
+    if (!nwt_ParseHeader( poDS->pGrd, reinterpret_cast<char *>( poDS->abyHeader ) ) ||
         !GDALCheckDatasetDimensions(poDS->pGrd->nXSide, poDS->pGrd->nYSide) )
     {
         delete poDS;
@@ -372,10 +391,10 @@ GDALDataset *NWT_GRDDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->nRasterXSize = poDS->pGrd->nXSide;
     poDS->nRasterYSize = poDS->pGrd->nYSide;
 
-// create a colorTable
-  // if( poDS->pGrd->iNumColorInflections > 0 )
-  //   poDS->CreateColorTable();
-  nwt_LoadColors( poDS->ColorMap, 4096, poDS->pGrd );
+    // create a colorTable
+    // if( poDS->pGrd->iNumColorInflections > 0 )
+    //   poDS->CreateColorTable();
+    nwt_LoadColors( poDS->ColorMap, 4096, poDS->pGrd );
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
@@ -393,7 +412,8 @@ GDALDataset *NWT_GRDDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Check for external overviews.                                   */
 /* -------------------------------------------------------------------- */
-    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles() );
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename,
+                                 poOpenInfo->GetSiblingFiles() );
 
     return (poDS);
 }
@@ -404,23 +424,21 @@ GDALDataset *NWT_GRDDataset::Open( GDALOpenInfo * poOpenInfo )
 /************************************************************************/
 void GDALRegister_NWT_GRD()
 {
-    GDALDriver *poDriver;
+    if( GDALGetDriverByName( "NWT_GRD" ) != NULL )
+      return;
 
-    if( GDALGetDriverByName( "NWT_GRD" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "NWT_GRD" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                 "Northwood Numeric Grid Format .grd/.tab" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#grd");
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "grd" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetDescription( "NWT_GRD" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Northwood Numeric Grid Format .grd/.tab" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#grd");
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "grd" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = NWT_GRDDataset::Open;
-        poDriver->pfnIdentify = NWT_GRDDataset::Identify;
+    poDriver->pfnOpen = NWT_GRDDataset::Open;
+    poDriver->pfnIdentify = NWT_GRDDataset::Identify;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/northwood/northwood.cpp b/frmts/northwood/northwood.cpp
index de08f58..798f88a 100644
--- a/frmts/northwood/northwood.cpp
+++ b/frmts/northwood/northwood.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: northwood.cpp 30004 2015-09-01 08:17:04Z rouault $
+ * $Id: northwood.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  GRC/GRD Reader
  * Purpose:  Northwood Format basic implementation
@@ -28,20 +28,15 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-
-//#ifndef MSVC
 #include "gdal_pam.h"
-//#endif
 
 #include "northwood.h"
 
+#include <algorithm>
 
 int nwt_ParseHeader( NWT_GRID * pGrd, char *nwtHeader )
 {
-    int i;
-    unsigned short usTmp;
     /* double dfTmp; */
-    unsigned char cTmp[256];
 
     if( nwtHeader[4] == '1' )
         pGrd->cFormat = 0x00;        // grd - surface type
@@ -50,65 +45,86 @@ int nwt_ParseHeader( NWT_GRID * pGrd, char *nwtHeader )
 
     pGrd->stClassDict = NULL;
 
-    memcpy( (void *) &pGrd->fVersion, (void *) &nwtHeader[5],
-              sizeof(pGrd->fVersion) );
+    memcpy( reinterpret_cast<void *>( &pGrd->fVersion ),
+            reinterpret_cast<void *>( &nwtHeader[5] ),
+            sizeof( pGrd->fVersion ) );
     CPL_LSBPTR32(&pGrd->fVersion);
 
-    memcpy( (void *) &usTmp, (void *) &nwtHeader[9], 2 );
+    unsigned short usTmp;
+    memcpy( reinterpret_cast<void *>( &usTmp ),
+            reinterpret_cast<void *>( &nwtHeader[9] ),
+            2 );
     CPL_LSBPTR16(&usTmp);
-    pGrd->nXSide = (unsigned int) usTmp;
+    pGrd->nXSide = static_cast<unsigned int>( usTmp );
     if( pGrd->nXSide == 0 )
     {
-        memcpy( (void *) &pGrd->nXSide, (void *) &nwtHeader[128],
+        memcpy( reinterpret_cast<void *>( &pGrd->nXSide ),
+                reinterpret_cast<void *>( &nwtHeader[128] ),
                 sizeof(pGrd->nXSide) );
         CPL_LSBPTR32(&pGrd->nXSide);
     }
 
-    memcpy( (void *) &usTmp, (void *) &nwtHeader[11], 2 );
+    memcpy( reinterpret_cast<void *>( &usTmp ),
+            reinterpret_cast<void *>( &nwtHeader[11] ),
+            2 );
     CPL_LSBPTR16(&usTmp);
-    pGrd->nYSide = (unsigned int) usTmp;
+    pGrd->nYSide = static_cast<unsigned int>( usTmp );
     if( pGrd->nYSide == 0 )
     {
-        memcpy( (void *) &pGrd->nYSide, (void *) &nwtHeader[132],
-                sizeof(pGrd->nYSide) );
+        memcpy( reinterpret_cast<void *>( &pGrd->nYSide ),
+                reinterpret_cast<void *>( &nwtHeader[132] ),
+                sizeof( pGrd->nYSide ) );
         CPL_LSBPTR32(&pGrd->nYSide);
     }
 
-    memcpy( (void *) &pGrd->dfMinX, (void *) &nwtHeader[13],
+    memcpy( reinterpret_cast<void *>( &pGrd->dfMinX ),
+            reinterpret_cast<void *>( &nwtHeader[13] ),
             sizeof(pGrd->dfMinX) );
     CPL_LSBPTR64(&pGrd->dfMinX);
-    memcpy( (void *) &pGrd->dfMaxX, (void *) &nwtHeader[21],
+    memcpy( reinterpret_cast<void *>( &pGrd->dfMaxX ),
+            reinterpret_cast<void *>( &nwtHeader[21] ),
             sizeof(pGrd->dfMaxX) );
     CPL_LSBPTR64(&pGrd->dfMaxX);
-    memcpy( (void *) &pGrd->dfMinY, (void *) &nwtHeader[29],
+    memcpy( reinterpret_cast<void *>( &pGrd->dfMinY ),
+            reinterpret_cast<void *>( &nwtHeader[29] ),
             sizeof(pGrd->dfMinY) );
     CPL_LSBPTR64(&pGrd->dfMinY);
-    memcpy( (void *) &pGrd->dfMaxY, (void *) &nwtHeader[37],
+    memcpy( reinterpret_cast<void *>( &pGrd->dfMaxY ),
+            reinterpret_cast<void *>( &nwtHeader[37] ),
             sizeof(pGrd->dfMaxY) );
     CPL_LSBPTR64(&pGrd->dfMaxY);
 
     pGrd->dfStepSize = (pGrd->dfMaxX - pGrd->dfMinX) / (pGrd->nXSide - 1);
     /* dfTmp = (pGrd->dfMaxY - pGrd->dfMinY) / (pGrd->nYSide - 1); */
 
-    memcpy( (void *) &pGrd->fZMin, (void *) &nwtHeader[45],
+    memcpy( reinterpret_cast<void *>( &pGrd->fZMin ),
+            reinterpret_cast<void *>( &nwtHeader[45] ),
             sizeof(pGrd->fZMin) );
     CPL_LSBPTR32(&pGrd->fZMin);
-    memcpy( (void *) &pGrd->fZMax, (void *) &nwtHeader[49],
+    memcpy( reinterpret_cast<void *>( &pGrd->fZMax ),
+            reinterpret_cast<void *>( &nwtHeader[49] ),
             sizeof(pGrd->fZMax) );
     CPL_LSBPTR32(&pGrd->fZMax);
-    memcpy( (void *) &pGrd->fZMinScale, (void *) &nwtHeader[53],
+    memcpy( reinterpret_cast<void *>( &pGrd->fZMinScale ),
+            reinterpret_cast<void *>( &nwtHeader[53] ),
             sizeof(pGrd->fZMinScale) );
     CPL_LSBPTR32(&pGrd->fZMinScale);
-    memcpy( (void *) &pGrd->fZMaxScale, (void *) &nwtHeader[57],
+    memcpy( reinterpret_cast<void *>( &pGrd->fZMaxScale ),
+            reinterpret_cast<void *>( &nwtHeader[57] ),
             sizeof(pGrd->fZMaxScale) );
     CPL_LSBPTR32(&pGrd->fZMaxScale);
 
-    memcpy( (void *) &pGrd->cDescription, (void *) &nwtHeader[61],
+    memcpy( reinterpret_cast<void *>( &pGrd->cDescription ),
+            reinterpret_cast<void *>( &nwtHeader[61] ),
             sizeof(pGrd->cDescription) );
-    memcpy( (void *) &pGrd->cZUnits, (void *) &nwtHeader[93],
+    memcpy( reinterpret_cast<void *>( &pGrd->cZUnits ),
+            reinterpret_cast<void *>( &nwtHeader[93] ),
             sizeof(pGrd->cZUnits) );
 
-    memcpy( (void *) &i, (void *) &nwtHeader[136], 4 );
+    int i;
+    memcpy( reinterpret_cast<void *>( &i ),
+            reinterpret_cast<void *>( &nwtHeader[136] ),
+            4 );
     CPL_LSBPTR32(&i);
 
     if( i == 1129336130 )
@@ -120,7 +136,8 @@ int nwt_ParseHeader( NWT_GRID * pGrd, char *nwtHeader )
         }
     }
 
-    memcpy( (void *) &pGrd->cMICoordSys, (void *) &nwtHeader[256],
+    memcpy( reinterpret_cast<void *>( &pGrd->cMICoordSys ),
+            reinterpret_cast<void *>( &nwtHeader[256] ),
             sizeof(pGrd->cMICoordSys) );
     pGrd->cMICoordSys[sizeof(pGrd->cMICoordSys)-1] = '\0';
 
@@ -135,35 +152,37 @@ int nwt_ParseHeader( NWT_GRID * pGrd, char *nwtHeader )
     if( nwtHeader[513] & 0x20 )
         pGrd->bHillShadeExists = true;
 
-    memcpy( (void *) &pGrd->iNumColorInflections, (void *) &nwtHeader[516],
+    memcpy( reinterpret_cast<void *>( &pGrd->iNumColorInflections ),
+            reinterpret_cast<void *>( &nwtHeader[516] ),
             2 );
     CPL_LSBPTR16(&pGrd->iNumColorInflections);
 
     if (pGrd->iNumColorInflections > 32)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Corrupt header");
-        pGrd->iNumColorInflections = (unsigned short)i;
+        pGrd->iNumColorInflections = 0;
         return FALSE;
     }
-    
+
     for( i = 0; i < pGrd->iNumColorInflections; i++ )
     {
-        
-        memcpy( (void *) &pGrd->stInflection[i].zVal,
-                (void *) &nwtHeader[518 + (7 * i)], 4 );
+        memcpy( reinterpret_cast<void *>( &pGrd->stInflection[i].zVal ),
+                reinterpret_cast<void *>( &nwtHeader[518 + (7 * i)] ), 4 );
         CPL_LSBPTR32(&pGrd->stInflection[i].zVal);
-        memcpy( (void *) &pGrd->stInflection[i].r,
-                (void *) &nwtHeader[522 + (7 * i)], 1 );
-        memcpy( (void *) &pGrd->stInflection[i].g,
-                (void *) &nwtHeader[523 + (7 * i)], 1 );
-        memcpy( (void *) &pGrd->stInflection[i].b,
-                (void *) &nwtHeader[524 + (7 * i)], 1 );
+        memcpy( reinterpret_cast<void *>( &pGrd->stInflection[i].r ),
+                reinterpret_cast<void *>( &nwtHeader[522 + (7 * i)] ), 1 );
+        memcpy( reinterpret_cast<void *>( &pGrd->stInflection[i].g ),
+                reinterpret_cast<void *>( &nwtHeader[523 + (7 * i)] ), 1 );
+        memcpy( reinterpret_cast<void *>( &pGrd->stInflection[i].b ),
+                reinterpret_cast<void *>( &nwtHeader[524 + (7 * i)] ), 1 );
     }
 
-    memcpy( (void *) &pGrd->fHillShadeAzimuth, (void *) &nwtHeader[966],
+    memcpy( reinterpret_cast<void *>( &pGrd->fHillShadeAzimuth ),
+            reinterpret_cast<void *>( &nwtHeader[966] ),
             sizeof(pGrd->fHillShadeAzimuth) );
     CPL_LSBPTR32(&pGrd->fHillShadeAzimuth);
-    memcpy( (void *) &pGrd->fHillShadeAngle, (void *) &nwtHeader[970],
+    memcpy( reinterpret_cast<void *>( &pGrd->fHillShadeAngle ),
+            reinterpret_cast<void *>( &nwtHeader[970] ),
             sizeof(pGrd->fHillShadeAngle) );
     CPL_LSBPTR32(&pGrd->fHillShadeAngle);
 
@@ -190,54 +209,56 @@ int nwt_ParseHeader( NWT_GRID * pGrd, char *nwtHeader )
 
         if( !VSIFReadL( &usTmp, 2, 1, pGrd->fp) )
         {
-            CPLError( CE_Failure, CPLE_FileIO, 
+            CPLError( CE_Failure, CPLE_FileIO,
                       "Read failure, file short?" );
             return FALSE;
         }
         CPL_LSBPTR16(&usTmp);
-        pGrd->stClassDict =
-            (NWT_CLASSIFIED_DICT *) calloc( sizeof(NWT_CLASSIFIED_DICT), 1 );
+        pGrd->stClassDict = reinterpret_cast<NWT_CLASSIFIED_DICT *>(
+             calloc( sizeof(NWT_CLASSIFIED_DICT), 1 ) );
 
         pGrd->stClassDict->nNumClassifiedItems = usTmp;
 
-        pGrd->stClassDict->stClassifedItem =
-            (NWT_CLASSIFIED_ITEM **) calloc( sizeof(NWT_CLASSIFIED_ITEM *),
-                                             pGrd->
-                                             stClassDict->nNumClassifiedItems +
-                                             1 );
+        pGrd->stClassDict->stClassifedItem
+            = reinterpret_cast<NWT_CLASSIFIED_ITEM **> (
+              calloc( sizeof(NWT_CLASSIFIED_ITEM *),
+                      pGrd->stClassDict->nNumClassifiedItems + 1 ) );
 
         //load the dictionary
         for( usTmp=0; usTmp < pGrd->stClassDict->nNumClassifiedItems; usTmp++ )
         {
-            NWT_CLASSIFIED_ITEM *psItem = 
+            NWT_CLASSIFIED_ITEM *psItem =
                 pGrd->stClassDict->stClassifedItem[usTmp] =
-                (NWT_CLASSIFIED_ITEM *) calloc(sizeof(NWT_CLASSIFIED_ITEM), 1);
+                reinterpret_cast<NWT_CLASSIFIED_ITEM *>(
+                    calloc(sizeof(NWT_CLASSIFIED_ITEM), 1) );
 
+            unsigned char cTmp[256];
             if( !VSIFReadL( &cTmp, 9, 1, pGrd->fp ) )
             {
-                CPLError( CE_Failure, CPLE_FileIO, 
+                CPLError( CE_Failure, CPLE_FileIO,
                           "Read failure, file short?" );
                 return FALSE;
             }
-            memcpy( (void *) &psItem->usPixVal, (void *) &cTmp[0], 2 );
+            memcpy( reinterpret_cast<void *>( &psItem->usPixVal ),
+                    reinterpret_cast<void *>( &cTmp[0]) , 2 );
             CPL_LSBPTR16(&psItem->usPixVal);
-            memcpy( (void *) &psItem->res1,
-                    (void *) &cTmp[2], 1 );
-            memcpy( (void *) &psItem->r,
-                    (void *) &cTmp[3], 1 );
-            memcpy( (void *) &psItem->g,
-                    (void *) &cTmp[4], 1 );
-            memcpy( (void *) &psItem->b,
-                    (void *) &cTmp[5], 1 );
-            memcpy( (void *) &psItem->res2,
-                    (void *) &cTmp[6], 1 );
-            memcpy( (void *) &psItem->usLen,
-                    (void *) &cTmp[7], 2 );
+            memcpy( reinterpret_cast<void *>( &psItem->res1 ),
+                    reinterpret_cast<void *>( &cTmp[2] ), 1 );
+            memcpy( reinterpret_cast<void *>( &psItem->r ),
+                    reinterpret_cast<void *>( &cTmp[3] ), 1 );
+            memcpy( reinterpret_cast<void *>( &psItem->g ),
+                    reinterpret_cast<void *>( &cTmp[4] ), 1 );
+            memcpy( reinterpret_cast<void *>( &psItem->b ),
+                    reinterpret_cast<void *>( &cTmp[5] ), 1 );
+            memcpy( reinterpret_cast<void *>( &psItem->res2 ),
+                    reinterpret_cast<void *>( &cTmp[6] ), 1 );
+            memcpy( reinterpret_cast<void *>( &psItem->usLen ),
+                    reinterpret_cast<void *>( &cTmp[7] ), 2 );
             CPL_LSBPTR16(&psItem->usLen);
-                    
+
             if ( psItem->usLen > sizeof(psItem->szClassName)-1 )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "Unexpected long class name, %d characters long - unable to read file.",
                           psItem->usLen );
                 return FALSE;
@@ -247,7 +268,7 @@ int nwt_ParseHeader( NWT_GRID * pGrd, char *nwtHeader )
                 return FALSE;
         }
     }
-    
+
     return TRUE;
 }
 
@@ -261,6 +282,9 @@ int nwt_LoadColors( NWT_RGB * pMap, int mapSize, NWT_GRID * pGrd )
     int nWarkerMark = 0;
 
     createIP( 0, 255, 255, 255, pMap, &nWarkerMark );
+    if( pGrd->iNumColorInflections == 0 )
+        return 0;
+
     // If Zmin is less than the 1st inflection use the 1st inflections color to
     // the start of the ramp
     if( pGrd->fZMin <= pGrd->stInflection[0].zVal )
@@ -312,10 +336,11 @@ int nwt_LoadColors( NWT_RGB * pMap, int mapSize, NWT_GRID * pGrd )
                 break;
             }
             // save the inflections between zmin and zmax
-            index = (int)( ( (pGrd->stInflection[i].zVal - pGrd->fZMin) /
-                                              (pGrd->fZMax - pGrd->fZMin) )
-                           * mapSize);
-                           
+            index = static_cast<int>(
+                ( (pGrd->stInflection[i].zVal - pGrd->fZMin) /
+                  (pGrd->fZMax - pGrd->fZMin) )
+                * mapSize );
+
             if ( index >= mapSize )
                 index = mapSize - 1;
             createIP( index,
@@ -353,11 +378,11 @@ void linearColor( NWT_RGB * pRGB, NWT_INFLECTION * pIPLow, NWT_INFLECTION * pIPH
     else
     {
         float scale = (fMid - pIPLow->zVal) / (pIPHigh->zVal - pIPLow->zVal);
-        pRGB->r = (unsigned char)
+        pRGB->r = static_cast<unsigned char>
                 (scale * (pIPHigh->r - pIPLow->r) + pIPLow->r + 0.5);
-        pRGB->g = (unsigned char)
+        pRGB->g = static_cast<unsigned char>
                 (scale * (pIPHigh->g - pIPLow->g) + pIPLow->g + 0.5);
-        pRGB->b = (unsigned char)
+        pRGB->b = static_cast<unsigned char>
                 (scale * (pIPHigh->b - pIPLow->b) + pIPLow->b + 0.5);
     }
 }
@@ -382,14 +407,14 @@ void createIP( int index, unsigned char r, unsigned char g, unsigned char b,
 
     int wm = *pnWarkerMark;
 
-    float rslope = (float)(r - map[wm].r) / (float)(index - wm);
-    float gslope = (float)(g - map[wm].g) / (float)(index - wm);
-    float bslope = (float)(b - map[wm].b) / (float)(index - wm);
+    float rslope = static_cast<float>(r - map[wm].r) / static_cast<float>(index - wm);
+    float gslope = static_cast<float>(g - map[wm].g) / static_cast<float>(index - wm);
+    float bslope = static_cast<float>(b - map[wm].b) / static_cast<float>(index - wm);
     for( i = wm + 1; i < index; i++)
     {
-        map[i].r = (unsigned char)(map[wm].r + ((i - wm) * rslope) + 0.5);
-        map[i].g = (unsigned char)(map[wm].g + ((i - wm) * gslope) + 0.5);
-        map[i].b = (unsigned char)(map[wm].b + ((i - wm) * bslope) + 0.5);
+        map[i].r = static_cast<unsigned char>(map[wm].r + ((i - wm) * rslope) + 0.5);
+        map[i].g = static_cast<unsigned char>(map[wm].g + ((i - wm) * gslope) + 0.5);
+        map[i].b = static_cast<unsigned char>(map[wm].b + ((i - wm) * bslope) + 0.5);
     }
     map[index].r = r;
     map[index].g = g;
@@ -438,7 +463,8 @@ NWT_GRID *nwtOpenGrid( char *filename )
         nwtHeader[3] != 'C' )
           return NULL;
 
-    pGrd = (NWT_GRID *) calloc( sizeof(NWT_GRID), 1 );
+    pGrd = reinterpret_cast<NWT_GRID *>(
+        calloc( sizeof(NWT_GRID), 1 ) );
 
     if( nwtHeader[4] == '1' )
         pGrd->cFormat = 0x00;        // grd - surface type
@@ -453,7 +479,8 @@ NWT_GRID *nwtOpenGrid( char *filename )
         return NULL;
     }
 
-    strcpy( pGrd->szFileName, filename );
+    strncpy( pGrd->szFileName, filename, sizeof(pGrd->szFileName) );
+    pGrd->szFileName[sizeof(pGrd->szFileName) - 1] = '\0';
     pGrd->fp = fp;
     nwt_ParseHeader( pGrd, nwtHeader );
 
@@ -463,11 +490,9 @@ NWT_GRID *nwtOpenGrid( char *filename )
 //close the file and free the mem
 void nwtCloseGrid( NWT_GRID * pGrd )
 {
-    unsigned short usTmp;
-
     if( (pGrd->cFormat & 0x80) && pGrd->stClassDict )        // if is GRC - free the Dictionary
     {
-        for( usTmp = 0; usTmp < pGrd->stClassDict->nNumClassifiedItems; usTmp++ )
+        for( unsigned short usTmp = 0; usTmp < pGrd->stClassDict->nNumClassifiedItems; usTmp++ )
         {
             free( pGrd->stClassDict->stClassifedItem[usTmp] );
         }
@@ -480,14 +505,8 @@ void nwtCloseGrid( NWT_GRID * pGrd )
         return;
 }
 
-void nwtGetRow( CPL_UNUSED NWT_GRID * pGrd )
-{
-}
-
 void nwtPrintGridHeader( NWT_GRID * pGrd )
 {
-    int i;
-
     if( pGrd->cFormat & 0x80 )
     {
         printf( "\n%s\n\nGrid type is Classified ", pGrd->szFileName );
@@ -537,7 +556,7 @@ void nwtPrintGridHeader( NWT_GRID * pGrd )
         if( pGrd->bShowHillShade )
             printf( " Hill Shading" );
 
-        for( i = 0; i < pGrd->iNumColorInflections; i++ )
+        for( int i = 0; i < pGrd->iNumColorInflections; i++ )
         {
             printf( "\nColor Inflection %d - %f (%d,%d,%d)", i + 1,
                     pGrd->stInflection[i].zVal, pGrd->stInflection[i].r,
@@ -558,7 +577,7 @@ void nwtPrintGridHeader( NWT_GRID * pGrd )
     {
         printf( "\nNumber of Classes defined = %d",
                 pGrd->stClassDict->nNumClassifiedItems );
-        for( i = 0; i < (int) pGrd->stClassDict->nNumClassifiedItems; i++ )
+        for( int i = 0; i < static_cast<int>( pGrd->stClassDict->nNumClassifiedItems ); i++ )
         {
             printf( "\n%s - (%d,%d,%d)  Raw = %d  %d %d",
                     pGrd->stClassDict->stClassifedItem[i]->szClassName,
@@ -574,20 +593,18 @@ void nwtPrintGridHeader( NWT_GRID * pGrd )
 
 HLS RGBtoHLS( NWT_RGB rgb )
 {
-    short R, G, B;                /* input RGB values */
-    HLS hls;
-    unsigned char cMax, cMin;        /* max and min RGB values */
-    short Rdelta, Gdelta, Bdelta;    /* intermediate value: % of spread from max */
     /* get R, G, and B out of DWORD */
-    R = rgb.r;
-    G = rgb.g;
-    B = rgb.b;
+    short R = rgb.r;
+    short G = rgb.g;
+    short B = rgb.b;
 
     /* calculate lightness */
-    cMax = (unsigned char) MAX( MAX(R,G), B );
-    cMin = (unsigned char) MIN( MIN(R,G), B );
+    unsigned char cMax = static_cast<unsigned char>( std::max( std::max(R,G), B ) );
+    unsigned char cMin = static_cast<unsigned char>( std::min( std::min(R,G), B ) );
+    HLS hls;
     hls.l = (((cMax + cMin) * HLSMAX) + RGBMAX) / (2 * RGBMAX);
 
+    short Rdelta, Gdelta, Bdelta;    /* intermediate value: % of spread from max */
     if( cMax == cMin )
     {                            /* r=g=b --> achromatic case */
         hls.s = 0;                /* saturation */
@@ -628,7 +645,7 @@ HLS RGBtoHLS( NWT_RGB rgb )
 
 
 /* utility routine for HLStoRGB */
-short HueToRGB( short n1, short n2, short hue )
+static short HueToRGB( short n1, short n2, short hue )
 {
     /* range check: note values passed add/subtract thirds of range */
     if( hue < 0 )
@@ -653,11 +670,10 @@ short HueToRGB( short n1, short n2, short hue )
 NWT_RGB HLStoRGB( HLS hls )
 {
     NWT_RGB rgb;
-    short Magic1, Magic2;            /* calculated magic numbers (really!) */
 
     if( hls.s == 0 )
     {                            /* achromatic case */
-        rgb.r = rgb.g = rgb.b = (unsigned char) ((hls.l * RGBMAX) / HLSMAX);
+        rgb.r = rgb.g = rgb.b = static_cast<unsigned char>( (hls.l * RGBMAX) / HLSMAX );
         if( hls.h != UNDEFINED )
         {
             /* ERROR */
@@ -666,6 +682,7 @@ NWT_RGB HLStoRGB( HLS hls )
     else
     {                            /* chromatic case */
         /* set up magic numbers */
+        short Magic1, Magic2;            /* calculated magic numbers (really!) */
         if( hls.l <= (HLSMAX / 2) )
             Magic2 = (hls.l * (HLSMAX + hls.s) + (HLSMAX / 2)) / HLSMAX;
         else
@@ -673,9 +690,9 @@ NWT_RGB HLStoRGB( HLS hls )
         Magic1 = 2 * hls.l - Magic2;
 
         /* get RGB, change units from HLSMAX to RGBMAX */
-        rgb.r = (unsigned char) ((HueToRGB (Magic1, Magic2, hls.h + (HLSMAX / 3)) * RGBMAX + (HLSMAX / 2)) / HLSMAX);
-        rgb.g = (unsigned char) ((HueToRGB (Magic1, Magic2, hls.h) * RGBMAX + (HLSMAX / 2)) / HLSMAX);
-        rgb.b = (unsigned char) ((HueToRGB (Magic1, Magic2, hls.h - (HLSMAX / 3)) * RGBMAX + (HLSMAX / 2)) / HLSMAX);
+        rgb.r = static_cast<unsigned char> ((HueToRGB (Magic1, Magic2, hls.h + (HLSMAX / 3)) * RGBMAX + (HLSMAX / 2)) / HLSMAX);
+        rgb.g = static_cast<unsigned char> ((HueToRGB (Magic1, Magic2, hls.h) * RGBMAX + (HLSMAX / 2)) / HLSMAX);
+        rgb.b = static_cast<unsigned char> ((HueToRGB (Magic1, Magic2, hls.h - (HLSMAX / 3)) * RGBMAX + (HLSMAX / 2)) / HLSMAX);
     }
 
     return rgb;
diff --git a/frmts/northwood/northwood.h b/frmts/northwood/northwood.h
index 5f415f7..d36b57b 100644
--- a/frmts/northwood/northwood.h
+++ b/frmts/northwood/northwood.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: northwood.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: northwood.h 31749 2015-11-25 02:32:55Z goatbar $
  *
  * Project:  GRC/GRD Reader
  * Purpose:  Northwood Technologies Grid format declarations
@@ -39,15 +39,6 @@
 #include "cpl_vsi.h"
 #endif
 
-#ifndef MAX
-#define MAX(a, b) (a > b ? a : b)
-#endif
-
-#ifndef MIN
-#define MIN(a, b) (a < b ? a : b)
-#endif
-
-
 typedef struct
 {
     int row;
@@ -102,7 +93,7 @@ typedef struct
     char szFileName[256];
     VSILFILE *fp;
     float fVersion;
-    unsigned char cFormat;        //0x00 16 bit, 0x01 32 bit, 0x80 8 bit classifed, 0x81 16 bit classified
+    unsigned char cFormat;  // 0x00 16 bit, 0x01 32 bit, 0x80 8 bit classified, 0x81 16 bit classified
     unsigned int nBitsPerPixel;
     unsigned int nXSide;
     unsigned int nYSide;
diff --git a/frmts/ogdi/frmt_ogdi.html b/frmts/ogdi/frmt_ogdi.html
index 69a6a38..cce957b 100644
--- a/frmts/ogdi/frmt_ogdi.html
+++ b/frmts/ogdi/frmt_ogdi.html
@@ -17,9 +17,9 @@ and Image families should be fully supported, as well as reading of colormap
 and projection metadata.  The GDAL reader is intended
 to be used with OGDI 3.1 drivers, but OGDI 3.0 drivers should also work.<p>
 
-OGDI datasets are opened within GDAL by selecting the GLTP url.  For
+OGDI datasets are opened within GDAL by selecting the GLTP URL.  For
 instance, gltp://gdal.velocet.ca/adrg/usr4/mpp1/adrg/TPSUS0101 would open
-the ADRG dataset stored at /usr4/mpp1/adrg/TPSUS0101 on the machine 
+the ADRG dataset stored at /usr4/mpp1/adrg/TPSUS0101 on the machine
 gdal.velocet.ca (assuming it has an OGDI server running) using the 'adrg'
 driver.  This default access to a whole datastore will attempt to represent
 all layers (and all supported family types) as bands all at the resolution
@@ -27,13 +27,13 @@ and region reported by the datastore when initially accessed.<p>
 
 It is also possible to select a particular layer and access family
 from an OGDI datastore by indicating the layer name family in the name.
-The GDAL dataset name 
+The GDAL dataset name
 gltp:/adrg/usr4/mpp1/adrg/TPUS0101:"TPUS0102.IMG":Matrix would select
-the layer named TPUS0102.IMG from the dataset /usr4/mpp1/adrg/TPUS0101 
+the layer named TPUS0102.IMG from the dataset /usr4/mpp1/adrg/TPUS0101
 on the local system using the ADRG driver, and access the Matrix family.
 When a specific layer is accessed in this manner GDAL will attempt to determine
 the region and resolution from the OGDI 3.1 capabilities document.  Note that
-OGDI 3.0 datastores must have the layer and family specified in the 
+OGDI 3.0 datastores must have the layer and family specified in the
 dataset name since they cannot be determined automatically.<p>
 
 <pre>
@@ -46,13 +46,13 @@ eg.
 OGDI Matrix family layers (pseudocolored integer layers) are represented
 as a single band of raster data with a color table.  Though the Matrix layers
 contain 32bit integer values, they are represented through GDAL as eight
-layers.  All values over 255 are truncated to 255, and only 256 colormap 
+layers.  All values over 255 are truncated to 255, and only 256 colormap
 entries are captured.  While this works well for most Matrix layers, it is
 anticipated that at some point in the future Matrix layers with a larger
 dynamic range will be represented as other data types. <p>
 
 OGDI Image family layers may internally have a type of RGB (1) which is
-represented as three 8bit bands in GDAL, or Byte (2), UInt16 (3), Int16 (4) 
+represented as three 8bit bands in GDAL, or Byte (2), UInt16 (3), Int16 (4)
 or Int32 (5).   There is no support for floating points bands in OGDI 3.1.<p>
 
 The GDAL OGDI driver will represent OGDI datasources as having <i>arbitrary</i>
@@ -62,8 +62,8 @@ efficient reading of overview information from OGDI datastores.<p>
 
 If an OGDI datastore is opened without selecting a layer name in the dataset
 name, and if the datastore has OGDI 3.1 style capabilities, the list of layers
-will be made available as SUBDATASETS metadata.  For instance, the 
-<i>gdalinfo</i> command might report the following.  This information can be 
+will be made available as SUBDATASETS metadata.  For instance, the
+<i>gdalinfo</i> command might report the following.  This information can be
 used to establish available layers for direct access.<p>
 
 <pre>
diff --git a/frmts/ogdi/ogdidataset.cpp b/frmts/ogdi/ogdidataset.cpp
index ae0590f..7c6273a 100644
--- a/frmts/ogdi/ogdidataset.cpp
+++ b/frmts/ogdi/ogdidataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogdidataset.cpp 28216 2014-12-25 18:02:53Z goatbar $
+ * $Id: ogdidataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Name:     ogdidataset.cpp
  * Project:  OGDI Bridge
@@ -31,15 +31,12 @@
 
 #include <math.h>
 #include "ecs.h"
+#include "gdal_frmts.h"
 #include "gdal_priv.h"
 #include "cpl_string.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: ogdidataset.cpp 28216 2014-12-25 18:02:53Z goatbar $");
-
-CPL_C_START
-void	GDALRegister_OGDI(void);
-CPL_C_END
+CPL_CVSID("$Id: ogdidataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -52,7 +49,7 @@ class OGDIRasterBand;
 class CPL_DLL OGDIDataset : public GDALDataset
 {
     friend class OGDIRasterBand;
-    
+
     int		nClientID;
 
     ecs_Region	sGlobalBounds;
@@ -93,7 +90,7 @@ class OGDIRasterBand : public GDALRasterBand
 {
     friend class OGDIDataset;
 
-    int		nOGDIImageType; /* ie. 1 for RGB */
+    int nOGDIImageType; /* i.e. 1 for RGB */
 
     char	*pszLayerName;
     ecs_Family  eFamily;
@@ -108,7 +105,7 @@ class OGDIRasterBand : public GDALRasterBand
                               GSpacing nLineSpace,
                               GDALRasterIOExtraArg* psExtraArg );
 
-    CPLErr         EstablishAccess( int nXOff, int nYOff, 
+    CPLErr         EstablishAccess( int nXOff, int nYOff,
                                     int nXSize, int nYSize,
                                     int nBufXSize, int nBufYSize );
 
@@ -124,7 +121,7 @@ class OGDIRasterBand : public GDALRasterBand
     virtual GDALColorTable *GetColorTable();
 
     virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
-                               int nBufXSize, int nBufYSize, 
+                               int nBufXSize, int nBufYSize,
                                GDALDataType eDT, char **papszOptions );
 
 };
@@ -133,31 +130,31 @@ class OGDIRasterBand : public GDALRasterBand
 /*                           OGDIRasterBand()                            */
 /************************************************************************/
 
-OGDIRasterBand::OGDIRasterBand( OGDIDataset *poDS, int nBand, 
-                                const char * pszName, ecs_Family eFamily,
-                                int nComponent )
+OGDIRasterBand::OGDIRasterBand( OGDIDataset *poDSIn, int nBandIn,
+                                const char * pszName, ecs_Family eFamilyIn,
+                                int nComponentIn )
 
 {
     ecs_Result	*psResult;
-    
-    this->poDS = poDS;
-    this->nBand = nBand;
-    this->eFamily = eFamily;
+
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
+    this->eFamily = eFamilyIn;
     this->pszLayerName = CPLStrdup(pszName);
-    this->nComponent = nComponent;
+    this->nComponent = nComponentIn;
     poCT = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Make this layer current.                                        */
 /* -------------------------------------------------------------------- */
-    EstablishAccess( 0, 0, 
-                     poDS->GetRasterXSize(), poDS->GetRasterYSize(), 
+    EstablishAccess( 0, 0,
+                     poDS->GetRasterXSize(), poDS->GetRasterYSize(),
                      poDS->GetRasterXSize(), poDS->GetRasterYSize() );
 
 /* -------------------------------------------------------------------- */
 /*      Get the raster info.                                            */
 /* -------------------------------------------------------------------- */
-    psResult = cln_GetRasterInfo( poDS->nClientID );
+    psResult = cln_GetRasterInfo( poDSIn->nClientID );
     if( ECSERROR(psResult) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -172,7 +169,7 @@ OGDIRasterBand::OGDIRasterBand( OGDIDataset *poDS, int nBand,
         int     i;
 
         poCT = new GDALColorTable();
-        
+
         for( i = 0; i < (int) ECSRASTERINFO(psResult).cat.cat_len; i++ ) {
             GDALColorEntry   sEntry;
 
@@ -181,11 +178,11 @@ OGDIRasterBand::OGDIRasterBand( OGDIDataset *poDS, int nBand,
             sEntry.c3 = ECSRASTERINFO(psResult).cat.cat_val[i].b;
             sEntry.c4 = 255;
 
-            poCT->SetColorEntry( ECSRASTERINFO(psResult).cat.cat_val[i].no_cat, 
+            poCT->SetColorEntry( static_cast<int>(ECSRASTERINFO(psResult).cat.cat_val[i].no_cat),
                                  &sEntry );
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Get the GDAL data type.  Eventually we might use the            */
 /*      category info to establish what to do here.                     */
@@ -206,7 +203,7 @@ OGDIRasterBand::OGDIRasterBand( OGDIDataset *poDS, int nBand,
         eDataType = GDT_UInt32;
 
     nOGDIImageType = ECSRASTERINFO(psResult).width;
-    
+
 /* -------------------------------------------------------------------- */
 /*	Currently only works for strips 				*/
 /* -------------------------------------------------------------------- */
@@ -235,8 +232,8 @@ CPLErr OGDIRasterBand::IReadBlock( int, int nBlockYOff, void * pImage )
     GDALRasterIOExtraArg sExtraArg;
     INIT_RASTERIO_EXTRA_ARG(sExtraArg);
 
-    return IRasterIO( GF_Read, 0, nBlockYOff, nBlockXSize, 1, 
-                      pImage, nBlockXSize, 1, eDataType, 
+    return IRasterIO( GF_Read, 0, nBlockYOff, nBlockXSize, 1,
+                      pImage, nBlockXSize, 1, eDataType,
                       GDALGetDataTypeSize(eDataType)/8, 0, &sExtraArg );
 }
 
@@ -263,7 +260,7 @@ CPLErr OGDIRasterBand::IRasterIO( CPL_UNUSED GDALRWFlag eRWFlag,
 /* -------------------------------------------------------------------- */
 /*      Establish access at the desired resolution.                     */
 /* -------------------------------------------------------------------- */
-    eErr = EstablishAccess( nXOff, nYOff, nXSize, nYSize, 
+    eErr = EstablishAccess( nXOff, nYOff, nXSize, nYSize,
                             nBufXSize, nBufYSize );
     if( eErr != CE_None )
         return eErr;
@@ -291,15 +288,15 @@ CPLErr OGDIRasterBand::IRasterIO( CPL_UNUSED GDALRWFlag eRWFlag,
 
         if( eFamily == Matrix )
         {
-            GDALCopyWords( ECSRASTER(psResult), GDT_UInt32, 4, 
-                           pLineData, eBufType, nPixelSpace,
+            GDALCopyWords( ECSRASTER(psResult), GDT_UInt32, 4,
+                           pLineData, eBufType, static_cast<int>(nPixelSpace),
                            nBufXSize );
         }
         else if( nOGDIImageType == 1 )
         {
-            GDALCopyWords( ((GByte *) ECSRASTER(psResult)) + nComponent, 
+            GDALCopyWords( ((GByte *) ECSRASTER(psResult)) + nComponent,
                            GDT_Byte, 4,
-                           pLineData, eBufType, nPixelSpace, nBufXSize );
+                           pLineData, eBufType, static_cast<int>(nPixelSpace), nBufXSize );
 
             if( nComponent == 3 )
             {
@@ -311,32 +308,31 @@ CPLErr OGDIRasterBand::IRasterIO( CPL_UNUSED GDALRWFlag eRWFlag,
                         ((GByte *) pLineData)[i] = 255;
                     else
                         ((GByte *) pLineData)[i] = 0;
-                    
                 }
             }
         }
         else if( nOGDIImageType == 2 )
         {
             GDALCopyWords( ECSRASTER(psResult), GDT_Byte, 1,
-                           pLineData, eBufType, nPixelSpace,
+                           pLineData, eBufType, static_cast<int>(nPixelSpace),
                            nBufXSize );
         }
         else if( nOGDIImageType == 3 )
         {
             GDALCopyWords( ECSRASTER(psResult), GDT_UInt16, 2,
-                           pLineData, eBufType, nPixelSpace,
+                           pLineData, eBufType, static_cast<int>(nPixelSpace),
                            nBufXSize );
         }
         else if( nOGDIImageType == 4 )
         {
             GDALCopyWords( ECSRASTER(psResult), GDT_Int16, 2,
-                           pLineData, eBufType, nPixelSpace,
+                           pLineData, eBufType, static_cast<int>(nPixelSpace),
                            nBufXSize );
         }
         else if( nOGDIImageType == 5 )
         {
             GDALCopyWords( ECSRASTER(psResult), GDT_Int32, 4,
-                           pLineData, eBufType, nPixelSpace,
+                           pLineData, eBufType, static_cast<int>(nPixelSpace),
                            nBufXSize );
         }
     }
@@ -358,8 +354,8 @@ int OGDIRasterBand::HasArbitraryOverviews()
 /*                          EstablishAccess()                           */
 /************************************************************************/
 
-CPLErr OGDIRasterBand::EstablishAccess( int nXOff, int nYOff, 
-                                        int nWinXSize, int nWinYSize, 
+CPLErr OGDIRasterBand::EstablishAccess( int nXOff, int nYOff,
+                                        int nWinXSize, int nWinYSize,
                                         int nBufXSize, int nBufYSize )
 
 {
@@ -372,10 +368,10 @@ CPLErr OGDIRasterBand::EstablishAccess( int nXOff, int nYOff,
     if( poODS->nCurrentBand != nBand )
     {
         ecs_LayerSelection sSelection;
-        
+
         sSelection.Select = pszLayerName;
         sSelection.F = eFamily;
-        
+
         CPLDebug( "OGDIRasterBand", "<EstablishAccess: SelectLayer(%s)>",
                   pszLayerName );
         psResult = cln_SelectLayer( poODS->nClientID, &sSelection );
@@ -389,7 +385,7 @@ CPLErr OGDIRasterBand::EstablishAccess( int nXOff, int nYOff,
         poODS->nCurrentBand = nBand;
         poODS->nCurrentIndex = -1;
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      What region would represent this resolution and window?         */
 /* -------------------------------------------------------------------- */
@@ -402,11 +398,11 @@ CPLErr OGDIRasterBand::EstablishAccess( int nXOff, int nYOff,
         + poODS->sGlobalBounds.west;
     sWin.ew_res = poODS->sGlobalBounds.ew_res*(nWinXSize/(double)nBufXSize);
 
-    sWin.north = poODS->sGlobalBounds.north 
+    sWin.north = poODS->sGlobalBounds.north
         - nYOff*poODS->sGlobalBounds.ns_res;
     if( nBufYSize == 1 && nWinYSize == 1 )
     {
-        sWin.ns_res = sWin.ew_res 
+        sWin.ns_res = sWin.ew_res
             * (poODS->sGlobalBounds.ns_res / poODS->sGlobalBounds.ew_res);
         nWinYSize = (int) ((sWin.north - poODS->sGlobalBounds.south + sWin.ns_res*0.9)
                                 / sWin.ns_res);
@@ -433,13 +429,13 @@ CPLErr OGDIRasterBand::EstablishAccess( int nXOff, int nYOff,
     }
 
     if( poODS->nCurrentIndex != 0
-        || ABS(sWin.west - poODS->sCurrentBounds.west) > 0.0001 
-        || ABS(sWin.east - poODS->sCurrentBounds.east) > 0.0001 
-        || ABS(sWin.north - (poODS->sCurrentBounds.north - poODS->nCurrentIndex * poODS->sCurrentBounds.ns_res)) > dfNSTolerance 
+        || ABS(sWin.west - poODS->sCurrentBounds.west) > 0.0001
+        || ABS(sWin.east - poODS->sCurrentBounds.east) > 0.0001
+        || ABS(sWin.north - (poODS->sCurrentBounds.north - poODS->nCurrentIndex * poODS->sCurrentBounds.ns_res)) > dfNSTolerance
         || ABS(sWin.ew_res/poODS->sCurrentBounds.ew_res - 1.0) > 0.0001
         || ABS(sWin.ns_res - poODS->sCurrentBounds.ns_res) > dfNSTolerance )
     {
-        CPLDebug( "OGDIRasterBand", 
+        CPLDebug( "OGDIRasterBand",
                   "<EstablishAccess: Set Region(%d,%d,%d,%d,%d,%d>",
                   nXOff, nYOff, nWinXSize, nWinYSize, nBufXSize, nBufYSize );
 
@@ -450,7 +446,7 @@ CPLErr OGDIRasterBand::EstablishAccess( int nXOff, int nYOff,
                       "%s", psResult->message );
             return CE_Failure;
         }
-        
+
         poODS->sCurrentBounds = sWin;
         poODS->nCurrentIndex = 0;
     }
@@ -496,17 +492,17 @@ GDALColorTable *OGDIRasterBand::GetColorTable()
 /*      want the data.                                                  */
 /************************************************************************/
 
-CPLErr OGDIRasterBand::AdviseRead( int nXOff, int nYOff, 
+CPLErr OGDIRasterBand::AdviseRead( int nXOff, int nYOff,
                                    int nXSize, int nYSize,
-                                   int nBufXSize, int nBufYSize, 
+                                   int nBufXSize, int nBufYSize,
                                    CPL_UNUSED GDALDataType eDT,
                                    CPL_UNUSED char **papszOptions )
 
 {
-    return EstablishAccess( nXOff, nYOff, nXSize, nYSize, 
+    return EstablishAccess( nXOff, nYOff, nXSize, nYSize,
                             nBufXSize, nBufYSize );
 }
-    
+
 /************************************************************************/
 /* ==================================================================== */
 /*                            OGDIDataset                               */
@@ -570,40 +566,40 @@ char **OGDIDataset::GetMetadata( const char *pszDomain )
 GDALDataset *OGDIDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    ecs_Result	*psResult;
-    int		nClientID;
+    ecs_Result *psResult;
+    int nClientID;
     char        **papszImages=NULL, **papszMatrices=NULL;
-    
-    if( !EQUALN(poOpenInfo->pszFilename,"gltp:",5) )
+
+    if( !STARTS_WITH_CI(poOpenInfo->pszFilename, "gltp:") )
         return( NULL );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The OGDI driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Has the user hardcoded a layer and family in the URL?           */
 /*      Honour quoted strings for the layer name, since some layers     */
-/*      (ie. RPF/CADRG) have embedded colons.                           */
+/*      (i.e. RPF/CADRG) have embedded colons.                           */
 /* -------------------------------------------------------------------- */
-    int       nC1=-1, nC2=-1, i, bInQuotes = FALSE;
+    int       nC1=-1, nC2=-1, bInQuotes = FALSE;
     char      *pszURL = CPLStrdup(poOpenInfo->pszFilename);
 
-    for( i = strlen(pszURL)-1; i > 0; i-- )
+    for( int i = static_cast<int>(strlen(pszURL))-1; i > 0; i-- )
     {
         if( pszURL[i] == '/' )
             break;
 
         if( pszURL[i] == '"' && pszURL[i-1] != '\\' )
             bInQuotes = !bInQuotes;
-            
+
         else if( pszURL[i] == ':' && !bInQuotes )
         {
             if( nC1 == -1 )
@@ -617,14 +613,14 @@ GDALDataset *OGDIDataset::Open( GDALOpenInfo * poOpenInfo )
                 pszURL[nC2] = '\0';
             }
         }
-    }	
+    }
 
 /* -------------------------------------------------------------------- */
 /*      If we got a "family", and it is a vector family then return     */
 /*      quietly.                                                        */
 /* -------------------------------------------------------------------- */
-    if( nC2 != -1 
-        && !EQUAL(pszURL+nC1+1,"Matrix") 
+    if( nC2 != -1
+        && !EQUAL(pszURL+nC1+1,"Matrix")
         && !EQUAL(pszURL+nC1+1,"Image") )
     {
         CPLFree( pszURL );
@@ -654,18 +650,18 @@ GDALDataset *OGDIDataset::Open( GDALOpenInfo * poOpenInfo )
     else
     {
         char	*pszLayerName = CPLStrdup( pszURL+nC2+1 );
-        
+
         if( pszLayerName[0] == '"' )
         {
             int		nOut = 0;
 
-            for( i = 1; pszLayerName[i] != '\0'; i++ )
+            for( int i = 1; pszLayerName[i] != '\0'; i++ )
             {
                 if( pszLayerName[i+1] == '"' && pszLayerName[i] == '\\' )
                     pszLayerName[nOut++] = pszLayerName[++i];
                 else if( pszLayerName[i] != '"' )
                     pszLayerName[nOut++] = pszLayerName[i];
-                else 
+                else
                     break;
             }
             pszLayerName[nOut] = '\0';
@@ -682,16 +678,16 @@ GDALDataset *OGDIDataset::Open( GDALOpenInfo * poOpenInfo )
     CPLFree( pszURL );
 
 /* -------------------------------------------------------------------- */
-/*      If this is a 3.1 server (ie, it support                         */
+/*      If this is a 3.1 server (i.e, it support                         */
 /*      cln_GetLayerCapabilities()) and it has no raster layers then    */
 /*      we can assume it must be a vector datastore.  End without an    */
 /*      error in case the application wants to try this through         */
 /*      OGR.                                                            */
 /* -------------------------------------------------------------------- */
     psResult = cln_GetVersion(nClientID);
-    
+
     if( (ECSERROR(psResult) || CPLAtof(ECSTEXT(psResult)) >= 3.1)
-        && CSLCount(papszMatrices) == 0 
+        && CSLCount(papszMatrices) == 0
         && CSLCount(papszImages) == 0 )
     {
         CPLDebug( "OGDIDataset",
@@ -701,7 +697,7 @@ GDALDataset *OGDIDataset::Open( GDALOpenInfo * poOpenInfo )
         cln_DestroyClient( nClientID );
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
@@ -743,7 +739,7 @@ GDALDataset *OGDIDataset::Open( GDALOpenInfo * poOpenInfo )
     else
     {
         CPLError( CE_Warning, CPLE_NotSupported,
-                  "untranslatable PROJ.4 projection: %s\n", 
+                  "untranslatable PROJ.4 projection: %s\n",
                   ECSTEXT(psResult) );
         poDS->pszProjection = CPLStrdup("");
     }
@@ -768,9 +764,9 @@ GDALDataset *OGDIDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( CSLCount(papszMatrices) + CSLCount(papszImages) == 1 )
     {
-        if( CSLCount(papszMatrices) == 1 )
+        if( papszMatrices != NULL && *papszMatrices != NULL )
             OverrideGlobalInfo( poDS, papszMatrices[0] );
-        else
+        else if( papszImages != NULL && *papszImages != NULL )
             OverrideGlobalInfo( poDS, papszImages[0] );
     }
 
@@ -787,34 +783,34 @@ GDALDataset *OGDIDataset::Open( GDALOpenInfo * poOpenInfo )
         for( i = 0; papszImages != NULL && papszImages[i] != NULL; i++ )
             poDS->AddSubDataset( "Image", papszImages[i] );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Establish raster info.                                          */
 /* -------------------------------------------------------------------- */
-    poDS->nRasterXSize = (int) 
+    poDS->nRasterXSize = (int)
         (((poDS->sGlobalBounds.east - poDS->sGlobalBounds.west)
           / poDS->sGlobalBounds.ew_res) + 0.5);
-    
-    poDS->nRasterYSize = (int) 
+
+    poDS->nRasterYSize = (int)
         (((poDS->sGlobalBounds.north - poDS->sGlobalBounds.south)
           / poDS->sGlobalBounds.ns_res) + 0.5);
 
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    for( i=0; papszMatrices != NULL && papszMatrices[i] != NULL; i++)
+    for( int i=0; papszMatrices != NULL && papszMatrices[i] != NULL; i++)
     {
         if( CSLFindString( papszImages, papszMatrices[i] ) == -1 )
-            poDS->SetBand( poDS->GetRasterCount()+1, 
-                           new OGDIRasterBand( poDS, poDS->GetRasterCount()+1, 
+            poDS->SetBand( poDS->GetRasterCount()+1,
+                           new OGDIRasterBand( poDS, poDS->GetRasterCount()+1,
                                                papszMatrices[i], Matrix, 0 ) );
     }
 
-    for( i=0; papszImages != NULL && papszImages[i] != NULL; i++)
+    for( int i=0; papszImages != NULL && papszImages[i] != NULL; i++)
     {
         OGDIRasterBand	*poBand;
 
-        poBand = new OGDIRasterBand( poDS, poDS->GetRasterCount()+1, 
+        poBand = new OGDIRasterBand( poDS, poDS->GetRasterCount()+1,
                                      papszImages[i], Image, 0 );
 
         poDS->SetBand( poDS->GetRasterCount()+1, poBand );
@@ -822,14 +818,14 @@ GDALDataset *OGDIDataset::Open( GDALOpenInfo * poOpenInfo )
         /* special case for RGBt Layers */
         if( poBand->nOGDIImageType == 1 )
         {
-            poDS->SetBand( poDS->GetRasterCount()+1, 
-                           new OGDIRasterBand( poDS, poDS->GetRasterCount()+1, 
+            poDS->SetBand( poDS->GetRasterCount()+1,
+                           new OGDIRasterBand( poDS, poDS->GetRasterCount()+1,
                                                papszImages[i], Image, 1 ));
-            poDS->SetBand( poDS->GetRasterCount()+1, 
-                           new OGDIRasterBand( poDS, poDS->GetRasterCount()+1, 
+            poDS->SetBand( poDS->GetRasterCount()+1,
+                           new OGDIRasterBand( poDS, poDS->GetRasterCount()+1,
                                                papszImages[i], Image, 2 ));
-            poDS->SetBand( poDS->GetRasterCount()+1, 
-                           new OGDIRasterBand( poDS, poDS->GetRasterCount()+1, 
+            poDS->SetBand( poDS->GetRasterCount()+1,
+                           new OGDIRasterBand( poDS, poDS->GetRasterCount()+1,
                                                papszImages[i], Image, 3 ));
         }
     }
@@ -850,14 +846,14 @@ void OGDIDataset::AddSubDataset( const char *pszType, const char *pszLayer )
     char	szName[80];
     int		nCount = CSLCount( papszSubDatasets ) / 2;
 
-    sprintf( szName, "SUBDATASET_%d_NAME", nCount+1 );
-    papszSubDatasets = 
-        CSLSetNameValue( papszSubDatasets, szName, 
+    snprintf( szName, sizeof(szName), "SUBDATASET_%d_NAME", nCount+1 );
+    papszSubDatasets =
+        CSLSetNameValue( papszSubDatasets, szName,
               CPLSPrintf( "%s:\"%s\":%s", GetDescription(), pszLayer, pszType ) );
 
-    sprintf( szName, "SUBDATASET_%d_DESC", nCount+1 );
-    papszSubDatasets = 
-        CSLSetNameValue( papszSubDatasets, szName, 
+    snprintf( szName, sizeof(szName), "SUBDATASET_%d_DESC", nCount+1 );
+    papszSubDatasets =
+        CSLSetNameValue( papszSubDatasets, szName,
               CPLSPrintf( "%s as %s", pszLayer, pszType ) );
 }
 
@@ -865,15 +861,15 @@ void OGDIDataset::AddSubDataset( const char *pszType, const char *pszLayer )
 /*                           CollectLayers()                            */
 /************************************************************************/
 
-CPLErr OGDIDataset::CollectLayers( int nClientID, 
-                                   char ***ppapszImages, 
+CPLErr OGDIDataset::CollectLayers( int nClientID,
+                                   char ***ppapszImages,
                                    char ***ppapszMatrices )
 
 {
     const ecs_LayerCapabilities	*psLayer;
     int		iLayer;
 
-    for( iLayer = 0; 
+    for( iLayer = 0;
          (psLayer = cln_GetLayerCapabilities(nClientID,iLayer)) != NULL;
          iLayer++ )
     {
@@ -904,7 +900,7 @@ CPLErr OGDIDataset::OverrideGlobalInfo( OGDIDataset *poDS,
     const ecs_LayerCapabilities	*psLayer;
     int		iLayer;
 
-    for( iLayer = 0; 
+    for( iLayer = 0;
          (psLayer = cln_GetLayerCapabilities(poDS->nClientID,iLayer)) != NULL;
          iLayer++ )
     {
@@ -951,31 +947,27 @@ CPLErr OGDIDataset::GetGeoTransform( double * padfTransform )
 }
 
 /************************************************************************/
-/*                          GDALRegister_OGDI()                        */
+/*                          GDALRegister_OGDI()                         */
 /************************************************************************/
 
 void GDALRegister_OGDI()
 
 {
-    GDALDriver	*poDriver;
+    if( !GDAL_CHECK_VERSION( "GDAL/OGDI driver" ) )
+        return;
 
-    if (! GDAL_CHECK_VERSION("GDAL/OGDI driver"))
+    if( GDALGetDriverByName( "OGDI" ) != NULL )
         return;
-    
-    if( GDALGetDriverByName( "OGDI" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "OGDI" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "OGDI Bridge" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_ogdi.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
-
-        poDriver->pfnOpen = OGDIDataset::Open;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "OGDI" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "OGDI Bridge" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_ogdi.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
+
+    poDriver->pfnOpen = OGDIDataset::Open;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/openjpeg/frmt_jp2openjpeg.html b/frmts/openjpeg/frmt_jp2openjpeg.html
index d90c431..7a1275f 100644
--- a/frmts/openjpeg/frmt_jp2openjpeg.html
+++ b/frmts/openjpeg/frmt_jp2openjpeg.html
@@ -11,7 +11,7 @@
 
 <p>This driver is an implementation of a JPEG2000 reader/writer based on OpenJPEG library <b>v2</b>.</p>
 
-<p>For GDAL 1.10 or later, use openjpeg 2.X.</p>
+<p>For GDAL 1.10, use openjpeg 2.0. For GDAL 1.11 or later, use openjpeg 2.X.</p>
 <p>For GDAL 1.9.x or before, use the v2 branch from its Subversion repository : http://openjpeg.googlecode.com/svn/branches/v2 (before r2230 when it was deleted).</p>
 
 <p>The driver uses the VSI Virtual File API, so it can read JPEG2000 compressed NITF files.</p>
@@ -207,7 +207,7 @@ of the source dataset unmodified. Defaults to NO. Note that enabling that featur
 in inconsistent content of the JP2 boxes w.r.t. to the content of the source codestream.
 Most other creation options will be ignored in that mode. Can be useful in some
 use cases when adding/correcting georeferencing, metadata, ... INSPIRE_TG and
-PROFILE options will be ignored, and the profile of the codestream will be overriden
+PROFILE options will be ignored, and the profile of the codestream will be overridden
 with the one specified/implied by the options (which may be inconsistent with
 the characteristics of the codestream).
 </p></li>
@@ -225,7 +225,7 @@ Lossless compression can be achieved if ALL the following creation options are d
 
 <h3><a name="GMLJP2v2Def">GMLJP2v2 definition file</a></h3>
 
-A GMLJP2v2 box typically contains a GMLJP2RectifiedGridCoverage with the 
+A GMLJP2v2 box typically contains a GMLJP2RectifiedGridCoverage with the
 SRS information and geotransformation matrix. It is also possible to add metadata,
 vector features (GML feature collections), annotations (KML), styles (typically
 SLD, or other XML format) or any XML content as an extension.
@@ -272,7 +272,7 @@ the below syntax (elements starting with "#" are documentation, and can be omitt
                     [ "The metadata file will be generated from a template and a source file.",
                       "The template is a valid GMLJP2 metadata XML tree with placeholders like",
                       "{{{XPATH(some_xpath_expression)}}}",
-                      "that are evalated from the source XML file. Typical use case",
+                      "that are evaluated from the source XML file. Typical use case",
                       "is to generate a gmljp2:eopMetadata from the XML metadata",
                       "provided by the image provider in their own particular format." ],
                 "dynamic_metadata" :
@@ -316,7 +316,7 @@ the below syntax (elements starting with "#" are documentation, and can be omitt
                                   "Ignored for a remote_resource"],
                 "namespace": "http://example.com",
 
-                "#schema_location_doc": ["Value of the substitued schemaLocation. ",
+                "#schema_location_doc": ["Value of the substituted schemaLocation. ",
                                          "Typically a schema box label (link)",
                                          "Ignored for a remote_resource"],
                 "schema_location": "gmljp2://xml/schema_0.xsd",
@@ -380,7 +380,7 @@ against the content of the source file. xpath_expr must be a XPath 1.0 compatibl
 expression, with the addition of the following functions :
 
 <ul>
-<li><b>if(cond_expr,expr_if_true,expr_if_false)</b>: if cond_expr evalutes to
+<li><b>if(cond_expr,expr_if_true,expr_if_false)</b>: if cond_expr evaluates to
 true, returns expr_if_true. Otherwise returns expr_if_false</li>
 <li><b>uuid()</b>: evaluates to a random UUID</b></li>
 </ul>
@@ -399,7 +399,7 @@ the OGR API.
 
 For example:
 <pre>
-ogrinfo -ro my.jp2 
+ogrinfo -ro my.jp2
 
 INFO: Open of my.jp2'
       using driver `JP2OpenJPEG' successful.
@@ -417,7 +417,7 @@ OPEN_REMOTE_GML is set to YES.</p>
 <ul>
 <li><p> Implemented as <tt>gdal/frmts/openjpeg/openjpegdataset.cpp</tt>.</p></li>
 <li><p> <a href="http://www.jpeg.org/jpeg2000/index.html">Official JPEG-2000 page<a></p></li>
-<li><p> <a href="http://code.google.com/p/openjpeg/">The OpenJPEG library home page</a></p></li>
+<li><p> <a href="https://github.com/uclouvain/openjpeg">The OpenJPEG library home page</a></p></li>
 <li><p> <a href="http://inspire.ec.europa.eu/documents/Data_Specifications/INSPIRE_DataSpecification_OI_v3.0.pdf">
 Inspire Data Specification on Orthoimagery - Technical Guidelines</a></p></li>
 </ul>
diff --git a/frmts/openjpeg/openjpegdataset.cpp b/frmts/openjpeg/openjpegdataset.cpp
index d608b91..4269007 100644
--- a/frmts/openjpeg/openjpegdataset.cpp
+++ b/frmts/openjpeg/openjpegdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: openjpegdataset.cpp 29330 2015-06-14 12:11:11Z rouault $
+ * $Id: openjpegdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  JPEG2000 driver based on OpenJPEG library
  * Purpose:  JPEG2000 driver based on OpenJPEG library
@@ -38,14 +38,15 @@
 #endif
 #include <vector>
 
-#include "gdaljp2abstractdataset.h"
+#include "cpl_atomic_ops.h"
+#include "cpl_multiproc.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "gdaljp2abstractdataset.h"
 #include "gdaljp2metadata.h"
-#include "cpl_multiproc.h"
-#include "cpl_atomic_ops.h"
 #include "vrt/vrtdataset.h"
 
-CPL_CVSID("$Id: openjpegdataset.cpp 29330 2015-06-14 12:11:11Z rouault $");
+CPL_CVSID("$Id: openjpegdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /*                  JP2OpenJPEGDataset_ErrorCallback()                  */
@@ -79,7 +80,9 @@ static void JP2OpenJPEGDataset_WarningCallback(const char *pszMsg, CPL_UNUSED vo
 
 static void JP2OpenJPEGDataset_InfoCallback(const char *pszMsg, CPL_UNUSED void *unused)
 {
-    char* pszMsgTmp = CPLStrdup(pszMsg);
+    char* pszMsgTmp = VSIStrdup(pszMsg);
+    if( pszMsgTmp == NULL )
+        return;
     int nLen = (int)strlen(pszMsgTmp);
     while( nLen > 0 && pszMsgTmp[nLen-1] == '\n' )
     {
@@ -104,7 +107,7 @@ static OPJ_SIZE_T JP2OpenJPEGDataset_Read(void* pBuffer, OPJ_SIZE_T nBytes,
                                        void *pUserData)
 {
     JP2OpenJPEGFile* psJP2OpenJPEGFile = (JP2OpenJPEGFile* )pUserData;
-    int nRet = VSIFReadL(pBuffer, 1, nBytes, psJP2OpenJPEGFile->fp);
+    int nRet = static_cast<int>(VSIFReadL(pBuffer, 1, nBytes, psJP2OpenJPEGFile->fp));
 #ifdef DEBUG_IO
     CPLDebug("OPENJPEG", "JP2OpenJPEGDataset_Read(%d) = %d", (int)nBytes, nRet);
 #endif
@@ -122,7 +125,7 @@ static OPJ_SIZE_T JP2OpenJPEGDataset_Write(void* pBuffer, OPJ_SIZE_T nBytes,
                                        void *pUserData)
 {
     JP2OpenJPEGFile* psJP2OpenJPEGFile = (JP2OpenJPEGFile* )pUserData;
-    int nRet = VSIFWriteL(pBuffer, 1, nBytes, psJP2OpenJPEGFile->fp);
+    int nRet = static_cast<int>(VSIFWriteL(pBuffer, 1, nBytes, psJP2OpenJPEGFile->fp));
 #ifdef DEBUG_IO
     CPLDebug("OPENJPEG", "JP2OpenJPEGDataset_Write(%d) = %d", (int)nBytes, nRet);
 #endif
@@ -201,12 +204,12 @@ class JP2OpenJPEGDataset : public GDALJP2AbstractDataset
   public:
                 JP2OpenJPEGDataset();
                 ~JP2OpenJPEGDataset();
-    
+
     static int Identify( GDALOpenInfo * poOpenInfo );
     static GDALDataset  *Open( GDALOpenInfo * );
     static GDALDataset  *CreateCopy( const char * pszFilename,
-                                           GDALDataset *poSrcDS, 
-                                           int bStrict, char ** papszOptions, 
+                                           GDALDataset *poSrcDS,
+                                           int bStrict, char ** papszOptions,
                                            GDALProgressFunc pfnProgress,
                                            void * pProgressData );
 
@@ -223,7 +226,7 @@ class JP2OpenJPEGDataset : public GDALJP2AbstractDataset
     virtual CPLErr  IRasterIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
                                void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType, 
+                               GDALDataType eBufType,
                                int nBandCount, int *panBandMap,
                                GSpacing nPixelSpace, GSpacing nLineSpace,
                                GSpacing nBandSpace,
@@ -246,6 +249,8 @@ class JP2OpenJPEGDataset : public GDALJP2AbstractDataset
     int         PreloadBlocks( JP2OpenJPEGRasterBand* poBand,
                                int nXOff, int nYOff, int nXSize, int nYSize,
                                int nBandCount, int *panBandMap );
+
+    static void JP2OpenJPEGReadBlockInThread(void* userdata);
 };
 
 /************************************************************************/
@@ -281,7 +286,7 @@ class JP2OpenJPEGRasterBand : public GDALPamRasterBand
 
     virtual int             GetOverviewCount();
     virtual GDALRasterBand* GetOverview(int iOvrLevel);
-    
+
     virtual int HasArbitraryOverviews() { return poCT == NULL; }
 };
 
@@ -290,16 +295,16 @@ class JP2OpenJPEGRasterBand : public GDALPamRasterBand
 /*                        JP2OpenJPEGRasterBand()                       */
 /************************************************************************/
 
-JP2OpenJPEGRasterBand::JP2OpenJPEGRasterBand( JP2OpenJPEGDataset *poDS, int nBand,
-                                              GDALDataType eDataType, int nBits,
-                                              int bPromoteTo8Bit,
-                                              int nBlockXSize, int nBlockYSize )
+JP2OpenJPEGRasterBand::JP2OpenJPEGRasterBand( JP2OpenJPEGDataset *poDSIn, int nBandIn,
+                                              GDALDataType eDataTypeIn, int nBits,
+                                              int bPromoteTo8BitIn,
+                                              int nBlockXSizeIn, int nBlockYSizeIn )
 
 {
-    this->eDataType = eDataType;
-    this->nBlockXSize = nBlockXSize;
-    this->nBlockYSize = nBlockYSize;
-    this->bPromoteTo8Bit = bPromoteTo8Bit;
+    this->eDataType = eDataTypeIn;
+    this->nBlockXSize = nBlockXSizeIn;
+    this->nBlockYSize = nBlockYSizeIn;
+    this->bPromoteTo8Bit = bPromoteTo8BitIn;
     poCT = NULL;
 
     if( (nBits % 8) != 0 )
@@ -308,8 +313,8 @@ JP2OpenJPEGRasterBand::JP2OpenJPEGRasterBand( JP2OpenJPEGDataset *poDS, int nBan
                         "IMAGE_STRUCTURE" );
     GDALRasterBand::SetMetadataItem("COMPRESSION", "JPEG2000",
                     "IMAGE_STRUCTURE" );
-    this->poDS = poDS;
-    this->nBand = nBand;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
 }
 
 /************************************************************************/
@@ -374,27 +379,22 @@ CPLErr JP2OpenJPEGRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     if( (nBufXSize < nXSize || nBufYSize < nYSize)
         && GetOverviewCount() > 0 && eRWFlag == GF_Read )
     {
-        int         nOverview;
-        GDALRasterIOExtraArg sExtraArg;
-    
-        GDALCopyRasterIOExtraArg(&sExtraArg, psExtraArg);
-
-        nOverview =
-            GDALBandGetBestOverviewLevel2(this, nXOff, nYOff, nXSize, nYSize,
-                                        nBufXSize, nBufYSize, &sExtraArg);
-        if (nOverview >= 0)
-        {
-            GDALRasterBand* poOverviewBand = GetOverview(nOverview);
-            if (poOverviewBand == NULL)
-                return CE_Failure;
-
-            return poOverviewBand->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                                            pData, nBufXSize, nBufYSize, eBufType,
-                                            nPixelSpace, nLineSpace, &sExtraArg );
-        }
+        int bTried;
+        CPLErr eErr = TryOverviewRasterIO( eRWFlag,
+                                    nXOff, nYOff, nXSize, nYSize,
+                                    pData, nBufXSize, nBufYSize,
+                                    eBufType,
+                                    nPixelSpace, nLineSpace,
+                                    psExtraArg,
+                                    &bTried );
+        if( bTried )
+            return eErr;
     }
 
-    poGDS->bEnoughMemoryToLoadOtherBands = poGDS->PreloadBlocks(this, nXOff, nYOff, nXSize, nYSize, 0, NULL);
+    int nRet = poGDS->PreloadBlocks(this, nXOff, nYOff, nXSize, nYSize, 0, NULL);
+    if( nRet < 0 )
+        return CE_Failure;
+    poGDS->bEnoughMemoryToLoadOtherBands = nRet;
 
     CPLErr eErr = GDALPamRasterBand::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
                                          pData, nBufXSize, nBufYSize, eBufType,
@@ -439,12 +439,22 @@ public:
     volatile int        nCurPair;
     int                 nBandCount;
     int                *panBandMap;
+    VOLATILE_BOOL       bSuccess;
 };
 
-static void JP2OpenJPEGReadBlockInThread(void* userdata)
+void JP2OpenJPEGDataset::JP2OpenJPEGReadBlockInThread(void* userdata)
 {
     int nPair;
     JobStruct* poJob = (JobStruct*) userdata;
+
+    /*void* pDummy = VSIMalloc(128*1024);
+    if( pDummy == NULL )
+    {
+        fprintf(stderr, "Out of memory in thread\n");
+        poJob->bSuccess = false;
+        return;
+    }*/
+
     JP2OpenJPEGDataset* poGDS = poJob->poGDS;
     int nBand = poJob->nBand;
     int nPairs = (int)poJob->oPairs.size();
@@ -454,32 +464,38 @@ static void JP2OpenJPEGReadBlockInThread(void* userdata)
     if( fp == NULL )
     {
         CPLDebug("OPENJPEG", "Cannot open %s", poGDS->GetDescription());
+        poJob->bSuccess = false;
+        //VSIFree(pDummy);
         return;
     }
 
-    while( (nPair = CPLAtomicInc(&(poJob->nCurPair))) < nPairs )
+    while( (nPair = CPLAtomicInc(&(poJob->nCurPair))) < nPairs ||
+           !poJob->bSuccess )
     {
         int nBlockXOff = poJob->oPairs[nPair].first;
         int nBlockYOff = poJob->oPairs[nPair].second;
+        poGDS->AcquireMutex();
         GDALRasterBlock* poBlock = poGDS->GetRasterBand(nBand)->
                 GetLockedBlockRef(nBlockXOff,nBlockYOff, TRUE);
+        poGDS->ReleaseMutex();
         if (poBlock == NULL)
+        {
+            poJob->bSuccess = false;
             break;
+        }
 
         void* pDstBuffer = poBlock->GetDataRef();
-        if (!pDstBuffer)
+        if( poGDS->ReadBlock(nBand, fp, nBlockXOff, nBlockYOff, pDstBuffer,
+                             nBandCount, panBandMap) != CE_None )
         {
-            poBlock->DropLock();
-            break;
+            poJob->bSuccess = false;
         }
 
-        poGDS->ReadBlock(nBand, fp, nBlockXOff, nBlockYOff, pDstBuffer,
-                         nBandCount, panBandMap);
-
         poBlock->DropLock();
     }
 
     VSIFCloseL(fp);
+    //VSIFree(pDummy);
 }
 
 /************************************************************************/
@@ -504,35 +520,45 @@ int JP2OpenJPEGDataset::PreloadBlocks(JP2OpenJPEGRasterBand* poBand,
         if( nReqMem > GDALGetCacheMax64() / (nBandCount == 0 ? 1 : nBandCount) )
             return FALSE;
 
+        JobStruct oJob;
         int nBlocksToLoad = 0;
-        std::vector< std::pair<int,int> > oPairs;
-        for(int nBlockXOff = nXStart; nBlockXOff <= nXEnd; ++nBlockXOff)
+        try
         {
-            for(int nBlockYOff = nYStart; nBlockYOff <= nYEnd; ++nBlockYOff)
+            for(int nBlockXOff = nXStart; nBlockXOff <= nXEnd; ++nBlockXOff)
             {
-                GDALRasterBlock* poBlock = poBand->TryGetLockedBlockRef(nBlockXOff,nBlockYOff);
-                if (poBlock != NULL)
+                for(int nBlockYOff = nYStart; nBlockYOff <= nYEnd; ++nBlockYOff)
                 {
-                    poBlock->DropLock();
-                    continue;
+                    GDALRasterBlock* poBlock = poBand->TryGetLockedBlockRef(nBlockXOff,nBlockYOff);
+                    if (poBlock != NULL)
+                    {
+                        poBlock->DropLock();
+                        continue;
+                    }
+                    oJob.oPairs.push_back( std::pair<int,int>(nBlockXOff, nBlockYOff) );
+                    nBlocksToLoad ++;
                 }
-                oPairs.push_back( std::pair<int,int>(nBlockXOff, nBlockYOff) );
-                nBlocksToLoad ++;
             }
         }
+        catch( const std::bad_alloc& )
+        {
+            CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory error");
+            return -1;
+        }
 
         if( nBlocksToLoad > 1 )
         {
-            int nThreads = MIN(nBlocksToLoad, nMaxThreads);
-            CPLJoinableThread** pahThreads = (CPLJoinableThread**) CPLMalloc( sizeof(CPLJoinableThread*) * nThreads );
+            int l_nThreads = MIN(nBlocksToLoad, nMaxThreads);
+            CPLJoinableThread** pahThreads = (CPLJoinableThread**) VSI_CALLOC_VERBOSE( sizeof(CPLJoinableThread*), l_nThreads );
+            if( pahThreads == NULL )
+            {
+                return -1;
+            }
             int i;
 
-            CPLDebug("OPENJPEG", "%d blocks to load", nBlocksToLoad);
+            CPLDebug("OPENJPEG", "%d blocks to load (%d threads)", nBlocksToLoad, l_nThreads);
 
-            JobStruct oJob;
             oJob.poGDS = this;
             oJob.nBand = poBand->GetBand();
-            oJob.oPairs = oPairs;
             oJob.nCurPair = -1;
             if( nBandCount > 0 )
             {
@@ -553,6 +579,7 @@ int JP2OpenJPEGDataset::PreloadBlocks(JP2OpenJPEGRasterBand* poBand,
                     oJob.panBandMap = &oJob.nBand;
                 }
             }
+            oJob.bSuccess = true;
 
             /* Flushes all dirty blocks from cache to disk to avoid them */
             /* to be flushed randomly, and simultaneously, from our worker threads, */
@@ -560,11 +587,17 @@ int JP2OpenJPEGDataset::PreloadBlocks(JP2OpenJPEGRasterBand* poBand,
             /* This is a workaround to a design defect of the block cache */
             GDALRasterBlock::FlushDirtyBlocks();
 
-            for(i=0;i<nThreads;i++)
+            for(i=0;i<l_nThreads;i++)
+            {
                 pahThreads[i] = CPLCreateJoinableThread(JP2OpenJPEGReadBlockInThread, &oJob);
-            for(i=0;i<nThreads;i++)
+                if( pahThreads[i] == NULL )
+                    oJob.bSuccess = false;
+            }
+            for(i=0;i<l_nThreads;i++)
                 CPLJoinThread( pahThreads[i] );
             CPLFree(pahThreads);
+            if( !oJob.bSuccess )
+                return -1;
         }
     }
 
@@ -578,7 +611,7 @@ int JP2OpenJPEGDataset::PreloadBlocks(JP2OpenJPEGRasterBand* poBand,
 CPLErr  JP2OpenJPEGDataset::IRasterIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
                                void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType, 
+                               GDALDataType eBufType,
                                int nBandCount, int *panBandMap,
                                GSpacing nPixelSpace, GSpacing nLineSpace,
                                GSpacing nBandSpace,
@@ -600,22 +633,18 @@ CPLErr  JP2OpenJPEGDataset::IRasterIO( GDALRWFlag eRWFlag,
     if( (nBufXSize < nXSize || nBufYSize < nYSize)
         && poBand->GetOverviewCount() > 0 && eRWFlag == GF_Read )
     {
-        int         nOverview;
-        GDALRasterIOExtraArg sExtraArg;
-    
-        GDALCopyRasterIOExtraArg(&sExtraArg, psExtraArg);
-
-        nOverview =
-            GDALBandGetBestOverviewLevel2(poBand, nXOff, nYOff, nXSize, nYSize,
-                                          nBufXSize, nBufYSize, &sExtraArg);
-        if (nOverview >= 0)
-        {
-            return papoOverviewDS[nOverview]->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                                                        pData, nBufXSize, nBufYSize, eBufType,
-                                                        nBandCount, panBandMap,
-                                                        nPixelSpace, nLineSpace, nBandSpace,
-                                                        &sExtraArg);
-        }
+        int bTried;
+        CPLErr eErr = TryOverviewRasterIO( eRWFlag,
+                                    nXOff, nYOff, nXSize, nYSize,
+                                    pData, nBufXSize, nBufYSize,
+                                    eBufType,
+                                    nBandCount, panBandMap,
+                                    nPixelSpace, nLineSpace,
+                                    nBandSpace,
+                                    psExtraArg,
+                                    &bTried );
+        if( bTried )
+            return eErr;
     }
 
     bEnoughMemoryToLoadOtherBands = PreloadBlocks(poBand, nXOff, nYOff, nXSize, nYSize, nBandCount, panBandMap);
@@ -623,7 +652,7 @@ CPLErr  JP2OpenJPEGDataset::IRasterIO( GDALRWFlag eRWFlag,
     CPLErr eErr = GDALPamDataset::IRasterIO(   eRWFlag,
                                         nXOff, nYOff, nXSize, nYSize,
                                         pData, nBufXSize, nBufYSize,
-                                        eBufType, 
+                                        eBufType,
                                         nBandCount, panBandMap,
                                         nPixelSpace, nLineSpace, nBandSpace,
                                         psExtraArg );
@@ -640,6 +669,8 @@ static opj_stream_t* JP2OpenJPEGCreateReadStream(JP2OpenJPEGFile* psJP2OpenJPEGF
                                                  vsi_l_offset nSize)
 {
     opj_stream_t *pStream = opj_stream_create(1024, TRUE); // Default 1MB is way too big for some datasets
+    if( pStream == NULL )
+        return NULL;
 
     VSIFSeekL(psJP2OpenJPEGFile->fp, psJP2OpenJPEGFile->nBaseOffset, SEEK_SET);
     opj_stream_set_user_data_length(pStream, nSize);
@@ -660,15 +691,16 @@ static opj_stream_t* JP2OpenJPEGCreateReadStream(JP2OpenJPEGFile* psJP2OpenJPEGF
 /*                             ReadBlock()                              */
 /************************************************************************/
 
-CPLErr JP2OpenJPEGDataset::ReadBlock( int nBand, VSILFILE* fp,
+CPLErr JP2OpenJPEGDataset::ReadBlock( int nBand, VSILFILE* fpIn,
                                       int nBlockXOff, int nBlockYOff, void * pImage,
                                       int nBandCount, int* panBandMap )
 {
     CPLErr          eErr = CE_None;
-    opj_codec_t*    pCodec;
-    opj_stream_t *  pStream;
-    opj_image_t *   psImage;
-    
+    opj_codec_t*    pCodec = NULL;
+    opj_stream_t *  pStream = NULL;
+    opj_image_t *   psImage = NULL;
+    JP2OpenJPEGFile sJP2OpenJPEGFile;
+
     JP2OpenJPEGRasterBand* poBand = (JP2OpenJPEGRasterBand*) GetRasterBand(nBand);
     int nBlockXSize = poBand->nBlockXSize;
     int nBlockYSize = poBand->nBlockYSize;
@@ -681,6 +713,12 @@ CPLErr JP2OpenJPEGDataset::ReadBlock( int nBand, VSILFILE* fp,
     int nHeightToRead = MIN(nBlockYSize, nRasterYSize - nBlockYOff * nBlockYSize);
 
     pCodec = opj_create_decompress(OPJ_CODEC_J2K);
+    if( pCodec == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "opj_create_decompress() failed");
+        eErr = CE_Failure;
+        goto end;
+    }
 
     opj_set_info_handler(pCodec, JP2OpenJPEGDataset_InfoCallback,NULL);
     opj_set_warning_handler(pCodec, JP2OpenJPEGDataset_WarningCallback, NULL);
@@ -692,18 +730,28 @@ CPLErr JP2OpenJPEGDataset::ReadBlock( int nBand, VSILFILE* fp,
     if (! opj_setup_decoder(pCodec,&parameters))
     {
         CPLError(CE_Failure, CPLE_AppDefined, "opj_setup_decoder() failed");
-        return CE_Failure;
+        eErr = CE_Failure;
+        goto end;
     }
 
-    JP2OpenJPEGFile sJP2OpenJPEGFile;
-    sJP2OpenJPEGFile.fp = fp;
+    sJP2OpenJPEGFile.fp = fpIn;
     sJP2OpenJPEGFile.nBaseOffset = nCodeStreamStart;
     pStream = JP2OpenJPEGCreateReadStream(&sJP2OpenJPEGFile, nCodeStreamLength);
+    if( pStream == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "JP2OpenJPEGCreateReadStream() failed");
+        eErr = CE_Failure;
+        goto end;
+    }
 
     if(!opj_read_header(pStream,pCodec,&psImage))
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "opj_read_header() failed");
+        CPLError(CE_Failure, CPLE_AppDefined, "opj_read_header() failed (psImage=%p)", psImage);
+        // We may leak objects, but the cleanup of openjpeg can cause
+        // double frees sometimes...
         return CE_Failure;
+        //eErr = CE_Failure;
+        //goto end;
     }
 
     if (!opj_set_decoded_resolution_factor( pCodec, iLevel ))
@@ -742,6 +790,17 @@ CPLErr JP2OpenJPEGDataset::ReadBlock( int nBand, VSILFILE* fp,
         }
     }
 
+    for(unsigned int iBand = 0; iBand < psImage->numcomps; iBand ++)
+    {
+        if( psImage->comps[iBand].data == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "psImage->comps[%d].data == NULL", iBand);
+            eErr = CE_Failure;
+            goto end;
+        }
+    }
+
     for(int xBand = 0; xBand < nBandCount; xBand ++)
     {
         void* pDstBuffer;
@@ -753,66 +812,81 @@ CPLErr JP2OpenJPEGDataset::ReadBlock( int nBand, VSILFILE* fp,
             pDstBuffer = pImage;
         else
         {
+            AcquireMutex();
             poBlock = ((JP2OpenJPEGRasterBand*)GetRasterBand(iBand))->
                 TryGetLockedBlockRef(nBlockXOff,nBlockYOff);
             if (poBlock != NULL)
             {
+                ReleaseMutex();
                 poBlock->DropLock();
                 continue;
             }
 
             poBlock = GetRasterBand(iBand)->
                 GetLockedBlockRef(nBlockXOff,nBlockYOff, TRUE);
+            ReleaseMutex();
             if (poBlock == NULL)
             {
                 continue;
             }
 
             pDstBuffer = poBlock->GetDataRef();
-            if (!pDstBuffer)
-            {
-                poBlock->DropLock();
-                continue;
-            }
         }
 
         if (bIs420)
         {
-            CPLAssert((int)psImage->comps[0].w >= nWidthToRead);
-            CPLAssert((int)psImage->comps[0].h >= nHeightToRead);
-            CPLAssert(psImage->comps[1].w == (psImage->comps[0].w + 1) / 2);
-            CPLAssert(psImage->comps[1].h == (psImage->comps[0].h + 1) / 2);
-            CPLAssert(psImage->comps[2].w == (psImage->comps[0].w + 1) / 2);
-            CPLAssert(psImage->comps[2].h == (psImage->comps[0].h + 1) / 2);
-            if( nBands == 4 )
+            if( (int)psImage->comps[0].w < nWidthToRead ||
+                (int)psImage->comps[0].h < nHeightToRead ||
+                psImage->comps[1].w != (psImage->comps[0].w + 1) / 2 ||
+                psImage->comps[1].h != (psImage->comps[0].h + 1) / 2 ||
+                psImage->comps[2].w != (psImage->comps[0].w + 1) / 2 ||
+                psImage->comps[2].h != (psImage->comps[0].h + 1) / 2 ||
+                (nBands == 4 && (
+                    (int)psImage->comps[3].w < nWidthToRead ||
+                    (int)psImage->comps[3].h < nHeightToRead)) )
             {
-                CPLAssert((int)psImage->comps[3].w >= nWidthToRead);
-                CPLAssert((int)psImage->comps[3].h >= nHeightToRead);
+                CPLError(CE_Failure, CPLE_AssertionFailed,
+                         "Assertion at line %d of %s failed",
+                         __LINE__, __FILE__);
+                if (poBlock != NULL)
+                    poBlock->DropLock();
+                eErr = CE_Failure;
+                goto end;
             }
 
-            OPJ_INT32* pSrcY = psImage->comps[0].data;
-            OPJ_INT32* pSrcCb = psImage->comps[1].data;
-            OPJ_INT32* pSrcCr = psImage->comps[2].data;
-            OPJ_INT32* pSrcA = (nBands == 4) ? psImage->comps[3].data : NULL;
             GByte* pDst = (GByte*)pDstBuffer;
-            for(int j=0;j<nHeightToRead;j++)
+            if( iBand == 4 )
             {
-                for(int i=0;i<nWidthToRead;i++)
+                const OPJ_INT32* pSrcA = psImage->comps[3].data;
+                for(int j=0;j<nHeightToRead;j++)
                 {
-                    int Y = pSrcY[j * psImage->comps[0].w + i];
-                    int Cb = pSrcCb[(j/2) * psImage->comps[1].w + (i/2)];
-                    int Cr = pSrcCr[(j/2) * psImage->comps[2].w + (i/2)];
-                    if (iBand == 1)
-                        pDst[j * nBlockXSize + i] = CLAMP_0_255((int)(Y + 1.402 * (Cr - 128)));
-                    else if (iBand == 2)
-                        pDst[j * nBlockXSize + i] = CLAMP_0_255((int)(Y - 0.34414 * (Cb - 128) - 0.71414 * (Cr - 128)));
-                    else if (iBand == 3)
-                        pDst[j * nBlockXSize + i] = CLAMP_0_255((int)(Y + 1.772 * (Cb - 128)));
-                    else if (iBand == 4)
-                        pDst[j * nBlockXSize + i] = pSrcA[j * psImage->comps[0].w + i];
+                    memcpy(pDst + j*nBlockXSize,
+                            pSrcA + j * psImage->comps[0].w,
+                            nWidthToRead);
                 }
             }
-            
+            else
+            {
+                const OPJ_INT32* pSrcY = psImage->comps[0].data;
+                const OPJ_INT32* pSrcCb = psImage->comps[1].data;
+                const OPJ_INT32* pSrcCr = psImage->comps[2].data;
+                for(int j=0;j<nHeightToRead;j++)
+                {
+                    for(int i=0;i<nWidthToRead;i++)
+                    {
+                        int Y = pSrcY[j * psImage->comps[0].w + i];
+                        int Cb = pSrcCb[(j/2) * psImage->comps[1].w + (i/2)];
+                        int Cr = pSrcCr[(j/2) * psImage->comps[2].w + (i/2)];
+                        if (iBand == 1)
+                            pDst[j * nBlockXSize + i] = CLAMP_0_255((int)(Y + 1.402 * (Cr - 128)));
+                        else if (iBand == 2)
+                            pDst[j * nBlockXSize + i] = CLAMP_0_255((int)(Y - 0.34414 * (Cb - 128) - 0.71414 * (Cr - 128)));
+                        else if (iBand == 3)
+                            pDst[j * nBlockXSize + i] = CLAMP_0_255((int)(Y + 1.772 * (Cb - 128)));
+                    }
+                }
+            }
+
             if( bPromoteTo8Bit )
             {
                 for(int j=0;j<nHeightToRead;j++)
@@ -826,9 +900,18 @@ CPLErr JP2OpenJPEGDataset::ReadBlock( int nBand, VSILFILE* fp,
         }
         else
         {
-            CPLAssert((int)psImage->comps[iBand-1].w >= nWidthToRead);
-            CPLAssert((int)psImage->comps[iBand-1].h >= nHeightToRead);
-            
+            if( (int)psImage->comps[iBand-1].w < nWidthToRead ||
+                (int)psImage->comps[iBand-1].h < nHeightToRead )
+            {
+                CPLError(CE_Failure, CPLE_AssertionFailed,
+                         "Assertion at line %d of %s failed",
+                         __LINE__, __FILE__);
+                if (poBlock != NULL)
+                    poBlock->DropLock();
+                eErr = CE_Failure;
+                goto end;
+            }
+
             if( bPromoteTo8Bit )
             {
                 for(int j=0;j<nHeightToRead;j++)
@@ -862,10 +945,14 @@ CPLErr JP2OpenJPEGDataset::ReadBlock( int nBand, VSILFILE* fp,
     }
 
 end:
-    opj_end_decompress(pCodec,pStream);
-    opj_stream_destroy(pStream);
-    opj_destroy_codec(pCodec);
-    opj_image_destroy(psImage);
+    if( pCodec && pStream )
+        opj_end_decompress(pCodec,pStream);
+    if( pStream )
+        opj_stream_destroy(pStream);
+    if( pCodec )
+        opj_destroy_codec(pCodec);
+    if( psImage )
+        opj_image_destroy(psImage);
 
     return eErr;
 }
@@ -1060,7 +1147,7 @@ JP2OpenJPEGDataset::~JP2OpenJPEGDataset()
                 pszGMLJP2 = "GMLJP2=NO";
 
             const char* pszGeoJP2;
-            int bGeoreferencingCompatOfGeoJP2 = 
+            int bGeoreferencingCompatOfGeoJP2 =
                     ((pszProjection != NULL && pszProjection[0] != '\0' ) ||
                     nGCPCount != 0 || bGeoTransformValid);
             if( bGeoreferencingCompatOfGeoJP2 &&
@@ -1077,7 +1164,7 @@ JP2OpenJPEGDataset::~JP2OpenJPEGDataset()
                 VSIFSeekL(fp, nOffsetJP2C - 8, SEEK_SET);
                 GByte abyBuffer[8];
                 VSIFReadL(abyBuffer, 1, 8, fp);
-                if( EQUALN((const char*)abyBuffer + 4, "jp2c", 4) &&
+                if( STARTS_WITH_CI((const char*)abyBuffer + 4, "jp2c") &&
                     abyBuffer[0] == 0 && abyBuffer[1] == 0 &&
                     abyBuffer[2] == 0 && abyBuffer[3] == 0 )
                 {
@@ -1160,7 +1247,7 @@ JP2OpenJPEGDataset::~JP2OpenJPEGDataset()
                 }
 
                 WriteXMPBox(fp, this, NULL);
-                
+
                 VSIFTruncateL( fp, VSIFTellL(fp) );
 
                 VSIFCloseL( fp );
@@ -1168,7 +1255,7 @@ JP2OpenJPEGDataset::~JP2OpenJPEGDataset()
             else
             {
                 VSIFCloseL( fp );
-                
+
                 CPLDebug("OPENJPEG", "Rewriting whole file");
 
                 const char* apszOptions[] = {
@@ -1320,14 +1407,14 @@ static const unsigned char jp2_box_jp[] = {0x6a,0x50,0x20,0x20}; /* 'jP  ' */
 int JP2OpenJPEGDataset::Identify( GDALOpenInfo * poOpenInfo )
 
 {
-    if( poOpenInfo->nHeaderBytes >= 16 
-        && (memcmp( poOpenInfo->pabyHeader, jpc_header, 
+    if( poOpenInfo->nHeaderBytes >= 16
+        && (memcmp( poOpenInfo->pabyHeader, jpc_header,
                     sizeof(jpc_header) ) == 0
-            || memcmp( poOpenInfo->pabyHeader + 4, jp2_box_jp, 
+            || memcmp( poOpenInfo->pabyHeader + 4, jp2_box_jp,
                     sizeof(jp2_box_jp) ) == 0
            ) )
         return TRUE;
-    
+
     else
         return FALSE;
 }
@@ -1402,6 +1489,8 @@ GDALDataset *JP2OpenJPEGDataset::Open( GDALOpenInfo * poOpenInfo )
     opj_codec_t* pCodec;
 
     pCodec = opj_create_decompress(OPJ_CODEC_J2K);
+    if( pCodec == NULL )
+        return NULL;
 
     opj_set_info_handler(pCodec, JP2OpenJPEGDataset_InfoCallback,NULL);
     opj_set_warning_handler(pCodec, JP2OpenJPEGDataset_WarningCallback, NULL);
@@ -1412,6 +1501,7 @@ GDALDataset *JP2OpenJPEGDataset::Open( GDALOpenInfo * poOpenInfo )
 
     if (! opj_setup_decoder(pCodec,&parameters))
     {
+        opj_destroy_codec(pCodec);
         return NULL;
     }
 
@@ -1423,6 +1513,14 @@ GDALDataset *JP2OpenJPEGDataset::Open( GDALOpenInfo * poOpenInfo )
 
     opj_image_t * psImage = NULL;
 
+    if( pStream == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "JP2OpenJPEGCreateReadStream() failed");
+        opj_stream_destroy(pStream);
+        opj_destroy_codec(pCodec);
+        return NULL;
+    }
+
     if(!opj_read_header(pStream,pCodec,&psImage))
     {
         CPLError(CE_Failure, CPLE_AppDefined, "opj_read_header() failed");
@@ -1457,7 +1555,6 @@ GDALDataset *JP2OpenJPEGDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
 #ifdef DEBUG
-    int i;
     CPLDebug("OPENJPEG", "nX0 = %u", nX0);
     CPLDebug("OPENJPEG", "nY0 = %u", nY0);
     CPLDebug("OPENJPEG", "nTileW = %u", nTileW);
@@ -1472,7 +1569,7 @@ GDALDataset *JP2OpenJPEGDataset::Open( GDALOpenInfo * poOpenInfo )
     CPLDebug("OPENJPEG", "psImage->numcomps = %d", psImage->numcomps);
     //CPLDebug("OPENJPEG", "psImage->color_space = %d", psImage->color_space);
     CPLDebug("OPENJPEG", "numResolutions = %d", numResolutions);
-    for(i=0;i<(int)psImage->numcomps;i++)
+    for(int i=0;i<(int)psImage->numcomps;i++)
     {
         CPLDebug("OPENJPEG", "psImage->comps[%d].dx = %u", i, psImage->comps[i].dx);
         CPLDebug("OPENJPEG", "psImage->comps[%d].dy = %u", i, psImage->comps[i].dy);
@@ -1527,7 +1624,7 @@ GDALDataset *JP2OpenJPEGDataset::Open( GDALOpenInfo * poOpenInfo )
                     psImage->comps[1].h == psImage->comps[0].h / 2 &&
                     psImage->comps[2].w == psImage->comps[0].w / 2 &&
                     psImage->comps[2].h == psImage->comps[0].h / 2) &&
-                    (psImage->numcomps == 3 || 
+                    (psImage->numcomps == 3 ||
                      (psImage->numcomps == 4 &&
                       psImage->comps[3].w == psImage->comps[0].w &&
                       psImage->comps[3].h == psImage->comps[0].h));
@@ -1573,13 +1670,25 @@ GDALDataset *JP2OpenJPEGDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->nCodeStreamLength = nCodeStreamLength;
     poDS->bIs420 = bIs420;
 
-    poDS->bUseSetDecodeArea = 
+    poDS->bUseSetDecodeArea =
         (poDS->nRasterXSize == (int)nTileW &&
          poDS->nRasterYSize == (int)nTileH &&
          (poDS->nRasterXSize > 1024 ||
           poDS->nRasterYSize > 1024));
 
-    if (poDS->bUseSetDecodeArea)
+    /* Sentinel2 preview datasets are 343x343 and 60m are 1830x1830, but they */
+    /* are tiled with tile dimensions 2048x2048. It would be a waste of */
+    /* memory to allocate such big blocks */
+    if( poDS->nRasterXSize < (int)nTileW &&
+        poDS->nRasterYSize < (int)nTileH )
+    {
+        poDS->bUseSetDecodeArea = TRUE;
+        nTileW = poDS->nRasterXSize;
+        nTileH = poDS->nRasterYSize;
+        if (nTileW > 2048) nTileW = 2048;
+        if (nTileH > 2048) nTileH = 2048;
+    }
+    else if (poDS->bUseSetDecodeArea)
     {
         if (nTileW > 1024) nTileW = 1024;
         if (nTileH > 1024) nTileH = 1024;
@@ -1777,9 +1886,9 @@ GDALDataset *JP2OpenJPEGDataset::Open( GDALOpenInfo * poOpenInfo )
         int bPromoteTo8Bit = (
             iBand == poDS->nAlphaIndex + 1 &&
             psImage->comps[(poDS->nAlphaIndex==0 && poDS->nBands > 1) ? 1 : 0].prec == 8 &&
-            psImage->comps[poDS->nAlphaIndex ].prec == 1 && 
+            psImage->comps[poDS->nAlphaIndex ].prec == 1 &&
             CSLFetchBoolean(poOpenInfo->papszOpenOptions, "1BIT_ALPHA_PROMOTION",
-                    CSLTestBoolean(CPLGetConfigOption("JP2OPENJPEG_PROMOTE_1BIT_ALPHA_AS_8BIT", "YES"))) );
+                    CPLTestBool(CPLGetConfigOption("JP2OPENJPEG_PROMOTE_1BIT_ALPHA_AS_8BIT", "YES"))) );
         if( bPromoteTo8Bit )
             CPLDebug("JP2OpenJPEG", "Alpha band is promoted from 1 bit to 8 bit");
 
@@ -1849,9 +1958,9 @@ GDALDataset *JP2OpenJPEGDataset::Open( GDALOpenInfo * poOpenInfo )
             int bPromoteTo8Bit = (
                 iBand == poDS->nAlphaIndex + 1 &&
                 psImage->comps[(poDS->nAlphaIndex==0 && poDS->nBands > 1) ? 1 : 0].prec == 8 &&
-                psImage->comps[poDS->nAlphaIndex].prec == 1 && 
+                psImage->comps[poDS->nAlphaIndex].prec == 1 &&
                 CSLFetchBoolean(poOpenInfo->papszOpenOptions, "1BIT_ALPHA_PROMOTION",
-                        CSLTestBoolean(CPLGetConfigOption("JP2OPENJPEG_PROMOTE_1BIT_ALPHA_AS_8BIT", "YES"))) );
+                        CPLTestBool(CPLGetConfigOption("JP2OPENJPEG_PROMOTE_1BIT_ALPHA_AS_8BIT", "YES"))) );
 
             poODS->SetBand( iBand, new JP2OpenJPEGRasterBand( poODS, iBand, eDataType,
                                                               bPromoteTo8Bit ? 8: psImage->comps[iBand-1].prec,
@@ -1882,7 +1991,7 @@ GDALDataset *JP2OpenJPEGDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->LoadJP2Metadata(poOpenInfo);
     poOpenInfo->fpL = NULL;
 
-    poDS->bHasGeoreferencingAtOpening = 
+    poDS->bHasGeoreferencingAtOpening =
         ((poDS->pszProjection != NULL && poDS->pszProjection[0] != '\0' )||
          poDS->nGCPCount != 0 || poDS->bGeoTransformValid);
 
@@ -2017,8 +2126,8 @@ static int FloorPowerOfTwo(int nVal)
 /************************************************************************/
 
 GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
-                                           GDALDataset *poSrcDS, 
-                                           int bStrict, char ** papszOptions, 
+                                           GDALDataset *poSrcDS,
+                                           CPL_UNUSED int bStrict, char ** papszOptions,
                                            GDALProgressFunc pfnProgress,
                                            void * pProgressData )
 
@@ -2097,10 +2206,23 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
         return NULL;
     }
 
-    if (nXSize < nBlockXSize)
-        nBlockXSize = nXSize;
-    if (nYSize < nBlockYSize)
-        nBlockYSize = nYSize;
+    // By default do not generate tile sizes larger than the dataset
+    // dimensions
+    if( !CSLFetchBoolean(papszOptions, "BLOCKSIZE_STRICT", FALSE) )
+    {
+        if (nXSize < nBlockXSize)
+        {
+            CPLDebug("OPENJPEG", "Adjusting block width from %d to %d",
+                     nBlockXSize, nXSize);
+            nBlockXSize = nXSize;
+        }
+        if (nYSize < nBlockYSize)
+        {
+            CPLDebug("OPENJPEG", "Adjusting block width from %d to %d",
+                     nBlockYSize, nYSize);
+            nBlockYSize = nYSize;
+        }
+    }
 
     OPJ_PROG_ORDER eProgOrder = OPJ_LRCP;
     const char* pszPROGORDER =
@@ -2188,8 +2310,8 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
         }
     }
 
-    int bSOP = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SOP", "FALSE"));
-    int bEPH = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "EPH", "FALSE"));
+    int bSOP = CPLTestBool(CSLFetchNameValueDef(papszOptions, "SOP", "FALSE"));
+    int bEPH = CPLTestBool(CSLFetchNameValueDef(papszOptions, "EPH", "FALSE"));
 
     int nRedBandIndex = -1, nGreenBandIndex = -1, nBlueBandIndex = -1;
     int nAlphaBandIndex = -1;
@@ -2206,14 +2328,14 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
             nAlphaBandIndex = i;
     }
     const char* pszAlpha = CSLFetchNameValue(papszOptions, "ALPHA");
-    if( nAlphaBandIndex < 0 && nBands > 1 && pszAlpha != NULL && CSLTestBoolean(pszAlpha) )
+    if( nAlphaBandIndex < 0 && nBands > 1 && pszAlpha != NULL && CPLTestBool(pszAlpha) )
     {
         nAlphaBandIndex = nBands - 1;
     }
 
     const char* pszYCBCR420 = CSLFetchNameValue(papszOptions, "YCBCR420");
     int bYCBCR420 = FALSE;
-    if( pszYCBCR420 && CSLTestBoolean(pszYCBCR420) )
+    if( pszYCBCR420 && CPLTestBool(pszYCBCR420) )
     {
         if ((nBands == 3 || nBands == 4) && eDataType == GDT_Byte &&
             nRedBandIndex == 0 && nGreenBandIndex == 1 && nBlueBandIndex == 2)
@@ -2237,8 +2359,8 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
 
     const char* pszYCC = CSLFetchNameValue(papszOptions, "YCC");
     int bYCC = ((nBands == 3 || nBands == 4) && eDataType == GDT_Byte &&
-            CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "YCC", "TRUE")));
-    
+            CPLTestBool(CSLFetchNameValueDef(papszOptions, "YCC", "TRUE")));
+
     /* TODO: when OpenJPEG 2.2 is released, make this conditional */
     /* Depending on the way OpenJPEG <= r2950 is built, YCC with 4 bands might work on
      * Debug mode, but this relies on unreliable stack buffer overflows, so
@@ -2253,7 +2375,7 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
         }
         bYCC = FALSE;
     }
-    
+
     if( bYCBCR420 && bYCC )
     {
         if( pszYCC != NULL )
@@ -2263,7 +2385,7 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
         }
         bYCC = FALSE;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Deal with codeblocks size                                       */
 /* -------------------------------------------------------------------- */
@@ -2388,12 +2510,12 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
             return NULL;
         }
     }
-    else if( poSrcDS->GetRasterBand(1)->GetMetadataItem( "NBITS", "IMAGE_STRUCTURE" ) 
+    else if( poSrcDS->GetRasterBand(1)->GetMetadataItem( "NBITS", "IMAGE_STRUCTURE" )
              != NULL )
     {
-        nBits = atoi(poSrcDS->GetRasterBand(1)->GetMetadataItem( "NBITS", 
+        nBits = atoi(poSrcDS->GetRasterBand(1)->GetMetadataItem( "NBITS",
                                                        "IMAGE_STRUCTURE" ));
-        if( bInspireTG && 
+        if( bInspireTG &&
             !(nBits == 1 || nBits == 8 || nBits == 16 || nBits == 32) )
         {
             /* Implements "NOTE If the original data do not satisfy this "
@@ -2464,7 +2586,7 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
                 oJP2MD.SetGeoTransform( adfGeoTransform );
             }
             bGeoreferencingCompatOfGMLJP2 =
-                        ( pszWKT != NULL && pszWKT[0] != '\0' ) && 
+                        ( pszWKT != NULL && pszWKT[0] != '\0' ) &&
                           poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None;
         }
         if( poSrcDS->GetMetadata("RPC") != NULL )
@@ -2530,7 +2652,7 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
     parameters.irreversible = bIsIrreversible;
     parameters.numresolution = nNumResolutions;
     parameters.prog_order = eProgOrder;
-    parameters.tcp_mct = bYCC;
+    parameters.tcp_mct = static_cast<char>(bYCC);
     parameters.cblockw_init = nCblockW;
     parameters.cblockh_init = nCblockH;
 
@@ -2717,7 +2839,7 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
 /*      Create the dataset.                                             */
 /* -------------------------------------------------------------------- */
 
-    const char* pszAccess = EQUALN(pszFilename, "/vsisubfile/", 12) ? "r+b" : "w+b";
+    const char* pszAccess = STARTS_WITH_CI(pszFilename, "/vsisubfile/") ? "r+b" : "w+b";
     VSILFILE* fp = VSIFOpenL(pszFilename, pszAccess);
     if (fp == NULL)
     {
@@ -2764,7 +2886,7 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
         }
         WriteBox(fp, &ftypBox);
 
-        int bIPR = poSrcDS->GetMetadata("xml:IPR") != NULL &&
+        const bool bIPR = poSrcDS->GetMetadata("xml:IPR") != NULL &&
                    CSLFetchBoolean(papszOptions, "WRITE_METADATA", FALSE);
 
         /* Reader requirement box */
@@ -2777,7 +2899,7 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
             rreqBox.AppendUInt8(0x80 | 0x40 | (bIPR ? 0x20 : 0)); /* FUAM */
             rreqBox.AppendUInt8(0x80); /* DCM */
 
-            rreqBox.AppendUInt16(2 + bIPR); /* NSF: Number of standard features */
+            rreqBox.AppendUInt16(2 + (bIPR ? 1 : 0)); /* NSF: Number of standard features */
 
             rreqBox.AppendUInt16((bProfile1) ? 4 : 5); /* SF0 : PROFILE 1 or PROFILE 2 */
             rreqBox.AppendUInt8(0x80); /* SM0 */
@@ -2798,24 +2920,24 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
         ihdrBox.SetType("ihdr");
         ihdrBox.AppendUInt32(nYSize);
         ihdrBox.AppendUInt32(nXSize);
-        ihdrBox.AppendUInt16(nBands);
+        ihdrBox.AppendUInt16(static_cast<GUInt16>(nBands));
         GByte BPC;
         if( bSamePrecision )
-            BPC = (pasBandParams[0].prec-1) | (pasBandParams[0].sgnd << 7);
+            BPC = static_cast<GByte>((pasBandParams[0].prec-1) | (pasBandParams[0].sgnd << 7));
         else
             BPC = 255;
         ihdrBox.AppendUInt8(BPC);
         ihdrBox.AppendUInt8(7); /* C=Compression type: fixed value */
         ihdrBox.AppendUInt8(0); /* UnkC: 0= colourspace of the image is known */
                                 /*and correctly specified in the Colourspace Specification boxes within the file */
-        ihdrBox.AppendUInt8(bIPR); /* IPR: 0=no intellectual property, 1=IPR box */
+        ihdrBox.AppendUInt8(bIPR ? 1 : 0); /* IPR: 0=no intellectual property, 1=IPR box */
 
         GDALJP2Box bpccBox(fp);
         if( !bSamePrecision )
         {
             bpccBox.SetType("bpcc");
             for(int i=0;i<nBands;i++)
-                bpccBox.AppendUInt8((pasBandParams[i].prec-1) | (pasBandParams[i].sgnd << 7));
+                bpccBox.AppendUInt8(static_cast<GByte>((pasBandParams[i].prec-1) | (pasBandParams[i].sgnd << 7)));
         }
 
         GDALJP2Box colrBox(fp);
@@ -2868,8 +2990,8 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
             nBlueBandIndex = 2;
             nAlphaBandIndex = (nCTComponentCount == 4) ? 3 : -1;
 
-            pclrBox.AppendUInt16(nEntries);
-            pclrBox.AppendUInt8(nCTComponentCount); /* NPC: Number of components */
+            pclrBox.AppendUInt16(static_cast<GUInt16>(nEntries));
+            pclrBox.AppendUInt8(static_cast<GByte>(nCTComponentCount)); /* NPC: Number of components */
             for(int i=0;i<nCTComponentCount;i++)
             {
                 pclrBox.AppendUInt8(7); /* Bi: unsigned 8 bits */
@@ -2883,13 +3005,13 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
                 if( nCTComponentCount == 4 )
                     pclrBox.AppendUInt8((GByte)psEntry->c4);
             }
-            
+
             cmapBox.SetType("cmap");
             for(int i=0;i<nCTComponentCount;i++)
             {
                 cmapBox.AppendUInt16(0); /* CMPi: code stream component index */
                 cmapBox.AppendUInt8(1); /* MYTPi: 1=palette mapping */
-                cmapBox.AppendUInt8(i); /* PCOLi: index component from the map */
+                cmapBox.AppendUInt8(static_cast<GByte>(i)); /* PCOLi: index component from the map */
             }
         }
 
@@ -2901,10 +3023,10 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
         {
             cdefBox.SetType("cdef");
             int nComponents = (nCTComponentCount == 4) ? 4 : nBands;
-            cdefBox.AppendUInt16(nComponents);
+            cdefBox.AppendUInt16(static_cast<GUInt16>(nComponents));
             for(int i=0;i<nComponents;i++)
             {
-                cdefBox.AppendUInt16(i);   /* Component number */
+                cdefBox.AppendUInt16(static_cast<GUInt16>(i));   /* Component number */
                 if( i != nAlphaBandIndex )
                 {
                     cdefBox.AppendUInt16(0);   /* Signification: This channel is the colour image data for the associated colour */
@@ -3123,6 +3245,7 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
         GByte abyBuffer[4096];
         VSIFSeekL( fpSrc, nCodeStreamStart, SEEK_SET );
         vsi_l_offset nRead = 0;
+        /* coverity[tainted_data] */
         while( nRead < nCodeStreamLength )
         {
             int nToRead = ( nCodeStreamLength-nRead > 4096 ) ? 4049 :
@@ -3200,7 +3323,7 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
 
         GUIntBig nTileSize = (GUIntBig)nBlockXSize * nBlockYSize * nBands * nDataTypeSize;
         GByte* pTempBuffer;
-        if( nTileSize != (GUIntBig)(GUInt32)nTileSize )
+        if( nTileSize > UINT_MAX )
         {
             CPLError(CE_Failure, CPLE_NotSupported, "Tile size exceeds 4GB");
             pTempBuffer = NULL;
@@ -3380,7 +3503,7 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
             GUInt32 nBoxSize32 = (GUInt32)nBoxSize;
             if( (vsi_l_offset)nBoxSize32 != nBoxSize )
             {
-                /*  Shouldn't happen hopefully */
+                /*  Should not happen hopefully */
                 if( (bGeoreferencingCompatOfGeoJP2 || poGMLJP2Box) && bGeoBoxesAfter )
                 {
                     CPLError(CE_Warning, CPLE_AppDefined,
@@ -3489,35 +3612,33 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
 void GDALRegister_JP2OpenJPEG()
 
 {
-    GDALDriver  *poDriver;
-    
-    if (! GDAL_CHECK_VERSION("JP2OpenJPEG driver"))
+    if( !GDAL_CHECK_VERSION( "JP2OpenJPEG driver" ) )
         return;
 
-    if( GDALGetDriverByName( "JP2OpenJPEG" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "JP2OpenJPEG" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "JPEG-2000 driver based on OpenJPEG library" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_jp2openjpeg.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/jp2" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jp2" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "jp2 j2k" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte Int16 UInt16 Int32 UInt32" );
-
-        poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST, 
+    if( GDALGetDriverByName( "JP2OpenJPEG" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "JP2OpenJPEG" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "JPEG-2000 driver based on OpenJPEG library" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_jp2openjpeg.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/jp2" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jp2" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "jp2 j2k" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte Int16 UInt16 Int32 UInt32" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
 "<OpenOptionList>"
 "   <Option name='1BIT_ALPHA_PROMOTION' type='boolean' description='Whether a 1-bit alpha channel should be promoted to 8-bit' default='YES'/>"
 "   <Option name='OPEN_REMOTE_GML' type='boolean' description='Whether to load remote vector layers referenced by a link in a GMLJP2 v2 box' default='NO'/>"
 "</OpenOptionList>" );
 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "   <Option name='CODEC' type='string-select' default='according to file extension. If unknown, default to J2K'>"
 "       <Value>JP2</Value>"
@@ -3568,12 +3689,11 @@ void GDALRegister_JP2OpenJPEG()
 "   <Option name='USE_SRC_CODESTREAM' type='boolean' description='When source dataset is JPEG2000, whether to reuse the codestream of the source dataset unmodified' default='NO'/>"
 "</CreationOptionList>"  );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnIdentify = JP2OpenJPEGDataset::Identify;
-        poDriver->pfnOpen = JP2OpenJPEGDataset::Open;
-        poDriver->pfnCreateCopy = JP2OpenJPEGDataset::CreateCopy;
+    poDriver->pfnIdentify = JP2OpenJPEGDataset::Identify;
+    poDriver->pfnOpen = JP2OpenJPEGDataset::Open;
+    poDriver->pfnCreateCopy = JP2OpenJPEGDataset::CreateCopy;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/ozi/ozidataset.cpp b/frmts/ozi/ozidataset.cpp
index f85be77..e0cd02e 100644
--- a/frmts/ozi/ozidataset.cpp
+++ b/frmts/ozi/ozidataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ozidataset.cpp 28039 2014-11-30 18:24:59Z rouault $
+ * $Id: ozidataset.cpp 33105 2016-01-23 15:27:32Z rouault $
  *
  * Project:   OZF2 and OZFx3 binary files driver
  * Purpose:  GDALDataset driver for OZF2 and OZFx3 binary files.
@@ -27,16 +27,13 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 #include "zlib.h"
 
 /* g++ -fPIC -g -Wall frmts/ozi/ozidataset.cpp -shared -o gdal_OZI.so -Iport -Igcore -Iogr -L. -lgdal  */
 
-CPL_CVSID("$Id: ozidataset.cpp 28039 2014-11-30 18:24:59Z rouault $");
-
-CPL_C_START
-void    GDALRegister_OZI(void);
-CPL_C_END
+CPL_CVSID("$Id: ozidataset.cpp 33105 2016-01-23 15:27:32Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -113,10 +110,10 @@ static const GByte abyKey[] =
 
 static void OZIDecrypt(void *pabyVal, int n, GByte nKeyInit)
 {
-    int i;
-    for(i = 0; i < n; i++)
+    for(int i = 0; i < n; i++)
     {
-        ((GByte*)pabyVal)[i] ^= abyKey[i % sizeof(abyKey)] + nKeyInit;
+        reinterpret_cast<GByte*>( pabyVal )[i]
+            ^= abyKey[i % sizeof(abyKey)] + nKeyInit;
     }
 }
 
@@ -142,7 +139,8 @@ static int ReadInt(VSILFILE* fp, int bOzi3 = FALSE, int nKeyInit = 0)
 {
     int nVal;
     VSIFReadL(&nVal, 1, 4, fp);
-    if (bOzi3) OZIDecrypt(&nVal, 4, (GByte) nKeyInit);
+    if (bOzi3)
+        OZIDecrypt(&nVal, 4, static_cast<GByte>( nKeyInit ) );
     CPL_LSBPTR32(&nVal);
     return nVal;
 }
@@ -151,7 +149,8 @@ static short ReadShort(VSILFILE* fp, int bOzi3 = FALSE, int nKeyInit = 0)
 {
     short nVal;
     VSIFReadL(&nVal, 1, 2, fp);
-    if (bOzi3) OZIDecrypt(&nVal, 2, (GByte) nKeyInit);
+    if (bOzi3)
+        OZIDecrypt(&nVal, 2, static_cast<GByte>( nKeyInit ) );
     CPL_LSBPTR16(&nVal);
     return nVal;
 }
@@ -160,13 +159,13 @@ static short ReadShort(VSILFILE* fp, int bOzi3 = FALSE, int nKeyInit = 0)
 /*                         OZIRasterBand()                             */
 /************************************************************************/
 
-OZIRasterBand::OZIRasterBand( OZIDataset *poDS, int nZoomLevel,
-                              int nRasterXSize, int nRasterYSize,
-                              int nXBlocks,
-                              GDALColorTable* poColorTable )
-
+OZIRasterBand::OZIRasterBand( OZIDataset *poDSIn, int nZoomLevelIn,
+                              int nRasterXSizeIn, int nRasterYSizeIn,
+                              int nXBlocksIn,
+                              GDALColorTable* poColorTableIn ) :
+    pabyTranslationTable(NULL)
 {
-    this->poDS = poDS;
+    this->poDS = poDSIn;
     this->nBand = 1;
 
     eDataType = GDT_Byte;
@@ -174,13 +173,11 @@ OZIRasterBand::OZIRasterBand( OZIDataset *poDS, int nZoomLevel,
     nBlockXSize = 64;
     nBlockYSize = 64;
 
-    this->nZoomLevel = nZoomLevel;
-    this->nRasterXSize = nRasterXSize;
-    this->nRasterYSize = nRasterYSize;
-    this->poColorTable = poColorTable;
-    this->nXBlocks = nXBlocks;
-
-    pabyTranslationTable = NULL;
+    this->nZoomLevel = nZoomLevelIn;
+    this->nRasterXSize = nRasterXSizeIn;
+    this->nRasterYSize = nRasterYSizeIn;
+    this->poColorTable = poColorTableIn;
+    this->nXBlocks = nXBlocksIn;
 }
 
 /************************************************************************/
@@ -220,13 +217,13 @@ CPLErr OZIRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                   void * pImage )
 
 {
-    OZIDataset *poGDS = (OZIDataset *) poDS;
+    OZIDataset *poGDS = reinterpret_cast<OZIDataset *>( poDS );
 
-    int nBlock = nBlockYOff * nXBlocks + nBlockXOff;
+    const int nBlock = nBlockYOff * nXBlocks + nBlockXOff;
 
     VSIFSeekL(poGDS->fp, poGDS->panZoomLevelOffsets[nZoomLevel] +
                          12 + 1024 + 4 * nBlock, SEEK_SET);
-    int nPointer = ReadInt(poGDS->fp, poGDS->bOzi3, poGDS->nKeyInit);
+    const int nPointer = ReadInt(poGDS->fp, poGDS->bOzi3, poGDS->nKeyInit);
     if (nPointer < 0  || (vsi_l_offset)nPointer >= poGDS->nFileSize)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -247,8 +244,8 @@ CPLErr OZIRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
     VSIFSeekL(poGDS->fp, nPointer, SEEK_SET);
 
-    int nToRead = nNextPointer - nPointer;
-    GByte* pabyZlibBuffer = (GByte*)CPLMalloc(nToRead);
+    const int nToRead = nNextPointer - nPointer;
+    GByte* pabyZlibBuffer = reinterpret_cast<GByte *>( CPLMalloc( nToRead ) );
     if (VSIFReadL(pabyZlibBuffer, nToRead, 1, poGDS->fp) != 1)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -272,18 +269,17 @@ CPLErr OZIRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     }
 
     z_stream      stream;
-    stream.zalloc = (alloc_func)0;
-    stream.zfree = (free_func)0;
-    stream.opaque = (voidpf)0;
+    stream.zalloc = (alloc_func)NULL;
+    stream.zfree = (free_func)NULL;
+    stream.opaque = (voidpf)NULL;
     stream.next_in = pabyZlibBuffer + 2;
     stream.avail_in = nToRead - 2;
 
     int err = inflateInit2(&(stream), -MAX_WBITS);
 
-    int i;
-    for(i=0;i<64 && err == Z_OK;i++)
+    for( int i = 0; i < 64 && err == Z_OK; i++ )
     {
-        stream.next_out = (Bytef*)pImage + (63 - i) * 64;
+        stream.next_out = reinterpret_cast<Bytef *>( pImage ) + (63 - i) * 64;
         stream.avail_out = 64;
         err = inflate(& (stream), Z_NO_FLUSH);
         if (err != Z_OK && err != Z_STREAM_END)
@@ -291,9 +287,8 @@ CPLErr OZIRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
         if (pabyTranslationTable)
         {
-            int j;
-            GByte* ptr = ((GByte*)pImage) + (63 - i) * 64;
-            for(j=0;j<64;j++)
+            GByte* ptr = reinterpret_cast<GByte *>( pImage ) + (63 - i) * 64;
+            for( int j = 0; j < 64; j++ )
             {
                 *ptr = pabyTranslationTable[*ptr];
                 ptr ++;
@@ -317,7 +312,7 @@ int OZIRasterBand::GetOverviewCount()
     if (nZoomLevel != 0)
         return 0;
 
-    OZIDataset *poGDS = (OZIDataset *) poDS;
+    OZIDataset *poGDS = reinterpret_cast<OZIDataset *>( poDS );
     return poGDS->nZoomLevelCount - 1;
 }
 
@@ -330,7 +325,7 @@ GDALRasterBand* OZIRasterBand::GetOverview(int nLevel)
     if (nZoomLevel != 0)
         return NULL;
 
-    OZIDataset *poGDS = (OZIDataset *) poDS;
+    OZIDataset *poGDS = reinterpret_cast<OZIDataset *>( poDS );
     if (nLevel < 0 || nLevel >= poGDS->nZoomLevelCount - 1)
         return NULL;
 
@@ -341,15 +336,15 @@ GDALRasterBand* OZIRasterBand::GetOverview(int nLevel)
 /*                            ~OZIDataset()                            */
 /************************************************************************/
 
-OZIDataset::OZIDataset()
-{
-    fp = NULL;
-    nZoomLevelCount = 0;
-    panZoomLevelOffsets = NULL;
-    papoOvrBands = NULL;
-    bOzi3 = FALSE;
-    nKeyInit = 0;
-}
+OZIDataset::OZIDataset() :
+    fp(NULL),
+    nZoomLevelCount(0),
+    panZoomLevelOffsets(NULL),
+    papoOvrBands(NULL),
+    nFileSize(0),
+    bOzi3(FALSE),
+    nKeyInit(0)
+{}
 
 /************************************************************************/
 /*                            ~OZIDataset()                            */
@@ -405,12 +400,12 @@ GDALDataset *OZIDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
 
     GByte abyHeader[14];
-    CPLString osImgFilename = poOpenInfo->pszFilename;
     memcpy(abyHeader, poOpenInfo->pabyHeader, 14);
 
     int bOzi3 = (abyHeader[0] == 0x80 &&
                  abyHeader[1] == 0x77);
 
+    const CPLString osImgFilename = poOpenInfo->pszFilename;
     VSILFILE* fp = VSIFOpenL(osImgFilename.c_str(), "rb");
     if (fp == NULL)
         return NULL;
@@ -418,11 +413,12 @@ GDALDataset *OZIDataset::Open( GDALOpenInfo * poOpenInfo )
     OZIDataset* poDS = new OZIDataset();
     poDS->fp = fp;
 
-    GByte nRandomNumber = 0;
     GByte nKeyInit = 0;
     if (bOzi3)
     {
         VSIFSeekL(fp, 14, SEEK_SET);
+
+        GByte nRandomNumber = 0;
         VSIFReadL(&nRandomNumber, 1, 1, fp);
         //printf("nRandomNumber = %d\n", nRandomNumber);
         if (nRandomNumber < 0x94)
@@ -450,7 +446,7 @@ GDALDataset *OZIDataset::Open( GDALOpenInfo * poOpenInfo )
         }
 
         VSIFSeekL(fp, 14 + 1 + nRandomNumber, SEEK_SET);
-        int nMagic = ReadInt(fp, bOzi3, nKeyInit);
+        const int nMagic = ReadInt(fp, bOzi3, nKeyInit);
         CPLDebug("OZI", "OZI version code : 0x%08X", nMagic);
 
         poDS->bOzi3 = bOzi3;
@@ -468,19 +464,18 @@ GDALDataset *OZIDataset::Open( GDALOpenInfo * poOpenInfo )
     /* and the nKeyInit, but I'm too lazy to add switch/cases that might */
     /* be not exhaustive, so let's try the 'brute force' attack !!! */
     /* It is much so funny to be able to run one in a few microseconds :-) */
-    int i;
-    for(i = 0; i < 256; i ++)
+    for( int i = 0; i < 256; i++ )
     {
-        nKeyInit = (GByte)i;
+        nKeyInit = static_cast<GByte>( i );
         GByte* pabyHeader2 = abyHeader2;
         if (bOzi3)
             OZIDecrypt(abyHeader2, 40, nKeyInit);
 
-        int nHeaderSize = ReadInt(&pabyHeader2); /* should be 40 */
+        const int nHeaderSize = ReadInt(&pabyHeader2); /* should be 40 */
         poDS->nRasterXSize = ReadInt(&pabyHeader2);
         poDS->nRasterYSize = ReadInt(&pabyHeader2);
-        int nDepth = ReadShort(&pabyHeader2); /* should be 1 */
-        int nBPP = ReadShort(&pabyHeader2); /* should be 8 */
+        const int nDepth = ReadShort(&pabyHeader2); /* should be 1 */
+        const int nBPP = ReadShort(&pabyHeader2); /* should be 8 */
         ReadInt(&pabyHeader2); /* reserved */
         ReadInt(&pabyHeader2); /* pixel number (height * width) : unused */
         ReadInt(&pabyHeader2); /* reserved */
@@ -499,7 +494,7 @@ GDALDataset *OZIDataset::Open( GDALOpenInfo * poOpenInfo )
                 }
                 else
                 {
-                    CPLDebug("OZI", "Cannot decypher 2nd header. Sorry...");
+                  CPLDebug( "OZI", "Cannot decipher 2nd header. Sorry..." );
                     delete poDS;
                     return NULL;
                 }
@@ -526,7 +521,11 @@ GDALDataset *OZIDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
     poDS->nZoomLevelCount = ReadShort(fp);
-    //CPLDebug("OZI", "nZoomLevelCount = %d", poDS->nZoomLevelCount);
+
+#ifdef DEBUG_VERBOSE
+    CPLDebug("OZI", "nZoomLevelCount = %d", poDS->nZoomLevelCount);
+#endif
+
     if (poDS->nZoomLevelCount < 0 || poDS->nZoomLevelCount >= 256)
     {
         CPLDebug("OZI", "nZoomLevelCount = %d", poDS->nZoomLevelCount);
@@ -543,7 +542,7 @@ GDALDataset *OZIDataset::Open( GDALOpenInfo * poOpenInfo )
         /* Some files have 8 extra bytes before the marker. I'm not sure */
         /* what they are used for. So just skeep them and hope that */
         /* we'll find the marker */
-        nSeparator = ReadInt(fp);
+        CPL_IGNORE_RET_VAL(ReadInt(fp));
         nSeparator = ReadInt(fp);
         if (nSeparator != 0x77777777)
         {
@@ -554,10 +553,10 @@ GDALDataset *OZIDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
     VSIFSeekL(fp, 0, SEEK_END);
-    vsi_l_offset nFileSize = VSIFTellL(fp);
+    const vsi_l_offset nFileSize = VSIFTellL(fp);
     poDS->nFileSize = nFileSize;
     VSIFSeekL(fp, nFileSize - 4, SEEK_SET);
-    int nZoomLevelTableOffset = ReadInt(fp, bOzi3, nKeyInit);
+    const int nZoomLevelTableOffset = ReadInt(fp, bOzi3, nKeyInit);
     if (nZoomLevelTableOffset < 0 ||
         (vsi_l_offset)nZoomLevelTableOffset >= nFileSize)
     {
@@ -570,9 +569,10 @@ GDALDataset *OZIDataset::Open( GDALOpenInfo * poOpenInfo )
     VSIFSeekL(fp, nZoomLevelTableOffset, SEEK_SET);
 
     poDS->panZoomLevelOffsets =
-        (int*)CPLMalloc(sizeof(int) * poDS->nZoomLevelCount);
+        reinterpret_cast<int *>(
+            CPLMalloc( sizeof(int) * poDS->nZoomLevelCount ) );
 
-    for(i=0;i<poDS->nZoomLevelCount;i++)
+    for( int i = 0; i < poDS->nZoomLevelCount; i++ )
     {
         poDS->panZoomLevelOffsets[i] = ReadInt(fp, bOzi3, nKeyInit);
         if (poDS->panZoomLevelOffsets[i] < 0 ||
@@ -586,19 +586,23 @@ GDALDataset *OZIDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
     poDS->papoOvrBands =
-        (OZIRasterBand**)CPLCalloc(sizeof(OZIRasterBand*), poDS->nZoomLevelCount);
+        reinterpret_cast<OZIRasterBand **>(
+            CPLCalloc( sizeof( OZIRasterBand * ), poDS->nZoomLevelCount ) );
 
-    for(i=0;i<poDS->nZoomLevelCount;i++)
+    for( int i = 0; i < poDS->nZoomLevelCount; i++ )
     {
         VSIFSeekL(fp, poDS->panZoomLevelOffsets[i], SEEK_SET);
-        int nW = ReadInt(fp, bOzi3, nKeyInit);
-        int nH = ReadInt(fp, bOzi3, nKeyInit);
-        short nTileX = ReadShort(fp, bOzi3, nKeyInit);
-        short nTileY = ReadShort(fp, bOzi3, nKeyInit);
+        const int nW = ReadInt(fp, bOzi3, nKeyInit);
+        const int nH = ReadInt(fp, bOzi3, nKeyInit);
+        const short nTileX = ReadShort(fp, bOzi3, nKeyInit);
+        const short nTileY = ReadShort(fp, bOzi3, nKeyInit);
         if (i == 0 && (nW != poDS->nRasterXSize || nH != poDS->nRasterYSize))
         {
-            CPLDebug("OZI", "zoom[%d] inconsistent dimensions for zoom level 0 : nW=%d, nH=%d, nTileX=%d, nTileY=%d, nRasterXSize=%d, nRasterYSize=%d",
-                     i, nW, nH, nTileX, nTileY, poDS->nRasterXSize, poDS->nRasterYSize);
+            CPLDebug("OZI", "zoom[%d] inconsistent dimensions for zoom level 0 "
+                     ": nW=%d, nH=%d, nTileX=%d, nTileY=%d, nRasterXSize=%d, "
+                     "nRasterYSize=%d",
+                     i, nW, nH, nTileX, nTileY, poDS->nRasterXSize,
+                     poDS->nRasterYSize);
             delete poDS;
             return NULL;
         }
@@ -611,7 +615,8 @@ GDALDataset *OZIDataset::Open( GDALOpenInfo * poOpenInfo )
         /* to work properly */
         if ((nW + 63) / 64 > nTileX || (nH + 63) / 64 > nTileY)
         {
-            CPLDebug("OZI", "zoom[%d] unexpected number of tiles : nW=%d, nH=%d, nTileX=%d, nTileY=%d",
+            CPLDebug("OZI", "zoom[%d] unexpected number of tiles : nW=%d, "
+                     "nH=%d, nTileX=%d, nTileY=%d",
                      i, nW, nH, nTileX, nTileY);
             delete poDS;
             return NULL;
@@ -622,8 +627,7 @@ GDALDataset *OZIDataset::Open( GDALOpenInfo * poOpenInfo )
         VSIFReadL(abyColorTable, 1, 1024, fp);
         if (bOzi3)
             OZIDecrypt(abyColorTable, 1024, nKeyInit);
-        int j;
-        for(j=0;j<256;j++)
+        for( int j = 0; j < 256; j++ )
         {
             GDALColorEntry sEntry;
             sEntry.c1 = abyColorTable[4*j + 2];
@@ -669,28 +673,22 @@ GDALDataset *OZIDataset::Open( GDALOpenInfo * poOpenInfo )
 void GDALRegister_OZI()
 
 {
-    GDALDriver  *poDriver;
-
-    if (! GDAL_CHECK_VERSION("OZI driver"))
+    if( !GDAL_CHECK_VERSION( "OZI driver" ) )
         return;
 
-    if( GDALGetDriverByName( "OZI" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    if( GDALGetDriverByName( "OZI" ) != NULL )
+        return;
 
-        poDriver->SetDescription( "OZI" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "OziExplorer Image File" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "frmt_ozi.html" );
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetDescription( "OZI" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "OziExplorer Image File" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_ozi.html" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = OZIDataset::Open;
-        poDriver->pfnIdentify = OZIDataset::Identify;
+    poDriver->pfnOpen = OZIDataset::Open;
+    poDriver->pfnIdentify = OZIDataset::Identify;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
-
diff --git a/frmts/pcidsk/GNUmakefile b/frmts/pcidsk/GNUmakefile
index 644f54d..86fa289 100644
--- a/frmts/pcidsk/GNUmakefile
+++ b/frmts/pcidsk/GNUmakefile
@@ -9,10 +9,8 @@ ifneq ($(JPEG_SETTING),no)
 JPEG_FLAGS = -DHAVE_LIBJPEG
 endif
 
-ifeq ($(PCIDSK_SETTING),old)
-OBJ	=	pcidskdataset.o pcidsktiledrasterband.o
-CPPFLAGS	:=	 -I../raw $(CPPFLAGS)
-$(O_OBJ):	../raw/rawdataset.h gdal_pcidsk.h
+ifeq ($(PCIDSK_SETTING),no)
+# Do nothing.
 else
 OBJ	=	pcidskdataset2.o ogrpcidsklayer.o vsi_pcidsk_io.o gdal_edb.o $(SDKOBJ)
 ifeq ($(PCIDSK_SETTING),internal)
diff --git a/frmts/pcidsk/frmt_pcidsk.html b/frmts/pcidsk/frmt_pcidsk.html
index 9f87d17..6017b92 100644
--- a/frmts/pcidsk/frmt_pcidsk.html
+++ b/frmts/pcidsk/frmt_pcidsk.html
@@ -10,9 +10,9 @@
 PCIDSK database file used by PCI EASI/PACE software for image analysis.
 It is supported for reading, and writing by GDAL.  All pixel data types, and
 data organizations (pixel interleaved, band interleaved, file interleaved
-and tiled) should be supported.  
-Currently LUT segments are ignored, but PCT segments should be treated 
-as associated with the bands.  Overall file, 
+and tiled) should be supported.
+Currently LUT segments are ignored, but PCT segments should be treated
+as associated with the bands.  Overall file,
 and band specific metadata should be correctly associated with the image
 or bands.<P>
 
@@ -27,7 +27,7 @@ Starting with GDAL 2.0, vector segments are also supported by the driver.<p>
 
 <h2>Creation Options</h2>
 
-Note that PCIDSK files are always produced pixel interleaved, even though 
+Note that PCIDSK files are always produced pixel interleaved, even though
 other organizations are supported for read.<p>
 
 <ul>
@@ -35,7 +35,7 @@ other organizations are supported for read.<p>
 <li> <b>INTERLEAVING=PIXEL/BAND/FILE/TILED</b>: sets the interleaving for
 the file raster data.  <p>
 
-<li> <b>COMPRESSION=NONE/RLE/JPEG</b>: Sets the compression to use.  Values 
+<li> <b>COMPRESSION=NONE/RLE/JPEG</b>: Sets the compression to use.  Values
 other than NONE (the default) may only be used with TILED interleaving.
 If JPEG is select it may include a quality value between 1 and 100 - eg. COMPRESSION=JPEG40.<p>
 
diff --git a/frmts/pcidsk/gdal_edb.cpp b/frmts/pcidsk/gdal_edb.cpp
index 214b0ec..012d1f0 100644
--- a/frmts/pcidsk/gdal_edb.cpp
+++ b/frmts/pcidsk/gdal_edb.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_edb.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: gdal_edb.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  PCIDSK Database File
  * Purpose:  External Database access interface implementation (EDBFile).
@@ -32,9 +32,19 @@
 #include "gdal_priv.h"
 #include "pcidsk.h"
 
-CPL_CVSID("$Id: gdal_edb.cpp 28053 2014-12-04 09:31:07Z rouault $");
+CPL_CVSID("$Id: gdal_edb.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
-using namespace PCIDSK;
+using PCIDSK::EDBFile;
+using PCIDSK::eChanType;
+using PCIDSK::ThrowPCIDSKException;
+using PCIDSK::CHN_8U;
+using PCIDSK::CHN_16S;
+using PCIDSK::CHN_16U;
+using PCIDSK::CHN_32R;
+using PCIDSK::CHN_C16S;
+using PCIDSK::CHN_UNKNOWN;
+
+EDBFile *GDAL_EDBOpen( std::string osFilename, std::string osAccess );
 
 /************************************************************************/
 /* ==================================================================== */
@@ -48,7 +58,7 @@ class GDAL_EDBFile : public EDBFile
 
 public:
 
-    GDAL_EDBFile( GDALDataset *poDSIn ) { poDS = poDSIn; }
+    explicit GDAL_EDBFile( GDALDataset *poDSIn ) { poDS = poDSIn; }
     ~GDAL_EDBFile() { if( poDS ) Close(); }
 
     int Close() const;
@@ -75,9 +85,9 @@ EDBFile *GDAL_EDBOpen( std::string osFilename, std::string osAccess )
     GDALDataset *poDS;
 
     if( osAccess == "r" )
-        poDS = (GDALDataset *) GDALOpen( osFilename.c_str(), GA_ReadOnly );
+        poDS = reinterpret_cast<GDALDataset *>( GDALOpen( osFilename.c_str(), GA_ReadOnly )) ;
     else
-        poDS = (GDALDataset *) GDALOpen( osFilename.c_str(), GA_Update );
+        poDS = reinterpret_cast<GDALDataset *>( GDALOpen( osFilename.c_str(), GA_Update ) );
 
     if( poDS == NULL )
         ThrowPCIDSKException( "%s", CPLGetLastErrorMsg() );
@@ -95,7 +105,7 @@ int GDAL_EDBFile::Close() const
     if( poDS != NULL )
     {
         delete poDS;
-        ((GDAL_EDBFile*)this)->poDS = NULL;
+        const_cast<GDAL_EDBFile*>( this )->poDS = NULL;
     }
 
     return 1;
@@ -198,11 +208,6 @@ int GDAL_EDBFile::ReadBlock( int channel,
 
 {
     GDALRasterBand *poBand = poDS->GetRasterBand(channel);
-    int nBlockXSize, nBlockYSize;
-    int nBlockX, nBlockY;
-    int nWidthInBlocks;
-    int nPixelOffset;
-    int nLineOffset;
 
     if( GetType(channel) == CHN_UNKNOWN )
     {
@@ -210,15 +215,16 @@ int GDAL_EDBFile::ReadBlock( int channel,
                              GDALGetDataTypeName(poBand->GetRasterDataType()) );
     }
 
+    int nBlockXSize, nBlockYSize;
     poBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
 
-    nWidthInBlocks = (poBand->GetXSize() + nBlockXSize - 1) / nBlockXSize;
-    
-    nBlockX = block_index % nWidthInBlocks;
-    nBlockY = block_index / nWidthInBlocks;
+    const int nWidthInBlocks = (poBand->GetXSize() + nBlockXSize - 1) / nBlockXSize;
 
-    nPixelOffset = GDALGetDataTypeSize(poBand->GetRasterDataType()) / 8;
-    nLineOffset = win_xsize * nPixelOffset;
+    const int nBlockX = block_index % nWidthInBlocks;
+    const int nBlockY = block_index / nWidthInBlocks;
+
+    const int nPixelOffset = GDALGetDataTypeSize(poBand->GetRasterDataType()) / 8;
+    const int nLineOffset = win_xsize * nPixelOffset;
 
 /* -------------------------------------------------------------------- */
 /*      Are we reading a partial block at the edge of the database?     */
@@ -230,11 +236,11 @@ int GDAL_EDBFile::ReadBlock( int channel,
     if( nBlockY * nBlockYSize + win_yoff + win_ysize > poBand->GetYSize() )
         win_ysize = poBand->GetYSize() - nBlockY * nBlockYSize - win_yoff;
 
-    CPLErr eErr = poBand->RasterIO( GF_Read, 
-                                    nBlockX * nBlockXSize + win_xoff, 
+    const CPLErr eErr = poBand->RasterIO( GF_Read,
+                                    nBlockX * nBlockXSize + win_xoff,
                                     nBlockY * nBlockYSize + win_yoff,
-                                    win_xsize, win_ysize, 
-                                    buffer, win_xsize, win_ysize, 
+                                    win_xsize, win_ysize,
+                                    buffer, win_xsize, win_ysize,
                                     poBand->GetRasterDataType(),
                                     nPixelOffset, nLineOffset, NULL );
 
@@ -254,10 +260,6 @@ int GDAL_EDBFile::WriteBlock( int channel, int block_index, void *buffer)
 
 {
     GDALRasterBand *poBand = poDS->GetRasterBand(channel);
-    int nBlockXSize, nBlockYSize;
-    int nBlockX, nBlockY;
-    int nWinXSize, nWinYSize;
-    int nWidthInBlocks;
 
     if( GetType(channel) == CHN_UNKNOWN )
     {
@@ -265,17 +267,20 @@ int GDAL_EDBFile::WriteBlock( int channel, int block_index, void *buffer)
                              GDALGetDataTypeName(poBand->GetRasterDataType()) );
     }
 
+    int nBlockXSize, nBlockYSize;
     poBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
 
-    nWidthInBlocks = (poBand->GetXSize() + nBlockXSize - 1) / nBlockXSize;
-    
-    nBlockX = block_index % nWidthInBlocks;
-    nBlockY = block_index / nWidthInBlocks;
+    const int nWidthInBlocks = (poBand->GetXSize() + nBlockXSize - 1) / nBlockXSize;
+
+    const int nBlockX = block_index % nWidthInBlocks;
+    const int nBlockY = block_index / nWidthInBlocks;
 
 /* -------------------------------------------------------------------- */
 /*      Are we reading a partial block at the edge of the database?     */
 /*      If so, ensure we don't read off the database.                   */
 /* -------------------------------------------------------------------- */
+    int nWinXSize, nWinYSize;
+
     if( nBlockX * nBlockXSize + nBlockXSize > poBand->GetXSize() )
         nWinXSize = poBand->GetXSize() - nBlockX * nBlockXSize;
     else
@@ -286,8 +291,8 @@ int GDAL_EDBFile::WriteBlock( int channel, int block_index, void *buffer)
     else
         nWinYSize = nBlockYSize;
 
-    CPLErr eErr = poBand->RasterIO( GF_Write, 
-                                    nBlockX * nBlockXSize, 
+    const CPLErr eErr = poBand->RasterIO( GF_Write,
+                                    nBlockX * nBlockXSize,
                                     nBlockY * nBlockYSize,
                                     nWinXSize, nWinYSize,
                                     buffer, nWinXSize, nWinYSize,
diff --git a/frmts/pcidsk/gdal_pcidsk.h b/frmts/pcidsk/gdal_pcidsk.h
deleted file mode 100644
index 099385c..0000000
--- a/frmts/pcidsk/gdal_pcidsk.h
+++ /dev/null
@@ -1,221 +0,0 @@
-/******************************************************************************
- * $Id: gdal_pcidsk.h 20996 2010-10-28 18:38:15Z rouault $
- *
- * Project:  PCIDSK Database File
- * Purpose:  PCIDSK driver declarations.
- * Author:   Andrey Kiselev, dron at remotesensing.org
- *
- ******************************************************************************
- * Copyright (c) 2003, Andrey Kiselev <dron at remotesensing.org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "cpl_conv.h"
-#include "cpl_string.h"
-#include "ogr_spatialref.h"
-#include "rawdataset.h"
-
-typedef enum
-{
-    PDI_PIXEL,
-    PDI_BAND,
-    PDI_FILE
-} PCIDSKInterleaving;
-
-/************************************************************************/
-/*                              PCIDSKDataset                           */
-/************************************************************************/
-
-class PCIDSKDataset : public RawDataset
-{
-    friend class PCIDSKRawRasterBand;
-    friend class PCIDSKTiledRasterBand;
-
-    const char          *pszFilename;
-    VSILFILE            *fp;
-
-    vsi_l_offset        nFileSize;
-
-    char                *pszCreatTime;  // Date/time of the database creation
-
-    vsi_l_offset        nGeoPtrOffset;  // Offset in bytes to the pointer
-                                        // to GEO segment
-    vsi_l_offset        nGeoOffset;     // Offset in bytes to the GEO segment
-    vsi_l_offset        nGcpPtrOffset;  // Offset in bytes to the pointer
-                                        // to GCP segment
-    vsi_l_offset        nGcpOffset;     // Offset in bytes to the GCP segment
-
-    int                 bGeoSegmentDirty;
-    int		        bGeoTransformValid;
-
-    int                 nBlockMapSeg;
-
-    GDAL_GCP            *pasGCPList;
-    long                 nGCPCount;
-
-    double              adfGeoTransform[6];
-    char                *pszProjection;
-    char                *pszGCPProjection;
-
-    GDALDataType  PCIDSKTypeToGDAL( const char *);
-    void          WriteGeoSegment();
-
-    void          CollectPCIDSKMetadata( int nSegment );
-
-    // Segment map
-    int           nSegCount;
-    int          *panSegType;
-    char        **papszSegName;
-    vsi_l_offset *panSegOffset;
-    vsi_l_offset *panSegSize;
-
-    int         nBandFileCount;
-    VSILFILE  **pafpBandFiles;
-
-  public:
-                PCIDSKDataset();
-                ~PCIDSKDataset();
-
-    static int           Identify( GDALOpenInfo * );
-    static GDALDataset  *Open( GDALOpenInfo * );
-    static GDALDataset  *Create( const char * pszFilename,
-                                 int nXSize, int nYSize, int nBands,
-                                 GDALDataType eType, char **papszParmList );
-    static GDALDataset *CreateCopy( const char * pszFilename, 
-                                    GDALDataset *poSrcDS, 
-                                    int bStrict, char ** papszOptions, 
-                                    GDALProgressFunc pfnProgress, 
-                                    void * pProgressData );
-
-    virtual void        FlushCache( void );
-
-    CPLErr              GetGeoTransform( double * padfTransform );
-    virtual CPLErr      SetGeoTransform( double * );
-    const char          *GetProjectionRef();
-    virtual CPLErr      SetProjection( const char * );
-    virtual int         GetGCPCount();
-    virtual const       char *GetGCPProjection();
-    virtual const       GDAL_GCP *GetGCPs();
-
-    // pcidsk specific
-    int                 SegRead( int nSegment,
-                                 vsi_l_offset nOffset,
-                                 int nSize,
-                                 void *pBuffer );
-};
-
-/************************************************************************/
-/*                         PCIDSKTiledRasterBand                        */
-/************************************************************************/
-
-class PCIDSKTiledRasterBand : public GDALPamRasterBand
-{
-    friend class PCIDSKDataset;
-
-    PCIDSKDataset *poPDS;
-    
-    int          nImage;
-
-    int           nBlocks;
-    vsi_l_offset *panBlockOffset;// offset in physical file.
-
-    int           nTileCount;
-    vsi_l_offset *panTileOffset; // offset in "image" virtual file.
-    int          *panTileSize;
-
-    int         nOverviewCount;
-    GDALRasterBand **papoOverviews;
-
-    char        szCompression[9];
-    
-    void        AttachOverview( GDALRasterBand *poOvBand ) {
-
-        nOverviewCount++;
-        papoOverviews = (GDALRasterBand **)
-            CPLRealloc(papoOverviews,sizeof(void*) * nOverviewCount);
-        papoOverviews[nOverviewCount-1] = poOvBand;
-    }
-
-    int         BuildBlockMap();
-    int         BuildTileMap();
-    
-  public:
-                PCIDSKTiledRasterBand( PCIDSKDataset *, int, int );
-                ~PCIDSKTiledRasterBand();
-
-    virtual CPLErr IReadBlock( int, int, void * );
-
-    int         SysRead( vsi_l_offset nOffset, int nSize, void * );
-
-    virtual int GetOverviewCount() { return nOverviewCount; }
-    virtual GDALRasterBand *GetOverview(int iOverview)
-        { return papoOverviews[iOverview]; }
-};
-
-/************************************************************************/
-/*                         PCIDSKRawRasterBand                          */
-/************************************************************************/
-
-class PCIDSKRawRasterBand : public RawRasterBand
-{
-    friend class PCIDSKDataset;
-
-    int         nOverviewCount;
-    GDALRasterBand **papoOverviews;
-    
-    void        AttachOverview( GDALRasterBand *poOvBand ) {
-        nOverviewCount++;
-        papoOverviews = (GDALRasterBand **)
-            CPLRealloc(papoOverviews,sizeof(void*) * nOverviewCount);
-        papoOverviews[nOverviewCount-1] = poOvBand;
-    }
-    
-  public:
-    PCIDSKRawRasterBand( GDALDataset *poDS, int nBand, VSILFILE * fpRaw,
-                         vsi_l_offset nImgOffset, int nPixelOffset,
-                         int nLineOffset,
-                         GDALDataType eDataType, int bNativeOrder )
-        : RawRasterBand( poDS, nBand, fpRaw, nImgOffset, nPixelOffset,
-                         nLineOffset, eDataType, bNativeOrder, TRUE ) {
-        nOverviewCount = 0;
-        papoOverviews = NULL;
-    }
-    ~PCIDSKRawRasterBand() {
-        FlushCache();
-        for( int i = 0; i < nOverviewCount; i++ )
-            delete papoOverviews[i];
-        CPLFree( papoOverviews );
-    }
-
-    virtual int GetOverviewCount() { 
-        if (nOverviewCount > 0)
-            return nOverviewCount; 
-
-        return RawRasterBand::GetOverviewCount();
-    }
-    virtual GDALRasterBand *GetOverview(int iOverview) { 
-        if (iOverview < nOverviewCount)
-            return papoOverviews[iOverview]; 
-
-        return RawRasterBand::GetOverview(iOverview);
-    }
-};
-
-
diff --git a/frmts/pcidsk/ogrpcidsklayer.cpp b/frmts/pcidsk/ogrpcidsklayer.cpp
index 16a090f..a7515d7 100644
--- a/frmts/pcidsk/ogrpcidsklayer.cpp
+++ b/frmts/pcidsk/ogrpcidsklayer.cpp
@@ -37,13 +37,14 @@ CPL_CVSID("$Id$");
 /************************************************************************/
 
 OGRPCIDSKLayer::OGRPCIDSKLayer( PCIDSK::PCIDSKSegment *poSegIn,
+                                PCIDSK::PCIDSKVectorSegment * poVecSegIn,
                                 bool bUpdate )
 
 {
     poSRS = NULL;
     bUpdateAccess = bUpdate;
     poSeg = poSegIn;
-    poVecSeg = dynamic_cast<PCIDSK::PCIDSKVectorSegment*>( poSeg );
+    poVecSeg = poVecSegIn;
 
     poFeatureDefn = new OGRFeatureDefn( poSeg->GetName().c_str() );
     SetDescription( poFeatureDefn->GetName() );
@@ -56,7 +57,7 @@ OGRPCIDSKLayer::OGRPCIDSKLayer( PCIDSK::PCIDSKSegment *poSegIn,
 /* -------------------------------------------------------------------- */
     try {
         std::string osLayerType = poSeg->GetMetadataValue( "LAYER_TYPE" );
-        
+
         if( osLayerType == "WHOLE_POLYGONS" )
             poFeatureDefn->SetGeomType( wkbPolygon25D );
         else if( osLayerType == "ARCS" || osLayerType == "TOPO_ARCS" )
@@ -78,37 +79,37 @@ OGRPCIDSKLayer::OGRPCIDSKLayer( PCIDSK::PCIDSKSegment *poSegIn,
         for( int iField = 0; iField < poVecSeg->GetFieldCount(); iField++ )
         {
             OGRFieldDefn oField( poVecSeg->GetFieldName(iField).c_str(), OFTString);
-            
+
             switch( poVecSeg->GetFieldType(iField) )
             {
               case PCIDSK::FieldTypeFloat:
               case PCIDSK::FieldTypeDouble:
                 oField.SetType( OFTReal );
                 break;
-                
+
               case PCIDSK::FieldTypeInteger:
                 oField.SetType( OFTInteger );
                 break;
-                
+
               case PCIDSK::FieldTypeString:
                 oField.SetType( OFTString );
                 break;
-                
+
               case PCIDSK::FieldTypeCountedInt:
                 oField.SetType( OFTIntegerList );
                 break;
-                
+
               default:
                 CPLAssert( FALSE );
                 break;
             }
-            
+
             // we ought to try and extract some width/precision information
             // from the format string at some point.
-            
+
             // If the last field is named RingStart we treat it specially.
             if( EQUAL(oField.GetNameRef(),"RingStart")
-                && oField.GetType() == OFTIntegerList 
+                && oField.GetType() == OFTIntegerList
                 && iField == poVecSeg->GetFieldCount()-1 )
                 iRingStartField = iField;
             else
@@ -124,22 +125,22 @@ OGRPCIDSKLayer::OGRPCIDSKLayer( PCIDSK::PCIDSKSegment *poSegIn,
 
         adfParameters = poVecSeg->GetProjection( osGeosys );
 
-        if( ((PCIDSK::UnitCode)(int)adfParameters[16]) 
+        if( static_cast<PCIDSK::UnitCode>( static_cast<int>( adfParameters[16] ) )
             == PCIDSK::UNIT_DEGREE )
             pszUnits = "DEGREE";
-        else if( ((PCIDSK::UnitCode)(int)adfParameters[16]) 
+        else if( static_cast<PCIDSK::UnitCode>( static_cast<int>( adfParameters[16] ))
                  == PCIDSK::UNIT_METER )
             pszUnits = "METER";
-        else if( ((PCIDSK::UnitCode)(int)adfParameters[16]) 
+        else if( static_cast<PCIDSK::UnitCode>( static_cast<int>( adfParameters[16] ) )
                  == PCIDSK::UNIT_US_FOOT )
             pszUnits = "FOOT";
-        else if( ((PCIDSK::UnitCode)(int)adfParameters[16]) 
+        else if( static_cast<PCIDSK::UnitCode>( static_cast<int>( adfParameters[16] ) )
                  == PCIDSK::UNIT_INTL_FOOT )
             pszUnits = "INTL FOOT";
 
         poSRS = new OGRSpatialReference();
 
-        if( poSRS->importFromPCI( osGeosys, pszUnits, 
+        if( poSRS->importFromPCI( osGeosys, pszUnits,
                                   &(adfParameters[0]) ) != OGRERR_NONE )
         {
             delete poSRS;
@@ -157,10 +158,10 @@ OGRPCIDSKLayer::OGRPCIDSKLayer( PCIDSK::PCIDSKSegment *poSegIn,
     }
     catch(...)
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Non-PCIDSK exception trapped while initializing layer, operation likely impaired." );
     }
-    
+
     if( poFeatureDefn->GetGeomFieldCount() > 0 )
         poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 }
@@ -172,10 +173,10 @@ OGRPCIDSKLayer::OGRPCIDSKLayer( PCIDSK::PCIDSKSegment *poSegIn,
 OGRPCIDSKLayer::~OGRPCIDSKLayer()
 
 {
-    if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
+    if( m_nFeaturesRead > 0 )
     {
         CPLDebug( "PCIDSK", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
+                  static_cast<int>( m_nFeaturesRead ),
                   poFeatureDefn->GetName() );
     }
 
@@ -208,7 +209,7 @@ OGRFeature *OGRPCIDSKLayer::GetNextFeature()
 /*      Read features till we find one that satisfies our current       */
 /*      spatial criteria.                                               */
 /* -------------------------------------------------------------------- */
-    while( TRUE )
+    while( true )
     {
         poFeature = GetNextUnfilteredFeature();
         if( poFeature == NULL )
@@ -230,21 +231,30 @@ OGRFeature *OGRPCIDSKLayer::GetNextFeature()
 /*                      GetNextUnfilteredFeature()                      */
 /************************************************************************/
 
-OGRFeature * OGRPCIDSKLayer::GetNextUnfilteredFeature()
+OGRFeature *OGRPCIDSKLayer::GetNextUnfilteredFeature()
 
 {
+    try
+    {
 /* -------------------------------------------------------------------- */
 /*      Get the next shapeid.                                           */
 /* -------------------------------------------------------------------- */
-    if( hLastShapeId == PCIDSK::NullShapeId )
-        hLastShapeId = poVecSeg->FindFirst();
-    else
-        hLastShapeId = poVecSeg->FindNext( hLastShapeId );
+        if( hLastShapeId == PCIDSK::NullShapeId )
+            hLastShapeId = poVecSeg->FindFirst();
+        else
+            hLastShapeId = poVecSeg->FindNext( hLastShapeId );
 
-    if( hLastShapeId == PCIDSK::NullShapeId )
-        return NULL;
+        if( hLastShapeId == PCIDSK::NullShapeId )
+            return NULL;
 
-    return GetFeature( hLastShapeId );
+        return GetFeature( hLastShapeId );
+    }
+    catch( const PCIDSK::PCIDSKException& ex )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "PCIDSK Exception while iterating features.\n%s", ex.what() );
+        return NULL;
+    }
 }
 
 /************************************************************************/
@@ -257,22 +267,19 @@ OGRFeature *OGRPCIDSKLayer::GetFeature( GIntBig nFID )
 /* -------------------------------------------------------------------- */
 /*      Create the OGR feature.                                         */
 /* -------------------------------------------------------------------- */
-    OGRFeature *poFeature;
-
-    poFeature = new OGRFeature( poFeatureDefn );
-    poFeature->SetFID( (int) nFID );
+    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
+    poFeature->SetFID( static_cast<int>( nFID ) );
 
 /* -------------------------------------------------------------------- */
 /*      Set attributes for any indicated attribute records.             */
 /* -------------------------------------------------------------------- */
     try {
         std::vector<PCIDSK::ShapeField> aoFields;
-        unsigned int i;
 
-        poVecSeg->GetFields( (int) nFID, aoFields );
-        for( i=0; i < aoFields.size(); i++ )
+        poVecSeg->GetFields( static_cast<int>( nFID ), aoFields );
+        for( unsigned int i=0; i < aoFields.size(); i++ )
         {
-            if( (int) i == iRingStartField )
+            if( static_cast<int>( i ) == iRingStartField )
                 continue;
 
             switch( aoFields[i].GetType() )
@@ -284,23 +291,23 @@ OGRFeature *OGRPCIDSKLayer::GetFeature( GIntBig nFID )
               case PCIDSK::FieldTypeInteger:
                 poFeature->SetField( i, aoFields[i].GetValueInteger() );
                 break;
-                                 
+
               case PCIDSK::FieldTypeFloat:
                 poFeature->SetField( i, aoFields[i].GetValueFloat() );
                 break;
-                                 
+
               case PCIDSK::FieldTypeDouble:
                 poFeature->SetField( i, aoFields[i].GetValueDouble() );
                 break;
-                                 
+
               case PCIDSK::FieldTypeString:
                 poFeature->SetField( i, aoFields[i].GetValueString().c_str() );
                 break;
-                                 
+
               case PCIDSK::FieldTypeCountedInt:
                 std::vector<PCIDSK::int32> list = aoFields[i].GetValueCountedInt();
-            
-                poFeature->SetField( i, list.size(), &(list[0]) );
+
+                poFeature->SetField( i, static_cast<int>(list.size()), &(list[0]) );
                 break;
             }
         }
@@ -310,20 +317,20 @@ OGRFeature *OGRPCIDSKLayer::GetFeature( GIntBig nFID )
 /* -------------------------------------------------------------------- */
         std::vector<PCIDSK::ShapeVertex> aoVertices;
 
-        poVecSeg->GetVertices( (int) nFID, aoVertices );
+        poVecSeg->GetVertices( static_cast<int>( nFID ), aoVertices );
 
 /* -------------------------------------------------------------------- */
 /*      Point                                                           */
 /* -------------------------------------------------------------------- */
-        if( poFeatureDefn->GetGeomType() == wkbPoint25D 
-            || (wkbFlatten(poFeatureDefn->GetGeomType()) == wkbUnknown 
+        if( poFeatureDefn->GetGeomType() == wkbPoint25D
+            || (wkbFlatten(poFeatureDefn->GetGeomType()) == wkbUnknown
                 && aoVertices.size() == 1) )
         {
             if( aoVertices.size() == 1 )
             {
                 OGRPoint* poPoint =
                     new OGRPoint( aoVertices[0].x,
-                                  aoVertices[0].y, 
+                                  aoVertices[0].y,
                                   aoVertices[0].z );
                 if (poSRS)
                     poPoint->assignSpatialReference(poSRS);
@@ -333,27 +340,27 @@ OGRFeature *OGRPCIDSKLayer::GetFeature( GIntBig nFID )
             {
                 // report issue?
             }
-        }    
+        }
 
 /* -------------------------------------------------------------------- */
 /*      LineString                                                      */
 /* -------------------------------------------------------------------- */
-        else if( poFeatureDefn->GetGeomType() == wkbLineString25D 
-                 || (wkbFlatten(poFeatureDefn->GetGeomType()) == wkbUnknown 
+        else if( poFeatureDefn->GetGeomType() == wkbLineString25D
+                 || (wkbFlatten(poFeatureDefn->GetGeomType()) == wkbUnknown
                      && aoVertices.size() > 1) )
         {
-            // We should likely be applying ringstart to break things into 
+            // We should likely be applying ringstart to break things into
             // a multilinestring in some cases.
             if( aoVertices.size() > 1 )
             {
                 OGRLineString *poLS = new OGRLineString();
 
-                poLS->setNumPoints( aoVertices.size() );
-            
-                for( i = 0; i < aoVertices.size(); i++ )
+                poLS->setNumPoints( static_cast<int>(aoVertices.size()) );
+
+                for( unsigned int i = 0; i < aoVertices.size(); i++ )
                     poLS->setPoint( i,
-                                    aoVertices[i].x, 
-                                    aoVertices[i].y, 
+                                    aoVertices[i].x,
+                                    aoVertices[i].y,
                                     aoVertices[i].z );
                 if (poSRS)
                     poLS->assignSpatialReference(poSRS);
@@ -364,7 +371,7 @@ OGRFeature *OGRPCIDSKLayer::GetFeature( GIntBig nFID )
             {
                 // report issue?
             }
-        }    
+        }
 
 /* -------------------------------------------------------------------- */
 /*      Polygon - Currently we have no way to recognise if we are       */
@@ -377,32 +384,32 @@ OGRFeature *OGRPCIDSKLayer::GetFeature( GIntBig nFID )
         {
             std::vector<PCIDSK::int32> anRingStart;
             OGRPolygon *poPoly = new OGRPolygon();
-            unsigned int iRing;
 
             if( iRingStartField != -1 )
                 anRingStart = aoFields[iRingStartField].GetValueCountedInt();
 
-            for( iRing = 0; iRing < anRingStart.size()+1; iRing++ )
+            for( unsigned int iRing = 0; iRing < anRingStart.size()+1; iRing++ )
             {
-                int iStartVertex, iEndVertex, iVertex;
-                OGRLinearRing *poRing = new OGRLinearRing();
-
+                int iStartVertex;
                 if( iRing == 0 )
                     iStartVertex = 0;
                 else
                     iStartVertex = anRingStart[iRing-1];
 
+                int iEndVertex;
                 if( iRing == anRingStart.size() )
-                    iEndVertex = aoVertices.size() - 1;
+                    iEndVertex = static_cast<int>(aoVertices.size()) - 1;
                 else
                     iEndVertex = anRingStart[iRing] - 1;
 
+                int iVertex;
+                OGRLinearRing *poRing = new OGRLinearRing();
                 poRing->setNumPoints( iEndVertex - iStartVertex + 1 );
                 for( iVertex = iStartVertex; iVertex <= iEndVertex; iVertex++ )
                 {
                     poRing->setPoint( iVertex - iStartVertex,
-                                      aoVertices[iVertex].x, 
-                                      aoVertices[iVertex].y, 
+                                      aoVertices[iVertex].x,
+                                      aoVertices[iVertex].y,
                                       aoVertices[iVertex].z );
                 }
 
@@ -413,23 +420,23 @@ OGRFeature *OGRPCIDSKLayer::GetFeature( GIntBig nFID )
                 poPoly->assignSpatialReference(poSRS);
 
             poFeature->SetGeometryDirectly( poPoly );
-        }    
+        }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Trap exceptions and report as CPL errors.                       */
 /* -------------------------------------------------------------------- */
     catch( PCIDSK::PCIDSKException ex )
     {
         delete poFeature;
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", ex.what() );
         return NULL;
     }
     catch(...)
     {
         delete poFeature;
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Non-PCIDSK exception trapped." );
         return NULL;
     }
@@ -452,7 +459,7 @@ int OGRPCIDSKLayer::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCFastFeatureCount) )
         return m_poFilterGeom == NULL && m_poAttrQuery == NULL;
 
-    else if( EQUAL(pszCap,OLCSequentialWrite) 
+    else if( EQUAL(pszCap,OLCSequentialWrite)
              || EQUAL(pszCap,OLCRandomWrite) )
         return bUpdateAccess;
 
@@ -462,8 +469,7 @@ int OGRPCIDSKLayer::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCCreateField) )
         return bUpdateAccess;
 
-    else 
-        return FALSE;
+    return FALSE;
 }
 
 /************************************************************************/
@@ -475,13 +481,11 @@ GIntBig OGRPCIDSKLayer::GetFeatureCount( int bForce )
 {
     if( m_poFilterGeom != NULL || m_poAttrQuery != NULL )
         return OGRLayer::GetFeatureCount( bForce );
-    else
-    {
-        try {
-            return poVecSeg->GetShapeCount();
-        } catch(...) {
-            return 0;
-        }
+
+    try {
+        return poVecSeg->GetShapeCount();
+    } catch(...) {
+        return 0;
     }
 }
 
@@ -494,28 +498,26 @@ OGRErr OGRPCIDSKLayer::GetExtent (OGREnvelope *psExtent, int bForce)
 {
     if( !bForce )
         return OGRERR_FAILURE;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Loop over all features, but just read the geometry.  This is    */
 /*      a fair amount quicker than actually processing all the          */
-/*      attributes, forming features and then exaimining the            */
-/*      geometries as the default implemntation would do.               */
+/*      attributes, forming features and then examining the             */
+/*      geometries as the default implementation would do.              */
 /* -------------------------------------------------------------------- */
     try
     {
-        bool bHaveExtent = FALSE;
+        bool bHaveExtent = false;
 
         std::vector<PCIDSK::ShapeVertex> asVertices;
 
-        for( PCIDSK::ShapeIterator oIt = poVecSeg->begin(); 
+        for( PCIDSK::ShapeIterator oIt = poVecSeg->begin();
              oIt != poVecSeg->end();
              oIt++ )
         {
-            unsigned int i;
-
             poVecSeg->GetVertices( *oIt, asVertices );
 
-            for( i = 0; i < asVertices.size(); i++ )
+            for( unsigned int i = 0; i < asVertices.size(); i++ )
             {
                 if( !bHaveExtent )
                 {
@@ -535,8 +537,8 @@ OGRErr OGRPCIDSKLayer::GetExtent (OGREnvelope *psExtent, int bForce)
 
         if( bHaveExtent )
             return OGRERR_NONE;
-        else
-            return OGRERR_FAILURE;
+
+        return OGRERR_FAILURE;
     }
 
 /* -------------------------------------------------------------------- */
@@ -550,7 +552,7 @@ OGRErr OGRPCIDSKLayer::GetExtent (OGREnvelope *psExtent, int bForce)
     }
     catch(...)
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Non-PCIDSK exception trapped while initializing layer, operation likely impaired." );
         return OGRERR_FAILURE;
     }
@@ -564,7 +566,6 @@ OGRErr OGRPCIDSKLayer::DeleteFeature( GIntBig nFID )
 
 {
     try {
-
         poVecSeg->DeleteShape( (PCIDSK::ShapeId) nFID );
 
         return OGRERR_NONE;
@@ -575,13 +576,13 @@ OGRErr OGRPCIDSKLayer::DeleteFeature( GIntBig nFID )
 /* -------------------------------------------------------------------- */
     catch( PCIDSK::PCIDSKException ex )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", ex.what() );
         return OGRERR_FAILURE;
     }
     catch(...)
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Non-PCIDSK exception trapped." );
         return OGRERR_FAILURE;
     }
@@ -595,8 +596,7 @@ OGRErr OGRPCIDSKLayer::ICreateFeature( OGRFeature *poFeature )
 
 {
     try {
-
-        PCIDSK::ShapeId id = poVecSeg->CreateShape( 
+        PCIDSK::ShapeId id = poVecSeg->CreateShape(
             (PCIDSK::ShapeId) poFeature->GetFID() );
 
         poFeature->SetFID( (long) id );
@@ -608,17 +608,16 @@ OGRErr OGRPCIDSKLayer::ICreateFeature( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
     catch( PCIDSK::PCIDSKException ex )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", ex.what() );
         return OGRERR_FAILURE;
     }
     catch(...)
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Non-PCIDSK exception trapped." );
         return OGRERR_FAILURE;
     }
-    
 }
 
 /************************************************************************/
@@ -629,22 +628,18 @@ OGRErr OGRPCIDSKLayer::ISetFeature( OGRFeature *poFeature )
 
 {
     PCIDSK::ShapeId id = (PCIDSK::ShapeId) poFeature->GetFID();
-    
+
 /* -------------------------------------------------------------------- */
 /*      Translate attribute fields.                                     */
 /* -------------------------------------------------------------------- */
     try {
-
-        int iPCI;
         std::vector<PCIDSK::ShapeField>  aoPCIFields;
 
         aoPCIFields.resize(poVecSeg->GetFieldCount());
 
-        for( iPCI = 0; iPCI < poVecSeg->GetFieldCount(); iPCI++ )
+        for( int iPCI = 0; iPCI < poVecSeg->GetFieldCount(); iPCI++ )
         {
-            int iOGR;
-
-            iOGR = poFeatureDefn->GetFieldIndex(
+            int iOGR = poFeatureDefn->GetFieldIndex(
                 poVecSeg->GetFieldName(iPCI).c_str() );
 
             if( iOGR == -1 )
@@ -659,12 +654,12 @@ OGRErr OGRPCIDSKLayer::ISetFeature( OGRFeature *poFeature )
 
               case PCIDSK::FieldTypeFloat:
                 aoPCIFields[iPCI].SetValue(
-                    (float) poFeature->GetFieldAsDouble( iOGR ) );
+                    static_cast<float>( poFeature->GetFieldAsDouble( iOGR ) ) );
                 break;
 
               case PCIDSK::FieldTypeDouble:
                 aoPCIFields[iPCI].SetValue(
-                    (double) poFeature->GetFieldAsDouble( iOGR ) );
+                    static_cast<double>( poFeature->GetFieldAsDouble( iOGR ) ) );
                 break;
 
               case PCIDSK::FieldTypeString:
@@ -675,10 +670,10 @@ OGRErr OGRPCIDSKLayer::ISetFeature( OGRFeature *poFeature )
               case PCIDSK::FieldTypeCountedInt:
               {
                   int nCount;
-                  const int *panList = 
+                  const int *panList =
                       poFeature->GetFieldAsIntegerList( iOGR, &nCount );
                   std::vector<PCIDSK::int32> anList;
-                  
+
                   anList.resize( nCount );
                   memcpy( &(anList[0]), panList, 4 * anList.size() );
                   aoPCIFields[iPCI].SetValue( anList );
@@ -702,11 +697,12 @@ OGRErr OGRPCIDSKLayer::ISetFeature( OGRFeature *poFeature )
 
         if( poGeometry == NULL )
         {
+            // TODO: What?  Is this really a NOP?
         }
 
         else if( wkbFlatten(poGeometry->getGeometryType()) == wkbPoint )
         {
-            OGRPoint *poPoint = (OGRPoint *) poGeometry;
+            OGRPoint *poPoint = reinterpret_cast<OGRPoint *>( poGeometry );
 
             aoVertices.resize(1);
             aoVertices[0].x = poPoint->getX();
@@ -716,7 +712,7 @@ OGRErr OGRPCIDSKLayer::ISetFeature( OGRFeature *poFeature )
 
         else if( wkbFlatten(poGeometry->getGeometryType()) == wkbLineString )
         {
-            OGRLineString *poLS = (OGRLineString *) poGeometry;
+            OGRLineString *poLS = reinterpret_cast<OGRLineString *>( poGeometry );
             unsigned int i;
 
             aoVertices.resize(poLS->getNumPoints());
@@ -744,13 +740,13 @@ OGRErr OGRPCIDSKLayer::ISetFeature( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
     catch( PCIDSK::PCIDSKException ex )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", ex.what() );
         return OGRERR_FAILURE;
     }
     catch(...)
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Non-PCIDSK exception trapped." );
         return OGRERR_FAILURE;
     }
@@ -767,32 +763,31 @@ OGRErr OGRPCIDSKLayer::CreateField( OGRFieldDefn *poFieldDefn,
 
 {
     try {
-        
         if( poFieldDefn->GetType() == OFTInteger )
         {
-            poVecSeg->AddField( poFieldDefn->GetNameRef(), 
-                                PCIDSK::FieldTypeInteger, 
+            poVecSeg->AddField( poFieldDefn->GetNameRef(),
+                                PCIDSK::FieldTypeInteger,
                                 "", "" );
             poFeatureDefn->AddFieldDefn( poFieldDefn );
         }
         else if( poFieldDefn->GetType() == OFTReal )
         {
-            poVecSeg->AddField( poFieldDefn->GetNameRef(), 
-                                PCIDSK::FieldTypeDouble, 
+            poVecSeg->AddField( poFieldDefn->GetNameRef(),
+                                PCIDSK::FieldTypeDouble,
                                 "", "" );
             poFeatureDefn->AddFieldDefn( poFieldDefn );
         }
         else if( poFieldDefn->GetType() == OFTString )
         {
-            poVecSeg->AddField( poFieldDefn->GetNameRef(), 
-                                PCIDSK::FieldTypeString, 
+            poVecSeg->AddField( poFieldDefn->GetNameRef(),
+                                PCIDSK::FieldTypeString,
                                 "", "" );
             poFeatureDefn->AddFieldDefn( poFieldDefn );
         }
         else if( poFieldDefn->GetType() == OFTIntegerList )
         {
-            poVecSeg->AddField( poFieldDefn->GetNameRef(), 
-                                PCIDSK::FieldTypeCountedInt, 
+            poVecSeg->AddField( poFieldDefn->GetNameRef(),
+                                PCIDSK::FieldTypeCountedInt,
                                 "", "" );
             poFeatureDefn->AddFieldDefn( poFieldDefn );
         }
@@ -801,8 +796,8 @@ OGRErr OGRPCIDSKLayer::CreateField( OGRFieldDefn *poFieldDefn,
             // Fallback to treating everything else as a string field.
             OGRFieldDefn oModFieldDefn(poFieldDefn);
             oModFieldDefn.SetType( OFTString );
-            poVecSeg->AddField( poFieldDefn->GetNameRef(), 
-                                PCIDSK::FieldTypeString, 
+            poVecSeg->AddField( poFieldDefn->GetNameRef(),
+                                PCIDSK::FieldTypeString,
                                 "", "" );
             poFeatureDefn->AddFieldDefn( &oModFieldDefn );
         }
@@ -819,13 +814,13 @@ OGRErr OGRPCIDSKLayer::CreateField( OGRFieldDefn *poFieldDefn,
 /* -------------------------------------------------------------------- */
     catch( PCIDSK::PCIDSKException ex )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", ex.what() );
         return OGRERR_FAILURE;
     }
     catch(...)
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Non-PCIDSK exception trapped." );
         return OGRERR_FAILURE;
     }
diff --git a/frmts/pcidsk/pcidskdataset.cpp b/frmts/pcidsk/pcidskdataset.cpp
deleted file mode 100644
index 85d24df..0000000
--- a/frmts/pcidsk/pcidskdataset.cpp
+++ /dev/null
@@ -1,1644 +0,0 @@
-/******************************************************************************
- * $Id: pcidskdataset.cpp 28373 2015-01-30 00:14:24Z rouault $
- *
- * Project:  PCIDSK Database File
- * Purpose:  Read/write PCIDSK Database File used by the PCI software
- * Author:   Andrey Kiselev, dron at ak4719.spb.edu
- *
- ******************************************************************************
- * Copyright (c) 2003, Andrey Kiselev <dron at ak4719.spb.edu>
- * Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "gdal_pcidsk.h"
-
-CPL_CVSID("$Id: pcidskdataset.cpp 28373 2015-01-30 00:14:24Z rouault $");
-
-CPL_C_START
-void    GDALRegister_PCIDSK(void);
-CPL_C_END
-
-const int       nSegBlocks = 64;    // Number of blocks of Segment Pointers
-const int       nGeoSegBlocks = 8;  // Number of blocks in GEO Segment
-
-/************************************************************************/
-/*                           PCIDSKDataset()                            */
-/************************************************************************/
-
-PCIDSKDataset::PCIDSKDataset()
-{
-    pszFilename = NULL;
-    fp = NULL;
-    nFileSize = 0;
-    nBands = 0;
-    pszCreatTime = NULL;
-    nGeoOffset = 0;
-    bGeoSegmentDirty = FALSE;
-
-    nBlockMapSeg = 0;
-
-    nSegCount = 0;
-    panSegType = NULL;
-    papszSegName = NULL;
-    panSegOffset = NULL;
-    panSegSize = NULL;
-
-    pszProjection = CPLStrdup( "" );
-    pszGCPProjection = CPLStrdup( "" );
-    nGCPCount = 0;
-    pasGCPList = NULL;
-    adfGeoTransform[0] = 0.0;
-    adfGeoTransform[1] = 1.0;
-    adfGeoTransform[2] = 0.0;
-    adfGeoTransform[3] = 0.0;
-    adfGeoTransform[4] = 0.0;
-    adfGeoTransform[5] = 1.0;
-    bGeoTransformValid = FALSE;
-
-    nBandFileCount = 0;
-    pafpBandFiles = NULL;
-}
-
-/************************************************************************/
-/*                            ~PCIDSKDataset()                          */
-/************************************************************************/
-
-PCIDSKDataset::~PCIDSKDataset()
-{
-    int  i;
-
-    FlushCache();
-
-    if ( pszProjection )
-        CPLFree( pszProjection );
-    if ( pszGCPProjection )
-        CPLFree( pszGCPProjection );
-    if( fp != NULL )
-        VSIFCloseL( fp );
-    if( pszCreatTime )
-        CPLFree( pszCreatTime );
-    if( nGCPCount > 0 )
-    {
-        GDALDeinitGCPs( nGCPCount, pasGCPList );
-        CPLFree( pasGCPList );
-    }
-
-    CPLFree( panSegOffset );
-    CPLFree( panSegSize );
-    CPLFree( panSegType );
-
-    for( i = 0; i < nSegCount; i++ )
-        if( papszSegName[i] != NULL )
-            CPLFree( papszSegName[i] );
-    CPLFree( papszSegName );
-
-    for( i = 0; i < nBandFileCount; i++ )
-        VSIFCloseL( pafpBandFiles[i] );
-    CPLFree( pafpBandFiles );
-}
-
-/************************************************************************/
-/*                          GetGeoTransform()                           */
-/************************************************************************/
-
-CPLErr PCIDSKDataset::GetGeoTransform( double * padfTransform )
-{
-    if( !bGeoTransformValid )
-        return GDALPamDataset::GetGeoTransform( padfTransform );
-    else
-    {
-        memcpy( padfTransform, adfGeoTransform, sizeof(adfGeoTransform[0])*6 );
-        return CE_None;
-    }
-}
-
-/************************************************************************/
-/*                          SetGeoTransform()                           */
-/************************************************************************/
-
-CPLErr PCIDSKDataset::SetGeoTransform( double * padfTransform )
-{
-    memcpy( adfGeoTransform, padfTransform, sizeof(double) * 6 );
-    bGeoSegmentDirty = TRUE;
-    bGeoTransformValid = TRUE;
-
-    return CE_None;
-}
-
-/************************************************************************/
-/*                          GetProjectionRef()                          */
-/************************************************************************/
-
-const char *PCIDSKDataset::GetProjectionRef()
-{
-    if( pszProjection )
-        return pszProjection;
-    else
-        return GDALPamDataset::GetProjectionRef();
-}
-
-/************************************************************************/
-/*                          SetProjection()                             */
-/************************************************************************/
-
-CPLErr PCIDSKDataset::SetProjection( const char *pszNewProjection )
-
-{
-    if( pszProjection )
-	CPLFree( pszProjection );
-    pszProjection = CPLStrdup( pszNewProjection );
-    bGeoSegmentDirty = TRUE;
-
-    return CE_None;
-}
-
-/************************************************************************/
-/*                            GetGCPCount()                             */
-/************************************************************************/
-
-int PCIDSKDataset::GetGCPCount()
-
-{
-    return nGCPCount;
-}
-
-/************************************************************************/
-/*                          GetGCPProjection()                          */
-/************************************************************************/
-
-const char *PCIDSKDataset::GetGCPProjection()
-
-{
-    if( nGCPCount > 0 )
-        return pszGCPProjection;
-    else
-        return GDALPamDataset::GetGCPProjection();
-}
-
-/************************************************************************/
-/*                               GetGCPs()                              */
-/************************************************************************/
-
-const GDAL_GCP *PCIDSKDataset::GetGCPs()
-{
-    return pasGCPList;
-}
-
-/************************************************************************/
-/*                             FlushCache()                             */
-/************************************************************************/
-
-void PCIDSKDataset::FlushCache()
-{
-    GDALPamDataset::FlushCache();
-
-    if( GetAccess() == GA_Update )
-    {
-        char        szTemp[64];
-
-/* -------------------------------------------------------------------- */
-/*      Write out pixel size.                                           */
-/* -------------------------------------------------------------------- */
-        CPLPrintDouble( szTemp, "%16.9E", ABS(adfGeoTransform[1]), "C" );
-        CPLPrintDouble( szTemp + 16, "%16.9E", ABS(adfGeoTransform[5]), "C" );
-
-        VSIFSeekL( fp, 408, SEEK_SET );
-        VSIFWriteL( (void *)szTemp, 1, 32, fp );
-
-/* -------------------------------------------------------------------- */
-/*      Write out Georeferencing segment.                               */
-/* -------------------------------------------------------------------- */
-        if ( nGeoOffset && bGeoSegmentDirty )
-        {
-            WriteGeoSegment();
-            bGeoSegmentDirty = FALSE;
-        }
-    }
-}
-
-/************************************************************************/
-/*                         WriteGeoSegment()                            */
-/************************************************************************/
-
-void PCIDSKDataset::WriteGeoSegment( )
-{
-    char            szTemp[3072];
-    struct tm       oUpdateTime;
-    time_t          nTime = VSITime(NULL);
-    char            *pszP = pszProjection;
-    OGRSpatialReference oSRS;
-    int             i;
-
-#ifdef DEBUG
-    CPLDebug( "PCIDSK", "Writing out georeferencing segment." );
-#endif
-    
-    VSILocalTime( &nTime, &oUpdateTime );
-
-    CPLPrintStringFill( szTemp, "Master Georeferencing Segment for File", 64 );
-    CPLPrintStringFill( szTemp + 64, "", 64 );
-    if ( pszCreatTime )
-        CPLPrintStringFill( szTemp + 128, pszCreatTime, 16 );
-    else
-        CPLPrintTime( szTemp + 128, 16, "%H:%M %d-%b-%y ", &oUpdateTime, "C" );
-    CPLPrintTime( szTemp + 144, 16, "%H:%M %d-%b-%y ", &oUpdateTime, "C" );
-    CPLPrintStringFill( szTemp + 160, "", 224 );
-    // Write the history line
-    CPLPrintStringFill( szTemp + 384,
-                        "GDAL: Master Georeferencing Segment for File", 64 );
-    CPLPrintTime( szTemp + 448, 16, "%H:%M %d-%b-%y ", &oUpdateTime, "C" );
-    // Fill other lines with spaces
-    CPLPrintStringFill( szTemp + 464, "", 80 * 7 );
-
-    // More history lines may be used, if needed.
-    // CPLPrintStringFill( szTemp + 464, "History2", 80 );
-    // CPLPrintStringFill( szTemp + 544, "History3", 80 );
-    // CPLPrintStringFill( szTemp + 624, "History4", 80 );
-    // CPLPrintStringFill( szTemp + 704, "History5", 80 );
-    // CPLPrintStringFill( szTemp + 784, "History6", 80 );
-    // CPLPrintStringFill( szTemp + 864, "History7", 80 );
-    // CPLPrintStringFill( szTemp + 944, "History8", 80 );
-
-    VSIFSeekL( fp, nGeoOffset, SEEK_SET );
-    VSIFWriteL( (void *)szTemp, 1, 1024, fp );
-
-    CPLPrintStringFill( szTemp, "PROJECTION", 16 );
-    CPLPrintStringFill( szTemp + 16, "PIXEL", 16 );
-
-    if( pszProjection != NULL && !EQUAL( pszProjection, "" )
-        && oSRS.importFromWkt( &pszP ) == OGRERR_NONE )
-    {
-        char      *pszProj = NULL;
-        char      *pszUnits = NULL;
-        double    *padfPrjParms = NULL;
-
-        oSRS.exportToPCI( &pszProj, &pszUnits, &padfPrjParms );
-        CPLPrintStringFill( szTemp + 32, pszProj, 16 );
-
-        CPLPrintInt32( szTemp + 48, 3, 8 );
-        CPLPrintInt32( szTemp + 56, 3, 8 );
-
-        CPLPrintStringFill( szTemp + 64, pszUnits, 16 );
-
-        for ( i = 0; i < 17; i++ )
-        {
-            CPLPrintDouble( szTemp + 80 + 26 * i,
-                            "%26.18E", padfPrjParms[i], "C" );
-        }
-
-        CPLPrintStringFill( szTemp + 522, "", 936 );
-
-        if ( pszProj )
-            CPLFree( pszProj );
-        if ( pszUnits )
-            CPLFree(pszUnits );
-        if ( padfPrjParms )
-            CPLFree( padfPrjParms );
-    }
-    else
-    {
-        if( adfGeoTransform[0] == 0.0
-            && adfGeoTransform[1] == 1.0
-            && adfGeoTransform[2] == 0.0
-            && adfGeoTransform[3] == 0.0
-            && adfGeoTransform[4] == 0.0
-            && ABS(adfGeoTransform[5]) == 1.0 ) 
-        {
-            // no georeferencing at all.
-            CPLPrintStringFill( szTemp + 32, "PIXEL", 16 );
-        }
-        else
-        {
-            // georeferenced but not a known coordinate system.
-            CPLPrintStringFill( szTemp + 32, "METER", 16 );
-        }
-        CPLPrintInt32( szTemp + 48, 3, 8 );
-        CPLPrintInt32( szTemp + 56, 3, 8 );
-        CPLPrintStringFill( szTemp + 64, "METER", 16 );
-        CPLPrintStringFill( szTemp + 80, "", 1378 );
-    }
-
-    /* TODO: USGS format */
-    CPLPrintStringFill( szTemp + 1458, "", 1614 );
-
-    for ( i = 0; i < 3; i++ )
-    {
-        CPLPrintDouble( szTemp + 1980 + 26 * i,
-                        "%26.18E", adfGeoTransform[i], "C" );
-    }
-    for ( i = 0; i < 3; i++ )
-    {
-        CPLPrintDouble( szTemp + 2526 + 26 * i,
-                        "%26.18E", adfGeoTransform[i + 3], "C" );
-    }
-
-    VSIFWriteL( (void *)szTemp, 1, 3072, fp );
-
-    // Now make the segment active
-    szTemp[0] = 'A';
-    VSIFSeekL( fp, nGeoPtrOffset, SEEK_SET );
-    VSIFWriteL( (void *)szTemp, 1, 1, fp );
-}
-
-/************************************************************************/
-/*                         PCIDSKTypeToGDAL()                           */
-/************************************************************************/
-
-GDALDataType PCIDSKDataset::PCIDSKTypeToGDAL( const char *pszType )
-{
-    if ( EQUALN( pszType, "8U", 2 ) )
-        return GDT_Byte;
-    if ( EQUALN( pszType, "16S", 3 ) )
-        return GDT_Int16;
-    if ( EQUALN( pszType, "16U", 3 ) )
-        return GDT_UInt16;
-    if ( EQUALN( pszType, "32R", 3 ) )
-        return GDT_Float32;
-
-    return GDT_Unknown;
-}
-
-/************************************************************************/
-/*                              Identify()                              */
-/************************************************************************/
-
-int PCIDSKDataset::Identify( GDALOpenInfo * poOpenInfo )
-{
-    if( poOpenInfo->nHeaderBytes < 512 
-        || !EQUALN((const char *) poOpenInfo->pabyHeader, "PCIDSK  ", 8) )
-        return FALSE;
-    else
-        return TRUE;
-}
-
-/************************************************************************/
-/*                                Open()                                */
-/************************************************************************/
-
-GDALDataset *PCIDSKDataset::Open( GDALOpenInfo * poOpenInfo )
-{
-    if( !Identify( poOpenInfo ) )
-        return NULL;
-
-/* -------------------------------------------------------------------- */
-/*      Create a corresponding GDALDataset.                             */
-/* -------------------------------------------------------------------- */
-    PCIDSKDataset   *poDS;
-
-    poDS = new PCIDSKDataset();
-
-    if( poOpenInfo->eAccess == GA_ReadOnly )
-        poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
-    else
-        poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "r+b" );
-    if ( !poDS->fp )
-    {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Failed to re-open %s within PCIDSK driver.\n",
-                  poOpenInfo->pszFilename );
-        delete poDS;
-        return NULL;
-    }
-    poDS->eAccess = poOpenInfo->eAccess;
-
-/* ==================================================================== */
-/*   Read PCIDSK File Header.                                           */
-/* ==================================================================== */
-    char            szTemp[1024];
-    char            *pszString;
-
-    VSIFSeekL( poDS->fp, 0, SEEK_END );
-    poDS->nFileSize = VSIFTellL( poDS->fp );
-
-/* -------------------------------------------------------------------- */
-/*      Read File Identification.                                       */
-/* -------------------------------------------------------------------- */
-    VSIFSeekL( poDS->fp, 0, SEEK_SET );
-    VSIFReadL( szTemp, 1, 512, poDS->fp );
-
-    pszString = CPLScanString( szTemp + 8, 8, TRUE, TRUE );
-    poDS->SetMetadataItem( "SOFTWARE", pszString );
-    CPLFree( pszString );
-
-    pszString = CPLScanString( szTemp + 48, 64, TRUE, TRUE );
-    poDS->SetMetadataItem( "FILE_ID", pszString );
-    CPLFree( pszString );
-
-    pszString = CPLScanString( szTemp + 112, 32, TRUE, TRUE );
-    poDS->SetMetadataItem( "GENERATING_FACILITY", pszString );
-    CPLFree( pszString );
-
-    pszString = CPLScanString( szTemp + 144, 64, TRUE, TRUE );
-    poDS->SetMetadataItem( "DESCRIPTION1", pszString );
-    CPLFree( pszString );
-
-    pszString = CPLScanString( szTemp + 208, 64, TRUE, TRUE );
-    poDS->SetMetadataItem( "DESCRIPTION2", pszString );
-    CPLFree( pszString );
-
-    pszString = CPLScanString( szTemp + 272, 16, TRUE, TRUE );
-    poDS->SetMetadataItem( "DATE_OF_CREATION", pszString );
-    CPLFree( pszString );
-    // Store original creation time string for later use
-    poDS->pszCreatTime = CPLScanString( szTemp + 272, 16, TRUE, FALSE );
-
-    pszString = CPLScanString( szTemp + 288, 16, TRUE, TRUE );
-    poDS->SetMetadataItem( "DATE_OF_UPDATE", pszString );
-    CPLFree( pszString );
-
-/* ==================================================================== */
-/*   Read Segment Pointers.                                             */
-/* ==================================================================== */
-    vsi_l_offset    nSegPointersStart;  // Start block of Segment Pointers
-    vsi_l_offset    nSegPointersOffset; // Offset in bytes to Pointers
-    int             nSegBlocks;         // Number of blocks of Segment Pointers
-
-    {
-        VSIFSeekL( poDS->fp, 440, SEEK_SET );
-        VSIFReadL( szTemp, 1, 16, poDS->fp );
-        szTemp[16] = '\0';
-        nSegPointersStart = atol( szTemp ); // XXX: should be atoll()
-        nSegPointersOffset = ( nSegPointersStart - 1 ) * 512;
-        
-        VSIFSeekL( poDS->fp, 456, SEEK_SET );
-        VSIFReadL( szTemp, 1, 8, poDS->fp );
-        nSegBlocks = CPLScanLong( szTemp, 8 );
-        poDS->nSegCount = ( nSegBlocks * 512 ) / 32;
-
-        if ( poDS->nSegCount < 0 ||
-             nSegPointersOffset + poDS->nSegCount * 32 >= poDS->nFileSize )
-        {
-            CPLDebug("PCIDSK", "nSegCount=%d", poDS->nSegCount);
-            delete poDS;
-            return NULL;
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Allocate segment info structures.                               */
-/* -------------------------------------------------------------------- */
-        poDS->panSegType =
-            (int *) VSICalloc( sizeof(int), poDS->nSegCount );
-        poDS->papszSegName =
-            (char **) VSICalloc( sizeof(char*), poDS->nSegCount );
-        poDS->panSegOffset = (vsi_l_offset *) 
-            VSICalloc( sizeof(vsi_l_offset), poDS->nSegCount );
-        poDS->panSegSize = (vsi_l_offset *) 
-            VSICalloc( sizeof(vsi_l_offset), poDS->nSegCount );
-        
-        if (poDS->panSegType == NULL ||
-            poDS->papszSegName == NULL ||
-            poDS->panSegOffset == NULL ||
-            poDS->panSegSize == NULL)
-        {
-            CPLError( CE_Failure, CPLE_OutOfMemory,
-                       "Not enough memory to hold segment description of %s",
-                      poOpenInfo->pszFilename );
-            delete poDS;
-            return NULL;
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Parse each segment pointer.                                     */
-/* -------------------------------------------------------------------- */
-        int             iSeg;
-    
-        for( iSeg = 0; iSeg < poDS->nSegCount; iSeg++ )
-        {
-            int bActive, nSegStartBlock, nSegSize;
-            char szSegName[9];
-            
-            VSIFSeekL( poDS->fp, nSegPointersOffset + iSeg * 32, SEEK_SET );
-            if (VSIFReadL( szTemp, 1, 32, poDS->fp ) != 32)
-            {
-                delete poDS;
-                return NULL;
-            }
-            szTemp[32] = '\0';
-            
-            strncpy( szSegName, szTemp+4, 8 );
-            szSegName[8] = '\0';
-            
-            if ( szTemp[0] == 'A' || szTemp[0] == 'L' )
-                bActive = TRUE;
-            else
-                bActive = FALSE;
-            
-            if( !bActive )
-                continue;
-            
-            poDS->panSegType[iSeg] = CPLScanLong( szTemp + 1, 3 );
-            nSegStartBlock = CPLScanLong( szTemp+12, 11 );
-            nSegSize = CPLScanLong( szTemp+23, 9 );
-            
-            poDS->papszSegName[iSeg] = CPLStrdup( szSegName );
-            poDS->panSegOffset[iSeg] = 512 * ((vsi_l_offset) (nSegStartBlock-1));
-            poDS->panSegSize[iSeg] = 512 * ((vsi_l_offset) nSegSize);
-            
-            CPLDebug( "PCIDSK", 
-                      "Seg=%d, Type=%d, Start=%9d, Size=%7d, Name=%s",
-                      iSeg+1, poDS->panSegType[iSeg], 
-                      nSegStartBlock, nSegSize, szSegName );
-            
-            // Some segments will be needed sooner, rather than later. 
-            
-            if( poDS->panSegType[iSeg] == 182 && EQUAL(szSegName,"SysBMDir"))
-                poDS->nBlockMapSeg = iSeg+1;
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Read Image Data.                                                */
-/* -------------------------------------------------------------------- */
-    vsi_l_offset    nImageStart;        // Start block of image data
-    vsi_l_offset    nImgHdrsStart;      // Start block of image headers
-    vsi_l_offset    nImageOffset;       // Offset to the first byte of the image
-    int             nByteBands, nInt16Bands, nUInt16Bands, nFloat32Bands;
-
-    pszString = CPLScanString( szTemp + 304, 16, TRUE, FALSE );
-    if ( !EQUAL( pszString, "" ) )
-        nImageStart = atol( pszString );// XXX: should be atoll()
-    else
-        nImageStart = 1;
-    CPLFree( pszString );
-    nImageOffset = (nImageStart - 1) * 512;
-
-    pszString = CPLScanString( szTemp + 336, 16, TRUE, FALSE );
-    nImgHdrsStart = atol( pszString );  // XXX: should be atoll()
-    CPLFree( pszString );
-
-    poDS->nBands = CPLScanLong( szTemp + 376, 8 );
-    poDS->nRasterXSize = CPLScanLong( szTemp + 384, 8 );
-    poDS->nRasterYSize = CPLScanLong( szTemp + 392, 8 );
-
-    if  ( poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0 )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Invalid dimensions : %d x %d", 
-                  poDS->nRasterXSize, poDS->nRasterYSize );
-        delete poDS;
-        return NULL;
-    }
-
-    nByteBands = CPLScanLong( szTemp + 464, 4 );
-    nInt16Bands = CPLScanLong( szTemp + 468, 4 );
-    nUInt16Bands = CPLScanLong( szTemp + 472, 4 );
-    nFloat32Bands = CPLScanLong( szTemp + 476, 4 );
-
-    // If these fields are blank, then it is assumed that all channels are 8-bit
-    if ( nByteBands == 0 && nInt16Bands == 0
-         && nUInt16Bands == 0 && nFloat32Bands == 0 )
-        nByteBands = poDS->nBands;
-
-/* ==================================================================== */
-/*   Read Image Headers and create band information objects.            */
-/* ==================================================================== */
-    int             iBand;
-    PCIDSKInterleaving eInterleaving;
-
-/* -------------------------------------------------------------------- */
-/*      Read type of interleaving and set up image parameters.          */
-/* -------------------------------------------------------------------- */
-    pszString = CPLScanString( szTemp + 360, 8, TRUE, FALSE );
-    if ( EQUALN( pszString, "PIXEL", 5 ) )
-        eInterleaving = PDI_PIXEL;
-    else if ( EQUALN( pszString, "BAND", 4 ) )
-        eInterleaving = PDI_BAND;
-    else if ( EQUALN( pszString, "FILE", 4 ) )
-        eInterleaving = PDI_FILE;
-    else
-    {
-        CPLDebug( "PCIDSK",
-                  "PCIDSK interleaving type %s is not supported by GDAL",
-                  pszString );
-        delete poDS;
-        return NULL;
-    }
-    CPLFree( pszString );
-
-    for( iBand = 0; iBand < poDS->nBands; iBand++ )
-    {
-        GDALDataType    eType;
-        GDALRasterBand  *poBand = NULL;
-        vsi_l_offset    nImgHdrOffset = (nImgHdrsStart - 1 + iBand * 2) * 512;
-        vsi_l_offset    nPixelOffset = 0, nLineOffset = 0, nLineSize = 0;
-        int             bNativeOrder;
-        int             i;
-        VSILFILE       *fp = poDS->fp;
-
-        VSIFSeekL( poDS->fp, nImgHdrOffset, SEEK_SET );
-        if ( VSIFReadL( szTemp, 1, 1024, poDS->fp ) != 1024 )
-        {
-            delete poDS;
-            return NULL;
-        }
-
-        pszString = CPLScanString( szTemp + 160, 8, TRUE, FALSE );
-        eType = poDS->PCIDSKTypeToGDAL( pszString );
-
-        // Old files computed type based on list.
-        if( eType == GDT_Unknown && pszString[0] == '\0' )
-        {
-            if( iBand < nByteBands )
-                eType = GDT_Byte;
-            else if( iBand < nByteBands + nInt16Bands )
-                eType = GDT_Int16;
-            else if( iBand < nByteBands + nInt16Bands + nUInt16Bands )
-                eType = GDT_UInt16;
-            else if( iBand < nByteBands + nInt16Bands  + nUInt16Bands
-                     + nFloat32Bands )
-                eType = GDT_Float32;
-        }
-
-        if ( eType == GDT_Unknown )
-        {
-            CPLDebug( "PCIDSK",
-                      "PCIDSK data type %s is not supported by GDAL",
-                      pszString );
-            delete poDS;
-            return NULL;
-        }
-        CPLFree( pszString );
-
-        switch ( eInterleaving )
-        {
-          case PDI_PIXEL:
-            nPixelOffset = nByteBands + 2 * (nInt16Bands + nUInt16Bands)
-                + 4 * nFloat32Bands;
-            nLineSize = nPixelOffset * poDS->nRasterXSize;
-            nLineOffset = ((int)((nLineSize + 511)/512)) * 512;
-            break;
-          case PDI_BAND:
-            nPixelOffset = GDALGetDataTypeSize( eType ) / 8;
-            nLineOffset = nPixelOffset * poDS->nRasterXSize;
-            break;
-          case PDI_FILE:
-          {
-              char    *pszFilename;
-
-              // Read the filename
-              pszFilename = CPLScanString( szTemp + 64, 64, TRUE, FALSE );
-
-              // /SIS=n is special case for internal tiled file.
-              if( EQUALN(pszFilename,"/SIS=",5) )
-              {
-                  int nImage = atoi(pszFilename+5);
-                  poBand = new PCIDSKTiledRasterBand( poDS, iBand+1, nImage );
-                  if ( poBand->GetXSize() == 0 )
-                  {
-                      CPLFree( pszFilename );
-                      delete poBand;
-                      delete poDS;
-                      return NULL;
-                  }
-              }
-
-              // Non-empty filename means we have data stored in
-              // external raw file
-              else if ( !EQUAL(pszFilename, "") )
-              {
-                  CPLDebug( "PCIDSK", "pszFilename=%s", pszFilename );
-
-                  if( poOpenInfo->eAccess == GA_ReadOnly )
-                      fp = VSIFOpenL( pszFilename, "rb" );
-                  else
-                      fp = VSIFOpenL( pszFilename, "r+b" );
-
-                  if ( !fp )
-                  {
-                      CPLDebug( "PCIDSK",
-                                "Cannot open external raw file %s",
-                                pszFilename );
-                      iBand--;
-                      poDS->nBands--;
-                      CPLFree( pszFilename );
-                      continue;
-                  }
-
-                  poDS->nBandFileCount++;
-                  poDS->pafpBandFiles = (VSILFILE **)
-                      CPLRealloc( poDS->pafpBandFiles,
-                                  poDS->nBandFileCount * sizeof(VSILFILE*) );
-                  poDS->pafpBandFiles[poDS->nBandFileCount-1] = fp;
-              }
-
-              pszString = CPLScanString( szTemp + 168, 16, TRUE, FALSE );
-              nImageOffset = atol( pszString ); // XXX: should be atoll()
-              CPLFree( pszString );
-
-              nPixelOffset = CPLScanLong( szTemp + 184, 8 );
-              nLineOffset = CPLScanLong( szTemp +  + 192, 8 );
-
-              CPLFree( pszFilename );
-          }
-          break;
-          default: /* NOTREACHED */
-            break;
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Create raw band, only if we didn't already get a tiled band.    */
-/* -------------------------------------------------------------------- */
-        if( poBand == NULL )
-        {
-#ifdef CPL_MSB
-            bNativeOrder = ( szTemp[201] == 'S')?FALSE:TRUE;
-#else
-            bNativeOrder = ( szTemp[201] == 'S')?TRUE:FALSE;
-#endif
-
-#ifdef DEBUG
-            CPLDebug( "PCIDSK",
-                      "Band %d: nImageOffset=" CPL_FRMT_GIB ", nPixelOffset=" CPL_FRMT_GIB ", "
-                      "nLineOffset=" CPL_FRMT_GIB ", nLineSize=" CPL_FRMT_GIB,
-                      iBand + 1, (GIntBig)nImageOffset, (GIntBig)nPixelOffset,
-                      (GIntBig)nLineOffset, (GIntBig)nLineSize );
-#endif
-            
-            poBand = new PCIDSKRawRasterBand( poDS, iBand + 1, fp,
-                                              nImageOffset, 
-                                              (int) nPixelOffset, 
-                                              (int) nLineOffset, 
-                                              eType, bNativeOrder);
-
-            switch ( eInterleaving )
-            {
-              case PDI_PIXEL:
-                nImageOffset += GDALGetDataTypeSize( eType ) / 8;
-                break;
-              case  PDI_BAND:
-                nImageOffset += nLineOffset * poDS->nRasterYSize;
-                break;
-              default:
-                break;
-            }
-        }
-
-        poDS->SetBand( iBand + 1, poBand );
-
-/* -------------------------------------------------------------------- */
-/*      Read and assign few metadata parameters to each image band.     */
-/* -------------------------------------------------------------------- */
-        pszString = CPLScanString( szTemp, 64, TRUE, TRUE );
-        poBand->SetDescription( pszString );
-        CPLFree( pszString );
-
-        pszString = CPLScanString( szTemp + 128, 16, TRUE, TRUE );
-        poBand->SetMetadataItem( "DATE_OF_CREATION", pszString );
-        CPLFree( pszString );
-
-        pszString = CPLScanString( szTemp + 144, 16, TRUE, TRUE );
-        poBand->SetMetadataItem( "DATE_OF_UPDATE",  pszString );
-        CPLFree( pszString );
-
-        pszString = CPLScanString( szTemp + 202, 16, TRUE, TRUE );
-        if ( !EQUAL( szTemp, "" ) )
-            poBand->SetMetadataItem( "UNITS",  pszString );
-        CPLFree( pszString );
-
-        for ( i = 0; i < 8; i++ )
-        {
-            pszString = CPLScanString( szTemp + 384 + i * 80, 80, TRUE, TRUE );
-            if ( !EQUAL( pszString, "" ) )
-                poBand->SetMetadataItem( CPLSPrintf("HISTORY%d", i + 1),
-                                         pszString );
-            CPLFree( pszString );
-        }
-
-    }
-
-    if (!poDS->GetRasterCount())
-        CPLError(CE_Warning, CPLE_None, "Dataset contain no raster bands.");
-   
-/* ==================================================================== */
-/*      Process some segments of interest.                              */
-/* ==================================================================== */
-    int iSeg;
-
-    for( iSeg = 0; iSeg < poDS->nSegCount; iSeg++ )
-    {
-        switch( poDS->panSegType[iSeg] )
-        {
-/* -------------------------------------------------------------------- */
-/*      Georeferencing segment.                                         */
-/* -------------------------------------------------------------------- */
-            case 150:                   // GEO segment
-            {
-                vsi_l_offset    nGeoDataOffset;
-                int             j, nXCoeffs, nYCoeffs;
-                OGRSpatialReference oSRS;
-
-                poDS->nGeoPtrOffset = nSegPointersOffset + iSeg * 32;
-                poDS->nGeoOffset = poDS->panSegOffset[iSeg];
-                nGeoDataOffset = poDS->nGeoOffset + 1024;
-
-                VSIFSeekL( poDS->fp, nGeoDataOffset, SEEK_SET );
-                VSIFReadL( szTemp, 1, 16, poDS->fp );
-                szTemp[16] = '\0';
-                if ( EQUALN( szTemp, "POLYNOMIAL", 10 ) )
-                {
-                    char        szProj[17];
-
-                    // Read projection definition
-                    VSIFSeekL( poDS->fp, nGeoDataOffset + 32, SEEK_SET );
-                    VSIFReadL( szProj, 1, 16, poDS->fp );
-                    szProj[16] = '\0';
-                    if ( EQUALN( szProj, "PIXEL", 5 ) )
-                        break;
-
-                    // Read number of transform coefficients
-                    VSIFSeekL( poDS->fp, nGeoDataOffset + 48, SEEK_SET );
-                    VSIFReadL( szTemp, 1, 16, poDS->fp );
-                    nXCoeffs = CPLScanLong( szTemp, 8 );
-                    if ( nXCoeffs > 3 )
-                        nXCoeffs = 3;
-                    nYCoeffs = CPLScanLong( szTemp + 8, 8 );
-                    if ( nYCoeffs > 3 )
-                        nYCoeffs = 3;
-
-                    // Read geotransform coefficients
-                    VSIFSeekL( poDS->fp, nGeoDataOffset + 212, SEEK_SET );
-                    VSIFReadL( szTemp, 1, nXCoeffs * 26, poDS->fp );
-                    for ( j = 0; j < nXCoeffs; j++ )
-                    {
-                        poDS->adfGeoTransform[j] =
-                            CPLScanDouble( szTemp + 26 * j, 26 );
-                    }
-                    VSIFSeekL( poDS->fp, nGeoDataOffset + 1642, SEEK_SET );
-                    VSIFReadL( szTemp, 1, nYCoeffs * 26, poDS->fp );
-                    for ( j = 0; j < nYCoeffs; j++ )
-                    {
-                        poDS->adfGeoTransform[j + 3] =
-                            CPLScanDouble( szTemp + 26 * j, 26 );
-                    }
-
-                    poDS->bGeoTransformValid = TRUE;
-
-                    oSRS.importFromPCI( szProj, NULL, NULL );
-                    if ( poDS->pszProjection )
-                        CPLFree( poDS->pszProjection );
-                    oSRS.exportToWkt( &poDS->pszProjection );
-                }
-                else if ( EQUALN( szTemp, "PROJECTION", 10 ) )
-                {
-                    char        szProj[17], szUnits[17];
-                    double      adfProjParms[17];
-
-                    // Read projection definition
-                    VSIFSeekL( poDS->fp, nGeoDataOffset + 32, SEEK_SET );
-                    VSIFReadL( szProj, 1, 16, poDS->fp );
-                    szProj[16] = '\0';
-                    if ( EQUALN( szProj, "PIXEL", 5 )
-                         || EQUALN( szProj, "METRE", 5 ) )
-                        break;
-
-                    // Read number of transform coefficients
-                    VSIFSeekL( poDS->fp, nGeoDataOffset + 48, SEEK_SET );
-                    VSIFReadL( szTemp, 1, 16, poDS->fp );
-                    nXCoeffs = CPLScanLong( szTemp, 8 );
-                    if ( nXCoeffs > 3 )
-                        nXCoeffs = 3;
-                    nYCoeffs = CPLScanLong( szTemp + 8, 8 );
-                    if ( nYCoeffs > 3 )
-                        nYCoeffs = 3;
-
-                    // Read grid units definition
-                    VSIFSeekL( poDS->fp, nGeoDataOffset + 64, SEEK_SET );
-                    VSIFReadL( szUnits, 1, 16, poDS->fp );
-                    szUnits[16] = '\0';
-
-                    // Read 16 projection parameters
-                    VSIFSeekL( poDS->fp, nGeoDataOffset + 80, SEEK_SET );
-                    VSIFReadL( szTemp, 1, 26 * 16, poDS->fp );
-                    for ( j = 0; j < 17; j++ )
-                    {
-                        adfProjParms[j] =
-                            CPLScanDouble( szTemp + 26 * j, 26 );
-                    }
-
-                    // Read geotransform coefficients
-                    VSIFSeekL( poDS->fp, nGeoDataOffset + 1980, SEEK_SET );
-                    VSIFReadL( szTemp, 1, nXCoeffs * 26, poDS->fp );
-                    for ( j = 0; j < nXCoeffs; j++ )
-                    {
-                        poDS->adfGeoTransform[j] =
-                            CPLScanDouble( szTemp + 26 * j, 26 );;
-                    }
-                    VSIFSeekL( poDS->fp, nGeoDataOffset + 2526, SEEK_SET );
-                    VSIFReadL( szTemp, 1, nYCoeffs * 26, poDS->fp );
-                    for ( j = 0; j < nYCoeffs; j++ )
-                    {
-                        poDS->adfGeoTransform[j + 3] =
-                            CPLScanDouble( szTemp + 26 * j, 26 );
-                    }
-
-                    poDS->bGeoTransformValid = TRUE;
-
-                    oSRS.importFromPCI( szProj, szUnits, adfProjParms );
-                    if ( poDS->pszProjection )
-                        CPLFree( poDS->pszProjection );
-                    oSRS.exportToWkt( &poDS->pszProjection );
-                }
-            }
-            break;
-
-/* -------------------------------------------------------------------- */
-/*      GCP Segment                                                     */
-/* -------------------------------------------------------------------- */
-            case 214:                       // GCP segment
-            {
-                vsi_l_offset    nGcpDataOffset;
-                int             j;
-                OGRSpatialReference oSRS;
-
-                poDS->nGcpPtrOffset = nSegPointersOffset + iSeg * 32;
-                poDS->nGcpOffset = poDS->panSegOffset[iSeg];
-                nGcpDataOffset = poDS->nGcpOffset + 1024;
-
-                if( !poDS->nGCPCount )  // XXX: We will read the
-                    // first GCP segment only
-                {
-                    VSIFSeekL( poDS->fp, nGcpDataOffset, SEEK_SET );
-                    VSIFReadL( szTemp, 1, 80, poDS->fp );
-                    poDS->nGCPCount = CPLScanLong( szTemp, 16 );
-                    if ( poDS->nGCPCount > 0 &&
-                         nGcpDataOffset + poDS->nGCPCount * 128 + 512 < poDS->nFileSize )
-                    {
-                        double      dfUnitConv = 1.0;
-                        char        szProj[17];
-
-                        memcpy( szProj, szTemp + 32, 16 );
-                        szProj[16] = '\0';
-                        oSRS.importFromPCI( szProj, NULL, NULL );
-                        if ( poDS->pszGCPProjection )
-                            CPLFree( poDS->pszGCPProjection );
-                        oSRS.exportToWkt( &poDS->pszGCPProjection );
-                        poDS->pasGCPList = (GDAL_GCP *)
-                            CPLCalloc( poDS->nGCPCount, sizeof(GDAL_GCP) );
-                        GDALInitGCPs( poDS->nGCPCount, poDS->pasGCPList );
-                        if ( EQUALN( szTemp + 64, "FEET     ", 9 ) )
-                            dfUnitConv = CPLAtof(SRS_UL_FOOT_CONV);
-                        for ( j = 0; j < poDS->nGCPCount; j++ )
-                        {
-                            VSIFSeekL( poDS->fp, nGcpDataOffset + j * 128 + 512,
-                                       SEEK_SET );
-                            VSIFReadL( szTemp, 1, 128, poDS->fp );
-                            poDS->pasGCPList[j].dfGCPPixel =
-                                CPLScanDouble( szTemp + 6, 18 );
-                            poDS->pasGCPList[j].dfGCPLine = 
-                                CPLScanDouble( szTemp + 24, 18 );
-                            poDS->pasGCPList[j].dfGCPX = 
-                                CPLScanDouble( szTemp + 60, 18 );
-                            poDS->pasGCPList[j].dfGCPY = 
-                                CPLScanDouble( szTemp + 78, 18 );
-                            poDS->pasGCPList[j].dfGCPZ =
-                                CPLScanDouble( szTemp + 96, 18 ) / dfUnitConv;
-                        }
-                    }
-
-                    poDS->bGeoTransformValid = TRUE;
-                }
-            }
-            break;
-
-/* -------------------------------------------------------------------- */
-/*      SYS Segments.  Process metadata immediately.                    */
-/* -------------------------------------------------------------------- */
-            case 182: // SYS segment.
-            {
-                if( EQUAL(poDS->papszSegName[iSeg],"METADATA") )
-                    poDS->CollectPCIDSKMetadata( iSeg+1 );
-            }
-            break;
-
-            default:
-                break;
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Check for band overviews.                                       */
-/* -------------------------------------------------------------------- */
-    for( iBand = 0; iBand < poDS->GetRasterCount(); iBand++ )
-    {
-        GDALRasterBand *poBand = poDS->GetRasterBand( iBand+1 );
-        char **papszMD = poBand->GetMetadata( "PCISYS" );
-        int iMD;
-
-        for( iMD = 0; papszMD != NULL && papszMD[iMD] != NULL; iMD++ )
-        {
-            if( EQUALN(papszMD[iMD],"Overview_",9) )
-            {
-                int nBlockXSize, nBlockYSize;
-                int nImage = atoi(CPLParseNameValue( papszMD[iMD], NULL ));
-                PCIDSKTiledRasterBand *poOvBand;
-
-                poOvBand = new PCIDSKTiledRasterBand( poDS, 0, nImage );
-                if ( poOvBand->GetXSize() == 0 )
-                {
-                    delete poOvBand;
-                    delete poDS;
-                    return NULL;
-                }
-
-                poBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
-               
-                if( nBlockYSize == 1 )
-                    ((PCIDSKRawRasterBand *) poBand)->
-                        AttachOverview( poOvBand );
-                else
-                    ((PCIDSKTiledRasterBand *) poBand)->
-                        AttachOverview( poOvBand );
-            }
-        }
-    }
-    
-/* -------------------------------------------------------------------- */
-/*      Check for worldfile if we have no other georeferencing.         */
-/* -------------------------------------------------------------------- */
-    if( !poDS->bGeoTransformValid ) 
-        poDS->bGeoTransformValid = 
-            GDALReadWorldFile( poOpenInfo->pszFilename, "pxw", 
-                               poDS->adfGeoTransform );
-
-/* -------------------------------------------------------------------- */
-/*      Initialize any PAM information.                                 */
-/* -------------------------------------------------------------------- */
-    poDS->SetDescription( poOpenInfo->pszFilename );
-    poDS->TryLoadXML();
-
-/* -------------------------------------------------------------------- */
-/*      Open overviews.                                                 */
-/* -------------------------------------------------------------------- */
-    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
-
-    return( poDS );
-}
-
-/************************************************************************/
-/*                              SegRead()                               */
-/************************************************************************/
-
-int PCIDSKDataset::SegRead( int nSegment, vsi_l_offset nOffset, 
-                            int nSize, void *pBuffer )
-
-{
-    if( nSegment < 1 || nSegment > nSegCount || panSegType[nSegment-1] == 0 )
-        return 0;
-
-    if( nOffset + nSize > panSegSize[nSegment-1] )
-    {
-        return 0;
-    }
-    else
-    {
-        if( VSIFSeekL( fp, panSegOffset[nSegment-1]+nOffset+1024, 
-                       SEEK_SET ) != 0 ) 
-            return 0;
-
-        return VSIFReadL( pBuffer, 1, nSize, fp );
-    }
-}
-
-
-/************************************************************************/
-/*                       CollectPCIDSKMetadata()                        */
-/************************************************************************/
-
-void PCIDSKDataset::CollectPCIDSKMetadata( int nSegment )
-
-{
-    int nSegSize = (int) panSegSize[nSegment-1];
-
-/* -------------------------------------------------------------------- */
-/*      Read all metadata in one gulp.                                  */
-/* -------------------------------------------------------------------- */
-    char *pszMetadataBuf = (char *) VSICalloc( 1, nSegSize + 1 );
-    if ( pszMetadataBuf == NULL )
-        return;
-
-    if( !SegRead( nSegment, 0, nSegSize, pszMetadataBuf ) )
-    {
-        CPLFree( pszMetadataBuf );
-        CPLError( CE_Warning, CPLE_FileIO,
-                  "IO error reading metadata, ignoring." );
-        return;
-    }
-
-/* ==================================================================== */
-/*      Parse out domain/name/value sets.                               */
-/* ==================================================================== */
-    char *pszNext = pszMetadataBuf;
-
-    while( *pszNext != '\0' )
-    {
-        char *pszName, *pszValue;
-
-        pszName = pszNext;
-        
-/* -------------------------------------------------------------------- */
-/*      Identify the end of this line, and zero terminate it.           */
-/* -------------------------------------------------------------------- */
-        while( *pszNext != 10 && *pszNext != 12 && *pszNext != 0 )
-            pszNext++;
-
-        if( *pszNext != 0 )
-        {
-            *(pszNext++) = '\0';
-            while( *pszNext == 10 || *pszNext == 12 )
-                pszNext++;
-        }
-            
-/* -------------------------------------------------------------------- */
-/*      Split off the value from the name.                              */
-/* -------------------------------------------------------------------- */
-        pszValue = pszName;
-        while( *pszValue != 0 && *pszValue != ':' ) 
-            pszValue++;
-
-        if( *pszValue != 0 )
-            *(pszValue++) = '\0';
-
-        while( *pszValue == ' ' )
-            pszValue++;
-
-/* -------------------------------------------------------------------- */
-/*      Handle METADATA_IMG values by assigning to the appropriate      */
-/*      band object.                                                    */
-/* -------------------------------------------------------------------- */
-        if( EQUALN(pszName,"METADATA_IMG_",13) )
-        {
-            int nBand = atoi(pszName+13);
-            pszName += 13;
-            while( *pszName && *pszName != '_' )
-                pszName++;
-
-            if( *pszName == '_' )
-                pszName++;
-
-            if( nBand > 0 && nBand <= GetRasterCount() )
-            {
-                GDALRasterBand *poBand = GetRasterBand( nBand );
-
-                if( *pszName == '_' )
-                    poBand->SetMetadataItem( pszName+1, pszValue, "PCISYS" );
-                else
-                    poBand->SetMetadataItem( pszName, pszValue );
-            }
-        }
-        
-        else if( EQUALN(pszName,"METADATA_FIL",13) )
-        {
-            pszName += 13;
-            if( *pszName == '_' )
-                pszName++;
-
-            if( *pszName == '_' )
-                SetMetadataItem( pszName+1, pszValue, "PCISYS" );
-            else
-                SetMetadataItem( pszName, pszValue );
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Cleanup                                                         */
-/* -------------------------------------------------------------------- */
-    CPLFree( pszMetadataBuf );
-}
-
-/************************************************************************/
-/*                               Create()                               */
-/************************************************************************/
-
-GDALDataset *PCIDSKDataset::Create( const char * pszFilename,
-                                    int nXSize, int nYSize, int nBands,
-                                    GDALDataType eType, char **papszOptions )
-
-{
-    if ( eType != GDT_Byte
-         && eType != GDT_Int16
-         && eType != GDT_UInt16
-         && eType != GDT_Float32 )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-              "Attempt to create PCIDSK dataset with an illegal data type (%s),\n"
-              "only Byte, Int16, UInt16 and Float32 supported by the format.\n",
-              GDALGetDataTypeName(eType) );
-
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Try to create the file.                                         */
-/* -------------------------------------------------------------------- */
-    VSILFILE        *fp = VSIFOpenL( pszFilename, "wb" );
-
-    if( fp == NULL )
-    {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Unable to create file %s.\n", pszFilename );
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Get current time to fill appropriate fields.                    */
-/* -------------------------------------------------------------------- */
-    struct tm       oUpdateTime;
-    time_t          nTime = VSITime(NULL);
-
-    VSILocalTime( &nTime, &oUpdateTime );
-
-/* ==================================================================== */
-/*      Fill the PCIDSK File Header.                                    */
-/* ==================================================================== */
-    const char      *pszDesc;
-    char            szTemp[1024];
-    vsi_l_offset    nImageStart;        // Start block of image data
-    vsi_l_offset    nSegPointersStart;  // Start block of Segment Pointers
-    vsi_l_offset    nImageBlocks;       // Number of blocks of image data
-    int             nImgHdrBlocks;      // Number of blocks of image header data
-
-/* -------------------------------------------------------------------- */
-/*      Calculate offsets.                                              */
-/* -------------------------------------------------------------------- */
-    nImgHdrBlocks = nBands * 2;
-    nSegPointersStart = 2 + nImgHdrBlocks;
-    nImageStart = nSegPointersStart + nSegBlocks;
-    nImageBlocks = 
-        (nXSize * ((vsi_l_offset)nYSize) * nBands * (GDALGetDataTypeSize(eType)/8) + 512) / 512;
- 
-/* -------------------------------------------------------------------- */
-/*      Fill the File Identification.                                   */
-/* -------------------------------------------------------------------- */
-    CPLPrintStringFill( szTemp, "PCIDSK  ", 8 );
-    CPLPrintStringFill( szTemp + 8, "GDAL", 4 );
-    CPLPrintStringFill( szTemp + 12, GDALVersionInfo( "VERSION_NUM" ), 4 );
-    CPLPrintUIntBig( szTemp + 16,
-                  nImageStart + nImageBlocks + nGeoSegBlocks - 1, 16 );
-    CPLPrintStringFill( szTemp + 32, "", 16 );
-    CPLPrintStringFill( szTemp + 48, CPLGetFilename(pszFilename), 64 );
-    CPLPrintStringFill( szTemp + 112, "Created with GDAL", 32 );
-
-    pszDesc = CSLFetchNameValue( papszOptions, "FILEDESC1" );
-    if ( !pszDesc )
-        pszDesc = "";
-    CPLPrintStringFill( szTemp + 144, pszDesc, 64 );
-
-    pszDesc = CSLFetchNameValue( papszOptions, "FILEDESC2" );
-    if ( !pszDesc )
-        pszDesc = "";
-    CPLPrintStringFill( szTemp + 208, pszDesc, 64 );
-
-    CPLPrintTime( szTemp + 272, 16, "%H:%M %d-%b-%y ", &oUpdateTime, "C" );
-    CPLPrintTime( szTemp + 288, 16, "%H:%M %d-%b-%y ", &oUpdateTime, "C" );
-
-/* -------------------------------------------------------------------- */
-/*      Fill the Image Data and Segment Pointers.                       */
-/* -------------------------------------------------------------------- */
-    CPLPrintUIntBig( szTemp + 304, nImageStart, 16 );
-    CPLPrintUIntBig( szTemp + 320, nImageBlocks, 16 );
-    sprintf( szTemp + 336, "%16d", 2 );
-    sprintf( szTemp + 352, "%8d", nImgHdrBlocks );
-    CPLPrintStringFill( szTemp + 360, "BAND", 8 );
-    CPLPrintStringFill( szTemp + 368, "", 8 );
-    sprintf( szTemp + 376, "%8d", nBands );
-    sprintf( szTemp + 384, "%8d", nXSize );
-    sprintf( szTemp + 392, "%8d", nYSize );
-    CPLPrintStringFill( szTemp + 400, "METRE", 8 );
-    // Two following parameters will be filled with real values in FlushCache()
-    CPLPrintStringFill( szTemp + 408, "", 16 );    // X size of pixel
-    CPLPrintStringFill( szTemp + 424, "", 16 );    // Y size of pixel
-
-    CPLPrintUIntBig( szTemp + 440, nSegPointersStart, 16 );
-    sprintf( szTemp + 456, "%8d", nSegBlocks );
-    if ( eType == GDT_Byte )
-        sprintf( szTemp + 464, "%4d", nBands );
-    else
-        CPLPrintStringFill( szTemp + 464, "   0", 4 );
-    if ( eType == GDT_Int16 )
-        sprintf( szTemp + 468, "%4d", nBands );
-    else
-        CPLPrintStringFill( szTemp + 468, "   0", 4 );
-    if ( eType == GDT_UInt16 )
-        sprintf( szTemp + 472, "%4d", nBands );
-    else
-        CPLPrintStringFill( szTemp + 472, "   0", 4 );
-    if ( eType == GDT_Float32 )
-        sprintf( szTemp + 476, "%4d", nBands );
-    else
-        CPLPrintStringFill( szTemp + 476, "   0", 4 );
-    CPLPrintStringFill( szTemp + 480, "", 32 );
-    
-    VSIFSeekL( fp, 0, SEEK_SET );
-    VSIFWriteL( (void *)szTemp, 1, 512, fp );
-
-/* ==================================================================== */
-/*      Fill the Image Headers.                                         */
-/* ==================================================================== */
-    int         i;
-
-    for ( i = 0; i < nBands; i++ )
-    {
-        pszDesc =
-            CSLFetchNameValue( papszOptions, CPLSPrintf("BANDDESC%d", i + 1) );
-
-        if ( !pszDesc )
-            pszDesc = CPLSPrintf( "Image band %d", i + 1 );
-
-        CPLPrintStringFill( szTemp, pszDesc, 64 );
-        CPLPrintStringFill( szTemp + 64, "", 64 );
-        CPLPrintTime( szTemp + 128, 16, "%H:%M %d-%b-%y ", &oUpdateTime, "C" );
-        CPLPrintTime( szTemp + 144, 16, "%H:%M %d-%b-%y ", &oUpdateTime, "C" );
-        switch ( eType )
-        {
-            case GDT_Byte:
-                CPLPrintStringFill( szTemp + 160, "8U", 8 );
-                break;
-            case GDT_Int16:
-                CPLPrintStringFill( szTemp + 160, "16S", 8 );
-                break;
-            case GDT_UInt16:
-                CPLPrintStringFill( szTemp + 160, "16U", 8 );
-                break;
-            case GDT_Float32:
-                CPLPrintStringFill( szTemp + 160, "32R", 8 );
-                break;
-            default:
-                break;
-        }
-        CPLPrintStringFill( szTemp + 168, "", 16 );
-        CPLPrintStringFill( szTemp + 184, "", 8 );
-        CPLPrintStringFill( szTemp + 192, "", 8 );
-        CPLPrintStringFill( szTemp + 200, " ", 1 );
-        CPLPrintStringFill( szTemp + 201, "N", 1 ); // only N is supported!
-        CPLPrintStringFill( szTemp + 202, "", 48 );
-        CPLPrintStringFill( szTemp + 250, "", 32 );
-        CPLPrintStringFill( szTemp + 282, "", 8 );
-        CPLPrintStringFill( szTemp + 290, "", 94 );
-
-        // Write the history line
-        CPLPrintStringFill( szTemp + 384,
-                            "GDAL: Image band created with GDAL", 64 );
-        CPLPrintTime( szTemp + 448, 16, "%H:%M %d-%b-%y ", &oUpdateTime, "C" );
-        // Fill other lines with spaces
-        CPLPrintStringFill( szTemp + 464, "", 80 * 7 );
-
-        // More history lines may be used if needed.
-        // CPLPrintStringFill( szTemp + 464, "HistoryLine2", 80 );
-        // CPLPrintStringFill( szTemp + 544, "HistoryLine3", 80 );
-        // CPLPrintStringFill( szTemp + 624, "HistoryLine4", 80 );
-        // CPLPrintStringFill( szTemp + 704, "HistoryLine5", 80 );
-        // CPLPrintStringFill( szTemp + 784, "HistoryLine6", 80 );
-        // CPLPrintStringFill( szTemp + 864, "HistoryLine7", 80 );
-        // CPLPrintStringFill( szTemp + 944, "HistoryLine8", 80 );
-
-        VSIFWriteL( (void *)szTemp, 1, 1024, fp );
-    }
-
-/* ==================================================================== */
-/*      Fill the Segment Pointers.                                      */
-/* ==================================================================== */
-    int         nSegments = ( nSegBlocks * 512 ) / 32;
-
-/* -------------------------------------------------------------------- */
-/*      Write out pointer to the Georeferencing segment.                */
-/* -------------------------------------------------------------------- */
-    CPLPrintStringFill( szTemp, "A150GEOref", 12 );
-    CPLPrintUIntBig( szTemp + 12, nImageStart + nImageBlocks, 11 );
-    sprintf( szTemp + 23, "%9d", nGeoSegBlocks );
-    VSIFWriteL( (void *)szTemp, 1, 32, fp );
-
-/* -------------------------------------------------------------------- */
-/*      Blank all other segment pointers                                */
-/* -------------------------------------------------------------------- */
-    CPLPrintStringFill( szTemp, "", 32 );
-    for ( i = 1; i < nSegments; i++ )
-        VSIFWriteL( (void *)szTemp, 1, 32, fp );
-
-/* -------------------------------------------------------------------- */
-/*      Write out default georef segment.                               */
-/* -------------------------------------------------------------------- */
-    static const char *apszGeoref[] = {
-        "Master Georeferencing Segment for File                                                                                          17:27 11Nov2003 17:27 11Nov2003                                                                                                                                                                                                                                                                                                                                     [...]
-
-    for( i = 0; apszGeoref[i] != NULL; i++ )
-        VSIFWriteL( (void *) apszGeoref[i], 1, strlen(apszGeoref[i]), fp );
-
-    VSIFCloseL( fp );
-    return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
-}
-
-
-/************************************************************************/
-/*                             CreateCopy()                             */
-/************************************************************************/
-
-GDALDataset *
-PCIDSKDataset::CreateCopy( const char * pszFilename,
-                           GDALDataset *poSrcDS,
-                           CPL_UNUSED int bStrict,
-                           char ** papszOptions,
-                           GDALProgressFunc pfnProgress,
-                           void * pProgressData )
-{
-    PCIDSKDataset	*poDS;
-    GDALDataType eType;
-    int          iBand;
-
-    int nBands = poSrcDS->GetRasterCount();
-    if (nBands == 0)
-    {
-        CPLError( CE_Failure, CPLE_NotSupported, 
-                  "PCIDSK driver does not support source dataset with zero band.\n");
-        return NULL;
-    }
-
-    if( !pfnProgress( 0.0, NULL, pProgressData ) )
-        return NULL;
-
-    eType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
-
-    /* check that other bands match type- sets type */
-    /* to unknown if they differ.                  */
-    for( iBand = 1; iBand < nBands; iBand++ )
-     {
-         GDALRasterBand *poBand = poSrcDS->GetRasterBand( iBand+1 );
-         eType = GDALDataTypeUnion( eType, poBand->GetRasterDataType() );
-     }
-
-    poDS = (PCIDSKDataset *) Create( pszFilename, 
-                                  poSrcDS->GetRasterXSize(), 
-                                  poSrcDS->GetRasterYSize(), 
-                                  poSrcDS->GetRasterCount(), 
-                                  eType, papszOptions );
-
-   /* Check that Create worked- return Null if it didn't */
-    if (poDS == NULL)
-        return NULL;
-
-/* -------------------------------------------------------------------- */
-/*      Copy the image data.                                            */
-/* -------------------------------------------------------------------- */
-    int         nXSize = poDS->GetRasterXSize();
-    int         nYSize = poDS->GetRasterYSize();
-    int  	nBlockXSize, nBlockYSize, nBlockTotal, nBlocksDone;
-
-    poDS->GetRasterBand(1)->GetBlockSize( &nBlockXSize, &nBlockYSize );
-
-    nBlockTotal = ((nXSize + nBlockXSize - 1) / nBlockXSize)
-        * ((nYSize + nBlockYSize - 1) / nBlockYSize)
-        * poSrcDS->GetRasterCount();
-
-    nBlocksDone = 0;
-    for( iBand = 0; iBand < poSrcDS->GetRasterCount(); iBand++ )
-    {
-        GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand+1 );
-        GDALRasterBand *poDstBand = poDS->GetRasterBand( iBand+1 );
-        int	       iYOffset, iXOffset;
-        void           *pData;
-        CPLErr  eErr;
-
-
-        pData = CPLMalloc(nBlockXSize * nBlockYSize
-                          * GDALGetDataTypeSize(eType) / 8);
-
-        for( iYOffset = 0; iYOffset < nYSize; iYOffset += nBlockYSize )
-        {
-            for( iXOffset = 0; iXOffset < nXSize; iXOffset += nBlockXSize )
-            {
-                int	nTBXSize, nTBYSize;
-
-                if( !pfnProgress( (nBlocksDone++) / (float) nBlockTotal,
-                                  NULL, pProgressData ) )
-                {
-                    CPLError( CE_Failure, CPLE_UserInterrupt, 
-                              "User terminated" );
-                    delete poDS;
-
-                    GDALDriver *poPCIDSKDriver = 
-                        (GDALDriver *) GDALGetDriverByName( "PCIDSK" );
-                    poPCIDSKDriver->Delete( pszFilename );
-                    return NULL;
-                }
-
-                nTBXSize = MIN(nBlockXSize,nXSize-iXOffset);
-                nTBYSize = MIN(nBlockYSize,nYSize-iYOffset);
-
-                eErr = poSrcBand->RasterIO( GF_Read, 
-                                            iXOffset, iYOffset, 
-                                            nTBXSize, nTBYSize,
-                                            pData, nTBXSize, nTBYSize,
-                                            eType, 0, 0, NULL );
-                if( eErr != CE_None )
-                {
-                    return NULL;
-                }
-            
-                eErr = poDstBand->RasterIO( GF_Write, 
-                                            iXOffset, iYOffset, 
-                                            nTBXSize, nTBYSize,
-                                            pData, nTBXSize, nTBYSize,
-                                            eType, 0, 0, NULL );
-
-                if( eErr != CE_None )
-                {
-                    return NULL;
-                }
-            }
-        }
-
-        CPLFree( pData );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Copy georeferencing information, if enough is available.        */
-/* -------------------------------------------------------------------- */
-
-    double *tempGeoTransform=NULL; 
-
-    tempGeoTransform = (double *) CPLMalloc(6*sizeof(double));
-
-    if (( poSrcDS->GetGeoTransform( tempGeoTransform ) == CE_None)
-        && (tempGeoTransform[0] != 0.0 || tempGeoTransform[1] != 1.0
-        || tempGeoTransform[2] != 0.0 || tempGeoTransform[3] != 0.0
-        || tempGeoTransform[4] != 0.0 || ABS(tempGeoTransform[5]) != 1.0 ))
-    {
-          poDS->SetProjection(poSrcDS->GetProjectionRef());
-          poDS->SetGeoTransform(tempGeoTransform);
-    }
-    CPLFree(tempGeoTransform);
-        
-   
-    poDS->FlushCache();
-
-    if( !pfnProgress( 1.0, NULL, pProgressData ) )
-    {
-        CPLError( CE_Failure, CPLE_UserInterrupt, 
-                  "User terminated" );
-        delete poDS;
-
-        GDALDriver *poPCIDSKDriver = 
-            (GDALDriver *) GDALGetDriverByName( "PCIDSK" );
-        poPCIDSKDriver->Delete( pszFilename );
-        return NULL;
-    }
-
-    poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
-
-    return poDS;
-}
-/************************************************************************/
-/*                        GDALRegister_PCIDSK()                         */
-/************************************************************************/
-
-void GDALRegister_PCIDSK()
-
-{
-    GDALDriver  *poDriver;
-
-    if( GDALGetDriverByName( "PCIDSK" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-
-        poDriver->SetDescription( "PCIDSK" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "PCIDSK Database File" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "frmt_pcidsk.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "pix" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte UInt16 Int16 Float32" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
-"<CreationOptionList>"
-"   <Option name='FILEDESC1' type='string' description='The first line of descriptive text'/>"
-"   <Option name='FILEDESC2' type='string' description='The second line of descriptive text'/>"
-"   <Option name='BANDDESCn' type='string' description='Text describing contents of the specified band'/>"
-"</CreationOptionList>" ); 
-
-        poDriver->pfnIdentify = PCIDSKDataset::Identify;
-        poDriver->pfnOpen = PCIDSKDataset::Open;
-        poDriver->pfnCreate = PCIDSKDataset::Create;
-        poDriver->pfnCreateCopy = PCIDSKDataset::CreateCopy;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
-}
-
-
diff --git a/frmts/pcidsk/pcidskdataset2.cpp b/frmts/pcidsk/pcidskdataset2.cpp
index 4c83a62..ecb1054 100644
--- a/frmts/pcidsk/pcidskdataset2.cpp
+++ b/frmts/pcidsk/pcidskdataset2.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pcidskdataset2.cpp 28292 2015-01-05 19:35:55Z rouault $
+ * $Id: pcidskdataset2.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  PCIDSK Database File
  * Purpose:  Read/write PCIDSK Database File used by the PCI software, using
@@ -29,9 +29,10 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "gdal_frmts.h"
 #include "pcidskdataset2.h"
 
-CPL_CVSID("$Id: pcidskdataset2.cpp 28292 2015-01-05 19:35:55Z rouault $");
+CPL_CVSID("$Id: pcidskdataset2.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 const PCIDSK::PCIDSKInterfaces *PCIDSK2GetInterfaces(void);
 
@@ -47,26 +48,26 @@ const PCIDSK::PCIDSKInterfaces *PCIDSK2GetInterfaces(void);
 /*      This constructor is used for main file channels.                */
 /************************************************************************/
 
-PCIDSK2Band::PCIDSK2Band( PCIDSK2Dataset *poDS, 
-                          PCIDSKFile *poFile,
-                          int nBand )                        
+PCIDSK2Band::PCIDSK2Band( PCIDSK2Dataset *poDSIn,
+                          PCIDSKFile *poFileIn,
+                          int nBandIn )
 
 {
     Initialize();
 
-    this->poDS = poDS;
-    this->poFile = poFile;
-    this->nBand = nBand;
+    this->poDS = poDSIn;
+    this->poFile = poFileIn;
+    this->nBand = nBandIn;
 
     poChannel = poFile->GetChannel( nBand );
 
-    nBlockXSize = (int) poChannel->GetBlockWidth();
-    nBlockYSize = (int) poChannel->GetBlockHeight();
-    
+    nBlockXSize = static_cast<int>( poChannel->GetBlockWidth() );
+    nBlockYSize = static_cast<int>( poChannel->GetBlockHeight() );
+
     eDataType = PCIDSK2Dataset::PCIDSKTypeToGDAL( poChannel->GetType() );
 
-    if( !EQUALN(poChannel->GetDescription().c_str(),
-                "Contents Not Specified",20) )
+    if( !STARTS_WITH_CI(poChannel->GetDescription().c_str(),
+                "Contents Not Specified") )
         GDALMajorObject::SetDescription( poChannel->GetDescription().c_str() );
 
 /* -------------------------------------------------------------------- */
@@ -82,20 +83,20 @@ PCIDSK2Band::PCIDSK2Band( PCIDSK2Dataset *poDS,
 /*      as bands.                                                       */
 /************************************************************************/
 
-PCIDSK2Band::PCIDSK2Band( PCIDSKChannel *poChannel )
+PCIDSK2Band::PCIDSK2Band( PCIDSKChannel *poChannelIn )
 
 {
     Initialize();
 
-    this->poChannel = poChannel;
+    this->poChannel = poChannelIn;
 
     nBand = 1;
 
-    nBlockXSize = (int) poChannel->GetBlockWidth();
-    nBlockYSize = (int) poChannel->GetBlockHeight();
-    
-    nRasterXSize = (int) poChannel->GetWidth();
-    nRasterYSize = (int) poChannel->GetHeight();
+    nBlockXSize = static_cast<int>( poChannel->GetBlockWidth() );
+    nBlockYSize = static_cast<int>( poChannel->GetBlockHeight() );
+
+    nRasterXSize = static_cast<int>( poChannel->GetWidth() );
+    nRasterYSize = static_cast<int>( poChannel->GetHeight() );
 
     eDataType = PCIDSK2Dataset::PCIDSKTypeToGDAL( poChannel->GetType() );
 
@@ -103,8 +104,8 @@ PCIDSK2Band::PCIDSK2Band( PCIDSKChannel *poChannel )
     {
         SetMetadataItem( "NBITS", "1", "IMAGE_STRUCTURE" );
 
-        if( !EQUALN(poChannel->GetDescription().c_str(),
-                    "Contents Not Specified",20) )
+        if( !STARTS_WITH_CI(poChannel->GetDescription().c_str(),
+                    "Contents Not Specified") )
             GDALMajorObject::SetDescription( poChannel->GetDescription().c_str() );
     }
 }
@@ -154,15 +155,15 @@ PCIDSK2Band::~PCIDSK2Band()
 void PCIDSK2Band::SetDescription( const char *pszDescription )
 
 {
-    try 
+    try
     {
         poChannel->SetDescription( pszDescription );
 
-        if( !EQUALN(poChannel->GetDescription().c_str(),
-                    "Contents Not Specified",20) )
+        if( !STARTS_WITH_CI(poChannel->GetDescription().c_str(),
+                    "Contents Not Specified") )
             GDALMajorObject::SetDescription( poChannel->GetDescription().c_str() );
     }
-    catch( PCIDSKException ex )
+    catch( const PCIDSKException& ex )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", ex.what() );
@@ -182,21 +183,20 @@ char **PCIDSK2Band::GetCategoryNames()
     if( papszCategoryNames != NULL )
         return papszCategoryNames;
 
-    try 
+    try
     {
         std::vector<std::string> aosMDKeys = poChannel->GetMetadataKeys();
-        size_t i;
         int nClassCount = 0;
         static const int nMaxClasses = 10000;
-        papszCategoryNames = (char **) CPLCalloc(nMaxClasses+1, sizeof(char*));
-        
-        for( i=0; i < aosMDKeys.size(); i++ )
+        papszCategoryNames = reinterpret_cast<char **>(
+            CPLCalloc(nMaxClasses+1, sizeof(char*) ) );
+
+        for( size_t i = 0; i < aosMDKeys.size(); i++ )
         {
             CPLString osKey = aosMDKeys[i];
 
             // is this a "Class_n_name" keyword?
-
-            if( !EQUALN(osKey,"Class_",6) )
+            if( !STARTS_WITH_CI(osKey, "Class_") )
                 continue;
 
             if( !EQUAL(osKey.c_str() + osKey.size() - 5, "_name") )
@@ -210,7 +210,7 @@ char **PCIDSK2Band::GetCategoryNames()
 
             // Fetch the name.
             CPLString osName  = poChannel->GetMetadataValue(osKey);
-            
+
             // do we need to put in place dummy class names for missing values?
             if( iClass >= nClassCount )
             {
@@ -227,13 +227,13 @@ char **PCIDSK2Band::GetCategoryNames()
 
             papszCategoryNames[iClass] = CPLStrdup(osName);
         }
-        
+
         if( nClassCount == 0 )
             return GDALPamRasterBand::GetCategoryNames();
-        else
-            return papszCategoryNames;
+
+        return papszCategoryNames;
     }
-    catch( PCIDSKException ex )
+    catch( const PCIDSKException& ex )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", ex.what() );
@@ -253,7 +253,7 @@ bool PCIDSK2Band::CheckForColorTable()
 
     bCheckedForColorTable = true;
 
-    try 
+    try
     {
 /* -------------------------------------------------------------------- */
 /*      Try to find an appropriate PCT segment to use.                  */
@@ -263,44 +263,46 @@ bool PCIDSK2Band::CheckForColorTable()
 
         // If there is no metadata, assume a single PCT in a file with only
         // one raster band must be intended for it.
-        if( osDefaultPCT.size() == 0 
-            && poDS != NULL 
+        if( osDefaultPCT.size() == 0
+            && poDS != NULL
             && poDS->GetRasterCount() == 1 )
         {
             poPCTSeg = poFile->GetSegment( SEG_PCT, "" );
-            if( poPCTSeg != NULL 
-                && poFile->GetSegment( SEG_PCT, "", 
+            if( poPCTSeg != NULL
+                && poFile->GetSegment( SEG_PCT, "",
                                        poPCTSeg->GetSegmentNumber() ) != NULL )
                 poPCTSeg = NULL;
         }
         // Parse default PCT ref assuming an in file reference.
-        else if( osDefaultPCT.size() != 0 
+        else if( osDefaultPCT.size() != 0
                  && strstr(osDefaultPCT.c_str(),"PCT:") != NULL )
         {
-            poPCTSeg = poFile->GetSegment( 
+            poPCTSeg = poFile->GetSegment(
                 atoi(strstr(osDefaultPCT.c_str(),"PCT:") + 4) );
         }
 
         if( poPCTSeg != NULL )
         {
-            PCIDSK_PCT *poPCT = dynamic_cast<PCIDSK_PCT*>( poPCTSeg );
             poColorTable = new GDALColorTable();
-            int i;
             unsigned char abyPCT[768];
 
-            nPCTSegNumber = poPCTSeg->GetSegmentNumber();
-            
-            poPCT->ReadPCT( abyPCT );
-            
-            for( i = 0; i < 256; i++ )
+            PCIDSK_PCT *poPCT = dynamic_cast<PCIDSK_PCT*>( poPCTSeg );
+            if( poPCT )
             {
-                GDALColorEntry sEntry;
-                
-                sEntry.c1 = abyPCT[256 * 0 + i];
-                sEntry.c2 = abyPCT[256 * 1 + i];
-                sEntry.c3 = abyPCT[256 * 2 + i];
-                sEntry.c4 = 255;
-                poColorTable->SetColorEntry( i, &sEntry );
+                nPCTSegNumber = poPCTSeg->GetSegmentNumber();
+
+                poPCT->ReadPCT( abyPCT );
+
+                for( int i = 0; i < 256; i++ )
+                {
+                    GDALColorEntry sEntry;
+
+                    sEntry.c1 = abyPCT[256 * 0 + i];
+                    sEntry.c2 = abyPCT[256 * 1 + i];
+                    sEntry.c3 = abyPCT[256 * 2 + i];
+                    sEntry.c4 = 255;
+                    poColorTable->SetColorEntry( i, &sEntry );
+                }
             }
         }
 
@@ -309,34 +311,33 @@ bool PCIDSK2Band::CheckForColorTable()
 /*      Class_n color data from which to construct a color table.       */
 /* -------------------------------------------------------------------- */
         std::vector<std::string> aosMDKeys = poChannel->GetMetadataKeys();
-        size_t i;
-        
-        for( i=0; i < aosMDKeys.size(); i++ )
+
+        for( size_t i=0; i < aosMDKeys.size(); i++ )
         {
             CPLString osKey = aosMDKeys[i];
 
             // is this a "Class_n_name" keyword?
 
-            if( !EQUALN(osKey,"Class_",6) )
+            if( !STARTS_WITH_CI(osKey, "Class_") )
                 continue;
 
             if( !EQUAL(osKey.c_str() + osKey.size() - 6, "_Color") )
                 continue;
 
             // Ignore unreasonable class values.
-            int iClass = atoi(osKey.c_str() + 6);
+            const int iClass = atoi(osKey.c_str() + 6);
 
             if( iClass < 0 || iClass > 10000 )
                 continue;
 
             // Fetch and parse the RGB value "(RGB:red green blue)"
             CPLString osRGB  = poChannel->GetMetadataValue(osKey);
-            int nRed, nGreen, nBlue;
 
-            if( !EQUALN(osRGB,"(RGB:",5) )
+            if( !STARTS_WITH_CI(osRGB, "(RGB:") )
                 continue;
 
-            if( sscanf( osRGB.c_str() + 5, "%d %d %d", 
+            int nRed, nGreen, nBlue;
+            if( sscanf( osRGB.c_str() + 5, "%d %d %d",
                         &nRed, &nGreen, &nBlue ) != 3 )
                 continue;
 
@@ -357,7 +358,7 @@ bool PCIDSK2Band::CheckForColorTable()
             poColorTable->SetColorEntry( iClass, &sEntry );
         }
     }
-    catch( PCIDSKException ex )
+    catch( const PCIDSKException& ex )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", ex.what() );
@@ -378,9 +379,8 @@ GDALColorTable *PCIDSK2Band::GetColorTable()
 
     if( poColorTable )
         return poColorTable;
-    else
-        return GDALPamRasterBand::GetColorTable();
-            
+
+    return GDALPamRasterBand::GetColorTable();
 }
 
 /************************************************************************/
@@ -397,7 +397,7 @@ CPLErr PCIDSK2Band::SetColorTable( GDALColorTable *poCT )
     if( poFile == NULL )
         return CE_Failure;
 
-    try 
+    try
     {
 /* -------------------------------------------------------------------- */
 /*      Are we trying to delete the color table?                        */
@@ -421,12 +421,11 @@ CPLErr PCIDSK2Band::SetColorTable( GDALColorTable *poCT )
 /* -------------------------------------------------------------------- */
         if( nPCTSegNumber == -1 )
         {
-            nPCTSegNumber = poFile->CreateSegment( "PCTTable", 
-                                                   "Default Pseudo-Color Table", 
+            nPCTSegNumber = poFile->CreateSegment( "PCTTable",
+                                                   "Default Pseudo-Color Table",
                                                    SEG_PCT, 0 );
-            
+
             CPLString osRef;
-            
             osRef.Printf( "gdb:/{PCT:%d}", nPCTSegNumber );
             poChannel->SetMetadataValue( "DEFAULT_PCT_REF", osRef );
         }
@@ -434,12 +433,12 @@ CPLErr PCIDSK2Band::SetColorTable( GDALColorTable *poCT )
 /* -------------------------------------------------------------------- */
 /*      Write out the PCT.                                              */
 /* -------------------------------------------------------------------- */
-        unsigned char abyPCT[768];
-        int i, nColorCount = MIN(256,poCT->GetColorEntryCount());
+        const int nColorCount = MIN(256,poCT->GetColorEntryCount());
 
+        unsigned char abyPCT[768];
         memset( abyPCT, 0, 768 );
 
-        for( i = 0; i < nColorCount; i++ )
+        for( int i = 0; i < nColorCount; i++ )
         {
             GDALColorEntry sEntry;
 
@@ -449,10 +448,10 @@ CPLErr PCIDSK2Band::SetColorTable( GDALColorTable *poCT )
             abyPCT[256 * 2 + i] = (unsigned char) sEntry.c3;
         }
 
-        PCIDSK_PCT *poPCT = dynamic_cast<PCIDSK_PCT*>( 
+        PCIDSK_PCT *poPCT = dynamic_cast<PCIDSK_PCT*>(
             poFile->GetSegment( nPCTSegNumber ) );
-
-        poPCT->WritePCT( abyPCT );
+        if( poPCT )
+            poPCT->WritePCT( abyPCT );
 
         delete poColorTable;
         poColorTable = poCT->Clone();
@@ -461,13 +460,13 @@ CPLErr PCIDSK2Band::SetColorTable( GDALColorTable *poCT )
 /* -------------------------------------------------------------------- */
 /*      Trap exceptions.                                                */
 /* -------------------------------------------------------------------- */
-    catch( PCIDSKException ex )
+    catch( const PCIDSKException& ex )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", ex.what() );
         return CE_Failure;
     }
-    
+
     return CE_None;
 }
 
@@ -482,8 +481,8 @@ GDALColorInterp PCIDSK2Band::GetColorInterpretation()
 
     if( poColorTable != NULL )
         return GCI_PaletteIndex;
-    else
-        return GDALPamRasterBand::GetColorInterpretation();
+
+    return GDALPamRasterBand::GetColorInterpretation();
 }
 
 /************************************************************************/
@@ -506,8 +505,8 @@ void PCIDSK2Band::RefreshOverviewList()
 /*      Fetch overviews.                                                */
 /* -------------------------------------------------------------------- */
     for( int iOver = 0; iOver < poChannel->GetOverviewCount(); iOver++ )
-    {								       
-        apoOverviews.push_back( 
+    {
+        apoOverviews.push_back(
             new PCIDSK2Band( poChannel->GetOverview(iOver) ) );
     }
 }
@@ -519,7 +518,7 @@ void PCIDSK2Band::RefreshOverviewList()
 CPLErr PCIDSK2Band::IReadBlock( int iBlockX, int iBlockY, void *pData )
 
 {
-    try 
+    try
     {
         poChannel->ReadBlock( iBlockX + iBlockY * nBlocksPerRow,
                               pData );
@@ -527,7 +526,7 @@ CPLErr PCIDSK2Band::IReadBlock( int iBlockX, int iBlockY, void *pData )
         // Do we need to upsample 1bit to 8bit?
         if( poChannel->GetType() == CHN_BIT )
         {
-            GByte	*pabyData = (GByte *) pData;
+            GByte *pabyData = reinterpret_cast<GByte *>( pData );
 
             for( int ii = nBlockXSize * nBlockYSize - 1; ii >= 0; ii-- )
             {
@@ -540,7 +539,7 @@ CPLErr PCIDSK2Band::IReadBlock( int iBlockX, int iBlockY, void *pData )
 
         return CE_None;
     }
-    catch( PCIDSKException ex )
+    catch( const PCIDSKException& ex )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", ex.what() );
@@ -555,18 +554,19 @@ CPLErr PCIDSK2Band::IReadBlock( int iBlockX, int iBlockY, void *pData )
 CPLErr PCIDSK2Band::IWriteBlock( int iBlockX, int iBlockY, void *pData )
 
 {
-    try 
+    try
     {
         poChannel->WriteBlock( iBlockX + iBlockY * nBlocksPerRow,
                                pData );
-        return CE_None;
     }
-    catch( PCIDSKException ex )
+    catch( const PCIDSKException& ex )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", ex.what() );
         return CE_Failure;
     }
+
+    return CE_None;
 }
 
 /************************************************************************/
@@ -577,9 +577,9 @@ int PCIDSK2Band::GetOverviewCount()
 
 {
     if( apoOverviews.size() > 0 )
-        return (int) apoOverviews.size();
-    else
-        return GDALPamRasterBand::GetOverviewCount();
+        return static_cast<int>( apoOverviews.size() );
+
+    return GDALPamRasterBand::GetOverviewCount();
 }
 
 /************************************************************************/
@@ -589,17 +589,17 @@ int PCIDSK2Band::GetOverviewCount()
 GDALRasterBand *PCIDSK2Band::GetOverview(int iOverview)
 
 {
-    if( iOverview < 0 || iOverview >= (int) apoOverviews.size() )
+    if( iOverview < 0 || iOverview >= static_cast<int>( apoOverviews.size() ) )
         return GDALPamRasterBand::GetOverview( iOverview );
-    else
-        return apoOverviews[iOverview];
+
+    return apoOverviews[iOverview];
 }
 
 /************************************************************************/
 /*                            SetMetadata()                             */
 /************************************************************************/
 
-CPLErr PCIDSK2Band::SetMetadata( char **papszMD, 
+CPLErr PCIDSK2Band::SetMetadata( char **papszMD,
                                  const char *pszDomain )
 
 {
@@ -617,36 +617,35 @@ CPLErr PCIDSK2Band::SetMetadata( char **papszMD,
 
     try
     {
-        int iItem;
-
-        for( iItem = 0; papszMD && papszMD[iItem]; iItem++ )
+        for( int iItem = 0; papszMD && papszMD[iItem]; iItem++ )
         {
-            const char *pszItemValue;
             char *pszItemName = NULL;
 
-            pszItemValue = CPLParseNameValue( papszMD[iItem], &pszItemName);
+            const char *pszItemValue
+                = CPLParseNameValue( papszMD[iItem], &pszItemName);
             if( pszItemName != NULL )
             {
                 poChannel->SetMetadataValue( pszItemName, pszItemValue );
                 CPLFree( pszItemName );
             }
         }
-        return CE_None;
     }
-    catch( PCIDSKException ex )
+    catch( const PCIDSKException& ex )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", ex.what() );
         return CE_Failure;
     }
+
+    return CE_None;
 }
 
 /************************************************************************/
 /*                          SetMetadataItem()                           */
 /************************************************************************/
 
-CPLErr PCIDSK2Band::SetMetadataItem( const char *pszName, 
-                                     const char *pszValue, 
+CPLErr PCIDSK2Band::SetMetadataItem( const char *pszName,
+                                     const char *pszValue,
                                      const char *pszDomain )
 
 {
@@ -667,14 +666,15 @@ CPLErr PCIDSK2Band::SetMetadataItem( const char *pszName,
         if( !pszValue )
           pszValue = "";
         poChannel->SetMetadataValue( pszName, pszValue );
-        return CE_None;
     }
-    catch( PCIDSKException ex )
+   catch( const PCIDSKException& ex )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", ex.what() );
         return CE_Failure;
     }
+
+    return CE_None;
 }
 
 /************************************************************************/
@@ -692,7 +692,7 @@ char **PCIDSK2Band::GetMetadataDomainList()
 /*                          GetMetadataItem()                           */
 /************************************************************************/
 
-const char *PCIDSK2Band::GetMetadataItem( const char *pszName, 
+const char *PCIDSK2Band::GetMetadataItem( const char *pszName,
                                           const char *pszDomain )
 
 {
@@ -708,18 +708,18 @@ const char *PCIDSK2Band::GetMetadataItem( const char *pszName,
     try
     {
         osLastMDValue = poChannel->GetMetadataValue( pszName );
-
-        if( osLastMDValue == "" )
-            return NULL;
-        else
-            return osLastMDValue.c_str();
     }
-    catch( PCIDSKException ex )
+    catch( const PCIDSKException& ex )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", ex.what() );
         return NULL;
     }
+
+    if( osLastMDValue == "" )
+        return NULL;
+
+    return osLastMDValue.c_str();
 }
 
 /************************************************************************/
@@ -747,20 +747,19 @@ char **PCIDSK2Band::GetMetadata( const char *pszDomain )
     try
     {
         std::vector<std::string> aosKeys = poChannel->GetMetadataKeys();
-        unsigned int i;
-    
-        for( i = 0; i < aosKeys.size(); i++ )
+
+        for( unsigned int i = 0; i < aosKeys.size(); i++ )
         {
             if( aosKeys[i].c_str()[0] == '_' )
                 continue;
 
             papszLastMDListValue =
                 CSLSetNameValue( papszLastMDListValue,
-                                 aosKeys[i].c_str(), 
+                                 aosKeys[i].c_str(),
                                  poChannel->GetMetadataValue(aosKeys[i]).c_str() );
         }
     }
-    catch( PCIDSKException ex )
+    catch( const PCIDSKException& ex )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", ex.what() );
@@ -780,16 +779,20 @@ char **PCIDSK2Band::GetMetadata( const char *pszDomain )
 /*                           PCIDSK2Dataset()                            */
 /************************************************************************/
 
-PCIDSK2Dataset::PCIDSK2Dataset()
-{
-    poFile = NULL;
-    papszLastMDListValue = NULL;
-}
+PCIDSK2Dataset::PCIDSK2Dataset() :
+    papszLastMDListValue(NULL),
+    poFile(NULL)
+{}
 
 /************************************************************************/
 /*                            ~PCIDSK2Dataset()                          */
 /************************************************************************/
 
+// FIXME? is an exception can really be thrown in the destructor, then it is very dangerous !
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable : 4702 )  /*  unreachable code */
+#endif
 PCIDSK2Dataset::~PCIDSK2Dataset()
 {
     FlushCache();
@@ -801,26 +804,29 @@ PCIDSK2Dataset::~PCIDSK2Dataset()
     }
 
     try {
-        delete poFile;
-        poFile = NULL;
+        if( poFile != NULL)
+            delete poFile;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Trap exceptions.                                                */
 /* -------------------------------------------------------------------- */
-    catch( PCIDSKException ex )
+    catch( const PCIDSKException& ex )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", ex.what() );
     }
     catch( ... )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "PCIDSK SDK Failure in Close(), unexpected exception." );
     }
 
     CSLDestroy( papszLastMDListValue );
 }
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
 
 /************************************************************************/
 /*                            GetFileList()                             */
@@ -832,7 +838,7 @@ char **PCIDSK2Dataset::GetFileList()
     char **papszFileList = GDALPamDataset::GetFileList();
     CPLString osBaseDir = CPLGetPath( GetDescription() );
 
-    try 
+    try
     {
         for( int nChan = 1; nChan <= poFile->GetChannels(); nChan++ )
         {
@@ -841,21 +847,21 @@ char **PCIDSK2Dataset::GetFileList()
             uint64 image_offset, pixel_offset, line_offset;
             bool little_endian;
 
-            poChannel->GetChanInfo( osChanFilename, image_offset, 
+            poChannel->GetChanInfo( osChanFilename, image_offset,
                                     pixel_offset, line_offset, little_endian );
 
             if( osChanFilename != "" )
             {
-                papszFileList = 
-                    CSLAddString( papszFileList, 
-                                  CPLProjectRelativeFilename( osBaseDir, 
+                papszFileList =
+                    CSLAddString( papszFileList,
+                                  CPLProjectRelativeFilename( osBaseDir,
                                                               osChanFilename ) );
             }
         }
-    
+
         return papszFileList;
     }
-    catch( PCIDSKException ex )
+    catch( const PCIDSKException& ex )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", ex.what() );
@@ -876,11 +882,11 @@ void PCIDSK2Dataset::ProcessRPC()
     PCIDSKSegment *poSeg = poFile->GetSegment( SEG_BIN, "" );
     PCIDSKRPCSegment *poRPCSeg = NULL;
 
-    while( poSeg != NULL 
+    while( poSeg != NULL
            && (poRPCSeg = dynamic_cast<PCIDSKRPCSegment*>( poSeg )) == NULL )
-			   
+
     {
-        poSeg = poFile->GetSegment( SEG_BIN, "", 
+        poSeg = poFile->GetSegment( SEG_BIN, "",
                                     poSeg->GetSegmentNumber() );
     }
 
@@ -897,9 +903,9 @@ void PCIDSK2Dataset::ProcessRPC()
         double dfLatOffset, dfLatScale,
             dfLongOffset, dfLongScale,
             dfHeightOffset, dfHeightScale;
-		
-        poRPCSeg->GetRPCTranslationCoeffs( 
-            dfLongOffset, dfLongScale, 
+
+        poRPCSeg->GetRPCTranslationCoeffs(
+            dfLongOffset, dfLongScale,
             dfLatOffset, dfLatScale,
             dfHeightOffset, dfHeightScale,
             dfSampOffset, dfSampScale,
@@ -935,13 +941,9 @@ void PCIDSK2Dataset::ProcessRPC()
         osValue.Printf( "%.16g", dfHeightScale );
         GDALPamDataset::SetMetadataItem( "HEIGHT_SCALE", osValue, "RPC" );
 
-        CPLString osCoefList;
-        std::vector<double> adfCoef;
-        int i;
-
-        if( poRPCSeg->GetXNumerator().size() != 20 
-            || poRPCSeg->GetXDenominator().size() != 20 
-            || poRPCSeg->GetYNumerator().size() != 20 
+        if( poRPCSeg->GetXNumerator().size() != 20
+            || poRPCSeg->GetXDenominator().size() != 20
+            || poRPCSeg->GetYNumerator().size() != 20
             || poRPCSeg->GetYDenominator().size() != 20 )
         {
             GDALPamDataset::SetMetadata( NULL, "RPC" );
@@ -950,9 +952,9 @@ void PCIDSK2Dataset::ProcessRPC()
             return;
         }
 
-        adfCoef = poRPCSeg->GetYNumerator();
-        osCoefList = "";
-        for( i = 0; i < 20; i++ )
+        std::vector<double> adfCoef = poRPCSeg->GetYNumerator();
+        CPLString osCoefList = "";
+        for( int i = 0; i < 20; i++ )
         {
             osValue.Printf( "%.16g ", adfCoef[i] );
             osCoefList += osValue;
@@ -961,7 +963,7 @@ void PCIDSK2Dataset::ProcessRPC()
 
         adfCoef = poRPCSeg->GetYDenominator();
         osCoefList = "";
-        for( i = 0; i < 20; i++ )
+        for( int i = 0; i < 20; i++ )
         {
             osValue.Printf( "%.16g ", adfCoef[i] );
             osCoefList += osValue;
@@ -970,7 +972,7 @@ void PCIDSK2Dataset::ProcessRPC()
 
         adfCoef = poRPCSeg->GetXNumerator();
         osCoefList = "";
-        for( i = 0; i < 20; i++ )
+        for( int i = 0; i < 20; i++ )
         {
             osValue.Printf( "%.16g ", adfCoef[i] );
             osCoefList += osValue;
@@ -979,14 +981,14 @@ void PCIDSK2Dataset::ProcessRPC()
 
         adfCoef = poRPCSeg->GetXDenominator();
         osCoefList = "";
-        for( i = 0; i < 20; i++ )
+        for( int i = 0; i < 20; i++ )
         {
             osValue.Printf( "%.16g ", adfCoef[i] );
             osCoefList += osValue;
         }
         GDALPamDataset::SetMetadataItem( "SAMP_DEN_COEFF", osCoefList, "RPC" );
     }
-    catch( PCIDSKException ex )
+    catch( const PCIDSKException& ex )
     {
         GDALPamDataset::SetMetadata( NULL, "RPC" );
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -1008,7 +1010,7 @@ void PCIDSK2Dataset::FlushCache()
         try {
             poFile->Synchronize();
         }
-        catch( PCIDSKException ex )
+        catch( const PCIDSKException& ex )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "%s", ex.what() );
@@ -1020,7 +1022,7 @@ void PCIDSK2Dataset::FlushCache()
 /*                            SetMetadata()                             */
 /************************************************************************/
 
-CPLErr PCIDSK2Dataset::SetMetadata( char **papszMD, 
+CPLErr PCIDSK2Dataset::SetMetadata( char **papszMD,
                                     const char *pszDomain )
 
 {
@@ -1038,36 +1040,34 @@ CPLErr PCIDSK2Dataset::SetMetadata( char **papszMD,
 
     try
     {
-        int iItem;
-
-        for( iItem = 0; papszMD && papszMD[iItem]; iItem++ )
+        for( int iItem = 0; papszMD && papszMD[iItem]; iItem++ )
         {
-            const char *pszItemValue;
             char *pszItemName = NULL;
-
-            pszItemValue = CPLParseNameValue( papszMD[iItem], &pszItemName);
+            const char *pszItemValue
+                = CPLParseNameValue( papszMD[iItem], &pszItemName);
             if( pszItemName != NULL )
             {
                 poFile->SetMetadataValue( pszItemName, pszItemValue );
                 CPLFree( pszItemName );
             }
         }
-        return CE_None;
     }
-    catch( PCIDSKException ex )
+    catch( const PCIDSKException& ex )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", ex.what() );
         return CE_Failure;
     }
+
+    return CE_None;
 }
 
 /************************************************************************/
 /*                          SetMetadataItem()                           */
 /************************************************************************/
 
-CPLErr PCIDSK2Dataset::SetMetadataItem( const char *pszName, 
-                                        const char *pszValue, 
+CPLErr PCIDSK2Dataset::SetMetadataItem( const char *pszName,
+                                        const char *pszValue,
                                         const char *pszDomain )
 
 {
@@ -1086,14 +1086,15 @@ CPLErr PCIDSK2Dataset::SetMetadataItem( const char *pszName,
     try
     {
         poFile->SetMetadataValue( pszName, pszValue );
-        return CE_None;
     }
-    catch( PCIDSKException ex )
+    catch( const PCIDSKException& ex )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", ex.what() );
         return CE_Failure;
     }
+
+    return CE_None;
 }
 
 /************************************************************************/
@@ -1111,7 +1112,7 @@ char **PCIDSK2Dataset::GetMetadataDomainList()
 /*                          GetMetadataItem()                           */
 /************************************************************************/
 
-const char *PCIDSK2Dataset::GetMetadataItem( const char *pszName, 
+const char *PCIDSK2Dataset::GetMetadataItem( const char *pszName,
                                              const char *pszDomain )
 
 {
@@ -1127,18 +1128,19 @@ const char *PCIDSK2Dataset::GetMetadataItem( const char *pszName,
     try
     {
         osLastMDValue = poFile->GetMetadataValue( pszName );
-
-        if( osLastMDValue == "" )
-            return NULL;
-        else
-            return osLastMDValue.c_str();
     }
-    catch( PCIDSKException ex )
+    catch( const PCIDSKException& ex )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", ex.what() );
         return NULL;
     }
+
+
+    if( osLastMDValue == "" )
+        return NULL;
+
+    return osLastMDValue.c_str();
 }
 
 /************************************************************************/
@@ -1166,20 +1168,19 @@ char **PCIDSK2Dataset::GetMetadata( const char *pszDomain )
     try
     {
         std::vector<std::string> aosKeys = poFile->GetMetadataKeys();
-        unsigned int i;
-    
-        for( i = 0; i < aosKeys.size(); i++ )
+
+        for( unsigned int i = 0; i < aosKeys.size(); i++ )
         {
             if( aosKeys[i].c_str()[0] == '_' )
                 continue;
 
             papszLastMDListValue =
                 CSLSetNameValue( papszLastMDListValue,
-                                 aosKeys[i].c_str(), 
+                                 aosKeys[i].c_str(),
                                  poFile->GetMetadataValue(aosKeys[i]).c_str() );
         }
     }
-    catch( PCIDSKException ex )
+    catch( const PCIDSKException& ex )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", ex.what() );
@@ -1201,34 +1202,32 @@ CPLErr PCIDSK2Dataset::SetGeoTransform( double * padfTransform )
         PCIDSKSegment *poGeoSeg = poFile->GetSegment(1);
         poGeoref = dynamic_cast<PCIDSKGeoref*>( poGeoSeg );
     }
-    catch( PCIDSKException ex )
+    catch( const PCIDSKException& )
     {
         // I should really check whether this is an expected issue.
     }
-        
+
     if( poGeoref == NULL )
         return GDALPamDataset::SetGeoTransform( padfTransform );
-    else
-    {
-        try
-        {
-            poGeoref->WriteSimple( poGeoref->GetGeosys(), 
-                                   padfTransform[0], 
-                                   padfTransform[1],
-                                   padfTransform[2],
-                                   padfTransform[3],
-                                   padfTransform[4],
-                                   padfTransform[5] );
-        }
-        catch( PCIDSKException ex )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "%s", ex.what() );
-            return CE_Failure;
-        }
 
-        return CE_None;
+    try
+    {
+        poGeoref->WriteSimple( poGeoref->GetGeosys(),
+                               padfTransform[0],
+                               padfTransform[1],
+                               padfTransform[2],
+                               padfTransform[3],
+                               padfTransform[4],
+                               padfTransform[5] );
     }
+    catch( const PCIDSKException& ex )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "%s", ex.what() );
+        return CE_Failure;
+    }
+
+    return CE_None;
 }
 
 /************************************************************************/
@@ -1243,23 +1242,23 @@ CPLErr PCIDSK2Dataset::GetGeoTransform( double * padfTransform )
         PCIDSKSegment *poGeoSeg = poFile->GetSegment(1);
         poGeoref = dynamic_cast<PCIDSKGeoref*>( poGeoSeg );
     }
-    catch( PCIDSKException ex )
+    catch( const PCIDSKException& )
     {
         // I should really check whether this is an expected issue.
     }
-        
+
     if( poGeoref != NULL )
     {
         try
         {
-            poGeoref->GetTransform( padfTransform[0], 
+            poGeoref->GetTransform( padfTransform[0],
                                     padfTransform[1],
                                     padfTransform[2],
                                     padfTransform[3],
                                     padfTransform[4],
                                     padfTransform[5] );
         }
-        catch( PCIDSKException ex )
+        catch( const PCIDSKException& ex )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "%s", ex.what() );
@@ -1279,11 +1278,11 @@ CPLErr PCIDSK2Dataset::GetGeoTransform( double * padfTransform )
 /* -------------------------------------------------------------------- */
 /*      Check for worldfile if we have no other georeferencing.         */
 /* -------------------------------------------------------------------- */
-    if( GDALReadWorldFile( GetDescription(), "pxw", 
+    if( GDALReadWorldFile( GetDescription(), "pxw",
                            padfTransform ) )
         return CE_None;
-    else
-        return GDALPamDataset::GetGeoTransform( padfTransform );
+
+    return GDALPamDataset::GetGeoTransform( padfTransform );
 }
 
 /************************************************************************/
@@ -1302,75 +1301,75 @@ CPLErr PCIDSK2Dataset::SetProjection( const char *pszWKT )
         PCIDSKSegment *poGeoSeg = poFile->GetSegment(1);
         poGeoref = dynamic_cast<PCIDSKGeoref*>( poGeoSeg );
     }
-    catch( PCIDSKException ex )
+    catch( const PCIDSKException& )
     {
         // I should really check whether this is an expected issue.
     }
-        
+
     if( poGeoref == NULL )
     {
         return GDALPamDataset::SetProjection( pszWKT );
     }
-    else
-    {
-        char *pszGeosys = NULL;
-        char *pszUnits = NULL;
-        double *padfPrjParams = NULL;
 
-        OGRSpatialReference oSRS;
-        char *pszWKTWork = (char *) pszWKT;
+    char *pszGeosys = NULL;
+    char *pszUnits = NULL;
+    double *padfPrjParams = NULL;
 
-        if( oSRS.importFromWkt( &pszWKTWork ) == OGRERR_NONE
-            && oSRS.exportToPCI( &pszGeosys, &pszUnits, 
-                                 &padfPrjParams ) == OGRERR_NONE )
-        {
-            try
-            {
-                double adfGT[6];
-                std::vector<double> adfPCIParameters;
-                unsigned int i;
-
-                poGeoref->GetTransform( adfGT[0], adfGT[1], adfGT[2],
-                                        adfGT[3], adfGT[4], adfGT[5] );
-
-                poGeoref->WriteSimple( pszGeosys, 
-                                       adfGT[0], adfGT[1], adfGT[2],
-                                       adfGT[3], adfGT[4], adfGT[5] );
-
-                for( i = 0; i < 17; i++ )
-                    adfPCIParameters.push_back( padfPrjParams[i] );
-
-                if( EQUALN(pszUnits,"FOOT",4) )
-                    adfPCIParameters.push_back( 
-                        (double)(int) PCIDSK::UNIT_US_FOOT );
-                else if( EQUALN(pszUnits,"INTL FOOT",9) )
-                    adfPCIParameters.push_back( 
-                        (double)(int) PCIDSK::UNIT_INTL_FOOT );
-                else if( EQUALN(pszUnits,"DEGREE",6) )
-                    adfPCIParameters.push_back( 
-                        (double)(int) PCIDSK::UNIT_DEGREE );
-                else 
-                    adfPCIParameters.push_back( 
-                        (double)(int) PCIDSK::UNIT_METER );
-
-                poGeoref->WriteParameters( adfPCIParameters );
-            }
-            catch( PCIDSKException ex )
-            {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                          "%s", ex.what() );
-                return CE_Failure;
-            }
+    OGRSpatialReference oSRS;
+    char *pszWKTWork = const_cast<char *>( pszWKT );
 
-            CPLFree( pszGeosys );
-            CPLFree( pszUnits );
-            CPLFree( padfPrjParams );
+    if( ! (oSRS.importFromWkt( &pszWKTWork ) == OGRERR_NONE
+        && oSRS.exportToPCI( &pszGeosys, &pszUnits,
+                             &padfPrjParams ) == OGRERR_NONE ) )
+    {
+        return GDALPamDataset::SetProjection( pszWKT );
+    }
 
-            return CE_None;
-        }
+    try
+    {
+        double adfGT[6];
+        poGeoref->GetTransform( adfGT[0], adfGT[1], adfGT[2],
+                                adfGT[3], adfGT[4], adfGT[5] );
+
+        poGeoref->WriteSimple( pszGeosys,
+                               adfGT[0], adfGT[1], adfGT[2],
+                               adfGT[3], adfGT[4], adfGT[5] );
+
+        std::vector<double> adfPCIParameters;
+        for( unsigned int i = 0; i < 17; i++ )
+            adfPCIParameters.push_back( padfPrjParams[i] );
+
+        if( STARTS_WITH_CI(pszUnits, "FOOT") )
+                adfPCIParameters.push_back(
+                    static_cast<double>( static_cast<int>(
+                        PCIDSK::UNIT_US_FOOT ) ) );
+        else if( EQUALN(pszUnits, "INTL FOOT", 9) )
+            adfPCIParameters.push_back(
+                static_cast<double>( static_cast<int>(
+                    PCIDSK::UNIT_INTL_FOOT ) ) );
+        else if( EQUALN(pszUnits,"DEGREE",6) )
+            adfPCIParameters.push_back(
+                static_cast<double>( static_cast<int>(
+                    PCIDSK::UNIT_DEGREE ) ) );
         else
-            return GDALPamDataset::SetProjection( pszWKT );
+            adfPCIParameters.push_back(
+                static_cast<double>( static_cast<int>(
+                    PCIDSK::UNIT_METER ) ) );
+
+        poGeoref->WriteParameters( adfPCIParameters );
     }
+    catch( const PCIDSKException& ex )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "%s", ex.what() );
+        return CE_Failure;
+    }
+
+    CPLFree( pszGeosys );
+    CPLFree( pszUnits );
+    CPLFree( padfPrjParams );
+
+    return CE_None;
 }
 
 /************************************************************************/
@@ -1389,61 +1388,57 @@ const char *PCIDSK2Dataset::GetProjectionRef()
         PCIDSKSegment *poGeoSeg = poFile->GetSegment(1);
         poGeoref = dynamic_cast<PCIDSKGeoref*>( poGeoSeg );
     }
-    catch( PCIDSKException ex )
+    catch( const PCIDSKException& )
     {
         // I should really check whether this is an expected issue.
     }
-        
+
     if( poGeoref == NULL )
     {
         osSRS = GDALPamDataset::GetProjectionRef();
+        return osSRS.c_str();
     }
-    else
+
+    CPLString osGeosys;
+    const char *pszUnits = NULL;
+
+    std::vector<double> adfParameters;
+    adfParameters.resize(18);
+
+    try
     {
-        CPLString osGeosys;
-        const char *pszUnits = NULL;
-        OGRSpatialReference oSRS;
-        char *pszWKT = NULL;
-        std::vector<double> adfParameters;
+        osGeosys = poGeoref->GetGeosys();
+        adfParameters = poGeoref->GetParameters();
+        const UnitCode code
+            = static_cast<UnitCode>( static_cast<int>( adfParameters[16] ) );
 
-        adfParameters.resize(18);
-        try
-        {
-            if( poGeoref )
-            {
-                osGeosys = poGeoref->GetGeosys();
-                adfParameters = poGeoref->GetParameters();
-                if( ((UnitCode)(int)adfParameters[16]) 
-                    == PCIDSK::UNIT_DEGREE )
-                    pszUnits = "DEGREE";
-                else if( ((UnitCode)(int)adfParameters[16]) 
-                         == PCIDSK::UNIT_METER )
-                    pszUnits = "METER";
-                else if( ((UnitCode)(int)adfParameters[16]) 
-                         == PCIDSK::UNIT_US_FOOT )
-                    pszUnits = "FOOT";
-                else if( ((UnitCode)(int)adfParameters[16]) 
-                         == PCIDSK::UNIT_INTL_FOOT )
-                    pszUnits = "INTL FOOT";
-            }
-        }
-        catch( PCIDSKException ex )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "%s", ex.what() );
-        }
-        
-        if( oSRS.importFromPCI( osGeosys, pszUnits, 
-                                &(adfParameters[0]) ) == OGRERR_NONE )
-        {
-            oSRS.exportToWkt( &pszWKT );
-            osSRS = pszWKT;
-            CPLFree( pszWKT );
-        }
-        else
-        {
-            osSRS = GDALPamDataset::GetProjectionRef();
-        }
+        if( code == PCIDSK::UNIT_DEGREE )
+            pszUnits = "DEGREE";
+        else if( code == PCIDSK::UNIT_METER )
+            pszUnits = "METER";
+        else if( code == PCIDSK::UNIT_US_FOOT )
+            pszUnits = "FOOT";
+        else if( code == PCIDSK::UNIT_INTL_FOOT )
+            pszUnits = "INTL FOOT";
+    }
+    catch( const PCIDSKException& ex )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "%s", ex.what() );
+    }
+
+    OGRSpatialReference oSRS;
+    if( oSRS.importFromPCI( osGeosys, pszUnits,
+                            &(adfParameters[0]) ) == OGRERR_NONE )
+    {
+        char *pszWKT = NULL;
+        oSRS.exportToWkt( &pszWKT );
+        osSRS = pszWKT;
+        CPLFree( pszWKT );
+    }
+    else
+    {
+        osSRS = GDALPamDataset::GetProjectionRef();
     }
 
     return osSRS.c_str();
@@ -1453,10 +1448,10 @@ const char *PCIDSK2Dataset::GetProjectionRef()
 /*                          IBuildOverviews()                           */
 /************************************************************************/
 
-CPLErr PCIDSK2Dataset::IBuildOverviews( const char *pszResampling, 
+CPLErr PCIDSK2Dataset::IBuildOverviews( const char *pszResampling,
                                         int nOverviews, int *panOverviewList,
-                                        int nListBands, int *panBandList, 
-                                        GDALProgressFunc pfnProgress, 
+                                        int nListBands, int *panBandList,
+                                        GDALProgressFunc pfnProgress,
                                         void *pProgressData )
 
 {
@@ -1478,28 +1473,26 @@ CPLErr PCIDSK2Dataset::IBuildOverviews( const char *pszResampling,
 /*      which are new.  We assume that band 1 of the file is            */
 /*      representative.                                                 */
 /* -------------------------------------------------------------------- */
-    int   i, nNewOverviews, *panNewOverviewList = NULL;
-    PCIDSK2Band *poBand = (PCIDSK2Band*) GetRasterBand( panBandList[0] );
+    PCIDSK2Band *poBand = reinterpret_cast<PCIDSK2Band*>(
+        GetRasterBand( panBandList[0] ) );
 
-    nNewOverviews = 0;
-    panNewOverviewList = (int *) CPLCalloc(sizeof(int),nOverviews);
-    for( i = 0; i < nOverviews && poBand != NULL; i++ )
+    int nNewOverviews = 0;
+    int *panNewOverviewList = reinterpret_cast<int *>(
+        CPLCalloc( sizeof( int ), nOverviews ) );
+    for( int i = 0; i < nOverviews && poBand != NULL; i++ )
     {
-        int   j;
-
-        for( j = 0; j < poBand->GetOverviewCount(); j++ )
+        for( int j = 0; j < poBand->GetOverviewCount(); j++ )
         {
-            int    nOvFactor;
             GDALRasterBand * poOverview = poBand->GetOverview( j );
- 
-            nOvFactor = GDALComputeOvFactor(poOverview->GetXSize(),
-                                            poBand->GetXSize(),
-                                            poOverview->GetYSize(),
-                                            poBand->GetYSize());
-
-            if( nOvFactor == panOverviewList[i] 
-                || nOvFactor == GDALOvLevelAdjust2( panOverviewList[i], 
-                                                    poBand->GetXSize(), 
+
+            int nOvFactor = GDALComputeOvFactor(poOverview->GetXSize(),
+                                                poBand->GetXSize(),
+                                                poOverview->GetYSize(),
+                                                poBand->GetYSize());
+
+            if( nOvFactor == panOverviewList[i]
+                || nOvFactor == GDALOvLevelAdjust2( panOverviewList[i],
+                                                    poBand->GetXSize(),
                                                     poBand->GetYSize() ) )
                 panOverviewList[i] *= -1;
         }
@@ -1513,15 +1506,15 @@ CPLErr PCIDSK2Dataset::IBuildOverviews( const char *pszResampling,
 /* -------------------------------------------------------------------- */
 /*      Create the overviews that are missing.                          */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < nNewOverviews; i++ )
+    for( int i = 0; i < nNewOverviews; i++ )
     {
-        try 
+        try
         {
             // conveniently our resampling values mostly match PCIDSK.
-            poFile->CreateOverviews( nListBands, panBandList, 
+            poFile->CreateOverviews( nListBands, panBandList,
                                      panNewOverviewList[i], pszResampling );
         }
-        catch( PCIDSKException ex )
+        catch( const PCIDSKException& ex )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "%s", ex.what() );
@@ -1533,46 +1526,43 @@ CPLErr PCIDSK2Dataset::IBuildOverviews( const char *pszResampling,
     CPLFree( panNewOverviewList );
     panNewOverviewList = NULL;
 
-    int iBand;
-    for( iBand = 0; iBand < nListBands; iBand++ )
+    for( int iBand = 0; iBand < nListBands; iBand++ )
     {
-        poBand = (PCIDSK2Band *) GetRasterBand( panBandList[iBand] );
-        ((PCIDSK2Band *) poBand)->RefreshOverviewList();
+        poBand = reinterpret_cast<PCIDSK2Band *>(
+            GetRasterBand( panBandList[iBand] ) );
+        reinterpret_cast<PCIDSK2Band *>( poBand )->RefreshOverviewList();
     }
 
 /* -------------------------------------------------------------------- */
 /*      Actually generate the overview imagery.                         */
 /* -------------------------------------------------------------------- */
-    GDALRasterBand **papoOverviewBands;
     CPLErr eErr = CE_None;
     std::vector<int> anRegenLevels;
 
-    papoOverviewBands = (GDALRasterBand **) 
-        CPLCalloc(sizeof(void*),nOverviews);
+    GDALRasterBand **papoOverviewBands = reinterpret_cast<GDALRasterBand **>(
+        CPLCalloc( sizeof(void*), nOverviews ) );
 
-    for( iBand = 0; iBand < nListBands && eErr == CE_None; iBand++ )
+    for( int iBand = 0; iBand < nListBands && eErr == CE_None; iBand++ )
     {
         nNewOverviews = 0;
 
-        poBand = (PCIDSK2Band*) GetRasterBand( panBandList[iBand] );
+        poBand = reinterpret_cast<PCIDSK2Band *>(
+            GetRasterBand( panBandList[iBand] ) );
 
-        for( i = 0; i < nOverviews && poBand != NULL; i++ )
+        for( int i = 0; i < nOverviews && poBand != NULL; i++ )
         {
-            int   j;
-            
-            for( j = 0; j < poBand->GetOverviewCount(); j++ )
+            for( int j = 0; j < poBand->GetOverviewCount(); j++ )
             {
-                int    nOvFactor;
                 GDALRasterBand * poOverview = poBand->GetOverview( j );
 
-                nOvFactor = GDALComputeOvFactor(poOverview->GetXSize(),
-                                            poBand->GetXSize(),
-                                            poOverview->GetYSize(),
-                                            poBand->GetYSize());
+                int nOvFactor = GDALComputeOvFactor(poOverview->GetXSize(),
+                                                    poBand->GetXSize(),
+                                                    poOverview->GetYSize(),
+                                                    poBand->GetYSize());
 
-                if( nOvFactor == panOverviewList[i] 
-                    || nOvFactor == GDALOvLevelAdjust2( panOverviewList[i], 
-                                                       poBand->GetXSize(), 
+                if( nOvFactor == panOverviewList[i]
+                    || nOvFactor == GDALOvLevelAdjust2( panOverviewList[i],
+                                                       poBand->GetXSize(),
                                                        poBand->GetYSize() ) )
                 {
                     papoOverviewBands[nNewOverviews++] = poOverview;
@@ -1584,15 +1574,15 @@ CPLErr PCIDSK2Dataset::IBuildOverviews( const char *pszResampling,
 
         if( nNewOverviews > 0 )
         {
-            eErr = GDALRegenerateOverviews( (GDALRasterBandH) poBand, 
-                                            nNewOverviews, 
-                                            (GDALRasterBandH*)papoOverviewBands,
-                                            pszResampling, 
+            eErr = GDALRegenerateOverviews( (GDALRasterBandH) poBand,
+                                            nNewOverviews,
+                                            reinterpret_cast<GDALRasterBandH*>( papoOverviewBands ),
+                                            pszResampling,
                                             pfnProgress, pProgressData );
 
             // Mark the regenerated overviews as valid.
-            for( i = 0; i < (int) anRegenLevels.size(); i++ )
-                poBand->poChannel->SetOverviewValidity( anRegenLevels[i], 
+            for( int i = 0; i < static_cast<int>( anRegenLevels.size() ); i++ )
+                poBand->poChannel->SetOverviewValidity( anRegenLevels[i],
                                                         true );
         }
     }
@@ -1612,28 +1602,28 @@ GDALDataType PCIDSK2Dataset::PCIDSKTypeToGDAL( eChanType eType )
     {
       case CHN_8U:
         return GDT_Byte;
-        
+
       case CHN_16U:
         return GDT_UInt16;
-        
+
       case CHN_16S:
         return GDT_Int16;
-        
+
       case CHN_32R:
         return GDT_Float32;
 
       case CHN_BIT:
         return GDT_Byte;
-        
+
       case CHN_C16U:
         return GDT_CInt16;
-      
+
       case CHN_C16S:
         return GDT_CInt16;
-      
+
       case CHN_C32R:
         return GDT_CFloat32;
-        
+
       default:
         return GDT_Unknown;
     }
@@ -1645,11 +1635,11 @@ GDALDataType PCIDSK2Dataset::PCIDSKTypeToGDAL( eChanType eType )
 
 int PCIDSK2Dataset::Identify( GDALOpenInfo * poOpenInfo )
 {
-    if( poOpenInfo->nHeaderBytes < 512 
-        || !EQUALN((const char *) poOpenInfo->pabyHeader, "PCIDSK  ", 8) )
+    if( poOpenInfo->nHeaderBytes < 512
+        || !STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "PCIDSK  ") )
         return FALSE;
-    else
-        return TRUE;
+
+    return TRUE;
 }
 
 /************************************************************************/
@@ -1665,8 +1655,8 @@ GDALDataset *PCIDSK2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Try opening the file.                                           */
 /* -------------------------------------------------------------------- */
     try {
-        PCIDSKFile *poFile = 
-            PCIDSK::Open( poOpenInfo->pszFilename, 
+        PCIDSKFile *poFile =
+            PCIDSK::Open( poOpenInfo->pszFilename,
                           poOpenInfo->eAccess == GA_ReadOnly ? "r" : "r+",
                           PCIDSK2GetInterfaces() );
         if( poFile == NULL )
@@ -1709,7 +1699,7 @@ GDALDataset *PCIDSK2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Trap exceptions.                                                */
 /* -------------------------------------------------------------------- */
-    catch( PCIDSKException ex )
+    catch( const PCIDSKException& ex )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", ex.what() );
@@ -1730,24 +1720,22 @@ GDALDataset *PCIDSK2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /*      PCIDSKFile.                                                     */
 /************************************************************************/
 
-GDALDataset *PCIDSK2Dataset::LLOpen( const char *pszFilename, 
+GDALDataset *PCIDSK2Dataset::LLOpen( const char *pszFilename,
                                      PCIDSK::PCIDSKFile *poFile,
                                      GDALAccess eAccess,
                                      char** papszSiblingFiles )
 
 {
-    PCIDSK2Dataset   *poDS = NULL;
-    try {
+    PCIDSK2Dataset *poDS = new PCIDSK2Dataset();
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
+    poDS->poFile = poFile;
+    poDS->eAccess = eAccess;
+    poDS->nRasterXSize = poFile->GetWidth();
+    poDS->nRasterYSize = poFile->GetHeight();
 
-        poDS = new PCIDSK2Dataset();
-
-        poDS->poFile = poFile;
-        poDS->eAccess = eAccess;
-        poDS->nRasterXSize = poFile->GetWidth();
-        poDS->nRasterYSize = poFile->GetHeight();
+    try {
 
 /* -------------------------------------------------------------------- */
 /*      Are we specifically PIXEL or BAND interleaving?                 */
@@ -1756,18 +1744,16 @@ GDALDataset *PCIDSK2Dataset::LLOpen( const char *pszFilename,
 /*      this is tiled or what the on disk interleaving is.              */
 /* -------------------------------------------------------------------- */
         if( EQUAL(poFile->GetInterleaving().c_str(),"PIXEL") )
-            poDS->SetMetadataItem( "IMAGE_STRUCTURE", "PIXEL", 
+            poDS->SetMetadataItem( "IMAGE_STRUCTURE", "PIXEL",
                                    "IMAGE_STRUCTURE" );
         else if( EQUAL(poFile->GetInterleaving().c_str(),"BAND") )
-            poDS->SetMetadataItem( "IMAGE_STRUCTURE", "BAND", 
+            poDS->SetMetadataItem( "IMAGE_STRUCTURE", "BAND",
                                    "IMAGE_STRUCTURE" );
 
 /* -------------------------------------------------------------------- */
 /*      Create band objects.                                            */
 /* -------------------------------------------------------------------- */
-        int iBand;
-
-        for( iBand = 0; iBand < poFile->GetChannels(); iBand++ )
+        for( int iBand = 0; iBand < poFile->GetChannels(); iBand++ )
         {
             PCIDSKChannel* poChannel = poFile->GetChannel( iBand + 1 );
             if (poChannel->GetBlockWidth() <= 0 ||
@@ -1785,20 +1771,21 @@ GDALDataset *PCIDSK2Dataset::LLOpen( const char *pszFilename,
 /* -------------------------------------------------------------------- */
         int nLastBitmapSegment = 0;
         PCIDSKSegment *poBitSeg;
-        
-        while( (poBitSeg = poFile->GetSegment( SEG_BIT, "", 
+
+        while( (poBitSeg = poFile->GetSegment( SEG_BIT, "",
                                                nLastBitmapSegment)) != NULL )
         {
-            PCIDSKChannel *poChannel = 
+            PCIDSKChannel *poChannel =
                 dynamic_cast<PCIDSKChannel*>( poBitSeg );
-            if (poChannel->GetBlockWidth() <= 0 ||
+            if (poChannel == NULL ||
+                poChannel->GetBlockWidth() <= 0 ||
                 poChannel->GetBlockHeight() <= 0)
             {
                 delete poDS;
                 return NULL;
             }
 
-            poDS->SetBand( poDS->GetRasterCount()+1, 
+            poDS->SetBand( poDS->GetRasterCount()+1,
                            new PCIDSK2Band( poChannel ) );
 
             nLastBitmapSegment = poBitSeg->GetSegmentNumber();
@@ -1807,13 +1794,16 @@ GDALDataset *PCIDSK2Dataset::LLOpen( const char *pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Create vector layers from vector segments.                      */
 /* -------------------------------------------------------------------- */
-        PCIDSK::PCIDSKSegment *segobj;
-        for( segobj = poFile->GetSegment( PCIDSK::SEG_VEC, "" );
+        PCIDSK::PCIDSKSegment *segobj
+            = poFile->GetSegment( PCIDSK::SEG_VEC, "" );
+        for( ;
              segobj != NULL;
              segobj = poFile->GetSegment( PCIDSK::SEG_VEC, "",
                                           segobj->GetSegmentNumber() ) )
         {
-            poDS->apoLayers.push_back( new OGRPCIDSKLayer( segobj, eAccess == GA_Update ) );
+            PCIDSK::PCIDSKVectorSegment* poVecSeg = dynamic_cast<PCIDSK::PCIDSKVectorSegment*>( segobj );
+            if( poVecSeg )
+                poDS->apoLayers.push_back( new OGRPCIDSKLayer( segobj, poVecSeg, eAccess == GA_Update ) );
         }
 
 /* -------------------------------------------------------------------- */
@@ -1831,21 +1821,21 @@ GDALDataset *PCIDSK2Dataset::LLOpen( const char *pszFilename,
 /*      Open overviews.                                                 */
 /* -------------------------------------------------------------------- */
         poDS->oOvManager.Initialize( poDS, pszFilename, papszSiblingFiles );
-        
+
         return( poDS );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Trap exceptions.                                                */
 /* -------------------------------------------------------------------- */
-    catch( PCIDSKException ex )
+    catch( const PCIDSKException& ex )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", ex.what() );
     }
     catch( ... )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "PCIDSK SDK Failure in Open(), unexpected exception." );
     }
 
@@ -1867,8 +1857,6 @@ GDALDataset *PCIDSK2Dataset::Create( const char * pszFilename,
                                      char **papszParmList )
 
 {
-    PCIDSKFile *poFile;
-
 /* -------------------------------------------------------------------- */
 /*      Prepare channel type list.                                      */
 /* -------------------------------------------------------------------- */
@@ -1884,7 +1872,7 @@ GDALDataset *PCIDSK2Dataset::Create( const char * pszFilename,
         aeChanTypes.resize( MAX(1, nBands), CHN_C16S );
     else if( eType == GDT_CFloat32 )
         aeChanTypes.resize( MAX(1, nBands), CHN_C32R );
-    else 
+    else
         aeChanTypes.resize( MAX(1,nBands), CHN_8U );
 
 /* -------------------------------------------------------------------- */
@@ -1892,9 +1880,7 @@ GDALDataset *PCIDSK2Dataset::Create( const char * pszFilename,
 /*      quality.                                                        */
 /* -------------------------------------------------------------------- */
     CPLString osOptions;
-    const char *pszValue;
-
-    pszValue = CSLFetchNameValue( papszParmList, "INTERLEAVING" );
+    const char *pszValue = CSLFetchNameValue( papszParmList, "INTERLEAVING" );
     if( pszValue == NULL )
         pszValue = "BAND";
 
@@ -1917,21 +1903,22 @@ GDALDataset *PCIDSK2Dataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Try creation.                                                   */
 /* -------------------------------------------------------------------- */
+
     try {
         if( nBands == 0 )
             nXSize = nYSize = 512;
-        poFile = PCIDSK::Create( pszFilename, nXSize, nYSize, nBands, 
-                                 &(aeChanTypes[0]), osOptions, 
-                                 PCIDSK2GetInterfaces() );
+        PCIDSKFile *poFile = PCIDSK::Create( pszFilename, nXSize, nYSize, nBands,
+                                             &(aeChanTypes[0]), osOptions,
+                                             PCIDSK2GetInterfaces() );
 
 /* -------------------------------------------------------------------- */
 /*      Apply band descriptions, if provided as creation options.       */
 /* -------------------------------------------------------------------- */
-        size_t i;
-
-        for( i = 0; papszParmList != NULL && papszParmList[i] != NULL; i++ )
+        for( size_t i = 0;
+             papszParmList != NULL && papszParmList[i] != NULL;
+             i++ )
         {
-            if( EQUALN(papszParmList[i],"BANDDESC",8) )
+            if( STARTS_WITH_CI(papszParmList[i], "BANDDESC") )
             {
                 int nBand = atoi(papszParmList[i] + 8 );
                 const char *pszDescription = strstr(papszParmList[i],"=");
@@ -1947,18 +1934,18 @@ GDALDataset *PCIDSK2Dataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Trap exceptions.                                                */
 /* -------------------------------------------------------------------- */
-    catch( PCIDSKException ex )
+    catch( const PCIDSKException& ex )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", ex.what() );
-        return NULL;
     }
     catch( ... )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "PCIDSK::Create() failed, unexpected exception." );
-        return NULL;
     }
+
+    return NULL;
 }
 
 /************************************************************************/
@@ -1970,8 +1957,8 @@ int PCIDSK2Dataset::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,ODsCCreateLayer) )
         return eAccess == GA_Update;
-    else
-        return FALSE;
+
+    return FALSE;
 }
 
 /************************************************************************/
@@ -1981,10 +1968,10 @@ int PCIDSK2Dataset::TestCapability( const char * pszCap )
 OGRLayer *PCIDSK2Dataset::GetLayer( int iLayer )
 
 {
-    if( iLayer < 0 || iLayer >= (int) apoLayers.size() )
+  if( iLayer < 0 || iLayer >= static_cast<int>( apoLayers.size() ) )
         return NULL;
-    else
-        return apoLayers[iLayer];
+
+    return apoLayers[iLayer];
 }
 
 /************************************************************************/
@@ -2006,10 +1993,9 @@ PCIDSK2Dataset::ICreateLayer( const char * pszLayerName,
                   "Data source %s opened read-only.\n"
                   "New layer %s cannot be created.\n",
                   GetDescription(), pszLayerName );
-        
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Figure out what type of layer we need.                          */
 /* -------------------------------------------------------------------- */
@@ -2020,7 +2006,7 @@ PCIDSK2Dataset::ICreateLayer( const char * pszLayerName,
       case wkbPoint:
         osLayerType = "POINTS";
         break;
-    
+
       case wkbLineString:
         osLayerType = "ARCS";
         break;
@@ -2028,7 +2014,7 @@ PCIDSK2Dataset::ICreateLayer( const char * pszLayerName,
       case wkbPolygon:
         osLayerType = "WHOLE_POLYGONS";
         break;
-        
+
       case wkbNone:
         osLayerType = "TABLE";
         break;
@@ -2040,11 +2026,13 @@ PCIDSK2Dataset::ICreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
 /*      Create the segment.                                             */
 /* -------------------------------------------------------------------- */
-    int     nSegNum = poFile->CreateSegment( pszLayerName, "", 
+    const int nSegNum = poFile->CreateSegment( pszLayerName, "",
                                              PCIDSK::SEG_VEC, 0L );
     PCIDSK::PCIDSKSegment *poSeg = poFile->GetSegment( nSegNum );
-    PCIDSK::PCIDSKVectorSegment *poVecSeg = 
+    PCIDSK::PCIDSKVectorSegment *poVecSeg =
         dynamic_cast<PCIDSK::PCIDSKVectorSegment*>( poSeg );
+    if( poVecSeg == NULL )
+        return NULL;
 
     if( osLayerType != "" )
         poSeg->SetMetadataValue( "LAYER_TYPE", osLayerType );
@@ -2056,39 +2044,42 @@ PCIDSK2Dataset::ICreateLayer( const char * pszLayerName,
     char *pszUnits = NULL;
     double *padfPrjParams = NULL;
 
-    if( poSRS != NULL 
-        && poSRS->exportToPCI( &pszGeosys, &pszUnits, 
+    if( poSRS != NULL
+        && poSRS->exportToPCI( &pszGeosys, &pszUnits,
                                &padfPrjParams ) == OGRERR_NONE )
     {
         try
         {
             std::vector<double> adfPCIParameters;
-            int i;
 
-            for( i = 0; i < 17; i++ )
+            for( int i = 0; i < 17; i++ )
                 adfPCIParameters.push_back( padfPrjParams[i] );
-            
-            if( EQUALN(pszUnits,"FOOT",4) )
-                adfPCIParameters.push_back( 
-                    (double)(int) PCIDSK::UNIT_US_FOOT );
-            else if( EQUALN(pszUnits,"INTL FOOT",9) )
-                adfPCIParameters.push_back( 
-                    (double)(int) PCIDSK::UNIT_INTL_FOOT );
-            else if( EQUALN(pszUnits,"DEGREE",6) )
-                adfPCIParameters.push_back( 
-                    (double)(int) PCIDSK::UNIT_DEGREE );
-            else 
-                adfPCIParameters.push_back( 
-                    (double)(int) PCIDSK::UNIT_METER );
-            
+
+            if( STARTS_WITH_CI(pszUnits, "FOOT") )
+                adfPCIParameters.push_back(
+                    static_cast<double>( static_cast<int>(
+                        PCIDSK::UNIT_US_FOOT ) ) );
+            else if( STARTS_WITH_CI(pszUnits, "INTL FOOT") )
+                adfPCIParameters.push_back(
+                    static_cast<double>( static_cast<int>(
+                        PCIDSK::UNIT_INTL_FOOT ) ) );
+            else if( STARTS_WITH_CI(pszUnits, "DEGREE") )
+                adfPCIParameters.push_back(
+                    static_cast<double>( static_cast<int>(
+                        PCIDSK::UNIT_DEGREE ) ) );
+            else
+                adfPCIParameters.push_back(
+                    static_cast<double>( static_cast<int>(
+                        PCIDSK::UNIT_METER ) ) );
+
             poVecSeg->SetProjection( pszGeosys, adfPCIParameters );
         }
-        catch( PCIDSK::PCIDSKException ex )
+        catch( const PCIDSKException& ex )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "%s", ex.what() );
         }
-        
+
         CPLFree( pszGeosys );
         CPLFree( pszUnits );
         CPLFree( padfPrjParams );
@@ -2097,7 +2088,8 @@ PCIDSK2Dataset::ICreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
 /*      Create the layer object.                                        */
 /* -------------------------------------------------------------------- */
-    apoLayers.push_back( new OGRPCIDSKLayer( poSeg, TRUE ) );
+
+    apoLayers.push_back( new OGRPCIDSKLayer( poSeg, poVecSeg, TRUE ) );
 
     return apoLayers[apoLayers.size()-1];
 }
@@ -2109,23 +2101,21 @@ PCIDSK2Dataset::ICreateLayer( const char * pszLayerName,
 void GDALRegister_PCIDSK()
 
 {
-    GDALDriver  *poDriver;
-
-    if( GDALGetDriverByName( "PCIDSK" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-
-        poDriver->SetDescription( "PCIDSK" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "PCIDSK Database File" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "frmt_pcidsk.html" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "pix" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte UInt16 Int16 Float32 CInt16 CFloat32" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    if( GDALGetDriverByName( "PCIDSK" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "PCIDSK" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "PCIDSK Database File" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_pcidsk.html" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "pix" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte UInt16 Int16 Float32 CInt16 CFloat32" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "   <Option name='INTERLEAVING' type='string-select' default='BAND' description='raster data organization'>"
 "       <Value>PIXEL</Value>"
@@ -2139,13 +2129,13 @@ void GDALRegister_PCIDSK()
 "       <Value>JPEG</Value>"
 "   </Option>"
 "   <Option name='TILESIZE' type='int' default='127' description='Tile Size (INTERLEAVING=TILED only)'/>"
-"</CreationOptionList>" ); 
-        poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST, "<LayerCreationOptionList/>" );
+"</CreationOptionList>" );
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+                               "<LayerCreationOptionList/>" );
 
-        poDriver->pfnIdentify = PCIDSK2Dataset::Identify;
-        poDriver->pfnOpen = PCIDSK2Dataset::Open;
-        poDriver->pfnCreate = PCIDSK2Dataset::Create;
+    poDriver->pfnIdentify = PCIDSK2Dataset::Identify;
+    poDriver->pfnOpen = PCIDSK2Dataset::Open;
+    poDriver->pfnCreate = PCIDSK2Dataset::Create;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/pcidsk/pcidskdataset2.h b/frmts/pcidsk/pcidskdataset2.h
index 7d59927..d88f440 100644
--- a/frmts/pcidsk/pcidskdataset2.h
+++ b/frmts/pcidsk/pcidskdataset2.h
@@ -34,13 +34,13 @@
 
 #define GDAL_PCIDSK_DRIVER
 
+#include "cpl_string.h"
+#include "gdal_pam.h"
+#include "ogrsf_frmts.h"
+#include "ogr_spatialref.h"
 #include "pcidsk.h"
 #include "pcidsk_pct.h"
-#include "ogrsf_frmts.h"
 #include "pcidsk_vectorsegment.h"
-#include "gdal_pam.h"
-#include "cpl_string.h"
-#include "ogr_spatialref.h"
 
 using namespace PCIDSK;
 
@@ -58,11 +58,11 @@ class PCIDSK2Dataset : public GDALPamDataset
     CPLString   osLastMDValue;
     char      **papszLastMDListValue;
 
-    PCIDSKFile  *poFile;
+    PCIDSK::PCIDSKFile  *poFile;
 
     std::vector<OGRPCIDSKLayer*> apoLayers;
 
-    static GDALDataType  PCIDSKTypeToGDAL( eChanType eType );
+    static GDALDataType  PCIDSKTypeToGDAL( PCIDSK::eChanType eType );
     void                 ProcessRPC();
 
   public:
@@ -113,12 +113,12 @@ class PCIDSK2Band : public GDALPamRasterBand
 {
     friend class PCIDSK2Dataset;
 
-    PCIDSKChannel *poChannel;
-    PCIDSKFile    *poFile;
+    PCIDSK::PCIDSKChannel *poChannel;
+    PCIDSK::PCIDSKFile *poFile;
 
     void        RefreshOverviewList();
     std::vector<PCIDSK2Band*> apoOverviews;
-    
+
     CPLString   osLastMDValue;
     char      **papszLastMDListValue;
 
@@ -132,8 +132,8 @@ class PCIDSK2Band : public GDALPamRasterBand
     void        Initialize();
 
   public:
-                PCIDSK2Band( PCIDSK2Dataset *, PCIDSKFile *, int );
-                PCIDSK2Band( PCIDSKChannel * );
+                PCIDSK2Band( PCIDSK2Dataset *, PCIDSK::PCIDSKFile *, int );
+                PCIDSK2Band( PCIDSK::PCIDSKChannel * );
                 ~PCIDSK2Band();
 
     virtual CPLErr IReadBlock( int, int, void * );
@@ -144,7 +144,7 @@ class PCIDSK2Band : public GDALPamRasterBand
 
     virtual GDALColorInterp GetColorInterpretation();
     virtual GDALColorTable *GetColorTable();
-    virtual CPLErr SetColorTable( GDALColorTable * ); 
+    virtual CPLErr SetColorTable( GDALColorTable * );
 
     virtual void        SetDescription( const char * );
 
@@ -178,7 +178,7 @@ class OGRPCIDSKLayer : public OGRLayer
     OGRSpatialReference *poSRS;
 
   public:
-    OGRPCIDSKLayer( PCIDSK::PCIDSKSegment*, bool bUpdate );
+    OGRPCIDSKLayer( PCIDSK::PCIDSKSegment*, PCIDSK::PCIDSKVectorSegment *, bool bUpdate );
     ~OGRPCIDSKLayer();
 
     void                ResetReading();
@@ -197,6 +197,8 @@ class OGRPCIDSKLayer : public OGRLayer
 
     GIntBig             GetFeatureCount( int );
     OGRErr              GetExtent( OGREnvelope *psExtent, int bForce );
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 };
 
 #endif /*  PCIDSKDATASET2_H_INCLUDED */
diff --git a/frmts/pcidsk/pcidsktiledrasterband.cpp b/frmts/pcidsk/pcidsktiledrasterband.cpp
deleted file mode 100644
index 5af012f..0000000
--- a/frmts/pcidsk/pcidsktiledrasterband.cpp
+++ /dev/null
@@ -1,365 +0,0 @@
-/******************************************************************************
- * $Id: pcidsktiledrasterband.cpp 17688 2009-09-25 16:01:19Z dron $
- *
- * Project:  PCIDSK Database File
- * Purpose:  Implementation of PCIDSKTiledRasterBand
- * Author:   Frank Warmerdam <warmerdam at pobox.com>
- *
- ******************************************************************************
- * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "gdal_pcidsk.h"
-
-CPL_CVSID("$Id: pcidsktiledrasterband.cpp 17688 2009-09-25 16:01:19Z dron $");
-
-/************************************************************************/
-/*                           PCIDSKRasterBand()                         */
-/************************************************************************/
-
-PCIDSKTiledRasterBand::PCIDSKTiledRasterBand( PCIDSKDataset *poDS, 
-                                              int nBand, int nImage )
-
-{
-    poPDS = poDS;
-    this->poDS = poDS;
-
-    this->nBand = nBand;
-    this->nImage = nImage;
-
-    nOverviewCount = 0;
-    papoOverviews = NULL;
-
-    nBlocks = 0;
-    panBlockOffset = NULL;
-    
-    if( !BuildBlockMap() )
-        return;
-
-/* -------------------------------------------------------------------- */
-/*      Load and parse image header.  This is the image header          */
-/*      within the tiled image data.                                    */
-/* -------------------------------------------------------------------- */
-    char achBData[128];
-
-    SysRead( 0, 128, achBData );
- 
-    nRasterXSize = (int) CPLScanLong(achBData + 0, 8);
-    nRasterYSize = (int) CPLScanLong(achBData + 8, 8);
-    nBlockXSize = (int) CPLScanLong(achBData + 16, 8);
-    nBlockYSize = (int) CPLScanLong(achBData + 24, 8);
-    
-    int nBPR = (nBlockXSize) ? (nRasterXSize + nBlockXSize - 1) / nBlockXSize : 0;
-    int nBPC = (nBlockYSize) ? (nRasterYSize + nBlockYSize - 1) / nBlockYSize : 0;
-
-    /* nBPR * nBPC * 20 must fit on an int. See BuildTileMap() */
-    if ( nRasterXSize <= 0 || nRasterYSize <= 0 || nBlockXSize <= 0 || nBlockYSize <= 0
-         || nRasterXSize > INT_MAX - (nBlockXSize - 1)
-         || nRasterYSize > INT_MAX - (nBlockYSize - 1)
-         || (double)nBPR * (double)nBPC * 20 > INT_MAX )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, "Invalid raster or block dimensions" );
-        nRasterXSize = 0;
-        nRasterYSize = 0;
-        nBlockXSize = 0;
-        nBlockYSize = 0;
-    }
-    
-    eDataType = poPDS->PCIDSKTypeToGDAL( achBData + 32 );
-
-    szCompression[8] = '\0';
-    memcpy( szCompression, achBData+54, 8 );
-}
-
-/************************************************************************/
-/*                       ~PCIDSKTiledRasterBand()                       */
-/************************************************************************/
-
-PCIDSKTiledRasterBand::~PCIDSKTiledRasterBand()
-{
-    FlushCache();
-
-    int i;
-
-    for( i = 0; i < nOverviewCount; i++ )
-        delete papoOverviews[i];
-    CPLFree( papoOverviews );
-
-    CPLFree( panBlockOffset );
-    CPLFree( panTileOffset );
-    CPLFree( panTileSize );
-}
-
-/************************************************************************/
-/*                           BuildBlockMap()                            */
-/************************************************************************/
-
-int PCIDSKTiledRasterBand::BuildBlockMap()
-
-{
-    nBlocks = 0;
-    panBlockOffset = NULL;
-
-    nTileCount = 0;
-    panTileOffset = NULL;
-    panTileSize = NULL;
-
-/* -------------------------------------------------------------------- */
-/*      Read the whole block map segment.                               */
-/* -------------------------------------------------------------------- */
-    int  nBMapSize;
-    char *pachBMap;
-
-    if( poPDS->nBlockMapSeg < 1 )
-        return FALSE;
-
-    nBMapSize = (int) poPDS->panSegSize[poPDS->nBlockMapSeg-1];
-    pachBMap = (char *) CPLCalloc(nBMapSize+1,1);
-    
-    if( !poPDS->SegRead( poPDS->nBlockMapSeg, 0, nBMapSize, pachBMap ) )
-        return FALSE;
-    
-/* -------------------------------------------------------------------- */
-/*      Parse the header.                                               */
-/* -------------------------------------------------------------------- */
-    int nMaxBlocks = (int) CPLScanLong(pachBMap + 18,8);
-
-    if( !EQUALN(pachBMap,"VERSION",7) )
-        return FALSE;
-
-/* -------------------------------------------------------------------- */
-/*      Build a "back link" map for this image's blocks.  We need       */
-/*      this to positively identify the first block in the chain.       */
-/* -------------------------------------------------------------------- */
-    int *panBackLink;
-    int i, nLastBlock = -1;
-
-    panBackLink = (int *) VSICalloc( sizeof(int), nMaxBlocks );
-    if ( panBackLink == NULL )
-    {
-        VSIFree( pachBMap );
-        VSIFree( panBackLink );
-        return FALSE;
-    }
-    for( i = 0; i < nMaxBlocks; i++ )
-        panBackLink[i] = -1;
-
-    for( i = 0; i < nMaxBlocks; i++ )
-    {
-        char *pachEntry = pachBMap + i * 28 + 512;
-        int nThisImage = (int) CPLScanLong(pachEntry + 12,8);
-        int nNextBlock = (int) CPLScanLong(pachEntry + 20,8);
-
-        if ( nThisImage != nImage || nNextBlock >= nMaxBlocks )
-            continue;
-
-        if( nNextBlock == -1 )
-            nLastBlock = i;
-        else
-            panBackLink[nNextBlock] = i;
-    }
-    
-/* -------------------------------------------------------------------- */
-/*      Track back through chain to identify the first entry (while     */
-/*      counting).                                                      */
-/* -------------------------------------------------------------------- */
-    int iBlock = nLastBlock;
-
-    nBlocks = 1;
-    while( panBackLink[iBlock] != -1 )
-    {
-        nBlocks++;
-        iBlock = panBackLink[iBlock];
-    }
-
-    CPLFree( panBackLink );
-    panBlockOffset = (vsi_l_offset *) VSIMalloc(sizeof(vsi_l_offset)*nBlocks);
-    if ( panBlockOffset == NULL )
-    {
-        CPLFree( pachBMap );
-        return FALSE;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Process blocks, transforming to absolute offsets in the         */
-/*      PCIDSK file.                                                    */
-/* -------------------------------------------------------------------- */
-    for( i = 0; i < nBlocks; i++ )
-    {
-        char *pachEntry = pachBMap + iBlock * 28 + 512;
-        int nBDataSeg = CPLScanLong( pachEntry + 0, 4 );
-        int nBDataBlock = CPLScanLong( pachEntry + 4, 8 );
-
-        if ( nBDataSeg <= 0 || nBDataSeg > poPDS->nSegCount
-             || poPDS->panSegType[nBDataSeg-1] != 182)
-        {
-            CPLFree( pachBMap );
-            return FALSE;
-        }
-
-        panBlockOffset[i] = 
-            ((vsi_l_offset) nBDataBlock) * 8192
-            + poPDS->panSegOffset[nBDataSeg-1] + 1024;
-
-        iBlock = (int) CPLScanLong( pachEntry + 20, 8 );
-    }            
-
-    CPLFree( pachBMap );
-
-    return TRUE;
-}
-
-/************************************************************************/
-/*                            BuildTileMap()                            */
-/************************************************************************/
-
-int PCIDSKTiledRasterBand::BuildTileMap()
-
-{
-    if ( nTileCount < 0 )
-        return FALSE;
-    if( nTileCount > 0)
-        return TRUE;
-
-    int nBPR = (nRasterXSize + nBlockXSize - 1) / nBlockXSize;
-    int nBPC = (nRasterYSize + nBlockYSize - 1) / nBlockYSize;
-
-    nTileCount = nBPR * nBPC;
-    panTileOffset = (vsi_l_offset *) 
-        VSICalloc( sizeof(vsi_l_offset), nTileCount );
-    panTileSize = (int *) VSICalloc( sizeof(int), nTileCount );
-
-    char *pachTileInfo = (char *) VSIMalloc( 20 * nTileCount );
-    if ( panTileOffset == NULL || panTileSize == NULL || pachTileInfo == NULL )
-    {
-        CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory" );
-        nTileCount = -1;
-        CPLFree( pachTileInfo );
-        return FALSE;
-    }
-
-    if( !SysRead( 128, 20 * nTileCount, pachTileInfo ) )
-    {
-        nTileCount = -1;
-        CPLFree( pachTileInfo );
-        return FALSE;
-    }
-
-    for( int iTile = 0; iTile < nTileCount; iTile++ )
-    {
-        panTileOffset[iTile] = (vsi_l_offset)
-            CPLScanUIntBig( pachTileInfo+12*iTile, 12 );
-        panTileSize[iTile] = (int)
-            CPLScanLong( pachTileInfo+12*nTileCount+8*iTile, 8 );
-    }
-
-    CPLFree( pachTileInfo );
-
-    return TRUE;
-}
-
-/************************************************************************/
-/*                             IReadBlock()                             */
-/************************************************************************/
-
-CPLErr PCIDSKTiledRasterBand::IReadBlock( int nBlockX, int nBlockY, 
-                                          void *pData )
-
-{
-    int iTile;
-
-    if( !EQUALN(szCompression,"NONE",4) )
-    {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "Compression '%s' not supported by GDAL.", 
-                  szCompression );
-        return CE_Failure;
-    }
-
-    if( !BuildTileMap() )
-        return CE_Failure;
-    
-    int nBPR = (nRasterXSize + nBlockXSize - 1) / nBlockXSize;
-
-    iTile = nBlockX + nBlockY * nBPR;
-
-    if( panTileOffset[iTile] == (vsi_l_offset) -1 )
-    {
-        int   nWordSize = GDALGetDataTypeSize( eDataType ) / 8;
-        memset( pData, 0, nBlockXSize*nBlockYSize*nWordSize );
-    }
-    else
-    {
-        if( !SysRead( panTileOffset[iTile], panTileSize[iTile], pData ) )
-            return CE_Failure;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      PCIDSK multibyte data is always big endian.  Swap if needed.    */
-/* -------------------------------------------------------------------- */
-#ifdef CPL_LSB
-    int   nWordSize = GDALGetDataTypeSize( eDataType ) / 8;
-    GDALSwapWords( pData, nWordSize, nBlockXSize * nBlockYSize, nWordSize );
-#endif
-
-    return CE_None;
-}
-
-/************************************************************************/
-/*                              SysRead()                               */
-/************************************************************************/
-
-int PCIDSKTiledRasterBand::SysRead( vsi_l_offset nOffset, 
-                                    int nSize, 
-                                    void *pData )
-
-{
-    int iReadSoFar = 0;
-
-    while( iReadSoFar < nSize )
-    {
-        int iBlock;
-        vsi_l_offset nNextOffset = nOffset + iReadSoFar;
-        vsi_l_offset nRealOffset;
-        int          nOffsetInBlock, nThisReadBytes;
-        
-        iBlock = (int) (nNextOffset >> 13);
-        nOffsetInBlock = (int) (nNextOffset & 0x1fff);
-
-        if ( iBlock >= nBlocks )
-            return 0;
-
-        nRealOffset = panBlockOffset[iBlock] + nOffsetInBlock;
-        
-        nThisReadBytes = MIN(nSize - iReadSoFar,8192 - nOffsetInBlock);
-        
-        if( VSIFSeekL( poPDS->fp, nRealOffset, SEEK_SET ) != 0 )
-            return 0;
-
-        if( VSIFReadL( ((char *) pData) + iReadSoFar, 1, nThisReadBytes,
-                       poPDS->fp ) != (size_t) nThisReadBytes )
-            return 0;
-
-        iReadSoFar += nThisReadBytes;
-    }
-
-    return nSize;
-}
diff --git a/frmts/pcidsk/sdk/Doxyfile b/frmts/pcidsk/sdk/Doxyfile
index 113d33c..3e79a2b 100644
--- a/frmts/pcidsk/sdk/Doxyfile
+++ b/frmts/pcidsk/sdk/Doxyfile
@@ -427,7 +427,7 @@ WARN_IF_UNDOCUMENTED   = YES
 
 WARN_IF_DOC_ERROR      = YES
 
-# This WARN_NO_PARAMDOC option can be abled to get warnings for 
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for 
 # functions that are documented, but have no documentation for their parameters 
 # or return value. If set to NO (the default) doxygen will only warn about 
 # wrong or incomplete parameter documentation, but not about the absence of 
@@ -590,7 +590,7 @@ REFERENCES_RELATION    = YES
 # If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
 # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
 # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
-# link to the source code.  Otherwise they will link to the documentstion.
+# link to the source code.  Otherwise they will link to the documentation.
 
 REFERENCES_LINK_SOURCE = YES
 
diff --git a/frmts/pcidsk/sdk/channel/cbandinterleavedchannel.cpp b/frmts/pcidsk/sdk/channel/cbandinterleavedchannel.cpp
index bf01885..8ff3b03 100644
--- a/frmts/pcidsk/sdk/channel/cbandinterleavedchannel.cpp
+++ b/frmts/pcidsk/sdk/channel/cbandinterleavedchannel.cpp
@@ -53,13 +53,13 @@ using namespace PCIDSK;
 /************************************************************************/
 
 CBandInterleavedChannel::CBandInterleavedChannel( PCIDSKBuffer &image_header,
-                                                  uint64 ih_offset,
+                                                  uint64 ih_offsetIn,
                                                   CPL_UNUSED PCIDSKBuffer &file_header,
                                                   int channelnum,
-                                                  CPCIDSKFile *file,
+                                                  CPCIDSKFile *fileIn,
                                                   uint64 image_offset,
-                                                  eChanType pixel_type )
-        : CPCIDSKChannel( image_header, ih_offset, file, pixel_type, channelnum)
+                                                  eChanType pixel_typeIn )
+        : CPCIDSKChannel( image_header, ih_offsetIn, fileIn, pixel_typeIn, channelnum)
 
 {
     io_handle_p = NULL;
@@ -134,7 +134,7 @@ int CBandInterleavedChannel::ReadBlock( int block_index, void *buffer,
     if( xoff < 0 || xoff + xsize > GetBlockWidth()
         || yoff < 0 || yoff + ysize > GetBlockHeight() )
     {
-        ThrowPCIDSKException( 
+        return ThrowPCIDSKException( 0,
             "Invalid window in ReadBloc(): xoff=%d,yoff=%d,xsize=%d,ysize=%d",
             xoff, yoff, xsize, ysize );
     }
@@ -210,7 +210,7 @@ int CBandInterleavedChannel::WriteBlock( int block_index, void *buffer )
     PCIDSKInterfaces *interfaces = file->GetInterfaces();
 
     if( !file->GetUpdatable() )
-        throw PCIDSKException( "File not open for update in WriteBlock()" );
+        return ThrowPCIDSKException(0, "File not open for update in WriteBlock()" );
 
     InvalidateOverviews();
 
@@ -290,13 +290,13 @@ int CBandInterleavedChannel::WriteBlock( int block_index, void *buffer )
 /************************************************************************/
 void CBandInterleavedChannel
 ::GetChanInfo( std::string &filename_ret, uint64 &image_offset, 
-               uint64 &pixel_offset, uint64 &line_offset, 
+               uint64 &pixel_offsetOut, uint64 &line_offsetOut, 
                bool &little_endian ) const
 
 {
     image_offset = start_byte;
-    pixel_offset = this->pixel_offset;
-    line_offset = this->line_offset;
+    pixel_offsetOut = this->pixel_offset;
+    line_offsetOut = this->line_offset;
     little_endian = (byte_order == 'S');
 
 /* -------------------------------------------------------------------- */
@@ -315,13 +315,13 @@ void CBandInterleavedChannel
 /************************************************************************/
 
 void CBandInterleavedChannel
-::SetChanInfo( std::string filename, uint64 image_offset, 
-               uint64 pixel_offset, uint64 line_offset, 
+::SetChanInfo( std::string filenameIn, uint64 image_offset, 
+               uint64 pixel_offsetIn, uint64 line_offsetIn, 
                bool little_endian )
 
 {
     if( ih_offset == 0 )
-        ThrowPCIDSKException( "No Image Header available for this channel." );
+        return ThrowPCIDSKException( "No Image Header available for this channel." );
 
 /* -------------------------------------------------------------------- */
 /*      Fetch the existing image header.                                */
@@ -337,7 +337,7 @@ void CBandInterleavedChannel
 /* -------------------------------------------------------------------- */
     std::string IHi2_filename;
     
-    if( filename.size() > 64 )
+    if( filenameIn.size() > 64 )
     {
         int link_segment;
         
@@ -356,7 +356,7 @@ void CBandInterleavedChannel
                                      "Long external channel filename link.", 
                                      SEG_SYS, 1 );
 
-            sprintf( link_filename, "LNK %4d", link_segment );
+            snprintf( link_filename, sizeof(link_filename), "LNK %4d", link_segment );
             IHi2_filename = link_filename;
         }
 
@@ -365,7 +365,7 @@ void CBandInterleavedChannel
         
         if( link != NULL )
         {
-            link->SetPath( filename );
+            link->SetPath( filenameIn );
             link->Synchronize();
         }
     }
@@ -385,7 +385,7 @@ void CBandInterleavedChannel
             file->DeleteSegment( link_segment );
         }
         
-        IHi2_filename = filename;
+        IHi2_filename = filenameIn;
     }
         
 /* -------------------------------------------------------------------- */
@@ -398,10 +398,10 @@ void CBandInterleavedChannel
     ih.Put( image_offset, 168, 16 );
 
     // IHi.6.2
-    ih.Put( pixel_offset, 184, 8 );
+    ih.Put( pixel_offsetIn, 184, 8 );
 
     // IHi.6.3
-    ih.Put( line_offset, 192, 8 );
+    ih.Put( line_offsetIn, 192, 8 );
 
     // IHi.6.5
     if( little_endian )
@@ -416,11 +416,11 @@ void CBandInterleavedChannel
 /* -------------------------------------------------------------------- */
     this->filename = MergeRelativePath( file->GetInterfaces()->io,
                                         file->GetFilename(), 
-                                        filename );
+                                        filenameIn );
 
     start_byte = image_offset;
-    this->pixel_offset = pixel_offset;
-    this->line_offset = line_offset;
+    this->pixel_offset = pixel_offsetIn;
+    this->line_offset = line_offsetIn;
     
     if( little_endian )
         byte_order = 'S';
@@ -458,15 +458,17 @@ std::string CBandInterleavedChannel::MassageLink( std::string filename_in ) cons
         
         if (seg_num == 0)
         {
-            throw PCIDSKException("Unable to find link segment. Link name: %s",
+            ThrowPCIDSKException("Unable to find link segment. Link name: %s",
                                   filename_in.c_str());
+            return "";
         }
         
         CLinkSegment* link_seg = 
             dynamic_cast<CLinkSegment*>(file->GetSegment(seg_num));
         if (link_seg == NULL)
         {
-            throw PCIDSKException("Failed to get Link Information Segment.");
+            ThrowPCIDSKException("Failed to get Link Information Segment.");
+            return "";
         }
         
         filename_in = link_seg->GetPath();
diff --git a/frmts/pcidsk/sdk/channel/cbandinterleavedchannel.h b/frmts/pcidsk/sdk/channel/cbandinterleavedchannel.h
index 92d4efb..98af6b0 100644
--- a/frmts/pcidsk/sdk/channel/cbandinterleavedchannel.h
+++ b/frmts/pcidsk/sdk/channel/cbandinterleavedchannel.h
@@ -28,8 +28,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_CHANNEL_CBANDINTERLEAVEDCHANNEL_H
-#define __INCLUDE_CHANNEL_CBANDINTERLEAVEDCHANNEL_H
+#ifndef INCLUDE_CHANNEL_CBANDINTERLEAVEDCHANNEL_H
+#define INCLUDE_CHANNEL_CBANDINTERLEAVEDCHANNEL_H
 
 #include "pcidsk_config.h"
 #include "pcidsk_types.h"
@@ -86,4 +86,4 @@ namespace PCIDSK
     };
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_CHANNEL_CBANDINTERLEAVEDCHANNEL_H
+#endif // INCLUDE_CHANNEL_CBANDINTERLEAVEDCHANNEL_H
diff --git a/frmts/pcidsk/sdk/channel/cexternalchannel.cpp b/frmts/pcidsk/sdk/channel/cexternalchannel.cpp
index 9ba29f3..996139b 100644
--- a/frmts/pcidsk/sdk/channel/cexternalchannel.cpp
+++ b/frmts/pcidsk/sdk/channel/cexternalchannel.cpp
@@ -52,40 +52,42 @@ using namespace PCIDSK;
 /*                          CExternalChannel()                          */
 /************************************************************************/
 
-CExternalChannel::CExternalChannel( PCIDSKBuffer &image_header,
-                                    uint64 ih_offset,
-                                    CPL_UNUSED PCIDSKBuffer &file_header,
-                                    std::string filename,
-                                    int channelnum,
-                                    CPCIDSKFile *file,
-                                    eChanType pixel_type )
-        : CPCIDSKChannel( image_header, ih_offset, file, pixel_type, channelnum)
+CExternalChannel::CExternalChannel( PCIDSKBuffer &image_headerIn,
+                                    uint64 ih_offsetIn,
+                                    CPL_UNUSED PCIDSKBuffer &file_headerIn,
+                                    std::string filenameIn,
+                                    int channelnumIn,
+                                    CPCIDSKFile *fileIn,
+                                    eChanType pixel_typeIn )
+        : CPCIDSKChannel( image_headerIn, ih_offsetIn, fileIn, pixel_typeIn, channelnumIn)
 
 {
     db = NULL;
     mutex = NULL;
+    writable = false;
+    blocks_per_row = 0;
 
 /* -------------------------------------------------------------------- */
 /*      Establish the data window.                                      */
 /* -------------------------------------------------------------------- */
-    exoff  = atoi(image_header.Get( 250, 8 ));
-    eyoff  = atoi(image_header.Get( 258, 8 ));
-    exsize = atoi(image_header.Get( 266, 8 ));
-    eysize = atoi(image_header.Get( 274, 8 ));
+    exoff  = atoi(image_headerIn.Get( 250, 8 ));
+    eyoff  = atoi(image_headerIn.Get( 258, 8 ));
+    exsize = atoi(image_headerIn.Get( 266, 8 ));
+    eysize = atoi(image_headerIn.Get( 274, 8 ));
 
-    echannel = atoi(image_header.Get( 282, 8 ));
+    echannel = atoi(image_headerIn.Get( 282, 8 ));
 
     if (echannel == 0) {
-        echannel = channelnum;
+        echannel = channelnumIn;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Establish the file we will be accessing.                        */
 /* -------------------------------------------------------------------- */
-    if( filename != "" )
-        this->filename = filename;
+    if( filenameIn != "" )
+        this->filename = filenameIn;
     else
-        image_header.Get(64,64,this->filename);
+        image_headerIn.Get(64,64,this->filename);
 }
 
 /************************************************************************/
@@ -178,7 +180,7 @@ int CExternalChannel::ReadBlock( int block_index, void *buffer,
     if( xoff < 0 || xoff + xsize > GetBlockWidth()
         || yoff < 0 || yoff + ysize > GetBlockHeight() )
     {
-        ThrowPCIDSKException( 
+        return ThrowPCIDSKException( 0,
             "Invalid window in ReadBlock(): xoff=%d,yoff=%d,xsize=%d,ysize=%d",
             xoff, yoff, xsize, ysize );
     }
@@ -210,7 +212,7 @@ int CExternalChannel::ReadBlock( int block_index, void *buffer,
     int dst_blockx, dst_blocky;
 
     if( temp_buffer == NULL )
-        ThrowPCIDSKException( "Failed to allocate temporary block buffer." );
+        return ThrowPCIDSKException(0, "Failed to allocate temporary block buffer." );
 
     dst_blockx = block_index % blocks_per_row;
     dst_blocky = block_index / blocks_per_row;
@@ -407,7 +409,7 @@ int CExternalChannel::WriteBlock( int block_index, void *buffer )
     AccessDB();
 
     if( !file->GetUpdatable() || !writable )
-        throw PCIDSKException( "File not open for update in WriteBlock()" );
+        return ThrowPCIDSKException(0, "File not open for update in WriteBlock()" );
 
 /* -------------------------------------------------------------------- */
 /*      Pass the request on directly in the simple case.                */
@@ -435,7 +437,7 @@ int CExternalChannel::WriteBlock( int block_index, void *buffer )
     int dst_blockx, dst_blocky;
 
     if( temp_buffer == NULL )
-        ThrowPCIDSKException( "Failed to allocate temporary block buffer." );
+        return ThrowPCIDSKException(0, "Failed to allocate temporary block buffer." );
 
     dst_blockx = block_index % blocks_per_row;
     dst_blocky = block_index / blocks_per_row;
@@ -646,30 +648,30 @@ int CExternalChannel::WriteBlock( int block_index, void *buffer )
 /************************************************************************/
 /*                            GetEChanInfo()                            */
 /************************************************************************/
-void CExternalChannel::GetEChanInfo( std::string &filename, int &echannel,
-                                     int &exoff, int &eyoff, 
-                                     int &exsize, int &eysize ) const
+void CExternalChannel::GetEChanInfo( std::string &filenameOut, int &echannelOut,
+                                     int &exoffOut, int &eyoffOut, 
+                                     int &exsizeOut, int &eysizeOut ) const
 
 {
-    echannel = this->echannel;
-    exoff = this->exoff;
-    eyoff = this->eyoff;
-    exsize = this->exsize;
-    eysize = this->eysize;
-    filename = this->filename;
+    echannelOut = this->echannel;
+    exoffOut = this->exoff;
+    eyoffOut = this->eyoff;
+    exsizeOut = this->exsize;
+    eysizeOut = this->eysize;
+    filenameOut = this->filename;
 }
 
 /************************************************************************/
 /*                            SetEChanInfo()                            */
 /************************************************************************/
 
-void CExternalChannel::SetEChanInfo( std::string filename, int echannel,
-                                     int exoff, int eyoff, 
-                                     int exsize, int eysize )
+void CExternalChannel::SetEChanInfo( std::string filenameIn, int echannelIn,
+                                     int exoffIn, int eyoffIn, 
+                                     int exsizeIn, int eysizeIn )
 
 {
     if( ih_offset == 0 )
-        ThrowPCIDSKException( "No Image Header available for this channel." );
+        return ThrowPCIDSKException( "No Image Header available for this channel." );
 
 /* -------------------------------------------------------------------- */
 /*      Fetch the existing image header.                                */
@@ -685,7 +687,7 @@ void CExternalChannel::SetEChanInfo( std::string filename, int echannel,
 /* -------------------------------------------------------------------- */
     std::string IHi2_filename;
     
-    if( filename.size() > 64 )
+    if( filenameIn.size() > 64 )
     {
         int link_segment;
         
@@ -704,7 +706,7 @@ void CExternalChannel::SetEChanInfo( std::string filename, int echannel,
                                      "Long external channel filename link.", 
                                      SEG_SYS, 1 );
 
-            sprintf( link_filename, "LNK %4d", link_segment );
+            snprintf( link_filename, sizeof(link_filename), "LNK %4d", link_segment );
             IHi2_filename = link_filename;
         }
 
@@ -713,7 +715,7 @@ void CExternalChannel::SetEChanInfo( std::string filename, int echannel,
         
         if( link != NULL )
         {
-            link->SetPath( filename );
+            link->SetPath( filenameIn );
             link->Synchronize();
         }
     }
@@ -733,7 +735,7 @@ void CExternalChannel::SetEChanInfo( std::string filename, int echannel,
             file->DeleteSegment( link_segment );
         }
         
-        IHi2_filename = filename;
+        IHi2_filename = filenameIn;
     }
         
 /* -------------------------------------------------------------------- */
@@ -755,19 +757,19 @@ void CExternalChannel::SetEChanInfo( std::string filename, int echannel,
     ih.Put( "", 201, 1 );
 
     // IHi.6.7
-    ih.Put( exoff, 250, 8 );
+    ih.Put( exoffIn, 250, 8 );
 
     // IHi.6.8
-    ih.Put( eyoff, 258, 8 );
+    ih.Put( eyoffIn, 258, 8 );
 
     // IHi.6.9
-    ih.Put( exsize, 266, 8 );
+    ih.Put( exsizeIn, 266, 8 );
 
     // IHi.6.10
-    ih.Put( eysize, 274, 8 );
+    ih.Put( eysizeIn, 274, 8 );
 
     // IHi.6.11
-    ih.Put( echannel, 282, 8 );
+    ih.Put( echannelIn, 282, 8 );
 
     file->WriteToFile( ih.buffer, ih_offset, 1024 );
 
@@ -776,11 +778,11 @@ void CExternalChannel::SetEChanInfo( std::string filename, int echannel,
 /* -------------------------------------------------------------------- */
     this->filename = MergeRelativePath( file->GetInterfaces()->io,
                                         file->GetFilename(), 
-                                        filename );
+                                        filenameIn );
 
-    this->exoff = exoff;
-    this->eyoff = eyoff;
-    this->exsize = exsize;
-    this->eysize = eysize;
-    this->echannel = echannel;
+    this->exoff = exoffIn;
+    this->eyoff = eyoffIn;
+    this->exsize = exsizeIn;
+    this->eysize = eysizeIn;
+    this->echannel = echannelIn;
 }
diff --git a/frmts/pcidsk/sdk/channel/cexternalchannel.h b/frmts/pcidsk/sdk/channel/cexternalchannel.h
index 00ab9e6..d7d8f7a 100644
--- a/frmts/pcidsk/sdk/channel/cexternalchannel.h
+++ b/frmts/pcidsk/sdk/channel/cexternalchannel.h
@@ -29,8 +29,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef __INCLUDE_CHANNEL_CEXTERNALCHANNEL_H
-#define __INCLUDE_CHANNEL_CEXTERNALCHANNEL_H
+#ifndef INCLUDE_CHANNEL_CEXTERNALCHANNEL_H
+#define INCLUDE_CHANNEL_CEXTERNALCHANNEL_H
 
 #include "pcidsk_config.h"
 #include "pcidsk_types.h"
@@ -91,4 +91,4 @@ namespace PCIDSK
     };
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_CHANNEL_CEXTERNALCHANNEL_H
+#endif // INCLUDE_CHANNEL_CEXTERNALCHANNEL_H
diff --git a/frmts/pcidsk/sdk/channel/cpcidskchannel.cpp b/frmts/pcidsk/sdk/channel/cpcidskchannel.cpp
index 9c053d4..5c1a7cc 100644
--- a/frmts/pcidsk/sdk/channel/cpcidskchannel.cpp
+++ b/frmts/pcidsk/sdk/channel/cpcidskchannel.cpp
@@ -48,16 +48,18 @@ using namespace PCIDSK;
 /************************************************************************/
 
 CPCIDSKChannel::CPCIDSKChannel( PCIDSKBuffer &image_header, 
-                                uint64 ih_offset,
-                                CPCIDSKFile *file, 
-                                eChanType pixel_type,
-                                int channel_number )
+                                uint64 ih_offsetIn,
+                                CPCIDSKFile *fileIn, 
+                                eChanType pixel_typeIn,
+                                int channel_numberIn )
 
 {
-    this->pixel_type = pixel_type;
-    this->file = file;
-    this->channel_number = channel_number;
-    this->ih_offset = ih_offset;
+    this->pixel_type = pixel_typeIn;
+    this->file = fileIn;
+    this->channel_number = channel_numberIn;
+    this->ih_offset = ih_offsetIn;
+    byte_order = 'S';
+    needs_swap = FALSE;
 
     width = file->GetWidth();
     height = file->GetHeight();
@@ -150,7 +152,7 @@ void CPCIDSKChannel::EstablishOverviewInfo() const
 
     for( i = 0; i < keys.size(); i++ )
     {
-        if( strncmp(keys[i].c_str(),"_Overview_",10) != 0 )
+        if( !STARTS_WITH(keys[i].c_str(), "_Overview_") )
             continue;
 
         std::string value = GetMetadataValue( keys[i] );
@@ -187,7 +189,7 @@ int CPCIDSKChannel::GetOverviewCount()
 {
     EstablishOverviewInfo();
 
-    return overview_infos.size();
+    return static_cast<int>(overview_infos.size());
 }
 
 /************************************************************************/
@@ -200,7 +202,7 @@ PCIDSKChannel *CPCIDSKChannel::GetOverview( int overview_index )
     EstablishOverviewInfo();
 
     if( overview_index < 0 || overview_index >= (int) overview_infos.size() )
-        ThrowPCIDSKException( "Non existent overview (%d) requested.", 
+        return (PCIDSKChannel*)ThrowPCIDSKExceptionPtr( "Non existent overview (%d) requested.", 
                               overview_index );
 
     if( overview_bands[overview_index] == NULL )
@@ -208,7 +210,7 @@ PCIDSKChannel *CPCIDSKChannel::GetOverview( int overview_index )
         PCIDSKBuffer image_header(1024), file_header(1024);
         char  pseudo_filename[65];
 
-        sprintf( pseudo_filename, "/SIS=%d", 
+        snprintf( pseudo_filename, sizeof(pseudo_filename), "/SIS=%d", 
                  atoi(overview_infos[overview_index].c_str()) );
 
         image_header.Put( pseudo_filename, 64, 64 );
@@ -231,8 +233,8 @@ bool CPCIDSKChannel::IsOverviewValid( int overview_index )
     EstablishOverviewInfo();
 
     if( overview_index < 0 || overview_index >= (int) overview_infos.size() )
-        ThrowPCIDSKException( "Non existent overview (%d) requested.", 
-                              overview_index );
+        return ThrowPCIDSKException(0, "Non existent overview (%d) requested.", 
+                              overview_index ) != 0;
 
     int sis_id, validity=0;
 
@@ -252,8 +254,11 @@ std::string CPCIDSKChannel::GetOverviewResampling( int overview_index )
     EstablishOverviewInfo();
 
     if( overview_index < 0 || overview_index >= (int) overview_infos.size() )
+    {
         ThrowPCIDSKException( "Non existent overview (%d) requested.", 
                               overview_index );
+        return "";
+    }
 
     int sis_id, validity=0;
     char resampling[17];
@@ -275,7 +280,7 @@ void CPCIDSKChannel::SetOverviewValidity( int overview_index,
     EstablishOverviewInfo();
 
     if( overview_index < 0 || overview_index >= (int) overview_infos.size() )
-        ThrowPCIDSKException( "Non existent overview (%d) requested.", 
+        return ThrowPCIDSKException( "Non existent overview (%d) requested.", 
                               overview_index );
 
     int sis_id, validity=0;
@@ -290,14 +295,14 @@ void CPCIDSKChannel::SetOverviewValidity( int overview_index,
 
     char new_info[48];
 
-    sprintf( new_info, "%d %d %s", 
+    snprintf( new_info, sizeof(new_info), "%d %d %s", 
              sis_id, (new_validity ? 1 : 0 ), resampling );
 
     overview_infos[overview_index] = new_info;
 
     // write back to metadata.
     char key[20];
-    sprintf( key, "_Overview_%d", overview_decimations[overview_index] );
+    snprintf( key, sizeof(key), "_Overview_%d", overview_decimations[overview_index] );
 
     SetMetadataValue( key, new_info );
 }
@@ -356,7 +361,7 @@ void CPCIDSKChannel::SetDescription( const std::string &description )
 
 {
     if( ih_offset == 0 )
-        ThrowPCIDSKException( "Description cannot be set on overviews." );
+        return ThrowPCIDSKException( "Description cannot be set on overviews." );
         
     PCIDSKBuffer ih_1(64);
     ih_1.Put( description.c_str(), 0, 64 );
@@ -410,7 +415,7 @@ void CPCIDSKChannel::SetHistoryEntries(const std::vector<std::string> &entries)
 
 {
     if( ih_offset == 0 )
-        ThrowPCIDSKException( "Attempt to update history on a raster that is not\na conventional band with an image header." );
+        return ThrowPCIDSKException( "Attempt to update history on a raster that is not\na conventional band with an image header." );
 
     PCIDSKBuffer image_header(1024);
 
@@ -488,7 +493,7 @@ void CPCIDSKChannel::SetChanInfo( CPL_UNUSED std::string filename,
                                   CPL_UNUSED uint64 line_offset,
                                   CPL_UNUSED bool little_endian )
 {
-    ThrowPCIDSKException( "Attempt to SetChanInfo() on a channel that is not FILE interleaved." );
+    return ThrowPCIDSKException( "Attempt to SetChanInfo() on a channel that is not FILE interleaved." );
 }
 
 /************************************************************************/
@@ -518,5 +523,5 @@ void CPCIDSKChannel::SetEChanInfo( CPL_UNUSED std::string filename,
                                    CPL_UNUSED int exsize,
                                    CPL_UNUSED int eysize )
 {
-    ThrowPCIDSKException( "Attempt to SetEChanInfo() on a channel that is not FILE interleaved." );
+    return ThrowPCIDSKException( "Attempt to SetEChanInfo() on a channel that is not FILE interleaved." );
 }
diff --git a/frmts/pcidsk/sdk/channel/cpcidskchannel.h b/frmts/pcidsk/sdk/channel/cpcidskchannel.h
index 308ca77..754c949 100644
--- a/frmts/pcidsk/sdk/channel/cpcidskchannel.h
+++ b/frmts/pcidsk/sdk/channel/cpcidskchannel.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_CHANNEL_CPCIDSKCHANNEL_H
-#define __INCLUDE_CHANNEL_CPCIDSKCHANNEL_H
+#ifndef INCLUDE_CHANNEL_CPCIDSKCHANNEL_H
+#define INCLUDE_CHANNEL_CPCIDSKCHANNEL_H
 
 #include "pcidsk_config.h"
 #include "pcidsk_buffer.h"
@@ -139,4 +139,4 @@ namespace PCIDSK
     };
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_CHANNEL_CPCIDSKCHANNEL_H
+#endif // INCLUDE_CHANNEL_CPCIDSKCHANNEL_H
diff --git a/frmts/pcidsk/sdk/channel/cpixelinterleavedchannel.cpp b/frmts/pcidsk/sdk/channel/cpixelinterleavedchannel.cpp
index c1122e6..99e456d 100644
--- a/frmts/pcidsk/sdk/channel/cpixelinterleavedchannel.cpp
+++ b/frmts/pcidsk/sdk/channel/cpixelinterleavedchannel.cpp
@@ -40,17 +40,17 @@ using namespace PCIDSK;
 /*                      CPixelInterleavedChannel()                      */
 /************************************************************************/
 
-CPixelInterleavedChannel::CPixelInterleavedChannel( PCIDSKBuffer &image_header,
-                                                    uint64 ih_offset,
-                                                    CPL_UNUSED PCIDSKBuffer &file_header,
-                                                    int channelnum,
-                                                    CPCIDSKFile *file,
-                                                    int image_offset,
-                                                    eChanType pixel_type )
-        : CPCIDSKChannel( image_header, ih_offset, file, pixel_type, channelnum)
+CPixelInterleavedChannel::CPixelInterleavedChannel( PCIDSKBuffer &image_headerIn,
+                                                    uint64 ih_offsetIn,
+                                                    CPL_UNUSED PCIDSKBuffer &file_headerIn,
+                                                    int channelnumIn,
+                                                    CPCIDSKFile *fileIn,
+                                                    int image_offsetIn,
+                                                    eChanType pixel_typeIn )
+        : CPCIDSKChannel( image_headerIn, ih_offsetIn, fileIn, pixel_typeIn, channelnumIn)
 
 {
-    this->image_offset = image_offset;
+    this->image_offset = image_offsetIn;
 }
 
 /************************************************************************/
@@ -88,7 +88,7 @@ int CPixelInterleavedChannel::ReadBlock( int block_index, void *buffer,
     if( win_xoff < 0 || win_xoff + win_xsize > GetBlockWidth()
         || win_yoff < 0 || win_yoff + win_ysize > GetBlockHeight() )
     {
-        ThrowPCIDSKException( 
+        return ThrowPCIDSKException(0, 
             "Invalid window in ReadBloc(): win_xoff=%d,win_yoff=%d,xsize=%d,ysize=%d",
             win_xoff, win_yoff, win_xsize, win_ysize );
     }
@@ -148,10 +148,10 @@ int CPixelInterleavedChannel::ReadBlock( int block_index, void *buffer,
             }
         }
         else
-            ThrowPCIDSKException( "Unsupported pixel type..." );
+            return ThrowPCIDSKException(0, "Unsupported pixel type..." );
     }
     
-    file->UnlockBlock( 0 );
+    file->UnlockBlock( false );
 
 /* -------------------------------------------------------------------- */
 /*      Do byte swapping if needed.                                     */
@@ -163,7 +163,7 @@ int CPixelInterleavedChannel::ReadBlock( int block_index, void *buffer,
 }
 
 template <typename T>
-void CopyPixels(const T* const src, T* const dst,
+static void CopyPixels(const T* const src, T* const dst,
                 std::size_t offset, std::size_t count)
 {
     for (std::size_t i = 0; i < count; i++)
@@ -180,7 +180,7 @@ int CPixelInterleavedChannel::WriteBlock( int block_index, void *buffer )
 
 {
     if( !file->GetUpdatable() )
-        throw PCIDSKException( "File not open for update in WriteBlock()" );
+        return ThrowPCIDSKException(0, "File not open for update in WriteBlock()" );
 
     InvalidateOverviews();
 
@@ -248,10 +248,10 @@ int CPixelInterleavedChannel::WriteBlock( int block_index, void *buffer )
             }
         }
         else
-            ThrowPCIDSKException( "Unsupported pixel type..." );
+            return ThrowPCIDSKException(0, "Unsupported pixel type..." );
     }
     
-    file->UnlockBlock( 1 );
+    file->UnlockBlock( true );
 
 /* -------------------------------------------------------------------- */
 /*      Do byte swapping if needed.                                     */
diff --git a/frmts/pcidsk/sdk/channel/cpixelinterleavedchannel.h b/frmts/pcidsk/sdk/channel/cpixelinterleavedchannel.h
index 1592111..4ec652f 100644
--- a/frmts/pcidsk/sdk/channel/cpixelinterleavedchannel.h
+++ b/frmts/pcidsk/sdk/channel/cpixelinterleavedchannel.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_CHANNEL_CPIXELINTERLEAVEDCHANNEL_H
-#define __INCLUDE_CHANNEL_CPIXELINTERLEAVEDCHANNEL_H
+#ifndef INCLUDE_CHANNEL_CPIXELINTERLEAVEDCHANNEL_H
+#define INCLUDE_CHANNEL_CPIXELINTERLEAVEDCHANNEL_H
 
 #include "pcidsk_config.h"
 #include "pcidsk_types.h"
@@ -63,4 +63,4 @@ namespace PCIDSK
     };
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_CHANNEL_CPIXELINTERLEAVEDCHANNEL_H
+#endif // INCLUDE_CHANNEL_CPIXELINTERLEAVEDCHANNEL_H
diff --git a/frmts/pcidsk/sdk/channel/ctiledchannel.cpp b/frmts/pcidsk/sdk/channel/ctiledchannel.cpp
index cbdad3b..11c299f 100644
--- a/frmts/pcidsk/sdk/channel/ctiledchannel.cpp
+++ b/frmts/pcidsk/sdk/channel/ctiledchannel.cpp
@@ -49,20 +49,20 @@ using namespace PCIDSK;
 /*                           CTiledChannel()                            */
 /************************************************************************/
 
-CTiledChannel::CTiledChannel( PCIDSKBuffer &image_header,
-                              uint64 ih_offset,
-                              CPL_UNUSED PCIDSKBuffer &file_header,
-                              int channelnum,
-                              CPCIDSKFile *file,
-                              eChanType pixel_type )
-        : CPCIDSKChannel( image_header, ih_offset, file, pixel_type, channelnum)
+CTiledChannel::CTiledChannel( PCIDSKBuffer &image_headerIn,
+                              uint64 ih_offsetIn,
+                              CPL_UNUSED PCIDSKBuffer &file_headerIn,
+                              int channelnumIn,
+                              CPCIDSKFile *fileIn,
+                              eChanType pixel_typeIn )
+        : CPCIDSKChannel( image_headerIn, ih_offsetIn, fileIn, pixel_typeIn, channelnumIn)
 {
 /* -------------------------------------------------------------------- */
 /*      Establish the virtual file we will be accessing.                */
 /* -------------------------------------------------------------------- */
     std::string filename;
 
-    image_header.Get(64,64,filename);
+    image_headerIn.Get(64,64,filename);
 
     assert( strstr(filename.c_str(),"SIS=") != NULL );
 
@@ -71,17 +71,20 @@ CTiledChannel::CTiledChannel( PCIDSKBuffer &image_header,
     vfile = NULL;
 
 /* -------------------------------------------------------------------- */
-/*      If this is an unassociated channel (ie. an overview), we        */
+/*      If this is an unassociated channel (i.e. an overview), we        */
 /*      will set the size and blocksize values to something             */
 /*      unreasonable and set them properly in EstablishAccess()         */
 /* -------------------------------------------------------------------- */
-    if( channelnum == -1 )
+    if( channelnumIn == -1 )
     {
         width = -1;
         height = -1;
         block_width = -1;
         block_height = -1;
     }
+    tile_count = 0;
+    tiles_per_row = 0;
+    tiles_per_col = 0;
 }
 
 /************************************************************************/
@@ -111,7 +114,7 @@ void CTiledChannel::EstablishAccess() const
         file->GetSegment( SEG_SYS, "SysBMDir" ));
 
     if( bmap == NULL )
-        ThrowPCIDSKException( "Unable to find SysBMDir segment." );
+        return ThrowPCIDSKException( "Unable to find SysBMDir segment." );
 
     vfile = bmap->GetVirtualFile( image );
 
@@ -134,9 +137,14 @@ void CTiledChannel::EstablishAccess() const
     pixel_type = GetDataTypeFromName(data_type);
     if (pixel_type == CHN_UNKNOWN)
     {
-        ThrowPCIDSKException( "Unknown channel type: %s", 
+        return ThrowPCIDSKException( "Unknown channel type: %s", 
                               data_type.c_str() );
     }
+    if( block_width <= 0 || block_height <= 0 )
+    {
+        return ThrowPCIDSKException( "Invalid blocksize: %d x %d", 
+                              block_width, block_height );
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Compute information on the tiles.                               */
@@ -229,7 +237,7 @@ void CTiledChannel::SaveTileInfoBlock( int block )
 
 {
     assert( tile_offsets[block].size() != 0 );
-    int tiles_in_block = tile_offsets[block].size();
+    int tiles_in_block = static_cast<int>(tile_offsets[block].size());
 
 /* -------------------------------------------------------------------- */
 /*      Write the offset and size data to disk.                         */
@@ -351,14 +359,14 @@ int CTiledChannel::ReadBlock( int block_index, void *buffer,
     if( xoff < 0 || xoff + xsize > GetBlockWidth()
         || yoff < 0 || yoff + ysize > GetBlockHeight() )
     {
-        ThrowPCIDSKException( 
+        return ThrowPCIDSKException( 0,
             "Invalid window in ReadBloc(): xoff=%d,yoff=%d,xsize=%d,ysize=%d",
             xoff, yoff, xsize, ysize );
     }
 
     if( block_index < 0 || block_index >= tile_count )
     {
-        ThrowPCIDSKException( "Requested non-existent block (%d)", 
+        return ThrowPCIDSKException( 0, "Requested non-existent block (%d)", 
                               block_index );
     }
 
@@ -433,13 +441,13 @@ int CTiledChannel::ReadBlock( int block_index, void *buffer,
     {
         RLEDecompressBlock( oCompressedData, oUncompressedData );
     }
-    else if( strncmp(compression.c_str(),"JPEG",4) == 0 )
+    else if( STARTS_WITH(compression.c_str(), "JPEG") )
     {
         JPEGDecompressBlock( oCompressedData, oUncompressedData );
     }
     else
     {
-        ThrowPCIDSKException( 
+        return ThrowPCIDSKException( 0,
             "Unable to read tile of unsupported compression type: %s",
             compression.c_str() );
     }
@@ -507,7 +515,7 @@ int CTiledChannel::WriteBlock( int block_index, void *buffer )
 
 {
     if( !file->GetUpdatable() )
-        throw PCIDSKException( "File not open for update in WriteBlock()" );
+        return ThrowPCIDSKException(0, "File not open for update in WriteBlock()" );
 
     InvalidateOverviews();
 
@@ -516,7 +524,7 @@ int CTiledChannel::WriteBlock( int block_index, void *buffer )
 
     if( block_index < 0 || block_index >= tile_count )
     {
-        ThrowPCIDSKException( "Requested non-existent block (%d)", 
+        return ThrowPCIDSKException( 0, "Requested non-existent block (%d)", 
                               block_index );
     }
 
@@ -581,13 +589,13 @@ int CTiledChannel::WriteBlock( int block_index, void *buffer )
     {
         RLECompressBlock( oUncompressedData, oCompressedData );
     }
-    else if( strncmp(compression.c_str(),"JPEG",4) == 0 )
+    else if( STARTS_WITH(compression.c_str(), "JPEG") )
     {
         JPEGCompressBlock( oUncompressedData, oCompressedData );
     }
     else
     {
-        ThrowPCIDSKException( 
+        return ThrowPCIDSKException( 0,
             "Unable to write tile of unsupported compression type: %s",
             compression.c_str() );
     }
@@ -687,7 +695,7 @@ eChanType CTiledChannel::GetType() const
 void CTiledChannel::RLEDecompressBlock( PCIDSKBuffer &oCompressedData,
                                         PCIDSKBuffer &oDecompressedData )
 
-                               
+
 {
     int    src_offset=0, dst_offset=0;
     uint8  *src = (uint8 *) oCompressedData.buffer;
@@ -696,7 +704,7 @@ void CTiledChannel::RLEDecompressBlock( PCIDSKBuffer &oCompressedData,
 
 /* -------------------------------------------------------------------- */
 /*      Process till we are out of source data, or our destination      */
-/*      buffer is full.  These conditions should be satisified at       */
+/*      buffer is full.  These conditions should be satisfied at        */
 /*      the same time!                                                  */
 /* -------------------------------------------------------------------- */
     while( src_offset + 1 + pixel_size <= oCompressedData.buffer_size
@@ -712,7 +720,7 @@ void CTiledChannel::RLEDecompressBlock( PCIDSKBuffer &oCompressedData,
 
             if( dst_offset + count * pixel_size > oDecompressedData.buffer_size)
             {
-                ThrowPCIDSKException( "RLE compressed tile corrupt, overrun avoided." );
+                return ThrowPCIDSKException( "RLE compressed tile corrupt, overrun avoided." );
             }
 
             while( count-- > 0 )
@@ -733,7 +741,7 @@ void CTiledChannel::RLEDecompressBlock( PCIDSKBuffer &oCompressedData,
             if( dst_offset + count*pixel_size > oDecompressedData.buffer_size
                 || src_offset + count*pixel_size > oCompressedData.buffer_size)
             {
-                ThrowPCIDSKException( "RLE compressed tile corrupt, overrun avoided." );
+                return ThrowPCIDSKException( "RLE compressed tile corrupt, overrun avoided." );
             }
 
             memcpy( dst + dst_offset, src + src_offset, 
@@ -750,7 +758,7 @@ void CTiledChannel::RLEDecompressBlock( PCIDSKBuffer &oCompressedData,
     if( src_offset != oCompressedData.buffer_size 
         || dst_offset != oDecompressedData.buffer_size ) 
     {
-        ThrowPCIDSKException( "RLE compressed tile corrupt, result incomplete." );
+        return ThrowPCIDSKException( "RLE compressed tile corrupt, result incomplete." );
     }
 }
 
@@ -763,7 +771,6 @@ void CTiledChannel::RLEDecompressBlock( PCIDSKBuffer &oCompressedData,
 void CTiledChannel::RLECompressBlock( PCIDSKBuffer &oUncompressedData,
                                       PCIDSKBuffer &oCompressedData )
 
-                               
 {
     int    src_bytes = oUncompressedData.buffer_size;
     int    pixel_size = DataTypeSize(GetType());
@@ -772,12 +779,12 @@ void CTiledChannel::RLECompressBlock( PCIDSKBuffer &oUncompressedData,
     uint8  *src = (uint8 *) oUncompressedData.buffer;
 
 /* -------------------------------------------------------------------- */
-/*      Loop till input exausted.                                       */
+/*      Loop till input exhausted.                                      */
 /* -------------------------------------------------------------------- */
     while( src_offset < src_bytes )
     {
         bool	bGotARun = false;
-        
+
 /* -------------------------------------------------------------------- */
 /*	Establish the run length, and emit if greater than 3. 		*/
 /* -------------------------------------------------------------------- */
@@ -881,7 +888,7 @@ void CTiledChannel::JPEGDecompressBlock( PCIDSKBuffer &oCompressedData,
                                
 {
     if( file->GetInterfaces()->JPEGDecompressBlock == NULL )
-        ThrowPCIDSKException( "JPEG decompression not enabled in the PCIDSKInterfaces of this build." );
+        return ThrowPCIDSKException( "JPEG decompression not enabled in the PCIDSKInterfaces of this build." );
 
     file->GetInterfaces()->JPEGDecompressBlock( 
         (uint8 *) oCompressedData.buffer, oCompressedData.buffer_size,
@@ -897,7 +904,7 @@ void CTiledChannel::JPEGCompressBlock( PCIDSKBuffer &oDecompressedData,
                                        PCIDSKBuffer &oCompressedData )
 {
     if( file->GetInterfaces()->JPEGCompressBlock == NULL )
-        ThrowPCIDSKException( "JPEG compression not enabled in the PCIDSKInterfaces of this build." );
+        return ThrowPCIDSKException( "JPEG compression not enabled in the PCIDSKInterfaces of this build." );
 
 /* -------------------------------------------------------------------- */
 /*      What quality should we be using?                                */
@@ -911,7 +918,7 @@ void CTiledChannel::JPEGCompressBlock( PCIDSKBuffer &oDecompressedData,
 #endif
 
 /* -------------------------------------------------------------------- */
-/*      Make the output buffer plent big to hold any conceivable        */
+/*      Make the output buffer plenty big to hold any conceivable       */
 /*      result.                                                         */
 /* -------------------------------------------------------------------- */
     oCompressedData.SetSize( oDecompressedData.buffer_size * 2 + 1000 );
diff --git a/frmts/pcidsk/sdk/channel/ctiledchannel.h b/frmts/pcidsk/sdk/channel/ctiledchannel.h
index 8263ffc..3553081 100644
--- a/frmts/pcidsk/sdk/channel/ctiledchannel.h
+++ b/frmts/pcidsk/sdk/channel/ctiledchannel.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_CHANNEL_CTILEDCHANNEL_H
-#define __INCLUDE_CHANNEL_CTILEDCHANNEL_H
+#ifndef INCLUDE_CHANNEL_CTILEDCHANNEL_H
+#define INCLUDE_CHANNEL_CTILEDCHANNEL_H
 
 #include "pcidsk_config.h"
 #include "pcidsk_types.h"
@@ -107,4 +107,4 @@ namespace PCIDSK
     };
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_CHANNEL_CTILEDCHANNEL_H
+#endif // INCLUDE_CHANNEL_CTILEDCHANNEL_H
diff --git a/frmts/pcidsk/sdk/core/clinksegment.cpp b/frmts/pcidsk/sdk/core/clinksegment.cpp
index 02627e5..9948246 100644
--- a/frmts/pcidsk/sdk/core/clinksegment.cpp
+++ b/frmts/pcidsk/sdk/core/clinksegment.cpp
@@ -39,10 +39,10 @@
 
 using namespace PCIDSK;
 
-CLinkSegment::CLinkSegment(PCIDSKFile *file, 
-                           int segment,
+CLinkSegment::CLinkSegment(PCIDSKFile *fileIn, 
+                           int segmentIn,
                            const char *segment_pointer) :
-    CPCIDSKSegment(file, segment, segment_pointer), 
+    CPCIDSKSegment(fileIn, segmentIn, segment_pointer), 
     loaded_(false), modified_(false)
 {
     Load();
@@ -63,11 +63,11 @@ void CLinkSegment::Load()
     
     assert(data_size - 1024 == 1 * 512);
     
-    seg_data.SetSize(data_size - 1024); // should be 1 * 512
+    seg_data.SetSize(static_cast<int>(data_size) - 1024); // should be 1 * 512
     
     ReadFromFile(seg_data.buffer, 0, data_size - 1024);
     
-    if (std::strncmp(seg_data.buffer, "SysLinkF", 8)) 
+    if (!STARTS_WITH(seg_data.buffer, "SysLinkF")) 
     {
         seg_data.Put("SysLinkF",0,8);
         return;
@@ -95,7 +95,7 @@ void CLinkSegment::Write(void)
     }
       
     seg_data.Put("SysLinkF",0,8);
-    seg_data.Put(path.c_str(), 8, path.size(), true);
+    seg_data.Put(path.c_str(), 8, static_cast<int>(path.size()), true);
 
     WriteToFile(seg_data.buffer, 0, data_size-1024);
     modified_ = false;
@@ -115,7 +115,7 @@ void CLinkSegment::SetPath(const std::string& oPath)
     }
     else
     {
-        throw PCIDSKException("The size of the path cannot be"
+        return ThrowPCIDSKException("The size of the path cannot be"
                               " bigger than 504 characters.");
     }
 }
diff --git a/frmts/pcidsk/sdk/core/clinksegment.h b/frmts/pcidsk/sdk/core/clinksegment.h
index 03448de..52cebf0 100644
--- a/frmts/pcidsk/sdk/core/clinksegment.h
+++ b/frmts/pcidsk/sdk/core/clinksegment.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PCIDSK_SEGMENT_CLINKSEGMENT_H
-#define __INCLUDE_PCIDSK_SEGMENT_CLINKSEGMENT_H
+#ifndef INCLUDE_PCIDSK_SEGMENT_CLINKSEGMENT_H
+#define INCLUDE_PCIDSK_SEGMENT_CLINKSEGMENT_H
 
 #include "segment/cpcidsksegment.h"
 #include "pcidsk_buffer.h"
@@ -58,4 +58,4 @@ namespace PCIDSK {
     };
 }
 
-#endif // __INCLUDE_PCIDSK_SEGMENT_CLINKSEGMENT_H
+#endif // INCLUDE_PCIDSK_SEGMENT_CLINKSEGMENT_H
diff --git a/frmts/pcidsk/sdk/core/cpcidskfile.cpp b/frmts/pcidsk/sdk/core/cpcidskfile.cpp
index 28ab9a2..f4c5c4e 100644
--- a/frmts/pcidsk/sdk/core/cpcidskfile.cpp
+++ b/frmts/pcidsk/sdk/core/cpcidskfile.cpp
@@ -77,6 +77,25 @@ CPCIDSKFile::CPCIDSKFile( std::string filename )
     io_mutex = NULL;
     updatable = false;
     base_filename = filename;
+    width = 0;
+    height = 0;
+    channel_count = 0;
+    segment_count = 0;
+    segment_pointers_offset = 0;
+    block_size = 0;
+    pixel_group_size = 0;
+    segment_count = 0;
+    segment_pointers_offset = 0;
+    block_size = 0;
+    pixel_group_size = 0;
+    first_line_offset = 0;
+    last_block_index = 0;
+    last_block_dirty = false;
+    last_block_xoff = 0;
+    last_block_xsize = 0;
+    last_block_data = NULL;
+    last_block_mutex = NULL;
+    file_size = 0;
 
 /* -------------------------------------------------------------------- */
 /*      Initialize the metadata object, but do not try to load till     */
@@ -189,7 +208,7 @@ void CPCIDSKFile::Synchronize()
     }
 
 /* -------------------------------------------------------------------- */
-/*      Ensure the file is synhronized to disk.                         */
+/*      Ensure the file is synchronized to disk.                        */
 /* -------------------------------------------------------------------- */
     MutexHolder oHolder( io_mutex );
 
@@ -204,7 +223,7 @@ PCIDSKChannel *CPCIDSKFile::GetChannel( int band )
 
 {
     if( band < 1 || band > channel_count )
-        ThrowPCIDSKException( "Out of range band (%d) requested.", 
+        return (PCIDSKChannel*)ThrowPCIDSKExceptionPtr( "Out of range band (%d) requested.", 
                               band );
 
     return channels[band-1];
@@ -262,11 +281,11 @@ PCIDSK::PCIDSKSegment *CPCIDSKFile::GetSegment( int segment )
         break;
 
       case SEG_SYS:
-        if( strncmp(segment_pointer + 4, "SysBMDir",8) == 0 )
+        if( STARTS_WITH(segment_pointer + 4, "SysBMDir") )
             segobj = new SysBlockMap( this, segment, segment_pointer );
-        else if( strncmp(segment_pointer + 4, "METADATA",8) == 0 )
+        else if( STARTS_WITH(segment_pointer + 4, "METADATA") )
             segobj = new MetadataSegment( this, segment, segment_pointer );
-        else if (strncmp(segment_pointer + 4, "Link    ", 8) == 0)
+        else if (STARTS_WITH(segment_pointer + 4, "Link    ") )
             segobj = new CLinkSegment(this, segment, segment_pointer);
         else
             segobj = new CPCIDSKSegment( this, segment, segment_pointer );
@@ -286,35 +305,35 @@ PCIDSK::PCIDSKSegment *CPCIDSKFile::GetSegment( int segment )
         break;
 
       case SEG_BIN:
-        if (!strncmp(segment_pointer + 4, "RFMODEL ", 8))
+        if (STARTS_WITH(segment_pointer + 4, "RFMODEL "))
         {
             segobj = new CPCIDSKRPCModelSegment( this, segment, segment_pointer );
         }
-        else if (!strncmp(segment_pointer + 4, "APMODEL ", 8)) 
+        else if (STARTS_WITH(segment_pointer + 4, "APMODEL ")) 
         {
             segobj = new CPCIDSKAPModelSegment(this, segment, segment_pointer);
         }
-        else if (!strncmp(segment_pointer + 4, "ADSMODEL", 8)) 
+        else if (STARTS_WITH(segment_pointer + 4, "ADSMODEL")) 
         {
             segobj = new CPCIDSKADS40ModelSegment(this, segment, segment_pointer);
         }
-        else if (!strncmp(segment_pointer + 4, "POLYMDL ", 8)) 
+        else if (STARTS_WITH(segment_pointer + 4, "POLYMDL ")) 
         {
             segobj = new CPCIDSKBinarySegment(this, segment, segment_pointer);
         }
-        else if (!strncmp(segment_pointer + 4, "TPSMODEL", 8)) 
+        else if (STARTS_WITH(segment_pointer + 4, "TPSMODEL")) 
         {
             segobj = new CPCIDSKGCP2Segment(this, segment, segment_pointer);
         }
-        else if (!strncmp(segment_pointer + 4, "MODEL   ", 8)) 
+        else if (STARTS_WITH(segment_pointer + 4, "MODEL   ")) 
         {
             segobj = new CPCIDSKToutinModelSegment(this, segment, segment_pointer);
         }
-        else if (!strncmp(segment_pointer + 4, "MMSPB   ", 8)) 
+        else if (STARTS_WITH(segment_pointer + 4, "MMSPB   ")) 
         {
             segobj = new CPCIDSKBinarySegment(this, segment, segment_pointer);
         }
-        else if (!strncmp(segment_pointer + 4, "MMADS   ", 8)) 
+        else if (STARTS_WITH(segment_pointer + 4, "MMADS   ")) 
         {
             segobj = new CPCIDSKBinarySegment(this, segment, segment_pointer);
         }
@@ -349,7 +368,7 @@ PCIDSK::PCIDSKSegment *CPCIDSKFile::GetSegment( int type, std::string name,
     //see function BuildChildrenLayer in jtfile.cpp, the call on GDBSegNext
     //in the loop on gasTypeTable can create issue in PCIDSKSegNext 
     //(in pcic/gdbfrtms/pcidskopen.cpp)
-    sprintf( type_str, "%03d", (type % 1000) );
+    snprintf( type_str, sizeof(type_str), "%03d", (type % 1000) );
 
     for( i = previous; i < segment_count; i++ )
     {
@@ -411,7 +430,7 @@ void CPCIDSKFile::InitializeFromHeader()
 
     block_size = 0;
     last_block_index = -1;
-    last_block_dirty = 0;
+    last_block_dirty = false;
     last_block_data = NULL;
     last_block_mutex = NULL;
 
@@ -459,13 +478,13 @@ void CPCIDSKFile::InitializeFromHeader()
         first_line_offset = image_offset;
         pixel_group_size = count_8u + count_16s*2 + count_16u*2 + count_32r*4;
         
-        block_size = pixel_group_size * width;
+        block_size = static_cast<PCIDSK::uint64>(pixel_group_size) * width;
         if( block_size % 512 != 0 )
             block_size += 512 - (block_size % 512);
 
         last_block_data = malloc((size_t) block_size);
         if( last_block_data == NULL )
-            ThrowPCIDSKException( "Allocating %d bytes for scanline buffer failed.", 
+            return ThrowPCIDSKException( "Allocating %d bytes for scanline buffer failed.", 
                                        (int) block_size );
 
         last_block_mutex = interfaces.CreateMutex();
@@ -502,9 +521,11 @@ void CPCIDSKFile::InitializeFromHeader()
         // if we didn't get channel type in header, work out from counts (old).
         // Check this only if we don't have complex channels:
         
-        if (strncmp(pixel_type_string,"        ",8) == 0 ) 
+        if (STARTS_WITH(pixel_type_string,"        ")) 
         {
-            assert( count_c32r == 0 && count_c16u == 0 && count_c16s == 0 );
+            if( !( count_c32r == 0 && count_c16u == 0 && count_c16s == 0 ) )
+                return ThrowPCIDSKException("Assertion 'count_c32r == 0 && count_c16u == 0 && count_c16s == 0' failed");
+
             if( channelnum <= count_8u )
                 pixel_type = CHN_8U;
             else if( channelnum <= count_8u + count_16s )
@@ -536,7 +557,7 @@ void CPCIDSKFile::InitializeFromHeader()
         }
 
         else if( interleaving == "FILE" 
-                 && strncmp(filename.c_str(),"/SIS=",5) == 0 )
+                 && STARTS_WITH(filename.c_str(),"/SIS=") )
         {
             channel = new CTiledChannel( ih, ih_offset, fh, 
                                          channelnum, this, pixel_type );
@@ -544,7 +565,7 @@ void CPCIDSKFile::InitializeFromHeader()
 
         else if( interleaving == "FILE" 
                  && filename != ""
-                 && strncmp(((const char*)ih.buffer)+250, "        ", 8 ) != 0 )
+                 && !STARTS_WITH(((const char*)ih.buffer)+250, "        ") )
         {
             channel = new CExternalChannel( ih, ih_offset, fh, filename,
                                             channelnum, this, pixel_type );
@@ -558,7 +579,7 @@ void CPCIDSKFile::InitializeFromHeader()
         }
 
         else
-            ThrowPCIDSKException( "Unsupported interleaving:%s", 
+            return ThrowPCIDSKException( "Unsupported interleaving:%s", 
                                        interleaving.c_str() );
 
         channels.push_back( channel );
@@ -576,8 +597,8 @@ void CPCIDSKFile::ReadFromFile( void *buffer, uint64 offset, uint64 size )
 
     interfaces.io->Seek( io_handle, offset, SEEK_SET );
     if( interfaces.io->Read( buffer, 1, size, io_handle ) != size )
-        ThrowPCIDSKException( "PCIDSKFile:Failed to read %d bytes at %d.", 
-                                   (int) size, (int) offset );
+        return ThrowPCIDSKException( "PCIDSKFile:Failed to read %u bytes at %u.", 
+                                   (unsigned int) size, (unsigned int) offset );
 }
 
 /************************************************************************/
@@ -594,8 +615,8 @@ void CPCIDSKFile::WriteToFile( const void *buffer, uint64 offset, uint64 size )
 
     interfaces.io->Seek( io_handle, offset, SEEK_SET );
     if( interfaces.io->Write( buffer, 1, size, io_handle ) != size )
-        ThrowPCIDSKException( "PCIDSKFile:Failed to write %d bytes at %d.",
-                                   (int) size, (int) offset );
+        return ThrowPCIDSKException( "PCIDSKFile:Failed to write %u bytes at %u.",
+                                   (unsigned int) size, (unsigned int) offset );
 }
 
 /************************************************************************/
@@ -607,7 +628,7 @@ void *CPCIDSKFile::ReadAndLockBlock( int block_index,
 
 {
     if( last_block_data == NULL )
-        ThrowPCIDSKException( "ReadAndLockBlock() called on a file that is not pixel interleaved." );
+        return ThrowPCIDSKExceptionPtr( "ReadAndLockBlock() called on a file that is not pixel interleaved." );
 
 /* -------------------------------------------------------------------- */
 /*      Default, and validate windowing.                                */
@@ -620,7 +641,7 @@ void *CPCIDSKFile::ReadAndLockBlock( int block_index,
 
     if( win_xoff < 0 || win_xoff+win_xsize > GetWidth() )
     {
-        ThrowPCIDSKException( "CPCIDSKFile::ReadAndLockBlock(): Illegal window - xoff=%d, xsize=%d", 
+        return ThrowPCIDSKExceptionPtr( "CPCIDSKFile::ReadAndLockBlock(): Illegal window - xoff=%d, xsize=%d", 
                                    win_xoff, win_xsize );
     }
 
@@ -675,10 +696,10 @@ void CPCIDSKFile::WriteBlock( int block_index, void *buffer )
 
 {
     if( !GetUpdatable() )
-        throw PCIDSKException( "File not open for update in WriteBlock()" );
+        return ThrowPCIDSKException( "File not open for update in WriteBlock()" );
 
     if( last_block_data == NULL )
-        ThrowPCIDSKException( "WriteBlock() called on a file that is not pixel interleaved." );
+        return ThrowPCIDSKException( "WriteBlock() called on a file that is not pixel interleaved." );
 
     WriteToFile( buffer,
                  first_line_offset + block_index*block_size,
@@ -698,7 +719,7 @@ void CPCIDSKFile::FlushBlock()
         if( last_block_dirty ) // is it still dirty?
         {
             WriteBlock( last_block_index, last_block_data );
-            last_block_dirty = 0;
+            last_block_dirty = false;
         }
         last_block_mutex->Release();
     }
@@ -754,8 +775,8 @@ bool CPCIDSKFile::GetEDBFileDetails( EDBFile** file_p,
         new_file.file = interfaces.OpenEDB( filename, "r" );
 
     if( new_file.file == NULL )
-        ThrowPCIDSKException( "Unable to open file '%s'.", 
-                              filename.c_str() );
+        return ThrowPCIDSKException( 0, "Unable to open file '%s'.", 
+                              filename.c_str() ) != 0;
 
 /* -------------------------------------------------------------------- */
 /*      Push the new file into the list of files managed for this       */
@@ -823,7 +844,7 @@ void CPCIDSKFile::GetIODetails( void ***io_handle_pp,
         new_file.io_handle = interfaces.io->Open( filename, "r" );
         
     if( new_file.io_handle == NULL )
-        ThrowPCIDSKException( "Unable to open file '%s'.", 
+        return ThrowPCIDSKException( "Unable to open file '%s'.", 
                               filename.c_str() );
 
 /* -------------------------------------------------------------------- */
@@ -853,7 +874,7 @@ void CPCIDSKFile::DeleteSegment( int segment )
     PCIDSKSegment *poSeg = GetSegment( segment );
 
     if( poSeg == NULL )
-        ThrowPCIDSKException( "DeleteSegment(%d) failed, segment does not exist.", segment );
+        return ThrowPCIDSKException( "DeleteSegment(%d) failed, segment does not exist.", segment );
 
 /* -------------------------------------------------------------------- */
 /*      Wipe associated metadata.                                       */
@@ -996,7 +1017,7 @@ int CPCIDSKFile::CreateSegment( std::string name, std::string description,
     }
     
     if( segment > segment_count )
-        ThrowPCIDSKException( "All %d segment pointers in use.", segment_count);
+        return ThrowPCIDSKException(0, "All %d segment pointers in use.", segment_count);
 
 /* -------------------------------------------------------------------- */
 /*      If the segment does not have a data area already, identify      */
@@ -1028,6 +1049,7 @@ int CPCIDSKFile::CreateSegment( std::string name, std::string description,
     segptr.Put( data_blocks+2, 23, 9 );
 
     // Update in memory copy of segment pointers.
+    assert(segment >= 1);
     memcpy( segment_pointers.buffer+(segment-1)*32, segptr.buffer, 32);
 
     // Update on disk. 
@@ -1080,9 +1102,9 @@ void CPCIDSKFile::ExtendFile( uint64 blocks_requested, bool prezero )
     {
         std::vector<uint8> zeros;
         uint64 blocks_to_zero = blocks_requested;
-        
+
         zeros.resize( 512 * 32 );
-        
+
         while( blocks_to_zero > 0 )
         {
             uint64 this_time = blocks_to_zero;
@@ -1186,8 +1208,8 @@ void CPCIDSKFile::MoveSegmentToEOF( int segment )
     {
         CPCIDSKSegment *seg = 
             dynamic_cast<CPCIDSKSegment *>( segments[segment] );
-
-        seg->LoadSegmentPointer( segment_pointers.buffer + segptr_off );
+        if( seg )
+            seg->LoadSegmentPointer( segment_pointers.buffer + segptr_off );
     }
 }
 
@@ -1232,7 +1254,7 @@ void CPCIDSKFile::CreateOverviews( int chan_count, int *chan_list,
     int         blocksize = 127;
     std::string compression = "NONE";
 
-    if( strncmp( layout.c_str(), "TILED", 5 ) == 0 )
+    if( STARTS_WITH( layout.c_str(), "TILED") )
     {
         ParseTileFormat( layout, blocksize, compression );
     }
@@ -1251,7 +1273,8 @@ void CPCIDSKFile::CreateOverviews( int chan_count, int *chan_list,
                        SEG_SYS, 0 );
         bm_seg = GetSegment( SEG_SYS, "SysBMDir" );
         bm = dynamic_cast<SysBlockMap *>(bm_seg);
-        bm->Initialize();
+        if( bm )
+            bm->Initialize();
     }
     else
         bm = dynamic_cast<SysBlockMap *>(bm_seg);
@@ -1280,7 +1303,7 @@ void CPCIDSKFile::CreateOverviews( int chan_count, int *chan_list,
             }
         }
 
-        if (overview_exists == false)
+        if (overview_exists == false && bm != NULL)
         {
 /* -------------------------------------------------------------------- */
 /*      Create the overview as a tiled image layer.                     */
@@ -1294,11 +1317,11 @@ void CPCIDSKFile::CreateOverviews( int chan_count, int *chan_list,
 /* -------------------------------------------------------------------- */
 /*      Attach reference to this overview as metadata.                  */
 /* -------------------------------------------------------------------- */
-            char overview_md_value[128];
             char overview_md_key[128];
+            char overview_md_value[128];
 
-            sprintf( overview_md_key, "_Overview_%d", factor );
-            sprintf( overview_md_value, "%d 0 %s",virtual_image,resampling.c_str());
+            snprintf( overview_md_key, sizeof(overview_md_key),  "_Overview_%d", factor );
+            snprintf( overview_md_value, sizeof(overview_md_value), "%d 0 %s",virtual_image,resampling.c_str());
                      
             channel->SetMetadataValue( overview_md_key, overview_md_value );
         }
@@ -1306,7 +1329,9 @@ void CPCIDSKFile::CreateOverviews( int chan_count, int *chan_list,
 /* -------------------------------------------------------------------- */
 /*      Force channel to invalidate it's loaded overview list.          */
 /* -------------------------------------------------------------------- */
-        dynamic_cast<CPCIDSKChannel *>(channel)->InvalidateOverviewInfo();
+        CPCIDSKChannel* cpcidskchannel = dynamic_cast<CPCIDSKChannel *>(channel);
+        if( cpcidskchannel )
+            cpcidskchannel->InvalidateOverviewInfo();
     }
 }
 
diff --git a/frmts/pcidsk/sdk/core/cpcidskfile.h b/frmts/pcidsk/sdk/core/cpcidskfile.h
index af5af91..d62fa20 100644
--- a/frmts/pcidsk/sdk/core/cpcidskfile.h
+++ b/frmts/pcidsk/sdk/core/cpcidskfile.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PRIV_CPCIDSKFILE_H
-#define __INCLUDE_PRIV_CPCIDSKFILE_H
+#ifndef INCLUDE_PRIV_CPCIDSKFILE_H
+#define INCLUDE_PRIV_CPCIDSKFILE_H
 
 #include "pcidsk_config.h"
 #include "pcidsk_types.h"
@@ -158,4 +158,4 @@ namespace PCIDSK
     };
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_PRIV_CPCIDSKFILE_H
+#endif // INCLUDE_PRIV_CPCIDSKFILE_H
diff --git a/frmts/pcidsk/sdk/core/libjpeg_io.cpp b/frmts/pcidsk/sdk/core/libjpeg_io.cpp
index 91cc2d6..16757f3 100644
--- a/frmts/pcidsk/sdk/core/libjpeg_io.cpp
+++ b/frmts/pcidsk/sdk/core/libjpeg_io.cpp
@@ -60,7 +60,7 @@ static void JpegError(j_common_ptr cinfo)
     char buf[256];
 
     cinfo->err->format_message(cinfo, buf);
-    ThrowPCIDSKException( "%s", buf );
+    return ThrowPCIDSKException( "%s", buf );
 }
 
 /************************************************************************/
@@ -75,12 +75,12 @@ void PCIDSK::LibJPEG_DecompressBlock(
     struct jpeg_source_mgr	sSrcMgr;
     struct jpeg_error_mgr	sErrMgr;
 
-    int				i;
+    int i;
 
 /* -------------------------------------------------------------------- */
 /*      Setup the buffer we will compress into.  We make it pretty      */
 /*      big to ensure there is space.  The calling function will        */
-/*      free it as soon as it is done so this shouldn't hurt much.      */
+/*      free it as soon as it is done so this should not hurt much.     */
 /* -------------------------------------------------------------------- */
     sSrcMgr.init_source = _DummySrcMgrMethod;
     sSrcMgr.fill_input_buffer = (boolean (*)(j_decompress_ptr))
@@ -109,7 +109,7 @@ void PCIDSK::LibJPEG_DecompressBlock(
     if (sJCompInfo.image_width != (unsigned int)xsize ||
         sJCompInfo.image_height != (unsigned int)ysize)
     {
-        ThrowPCIDSKException("Tile Size wrong in LibJPEG_DecompressTile(), got %dx%d, expected %dx%d.",
+        return ThrowPCIDSKException("Tile Size wrong in LibJPEG_DecompressTile(), got %dx%d, expected %dx%d.",
                              sJCompInfo.image_width,
                              sJCompInfo.image_height,
                              xsize, ysize );
@@ -191,7 +191,7 @@ void PCIDSK::LibJPEG_CompressBlock(
 /* -------------------------------------------------------------------- */
     jpeg_finish_compress( &sJCompInfo );
 
-    dst_bytes = dst_bytes - sDstMgr.free_in_buffer;
+    dst_bytes = static_cast<int>(dst_bytes - sDstMgr.free_in_buffer);
     
     jpeg_destroy_compress( &sJCompInfo );
 }
diff --git a/frmts/pcidsk/sdk/core/metadataset.h b/frmts/pcidsk/sdk/core/metadataset.h
index 2c2f63b..fd3dad5 100644
--- a/frmts/pcidsk/sdk/core/metadataset.h
+++ b/frmts/pcidsk/sdk/core/metadataset.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PRIV_METADATASET_H
-#define __INCLUDE_PRIV_METADATASET_H
+#ifndef INCLUDE_PRIV_METADATASET_H
+#define INCLUDE_PRIV_METADATASET_H
 
 #include "pcidsk_config.h"
 #include "pcidsk_file.h"
@@ -64,4 +64,4 @@ namespace PCIDSK
     };
     
 } // end namespace PCIDSK
-#endif // __INCLUDE_PRIV_METADATASET_H
+#endif // INCLUDE_PRIV_METADATASET_H
diff --git a/frmts/pcidsk/sdk/core/metadataset_p.cpp b/frmts/pcidsk/sdk/core/metadataset_p.cpp
index 31da995..a301621 100644
--- a/frmts/pcidsk/sdk/core/metadataset_p.cpp
+++ b/frmts/pcidsk/sdk/core/metadataset_p.cpp
@@ -63,12 +63,12 @@ MetadataSet::~MetadataSet()
 /*                             Initialize()                             */
 /************************************************************************/
 
-void MetadataSet::Initialize( PCIDSKFile *file, const std::string& group, int id )
+void MetadataSet::Initialize( PCIDSKFile *fileIn, const std::string& groupIn, int idIn )
 
 {
-    this->file = file;
-    this->group = group;
-    this->id = id;
+    this->file = fileIn;
+    this->group = groupIn;
+    this->id = idIn;
 }
 
 /************************************************************************/
@@ -98,8 +98,8 @@ void MetadataSet::Load()
     }
 
     MetadataSegment *md_seg = dynamic_cast<MetadataSegment *>( seg );
-
-    md_seg->FetchGroupMetadata( group.c_str(), id, md_set );
+    if( md_seg )
+        md_seg->FetchGroupMetadata( group.c_str(), id, md_set );
     loaded = true;
 }
 
@@ -130,7 +130,7 @@ void MetadataSet::SetMetadataValue( const std::string& key, const std::string& v
 
     if( file == NULL )
     {
-        ThrowPCIDSKException( "Attempt to set metadata on an unassociated MetadataSet, likely an overview channel." );
+        return ThrowPCIDSKException( "Attempt to set metadata on an unassociated MetadataSet, likely an overview channel." );
     }
 
     md_set[key] = value;
@@ -146,8 +146,8 @@ void MetadataSet::SetMetadataValue( const std::string& key, const std::string& v
     }
 
     MetadataSegment *md_seg = dynamic_cast<MetadataSegment *>( seg );
-
-    md_seg->SetGroupMetadataValue( group.c_str(), id, key, value );
+    if( md_seg )
+        md_seg->SetGroupMetadataValue( group.c_str(), id, key, value );
 }
 
 /************************************************************************/
diff --git a/frmts/pcidsk/sdk/core/mutexholder.h b/frmts/pcidsk/sdk/core/mutexholder.h
index 707c319..a507b27 100644
--- a/frmts/pcidsk/sdk/core/mutexholder.h
+++ b/frmts/pcidsk/sdk/core/mutexholder.h
@@ -25,8 +25,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_CORE_MUTEXHOLDER_H
-#define __INCLUDE_CORE_MUTEXHOLDER_H
+#ifndef INCLUDE_CORE_MUTEXHOLDER_H
+#define INCLUDE_CORE_MUTEXHOLDER_H
 
 #include "pcidsk_mutex.h"
 
@@ -38,9 +38,9 @@ namespace PCIDSK
     class PCIDSK_DLL MutexHolder
     {
     public:
-        MutexHolder( Mutex *mutex ) 
+        MutexHolder( Mutex *mutexIn ) 
         { 
-            this->mutex = mutex; 
+            this->mutex = mutexIn; 
             if( mutex != NULL )
                 mutex->Acquire(); 
         }
@@ -57,4 +57,4 @@ namespace PCIDSK
 
 } //end namespace PCIDSK
 
-#endif // __INCLUDE_CORE_MUTEXHOLDER_H
+#endif // INCLUDE_CORE_MUTEXHOLDER_H
diff --git a/frmts/pcidsk/sdk/core/pcidsk_pubutils.cpp b/frmts/pcidsk/sdk/core/pcidsk_pubutils.cpp
index 1d6aa12..c5385c1 100644
--- a/frmts/pcidsk/sdk/core/pcidsk_pubutils.cpp
+++ b/frmts/pcidsk/sdk/core/pcidsk_pubutils.cpp
@@ -85,7 +85,7 @@ int PCIDSK::DataTypeSize( eChanType chan_type )
  * Return name for the data type.
  *
  * The returned values are suitable for display to people, and matches
- * the portion of the name after the underscore (ie. "8U" for CHN_8U.
+ * the portion of the name after the underscore (i.e. "8U" for CHN_8U.
  *
  * @param chan_type the channel type enumeration value to be translated.
  *
@@ -184,9 +184,9 @@ bool PCIDSK::IsDataTypeComplex(eChanType type)
  * Return name for segment type.
  *
  * Returns a short name for the segment type code passed in.  This is normally
- * the portion of the enumeration name that comes after the underscore - ie. 
- * "BIT" for SEG_BIT. 
- * 
+ * the portion of the enumeration name that comes after the underscore - i.e.
+ * "BIT" for SEG_BIT.
+ *
  * @param type the segment type code.
  *
  * @return the string for the segment type.
diff --git a/frmts/pcidsk/sdk/core/pcidsk_utils.cpp b/frmts/pcidsk/sdk/core/pcidsk_utils.cpp
index a3f5231..728bd6c 100644
--- a/frmts/pcidsk/sdk/core/pcidsk_utils.cpp
+++ b/frmts/pcidsk/sdk/core/pcidsk_utils.cpp
@@ -98,7 +98,7 @@ std::string &PCIDSK::UCaseStr( std::string &target )
         if( islower(target[i]) )
             target[i] = (char) toupper(target[i]);
     }
-    
+
     return target;
 }
 
@@ -134,9 +134,9 @@ int64 PCIDSK::atoint64( const char *str_value )
 /*                            SwapPixels()                              */
 /************************************************************************/
 /**
- * @brief Perform an endianess swap for a given buffer of pixels
+ * @brief Perform an endianness swap for a given buffer of pixels
  *
- * Baed on the provided data type, do an appropriate endianess swap for
+ * Baed on the provided data type, do an appropriate endianness swap for
  * a buffer of pixels. Deals with the Complex case specially, in
  * particular.
  *
@@ -153,15 +153,15 @@ void PCIDSK::SwapPixels(void* const data,
     case CHN_16U:
     case CHN_16S:
     case CHN_32R:
-        SwapData(data, DataTypeSize(type), count);
+        SwapData(data, DataTypeSize(type), static_cast<int>(count));
         break;
     case CHN_C16U:
     case CHN_C16S:
     case CHN_C32R:
-        SwapData(data, DataTypeSize(type) / 2, count * 2);
+        SwapData(data, DataTypeSize(type) / 2, static_cast<int>(count) * 2);
         break;
     default:
-        ThrowPCIDSKException("Unknown data type passed to SwapPixels."
+        return ThrowPCIDSKException("Unknown data type passed to SwapPixels."
             "This is a software bug. Please contact your vendor.");
     }
 }
@@ -234,7 +234,7 @@ void PCIDSK::SwapData( void* const data, const int size, const int wcount )
         }
     }
     else
-        ThrowPCIDSKException( "Unsupported data size in SwapData()" );
+        return ThrowPCIDSKException( "Unsupported data size in SwapData()" );
 }
 
 /************************************************************************/
@@ -273,7 +273,7 @@ void PCIDSK::ParseTileFormat( std::string full_text,
 /* -------------------------------------------------------------------- */
 /*      Only operate on tiled stuff.                                    */
 /* -------------------------------------------------------------------- */
-    if( strncmp(full_text.c_str(),"TILED",5) != 0 )
+    if( !STARTS_WITH(full_text.c_str(), "TILED") )
         return;
 
 /* -------------------------------------------------------------------- */
@@ -287,7 +287,7 @@ void PCIDSK::ParseTileFormat( std::string full_text,
         while( isdigit(*next_text) )
             next_text++;
     }
-    
+
     while( *next_text == ' ' )
         next_text++;
 
@@ -300,16 +300,16 @@ void PCIDSK::ParseTileFormat( std::string full_text,
         if (compression == "NO_WARNINGS")
             compression = "";
         else if( compression != "RLE"
-            && strncmp(compression.c_str(),"JPEG",4) != 0 
+            && !STARTS_WITH(compression.c_str(), "JPEG") 
             && compression != "NONE"
             && compression != "QUADTREE" )
         {
-            ThrowPCIDSKException( "Unsupported tile compression scheme '%s' requested.",
+            return ThrowPCIDSKException( "Unsupported tile compression scheme '%s' requested.",
                                   compression.c_str() );
         }
     }    
 }
-                      
+
 /************************************************************************/
 /*                           pci_strcasecmp()                           */
 /************************************************************************/
@@ -347,12 +347,10 @@ int PCIDSK::pci_strcasecmp( const char *string1, const char *string2 )
 /*                          pci_strncasecmp()                           */
 /************************************************************************/
 
-int PCIDSK::pci_strncasecmp( const char *string1, const char *string2, int len )
+int PCIDSK::pci_strncasecmp( const char *string1, const char *string2, size_t len )
 
 {
-    int i;
-
-    for( i = 0; i < len; i++ )
+    for( size_t i = 0; i < len; i++ )
     {
         if( string1[i] == '\0' && string2[i] == '\0' )
             return 0;
@@ -391,9 +389,8 @@ std::vector<double> PCIDSK::ProjParmsFromText( std::string geosys,
 
 {
     std::vector<double> dparms;
-    const char *next = sparms.c_str();
 
-    for( next = sparms.c_str(); *next != '\0'; )
+    for( const char* next = sparms.c_str(); *next != '\0'; )
     {
         dparms.push_back( CPLAtof(next) );
 
@@ -409,25 +406,25 @@ std::vector<double> PCIDSK::ProjParmsFromText( std::string geosys,
     dparms.resize(18);
 
     // This is rather iffy!
-    if( EQUALN(geosys.c_str(),"DEGREE",3) )
+    if( STARTS_WITH_CI(geosys.c_str(),"DEG" /* "DEGREE" */) )
         dparms[17] = (double) (int) UNIT_DEGREE;
-    else if( EQUALN(geosys.c_str(),"MET",3) )
+    else if( STARTS_WITH_CI(geosys.c_str(), "MET") )
         dparms[17] = (double) (int) UNIT_METER;
-    else if( EQUALN(geosys.c_str(),"FOOT",4) )
+    else if( STARTS_WITH_CI(geosys.c_str(), "FOOT") )
         dparms[17] = (double) (int) UNIT_US_FOOT;
-    else if( EQUALN(geosys.c_str(),"FEET",4) )
+    else if( STARTS_WITH_CI(geosys.c_str(), "FEET") )
         dparms[17] = (double) (int) UNIT_US_FOOT;
-    else if( EQUALN(geosys.c_str(),"INTL FOOT",5) )
+    else if( STARTS_WITH_CI(geosys.c_str(),"INTL " /* "INTL FOOT" */) )
         dparms[17] = (double) (int) UNIT_INTL_FOOT;
-    else if( EQUALN(geosys.c_str(),"SPCS",4) )
+    else if( STARTS_WITH_CI(geosys.c_str(), "SPCS") )
         dparms[17] = (double) (int) UNIT_METER;
-    else if( EQUALN(geosys.c_str(),"SPIF",4) )
+    else if( STARTS_WITH_CI(geosys.c_str(), "SPIF") )
         dparms[17] = (double) (int) UNIT_INTL_FOOT;
-    else if( EQUALN(geosys.c_str(),"SPAF",4) )
+    else if( STARTS_WITH_CI(geosys.c_str(), "SPAF") )
         dparms[17] = (double) (int) UNIT_US_FOOT;
     else
         dparms[17] = -1.0; /* unknown */
-    
+
     return dparms;
 }
 
@@ -438,10 +435,9 @@ std::vector<double> PCIDSK::ProjParmsFromText( std::string geosys,
 std::string PCIDSK::ProjParmsToText( std::vector<double> dparms )
 
 {
-    unsigned int i;
     std::string sparms;
 
-    for( i = 0; i < 17; i++ )
+    for( unsigned int i = 0; i < 17; i++ )
     {
         char value[64];
         double dvalue;
@@ -452,13 +448,13 @@ std::string PCIDSK::ProjParmsToText( std::vector<double> dparms )
             dvalue = 0.0;
 
         if( dvalue == floor(dvalue) )
-            sprintf( value, "%d", (int) dvalue );
+            CPLsnprintf( value, sizeof(value), "%d", (int) dvalue );
         else
-            CPLsprintf( value, "%.15g", dvalue );
-        
+            CPLsnprintf( value, sizeof(value), "%.15g", dvalue );
+
         if( i > 0 )
             sparms += " ";
-        
+
         sparms += value;
     }
 
@@ -470,7 +466,7 @@ std::string PCIDSK::ProjParmsToText( std::vector<double> dparms )
 /*                                                                      */
 /*      Extract the directory path portion of the passed filename.      */
 /*      It assumes the last component is a filename and should not      */
-/*      be passed a bare path.  The trailing directory delimeter is     */
+/*      be passed a bare path.  The trailing directory delimiter is     */
 /*      removed from the result.  The return result is an empty         */
 /*      string for a simple filename passed in with no directory        */
 /*      component.                                                      */
@@ -481,7 +477,7 @@ std::string PCIDSK::ExtractPath( std::string filename )
 {
     int i;
 
-    for( i = filename.size()-1; i >= 0; i-- )
+    for( i = static_cast<int>(filename.size())-1; i >= 0; i-- )
     {
         if( filename[i] == '\\' || filename[i] == '/' )
             break;
@@ -568,7 +564,7 @@ void PCIDSK::DefaultDebug( const char * message )
 {
     static bool initialized = false;
     static bool enabled = false;
-    
+
     if( !initialized )
     {
         if( getenv( "PCIDSK_DEBUG" ) != NULL )
@@ -622,7 +618,7 @@ static void vDebug( void (*pfnDebug)(const char *),
 #else
     wrk_args = args;
 #endif
-    
+
     nPR = vsnprintf( szModestBuffer, sizeof(szModestBuffer), fmt, 
                      wrk_args );
     if( nPR == -1 || nPR >= (int) sizeof(szModestBuffer)-1 )
diff --git a/frmts/pcidsk/sdk/core/pcidsk_utils.h b/frmts/pcidsk/sdk/core/pcidsk_utils.h
index 2f553db..d7c580f 100644
--- a/frmts/pcidsk/sdk/core/pcidsk_utils.h
+++ b/frmts/pcidsk/sdk/core/pcidsk_utils.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_CORE_PCIDSK_UTILS_H
-#define __INCLUDE_CORE_PCIDSK_UTILS_H
+#ifndef INCLUDE_CORE_PCIDSK_UTILS_H
+#define INCLUDE_CORE_PCIDSK_UTILS_H
 
 #include "pcidsk_config.h"
 #include "pcidsk_types.h"
@@ -44,10 +44,16 @@ namespace PCIDSK
     uint64 atouint64( const char *);
     int64  atoint64( const char *);
     int    pci_strcasecmp( const char *, const char * );
-    int    pci_strncasecmp( const char *, const char *, int );
+    int    pci_strncasecmp( const char *, const char *, size_t );
 
+#ifndef EQUAL
 #define EQUAL(x,y) (pci_strcasecmp(x,y) == 0)
 #define EQUALN(x,y,n) (pci_strncasecmp(x,y,n) == 0)
+#endif
+#ifndef STARTS_WITH_CI
+#define STARTS_WITH_CI(x,y) EQUALN(x,y,strlen(y))
+#define STARTS_WITH(x,y) (std::strncmp(x,y,strlen(y)) == 0)
+#endif
   
     void   SwapData( void* const data, const int size, const int wcount );
     bool   BigEndianSystem(void);
@@ -76,8 +82,8 @@ namespace PCIDSK
         int xsize, int ysize, eChanType pixel_type, int quality );
 
     void                DefaultDebug( const char * );
-    void                Debug( void (*)(const char *), const char *fmt, ... );
+    void                Debug( void (*)(const char *), const char *fmt, ... ) PCIDSK_PRINT_FUNC_FORMAT(2,3);
 
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_CORE_PCIDSK_UTILS_H
+#endif // INCLUDE_CORE_PCIDSK_UTILS_H
diff --git a/frmts/pcidsk/sdk/core/pcidskbuffer.cpp b/frmts/pcidsk/sdk/core/pcidskbuffer.cpp
index cffd4bb..2810924 100644
--- a/frmts/pcidsk/sdk/core/pcidskbuffer.cpp
+++ b/frmts/pcidsk/sdk/core/pcidskbuffer.cpp
@@ -89,18 +89,18 @@ void PCIDSKBuffer::SetSize( int size )
 
 {
     buffer_size = size;
-    if( buffer == NULL )
-        buffer = (char *) malloc(size+1);
-    else
-        buffer = (char *) realloc(buffer,size+1);
+    char* new_buffer = (char *) realloc(buffer,size+1);
 
-    if( buffer == NULL )
+    if( new_buffer == NULL )
     {
+        free( buffer );
+        buffer = NULL;
         buffer_size = 0;
-        ThrowPCIDSKException( "Out of memory allocating %d byte PCIDSKBuffer.",
+        throw PCIDSKException( "Out of memory allocating %d byte PCIDSKBuffer.",
                                size );
     }
 
+    buffer = new_buffer;
     buffer[size] = '\0';
 }
 
@@ -123,7 +123,7 @@ void PCIDSKBuffer::Get( int offset, int size, std::string &target, int unpad ) c
 
 {
     if( offset + size > buffer_size )
-        ThrowPCIDSKException( "Get() past end of PCIDSKBuffer." );
+        return ThrowPCIDSKException( "Get() past end of PCIDSKBuffer." );
 
     if( unpad )
     {
@@ -144,7 +144,7 @@ uint64 PCIDSKBuffer::GetUInt64( int offset, int size ) const
     std::string value_str;
 
     if( offset + size > buffer_size )
-        ThrowPCIDSKException( "GetUInt64() past end of PCIDSKBuffer." );
+        return ThrowPCIDSKException(0, "GetUInt64() past end of PCIDSKBuffer." );
 
     value_str.assign( buffer + offset, size );
 
@@ -161,7 +161,7 @@ int PCIDSKBuffer::GetInt( int offset, int size ) const
     std::string value_str;
 
     if( offset + size > buffer_size )
-        ThrowPCIDSKException( "GetInt() past end of PCIDSKBuffer." );
+        return ThrowPCIDSKException(0, "GetInt() past end of PCIDSKBuffer." );
 
     value_str.assign( buffer + offset, size );
 
@@ -178,7 +178,7 @@ double PCIDSKBuffer::GetDouble( int offset, int size ) const
     std::string value_str;
 
     if( offset + size > buffer_size )
-        ThrowPCIDSKException( "GetDouble() past end of PCIDSKBuffer." );
+        return ThrowPCIDSKException(0, "GetDouble() past end of PCIDSKBuffer." );
 
     value_str.assign( buffer + offset, size );
 
@@ -213,9 +213,9 @@ void PCIDSKBuffer::Put( const char *value, int offset, int size, bool null_term
 
 {
     if( offset + size > buffer_size )
-        ThrowPCIDSKException( "Put() past end of PCIDSKBuffer." );
+        return ThrowPCIDSKException( "Put() past end of PCIDSKBuffer." );
 
-    int v_size = strlen(value);
+    int v_size = static_cast<int>(strlen(value));
     if( v_size > size )
         v_size = size;
 
@@ -250,8 +250,8 @@ void PCIDSKBuffer::Put( uint64 value, int offset, int size )
     char fmt[64];
     char wrk[128];
 
-    sprintf( fmt, "%%%d%sd", size, PCIDSK_FRMT_64_WITHOUT_PREFIX );
-    sprintf( wrk, fmt, value );
+    snprintf( fmt, sizeof(fmt), "%%%d%sd", size, PCIDSK_FRMT_64_WITHOUT_PREFIX );
+    snprintf( wrk, sizeof(wrk), fmt, value );
 
     Put( wrk, offset, size );
 }
diff --git a/frmts/pcidsk/sdk/core/pcidskcreate.cpp b/frmts/pcidsk/sdk/core/pcidskcreate.cpp
index ea574d9..4d2eb75 100644
--- a/frmts/pcidsk/sdk/core/pcidskcreate.cpp
+++ b/frmts/pcidsk/sdk/core/pcidskcreate.cpp
@@ -95,20 +95,20 @@ PCIDSK::Create( std::string filename, int pixels, int lines,
 
     UCaseStr( options );
 
-    if(strncmp(options.c_str(),"PIXEL",5) == 0 )
+    if(STARTS_WITH(options.c_str(), "PIXEL") )
         interleaving = "PIXEL";
-    else if( strncmp(options.c_str(),"BAND",4) == 0 )
+    else if( STARTS_WITH(options.c_str(), "BAND") )
         interleaving = "BAND";
-    else if( strncmp(options.c_str(),"TILED",5) == 0 )
+    else if( STARTS_WITH(options.c_str(), "TILED") )
     {
         interleaving = "FILE";
         ParseTileFormat( options, blocksize, compression );
     }
-    else if( strncmp(options.c_str(),"FILE",4) == 0 )
+    else if( STARTS_WITH(options.c_str(), "FILE") )
     {
-        if( strncmp(options.c_str(),"FILENOCREATE",12) == 0 )
+        if( STARTS_WITH(options.c_str(), "FILENOCREATE") )
             nocreate = true;
-        else if( strncmp(options.c_str(),"FILELINK",8) == 0 )
+        else if( STARTS_WITH(options.c_str(), "FILELINK") )
         {
             nocreate = true;
             externallink = true;
@@ -116,7 +116,7 @@ PCIDSK::Create( std::string filename, int pixels, int lines,
         interleaving = "FILE";
     }
     else
-        ThrowPCIDSKException( "PCIDSK::Create() options '%s' not recognised.",
+        return (PCIDSKFile*)ThrowPCIDSKExceptionPtr( "PCIDSK::Create() options '%s' not recognised.",
                               options.c_str() );
 #if 0
     if( strstr(options.c_str(),"NOZERO") != NULL )
@@ -142,7 +142,7 @@ PCIDSK::Create( std::string filename, int pixels, int lines,
     
     if( !regular && strcmp(interleaving,"FILE") != 0 )
     {
-        ThrowPCIDSKException( 
+        return (PCIDSKFile*)ThrowPCIDSKExceptionPtr( 
            "Requested mixture of band types not supported for interleaving=%s.",
            interleaving );
     }
@@ -281,7 +281,7 @@ PCIDSK::Create( std::string filename, int pixels, int lines,
     // FH14 - interleaving.
     fh.Put( interleaving, 360, 8);
 
-    // FH15 - reserved - MIXED is for some ancient backwards compatability.
+    // FH15 - reserved - MIXED is for some ancient backwards compatibility.
     fh.Put( "MIXED", 368, 8);
 
     // FH16 - number of image bands.
@@ -295,7 +295,7 @@ PCIDSK::Create( std::string filename, int pixels, int lines,
 
     // FH19 - pixel ground size interpretation.
     fh.Put( "METRE", 400, 8 );
-    
+
     // TODO:
     //PrintDouble( fh->XPixelSize, "%16.9f", 1.0 );
     //PrintDouble( fh->YPixelSize, "%16.9f", 1.0 );
@@ -351,8 +351,8 @@ PCIDSK::Create( std::string filename, int pixels, int lines,
     ih.Put( "Contents Not Specified", 0, 64 );
 
     // IHi.2 - Filename storing image.
-    if( strncmp(interleaving,"FILE",4) == 0 )
-        ih.Put( "<unintialized>", 64, 64 );
+    if( STARTS_WITH(interleaving, "FILE") )
+        ih.Put( "<unintialized>", 64, 64 );  // TODO: Spelling?
     
     if( externallink )
     {
@@ -375,10 +375,10 @@ PCIDSK::Create( std::string filename, int pixels, int lines,
     {
         ih.Put(DataTypeName(channel_types[chan_index]).c_str(), 160, 8);    
 
-        if( strncmp("TILED",options.c_str(),5) == 0 )
+        if( STARTS_WITH(options.c_str(), "TILED") )
         {
             char sis_filename[65];
-            sprintf( sis_filename, "/SIS=%d", chan_index );
+            snprintf( sis_filename, sizeof(sis_filename), "/SIS=%d", chan_index );
             ih.Put( sis_filename, 64, 64 );
 
             // IHi.6.7 - IHi.6.10
@@ -399,7 +399,7 @@ PCIDSK::Create( std::string filename, int pixels, int lines,
          chan_index++ )
     {
         ih.Put( "", 160, 8 );
-        ih.Put( "<unintialized>", 64, 64 );
+        ih.Put( "<unintialized>", 64, 64 );  // TODO: Spelling?
         ih.Put( "", 250, 40 );
 
         interfaces->io->Write( ih.buffer, 1024, 1, io_handle );
@@ -443,7 +443,7 @@ PCIDSK::Create( std::string filename, int pixels, int lines,
 /* -------------------------------------------------------------------- */
 /*      If the dataset is tiled, create the file band data.             */
 /* -------------------------------------------------------------------- */
-    if( strncmp(options.c_str(),"TILED",5) == 0 )
+    if( STARTS_WITH(options.c_str(), "TILED") )
     {
         file->SetMetadataValue( "_DBLayout", options ); 
 
@@ -463,7 +463,7 @@ PCIDSK::Create( std::string filename, int pixels, int lines,
         sysbmdir_size = (int) (sysbmdir_size * 1.1 + 100);
         int segment = file->CreateSegment( "SysBMDir", 
                                            "System Block Map Directory - Do not modify.",
-                                           SEG_SYS, sysbmdir_size );
+                                           SEG_SYS, static_cast<int>(sysbmdir_size) );
         
         SysBlockMap *bm = 
             dynamic_cast<SysBlockMap *>(file->GetSegment( segment ));
@@ -480,8 +480,8 @@ PCIDSK::Create( std::string filename, int pixels, int lines,
 /*      If we have a non-tiled FILE interleaved file, should we         */
 /*      create external band files now?                                 */
 /* -------------------------------------------------------------------- */
-    if( strncmp(interleaving,"FILE",4) == 0 
-        && strncmp(options.c_str(),"TILED",5) != 0 
+    if( STARTS_WITH(interleaving, "FILE") 
+        && !STARTS_WITH(options.c_str(), "TILED") 
         && !nocreate )
     {
         for( chan_index = 0; chan_index < channel_count; chan_index++ )
@@ -493,7 +493,7 @@ PCIDSK::Create( std::string filename, int pixels, int lines,
             // file, and adds ".nnn" based on the band. 
             std::string band_filename = filename;
             char ext[5];
-            sprintf( ext, ".%03d", chan_index+1 );
+            snprintf( ext, sizeof(ext), ".%03d", chan_index+1 );
             
             size_t last_dot = band_filename.find_last_of(".");
             if( last_dot != std::string::npos 
diff --git a/frmts/pcidsk/sdk/core/pcidskexception.cpp b/frmts/pcidsk/sdk/core/pcidskexception.cpp
index ac74dd3..6badee9 100644
--- a/frmts/pcidsk/sdk/core/pcidskexception.cpp
+++ b/frmts/pcidsk/sdk/core/pcidskexception.cpp
@@ -210,7 +210,33 @@ void PCIDSK::ThrowPCIDSKException( const char *fmt, ... )
 
 {
     std::va_list args;
-    PCIDSKException ex("");
+    PCIDSKException ex;
+
+    va_start( args, fmt );
+    ex.vPrintf( fmt, args );
+    va_end( args );
+
+    throw ex;
+}
+
+int PCIDSK::ThrowPCIDSKException( int /*ret_unused*/, const char *fmt, ... )
+
+{
+    std::va_list args;
+    PCIDSKException ex;
+
+    va_start( args, fmt );
+    ex.vPrintf( fmt, args );
+    va_end( args );
+
+    throw ex;
+}
+
+void* PCIDSK::ThrowPCIDSKExceptionPtr( const char *fmt, ... )
+
+{
+    std::va_list args;
+    PCIDSKException ex;
 
     va_start( args, fmt );
     ex.vPrintf( fmt, args );
diff --git a/frmts/pcidsk/sdk/core/pcidskopen.cpp b/frmts/pcidsk/sdk/core/pcidskopen.cpp
index eb7c8c6..6bc867c 100644
--- a/frmts/pcidsk/sdk/core/pcidskopen.cpp
+++ b/frmts/pcidsk/sdk/core/pcidskopen.cpp
@@ -79,7 +79,7 @@ PCIDSKFile *PCIDSK::Open( std::string filename, std::string access,
         || memcmp(header_check,"PCIDSK",6) != 0 )
     {
         interfaces->io->Close( io_handle );
-        ThrowPCIDSKException( "File %s does not appear to be PCIDSK format.",
+        return (PCIDSKFile*)ThrowPCIDSKExceptionPtr( "File %s does not appear to be PCIDSK format.",
                               filename.c_str() );
     }
 
diff --git a/frmts/pcidsk/sdk/core/protectedfile.h b/frmts/pcidsk/sdk/core/protectedfile.h
index c8c4406..4a0ccd0 100644
--- a/frmts/pcidsk/sdk/core/protectedfile.h
+++ b/frmts/pcidsk/sdk/core/protectedfile.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_CORE_PROTECTEDFILE_H
-#define __INCLUDE_CORE_PROTECTEDFILE_H
+#ifndef INCLUDE_CORE_PROTECTEDFILE_H
+#define INCLUDE_CORE_PROTECTEDFILE_H
 
 namespace PCIDSK
 {
@@ -54,4 +54,4 @@ namespace PCIDSK
 
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_CORE_PROTECTEDFILE_H
+#endif // INCLUDE_CORE_PROTECTEDFILE_H
diff --git a/frmts/pcidsk/sdk/core/sysvirtualfile.cpp b/frmts/pcidsk/sdk/core/sysvirtualfile.cpp
index a149019..c8e8f1f 100644
--- a/frmts/pcidsk/sdk/core/sysvirtualfile.cpp
+++ b/frmts/pcidsk/sdk/core/sysvirtualfile.cpp
@@ -59,19 +59,19 @@ const int SysVirtualFile::block_size = SYSVIRTUALFILE_BLOCKSIZE;
 /*                           SysVirtualFile()                           */
 /************************************************************************/
 
-SysVirtualFile::SysVirtualFile( CPCIDSKFile *file, int start_block, 
+SysVirtualFile::SysVirtualFile( CPCIDSKFile *fileIn, int start_block, 
                                 uint64 image_length, 
-                                SysBlockMap *sysblockmap,
-                                int image_index )
+                                SysBlockMap *sysblockmapIn,
+                                int image_indexIn )
 
 {
     io_handle = NULL;
     io_mutex = NULL;
 
     file_length = image_length;
-    this->file = file;
-    this->sysblockmap = sysblockmap;
-    this->image_index = image_index;
+    this->file = fileIn;
+    this->sysblockmap = sysblockmapIn;
+    this->image_index = image_indexIn;
 
     loaded_block = -1;
     loaded_block_dirty = false;
@@ -112,7 +112,7 @@ uint16 SysVirtualFile::GetBlockSegment( int requested_block )
 
 {
     if( requested_block < 0 )
-        ThrowPCIDSKException( "SysVirtualFile::GetBlockSegment(%d) - illegal request.",
+        return (uint16)ThrowPCIDSKException(0, "SysVirtualFile::GetBlockSegment(%d) - illegal request.",
                               requested_block );
 
     if( requested_block >= blocks_loaded )
@@ -133,7 +133,7 @@ int SysVirtualFile::GetBlockIndexInSegment( int requested_block )
 
 {
     if( requested_block < 0 )
-        ThrowPCIDSKException( "SysVirtualFile::GetBlockIndexInSegment(%d) - illegal request.",
+        return ThrowPCIDSKException(0, "SysVirtualFile::GetBlockIndexInSegment(%d) - illegal request.",
                               requested_block );
 
     if( requested_block >= blocks_loaded )
@@ -157,7 +157,7 @@ void SysVirtualFile::SetBlockInfo( int requested_block,
 
 {
     if( requested_block < 0 )
-        ThrowPCIDSKException( "SysVirtualFile::SetBlockSegment(%d) - illegal request.",
+        return ThrowPCIDSKException( "SysVirtualFile::SetBlockSegment(%d) - illegal request.",
                               requested_block );
 
     // this should always be the case.
@@ -189,13 +189,14 @@ void SysVirtualFile::SetBlockInfo( int requested_block,
     }
 
     // Ah, we see they are now irregular.  We need to build up the
-    // segment/index arrays and proceed to populate them. 
-    Debug( file->GetInterfaces()->Debug, 
-           "SysVirtualFile - Discovered stream is irregulr.  %d/%d follows %d/%d at block %d.\n",
+    // segment/index arrays and proceed to populate them.
+    Debug( file->GetInterfaces()->Debug,
+           "SysVirtualFile - Discovered stream is irregular.  "
+           "%d/%d follows %d/%d at block %d.\n",
            new_block_segment, new_block_index,
            xblock_segment[0], xblock_index[0], 
            requested_block );
-           
+
     regular_blocks = false;
     while( (int) xblock_segment.size() < blocks_loaded )
     {
@@ -330,7 +331,7 @@ void SysVirtualFile::LoadBlock( int requested_block )
 /*      Does this block exist in the virtual file?                      */
 /* -------------------------------------------------------------------- */
     if( requested_block < 0 || requested_block >= blocks_loaded )
-        ThrowPCIDSKException( "SysVirtualFile::LoadBlock(%d) - block out of range.",
+        return ThrowPCIDSKException( "SysVirtualFile::LoadBlock(%d) - block out of range.",
                               requested_block );
 
 /* -------------------------------------------------------------------- */
@@ -344,6 +345,9 @@ void SysVirtualFile::LoadBlock( int requested_block )
     LoadBMEntrysTo( requested_block );
     PCIDSKSegment *data_seg_obj =
         file->GetSegment( GetBlockSegment( requested_block ) );
+    if( data_seg_obj == NULL )
+        return ThrowPCIDSKException( "SysVirtualFile::LoadBlock(%d) - no segment found",
+                                     requested_block );
 
     data_seg_obj->ReadFromFile( block_data,
                                 block_size * (uint64) GetBlockIndexInSegment( requested_block ),
@@ -382,7 +386,7 @@ void SysVirtualFile::FlushDirtyBlock(void)
 /************************************************************************/
 void SysVirtualFile::GrowVirtualFile(std::ptrdiff_t requested_block)
 {
-    LoadBMEntrysTo( requested_block );
+    LoadBMEntrysTo( static_cast<int>(requested_block) );
 
     if( requested_block == blocks_loaded )
     {
@@ -396,7 +400,7 @@ void SysVirtualFile::GrowVirtualFile(std::ptrdiff_t requested_block)
 
         offset = 
             sysblockmap->GrowVirtualFile( image_index, last_bm_index, new_seg);
-        SetBlockInfo( requested_block, (uint16) new_seg, offset );
+        SetBlockInfo( static_cast<int>(requested_block), (uint16) new_seg, offset );
     }
 }
 
@@ -431,23 +435,23 @@ void SysVirtualFile::WriteBlocks(int first_block,
     std::size_t blocks_written = 0;
     std::size_t current_first_block = first_block;
     while (blocks_written < (std::size_t) block_count) {
-        LoadBMEntrysTo( current_first_block+1 );
+        LoadBMEntrysTo( static_cast<int>(current_first_block+1) );
 
-        unsigned int cur_segment = GetBlockSegment( current_first_block );
-        unsigned int cur_block = current_first_block;
+        unsigned int cur_segment = GetBlockSegment( static_cast<int>(current_first_block) );
+        unsigned int cur_block = static_cast<unsigned int>(current_first_block);
         while (cur_block < (unsigned int)block_count + first_block &&
                (unsigned int) GetBlockSegment(cur_block + 1) == cur_segment)
         {
             cur_block++;
-            LoadBMEntrysTo( current_first_block+1 );
+            LoadBMEntrysTo( static_cast<int>(current_first_block+1) );
         }
         
         // Find largest span of contiguous blocks we can write
-        uint64 write_start = GetBlockIndexInSegment(current_first_block);
+        uint64 write_start = GetBlockIndexInSegment(static_cast<int>(current_first_block));
         uint64 write_cur = write_start * block_size;
         unsigned int count_to_write = 1;
         while (write_cur + block_size ==
-               (uint64)GetBlockIndexInSegment(count_to_write + current_first_block - 1) * block_size &&
+               (uint64)GetBlockIndexInSegment(static_cast<int>(count_to_write + current_first_block - 1)) * block_size &&
             count_to_write < (cur_block - current_first_block))
         {
             write_cur += block_size;
@@ -528,14 +532,14 @@ void SysVirtualFile::LoadBlocks(int requested_block_start,
         for (unsigned int i = 0 ; i < count_to_read; i++) {
             GrowVirtualFile(i + current_start);
         }
-        
+
         printf("Coalescing the read of %d blocks\n", count_to_read);
 #endif
 
         // Perform the actual read
         PCIDSKSegment *data_seg_obj =
             file->GetSegment( cur_segment );
-        
+
         std::size_t data_size = block_size * count_to_read;
 
 #if 0
@@ -545,10 +549,10 @@ void SysVirtualFile::LoadBlocks(int requested_block_start,
         data_seg_obj->ReadFromFile( ((uint8*)buffer) + buffer_off,
                                     block_size * read_start,
                                     data_size );
-                                    
+
         buffer_off += data_size; // increase buffer offset
-        
-        // Increment the current start by the number of blocks we jsut read
+
+        // Increment the current start by the number of blocks we just read
         current_start += count_to_read;
         blocks_read += count_to_read;
     }
diff --git a/frmts/pcidsk/sdk/core/sysvirtualfile.h b/frmts/pcidsk/sdk/core/sysvirtualfile.h
index 5a0e5e9..7fbd059 100644
--- a/frmts/pcidsk/sdk/core/sysvirtualfile.h
+++ b/frmts/pcidsk/sdk/core/sysvirtualfile.h
@@ -35,8 +35,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_CORE_SYSVIRTUALFILE_H
-#define __INCLUDE_CORE_SYSVIRTUALFILE_H
+#ifndef INCLUDE_CORE_SYSVIRTUALFILE_H
+#define INCLUDE_CORE_SYSVIRTUALFILE_H
 
 #include "pcidsk_buffer.h"
 #include "pcidsk_mutex.h"
@@ -110,4 +110,4 @@ namespace PCIDSK
     };
 }
 
-#endif // __INCLUDE_CORE_SYSVIRTUALFILE_H
+#endif // INCLUDE_CORE_SYSVIRTUALFILE_H
diff --git a/frmts/pcidsk/sdk/pcidsk_ads40.h b/frmts/pcidsk/sdk/pcidsk_ads40.h
index ea5ef12..cdebd31 100644
--- a/frmts/pcidsk/sdk/pcidsk_ads40.h
+++ b/frmts/pcidsk/sdk/pcidsk_ads40.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PCIDSK_PCIDSK_ADS40_H
-#define __INCLUDE_PCIDSK_PCIDSK_ADS40_H
+#ifndef INCLUDE_PCIDSK_PCIDSK_ADS40_H
+#define INCLUDE_PCIDSK_PCIDSK_ADS40_H
 
 #include <vector>
 #include <string>
@@ -45,4 +45,4 @@ namespace PCIDSK {
     };
 }
 
-#endif // __INCLUDE_PCIDSK_PCIDSK_ADS40_H
+#endif // INCLUDE_PCIDSK_PCIDSK_ADS40_H
diff --git a/frmts/pcidsk/sdk/pcidsk_airphoto.h b/frmts/pcidsk/sdk/pcidsk_airphoto.h
index 740f984..f8242b4 100644
--- a/frmts/pcidsk/sdk/pcidsk_airphoto.h
+++ b/frmts/pcidsk/sdk/pcidsk_airphoto.h
@@ -25,8 +25,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PCIDSK_SRC_PCIDSK_AIRPHOTO_H
-#define __INCLUDE_PCIDSK_SRC_PCIDSK_AIRPHOTO_H
+#ifndef INCLUDE_PCIDSK_SRC_PCIDSK_AIRPHOTO_H
+#define INCLUDE_PCIDSK_SRC_PCIDSK_AIRPHOTO_H
 
 #include "pcidsk_config.h"
 
@@ -158,5 +158,5 @@ namespace PCIDSK {
     
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_PCIDSK_SRC_PCIDSK_AIRPHOTO_H
+#endif // INCLUDE_PCIDSK_SRC_PCIDSK_AIRPHOTO_H
 
diff --git a/frmts/pcidsk/sdk/pcidsk_array.h b/frmts/pcidsk/sdk/pcidsk_array.h
index abc6428..75beab4 100644
--- a/frmts/pcidsk/sdk/pcidsk_array.h
+++ b/frmts/pcidsk/sdk/pcidsk_array.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PCIDSK_ARRAY_H
-#define __INCLUDE_PCIDSK_ARRAY_H
+#ifndef INCLUDE_PCIDSK_ARRAY_H
+#define INCLUDE_PCIDSK_ARRAY_H
 
 #include <string>
 #include <vector>
@@ -53,4 +53,4 @@ namespace PCIDSK
     };
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_PCIDSK_ARRAY_H
+#endif // INCLUDE_PCIDSK_ARRAY_H
diff --git a/frmts/pcidsk/sdk/pcidsk_binary.h b/frmts/pcidsk/sdk/pcidsk_binary.h
index 8646a14..12c2386 100644
--- a/frmts/pcidsk/sdk/pcidsk_binary.h
+++ b/frmts/pcidsk/sdk/pcidsk_binary.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PCIDSK_PCIDSK_BINARY_H
-#define __INCLUDE_PCIDSK_PCIDSK_BINARY_H
+#ifndef INCLUDE_PCIDSK_PCIDSK_BINARY_H
+#define INCLUDE_PCIDSK_PCIDSK_BINARY_H
 
 namespace PCIDSK {
 //! Interface to PCIDSK Binary segment.
@@ -42,4 +42,4 @@ namespace PCIDSK {
     };
 }
 
-#endif // __INCLUDE_PCIDSK_PCIDSK_BINARY_H
+#endif // INCLUDE_PCIDSK_PCIDSK_BINARY_H
diff --git a/frmts/pcidsk/sdk/pcidsk_buffer.h b/frmts/pcidsk/sdk/pcidsk_buffer.h
index 58c200b..b96e96c 100644
--- a/frmts/pcidsk/sdk/pcidsk_buffer.h
+++ b/frmts/pcidsk/sdk/pcidsk_buffer.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PCIDSKBUFFER_H
-#define __INCLUDE_PCIDSKBUFFER_H
+#ifndef INCLUDE_PCIDSKBUFFER_H
+#define INCLUDE_PCIDSKBUFFER_H
 
 #include "pcidsk_config.h"
 
@@ -77,4 +77,4 @@ namespace PCIDSK
         mutable std::string work_field;
     };
 } // end namespace PCIDSK
-#endif // __INCLUDE_PCIDSKBUFFER_H 
+#endif // INCLUDE_PCIDSKBUFFER_H 
diff --git a/frmts/pcidsk/sdk/pcidsk_channel.h b/frmts/pcidsk/sdk/pcidsk_channel.h
index dd841b8..b596a06 100644
--- a/frmts/pcidsk/sdk/pcidsk_channel.h
+++ b/frmts/pcidsk/sdk/pcidsk_channel.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PCIDSK_CHANNEL_H
-#define __INCLUDE_PCIDSK_CHANNEL_H
+#ifndef INCLUDE_PCIDSK_CHANNEL_H
+#define INCLUDE_PCIDSK_CHANNEL_H
 
 #include "pcidsk_types.h"
 #include <string>
@@ -92,4 +92,4 @@ namespace PCIDSK
     };
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_PCIDSK_CHANNEL_H
+#endif // INCLUDE_PCIDSK_CHANNEL_H
diff --git a/frmts/pcidsk/sdk/pcidsk_config.h b/frmts/pcidsk/sdk/pcidsk_config.h
index 52606d4..1b387b9 100644
--- a/frmts/pcidsk/sdk/pcidsk_config.h
+++ b/frmts/pcidsk/sdk/pcidsk_config.h
@@ -28,6 +28,10 @@
 #ifndef PCIDSK_CONFIG_H_INCLUDED
 #define PCIDSK_CONFIG_H_INCLUDED
 
+#if defined(DEBUG_BOOL) || defined(NULL_AS_NULLPTR)
+#include "cpl_port.h"
+#endif
+
 namespace PCIDSK {
 
     typedef unsigned char  uint8;
@@ -82,12 +86,18 @@ namespace PCIDSK {
 #define PCIDSK_SDK_MAJOR_VERSION    0
 #define PCIDSK_SDK_MINOR_VERSION    1
 
+#if defined(__GNUC__) && __GNUC__ >= 3 && !defined(DOXYGEN_SKIP)
+#define PCIDSK_PRINT_FUNC_FORMAT( format_idx, arg_idx )  __attribute__((__format__ (__printf__, format_idx, arg_idx)))
+#else
+#define PCIDSK_PRINT_FUNC_FORMAT( format_idx, arg_idx )
+#endif
+
 #ifndef GDAL_PCIDSK_DRIVER
 #ifdef PCIDSK_INTERNAL
 #include <stdlib.h>
 extern "C" double CPLAtof(const char*);
-extern "C" int CPLsprintf(char *str, const char* fmt, ...);
-extern "C" int CPLsnprintf(char *str, size_t size, const char* fmt, ...);
+extern "C" int CPLsprintf(char *str, const char* fmt, ...) PCIDSK_PRINT_FUNC_FORMAT(2,3);
+extern "C" int CPLsnprintf(char *str, size_t size, const char* fmt, ...) PCIDSK_PRINT_FUNC_FORMAT(3,4);
 #else
 #define CPLAtof atof
 #define CPLsprintf sprintf
@@ -95,4 +105,8 @@ extern "C" int CPLsnprintf(char *str, size_t size, const char* fmt, ...);
 #endif
 #endif
 
+#if defined(_MSC_VER) && (_MSC_VER < 1900)
+#  define snprintf _snprintf
+#endif
+
 #endif // PCIDSK_CONFIG_H_INCLUDED
diff --git a/frmts/pcidsk/sdk/pcidsk_edb.h b/frmts/pcidsk/sdk/pcidsk_edb.h
index f6ac3aa..0a42a96 100644
--- a/frmts/pcidsk/sdk/pcidsk_edb.h
+++ b/frmts/pcidsk/sdk/pcidsk_edb.h
@@ -25,8 +25,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PCIDSK_EDB_H
-#define __INCLUDE_PCIDSK_EDB_H
+#ifndef INCLUDE_PCIDSK_EDB_H
+#define INCLUDE_PCIDSK_EDB_H
 
 #include "pcidsk_config.h"
 
@@ -63,4 +63,4 @@ namespace PCIDSK
                                        std::string access);    
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_PCIDSK_EDB_H
+#endif // INCLUDE_PCIDSK_EDB_H
diff --git a/frmts/pcidsk/sdk/pcidsk_ephemeris.h b/frmts/pcidsk/sdk/pcidsk_ephemeris.h
index 7f11c22..7e48871 100644
--- a/frmts/pcidsk/sdk/pcidsk_ephemeris.h
+++ b/frmts/pcidsk/sdk/pcidsk_ephemeris.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PCIDSK_PCIDSK_EPHEMERIS_H
-#define __INCLUDE_PCIDSK_PCIDSK_EPHEMERIS_H
+#ifndef INCLUDE_PCIDSK_PCIDSK_EPHEMERIS_H
+#define INCLUDE_PCIDSK_PCIDSK_EPHEMERIS_H
 
 #include <vector>
 #include <string>
@@ -45,4 +45,4 @@ namespace PCIDSK {
     };
 }
 
-#endif // __INCLUDE_PCIDSK_PCIDSK_EPHEMERIS_H
+#endif // INCLUDE_PCIDSK_PCIDSK_EPHEMERIS_H
diff --git a/frmts/pcidsk/sdk/pcidsk_exception.h b/frmts/pcidsk/sdk/pcidsk_exception.h
index 5a35f06..b7cd8d0 100644
--- a/frmts/pcidsk/sdk/pcidsk_exception.h
+++ b/frmts/pcidsk/sdk/pcidsk_exception.h
@@ -25,8 +25,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PCIDSK_EXCEPTION_H
-#define __INCLUDE_PCIDSK_EXCEPTION_H
+#ifndef INCLUDE_PCIDSK_EXCEPTION_H
+#define INCLUDE_PCIDSK_EXCEPTION_H
 
 #include "pcidsk_config.h"
 
@@ -42,8 +42,12 @@ namespace PCIDSK
 
     class PCIDSKException : public std::exception
     {
+        friend void PCIDSK_DLL ThrowPCIDSKException( const char *fmt, ... ) PCIDSK_PRINT_FUNC_FORMAT(1,2);
+        friend int PCIDSK_DLL ThrowPCIDSKException( int ret_unused, const char *fmt, ... ) PCIDSK_PRINT_FUNC_FORMAT(2,3);
+        friend void* PCIDSK_DLL ThrowPCIDSKExceptionPtr( const char *fmt, ... ) PCIDSK_PRINT_FUNC_FORMAT(1,2);
+        PCIDSKException() {}
     public:
-        PCIDSKException(const char *fmt, ... );
+        PCIDSKException(const char *fmt, ... ) PCIDSK_PRINT_FUNC_FORMAT(2,3);
         virtual ~PCIDSKException() throw();
 
         void vPrintf( const char *fmt, std::va_list list );
@@ -52,8 +56,10 @@ namespace PCIDSK
         std::string   message;
     };
 
-    void PCIDSK_DLL ThrowPCIDSKException( const char *fmt, ... );
+    void PCIDSK_DLL ThrowPCIDSKException( const char *fmt, ... ) PCIDSK_PRINT_FUNC_FORMAT(1,2);
+    int PCIDSK_DLL ThrowPCIDSKException( int ret_unused, const char *fmt, ... ) PCIDSK_PRINT_FUNC_FORMAT(2,3);
+    void* PCIDSK_DLL ThrowPCIDSKExceptionPtr( const char *fmt, ... ) PCIDSK_PRINT_FUNC_FORMAT(1,2);
 
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_PCIDSK_EXCEPTION_H
+#endif // INCLUDE_PCIDSK_EXCEPTION_H
diff --git a/frmts/pcidsk/sdk/pcidsk_file.h b/frmts/pcidsk/sdk/pcidsk_file.h
index e4e3ad7..a506700 100644
--- a/frmts/pcidsk/sdk/pcidsk_file.h
+++ b/frmts/pcidsk/sdk/pcidsk_file.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PCIDSK_FILE_H
-#define __INCLUDE_PCIDSK_FILE_H
+#ifndef INCLUDE_PCIDSK_FILE_H
+#define INCLUDE_PCIDSK_FILE_H
 
 #include "pcidsk_segment.h"
 #include <string>
@@ -90,4 +90,4 @@ namespace PCIDSK
     };
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_PCIDSK_FILE_H
+#endif // INCLUDE_PCIDSK_FILE_H
diff --git a/frmts/pcidsk/sdk/pcidsk_gcp.h b/frmts/pcidsk/sdk/pcidsk_gcp.h
index 8e9b9c0..f4822a1 100644
--- a/frmts/pcidsk/sdk/pcidsk_gcp.h
+++ b/frmts/pcidsk/sdk/pcidsk_gcp.h
@@ -25,8 +25,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef __INCLUDE_PCIDSK_SRC_GCP_H
-#define __INCLUDE_PCIDSK_SRC_GCP_H
+#ifndef INCLUDE_PCIDSK_SRC_GCP_H
+#define INCLUDE_PCIDSK_SRC_GCP_H
 
 #include "pcidsk_config.h"
 
@@ -200,5 +200,5 @@ namespace PCIDSK {
     };
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_PCIDSK_SRC_GCP_H
+#endif // INCLUDE_PCIDSK_SRC_GCP_H
 
diff --git a/frmts/pcidsk/sdk/pcidsk_gcpsegment.h b/frmts/pcidsk/sdk/pcidsk_gcpsegment.h
index b8e1ff8..bb5c782 100644
--- a/frmts/pcidsk/sdk/pcidsk_gcpsegment.h
+++ b/frmts/pcidsk/sdk/pcidsk_gcpsegment.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PCIDSK_PCIDSK_GCPSEGMENT_H
-#define __INCLUDE_PCIDSK_PCIDSK_GCPSEGMENT_H
+#ifndef INCLUDE_PCIDSK_PCIDSK_GCPSEGMENT_H
+#define INCLUDE_PCIDSK_PCIDSK_GCPSEGMENT_H
 
 #include "pcidsk_gcp.h"
 
@@ -55,5 +55,5 @@ namespace PCIDSK {
 } // end namespace PCIDSK
 
 
-#endif // __INCLUDE_PCIDSK_PCIDSK_GCPSEGMENT_H
+#endif // INCLUDE_PCIDSK_PCIDSK_GCPSEGMENT_H
 
diff --git a/frmts/pcidsk/sdk/pcidsk_georef.h b/frmts/pcidsk/sdk/pcidsk_georef.h
index 57a2852..f83e9c2 100644
--- a/frmts/pcidsk/sdk/pcidsk_georef.h
+++ b/frmts/pcidsk/sdk/pcidsk_georef.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PCIDSK_GEOREF_H
-#define __INCLUDE_PCIDSK_GEOREF_H
+#ifndef INCLUDE_PCIDSK_GEOREF_H
+#define INCLUDE_PCIDSK_GEOREF_H
 
 #include <string>
 #include <vector>
@@ -80,7 +80,7 @@ pixel.  For an ungeoreferenced image the values will be
 /**
 \brief Fetch georeferencing string.
 
-Returns the short, 16 character, georeferncing string.  This string is
+Returns the short, 16 character, georeferencing string.  This string is
 sufficient to document the coordinate system of simple coordinate
 systems (like "UTM    17 S D000"), while other coordinate systems are
 only fully defined with additional projection parameters.
@@ -158,4 +158,4 @@ See GetParameters() for the description of the parameters list.
     };
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_PCIDSK_GEOREF_H
+#endif // INCLUDE_PCIDSK_GEOREF_H
diff --git a/frmts/pcidsk/sdk/pcidsk_interfaces.h b/frmts/pcidsk/sdk/pcidsk_interfaces.h
index 843adec..71dc2b0 100644
--- a/frmts/pcidsk/sdk/pcidsk_interfaces.h
+++ b/frmts/pcidsk/sdk/pcidsk_interfaces.h
@@ -25,8 +25,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef __INCLUDE_PCIDSK_INTERFACES_H
-#define __INCLUDE_PCIDSK_INTERFACES_H
+#ifndef INCLUDE_PCIDSK_INTERFACES_H
+#define INCLUDE_PCIDSK_INTERFACES_H
 
 #include "pcidsk_io.h"
 #include "pcidsk_mutex.h"
@@ -62,4 +62,4 @@ namespace PCIDSK
     };
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_PCIDSK_INTERFACES_H
+#endif // INCLUDE_PCIDSK_INTERFACES_H
diff --git a/frmts/pcidsk/sdk/pcidsk_io.h b/frmts/pcidsk/sdk/pcidsk_io.h
index 24e336c..e4ff887 100644
--- a/frmts/pcidsk/sdk/pcidsk_io.h
+++ b/frmts/pcidsk/sdk/pcidsk_io.h
@@ -25,8 +25,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PCIDSK_IO_H
-#define __INCLUDE_PCIDSK_IO_H
+#ifndef INCLUDE_PCIDSK_IO_H
+#define INCLUDE_PCIDSK_IO_H
 
 #include "pcidsk_config.h"
 
@@ -58,4 +58,4 @@ namespace PCIDSK
 
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_PCIDSK_IO_H
+#endif // INCLUDE_PCIDSK_IO_H
diff --git a/frmts/pcidsk/sdk/pcidsk_mutex.h b/frmts/pcidsk/sdk/pcidsk_mutex.h
index 97cae0c..a660e25 100644
--- a/frmts/pcidsk/sdk/pcidsk_mutex.h
+++ b/frmts/pcidsk/sdk/pcidsk_mutex.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PCIDSK_MUTEX_H
-#define __INCLUDE_PCIDSK_MUTEX_H
+#ifndef INCLUDE_PCIDSK_MUTEX_H
+#define INCLUDE_PCIDSK_MUTEX_H
 
 #include "pcidsk_config.h"
 
@@ -47,4 +47,4 @@ namespace PCIDSK
     Mutex PCIDSK_DLL *DefaultCreateMutex(void);    
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_PCIDSK_MUTEX_H
+#endif // INCLUDE_PCIDSK_MUTEX_H
diff --git a/frmts/pcidsk/sdk/pcidsk_pct.h b/frmts/pcidsk/sdk/pcidsk_pct.h
index 3867aa5..d5d235f 100644
--- a/frmts/pcidsk/sdk/pcidsk_pct.h
+++ b/frmts/pcidsk/sdk/pcidsk_pct.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PCIDSK_PCT_H
-#define __INCLUDE_PCIDSK_PCT_H
+#ifndef INCLUDE_PCIDSK_PCT_H
+#define INCLUDE_PCIDSK_PCT_H
 
 #include <string>
 #include <vector>
@@ -67,4 +67,4 @@ and ends with the blue gun output values (pct[512-767]).
     };
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_PCIDSK_PCT_H
+#endif // INCLUDE_PCIDSK_PCT_H
diff --git a/frmts/pcidsk/sdk/pcidsk_poly.h b/frmts/pcidsk/sdk/pcidsk_poly.h
index a0d579a..1a9292e 100644
--- a/frmts/pcidsk/sdk/pcidsk_poly.h
+++ b/frmts/pcidsk/sdk/pcidsk_poly.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PCIDSK_PCIDSK_POLY_H
-#define __INCLUDE_PCIDSK_PCIDSK_POLY_H
+#ifndef INCLUDE_PCIDSK_PCIDSK_POLY_H
+#define INCLUDE_PCIDSK_PCIDSK_POLY_H
 
 #include <vector>
 #include <string>
@@ -59,9 +59,9 @@ namespace PCIDSK {
         // Set the Geosys string
         virtual void SetGeosysString(const std::string& oGeosys) =0;
 
-        //Get the projection informations
+        //Get the projection information
         virtual std::vector<double> GetProjParmInfo() const=0;
-        //Set the projection informations
+        //Set the projection information
         virtual void SetProjParmInfo(const std::vector<double>& oInfo) =0;
 
         // Virtual destructor
@@ -69,4 +69,4 @@ namespace PCIDSK {
     };
 }
 
-#endif // __INCLUDE_PCIDSK_PCIDSK_POLY_H
+#endif // INCLUDE_PCIDSK_PCIDSK_POLY_H
diff --git a/frmts/pcidsk/sdk/pcidsk_rpc.h b/frmts/pcidsk/sdk/pcidsk_rpc.h
index 4be9514..157834f 100644
--- a/frmts/pcidsk/sdk/pcidsk_rpc.h
+++ b/frmts/pcidsk/sdk/pcidsk_rpc.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PCIDSK_PCIDSK_RPC_H
-#define __INCLUDE_PCIDSK_PCIDSK_RPC_H
+#ifndef INCLUDE_PCIDSK_PCIDSK_RPC_H
+#define INCLUDE_PCIDSK_PCIDSK_RPC_H
 
 #include <vector>
 #include <string>
@@ -109,4 +109,4 @@ namespace PCIDSK {
     };
 }
 
-#endif // __INCLUDE_PCIDSK_PCIDSK_RPC_H
+#endif // INCLUDE_PCIDSK_PCIDSK_RPC_H
diff --git a/frmts/pcidsk/sdk/pcidsk_segment.h b/frmts/pcidsk/sdk/pcidsk_segment.h
index 9aa500e..585faa7 100644
--- a/frmts/pcidsk/sdk/pcidsk_segment.h
+++ b/frmts/pcidsk/sdk/pcidsk_segment.h
@@ -25,8 +25,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
  
-#ifndef __INCLUDE_SEGMENT_PCIDSKSEGMENT_H
-#define __INCLUDE_SEGMENT_PCIDSKSEGMENT_H
+#ifndef INCLUDE_PCIDSKSEGMENT_H
+#define INCLUDE_PCIDSKSEGMENT_H
 
 #include "pcidsk_config.h"
 #include "pcidsk_types.h"
@@ -76,4 +76,4 @@ namespace PCIDSK
 
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_SEGMENT_PCIDSKSEGMENT_H
+#endif // INCLUDE_PCIDSKSEGMENT_H
diff --git a/frmts/pcidsk/sdk/pcidsk_shape.h b/frmts/pcidsk/sdk/pcidsk_shape.h
index 0dd3c7c..9bd8f86 100644
--- a/frmts/pcidsk/sdk/pcidsk_shape.h
+++ b/frmts/pcidsk/sdk/pcidsk_shape.h
@@ -25,8 +25,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef __INCLUDE_PCIDSK_SHAPE_H
-#define __INCLUDE_PCIDSK_SHAPE_H
+#ifndef INCLUDE_PCIDSK_SHAPE_H
+#define INCLUDE_PCIDSK_SHAPE_H
 
 #include <string>
 #include <vector>
@@ -95,8 +95,8 @@ namespace PCIDSK
      types in a convenient way that avoids memory leaks or ownership confusion.
      The object has a field type (initially FieldTypeNone on construction)
      and a value of the specified type.  Note that the appropriate value
-     accessor (ie. GetValueInteger()) must be used that corresponds to the
-     fields type. No attempt is made to automatically convert (ie. float to
+     accessor (i.e. GetValueInteger()) must be used that corresponds to the
+     fields type. No attempt is made to automatically convert (i.e. float to
      double) if the wrong accessor is used.
 
     */
@@ -210,7 +210,7 @@ namespace PCIDSK
                 type = FieldTypeCountedInt; 
                 v.integer_list_val = (int32*)
                     malloc(sizeof(int32) * (val.size()+1) );
-                v.integer_list_val[0] = val.size();
+                v.integer_list_val[0] = static_cast<int>(val.size());
                 if( val.size() > 0 )
                     memcpy( v.integer_list_val+1, &(val[0]), 
                             sizeof(int32) * val.size() ); 
@@ -269,4 +269,4 @@ namespace PCIDSK
 
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_PCIDSK_SHAPE_H
+#endif // INCLUDE_PCIDSK_SHAPE_H
diff --git a/frmts/pcidsk/sdk/pcidsk_tex.h b/frmts/pcidsk/sdk/pcidsk_tex.h
index cf9cb95..4956a00 100644
--- a/frmts/pcidsk/sdk/pcidsk_tex.h
+++ b/frmts/pcidsk/sdk/pcidsk_tex.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PCIDSK_TEX_H
-#define __INCLUDE_PCIDSK_TEX_H
+#ifndef INCLUDE_PCIDSK_TEX_H
+#define INCLUDE_PCIDSK_TEX_H
 
 #include <string>
 #include <vector>
@@ -68,4 +68,4 @@ file.
     };
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_PCIDSK_TEX_H
+#endif // INCLUDE_PCIDSK_TEX_H
diff --git a/frmts/pcidsk/sdk/pcidsk_toutin.h b/frmts/pcidsk/sdk/pcidsk_toutin.h
index b9cc200..d85354c 100644
--- a/frmts/pcidsk/sdk/pcidsk_toutin.h
+++ b/frmts/pcidsk/sdk/pcidsk_toutin.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PCIDSK_PCIDSK_TOUTIN_H
-#define __INCLUDE_PCIDSK_PCIDSK_TOUTIN_H
+#ifndef INCLUDE_PCIDSK_PCIDSK_TOUTIN_H
+#define INCLUDE_PCIDSK_PCIDSK_TOUTIN_H
 
 #include <vector>
 #include <string>
@@ -45,4 +45,4 @@ namespace PCIDSK {
     };
 }
 
-#endif // __INCLUDE_PCIDSK_PCIDSK_TOUTIN_H
+#endif // INCLUDE_PCIDSK_PCIDSK_TOUTIN_H
diff --git a/frmts/pcidsk/sdk/pcidsk_types.h b/frmts/pcidsk/sdk/pcidsk_types.h
index 2bb9378..1f7d263 100644
--- a/frmts/pcidsk/sdk/pcidsk_types.h
+++ b/frmts/pcidsk/sdk/pcidsk_types.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PCIDSK_TYPES_H
-#define __INCLUDE_PCIDSK_TYPES_H
+#ifndef INCLUDE_PCIDSK_TYPES_H
+#define INCLUDE_PCIDSK_TYPES_H
 
 #include "pcidsk_config.h"
 
@@ -76,4 +76,4 @@ namespace PCIDSK
 
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_PCIDSK_TYPES_H
+#endif // INCLUDE_PCIDSK_TYPES_H
diff --git a/frmts/pcidsk/sdk/pcidsk_vectorsegment.h b/frmts/pcidsk/sdk/pcidsk_vectorsegment.h
index 1944333..9cf8ae4 100644
--- a/frmts/pcidsk/sdk/pcidsk_vectorsegment.h
+++ b/frmts/pcidsk/sdk/pcidsk_vectorsegment.h
@@ -25,8 +25,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef __INCLUDE_PCIDSK_VECTORSEGMENT_H
-#define __INCLUDE_PCIDSK_VECTORSEGMENT_H
+#ifndef INCLUDE_PCIDSK_VECTORSEGMENT_H
+#define INCLUDE_PCIDSK_VECTORSEGMENT_H
 
 #include <string>
 #include <vector>
@@ -59,7 +59,7 @@ end() methods).
 The PCIDSKSegment interface for the segment can be used to fetch the
 LAYER_TYPE metadata describing how the vertices should be interpreted
 as a geometry.  Some layers will also have a RingStart attribute field
-which is used in conjunction with the LAYER_TYPE to interprete the
+which is used in conjunction with the LAYER_TYPE to interpret the
 geometry.  Some vector segments may have no LAYER_TYPE metadata in which
 case single vertices are interpreted as points, and multiple vertices
 as linestrings.  
@@ -306,4 +306,4 @@ The list of fields should match the types and length from the schema
 
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_PCIDSK_VECTORSEGMENT_H
+#endif // INCLUDE_PCIDSK_VECTORSEGMENT_H
diff --git a/frmts/pcidsk/sdk/segment/cpcidsk_array.cpp b/frmts/pcidsk/sdk/segment/cpcidsk_array.cpp
index 73a989d..8ba560c 100644
--- a/frmts/pcidsk/sdk/segment/cpcidsk_array.cpp
+++ b/frmts/pcidsk/sdk/segment/cpcidsk_array.cpp
@@ -39,9 +39,9 @@ using namespace PCIDSK;
 /*                            CPCIDSK_ARRAY()                           */
 /************************************************************************/
 
-CPCIDSK_ARRAY::CPCIDSK_ARRAY( PCIDSKFile *file, int segment,
+CPCIDSK_ARRAY::CPCIDSK_ARRAY( PCIDSKFile *fileIn, int segmentIn,
                               const char *segment_pointer )
-        : CPCIDSKSegment( file, segment, segment_pointer ),
+        : CPCIDSKSegment( fileIn, segmentIn, segment_pointer ),
         loaded_(false),mbModified(false)
 {
     MAX_DIMENSIONS = 8;
@@ -68,10 +68,10 @@ void CPCIDSK_ARRAY::Load()
     }
 
     PCIDSKBuffer& seg_header = this->GetHeader();
-    seg_data.SetSize(GetContentSize());
+    seg_data.SetSize(static_cast<int>(GetContentSize()));
     ReadFromFile(seg_data.buffer, 0, seg_data.buffer_size);
 
-    if(std::strncmp(seg_header.buffer+160, "64R     ", 8))
+    if(!STARTS_WITH(seg_header.buffer+160, "64R     "))
     {
         seg_header.Put("64R     ",160,8);
         loaded_ = true;
@@ -85,7 +85,7 @@ void CPCIDSK_ARRAY::Load()
         oStream << "Invalid array dimension " << nDimension;
         oStream << " stored in the segment.";
         std::string oMsg = oStream.str();
-        throw PCIDSKException(oMsg.c_str());
+        return ThrowPCIDSKException("%s", oMsg.c_str());
     }
     mnDimension = static_cast<unsigned char>(nDimension);
 
@@ -98,7 +98,7 @@ void CPCIDSK_ARRAY::Load()
             std::stringstream oStream;
             oStream << "Invalid size " << nSize << " for dimension " << i+1;
             std::string oMsg = oStream.str();
-            throw PCIDSKException(oMsg.c_str());
+            return ThrowPCIDSKException("%s", oMsg.c_str());
         }
 		moSizes.push_back( nSize );
     }
@@ -140,10 +140,10 @@ void CPCIDSK_ARRAY::Write(void)
     }
 
     PCIDSKBuffer& seg_header = this->GetHeader();
-    int nBlocks = (moArray.size()*8 + 511)/512 ;
+    int nBlocks = (static_cast<int>(moArray.size())*8 + 511)/512 ;
     unsigned int nSizeBuffer = (nBlocks)*512 ;
     //64 values can be put into 512 bytes.
-    unsigned int nRest = nBlocks*64 - moArray.size();
+    unsigned int nRest = nBlocks*64 - static_cast<unsigned int>(moArray.size());
 
     seg_data.SetSize(nSizeBuffer);
 
@@ -166,7 +166,7 @@ void CPCIDSK_ARRAY::Write(void)
     //set the end of the buffer to 0.
     for( unsigned int i=0 ; i < nRest ; i++)
     {
-        seg_data.Put(0.0,(moArray.size()+i)*8,8,"%22.14f");
+        seg_data.Put(0.0,(static_cast<int>(moArray.size())+i)*8,8,"%22.14f");
     }
 
     WriteToFile(seg_data.buffer,0,seg_data.buffer_size);
@@ -175,7 +175,7 @@ void CPCIDSK_ARRAY::Write(void)
 }
 
 /**
- * Synchronize the segement, if it was modified then
+ * Synchronize the segment, if it was modified then
  * write it into disk.
  */
 void CPCIDSK_ARRAY::Synchronize()
@@ -210,7 +210,7 @@ void CPCIDSK_ARRAY::SetDimensionCount(unsigned char nDim)
 {
     if(nDim < 1 || nDim > 8)
     {
-        throw PCIDSKException("An array cannot have a "
+        return ThrowPCIDSKException("An array cannot have a "
             "dimension bigger than 8 or smaller than 1.");
     }
     mnDimension = nDim;
@@ -239,7 +239,7 @@ void CPCIDSK_ARRAY::SetSizes(const std::vector<unsigned int>& oSizes)
 {
     if(oSizes.size() != GetDimensionCount())
     {
-        throw PCIDSKException("You need to specify the sizes"
+        return ThrowPCIDSKException("You need to specify the sizes"
             " for each dimension of the array");
     }
 
@@ -247,7 +247,7 @@ void CPCIDSK_ARRAY::SetSizes(const std::vector<unsigned int>& oSizes)
     {
         if(oSizes[i] == 0)
         {
-            throw PCIDSKException("You cannot define the size of a dimension to 0.");
+            return ThrowPCIDSKException("You cannot define the size of a dimension to 0.");
         }
     }
     moSizes = oSizes;
@@ -298,7 +298,7 @@ void CPCIDSK_ARRAY::SetArray(const std::vector<double>& oArray)
 
     if(nLength != oArray.size())
     {
-        throw PCIDSKException("the size of this array doesn't match "
+        return ThrowPCIDSKException("the size of this array doesn't match "
             "the size specified in GetSizes(). See documentation for"
             " more information.");
     }
diff --git a/frmts/pcidsk/sdk/segment/cpcidsk_array.h b/frmts/pcidsk/sdk/segment/cpcidsk_array.h
index 0618066..ec25673 100644
--- a/frmts/pcidsk/sdk/segment/cpcidsk_array.h
+++ b/frmts/pcidsk/sdk/segment/cpcidsk_array.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_SEGMENT_PCIDSK_ARRAY_H
-#define __INCLUDE_SEGMENT_PCIDSK_ARRAY_H
+#ifndef INCLUDE_SEGMENT_PCIDSK_ARRAY_H
+#define INCLUDE_SEGMENT_PCIDSK_ARRAY_H
 
 #include "pcidsk_config.h"
 #include "pcidsk_types.h"
@@ -87,4 +87,4 @@ namespace PCIDSK
     };
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_SEGMENT_PCIDSK_ARRAY_H
+#endif // INCLUDE_SEGMENT_PCIDSK_ARRAY_H
diff --git a/frmts/pcidsk/sdk/segment/cpcidsk_tex.cpp b/frmts/pcidsk/sdk/segment/cpcidsk_tex.cpp
index 5a107b8..80d830d 100644
--- a/frmts/pcidsk/sdk/segment/cpcidsk_tex.cpp
+++ b/frmts/pcidsk/sdk/segment/cpcidsk_tex.cpp
@@ -36,9 +36,9 @@ using namespace PCIDSK;
 /*                            CPCIDSK_TEX()                             */
 /************************************************************************/
 
-CPCIDSK_TEX::CPCIDSK_TEX( PCIDSKFile *file, int segment,
+CPCIDSK_TEX::CPCIDSK_TEX( PCIDSKFile *fileIn, int segmentIn,
                           const char *segment_pointer )
-        : CPCIDSKSegment( file, segment, segment_pointer )
+        : CPCIDSKSegment( fileIn, segmentIn, segment_pointer )
 
 {
 }
diff --git a/frmts/pcidsk/sdk/segment/cpcidsk_tex.h b/frmts/pcidsk/sdk/segment/cpcidsk_tex.h
index 7e67a45..a898f9b 100644
--- a/frmts/pcidsk/sdk/segment/cpcidsk_tex.h
+++ b/frmts/pcidsk/sdk/segment/cpcidsk_tex.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_SEGMENT_PCIDSK_TEX_H
-#define __INCLUDE_SEGMENT_PCIDSK_TEX_H
+#ifndef INCLUDE_SEGMENT_PCIDSK_TEX_H
+#define INCLUDE_SEGMENT_PCIDSK_TEX_H
 
 #include "pcidsk_config.h"
 #include "pcidsk_types.h"
@@ -58,4 +58,4 @@ namespace PCIDSK
     };
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_SEGMENT_PCIDSK_TEX_H
+#endif // INCLUDE_SEGMENT_PCIDSK_TEX_H
diff --git a/frmts/pcidsk/sdk/segment/cpcidskads40model.cpp b/frmts/pcidsk/sdk/segment/cpcidskads40model.cpp
index 5c92189..3a797b2 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskads40model.cpp
+++ b/frmts/pcidsk/sdk/segment/cpcidskads40model.cpp
@@ -47,10 +47,10 @@ struct CPCIDSKADS40ModelSegment::PCIDSKADS40Info
     PCIDSKBuffer seg_data;
 };
 
-CPCIDSKADS40ModelSegment::CPCIDSKADS40ModelSegment(PCIDSKFile *file, 
-                                                   int segment,
+CPCIDSKADS40ModelSegment::CPCIDSKADS40ModelSegment(PCIDSKFile *fileIn, 
+                                                   int segmentIn,
                                                    const char *segment_pointer) :
-    CPCIDSKSegment(file, segment, segment_pointer), 
+    CPCIDSKSegment(fileIn, segmentIn, segment_pointer), 
     pimpl_(new CPCIDSKADS40ModelSegment::PCIDSKADS40Info), 
     loaded_(false),mbModified(false)
 {
@@ -73,7 +73,7 @@ void CPCIDSKADS40ModelSegment::Load()
     
     assert(data_size - 1024 == 1 * 512);
     
-    pimpl_->seg_data.SetSize(data_size - 1024); // should be 1 * 512
+    pimpl_->seg_data.SetSize(static_cast<int>(data_size) - 1024); // should be 1 * 512
     
     ReadFromFile(pimpl_->seg_data.buffer, 0, data_size - 1024);
     
@@ -84,7 +84,7 @@ void CPCIDSKADS40ModelSegment::Load()
     // Bytes   0-7: 'ADS40  '
     // Byte    8-512: the path
     
-    if (std::strncmp(pimpl_->seg_data.buffer, "ADS40   ", 8)) 
+    if (!STARTS_WITH(pimpl_->seg_data.buffer, "ADS40   ")) 
     {
         pimpl_->seg_data.Put("ADS40   ",0,8);
         return;
@@ -110,7 +110,7 @@ void CPCIDSKADS40ModelSegment::Write(void)
     }
       
     pimpl_->seg_data.Put("ADS40   ",0,8);
-    pimpl_->seg_data.Put(pimpl_->path.c_str(),8,pimpl_->path.size());
+    pimpl_->seg_data.Put(pimpl_->path.c_str(),8,static_cast<int>(pimpl_->path.size()));
 
     WriteToFile(pimpl_->seg_data.buffer,0,data_size-1024);
     mbModified = false;
@@ -132,7 +132,7 @@ void CPCIDSKADS40ModelSegment::SetPath(const std::string& oPath)
     }
     else
     {
-        throw PCIDSKException("The size of the path cannot be"
+        return ThrowPCIDSKException("The size of the path cannot be"
                               " bigger than 504 characters.");
     }
 }
diff --git a/frmts/pcidsk/sdk/segment/cpcidskads40model.h b/frmts/pcidsk/sdk/segment/cpcidskads40model.h
index 5d2987c..b912346 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskads40model.h
+++ b/frmts/pcidsk/sdk/segment/cpcidskads40model.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PCIDSK_SEGMENT_PCIDSKADS40MODEL_H
-#define __INCLUDE_PCIDSK_SEGMENT_PCIDSKADS40MODEL_H
+#ifndef INCLUDE_PCIDSK_SEGMENT_PCIDSKADS40MODEL_H
+#define INCLUDE_PCIDSK_SEGMENT_PCIDSKADS40MODEL_H
  
 #include "pcidsk_ads40.h"
 #include "segment/cpcidsksegment.h"
@@ -59,4 +59,4 @@ namespace PCIDSK {
     };
 }
 
-#endif // __INCLUDE_PCIDSK_SEGMENT_PCIDSKADS40MODEL_H
+#endif // INCLUDE_PCIDSK_SEGMENT_PCIDSKADS40MODEL_H
diff --git a/frmts/pcidsk/sdk/segment/cpcidskapmodel.cpp b/frmts/pcidsk/sdk/segment/cpcidskapmodel.cpp
index e31f6ea..611d190 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskapmodel.cpp
+++ b/frmts/pcidsk/sdk/segment/cpcidskapmodel.cpp
@@ -27,6 +27,7 @@
 #include "pcidsk_airphoto.h"
 #include "pcidsk_exception.h"
 #include "segment/cpcidskapmodel.h"
+#include "core/pcidsk_utils.h"
 
 #include <utility>
 #include <vector>
@@ -207,8 +208,8 @@ bool PCIDSKAPModelMiscParams::HasRadius(void) const
 /**
  * Create a new PCIDSK APMODEL segment
  */
-CPCIDSKAPModelSegment::CPCIDSKAPModelSegment(PCIDSKFile *file, int segment, const char *segment_pointer) : 
-    CPCIDSKSegment(file, segment, segment_pointer)
+CPCIDSKAPModelSegment::CPCIDSKAPModelSegment(PCIDSKFile *fileIn, int segmentIn, const char *segment_pointer) : 
+    CPCIDSKSegment(fileIn, segmentIn, segment_pointer)
 {
     filled_ = false;
     io_params_ = NULL;
@@ -227,7 +228,7 @@ CPCIDSKAPModelSegment::~CPCIDSKAPModelSegment()
 unsigned int CPCIDSKAPModelSegment::GetWidth(void) const
 {
     if (!filled_) {
-        ThrowPCIDSKException("Failed to determine width from APModel.");
+        return ThrowPCIDSKException(0 , "Failed to determine width from APModel.");
     }
     return width_;
 }
@@ -235,7 +236,7 @@ unsigned int CPCIDSKAPModelSegment::GetWidth(void) const
 unsigned int CPCIDSKAPModelSegment::GetHeight(void) const
 {
     if (!filled_) {
-        ThrowPCIDSKException("Failed to determine height from APModel.");
+        return ThrowPCIDSKException(0, "Failed to determine height from APModel.");
     }
     return height_;
 }
@@ -243,7 +244,7 @@ unsigned int CPCIDSKAPModelSegment::GetHeight(void) const
 unsigned int CPCIDSKAPModelSegment::GetDownsampleFactor(void) const
 {
     if (!filled_) {
-        ThrowPCIDSKException("Failed to determine APModel downsample factor.");
+        return ThrowPCIDSKException(0, "Failed to determine APModel downsample factor.");
     }
     return downsample_;
 }
@@ -252,7 +253,7 @@ unsigned int CPCIDSKAPModelSegment::GetDownsampleFactor(void) const
 PCIDSKAPModelIOParams const& CPCIDSKAPModelSegment::GetInteriorOrientationParams(void) const
 {
     if (io_params_ == NULL) {
-        ThrowPCIDSKException("There was a failure in reading the APModel IO params.");
+        throw PCIDSKException("There was a failure in reading the APModel IO params.");
     }
     return *io_params_;
 }
@@ -261,7 +262,7 @@ PCIDSKAPModelIOParams const& CPCIDSKAPModelSegment::GetInteriorOrientationParams
 PCIDSKAPModelEOParams const& CPCIDSKAPModelSegment::GetExteriorOrientationParams(void) const
 {
     if (eo_params_ == NULL) {
-        ThrowPCIDSKException("There was a failure in reading the APModel EO params.");
+        throw PCIDSKException("There was a failure in reading the APModel EO params.");
     }
     return *eo_params_;
 }
@@ -269,7 +270,7 @@ PCIDSKAPModelEOParams const& CPCIDSKAPModelSegment::GetExteriorOrientationParams
 PCIDSKAPModelMiscParams const& CPCIDSKAPModelSegment::GetAdditionalParams(void) const
 {
     if (misc_params_ == NULL) {
-        ThrowPCIDSKException("There was a failure in reading the APModel camera params.");
+        throw PCIDSKException("There was a failure in reading the APModel camera params.");
     }
     return *misc_params_;
 }
@@ -326,10 +327,10 @@ namespace {
     /*	Read the header block						    */
     /* -------------------------------------------------------------------- */
     
-        if(strncmp(buf.buffer,"APMODEL ",8))
+        if(!STARTS_WITH(buf.buffer,"APMODEL "))
         {
             std::string magic(buf.buffer, 8);
-            ThrowPCIDSKException("Bad segment magic found. Found: [%s] expecting [APMODEL ]",
+            return ThrowPCIDSKException("Bad segment magic found. Found: [%s] expecting [APMODEL ]",
                 magic.c_str());
         }
 
@@ -365,7 +366,7 @@ namespace {
         eo_params = new PCIDSKAPModelEOParams("",
                                               earth_to_body,
                                               perspective_centre,
-                                              -1);
+                                              0 /* FIXME?: this was originally -1 */);
     
         std::vector<double> x3d(3);
         std::vector<double> y3d(3);
@@ -465,7 +466,7 @@ namespace {
     /* -------------------------------------------------------------------- */
         buf.Get(512 * 4, 16, map_units);
     
-        if (!std::strncmp(buf.Get(512 * 4 + 16, 3), "UTM", 3))
+        if (STARTS_WITH(buf.Get(512 * 4 + 16, 3), "UTM"))
         {
             buf.Get(512 * 4, 3, utm_units);
         }
@@ -503,8 +504,8 @@ void CPCIDSKAPModelSegment::UpdateFromDisk(void)
     // Start reading in the APModel segment. APModel segments should be
     // 7 blocks long.
     if (data_size < (1024 + 7 * 512)) {
-        ThrowPCIDSKException("APMODEL segment is smaller than expected. A "
-            "segment of size %d was found", data_size);
+        return ThrowPCIDSKException("APMODEL segment is smaller than expected. A "
+            "segment of size %d was found", static_cast<int>(data_size));
     }
     buf.SetSize( (int) (data_size - 1024) );
     ReadFromFile(buf.buffer, 0, data_size - 1024);
diff --git a/frmts/pcidsk/sdk/segment/cpcidskapmodel.h b/frmts/pcidsk/sdk/segment/cpcidskapmodel.h
index d57e855..a29a142 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskapmodel.h
+++ b/frmts/pcidsk/sdk/segment/cpcidskapmodel.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_SEGMENT_CPCIDSKAPMODEL_H
-#define __INCLUDE_SEGMENT_CPCIDSKAPMODEL_H
+#ifndef INCLUDE_SEGMENT_CPCIDSKAPMODEL_H
+#define INCLUDE_SEGMENT_CPCIDSKAPMODEL_H
 
 #include "pcidsk_airphoto.h"
 #include "segment/cpcidsksegment.h"
@@ -76,5 +76,5 @@ namespace PCIDSK {
 
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_SEGMENT_CPCIDSKAPMODEL_H
+#endif // INCLUDE_SEGMENT_CPCIDSKAPMODEL_H
 
diff --git a/frmts/pcidsk/sdk/segment/cpcidskbinarysegment.cpp b/frmts/pcidsk/sdk/segment/cpcidskbinarysegment.cpp
index 567eaed..3e4c50d 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskbinarysegment.cpp
+++ b/frmts/pcidsk/sdk/segment/cpcidskbinarysegment.cpp
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Purpose:  Implementation of the CPCIDSKBinarySegment class.
- * 
+ *
  ******************************************************************************
  * Copyright (c) 2010
  * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
@@ -40,16 +40,16 @@ using namespace PCIDSK;
 
 /**
  * Binary Segment constructor
- * @param[in,out] file the PCIDSK file
- * @param[in] segment the segment index
- * @param[in] segment_pointer the segement pointer
+ * @param[in,out] fileIn the PCIDSK file
+ * @param[in] segmentIn the segment index
+ * @param[in] segment_pointer the segment pointer
  * @param[in] bLoad true to load the segment, else false (default true)
  */
-CPCIDSKBinarySegment::CPCIDSKBinarySegment(PCIDSKFile *file, 
-                                           int segment,
+CPCIDSKBinarySegment::CPCIDSKBinarySegment(PCIDSKFile *fileIn, 
+                                           int segmentIn,
                                            const char *segment_pointer,
                                            bool bLoad) :
-    CPCIDSKSegment(file, segment, segment_pointer),
+    CPCIDSKSegment(fileIn, segmentIn, segment_pointer),
     loaded_(false),mbModified(false)
 {
     if (true == bLoad)
@@ -75,12 +75,11 @@ void CPCIDSKBinarySegment::Load()
     }
 
     seg_data.SetSize((int)data_size - 1024);
-    
+
     ReadFromFile(seg_data.buffer, 0, data_size - 1024);
-    
+
     // Mark it as being loaded properly.
     loaded_ = true;
-    
 }
 
 /**
@@ -99,7 +98,7 @@ void CPCIDSKBinarySegment::Write(void)
 }
 
 /**
- * Synchronize the segement, if it was modified then
+ * Synchronize the segment, if it was modified then
  * write it into disk.
  */
 void CPCIDSKBinarySegment::Synchronize()
diff --git a/frmts/pcidsk/sdk/segment/cpcidskbinarysegment.h b/frmts/pcidsk/sdk/segment/cpcidskbinarysegment.h
index f3d9ce5..48a26e4 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskbinarysegment.h
+++ b/frmts/pcidsk/sdk/segment/cpcidskbinarysegment.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PCIDSK_SEGMENT_PCIDSKBINARY_SEG_H
-#define __INCLUDE_PCIDSK_SEGMENT_PCIDSKBINARY_SEG_H
+#ifndef INCLUDE_PCIDSK_SEGMENT_PCIDSKBINARY_SEG_H
+#define INCLUDE_PCIDSK_SEGMENT_PCIDSKBINARY_SEG_H
  
 #include "pcidsk_binary.h"
 #include "segment/cpcidsksegment.h"
@@ -70,4 +70,4 @@ namespace PCIDSK {
     };
 }
 
-#endif // __INCLUDE_PCIDSK_SEGMENT_PCIDSKBINARY_SEG_H
+#endif // INCLUDE_PCIDSK_SEGMENT_PCIDSKBINARY_SEG_H
diff --git a/frmts/pcidsk/sdk/segment/cpcidskbitmap.cpp b/frmts/pcidsk/sdk/segment/cpcidskbitmap.cpp
index 89013a5..e2ea940 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskbitmap.cpp
+++ b/frmts/pcidsk/sdk/segment/cpcidskbitmap.cpp
@@ -43,12 +43,16 @@ using namespace PCIDSK;
 /*                           CPCIDSKBitmap()                            */
 /************************************************************************/
 
-CPCIDSKBitmap::CPCIDSKBitmap( PCIDSKFile *file, int segment,
+CPCIDSKBitmap::CPCIDSKBitmap( PCIDSKFile *fileIn, int segmentIn,
                               const char *segment_pointer )
-        : CPCIDSKSegment( file, segment, segment_pointer )
+        : CPCIDSKSegment( fileIn, segmentIn, segment_pointer )
 
 {
     loaded = false;
+    width = 0;
+    height = 0;
+    block_width = 0;
+    block_height = 0;
 }
 
 /************************************************************************/
@@ -233,12 +237,12 @@ int CPCIDSKBitmap::ReadBlock( int block_index, void *buffer,
                               int win_xsize, int win_ysize )
 
 {
-    uint64 block_size = (block_width * block_height + 7) / 8;
+    uint64 block_size = (static_cast<uint64>(block_width) * block_height + 7) / 8;
     uint8 *wrk_buffer = (uint8 *) buffer;
 
     if( block_index < 0 || block_index >= GetBlockCount() )
     {
-        ThrowPCIDSKException( "Requested non-existent block (%d)", 
+        return ThrowPCIDSKException(0, "Requested non-existent block (%d)", 
                               block_index );
     }
 /* -------------------------------------------------------------------- */
@@ -253,14 +257,14 @@ int CPCIDSKBitmap::ReadBlock( int block_index, void *buffer,
         if( win_xoff < 0 || win_xoff + win_xsize > GetBlockWidth()
             || win_yoff < 0 || win_yoff + win_ysize > GetBlockHeight() )
         {
-            ThrowPCIDSKException( 
+            return ThrowPCIDSKException( 0,
                 "Invalid window in CPCIDSKBitmap::ReadBlock(): xoff=%d,yoff=%d,xsize=%d,ysize=%d",
                 win_xoff, win_yoff, win_xsize, win_ysize );
         }
 
         wrk_buffer = (uint8 *) malloc((size_t) block_size);
         if( wrk_buffer == NULL )
-            ThrowPCIDSKException( "Out of memory allocating %d bytes in CPCIDSKBitmap::ReadBlock()", 
+            return ThrowPCIDSKException(0, "Out of memory allocating %d bytes in CPCIDSKBitmap::ReadBlock()", 
                                   (int) block_size );
     }
 
@@ -277,7 +281,7 @@ int CPCIDSKBitmap::ReadBlock( int block_index, void *buffer,
         memset( buffer, 0, (size_t) block_size );
         
         short_block_size = 
-            ((height - block_index*block_height) * block_width + 7) / 8;
+            (static_cast<uint64>(height - block_index*block_height) * block_width + 7) / 8;
         
         ReadFromFile( wrk_buffer, block_size * block_index, short_block_size );
     }
@@ -310,7 +314,7 @@ int CPCIDSKBitmap::ReadBlock( int block_index, void *buffer,
 int CPCIDSKBitmap::WriteBlock( int block_index, void *buffer )
 
 {
-    uint64 block_size = (block_width * block_height) / 8;
+    uint64 block_size = (static_cast<uint64>(block_width) * block_height) / 8;
 
     if( (block_index+1) * block_height <= height )
         WriteToFile( buffer, block_size * block_index, block_size );
@@ -319,7 +323,7 @@ int CPCIDSKBitmap::WriteBlock( int block_index, void *buffer )
         uint64 short_block_size;
 
         short_block_size =
-            ((height - block_index*block_height) * block_width + 7) / 8;
+            (static_cast<uint64>(height - block_index*block_height) * block_width + 7) / 8;
 
         WriteToFile( buffer, block_size * block_index, short_block_size );
     }
@@ -340,11 +344,9 @@ int CPCIDSKBitmap::GetOverviewCount()
 /*                            GetOverview()                             */
 /************************************************************************/
 
-PCIDSKChannel *CPCIDSKBitmap::GetOverview( CPL_UNUSED int i )
+PCIDSKChannel *CPCIDSKBitmap::GetOverview( int i )
 {
-    // The %d is ignored in the exception.
-    ThrowPCIDSKException("Non-existent overview %d requested on bitmap segment.");
-    return NULL;
+    return (PCIDSKChannel*) ThrowPCIDSKExceptionPtr("Non-existent overview %d requested on bitmap segment.", i);
 }
 
 /************************************************************************/
@@ -500,7 +502,7 @@ void CPCIDSKBitmap::SetChanInfo( CPL_UNUSED std::string filename, CPL_UNUSED uin
                                  CPL_UNUSED uint64 pixel_offset, CPL_UNUSED uint64 line_offset,
                                  CPL_UNUSED bool little_endian )
 {
-    ThrowPCIDSKException( "Attempt to SetChanInfo() on a bitmap." );
+    return ThrowPCIDSKException( "Attempt to SetChanInfo() on a bitmap." );
 }
 
 /************************************************************************/
@@ -526,5 +528,5 @@ void CPCIDSKBitmap::SetEChanInfo( CPL_UNUSED std::string filename, CPL_UNUSED in
                                   CPL_UNUSED int exoff, CPL_UNUSED int eyoff,
                                   CPL_UNUSED int exsize, CPL_UNUSED int eysize )
 {
-    ThrowPCIDSKException( "Attempt to SetEChanInfo() on a bitmap." );
+    return ThrowPCIDSKException( "Attempt to SetEChanInfo() on a bitmap." );
 }
diff --git a/frmts/pcidsk/sdk/segment/cpcidskbitmap.h b/frmts/pcidsk/sdk/segment/cpcidskbitmap.h
index 826125b..5f4494e 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskbitmap.h
+++ b/frmts/pcidsk/sdk/segment/cpcidskbitmap.h
@@ -25,8 +25,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef __INCLUDE_SEGMENT_PCIDSKBITMAP_H
-#define __INCLUDE_SEGMENT_PCIDSKBITMAP_H
+#ifndef INCLUDE_SEGMENT_PCIDSKBITMAP_H
+#define INCLUDE_SEGMENT_PCIDSKBITMAP_H
 
 #include "pcidsk_config.h"
 #include "pcidsk_types.h"
@@ -110,4 +110,4 @@ namespace PCIDSK
     };
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_SEGMENT_PCIDSKBITMAP_H
+#endif // INCLUDE_SEGMENT_PCIDSKBITMAP_H
diff --git a/frmts/pcidsk/sdk/segment/cpcidskephemerissegment.cpp b/frmts/pcidsk/sdk/segment/cpcidskephemerissegment.cpp
index 5b0e3da..fdbc750 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskephemerissegment.cpp
+++ b/frmts/pcidsk/sdk/segment/cpcidskephemerissegment.cpp
@@ -56,16 +56,16 @@ namespace
 
 /**
  * Ephemeris Segment constructor
- * @param file the PCIDSK file
- * @param segment the segment index
- * @param segment_pointer the segement pointer
+ * @param fileIn the PCIDSK file
+ * @param segmentIn the segment index
+ * @param segment_pointer the segment pointer
  * @param bLoad true to load the segment, else false (default true)
  */
-CPCIDSKEphemerisSegment::CPCIDSKEphemerisSegment(PCIDSKFile *file, 
-                                                   int segment,
+CPCIDSKEphemerisSegment::CPCIDSKEphemerisSegment(PCIDSKFile *fileIn, 
+                                                   int segmentIn,
                                                    const char *segment_pointer,
                                                    bool bLoad) :
-    CPCIDSKSegment(file, segment, segment_pointer),
+    CPCIDSKSegment(fileIn, segmentIn, segment_pointer),
     loaded_(false),mbModified(false)
 {
     mpoEphemeris = NULL;
@@ -97,19 +97,18 @@ void CPCIDSKEphemerisSegment::Load()
 
     // We test the name of the binary segment before starting to read 
     // the buffer.
-    if (std::strncmp(seg_data.buffer, "ORBIT   ", 8)) 
+    if (!STARTS_WITH(seg_data.buffer, "ORBIT   ")) 
     {
         seg_data.Put("ORBIT   ",0,8);
         loaded_ = true;
         return ;
     }
-    
+
     mpoEphemeris = BinaryToEphemeris(0);
 
     // We've now loaded the structure up with data. Mark it as being loaded 
     // properly.
     loaded_ = true;
-    
 }
 
 /**
@@ -131,7 +130,7 @@ void CPCIDSKEphemerisSegment::Write(void)
 }
 
 /**
- * Synchronize the segement, if it was modified then
+ * Synchronize the segment, if it was modified then
  * write it into disk.
  */
 void CPCIDSKEphemerisSegment::Synchronize()
@@ -175,7 +174,6 @@ double CPCIDSKEphemerisSegment::ConvertDeg(double degree, int mode)
 	    result = 360 + degree;
 	else
 	    result = degree;
-	
     }
     return (result);
 }
@@ -183,12 +181,12 @@ double CPCIDSKEphemerisSegment::ConvertDeg(double degree, int mode)
 /************************************************************************/
 /*		      ReadAvhrrEphemerisSegment()                       */
 /************************************************************************/
-/**                                                                      
- *  Read the contents of blocks 9, 11, and onwards from the orbit	
- *  segment into the EphemerisSeg_t structure.	
+/**
+ *  Read the contents of blocks 9, 11, and onwards from the orbit
+ *  segment into the EphemerisSeg_t structure.
  * @param nStartBlock where to start to read in the buffer
  * @param psEphSegRec the structure to populate with information.
- */   
+ */
 void 
 CPCIDSKEphemerisSegment::ReadAvhrrEphemerisSegment(int nStartBlock,
                                          EphemerisSeg_t *psEphSegRec)
@@ -205,21 +203,20 @@ CPCIDSKEphemerisSegment::ReadAvhrrEphemerisSegment(int nStartBlock,
     as = psEphSegRec->AvhrrSeg;
 
 /* -------------------------------------------------------------------- */
-/*  Read in the Nineth Block which contains general info + ephemeris	*/
-/*  info as well.							*/
+/*  Read in the Ninth Block which contains general info + ephemeris     */
+/*  info as well.                                                       */
 /* -------------------------------------------------------------------- */
     nPos = nStartBlock + 8*512;
-    
+
     as->szImageFormat = seg_data.Get(nPos, 16);
     as->nImageXSize = seg_data.GetInt(nPos+16, 16);
     as->nImageYSize = seg_data.GetInt(nPos+32, 16);
 
-    
-    if ( std::strncmp(seg_data.Get(nPos+48,9), "ASCENDING", 9)==0 )
+    if ( STARTS_WITH(seg_data.Get(nPos+48,9), "ASCENDING") )
         as->bIsAscending = true;
     else
         as->bIsAscending = false;
-    if ( std::strncmp(seg_data.Get(nPos+64,7), "ROTATED", 7)==0 )
+    if ( STARTS_WITH(seg_data.Get(nPos+64,7), "ROTATED") )
         as->bIsImageRotated = true;
     else
         as->bIsImageRotated = false;
@@ -320,16 +317,16 @@ CPCIDSKEphemerisSegment::ReadAvhrrScanlineRecord(int nPos,
     sr->nStartScanTimeGMTMsec = ReadAvhrrInt32((unsigned char*)seg_data.Get(nPos+4,4));
 
     for(i = 0; i < 10; ++i)
-        sr->abyScanLineQuality[i] = seg_data.GetInt(nPos+8+i,1);
+        sr->abyScanLineQuality[i] = static_cast<unsigned char>(seg_data.GetInt(nPos+8+i,1));
 
     for(i = 0; i < 5; ++i)
     {
-        sr->aabyBadBandIndicators[i][0] = seg_data.GetInt(nPos+18+2*i,1);
-        sr->aabyBadBandIndicators[i][1] = seg_data.GetInt(nPos+18+2*i+1,1);
+        sr->aabyBadBandIndicators[i][0] = static_cast<unsigned char>(seg_data.GetInt(nPos+18+2*i,1));
+        sr->aabyBadBandIndicators[i][1] = static_cast<unsigned char>(seg_data.GetInt(nPos+18+2*i+1,1));
     }
 
     for(i = 0; i < 8; ++i)
-        sr->abySatelliteTimeCode[i] = seg_data.GetInt(nPos+28+i,1);
+        sr->abySatelliteTimeCode[i] = static_cast<unsigned char>(seg_data.GetInt(nPos+28+i,1));
 
     for(i = 0; i < 3; ++i)
         sr->anTargetTempData[i] = ReadAvhrrInt32((unsigned char*)seg_data.Get(nPos+36+i*4,4));
@@ -360,8 +357,8 @@ CPCIDSKEphemerisSegment::ReadAvhrrInt32(unsigned char* pbyBuf)
 /************************************************************************/
 /*		      WriteAvhrrEphemerisSegment()                      */
 /************************************************************************/
-/**                                                                      
- *  Write the contents of blocks 9, 10, and onwards to the orbit	
+/**
+ *  Write the contents of blocks 9, 10, and onwards to the orbit
  *  segment from fields in the EphemerisSeg_t structure.
  * @param nStartBlock where to start to write the information in the buffer
  * @param psEphSegRec the information to write.
@@ -380,7 +377,7 @@ CPCIDSKEphemerisSegment::WriteAvhrrEphemerisSegment(int nStartBlock,
 
     if ( as == NULL)
     {
-	throw PCIDSKException("The AvhrrSeg is NULL.");
+	return ThrowPCIDSKException("The AvhrrSeg is NULL.");
     }
 
 /* -------------------------------------------------------------------- */
@@ -440,7 +437,7 @@ CPCIDSKEphemerisSegment::WriteAvhrrEphemerisSegment(int nStartBlock,
     seg_data.Put(as->szInclination.c_str(),nPos+432,16,true);
     seg_data.Put(as->szMeanAnomaly.c_str(),nPos+448,16,true);
     seg_data.Put(as->szSemiMajorAxis.c_str(),nPos+464,16,true);
-   
+
 /* -------------------------------------------------------------------- */
 /*  second avhrr block is all zeros.					*/
 /* -------------------------------------------------------------------- */
@@ -449,7 +446,7 @@ CPCIDSKEphemerisSegment::WriteAvhrrEphemerisSegment(int nStartBlock,
 /*  Write the 3rd avhrr Block.                                          */
 /* -------------------------------------------------------------------- */
     nPos = nStartBlock + 512*2;
-    
+
     seg_data.Put(as->nRecordSize,nPos,16);
     seg_data.Put(as->nBlockSize,nPos+16,16);
     seg_data.Put(as->nNumRecordsPerBlock,nPos+32,16);
@@ -523,7 +520,7 @@ CPCIDSKEphemerisSegment::WriteAvhrrScanlineRecord(
         WriteAvhrrInt32(sr->anSpaceScanData[i],  b+(60+i*4));
 
 }
- 
+
 /************************************************************************/
 /*			   WriteAvhrrInt32()                            */
 /************************************************************************/
@@ -535,10 +532,10 @@ CPCIDSKEphemerisSegment::WriteAvhrrScanlineRecord(
 void CPCIDSKEphemerisSegment::WriteAvhrrInt32(int nValue, 
                                               unsigned char* pbyBuf)
 {
-    pbyBuf[0] = ((nValue & 0xff000000) >> 24);
-    pbyBuf[1] = ((nValue & 0x00ff0000) >> 16);
-    pbyBuf[2] = ((nValue & 0x0000ff00) >> 8);
-    pbyBuf[3] =  (nValue & 0x000000ff);
+    pbyBuf[0] = static_cast<unsigned char>((nValue & 0xff000000) >> 24);
+    pbyBuf[1] = static_cast<unsigned char>((nValue & 0x00ff0000) >> 16);
+    pbyBuf[2] = static_cast<unsigned char>((nValue & 0x0000ff00) >> 8);
+    pbyBuf[3] = static_cast<unsigned char>(nValue & 0x000000ff);
 }
 
 
@@ -546,204 +543,204 @@ void CPCIDSKEphemerisSegment::WriteAvhrrInt32(int nValue,
 /*                        BinaryToEphemeris()                           */
 /************************************************************************/
 /**
- * Read binary information from a binary buffer to create an 
+ * Read binary information from a binary buffer to create an
  * EphemerisSeg_t structure. The caller is responsible to free the memory
  * of the returned structure with delete.
  *
  * @param nStartBlock where to start read the orbit info into the buffer.
- * @return the orbbit information 
+ * @return the orbit information.
  */
 EphemerisSeg_t *
 CPCIDSKEphemerisSegment::BinaryToEphemeris( int nStartBlock )
 
 {
-    EphemerisSeg_t *segment;
+    EphemerisSeg_t *l_segment;
     int		i;
     int nPos = nStartBlock;
 
-    segment = new EphemerisSeg_t();
-    
+    l_segment = new EphemerisSeg_t();
+
 /* -------------------------------------------------------------------- */
 /*	Process first block.						*/
 /* -------------------------------------------------------------------- */
-    
-    segment->SatelliteDesc = seg_data.Get(nPos+8,32);  
-    segment->SceneID = seg_data.Get(nPos+40, 32);
+
+    l_segment->SatelliteDesc = seg_data.Get(nPos+8,32);  
+    l_segment->SceneID = seg_data.Get(nPos+40, 32);
 
 /* -------------------------------------------------------------------- */
 /*	Process the second block.					*/
 /* -------------------------------------------------------------------- */
     nPos = nStartBlock + 512;
 
-    segment->SatelliteSensor = seg_data.Get(nPos, 16);
+    l_segment->SatelliteSensor = seg_data.Get(nPos, 16);
     for (i=0; i<16; i++)
     {
-        if (segment->SatelliteSensor[i] == ' ')
+        if (l_segment->SatelliteSensor[i] == ' ')
         {
-            segment->SatelliteSensor = segment->SatelliteSensor.substr(0,i);
+            l_segment->SatelliteSensor = l_segment->SatelliteSensor.substr(0,i);
             break;
         }
     }
 
-    segment->SensorNo = seg_data.Get(nPos+22, 2);
-    segment->DateImageTaken = seg_data.Get(nPos+44, 22);
+    l_segment->SensorNo = seg_data.Get(nPos+22, 2);
+    l_segment->DateImageTaken = seg_data.Get(nPos+44, 22);
 
     if (seg_data.buffer[nPos+66] == 'Y' || 
         seg_data.buffer[nPos+66] == 'y')
-        segment->SupSegExist = true;
+        l_segment->SupSegExist = true;
     else
-        segment->SupSegExist = false;
-    segment->FieldOfView = seg_data.GetDouble(nPos+88, 22); 
-    segment->ViewAngle = seg_data.GetDouble(nPos+110, 22);
-    segment->NumColCentre = seg_data.GetDouble(nPos+132, 22);
-    segment->RadialSpeed = seg_data.GetDouble(nPos+154, 22);
-    segment->Eccentricity = seg_data.GetDouble(nPos+176, 22);
-    segment->Height = seg_data.GetDouble(nPos+198, 22);
-    segment->Inclination = seg_data.GetDouble(nPos+220, 22);
-    segment->TimeInterval = seg_data.GetDouble(nPos+242, 22);
-    segment->NumLineCentre = seg_data.GetDouble(nPos+264, 22);
-    segment->LongCentre = seg_data.GetDouble(nPos+286, 22);
-    segment->AngularSpd = seg_data.GetDouble(nPos+308, 22);		
-    segment->AscNodeLong = seg_data.GetDouble(nPos+330, 22);
-    segment->ArgPerigee = seg_data.GetDouble(nPos+352, 22);
-    segment->LatCentre = seg_data.GetDouble(nPos+374, 22);
-    segment->EarthSatelliteDist = seg_data.GetDouble(nPos+396, 22);
-    segment->NominalPitch = seg_data.GetDouble(nPos+418, 22);
-    segment->TimeAtCentre = seg_data.GetDouble(nPos+440, 22);
-    segment->SatelliteArg = seg_data.GetDouble(nPos+462, 22);
-    segment->bDescending = true;
+        l_segment->SupSegExist = false;
+    l_segment->FieldOfView = seg_data.GetDouble(nPos+88, 22); 
+    l_segment->ViewAngle = seg_data.GetDouble(nPos+110, 22);
+    l_segment->NumColCentre = seg_data.GetDouble(nPos+132, 22);
+    l_segment->RadialSpeed = seg_data.GetDouble(nPos+154, 22);
+    l_segment->Eccentricity = seg_data.GetDouble(nPos+176, 22);
+    l_segment->Height = seg_data.GetDouble(nPos+198, 22);
+    l_segment->Inclination = seg_data.GetDouble(nPos+220, 22);
+    l_segment->TimeInterval = seg_data.GetDouble(nPos+242, 22);
+    l_segment->NumLineCentre = seg_data.GetDouble(nPos+264, 22);
+    l_segment->LongCentre = seg_data.GetDouble(nPos+286, 22);
+    l_segment->AngularSpd = seg_data.GetDouble(nPos+308, 22);		
+    l_segment->AscNodeLong = seg_data.GetDouble(nPos+330, 22);
+    l_segment->ArgPerigee = seg_data.GetDouble(nPos+352, 22);
+    l_segment->LatCentre = seg_data.GetDouble(nPos+374, 22);
+    l_segment->EarthSatelliteDist = seg_data.GetDouble(nPos+396, 22);
+    l_segment->NominalPitch = seg_data.GetDouble(nPos+418, 22);
+    l_segment->TimeAtCentre = seg_data.GetDouble(nPos+440, 22);
+    l_segment->SatelliteArg = seg_data.GetDouble(nPos+462, 22);
+    l_segment->bDescending = true;
     if (seg_data.buffer[nPos+484] == 'A')
-        segment->bDescending = false;
+        l_segment->bDescending = false;
 
 /* -------------------------------------------------------------------- */
 /*	Process the third block.					*/
 /* -------------------------------------------------------------------- */
     nPos = nStartBlock + 2*512;
 
-    segment->XCentre = seg_data.GetDouble(nPos, 22);
-    segment->YCentre = seg_data.GetDouble(nPos+22, 22);
-    segment->UtmXCentre = seg_data.GetDouble(nPos+44, 22);
-    segment->UtmYCentre = seg_data.GetDouble(nPos+66, 22);
-    segment->PixelRes = seg_data.GetDouble(nPos+88, 22);
-    segment->LineRes = seg_data.GetDouble(nPos+110, 22);
+    l_segment->XCentre = seg_data.GetDouble(nPos, 22);
+    l_segment->YCentre = seg_data.GetDouble(nPos+22, 22);
+    l_segment->UtmXCentre = seg_data.GetDouble(nPos+44, 22);
+    l_segment->UtmYCentre = seg_data.GetDouble(nPos+66, 22);
+    l_segment->PixelRes = seg_data.GetDouble(nPos+88, 22);
+    l_segment->LineRes = seg_data.GetDouble(nPos+110, 22);
     if (seg_data.buffer[nPos+132] == 'Y' || 
         seg_data.buffer[nPos+132] == 'y')
-        segment->CornerAvail = true;
+        l_segment->CornerAvail = true;
     else
-        segment->CornerAvail = false;
-    segment->MapUnit = seg_data.Get(nPos+133, 16);
-
-    segment->XUL = seg_data.GetDouble(nPos+149, 22);
-    segment->YUL = seg_data.GetDouble(nPos+171, 22);
-    segment->XUR = seg_data.GetDouble(nPos+193, 22);
-    segment->YUR = seg_data.GetDouble(nPos+215, 22);
-    segment->XLR = seg_data.GetDouble(nPos+237, 22);
-    segment->YLR = seg_data.GetDouble(nPos+259, 22);
-    segment->XLL = seg_data.GetDouble(nPos+281, 22);
-    segment->YLL = seg_data.GetDouble(nPos+303, 22);
-    segment->UtmXUL = seg_data.GetDouble(nPos+325, 22);
-    segment->UtmYUL = seg_data.GetDouble(nPos+347, 22);
-    segment->UtmXUR = seg_data.GetDouble(nPos+369, 22);
-    segment->UtmYUR = seg_data.GetDouble(nPos+391, 22);
-    segment->UtmXLR = seg_data.GetDouble(nPos+413, 22);
-    segment->UtmYLR = seg_data.GetDouble(nPos+435, 22);
-    segment->UtmXLL = seg_data.GetDouble(nPos+457, 22);
-    segment->UtmYLL = seg_data.GetDouble(nPos+479, 22);
+        l_segment->CornerAvail = false;
+    l_segment->MapUnit = seg_data.Get(nPos+133, 16);
+
+    l_segment->XUL = seg_data.GetDouble(nPos+149, 22);
+    l_segment->YUL = seg_data.GetDouble(nPos+171, 22);
+    l_segment->XUR = seg_data.GetDouble(nPos+193, 22);
+    l_segment->YUR = seg_data.GetDouble(nPos+215, 22);
+    l_segment->XLR = seg_data.GetDouble(nPos+237, 22);
+    l_segment->YLR = seg_data.GetDouble(nPos+259, 22);
+    l_segment->XLL = seg_data.GetDouble(nPos+281, 22);
+    l_segment->YLL = seg_data.GetDouble(nPos+303, 22);
+    l_segment->UtmXUL = seg_data.GetDouble(nPos+325, 22);
+    l_segment->UtmYUL = seg_data.GetDouble(nPos+347, 22);
+    l_segment->UtmXUR = seg_data.GetDouble(nPos+369, 22);
+    l_segment->UtmYUR = seg_data.GetDouble(nPos+391, 22);
+    l_segment->UtmXLR = seg_data.GetDouble(nPos+413, 22);
+    l_segment->UtmYLR = seg_data.GetDouble(nPos+435, 22);
+    l_segment->UtmXLL = seg_data.GetDouble(nPos+457, 22);
+    l_segment->UtmYLL = seg_data.GetDouble(nPos+479, 22);
     
 /* -------------------------------------------------------------------- */
 /*      Process the 4th block (Corner lat/long coordinates)             */
 /* -------------------------------------------------------------------- */
     nPos = nStartBlock + 3*512;
 
-    segment->LongCentreDeg = seg_data.GetDouble(nPos, 16);
-    segment->LatCentreDeg = seg_data.GetDouble(nPos+16, 16);
-    segment->LongUL =  seg_data.GetDouble(nPos+32, 16);
-    segment->LatUL = seg_data.GetDouble(nPos+48, 16);
-    segment->LongUR =  seg_data.GetDouble(nPos+64, 16);
-    segment->LatUR = seg_data.GetDouble(nPos+80, 16);
-    segment->LongLR = seg_data.GetDouble(nPos+96, 16);
-    segment->LatLR = seg_data.GetDouble(nPos+112, 16);
-    segment->LongLL = seg_data.GetDouble(nPos+128, 16);
-    segment->LatLL = seg_data.GetDouble(nPos+144, 16);
-    segment->HtCentre = seg_data.GetDouble(nPos+160, 16);
-    segment->HtUL = seg_data.GetDouble(nPos+176, 16);
-    segment->HtUR = seg_data.GetDouble(nPos+192, 16);
-    segment->HtLR = seg_data.GetDouble(nPos+208, 16);
-    segment->HtLL = seg_data.GetDouble(nPos+224, 16);
+    l_segment->LongCentreDeg = seg_data.GetDouble(nPos, 16);
+    l_segment->LatCentreDeg = seg_data.GetDouble(nPos+16, 16);
+    l_segment->LongUL =  seg_data.GetDouble(nPos+32, 16);
+    l_segment->LatUL = seg_data.GetDouble(nPos+48, 16);
+    l_segment->LongUR =  seg_data.GetDouble(nPos+64, 16);
+    l_segment->LatUR = seg_data.GetDouble(nPos+80, 16);
+    l_segment->LongLR = seg_data.GetDouble(nPos+96, 16);
+    l_segment->LatLR = seg_data.GetDouble(nPos+112, 16);
+    l_segment->LongLL = seg_data.GetDouble(nPos+128, 16);
+    l_segment->LatLL = seg_data.GetDouble(nPos+144, 16);
+    l_segment->HtCentre = seg_data.GetDouble(nPos+160, 16);
+    l_segment->HtUL = seg_data.GetDouble(nPos+176, 16);
+    l_segment->HtUR = seg_data.GetDouble(nPos+192, 16);
+    l_segment->HtLR = seg_data.GetDouble(nPos+208, 16);
+    l_segment->HtLL = seg_data.GetDouble(nPos+224, 16);
 
 /* -------------------------------------------------------------------- */
 /*      Process the 5th block.                                          */
 /* -------------------------------------------------------------------- */
     nPos = nStartBlock + 512*4;
 
-    segment->ImageRecordLength = seg_data.GetInt(nPos, 16);
-    segment->NumberImageLine = seg_data.GetInt(nPos+16, 16);
-    segment->NumberBytePerPixel = seg_data.GetInt(nPos+32, 16);
-    segment->NumberSamplePerLine = seg_data.GetInt(nPos+48, 16);
-    segment->NumberPrefixBytes = seg_data.GetInt(nPos+64, 16);
-    segment->NumberSuffixBytes = seg_data.GetInt(nPos+80, 16);
+    l_segment->ImageRecordLength = seg_data.GetInt(nPos, 16);
+    l_segment->NumberImageLine = seg_data.GetInt(nPos+16, 16);
+    l_segment->NumberBytePerPixel = seg_data.GetInt(nPos+32, 16);
+    l_segment->NumberSamplePerLine = seg_data.GetInt(nPos+48, 16);
+    l_segment->NumberPrefixBytes = seg_data.GetInt(nPos+64, 16);
+    l_segment->NumberSuffixBytes = seg_data.GetInt(nPos+80, 16);
 
 /* -------------------------------------------------------------------- */
 /*      Process the 6th and 7th block.                                  */
 /* -------------------------------------------------------------------- */
     nPos = nStartBlock + 5*512;
 
-    segment->SPNCoeff = 0;
+    l_segment->SPNCoeff = 0;
 
-    if(std::strncmp(seg_data.Get(nPos,8), "SPOT1BOD", 8)==0 ||
-       std::strncmp(seg_data.Get(nPos,8), "SPOT1BNW", 8)==0)
+    if(STARTS_WITH(seg_data.Get(nPos,8), "SPOT1BOD") ||
+       STARTS_WITH(seg_data.Get(nPos,8), "SPOT1BNW"))
     {
-        segment->SPNCoeff = seg_data.GetInt(nPos+22, 22);
+        l_segment->SPNCoeff = seg_data.GetInt(nPos+22, 22);
         for (i=0; i<20; i++)   
         {
-            segment->SPCoeff1B[i] = 
+            l_segment->SPCoeff1B[i] = 
                 seg_data.GetDouble(nPos+(i+2)*22, 22);
         }
 
-        if (std::strncmp(seg_data.Get(nPos,8), "SPOT1BNW", 8)==0)
+        if (STARTS_WITH(seg_data.Get(nPos,8), "SPOT1BNW"))
         {
             nPos = nStartBlock + 6*512;
 
             for (i=0; i<19; i++)   
             {
-                segment->SPCoeff1B[i+20] = 
+                l_segment->SPCoeff1B[i+20] = 
                     seg_data.GetDouble(nPos+i*22, 22);
             }
-            segment->SPCoeffSg[0] = seg_data.GetInt(nPos+418, 8);
-            segment->SPCoeffSg[1] = seg_data.GetInt(nPos+426, 8);
-            segment->SPCoeffSg[2] = seg_data.GetInt(nPos+434, 8);
-            segment->SPCoeffSg[3] = seg_data.GetInt(nPos+442, 8);
+            l_segment->SPCoeffSg[0] = seg_data.GetInt(nPos+418, 8);
+            l_segment->SPCoeffSg[1] = seg_data.GetInt(nPos+426, 8);
+            l_segment->SPCoeffSg[2] = seg_data.GetInt(nPos+434, 8);
+            l_segment->SPCoeffSg[3] = seg_data.GetInt(nPos+442, 8);
         }
     }
 
 /* -------------------------------------------------------------------- */
-/*	6th and 7th block of ORBIT segment are blank.			*/
+/*	6th and 7th block of ORBIT l_segment are blank.			*/
 /*	Read in the 8th block.						*/
 /* -------------------------------------------------------------------- */
     nPos = nStartBlock + 7*512;
     
-    if (std::strncmp(seg_data.Get(nPos,8), "ATTITUDE", 8)==0)
-        segment->Type = OrbAttitude;
-    else if (std::strncmp(seg_data.Get(nPos,8), "RADAR   ", 8)==0)
-        segment->Type = OrbLatLong;
-    else if (std::strncmp(seg_data.Get(nPos,8), "AVHRR   ", 8)==0)
-        segment->Type = OrbAvhrr;
-    else if (std::strncmp(seg_data.Get(nPos,8), "NO_DATA ", 8)==0)
-        segment->Type = OrbNone;
+    if (STARTS_WITH(seg_data.Get(nPos,8), "ATTITUDE"))
+        l_segment->Type = OrbAttitude;
+    else if (STARTS_WITH(seg_data.Get(nPos,8), "RADAR   "))
+        l_segment->Type = OrbLatLong;
+    else if (STARTS_WITH(seg_data.Get(nPos,8), "AVHRR   "))
+        l_segment->Type = OrbAvhrr;
+    else if (STARTS_WITH(seg_data.Get(nPos,8), "NO_DATA "))
+        l_segment->Type = OrbNone;
     else
-        throw PCIDSKException("Invalid Orbit type found: [%s]", 
+        return (EphemerisSeg_t*)ThrowPCIDSKExceptionPtr("Invalid Orbit type found: [%s]", 
                               seg_data.Get(nPos,8));
 
 /* -------------------------------------------------------------------- */
-/*	Orbit segment is a Satellite Attitude Segment(ATTITUDE) only	*/
+/*	Orbit l_segment is a Satellite Attitude Segment(ATTITUDE) only	*/
 /*	for SPOT 1A.							*/
 /* -------------------------------------------------------------------- */
-    if (segment->Type == OrbAttitude)
+    if (l_segment->Type == OrbAttitude)
     {
         AttitudeSeg_t 	*AttitudeSeg;
         int		nBlock, nData;
 
-        AttitudeSeg = segment->AttitudeSeg = new AttitudeSeg_t();  
+        AttitudeSeg = l_segment->AttitudeSeg = new AttitudeSeg_t();  
 	
 /* -------------------------------------------------------------------- */
 /*	Read in the 9th block.						*/
@@ -791,21 +788,21 @@ CPCIDSKEphemerisSegment::BinaryToEphemeris( int nStartBlock )
 
         if (nData != AttitudeSeg->NumberOfLine)
         {
-            throw PCIDSKException("Number of data line read (%d) "
+            return (EphemerisSeg_t*)ThrowPCIDSKExceptionPtr("Number of data line read (%d) "
                      "does not matches with what is specified in "
-                     "the segment (%d).\n", nData, 
+                     "the l_segment (%d).\n", nData, 
                      AttitudeSeg->NumberOfLine);
         }
     }
 /* -------------------------------------------------------------------- */
-/*	Radar segment (LATLONG)						*/
+/*	Radar l_segment (LATLONG)						*/
 /* -------------------------------------------------------------------- */
-    else if (segment->Type == OrbLatLong)
+    else if (l_segment->Type == OrbLatLong)
     {
         RadarSeg_t *RadarSeg;
         int	nBlock, nData;
 
-        RadarSeg = segment->RadarSeg = new RadarSeg_t(); 
+        RadarSeg = l_segment->RadarSeg = new RadarSeg_t(); 
 /* -------------------------------------------------------------------- */
 /*	Read in the 9th block.						*/
 /* -------------------------------------------------------------------- */
@@ -925,21 +922,21 @@ CPCIDSKEphemerisSegment::BinaryToEphemeris( int nStartBlock )
 
         if (RadarSeg->NumberData != nData)
         {
-            throw PCIDSKException("Number "
+            return (EphemerisSeg_t*)ThrowPCIDSKExceptionPtr("Number "
 		     "of data lines read (%d) does not match with"
-                     "\nwhat is specified in segment (%d).\n", nData, 
+                     "\nwhat is specified in l_segment (%d).\n", nData, 
                      RadarSeg->NumberData);
         }
     }
 /* -------------------------------------------------------------------- */
-/*	AVHRR segment 							*/
+/*	AVHRR l_segment 							*/
 /* -------------------------------------------------------------------- */
-    else if (segment->Type == OrbAvhrr)
+    else if (l_segment->Type == OrbAvhrr)
     {
-        ReadAvhrrEphemerisSegment( nStartBlock, segment);
+        ReadAvhrrEphemerisSegment( nStartBlock, l_segment);
     }
 
-    return segment;
+    return l_segment;
 }
 
 /************************************************************************/
@@ -1149,7 +1146,7 @@ CPCIDSKEphemerisSegment::EphemerisToBinary( EphemerisSeg_t * psOrbit,
         seg_data.Put("NO_DATA ",nPos,8);
     else
     {
-        throw PCIDSKException("Invalid Orbit type."); 
+        return ThrowPCIDSKException("Invalid Orbit type."); 
     }
 
 /* ==================================================================== */
@@ -1165,19 +1162,19 @@ CPCIDSKEphemerisSegment::EphemerisToBinary( EphemerisSeg_t * psOrbit,
 
         if (AttitudeSeg == NULL)
         {
-            throw PCIDSKException("The AttitudeSeg is NULL.");
+            return ThrowPCIDSKException("The AttitudeSeg is NULL.");
         }
 
 /* -------------------------------------------------------------------- */
 /*      Add one block                                                   */
 /* -------------------------------------------------------------------- */
         seg_data.SetSize(seg_data.buffer_size + 512);
-            
+
         nPos = nStartBlock + 512*8;
         memset(seg_data.buffer+nPos,' ',512);
-            
+
 /* -------------------------------------------------------------------- */
-/*	Write the nineth block.						*/
+/*      Write the ninth block.                                          */
 /* -------------------------------------------------------------------- */
 
         seg_data.Put(AttitudeSeg->Roll,nPos,22,"%22.14f");
@@ -1199,18 +1196,17 @@ CPCIDSKEphemerisSegment::EphemerisToBinary( EphemerisSeg_t * psOrbit,
 /* -------------------------------------------------------------------- */
         seg_data.SetSize(seg_data.buffer_size + 
                                  512 * AttitudeSeg->NumberBlockData);
-            
+
         nPos = nStartBlock + 512*9;
         memset(seg_data.buffer+nPos,' ',
                512 * AttitudeSeg->NumberBlockData);
-            
+
 /* -------------------------------------------------------------------- */
 /*	Write out the line required.					*/
 /* -------------------------------------------------------------------- */
         for (nBlock=0, nData=0; nBlock<AttitudeSeg->NumberBlockData; 
              nBlock++)
         {
-            int		i;
             nPos = nStartBlock + 512*(nBlock + 9);
 
 /* -------------------------------------------------------------------- */
@@ -1232,7 +1228,7 @@ CPCIDSKEphemerisSegment::EphemerisToBinary( EphemerisSeg_t * psOrbit,
 
         if (nData != AttitudeSeg->NumberOfLine)
         {
-            throw PCIDSKException("Number of data line written"
+            return ThrowPCIDSKException("Number of data line written"
 		    " (%d) does not match with\nwhat is specified "
 		    " in the segment (%d).\n", 
 		    nData, AttitudeSeg->NumberOfLine);
@@ -1245,27 +1241,26 @@ CPCIDSKEphemerisSegment::EphemerisToBinary( EphemerisSeg_t * psOrbit,
     else if (psOrbit->Type == OrbLatLong)
     {
         RadarSeg_t *RadarSeg;
-        int	   i, nBlock, nData;
+        int	   nBlock, nData;
 
         RadarSeg = psOrbit->RadarSeg;
 
         if (RadarSeg == NULL)
         {
-            throw PCIDSKException("The RadarSeg is NULL.");
+            return ThrowPCIDSKException("The RadarSeg is NULL.");
         }
 
 /* -------------------------------------------------------------------- */
 /*      Add two blocks.                                                 */
 /* -------------------------------------------------------------------- */
         seg_data.SetSize(seg_data.buffer_size + 512*2);
-            
+
         nPos = nStartBlock + 512*8;
         memset(seg_data.buffer+nPos,' ', 512*2);
-            
+
 /* -------------------------------------------------------------------- */
-/*	Write out the nineth block.					*/
+/*      Write out the ninth block.                                      */
 /* -------------------------------------------------------------------- */
-
         seg_data.Put(RadarSeg->Identifier.c_str(), nPos,16);
         seg_data.Put(RadarSeg->Facility.c_str(), nPos+16,16);
         seg_data.Put(RadarSeg->Ellipsoid.c_str(), nPos+32,16);
@@ -1290,7 +1285,7 @@ CPCIDSKEphemerisSegment::EphemerisToBinary( EphemerisSeg_t * psOrbit,
 /* -------------------------------------------------------------------- */
         seg_data.SetSize(seg_data.buffer_size + 
                                  512 * RadarSeg->NumberBlockData);
-            
+
         nPos = nStartBlock + 512*10;
         memset(seg_data.buffer+nPos,' ', 
                512 * RadarSeg->NumberBlockData);
diff --git a/frmts/pcidsk/sdk/segment/cpcidskephemerissegment.h b/frmts/pcidsk/sdk/segment/cpcidskephemerissegment.h
index bd9bacf..00e51bf 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskephemerissegment.h
+++ b/frmts/pcidsk/sdk/segment/cpcidskephemerissegment.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PCIDSK_SEGMENT_PCIDSKEPHEMERIS_SEG_H
-#define __INCLUDE_PCIDSK_SEGMENT_PCIDSKEPHEMERIS_SEG_H
+#ifndef INCLUDE_PCIDSK_SEGMENT_PCIDSKEPHEMERIS_SEG_H
+#define INCLUDE_PCIDSK_SEGMENT_PCIDSKEPHEMERIS_SEG_H
  
 #include "pcidsk_ephemeris.h"
 #include "segment/cpcidsksegment.h"
@@ -84,4 +84,4 @@ namespace PCIDSK {
     };
 }
 
-#endif // __INCLUDE_PCIDSK_SEGMENT_PCIDSKEPHEMERIS_SEG_H
+#endif // INCLUDE_PCIDSK_SEGMENT_PCIDSKEPHEMERIS_SEG_H
diff --git a/frmts/pcidsk/sdk/segment/cpcidskgcp2segment.cpp b/frmts/pcidsk/sdk/segment/cpcidskgcp2segment.cpp
index 2b4720e..a68fde2 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskgcp2segment.cpp
+++ b/frmts/pcidsk/sdk/segment/cpcidskgcp2segment.cpp
@@ -28,6 +28,7 @@
 
 #include "pcidsk_gcp.h"
 #include "pcidsk_exception.h"
+#include "core/pcidsk_utils.h"
 
 #include <cstring>
 #include <iostream>
@@ -48,8 +49,8 @@ struct CPCIDSKGCP2Segment::PCIDSKGCP2SegInfo
     bool changed;
 };
 
-CPCIDSKGCP2Segment::CPCIDSKGCP2Segment(PCIDSKFile *file, int segment, const char *segment_pointer)
-    : CPCIDSKSegment(file, segment, segment_pointer), loaded_(false)
+CPCIDSKGCP2Segment::CPCIDSKGCP2Segment(PCIDSKFile *fileIn, int segmentIn, const char *segment_pointer)
+    : CPCIDSKSegment(fileIn, segmentIn, segment_pointer), loaded_(false)
 {
     pimpl_ = new PCIDSKGCP2SegInfo;
     pimpl_->gcps.clear();
@@ -68,14 +69,14 @@ void CPCIDSKGCP2Segment::Load()
     if (loaded_) {
         return;
     }
-    
-    // Read the the segment in. The first block has information about
+
+    // Read the segment in. The first block has information about
     // the structure of the GCP segment (how many, the projection, etc.)
-    pimpl_->seg_data.SetSize(data_size - 1024);
+    pimpl_->seg_data.SetSize(static_cast<int>(data_size) - 1024);
     ReadFromFile(pimpl_->seg_data.buffer, 0, data_size - 1024);
-    
+
     // check for 'GCP2    ' in the first 8 bytes
-    if (std::strncmp(pimpl_->seg_data.buffer, "GCP2    ", 8) != 0) {
+    if (!STARTS_WITH(pimpl_->seg_data.buffer, "GCP2    ")) {
         // Assume it's an empty segment, so we can mark loaded_ = true,
         // write it out and return
         pimpl_->changed = true;
@@ -107,7 +108,7 @@ void CPCIDSKGCP2Segment::Load()
     // Get the number of alternative projections (should be 0!)
     pimpl_->num_proj = pimpl_->seg_data.GetInt(40, 8);
     if (pimpl_->num_proj != 0) {
-        ThrowPCIDSKException("There are alternative projections contained in this "
+        return ThrowPCIDSKException("There are alternative projections contained in this "
             "GCP2 segment. This functionality is not supported in libpcidsk.");
     }
     
@@ -165,7 +166,7 @@ std::vector<PCIDSK::GCP> const& CPCIDSKGCP2Segment::GetGCPs(void) const
 // exists, it will be replaced with this one.
 void CPCIDSKGCP2Segment::SetGCPs(std::vector<PCIDSK::GCP> const& gcps)
 {
-    pimpl_->num_gcps = gcps.size();
+    pimpl_->num_gcps = static_cast<unsigned int>(gcps.size());
     pimpl_->gcps = gcps; // copy them in
     pimpl_->changed = true;
     
@@ -209,9 +210,9 @@ void CPCIDSKGCP2Segment::RebuildSegmentData(void)
     std::vector<PCIDSK::GCP>::const_iterator iter =
         pimpl_->gcps.begin();
     
-    unsigned int id = 0;
+    int id = 0;
     while (iter != pimpl_->gcps.end()) {
-        std::size_t offset = 512 + id * 256;
+        int offset = 512 + id * 256;
         
         if ((*iter).IsCheckPoint()) {
             pimpl_->seg_data.Put("C", offset, 1);
@@ -292,4 +293,3 @@ void  CPCIDSKGCP2Segment::ClearGCPs(void)
     
     RebuildSegmentData();
 }
-
diff --git a/frmts/pcidsk/sdk/segment/cpcidskgcp2segment.h b/frmts/pcidsk/sdk/segment/cpcidskgcp2segment.h
index 24fed85..b7cc2bf 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskgcp2segment.h
+++ b/frmts/pcidsk/sdk/segment/cpcidskgcp2segment.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_SEGMENT_CPCIDSKGCP2SEGMENT_H
-#define __INCLUDE_SEGMENT_CPCIDSKGCP2SEGMENT_H
+#ifndef INCLUDE_SEGMENT_CPCIDSKGCP2SEGMENT_H
+#define INCLUDE_SEGMENT_CPCIDSKGCP2SEGMENT_H
 
 #include "pcidsk_gcp.h"
 #include "pcidsk_gcpsegment.h"
@@ -60,5 +60,5 @@ namespace PCIDSK {
     };
 }
 
-#endif // __INCLUDE_SEGMENT_CPCIDSKGCP2SEGMENT_H
+#endif // INCLUDE_SEGMENT_CPCIDSKGCP2SEGMENT_H
 
diff --git a/frmts/pcidsk/sdk/segment/cpcidskgeoref.cpp b/frmts/pcidsk/sdk/segment/cpcidskgeoref.cpp
index bab64ad..05bb731 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskgeoref.cpp
+++ b/frmts/pcidsk/sdk/segment/cpcidskgeoref.cpp
@@ -46,12 +46,18 @@ static double PAK2PCI( double deg, int function );
 /*                           CPCIDSKGeoref()                            */
 /************************************************************************/
 
-CPCIDSKGeoref::CPCIDSKGeoref( PCIDSKFile *file, int segment,
+CPCIDSKGeoref::CPCIDSKGeoref( PCIDSKFile *fileIn, int segmentIn,
                               const char *segment_pointer )
-        : CPCIDSKSegment( file, segment, segment_pointer )
+        : CPCIDSKSegment( fileIn, segmentIn, segment_pointer )
 
 {
     loaded = false;
+    a1 = 0;
+    a2 = 0;
+    xrot = 0;
+    b1 = 0;
+    yrot = 0;
+    b3 = 0;
 }
 
 /************************************************************************/
@@ -98,12 +104,12 @@ void CPCIDSKGeoref::Load()
 /* -------------------------------------------------------------------- */
 /*      Handle simple case of a POLYNOMIAL.                             */
 /* -------------------------------------------------------------------- */
-    if( strncmp(seg_data.buffer,"POLYNOMIAL",10) == 0 )
+    if( STARTS_WITH(seg_data.buffer, "POLYNOMIAL") )
     {
         seg_data.Get(32,16,geosys);
         
         if( seg_data.GetInt(48,8) != 3 || seg_data.GetInt(56,8) != 3 )
-            ThrowPCIDSKException( "Unexpected number of coefficients in POLYNOMIAL GEO segment." );
+            return ThrowPCIDSKException( "Unexpected number of coefficients in POLYNOMIAL GEO segment." );
 
         a1   = seg_data.GetDouble(212+26*0,26);
         a2   = seg_data.GetDouble(212+26*1,26);
@@ -118,12 +124,12 @@ void CPCIDSKGeoref::Load()
 /*      Handle the case of a PROJECTION segment - for now we ignore     */
 /*      the actual projection parameters.                               */
 /* -------------------------------------------------------------------- */
-    else if( strncmp(seg_data.buffer,"PROJECTION",10) == 0 )
+    else if( STARTS_WITH(seg_data.buffer, "PROJECTION") )
     {
         seg_data.Get(32,16,geosys);
         
         if( seg_data.GetInt(48,8) != 3 || seg_data.GetInt(56,8) != 3 )
-            ThrowPCIDSKException( "Unexpected number of coefficients in POLYNOMIAL GEO segment." );
+            return ThrowPCIDSKException( "Unexpected number of coefficients in POLYNOMIAL GEO segment." );
 
         a1   = seg_data.GetDouble(1980+26*0,26);
         a2   = seg_data.GetDouble(1980+26*1,26);
@@ -152,7 +158,7 @@ void CPCIDSKGeoref::Load()
 
     else
     {
-        ThrowPCIDSKException( "Unexpected GEO segment type: %s", 
+        return ThrowPCIDSKException( "Unexpected GEO segment type: %s", 
                               seg_data.Get(0,16) );
     }
 
@@ -174,18 +180,18 @@ std::string CPCIDSKGeoref::GetGeosys()
 /*                            GetTransform()                            */
 /************************************************************************/
 
-void CPCIDSKGeoref::GetTransform( double &a1, double &a2, double &xrot, 
-                                  double &b1, double &yrot, double &b3 )
+void CPCIDSKGeoref::GetTransform( double &a1Out, double &a2Out, double &xrotOut, 
+                                  double &b1Out, double &yrotOut, double &b3Out )
 
 {
     Load();
 
-    a1   = this->a1;
-    a2   = this->a2;
-    xrot = this->xrot;
-    b1   = this->b1;
-    yrot = this->yrot;
-    b3   = this->b3;
+    a1Out   = this->a1;
+    a2Out   = this->a2;
+    xrotOut = this->xrot;
+    b1Out   = this->b1;
+    yrotOut = this->yrot;
+    b3Out   = this->b3;
 }
 
 /************************************************************************/
@@ -202,7 +208,7 @@ std::vector<double> CPCIDSKGeoref::GetParameters()
 
     parms.resize(18);
 
-    if( strncmp(seg_data.buffer,"PROJECTION",10) != 0 )
+    if( !STARTS_WITH(seg_data.buffer, "PROJECTION") )
     {
         for( i = 0; i < 17; i++ )
             parms[i] = 0.0;
@@ -216,15 +222,15 @@ std::vector<double> CPCIDSKGeoref::GetParameters()
         std::string grid_units;
         seg_data.Get(64,16,grid_units);
 
-        if( EQUALN(grid_units.c_str(),"DEGREE",3) )
+        if( STARTS_WITH_CI(grid_units.c_str(),"DEG" /* "DEGREE" */) )
             parms[17] = (double) (int) UNIT_DEGREE;
-        else if( EQUALN(grid_units.c_str(),"MET",3) )
+        else if( STARTS_WITH_CI(grid_units.c_str(), "MET") )
             parms[17] = (double) (int) UNIT_METER;
-        else if( EQUALN(grid_units.c_str(),"FOOT",4) )
+        else if( STARTS_WITH_CI(grid_units.c_str(), "FOOT") )
             parms[17] = (double) (int) UNIT_US_FOOT;
-        else if( EQUALN(grid_units.c_str(),"FEET",4) )
+        else if( STARTS_WITH_CI(grid_units.c_str(), "FEET") )
             parms[17] = (double) (int) UNIT_US_FOOT;
-        else if( EQUALN(grid_units.c_str(),"INTL FOOT",5) )
+        else if( STARTS_WITH_CI(grid_units.c_str(), "INTL " /* "INTL FOOT" */) )
             parms[17] = (double) (int) UNIT_INTL_FOOT;
         else
             parms[17] = -1.0; /* unknown */
@@ -237,29 +243,29 @@ std::vector<double> CPCIDSKGeoref::GetParameters()
 /*                            WriteSimple()                             */
 /************************************************************************/
 
-void CPCIDSKGeoref::WriteSimple( std::string const& geosys, 
-                                 double a1, double a2, double xrot, 
-                                 double b1, double yrot, double b3 )
+void CPCIDSKGeoref::WriteSimple( std::string const& geosysIn, 
+                                 double a1In, double a2In, double xrotIn, 
+                                 double b1In, double yrotIn, double b3In )
 
 {
     Load();
 
-    std::string geosys_clean(ReformatGeosys( geosys ));
+    std::string geosys_clean(ReformatGeosys( geosysIn ));
 
 /* -------------------------------------------------------------------- */
 /*      Establish the appropriate units code when possible.             */
 /* -------------------------------------------------------------------- */
     std::string units_code = "METER";
 
-    if( EQUALN(geosys_clean.c_str(),"FOOT",4) )
+    if( STARTS_WITH_CI(geosys_clean.c_str(), "FOOT") )
         units_code = "FOOT";
-    else if( EQUALN(geosys_clean.c_str(),"SPAF",4) )
+    else if( STARTS_WITH_CI(geosys_clean.c_str(), "SPAF") )
         units_code = "FOOT";
-    else if( EQUALN(geosys_clean.c_str(),"SPIF",4) )
+    else if( STARTS_WITH_CI(geosys_clean.c_str(), "SPIF") )
         units_code = "INTL FOOT";
-    else if( EQUALN(geosys_clean.c_str(),"LONG",4) )
-        units_code = "DEEGREE";
-        
+    else if( STARTS_WITH_CI(geosys_clean.c_str(), "LONG") )
+        units_code = "DEGREE";
+
 /* -------------------------------------------------------------------- */
 /*      Write a fairly simple PROJECTION segment.                       */
 /* -------------------------------------------------------------------- */
@@ -293,14 +299,14 @@ void CPCIDSKGeoref::WriteSimple( std::string const& geosys,
     PrepareGCTPFields();
 
     // SD.PRO.P26
-    seg_data.Put( a1,  1980 + 0*26, 26, "%26.18E" );
-    seg_data.Put( a2,  1980 + 1*26, 26, "%26.18E" );
-    seg_data.Put( xrot,1980 + 2*26, 26, "%26.18E" );
+    seg_data.Put( a1In,  1980 + 0*26, 26, "%26.18E" );
+    seg_data.Put( a2In,  1980 + 1*26, 26, "%26.18E" );
+    seg_data.Put( xrotIn,1980 + 2*26, 26, "%26.18E" );
 
     // SD.PRO.P27
-    seg_data.Put( b1,   2526 + 0*26, 26, "%26.18E" );
-    seg_data.Put( yrot, 2526 + 1*26, 26, "%26.18E" );
-    seg_data.Put( b3,   2526 + 2*26, 26, "%26.18E" );
+    seg_data.Put( b1In,   2526 + 0*26, 26, "%26.18E" );
+    seg_data.Put( yrotIn, 2526 + 1*26, 26, "%26.18E" );
+    seg_data.Put( b3In,   2526 + 2*26, 26, "%26.18E" );
 
     WriteToFile( seg_data.buffer, 0, seg_data.buffer_size );
 
@@ -317,7 +323,7 @@ void CPCIDSKGeoref::WriteParameters( std::vector<double> const& parms )
     Load();
 
     if( parms.size() < 17 )
-        ThrowPCIDSKException( "Did not get expected number of parameters in WriteParameters()" );
+        return ThrowPCIDSKException( "Did not get expected number of parameters in WriteParameters()" );
 
     unsigned int i;
 
@@ -366,7 +372,7 @@ std::vector<double> CPCIDSKGeoref::GetUSGSParameters()
     Load();
 
     parms.resize(19);
-    if( strncmp(seg_data.buffer,"PROJECTION",10) != 0 )
+    if( !STARTS_WITH(seg_data.buffer, "PROJECTION") )
     {
         for( i = 0; i < 19; i++ )
             parms[i] = 0.0;
@@ -387,7 +393,7 @@ std::vector<double> CPCIDSKGeoref::GetUSGSParameters()
 /*      DecodeGeosys() function in the PCI SDK does.                    */
 /************************************************************************/
 
-std::string CPCIDSKGeoref::ReformatGeosys( std::string const& geosys )
+std::string CPCIDSKGeoref::ReformatGeosys( std::string const& geosysIn )
 
 {
 /* -------------------------------------------------------------------- */
@@ -396,7 +402,7 @@ std::string CPCIDSKGeoref::ReformatGeosys( std::string const& geosys )
 /* -------------------------------------------------------------------- */
     char local_buf[33];
 
-    strncpy( local_buf, geosys.c_str(), 16 );
+    strncpy( local_buf, geosysIn.c_str(), 16 );
     local_buf[16] = '\0';
     strcat( local_buf, "                " );
     local_buf[16] = '\0';
@@ -437,18 +443,18 @@ std::string CPCIDSKGeoref::ReformatGeosys( std::string const& geosys )
                )
         {
             if( *cp == 'D' || *cp == 'd' )
-                sprintf( earthmodel, "D%03d", i );
+                snprintf( earthmodel, sizeof(earthmodel), "D%03d", i );
             else
-                sprintf( earthmodel, "E%03d", i );
+                snprintf( earthmodel, sizeof(earthmodel), "E%03d", i );
         }
         else
         {
-            sprintf( earthmodel, "    " );
+            snprintf( earthmodel, sizeof(earthmodel), "    " );
         }
     }
     else
     {
-        sprintf( earthmodel, "    " );
+        snprintf( earthmodel, sizeof(earthmodel), "    " );
     }
 
 /* -------------------------------------------------------------------- */
@@ -458,11 +464,11 @@ std::string CPCIDSKGeoref::ReformatGeosys( std::string const& geosys )
     int zone, ups_zone;
     char zone_code = ' ';
 
-    if( EQUALN(local_buf,"PIX",3) )
+    if( STARTS_WITH_CI(local_buf, "PIX") )
     {
         strcpy( local_buf, "PIXEL           " );
     }
-    else if( EQUALN(local_buf,"UTM",3) )
+    else if( STARTS_WITH_CI(local_buf, "UTM") )
     {
         /* Attempt to find a zone and ellipsoid */
         for( ptr=local_buf+3; isspace(*ptr); ptr++ ) {}
@@ -489,13 +495,13 @@ std::string CPCIDSKGeoref::ReformatGeosys( std::string const& geosys )
 
             zone = ABS(zone);
 
-            sprintf( local_buf,
+            snprintf( local_buf, sizeof(local_buf),
                      "UTM   %3d %c %4s", 
                      zone, zone_code, earthmodel );
         }
         else
         {	
-            sprintf( local_buf, 
+            snprintf( local_buf, sizeof(local_buf), 
                      "UTM         %4s", 
                      earthmodel );
         }
@@ -504,188 +510,188 @@ std::string CPCIDSKGeoref::ReformatGeosys( std::string const& geosys )
         if( local_buf[13] == ' ' )
             local_buf[13] = '0';
     }
-    else if( EQUALN(local_buf,"MET",3) )
+    else if( STARTS_WITH_CI(local_buf, "MET") )
     {
-        sprintf( local_buf, "METRE       %4s", earthmodel );
+        snprintf( local_buf, sizeof(local_buf), "METRE       %4s", earthmodel );
     }
-    else if( EQUALN(local_buf,"FEET",4) || EQUALN(local_buf,"FOOT",4))
+    else if( STARTS_WITH_CI(local_buf, "FEET") || STARTS_WITH_CI(local_buf, "FOOT"))
     {
-        sprintf( local_buf, "FOOT        %4s", earthmodel );
+        snprintf( local_buf, sizeof(local_buf), "FOOT        %4s", earthmodel );
     }
-    else if( EQUALN(local_buf,"LAT",3) ||
-             EQUALN(local_buf,"LON",3) )
+    else if( STARTS_WITH_CI(local_buf, "LAT") ||
+             STARTS_WITH_CI(local_buf, "LON") )
     {
-        sprintf( local_buf, 
+        snprintf( local_buf, sizeof(local_buf), 
                  "LONG/LAT    %4s",
                  earthmodel );
     }
-    else if( EQUALN(local_buf,"SPCS ",5) ||
-             EQUALN(local_buf,"SPAF ",5) ||
-             EQUALN(local_buf,"SPIF ",5) )
+    else if( STARTS_WITH_CI(local_buf, "SPCS ") ||
+             STARTS_WITH_CI(local_buf, "SPAF ") ||
+             STARTS_WITH_CI(local_buf, "SPIF ") )
     {
         int nSPZone = 0;
 
         for( ptr=local_buf+4; isspace(*ptr); ptr++ ) {}
         nSPZone = atoi(ptr);
 
-        if      ( EQUALN(local_buf,"SPCS ",5) ) 
+        if      ( STARTS_WITH_CI(local_buf, "SPCS ") ) 
             strcpy( local_buf, "SPCS " );
-        else if ( EQUALN(local_buf,"SPAF ",5) ) 
+        else if ( STARTS_WITH_CI(local_buf, "SPAF ") ) 
             strcpy( local_buf, "SPAF " );
         else
             strcpy( local_buf, "SPIF " );
 
         if( nSPZone != 0 )
-            sprintf( local_buf + 5, "%4d   %4s",nSPZone,earthmodel);
+            snprintf( local_buf + 5, sizeof(local_buf)-5, "%4d   %4s",nSPZone,earthmodel);
         else
-            sprintf( local_buf + 5, "       %4s",earthmodel);
+            snprintf( local_buf + 5, sizeof(local_buf)-5, "       %4s",earthmodel);
 
     }
-    else if( EQUALN(local_buf,"ACEA ",5) )
+    else if( STARTS_WITH_CI(local_buf, "ACEA ") )
     {
-        sprintf( local_buf, 
+        snprintf( local_buf, sizeof(local_buf), 
                  "ACEA        %4s",
                  earthmodel );
     }
-    else if( EQUALN(local_buf,"AE ",3) )
+    else if( STARTS_WITH_CI(local_buf, "AE ") )
     {
-        sprintf( local_buf, 
+        snprintf( local_buf, sizeof(local_buf), 
                  "AE          %4s",
                  earthmodel );
     }
-    else if( EQUALN(local_buf,"EC ",3) )
+    else if( STARTS_WITH_CI(local_buf, "EC ") )
     {
-        sprintf( local_buf, 
+        snprintf( local_buf, sizeof(local_buf), 
                  "EC          %4s",
                  earthmodel );
     }
-    else if( EQUALN(local_buf,"ER ",3) )
+    else if( STARTS_WITH_CI(local_buf, "ER ") )
     {
-        sprintf( local_buf, 
+        snprintf( local_buf, sizeof(local_buf), 
                  "ER          %4s",
                  earthmodel );
     }
-    else if( EQUALN(local_buf,"GNO ",4) )
+    else if( STARTS_WITH_CI(local_buf, "GNO ") )
     {
-        sprintf( local_buf, 
+        snprintf( local_buf, sizeof(local_buf), 
                  "GNO         %4s",
                  earthmodel );
     }
-    else if( EQUALN(local_buf,"GVNP",4) )
+    else if( STARTS_WITH_CI(local_buf, "GVNP") )
     {
-        sprintf( local_buf, 
+        snprintf( local_buf, sizeof(local_buf), 
                  "GVNP        %4s",
                  earthmodel );
     }
-    else if( EQUALN(local_buf,"LAEA_ELL",8) )
+    else if( STARTS_WITH_CI(local_buf, "LAEA_ELL") )
     {
-        sprintf( local_buf, 
+        snprintf( local_buf, sizeof(local_buf), 
                  "LAEA_ELL    %4s",
                  earthmodel );
     }
-    else if( EQUALN(local_buf,"LAEA",4) )
+    else if( STARTS_WITH_CI(local_buf, "LAEA") )
     {
-        sprintf( local_buf, 
+        snprintf( local_buf, sizeof(local_buf), 
                  "LAEA        %4s",
                  earthmodel );
     }
-    else if( EQUALN(local_buf,"LCC_1SP",7) )
+    else if( STARTS_WITH_CI(local_buf, "LCC_1SP") )
     {
-        sprintf( local_buf, 
+        snprintf( local_buf, sizeof(local_buf), 
                  "LCC_1SP     %4s",
                  earthmodel );
     }
-    else if( EQUALN(local_buf,"LCC ",4) )
+    else if( STARTS_WITH_CI(local_buf, "LCC ") )
     {
-        sprintf( local_buf, 
+        snprintf( local_buf, sizeof(local_buf), 
                  "LCC         %4s",
                  earthmodel );
     }
-    else if( EQUALN(local_buf,"MC ",3) )
+    else if( STARTS_WITH_CI(local_buf, "MC ") )
     {
-        sprintf( local_buf, 
+        snprintf( local_buf, sizeof(local_buf), 
                  "MC          %4s",
                  earthmodel );
     }
-    else if( EQUALN(local_buf,"MER ",4) )
+    else if( STARTS_WITH_CI(local_buf, "MER ") )
     {
-        sprintf( local_buf, 
+        snprintf( local_buf, sizeof(local_buf), 
                  "MER         %4s",
                  earthmodel );
     }
-    else if( EQUALN(local_buf,"MSC ",4) )
+    else if( STARTS_WITH_CI(local_buf, "MSC ") )
     {
-        sprintf( local_buf, 
+        snprintf( local_buf, sizeof(local_buf), 
                  "MSC         %4s",
                  earthmodel );
     }
-    else if( EQUALN(local_buf,"OG ",3) )
+    else if( STARTS_WITH_CI(local_buf, "OG ") )
     {
-        sprintf( local_buf, 
+        snprintf( local_buf, sizeof(local_buf), 
                  "OG          %4s",
                  earthmodel );
     }
-    else if( EQUALN(local_buf,"OM ",3) )
+    else if( STARTS_WITH_CI(local_buf, "OM ") )
     {
-        sprintf( local_buf, 
+        snprintf( local_buf, sizeof(local_buf), 
                  "OM          %4s",
                  earthmodel );
     }
-    else if( EQUALN(local_buf,"PC ",3) )
+    else if( STARTS_WITH_CI(local_buf, "PC ") )
     {
-        sprintf( local_buf, 
+        snprintf( local_buf, sizeof(local_buf), 
                  "PC          %4s",
                  earthmodel );
     }
-    else if( EQUALN(local_buf,"PS ",3) )
+    else if( STARTS_WITH_CI(local_buf, "PS ") )
     {
-        sprintf( local_buf, 
+        snprintf( local_buf, sizeof(local_buf), 
                  "PS          %4s",
                  earthmodel );
     }
-    else if( EQUALN(local_buf,"ROB ",4) )
+    else if( STARTS_WITH_CI(local_buf, "ROB ") )
     {
-        sprintf( local_buf, 
+        snprintf( local_buf, sizeof(local_buf), 
                  "ROB         %4s",
                  earthmodel );
     }
-    else if( EQUALN(local_buf,"SG ",3) )
+    else if( STARTS_WITH_CI(local_buf, "SG ") )
     {
-        sprintf( local_buf, 
+        snprintf( local_buf, sizeof(local_buf), 
                  "SG          %4s",
                  earthmodel );
     }
-    else if( EQUALN(local_buf,"SIN ",4) )
+    else if( STARTS_WITH_CI(local_buf, "SIN ") )
     {
-        sprintf( local_buf, 
+        snprintf( local_buf, sizeof(local_buf), 
                  "SIN         %4s",
                  earthmodel );
     }
-    else if( EQUALN(local_buf,"SOM ",4) )
+    else if( STARTS_WITH_CI(local_buf, "SOM ") )
     {
-        sprintf( local_buf, 
+        snprintf( local_buf, sizeof(local_buf), 
                  "SOM         %4s",
                  earthmodel );
     }
-    else if( EQUALN(local_buf,"TM ",3) )
+    else if( STARTS_WITH_CI(local_buf, "TM ") )
     {
-        sprintf( local_buf, 
+        snprintf( local_buf, sizeof(local_buf), 
                  "TM          %4s",
                  earthmodel );
     }
-    else if( EQUALN(local_buf,"VDG ",4) )
+    else if( STARTS_WITH_CI(local_buf, "VDG ") )
     {
-        sprintf( local_buf, 
+        snprintf( local_buf, sizeof(local_buf), 
                  "VDG         %4s",
                  earthmodel );
     }
-    else if( EQUALN(local_buf,"UPSA",4) )
+    else if( STARTS_WITH_CI(local_buf, "UPSA") )
     {
-        sprintf( local_buf, 
+        snprintf( local_buf, sizeof(local_buf), 
                  "UPSA        %4s",
                  earthmodel );
     }
-    else if( EQUALN(local_buf,"UPS ",4) )
+    else if( STARTS_WITH_CI(local_buf, "UPS ") )
     {
         /* Attempt to find UPS zone */
         for( ptr=local_buf+3; isspace(*ptr); ptr++ ) {}
@@ -696,70 +702,70 @@ std::string CPCIDSKGeoref::ReformatGeosys( std::string const& geosys )
         else
             ups_zone = ' ';
 
-        sprintf( local_buf, 
+        snprintf( local_buf, sizeof(local_buf), 
                  "UPS       %c %4s",
                  ups_zone, earthmodel );
     }
-    else if( EQUALN(local_buf,"GOOD",4) )
+    else if( STARTS_WITH_CI(local_buf, "GOOD") )
     {
-        sprintf( local_buf, 
+        snprintf( local_buf, sizeof(local_buf), 
                  "GOOD        %4s",
                  earthmodel );
     }
-    else if( EQUALN(local_buf,"NZMG",4) )
+    else if( STARTS_WITH_CI(local_buf, "NZMG") )
     {
-        sprintf( local_buf, 
+        snprintf( local_buf, sizeof(local_buf), 
                  "NZMG        %4s",
                  earthmodel );
     }
-    else if( EQUALN(local_buf,"CASS",4) )
+    else if( STARTS_WITH_CI(local_buf, "CASS") )
     {
-        if( EQUALN( earthmodel, "D000", 4 ) )
-            sprintf( local_buf,  "CASS        %4s", "E010" );
+        if( STARTS_WITH_CI(earthmodel, "D000") )
+            snprintf( local_buf, sizeof(local_buf),  "CASS        %4s", "E010" );
         else
-            sprintf( local_buf,  "CASS        %4s", earthmodel );
+            snprintf( local_buf, sizeof(local_buf),  "CASS        %4s", earthmodel );
     }
-    else if( EQUALN(local_buf,"RSO ",4) )
+    else if( STARTS_WITH_CI(local_buf, "RSO ") )
     {
-        if( EQUALN( earthmodel, "D000", 4 ) )
-            sprintf( local_buf,  "RSO         %4s", "E010" );
+        if( STARTS_WITH_CI(earthmodel, "D000") )
+            snprintf( local_buf, sizeof(local_buf),  "RSO         %4s", "E010" );
         else
-            sprintf( local_buf,  "RSO         %4s", earthmodel );
+            snprintf( local_buf, sizeof(local_buf),  "RSO         %4s", earthmodel );
     }
-    else if( EQUALN(local_buf,"KROV",4) )
+    else if( STARTS_WITH_CI(local_buf, "KROV") )
     {
-        if( EQUALN( earthmodel, "D000", 4 ) )
-            sprintf( local_buf,  "KROV        %4s", "E002" );
+        if( STARTS_WITH_CI(earthmodel, "D000") )
+            snprintf( local_buf, sizeof(local_buf),  "KROV        %4s", "E002" );
         else
-            sprintf( local_buf,  "KROV        %4s", earthmodel );
+            snprintf( local_buf, sizeof(local_buf),  "KROV        %4s", earthmodel );
     }
-    else if( EQUALN(local_buf,"KRON",4) )
+    else if( STARTS_WITH_CI(local_buf, "KRON") )
     {
-        if( EQUALN( earthmodel, "D000", 4 ) )
-            sprintf( local_buf,  "KRON        %4s", "E002" );
+        if( STARTS_WITH_CI(earthmodel, "D000") )
+            snprintf( local_buf, sizeof(local_buf),  "KRON        %4s", "E002" );
         else
-            sprintf( local_buf,  "KRON        %4s", earthmodel );
+            snprintf( local_buf, sizeof(local_buf),  "KRON        %4s", earthmodel );
     }
-    else if( EQUALN(local_buf,"SGDO",4) )
+    else if( STARTS_WITH_CI(local_buf, "SGDO") )
     {
-        if( EQUALN( earthmodel, "D000", 4 ) )
-            sprintf( local_buf,  "SGDO        %4s", "E910" );
+        if( STARTS_WITH_CI(earthmodel, "D000") )
+            snprintf( local_buf, sizeof(local_buf),  "SGDO        %4s", "E910" );
         else
-            sprintf( local_buf,  "SGDO        %4s", earthmodel );
+            snprintf( local_buf, sizeof(local_buf),  "SGDO        %4s", earthmodel );
     }
-    else if( EQUALN(local_buf,"LBSG",4) )
+    else if( STARTS_WITH_CI(local_buf, "LBSG") )
     {
-        if( EQUALN( earthmodel, "D000", 4 ) )
-            sprintf( local_buf,  "LBSG        %4s", "E202" );
+        if( STARTS_WITH_CI(earthmodel, "D000") )
+            snprintf( local_buf, sizeof(local_buf),  "LBSG        %4s", "E202" );
         else
-            sprintf( local_buf,  "LBSG        %4s", earthmodel );
+            snprintf( local_buf, sizeof(local_buf),  "LBSG        %4s", earthmodel );
     }
-    else if( EQUALN(local_buf,"ISIN",4) )
+    else if( STARTS_WITH_CI(local_buf, "ISIN") )
     {
-        if( EQUALN( earthmodel, "D000", 4 ) )
-            sprintf( local_buf,  "ISIN        %4s", "E700" );
+        if( STARTS_WITH_CI(earthmodel, "D000") )
+            snprintf( local_buf, sizeof(local_buf),  "ISIN        %4s", "E700" );
         else
-            sprintf( local_buf,  "ISIN        %4s", earthmodel );
+            snprintf( local_buf, sizeof(local_buf),  "ISIN        %4s", earthmodel );
     }
 /* -------------------------------------------------------------------- */
 /*      This may be a user projection. Just reformat the earth model    */
@@ -767,7 +773,7 @@ std::string CPCIDSKGeoref::ReformatGeosys( std::string const& geosys )
 /* -------------------------------------------------------------------- */
     else
     {
-        sprintf( local_buf, "%-11.11s %4s", geosys.c_str(), earthmodel );
+        snprintf( local_buf, sizeof(local_buf), "%-11.11s %4s", geosysIn.c_str(), earthmodel );
     }
 
     return local_buf;
@@ -780,7 +786,7 @@ C       The standard packed DMS format is the required format for any
 C       Latitude or Longitude value in the projection parameter array
 C       (TPARIN and/or TPARIO) in calling the U.S.G.S. GCTP package,
 C       but is not required for the actual coordinates to be converted.
-C	This routine has been coverted from the PAKPCI fortran routine.
+C       This routine has been converted from the PAKPCI FORTRAN routine.
 C
 C       When function is 1, the value returned is made up as follows:
 C
@@ -805,7 +811,7 @@ C
 C       double = PACK2PCI (degrees, function)
 C
 C       degrees  - (double) Latitude or Longitude value in decimal 
-C	                    degrees.
+C                           degrees.
 C
 C       function - (Int)    Function to perform                            
 C                           1, convert decimal degrees to DDDMMMSSS.SSS
@@ -917,19 +923,19 @@ void CPCIDSKGeoref::PrepareGCTPFields()
     std::string grid_units;
     seg_data.Get(64,16,grid_units);
 
-    if( EQUALN(grid_units.c_str(),"MET",3) )
+    if( STARTS_WITH_CI(grid_units.c_str(), "MET") )
         UnitsCode = GCTP_UNIT_METRE;
-    else if( EQUALN( grid_units.c_str(), "FOOT", 4 ) )
+    else if( STARTS_WITH_CI(grid_units.c_str(), "FOOT") )
     {
         UnitsCode = GCTP_UNIT_US_FOOT;
         IOmultiply = 1.0 / 0.3048006096012192;
     }
-    else if( EQUALN( grid_units.c_str(), "INTL FOOT", 9 ) )
+    else if( STARTS_WITH_CI(grid_units.c_str(), "INTL FOOT") )
     {
         UnitsCode = GCTP_UNIT_INTL_FOOT;
         IOmultiply = 1.0 / 0.3048;
     }
-    else if( EQUALN( grid_units.c_str(), "DEGREE", 6 ) )
+    else if( STARTS_WITH_CI(grid_units.c_str(), "DEGREE") )
         UnitsCode = GCTP_UNIT_DEGREE;
     
 /* -------------------------------------------------------------------- */
@@ -964,10 +970,10 @@ void CPCIDSKGeoref::PrepareGCTPFields()
 /* -------------------------------------------------------------------- */
     int ProjectionZone = 0;
 
-    if( strncmp(geosys_clean.c_str(),"UTM ",4) == 0 
-        || strncmp(geosys_clean.c_str(),"SPCS ",5) == 0 
-        || strncmp(geosys_clean.c_str(),"SPAF ",5) == 0 
-        || strncmp(geosys_clean.c_str(),"SPIF ",5) == 0 )
+    if( STARTS_WITH(geosys_clean.c_str(), "UTM ") 
+        || STARTS_WITH(geosys_clean.c_str(), "SPCS ") 
+        || STARTS_WITH(geosys_clean.c_str(), "SPAF ") 
+        || STARTS_WITH(geosys_clean.c_str(), "SPIF ") )
     {
         ProjectionZone = atoi(geosys_clean.c_str() + 5);
     }
@@ -999,8 +1005,8 @@ void CPCIDSKGeoref::PrepareGCTPFields()
 /* -------------------------------------------------------------------- */
 /*	Projection 0: Geographic (no projection)			*/
 /* -------------------------------------------------------------------- */
-    if( strncmp(geosys_clean.c_str(),"LON",3) == 0 
-        || strncmp(geosys_clean.c_str(),"LAT",3) == 0 )
+    if( STARTS_WITH(geosys_clean.c_str(), "LON") 
+        || STARTS_WITH(geosys_clean.c_str(), "LAT") )
     {
         gsys = 0;
         UnitsCode = GCTP_UNIT_DEGREE;
@@ -1009,10 +1015,10 @@ void CPCIDSKGeoref::PrepareGCTPFields()
 /* -------------------------------------------------------------------- */
 /*	Projection 1: Universal Transverse Mercator			*/
 /* -------------------------------------------------------------------- */
-    else if( strncmp(geosys_clean.c_str(),"UTM ",4) == 0 )
+    else if( STARTS_WITH(geosys_clean.c_str(), "UTM ") )
     {
         char row_char = geosys_clean[10];
-        gsys = 1;
+        /*gsys = 1;*/
 
         // Southern hemisphere?
         if( (row_char >= 'C') && (row_char <= 'M') && ProjectionZone > 0 )
@@ -1040,7 +1046,7 @@ void CPCIDSKGeoref::PrepareGCTPFields()
 /* -------------------------------------------------------------------- */
 /*	Projection 2: State Plane Coordinate System			*/
 /* -------------------------------------------------------------------- */
-    else if( strncmp(geosys_clean.c_str(),"SPCS ",5) == 0 )
+    else if( STARTS_WITH(geosys_clean.c_str(), "SPCS ") )
     {
         gsys = 2;
         if(    UnitsCode != GCTP_UNIT_METRE
@@ -1049,7 +1055,7 @@ void CPCIDSKGeoref::PrepareGCTPFields()
             UnitsCode = GCTP_UNIT_METRE;
     }
 
-    else if( strncmp(geosys_clean.c_str(),"SPAF ",5) == 0 )
+    else if( STARTS_WITH(geosys_clean.c_str(), "SPAF ") )
     {
         gsys = 2;
         if(    UnitsCode != GCTP_UNIT_METRE
@@ -1058,7 +1064,7 @@ void CPCIDSKGeoref::PrepareGCTPFields()
             UnitsCode = GCTP_UNIT_US_FOOT;
     }
 
-    else if( strncmp(geosys_clean.c_str(),"SPIF ",5) == 0 )
+    else if( STARTS_WITH(geosys_clean.c_str(), "SPIF ") )
     {
         gsys = 2;
         if(    UnitsCode != GCTP_UNIT_METRE
@@ -1070,7 +1076,7 @@ void CPCIDSKGeoref::PrepareGCTPFields()
 /* -------------------------------------------------------------------- */
 /*	Projection 3: Albers Conical Equal-Area 			*/
 /* -------------------------------------------------------------------- */
-    else if( strncmp(geosys_clean.c_str(),"ACEA ",5) == 0 )
+    else if( STARTS_WITH(geosys_clean.c_str(), "ACEA ") )
     {
         gsys = 3;
         USGSParms[0] = Dearth0;
@@ -1086,7 +1092,7 @@ void CPCIDSKGeoref::PrepareGCTPFields()
 /* -------------------------------------------------------------------- */
 /*	Projection 4: Lambert Conformal Conic				*/ 
 /* -------------------------------------------------------------------- */
-    else if( strncmp(geosys_clean.c_str(),"LCC  ",5) == 0 )
+    else if( STARTS_WITH(geosys_clean.c_str(), "LCC  ") )
     {
         gsys = 4;
         USGSParms[0] = Dearth0;
@@ -1102,7 +1108,7 @@ void CPCIDSKGeoref::PrepareGCTPFields()
 /* -------------------------------------------------------------------- */
 /*	Projection 5: Mercator						*/ 
 /* -------------------------------------------------------------------- */
-    else if( strncmp(geosys_clean.c_str(),"MER  ",5) == 0 )
+    else if( STARTS_WITH(geosys_clean.c_str(), "MER  ") )
     {
         gsys = 5;
         USGSParms[0] = Dearth0;
@@ -1117,7 +1123,7 @@ void CPCIDSKGeoref::PrepareGCTPFields()
 /* -------------------------------------------------------------------- */
 /*	Projection 6: Polar Stereographic		 		*/
 /* -------------------------------------------------------------------- */
-    else if( strncmp(geosys_clean.c_str(),"PS   ",5) == 0 )
+    else if( STARTS_WITH(geosys_clean.c_str(), "PS   ") )
     {
         gsys = 6;
         USGSParms[0] = Dearth0;
@@ -1132,7 +1138,7 @@ void CPCIDSKGeoref::PrepareGCTPFields()
 /* -------------------------------------------------------------------- */
 /*	Projection 7: Polyconic			 			*/
 /* -------------------------------------------------------------------- */
-    else if( strncmp(geosys_clean.c_str(),"PC   ",5) == 0 )
+    else if( STARTS_WITH(geosys_clean.c_str(), "PC   ") )
     {
         gsys = 7;
         USGSParms[0] = Dearth0;
@@ -1149,7 +1155,7 @@ void CPCIDSKGeoref::PrepareGCTPFields()
 /*	Format A, one standard parallel,  usgs_params[8] = 0		*/
 /*      Format B, two standard parallels, usgs_params[8] = not 0	*/
 /* -------------------------------------------------------------------- */
-    else if( strncmp(geosys_clean.c_str(),"EC   ",5) == 0 )
+    else if( STARTS_WITH(geosys_clean.c_str(), "EC   ") )
     {
         gsys = 8;
         USGSParms[0] = Dearth0;
@@ -1170,7 +1176,7 @@ void CPCIDSKGeoref::PrepareGCTPFields()
 /* -------------------------------------------------------------------- */
 /*	Projection 9: Transverse Mercator				*/ 
 /* -------------------------------------------------------------------- */
-    else if( strncmp(geosys_clean.c_str(),"TM   ",5) == 0 )
+    else if( STARTS_WITH(geosys_clean.c_str(), "TM   ") )
     {
         gsys = 9;
         USGSParms[0] = Dearth0;
@@ -1186,7 +1192,7 @@ void CPCIDSKGeoref::PrepareGCTPFields()
 /* -------------------------------------------------------------------- */
 /*	Projection 10: Stereographic					*/
 /* -------------------------------------------------------------------- */
-    else if( strncmp(geosys_clean.c_str(),"SG   ",5) == 0 )
+    else if( STARTS_WITH(geosys_clean.c_str(), "SG   ") )
     {
         gsys = 10;
         USGSParms[0] = Dearth0;
@@ -1200,7 +1206,7 @@ void CPCIDSKGeoref::PrepareGCTPFields()
 /* -------------------------------------------------------------------- */
 /*	Projection 11: Lambert Azimuthal Equal-Area			*/
 /* -------------------------------------------------------------------- */
-    else if( strncmp(geosys_clean.c_str(),"LAEA ",5) == 0 )
+    else if( STARTS_WITH(geosys_clean.c_str(), "LAEA ") )
     {
         gsys = 11;
         
@@ -1215,7 +1221,7 @@ void CPCIDSKGeoref::PrepareGCTPFields()
 /* -------------------------------------------------------------------- */
 /*	Projection 12: Azimuthal Equidistant				*/
 /* -------------------------------------------------------------------- */
-    else if( strncmp(geosys_clean.c_str(),"AE   ",5) == 0 )
+    else if( STARTS_WITH(geosys_clean.c_str(), "AE   ") )
     {
         gsys = 12;
         USGSParms[0] = Dearth0;
@@ -1229,7 +1235,7 @@ void CPCIDSKGeoref::PrepareGCTPFields()
 /* -------------------------------------------------------------------- */
 /*	Projection 13: Gnomonic						*/
 /* -------------------------------------------------------------------- */
-    else if( strncmp(geosys_clean.c_str(),"GNO  ",5) == 0 )
+    else if( STARTS_WITH(geosys_clean.c_str(), "GNO  ") )
     {
         gsys = 13;
         USGSParms[0] = Dearth0;
@@ -1243,7 +1249,7 @@ void CPCIDSKGeoref::PrepareGCTPFields()
 /* -------------------------------------------------------------------- */
 /*	Projection 14: Orthographic					*/ 
 /* -------------------------------------------------------------------- */
-    else if( strncmp(geosys_clean.c_str(),"OG   ",5) == 0 )
+    else if( STARTS_WITH(geosys_clean.c_str(), "OG   ") )
     {
         gsys = 14;
         USGSParms[0] = Dearth0;
@@ -1257,7 +1263,7 @@ void CPCIDSKGeoref::PrepareGCTPFields()
 /* -------------------------------------------------------------------- */
 /*	Projection  15: General Vertical Near-Side Perspective		*/
 /* -------------------------------------------------------------------- */
-    else if( strncmp(geosys_clean.c_str(),"GVNP ",5) == 0 )
+    else if( STARTS_WITH(geosys_clean.c_str(), "GVNP ") )
     {
         gsys = 15;
         USGSParms[0] = Dearth0;
@@ -1273,7 +1279,7 @@ void CPCIDSKGeoref::PrepareGCTPFields()
 /* -------------------------------------------------------------------- */
 /*	Projection 16: Sinusoidal 					*/
 /* -------------------------------------------------------------------- */
-    else if( strncmp(geosys_clean.c_str(),"SIN  ",5) == 0 )
+    else if( STARTS_WITH(geosys_clean.c_str(), "SIN  ") )
     {
         gsys = 16;
         USGSParms[0] = Dearth0;
@@ -1285,7 +1291,7 @@ void CPCIDSKGeoref::PrepareGCTPFields()
 /* -------------------------------------------------------------------- */
 /*	Projection 17: Equirectangular					*/
 /* -------------------------------------------------------------------- */
-    else if( strncmp(geosys_clean.c_str(),"ER   ",5) == 0 )
+    else if( STARTS_WITH(geosys_clean.c_str(), "ER   ") )
     {
         gsys = 17;
         USGSParms[0] = Dearth0;
@@ -1297,7 +1303,7 @@ void CPCIDSKGeoref::PrepareGCTPFields()
 /* -------------------------------------------------------------------- */
 /*	Projection 18: Miller Cylindrical				*/
 /* -------------------------------------------------------------------- */
-    else if( strncmp(geosys_clean.c_str(),"MC   ",5) == 0 )
+    else if( STARTS_WITH(geosys_clean.c_str(), "MC   ") )
     {
         gsys = 18;
         USGSParms[0] = Dearth0;
@@ -1311,7 +1317,7 @@ void CPCIDSKGeoref::PrepareGCTPFields()
 /* -------------------------------------------------------------------- */
 /*	Projection 19: Van der Grinten					*/
 /* -------------------------------------------------------------------- */
-    else if( strncmp(geosys_clean.c_str(),"VDG  ",5) == 0 )
+    else if( STARTS_WITH(geosys_clean.c_str(), "VDG  ") )
     {
         gsys = 19;
         USGSParms[0] = Dearth0;
@@ -1329,7 +1335,7 @@ void CPCIDSKGeoref::PrepareGCTPFields()
 /*	  Format B, Long1, Lat1, Long2, Lat2 defined (Azimuth		*/
 /*	     and RefLong not defined), usgs_params[12] = not 0      	*/
 /* -------------------------------------------------------------------- */
-    else if( strncmp(geosys_clean.c_str(),"OM   ",5) == 0 )
+    else if( STARTS_WITH(geosys_clean.c_str(), "OM   ") )
     {
         gsys = 20;
         USGSParms[0] = Dearth0;
@@ -1355,7 +1361,7 @@ void CPCIDSKGeoref::PrepareGCTPFields()
 /* -------------------------------------------------------------------- */
 /*	Projection 21: Robinson						*/
 /* -------------------------------------------------------------------- */
-    else if( strncmp(geosys_clean.c_str(),"ROB  ",5) == 0 )
+    else if( STARTS_WITH(geosys_clean.c_str(), "ROB  ") )
     {
           gsys = 21;
           USGSParms[0] = Dearth0;
@@ -1370,7 +1376,7 @@ void CPCIDSKGeoref::PrepareGCTPFields()
 /* -------------------------------------------------------------------- */
 /*	Projection 22: Space Oblique Mercator				*/
 /* -------------------------------------------------------------------- */
-    else if( strncmp(geosys_clean.c_str(),"SOM  ",5) == 0 )
+    else if( STARTS_WITH(geosys_clean.c_str(), "SOM  ") )
     {
           gsys = 22;
           USGSParms[0] = Dearth0;
@@ -1385,7 +1391,7 @@ void CPCIDSKGeoref::PrepareGCTPFields()
 /* -------------------------------------------------------------------- */
 /*	Projection 23: Modified Stereographic Conformal (Alaska)	*/ 
 /* -------------------------------------------------------------------- */
-    else if( strncmp(geosys_clean.c_str(),"MSC  ",5) == 0 )
+    else if( STARTS_WITH(geosys_clean.c_str(), "MSC  ") )
     {
           gsys = 23;
           USGSParms[0] = Dearth0;
@@ -1400,7 +1406,7 @@ void CPCIDSKGeoref::PrepareGCTPFields()
 /*	Projection 6: Universal Polar Stereographic is just Polar	*/
 /*	Stereographic with certain assumptions.				*/
 /* -------------------------------------------------------------------- */
-    else if( strncmp(geosys_clean.c_str(),"UPS  ",5) == 0 )
+    else if( STARTS_WITH(geosys_clean.c_str(), "UPS  ") )
     {
           gsys = 6;
 
diff --git a/frmts/pcidsk/sdk/segment/cpcidskgeoref.h b/frmts/pcidsk/sdk/segment/cpcidskgeoref.h
index 7607345..a9c9c59 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskgeoref.h
+++ b/frmts/pcidsk/sdk/segment/cpcidskgeoref.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_SEGMENT_PCIDSKGEOREF_H
-#define __INCLUDE_SEGMENT_PCIDSKGEOREF_H
+#ifndef INCLUDE_SEGMENT_PCIDSKGEOREF_H
+#define INCLUDE_SEGMENT_PCIDSKGEOREF_H
 
 #include "pcidsk_config.h"
 #include "pcidsk_types.h"
@@ -85,4 +85,4 @@ namespace PCIDSK
     };
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_SEGMENT_PCIDSKGEOREF_H
+#endif // INCLUDE_SEGMENT_PCIDSKGEOREF_H
diff --git a/frmts/pcidsk/sdk/segment/cpcidskpct.cpp b/frmts/pcidsk/sdk/segment/cpcidskpct.cpp
index 722fff0..ca7e2b3 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskpct.cpp
+++ b/frmts/pcidsk/sdk/segment/cpcidskpct.cpp
@@ -36,9 +36,9 @@ using namespace PCIDSK;
 /*                            CPCIDSK_PCT()                             */
 /************************************************************************/
 
-CPCIDSK_PCT::CPCIDSK_PCT( PCIDSKFile *file, int segment,
+CPCIDSK_PCT::CPCIDSK_PCT( PCIDSKFile *fileIn, int segmentIn,
                           const char *segment_pointer )
-        : CPCIDSKSegment( file, segment, segment_pointer )
+        : CPCIDSKSegment( fileIn, segmentIn, segment_pointer )
 
 {
 }
diff --git a/frmts/pcidsk/sdk/segment/cpcidskpct.h b/frmts/pcidsk/sdk/segment/cpcidskpct.h
index dec13f3..2e18a61 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskpct.h
+++ b/frmts/pcidsk/sdk/segment/cpcidskpct.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_SEGMENT_PCIDSK_PCT_H
-#define __INCLUDE_SEGMENT_PCIDSK_PCT_H
+#ifndef INCLUDE_SEGMENT_PCIDSK_PCT_H
+#define INCLUDE_SEGMENT_PCIDSK_PCT_H
 
 #include "pcidsk_config.h"
 #include "pcidsk_types.h"
diff --git a/frmts/pcidsk/sdk/segment/cpcidskpolymodel.h b/frmts/pcidsk/sdk/segment/cpcidskpolymodel.h
index f68230c..e1db7c5 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskpolymodel.h
+++ b/frmts/pcidsk/sdk/segment/cpcidskpolymodel.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PCIDSK_SEGMENT_PCIDSKPOLYMODEL_H
-#define __INCLUDE_PCIDSK_SEGMENT_PCIDSKPOLYMODEL_H
+#ifndef INCLUDE_PCIDSK_SEGMENT_PCIDSKPOLYMODEL_H
+#define INCLUDE_PCIDSK_SEGMENT_PCIDSKPOLYMODEL_H
  
 #include "pcidsk_poly.h"
 #include "segment/cpcidsksegment.h"
@@ -74,4 +74,4 @@ namespace PCIDSK {
     };
 }
 
-#endif // __INCLUDE_PCIDSK_SEGMENT_PCIDSKPOLYMODEL_H
+#endif // INCLUDE_PCIDSK_SEGMENT_PCIDSKPOLYMODEL_H
diff --git a/frmts/pcidsk/sdk/segment/cpcidskrpcmodel.cpp b/frmts/pcidsk/sdk/segment/cpcidskrpcmodel.cpp
index 9b7f669..b8377c6 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskrpcmodel.cpp
+++ b/frmts/pcidsk/sdk/segment/cpcidskrpcmodel.cpp
@@ -25,6 +25,7 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "pcidsk_config.h"
 #include "pcidsk_rpc.h"
 #include "segment/cpcidsksegment.h"
 #include "core/pcidsk_utils.h"
@@ -44,31 +45,31 @@ struct CPCIDSKRPCModelSegment::PCIDSKRPCInfo
     bool userrpc; // whether or not the RPC was generated from GCPs
     bool adjusted; // Whether or not the RPC has been adjusted
     int downsample; // Epipolar Downsample factor
-    
+
     unsigned int pixels; // pixels in the image
     unsigned int lines; // lines in the image
-    
+
     unsigned int num_coeffs; // number of coefficientsg
-    
+
     std::vector<double> pixel_num; // numerator, pixel direction
     std::vector<double> pixel_denom; // denominator, pixel direction
     std::vector<double> line_num; // numerator, line direction
     std::vector<double> line_denom; // denominator, line direction
-    
+
     // Scale/offset coefficients in the ground domain
     double x_off;
     double x_scale;
-    
+
     double y_off;
     double y_scale;
-    
+
     double z_off;
     double z_scale;
-    
+
     // Scale/offset coefficients in the raster domain
     double pix_off;
     double pix_scale;
-    
+
     double line_off;
     double line_scale;
     
@@ -85,8 +86,8 @@ struct CPCIDSKRPCModelSegment::PCIDSKRPCInfo
     PCIDSKBuffer seg_data;
 };
 
-CPCIDSKRPCModelSegment::CPCIDSKRPCModelSegment(PCIDSKFile *file, int segment,const char *segment_pointer) :
-    CPCIDSKSegment(file, segment, segment_pointer), pimpl_(new CPCIDSKRPCModelSegment::PCIDSKRPCInfo), 
+CPCIDSKRPCModelSegment::CPCIDSKRPCModelSegment(PCIDSKFile *fileIn, int segmentIn,const char *segment_pointer) :
+    CPCIDSKSegment(fileIn, segmentIn, segment_pointer), pimpl_(new CPCIDSKRPCModelSegment::PCIDSKRPCInfo), 
     loaded_(false),mbModified(false)
 {
     Load();
@@ -124,7 +125,7 @@ void CPCIDSKRPCModelSegment::Load()
     // Bytes 30-35: 'SENSOR'
     // Bytes    36: Sensor Name (NULL terminated)
     
-    if (std::strncmp(pimpl_->seg_data.buffer, "RFMODEL ", 8)) 
+    if (!STARTS_WITH(pimpl_->seg_data.buffer, "RFMODEL ")) 
     {
         pimpl_->seg_data.Put("RFMODEL",0,8);
         pimpl_->userrpc = false;
@@ -146,23 +147,23 @@ void CPCIDSKRPCModelSegment::Load()
     
     // Check for the DS characters
     pimpl_->downsample = 1;
-    if (!std::strncmp(&pimpl_->seg_data.buffer[22], "DS", 2)) 
+    if (STARTS_WITH(&pimpl_->seg_data.buffer[22], "DS")) 
     {
         // Read the downsample factor
         pimpl_->downsample = pimpl_->seg_data.GetInt(24, 3);
     }
     
-    //This is requiered if writting with PCIDSKIO 
+    //This is required if writing with PCIDSKIO
     //and reading with GDBIO (probably because of legacy issue)
     // see Bugzilla 255 and 254.
     bool bSecond = false;
-    if (!std::strncmp(&pimpl_->seg_data.buffer[27], "2ND", 3)) 
+    if (STARTS_WITH(&pimpl_->seg_data.buffer[27], "2ND")) 
     {
         bSecond = true;
     }
     
     // Sensor name:
-    if (!std::strncmp(&pimpl_->seg_data.buffer[30], "SENSOR", 6)) {
+    if (STARTS_WITH(&pimpl_->seg_data.buffer[30], "SENSOR")) {
         pimpl_->sensor_name = std::string(&pimpl_->seg_data.buffer[36]);
     } else {
         pimpl_->sensor_name = "";
@@ -194,7 +195,7 @@ void CPCIDSKRPCModelSegment::Load()
 
         if (pimpl_->num_coeffs * 22 > 512) {
             // this segment is malformed. Throw an exception.
-            throw PCIDSKException("RFMODEL segment coefficient count requires more "
+            return ThrowPCIDSKException("RFMODEL segment coefficient count requires more "
                 "than one block to store. There is an error in this segment. The "
                 "number of coefficients according to the segment is %d.", pimpl_->num_coeffs);
         }
@@ -241,7 +242,7 @@ void CPCIDSKRPCModelSegment::Load()
 
         if (pimpl_->num_coeffs * 22 > 512) {
             // this segment is malformed. Throw an exception.
-            throw PCIDSKException("RFMODEL segment coefficient count requires more "
+            return ThrowPCIDSKException("RFMODEL segment coefficient count requires more "
                 "than one block to store. There is an error in this segment. The "
                 "number of coefficients according to the segment is %d.", pimpl_->num_coeffs);
         }
@@ -355,14 +356,14 @@ void CPCIDSKRPCModelSegment::Write(void)
     pimpl_->seg_data.Put("DS",22,2);
     pimpl_->seg_data.Put(pimpl_->downsample,24,3);
 
-    //This is requiered if writting with PCIDSKIO 
+    //This is required if writing with PCIDSKIO 
     //and reading with GDBIO (probably because of legacy issue)
     // see Bugzilla 255 and 254.
     pimpl_->seg_data.Put("2ND",27,3);
 
     // Sensor name:
     pimpl_->seg_data.Put("SENSOR",30,6);
-    pimpl_->seg_data.Put(pimpl_->sensor_name.c_str(),36,pimpl_->sensor_name.size());
+    pimpl_->seg_data.Put(pimpl_->sensor_name.c_str(),36,static_cast<int>(pimpl_->sensor_name.size()));
   
     // Block 2:
     // Bytes     0-3: Number of coefficients
@@ -383,7 +384,7 @@ void CPCIDSKRPCModelSegment::Write(void)
 
     if (pimpl_->num_coeffs * 22 > 512) {
         // this segment is malformed. Throw an exception.
-        throw PCIDSKException("RFMODEL segment coefficient count requires more "
+        return ThrowPCIDSKException("RFMODEL segment coefficient count requires more "
             "than one block to store. There is an error in this segment. The "
             "number of coefficients according to the segment is %d.", pimpl_->num_coeffs);
     }
@@ -491,7 +492,7 @@ void CPCIDSKRPCModelSegment::SetCoefficients(
 {
     if (xnum.size() != xdenom.size() || ynum.size() != ydenom.size() ||
         xnum.size() != ynum.size() || xdenom.size() != ydenom.size()) {
-        throw PCIDSKException("All RPC coefficient vectors must be the "
+        return ThrowPCIDSKException("All RPC coefficient vectors must be the "
             "same size.");
     }
     
@@ -566,7 +567,7 @@ void CPCIDSKRPCModelSegment::SetAdjCoordValues(const std::vector<double>& xcoord
     const std::vector<double>& ycoord)
 {
     if (xcoord.size() != 6 || ycoord.size() != 6) {
-        throw PCIDSKException("X and Y adjusted coordinates must have "
+        return ThrowPCIDSKException("X and Y adjusted coordinates must have "
             "length 6.");
     }
     
@@ -626,7 +627,7 @@ std::string CPCIDSKRPCModelSegment::GetGeosysString(void) const
 void CPCIDSKRPCModelSegment::SetGeosysString(const std::string& geosys)
 {
     if (geosys.size() > 16) {
-        throw PCIDSKException("GeoSys/MapUnits string must be no more than "
+        return ThrowPCIDSKException("GeoSys/MapUnits string must be no more than "
             "16 characters to be valid.");
     }
     pimpl_->map_units = geosys;
@@ -647,9 +648,10 @@ unsigned int CPCIDSKRPCModelSegment::GetPixels(void) const
 void CPCIDSKRPCModelSegment::SetRasterSize(const unsigned int lines, const unsigned int pixels)
 {
     if (lines == 0 || pixels == 0) {
-        throw PCIDSKException("Non-sensical raster dimensions provided: %ux%u", lines, pixels);
+        return ThrowPCIDSKException("Nonsensical raster dimensions provided: %ux%u",
+                              lines, pixels);
     }
-    
+
     pimpl_->lines = lines;
     pimpl_->pixels = pixels;
     mbModified = true;
@@ -658,9 +660,9 @@ void CPCIDSKRPCModelSegment::SetRasterSize(const unsigned int lines, const unsig
 void CPCIDSKRPCModelSegment::SetDownsample(const unsigned int downsample)
 {
     if (downsample == 0) {
-        throw PCIDSKException("Invalid downsample factor provided: %u", downsample);
+        return ThrowPCIDSKException("Invalid downsample factor provided: %u", downsample);
     }
-    
+
     pimpl_->downsample = downsample;
     mbModified = true;
 }
@@ -677,4 +679,3 @@ void CPCIDSKRPCModelSegment::Synchronize()
         this->Write();
     }
 }
-
diff --git a/frmts/pcidsk/sdk/segment/cpcidskrpcmodel.h b/frmts/pcidsk/sdk/segment/cpcidskrpcmodel.h
index 224eb4b..2c077af 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskrpcmodel.h
+++ b/frmts/pcidsk/sdk/segment/cpcidskrpcmodel.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PCIDSK_SEGMENT_PCIDSKRPCMODEL_H
-#define __INCLUDE_PCIDSK_SEGMENT_PCIDSKRPCMODEL_H
+#ifndef INCLUDE_PCIDSK_SEGMENT_PCIDSKRPCMODEL_H
+#define INCLUDE_PCIDSK_SEGMENT_PCIDSKRPCMODEL_H
  
 #include "pcidsk_rpc.h"
 #include "segment/cpcidsksegment.h"
@@ -124,4 +124,4 @@ namespace PCIDSK {
     };
 }
 
-#endif // __INCLUDE_PCIDSK_SEGMENT_PCIDSKRPCMODEL_H
+#endif // INCLUDE_PCIDSK_SEGMENT_PCIDSKRPCMODEL_H
diff --git a/frmts/pcidsk/sdk/segment/cpcidsksegment.cpp b/frmts/pcidsk/sdk/segment/cpcidsksegment.cpp
index 577eef7..8f293c9 100644
--- a/frmts/pcidsk/sdk/segment/cpcidsksegment.cpp
+++ b/frmts/pcidsk/sdk/segment/cpcidsksegment.cpp
@@ -43,12 +43,12 @@ using namespace PCIDSK;
 /*                           PCIDSKSegment()                            */
 /************************************************************************/
 
-CPCIDSKSegment::CPCIDSKSegment( PCIDSKFile *file, int segment,
+CPCIDSKSegment::CPCIDSKSegment( PCIDSKFile *fileIn, int segmentIn,
                               const char *segment_pointer )
 
 {
-    this->file = file;
-    this->segment = segment;
+    this->file = fileIn;
+    this->segment = segmentIn;
 
     LoadSegmentPointer( segment_pointer );
     LoadSegmentHeader(); // eventually we might want to defer this.
@@ -166,9 +166,9 @@ void CPCIDSKSegment::ReadFromFile( void *buffer, uint64 offset, uint64 size )
 
 {
     if( offset+size+1024 > data_size )
-        ThrowPCIDSKException( 
-            "Attempt to read past end of segment %d (%d bytes at offset %d)",
-            segment, (int) offset, (int) size );
+        return ThrowPCIDSKException( 
+            "Attempt to read past end of segment %d (%u bytes at offset %u)",
+            segment, (unsigned int) offset, (unsigned int) size );
     file->ReadFromFile( buffer, offset + data_offset + 1024, size );
 }
 
@@ -183,7 +183,7 @@ void CPCIDSKSegment::WriteToFile( const void *buffer, uint64 offset, uint64 size
         CPCIDSKFile *poFile = dynamic_cast<CPCIDSKFile *>(file);
         
         if (poFile == NULL) {
-            ThrowPCIDSKException("Attempt to dynamic_cast the file interface "
+            return ThrowPCIDSKException("Attempt to dynamic_cast the file interface "
                 "to a CPCIDSKFile failed. This is a programmer error, and should "
                 "be reported to your software provider.");
         }
diff --git a/frmts/pcidsk/sdk/segment/cpcidsksegment.h b/frmts/pcidsk/sdk/segment/cpcidsksegment.h
index aed4176..c7557fd 100644
--- a/frmts/pcidsk/sdk/segment/cpcidsksegment.h
+++ b/frmts/pcidsk/sdk/segment/cpcidsksegment.h
@@ -25,8 +25,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _INCLUDE_SEGMENT_PCIDSKSEGMENT_H
-#define _INCLUDE_SEGMENT_PCIDSKSEGMENT_H
+#ifndef INCLUDE_SEGMENT_PCIDSKSEGMENT_H
+#define INCLUDE_SEGMENT_PCIDSKSEGMENT_H
 
 #include "pcidsk_config.h"
 #include "pcidsk_types.h"
@@ -110,4 +110,4 @@ namespace PCIDSK
     };
     
 } // end namespace PCIDSK
-#endif // _INCLUDE_SEGMENT_PCIDSKSEGMENT_H
+#endif // INCLUDE_SEGMENT_PCIDSKSEGMENT_H
diff --git a/frmts/pcidsk/sdk/segment/cpcidsktoutinmodel.cpp b/frmts/pcidsk/sdk/segment/cpcidsktoutinmodel.cpp
index 7ce2f5d..91647bb 100644
--- a/frmts/pcidsk/sdk/segment/cpcidsktoutinmodel.cpp
+++ b/frmts/pcidsk/sdk/segment/cpcidsktoutinmodel.cpp
@@ -56,10 +56,10 @@ namespace
 #endif
 }
 
-CPCIDSKToutinModelSegment::CPCIDSKToutinModelSegment(PCIDSKFile *file, 
-                                                   int segment,
+CPCIDSKToutinModelSegment::CPCIDSKToutinModelSegment(PCIDSKFile *fileIn, 
+                                                   int segmentIn,
                                                    const char *segment_pointer) :
-    CPCIDSKEphemerisSegment(file, segment, segment_pointer,false)
+    CPCIDSKEphemerisSegment(fileIn, segmentIn, segment_pointer,false)
 {
     loaded_ = false;
     mbModified = false;
@@ -116,15 +116,14 @@ void CPCIDSKToutinModelSegment::Load()
     seg_data.SetSize((int)data_size - 1024);
     
     ReadFromFile(seg_data.buffer, 0, data_size - 1024);
-    
+
     SRITInfo_t* poInfo = BinaryToSRITInfo();
 
     mpoInfo = poInfo;
-    
+
     // We've now loaded the structure up with data. Mark it as being loaded 
     // properly.
     loaded_ = true;
-    
 }
 
 /**
@@ -145,7 +144,7 @@ void CPCIDSKToutinModelSegment::Write(void)
 }
 
 /**
- * Synchronize the segement, if it was modified then
+ * Synchronize the segment, if it was modified then
  * write it into disk.
  */
 void CPCIDSKToutinModelSegment::Synchronize()
@@ -177,7 +176,7 @@ CPCIDSKToutinModelSegment::BinaryToSRITInfo()
 /* -------------------------------------------------------------------- */    
     // We test the name of the binary segment before starting to read 
     // the buffer.
-    if (std::strncmp(seg_data.buffer, "MODEL   ", 8)) 
+    if (!STARTS_WITH(seg_data.buffer, "MODEL   ")) 
     {
         seg_data.Put("MODEL   ",0,8);
         return NULL;
@@ -199,10 +198,10 @@ CPCIDSKToutinModelSegment::BinaryToSRITInfo()
 /*      Allocate the SRITModel.                                         */
 /* -------------------------------------------------------------------- */
     SRITModel = new SRITInfo_t();
-    
+
     SRITModel->GCPMeanHtFlag = 0;
     SRITModel->nDownSample = 1;
-    if(std::strncmp(seg_data.Get(22,2) , "DS", 2)==0)
+    if(STARTS_WITH(seg_data.Get(22,2) , "DS"))
     {
 	SRITModel->nDownSample = seg_data.GetInt(24,3); 
     }
@@ -210,7 +209,7 @@ CPCIDSKToutinModelSegment::BinaryToSRITInfo()
 /* -------------------------------------------------------------------- */
 /*      Read the Block 1                                                */
 /* -------------------------------------------------------------------- */
-    
+
     SRITModel->N0x2        = seg_data.GetDouble(512,22);
     SRITModel->aa          = seg_data.GetDouble(512+22,22);
     SRITModel->SmALPHA     = seg_data.GetDouble(512+44,22);
@@ -244,9 +243,9 @@ CPCIDSKToutinModelSegment::BinaryToSRITInfo()
         SRITModel->delL   = 0.0;
         SRITModel->delTau = 0.0;
     }
-                                                                  
+
 /* -------------------------------------------------------------------- */
-/*	Read the GCP information in Block 2     			*/
+/*      Read the GCP information in Block 2                             */
 /* -------------------------------------------------------------------- */
 
     SRITModel->nGCPCount       = seg_data.GetInt(2*512,10); 
@@ -313,12 +312,12 @@ CPCIDSKToutinModelSegment::BinaryToSRITInfo()
 
     if( SRITModel->nSensor == -999)
     {
-        throw PCIDSKException("Invalid Sensor : %s.",
+        return (SRITInfo_t*)ThrowPCIDSKExceptionPtr("Invalid Sensor : %s.",
                               SRITModel->OrbitPtr->SatelliteSensor.c_str());
     }
     if( SRITModel->nModel == -999)
     {
-	throw PCIDSKException("Invalid Model from sensor number: %d.",
+        return (SRITInfo_t*)ThrowPCIDSKExceptionPtr("Invalid Model from sensor number: %d.",
                               SRITModel->nSensor);
     }
 
@@ -328,14 +327,16 @@ CPCIDSKToutinModelSegment::BinaryToSRITInfo()
     if (SRITModel->OrbitPtr->AttitudeSeg != NULL ||
         SRITModel->OrbitPtr->RadarSeg != NULL)
     {
-        if (SRITModel->OrbitPtr->Type == OrbAttitude)
+        AttitudeSeg_t *attitudeSeg
+            = SRITModel->OrbitPtr->AttitudeSeg;
+
+        if (SRITModel->OrbitPtr->Type == OrbAttitude &&
+            attitudeSeg != NULL)
         {
             int  ndata;
-            AttitudeSeg_t *attitudeSeg
-                = SRITModel->OrbitPtr->AttitudeSeg;
 
-	    ndata = SRITModel->OrbitPtr->AttitudeSeg->NumberOfLine;
-       
+            ndata = attitudeSeg->NumberOfLine;
+
             for (i=0; i<ndata; i++)
             {
                 SRITModel->Hdeltat.push_back(
@@ -359,14 +360,14 @@ CPCIDSKToutinModelSegment::BinaryToSRITInfo()
 /************************************************************************/
 /**
   * Translate a SRITInfo_t into binary data.
-  * Translate a SRITInfo_t into the corresponding block of          
-  * binary data.  This function is expected to be used by           
-  * ranslators such as iisopen.c (VISTA) so that our satellite     
-  * models can be converted into some opaque serialized form.       
-  * Translate a RFInfo_t into the corresponding block of binary data. 
+  * Translate a SRITInfo_t into the corresponding block of
+  * binary data.  This function is expected to be used by
+  * translators such as iisopen.c (VISTA) so that our satellite
+  * models can be converted into some opaque serialized form.
+  * Translate a RFInfo_t into the corresponding block of binary data.
   *
-  * @param  SRITModel	     Satellite Model structure.
-  * @param  pnBinaryLength	Length of binary data.
+  * @param  SRITModel        Satellite Model structure.
+  * @param  pnBinaryLength   Length of binary data.
   * @return Binary data for a  Satellite Model structure.
   */
 void
@@ -384,7 +385,7 @@ CPCIDSKToutinModelSegment::SRITInfoToBinary( SRITInfo_t *SRITModel )
 
     //clean the buffer
     memset( seg_data.buffer , ' ', 512 * 21 );
-    
+
 /* -------------------------------------------------------------------- */
 /*	Initialize the header.						*/
 /* -------------------------------------------------------------------- */
@@ -398,7 +399,7 @@ CPCIDSKToutinModelSegment::SRITInfoToBinary( SRITInfo_t *SRITModel )
 /*      Write the model results to second segment                       */
 /* -------------------------------------------------------------------- */
     nPos = 512*1;
-    
+
     seg_data.Put(SRITModel->N0x2,nPos,22,"%22.14f");
     seg_data.Put(SRITModel->aa,nPos+22,22,"%22.14f");
     seg_data.Put(SRITModel->SmALPHA,nPos+22*2,22,"%22.14f");
@@ -424,7 +425,7 @@ CPCIDSKToutinModelSegment::SRITInfoToBinary( SRITInfo_t *SRITModel )
     seg_data.Put(SRITModel->delTau,nPos+22*22,22,"%22.14f");
 
 /* -------------------------------------------------------------------- */
-/*      Find the min and max height					*/
+/*      Find the min and max height                                     */
 /* -------------------------------------------------------------------- */
     nPos = 2*512;
 
@@ -456,7 +457,8 @@ CPCIDSKToutinModelSegment::SRITInfoToBinary( SRITInfo_t *SRITModel )
         SRITModel->OrbitPtr->RadarSeg != NULL ||
         SRITModel->OrbitPtr->AvhrrSeg != NULL )
     {
-        if (SRITModel->OrbitPtr->Type == OrbAttitude) 
+        if (SRITModel->OrbitPtr->Type == OrbAttitude &&
+            SRITModel->OrbitPtr->AttitudeSeg != NULL) 
 	{
 	    if (SRITModel->OrbitPtr->AttitudeSeg->NumberOfLine != 0)
                 seg_data.Put("3",nPos+20,1);
@@ -531,219 +533,219 @@ int  CPCIDSKToutinModelSegment::GetSensor( EphemerisSeg_t *OrbitPtr)
 
     nSensor = -999;
 
-    if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"AVHRR",5))
+    if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "AVHRR"))
         nSensor = AVHRR;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"PLA",3))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "PLA"))
         nSensor = PLA_1;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"MLA",3))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "MLA"))
         nSensor = MLA_1;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"ASTER",5))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "ASTER"))
         nSensor = ASTER;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"SAR",3))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "SAR"))
     {
         nSensor = SAR;
         if (OrbitPtr->PixelRes == 6.25)
             nSensor = RSAT_FIN;
     }
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"LISS-1",6))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "LISS-1"))
         nSensor = LISS_1;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"LISS-2",6))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "LISS-2"))
         nSensor = LISS_2;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"LISS-3",6))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "LISS-3"))
         nSensor = LISS_3;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"LISS-L3-L2",10))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "LISS-L3-L2"))
         nSensor = LISS_L3_L2;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"LISS-L3",7))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "LISS-L3"))
         nSensor = LISS_L3;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"LISS-L4-L2",10))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "LISS-L4-L2"))
         nSensor = LISS_L4_L2;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"LISS-L4",7))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "LISS-L4"))
         nSensor = LISS_L4;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"LISS-P3-L2",10))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "LISS-P3-L2"))
         nSensor = LISS_P3_L2;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"LISS-P3",7))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "LISS-P3"))
         nSensor = LISS_P3;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"LISS-W3-L2",10))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "LISS-W3-L2"))
         nSensor = LISS_W3_L2;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"LISS-W3",7))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "LISS-W3"))
         nSensor = LISS_W3;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"LISS-M3",7))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "LISS-M3"))
         nSensor = LISS_M3;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"LISS-AWF-L2",11))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "LISS-AWF-L2"))
         nSensor = LISS_AWF_L2;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"LISS-AWF",8))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "LISS-AWF"))
         nSensor = LISS_AWF;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"EOC",3))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "EOC"))
         nSensor = EOC;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"IRS",3))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "IRS"))
         nSensor = IRS_1;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"TM",2))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "TM"))
     {
         nSensor = TM;
         if (OrbitPtr->PixelRes == 15)
             nSensor = ETM;
     }
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"ETM",3))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "ETM"))
         nSensor = ETM;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"IKO",3))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "IKO"))
     {
         nSensor = IKO_PAN;
         if (OrbitPtr->PixelRes == 4)
             nSensor = IKO_MULTI;
     }
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"ORBVIEW",7))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "ORBVIEW"))
     {
         nSensor = ORBVIEW_PAN;
         if (OrbitPtr->PixelRes == 4)
             nSensor = ORBVIEW_MULTI;
     }
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"OV",2))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "OV"))
     {
-        if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"OV3_PAN_BASIC",13))
+        if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "OV3_PAN_BASIC"))
             nSensor = OV3_PAN_BASIC;
-        else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"OV3_PAN_GEO",11))
+        else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "OV3_PAN_GEO"))
             nSensor = OV3_PAN_GEO;
-        else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"OV3_MULTI_BASIC",15))
+        else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "OV3_MULTI_BASIC"))
             nSensor = OV3_MULTI_BASIC;
-        else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"OV3_MULTI_GEO",13))
+        else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "OV3_MULTI_GEO"))
             nSensor = OV3_MULTI_GEO;
-        else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"OV5_PAN_BASIC",13))
+        else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "OV5_PAN_BASIC"))
             nSensor = OV5_PAN_BASIC;
-        else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"OV5_PAN_GEO",11))
+        else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "OV5_PAN_GEO"))
             nSensor = OV5_PAN_GEO;
-        else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"OV5_MULTI_BASIC",15))
+        else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "OV5_MULTI_BASIC"))
             nSensor = OV5_MULTI_BASIC;
-        else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"OV5_MULTI_GEO",13))
+        else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "OV5_MULTI_GEO"))
             nSensor = OV5_MULTI_GEO;
     }
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"QBIRD_PAN_STD",13))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "QBIRD_PAN_STD"))
         nSensor = QBIRD_PAN_STD; 	// this checking must go first
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"QBIRD_PAN_STH",13))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "QBIRD_PAN_STH"))
         nSensor = QBIRD_PAN_STH;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"QBIRD_PAN",9))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "QBIRD_PAN"))
         nSensor = QBIRD_PAN;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"QBIRD_MULTI_STD",15))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "QBIRD_MULTI_STD"))
         nSensor = QBIRD_MULTI_STD;	// this checking must go first
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"QBIRD_MULTI_STH",15))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "QBIRD_MULTI_STH"))
         nSensor = QBIRD_MULTI_STH;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"QBIRD_MULTI",11))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "QBIRD_MULTI"))
         nSensor = QBIRD_MULTI;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"WVIEW1_PAN_STD",14) ||
-        EQUALN(OrbitPtr->SatelliteSensor.c_str(),"WVIEW_PAN_STD",13))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "WVIEW1_PAN_STD") ||
+        STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "WVIEW_PAN_STD"))
         nSensor = WVIEW_PAN_STD; 	// this checking must go first
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"WVIEW1_PAN",10) ||
-        EQUALN(OrbitPtr->SatelliteSensor.c_str(),"WVIEW_PAN",9))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "WVIEW1_PAN") ||
+        STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "WVIEW_PAN"))
         nSensor = WVIEW_PAN;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"WVIEW_MULTI_STD",15))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "WVIEW_MULTI_STD"))
         nSensor = WVIEW_MULTI_STD;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"WVIEW_MULTI",11))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "WVIEW_MULTI"))
         nSensor = WVIEW_MULTI;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"FORMOSAT",8))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "FORMOSAT"))
     {
-        if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"FORMOSAT_PAN_L2",15))
+        if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "FORMOSAT_PAN_L2"))
             nSensor = FORMOSAT_PAN_L2;
-        else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"FORMOSAT_MULTIL2",16))
+        else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "FORMOSAT_MULTIL2"))
             nSensor = FORMOSAT_MULTIL2;
-        else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"FORMOSAT_PAN",12))
+        else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "FORMOSAT_PAN"))
             nSensor = FORMOSAT_PAN;
-        else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"FORMOSAT_MULTI",14))
+        else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "FORMOSAT_MULTI"))
             nSensor = FORMOSAT_MULTI;
     }
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"SPOT5_PAN_2_5",13))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "SPOT5_PAN_2_5"))
         nSensor = SPOT5_PAN_2_5;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"SPOT5_PAN_5",11))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "SPOT5_PAN_5"))
         nSensor = SPOT5_PAN_5;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"SPOT5_HRS",9))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "SPOT5_HRS"))
         nSensor = SPOT5_HRS;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"SPOT5_MULTI",11))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "SPOT5_MULTI"))
         nSensor = SPOT5_MULTI;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"MERIS_FR",8))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "MERIS_FR"))
         nSensor = MERIS_FR;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"MERIS_RR",8))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "MERIS_RR"))
         nSensor = MERIS_RR;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"MERIS_LR",8))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "MERIS_LR"))
         nSensor = MERIS_LR;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"ASAR",4))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "ASAR"))
         nSensor = ASAR;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"EROS",4))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "EROS"))
         nSensor = EROS;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"MODIS_1000",10))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "MODIS_1000"))
         nSensor = MODIS_1000;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"MODIS_500",9))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "MODIS_500"))
         nSensor = MODIS_500;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"MODIS_250",9))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "MODIS_250"))
         nSensor = MODIS_250;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"CBERS_HRC_L2",12))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "CBERS_HRC_L2"))
         nSensor = CBERS_HRC_L2;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"CBERS_HRC",9))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "CBERS_HRC"))
         nSensor = CBERS_HRC;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"CBERS_CCD_L2",12))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "CBERS_CCD_L2"))
         nSensor = CBERS_CCD_L2;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"CBERS_CCD",9))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "CBERS_CCD"))
         nSensor = CBERS_CCD;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"CBERS_IRM_80_L2",15))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "CBERS_IRM_80_L2"))
         nSensor = CBERS_IRM_80_L2;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"CBERS_IRM_80",12))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "CBERS_IRM_80"))
         nSensor = CBERS_IRM_80;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"CBERS_IRM_160_L2",16))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "CBERS_IRM_160_L2"))
         nSensor = CBERS_IRM_160_L2;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"CBERS_IRM_160",13))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "CBERS_IRM_160"))
         nSensor = CBERS_IRM_160;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"CBERS_WFI_L2",12))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "CBERS_WFI_L2"))
         nSensor = CBERS_WFI_L2;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"CBERS_WFI",9))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "CBERS_WFI"))
         nSensor = CBERS_WFI;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"CARTOSAT1_L1",12))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "CARTOSAT1_L1"))
         nSensor = CARTOSAT1_L1;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"CARTOSAT1_L2",12))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "CARTOSAT1_L2"))
         nSensor = CARTOSAT1_L2;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"DMC_1R",6))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "DMC_1R"))
         nSensor = DMC_1R;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"DMC_1T",6))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "DMC_1T"))
         nSensor = DMC_1T;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"ALOS_PRISM_L1",13))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "ALOS_PRISM_L1"))
         nSensor = ALOS_PRISM_L1;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"ALOS_PRISM_L2",13))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "ALOS_PRISM_L2"))
         nSensor = ALOS_PRISM_L2;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"ALOS_AVNIR_L1",13))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "ALOS_AVNIR_L1"))
         nSensor = ALOS_AVNIR_L1;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"ALOS_AVNIR_L2",13))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "ALOS_AVNIR_L2"))
         nSensor = ALOS_AVNIR_L2;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"PALSAR",6))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "PALSAR"))
         nSensor = PALSAR;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"KOMPSAT2_PAN",12))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "KOMPSAT2_PAN"))
         nSensor = KOMPSAT2_PAN;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"KOMPSAT2_MULTI",14))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "KOMPSAT2_MULTI"))
         nSensor = KOMPSAT2_MULTI;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"TERRASAR",8))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "TERRASAR"))
         nSensor = TERRASAR;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"RAPIDEYE",8))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "RAPIDEYE"))
         nSensor = RAPIDEYE_L1B;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"THEOS_PAN_L1",12))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "THEOS_PAN_L1"))
         nSensor = THEOS_PAN_L1;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"THEOS_PAN_L2",12))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "THEOS_PAN_L2"))
         nSensor = THEOS_PAN_L2;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"THEOS_MS_L1",11))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "THEOS_MS_L1"))
         nSensor = THEOS_MS_L1;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"THEOS_MS_L2",11))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "THEOS_MS_L2"))
         nSensor = THEOS_MS_L2;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"GOSAT_500_L1",12))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "GOSAT_500_L1"))
         nSensor = GOSAT_500_L1;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"GOSAT_500_L2",12))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "GOSAT_500_L2"))
         nSensor = GOSAT_500_L2;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"GOSAT_1500_L1",13))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "GOSAT_1500_L1"))
         nSensor = GOSAT_1500_L1;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"GOSAT_1500_L2",13))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "GOSAT_1500_L2"))
         nSensor = GOSAT_1500_L2;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"HJ_CCD_1A",9))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "HJ_CCD_1A"))
         nSensor = HJ_CCD_1A;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"HJ_CCD_1B",5))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "HJ_CCD_1B"))
         nSensor = HJ_CCD_1B;
-    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"NEW",3))
+    else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "NEW"))
         nSensor = NEW;
     else
     {
-        throw PCIDSKException("Invalid Sensor %s",
+        return ThrowPCIDSKException(0, "Invalid Sensor %s",
             OrbitPtr->SatelliteSensor.c_str());
     }
 
@@ -758,8 +760,6 @@ int CPCIDSKToutinModelSegment::GetModel( int nSensor )
 {
     int  nModel;
 
-    nModel = -999;
-
     switch (nSensor)
     {
     case PLA_1:
@@ -885,7 +885,7 @@ int CPCIDSKToutinModelSegment::GetModel( int nSensor )
         break;
 
     default:
-        throw PCIDSKException("Invalid sensor type.");
+        return ThrowPCIDSKException(0, "Invalid sensor type.");
         break;
     }
 
diff --git a/frmts/pcidsk/sdk/segment/cpcidsktoutinmodel.h b/frmts/pcidsk/sdk/segment/cpcidsktoutinmodel.h
index 436d837..0257d02 100644
--- a/frmts/pcidsk/sdk/segment/cpcidsktoutinmodel.h
+++ b/frmts/pcidsk/sdk/segment/cpcidsktoutinmodel.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PCIDSK_SEGMENT_PCIDSKTOUTINMODEL_H
-#define __INCLUDE_PCIDSK_SEGMENT_PCIDSKTOUTINMODEL_H
+#ifndef INCLUDE_PCIDSK_SEGMENT_PCIDSKTOUTINMODEL_H
+#define INCLUDE_PCIDSK_SEGMENT_PCIDSKTOUTINMODEL_H
  
 #include "pcidsk_toutin.h"
 #include "segment/cpcidsksegment.h"
@@ -54,7 +54,7 @@ namespace PCIDSK {
 
     //functions to read/write binary information
     private:
-        //Toutin informations.
+        //Toutin information.
         SRITInfo_t* mpoInfo;
 
         SRITInfo_t *BinaryToSRITInfo();
@@ -65,4 +65,4 @@ namespace PCIDSK {
     };
 }
 
-#endif // __INCLUDE_PCIDSK_SEGMENT_PCIDSKTOUTINMODEL_H
+#endif // INCLUDE_PCIDSK_SEGMENT_PCIDSKTOUTINMODEL_H
diff --git a/frmts/pcidsk/sdk/segment/cpcidskvectorsegment.cpp b/frmts/pcidsk/sdk/segment/cpcidskvectorsegment.cpp
index 8c29289..814266e 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskvectorsegment.cpp
+++ b/frmts/pcidsk/sdk/segment/cpcidskvectorsegment.cpp
@@ -32,14 +32,15 @@
 #include <cassert>
 #include <cstring>
 #include <cstdio>
+#include <limits>
 
 using namespace PCIDSK;
 
 /* -------------------------------------------------------------------- */
-/*      Size of a block in the record/vertice block tables.  This is    */
+/*      Size of a block in the record/vertex block tables.  This is    */
 /*      determined by the PCIDSK format and may not be changed.         */
 /* -------------------------------------------------------------------- */
-static const int block_page_size = 8192;  
+static const int block_page_size = 8192;
 
 
 /* -------------------------------------------------------------------- */
@@ -54,13 +55,16 @@ static const int shapeid_page_size = 1024;
 /*                        CPCIDSKVectorSegment()                        */
 /************************************************************************/
 
-CPCIDSKVectorSegment::CPCIDSKVectorSegment( PCIDSKFile *file, int segment,
+CPCIDSKVectorSegment::CPCIDSKVectorSegment( PCIDSKFile *fileIn, int segmentIn,
                                             const char *segment_pointer )
-        : CPCIDSKSegment( file, segment, segment_pointer )
+        : CPCIDSKSegment( fileIn, segmentIn, segment_pointer )
 
 {
     base_initialized = false;
-    
+    needs_swap = false;
+
+    shape_count = 0;
+
     last_shapes_id = NullShapeId;
     last_shapes_index = -1;
 
@@ -263,6 +267,8 @@ uint32 CPCIDSKVectorSegment::ReadField( uint32 offset, ShapeField& field,
           value.resize( count );
           if( count > 0 )
           {
+              if( offset > std::numeric_limits<uint32>::max() - 8 )
+                    return ThrowPCIDSKException(0, "Invalid offset = %u", offset);
               memcpy( &(value[0]), GetData(section,offset+4,NULL,4*count), 4*count );
               if( needs_swap )
                   SwapData( &(value[0]), 4, count );
@@ -273,8 +279,7 @@ uint32 CPCIDSKVectorSegment::ReadField( uint32 offset, ShapeField& field,
       }
 
       default:
-        assert( 0 );
-        return offset;
+        return ThrowPCIDSKException(0, "Unhandled field type %d", field_type);
     }
 }
 
@@ -310,11 +315,11 @@ uint32 CPCIDSKVectorSegment::WriteField( uint32 offset,
         break;
 
       case FieldTypeString:
-        item_size = field.GetValueString().size() + 1;
+        item_size = static_cast<uint32>(field.GetValueString().size()) + 1;
         break;
 
       case FieldTypeCountedInt:
-        item_size = field.GetValueCountedInt().size() * 4 + 4;
+        item_size = static_cast<uint32>(field.GetValueCountedInt().size()) * 4 + 4;
         break;
 
       default:
@@ -372,7 +377,7 @@ uint32 CPCIDSKVectorSegment::WriteField( uint32 offset,
       case FieldTypeCountedInt:
       {
           std::vector<int32> value = field.GetValueCountedInt();
-          uint32 count = value.size();
+          uint32 count = static_cast<uint32>(value.size());
           memcpy( buffer.buffer+offset, &count, 4 );
           if( count > 0 )
           {
@@ -428,20 +433,27 @@ char *CPCIDSKVectorSegment::GetData( int section, uint32 offset,
         pbuf_offset = &record_loaded_data_offset;
         pbuf_dirty = &record_loaded_data_dirty;
     }
+    else
+    {
+        return (char*)ThrowPCIDSKExceptionPtr("Unexpected case");
+    }
+    
+    if( offset > std::numeric_limits<uint32>::max() - static_cast<uint32>(min_bytes) )
+        return (char*)ThrowPCIDSKExceptionPtr("Invalid offset : %u", offset);
 
 /* -------------------------------------------------------------------- */
 /*      If the desired data is not within our loaded section, reload    */
 /*      one or more blocks around the request.                          */
 /* -------------------------------------------------------------------- */
     if( offset < *pbuf_offset
-        || offset+min_bytes > *pbuf_offset + pbuf->buffer_size )
+        || offset+static_cast<uint32>(min_bytes) > *pbuf_offset + static_cast<uint32>(pbuf->buffer_size) )
     {
         if( *pbuf_dirty )
             FlushDataBuffer( section );
 
         // we want whole 8K blocks around the target region.
         uint32 load_offset = offset - (offset % block_page_size);
-        int size = (offset + min_bytes - load_offset + block_page_size - 1);
+        int size = (offset + static_cast<uint32>(min_bytes) - load_offset + block_page_size - 1);
 
         size -= (size % block_page_size);
 
@@ -506,23 +518,28 @@ void CPCIDSKVectorSegment::ReadSecFromFile( int section, char *buffer,
 /* -------------------------------------------------------------------- */
     if( section == sec_raw )
     {
-        ReadFromFile( buffer, block_offset*block_page_size, block_count*block_page_size );
+        ReadFromFile( buffer, static_cast<uint64>(block_offset)*static_cast<uint32>(block_page_size),
+                      block_count*block_page_size );
         return;
     }
 
 /* -------------------------------------------------------------------- */
-/*      Process one 8K block at a time in case they are discontigous    */
+/*      Process one 8K block at a time in case they are discontiguous   */
 /*      which they often are.                                           */
 /* -------------------------------------------------------------------- */
     int i;
     const std::vector<uint32> *block_map = di[section].GetIndex();
 
-    assert( block_count + block_offset <= (int) block_map->size() );
+    if(  block_count + block_offset > (int) block_map->size() )
+    {
+        return ThrowPCIDSKException("Assertion failed: block_count(=%d) + block_offset(=%d) <= block_map->size()(=%d)",
+                                    block_count, block_offset, (int) block_map->size() );
+    }
 
     for( i = 0; i < block_count; i++ )
     {
         ReadFromFile( buffer + i * block_page_size, 
-                      block_page_size * (*block_map)[block_offset+i], 
+                      block_page_size * static_cast<uint64>((*block_map)[block_offset+i]), 
                       block_page_size );
     }
 }
@@ -562,6 +579,10 @@ void CPCIDSKVectorSegment::FlushDataBuffer( int section )
         pbuf_offset = &record_loaded_data_offset;
         pbuf_dirty = &record_loaded_data_dirty;
     }
+    else
+    {
+        return ThrowPCIDSKException("Unexpected case");
+    }
 
     if( ! *pbuf_dirty || pbuf->buffer_size == 0 )
         return;
@@ -610,12 +631,14 @@ void CPCIDSKVectorSegment::WriteSecToFile( int section, char *buffer,
 
     if( block_count + block_offset > (int) block_map->size() )
     {
-        vh.GrowBlockIndex( section, 
-                           block_count + block_offset - block_map->size() );
+        vh.GrowBlockIndex( section,
+                           static_cast<int>(block_count
+                                            + block_offset
+                                            - block_map->size() ) );
     }
 
 /* -------------------------------------------------------------------- */
-/*      Process one 8K block at a time in case they are discontigous    */
+/*      Process one 8K block at a time in case they are discontiguous   */
 /*      which they often are.                                           */
 /* -------------------------------------------------------------------- */
     int i;
@@ -760,10 +783,12 @@ void CPCIDSKVectorSegment::LoadShapeIdPage( int page )
         entries_to_load = shape_count - shape_index_start;
 
     PCIDSKBuffer wrk_index;
+    if( entries_to_load < 0 || entries_to_load > std::numeric_limits<int>::max() / 12 )
+        return ThrowPCIDSKException("Invalid entries_to_load = %d", entries_to_load);
     wrk_index.SetSize( entries_to_load * 12 );
     
     ReadFromFile( wrk_index.buffer, 
-                  shape_index_byte_offset + shape_index_start*12,
+                  shape_index_byte_offset + static_cast<uint64>(shape_index_start)*12,
                   wrk_index.buffer_size );
 
 /* -------------------------------------------------------------------- */
@@ -953,7 +978,7 @@ void CPCIDSKVectorSegment::GetVertices( ShapeId shape_id,
     int shape_index = IndexFromShapeId( shape_id );
 
     if( shape_index == -1 )
-        ThrowPCIDSKException( "Attempt to call GetVertices() on non-existing shape id '%d'.",
+        return ThrowPCIDSKException( "Attempt to call GetVertices() on non-existing shape id '%d'.",
                               (int) shape_id );
 
     AccessShapeByIndex( shape_index );
@@ -967,16 +992,28 @@ void CPCIDSKVectorSegment::GetVertices( ShapeId shape_id,
         return;
     }
 
+    if( vert_off > std::numeric_limits<uint32>::max() - 4 )
+        return ThrowPCIDSKException( "Invalid vert_off = %u", vert_off);
     memcpy( &vertex_count, GetData( sec_vert, vert_off+4, NULL, 4 ), 4 );
     if( needs_swap )
         SwapData( &vertex_count, 4, 1 );
 
-    vertices.resize( vertex_count );
+    try
+    {
+        vertices.resize( vertex_count );
+    }
+    catch( const std::bad_alloc& ex )
+    {
+        return ThrowPCIDSKException("Out of memory allocating vertices(%u): %s",
+                                    vertex_count, ex.what());
+    }
     
     // We ought to change this to process the available data and
     // then request more. 
     if( vertex_count > 0 )
     {
+        if( vert_off > std::numeric_limits<uint32>::max() - 8 )
+            return ThrowPCIDSKException( "Invalid vert_off = %u", vert_off);
         memcpy( &(vertices[0]), 
                 GetData( sec_vert, vert_off+8, NULL, vertex_count*24),
                 vertex_count * 24 );
@@ -994,7 +1031,7 @@ int CPCIDSKVectorSegment::GetFieldCount()
 {
     LoadHeader();
 
-    return vh.field_names.size();
+    return static_cast<int>(vh.field_names.size());
 }
 
 /************************************************************************/
@@ -1069,7 +1106,7 @@ void CPCIDSKVectorSegment::GetFields( ShapeId id,
     int shape_index = IndexFromShapeId( id );
 
     if( shape_index == -1 )
-        ThrowPCIDSKException( "Attempt to call GetFields() on non-existing shape id '%d'.",
+        return ThrowPCIDSKException( "Attempt to call GetFields() on non-existing shape id '%d'.",
                               (int) id );
 
     AccessShapeByIndex( shape_index );
@@ -1144,13 +1181,13 @@ void CPCIDSKVectorSegment::AddField( std::string name, ShapeFieldType type,
 /* -------------------------------------------------------------------- */
     if( default_value->GetType() != type )
     {
-        ThrowPCIDSKException( "Attempt to add field with a default value of "
+        return ThrowPCIDSKException( "Attempt to add field with a default value of "
                               "a different type than the field." );
     }
 
     if( type == FieldTypeNone )
     {
-        ThrowPCIDSKException( "Creating fields of type None not supported." );
+        return ThrowPCIDSKException( "Creating fields of type None not supported." );
     }
 
 /* -------------------------------------------------------------------- */
@@ -1170,7 +1207,7 @@ void CPCIDSKVectorSegment::AddField( std::string name, ShapeFieldType type,
 /* -------------------------------------------------------------------- */
     if( shape_count > 0 )
     {
-        ThrowPCIDSKException( "Support for adding fields in populated layers "
+        return ThrowPCIDSKException( "Support for adding fields in populated layers "
                               "has not yet been implemented." );
     }
 }
@@ -1206,7 +1243,7 @@ ShapeId CPCIDSKVectorSegment::CreateShape( ShapeId id )
         PopulateShapeIdMap();
         if( shapeid_map.count(id) > 0 )
         {
-            ThrowPCIDSKException( "Attempt to create a shape with id '%d', but that already exists.", id );
+            return ThrowPCIDSKException( 0, "Attempt to create a shape with id '%d', but that already exists.", id );
         }
     }
 
@@ -1239,7 +1276,7 @@ void CPCIDSKVectorSegment::DeleteShape( ShapeId id )
     int shape_index = IndexFromShapeId( id );
 
     if( shape_index == -1 )
-        ThrowPCIDSKException( "Attempt to call DeleteShape() on non-existing shape '%d'.",
+        return ThrowPCIDSKException( "Attempt to call DeleteShape() on non-existing shape '%d'.",
                               (int) id );
 
 /* ==================================================================== */
@@ -1302,10 +1339,10 @@ void CPCIDSKVectorSegment::SetVertices( ShapeId id,
     int shape_index = IndexFromShapeId( id );
 
     if( shape_index == -1 )
-        ThrowPCIDSKException( "Attempt to call SetVertices() on non-existing shape '%d'.",
+        return ThrowPCIDSKException( "Attempt to call SetVertices() on non-existing shape '%d'.",
                               (int) id );
 
-    PCIDSKBuffer vbuf( list.size() * 24 + 8 );
+    PCIDSKBuffer vbuf( static_cast<int>(list.size()) * 24 + 8 );
 
     AccessShapeByIndex( shape_index );
 
@@ -1313,7 +1350,7 @@ void CPCIDSKVectorSegment::SetVertices( ShapeId id,
 /*      Is the current space big enough to hold the new vertex set?     */
 /* -------------------------------------------------------------------- */
     uint32 vert_off = shape_index_vertex_off[shape_index - shape_index_start];
-    uint32 chunk_size;
+    uint32 chunk_size = 0;
 
     if( vert_off != 0xffffffff )
     {
@@ -1339,7 +1376,7 @@ void CPCIDSKVectorSegment::SetVertices( ShapeId id,
 /* -------------------------------------------------------------------- */
 /*      Format the vertices in a buffer.                                */
 /* -------------------------------------------------------------------- */
-    uint32 vert_count = list.size();
+    uint32 vert_count = static_cast<uint32>(list.size());
     unsigned int i;
 
     memcpy( vbuf.buffer, &chunk_size, 4 );
@@ -1387,14 +1424,14 @@ void CPCIDSKVectorSegment::SetFields( ShapeId id,
     const std::vector<ShapeField> *listp = NULL;
 
     if( shape_index == -1 )
-        ThrowPCIDSKException( "Attempt to call SetFields() on non-existing shape id '%d'.",
+        return ThrowPCIDSKException( "Attempt to call SetFields() on non-existing shape id '%d'.",
                               (int) id );
 
     if( list_in.size() > vh.field_names.size() )
     {
-        ThrowPCIDSKException( 
+        return ThrowPCIDSKException( 
             "Attempt to write %d fields to a layer with only %d fields.", 
-            list_in.size(), vh.field_names.size() );
+            static_cast<int>(list_in.size()), static_cast<int>(vh.field_names.size()) );
     }
 
     if( list_in.size() < vh.field_names.size() )
@@ -1402,7 +1439,7 @@ void CPCIDSKVectorSegment::SetFields( ShapeId id,
         full_list = list_in;
 
         // fill out missing fields in list with defaults.
-        for( i = list_in.size(); i < vh.field_names.size(); i++ )
+        for( i = static_cast<uint32>(list_in.size()); i < static_cast<uint32>(vh.field_names.size()); i++ )
             full_list[i] = vh.field_defaults[i];
         
         listp = &full_list;
@@ -1507,7 +1544,7 @@ void CPCIDSKVectorSegment::FlushLoadedShapeIndex()
     }
 
     if( needs_swap )
-        SwapData( write_buffer.buffer, 4, shape_index_ids.size() * 3 );
+        SwapData( write_buffer.buffer, 4, static_cast<int>(shape_index_ids.size()) * 3 );
 
     WriteToFile( write_buffer.buffer, 
                  offset + 4 + shape_index_start * 12, 
diff --git a/frmts/pcidsk/sdk/segment/cpcidskvectorsegment.h b/frmts/pcidsk/sdk/segment/cpcidskvectorsegment.h
index aeb6df7..2ce8ae2 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskvectorsegment.h
+++ b/frmts/pcidsk/sdk/segment/cpcidskvectorsegment.h
@@ -24,8 +24,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_SEGMENT_PCIDSKVECTORSEGMENT_H
-#define __INCLUDE_SEGMENT_PCIDSKVECTORSEGMENT_H
+#ifndef INCLUDE_SEGMENT_PCIDSKVECTORSEGMENT_H
+#define INCLUDE_SEGMENT_PCIDSKVECTORSEGMENT_H
 
 #include "pcidsk_config.h"
 #include "pcidsk_types.h"
diff --git a/frmts/pcidsk/sdk/segment/cpcidskvectorsegment_consistencycheck.cpp b/frmts/pcidsk/sdk/segment/cpcidskvectorsegment_consistencycheck.cpp
index f4f7c9c..feddea9 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskvectorsegment_consistencycheck.cpp
+++ b/frmts/pcidsk/sdk/segment/cpcidskvectorsegment_consistencycheck.cpp
@@ -36,10 +36,13 @@
 using namespace PCIDSK;
 
 /* -------------------------------------------------------------------- */
-/*      Size of a block in the record/vertice block tables.  This is    */
+/*      Size of a block in the record/vertex block tables.  This is    */
 /*      determined by the PCIDSK format and may not be changed.         */
 /* -------------------------------------------------------------------- */
-static const int block_page_size = 8192;  
+static const int block_page_size = 8192;
+#ifndef CPL_BASE_H_INCLUDED
+template<class T> static void CPL_IGNORE_RET_VAL(T) {}
+#endif
 
 /************************************************************************/
 /* ==================================================================== */
@@ -61,7 +64,7 @@ public:
             if( offsets.size() == 0 )
                 return 0;
 
-            uint32 start=0, end=offsets.size()-1;
+            uint32 start=0, end=static_cast<uint32>(offsets.size())-1;
 
             while( end > start )
             {
@@ -219,7 +222,7 @@ std::string CPCIDSKVectorSegment::ConsistencyCheck_DataIndices()
 
     SpaceMap smap;
 
-    smap.AddChunk( 0, vh.header_blocks );
+    CPL_IGNORE_RET_VAL(smap.AddChunk( 0, vh.header_blocks ));
 
     for( section = 0; section < 2; section++ )
     {
@@ -232,7 +235,8 @@ std::string CPCIDSKVectorSegment::ConsistencyCheck_DataIndices()
             {
                 char msg[100];
 
-                sprintf( msg, "Conflict for block %d, held by at least data index '%d'.\n",
+                snprintf( msg,  sizeof(msg),
+                          "Conflict for block %d, held by at least data index '%d'.\n",
                          (*map)[i], section );
 
                 report += msg;
@@ -270,7 +274,8 @@ std::string CPCIDSKVectorSegment::ConsistencyCheck_ShapeIndices()
         {
             char msg[100];
 
-            sprintf( msg, "ShapeID %d is used for shape %d and %d!\n", 
+            snprintf( msg, sizeof(msg),
+                      "ShapeID %d is used for shape %d and %d!\n", 
                      shape_index_ids[toff], 
                      toff, id_map[shape_index_ids[toff]]);
             report += msg;
diff --git a/frmts/pcidsk/sdk/segment/metadatasegment.h b/frmts/pcidsk/sdk/segment/metadatasegment.h
index a857a6d..3a47d07 100644
--- a/frmts/pcidsk/sdk/segment/metadatasegment.h
+++ b/frmts/pcidsk/sdk/segment/metadatasegment.h
@@ -30,8 +30,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
  
-#ifndef __INCLUDE_SEGMENT_METADATASEGMENT_H
-#define __INCLUDE_SEGMENT_METADATASEGMENT_H
+#ifndef INCLUDE_SEGMENT_METADATASEGMENT_H
+#define INCLUDE_SEGMENT_METADATASEGMENT_H
 
 #include "pcidsk_buffer.h"
 #include "segment/cpcidsksegment.h"
@@ -72,4 +72,4 @@ namespace PCIDSK
     };
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_SEGMENT_METADATASEGMENT_H
+#endif // INCLUDE_SEGMENT_METADATASEGMENT_H
diff --git a/frmts/pcidsk/sdk/segment/metadatasegment_p.cpp b/frmts/pcidsk/sdk/segment/metadatasegment_p.cpp
index a0d9012..cce31fa 100644
--- a/frmts/pcidsk/sdk/segment/metadatasegment_p.cpp
+++ b/frmts/pcidsk/sdk/segment/metadatasegment_p.cpp
@@ -43,9 +43,9 @@ using namespace PCIDSK;
 /*                          MetadataSegment()                           */
 /************************************************************************/
 
-MetadataSegment::MetadataSegment( PCIDSKFile *file, int segment,
+MetadataSegment::MetadataSegment( PCIDSKFile *fileIn, int segmentIn,
                                   const char *segment_pointer )
-        : CPCIDSKSegment( file, segment, segment_pointer )
+        : CPCIDSKSegment( fileIn, segmentIn, segment_pointer )
 
 {
     loaded = false;
@@ -109,9 +109,9 @@ void MetadataSegment::FetchGroupMetadata( const char *group, int id,
 /*      Establish the key prefix we are searching for.                  */
 /* -------------------------------------------------------------------- */
     char key_prefix[200];
-    int  prefix_len;
+    size_t  prefix_len;
 
-    std::sprintf( key_prefix, "METADATA_%s_%d_", group, id );
+    snprintf( key_prefix, sizeof(key_prefix), "METADATA_%s_%d_", group, id );
     prefix_len = std::strlen(key_prefix);
 
 /* -------------------------------------------------------------------- */
@@ -175,7 +175,7 @@ void MetadataSegment::SetGroupMetadataValue( const char *group, int id,
 
     char key_prefix[200];
 
-    std::sprintf( key_prefix, "METADATA_%s_%d_", group, id );
+    snprintf( key_prefix, sizeof(key_prefix), "METADATA_%s_%d_", group, id );
 
     std::string full_key;
 
@@ -190,7 +190,7 @@ void MetadataSegment::SetGroupMetadataValue( const char *group, int id,
 /*                                                                      */
 /*      When saving we first need to merge in any updates.  We put      */
 /*      this off since scanning and updating the metadata doc could     */
-/*      be epxensive if done for each item.                             */
+/*      be expensive if done for each item.                             */
 /************************************************************************/
 
 void MetadataSegment::Save()
@@ -219,7 +219,7 @@ void MetadataSegment::Save()
                 i_split = i;
         }
 
-        if( pszNext[i] == '\0' )
+        if( i_split < 0 || pszNext[i] == '\0' )
             break;
 
 /* -------------------------------------------------------------------- */
@@ -274,7 +274,7 @@ void MetadataSegment::Save()
                          '\0' );
     }
 
-    seg_data.SetSize( new_data.size() );
+    seg_data.SetSize( static_cast<int>(new_data.size()) );
     std::memcpy( seg_data.buffer, new_data.c_str(), new_data.size() );
 
     WriteToFile( seg_data.buffer, 0, seg_data.buffer_size );
diff --git a/frmts/pcidsk/sdk/segment/orbitstructures.h b/frmts/pcidsk/sdk/segment/orbitstructures.h
index 3bdf8ac..d75d439 100644
--- a/frmts/pcidsk/sdk/segment/orbitstructures.h
+++ b/frmts/pcidsk/sdk/segment/orbitstructures.h
@@ -24,10 +24,11 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PCIDSK_ORBIT_INFORMATION_H
-#define __INCLUDE_PCIDSK_ORBIT_INFORMATION_H
+#ifndef INCLUDE_PCIDSK_ORBIT_INFORMATION_H
+#define INCLUDE_PCIDSK_ORBIT_INFORMATION_H
 
 #include <string>
+#include <cstring>
 #include <vector>
 
 namespace PCIDSK
@@ -51,7 +52,15 @@ namespace PCIDSK
         /**
          * Default constrcutor
          */
-        AncillaryData_t()
+        AncillaryData_t() :
+            SlantRangeFstPixel(0),
+            SlantRangeLastPixel(0),
+            FstPixelLat(0.f),
+            MidPixelLat(0.f),
+            LstPixelLat(0.f),
+            FstPixelLong(0.f),
+            MidPixelLong(0.f),
+            LstPixelLong(0.f)
         {
         }
         /**
@@ -64,7 +73,7 @@ namespace PCIDSK
         }
 
         /**
-         * assignement operator
+         * assignment operator
          * @param oAD the ancillary data to assign
          */
         AncillaryData_t& operator=(const AncillaryData_t& oAD)
@@ -111,7 +120,15 @@ namespace PCIDSK
         /**
          * Default constrcutor
          */
-        RadarSeg_t()
+        RadarSeg_t() :
+            EquatorialRadius(0.0),
+            PolarRadius(0.0),
+            IncidenceAngle(0.0),
+            PixelSpacing(0.0),
+            LineSpacing(0.0),
+            ClockAngle(0.0),
+            NumberBlockData(0),
+            NumberData(0)
         {
         }
         /**
@@ -124,7 +141,7 @@ namespace PCIDSK
         }
 
         /**
-         * assignement operator
+         * assignment operator
          * @param oRS the radar segment to assign
          */
         RadarSeg_t& operator=(const RadarSeg_t& oRS)
@@ -190,7 +207,9 @@ namespace PCIDSK
         /**
          * Default constrcutor
          */
-        AttitudeLine_t()
+        AttitudeLine_t():
+            ChangeInAttitude(0.0),
+            ChangeEarthSatelliteDist(0.0)
         {
         }
         /**
@@ -203,7 +222,7 @@ namespace PCIDSK
         }
 
         /**
-         * assignement operator
+         * assignment operator
          * @param oAL the attitude line to assign
          */
         AttitudeLine_t& operator=(const AttitudeLine_t& oAL)
@@ -226,7 +245,7 @@ namespace PCIDSK
             ChangeEarthSatelliteDist = oAL.ChangeEarthSatelliteDist;
         }
 
-        double ChangeInAttitude; /* Change in satellite attiutde (D22.16) */
+        double ChangeInAttitude; /* Change in satellite attitude (D22.16) */
         double ChangeEarthSatelliteDist; /* Change in earth-satellite distance
                                          (D22.16) */
     } ;
@@ -239,7 +258,12 @@ namespace PCIDSK
         /**
          * Default constrcutor
          */
-        AttitudeSeg_t()
+        AttitudeSeg_t() :
+            Roll(0.0),
+            Pitch(0.0),
+            Yaw(0.0),
+            NumberOfLine(0),
+            NumberBlockData(0)
         {
         }
         /**
@@ -252,7 +276,7 @@ namespace PCIDSK
         }
 
         /**
-         * assignement operator
+         * assignment operator
          * @param oAS the avhrr segment to assign
          */
         AttitudeSeg_t& operator=(const AttitudeSeg_t& oAS)
@@ -305,6 +329,14 @@ namespace PCIDSK
          */
         AvhrrLine_t()
         {
+            nScanLineNum = 0;
+            nStartScanTimeGMTMsec = 0;
+            std::memset(abyScanLineQuality, 0, sizeof(abyScanLineQuality));
+            std::memset(aabyBadBandIndicators, 0, sizeof(aabyBadBandIndicators));
+            std::memset(abySatelliteTimeCode, 0, sizeof(abySatelliteTimeCode));
+            std::memset(anTargetTempData, 0, sizeof(anTargetTempData));
+            std::memset(anTargetScanData, 0, sizeof(anTargetScanData));
+            std::memset(anSpaceScanData, 0, sizeof(anSpaceScanData));
         }
         /**
          * Copy constructor
@@ -316,7 +348,7 @@ namespace PCIDSK
         }
 
         /**
-         * assignement operator
+         * assignment operator
          * @param oAL the avhrr line to assign
          */
         AvhrrLine_t& operator=(const AvhrrLine_t& oAL)
@@ -376,7 +408,16 @@ namespace PCIDSK
         /**
          * Default constrcutor
          */
-        AvhrrSeg_t()
+        AvhrrSeg_t() :
+            nImageXSize(0),
+            nImageYSize(0),
+            bIsAscending(false),
+            bIsImageRotated(false),
+            nRecordSize(0),
+            nBlockSize(0),
+            nNumRecordsPerBlock(0),
+            nNumBlocks(0),
+            nNumScanlineRecords(0)
         {
         }
         /**
@@ -389,7 +430,7 @@ namespace PCIDSK
         }
 
         /**
-         * assignement operator
+         * assignment operator
          * @param oAS the avhrr segment to assign
          */
         AvhrrSeg_t& operator=(const AvhrrSeg_t& oAS)
@@ -446,14 +487,14 @@ namespace PCIDSK
             Line = oAS.Line;
         }
 
-        /* Nineth Block Part 1 - General/header information */
+        /* Ninth Block Part 1 - General/header information */
         std::string  szImageFormat;
         int   nImageXSize;
         int   nImageYSize;
         bool bIsAscending;
         bool bIsImageRotated;
 
-        /* Nineth Block Part 2 - Ephemeris information */
+        /* Ninth Block Part 2 - Ephemeris information */
         std::string  szOrbitNumber;
         std::string  szAscendDescendNodeFlag;
         std::string  szEpochYearAndDay;
@@ -515,6 +556,74 @@ namespace PCIDSK
          */
         EphemerisSeg_t()
         {
+            SupSegExist = false;
+            FieldOfView = 0.0;
+            ViewAngle = 0.0;
+            NumColCentre = 0.0;
+            RadialSpeed = 0.0;
+            Eccentricity = 0.0;
+            Height = 0.0;
+            Inclination = 0.0;
+            TimeInterval = 0.0;
+            NumLineCentre = 0.0;
+            LongCentre = 0.0;
+            AngularSpd = 0.0;
+            AscNodeLong = 0.0; 
+            ArgPerigee = 0.0;
+            LatCentre = 0.0;
+            EarthSatelliteDist = 0.0;
+            NominalPitch = 0.0;
+            TimeAtCentre = 0.0;
+            SatelliteArg = 0.0;
+            XCentre = 0.0;
+            YCentre = 0.0;
+            UtmYCentre = 0.0;
+            UtmXCentre = 0.0;
+            PixelRes = 0.0;
+            LineRes = 0.0;
+            CornerAvail = false;
+            XUL = 0.0;
+            YUL = 0.0;
+            XUR = 0.0;
+            YUR = 0.0;
+            XLR = 0.0;
+            YLR = 0.0;
+            XLL = 0.0;
+            YLL = 0.0;
+            UtmYUL = 0.0;
+            UtmXUL = 0.0;
+            UtmYUR = 0.0;
+            UtmXUR = 0.0;
+            UtmYLR = 0.0;
+            UtmXLR = 0.0;
+            UtmYLL = 0.0;
+            UtmXLL = 0.0;
+            LatCentreDeg = 0.0;
+            LongCentreDeg = 0.0;
+            LatUL = 0.0;
+            LongUL = 0.0;
+            LatUR = 0.0;
+            LongUR = 0.0;
+            LatLR = 0.0;
+            LongLR = 0.0;
+            LatLL = 0.0;
+            LongLL = 0.0;
+            HtCentre = 0.0;
+            HtUL = 0.0;
+            HtUR = 0.0;
+            HtLR = 0.0;
+            HtLL = 0.0;
+            std::memset(SPCoeff1B, 0, sizeof(SPCoeff1B));
+            std::memset(SPCoeffSg, 0, sizeof(SPCoeffSg));
+            ImageRecordLength = 0;
+            NumberImageLine = 0;
+            NumberBytePerPixel = 0;
+            NumberSamplePerLine = 0;
+            NumberPrefixBytes = 0;
+            NumberSuffixBytes = 0;
+            SPNCoeff = 0;
+            bDescending = false;
+            Type = OrbNone;
             AttitudeSeg = NULL;
             RadarSeg = NULL;
             AvhrrSeg = NULL;
@@ -543,7 +652,7 @@ namespace PCIDSK
         }
 
         /**
-         * assignement operator
+         * assignment operator
          * @param oES the ephemeris segment to assign
          */
         EphemerisSeg_t& operator=(const EphemerisSeg_t& oES)
@@ -842,4 +951,4 @@ namespace PCIDSK
 		HJ_CCD_1A, HJ_CCD_1B, NEW, AVHRR} TypeDeCapteur;
 }
 
-#endif // __INCLUDE_PCIDSK_ORBIT_INFORMATION_H
+#endif // INCLUDE_PCIDSK_ORBIT_INFORMATION_H
diff --git a/frmts/pcidsk/sdk/segment/pcidsksegmentbuilder.h b/frmts/pcidsk/sdk/segment/pcidsksegmentbuilder.h
index 360e9c7..6bf8fcf 100644
--- a/frmts/pcidsk/sdk/segment/pcidsksegmentbuilder.h
+++ b/frmts/pcidsk/sdk/segment/pcidsksegmentbuilder.h
@@ -26,8 +26,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
  
-#ifndef __INCLUDE_SEGMENT_PCIDSKSEGMENTBUILDER_H
-#define __INCLUDE_SEGMENT_PCIDSKSEGMENTBUILDER_H
+#ifndef INCLUDE_SEGMENT_PCIDSKSEGMENTBUILDER_H
+#define INCLUDE_SEGMENT_PCIDSKSEGMENTBUILDER_H
 
 namespace PCIDSK
 {
@@ -36,7 +36,7 @@ namespace PCIDSK
 
     /**
      * PCIDSK Abstract Builder class. Given a segment pointer, constructs
-     * an instance of a given PCIDSKSegment implementor. Typically an instance
+     * an instance of a given PCIDSKSegment implementer. Typically an instance
      * of this will be registered with the PCIDSK Segment Factory.
      */
     struct IPCIDSKSegmentBuilder
@@ -60,4 +60,4 @@ namespace PCIDSK
 
 }; // end namespace PCIDSK
 
-#endif // __INCLUDE_SEGMENT_PCIDSKSEGMENTBUILDER_H
+#endif // INCLUDE_SEGMENT_PCIDSKSEGMENTBUILDER_H
diff --git a/frmts/pcidsk/sdk/segment/sysblockmap.cpp b/frmts/pcidsk/sdk/segment/sysblockmap.cpp
index 9fa1b43..78f19b3 100644
--- a/frmts/pcidsk/sdk/segment/sysblockmap.cpp
+++ b/frmts/pcidsk/sdk/segment/sysblockmap.cpp
@@ -38,11 +38,13 @@
 #include "core/sysvirtualfile.h"
 #include "segment/sysblockmap.h"
 #include "core/cpcidskfile.h"
+#include "core/pcidsk_utils.h"
 
 #include <cassert>
 #include <vector>
 #include <cstring>
 #include <cstdlib>
+#include <cstdio>
 
 using namespace PCIDSK;
 
@@ -50,15 +52,17 @@ using namespace PCIDSK;
 /*                            SysBlockMap()                             */
 /************************************************************************/
 
-SysBlockMap::SysBlockMap( PCIDSKFile *file, int segment,
+SysBlockMap::SysBlockMap( PCIDSKFile *fileIn, int segmentIn,
                               const char *segment_pointer )
-        : CPCIDSKSegment( file, segment, segment_pointer )
+        : CPCIDSKSegment( fileIn, segmentIn, segment_pointer )
 
 {
     partial_loaded = false;
     full_loaded = false;
     dirty = false;
     growing_segment = 0;
+    block_count = 0;
+    first_free_block = 0;
 }
 
 /************************************************************************/
@@ -76,7 +80,15 @@ SysBlockMap::~SysBlockMap()
         virtual_files[i] = NULL;
     }
 
-    Synchronize();
+    try
+    {
+        Synchronize();
+    }
+    catch( const PCIDSKException& e )
+    {
+        fprintf(stderr, "Exception in SysBlockMap::~SysBlockMap(): %s\n",
+                e.what());
+    }
 }
 
 /************************************************************************/
@@ -127,11 +139,11 @@ void SysBlockMap::PartialLoad()
     count_data.SetSize( 512 );
     ReadFromFile( count_data.buffer, 0, 512 );
 
-    if( strncmp(count_data.buffer,"VERSION",7) != 0 )
-        ThrowPCIDSKException( "SysBlockMap::PartialLoad() - block map corrupt." );
+    if( !STARTS_WITH(count_data.buffer, "VERSION") )
+        return ThrowPCIDSKException( "SysBlockMap::PartialLoad() - block map corrupt." );
 
     if( count_data.GetInt( 7, 3 ) != 1 )
-        ThrowPCIDSKException( "SysBlockMap::PartialLoad() - unsupported version." );
+        return ThrowPCIDSKException( "SysBlockMap::PartialLoad() - unsupported version." );
 
 /* -------------------------------------------------------------------- */
 /*      Establish our SysVirtualFile array based on the number of       */
@@ -238,14 +250,14 @@ void SysBlockMap::AllocateBlocks()
 
     if( growing_segment == 0 )
     {
-        PCIDSKSegment *seg;
+        PCIDSKSegment *l_seg;
         int  previous = 0;
 
-        while( (seg=file->GetSegment( SEG_SYS, "SysBData", previous )) != NULL )
+        while( (l_seg=file->GetSegment( SEG_SYS, "SysBData", previous )) != NULL )
         {
-            previous = seg->GetSegmentNumber();
+            previous = l_seg->GetSegmentNumber();
             
-            if( seg->IsAtEOF() )
+            if( l_seg->IsAtEOF() )
             {
                 growing_segment = previous;
                 break;
@@ -381,7 +393,7 @@ SysVirtualFile *SysBlockMap::GetVirtualFile( int image )
     PartialLoad();
 
     if( image < 0 || image >= (int) virtual_files.size() )
-        ThrowPCIDSKException( "GetImageSysFile(%d): invalid image index",
+        return (SysVirtualFile*)ThrowPCIDSKExceptionPtr( "GetImageSysFile(%d): invalid image index",
                               image );
 
     if( virtual_files[image] != NULL )
@@ -425,7 +437,7 @@ int SysBlockMap::CreateVirtualFile()
 /* -------------------------------------------------------------------- */
     if( layer_index == virtual_files.size() )
     {
-        layer_index = virtual_files.size();
+        layer_index = static_cast<int>(virtual_files.size());
         layer_data.SetSize( (layer_index+1) * 24 );
         virtual_files.push_back( NULL );
     }
@@ -508,7 +520,7 @@ int SysBlockMap::CreateVirtualImageFile( int width, int height,
 /************************************************************************/
 
 int SysBlockMap::GetNextBlockMapEntry( int bm_index,
-                                       uint16 &segment,
+                                       uint16 &segmentOut,
                                        int &block_in_segment )
 
 {
@@ -545,7 +557,7 @@ int SysBlockMap::GetNextBlockMapEntry( int bm_index,
     block_in_segment = atoi(bm_entry+4);
 
     bm_entry[4] = '\0';
-    segment = atoi(bm_entry);
+    segmentOut = static_cast<PCIDSK::uint16>(atoi(bm_entry));
     
     return next_block;
 }
diff --git a/frmts/pcidsk/sdk/segment/sysblockmap.h b/frmts/pcidsk/sdk/segment/sysblockmap.h
index 3a9ec97..b7c08b5 100644
--- a/frmts/pcidsk/sdk/segment/sysblockmap.h
+++ b/frmts/pcidsk/sdk/segment/sysblockmap.h
@@ -32,8 +32,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_SEGMENT_SYSBLOCKMAP_H
-#define __INCLUDE_SEGMENT_SYSBLOCKMAP_H
+#ifndef INCLUDE_SEGMENT_SYSBLOCKMAP_H
+#define INCLUDE_SEGMENT_SYSBLOCKMAP_H
 
 #include "pcidsk_config.h"
 #include "pcidsk_types.h"
@@ -94,4 +94,4 @@ namespace PCIDSK
     };
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_SEGMENT_SYSBLOCKMAP_H
+#endif // INCLUDE_SEGMENT_SYSBLOCKMAP_H
diff --git a/frmts/pcidsk/sdk/segment/toutinstructures.h b/frmts/pcidsk/sdk/segment/toutinstructures.h
index 35778a9..099a274 100644
--- a/frmts/pcidsk/sdk/segment/toutinstructures.h
+++ b/frmts/pcidsk/sdk/segment/toutinstructures.h
@@ -24,9 +24,10 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_PCIDSK_TOUTIN_INFORMATION_H
-#define __INCLUDE_PCIDSK_TOUTIN_INFORMATION_H
+#ifndef INCLUDE_PCIDSK_TOUTIN_INFORMATION_H
+#define INCLUDE_PCIDSK_TOUTIN_INFORMATION_H
 
+#include <cstring>
 #include "segment/orbitstructures.h"
 
 namespace PCIDSK
@@ -59,6 +60,44 @@ namespace PCIDSK
          */
         SRITInfo_t()
         {
+            N0x2 = 0.0;
+            aa = 0.0;
+            SmALPHA = 0.0;
+            bb = 0.0;
+            C0 = 0.0;
+            cc = 0.0;
+            COS_KHI = 0.0;
+            DELTA_GAMMA = 0.0;
+            GAMMA = 0.0;
+            K_1 = 0.0;
+            L0 = 0.0;
+            P = 0.0;
+            Q = 0.0;
+            TAU = 0.0;
+            THETA = 0.0;
+            THETA_SEC = 0.0;
+            X0 = 0.0;
+            Y0 = 0.0;
+            delh = 0.0;
+            COEF_Y2 = 0.0;
+            delT = 0.0;
+            delL = 0.0;
+            delTau = 0.0;
+            nDownSample = 0;
+            nGCPCount = 0;
+            nEphemerisSegNo = 0;
+            nAttitudeFlag = 0;
+            GCPMeanHtFlag = 0;
+            dfGCPMeanHt = 0.0;
+            dfGCPMinHt = 0.0;
+            dfGCPMaxHt = 0.0;
+            std::memset(nGCPIds, 0, sizeof(nGCPIds));
+            std::memset(nPixel, 0, sizeof(nPixel));
+            std::memset(nLine, 0, sizeof(nLine));
+            std::memset(dfElev, 0, sizeof(dfElev));
+            nSensor = 0;
+            nModel = 0;
+            RawToGeo = false;
             OrbitPtr = NULL;
         }
         /**
@@ -203,4 +242,4 @@ namespace PCIDSK
     } ;
 }
 
-#endif // __INCLUDE_PCIDSK_TOUTIN_INFORMATION_H
+#endif // INCLUDE_PCIDSK_TOUTIN_INFORMATION_H
diff --git a/frmts/pcidsk/sdk/segment/vecsegdataindex.cpp b/frmts/pcidsk/sdk/segment/vecsegdataindex.cpp
index c07a78a..473631a 100644
--- a/frmts/pcidsk/sdk/segment/vecsegdataindex.cpp
+++ b/frmts/pcidsk/sdk/segment/vecsegdataindex.cpp
@@ -40,10 +40,10 @@
 using namespace PCIDSK;
 
 /* -------------------------------------------------------------------- */
-/*      Size of a block in the record/vertice block tables.  This is    */
+/*      Size of a block in the record/vertex block tables.  This is    */
 /*      determined by the PCIDSK format and may not be changed.         */
 /* -------------------------------------------------------------------- */
-static const int block_page_size = 8192;  
+static const int block_page_size = 8192;
 
 /************************************************************************/
 /*                          VecSegDataIndex()                           */
@@ -55,6 +55,11 @@ VecSegDataIndex::VecSegDataIndex()
     block_initialized = false;
     vs = NULL;
     dirty = false;
+    section = 0;
+    offset_on_disk_within_section = 0;
+    size_on_disk = 0;
+    block_count = 0;
+    bytes = 0;
 }
 
 /************************************************************************/
@@ -70,11 +75,11 @@ VecSegDataIndex::~VecSegDataIndex()
 /*                             Initialize()                             */
 /************************************************************************/
 
-void VecSegDataIndex::Initialize( CPCIDSKVectorSegment *vs, int section )
+void VecSegDataIndex::Initialize( CPCIDSKVectorSegment *vsIn, int sectionIn )
 
 {
-    this->section = section;
-    this->vs = vs;
+    this->section = sectionIn;
+    this->vs = vsIn;
 
     if( section == sec_vert )
         offset_on_disk_within_section = 0;
@@ -122,7 +127,15 @@ const std::vector<uint32> *VecSegDataIndex::GetIndex()
     {
         bool needs_swap = !BigEndianSystem();
 
-        block_index.resize( block_count );
+        try
+        {
+            block_index.resize( block_count );
+        }
+        catch( const std::bad_alloc& ex )
+        {
+            throw PCIDSKException("Out of memory allocating block_index(%u): %s",
+                                  block_count, ex.what());
+        }
         if( block_count > 0 )
         {
             vs->ReadFromFile( &(block_index[0]), 
diff --git a/frmts/pcidsk/sdk/segment/vecsegdataindex.h b/frmts/pcidsk/sdk/segment/vecsegdataindex.h
index aa22217..32f0934 100644
--- a/frmts/pcidsk/sdk/segment/vecsegdataindex.h
+++ b/frmts/pcidsk/sdk/segment/vecsegdataindex.h
@@ -30,8 +30,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef __INCLUDE_SEGMENT_VECSEGDATAINDEX_H
-#define __INCLUDE_SEGMENT_VECSEGDATAINDEX_H
+#ifndef INCLUDE_SEGMENT_VECSEGDATAINDEX_H
+#define INCLUDE_SEGMENT_VECSEGDATAINDEX_H
 
 #include "pcidsk_config.h"
 #include "pcidsk_types.h"
@@ -82,4 +82,4 @@ namespace PCIDSK
     };
 } // end namespace PCIDSK
 
-#endif // __INCLUDE_SEGMENT_VECSEGDATAINDEX_H
+#endif // INCLUDE_SEGMENT_VECSEGDATAINDEX_H
diff --git a/frmts/pcidsk/sdk/segment/vecsegheader.cpp b/frmts/pcidsk/sdk/segment/vecsegheader.cpp
index f27e576..5086859 100644
--- a/frmts/pcidsk/sdk/segment/vecsegheader.cpp
+++ b/frmts/pcidsk/sdk/segment/vecsegheader.cpp
@@ -36,14 +36,15 @@
 #include <cassert>
 #include <cstring>
 #include <cstdio>
+#include <limits>
 
 using namespace PCIDSK;
 
 /* -------------------------------------------------------------------- */
-/*      Size of a block in the record/vertice block tables.  This is    */
+/*      Size of a block in the record/vertex block tables.  This is    */
 /*      determined by the PCIDSK format and may not be changed.         */
 /* -------------------------------------------------------------------- */
-static const int block_page_size = 8192;  
+static const int block_page_size = 8192;
 
 /************************************************************************/
 /*                            VecSegHeader()                            */
@@ -55,6 +56,7 @@ VecSegHeader::VecSegHeader()
     vs = NULL;
     initialized = false;
     needs_swap = !BigEndianSystem();
+    header_blocks = 0;
 }
 
 /************************************************************************/
@@ -166,7 +168,7 @@ void VecSegHeader::InitializeExisting()
 
     if( memcmp( vs->GetData( sec_raw, 0, NULL, 24 ), magic, 24 ) != 0 )
     {
-        ThrowPCIDSKException( "Unexpected vector header values, possibly it is not a V6 vector segment?" );
+        return ThrowPCIDSKException( "Unexpected vector header values, possibly it is not a V6 vector segment?" );
     }
     
 /* -------------------------------------------------------------------- */
@@ -219,7 +221,10 @@ void VecSegHeader::InitializeExisting()
         field_descriptions.push_back( work_value.GetValueString() );
         
         next_off = vs->ReadField( next_off, work_value, FieldTypeInteger, sec_raw );
-        field_types.push_back( (ShapeFieldType) work_value.GetValueInteger() );
+        int field_type = work_value.GetValueInteger();
+        if( field_type < 0 || field_type > FieldTypeCountedInt )
+            return ThrowPCIDSKException( "Invalid field type: %d", field_type );
+        field_types.push_back( static_cast<ShapeFieldType> (field_type) );
         
         next_off = vs->ReadField( next_off, work_value, FieldTypeString, sec_raw );
         field_formats.push_back( work_value.GetValueString() );
@@ -250,12 +255,18 @@ void VecSegHeader::InitializeExisting()
     memcpy( &(vs->shape_count), vs->GetData(sec_raw,next_off,NULL,4), 4);
     if( needs_swap )
         SwapData( &(vs->shape_count), 4, 1 );
+    if( vs->shape_count < 0 )
+        return ThrowPCIDSKException( "Invalid shape_count: %d", vs->shape_count );
 
     next_off += 4;
     vs->shape_index_start = 0;
 
-    section_sizes[hsec_shape] = next_off - section_offsets[hsec_shape] 
-        + vs->shape_count * 12;
+    uint64 section_size = next_off - section_offsets[hsec_shape] 
+        + static_cast<uint64>(vs->shape_count) * 12;
+    if( section_size > std::numeric_limits<uint32>::max() )
+        return ThrowPCIDSKException( "Invalid section_size" );
+        
+    section_sizes[hsec_shape] = static_cast<uint32>(section_size);
 }
 
 /************************************************************************/
diff --git a/frmts/pcidsk/sdk/segment/vecsegheader.h b/frmts/pcidsk/sdk/segment/vecsegheader.h
index 509365c..ddcbf88 100644
--- a/frmts/pcidsk/sdk/segment/vecsegheader.h
+++ b/frmts/pcidsk/sdk/segment/vecsegheader.h
@@ -28,8 +28,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#ifndef __INCLUDE_SEGMENT_VECSEGHEADER_H
-#define __INCLUDE_SEGMENT_VECSEGHEADER_H
+#ifndef INCLUDE_SEGMENT_VECSEGHEADER_H
+#define INCLUDE_SEGMENT_VECSEGHEADER_H
 
 #include "pcidsk_config.h"
 #include "pcidsk_types.h"
diff --git a/frmts/pcidsk/vsi_pcidsk_io.cpp b/frmts/pcidsk/vsi_pcidsk_io.cpp
index 397ae98..d8f22c7 100644
--- a/frmts/pcidsk/vsi_pcidsk_io.cpp
+++ b/frmts/pcidsk/vsi_pcidsk_io.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: vsi_pcidsk_io.cpp 28459 2015-02-12 13:48:21Z rouault $
+ * $Id: vsi_pcidsk_io.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  PCIDSK Database File
- * Purpose:  PCIDSK SDK compatiable io interface built on VSI.
+ * Purpose:  PCIDSK SDK compatible IO interface built on VSI.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -32,11 +32,15 @@
 #include "cpl_multiproc.h"
 #include "pcidsk.h"
 
-CPL_CVSID("$Id: vsi_pcidsk_io.cpp 28459 2015-02-12 13:48:21Z rouault $");
+using PCIDSK::IOInterfaces;
+using PCIDSK::PCIDSKInterfaces;
+using PCIDSK::ThrowPCIDSKException;
+using PCIDSK::uint64;
 
-using namespace PCIDSK;
+CPL_CVSID("$Id: vsi_pcidsk_io.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
-EDBFile *GDAL_EDBOpen( std::string osFilename, std::string osAccess );
+PCIDSK::EDBFile *GDAL_EDBOpen( std::string osFilename, std::string osAccess );
+const PCIDSK::PCIDSKInterfaces *PCIDSK2GetInterfaces();
 
 class VSI_IOInterface : public IOInterfaces
 {
@@ -78,7 +82,7 @@ VSI_IOInterface::Open( std::string filename, std::string access ) const
     VSILFILE *fp = VSIFOpenL( filename.c_str(), access.c_str() );
 
     if( fp == NULL )
-        ThrowPCIDSKException( "Failed to open %s: %s", 
+        ThrowPCIDSKException( "Failed to open %s: %s",
                               filename.c_str(), LastError() );
 
     return fp;
@@ -88,17 +92,17 @@ VSI_IOInterface::Open( std::string filename, std::string access ) const
 /*                                Seek()                                */
 /************************************************************************/
 
-uint64 
+uint64
 VSI_IOInterface::Seek( void *io_handle, uint64 offset, int whence ) const
 
 {
-    VSILFILE *fp = (VSILFILE *) io_handle;
+    VSILFILE *fp = reinterpret_cast<VSILFILE *>( io_handle );
 
     uint64 result = VSIFSeekL( fp, offset, whence );
 
-    if( result == (uint64) -1 )
-        ThrowPCIDSKException( "Seek(%d,%d): %s", 
-                              (int) offset, whence, 
+    if( result == static_cast<uint64>( -1 ) )
+        ThrowPCIDSKException( "Seek(%d,%d): %s",
+                              static_cast<int>( offset ), whence,
                               LastError() );
 
     return result;
@@ -111,7 +115,7 @@ VSI_IOInterface::Seek( void *io_handle, uint64 offset, int whence ) const
 uint64 VSI_IOInterface::Tell( void *io_handle ) const
 
 {
-    VSILFILE *fp = (VSILFILE *) io_handle;
+    VSILFILE *fp = reinterpret_cast<VSILFILE *>( io_handle );
 
     return VSIFTellL( fp );
 }
@@ -120,19 +124,19 @@ uint64 VSI_IOInterface::Tell( void *io_handle ) const
 /*                                Read()                                */
 /************************************************************************/
 
-uint64 VSI_IOInterface::Read( void *buffer, uint64 size, uint64 nmemb, 
+uint64 VSI_IOInterface::Read( void *buffer, uint64 size, uint64 nmemb,
                                void *io_handle ) const
 
 {
-    VSILFILE *fp = (VSILFILE *) io_handle;
+    VSILFILE *fp = reinterpret_cast<VSILFILE *>( io_handle );
 
     errno = 0;
 
     uint64 result = VSIFReadL( buffer, (size_t) size, (size_t) nmemb, fp );
 
     if( errno != 0 && result == 0 && nmemb != 0 )
-        ThrowPCIDSKException( "Read(%d): %s", 
-                              (int) size * nmemb,
+        ThrowPCIDSKException( "Read(%d): %s",
+                              static_cast<int>( size * nmemb ),
                               LastError() );
 
     return result;
@@ -142,19 +146,20 @@ uint64 VSI_IOInterface::Read( void *buffer, uint64 size, uint64 nmemb,
 /*                               Write()                                */
 /************************************************************************/
 
-uint64 VSI_IOInterface::Write( const void *buffer, uint64 size, uint64 nmemb, 
+uint64 VSI_IOInterface::Write( const void *buffer, uint64 size, uint64 nmemb,
                                 void *io_handle ) const
 
 {
-    VSILFILE *fp = (VSILFILE *) io_handle;
+    VSILFILE *fp = reinterpret_cast<VSILFILE *>( io_handle );
 
     errno = 0;
 
-    uint64 result = VSIFWriteL( buffer, (size_t) size, (size_t) nmemb, fp );
+    uint64 result = VSIFWriteL( buffer, static_cast<size_t>( size ),
+                                static_cast<size_t>( nmemb ), fp );
 
     if( errno != 0 && result == 0 && nmemb != 0 )
-        ThrowPCIDSKException( "Write(%d): %s", 
-                              (int) size * nmemb,
+        ThrowPCIDSKException( "Write(%d): %s",
+                              static_cast<int>( size * nmemb ),
                               LastError() );
 
     return result;
@@ -167,7 +172,7 @@ uint64 VSI_IOInterface::Write( const void *buffer, uint64 size, uint64 nmemb,
 int VSI_IOInterface::Eof( void *io_handle ) const
 
 {
-    return VSIFEofL( (VSILFILE *) io_handle );
+    return VSIFEofL( reinterpret_cast<VSILFILE *>( io_handle ) );
 }
 
 /************************************************************************/
@@ -177,7 +182,7 @@ int VSI_IOInterface::Eof( void *io_handle ) const
 int VSI_IOInterface::Flush( void *io_handle ) const
 
 {
-    return VSIFFlushL( (VSILFILE *) io_handle );
+    return VSIFFlushL( reinterpret_cast<VSILFILE *>( io_handle ) );
 }
 
 /************************************************************************/
@@ -187,7 +192,7 @@ int VSI_IOInterface::Flush( void *io_handle ) const
 int VSI_IOInterface::Close( void *io_handle ) const
 
 {
-    return VSIFCloseL( (VSILFILE *) io_handle );
+    return VSIFCloseL( reinterpret_cast<VSILFILE *>( io_handle ) );
 }
 
 /************************************************************************/
diff --git a/frmts/pcraster/libcsf/_gsomece.c b/frmts/pcraster/libcsf/_gsomece.c
index a9779b6..84e293a 100644
--- a/frmts/pcraster/libcsf/_gsomece.c
+++ b/frmts/pcraster/libcsf/_gsomece.c
@@ -27,7 +27,8 @@ size_t RgetSomeCells(
 
 	offset <<= LOG_CELLSIZE(inFileCR);
 	readAt = ADDR_DATA + (CSF_FADDR)offset;
-	fseek(map->fp, (long)readAt, SEEK_SET);
+	if( fseek(map->fp, (long)readAt, SEEK_SET) != 0 )
+            return 0;
 	cellsRead = map->read(buf, (size_t)CELLSIZE(inFileCR),
 	(size_t)nrCells, map->fp);
 
diff --git a/frmts/pcraster/libcsf/attrsize.c b/frmts/pcraster/libcsf/attrsize.c
index a707a6d..b8363f9 100644
--- a/frmts/pcraster/libcsf/attrsize.c
+++ b/frmts/pcraster/libcsf/attrsize.c
@@ -11,6 +11,7 @@ size_t CsfAttributeSize(
 	 CSF_ATTR_ID id)    /* identification of attribute */
 {
 	ATTR_CNTRL_BLOCK b;
+        memset(&b, 0, sizeof(b));
 
 	if (CsfGetAttrBlock(m, id, &b) != 0)
 		return b.attrs[CsfGetAttrIndex(id, &b)].attrSize;
diff --git a/frmts/pcraster/libcsf/create2.c b/frmts/pcraster/libcsf/create2.c
index a2017f1..abc47bd 100644
--- a/frmts/pcraster/libcsf/create2.c
+++ b/frmts/pcraster/libcsf/create2.c
@@ -170,8 +170,8 @@ MAP *Rcreate(
 	CsfSetVarTypeMV( &(newMap->raster.maxVal), cellRepr);
 	newMap->raster.xUL = xUL;
 	newMap->raster.yUL = yUL;
-	newMap->raster.nrRows = nrRows;
-	newMap->raster.nrCols = nrCols;
+	newMap->raster.nrRows = (UINT4)nrRows;
+	newMap->raster.nrCols = (UINT4)nrCols;
 	newMap->raster.cellSize = cellSize;
 	newMap->raster.cellSizeDupl = cellSize;
 	newMap->raster.angle = angle;
diff --git a/frmts/pcraster/libcsf/csfsup.c b/frmts/pcraster/libcsf/csfsup.c
index 0276e63..16da8b2 100644
--- a/frmts/pcraster/libcsf/csfsup.c
+++ b/frmts/pcraster/libcsf/csfsup.c
@@ -10,15 +10,15 @@ void SetMemMV(
 	size_t nrElements,      /* number of cells */
 	CSF_CR cellRepr)         /* cell representation */
 {
-size_t index;
+size_t i;
 
 	switch (cellRepr) {
-	  case CR_INT1: (void)memset(buf,MV_INT1,nrElements);break;
-	  case CR_INT2: for (index=0;index<nrElements;index++)
-					 ((INT2 *) buf)[index]=MV_INT2;
+	  case CR_INT1: (void)memset(buf,MV_INT1+256,nrElements);break;
+	  case CR_INT2: for (i=0;i<nrElements;i++)
+					 ((INT2 *) buf)[i]=MV_INT2;
 			break;
-	  case CR_INT4: for (index=0;index<nrElements;index++)
-					 ((INT4 *) buf)[index]=MV_INT4;
+	  case CR_INT4: for (i=0;i<nrElements;i++)
+					 ((INT4 *) buf)[i]=MV_INT4;
 			break;
 	  default: (void)memset(buf,MV_UINT1,CSFSIZEOF(nrElements,cellRepr));
 	}
diff --git a/frmts/pcraster/libcsf/csftypes.h b/frmts/pcraster/libcsf/csftypes.h
index db72e4c..483a31b 100644
--- a/frmts/pcraster/libcsf/csftypes.h
+++ b/frmts/pcraster/libcsf/csftypes.h
@@ -198,7 +198,7 @@ typedef double              REAL8; /* IEEE-754 64-bit */
                             */
 #define PT_UTM 1  /* Universal Transverse Mercator (= PT_YDECT2B)
                             */
-#define PT_LATLON 2  /* Lattitude / Longitude (= PT_YDECT2B)
+#define PT_LATLON 2  /* Latitude / Longitude (= PT_YDECT2B)
                             */
 #define PT_CART        3  /* Carthesian (= PT_YDECT2B)
                             */
diff --git a/frmts/pcraster/libcsf/delattr.c b/frmts/pcraster/libcsf/delattr.c
index 840262c..71727f5 100644
--- a/frmts/pcraster/libcsf/delattr.c
+++ b/frmts/pcraster/libcsf/delattr.c
@@ -5,7 +5,7 @@
  * MdelAttribute deletes an attribute
  * from a map, if the attribute is available.
  * returns
- * the id argument if the attribute is succesfully deleted,
+ * the id argument if the attribute is successfully deleted,
  * or 0 in case of error or if the attribute is not found.
  *
  * Merrno
diff --git a/frmts/pcraster/libcsf/getattr.c b/frmts/pcraster/libcsf/getattr.c
index fd6246f..9e99b04 100644
--- a/frmts/pcraster/libcsf/getattr.c
+++ b/frmts/pcraster/libcsf/getattr.c
@@ -5,7 +5,7 @@
  * MgetAttribute reads an attribute if it is available.
  * Be aware that you can't pass a simple pointer to some 
  * (array of) structure(s) due to allignment en endian problems.
- * At some time there will be a seperate get function for each attribute
+ * At some time there will be a separate get function for each attribute
  * returns 0 if the attribute is not found, arg id if
  * the attribute is found.
  */
@@ -13,7 +13,7 @@ CSF_ATTR_ID CsfGetAttribute(
 	 MAP *m, /* map handle */
 	 CSF_ATTR_ID id, /* id of attribute to be read */
 	 size_t  elSize, /* size of each data-element */
-	 size_t *nmemb, /* write-only. how many elSize mebers are read */
+	 size_t *nmemb, /* write-only. How many elSize members are read. */
 	 void  *attr) /* write-only. buffer where attribute is read in.
 	               * Must be big enough to hold buffer.
 	               */
diff --git a/frmts/pcraster/libcsf/kernlcsf.c b/frmts/pcraster/libcsf/kernlcsf.c
index 3d3fe8e..481d423 100644
--- a/frmts/pcraster/libcsf/kernlcsf.c
+++ b/frmts/pcraster/libcsf/kernlcsf.c
@@ -94,7 +94,8 @@ void CsfRegisterMap(
   {
     size_t j;
     /* double size */
-    mapListLen *=2;
+    /* +1 to make clang static analyzer not warn about realloc(0) */
+    mapListLen = 2 * mapListLen + 1;
     mapList=realloc(mapList,sizeof(MAP *)*mapListLen);
     if (mapList == NULL) {
      (void)fprintf(stderr,"CSF_INTERNAL_ERROR: Not enough memory to use CSF-files\n");
@@ -106,7 +107,7 @@ void CsfRegisterMap(
   }
 
   mapList[i] =   m;
-  m->mapListId = i;
+  m->mapListId = (int)i;
 }
 
 /* remove map from run time structure (LIBRARY_INTERNAL)
diff --git a/frmts/pcraster/libcsf/legend.c b/frmts/pcraster/libcsf/legend.c
index 3f3e336..b95a6b6 100644
--- a/frmts/pcraster/libcsf/legend.c
+++ b/frmts/pcraster/libcsf/legend.c
@@ -6,7 +6,7 @@
  */
 static int NrLegendEntries(MAP *m)
 {
-	int size = CsfAttributeSize(m, ATTR_ID_LEGEND_V2);
+	int size = (int)CsfAttributeSize(m, ATTR_ID_LEGEND_V2);
 	if (size == 0)
 	{
 		if ( (size = -(int)CsfAttributeSize(m, ATTR_ID_LEGEND_V1)) != 0 )
@@ -66,7 +66,8 @@ int MgetLegend(
 	size_t i,nr,start = 0;
         if (pos == 0)
         	return 0;
-        fseek(m->fp, (long)pos, SEEK_SET);
+        if( fseek(m->fp, (long)pos, SEEK_SET) != 0 )
+                return 0;
         if (id == ATTR_ID_LEGEND_V1)
         { 
         	/* empty name */
diff --git a/frmts/pcraster/libcsf/mclose.c b/frmts/pcraster/libcsf/mclose.c
index e1dcef1..228e18b 100644
--- a/frmts/pcraster/libcsf/mclose.c
+++ b/frmts/pcraster/libcsf/mclose.c
@@ -7,7 +7,7 @@
  * the Mclose function closes a map
  * if the map is being used for output 
  * all header data is rewritten first
- * returns Upon succesful completion 0 is returned. 
+ * returns Upon successful completion 0 is returned.
  * Otherwise, a non-zero value is returned
  *
  * Merrno
@@ -37,8 +37,8 @@ int Mclose(
      CsfSwap((void*)&(m->raster.maxVal), CELLSIZE(m->raster.cellRepr),(size_t)1);
     }
 
-    fseek(m->fp,(long)ADDR_MAIN_HEADER,SEEK_SET);
-    if(m->write((void*)&(m->main.signature),sizeof(char), CSF_SIG_SPACE,m->fp)
+    if(fseek(m->fp,(long)ADDR_MAIN_HEADER,SEEK_SET) != 0 ||
+       m->write((void*)&(m->main.signature),sizeof(char), CSF_SIG_SPACE,m->fp)
                                                        != CSF_SIG_SPACE ||
        m->write((void*)&(m->main.version),sizeof(UINT2),(size_t)1,m->fp)!=1 ||
        m->write((void*)&(m->main.gisFileId),sizeof(UINT4),(size_t)1,m->fp)!=1 ||
@@ -52,9 +52,10 @@ int Mclose(
       M_ERROR(WRITE_ERROR);
       goto error;
     }
-    fseek(m->fp,ADDR_SECOND_HEADER, SEEK_SET);
+    
 
-    if (    m->write((void*)&(m->raster.valueScale),sizeof(UINT2),(size_t)1,m->fp) !=1 ||
+    if ( fseek(m->fp,ADDR_SECOND_HEADER, SEEK_SET) != 0 ||
+        m->write((void*)&(m->raster.valueScale),sizeof(UINT2),(size_t)1,m->fp) !=1 ||
       m->write((void*)&(m->raster.cellRepr), sizeof(UINT2),(size_t)1,m->fp) !=1 ||
         fwrite((void*)&(m->raster.minVal), sizeof(CSF_VAR_TYPE),(size_t)1,m->fp) !=1 ||
         fwrite((void*)&(m->raster.maxVal), sizeof(CSF_VAR_TYPE),(size_t)1,m->fp) !=1 ||
diff --git a/frmts/pcraster/libcsf/mopen.c b/frmts/pcraster/libcsf/mopen.c
index 56af168..7995b09 100644
--- a/frmts/pcraster/libcsf/mopen.c
+++ b/frmts/pcraster/libcsf/mopen.c
@@ -4,7 +4,7 @@
 #include "csfimpl.h"
 
 
-static const char *openModes[3] = {
+static const char * const openModes[3] = {
 	S_READ,
 	S_WRITE,
 	S_READ_WRITE
@@ -98,6 +98,11 @@ MAP  *Mopen(
      fprintf(stderr, "WARNING: Unable to read ORD_OK in CSF.\n");
  }
  if (s != ORD_OK) {
+    if( s != ORD_SWAB )
+    {
+        M_ERROR(NOT_CSF);
+        goto error_open;
+    }
 	m->write = CsfWriteSwapped;
 	m->read  = CsfReadSwapped;
  }
diff --git a/frmts/pcraster/libcsf/moreattr.c b/frmts/pcraster/libcsf/moreattr.c
index d834858..a49c8cb 100644
--- a/frmts/pcraster/libcsf/moreattr.c
+++ b/frmts/pcraster/libcsf/moreattr.c
@@ -5,7 +5,7 @@
 
 /* get the size of the history attribute
  * returns
- *  the size of history buffer INCLUDING the termimating `\0`,
+ *  the size of history buffer INCLUDING the terminating `\0`,
  *  or 0 if not available or in case of error
  */
 size_t MgetHistorySize(MAP *m) /* the map to get it from */
@@ -15,7 +15,7 @@ size_t MgetHistorySize(MAP *m) /* the map to get it from */
 
 /* get the size of the description attribute
  * returns
- *  the size of description buffer INCLUDING the termimating `\0`,
+ *  the size of description buffer INCLUDING the terminating `\0`,
  *  or 0 if not available or in case of error
  */
 size_t MgetDescriptionSize(MAP *m) /* the map to get it from */
@@ -25,10 +25,10 @@ size_t MgetDescriptionSize(MAP *m) /* the map to get it from */
 
 /* get the number of colour palette entries
  * MgetNrColourPaletteEntries returns the number of rgb tupels
- * of the colour palette. Each tupel is a sequence of 3 UINT2
+ * of the colour palette. Each tuple is a sequence of 3 UINT2
  * words describing red, green and blue.
  * returns
- *  the number of rgb tupels,
+ *  the number of rgb tuples,
  *  or 0 if not available or in case of error
  */
 size_t MgetNrColourPaletteEntries(MAP *m) /* the map to get it from */
@@ -40,10 +40,10 @@ size_t MgetNrColourPaletteEntries(MAP *m) /* the map to get it from */
 
 /* get the number of grey palette entries
  * MgetNrGreyPaletteEntries returns the number of grey tupels
- * of the grey palette. Each tupel is one UINT2
+ * of the grey palette. Each tuple is one UINT2
  * words describing the intensity: low, 0 is black, high is white.
  * returns
- *  the number of grey tupels,
+ *  the number of grey tuples,
  *  or 0 if not available or in case of error
  */
 size_t MgetNrGreyPaletteEntries(MAP *m) /* the map to get it from */
@@ -79,7 +79,7 @@ int MgetHistory(MAP *m,    /* the map to get it from */
 
 /* get the colour palette 
  * MgetColourPalette fills the pal argument with a number of rgb tupels
- * of the colour palette. Each tupel is a sequence of 3 UINT2
+ * of the colour palette. Each tuple is a sequence of 3 UINT2
  * words describing red, green and blue. Thus if the map has 8
  * colour palette entries it puts 24 UINT2 values in pal.
  * returns
@@ -95,7 +95,7 @@ int MgetColourPalette(MAP *m, /* the map to get it from */
 
 /* get the grey palette 
  * MgetGreyPalette fills the pal argument with a number of grey tupels
- * of the grey palette. Each tupel is one UINT2
+ * of the grey palette. Each tuple is one UINT2
  * words describing the intensity: low, 0 is black, high is white.
  * returns
  *  0 if not available or in case of error,
@@ -143,7 +143,7 @@ int MputHistory(MAP *m,    /* the map to get it from */
 /* put the colour palette 
  * MputColourPalette writes the pal argument that is filled 
  * with a number of rgb tupels
- * of the colour palette to the map. Each tupel is a sequence of 3 UINT2
+ * of the colour palette to the map. Each tuple is a sequence of 3 UINT2
  * words describing red, green and blue. Thus if the map has 8
  * colour palette entries it puts 24 UINT2 values in map palette.
  * An existing colour palette is overwritten.
@@ -153,7 +153,7 @@ int MputHistory(MAP *m,    /* the map to get it from */
  */
 int MputColourPalette(MAP *m, /* the map to get it from */
 	UINT2 *pal, /* the new palette */
-	size_t nrTupels) /* the number of 3 UINT2 words tupels of pal */
+	size_t nrTupels) /* the number of 3 UINT2 words tuples of pal */
 {
 	return CsfUpdateAttribute(m, ATTR_ID_COLOUR_PAL, sizeof(UINT2), 
 		nrTupels*3, pal);
@@ -162,7 +162,7 @@ int MputColourPalette(MAP *m, /* the map to get it from */
 /* put the grey palette 
  * MputColourPalette writes the pal argument that is filled 
  * with a number of grey tupels
- * of the grey palette. Each tupel is one UINT2
+ * of the grey palette. Each tuple is one UINT2
  * words describing the intensity: low, 0 is black, high is white.
  * An existing grey palette is overwritten.
  * returns
@@ -171,7 +171,7 @@ int MputColourPalette(MAP *m, /* the map to get it from */
  */
 int MputGreyPalette(MAP *m, /* the map to get it from */
 	UINT2 *pal, /* the new grey palette */
-	size_t nrTupels) /* the number of UINT2 words tupels of pal */
+	size_t nrTupels) /* the number of UINT2 words tuples of pal */
 {
 	return CsfUpdateAttribute(m, ATTR_ID_GREY_PAL, sizeof(UINT2), 
 		nrTupels, pal);
diff --git a/frmts/pcraster/libcsf/mperror.c b/frmts/pcraster/libcsf/mperror.c
index f625219..8a49332 100644
--- a/frmts/pcraster/libcsf/mperror.c
+++ b/frmts/pcraster/libcsf/mperror.c
@@ -2,7 +2,7 @@
 #include "csfimpl.h"
 
 
-static const char *errolist[ERRORNO]={
+static const char * const errolist[ERRORNO]={
 "No error",
 "File could not be opened or does not exist",
 "File is not a PCRaster file",
@@ -10,7 +10,7 @@ static const char *errolist[ERRORNO]={
 "Wrong byte order",
 "Not enough memory",
 "Illegal cell representation constant",
-"Acces denied",
+"Access denied",
 "Row number to big",
 "Collumn number to big",
 "Map is not a raster file",
diff --git a/frmts/pcraster/libcsf/pcrtypes.h b/frmts/pcraster/libcsf/pcrtypes.h
index c1bf244..e8504cb 100644
--- a/frmts/pcraster/libcsf/pcrtypes.h
+++ b/frmts/pcraster/libcsf/pcrtypes.h
@@ -65,20 +65,20 @@ namespace pcr {
   \param     v the value to be tested.
   \return    True if value \a v is a missing value.
 
-    the generic isMV(const T& v) is not implemented, only the specializations
+    The generic isMV(const T& v) is not implemented, only the specializations.
 
-  \todo      Zet alle dingen met een bepaald type,isMV, setMv, isType in
-             een zgn. struct trait
-             zie cast drama als isMV mist voor INT2 in BandMapTest::Open2
-             Zie numeric_limit discussie in Josuttis
+  TODO: Check translation of todo to English.
+  \todo      Put all things with a certain type, SMF, set Mv isType in a so-called.
+             Struct trait see cast drama as isMV fog INT2 in BandMapTest::Open2.
+             See numeric_limit discussion in Josuttis.
 */
-  template<typename T> bool isMV(const T& v);
+  template<typename T> static bool isMV(const T& v);
 /*!
   \brief     Tests if the value pointed to by v is a missing value.
   \param     v Pointer to the value to be tested.
   \return    True if the value pointed to by v is a missing value.
 */
-  template<typename T> bool isMV(T* v) {
+  template<typename T> static bool isMV(T* v) {
     return isMV(*v);
   }
 
@@ -121,7 +121,7 @@ template<> inline bool isMV(std::string const& string)
     \brief     Sets the value pointed to by v to a missing value.
     \param     v Pointer to the value to be set.
   */
-  template<typename T> void setMV(T *v) {
+  template<typename T> static void setMV(T *v) {
     setMV(*v);
   }
 
@@ -190,7 +190,7 @@ inline void setMV(std::string& string)
  *   or optimize for I86, for gcc look into include/asm/string
  */
 template<typename T>
- void setMV(T *v, size_t n)
+static void setMV(T *v, size_t n)
 {
   for(size_t i=0; i<n; i++)
       pcr::setMV(v[i]);
@@ -198,7 +198,7 @@ template<typename T>
 
  namespace detail {
    template<typename T>
-    void setMVMemSet(T *v, size_t n) {
+    static void setMVMemSet(T *v, size_t n) {
       memset(v,MV_UINT1,n*sizeof(T));
     }
  }
diff --git a/frmts/pcraster/libcsf/putallmv.c b/frmts/pcraster/libcsf/putallmv.c
index 6904f28..a856e02 100644
--- a/frmts/pcraster/libcsf/putallmv.c
+++ b/frmts/pcraster/libcsf/putallmv.c
@@ -7,7 +7,7 @@
  * RputAllMV writes a missing values to all the cells in a
  * map. For this is allocates a buffer to hold one row at a
  * time.
- * returns 1 if succesfull, 0 in case of an error
+ * returns 1 if successfully, 0 in case of an error
  */
 int RputAllMV(
 	MAP *m)
diff --git a/frmts/pcraster/libcsf/putattr.c b/frmts/pcraster/libcsf/putattr.c
index 7dba3fd..610cb9d 100644
--- a/frmts/pcraster/libcsf/putattr.c
+++ b/frmts/pcraster/libcsf/putattr.c
@@ -87,17 +87,17 @@ CSF_ATTR_ID CsfPutAttribute(
 		M_ERROR(WRITE_ERROR);
 		goto error;
 	}
-	return(id); 		/* succes */
+	return(id); 		/* success */
 error:	return(0);	/* failure */
 }
 
-/* seek to space for attribute  (LIBRARY_INTERNAL)
+/* Seek to space for attribute  (LIBRARY_INTERNAL)
  * CsfSeekAttrSpace seeks to the a point in the file where
  * the attribute must be stored and update the attribute control
  * blocks accordingly.
  * Writing can still fail since there is no check if that space is really
- * avalaible on the device. After this call returns the file is already
- * seeked to the point the functions returns.
+ * available on the device. After this call returns the file is already
+ * sought to the point the functions returns.
  * returns the file position or 0 in case of error.
  *
  * Merrno
@@ -107,13 +107,15 @@ error:	return(0);	/* failure */
  */
 CSF_FADDR32 CsfSeekAttrSpace(
 	MAP *m,       		/* map handle */
-	CSF_ATTR_ID id,               /* attribute identification only for check if avalaible */
-	size_t size)            /* size to be seeked to */
+	CSF_ATTR_ID id,         /* attribute identification only for check if available */
+	size_t size)            /* size to be sought to */
 {
 	ATTR_CNTRL_BLOCK b;
 	CSF_FADDR32 currBlockPos, prevBlockPos=USED_UNINIT_ZERO, newPos, endBlock, resultPos=0;
 	int noPosFound;
 	int i;
+        
+        memset(&b, 0, sizeof(b));
 
 	if (MattributeAvail(m ,id))
 	{
@@ -135,10 +137,10 @@ CSF_FADDR32 CsfSeekAttrSpace(
 		{
 			if (m->main.attrTable == 0)
 			{ /* FIRST BLOCK */
-				newPos =( (CSF_FADDR)(m->raster.nrRows)*
+				newPos =(CSF_FADDR32)(( (CSF_FADDR)(m->raster.nrRows)*
 					   (CSF_FADDR)(m->raster.nrCols)*
 					  (CSF_FADDR)(CELLSIZE(RgetCellRepr(m))))
-					  + ADDR_DATA;
+					  + ADDR_DATA);
 				m->main.attrTable = newPos;
 			}
 			else
@@ -150,7 +152,7 @@ CSF_FADDR32 CsfSeekAttrSpace(
 				if (CsfWriteAttrBlock(m, prevBlockPos, &b))
 				{
 					M_ERROR(WRITE_ERROR);
-					resultPos = 0;
+					/*resultPos = 0;*/
 				}
 			}
 			InitBlock(&b);
@@ -175,7 +177,7 @@ CSF_FADDR32 CsfSeekAttrSpace(
 					noPosFound = 0;
                                         break;
 				case ATTR_NOT_USED:
-					if (i == NR_ATTR_IN_BLOCK)
+					if (i+1 == NR_ATTR_IN_BLOCK)
 						endBlock = b.next;
 					else
 						endBlock = b.attrs[i+1].attrOffset;
@@ -199,7 +201,7 @@ CSF_FADDR32 CsfSeekAttrSpace(
 			currBlockPos = b.next;
  	} /* while */
 
-	b.attrs[i].attrSize = size;
+	b.attrs[i].attrSize = (UINT4)size;
 	b.attrs[i].attrId   = id;
 	resultPos = b.attrs[i].attrOffset;
 
@@ -208,6 +210,10 @@ CSF_FADDR32 CsfSeekAttrSpace(
 		M_ERROR(WRITE_ERROR);
 		resultPos = 0;
 	}
-	fseek(m->fp, (long)resultPos, SEEK_SET); /* fsetpos() is better */
+	if( fseek(m->fp, (long)resultPos, SEEK_SET) != 0 ) /* fsetpos() is better */
+        {
+                M_ERROR(WRITE_ERROR);
+                resultPos = 0;
+        }
 error:	return resultPos;
 } /* CsfSeekAttrSpace */
diff --git a/frmts/pcraster/libcsf/putsomec.c b/frmts/pcraster/libcsf/putsomec.c
index 0f42792..ee44673 100644
--- a/frmts/pcraster/libcsf/putsomec.c
+++ b/frmts/pcraster/libcsf/putsomec.c
@@ -257,6 +257,7 @@ size_t RputSomeCells(
 
 	writeAt  = ((CSF_FADDR)offset) << LOG_CELLSIZE(cr);
 	writeAt += ADDR_DATA;
-	fseek(map->fp, (long)writeAt, SEEK_SET); 
+	if( fseek(map->fp, (long)writeAt, SEEK_SET) != 0 )
+            return 0;
 	return(map->write(buf, (size_t)CELLSIZE(cr), (size_t)nrCells, map->fp));
 }
diff --git a/frmts/pcraster/libcsf/rattrblk.c b/frmts/pcraster/libcsf/rattrblk.c
index c545269..32db1bd 100644
--- a/frmts/pcraster/libcsf/rattrblk.c
+++ b/frmts/pcraster/libcsf/rattrblk.c
@@ -9,7 +9,8 @@ void CsfReadAttrBlock(
 	ATTR_CNTRL_BLOCK *b) /* write-only. attribute control block read */
 {
 	int i;
-	fseek(m->fp, (long)pos, SEEK_SET);
+	if (fseek(m->fp, (long)pos, SEEK_SET) != 0 )
+            return;
 	for(i=0; i < NR_ATTR_IN_BLOCK; i++)
 	{
 	 m->read((void *)&(b->attrs[i].attrId), sizeof(UINT2),(size_t)1,m->fp);
diff --git a/frmts/pcraster/libcsf/rextend.c b/frmts/pcraster/libcsf/rextend.c
index f159fce..4927338 100644
--- a/frmts/pcraster/libcsf/rextend.c
+++ b/frmts/pcraster/libcsf/rextend.c
@@ -17,14 +17,14 @@
 
 static double RoundDown(
 	double v,
-	double round)
+	double dfRound)
 {
-	double rVal = fmod(v, round);
+	double rVal = fmod(v, dfRound);
 	double x;
 	if(rVal == 0)
-		return v-round;
+		return v-dfRound;
 	if (v < 0)
-		x = v-round-rVal;
+		x = v-dfRound-rVal;
 	else
 		x = v-rVal;
 	return  x;
@@ -32,15 +32,15 @@ static double RoundDown(
 
 static double RoundUp(
 	double v,
-	double round)
+	double dfRound)
 {
-	double rVal = fmod(v, round);
+	double rVal = fmod(v, dfRound);
 	if(rVal == 0)
-		return v+round;
+		return v+dfRound;
 	if (v < 0)
 	  return v-rVal;
 	else
-	  return v+round-rVal; 
+	  return v+dfRound-rVal; 
 }
 
 /* compute (xUL,yUL) and nrRows, nrCols from some coordinates
diff --git a/frmts/pcraster/libcsf/ruseas.c b/frmts/pcraster/libcsf/ruseas.c
index b272d30..9670d9f 100644
--- a/frmts/pcraster/libcsf/ruseas.c
+++ b/frmts/pcraster/libcsf/ruseas.c
@@ -364,7 +364,7 @@ static CSF_CONV_FUNC ConvFunc(CSF_CR destType, CSF_CR srcType)
 	PRECOND(convTableIndex[CSF_UNIQ_CR_MASK(destType)] != -1);
 	/* don't complain on illegal, it can be attached
 	 * to a app2file while there's no WRITE_MODE
-	 * if it's an error then it's catched in RputSomeCells
+	 * if it's an error then it's cached in RputSomeCells
 	 */
 	return 
          ConvTable[(int)convTableIndex[CSF_UNIQ_CR_MASK(srcType)]]
@@ -437,12 +437,20 @@ int RuseAs(
   CSF_CR inFileCR = RgetCellRepr(m);
   CSF_VS inFileVS = RgetValueScale(m);
   int hasInFileCellReprType2 =  HasInFileCellReprType2(inFileCR);
+  int useTypeNoEnumIn;
+  int useTypeNoEnum;
 
-  /* it is very unconvenient that both, VS and CR are taken as arguments
+  /* It is very inconvenient that both, VS and CR are taken as arguments
    * for this function, and previously were used in the switch statement
-   * now, at least 'special conversions' handled first
+   * now, at least 'special conversions' handled first.
    */
-  if((int)useType == VS_BOOLEAN){
+
+  /* Hopefully Coverity will no longer detect that useTypeNoEnum */
+  /* comes from useType */
+  useTypeNoEnumIn = useType;
+  memcpy(&useTypeNoEnum, &useTypeNoEnumIn, sizeof(int));
+
+  if(useTypeNoEnum == VS_BOOLEAN){
     switch(inFileVS) {
       case VS_LDD:
       case VS_DIRECTION: {
@@ -469,7 +477,7 @@ int RuseAs(
       }
     }
   }
-  else if ((int)useType == VS_LDD){
+  else if (useTypeNoEnum == VS_LDD){
     switch(inFileVS) {
       case VS_LDD: {
         POSTCOND(inFileCR == CR_UINT1);
diff --git a/frmts/pcraster/libcsf/setangle.c b/frmts/pcraster/libcsf/setangle.c
index d20278b..1474e1e 100644
--- a/frmts/pcraster/libcsf/setangle.c
+++ b/frmts/pcraster/libcsf/setangle.c
@@ -31,8 +31,8 @@
  * routines. And since they do a counter clockwise rotation we
  * take the sine and cosine of the negative angle.
  *
- * copy projection field into  raster, so raster can act as an 
- * indepent structure, for transformations
+ * Copy projection field into the raster, so raster can act as an 
+ * independent structure for transformations.
  */
 void CsfFinishMapInit(
 	MAP *m)		/* map handle */
diff --git a/frmts/pcraster/libcsf/setmv.c b/frmts/pcraster/libcsf/setmv.c
index d5e2a98..82be83a 100644
--- a/frmts/pcraster/libcsf/setmv.c
+++ b/frmts/pcraster/libcsf/setmv.c
@@ -45,8 +45,9 @@ void SetMVcellRepr(
 				break;
 		case CR_REAL8 :
 				((UINT4 *)c)[1] = MV_UINT4;
+                                *((UINT4 *)c) = MV_UINT4;
+                                break;
 		default       : POSTCOND(
-					cellRepr == CR_REAL8 ||
 					cellRepr == CR_REAL4 ||
 					cellRepr == CR_UINT4 );
 				*((UINT4 *)c) = MV_UINT4;
diff --git a/frmts/pcraster/libcsf/strconst.c b/frmts/pcraster/libcsf/strconst.c
index 6575338..4c82606 100644
--- a/frmts/pcraster/libcsf/strconst.c
+++ b/frmts/pcraster/libcsf/strconst.c
@@ -21,7 +21,7 @@ static char errorBuf[64];
 /* IMPLEMENTATION */
 /******************/
 
-/* string with cell representation in plain english or acronym
+/* string with cell representation in plain English or acronym
  * The string is in lower case except for INT1,INT2,UINT2 and UINT4
  *, they return an acronym. If cr is not
  * a valid constant, for example 999,  then the string is  
@@ -42,7 +42,7 @@ const char *RstrCellRepr(CSF_CR cr) /* cell representation constant */
 	case CR_UINT4 : return "UINT4";
 	case CR_REAL4 : return "small real";
 	case CR_REAL8 : return "large real";
-	default       : (void)sprintf(errorBuf,"%u is no CR constant", (unsigned)cr);
+	default       : (void)snprintf(errorBuf, sizeof(errorBuf), "%u is no CR constant", (unsigned)cr);
                         return errorBuf;
  }
 }
@@ -68,7 +68,7 @@ const char *RstrValueScale(CSF_VS vs) /* value scale constant */
 	case VS_SCALAR        : return "scalar";
 	case VS_DIRECTION     : return "directional";
 	case VS_LDD           : return "ldd";
-	default       : (void)sprintf(errorBuf,"%u is no VS constant", (unsigned)vs);
+	default       : (void)snprintf(errorBuf, sizeof(errorBuf), "%u is no VS constant", (unsigned)vs);
                         return errorBuf;
  }
 }
diff --git a/frmts/pcraster/libcsf/trackmm.c b/frmts/pcraster/libcsf/trackmm.c
index 92389e7..eeeb115 100644
--- a/frmts/pcraster/libcsf/trackmm.c
+++ b/frmts/pcraster/libcsf/trackmm.c
@@ -24,7 +24,7 @@
 
 /* disable automatic tracking of minimum and maximum value 
  * A call to RdontTrackMinMax disables the automatic tracking
- * of the min/max value in succesive cell writes. 
+ * of the min/max value in successive cell writes.
  * If used, one must always
  * use RputMinVal and RputMaxVal to set the correct values.
  */
diff --git a/frmts/pcraster/pcrasterdataset.cpp b/frmts/pcraster/pcrasterdataset.cpp
index ef34e82..070e12d 100644
--- a/frmts/pcraster/pcrasterdataset.cpp
+++ b/frmts/pcraster/pcrasterdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pcrasterdataset.cpp 29187 2015-05-13 14:20:13Z kdejong $
+ * $Id: pcrasterdataset.cpp 33105 2016-01-23 15:27:32Z rouault $
  *
  * Project:  PCRaster Integration
  * Purpose:  PCRaster CSF 2.0 raster file driver
@@ -27,41 +27,14 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef INCLUDED_IOSTREAM
-#include <iostream>
-#define INCLUDED_IOSTREAM
-#endif
-
-#ifndef INCLUDED_GDAL_PAM
-#include "gdal_pam.h"
-#define INCLUDED_GDAL_PAM
-#endif
-
-#ifndef INCLUDED_CPL_STRING
 #include "cpl_string.h"
-#define INCLUDED_CPL_STRING
-#endif
-
-CPL_CVSID("$Id: pcrasterdataset.cpp 29187 2015-05-13 14:20:13Z kdejong $");
-
-// PCRaster library headers.
+#include "gdal_pam.h"
 
-// Module headers.
-#ifndef INCLUDED_PCRASTERRASTERBAND
 #include "pcrasterrasterband.h"
-#define INCLUDED_PCRASTERRASTERBAND
-#endif
-
-#ifndef INCLUDED_PCRASTERDATASET
 #include "pcrasterdataset.h"
-#define INCLUDED_PCRASTERDATASET
-#endif
-
-#ifndef INCLUDED_PCRASTERUTIL
 #include "pcrasterutil.h"
-#define INCLUDED_PCRASTERUTIL
-#endif
 
+CPL_CVSID("$Id: pcrasterdataset.cpp 33105 2016-01-23 15:27:32Z rouault $");
 
 
 /*!
@@ -80,15 +53,15 @@ CPL_CVSID("$Id: pcrasterdataset.cpp 29187 2015-05-13 14:20:13Z kdejong $");
   \param     info Object with information about the dataset to open.
   \return    Pointer to newly allocated GDALDataset or 0.
 
-  Returns 0 if the file could not be opened.
+  Returns a nullptr if the file could not be opened.
 */
 GDALDataset* PCRasterDataset::open(
          GDALOpenInfo* info)
 {
-  PCRasterDataset* dataset = 0;
+  PCRasterDataset* dataset = NULL;
 
   if(info->fpL && info->nHeaderBytes >= static_cast<int>(CSF_SIZE_SIG) &&
-         strncmp((char*)info->pabyHeader, CSF_SIG, CSF_SIZE_SIG) == 0) {
+     strncmp(reinterpret_cast<char*>( info->pabyHeader ), CSF_SIG, CSF_SIZE_SIG) == 0) {
     MOPEN_PERM mode = info->eAccess == GA_Update
          ? M_READ_WRITE
          : M_READ;
@@ -96,7 +69,13 @@ GDALDataset* PCRasterDataset::open(
     MAP* map = mapOpen(info->pszFilename, mode);
 
     if(map) {
+      CPLErrorReset();
       dataset = new PCRasterDataset(map);
+      if( CPLGetLastErrorType() != CE_None )
+      {
+          delete dataset;
+          return NULL;
+      }
     }
   }
 
@@ -138,19 +117,16 @@ GDALDataset* PCRasterDataset::createCopy(
     void* progressData)
 {
   // Checks.
-  int nrBands = source->GetRasterCount();
+  const int nrBands = source->GetRasterCount();
   if(nrBands != 1) {
     CPLError(CE_Failure, CPLE_NotSupported,
          "PCRaster driver: Too many bands ('%d'): must be 1 band", nrBands);
-    return 0;
+    return NULL;
   }
 
   GDALRasterBand* raster = source->GetRasterBand(1);
 
   // Create PCRaster raster. Determine properties of raster to create.
-  size_t nrRows = raster->GetYSize();
-  size_t nrCols = raster->GetXSize();
-  std::string string;
 
   // The in-file type of the cells.
   CSF_CR fileCellRepresentation = GDALType2CellRepresentation(
@@ -159,27 +135,28 @@ GDALDataset* PCRasterDataset::createCopy(
   if(fileCellRepresentation == CR_UNDEFINED) {
     CPLError(CE_Failure, CPLE_NotSupported,
          "PCRaster driver: Cannot determine a valid cell representation");
-    return 0;
+    return NULL;
   }
 
   // The value scale of the values.
   CSF_VS valueScale = VS_UNDEFINED;
+  std::string osString;
   if(source->GetMetadataItem("PCRASTER_VALUESCALE")) {
-    string = source->GetMetadataItem("PCRASTER_VALUESCALE");
+    osString = source->GetMetadataItem("PCRASTER_VALUESCALE");
   }
 
-  valueScale = !string.empty()
-         ? string2ValueScale(string)
+  valueScale = !osString.empty()
+         ? string2ValueScale(osString)
          : GDALType2ValueScale(raster->GetRasterDataType());
 
   if(valueScale == VS_UNDEFINED) {
     CPLError(CE_Failure, CPLE_NotSupported,
          "PCRaster driver: Cannot determine a valid value scale");
-    return 0;
+    return NULL;
   }
 
   CSF_PT const projection = PT_YDECT2B;
-  REAL8  const angle = 0.0;
+  const REAL8 angle = 0.0;
   REAL8 west = 0.0;
   REAL8 north = 0.0;
   REAL8 cellSize = 1.0;
@@ -201,7 +178,7 @@ GDALDataset* PCRasterDataset::createCopy(
   if(appCellRepresentation == CR_UNDEFINED) {
     CPLError(CE_Failure, CPLE_NotSupported,
          "PCRaster driver: Cannot determine a valid cell representation");
-    return 0;
+    return NULL;
   }
 
   // Check whether value scale fits the cell representation. Adjust when
@@ -209,13 +186,15 @@ GDALDataset* PCRasterDataset::createCopy(
   valueScale = fitValueScale(valueScale, appCellRepresentation);
 
   // Create a raster with the in file cell representation.
+  const size_t nrRows = raster->GetYSize();
+  const size_t nrCols = raster->GetXSize();
   MAP* map = Rcreate(filename, nrRows, nrCols, fileCellRepresentation,
          valueScale, projection, west, north, angle, cellSize);
 
   if(!map) {
     CPLError(CE_Failure, CPLE_OpenFailed,
          "PCRaster driver: Unable to create raster %s", filename);
-    return 0;
+    return NULL;
   }
 
   // Try to convert in app cell representation to the cell representation
@@ -224,7 +203,7 @@ GDALDataset* PCRasterDataset::createCopy(
     CPLError(CE_Failure, CPLE_NotSupported,
          "PCRaster driver: Cannot convert cells: %s", MstrError());
     Mclose(map);
-    return 0;
+    return NULL;
   }
 
   int hasMissingValue;
@@ -239,8 +218,9 @@ GDALDataset* PCRasterDataset::createCopy(
     missingValue = ::missingValue(fileCellRepresentation);
   }
 
-  // TODO conversie van INT2 naar INT4 ondersteunen. zie ruseas.c regel 503.
-  // conversie op r 159.
+  // TODO: Proper translation of TODO.
+  // TODO: Support conversion to INT2 (?) INT4. ruseas.c see line 503.
+  // Conversion r 159.
 
   // Create buffer for one row of values.
   void* buffer = Rmalloc(map, nrCols);
@@ -250,7 +230,9 @@ GDALDataset* PCRasterDataset::createCopy(
   for(size_t row = 0; errorCode == CE_None && row < nrRows; ++row) {
 
     // Get row from source.
-    if(raster->RasterIO(GF_Read, 0, row, nrCols, 1, buffer, nrCols, 1,
+    if(raster->RasterIO(GF_Read, 0, static_cast<int>(row),
+        static_cast<int>(nrCols), 1, buffer,
+        static_cast<int>(nrCols), 1,
          raster->GetRasterDataType(), 0, 0, NULL) != CE_None) {
       CPLError(CE_Failure, CPLE_FileIO,
          "PCRaster driver: Error reading from source raster");
@@ -274,7 +256,7 @@ GDALDataset* PCRasterDataset::createCopy(
     // Write row in target.
     RputRow(map, row, buffer);
 
-    if(!progress((row + 1) / (static_cast<double>(nrRows)), 0, progressData)) {
+    if(!progress((row + 1) / (static_cast<double>(nrRows)), NULL, progressData)) {
       CPLError(CE_Failure, CPLE_UserInterrupt,
          "PCRaster driver: User terminated CreateCopy()");
       errorCode = CE_Failure;
@@ -283,10 +265,10 @@ GDALDataset* PCRasterDataset::createCopy(
   }
 
   Mclose(map);
-  map = 0;
+  map = NULL;
 
   free(buffer);
-  buffer = 0;
+  buffer = NULL;
 
   if( errorCode != CE_None )
       return NULL;
@@ -294,8 +276,8 @@ GDALDataset* PCRasterDataset::createCopy(
 /* -------------------------------------------------------------------- */
 /*      Re-open dataset, and copy any auxiliary pam information.        */
 /* -------------------------------------------------------------------- */
-  GDALPamDataset *poDS = (GDALPamDataset *)
-        GDALOpen( filename, GA_Update );
+  GDALPamDataset *poDS = reinterpret_cast<GDALPamDataset *>(
+      GDALOpen( filename, GA_Update ) );
 
   if( poDS )
       poDS->CloneInfo( source, GCIF_PAM_DEFAULT );
@@ -313,25 +295,31 @@ GDALDataset* PCRasterDataset::createCopy(
 /*!
   \param     map PCRaster map handle. It is ours to close.
 */
-PCRasterDataset::PCRasterDataset(
-         MAP* map)
-
-  : GDALPamDataset(),
-    d_map(map), d_west(0.0), d_north(0.0), d_cellSize(0.0)
-
+PCRasterDataset::PCRasterDataset( MAP* mapIn) :
+    GDALPamDataset(),
+    d_map(mapIn),
+    d_west(0.0),
+    d_north(0.0),
+    d_cellSize(0.0),
+    d_location_changed(false)
 {
   // Read header info.
-  nRasterXSize = RgetNrCols(d_map);
-  nRasterYSize = RgetNrRows(d_map);
+  nRasterXSize = static_cast<int>(RgetNrCols(d_map));
+  nRasterYSize = static_cast<int>(RgetNrRows(d_map));
   d_west = static_cast<double>(RgetXUL(d_map));
   d_north = static_cast<double>(RgetYUL(d_map));
   d_cellSize = static_cast<double>(RgetCellSize(d_map));
   d_cellRepresentation = RgetUseCellRepr(d_map);
-  CPLAssert(d_cellRepresentation != CR_UNDEFINED);
+  if( d_cellRepresentation == CR_UNDEFINED )
+  {
+      CPLError(CE_Failure, CPLE_AssertionFailed, "d_cellRepresentation != CR_UNDEFINED");
+  }
   d_valueScale = RgetValueScale(d_map);
-  CPLAssert(d_valueScale != VS_UNDEFINED);
+  if( d_valueScale == VS_UNDEFINED )
+  {
+      CPLError(CE_Failure, CPLE_AssertionFailed, "d_valueScale != VS_UNDEFINED");
+  }
   d_defaultNoDataValue = ::missingValue(d_cellRepresentation);
-  d_location_changed = false;
 
   // Create band information objects.
   nBands = 1;
@@ -444,7 +432,7 @@ GDALDataset* PCRasterDataset::create(
     return NULL;
   }
 
-  int row_col_max = INT4_MAX - 1;
+  const int row_col_max = INT4_MAX - 1;
   if(nr_cols > row_col_max){
     CPLError(CE_Failure, CPLE_NotSupported,
          "PCRaster driver : "
@@ -521,8 +509,8 @@ GDALDataset* PCRasterDataset::create(
 /* -------------------------------------------------------------------- */
 /*      Re-open dataset, and copy any auxiliary pam information.        */
 /* -------------------------------------------------------------------- */
-  GDALPamDataset *poDS = (GDALPamDataset *)
-        GDALOpen(filename, GA_Update);
+  GDALPamDataset *poDS = reinterpret_cast<GDALPamDataset *>(
+      GDALOpen(filename, GA_Update) );
 
   return poDS;
 }
@@ -556,14 +544,3 @@ CPLErr PCRasterDataset::SetGeoTransform(double* transform)
 bool PCRasterDataset::location_changed() const {
   return d_location_changed;
 }
-
-
-//------------------------------------------------------------------------------
-// DEFINITION OF FREE OPERATORS
-//------------------------------------------------------------------------------
-
-
-
-//------------------------------------------------------------------------------
-// DEFINITION OF FREE FUNCTIONS
-//------------------------------------------------------------------------------
diff --git a/frmts/pcraster/pcrasterdataset.h b/frmts/pcraster/pcrasterdataset.h
index e6651d4..2abcf97 100644
--- a/frmts/pcraster/pcrasterdataset.h
+++ b/frmts/pcraster/pcrasterdataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pcrasterdataset.h 29187 2015-05-13 14:20:13Z kdejong $
+ * $Id: pcrasterdataset.h 31137 2015-10-26 12:58:08Z goatbar $
  *
  * Project:  PCRaster Integration
  * Purpose:  PCRaster CSF 2.0 raster file driver declarations.
@@ -30,19 +30,8 @@
 #ifndef INCLUDED_PCRASTERDATASET
 #define INCLUDED_PCRASTERDATASET
 
-// Library headers.
-#ifndef INCLUDED_GDAL_PAM
 #include "gdal_pam.h"
-#define INCLUDED_GDAL_PAM
-#endif
-
-// PCRaster library headers.
-#ifndef INCLUDED_CSF
 #include "csf.h"
-#define INCLUDED_CSF
-#endif
-
-// Module headers.
 
 // namespace {
   // PCRasterDataset declarations.
@@ -155,27 +144,6 @@ public:
   bool             location_changed    () const;
 
 };
-
-
-
-//------------------------------------------------------------------------------
-// INLINE FUNCTIONS
-//------------------------------------------------------------------------------
-
-
-
-//------------------------------------------------------------------------------
-// FREE OPERATORS
-//------------------------------------------------------------------------------
-
-
-
-//------------------------------------------------------------------------------
-// FREE FUNCTIONS
-//------------------------------------------------------------------------------
-
-
-
 // } // namespace
 
 #endif
diff --git a/frmts/pcraster/pcrastermisc.cpp b/frmts/pcraster/pcrastermisc.cpp
index 71f23ac..7f8c055 100644
--- a/frmts/pcraster/pcrastermisc.cpp
+++ b/frmts/pcraster/pcrastermisc.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pcrastermisc.cpp 28862 2015-04-07 10:10:25Z kdejong $
+ * $Id: pcrastermisc.cpp 32215 2015-12-18 06:30:54Z goatbar $
  *
  * Project:  PCRaster Integration
  * Purpose:  PCRaster driver support functions.
@@ -27,59 +27,31 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-// Library headers.
-#ifndef INCLUDED_IOSTREAM
-#include <iostream>
-#define INCLUDED_IOSTREAM
-#endif
-
-#ifndef INCLUDED_STRING
-#include <string>
-#define INCLUDED_STRING
-#endif
-
-#ifndef INCLUDED_GDAL_PAM
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
-#define INCLUDED_GDAL_PAM
-#endif
-
-// PCRaster library headers.
-
-// Module headers.
-#ifndef INCLUDED_PCRASTERDATASET
 #include "pcrasterdataset.h"
-#define INCLUDED_PCRASTERDATASET
-#endif
-
-
-
-CPL_C_START
-void GDALRegister_PCRaster(void);
-CPL_C_END
-
-
 
 void GDALRegister_PCRaster()
 {
-    if (! GDAL_CHECK_VERSION("PCRaster driver"))
+    if( !GDAL_CHECK_VERSION( "PCRaster driver" ) )
         return;
 
-    if(!GDALGetDriverByName("PCRaster")) {
+    if( GDALGetDriverByName( "PCRaster" ) != NULL )
+        return;
 
-        GDALDriver* poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetDescription("PCRaster");
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetDescription("PCRaster");
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
 
-        poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "PCRaster Raster File");
-        poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, "Byte Int32 Float32");
-        poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "frmt_various.html#PCRaster");
-        poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "map" );
+    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "PCRaster Raster File");
+    poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, "Byte Int32 Float32");
+    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "frmt_various.html#PCRaster");
+    poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "map" );
 
-        poDriver->pfnOpen = PCRasterDataset::open;
-        poDriver->pfnCreate = PCRasterDataset::create;
-        poDriver->pfnCreateCopy = PCRasterDataset::createCopy;
+    poDriver->pfnOpen = PCRasterDataset::open;
+    poDriver->pfnCreate = PCRasterDataset::create;
+    poDriver->pfnCreateCopy = PCRasterDataset::createCopy;
 
-        GetGDALDriverManager()->RegisterDriver(poDriver);
-    }
+    GetGDALDriverManager()->RegisterDriver(poDriver);
 }
diff --git a/frmts/pcraster/pcrasterrasterband.cpp b/frmts/pcraster/pcrasterrasterband.cpp
index 2bcf084..88bdd44 100644
--- a/frmts/pcraster/pcrasterrasterband.cpp
+++ b/frmts/pcraster/pcrasterrasterband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pcrasterrasterband.cpp 29187 2015-05-13 14:20:13Z kdejong $
+ * $Id: pcrasterrasterband.cpp 31680 2015-11-21 13:44:47Z rouault $
  *
  * Project:  PCRaster Integration
  * Purpose:  PCRaster raster band implementation.
@@ -27,48 +27,17 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef INCLUDED_PCRASTERRASTERBAND
-#include "pcrasterrasterband.h"
-#define INCLUDED_PCRASTERRASTERBAND
-#endif
-
-// PCRaster library headers.
-#ifndef INCLUDED_CSF
 #include "csf.h"
-#define INCLUDED_CSF
-#endif
-
-#ifndef INCLUDED_CSFIMPL
 #include "csfimpl.h"
-#define INCLUDED_CSFIMPL
-#endif
-
-// Module headers.
-#ifndef INCLUDED_PCRASTERDATASET
 #include "pcrasterdataset.h"
-#define INCLUDED_PCRASTERDATASET
-#endif
-
-#ifndef INCLUDED_PCRASTERUTIL
+#include "pcrasterrasterband.h"
 #include "pcrasterutil.h"
-#define INCLUDED_PCRASTERUTIL
-#endif
-
-
 
 /*!
   \file
   This file contains the implementation of the PCRasterRasterBand class.
 */
 
-
-
-//------------------------------------------------------------------------------
-// DEFINITION OF STATIC PCRRASTERBAND MEMBERS
-//------------------------------------------------------------------------------
-
-
-
 //------------------------------------------------------------------------------
 // DEFINITION OF PCRRASTERBAND MEMBERS
 //------------------------------------------------------------------------------
@@ -77,36 +46,26 @@
 /*!
   \param     dataset The dataset we are a part of.
 */
-PCRasterRasterBand::PCRasterRasterBand(
-         PCRasterDataset* dataset)
-
-  : GDALPamRasterBand(),
+PCRasterRasterBand::PCRasterRasterBand( PCRasterDataset* dataset ) :
+    GDALPamRasterBand(),
     d_dataset(dataset),
     d_noDataValue(),
     d_defaultNoDataValueOverridden(false),
     d_create_in(GDT_Unknown)
-
 {
-  this->poDS = dataset;
-  this->nBand = 1;
-  this->eDataType = cellRepresentation2GDALType(dataset->cellRepresentation());
-  this->nBlockXSize = dataset->GetRasterXSize();
-  this->nBlockYSize = 1;
+    poDS = dataset;
+    nBand = 1;
+    eDataType = cellRepresentation2GDALType(dataset->cellRepresentation());
+    nBlockXSize = dataset->GetRasterXSize();
+    nBlockYSize = 1;
 }
 
-
-
 //! Destructor.
 /*!
 */
-PCRasterRasterBand::~PCRasterRasterBand()
-{
-}
-
-
+PCRasterRasterBand::~PCRasterRasterBand() {}
 
-double PCRasterRasterBand::GetNoDataValue(
-         int* success)
+double PCRasterRasterBand::GetNoDataValue( int* success )
 {
   if(success) {
     *success = 1;
@@ -116,68 +75,66 @@ double PCRasterRasterBand::GetNoDataValue(
     ? d_noDataValue : d_dataset->defaultNoDataValue();
 }
 
-
-
 double PCRasterRasterBand::GetMinimum(
          int* success)
 {
   double result;
-  int isValid;
+  bool isValid;
 
   switch(d_dataset->cellRepresentation()) {
     // CSF version 2. ----------------------------------------------------------
     case CR_UINT1: {
       UINT1 min;
-      isValid = RgetMinVal(d_dataset->map(), &min);
+      isValid = CPL_TO_BOOL(RgetMinVal(d_dataset->map(), &min));
       result = static_cast<double>(min);
       break;
     }
     case CR_INT4: {
       INT4 min;
-      isValid = RgetMinVal(d_dataset->map(), &min);
+      isValid = CPL_TO_BOOL(RgetMinVal(d_dataset->map(), &min));
       result = static_cast<double>(min);
       break;
     }
     case CR_REAL4: {
       REAL4 min;
-      isValid = RgetMinVal(d_dataset->map(), &min);
+      isValid = CPL_TO_BOOL(RgetMinVal(d_dataset->map(), &min));
       result = static_cast<double>(min);
       break;
     }
     case CR_REAL8: {
       REAL8 min;
-      isValid = RgetMinVal(d_dataset->map(), &min);
+      isValid = CPL_TO_BOOL(RgetMinVal(d_dataset->map(), &min));
       result = static_cast<double>(min);
       break;
     }
     // CSF version 1. ----------------------------------------------------------
     case CR_INT1: {
       INT1 min;
-      isValid = RgetMinVal(d_dataset->map(), &min);
+      isValid = CPL_TO_BOOL(RgetMinVal(d_dataset->map(), &min));
       result = static_cast<double>(min);
       break;
     }
     case CR_INT2: {
       INT2 min;
-      isValid = RgetMinVal(d_dataset->map(), &min);
+      isValid = CPL_TO_BOOL(RgetMinVal(d_dataset->map(), &min));
       result = static_cast<double>(min);
       break;
     }
     case CR_UINT2: {
       UINT2 min;
-      isValid = RgetMinVal(d_dataset->map(), &min);
+      isValid = CPL_TO_BOOL(RgetMinVal(d_dataset->map(), &min));
       result = static_cast<double>(min);
       break;
     }
     case CR_UINT4: {
       UINT4 min;
-      isValid = RgetMinVal(d_dataset->map(), &min);
+      isValid = CPL_TO_BOOL(RgetMinVal(d_dataset->map(), &min));
       result = static_cast<double>(min);
       break;
     }
     default: {
       result = 0.0;
-      isValid = 0;
+      isValid = false;
       break;
     }
   }
@@ -195,55 +152,55 @@ double PCRasterRasterBand::GetMaximum(
          int* success)
 {
   double result;
-  int isValid;
+  bool isValid;
 
   switch(d_dataset->cellRepresentation()) {
     case CR_UINT1: {
       UINT1 max;
-      isValid = RgetMaxVal(d_dataset->map(), &max);
+      isValid = CPL_TO_BOOL(RgetMaxVal(d_dataset->map(), &max));
       result = static_cast<double>(max);
       break;
     }
     case CR_INT4: {
       INT4 max;
-      isValid = RgetMaxVal(d_dataset->map(), &max);
+      isValid = CPL_TO_BOOL(RgetMaxVal(d_dataset->map(), &max));
       result = static_cast<double>(max);
       break;
     }
     case CR_REAL4: {
       REAL4 max;
-      isValid = RgetMaxVal(d_dataset->map(), &max);
+      isValid = CPL_TO_BOOL(RgetMaxVal(d_dataset->map(), &max));
       result = static_cast<double>(max);
       break;
     }
     // CSF version 1. ----------------------------------------------------------
     case CR_INT1: {
       INT1 max;
-      isValid = RgetMaxVal(d_dataset->map(), &max);
+      isValid = CPL_TO_BOOL(RgetMaxVal(d_dataset->map(), &max));
       result = static_cast<double>(max);
       break;
     }
     case CR_INT2: {
       INT2 max;
-      isValid = RgetMaxVal(d_dataset->map(), &max);
+      isValid = CPL_TO_BOOL(RgetMaxVal(d_dataset->map(), &max));
       result = static_cast<double>(max);
       break;
     }
     case CR_UINT2: {
       UINT2 max;
-      isValid = RgetMaxVal(d_dataset->map(), &max);
+      isValid = CPL_TO_BOOL(RgetMaxVal(d_dataset->map(), &max));
       result = static_cast<double>(max);
       break;
     }
     case CR_UINT4: {
       UINT4 max;
-      isValid = RgetMaxVal(d_dataset->map(), &max);
+      isValid = CPL_TO_BOOL(RgetMaxVal(d_dataset->map(), &max));
       result = static_cast<double>(max);
       break;
     }
     default: {
       result = 0.0;
-      isValid = 0;
+      isValid = false;
       break;
     }
   }
@@ -341,7 +298,7 @@ CPLErr PCRasterRasterBand::IWriteBlock(
     (void)RputCellSize(d_dataset->map(), cellSize);
   }
 
-  int nr_cols = this->poDS->GetRasterXSize();
+  const int nr_cols = this->poDS->GetRasterXSize();
 
   // new maps from create() set min/max to MV
   // in case of reopening that map the min/max
@@ -409,14 +366,3 @@ CPLErr PCRasterRasterBand::SetNoDataValue(double nodata)
 
   return CE_None;
 }
-
-
-//------------------------------------------------------------------------------
-// DEFINITION OF FREE OPERATORS
-//------------------------------------------------------------------------------
-
-
-
-//------------------------------------------------------------------------------
-// DEFINITION OF FREE FUNCTIONS
-//------------------------------------------------------------------------------
diff --git a/frmts/pcraster/pcrasterrasterband.h b/frmts/pcraster/pcrasterrasterband.h
index 471e8a6..abda85d 100644
--- a/frmts/pcraster/pcrasterrasterband.h
+++ b/frmts/pcraster/pcrasterrasterband.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pcrasterrasterband.h 29187 2015-05-13 14:20:13Z kdejong $
+ * $Id: pcrasterrasterband.h 31137 2015-10-26 12:58:08Z goatbar $
  *
  * Project:  PCRaster Integration
  * Purpose:  PCRaster raster band declaration.
@@ -30,29 +30,15 @@
 #ifndef INCLUDED_PCRASTERRASTERBAND
 #define INCLUDED_PCRASTERRASTERBAND
 
-// Library headers.
-#ifndef INCLUDED_GDAL_PAM
 #include "gdal_pam.h"
-#define INCLUDED_GDAL_PAM
-#endif
-
-// PCRaster library headers.
-
-// Module headers.
-
-
 
 // namespace {
   // PCRasterRasterBand declarations.
 // }
 class PCRasterDataset;
 
-
-
 // namespace {
 
-
-
 //! This class specialises the GDALRasterBand class for PCRaster rasters.
 /*!
 */
@@ -65,9 +51,7 @@ private:
   PCRasterDataset const* d_dataset;
 
   double           d_noDataValue;
-
   bool             d_defaultNoDataValueOverridden;
-
   GDALDataType     d_create_in;
 
   virtual CPLErr   IRasterIO           (GDALRWFlag, int, int, int, int,
@@ -83,21 +67,12 @@ private:
                    PCRasterRasterBand  (const PCRasterRasterBand&);
 
 protected:
-
   double           GetNoDataValue      (int* success=NULL);
-
   double           GetMinimum          (int* success);
-
   double           GetMaximum          (int* success);
 
 public:
-
-  //----------------------------------------------------------------------------
-  // CREATORS
-  //----------------------------------------------------------------------------
-
                    PCRasterRasterBand  (PCRasterDataset* dataset);
-
   /* virtual */    ~PCRasterRasterBand ();
 
   //----------------------------------------------------------------------------
@@ -117,29 +92,7 @@ public:
   CPLErr           IReadBlock          (int nBlockXoff,
                                         int nBlockYoff,
                                         void* buffer);
-
 };
-
-
-
-//------------------------------------------------------------------------------
-// INLINE FUNCTIONS
-//------------------------------------------------------------------------------
-
-
-
-//------------------------------------------------------------------------------
-// FREE OPERATORS
-//------------------------------------------------------------------------------
-
-
-
-//------------------------------------------------------------------------------
-// FREE FUNCTIONS
-//------------------------------------------------------------------------------
-
-
-
 // } // namespace
 
 #endif
diff --git a/frmts/pcraster/pcrasterutil.cpp b/frmts/pcraster/pcrasterutil.cpp
index 802c711..45ebc91 100644
--- a/frmts/pcraster/pcrasterutil.cpp
+++ b/frmts/pcraster/pcrasterutil.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pcrasterutil.cpp 28862 2015-04-07 10:10:25Z kdejong $
+ * $Id: pcrasterutil.cpp 32957 2016-01-12 18:53:43Z rouault $
  *
  * Project:  PCRaster Integration
  * Purpose:  PCRaster driver support functions.
@@ -27,31 +27,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef INCLUDED_IOSTREAM
-#include <iostream>
-#define INCLUDED_IOSTREAM
-#endif
+#include <cfloat>
 
-#ifndef INCLUDED_ALGORITHM
 #include <algorithm>
-#define INCLUDED_ALGORITHM
-#endif
 
-#ifndef INCLUDED_FLOAT
-#include <float.h>
-#define INCLUDED_FLOAT
-#endif
-
-#ifndef INCLUDED_PCRTYPES
-#include "pcrtypes.h"
-#define INCLUDED_PCRTYPES
-#endif
-
-#ifndef INCLUDED_PCRASTERUTIL
 #include "pcrasterutil.h"
-#define INCLUDED_PCRASTERUTIL
-#endif
-
+#include "pcrtypes.h"
 
 
 //! Converts PCRaster data type to GDAL data type.
@@ -108,7 +89,6 @@ GDALDataType cellRepresentation2GDALType(
 }
 
 
-
 CSF_VS string2ValueScale(
          std::string const& string)
 {
@@ -148,7 +128,6 @@ CSF_VS string2ValueScale(
 }
 
 
-
 std::string valueScale2String(
          CSF_VS valueScale)
 {
@@ -202,7 +181,6 @@ std::string valueScale2String(
 }
 
 
-
 std::string cellRepresentation2String(
          CSF_CR cellRepresentation)
 {
@@ -253,7 +231,6 @@ std::string cellRepresentation2String(
 }
 
 
-
 //! Converts GDAL data type to PCRaster value scale.
 /*!
   \param     type GDAL data type.
@@ -303,7 +280,6 @@ CSF_VS GDALType2ValueScale(
 }
 
 
-
 //! Converts a GDAL type to a PCRaster cell representation.
 /*!
   \param     type GDAL type.
@@ -364,7 +340,6 @@ CSF_CR GDALType2CellRepresentation(
 }
 
 
-
 //! Determines a missing value to use for data of \a cellRepresentation.
 /*!
   \param     cellRepresentation Cell representation of the data.
@@ -420,7 +395,8 @@ double missingValue(
       break;
     }
     default: {
-      CPLAssert(false);
+      CPLError(CE_Failure, CPLE_NotSupported,
+               "Unexpected value for cellRepresentation = %d", cellRepresentation);
       break;
     }
   }
@@ -429,7 +405,6 @@ double missingValue(
 }
 
 
-
 //! Opens the raster in \a filename using mode \a mode.
 /*!
   \param     filename Filename of raster to open.
@@ -448,7 +423,6 @@ MAP* mapOpen(
 }
 
 
-
 void alterFromStdMV(
          void* buffer,
          size_t size,
@@ -514,7 +488,6 @@ void alterFromStdMV(
 }
 
 
-
 void alterToStdMV(
          void* buffer,
          size_t size,
@@ -580,7 +553,6 @@ void alterToStdMV(
 }
 
 
-
 CSF_VS fitValueScale(
          CSF_VS valueScale,
          CSF_CR cellRepresentation)
@@ -648,7 +620,6 @@ CSF_VS fitValueScale(
 }
 
 
-
 void castValuesToBooleanRange(
          void* buffer,
          size_t size,
@@ -713,7 +684,6 @@ void castValuesToBooleanRange(
 }
 
 
-
 void castValuesToDirectionRange(
          void* buffer,
          size_t size)
@@ -724,7 +694,6 @@ void castValuesToDirectionRange(
 }
 
 
-
 void castValuesToLddRange(
          void* buffer,
          size_t size)
@@ -732,4 +701,4 @@ void castValuesToLddRange(
   std::for_each(static_cast<UINT1*>(buffer),
        static_cast<UINT1*>(buffer) + size,
        CastToLdd());
-}
\ No newline at end of file
+}
diff --git a/frmts/pcraster/pcrasterutil.h b/frmts/pcraster/pcrasterutil.h
index 6ad55e6..fefeeee 100644
--- a/frmts/pcraster/pcrasterutil.h
+++ b/frmts/pcraster/pcrasterutil.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pcrasterutil.h 28862 2015-04-07 10:10:25Z kdejong $
+ * $Id: pcrasterutil.h 31687 2015-11-21 16:35:21Z rouault $
  *
  * Project:  PCRaster Integration
  * Purpose:  PCRaster driver support declarations.
@@ -27,28 +27,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-// Library headers.
-#ifndef INCLUDED_STRING
-#include <string>
-#define INCLUDED_STRING
-#endif
+#ifndef INCLUDED_PCRASTERUTIL
+#define INCLUDED_PCRASTERUTIL
 
-// PCRaster library headers.
-#ifndef INCLUDED_CSF
 #include "csf.h"
-#define INCLUDED_CSF
-#endif
-
-#ifndef INCLUDED_PCRTYPES
-#include "pcrtypes.h"
-#define INCLUDED_PCRTYPES
-#endif
-
-// Module headers.
-#ifndef INCLUDED_GDAL_PRIV
 #include "gdal_priv.h"
-#define INCLUDED_GDAL_PRIV
-#endif
+#include "pcrtypes.h"
 
 
 GDALDataType       cellRepresentation2GDALType(CSF_CR cellRepresentation);
@@ -124,7 +108,6 @@ struct CastToBooleanRange
 };
 
 
-
 template<>
 struct CastToBooleanRange<UINT1>
 {
@@ -136,7 +119,6 @@ struct CastToBooleanRange<UINT1>
 };
 
 
-
 template<>
 struct CastToBooleanRange<UINT2>
 {
@@ -148,7 +130,6 @@ struct CastToBooleanRange<UINT2>
 };
 
 
-
 template<>
 struct CastToBooleanRange<UINT4>
 {
@@ -163,7 +144,7 @@ struct CastToBooleanRange<UINT4>
 struct CastToDirection
 {
   void operator()(REAL4& value) {
-    REAL4 factor = M_PI / 180.0;
+    REAL4 factor = static_cast<REAL4>(M_PI / 180.0);
     if(!pcr::isMV(value)) {
       value = REAL4(value * factor);
     }
@@ -171,7 +152,6 @@ struct CastToDirection
 };
 
 
-
 struct CastToLdd
 {
   void operator()(UINT1& value) {
@@ -186,4 +166,6 @@ struct CastToLdd
       }
     }
   }
-};
\ No newline at end of file
+};
+
+#endif  // INCLUDED_PCRASTERUTIL
diff --git a/frmts/pdf/GNUmakefile b/frmts/pdf/GNUmakefile
index 208632c..f5b7f41 100644
--- a/frmts/pdf/GNUmakefile
+++ b/frmts/pdf/GNUmakefile
@@ -2,6 +2,15 @@ include ../../GDALmake.opt
 
 OBJ	=	pdfdataset.o pdfio.o pdfobject.o pdfcreatecopy.o ogrpdflayer.o pdfwritabledataset.o pdfreadvectors.o
 
+PLUGIN_DL =	gdal_PDF.so
+
+ifeq ($(MACOSX_FRAMEWORK),yes)
+PLUGIN_DL = gdal_PDF.dylib
+LDFLAGS += -Wl,-undefined -Wl,dynamic_lookup -stdlib=libstdc++
+CPPFLAGS += -stdlib=libstdc++
+LD_SHARED = $(LD) -bundle
+endif
+
 ifeq ($(HAVE_POPPLER),yes)
 CPPFLAGS +=  -DHAVE_POPPLER
 endif
@@ -26,13 +35,23 @@ ifeq ($(HAVE_PODOFO),yes)
 CPPFLAGS +=  -DHAVE_PODOFO
 endif
 
-$(O_OBJ):       pdfobject.h pdfio.h pdfcreatecopy.h gdal_pdf.h
+ifeq ($(HAVE_PDFIUM),yes)
+CPPFLAGS +=  -DHAVE_PDFIUM
+endif
 
-CPPFLAGS	:=	 $(CPPFLAGS) -I../vrt -I../mem -I../../ogr/ogrsf_frmts/mem $(POPPLER_INC) $(PODOFO_INC)
+$(O_OBJ):       pdfobject.h pdfio.h pdfcreatecopy.h gdal_pdf.h ../../ogr/ogrsf_frmts/mem/ogr_mem.h
+
+CPPFLAGS	:=	 -I../vrt -I../mem -I../../ogr/ogrsf_frmts/mem $(CPPFLAGS) $(POPPLER_INC) $(PODOFO_INC) $(PDFIUM_INC)
 
 default:	$(OBJ:.o=.$(OBJ_EXT))
 
 clean:
 	rm -f *.o $(O_OBJ)
+	rm -f $(PLUGIN_DL)
 
 install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+plugin: $(PLUGIN_DL)
+
+$(PLUGIN_DL):  $(OBJ)
+	$(LD_SHARED) $(OBJ) ../../ogr/ogrsf_frmts/o/ogrmemdatasource.o ../../ogr/ogrsf_frmts/o/ogrmemdriver.o ../../ogr/ogrsf_frmts/o/ogrmemlayer.o $(LDFLAGS) $(CONFIG_LIBS) -o $(PLUGIN_DL) $(PDFIUM_PLUGIN_LIB) $(POPPLER_PLUGIN_LIB) $(PODOFO_PLUGIN_LIB)
diff --git a/frmts/pdf/frmt_pdf.html b/frmts/pdf/frmt_pdf.html
index 70d3d9b..2dc3ac4 100644
--- a/frmts/pdf/frmt_pdf.html
+++ b/frmts/pdf/frmt_pdf.html
@@ -16,38 +16,16 @@ Non-geospatial PDF documents will also be recognized by the driver.
 Starting with GDAL >= 1.10.0, PDF documents can be created from other GDAL raster datasets, and OGR datasources can
 also optionally be drawn on top of the raster layer (see OGR_* creation options in the below section).
 <p>
-GDAL must be compiled with libpoppler support (GPL-licensed), and libpoppler itself must have been configured with
---enable-xpdf-headers so that the xpdf C++ headers are available. Note: the poppler C++ API isn't
-stable, so the driver compilation may fail with too old or too recent poppler versions.
-Successfully tested versions are poppler >= 0.12.X and <= 0.26.0.
-<p>
-Starting with GDAL 1.9.0, as an alternative, the PDF driver can be compiled against libpodofo (LGPL-licensed)
-to avoid the libpoppler dependency. This is sufficient to get the georeferencing and vector information. However, for
-getting the imagery, the pdftoppm utility that comes with the poppler distribution must be available in the system PATH.
-A temporary file will be generated in a directory determined by the following configuration options : CPL_TMPDIR,
-TMPDIR or TEMP (in that order). If none are defined, the current directory will be used.
-Successfully tested versions are libpodofo 0.8.4 and 0.9.1.
-<p>
 The driver supports reading georeferencing encoded in either of the 2 current existing ways : according to the OGC
 encoding best practice, or according to the Adobe Supplement to ISO 32000.
 <p>
 Multipage documents are exposed as subdatasets, one subdataset par page of the document.
-<p>
-The neatline (for OGC best practice) or the bounding box (Adobe style) will be reported as a NEATLINE metadata item,
-so that it can be later used as a cutline for the warping algorithm.
-<p>
-Starting with GDAL 1.9.0, XMP metadata can be extracted from the file, and will be
-stored as XML raw content in the xml:XMP metadata domain.
-<p>
-Starting with GDAL 1.10.0, additional metadata, such as found in USGS Topo PDF can be extracted from the file, and will be
-stored as XML raw content in the EMBEDDED_METADATA metadata domain.
-<p>
 
 <h2>Vector support</h2>
 
 <p>
 Starting with GDAL 1.10, this driver can read and write geospatial PDF with vector features.
-Vector read support requires linking to podofo or poppler libraries, but write support does not.
+Vector read support requires linking to one of the above mentioned dependent libraries, but write support does not.
 
 The driver can read vector features encoded according to PDF's logical structure facilities (as described by "§10.6 - Logical Structure" of PDF spec),
 or retrieve only vector geometries for other vector PDF files.<p>
@@ -86,6 +64,19 @@ Alpha values are supported for colors to control the opacity. If not specified,
 
 For SYMBOL with a bitmap name, only the alpha value of the color specified with 'c' is taken into account.<p>
 
+<h2>Metadata</h2>
+
+<p>
+The neatline (for OGC best practice) or the bounding box (Adobe style) will be reported as a NEATLINE metadata item,
+so that it can be later used as a cutline for the warping algorithm.
+<p>
+Starting with GDAL 1.9.0, XMP metadata can be extracted from the file, and will be
+stored as XML raw content in the xml:XMP metadata domain.
+<p>
+Starting with GDAL 1.10.0, additional metadata, such as found in USGS Topo PDF can be extracted from the file, and will be
+stored as XML raw content in the EMBEDDED_METADATA metadata domain.
+<p>
+
 <h2>Configuration options</h2>
 
 <ul>
@@ -96,26 +87,42 @@ from the raster images inside the PDF (in simple cases).</li>
 <li><i>GDAL_PDF_NEATLINE</i> : (GDAL >= 1.10.0 ) The name of the neatline to select (only available for geospatial PDF, encoded
 according to OGC Best Practice). This defaults to "Map Layers" for USGS Topo PDF. If not found, the neatline that
 covers the largest area.</li>
-
+<li><i>GDAL_USER_PWD</i> : User password for protected PDFs.</li>
 <p>
-Starting with GDAL >= 1.10.0 and when GDAL is compiled against libpoppler, the following options are also
-available :
+Starting with GDAL >= 1.10.0, the following options are also available :
 
 <li><i>GDAL_PDF_RENDERING_OPTIONS</i> : a combination of VECTOR, RASTER and TEXT separated
 by comma, to select whether vector, raster or text features should be rendered. If the option is not
-specified, all features are rendered.</li>
+specified, all features are rendered (Poppler and PDFium).</li>
 <li><i>GDAL_PDF_BANDS</i> = 3 or 4 : whether the PDF should be rendered as a RGB (3) or RGBA (4) image.
 Defaults to 3.</li>
 <li><i>GDAL_PDF_LAYERS</i> = list of layers (comma separated) to turn ON (or "ALL" to turn all layers ON).
 The layer names can be obtained by querying the LAYERS metadata domain. When this option is specified,
-layers not explicitly listed will be turned off.</li>
+layers not explicitly listed will be turned off (Poppler and PDFium).</li>
 <li><i>GDAL_PDF_LAYERS_OFF</i> = list of layers (comma separated) to turn OFF. The layer names can be obtained by
-querying the LAYERS metadata domain.</li>
+querying the LAYERS metadata domain (Poppler and PDFium).</li>
+</ul>
+
+<h3>Open Options</h3>
+
+Since GDAL 2.0, above configuration options are also available as open options.
+
+<ul>
+<li><p><b>RENDERING_OPTIONS</b>=[RASTER,VECTOR,TEXT / RASTER,VECTOR / RASTER,TEXT / RASTER / VECTOR,TEXT / VECTOR / TEXT]:
+same as GDAL_PDF_RENDERING_OPTIONS configuration option</p></li>
+<li><p><b>DPI</b>=value: same as GDAL_PDF_DPI configuration option</p></li>
+<li><p><b>USER_PWD</b>=password: same as GDAL_USER_PWD configuration option</p></li>
+<li><p><b>PDF_LIB</b>=[POPPLER/PODOFO/PDFIUM]: only available for builds with multiple backends.</p></li>
+<li><p><b>LAYERS</b>=string: list of layers (comma separated) to turn ON. Same as GDAL_PDF_LAYERS configuration option</p></li>
+<li><p><b>GDAL_PDF_LAYERS_OFF</b>=string: list of layers (comma separated) to turn OFF. Same as GDAL_PDF_LAYERS_OFF configuration option</p></li>
+<li><p><b>BANDS</b>=3 or 4. Same as GDAL_PDF_BANDS configuration option</p></li>
+<li><p><b>NEATLINE</b>=name of neatline. Same as GDAL_PDF_NEATLINE configuration option</p></li>
 </ul>
 
 <h2>LAYERS Metadata domain</h2>
 
-Starting with GDAL >= 1.10.0 and when GDAL is compiled against libpoppler, the LAYERS metadata domain can be queried
+Starting with GDAL >= 1.10.0 and when GDAL is compiled against Poppler or PDFium,
+the LAYERS metadata domain can be queried
 to retrieve layer names that can be turned ON or OFF. This is useful to know which values to specify for the
 <i>GDAL_PDF_LAYERS</i> or <i>GDAL_PDF_LAYERS_OFF</i> configuration options.<p>
 
@@ -141,11 +148,10 @@ $ gdal_translate ../autotest/gdrivers/data/adobe_style_geospatial.pdf out.tif --
 <h2>Restrictions</h2>
 
 The opening of a PDF document (to get the georeferencing) is fast, but at the first access to a raster block,
-the whole page will be rasterized, which can be a slow operation.
+the whole page will be rasterized (with Poppler), which can be a slow operation.
 <p>
 Note: starting with GDAL 1.10, some raster-only PDF files (such as some USGS GeoPDF files), that are regularly
-tiled are exposed as tiled dataset by the GDAL PDF driver, and can be rendered with either the Poppler or the
-Podofo backends.
+tiled are exposed as tiled dataset by the GDAL PDF driver, and can be rendered with any backends.
 <p>
 Only a few of the possible Datums available in the OGC best practice spec have been currently mapped
 in the driver. Unrecognized datums will be considered as being based on the WGS84 ellipsoid.
@@ -163,7 +169,7 @@ have 1 band (graylevel or with color table), 3 bands (RGB) or 4 bands (RGBA).</p
 the ISO32000 specification. It is also possible to write it according to the
 OGC Best Practice conventions (but limited to a few datum and projection types).</p>
 
-<p>Note: PDF write support does not require linking to poppler or podofo.</p>
+<p>Note: PDF write support does not require linking to any backend.</p>
 
 <h3>Creation Options</h3>
 
@@ -304,6 +310,70 @@ selected by setting the GDAL_PDF_GEO_ENCODING configuration option to OGC_BP.<p>
 Updated elements are written at the end of the file, following the incremental update method described in
 the PDF specification.<p>
 
+<h2>Build dependencies</h2>
+
+<p>For read support, GDAL must be built against one of the following libraries :
+<ul>
+<li><a href="http://poppler.freedesktop.org/">Poppler</a> (GPL-licensed)</li>
+<li><a href="http://podofo.sourceforge.net/">PoDoFo</a> (LGPL-licensed)</li>
+<li><a href="https://code.google.com/p/pdfium/">PDFium</a> (New BSD-licensed, supported since GDAL 2.1.0)</li>
+</ul>
+
+<p>Note: it is also possible to build against a combination of several of the
+above libraries. PDFium will be used in priority over Poppler, itself used in
+priority over PoDoFo.</p>
+
+<h3>Unix build</h3>
+<p>
+The relevant configure options are --with-poppler, --with-podofo, --with-podofo-lib
+and --with-podofo-extra-lib-for-test.
+</p>
+<p>
+Starting with GDAL 2.1.0, --with-pdfium, --with-pdfium-lib, --with-pdfium-extra-lib-for-test
+and --enable-pdf-plugin are also available.
+</p>
+
+<h3>Poppler</h3>
+<p>
+libpoppler itself must have been configured with
+--enable-xpdf-headers so that the xpdf C++ headers are available. Note: the poppler C++ API isn't
+stable, so the driver compilation may fail with too old or too recent poppler versions.
+Successfully tested versions are poppler >= 0.12.X and <= 0.31.0.
+</p>
+
+<h3>PoDoFo</h3>
+<p>
+As a partial alternative, the PDF driver can be compiled against libpodofo
+to avoid the libpoppler dependency. This is sufficient to get the georeferencing and vector information. However, for
+getting the imagery, the pdftoppm utility that comes with the poppler distribution must be available in the system PATH.
+A temporary file will be generated in a directory determined by the following configuration options : CPL_TMPDIR,
+TMPDIR or TEMP (in that order). If none are defined, the current directory will be used.
+Successfully tested versions are libpodofo 0.8.4, 0.9.1 and 0.9.3. Important note: using PoDoFo 0.9.0 is strongly discouraged,
+as it could cause crashes in GDAL due to a bug in PoDoFo.
+</p>
+
+<h3>PDFium (GDAL > 2.1.0)</h3>
+<p>
+Using PDFium as a backend allows access to raster, vector, georeferencing and other metadata.
+The PDFium backend has also support for arbitrary overviews, for fast zoom-out.
+</p>
+<p>
+Only GDAL builds against static builds of PDFium have been tested. Building PDFium
+can be challenging. A <a href="https://github.com/rouault/pdfium">PDFium forked version for simpler builds</a>
+is available (for Windows, a dedicated <a href="https://github.com/rouault/pdfium/tree/win_gdal_build">win_gdal_build</a>
+branch is recommended).
+A <a href="https://github.com/rouault/pdfium/tree/build">build repository</a> is available
+with a few scripts that can be used as a template to build PDFium for Linux/MacOSX/Windows.
+Those forked versions remove the dependency to the V8 JavaScript engine,
+and have also a few changes to avoid symbol clashes, on Linux, with libjpeg and libopenjpeg.
+Building the PDF driver as a GDAL plugin is also a way of avoiding such issues.
+PDFium build requires a C++11 compatible compiler, as well as for building GDAL itself
+against PDFium. Successfully tested versions are GCC 4.7.0
+(previous versions aren't compatible) and Visual Studio 12 / VS2013.
+</p>
+
+</p>
+
 <h2>Examples</h2>
 
 <ul>
@@ -335,7 +405,7 @@ if (button == 4) app.launchURL('http://gdal.org/');
 Specifications :
 
 <ul>
-<li><a href="ogr/ogr_feature_style.html">OGR Feature Style Specification</a></li>
+<li><a href="ogr_feature_style.html">OGR Feature Style Specification</a></li>
 <li><a href="http://portal.opengeospatial.org/files/?artifact_id=40537">OGC GeoPDF Encoding Best Practice Version 2.2 (08-139r3)</a></li>
 <li><a href="http://www.adobe.com/devnet/acrobat/pdfs/adobe_supplement_iso32000.pdf">Adobe Supplement to ISO 32000</a></li>
 <li><a href="http://www.adobe.com/devnet/acrobat/pdfs/pdf_reference_1-7.pdf">PDF Reference, version 1.7</a></li>
@@ -348,6 +418,8 @@ Libraries :
 <ul>
 <li><a href="http://poppler.freedesktop.org/">Poppler homepage</a></li>
 <li><a href="http://podofo.sourceforge.net/">PoDoFo homepage</a></li>
+<li><a href="https://code.google.com/p/pdfium/">PDFium homepage</a></li>
+<li><a href="https://github.com/rouault/pdfium">PDFium forked version for simpler builds</a></li>
 </ul>
 
 <p>
diff --git a/frmts/pdf/gdal_pdf.h b/frmts/pdf/gdal_pdf.h
index 10cc9b1..c9ec186 100644
--- a/frmts/pdf/gdal_pdf.h
+++ b/frmts/pdf/gdal_pdf.h
@@ -6,6 +6,13 @@
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
+ *
+ * Support for open-source PDFium library
+ *
+ * Copyright (C) 2015 Klokan Technologies GmbH (http://www.klokantech.com/)
+ * Author: Martin Mikita <martin.mikita at klokantech.com>, xmikit00 @ FIT VUT Brno
+ *
+ ******************************************************************************
  * Copyright (c) 2010-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -27,18 +34,10 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _GDAL_PDF_H_INCLUDED
-#define _GDAL_PDF_H_INCLUDED
-
-#ifdef HAVE_POPPLER
-
-/* hack for PDF driver and poppler >= 0.15.0 that defines incompatible "typedef bool GBool" */
-/* in include/poppler/goo/gtypes.h with the one defined in cpl_port.h */
-#define CPL_GBOOL_DEFINED
-#define OGR_FEATURESTYLE_INCLUDE
+#ifndef GDAL_PDF_H_INCLUDED
+#define GDAL_PDF_H_INCLUDED
 
-#include <goo/gtypes.h>
-#endif
+#include "pdfsdk_headers.h"
 
 #include "gdal_pam.h"
 #include "ogrsf_frmts.h"
@@ -48,12 +47,18 @@
 
 #include <map>
 #include <stack>
+#include <bitset>   // For detecting usage of PDF library
+
+#define     PDFLIB_POPPLER    0
+#define     PDFLIB_PODOFO     1
+#define     PDFLIB_PDFIUM     2
+#define     PDFLIB_COUNT      3
 
 /************************************************************************/
 /*                             OGRPDFLayer                              */
 /************************************************************************/
 
-#if defined(HAVE_POPPLER) || defined(HAVE_PODOFO)
+#if defined(HAVE_POPPLER) || defined(HAVE_PODOFO) || defined(HAVE_PDFIUM)
 
 class PDFDataset;
 
@@ -109,6 +114,45 @@ typedef struct
     int            nBands;
 } GDALPDFTileDesc;
 
+#ifdef HAVE_PDFIUM
+/**
+ * Structures for Document and Document's Page for PDFium library,
+ *  which does not support multi-threading.
+ * Structures keeps objects for PDFium library and exclusive mutex locks
+ *  for one-per-time access of PDFium library methods with multi-threading GDAL
+ * Structures also keeps only one object per each opened PDF document
+ *  - this saves time for opening and memory for opened objects
+ * Document is closed after closing all pages object.
+ */
+
+/************************************************************************/
+/*                           TPdfiumPageStruct                          */
+/************************************************************************/
+
+// Map of Pdfium pages in following structure
+typedef struct {
+  int pageNum;
+  CPDF_Page* page;
+  CPLMutex * readMutex;
+  int sharedNum;
+} TPdfiumPageStruct;
+
+typedef std::map<int, TPdfiumPageStruct*>        TMapPdfiumPages;
+
+/************************************************************************/
+/*                         TPdfiumDocumentStruct                        */
+/************************************************************************/
+
+// Structure for Mutex on File
+typedef struct {
+  char* filename;
+  CPDF_Document* doc;
+  TMapPdfiumPages pages;
+  FPDF_FILEACCESS* psFileAccess;
+} TPdfiumDocumentStruct;
+
+#endif  // ~ HAVE_PDFIUM
+
 /************************************************************************/
 /* ==================================================================== */
 /*                              PDFDataset                              */
@@ -125,13 +169,15 @@ class ObjectAutoFree;
 #define MAX_TOKEN_SIZE 256
 #define TOKEN_STACK_SIZE 8
 
-#if defined(HAVE_POPPLER) || defined(HAVE_PODOFO)
+#if defined(HAVE_POPPLER) || defined(HAVE_PODOFO) || defined(HAVE_PDFIUM)
 
 class PDFDataset : public GDALPamDataset
 {
     friend class PDFRasterBand;
     friend class PDFImageRasterBand;
 
+    PDFDataset*  poParentDS;
+
     CPLString    osFilename;
     CPLString    osUserPwd;
     char        *pszWKT;
@@ -149,7 +195,7 @@ class PDFDataset : public GDALPamDataset
     int          bInfoDirty;
     int          bXMPDirty;
 
-    int          bUsePoppler;
+    std::bitset<PDFLIB_COUNT> bUseLib;
 #ifdef HAVE_POPPLER
     PDFDoc*      poDocPoppler;
 #endif
@@ -157,6 +203,11 @@ class PDFDataset : public GDALPamDataset
     PoDoFo::PdfMemDocument* poDocPodofo;
     int          bPdfToPpmFailed;
 #endif
+#ifdef HAVE_PDFIUM
+    TPdfiumDocumentStruct*  poDocPdfium;
+    TPdfiumPageStruct*      poPagePdfium;
+    std::vector<PDFDataset*> apoOvrDS, apoOvrDSBackup;
+#endif
     GDALPDFObject* poPageObj;
 
     int          iPage;
@@ -195,15 +246,41 @@ class PDFDataset : public GDALPamDataset
     GDALPDFObject* poCatalogObject;
     GDALPDFObject* GetCatalog();
 
-#ifdef HAVE_POPPLER
-    void         AddLayer(const char* pszLayerName, OptionalContentGroup* ocg);
-    void         ExploreLayers(GDALPDFArray* poArray, int nRecLevel, CPLString osTopLayer = "");
-    void         FindLayers();
-    void         TurnLayersOnOff();
-    CPLStringList osLayerList;
-    std::map<CPLString, OptionalContentGroup*> oLayerOCGMap;
+#if defined(HAVE_POPPLER) || defined(HAVE_PDFIUM)
+    void         AddLayer(const char* pszLayerName);
+#endif
+
+#if defined(HAVE_POPPLER)
+    void         ExploreLayersPoppler(GDALPDFArray* poArray, int nRecLevel, CPLString osTopLayer = "");
+    void         FindLayersPoppler();
+    void         TurnLayersOnOffPoppler();
+    std::map<CPLString, OptionalContentGroup*> oLayerOCGMapPoppler;
 #endif
 
+#ifdef HAVE_PDFIUM
+    void         ExploreLayersPdfium(GDALPDFArray* poArray, int nRecLevel, CPLString osTopLayer = "");
+    void         FindLayersPdfium();
+    void         PDFiumRenderPageBitmap(FPDF_BITMAP bitmap, FPDF_PAGE page, int start_x, int start_y,
+                                        int size_x, int size_y, const char* pszRenderingOptions);
+    void         TurnLayersOnOffPdfium();
+
+public:
+    typedef enum
+    {
+        VISIBILITY_DEFAULT,
+        VISIBILITY_ON,
+        VISIBILITY_OFF
+    } VisibilityState;
+
+    VisibilityState GetVisibilityStateForOGCPdfium(int nNum, int nGen);
+
+private:
+    std::map< CPLString, std::pair<int,int> > oMapLayerNameToOCGNumGenPdfium;
+    std::map< std::pair<int,int>, VisibilityState > oMapOCGNumGenToVisibilityStatePdfium;
+#endif
+
+    CPLStringList osLayerList;
+
     CPLStringList osLayerWithRefList;
     CPLString     FindLayerOCG(GDALPDFDictionary* poPageDict,
                                const char* pszLayerName);
@@ -230,7 +307,7 @@ class PDFDataset : public GDALPamDataset
 
     std::map<CPLString, int> oMapOperators;
     void                InitMapOperators();
-    
+
     int                 bSetStyle;
 
     void                ExploreTree(GDALPDFObject* poObj, int nRecLevel);
@@ -258,8 +335,12 @@ class PDFDataset : public GDALPamDataset
 
     int                 OpenVectorLayers(GDALPDFDictionary* poPageDict);
 
+#ifdef HAVE_PDFIUM
+    void    InitOverviews();
+#endif  // ~ HAVE_PDFIUM
+
   public:
-                 PDFDataset();
+                 PDFDataset(PDFDataset* poParentDS = NULL, int nXSize = 0, int nYSize = 0);
     virtual     ~PDFDataset();
 
     virtual const char* GetProjectionRef();
@@ -307,6 +388,13 @@ class PDFDataset : public GDALPamDataset
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int          Identify( GDALOpenInfo * );
+
+#ifdef HAVE_PDFIUM
+    virtual CPLErr IBuildOverviews( const char *, int, int *,
+                                    int, int *, GDALProgressFunc, void * );
+
+    static int bPdfiumInit;
+#endif
 };
 
 /************************************************************************/
@@ -319,17 +407,32 @@ class PDFRasterBand : public GDALPamRasterBand
 {
     friend class PDFDataset;
 
+    int   nResolutionLevel;
+
     CPLErr IReadBlockFromTile( int, int, void * );
 
   public:
 
-                PDFRasterBand( PDFDataset *, int );
+                PDFRasterBand( PDFDataset *, int, int );
+                ~PDFRasterBand();
+
+#ifdef HAVE_PDFIUM
+    virtual int    GetOverviewCount();
+    virtual GDALRasterBand *GetOverview( int );
+#endif  // ~ HAVE_PDFIUM
 
     virtual CPLErr IReadBlock( int, int, void * );
     virtual GDALColorInterp GetColorInterpretation();
+
+#ifdef notdef
+    virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
+                              void *, int, int, GDALDataType,
+                              GSpacing nPixelSpace, GSpacing nLineSpace,
+                              GDALRasterIOExtraArg* psExtraArg);
+#endif
 };
 
-#endif /*  defined(HAVE_POPPLER) || defined(HAVE_PODOFO) */
+#endif /*  defined(HAVE_POPPLER) || defined(HAVE_PODOFO)|| defined(HAVE_PDFIUM) */
 
 /************************************************************************/
 /*                          PDFWritableDataset                          */
@@ -370,4 +473,4 @@ class PDFWritableVectorDataset : public GDALDataset
 GDALDataset* GDALPDFOpen(const char* pszFilename, GDALAccess eAccess);
 CPLString PDFSanitizeLayerName(const char* pszName);
 
-#endif /* ndef _GDAL_PDF_H_INCLUDED */
+#endif /* ndef GDAL_PDF_H_INCLUDED */
diff --git a/frmts/pdf/makefile.vc b/frmts/pdf/makefile.vc
index fbca18f..92d7b44 100644
--- a/frmts/pdf/makefile.vc
+++ b/frmts/pdf/makefile.vc
@@ -11,7 +11,7 @@ GDAL_ROOT	=	..\..
 OBJ = $(OBJ) ..\..\ogr\ogrsf_frmts\mem\ogrmemdatasource.obj ..\..\ogr\ogrsf_frmts\mem\ogrmemdriver.obj ..\..\ogr\ogrsf_frmts\mem\ogrmemlayer.obj
 !ENDIF
 
-EXTRAFLAGS =  -I..\vrt -I..\mem -I..\..\ogr\ogrsf_frmts\mem $(POPPLER_EXTRAFLAGS) $(PODOFO_EXTRAFLAGS)
+EXTRAFLAGS =  -I..\vrt -I..\mem -I..\..\ogr\ogrsf_frmts\mem $(POPPLER_EXTRAFLAGS) $(PODOFO_EXTRAFLAGS) $(PDFIUM_EXTRAFLAGS)
 
 !IFDEF POPPLER_ENABLED
 POPPLER_EXTRAFLAGS = $(POPPLER_CFLAGS) $(POPPLER_HAS_OPTCONTENT_FLAGS) $(POPPLER_BASE_STREAM_HAS_TWO_ARGS_FLAGS) $(POPPLER_0_20_OR_LATER_FLAGS) $(POPPLER_0_23_OR_LATER_FLAGS) -DHAVE_POPPLER
@@ -38,6 +38,10 @@ POPPLER_0_23_OR_LATER_FLAGS = -DPOPPLER_0_23_OR_LATER
 PODOFO_EXTRAFLAGS = $(PODOFO_CFLAGS) -DHAVE_PODOFO
 !ENDIF
 
+!IFDEF PDFIUM_ENABLED
+PDFIUM_EXTRAFLAGS = $(PDFIUM_CFLAGS) -DHAVE_PDFIUM -DNOMINMAX /wd4512
+!ENDIF
+
 default:	$(OBJ)
 	xcopy /D  /Y *.obj ..\o
 
@@ -47,9 +51,9 @@ clean:
 plugin:	$(PLUGIN_DLL)
 
 $(PLUGIN_DLL): $(OBJ)
-	link /dll $(LDEBUG) /out:$(PLUGIN_DLL) $(OBJ) $(GDALLIB) $(POPPLER_LIBS) $(PODOFO_LIBS)
+	link /dll $(LDEBUG) /out:$(PLUGIN_DLL) $(OBJ) $(GDALLIB) $(POPPLER_LIBS) $(PODOFO_LIBS) $(PDFIUM_LIBS)
 	if exist $(PLUGIN_DLL).manifest mt -manifest $(PLUGIN_DLL).manifest -outputresource:$(PLUGIN_DLL);2
 
 plugin-install:
 	-mkdir $(PLUGINDIR)
-	$(INSTALL) $(PLUGIN_DLL) $(PLUGINDIR)
\ No newline at end of file
+	$(INSTALL) $(PLUGIN_DLL) $(PLUGINDIR)
diff --git a/frmts/pdf/ogrpdflayer.cpp b/frmts/pdf/ogrpdflayer.cpp
index 263494f..86c44a3 100644
--- a/frmts/pdf/ogrpdflayer.cpp
+++ b/frmts/pdf/ogrpdflayer.cpp
@@ -31,19 +31,19 @@
 
 CPL_CVSID("$Id$");
 
-#if defined(HAVE_POPPLER) || defined(HAVE_PODOFO)
+#if defined(HAVE_POPPLER) || defined(HAVE_PODOFO) || defined(HAVE_PDFIUM)
 
 /************************************************************************/
 /*                            OGRPDFLayer()                             */
 /************************************************************************/
 
-OGRPDFLayer::OGRPDFLayer( PDFDataset* poDS,
+OGRPDFLayer::OGRPDFLayer( PDFDataset* poDSIn,
                           const char * pszName,
                           OGRSpatialReference *poSRS,
                           OGRwkbGeometryType eGeomType ) :
                                 OGRMemLayer(pszName, poSRS, eGeomType )
 {
-    this->poDS = poDS;
+    this->poDS = poDSIn;
     bGeomTypeSet = FALSE;
     bGeomTypeMixed = FALSE;
 }
@@ -170,19 +170,19 @@ int OGRPDFLayer::TestCapability( const char * pszCap )
         return OGRMemLayer::TestCapability(pszCap);
 }
 
-#endif /* defined(HAVE_POPPLER) || defined(HAVE_PODOFO) */
+#endif /* defined(HAVE_POPPLER) || defined(HAVE_PODOFO) || defined(HAVE_PDFIUM) */
 
 /************************************************************************/
 /*                        OGRPDFWritableLayer()                         */
 /************************************************************************/
 
-OGRPDFWritableLayer::OGRPDFWritableLayer( PDFWritableVectorDataset* poDS,
+OGRPDFWritableLayer::OGRPDFWritableLayer( PDFWritableVectorDataset* poDSIn,
                           const char * pszName,
                           OGRSpatialReference *poSRS,
                           OGRwkbGeometryType eGeomType ) :
                                 OGRMemLayer(pszName, poSRS, eGeomType )
 {
-    this->poDS = poDS;
+    this->poDS = poDSIn;
 }
 
 /************************************************************************/
diff --git a/frmts/pdf/pdfcreatecopy.cpp b/frmts/pdf/pdfcreatecopy.cpp
index 773b8e9..3215ec3 100644
--- a/frmts/pdf/pdfcreatecopy.cpp
+++ b/frmts/pdf/pdfcreatecopy.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pdfcreatecopy.cpp 28780 2015-03-26 12:29:35Z rouault $
+ * $Id: pdfcreatecopy.cpp 33757 2016-03-20 20:22:33Z goatbar $
  *
  * Project:  PDF driver
  * Purpose:  GDALDataset driver for PDF dataset.
@@ -39,14 +39,10 @@
 
 #include "pdfobject.h"
 
-#ifndef M_PI
-#define M_PI       3.14159265358979323846
-#endif
-
 /* Cf PDF reference v1.7, Appendix C, page 993 */
 #define MAXIMUM_SIZE_IN_UNITS   14400
 
-CPL_CVSID("$Id: pdfcreatecopy.cpp 28780 2015-03-26 12:29:35Z rouault $");
+CPL_CVSID("$Id: pdfcreatecopy.cpp 33757 2016-03-20 20:22:33Z goatbar $");
 
 #define PIXEL_TO_GEO_X(x,y) adfGeoTransform[0] + x * adfGeoTransform[1] + y * adfGeoTransform[2]
 #define PIXEL_TO_GEO_Y(x,y) adfGeoTransform[3] + x * adfGeoTransform[4] + y * adfGeoTransform[5]
@@ -161,7 +157,7 @@ int GDALPDFWriter::ParseTrailerAndXRef()
     int i;
     for(i = nRead - 9; i>= 0; i --)
     {
-        if (strncmp(szBuf + i, "startxref", 9) == 0)
+        if (STARTS_WITH(szBuf + i, "startxref"))
         {
             pszStartXRef = szBuf + i;
             break;
@@ -190,7 +186,7 @@ int GDALPDFWriter::ParseTrailerAndXRef()
     const char* pszLine;
     while( (pszLine = CPLReadLineL(fp)) != NULL)
     {
-        if (strncmp(pszLine, "trailer", 7) == 0)
+        if (STARTS_WITH(pszLine, "trailer"))
             break;
     }
 
@@ -657,24 +653,24 @@ int  GDALPDFWriter::WriteSRS_ISO32000(GDALDataset* poSrcDS,
                      "GCPs should form a rectangle in pixel space");
             return 0;
         }
-        
+
         dfULPixel = pasGCPList[iUL].dfGCPPixel;
         dfULLine = pasGCPList[iUL].dfGCPLine;
         dfLRPixel = pasGCPList[iLR].dfGCPPixel;
         dfLRLine = pasGCPList[iLR].dfGCPLine;
-        
+
         /* Upper-left */
         adfGPTS[0] = pasGCPList[iUL].dfGCPX;
         adfGPTS[1] = pasGCPList[iUL].dfGCPY;
-        
+
         /* Lower-left */
         adfGPTS[2] = pasGCPList[iLL].dfGCPX;
         adfGPTS[3] = pasGCPList[iLL].dfGCPY;
-        
+
         /* Lower-right */
         adfGPTS[4] = pasGCPList[iLR].dfGCPX;
         adfGPTS[5] = pasGCPList[iLR].dfGCPY;
-        
+
         /* Upper-right */
         adfGPTS[6] = pasGCPList[iUR].dfGCPX;
         adfGPTS[7] = pasGCPList[iUR].dfGCPY;
@@ -697,7 +693,7 @@ int  GDALPDFWriter::WriteSRS_ISO32000(GDALDataset* poSrcDS,
         adfGPTS[6] = PIXEL_TO_GEO_X(nWidth, 0);
         adfGPTS[7] = PIXEL_TO_GEO_Y(nWidth, 0);
     }
-    
+
     OGRSpatialReferenceH hSRS = OSRNewSpatialReference(pszWKT);
     if( hSRS == NULL )
         return 0;
@@ -716,7 +712,7 @@ int  GDALPDFWriter::WriteSRS_ISO32000(GDALDataset* poSrcDS,
     }
 
     int bSuccess = TRUE;
-    
+
     bSuccess &= (OCTTransform( hCT, 1, adfGPTS + 0, adfGPTS + 1, NULL ) == 1);
     bSuccess &= (OCTTransform( hCT, 1, adfGPTS + 2, adfGPTS + 3, NULL ) == 1);
     bSuccess &= (OCTTransform( hCT, 1, adfGPTS + 4, adfGPTS + 5, NULL ) == 1);
@@ -855,8 +851,8 @@ static GDALPDFObject* GDALPDFBuildOGC_BP_Datum(const OGRSpatialReference* poSRS)
             {
                 poPDFDatumDict->Add("Description", pszDatumDescription);
 
-                const char* pszEllipsoidCode = NULL;
 #ifdef disabled_because_terrago_toolbar_does_not_like_it
+                const char* pszEllipsoidCode = NULL;
                 if( ABS(dfSemiMajor-6378249.145) < 0.01
                     && ABS(dfInvFlattening-293.465) < 0.0001 )
                 {
@@ -951,13 +947,13 @@ static GDALPDFObject* GDALPDFBuildOGC_BP_Datum(const OGRSpatialReference* poSRS)
                 {
                     pszEllipsoidCode = "WE";
                 }
-#endif
 
                 if( pszEllipsoidCode != NULL )
                 {
                     poPDFDatumDict->Add("Ellipsoid", pszEllipsoidCode);
                 }
                 else
+#endif /* disabled_because_terrago_toolbar_does_not_like_it */
                 {
                     const char* pszEllipsoidDescription =
                         poSpheroidNode->GetChild(0)->GetValue();
@@ -1193,7 +1189,7 @@ int GDALPDFWriter::WriteSRS_OGC_BP(GDALDataset* poSrcDS,
 
     if( pszWKT == NULL || EQUAL(pszWKT, "") )
         return 0;
-    
+
     if( !bHasGT )
     {
         if (!GDALGCPsToGeoTransform( nGCPCount, pasGCPList,
@@ -1360,14 +1356,14 @@ int GDALPDFWriter::WriteSRS_OGC_BP(GDALDataset* poSrcDS,
     oLGIDict.Add("Projection", poProjectionDict);
 
     /* GDAL extension */
-    if( CSLTestBoolean( CPLGetConfigOption("GDAL_PDF_OGC_BP_WRITE_WKT", "TRUE") ) )
+    if( CPLTestBool( CPLGetConfigOption("GDAL_PDF_OGC_BP_WRITE_WKT", "TRUE") ) )
         poProjectionDict->Add("WKT", pszWKT);
 
     VSIFPrintfL(fp, "%s\n", oLGIDict.Serialize().c_str());
     EndObj();
 
     OSRDestroySpatialReference(hSRS);
-    
+
     return nLGIDictId;
 }
 
@@ -1438,7 +1434,7 @@ int GDALPDFWriter::SetInfo(GDALDataset* poSrcDS,
 int  GDALPDFWriter::SetXMP(GDALDataset* poSrcDS,
                            const char* pszXMP)
 {
-    if (pszXMP != NULL && EQUALN(pszXMP, "NO", 2))
+    if (pszXMP != NULL && STARTS_WITH_CI(pszXMP, "NO"))
         return 0;
     if (pszXMP != NULL && pszXMP[0] == '\0')
         return 0;
@@ -1893,7 +1889,6 @@ int GDALPDFWriter::WriteClippedImagery(
     return TRUE;
 }
 
-#ifdef OGR_ENABLED
 
 /************************************************************************/
 /*                          WriteOGRDataSource()                        */
@@ -2159,9 +2154,9 @@ int GDALPDFWriter::WriteOGRFeature(GDALPDFLayerDesc& osVectorDesc,
                                    int& iObj,
                                    int& iObjLayer)
 {
-    GDALDataset* poClippingDS = oPageContext.poClippingDS;
-    int  nHeight = poClippingDS->GetRasterYSize();
-    double dfUserUnit = oPageContext.dfDPI * USER_UNIT_IN_INCH;
+    GDALDataset* const  poClippingDS = oPageContext.poClippingDS;
+    const int  nHeight = poClippingDS->GetRasterYSize();
+    const double dfUserUnit = oPageContext.dfDPI * USER_UNIT_IN_INCH;
     double adfGeoTransform[6];
     poClippingDS->GetGeoTransform(adfGeoTransform);
 
@@ -2189,11 +2184,13 @@ int GDALPDFWriter::WriteOGRFeature(GDALPDFLayerDesc& osVectorDesc,
 
         OGREnvelope sRasterEnvelope;
         sRasterEnvelope.MinX = adfGeoTransform[0];
-        sRasterEnvelope.MinY = adfGeoTransform[3] + poClippingDS->GetRasterYSize() * adfGeoTransform[5];
-        sRasterEnvelope.MaxX = adfGeoTransform[0] + poClippingDS->GetRasterXSize() * adfGeoTransform[1];
+        sRasterEnvelope.MinY = adfGeoTransform[3]
+            + poClippingDS->GetRasterYSize() * adfGeoTransform[5];
+        sRasterEnvelope.MaxX = adfGeoTransform[0]
+            + poClippingDS->GetRasterXSize() * adfGeoTransform[1];
         sRasterEnvelope.MaxY = adfGeoTransform[3];
 
-        /* Check that the reprojected geometry interescts the raster envelope */
+        // Check that the reprojected geometry intersects the raster envelope.
         OGR_G_GetEnvelope(hGeom, &sEnvelope);
         if( !(sRasterEnvelope.Intersects(sEnvelope)) )
         {
@@ -2504,7 +2501,7 @@ int GDALPDFWriter::WriteOGRFeature(GDALPDFLayerDesc& osVectorDesc,
             oDict.Add("Border", &(new GDALPDFArrayRW())->Add(0).Add(0).Add(0));
             oDict.Add("H", GDALPDFObjectRW::CreateName("I"));
 
-            if( wkbFlatten(OGR_G_GetGeometryType(hGeom)) == wkbPolygon && 
+            if( wkbFlatten(OGR_G_GetGeometryType(hGeom)) == wkbPolygon &&
                 OGR_G_GetGeometryCount(hGeom) == 1 )
             {
                 OGRGeometryH hSubGeom = OGR_G_GetGeometryRef(hGeom, 0);
@@ -2684,7 +2681,7 @@ int GDALPDFWriter::WriteOGRFeature(GDALPDFLayerDesc& osVectorDesc,
                         dfX - dfRadius * dfKappa, dfY + dfRadius,
                         dfX - dfRadius, dfY + dfRadius * dfKappa,
                         dfX - dfRadius, dfY);
-            if (osSymbolId == "ogr-sym-2") 
+            if (osSymbolId == "ogr-sym-2")
                 VSIFPrintfL(fp, "s\n"); /* not filled */
             else
                 VSIFPrintfL(fp, "b*\n"); /* filled */
@@ -2773,10 +2770,7 @@ int GDALPDFWriter::WriteOGRFeature(GDALPDFLayerDesc& osVectorDesc,
         {
             GDALPDFDictionaryRW oDict;
 
-            GDALDataset* poClippingDS = oPageContext.poClippingDS;
             int  nWidth = poClippingDS->GetRasterXSize();
-            int  nHeight = poClippingDS->GetRasterYSize();
-            double dfUserUnit = oPageContext.dfDPI * USER_UNIT_IN_INCH;
             double dfWidthInUserUnit = nWidth / dfUserUnit + oPageContext.sMargins.nLeft + oPageContext.sMargins.nRight;
             double dfHeightInUserUnit = nHeight / dfUserUnit + oPageContext.sMargins.nBottom + oPageContext.sMargins.nTop;
 
@@ -2826,10 +2820,10 @@ int GDALPDFWriter::WriteOGRFeature(GDALPDFLayerDesc& osVectorDesc,
         /* -------------------------------------------------------------- */
         VSIFPrintfL(fp, "stream\n");
 
-        vsi_l_offset nStreamStart = VSIFTellL(fp);
+        nStreamStart = VSIFTellL(fp);
 
-        VSILFILE* fpGZip = NULL;
-        VSILFILE* fpBack = fp;
+        fpGZip = NULL;
+        fpBack = fp;
         if( oPageContext.eStreamCompressMethod != COMPRESS_NONE )
         {
             fpGZip = (VSILFILE* )VSICreateGZipWritable( (VSIVirtualHandle*) fp, TRUE, FALSE );
@@ -2881,7 +2875,7 @@ int GDALPDFWriter::WriteOGRFeature(GDALPDFLayerDesc& osVectorDesc,
             VSIFCloseL(fpGZip);
         fp = fpBack;
 
-        vsi_l_offset nStreamEnd = VSIFTellL(fp);
+        nStreamEnd = VSIFTellL(fp);
         VSIFPrintfL(fp, "\n");
         VSIFPrintfL(fp, "endstream\n");
         EndObj();
@@ -2906,9 +2900,10 @@ int GDALPDFWriter::WriteOGRFeature(GDALPDFLayerDesc& osVectorDesc,
 
     if (bWriteOGRAttributes)
     {
-        int iField = -1;
-        if (pszOGRDisplayField &&
-            (iField = OGR_FD_GetFieldIndex(OGR_F_GetDefnRef(hFeat), pszOGRDisplayField)) >= 0)
+        iField = -1;
+        if (pszOGRDisplayField )
+            iField = OGR_FD_GetFieldIndex(OGR_F_GetDefnRef(hFeat), pszOGRDisplayField);
+        if( iField >= 0 )
             osFeatureName = OGR_F_GetFieldAsString(hFeat, iField);
         else
             osFeatureName = CPLSPrintf("feature%d", iObjLayer + 1);
@@ -2962,7 +2957,6 @@ int GDALPDFWriter::WriteOGRFeature(GDALPDFLayerDesc& osVectorDesc,
     return TRUE;
 }
 
-#endif
 
 /************************************************************************/
 /*                               EndPage()                              */
@@ -3003,7 +2997,7 @@ int GDALPDFWriter::EndPage(const char* pszExtraImages,
             double dfScale = CPLAtof(papszExtraImagesTokens[i+3]);
             const char* pszLinkVal = NULL;
             i += 4;
-            if( i < nCount && EQUALN(papszExtraImagesTokens[i],"link=",5) )
+            if( i < nCount && STARTS_WITH_CI(papszExtraImagesTokens[i], "link=") )
             {
                 pszLinkVal = papszExtraImagesTokens[i] + 5;
                 i++;
@@ -3700,7 +3694,7 @@ int GDALPDFWriter::WriteBlock(GDALDataset* poSrcDS,
     int nImageLengthId = AllocNewObject();
 
     int nMeasureId = 0;
-    if( CSLTestBoolean(CPLGetConfigOption("GDAL_PDF_WRITE_GEOREF_ON_IMAGE", "FALSE")) &&
+    if( CPLTestBool(CPLGetConfigOption("GDAL_PDF_WRITE_GEOREF_ON_IMAGE", "FALSE")) &&
         nReqXSize == poSrcDS->GetRasterXSize() &&
         nReqYSize == poSrcDS->GetRasterYSize() )
     {
@@ -3766,7 +3760,7 @@ int GDALPDFWriter::WriteBlock(GDALDataset* poSrcDS,
             poJPEGDriver = (GDALDriver*) GDALGetDriverByName("JPEG");
             if (poJPEGDriver != NULL && nJPEGQuality > 0)
                 papszOptions = CSLAddString(papszOptions, CPLSPrintf("QUALITY=%d", nJPEGQuality));
-            sprintf(szTmp, "/vsimem/pdftemp/%p.jpg", this);
+            snprintf(szTmp, sizeof(szTmp), "/vsimem/pdftemp/%p.jpg", this);
         }
         else
         {
@@ -3806,7 +3800,7 @@ int GDALPDFWriter::WriteBlock(GDALDataset* poSrcDS,
                 if (pszJPEG2000_DRIVER == NULL || EQUAL(pszJPEG2000_DRIVER, "JPEG2000"))
                     poJPEGDriver = (GDALDriver*) GDALGetDriverByName("JPEG2000");
             }
-            sprintf(szTmp, "/vsimem/pdftemp/%p.jp2", this);
+            snprintf(szTmp, sizeof(szTmp), "/vsimem/pdftemp/%p.jp2", this);
         }
 
         if( poJPEGDriver == NULL )
@@ -3835,7 +3829,7 @@ int GDALPDFWriter::WriteBlock(GDALDataset* poSrcDS,
 
         vsi_l_offset nJPEGDataSize = 0;
         GByte* pabyJPEGData = VSIGetMemFileBuffer(szTmp, &nJPEGDataSize, TRUE);
-        VSIFWriteL(pabyJPEGData, nJPEGDataSize, 1, fp);
+        VSIFWriteL(pabyJPEGData, static_cast<size_t>(nJPEGDataSize), 1, fp);
         CPLFree(pabyJPEGData);
     }
     else
@@ -3961,19 +3955,16 @@ int GDALPDFWriter::WriteJavascript(const char* pszJavascript)
     VSIFPrintfL(fp, "stream\n");
     vsi_l_offset nStreamStart = VSIFTellL(fp);
 
-    VSILFILE* fpGZip = NULL;
-    VSILFILE* fpBack = fp;
     if( oPageContext.eStreamCompressMethod != COMPRESS_NONE )
     {
-        fpGZip = (VSILFILE* )VSICreateGZipWritable( (VSIVirtualHandle*) fp, TRUE, FALSE );
-        fp = fpGZip;
+        VSILFILE* fpTemp = (VSILFILE* )VSICreateGZipWritable( (VSIVirtualHandle*) fp, TRUE, FALSE );
+        VSIFWriteL(pszJavascript, strlen(pszJavascript), 1, fpTemp);
+        VSIFCloseL(fpTemp);
+    }
+    else
+    {
+        VSIFWriteL(pszJavascript, strlen(pszJavascript), 1, fp);
     }
-
-    VSIFWriteL(pszJavascript, strlen(pszJavascript), 1, fp);
-
-    if (fpGZip)
-        VSIFCloseL(fpGZip);
-    fp = fpBack;
 
     vsi_l_offset nStreamEnd = VSIFTellL(fp);
     VSIFPrintfL(fp,
@@ -4072,8 +4063,7 @@ void GDALPDFWriter::WritePages()
 
             /* Build "Order" array of D dict */
             GDALPDFArrayRW* poArrayOrder = new GDALPDFArrayRW();
-            size_t i;
-            for(i=0;i<asOCGs.size();i++)
+            for(size_t i=0;i<asOCGs.size();i++)
             {
                 poArrayOrder->Add(asOCGs[i].nId, 0);
                 if (i + 1 < asOCGs.size() && asOCGs[i+1].nParentId == asOCGs[i].nId)
@@ -4160,7 +4150,7 @@ void GDALPDFWriter::WritePages()
             }
 
             GDALPDFArrayRW* poArrayOGCs = new GDALPDFArrayRW();
-            for(i=0;i<asOCGs.size();i++)
+            for(size_t i=0;i<asOCGs.size();i++)
                 poArrayOGCs->Add(asOCGs[i].nId, 0);
             poDictOCProperties->Add("OCGs", poArrayOGCs);
         }
@@ -4214,7 +4204,7 @@ class GDALPDFClippingDataset: public GDALDataset
         double adfGeoTransform[6];
 
     public:
-        GDALPDFClippingDataset(GDALDataset* poSrcDS, double adfClippingExtent[4]) : poSrcDS(poSrcDS)
+        GDALPDFClippingDataset(GDALDataset* poSrcDSIn, double adfClippingExtent[4]) : poSrcDS(poSrcDSIn)
         {
             double adfSrcGeoTransform[6];
             poSrcDS->GetGeoTransform(adfSrcGeoTransform);
@@ -4524,7 +4514,7 @@ GDALDataset *GDALPDFCreateCopy( const char * pszFilename,
 
     const char* pszExtraRasters = CSLFetchNameValue(papszOptions, "EXTRA_RASTERS");
     const char* pszExtraRastersLayerName = CSLFetchNameValue(papszOptions, "EXTRA_RASTERS_LAYER_NAME");
-    
+
     const char* pszOffLayers = CSLFetchNameValue(papszOptions, "OFF_LAYERS");
     const char* pszExclusiveLayers = CSLFetchNameValue(papszOptions, "EXCLUSIVE_LAYERS");
 
@@ -4698,14 +4688,12 @@ GDALDataset *GDALPDFCreateCopy( const char * pszFilename,
     CSLDestroy(papszExtraRasters);
     CSLDestroy(papszExtraRastersLayerName);
 
-#ifdef OGR_ENABLED
     if (bRet && pszOGRDataSource != NULL)
         oWriter.WriteOGRDataSource(pszOGRDataSource,
                                    pszOGRDisplayField,
                                    pszOGRDisplayLayerNames,
                                    pszOGRLinkField,
                                    bWriteOGRAttributes);
-#endif
 
     if (bRet)
         oWriter.EndPage(pszExtraImages,
@@ -4720,7 +4708,7 @@ GDALDataset *GDALPDFCreateCopy( const char * pszFilename,
         oWriter.WriteJavascriptFile(pszJavascriptFile);
 
     oWriter.Close();
-    
+
     if (poClippingDS != poSrcDS)
         delete poClippingDS;
 
@@ -4731,7 +4719,7 @@ GDALDataset *GDALPDFCreateCopy( const char * pszFilename,
     }
     else
     {
-#if defined(HAVE_POPPLER) || defined(HAVE_PODOFO)
+#if defined(HAVE_POPPLER) || defined(HAVE_PODOFO) || defined(HAVE_PDFIUM)
         return GDALPDFOpen(pszFilename, GA_ReadOnly);
 #else
         return new GDALFakePDFDataset();
diff --git a/frmts/pdf/pdfcreatecopy.h b/frmts/pdf/pdfcreatecopy.h
index 4bc0e17..140e96b 100644
--- a/frmts/pdf/pdfcreatecopy.h
+++ b/frmts/pdf/pdfcreatecopy.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pdfcreatecopy.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: pdfcreatecopy.h 33757 2016-03-20 20:22:33Z goatbar $
  *
  * Project:  PDF driver
  * Purpose:  GDALDataset driver for PDF dataset.
@@ -35,9 +35,7 @@
 #include <vector>
 #include <map>
 
-#ifdef OGR_ENABLED
 #include "ogr_api.h"
-#endif
 
 typedef enum
 {
@@ -235,7 +233,6 @@ class GDALPDFWriter
                                int nBlockXSize, int nBlockYSize,
                                GDALProgressFunc pfnProgress,
                                void * pProgressData);
-#ifdef OGR_ENABLED
        int WriteOGRDataSource(const char* pszOGRDataSource,
                               const char* pszOGRDisplayField,
                               const char* pszOGRDisplayLayerNames,
@@ -262,7 +259,6 @@ class GDALPDFWriter
                            int bWriteOGRAttributes,
                            int& iObj,
                            int& iObjLayer);
-#endif
 
        int  WriteJavascript(const char* pszJavascript);
        int  WriteJavascriptFile(const char* pszJavascriptFile);
diff --git a/frmts/pdf/pdfdataset.cpp b/frmts/pdf/pdfdataset.cpp
index 309018f..4bee2d8 100644
--- a/frmts/pdf/pdfdataset.cpp
+++ b/frmts/pdf/pdfdataset.cpp
@@ -1,11 +1,18 @@
 /******************************************************************************
- * $Id: pdfdataset.cpp 32773 2016-01-06 11:24:07Z rouault $
+ * $Id: pdfdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  PDF driver
  * Purpose:  GDALDataset driver for PDF dataset.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
+ *
+ * Support for open-source PDFium library
+ *
+ * Copyright (C) 2015 Klokan Technologies GmbH (http://www.klokantech.com/)
+ * Author: Martin Mikita <martin.mikita at klokantech.com>, xmikit00 @ FIT VUT Brno
+ *
+ ******************************************************************************
  * Copyright (c) 2010-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -30,15 +37,15 @@
 #include "gdal_pdf.h"
 
 #include "cpl_vsi_virtual.h"
+#include "cpl_spawn.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
 #include "ogr_spatialref.h"
 #include "ogr_geometry.h"
-#include "cpl_spawn.h"
 
 #ifdef HAVE_POPPLER
 #include "cpl_multiproc.h"
 #include "pdfio.h"
-#include <goo/GooList.h>
 #endif // HAVE_POPPLER
 
 #include "pdfcreatecopy.h"
@@ -48,15 +55,21 @@
 
 /* g++ -fPIC -g -Wall frmts/pdf/pdfdataset.cpp -shared -o gdal_PDF.so -Iport -Igcore -Iogr -L. -lgdal -lpoppler -I/usr/include/poppler */
 
-CPL_CVSID("$Id: pdfdataset.cpp 32773 2016-01-06 11:24:07Z rouault $");
+CPL_CVSID("$Id: pdfdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
-CPL_C_START
-void    GDALRegister_PDF(void);
-CPL_C_END
+#if defined(HAVE_POPPLER) || defined(HAVE_PODOFO) || defined(HAVE_PDFIUM)
 
-#if defined(HAVE_POPPLER) || defined(HAVE_PODOFO)
-static const char* pszOpenOptionList =
+#if defined(HAVE_PDFIUM) && defined(HAVE_POPPLER)
+#define HAVE_MULTIPLE_PDF_BACKENDS
+#elif defined(HAVE_PDFIUM) && defined(HAVE_PODOFO)
+#define HAVE_MULTIPLE_PDF_BACKENDS
+#elif defined(HAVE_POPPLER) && defined(HAVE_PODOFO)
+#define HAVE_MULTIPLE_PDF_BACKENDS
+#endif
+
+static const char* const szOpenOptionList =
 "<OpenOptionList>"
+#if defined(HAVE_POPPLER) || defined(HAVE_PDFIUM)
 "  <Option name='RENDERING_OPTIONS' type='string-select' description='Which graphical elements to render' default='RASTER,VECTOR,TEXT' alt_config_option='GDAL_PDF_RENDERING_OPTIONS'>"
 "     <Value>RASTER,VECTOR,TEXT</Value>\n"
 "     <Value>RASTER,VECTOR</Value>\n"
@@ -66,14 +79,30 @@ static const char* pszOpenOptionList =
 "     <Value>VECTOR</Value>\n"
 "     <Value>TEXT</Value>\n"
 "  </Option>"
+#endif
 "  <Option name='DPI' type='float' description='Resolution in Dot Per Inch' default='72' alt_config_option='GDAL_PDF_DPI'/>"
 "  <Option name='USER_PWD' type='string' description='Password' alt_config_option='PDF_USER_PWD'/>"
-#if defined(HAVE_POPPLER) && defined(HAVE_PODOFO)
-"  <Option name='PDF_LIB' type='string-select' description='Which underlying PDF library to use' default='POPPLER' alt_config_option='GDAL_PDF_LIB'>"
+#ifdef HAVE_MULTIPLE_PDF_BACKENDS
+"  <Option name='PDF_LIB' type='string-select' description='Which underlying PDF library to use' "
+#if defined(HAVE_PDFIUM)
+  "default='PDFIUM'"
+#elif defined(HAVE_POPPLER)
+  "default='POPPLER'"
+#elif defined(HAVE_PODOFO)
+  "default='PODOFO'"
+#endif  // ~ default PDF_LIB
+  "alt_config_option='GDAL_PDF_LIB'>"
+#if defined(HAVE_POPPLER)
 "     <Value>POPPLER</Value>\n"
+#endif  // HAVE_POPPLER
+#if defined(HAVE_PODOFO)
 "     <Value>PODOFO</Value>\n"
+#endif  // HAVE_PODOFO
+#if defined(HAVE_PDFIUM)
+"     <Value>PDFIUM</Value>\n"
+#endif  // HAVE_PDFIUM
 "  </Option>"
-#endif // HAVE_POPPLER && HAVE_PODOFO
+#endif // HAVE_MULTIPLE_PDF_BACKENDS
 "  <Option name='LAYERS' type='string' description='List of layers (comma separated) to turn ON (or ALL to turn all layers ON)' alt_config_option='GDAL_PDF_LAYERS'/>"
 "  <Option name='LAYERS_OFF' type='string' description='List of layers (comma separated) to turn OFF' alt_config_option='GDAL_PDF_LAYERS_OFF'/>"
 "  <Option name='BANDS' type='string-select' description='Number of raster bands' default='3' alt_config_option='GDAL_PDF_BANDS'>"
@@ -95,9 +124,13 @@ static CPLMutex* hGlobalParamsMutex = NULL;
 
 class ObjectAutoFree : public Object
 {
+    Object obj;
+
 public:
     ObjectAutoFree() {}
-    ~ObjectAutoFree() { free(); }
+    ~ObjectAutoFree() { obj.free(); }
+
+    Object* getObj() { return &obj; }
 };
 
 
@@ -141,13 +174,13 @@ class GDALPDFOutputDev : public SplashOutputDev
 
         virtual void startPage(int pageNum, GfxState *state
 #ifdef POPPLER_0_23_OR_LATER
-                               ,XRef* xref
+                               ,XRef* xrefIn
 #endif
         )
         {
             SplashOutputDev::startPage(pageNum, state
 #ifdef POPPLER_0_23_OR_LATER
-                                       ,xref
+                                       ,xrefIn
 #endif
             );
             SplashBitmap* poBitmap = getBitmap();
@@ -309,7 +342,7 @@ class GDALPDFOutputDev : public SplashOutputDev
         }
 };
 
-#endif
+#endif  // ~ HAVE_POPPLER
 
 /************************************************************************/
 /*                         Dump routines                                */
@@ -326,9 +359,24 @@ class GDALPDFDumper
         void DumpSimplified(GDALPDFObject* poObj);
 
     public:
-        GDALPDFDumper(FILE* fIn, int nDepthLimitIn = -1) : f(fIn), nDepthLimit(nDepthLimitIn)
+        GDALPDFDumper(const char* pszFilename,
+                      const char* pszDumpFile, int nDepthLimitIn = -1) : nDepthLimit(nDepthLimitIn)
+        {
+            bDumpParent = CPLTestBool(CPLGetConfigOption("PDF_DUMP_PARENT", "FALSE"));
+            if (strcmp(pszDumpFile, "stderr") == 0)
+                f = stderr;
+            else if (EQUAL(pszDumpFile, "YES"))
+                f = fopen(CPLSPrintf("dump_%s.txt", CPLGetFilename(pszFilename)), "wt");
+            else
+                f = fopen(pszDumpFile, "wt");
+            if (f == NULL)
+                f = stderr;
+        }
+
+        ~GDALPDFDumper()
         {
-            bDumpParent = CSLTestBoolean(CPLGetConfigOption("PDF_DUMP_PARENT", "FALSE"));
+            if( f != stderr )
+                fclose(f);
         }
 
         void Dump(GDALPDFObject* poObj, int nDepth = 0);
@@ -515,31 +563,71 @@ void GDALPDFDumper::Dump(GDALPDFDictionary* poDict, int nDepth)
 /*                         PDFRasterBand()                              */
 /************************************************************************/
 
-PDFRasterBand::PDFRasterBand( PDFDataset *poDS, int nBand )
+PDFRasterBand::PDFRasterBand( PDFDataset *poDSIn, int nBandIn, int nResolutionLevelIn )
 
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
+    this->nResolutionLevel = nResolutionLevelIn;
 
     eDataType = GDT_Byte;
 
-    if( poDS->nBlockXSize )
+    if( nResolutionLevel > 0 )
     {
-        nBlockXSize = poDS->nBlockXSize;
-        nBlockYSize = poDS->nBlockYSize;
+        nBlockXSize = 256;
+        nBlockYSize = 256;
+        poDSIn->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
     }
-    else if( poDS->GetRasterXSize() < 64 * 1024 * 1024 / poDS->GetRasterYSize() )
+    else if( poDSIn->nBlockXSize )
     {
-        nBlockXSize = poDS->GetRasterXSize();
+        nBlockXSize = poDSIn->nBlockXSize;
+        nBlockYSize = poDSIn->nBlockYSize;
+    }
+    else if( poDSIn->GetRasterXSize() < 64 * 1024 * 1024 / poDSIn->GetRasterYSize() )
+    {
+        nBlockXSize = poDSIn->GetRasterXSize();
         nBlockYSize = 1;
     }
     else
     {
-        nBlockXSize = MIN(1024, poDS->GetRasterXSize());
-        nBlockYSize = MIN(1024, poDS->GetRasterYSize());
-        poDS->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
+        nBlockXSize = MIN(1024, poDSIn->GetRasterXSize());
+        nBlockYSize = MIN(1024, poDSIn->GetRasterYSize());
+        poDSIn->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
+    }
+}
+
+/************************************************************************/
+/*                         InitOverviews()                              */
+/************************************************************************/
+
+#ifdef HAVE_PDFIUM
+void PDFDataset::InitOverviews()
+{
+    // Only if used pdfium, make "arbitrary overviews"
+    // Blocks are 256x256
+    if(bUseLib.test(PDFLIB_PDFIUM) &&
+       ((GDALPamRasterBand*)GetRasterBand(1))->GDALPamRasterBand::GetOverviewCount() == 0)
+    {
+        int nXSize = nRasterXSize, nYSize = nRasterYSize;
+        int blockXSize = 256;
+        int blockYSize = 256;
+        int nDiscard = 1;
+        while (nXSize > blockXSize || nYSize > blockYSize)
+        {
+            nXSize = (nXSize+1) / 2;
+            nYSize = (nYSize+1) / 2;
+
+            PDFDataset* poOvrDS = new PDFDataset(this, nXSize, nYSize);
+            apoOvrDS.push_back(poOvrDS);
+
+            for(int i=0;i<nBands;i++)
+                poOvrDS->SetBand( i+1, new PDFRasterBand(poOvrDS, i+1, nDiscard) );
+
+            ++nDiscard;
+        }
     }
 }
+#endif
 
 /************************************************************************/
 /*                        GetColorInterpretation()                      */
@@ -554,6 +642,51 @@ GDALColorInterp PDFRasterBand::GetColorInterpretation()
         return (GDALColorInterp)(GCI_RedBand + (nBand - 1));
 }
 
+#ifdef HAVE_PDFIUM
+
+/************************************************************************/
+/*                          GetOverviewCount()                          */
+/************************************************************************/
+
+int PDFRasterBand::GetOverviewCount()
+{
+    if( GDALPamRasterBand::GetOverviewCount() > 0 )
+        return GDALPamRasterBand::GetOverviewCount();
+    else
+    {
+        PDFDataset *poGDS = (PDFDataset *) poDS;
+        return (int)poGDS->apoOvrDS.size();
+    }
+}
+
+/************************************************************************/
+/*                            GetOverview()                             */
+/************************************************************************/
+
+GDALRasterBand* PDFRasterBand::GetOverview( int iOverviewIndex)
+{
+    if( GDALPamRasterBand::GetOverviewCount() > 0 )
+        return GDALPamRasterBand::GetOverview( iOverviewIndex );
+
+    else if( iOverviewIndex < 0 || iOverviewIndex >= GetOverviewCount() )
+        return NULL;
+    else
+    {
+        PDFDataset *poGDS = (PDFDataset *) poDS;
+        return poGDS->apoOvrDS[iOverviewIndex]->GetRasterBand(nBand);
+    }
+}
+
+#endif  // ~ HAVE_PDFIUM
+
+/************************************************************************/
+/*                           ~PDFRasterBand()                           */
+/************************************************************************/
+
+PDFRasterBand::~PDFRasterBand()
+{
+}
+
 /************************************************************************/
 /*                         IReadBlockFromTile()                         */
 /************************************************************************/
@@ -573,15 +706,10 @@ CPLErr PDFRasterBand::IReadBlockFromTile( int nBlockXOff, int nBlockYOff,
 
     int nXBlocks = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
     int iTile = poGDS->aiTiles[nBlockYOff * nXBlocks + nBlockXOff];
+
     GDALPDFTileDesc& sTile = poGDS->asTiles[iTile];
     GDALPDFObject* poImage = sTile.poImage;
 
-    if( iTile < 0 )
-    {
-        memset(pImage, 0, nBlockXSize * nBlockYSize);
-        return CE_None;
-    }
-
     if( nBand == 4 )
     {
         GDALPDFDictionary* poImageDict = poImage->GetDictionary();
@@ -663,8 +791,10 @@ CPLErr PDFRasterBand::IReadBlockFromTile( int nBlockXOff, int nBlockYOff,
         poGDS->nLastBlockYOff == nBlockYOff &&
         poGDS->pabyCachedData != NULL )
     {
+#ifdef DEBUG
         CPLDebug("PDF", "Using cached block (%d, %d)",
                  nBlockXOff, nBlockYOff);
+#endif
         // do nothing
     }
     else
@@ -788,21 +918,28 @@ CPLErr PDFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     else
     {
 #ifdef HAVE_PODOFO
-        if (!poGDS->bUsePoppler && nBand == 4)
+        if (poGDS->bUseLib.test(PDFLIB_PODOFO) && nBand == 4)
         {
             memset(pImage, 255, nBlockXSize * nBlockYSize);
             return CE_None;
         }
 #endif
 
-        CPLErr eErr = poGDS->ReadPixels( nBlockXOff * nBlockXSize,
-                                         (nBlockYSize == 1) ? 0 : nBlockYOff * nBlockYSize,
+        const int nReqXOff = nBlockXOff * nBlockXSize;
+        const int nReqYOff = (nBlockYSize == 1) ? 0 : nBlockYOff * nBlockYSize;
+        const GSpacing nPixelSpace = 1;
+        const GSpacing nLineSpace = nBlockXSize;
+        const GSpacing nBandSpace = static_cast<GSpacing>(nBlockXSize) * ((nBlockYSize == 1) ? nRasterYSize : nBlockYSize);
+
+        CPLErr eErr = poGDS->ReadPixels( nReqXOff,
+                                         nReqYOff,
                                          nReqXSize,
                                          nReqYSize,
-                                         1,
-                                         nBlockXSize,
-                                         nBlockXSize * ((nBlockYSize == 1) ? nRasterYSize : nBlockYSize),
-                                         poGDS->pabyCachedData);
+                                         nPixelSpace,
+                                         nLineSpace,
+                                         nBandSpace,
+                                         poGDS->pabyCachedData );
+
         if( eErr == CE_None )
         {
             poGDS->nLastBlockXOff = nBlockXOff;
@@ -831,6 +968,342 @@ CPLErr PDFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 }
 
 /************************************************************************/
+/*                    PDFEnterPasswordFromConsoleIfNeeded()             */
+/************************************************************************/
+
+static const char* PDFEnterPasswordFromConsoleIfNeeded(const char* pszUserPwd)
+{
+    if (EQUAL(pszUserPwd, "ASK_INTERACTIVE"))
+    {
+        static char szPassword[81];
+        printf( "Enter password (will be echo'ed in the console): " );
+        if (NULL == fgets( szPassword, sizeof(szPassword), stdin ))
+        {
+            fprintf(stderr, "WARNING: Error getting password.\n");
+        }
+        szPassword[sizeof(szPassword)-1] = 0;
+        char* sz10 = strchr(szPassword, '\n');
+        if (sz10)
+            *sz10 = 0;
+        return szPassword;
+    }
+    return pszUserPwd;
+}
+
+#ifdef HAVE_PDFIUM
+
+/************************************************************************/
+/*                         Pdfium Load/Unload                           */
+/* Copyright (C) 2015 Klokan Technologies GmbH (http://www.klokantech.com/) */
+/* Author: Martin Mikita <martin.mikita at klokantech.com>                 */
+/************************************************************************/
+
+// Flag for calling PDFium Init and Destroy methods
+int PDFDataset::bPdfiumInit = FALSE;
+
+// Pdfium global read mutex - Pdfium is not multi-thread
+static CPLMutex * g_oPdfiumReadMutex = NULL;
+static CPLMutex * g_oPdfiumLoadDocMutex = NULL;
+
+// Comparison of char* for std::map
+struct cmp_str
+{
+   bool operator()(char const *a, char const *b) const
+   {
+      return strcmp(a, b) < 0;
+   }
+};
+
+static int GDALPdfiumGetBlock(void* param, unsigned long position, unsigned char* pBuf, unsigned long size)
+{
+    VSILFILE* fp = (VSILFILE*)param;
+    VSIFSeekL(fp, position, SEEK_SET);
+    return VSIFReadL(pBuf, size, 1, fp) == 1;
+}
+
+// List of all PDF datasets
+typedef std::map<char*, TPdfiumDocumentStruct*, cmp_str>    TMapPdfiumDatasets;
+static TMapPdfiumDatasets g_mPdfiumDatasets;
+
+/**
+ * Loading PDFIUM page
+ * - multithreading requires "mutex"
+ * - one page can require too much RAM
+ * - we will have one document per filename and one object per page
+ */
+
+static
+int LoadPdfiumDocumentPage(const char* pszFilename, const char* pszUserPwd,
+    int pageNum, TPdfiumDocumentStruct** doc, TPdfiumPageStruct** page, int *pnPageCount)
+{
+  TPdfiumDocumentStruct *poDoc;
+  TPdfiumPageStruct *poPage;
+
+  // Prepare NULL for error returning
+  if(doc)
+    *doc = NULL;
+  if(page)
+    *page = NULL;
+  if(pnPageCount)
+    *pnPageCount = 0;
+
+  // Loading document and page must be only in one thread!
+  CPLCreateOrAcquireMutex(&g_oPdfiumLoadDocMutex, PDFIUM_MUTEX_TIMEOUT);
+
+  // Library can be destroyed if every PDF dataset was closed!
+  if(!PDFDataset::bPdfiumInit) {
+    FPDF_InitLibrary();
+    PDFDataset::bPdfiumInit = TRUE;
+  }
+
+  TMapPdfiumDatasets::iterator it;
+  it = g_mPdfiumDatasets.find((char*)pszFilename);
+  // Load new document if missing
+  if(it == g_mPdfiumDatasets.end() ) {
+    // Try without password (if PDF not requires password it can fail)
+    CPDF_Document* docPdfium;
+
+    VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
+    if( fp == NULL )
+    {
+        CPLReleaseMutex(g_oPdfiumLoadDocMutex);
+        return FALSE;
+    }
+    VSIFSeekL(fp, 0, SEEK_END);
+    unsigned long nFileLen = (unsigned long)VSIFTellL(fp);
+    if( nFileLen != VSIFTellL(fp) )
+    {
+        VSIFCloseL(fp);
+        CPLReleaseMutex(g_oPdfiumLoadDocMutex);
+        return FALSE;
+    }
+
+    FPDF_FILEACCESS* psFileAccess = new FPDF_FILEACCESS;
+    psFileAccess->m_Param = fp;
+    psFileAccess->m_FileLen = nFileLen;
+    psFileAccess->m_GetBlock = GDALPdfiumGetBlock;
+    docPdfium = reinterpret_cast<CPDF_Document*>(FPDF_LoadCustomDocument(psFileAccess, NULL));
+    if(docPdfium == NULL)
+    {
+      unsigned long err = FPDF_GetLastError();
+      if( err == FPDF_ERR_PASSWORD) {
+          if(pszUserPwd) {
+            pszUserPwd = PDFEnterPasswordFromConsoleIfNeeded(pszUserPwd);
+            docPdfium = reinterpret_cast<CPDF_Document*>(FPDF_LoadCustomDocument(psFileAccess, pszUserPwd));
+            if(docPdfium == NULL)
+              err = FPDF_GetLastError();
+            else
+              err = FPDF_ERR_SUCCESS;
+          }
+          else {
+            CPLError(CE_Failure, CPLE_AppDefined,
+              "A password is needed. You can specify it through the PDF_USER_PWD "
+              "configuration option / USER_PWD open option (that can be set to ASK_INTERACTIVE)");
+
+            VSIFCloseL(fp);
+            delete psFileAccess;
+            CPLReleaseMutex(g_oPdfiumLoadDocMutex);
+            return FALSE;
+          }
+      } // First Error Password [null password given]
+      if( err != FPDF_ERR_SUCCESS ) {
+        if(err == FPDF_ERR_PASSWORD)
+          CPLError(CE_Failure, CPLE_AppDefined, "PDFium Invalid password.");
+        else if(err == FPDF_ERR_SECURITY)
+          CPLError(CE_Failure, CPLE_AppDefined, "PDFium Unsupported security scheme.");
+        else if(err == FPDF_ERR_FORMAT)
+          CPLError(CE_Failure, CPLE_AppDefined, "PDFium File not in PDF format or corrupted.");
+        else if(err == FPDF_ERR_FILE)
+          CPLError(CE_Failure, CPLE_AppDefined, "PDFium File not found or could not be opened.");
+        else
+          CPLError(CE_Failure, CPLE_AppDefined, "PDFium Unknown PDF error or invalid PDF.");
+
+        VSIFCloseL(fp);
+        delete psFileAccess;
+        CPLReleaseMutex(g_oPdfiumLoadDocMutex);
+        return FALSE;
+      }
+    } // ~ wrong PDF or password required
+
+    // Create new poDoc
+    poDoc = new TPdfiumDocumentStruct;
+    if(!poDoc) {
+      CPLError(CE_Failure, CPLE_AppDefined, "Not enough memory for Pdfium Document object");
+
+      VSIFCloseL(fp);
+      delete psFileAccess;
+      CPLReleaseMutex(g_oPdfiumLoadDocMutex);
+      return FALSE;
+    }
+    poDoc->filename = CPLStrdup(pszFilename);
+    poDoc->doc = docPdfium;
+    poDoc->psFileAccess = psFileAccess;
+
+    g_mPdfiumDatasets[poDoc->filename] = poDoc;
+  }
+  // Document already loaded
+  else {
+    poDoc = it->second;
+  }
+
+  // Check page num in document
+  int nPages = poDoc->doc->GetPageCount();
+  if (pageNum < 1 || pageNum > nPages)
+  {
+      CPLError(CE_Failure, CPLE_AppDefined, "PDFium Invalid page number (%d/%d) for document %s",
+                pageNum, nPages, pszFilename);
+
+      CPLReleaseMutex(g_oPdfiumLoadDocMutex);
+      return FALSE;
+  }
+
+  /* Sanity check to validate page count */
+  if( pageNum != nPages )
+  {
+      if( poDoc->doc->GetPage(nPages - 1) == NULL )
+      {
+        CPLError(CE_Failure, CPLE_AppDefined, "Invalid PDF : invalid page count");
+        CPLReleaseMutex(g_oPdfiumLoadDocMutex);
+        return FALSE;
+      }
+  }
+
+  TMapPdfiumPages::iterator itPage;
+  itPage = poDoc->pages.find(pageNum);
+  // Page not loaded
+  if(itPage == poDoc->pages.end()) {
+    CPDF_Dictionary* pDict = poDoc->doc->GetPage(pageNum - 1);
+    if (pDict == NULL) {
+      CPLError(CE_Failure, CPLE_AppDefined, "Invalid PDFium : invalid page");
+
+      CPLReleaseMutex(g_oPdfiumLoadDocMutex);
+      return FALSE;
+    }
+    CPDF_Page* pPage = new CPDF_Page;
+    if(!pPage) {
+      CPLError(CE_Failure, CPLE_AppDefined, "Not enough memory for Pdfium Page object");
+
+      CPLReleaseMutex(g_oPdfiumLoadDocMutex);
+      return FALSE;
+    }
+    pPage->Load(poDoc->doc, pDict);
+
+    poPage = new TPdfiumPageStruct;
+    if(!poPage) {
+      CPLError(CE_Failure, CPLE_AppDefined, "Not enough memory for Pdfium Page object");
+
+      CPLReleaseMutex(g_oPdfiumLoadDocMutex);
+      return FALSE;
+    }
+    poPage->pageNum = pageNum;
+    poPage->page = pPage;
+    poPage->readMutex = NULL;
+    poPage->sharedNum = 0;
+
+    poDoc->pages[pageNum] = poPage;
+  }
+  // Page already loaded
+  else {
+    poPage = itPage->second;
+  }
+
+  // Increase number of used
+  ++poPage->sharedNum;
+
+  if(doc)
+    *doc = poDoc;
+  if(page)
+    *page = poPage;
+  if(pnPageCount)
+    *pnPageCount = nPages;
+
+  CPLReleaseMutex(g_oPdfiumLoadDocMutex);
+
+  return TRUE;
+}
+// ~ static int LoadPdfiumDocumentPage()
+
+static
+int UnloadPdfiumDocumentPage(TPdfiumDocumentStruct** doc, TPdfiumPageStruct** page)
+{
+  if(!doc || !page)
+    return FALSE;
+
+  TPdfiumPageStruct* pPage = *page;
+  TPdfiumDocumentStruct* pDoc = *doc;
+
+  // Get mutex for loading pdfium
+  CPLCreateOrAcquireMutex(&g_oPdfiumLoadDocMutex, PDFIUM_MUTEX_TIMEOUT);
+
+  // Decreas page use
+  --pPage->sharedNum;
+
+#ifdef DEBUG
+  CPLDebug("PDF", "PDFDataset::UnloadPdfiumDocumentPage: page shared num %d",
+      pPage->sharedNum);
+#endif
+  // Page is used (also document)
+  if(pPage->sharedNum != 0) {
+    CPLReleaseMutex(g_oPdfiumLoadDocMutex);
+    return TRUE;
+  }
+
+  // Get mutex, release and destroy it
+  CPLCreateOrAcquireMutex(&(pPage->readMutex), PDFIUM_MUTEX_TIMEOUT);
+  CPLReleaseMutex(pPage->readMutex);
+  CPLDestroyMutex(pPage->readMutex);
+  // Close page and remove from map
+  FPDF_ClosePage(pPage->page);
+
+  pDoc->pages.erase(pPage->pageNum);
+  delete pPage;
+  pPage = NULL;
+
+#ifdef DEBUG
+  CPLDebug("PDF", "PDFDataset::UnloadPdfiumDocumentPage: pages %lu",
+      pDoc->pages.size());
+#endif
+  // Another page is used
+  if(pDoc->pages.size() != 0) {
+    CPLReleaseMutex(g_oPdfiumLoadDocMutex);
+    return TRUE;
+  }
+
+  // Close document and remove from map
+  FPDF_CloseDocument(pDoc->doc);
+  g_mPdfiumDatasets.erase(pDoc->filename);
+  CPLFree(pDoc->filename);
+  VSIFCloseL((VSILFILE*)pDoc->psFileAccess->m_Param);
+  delete pDoc->psFileAccess;
+  delete pDoc;
+  pDoc = NULL;
+
+#ifdef DEBUG
+  CPLDebug("PDF", "PDFDataset::UnloadPdfiumDocumentPage: documents %lu",
+      g_mPdfiumDatasets.size());
+#endif
+  // Another document is used
+  if(g_mPdfiumDatasets.size() != 0) {
+    CPLReleaseMutex(g_oPdfiumLoadDocMutex);
+    return TRUE;
+  }
+
+#ifdef DEBUG
+  CPLDebug("PDF", "PDFDataset::UnloadPdfiumDocumentPage: Nothing loaded, destroy Library");
+#endif
+  // No document loaded, destroy pdfium
+  FPDF_DestroyLibrary();
+  PDFDataset::bPdfiumInit = FALSE;
+
+  CPLReleaseMutex(g_oPdfiumLoadDocMutex);
+
+  return TRUE;
+}
+// ~ static int UnloadPdfiumDocumentPage()
+
+#endif  // ~ HAVE_PDFIUM
+
+/************************************************************************/
 /*                             GetOption()                              */
 /************************************************************************/
 
@@ -839,9 +1312,9 @@ const char* PDFDataset::GetOption(char** papszOpenOptions,
                                   const char* pszDefaultVal)
 {
     CPLErr eLastErrType = CPLGetLastErrorType();
-    int nLastErrno = CPLGetLastErrorNo();
+    CPLErrorNum nLastErrno = CPLGetLastErrorNo();
     CPLString osLastErrorMsg(CPLGetLastErrorMsg());
-    CPLXMLNode* psNode = CPLParseXMLString(pszOpenOptionList);
+    CPLXMLNode* psNode = CPLParseXMLString(szOpenOptionList);
     CPLErrorSetState(eLastErrType, nLastErrno, osLastErrorMsg);
     if( psNode == NULL ) return pszDefaultVal;
     CPLXMLNode* psIter = psNode->psChild;
@@ -873,6 +1346,351 @@ const char* PDFDataset::GetOption(char** papszOpenOptions,
     return pszDefaultVal;
 }
 
+#ifdef HAVE_PDFIUM
+
+/************************************************************************/
+/*                         GDALPDFiumOCContext                          */
+/************************************************************************/
+
+class GDALPDFiumOCContext : public IPDF_OCContext
+{
+    PDFDataset* m_poDS;
+    CPDF_OCContext m_DefaultOCContext;
+public:
+
+    GDALPDFiumOCContext(PDFDataset* poDS, CPDF_Document *pDoc) :
+                                m_poDS(poDS), m_DefaultOCContext(pDoc) {}
+
+    virtual FX_BOOL CheckOCGVisible(const CPDF_Dictionary *pOCGDict) override
+    {
+        PDFDataset::VisibilityState eVisibility =
+            m_poDS->GetVisibilityStateForOGCPdfium(
+                                pOCGDict->GetObjNum(), pOCGDict->GetGenNum() );
+        if( eVisibility == PDFDataset::VISIBILITY_ON )
+            return TRUE;
+        if( eVisibility == PDFDataset::VISIBILITY_OFF )
+            return FALSE;
+        return m_DefaultOCContext.CheckOCGVisible(pOCGDict);
+    }
+};
+
+/************************************************************************/
+/*                      GDALPDFiumRenderDeviceDriver                    */
+/************************************************************************/
+
+class GDALPDFiumRenderDeviceDriver: public IFX_RenderDeviceDriver
+{
+        IFX_RenderDeviceDriver* m_poParent;
+        CFX_RenderDevice* m_pDevice;
+
+        int bEnableVector;
+        int bEnableText;
+        int bEnableBitmap;
+        int bTemporaryEnableVectorForTextStroking;
+
+public:
+
+    GDALPDFiumRenderDeviceDriver(IFX_RenderDeviceDriver* poParent, CFX_RenderDevice* pDevice):
+                                                        m_poParent(poParent),
+                                                        m_pDevice(pDevice),
+                                                        bEnableVector(TRUE),
+                                                        bEnableText(TRUE),
+                                                        bEnableBitmap(TRUE),
+                                                        bTemporaryEnableVectorForTextStroking(FALSE) {}
+    ~GDALPDFiumRenderDeviceDriver() { delete m_poParent; }
+
+    void SetEnableVector(int bFlag) { bEnableVector = bFlag; }
+    void SetEnableText(int bFlag) { bEnableText = bFlag; }
+    void SetEnableBitmap(int bFlag) { bEnableBitmap = bFlag; }
+
+    virtual void Begin() override { m_poParent->Begin(); }
+    virtual void End() override { m_poParent->End(); }
+    virtual int         GetDeviceCaps(int caps_id) override { return m_poParent->GetDeviceCaps(caps_id); }
+    virtual CFX_Matrix  GetCTM() const override { return m_poParent->GetCTM(); }
+    virtual FX_BOOL IsPSPrintDriver() override { return m_poParent->IsPSPrintDriver(); }
+    virtual FX_BOOL     StartRendering() override { return m_poParent->StartRendering(); }
+    virtual void        EndRendering() override { m_poParent->EndRendering(); }
+    virtual void        SaveState() override { m_poParent->SaveState(); }
+    virtual void        RestoreState(FX_BOOL bKeepSaved = FALSE) override { m_poParent->RestoreState(bKeepSaved); }
+
+    virtual FX_BOOL     SetClip_PathFill(const CFX_PathData* pPathData,
+                                     const CFX_AffineMatrix* pObject2Device,
+                                     int fill_mode
+                                    ) override
+    {
+        if( !bEnableVector && !bTemporaryEnableVectorForTextStroking )
+            return TRUE;
+        return m_poParent->SetClip_PathFill(pPathData, pObject2Device, fill_mode);
+    }
+
+    virtual FX_BOOL     SetClip_PathStroke(const CFX_PathData* pPathData,
+                                       const CFX_AffineMatrix* pObject2Device,
+                                       const CFX_GraphStateData* pGraphState
+                                      ) override
+    {
+        if( !bEnableVector && !bTemporaryEnableVectorForTextStroking )
+            return TRUE;
+        return m_poParent->SetClip_PathStroke(pPathData, pObject2Device, pGraphState);
+    }
+
+    virtual FX_BOOL     DrawPath(const CFX_PathData* pPathData,
+                             const CFX_AffineMatrix* pObject2Device,
+                             const CFX_GraphStateData* pGraphState,
+                             FX_DWORD fill_color,
+                             FX_DWORD stroke_color,
+                             int fill_mode,
+                             int alpha_flag = 0,
+                             void* pIccTransform = NULL,
+                             int blend_type = FXDIB_BLEND_NORMAL
+                            )  override
+    {
+        if( !bEnableVector && !bTemporaryEnableVectorForTextStroking )
+            return TRUE;
+        return m_poParent->DrawPath(pPathData, pObject2Device, pGraphState ,
+                                    fill_color, stroke_color, fill_mode,
+                                    alpha_flag, pIccTransform, blend_type);
+    }
+
+    virtual FX_BOOL     SetPixel(int x, int y, FX_DWORD color,
+                             int alpha_flag = 0, void* pIccTransform = NULL) override
+    {
+        if( !bEnableBitmap && !bTemporaryEnableVectorForTextStroking )
+            return TRUE;
+        return m_poParent->SetPixel(x,y,color,alpha_flag,pIccTransform);
+    }
+
+    virtual FX_BOOL FillRect(const FX_RECT* pRect, FX_DWORD fill_color,
+                             int alpha_flag = 0, void* pIccTransform = NULL, int blend_type = FXDIB_BLEND_NORMAL) override
+    {
+        return m_poParent->FillRect(pRect,fill_color,alpha_flag,pIccTransform,blend_type);
+    }
+
+    virtual FX_BOOL     DrawCosmeticLine(FX_FLOAT x1, FX_FLOAT y1, FX_FLOAT x2, FX_FLOAT y2, FX_DWORD color,
+                                     int alpha_flag = 0, void* pIccTransform = NULL, int blend_type = FXDIB_BLEND_NORMAL) override
+    {
+        if( !bEnableVector && !bTemporaryEnableVectorForTextStroking )
+            return TRUE;
+        return m_poParent->DrawCosmeticLine(x1,y1,x2,y2,color,alpha_flag,pIccTransform,blend_type);
+    }
+
+    virtual FX_BOOL GetClipBox(FX_RECT* pRect)  override
+    {
+        return m_poParent->GetClipBox(pRect);
+    }
+
+    virtual FX_BOOL     GetDIBits(CFX_DIBitmap* pBitmap, int left, int top, void* pIccTransform = NULL, FX_BOOL bDEdge = FALSE) override
+    {
+        return m_poParent->GetDIBits(pBitmap,left,top, pIccTransform, bDEdge);
+    }
+    virtual CFX_DIBitmap*   GetBackDrop() override
+    {
+        return m_poParent->GetBackDrop();
+    }
+
+    virtual FX_BOOL     SetDIBits(const CFX_DIBSource* pBitmap, FX_DWORD color, const FX_RECT* pSrcRect,
+                              int dest_left, int dest_top, int blend_type,
+                              int alpha_flag = 0, void* pIccTransform = NULL) override
+    {
+        if( !bEnableBitmap && !bTemporaryEnableVectorForTextStroking )
+            return TRUE;
+        return m_poParent->SetDIBits(pBitmap, color, pSrcRect,
+                                     dest_left, dest_top, blend_type,
+                                     alpha_flag, pIccTransform);
+    }
+
+    virtual FX_BOOL     StretchDIBits(const CFX_DIBSource* pBitmap, FX_DWORD color, int dest_left, int dest_top,
+                                  int dest_width, int dest_height, const FX_RECT* pClipRect, FX_DWORD flags,
+                                  int alpha_flag = 0, void* pIccTransform = NULL, int blend_type = FXDIB_BLEND_NORMAL) override
+    {
+        if( !bEnableBitmap && !bTemporaryEnableVectorForTextStroking )
+            return TRUE;
+        return m_poParent->StretchDIBits(pBitmap, color, dest_left, dest_top,
+                                     dest_width, dest_height, pClipRect, flags,
+                                     alpha_flag, pIccTransform, blend_type);
+    }
+
+    virtual FX_BOOL     StartDIBits(const CFX_DIBSource* pBitmap, int bitmap_alpha, FX_DWORD color,
+                                const CFX_AffineMatrix* pMatrix, FX_DWORD flags, void*& handle,
+                                int alpha_flag = 0, void* pIccTransform = NULL, int blend_type = FXDIB_BLEND_NORMAL) override
+    {
+        if( !bEnableBitmap && !bTemporaryEnableVectorForTextStroking )
+            return TRUE;
+        return m_poParent->StartDIBits(pBitmap, bitmap_alpha, color, pMatrix, flags,
+                                       handle, alpha_flag, pIccTransform, blend_type);
+    }
+
+    virtual FX_BOOL     ContinueDIBits(void* handle, IFX_Pause* pPause) override
+    {
+        return m_poParent->ContinueDIBits(handle, pPause);
+    }
+
+    virtual void        CancelDIBits(void* handle) override
+    {
+        m_poParent->CancelDIBits(handle);
+    }
+
+    virtual FX_BOOL DrawDeviceText(int nChars, const FXTEXT_CHARPOS* pCharPos, CFX_Font* pFont,
+                                   CFX_FontCache* pCache, const CFX_AffineMatrix* pObject2Device, FX_FLOAT font_size, FX_DWORD color,
+                                   int alpha_flag = 0, void* pIccTransform = NULL) override
+    {
+        if( bEnableText )
+        {
+            // This is quite tricky. We call again the guy who called us (CFX_RenderDevice::DrawNormalText())
+            // but we set a special flag to allow vector&raster operations so
+            // that the rendering will happen in the next phase
+            if( bTemporaryEnableVectorForTextStroking )
+                return FALSE; // this is the default behaviour of the parent
+            bTemporaryEnableVectorForTextStroking = TRUE;
+            FX_BOOL bRet = m_pDevice->DrawNormalText(nChars, pCharPos,
+                                                     pFont, pCache,
+                                                     font_size, pObject2Device,
+                                                     color, 0 /* text_flags */,
+                                                     alpha_flag, pIccTransform);
+            bTemporaryEnableVectorForTextStroking = FALSE;
+            return bRet;
+        }
+        else
+            return TRUE; // pretend that we did the job
+        //return m_poParent->DrawDeviceText(nChars, pCharPos, pFont,
+        //                                  pCache, pObject2Device, font_size, color,
+        //                                  alpha_flag, pIccTransform);
+    }
+
+    virtual void*       GetPlatformSurface() override
+    {
+        return m_poParent->GetPlatformSurface();
+    }
+
+    virtual int         GetDriverType() override
+    {
+        return m_poParent->GetDriverType();
+    }
+
+    virtual void    ClearDriver() override { m_poParent->ClearDriver(); }
+};
+
+/************************************************************************/
+/*                         PDFiumRenderPageBitmap()                     */
+/************************************************************************/
+
+/* This method is a customization of FPDF_RenderPageBitmap() and FPDF_RenderPage_Retail()
+   from pdfium/fpdfsdk/src/fpdfview.cpp to allow selection of which OGC/layer are
+   active. Thus it inherits the following license */
+// Copyright 2014 PDFium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+void PDFDataset::PDFiumRenderPageBitmap(FPDF_BITMAP bitmap, FPDF_PAGE page,
+                                        int start_x, int start_y,
+                                        int size_x, int size_y,
+                                        const char* pszRenderingOptions)
+{
+    CPDF_Page* pPage = (CPDF_Page*)page;
+
+    CRenderContext* pContext = new CRenderContext;
+    pPage->SetPrivateData((void*)1, pContext, DropContext);
+
+    CFX_FxgeDevice* pDevice = new CFX_FxgeDevice;
+
+    // The 3 following lines are basically CFX_FxgeDevice::Attach()
+    // except that we wrap the RenderDeviceDriver with our own class
+    pDevice->SetBitmap((CFX_DIBitmap*)bitmap);
+    IFX_RenderDeviceDriver* pDriver = IFX_RenderDeviceDriver::CreateFxgeDriver((CFX_DIBitmap*)bitmap);
+    if (pszRenderingOptions != NULL)
+    {
+        int bEnableVector = FALSE;
+        int bEnableText = FALSE;
+        int bEnableBitmap = FALSE;
+
+        char** papszTokens = CSLTokenizeString2( pszRenderingOptions, " ,", 0 );
+        for(int i=0;papszTokens[i] != NULL;i++)
+        {
+            if (EQUAL(papszTokens[i], "VECTOR"))
+                bEnableVector = TRUE;
+            else if (EQUAL(papszTokens[i], "TEXT"))
+                bEnableText = TRUE;
+            else if (EQUAL(papszTokens[i], "RASTER") ||
+                        EQUAL(papszTokens[i], "BITMAP"))
+                bEnableBitmap = TRUE;
+            else
+            {
+                CPLError(CE_Warning, CPLE_NotSupported,
+                            "Value %s is not a valid value for GDAL_PDF_RENDERING_OPTIONS",
+                            papszTokens[i]);
+            }
+        }
+        CSLDestroy(papszTokens);
+
+        if( !bEnableVector || !bEnableText || !bEnableBitmap )
+        {
+            GDALPDFiumRenderDeviceDriver* poGDALRDDriver = new GDALPDFiumRenderDeviceDriver(pDriver, pDevice);
+            poGDALRDDriver->SetEnableVector(bEnableVector);
+            poGDALRDDriver->SetEnableText(bEnableText);
+            poGDALRDDriver->SetEnableBitmap(bEnableBitmap);
+            pDriver = poGDALRDDriver;
+        }
+    }
+
+    pDevice->SetDeviceDriver(pDriver);
+
+    pContext->m_pDevice = pDevice;
+
+    CPLAssert(pContext->m_pOptions == NULL);
+    pContext->m_pOptions = new CPDF_RenderOptions;
+
+    pContext->m_pOptions->m_pOCContext = new GDALPDFiumOCContext(
+        poParentDS ? poParentDS: this, pPage->m_pDocument);
+
+    CFX_AffineMatrix matrix;
+    pPage->GetDisplayMatrix(matrix, start_x, start_y, size_x, size_y, 0);
+
+    FX_RECT clip;
+    clip.left = start_x;
+    clip.right = start_x + size_x;
+    clip.top = start_y;
+    clip.bottom = start_y + size_y;
+    pContext->m_pDevice->SaveState();
+    pContext->m_pDevice->SetClip_Rect(&clip);
+
+    pContext->m_pContext = new CPDF_RenderContext;
+    pContext->m_pContext->Create(pPage);
+    pContext->m_pContext->AppendObjectList(pPage, &matrix);
+
+    pContext->m_pRenderer = new CPDF_ProgressiveRenderer(
+        pContext->m_pContext, pContext->m_pDevice, pContext->m_pOptions);
+    pContext->m_pRenderer->Start(NULL);
+    pContext->m_pDevice->RestoreState();
+
+    delete pContext;
+    pPage->RemovePrivateData((void*)1);
+}
+
+#endif /* HAVE_PDFIUM */
+
 /************************************************************************/
 /*                             ReadPixels()                             */
 /************************************************************************/
@@ -887,7 +1705,7 @@ CPLErr PDFDataset::ReadPixels( int nReqXOff, int nReqYOff,
     const char* pszRenderingOptions = GetOption(papszOpenOptions, "RENDERING_OPTIONS", NULL);
 
 #ifdef HAVE_POPPLER
-    if(bUsePoppler)
+    if(bUseLib.test(PDFLIB_POPPLER))
     {
         SplashColor sColor;
         sColor[0] = 255;
@@ -1004,23 +1822,23 @@ CPLErr PDFDataset::ReadPixels( int nReqXOff, int nReqYOff,
 #endif // HAVE_POPPLER
 
 #ifdef HAVE_PODOFO
-    if (!bUsePoppler)
+    if (bUseLib.test(PDFLIB_PODOFO))
     {
         if( bPdfToPpmFailed )
             return CE_Failure;
 
-        if (pszRenderingOptions != NULL)
+        if( pszRenderingOptions != NULL && !EQUAL(pszRenderingOptions,"RASTER,VECTOR,TEXT") )
         {
             CPLError(CE_Warning, CPLE_NotSupported,
                         "GDAL_PDF_RENDERING_OPTIONS only supported "
-                        "when PDF driver is compiled against Poppler.");
+                        "when PDF lib is Poppler.");
         }
 
         CPLString osTmpFilename;
         int nRet;
 
 #ifdef notdef
-        int bUseSpawn = CSLTestBoolean(CPLGetConfigOption("GDAL_PDF_USE_SPAWN", "YES"));
+        int bUseSpawn = CPLTestBool(CPLGetConfigOption("GDAL_PDF_USE_SPAWN", "YES"));
         if( !bUseSpawn )
         {
             CPLString osCmd = CPLSPrintf("pdftoppm -r %f -x %d -y %d -W %d -H %d -f %d -l %d \"%s\"",
@@ -1089,31 +1907,157 @@ CPLErr PDFDataset::ReadPixels( int nReqXOff, int nReqYOff,
 
         if (nRet == 0)
         {
-            GDALDataset* poDS = (GDALDataset*) GDALOpen(osTmpFilename, GA_ReadOnly);
-            if (poDS)
+            GDALDataset* poDS = (GDALDataset*) GDALOpen(osTmpFilename, GA_ReadOnly);
+            if (poDS)
+            {
+                if (poDS->GetRasterCount() == 3)
+                {
+                    eErr = poDS->RasterIO(GF_Read, 0, 0,
+                                          nReqXSize,
+                                          nReqYSize,
+                                          pabyData,
+                                          nReqXSize, nReqYSize,
+                                          GDT_Byte, 3, NULL,
+                                          nPixelSpace, nLineSpace, nBandSpace, NULL);
+                }
+                delete poDS;
+            }
+        }
+        else
+        {
+            CPLDebug("PDF", "Ret code = %d", nRet);
+            bPdfToPpmFailed = TRUE;
+            eErr = CE_Failure;
+        }
+        VSIUnlink(osTmpFilename);
+    }
+#endif  // HAVE_PODOFO
+#ifdef HAVE_PDFIUM
+    if (bUseLib.test(PDFLIB_PDFIUM))
+    {
+        if(!poPagePdfium) {
+            return CE_Failure;
+        }
+
+        // Pdfium does not support multithreading
+        CPLCreateOrAcquireMutex(&g_oPdfiumReadMutex, PDFIUM_MUTEX_TIMEOUT);
+
+        CPLCreateOrAcquireMutex(&(poPagePdfium->readMutex), PDFIUM_MUTEX_TIMEOUT);
+
+        // Parsing content required before rastering
+        // can takes too long for PDF with large number of objects/layers
+        poPagePdfium->page->ParseContent();
+
+        FPDF_BITMAP bitmap = FPDFBitmap_Create(nReqXSize, nReqYSize, nBands == 4/*alpha*/);
+        // As coded now, FPDFBitmap_Create cannot allocate more than 1 GB
+        if( bitmap == NULL )
+        {
+            // Release mutex - following code is thread-safe
+            CPLReleaseMutex(poPagePdfium->readMutex);
+            CPLReleaseMutex(g_oPdfiumReadMutex);
+
+#ifdef notdef
+            // If the requested area is not too small, then try subdividing
+            if( (GIntBig)nReqXSize * nReqYSize * 4 > 1024 * 1024 )
+            {
+#ifdef DEBUG
+                CPLDebug("PDF", "Subdividing PDFDataset::ReadPixels(%d, %d, %d, %d, scaleFactor=%d)",
+                    nReqXOff, nReqYOff, nReqXSize, nReqYSize,
+                    1 << ((PDFRasterBand*)GetRasterBand(1))->nResolutionLevel);
+#endif
+                if( nReqXSize >= nReqYSize )
+                {
+                    eErr = ReadPixels( nReqXOff, nReqYOff,
+                                        nReqXSize / 2, nReqYSize,
+                                        nPixelSpace, nLineSpace, nBandSpace,
+                                        pabyData );
+                    if( eErr == CE_None )
+                    {
+                        eErr = ReadPixels( nReqXSize / 2, nReqYOff,
+                                            nReqXSize - nReqXSize / 2, nReqYSize,
+                                            nPixelSpace, nLineSpace, nBandSpace,
+                                            pabyData + nPixelSpace * (nReqXSize / 2) );
+                    }
+                }
+                else
+                {
+                    eErr = ReadPixels( nReqXOff, nReqYOff,
+                                        nReqXSize, nReqYSize - nReqYSize / 2,
+                                        nPixelSpace, nLineSpace, nBandSpace,
+                                        pabyData );
+                    if( eErr == CE_None )
+                    {
+                        eErr = ReadPixels( nReqXOff, nReqYSize / 2,
+                                            nReqXSize, nReqYSize - nReqYSize / 2,
+                                            nPixelSpace, nLineSpace, nBandSpace,
+                                            pabyData + nLineSpace * (nReqYSize / 2) );
+                    }
+                }
+                return eErr;
+            }
+#endif
+
+            CPLError(CE_Failure, CPLE_AppDefined, "FPDFBitmap_Create(%d,%d) failed",
+                     nReqXSize, nReqYSize);
+
+            return CE_Failure;
+        }
+        // alpha is 0% which is transported to FF if not alpha
+        // Default background color is white
+        FPDF_DWORD color = 0x00FFFFFF; // A,R,G,B
+        FPDFBitmap_FillRect(bitmap, 0, 0, nReqXSize, nReqYSize, color);
+
+#ifdef DEBUG
+        // start_x, start_y, size_x, size_y, rotate, flags
+        CPLDebug("PDF", "PDFDataset::ReadPixels(%d, %d, %d, %d, scaleFactor=%d)",
+            nReqXOff, nReqYOff, nReqXSize, nReqYSize,
+            1 << ((PDFRasterBand*)GetRasterBand(1))->nResolutionLevel);
+
+        CPLDebug("PDF", "FPDF_RenderPageBitmap(%d, %d, %d, %d)",
+                 -nReqXOff, -nReqYOff, nRasterXSize, nRasterYSize);
+#endif
+
+        // Part of PDF is render with -x, -y, page_width, page_height
+        // (not requested size!)
+        PDFiumRenderPageBitmap(bitmap, poPagePdfium->page,
+              -nReqXOff, -nReqYOff, nRasterXSize, nRasterYSize, pszRenderingOptions);
+
+        int stride = FPDFBitmap_GetStride(bitmap);
+        const GByte* buffer = reinterpret_cast<const GByte*>(FPDFBitmap_GetBuffer(bitmap));
+
+        // Release mutex - following code is thread-safe
+        CPLReleaseMutex(poPagePdfium->readMutex);
+        CPLReleaseMutex(g_oPdfiumReadMutex);
+
+        // Source data is B, G, R, unused.
+        // Destination data is R, G, B (,A if is alpha)
+        GByte* pabyDataR = pabyData;
+        GByte* pabyDataG = pabyData + 1 * nBandSpace;
+        GByte* pabyDataB = pabyData + 2 * nBandSpace;
+        GByte* pabyDataA = pabyData + 3 * nBandSpace;
+        // Copied from Poppler
+        int i, j;
+        for(j=0;j<nReqYSize;j++)
+        {
+            for(i=0;i<nReqXSize;i++)
             {
-                if (poDS->GetRasterCount() == 3)
+                pabyDataR[i * nPixelSpace] = buffer[(i*4) + 2];
+                pabyDataG[i * nPixelSpace] = buffer[(i*4) + 1];
+                pabyDataB[i * nPixelSpace] = buffer[(i*4) + 0];
+                if (nBands == 4)
                 {
-                    eErr = poDS->RasterIO(GF_Read, 0, 0,
-                                          nReqXSize,
-                                          nReqYSize,
-                                          pabyData,
-                                          nReqXSize, nReqYSize,
-                                          GDT_Byte, 3, NULL,
-                                          nPixelSpace, nLineSpace, nBandSpace, NULL);
+                    pabyDataA[i * nPixelSpace] = buffer[(i*4) + 3];
                 }
-                delete poDS;
             }
+            pabyDataR += nLineSpace;
+            pabyDataG += nLineSpace;
+            pabyDataB += nLineSpace;
+            pabyDataA += nLineSpace;
+            buffer += stride;
         }
-        else
-        {
-            CPLDebug("PDF", "Ret code = %d", nRet);
-            bPdfToPpmFailed = TRUE;
-            eErr = CE_Failure;
-        }
-        VSIUnlink(osTmpFilename);
+        FPDFBitmap_Destroy(bitmap);
     }
-#endif
+#endif  // ~ HAVE_PDFIUM
 
     return eErr;
 }
@@ -1140,7 +2084,7 @@ class PDFImageRasterBand : public PDFRasterBand
 /*                        PDFImageRasterBand()                          */
 /************************************************************************/
 
-PDFImageRasterBand::PDFImageRasterBand( PDFDataset *poDS, int nBand ) : PDFRasterBand(poDS, nBand)
+PDFImageRasterBand::PDFImageRasterBand( PDFDataset *poDSIn, int nBandIn ) : PDFRasterBand(poDSIn, nBandIn, 0)
 
 {
 }
@@ -1207,12 +2151,17 @@ CPLErr PDFImageRasterBand::IReadBlock( int CPL_UNUSED nBlockXOff, int nBlockYOff
 }
 
 /************************************************************************/
-/*                            ~PDFDataset()                            */
+/*                            PDFDataset()                              */
 /************************************************************************/
 
-PDFDataset::PDFDataset()
+PDFDataset::PDFDataset(PDFDataset* poParentDSIn, int nXSize, int nYSize)
 {
-    bUsePoppler = FALSE;
+    poParentDS = poParentDSIn;
+    nRasterXSize = nXSize;
+    nRasterYSize = nYSize;
+    bUseLib.reset();
+    if( poParentDSIn )
+        bUseLib = poParentDS->bUseLib;
 #ifdef HAVE_POPPLER
     poDocPoppler = NULL;
 #endif
@@ -1220,6 +2169,11 @@ PDFDataset::PDFDataset()
     poDocPodofo = NULL;
     bPdfToPpmFailed = FALSE;
 #endif
+#ifdef HAVE_PDFIUM
+    poDocPdfium = poParentDSIn ? poParentDSIn->poDocPdfium: NULL;
+    poPagePdfium = poParentDSIn ? poParentDSIn->poPagePdfium: NULL;
+#endif
+    poPageObj = NULL;
     poImageObj = NULL;
     pszWKT = NULL;
     dfDPI = GDAL_DEFAULT_DPI;
@@ -1259,11 +2213,43 @@ PDFDataset::PDFDataset()
 
     dfPageWidth = dfPageHeight = 0;
 
-    bSetStyle = CSLTestBoolean(CPLGetConfigOption("OGR_PDF_SET_STYLE", "YES"));
+    bSetStyle = CPLTestBool(CPLGetConfigOption("OGR_PDF_SET_STYLE", "YES"));
 
     InitMapOperators();
 }
 
+#ifdef HAVE_PDFIUM
+
+/************************************************************************/
+/*                          IBuildOverviews()                           */
+/************************************************************************/
+
+CPLErr PDFDataset::IBuildOverviews( const char *pszResampling,
+                                       int nOverviews, int *panOverviewList,
+                                       int nListBands, int *panBandList,
+                                       GDALProgressFunc pfnProgress,
+                                       void *pProgressData )
+
+{
+/* -------------------------------------------------------------------- */
+/*      In order for building external overviews to work properly we    */
+/*      discard any concept of internal overviews when the user         */
+/*      first requests to build external overviews.                     */
+/* -------------------------------------------------------------------- */
+    if( apoOvrDS.size() )
+    {
+        apoOvrDSBackup = apoOvrDS;
+        apoOvrDS.clear();
+    }
+
+    return GDALPamDataset::IBuildOverviews( pszResampling,
+                                            nOverviews, panOverviewList,
+                                            nListBands, panBandList,
+                                            pfnProgress, pProgressData );
+}
+
+#endif  // ~ HAVE_PDFIUM
+
 /************************************************************************/
 /*                           PDFFreeDoc()                               */
 /************************************************************************/
@@ -1294,17 +2280,17 @@ GDALPDFObject* PDFDataset::GetCatalog()
         return poCatalogObject;
 
 #ifdef HAVE_POPPLER
-    if (bUsePoppler)
+    if (bUseLib.test(PDFLIB_POPPLER))
     {
         poCatalogObjectPoppler = new ObjectAutoFree;
-        poDocPoppler->getXRef()->getCatalog(poCatalogObjectPoppler);
-        if (!poCatalogObjectPoppler->isNull())
-            poCatalogObject = new GDALPDFObjectPoppler(poCatalogObjectPoppler, FALSE);
+        poDocPoppler->getXRef()->getCatalog(poCatalogObjectPoppler->getObj());
+        if (!poCatalogObjectPoppler->getObj()->isNull())
+            poCatalogObject = new GDALPDFObjectPoppler(poCatalogObjectPoppler->getObj(), FALSE);
     }
 #endif
 
 #ifdef HAVE_PODOFO
-    if (!bUsePoppler)
+    if (bUseLib.test(PDFLIB_PODOFO))
     {
         int nCatalogNum = 0, nCatalogGen = 0;
         VSILFILE* fp = VSIFOpenL(osFilename.c_str(), "rb");
@@ -1326,6 +2312,15 @@ GDALPDFObject* PDFDataset::GetCatalog()
     }
 #endif
 
+#ifdef HAVE_PDFIUM
+    if(bUseLib.test(PDFLIB_PDFIUM))
+    {
+        CPDF_Dictionary* catalog = poDocPdfium->doc->GetRoot();
+        if(catalog)
+            poCatalogObject = GDALPDFObjectPdfium::Build(catalog);
+    }
+#endif  // ~ HAVE_PDFIUM
+
     return poCatalogObject;
 }
 
@@ -1335,6 +2330,15 @@ GDALPDFObject* PDFDataset::GetCatalog()
 
 PDFDataset::~PDFDataset()
 {
+#ifdef HAVE_PDFIUM
+    for(size_t i=0;i<apoOvrDS.size();i++)
+        delete apoOvrDS[i];
+    apoOvrDS.clear();
+    for(size_t i=0;i<apoOvrDSBackup.size();i++)
+        delete apoOvrDSBackup[i];
+    apoOvrDSBackup.clear();
+#endif
+
     CPLFree(pabyCachedData);
     pabyCachedData = NULL;
 
@@ -1342,24 +2346,29 @@ PDFDataset::~PDFDataset()
     poNeatLine = NULL;
 
     /* Collect data necessary to update */
-    int nNum = poPageObj->GetRefNum();
-    int nGen = poPageObj->GetRefGen();
+    int nNum = 0;
+    int nGen = 0;
     GDALPDFDictionaryRW* poPageDictCopy = NULL;
     GDALPDFDictionaryRW* poCatalogDictCopy = NULL;
-    if (eAccess == GA_Update &&
-        (bProjDirty || bNeatLineDirty || bInfoDirty || bXMPDirty) &&
-        nNum != 0 &&
-        poPageObj != NULL &&
-        poPageObj->GetType() == PDFObjectType_Dictionary)
-    {
-        poPageDictCopy = poPageObj->GetDictionary()->Clone();
-
-        if (bXMPDirty)
+    if( poPageObj )
+    {
+        nNum = poPageObj->GetRefNum();
+        nGen = poPageObj->GetRefGen();
+        if (eAccess == GA_Update &&
+            (bProjDirty || bNeatLineDirty || bInfoDirty || bXMPDirty) &&
+            nNum != 0 &&
+            poPageObj != NULL &&
+            poPageObj->GetType() == PDFObjectType_Dictionary)
         {
-            /* We need the catalog because it points to the XMP Metadata object */
-            GetCatalog();
-            if (poCatalogObject && poCatalogObject->GetType() == PDFObjectType_Dictionary)
-                poCatalogDictCopy = poCatalogObject->GetDictionary()->Clone();
+            poPageDictCopy = poPageObj->GetDictionary()->Clone();
+
+            if (bXMPDirty)
+            {
+                /* We need the catalog because it points to the XMP Metadata object */
+                GetCatalog();
+                if (poCatalogObject && poCatalogObject->GetType() == PDFObjectType_Dictionary)
+                    poCatalogDictCopy = poCatalogObject->GetDictionary()->Clone();
+            }
         }
     }
 
@@ -1370,14 +2379,28 @@ PDFDataset::~PDFDataset()
     delete poCatalogObject;
     poCatalogObject = NULL;
 #ifdef HAVE_POPPLER
-    delete poCatalogObjectPoppler;
-    PDFFreeDoc(poDocPoppler);
+    if(bUseLib.test(PDFLIB_POPPLER)) {
+        delete poCatalogObjectPoppler;
+        PDFFreeDoc(poDocPoppler);
+    }
     poDocPoppler = NULL;
 #endif
 #ifdef HAVE_PODOFO
-    delete poDocPodofo;
+    if(bUseLib.test(PDFLIB_PODOFO)) {
+        delete poDocPodofo;
+    }
     poDocPodofo = NULL;
 #endif
+#ifdef HAVE_PDFIUM
+    if( poParentDS == NULL )
+    {
+        if(bUseLib.test(PDFLIB_PDFIUM)) {
+            UnloadPdfiumDocumentPage(&poDocPdfium, &poPagePdfium);
+        }
+    }
+    poDocPdfium = NULL;
+    poPagePdfium = NULL;
+#endif  // ~ HAVE_PDFIUM
 
     /* Now do the update */
     if (poPageDictCopy)
@@ -1437,13 +2460,14 @@ PDFDataset::~PDFDataset()
 CPLErr PDFDataset::IRasterIO( GDALRWFlag eRWFlag,
                               int nXOff, int nYOff, int nXSize, int nYSize,
                               void * pData, int nBufXSize, int nBufYSize,
-                              GDALDataType eBufType, 
+                              GDALDataType eBufType,
                               int nBandCount, int *panBandMap,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
                               GSpacing nBandSpace,
                               GDALRasterIOExtraArg* psExtraArg)
 {
     int nBandBlockXSize, nBandBlockYSize;
+    int bReadPixels = FALSE;
     GetRasterBand(1)->GetBlockSize(&nBandBlockXSize, &nBandBlockYSize);
     if( aiTiles.size() == 0 &&
         eRWFlag == GF_Read && nXSize == nBufXSize && nYSize == nBufYSize &&
@@ -1452,41 +2476,89 @@ CPLErr PDFDataset::IRasterIO( GDALRWFlag eRWFlag,
         (nBands >= 3 && panBandMap[0] == 1 && panBandMap[1] == 2 &&
          panBandMap[2] == 3 && ( nBands == 3 || panBandMap[3] == 4)) )
     {
-        int bReadPixels = TRUE;
+        bReadPixels = TRUE;
 #ifdef HAVE_PODOFO
-        if (!bUsePoppler && nBands == 4)
+        if (bUseLib.test(PDFLIB_PODOFO) && nBands == 4)
         {
             bReadPixels = FALSE;
         }
 #endif
-        if( bReadPixels )
-            return ReadPixels(nXOff, nYOff, nXSize, nYSize,
-                              nPixelSpace, nLineSpace, nBandSpace, (GByte*)pData);
     }
 
+    if( bReadPixels )
+        return ReadPixels(nXOff, nYOff, nXSize, nYSize,
+                          nPixelSpace, nLineSpace, nBandSpace, (GByte*)pData);
+
     return GDALPamDataset::IRasterIO( eRWFlag,
                                         nXOff, nYOff, nXSize, nYSize,
                                         pData, nBufXSize, nBufYSize,
-                                        eBufType, 
+                                        eBufType,
                                         nBandCount, panBandMap,
                                         nPixelSpace, nLineSpace, nBandSpace, psExtraArg );
 }
 
+#ifdef notdef
+/************************************************************************/
+/*                            IRasterIO()                               */
+/************************************************************************/
+
+CPLErr PDFRasterBand::IRasterIO( GDALRWFlag eRWFlag,
+                              int nXOff, int nYOff, int nXSize, int nYSize,
+                              void * pData, int nBufXSize, int nBufYSize,
+                              GDALDataType eBufType,
+                              GSpacing nPixelSpace, GSpacing nLineSpace,
+                              GDALRasterIOExtraArg* psExtraArg)
+{
+    PDFDataset *poGDS = (PDFDataset *) poDS;
+    int bReadPixels = FALSE;
+    if( poGDS->aiTiles.size() == 0 &&
+        eRWFlag == GF_Read && nXSize == nBufXSize && nYSize == nBufYSize &&
+        (nBufXSize > nBlockXSize || nBufYSize > nBlockYSize) &&
+        eBufType == GDT_Byte )
+    {
+        bReadPixels = TRUE;
+#ifdef HAVE_PODOFO
+        if (poGDS->bUseLib.test(PDFLIB_PODOFO) && poGDS->nBands == 4)
+        {
+            bReadPixels = FALSE;
+        }
+#endif
+    }
+
+    if( bReadPixels )
+    {
+        CPLErr eErr = ReadPixels(nXOff, nYOff, nXSize, nYSize,
+                                 nPixelSpace, nLineSpace, 0, NULL);
+        if( eErr == CE_None )
+        {
+
+        }
+        return eErr;
+    }
+
+    return GDALPamRasterBand::IRasterIO( eRWFlag,
+                                        nXOff, nYOff, nXSize, nYSize,
+                                        pData, nBufXSize, nBufYSize,
+                                        eBufType,
+                                        nPixelSpace, nLineSpace, psExtraArg );
+}
+#endif
+
 /************************************************************************/
 /*                             Identify()                               */
 /************************************************************************/
 
 int PDFDataset::Identify( GDALOpenInfo * poOpenInfo )
 {
-    if (strncmp(poOpenInfo->pszFilename, "PDF:", 4) == 0)
+    if (STARTS_WITH(poOpenInfo->pszFilename, "PDF:"))
         return TRUE;
-    if (strncmp(poOpenInfo->pszFilename, "PDF_IMAGE:", 10) == 0)
+    if (STARTS_WITH(poOpenInfo->pszFilename, "PDF_IMAGE:"))
         return TRUE;
 
     if (poOpenInfo->nHeaderBytes < 128)
         return FALSE;
 
-    return strncmp((const char*)poOpenInfo->pabyHeader, "%PDF", 4) == 0;
+    return STARTS_WITH((const char*)poOpenInfo->pabyHeader, "%PDF");
 }
 
 /************************************************************************/
@@ -1510,7 +2582,7 @@ static void PDFDatasetErrorFunctionCommon(const CPLString& osError)
 }
 
 #ifdef POPPLER_0_20_OR_LATER
-static void PDFDatasetErrorFunction(CPL_UNUSED void* userData, CPL_UNUSED ErrorCategory eErrCatagory,
+static void PDFDatasetErrorFunction(CPL_UNUSED void* userData, CPL_UNUSED ErrorCategory eErrCategory,
 #ifdef POPPLER_0_23_OR_LATER
                                     Goffset nPos,
 #else
@@ -1775,7 +2847,7 @@ int GDALPDFParseStreamContent(const char* pszContent,
 int PDFDataset::CheckTiledRaster()
 {
     size_t i;
-    int nBlockXSize = 0, nBlockYSize = 0;
+    int l_nBlockXSize = 0, l_nBlockYSize = 0;
     const double dfUserUnit = dfDPI * USER_UNIT_IN_INCH;
 
     /* First pass : check that all tiles have same DPI, */
@@ -1798,7 +2870,7 @@ int PDFDataset::CheckTiledRaster()
         GDALPDFObject* poFilter = poImageDict->Get("Filter");
 
         /* Podofo cannot uncompress JPEG2000 streams */
-        if( !bUsePoppler && poFilter != NULL &&
+        if( bUseLib.test(PDFLIB_PODOFO) && poFilter != NULL &&
             poFilter->GetType() == PDFObjectType_Name &&
             poFilter->GetName() == "JPXDecode" )
         {
@@ -1833,18 +2905,18 @@ int PDFDataset::CheckTiledRaster()
                      asTiles[i].dfWidth, asTiles[i].dfHeight);
             return FALSE;
         }
-        if( nBlockXSize == 0 && nBlockYSize == 0 &&
+        if( l_nBlockXSize == 0 && l_nBlockYSize == 0 &&
             nX == 0 && nY != 0 )
         {
-            nBlockXSize = nWidth;
-            nBlockYSize = nHeight;
+            l_nBlockXSize = nWidth;
+            l_nBlockYSize = nHeight;
         }
     }
-    if( nBlockXSize <= 0 || nBlockYSize <= 0 || nBlockXSize > 2048 || nBlockYSize > 2048 )
+    if( l_nBlockXSize <= 0 || l_nBlockYSize <= 0 || l_nBlockXSize > 2048 || l_nBlockYSize > 2048 )
         return FALSE;
 
-    int nXBlocks = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
-    int nYBlocks = DIV_ROUND_UP(nRasterYSize, nBlockYSize);
+    int nXBlocks = DIV_ROUND_UP(nRasterXSize, l_nBlockXSize);
+    int nYBlocks = DIV_ROUND_UP(nRasterYSize, l_nBlockYSize);
 
     /* Second pass to determine that all tiles are properly aligned on block size */
     for(i=0; i<asTiles.size(); i++)
@@ -1856,17 +2928,17 @@ int PDFDataset::CheckTiledRaster()
         int nWidth = (int)(asTiles[i].dfWidth + 1e-8);
         int nHeight = (int)(asTiles[i].dfHeight + 1e-8);
         int bOK = TRUE;
-        int nBlockXOff = nX / nBlockXSize;
-        if( (nX % nBlockXSize) != 0 )
+        int nBlockXOff = nX / l_nBlockXSize;
+        if( (nX % l_nBlockXSize) != 0 )
             bOK = FALSE;
-        if( nBlockXOff < nXBlocks - 1 && nWidth != nBlockXSize )
+        if( nBlockXOff < nXBlocks - 1 && nWidth != l_nBlockXSize )
             bOK = FALSE;
         if( nBlockXOff == nXBlocks - 1 && nX + nWidth != nRasterXSize )
             bOK = FALSE;
 
-        if( nY > 0 && nHeight != nBlockYSize )
+        if( nY > 0 && nHeight != l_nBlockYSize )
             bOK = FALSE;
-        if( nY == 0 && nHeight != nRasterYSize - (nYBlocks - 1) * nBlockYSize)
+        if( nY == 0 && nHeight != nRasterYSize - (nYBlocks - 1) * l_nBlockYSize)
             bOK = FALSE;
 
         if( !bOK )
@@ -1886,13 +2958,13 @@ int PDFDataset::CheckTiledRaster()
         int nHeight = (int)(asTiles[i].dfHeight + 1e-8);
         int nX = (int)(dfX+0.1);
         int nY = nRasterYSize - ((int)(dfY+0.1) + nHeight);
-        int nBlockXOff = nX / nBlockXSize;
-        int nBlockYOff = nY / nBlockYSize;
+        int nBlockXOff = nX / l_nBlockXSize;
+        int nBlockYOff = nY / l_nBlockYSize;
         aiTiles[ nBlockYOff * nXBlocks + nBlockXOff ] = (int) i;
     }
 
-    this->nBlockXSize = nBlockXSize;
-    this->nBlockYSize = nBlockYSize;
+    this->nBlockXSize = l_nBlockXSize;
+    this->nBlockYSize = l_nBlockYSize;
 
     return TRUE;
 }
@@ -2027,8 +3099,7 @@ void PDFDataset::GuessDPI(GDALPDFDictionary* poPageDict, int* pnBands)
                                             else
                                                 break;
                                         }
-                                        if( strncmp(pszIter, "1 0 0 1 0 0 cm\n",
-                                                    strlen( "1 0 0 1 0 0 cm\n" )) == 0 )
+                                        if( STARTS_WITH(pszIter, "1 0 0 1 0 0 cm\n") )
                                             pszIter += strlen("1 0 0 1 0 0 cm\n");
                                         if( *pszIter == '/' )
                                         {
@@ -2063,7 +3134,7 @@ void PDFDataset::GuessDPI(GDALPDFDictionary* poPageDict, int* pnBands)
                                 poSubtype->GetType() == PDFObjectType_Name &&
                                 poSubtype->GetName() == "Form")
                             {
-                                int nLength = poPageStream->GetLength();
+                                nLength = poPageStream->GetLength();
                                 if( nLength < 100000 )
                                 {
                                     pszContent = poPageStream->GetBytes();
@@ -2090,8 +3161,8 @@ void PDFDataset::GuessDPI(GDALPDFDictionary* poPageDict, int* pnBands)
                             if( *pszContentToParse == 13 || *pszContentToParse == 10 ||
                                 *pszContentToParse == ' ' ||
                                 (*pszContentToParse >= '0' && *pszContentToParse <= '9') ||
-                                *pszContentToParse == '.' || 
-                                *pszContentToParse == '-' || 
+                                *pszContentToParse == '.' ||
+                                *pszContentToParse == '-' ||
                                 *pszContentToParse == 'l' ||
                                 *pszContentToParse == 'm' ||
                                 *pszContentToParse == 'n' ||
@@ -2130,7 +3201,7 @@ void PDFDataset::GuessDPI(GDALPDFDictionary* poPageDict, int* pnBands)
               (poUserUnit->GetType() == PDFObjectType_Int ||
                poUserUnit->GetType() == PDFObjectType_Real) )
         {
-            dfDPI = ROUND_TO_INT_IF_CLOSE(Get(poUserUnit) * DEFAULT_DPI);
+            dfDPI = ROUND_TO_INT_IF_CLOSE(Get(poUserUnit) * DEFAULT_DPI, 1e-5);
             CPLDebug("PDF", "Found UserUnit in Page --> DPI = %.16g", dfDPI);
             SetMetadataItem("DPI", CPLSPrintf("%.16g", dfDPI));
         }
@@ -2173,7 +3244,7 @@ void PDFDataset::FindXMP(GDALPDFObject* poObj)
     char* pszContent = poStream->GetBytes();
     int nLength = (int)poStream->GetLength();
     if (pszContent != NULL && nLength > 15 &&
-        strncmp(pszContent, "<?xpacket begin=", strlen("<?xpacket begin=")) == 0)
+        STARTS_WITH(pszContent, "<?xpacket begin="))
     {
         char *apszMDList[2];
         apszMDList[0] = pszContent;
@@ -2242,49 +3313,291 @@ void PDFDataset::ParseInfo(GDALPDFObject* poInfoObj)
     }
 }
 
-#ifdef HAVE_POPPLER
+#if defined(HAVE_POPPLER) || defined(HAVE_PDFIUM)
+
+/************************************************************************/
+/*                               AddLayer()                             */
+/************************************************************************/
+
+void PDFDataset::AddLayer(const char* pszLayerName)
+{
+    int nNewIndex = osLayerList.size() /*/ 2*/;
+
+    if (nNewIndex == 100)
+    {
+        CPLStringList osNewLayerList;
+        for(int i=0;i<100;i++)
+        {
+            osNewLayerList.AddNameValue(CPLSPrintf("LAYER_%03d_NAME", i),
+                                        osLayerList[/*2 * */ i] + strlen("LAYER_00_NAME="));
+        }
+        osLayerList = osNewLayerList;
+    }
+
+    char szFormatName[64];
+    snprintf(szFormatName, sizeof(szFormatName), "LAYER_%%0%dd_NAME",  nNewIndex >= 100 ? 3 : 2);
+
+    osLayerList.AddNameValue(CPLSPrintf(szFormatName, nNewIndex),
+                             pszLayerName);
+
+}
+
+#endif//  defined(HAVE_POPPLER) || defined(HAVE_PDFIUM)
+
+#ifdef HAVE_POPPLER
+
+/************************************************************************/
+/*                       ExploreLayersPoppler()                         */
+/************************************************************************/
+
+void PDFDataset::ExploreLayersPoppler(GDALPDFArray* poArray,
+                               int nRecLevel,
+                               CPLString osTopLayer)
+{
+    if( nRecLevel == 16 )
+        return;
+
+    int nLength = poArray->GetLength();
+    CPLString osCurLayer;
+    for(int i=0;i<nLength;i++)
+    {
+        GDALPDFObject* poObj = poArray->Get(i);
+        if (i == 0 && poObj->GetType() == PDFObjectType_String)
+        {
+            CPLString osName = PDFSanitizeLayerName(poObj->GetString().c_str());
+            if (osTopLayer.size())
+                osTopLayer = osTopLayer + "." + osName;
+            else
+                osTopLayer = osName;
+            AddLayer(osTopLayer.c_str());
+            oLayerOCGMapPoppler[osTopLayer.c_str()] = NULL;
+        }
+        else if (poObj->GetType() == PDFObjectType_Array)
+        {
+            ExploreLayersPoppler(poObj->GetArray(), nRecLevel + 1, osCurLayer);
+            osCurLayer = "";
+        }
+        else if (poObj->GetType() == PDFObjectType_Dictionary)
+        {
+            GDALPDFDictionary* poDict = poObj->GetDictionary();
+            GDALPDFObject* poName = poDict->Get("Name");
+            if (poName != NULL && poName->GetType() == PDFObjectType_String)
+            {
+                CPLString osName = PDFSanitizeLayerName(poName->GetString().c_str());
+                /* coverity[copy_paste_error] */
+                if (osTopLayer.size())
+                    osCurLayer = osTopLayer + "." + osName;
+                else
+                    osCurLayer = osName;
+                //CPLDebug("PDF", "Layer %s", osCurLayer.c_str());
+
+                OCGs* optContentConfig = poDocPoppler->getOptContentConfig();
+                struct Ref r;
+                r.num = poObj->GetRefNum();
+                r.gen = poObj->GetRefGen();
+                OptionalContentGroup* ocg = optContentConfig->findOcgByRef(r);
+                if (ocg)
+                {
+                    AddLayer(osCurLayer.c_str());
+                    oLayerOCGMapPoppler[osCurLayer.c_str()] = ocg;
+                    osLayerWithRefList.AddString(
+                        CPLSPrintf("%s %d %d", osCurLayer.c_str(), r.num, r.gen));
+                }
+            }
+        }
+    }
+}
+
+/************************************************************************/
+/*                         FindLayersPoppler()                          */
+/************************************************************************/
+
+void PDFDataset::FindLayersPoppler()
+{
+    OCGs* optContentConfig = poDocPoppler->getOptContentConfig();
+    if (optContentConfig == NULL || !optContentConfig->isOk() )
+        return;
+
+    Array* array = optContentConfig->getOrderArray();
+    if (array)
+    {
+        GDALPDFArray* poArray = GDALPDFCreateArray(array);
+        ExploreLayersPoppler(poArray, 0);
+        delete poArray;
+    }
+    else
+    {
+        GooList* ocgList = optContentConfig->getOCGs();
+        for(int i=0;i<ocgList->getLength();i++)
+        {
+            OptionalContentGroup* ocg = (OptionalContentGroup*) ocgList->get(i);
+            if( ocg != NULL && ocg->getName() != NULL )
+            {
+                const char* pszLayerName = (const char*)ocg->getName()->getCString();
+                AddLayer(pszLayerName);
+                oLayerOCGMapPoppler[pszLayerName] = ocg;
+            }
+        }
+    }
+
+    oMDMD.SetMetadata(osLayerList.List(), "LAYERS");
+}
+
+/************************************************************************/
+/*                       TurnLayersOnOffPoppler()                       */
+/************************************************************************/
+
+void PDFDataset::TurnLayersOnOffPoppler()
+{
+    OCGs* optContentConfig = poDocPoppler->getOptContentConfig();
+    if (optContentConfig == NULL || !optContentConfig->isOk() )
+        return;
+
+    // Which layers to turn ON ?
+    const char* pszLayers = GetOption(papszOpenOptions, "LAYERS", NULL);
+    if (pszLayers)
+    {
+        int i;
+        int bAll = EQUAL(pszLayers, "ALL");
+        GooList* ocgList = optContentConfig->getOCGs();
+        for(i=0;i<ocgList->getLength();i++)
+        {
+            OptionalContentGroup* ocg = (OptionalContentGroup*) ocgList->get(i);
+            ocg->setState( (bAll) ? OptionalContentGroup::On : OptionalContentGroup::Off );
+        }
+
+        char** papszLayers = CSLTokenizeString2(pszLayers, ",", 0);
+        for(i=0;!bAll && papszLayers[i] != NULL;i++)
+        {
+            std::map<CPLString, OptionalContentGroup*>::iterator oIter =
+                oLayerOCGMapPoppler.find(papszLayers[i]);
+            if (oIter != oLayerOCGMapPoppler.end())
+            {
+                if (oIter->second)
+                {
+                    //CPLDebug("PDF", "Turn '%s' on", papszLayers[i]);
+                    oIter->second->setState(OptionalContentGroup::On);
+                }
+
+                // Turn child layers on, unless there's one of them explicitly listed
+                // in the list.
+                size_t nLen = strlen(papszLayers[i]);
+                int bFoundChildLayer = FALSE;
+                oIter = oLayerOCGMapPoppler.begin();
+                for( ; oIter != oLayerOCGMapPoppler.end() && !bFoundChildLayer; oIter ++)
+                {
+                    if (oIter->first.size() > nLen &&
+                        strncmp(oIter->first.c_str(), papszLayers[i], nLen) == 0 &&
+                        oIter->first[nLen] == '.')
+                    {
+                        for(int j=0;papszLayers[j] != NULL;j++)
+                        {
+                            if (strcmp(papszLayers[j], oIter->first.c_str()) == 0)
+                                bFoundChildLayer = TRUE;
+                        }
+                    }
+                }
+
+                if( !bFoundChildLayer )
+                {
+                    oIter = oLayerOCGMapPoppler.begin();
+                    for( ; oIter != oLayerOCGMapPoppler.end() && !bFoundChildLayer; oIter ++)
+                    {
+                        if (oIter->first.size() > nLen &&
+                            strncmp(oIter->first.c_str(), papszLayers[i], nLen) == 0 &&
+                            oIter->first[nLen] == '.')
+                        {
+                            if (oIter->second)
+                            {
+                                //CPLDebug("PDF", "Turn '%s' on too", oIter->first.c_str());
+                                oIter->second->setState(OptionalContentGroup::On);
+                            }
+                        }
+                    }
+                }
 
-/************************************************************************/
-/*                               AddLayer()                             */
-/************************************************************************/
+                // Turn parent layers on too
+                char* pszLastDot;
+                while( (pszLastDot = strrchr(papszLayers[i], '.')) != NULL)
+                {
+                    *pszLastDot = '\0';
+                    oIter = oLayerOCGMapPoppler.find(papszLayers[i]);
+                    if (oIter != oLayerOCGMapPoppler.end())
+                    {
+                        if (oIter->second)
+                        {
+                            //CPLDebug("PDF", "Turn '%s' on too", papszLayers[i]);
+                            oIter->second->setState(OptionalContentGroup::On);
+                        }
+                    }
+                }
+            }
+            else
+            {
+                CPLError(CE_Warning, CPLE_AppDefined, "Unknown layer '%s'",
+                            papszLayers[i]);
+            }
+        }
+        CSLDestroy(papszLayers);
 
-void PDFDataset::AddLayer(const char* pszLayerName, OptionalContentGroup* ocg)
-{
-    int nNewIndex = osLayerList.size() /*/ 2*/;
+        bUseOCG = TRUE;
+    }
 
-    if (nNewIndex == 100)
+    // Which layers to turn OFF ?
+    const char* pszLayersOFF = GetOption(papszOpenOptions, "LAYERS_OFF", NULL);
+    if (pszLayersOFF)
     {
-        CPLStringList osNewLayerList;
-        for(int i=0;i<100;i++)
+        char** papszLayersOFF = CSLTokenizeString2(pszLayersOFF, ",", 0);
+        for(int i=0;papszLayersOFF[i] != NULL;i++)
         {
-            osNewLayerList.AddNameValue(CPLSPrintf("LAYER_%03d_NAME", i),
-                                        osLayerList[/*2 * */ i] + strlen("LAYER_00_NAME="));
-            /*osNewLayerList.AddNameValue(CPLSPrintf("LAYER_%03d_INIT_STATE", i),
-                                        osLayerList[i * 2 + 1] + strlen("LAYER_00_INIT_STATE="));*/
+            std::map<CPLString, OptionalContentGroup*>::iterator oIter =
+                oLayerOCGMapPoppler.find(papszLayersOFF[i]);
+            if (oIter != oLayerOCGMapPoppler.end())
+            {
+                if (oIter->second)
+                {
+                    //CPLDebug("PDF", "Turn '%s' off", papszLayersOFF[i]);
+                    oIter->second->setState(OptionalContentGroup::Off);
+                }
+
+                // Turn child layers off too
+                size_t nLen = strlen(papszLayersOFF[i]);
+                oIter = oLayerOCGMapPoppler.begin();
+                for( ; oIter != oLayerOCGMapPoppler.end(); oIter ++)
+                {
+                    if (oIter->first.size() > nLen &&
+                        strncmp(oIter->first.c_str(), papszLayersOFF[i], nLen) == 0 &&
+                        oIter->first[nLen] == '.')
+                    {
+                        if (oIter->second)
+                        {
+                            //CPLDebug("PDF", "Turn '%s' off too", oIter->first.c_str());
+                            oIter->second->setState(OptionalContentGroup::Off);
+                        }
+                    }
+                }
+            }
+            else
+            {
+                CPLError(CE_Warning, CPLE_AppDefined, "Unknown layer '%s'",
+                            papszLayersOFF[i]);
+            }
         }
-        osLayerList = osNewLayerList;
-    }
+        CSLDestroy(papszLayersOFF);
 
-    char szFormatName[64];
-    /* char szFormatInitState[64]; */
-    sprintf(szFormatName, "LAYER_%%0%dd_NAME",  nNewIndex >= 100 ? 3 : 2);
-    /* sprintf(szFormatInitState, "LAYER_%%0%dd_INIT_STATE", nNewIndex >= 100 ? 3 : 2); */
+        bUseOCG = TRUE;
+    }
+}
 
-    osLayerList.AddNameValue(CPLSPrintf(szFormatName, nNewIndex),
-                             pszLayerName);
-    /*osLayerList.AddNameValue(CPLSPrintf(szFormatInitState, nNewIndex),
-                             (ocg == NULL || ocg->getState() == OptionalContentGroup::On) ? "ON" : "OFF");*/
-    oLayerOCGMap[pszLayerName] = ocg;
+#endif
 
-    //if (ocg != NULL && ocg->getState() == OptionalContentGroup::Off)
-    //    bUseOCG = TRUE;
-}
+#ifdef HAVE_PDFIUM
 
 /************************************************************************/
-/*                             ExploreLayers()                          */
+/*                       ExploreLayersPdfium()                          */
 /************************************************************************/
 
-void PDFDataset::ExploreLayers(GDALPDFArray* poArray,
+void PDFDataset::ExploreLayersPdfium(GDALPDFArray* poArray,
                                int nRecLevel,
                                CPLString osTopLayer)
 {
@@ -2303,11 +3616,13 @@ void PDFDataset::ExploreLayers(GDALPDFArray* poArray,
                 osTopLayer = osTopLayer + "." + osName;
             else
                 osTopLayer = osName;
-            AddLayer(osTopLayer.c_str(), NULL);
+            AddLayer(osTopLayer.c_str());
+            oMapLayerNameToOCGNumGenPdfium[osTopLayer] =
+                    std::pair<int,int>(-1, -1);
         }
         else if (poObj->GetType() == PDFObjectType_Array)
         {
-            ExploreLayers(poObj->GetArray(), nRecLevel + 1, osCurLayer);
+            ExploreLayersPdfium(poObj->GetArray(), nRecLevel + 1, osCurLayer);
             osCurLayer = "";
         }
         else if (poObj->GetType() == PDFObjectType_Dictionary)
@@ -2323,61 +3638,65 @@ void PDFDataset::ExploreLayers(GDALPDFArray* poArray,
                     osCurLayer = osName;
                 //CPLDebug("PDF", "Layer %s", osCurLayer.c_str());
 
-                OCGs* optContentConfig = poDocPoppler->getOptContentConfig();
-                struct Ref r;
-                r.num = poObj->GetRefNum();
-                r.gen = poObj->GetRefGen();
-                OptionalContentGroup* ocg = optContentConfig->findOcgByRef(r);
-                if (ocg)
-                {
-                    AddLayer(osCurLayer.c_str(), ocg);
-                    osLayerWithRefList.AddString(
-                        CPLSPrintf("%s %d %d", osCurLayer.c_str(), r.num, r.gen));
-                }
+                AddLayer(osCurLayer.c_str());
+                osLayerWithRefList.AddString(
+                    CPLSPrintf("%s %d %d", osCurLayer.c_str(), poObj->GetRefNum(), poObj->GetRefGen()));
+                oMapLayerNameToOCGNumGenPdfium[osCurLayer] =
+                    std::pair<int,int>(poObj->GetRefNum(), poObj->GetRefGen());
             }
         }
     }
 }
 
 /************************************************************************/
-/*                              FindLayers()                            */
+/*                         FindLayersPdfium()                          */
 /************************************************************************/
 
-void PDFDataset::FindLayers()
+void PDFDataset::FindLayersPdfium()
 {
-    OCGs* optContentConfig = poDocPoppler->getOptContentConfig();
-    if (optContentConfig == NULL || !optContentConfig->isOk() )
+    GDALPDFObject* poCatalog = GetCatalog();
+    if( poCatalog == NULL || poCatalog->GetType() != PDFObjectType_Dictionary )
         return;
-
-    Array* array = optContentConfig->getOrderArray();
-    if (array)
+    GDALPDFObject* poOrder = poCatalog->LookupObject("OCProperties.D.Order");
+    if( poOrder != NULL && poOrder->GetType() == PDFObjectType_Array )
     {
-        GDALPDFArray* poArray = GDALPDFCreateArray(array);
-        ExploreLayers(poArray, 0);
-        delete poArray;
+        ExploreLayersPdfium(poOrder->GetArray(), 0);
     }
+#if 0
     else
     {
-        GooList* ocgList = optContentConfig->getOCGs();
-        for(int i=0;i<ocgList->getLength();i++)
+        GDALPDFObject* poOCGs = poD->GetDictionary()->Get("OCGs");
+        if( poOCGs != NULL && poOCGs->GetType() == PDFObjectType_Array )
         {
-            OptionalContentGroup* ocg = (OptionalContentGroup*) ocgList->get(i);
-            if( ocg != NULL && ocg->getName() != NULL )
-                AddLayer((const char*)ocg->getName()->getCString(), ocg);
+            GDALPDFArray* poArray = poOCGs->GetArray();
+            int nLength = poArray->GetLength();
+            for(int i=0;i<nLength;i++)
+            {
+                GDALPDFObject* poObj = poArray->Get(i);
+                if( poObj != NULL )
+                {
+                    // TODO ?
+                }
+            }
         }
     }
+#endif
 
     oMDMD.SetMetadata(osLayerList.List(), "LAYERS");
 }
 
+
 /************************************************************************/
-/*                            TurnLayersOnOff()                         */
+/*                       TurnLayersOnOffPdfium()                       */
 /************************************************************************/
 
-void PDFDataset::TurnLayersOnOff()
+void PDFDataset::TurnLayersOnOffPdfium()
 {
-    OCGs* optContentConfig = poDocPoppler->getOptContentConfig();
-    if (optContentConfig == NULL || !optContentConfig->isOk() )
+    GDALPDFObject* poCatalog = GetCatalog();
+    if( poCatalog == NULL || poCatalog->GetType() != PDFObjectType_Dictionary )
+        return;
+    GDALPDFObject* poOCGs = poCatalog->LookupObject("OCProperties.OCGs");
+    if( poOCGs == NULL || poOCGs->GetType() != PDFObjectType_Array )
         return;
 
     // Which layers to turn ON ?
@@ -2386,32 +3705,35 @@ void PDFDataset::TurnLayersOnOff()
     {
         int i;
         int bAll = EQUAL(pszLayers, "ALL");
-        GooList* ocgList = optContentConfig->getOCGs();
-        for(i=0;i<ocgList->getLength();i++)
+
+        GDALPDFArray* poOCGsArray = poOCGs->GetArray();
+        int nLength = poOCGsArray->GetLength();
+        for(i=0;i<nLength;i++)
         {
-            OptionalContentGroup* ocg = (OptionalContentGroup*) ocgList->get(i);
-            ocg->setState( (bAll) ? OptionalContentGroup::On : OptionalContentGroup::Off );
+            GDALPDFObject* poOCG = poOCGsArray->Get(i);
+            oMapOCGNumGenToVisibilityStatePdfium[ std::pair<int,int>(poOCG->GetRefNum(), poOCG->GetRefGen()) ] =
+                (bAll) ? VISIBILITY_ON : VISIBILITY_OFF;
         }
 
         char** papszLayers = CSLTokenizeString2(pszLayers, ",", 0);
         for(i=0;!bAll && papszLayers[i] != NULL;i++)
         {
-            std::map<CPLString, OptionalContentGroup*>::iterator oIter =
-                oLayerOCGMap.find(papszLayers[i]);
-            if (oIter != oLayerOCGMap.end())
+            std::map< CPLString, std::pair<int,int> >::iterator oIter =
+                oMapLayerNameToOCGNumGenPdfium.find(papszLayers[i]);
+            if (oIter != oMapLayerNameToOCGNumGenPdfium.end())
             {
-                if (oIter->second)
+                if (oIter->second.first >= 0)
                 {
                     //CPLDebug("PDF", "Turn '%s' on", papszLayers[i]);
-                    oIter->second->setState(OptionalContentGroup::On);
+                    oMapOCGNumGenToVisibilityStatePdfium[ oIter->second ] = VISIBILITY_ON;
                 }
 
                 // Turn child layers on, unless there's one of them explicitly listed
                 // in the list.
                 size_t nLen = strlen(papszLayers[i]);
                 int bFoundChildLayer = FALSE;
-                oIter = oLayerOCGMap.begin();
-                for( ; oIter != oLayerOCGMap.end() && !bFoundChildLayer; oIter ++)
+                oIter = oMapLayerNameToOCGNumGenPdfium.begin();
+                for( ; oIter != oMapLayerNameToOCGNumGenPdfium.end() && !bFoundChildLayer; oIter ++)
                 {
                     if (oIter->first.size() > nLen &&
                         strncmp(oIter->first.c_str(), papszLayers[i], nLen) == 0 &&
@@ -2427,17 +3749,17 @@ void PDFDataset::TurnLayersOnOff()
 
                 if( !bFoundChildLayer )
                 {
-                    oIter = oLayerOCGMap.begin();
-                    for( ; oIter != oLayerOCGMap.end() && !bFoundChildLayer; oIter ++)
+                    oIter = oMapLayerNameToOCGNumGenPdfium.begin();
+                    for( ; oIter != oMapLayerNameToOCGNumGenPdfium.end() && !bFoundChildLayer; oIter ++)
                     {
                         if (oIter->first.size() > nLen &&
                             strncmp(oIter->first.c_str(), papszLayers[i], nLen) == 0 &&
                             oIter->first[nLen] == '.')
                         {
-                            if (oIter->second)
+                            if (oIter->second.first >= 0 )
                             {
                                 //CPLDebug("PDF", "Turn '%s' on too", oIter->first.c_str());
-                                oIter->second->setState(OptionalContentGroup::On);
+                                oMapOCGNumGenToVisibilityStatePdfium[ oIter->second ] = VISIBILITY_ON;
                             }
                         }
                     }
@@ -2448,13 +3770,13 @@ void PDFDataset::TurnLayersOnOff()
                 while( (pszLastDot = strrchr(papszLayers[i], '.')) != NULL)
                 {
                     *pszLastDot = '\0';
-                    oIter = oLayerOCGMap.find(papszLayers[i]);
-                    if (oIter != oLayerOCGMap.end())
+                    oIter = oMapLayerNameToOCGNumGenPdfium.find(papszLayers[i]);
+                    if (oIter != oMapLayerNameToOCGNumGenPdfium.end())
                     {
-                        if (oIter->second)
+                        if (oIter->second.first >= 0 )
                         {
                             //CPLDebug("PDF", "Turn '%s' on too", papszLayers[i]);
-                            oIter->second->setState(OptionalContentGroup::On);
+                            oMapOCGNumGenToVisibilityStatePdfium[ oIter->second ] = VISIBILITY_ON;
                         }
                     }
                 }
@@ -2477,29 +3799,29 @@ void PDFDataset::TurnLayersOnOff()
         char** papszLayersOFF = CSLTokenizeString2(pszLayersOFF, ",", 0);
         for(int i=0;papszLayersOFF[i] != NULL;i++)
         {
-            std::map<CPLString, OptionalContentGroup*>::iterator oIter =
-                oLayerOCGMap.find(papszLayersOFF[i]);
-            if (oIter != oLayerOCGMap.end())
+            std::map< CPLString, std::pair<int,int> >::iterator oIter =
+                oMapLayerNameToOCGNumGenPdfium.find(papszLayersOFF[i]);
+            if (oIter != oMapLayerNameToOCGNumGenPdfium.end())
             {
-                if (oIter->second)
+                if (oIter->second.first >= 0 )
                 {
                     //CPLDebug("PDF", "Turn '%s' off", papszLayersOFF[i]);
-                    oIter->second->setState(OptionalContentGroup::Off);
+                    oMapOCGNumGenToVisibilityStatePdfium[ oIter->second ] = VISIBILITY_OFF;
                 }
 
                 // Turn child layers off too
                 size_t nLen = strlen(papszLayersOFF[i]);
-                oIter = oLayerOCGMap.begin();
-                for( ; oIter != oLayerOCGMap.end(); oIter ++)
+                oIter = oMapLayerNameToOCGNumGenPdfium.begin();
+                for( ; oIter != oMapLayerNameToOCGNumGenPdfium.end(); oIter ++)
                 {
                     if (oIter->first.size() > nLen &&
                         strncmp(oIter->first.c_str(), papszLayersOFF[i], nLen) == 0 &&
                         oIter->first[nLen] == '.')
                     {
-                        if (oIter->second)
+                        if (oIter->second.first >= 0 )
                         {
                             //CPLDebug("PDF", "Turn '%s' off too", oIter->first.c_str());
-                            oIter->second->setState(OptionalContentGroup::Off);
+                            oMapOCGNumGenToVisibilityStatePdfium[ oIter->second ] = VISIBILITY_OFF;
                         }
                     }
                 }
@@ -2516,7 +3838,20 @@ void PDFDataset::TurnLayersOnOff()
     }
 }
 
-#endif
+/************************************************************************/
+/*                    GetVisibilityStateForOGCPdfium()                  */
+/************************************************************************/
+
+PDFDataset::VisibilityState PDFDataset::GetVisibilityStateForOGCPdfium(int nNum, int nGen)
+{
+    std::map< std::pair<int,int>, VisibilityState >::iterator oIter =
+            oMapOCGNumGenToVisibilityStatePdfium.find(std::pair<int,int>(nNum,nGen));
+    if( oIter == oMapOCGNumGenToVisibilityStatePdfium.end() )
+        return VISIBILITY_DEFAULT;
+    return oIter->second;
+}
+
+#endif /* HAVE_PDFIUM */
 
 /************************************************************************/
 /*                           FindLayerOCG()                             */
@@ -2609,12 +3944,11 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
 
     const char* pszUserPwd = GetOption(poOpenInfo->papszOpenOptions, "USER_PWD", NULL);
 
-    int bOpenSubdataset = strncmp(poOpenInfo->pszFilename, "PDF:", 4) == 0;
-    int bOpenSubdatasetImage = strncmp(poOpenInfo->pszFilename, "PDF_IMAGE:", 10) == 0;
+    int bOpenSubdataset = STARTS_WITH(poOpenInfo->pszFilename, "PDF:");
+    int bOpenSubdatasetImage = STARTS_WITH(poOpenInfo->pszFilename, "PDF_IMAGE:");
     int iPage = -1;
     int nImageNum = -1;
     const char* pszFilename = poOpenInfo->pszFilename;
-    char szPassword[81];
 
     if (bOpenSubdataset)
     {
@@ -2645,25 +3979,50 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
     else
         iPage = 1;
 
-    int bUsePoppler;
-#if defined(HAVE_POPPLER) && !defined(HAVE_PODOFO)
-    bUsePoppler = TRUE;
-#elif !defined(HAVE_POPPLER) && defined(HAVE_PODOFO)
-    bUsePoppler = FALSE;
-#elif defined(HAVE_POPPLER) && defined(HAVE_PODOFO)
-    const char* pszPDFLib = GetOption(poOpenInfo->papszOpenOptions, "PDF_LIB", "POPPLER");
-    if (EQUAL(pszPDFLib, "POPPLER"))
-        bUsePoppler = TRUE;
-    else if (EQUAL(pszPDFLib, "PODOFO"))
-        bUsePoppler = FALSE;
-    else
-    {
-        CPLDebug("PDF", "Invalid value for GDAL_PDF_LIB config option");
-        bUsePoppler = TRUE;
+    std::bitset<PDFLIB_COUNT> bHasLib;
+    bHasLib.reset();
+    // Each library set their flag
+#if defined(HAVE_POPPLER)
+    bHasLib.set(PDFLIB_POPPLER);
+#endif  // HAVE_POPPLER
+#if defined(HAVE_PODOFO)
+    bHasLib.set(PDFLIB_PODOFO);
+#endif  // HAVE_PODOFO
+#if defined(HAVE_PDFIUM)
+    bHasLib.set(PDFLIB_PDFIUM);
+#endif  // HAVE_PDFIUM
+
+    std::bitset<PDFLIB_COUNT> bUseLib;
+
+    // More than one library available
+    // Detect which one
+    if(bHasLib.count() != 1) {
+        const char* pszDefaultLib =
+                bHasLib.test(PDFLIB_PDFIUM) ? "PDFIUM" :
+                bHasLib.test(PDFLIB_POPPLER) ? "POPPLER" : "PODOFO";
+        const char* pszPDFLib = GetOption(poOpenInfo->papszOpenOptions, "PDF_LIB", pszDefaultLib );
+        while( true )
+        {
+            if (EQUAL(pszPDFLib, "POPPLER"))
+                bUseLib.set(PDFLIB_POPPLER);
+            else if (EQUAL(pszPDFLib, "PODOFO"))
+                bUseLib.set(PDFLIB_PODOFO);
+            else if (EQUAL(pszPDFLib, "PDFIUM"))
+                bUseLib.set(PDFLIB_PDFIUM);
+
+            if(bUseLib.count() != 1 || (bHasLib & bUseLib) == 0)
+            {
+                CPLDebug("PDF", "Invalid value for GDAL_PDF_LIB config option: %s. Fallback to %s",
+                        pszPDFLib, pszDefaultLib);
+                pszPDFLib = pszDefaultLib;
+                bUseLib.reset();
+            }
+            else
+                break;
+        }
     }
-#else
-    return NULL;
-#endif
+    else
+        bUseLib = bHasLib;
 
     GDALPDFObject* poPageObj = NULL;
 #ifdef HAVE_POPPLER
@@ -2676,10 +4035,14 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
     PoDoFo::PdfMemDocument* poDocPodofo = NULL;
     PoDoFo::PdfPage* poPagePodofo = NULL;
 #endif
+#ifdef HAVE_PDFIUM
+    TPdfiumDocumentStruct* poDocPdfium = NULL;
+    TPdfiumPageStruct* poPagePdfium = NULL;
+#endif
     int nPages = 0;
 
 #ifdef HAVE_POPPLER
-  if(bUsePoppler)
+  if(bUseLib.test(PDFLIB_POPPLER))
   {
     GooString* poUserPwd = NULL;
 
@@ -2696,11 +4059,11 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
         if (globalParams == NULL)
             globalParams = new GlobalParams();
 
-        globalParams->setPrintCommands(CSLTestBoolean(
+        globalParams->setPrintCommands(CPLTestBool(
             CPLGetConfigOption("GDAL_PDF_PRINT_COMMANDS", "FALSE")));
     }
 
-    while(TRUE)
+    while( true )
     {
         VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
         if (fp == NULL)
@@ -2711,8 +4074,8 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
         if (pszUserPwd)
             poUserPwd = new GooString(pszUserPwd);
 
-        oObj.initNull();
-        poDocPoppler = new PDFDoc(new VSIPDFFileStream(fp, pszFilename, &oObj), NULL, poUserPwd);
+        oObj.getObj()->initNull();
+        poDocPoppler = new PDFDoc(new VSIPDFFileStream(fp, pszFilename, oObj.getObj()), NULL, poUserPwd);
         delete poUserPwd;
 
         if ( !poDocPoppler->isOk() || poDocPoppler->getNumPages() == 0 )
@@ -2721,24 +4084,20 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
             {
                 if (pszUserPwd && EQUAL(pszUserPwd, "ASK_INTERACTIVE"))
                 {
-                    printf( "Enter password (will be echo'ed in the console): " );
-                    if (0 == fgets( szPassword, sizeof(szPassword), stdin ))
-                    {
-                      fprintf(stderr, "WARNING: Error getting password.\n");
-                    }
-                    szPassword[sizeof(szPassword)-1] = 0;
-                    char* sz10 = strchr(szPassword, '\n');
-                    if (sz10)
-                        *sz10 = 0;
-                    pszUserPwd = szPassword;
+                    pszUserPwd = PDFEnterPasswordFromConsoleIfNeeded(pszUserPwd);
                     PDFFreeDoc(poDocPoppler);
+
+                    /* Reset errors that could have been issued during opening and that */
+                    /* did not result in an invalid document */
+                    CPLErrorReset();
+
                     continue;
                 }
                 else if (pszUserPwd == NULL)
                 {
                     CPLError(CE_Failure, CPLE_AppDefined,
                              "A password is needed. You can specify it through the PDF_USER_PWD "
-                             "configuration option (that can be set to ASK_INTERACTIVE)");
+                             "configuration option / USER_PWD open option (that can be set to ASK_INTERACTIVE)");
                 }
                 else
                 {
@@ -2756,10 +4115,6 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
         }
         else
             break;
-
-        /* Reset errors that could have been issued during opening and that */
-        /* did not result in an invalid document */
-        CPLErrorReset();
     }
 
     poCatalogPoppler = poDocPoppler->getCatalog();
@@ -2770,17 +4125,19 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-#ifdef dump_catalog
+    nPages = poDocPoppler->getNumPages();
+
+    if( iPage == 1 && nPages > 10000 &&
+        CPLTestBool(CPLGetConfigOption("GDAL_PDF_LIMIT_PAGE_COUNT", "YES")) )
     {
-        ObjectAutoFree oCatalog;
-        poDocPoppler->getXRef()->getCatalog(&oCatalog);
-        GDALPDFObjectPoppler oCatalogGDAL(&oCatalog, FALSE);
-        GDALPDFDumper oDumper(stderr);
-        oDumper.Dump(&oCatalogGDAL);
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "This PDF document reports %d pages. "
+                 "Limiting count to 10000 for performance reasons. "
+                 "You may remove this limit by setting the GDAL_PDF_LIMIT_PAGE_COUNT configuration option to NO",
+                 nPages);
+        nPages = 10000;
     }
-#endif
 
-    nPages = poDocPoppler->getNumPages();
     if (iPage < 1 || iPage > nPages)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Invalid page number (%d/%d)",
@@ -2790,7 +4147,7 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
     /* Sanity check to validate page count */
-    if( iPage != nPages )
+    if( iPage > 1 && nPages <= 10000 && iPage != nPages )
     {
         poPagePoppler = poCatalogPoppler->getPage(nPages);
         if ( poPagePoppler == NULL || !poPagePoppler->isOk() )
@@ -2826,10 +4183,10 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
         ((GDALPDFObjectPoppler*)poPageObj)->SetRefNumAndGen(poPageRef->num, poPageRef->gen);
     }
   }
-#endif
+#endif  // ~ HAVE_POPPLER
 
 #ifdef HAVE_PODOFO
-  if (!bUsePoppler)
+  if (bUseLib.test(PDFLIB_PODOFO) && poPageObj == NULL)
   {
     PoDoFo::PdfError::EnableDebug( false );
     PoDoFo::PdfError::EnableLogging( false );
@@ -2845,33 +4202,21 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
         {
             if (pszUserPwd)
             {
-                if (EQUAL(pszUserPwd, "ASK_INTERACTIVE"))
-                {
-                    printf( "Enter password (will be echo'ed in the console): " );
-                    if (0 == fgets( szPassword, sizeof(szPassword), stdin ))
-                    {
-                      fprintf(stderr, "WARNING: Error getting password.\n");
-                    }
-                    szPassword[sizeof(szPassword)-1] = 0;
-                    char* sz10 = strchr(szPassword, '\n');
-                    if (sz10)
-                        *sz10 = 0;
-                    pszUserPwd = szPassword;
-                }
+                pszUserPwd = PDFEnterPasswordFromConsoleIfNeeded(pszUserPwd);
 
                 try
                 {
                     poDocPodofo->SetPassword(pszUserPwd);
                 }
-                catch(PoDoFo::PdfError& oError)
+                catch(PoDoFo::PdfError& oError2)
                 {
-                    if (oError.GetError() == PoDoFo::ePdfError_InvalidPassword)
+                    if (oError2.GetError() == PoDoFo::ePdfError_InvalidPassword)
                     {
                         CPLError(CE_Failure, CPLE_AppDefined, "Invalid password");
                     }
                     else
                     {
-                        CPLError(CE_Failure, CPLE_AppDefined, "Invalid PDF : %s", oError.what());
+                        CPLError(CE_Failure, CPLE_AppDefined, "Invalid PDF : %s", oError2.what());
                     }
                     delete poDocPodofo;
                     return NULL;
@@ -2887,7 +4232,7 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
                             "A password is needed. You can specify it through the PDF_USER_PWD "
-                            "configuration option (that can be set to ASK_INTERACTIVE)");
+                            "configuration option / USER_PWD open option (that can be set to ASK_INTERACTIVE)");
                 delete poDocPodofo;
                 return NULL;
             }
@@ -2919,7 +4264,7 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
     {
         /* Sanity check to validate page count */
         if( iPage != nPages )
-            poPagePodofo = poDocPodofo->GetPage(nPages - 1);
+            CPL_IGNORE_RET_VAL( poDocPodofo->GetPage(nPages - 1) );
 
         poPagePodofo = poDocPodofo->GetPage(iPage - 1);
     }
@@ -2946,17 +4291,48 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
     PoDoFo::PdfObject* pObj = poPagePodofo->GetObject();
     poPageObj = new GDALPDFObjectPodofo(pObj, poDocPodofo->GetObjects());
   }
-#endif
+#endif  // ~ HAVE_PODOFO
+
+#ifdef HAVE_PDFIUM
+  if (bUseLib.test(PDFLIB_PDFIUM) && poPageObj == NULL)
+  {
+    if(!LoadPdfiumDocumentPage(pszFilename, pszUserPwd, iPage,
+      &poDocPdfium, &poPagePdfium, &nPages)) {
+        // CPLError is called inside function
+        return NULL;
+    }
+
+    CPDF_Object* pageObj = poPagePdfium->page->m_pFormDict;
+    if(pageObj == NULL) {
+        CPLError(CE_Failure, CPLE_AppDefined, "Invalid PDF : invalid page object");
+        UnloadPdfiumDocumentPage(&poDocPdfium, &poPagePdfium);
+        return NULL;
+    }
+    poPageObj = GDALPDFObjectPdfium::Build(pageObj);
+    if( poPageObj == NULL )
+        return NULL;
+  }
+#endif  // ~ HAVE_PDFIUM
 
     GDALPDFDictionary* poPageDict = poPageObj->GetDictionary();
     if ( poPageDict == NULL )
     {
+        delete poPageObj;
+
         CPLError(CE_Failure, CPLE_AppDefined, "Invalid PDF : poPageDict == NULL");
 #ifdef HAVE_POPPLER
-        PDFFreeDoc(poDocPoppler);
+        if (bUseLib.test(PDFLIB_POPPLER))
+            PDFFreeDoc(poDocPoppler);
 #endif
 #ifdef HAVE_PODOFO
-        delete poDocPodofo;
+        if (bUseLib.test(PDFLIB_PODOFO)) {
+            delete poDocPodofo;
+        }
+#endif
+#ifdef HAVE_PDFIUM
+        if (bUseLib.test(PDFLIB_PDFIUM)) {
+            UnloadPdfiumDocumentPage(&poDocPdfium, &poPagePdfium);
+        }
 #endif
         return NULL;
     }
@@ -2964,25 +4340,13 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
     const char* pszDumpObject = CPLGetConfigOption("PDF_DUMP_OBJECT", NULL);
     if (pszDumpObject != NULL)
     {
-        FILE* f;
-        if (strcmp(pszDumpObject, "stderr") == 0)
-            f = stderr;
-        else if (EQUAL(pszDumpObject, "YES"))
-            f = fopen(CPLSPrintf("dump_%s.txt", CPLGetFilename(pszFilename)), "wt");
-        else
-            f = fopen(pszDumpObject, "wt");
-        if (f == NULL)
-            f = stderr;
-
-        GDALPDFDumper oDumper(f);
+        GDALPDFDumper oDumper(pszFilename, pszDumpObject);
         oDumper.Dump(poPageObj);
-        if (f != stderr)
-            fclose(f);
     }
 
     PDFDataset* poDS = new PDFDataset();
     poDS->papszOpenOptions = CSLDuplicate(poOpenInfo->papszOpenOptions);
-    poDS->bUsePoppler = bUsePoppler;
+    poDS->bUseLib = bUseLib;
     poDS->osFilename = pszFilename;
     poDS->eAccess = poOpenInfo->eAccess;
 
@@ -2993,9 +4357,9 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
         for(i=0;i<nPages;i++)
         {
             char szKey[32];
-            sprintf( szKey, "SUBDATASET_%d_NAME", i+1 );
+            snprintf( szKey, sizeof(szKey), "SUBDATASET_%d_NAME", i+1 );
             aosList.AddNameValue(szKey, CPLSPrintf("PDF:%d:%s", i+1, poOpenInfo->pszFilename));
-            sprintf( szKey, "SUBDATASET_%d_DESC", i+1 );
+            snprintf( szKey, sizeof(szKey), "SUBDATASET_%d_DESC", i+1 );
             aosList.AddNameValue(szKey, CPLSPrintf("Page %d of %s", i+1, poOpenInfo->pszFilename));
         }
         poDS->SetMetadata( aosList.List(), "SUBDATASETS" );
@@ -3007,10 +4371,21 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
 #ifdef HAVE_PODOFO
     poDS->poDocPodofo = poDocPodofo;
 #endif
+#ifdef HAVE_PDFIUM
+    poDS->poDocPdfium = poDocPdfium;
+    poDS->poPagePdfium = poPagePdfium;
+#endif
     poDS->poPageObj = poPageObj;
     poDS->osUserPwd = pszUserPwd ? pszUserPwd : "";
     poDS->iPage = iPage;
 
+    const char* pszDumpCatalog = CPLGetConfigOption("PDF_DUMP_CATALOG", NULL);
+    if (pszDumpCatalog != NULL)
+    {
+        GDALPDFDumper oDumper(pszFilename, pszDumpCatalog);
+        oDumper.Dump(poDS->GetCatalog());
+    }
+
     int nBandsGuessed = 0;
     if (nImageNum < 0)
     {
@@ -3030,7 +4405,7 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
     double dfX1 = 0.0, dfY1 = 0.0, dfX2 = 0.0, dfY2 = 0.0;
 
 #ifdef HAVE_POPPLER
-    if (bUsePoppler)
+    if (bUseLib.test(PDFLIB_POPPLER))
     {
         PDFRectangle* psMediaBox = poPagePoppler->getMediaBox();
         dfX1 = psMediaBox->x1;
@@ -3041,8 +4416,9 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
 #endif
 
 #ifdef HAVE_PODOFO
-    if (!bUsePoppler)
+    if (bUseLib.test(PDFLIB_PODOFO))
     {
+        CPLAssert(poPagePodofo);
         PoDoFo::PdfRect oMediaBox = poPagePodofo->GetMediaBox();
         dfX1 = oMediaBox.GetLeft();
         dfY1 = oMediaBox.GetBottom();
@@ -3051,9 +4427,20 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 #endif
 
+#ifdef HAVE_PDFIUM
+    if (bUseLib.test(PDFLIB_PDFIUM)) {
+        CFX_FloatRect rect = poPagePdfium->page->GetPageBBox();
+        dfX1 = rect.left;
+        dfX2 = rect.right;
+        dfY1 = rect.bottom;
+        dfY2 = rect.top;
+    }
+#endif  // ~ HAVE_PDFIUM
+
     double dfUserUnit = poDS->dfDPI * USER_UNIT_IN_INCH;
     poDS->dfPageWidth = dfX2 - dfX1;
     poDS->dfPageHeight = dfY2 - dfY1;
+    //CPLDebug("PDF", "left=%f right=%f bottom=%f top=%f", dfX1, dfX2, dfY1, dfY2);
     poDS->nRasterXSize = (int) floor((dfX2 - dfX1) * dfUserUnit+0.5);
     poDS->nRasterYSize = (int) floor((dfY2 - dfY1) * dfUserUnit+0.5);
 
@@ -3065,25 +4452,38 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
 
     double dfRotation = 0;
 #ifdef HAVE_POPPLER
-    if (bUsePoppler)
+    if (bUseLib.test(PDFLIB_POPPLER))
         dfRotation = poDocPoppler->getPageRotate(iPage);
 #endif
 
 #ifdef HAVE_PODOFO
-    if (!bUsePoppler)
+    if (bUseLib.test(PDFLIB_PODOFO))
+    {
+        CPLAssert(poPagePodofo);
         dfRotation = poPagePodofo->GetRotation();
+    }
+#endif
+
+#ifdef HAVE_PDFIUM
+    if (bUseLib.test(PDFLIB_PDFIUM))
+    {
+        CPDF_Object* pRotate = poPagePdfium->page->GetPageAttr(FX_BSTRC("Rotate"));
+        if (pRotate)
+          dfRotation = pRotate->GetInteger();
+        if(dfRotation < 0)
+          dfRotation += 360.0;
+    }
 #endif
+
     if ( dfRotation == 90 ||
          dfRotation == -90 ||
          dfRotation == 270 )
     {
-/* FIXME: the non poppler case should be implemented. This needs to rotate */
+/* FIXME: the podofo case should be implemented. This needs to rotate */
 /* the output of pdftoppm */
-#ifdef HAVE_POPPLER
-      if (bUsePoppler)
+#if defined(HAVE_POPPLER) || defined(HAVE_PDFIUM)
+      if (bUseLib.test(PDFLIB_POPPLER) || bUseLib.test(PDFLIB_PDFIUM))
       {
-        /* Wondering how it would work with a georeferenced image */
-        /* Has only been tested with ungeoreferenced image */
         int nTmp = poDS->nRasterXSize;
         poDS->nRasterXSize = poDS->nRasterYSize;
         poDS->nRasterYSize = nTmp;
@@ -3132,14 +4532,14 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
                 }
                 else
                 {
-                    poDS->adfGeoTransform[0] = poDS->adfCTM[4] + poDS->adfCTM[2] * poDS->dfPageHeight;
+                    poDS->adfGeoTransform[0] = poDS->adfCTM[4] + poDS->adfCTM[2] * dfY2 + poDS->adfCTM[0] * dfX1;
                     poDS->adfGeoTransform[1] = poDS->adfCTM[0] / dfUserUnit;
                     poDS->adfGeoTransform[2] = - poDS->adfCTM[2] / dfUserUnit;
-                    poDS->adfGeoTransform[3] = poDS->adfCTM[5] + poDS->adfCTM[3] * poDS->dfPageHeight;
+                    poDS->adfGeoTransform[3] = poDS->adfCTM[5] + poDS->adfCTM[3] * dfY2 + poDS->adfCTM[1] * dfX1;
                     poDS->adfGeoTransform[4] = poDS->adfCTM[1] / dfUserUnit;
                     poDS->adfGeoTransform[5] = - poDS->adfCTM[3] / dfUserUnit;
                 }
-                
+
                 poDS->bGeoTransformValid = TRUE;
             }
 
@@ -3164,8 +4564,8 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
                 }
                 else
                 {
-                    poDS->pasGCPList[i].dfGCPPixel = poDS->pasGCPList[i].dfGCPPixel * dfUserUnit;
-                    poDS->pasGCPList[i].dfGCPLine = poDS->nRasterYSize - poDS->pasGCPList[i].dfGCPLine * dfUserUnit;
+                    poDS->pasGCPList[i].dfGCPPixel = (-dfX1 + poDS->pasGCPList[i].dfGCPPixel) * dfUserUnit;
+                    poDS->pasGCPList[i].dfGCPLine = (dfY2 - poDS->pasGCPList[i].dfGCPLine) * dfUserUnit;
                 }
             }
         }
@@ -3280,6 +4680,22 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->adfGeoTransform[3] = ROUND_TO_INT_IF_CLOSE(poDS->adfGeoTransform[3], dfEps);
     poDS->adfGeoTransform[5] = ROUND_TO_INT_IF_CLOSE(poDS->adfGeoTransform[5]);
 
+    if( bUseLib.test(PDFLIB_PDFIUM) )
+    {
+        // Attempt to "fix" the loss of precision due to the use of float32 for numbers by pdfium
+        if( (fabs(poDS->adfGeoTransform[0]) > 1e5 || fabs(poDS->adfGeoTransform[3]) > 1e5) &&
+            fabs(poDS->adfGeoTransform[0] - (int)floor(poDS->adfGeoTransform[0]+0.5)) < 1e-6 * fabs(poDS->adfGeoTransform[0]) &&
+            fabs(poDS->adfGeoTransform[1] - (int)floor(poDS->adfGeoTransform[1]+0.5)) < 1e-3 * fabs(poDS->adfGeoTransform[1]) &&
+            fabs(poDS->adfGeoTransform[3] - (int)floor(poDS->adfGeoTransform[3]+0.5)) < 1e-6 * fabs(poDS->adfGeoTransform[3]) &&
+            fabs(poDS->adfGeoTransform[5] - (int)floor(poDS->adfGeoTransform[5]+0.5)) < 1e-3 * fabs(poDS->adfGeoTransform[5]) )
+        {
+            for(int i=0;i<6;i++)
+            {
+                poDS->adfGeoTransform[i] = (int)floor(poDS->adfGeoTransform[i]+0.5);
+            }
+        }
+    }
+
     if (poDS->poNeatLine)
     {
         char* pszNeatLineWkt = NULL;
@@ -3305,8 +4721,8 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
                 }
                 else
                 {
-                    x = poRing->getX(i) * dfUserUnit;
-                    y = poDS->nRasterYSize - poRing->getY(i) * dfUserUnit;
+                    x = (-dfX1 + poRing->getX(i)) * dfUserUnit;
+                    y = (dfY2 - poRing->getY(i)) * dfUserUnit;
                 }
                 double X = poDS->adfGeoTransform[0] + x * poDS->adfGeoTransform[1] +
                                                       y * poDS->adfGeoTransform[2];
@@ -3325,14 +4741,14 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
 
 
 #ifdef HAVE_POPPLER
-  if (bUsePoppler)
+  if (bUseLib.test(PDFLIB_POPPLER))
   {
     GooString* poMetadata = poCatalogPoppler->readMetadata();
     if (poMetadata)
     {
         char* pszContent = poMetadata->getCString();
         if (pszContent != NULL &&
-            strncmp(pszContent, "<?xpacket begin=", strlen("<?xpacket begin=")) == 0)
+            STARTS_WITH(pszContent, "<?xpacket begin="))
         {
             char *apszMDList[2];
             apszMDList[0] = pszContent;
@@ -3355,15 +4771,15 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
     /* Find layers */
-    poDS->FindLayers();
+    poDS->FindLayersPoppler();
 
     /* Turn user specified layers on or off */
-    poDS->TurnLayersOnOff();
+    poDS->TurnLayersOnOffPoppler();
   }
 #endif
 
 #ifdef HAVE_PODOFO
-  if (!bUsePoppler)
+  if (bUseLib.test(PDFLIB_PODOFO))
   {
     PoDoFo::TIVecObjects it = poDocPodofo->GetObjects().begin();
     for( ; it != poDocPodofo->GetObjects().end(); ++it )
@@ -3384,8 +4800,54 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
     }
   }
 #endif
+#ifdef HAVE_PDFIUM
+    if (bUseLib.test(PDFLIB_PDFIUM))
+    {
+        GDALPDFObjectPdfium* poRoot = GDALPDFObjectPdfium::Build(poDocPdfium->doc->GetRoot());
+        if(poRoot->GetType() == PDFObjectType_Dictionary) {
+          GDALPDFDictionary* poDict = poRoot->GetDictionary();
+          GDALPDFObject* poMetadata(poDict->Get("Metadata"));
+          if(poMetadata != NULL) {
+            GDALPDFStream* poStream = poMetadata->GetStream();
+            if (poStream != NULL) {
+              char* pszContent = poStream->GetBytes();
+              int nLength = (int)poStream->GetLength();
+              if (pszContent != NULL && nLength > 15 &&
+                  STARTS_WITH(pszContent, "<?xpacket begin="))
+              {
+                  char *apszMDList[2];
+                  apszMDList[0] = pszContent;
+                  apszMDList[1] = NULL;
+                  poDS->SetMetadata(apszMDList, "xml:XMP");
+              }
+              CPLFree(pszContent);
+            }
+          }
+        }
+        delete poRoot;
+
+        /* Find layers */
+        poDS->FindLayersPdfium();
+
+        /* Turn user specified layers on or off */
+        poDS->TurnLayersOnOffPdfium();
+
+        GDALPDFObjectPdfium* poInfo = GDALPDFObjectPdfium::Build(poDocPdfium->doc->GetInfo());
+        if( poInfo )
+        {
+            /* Read Info object */
+            poDS->ParseInfo(poInfo);
+            delete poInfo;
+        }
+    }
+#endif  // ~ HAVE_PDFIUM
 
     int nBands = 3;
+#ifdef HAVE_PDFIUM
+    // Use Alpha channel for PDFIUM as default format RGBA
+    if(bUseLib.test(PDFLIB_PDFIUM))
+        nBands = 4;
+#endif
     if( nBandsGuessed )
         nBands = nBandsGuessed;
     const char* pszPDFBands = GetOption(poOpenInfo->papszOpenOptions, "BANDS", NULL);
@@ -3400,10 +4862,10 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
         }
     }
 #ifdef HAVE_PODOFO
-    if (!bUsePoppler && nBands == 4 && poDS->aiTiles.size() == 0)
+    if (bUseLib.test(PDFLIB_PODOFO) && nBands == 4 && poDS->aiTiles.size() == 0)
     {
         CPLError(CE_Warning, CPLE_NotSupported,
-                 "GDAL_PDF_BANDS=4 only supported when PDF driver is compiled against Poppler. "
+                 "GDAL_PDF_BANDS=4 not supported when PDF driver is compiled against Podofo. "
                  "Using 3 as a fallback");
         nBands = 3;
     }
@@ -3415,7 +4877,7 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
         if (poDS->poImageObj != NULL)
             poDS->SetBand(iBand, new PDFImageRasterBand(poDS, iBand));
         else
-            poDS->SetBand(iBand, new PDFRasterBand(poDS, iBand));
+            poDS->SetBand(iBand, new PDFRasterBand(poDS, iBand, 0));
     }
 
     /* Check if this is a raster-only PDF file and that we are */
@@ -3424,8 +4886,13 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
         (poOpenInfo->nOpenFlags & GDAL_OF_VECTOR) != 0 &&
         !poDS->OpenVectorLayers(poPageDict) )
     {
-        CPLDebug("PCIDSK", "This is a raster-only PDF dataset, "
+        CPLDebug("PDF", "This is a raster-only PDF dataset, "
                     "but it has been opened in vector-only mode");
+        /* Clear dirty flag */
+        poDS->bProjDirty = FALSE;
+        poDS->bNeatLineDirty = FALSE;
+        poDS->bInfoDirty = FALSE;
+        poDS->bXMPDirty = FALSE;
         delete poDS;
         return NULL;
     }
@@ -3441,6 +4908,10 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
+#ifdef HAVE_PDFIUM
+    poDS->InitOverviews();
+#endif
+
     /* Clear dirty flag */
     poDS->bProjDirty = FALSE;
     poDS->bNeatLineDirty = FALSE;
@@ -3752,7 +5223,8 @@ int PDFDataset::ParseLGIDictDictSecondPass(GDALPDFDictionary* poLGIDict)
     GDALPDFObject* poCTM;
     bHasCTM = FALSE;
     if ((poCTM = poLGIDict->Get("CTM")) != NULL &&
-        poCTM->GetType() == PDFObjectType_Array)
+        poCTM->GetType() == PDFObjectType_Array &&
+        CPLTestBool(CPLGetConfigOption("PDF_USE_CTM", "YES")) )
     {
         int nLength = poCTM->GetArray()->GetLength();
         if ( nLength != 6 )
@@ -3767,7 +5239,7 @@ int PDFDataset::ParseLGIDictDictSecondPass(GDALPDFDictionary* poLGIDict)
         {
             adfCTM[i] = Get(poCTM, i);
             /* Nullify rotation terms that are significantly smaller than */
-            /* scaling termes */
+            /* scaling terms. */
             if ((i == 1 || i == 2) && fabs(adfCTM[i]) < fabs(adfCTM[0]) * 1e-10)
                 adfCTM[i] = 0;
             CPLDebug("PDF", "CTM[%d] = %.16g", i, adfCTM[i]);
@@ -3784,7 +5256,7 @@ int PDFDataset::ParseLGIDictDictSecondPass(GDALPDFDictionary* poLGIDict)
         GDALPDFArray* poRegistrationArray = poRegistration->GetArray();
         int nLength = poRegistrationArray->GetLength();
         if( nLength > 4 || (!bHasCTM && nLength >= 2) ||
-            CSLTestBoolean(CPLGetConfigOption("PDF_REPORT_GCPS", "NO")) )
+            CPLTestBool(CPLGetConfigOption("PDF_REPORT_GCPS", "NO")) )
         {
             nGCPCount = 0;
             pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),nLength);
@@ -3806,7 +5278,7 @@ int PDFDataset::ParseLGIDictDictSecondPass(GDALPDFDictionary* poLGIDict)
                     CPLDebug("PDF", "GCP[%d].y = %.16g", i, dfY);
 
                     char    szID[32];
-                    sprintf( szID, "%d", nGCPCount+1 );
+                    snprintf( szID, sizeof(szID), "%d", nGCPCount+1 );
                     pasGCPList[nGCPCount].pszId = CPLStrdup( szID );
                     pasGCPList[nGCPCount].pszInfo = CPLStrdup("");
                     pasGCPList[nGCPCount].dfGCPPixel = dfUserX;
@@ -3855,7 +5327,7 @@ int PDFDataset::ParseProjDict(GDALPDFDictionary* poProjDict)
     GDALPDFObject* poWKT;
     if ( (poWKT = poProjDict->Get("WKT")) != NULL &&
          poWKT->GetType() == PDFObjectType_String &&
-         CSLTestBoolean( CPLGetConfigOption("GDAL_PDF_OGC_BP_READ_WKT", "TRUE") ) )
+         CPLTestBool( CPLGetConfigOption("GDAL_PDF_OGC_BP_READ_WKT", "TRUE") ) )
     {
         CPLDebug("PDF", "Found WKT attribute (GDAL extension). Using it");
         const char* pszWKTRead = poWKT->GetString().c_str();
@@ -3910,12 +5382,12 @@ int PDFDataset::ParseProjDict(GDALPDFDictionary* poProjDict)
                 bIsWGS84 = TRUE;
                 oSRS.SetWellKnownGeogCS("WGS84");
             }
-            else if (EQUAL(pszDatum, "NAR") || EQUALN(pszDatum, "NAR-", 4))
+            else if (EQUAL(pszDatum, "NAR") || STARTS_WITH_CI(pszDatum, "NAR-"))
             {
                 bIsNAD83 = TRUE;
                 oSRS.SetWellKnownGeogCS("NAD83");
             }
-            else if (EQUAL(pszDatum, "NAS") || EQUALN(pszDatum, "NAS-", 4))
+            else if (EQUAL(pszDatum, "NAS") || STARTS_WITH_CI(pszDatum, "NAS-"))
             {
                 /* bIsNAD27 = TRUE; */
                 oSRS.SetWellKnownGeogCS("NAD27");
@@ -3936,7 +5408,7 @@ int PDFDataset::ParseProjDict(GDALPDFDictionary* poProjDict)
             {
                 oSRS.importFromEPSG(4283);
             }
-            else if (EQUALN(pszDatum, "OHA-", 4)) /* Old Hawaiian */
+            else if (STARTS_WITH_CI(pszDatum, "OHA-")) /* Old Hawaiian */
             {
                 oSRS.importFromEPSG(4135); /* matches OHA-M (Mean) */
                 if( !EQUAL(pszDatum, "OHA-M") )
@@ -3979,7 +5451,7 @@ int PDFDataset::ParseProjDict(GDALPDFDictionary* poProjDict)
                 poDatumDescription->GetType() == PDFObjectType_String)
                 pszDatumDescription  = poDatumDescription->GetString().c_str();
             CPLDebug("PDF", "Datum.Description = %s", pszDatumDescription);
-                
+
             GDALPDFObject* poEllipsoid = poDatumDict->Get("Ellipsoid");
             if (poEllipsoid == NULL ||
                 !(poEllipsoid->GetType() == PDFObjectType_String ||
@@ -4024,11 +5496,11 @@ int PDFDataset::ParseProjDict(GDALPDFDictionary* poProjDict)
                     poEllipsoidDescription->GetType() == PDFObjectType_String)
                     pszEllipsoidDescription = poEllipsoidDescription->GetString().c_str();
                 CPLDebug("PDF", "Datum.Ellipsoid.Description = %s", pszEllipsoidDescription);
-                    
+
                 double dfSemiMajor = Get(poEllipsoidDict, "SemiMajorAxis");
                 CPLDebug("PDF", "Datum.Ellipsoid.SemiMajorAxis = %.16g", dfSemiMajor);
                 double dfInvFlattening = -1.0;
-                
+
                 if( poEllipsoidDict->Get("InvFlattening") )
                 {
                     dfInvFlattening = Get(poEllipsoidDict, "InvFlattening");
@@ -4040,7 +5512,7 @@ int PDFDataset::ParseProjDict(GDALPDFDictionary* poProjDict)
                     CPLDebug("PDF", "Datum.Ellipsoid.SemiMinorAxis = %.16g", dfSemiMinor);
                     dfInvFlattening = OSRCalcInvFlattening(dfSemiMajor, dfSemiMinor);
                 }
-                
+
                 if( dfSemiMajor != 0.0 && dfInvFlattening != -1.0 )
                 {
                     oSRS.SetGeogCS( "unknown",
@@ -4057,10 +5529,8 @@ int PDFDataset::ParseProjDict(GDALPDFDictionary* poProjDict)
                                     pszEllipsoidDescription,
                                     6378137,298.257223563);
                 }
-                
-                
             }
-            
+
             GDALPDFObject* poTOWGS84 = poDatumDict->Get("ToWGS84");
             if( poTOWGS84 != NULL && poTOWGS84->GetType() == PDFObjectType_Dictionary )
             {
@@ -4157,7 +5627,7 @@ int PDFDataset::ParseProjDict(GDALPDFDictionary* poProjDict)
                      dfCenterLat, dfCenterLong,
                      dfFalseEasting, dfFalseNorthing );
     }
- 
+
     else if (EQUAL(osProjectionType, "AL")) /* Azimuthal Equidistant */
     {
         double dfCenterLat = Get(poProjDict, "OriginLatitude");
@@ -4253,8 +5723,8 @@ int PDFDataset::ParseProjDict(GDALPDFDictionary* poProjDict)
     {
 #ifdef not_supported
         if (poProjDict->Get("StandardParallelOne") == NULL)
-        {
 #endif
+        {
         double dfCenterLat = Get(poProjDict, "OriginLatitude");
         double dfCenterLong = Get(poProjDict, "CentralMeridian");
         double dfScale = Get(poProjDict, "ScaleFactor");
@@ -4263,8 +5733,8 @@ int PDFDataset::ParseProjDict(GDALPDFDictionary* poProjDict)
         oSRS.SetMercator( dfCenterLat, dfCenterLong,
                           dfScale,
                           dfFalseEasting, dfFalseNorthing );
-#ifdef not_supported
         }
+#ifdef not_supported
         else
         {
             double dfStdP1 = Get(poProjDict, "StandardParallelOne");
@@ -4826,7 +6296,7 @@ int PDFDataset::ParseMeasure(GDALPDFObject* poMeasure,
     /* For http://www.avenza.com/sites/default/files/spatialpdf/US_County_Populations.pdf */
     /* or http://www.agmkt.state.ny.us/soilwater/aem/gis_mapping_tools/HUC12_Albany.pdf */
     const char* pszDatum = oSRS.GetAttrValue("Datum");
-    if (pszDatum && strncmp(pszDatum, "D_", 2) == 0)
+    if (pszDatum && STARTS_WITH(pszDatum, "D_"))
     {
         oSRS.morphFromESRI();
 
@@ -4930,15 +6400,16 @@ int PDFDataset::ParseMeasure(GDALPDFObject* poMeasure,
     }
     bGeoTransformValid = TRUE;
 
-    /* If the non scaling terms of the geotransform are significantly smaller than */
-    /* the pixel size, then nullify them as being just artifacts of reprojection and */
-    /* GDALGCPsToGeoTransform() numerical imprecisions */
+    // If the non scaling terms of the geotransform are significantly smaller
+    // than the pixel size, then nullify them as being just artifacts of
+    //  reprojection and GDALGCPsToGeoTransform() numerical imprecisions.
     double dfPixelSize = MIN(fabs(adfGeoTransform[1]), fabs(adfGeoTransform[5]));
     double dfRotationShearTerm = MAX(fabs(adfGeoTransform[2]), fabs(adfGeoTransform[4]));
-    if (dfRotationShearTerm < 1e-5 * dfPixelSize)
+    if (dfRotationShearTerm < 1e-5 * dfPixelSize ||
+        (bUseLib.test(PDFLIB_PDFIUM) && MIN(fabs(adfGeoTransform[2]), fabs(adfGeoTransform[4])) < 1e-5 * dfPixelSize))
     {
-        double dfLRX = adfGeoTransform[0] + nRasterXSize * adfGeoTransform[1] + nRasterYSize * adfGeoTransform[2];
-        double dfLRY = adfGeoTransform[3] + nRasterXSize * adfGeoTransform[4] + nRasterYSize * adfGeoTransform[5];
+        dfLRX = adfGeoTransform[0] + nRasterXSize * adfGeoTransform[1] + nRasterYSize * adfGeoTransform[2];
+        dfLRY = adfGeoTransform[3] + nRasterXSize * adfGeoTransform[4] + nRasterYSize * adfGeoTransform[5];
         adfGeoTransform[1] = (dfLRX - adfGeoTransform[0]) / nRasterXSize;
         adfGeoTransform[5] = (dfLRY - adfGeoTransform[3]) / nRasterYSize;
         adfGeoTransform[2] = adfGeoTransform[4] = 0;
@@ -5073,6 +6544,16 @@ CPLErr      PDFDataset::SetMetadata( char ** papszMetadata,
 const char *PDFDataset::GetMetadataItem( const char * pszName,
                                          const char * pszDomain )
 {
+    if( pszDomain != NULL && EQUAL(pszDomain, "_INTERNAL_") &&
+        pszName != NULL && EQUAL(pszName, "PDF_LIB") )
+    {
+        if(bUseLib.test(PDFLIB_POPPLER))
+            return "POPPLER";
+        if(bUseLib.test(PDFLIB_PODOFO))
+            return "PODOFO";
+        if(bUseLib.test(PDFLIB_PDFIUM))
+            return "PDFIUM";
+    }
     return oMDMD.GetMetadataItem(pszName, pszDomain);
 }
 
@@ -5148,18 +6629,18 @@ CPLErr PDFDataset::SetGCPs( int nGCPCountIn, const GDAL_GCP *pasGCPListIn,
                  "GDAL_PDF_GEO_ENCODING=ISO32000.");
         return CE_Failure;
     }
-    
+
     /* Free previous GCPs */
     GDALDeinitGCPs( nGCPCount, pasGCPList );
     CPLFree( pasGCPList );
-    
+
     /* Duplicate in GCPs */
     nGCPCount = nGCPCountIn;
     pasGCPList = GDALDuplicateGCPs(nGCPCount, pasGCPListIn);
-    
+
     CPLFree(pszWKT);
     pszWKT = CPLStrdup(pszGCPProjectionIn);
-    
+
     bProjDirty = TRUE;
 
     /* Reset NEATLINE if not explicitly set by the user */
@@ -5169,14 +6650,14 @@ CPLErr PDFDataset::SetGCPs( int nGCPCountIn, const GDAL_GCP *pasGCPListIn,
     return CE_None;
 }
 
-#endif // #if defined(HAVE_POPPLER) || defined(HAVE_PODOFO)
+#endif // #if defined(HAVE_POPPLER) || defined(HAVE_PODOFO) || defined(HAVE_PDFIUM)
 
 /************************************************************************/
 /*                          GDALPDFOpen()                               */
 /************************************************************************/
 
 GDALDataset* GDALPDFOpen(
-#if defined(HAVE_POPPLER) || defined(HAVE_PODOFO)
+#if defined(HAVE_POPPLER) || defined(HAVE_PODOFO) || defined(HAVE_PDFIUM)
                          const char* pszFilename,
                          GDALAccess eAccess
 #else
@@ -5185,7 +6666,7 @@ GDALDataset* GDALPDFOpen(
 #endif
                          )
 {
-#if defined(HAVE_POPPLER) || defined(HAVE_PODOFO)
+#if defined(HAVE_POPPLER) || defined(HAVE_PODOFO) || defined(HAVE_PDFIUM)
     GDALOpenInfo oOpenInfo(pszFilename, eAccess);
     return PDFDataset::Open(&oOpenInfo);
 #else
@@ -5203,6 +6684,45 @@ static void GDALPDFUnloadDriver(CPL_UNUSED GDALDriver * poDriver)
     if( hGlobalParamsMutex != NULL )
         CPLDestroyMutex(hGlobalParamsMutex);
 #endif
+#ifdef HAVE_PDFIUM
+    if(PDFDataset::bPdfiumInit) {
+        CPLCreateOrAcquireMutex(&g_oPdfiumLoadDocMutex, PDFIUM_MUTEX_TIMEOUT);
+        // Destroy every loaded document or page
+        TMapPdfiumDatasets::iterator itDoc;
+        TMapPdfiumPages::iterator itPage;
+        for(itDoc = g_mPdfiumDatasets.begin(); itDoc != g_mPdfiumDatasets.end(); ++itDoc) {
+          TPdfiumDocumentStruct* pDoc = itDoc->second;
+          for(itPage = pDoc->pages.begin(); itPage != pDoc->pages.end(); ++itPage) {
+            TPdfiumPageStruct* pPage = itPage->second;
+
+            CPLCreateOrAcquireMutex(&g_oPdfiumReadMutex, PDFIUM_MUTEX_TIMEOUT);
+            CPLCreateOrAcquireMutex(&(pPage->readMutex), PDFIUM_MUTEX_TIMEOUT);
+            CPLReleaseMutex(pPage->readMutex);
+            CPLDestroyMutex(pPage->readMutex);
+            FPDF_ClosePage(pPage->page);
+            delete pPage;
+            CPLReleaseMutex(g_oPdfiumReadMutex);
+          } // ~ foreach page
+
+          FPDF_CloseDocument(pDoc->doc);
+          CPLFree(pDoc->filename);
+          VSIFCloseL((VSILFILE*)pDoc->psFileAccess->m_Param);
+          delete pDoc->psFileAccess;
+          pDoc->pages.clear();
+
+          delete pDoc;
+        } // ~ foreach document
+        g_mPdfiumDatasets.clear();
+        FPDF_DestroyLibrary();
+        PDFDataset::bPdfiumInit = FALSE;
+
+        CPLReleaseMutex(g_oPdfiumLoadDocMutex);
+
+        if( g_oPdfiumReadMutex )
+            CPLDestroyMutex(g_oPdfiumReadMutex);
+        CPLDestroyMutex(g_oPdfiumLoadDocMutex);
+    }
+#endif
 }
 
 /************************************************************************/
@@ -5229,34 +6749,37 @@ CPLString PDFSanitizeLayerName(const char* pszName)
 void GDALRegister_PDF()
 
 {
-    GDALDriver  *poDriver;
+    if( !GDAL_CHECK_VERSION( "PDF driver" ) )
+        return;
 
-    if (! GDAL_CHECK_VERSION("PDF driver"))
+    if( GDALGetDriverByName( "PDF" ) != NULL )
         return;
 
-    if( GDALGetDriverByName( "PDF" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "PDF" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Geospatial PDF" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_pdf.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "pdf" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte" );
+
+#if defined(HAVE_POPPLER) || defined(HAVE_PDFIUM)
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+#endif
 
-        poDriver->SetDescription( "PDF" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Geospatial PDF" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "frmt_pdf.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "pdf" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
-                                   "Byte" );
 #ifdef HAVE_POPPLER
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-        poDriver->SetMetadataItem( "HAVE_POPPLER", "YES" );
+    poDriver->SetMetadataItem( "HAVE_POPPLER", "YES" );
 #endif // HAVE_POPPLER
 #ifdef HAVE_PODOFO
-        poDriver->SetMetadataItem( "HAVE_PODOFO", "YES" );
+    poDriver->SetMetadataItem( "HAVE_PODOFO", "YES" );
 #endif // HAVE_PODOFO
+#ifdef HAVE_PDFIUM
+    poDriver->SetMetadataItem( "HAVE_PDFIUM", "YES" );
+#endif // HAVE_PDFIUM
 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>\n"
 "   <Option name='COMPRESS' type='string-select' description='Compression method for raster data' default='DEFLATE'>\n"
 "     <Value>NONE</Value>\n"
@@ -5314,17 +6837,16 @@ void GDALRegister_PDF()
 "   <Option name='JAVASCRIPT_FILE' type='string' description='Filename of the Javascript script to embed and run at file opening'/>\n"
 "</CreationOptionList>\n" );
 
-#if defined(HAVE_POPPLER) || defined(HAVE_PODOFO)
-        poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST, pszOpenOptionList );
-        poDriver->pfnOpen = PDFDataset::Open;
-        poDriver->pfnIdentify = PDFDataset::Identify;
-        poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
-#endif // HAVE_POPPLER || HAVE_PODOFO
+#if defined(HAVE_POPPLER) || defined(HAVE_PODOFO) || defined(HAVE_PDFIUM)
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST, szOpenOptionList );
+    poDriver->pfnOpen = PDFDataset::Open;
+    poDriver->pfnIdentify = PDFDataset::Identify;
+    poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
+#endif // HAVE_POPPLER || HAVE_PODOFO || defined(HAVE_PDFIUM)
 
-        poDriver->pfnCreateCopy = GDALPDFCreateCopy;
-        poDriver->pfnCreate = PDFWritableVectorDataset::Create;
-        poDriver->pfnUnloadDriver = GDALPDFUnloadDriver;
+    poDriver->pfnCreateCopy = GDALPDFCreateCopy;
+    poDriver->pfnCreate = PDFWritableVectorDataset::Create;
+    poDriver->pfnUnloadDriver = GDALPDFUnloadDriver;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/pdf/pdfio.cpp b/frmts/pdf/pdfio.cpp
index 0334311..3baeac0 100644
--- a/frmts/pdf/pdfio.cpp
+++ b/frmts/pdf/pdfio.cpp
@@ -35,7 +35,7 @@
 
 #include "cpl_vsi.h"
 
-CPL_CVSID("$Id: pdfio.cpp 28956 2015-04-20 16:17:55Z rouault $");
+CPL_CVSID("$Id: pdfio.cpp 31977 2015-12-03 11:42:22Z rouault $");
 
 
 #ifdef POPPLER_BASE_STREAM_HAS_TWO_ARGS
@@ -53,20 +53,20 @@ static vsi_l_offset VSIPDFFileStreamGetSize(VSILFILE* f)
 /*                         VSIPDFFileStream()                           */
 /************************************************************************/
 
-VSIPDFFileStream::VSIPDFFileStream(VSILFILE* f, const char* pszFilename, Object *dictA):
+VSIPDFFileStream::VSIPDFFileStream(VSILFILE* fIn, const char* pszFilename, Object *dictA):
 #ifdef POPPLER_BASE_STREAM_HAS_TWO_ARGS
-                                                        BaseStream(dictA, (setPos_offset_type)VSIPDFFileStreamGetSize(f))
+                                                        BaseStream(dictA, (setPos_offset_type)VSIPDFFileStreamGetSize(fIn))
 #else
                                                         BaseStream(dictA)
 #endif
 {
     poParent = NULL;
     poFilename = new GooString(pszFilename);
-    this->f = f;
+    this->f = fIn;
     nStart = 0;
     bLimited = gFalse;
     nLength = 0;
-    nCurrentPos = -1;
+    nCurrentPos = VSI_L_OFFSET_MAX;
     bHasSavedPos = FALSE;
     nSavedPos = 0;
     nPosInBuffer = nBufferLength = -1;
@@ -76,22 +76,22 @@ VSIPDFFileStream::VSIPDFFileStream(VSILFILE* f, const char* pszFilename, Object
 /*                         VSIPDFFileStream()                           */
 /************************************************************************/
 
-VSIPDFFileStream::VSIPDFFileStream(VSIPDFFileStream* poParent,
+VSIPDFFileStream::VSIPDFFileStream(VSIPDFFileStream* poParentIn,
                                    vsi_l_offset startA, GBool limitedA,
                                    vsi_l_offset lengthA, Object *dictA):
 #ifdef POPPLER_BASE_STREAM_HAS_TWO_ARGS
-                                                        BaseStream(dictA, lengthA)
+                                                        BaseStream(dictA, (makeSubStream_offset_type)lengthA)
 #else
                                                         BaseStream(dictA)
 #endif
 {
-    this->poParent = poParent;
+    this->poParent = poParentIn;
     poFilename = poParent->poFilename;
     f = poParent->f;
     nStart = startA;
     bLimited = limitedA;
     nLength = lengthA;
-    nCurrentPos = -1;
+    nCurrentPos = VSI_L_OFFSET_MAX;
     bHasSavedPos = FALSE;
     nSavedPos = 0;
     nPosInBuffer = nBufferLength = -1;
@@ -206,7 +206,7 @@ int VSIPDFFileStream::FillBuffer()
     // So make as if the file is not linearized to avoid those issues...
     // All this is due to our attempt of avoiding cross-heap issues with allocation
     // and liberation of VSIPDFFileStream as PDFDoc::str member.
-    if( nCurrentPos <= 0 )
+    if( nCurrentPos == 0 || nCurrentPos == VSI_L_OFFSET_MAX )
     {
         for(int i=0;i<nToRead-(int)strlen("/Linearized ");i++)
         {
diff --git a/frmts/pdf/pdfio.h b/frmts/pdf/pdfio.h
index f649a1b..13b36a0 100644
--- a/frmts/pdf/pdfio.h
+++ b/frmts/pdf/pdfio.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pdfio.h 28438 2015-02-07 21:47:35Z rouault $
+ * $Id: pdfio.h 33338 2016-02-03 10:24:38Z rouault $
  *
  * Project:  PDF driver
  * Purpose:  GDALDataset driver for PDF dataset.
@@ -32,12 +32,6 @@
 
 #include "cpl_vsi_virtual.h"
 
-
-/* begin of poppler xpdf includes */
-#include <poppler/Object.h>
-#include <poppler/Stream.h>
-/* end of poppler xpdf includes */
-
 /************************************************************************/
 /*                         VSIPDFFileStream                             */
 /************************************************************************/
@@ -101,7 +95,7 @@ class VSIPDFFileStream: public BaseStream
         GooString         *poFilename;
         VSILFILE          *f;
         vsi_l_offset       nStart;
-        int                bLimited;
+        GBool              bLimited;
         vsi_l_offset       nLength;
 
         vsi_l_offset       nCurrentPos;
diff --git a/frmts/pdf/pdfobject.cpp b/frmts/pdf/pdfobject.cpp
index 58995a4..e1f11a9 100644
--- a/frmts/pdf/pdfobject.cpp
+++ b/frmts/pdf/pdfobject.cpp
@@ -1,11 +1,18 @@
 /******************************************************************************
- * $Id: pdfobject.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: pdfobject.cpp 32179 2015-12-14 16:22:34Z goatbar $
  *
  * Project:  PDF driver
  * Purpose:  GDALDataset driver for PDF dataset.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
+ *
+ * Support for open-source PDFium library
+ *
+ * Copyright (C) 2015 Klokan Technologies GmbH (http://www.klokantech.com/)
+ * Author: Martin Mikita <martin.mikita at klokantech.com>, xmikit00 @ FIT VUT Brno
+ *
+ ******************************************************************************
  * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -32,7 +39,7 @@
 #include <vector>
 #include "pdfobject.h"
 
-CPL_CVSID("$Id: pdfobject.cpp 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: pdfobject.cpp 32179 2015-12-14 16:22:34Z goatbar $");
 
 /************************************************************************/
 /*                        ROUND_TO_INT_IF_CLOSE()                       */
@@ -101,6 +108,76 @@ static CPLString GDALPDFGetPDFString(const char* pszStr)
     return osStr;
 }
 
+#if defined(HAVE_POPPLER) || defined(HAVE_PDFIUM)
+
+/************************************************************************/
+/*                     GDALPDFGetUTF8StringFromBytes()                  */
+/************************************************************************/
+
+static CPLString GDALPDFGetUTF8StringFromBytes(const GByte* pabySrc, int nLen)
+{
+    int bLEUnicodeMarker = nLen > 2 && pabySrc[0] == 0xFE && pabySrc[1] == 0xFF;
+    int bBEUnicodeMarker = nLen > 2 && pabySrc[0] == 0xFF && pabySrc[1] == 0xFE;
+    if (!bLEUnicodeMarker && !bBEUnicodeMarker)
+    {
+        CPLString osStr;
+        osStr.resize( nLen + 1 );
+        osStr.assign( (const char*)pabySrc, (size_t)nLen );
+        osStr[nLen] = 0;
+        const char* pszStr = osStr.c_str();
+        if (CPLIsUTF8(pszStr, -1))
+            return osStr;
+        else
+        {
+            char* pszUTF8 = CPLRecode( pszStr, CPL_ENC_ISO8859_1, CPL_ENC_UTF8 );
+            CPLString osRet = pszUTF8;
+            CPLFree(pszUTF8);
+            return osRet;
+        }
+    }
+
+    /* This is UTF-16 content */
+    pabySrc += 2;
+    nLen = (nLen - 2) / 2;
+    wchar_t *pwszSource = new wchar_t[nLen + 1];
+    int j = 0;
+    for(int i=0; i<nLen; i++, j++)
+    {
+        if (!bBEUnicodeMarker)
+            pwszSource[j] = (pabySrc[2 * i] << 8) + pabySrc[2 * i + 1];
+        else
+            pwszSource[j] = (pabySrc[2 * i + 1] << 8) + pabySrc[2 * i];
+#ifndef _WIN32
+        /* Is there a surrogate pair ? See http://en.wikipedia.org/wiki/UTF-16 */
+        /* On Windows, CPLRecodeFromWChar does this for us, because wchar_t is only */
+        /* 2 bytes wide, whereas on Unix it is 32bits */
+        if (pwszSource[j] >= 0xD800 && pwszSource[j] <= 0xDBFF && i + 1 < nLen)
+        {
+            /* should be in the range 0xDC00... 0xDFFF */
+            wchar_t nTrailSurrogate;
+            if (!bBEUnicodeMarker)
+                nTrailSurrogate = (pabySrc[2 * (i+1)] << 8) + pabySrc[2 * (i+1) + 1];
+            else
+                nTrailSurrogate = (pabySrc[2 * (i+1) + 1] << 8) + pabySrc[2 * (i+1)];
+            if (nTrailSurrogate >= 0xDC00 && nTrailSurrogate <= 0xDFFF)
+            {
+                pwszSource[j] = ((pwszSource[j] - 0xD800) << 10) + (nTrailSurrogate - 0xDC00) + 0x10000;
+                i++;
+            }
+        }
+#endif
+    }
+    pwszSource[j] = 0;
+
+    char* pszUTF8 = CPLRecodeFromWChar( pwszSource, CPL_ENC_UCS2, CPL_ENC_UTF8 );
+    delete[] pwszSource;
+    CPLString osStrUTF8(pszUTF8);
+    CPLFree(pszUTF8);
+    return osStrUTF8;
+}
+
+#endif // defined(HAVE_POPPLER) || defined(HAVE_PDFIUM)
+
 /************************************************************************/
 /*                          GDALPDFGetPDFName()                         */
 /************************************************************************/
@@ -192,15 +269,15 @@ void GDALPDFObject::Serialize(CPLString& osStr)
             double dfRealNonRounded = GetReal();
             double dfReal = ROUND_TO_INT_IF_CLOSE(dfRealNonRounded);
             if (dfReal == (double)(GIntBig)dfReal)
-                sprintf(szReal, CPL_FRMT_GIB, (GIntBig)dfReal);
+                snprintf(szReal, sizeof(szReal), CPL_FRMT_GIB, (GIntBig)dfReal);
             else if (CanRepresentRealAsString())
             {
                 /* Used for OGC BP numeric values */
-                CPLsprintf(szReal, "(%.16g)", dfReal);
+                CPLsnprintf(szReal, sizeof(szReal), "(%.16g)", dfReal);
             }
             else
             {
-                CPLsprintf(szReal, "%.16f", dfReal);
+                CPLsnprintf(szReal, sizeof(szReal), "%.16f", dfReal);
 
                 /* Remove non significant trailing zeroes */
                 char* pszDot = strchr(szReal, '.');
@@ -778,7 +855,7 @@ GDALPDFArrayRW::GDALPDFArrayRW()
 
 GDALPDFArrayRW::~GDALPDFArrayRW()
 {
-    for(int i=0; i < (int)m_array.size(); i++)
+    for(size_t i=0; i < m_array.size(); i++)
         delete m_array[i];
 }
 
@@ -788,7 +865,7 @@ GDALPDFArrayRW::~GDALPDFArrayRW()
 
 int GDALPDFArrayRW::GetLength()
 {
-    return (int)m_array.size();
+    return static_cast<int>(m_array.size());
 }
 
 /************************************************************************/
@@ -973,76 +1050,17 @@ double GDALPDFObjectPoppler::GetReal()
 }
 
 /************************************************************************/
-/*                         GDALPDFPopplerGetUTF8()                      */
-/************************************************************************/
-
-static CPLString GDALPDFPopplerGetUTF8(GooString* poStr)
-{
-    GByte* pabySrc = (GByte*)poStr->getCString();
-    int nLen = poStr->getLength();
-    int bBEUnicodeMarker = nLen > 2 && pabySrc[0] == 0xFF && pabySrc[1] == 0xFE;
-    if (!poStr->hasUnicodeMarker() && !bBEUnicodeMarker)
-    {
-        const char* pszStr = poStr->getCString();
-        if (CPLIsUTF8(pszStr, -1))
-            return pszStr;
-        else
-        {
-            char* pszUTF8 = CPLRecode( pszStr, CPL_ENC_ISO8859_1, CPL_ENC_UTF8 );
-            CPLString osRet = pszUTF8;
-            CPLFree(pszUTF8);
-            return osRet;
-        }
-    }
-
-    /* This is UTF-16 content */
-    pabySrc += 2;
-    nLen = (nLen - 2) / 2;
-    wchar_t *pwszSource = new wchar_t[nLen + 1];
-    int j = 0;
-    for(int i=0; i<nLen; i++, j++)
-    {
-        if (!bBEUnicodeMarker)
-            pwszSource[j] = (pabySrc[2 * i] << 8) + pabySrc[2 * i + 1];
-        else
-            pwszSource[j] = (pabySrc[2 * i + 1] << 8) + pabySrc[2 * i];
-#ifndef _WIN32
-        /* Is there a surrogate pair ? See http://en.wikipedia.org/wiki/UTF-16 */
-        /* On Windows, CPLRecodeFromWChar does this for us, because wchar_t is only */
-        /* 2 bytes wide, whereas on Unix it is 32bits */
-        if (pwszSource[j] >= 0xD800 && pwszSource[j] <= 0xDBFF && i + 1 < nLen)
-        {
-            /* should be in the range 0xDC00... 0xDFFF */
-            wchar_t nTrailSurrogate;
-            if (!bBEUnicodeMarker)
-                nTrailSurrogate = (pabySrc[2 * (i+1)] << 8) + pabySrc[2 * (i+1) + 1];
-            else
-                nTrailSurrogate = (pabySrc[2 * (i+1) + 1] << 8) + pabySrc[2 * (i+1)];
-            if (nTrailSurrogate >= 0xDC00 && nTrailSurrogate <= 0xDFFF)
-            {
-                pwszSource[j] = ((pwszSource[j] - 0xD800) << 10) + (nTrailSurrogate - 0xDC00) + 0x10000;
-                i++;
-            }
-        }
-#endif
-    }
-    pwszSource[j] = 0;
-
-    char* pszUTF8 = CPLRecodeFromWChar( pwszSource, CPL_ENC_UCS2, CPL_ENC_UTF8 );
-    delete[] pwszSource;
-    CPLString osStrUTF8(pszUTF8);
-    CPLFree(pszUTF8);
-    return osStrUTF8;
-}
-
-/************************************************************************/
 /*                              GetString()                             */
 /************************************************************************/
 
 const CPLString& GDALPDFObjectPoppler::GetString()
 {
     if (GetType() == PDFObjectType_String)
-        return (osStr = GDALPDFPopplerGetUTF8(m_po->getString()));
+    {
+        GooString* gooString = m_po->getString();
+        return (osStr = GDALPDFGetUTF8StringFromBytes(reinterpret_cast<const GByte*>(gooString->getCString()),
+                                                      static_cast<int>(gooString->getLength())));
+    }
     else
         return (osStr = "");
 }
@@ -1234,7 +1252,7 @@ GDALPDFArray* GDALPDFCreateArray(Array* array)
 
 GDALPDFArrayPoppler::~GDALPDFArrayPoppler()
 {
-    for(int i=0;i<(int)m_v.size();i++)
+    for(size_t i=0;i<m_v.size();i++)
     {
         delete m_v[i];
     }
@@ -1258,7 +1276,7 @@ GDALPDFObject* GDALPDFArrayPoppler::Get(int nIndex)
     if (nIndex < 0 || nIndex >= GetLength())
         return NULL;
 
-    int nOldSize = (int)m_v.size();
+    int nOldSize = static_cast<int>(m_v.size());
     if (nIndex >= nOldSize)
     {
         m_v.resize(nIndex+1);
@@ -1337,10 +1355,11 @@ char* GDALPDFStreamPoppler::GetBytes()
     {
         m_nLength = gstr->getLength();
         char* pszContent = (char*) VSIMalloc(m_nLength + 1);
-        if (!pszContent)
-            return NULL;
-        memcpy(pszContent, gstr->getCString(), m_nLength);
-        pszContent[m_nLength] = '\0';
+        if (pszContent)
+        {
+            memcpy(pszContent, gstr->getCString(), m_nLength);
+            pszContent[m_nLength] = '\0';
+        }
         delete gstr;
         return pszContent;
     }
@@ -1441,11 +1460,11 @@ class GDALPDFArrayPodofo : public GDALPDFArray
 class GDALPDFStreamPodofo : public GDALPDFStream
 {
     private:
-        PoDoFo::PdfMemStream* m_pStream;
+        PoDoFo::PdfStream* m_pStream;
 
     public:
-        GDALPDFStreamPodofo(PoDoFo::PdfMemStream* pStream) : m_pStream(pStream) { }
-        virtual ~GDALPDFStreamPodofo() {}
+        GDALPDFStreamPodofo(PoDoFo::PdfStream* pStream) : m_pStream(pStream) { }
+        virtual ~GDALPDFStreamPodofo() { }
 
         virtual int GetLength();
         virtual char* GetBytes();
@@ -1555,7 +1574,7 @@ int GDALPDFObjectPodofo::GetBool()
 int GDALPDFObjectPodofo::GetInt()
 {
     if (m_po->GetDataType() == PoDoFo::ePdfDataType_Number)
-        return (int)m_po->GetNumber();
+        return static_cast<int>(m_po->GetNumber());
     else
         return 0;
 }
@@ -1650,26 +1669,9 @@ GDALPDFStream* GDALPDFObjectPodofo::GetStream()
         return NULL;
     }
 
-    if (m_poStream)
-        return m_poStream;
-    PoDoFo::PdfMemStream* pStream = NULL;
-    try
-    {
-        pStream = dynamic_cast<PoDoFo::PdfMemStream*>(m_po->GetStream());
-        pStream->Uncompress();
-    }
-    catch( const PoDoFo::PdfError & e )
-    {
-        e.PrintErrorMsg();
-        pStream = NULL;
-    }
-    if (pStream)
-    {
-        m_poStream = new GDALPDFStreamPodofo(pStream);
-        return m_poStream;
-    }
-    else
-        return NULL;
+    if (m_poStream == NULL)
+        m_poStream = new GDALPDFStreamPodofo(m_po->GetStream());
+    return m_poStream;
 }
 
 /************************************************************************/
@@ -1756,7 +1758,7 @@ std::map<CPLString, GDALPDFObject*>& GDALPDFDictionaryPodofo::GetValues()
 
 GDALPDFArrayPodofo::~GDALPDFArrayPodofo()
 {
-    for(int i=0;i<(int)m_v.size();i++)
+    for(size_t i=0;i<m_v.size();i++)
     {
         delete m_v[i];
     }
@@ -1768,7 +1770,7 @@ GDALPDFArrayPodofo::~GDALPDFArrayPodofo()
 
 int GDALPDFArrayPodofo::GetLength()
 {
-    return (int)m_poArray->GetSize();
+    return static_cast<int>(m_poArray->GetSize());
 }
 
 /************************************************************************/
@@ -1780,7 +1782,7 @@ GDALPDFObject* GDALPDFArrayPodofo::Get(int nIndex)
     if (nIndex < 0 || nIndex >= GetLength())
         return NULL;
 
-    int nOldSize = (int)m_v.size();
+    int nOldSize = static_cast<int>(m_v.size());
     if (nIndex >= nOldSize)
     {
         m_v.resize(nIndex+1);
@@ -1811,7 +1813,18 @@ GDALPDFObject* GDALPDFArrayPodofo::Get(int nIndex)
 
 int GDALPDFStreamPodofo::GetLength()
 {
-    return (int)m_pStream->GetLength();
+    char* pBuffer = NULL;
+    PoDoFo::pdf_long nLen = 0;
+    try
+    {
+        m_pStream->GetFilteredCopy( &pBuffer, &nLen );
+        PoDoFo::podofo_free(pBuffer);
+        return (int)nLen;
+    }
+    catch( PoDoFo::PdfError & e )
+    {
+    }
+    return 0;
 }
 
 /************************************************************************/
@@ -1820,13 +1833,513 @@ int GDALPDFStreamPodofo::GetLength()
 
 char* GDALPDFStreamPodofo::GetBytes()
 {
+    char* pBuffer = NULL;
+    PoDoFo::pdf_long nLen = 0;
+    try
+    {
+        m_pStream->GetFilteredCopy( &pBuffer, &nLen );
+    }
+    catch( PoDoFo::PdfError & e )
+    {
+        return NULL;
+    }
+    char* pszContent = (char*) VSIMalloc(nLen + 1);
+    if (!pszContent)
+    {
+        PoDoFo::podofo_free(pBuffer);
+        return NULL;
+    }
+    memcpy(pszContent, pBuffer, nLen);
+    PoDoFo::podofo_free(pBuffer);
+    pszContent[nLen] = '\0';
+    return pszContent;
+}
+
+#endif // HAVE_PODOFO
+
+#ifdef HAVE_PDFIUM
+
+/************************************************************************/
+/* ==================================================================== */
+/*                         GDALPDFDictionaryPdfium                      */
+/* ==================================================================== */
+/************************************************************************/
+
+class GDALPDFDictionaryPdfium: public GDALPDFDictionary
+{
+    private:
+        CPDF_Dictionary* m_poDict;
+        std::map<CPLString, GDALPDFObject*> m_map;
+
+    public:
+        GDALPDFDictionaryPdfium(CPDF_Dictionary* poDict) : m_poDict(poDict) {}
+        virtual ~GDALPDFDictionaryPdfium();
+
+        virtual GDALPDFObject* Get(const char* pszKey);
+        virtual std::map<CPLString, GDALPDFObject*>& GetValues();
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                           GDALPDFArrayPdfium                         */
+/* ==================================================================== */
+/************************************************************************/
+
+class GDALPDFArrayPdfium : public GDALPDFArray
+{
+    private:
+        CPDF_Array* m_poArray;
+        std::vector<GDALPDFObject*> m_v;
+
+    public:
+        GDALPDFArrayPdfium(CPDF_Array* poArray) : m_poArray(poArray) {}
+        virtual ~GDALPDFArrayPdfium();
+
+        virtual int GetLength();
+        virtual GDALPDFObject* Get(int nIndex);
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                          GDALPDFStreamPdfium                         */
+/* ==================================================================== */
+/************************************************************************/
+
+class GDALPDFStreamPdfium : public GDALPDFStream
+{
+    private:
+        CPDF_Stream* m_pStream;
+        int m_nSize;
+        void* m_pData;
+
+        void Decompress();
+
+    public:
+        GDALPDFStreamPdfium(CPDF_Stream* pStream) : m_pStream(pStream), m_nSize(0), m_pData(NULL) { }
+        virtual ~GDALPDFStreamPdfium() { FX_Free(m_pData); }
+
+        virtual int GetLength();
+        virtual char* GetBytes();
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                          GDALPDFObjectPdfium                         */
+/* ==================================================================== */
+/************************************************************************/
+
+/************************************************************************/
+/*                          GDALPDFObjectPdfium()                       */
+/************************************************************************/
+
+GDALPDFObjectPdfium::GDALPDFObjectPdfium(CPDF_Object *po) :
+        m_po(po), m_poDict(NULL), m_poArray(NULL), m_poStream(NULL)
+{
+    CPLAssert(m_po != NULL);
+}
+
+/************************************************************************/
+/*                         ~GDALPDFObjectPdfium()                       */
+/************************************************************************/
+
+GDALPDFObjectPdfium::~GDALPDFObjectPdfium()
+{
+    delete m_poDict;
+    delete m_poArray;
+    delete m_poStream;
+}
+
+/************************************************************************/
+/*                               Build()                                */
+/************************************************************************/
+
+GDALPDFObjectPdfium* GDALPDFObjectPdfium::Build(CPDF_Object *poVal)
+{
+    if( poVal == NULL )
+        return NULL;
+    if( poVal->GetType() == PDFOBJ_REFERENCE )
+    {
+        poVal = poVal->GetDirect();
+        if( poVal == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Cannot resolve indirect object");
+            return NULL;
+        }
+    }
+    return new GDALPDFObjectPdfium(poVal);
+}
+
+/************************************************************************/
+/*                               GetType()                              */
+/************************************************************************/
+
+GDALPDFObjectType GDALPDFObjectPdfium::GetType()
+{
+    switch(m_po->GetType())
+    {
+        case PDFOBJ_NULL:                     return PDFObjectType_Null;
+        case PDFOBJ_BOOLEAN:                  return PDFObjectType_Bool;
+        case PDFOBJ_NUMBER:
+          return (reinterpret_cast<CPDF_Number*>(m_po))->IsInteger()
+              ? PDFObjectType_Int
+              : PDFObjectType_Real;
+        case PDFOBJ_STRING:                   return PDFObjectType_String;
+        case PDFOBJ_NAME:                     return PDFObjectType_Name;
+        case PDFOBJ_ARRAY:                    return PDFObjectType_Array;
+        case PDFOBJ_DICTIONARY:               return PDFObjectType_Dictionary;
+        case PDFOBJ_STREAM:                   return PDFObjectType_Dictionary;
+        default:
+          CPLAssert(FALSE);
+          return PDFObjectType_Unknown;
+    }
+}
+
+/************************************************************************/
+/*                          GetTypeNameNative()                         */
+/************************************************************************/
+
+const char* GDALPDFObjectPdfium::GetTypeNameNative()
+{
+    if(m_po->GetType() == PDFOBJ_STREAM)
+      return "stream";
+    else
+      return "";
+}
+
+/************************************************************************/
+/*                              GetBool()                               */
+/************************************************************************/
+
+int GDALPDFObjectPdfium::GetBool()
+{
+    return m_po->GetInteger();
+}
+
+/************************************************************************/
+/*                              GetInt()                                */
+/************************************************************************/
+
+int GDALPDFObjectPdfium::GetInt()
+{
+    return m_po->GetInteger();
+}
+
+
+/************************************************************************/
+/*                       CPLRoundToMoreLikelyDouble()                   */
+/************************************************************************/
+
+// We try to compensate for rounding errors when converting the number
+// in the PDF expressed as a string (e.g 297.84) to float32 by pdfium : 297.8399963378906
+// Which is technically correct per the PDF spec, but in practice poppler or podofo use double
+// and Geospatial PDF are often encoded with double precision.
+
+static double CPLRoundToMoreLikelyDouble(float f)
+{
+    if( (float)(int)f == f )
+        return f;
+
+    char szBuffer[80];
+    CPLsnprintf(szBuffer, 80, "%f\n", f);
+    double d = f;
+    char* pszDot = strchr(szBuffer, '.');
+    if( pszDot == NULL )
+        return d;
+    pszDot ++;
+    if( pszDot[0] == 0 || pszDot[1] == 0 )
+        return d;
+    if( STARTS_WITH(pszDot + 2, "99") )
+    {
+        pszDot[2] = 0;
+        double d2 = CPLAtof(szBuffer) + 0.01;
+        float f2 = (float)d2;
+        if( f == f2 || nextafterf(f,f+1.0f) == f2 || nextafterf(f,f-1.0f) == f2 )
+            d = d2;
+    }
+    else if( STARTS_WITH(pszDot + 2, "00") )
+    {
+        pszDot[2] = 0;
+        double d2 = CPLAtof(szBuffer);
+        float f2 = (float)d2;
+        if( f == f2 || nextafterf(f,f+1.0f) == f2 || nextafterf(f,f-1.0f) == f2 )
+            d = d2;
+    }
+    return d;
+}
+
+/************************************************************************/
+/*                              GetReal()                               */
+/************************************************************************/
+
+double GDALPDFObjectPdfium::GetReal()
+{
+    return CPLRoundToMoreLikelyDouble(m_po->GetNumber());
+}
+
+/************************************************************************/
+/*                              GetString()                             */
+/************************************************************************/
+
+const CPLString& GDALPDFObjectPdfium::GetString()
+{
+    if (GetType() == PDFObjectType_String) {
+        CFX_ByteStringC bs = m_po->GetConstString();
+        // If empty string, code crashes
+        if(bs.IsEmpty())
+          return (osStr = "");
+        return (osStr = GDALPDFGetUTF8StringFromBytes(static_cast<const GByte*>(bs.GetPtr()),
+                                                      static_cast<int>(bs.GetLength())));
+    }
+    else
+        return (osStr = "");
+}
+
+/************************************************************************/
+/*                              GetName()                               */
+/************************************************************************/
+
+const CPLString&  GDALPDFObjectPdfium::GetName()
+{
+    if (GetType() == PDFObjectType_Name)
+        return (osStr = m_po->GetConstString().GetCStr());
+    else
+        return (osStr = "");
+}
+
+/************************************************************************/
+/*                             GetDictionary()                          */
+/************************************************************************/
+
+GDALPDFDictionary* GDALPDFObjectPdfium::GetDictionary()
+{
+    if (GetType() != PDFObjectType_Dictionary)
+        return NULL;
+
+    if (m_poDict)
+        return m_poDict;
+
+    m_poDict = new GDALPDFDictionaryPdfium(m_po->GetDict());
+    return m_poDict;
+}
+
+/************************************************************************/
+/*                                GetArray()                            */
+/************************************************************************/
+
+GDALPDFArray* GDALPDFObjectPdfium::GetArray()
+{
+    if (GetType() != PDFObjectType_Array)
+        return NULL;
+
+    if (m_poArray)
+        return m_poArray;
+
+    m_poArray = new GDALPDFArrayPdfium(reinterpret_cast<CPDF_Array*>(m_po));
+    return m_poArray;
+}
+
+/************************************************************************/
+/*                               GetStream()                            */
+/************************************************************************/
+
+GDALPDFStream* GDALPDFObjectPdfium::GetStream()
+{
+    if (m_po->GetType() != PDFOBJ_STREAM)
+        return NULL;
+
+    if (m_poStream)
+        return m_poStream;
+    CPDF_Stream* pStream = reinterpret_cast<CPDF_Stream*>(m_po);
+    if (pStream)
+    {
+        m_poStream = new GDALPDFStreamPdfium(pStream);
+        return m_poStream;
+    }
+    else
+        return NULL;
+}
+
+/************************************************************************/
+/*                               GetRefNum()                            */
+/************************************************************************/
+
+int GDALPDFObjectPdfium::GetRefNum()
+{
+    return m_po->GetObjNum();
+}
+
+/************************************************************************/
+/*                               GetRefGen()                            */
+/************************************************************************/
+
+int GDALPDFObjectPdfium::GetRefGen()
+{
+    return m_po->GetGenNum();
+}
+
+/************************************************************************/
+/* ==================================================================== */
+/*                         GDALPDFDictionaryPdfium                      */
+/* ==================================================================== */
+/************************************************************************/
+
+/************************************************************************/
+/*                         ~GDALPDFDictionaryPdfium()                   */
+/************************************************************************/
+
+GDALPDFDictionaryPdfium::~GDALPDFDictionaryPdfium()
+{
+    std::map<CPLString, GDALPDFObject*>::iterator oIter = m_map.begin();
+    std::map<CPLString, GDALPDFObject*>::iterator oEnd = m_map.end();
+    for(; oIter != oEnd; ++oIter)
+        delete oIter->second;
+}
+
+/************************************************************************/
+/*                                  Get()                               */
+/************************************************************************/
+
+GDALPDFObject* GDALPDFDictionaryPdfium::Get(const char* pszKey)
+{
+    std::map<CPLString, GDALPDFObject*>::iterator oIter = m_map.find(pszKey);
+    if (oIter != m_map.end())
+        return oIter->second;
+
+    CFX_ByteStringC pdfiumKey(pszKey);
+    CPDF_Object* poVal = m_poDict->GetElement(pdfiumKey);
+    GDALPDFObjectPdfium* poObj = GDALPDFObjectPdfium::Build(poVal);
+    if (poObj)
+    {
+        m_map[pszKey] = poObj;
+        return poObj;
+    }
+    else
+    {
+        return NULL;
+    }
+}
+
+/************************************************************************/
+/*                              GetValues()                             */
+/************************************************************************/
+
+std::map<CPLString, GDALPDFObject*>& GDALPDFDictionaryPdfium::GetValues()
+{
+    FX_POSITION pos = m_poDict->GetStartPos();
+    while(pos)
+    {
+        CFX_ByteString key;
+        CPDF_Object* poVal = m_poDict->GetNextElement(pos, key);
+        // No object for this key
+        if(!poVal)
+          continue;
+
+        const char* pszKey = key.c_str();
+        // Objects exists in the map
+        if(m_map.find(pszKey) != m_map.end())
+          continue;
+        GDALPDFObjectPdfium* poObj = GDALPDFObjectPdfium::Build(poVal);
+        if( poObj == NULL )
+            continue;
+        m_map[pszKey] = poObj;
+    }
+    return m_map;
+}
+
+/************************************************************************/
+/* ==================================================================== */
+/*                           GDALPDFArrayPdfium                         */
+/* ==================================================================== */
+/************************************************************************/
+
+GDALPDFArrayPdfium::~GDALPDFArrayPdfium()
+{
+    for(size_t i=0;i<m_v.size();i++)
+    {
+        delete m_v[i];
+    }
+}
+
+/************************************************************************/
+/*                              GetLength()                             */
+/************************************************************************/
+
+int GDALPDFArrayPdfium::GetLength()
+{
+    return static_cast<int>(m_poArray->GetCount());
+}
+
+/************************************************************************/
+/*                                Get()                                 */
+/************************************************************************/
+
+GDALPDFObject* GDALPDFArrayPdfium::Get(int nIndex)
+{
+    if (nIndex < 0 || nIndex >= GetLength())
+        return NULL;
+
+    int nOldSize = static_cast<int>(m_v.size());
+    if (nIndex >= nOldSize)
+    {
+        m_v.resize(nIndex+1);
+        for(int i=nOldSize;i<=nIndex;i++)
+        {
+            m_v[i] = NULL;
+        }
+    }
+
+    if (m_v[nIndex] != NULL)
+        return m_v[nIndex];
+
+    CPDF_Object* poVal = m_poArray->GetElement(nIndex);
+    GDALPDFObjectPdfium* poObj = GDALPDFObjectPdfium::Build(poVal);
+    if( poObj == NULL )
+        return NULL;
+    m_v[nIndex] = poObj;
+    return poObj;
+}
+
+/************************************************************************/
+/* ==================================================================== */
+/*                           GDALPDFStreamPdfium                        */
+/* ==================================================================== */
+/************************************************************************/
+
+void GDALPDFStreamPdfium::Decompress()
+{
+    if( m_pData != NULL )
+        return;
+    CPDF_StreamAcc acc;
+    acc.LoadAllData(m_pStream);
+    m_nSize = static_cast<int>(acc.GetSize());
+    m_pData = acc.DetachData();
+}
+
+/************************************************************************/
+/*                              GetLength()                             */
+/************************************************************************/
+
+int GDALPDFStreamPdfium::GetLength()
+{
+    Decompress();
+    return m_nSize;
+}
+
+/************************************************************************/
+/*                               GetBytes()                             */
+/************************************************************************/
+
+char* GDALPDFStreamPdfium::GetBytes()
+{
     int nLength = GetLength();
-    char* pszContent = (char*) VSIMalloc(nLength + 1);
+    if(nLength == 0)
+      return NULL;
+    char* pszContent = (char*) VSIMalloc(sizeof(char)*(nLength + 1));
     if (!pszContent)
         return NULL;
-    memcpy(pszContent, m_pStream->Get(), nLength);
+    memcpy( pszContent, m_pData, nLength);
     pszContent[nLength] = '\0';
     return pszContent;
 }
 
-#endif // HAVE_PODOFO
+#endif // HAVE_PDFIUM
diff --git a/frmts/pdf/pdfobject.h b/frmts/pdf/pdfobject.h
index 448cab0..d7ba21f 100644
--- a/frmts/pdf/pdfobject.h
+++ b/frmts/pdf/pdfobject.h
@@ -1,11 +1,18 @@
 /******************************************************************************
- * $Id: pdfobject.h 27329 2014-05-14 16:24:17Z rouault $
+ * $Id: pdfobject.h 31213 2015-10-29 00:02:45Z rouault $
  *
  * Project:  PDF driver
  * Purpose:  GDALDataset driver for PDF dataset.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
+ *
+ * Support for open-source PDFium library
+ *
+ * Copyright (C) 2015 Klokan Technologies GmbH (http://www.klokantech.com/)
+ * Author: Martin Mikita <martin.mikita at klokantech.com>, xmikit00 @ FIT VUT Brno
+ *
+ ******************************************************************************
  * Copyright (c) 2011-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -30,6 +37,8 @@
 #ifndef PDFOBJECT_H_INCLUDED
 #define PDFOBJECT_H_INCLUDED
 
+#include "pdfsdk_headers.h"
+
 #include "cpl_string.h"
 #include <map>
 #include <vector>
@@ -37,48 +46,6 @@
 #define DEFAULT_DPI         (72.0)
 #define USER_UNIT_IN_INCH   (1.0 / DEFAULT_DPI)
 
-#ifdef HAVE_POPPLER
-
-/* begin of poppler xpdf includes */
-#include <poppler/Object.h>
-
-#define private public /* Ugly! Page::pageObj is private but we need it... */
-#include <poppler/Page.h>
-#undef private
-
-#include <poppler/Dict.h>
-
-#define private public /* Ugly! Catalog::optContent is private but we need it... */
-#include <poppler/Catalog.h>
-#undef private
-
-#define private public  /* Ugly! PDFDoc::str is private but we need it... */
-#include <poppler/PDFDoc.h>
-#undef private
-
-#include <poppler/splash/SplashBitmap.h>
-#include <poppler/splash/Splash.h>
-#include <poppler/SplashOutputDev.h>
-#include <poppler/GlobalParams.h>
-#include <poppler/ErrorCodes.h>
-/* end of poppler xpdf includes */
-
-#endif // HAVE_POPPLER
-
-#ifdef HAVE_PODOFO
-/*
- * Some Windows header defines a GetObject macro that
- * shadows a GetObject() method in PoDoFo. This
- * workaround is documented in the PoDoFo source.
- */ 
-#ifdef GetObject
-#undef GetObject
-#endif
-
-#include "podofo.h"
-#endif // HAVE_PODOFO
-
-
 double ROUND_TO_INT_IF_CLOSE(double x, double eps = 0);
 
 typedef enum
@@ -338,4 +305,41 @@ class GDALPDFObjectPodofo : public GDALPDFObject
 
 #endif // HAVE_PODOFO
 
+#ifdef HAVE_PDFIUM
+
+class GDALPDFObjectPdfium : public GDALPDFObject
+{
+    private:
+        CPDF_Object* m_po;
+        GDALPDFDictionary* m_poDict;
+        GDALPDFArray* m_poArray;
+        GDALPDFStream* m_poStream;
+        CPLString osStr;
+
+                GDALPDFObjectPdfium(CPDF_Object *po);
+
+    protected:
+        virtual const char*       GetTypeNameNative();
+
+    public:
+        static GDALPDFObjectPdfium* Build(CPDF_Object *po);
+
+        virtual ~GDALPDFObjectPdfium();
+
+        virtual GDALPDFObjectType GetType();
+        virtual int               GetBool();
+        virtual int               GetInt();
+        virtual double            GetReal();
+        virtual const CPLString&  GetString();
+        virtual const CPLString&  GetName();
+        virtual GDALPDFDictionary*  GetDictionary();
+        virtual GDALPDFArray*       GetArray();
+        virtual GDALPDFStream*      GetStream();
+        virtual int                 GetRefNum();
+        virtual int                 GetRefGen();
+
+};
+
+#endif // HAVE_PDFIUM
+
 #endif // PDFOBJECT_H_INCLUDED
diff --git a/frmts/pdf/pdfreadvectors.cpp b/frmts/pdf/pdfreadvectors.cpp
index 4b9bc39..07fb87d 100644
--- a/frmts/pdf/pdfreadvectors.cpp
+++ b/frmts/pdf/pdfreadvectors.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pdfreadvectors.cpp 29846 2015-08-27 15:29:32Z rouault $
+ * $Id: pdfreadvectors.cpp 33123 2016-01-23 18:59:28Z rouault $
  *
  * Project:  PDF driver
  * Purpose:  GDALDataset driver for PDF dataset (read vector features)
@@ -32,9 +32,9 @@
 #define SQUARE(x) ((x)*(x))
 #define EPSILON 1e-5
 
-CPL_CVSID("$Id: pdfreadvectors.cpp 29846 2015-08-27 15:29:32Z rouault $");
+CPL_CVSID("$Id: pdfreadvectors.cpp 33123 2016-01-23 18:59:28Z rouault $");
 
-#if defined(HAVE_POPPLER) || defined(HAVE_PODOFO)
+#if defined(HAVE_POPPLER) || defined(HAVE_PODOFO) || defined(HAVE_PDFIUM)
 
 /************************************************************************/
 /*                        OpenVectorLayers()                            */
@@ -70,7 +70,7 @@ int PDFDataset::OpenVectorLayers(GDALPDFDictionary* poPageDict)
         return FALSE;
 
     GDALPDFObject* poStructTreeRoot = poCatalogObject->GetDictionary()->Get("StructTreeRoot");
-    if (CSLTestBoolean(CPLGetConfigOption("OGR_PDF_READ_NON_STRUCTURED", "NO")) ||
+    if (CPLTestBool(CPLGetConfigOption("OGR_PDF_READ_NON_STRUCTURED", "NO")) ||
         poStructTreeRoot == NULL ||
         poStructTreeRoot->GetType() != PDFObjectType_Dictionary)
     {
@@ -285,12 +285,12 @@ void PDFDataset::ExploreTree(GDALPDFObject* poObj, int nRecLevel)
                     osLayerName = CPLSPrintf("Layer%d", nLayers + 1);
             }
 
-            const char* pszWKT = GetProjectionRef();
+            const char* l_pszWKT = GetProjectionRef();
             OGRSpatialReference* poSRS = NULL;
-            if (pszWKT && pszWKT[0] != '\0')
+            if (l_pszWKT && l_pszWKT[0] != '\0')
             {
                 poSRS = new OGRSpatialReference();
-                poSRS->importFromWkt((char**) &pszWKT);
+                poSRS->importFromWkt((char**) &l_pszWKT);
             }
 
             OGRPDFLayer* poLayer =
@@ -604,7 +604,7 @@ OGRGeometry* PDFDataset::ParseContent(const char* pszContent,
     int nParenthesisLevel = 0;
     int nArrayLevel = 0;
     int nBTLevel = 0;
-    
+
     int bCollectAllObjects = poResources != NULL && !bInitBDCStack && !bMatchQ;
 
     GraphicState oGS;
@@ -614,7 +614,7 @@ OGRGeometry* PDFDataset::ParseContent(const char* pszContent,
     std::vector<double> oCoords;
     int bHasFoundFill = FALSE;
     int bHasMultiPart = FALSE;
-    
+
     szToken[0] = '\0';
 
     if (bInitBDCStack)
@@ -1147,7 +1147,7 @@ OGRGeometry* PDFDataset::ParseContent(const char* pszContent,
                         }
                         poGeom->assignSpatialReference(poCurLayer->GetSpatialRef());
                         poFeature->SetGeometryDirectly(poGeom);
-                        poCurLayer->CreateFeature(poFeature);
+                        CPL_IGNORE_RET_VAL(poCurLayer->CreateFeature(poFeature));
                         delete poFeature;
                     }
 
@@ -1166,7 +1166,7 @@ OGRGeometry* PDFDataset::ParseContent(const char* pszContent,
         {
             nTokenStackSize--;
             CPLDebug("PDF",
-                     "Remaing values in stack : %s",
+                     "Remaining values in stack : %s",
                      aszTokenStack[nTokenStackSize]);
         }
         return  NULL;
@@ -1211,11 +1211,17 @@ OGRGeometry* PDFDataset::BuildGeometry(std::vector<double>& oCoords,
         {
             if (oCoords[i] == NEW_SUBPATH && oCoords[i+1] == NEW_SUBPATH)
             {
-                poLS = new OGRLineString();
                 if (poMLS)
+                {
+                    poLS = new OGRLineString();
                     poMLS->addGeometryDirectly(poLS);
+                }
                 else
+                {
+                    delete poLS;
+                    poLS = new OGRLineString();
                     poGeom = poLS;
+                }
             }
             else if (oCoords[i] == CLOSE_SUBPATH && oCoords[i+1] == CLOSE_SUBPATH)
             {
@@ -1242,26 +1248,26 @@ OGRGeometry* PDFDataset::BuildGeometry(std::vector<double>& oCoords,
             }
         }
 
-        /* Recognize points as outputed by GDAL (ogr-sym-2 : circle (not filled)) */
+        // Recognize points as written by GDAL (ogr-sym-2 : circle (not filled))
         OGRGeometry* poCenter = NULL;
         if (poCenter == NULL && poLS != NULL && poLS->getNumPoints() == 5)
         {
             poCenter = PDFGetCircleCenter(poLS);
         }
 
-        /* Recognize points as outputed by GDAL (ogr-sym-4: square (not filled)) */
+        // Recognize points as written by GDAL (ogr-sym-4: square (not filled))
         if (poCenter == NULL && poLS != NULL && (poLS->getNumPoints() == 4 || poLS->getNumPoints() == 5))
         {
             poCenter = PDFGetSquareCenter(poLS);
         }
 
-        /* Recognize points as outputed by GDAL (ogr-sym-6: triangle (not filled)) */
+        // Recognize points as written by GDAL (ogr-sym-6: triangle (not filled))
         if (poCenter == NULL && poLS != NULL && (poLS->getNumPoints() == 3 || poLS->getNumPoints() == 4))
         {
             poCenter = PDFGetTriangleCenter(poLS);
         }
 
-        /* Recognize points as outputed by GDAL (ogr-sym-8: star (not filled)) */
+        // Recognize points as written by GDAL (ogr-sym-8: star (not filled))
         if (poCenter == NULL && poLS != NULL && (poLS->getNumPoints() == 10 || poLS->getNumPoints() == 11))
         {
             poCenter = PDFGetStarCenter(poLS);
@@ -1272,7 +1278,7 @@ OGRGeometry* PDFDataset::BuildGeometry(std::vector<double>& oCoords,
             OGRLineString* poLS1 = (OGRLineString* )poMLS->getGeometryRef(0);
             OGRLineString* poLS2 = (OGRLineString* )poMLS->getGeometryRef(1);
 
-            /* Recognize points as outputed by GDAL (ogr-sym-0: cross (+) ) */
+            // Recognize points as written by GDAL (ogr-sym-0: cross (+) ).
             if (poLS1->getNumPoints() == 2 && poLS2->getNumPoints() == 2 &&
                 poLS1->getY(0) == poLS1->getY(1) &&
                 poLS2->getX(0) == poLS2->getX(1) &&
@@ -1282,7 +1288,7 @@ OGRGeometry* PDFDataset::BuildGeometry(std::vector<double>& oCoords,
             {
                 poCenter = new OGRPoint(poLS2->getX(0), poLS1->getY(0));
             }
-            /* Recognize points as outputed by GDAL (ogr-sym-1: diagcross (X) ) */
+            // Recognize points as written by GDAL (ogr-sym-1: diagcross (X) ).
             else if (poLS1->getNumPoints() == 2 && poLS2->getNumPoints() == 2 &&
                      poLS1->getX(0) == poLS2->getX(0) &&
                      poLS1->getY(0) == poLS2->getY(1) &&
@@ -1327,10 +1333,10 @@ OGRGeometry* PDFDataset::BuildGeometry(std::vector<double>& oCoords,
                         poLS &&
                         poLS->getNumPoints() == 5)
                     {
-                        /* Recognize points as outputed by GDAL (ogr-sym-3 : circle (filled)) */
+                        // Recognize points as written by GDAL (ogr-sym-3 : circle (filled))
                         poCenter = PDFGetCircleCenter(poLS);
 
-                        /* Recognize points as outputed by GDAL (ogr-sym-5: square (filled)) */
+                        // Recognize points as written by GDAL (ogr-sym-5: square (filled))
                         if (poCenter == NULL)
                             poCenter = PDFGetSquareCenter(poLS);
 
@@ -1346,14 +1352,14 @@ OGRGeometry* PDFDataset::BuildGeometry(std::vector<double>& oCoords,
                                                     (poLS->getY(0) + poLS->getY(2)) / 2);
                         }
                     }
-                    /* Recognize points as outputed by GDAL (ogr-sym-7: triangle (filled)) */
+                    // Recognize points as written by GDAL (ogr-sym-7: triangle (filled))
                     else if (nPolys == 0 &&
                              poLS &&
                              poLS->getNumPoints() == 4)
                     {
                         poCenter = PDFGetTriangleCenter(poLS);
                     }
-                    /* Recognize points as outputed by GDAL (ogr-sym-9: star (filled)) */
+                    // Recognize points as written by GDAL (ogr-sym-9: star (filled))
                     else if (nPolys == 0 &&
                              poLS &&
                              poLS->getNumPoints() == 11)
@@ -1480,7 +1486,7 @@ void PDFDataset::ExploreContents(GDALPDFObject* poObj,
             int bMatchQ = FALSE;
             while (pszAfterBDC[0] == ' ' || pszAfterBDC[0] == '\r' || pszAfterBDC[0] == '\n')
                 pszAfterBDC ++;
-            if (strncmp(pszAfterBDC, "0 0 m", 5) == 0)
+            if (STARTS_WITH(pszAfterBDC, "0 0 m"))
             {
                 const char* pszLastq = pszBDC;
                 while(pszLastq > pszStr && *pszLastq != 'q')
@@ -1603,12 +1609,12 @@ void PDFDataset::ExploreContentsNonStructured(GDALPDFObject* poContents,
                 OGRPDFLayer* poLayer = (OGRPDFLayer*) GetLayerByName(osSanitizedName.c_str());
                 if (poLayer == NULL)
                 {
-                    const char* pszWKT = GetProjectionRef();
+                    const char* l_pszWKT = GetProjectionRef();
                     OGRSpatialReference* poSRS = NULL;
-                    if (pszWKT && pszWKT[0] != '\0')
+                    if (l_pszWKT && l_pszWKT[0] != '\0')
                     {
                         poSRS = new OGRSpatialReference();
-                        poSRS->importFromWkt((char**) &pszWKT);
+                        poSRS->importFromWkt((char**) &l_pszWKT);
                     }
 
                     poLayer =
@@ -1676,4 +1682,4 @@ void PDFDataset::ExploreContentsNonStructured(GDALPDFObject* poContents,
     }
 }
 
-#endif /* defined(HAVE_POPPLER) || defined(HAVE_PODOFO) */
+#endif /* defined(HAVE_POPPLER) || defined(HAVE_PODOFO) || defined(HAVE_PDFIUM) */
diff --git a/frmts/pdf/pdfsdk_headers.h b/frmts/pdf/pdfsdk_headers.h
new file mode 100644
index 0000000..5905a0a
--- /dev/null
+++ b/frmts/pdf/pdfsdk_headers.h
@@ -0,0 +1,129 @@
+/******************************************************************************
+ *
+ * Project:  GDAL
+ * Purpose:  Includes PDF SDK headers
+ * Author:   Even Rouault <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+#ifndef PDFSDK_HEADERS_H
+#define PDFSDK_HEADERS_H
+
+/* We avoid to include cpl_port.h directly or indirectly */
+#if ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) && !defined(_MSC_VER))
+#pragma GCC system_header
+#endif
+
+#ifdef HAVE_POPPLER
+
+/* Horrible hack because there's a conflict between struct FlateDecode of */
+/* include/poppler/Stream.h and the FlateDecode() function of */
+/* pdfium/core/include/fpdfapi/fpdf_parser.h. */
+/* The part of Stream.h where struct FlateDecode is defined isn't needed */
+/* by GDAL, and is luckily protected by a #ifndef ENABLE_ZLIB section */
+#ifdef HAVE_PDFIUM
+#define ENABLE_ZLIB
+#endif /* HAVE_PDFIUM */
+
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable : 4244 ) /* conversion from 'const int' to 'Guchar', possible loss of data */
+#endif
+
+/* hack for PDF driver and poppler >= 0.15.0 that defines incompatible "typedef bool GBool" */
+/* in include/poppler/goo/gtypes.h with the one defined in cpl_port.h */
+#define CPL_GBOOL_DEFINED
+#define OGR_FEATURESTYLE_INCLUDE
+
+#include <goo/gtypes.h>
+#include <goo/GooList.h>
+
+/* begin of poppler xpdf includes */
+#include <poppler/Object.h>
+#include <poppler/Stream.h>
+
+#define private public /* Ugly! Page::pageObj is private but we need it... */
+#include <poppler/Page.h>
+#undef private
+
+#include <poppler/Dict.h>
+
+#define private public /* Ugly! Catalog::optContent is private but we need it... */
+#include <poppler/Catalog.h>
+#undef private
+
+#define private public  /* Ugly! PDFDoc::str is private but we need it... */
+#include <poppler/PDFDoc.h>
+#undef private
+
+#include <poppler/splash/SplashBitmap.h>
+#include <poppler/splash/Splash.h>
+#include <poppler/SplashOutputDev.h>
+#include <poppler/GlobalParams.h>
+#include <poppler/ErrorCodes.h>
+
+/* end of poppler xpdf includes */
+
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
+
+#endif /* HAVE_POPPLER */
+
+#ifdef HAVE_PODOFO
+
+/*
+ * Some Windows header defines a GetObject macro that
+ * shadows a GetObject() method in PoDoFo. This
+ * workaround is documented in the PoDoFo source.
+ */
+#ifdef GetObject
+#undef GetObject
+#endif
+
+#include "podofo.h"
+#endif // HAVE_PODOFO
+
+#ifdef HAVE_PDFIUM
+#include "cpl_multiproc.h"
+
+#if (!defined(CPL_MULTIPROC_WIN32) && !defined(CPL_MULTIPROC_PTHREAD)) || defined(CPL_MULTIPROC_STUB) || defined(CPL_MULTIPROC_NONE)
+#error PDF driver compiled with PDFium library requires working threads with mutex locking!
+#endif
+
+// Linux ignores timeout, Windows returns if not INFINITE
+#ifdef WIN32
+#define  PDFIUM_MUTEX_TIMEOUT     INFINITE
+#else
+#define  PDFIUM_MUTEX_TIMEOUT     0.0f
+#endif
+
+#include <cstring>
+//#include <fpdfsdk/include/fsdk_define.h>
+#include <fpdfview.h>
+#include <core/include/fpdfapi/fpdf_page.h>
+#include <core/include/fpdfapi/fpdf_objects.h>
+#include "fpdfsdk/include/fsdk_rendercontext.h"
+#endif // HAVE_PDFIUM
+
+#endif
diff --git a/frmts/pdf/pdfwritabledataset.cpp b/frmts/pdf/pdfwritabledataset.cpp
index 2471d58..d3ef602 100644
--- a/frmts/pdf/pdfwritabledataset.cpp
+++ b/frmts/pdf/pdfwritabledataset.cpp
@@ -93,7 +93,7 @@ OGRLayer *
 PDFWritableVectorDataset::ICreateLayer( const char * pszLayerName,
                                         OGRSpatialReference *poSRS,
                                         OGRwkbGeometryType eType,
-                                        CPL_UNUSED char ** papszOptions )
+                                        char ** )
 {
 /* -------------------------------------------------------------------- */
 /*      Create the layer object.                                        */
@@ -253,12 +253,12 @@ OGRErr PDFWritableVectorDataset::SyncToDisk()
     if (dfRatio < 1)
     {
         nWidth = 1024;
-        nHeight = nWidth * dfRatio;
+        nHeight = static_cast<int>(nWidth * dfRatio);
     }
     else
     {
         nHeight = 1024;
-        nWidth = nHeight / dfRatio;
+        nWidth = static_cast<int>(nHeight / dfRatio);
     }
 
     GDALDataset* poSrcDS = MEMDataset::Create( "MEM:::", nWidth, nHeight, 0, GDT_Byte, NULL );
@@ -293,7 +293,7 @@ OGRErr PDFWritableVectorDataset::SyncToDisk()
                       bWriteOGRAttributes);
 
     int iObj = 0;
-    
+
     char** papszLayerNames = CSLTokenizeString2(pszOGRDisplayLayerNames,",",0);
 
     for(int i=0;i<nLayers;i++)
diff --git a/frmts/pds/frmt_isis2.html b/frmts/pds/frmt_isis2.html
index 3d7a392..402b551 100644
--- a/frmts/pds/frmt_isis2.html
+++ b/frmts/pds/frmt_isis2.html
@@ -34,8 +34,8 @@ other metadata is captured.<p>
 
 <ul>
 
-<li><p><b>LABELING_METHOD=ATTACHED/DETACHED</b>: Determines whether the 
-header labelling should be in the same file as the imagery (the default - ATTACHED)
+<li><p><b>LABELING_METHOD=ATTACHED/DETACHED</b>: Determines whether the
+header labeling should be in the same file as the imagery (the default - ATTACHED)
 or in a separate file (DETACHED).</p></li>
 <li><p><b>IMAGE_EXTENSION=<i>extension</i></b>: Set the extension used
 for detached image files, defaults to "cub".  Only used if LABELING_METHOD=DETACHED.</p></li>
diff --git a/frmts/pds/frmt_isis3.html b/frmts/pds/frmt_isis3.html
index e842aae..95c028b 100644
--- a/frmts/pds/frmt_isis3.html
+++ b/frmts/pds/frmt_isis3.html
@@ -8,7 +8,7 @@
 <h1>ISIS3 -- USGS Astrogeology ISIS Cube (Version 3)</h1>
 
 ISIS3 is a format used by the USGS Planetary Cartography group
-to store and distribute planetary imagery data.  GDAL provides 
+to store and distribute planetary imagery data.  GDAL provides
 read-only access to ISIS3 formatted imagery data.<p>
 
 ISIS3 files often have the extension .cub, sometimes with an associated
@@ -24,7 +24,6 @@ Geological Survey.<p>
 
 ISIS3 is part of a family of related formats including PDS and ISIS2.<p>
 
-
 <h2>See Also:</h2>
 
 <ul>
diff --git a/frmts/pds/frmt_pds.html b/frmts/pds/frmt_pds.html
index 16f4b86..8eb7be7 100644
--- a/frmts/pds/frmt_pds.html
+++ b/frmts/pds/frmt_pds.html
@@ -7,7 +7,7 @@
 
 <h1>PDS -- Planetary Data System</h1>
 
-PDS is a format used primarily by NASA to store and distribute 
+PDS is a format used primarily by NASA to store and distribute
 solar, lunar and planetary imagery data.  GDAL provides read-only
 access to PDS formatted imagery data.<p>
 
@@ -24,14 +24,14 @@ Geological Survey.<p>
 
 <hr>
 
-Due to ambiguities in the PDS specification, the georeferencing of 
+Due to ambiguities in the PDS specification, the georeferencing of
 some products is subtly or grossly incorrect.  There are configuration
 variables which may be set for these products to correct the interpretation
-of the georeferencing.  Some details are available in 
+of the georeferencing.  Some details are available in
 <a href="http://trac.osgeo.org/gdal/ticket/3940">ticket #3940</a>.<p>
 
-For example, the MOLA labels currently contain a one pixel offset. Once 
-<a href="http://trac.osgeo.org/gdal/ticket/5941">ticket #5941</a> is applied (should be available post 1.11.3), 
+For example, the MOLA labels currently contain a one pixel offset. Once
+<a href="http://trac.osgeo.org/gdal/ticket/5941">ticket #5941</a> is applied (should be available post 1.11.3),
 which corrects the PDS offset defaults, here is how you can correctly read in
 a MOLA label using the --config options in the PDS reader.
 <p>
diff --git a/frmts/pds/isis2dataset.cpp b/frmts/pds/isis2dataset.cpp
index 23fc03c..c5cc84c 100644
--- a/frmts/pds/isis2dataset.cpp
+++ b/frmts/pds/isis2dataset.cpp
@@ -1,21 +1,21 @@
 /******************************************************************************
- * $Id: isis2dataset.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: isis2dataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  ISIS Version 2 Driver
  * Purpose:  Implementation of ISIS2Dataset
  * Author:   Trent Hare (thare at usgs.gov),
  *           Robert Soricone (rsoricone at usgs.gov)
- *           Ludovic Mercier (ludovic.mercier at gmail.com) 
+ *           Ludovic Mercier (ludovic.mercier at gmail.com)
  *           Frank Warmerdam (warmerdam at pobox.com)
  *
- * NOTE: Original code authored by Trent and Robert and placed in the public 
- * domain as per US government policy.  I have (within my rights) appropriated 
- * it and placed it under the following license.  This is not intended to 
- * diminish Trent and Roberts contribution. 
+ * NOTE: Original code authored by Trent and Robert and placed in the public
+ * domain as per US government policy.  I have (within my rights) appropriated
+ * it and placed it under the following license.  This is not intended to
+ * diminish Trent and Roberts contribution.
  ******************************************************************************
  * Copyright (c) 2006, Frank Warmerdam <warmerdam at pobox.com>
  * Copyright (c) 2008-2011, Even Rouault <even dot rouault at mines-paris dot org>
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * to deal in the Software without restriction, including without limitation
@@ -35,26 +35,19 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#define NULL1 0
-#define NULL2 -32768
-#define NULL3 -3.4028226550889044521e+38
-
-#ifndef PI
-#  define PI 3.1415926535897932384626433832795
-#endif
+static const int NULL1 = 0;
+static const int NULL2 = -32768;
+static const double NULL3 = -3.4028226550889044521e+38;
 
-#define RECORD_SIZE 512
+static const int RECORD_SIZE = 512;
 
-#include "rawdataset.h"
-#include "ogr_spatialref.h"
-#include "cpl_string.h" 
+#include "cpl_string.h"
+#include "gdal_frmts.h"
 #include "nasakeywordhandler.h"
+#include "ogr_spatialref.h"
+#include "rawdataset.h"
 
-CPL_CVSID("$Id: isis2dataset.cpp 27942 2014-11-11 00:57:41Z rouault $");
-
-CPL_C_START
-void	GDALRegister_ISIS2(void);
-CPL_C_END
+CPL_CVSID("$Id: isis2dataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -68,10 +61,10 @@ class ISIS2Dataset : public RawDataset
     CPLString    osExternalCube;
 
     NASAKeywordHandler  oKeywords;
-  
+
     int         bGotTransform;
     double      adfGeoTransform[6];
-  
+
     CPLString   osProjection;
 
     int parse_label(const char *file, char *keyword, char *value);
@@ -81,10 +74,10 @@ class ISIS2Dataset : public RawDataset
 
     void        CleanString( CPLString &osInput );
 
-    const char *GetKeyword( const char *pszPath, 
+    const char *GetKeyword( const char *pszPath,
                             const char *pszDefault = "");
-    const char *GetKeywordSub( const char *pszPath, 
-                               int iSubscript, 
+    const char *GetKeywordSub( const char *pszPath,
+                               int iSubscript,
                                const char *pszDefault = "");
 
 public:
@@ -93,7 +86,7 @@ public:
 
     virtual CPLErr GetGeoTransform( double * padfTransform );
     virtual const char *GetProjectionRef(void);
-  
+
     virtual char **GetFileList();
 
     static int          Identify( GDALOpenInfo * );
@@ -119,10 +112,10 @@ public:
 /*                            ISIS2Dataset()                            */
 /************************************************************************/
 
-ISIS2Dataset::ISIS2Dataset()
+ISIS2Dataset::ISIS2Dataset() :
+    fpImage(NULL),
+    bGotTransform(FALSE)
 {
-    fpImage = NULL;
-    bGotTransform = FALSE;
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
@@ -150,9 +143,7 @@ ISIS2Dataset::~ISIS2Dataset()
 char **ISIS2Dataset::GetFileList()
 
 {
-    char **papszFileList = NULL;
-
-    papszFileList = GDALPamDataset::GetFileList();
+    char **papszFileList = GDALPamDataset::GetFileList();
 
     if( strlen(osExternalCube) > 0 )
         papszFileList = CSLAddString( papszFileList, osExternalCube );
@@ -169,8 +160,8 @@ const char *ISIS2Dataset::GetProjectionRef()
 {
     if( strlen(osProjection) > 0 )
         return osProjection;
-    else
-        return GDALPamDataset::GetProjectionRef();
+
+    return GDALPamDataset::GetProjectionRef();
 }
 
 /************************************************************************/
@@ -185,10 +176,8 @@ CPLErr ISIS2Dataset::GetGeoTransform( double * padfTransform )
         memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
         return CE_None;
     }
-    else
-    {
-        return GDALPamDataset::GetGeoTransform( padfTransform );
-    }
+
+    return GDALPamDataset::GetGeoTransform( padfTransform );
 }
 
 /************************************************************************/
@@ -203,8 +192,8 @@ int ISIS2Dataset::Identify( GDALOpenInfo * poOpenInfo )
 
     if( strstr((const char *)poOpenInfo->pabyHeader,"^QUBE") == NULL )
         return FALSE;
-    else
-        return TRUE;
+
+    return TRUE;
 }
 
 /************************************************************************/
@@ -227,9 +216,7 @@ GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
     if( fpQube == NULL )
         return NULL;
 
-    ISIS2Dataset 	*poDS;
-
-    poDS = new ISIS2Dataset();
+    ISIS2Dataset *poDS = new ISIS2Dataset();
 
     if( ! poDS->oKeywords.Ingest( fpQube, 0 ) )
     {
@@ -237,11 +224,11 @@ GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
         delete poDS;
         return NULL;
     }
-    
+
     VSIFCloseL( fpQube );
 
 /* -------------------------------------------------------------------- */
-/*	We assume the user is pointing to the label (ie. .lab) file.  	*/
+/*      We assume the user is pointing to the label (i.e. .lab) file.   */
 /* -------------------------------------------------------------------- */
     // QUBE can be inline or detached and point to an image name
     // ^QUBE = 76
@@ -254,27 +241,27 @@ GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
     CPLString osTargetFile = poOpenInfo->pszFilename;
 
     if( pszQube[0] == '"' )
-    { 
-        CPLString osTPath = CPLGetPath(poOpenInfo->pszFilename); 
+    {
+        const CPLString osTPath = CPLGetPath(poOpenInfo->pszFilename);
         CPLString osFilename = pszQube;
-        poDS->CleanString( osFilename ); 
-        osTargetFile = CPLFormCIFilename( osTPath, osFilename, NULL ); 
+        poDS->CleanString( osFilename );
+        osTargetFile = CPLFormCIFilename( osTPath, osFilename, NULL );
         poDS->osExternalCube = osTargetFile;
     }
-    else if( pszQube[0] == '(' ) 
-    { 
-        CPLString osTPath = CPLGetPath(poOpenInfo->pszFilename); 
-        CPLString osFilename = poDS->GetKeywordSub("^QUBE",1,""); 
-        poDS->CleanString( osFilename ); 
-        osTargetFile = CPLFormCIFilename( osTPath, osFilename, NULL ); 
+    else if( pszQube[0] == '(' )
+    {
+        const CPLString osTPath = CPLGetPath(poOpenInfo->pszFilename);
+        CPLString osFilename = poDS->GetKeywordSub("^QUBE",1,"");
+        poDS->CleanString( osFilename );
+        osTargetFile = CPLFormCIFilename( osTPath, osFilename, NULL );
         poDS->osExternalCube = osTargetFile;
 
         nQube = atoi(poDS->GetKeywordSub("^QUBE",2,"1"));
         if( strstr(poDS->GetKeywordSub("^QUBE",2,"1"),"<BYTES>") != NULL )
             bByteLocation = true;
-    } 
-    else 
-    { 
+    }
+    else
+    {
         nQube = atoi(pszQube);
         if( strstr(pszQube,"<BYTES>") != NULL )
             bByteLocation = true;
@@ -284,66 +271,33 @@ GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Check if file an ISIS2 header file?  Read a few lines of text   */
 /*      searching for something starting with nrows or ncols.           */
 /* -------------------------------------------------------------------- */
-    GDALDataType eDataType = GDT_Byte;
-    OGRSpatialReference oSRS;
-
-    //image parameters
-    int	nRows, nCols, nBands = 1;
-    GUIntBig nSkipBytes = 0;
-    int itype;
-    int  s_ix, s_iy, s_iz; // check SUFFIX_ITEMS params.
-    int record_bytes;
-    int	bNoDataSet = FALSE;
-    char chByteOrder = 'M';  //default to MSB
- 
-    //Georef parameters
-    double dfULXMap=0.5;
-    double dfULYMap = 0.5;
-    double dfXDim = 1.0;
-    double dfYDim = 1.0;
-    double dfNoData = 0.0;
-    double xulcenter = 0.0;
-    double yulcenter = 0.0;
-
-    //projection parameters
-    int	bProjectionSet = TRUE;
-    double semi_major = 0.0;
-    double semi_minor = 0.0;
-    double iflattening = 0.0;
-    double center_lat = 0.0;
-    double center_lon = 0.0;
-    double first_std_parallel = 0.0;
-    double second_std_parallel = 0.0;
-    VSILFILE	*fp;
 
     /* -------------------------------------------------------------------- */
     /*      Checks to see if this is valid ISIS2 cube                       */
     /*      SUFFIX_ITEM tag in .cub file should be (0,0,0); no side-planes  */
     /* -------------------------------------------------------------------- */
-    s_ix = atoi(poDS->GetKeywordSub( "QUBE.SUFFIX_ITEMS", 1 ));
-    s_iy = atoi(poDS->GetKeywordSub( "QUBE.SUFFIX_ITEMS", 2 ));
-    s_iz = atoi(poDS->GetKeywordSub( "QUBE.SUFFIX_ITEMS", 3 ));
-     
-    if( s_ix != 0 || s_iy != 0 || s_iz != 0 ) 
+    const int s_ix = atoi(poDS->GetKeywordSub( "QUBE.SUFFIX_ITEMS", 1 ));
+    const int s_iy = atoi(poDS->GetKeywordSub( "QUBE.SUFFIX_ITEMS", 2 ));
+    const int s_iz = atoi(poDS->GetKeywordSub( "QUBE.SUFFIX_ITEMS", 3 ));
+
+    if( s_ix != 0 || s_iy != 0 || s_iz != 0 )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "*** ISIS 2 cube file has invalid SUFFIX_ITEMS parameters:\n"
                   "*** gdal isis2 driver requires (0, 0, 0), thus no sideplanes or backplanes\n"
                   "found: (%i, %i, %i)\n\n", s_ix, s_iy, s_iz );
         delete poDS;
         return NULL;
-    } 
+    }
 
     /**************** end SUFFIX_ITEM check ***********************/
-    
-    
+
     /***********   Grab layout type (BSQ, BIP, BIL) ************/
     //  AXIS_NAME = (SAMPLE,LINE,BAND)
     /***********************************************************/
-    const char *value;
 
     char szLayout[10] = "BSQ"; //default to band seq.
-    value = poDS->GetKeyword( "QUBE.AXIS_NAME", "" );
+    const char *value = poDS->GetKeyword( "QUBE.AXIS_NAME", "" );
     if (EQUAL(value,"(SAMPLE,LINE,BAND)") )
         strcpy(szLayout,"BSQ");
     else if (EQUAL(value,"(BAND,LINE,SAMPLE)") )
@@ -351,42 +305,48 @@ GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
     else if (EQUAL(value,"(SAMPLE,BAND,LINE)") || EQUAL(value,"") )
         strcpy(szLayout,"BSQ");
     else {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "%s layout not supported. Abort\n\n", value);
         delete poDS;
         return NULL;
     }
 
     /***********   Grab samples lines band ************/
-    nCols = atoi(poDS->GetKeywordSub("QUBE.CORE_ITEMS",1));
-    nRows = atoi(poDS->GetKeywordSub("QUBE.CORE_ITEMS",2));
-    nBands = atoi(poDS->GetKeywordSub("QUBE.CORE_ITEMS",3));
-    
+    const int nCols = atoi(poDS->GetKeywordSub("QUBE.CORE_ITEMS",1));
+    const int nRows = atoi(poDS->GetKeywordSub("QUBE.CORE_ITEMS",2));
+    const int nBands = atoi(poDS->GetKeywordSub("QUBE.CORE_ITEMS",3));
+
     /***********   Grab Qube record bytes  **********/
-    record_bytes = atoi(poDS->GetKeyword("RECORD_BYTES"));
+    const int record_bytes = atoi(poDS->GetKeyword("RECORD_BYTES"));
 
+    GUIntBig nSkipBytes = 0;
     if (nQube > 0 && bByteLocation )
         nSkipBytes = (nQube - 1);
     else if( nQube > 0 )
-        nSkipBytes = (nQube - 1) * record_bytes;     
+        nSkipBytes = (nQube - 1) * record_bytes;
     else
-        nSkipBytes = 0;     
-     
+        nSkipBytes = 0;
+
     /***********   Grab samples lines band ************/
+    char chByteOrder = 'M';  //default to MSB
     CPLString osCoreItemType = poDS->GetKeyword( "QUBE.CORE_ITEM_TYPE" );
-    if( (EQUAL(osCoreItemType,"PC_INTEGER")) || 
-        (EQUAL(osCoreItemType,"PC_UNSIGNED_INTEGER")) || 
+    if( (EQUAL(osCoreItemType,"PC_INTEGER")) ||
+        (EQUAL(osCoreItemType,"PC_UNSIGNED_INTEGER")) ||
         (EQUAL(osCoreItemType,"PC_REAL")) ) {
         chByteOrder = 'I';
     }
-    
+
     /********   Grab format type - isis2 only supports 8,16,32 *******/
-    itype = atoi(poDS->GetKeyword("QUBE.CORE_ITEM_BYTES",""));
+    GDALDataType eDataType = GDT_Byte;
+    bool bNoDataSet = false;
+    double dfNoData = 0.0;
+
+    int itype = atoi(poDS->GetKeyword("QUBE.CORE_ITEM_BYTES",""));
     switch(itype) {
       case 1 :
         eDataType = GDT_Byte;
         dfNoData = NULL1;
-        bNoDataSet = TRUE;
+        bNoDataSet = true;
         break;
       case 2 :
         if( strstr(osCoreItemType,"UNSIGNED") != NULL )
@@ -399,99 +359,112 @@ GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
             dfNoData = NULL2;
             eDataType = GDT_Int16;
         }
-        bNoDataSet = TRUE;
+        bNoDataSet = true;
         break;
       case 4 :
         eDataType = GDT_Float32;
         dfNoData = NULL3;
-        bNoDataSet = TRUE;
+        bNoDataSet = true;
         break;
       case 8 :
         eDataType = GDT_Float64;
         dfNoData = NULL3;
-        bNoDataSet = TRUE;
+        bNoDataSet = true;
         break;
       default :
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Itype of %d is not supported in ISIS 2.",
-                  itype); 
+                  itype);
         delete poDS;
         return NULL;
     }
 
     /***********   Grab Cellsize ************/
+    double dfXDim = 1.0;
+    double dfYDim = 1.0;
+
     value = poDS->GetKeyword("QUBE.IMAGE_MAP_PROJECTION.MAP_SCALE");
     if (strlen(value) > 0 ) {
-        dfXDim = (float) CPLAtof(value) * 1000.0; /* convert from km to m */
-        dfYDim = (float) CPLAtof(value) * 1000.0 * -1;
+        // Convert km to m
+        dfXDim = static_cast<float>( CPLAtof(value) * 1000.0 );
+        dfYDim = static_cast<float>( CPLAtof(value) * 1000.0 * -1 );
     }
-    
+
     /***********   Grab LINE_PROJECTION_OFFSET ************/
+    double dfULYMap = 0.5;
+    double yulcenter = 0.0;
+
     value = poDS->GetKeyword("QUBE.IMAGE_MAP_PROJECTION.LINE_PROJECTION_OFFSET");
     if (strlen(value) > 0) {
-        yulcenter = (float) CPLAtof(value);
+        yulcenter = static_cast<float>( CPLAtof(value) );
         yulcenter = ((yulcenter) * dfYDim);
         dfULYMap = yulcenter - (dfYDim/2);
     }
-     
+
     /***********   Grab SAMPLE_PROJECTION_OFFSET ************/
+    double dfULXMap = 0.5;
+    double xulcenter = 0.0;
+
     value = poDS->GetKeyword("QUBE.IMAGE_MAP_PROJECTION.SAMPLE_PROJECTION_OFFSET");
     if( strlen(value) > 0 ) {
-        xulcenter = (float) CPLAtof(value);
+        xulcenter= static_cast<float>( CPLAtof(value) );
         xulcenter = ((xulcenter) * dfXDim);
         dfULXMap = xulcenter - (dfXDim/2);
     }
-     
+
     /***********  Grab TARGET_NAME  ************/
     /**** This is the planets name i.e. MARS ***/
     CPLString target_name = poDS->GetKeyword("QUBE.TARGET_NAME");
-     
+
     /***********   Grab MAP_PROJECTION_TYPE ************/
-    CPLString map_proj_name = 
+    CPLString map_proj_name =
         poDS->GetKeyword( "QUBE.IMAGE_MAP_PROJECTION.MAP_PROJECTION_TYPE");
     poDS->CleanString( map_proj_name );
 
     /***********   Grab SEMI-MAJOR ************/
-    semi_major = 
+    const double semi_major =
         CPLAtof(poDS->GetKeyword( "QUBE.IMAGE_MAP_PROJECTION.A_AXIS_RADIUS")) * 1000.0;
 
     /***********   Grab semi-minor ************/
-    semi_minor = 
+    const double semi_minor =
         CPLAtof(poDS->GetKeyword( "QUBE.IMAGE_MAP_PROJECTION.C_AXIS_RADIUS")) * 1000.0;
 
     /***********   Grab CENTER_LAT ************/
-    center_lat = 
+    const double center_lat =
         CPLAtof(poDS->GetKeyword( "QUBE.IMAGE_MAP_PROJECTION.CENTER_LATITUDE"));
 
     /***********   Grab CENTER_LON ************/
-    center_lon = 
+    const double center_lon =
         CPLAtof(poDS->GetKeyword( "QUBE.IMAGE_MAP_PROJECTION.CENTER_LONGITUDE"));
 
     /***********   Grab 1st std parallel ************/
-    first_std_parallel = 
+    const double first_std_parallel =
         CPLAtof(poDS->GetKeyword( "QUBE.IMAGE_MAP_PROJECTION.FIRST_STANDARD_PARALLEL"));
 
     /***********   Grab 2nd std parallel ************/
-    second_std_parallel = 
+    const double second_std_parallel =
         CPLAtof(poDS->GetKeyword( "QUBE.IMAGE_MAP_PROJECTION.SECOND_STANDARD_PARALLEL"));
-     
+
     /*** grab  PROJECTION_LATITUDE_TYPE = "PLANETOCENTRIC" ****/
     // Need to further study how ocentric/ographic will effect the gdal library.
     // So far we will use this fact to define a sphere or ellipse for some projections
     // Frank - may need to talk this over
-    char bIsGeographic = TRUE;
+    bool bIsGeographic = true;
     value = poDS->GetKeyword("CUBE.IMAGE_MAP_PROJECTION.PROJECTION_LATITUDE_TYPE");
     if (EQUAL( value, "\"PLANETOCENTRIC\"" ))
-        bIsGeographic = FALSE; 
-     
+        bIsGeographic = false;
+
     CPLDebug("ISIS2","using projection %s", map_proj_name.c_str() );
 
+    OGRSpatialReference oSRS;
+    bool bProjectionSet = true;
+
     //Set oSRS projection and parameters
     if ((EQUAL( map_proj_name, "EQUIRECTANGULAR_CYLINDRICAL" )) ||
         (EQUAL( map_proj_name, "EQUIRECTANGULAR" )) ||
         (EQUAL( map_proj_name, "SIMPLE_CYLINDRICAL" )) ) {
         oSRS.OGRSpatialReference::SetEquirectangular2 ( 0.0, center_lon, center_lat, 0, 0 );
-    } else if (EQUAL( map_proj_name, "ORTHOGRAPHIC" )) { 
+    } else if (EQUAL( map_proj_name, "ORTHOGRAPHIC" )) {
         oSRS.OGRSpatialReference::SetOrthographic ( center_lat, center_lon, 0, 0 );
     } else if ((EQUAL( map_proj_name, "SINUSOIDAL" )) ||
                (EQUAL( map_proj_name, "SINUSOIDAL_EQUAL-AREA" ))) {
@@ -506,97 +479,100 @@ GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
         oSRS.OGRSpatialReference::SetLCC ( first_std_parallel, second_std_parallel, center_lat, center_lon, 0, 0 );
     } else if (EQUAL( map_proj_name, "") ) {
         /* no projection */
-        bProjectionSet = FALSE;
+        bProjectionSet = false;
     } else {
         CPLDebug( "ISIS2",
                   "Dataset projection %s is not supported. Continuing...",
                   map_proj_name.c_str() );
-        bProjectionSet = FALSE;
+        bProjectionSet = false;
     }
 
     if (bProjectionSet) {
         //Create projection name, i.e. MERCATOR MARS and set as ProjCS keyword
-        CPLString proj_target_name = map_proj_name + " " + target_name;
+        const CPLString proj_target_name = map_proj_name + " " + target_name;
         oSRS.SetProjCS(proj_target_name); //set ProjCS keyword
-     
+
         //The geographic/geocentric name will be the same basic name as the body name
         //'GCS' = Geographic/Geocentric Coordinate System
-        CPLString geog_name = "GCS_" + target_name;
-        
+        const CPLString geog_name = "GCS_" + target_name;
+
         //The datum and sphere names will be the same basic name aas the planet
-        CPLString datum_name = "D_" + target_name;
-        CPLString sphere_name = target_name; // + "_IAU_IAG");  //Might not be IAU defined so don't add
-          
+        const CPLString datum_name = "D_" + target_name;
+        // Might not be IAU defined so don't add.
+        CPLString sphere_name = target_name; // + "_IAU_IAG");
+
         //calculate inverse flattening from major and minor axis: 1/f = a/(a-b)
-        if ((semi_major - semi_minor) < 0.0000001) 
+        double iflattening = 0.0;
+        if ((semi_major - semi_minor) < 0.0000001)
             iflattening = 0;
         else
             iflattening = semi_major / (semi_major - semi_minor);
-     
+
         //Set the body size but take into consideration which proj is being used to help w/ proj4 compatibility
         //The use of a Sphere, polar radius or ellipse here is based on how ISIS does it internally
-        if ( ( (EQUAL( map_proj_name, "STEREOGRAPHIC" ) && (fabs(center_lat) == 90)) ) || 
-             (EQUAL( map_proj_name, "POLAR_STEREOGRAPHIC" )))  
+        if ( ( (EQUAL( map_proj_name, "STEREOGRAPHIC" ) && (fabs(center_lat) == 90)) ) ||
+             (EQUAL( map_proj_name, "POLAR_STEREOGRAPHIC" )))
         {
-            if (bIsGeographic) { 
+            if (bIsGeographic) {
                 //Geograpraphic, so set an ellipse
                 oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                                semi_major, iflattening, 
+                                semi_major, iflattening,
                                 "Reference_Meridian", 0.0 );
             } else {
-                //Geocentric, so force a sphere using the semi-minor axis. I hope... 
+                //Geocentric, so force a sphere using the semi-minor axis. I hope...
                 sphere_name += "_polarRadius";
                 oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                                semi_minor, 0.0, 
+                                semi_minor, 0.0,
                                 "Reference_Meridian", 0.0 );
             }
         }
-        else if ( (EQUAL( map_proj_name, "SIMPLE_CYLINDRICAL" )) || 
+        else if ( (EQUAL( map_proj_name, "SIMPLE_CYLINDRICAL" )) ||
                   (EQUAL( map_proj_name, "ORTHOGRAPHIC" )) ||
                   (EQUAL( map_proj_name, "STEREOGRAPHIC" )) ||
                   (EQUAL( map_proj_name, "SINUSOIDAL_EQUAL-AREA" )) ||
                   (EQUAL( map_proj_name, "SINUSOIDAL" ))  ) {
-            //isis uses the sphereical equation for these projections so force a sphere
+            // ISIS uses the spherical equation for these projections so force
+            // a sphere.
             oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                            semi_major, 0.0, 
+                            semi_major, 0.0,
                             "Reference_Meridian", 0.0 );
-        } 
-        else if  ((EQUAL( map_proj_name, "EQUIRECTANGULAR_CYLINDRICAL" )) || 
+        }
+        else if  ((EQUAL( map_proj_name, "EQUIRECTANGULAR_CYLINDRICAL" )) ||
                   (EQUAL( map_proj_name, "EQUIRECTANGULAR" )) ) {
-            //Calculate localRadius using ISIS3 simple elliptical method 
+            //Calculate localRadius using ISIS3 simple elliptical method
             //  not the more standard Radius of Curvature method
             //PI = 4 * atan(1);
-            double radLat, localRadius;
             if (center_lon == 0) { //No need to calculate local radius
                 oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                                semi_major, 0.0, 
+                                semi_major, 0.0,
                                 "Reference_Meridian", 0.0 );
-            } else {  
-                radLat = center_lat * PI / 180;  // in radians
-                localRadius = semi_major * semi_minor / sqrt(pow(semi_minor*cos(radLat),2)
-                                                             + pow(semi_major*sin(radLat),2) );
+            } else {
+                const double radLat = center_lat * M_PI / 180;  // in radians
+                const double localRadius
+                    = semi_major * semi_minor
+                    / sqrt(pow(semi_minor*cos(radLat),2)
+                           + pow(semi_major*sin(radLat),2) );
                 sphere_name += "_localRadius";
                 oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                                localRadius, 0.0, 
+                                localRadius, 0.0,
                                 "Reference_Meridian", 0.0 );
                 CPLDebug( "ISIS2", "local radius: %f", localRadius);
             }
-        } 
-        else { 
+        }
+        else {
             //All other projections: Mercator, Transverse Mercator, Lambert Conformal, etc.
             //Geographic, so set an ellipse
             if (bIsGeographic) {
                 oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                                semi_major, iflattening, 
+                                semi_major, iflattening,
                                 "Reference_Meridian", 0.0 );
-            } else { 
-                //Geocentric, so force a sphere. I hope... 
+            } else {
+                //Geocentric, so force a sphere. I hope...
                 oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                                semi_major, 0.0, 
+                                semi_major, 0.0,
                                 "Reference_Meridian", 0.0 );
             }
         }
-        
 
         // translate back into a projection string.
         char *pszResult = NULL;
@@ -607,7 +583,7 @@ GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
 
 /* END ISIS2 Label Read */
 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-    
+
 /* -------------------------------------------------------------------- */
 /*      Did we get the required keywords?  If not we return with        */
 /*      this never having been considered to be a match. This isn't     */
@@ -628,7 +604,7 @@ GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Open target binary file.                                        */
 /* -------------------------------------------------------------------- */
-    
+
     if( poOpenInfo->eAccess == GA_ReadOnly )
         poDS->fpImage = VSIFOpenL( osTargetFile, "rb" );
     else
@@ -636,8 +612,8 @@ GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
 
     if( poDS->fpImage == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Failed to open %s with write permission.\n%s", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to open %s with write permission.\n%s",
                   osTargetFile.c_str(), VSIStrerror( errno ) );
         delete poDS;
         return NULL;
@@ -648,9 +624,9 @@ GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Compute the line offset.                                        */
 /* -------------------------------------------------------------------- */
-    int     nItemSize = GDALGetDataTypeSize(eDataType)/8;
-    int		nLineOffset, nPixelOffset, nBandOffset;
-    
+    int nItemSize = GDALGetDataTypeSize(eDataType)/8;
+    int nLineOffset, nPixelOffset, nBandOffset;
+
     if( EQUAL(szLayout,"BIP") )
     {
         nPixelOffset = nItemSize * nBands;
@@ -669,26 +645,22 @@ GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
         nLineOffset = nItemSize * nBands * nCols;
         nBandOffset = nItemSize * nCols;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    int i;
-
     poDS->nBands = nBands;;
-    for( i = 0; i < poDS->nBands; i++ )
+    for( int i = 0; i < poDS->nBands; i++ )
     {
-        RawRasterBand	*poBand;
-
-        poBand = 
+        RawRasterBand *poBand =
             new RawRasterBand( poDS, i+1, poDS->fpImage,
-                               nSkipBytes + nBandOffset * i, 
+                               nSkipBytes + nBandOffset * i,
                                nPixelOffset, nLineOffset, eDataType,
-#ifdef CPL_LSB                               
+#ifdef CPL_LSB
                                chByteOrder == 'I' || chByteOrder == 'L',
 #else
                                chByteOrder == 'M',
-#endif        
+#endif
                                TRUE );
 
         if( bNoDataSet )
@@ -697,35 +669,31 @@ GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->SetBand( i+1, poBand );
 
         // Set offset/scale values at the PAM level.
-        poBand->SetOffset( 
+        poBand->SetOffset(
             CPLAtofM(poDS->GetKeyword("QUBE.CORE_BASE","0.0")));
-        poBand->SetScale( 
+        poBand->SetScale(
             CPLAtofM(poDS->GetKeyword("QUBE.CORE_MULTIPLIER","1.0")));
     }
 
 /* -------------------------------------------------------------------- */
 /*      Check for a .prj file. For isis2 I would like to keep this in   */
 /* -------------------------------------------------------------------- */
-    CPLString osPath, osName;
-
-    osPath = CPLGetPath( poOpenInfo->pszFilename );
-    osName = CPLGetBasename(poOpenInfo->pszFilename);
+    const CPLString osPath = CPLGetPath( poOpenInfo->pszFilename );
+    const CPLString osName = CPLGetBasename(poOpenInfo->pszFilename);
     const char  *pszPrjFile = CPLFormCIFilename( osPath, osName, "prj" );
 
-    fp = VSIFOpenL( pszPrjFile, "r" );
+    VSILFILE *fp = VSIFOpenL( pszPrjFile, "r" );
     if( fp != NULL )
     {
-        char	**papszLines;
-        OGRSpatialReference oSRS;
-
         VSIFCloseL( fp );
-        
-        papszLines = CSLLoad( pszPrjFile );
 
-        if( oSRS.importFromESRI( papszLines ) == OGRERR_NONE )
+        char **papszLines = CSLLoad( pszPrjFile );
+
+        OGRSpatialReference oSRS2;
+        if( oSRS2.importFromESRI( papszLines ) == OGRERR_NONE )
         {
             char *pszResult = NULL;
-            oSRS.exportToWkt( &pszResult );
+            oSRS2.exportToWkt( &pszResult );
             poDS->osProjection = pszResult;
             CPLFree( pszResult );
         }
@@ -733,8 +701,7 @@ GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
         CSLDestroy( papszLines );
     }
 
-    
-    if( dfULYMap != 0.5 || dfULYMap != 0.5 || dfXDim != 1.0 || dfYDim != 1.0 )
+    if( dfULXMap != 0.5 || dfULYMap != 0.5 || dfXDim != 1.0 || dfYDim != 1.0 )
     {
         poDS->bGotTransform = TRUE;
         poDS->adfGeoTransform[0] = dfULXMap;
@@ -744,22 +711,22 @@ GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->adfGeoTransform[4] = 0.0;
         poDS->adfGeoTransform[5] = dfYDim;
     }
-    
+
     if( !poDS->bGotTransform )
-        poDS->bGotTransform = 
-            GDALReadWorldFile( poOpenInfo->pszFilename, "cbw", 
+        poDS->bGotTransform =
+            GDALReadWorldFile( poOpenInfo->pszFilename, "cbw",
                                poDS->adfGeoTransform );
 
     if( !poDS->bGotTransform )
-        poDS->bGotTransform = 
-            GDALReadWorldFile( poOpenInfo->pszFilename, "wld", 
+        poDS->bGotTransform =
+            GDALReadWorldFile( poOpenInfo->pszFilename, "wld",
                                poDS->adfGeoTransform );
 
-/* -------------------------------------------------------------------- */ 
-/*      Initialize any PAM information.                                 */ 
-/* -------------------------------------------------------------------- */ 
-    poDS->SetDescription( poOpenInfo->pszFilename ); 
-    poDS->TryLoadXML(); 
+/* -------------------------------------------------------------------- */
+/*      Initialize any PAM information.                                 */
+/* -------------------------------------------------------------------- */
+    poDS->SetDescription( poOpenInfo->pszFilename );
+    poDS->TryLoadXML();
 
 /* -------------------------------------------------------------------- */
 /*      Check for overviews.                                            */
@@ -773,7 +740,7 @@ GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /*                             GetKeyword()                             */
 /************************************************************************/
 
-const char *ISIS2Dataset::GetKeyword( const char *pszPath, 
+const char *ISIS2Dataset::GetKeyword( const char *pszPath,
                                       const char *pszDefault )
 
 {
@@ -784,20 +751,20 @@ const char *ISIS2Dataset::GetKeyword( const char *pszPath,
 /*                            GetKeywordSub()                           */
 /************************************************************************/
 
-const char *ISIS2Dataset::GetKeywordSub( const char *pszPath, 
+const char *ISIS2Dataset::GetKeywordSub( const char *pszPath,
                                          int iSubscript,
                                          const char *pszDefault )
 
 {
     const char *pszResult = oKeywords.GetKeyword( pszPath, NULL );
-    
+
     if( pszResult == NULL )
         return pszDefault;
 
     if( pszResult[0] != '(' )
         return pszDefault;
 
-    char **papszTokens = CSLTokenizeString2( pszResult, "(,)", 
+    char **papszTokens = CSLTokenizeString2( pszResult, "(,)",
                                              CSLT_HONOURSTRINGS );
 
     if( iSubscript <= CSLCount(papszTokens) )
@@ -806,11 +773,9 @@ const char *ISIS2Dataset::GetKeywordSub( const char *pszPath,
         CSLDestroy( papszTokens );
         return oTempResult.c_str();
     }
-    else
-    {
-        CSLDestroy( papszTokens );
-        return pszDefault;
-    }
+
+    CSLDestroy( papszTokens );
+    return pszDefault;
 }
 
 /************************************************************************/
@@ -829,11 +794,10 @@ void ISIS2Dataset::CleanString( CPLString &osInput )
         return;
 
     char *pszWrk = CPLStrdup(osInput.c_str() + 1);
-    int i;
 
     pszWrk[strlen(pszWrk)-1] = '\0';
-    
-    for( i = 0; pszWrk[i] != '\0'; i++ )
+
+    for( int i = 0; pszWrk[i] != '\0'; i++ )
     {
         if( pszWrk[i] == ' ' )
             pszWrk[i] = '_';
@@ -875,9 +839,9 @@ GDALDataset *ISIS2Dataset::Create(const char* pszFilename,
     const char *pszInterleaving = "(SAMPLE,LINE,BAND)";
     const char *pszInterleavingParam = CSLFetchNameValue( papszParmList, "INTERLEAVE" );
     if ( pszInterleavingParam ) {
-        if ( EQUALN( pszInterleavingParam, "bip", 3 ) )
+        if ( STARTS_WITH_CI(pszInterleavingParam, "bip") )
             pszInterleaving = "(BAND,SAMPLE,LINE)";
-        else if ( EQUALN( pszInterleavingParam, "bil", 3 ) )
+        else if ( STARTS_WITH_CI(pszInterleavingParam, "bil") )
             pszInterleaving = "(SAMPLE,BAND,LINE)";
         else
             pszInterleaving = "(SAMPLE,LINE,BAND)";
@@ -888,10 +852,10 @@ GDALDataset *ISIS2Dataset::Create(const char* pszFilename,
     /* check if labeling method is set : check the all three first chars */
     const char *pszLabelingMethod = CSLFetchNameValue( papszParmList, "LABELING_METHOD" );
     if ( pszLabelingMethod ){
-        if ( EQUALN( pszLabelingMethod, "detached", 3 ) ){
+        if ( STARTS_WITH_CI( pszLabelingMethod, "det" /* "detached" */ ) ){
             bAttachedLabelingMethod = false;
         }
-        if ( EQUALN( pszLabelingMethod, "attached", 3 ) ){
+        if ( STARTS_WITH_CI( pszLabelingMethod, "att" /* attached" */ ) ){
             bAttachedLabelingMethod = true;
         }
     }
@@ -940,7 +904,7 @@ GDALDataset *ISIS2Dataset::Create(const char* pszFilename,
 
     CPLDebug("ISIS2","irecord = %i",static_cast<int>(iRecords));
 
-    if( bAttachedLabelingMethod ) 
+    if( bAttachedLabelingMethod )
     {
         ISIS2Dataset::WriteLabel(osRasterFile, "", sObject, nXSize, nYSize, nBands, eType, iRecords, pszInterleaving, iLabelRecords, true);
     }
@@ -949,12 +913,12 @@ GDALDataset *ISIS2Dataset::Create(const char* pszFilename,
         ISIS2Dataset::WriteLabel(osLabelFile, osRasterFile, sObject, nXSize, nYSize, nBands, eType, iRecords, pszInterleaving, iLabelRecords);
     }
 
-    if( !ISIS2Dataset::WriteRaster(osRasterFile, bAttachedLabelingMethod, 
-                                   iRecords, iLabelRecords, eType, 
+    if( !ISIS2Dataset::WriteRaster(osRasterFile, bAttachedLabelingMethod,
+                                   iRecords, iLabelRecords, eType,
                                    pszInterleaving) )
         return NULL;
 
-    return (GDALDataset *) GDALOpen( osOutFile, GA_Update );
+    return reinterpret_cast<GDALDataset *>( GDALOpen( osOutFile, GA_Update ) );
 }
 
 
@@ -967,9 +931,8 @@ int ISIS2Dataset::WriteRaster(CPLString osFilename,
                               GUIntBig iRecords,
                               GUIntBig iLabelRecords,
                               CPL_UNUSED GDALDataType eType,
-                              CPL_UNUSED const char * pszInterleaving) {
-    GUIntBig nSize;
-    GByte byZero(0);
+                              CPL_UNUSED const char * pszInterleaving)
+{
     CPLString pszAccess("wb");
     if(includeLabel)
         pszAccess = "ab";
@@ -982,15 +945,16 @@ int ISIS2Dataset::WriteRaster(CPLString osFilename,
         return FALSE;
     }
 
-    nSize = iRecords * RECORD_SIZE;
+    GUIntBig nSize = iRecords * RECORD_SIZE;
     CPLDebug("ISIS2","nSize = %i", static_cast<int>(nSize));
 
     if(includeLabel)
         nSize = iLabelRecords * RECORD_SIZE + nSize;
 
     // write last byte
+    const GByte byZero(0);
     if(VSIFSeekL( fpBin, nSize-1, SEEK_SET ) != 0 ||
-       VSIFWriteL( &byZero, 1, 1, fpBin ) != 1){
+       VSIFWriteL( &byZero, 1, 1, fpBin ) != 1) {
         CPLError( CE_Failure, CPLE_FileIO,
                   "Failed to write %s:\n%s",
                   osFilename.c_str(), VSIStrerror( errno ) );
@@ -1008,7 +972,7 @@ int ISIS2Dataset::WriteRaster(CPLString osFilename,
 GUIntBig ISIS2Dataset::RecordSizeCalculation(unsigned int nXSize, unsigned int nYSize, unsigned int nBands, GDALDataType eType )
 
 {
-    GUIntBig n = nXSize * nYSize * nBands * (  GDALGetDataTypeSize(eType) / 8);
+    const GUIntBig n = static_cast<GUIntBig>(nXSize) * nYSize * nBands * (  GDALGetDataTypeSize(eType) / 8);
     // size of pds file is a multiple of RECORD_SIZE Bytes.
     CPLDebug("ISIS2","n = %i", static_cast<int>(n));
     CPLDebug("ISIS2","RECORD SIZE = %i", RECORD_SIZE);
@@ -1016,7 +980,7 @@ GUIntBig ISIS2Dataset::RecordSizeCalculation(unsigned int nXSize, unsigned int n
     CPLDebug("ISIS2","nYSize = %i", nYSize);
     CPLDebug("ISIS2","nBands = %i", nBands);
     CPLDebug("ISIS2","DataTypeSize = %i", GDALGetDataTypeSize(eType));
-    return (GUIntBig) ceil(static_cast<float>(n)/RECORD_SIZE);
+    return static_cast<GUIntBig>( ceil(static_cast<float>( n ) / RECORD_SIZE) );
 }
 
 /************************************************************************/
@@ -1025,7 +989,7 @@ GUIntBig ISIS2Dataset::RecordSizeCalculation(unsigned int nXSize, unsigned int n
 
 int ISIS2Dataset::WriteQUBE_Information(
     VSILFILE *fpLabel, unsigned int iLevel, unsigned int & nWritingBytes,
-    unsigned int nXSize,  unsigned int nYSize, unsigned int nBands, 
+    unsigned int nXSize,  unsigned int nYSize, unsigned int nBands,
     GDALDataType eType, const char * pszInterleaving)
 
 {
@@ -1044,17 +1008,17 @@ int ISIS2Dataset::WriteQUBE_Information(
     nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "CORE_UNIT", "\"N/A\"");
     // TODO change for eType
 
-    if( eType == GDT_Byte ) 
+    if( eType == GDT_Byte )
     {
         nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "CORE_ITEM_TYPE", "PC_UNSIGNED_INTEGER");
         nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "CORE_ITEM_BYTES", "1");
     }
-    else if( eType == GDT_UInt16 ) 
+    else if( eType == GDT_UInt16 )
     {
         nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "CORE_ITEM_TYPE", "PC_UNSIGNED_INTEGER");
         nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "CORE_ITEM_BYTES", "2");
     }
-    else if( eType == GDT_Int16 ) 
+    else if( eType == GDT_Int16 )
     {
         nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "CORE_ITEM_TYPE", "PC_INTEGER");
         nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "CORE_ITEM_BYTES", "2");
@@ -1079,7 +1043,7 @@ int ISIS2Dataset::WriteQUBE_Information(
     nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "SUFFIX_ITEMS", "( 0, 0, 0)");
     iLevel--;
     nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "END_OBJECT", "QUBE");
-    
+
     return TRUE;
 }
 
@@ -1089,7 +1053,7 @@ int ISIS2Dataset::WriteQUBE_Information(
 /*      osRasterFile : name of raster file but if it is empty we        */
 /*                     have only one file with an attached label        */
 /*      sObjectTag : QUBE, IMAGE or SPECTRAL_QUBE                       */
-/*      bRelaunch : flag to allow recursiv call                         */
+/*      bRelaunch : flag to allow recursive call                        */
 /************************************************************************/
 
 int ISIS2Dataset::WriteLabel(
@@ -1112,7 +1076,7 @@ int ISIS2Dataset::WriteLabel(
         return FALSE;
     }
 
-    unsigned int iLevel(0);
+    const unsigned int iLevel(0);
     unsigned int nWritingBytes(0);
 
     /* write common header */
@@ -1143,17 +1107,18 @@ int ISIS2Dataset::WriteLabel(
     nWritingBytes += ISIS2Dataset::WriteFormatting( fpLabel, "END");
 
     // check if file record is correct
-    unsigned int q = nWritingBytes/RECORD_SIZE;
+    const unsigned int q = nWritingBytes/RECORD_SIZE;
     if( q <= iLabelRecords){
         // correct we add space after the label end for complete from iLabelRecords
-        unsigned int nSpaceBytesToWrite = (unsigned int) (iLabelRecords * RECORD_SIZE - nWritingBytes);
+        unsigned int nSpaceBytesToWrite = static_cast<unsigned int>(
+            iLabelRecords * RECORD_SIZE - nWritingBytes );
         VSIFPrintfL(fpLabel,"%*c", nSpaceBytesToWrite, ' ');
     }else{
         iLabelRecords = q+1;
         ISIS2Dataset::WriteLabel(osFilename, osRasterFile, sObjectTag, nXSize, nYSize, nBands, eType, iRecords, pszInterleaving, iLabelRecords);
     }
     VSIFCloseL( fpLabel );
-  
+
     return TRUE;
 }
 
@@ -1166,9 +1131,10 @@ int ISIS2Dataset::WriteLabel(
 
     {
         CPLString tab = "";
-        iLevel *= 4; // each struct is idented by 4 spaces
-        int ret = VSIFPrintfL(fpLabel,"%*s%s=%s\n", iLevel, tab.c_str(), key.c_str(), value.c_str());
-        return ret;
+        iLevel *= 4; // each struct is indented by 4 spaces.
+
+        return VSIFPrintfL(fpLabel,"%*s%s=%s\n", iLevel, tab.c_str(),
+                           key.c_str(), value.c_str());
     }
 
 /************************************************************************/
@@ -1178,32 +1144,31 @@ int ISIS2Dataset::WriteLabel(
     unsigned int ISIS2Dataset::WriteFormatting(VSILFILE *fpLabel, CPLString data)
 
     {
-        int ret = VSIFPrintfL(fpLabel,"%s\n", data.c_str());
-        return ret;
+        return VSIFPrintfL(fpLabel,"%s\n", data.c_str());
     }
 
 /************************************************************************/
 /*                         GDALRegister_ISIS2()                         */
 /************************************************************************/
 
-    void GDALRegister_ISIS2()
+void GDALRegister_ISIS2()
 
-    {
-        GDALDriver	*poDriver;
+{
+    if( GDALGetDriverByName( "ISIS2" ) != NULL )
+        return;
 
-        if( GDALGetDriverByName( "ISIS2" ) == NULL )
-        {
-            poDriver = new GDALDriver();
-        
-            poDriver->SetDescription( "ISIS2" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-            poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                       "USGS Astrogeology ISIS cube (Version 2)" );
-            poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_isis2.html" );
-            poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-            poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte Int16 UInt16 Float32 Float64");
-
-            poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "ISIS2" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "USGS Astrogeology ISIS cube (Version 2)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_isis2.html" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte Int16 UInt16 Float32 Float64");
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>\n"
 "   <Option name='LABELING_METHOD' type='string-select' default='ATTACHED'>\n"
 "     <Value>ATTACHED</Value>"
@@ -1212,10 +1177,9 @@ int ISIS2Dataset::WriteLabel(
 "   <Option name='IMAGE_EXTENSION' type='string' default='cub'/>\n"
 "</CreationOptionList>\n" );
 
-            poDriver->pfnIdentify = ISIS2Dataset::Identify;
-            poDriver->pfnOpen = ISIS2Dataset::Open;
-            poDriver->pfnCreate = ISIS2Dataset::Create;
+    poDriver->pfnIdentify = ISIS2Dataset::Identify;
+    poDriver->pfnOpen = ISIS2Dataset::Open;
+    poDriver->pfnCreate = ISIS2Dataset::Create;
 
-            GetGDALDriverManager()->RegisterDriver( poDriver );
-        }
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/frmts/pds/isis3dataset.cpp b/frmts/pds/isis3dataset.cpp
index 3fa0f6a..e7da2c2 100644
--- a/frmts/pds/isis3dataset.cpp
+++ b/frmts/pds/isis3dataset.cpp
@@ -6,14 +6,14 @@
  * Author:   Trent Hare (thare at usgs.gov)
  *           Frank Warmerdam (warmerdam at pobox.com)
  *
- * NOTE: Original code authored by Trent and placed in the public domain as 
- * per US government policy.  I have (within my rights) appropriated it and 
- * placed it under the following license.  This is not intended to diminish 
- * Trents contribution. 
+ * NOTE: Original code authored by Trent and placed in the public domain as
+ * per US government policy.  I have (within my rights) appropriated it and
+ * placed it under the following license.  This is not intended to diminish
+ * Trents contribution.
  ******************************************************************************
  * Copyright (c) 2007, Frank Warmerdam <warmerdam at pobox.com>
  * Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * to deal in the Software without restriction, including without limitation
@@ -33,28 +33,21 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#define NULL1 0
-#define NULL2 -32768
+static const int NULL1 = 0;
+static const int NULL2 = -32768;
 //#define NULL3 0xFF7FFFFB //in hex
 //Same as ESRI_GRID_FLOAT_NO_DATA
 //#define NULL3 -340282346638528859811704183484516925440.0
-#define NULL3 -3.4028226550889044521e+38
-
-#ifndef PI
-#  define PI 3.1415926535897932384626433832795
-#endif
+static const double NULL3 = -3.4028226550889044521e+38;
 
-#include "rawdataset.h"
-#include "ogr_spatialref.h"
-#include "cpl_string.h" 
+#include "cpl_string.h"
+#include "gdal_frmts.h"
 #include "nasakeywordhandler.h"
+#include "ogr_spatialref.h"
+#include "rawdataset.h"
 
 CPL_CVSID("$Id: isis3dataset.cpp 10646 2007-09-18 02:38:10Z xxxx $");
 
-CPL_C_START
-void GDALRegister_ISIS3(void);
-CPL_C_END
-
 class ISIS3Dataset;
 
 /************************************************************************/
@@ -75,8 +68,8 @@ class ISISTiledBand : public GDALPamRasterBand
 
                 ISISTiledBand( GDALDataset *poDS, VSILFILE *fpVSIL,
                                int nBand, GDALDataType eDT,
-                               int nTileXSize, int nTileYSize, 
-                               GIntBig nFirstTileOffset, 
+                               int nTileXSize, int nTileYSize,
+                               GIntBig nFirstTileOffset,
                                GIntBig nXTileOffset,
                                GIntBig nYTileOffset,
                                int bNativeOrder );
@@ -89,39 +82,39 @@ class ISISTiledBand : public GDALPamRasterBand
 /*                           ISISTiledBand()                            */
 /************************************************************************/
 
-ISISTiledBand::ISISTiledBand( GDALDataset *poDS, VSILFILE *fpVSIL,
-                              int nBand, GDALDataType eDT,
-                              int nTileXSize, int nTileYSize, 
-                              GIntBig nFirstTileOffset, 
-                              GIntBig nXTileOffset,
-                              GIntBig nYTileOffset,
-                              int bNativeOrder )
+ISISTiledBand::ISISTiledBand( GDALDataset *poDSIn, VSILFILE *fpVSILIn,
+                              int nBandIn, GDALDataType eDT,
+                              int nTileXSize, int nTileYSize,
+                              GIntBig nFirstTileOffsetIn,
+                              GIntBig nXTileOffsetIn,
+                              GIntBig nYTileOffsetIn,
+                              int bNativeOrderIn )
 
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
-    this->fpVSIL = fpVSIL;
-    this->bNativeOrder = bNativeOrder;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
+    this->fpVSIL = fpVSILIn;
+    this->bNativeOrder = bNativeOrderIn;
     eDataType = eDT;
     nBlockXSize = nTileXSize;
     nBlockYSize = nTileYSize;
+    this->nXTileOffset = nXTileOffsetIn;
+    this->nYTileOffset = nYTileOffsetIn;
 
-    int nBlocksPerRow = 
+    const int l_nBlocksPerRow =
             (poDS->GetRasterXSize() + nTileXSize - 1) / nTileXSize;
-    int nBlocksPerColumn = 
+    const int l_nBlocksPerColumn =
             (poDS->GetRasterYSize() + nTileYSize - 1) / nTileYSize;
 
     if( nXTileOffset == 0 && nYTileOffset == 0 )
     {
-        nXTileOffset = (GDALGetDataTypeSize(eDT)/8) * nTileXSize * nTileYSize;
-        nYTileOffset = nXTileOffset * nBlocksPerRow;
+        nXTileOffset = static_cast<GIntBig>(GDALGetDataTypeSize(eDT)/8) * nTileXSize * nTileYSize;
+        nYTileOffset = nXTileOffset * l_nBlocksPerRow;
     }
 
-    this->nFirstTileOffset = nFirstTileOffset
-        + (nBand-1) * nYTileOffset * nBlocksPerColumn;
+    this->nFirstTileOffset = nFirstTileOffsetIn
+        + (nBand-1) * nYTileOffset * l_nBlocksPerColumn;
 
-    this->nXTileOffset = nXTileOffset;
-    this->nYTileOffset = nYTileOffset;
 }
 
 /************************************************************************/
@@ -131,30 +124,30 @@ ISISTiledBand::ISISTiledBand( GDALDataset *poDS, VSILFILE *fpVSIL,
 CPLErr ISISTiledBand::IReadBlock( int nXBlock, int nYBlock, void *pImage )
 
 {
-    GIntBig  nOffset = nFirstTileOffset + 
+    const GIntBig  nOffset = nFirstTileOffset +
         nXBlock * nXTileOffset + nYBlock * nYTileOffset;
-    size_t nBlockSize = 
+    const size_t nBlockSize =
         (GDALGetDataTypeSize(eDataType)/8) * nBlockXSize * nBlockYSize;
 
     if( VSIFSeekL( fpVSIL, nOffset, SEEK_SET ) != 0 )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   "Failed to seek to offset %d to read tile %d,%d.",
-                  (int) nOffset, nXBlock, nYBlock );
+                  static_cast<int>( nOffset ), nXBlock, nYBlock );
         return CE_Failure;
     }
 
     if( VSIFReadL( pImage, 1, nBlockSize, fpVSIL ) != nBlockSize )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   "Failed to read %d bytes for tile %d,%d.",
-                  (int) nBlockSize, nXBlock, nYBlock );
+                  static_cast<int>( nBlockSize ), nXBlock, nYBlock );
         return CE_Failure;
     }
 
     if( !bNativeOrder )
-        GDALSwapWords( pImage, GDALGetDataTypeSize(eDataType)/8, 
-                       nBlockXSize*nBlockYSize, 
+        GDALSwapWords( pImage, GDALGetDataTypeSize(eDataType)/8,
+                       nBlockXSize*nBlockYSize,
                        GDALGetDataTypeSize(eDataType)/8 );
 
     return CE_None;
@@ -171,12 +164,12 @@ class ISIS3Dataset : public RawDataset
     VSILFILE	*fpImage;	// image data file.
 
     CPLString   osExternalCube;
-    
+
     NASAKeywordHandler  oKeywords;
-  
+
     int         bGotTransform;
     double      adfGeoTransform[6];
-  
+
     CPLString   osProjection;
 
     int parse_label(const char *file, char *keyword, char *value);
@@ -184,19 +177,19 @@ class ISIS3Dataset : public RawDataset
 
     CPLString   oTempResult;
 
-    const char *GetKeyword( const char *pszPath, 
+    const char *GetKeyword( const char *pszPath,
                             const char *pszDefault = "");
-    const char *GetKeywordSub( const char *pszPath, 
-                               int iSubscript, 
+    const char *GetKeywordSub( const char *pszPath,
+                               int iSubscript,
                                const char *pszDefault = "");
-    
+
 public:
     ISIS3Dataset();
     ~ISIS3Dataset();
-  
+
     virtual CPLErr GetGeoTransform( double * padfTransform );
     virtual const char *GetProjectionRef(void);
-  
+
     virtual char **GetFileList();
 
     static int          Identify( GDALOpenInfo * );
@@ -207,15 +200,14 @@ public:
 };
 
 
-
 /************************************************************************/
 /*                            ISIS3Dataset()                            */
 /************************************************************************/
 
-ISIS3Dataset::ISIS3Dataset()
+ISIS3Dataset::ISIS3Dataset() :
+    fpImage(NULL),
+    bGotTransform(FALSE)
 {
-    fpImage = NULL;
-    bGotTransform = FALSE;
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
@@ -243,9 +235,7 @@ ISIS3Dataset::~ISIS3Dataset()
 char **ISIS3Dataset::GetFileList()
 
 {
-    char **papszFileList = NULL;
-
-    papszFileList = GDALPamDataset::GetFileList();
+    char **papszFileList = GDALPamDataset::GetFileList();
 
     if( strlen(osExternalCube) > 0 )
         papszFileList = CSLAddString( papszFileList, osExternalCube );
@@ -262,8 +252,8 @@ const char *ISIS3Dataset::GetProjectionRef()
 {
     if( strlen(osProjection) > 0 )
         return osProjection;
-    else
-        return GDALPamDataset::GetProjectionRef();
+
+    return GDALPamDataset::GetProjectionRef();
 }
 
 /************************************************************************/
@@ -278,23 +268,21 @@ CPLErr ISIS3Dataset::GetGeoTransform( double * padfTransform )
         memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
         return CE_None;
     }
-    else
-    {
-        return GDALPamDataset::GetGeoTransform( padfTransform );
-    }
+
+    return GDALPamDataset::GetGeoTransform( padfTransform );
 }
 
 /************************************************************************/
 /*                              Identify()                              */
 /************************************************************************/
 int ISIS3Dataset::Identify( GDALOpenInfo * poOpenInfo )
-    
+
 {
     if( poOpenInfo->pabyHeader != NULL
         && strstr((const char *)poOpenInfo->pabyHeader,"IsisCube") != NULL )
         return TRUE;
-    else
-        return FALSE;
+
+    return FALSE;
 }
 
 /************************************************************************/
@@ -317,9 +305,7 @@ GDALDataset *ISIS3Dataset::Open( GDALOpenInfo * poOpenInfo )
     if( fpQube == NULL )
         return NULL;
 
-    ISIS3Dataset 	*poDS;
-
-    poDS = new ISIS3Dataset();
+    ISIS3Dataset *poDS = new ISIS3Dataset();
 
     if( ! poDS->oKeywords.Ingest( fpQube, 0 ) )
     {
@@ -327,11 +313,11 @@ GDALDataset *ISIS3Dataset::Open( GDALOpenInfo * poOpenInfo )
         delete poDS;
         return NULL;
     }
-    
+
     VSIFCloseL( fpQube );
 
 /* -------------------------------------------------------------------- */
-/*	Assume user is pointing to label (ie .lbl) file for detached option */
+/* Assume user is pointing to label (i.e. .lbl) file for detached option */
 /* -------------------------------------------------------------------- */
     //  Image can be inline or detached and point to an image name
     //  the Format can be Tiled or Raw
@@ -352,7 +338,7 @@ GDALDataset *ISIS3Dataset::Open( GDALOpenInfo * poOpenInfo )
     //      Format      = Tile
     //      TileSamples = 128
     //      TileLines   = 128
-    
+
 /* -------------------------------------------------------------------- */
 /*      What file contains the actual data?                             */
 /* -------------------------------------------------------------------- */
@@ -372,50 +358,17 @@ GDALDataset *ISIS3Dataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Check if file an ISIS3 header file?  Read a few lines of text   */
 /*      searching for something starting with nrows or ncols.           */
 /* -------------------------------------------------------------------- */
-    GDALDataType eDataType = GDT_Byte;
-    OGRSpatialReference oSRS;
-
-    int	nRows = -1;
-    int nCols = -1;
-    int nBands = 1;
-    int nSkipBytes = 0;
-    int tileSizeX = 0;
-    int tileSizeY = 0;
-    double dfULXMap=0.5;
-    double dfULYMap = 0.5;
-    double dfXDim = 1.0;
-    double dfYDim = 1.0;
-    double scaleFactor = 1.0;
-    double dfNoData = 0.0;
-    int	bNoDataSet = FALSE;
-    char chByteOrder = 'M';  //default to MSB
-    char szLayout[32] = "BandSequential"; //default to band seq.
-    const char *target_name; //planet name
-    //projection parameters
-    const char *map_proj_name;
-    int	bProjectionSet = TRUE;
-    char proj_target_name[200]; 
-    char geog_name[60];  
-    char datum_name[60];  
-    char sphere_name[60];
-    char bIsGeographic = TRUE;
-    double semi_major = 0.0;
-    double semi_minor = 0.0;
-    double iflattening = 0.0;
-    double center_lat = 0.0;
-    double center_lon = 0.0;
-    double first_std_parallel = 0.0;
-    double second_std_parallel = 0.0;
-    double radLat, localRadius;
-    VSILFILE	*fp;
 
     /*************   Skipbytes     *****************************/
-    nSkipBytes = atoi(poDS->GetKeyword("IsisCube.Core.StartByte","")) - 1;
+    const int nSkipBytes = atoi(poDS->GetKeyword("IsisCube.Core.StartByte","")) - 1;
 
     /*******   Grab format type (BandSequential, Tiled)  *******/
-    const char *value;
+    const char *value = poDS->GetKeyword( "IsisCube.Core.Format", "" );
+
+    char szLayout[32] = "BandSequential";
+    int tileSizeX = 0;
+    int tileSizeY = 0;
 
-    value = poDS->GetKeyword( "IsisCube.Core.Format", "" );
     if (EQUAL(value,"Tile") )  { //Todo
         strcpy(szLayout,"Tiled");
        /******* Get Tile Sizes *********/
@@ -432,135 +385,150 @@ GDALDataset *ISIS3Dataset::Open( GDALOpenInfo * poOpenInfo )
     else if (EQUAL(value,"BandSequential") )
         strcpy(szLayout,"BSQ");
     else {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "%s layout not supported. Abort\n\n", value);
         delete poDS;
         return NULL;
     }
 
     /***********   Grab samples lines band ************/
-    nCols = atoi(poDS->GetKeyword("IsisCube.Core.Dimensions.Samples",""));
-    nRows = atoi(poDS->GetKeyword("IsisCube.Core.Dimensions.Lines",""));
-    nBands = atoi(poDS->GetKeyword("IsisCube.Core.Dimensions.Bands",""));
-     
+    const int nCols = atoi(poDS->GetKeyword("IsisCube.Core.Dimensions.Samples",""));
+    const int nRows = atoi(poDS->GetKeyword("IsisCube.Core.Dimensions.Lines",""));
+    const int nBands = atoi(poDS->GetKeyword("IsisCube.Core.Dimensions.Bands",""));
+
     /****** Grab format type - ISIS3 only supports 8,U16,S16,32 *****/
-    const char *itype;
+    GDALDataType eDataType = GDT_Byte;
+    double dfNoData = 0.0;
+    bool bNoDataSet = false;
 
-    itype = poDS->GetKeyword( "IsisCube.Core.Pixels.Type" );
+    const char *itype = poDS->GetKeyword( "IsisCube.Core.Pixels.Type" );
     if (EQUAL(itype,"UnsignedByte") ) {
         eDataType = GDT_Byte;
         dfNoData = NULL1;
-        bNoDataSet = TRUE;
+        bNoDataSet = true;
     }
     else if (EQUAL(itype,"UnsignedWord") ) {
         eDataType = GDT_UInt16;
         dfNoData = NULL1;
-        bNoDataSet = TRUE;
+        bNoDataSet = true;
     }
     else if (EQUAL(itype,"SignedWord") ) {
         eDataType = GDT_Int16;
         dfNoData = NULL2;
-        bNoDataSet = TRUE;
+        bNoDataSet = true;
     }
     else if (EQUAL(itype,"Real") || EQUAL(value,"") ) {
         eDataType = GDT_Float32;
         dfNoData = NULL3;
-        bNoDataSet = TRUE;
+        bNoDataSet = true;
     }
     else {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "%s layout type not supported. Abort\n\n", itype);
         delete poDS;
         return NULL;
     }
 
     /***********   Grab samples lines band ************/
+    char chByteOrder = 'M';  //default to MSB
+
     value = poDS->GetKeyword( "IsisCube.Core.Pixels.ByteOrder");
     if (EQUAL(value,"Lsb"))
         chByteOrder = 'I';
-    
+
     /***********   Grab Cellsize ************/
+    double dfXDim = 1.0;
+    double dfYDim = 1.0;
+
     value = poDS->GetKeyword("IsisCube.Mapping.PixelResolution");
     if (strlen(value) > 0 ) {
         dfXDim = CPLAtof(value); /* values are in meters */
         dfYDim = -CPLAtof(value);
     }
-    
+
     /***********   Grab UpperLeftCornerY ************/
+    double dfULYMap = 0.5;
+
     value = poDS->GetKeyword("IsisCube.Mapping.UpperLeftCornerY");
     if (strlen(value) > 0) {
         dfULYMap = CPLAtof(value);
     }
-     
+
     /***********   Grab UpperLeftCornerX ************/
+    double dfULXMap = 0.5;
+
     value = poDS->GetKeyword("IsisCube.Mapping.UpperLeftCornerX");
     if( strlen(value) > 0 ) {
         dfULXMap = CPLAtof(value);
     }
-     
+
     /***********  Grab TARGET_NAME  ************/
     /**** This is the planets name i.e. Mars ***/
-    target_name = poDS->GetKeyword("IsisCube.Mapping.TargetName");
-     
+    const char *target_name = poDS->GetKeyword("IsisCube.Mapping.TargetName");
+
     /***********   Grab MAP_PROJECTION_TYPE ************/
-    map_proj_name = 
+     const char *map_proj_name =
         poDS->GetKeyword( "IsisCube.Mapping.ProjectionName");
 
     /***********   Grab SEMI-MAJOR ************/
-    semi_major = 
+    const double semi_major =
         CPLAtof(poDS->GetKeyword( "IsisCube.Mapping.EquatorialRadius"));
 
     /***********   Grab semi-minor ************/
-    semi_minor = 
+    const double semi_minor =
         CPLAtof(poDS->GetKeyword( "IsisCube.Mapping.PolarRadius"));
 
     /***********   Grab CENTER_LAT ************/
-    center_lat = 
+    const double center_lat =
         CPLAtof(poDS->GetKeyword( "IsisCube.Mapping.CenterLatitude"));
 
     /***********   Grab CENTER_LON ************/
-    center_lon = 
+    const double center_lon =
         CPLAtof(poDS->GetKeyword( "IsisCube.Mapping.CenterLongitude"));
 
     /***********   Grab 1st std parallel ************/
-    first_std_parallel = 
+    const double first_std_parallel =
         CPLAtof(poDS->GetKeyword( "IsisCube.Mapping.FirstStandardParallel"));
 
     /***********   Grab 2nd std parallel ************/
-    second_std_parallel = 
+    const double second_std_parallel =
         CPLAtof(poDS->GetKeyword( "IsisCube.Mapping.SecondStandardParallel"));
-     
+
     /***********   Grab scaleFactor ************/
-    scaleFactor = 
+    const double scaleFactor =
         CPLAtof(poDS->GetKeyword( "IsisCube.Mapping.scaleFactor", "1.0"));
-     
+
     /*** grab      LatitudeType = Planetographic ****/
     // Need to further study how ocentric/ographic will effect the gdal library
-    // So far we will use this fact to define a sphere or ellipse for some 
+    // So far we will use this fact to define a sphere or ellipse for some
     // projections
 
     // Frank - may need to talk this over
     value = poDS->GetKeyword("IsisCube.Mapping.LatitudeType");
+    bool bIsGeographic = true;
     if (EQUAL( value, "Planetocentric" ))
-        bIsGeographic = FALSE; 
-     
+        bIsGeographic = false;
+
     //Set oSRS projection and parameters
     //############################################################
     //ISIS3 Projection types
-    //  Equirectangular 
-    //  LambertConformal 
-    //  Mercator 
+    //  Equirectangular
+    //  LambertConformal
+    //  Mercator
     //  ObliqueCylindrical //Todo
-    //  Orthographic 
-    //  PolarStereographic 
-    //  SimpleCylindrical 
-    //  Sinusoidal 
+    //  Orthographic
+    //  PolarStereographic
+    //  SimpleCylindrical
+    //  Sinusoidal
     //  TransverseMercator
-    
+
 #ifdef DEBUG
     CPLDebug( "ISIS3", "using projection %s", map_proj_name);
 #endif
 
+    OGRSpatialReference oSRS;
+    bool bProjectionSet = true;
+
     if ((EQUAL( map_proj_name, "Equirectangular" )) ||
         (EQUAL( map_proj_name, "SimpleCylindrical" )) )  {
         oSRS.OGRSpatialReference::SetEquirectangular2 ( 0.0, center_lon, center_lat, 0, 0 );
@@ -580,84 +548,93 @@ GDALDataset *ISIS3Dataset::Open( GDALOpenInfo * poOpenInfo )
         CPLDebug( "ISIS3",
                   "Dataset projection %s is not supported. Continuing...",
                   map_proj_name );
-        bProjectionSet = FALSE;
+        bProjectionSet = false;
     }
 
     if (bProjectionSet) {
+        char proj_target_name[200];
+
         //Create projection name, i.e. MERCATOR MARS and set as ProjCS keyword
         strcpy(proj_target_name, map_proj_name);
         strcat(proj_target_name, " ");
         strcat(proj_target_name, target_name);
         oSRS.SetProjCS(proj_target_name); //set ProjCS keyword
-     
+
         //The geographic/geocentric name will be the same basic name as the body name
         //'GCS' = Geographic/Geocentric Coordinate System
+        char geog_name[60];
         strcpy(geog_name, "GCS_");
         strcat(geog_name, target_name);
-        
+
         //The datum name will be the same basic name as the planet
+        char datum_name[60];
         strcpy(datum_name, "D_");
         strcat(datum_name, target_name);
-     
+
+        char sphere_name[60];
         strcpy(sphere_name, target_name);
         //strcat(sphere_name, "_IAU_IAG");  //Might not be IAU defined so don't add
-          
+
         //calculate inverse flattening from major and minor axis: 1/f = a/(a-b)
-        if ((semi_major - semi_minor) < 0.0000001) 
+        double iflattening = 0.0;
+        if ((semi_major - semi_minor) < 0.0000001)
            iflattening = 0;
         else
            iflattening = semi_major / (semi_major - semi_minor);
-     
+
         //Set the body size but take into consideration which proj is being used to help w/ proj4 compatibility
         //The use of a Sphere, polar radius or ellipse here is based on how ISIS does it internally
-        if ( ( (EQUAL( map_proj_name, "Stereographic" ) && (fabs(center_lat) == 90)) ) || 
-	           (EQUAL( map_proj_name, "PolarStereographic" )) )  
+        if ( ( (EQUAL( map_proj_name, "Stereographic" ) && (fabs(center_lat) == 90)) ) ||
+	           (EQUAL( map_proj_name, "PolarStereographic" )) )
          {
-            if (bIsGeographic) { 
+            if (bIsGeographic) {
                 //Geograpraphic, so set an ellipse
                 oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                                semi_major, iflattening, 
+                                semi_major, iflattening,
                                "Reference_Meridian", 0.0 );
             } else {
-              //Geocentric, so force a sphere using the semi-minor axis. I hope... 
+              //Geocentric, so force a sphere using the semi-minor axis. I hope...
               strcat(sphere_name, "_polarRadius");
               oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                              semi_minor, 0.0, 
+                              semi_minor, 0.0,
                               "Reference_Meridian", 0.0 );
             }
         }
-        else if ( (EQUAL( map_proj_name, "SimpleCylindrical" )) || 
-  	               (EQUAL( map_proj_name, "Orthographic" )) || 
-	               (EQUAL( map_proj_name, "Stereographic" )) || 
+        else if ( (EQUAL( map_proj_name, "SimpleCylindrical" )) ||
+  	               (EQUAL( map_proj_name, "Orthographic" )) ||
+	               (EQUAL( map_proj_name, "Stereographic" )) ||
 	               (EQUAL( map_proj_name, "Sinusoidal" )) ) {
-            //isis uses the sphereical equation for these projections so force a sphere
+            // ISIS uses the spherical equation for these projections
+            // so force a sphere.
             oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                            semi_major, 0.0, 
+                            semi_major, 0.0,
                             "Reference_Meridian", 0.0 );
-        } 
-        else if  (EQUAL( map_proj_name, "Equirectangular" )) { 
-            //Calculate localRadius using ISIS3 simple elliptical method 
+        }
+        else if  (EQUAL( map_proj_name, "Equirectangular" )) {
+            //Calculate localRadius using ISIS3 simple elliptical method
             //  not the more standard Radius of Curvature method
             //PI = 4 * atan(1);
-            radLat = center_lat * PI / 180;  // in radians
-            localRadius = semi_major * semi_minor / sqrt(pow(semi_minor*cos(radLat),2) 
-                          + pow(semi_major*sin(radLat),2) );
+            const double radLat = center_lat * M_PI / 180;  // in radians
+            const double localRadius
+                = semi_major * semi_minor
+                / sqrt( pow( semi_minor * cos( radLat ), 2)
+                       + pow( semi_major * sin( radLat ), 2) );
             strcat(sphere_name, "_localRadius");
             oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                            localRadius, 0.0, 
+                            localRadius, 0.0,
                             "Reference_Meridian", 0.0 );
-        } 
-        else { 
+        }
+        else {
             //All other projections: Mercator, Transverse Mercator, Lambert Conformal, etc.
             //Geographic, so set an ellipse
             if (bIsGeographic) {
                 oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                                semi_major, iflattening, 
+                                semi_major, iflattening,
                                 "Reference_Meridian", 0.0 );
-            } else { 
-                //Geocentric, so force a sphere. I hope... 
+            } else {
+                //Geocentric, so force a sphere. I hope...
                 oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                                semi_major, 0.0, 
+                                semi_major, 0.0,
                                 "Reference_Meridian", 0.0 );
             }
         }
@@ -671,7 +648,7 @@ GDALDataset *ISIS3Dataset::Open( GDALOpenInfo * poOpenInfo )
 
 /* END ISIS3 Label Read */
 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-    
+
 /* -------------------------------------------------------------------- */
 /*     Is the CUB detached - if so, reset name to binary file?          */
 /* -------------------------------------------------------------------- */
@@ -711,8 +688,8 @@ GDALDataset *ISIS3Dataset::Open( GDALOpenInfo * poOpenInfo )
 
     if( poDS->fpImage == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Failed to open %s with write permission.\n%s", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to open %s with write permission.\n%s",
                   osQubeFile.c_str(),
                   VSIStrerror( errno ) );
         delete poDS;
@@ -724,91 +701,84 @@ GDALDataset *ISIS3Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Compute the line offset.                                        */
 /* -------------------------------------------------------------------- */
-    int     nItemSize = GDALGetDataTypeSize(eDataType)/8;
-    int	    nLineOffset=0, nPixelOffset=0, nBandOffset=0;
-    
+    const int nItemSize = GDALGetDataTypeSize(eDataType)/8;
+    int nLineOffset=0, nPixelOffset=0, nBandOffset=0;
+
     if( EQUAL(szLayout,"BSQ") )
     {
         nPixelOffset = nItemSize;
         nLineOffset = nPixelOffset * nCols;
         nBandOffset = nLineOffset * nRows;
     }
-    else /* Tiled */
-    {
-    }
-    
+    /* else Tiled */
+
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    int i;
-
-#ifdef CPL_LSB                               
+#ifdef CPL_LSB
     int bNativeOrder = !(chByteOrder == 'M');
 #else
     int bNativeOrder = (chByteOrder == 'M');
-#endif        
+#endif
 
 
-    for( i = 0; i < nBands; i++ )
+    for( int i = 0; i < nBands; i++ )
     {
         GDALRasterBand	*poBand;
 
         if( EQUAL(szLayout,"Tiled") )
         {
             poBand = new ISISTiledBand( poDS, poDS->fpImage, i+1, eDataType,
-                                        tileSizeX, tileSizeY, 
-                                        nSkipBytes, 0, 0, 
+                                        tileSizeX, tileSizeY,
+                                        nSkipBytes, 0, 0,
                                         bNativeOrder );
         }
         else
         {
-            poBand = 
+            poBand =
                 new RawRasterBand( poDS, i+1, poDS->fpImage,
-                                   nSkipBytes + nBandOffset * i, 
+                                   nSkipBytes + nBandOffset * i,
                                    nPixelOffset, nLineOffset, eDataType,
-#ifdef CPL_LSB                               
+#ifdef CPL_LSB
                                    chByteOrder == 'I' || chByteOrder == 'L',
 #else
                                    chByteOrder == 'M',
-#endif        
+#endif
                                    TRUE );
         }
 
         poDS->SetBand( i+1, poBand );
 
         if( bNoDataSet )
-            ((GDALPamRasterBand *) poBand)->SetNoDataValue( dfNoData );
+            reinterpret_cast<GDALPamRasterBand *>(
+                poBand )->SetNoDataValue( dfNoData );
 
         // Set offset/scale values at the PAM level.
-        poBand->SetOffset( 
+        poBand->SetOffset(
             CPLAtofM(poDS->GetKeyword("IsisCube.Core.Pixels.Base","0.0")));
-        poBand->SetScale( 
+        poBand->SetScale(
           CPLAtofM(poDS->GetKeyword("IsisCube.Core.Pixels.Multiplier","1.0")));
     }
 
 /* -------------------------------------------------------------------- */
 /*      Check for a .prj file. For ISIS3 I would like to keep this in   */
 /* -------------------------------------------------------------------- */
-    CPLString osPath, osName;
-
-    osPath = CPLGetPath( poOpenInfo->pszFilename );
-    osName = CPLGetBasename(poOpenInfo->pszFilename);
+    const CPLString osPath = CPLGetPath( poOpenInfo->pszFilename );
+    const CPLString osName = CPLGetBasename(poOpenInfo->pszFilename);
     const char  *pszPrjFile = CPLFormCIFilename( osPath, osName, "prj" );
 
-    fp = VSIFOpenL( pszPrjFile, "r" );
+    VSILFILE *fp = VSIFOpenL( pszPrjFile, "r" );
     if( fp != NULL )
     {
-        char	**papszLines;
-        OGRSpatialReference oSRS;
-
         VSIFCloseL( fp );
-        
-        papszLines = CSLLoad( pszPrjFile );
 
-        if( oSRS.importFromESRI( papszLines ) == OGRERR_NONE )
+        char **papszLines = CSLLoad( pszPrjFile );
+
+        OGRSpatialReference oSRS2;
+        if( oSRS2.importFromESRI( papszLines ) == OGRERR_NONE )
         {
             char *pszResult = NULL;
-            oSRS.exportToWkt( &pszResult );
+            oSRS2.exportToWkt( &pszResult );
             poDS->osProjection = pszResult;
             CPLFree( pszResult );
         }
@@ -816,8 +786,7 @@ GDALDataset *ISIS3Dataset::Open( GDALOpenInfo * poOpenInfo )
         CSLDestroy( papszLines );
     }
 
-    
-    if( dfULYMap != 0.5 || dfULYMap != 0.5 || dfXDim != 1.0 || dfYDim != 1.0 )
+    if( dfULXMap != 0.5 || dfULYMap != 0.5 || dfXDim != 1.0 || dfYDim != 1.0 )
     {
         poDS->bGotTransform = TRUE;
         poDS->adfGeoTransform[0] = dfULXMap;
@@ -827,15 +796,15 @@ GDALDataset *ISIS3Dataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->adfGeoTransform[4] = 0.0;
         poDS->adfGeoTransform[5] = dfYDim;
     }
-    
+
     if( !poDS->bGotTransform )
-        poDS->bGotTransform = 
-            GDALReadWorldFile( poOpenInfo->pszFilename, "cbw", 
+        poDS->bGotTransform =
+            GDALReadWorldFile( poOpenInfo->pszFilename, "cbw",
                                poDS->adfGeoTransform );
 
     if( !poDS->bGotTransform )
-        poDS->bGotTransform = 
-            GDALReadWorldFile( poOpenInfo->pszFilename, "wld", 
+        poDS->bGotTransform =
+            GDALReadWorldFile( poOpenInfo->pszFilename, "wld",
                                poDS->adfGeoTransform );
 
 /* -------------------------------------------------------------------- */
@@ -856,7 +825,7 @@ GDALDataset *ISIS3Dataset::Open( GDALOpenInfo * poOpenInfo )
 /*                             GetKeyword()                             */
 /************************************************************************/
 
-const char *ISIS3Dataset::GetKeyword( const char *pszPath, 
+const char *ISIS3Dataset::GetKeyword( const char *pszPath,
                                       const char *pszDefault )
 
 {
@@ -867,20 +836,20 @@ const char *ISIS3Dataset::GetKeyword( const char *pszPath,
 /*                            GetKeywordSub()                           */
 /************************************************************************/
 
-const char *ISIS3Dataset::GetKeywordSub( const char *pszPath, 
+const char *ISIS3Dataset::GetKeywordSub( const char *pszPath,
                                          int iSubscript,
                                          const char *pszDefault )
 
 {
     const char *pszResult = oKeywords.GetKeyword( pszPath, NULL );
-    
+
     if( pszResult == NULL )
         return pszDefault;
 
     if( pszResult[0] != '(' )
         return pszDefault;
 
-    char **papszTokens = CSLTokenizeString2( pszResult, "(,)", 
+    char **papszTokens = CSLTokenizeString2( pszResult, "(,)",
                                              CSLT_HONOURSTRINGS );
 
     if( iSubscript <= CSLCount(papszTokens) )
@@ -889,11 +858,9 @@ const char *ISIS3Dataset::GetKeywordSub( const char *pszPath,
         CSLDestroy( papszTokens );
         return oTempResult.c_str();
     }
-    else
-    {
-        CSLDestroy( papszTokens );
-        return pszDefault;
-    }
+
+    CSLDestroy( papszTokens );
+    return pszDefault;
 }
 
 
@@ -904,24 +871,21 @@ const char *ISIS3Dataset::GetKeywordSub( const char *pszPath,
 void GDALRegister_ISIS3()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "ISIS3" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "ISIS3" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "ISIS3" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "USGS Astrogeology ISIS cube (Version 3)" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_isis3.html" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = ISIS3Dataset::Open;
-        poDriver->pfnIdentify = ISIS3Dataset::Identify;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
-}
+    GDALDriver *poDriver = new GDALDriver();
 
+    poDriver->SetDescription( "ISIS3" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "USGS Astrogeology ISIS cube (Version 3)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_isis3.html" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = ISIS3Dataset::Open;
+    poDriver->pfnIdentify = ISIS3Dataset::Identify;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/frmts/pds/nasakeywordhandler.cpp b/frmts/pds/nasakeywordhandler.cpp
index baf1a07..f3cea30 100644
--- a/frmts/pds/nasakeywordhandler.cpp
+++ b/frmts/pds/nasakeywordhandler.cpp
@@ -2,14 +2,14 @@
  * $Id: pdsdataset.cpp 12658 2007-11-07 23:14:33Z warmerdam $
  *
  * Project:  PDS Driver; Planetary Data System Format
- * Purpose:  Implementation of NASAKeywordHandler - a class to read 
+ * Purpose:  Implementation of NASAKeywordHandler - a class to read
  *           keyword data from PDS, ISIS2 and ISIS3 data products.
  * Author:   Frank Warmerdam <warmerdam at pobox.com
  *
  ******************************************************************************
  * Copyright (c) 2006, Frank Warmerdam <warmerdam at pobox.com>
  * Copyright (c) 2008-2010, Even Rouault <even dot rouault at mines-paris dot org>
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * to deal in the Software without restriction, including without limitation
@@ -32,25 +32,25 @@
  * and other NASA data systems. Refer to Chapter 12 of "PDS Standards
  * Reference" at http://pds.jpl.nasa.gov/tools/standards-reference.shtml for
  * further details about ODL.
- * 
+ *
  * This is also known as PVL (Parameter Value Language) which is written
  * about at http://www.orrery.us/node/44 where it notes:
- * 
- * The PVL syntax that the PDS uses is specified by the Consultative Committee 
- * for Space Data Systems in their Blue Book publication: "Parameter Value 
- * Language Specification (CCSD0006 and CCSD0008)", June 2000 
- * [CCSDS 641.0-B-2], and Green Book publication: "Parameter Value Language - 
+ *
+ * The PVL syntax that the PDS uses is specified by the Consultative Committee
+ * for Space Data Systems in their Blue Book publication: "Parameter Value
+ * Language Specification (CCSD0006 and CCSD0008)", June 2000
+ * [CCSDS 641.0-B-2], and Green Book publication: "Parameter Value Language -
  * A Tutorial", June 2000 [CCSDS 641.0-G-2]. PVL has also been accepted by the
- * International Standards Organization (ISO), as a Final Draft International 
- * Standard (ISO 14961:2002) keyword value type language for naming and 
+ * International Standards Organization (ISO), as a Final Draft International
+ * Standard (ISO 14961:2002) keyword value type language for naming and
  * expressing data values.
  * --
  * also of interest, on PDS ODL:
  *  http://pds.jpl.nasa.gov/documents/sr/Chapter12.pdf
- *  
+ *
  ****************************************************************************/
 
-#include "cpl_string.h" 
+#include "cpl_string.h"
 #include "nasakeywordhandler.h"
 
 /************************************************************************/
@@ -63,10 +63,10 @@
 /*                         NASAKeywordHandler()                         */
 /************************************************************************/
 
-NASAKeywordHandler::NASAKeywordHandler()
-
+NASAKeywordHandler::NASAKeywordHandler() :
+    papszKeywordList(NULL),
+    pszHeaderNext(NULL)
 {
-    papszKeywordList = NULL;
 }
 
 /************************************************************************/
@@ -93,12 +93,11 @@ int NASAKeywordHandler::Ingest( VSILFILE *fp, int nOffset )
     if( VSIFSeekL( fp, nOffset, SEEK_SET ) != 0 )
         return FALSE;
 
-    for( ; TRUE; ) 
+    for( ; true; )
     {
-        const char *pszCheck;
         char szChunk[513];
 
-        int nBytesRead = VSIFReadL( szChunk, 1, 512, fp );
+        int nBytesRead = static_cast<int>(VSIFReadL( szChunk, 1, 512, fp ));
 
         szChunk[nBytesRead] = '\0';
         osHeaderText += szChunk;
@@ -106,14 +105,15 @@ int NASAKeywordHandler::Ingest( VSILFILE *fp, int nOffset )
         if( nBytesRead < 512 )
             break;
 
+        const char *pszCheck;
         if( osHeaderText.size() > 520 )
             pszCheck = osHeaderText.c_str() + (osHeaderText.size() - 520);
         else
             pszCheck = szChunk;
 
-        if( strstr(pszCheck,"\r\nEND\r\n") != NULL 
-            || strstr(pszCheck,"\nEND\n") != NULL 
-            || strstr(pszCheck,"\r\nEnd\r\n") != NULL 
+        if( strstr(pszCheck,"\r\nEND\r\n") != NULL
+            || strstr(pszCheck,"\nEND\n") != NULL
+            || strstr(pszCheck,"\r\nEnd\r\n") != NULL
             || strstr(pszCheck,"\nEnd\n") != NULL )
             break;
     }
@@ -133,10 +133,9 @@ int NASAKeywordHandler::Ingest( VSILFILE *fp, int nOffset )
 int NASAKeywordHandler::ReadGroup( const char *pszPathPrefix )
 
 {
-    CPLString osName, osValue;
-
-    for( ; TRUE; )
+    for( ; true; )
     {
+        CPLString osName, osValue;
         if( !ReadPair( osName, osValue ) )
             return FALSE;
 
@@ -145,7 +144,7 @@ int NASAKeywordHandler::ReadGroup( const char *pszPathPrefix )
             if( !ReadGroup( (CPLString(pszPathPrefix) + osValue + ".").c_str() ) )
                 return FALSE;
         }
-        else if( EQUAL(osName,"END") 
+        else if( EQUAL(osName,"END")
                  || EQUAL(osName,"END_GROUP" )
                  || EQUAL(osName,"END_OBJECT" ) )
         {
@@ -154,7 +153,7 @@ int NASAKeywordHandler::ReadGroup( const char *pszPathPrefix )
         else
         {
             osName = pszPathPrefix + osName;
-            papszKeywordList = CSLSetNameValue( papszKeywordList, 
+            papszKeywordList = CSLSetNameValue( papszKeywordList,
                                                 osName, osValue );
         }
     }
@@ -184,17 +183,17 @@ int NASAKeywordHandler::ReadPair( CPLString &osName, CPLString &osValue )
 
     if( *pszHeaderNext != '=' )
     {
-        // ISIS3 does not have anything after the end group/object keyword. 
+        // ISIS3 does not have anything after the end group/object keyword.
         if( EQUAL(osName,"End_Group") || EQUAL(osName,"End_Object") )
             return TRUE;
-        else
-            return FALSE;
+
+        return FALSE;
     }
-    
+
     pszHeaderNext++;
-    
+
     SkipWhite();
-    
+
     osValue = "";
 
     // Handle value lists like:     Name   = (Red, Red)
@@ -227,35 +226,33 @@ int NASAKeywordHandler::ReadPair( CPLString &osName, CPLString &osValue )
         }
     }
 
-    else // Handle more normal "single word" values. 
+    else // Handle more normal "single word" values.
     {
         if( !ReadWord( osValue ) )
             return FALSE;
-
     }
-        
+
     SkipWhite();
 
-    // No units keyword?   
+    // No units keyword?
     if( *pszHeaderNext != '<' )
         return TRUE;
 
     // Append units keyword.  For lines that like like this:
     //  MAP_RESOLUTION               = 4.0 <PIXEL/DEGREE>
-    
-    CPLString osWord;
-    
+
     osValue += " ";
-    
+
+    CPLString osWord;
     while( ReadWord( osWord ) )
     {
         SkipWhite();
-        
+
         osValue += osWord;
         if( osWord[strlen(osWord)-1] == '>' )
             break;
     }
-    
+
     return TRUE;
 }
 
@@ -271,9 +268,9 @@ int NASAKeywordHandler::ReadWord( CPLString &osWord )
 
     SkipWhite();
 
-    if( !(*pszHeaderNext != '\0' 
-           && *pszHeaderNext != '=' 
-           && !isspace((unsigned char)*pszHeaderNext)) )
+    if( !(*pszHeaderNext != '\0'
+          && *pszHeaderNext != '='
+          && !isspace( static_cast<unsigned char>( *pszHeaderNext ) ) ) )
         return FALSE;
 
     /* Extract a text string delimited by '\"' */
@@ -308,7 +305,7 @@ int NASAKeywordHandler::ReadWord( CPLString &osWord )
     /* These are expected to not have
        '\'' (delimiters),
        format effectors (should fit on a single line) or
-       control characters.  
+       control characters.
     */
     if( *pszHeaderNext == '\'' )
     {
@@ -325,27 +322,27 @@ int NASAKeywordHandler::ReadWord( CPLString &osWord )
     }
 
     /*
-     * Extract normal text.  Terminated by '=' or whitespace. 
+     * Extract normal text.  Terminated by '=' or whitespace.
      *
-     * A special exception is that a line may terminate with a '-' 
+     * A special exception is that a line may terminate with a '-'
      * which is taken as a line extender, and we suck up white space to new
      * text.
      */
-    while( *pszHeaderNext != '\0' 
-           && *pszHeaderNext != '=' 
-           && !isspace((unsigned char)*pszHeaderNext) )
+    while( *pszHeaderNext != '\0'
+           && *pszHeaderNext != '='
+           && !isspace(static_cast<unsigned char>( *pszHeaderNext ) ) )
     {
         osWord += *pszHeaderNext;
         pszHeaderNext++;
 
-        if( *pszHeaderNext == '-' 
+        if( *pszHeaderNext == '-'
             && (pszHeaderNext[1] == 10 || pszHeaderNext[1] == 13) )
         {
             pszHeaderNext += 2;
             SkipWhite();
         }
     }
-    
+
     return TRUE;
 }
 
@@ -357,15 +354,15 @@ int NASAKeywordHandler::ReadWord( CPLString &osWord )
 void NASAKeywordHandler::SkipWhite()
 
 {
-    for( ; TRUE; )
+    for( ; true; )
     {
-        // Skip C style comments 
+        // Skip C style comments
         if( *pszHeaderNext == '/' && pszHeaderNext[1] == '*' )
         {
             pszHeaderNext += 2;
-            
-            while( *pszHeaderNext != '\0' 
-                   && (*pszHeaderNext != '*' 
+
+            while( *pszHeaderNext != '\0'
+                   && (*pszHeaderNext != '*'
                        || pszHeaderNext[1] != '/' ) )
             {
                 pszHeaderNext++;
@@ -384,15 +381,15 @@ void NASAKeywordHandler::SkipWhite()
             continue;
         }
 
-        // Skip # style comments 
-         if( (*pszHeaderNext == 10 || *pszHeaderNext == 13 ||
+        // Skip # style comments
+        if( (*pszHeaderNext == 10 || *pszHeaderNext == 13 ||
  	     *pszHeaderNext == ' ' || *pszHeaderNext == '\t' )
               && pszHeaderNext[1] == '#' )
         {
             pszHeaderNext += 2;
 
             // consume till end of line.
-            while( *pszHeaderNext != '\0' 
+            while( *pszHeaderNext != '\0'
                    && *pszHeaderNext != 10
                    && *pszHeaderNext != 13 )
             {
@@ -402,13 +399,13 @@ void NASAKeywordHandler::SkipWhite()
         }
 
         // Skip white space (newline, space, tab, etc )
-        if( isspace( (unsigned char)*pszHeaderNext ) )
+        if( isspace( static_cast<unsigned char>( *pszHeaderNext ) ) )
         {
-            pszHeaderNext++; 
+            pszHeaderNext++;
             continue;
         }
-        
-        // not white space, return. 
+
+        // not white space, return.
         return;
     }
 }
@@ -421,21 +418,19 @@ const char *NASAKeywordHandler::GetKeyword( const char *pszPath,
                                             const char *pszDefault )
 
 {
-    const char *pszResult;
+    const char *pszResult = CSLFetchNameValue( papszKeywordList, pszPath );
 
-    pszResult = CSLFetchNameValue( papszKeywordList, pszPath );
     if( pszResult == NULL )
         return pszDefault;
-    else
-        return pszResult;
+
+    return pszResult;
 }
 
 /************************************************************************/
 /*                             GetKeywordList()                         */
 /************************************************************************/
- 
+
 char **NASAKeywordHandler::GetKeywordList()
 {
     return papszKeywordList;
 }
-
diff --git a/frmts/pds/pdsdataset.cpp b/frmts/pds/pdsdataset.cpp
index d3db245..fe213ad 100644
--- a/frmts/pds/pdsdataset.cpp
+++ b/frmts/pds/pdsdataset.cpp
@@ -1,19 +1,19 @@
 /******************************************************************************
- * $Id: pdsdataset.cpp 30712 2015-09-26 08:06:35Z rouault $
+ * $Id: pdsdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  PDS Driver; Planetary Data System Format
  * Purpose:  Implementation of PDSDataset
  * Author:   Trent Hare (thare at usgs.gov),
  *           Robert Soricone (rsoricone at usgs.gov)
  *
- * NOTE: Original code authored by Trent and Robert and placed in the public 
- * domain as per US government policy.  I have (within my rights) appropriated 
- * it and placed it under the following license.  This is not intended to 
- * diminish Trent and Roberts contribution. 
+ * NOTE: Original code authored by Trent and Robert and placed in the public
+ * domain as per US government policy.  I have (within my rights) appropriated
+ * it and placed it under the following license.  This is not intended to
+ * diminish Trent and Roberts contribution.
  ******************************************************************************
  * Copyright (c) 2007, Frank Warmerdam <warmerdam at pobox.com>
  * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * to deal in the Software without restriction, including without limitation
@@ -34,24 +34,21 @@
  ****************************************************************************/
 
 // Set up PDS NULL values
-#define NULL1 0
-#define NULL2 -32768
+static const int NULL1 = 0;
+static const int NULL2 = -32768;
 //#define NULL3 -0.3402822655089E+39
 //Same as ESRI_GRID_FLOAT_NO_DATA
 //#define NULL3 -340282346638528859811704183484516925440.0
-#define NULL3 -3.4028226550889044521e+38
+static const double NULL3 = -3.4028226550889044521e+38;
 
-#include "rawdataset.h"
+#include "cpl_string.h"
+#include "gdal_frmts.h"
 #include "gdal_proxy.h"
-#include "ogr_spatialref.h"
-#include "cpl_string.h" 
 #include "nasakeywordhandler.h"
+#include "ogr_spatialref.h"
+#include "rawdataset.h"
 
-CPL_CVSID("$Id: pdsdataset.cpp 30712 2015-09-26 08:06:35Z rouault $");
-
-CPL_C_START
-void	GDALRegister_PDS(void);
-CPL_C_END
+CPL_CVSID("$Id: pdsdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 enum PDSLayout
 {
@@ -72,10 +69,10 @@ class PDSDataset : public RawDataset
     GDALDataset *poCompressedDS;
 
     NASAKeywordHandler  oKeywords;
-  
+
     int         bGotTransform;
     double      adfGeoTransform[6];
-  
+
     CPLString   osProjection;
 
     CPLString   osTempResult;
@@ -90,10 +87,10 @@ class PDSDataset : public RawDataset
     const char *GetKeyword( std::string osPath,
                             const char *pszDefault = "");
     const char *GetKeywordSub( std::string osPath,
-                               int iSubscript, 
+                               int iSubscript,
                                const char *pszDefault = "");
-    const char *GetKeywordUnit( const char *pszPath, 
-                               int iSubscript, 
+    const char *GetKeywordUnit( const char *pszPath,
+                               int iSubscript,
                                const char *pszDefault = "");
 
   protected:
@@ -102,15 +99,15 @@ class PDSDataset : public RawDataset
 public:
     PDSDataset();
     ~PDSDataset();
-  
+
     virtual CPLErr GetGeoTransform( double * padfTransform );
     virtual const char *GetProjectionRef(void);
-  
+
     virtual char      **GetFileList(void);
 
     virtual CPLErr IBuildOverviews( const char *, int, int *,
                                     int, int *, GDALProgressFunc, void * );
-    
+
     virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
                               void *, int, int, GDALDataType,
                               int, int *,
@@ -129,17 +126,17 @@ public:
 /*                            PDSDataset()                            */
 /************************************************************************/
 
-PDSDataset::PDSDataset()
+PDSDataset::PDSDataset() :
+    fpImage(NULL),
+    poCompressedDS(NULL),
+    bGotTransform(FALSE)
 {
-    fpImage = NULL;
-    bGotTransform = FALSE;
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
-    poCompressedDS = NULL;
 }
 
 /************************************************************************/
@@ -166,7 +163,7 @@ int PDSDataset::CloseDependentDatasets()
 
     if( poCompressedDS )
     {
-        bHasDroppedRef = TRUE;
+        bHasDroppedRef = FALSE;
         delete poCompressedDS;
         poCompressedDS = NULL;
     }
@@ -193,7 +190,7 @@ char **PDSDataset::GetFileList()
     {
         char **papszCFileList = poCompressedDS->GetFileList();
 
-        papszFileList = CSLInsertStrings( papszFileList, -1, 
+        papszFileList = CSLInsertStrings( papszFileList, -1,
                                           papszCFileList );
         CSLDestroy( papszCFileList );
     }
@@ -210,24 +207,24 @@ char **PDSDataset::GetFileList()
 /*                          IBuildOverviews()                           */
 /************************************************************************/
 
-CPLErr PDSDataset::IBuildOverviews( const char *pszResampling, 
-                                    int nOverviews, int *panOverviewList, 
+CPLErr PDSDataset::IBuildOverviews( const char *pszResampling,
+                                    int nOverviews, int *panOverviewList,
                                     int nListBands, int *panBandList,
-                                    GDALProgressFunc pfnProgress, 
+                                    GDALProgressFunc pfnProgress,
                                     void * pProgressData )
 {
     if( poCompressedDS != NULL )
-        return poCompressedDS->BuildOverviews( pszResampling, 
+        return poCompressedDS->BuildOverviews( pszResampling,
                                                nOverviews, panOverviewList,
-                                               nListBands, panBandList, 
+                                               nListBands, panBandList,
                                                pfnProgress, pProgressData );
-    else
-        return RawDataset::IBuildOverviews( pszResampling, 
-                                            nOverviews, panOverviewList,
-                                            nListBands, panBandList, 
-                                            pfnProgress, pProgressData );
+
+    return RawDataset::IBuildOverviews( pszResampling,
+                                        nOverviews, panOverviewList,
+                                        nListBands, panBandList,
+                                        pfnProgress, pProgressData );
 }
-        
+
 /************************************************************************/
 /*                             IRasterIO()                              */
 /************************************************************************/
@@ -235,7 +232,7 @@ CPLErr PDSDataset::IBuildOverviews( const char *pszResampling,
 CPLErr PDSDataset::IRasterIO( GDALRWFlag eRWFlag,
                               int nXOff, int nYOff, int nXSize, int nYSize,
                               void * pData, int nBufXSize, int nBufYSize,
-                              GDALDataType eBufType, 
+                              GDALDataType eBufType,
                               int nBandCount, int *panBandMap,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
                               GSpacing nBandSpace,
@@ -243,18 +240,18 @@ CPLErr PDSDataset::IRasterIO( GDALRWFlag eRWFlag,
 
 {
     if( poCompressedDS != NULL )
-        return poCompressedDS->RasterIO( eRWFlag, 
-                                         nXOff, nYOff, nXSize, nYSize, 
-                                         pData, nBufXSize, nBufYSize, 
+        return poCompressedDS->RasterIO( eRWFlag,
+                                         nXOff, nYOff, nXSize, nYSize,
+                                         pData, nBufXSize, nBufYSize,
                                          eBufType, nBandCount, panBandMap,
                                          nPixelSpace, nLineSpace, nBandSpace,
                                          psExtraArg);
-    else
-        return RawDataset::IRasterIO( eRWFlag, 
-                                      nXOff, nYOff, nXSize, nYSize, 
-                                      pData, nBufXSize, nBufYSize, 
-                                      eBufType, nBandCount, panBandMap,
-                                      nPixelSpace, nLineSpace, nBandSpace, psExtraArg );
+
+    return RawDataset::IRasterIO( eRWFlag,
+                                  nXOff, nYOff, nXSize, nYSize,
+                                  pData, nBufXSize, nBufYSize,
+                                  eBufType, nBandCount, panBandMap,
+                                  nPixelSpace, nLineSpace, nBandSpace, psExtraArg );
 }
 
 /************************************************************************/
@@ -266,8 +263,8 @@ const char *PDSDataset::GetProjectionRef()
 {
     if( strlen(osProjection) > 0 )
         return osProjection;
-    else
-        return GDALPamDataset::GetProjectionRef();
+
+    return GDALPamDataset::GetProjectionRef();
 }
 
 /************************************************************************/
@@ -282,10 +279,8 @@ CPLErr PDSDataset::GetGeoTransform( double * padfTransform )
         memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
         return CE_None;
     }
-    else
-    {
-        return GDALPamDataset::GetGeoTransform( padfTransform );
-    }
+
+    return GDALPamDataset::GetGeoTransform( padfTransform );
 }
 
 /************************************************************************/
@@ -309,16 +304,11 @@ void PDSDataset::ParseSRS()
     //example:
     //MAP_SCALE   = 14.818 <KM/PIXEL>
     //added search for unit (only checks for CM, KM - defaults to Meters)
-    const char *value;
     //Georef parameters
-    double dfULXMap=0.5;
-    double dfULYMap = 0.5;
     double dfXDim = 1.0;
     double dfYDim = 1.0;
-    double xulcenter = 0.0;
-    double yulcenter = 0.0;
 
-    value = GetKeyword(osPrefix + "IMAGE_MAP_PROJECTION.MAP_SCALE");
+    const char *value = GetKeyword(osPrefix + "IMAGE_MAP_PROJECTION.MAP_SCALE");
     if (strlen(value) > 0 ) {
         dfXDim = CPLAtof(value);
         dfYDim = CPLAtof(value) * -1;
@@ -337,9 +327,9 @@ void PDSDataset::ParseSRS()
             //defaults to convert km to m
             dfXDim = dfXDim * 1000.0;
             dfYDim = dfYDim * 1000.0;
-        }            
+        }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Calculate upper left corner of pixel in meters from the         */
 /*      upper  left center pixel sample/line offsets.  It doesn't       */
@@ -350,28 +340,27 @@ void PDSDataset::ParseSRS()
 /*      see GDAL PDS page or mapping within ISIS3 source (USGS)         */
 /*      $ISIS3DATA/base/translations/pdsProjectionLineSampToXY.def      */
 /* -------------------------------------------------------------------- */
-   
+
     // defaults should be correct for what is documented in the PDS3 standard
-    double   dfSampleOffset_Shift;
-    double   dfLineOffset_Shift;
-    double   dfSampleOffset_Mult;
-    double   dfLineOffset_Mult;
 
-    /* See https://trac.osgeo.org/gdal/ticket/5941 for the history of the default */
+    // https://trac.osgeo.org/gdal/ticket/5941 has the history of the default
     /* value of PDS_SampleProjOffset_Shift and PDS_LineProjOffset_Shift */
-    dfSampleOffset_Shift = 
+    double dfSampleOffset_Shift =
         CPLAtof(CPLGetConfigOption( "PDS_SampleProjOffset_Shift", "0.5" ));
-    
-    dfLineOffset_Shift = 
+
+    const double dfLineOffset_Shift =
         CPLAtof(CPLGetConfigOption( "PDS_LineProjOffset_Shift", "0.5" ));
 
-    dfSampleOffset_Mult =
+    const double dfSampleOffset_Mult =
         CPLAtof(CPLGetConfigOption( "PDS_SampleProjOffset_Mult", "-1.0") );
 
-    dfLineOffset_Mult = 
+    const double dfLineOffset_Mult =
         CPLAtof( CPLGetConfigOption( "PDS_LineProjOffset_Mult", "1.0") );
 
     /***********   Grab LINE_PROJECTION_OFFSET ************/
+    double dfULYMap = 0.5;
+    double yulcenter = 0.0;
+
     value = GetKeyword(osPrefix + "IMAGE_MAP_PROJECTION.LINE_PROJECTION_OFFSET");
     if (strlen(value) > 0) {
         yulcenter = CPLAtof(value);
@@ -379,6 +368,9 @@ void PDSDataset::ParseSRS()
         //notice dfYDim is negative here which is why it is again negated here
     }
     /***********   Grab SAMPLE_PROJECTION_OFFSET ************/
+    double dfULXMap = 0.5;
+    double xulcenter = 0.0;
+
     value = GetKeyword(osPrefix + "IMAGE_MAP_PROJECTION.SAMPLE_PROJECTION_OFFSET");
     if( strlen(value) > 0 ) {
         xulcenter = CPLAtof(value);
@@ -388,50 +380,41 @@ void PDSDataset::ParseSRS()
 /* ==================================================================== */
 /*      Get the coordinate system.                                      */
 /* ==================================================================== */
-    int	bProjectionSet = TRUE;
-    double semi_major = 0.0;
-    double semi_minor = 0.0;
-    double iflattening = 0.0;
-    double center_lat = 0.0;
-    double center_lon = 0.0;
-    double first_std_parallel = 0.0;
-    double second_std_parallel = 0.0;
-    OGRSpatialReference oSRS;
 
     /***********  Grab TARGET_NAME  ************/
     /**** This is the planets name i.e. MARS ***/
     CPLString target_name = GetKeyword("TARGET_NAME");
     CleanString( target_name );
-     
+
     /**********   Grab MAP_PROJECTION_TYPE *****/
-    CPLString map_proj_name = 
+    CPLString map_proj_name =
         GetKeyword( osPrefix + "IMAGE_MAP_PROJECTION.MAP_PROJECTION_TYPE");
     CleanString( map_proj_name );
-     
+
     /******  Grab semi_major & convert to KM ******/
-    semi_major = 
+    const double semi_major =
         CPLAtof(GetKeyword( osPrefix + "IMAGE_MAP_PROJECTION.A_AXIS_RADIUS")) * 1000.0;
-    
+
     /******  Grab semi-minor & convert to KM ******/
-    semi_minor = 
+    const double semi_minor =
         CPLAtof(GetKeyword( osPrefix + "IMAGE_MAP_PROJECTION.C_AXIS_RADIUS")) * 1000.0;
 
     /***********   Grab CENTER_LAT ************/
-    center_lat = 
+    const double center_lat =
         CPLAtof(GetKeyword( osPrefix + "IMAGE_MAP_PROJECTION.CENTER_LATITUDE"));
 
     /***********   Grab CENTER_LON ************/
-    center_lon = 
+    const double center_lon =
         CPLAtof(GetKeyword( osPrefix + "IMAGE_MAP_PROJECTION.CENTER_LONGITUDE"));
 
     /**********   Grab 1st std parallel *******/
-    first_std_parallel = 
+    const double first_std_parallel =
         CPLAtof(GetKeyword( osPrefix + "IMAGE_MAP_PROJECTION.FIRST_STANDARD_PARALLEL"));
 
     /**********   Grab 2nd std parallel *******/
-    second_std_parallel = 
+    const double second_std_parallel =
         CPLAtof(GetKeyword( osPrefix + "IMAGE_MAP_PROJECTION.SECOND_STANDARD_PARALLEL"));
-     
+
     /*** grab  PROJECTION_LATITUDE_TYPE = "PLANETOCENTRIC" ****/
     // Need to further study how ocentric/ographic will effect the gdal library.
     // So far we will use this fact to define a sphere or ellipse for some projections
@@ -439,11 +422,11 @@ void PDSDataset::ParseSRS()
     char bIsGeographic = TRUE;
     value = GetKeyword(osPrefix + "IMAGE_MAP_PROJECTION.COORDINATE_SYSTEM_NAME");
     if (EQUAL( value, "PLANETOCENTRIC" ))
-        bIsGeographic = FALSE; 
+        bIsGeographic = FALSE;
 
 /**   Set oSRS projection and parameters --- all PDS supported types added if apparently supported in oSRS
       "AITOFF",  ** Not supported in GDAL??
-      "ALBERS", 
+      "ALBERS",
       "BONNE",
       "BRIESEMEISTER",   ** Not supported in GDAL??
       "CYLINDRICAL EQUAL AREA",
@@ -463,10 +446,13 @@ void PDSDataset::ParseSRS()
       "STEREOGRAPHIC",
       "TRANSVERSE MERCATOR",
       "VAN DER GRINTEN",     ** Not supported in GDAL??
-      "WERNER"     ** Not supported in GDAL?? 
-**/ 
+      "WERNER"     ** Not supported in GDAL??
+**/
     CPLDebug( "PDS","using projection %s\n\n", map_proj_name.c_str());
 
+    bool bProjectionSet = true;
+    OGRSpatialReference oSRS;
+
     if ((EQUAL( map_proj_name, "EQUIRECTANGULAR" )) ||
         (EQUAL( map_proj_name, "SIMPLE_CYLINDRICAL" )) ||
         (EQUAL( map_proj_name, "EQUIDISTANT" )) )  {
@@ -484,7 +470,7 @@ void PDSDataset::ParseSRS()
     } else if (EQUAL( map_proj_name, "TRANSVERSE_MERCATOR" )) {
         oSRS.SetTM ( center_lat, center_lon, 1, 0, 0 );
     } else if (EQUAL( map_proj_name, "LAMBERT_CONFORMAL_CONIC" )) {
-        oSRS.SetLCC ( first_std_parallel, second_std_parallel, 
+        oSRS.SetLCC ( first_std_parallel, second_std_parallel,
                       center_lat, center_lon, 0, 0 );
     } else if (EQUAL( map_proj_name, "LAMBERT_AZIMUTHAL_EQUAL_AREA" )) {
         oSRS.SetLAEA( center_lat, center_lon, 0, 0 );
@@ -493,89 +479,91 @@ void PDSDataset::ParseSRS()
     } else if (EQUAL( map_proj_name, "MOLLWEIDE" )) {
         oSRS.SetMollweide ( center_lon, 0, 0 );
     } else if (EQUAL( map_proj_name, "ALBERS" )) {
-        oSRS.SetACEA ( first_std_parallel, second_std_parallel, 
+        oSRS.SetACEA ( first_std_parallel, second_std_parallel,
                        center_lat, center_lon, 0, 0 );
     } else if (EQUAL( map_proj_name, "BONNE" )) {
         oSRS.SetBonne ( first_std_parallel, center_lon, 0, 0 );
     } else if (EQUAL( map_proj_name, "GNOMONIC" )) {
         oSRS.SetGnomonic ( center_lat, center_lon, 0, 0 );
-    } else if (EQUAL( map_proj_name, "OBLIQUE_CYLINDRICAL" )) { 
+    } else if (EQUAL( map_proj_name, "OBLIQUE_CYLINDRICAL" )) {
         // hope Swiss Oblique Cylindrical is the same
         oSRS.SetSOC ( center_lat, center_lon, 0, 0 );
     } else {
         CPLDebug( "PDS",
                   "Dataset projection %s is not supported. Continuing...",
                   map_proj_name.c_str() );
-        bProjectionSet = FALSE;
+        bProjectionSet = false;
     }
 
     if (bProjectionSet) {
         //Create projection name, i.e. MERCATOR MARS and set as ProjCS keyword
-        CPLString proj_target_name = map_proj_name + " " + target_name;
+        const CPLString proj_target_name = map_proj_name + " " + target_name;
         oSRS.SetProjCS(proj_target_name); //set ProjCS keyword
-     
+
         //The geographic/geocentric name will be the same basic name as the body name
         //'GCS' = Geographic/Geocentric Coordinate System
-        CPLString geog_name = "GCS_" + target_name;
-        
+        const CPLString geog_name = "GCS_" + target_name;
+
         //The datum and sphere names will be the same basic name aas the planet
-        CPLString datum_name = "D_" + target_name;
-        CPLString sphere_name = target_name; // + "_IAU_IAG");  //Might not be IAU defined so don't add
-          
+        const CPLString datum_name = "D_" + target_name;
+        // Might not be IAU defined so don't add.
+        CPLString sphere_name = target_name; // + "_IAU_IAG");
+
         //calculate inverse flattening from major and minor axis: 1/f = a/(a-b)
-        if ((semi_major - semi_minor) < 0.0000001) 
+        double iflattening;
+        if ((semi_major - semi_minor) < 0.0000001)
             iflattening = 0;
         else
             iflattening = semi_major / (semi_major - semi_minor);
-     
+
         //Set the body size but take into consideration which proj is being used to help w/ compatibility
-        //Notice that most PDS projections are spherical based on the fact that ISIS/PICS are spherical 
+        //Notice that most PDS projections are spherical based on the fact that ISIS/PICS are spherical
         //Set the body size but take into consideration which proj is being used to help w/ proj4 compatibility
         //The use of a Sphere, polar radius or ellipse here is based on how ISIS does it internally
-        if ( ( (EQUAL( map_proj_name, "STEREOGRAPHIC" ) && (fabs(center_lat) == 90)) ) || 
-             (EQUAL( map_proj_name, "POLAR_STEREOGRAPHIC" )))  
+        if ( ( (EQUAL( map_proj_name, "STEREOGRAPHIC" ) && (fabs(center_lat) == 90)) ) ||
+             (EQUAL( map_proj_name, "POLAR_STEREOGRAPHIC" )))
         {
-            if (bIsGeographic) { 
+            if (bIsGeographic) {
                 //Geograpraphic, so set an ellipse
                 oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                                semi_major, iflattening, 
+                                semi_major, iflattening,
                                 "Reference_Meridian", 0.0 );
             } else {
-                //Geocentric, so force a sphere using the semi-minor axis. I hope... 
+                //Geocentric, so force a sphere using the semi-minor axis. I hope...
                 sphere_name += "_polarRadius";
                 oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                                semi_minor, 0.0, 
+                                semi_minor, 0.0,
                                 "Reference_Meridian", 0.0 );
             }
         }
-        else if ( (EQUAL( map_proj_name, "SIMPLE_CYLINDRICAL" )) || 
-                  (EQUAL( map_proj_name, "EQUIDISTANT" )) || 
-                  (EQUAL( map_proj_name, "ORTHOGRAPHIC" )) || 
-                  (EQUAL( map_proj_name, "STEREOGRAPHIC" )) || 
+        else if ( (EQUAL( map_proj_name, "SIMPLE_CYLINDRICAL" )) ||
+                  (EQUAL( map_proj_name, "EQUIDISTANT" )) ||
+                  (EQUAL( map_proj_name, "ORTHOGRAPHIC" )) ||
+                  (EQUAL( map_proj_name, "STEREOGRAPHIC" )) ||
                   (EQUAL( map_proj_name, "SINUSOIDAL" )) ) {
             //isis uses the spherical equation for these projections so force a sphere
             oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                            semi_major, 0.0, 
+                            semi_major, 0.0,
                             "Reference_Meridian", 0.0 );
-        } 
-        else if (EQUAL( map_proj_name, "EQUIRECTANGULAR" )) { 
+        }
+        else if (EQUAL( map_proj_name, "EQUIRECTANGULAR" )) {
             //isis uses local radius as a sphere, which is pre-calculated in the PDS label as the semi-major
             sphere_name += "_localRadius";
             oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                            semi_major, 0.0, 
+                            semi_major, 0.0,
                             "Reference_Meridian", 0.0 );
-        } 
-        else { 
+        }
+        else {
             //All other projections: Mercator, Transverse Mercator, Lambert Conformal, etc.
             //Geographic, so set an ellipse
             if (bIsGeographic) {
                 oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                                semi_major, iflattening, 
+                                semi_major, iflattening,
                                 "Reference_Meridian", 0.0 );
-            } else { 
-                //Geocentric, so force a sphere. I hope... 
+            } else {
+                //Geocentric, so force a sphere. I hope...
                 oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                                semi_major, 0.0, 
+                                semi_major, 0.0,
                                 "Reference_Meridian", 0.0 );
             }
         }
@@ -591,27 +579,23 @@ void PDSDataset::ParseSRS()
 /*      Check for a .prj and world file to override the georeferencing. */
 /* ==================================================================== */
     {
-        CPLString osPath, osName;
-        VSILFILE *fp;
-
-        osPath = CPLGetPath( pszFilename );
-        osName = CPLGetBasename(pszFilename);
+        const CPLString osPath = CPLGetPath( pszFilename );
+        const CPLString osName = CPLGetBasename(pszFilename);
         const char  *pszPrjFile = CPLFormCIFilename( osPath, osName, "prj" );
 
-        fp = VSIFOpenL( pszPrjFile, "r" );
+        VSILFILE *fp = VSIFOpenL( pszPrjFile, "r" );
         if( fp != NULL )
         {
-            char	**papszLines;
-            OGRSpatialReference oSRS;
+            OGRSpatialReference oSRS2;
 
             VSIFCloseL( fp );
-        
-            papszLines = CSLLoad( pszPrjFile );
 
-            if( oSRS.importFromESRI( papszLines ) == OGRERR_NONE )
+            char **papszLines = CSLLoad( pszPrjFile );
+
+            if( oSRS2.importFromESRI( papszLines ) == OGRERR_NONE )
             {
                 char *pszResult = NULL;
-                oSRS.exportToWkt( &pszResult );
+                oSRS2.exportToWkt( &pszResult );
                 osProjection = pszResult;
                 CPLFree( pszResult );
             }
@@ -619,8 +603,8 @@ void PDSDataset::ParseSRS()
             CSLDestroy( papszLines );
         }
     }
-    
-    if( dfULYMap != 0.5 || dfULYMap != 0.5 || dfXDim != 1.0 || dfYDim != 1.0 )
+
+    if( dfULXMap != 0.5 || dfULYMap != 0.5 || dfXDim != 1.0 || dfYDim != 1.0 )
     {
         bGotTransform = TRUE;
         adfGeoTransform[0] = dfULXMap;
@@ -630,15 +614,15 @@ void PDSDataset::ParseSRS()
         adfGeoTransform[4] = 0.0;
         adfGeoTransform[5] = dfYDim;
     }
-    
+
     if( !bGotTransform )
-        bGotTransform = 
-            GDALReadWorldFile( pszFilename, "psw", 
+        bGotTransform =
+            GDALReadWorldFile( pszFilename, "psw",
                                adfGeoTransform );
 
     if( !bGotTransform )
-        bGotTransform = 
-            GDALReadWorldFile( pszFilename, "wld", 
+        bGotTransform =
+            GDALReadWorldFile( pszFilename, "wld",
                                adfGeoTransform );
 
 }
@@ -649,7 +633,7 @@ void PDSDataset::ParseSRS()
 
 static GUInt32 PDSConvertFromHex(const char* pszVal)
 {
-    if( !EQUALN(pszVal, "16#", 3) )
+    if( !STARTS_WITH_CI(pszVal, "16#") )
         return 0;
 
     pszVal += 3;
@@ -665,6 +649,7 @@ static GUInt32 PDSConvertFromHex(const char* pszVal)
             return 0;
         pszVal ++;
     }
+
     return nVal;
 }
 
@@ -675,7 +660,7 @@ static GUInt32 PDSConvertFromHex(const char* pszVal)
 int PDSDataset::ParseImage( CPLString osPrefix, CPLString osFilenamePrefix )
 {
 /* ------------------------------------------------------------------- */
-/*	We assume the user is pointing to the label (ie. .lbl) file.  	   */
+/*      We assume the user is pointing to the label (i.e. .lbl) file.  */
 /* ------------------------------------------------------------------- */
     // IMAGE can be inline or detached and point to an image name
     // ^IMAGE = 3
@@ -696,9 +681,9 @@ int PDSDataset::ParseImage( CPLString osPrefix, CPLString osFilenamePrefix )
         osQube = GetKeyword( osPrefix + "^" + osImageKeyword );
     }
 
-    int nQube = atoi(osQube);
+    const int nQube = atoi(osQube);
     int nDetachedOffset = 0;
-    int bDetachedOffsetInBytes = FALSE;
+    bool bDetachedOffsetInBytes = false;
 
     if( osQube.size() && osQube[0] == '(' )
     {
@@ -710,7 +695,7 @@ int PDSDataset::ParseImage( CPLString osPrefix, CPLString osFilenamePrefix )
         // If this is not explicitly in bytes, then it is assumed to be in
         // records, and we need to translate to bytes.
         if (strstr(GetKeywordSub(osPrefix + "^" + osImageKeyword, 2),"<BYTES>") != NULL)
-            bDetachedOffsetInBytes = TRUE;
+            bDetachedOffsetInBytes = true;
     }
 
     if( osQube.size() && osQube[0] == '"' )
@@ -728,42 +713,25 @@ int PDSDataset::ParseImage( CPLString osPrefix, CPLString osFilenamePrefix )
             osExternalCube = osTargetFile;
         }
     }
-    
-
-    GDALDataType eDataType = GDT_Byte;
 
-    
-    //image parameters
-    int	nRows, nCols, nBands = 1;
-    int nSkipBytes = 0;
-    int itype;
-    int record_bytes;
-    int nSuffixItems = 0, nSuffixLines = 0;
-    int nSuffixBytes = 4; // Default as per PDS specification 
-    char chByteOrder = 'M';  //default to MSB
-    double dfNoData = 0.0, dfScale = 1.0, dfOffset = 0.0;
-    const char *pszUnit = NULL, *pszDesc = NULL;
- 
     /* -------------------------------------------------------------------- */
     /*      Checks to see if this is raw PDS image not compressed image     */
     /*      so ENCODING_TYPE either does not exist or it equals "N/A".      */
     /*      Compressed types will not be supported in this routine          */
     /* -------------------------------------------------------------------- */
-    CPLString value;
 
     CPLString osEncodingType = GetKeyword(osPrefix+"IMAGE.ENCODING_TYPE","N/A");
     CleanString(osEncodingType);
     if ( !EQUAL(osEncodingType.c_str(),"N/A") )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "*** PDS image file has an ENCODING_TYPE parameter:\n"
                   "*** gdal pds driver does not support compressed image types\n"
                   "found: (%s)\n\n", osEncodingType.c_str() );
         return FALSE;
-    } 
+    }
     /**************** end ENCODING_TYPE check ***********************/
-    
-    
+
     /***********   Grab layout type (BSQ, BIP, BIL) ************/
     //  AXIS_NAME = (SAMPLE,LINE,BAND)
     /***********   Grab samples lines band        **************/
@@ -772,46 +740,49 @@ int PDSDataset::ParseImage( CPLString osPrefix, CPLString osFilenamePrefix )
     /** if not NULL then CORE_ITEMS keyword i.e. (234,322,2)  **/
     /***********************************************************/
     int eLayout = PDS_BSQ; //default to band seq.
-    value = GetKeyword( osPrefix+osImageKeyword+".AXIS_NAME", "" );
+    int	nRows, nCols, l_nBands = 1;
+
+    CPLString value = GetKeyword( osPrefix+osImageKeyword+".AXIS_NAME", "" );
     if (EQUAL(value,"(SAMPLE,LINE,BAND)") ) {
         eLayout = PDS_BSQ;
         nCols = atoi(GetKeywordSub(osPrefix+osImageKeyword+".CORE_ITEMS",1));
         nRows = atoi(GetKeywordSub(osPrefix+osImageKeyword+".CORE_ITEMS",2));
-        nBands = atoi(GetKeywordSub(osPrefix+osImageKeyword+".CORE_ITEMS",3));
+        l_nBands = atoi(GetKeywordSub(osPrefix+osImageKeyword+".CORE_ITEMS",3));
     }
     else if (EQUAL(value,"(BAND,LINE,SAMPLE)") ) {
         eLayout = PDS_BIP;
-        nBands = atoi(GetKeywordSub(osPrefix+osImageKeyword+".CORE_ITEMS",1));
+        l_nBands = atoi(GetKeywordSub(osPrefix+osImageKeyword+".CORE_ITEMS",1));
         nRows = atoi(GetKeywordSub(osPrefix+osImageKeyword+".CORE_ITEMS",2));
         nCols = atoi(GetKeywordSub(osPrefix+osImageKeyword+".CORE_ITEMS",3));
     }
     else if (EQUAL(value,"(SAMPLE,BAND,LINE)") ) {
         eLayout = PDS_BIL;
         nCols = atoi(GetKeywordSub(osPrefix+osImageKeyword+".CORE_ITEMS",1));
-        nBands = atoi(GetKeywordSub(osPrefix+osImageKeyword+".CORE_ITEMS",2));
+        l_nBands = atoi(GetKeywordSub(osPrefix+osImageKeyword+".CORE_ITEMS",2));
         nRows = atoi(GetKeywordSub(osPrefix+osImageKeyword+".CORE_ITEMS",3));
     }
     else if ( EQUAL(value,"") ) {
         eLayout = PDS_BSQ;
         nCols = atoi(GetKeyword(osPrefix+osImageKeyword+".LINE_SAMPLES",""));
         nRows = atoi(GetKeyword(osPrefix+osImageKeyword+".LINES",""));
-        nBands = atoi(GetKeyword(osPrefix+osImageKeyword+".BANDS","1"));
+        l_nBands = atoi(GetKeyword(osPrefix+osImageKeyword+".BANDS","1"));
     }
     else {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "%s layout not supported. Abort\n\n", value.c_str() );
         return FALSE;
     }
-    
+
     /***********   Grab Qube record bytes  **********/
-    record_bytes = atoi(GetKeyword(osPrefix+"IMAGE.RECORD_BYTES"));
+    int record_bytes = atoi(GetKeyword(osPrefix+"IMAGE.RECORD_BYTES"));
     if (record_bytes == 0)
         record_bytes = atoi(GetKeyword(osPrefix+"RECORD_BYTES"));
 
-    // this can happen with "record_type = undefined". 
+    // this can happen with "record_type = undefined".
     if( record_bytes == 0 )
         record_bytes = 1;
 
+    int nSkipBytes = 0;
     if( nQube >0 && osQube.find("<BYTES>") != CPLString::npos )
         nSkipBytes = nQube - 1;
     else if (nQube > 0 )
@@ -824,34 +795,45 @@ int PDSDataset::ParseImage( CPLString osPrefix, CPLString osFilenamePrefix )
             nSkipBytes = nDetachedOffset * record_bytes;
     }
     else
-        nSkipBytes = 0;     
+        nSkipBytes = 0;
 
     nSkipBytes += atoi(GetKeyword(osPrefix+"IMAGE.LINE_PREFIX_BYTES",""));
-    
+
     /***********   Grab SAMPLE_TYPE *****************/
     /** if keyword not found leave as "M" or "MSB" **/
+
     CPLString osST = GetKeyword( osPrefix+"IMAGE.SAMPLE_TYPE" );
     if( osST.size() >= 2 && osST[0] == '"' && osST[osST.size()-1] == '"' )
         osST = osST.substr( 1, osST.size() - 2 );
 
-    if( (EQUAL(osST,"LSB_INTEGER")) || 
+    char chByteOrder = 'M';  //default to MSB
+    if( (EQUAL(osST,"LSB_INTEGER")) ||
         (EQUAL(osST,"LSB")) || // just incase
-        (EQUAL(osST,"LSB_UNSIGNED_INTEGER")) || 
-        (EQUAL(osST,"LSB_SIGNED_INTEGER")) || 
-        (EQUAL(osST,"UNSIGNED_INTEGER")) || 
-        (EQUAL(osST,"VAX_REAL")) || 
-        (EQUAL(osST,"VAX_INTEGER")) || 
-        (EQUAL(osST,"PC_INTEGER")) ||  //just incase 
+        (EQUAL(osST,"LSB_UNSIGNED_INTEGER")) ||
+        (EQUAL(osST,"LSB_SIGNED_INTEGER")) ||
+        (EQUAL(osST,"UNSIGNED_INTEGER")) ||
+        (EQUAL(osST,"VAX_REAL")) ||
+        (EQUAL(osST,"VAX_INTEGER")) ||
+        (EQUAL(osST,"PC_INTEGER")) ||  //just incase
         (EQUAL(osST,"PC_REAL")) ) {
         chByteOrder = 'I';
     }
 
     /**** Grab format type - pds supports 1,2,4,8,16,32,64 (in theory) **/
     /**** I have only seen 8, 16, 32 (float) in released datasets      **/
+    GDALDataType eDataType = GDT_Byte;
+    int nSuffixItems = 0, nSuffixLines = 0;
+    int nSuffixBytes = 4; // Default as per PDS specification
+    double dfNoData = 0.0;
+    double dfScale = 1.0;
+    double dfOffset = 0.0;
+    const char *pszUnit = NULL;
+    const char *pszDesc = NULL;
+
     CPLString osSB = GetKeyword(osPrefix+"IMAGE.SAMPLE_BITS","");
     if ( osSB.size() > 0 )
     {
-        itype = atoi(osSB);
+        const int itype = atoi(osSB);
         switch(itype) {
           case 8 :
             eDataType = GDT_Byte;
@@ -880,7 +862,7 @@ int PDSDataset::ParseImage( CPLString osPrefix, CPLString osFilenamePrefix )
           default :
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Sample_bits of %d is not supported in this gdal PDS reader.",
-                      itype); 
+                      itype);
             return FALSE;
         }
 
@@ -890,7 +872,7 @@ int PDSDataset::ParseImage( CPLString osPrefix, CPLString osFilenamePrefix )
     else /* No IMAGE object, search for the QUBE. */
     {
         osSB = GetKeyword(osPrefix+"SPECTRAL_QUBE.CORE_ITEM_BYTES","");
-        itype = atoi(osSB);
+        const int itype = atoi(osSB);
         switch(itype) {
           case 1 :
             eDataType = GDT_Byte;
@@ -907,7 +889,7 @@ int PDSDataset::ParseImage( CPLString osPrefix, CPLString osFilenamePrefix )
           default :
             CPLError( CE_Failure, CPLE_AppDefined,
                       "CORE_ITEM_BYTES of %d is not supported in this gdal PDS reader.",
-                      itype); 
+                      itype);
             return FALSE;
         }
 
@@ -952,7 +934,7 @@ int PDSDataset::ParseImage( CPLString osPrefix, CPLString osFilenamePrefix )
             pszMissing ++;
 
         /* For example : MISSING_CONSTANT             = "16#FF7FFFFB#" */
-        if( EQUALN(pszMissing, "16#", 3) && strlen(pszMissing) >= 3 + 8 + 1 &&
+        if( STARTS_WITH_CI(pszMissing, "16#") && strlen(pszMissing) >= 3 + 8 + 1 &&
             pszMissing[3 + 8] == '#' && (eDataType == GDT_Float32 || eDataType == GDT_Float64) )
         {
             GUInt32 nVal = PDSConvertFromHex(pszMissing);
@@ -969,10 +951,10 @@ int PDSDataset::ParseImage( CPLString osPrefix, CPLString osFilenamePrefix )
 /*      this never having been considered to be a match. This isn't     */
 /*      an error!                                                       */
 /* -------------------------------------------------------------------- */
-    if( nRows < 1 || nCols < 1 || nBands < 1 )
+    if( nRows < 1 || nCols < 1 || l_nBands < 1 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "File %s appears to be a PDS file, but failed to find some required keywords.", 
+                  "File %s appears to be a PDS file, but failed to find some required keywords.",
                   GetDescription() );
         return FALSE;
     }
@@ -986,14 +968,14 @@ int PDSDataset::ParseImage( CPLString osPrefix, CPLString osFilenamePrefix )
 /* -------------------------------------------------------------------- */
 /*      Open target binary file.                                        */
 /* -------------------------------------------------------------------- */
-    
+
     if( eAccess == GA_ReadOnly )
     {
         fpImage = VSIFOpenL( osTargetFile, "rb" );
         if( fpImage == NULL )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
-                    "Failed to open %s.\n%s", 
+            CPLError( CE_Failure, CPLE_OpenFailed,
+                    "Failed to open %s.\n%s",
                     osTargetFile.c_str(),
                     VSIStrerror( errno ) );
             return FALSE;
@@ -1004,8 +986,8 @@ int PDSDataset::ParseImage( CPLString osPrefix, CPLString osFilenamePrefix )
         fpImage = VSIFOpenL( osTargetFile, "r+b" );
         if( fpImage == NULL )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
-                    "Failed to open %s with write permission.\n%s", 
+            CPLError( CE_Failure, CPLE_OpenFailed,
+                    "Failed to open %s with write permission.\n%s",
                     osTargetFile.c_str(),
                     VSIStrerror( errno ) );
             return FALSE;
@@ -1015,13 +997,14 @@ int PDSDataset::ParseImage( CPLString osPrefix, CPLString osFilenamePrefix )
 /* -------------------------------------------------------------------- */
 /*      Compute the line offset.                                        */
 /* -------------------------------------------------------------------- */
-    int     nItemSize = GDALGetDataTypeSize(eDataType)/8;
-    int     nLineOffset = record_bytes;
-    int	    nPixelOffset, nBandOffset;
+    const int nItemSize = GDALGetDataTypeSize(eDataType)/8;
+    int nLineOffset;
+    int nPixelOffset;
+    int nBandOffset;
 
     if( eLayout == PDS_BIP )
     {
-        nPixelOffset = nItemSize * nBands;
+        nPixelOffset = nItemSize * l_nBands;
         nBandOffset = nItemSize;
         nLineOffset = ((nPixelOffset * nCols + record_bytes - 1)/record_bytes)
             * record_bytes;
@@ -1041,28 +1024,24 @@ int PDSDataset::ParseImage( CPLString osPrefix, CPLString osFilenamePrefix )
         nLineOffset = ((nBandOffset * nCols + record_bytes - 1)/record_bytes)
             * record_bytes;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    int i;
-
-    for( i = 0; i < nBands; i++ )
+    for( int i = 0; i < l_nBands; i++ )
     {
-        RawRasterBand	*poBand;
-
-        poBand = 
+        RawRasterBand *poBand =
             new RawRasterBand( this, i+1, fpImage,
-                               nSkipBytes + nBandOffset * i, 
+                               nSkipBytes + nBandOffset * i,
                                nPixelOffset, nLineOffset, eDataType,
-#ifdef CPL_LSB                               
+#ifdef CPL_LSB
                                chByteOrder == 'I' || chByteOrder == 'L',
 #else
                                chByteOrder == 'M',
-#endif        
+#endif
                                TRUE );
 
-        if( nBands == 1 )
+        if( l_nBands == 1 )
         {
             const char* pszMin = GetKeyword(osPrefix+"IMAGE.MINIMUM", NULL);
             const char* pszMax = GetKeyword(osPrefix+"IMAGE.MAXIMUM", NULL);
@@ -1109,9 +1088,9 @@ class PDSWrapperRasterBand : public GDALProxyRasterBand
     virtual GDALRasterBand* RefUnderlyingRasterBand() { return poBaseBand; }
 
   public:
-    PDSWrapperRasterBand( GDALRasterBand* poBaseBand ) 
+    explicit PDSWrapperRasterBand( GDALRasterBand* poBaseBandIn )
         {
-            this->poBaseBand = poBaseBand;
+            this->poBaseBand = poBaseBandIn;
             eDataType = poBaseBand->GetRasterDataType();
             poBaseBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
         }
@@ -1128,23 +1107,23 @@ int PDSDataset::ParseCompressedImage()
     CPLString osFileName = GetKeyword( "COMPRESSED_FILE.FILE_NAME", "" );
     CleanString( osFileName );
 
-    CPLString osPath = CPLGetPath(GetDescription());
-    CPLString osFullFileName = CPLFormFilename( osPath, osFileName, NULL );
-    int iBand;
+    const CPLString osPath = CPLGetPath(GetDescription());
+    const CPLString osFullFileName = CPLFormFilename( osPath, osFileName, NULL );
+
+    poCompressedDS = reinterpret_cast<GDALDataset *>(
+        GDALOpen( osFullFileName, GA_ReadOnly ) );
 
-    poCompressedDS = (GDALDataset*) GDALOpen( osFullFileName, GA_ReadOnly );
-    
     if( poCompressedDS == NULL )
         return FALSE;
 
     nRasterXSize = poCompressedDS->GetRasterXSize();
     nRasterYSize = poCompressedDS->GetRasterYSize();
 
-    for( iBand = 0; iBand < poCompressedDS->GetRasterCount(); iBand++ )
+    for( int iBand = 0; iBand < poCompressedDS->GetRasterCount(); iBand++ )
     {
         SetBand( iBand+1, new PDSWrapperRasterBand( poCompressedDS->GetRasterBand( iBand+1 ) ) );
     }
-    
+
     return TRUE;
 }
 
@@ -1158,7 +1137,10 @@ int PDSDataset::Identify( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->pabyHeader == NULL )
         return FALSE;
 
-    return strstr((char*)poOpenInfo->pabyHeader,"PDS_VERSION_ID") != NULL;
+    return strstr(reinterpret_cast<char *>( poOpenInfo->pabyHeader ),
+                  "PDS_VERSION_ID") != NULL ||
+           strstr(reinterpret_cast<char *>( poOpenInfo->pabyHeader ),
+                  "ODL_VERSION_ID") != NULL;
 }
 
 /************************************************************************/
@@ -1170,7 +1152,9 @@ GDALDataset *PDSDataset::Open( GDALOpenInfo * poOpenInfo )
     if( !Identify( poOpenInfo ) )
         return NULL;
 
-    if( strstr((const char *)poOpenInfo->pabyHeader,"PDS3") == NULL )
+    if( strstr(reinterpret_cast<char *>( poOpenInfo->pabyHeader ),
+                  "PDS_VERSION_ID") != NULL &&
+        strstr((const char *)poOpenInfo->pabyHeader,"PDS3") == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
                   "It appears this is an older PDS image type.  Only PDS_VERSION_ID = PDS3 are currently supported by this gdal PDS reader.");
@@ -1186,16 +1170,14 @@ GDALDataset *PDSDataset::Open( GDALOpenInfo * poOpenInfo )
     if( fpQube == NULL )
         return NULL;
 
-    PDSDataset 	*poDS;
-
-    poDS = new PDSDataset();
+    PDSDataset *poDS = new PDSDataset();
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->eAccess = poOpenInfo->eAccess;
-    
+
     const char* pszPDSVersionID = strstr((const char *)poOpenInfo->pabyHeader,"PDS_VERSION_ID");
     int nOffset = 0;
     if (pszPDSVersionID)
-        nOffset = pszPDSVersionID - (const char *)poOpenInfo->pabyHeader;
+        nOffset = static_cast<int>(pszPDSVersionID - (const char *)poOpenInfo->pabyHeader);
 
     if( ! poDS->oKeywords.Ingest( fpQube, nOffset ) )
     {
@@ -1228,7 +1210,7 @@ GDALDataset *PDSDataset::Open( GDALOpenInfo * poOpenInfo )
         osCompressedFilename.size() != 0 &&
         osUncompressedFilename.size() != 0 )
     {
-        CPLString osPath = CPLGetPath(poDS->GetDescription());
+        const CPLString osPath = CPLGetPath(poDS->GetDescription());
         osCompressedFilename = CPLFormFilename( osPath, osCompressedFilename, NULL );
         osUncompressedFilename = CPLFormFilename( osPath, osUncompressedFilename, NULL );
         if( VSIStatExL(osCompressedFilename, &sStat, VSI_STAT_EXISTS_FLAG) == 0 &&
@@ -1254,7 +1236,7 @@ GDALDataset *PDSDataset::Open( GDALOpenInfo * poOpenInfo )
 
         if( osUncompressedFilename != "" )
             osPrefix = "UNCOMPRESSED_FILE.";
-        
+
         if( !poDS->ParseImage(osPrefix, osFilenamePrefix) )
         {
             delete poDS;
@@ -1270,16 +1252,15 @@ GDALDataset *PDSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Transfer a few interesting keywords as metadata.                */
 /* -------------------------------------------------------------------- */
-    int i;
-    static const char *apszKeywords[] = 
-        { "FILTER_NAME", "DATA_SET_ID", "PRODUCT_ID", 
+    static const char * const apszKeywords[] =
+        { "FILTER_NAME", "DATA_SET_ID", "PRODUCT_ID",
           "PRODUCER_INSTITUTION_NAME", "PRODUCT_TYPE", "MISSION_NAME",
-          "SPACECRAFT_NAME", "INSTRUMENT_NAME", "INSTRUMENT_ID", 
+          "SPACECRAFT_NAME", "INSTRUMENT_NAME", "INSTRUMENT_ID",
           "TARGET_NAME", "CENTER_FILTER_WAVELENGTH", "BANDWIDTH",
           "PRODUCT_CREATION_TIME", "NOTE",
           NULL };
-    
-    for( i = 0; apszKeywords[i] != NULL; i++ )
+
+    for( int i = 0; apszKeywords[i] != NULL; i++ )
     {
         const char *pszKeywordValue = poDS->GetKeyword( apszKeywords[i] );
 
@@ -1321,14 +1302,14 @@ const char *PDSDataset::GetKeywordSub( std::string osPath,
 
 {
     const char *pszResult = oKeywords.GetKeyword( osPath.c_str(), NULL );
-    
+
     if( pszResult == NULL )
         return pszDefault;
 
-    if( pszResult[0] != '(' ) 
+    if( pszResult[0] != '(' )
         return pszDefault;
 
-    char **papszTokens = CSLTokenizeString2( pszResult, "(,)", 
+    char **papszTokens = CSLTokenizeString2( pszResult, "(,)",
                                              CSLT_HONOURSTRINGS );
 
     if( iSubscript <= CSLCount(papszTokens) )
@@ -1337,28 +1318,26 @@ const char *PDSDataset::GetKeywordSub( std::string osPath,
         CSLDestroy( papszTokens );
         return osTempResult.c_str();
     }
-    else
-    {
-        CSLDestroy( papszTokens );
-        return pszDefault;
-    }
+
+    CSLDestroy( papszTokens );
+    return pszDefault;
 }
 
 /************************************************************************/
 /*                            GetKeywordUnit()                          */
 /************************************************************************/
 
-const char *PDSDataset::GetKeywordUnit( const char *pszPath, 
+const char *PDSDataset::GetKeywordUnit( const char *pszPath,
                                          int iSubscript,
                                          const char *pszDefault )
 
 {
     const char *pszResult = oKeywords.GetKeyword( pszPath, NULL );
-    
+
     if( pszResult == NULL )
         return pszDefault;
- 
-    char **papszTokens = CSLTokenizeString2( pszResult, "</>", 
+
+    char **papszTokens = CSLTokenizeString2( pszResult, "</>",
                                              CSLT_HONOURSTRINGS );
 
     if( iSubscript <= CSLCount(papszTokens) )
@@ -1367,11 +1346,9 @@ const char *PDSDataset::GetKeywordUnit( const char *pszPath,
         CSLDestroy( papszTokens );
         return osTempResult.c_str();
     }
-    else
-    {
-        CSLDestroy( papszTokens );
-        return pszDefault;
-    }
+
+    CSLDestroy( papszTokens );
+    return pszDefault;
 }
 
 /************************************************************************/
@@ -1390,11 +1367,10 @@ void PDSDataset::CleanString( CPLString &osInput )
         return;
 
     char *pszWrk = CPLStrdup(osInput.c_str() + 1);
-    int i;
 
     pszWrk[strlen(pszWrk)-1] = '\0';
-    
-    for( i = 0; pszWrk[i] != '\0'; i++ )
+
+    for( int i = 0; pszWrk[i] != '\0'; i++ )
     {
         if( pszWrk[i] == ' ' )
             pszWrk[i] = '_';
@@ -1404,30 +1380,27 @@ void PDSDataset::CleanString( CPLString &osInput )
     CPLFree( pszWrk );
 }
 /************************************************************************/
-/*                         GDALRegister_PDS()                         */
+/*                         GDALRegister_PDS()                           */
 /************************************************************************/
 
 void GDALRegister_PDS()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "PDS" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "PDS" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "PDS" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "NASA Planetary Data System" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_pds.html" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = PDSDataset::Open;
-        poDriver->pfnIdentify = PDSDataset::Identify;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
-}
+    GDALDriver *poDriver = new GDALDriver();
 
+    poDriver->SetDescription( "PDS" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "NASA Planetary Data System" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_pds.html" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = PDSDataset::Open;
+    poDriver->pfnIdentify = PDSDataset::Identify;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/frmts/pds/vicardataset.cpp b/frmts/pds/vicardataset.cpp
index a0b725e..2ddc557 100644
--- a/frmts/pds/vicardataset.cpp
+++ b/frmts/pds/vicardataset.cpp
@@ -1,14 +1,14 @@
 /******************************************************************************
- * 
+ *
  * Project:  VICAR Driver; JPL/MIPL VICAR Format
  * Purpose:  Implementation of VICARDataset
  * Author:   Sebastian Walter <sebastian dot walter at fu-berlin dot de>
  *
  * NOTE: This driver code is loosely based on the ISIS and PDS drivers.
- * It is not intended to diminish the contribution of the original authors 
+ * It is not intended to diminish the contribution of the original authors
  ******************************************************************************
  * Copyright (c) 2014, Sebastian Walter <sebastian dot walter at fu-berlin dot de>
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * to deal in the Software without restriction, including without limitation
@@ -28,26 +28,19 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#define NULL1 0
-#define NULL2 -32768
-#define NULL3 -32768.
-
-#ifndef PI
-#  define PI 3.1415926535897932384626433832795
-#endif
+static const int NULL1 = 0;
+static const int NULL2 = -32768;
+static const double NULL3 = -32768.0;
 
-#include "rawdataset.h"
+#include "cpl_string.h"
+#include "gdal_frmts.h"
 #include "ogr_spatialref.h"
-#include "cpl_string.h" 
+#include "rawdataset.h"
 #include "vicarkeywordhandler.h"
 
 #include <string>
 
-CPL_CVSID("$Id: vicardataset.cpp 31757 2015-11-25 13:54:13Z rouault $");
-
-CPL_C_START
-void GDALRegister_VICAR(void);
-CPL_C_END
+CPL_CVSID("$Id: vicardataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -61,24 +54,24 @@ class VICARDataset : public RawDataset
 
     GByte	abyHeader[10000];
     CPLString   osExternalCube;
-    
+
     VICARKeywordHandler  oKeywords;
-  
+
     int         bGotTransform;
     double      adfGeoTransform[6];
-  
+
     CPLString   osProjection;
 
-    const char *GetKeyword( const char *pszPath, 
+    const char *GetKeyword( const char *pszPath,
                             const char *pszDefault = "");
-    
+
 public:
     VICARDataset();
     ~VICARDataset();
-  
+
     virtual CPLErr GetGeoTransform( double * padfTransform );
     virtual const char *GetProjectionRef(void);
-  
+
     virtual char **GetFileList();
 
     static int          Identify( GDALOpenInfo * );
@@ -89,16 +82,14 @@ public:
 
 };
 
-
-
 /************************************************************************/
 /*                            VICARDataset()                            */
 /************************************************************************/
 
-VICARDataset::VICARDataset()
+VICARDataset::VICARDataset() :
+    fpImage(NULL),
+    bGotTransform(FALSE)
 {
-    fpImage = NULL;
-    bGotTransform = FALSE;
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
@@ -126,9 +117,7 @@ VICARDataset::~VICARDataset()
 char **VICARDataset::GetFileList()
 
 {
-    char **papszFileList = NULL;
-
-    papszFileList = GDALPamDataset::GetFileList();
+    char **papszFileList = GDALPamDataset::GetFileList();
 
     if( strlen(osExternalCube) > 0 )
         papszFileList = CSLAddString( papszFileList, osExternalCube );
@@ -145,8 +134,8 @@ const char *VICARDataset::GetProjectionRef()
 {
     if( strlen(osProjection) > 0 )
         return osProjection;
-    else
-        return GDALPamDataset::GetProjectionRef();
+
+    return GDALPamDataset::GetProjectionRef();
 }
 
 /************************************************************************/
@@ -161,10 +150,8 @@ CPLErr VICARDataset::GetGeoTransform( double * padfTransform )
         memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
         return CE_None;
     }
-    else
-    {
-        return GDALPamDataset::GetGeoTransform( padfTransform );
-    }
+
+    return GDALPamDataset::GetGeoTransform( padfTransform );
 }
 
 /************************************************************************/
@@ -177,11 +164,12 @@ int VICARDataset::Identify( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->pabyHeader == NULL )
         return FALSE;
 
-    return strstr((char*)poOpenInfo->pabyHeader,"LBLSIZE") != NULL &&
-           strstr((char*)poOpenInfo->pabyHeader,"FORMAT") != NULL &&
-           strstr((char*)poOpenInfo->pabyHeader,"NL") != NULL &&
-           strstr((char*)poOpenInfo->pabyHeader,"NS") != NULL &&
-           strstr((char*)poOpenInfo->pabyHeader,"NB") != NULL;
+    return
+        strstr(reinterpret_cast<char *>( poOpenInfo->pabyHeader ), "LBLSIZE" ) != NULL &&
+        strstr(reinterpret_cast<char *>( poOpenInfo->pabyHeader ), "FORMAT" ) != NULL &&
+        strstr(reinterpret_cast<char *>( poOpenInfo->pabyHeader ), "NL" ) != NULL &&
+        strstr(reinterpret_cast<char *>( poOpenInfo->pabyHeader ), "NS" ) != NULL &&
+        strstr(reinterpret_cast<char *>( poOpenInfo->pabyHeader ), "NB" ) != NULL;
 }
 
 /************************************************************************/
@@ -204,83 +192,73 @@ GDALDataset *VICARDataset::Open( GDALOpenInfo * poOpenInfo )
     if( fpQube == NULL )
         return NULL;
 
-    VICARDataset 	*poDS;
-
-    poDS = new VICARDataset();
+    VICARDataset *poDS = new VICARDataset();
     if( ! poDS->oKeywords.Ingest( fpQube, poOpenInfo->pabyHeader ) ) {
         VSIFCloseL( fpQube );
         delete poDS;
         return NULL;
     }
-    
-    VSIFCloseL( fpQube );
 
-    CPLString osQubeFile;
-    osQubeFile = poOpenInfo->pszFilename;
-    GDALDataType eDataType = GDT_Byte;
+    VSIFCloseL( fpQube );
 
-    int	nRows = -1;
-    int nCols = -1;
-    int nBands = 1;
-    int nSkipBytes = 0;
-    int bIsDTM = FALSE;
-    char chByteOrder = 'M';
-    double dfNoData = 0.0;
-    const char *value;
-    
     /***** CHECK ENDIANNESS **************/
-    
-    value = poDS->GetKeyword( "INTFMT" );
+
+    const char *value = poDS->GetKeyword( "INTFMT" );
     if (!EQUAL(value,"LOW") ) {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "%s layout not supported. Abort\n\n", value);
-        return FALSE;
+        delete poDS;
+        return NULL;
     }
     value = poDS->GetKeyword( "REALFMT" );
     if (!EQUAL(value,"RIEEE") ) {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "%s layout not supported. Abort\n\n", value);
-        return FALSE;
+        delete poDS;
+        return NULL;
     }
+
+    char chByteOrder = 'M';
     value = poDS->GetKeyword( "BREALFMT" );
     if (EQUAL(value,"VAX") ) {
         chByteOrder = 'I';
     }
-    
+
     /************ CHECK INSTRUMENT *****************/
     /************ ONLY HRSC TESTED *****************/
-    
+
+    bool bIsDTM = false;
     value = poDS->GetKeyword( "DTM.DTM_OFFSET" );
     if (!EQUAL(value,"") ) {
-        bIsDTM = TRUE;
+        bIsDTM = true;
     }
-    
-    
+
     value = poDS->GetKeyword( "BLTYPE" );
-    if (!EQUAL(value,"M94_HRSC") && bIsDTM==FALSE ) {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+    if (!EQUAL(value,"M94_HRSC") && !bIsDTM ) {
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "%s instrument not tested. Continue with caution!\n\n", value);
     }
-    
+
     /***********   Grab layout type (BSQ, BIP, BIL) ************/
-    
+
     char szLayout[10] = "BSQ"; //default to band seq.
     value = poDS->GetKeyword( "ORG" );
-    if (EQUAL(value,"BSQ") ) {
-        strcpy(szLayout,"BSQ");
-        nCols = atoi(poDS->GetKeyword("NS"));
-        nRows = atoi(poDS->GetKeyword("NL"));
-        nBands = atoi(poDS->GetKeyword("NB"));
-    }
-    else {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+    if (!EQUAL(value,"BSQ") )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "%s layout not supported. Abort\n\n", value);
-        return FALSE;
+        delete poDS;
+        return NULL;
     }
-    
+
+    strcpy(szLayout,"BSQ");
+    const int nCols = atoi(poDS->GetKeyword("NS"));
+    const int nRows = atoi(poDS->GetKeyword("NL"));
+    const int nBands = atoi(poDS->GetKeyword("NB"));
+
     /***********   Grab record bytes  **********/
-    nSkipBytes = atoi(poDS->GetKeyword("NBB"));
-    
+    GDALDataType eDataType = GDT_Byte;
+    double dfNoData = 0.0;
     if (EQUAL( poDS->GetKeyword( "FORMAT" ), "BYTE" )) {
         eDataType = GDT_Byte;
         dfNoData = NULL1;
@@ -293,14 +271,15 @@ GDALDataset *VICARDataset::Open( GDALOpenInfo * poOpenInfo )
     else if (EQUAL( poDS->GetKeyword( "FORMAT" ), "FULL" )) {
         eDataType = GDT_UInt32;
         dfNoData = 0;
-    } 
+    }
     else if (EQUAL( poDS->GetKeyword( "FORMAT" ), "REAL" )) {
         eDataType = GDT_Float32;
         dfNoData = NULL3;
         chByteOrder = 'I';
     }
     else {
-	    printf("Could not find known VICAR label entries!\n");
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Could not find known VICAR label entries!\n");
         delete poDS;
         return NULL;
     }
@@ -308,9 +287,11 @@ GDALDataset *VICARDataset::Open( GDALOpenInfo * poOpenInfo )
     if( nRows < 1 || nCols < 1 || nBands < 1 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "File %s appears to be a VICAR file, but failed to find some required keywords.", 
+                  "File %s appears to be a VICAR file, but failed to find some "
+                  "required keywords.",
                   poDS->GetDescription() );
-        return FALSE;
+        delete poDS;
+        return NULL;
     }
 /* -------------------------------------------------------------------- */
 /*      Capture some information from the file that is of interest.     */
@@ -318,108 +299,95 @@ GDALDataset *VICARDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->nRasterXSize = nCols;
     poDS->nRasterYSize = nRows;
 
-    double dfULXMap=0.5;
-    double dfULYMap = 0.5;
     double dfXDim = 1.0;
     double dfYDim = 1.0;
-    double xulcenter = 0.0;
-    double yulcenter = 0.0;
 
     value = poDS->GetKeyword("MAP.MAP_SCALE");
     if (strlen(value) > 0 ) {
-        dfXDim = CPLAtof(value);
-        dfYDim = CPLAtof(value) * -1;
-        dfXDim = dfXDim * 1000.0;
-        dfYDim = dfYDim * 1000.0;
+        dfXDim = CPLAtof(value) * 1000.0;
+        dfYDim = CPLAtof(value) * -1 * 1000.0;
     }
 
-    double   dfSampleOffset_Shift;
-    double   dfLineOffset_Shift;
-    double   dfSampleOffset_Mult;
-    double   dfLineOffset_Mult;
-    
-    dfSampleOffset_Shift = 
+    const double dfSampleOffset_Shift =
         CPLAtof(CPLGetConfigOption( "PDS_SampleProjOffset_Shift", "0.5" ));
-    
-    dfLineOffset_Shift = 
+
+    const double dfLineOffset_Shift =
         CPLAtof(CPLGetConfigOption( "PDS_LineProjOffset_Shift", "0.5" ));
 
-    dfSampleOffset_Mult =
+    const double dfSampleOffset_Mult =
         CPLAtof(CPLGetConfigOption( "PDS_SampleProjOffset_Mult", "-1.0") );
 
-    dfLineOffset_Mult = 
+    const double dfLineOffset_Mult =
         CPLAtof( CPLGetConfigOption( "PDS_LineProjOffset_Mult", "1.0") );
 
     /***********   Grab LINE_PROJECTION_OFFSET ************/
+    double yulcenter = 0.0;
+    double dfULYMap = 0.5;
+
     value = poDS->GetKeyword("MAP.LINE_PROJECTION_OFFSET");
     if (strlen(value) > 0) {
         yulcenter = CPLAtof(value);
         dfULYMap = ((yulcenter + dfLineOffset_Shift) * -dfYDim * dfLineOffset_Mult);
     }
     /***********   Grab SAMPLE_PROJECTION_OFFSET ************/
+    double xulcenter = 0.0;
+    double dfULXMap=0.5;
+
     value = poDS->GetKeyword("MAP.SAMPLE_PROJECTION_OFFSET");
     if( strlen(value) > 0 ) {
         xulcenter = CPLAtof(value);
         dfULXMap = ((xulcenter + dfSampleOffset_Shift) * dfXDim * dfSampleOffset_Mult);
     }
-    
+
 /* ==================================================================== */
 /*      Get the coordinate system.                                      */
 /* ==================================================================== */
-    int	bProjectionSet = TRUE;
-    double semi_major = 0.0;
-    double semi_minor = 0.0;
-    double iflattening = 0.0;
-    double center_lat = 0.0;
-    double center_lon = 0.0;
-    double first_std_parallel = 0.0;
-    double second_std_parallel = 0.0;    
-    OGRSpatialReference oSRS;
-    
+    bool bProjectionSet = true;
+
     /***********  Grab TARGET_NAME  ************/
     /**** This is the planets name i.e. MARS ***/
-    CPLString target_name = poDS->GetKeyword("MAP.TARGET_NAME");
-     
+    const CPLString target_name = poDS->GetKeyword("MAP.TARGET_NAME");
+
     /**********   Grab MAP_PROJECTION_TYPE *****/
-    CPLString map_proj_name = 
-        poDS->GetKeyword( "MAP.MAP_PROJECTION_TYPE");
-     
+    const CPLString map_proj_name
+        = poDS->GetKeyword( "MAP.MAP_PROJECTION_TYPE");
+
     /******  Grab semi_major & convert to KM ******/
-    semi_major = 
-        CPLAtof(poDS->GetKeyword( "MAP.A_AXIS_RADIUS")) * 1000.0;
-    
+    const double semi_major
+        = CPLAtof(poDS->GetKeyword( "MAP.A_AXIS_RADIUS")) * 1000.0;
+
     /******  Grab semi-minor & convert to KM ******/
-    semi_minor = 
-        CPLAtof(poDS->GetKeyword( "MAP.C_AXIS_RADIUS")) * 1000.0;
+    const double semi_minor
+        = CPLAtof(poDS->GetKeyword( "MAP.C_AXIS_RADIUS")) * 1000.0;
 
     /***********   Grab CENTER_LAT ************/
-    center_lat = 
+    const double center_lat =
         CPLAtof(poDS->GetKeyword( "MAP.CENTER_LATITUDE"));
 
     /***********   Grab CENTER_LON ************/
-    center_lon = 
-        CPLAtof(poDS->GetKeyword( "MAP.CENTER_LONGITUDE"));
+    const double center_lon
+        = CPLAtof(poDS->GetKeyword( "MAP.CENTER_LONGITUDE"));
 
     /**********   Grab 1st std parallel *******/
-    first_std_parallel = 
+    const double first_std_parallel =
         CPLAtof(poDS->GetKeyword( "MAP.FIRST_STANDARD_PARALLEL"));
 
     /**********   Grab 2nd std parallel *******/
-    second_std_parallel = 
+    const double second_std_parallel =
         CPLAtof(poDS->GetKeyword( "MAP.SECOND_STANDARD_PARALLEL"));
-     
+
     /*** grab  PROJECTION_LATITUDE_TYPE = "PLANETOCENTRIC" ****/
     // Need to further study how ocentric/ographic will effect the gdal library.
     // So far we will use this fact to define a sphere or ellipse for some projections
     // Frank - may need to talk this over
-    char bIsGeographic = TRUE;
+    bool bIsGeographic = true;
     value = poDS->GetKeyword("MAP.COORDINATE_SYSTEM_NAME");
     if (EQUAL( value, "PLANETOCENTRIC" ))
-        bIsGeographic = FALSE; 
+        bIsGeographic = false;
 
 /**   Set oSRS projection and parameters --- all PDS supported types added if apparently supported in oSRS
       "AITOFF",  ** Not supported in GDAL??
-      "ALBERS", 
+      "ALBERS",
       "BONNE",
       "BRIESEMEISTER",   ** Not supported in GDAL??
       "CYLINDRICAL EQUAL AREA",
@@ -439,9 +407,11 @@ GDALDataset *VICARDataset::Open( GDALOpenInfo * poOpenInfo )
       "STEREOGRAPHIC",
       "TRANSVERSE MERCATOR",
       "VAN DER GRINTEN",     ** Not supported in GDAL??
-      "WERNER"     ** Not supported in GDAL?? 
-**/ 
-    CPLDebug( "PDS","using projection %s\n\n", map_proj_name.c_str());
+      "WERNER"     ** Not supported in GDAL??
+**/
+    CPLDebug( "PDS", "using projection %s\n\n", map_proj_name.c_str());
+
+    OGRSpatialReference oSRS;
 
     if ((EQUAL( map_proj_name, "EQUIRECTANGULAR" )) ||
         (EQUAL( map_proj_name, "SIMPLE_CYLINDRICAL" )) ||
@@ -460,7 +430,7 @@ GDALDataset *VICARDataset::Open( GDALOpenInfo * poOpenInfo )
     } else if (EQUAL( map_proj_name, "TRANSVERSE_MERCATOR" )) {
         oSRS.SetTM ( center_lat, center_lon, 1, 0, 0 );
     } else if (EQUAL( map_proj_name, "LAMBERT_CONFORMAL_CONIC" )) {
-        oSRS.SetLCC ( first_std_parallel, second_std_parallel, 
+        oSRS.SetLCC ( first_std_parallel, second_std_parallel,
                       center_lat, center_lon, 0, 0 );
     } else if (EQUAL( map_proj_name, "LAMBERT_AZIMUTHAL_EQUAL_AREA" )) {
         oSRS.SetLAEA( center_lat, center_lon, 0, 0 );
@@ -469,89 +439,93 @@ GDALDataset *VICARDataset::Open( GDALOpenInfo * poOpenInfo )
     } else if (EQUAL( map_proj_name, "MOLLWEIDE" )) {
         oSRS.SetMollweide ( center_lon, 0, 0 );
     } else if (EQUAL( map_proj_name, "ALBERS" )) {
-        oSRS.SetACEA ( first_std_parallel, second_std_parallel, 
+        oSRS.SetACEA ( first_std_parallel, second_std_parallel,
                        center_lat, center_lon, 0, 0 );
     } else if (EQUAL( map_proj_name, "BONNE" )) {
         oSRS.SetBonne ( first_std_parallel, center_lon, 0, 0 );
     } else if (EQUAL( map_proj_name, "GNOMONIC" )) {
         oSRS.SetGnomonic ( center_lat, center_lon, 0, 0 );
-    } else if (EQUAL( map_proj_name, "OBLIQUE_CYLINDRICAL" )) { 
+    } else if (EQUAL( map_proj_name, "OBLIQUE_CYLINDRICAL" )) {
         // hope Swiss Oblique Cylindrical is the same
         oSRS.SetSOC ( center_lat, center_lon, 0, 0 );
     } else {
         CPLDebug( "VICAR",
                   "Dataset projection %s is not supported. Continuing...",
                   map_proj_name.c_str() );
-        bProjectionSet = FALSE;
+        bProjectionSet = false;
     }
 
     if (bProjectionSet) {
         //Create projection name, i.e. MERCATOR MARS and set as ProjCS keyword
-        CPLString proj_target_name = map_proj_name + " " + target_name;
+        const CPLString proj_target_name = map_proj_name + " " + target_name;
         oSRS.SetProjCS(proj_target_name); //set ProjCS keyword
-     
+
         //The geographic/geocentric name will be the same basic name as the body name
         //'GCS' = Geographic/Geocentric Coordinate System
-        CPLString geog_name = "GCS_" + target_name;
-        
+        const CPLString geog_name = "GCS_" + target_name;
+
         //The datum and sphere names will be the same basic name aas the planet
-        CPLString datum_name = "D_" + target_name;
+        const CPLString datum_name = "D_" + target_name;
         CPLString sphere_name = target_name; // + "_IAU_IAG");  //Might not be IAU defined so don't add
-          
+
         //calculate inverse flattening from major and minor axis: 1/f = a/(a-b)
-        if ((semi_major - semi_minor) < 0.0000001) 
+        double iflattening = 0.0;
+        if ((semi_major - semi_minor) < 0.0000001)
             iflattening = 0;
         else
             iflattening = semi_major / (semi_major - semi_minor);
-     
+
         //Set the body size but take into consideration which proj is being used to help w/ compatibility
-        //Notice that most PDS projections are spherical based on the fact that ISIS/PICS are spherical 
+        //Notice that most PDS projections are spherical based on the fact that ISIS/PICS are spherical
         //Set the body size but take into consideration which proj is being used to help w/ proj4 compatibility
         //The use of a Sphere, polar radius or ellipse here is based on how ISIS does it internally
-        if ( ( (EQUAL( map_proj_name, "STEREOGRAPHIC" ) && (fabs(center_lat) == 90)) ) || 
-             (EQUAL( map_proj_name, "POLAR_STEREOGRAPHIC" )))  
+        if ( ( (EQUAL( map_proj_name, "STEREOGRAPHIC" ) && (fabs(center_lat) == 90)) ) ||
+             (EQUAL( map_proj_name, "POLAR_STEREOGRAPHIC" )))
         {
-            if (bIsGeographic) { 
+            if (bIsGeographic) {
                 //Geograpraphic, so set an ellipse
                 oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                                semi_major, iflattening, 
+                                semi_major, iflattening,
                                 "Reference_Meridian", 0.0 );
             } else {
-                //Geocentric, so force a sphere using the semi-minor axis. I hope... 
+                //Geocentric, so force a sphere using the semi-minor axis. I hope...
                 sphere_name += "_polarRadius";
                 oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                                semi_minor, 0.0, 
+                                semi_minor, 0.0,
                                 "Reference_Meridian", 0.0 );
             }
         }
-        else if ( (EQUAL( map_proj_name, "SIMPLE_CYLINDRICAL" )) || 
-                  (EQUAL( map_proj_name, "EQUIDISTANT" )) || 
-                  (EQUAL( map_proj_name, "ORTHOGRAPHIC" )) || 
-                  (EQUAL( map_proj_name, "STEREOGRAPHIC" )) || 
+        else if ( (EQUAL( map_proj_name, "SIMPLE_CYLINDRICAL" )) ||
+                  (EQUAL( map_proj_name, "EQUIDISTANT" )) ||
+                  (EQUAL( map_proj_name, "ORTHOGRAPHIC" )) ||
+                  (EQUAL( map_proj_name, "STEREOGRAPHIC" )) ||
                   (EQUAL( map_proj_name, "SINUSOIDAL" )) ) {
             //isis uses the spherical equation for these projections so force a sphere
             oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                            semi_major, 0.0, 
+                            semi_major, 0.0,
                             "Reference_Meridian", 0.0 );
-        } 
-        else if (EQUAL( map_proj_name, "EQUIRECTANGULAR" )) { 
+        }
+        else if (EQUAL( map_proj_name, "EQUIRECTANGULAR" )) {
             //isis uses local radius as a sphere, which is pre-calculated in the PDS label as the semi-major
             sphere_name += "_localRadius";
             oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                            semi_major, 0.0, 
+                            semi_major, 0.0,
                             "Reference_Meridian", 0.0 );
-        } 
-        else { 
+        }
+        else
+        {
             //All other projections: Mercator, Transverse Mercator, Lambert Conformal, etc.
             //Geographic, so set an ellipse
             if (bIsGeographic) {
                 oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                                semi_major, iflattening, 
+                                semi_major, iflattening,
                                 "Reference_Meridian", 0.0 );
-            } else { 
-                //Geocentric, so force a sphere. I hope... 
+            }
+            else
+            {
+                //Geocentric, so force a sphere. I hope...
                 oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                                semi_major, 0.0, 
+                                semi_major, 0.0,
                                 "Reference_Meridian", 0.0 );
             }
         }
@@ -571,18 +545,18 @@ GDALDataset *VICARDataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->adfGeoTransform[4] = 0.0;
         poDS->adfGeoTransform[5] = dfYDim;
     }
-    
+
+    const CPLString osQubeFile = poOpenInfo->pszFilename;
     if( !poDS->bGotTransform )
-        poDS->bGotTransform = 
-            GDALReadWorldFile( osQubeFile, "psw", 
+        poDS->bGotTransform =
+            GDALReadWorldFile( osQubeFile, "psw",
                                poDS->adfGeoTransform );
 
     if( !poDS->bGotTransform )
-        poDS->bGotTransform = 
-            GDALReadWorldFile( osQubeFile, "wld", 
+        poDS->bGotTransform =
+            GDALReadWorldFile( osQubeFile, "wld",
                                poDS->adfGeoTransform );
 
-
 /* -------------------------------------------------------------------- */
 /*      Open target binary file.                                        */
 /* -------------------------------------------------------------------- */
@@ -593,8 +567,8 @@ GDALDataset *VICARDataset::Open( GDALOpenInfo * poOpenInfo )
 
     if( poDS->fpImage == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Failed to open %s with write permission.\n%s", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to open %s with write permission.\n%s",
                   osQubeFile.c_str(),
                   VSIStrerror( errno ) );
         delete poDS;
@@ -607,26 +581,22 @@ GDALDataset *VICARDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Compute the line offsets.                                        */
 /* -------------------------------------------------------------------- */
 
-    long int        nItemSize = GDALGetDataTypeSize(eDataType)/8;
-    long int	    nLineOffset=0, nPixelOffset=0, nBandOffset=0;
-    nPixelOffset = nItemSize;
-    nLineOffset = nPixelOffset * nCols + atoi(poDS->GetKeyword("NBB")) ;
-    nBandOffset = nLineOffset * nRows;
+    const long int nItemSize = GDALGetDataTypeSize(eDataType)/8;
+    const long int nPixelOffset = nItemSize;
+    const long int nLineOffset = nPixelOffset * nCols + atoi(poDS->GetKeyword("NBB")) ;
+    const long int nBandOffset = nLineOffset * nRows;
 
-    nSkipBytes = atoi(poDS->GetKeyword("LBLSIZE"));
+    int nSkipBytes = atoi(poDS->GetKeyword("LBLSIZE"));
 
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    int i;
-
-    for( i = 0; i < nBands; i++ )
+    for( int i = 0; i < nBands; i++ )
     {
-        GDALRasterBand	*poBand;
-
-        poBand = new RawRasterBand( poDS, i+1, poDS->fpImage, nSkipBytes + nBandOffset * i, 
-                                   nPixelOffset, nLineOffset, eDataType,
-#ifdef CPL_LSB                               
+        GDALRasterBand	*poBand
+            = new RawRasterBand( poDS, i+1, poDS->fpImage, nSkipBytes + nBandOffset * i,
+                                 static_cast<int>(nPixelOffset), static_cast<int>(nLineOffset), eDataType,
+#ifdef CPL_LSB
                                    chByteOrder == 'I' || chByteOrder == 'L',
 #else
                                    chByteOrder == 'M',
@@ -635,9 +605,11 @@ GDALDataset *VICARDataset::Open( GDALOpenInfo * poOpenInfo )
 
         poDS->SetBand( i+1, poBand );
         poBand->SetNoDataValue( dfNoData );
-        if (bIsDTM==TRUE) {
-            poBand->SetScale( (double) CPLAtof(poDS->GetKeyword( "DTM.DTM_SCALING_FACTOR") ) );
-            poBand->SetOffset( (double) CPLAtof(poDS->GetKeyword( "DTM.DTM_OFFSET") ) );
+        if (bIsDTM) {
+            poBand->SetScale( static_cast<double>(
+                CPLAtof(poDS->GetKeyword( "DTM.DTM_SCALING_FACTOR") ) ) );
+            poBand->SetOffset( static_cast<double>(
+                CPLAtof(poDS->GetKeyword( "DTM.DTM_OFFSET") ) ) );
             const char* pszMin = poDS->GetKeyword( "DTM.DTM_MINIMUM_DN", NULL );
             const char* pszMax = poDS->GetKeyword( "DTM.DTM_MAXIMUM_DN", NULL );
             if (pszMin != NULL && pszMax != NULL )
@@ -646,12 +618,12 @@ GDALDataset *VICARDataset::Open( GDALOpenInfo * poOpenInfo )
             if (pszNoData != NULL )
                 poBand->SetNoDataValue( CPLAtofM(pszNoData) );
         } else if (EQUAL( poDS->GetKeyword( "BLTYPE"), "M94_HRSC" )) {
-            float scale=CPLAtof(poDS->GetKeyword("DLRTO8.REFLECTANCE_SCALING_FACTOR","-1."));
+            double scale=CPLAtof(poDS->GetKeyword("DLRTO8.REFLECTANCE_SCALING_FACTOR","-1."));
             if (scale < 0.) {
                 scale = CPLAtof(poDS->GetKeyword( "HRCAL.REFLECTANCE_SCALING_FACTOR","1."));
             }
             poBand->SetScale( scale );
-            float offset=CPLAtof(poDS->GetKeyword("DLRTO8.REFLECTANCE_OFFSET","-1."));
+            double offset=CPLAtof(poDS->GetKeyword("DLRTO8.REFLECTANCE_OFFSET","-1."));
             if (offset < 0.) {
                 offset = CPLAtof(poDS->GetKeyword( "HRCAL.REFLECTANCE_OFFSET","0."));
             }
@@ -671,27 +643,27 @@ GDALDataset *VICARDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 
 /******************   HRSC    ******************************/
-   
+
     if (EQUAL( poDS->GetKeyword( "BLTYPE"), "M94_HRSC" ) ) {
         poDS->SetMetadataItem( "SPACECRAFT_NAME", poDS->GetKeyword( "M94_INSTRUMENT.INSTRUMENT_HOST_NAME") );
         poDS->SetMetadataItem( "PRODUCT_TYPE", poDS->GetKeyword( "TYPE"));
-    	
+
         if (EQUAL( poDS->GetKeyword( "M94_INSTRUMENT.DETECTOR_ID"), "MEX_HRSC_SRC" )) {
-            static const char *apszKeywords[] =  {
+            static const char * const apszKeywords[] =  {
                         "M94_ORBIT.IMAGE_TIME",
                         "FILE.EVENT_TYPE",
                         "FILE.PROCESSING_LEVEL_ID",
-                        "M94_INSTRUMENT.DETECTOR_ID", 
+                        "M94_INSTRUMENT.DETECTOR_ID",
                         "M94_CAMERAS.EXPOSURE_DURATION",
                         "HRCONVER.INSTRUMENT_TEMPERATURE", NULL
                     };
-            for( i = 0; apszKeywords[i] != NULL; i++ ) {
+            for( int i = 0; apszKeywords[i] != NULL; i++ ) {
                 const char *pszKeywordValue = poDS->GetKeyword( apszKeywords[i] );
                 if( pszKeywordValue != NULL )
                     poDS->SetMetadataItem( apszKeywords[i], pszKeywordValue );
             }
         } else {
-            static const char *apszKeywords[] =  {
+            static const char * const apszKeywords[] =  {
                 "M94_ORBIT.START_TIME", "M94_ORBIT.STOP_TIME",
                 "M94_INSTRUMENT.DETECTOR_ID",
                 "M94_CAMERAS.MACROPIXEL_SIZE",
@@ -707,21 +679,21 @@ GDALDataset *VICARDataset::Open( GDALOpenInfo * poOpenInfo )
                 "HRORTHO.DTM_NAME", "HRORTHO.EXTORI_FILE_NAME", "HRORTHO.GEOMETRIC_CALIB_FILE_NAME",
                 NULL
             };
-            for( i = 0; apszKeywords[i] != NULL; i++ ) {
+            for( int i = 0; apszKeywords[i] != NULL; i++ ) {
                 const char *pszKeywordValue = poDS->GetKeyword( apszKeywords[i], NULL );
                 if( pszKeywordValue != NULL )
                     poDS->SetMetadataItem( apszKeywords[i], pszKeywordValue );
             }
         }
     }
-    if (bIsDTM==TRUE && EQUAL( poDS->GetKeyword( "MAP.TARGET_NAME"), "MARS" )) {
+    if (bIsDTM && EQUAL( poDS->GetKeyword( "MAP.TARGET_NAME"), "MARS" )) {
         poDS->SetMetadataItem( "SPACECRAFT_NAME", "MARS_EXPRESS" );
         poDS->SetMetadataItem( "PRODUCT_TYPE", "DTM");
-        static const char *apszKeywords[] = {
-            "DTM.DTM_MISSING_DN", "DTM.DTM_OFFSET", "DTM.DTM_SCALING_FACTOR", "DTM.DTM_A_AXIS_RADIUS", 
+        static const char * const apszKeywords[] = {
+            "DTM.DTM_MISSING_DN", "DTM.DTM_OFFSET", "DTM.DTM_SCALING_FACTOR", "DTM.DTM_A_AXIS_RADIUS",
             "DTM.DTM_B_AXIS_RADIUS", "DTM.DTM_C_AXIS_RADIUS", "DTM.DTM_DESC", "DTM.DTM_MINIMUM_DN",
             "DTM.DTM_MAXIMUM_DN", NULL };
-        for( i = 0; apszKeywords[i] != NULL; i++ ) {
+        for( int i = 0; apszKeywords[i] != NULL; i++ ) {
             const char *pszKeywordValue = poDS->GetKeyword( apszKeywords[i] );
             if( pszKeywordValue != NULL )
                 poDS->SetMetadataItem( apszKeywords[i], pszKeywordValue );
@@ -732,7 +704,7 @@ GDALDataset *VICARDataset::Open( GDALOpenInfo * poOpenInfo )
 /******************   DAWN   ******************************/
     else if (EQUAL( poDS->GetKeyword( "INSTRUMENT_ID"), "FC2" )) {
         poDS->SetMetadataItem( "SPACECRAFT_NAME", "DAWN" );
-        static const char *apszKeywords[] =  {"ORBIT_NUMBER","FILTER_NUMBER",
+        static const char * const apszKeywords[] =  {"ORBIT_NUMBER","FILTER_NUMBER",
         "FRONT_DOOR_STATUS",
         "FIRST_LINE",
         "FIRST_LINE_SAMPLE",
@@ -748,24 +720,24 @@ GDALDataset *VICARDataset::Open( GDALOpenInfo * poOpenInfo )
         "SPACECRAFT_EASTERN_LONGITUDE",
         "FOOTPRINT_POSITIVE_LONGITUDE",
             NULL };
-        for( i = 0; apszKeywords[i] != NULL; i++ ) {
+        for( int i = 0; apszKeywords[i] != NULL; i++ ) {
             const char *pszKeywordValue = poDS->GetKeyword( apszKeywords[i] );
             if( pszKeywordValue != NULL )
                 poDS->SetMetadataItem( apszKeywords[i], pszKeywordValue );
         }
-        
+
     }
-    else if (bIsDTM==TRUE && EQUAL( poDS->GetKeyword( "TARGET_NAME"), "VESTA" )) {
+    else if (bIsDTM && EQUAL( poDS->GetKeyword( "TARGET_NAME"), "VESTA" )) {
         poDS->SetMetadataItem( "SPACECRAFT_NAME", "DAWN" );
         poDS->SetMetadataItem( "PRODUCT_TYPE", "DTM");
-        static const char *apszKeywords[] = {
-            "DTM_MISSING_DN", "DTM_OFFSET", "DTM_SCALING_FACTOR", "DTM_A_AXIS_RADIUS", 
+        static const char * const apszKeywords[] = {
+            "DTM_MISSING_DN", "DTM_OFFSET", "DTM_SCALING_FACTOR", "DTM_A_AXIS_RADIUS",
             "DTM_B_AXIS_RADIUS", "DTM_C_AXIS_RADIUS", "DTM_MINIMUM_DN",
             "DTM_MAXIMUM_DN", "MAP_PROJECTION_TYPE", "COORDINATE_SYSTEM_NAME",
             "POSITIVE_LONGITUDE_DIRECTION", "MAP_SCALE",
             "CENTER_LONGITUDE", "LINE_PROJECTION_OFFSET", "SAMPLE_PROJECTION_OFFSET",
             NULL };
-        for( i = 0; apszKeywords[i] != NULL; i++ ) {
+        for( int i = 0; apszKeywords[i] != NULL; i++ ) {
             const char *pszKeywordValue = poDS->GetKeyword( apszKeywords[i] );
             if( pszKeywordValue != NULL )
                 poDS->SetMetadataItem( apszKeywords[i], pszKeywordValue );
@@ -780,6 +752,7 @@ GDALDataset *VICARDataset::Open( GDALOpenInfo * poOpenInfo )
     if (EQUAL(poDS->GetKeyword( "EOL"), "1" ))
         poDS->SetMetadataItem( "END-OF-DATASET_LABEL", "PRESENT" );
     poDS->SetMetadataItem( "CONVERSION_DETAILS", "http://www.lpi.usra.edu/meetings/lpsc2014/pdf/1088.pdf" );
+    poDS->SetMetadataItem( "PIXEL-SHIFT-BUG", "CORRECTED" );
 
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
@@ -798,15 +771,13 @@ GDALDataset *VICARDataset::Open( GDALOpenInfo * poOpenInfo )
 /*                             GetKeyword()                             */
 /************************************************************************/
 
-const char *VICARDataset::GetKeyword( const char *pszPath, 
+const char *VICARDataset::GetKeyword( const char *pszPath,
                                       const char *pszDefault )
 
 {
     return oKeywords.GetKeyword( pszPath, pszDefault );
 }
 
-
-
 /************************************************************************/
 /*                         GDALRegister_VICAR()                         */
 /************************************************************************/
@@ -814,22 +785,19 @@ const char *VICARDataset::GetKeyword( const char *pszPath,
 void GDALRegister_VICAR()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "VICAR" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "VICAR" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "VICAR" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "MIPL VICAR file" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_vicar.html" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = VICARDataset::Open;
-        poDriver->pfnIdentify = VICARDataset::Identify;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
-}
+    GDALDriver *poDriver = new GDALDriver();
 
+    poDriver->SetDescription( "VICAR" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "MIPL VICAR file" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_vicar.html" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = VICARDataset::Open;
+    poDriver->pfnIdentify = VICARDataset::Identify;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/frmts/pds/vicarkeywordhandler.cpp b/frmts/pds/vicarkeywordhandler.cpp
index fda85a2..991e4c5 100644
--- a/frmts/pds/vicarkeywordhandler.cpp
+++ b/frmts/pds/vicarkeywordhandler.cpp
@@ -1,15 +1,15 @@
 /******************************************************************************
-* 
+*
 * Project:  VICAR Driver; JPL/MIPL VICAR Format
-* Purpose:  Implementation of VICARKeywordHandler - a class to read 
+* Purpose:  Implementation of VICARKeywordHandler - a class to read
 *           keyword data from VICAR data products.
 * Author:   Sebastian Walter <sebastian dot walter at fu-berlin dot de>
 *
 * NOTE: This driver code is loosely based on the ISIS and PDS drivers.
-* It is not intended to diminish the contribution of the authors 
+* It is not intended to diminish the contribution of the authors.
 ******************************************************************************
 * Copyright (c) 2014, Sebastian Walter <sebastian dot walter at fu-berlin dot de>
-* 
+*
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
@@ -30,34 +30,33 @@
 ****************************************************************************/
 
 
-#include "cpl_string.h" 
+#include "cpl_string.h"
 #include "vicarkeywordhandler.h"
 
 /************************************************************************/
 /* ==================================================================== */
-/*                          VICARKeywordHandler                          */
+/*                          VICARKeywordHandler                         */
 /* ==================================================================== */
 /************************************************************************/
 
 /************************************************************************/
-/*                         VICARKeywordHandler()                         */
+/*                         VICARKeywordHandler()                        */
 /************************************************************************/
 
-VICARKeywordHandler::VICARKeywordHandler()
-
-{
-    papszKeywordList = NULL;
-}
+VICARKeywordHandler::VICARKeywordHandler() :
+    papszKeywordList(NULL),
+    pszHeaderNext(NULL),
+    LabelSize(0)
+{ }
 
 /************************************************************************/
-/*                        ~VICARKeywordHandler()                         */
+/*                        ~VICARKeywordHandler()                        */
 /************************************************************************/
 
 VICARKeywordHandler::~VICARKeywordHandler()
 
 {
     CSLDestroy( papszKeywordList );
-    papszKeywordList = NULL;
 }
 
 /************************************************************************/
@@ -96,39 +95,43 @@ int VICARKeywordHandler::Ingest( VSILFILE *fp, GByte *pabyHeader )
     if( LabelSize <= 0 || LabelSize > 10 * 1024 * 124 )
         return FALSE;
 
-    char* pszChunk = (char*) VSIMalloc(LabelSize+1);
+    char* pszChunk = reinterpret_cast<char *>(  VSIMalloc( LabelSize + 1 ) );
     if( pszChunk == NULL )
         return FALSE;
-    int nBytesRead = VSIFReadL( pszChunk, 1, LabelSize, fp );
-    pszChunk[LabelSize] = 0;
+    int nBytesRead = static_cast<int>(VSIFReadL( pszChunk, 1, LabelSize, fp ));
+    pszChunk[nBytesRead] = '\0';
 
     osHeaderText += pszChunk ;
-    VSIFree(pszChunk);
+    VSIFree( pszChunk );
     pszHeaderNext = osHeaderText.c_str();
-    
+
 /* -------------------------------------------------------------------- */
 /*      Process name/value pairs, keeping track of a "path stack".      */
 /* -------------------------------------------------------------------- */
     if( !ReadGroup("") )
         return FALSE;
+
 /* -------------------------------------------------------------------- */
 /*      Now check for the Vicar End-of-Dataset Label...                 */
 /* -------------------------------------------------------------------- */
     const char *pszResult;
 
     pszResult = CSLFetchNameValue( papszKeywordList, "EOL" );
-    
+
     if( pszResult == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "END-OF-DATASET LABEL NOT DEFINED!");
         return FALSE;
+    }
 
-    if( !EQUAL(pszResult,"1") ) 
+    if( !EQUAL(pszResult,"1") )
         return TRUE;
 
 /* -------------------------------------------------------------------- */
 /*      There is a EOL!   e.G.  h4231_0000.nd4.06                       */
 /* -------------------------------------------------------------------- */
 
-    long int	    nLineOffset=0, nPixelOffset=0, nBandOffset=0;
+    long int nPixelOffset=0;
     if (EQUAL( CSLFetchNameValue(papszKeywordList,"FORMAT" ), "BYTE" )) {
         nPixelOffset = 1;
     }
@@ -137,56 +140,69 @@ int VICARKeywordHandler::Ingest( VSILFILE *fp, GByte *pabyHeader )
     }
     else if (EQUAL( CSLFetchNameValue(papszKeywordList,"FORMAT" ), "FULL" )) {
         nPixelOffset = 4;
-    } 
+    }
     else if (EQUAL( CSLFetchNameValue(papszKeywordList,"FORMAT" ), "REAL" )) {
         nPixelOffset = 4;
     }
-    long int nCols = atoi(CSLFetchNameValue(papszKeywordList,"NS")) ;
-    long int nRows = atoi(CSLFetchNameValue(papszKeywordList,"NL")) ;
-    int nBands = atoi(CSLFetchNameValue(papszKeywordList,"NB")) ;
-    int nBB = atoi(CSLFetchNameValue(papszKeywordList,"NBB")) ;
-    nLineOffset = nPixelOffset * nCols + nBB ;
-    nBandOffset = nLineOffset * nRows;
-    long int starteol = LabelSize + nBandOffset * nBands;
-    if( VSIFSeekL( fp, starteol, SEEK_SET ) != 0 ) {
+
+    const long int nCols = atoi( CSLFetchNameValue( papszKeywordList, "NS" ) );
+    const long int nRows = atoi( CSLFetchNameValue( papszKeywordList, "NL" ) );
+    const int nBands = atoi( CSLFetchNameValue( papszKeywordList, "NB" ) );
+    const int nBB = atoi( CSLFetchNameValue( papszKeywordList, "NBB" ) );
+
+    const long int nLineOffset = nPixelOffset * nCols + nBB ;
+    const long int nBandOffset = nLineOffset * nRows;
+
+    const long int starteol = LabelSize + nBandOffset * nBands;
+    if( VSIFSeekL( fp, starteol, SEEK_SET ) != 0 )
+    {
         CPLError(CE_Failure, CPLE_AppDefined, "Error seeking again to EOL!");
         return FALSE;
-        }
-    char szChunk[100];
-    nBytesRead = VSIFReadL( szChunk, 1, 30, fp );
-    szChunk[nBytesRead] = '\0';
-    pszLBLSIZE=strstr(szChunk,"LBLSIZE");
+    }
+    char* pszEOLHeader = static_cast<char*>(VSIMalloc(32));
+    if( pszEOLHeader == NULL )
+        return FALSE;
+    nBytesRead = static_cast<int>(VSIFReadL( pszEOLHeader, 1, 31, fp ));
+    pszEOLHeader[nBytesRead] = '\0';
+    pszLBLSIZE=strstr(pszEOLHeader,"LBLSIZE");
     nOffset=0;
-    
     if (pszLBLSIZE)
-        nOffset = static_cast<int>(pszLBLSIZE - (const char *)szChunk);
-    pch1 = strstr( reinterpret_cast<char *>( szChunk + nOffset ), "=" );
+        nOffset = static_cast<int>(pszLBLSIZE - (const char *)pszEOLHeader);
+    pch1 = strstr( reinterpret_cast<char *>( pszEOLHeader + nOffset ), "=" );
     if( pch1 == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "END-OF-DATASET LABEL NOT FOUND!");
+        VSIFree(pszEOLHeader);
         return FALSE;
+    }
+    VSIFree(pszEOLHeader);
     pch1 ++;
     pch2 = strstr( pch1, " " );
     if( pch2 == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "END-OF-DATASET LABEL NOT FOUND!");
         return FALSE;
+    }
     strncpy( keyval, pch1, MIN( static_cast<size_t>(pch2-pch1), sizeof(keyval)-1 ) );
     keyval[MIN( static_cast<size_t>(pch2-pch1), sizeof(keyval)-1 )] = '\0';
 
     int EOLabelSize = atoi( keyval );
-    if( EOLabelSize <= 0 )
+    if( EOLabelSize <= 0 || EOLabelSize > 100 * 1024 * 1024 )
         return FALSE;
-    if( EOLabelSize > static_cast<int>(sizeof(szChunk) - 1) )
-        EOLabelSize = static_cast<int>(sizeof(szChunk) - 1);
     if( VSIFSeekL( fp, starteol, SEEK_SET ) != 0 )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Error seeking again to EOL!");
         return FALSE;
-        }
-    nBytesRead = VSIFReadL( szChunk, 1, EOLabelSize, fp );
-    szChunk[nBytesRead] = '\0';
-    osHeaderText += szChunk ;
-    osHeaderText.append("END");
+    }
+    char* pszChunkEOL = (char*) VSIMalloc(EOLabelSize+1);
+    if( pszChunkEOL == NULL )
+        return FALSE;
+    nBytesRead = static_cast<int>(VSIFReadL( pszChunkEOL, 1, EOLabelSize, fp ));
+    pszChunkEOL[nBytesRead] = '\0';
+    osHeaderText += pszChunkEOL ;
+    VSIFree(pszChunkEOL);
     pszHeaderNext = osHeaderText.c_str();
     return ReadGroup( "" );
-    
 }
 
 /************************************************************************/
@@ -196,15 +212,15 @@ int VICARKeywordHandler::Ingest( VSILFILE *fp, GByte *pabyHeader )
 int VICARKeywordHandler::ReadGroup( CPL_UNUSED const char *pszPathPrefix ) {
     CPLString osName, osValue, osProperty;
 
-    for( ; TRUE; ) {
-        if( !ReadPair( osName, osValue ) ) {
-        //printf("Could not... \n");
-                return FALSE;
-                }
-            if( EQUAL(osName,"END") )
+    for( ; true; ) {
+        if( !ReadPair( osName, osValue ) )
+            return FALSE;
+
+        if( EQUAL(osName,"END") )
             return TRUE;
-            else if( EQUAL(osName,"PROPERTY") || EQUAL(osName,"HISTORY") || EQUAL(osName,"TASK"))
-                osProperty = osValue;
+
+        if( EQUAL(osName,"PROPERTY") || EQUAL(osName,"HISTORY") || EQUAL(osName,"TASK"))
+            osProperty = osValue;
         else {
             if ( !EQUAL(osProperty,"") )
                 osName = osProperty + "." + osName;
@@ -231,7 +247,7 @@ int VICARKeywordHandler::ReadPair( CPLString &osName, CPLString &osValue ) {
     return FALSE;}
 
     SkipWhite();
-    
+
     // VICAR has no NULL string termination
     if( *pszHeaderNext == '\0') {
         osName="END";
@@ -239,10 +255,8 @@ int VICARKeywordHandler::ReadPair( CPLString &osName, CPLString &osValue ) {
     }
 
     pszHeaderNext++;
-    
+
     SkipWhite();
-    
-    osValue = "";
 
     if( *pszHeaderNext == '(' && pszHeaderNext[1] == '\'' )
     {
@@ -255,7 +269,7 @@ int VICARKeywordHandler::ReadPair( CPLString &osName, CPLString &osValue ) {
         }
     }
 
-    else if( *pszHeaderNext == '(' && *pszHeaderNext-1 != '\'' )
+    else if( *pszHeaderNext == '(' && *(pszHeaderNext-1) != '\'' )
     {
         CPLString osWord;
 
@@ -270,12 +284,13 @@ int VICARKeywordHandler::ReadPair( CPLString &osName, CPLString &osValue ) {
 
     else
     {
-        if( !ReadWord( osValue ) ) return FALSE;
+        if( !ReadWord( osValue ) )
+            return FALSE;
 
     }
-        
+
     SkipWhite();
-    
+
     return TRUE;
 }
 
@@ -291,11 +306,11 @@ int VICARKeywordHandler::ReadWord( CPLString &osWord )
 
     SkipWhite();
 
-    if( *pszHeaderNext == '\0') return TRUE;
-    
-    if( !( *pszHeaderNext != '='  && !isspace((unsigned char)*pszHeaderNext)) ) {
-    return FALSE;
-    }
+    if( *pszHeaderNext == '\0')
+        return TRUE;
+
+    if( !( *pszHeaderNext != '='  && !isspace((unsigned char)*pszHeaderNext)) )
+        return FALSE;
 
     if( *pszHeaderNext == '\'' )
     {
@@ -327,9 +342,8 @@ int VICARKeywordHandler::ReadWord( CPLString &osWord )
             return FALSE;
         osWord += *pszHeaderNext;
         pszHeaderNext++;
-
     }
-    
+
     return TRUE;
 }
 
@@ -341,15 +355,15 @@ int VICARKeywordHandler::ReadWord( CPLString &osWord )
 void VICARKeywordHandler::SkipWhite()
 
 {
-    for( ; TRUE; )
+    for( ; true; )
     {
         if( isspace( (unsigned char)*pszHeaderNext ) )
         {
             pszHeaderNext++;
             continue;
         }
-        
-        // not white space, return. 
+
+        // not white space, return.
         return;
     }
 }
@@ -361,13 +375,12 @@ void VICARKeywordHandler::SkipWhite()
 const char *VICARKeywordHandler::GetKeyword( const char *pszPath, const char *pszDefault )
 
 {
-    const char *pszResult;
+    const char *pszResult = CSLFetchNameValue( papszKeywordList, pszPath );
 
-    pszResult = CSLFetchNameValue( papszKeywordList, pszPath );
-    if( pszResult == NULL ){
-        return pszDefault;}
-    else
-        return pszResult;
+    if( pszResult == NULL )
+        return pszDefault;
+
+    return pszResult;
 }
 
 /************************************************************************/
@@ -378,4 +391,3 @@ char **VICARKeywordHandler::GetKeywordList()
 {
     return papszKeywordList;
 }
-
diff --git a/frmts/pds/vicarkeywordhandler.h b/frmts/pds/vicarkeywordhandler.h
index 36564e4..c5ef7fc 100644
--- a/frmts/pds/vicarkeywordhandler.h
+++ b/frmts/pds/vicarkeywordhandler.h
@@ -1,15 +1,15 @@
 /******************************************************************************
- * 
+ *
  * Project:  VICAR Driver; JPL/MIPL VICAR Format
- * Purpose:  Implementation of VICARKeywordHandler - a class to read 
+ * Purpose:  Implementation of VICARKeywordHandler - a class to read
  *           keyword data from VICAR data products.
  * Authors:  Sebastian Walter <sebastian dot walter at fu-berlin dot de>
  *
  * NOTE: This driver code is loosely based on the ISIS and PDS drivers.
- * It is not intended to diminish the contribution of the authors 
+ * It is not intended to diminish the contribution of the authors.
  ******************************************************************************
  * Copyright (c) 2014, Sebastian Walter <sebastian dot walter at fu-berlin dot de>
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * to deal in the Software without restriction, including without limitation
@@ -35,12 +35,12 @@ class VICARKeywordHandler
     CPLString osHeaderText;
     const char *pszHeaderNext;
 
+    int     LabelSize;
+
     void    SkipWhite();
     int     ReadWord( CPLString &osWord );
     int     ReadPair( CPLString &osName, CPLString &osValue );
     int     ReadGroup( const char *pszPathPrefix );
-    int     LabelSize;
-    int     Eol;
 
 public:
     VICARKeywordHandler();
diff --git a/frmts/pgchip/GNUmakefile b/frmts/pgchip/GNUmakefile
deleted file mode 100644
index 43a2ef6..0000000
--- a/frmts/pgchip/GNUmakefile
+++ /dev/null
@@ -1,24 +0,0 @@
-# USER CONFIGURATION
-# Set your postgis include path here :
-POSTGIS_INC     =-I/path/to/your/postgis/headers
-# END OF USER CONFIGURATION 
-
-
-include ../../GDALmake.opt
-
-OBJ	=	pgchipdataset.o pgchiprasterband.o pgchiputilities.o
-
-
-CPPFLAGS	:= -Wall -g $(XTRA_OPT) $(PG_INC) $(POSTGIS_INC)  $(CPPFLAGS )
-
-default:	$(OBJ:.o=.$(OBJ_EXT))
-
-clean:
-	rm -f *.o $(O_OBJ)
-
-../o/%.$(OBJ_EXT):
-	$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@
-
-all:	$(OBJ:.o=.$(OBJ_EXT))
-
-install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
diff --git a/frmts/pgchip/INSTALL b/frmts/pgchip/INSTALL
deleted file mode 100644
index 36da77d..0000000
--- a/frmts/pgchip/INSTALL
+++ /dev/null
@@ -1,37 +0,0 @@
-REQUIREMENTS :
-
-* Make sure you have a full PostgreSQL/Postgis clean source installation 
-* You need to have Proj4 installed and configured in Pstgis to get the driver work
-
-
-INSTALL NOTES :
-
-1* Go to frmts directory under GDAL source tree
-
-2* Unpack pgchip archive in the frmts directory 
-
-3* Edit GNUMakefile to set your Postgis include path
-
-4* Add registration entry point declaration :
-    - Open gdal/gcore/gdal_frmts.h
-    - Add "void CPL_DLL GDALRegister_PGCHIP(void);" between the CPL_C_START and CPL_C_END tags
-
-5* Add a call to the registration function in frmts/gdalallregister.c
-    In the GDALAllRegister() function add the followinf lines :
-    #ifdef FRMT_pgchip
-        GDALRegister_PGCHIP();
-    #endif
-    
-6* Add the format short name to the GDAL_FORMATS macro in GDALmake.opt.in (and to GDALmake.opt) :
-    - Locate the variable GDAL_FORMATS and add "pgchip" (lowercase) to the list of formats
-    
-7* Add a format specific item to the EXTRAFLAGS macro in frmts/makefile.vc
-
-8* Recompile your GDAL library :
-    - make clean
-    -./configure
-    - make
-    - make install
-    
-9* Test your pgchip installation :
-    execute gdalinfo --formats and search for pgchip  
\ No newline at end of file
diff --git a/frmts/pgchip/README b/frmts/pgchip/README
deleted file mode 100644
index 5fab1f7..0000000
--- a/frmts/pgchip/README
+++ /dev/null
@@ -1,29 +0,0 @@
-Important Drivers Restrictions :
-
-    * PGCHIP driver is currently under development which means it has NOT been fully tested and no stable release is downloadable.
-    
-    * The driver only supports GDT_Byte and GDT_UInt16 datatypes and deals with 1 or 4 bands (GREY_SCALE, PALETTE and RGBA)
-    
-    * The column name for the chip is not yet changeable and is "raster" by default
-    
-    * In order to specify the database you want to connect to, you have to give a connection string. The differents connection parameters (host,port,dbname) must be delimited with a "#" character. The name of the Postgis layer should be given at the end of the string after a "%layer=" argument. Example : 
-
-        $ gdalinfo PG:host=192.168.1.1#dbname=mydb%layer=myRasterTable
-        
-        
-How can I test the driver :
-
-    * You can choose to build your own application using the GDAL API or use the utility programs.
-    * Some examples with gdal_translate :
-    
-        Import BMP raster :
-        gdal_translate -of pgchip /DATA/myRaster.bmp PG:host=192.168.1.1#dbname=mydb#port=5432%layer=myRaster
-    
-        Then export to PNG :
-        gdal_translate -of png -ot UInt16 PG:host=192.168.1.1#dbname=mydb#port=5432%layer=myRaster /DATA/myRaster.png
-
-                
-Author information and bug report :
-
-    website : http://simon.benjamin.free.fr/pgchip/
-    email : noumayoss at gmail.com
diff --git a/frmts/pgchip/makefile.vc b/frmts/pgchip/makefile.vc
deleted file mode 100644
index 5f115e3..0000000
--- a/frmts/pgchip/makefile.vc
+++ /dev/null
@@ -1,15 +0,0 @@
-
-OBJ	=	pgChipdataset.obj
-
-EXTRAFLAGS = 	-I..\iso8211
-
-GDAL_ROOT	=	..\..
-
-!INCLUDE $(GDAL_ROOT)\nmake.opt
-
-default:	$(OBJ)
-	xcopy /D  /Y *.obj ..\o
-
-clean:
-	-del *.obj
-
diff --git a/frmts/pgchip/pgchip.h b/frmts/pgchip/pgchip.h
deleted file mode 100644
index fbfb9d5..0000000
--- a/frmts/pgchip/pgchip.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/******************************************************************************
- *
- * File :    pgchip.h
- * Project:  PGCHIP Driver
- * Purpose:  Main header file for POSTGIS CHIP/GDAL Driver 
- * Author:   Benjamin Simon, noumayoss at gmail.com
- *
- ******************************************************************************
- * Copyright (c) 2005, Benjamin Simon, noumayoss at gmail.com
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ******************************************************************************
- * 
- * Revision 1.1  2005/08/29  bsimon
- * New
- *
- */
-
-#include "gdal_priv.h"
-#include "libpq-fe.h"
-#include "liblwgeom.h"
-
-// External functions (what's again the reason for using explicit hex form ?)
-extern void pgch_deparse_hex(unsigned char in, unsigned char *out);
-extern void deparse_hex_string(unsigned char *strOut,char *strIn,int length);
-extern void parse_hex_string(unsigned char *strOut,char *strIn,int length);
-
-/* color types */
-#define PGCHIP_COLOR_TYPE_GRAY 0
-#define PGCHIP_COLOR_TYPE_PALETTE 1
-#define PGCHIP_COLOR_TYPE_RGB_ALPHA 4
-
-//pg_chip color struct 
-typedef struct pgchip_color_nohex_struct
-{
-   unsigned char red; 
-   unsigned char green;
-   unsigned char blue;
-   unsigned char alpha;
-} pgchip_color;
-
-
-/************************************************************************/
-/* ==================================================================== */
-/*				PGCHIPDataset				*/
-/* ==================================================================== */
-/************************************************************************/
-
-class PGCHIPRasterBand;
-
-class PGCHIPDataset : public GDALDataset{
-
-    friend class PGCHIPRasterBand;
-
-    PGconn      *hPGConn;
-    char        *pszTableName;
-    char	*pszDSName;
-    char	*pszProjection;
-
-    CHIP        *PGCHIP;
-    int         SRID;
-    int         nBitDepth;
-    
-    int                 nColorType; /* PGHIP_COLOR_TYPE_* */
-    GDALColorTable      *poColorTable;
-    int		bHaveNoData;
-    double 	dfNoDataValue;
-    
-    double              adfGeoTransform[6];
-    int                 bGeoTransformValid;
-    
-  public:
-	
-	PGCHIPDataset();
-        ~PGCHIPDataset();
-    
-    static GDALDataset *Open( GDALOpenInfo * );
-    
-    static void        printChipInfo(const CHIP& chip);
-
-    CPLErr 	GetGeoTransform( double * padfTransform );
-    const char *GetProjectionRef();
-};
-
-/************************************************************************/
-/* ==================================================================== */
-/*                            PGCHIPRasterBand                          */
-/* ==================================================================== */
-/************************************************************************/
-
-class PGCHIPRasterBand : public GDALRasterBand{
-
-    friend class PGCHIPDataset;
-    
-  public:
-
-    PGCHIPRasterBand( PGCHIPDataset *, int );
-    
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual GDALColorTable *GetColorTable();
-            
-};
diff --git a/frmts/pgchip/pgchipdataset.cpp b/frmts/pgchip/pgchipdataset.cpp
deleted file mode 100644
index 0712f7e..0000000
--- a/frmts/pgchip/pgchipdataset.cpp
+++ /dev/null
@@ -1,995 +0,0 @@
-/******************************************************************************
- *
- * File :    pgchipdataset.cpp
- * Project:  PGCHIP Driver
- * Purpose:  GDALDataset code for POSTGIS CHIP/GDAL Driver 
- * Author:   Benjamin Simon, noumayoss at gmail.com
- *
- ******************************************************************************
- * Copyright (c) 2005, Benjamin Simon, noumayoss at gmail.com
- * Copyright (c) 2008, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ******************************************************************************
- * 
- * Revision 1.1  2005/08/29 bsimon
- * New
- *
- */
-
-#include "pgchip.h"
-
-/* Define to enable debugging info */
-/*#define PGCHIP_DEBUG 1*/
-
-CPL_C_START
-void	GDALRegister_PGCHIP(void);
-CPL_C_END
-
-
-/************************************************************************/
-/* ==================================================================== */
-/*				PGCHIPDataset				*/
-/* ==================================================================== */
-/************************************************************************/
-
-
-/************************************************************************/
-/*                            PGCHIPDataset()                           */
-/************************************************************************/
-
-PGCHIPDataset::PGCHIPDataset(){
-
-    hPGConn = NULL;
-    pszTableName = NULL;
-    pszDSName = NULL;
-    PGCHIP = NULL;
-    
-    bGeoTransformValid = FALSE;
-    adfGeoTransform[0] = 0.0;
-    adfGeoTransform[1] = 1.0;
-    adfGeoTransform[2] = 0.0;
-    adfGeoTransform[3] = 0.0;
-    adfGeoTransform[4] = 0.0;
-    adfGeoTransform[5] = 1.0;
-    
-    SRID = -1;
-    pszProjection = CPLStrdup("");
-    
-    bHaveNoData = FALSE;
-    dfNoDataValue = -1;
-}
-
-/************************************************************************/
-/*                            ~PGCHIPDataset()                             */
-/************************************************************************/
-
-PGCHIPDataset::~PGCHIPDataset(){
-
-    if( hPGConn != NULL )
-    {
-        /* XXX - mloskot: After the connection is closed, valgrind still
-         * reports 36 bytes definitely lost, somewhere in the libpq.
-         */
-        PQfinish( hPGConn );
-        hPGConn = NULL;
-    }
-
-    CPLFree(pszProjection);
-    CPLFree(pszTableName);
-    CPLFree(pszDSName);
-    CPLFree(PGCHIP);
-}
-
-/************************************************************************/
-/*                          GetGeoTransform()                           */
-/************************************************************************/
-
-CPLErr PGCHIPDataset::GetGeoTransform( double * padfTransform ){
-    
-    memcpy( padfTransform, adfGeoTransform, sizeof(adfGeoTransform[0]) * 6 );
-
-    if( bGeoTransformValid )
-        return CE_None;
-    else
-        return CE_Failure;
-}
-
-/************************************************************************/
-/*                          GetProjectionRef()                          */
-/************************************************************************/
-
-const char *PGCHIPDataset::GetProjectionRef(){
-
-    char    szCommand[1024];
-    PGresult    *hResult;
-
-    if(SRID == -1)
-    {
-        return "";
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Reading proj                                                    */
-/* -------------------------------------------------------------------- */
-
-    sprintf( szCommand,"SELECT srtext FROM spatial_ref_sys where SRID=%d",SRID);
-
-    hResult = PQexec(hPGConn,szCommand);
-
-    if( hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK 
-             && PQntuples(hResult) > 0 )
-    {
-        CPLFree(pszProjection);
-        pszProjection = CPLStrdup(PQgetvalue(hResult,0,0)); 
-    }
-
-    if( hResult )
-        PQclear( hResult );
-
-    return pszProjection;
-}
-
-/************************************************************************/
-/*                        PGChipOpenConnection()                        */
-/************************************************************************/
-
-static
-PGconn* PGChipOpenConnection(const char* pszFilename, char** ppszTableName, const char** ppszDSName,
-                             int bExitOnMissingTable, int* pbExistTable, int *pbHasNameCol)
-{
-    char       *pszConnectionString;
-    PGconn     *hPGConn;
-    PGresult   *hResult = NULL;
-    int         i=0;
-    int         bHavePostGIS;
-    char       *pszTableName;
-    char        szCommand[1024];
-
-    if( pszFilename == NULL || !EQUALN(pszFilename,"PG:",3))
-        return NULL;
-
-    pszConnectionString = CPLStrdup(pszFilename);
-
-/* -------------------------------------------------------------------- */
-/*      Try to establish connection.                                    */
-/* -------------------------------------------------------------------- */
-    while(pszConnectionString[i] != '\0')
-    {
-
-        if(pszConnectionString[i] == '#')
-            pszConnectionString[i] = ' ';
-        else if(pszConnectionString[i] == '%')
-        {
-            pszConnectionString[i] = '\0';
-            break;
-        }
-        i++;
-    }
-
-    hPGConn = PQconnectdb( pszConnectionString + 3 );
-    if( hPGConn == NULL || PQstatus(hPGConn) == CONNECTION_BAD )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "PGconnectcb failed.\n%s", 
-                  PQerrorMessage(hPGConn) );
-        PQfinish(hPGConn);
-        CPLFree(pszConnectionString);
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Test to see if this database instance has support for the       */
-/*      PostGIS Geometry type.  If so, disable sequential scanning      */
-/*      so we will get the value of the gist indexes.                   */
-/* -------------------------------------------------------------------- */
-
-    hResult = PQexec(hPGConn, 
-                         "SELECT oid FROM pg_type WHERE typname = 'geometry'" );
-
-    if( hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK 
-        && PQntuples(hResult) > 0 )
-    {
-        bHavePostGIS = TRUE;
-    }
-
-    if( hResult )
-        PQclear( hResult );
-
-    if(!bHavePostGIS){
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Can't find geometry type, is Postgis correctly installed ?\n");
-        PQfinish(hPGConn);
-        CPLFree(pszConnectionString);
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*  Try opening the layer                                               */
-/* -------------------------------------------------------------------- */
-
-    if( strstr(pszFilename, "layer=") != NULL )
-    {
-        pszTableName = CPLStrdup( strstr(pszFilename, "layer=") + 6 );
-    }
-    else
-    {
-        pszTableName = CPLStrdup("unknown_layer");
-    }
-
-    char* pszDSName = strstr(pszTableName, "%name=");
-    if (pszDSName)
-    {
-        *pszDSName = '\0';
-        pszDSName += 6;
-    }
-    else
-        pszDSName = "unknown_name";
-
-    sprintf( szCommand, 
-             "select b.attname from pg_class a,pg_attribute b where a.oid=b.attrelid and a.relname='%s' and b.attname='raster';",
-              pszTableName);
-
-    hResult = PQexec(hPGConn,szCommand);
-
-    if( ! (hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK && PQntuples(hResult) > 0) )
-    {
-        if (pbExistTable)
-            *pbExistTable = FALSE;
-
-        if (bExitOnMissingTable)
-        {
-            if (hResult)
-                PQclear( hResult );
-            CPLFree(pszConnectionString);
-            CPLFree(pszTableName);
-            PQfinish(hPGConn);
-            return NULL;
-        }
-    }
-    else
-    {
-        if (pbExistTable)
-            *pbExistTable = TRUE;
-
-        sprintf( szCommand, 
-                "select b.attname from pg_class a,pg_attribute b where a.oid=b.attrelid and a.relname='%s' and b.attname='name';",
-                pszTableName);
-
-        if (hResult)
-            PQclear( hResult );
-        hResult = PQexec(hPGConn,szCommand);
-        if (PQresultStatus(hResult) == PGRES_TUPLES_OK && PQntuples(hResult) > 0)
-        {
-            if (pbHasNameCol)
-                *pbHasNameCol = TRUE;
-        }
-        else
-        {
-            if (pbHasNameCol)
-                *pbHasNameCol = FALSE;
-        }
-    }
-
-    if (hResult)
-        PQclear( hResult );
-
-    if (ppszTableName)
-        *ppszTableName = pszTableName;
-    else
-        CPLFree(pszTableName);
-
-    if (ppszDSName)
-        *ppszDSName = pszDSName;
-
-    CPLFree(pszConnectionString);
-
-    return hPGConn;
-}
-
-
-
-/************************************************************************/
-/*                                Open()                                */
-/************************************************************************/
-
-GDALDataset *PGCHIPDataset::Open( GDALOpenInfo * poOpenInfo ){
-
-    char                szCommand[1024];
-    PGresult            *hResult = NULL;
-    PGCHIPDataset       *poDS = NULL;
-    char                *chipStringHex;
-
-    unsigned char       *chipdata;
-    int                 t;
-    char                *pszTableName = NULL;
-    const char          *pszDSName = NULL;
-    int                  bHasNameCol = FALSE;
-
-    PGconn* hPGConn = PGChipOpenConnection(poOpenInfo->pszFilename, &pszTableName, &pszDSName, TRUE, NULL, &bHasNameCol);
-
-    if( hPGConn == NULL)
-        return NULL;
-
-    poDS = new PGCHIPDataset();
-    poDS->hPGConn = hPGConn;
-    poDS->pszTableName = pszTableName;
-    poDS->pszDSName = CPLStrdup(pszDSName);
-
-/* -------------------------------------------------------------------- */
-/*      Read the chip                                                   */
-/* -------------------------------------------------------------------- */
-
-    hResult = PQexec(poDS->hPGConn, "BEGIN");
-    
-    if( hResult && PQresultStatus(hResult) == PGRES_COMMAND_OK )
-    {
-        PQclear( hResult );
-        if (bHasNameCol)
-            sprintf( szCommand, 
-                    "SELECT raster FROM %s WHERE name = '%s' LIMIT 1 ",
-                    poDS->pszTableName, poDS->pszDSName);
-        else
-            sprintf( szCommand, 
-                    "SELECT raster FROM %s LIMIT 1",
-                    poDS->pszTableName);
-
-        hResult = PQexec(poDS->hPGConn,szCommand);
-    }
-
-    if( !hResult || PQresultStatus(hResult) != PGRES_TUPLES_OK )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "%s", PQerrorMessage(poDS->hPGConn) );
-        if (hResult)
-            PQclear( hResult );
-        delete poDS;
-        return NULL;
-    }
-
-    if (PQntuples(hResult) == 0)
-    {
-        PQclear( hResult );
-        delete poDS;
-        return NULL;
-    }
-
-    chipStringHex = PQgetvalue(hResult, 0, 0);
-
-    if (chipStringHex == NULL)
-    {
-        PQclear( hResult );
-        delete poDS;
-        return NULL;
-    }
-
-    int stringlen = strlen((char *)chipStringHex);
-        
-    // Allocating memory for chip
-    chipdata = (unsigned char *) CPLMalloc(stringlen/2);
-                      	
-    for (t=0;t<stringlen/2;t++){
-	    chipdata[t] = parse_hex( &chipStringHex[t*2]) ;
-    }
-    
-    // Chip assigment
-    poDS->PGCHIP = (CHIP *)chipdata;
-    poDS->SRID = poDS->PGCHIP->SRID;
-    
-    if (poDS->PGCHIP->bvol.xmin != 0 && poDS->PGCHIP->bvol.ymin != 0 &
-        poDS->PGCHIP->bvol.xmax != 0 && poDS->PGCHIP->bvol.ymax != 0)
-    {
-        poDS->bGeoTransformValid = TRUE;
-
-        poDS->adfGeoTransform[0] = poDS->PGCHIP->bvol.xmin;
-        poDS->adfGeoTransform[3] = poDS->PGCHIP->bvol.ymax;
-        poDS->adfGeoTransform[1] = (poDS->PGCHIP->bvol.xmax - poDS->PGCHIP->bvol.xmin) / poDS->PGCHIP->width;
-        poDS->adfGeoTransform[5] = - (poDS->PGCHIP->bvol.ymax - poDS->PGCHIP->bvol.ymin) / poDS->PGCHIP->height;
-    }
-    
-#ifdef PGCHIP_DEBUG
-    poDS->printChipInfo(*(poDS->PGCHIP));
-#endif
-
-    PQclear( hResult );
-
-    hResult = PQexec(poDS->hPGConn, "COMMIT");
-    PQclear( hResult );
-    
-/* -------------------------------------------------------------------- */
-/*      Verify that there's no unknown field set.                       */
-/* -------------------------------------------------------------------- */
-
-    if ( poDS->PGCHIP->future[0] != 0 ||
-         poDS->PGCHIP->future[1] != 0 ||
-         poDS->PGCHIP->future[2] != 0 ||
-         poDS->PGCHIP->future[3] != 0 )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Unsupported CHIP format (future field bytes != 0)\n");
-        delete poDS;
-        return NULL;
-    }
-
-    if ( poDS->PGCHIP->compression != 0 )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Compressed CHIP unsupported\n");
-        delete poDS;
-        return NULL;
-    }
-    
-/* -------------------------------------------------------------------- */
-/*      Set some information from the file that is of interest.         */
-/* -------------------------------------------------------------------- */
-
-    poDS->nRasterXSize = poDS->PGCHIP->width;
-    poDS->nRasterYSize = poDS->PGCHIP->height;
-    poDS->nBands = 1; // (int)poDS->PGCHIP->future[0];
-    //poDS->nBitDepth = (int)poDS->PGCHIP->future[1];
-    poDS->nColorType = PGCHIP_COLOR_TYPE_GRAY; //(int)poDS->PGCHIP->future[2];
-
-    switch (poDS->PGCHIP->datatype)
-    {
-        case 5: // 24bit integer
-            poDS->nBitDepth = 24;
-            break;
-        case 6: // 16bit integer
-            poDS->nBitDepth = 16;
-            break;
-        case 8:
-            poDS->nBitDepth = 8;
-            break;
-        case 1: // float32
-        case 7: // 16bit ???
-        case 101: // float32 (NDR)
-        case 105: // 24bit integer (NDR)
-        case 106: // 16bit integer (NDR)
-        case 107: // 16bit ??? (NDR)
-        case 108: // 8bit ??? (NDR) [ doesn't make sense ]
-        default :
-             CPLError( CE_Failure, CPLE_AppDefined,
-                "Under development : CHIP datatype %d unsupported.\n",
-                poDS->PGCHIP->datatype);
-            break;   
-    }
-    
-        
-/* -------------------------------------------------------------------- */
-/*      Create band information objects.                                */
-/* -------------------------------------------------------------------- */
-    for( int iBand = 0; iBand < poDS->nBands; iBand++ )
-        poDS->SetBand( iBand+1, new PGCHIPRasterBand( poDS, iBand+1 ) );
-    
-    
-/* -------------------------------------------------------------------- */
-/*      Is there a palette?  Note: we should also read back and         */
-/*      apply transparency values if available.                         */
-/* -------------------------------------------------------------------- */
-    CPLAssert (poDS->nColorType != PGCHIP_COLOR_TYPE_PALETTE);
-    if( poDS->nColorType == PGCHIP_COLOR_TYPE_PALETTE )
-    {
-        unsigned char *pPalette;
-        int	nColorCount = 0;
-        int     sizePalette = 0;
-        int     offsetColor = -1;
-        GDALColorEntry oEntry;
-                
-        nColorCount = (int)poDS->PGCHIP->compression;
-        pPalette = (unsigned char *)chipdata + sizeof(CHIP);
-        sizePalette = nColorCount * sizeof(pgchip_color);
-        
-        poDS->poColorTable = new GDALColorTable();
-        
-        for( int iColor = 0; iColor < nColorCount; iColor++ )
-        {
-            oEntry.c1 = pPalette[offsetColor++];
-            oEntry.c2 = pPalette[offsetColor++];
-            oEntry.c3 = pPalette[offsetColor++];
-            oEntry.c4 = pPalette[offsetColor++];
-           
-            poDS->poColorTable->SetColorEntry( iColor, &oEntry );
-        }
-    }
-
-    return( poDS );
-}
-
-
-/************************************************************************/
-/*                           PGCHIPCreateCopy()                         */
-/************************************************************************/
-static GDALDataset * PGCHIPCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
-                int bStrict, char ** papszOptions, 
-                GDALProgressFunc pfnProgress, void * pProgressData ){
-
-    
-    PGconn          *hPGConn;
-    char            *pszTableName = NULL;
-    const char      *pszDSName = NULL;
-    char*            pszCommand;
-    PGresult        *hResult;
-    char            *pszProjection;
-    int              SRID;
-    GDALColorTable  *poCT= NULL;
-    int              bTableExists = FALSE;
-    int              bHasNameCol = FALSE;
-
-    int  nXSize = poSrcDS->GetRasterXSize();
-    int  nYSize = poSrcDS->GetRasterYSize();
-    int  nBands = poSrcDS->GetRasterCount();
-
-/* -------------------------------------------------------------------- */
-/*      Some some rudimentary checks                                    */
-/* -------------------------------------------------------------------- */
-
-    /* check number of bands */
-    if( nBands != 1 && nBands != 4)
-    {
-        CPLError( CE_Failure, CPLE_NotSupported, 
-                  "Under development : PGCHIP driver doesn't support %d bands.  Must be 1 or 4\n", nBands );
-
-        return NULL;
-    }
-
-    if( poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte 
-        && poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_UInt16)
-    {
-        CPLError( CE_Failure, CPLE_NotSupported, 
-                  "Under development : PGCHIP driver doesn't support data type %s. "
-                  "Only eight bit (Byte) and sixteen bit (UInt16) bands supported.\n", 
-                  GDALGetDataTypeName( 
-                      poSrcDS->GetRasterBand(1)->GetRasterDataType()) );
-
-        return NULL;
-    }
-
-    hPGConn = PGChipOpenConnection(pszFilename, &pszTableName, &pszDSName, FALSE, &bTableExists, &bHasNameCol);
-
-    /* Check Postgis connection string */
-    if( hPGConn == NULL){
-        CPLError( CE_Failure, CPLE_NotSupported, 
-                  "Cannont connect to %s.\n", pszFilename);
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Setup some parameters.                                          */
-/* -------------------------------------------------------------------- */
-    
-    int nBitDepth;
-    GDALDataType eType;
-    int storageChunk;
-    int nColorType=0;
-       
-    
-    if( nBands == 1 && poSrcDS->GetRasterBand(1)->GetColorTable() == NULL ){
-        nColorType = PGCHIP_COLOR_TYPE_GRAY;
-    }
-    else if( nBands == 1 ){
-        nColorType = PGCHIP_COLOR_TYPE_PALETTE;
-    }
-    else if( nBands == 4 ){
-        nColorType = PGCHIP_COLOR_TYPE_RGB_ALPHA;
-    }
-    
-    if( poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_UInt16 )
-    {
-        eType = GDT_Byte;
-        nBitDepth = 8;
-    }
-    else 
-    {
-        eType = GDT_UInt16;
-        nBitDepth = 16;
-    }
-    
-    storageChunk = nBitDepth/8;
-      
-    //printf("nBands = %d, nBitDepth = %d\n",nBands,nBitDepth);
-    
-    pszCommand = (char*)CPLMalloc(1024);
-
-    if(!bTableExists){
-        sprintf( pszCommand, 
-                "CREATE TABLE %s(raster chip, name varchar)",
-                pszTableName);
-
-        hResult = PQexec(hPGConn,pszCommand);
-        bHasNameCol = TRUE;
-    }
-    else
-    {
-        if (bHasNameCol)
-            sprintf( pszCommand, 
-                    "DELETE FROM %s WHERE name = '%s'", pszTableName, pszDSName);
-        else
-            sprintf( pszCommand, 
-                    "DELETE FROM %s", pszTableName);
-
-        hResult = PQexec(hPGConn,pszCommand);
-    }
-
-    if( hResult && (PQresultStatus(hResult) == PGRES_COMMAND_OK || PQresultStatus(hResult) == PGRES_TUPLES_OK)){
-        PQclear( hResult );
-    }
-    else {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "%s", PQerrorMessage(hPGConn) );
-        PQfinish( hPGConn );
-        hPGConn = NULL;
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Projection, finding SRID                                        */
-/* -------------------------------------------------------------------- */    
-  
-    pszProjection = (char *)poSrcDS->GetProjectionRef();
-    SRID = -1;
-    
-    if( !EQUALN(pszProjection,"GEOGCS",6)
-        && !EQUALN(pszProjection,"PROJCS",6)
-        && !EQUALN(pszProjection,"+",6)
-        && !EQUAL(pszProjection,"") )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                "Only OGC WKT Projections supported for writing to Postgis.\n"
-                "%s not supported.",
-                  pszProjection );
-    }
-    
-    
-    if( pszProjection[0]=='+')    
-        sprintf( pszCommand,"SELECT SRID FROM spatial_ref_sys where proj4text=%s",pszProjection);
-    else
-        sprintf( pszCommand,"SELECT SRID FROM spatial_ref_sys where srtext=%s",pszProjection);
-            
-    hResult = PQexec(hPGConn,pszCommand);
-        
-    if( hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK 
-             && PQntuples(hResult) > 0 ){
-        
-            SRID = atoi(PQgetvalue(hResult,0,0)); 
-        
-    }
-    
-    // Try to find SRID via EPSG number
-    if (SRID == -1 && strcmp(pszProjection,"") != 0){
-            
-            char *buf;
-            char epsg[16];
-            memset(epsg,0,16);
-            const char *workingproj = pszProjection;
-                
-            while( (buf = strstr(workingproj,"EPSG")) != 0){
-                workingproj = buf+4;
-            }
-            
-            int iChar = 0;
-            workingproj = workingproj + 3;
-            
-            
-            while(workingproj[iChar] != '"' && iChar < 15){
-                epsg[iChar] = workingproj[iChar];
-                iChar++;
-            }
-            
-            if(epsg[0] != 0){
-                SRID = atoi(epsg); 
-            }
-    }
-    else{
-            CPLError( CE_Failure, CPLE_AppDefined,
-                "Projection %s not found in spatial_ref_sys table. SRID will be set to -1.\n",
-                  pszProjection );
-        
-            SRID = -1;
-    }
-
-    if( hResult )
-        PQclear( hResult );
-        
-           
-/* -------------------------------------------------------------------- */
-/*      Write palette if there is one.  Technically, I think it is      */
-/*      possible to write 16bit palettes for PNG, but we will omit      */
-/*      this for now.                                                   */
-/* -------------------------------------------------------------------- */
-    
-    unsigned char	*pPalette = NULL;
-    int		bHaveNoData = FALSE;
-    double	dfNoDataValue = -1;
-    int nbColors = 0,bFoundTrans = FALSE;
-    size_t sizePalette = 0;
-    
-    if( nColorType == PGCHIP_COLOR_TYPE_PALETTE )
-    {
-        
-        GDALColorEntry  sEntry;
-        int		iColor;
-        int             offsetColor = -1;
-                        
-        poCT = poSrcDS->GetRasterBand(1)->GetColorTable();  
-        nbColors = poCT->GetColorEntryCount();
-                
-        sizePalette += sizeof(pgchip_color) * poCT->GetColorEntryCount();
-                
-        pPalette = (unsigned char *) CPLMalloc(sizePalette);
-               
-                                               
-        for( iColor = 0; iColor < poCT->GetColorEntryCount(); iColor++ )
-        {
-            poCT->GetColorEntryAsRGB( iColor, &sEntry );
-            if( sEntry.c4 != 255 )
-                bFoundTrans = TRUE;
-            
-            pPalette[offsetColor++]  = (unsigned char) sEntry.c1;
-            pPalette[offsetColor++]  = (unsigned char) sEntry.c2;
-            pPalette[offsetColor++]  = (unsigned char) sEntry.c3;
-            
-                       
-            if( bHaveNoData && iColor == (int) dfNoDataValue ){
-                pPalette[offsetColor++]  = 0;
-            }
-            else{
-                pPalette[offsetColor++]  = (unsigned char) sEntry.c4;
-            }
-        }
-    }
-    
-        
-/* -------------------------------------------------------------------- */
-/*     Initialize CHIP Structure                                        */
-/* -------------------------------------------------------------------- */  
-    
-    CHIP PGCHIP;
-    
-    memset(&PGCHIP,0,sizeof(PGCHIP));
-    
-    PGCHIP.factor = 1.0;
-    PGCHIP.endian_hint = 1;
-    PGCHIP.compression = 0; // nbColors; // To cope with palette extra information  : <header><palette><data>
-    PGCHIP.height = nYSize;
-    PGCHIP.width = nXSize;
-    PGCHIP.SRID = SRID;
-    PGCHIP.future[0] = 0; // nBands; //nBands is stored in future variable
-    PGCHIP.future[1] = 0; // nBitDepth; //nBitDepth is stored in future variable
-    PGCHIP.future[2] = 0; // nColorType; //nBitDepth is stored in future variable
-    PGCHIP.future[3] = 0; // nbColors; // Useless as we store nbColors in the "compression" integer
-    PGCHIP.data = NULL; // Serialized Form
-    
-    double adfGeoTransform[6];
-    if (GDALGetGeoTransform(poSrcDS, adfGeoTransform) == CE_None)
-    {
-        if (adfGeoTransform[2] == 0 &&
-            adfGeoTransform[4] == 0 &&
-            adfGeoTransform[5] < 0)
-        {
-            PGCHIP.bvol.xmin = adfGeoTransform[0];
-            PGCHIP.bvol.ymax = adfGeoTransform[3];
-            PGCHIP.bvol.xmax = adfGeoTransform[0] + nXSize * adfGeoTransform[1];
-            PGCHIP.bvol.ymin = adfGeoTransform[3] + nYSize * adfGeoTransform[5];
-        }
-        else
-        {
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "Could not write geotransform.\n" );
-        }
-    }
-
-    // PGCHIP.size changes if there is a palette.
-    // Is calculated by Postgis when inserting anyway
-    PGCHIP.size = sizeof(CHIP) - sizeof(void*) + (nYSize * nXSize * storageChunk * nBands) + sizePalette;
-    
-    switch(nBitDepth)
-    {
-        case 8:
-            PGCHIP.datatype = 8; // NDR|XDR ?
-            break;
-        case 16:
-            PGCHIP.datatype = 6; // NDR|XDR ?
-            break;
-        case 24:
-            PGCHIP.datatype = 5; // NDR|XDR ?
-            break;
-        default:
-             CPLError( CE_Failure, CPLE_AppDefined,"Under development : ERROR STORAGE CHUNK SIZE NOT SUPPORTED\n");
-            break;   
-    }
-    
-#ifdef PGCHIP_DEBUG
-    PGCHIPDataset::printChipInfo(PGCHIP);
-#endif
-                
-/* -------------------------------------------------------------------- */
-/*      Loop over image                                                 */
-/* -------------------------------------------------------------------- */
-       
-    CPLErr      eErr;
-    size_t lineSize = nXSize * storageChunk * nBands;
-    
-    // allocating data buffer
-    GByte *data = (GByte *) CPLMalloc( nYSize * lineSize);
-                    
-    for( int iLine = 0; iLine < nYSize; iLine++ ){
-        for( int iBand = 0; iBand < nBands; iBand++ ){
-            
-            GDALRasterBand * poBand = poSrcDS->GetRasterBand( iBand+1 );
-            
-            eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, 
-                                     data + (iBand*storageChunk) + iLine * lineSize, 
-                                     nXSize, 1, eType,
-                                     nBands * storageChunk, 
-                                     lineSize );  
-         }
-    }
-    
-        
-/* -------------------------------------------------------------------- */
-/*      Write Header, Palette and Data                                  */
-/* -------------------------------------------------------------------- */    
-    
-    char *result;
-    size_t j=0;
-    
-    // Calculating result length (*2 -> Hex form, +1 -> end string) 
-    size_t size_result = (PGCHIP.size * 2) + 1;
-        
-    // memory allocation
-    result = (char *) CPLMalloc( size_result * sizeof(char));
-            
-    // Assign chip
-    GByte *header = (GByte *)&PGCHIP;
-        
-    // Copy header into result string 
-    for(j=0; j<sizeof(PGCHIP)-sizeof(void*); j++) {
-        pgch_deparse_hex( header[j], (unsigned char*)&(result[j*2]));
-    }  
-    
-    // Copy Palette into result string if required
-    size_t offsetPalette = (sizeof(PGCHIP)-sizeof(void*)) * 2;
-    if(nColorType == PGCHIP_COLOR_TYPE_PALETTE && sizePalette>0){
-        for(j=0;j<sizePalette;j++){
-            pgch_deparse_hex( pPalette[j], (unsigned char *)&result[offsetPalette + (j*2)]);     
-        }                   
-    }
-    
-    // Copy data into result string
-    size_t offsetData = offsetPalette + sizePalette * 2;
-    for(j=0;j<(nYSize * lineSize);j++){
-         pgch_deparse_hex( data[j], (unsigned char *)&result[offsetData + (j*2)]);
-    }
-   
-    
-    // end string
-    result[offsetData + j*2] = '\0';
-    
-                                         
-/* -------------------------------------------------------------------- */
-/*      Inserting Chip                                                  */
-/* -------------------------------------------------------------------- */
-     
-    // Second allocation to cope with data size
-    CPLFree(pszCommand);
-    pszCommand = (char *)CPLMalloc(PGCHIP.size*2 + 256);
-
-    hResult = PQexec(hPGConn, "BEGIN");
-
-    if( hResult && PQresultStatus(hResult) == PGRES_COMMAND_OK )
-    {
-                        
-        PQclear( hResult );
-        if (bHasNameCol)
-            sprintf( pszCommand, 
-                    "INSERT INTO %s(raster, name) values('%s', '%s')",
-                    pszTableName,result, pszDSName);
-        else
-            sprintf( pszCommand, 
-                    "INSERT INTO %s(raster) values('%s')",
-                    pszTableName,result);
-                 
-                
-        hResult = PQexec(hPGConn,pszCommand);
-    
-    }
-    
-    CPLFree(pszTableName); pszTableName = NULL;
-    
-    if( hResult && PQresultStatus(hResult) == PGRES_COMMAND_OK ){
-        PQclear( hResult );
-    }
-    else {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "%s", PQerrorMessage(hPGConn) );
-        CPLFree(pszCommand); pszCommand = NULL;
-        PQfinish( hPGConn );
-        hPGConn = NULL;
-        return NULL;
-    }
-        
-    hResult = PQexec(hPGConn, "COMMIT");
-    PQclear( hResult );
-            
-    CPLFree( pszCommand ); pszCommand = NULL;
-    CPLFree( pPalette ); pPalette = NULL;
-    CPLFree( data ); data = NULL;
-    CPLFree( result ); result = NULL;
-
-    PQfinish( hPGConn );
-    hPGConn = NULL;
-
-    return (GDALDataset *)GDALOpen(pszFilename,GA_Update);
-}
-
-
-/************************************************************************/
-/*                          Display CHIP information                    */
-/************************************************************************/
-void     PGCHIPDataset::printChipInfo(const CHIP& c){
-
-    //if(this->PGCHIP != NULL){
-        printf("\n---< CHIP INFO >----\n");
-        printf("CHIP.datatype = %d\n", c.datatype);
-        printf("CHIP.compression = %d\n", c.compression);
-        printf("CHIP.size = %d\n", c.size);
-        printf("CHIP.factor = %f\n", c.factor);
-        printf("CHIP.width = %d\n", c.width);
-        printf("CHIP.height = %d\n", c.height);
-        //printf("CHIP.future[0] (nBands?) = %d\n", (int)c.future[0]);
-        //printf("CHIP.future[1] (nBitDepth?) = %d\n", (int)c.future[1]);
-        printf("--------------------\n");
-     //}
-}
-
-/************************************************************************/
-/*                              PGCHIPDelete                            */
-/************************************************************************/
-static CPLErr PGCHIPDelete(const char* pszFilename)
-{
-    return CE_None;
-}
-
-/************************************************************************/
-/*                          GDALRegister_PGCHIP()                       */
-/************************************************************************/
-void GDALRegister_PGCHIP(){
-
-    GDALDriver	*poDriver;
-
-    if( GDALGetDriverByName( "PGCHIP" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "PGCHIP" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Postgis CHIP raster" );
-                                   
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte UInt16" );
-         
-        poDriver->pfnOpen = PGCHIPDataset::Open;
-        poDriver->pfnCreateCopy = PGCHIPCreateCopy;
-        poDriver->pfnDelete = PGCHIPDelete;
-        
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
-}
-
diff --git a/frmts/pgchip/pgchiprasterband.cpp b/frmts/pgchip/pgchiprasterband.cpp
deleted file mode 100644
index 21abd35..0000000
--- a/frmts/pgchip/pgchiprasterband.cpp
+++ /dev/null
@@ -1,191 +0,0 @@
-/******************************************************************************
- *
- * File :    pgchiprasterband.cpp
- * Project:  PGCHIP Driver
- * Purpose:  GDALRasterBand code for POSTGIS CHIP/GDAL Driver 
- * Author:   Benjamin Simon, noumayoss at gmail.com
- *
- ******************************************************************************
- * Copyright (c) 2005, Benjamin Simon, noumayoss at gmail.com
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ******************************************************************************
- * 
- * Revision 1.1  2005/08/29 bsimon
- * New
- *
- */
-
-/************************************************************************/
-/* ==================================================================== */
-/*                            PGCHIPRasterBand                          */
-/* ==================================================================== */
-/************************************************************************/
-
-#include "pgchip.h"
-
-
-/************************************************************************/
-/*                           PGCHIPRasterBand()                         */
-/************************************************************************/
-
-PGCHIPRasterBand::PGCHIPRasterBand( PGCHIPDataset *poDS, int nBand ){
-
-    this->poDS = poDS;
-    this->nBand = nBand;
-    
-    if( poDS->nBitDepth == 16 )
-        eDataType = GDT_UInt16;
-    else
-        eDataType = GDT_Byte;
-
-    nBlockXSize = poDS->GetRasterXSize();
-    nBlockYSize = 1;
-    
-}
-
-/************************************************************************/
-/*                             IReadBlock()                             */
-/************************************************************************/
-
-CPLErr PGCHIPRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
-                                  void * pImage ){
-
-    PGCHIPDataset *poGDS = (PGCHIPDataset *) poDS;
-        
-    int        chipDataSize;
-    int        bandSize;
-    int        nPixelSize;
-    int        nPixelOffset;
-    int        nXSize;
-    int        i;
-    
-    // Must start on the very left
-    CPLAssert( nBlockXOff == 0 );
-           
-    
-    if( poGDS->nBitDepth == 16 )
-        nPixelSize = 2;
-    else
-        nPixelSize = 1;
-    
-    nXSize = GetXSize();
-    bandSize = nPixelSize * nXSize;
-    int sizePalette = 0;        
-    
-    if(poGDS->nColorType == PGCHIP_COLOR_TYPE_PALETTE){
-        sizePalette = (int)poGDS->PGCHIP->compression * sizeof(pgchip_color);
-    }
-    
-    // Determine size of whole Image Data
-    chipDataSize = poGDS->PGCHIP->size - (sizeof(CHIP)-sizeof(void*)) - sizePalette;
-    
-//printf("sizePalette: %d\n", sizePalette);
-     
-/* -------------------------------------------------------------------- */
-/*      Extracting band from pointer                                    */
-/* -------------------------------------------------------------------- */
-     
-               
-//printf("About to IReadBlock nBlockXOff: %d  nBlockYOff: %d, pixelSize: %d, pixelOffset:%d nXSize: %d, bandSize:%d\n", nBlockXOff, nBlockYOff, nPixelSize, nPixelOffset, nXSize, bandSize);
-
-    char* dataptr = (char*)&(poGDS->PGCHIP->data);
-    size_t bandoffset = nBlockYOff * bandSize + nBlockXOff * nPixelSize;
-
-    // This is for supporting nBands > 1
-    nPixelOffset = poGDS->nBands * nPixelSize;
-
-    if( nPixelSize == 1 ){
-    
-        char *bufferData = (char*)(dataptr + bandoffset);
-            
-        for(i = 0; i < nXSize; i++ ){
-            ((char *) pImage)[i] = bufferData[i*nPixelOffset];
-        }
-    }
-    else {
-
-        CPLAssert (nPixelSize==2);
-    
-        //GUInt16 *bufferData = (GUInt16 *)((char*)(dataptr + bandoffset));
-         
-        for(i = 0; i < nXSize; i++ )
-        {
-            // I'm not sure what we need this for
-            size_t offset = i*nPixelOffset;
-
-#if 0
-            printf("Reading from ptr %p at offset %d (%d total offset - %d)\n",
-                bufferData, offset,
-                (char*)&(bufferData[offset])-dataptr,
-                bandoffset+offset);
-#endif
-            
-            ((GUInt16 *) pImage)[i] = *(GUInt16*)&dataptr[bandoffset+offset];
-            
-        }
-    }
-     
-         
-    return CE_None;
-}
-
-
-
-/************************************************************************/
-/*                       GetColorInterpretation()                       */
-/************************************************************************/
-GDALColorInterp PGCHIPRasterBand::GetColorInterpretation(){
-
-    PGCHIPDataset	*poGDS = (PGCHIPDataset *) poDS;
-
-    if( poGDS->nColorType == PGCHIP_COLOR_TYPE_GRAY ){
-        return GCI_GrayIndex;
-    }
-    else  if( poGDS->nColorType == PGCHIP_COLOR_TYPE_PALETTE ){
-        return GCI_PaletteIndex;    
-    }
-    else if(poGDS->nColorType == PGCHIP_COLOR_TYPE_RGB_ALPHA){
-        if( nBand == 1 )
-            return GCI_RedBand;
-        else if( nBand == 2 )
-            return GCI_GreenBand;
-        else if( nBand == 3 )
-            return GCI_BlueBand;
-        else 
-            return GCI_AlphaBand;
-    }
-    
-    return GCI_GrayIndex;
-}
-
-
-/************************************************************************/
-/*                           GetColorTable()                            */
-/************************************************************************/
-
-GDALColorTable *PGCHIPRasterBand::GetColorTable(){
-
-    PGCHIPDataset	*poGDS = (PGCHIPDataset *) poDS;
-
-    if( nBand == 1 )
-        return poGDS->poColorTable;
-    else
-        return NULL;
-}
diff --git a/frmts/pgchip/pgchiputilities.cpp b/frmts/pgchip/pgchiputilities.cpp
deleted file mode 100644
index 4c3802e..0000000
--- a/frmts/pgchip/pgchiputilities.cpp
+++ /dev/null
@@ -1,290 +0,0 @@
-/******************************************************************************
- *
- * File :    pgchiputilities.cpp
- * Project:  PGCHIP Driver
- * Purpose:  Utility functions for POSTGIS CHIP/GDAL Driver 
- * Author:   Benjamin Simon, noumayoss at gmail.com
- *
- ******************************************************************************
- * Copyright (c) 2005, Benjamin Simon, noumayoss at gmail.com
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ******************************************************************************
- * 
- * Revision 1.1  2005/08/29 bsimon
- * New
- *
- */
- 
-#include "pgchip.h"
-
-/************************************************************************/
-/* ==================================================================== */
-/*				Utility Hex Functions                   */
-/* ==================================================================== */
-/************************************************************************/
-
-void pgch_deparse_hex(unsigned char str, unsigned char *result){
-
-	int	input_high;
-	int  input_low;
-
-	input_high = (str>>4);
-	input_low = (str & 0x0F);
-
-	switch (input_high)
-	{
-		case 0:
-			result[0] = '0';
-			break;
-		case 1:
-			result[0] = '1';
-			break;
-		case 2:
-			result[0] = '2';
-			break;
-		case 3:
-			result[0] = '3';
-			break;
-		case 4:
-			result[0] = '4';
-			break;
-		case 5:
-			result[0] = '5';
-			break;
-		case 6:
-			result[0] = '6';
-			break;
-		case 7:
-			result[0] = '7';
-			break;
-		case 8:
-			result[0] = '8';
-			break;
-		case 9:
-			result[0] = '9';
-			break;
-		case 10:
-			result[0] = 'A';
-			break;
-		case 11:
-			result[0] = 'B';
-			break;
-		case 12:
-			result[0] = 'C';
-			break;
-		case 13:
-			result[0] = 'D';
-			break;
-		case 14:
-			result[0] = 'E';
-			break;
-		case 15:
-			result[0] = 'F';
-			break;
-	}
-
-	switch (input_low)
-	{
-		case 0:
-			result[1] = '0';
-			break;
-		case 1:
-			result[1] = '1';
-			break;
-		case 2:
-			result[1] = '2';
-			break;
-		case 3:
-			result[1] = '3';
-			break;
-		case 4:
-			result[1] = '4';
-			break;
-		case 5:
-			result[1] = '5';
-			break;
-		case 6:
-			result[1] = '6';
-			break;
-		case 7:
-			result[1] = '7';
-			break;
-		case 8:
-			result[1] = '8';
-			break;
-		case 9:
-			result[1] = '9';
-			break;
-		case 10:
-			result[1] = 'A';
-			break;
-		case 11:
-			result[1] = 'B';
-			break;
-		case 12:
-			result[1] = 'C';
-			break;
-		case 13:
-			result[1] = 'D';
-			break;
-		case 14:
-			result[1] = 'E';
-			break;
-		case 15:
-			result[1] = 'F';
-			break;
-	}
-}
-
-//given a string with at least 2 chars in it, convert them to
-// a byte value.  No error checking done!
-unsigned char parse_hex(char *str){
-
-	//do this a little brute force to make it faster
-
-	unsigned char		result_high = 0;
-	unsigned char		result_low = 0;
-
-	switch (str[0])
-	{
-		case '0' :
-			result_high = 0;
-			break;
-		case '1' :
-			result_high = 1;
-			break;
-		case '2' :
-			result_high = 2;
-			break;
-		case '3' :
-			result_high = 3;
-			break;
-		case '4' :
-			result_high = 4;
-			break;
-		case '5' :
-			result_high = 5;
-			break;
-		case '6' :
-			result_high = 6;
-			break;
-		case '7' :
-			result_high = 7;
-			break;
-		case '8' :
-			result_high = 8;
-			break;
-		case '9' :
-			result_high = 9;
-			break;
-		case 'A' :
-			result_high = 10;
-			break;
-		case 'B' :
-			result_high = 11;
-			break;
-		case 'C' :
-			result_high = 12;
-			break;
-		case 'D' :
-			result_high = 13;
-			break;
-		case 'E' :
-			result_high = 14;
-			break;
-		case 'F' :
-			result_high = 15;
-			break;
-	}
-	switch (str[1])
-	{
-		case '0' :
-			result_low = 0;
-			break;
-		case '1' :
-			result_low = 1;
-			break;
-		case '2' :
-			result_low = 2;
-			break;
-		case '3' :
-			result_low = 3;
-			break;
-		case '4' :
-			result_low = 4;
-			break;
-		case '5' :
-			result_low = 5;
-			break;
-		case '6' :
-			result_low = 6;
-			break;
-		case '7' :
-			result_low = 7;
-			break;
-		case '8' :
-			result_low = 8;
-			break;
-		case '9' :
-			result_low = 9;
-			break;
-		case 'A' :
-			result_low = 10;
-			break;
-		case 'B' :
-			result_low = 11;
-			break;
-		case 'C' :
-			result_low = 12;
-			break;
-		case 'D' :
-			result_low = 13;
-			break;
-		case 'E' :
-			result_low = 14;
-			break;
-		case 'F' :
-			result_low = 15;
-			break;
-	}
-	return (unsigned char) ((result_high<<4) + result_low);
-}
-
-/* Parse an hex string */
-void parse_hex_string(unsigned char *strOut,char *strIn,int length){
-    
-    int i;
-    for(i=0;i<length;i++){
-        //printf("Before = %c\n",strIn[i]);
-        strOut[i] = parse_hex(&strIn[i]);
-        //printf("After = %c\n",strOut[i]);
-        }
-
-}
-
-/* Deparse an hex string */
-void deparse_hex_string(unsigned char *strOut,char *strIn,int length){
-    
-    int i;
-    
-    for(i=0;i<length;i++)
-        pgch_deparse_hex(strIn[i],&strOut[i]);
-
-}
diff --git a/frmts/pgchip/todo b/frmts/pgchip/todo
deleted file mode 100644
index e9a65ef..0000000
--- a/frmts/pgchip/todo
+++ /dev/null
@@ -1,9 +0,0 @@
-TODO List :
-
-* Test Driver compatibility with various raster formats
-* Modify the connection string to cope with the name of the raster column
-* Improve the number of color interpretation options
-* Manage geoTrasnform
-* Deal with more datatypes
-* Improve SRID conversion
-* Test makefile.vc (Visual C)
diff --git a/frmts/plmosaic/frmt_plmosaic.html b/frmts/plmosaic/frmt_plmosaic.html
index 3bb60d4..ca1557b 100644
--- a/frmts/plmosaic/frmt_plmosaic.html
+++ b/frmts/plmosaic/frmt_plmosaic.html
@@ -26,7 +26,7 @@ take a long time to complete.<p>
 
 The minimal syntax to open a datasource is : <pre>PLMosaic:[options]</pre><p>
 
-Additionnal optional parameters can be specified after the ':' sign.
+Additional optional parameters can be specified after the ':' sign.
 Currently the following one is supported :<p>
 
 <ul>
@@ -71,7 +71,7 @@ information about the underneath quad and the scenes that compose it (only scene
 whose footprint intersect the point are listed). This is
 the syntax used by the gdallocationinfo utility
 (see <a href="https://trac.osgeo.org/gdal/wiki/rfc32_gdallocationinfo">RFC 32</a>)
-</p> 
+</p>
 
 <p>Below an example of the return :
 <pre>
@@ -214,15 +214,15 @@ Lower Right (20037508.340,-20037508.340) (180d 0' 0.00"E, 85d 3' 4.06"S)
 Center      (   0.0000063,  -0.0000063) (  0d 0' 0.00"E,  0d 0' 0.00"S)
 Band 1 Block=256x256 Type=Byte, ColorInterp=Red
   Overviews: 4194304x4194304, ..., 256x256
-  Mask Flags: PER_DATASET ALPHA 
+  Mask Flags: PER_DATASET ALPHA
   Overviews of mask band: Overviews: 4194304x4194304, ..., 256x256
 Band 2 Block=256x256 Type=Byte, ColorInterp=Green
   Overviews: 4194304x4194304, ..., 256x256
-  Mask Flags: PER_DATASET ALPHA 
+  Mask Flags: PER_DATASET ALPHA
   Overviews of mask band: Overviews: 4194304x4194304, ..., 256x256
 Band 3 Block=256x256 Type=Byte, ColorInterp=Blue
   Overviews: 4194304x4194304, ..., 256x256
-  Mask Flags: PER_DATASET ALPHA 
+  Mask Flags: PER_DATASET ALPHA
   Overviews of mask band: Overviews: 4194304x4194304, ..., 256x256
 Band 4 Block=256x256 Type=Byte, ColorInterp=Alpha
   Overviews: 4194304x4194304, ..., 256x256
diff --git a/frmts/plmosaic/plmosaicdataset.cpp b/frmts/plmosaic/plmosaicdataset.cpp
index 6e4bc20..701b264 100644
--- a/frmts/plmosaic/plmosaicdataset.cpp
+++ b/frmts/plmosaic/plmosaicdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: plmosaicdataset.cpp 29019 2015-04-25 20:34:19Z rouault $
+ * $Id: plmosaicdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  PLMosaic driver
  * Purpose:  PLMosaic driver
@@ -27,17 +27,17 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_priv.h"
+#include "cpl_http.h"
+#include "cpl_minixml.h"
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
+#include "gdal_priv.h"
 #include "ogr_spatialref.h"
 #include "ogrsf_frmts.h"
-#include "cpl_http.h"
-#include "cpl_minixml.h"
-#include <json.h>
 
-CPL_CVSID("$Id: plmosaicdataset.cpp 29019 2015-04-25 20:34:19Z rouault $");
+#include <json.h>
 
-extern "C" void GDALRegister_PLMOSAIC();
+CPL_CVSID("$Id: plmosaicdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 // g++ -fPIC -g -Wall frmts/plmosaic/*.cpp -shared -o gdal_PLMOSAIC.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/geojson/libjson -L. -lgdal
 
@@ -67,8 +67,8 @@ class PLMosaicRasterBand;
 class PLMosaicDataset : public GDALPamDataset
 {
     friend class PLMosaicRasterBand;
-    
-        int                     bMustCleanPersistant;
+
+        int                     bMustCleanPersistent;
         CPLString               osCachePathRoot;
         int                     bTrustCache;
         CPLString               osBaseURL;
@@ -115,14 +115,14 @@ class PLMosaicDataset : public GDALPamDataset
   public:
                 PLMosaicDataset();
                 ~PLMosaicDataset();
-    
+
     static int Identify( GDALOpenInfo * poOpenInfo );
     static GDALDataset  *Open( GDALOpenInfo * );
 
     virtual CPLErr  IRasterIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
                                void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType, 
+                               GDALDataType eBufType,
                                int nBandCount, int *panBandMap,
                                GSpacing nPixelSpace, GSpacing nLineSpace,
                                GSpacing nBandSpace,
@@ -173,17 +173,17 @@ class PLMosaicRasterBand : public GDALRasterBand
 /*                        PLMosaicRasterBand()                          */
 /************************************************************************/
 
-PLMosaicRasterBand::PLMosaicRasterBand( PLMosaicDataset *poDS, int nBand,
-                                        GDALDataType eDataType )
+PLMosaicRasterBand::PLMosaicRasterBand( PLMosaicDataset *poDSIn, int nBandIn,
+                                        GDALDataType eDataTypeIn )
 
 {
-    this->eDataType = eDataType;
-    this->nBlockXSize = 256;
-    this->nBlockYSize = 256;
+    this->eDataType = eDataTypeIn;
+    nBlockXSize = 256;
+    nBlockYSize = 256;
+
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
 
-    this->poDS = poDS;
-    this->nBand = nBand;
-    
     if( eDataType == GDT_UInt16 )
     {
         if( nBand <= 3 )
@@ -196,37 +196,41 @@ PLMosaicRasterBand::PLMosaicRasterBand( PLMosaicDataset *poDS, int nBand,
 /************************************************************************/
 
 CPLErr PLMosaicRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
-                                       void * pImage )
+                                       void *pImage )
 {
-    PLMosaicDataset* poMOSDS = (PLMosaicDataset*) poDS;
-    //CPLDebug("PLMOSAIC", "IReadBlock(band=%d, x=%d, y=%d)", nBand, xBlock, yBlock);
+    PLMosaicDataset* poMOSDS = reinterpret_cast<PLMosaicDataset *>( poDS );
+
+#ifdef DEBUG_VERBOSE
+    CPLDebug("PLMOSAIC", "IReadBlock(band=%d, x=%d, y=%d)",
+             nBand, nBlockYOff, nBlockYOff);
+#endif
 
     if( poMOSDS->bUseTMSForMain && poMOSDS->poTMSDS )
         return poMOSDS->poTMSDS->GetRasterBand(nBand)->ReadBlock(nBlockXOff, nBlockYOff,
                                                                 pImage);
 
-    int bottom_yblock = (nRasterYSize - nBlockYOff * nBlockYSize) / nBlockYSize - 1;
+    const int bottom_yblock = (nRasterYSize - nBlockYOff * nBlockYSize) / nBlockYSize - 1;
 
-    int meta_tile_x = (nBlockXOff * nBlockXSize) / poMOSDS->nQuadSize;
-    int meta_tile_y = (bottom_yblock * nBlockYSize) / poMOSDS->nQuadSize;
-    int sub_tile_x = nBlockXOff % (poMOSDS->nQuadSize / nBlockXSize);
-    int sub_tile_y = nBlockYOff % (poMOSDS->nQuadSize / nBlockYSize);
+    const int meta_tile_x = (nBlockXOff * nBlockXSize) / poMOSDS->nQuadSize;
+    const int meta_tile_y = (bottom_yblock * nBlockYSize) / poMOSDS->nQuadSize;
+    const int sub_tile_x = nBlockXOff % (poMOSDS->nQuadSize / nBlockXSize);
+    const int sub_tile_y = nBlockYOff % (poMOSDS->nQuadSize / nBlockYSize);
 
     GDALDataset *poMetaTileDS = poMOSDS->GetMetaTile(meta_tile_x, meta_tile_y);
     if( poMetaTileDS == NULL )
     {
-        memset(pImage, 0, 
+        memset(pImage, 0,
                nBlockXSize * nBlockYSize * (GDALGetDataTypeSize(eDataType)/8));
         return CE_None;
     }
 
     return poMetaTileDS->GetRasterBand(nBand)->
-                RasterIO( GF_Read, 
+                RasterIO( GF_Read,
                         sub_tile_x * nBlockXSize,
                         sub_tile_y * nBlockYSize,
                         nBlockXSize,
                         nBlockYSize,
-                        pImage, nBlockXSize, nBlockYSize, 
+                        pImage, nBlockXSize, nBlockYSize,
                         eDataType, 0, 0, NULL);
 }
 
@@ -241,7 +245,7 @@ CPLErr PLMosaicRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                                          GSpacing nPixelSpace, GSpacing nLineSpace,
                                          GDALRasterIOExtraArg* psExtraArg )
 {
-    PLMosaicDataset* poMOSDS = (PLMosaicDataset*) poDS;
+    PLMosaicDataset* poMOSDS = reinterpret_cast<PLMosaicDataset *>( poDS );
     if( poMOSDS->bUseTMSForMain && poMOSDS->poTMSDS )
         return poMOSDS->poTMSDS->GetRasterBand(nBand)->RasterIO(
                                          eRWFlag, nXOff, nYOff, nXSize, nYSize,
@@ -264,11 +268,11 @@ const char* PLMosaicRasterBand::GetMetadataItem( const char* pszName,
     if( pszName != NULL && pszDomain != NULL && EQUAL(pszDomain, "LocationInfo") &&
         sscanf(pszName, "Pixel_%d_%d", &nPixel, &nLine) == 2 )
     {
-        PLMosaicDataset* poMOSDS = (PLMosaicDataset*) poDS;
+        PLMosaicDataset* poMOSDS = reinterpret_cast<PLMosaicDataset *>( poDS );
         return poMOSDS->GetLocationInfo(nPixel, nLine);
     }
-    else
-        return GDALRasterBand::GetMetadataItem(pszName, pszDomain);
+
+    return GDALRasterBand::GetMetadataItem(pszName, pszDomain);
 }
 
 
@@ -278,9 +282,10 @@ const char* PLMosaicRasterBand::GetMetadataItem( const char* pszName,
 
 int PLMosaicRasterBand::GetOverviewCount()
 {
-    PLMosaicDataset *poGDS = (PLMosaicDataset *) poDS;
+    PLMosaicDataset *poGDS = reinterpret_cast<PLMosaicDataset *>( poDS );
     if( !poGDS->poTMSDS )
         return 0;
+
     return poGDS->poTMSDS->GetRasterBand(1)->GetOverviewCount();
 }
 
@@ -290,7 +295,7 @@ int PLMosaicRasterBand::GetOverviewCount()
 
 GDALRasterBand* PLMosaicRasterBand::GetOverview(int iOvrLevel)
 {
-    PLMosaicDataset *poGDS = (PLMosaicDataset *) poDS;
+    PLMosaicDataset *poGDS = reinterpret_cast<PLMosaicDataset *>( poDS );
     if (iOvrLevel < 0 || iOvrLevel >= GetOverviewCount())
         return NULL;
 
@@ -331,29 +336,30 @@ GDALColorInterp PLMosaicRasterBand::GetColorInterpretation()
 /*                        PLMosaicDataset()                            */
 /************************************************************************/
 
-PLMosaicDataset::PLMosaicDataset()
+PLMosaicDataset::PLMosaicDataset() :
+    bMustCleanPersistent(FALSE),
+    bTrustCache(FALSE),
+    pszWKT(NULL),
+    nQuadSize(0),
+    bHasGeoTransform(FALSE),
+    nZoomLevel(0),
+    bUseTMSForMain(FALSE),
+    poTMSDS(NULL),
+    nCacheMaxSize(10),
+    psHead(NULL),
+    psTail(NULL),
+    nLastMetaTileX(-1),
+    nLastMetaTileY(-1)
 {
-    bMustCleanPersistant = FALSE;
-    bTrustCache = FALSE;
-    pszWKT = NULL;
-    nQuadSize = 0;
-    bHasGeoTransform = FALSE;
     adfGeoTransform[0] = 0;
     adfGeoTransform[1] = 1;
     adfGeoTransform[2] = 0;
     adfGeoTransform[3] = 0;
     adfGeoTransform[4] = 0;
     adfGeoTransform[5] = 1;
-    nZoomLevel = 0;
-    psHead = NULL;
-    psTail = NULL;
+
     SetMetadataItem("INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE");
     osCachePathRoot = CPLGetPath(CPLGenerateTempFilename(""));
-    nCacheMaxSize = 10;
-    nLastMetaTileX = -1;
-    nLastMetaTileY = -1;
-    bUseTMSForMain = FALSE;
-    poTMSDS = NULL;
 }
 
 /************************************************************************/
@@ -366,14 +372,14 @@ PLMosaicDataset::~PLMosaicDataset()
     FlushCache();
     CPLFree(pszWKT);
     delete poTMSDS;
-    if (bMustCleanPersistant)
+    if (bMustCleanPersistent)
     {
-        char** papszOptions = NULL;
-        papszOptions = CSLSetNameValue(papszOptions, "CLOSE_PERSISTENT", CPLSPrintf("PLMOSAIC:%p", this));
-        CPLHTTPFetch( osBaseURL, papszOptions);
+        char** papszOptions
+            = CSLSetNameValue(NULL, "CLOSE_PERSISTENT",
+                              CPLSPrintf("PLMOSAIC:%p", this));
+        CPLHTTPDestroyResult( CPLHTTPFetch( osBaseURL, papszOptions) );
         CSLDestroy(papszOptions);
     }
-
 }
 
 /************************************************************************/
@@ -390,7 +396,8 @@ void PLMosaicDataset::FlushDatasetsCache()
         delete psIter;
         psIter = psNext;
     }
-    psHead = psTail = NULL;
+    psHead = NULL;
+    psTail = NULL;
     oMapLinkedDatasets.clear();
 }
 
@@ -418,7 +425,7 @@ void PLMosaicDataset::FlushCache()
 int PLMosaicDataset::Identify( GDALOpenInfo * poOpenInfo )
 
 {
-    return EQUALN(poOpenInfo->pszFilename, "PLMOSAIC:", strlen("PLMOSAIC:"));
+    return STARTS_WITH_CI(poOpenInfo->pszFilename, "PLMOSAIC:");
 }
 
 /************************************************************************/
@@ -427,13 +434,13 @@ int PLMosaicDataset::Identify( GDALOpenInfo * poOpenInfo )
 
 char** PLMosaicDataset::GetBaseHTTPOptions()
 {
-    bMustCleanPersistant = TRUE;
+    bMustCleanPersistent = TRUE;
 
-    char** papszOptions = NULL;
-    papszOptions = CSLAddString(papszOptions, CPLSPrintf("PERSISTENT=PLMOSAIC:%p", this));
+    char** papszOptions
+        = CSLAddString(NULL, CPLSPrintf("PERSISTENT=PLMOSAIC:%p", this));
     /* Use basic auth, rather than Authorization headers since curl would forward it to S3 */
     papszOptions = CSLAddString(papszOptions, CPLSPrintf("USERPWD=%s:", osAPIKey.c_str()));
-    
+
     return papszOptions;
 }
 
@@ -446,24 +453,26 @@ CPLHTTPResult* PLMosaicDataset::Download(const char* pszURL,
 {
     char** papszOptions = CSLAddString(GetBaseHTTPOptions(), NULL);
     CPLHTTPResult * psResult;
-    if( strncmp(osBaseURL, "/vsimem/", strlen("/vsimem/")) == 0 &&
-        strncmp(pszURL, "/vsimem/", strlen("/vsimem/")) == 0 )
+    if( STARTS_WITH(osBaseURL, "/vsimem/") &&
+        STARTS_WITH(pszURL, "/vsimem/") )
     {
         CPLDebug("PLSCENES", "Fetching %s", pszURL);
-        psResult = (CPLHTTPResult*) CPLCalloc(1, sizeof(CPLHTTPResult));
+        psResult = reinterpret_cast<CPLHTTPResult *>(
+            CPLCalloc( 1, sizeof( CPLHTTPResult ) ) );
         vsi_l_offset nDataLength = 0;
         CPLString osURL(pszURL);
         if( osURL[osURL.size()-1 ] == '/' )
             osURL.resize(osURL.size()-1);
-        GByte* pabyBuf = VSIGetMemFileBuffer(osURL, &nDataLength, FALSE); 
+        GByte* pabyBuf = VSIGetMemFileBuffer(osURL, &nDataLength, FALSE);
         if( pabyBuf )
         {
-            psResult->pabyData = (GByte*) VSIMalloc(1 + (size_t)nDataLength);
+            psResult->pabyData = reinterpret_cast<GByte *>(
+                VSIMalloc(1 + static_cast<size_t>( nDataLength ) ) );
             if( psResult->pabyData )
             {
-                memcpy(psResult->pabyData, pabyBuf, (size_t)nDataLength);
+                memcpy(psResult->pabyData, pabyBuf, static_cast<size_t>( nDataLength ) );
                 psResult->pabyData[nDataLength] = 0;
-                psResult->nDataLen = (size_t)nDataLength;
+                psResult->nDataLen = static_cast<int>( nDataLength );
             }
         }
         else
@@ -481,19 +490,20 @@ CPLHTTPResult* PLMosaicDataset::Download(const char* pszURL,
             CPLPopErrorHandler();
     }
     CSLDestroy(papszOptions);
-    
+
     if( psResult->pszErrBuf != NULL )
     {
         if( !(bQuiet404Error && strstr(psResult->pszErrBuf, "404")) )
         {
-            CPLError(CE_Failure, CPLE_AppDefined, "%s",
-                    psResult->pabyData ? (const char*) psResult->pabyData :
-                    psResult->pszErrBuf);
+            CPLError( CE_Failure, CPLE_AppDefined, "%s",
+                      psResult->pabyData ? reinterpret_cast<const char*>(
+                          psResult->pabyData ) :
+                      psResult->pszErrBuf );
         }
         CPLHTTPDestroyResult(psResult);
         return NULL;
     }
-    
+
     if( psResult->pabyData == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Empty content returned by server");
@@ -517,11 +527,9 @@ json_object* PLMosaicDataset::RunRequest(const char* pszURL,
         return NULL;
     }
 
-    json_tokener* jstok = NULL;
-    json_object* poObj = NULL;
-
-    jstok = json_tokener_new();
-    poObj = json_tokener_parse_ex(jstok, (const char*) psResult->pabyData, -1);
+    json_tokener* jstok = json_tokener_new();
+    json_object* poObj
+        = json_tokener_parse_ex(jstok, (const char*) psResult->pabyData, -1);
     if( jstok->err != json_tokener_success)
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -541,7 +549,7 @@ json_object* PLMosaicDataset::RunRequest(const char* pszURL,
         json_object_put(poObj);
         poObj = NULL;
     }
-    
+
     return poObj;
 }
 
@@ -572,7 +580,7 @@ GDALDataset *PLMosaicDataset::Open( GDALOpenInfo * poOpenInfo )
     PLMosaicDataset* poDS = new PLMosaicDataset();
 
     poDS->osBaseURL = CPLGetConfigOption("PL_URL", "https://api.planet.com/v0/mosaics/");
-    
+
     char** papszOptions = CSLTokenizeStringComplex(
             poOpenInfo->pszFilename+strlen("PLMosaic:"), ",", TRUE, FALSE );
     for( char** papszIter = papszOptions; papszIter && *papszIter; papszIter ++ )
@@ -614,10 +622,10 @@ GDALDataset *PLMosaicDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->osCachePathRoot = PLMosaicGetParameter(poOpenInfo, papszOptions, "cache_path",
                                           CPLGetConfigOption("PL_CACHE_PATH",""));
 
-    poDS->bTrustCache = CSLTestBoolean(PLMosaicGetParameter(
+    poDS->bTrustCache = CPLTestBool(PLMosaicGetParameter(
                         poOpenInfo, papszOptions, "trust_cache", "FALSE"));
 
-    poDS->bUseTMSForMain = CSLTestBoolean(PLMosaicGetParameter(
+    poDS->bUseTMSForMain = CPLTestBool(PLMosaicGetParameter(
                         poOpenInfo, papszOptions, "use_tiles", "FALSE"));
 
     CSLDestroy(papszOptions);
@@ -643,18 +651,19 @@ GDALDataset *PLMosaicDataset::Open( GDALOpenInfo * poOpenInfo )
             char** papszMD = poDS->GetMetadata("SUBDATASETS");
             if( CSLCount(papszMD) == 2 )
             {
-                CPLString osOldFilename(poOpenInfo->pszFilename);
-                CPLString osMosaicConnectionString = CSLFetchNameValue(papszMD, "SUBDATASET_1_NAME");
+                const CPLString osOldFilename(poOpenInfo->pszFilename);
+                const CPLString osMosaicConnectionString
+                    = CSLFetchNameValue(papszMD, "SUBDATASET_1_NAME");
                 delete poDS;
                 GDALOpenInfo oOpenInfo(osMosaicConnectionString.c_str(), GA_ReadOnly);
                 oOpenInfo.papszOpenOptions = poOpenInfo->papszOpenOptions;
-                poDS = (PLMosaicDataset*) Open(&oOpenInfo);
+                poDS = reinterpret_cast<PLMosaicDataset *>( Open(&oOpenInfo) );
                 if( poDS )
                     poDS->SetDescription(osOldFilename);
             }
         }
     }
-    
+
     if( poDS )
         poDS->SetPamFlags(0);
 
@@ -670,12 +679,12 @@ static void ReplaceSubString(CPLString &osTarget,
                              CPLString osReplacement)
 
 {
-    // assumes only one occurance of osPattern
+    // Assumes only one occurrence of osPattern.
     size_t pos = osTarget.find(osPattern);
     if( pos == CPLString::npos )
         return;
 
-    osTarget.replace(pos, osPattern.size(), osReplacement); 
+    osTarget.replace(pos, osPattern.size(), osReplacement);
 }
 
 /************************************************************************/
@@ -686,8 +695,10 @@ CPLString PLMosaicDataset::GetMosaicCachePath()
 {
     if( osCachePathRoot.size() )
     {
-        CPLString osCachePath(CPLFormFilename(osCachePathRoot, "plmosaic_cache", NULL));
-        CPLString osMosaicPath(CPLFormFilename(osCachePath, osMosaic, NULL));
+        const CPLString osCachePath(
+            CPLFormFilename(osCachePathRoot, "plmosaic_cache", NULL));
+        const CPLString osMosaicPath(
+            CPLFormFilename(osCachePath, osMosaic, NULL));
 
         return osMosaicPath;
     }
@@ -702,8 +713,10 @@ void PLMosaicDataset::CreateMosaicCachePathIfNecessary()
 {
     if( osCachePathRoot.size() )
     {
-        CPLString osCachePath(CPLFormFilename(osCachePathRoot, "plmosaic_cache", NULL));
-        CPLString osMosaicPath(CPLFormFilename(osCachePath, osMosaic, NULL));
+        const CPLString osCachePath(
+            CPLFormFilename(osCachePathRoot, "plmosaic_cache", NULL));
+        const CPLString osMosaicPath(
+            CPLFormFilename(osCachePath, osMosaic, NULL));
 
         VSIStatBufL sStatBuf;
         if( VSIStatL(osMosaicPath, &sStatBuf) != 0 )
@@ -758,7 +771,7 @@ int PLMosaicDataset::OpenMosaic()
         json_object_put(poObj);
         return FALSE;
     }
-    
+
     const char* pszSRS = json_object_get_string(poCoordinateSystem);
     if( !EQUAL(pszSRS, "EPSG:3857") )
     {
@@ -771,7 +784,7 @@ int PLMosaicDataset::OpenMosaic()
     OGRSpatialReference oSRS;
     oSRS.SetFromUserInput(pszSRS);
     oSRS.exportToWkt(&pszWKT);
-    
+
     GDALDataType eDT = GDT_Unknown;
     const char* pszDataType = json_object_get_string(poDataType);
     if( EQUAL(pszDataType, "byte") )
@@ -787,7 +800,7 @@ int PLMosaicDataset::OpenMosaic()
         json_object_put(poObj);
         return FALSE;
     }
-    
+
     if( bUseTMSForMain && eDT != GDT_Byte )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
@@ -804,11 +817,11 @@ int PLMosaicDataset::OpenMosaic()
         return FALSE;
     }
 
-    double dfResolution = json_object_get_double(poResolution);
+    const double dfResolution = json_object_get_double(poResolution);
     if( EQUAL(pszSRS, "EPSG:3857") )
     {
         double dfZoomLevel = log(GM_ZOOM_0 / dfResolution)/log(2.0);
-        nZoomLevel = (int)(dfZoomLevel + 0.1);
+        nZoomLevel = static_cast<int>( dfZoomLevel + 0.1 );
         if( fabs(dfZoomLevel - nZoomLevel) > 1e-5 )
         {
             CPLError(CE_Failure, CPLE_NotSupported, "Unsupported resolution = %.12g",
@@ -823,10 +836,10 @@ int PLMosaicDataset::OpenMosaic()
         adfGeoTransform[3] = -GM_ORIGIN;
         adfGeoTransform[4] = 0;
         adfGeoTransform[5] = -dfResolution;
-        nRasterXSize = (int)(2 * -GM_ORIGIN / dfResolution + 0.5);
+        nRasterXSize = static_cast<int>( 2 * -GM_ORIGIN / dfResolution + 0.5 );
         nRasterYSize = nRasterXSize;
     }
-    
+
     const char* pszQuadPattern = json_object_get_string(poQuadPattern);
     if( strstr(pszQuadPattern, "{tilex:") == NULL ||
         strstr(pszQuadPattern, "{tiley:") == NULL )
@@ -861,7 +874,7 @@ int PLMosaicDataset::OpenMosaic()
             }
 
             CPLString osTMSURL(pszLinksTiles);
-            if( strncmp(pszLinksTiles, "https://", strlen("https://")) == 0 )
+            if( STARTS_WITH(pszLinksTiles, "https://") )
             {
                 // Add API key as Basic auth
                 osTMSURL = "https://";
@@ -874,7 +887,8 @@ int PLMosaicDataset::OpenMosaic()
             ReplaceSubString(osTMSURL, "{z}", "${z}");
             ReplaceSubString(osTMSURL, "{0-3}", "0");
 
-            CPLString osTMS = CPLSPrintf("<GDAL_WMS>\n"
+            CPLString osTMS = CPLSPrintf(
+"<GDAL_WMS>\n"
 "    <Service name=\"TMS\">\n"
 "        <ServerUrl>%s</ServerUrl>\n"
 "    </Service>\n"
@@ -904,11 +918,12 @@ int PLMosaicDataset::OpenMosaic()
                 osCacheStr.c_str());
             //CPLDebug("PLMosaic", "TMS : %s", osTMS.c_str());
 
-            poTMSDS = (GDALDataset*)GDALOpenEx(osTMS, GDAL_OF_RASTER | GDAL_OF_INTERNAL,
-                                               NULL, NULL, NULL);
+            poTMSDS = reinterpret_cast<GDALDataset *>(
+                GDALOpenEx( osTMS, GDAL_OF_RASTER | GDAL_OF_INTERNAL,
+                           NULL, NULL, NULL ) );
         }
     }
-    
+
     if( bUseTMSForMain && poTMSDS == NULL )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
@@ -937,7 +952,7 @@ int PLMosaicDataset::OpenMosaic()
         SetMetadataItem("TITLE", json_object_get_string(poTitle));
     }
 
-    
+
     json_object_put(poObj);
     return TRUE;
 }
@@ -976,7 +991,7 @@ int PLMosaicDataset::ListSubdatasets()
             return FALSE;
         }
 
-        int nMosaics = json_object_array_length(poMosaics);
+        const int nMosaics = json_object_array_length(poMosaics);
         for(int i=0;i< nMosaics;i++)
         {
             const char* pszName = NULL;
@@ -1015,7 +1030,7 @@ int PLMosaicDataset::ListSubdatasets()
             if( pszName && pszSelf && pszCoordinateSystem &&
                 EQUAL(pszCoordinateSystem, "EPSG:3857") )
             {
-                int nDatasetIdx = aosSubdatasets.Count() / 2 + 1;
+                const int nDatasetIdx = aosSubdatasets.Count() / 2 + 1;
                 aosSubdatasets.AddNameValue(
                     CPLSPrintf("SUBDATASET_%d_NAME", nDatasetIdx),
                     CPLSPrintf("PLMOSAIC:mosaic=%s", pszName));
@@ -1067,15 +1082,14 @@ CPLString PLMosaicDataset::formatTileName(int tile_x, int tile_y)
 
 {
     CPLString result = osQuadPattern;
-    CPLString fragment;
-    size_t nPos;
-    int nDigits;
 
-    nPos = osQuadPattern.find("{tilex:");
+    size_t nPos = osQuadPattern.find("{tilex:");
     nPos += strlen("{tilex:");
+    int nDigits;
     if( sscanf(osQuadPattern.c_str() + nPos, "0%dd}", &nDigits) != 1 ||
         nDigits <= 0 || nDigits > 9 )
         return result;
+    CPLString fragment;
     fragment.Printf(CPLSPrintf("%%0%dd", nDigits), tile_x);
     ReplaceSubString(result, CPLSPrintf("{tilex:0%dd}", nDigits), fragment);
 
@@ -1099,7 +1113,7 @@ CPLString PLMosaicDataset::formatTileName(int tile_x, int tile_y)
 
 void PLMosaicDataset::InsertNewDataset(CPLString osKey, GDALDataset* poDS)
 {
-    if( (int) oMapLinkedDatasets.size() == nCacheMaxSize )
+    if( static_cast<int>( oMapLinkedDatasets.size() ) == nCacheMaxSize )
     {
         CPLDebug("PLMOSAIC", "Discarding older entry %s from cache",
                  psTail->osKey.c_str());
@@ -1132,9 +1146,9 @@ GDALDataset* PLMosaicDataset::OpenAndInsertNewDataset(CPLString osTmpFilename,
                                                       CPLString osTilename)
 {
     const char* const apszAllowedDrivers[2] = { "GTiff", NULL };
-    GDALDataset* poDS = (GDALDataset*)
-        GDALOpenEx(osTmpFilename, GDAL_OF_RASTER | GDAL_OF_INTERNAL,
-                            apszAllowedDrivers, NULL, NULL);
+    GDALDataset* poDS = reinterpret_cast<GDALDataset *>(
+        GDALOpenEx( osTmpFilename, GDAL_OF_RASTER | GDAL_OF_INTERNAL,
+                    apszAllowedDrivers, NULL, NULL ) );
     if( poDS != NULL )
     {
         if( poDS->GetRasterXSize() != nQuadSize ||
@@ -1152,7 +1166,7 @@ GDALDataset* PLMosaicDataset::OpenAndInsertNewDataset(CPLString osTmpFilename,
         CPLError(CE_Failure, CPLE_AppDefined, "Invalid GTiff dataset: %s",
                  osTilename.c_str());
     }
-    
+
     InsertNewDataset(osTilename, poDS);
     return poDS;
 }
@@ -1163,14 +1177,14 @@ GDALDataset* PLMosaicDataset::OpenAndInsertNewDataset(CPLString osTmpFilename,
 
 GDALDataset* PLMosaicDataset::GetMetaTile(int tile_x, int tile_y)
 {
-    CPLString osTilename = formatTileName(tile_x, tile_y);
-    std::map<CPLString,PLLinkedDataset*>::const_iterator it = 
+    const CPLString osTilename = formatTileName(tile_x, tile_y);
+    std::map<CPLString,PLLinkedDataset*>::const_iterator it =
                                                     oMapLinkedDatasets.find(osTilename);
     if( it == oMapLinkedDatasets.end() )
     {
         CPLString osTmpFilename;
 
-        CPLString osMosaicPath(GetMosaicCachePath());
+        const CPLString osMosaicPath(GetMosaicCachePath());
         osTmpFilename = CPLFormFilename(osMosaicPath,
                 CPLSPrintf("%s_%s.tif", osMosaic.c_str(), CPLGetFilename(osTilename)), NULL);
         VSIStatBufL sStatBuf;
@@ -1204,7 +1218,7 @@ GDALDataset* PLMosaicDataset::GetMetaTile(int tile_x, int tile_y)
                 nFileSize = json_object_get_int(poFileSize);
             }
             json_object_put(poObj);
-            if( (int)sStatBuf.st_size == nFileSize )
+            if( static_cast<int>( sStatBuf.st_size ) == nFileSize )
             {
                 CPLDebug("PLMOSAIC", "Cached tile is up-to-date");
                 return OpenAndInsertNewDataset(osTmpFilename, osTilename);
@@ -1261,8 +1275,7 @@ GDALDataset* PLMosaicDataset::GetMetaTile(int tile_x, int tile_y)
         CPLHTTPDestroyResult(psResult);
         GDALDataset* poDS = OpenAndInsertNewDataset(osTmpFilename, osTilename);
 
-        if( strncmp(osTmpFilename, "/vsimem/single_tile_plmosaic_cache/",
-                    strlen("/vsimem/single_tile_plmosaic_cache/")) == 0 )
+        if( STARTS_WITH(osTmpFilename, "/vsimem/single_tile_plmosaic_cache/") )
             VSIUnlink(osTilename);
 
         return poDS;
@@ -1297,12 +1310,12 @@ const char* PLMosaicDataset::GetLocationInfo(int nPixel, int nLine)
     int nBlockXSize, nBlockYSize;
     GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
 
-    int nBlockXOff = nPixel / nBlockXSize;
-    int nBlockYOff = nLine / nBlockYSize;
-    int bottom_yblock = (nRasterYSize - nBlockYOff * nBlockYSize) / nBlockYSize - 1;
+    const int nBlockXOff = nPixel / nBlockXSize;
+    const int nBlockYOff = nLine / nBlockYSize;
+    const int bottom_yblock = (nRasterYSize - nBlockYOff * nBlockYSize) / nBlockYSize - 1;
 
-    int meta_tile_x = (nBlockXOff * nBlockXSize) / nQuadSize;
-    int meta_tile_y = (bottom_yblock * nBlockYSize) / nQuadSize;
+    const int meta_tile_x = (nBlockXOff * nBlockXSize) / nQuadSize;
+    const int meta_tile_y = (bottom_yblock * nBlockYSize) / nQuadSize;
 
     CPLString osQuadURL = osQuadsURL;
     CPLString osTilename = formatTileName(meta_tile_x, meta_tile_y);
@@ -1310,15 +1323,14 @@ const char* PLMosaicDataset::GetLocationInfo(int nPixel, int nLine)
 
     if( meta_tile_x != nLastMetaTileX || meta_tile_y != nLastMetaTileY )
     {
-        CPLHTTPResult* psResult;
-        psResult = Download(osQuadURL, TRUE);
+        CPLHTTPResult* psResult = Download(osQuadURL, TRUE);
         if( psResult )
             osLastQuadInformation = (const char*) psResult->pabyData;
         else
             osLastQuadInformation = "";
         CPLHTTPDestroyResult(psResult);
 
-        CPLString osQuadScenesURL = osQuadURL + "/scenes/";
+        const CPLString osQuadScenesURL = osQuadURL + "/scenes/";
 
         psResult = Download(osQuadScenesURL, TRUE);
         if( psResult )
@@ -1341,11 +1353,16 @@ const char* PLMosaicDataset::GetLocationInfo(int nPixel, int nLine)
         const char* const apszOptions[2] = { "FLATTEN_NESTED_ATTRIBUTES=YES", NULL };
         CPLString osTmpJSonFilename;
         osTmpJSonFilename.Printf("/vsimem/plmosaic/%p/quad.json", this);
-        VSIFCloseL(VSIFileFromMemBuffer(osTmpJSonFilename,
-                                        (GByte*)osLastQuadInformation.c_str(),
-                                        osLastQuadInformation.size(), FALSE));
-        GDALDataset* poDS = (GDALDataset*) GDALOpenEx(osTmpJSonFilename, GDAL_OF_VECTOR,
-                                                    apszAllowedDrivers, apszOptions, NULL);
+
+        VSIFCloseL(VSIFileFromMemBuffer(
+            osTmpJSonFilename,
+            reinterpret_cast<GByte *>( const_cast<char *>(
+                osLastQuadInformation.c_str() ) ),
+            osLastQuadInformation.size(), FALSE));
+
+        GDALDataset* poDS = reinterpret_cast<GDALDataset *>(
+            GDALOpenEx( osTmpJSonFilename, GDAL_OF_VECTOR,
+                        apszAllowedDrivers, apszOptions, NULL ) );
         VSIUnlink(osTmpJSonFilename);
 
         if( poDS )
@@ -1368,10 +1385,10 @@ const char* PLMosaicDataset::GetLocationInfo(int nPixel, int nLine)
                 if( poGeom )
                 {
                     CPLXMLNode* psItem = CPLCreateXMLNode(psQuad, CXT_Element, "geometry");
-                    char* pszWKT = NULL;
-                    poGeom->exportToWkt(&pszWKT);
-                    CPLCreateXMLNode(psItem, CXT_Text, pszWKT);
-                    CPLFree(pszWKT);
+                    char* l_pszWKT = NULL;
+                    poGeom->exportToWkt(&l_pszWKT);
+                    CPLCreateXMLNode(psItem, CXT_Text, l_pszWKT);
+                    CPLFree(l_pszWKT);
                 }
                 delete poFeat;
             }
@@ -1386,18 +1403,23 @@ const char* PLMosaicDataset::GetLocationInfo(int nPixel, int nLine)
         const char* const apszOptions[2] = { "FLATTEN_NESTED_ATTRIBUTES=YES", NULL };
         CPLString osTmpJSonFilename;
         osTmpJSonFilename.Printf("/vsimem/plmosaic/%p/scenes.json", this);
-        VSIFCloseL(VSIFileFromMemBuffer(osTmpJSonFilename,
-                                        (GByte*)osLastQuadSceneInformation.c_str(),
-                                        osLastQuadSceneInformation.size(), FALSE));
-        GDALDataset* poDS = (GDALDataset*) GDALOpenEx(osTmpJSonFilename, GDAL_OF_VECTOR,
-                                                    apszAllowedDrivers, apszOptions, NULL);
+
+        VSIFCloseL(VSIFileFromMemBuffer(
+            osTmpJSonFilename,
+            reinterpret_cast<GByte *>( const_cast<char *>(
+                osLastQuadSceneInformation.c_str() ) ),
+            osLastQuadSceneInformation.size(), FALSE));
+
+        GDALDataset* poDS = reinterpret_cast<GDALDataset*>(
+            GDALOpenEx( osTmpJSonFilename, GDAL_OF_VECTOR,
+                        apszAllowedDrivers, apszOptions, NULL ) );
         VSIUnlink(osTmpJSonFilename);
 
         OGRSpatialReference oSRSSrc, oSRSDst;
         oSRSSrc.SetFromUserInput(pszWKT);
         oSRSDst.importFromEPSG(4326);
         OGRCoordinateTransformation* poCT = OGRCreateCoordinateTransformation(&oSRSSrc,
-                                                                            &oSRSDst);
+                                                                              &oSRSDst);
         double x = adfGeoTransform[0] + nPixel * adfGeoTransform[1];
         double y = adfGeoTransform[3] + nLine * adfGeoTransform[5];
         if( poDS && poCT && poCT->Transform(1, &x, &y))
@@ -1424,10 +1446,10 @@ const char* PLMosaicDataset::GetLocationInfo(int nPixel, int nLine)
                         }
                     }
                     CPLXMLNode* psItem = CPLCreateXMLNode(psScene, CXT_Element, "geometry");
-                    char* pszWKT = NULL;
-                    poGeom->exportToWkt(&pszWKT);
-                    CPLCreateXMLNode(psItem, CXT_Text, pszWKT);
-                    CPLFree(pszWKT);
+                    char* l_pszWKT = NULL;
+                    poGeom->exportToWkt(&l_pszWKT);
+                    CPLCreateXMLNode(psItem, CXT_Text, l_pszWKT);
+                    CPLFree(l_pszWKT);
                 }
                 delete poFeat;
             }
@@ -1452,20 +1474,20 @@ const char* PLMosaicDataset::GetLocationInfo(int nPixel, int nLine)
 CPLErr  PLMosaicDataset::IRasterIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
                                void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType, 
+                               GDALDataType eBufType,
                                int nBandCount, int *panBandMap,
                                GSpacing nPixelSpace, GSpacing nLineSpace,
                                GSpacing nBandSpace,
                                GDALRasterIOExtraArg* psExtraArg)
 {
     if( bUseTMSForMain && poTMSDS )
-        return poTMSDS->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, 
+        return poTMSDS->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
                                   pData, nBufXSize, nBufYSize,
                                   eBufType, nBandCount, panBandMap,
                                   nPixelSpace, nLineSpace, nBandSpace,
                                   psExtraArg );
 
-    return BlockBasedRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, 
+    return BlockBasedRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
                                pData, nBufXSize, nBufYSize,
                                eBufType, nBandCount, panBandMap,
                                nPixelSpace, nLineSpace, nBandSpace,
@@ -1479,22 +1501,21 @@ CPLErr  PLMosaicDataset::IRasterIO( GDALRWFlag eRWFlag,
 void GDALRegister_PLMOSAIC()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "PLMOSAIC" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "PLMOSAIC" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "PLMOSAIC" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Planet Labs Mosaics API" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_plmosaic.html" );
-
-        poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, "PLMOSAIC:" );
-
-        poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST, 
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "PLMOSAIC" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Planet Labs Mosaics API" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_plmosaic.html" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, "PLMOSAIC:" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
 "<OpenOptionList>"
 "  <Option name='API_KEY' type='string' description='Account API key' required='true'/>"
 "  <Option name='MOSAIC' type='string' description='Mosaic name'/>"
@@ -1503,9 +1524,8 @@ void GDALRegister_PLMOSAIC()
 "  <Option name='USE_TILES' type='boolean' description='Whether to use the tile API even for full resolution data (only for Byte mosaics)' default='NO'/>"
 "</OpenOptionList>" );
 
-        poDriver->pfnIdentify = PLMosaicDataset::Identify;
-        poDriver->pfnOpen = PLMosaicDataset::Open;
+    poDriver->pfnIdentify = PLMosaicDataset::Identify;
+    poDriver->pfnOpen = PLMosaicDataset::Open;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/png/GNUmakefile b/frmts/png/GNUmakefile
index f39c869..6e25d93 100644
--- a/frmts/png/GNUmakefile
+++ b/frmts/png/GNUmakefile
@@ -1,4 +1,4 @@
-# $Id: GNUmakefile 27976 2014-11-17 13:13:44Z rouault $
+# $Id: GNUmakefile 31315 2015-11-02 15:10:52Z rouault $
 #
 # Makefile to build libpng using GNU Make and GCC.
 #
@@ -36,6 +36,8 @@ XTRA_OPT	:=	$(XTRA_OPT) -I../zlib
 endif
 
 CPPFLAGS	:=	$(XTRA_OPT)  $(CPPFLAGS)
+# Enable this to compile with -Wextra -Werror and get around the jump complaint.
+# CPPFLAGS += -Wno-clobbered
 
 default:	$(OBJ:.o=.$(OBJ_EXT))
 
@@ -43,7 +45,7 @@ clean:
 	rm -f *.o libpng/*.o $(O_OBJ)
 
 ../o/%.$(OBJ_EXT):	libpng/%.c
-	$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@
+	$(CC) -c $(CPPFLAGS) $(CFLAGS_NOFTRAPV) $< -o $@
 
 all:	$(OBJ:.o=.$(OBJ_EXT))
 
diff --git a/frmts/png/libpng/LICENSE b/frmts/png/libpng/LICENSE
index a684fe5..3b1f329 100644
--- a/frmts/png/libpng/LICENSE
+++ b/frmts/png/libpng/LICENSE
@@ -10,20 +10,15 @@ this sentence.
 
 This code is released under the libpng license.
 
-libpng versions 1.2.6, August 15, 2004, through 1.2.50, July 10, 2012, are
-Copyright (c) 2004, 2006-2009 Glenn Randers-Pehrson, and are
-distributed according to the same disclaimer and license as libpng-1.2.5
-with the following individual added to the list of Contributing Authors
-
-   Cosmin Truta
-
-libpng versions 1.0.7, July 1, 2000, through 1.2.5 - October 3, 2002, are
-Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are
-distributed according to the same disclaimer and license as libpng-1.0.6
-with the following individuals added to the list of Contributing Authors
+libpng versions 1.0.7, July 1, 2000, through 1.2.56, December 17, 2015, are
+Copyright (c) 2000-2002, 2004, 2006-2015 Glenn Randers-Pehrson, are
+derived from libpng-1.0.6, and are distributed according to the same
+disclaimer and license as libpng-1.0.6 with the following individuals
+added to the list of Contributing Authors:
 
    Simon-Pierre Cadieux
    Eric S. Raymond
+   Cosmin Truta
    Gilles Vollant
 
 and with the following additions to the disclaimer:
@@ -36,18 +31,20 @@ and with the following additions to the disclaimer:
    the user.
 
 libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
-Copyright (c) 1998, 1999 Glenn Randers-Pehrson, and are
-distributed according to the same disclaimer and license as libpng-0.96,
-with the following individuals added to the list of Contributing Authors:
+Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
+libpng-0.96, and are distributed according to the same disclaimer and
+license as libpng-0.96, with the following individuals added to the list
+of Contributing Authors:
 
    Tom Lane
    Glenn Randers-Pehrson
    Willem van Schaik
 
 libpng versions 0.89, June 1996, through 0.96, May 1997, are
-Copyright (c) 1996, 1997 Andreas Dilger
-Distributed according to the same disclaimer and license as libpng-0.88,
-with the following individuals added to the list of Contributing Authors:
+Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88,
+and are distributed according to the same disclaimer and license as
+libpng-0.88, with the following individuals added to the list of
+Contributing Authors:
 
    John Bowler
    Kevin Bracey
@@ -57,7 +54,7 @@ with the following individuals added to the list of Contributing Authors:
    Tom Tanner
 
 libpng versions 0.5, May 1995, through 0.88, January 1996, are
-Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
+Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
 
 For the purposes of this copyright and license, "Contributing Authors"
 is defined as the following set of individuals:
@@ -80,13 +77,13 @@ Permission is hereby granted to use, copy, modify, and distribute this
 source code, or portions hereof, for any purpose, without fee, subject
 to the following restrictions:
 
-1. The origin of this source code must not be misrepresented.
+  1. The origin of this source code must not be misrepresented.
 
-2. Altered versions must be plainly marked as such and must not
-   be misrepresented as being the original source.
+  2. Altered versions must be plainly marked as such and must not
+     be misrepresented as being the original source.
 
-3. This Copyright notice may not be removed or altered from any
-   source or altered source distribution.
+  3. This Copyright notice may not be removed or altered from any
+     source or altered source distribution.
 
 The Contributing Authors and Group 42, Inc. specifically permit, without
 fee, and encourage the use of this source code as a component to
@@ -94,18 +91,20 @@ supporting the PNG file format in commercial products.  If you use this
 source code in a product, acknowledgment is not required but would be
 appreciated.
 
+END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE.
 
 A "png_get_copyright" function is available, for convenient use in "about"
 boxes and the like:
 
-   printf("%s",png_get_copyright(NULL));
+   printf("%s", png_get_copyright(NULL));
 
 Also, the PNG logo (in PNG format, of course) is supplied in the
 files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31).
 
-Libpng is OSI Certified Open Source Software.  OSI Certified Open Source is a
-certification mark of the Open Source Initiative.
+Libpng is OSI Certified Open Source Software.  OSI Certified Open Source is
+a certification mark of the Open Source Initiative. OSI has not addressed
+the additional disclaimers inserted at version 1.0.7.
 
 Glenn Randers-Pehrson
 glennrp at users.sourceforge.net
-July 10, 2012
+December 17, 2015
diff --git a/frmts/png/libpng/README b/frmts/png/libpng/README
index 771ca50..496f2b5 100644
--- a/frmts/png/libpng/README
+++ b/frmts/png/libpng/README
@@ -4,7 +4,7 @@ $Id$
 Updating libpng in GDAL tree should follow update of zlib library in frmts/zlib.
 *****************
 
-libpng 1.2.52 is the official PNG reference library.
+libpng 1.2.56 is the official PNG reference library.
 It supports almost all PNG features, is extensible,
 and has been extensively tested for over 15 years.
 
diff --git a/frmts/png/libpng/makefile.vc b/frmts/png/libpng/makefile.vc
index a6b3e15..7af6480 100644
--- a/frmts/png/libpng/makefile.vc
+++ b/frmts/png/libpng/makefile.vc
@@ -1,4 +1,4 @@
-# $Id: makefile.vc 10656 2007-01-19 01:31:01Z mloskot $
+# $Id: makefile.vc 31687 2015-11-21 16:35:21Z rouault $
 #
 # Makefile to build libpng using NMAKE and Visual C++ compiler.
 #
@@ -23,7 +23,7 @@ OBJ = \
 
 GDAL_ROOT	=	..\..\..
 
-EXTRAFLAGS = 	-I..\..\zlib
+EXTRAFLAGS = 	-I..\..\zlib /wd4267 /wd4310 
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
diff --git a/frmts/png/libpng/png.c b/frmts/png/libpng/png.c
index 2ebb6f7..67b7881 100644
--- a/frmts/png/libpng/png.c
+++ b/frmts/png/libpng/png.c
@@ -1,8 +1,8 @@
 
 /* png.c - location for general purpose libpng functions
  *
- * Last changed in libpng 1.2.51 [February 6, 2014]
- * Copyright (c) 1998-2014 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.54 [November 12, 2015]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -17,7 +17,7 @@
 #include "png.h"
 
 /* Generate a compiler error if there is an old png.h in the search path. */
-typedef version_1_2_52 Your_png_h_is_not_version_1_2_52;
+typedef version_1_2_56 Your_png_h_is_not_version_1_2_56;
 
 /* Version information for C files.  This had better match the version
  * string defined in png.h.
@@ -158,12 +158,16 @@ voidpf /* PRIVATE */
 png_zalloc(voidpf png_ptr, uInt items, uInt size)
 {
    png_voidp ptr;
-   png_structp p=(png_structp)png_ptr;
-   png_uint_32 save_flags=p->flags;
+   png_structp p;
+   png_uint_32 save_flags;
    png_uint_32 num_bytes;
 
    if (png_ptr == NULL)
       return (NULL);
+
+   p=(png_structp)png_ptr;
+   save_flags=p->flags;
+
    if (items > PNG_UINT_32_MAX/size)
    {
      png_warning (p, "Potential overflow in png_zalloc()");
@@ -328,6 +332,8 @@ png_info_init_3(png_infopp ptr_ptr, png_size_t png_info_struct_size)
       png_destroy_struct(info_ptr);
       info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO);
       *ptr_ptr = info_ptr;
+      if (info_ptr == NULL)
+         return;
    }
 
    /* Set everything to 0 */
@@ -675,6 +681,7 @@ png_convert_to_rfc1123(png_structp png_ptr, png_timep ptime)
 
    if (png_ptr == NULL)
       return (NULL);
+
    if (png_ptr->time_buffer == NULL)
    {
       png_ptr->time_buffer = (png_charp)png_malloc(png_ptr, (png_uint_32)(29*
@@ -685,7 +692,7 @@ png_convert_to_rfc1123(png_structp png_ptr, png_timep ptime)
    {
       wchar_t time_buf[29];
       wsprintf(time_buf, TEXT("%d %S %d %02d:%02d:%02d +0000"),
-          ptime->day % 32, short_months[(ptime->month - 1) % 12],
+          ptime->day % 32, short_months[(ptime->month - 1U) % 12],
         ptime->year, ptime->hour % 24, ptime->minute % 60,
           ptime->second % 61);
       WideCharToMultiByte(CP_ACP, 0, time_buf, -1, png_ptr->time_buffer,
@@ -696,7 +703,7 @@ png_convert_to_rfc1123(png_structp png_ptr, png_timep ptime)
    {
       char near_time_buf[29];
       png_snprintf6(near_time_buf, 29, "%d %s %d %02d:%02d:%02d +0000",
-          ptime->day % 32, short_months[(ptime->month - 1) % 12],
+          ptime->day % 32, short_months[(ptime->month - 1U) % 12],
           ptime->year, ptime->hour % 24, ptime->minute % 60,
           ptime->second % 61);
       png_memcpy(png_ptr->time_buffer, near_time_buf,
@@ -704,7 +711,7 @@ png_convert_to_rfc1123(png_structp png_ptr, png_timep ptime)
    }
 #else
    png_snprintf6(png_ptr->time_buffer, 29, "%d %s %d %02d:%02d:%02d +0000",
-       ptime->day % 32, short_months[(ptime->month - 1) % 12],
+       ptime->day % 32, short_months[(ptime->month - 1U) % 12],
        ptime->year, ptime->hour % 24, ptime->minute % 60,
        ptime->second % 61);
 #endif
@@ -724,14 +731,15 @@ png_get_copyright(png_structp png_ptr)
 #else
 #ifdef __STDC__
    return ((png_charp) PNG_STRING_NEWLINE \
-     "libpng version 1.2.52 - November 20, 2014" PNG_STRING_NEWLINE \
-     "Copyright (c) 1998-2014 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \
+     "libpng version 1.2.56 - December 17, 2015" PNG_STRING_NEWLINE \
+     "Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson" \
+     PNG_STRING_NEWLINE \
      "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
      "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
      PNG_STRING_NEWLINE);
 #else
-      return ((png_charp) "libpng version 1.2.52 - November 20, 2014\
-      Copyright (c) 1998-2014 Glenn Randers-Pehrson\
+   return ((png_charp) "libpng version 1.2.56 - December 17, 2015\
+      Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson\
       Copyright (c) 1996-1997 Andreas Dilger\
       Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.");
 #endif
diff --git a/frmts/png/libpng/png.h b/frmts/png/libpng/png.h
index ed9e429..be6ee9d 100644
--- a/frmts/png/libpng/png.h
+++ b/frmts/png/libpng/png.h
@@ -1,7 +1,9 @@
+
 /* png.h - header file for PNG reference library
  *
- * libpng version 1.2.52 - November 20, 2014
- * Copyright (c) 1998-2014 Glenn Randers-Pehrson
+ * libpng version 1.2.56, December 17, 2015
+ *
+ * Copyright (c) 1998-2015 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -9,310 +11,9 @@
  *
  * Authors and maintainers:
  *  libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
- *  libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger
- *  libpng versions 0.97, January 1998, through 1.2.52 - November 20, 2014: Glenn
+ *  libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger
+ *  libpng versions 0.97, January 1998, through 1.2.56, December 17, 2015: Glenn
  *  See also "Contributing Authors", below.
- *
- * Note about libpng version numbers:
- *
- *    Due to various miscommunications, unforeseen code incompatibilities
- *    and occasional factors outside the authors' control, version numbering
- *    on the library has not always been consistent and straightforward.
- *    The following table summarizes matters since version 0.89c, which was
- *    the first widely used release:
- *
- *    source                 png.h  png.h  shared-lib
- *    version                string   int  version
- *    -------                ------ -----  ----------
- *    0.89c "1.0 beta 3"     0.89      89  1.0.89
- *    0.90  "1.0 beta 4"     0.90      90  0.90  [should have been 2.0.90]
- *    0.95  "1.0 beta 5"     0.95      95  0.95  [should have been 2.0.95]
- *    0.96  "1.0 beta 6"     0.96      96  0.96  [should have been 2.0.96]
- *    0.97b "1.00.97 beta 7" 1.00.97   97  1.0.1 [should have been 2.0.97]
- *    0.97c                  0.97      97  2.0.97
- *    0.98                   0.98      98  2.0.98
- *    0.99                   0.99      98  2.0.99
- *    0.99a-m                0.99      99  2.0.99
- *    1.00                   1.00     100  2.1.0 [100 should be 10000]
- *    1.0.0      (from here on, the   100  2.1.0 [100 should be 10000]
- *    1.0.1       png.h string is   10001  2.1.0
- *    1.0.1a-e    identical to the  10002  from here on, the shared library
- *    1.0.2       source version)   10002  is 2.V where V is the source code
- *    1.0.2a-b                      10003  version, except as noted.
- *    1.0.3                         10003
- *    1.0.3a-d                      10004
- *    1.0.4                         10004
- *    1.0.4a-f                      10005
- *    1.0.5 (+ 2 patches)           10005
- *    1.0.5a-d                      10006
- *    1.0.5e-r                      10100 (not source compatible)
- *    1.0.5s-v                      10006 (not binary compatible)
- *    1.0.6 (+ 3 patches)           10006 (still binary incompatible)
- *    1.0.6d-f                      10007 (still binary incompatible)
- *    1.0.6g                        10007
- *    1.0.6h                        10007  10.6h (testing xy.z so-numbering)
- *    1.0.6i                        10007  10.6i
- *    1.0.6j                        10007  2.1.0.6j (incompatible with 1.0.0)
- *    1.0.7beta11-14        DLLNUM  10007  2.1.0.7beta11-14 (binary compatible)
- *    1.0.7beta15-18           1    10007  2.1.0.7beta15-18 (binary compatible)
- *    1.0.7rc1-2               1    10007  2.1.0.7rc1-2 (binary compatible)
- *    1.0.7                    1    10007  (still compatible)
- *    1.0.8beta1-4             1    10008  2.1.0.8beta1-4
- *    1.0.8rc1                 1    10008  2.1.0.8rc1
- *    1.0.8                    1    10008  2.1.0.8
- *    1.0.9beta1-6             1    10009  2.1.0.9beta1-6
- *    1.0.9rc1                 1    10009  2.1.0.9rc1
- *    1.0.9beta7-10            1    10009  2.1.0.9beta7-10
- *    1.0.9rc2                 1    10009  2.1.0.9rc2
- *    1.0.9                    1    10009  2.1.0.9
- *    1.0.10beta1              1    10010  2.1.0.10beta1
- *    1.0.10rc1                1    10010  2.1.0.10rc1
- *    1.0.10                   1    10010  2.1.0.10
- *    1.0.11beta1-3            1    10011  2.1.0.11beta1-3
- *    1.0.11rc1                1    10011  2.1.0.11rc1
- *    1.0.11                   1    10011  2.1.0.11
- *    1.0.12beta1-2            2    10012  2.1.0.12beta1-2
- *    1.0.12rc1                2    10012  2.1.0.12rc1
- *    1.0.12                   2    10012  2.1.0.12
- *    1.1.0a-f                 -    10100  2.1.1.0a-f (branch abandoned)
- *    1.2.0beta1-2             2    10200  2.1.2.0beta1-2
- *    1.2.0beta3-5             3    10200  3.1.2.0beta3-5
- *    1.2.0rc1                 3    10200  3.1.2.0rc1
- *    1.2.0                    3    10200  3.1.2.0
- *    1.2.1beta1-4             3    10201  3.1.2.1beta1-4
- *    1.2.1rc1-2               3    10201  3.1.2.1rc1-2
- *    1.2.1                    3    10201  3.1.2.1
- *    1.2.2beta1-6            12    10202  12.so.0.1.2.2beta1-6
- *    1.0.13beta1             10    10013  10.so.0.1.0.13beta1
- *    1.0.13rc1               10    10013  10.so.0.1.0.13rc1
- *    1.2.2rc1                12    10202  12.so.0.1.2.2rc1
- *    1.0.13                  10    10013  10.so.0.1.0.13
- *    1.2.2                   12    10202  12.so.0.1.2.2
- *    1.2.3rc1-6              12    10203  12.so.0.1.2.3rc1-6
- *    1.2.3                   12    10203  12.so.0.1.2.3
- *    1.2.4beta1-3            13    10204  12.so.0.1.2.4beta1-3
- *    1.0.14rc1               13    10014  10.so.0.1.0.14rc1
- *    1.2.4rc1                13    10204  12.so.0.1.2.4rc1
- *    1.0.14                  10    10014  10.so.0.1.0.14
- *    1.2.4                   13    10204  12.so.0.1.2.4
- *    1.2.5beta1-2            13    10205  12.so.0.1.2.5beta1-2
- *    1.0.15rc1-3             10    10015  10.so.0.1.0.15rc1-3
- *    1.2.5rc1-3              13    10205  12.so.0.1.2.5rc1-3
- *    1.0.15                  10    10015  10.so.0.1.0.15
- *    1.2.5                   13    10205  12.so.0.1.2.5
- *    1.2.6beta1-4            13    10206  12.so.0.1.2.6beta1-4
- *    1.0.16                  10    10016  10.so.0.1.0.16
- *    1.2.6                   13    10206  12.so.0.1.2.6
- *    1.2.7beta1-2            13    10207  12.so.0.1.2.7beta1-2
- *    1.0.17rc1               10    10017  10.so.0.1.0.17rc1
- *    1.2.7rc1                13    10207  12.so.0.1.2.7rc1
- *    1.0.17                  10    10017  10.so.0.1.0.17
- *    1.2.7                   13    10207  12.so.0.1.2.7
- *    1.2.8beta1-5            13    10208  12.so.0.1.2.8beta1-5
- *    1.0.18rc1-5             10    10018  10.so.0.1.0.18rc1-5
- *    1.2.8rc1-5              13    10208  12.so.0.1.2.8rc1-5
- *    1.0.18                  10    10018  10.so.0.1.0.18
- *    1.2.8                   13    10208  12.so.0.1.2.8
- *    1.2.9beta1-3            13    10209  12.so.0.1.2.9beta1-3
- *    1.2.9beta4-11           13    10209  12.so.0.9[.0]
- *    1.2.9rc1                13    10209  12.so.0.9[.0]
- *    1.2.9                   13    10209  12.so.0.9[.0]
- *    1.2.10beta1-8           13    10210  12.so.0.10[.0]
- *    1.2.10rc1-3             13    10210  12.so.0.10[.0]
- *    1.2.10                  13    10210  12.so.0.10[.0]
- *    1.2.11beta1-4           13    10211  12.so.0.11[.0]
- *    1.0.19rc1-5             10    10019  10.so.0.19[.0]
- *    1.2.11rc1-5             13    10211  12.so.0.11[.0]
- *    1.0.19                  10    10019  10.so.0.19[.0]
- *    1.2.11                  13    10211  12.so.0.11[.0]
- *    1.0.20                  10    10020  10.so.0.20[.0]
- *    1.2.12                  13    10212  12.so.0.12[.0]
- *    1.2.13beta1             13    10213  12.so.0.13[.0]
- *    1.0.21                  10    10021  10.so.0.21[.0]
- *    1.2.13                  13    10213  12.so.0.13[.0]
- *    1.2.14beta1-2           13    10214  12.so.0.14[.0]
- *    1.0.22rc1               10    10022  10.so.0.22[.0]
- *    1.2.14rc1               13    10214  12.so.0.14[.0]
- *    1.0.22                  10    10022  10.so.0.22[.0]
- *    1.2.14                  13    10214  12.so.0.14[.0]
- *    1.2.15beta1-6           13    10215  12.so.0.15[.0]
- *    1.0.23rc1-5             10    10023  10.so.0.23[.0]
- *    1.2.15rc1-5             13    10215  12.so.0.15[.0]
- *    1.0.23                  10    10023  10.so.0.23[.0]
- *    1.2.15                  13    10215  12.so.0.15[.0]
- *    1.2.16beta1-2           13    10216  12.so.0.16[.0]
- *    1.2.16rc1               13    10216  12.so.0.16[.0]
- *    1.0.24                  10    10024  10.so.0.24[.0]
- *    1.2.16                  13    10216  12.so.0.16[.0]
- *    1.2.17beta1-2           13    10217  12.so.0.17[.0]
- *    1.0.25rc1               10    10025  10.so.0.25[.0]
- *    1.2.17rc1-3             13    10217  12.so.0.17[.0]
- *    1.0.25                  10    10025  10.so.0.25[.0]
- *    1.2.17                  13    10217  12.so.0.17[.0]
- *    1.0.26                  10    10026  10.so.0.26[.0]
- *    1.2.18                  13    10218  12.so.0.18[.0]
- *    1.2.19beta1-31          13    10219  12.so.0.19[.0]
- *    1.0.27rc1-6             10    10027  10.so.0.27[.0]
- *    1.2.19rc1-6             13    10219  12.so.0.19[.0]
- *    1.0.27                  10    10027  10.so.0.27[.0]
- *    1.2.19                  13    10219  12.so.0.19[.0]
- *    1.2.20beta01-04         13    10220  12.so.0.20[.0]
- *    1.0.28rc1-6             10    10028  10.so.0.28[.0]
- *    1.2.20rc1-6             13    10220  12.so.0.20[.0]
- *    1.0.28                  10    10028  10.so.0.28[.0]
- *    1.2.20                  13    10220  12.so.0.20[.0]
- *    1.2.21beta1-2           13    10221  12.so.0.21[.0]
- *    1.2.21rc1-3             13    10221  12.so.0.21[.0]
- *    1.0.29                  10    10029  10.so.0.29[.0]
- *    1.2.21                  13    10221  12.so.0.21[.0]
- *    1.2.22beta1-4           13    10222  12.so.0.22[.0]
- *    1.0.30rc1               10    10030  10.so.0.30[.0]
- *    1.2.22rc1               13    10222  12.so.0.22[.0]
- *    1.0.30                  10    10030  10.so.0.30[.0]
- *    1.2.22                  13    10222  12.so.0.22[.0]
- *    1.2.23beta01-05         13    10223  12.so.0.23[.0]
- *    1.2.23rc01              13    10223  12.so.0.23[.0]
- *    1.2.23                  13    10223  12.so.0.23[.0]
- *    1.2.24beta01-02         13    10224  12.so.0.24[.0]
- *    1.2.24rc01              13    10224  12.so.0.24[.0]
- *    1.2.24                  13    10224  12.so.0.24[.0]
- *    1.2.25beta01-06         13    10225  12.so.0.25[.0]
- *    1.2.25rc01-02           13    10225  12.so.0.25[.0]
- *    1.0.31                  10    10031  10.so.0.31[.0]
- *    1.2.25                  13    10225  12.so.0.25[.0]
- *    1.2.26beta01-06         13    10226  12.so.0.26[.0]
- *    1.2.26rc01              13    10226  12.so.0.26[.0]
- *    1.2.26                  13    10226  12.so.0.26[.0]
- *    1.0.32                  10    10032  10.so.0.32[.0]
- *    1.2.27beta01-06         13    10227  12.so.0.27[.0]
- *    1.2.27rc01              13    10227  12.so.0.27[.0]
- *    1.0.33                  10    10033  10.so.0.33[.0]
- *    1.2.27                  13    10227  12.so.0.27[.0]
- *    1.0.34                  10    10034  10.so.0.34[.0]
- *    1.2.28                  13    10228  12.so.0.28[.0]
- *    1.2.29beta01-03         13    10229  12.so.0.29[.0]
- *    1.2.29rc01              13    10229  12.so.0.29[.0]
- *    1.0.35                  10    10035  10.so.0.35[.0]
- *    1.2.29                  13    10229  12.so.0.29[.0]
- *    1.0.37                  10    10037  10.so.0.37[.0]
- *    1.2.30beta01-04         13    10230  12.so.0.30[.0]
- *    1.0.38rc01-08           10    10038  10.so.0.38[.0]
- *    1.2.30rc01-08           13    10230  12.so.0.30[.0]
- *    1.0.38                  10    10038  10.so.0.38[.0]
- *    1.2.30                  13    10230  12.so.0.30[.0]
- *    1.0.39rc01-03           10    10039  10.so.0.39[.0]
- *    1.2.31rc01-03           13    10231  12.so.0.31[.0]
- *    1.0.39                  10    10039  10.so.0.39[.0]
- *    1.2.31                  13    10231  12.so.0.31[.0]
- *    1.2.32beta01-02         13    10232  12.so.0.32[.0]
- *    1.0.40rc01              10    10040  10.so.0.40[.0]
- *    1.2.32rc01              13    10232  12.so.0.32[.0]
- *    1.0.40                  10    10040  10.so.0.40[.0]
- *    1.2.32                  13    10232  12.so.0.32[.0]
- *    1.2.33beta01-02         13    10233  12.so.0.33[.0]
- *    1.2.33rc01-02           13    10233  12.so.0.33[.0]
- *    1.0.41rc01              10    10041  10.so.0.41[.0]
- *    1.2.33                  13    10233  12.so.0.33[.0]
- *    1.0.41                  10    10041  10.so.0.41[.0]
- *    1.2.34beta01-07         13    10234  12.so.0.34[.0]
- *    1.0.42rc01              10    10042  10.so.0.42[.0]
- *    1.2.34rc01              13    10234  12.so.0.34[.0]
- *    1.0.42                  10    10042  10.so.0.42[.0]
- *    1.2.34                  13    10234  12.so.0.34[.0]
- *    1.2.35beta01-03         13    10235  12.so.0.35[.0]
- *    1.0.43rc01-02           10    10043  10.so.0.43[.0]
- *    1.2.35rc01-02           13    10235  12.so.0.35[.0]
- *    1.0.43                  10    10043  10.so.0.43[.0]
- *    1.2.35                  13    10235  12.so.0.35[.0]
- *    1.2.36beta01-05         13    10236  12.so.0.36[.0]
- *    1.2.36rc01              13    10236  12.so.0.36[.0]
- *    1.0.44                  10    10044  10.so.0.44[.0]
- *    1.2.36                  13    10236  12.so.0.36[.0]
- *    1.2.37beta01-03         13    10237  12.so.0.37[.0]
- *    1.2.37rc01              13    10237  12.so.0.37[.0]
- *    1.2.37                  13    10237  12.so.0.37[.0]
- *    1.0.45                  10    10045  12.so.0.45[.0]
- *    1.0.46                  10    10046  10.so.0.46[.0]
- *    1.2.38beta01            13    10238  12.so.0.38[.0]
- *    1.2.38rc01-03           13    10238  12.so.0.38[.0]
- *    1.0.47                  10    10047  10.so.0.47[.0]
- *    1.2.38                  13    10238  12.so.0.38[.0]
- *    1.2.39beta01-05         13    10239  12.so.0.39[.0]
- *    1.2.39rc01              13    10239  12.so.0.39[.0]
- *    1.0.48                  10    10048  10.so.0.48[.0]
- *    1.2.39                  13    10239  12.so.0.39[.0]
- *    1.2.40beta01            13    10240  12.so.0.40[.0]
- *    1.2.40rc01              13    10240  12.so.0.40[.0]
- *    1.0.49                  10    10049  10.so.0.49[.0]
- *    1.2.40                  13    10240  12.so.0.40[.0]
- *    1.2.41beta01-18         13    10241  12.so.0.41[.0]
- *    1.0.51rc01              10    10051  10.so.0.51[.0]
- *    1.2.41rc01-03           13    10241  12.so.0.41[.0]
- *    1.0.51                  10    10051  10.so.0.51[.0]
- *    1.2.41                  13    10241  12.so.0.41[.0]
- *    1.2.42beta01-02         13    10242  12.so.0.42[.0]
- *    1.2.42rc01-05           13    10242  12.so.0.42[.0]
- *    1.0.52                  10    10052  10.so.0.52[.0]
- *    1.2.42                  13    10242  12.so.0.42[.0]
- *    1.2.43beta01-05         13    10243  12.so.0.43[.0]
- *    1.0.53rc01-02           10    10053  10.so.0.53[.0]
- *    1.2.43rc01-02           13    10243  12.so.0.43[.0]
- *    1.0.53                  10    10053  10.so.0.53[.0]
- *    1.2.43                  13    10243  12.so.0.43[.0]
- *    1.2.44beta01-03         13    10244  12.so.0.44[.0]
- *    1.2.44rc01-03           13    10244  12.so.0.44[.0]
- *    1.2.44                  13    10244  12.so.0.44[.0]
- *    1.2.45beta01-03         13    10245  12.so.0.45[.0]
- *    1.0.55rc01              10    10055  10.so.0.55[.0]
- *    1.2.45rc01              13    10245  12.so.0.45[.0]
- *    1.0.55                  10    10055  10.so.0.55[.0]
- *    1.2.45                  13    10245  12.so.0.45[.0]
- *    1.2.46rc01-02           13    10246  12.so.0.46[.0]
- *    1.0.56                  10    10056  10.so.0.56[.0]
- *    1.2.46                  13    10246  12.so.0.46[.0]
- *    1.2.47beta01            13    10247  12.so.0.47[.0]
- *    1.2.47rc01              13    10247  12.so.0.47[.0]
- *    1.0.57rc01              10    10057  10.so.0.57[.0]
- *    1.2.47                  13    10247  12.so.0.47[.0]
- *    1.0.57                  10    10057  10.so.0.57[.0]
- *    1.2.48beta01            13    10248  12.so.0.48[.0]
- *    1.2.48rc01-02           13    10248  12.so.0.48[.0]
- *    1.0.58                  10    10058  10.so.0.58[.0]
- *    1.2.48                  13    10248  12.so.0.48[.0]
- *    1.2.49rc01              13    10249  12.so.0.49[.0]
- *    1.0.59                  10    10059  10.so.0.59[.0]
- *    1.2.49                  13    10249  12.so.0.49[.0]
- *    1.0.60                  10    10060  10.so.0.60[.0]
- *    1.2.50                  13    10250  12.so.0.50[.0]
- *    1.2.51beta01-05         13    10251  12.so.0.51[.0]
- *    1.2.51rc01-04           13    10251  12.so.0.51[.0]
- *    1.0.61                  10    10061  10.so.0.61[.0]
- *    1.2.51                  13    10251  12.so.0.51[.0]
- *    1.2.52beta01            13    10252  12.so.0.52[.0]
- *    1.2.52rc01-02           13    10252  12.so.0.52[.0]
- *    1.0.62                  10    10062  10.so.0.62[.0]
- *    1.2.52                  13    10252  12.so.0.52[.0]
- *
- *    Henceforth the source version will match the shared-library major
- *    and minor numbers; the shared-library major version number will be
- *    used for changes in backward compatibility, as it is intended.  The
- *    PNG_LIBPNG_VER macro, which is not used within libpng but is available
- *    for applications, is an unsigned integer of the form xyyzz corresponding
- *    to the source version x.y.z (leading zeros in y and z).  Beta versions
- *    were given the previous public release number plus a letter, until
- *    version 1.0.6j; from then on they were given the upcoming public
- *    release number plus "betaNN" or "rcNN".
- *
- *    Binary incompatibility exists only when applications make direct access
- *    to the info_ptr or png_ptr members through png.h, and the compiled
- *    application is loaded with a different version of the library.
- *
- *    DLLNUM will change each time there are forward or backward changes
- *    in binary compatibility (e.g., when a new feature is added).
- *
- * See libpng.txt or libpng.3 for more information.  The PNG specification
- * is available as a W3C Recommendation and as an ISO Specification,
- * <http://www.w3.org/TR/2003/REC-PNG-20031110/
  */
 
 /*
@@ -323,20 +24,15 @@
  *
  * This code is released under the libpng license.
  *
- * libpng versions 1.2.6, August 15, 2004, through 1.2.52, November 20, 2014, are
- * Copyright (c) 2004, 2006-2013 Glenn Randers-Pehrson, and are
- * distributed according to the same disclaimer and license as libpng-1.2.5
- * with the following individual added to the list of Contributing Authors:
- *
- *    Cosmin Truta
- *
- * libpng versions 1.0.7, July 1, 2000, through 1.2.5, October 3, 2002, are
- * Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are
- * distributed according to the same disclaimer and license as libpng-1.0.6
- * with the following individuals added to the list of Contributing Authors:
+ * libpng versions 1.0.7, July 1, 2000, through 1.2.54, November 12, 2015, are
+ * Copyright (c) 2000-2002, 2004, 2006-2015 Glenn Randers-Pehrson, are
+ * derived from libpng-1.0.6, and are distributed according to the same
+ * disclaimer and license as libpng-1.0.6 with the following individuals
+ * added to the list of Contributing Authors:
  *
  *    Simon-Pierre Cadieux
  *    Eric S. Raymond
+ *    Cosmin Truta
  *    Gilles Vollant
  *
  * and with the following additions to the disclaimer:
@@ -349,18 +45,20 @@
  *    the user.
  *
  * libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
- * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson, and are
- * distributed according to the same disclaimer and license as libpng-0.96,
- * with the following individuals added to the list of Contributing Authors:
+ * Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
+ * libpng-0.96, and are distributed according to the same disclaimer and
+ * license as libpng-0.96, with the following individuals added to the list
+ * of Contributing Authors:
  *
  *    Tom Lane
  *    Glenn Randers-Pehrson
  *    Willem van Schaik
  *
  * libpng versions 0.89, June 1996, through 0.96, May 1997, are
- * Copyright (c) 1996, 1997 Andreas Dilger
- * Distributed according to the same disclaimer and license as libpng-0.88,
- * with the following individuals added to the list of Contributing Authors:
+ * Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88,
+ * and are distributed according to the same disclaimer and license as
+ * libpng-0.88, with the following individuals added to the list of
+ * Contributing Authors:
  *
  *    John Bowler
  *    Kevin Bracey
@@ -370,7 +68,7 @@
  *    Tom Tanner
  *
  * libpng versions 0.5, May 1995, through 0.88, January 1996, are
- * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
  *
  * For the purposes of this copyright and license, "Contributing Authors"
  * is defined as the following set of individuals:
@@ -393,55 +91,130 @@
  * source code, or portions hereof, for any purpose, without fee, subject
  * to the following restrictions:
  *
- * 1. The origin of this source code must not be misrepresented.
+ *   1. The origin of this source code must not be misrepresented.
  *
- * 2. Altered versions must be plainly marked as such and
- * must not be misrepresented as being the original source.
+ *   2. Altered versions must be plainly marked as such and must not
+ *      be misrepresented as being the original source.
  *
- * 3. This Copyright notice may not be removed or altered from
- *    any source or altered source distribution.
+ *   3. This Copyright notice may not be removed or altered from any
+ *      source or altered source distribution.
  *
  * The Contributing Authors and Group 42, Inc. specifically permit, without
  * fee, and encourage the use of this source code as a component to
  * supporting the PNG file format in commercial products.  If you use this
  * source code in a product, acknowledgment is not required but would be
  * appreciated.
+ *
+ * END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE.
  */
 
 /*
  * A "png_get_copyright" function is available, for convenient use in "about"
  * boxes and the like:
  *
- * printf("%s",png_get_copyright(NULL));
+ *    printf("%s", png_get_copyright(NULL));
  *
  * Also, the PNG logo (in PNG format, of course) is supplied in the
  * files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31).
  */
 
 /*
- * Libpng is OSI Certified Open Source Software.  OSI Certified is a
- * certification mark of the Open Source Initiative.
+ * Libpng is OSI Certified Open Source Software.  OSI Certified Open Source is
+ * a certification mark of the Open Source Initiative. OSI has not addressed
+ * the additional disclaimers inserted at version 1.0.7.
  */
 
 /*
  * The contributing authors would like to thank all those who helped
- * with testing, bug fixes, and patience.  This wouldn't have been
+ * with testing, bug fixes, and patience.  This would not have been
  * possible without all of you.
  *
  * Thanks to Frank J. T. Wojcik for helping with the documentation.
  */
 
+/* Note about libpng version numbers:
+ *
+ *    Due to various miscommunications, unforeseen code incompatibilities
+ *    and occasional factors outside the authors' control, version numbering
+ *    on the library has not always been consistent and straightforward.
+ *    The following table summarizes matters since version 0.89c, which was
+ *    the first widely used release:
+ *
+ *    source                 png.h  png.h  shared-lib
+ *    version                string   int  version
+ *    -------                ------ -----  ----------
+ *    0.89c "1.0 beta 3"     0.89      89  1.0.89
+ *    0.90  "1.0 beta 4"     0.90      90  0.90  [should have been 2.0.90]
+ *    0.95  "1.0 beta 5"     0.95      95  0.95  [should have been 2.0.95]
+ *    0.96  "1.0 beta 6"     0.96      96  0.96  [should have been 2.0.96]
+ *    0.97b "1.00.97 beta 7" 1.00.97   97  1.0.1 [should have been 2.0.97]
+ *    0.97c                  0.97      97  2.0.97
+ *    0.98                   0.98      98  2.0.98
+ *    0.99                   0.99      98  2.0.99
+ *    0.99a-m                0.99      99  2.0.99
+ *    1.00                   1.00     100  2.1.0 [100 should be 10000]
+ *    1.0.0      (from here on, the   100  2.1.0 [100 should be 10000]
+ *    1.0.1       png.h string is   10001  2.1.0
+ *    1.0.1a-e    identical to the  10002  from here on, the shared library
+ *    1.0.2       source version)   10002  is 2.V where V is the source code
+ *    1.0.2a-b                      10003  version, except as noted.
+ *    1.0.3                         10003
+ *    1.0.3a-d                      10004
+ *    1.0.4                         10004
+ *    1.0.4a-f                      10005
+ *    1.0.5 (+ 2 patches)           10005
+ *    1.0.5a-d                      10006
+ *    1.0.5e-r                      10100 (not source compatible)
+ *    1.0.5s-v                      10006 (not binary compatible)
+ *    1.0.6 (+ 3 patches)           10006 (still binary incompatible)
+ *    1.0.6d-f                      10007 (still binary incompatible)
+ *    1.0.6g                        10007
+ *    1.0.6h                        10007  10.6h (testing xy.z so-numbering)
+ *    1.0.6i                        10007  10.6i
+ *    1.0.6j                        10007  2.1.0.6j (incompatible with 1.0.0)
+ *    1.0.7beta11-14        DLLNUM  10007  2.1.0.7beta11-14 (binary compatible)
+ *    1.0.7beta15-18           1    10007  2.1.0.7beta15-18 (binary compatible)
+ *    1.0.7rc1-2               1    10007  2.1.0.7rc1-2 (binary compatible)
+ *    1.0.7                    1    10007  (still compatible)
+ *    ...
+ *    1.0.19                  10    10019  10.so.0.19[.0]
+ *    ...
+ *    1.0.66                  10    10066  10.so.0.66[.0]
+ *    1.2.56                  13    10256  12.so.0.56[.0]
+ *
+ *    Henceforth the source version will match the shared-library major
+ *    and minor numbers; the shared-library major version number will be
+ *    used for changes in backward compatibility, as it is intended.  The
+ *    PNG_LIBPNG_VER macro, which is not used within libpng but is available
+ *    for applications, is an unsigned integer of the form xyyzz corresponding
+ *    to the source version x.y.z (leading zeros in y and z).  Beta versions
+ *    were given the previous public release number plus a letter, until
+ *    version 1.0.6j; from then on they were given the upcoming public
+ *    release number plus "betaNN" or "rcNN".
+ *
+ *    Binary incompatibility exists only when applications make direct access
+ *    to the info_ptr or png_ptr members through png.h, and the compiled
+ *    application is loaded with a different version of the library.
+ *
+ *    DLLNUM will change each time there are forward or backward changes
+ *    in binary compatibility (e.g., when a new feature is added).
+ *
+ * See libpng.txt or libpng.3 for more information.  The PNG specification
+ * is available as a W3C Recommendation and as an ISO Specification,
+ * <http://www.w3.org/TR/2003/REC-PNG-20031110/
+ */
+
 /*
  * Y2K compliance in libpng:
  * =========================
  *
- *    November 20, 2014
+ *    December 17, 2015
  *
  *    Since the PNG Development group is an ad-hoc body, we can't make
  *    an official declaration.
  *
  *    This is your unofficial assurance that libpng from version 0.71 and
- *    upward through 1.2.52 are Y2K compliant.  It is my belief that earlier
+ *    upward through 1.2.56 are Y2K compliant.  It is my belief that earlier
  *    versions were also Y2K compliant.
  *
  *    Libpng only has three year fields.  One is a 2-byte unsigned integer
@@ -497,9 +270,9 @@
  */
 
 /* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.2.52"
+#define PNG_LIBPNG_VER_STRING "1.2.56"
 #define PNG_HEADER_VERSION_STRING \
-   " libpng version 1.2.52 - November 20, 2014\n"
+   " libpng version 1.2.56 - December 17, 2015\n"
 
 #define PNG_LIBPNG_VER_SONUM   0
 #define PNG_LIBPNG_VER_DLLNUM  13
@@ -507,7 +280,7 @@
 /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
 #define PNG_LIBPNG_VER_MAJOR   1
 #define PNG_LIBPNG_VER_MINOR   2
-#define PNG_LIBPNG_VER_RELEASE 52
+#define PNG_LIBPNG_VER_RELEASE 56
 /* This should match the numeric part of the final component of
  * PNG_LIBPNG_VER_STRING, omitting any leading zero:
  */
@@ -534,10 +307,10 @@
 /* Careful here.  At one time, Guy wanted to use 082, but that would be octal.
  * We must not include leading zeros.
  * Versions 0.7 through 1.0.0 were in the range 0 to 100 here (only
- * version 1.0.0 was mis-numbered 100 instead of 10000).  From
- * version 1.0.1 it's    xxyyzz, where x=major, y=minor, z=release
+ * version 1.0.0 was misnumbered 100 instead of 10000).  From
+ * version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release
  */
-#define PNG_LIBPNG_VER 10252 /* 1.2.52 */
+#define PNG_LIBPNG_VER 10256 /* 1.2.56 */
 
 #ifndef PNG_VERSION_INFO_ONLY
 /* Include the compression library's header */
@@ -729,7 +502,7 @@ typedef struct png_text_struct
                               1: iTXt, none
                               2: iTXt, deflate  */
    png_charp key;          /* keyword, 1-79 character description of "text" */
-   png_charp text;         /* comment, may be an empty string (ie "")
+   png_charp text;         /* comment, may be an empty string (i.e. "")
                               or a NULL pointer */
    png_size_t text_length; /* length of the text string */
 #ifdef PNG_iTXt_SUPPORTED
@@ -1035,7 +808,7 @@ defined(PNG_READ_BACKGROUND_SUPPORTED)
    /* The sCAL chunk describes the actual physical dimensions of the
     * subject matter of the graphic.  The chunk contains a unit specification
     * a byte value, and two ASCII strings representing floating-point
-    * values.  The values are width and height corresponsing to one pixel
+    * values.  The values are width and height corresponding to one pixel
     * in the image.  This external representation is converted to double
     * here.  Data values are valid if (valid & PNG_INFO_sCAL) is non-zero.
     */
@@ -1399,7 +1172,7 @@ struct png_struct_def
 #endif
 
 #if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
-   png_color_8 shift PNG_DEPSTRUCT;         /* shift for significant bit tranformation */
+   png_color_8 shift PNG_DEPSTRUCT;         /* shift for significant bit transformation */
 #endif
 
 #if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \
@@ -1453,16 +1226,6 @@ struct png_struct_def
    png_uint_16p hist PNG_DEPSTRUCT;                /* histogram */
 #endif
 
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
-   png_byte heuristic_method PNG_DEPSTRUCT;        /* heuristic for row filter selection */
-   png_byte num_prev_filters PNG_DEPSTRUCT;        /* number of weights for previous rows */
-   png_bytep prev_filters PNG_DEPSTRUCT;           /* filter type(s) of previous row(s) */
-   png_uint_16p filter_weights PNG_DEPSTRUCT;      /* weight(s) for previous line(s) */
-   png_uint_16p inv_filter_weights PNG_DEPSTRUCT;  /* 1/weight(s) for previous line(s) */
-   png_uint_16p filter_costs PNG_DEPSTRUCT;        /* relative filter calculation cost */
-   png_uint_16p inv_filter_costs PNG_DEPSTRUCT;    /* 1/relative filter calculation cost */
-#endif
-
 #ifdef PNG_TIME_RFC1123_SUPPORTED
    png_charp time_buffer PNG_DEPSTRUCT;            /* String to hold RFC 1123 time text */
 #endif
@@ -1577,7 +1340,7 @@ struct png_struct_def
 /* This triggers a compiler error in png.c, if png.c and png.h
  * do not agree upon the version number.
  */
-typedef png_structp version_1_2_52;
+typedef png_structp version_1_2_56;
 
 typedef png_struct FAR * FAR * png_structpp;
 
@@ -1599,7 +1362,7 @@ extern PNG_EXPORT(void,png_set_sig_bytes) PNGARG((png_structp png_ptr,
 /* Check sig[start] through sig[start + num_to_check - 1] to see if it's a
  * PNG file.  Returns zero if the supplied bytes match the 8-byte PNG
  * signature, and non-zero otherwise.  Having num_to_check == 0 or
- * start > 7 will always fail (ie return non-zero).
+ * start > 7 will always fail (i.e. return non-zero).
  */
 extern PNG_EXPORT(int,png_sig_cmp) PNGARG((png_bytep sig, png_size_t start,
    png_size_t num_to_check));
@@ -1945,7 +1708,7 @@ extern PNG_EXPORT(void,png_set_crc_action) PNGARG((png_structp png_ptr,
  * mainly useful for testing, as the defaults should work with most users.
  * Those users who are tight on memory or want faster performance at the
  * expense of compression can modify them.  See the compression library
- * header file (zlib.h) for an explination of the compression functions.
+ * header file (zlib.h) for an explanation of the compression functions.
  */
 
 /* Set the filtering method(s) used by libpng.  Currently, the only valid
@@ -1978,35 +1741,7 @@ extern PNG_EXPORT(void,png_set_filter) PNGARG((png_structp png_ptr, int method,
 #define PNG_FILTER_VALUE_PAETH 4
 #define PNG_FILTER_VALUE_LAST  5
 
-#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* EXPERIMENTAL */
-/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_
- * defines, either the default (minimum-sum-of-absolute-differences), or
- * the experimental method (weighted-minimum-sum-of-absolute-differences).
- *
- * Weights are factors >= 1.0, indicating how important it is to keep the
- * filter type consistent between rows.  Larger numbers mean the current
- * filter is that many times as likely to be the same as the "num_weights"
- * previous filters.  This is cumulative for each previous row with a weight.
- * There needs to be "num_weights" values in "filter_weights", or it can be
- * NULL if the weights aren't being specified.  Weights have no influence on
- * the selection of the first row filter.  Well chosen weights can (in theory)
- * improve the compression for a given image.
- *
- * Costs are factors >= 1.0 indicating the relative decoding costs of a
- * filter type.  Higher costs indicate more decoding expense, and are
- * therefore less likely to be selected over a filter with lower computational
- * costs.  There needs to be a value in "filter_costs" for each valid filter
- * type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't
- * setting the costs.  Costs try to improve the speed of decompression without
- * unduly increasing the compressed image size.
- *
- * A negative weight or cost indicates the default value is to be used, and
- * values in the range [0.0, 1.0) indicate the value is to remain unchanged.
- * The default values for both weights and costs are currently 1.0, but may
- * change if good general weighting/cost heuristics can be found.  If both
- * the weights and costs are set to 1.0, this degenerates the WEIGHTED method
- * to the UNWEIGHTED method, but with added encoding time/computation.
- */
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* DEPRECATED */
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 extern PNG_EXPORT(void,png_set_filter_heuristics) PNGARG((png_structp png_ptr,
    int heuristic_method, int num_weights, png_doublep filter_weights,
@@ -2014,9 +1749,7 @@ extern PNG_EXPORT(void,png_set_filter_heuristics) PNGARG((png_structp png_ptr,
 #endif
 #endif /*  PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
 
-/* Heuristic used for row filter selection.  These defines should NOT be
- * changed.
- */
+/* The following are no longer used and will be removed from libpng-1.7: */
 #define PNG_FILTER_HEURISTIC_DEFAULT    0  /* Currently "UNWEIGHTED" */
 #define PNG_FILTER_HEURISTIC_UNWEIGHTED 1  /* Used by libpng < 0.95 */
 #define PNG_FILTER_HEURISTIC_WEIGHTED   2  /* Experimental feature */
@@ -2026,7 +1759,7 @@ extern PNG_EXPORT(void,png_set_filter_heuristics) PNGARG((png_structp png_ptr,
  * 0 - 9, corresponding directly to the zlib compression levels 0 - 9
  * (0 - no compression, 9 - "maximal" compression).  Note that tests have
  * shown that zlib compression levels 3-6 usually perform as well as level 9
- * for PNG images, and do considerably fewer caclulations.  In the future,
+ * for PNG images, and do considerably fewer calculations.  In the future,
  * these values may not correspond directly to the zlib compression levels.
  */
 extern PNG_EXPORT(void,png_set_compression_level) PNGARG((png_structp png_ptr,
@@ -3805,6 +3538,7 @@ PNG_EXTERN void png_check_IHDR PNGARG((png_structp png_ptr,
 PNG_EXTERN png_voidp png_calloc PNGARG((png_structp png_ptr,
    png_uint_32 size));
 
+
 /* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */
 
 #endif /* PNG_INTERNAL */
diff --git a/frmts/png/libpng/pngconf.h b/frmts/png/libpng/pngconf.h
index 008142e..03b5e69 100644
--- a/frmts/png/libpng/pngconf.h
+++ b/frmts/png/libpng/pngconf.h
@@ -1,17 +1,17 @@
 
 /* pngconf.h - machine configurable file for libpng
  *
- * libpng version 1.2.52 - November 20, 2014
- * Copyright (c) 1998-2013 Glenn Randers-Pehrson
+ * libpng version 1.2.56, December 17, 2015
+ *
+ * Copyright (c) 1998-2015 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
  * and license in png.h
- */
-
-/* Any machine specific code is near the front of this file, so if you
+ *
+ * Any machine specific code is near the front of this file, so if you
  * are configuring libpng for a machine, you may want to read the section
  * starting here down to where it starts to typedef png_color, png_text,
  * and png_info.
@@ -313,7 +313,7 @@
 #endif
 
 /* This macro protects us against machines that don't have function
- * prototypes (ie K&R style headers).  If your compiler does not handle
+ * prototypes (i.e. K&R style headers).  If your compiler does not handle
  * function prototypes, define this macro and use the included ansi2knr.
  * I've always been able to use _NO_PROTO as the indicator, but you may
  * need to drag the empty declaration out in front of here, or change the
@@ -361,7 +361,7 @@
 
 #ifdef PNG_SETJMP_SUPPORTED
 /* This is an attempt to force a single setjmp behaviour on Linux.  If
- * the X config stuff didn't define _BSD_SOURCE we wouldn't need this.
+ * the X config stuff did not define _BSD_SOURCE we would not need this.
  *
  * You can bypass this test if you know that your application uses exactly
  * the same setjmp.h that was included when libpng was built.  Only define
@@ -885,7 +885,7 @@
 
 /* Added at libpng-1.2.43 */
 #ifndef PNG_USER_CHUNK_MALLOC_MAX
-#  define PNG_USER_CHUNK_MALLOC_MAX 0
+#  define PNG_USER_CHUNK_MALLOC_MAX 8000000
 #endif
 
 #ifndef PNG_LITERAL_SHARP
@@ -939,7 +939,7 @@
 */
 
 /* Any chunks you are not interested in, you can undef here.  The
- * ones that allocate memory may be expecially important (hIST,
+ * ones that allocate memory may be especially important (hIST,
  * tEXt, zTXt, tRNS, pCAL).  Others will just save time and make png_info
  * a bit smaller.
  */
@@ -1297,7 +1297,7 @@ typedef unsigned char png_byte;
 
 /* Suggest testing for specific compiler first before testing for
  * FAR.  The Watcom compiler defines both __MEDIUM__ and M_I86MM,
- * making reliance oncertain keywords suspect. (SJT)
+ * making reliance on certain keywords suspect. (SJT)
  */
 
 /* MSC Medium model */
diff --git a/frmts/png/libpng/pngerror.c b/frmts/png/libpng/pngerror.c
index d8e7928..0ce1744 100644
--- a/frmts/png/libpng/pngerror.c
+++ b/frmts/png/libpng/pngerror.c
@@ -2,7 +2,7 @@
 /* pngerror.c - stub functions for i/o and memory allocation
  *
  * Last changed in libpng 1.2.51 [February 6, 2014]
- * Copyright (c) 1998-2014 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2014 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
diff --git a/frmts/png/libpng/pnggccrd.c b/frmts/png/libpng/pnggccrd.c
index 7eb7f67..2208fb0 100644
--- a/frmts/png/libpng/pnggccrd.c
+++ b/frmts/png/libpng/pnggccrd.c
@@ -1,7 +1,7 @@
 /* pnggccrd.c
  *
  * Last changed in libpng 1.2.48 [March 8, 2012]
- * Copyright (c) 1998-2012 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2012 Glenn Randers-Pehrson
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
diff --git a/frmts/png/libpng/pngget.c b/frmts/png/libpng/pngget.c
index c5d6543..d11c9b0 100644
--- a/frmts/png/libpng/pngget.c
+++ b/frmts/png/libpng/pngget.c
@@ -1,8 +1,8 @@
 
 /* pngget.c - retrieval of values from info struct
  *
- * Last changed in libpng 1.2.51 [February 6, 2014]
- * Copyright (c) 1998-2014 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.53 [February 26, 2015]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -885,7 +885,8 @@ png_uint_32 PNGAPI
 png_get_asm_flags (png_structp png_ptr)
 {
     /* Obsolete, to be removed from libpng-1.4.0 */
-    return (png_ptr? 0L: 0L);
+    PNG_UNUSED(png_ptr)
+    return 0L;
 }
 
 /* This function was added to libpng 1.2.0 and should exist by default */
@@ -913,7 +914,8 @@ png_byte PNGAPI
 png_get_mmx_bitdepth_threshold (png_structp png_ptr)
 {
     /* Obsolete, to be removed from libpng-1.4.0 */
-    return (png_ptr? 0: 0);
+    PNG_UNUSED(png_ptr)
+    return 0L;
 }
 
 /* This function was added to libpng 1.2.0 */
@@ -921,7 +923,8 @@ png_uint_32 PNGAPI
 png_get_mmx_rowbytes_threshold (png_structp png_ptr)
 {
     /* Obsolete, to be removed from libpng-1.4.0 */
-    return (png_ptr? 0L: 0L);
+    PNG_UNUSED(png_ptr)
+    return 0L;
 }
 #endif /* ?PNG_1_0_X */
 #endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */
diff --git a/frmts/png/libpng/pngmem.c b/frmts/png/libpng/pngmem.c
index a18719b..4d1e38e 100644
--- a/frmts/png/libpng/pngmem.c
+++ b/frmts/png/libpng/pngmem.c
@@ -2,7 +2,7 @@
 /* pngmem.c - stub functions for memory allocation
  *
  * Last changed in libpng 1.2.41 [February 25, 2010]
- * Copyright (c) 1998-2010 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2010 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -343,7 +343,7 @@ png_free_default(png_structp png_ptr, png_voidp ptr)
 
 /* Allocate memory for a png_struct or a png_info.  The malloc and
    memset can be replaced by a single call to calloc() if this is thought
-   to improve performance noticably. */
+   to improve performance noticeably. */
 png_voidp /* PRIVATE */
 png_create_struct(int type)
 {
@@ -353,7 +353,7 @@ png_create_struct(int type)
 
 /* Allocate memory for a png_struct or a png_info.  The malloc and
    memset can be replaced by a single call to calloc() if this is thought
-   to improve performance noticably. */
+   to improve performance noticeably. */
 png_voidp /* PRIVATE */
 png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)
 {
diff --git a/frmts/png/libpng/pngpread.c b/frmts/png/libpng/pngpread.c
index 5af209d..4c9ae76 100644
--- a/frmts/png/libpng/pngpread.c
+++ b/frmts/png/libpng/pngpread.c
@@ -2,7 +2,7 @@
 /* pngpread.c - read a png file in push mode
  *
  * Last changed in libpng 1.2.44 [June 26, 2010]
- * Copyright (c) 1998-2010 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2010 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -685,9 +685,12 @@ png_push_save_buffer(png_structp png_ptr)
         png_free(png_ptr, old_buffer);
         png_error(png_ptr, "Insufficient memory for save_buffer");
       }
-      png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
-      png_free(png_ptr, old_buffer);
-      png_ptr->save_buffer_max = new_max;
+      else
+      {
+        png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
+        png_free(png_ptr, old_buffer);
+        png_ptr->save_buffer_max = new_max;
+      }
    }
    if (png_ptr->current_buffer_size)
    {
diff --git a/frmts/png/libpng/pngread.c b/frmts/png/libpng/pngread.c
index 24277b1..9ea1738 100644
--- a/frmts/png/libpng/pngread.c
+++ b/frmts/png/libpng/pngread.c
@@ -1,8 +1,8 @@
 
 /* pngread.c - read a PNG file
  *
- * Last changed in libpng 1.2.52 [November 20, 2014]
- * Copyright (c) 1998-2014 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.53 [February 26, 2015]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -274,7 +274,7 @@ png_read_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver,
 
    do
    {
-      if (user_png_ver[i] != png_libpng_ver[i])
+      if (user_png_ver == NULL || user_png_ver[i] != png_libpng_ver[i])
       {
 #ifdef PNG_LEGACY_SUPPORTED
         png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
@@ -597,10 +597,12 @@ png_start_read_image(png_structp png_ptr)
 void PNGAPI
 png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
 {
+#ifndef PNG_USE_GLOBAL_ARRAYS
    PNG_CONST PNG_IDAT;
    PNG_CONST int png_pass_dsp_mask[7] = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55,
       0xff};
    PNG_CONST int png_pass_mask[7] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff};
+#endif
    int ret;
  
    if (png_ptr == NULL)
diff --git a/frmts/png/libpng/pngrio.c b/frmts/png/libpng/pngrio.c
index 6978682..fdff705 100644
--- a/frmts/png/libpng/pngrio.c
+++ b/frmts/png/libpng/pngrio.c
@@ -1,7 +1,7 @@
 
 /* pngrio.c - functions for data input
  *
- * Last changed in libpng 1.2.43 [February 25, 2010]
+ * Copyright (c) 1998-2002,2004,2006-2010 Glenn Randers-Pehrson
  * Copyright (c) 1998-2010 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
diff --git a/frmts/png/libpng/pngrtran.c b/frmts/png/libpng/pngrtran.c
index 0a760ce..4c9ff03 100644
--- a/frmts/png/libpng/pngrtran.c
+++ b/frmts/png/libpng/pngrtran.c
@@ -1,8 +1,8 @@
 
 /* pngrtran.c - transforms the data in a row for PNG readers
  *
- * Last changed in libpng 1.2.51 [February 6, 2014]
- * Copyright (c) 1998-2014 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.53 [February 26, 2015]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -2330,7 +2330,7 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
  *
  *  The calculation is to be done in a linear colorspace.
  *
- *  Other integer coefficents can be used via png_set_rgb_to_gray().
+ *  Other integer coefficients can be used via png_set_rgb_to_gray().
  */
 int /* PRIVATE */
 png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
@@ -2410,10 +2410,14 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
                for (i = 0; i < row_width; i++)
                {
                   png_uint_16 red, green, blue, w;
+                  png_byte hi,lo;
 
-                  red   = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
-                  green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
-                  blue  = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
+                  hi=*(sp)++; lo=*(sp)++;
+                  red   = (png_uint_16)((hi << 8) | (lo));
+                  hi=*(sp)++; lo=*(sp)++;
+                  green = (png_uint_16)((hi << 8) | (lo));
+                  hi=*(sp)++; lo=*(sp)++;
+                  blue  = (png_uint_16)((hi << 8) | (lo));
 
                   if (red == green && red == blue)
                      w = red;
@@ -2445,10 +2449,14 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
                for (i = 0; i < row_width; i++)
                {
                   png_uint_16 red, green, blue, gray16;
+                  png_byte hi,lo;
 
-                  red   = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
-                  green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
-                  blue  = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
+                  hi=*(sp)++; lo=*(sp)++;
+                  red   = (png_uint_16)((hi << 8) | (lo));
+                  hi=*(sp)++; lo=*(sp)++;
+                  green = (png_uint_16)((hi << 8) | (lo));
+                  hi=*(sp)++; lo=*(sp)++;
+                  blue  = (png_uint_16)((hi << 8) | (lo));
 
                   if (red != green || red != blue)
                      rgb_error |= 1;
@@ -2508,10 +2516,14 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
                for (i = 0; i < row_width; i++)
                {
                   png_uint_16 red, green, blue, w;
-
-                  red   = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
-                  green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
-                  blue  = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
+                  png_byte hi,lo;
+
+                  hi=*(sp)++; lo=*(sp)++;
+                  red   = (png_uint_16)((hi << 8) | (lo));
+                  hi=*(sp)++; lo=*(sp)++;
+                  green = (png_uint_16)((hi << 8) | (lo));
+                  hi=*(sp)++; lo=*(sp)++;
+                  blue  = (png_uint_16)((hi << 8) | (lo));
 
                   if (red == green && red == blue)
                      w = red;
diff --git a/frmts/png/libpng/pngrutil.c b/frmts/png/libpng/pngrutil.c
index 707bc1b..c9b3b46 100644
--- a/frmts/png/libpng/pngrutil.c
+++ b/frmts/png/libpng/pngrutil.c
@@ -1,8 +1,8 @@
 
 /* pngrutil.c - utilities to read a PNG file
  *
- * Last changed in libpng 1.2.51 [February 6, 2014]
- * Copyright (c) 1998-2014 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.55 [%RDATE%]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -57,13 +57,13 @@ png_get_uint_31(png_structp png_ptr, png_bytep buf)
    png_uint_32 i = png_get_uint_32(buf);
 #else
    /* Avoid an extra function call by inlining the result. */
-   png_uint_32 i = ((png_uint_32)(*buf) << 24) +
-      ((png_uint_32)(*(buf + 1)) << 16) +
-      ((png_uint_32)(*(buf + 2)) << 8) +
-      (png_uint_32)(*(buf + 3));
+   png_uint_32 i = ((png_uint_32)((*(buf    )) & 0xff) << 24) +
+                   ((png_uint_32)((*(buf + 1)) & 0xff) << 16) +
+                   ((png_uint_32)((*(buf + 2)) & 0xff) <<  8) +
+                   ((png_uint_32)((*(buf + 3)) & 0xff)      );
 #endif
    if (i > PNG_UINT_31_MAX)
-     png_error(png_ptr, "PNG unsigned integer out of range.");
+      png_error(png_ptr, "PNG unsigned integer out of range.");
    return (i);
 }
 #ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
@@ -71,10 +71,10 @@ png_get_uint_31(png_structp png_ptr, png_bytep buf)
 png_uint_32 PNGAPI
 png_get_uint_32(png_bytep buf)
 {
-   png_uint_32 i = ((png_uint_32)(*buf) << 24) +
-      ((png_uint_32)(*(buf + 1)) << 16) +
-      ((png_uint_32)(*(buf + 2)) << 8) +
-      (png_uint_32)(*(buf + 3));
+   png_uint_32 i = ((png_uint_32)((*(buf    )) & 0xff) << 24) +
+                   ((png_uint_32)((*(buf + 1)) & 0xff) << 16) +
+                   ((png_uint_32)((*(buf + 2)) & 0xff) <<  8) +
+                   ((png_uint_32)((*(buf + 3)) & 0xff)      );
 
    return (i);
 }
@@ -86,10 +86,10 @@ png_get_uint_32(png_bytep buf)
 png_int_32 PNGAPI
 png_get_int_32(png_bytep buf)
 {
-   png_int_32 i = ((png_int_32)(*buf) << 24) +
-      ((png_int_32)(*(buf + 1)) << 16) +
-      ((png_int_32)(*(buf + 2)) << 8) +
-      (png_int_32)(*(buf + 3));
+   png_int_32 i = ((png_int_32)((*(buf    )) & 0xff) << 24) +
+                  ((png_int_32)((*(buf + 1)) & 0xff) << 16) +
+                  ((png_int_32)((*(buf + 2)) & 0xff) <<  8) +
+                  ((png_int_32)((*(buf + 3)) & 0xff)      );
 
    return (i);
 }
@@ -98,8 +98,8 @@ png_get_int_32(png_bytep buf)
 png_uint_16 PNGAPI
 png_get_uint_16(png_bytep buf)
 {
-   png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
-      (png_uint_16)(*(buf + 1)));
+   png_uint_16 i = ((png_uint_16)((*(buf     )) & 0xff) << 8) +
+                   ((png_uint_16)((*(buf +  1)) & 0xff)     );
 
    return (i);
 }
@@ -225,7 +225,7 @@ png_inflate(png_structp png_ptr, const png_byte *data, png_size_t size,
    png_size_t count = 0;
 
    png_ptr->zstream.next_in = (png_bytep)data; /* const_cast: VALID */
-   png_ptr->zstream.avail_in = size;
+   png_ptr->zstream.avail_in = (uInt)size;
 
    while (1)
    {
@@ -235,10 +235,10 @@ png_inflate(png_structp png_ptr, const png_byte *data, png_size_t size,
        * after every inflate call.
        */
       png_ptr->zstream.next_out = png_ptr->zbuf;
-      png_ptr->zstream.avail_out = png_ptr->zbuf_size;
+      png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
 
       ret = inflate(&png_ptr->zstream, Z_NO_FLUSH);
-      avail = png_ptr->zbuf_size - png_ptr->zstream.avail_out;
+      avail = (int)(png_ptr->zbuf_size - png_ptr->zstream.avail_out);
 
       /* First copy/count any new output - but only if we didn't
        * get an error code.
@@ -294,12 +294,15 @@ png_inflate(png_structp png_ptr, const png_byte *data, png_size_t size,
 
             png_snprintf(umsg, sizeof umsg, msg, png_ptr->chunk_name);
             msg = umsg;
+            png_warning(png_ptr, msg);
 #else
             msg = "Damaged compressed datastream in chunk other than IDAT";
 #endif
          }
 
+#ifndef PNG_STDIO_SUPPORTED
          png_warning(png_ptr, msg);
+#endif
       }
 
       /* 0 means an error - notice that this code simple ignores
@@ -503,7 +506,7 @@ void /* PRIVATE */
 png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
    png_color palette[PNG_MAX_PALETTE_LENGTH];
-   int num, i;
+   int max_palette_length, num, i;
 #ifdef PNG_POINTER_INDEXING_SUPPORTED
    png_colorp pal_ptr;
 #endif
@@ -555,8 +558,22 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       }
    }
 
+   /* The cast is safe because 'length' is less than 3*PNG_MAX_PALETTE_LENGTH */
    num = (int)length / 3;
 
+   /* If the palette has 256 or fewer entries but is too large for the bit
+    * depth, we don't issue an error, to preserve the behavior of previous
+    * libpng versions. We silently truncate the unused extra palette entries
+    * here.
+    */
+   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+      max_palette_length = (1 << png_ptr->bit_depth);
+   else
+      max_palette_length = PNG_MAX_PALETTE_LENGTH;
+
+   if (num > max_palette_length)
+      num = max_palette_length;
+
 #ifdef PNG_POINTER_INDEXING_SUPPORTED
    for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
    {
@@ -580,7 +597,7 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    }
 #endif
 
-   /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
+   /* If we actually NEED the PLTE chunk (i.e. for a paletted image), we do
     * whatever the normal CRC configuration tells us.  However, if we
     * have an RGB image, the PLTE can be considered ancillary, so
     * we will act as though it is.
@@ -589,7 +606,7 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
 #endif
    {
-      png_crc_finish(png_ptr, 0);
+      png_crc_finish(png_ptr, (int) length - num * 3);
    }
 #ifndef PNG_READ_OPT_PLTE_SUPPORTED
    else if (png_crc_error(png_ptr))  /* Only if we have a CRC error */
@@ -1097,7 +1114,7 @@ png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    /* There should be at least one zero (the compression type byte)
     * following the separator, and we should be on it
     */
-   if ( profile >= png_ptr->chunkdata + slength - 1)
+   if (slength < 1U ||  profile >= png_ptr->chunkdata + slength - 1U)
    {
       png_free(png_ptr, png_ptr->chunkdata);
       png_ptr->chunkdata = NULL;
@@ -1130,10 +1147,10 @@ png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 
    /* Check the profile_size recorded in the first 32 bits of the ICC profile */
    pC = (png_bytep)(png_ptr->chunkdata + prefix_length);
-   profile_size = ((*(pC    ))<<24) |
-                  ((*(pC + 1))<<16) |
-                  ((*(pC + 2))<< 8) |
-                  ((*(pC + 3))    );
+   profile_size = ((png_uint_32) (*(pC    )<<24)) |
+                  ((png_uint_32) (*(pC + 1)<<16)) |
+                  ((png_uint_32) (*(pC + 2)<< 8)) |
+                  ((png_uint_32) (*(pC + 3)    ));
 
    if (profile_size < profile_length)
       profile_length = profile_size;
@@ -1225,7 +1242,8 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    ++entry_start;
 
    /* A sample depth should follow the separator, and we should be on it  */
-   if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2)
+   if (slength < 2U ||
+       entry_start > (png_bytep)png_ptr->chunkdata + slength - 2U)
    {
       png_free(png_ptr, png_ptr->chunkdata);
       png_ptr->chunkdata = NULL;
@@ -1235,7 +1253,7 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 
    new_palette.depth = *entry_start++;
    entry_size = (new_palette.depth == 8 ? 6 : 10);
-   data_length = (slength - (entry_start - (png_bytep)png_ptr->chunkdata));
+   data_length = (int)(slength - (entry_start - (png_bytep)png_ptr->chunkdata));
 
    /* Integrity-check the data length */
    if (data_length % entry_size)
@@ -1538,7 +1556,7 @@ png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       return;
    }
 
-   num = length / 2 ;
+   num = (unsigned int)(length / 2);
 
    for (i = 0; i < num; i++)
    {
@@ -1699,7 +1717,7 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 
    /* We need to have at least 12 bytes after the purpose string
       in order to get the parameter information. */
-   if (endptr <= buf + 12)
+   if (slength < 12U || endptr - buf <= 12)
    {
       png_warning(png_ptr, "Invalid pCAL data");
       png_free(png_ptr, png_ptr->chunkdata);
@@ -2155,7 +2173,7 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       /* Empty loop */ ;
 
    /* zTXt must have some text after the chunkdataword */
-   if (text >= png_ptr->chunkdata + slength - 2)
+   if (slength < 2U || text >= png_ptr->chunkdata + slength - 2U)
    {
       png_warning(png_ptr, "Truncated zTXt chunk");
       png_free(png_ptr, png_ptr->chunkdata);
@@ -2281,7 +2299,7 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
     * keyword
     */
 
-   if (lang >= png_ptr->chunkdata + slength - 3)
+   if (slength < 3U || lang >= png_ptr->chunkdata + slength - 3U)
    {
       png_warning(png_ptr, "Truncated iTXt chunk");
       png_free(png_ptr, png_ptr->chunkdata);
@@ -2353,7 +2371,7 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 #endif
 
 /* This function is called when we haven't found a handler for a
-   chunk.  If there isn't a problem with the chunk itself (ie bad
+   chunk.  If there isn't a problem with the chunk itself (i.e. bad
    chunk name, CRC, or a critical chunk), the chunk is silently ignored
    -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
    case it will be saved away to be written out later. */
@@ -2716,7 +2734,9 @@ png_do_read_interlace(png_structp png_ptr)
    png_uint_32 transformations = png_ptr->transformations;
    /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
    /* Offset to next interlace block */
+#ifndef PNG_USE_GLOBAL_ARRAYS
    PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+#endif
 
    png_debug(1, "in png_do_read_interlace");
    if (row != NULL && row_info != NULL)
@@ -3056,6 +3076,7 @@ void /* PRIVATE */
 png_read_finish_row(png_structp png_ptr)
 {
 #ifdef PNG_READ_INTERLACING_SUPPORTED
+#ifndef PNG_USE_GLOBAL_ARRAYS
    /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
 
    /* Start of interlace block */
@@ -3069,6 +3090,7 @@ png_read_finish_row(png_structp png_ptr)
 
    /* Offset to next interlace block in the y direction */
    PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
+#endif
 #endif /* PNG_READ_INTERLACING_SUPPORTED */
 
    png_debug(1, "in png_read_finish_row");
@@ -3184,6 +3206,7 @@ void /* PRIVATE */
 png_read_start_row(png_structp png_ptr)
 {
 #ifdef PNG_READ_INTERLACING_SUPPORTED
+#ifndef PNG_USE_GLOBAL_ARRAYS
    /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
 
    /* Start of interlace block */
@@ -3198,6 +3221,7 @@ png_read_start_row(png_structp png_ptr)
    /* Offset to next interlace block in the y direction */
    PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
 #endif
+#endif
 
    int max_pixel_depth;
    png_size_t row_bytes;
diff --git a/frmts/png/libpng/pngset.c b/frmts/png/libpng/pngset.c
index fed6a55..a53f9a8 100644
--- a/frmts/png/libpng/pngset.c
+++ b/frmts/png/libpng/pngset.c
@@ -1,8 +1,8 @@
 
 /* pngset.c - storage of image information into info struct
  *
- * Last changed in libpng 1.2.51 [February 6, 2014]
- * Copyright (c) 1998-2014 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.56 [%RDATE%]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -263,7 +263,10 @@ png_set_IHDR(png_structp png_ptr, png_infop info_ptr,
                  - 1        /* filter byte */
                  - 7*8      /* rounding of width to multiple of 8 pixels */
                  - 8)       /* extra max_pixel_depth pad */
+   {
       info_ptr->rowbytes = (png_size_t)0;
+      png_error(png_ptr, "Image width is too large for this architecture");
+   }
    else
       info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width);
 }
@@ -446,12 +449,17 @@ png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
    png_colorp palette, int num_palette)
 {
 
+   png_uint_32 max_palette_length;
+
    png_debug1(1, "in %s storage function", "PLTE");
 
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
-   if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH)
+   max_palette_length = (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ?
+      (1 << info_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH;
+
+   if (num_palette < 0 || num_palette > (int) max_palette_length)
    {
       if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
          png_error(png_ptr, "Invalid palette length");
@@ -471,8 +479,8 @@ png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
 #endif
 
    /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead
-    * of num_palette entries, in case of an invalid PNG file that has
-    * too-large sample values.
+    * of num_palette entries, in case of an invalid PNG file or incorrect
+    * call to png_set_PLTE() with too-large sample values.
     */
    png_ptr->palette = (png_colorp)png_calloc(png_ptr,
       PNG_MAX_PALETTE_LENGTH * png_sizeof(png_color));
@@ -770,10 +778,10 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr,
          (key_len + text_length + lang_len + lang_key_len + 4));
       if (textp->key == NULL)
          return(1);
-      png_debug2(2, "Allocated %lu bytes at %x in png_set_text",
+      png_debug2(2, "Allocated %lu bytes at %p in png_set_text",
                  (png_uint_32)
                  (key_len + lang_len + lang_key_len + text_length + 4),
-                 (int)textp->key);
+                 textp->key);
 
       png_memcpy(textp->key, text_ptr[i].key,(png_size_t)(key_len));
       *(textp->key + key_len) = '\0';
@@ -834,6 +842,15 @@ png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_timep mod_time)
        (png_ptr->mode & PNG_WROTE_tIME))
       return;
 
+   if (mod_time->month == 0   || mod_time->month > 12  ||
+       mod_time->day   == 0   || mod_time->day   > 31  ||
+       mod_time->hour  > 23   || mod_time->minute > 59 ||
+       mod_time->second > 60)
+   {
+      png_warning(png_ptr, "Ignoring invalid time value");
+      return;
+   }
+
    png_memcpy(&(info_ptr->mod_time), mod_time, png_sizeof(png_time));
    info_ptr->valid |= PNG_INFO_tIME;
 }
@@ -1215,7 +1232,7 @@ png_set_user_limits (png_structp png_ptr, png_uint_32 user_width_max,
 {
    /* Images with dimensions larger than these limits will be
     * rejected by png_set_IHDR().  To accept any PNG datastream
-    * regardless of dimensions, set both limits to 0x7ffffffL.
+    * regardless of dimensions, set both limits to 0x7fffffffL.
     */
    if (png_ptr == NULL)
       return;
@@ -1238,4 +1255,136 @@ png_set_benign_errors(png_structp png_ptr, int allowed)
 }
 #endif /* PNG_BENIGN_ERRORS_SUPPORTED */
 #endif /* ?PNG_1_0_X */
+
+#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
+    defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
+/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
+ * and if invalid, correct the keyword rather than discarding the entire
+ * chunk.  The PNG 1.0 specification requires keywords 1-79 characters in
+ * length, forbids leading or trailing whitespace, multiple internal spaces,
+ * and the non-break space (0x80) from ISO 8859-1.  Returns keyword length.
+ *
+ * The new_key is allocated to hold the corrected keyword and must be freed
+ * by the calling routine.  This avoids problems with trying to write to
+ * static keywords without having to have duplicate copies of the strings.
+ */
+png_size_t /* PRIVATE */
+png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key)
+{
+   png_size_t key_len;
+   png_charp kp, dp;
+   int kflag;
+   int kwarn=0;
+
+   png_debug(1, "in png_check_keyword");
+
+   *new_key = NULL;
+
+   if (key == NULL || (key_len = png_strlen(key)) == 0)
+   {
+      png_warning(png_ptr, "zero length keyword");
+      return ((png_size_t)0);
+   }
+
+   png_debug1(2, "Keyword to be checked is '%s'", key);
+
+   *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2));
+   if (*new_key == NULL)
+   {
+      png_warning(png_ptr, "Out of memory while procesing keyword");
+      return ((png_size_t)0);
+   }
+
+   /* Replace non-printing characters with a blank and print a warning */
+   for (kp = key, dp = *new_key; *kp != '\0'; kp++, dp++)
+   {
+      if ((png_byte)*kp < 0x20 ||
+         ((png_byte)*kp > 0x7E && (png_byte)*kp < 0xA1))
+      {
+#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
+         char msg[40];
+
+         png_snprintf(msg, 40,
+           "invalid keyword character 0x%02X", (png_byte)*kp);
+         png_warning(png_ptr, msg);
+#else
+         png_warning(png_ptr, "invalid character in keyword");
+#endif
+         *dp = ' ';
+      }
+      else
+      {
+         *dp = *kp;
+      }
+   }
+   *dp = '\0';
+
+   /* Remove any trailing white space. */
+   kp = *new_key + key_len - 1;
+   if (*kp == ' ')
+   {
+      png_warning(png_ptr, "trailing spaces removed from keyword");
+
+      while (key_len && *kp == ' ')
+      {
+         *(kp--) = '\0';
+         key_len--;
+      }
+   }
+
+   /* Remove any leading white space. */
+   kp = *new_key;
+   if (*kp == ' ')
+   {
+      png_warning(png_ptr, "leading spaces removed from keyword");
+
+      while (*kp == ' ')
+      {
+         kp++;
+         key_len--;
+      }
+   }
+
+   png_debug1(2, "Checking for multiple internal spaces in '%s'", kp);
+
+   /* Remove multiple internal spaces. */
+   for (kflag = 0, dp = *new_key; *kp != '\0'; kp++)
+   {
+      if (*kp == ' ' && kflag == 0)
+      {
+         *(dp++) = *kp;
+         kflag = 1;
+      }
+      else if (*kp == ' ')
+      {
+         key_len--;
+         kwarn=1;
+      }
+      else
+      {
+         *(dp++) = *kp;
+         kflag = 0;
+      }
+   }
+   *dp = '\0';
+   if (kwarn)
+      png_warning(png_ptr, "extra interior spaces removed from keyword");
+
+   if (key_len == 0)
+   {
+      png_free(png_ptr, *new_key);
+       *new_key=NULL;
+      png_warning(png_ptr, "Zero length keyword");
+   }
+
+   if (key_len > 79)
+   {
+      png_warning(png_ptr, "keyword length must be 1 - 79 characters");
+      (*new_key)[79] = '\0';
+      key_len = 79;
+   }
+
+   return (key_len);
+}
+#endif /* WRITE_TEXT || WRITE_pCAL) || WRITE_iCCP || WRITE_sPLT */
 #endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
diff --git a/frmts/png/libpng/pngtrans.c b/frmts/png/libpng/pngtrans.c
index 6ad9dcf..1137701 100644
--- a/frmts/png/libpng/pngtrans.c
+++ b/frmts/png/libpng/pngtrans.c
@@ -2,7 +2,7 @@
 /* pngtrans.c - transforms the data in a row (used by both readers and writers)
  *
  * Last changed in libpng 1.2.41 [December 3, 2009]
- * Copyright (c) 1998-2009 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2009 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
diff --git a/frmts/png/libpng/pngvcrd.c b/frmts/png/libpng/pngvcrd.c
index f553138..be6cbdb 100644
--- a/frmts/png/libpng/pngvcrd.c
+++ b/frmts/png/libpng/pngvcrd.c
@@ -1,6 +1,7 @@
 /* pngvcrd.c
  *
  * Last changed in libpng 1.2.48 [March 8, 2012]
+ * Copyright (c) 1998-2002,2004,2007,2012 Glenn Randers-Pehrson
  * Copyright (c) 1998-2012 Glenn Randers-Pehrson
  *
  * This code is released under the libpng license.
diff --git a/frmts/png/libpng/pngwio.c b/frmts/png/libpng/pngwio.c
index 44e5ea9..7962241 100644
--- a/frmts/png/libpng/pngwio.c
+++ b/frmts/png/libpng/pngwio.c
@@ -2,7 +2,7 @@
 /* pngwio.c - functions for data output
  *
  * Last changed in libpng 1.2.41 [December 3, 2009]
- * Copyright (c) 1998-2009 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-209 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
diff --git a/frmts/png/libpng/pngwrite.c b/frmts/png/libpng/pngwrite.c
index 894a984..12a11ba 100644
--- a/frmts/png/libpng/pngwrite.c
+++ b/frmts/png/libpng/pngwrite.c
@@ -1,8 +1,8 @@
 
 /* pngwrite.c - general routines to write a PNG file
  *
- * Last changed in libpng 1.2.52 [November 20, 2014]
- * Copyright (c) 1998-2014 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.54 [November 12, 2015]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -584,11 +584,6 @@ png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
    png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL,
       png_flush_ptr_NULL);
 
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
-   png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT,
-      1, png_doublep_NULL, png_doublep_NULL);
-#endif
-
 #ifdef PNG_SETJMP_SUPPORTED
    /* Applications that neglect to set up their own setjmp() and then
     * encounter a png_error() will longjmp here.  Since the jmpbuf is
@@ -731,10 +726,6 @@ png_write_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver,
    png_ptr->zbuf_size = PNG_ZBUF_SIZE;
    png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
      (png_uint_32)png_ptr->zbuf_size);
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
-   png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT,
-      1, png_doublep_NULL, png_doublep_NULL);
-#endif
 }
 
 /* Write a few rows of image data.  If the image is interlaced,
@@ -1150,14 +1141,6 @@ png_write_destroy(png_structp png_ptr)
    png_free(png_ptr, png_ptr->time_buffer);
 #endif
 
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
-   png_free(png_ptr, png_ptr->prev_filters);
-   png_free(png_ptr, png_ptr->filter_weights);
-   png_free(png_ptr, png_ptr->inv_filter_weights);
-   png_free(png_ptr, png_ptr->filter_costs);
-   png_free(png_ptr, png_ptr->inv_filter_costs);
-#endif
-
 #ifdef PNG_SETJMP_SUPPORTED
    /* Reset structure */
    png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf));
@@ -1201,14 +1184,13 @@ png_set_filter(png_structp png_ptr, int method, int filters)
    {
       switch (filters & (PNG_ALL_FILTERS | 0x07))
       {
+         case PNG_FILTER_VALUE_NONE:
+              png_ptr->do_filter = PNG_FILTER_NONE; break;
 #ifdef PNG_WRITE_FILTER_SUPPORTED
          case 5:
          case 6:
          case 7: png_warning(png_ptr, "Unknown row filter for method 0");
-#endif /* PNG_WRITE_FILTER_SUPPORTED */
-         case PNG_FILTER_VALUE_NONE:
-              png_ptr->do_filter = PNG_FILTER_NONE; break;
-#ifdef PNG_WRITE_FILTER_SUPPORTED
+                 break;
          case PNG_FILTER_VALUE_SUB:
               png_ptr->do_filter = PNG_FILTER_SUB; break;
          case PNG_FILTER_VALUE_UP:
@@ -1220,6 +1202,7 @@ png_set_filter(png_structp png_ptr, int method, int filters)
          default: png_ptr->do_filter = (png_byte)filters; break;
 #else
          default: png_warning(png_ptr, "Unknown row filter for method 0");
+                 break;
 #endif /* PNG_WRITE_FILTER_SUPPORTED */
       }
 
@@ -1310,117 +1293,11 @@ png_set_filter_heuristics(png_structp png_ptr, int heuristic_method,
    int num_weights, png_doublep filter_weights,
    png_doublep filter_costs)
 {
-   int i;
-
-   png_debug(1, "in png_set_filter_heuristics");
-
-   if (png_ptr == NULL)
-      return;
-   if (heuristic_method >= PNG_FILTER_HEURISTIC_LAST)
-   {
-      png_warning(png_ptr, "Unknown filter heuristic method");
-      return;
-   }
-
-   if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT)
-   {
-      heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED;
-   }
-
-   if (num_weights < 0 || filter_weights == NULL ||
-      heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED)
-   {
-      num_weights = 0;
-   }
-
-   png_ptr->num_prev_filters = (png_byte)num_weights;
-   png_ptr->heuristic_method = (png_byte)heuristic_method;
-
-   if (num_weights > 0)
-   {
-      if (png_ptr->prev_filters == NULL)
-      {
-         png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr,
-            (png_uint_32)(png_sizeof(png_byte) * num_weights));
-
-         /* To make sure that the weighting starts out fairly */
-         for (i = 0; i < num_weights; i++)
-         {
-            png_ptr->prev_filters[i] = 255;
-         }
-      }
-
-      if (png_ptr->filter_weights == NULL)
-      {
-         png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr,
-            (png_uint_32)(png_sizeof(png_uint_16) * num_weights));
-
-         png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr,
-            (png_uint_32)(png_sizeof(png_uint_16) * num_weights));
-         for (i = 0; i < num_weights; i++)
-         {
-            png_ptr->inv_filter_weights[i] =
-            png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
-         }
-      }
-
-      for (i = 0; i < num_weights; i++)
-      {
-         if (filter_weights[i] < 0.0)
-         {
-            png_ptr->inv_filter_weights[i] =
-            png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
-         }
-         else
-         {
-            png_ptr->inv_filter_weights[i] =
-               (png_uint_16)((double)PNG_WEIGHT_FACTOR*filter_weights[i]+0.5);
-            png_ptr->filter_weights[i] =
-               (png_uint_16)((double)PNG_WEIGHT_FACTOR/filter_weights[i]+0.5);
-         }
-      }
-   }
-
-   /* If, in the future, there are other filter methods, this would
-    * need to be based on png_ptr->filter.
-    */
-   if (png_ptr->filter_costs == NULL)
-   {
-      png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr,
-         (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST));
-
-      png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr,
-         (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST));
-
-      for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
-      {
-         png_ptr->inv_filter_costs[i] =
-         png_ptr->filter_costs[i] = PNG_COST_FACTOR;
-      }
-   }
-
-   /* Here is where we set the relative costs of the different filters.  We
-    * should take the desired compression level into account when setting
-    * the costs, so that Paeth, for instance, has a high relative cost at low
-    * compression levels, while it has a lower relative cost at higher
-    * compression settings.  The filter types are in order of increasing
-    * relative cost, so it would be possible to do this with an algorithm.
-    */
-   for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
-   {
-      if (filter_costs == NULL || filter_costs[i] < 0.0)
-      {
-         png_ptr->inv_filter_costs[i] =
-         png_ptr->filter_costs[i] = PNG_COST_FACTOR;
-      }
-      else if (filter_costs[i] >= 1.0)
-      {
-         png_ptr->inv_filter_costs[i] =
-            (png_uint_16)((double)PNG_COST_FACTOR / filter_costs[i] + 0.5);
-         png_ptr->filter_costs[i] =
-            (png_uint_16)((double)PNG_COST_FACTOR * filter_costs[i] + 0.5);
-      }
-   }
+   PNG_UNUSED(png_ptr)
+   PNG_UNUSED(heuristic_method)
+   PNG_UNUSED(num_weights)
+   PNG_UNUSED(filter_weights)
+   PNG_UNUSED(filter_costs)
 }
 #endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
 
diff --git a/frmts/png/libpng/pngwtran.c b/frmts/png/libpng/pngwtran.c
index 0ce9b9b..a702cf9 100644
--- a/frmts/png/libpng/pngwtran.c
+++ b/frmts/png/libpng/pngwtran.c
@@ -2,7 +2,7 @@
 /* pngwtran.c - transforms the data in a row for PNG writers
  *
  * Last changed in libpng 1.2.43 [February 25, 2010]
- * Copyright (c) 1998-2010 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2010 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
diff --git a/frmts/png/libpng/pngwutil.c b/frmts/png/libpng/pngwutil.c
index c75f53e..c09a96d 100644
--- a/frmts/png/libpng/pngwutil.c
+++ b/frmts/png/libpng/pngwutil.c
@@ -1,8 +1,8 @@
 
 /* pngwutil.c - utilities to write a PNG file
  *
- * Last changed in libpng 1.2.43 [February 25, 2010]
- * Copyright (c) 1998-2010 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.56 [%RDATE%]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -188,7 +188,7 @@ png_text_compress(png_structp png_ptr,
    if (compression == PNG_TEXT_COMPRESSION_NONE)
    {
        comp->input = text;
-       comp->input_len = text_len;
+       comp->input_len = (int)text_len;
        return((int)text_len);
    }
 
@@ -254,7 +254,7 @@ png_text_compress(png_structp png_ptr,
                old_ptr = comp->output_ptr;
                comp->output_ptr = (png_charpp)png_malloc(png_ptr,
                   (png_uint_32)
-                  (comp->max_output_ptr * png_sizeof(png_charpp)));
+                  (comp->max_output_ptr * png_sizeof(png_charp)));
                png_memcpy(comp->output_ptr, old_ptr, old_max
                   * png_sizeof(png_charp));
                png_free(png_ptr, old_ptr);
@@ -486,7 +486,7 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
    interlace_type=PNG_INTERLACE_NONE;
 #endif
 
-   /* Save the relevent information */
+   /* Save the relevant information */
    png_ptr->bit_depth = (png_byte)bit_depth;
    png_ptr->color_type = (png_byte)color_type;
    png_ptr->interlaced = (png_byte)interlace_type;
@@ -575,17 +575,20 @@ png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal)
 #ifdef PNG_USE_LOCAL_ARRAYS
    PNG_PLTE;
 #endif
-   png_uint_32 i;
+   png_uint_32 max_palette_length, i;
    png_colorp pal_ptr;
    png_byte buf[3];
 
    png_debug(1, "in png_write_PLTE");
 
+   max_palette_length = (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ?
+      (1 << png_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH;
+
    if ((
 #ifdef PNG_MNG_FEATURES_SUPPORTED
         !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) &&
 #endif
-        num_pal == 0) || num_pal > 256)
+       num_pal == 0) || num_pal > max_palette_length)
    {
      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
      {
@@ -856,7 +859,7 @@ png_write_sPLT(png_structp png_ptr, png_sPLT_tp spalette)
    png_charp new_name;
    png_byte entrybuf[10];
    int entry_size = (spalette->depth == 8 ? 6 : 10);
-   int palette_size = entry_size * spalette->nentries;
+   int palette_size = (int)(entry_size * spalette->nentries);
    png_sPLT_entryp ep;
 #ifndef PNG_POINTER_INDEXING_SUPPORTED
    int i;
@@ -1213,138 +1216,6 @@ png_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist)
 }
 #endif
 
-#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
-    defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
-/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
- * and if invalid, correct the keyword rather than discarding the entire
- * chunk.  The PNG 1.0 specification requires keywords 1-79 characters in
- * length, forbids leading or trailing whitespace, multiple internal spaces,
- * and the non-break space (0x80) from ISO 8859-1.  Returns keyword length.
- *
- * The new_key is allocated to hold the corrected keyword and must be freed
- * by the calling routine.  This avoids problems with trying to write to
- * static keywords without having to have duplicate copies of the strings.
- */
-png_size_t /* PRIVATE */
-png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key)
-{
-   png_size_t key_len;
-   png_charp kp, dp;
-   int kflag;
-   int kwarn=0;
-
-   png_debug(1, "in png_check_keyword");
-
-   *new_key = NULL;
-
-   if (key == NULL || (key_len = png_strlen(key)) == 0)
-   {
-      png_warning(png_ptr, "zero length keyword");
-      return ((png_size_t)0);
-   }
-
-   png_debug1(2, "Keyword to be checked is '%s'", key);
-
-   *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2));
-   if (*new_key == NULL)
-   {
-      png_warning(png_ptr, "Out of memory while procesing keyword");
-      return ((png_size_t)0);
-   }
-
-   /* Replace non-printing characters with a blank and print a warning */
-   for (kp = key, dp = *new_key; *kp != '\0'; kp++, dp++)
-   {
-      if ((png_byte)*kp < 0x20 ||
-         ((png_byte)*kp > 0x7E && (png_byte)*kp < 0xA1))
-      {
-#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
-         char msg[40];
-
-         png_snprintf(msg, 40,
-           "invalid keyword character 0x%02X", (png_byte)*kp);
-         png_warning(png_ptr, msg);
-#else
-         png_warning(png_ptr, "invalid character in keyword");
-#endif
-         *dp = ' ';
-      }
-      else
-      {
-         *dp = *kp;
-      }
-   }
-   *dp = '\0';
-
-   /* Remove any trailing white space. */
-   kp = *new_key + key_len - 1;
-   if (*kp == ' ')
-   {
-      png_warning(png_ptr, "trailing spaces removed from keyword");
-
-      while (*kp == ' ')
-      {
-         *(kp--) = '\0';
-         key_len--;
-      }
-   }
-
-   /* Remove any leading white space. */
-   kp = *new_key;
-   if (*kp == ' ')
-   {
-      png_warning(png_ptr, "leading spaces removed from keyword");
-
-      while (*kp == ' ')
-      {
-         kp++;
-         key_len--;
-      }
-   }
-
-   png_debug1(2, "Checking for multiple internal spaces in '%s'", kp);
-
-   /* Remove multiple internal spaces. */
-   for (kflag = 0, dp = *new_key; *kp != '\0'; kp++)
-   {
-      if (*kp == ' ' && kflag == 0)
-      {
-         *(dp++) = *kp;
-         kflag = 1;
-      }
-      else if (*kp == ' ')
-      {
-         key_len--;
-         kwarn=1;
-      }
-      else
-      {
-         *(dp++) = *kp;
-         kflag = 0;
-      }
-   }
-   *dp = '\0';
-   if (kwarn)
-      png_warning(png_ptr, "extra interior spaces removed from keyword");
-
-   if (key_len == 0)
-   {
-      png_free(png_ptr, *new_key);
-       *new_key=NULL;
-      png_warning(png_ptr, "Zero length keyword");
-   }
-
-   if (key_len > 79)
-   {
-      png_warning(png_ptr, "keyword length must be 1 - 79 characters");
-      (*new_key)[79] = '\0';
-      key_len = 79;
-   }
-
-   return (key_len);
-}
-#endif
-
 #ifdef PNG_WRITE_tEXt_SUPPORTED
 /* Write a tEXt chunk */
 void /* PRIVATE */
@@ -1759,6 +1630,7 @@ void /* PRIVATE */
 png_write_start_row(png_structp png_ptr)
 {
 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
+#ifndef PNG_USE_GLOBAL_ARRAYS
    /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
 
    /* Start of interlace block */
@@ -1773,6 +1645,7 @@ png_write_start_row(png_structp png_ptr)
    /* Offset to next interlace block in the y direction */
    int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
 #endif
+#endif
 
    png_size_t buf_size;
 
@@ -1857,6 +1730,7 @@ void /* PRIVATE */
 png_write_finish_row(png_structp png_ptr)
 {
 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
+#ifndef PNG_USE_GLOBAL_ARRAYS
    /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
 
    /* Start of interlace block */
@@ -1871,6 +1745,7 @@ png_write_finish_row(png_structp png_ptr)
    /* Offset to next interlace block in the y direction */
    int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
 #endif
+#endif
 
    int ret;
 
@@ -1976,11 +1851,13 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
 {
    /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
 
+#ifndef PNG_USE_GLOBAL_ARRAYS
    /* Start of interlace block */
    int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
 
    /* Offset to next interlace block */
    int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+#endif
 
    png_debug(1, "in png_do_write_interlace");
 
@@ -2150,20 +2027,9 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
    png_uint_32 mins, bpp;
    png_byte filter_to_do = png_ptr->do_filter;
    png_uint_32 row_bytes = row_info->rowbytes;
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
-   int num_p_filters = (int)png_ptr->num_prev_filters;
-#endif 
 
    png_debug(1, "in png_write_find_filter");
 
-#ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
-  if (png_ptr->row_number == 0 && filter_to_do == PNG_ALL_FILTERS)
-  {
-      /* These will never be selected so we need not test them. */
-      filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_PAETH);
-  }
-#endif 
-
    /* Find out how many bytes offset each pixel is */
    bpp = (row_info->pixel_depth + 7) >> 3;
 
@@ -2213,41 +2079,6 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
          sum += (v < 128) ? v : 256 - v;
       }
 
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
-      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
-      {
-         png_uint_32 sumhi, sumlo;
-         int j;
-         sumlo = sum & PNG_LOMASK;
-         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */
-
-         /* Reduce the sum if we match any of the previous rows */
-         for (j = 0; j < num_p_filters; j++)
-         {
-            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
-            {
-               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
-                  PNG_WEIGHT_SHIFT;
-               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
-                  PNG_WEIGHT_SHIFT;
-            }
-         }
-
-         /* Factor in the cost of this filter (this is here for completeness,
-          * but it makes no sense to have a "cost" for the NONE filter, as
-          * it has the minimum possible computational cost - none).
-          */
-         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
-            PNG_COST_SHIFT;
-         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
-            PNG_COST_SHIFT;
-
-         if (sumhi > PNG_HIMASK)
-            sum = PNG_MAXSUM;
-         else
-            sum = (sumhi << PNG_HISHIFT) + sumlo;
-      }
-#endif
       mins = sum;
    }
 
@@ -2277,41 +2108,6 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
       png_uint_32 i;
       int v;
 
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
-      /* We temporarily increase the "minimum sum" by the factor we
-       * would reduce the sum of this filter, so that we can do the
-       * early exit comparison without scaling the sum each time.
-       */
-      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
-      {
-         int j;
-         png_uint_32 lmhi, lmlo;
-         lmlo = lmins & PNG_LOMASK;
-         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
-
-         for (j = 0; j < num_p_filters; j++)
-         {
-            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
-            {
-               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
-                  PNG_WEIGHT_SHIFT;
-               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
-                  PNG_WEIGHT_SHIFT;
-            }
-         }
-
-         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
-            PNG_COST_SHIFT;
-         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
-            PNG_COST_SHIFT;
-
-         if (lmhi > PNG_HIMASK)
-            lmins = PNG_MAXSUM;
-         else
-            lmins = (lmhi << PNG_HISHIFT) + lmlo;
-      }
-#endif
-
       for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
            i++, rp++, dp++)
       {
@@ -2330,37 +2126,6 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
             break;
       }
 
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
-      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
-      {
-         int j;
-         png_uint_32 sumhi, sumlo;
-         sumlo = sum & PNG_LOMASK;
-         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
-
-         for (j = 0; j < num_p_filters; j++)
-         {
-            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
-            {
-               sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >>
-                  PNG_WEIGHT_SHIFT;
-               sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >>
-                  PNG_WEIGHT_SHIFT;
-            }
-         }
-
-         sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
-            PNG_COST_SHIFT;
-         sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
-            PNG_COST_SHIFT;
-
-         if (sumhi > PNG_HIMASK)
-            sum = PNG_MAXSUM;
-         else
-            sum = (sumhi << PNG_HISHIFT) + sumlo;
-      }
-#endif
-
       if (sum < mins)
       {
          mins = sum;
@@ -2390,38 +2155,6 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
       png_uint_32 i;
       int v;
 
-
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
-      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
-      {
-         int j;
-         png_uint_32 lmhi, lmlo;
-         lmlo = lmins & PNG_LOMASK;
-         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
-
-         for (j = 0; j < num_p_filters; j++)
-         {
-            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
-            {
-               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
-                  PNG_WEIGHT_SHIFT;
-               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
-                  PNG_WEIGHT_SHIFT;
-            }
-         }
-
-         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
-            PNG_COST_SHIFT;
-         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
-            PNG_COST_SHIFT;
-
-         if (lmhi > PNG_HIMASK)
-            lmins = PNG_MAXSUM;
-         else
-            lmins = (lmhi << PNG_HISHIFT) + lmlo;
-      }
-#endif
-
       for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
            pp = prev_row + 1; i < row_bytes; i++)
       {
@@ -2433,37 +2166,6 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
             break;
       }
 
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
-      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
-      {
-         int j;
-         png_uint_32 sumhi, sumlo;
-         sumlo = sum & PNG_LOMASK;
-         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
-
-         for (j = 0; j < num_p_filters; j++)
-         {
-            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
-            {
-               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
-                  PNG_WEIGHT_SHIFT;
-               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
-                  PNG_WEIGHT_SHIFT;
-            }
-         }
-
-         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
-            PNG_COST_SHIFT;
-         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
-            PNG_COST_SHIFT;
-
-         if (sumhi > PNG_HIMASK)
-            sum = PNG_MAXSUM;
-         else
-            sum = (sumhi << PNG_HISHIFT) + sumlo;
-      }
-#endif
-
       if (sum < mins)
       {
          mins = sum;
@@ -2496,37 +2198,6 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
       png_uint_32 i;
       int v;
 
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
-      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
-      {
-         int j;
-         png_uint_32 lmhi, lmlo;
-         lmlo = lmins & PNG_LOMASK;
-         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
-
-         for (j = 0; j < num_p_filters; j++)
-         {
-            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG)
-            {
-               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
-                  PNG_WEIGHT_SHIFT;
-               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
-                  PNG_WEIGHT_SHIFT;
-            }
-         }
-
-         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
-            PNG_COST_SHIFT;
-         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
-            PNG_COST_SHIFT;
-
-         if (lmhi > PNG_HIMASK)
-            lmins = PNG_MAXSUM;
-         else
-            lmins = (lmhi << PNG_HISHIFT) + lmlo;
-      }
-#endif
-
       for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
            pp = prev_row + 1; i < bpp; i++)
       {
@@ -2545,37 +2216,6 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
             break;
       }
 
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
-      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
-      {
-         int j;
-         png_uint_32 sumhi, sumlo;
-         sumlo = sum & PNG_LOMASK;
-         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
-
-         for (j = 0; j < num_p_filters; j++)
-         {
-            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
-            {
-               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
-                  PNG_WEIGHT_SHIFT;
-               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
-                  PNG_WEIGHT_SHIFT;
-            }
-         }
-
-         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
-            PNG_COST_SHIFT;
-         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
-            PNG_COST_SHIFT;
-
-         if (sumhi > PNG_HIMASK)
-            sum = PNG_MAXSUM;
-         else
-            sum = (sumhi << PNG_HISHIFT) + sumlo;
-      }
-#endif
-
       if (sum < mins)
       {
          mins = sum;
@@ -2629,37 +2269,6 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
       png_uint_32 i;
       int v;
 
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
-      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
-      {
-         int j;
-         png_uint_32 lmhi, lmlo;
-         lmlo = lmins & PNG_LOMASK;
-         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
-
-         for (j = 0; j < num_p_filters; j++)
-         {
-            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
-            {
-               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
-                  PNG_WEIGHT_SHIFT;
-               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
-                  PNG_WEIGHT_SHIFT;
-            }
-         }
-
-         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
-            PNG_COST_SHIFT;
-         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
-            PNG_COST_SHIFT;
-
-         if (lmhi > PNG_HIMASK)
-            lmins = PNG_MAXSUM;
-         else
-            lmins = (lmhi << PNG_HISHIFT) + lmlo;
-      }
-#endif
-
       for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
            pp = prev_row + 1; i < bpp; i++)
       {
@@ -2710,37 +2319,6 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
             break;
       }
 
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
-      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
-      {
-         int j;
-         png_uint_32 sumhi, sumlo;
-         sumlo = sum & PNG_LOMASK;
-         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
-
-         for (j = 0; j < num_p_filters; j++)
-         {
-            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
-            {
-               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
-                  PNG_WEIGHT_SHIFT;
-               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
-                  PNG_WEIGHT_SHIFT;
-            }
-         }
-
-         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
-            PNG_COST_SHIFT;
-         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
-            PNG_COST_SHIFT;
-
-         if (sumhi > PNG_HIMASK)
-            sum = PNG_MAXSUM;
-         else
-            sum = (sumhi << PNG_HISHIFT) + sumlo;
-      }
-#endif
-
       if (sum < mins)
       {
          best_row = png_ptr->paeth_row;
@@ -2750,21 +2328,6 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
    /* Do the actual writing of the filtered row data from the chosen filter. */
 
    png_write_filtered_row(png_ptr, best_row);
-
-#ifdef PNG_WRITE_FILTER_SUPPORTED
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
-   /* Save the type of filter we picked this time for future calculations */
-   if (png_ptr->num_prev_filters > 0)
-   {
-      int j;
-      for (j = 1; j < num_p_filters; j++)
-      {
-         png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1];
-      }
-      png_ptr->prev_filters[j] = best_row[0];
-   }
-#endif
-#endif /* PNG_WRITE_FILTER_SUPPORTED */
 }
 
 
diff --git a/frmts/png/pngdataset.cpp b/frmts/png/pngdataset.cpp
index c44a53a..768c526 100644
--- a/frmts/png/pngdataset.cpp
+++ b/frmts/png/pngdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pngdataset.cpp 28785 2015-03-26 20:46:45Z goatbar $
+ * $Id: pngdataset.cpp 33794 2016-03-26 13:19:07Z goatbar $
  *
  * Project:  PNG Driver
  * Purpose:  Implement GDAL PNG Support
@@ -29,32 +29,27 @@
  ******************************************************************************
  *
  * ISSUES:
- *  o CollectMetadata() will only capture TEXT chunks before the image 
- *    data as the code is currently structured. 
+ *  o CollectMetadata() will only capture TEXT chunks before the image
+ *    data as the code is currently structured.
  *  o Interlaced images are read entirely into memory for use.  This is
  *    bad for large images.
  *  o Image reading is always strictly sequential.  Reading backwards will
  *    cause the file to be rewound, and access started again from the
- *    beginning. 
- *  o 1, 2 and 4 bit data promoted to 8 bit. 
- *  o Transparency values not currently read and applied to palette.
- *  o 16 bit alpha values are not scaled by to eight bit. 
- *  o I should install setjmp()/longjmp() based error trapping for PNG calls.
- *    Currently a failure in png libraries will result in a complete
- *    application termination. 
- * 
+ *    beginning.
+ *  o 16 bit alpha values are not scaled by to eight bit.
+ *
  */
 
+#include "cpl_string.h"
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 #include "png.h"
-#include "cpl_string.h"
-#include <setjmp.h>
 
-CPL_CVSID("$Id: pngdataset.cpp 28785 2015-03-26 20:46:45Z goatbar $");
+#include <csetjmp>
 
-CPL_C_START
-void	GDALRegister_PNG(void);
-CPL_C_END
+#include <algorithm>
+
+CPL_CVSID("$Id: pngdataset.cpp 33794 2016-03-26 13:19:07Z goatbar $");
 
 // Define SUPPORT_CREATE if you want Create() call supported.
 // Note: callers must provide blocks in increasing Y order.
@@ -63,7 +58,7 @@ CPL_C_END
 // A lot of issues remains : uninitialized variables, unclosed file,
 // inability to handle properly multiband case, inability to read&write
 // at the same time. Do NOT use it unless you're ready to fix it
-//#define SUPPORT_CREATE
+// #define SUPPORT_CREATE
 
 // we believe it is ok to use setjmp() in this situation.
 #ifdef _MSC_VER
@@ -89,6 +84,12 @@ static void png_gdal_warning( png_structp png_ptr, const char *error_message );
 
 class PNGRasterBand;
 
+
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable : 4324 ) /* 'PNGDataset' : structure was padded due to __declspec(align()) at line where we use jmp_buf */
+#endif
+
 class PNGDataset : public GDALPamDataset
 {
     friend class PNGRasterBand;
@@ -126,13 +127,13 @@ class PNGDataset : public GDALPamDataset
 
     int         bHasReadICCMetadata;
     void        LoadICCProfile();
-    
+
     static void WriteMetadataAsText(png_structp hPNG, png_infop psPNGInfo,
                                     const char* pszKey, const char* pszValue);
 
   public:
                  PNGDataset();
-                 ~PNGDataset();
+    virtual ~PNGDataset();
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int          Identify( GDALOpenInfo * );
@@ -186,6 +187,10 @@ class PNGDataset : public GDALPamDataset
 #endif
 };
 
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
+
 /************************************************************************/
 /* ==================================================================== */
 /*                            PNGRasterBand                             */
@@ -199,6 +204,7 @@ class PNGRasterBand : public GDALPamRasterBand
   public:
 
                    PNGRasterBand( PNGDataset *, int );
+    virtual ~PNGRasterBand() {}
 
     virtual CPLErr IReadBlock( int, int, void * );
 
@@ -219,10 +225,10 @@ class PNGRasterBand : public GDALPamRasterBand
 	int m_bBandProvided[5];
 	void reset_band_provision_flags()
 	{
-		PNGDataset& ds = *(PNGDataset*)poDS;
+            PNGDataset& ds = *reinterpret_cast<PNGDataset *>( poDS );
 
-		for(size_t i = 0; i < ds.nBands; i++)
-			m_bBandProvided[i] = FALSE;
+            for(size_t i = 0; i < static_cast<size_t>( ds.nBands ); i++)
+                m_bBandProvided[i] = FALSE;
 	}
 #endif
 };
@@ -232,23 +238,21 @@ class PNGRasterBand : public GDALPamRasterBand
 /*                           PNGRasterBand()                            */
 /************************************************************************/
 
-PNGRasterBand::PNGRasterBand( PNGDataset *poDS, int nBand )
-
+PNGRasterBand::PNGRasterBand( PNGDataset *poDSIn, int nBandIn ) :
+    bHaveNoData(FALSE),
+    dfNoDataValue(-1)
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
 
-    if( poDS->nBitDepth == 16 )
+    if( poDSIn->nBitDepth == 16 )
         eDataType = GDT_UInt16;
     else
         eDataType = GDT_Byte;
 
-    nBlockXSize = poDS->nRasterXSize;;
+    nBlockXSize = poDSIn->nRasterXSize;
     nBlockYSize = 1;
 
-    bHaveNoData = FALSE;
-    dfNoDataValue = -1;
-
 #ifdef SUPPORT_CREATE
 	this->reset_band_provision_flags();
 #endif
@@ -262,10 +266,8 @@ CPLErr PNGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                   void * pImage )
 
 {
-    PNGDataset	*poGDS = (PNGDataset *) poDS;
-    CPLErr      eErr;
-    GByte       *pabyScanline;
-    int         i, nPixelSize, nPixelOffset, nXSize = GetXSize();
+    PNGDataset *poGDS = reinterpret_cast<PNGDataset *>( poDS );
+    int nPixelSize;
 
     CPLAssert( nBlockXOff == 0 );
 
@@ -275,54 +277,52 @@ CPLErr PNGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         nPixelSize = 1;
 
 
+    const int nXSize = GetXSize();
     if (poGDS->fpImage == NULL)
     {
         memset( pImage, 0, nPixelSize * nXSize );
         return CE_None;
     }
 
-    nPixelOffset = poGDS->nBands * nPixelSize;
-
 /* -------------------------------------------------------------------- */
 /*      Load the desired scanline into the working buffer.              */
 /* -------------------------------------------------------------------- */
-    eErr = poGDS->LoadScanline( nBlockYOff );
+    CPLErr eErr = poGDS->LoadScanline( nBlockYOff );
     if( eErr != CE_None )
         return eErr;
 
-    pabyScanline = poGDS->pabyBuffer 
+    const int nPixelOffset = poGDS->nBands * nPixelSize;
+
+    GByte *pabyScanline = poGDS->pabyBuffer
         + (nBlockYOff - poGDS->nBufferStartLine) * nPixelOffset * nXSize
         + nPixelSize * (nBand - 1);
 
 /* -------------------------------------------------------------------- */
-/*      Transfer between the working buffer the the callers buffer.     */
+/*      Transfer between the working buffer and the callers buffer.     */
 /* -------------------------------------------------------------------- */
     if( nPixelSize == nPixelOffset )
         memcpy( pImage, pabyScanline, nPixelSize * nXSize );
     else if( nPixelSize == 1 )
     {
-        for( i = 0; i < nXSize; i++ )
-            ((GByte *) pImage)[i] = pabyScanline[i*nPixelOffset];
+        for( int i = 0; i < nXSize; i++ )
+            reinterpret_cast<GByte *>( pImage )[i] = pabyScanline[i*nPixelOffset];
     }
-    else 
+    else
     {
         CPLAssert( nPixelSize == 2 );
-        for( i = 0; i < nXSize; i++ )
+        for( int i = 0; i < nXSize; i++ )
         {
-            ((GUInt16 *) pImage)[i] = 
-                *((GUInt16 *) (pabyScanline+i*nPixelOffset));
+            reinterpret_cast<GUInt16 *>( pImage )[i] =
+                *reinterpret_cast<GUInt16 *>( pabyScanline+i*nPixelOffset );
         }
     }
 
 /* -------------------------------------------------------------------- */
-/*      Forceably load the other bands associated with this scanline.   */
+/*      Forcibly load the other bands associated with this scanline.    */
 /* -------------------------------------------------------------------- */
-    int iBand;
-    for(iBand = 1; iBand < poGDS->GetRasterCount(); iBand++)
+    for(int iBand = 1; iBand < poGDS->GetRasterCount(); iBand++)
     {
-        GDALRasterBlock *poBlock;
-
-        poBlock = 
+        GDALRasterBlock *poBlock =
             poGDS->GetRasterBand(iBand+1)->GetLockedBlockRef(nBlockXOff,nBlockYOff);
         if( poBlock != NULL )
             poBlock->DropLock();
@@ -338,7 +338,7 @@ CPLErr PNGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 GDALColorInterp PNGRasterBand::GetColorInterpretation()
 
 {
-    PNGDataset	*poGDS = (PNGDataset *) poDS;
+    PNGDataset *poGDS = reinterpret_cast<PNGDataset *>( poDS );
 
     if( poGDS->nColorType == PNG_COLOR_TYPE_GRAY )
         return GCI_GrayIndex;
@@ -363,7 +363,7 @@ GDALColorInterp PNGRasterBand::GetColorInterpretation()
             return GCI_GreenBand;
         else if( nBand == 3 )
             return GCI_BlueBand;
-        else 
+        else
             return GCI_AlphaBand;
     }
     else
@@ -377,12 +377,12 @@ GDALColorInterp PNGRasterBand::GetColorInterpretation()
 GDALColorTable *PNGRasterBand::GetColorTable()
 
 {
-    PNGDataset	*poGDS = (PNGDataset *) poDS;
+    PNGDataset  *poGDS = reinterpret_cast<PNGDataset *>( poDS );
 
     if( nBand == 1 )
         return poGDS->poColorTable;
-    else
-        return NULL;
+
+    return NULL;
 }
 
 /************************************************************************/
@@ -394,7 +394,7 @@ CPLErr PNGRasterBand::SetNoDataValue( double dfNewValue )
 {
    bHaveNoData = TRUE;
    dfNoDataValue = dfNewValue;
-      
+
    return CE_None;
 }
 
@@ -411,10 +411,8 @@ double PNGRasterBand::GetNoDataValue( int *pbSuccess )
             *pbSuccess = bHaveNoData;
         return dfNoDataValue;
     }
-    else
-    {
-        return GDALPamRasterBand::GetNoDataValue( pbSuccess );
-    }
+
+    return GDALPamRasterBand::GetNoDataValue( pbSuccess );
 }
 
 /************************************************************************/
@@ -428,20 +426,23 @@ double PNGRasterBand::GetNoDataValue( int *pbSuccess )
 /*                            PNGDataset()                            */
 /************************************************************************/
 
-PNGDataset::PNGDataset()
-
+PNGDataset::PNGDataset() :
+    fpImage(NULL),
+    hPNG(NULL),
+    psPNGInfo(NULL),
+    nBitDepth(8),
+    nColorType(0),
+    bInterlaced(FALSE),
+    nBufferStartLine(0),
+    nBufferLines(0),
+    nLastLineRead(-1),
+    pabyBuffer(NULL),
+    poColorTable(NULL),
+    bGeoTransformValid(FALSE),
+    bHasReadXMPMetadata(FALSE),
+    bHasTriedLoadWorldFile(FALSE),
+    bHasReadICCMetadata(FALSE)
 {
-    fpImage = NULL;
-    hPNG = NULL;
-    psPNGInfo = NULL;
-    pabyBuffer = NULL;
-    nBufferStartLine = 0;
-    nBufferLines = 0;
-    nLastLineRead = -1;
-    poColorTable = NULL;
-    nBitDepth = 8;
-
-    bGeoTransformValid = FALSE;
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
@@ -449,9 +450,7 @@ PNGDataset::PNGDataset()
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
 
-    bHasTriedLoadWorldFile = FALSE;
-    bHasReadXMPMetadata = FALSE;
-    bHasReadICCMetadata = FALSE;
+    memset(&sSetJmpContext, 0, sizeof(sSetJmpContext));
 }
 
 /************************************************************************/
@@ -501,6 +500,12 @@ CPLErr PNGDataset::IRasterIO( GDALRWFlag eRWFlag,
                               GDALRasterIOExtraArg* psExtraArg )
 
 {
+    // Coverity says that we cannot pass a nullptr to IRasterIO.
+    if (panBandMap == NULL)
+    {
+      return CE_Failure;
+    }
+
     if((eRWFlag == GF_Read) &&
        (nBandCount == nBands) &&
        (nXOff == 0) && (nYOff == 0) &&
@@ -511,29 +516,26 @@ CPLErr PNGDataset::IRasterIO( GDALRWFlag eRWFlag,
        (pData != NULL) &&
        (panBandMap != NULL) && IsFullBandMap(panBandMap, nBands))
     {
-        int y;
-        CPLErr tmpError;
-        int x;
 
         // Pixel interleaved case
         if( nBandSpace == 1 )
         {
-            for(y = 0; y < nYSize; ++y)
+            for(int y = 0; y < nYSize; ++y)
             {
-                tmpError = LoadScanline(y);
+                CPLErr tmpError = LoadScanline(y);
                 if(tmpError != CE_None) return tmpError;
-                GByte* pabyScanline = pabyBuffer 
+                GByte* pabyScanline = pabyBuffer
                     + (y - nBufferStartLine) * nBands * nXSize;
                 if( nPixelSpace == nBandSpace * nBandCount )
                 {
-                    memcpy(&(((GByte*)pData)[(y*nLineSpace)]),
+                    memcpy(&(reinterpret_cast<GByte*>( pData )[(y*nLineSpace)]),
                            pabyScanline, nBandCount * nXSize);
                 }
                 else
                 {
-                    for(x = 0; x < nXSize; ++x)
+                    for(int x = 0; x < nXSize; ++x)
                     {
-                        memcpy(&(((GByte*)pData)[(y*nLineSpace) + (x*nPixelSpace)]), 
+                        memcpy(&(reinterpret_cast<GByte*>(pData)[(y*nLineSpace) + (x*nPixelSpace)]),
                                (const GByte*)&(pabyScanline[x* nBandCount]), nBandCount);
                     }
                 }
@@ -541,16 +543,16 @@ CPLErr PNGDataset::IRasterIO( GDALRWFlag eRWFlag,
         }
         else
         {
-            for(y = 0; y < nYSize; ++y)
+            for(int y = 0; y < nYSize; ++y)
             {
-                tmpError = LoadScanline(y);
+                CPLErr tmpError = LoadScanline(y);
                 if(tmpError != CE_None) return tmpError;
-                GByte* pabyScanline = pabyBuffer 
+                GByte* pabyScanline = pabyBuffer
                     + (y - nBufferStartLine) * nBands * nXSize;
-                for(x = 0; x < nXSize; ++x)
+                for(int x = 0; x < nXSize; ++x)
                 {
                     for(int iBand=0;iBand<nBands;iBand++)
-                        ((GByte*)pData)[(y*nLineSpace) + (x*nPixelSpace) + iBand * nBandSpace] = pabyScanline[x*nBands+iBand];
+                         reinterpret_cast<GByte *>( pData )[(y*nLineSpace) + (x*nPixelSpace) + iBand * nBandSpace] = pabyScanline[x*nBands+iBand];
                 }
             }
         }
@@ -559,8 +561,8 @@ CPLErr PNGDataset::IRasterIO( GDALRWFlag eRWFlag,
     }
 
     return GDALPamDataset::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                                     pData, nBufXSize, nBufYSize, eBufType, 
-                                     nBandCount, panBandMap, 
+                                     pData, nBufXSize, nBufYSize, eBufType,
+                                     nBandCount, panBandMap,
                                      nPixelSpace, nLineSpace, nBandSpace,
                                      psExtraArg);
 }
@@ -579,8 +581,8 @@ CPLErr PNGDataset::GetGeoTransform( double * padfTransform )
         memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
         return CE_None;
     }
-    else
-        return GDALPamDataset::GetGeoTransform( padfTransform );
+
+    return GDALPamDataset::GetGeoTransform( padfTransform );
 }
 
 /************************************************************************/
@@ -634,6 +636,20 @@ void PNGDataset::Restart()
 }
 
 /************************************************************************/
+/*                        safe_png_read_image()                         */
+/************************************************************************/
+
+static bool safe_png_read_image(png_structp hPNG,
+                                png_bytep *png_rows,
+                                jmp_buf     sSetJmpContext)
+{
+    if( setjmp( sSetJmpContext ) != 0 )
+        return false;
+    png_read_image( hPNG, png_rows );
+    return true;
+}
+
+/************************************************************************/
 /*                        LoadInterlacedChunk()                         */
 /************************************************************************/
 
@@ -650,11 +666,10 @@ CPLErr PNGDataset::LoadInterlacedChunk( int iLine )
 /* -------------------------------------------------------------------- */
 /*      Was is the biggest chunk we can safely operate on?              */
 /* -------------------------------------------------------------------- */
-#define MAX_PNG_CHUNK_BYTES 100000000
+    static const int MAX_PNG_CHUNK_BYTES = 100000000;
 
-    int         nMaxChunkLines = 
-        MAX(1,MAX_PNG_CHUNK_BYTES / (nPixelOffset * GetRasterXSize()));
-    png_bytep  *png_rows;
+    int nMaxChunkLines =
+        std::max(1, MAX_PNG_CHUNK_BYTES / (nPixelOffset * GetRasterXSize()));
 
     if( nMaxChunkLines > GetRasterYSize() )
         nMaxChunkLines = GetRasterYSize();
@@ -671,20 +686,16 @@ CPLErr PNGDataset::LoadInterlacedChunk( int iLine )
 
     if( pabyBuffer == NULL )
     {
-        pabyBuffer = (GByte *) 
-            VSIMalloc(nPixelOffset*GetRasterXSize()*nMaxChunkLines);
-        
+      pabyBuffer = reinterpret_cast<GByte *>(
+          VSI_MALLOC_VERBOSE(nPixelOffset*GetRasterXSize()*nMaxChunkLines) );
+
         if( pabyBuffer == NULL )
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory, 
-                      "Unable to allocate buffer for whole interlaced PNG"
-                      "image of size %dx%d.\n", 
-                      GetRasterXSize(), GetRasterYSize() );
             return CE_Failure;
         }
 #ifdef notdef
         if( nMaxChunkLines < GetRasterYSize() )
-            CPLDebug( "PNG", 
+            CPLDebug( "PNG",
                       "Interlaced file being handled in %d line chunks.\n"
                       "Performance is likely to be quite poor.",
                       nMaxChunkLines );
@@ -698,8 +709,6 @@ CPLErr PNGDataset::LoadInterlacedChunk( int iLine )
     if( nLastLineRead != -1 )
     {
         Restart();
-        if( setjmp( sSetJmpContext ) != 0 )
-            return CE_Failure;
     }
 
 /* -------------------------------------------------------------------- */
@@ -707,23 +716,27 @@ CPLErr PNGDataset::LoadInterlacedChunk( int iLine )
 /*      row in the image, but use our dummy line for rows not in the    */
 /*      target window.                                                  */
 /* -------------------------------------------------------------------- */
-    int        i;
-    png_bytep  dummy_row = (png_bytep)CPLMalloc(nPixelOffset*GetRasterXSize());
-    png_rows = (png_bytep*)CPLMalloc(sizeof(png_bytep) * GetRasterYSize());
+    png_bytep dummy_row = reinterpret_cast<png_bytep>(
+        CPLMalloc(nPixelOffset*GetRasterXSize()) );
+    png_bytep *png_rows
+        = reinterpret_cast<png_bytep *>(
+            CPLMalloc(sizeof(png_bytep) * GetRasterYSize()) );
 
-    for( i = 0; i < GetRasterYSize(); i++ )
+    for( int i = 0; i < GetRasterYSize(); i++ )
     {
         if( i >= nBufferStartLine && i < nBufferStartLine + nBufferLines )
-            png_rows[i] = pabyBuffer 
+            png_rows[i] = pabyBuffer
                 + (i-nBufferStartLine) * nPixelOffset * GetRasterXSize();
         else
             png_rows[i] = dummy_row;
     }
 
-    png_read_image( hPNG, png_rows );
+    bool bRet = safe_png_read_image( hPNG, png_rows, sSetJmpContext );
 
     CPLFree( png_rows );
     CPLFree( dummy_row );
+    if( !bRet )
+        return CE_Failure;
 
     nLastLineRead = nBufferStartLine + nBufferLines - 1;
 
@@ -731,27 +744,36 @@ CPLErr PNGDataset::LoadInterlacedChunk( int iLine )
 }
 
 /************************************************************************/
+/*                        safe_png_read_rows()                          */
+/************************************************************************/
+
+static bool safe_png_read_rows(png_structp hPNG,
+                                png_bytep  row,
+                                jmp_buf    sSetJmpContext)
+{
+    if( setjmp( sSetJmpContext ) != 0 )
+        return false;
+    png_read_rows( hPNG, &row, NULL, 1 );
+    return true;
+}
+/************************************************************************/
 /*                            LoadScanline()                            */
 /************************************************************************/
 
 CPLErr PNGDataset::LoadScanline( int nLine )
 
 {
-    int   nPixelOffset;
-
     CPLAssert( nLine >= 0 && nLine < GetRasterYSize() );
 
     if( nLine >= nBufferStartLine && nLine < nBufferStartLine + nBufferLines)
         return CE_None;
 
+    int nPixelOffset;
     if( nBitDepth == 16 )
         nPixelOffset = 2 * GetRasterCount();
     else
         nPixelOffset = 1 * GetRasterCount();
 
-    if( setjmp( sSetJmpContext ) != 0 )
-        return CE_Failure;
-
 /* -------------------------------------------------------------------- */
 /*      If the file is interlaced, we will load the entire image        */
 /*      into memory using the high level API.                           */
@@ -763,7 +785,8 @@ CPLErr PNGDataset::LoadScanline( int nLine )
 /*      Ensure we have space allocated for one scanline                 */
 /* -------------------------------------------------------------------- */
     if( pabyBuffer == NULL )
-        pabyBuffer = (GByte *) CPLMalloc(nPixelOffset * GetRasterXSize());
+        pabyBuffer = reinterpret_cast<GByte *>(
+            CPLMalloc(nPixelOffset * GetRasterXSize() ) );
 
 /* -------------------------------------------------------------------- */
 /*      Otherwise we just try to read the requested row.  Do we need    */
@@ -772,19 +795,16 @@ CPLErr PNGDataset::LoadScanline( int nLine )
     if( nLine <= nLastLineRead )
     {
         Restart();
-        if( setjmp( sSetJmpContext ) != 0 )
-            return CE_Failure;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Read till we get the desired row.                               */
 /* -------------------------------------------------------------------- */
-    png_bytep      row;
-
-    row = pabyBuffer;
+    png_bytep row = pabyBuffer;
     while( nLine > nLastLineRead )
     {
-        png_read_rows( hPNG, &row, NULL, 1 );
+        if( !safe_png_read_rows( hPNG, row, sSetJmpContext ) )
+            return CE_Failure;
         nLastLineRead++;
     }
 
@@ -807,7 +827,7 @@ CPLErr PNGDataset::LoadScanline( int nLine )
 /*                          CollectMetadata()                           */
 /*                                                                      */
 /*      We normally do this after reading up to the image, but be       */
-/*      forwarned ... we can missing text chunks this way.              */
+/*      forewarned ... we can missing text chunks this way.             */
 /*                                                                      */
 /*      We turn each PNG text chunk into one metadata item.  It         */
 /*      might be nice to preserve language information though we        */
@@ -817,25 +837,24 @@ CPLErr PNGDataset::LoadScanline( int nLine )
 void PNGDataset::CollectMetadata()
 
 {
-    int   nTextCount;
-    png_textp text_ptr;
-
     if( nBitDepth < 8 )
     {
         for( int iBand = 0; iBand < nBands; iBand++ )
         {
-            GetRasterBand(iBand+1)->SetMetadataItem( 
+            GetRasterBand(iBand+1)->SetMetadataItem(
                 "NBITS", CPLString().Printf( "%d", nBitDepth ),
                 "IMAGE_STRUCTURE" );
         }
     }
 
+    int nTextCount;
+    png_textp text_ptr;
     if( png_get_text( hPNG, psPNGInfo, &text_ptr, &nTextCount ) == 0 )
         return;
 
     for( int iText = 0; iText < nTextCount; iText++ )
     {
-        char	*pszTag = CPLStrdup(text_ptr[iText].key);
+        char *pszTag = CPLStrdup(text_ptr[iText].key);
 
         for( int i = 0; pszTag[i] != '\0'; i++ )
         {
@@ -852,7 +871,7 @@ void PNGDataset::CollectMetadata()
 /*                       CollectXMPMetadata()                           */
 /************************************************************************/
 
-/* See §2.1.5 of http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/XMPSpecificationPart3.pdf */
+// See §2.1.5 of http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/XMPSpecificationPart3.pdf
 
 void PNGDataset::CollectXMPMetadata()
 
@@ -861,17 +880,15 @@ void PNGDataset::CollectXMPMetadata()
         return;
 
     /* Save current position to avoid disturbing PNG stream decoding */
-    vsi_l_offset nCurOffset = VSIFTellL(fpImage);
+    const vsi_l_offset nCurOffset = VSIFTellL(fpImage);
 
     vsi_l_offset nOffset = 8;
     VSIFSeekL( fpImage, nOffset, SEEK_SET );
 
     /* Loop over chunks */
-    while(TRUE)
+    while( true )
     {
         int nLength;
-        char pszChunkType[5];
-        int nCRC;
 
         if (VSIFReadL( &nLength, 4, 1, fpImage ) != 1)
             break;
@@ -879,6 +896,8 @@ void PNGDataset::CollectXMPMetadata()
         CPL_MSBPTR32(&nLength);
         if (nLength <= 0)
             break;
+
+        char pszChunkType[5];
         if (VSIFReadL( pszChunkType, 4, 1, fpImage ) != 1)
             break;
         nOffset += 4;
@@ -886,7 +905,8 @@ void PNGDataset::CollectXMPMetadata()
 
         if (strcmp(pszChunkType, "iTXt") == 0 && nLength > 22)
         {
-            char* pszContent = (char*)VSIMalloc(nLength + 1);
+            char* pszContent = reinterpret_cast<char *>(
+                VSIMalloc(nLength + 1) );
             if (pszContent == NULL)
                 break;
             if (VSIFReadL( pszContent, nLength, 1, fpImage) != 1)
@@ -901,9 +921,7 @@ void PNGDataset::CollectXMPMetadata()
                 /* Avoid setting the PAM dirty bit just for that */
                 int nOldPamFlags = nPamFlags;
 
-                char *apszMDList[2];
-                apszMDList[0] = pszContent + 22;
-                apszMDList[1] = NULL;
+                char *apszMDList[2] = { pszContent + 22, NULL };
                 SetMetadata(apszMDList, "xml:XMP");
 
                 nPamFlags = nOldPamFlags;
@@ -924,6 +942,7 @@ void PNGDataset::CollectXMPMetadata()
         }
 
         nOffset += 4;
+        int nCRC;
         if (VSIFReadL( &nCRC, 4, 1, fpImage ) != 1)
             break;
     }
@@ -951,9 +970,6 @@ void PNGDataset::LoadICCProfile()
     png_charp pProfileData;
 #endif
     int nCompressionType;
-    int nsRGBIntent;
-    double dfGamma;
-    bool bGammaAvailable = false;
 
     /* Avoid setting the PAM dirty bit just for that */
     int nOldPamFlags = nPamFlags;
@@ -962,7 +978,8 @@ void PNGDataset::LoadICCProfile()
        &nCompressionType, &pProfileData, &nProfileLength) != 0)
     {
         /* Escape the profile */
-        char *pszBase64Profile = CPLBase64Encode(nProfileLength, (const GByte*)pProfileData);
+        char *pszBase64Profile = CPLBase64Encode(
+            static_cast<int>(nProfileLength), reinterpret_cast<const GByte *>( pProfileData ) );
 
         /* Set ICC profile metadata */
         SetMetadataItem( "SOURCE_ICC_PROFILE", pszBase64Profile, "COLOR_PROFILE" );
@@ -975,6 +992,7 @@ void PNGDataset::LoadICCProfile()
         return;
     }
 
+    int nsRGBIntent;
     if (png_get_sRGB(hPNG, psPNGInfo, &nsRGBIntent) != 0)
     {
         SetMetadataItem( "SOURCE_ICC_PROFILE_NAME", "sRGB", "COLOR_PROFILE" );
@@ -984,13 +1002,15 @@ void PNGDataset::LoadICCProfile()
         return;
     }
 
+    double dfGamma;
+    bool bGammaAvailable = false;
     if (png_get_valid(hPNG, psPNGInfo, PNG_INFO_gAMA))
     {
         bGammaAvailable = true;
 
         png_get_gAMA(hPNG,psPNGInfo, &dfGamma);
 
-        SetMetadataItem( "PNG_GAMMA", 
+        SetMetadataItem( "PNG_GAMMA",
             CPLString().Printf( "%.9f", dfGamma ) , "COLOR_PROFILE" );
     }
 
@@ -1007,14 +1027,14 @@ void PNGDataset::LoadICCProfile()
                     &dfaCHR[4], &dfaCHR[5]);
 
         // Set all the colorimetric metadata.
-        SetMetadataItem( "SOURCE_PRIMARIES_RED", 
+        SetMetadataItem( "SOURCE_PRIMARIES_RED",
             CPLString().Printf( "%.9f, %.9f, 1.0", dfaCHR[0], dfaCHR[1] ) , "COLOR_PROFILE" );
-        SetMetadataItem( "SOURCE_PRIMARIES_GREEN", 
+        SetMetadataItem( "SOURCE_PRIMARIES_GREEN",
             CPLString().Printf( "%.9f, %.9f, 1.0", dfaCHR[2], dfaCHR[3] ) , "COLOR_PROFILE" );
-        SetMetadataItem( "SOURCE_PRIMARIES_BLUE", 
+        SetMetadataItem( "SOURCE_PRIMARIES_BLUE",
             CPLString().Printf( "%.9f, %.9f, 1.0", dfaCHR[4], dfaCHR[5] ) , "COLOR_PROFILE" );
 
-        SetMetadataItem( "SOURCE_WHITEPOINT", 
+        SetMetadataItem( "SOURCE_WHITEPOINT",
             CPLString().Printf( "%.9f, %.9f, 1.0", dfaWhitepoint[0], dfaWhitepoint[1] ) , "COLOR_PROFILE" );
 
     }
@@ -1072,7 +1092,7 @@ int PNGDataset::Identify( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->nHeaderBytes < 4 )
         return FALSE;
 
-    if( png_sig_cmp(poOpenInfo->pabyHeader, (png_size_t)0, 
+    if( png_sig_cmp(poOpenInfo->pabyHeader, static_cast<png_size_t>( 0 ),
                     poOpenInfo->nHeaderBytes) != 0 )
         return FALSE;
 
@@ -1091,7 +1111,7 @@ GDALDataset *PNGDataset::Open( GDALOpenInfo * poOpenInfo )
 
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The PNG driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
@@ -1100,26 +1120,24 @@ GDALDataset *PNGDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    PNGDataset 	*poDS;
-
-    poDS = new PNGDataset();
+    PNGDataset 	*poDS = new PNGDataset();
 
     poDS->fpImage = poOpenInfo->fpL;
     poOpenInfo->fpL = NULL;
     poDS->eAccess = poOpenInfo->eAccess;
-    
-    poDS->hPNG = png_create_read_struct( PNG_LIBPNG_VER_STRING, poDS, 
+
+    poDS->hPNG = png_create_read_struct( PNG_LIBPNG_VER_STRING, poDS,
                                          NULL, NULL );
     if (poDS->hPNG == NULL)
     {
 #if (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR >= 2) || PNG_LIBPNG_VER_MAJOR > 1
-        int version = png_access_version_number();
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        int version = static_cast<int>(png_access_version_number());
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The PNG driver failed to access libpng with version '%s',"
                   " library is actually version '%d'.\n",
                   PNG_LIBPNG_VER_STRING, version);
 #else
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The PNG driver failed to in png_create_read_struct().\n"
                   "This may be due to version compatibility problems." );
 #endif
@@ -1151,17 +1169,17 @@ GDALDataset *PNGDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Capture some information from the file that is of interest.     */
 /* -------------------------------------------------------------------- */
-    poDS->nRasterXSize = png_get_image_width( poDS->hPNG, poDS->psPNGInfo);
-    poDS->nRasterYSize = png_get_image_height( poDS->hPNG,poDS->psPNGInfo);
+    poDS->nRasterXSize = static_cast<int>(png_get_image_width( poDS->hPNG, poDS->psPNGInfo));
+    poDS->nRasterYSize = static_cast<int>(png_get_image_height( poDS->hPNG,poDS->psPNGInfo));
 
     poDS->nBands = png_get_channels( poDS->hPNG, poDS->psPNGInfo );
     poDS->nBitDepth = png_get_bit_depth( poDS->hPNG, poDS->psPNGInfo );
-    poDS->bInterlaced = png_get_interlace_type( poDS->hPNG, poDS->psPNGInfo ) 
+    poDS->bInterlaced = png_get_interlace_type( poDS->hPNG, poDS->psPNGInfo )
         != PNG_INTERLACE_NONE;
 
     poDS->nColorType = png_get_color_type( poDS->hPNG, poDS->psPNGInfo );
 
-    if( poDS->nColorType == PNG_COLOR_TYPE_PALETTE 
+    if( poDS->nColorType == PNG_COLOR_TYPE_PALETTE
         && poDS->nBands > 1 )
     {
         CPLDebug( "GDAL", "PNG Driver got %d from png_get_channels(),\n"
@@ -1170,7 +1188,7 @@ GDALDataset *PNGDataset::Open( GDALOpenInfo * poOpenInfo )
                   poDS->nBands );
         poDS->nBands = 1;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      We want to treat 1,2,4 bit images as eight bit.  This call      */
 /*      causes libpng to unpack the image.                              */
@@ -1191,22 +1209,22 @@ GDALDataset *PNGDataset::Open( GDALOpenInfo * poOpenInfo )
     if( poDS->nColorType == PNG_COLOR_TYPE_PALETTE )
     {
         png_color *pasPNGPalette;
-        int	nColorCount;
-        GDALColorEntry oEntry;
-        unsigned char *trans = NULL;
-        png_color_16 *trans_values = NULL;
-        int	num_trans = 0;
-        int	nNoDataIndex = -1;
+        int nColorCount;
 
-        if( png_get_PLTE( poDS->hPNG, poDS->psPNGInfo, 
+        if( png_get_PLTE( poDS->hPNG, poDS->psPNGInfo,
                           &pasPNGPalette, &nColorCount ) == 0 )
             nColorCount = 0;
 
-        png_get_tRNS( poDS->hPNG, poDS->psPNGInfo, 
+        unsigned char *trans = NULL;
+        png_color_16 *trans_values = NULL;
+        int num_trans = 0;
+        png_get_tRNS( poDS->hPNG, poDS->psPNGInfo,
                       &trans, &num_trans, &trans_values );
 
         poDS->poColorTable = new GDALColorTable();
 
+        GDALColorEntry oEntry;
+        int nNoDataIndex = -1;
         for( int iColor = nColorCount - 1; iColor >= 0; iColor-- )
         {
             oEntry.c1 = pasPNGPalette[iColor].red;
@@ -1249,8 +1267,8 @@ GDALDataset *PNGDataset::Open( GDALOpenInfo * poOpenInfo )
         unsigned char *trans;
         int num_trans;
 
-        if( png_get_tRNS( poDS->hPNG, poDS->psPNGInfo, 
-                          &trans, &num_trans, &trans_values ) != 0 
+        if( png_get_tRNS( poDS->hPNG, poDS->psPNGInfo,
+                          &trans, &num_trans, &trans_values ) != 0
             && trans_values != NULL )
         {
             poDS->GetRasterBand(1)->SetNoDataValue(trans_values->gray);
@@ -1260,21 +1278,21 @@ GDALDataset *PNGDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Check for nodata color for RGB images.                          */
 /* -------------------------------------------------------------------- */
-    if( poDS->nColorType == PNG_COLOR_TYPE_RGB ) 
+    if( poDS->nColorType == PNG_COLOR_TYPE_RGB )
     {
         png_color_16 *trans_values = NULL;
         unsigned char *trans;
         int num_trans;
 
-        if( png_get_tRNS( poDS->hPNG, poDS->psPNGInfo, 
-                          &trans, &num_trans, &trans_values ) != 0 
+        if( png_get_tRNS( poDS->hPNG, poDS->psPNGInfo,
+                          &trans, &num_trans, &trans_values ) != 0
             && trans_values != NULL )
         {
             CPLString oNDValue;
 
-            oNDValue.Printf( "%d %d %d", 
-                    trans_values->red, 
-                    trans_values->green, 
+            oNDValue.Printf( "%d %d %d",
+                    trans_values->red,
+                    trans_values->green,
                     trans_values->blue );
             poDS->SetMetadataItem( "NODATA_VALUES", oNDValue.c_str() );
 
@@ -1370,14 +1388,15 @@ char **PNGDataset::GetFileList()
 #endif
 
 #ifdef HAVE_ITXT_SUPPORT
-static int IsASCII(const char* pszStr)
+static bool IsASCII(const char* pszStr)
 {
     for(int i=0;pszStr[i]!='\0';i++)
     {
-        if( ((GByte*)pszStr)[i] >= 128 )
-            return FALSE;
+        if( reinterpret_cast<GByte *>(
+            const_cast<char *>( pszStr ) )[i] >= 128 )
+            return false;
     }
-    return TRUE;
+    return true;
 }
 #endif
 
@@ -1390,7 +1409,7 @@ void PNGDataset::WriteMetadataAsText(png_structp hPNG, png_infop psPNGInfo,
     sText.key = (png_charp) pszKey;
     sText.text = (png_charp) pszValue;
 #ifdef HAVE_ITXT_SUPPORT
-    // UTF-8 values should be written in iTXt, whereas TEXT should be LATIN-1 
+    // UTF-8 values should be written in iTXt, whereas TEXT should be LATIN-1
     if( !IsASCII(pszValue) && CPLIsUTF8(pszValue, -1) )
         sText.compression = PNG_ITXT_COMPRESSION_NONE;
 #endif
@@ -1402,35 +1421,32 @@ void PNGDataset::WriteMetadataAsText(png_structp hPNG, png_infop psPNGInfo,
 /************************************************************************/
 
 GDALDataset *
-PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
-               int bStrict, char ** papszOptions, 
+PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
+               int bStrict, char ** papszOptions,
                GDALProgressFunc pfnProgress, void * pProgressData )
 
 {
-    int  nBands = poSrcDS->GetRasterCount();
-    int  nXSize = poSrcDS->GetRasterXSize();
-    int  nYSize = poSrcDS->GetRasterYSize();
-
 /* -------------------------------------------------------------------- */
 /*      Some some rudimentary checks                                    */
 /* -------------------------------------------------------------------- */
+    const int nBands = poSrcDS->GetRasterCount();
     if( nBands != 1 && nBands != 2 && nBands != 3 && nBands != 4 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "PNG driver doesn't support %d bands.  Must be 1 (grey),\n"
-                  "2 (grey+alpha), 3 (rgb) or 4 (rgba) bands.\n", 
+                  "2 (grey+alpha), 3 (rgb) or 4 (rgba) bands.\n",
                   nBands );
 
         return NULL;
     }
 
-    if( poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte 
+    if( poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte
         && poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_UInt16 )
     {
-        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, 
+        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
                   "PNG driver doesn't support data type %s. "
-                  "Only eight bit (Byte) and sixteen bit (UInt16) bands supported. %s\n", 
-                  GDALGetDataTypeName( 
+                  "Only eight bit (Byte) and sixteen bit (UInt16) bands supported. %s\n",
+                  GDALGetDataTypeName(
                       poSrcDS->GetRasterBand(1)->GetRasterDataType()),
                   (bStrict) ? "" : "Defaulting to Byte" );
 
@@ -1439,10 +1455,37 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     }
 
 /* -------------------------------------------------------------------- */
+/*      Create the dataset.                                             */
+/* -------------------------------------------------------------------- */
+    VSILFILE *fpImage = VSIFOpenL( pszFilename, "wb" );
+    if( fpImage == NULL )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Unable to create png file %s.\n",
+                  pszFilename );
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Initialize PNG access to the file.                              */
+/* -------------------------------------------------------------------- */
+    jmp_buf     sSetJmpContext;
+
+    png_structp hPNG = png_create_write_struct(
+        PNG_LIBPNG_VER_STRING, &sSetJmpContext, png_gdal_error, png_gdal_warning );
+    png_infop  psPNGInfo = png_create_info_struct( hPNG );
+
+    if( setjmp( sSetJmpContext ) != 0 )
+    {
+        VSIFCloseL( fpImage );
+        png_destroy_write_struct( &hPNG, &psPNGInfo );
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Setup some parameters.                                          */
 /* -------------------------------------------------------------------- */
-    int  nColorType=0, nBitDepth;
-    GDALDataType eType;
+    int  nColorType=0;
 
     if( nBands == 1 && poSrcDS->GetRasterBand(1)->GetColorTable() == NULL )
         nColorType = PNG_COLOR_TYPE_GRAY;
@@ -1455,53 +1498,48 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     else if( nBands == 4 )
         nColorType = PNG_COLOR_TYPE_RGB_ALPHA;
 
+    int nBitDepth;
+    GDALDataType eType;
     if( poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_UInt16 )
     {
         eType = GDT_Byte;
         nBitDepth = 8;
+        if( nBands == 1 )
+        {
+            const char* pszNbits = poSrcDS->GetRasterBand(1)->GetMetadataItem(
+                                                    "NBITS", "IMAGE_STRUCTURE");
+            if( pszNbits != NULL )
+            {
+                nBitDepth = atoi(pszNbits);
+                if( !(nBitDepth == 1 || nBitDepth == 2 || nBitDepth == 4) )
+                    nBitDepth = 8;
+            }
+        }
     }
-    else 
+    else
     {
         eType = GDT_UInt16;
         nBitDepth = 16;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Create the dataset.                                             */
-/* -------------------------------------------------------------------- */
-    VSILFILE	*fpImage;
-
-    fpImage = VSIFOpenL( pszFilename, "wb" );
-    if( fpImage == NULL )
+    const char* pszNbits = CSLFetchNameValue(papszOptions, "NBITS");
+    if( eType == GDT_Byte && pszNbits != NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Unable to create png file %s.\n", 
-                  pszFilename );
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Initialize PNG access to the file.                              */
-/* -------------------------------------------------------------------- */
-    png_structp hPNG;
-    png_infop   psPNGInfo;
-    
-    jmp_buf     sSetJmpContext;
-    hPNG = png_create_write_struct( PNG_LIBPNG_VER_STRING, 
-                                    &sSetJmpContext, png_gdal_error, png_gdal_warning );
-    psPNGInfo = png_create_info_struct( hPNG );
-
-    if( setjmp( sSetJmpContext ) != 0 )
-    {
-        VSIFCloseL( fpImage );
-        png_destroy_write_struct( &hPNG, &psPNGInfo );
-        return NULL;
+        nBitDepth = atoi(pszNbits);
+        if( !(nBitDepth == 1 || nBitDepth == 2 || nBitDepth == 4 || nBitDepth == 8) )
+        {
+            CPLError(CE_Warning, CPLE_NotSupported, "Invalid bit depth. Using 8");
+            nBitDepth = 8;
+        }
     }
 
     png_set_write_fn( hPNG, fpImage, png_vsi_write_data, png_vsi_flush );
 
-    png_set_IHDR( hPNG, psPNGInfo, nXSize, nYSize, 
-                  nBitDepth, nColorType, PNG_INTERLACE_NONE, 
+    const int nXSize = poSrcDS->GetRasterXSize();
+    const int nYSize = poSrcDS->GetRasterYSize();
+
+    png_set_IHDR( hPNG, psPNGInfo, nXSize, nYSize,
+                  nBitDepth, nColorType, PNG_INTERLACE_NONE,
                   PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE );
 
 /* -------------------------------------------------------------------- */
@@ -1511,7 +1549,7 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
     if( pszLevel )
     {
-        int nLevel = atoi(pszLevel);
+        const int nLevel = atoi(pszLevel);
         if( nLevel < 1 || nLevel > 9 )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -1533,10 +1571,9 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     // Gray nodata.
     if( nColorType == PNG_COLOR_TYPE_GRAY )
     {
-       int		bHaveNoData = FALSE;
-       double	dfNoDataValue = -1;
-
-       dfNoDataValue = poSrcDS->GetRasterBand(1)->GetNoDataValue( &bHaveNoData );
+       int bHaveNoData = FALSE;
+       const double dfNoDataValue
+           = poSrcDS->GetRasterBand(1)->GetNoDataValue( &bHaveNoData );
 
        if ( bHaveNoData && dfNoDataValue >= 0 && dfNoDataValue < 65536 )
        {
@@ -1553,7 +1590,7 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
        {
            char **papszValues = CSLTokenizeString(
                poSrcDS->GetMetadataItem( "NODATA_VALUES" ) );
-           
+
            if( CSLCount(papszValues) >= 3 )
            {
                sTRNSColor.red   = (png_uint_16) atoi(papszValues[0]);
@@ -1567,29 +1604,30 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
        // Otherwise, get the nodata value from the bands.
        else
        {
-          int	  bHaveNoDataRed = FALSE;
-          int	  bHaveNoDataGreen = FALSE;
-          int	  bHaveNoDataBlue = FALSE;
-          double dfNoDataValueRed = -1;
-          double dfNoDataValueGreen = -1;
-          double dfNoDataValueBlue = -1;
+          int bHaveNoDataRed = FALSE;
+          const double dfNoDataValueRed
+              = poSrcDS->GetRasterBand(1)->GetNoDataValue( &bHaveNoDataRed );
 
-          dfNoDataValueRed  = poSrcDS->GetRasterBand(1)->GetNoDataValue( &bHaveNoDataRed );
-          dfNoDataValueGreen= poSrcDS->GetRasterBand(2)->GetNoDataValue( &bHaveNoDataGreen );
-          dfNoDataValueBlue = poSrcDS->GetRasterBand(3)->GetNoDataValue( &bHaveNoDataBlue );
+          int bHaveNoDataGreen = FALSE;
+          const double dfNoDataValueGreen
+              = poSrcDS->GetRasterBand(2)->GetNoDataValue( &bHaveNoDataGreen );
+
+          int bHaveNoDataBlue = FALSE;
+          const double dfNoDataValueBlue
+              = poSrcDS->GetRasterBand(3)->GetNoDataValue( &bHaveNoDataBlue );
 
           if ( ( bHaveNoDataRed && dfNoDataValueRed >= 0 && dfNoDataValueRed < 65536 ) &&
                ( bHaveNoDataGreen && dfNoDataValueGreen >= 0 && dfNoDataValueGreen < 65536 ) &&
                ( bHaveNoDataBlue && dfNoDataValueBlue >= 0 && dfNoDataValueBlue < 65536 ) )
           {
-             sTRNSColor.red   = (png_uint_16) dfNoDataValueRed;
-             sTRNSColor.green = (png_uint_16) dfNoDataValueGreen;
-             sTRNSColor.blue  = (png_uint_16) dfNoDataValueBlue;
+             sTRNSColor.red   = static_cast<png_uint_16>( dfNoDataValueRed );
+             sTRNSColor.green = static_cast<png_uint_16>( dfNoDataValueGreen );
+             sTRNSColor.blue  = static_cast<png_uint_16>( dfNoDataValueBlue );
              png_set_tRNS( hPNG, psPNGInfo, NULL, 0, &sTRNSColor );
           }
        }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Copy colour profile data                                        */
 /* -------------------------------------------------------------------- */
@@ -1611,7 +1649,8 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     if (pszICCProfile != NULL)
     {
         char *pEmbedBuffer = CPLStrdup(pszICCProfile);
-        png_uint_32 nEmbedLen = CPLBase64DecodeInPlace((GByte*)pEmbedBuffer);
+        png_uint_32 nEmbedLen
+            = CPLBase64DecodeInPlace(reinterpret_cast<GByte *>( pEmbedBuffer ) );
         const char* pszLocalICCProfileName = (pszICCProfileName!=NULL)?pszICCProfileName:"ICC Profile";
 
         png_set_iCCP(hPNG, psPNGInfo,
@@ -1663,13 +1702,13 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             double faColour[8];
             char** apapszTokenList[4];
 
-            apapszTokenList[0] = CSLTokenizeString2( pszWhitepoint, ",", 
+            apapszTokenList[0] = CSLTokenizeString2( pszWhitepoint, ",",
                 CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
-            apapszTokenList[1] = CSLTokenizeString2( pszPrimariesRed, ",", 
+            apapszTokenList[1] = CSLTokenizeString2( pszPrimariesRed, ",",
                 CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
-            apapszTokenList[2] = CSLTokenizeString2( pszPrimariesGreen, ",", 
+            apapszTokenList[2] = CSLTokenizeString2( pszPrimariesGreen, ",",
                 CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
-            apapszTokenList[3] = CSLTokenizeString2( pszPrimariesBlue, ",", 
+            apapszTokenList[3] = CSLTokenizeString2( pszPrimariesBlue, ",",
                 CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
 
             if ((CSLCount( apapszTokenList[0] ) == 3) &&
@@ -1681,7 +1720,7 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                 {
                     for( int j = 0; j < 3; j++ )
                     {
-                        double v = CPLAtof(apapszTokenList[i][j]);
+                        const double v = CPLAtof(apapszTokenList[i][j]);
 
                         if (j == 2)
                         {
@@ -1703,10 +1742,10 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
                 if (bOk)
                 {
-                    png_set_cHRM(hPNG, psPNGInfo, 
-                        faColour[0], faColour[1], 
-                        faColour[2], faColour[3], 
-                        faColour[4], faColour[5], 
+                    png_set_cHRM(hPNG, psPNGInfo,
+                        faColour[0], faColour[1],
+                        faColour[2], faColour[3],
+                        faColour[4], faColour[5],
                         faColour[6], faColour[7]);
 
                 }
@@ -1719,43 +1758,45 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         }
 
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Write palette if there is one.  Technically, I think it is      */
 /*      possible to write 16bit palettes for PNG, but we will omit      */
 /*      this for now.                                                   */
 /* -------------------------------------------------------------------- */
-    png_color	*pasPNGColors = NULL;
-    unsigned char	*pabyAlpha = NULL;
-
     if( nColorType == PNG_COLOR_TYPE_PALETTE )
     {
-        GDALColorTable	*poCT;
-        GDALColorEntry  sEntry;
-        int		iColor, bFoundTrans = FALSE;
-        int		bHaveNoData = FALSE;
-        double	dfNoDataValue = -1;
+        int bHaveNoData = FALSE;
+        double dfNoDataValue
+            = poSrcDS->GetRasterBand(1)->GetNoDataValue( &bHaveNoData );
+
+        GDALColorTable *poCT = poSrcDS->GetRasterBand(1)->GetColorTable();
 
-        dfNoDataValue  = poSrcDS->GetRasterBand(1)->GetNoDataValue( &bHaveNoData );
-        
-        poCT = poSrcDS->GetRasterBand(1)->GetColorTable();
+        int nEntryCount = poCT->GetColorEntryCount();
+        int nMaxEntryCount = 1 << nBitDepth;
+        if( nEntryCount > nMaxEntryCount )
+            nEntryCount = nMaxEntryCount;
 
-        pasPNGColors = (png_color *) CPLMalloc(sizeof(png_color) *
-                                               poCT->GetColorEntryCount());
+        png_color *pasPNGColors = reinterpret_cast<png_color *>(
+            CPLMalloc( sizeof(png_color) * nEntryCount ) );
 
-        for( iColor = 0; iColor < poCT->GetColorEntryCount(); iColor++ )
+        GDALColorEntry sEntry;
+        bool bFoundTrans = false;
+        for( int iColor = 0; iColor < nEntryCount; iColor++ )
         {
             poCT->GetColorEntryAsRGB( iColor, &sEntry );
             if( sEntry.c4 != 255 )
-                bFoundTrans = TRUE;
+                bFoundTrans = true;
 
-            pasPNGColors[iColor].red = (png_byte) sEntry.c1;
-            pasPNGColors[iColor].green = (png_byte) sEntry.c2;
-            pasPNGColors[iColor].blue = (png_byte) sEntry.c3;
+            pasPNGColors[iColor].red = static_cast<png_byte>( sEntry.c1 );
+            pasPNGColors[iColor].green = static_cast<png_byte>( sEntry.c2 );
+            pasPNGColors[iColor].blue = static_cast<png_byte>( sEntry.c3 );
         }
-        
-        png_set_PLTE( hPNG, psPNGInfo, pasPNGColors, 
-                      poCT->GetColorEntryCount() );
+
+        png_set_PLTE( hPNG, psPNGInfo, pasPNGColors,
+                      nEntryCount );
+
+        CPLFree( pasPNGColors );
 
 /* -------------------------------------------------------------------- */
 /*      If we have transparent elements in the palette we need to       */
@@ -1763,30 +1804,35 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
         if( bFoundTrans || bHaveNoData )
         {
-            pabyAlpha = (unsigned char *)CPLMalloc(poCT->GetColorEntryCount());
+            unsigned char *pabyAlpha
+                = reinterpret_cast<unsigned char *>(
+                    CPLMalloc(nEntryCount) );
 
-            for( iColor = 0; iColor < poCT->GetColorEntryCount(); iColor++ )
+            for( int iColor = 0; iColor < nEntryCount; iColor++ )
             {
                 poCT->GetColorEntryAsRGB( iColor, &sEntry );
-                pabyAlpha[iColor] = (unsigned char) sEntry.c4;
+                pabyAlpha[iColor] = static_cast<unsigned char>( sEntry.c4 );
 
-                if( bHaveNoData && iColor == (int) dfNoDataValue )
+                if( bHaveNoData && iColor == static_cast<int>( dfNoDataValue ) )
                     pabyAlpha[iColor] = 0;
             }
 
-            png_set_tRNS( hPNG, psPNGInfo, pabyAlpha, 
-                          poCT->GetColorEntryCount(), NULL );
+            png_set_tRNS( hPNG, psPNGInfo, pabyAlpha,
+                          nEntryCount, NULL );
+
+            CPLFree( pabyAlpha );
         }
     }
 
 /* -------------------------------------------------------------------- */
 /*      Add text info                                                   */
 /* -------------------------------------------------------------------- */
-    /* Predefined keywords. See "4.2.7 tEXt Textual data" of http://www.w3.org/TR/PNG-Chunks.html */
+    // Predefined keywords. See "4.2.7 tEXt Textual data" of
+    // http://www.w3.org/TR/PNG-Chunks.html
     const char* apszKeywords[] = { "Title", "Author", "Description", "Copyright",
                                    "Creation Time", "Software", "Disclaimer",
                                    "Warning", "Source", "Comment", NULL };
-    int bWriteMetadataAsText = CSLTestBoolean(
+    const bool bWriteMetadataAsText = CPLTestBool(
         CSLFetchNameValueDef(papszOptions, "WRITE_METADATA_AS_TEXT", "FALSE"));
     for(int i=0;apszKeywords[i]!=NULL;i++)
     {
@@ -1808,7 +1854,7 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             const char* pszValue = CPLParseNameValue(*papszSrcMD, &pszKey );
             if( pszKey && pszValue )
             {
-                if( CSLFindString((char**)apszKeywords, pszKey) < 0 &&
+                if( CSLFindString(const_cast<char**>( apszKeywords ), pszKey) < 0 &&
                     !EQUAL(pszKey, "AREA_OR_POINT") && !EQUAL(pszKey, "NODATA_VALUES") )
                 {
                     WriteMetadataAsText(hPNG, psPNGInfo, pszKey, pszValue);
@@ -1823,24 +1869,27 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
     png_write_info( hPNG, psPNGInfo );
 
+    if( nBitDepth < 8 )
+        png_set_packing( hPNG );
+
 /* -------------------------------------------------------------------- */
 /*      Loop over image, copying image data.                            */
 /* -------------------------------------------------------------------- */
-    GByte 	*pabyScanline;
     CPLErr      eErr = CE_None;
-    int         nWordSize = nBitDepth/8;
+    const int nWordSize = GDALGetDataTypeSize(eType) / 8;
 
-    pabyScanline = (GByte *) CPLMalloc( nBands * nXSize * nWordSize );
+    GByte *pabyScanline = reinterpret_cast<GByte *>(
+        CPLMalloc( nBands * nXSize * nWordSize ) );
 
     for( int iLine = 0; iLine < nYSize && eErr == CE_None; iLine++ )
     {
         png_bytep       row = pabyScanline;
 
-        eErr = poSrcDS->RasterIO( GF_Read, 0, iLine, nXSize, 1, 
-                                  pabyScanline, 
+        eErr = poSrcDS->RasterIO( GF_Read, 0, iLine, nXSize, 1,
+                                  pabyScanline,
                                   nXSize, 1, eType,
                                   nBands, NULL,
-                                  nBands * nWordSize, 
+                                  nBands * nWordSize,
                                   nBands * nXSize * nWordSize,
                                   nWordSize,
                                   NULL );
@@ -1853,7 +1902,7 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             png_write_rows( hPNG, &row, 1 );
 
         if( eErr == CE_None
-            && !pfnProgress( (iLine+1) / (double) nYSize,
+            && !pfnProgress( (iLine+1) / static_cast<double>( nYSize ),
                              NULL, pProgressData ) )
         {
             eErr = CE_Failure;
@@ -1869,9 +1918,6 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
     VSIFCloseL( fpImage );
 
-    CPLFree( pabyAlpha );
-    CPLFree( pasPNGColors );
-
     if( eErr != CE_None )
         return NULL;
 
@@ -1881,7 +1927,7 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     if( CSLFetchBoolean( papszOptions, "WORLDFILE", FALSE ) )
     {
     	double      adfGeoTransform[6];
-	
+
 	if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None )
             GDALWriteWorldFile( pszFilename, "wld", adfGeoTransform );
     }
@@ -1890,13 +1936,14 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      Re-open dataset, and copy any auxiliary pam information.         */
 /* -------------------------------------------------------------------- */
 
-    /* If outputing to stdout, we can't reopen it, so we'll return */
+    /* If writing to stdout, we can't reopen it, so return */
     /* a fake dataset to make the caller happy */
-    if( CSLTestBoolean(CPLGetConfigOption("GDAL_OPEN_AFTER_COPY", "YES")) )
+    if( CPLTestBool(CPLGetConfigOption("GDAL_OPEN_AFTER_COPY", "YES")) )
     {
         CPLPushErrorHandler(CPLQuietErrorHandler);
         GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly);
-        PNGDataset *poDS = (PNGDataset*) PNGDataset::Open( &oOpenInfo );
+        PNGDataset *poDS = reinterpret_cast<PNGDataset *>(
+            PNGDataset::Open( &oOpenInfo ) );
         CPLPopErrorHandler();
         if( poDS )
         {
@@ -1927,16 +1974,15 @@ static void
 png_vsi_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
 
 {
-   png_size_t check;
-
-   /* fread() returns 0 on error, so it is OK to store this in a png_size_t
-    * instead of an int, which is what fread() actually returns.
-    */
-   check = (png_size_t)VSIFReadL(data, (png_size_t)1, length,
-                                 (VSILFILE*)png_get_io_ptr(png_ptr));
-
-   if (check != length)
-      png_error(png_ptr, "Read Error");
+    // fread() returns 0 on error, so it is OK to store this in a png_size_t
+    // instead of an int, which is what fread() actually returns.
+    const png_size_t check
+        = static_cast<png_size_t>(
+            VSIFReadL(data, (png_size_t)1, length,
+                      reinterpret_cast<VSILFILE *>( png_get_io_ptr(png_ptr) ) ) );
+
+    if (check != length)
+        png_error(png_ptr, "Read Error");
 }
 
 /************************************************************************/
@@ -1946,11 +1992,11 @@ png_vsi_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
 static void
 png_vsi_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
 {
-   png_uint_32 check;
+    const size_t check
+        = VSIFWriteL(data, 1, length, reinterpret_cast<VSILFILE *>(
+            png_get_io_ptr(png_ptr) ) );
 
-   check = VSIFWriteL(data, 1, length, (VSILFILE*)png_get_io_ptr(png_ptr));
-
-   if (check != length)
+    if (check != length)
       png_error(png_ptr, "Write Error");
 }
 
@@ -1959,7 +2005,7 @@ png_vsi_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
 /************************************************************************/
 static void png_vsi_flush(png_structp png_ptr)
 {
-    VSIFFlushL( (VSILFILE*)png_get_io_ptr(png_ptr) );
+    VSIFFlushL( reinterpret_cast<VSILFILE *>( png_get_io_ptr(png_ptr) ) );
 }
 
 /************************************************************************/
@@ -1968,14 +2014,15 @@ static void png_vsi_flush(png_structp png_ptr)
 
 static void png_gdal_error( png_structp png_ptr, const char *error_message )
 {
-    CPLError( CE_Failure, CPLE_AppDefined, 
+    CPLError( CE_Failure, CPLE_AppDefined,
               "libpng: %s", error_message );
 
-    // We have to use longjmp instead of a C++ exception because 
-    // libpng is generally not built as C++ and so won't honour unwind
-    // semantics.  Ugg. 
+    // We have to use longjmp instead of a C++ exception because
+    // libpng is generally not built as C++ and so will not honour unwind
+    // semantics.  Ugh.
 
-    jmp_buf* psSetJmpContext = (jmp_buf*) png_get_error_ptr(png_ptr);
+    jmp_buf* psSetJmpContext = reinterpret_cast<jmp_buf *>(
+        png_get_error_ptr( png_ptr ) );
     if (psSetJmpContext)
     {
         longjmp( *psSetJmpContext, 1 );
@@ -1986,7 +2033,8 @@ static void png_gdal_error( png_structp png_ptr, const char *error_message )
 /*                          png_gdal_warning()                          */
 /************************************************************************/
 
-static void png_gdal_warning( CPL_UNUSED png_structp png_ptr, const char *error_message )
+static void png_gdal_warning( CPL_UNUSED png_structp png_ptr,
+                              const char *error_message )
 {
     CPLError( CE_Warning, CPLE_AppDefined,
               "libpng: %s", error_message );
@@ -1999,29 +2047,28 @@ static void png_gdal_warning( CPL_UNUSED png_structp png_ptr, const char *error_
 void GDALRegister_PNG()
 
 {
-    GDALDriver	*poDriver;
-
-    if( GDALGetDriverByName( "PNG" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "PNG" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Portable Network Graphics" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#PNG" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "png" );
-        poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/png" );
-
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte UInt16" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
+    if( GDALGetDriverByName( "PNG" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "PNG" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Portable Network Graphics" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_various.html#PNG" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "png" );
+    poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/png" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte UInt16" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>\n"
 "   <Option name='WORLDFILE' type='boolean' description='Create world file' default='FALSE'/>\n"
 "   <Option name='ZLEVEL' type='int' description='DEFLATE compression level 1-9' default='6'/>\n"
 "   <Option name='SOURCE_ICC_PROFILE' type='string' description='ICC Profile'/>\n"
-"   <Option name='SOURCE_ICC_PROFILE_NAME' type='string' descriptor='ICC Profile name'/>\n"
+"   <Option name='SOURCE_ICC_PROFILE_NAME' type='string' description='ICC Profile name'/>\n"
 "   <Option name='SOURCE_PRIMARIES_RED' type='string' description='x,y,1.0 (xyY) red chromaticity'/>\n"
 "   <Option name='SOURCE_PRIMARIES_GREEN' type='string' description='x,y,1.0 (xyY) green chromaticity'/>\n"
 "   <Option name='SOURCE_PRIMARIES_BLUE' type='string' description='x,y,1.0 (xyY) blue chromaticity'/>\n"
@@ -2032,19 +2079,19 @@ void GDALRegister_PNG()
 "   <Option name='COPYRIGHT' type='string' description='Copyright'/>\n"
 "   <Option name='COMMENT' type='string' description='Comment'/>\n"
 "   <Option name='WRITE_METADATA_AS_TEXT' type='boolean' description='Whether to write source dataset metadata in TEXT chunks' default='FALSE'/>\n"
+"   <Option name='NBITS' type='int' description='Force output bit depth: 1, 2 or 4'/>\n"
 "</CreationOptionList>\n" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = PNGDataset::Open;
-        poDriver->pfnCreateCopy = PNGDataset::CreateCopy;
-        poDriver->pfnIdentify = PNGDataset::Identify;
+    poDriver->pfnOpen = PNGDataset::Open;
+    poDriver->pfnCreateCopy = PNGDataset::CreateCopy;
+    poDriver->pfnIdentify = PNGDataset::Identify;
 #ifdef SUPPORT_CREATE
-        poDriver->pfnCreate = PNGDataset::Create;
+    poDriver->pfnCreate = PNGDataset::Create;
 #endif
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
 
 #ifdef SUPPORT_CREATE
@@ -2055,14 +2102,12 @@ void GDALRegister_PNG()
 CPLErr PNGRasterBand::IWriteBlock(int x, int y, void* pvData)
 {
     // rcg, added to support Create().
-
-    PNGDataset& ds = *(PNGDataset*)poDS;
-
+    PNGDataset& ds = *reinterpret_cast<PNGDataset*>( poDS );
 
     // Write the block (or consolidate into multichannel block)
     // and then write.
 
-    const GDALDataType dt = this->GetRasterDataType();
+    const GDALDataType dt = GetRasterDataType();
     const size_t wordsize = ds.m_nBitDepth / 8;
     GDALCopyWords( pvData, dt, wordsize,
                    ds.m_pabyBuffer + (nBand-1) * wordsize,
@@ -2070,9 +2115,8 @@ CPLErr PNGRasterBand::IWriteBlock(int x, int y, void* pvData)
                    nBlockXSize );
 
     // See if we got all the bands.
-    size_t i;
     m_bBandProvided[nBand - 1] = TRUE;
-    for(i = 0; i < ds.nBands; i++)
+    for( size_t i = 0; i < static_cast<size_t>( ds.nBands ); i++ )
     {
         if(!m_bBandProvided[i])
             return CE_None;
@@ -2108,9 +2152,6 @@ CPLErr PNGRasterBand::IWriteBlock(int x, int y, void* pvData)
 CPLErr PNGDataset::SetGeoTransform( double * padfTransform )
 {
     // rcg, added to support Create().
-
-    CPLErr eErr = CE_None;
-
     memcpy( m_adfGeoTransform, padfTransform, sizeof(double) * 6 );
 
     if ( m_pszFilename )
@@ -2119,11 +2160,11 @@ CPLErr PNGDataset::SetGeoTransform( double * padfTransform )
              == FALSE )
         {
             CPLError( CE_Failure, CPLE_FileIO, "Can't write world file." );
-            eErr = CE_Failure;
+            return CE_Failure;
         }
     }
 
-    return eErr;
+    return CE_None;
 }
 
 
@@ -2137,12 +2178,12 @@ CPLErr PNGRasterBand::SetColorTable(GDALColorTable* poCT)
         return CE_Failure;
 
     // rcg, added to support Create().
-    // We get called even for grayscale files, since some 
+    // We get called even for grayscale files, since some
     // formats need a palette even then. PNG doesn't, so
     // if a gray palette is given, just ignore it.
 
     GDALColorEntry sEntry;
-    for( size_t i = 0; i < poCT->GetColorEntryCount(); i++ )
+    for( size_t i = 0; i < static_cast<size_t>( poCT->GetColorEntryCount() ); i++ )
     {
         poCT->GetColorEntryAsRGB( i, &sEntry );
         if( sEntry.c1 != sEntry.c2 || sEntry.c1 != sEntry.c3)
@@ -2151,10 +2192,10 @@ CPLErr PNGRasterBand::SetColorTable(GDALColorTable* poCT)
             if(err != CE_None)
                 return err;
 
-            PNGDataset& ds = *(PNGDataset*)poDS;
+            PNGDataset& ds = *reinterpret_cast<PNGDataset *>( poDS );
             ds.m_nColorType = PNG_COLOR_TYPE_PALETTE;
             break;
-            // band::IWriteBlock will emit color table as part of 
+            // band::IWriteBlock will emit color table as part of
             // header preceding first block write.
         }
     }
@@ -2162,7 +2203,6 @@ CPLErr PNGRasterBand::SetColorTable(GDALColorTable* poCT)
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                  PNGDataset::write_png_header()                      */
 /************************************************************************/
@@ -2172,17 +2212,16 @@ CPLErr PNGDataset::write_png_header()
 /* -------------------------------------------------------------------- */
 /*      Initialize PNG access to the file.                              */
 /* -------------------------------------------------------------------- */
-    
-    m_hPNG = png_create_write_struct( 
-        PNG_LIBPNG_VER_STRING, NULL, 
+    m_hPNG = png_create_write_struct(
+        PNG_LIBPNG_VER_STRING, NULL,
         png_gdal_error, png_gdal_warning );
 
     m_psPNGInfo = png_create_info_struct( m_hPNG );
 
     png_set_write_fn( m_hPNG, m_fpImage, png_vsi_write_data, png_vsi_flush );
 
-    png_set_IHDR( m_hPNG, m_psPNGInfo, nRasterXSize, nRasterYSize, 
-                  m_nBitDepth, m_nColorType, PNG_INTERLACE_NONE, 
+    png_set_IHDR( m_hPNG, m_psPNGInfo, nRasterXSize, nRasterYSize,
+                  m_nBitDepth, m_nColorType, PNG_INTERLACE_NONE,
                   PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT );
 
     png_set_compression_level(m_hPNG, Z_BEST_COMPRESSION);
@@ -2198,17 +2237,16 @@ CPLErr PNGDataset::write_png_header()
     //m_dfNoDataValue = -1;
     png_color_16 sTRNSColor;
 
-
-    int		bHaveNoData = FALSE;
-    double	dfNoDataValue = -1;
+    int bHaveNoData = FALSE;
+    double dfNoDataValue = -1;
 
     if( m_nColorType == PNG_COLOR_TYPE_GRAY )
     {
-        dfNoDataValue = this->GetRasterBand(1)->GetNoDataValue( &bHaveNoData );
+        dfNoDataValue = GetRasterBand(1)->GetNoDataValue( &bHaveNoData );
 
         if ( bHaveNoData && dfNoDataValue >= 0 && dfNoDataValue < 65536 )
         {
-            sTRNSColor.gray = (png_uint_16) dfNoDataValue;
+            sTRNSColor.gray = static_cast<png_uint_16>( dfNoDataValue );
             png_set_tRNS( m_hPNG, m_psPNGInfo, NULL, 0, &sTRNSColor );
         }
     }
@@ -2217,16 +2255,16 @@ CPLErr PNGDataset::write_png_header()
     if( nColorType == PNG_COLOR_TYPE_RGB )
     {
         // First try to use the NODATA_VALUES metadata item.
-        if ( this->GetMetadataItem( "NODATA_VALUES" ) != NULL )
+        if ( GetMetadataItem( "NODATA_VALUES" ) != NULL )
         {
             char **papszValues = CSLTokenizeString(
-                this->GetMetadataItem( "NODATA_VALUES" ) );
-           
+                GetMetadataItem( "NODATA_VALUES" ) );
+
             if( CSLCount(papszValues) >= 3 )
             {
-                sTRNSColor.red   = (png_uint_16) atoi(papszValues[0]);
-                sTRNSColor.green = (png_uint_16) atoi(papszValues[1]);
-                sTRNSColor.blue  = (png_uint_16) atoi(papszValues[2]);
+                sTRNSColor.red   = static_cast<png_uint_16>( atoi(papszValues[0] ) );
+                sTRNSColor.green = static_cast<png_uint_16>( atoi(papszValues[1] ) );
+                sTRNSColor.blue  = static_cast<png_uint_16>( atoi(papszValues[2] ) );
                 png_set_tRNS( m_hPNG, m_psPNGInfo, NULL, 0, &sTRNSColor );
             }
 
@@ -2235,24 +2273,25 @@ CPLErr PNGDataset::write_png_header()
         // Otherwise, get the nodata value from the bands.
         else
         {
-            int	  bHaveNoDataRed = FALSE;
-            int	  bHaveNoDataGreen = FALSE;
-            int	  bHaveNoDataBlue = FALSE;
-            double dfNoDataValueRed = -1;
-            double dfNoDataValueGreen = -1;
-            double dfNoDataValueBlue = -1;
+            int bHaveNoDataRed = FALSE;
+            const double dfNoDataValueRed
+                = GetRasterBand(1)->GetNoDataValue( &bHaveNoDataRed );
+
+            int bHaveNoDataGreen = FALSE;
+            const double dfNoDataValueGreen
+                = GetRasterBand(2)->GetNoDataValue( &bHaveNoDataGreen );
 
-            dfNoDataValueRed  = this->GetRasterBand(1)->GetNoDataValue( &bHaveNoDataRed );
-            dfNoDataValueGreen= this->GetRasterBand(2)->GetNoDataValue( &bHaveNoDataGreen );
-            dfNoDataValueBlue = this->GetRasterBand(3)->GetNoDataValue( &bHaveNoDataBlue );
+            int bHaveNoDataBlue = FALSE;
+            const double dfNoDataValueBlue
+                = GetRasterBand(3)->GetNoDataValue( &bHaveNoDataBlue );
 
             if ( ( bHaveNoDataRed && dfNoDataValueRed >= 0 && dfNoDataValueRed < 65536 ) &&
                  ( bHaveNoDataGreen && dfNoDataValueGreen >= 0 && dfNoDataValueGreen < 65536 ) &&
                  ( bHaveNoDataBlue && dfNoDataValueBlue >= 0 && dfNoDataValueBlue < 65536 ) )
             {
-                sTRNSColor.red   = (png_uint_16) dfNoDataValueRed;
-                sTRNSColor.green = (png_uint_16) dfNoDataValueGreen;
-                sTRNSColor.blue  = (png_uint_16) dfNoDataValueBlue;
+                sTRNSColor.red   = static_cast<png_uint_16>( dfNoDataValueRed );
+                sTRNSColor.green = static_cast<png_uint_16>( dfNoDataValueGreen );
+                sTRNSColor.blue  = static_cast<png_uint_16>( dfNoDataValueBlue );
                 png_set_tRNS( m_hPNG, m_psPNGInfo, NULL, 0, &sTRNSColor );
             }
         }
@@ -2266,31 +2305,28 @@ CPLErr PNGDataset::write_png_header()
 
     if( nColorType == PNG_COLOR_TYPE_PALETTE )
     {
-        GDALColorTable	*poCT;
-        GDALColorEntry  sEntry;
-        int		iColor, bFoundTrans = FALSE;
-        int		bHaveNoData = FALSE;
-        double	dfNoDataValue = -1;
+        GDALColorTable *poCT = GetRasterBand(1)->GetColorTable();
 
-        dfNoDataValue  = this->GetRasterBand(1)->GetNoDataValue( &bHaveNoData );
-        
-        poCT = this->GetRasterBand(1)->GetColorTable();
+        int bHaveNoData = FALSE;
+        double	dfNoDataValue = GetRasterBand(1)->GetNoDataValue( &bHaveNoData );
 
-        m_pasPNGColors = (png_color *) CPLMalloc(sizeof(png_color) *
-                                                 poCT->GetColorEntryCount());
+        m_pasPNGColors = reinterpret_cast<png_color *>(
+            CPLMalloc( sizeof(png_color) * poCT->GetColorEntryCount() ) );
 
-        for( iColor = 0; iColor < poCT->GetColorEntryCount(); iColor++ )
+        GDALColorEntry sEntry;
+        bool bFoundTrans = false;
+        for( int iColor = 0; iColor < poCT->GetColorEntryCount(); iColor++ )
         {
             poCT->GetColorEntryAsRGB( iColor, &sEntry );
             if( sEntry.c4 != 255 )
-                bFoundTrans = TRUE;
+                bFoundTrans = true;
 
-            m_pasPNGColors[iColor].red = (png_byte) sEntry.c1;
-            m_pasPNGColors[iColor].green = (png_byte) sEntry.c2;
-            m_pasPNGColors[iColor].blue = (png_byte) sEntry.c3;
+            m_pasPNGColors[iColor].red   = static_cast<png_byte>( sEntry.c1 );
+            m_pasPNGColors[iColor].green = static_cast<png_byte>( sEntry.c2 );
+            m_pasPNGColors[iColor].blue  = static_cast<png_byte>( sEntry.c3 );
         }
-        
-        png_set_PLTE( m_hPNG, m_psPNGInfo, m_pasPNGColors, 
+
+        png_set_PLTE( m_hPNG, m_psPNGInfo, m_pasPNGColors,
                       poCT->GetColorEntryCount() );
 
 /* -------------------------------------------------------------------- */
@@ -2299,18 +2335,19 @@ CPLErr PNGDataset::write_png_header()
 /* -------------------------------------------------------------------- */
         if( bFoundTrans || bHaveNoData )
         {
-            m_pabyAlpha = (unsigned char *)CPLMalloc(poCT->GetColorEntryCount());
+            m_pabyAlpha = reinterpret_cast<unsigned char *>(
+                CPLMalloc(poCT->GetColorEntryCount() ) );
 
-            for( iColor = 0; iColor < poCT->GetColorEntryCount(); iColor++ )
+            for( int iColor = 0; iColor < poCT->GetColorEntryCount(); iColor++ )
             {
                 poCT->GetColorEntryAsRGB( iColor, &sEntry );
-                m_pabyAlpha[iColor] = (unsigned char) sEntry.c4;
+                m_pabyAlpha[iColor] = static_cast<unsigned char>( sEntry.c4 );
 
-                if( bHaveNoData && iColor == (int) dfNoDataValue )
+                if( bHaveNoData && iColor == static_cast<int>( dfNoDataValue ) )
                     m_pabyAlpha[iColor] = 0;
             }
 
-            png_set_tRNS( m_hPNG, m_psPNGInfo, m_pabyAlpha, 
+            png_set_tRNS( m_hPNG, m_psPNGInfo, m_pabyAlpha,
                           poCT->GetColorEntryCount(), NULL );
         }
     }
@@ -2327,11 +2364,11 @@ CPLErr PNGDataset::write_png_header()
 // static
 GDALDataset *PNGDataset::Create
 (
-	const char* pszFilename,
-    int nXSize, int nYSize, 
-	int nBands,
-    GDALDataType eType, 
-	char **papszOptions 
+    const char* pszFilename,
+    int nXSize, int nYSize,
+    int nBands,
+    GDALDataType eType,
+    char **papszOptions
 )
 {
     if( eType != GDT_Byte && eType != GDT_UInt16)
@@ -2349,13 +2386,12 @@ GDALDataset *PNGDataset::Create
         CPLError( CE_Failure, CPLE_NotSupported,
                   "PNG driver doesn't support %d bands. "
                   "Must be 1 (gray/indexed color),\n"
-                  "2 (gray+alpha), 3 (rgb) or 4 (rgba) bands.\n", 
+                  "2 (gray+alpha), 3 (rgb) or 4 (rgba) bands.\n",
                   nBands );
 
         return NULL;
     }
 
-
     // Bands are:
     // 1: grayscale or indexed color
     // 2: gray plus alpha
@@ -2372,7 +2408,6 @@ GDALDataset *PNGDataset::Create
 /* -------------------------------------------------------------------- */
 /*      Setup some parameters.                                          */
 /* -------------------------------------------------------------------- */
-
     PNGDataset* poDS = new PNGDataset();
 
     poDS->nRasterXSize = nXSize;
@@ -2380,7 +2415,6 @@ GDALDataset *PNGDataset::Create
     poDS->eAccess = GA_Update;
     poDS->nBands = nBands;
 
-
     switch(nBands)
     {
       case 1:
@@ -2394,7 +2428,7 @@ GDALDataset *PNGDataset::Create
       case 3:
         poDS->m_nColorType = PNG_COLOR_TYPE_RGB;
         break;
-	
+
       case 4:
         poDS->m_nColorType = PNG_COLOR_TYPE_RGB_ALPHA;
         break;
@@ -2402,15 +2436,13 @@ GDALDataset *PNGDataset::Create
 
     poDS->m_nBitDepth = (eType == GDT_Byte ? 8 : 16);
 
-    poDS->m_pabyBuffer = (GByte *) CPLMalloc(
-        nBands * nXSize * poDS->m_nBitDepth / 8 );
+    poDS->m_pabyBuffer = reinterpret_cast<GByte *>(
+        CPLMalloc( nBands * nXSize * poDS->m_nBitDepth / 8 ) );
 
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    int iBand;
-
-    for( iBand = 1; iBand <= poDS->nBands; iBand++ )
+    for( int iBand = 1; iBand <= poDS->nBands; iBand++ )
         poDS->SetBand( iBand, new PNGRasterBand( poDS, iBand ) );
 
 /* -------------------------------------------------------------------- */
@@ -2426,8 +2458,8 @@ GDALDataset *PNGDataset::Create
     poDS->m_fpImage = VSIFOpenL( pszFilename, "wb" );
     if( poDS->m_fpImage == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Unable to create PNG file %s.\n", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Unable to create PNG file %s.\n",
                   pszFilename );
         delete poDS;
         return NULL;
diff --git a/frmts/postgisraster/postgisraster.h b/frmts/postgisraster/postgisraster.h
index fe5aa2c..3bbab65 100644
--- a/frmts/postgisraster/postgisraster.h
+++ b/frmts/postgisraster/postgisraster.h
@@ -4,7 +4,7 @@
  * Purpose:  Main header file for PostGIS Raster Driver
  * Author:   Jorge Arevalo, jorge.arevalo at deimos-space.com
  * 							jorgearevalo at libregis.org
- * 
+ *
  * Author:	 David Zwarg, dzwarg at azavea.com
  *
  * Last changes: $Id: $
@@ -13,24 +13,24 @@
  * Copyright (c) 2009 - 2013, Jorge Arevalo, David Zwarg
  * Copyright (c) 2013, Even Rouault
  *
- * Permission is hereby granted, free of charge, to any person obtaining 
- * a copy of this software and associated documentation files (the 
- * "Software"),to deal in the Software without restriction, including 
- * without limitation the rights to use, copy, modify, merge, publish, 
- * distribute, sublicense, and/or sell copies of the Software, and to 
- * permit persons to whom the Software is furnished to do so, subject to 
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"),to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
  * the following conditions:
  *
- * The above copyright notice and this permission notice shall be 
+ * The above copyright notice and this permission notice shall be
  * included in all copies or substantial portions of the Software.
  *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  **********************************************************************/
 
@@ -73,7 +73,6 @@
 
 #define GET_BAND_DATA(raster, nband, nodatasize, datasize) \
     ((raster) + RASTER_HEADER_SIZE + (nband) * BAND_SIZE(nodatasize, datasize) - (datasize))
-    
 
 #define GEOTRSFRM_TOPLEFT_X            0
 #define GEOTRSFRM_WE_RES               1
@@ -126,11 +125,11 @@ typedef enum
  * 		considered as tiles of a bigger raster coverage (the whole
  * 		table). If database and table name are specified and mode = 2
  * 		is present in the connection string, this is the selected mode.
- * - BROWSE_SCHEMA: If no table name is speficied, just database and
+ * - BROWSE_SCHEMA: If no table name is specified, just database and
  * 		schema names, the driver will yell of the schema's raster tables
  * 		as possible datasets.
  * - BROWSE_DATABASE: If no table name is specified, just database name,
- * 		the driver will yell of the database's raster tables as possible 
+ * 		the driver will yell of the database's raster tables as possible
  * 		datasets.
  **/
 typedef enum
@@ -168,13 +167,12 @@ char * ReplaceQuotes(const char *, int);
 char * ReplaceSingleQuotes(const char *, int);
 char ** ParseConnectionString(const char *);
 GBool TranslateDataType(const char *, GDALDataType *, int *, GBool *);
-        
 
 class PostGISRasterRasterBand;
 class PostGISRasterTileDataset;
 
 /***********************************************************************
- * PostGISRasterDriver: extends GDALDriver to support PostGIS Raster 
+ * PostGISRasterDriver: extends GDALDriver to support PostGIS Raster
  * connect.
  **********************************************************************/
 class PostGISRasterDriver : public GDALDriver {
@@ -191,7 +189,7 @@ public:
 
 
 /***********************************************************************
- * PostGISRasterDataset: extends VRTDataset to support PostGIS Raster 
+ * PostGISRasterDataset: extends VRTDataset to support PostGIS Raster
  * datasets
  **********************************************************************/
 class PostGISRasterDataset : public VRTDataset {
@@ -217,7 +215,7 @@ private:
     char* pszProjection;
     ResolutionStrategy resolutionStrategy;
     WorkingMode nMode;
-    int nTiles;
+    int m_nTiles;
     double xmin, ymin, xmax, ymax;
     PostGISRasterTileDataset ** papoSourcesHolders;
     CPLQuadTree * hQuadTree;
@@ -226,7 +224,7 @@ private:
     int nOverviewCount;
     PostGISRasterDataset* poParentDS;
     PostGISRasterDataset** papoOverviewDS;
-    
+
     std::map<CPLString, PostGISRasterTileDataset*> oMapPKIDToRTDS;
 
     GBool bAssumeMultiBandReadPattern;
@@ -238,7 +236,7 @@ private:
 
     GBool bHasTriedHasSpatialIndex;
     GBool bHasSpatialIndex;
-    
+
     GBool bBuildQuadTreeDynamically;
 
     GBool bTilesSameDimension;
@@ -250,11 +248,11 @@ private:
     GBool SetRasterProperties(const char *);
     GBool BrowseDatabase(const char *, const char *);
     GBool AddComplexSource(PostGISRasterTileDataset* poRTDS);
-    GBool GetDstWin(PostGISRasterTileDataset *, int *, int *, int *, 
+    GBool GetDstWin(PostGISRasterTileDataset *, int *, int *, int *,
 		int *);
     BandMetadata * GetBandsMetadata(int *);
     PROverview * GetOverviewTables(int *);
-    
+
     PostGISRasterTileDataset* BuildRasterTileDataset(const char* pszMetadata,
                                                      const char* pszPKID,
                                                      int nBandsFetched,
@@ -275,9 +273,9 @@ public:
     virtual ~PostGISRasterDataset();
     static GDALDataset* Open(GDALOpenInfo *);
     static int Identify(GDALOpenInfo *);
-    static GDALDataset* CreateCopy(const char *, GDALDataset *, 
+    static GDALDataset* CreateCopy(const char *, GDALDataset *,
         int, char **, GDALProgressFunc, void *);
-    static GBool InsertRaster(PGconn *, PostGISRasterDataset *, 
+    static GBool InsertRaster(PGconn *, PostGISRasterDataset *,
         const char *, const char *, const char *);
     static CPLErr Delete(const char*);
     virtual char      **GetMetadataDomainList();
@@ -294,17 +292,17 @@ public:
     const char * GetPrimaryKeyRef();
     GBool HasSpatialIndex();
     GBool LoadSources(int nXOff, int nYOff, int nXSize, int nYSize, int nBand);
-    GBool PolygonFromCoords(int nXOff, int nYOff, int nXEndOff, 
+    GBool PolygonFromCoords(int nXOff, int nYOff, int nXEndOff,
         int nYEndOff,double adfProjWin[8]);
     void CacheTile(const char* pszMetadata, const char* pszRaster, const char *pszPKID, int nBand, int bAllBandCaching);
 };
 
 /***********************************************************************
- * PostGISRasterRasterBand: extends VRTSourcedRasterBand to support 
+ * PostGISRasterRasterBand: extends VRTSourcedRasterBand to support
  * PostGIS Raster bands
  **********************************************************************/
 class PostGISRasterTileRasterBand;
- 
+
 class PostGISRasterRasterBand : public VRTSourcedRasterBand {
     friend class PostGISRasterDataset;
 protected:
@@ -321,7 +319,7 @@ protected:
     void                      NullBuffer(void* pData,
                                          int nBufXSize,
                                          int nBufYSize,
-                                         GDALDataType eBufType, 
+                                         GDALDataType eBufType,
                                          int nPixelSpace,
                                          int nLineSpace);
 public:
@@ -333,7 +331,7 @@ public:
 
     virtual double GetNoDataValue(int *pbSuccess = NULL);
     virtual CPLErr SetNoDataValue(double);
-    virtual CPLErr IRasterIO(GDALRWFlag, int, int, int, int, void *, 
+    virtual CPLErr IRasterIO(GDALRWFlag, int, int, int, int, void *,
 		int, int, GDALDataType,
         GSpacing nPixelSpace, GSpacing nLineSpace,
         GDALRasterIOExtraArg* psExtraArg);
@@ -367,7 +365,7 @@ private:
 
 public:
 	PostGISRasterTileDataset(PostGISRasterDataset* poRDS,
-                             int nXSize, 
+                             int nXSize,
                              int nYSize);
 	~PostGISRasterTileDataset();
     CPLErr GetGeoTransform(double *);
@@ -376,7 +374,7 @@ public:
 };
 
 /***********************************************************************
- * PostGISRasterTileRasterBand: it holds a raster tile band, that will 
+ * PostGISRasterTileRasterBand: it holds a raster tile band, that will
  * be used as a source for PostGISRasterRasterBand
  **********************************************************************/
 class PostGISRasterTileRasterBand : public GDALRasterBand {
@@ -386,10 +384,9 @@ private:
     GBool bIsOffline;
 
     GBool IsCached();
-    
+
     VRTSource* poSource;
-	
-	
+
 public:
 	PostGISRasterTileRasterBand(
         PostGISRasterTileDataset * poRTDS, int nBand,
diff --git a/frmts/postgisraster/postgisrasterdataset.cpp b/frmts/postgisraster/postgisrasterdataset.cpp
index 8847ab5..d709fd2 100644
--- a/frmts/postgisraster/postgisrasterdataset.cpp
+++ b/frmts/postgisraster/postgisrasterdataset.cpp
@@ -4,7 +4,7 @@
  * Purpose:  GDAL Dataset implementation for PostGIS Raster driver
  * Author:   Jorge Arevalo, jorge.arevalo at deimos-space.com
  *                          jorgearevalo at libregis.org
- * 
+ *
  * Author:	 David Zwarg, dzwarg at azavea.com
  *
  * Last changes: $Id: $
@@ -13,7 +13,7 @@
  * Copyright (c) 2009 - 2013, Jorge Arevalo, David Zwarg
  * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
- * Permission is hereby granted, free of charge, to any person obtaining 
+ * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
  * "Software"), to deal in the Software without restriction, including
  * without limitation the rights to use, copy, modify, merge, publish,
@@ -21,18 +21,20 @@
  * permit persons to whom the Software is furnished to do so, subject to
  * the following conditions:
  *
- * The above copyright notice and this permission notice shall be 
+ * The above copyright notice and this permission notice shall be
  * included in all copies or substantial portions of the Software.
  *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
- * NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  **********************************************************************/
+
+#include "gdal_frmts.h"
 #include "postgisraster.h"
 #include <math.h>
 
@@ -44,11 +46,6 @@
 #define DEFAULT_SCHEMA          "public"
 #define DEFAULT_COLUMN          "rast"
 
-
-CPL_C_START
-void GDALRegister_PostGISRaster(void);
-CPL_C_END
-
 /** Note on read performance on mode=2:
 
     There are different situations:
@@ -64,7 +61,7 @@ CPL_C_END
             During a IRasterIO() query,
             i) we will do a SQL query to retrieve the PKID of tiles that intersect the query window.
             ii) If some tiles are not registered as sources, then do a SQL query to fetch their metadata
-            and instanciate them and register them.
+            and instantiate them and register them.
             iii) If some tiles are not cached, then determine if the query window is not too big (w.r.t. GDAL cache),
             and if not, then do a SQL query to fetch their raster column.
 
@@ -104,96 +101,97 @@ PostGISRasterDataset::PostGISRasterDataset():VRTDataset(0, 0) {
     poConn = NULL;
     bRegularBlocking = false;
     bAllTilesSnapToSameGrid = false;
-    
-    
-    bCheckAllTiles = CSLTestBoolean( 
+
+    bCheckAllTiles = CPLTestBool(
         CPLGetConfigOption("PR_ALLOW_WHOLE_TABLE_SCAN", "YES"));
-    
+
     pszSchema = NULL;
     pszTable = NULL;
     pszColumn = NULL;
     pszWhere = NULL;
     pszProjection = NULL;
-    
+
     adfGeoTransform[GEOTRSFRM_TOPLEFT_X] = 0.0;
     adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1] = 0.0;
     adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] = 0.0;
     adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] = 0.0;
     adfGeoTransform[GEOTRSFRM_WE_RES] = 0;
     adfGeoTransform[GEOTRSFRM_NS_RES] = 0;
-    
+
     adfGeoTransform[GEOTRSFRM_WE_RES] =
         CPLAtof(CPLGetConfigOption("PR_WE_RES", NO_VALID_RES));
-        
+
     adfGeoTransform[GEOTRSFRM_NS_RES] =
         CPLAtof(CPLGetConfigOption("PR_NS_RES", NO_VALID_RES));
-    
+
     // Default
     resolutionStrategy = AVERAGE_APPROX_RESOLUTION;
-    
+
     const char * pszTmp = NULL;
     // We ignore this option if we provided the desired resolution
     if (CPLIsEqual(adfGeoTransform[GEOTRSFRM_WE_RES], CPLAtof(NO_VALID_RES)) ||
         CPLIsEqual(adfGeoTransform[GEOTRSFRM_NS_RES], CPLAtof(NO_VALID_RES))) {
-            
+
         // Resolution didn't have a valid value, so, we initiate it
         adfGeoTransform[GEOTRSFRM_WE_RES] = 0.0;
         adfGeoTransform[GEOTRSFRM_NS_RES] = 0.0;
-        
-        pszTmp = 
+
+        pszTmp =
             CPLGetConfigOption("PR_RESOLUTION_STRATEGY", "AVERAGE_APPROX");
-            
+
         if (EQUAL(pszTmp, "LOWEST"))
             resolutionStrategy = LOWEST_RESOLUTION;
-            
+
         else if (EQUAL(pszTmp, "HIGHEST"))
             resolutionStrategy = HIGHEST_RESOLUTION;
-            
+
         else if (EQUAL(pszTmp, "USER"))
             resolutionStrategy = USER_RESOLUTION;
-        
+
         else if (EQUAL(pszTmp, "AVERAGE"))
             resolutionStrategy = AVERAGE_RESOLUTION;
-    
+
     }
-    
+
     else {
         resolutionStrategy = USER_RESOLUTION;
+#ifdef DEBUG_VERBOSE
         pszTmp = "USER";
+#endif
     }
-    
+
 #ifdef DEBUG_VERBOSE
      CPLDebug("PostGIS_Raster", "PostGISRasterDataset::Constructor:"
                 "STRATEGY = %s", pszTmp);
 #endif
 
-    nTiles = 0;
+    m_nTiles = 0;
     nMode = NO_MODE;
     poDriver = NULL;
-    
+
     nRasterXSize = nRasterYSize = 0;
     pszPrimaryKeyName = NULL;
     bIsFastPK = false;
     bHasTriedFetchingPrimaryKeyName = false;
-    
+
     papoSourcesHolders = NULL;
     hQuadTree = NULL;
-    
+
     bHasBuiltOverviews = false;
     nOverviewCount = 0;
     papoOverviewDS = NULL;
     poParentDS = NULL;
-    
+
     bAssumeMultiBandReadPattern = true;
     nNextExpectedBand = 1;
     nXOffPrev = 0;
     nYOffPrev = 0;
     nXSizePrev = 0;
     nYSizePrev = 0;
-    
+
     bHasTriedHasSpatialIndex = false;
     bHasSpatialIndex = false;
-    
+
     bBuildQuadTreeDynamically = false;
 
     bTilesSameDimension = false;
@@ -205,9 +203,9 @@ PostGISRasterDataset::PostGISRasterDataset():VRTDataset(0, 0) {
 
     /**
      * TODO: Parametrize bAllTilesSnapToSameGrid. It controls if all the
-     * raster rows, in ONE_RASTER_PER_TABLE mode, must be checked to 
-     * test if they snap to the same grid and have the same srid. It can 
-     * be the user decission, if he/she's sure all the rows pass the 
+     * raster rows, in ONE_RASTER_PER_TABLE mode, must be checked to
+     * test if they snap to the same grid and have the same SRID. It can
+     * be the user decision, if he/she's sure all the rows pass the
      * test and want more speed.
      **/
 
@@ -222,22 +220,22 @@ PostGISRasterDataset::~PostGISRasterDataset() {
         CPLFree(pszSchema);
         pszSchema = NULL;
     }
-    
+
     if (pszTable) {
         CPLFree(pszTable);
         pszTable = NULL;
     }
-    
+
     if (pszColumn) {
         CPLFree(pszColumn);
         pszColumn = NULL;
     }
-    
+
     if (pszWhere) {
         CPLFree(pszWhere);
         pszWhere = NULL;
     }
-    
+
     if (pszProjection) {
         CPLFree(pszProjection);
         pszProjection = NULL;
@@ -252,12 +250,12 @@ PostGISRasterDataset::~PostGISRasterDataset() {
         CSLDestroy(papszSubdatasets);
         papszSubdatasets = NULL;
     }
-        
+
     if (hQuadTree) {
         CPLQuadTreeDestroy(hQuadTree);
         hQuadTree = NULL;
     }
-    
+
     // Call it now so that the VRT sources
     // are deleted and that there is no longer any code
     // referencing the bands of the source holders.
@@ -267,12 +265,12 @@ PostGISRasterDataset::~PostGISRasterDataset() {
 
     if (papoSourcesHolders) {
         int i;
-        for(i = 0; i < nTiles; i++) {
+        for(i = 0; i < m_nTiles; i++) {
             if (papoSourcesHolders[i])
                 delete papoSourcesHolders[i];
-            
+
         }
-        
+
         VSIFree(papoSourcesHolders);
         papoSourcesHolders = NULL;
     }
@@ -297,7 +295,7 @@ int PostGISRasterDataset::CloseDependentDatasets()
         nOverviewCount = 0;
         bHasDroppedRef = TRUE;
     }
-    
+
     return bHasDroppedRef;
 }
 
@@ -309,16 +307,16 @@ GBool PostGISRasterDataset::HasSpatialIndex()
 {
     CPLString osCommand;
     PGresult* poResult = NULL;
-    
+
     // If exists, return it
     if (bHasTriedHasSpatialIndex) {
         return bHasSpatialIndex;
     }
-    
+
     bHasTriedHasSpatialIndex = true;
 
     /* For debugging purposes only */
-    if( CSLTestBoolean(CPLGetConfigOption("PR_DISABLE_GIST", "FALSE") ) )
+    if( CPLTestBool(CPLGetConfigOption("PR_DISABLE_GIST", "FALSE") ) )
         return false;
 
     // Copyright dustymugs !!!
@@ -338,16 +336,16 @@ GBool PostGISRasterDataset::HasSpatialIndex()
     "AND n.nspname = '%s' "
     "AND c2.relname = '%s' "
     "AND att.attname = '%s' ", pszSchema, pszTable, pszColumn);
-    
+
 #ifdef DEBUG_QUERY
-    CPLDebug("PostGIS_Raster", 
-        "PostGISRasterDataset::HasSpatialIndex(): Query: %s", 
+    CPLDebug("PostGIS_Raster",
+        "PostGISRasterDataset::HasSpatialIndex(): Query: %s",
         osCommand.c_str());
 #endif
 
     poResult = PQexec(poConn, osCommand.c_str());
-    
-    if (poResult == NULL || 
+
+    if (poResult == NULL ||
         PQresultStatus(poResult) != PGRES_TUPLES_OK ||
         PQntuples(poResult) <= 0 )
     {
@@ -375,18 +373,18 @@ const char * PostGISRasterDataset::GetPrimaryKeyRef()
 {
     CPLString osCommand;
     PGresult* poResult = NULL;
-    
+
     // If exists, return it
     if (bHasTriedFetchingPrimaryKeyName) {
         return pszPrimaryKeyName;
     }
-    
+
     bHasTriedFetchingPrimaryKeyName = true;
 
     /* For debugging purposes only */
-    if( CSLTestBoolean(CPLGetConfigOption("PR_DISABLE_PK", "FALSE") ) )
+    if( CPLTestBool(CPLGetConfigOption("PR_DISABLE_PK", "FALSE") ) )
         return NULL;
-    
+
     /* Determine the primary key/unique column on the table */
     osCommand.Printf("select d.attname from pg_catalog.pg_constraint "
         "as a join pg_catalog.pg_indexes as b on a.conname = "
@@ -397,21 +395,21 @@ const char * PostGISRasterDataset::GetPrimaryKeyRef()
         "in ('p', 'u')", pszSchema, pszTable);
 
 #ifdef DEBUG_QUERY
-    CPLDebug("PostGIS_Raster", 
-        "PostGISRasterDataset::GetPrimaryKeyRef(): Query: %s", 
+    CPLDebug("PostGIS_Raster",
+        "PostGISRasterDataset::GetPrimaryKeyRef(): Query: %s",
         osCommand.c_str());
 #endif
 
     poResult = PQexec(poConn, osCommand.c_str());
-    
-    if (poResult == NULL || 
+
+    if (poResult == NULL ||
         PQresultStatus(poResult) != PGRES_TUPLES_OK ||
         PQntuples(poResult) <= 0 ) {
-            
+
         PQclear(poResult);
 
         /**
-         * Maybe there is no primary key or unique constraint; a 
+         * Maybe there is no primary key or unique constraint; a
          * sequence will also suffice; get the first one
          **/
 
@@ -419,27 +417,27 @@ const char * PostGISRasterDataset::GetPrimaryKeyRef()
             "information_schema.columns as cols join "
             "information_schema.sequences as seqs on "
             "cols.column_default like '%%'||seqs.sequence_name||'%%' "
-            "where cols.table_schema = '%s' and cols.table_name = '%s'", 
+            "where cols.table_schema = '%s' and cols.table_name = '%s'",
             pszSchema, pszTable);
 
 #ifdef DEBUG_QUERY
-        CPLDebug("PostGIS_Raster", 
-            "PostGISRasterDataset::GetPrimaryKeyRef(): Query: %s", 
+        CPLDebug("PostGIS_Raster",
+            "PostGISRasterDataset::GetPrimaryKeyRef(): Query: %s",
             osCommand.c_str());
 #endif
 
         poResult = PQexec(poConn, osCommand.c_str());
 
-        if (poResult == NULL || 
+        if (poResult == NULL ||
             PQresultStatus(poResult) != PGRES_TUPLES_OK ||
             PQntuples(poResult) <= 0) {
 
-            CPLDebug("PostGIS_Raster", 
+            CPLDebug("PostGIS_Raster",
             "PostGISRasterDataset::GetPrimaryKeyRef(): Could not "
             "find a primary key or unique column on the specified "
             "table %s.%s. For better performance, creating a primary key on the table is advised.",
             pszSchema, pszTable);
-            
+
             pszPrimaryKeyName = NULL; // Just in case
 
         }
@@ -449,8 +447,8 @@ const char * PostGISRasterDataset::GetPrimaryKeyRef()
         }
 
     }
-    
-    // Ok, get the primary key        
+
+    // Ok, get the primary key
     else {
         pszPrimaryKeyName = CPLStrdup(PQgetvalue(poResult, 0, 0));
         bIsFastPK = true;
@@ -463,27 +461,26 @@ const char * PostGISRasterDataset::GetPrimaryKeyRef()
 
 
 /***********************************************************************
- * \brief Look for raster tables in database and store them as 
+ * \brief Look for raster tables in database and store them as
  * subdatasets
  *
- * If no table is provided in connection string, the driver looks for 
- * the existent raster tables in the schema given as argument. This 
- * argument, however, is optional. If a NULL value is provided, the 
- * driver looks for all raster tables in all schemas of the 
+ * If no table is provided in connection string, the driver looks for
+ * the existent raster tables in the schema given as argument. This
+ * argument, however, is optional. If a NULL value is provided, the
+ * driver looks for all raster tables in all schemas of the
  * user-provided database.
  *
- * NOTE: Permissions are managed by libpq. The driver only returns an 
- * error if an error is returned when trying to access to tables not 
+ * NOTE: Permissions are managed by libpq. The driver only returns an
+ * error if an error is returned when trying to access to tables not
  * allowed to the current user.
  **********************************************************************/
 GBool PostGISRasterDataset::BrowseDatabase(const char* pszCurrentSchema,
         const char* pszValidConnectionString) {
-            
-    /* Be careful! These 3 vars override the class ones! */
-    char* pszSchema = NULL;
-    char* pszTable = NULL;
-    char* pszColumn = NULL;
-    
+
+    char* l_pszSchema = NULL;
+    char* l_pszTable = NULL;
+    char* l_pszColumn = NULL;
+
     int i = 0;
     int nTuples = 0;
     PGresult * poResult = NULL;
@@ -503,12 +500,12 @@ GBool PostGISRasterDataset::BrowseDatabase(const char* pszCurrentSchema,
             "pg_type.typname = 'raster'");
 
         poResult = PQexec(poConn, osCommand.c_str());
-        if (poResult == NULL || 
+        if (poResult == NULL ||
             PQresultStatus(poResult) != PGRES_TUPLES_OK ||
             PQntuples(poResult) <= 0) {
-                    
+
             ReportError(CE_Failure, CPLE_AppDefined,
-                "Error browsing database for PostGIS Raster tables: %s", 
+                "Error browsing database for PostGIS Raster tables: %s",
                 PQerrorMessage(poConn));
             if (poResult != NULL)
                 PQclear(poResult);
@@ -519,27 +516,27 @@ GBool PostGISRasterDataset::BrowseDatabase(const char* pszCurrentSchema,
 
         nTuples = PQntuples(poResult);
         for (i = 0; i < nTuples; i++) {
-            pszSchema = PQgetvalue(poResult, i, 0);
-            pszTable = PQgetvalue(poResult, i, 1);
-            pszColumn = PQgetvalue(poResult, i, 2);
+            l_pszSchema = PQgetvalue(poResult, i, 0);
+            l_pszTable = PQgetvalue(poResult, i, 1);
+            l_pszColumn = PQgetvalue(poResult, i, 2);
 
             papszSubdatasets = CSLSetNameValue(papszSubdatasets,
                 CPLSPrintf("SUBDATASET_%d_NAME", (i + 1)),
                 CPLSPrintf("PG:%s schema=%s table=%s column=%s",
-                pszValidConnectionString, pszSchema, pszTable, 
-                pszColumn));
+                pszValidConnectionString, l_pszSchema, l_pszTable,
+                l_pszColumn));
 
             papszSubdatasets = CSLSetNameValue(papszSubdatasets,
                 CPLSPrintf("SUBDATASET_%d_DESC", (i + 1)),
-                CPLSPrintf("PostGIS Raster table at %s.%s (%s)", 
-                pszSchema, pszTable, pszColumn));
+                CPLSPrintf("PostGIS Raster table at %s.%s (%s)",
+                l_pszSchema, l_pszTable, l_pszColumn));
         }
 
         PQclear(poResult);
 
     }
         /***************************************************************
-         * Fetch all the schema's raster tables and store them as 
+         * Fetch all the schema's raster tables and store them as
          * subdatasets
          **************************************************************/
     else {
@@ -553,14 +550,14 @@ GBool PostGISRasterDataset::BrowseDatabase(const char* pszCurrentSchema,
             "pg_namespace.nspname = '%s'", pszCurrentSchema);
 
         poResult = PQexec(poConn, osCommand.c_str());
-        if (poResult == NULL || 
-            PQresultStatus(poResult) != PGRES_TUPLES_OK || 
+        if (poResult == NULL ||
+            PQresultStatus(poResult) != PGRES_TUPLES_OK ||
             PQntuples(poResult) <= 0) {
-                
+
             ReportError(CE_Failure, CPLE_AppDefined,
-                "Error browsing database for PostGIS Raster tables: %s", 
+                "Error browsing database for PostGIS Raster tables: %s",
                 PQerrorMessage(poConn));
-                
+
             if (poResult != NULL)
                 PQclear(poResult);
 
@@ -570,19 +567,19 @@ GBool PostGISRasterDataset::BrowseDatabase(const char* pszCurrentSchema,
 
         nTuples = PQntuples(poResult);
         for (i = 0; i < nTuples; i++) {
-            pszTable = PQgetvalue(poResult, i, 0);
-            pszColumn = PQgetvalue(poResult, i, 1);
+            l_pszTable = PQgetvalue(poResult, i, 0);
+            l_pszColumn = PQgetvalue(poResult, i, 1);
 
             papszSubdatasets = CSLSetNameValue(papszSubdatasets,
                 CPLSPrintf("SUBDATASET_%d_NAME", (i + 1)),
                 CPLSPrintf("PG:%s schema=%s table=%s column=%s",
-                pszValidConnectionString, pszCurrentSchema, pszTable, 
-                pszColumn));
+                pszValidConnectionString, pszCurrentSchema, l_pszTable,
+                l_pszColumn));
 
             papszSubdatasets = CSLSetNameValue(papszSubdatasets,
                 CPLSPrintf("SUBDATASET_%d_DESC", (i + 1)),
-                CPLSPrintf("PostGIS Raster table at %s.%s (%s)", 
-                pszCurrentSchema, pszTable, pszColumn));
+                CPLSPrintf("PostGIS Raster table at %s.%s (%s)",
+                pszCurrentSchema, l_pszTable, l_pszColumn));
         }
 
         PQclear(poResult);
@@ -600,27 +597,27 @@ PROverview * PostGISRasterDataset::GetOverviewTables(int * pnOverviews)
     PROverview * poOV = NULL;
     CPLString osCommand;
     PGresult * poResult = NULL;
-    
+
     osCommand.Printf("SELECT o_table_name, overview_factor, "
             "o_raster_column, o_table_schema FROM raster_overviews "
             "WHERE r_table_schema = '%s' AND r_table_name = '%s' AND "
-            "r_raster_column = '%s' ORDER BY overview_factor", this->pszSchema, this->pszTable, 
+            "r_raster_column = '%s' ORDER BY overview_factor", this->pszSchema, this->pszTable,
             this->pszColumn);
 
 #ifdef DEBUG_QUERY
-    CPLDebug("PostGIS_Raster", 
-        "PostGISRasterDataset::GetOverviewTables(): Query: %s", 
+    CPLDebug("PostGIS_Raster",
+        "PostGISRasterDataset::GetOverviewTables(): Query: %s",
         osCommand.c_str());
 #endif
 
     poResult = PQexec(poConn, osCommand.c_str());
 
-    if (poResult == NULL || 
+    if (poResult == NULL ||
         PQresultStatus(poResult) != PGRES_TUPLES_OK ||
         PQntuples(poResult) < 0) {
-        
-        ReportError(CE_Failure, CPLE_AppDefined, 
-            "Error looking for overview tables: %s", 
+
+        ReportError(CE_Failure, CPLE_AppDefined,
+            "Error looking for overview tables: %s",
             PQerrorMessage(poConn));
 
         if (poResult)
@@ -628,51 +625,51 @@ PROverview * PostGISRasterDataset::GetOverviewTables(int * pnOverviews)
 
         return NULL;
     }
-    
+
     else if (PQntuples(poResult) == 0) {
-        CPLDebug("PostGIS_Raster", 
-            "PostGISRasterDataset::GetOverviewTables(): No overviews " 
+        CPLDebug("PostGIS_Raster",
+            "PostGISRasterDataset::GetOverviewTables(): No overviews "
             "for table %s.%s", pszTable, pszSchema);
-        
+
         if (poResult)
             PQclear(poResult);
 
         return NULL;
     }
-    
+
     int nTuples = PQntuples(poResult);
-    
+
     poOV = (PROverview *)VSIMalloc2(nTuples, sizeof(PROverview));
     if (poOV == NULL) {
-        ReportError(CE_Failure, CPLE_AppDefined, 
+        ReportError(CE_Failure, CPLE_AppDefined,
             "Error looking for overview tables");
-        
+
         PQclear(poResult);
-        
+
         return NULL;
     }
-    
+
     int iOVerview = 0;
     for(iOVerview = 0; iOVerview < nTuples; iOVerview++) {
-        poOV[iOVerview].pszSchema = 
+        poOV[iOVerview].pszSchema =
             CPLStrdup(PQgetvalue(poResult, iOVerview, 3));
-            
+
         poOV[iOVerview].pszTable =
             CPLStrdup(PQgetvalue(poResult, iOVerview, 0));
-            
-        poOV[iOVerview].pszColumn = 
+
+        poOV[iOVerview].pszColumn =
             CPLStrdup(PQgetvalue(poResult, iOVerview, 2));
-            
-        poOV[iOVerview].nFactor = 
+
+        poOV[iOVerview].nFactor =
             atoi(PQgetvalue(poResult, iOVerview, 1));
-    
+
     }
-    
+
     if (pnOverviews)
         *pnOverviews = nTuples;
-    
+
     PQclear(poResult);
-    
+
     return poOV;
 }
 
@@ -711,7 +708,7 @@ void PostGISRasterDataset::BuildOverviews()
             poOvrDS->pszWhere = pszWhere ? CPLStrdup(pszWhere) : NULL;
             poOvrDS->poParentDS = this;
 
-            if (!CSLTestBoolean(CPLGetConfigOption("PG_DIFFERED_OVERVIEWS", "YES")) &&
+            if (!CPLTestBool(CPLGetConfigOption("PG_DEFERRED_OVERVIEWS", "YES")) &&
                 (!poOvrDS->SetRasterProperties(NULL) ||
                 poOvrDS->GetRasterCount() != GetRasterCount()))
             {
@@ -745,12 +742,12 @@ PostGISRasterDataset* PostGISRasterDataset::GetOverviewDS(int iOvr)
         return NULL;
     return papoOverviewDS[iOvr];
 }
- 
+
 /***********************************************************************
- * \brief Calculates the destination window for a VRT source, taking 
- * into account that the source is a PostGIS Raster tile and the 
+ * \brief Calculates the destination window for a VRT source, taking
+ * into account that the source is a PostGIS Raster tile and the
  * destination is the general dataset itself
- * 
+ *
  * This method is adapted from gdalbuildvrt as is in GDAL 1.10.0
 ***********************************************************************/
 GBool PostGISRasterDataset::GetDstWin(
@@ -759,27 +756,27 @@ GBool PostGISRasterDataset::GetDstWin(
 {
     double we_res = this->adfGeoTransform[GEOTRSFRM_WE_RES];
     double ns_res = this->adfGeoTransform[GEOTRSFRM_NS_RES];
-    
+
     double adfTileGeoTransform[6];
     psDP->GetGeoTransform(adfTileGeoTransform);
-    
+
     *pnDstXOff = (int)
         (0.5 + (adfTileGeoTransform[GEOTRSFRM_TOPLEFT_X] - xmin) / we_res);
-    
+
     if( ns_res < 0 )
         *pnDstYOff = (int)
             (0.5 + (ymax - adfTileGeoTransform[GEOTRSFRM_TOPLEFT_Y]) / -ns_res);
     else
         *pnDstYOff = (int)
             (0.5 + (adfTileGeoTransform[GEOTRSFRM_TOPLEFT_Y] - ymin) / ns_res);
-    
+
     *pnDstXSize = (int)
         (0.5 + psDP->GetRasterXSize() *
          adfTileGeoTransform[GEOTRSFRM_WE_RES] / we_res);
     *pnDstYSize = (int)
         (0.5 + psDP->GetRasterYSize() *
          adfTileGeoTransform[GEOTRSFRM_NS_RES] / ns_res);
-         
+
     return true;
 }
 
@@ -801,12 +798,12 @@ GBool PostGISRasterDataset::AddComplexSource(PostGISRasterTileDataset* poRTDS)
         return false;
 
 #ifdef DEBUG_VERBOSE
-    CPLDebug("PostGIS_Raster", 
+    CPLDebug("PostGIS_Raster",
         "PostGISRasterDataset::AddComplexSource: "
         "Tile bounding box from (%d, %d) of size (%d, %d) will "
         "cover raster bounding box from (%d, %d) of size "
-        "(%d, %d)", 0, 0, 
-        poRTDS->GetRasterXSize(), 
+        "(%d, %d)", 0, 0,
+        poRTDS->GetRasterXSize(),
         poRTDS->GetRasterYSize(),
         nDstXOff, nDstYOff, nDstXSize, nDstYSize);
 #endif
@@ -814,17 +811,17 @@ GBool PostGISRasterDataset::AddComplexSource(PostGISRasterTileDataset* poRTDS)
     // Add tiles bands as sources for the raster bands
     for(int iBand = 0; iBand < nBandsToCreate; iBand++)
     {
-        PostGISRasterRasterBand * prb = 
+        PostGISRasterRasterBand * prb =
             (PostGISRasterRasterBand *)GetRasterBand(iBand + 1);
 
         int bHasNoData = FALSE;
         double dfBandNoDataValue = prb->GetNoDataValue(&bHasNoData);
-            
+
         PostGISRasterTileRasterBand * prtb =
             (PostGISRasterTileRasterBand *)
                 poRTDS->GetRasterBand(iBand + 1);
-            
-        prb->AddComplexSource(prtb, 0, 0, 
+
+        prb->AddComplexSource(prtb, 0, 0,
             poRTDS->GetRasterXSize(),
             poRTDS->GetRasterYSize(),
             nDstXOff, nDstYOff, nDstXSize, nDstYSize,
@@ -833,7 +830,7 @@ GBool PostGISRasterDataset::AddComplexSource(PostGISRasterTileDataset* poRTDS)
 
         prtb->poSource = prb->papoSources[prb->nSources-1];
     }
-    
+
     return true;
 }
 
@@ -844,20 +841,20 @@ GBool PostGISRasterDataset::AddComplexSource(PostGISRasterTileDataset* poRTDS)
 /**
  * \brief Get the tile dataset that matches the given upper left pixel
  **/
-PostGISRasterTileDataset * 
+PostGISRasterTileDataset *
     PostGISRasterDataset::GetMatchingSourceRef(double dfUpperLeftX,
                                                double dfUpperLeftY)
 {
     int i;
     PostGISRasterTileDataset * poRTDS = NULL;
 
-    for(i = 0; i < nTiles; i++)
+    for(i = 0; i < m_nTiles; i++)
     {
         poRTDS = papoSourcesHolders[i];
 
-        if (CPLIsEqual(poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_X], 
+        if (CPLIsEqual(poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_X],
                 dfUpperLeftX) &&
-            CPLIsEqual(poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_Y], 
+            CPLIsEqual(poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_Y],
                 dfUpperLeftY)) {
 
             return poRTDS;
@@ -884,18 +881,18 @@ void PostGISRasterDataset::CacheTile(const char* pszMetadata,
 
     // Skip first "("
     char* pszFilteredRes = pszRes + 1;
-    
+
     // Skip last ")"
     pszFilteredRes[strlen(pszFilteredRes)-1] = '\0';
-    
+
     // Tokenize
-    char** papszParams = 
-        CSLTokenizeString2(pszFilteredRes, ",", 
+    char** papszParams =
+        CSLTokenizeString2(pszFilteredRes, ",",
             CSLT_HONOURSTRINGS | CSLT_ALLOWEMPTYTOKENS);
     CPLAssert(CSLCount(papszParams) >= ELEMENTS_OF_METADATA_RECORD);
-    
+
     CPLFree(pszRes);
-    
+
     double dfTilePixelSizeX = CPLAtof(papszParams[POS_UPPERLEFTX]);
     double dfTilePixelSizeY = CPLAtof(papszParams[POS_UPPERLEFTY]);
     int nTileXSize = atoi(papszParams[POS_WIDTH]);
@@ -908,12 +905,12 @@ void PostGISRasterDataset::CacheTile(const char* pszMetadata,
         * Get actual raster band data
         **/
     int nBandDataTypeSize = GDALGetDataTypeSize(GetRasterBand(nBand)->GetRasterDataType()) / 8;
-    int nExpectedBandDataSize = 
+    int nExpectedBandDataSize =
         nTileXSize * nTileYSize * nBandDataTypeSize;
 
     int nWKBLength = 0;
     GByte* pbyData = CPLHexToBinary(pszRaster, &nWKBLength);
-        
+
     int nExpectedBands = bAllBandCaching ? GetRasterCount() : 1;
     int nExpectedWKBLength = RASTER_HEADER_SIZE + BAND_SIZE(nBandDataTypeSize, nExpectedBandDataSize) * nExpectedBands;
     if( nWKBLength != nExpectedWKBLength )
@@ -935,7 +932,7 @@ void PostGISRasterDataset::CacheTile(const char* pszMetadata,
     if( GetPrimaryKeyRef() != NULL )
         poRTDS = GetMatchingSourceRef(pszPKID);
     else
-        poRTDS = GetMatchingSourceRef(dfTilePixelSizeX, 
+        poRTDS = GetMatchingSourceRef(dfTilePixelSizeX,
                                       dfTilePixelSizeY);
     if( poRTDS == NULL )
     {
@@ -945,7 +942,7 @@ void PostGISRasterDataset::CacheTile(const char* pszMetadata,
 
     for(int k=1; k <= nExpectedBands; k++)
     {
-        GByte* pbyDataToRead = (GByte*)GET_BAND_DATA(pbyData, k, 
+        GByte* pbyDataToRead = (GByte*)GET_BAND_DATA(pbyData, k,
                 nBandDataTypeSize, nExpectedBandDataSize);
 
         if( bSwap && nBandDataTypeSize > 1 )
@@ -966,7 +963,7 @@ void PostGISRasterDataset::CacheTile(const char* pszMetadata,
         GDALRasterBand * poRTB = poRTDS->GetRasterBand(nCurBand);
 
         /**
-        * Manually add each tile data to the cache of the 
+        * Manually add each tile data to the cache of the
         * matching PostGISRasterTileRasterBand.
         **/
         if (poRTB)
@@ -975,7 +972,7 @@ void PostGISRasterDataset::CacheTile(const char* pszMetadata,
             if( poBlock != NULL )
             {
                 // Point block data ref to fetched data
-                memcpy(poBlock->GetDataRef(), (void *)pbyDataToRead, 
+                memcpy(poBlock->GetDataRef(), (void *)pbyDataToRead,
                     nExpectedBandDataSize);
 
                 poBlock->DropLock();
@@ -1008,7 +1005,7 @@ GBool PostGISRasterDataset::LoadSources(int nXOff, int nYOff, int nXSize, int nY
     else
     {
         double adfProjWin[8];
-        PolygonFromCoords(nXOff, nYOff, nXOff + nXSize, nYOff + nYSize, adfProjWin); 
+        PolygonFromCoords(nXOff, nYOff, nXOff + nXSize, nYOff + nYSize, adfProjWin);
         osSpatialFilter.Printf("%s && "
                         "ST_GeomFromText('POLYGON((%.18f %.18f,%.18f %.18f,%.18f %.18f,%.18f %.18f,%.18f %.18f))') ",
                         //"AND ST_Intersects(%s, ST_GeomFromEWKT('SRID=%d;POLYGON((%.18f %.18f,%.18f %.18f,%.18f %.18f,%.18f %.18f,%.18f %.18f))'))",
@@ -1029,7 +1026,7 @@ GBool PostGISRasterDataset::LoadSources(int nXOff, int nYOff, int nXSize, int nY
     int bLoadRasters = FALSE;
     int bAllBandCaching = FALSE;
 
-    if( nTiles > 0 && !bFetchAll )
+    if( m_nTiles > 0 && !bFetchAll )
     {
         osCommand.Printf("SELECT %s FROM %s.%s",
                         pszPrimaryKeyName, pszSchema, pszTable);
@@ -1041,29 +1038,29 @@ GBool PostGISRasterDataset::LoadSources(int nXOff, int nYOff, int nXSize, int nY
         poResult = PQexec(poConn, osCommand.c_str());
 
     #ifdef DEBUG_QUERY
-        CPLDebug("PostGIS_Raster", 
-            "PostGISRasterDataset::LoadSources(): Query = \"%s\" --> number of rows = %d", 
+        CPLDebug("PostGIS_Raster",
+            "PostGISRasterDataset::LoadSources(): Query = \"%s\" --> number of rows = %d",
             osCommand.c_str(), poResult ? PQntuples(poResult) : 0 );
     #endif
 
-        if (poResult == NULL || 
-            PQresultStatus(poResult) != PGRES_TUPLES_OK || 
+        if (poResult == NULL ||
+            PQresultStatus(poResult) != PGRES_TUPLES_OK ||
             PQntuples(poResult) < 0) {
 
             if (poResult)
                 PQclear(poResult);
-        
-            CPLError(CE_Failure, CPLE_AppDefined, 
-                "PostGISRasterDataset::LoadSources(): %s", 
+
+            CPLError(CE_Failure, CPLE_AppDefined,
+                "PostGISRasterDataset::LoadSources(): %s",
                 PQerrorMessage(poConn));
 
-            return false;  
+            return false;
         }
 
         if( bTilesSameDimension && nBand > 0 )
         {
-            GIntBig nMemoryRequiredForTiles = PQntuples(poResult) * nTileWidth * nTileHeight *
-                GDALGetDataTypeSize(GetRasterBand(nBand)->GetRasterDataType()) / 8;
+            GIntBig nMemoryRequiredForTiles = static_cast<GIntBig>(PQntuples(poResult)) * nTileWidth * nTileHeight *
+                (GDALGetDataTypeSize(GetRasterBand(nBand)->GetRasterDataType()) / 8);
             GIntBig nCacheMax = (GIntBig) GDALGetCacheMax64();
             if( nBands * nMemoryRequiredForTiles <= nCacheMax )
             {
@@ -1086,7 +1083,7 @@ GBool PostGISRasterDataset::LoadSources(int nXOff, int nYOff, int nXSize, int nY
                 bFetchTile = TRUE;
             else if( bLoadRasters )
             {
-                PostGISRasterTileRasterBand* poTileBand = 
+                PostGISRasterTileRasterBand* poTileBand =
                     (PostGISRasterTileRasterBand *)poTile->GetRasterBand(nBand);
                 if( !poTileBand->IsCached() )
                     bFetchTile = TRUE;
@@ -1134,23 +1131,23 @@ GBool PostGISRasterDataset::LoadSources(int nXOff, int nYOff, int nXSize, int nY
         poResult = PQexec(poConn, osCommand.c_str());
 
 #ifdef DEBUG_QUERY
-        CPLDebug("PostGIS_Raster", 
-            "PostGISRasterDataset::LoadSources(): Query = \"%s\" --> number of rows = %d", 
+        CPLDebug("PostGIS_Raster",
+            "PostGISRasterDataset::LoadSources(): Query = \"%s\" --> number of rows = %d",
             osCommand.c_str(), poResult ? PQntuples(poResult) : 0 );
 #endif
 
-        if (poResult == NULL || 
-            PQresultStatus(poResult) != PGRES_TUPLES_OK || 
+        if (poResult == NULL ||
+            PQresultStatus(poResult) != PGRES_TUPLES_OK ||
             PQntuples(poResult) < 0) {
 
             if (poResult)
                 PQclear(poResult);
-    
-            CPLError(CE_Failure, CPLE_AppDefined, 
-                "PostGISRasterDataset::LoadSources(): %s", 
+
+            CPLError(CE_Failure, CPLE_AppDefined,
+                "PostGISRasterDataset::LoadSources(): %s",
                 PQerrorMessage(poConn));
 
-            return false;  
+            return false;
         }
 
         for(int i=0;i<PQntuples(poResult);i++)
@@ -1169,8 +1166,8 @@ GBool PostGISRasterDataset::LoadSources(int nXOff, int nYOff, int nXSize, int nY
                     {
                         oMapPKIDToRTDS[poRTDS->pszPKID] = poRTDS;
                         papoSourcesHolders = (PostGISRasterTileDataset**)
-                            CPLRealloc(papoSourcesHolders, sizeof(PostGISRasterTileDataset*) * (nTiles + 1));
-                        papoSourcesHolders[nTiles ++] = poRTDS;
+                            CPLRealloc(papoSourcesHolders, sizeof(PostGISRasterTileDataset*) * (m_nTiles + 1));
+                        papoSourcesHolders[m_nTiles ++] = poRTDS;
                         CPLQuadTreeInsert(hQuadTree, poRTDS);
                     }
                     else
@@ -1190,18 +1187,18 @@ GBool PostGISRasterDataset::LoadSources(int nXOff, int nYOff, int nXSize, int nY
 
         PQclear(poResult);
     }
-    
+
     // If we have fetched the surface of all the dataset, then all sources have
     // been built, and we don't need to do a spatial query on following IRasterIO() calls
     if( bFetchAll )
         bBuildQuadTreeDynamically = false;
-    
+
     return true;
 }
 
 /***********************************************************************
  * \brief Get some useful metadata for all bands
- * 
+ *
  * The allocated memory is responsibility of the caller
  **********************************************************************/
 BandMetadata * PostGISRasterDataset::GetBandsMetadata(int * pnBands)
@@ -1212,139 +1209,136 @@ BandMetadata * PostGISRasterDataset::GetBandsMetadata(int * pnBands)
     char * pszRes = NULL;
     char * pszFilteredRes = NULL;
     char ** papszParams = NULL;
-        
+
     if (pszWhere == NULL) {
         osCommand.Printf("select st_bandmetadata(%s, band) from "
         "(select %s, generate_series(1, st_numbands(%s)) band from "
         "(select %s from %s.%s limit 1) bar) foo", pszColumn, pszColumn,
         pszColumn, pszColumn, pszSchema, pszTable);
-    } 
+    }
 
     else {
         osCommand.Printf("select st_bandmetadata(%s, band) from "
         "(select %s, generate_series(1, st_numbands(%s)) band from "
-        "(select %s from %s.%s where %s limit 1) bar) foo", pszColumn, 
+        "(select %s from %s.%s where %s limit 1) bar) foo", pszColumn,
         pszColumn, pszColumn, pszColumn, pszSchema, pszTable, pszWhere);
     }
-    
+
 #ifdef DEBUG_QUERY
-    CPLDebug("PostGIS_Raster", 
-        "PostGISRasterDataset::GetBandsMetadata(): Query: %s", 
+    CPLDebug("PostGIS_Raster",
+        "PostGISRasterDataset::GetBandsMetadata(): Query: %s",
         osCommand.c_str());
 #endif
 
     poResult = PQexec(poConn, osCommand.c_str());
     /* Error getting info from database */
-    if (poResult == NULL || 
+    if (poResult == NULL ||
         PQresultStatus(poResult) != PGRES_TUPLES_OK ||
         PQntuples(poResult) <= 0) {
-        
-        ReportError(CE_Failure, CPLE_AppDefined, 
+
+        ReportError(CE_Failure, CPLE_AppDefined,
             "Error getting band metadata while creating raster "
             "bands");
-            
-        CPLDebug("PostGIS_Raster", 
-            "PostGISRasterDataset::GetBandsMetadata(): %s", 
+
+        CPLDebug("PostGIS_Raster",
+            "PostGISRasterDataset::GetBandsMetadata(): %s",
             PQerrorMessage(poConn));
-        
+
         if (poResult)
             PQclear(poResult);
 
         return NULL;
     }
-    
+
     // Matches nBands
     int nTuples = PQntuples(poResult);
-    
-    poBMD = (BandMetadata *)VSIMalloc2(nTuples, sizeof(BandMetadata));
+
+    poBMD = (BandMetadata *)VSI_MALLOC2_VERBOSE(nTuples, sizeof(BandMetadata));
     if (poBMD == NULL) {
-        ReportError(CE_Failure, CPLE_OutOfMemory, 
-            "Out of memory getting metadata from bands");
-            
         PQclear(poResult);
-        
+
         return NULL;
     }
-    
+
 
     int iBand = 0;
-    
+
     for(iBand = 0; iBand < nTuples; iBand++) {
-    
+
         // Get metadata record
         pszRes = CPLStrdup(PQgetvalue(poResult, iBand, 0));
-        
+
         // Skip first "("
         pszFilteredRes = pszRes + 1;
-        
+
         // Skip last ")"
         pszFilteredRes[strlen(pszFilteredRes)-1] = '\0';
-        
+
         // Tokenize
-        papszParams = 
+        papszParams =
             CSLTokenizeString2(pszFilteredRes, ",", CSLT_HONOURSTRINGS | CSLT_ALLOWEMPTYTOKENS);
         CPLAssert(CSLCount(papszParams) >= ELEMENTS_OF_BAND_METADATA_RECORD);
-        
+
         CPLFree(pszRes);
-        
+
         // If the band doesn't have nodata, NULL is returned as nodata
-        TranslateDataType(papszParams[POS_PIXELTYPE], 
+        TranslateDataType(papszParams[POS_PIXELTYPE],
             &(poBMD[iBand].eDataType), &(poBMD[iBand].nBitsDepth),
             &(poBMD[iBand].bSignedByte));
-            
+
         if (papszParams[POS_NODATAVALUE] == NULL ||
-            EQUALN(papszParams[POS_NODATAVALUE], "NULL", 4*sizeof(char)) || 
-            EQUALN(papszParams[POS_NODATAVALUE], "f", sizeof(char)) || 
+            EQUAL(papszParams[POS_NODATAVALUE], "NULL") ||
+            EQUAL(papszParams[POS_NODATAVALUE], "f") ||
             EQUAL(papszParams[POS_NODATAVALUE], "")) {
-        
+
             poBMD[iBand].bHasNoDataValue = false;
             poBMD[iBand].dfNoDataValue = CPLAtof(NO_VALID_RES);
         }
-        
+
         else {
             poBMD[iBand].bHasNoDataValue = true;
-            poBMD[iBand].dfNoDataValue = 
+            poBMD[iBand].dfNoDataValue =
                 CPLAtof(papszParams[POS_NODATAVALUE]);
         }
-        
+
         // TODO: Manage outdb and get path
         poBMD[iBand].bIsOffline = (papszParams[POS_ISOUTDB] != NULL) ?
-            EQUALN(papszParams[POS_ISOUTDB], "t", sizeof(char)) :
+            EQUAL(papszParams[POS_ISOUTDB], "t") :
             false;
-        
+
         CSLDestroy(papszParams);
-    }   
-    
+    }
+
     if (pnBands)
         *pnBands = nTuples;
-    
+
     PQclear(poResult);
-    
-    return poBMD; 
-    
+
+    return poBMD;
+
 }
 
 /***********************************************************************
  * \brief Function to get the bounding box of each element inserted in
  * the QuadTree index
  **********************************************************************/
-static void GetTileBoundingBox(const void *hFeature, 
+static void GetTileBoundingBox(const void *hFeature,
     CPLRectObj * pBounds)
 {
-    PostGISRasterTileDataset * poRTD = 
+    PostGISRasterTileDataset * poRTD =
         (PostGISRasterTileDataset *)hFeature;
-        
+
     double adfTileGeoTransform[6];
     poRTD->GetGeoTransform(adfTileGeoTransform);
-    
+
     int nTileWidth = poRTD->GetRasterXSize();
     int nTileHeight = poRTD->GetRasterYSize();
-    
+
     pBounds->minx = adfTileGeoTransform[GEOTRSFRM_TOPLEFT_X];
     pBounds->maxx = adfTileGeoTransform[GEOTRSFRM_TOPLEFT_X] +
          nTileWidth *
          adfTileGeoTransform[GEOTRSFRM_WE_RES];
-    
+
     if (adfTileGeoTransform[GEOTRSFRM_NS_RES] >= 0.0) {
         pBounds->miny = adfTileGeoTransform[GEOTRSFRM_TOPLEFT_Y];
         pBounds->maxy = adfTileGeoTransform[GEOTRSFRM_TOPLEFT_Y] +
@@ -1357,7 +1351,7 @@ static void GetTileBoundingBox(const void *hFeature,
             nTileHeight *
             adfTileGeoTransform[GEOTRSFRM_NS_RES];
     }
-    
+
 #ifdef DEBUG_VERBOSE
     CPLDebug("PostGIS_Raster", "TileBoundingBox minx=%f miny=%f maxx=%f maxy=%f adfTileGeoTransform[GEOTRSFRM_NS_RES]=%f",
              pBounds->minx, pBounds->miny, pBounds->maxx, pBounds->maxy, adfTileGeoTransform[GEOTRSFRM_NS_RES]);
@@ -1379,42 +1373,43 @@ PostGISRasterTileDataset* PostGISRasterDataset::BuildRasterTileDataset(const cha
 
     // Skip first "("
     char* pszFilteredRes = pszRes + 1;
-    
+
     // Skip last ")"
     pszFilteredRes[strlen(pszFilteredRes)-1] = '\0';
-    
+
     // Tokenize
-    char** papszParams = 
-        CSLTokenizeString2(pszFilteredRes, ",", 
+    char** papszParams =
+        CSLTokenizeString2(pszFilteredRes, ",",
             CSLT_HONOURSTRINGS | CSLT_ALLOWEMPTYTOKENS);
     CPLAssert(CSLCount(papszParams) >= ELEMENTS_OF_METADATA_RECORD);
 
     CPLFree(pszRes);
-    
+
     double tileSkewX = CPLAtof(papszParams[POS_SKEWX]);
     double tileSkewY = CPLAtof(papszParams[POS_SKEWY]);
 
     // Rotated rasters are not allowed, so far
     // TODO: allow them
-    if (!CPLIsEqual(tileSkewX, 0.0) || 
+    if (!CPLIsEqual(tileSkewX, 0.0) ||
         !CPLIsEqual(tileSkewY, 0.0)) {
-        
-        ReportError(CE_Failure, CPLE_AppDefined, 
+
+        ReportError(CE_Failure, CPLE_AppDefined,
             "GDAL PostGIS Raster driver can not work with "
             "rotated rasters yet.");
 
+        CSLDestroy(papszParams);
         return NULL;
     }
 
-    int nTileWidth = atoi(papszParams[POS_WIDTH]);
-    int nTileHeight = atoi(papszParams[POS_HEIGHT]);
+    int l_nTileWidth = atoi(papszParams[POS_WIDTH]);
+    int l_nTileHeight = atoi(papszParams[POS_HEIGHT]);
 
     /**
         * Now, construct a PostGISRasterTileDataset, and add
         * its bands as sources for the general raster bands
         **/
     int nTileBands = atoi(papszParams[POS_NBANDS]);
-    
+
         /**
         * If the source doesn't have the same number of bands than
         * the raster band, is discarded
@@ -1429,40 +1424,40 @@ PostGISRasterTileDataset* PostGISRasterDataset::BuildRasterTileDataset(const cha
 
         return NULL;
     }
-    
+
     PostGISRasterTileDataset* poRTDS =
-        new PostGISRasterTileDataset(this, nTileWidth, nTileHeight);
-    
+        new PostGISRasterTileDataset(this, l_nTileWidth, l_nTileHeight);
+
     if (GetPrimaryKeyRef() != NULL)
     {
         poRTDS->pszPKID = CPLStrdup(pszPKID);
     }
-    
+
     poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_X]=
         CPLAtof(papszParams[POS_UPPERLEFTX]);
-        
+
     poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_Y]=
         CPLAtof(papszParams[POS_UPPERLEFTY]);
 
     poRTDS->adfGeoTransform[GEOTRSFRM_WE_RES]=
         CPLAtof(papszParams[POS_SCALEX]);
-        
+
     poRTDS->adfGeoTransform[GEOTRSFRM_NS_RES]=
         CPLAtof(papszParams[POS_SCALEY]);
- 
+
     // TODO: outdb bands should be handled. Not a priority.
     for(int j = 0; j < nTileBands; j++) {
-        
+
         // Create band
         poRTDS->SetBand(j + 1,
             new PostGISRasterTileRasterBand(
                 poRTDS,
-                j + 1, (poBandMetaData ) ? poBandMetaData[j].eDataType : GetRasterBand(j+1)->GetRasterDataType(), 
+                j + 1, (poBandMetaData ) ? poBandMetaData[j].eDataType : GetRasterBand(j+1)->GetRasterDataType(),
                 (poBandMetaData ) ? poBandMetaData[j].bIsOffline : FALSE));
     }
-    
+
     CSLDestroy(papszParams);
-    
+
     return poRTDS;
 }
 
@@ -1478,49 +1473,49 @@ void PostGISRasterDataset::UpdateGlobalResolutionWithTileResolution(
     if (resolutionStrategy == AVERAGE_RESOLUTION ||
         resolutionStrategy == AVERAGE_APPROX_RESOLUTION) {
         adfGeoTransform[GEOTRSFRM_WE_RES] += tilePixelSizeX;
-        adfGeoTransform[GEOTRSFRM_NS_RES] += tilePixelSizeY; 
+        adfGeoTransform[GEOTRSFRM_NS_RES] += tilePixelSizeY;
     }
 
     else if (resolutionStrategy == HIGHEST_RESOLUTION)  {
-        adfGeoTransform[GEOTRSFRM_WE_RES] = 
-            MIN(adfGeoTransform[GEOTRSFRM_WE_RES], 
+        adfGeoTransform[GEOTRSFRM_WE_RES] =
+            MIN(adfGeoTransform[GEOTRSFRM_WE_RES],
                 tilePixelSizeX);
 
         /**
-            * Yes : as ns_res is negative, the highest resolution 
+            * Yes : as ns_res is negative, the highest resolution
             * is the max value.
-            * 
-            * Negative tilePixelSizeY means that the coords origin 
-            * is in top left corner. This is not the common 
-            * situation. Most image files store data from top to 
-            * bottom, while the projected coordinate systems 
-            * utilize traditional Cartesian coordinates with the 
-            * origin in the conventional lower-left corner (bottom 
-            * to top). For that reason, this parameter is normally 
+            *
+            * Negative tilePixelSizeY means that the coords origin
+            * is in top left corner. This is not the common
+            * situation. Most image files store data from top to
+            * bottom, while the projected coordinate systems
+            * utilize traditional Cartesian coordinates with the
+            * origin in the conventional lower-left corner (bottom
+            * to top). For that reason, this parameter is normally
             * negative.
             **/
         if (tilePixelSizeY < 0.0)
-            adfGeoTransform[GEOTRSFRM_NS_RES] = 
-                MAX(adfGeoTransform[GEOTRSFRM_NS_RES], 
+            adfGeoTransform[GEOTRSFRM_NS_RES] =
+                MAX(adfGeoTransform[GEOTRSFRM_NS_RES],
                 tilePixelSizeY);
         else
-            adfGeoTransform[GEOTRSFRM_NS_RES] = 
-                MIN(adfGeoTransform[GEOTRSFRM_NS_RES], 
-                tilePixelSizeY);                                        
+            adfGeoTransform[GEOTRSFRM_NS_RES] =
+                MIN(adfGeoTransform[GEOTRSFRM_NS_RES],
+                tilePixelSizeY);
     }
 
     else if (resolutionStrategy == LOWEST_RESOLUTION) {
-        adfGeoTransform[GEOTRSFRM_WE_RES] = 
-            MAX(adfGeoTransform[GEOTRSFRM_WE_RES], 
+        adfGeoTransform[GEOTRSFRM_WE_RES] =
+            MAX(adfGeoTransform[GEOTRSFRM_WE_RES],
                 tilePixelSizeX);
 
         if (tilePixelSizeY < 0.0)
-            adfGeoTransform[GEOTRSFRM_NS_RES] = 
-                MIN(adfGeoTransform[GEOTRSFRM_NS_RES], 
+            adfGeoTransform[GEOTRSFRM_NS_RES] =
+                MIN(adfGeoTransform[GEOTRSFRM_NS_RES],
                 tilePixelSizeY);
-        else    
-            adfGeoTransform[GEOTRSFRM_NS_RES] = 
-                MAX(adfGeoTransform[GEOTRSFRM_NS_RES], 
+        else
+            adfGeoTransform[GEOTRSFRM_NS_RES] =
+                MAX(adfGeoTransform[GEOTRSFRM_NS_RES],
                 tilePixelSizeY);
     }
 
@@ -1533,37 +1528,37 @@ void PostGISRasterDataset::BuildBands(BandMetadata * poBandMetaData,
                                       int nBandsFetched)
 {
 #ifdef DEBUG_VERBOSE
-    CPLDebug("PostGIS_Raster", 
+    CPLDebug("PostGIS_Raster",
         "PostGISRasterDataset::ConstructOneDatasetFromTiles: "
         "Now constructing the raster dataset bands");
 #endif
-        
+
     int iBand;
     for (iBand = 0; iBand < nBandsFetched; iBand++) {
-            
-        SetBand(iBand + 1, new PostGISRasterRasterBand(this, iBand + 1, 
-            poBandMetaData[iBand].eDataType, 
-            poBandMetaData[iBand].bHasNoDataValue, 
-            poBandMetaData[iBand].dfNoDataValue, 
+
+        SetBand(iBand + 1, new PostGISRasterRasterBand(this, iBand + 1,
+            poBandMetaData[iBand].eDataType,
+            poBandMetaData[iBand].bHasNoDataValue,
+            poBandMetaData[iBand].dfNoDataValue,
             poBandMetaData[iBand].bIsOffline));
-        
+
         // Set some band metadata items
         GDALRasterBand * b = GetRasterBand(iBand + 1);
-        
+
         if (poBandMetaData[iBand].bSignedByte) {
             b->SetMetadataItem(
                 "PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" );
         }
-        
+
         if (poBandMetaData[iBand].nBitsDepth < 8) {
             b->SetMetadataItem(
-            "NBITS", CPLString().Printf( "%d", 
+            "NBITS", CPLString().Printf( "%d",
                 poBandMetaData[iBand].nBitsDepth ),
             "IMAGE_STRUCTURE" );
         }
-        
+
 #ifdef DEBUG_VERBOSE
-        CPLDebug("PostGIS_Raster", 
+        CPLDebug("PostGIS_Raster",
             "PostGISRasterDataset::ConstructOneDatasetFromTiles: "
             "Band %d built", iBand + 1);
 #endif
@@ -1572,12 +1567,12 @@ void PostGISRasterDataset::BuildBands(BandMetadata * poBandMetaData,
 
 /***********************************************************************
  * \brief Construct just one dataset from all the results fetched.
- * 
- * This method is not very elegant. It's strongly attached to 
+ *
+ * This method is not very elegant. It's strongly attached to
  * SetRasterProperties (it assumes poResult is not NULL, and the actual
  * results are stored at fixed positions). I just did it to avoid a
  * huge SetRasterProperties method.
- * 
+ *
  * I know, this could be avoided in a better way. Like implementing a
  * wrapper to raise queries and get results without all the checking
  * overhead. I'd like to do it, someday...
@@ -1585,112 +1580,111 @@ void PostGISRasterDataset::BuildBands(BandMetadata * poBandMetaData,
 GBool PostGISRasterDataset::ConstructOneDatasetFromTiles(
     PGresult * poResult)
 {
-    
+
     /*******************************************************************
-     * We first get the band metadata. So we'll can use it as metadata 
-     * for all the sources. 
-     * 
+     * We first get the band metadata. So we'll can use it as metadata
+     * for all the sources.
+     *
      * We just fetch the band metadata from 1 tile. So, we assume that:
      * - All the bands have the same data type
      * - All the bands have the same NODATA value
-     * 
-     * It's user's resposibility to ensure the requested table fit in
+     *
+     * It's user's responsibility to ensure the requested table fit in
      * this schema. He/she may use the 'where' clause to ensure this
      ******************************************************************/
     int nBandsFetched = 0;
     BandMetadata * poBandMetaData = GetBandsMetadata(&nBandsFetched);
-   
-    
+
     /*******************************************************************
-     * Now, we can iterate over the input query's results (metadata 
-     * from all the database tiles). 
-     * 
-     * In this iteration, we will construct the dataset GeoTransform 
+     * Now, we can iterate over the input query's results (metadata
+     * from all the database tiles).
+     *
+     * In this iteration, we will construct the dataset GeoTransform
      * array and we will add each tile's band as source for each of our
-     * rasterbands. 
+     * rasterbands.
      ******************************************************************/
-    int nTiles = PQntuples(poResult);
+    int l_nTiles = PQntuples(poResult);
 
     adfGeoTransform[GEOTRSFRM_TOPLEFT_X] = xmin;
 
     int nField = (GetPrimaryKeyRef() != NULL) ? 1 : 0;
     /**
-     * Optimization - Just one tile: The dataset's geotransform is the 
-     * tile's geotransform. And we don't need to construct sources for 
-     * the raster bands. We just read from the unique tile we have. So, 
+     * Optimization - Just one tile: The dataset's geotransform is the
+     * tile's geotransform. And we don't need to construct sources for
+     * the raster bands. We just read from the unique tile we have. So,
      * we avoid all the VRT stuff.
-     * 
+     *
      * TODO: For some reason, the implementation of IRasterIO in
      * PostGISRasterRasterBand class causes a segmentation fault when
      * tries to call GDALRasterBand::IRasterIO. This call intends to
      * delegate the I/O in the parent class, that will call
      * PostGISRasterRasterBand::IReadBlock.
-     * 
-     * If you avoid PostGISRasterRasterBand::IRasterIO method, the 
-     * IReadBlock method is directly call and it works fine. 
-     * 
+     *
+     * If you avoid PostGISRasterRasterBand::IRasterIO method, the
+     * IReadBlock method is directly call and it works fine.
+     *
      * Right now, we avoid this optimization by making the next boolean
      * variable always true.
      **/
-    //GBool bNeedToConstructSourcesHolders = (nTiles > 1); 
-    
+    //GBool bNeedToConstructSourcesHolders = (l_nTiles > 1);
+
     // As the optimization is not working, we avoid it
     GBool bNeedToConstructSourcesHolders = true;
-    
+
 #ifdef notdef
     // This won't be called if the optimization is disabled
     if (!bNeedToConstructSourcesHolders)
     {
         // Get metadata record
         char* pszRes = CPLStrdup(PQgetvalue(poResult, 0, nField));
-        
+
         // Skip first "("
         char* pszFilteredRes = pszRes + 1;
-        
+
         // Skip last ")"
         pszFilteredRes[strlen(pszFilteredRes)-1] = '\0';
-        
+
         // Tokenize
-        char** papszParams = 
+        char** papszParams =
             CSLTokenizeString2(pszFilteredRes, ",", CSLT_HONOURSTRINGS | CSLT_ALLOWEMPTYTOKENS);
         CPLAssert(CSLCount(papszParams) >= ELEMENTS_OF_METADATA_RECORD);
-        
+
         CPLFree(pszRes);
-        
-        adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1] = 
+
+        adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1] =
             CPLAtof(papszParams[POS_SKEWX]);
-            
-        adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] = 
+
+        adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] =
             CPLAtof(papszParams[POS_SKEWY]);
-         
+
         // Rotated rasters are not allowed, so far
         // TODO: allow them
         if (!CPLIsEqual(adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1], 0.0) ||
             !CPLIsEqual(adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2], 0.0)) {
-        
-            ReportError(CE_Failure, CPLE_AppDefined, 
+
+            ReportError(CE_Failure, CPLE_AppDefined,
                     "GDAL PostGIS Raster driver can not work with "
                     "rotated rasters yet.");
-        
-            VSIFree(poBandMetaData); 
+
+            VSIFree(poBandMetaData);
             CSLDestroy(papszParams);
-            
-            return false;          
+
+            return false;
         }
-            
+
         /**
          * We override user resolution. It only makes sense in case we
          * have several tiles with different resolutions
-         **/ 
-        adfGeoTransform[GEOTRSFRM_WE_RES] = 
-            CPLAtof(papszParams[POS_SCALEX]);        
-        adfGeoTransform[GEOTRSFRM_NS_RES] = 
+         **/
+        adfGeoTransform[GEOTRSFRM_WE_RES] =
+            CPLAtof(papszParams[POS_SCALEX]);
+        adfGeoTransform[GEOTRSFRM_NS_RES] =
             CPLAtof(papszParams[POS_SCALEY]);
-            
+
         CSLDestroy(papszParams);
-    
+
     }
-    
+
     /**
      * Several tiles: construct the dataset from metadata of all tiles,
      * and create PostGISRasterTileDataset objects, to hold the
@@ -1702,28 +1696,24 @@ GBool PostGISRasterDataset::ConstructOneDatasetFromTiles(
         int i;
 
 #ifdef DEBUG_VERBOSE
-        CPLDebug("PostGIS_Raster", 
+        CPLDebug("PostGIS_Raster",
             "PostGISRasterDataset::ConstructOneDatasetFromTiles: "
-            "Constructing one dataset from %d tiles", nTiles);
+            "Constructing one dataset from %d tiles", l_nTiles);
 #endif
-        
+
         papoSourcesHolders = (PostGISRasterTileDataset **)
-            VSIMalloc2(nTiles, sizeof(PostGISRasterTileDataset *));
-    
+            VSI_MALLOC2_VERBOSE(l_nTiles, sizeof(PostGISRasterTileDataset *));
+
         if (papoSourcesHolders == NULL) {
-            ReportError(CE_Failure, CPLE_OutOfMemory, 
-                "Out of memory allocating space for dataset bands "
-                "sources");
-                
             VSIFree(poBandMetaData);
-            
+
             return false;
         }
-        
+
         int nValidTiles = 0;
-        for(i = 0; i < nTiles; i++)
+        for(i = 0; i < l_nTiles; i++)
         {
-            PostGISRasterTileDataset* poRTDS = 
+            PostGISRasterTileDataset* poRTDS =
                 BuildRasterTileDataset(PQgetvalue(poResult, i, nField),
                                        (GetPrimaryKeyRef() != NULL) ? PQgetvalue(poResult, i, 0) : NULL,
                                        nBandsFetched,
@@ -1739,7 +1729,7 @@ GBool PostGISRasterDataset::ConstructOneDatasetFromTiles(
                 if( nValidTiles == 0 )
                 {
                     adfGeoTransform[GEOTRSFRM_WE_RES] = tilePixelSizeX;
-                    adfGeoTransform[GEOTRSFRM_NS_RES] = tilePixelSizeY; 
+                    adfGeoTransform[GEOTRSFRM_NS_RES] = tilePixelSizeY;
                 }
                 else
                 {
@@ -1751,8 +1741,8 @@ GBool PostGISRasterDataset::ConstructOneDatasetFromTiles(
             papoSourcesHolders[nValidTiles++] = poRTDS;
 
         } // end for
-        
-        nTiles = nValidTiles;
+
+        l_nTiles = nValidTiles;
 
         if( nOverviewFactor > 1 )
         {
@@ -1760,13 +1750,13 @@ GBool PostGISRasterDataset::ConstructOneDatasetFromTiles(
             adfGeoTransform[GEOTRSFRM_NS_RES] = poParentDS->adfGeoTransform[GEOTRSFRM_NS_RES] * nOverviewFactor;
         }
         else if ((resolutionStrategy == AVERAGE_RESOLUTION ||
-             resolutionStrategy == AVERAGE_APPROX_RESOLUTION) && nTiles > 0) {
-            adfGeoTransform[GEOTRSFRM_WE_RES] /= nTiles;
-            adfGeoTransform[GEOTRSFRM_NS_RES] /= nTiles;
+             resolutionStrategy == AVERAGE_APPROX_RESOLUTION) && l_nTiles > 0) {
+            adfGeoTransform[GEOTRSFRM_WE_RES] /= l_nTiles;
+            adfGeoTransform[GEOTRSFRM_NS_RES] /= l_nTiles;
         }
-        
+
     } // end else
-    
+
     /**
      * Complete the rest of geotransform parameters
      **/
@@ -1776,40 +1766,41 @@ GBool PostGISRasterDataset::ConstructOneDatasetFromTiles(
         adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] = ymax;
 
 #ifdef DEBUG_VERBOSE
-    CPLDebug("PostGIS_Raster", 
+    CPLDebug("PostGIS_Raster",
         "PostGISRasterDataset::ConstructOneDatasetFromTiles: "
         "GeoTransform array = (%f, %f, %f, %f, %f, %f)",
-        adfGeoTransform[GEOTRSFRM_TOPLEFT_X], 
+        adfGeoTransform[GEOTRSFRM_TOPLEFT_X],
         adfGeoTransform[GEOTRSFRM_WE_RES],
-        adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1], 
+        adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1],
         adfGeoTransform[GEOTRSFRM_TOPLEFT_Y],
-        adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2], 
+        adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2],
         adfGeoTransform[GEOTRSFRM_NS_RES]);
 #endif
 
     // Calculate the raster size from the geotransform array
-    nRasterXSize = (int) 
-        fabs(rint((xmax - xmin) / 
+    nRasterXSize = (int)
+        fabs(rint((xmax - xmin) /
             adfGeoTransform[GEOTRSFRM_WE_RES]));
-    
-    nRasterYSize = (int) 
-        fabs(rint((ymax - ymin) / 
+
+    nRasterYSize = (int)
+        fabs(rint((ymax - ymin) /
             adfGeoTransform[GEOTRSFRM_NS_RES]));
 
 #ifdef DEBUG_VERBOSE
-    CPLDebug("PostGIS_Raster", 
+    CPLDebug( "PostGIS_Raster",
         "PostGISRasterDataset::ConstructOneDatasetFromTiles: "
         "Raster size: (%d, %d), ",nRasterXSize, nRasterYSize);
 #endif
 
     if (nRasterXSize <= 0 || nRasterYSize <= 0) {
-        ReportError(CE_Failure, CPLE_AppDefined, 
+        ReportError(CE_Failure, CPLE_AppDefined,
             "Computed PostGIS Raster dimension is invalid. You've "
-            "probably specified unappropriate resolution.");
-        
+            "probably specified inappropriate resolution." );
+
+        VSIFree(poBandMetaData);
         return false;
     }
-    
+
     /*******************************************************************
      * Now construct the dataset bands
      ******************************************************************/
@@ -1818,17 +1809,16 @@ GBool PostGISRasterDataset::ConstructOneDatasetFromTiles(
     // And free bandmetadata
     VSIFree(poBandMetaData);
 
-    
     /*******************************************************************
      * Finally, add complex sources and create a quadtree index for them
      ******************************************************************/
     if (bNeedToConstructSourcesHolders) {
 #ifdef DEBUG_VERBOSE
-        CPLDebug("PostGIS_Raster", 
+        CPLDebug("PostGIS_Raster",
             "PostGISRasterDataset::ConstructOneDatasetFromTiles: "
             "Finally, adding sources for bands");
 #endif
-        for(int iSource = 0; iSource < nTiles; iSource++)
+        for(int iSource = 0; iSource < l_nTiles; iSource++)
         {
             PostGISRasterTileDataset* poRTDS =papoSourcesHolders[iSource];
             if (!AddComplexSource(poRTDS))
@@ -1853,12 +1843,12 @@ GBool PostGISRasterDataset::ConstructOneDatasetFromTiles(
 
 /***********************************************************************
  * \brief Construct subdatasets and show them.
- * 
- * This method is not very elegant. It's strongly attached to 
+ *
+ * This method is not very elegant. It's strongly attached to
  * SetRasterProperties (it assumes poResult is not NULL, and the actual
  * results are stored at fixed positions). I just did it to avoid a
  * huge SetRasterProperties method.
- * 
+ *
  * I know, this could be avoided in a better way. Like implementing a
  * wrapper to raise queries and get results without all the checking
  * overhead. I'd like to do it, someday...
@@ -1866,81 +1856,81 @@ GBool PostGISRasterDataset::ConstructOneDatasetFromTiles(
 GBool PostGISRasterDataset::YieldSubdatasets(PGresult * poResult,
 const char * pszValidConnectionString)
 {
-    int nTiles = PQntuples(poResult);
+    int l_nTiles = PQntuples(poResult);
     int i = 0;
     double dfTileUpperLeftX = 0;
     double dfTileUpperLeftY = 0;
-    
-    papszSubdatasets = (char**)VSICalloc(2 * nTiles + 1, sizeof(char*));
+
+    papszSubdatasets = (char**)VSICalloc(2 * l_nTiles + 1, sizeof(char*));
     if( papszSubdatasets == NULL )
         return false;
-    
+
     // Subdatasets identified by primary key
     if (GetPrimaryKeyRef() != NULL) {
-        
-        for(i = 0; i < nTiles; i++) {
-            
+
+        for(i = 0; i < l_nTiles; i++) {
+
             const char* pszId = PQgetvalue(poResult, i, 0);
-        
-            papszSubdatasets[2 * i] = 
+
+            papszSubdatasets[2 * i] =
                 CPLStrdup(CPLSPrintf("SUBDATASET_%d_NAME=PG:%s schema=%s table=%s column=%s "
-                    "where='%s = %s'", i+ 1, pszValidConnectionString, 
-                    pszSchema, pszTable, pszColumn, pszPrimaryKeyName, 
+                    "where='%s = %s'", i+ 1, pszValidConnectionString,
+                    pszSchema, pszTable, pszColumn, pszPrimaryKeyName,
                     pszId));
 
-            papszSubdatasets[2 * i + 1] = 
-                CPLStrdup(CPLSPrintf("SUBDATASET_%d_DESC=PostGIS Raster at %s.%s (%s), with %s = %s", 
-                    i + 1, pszSchema, pszTable, pszColumn, pszPrimaryKeyName, 
+            papszSubdatasets[2 * i + 1] =
+                CPLStrdup(CPLSPrintf("SUBDATASET_%d_DESC=PostGIS Raster at %s.%s (%s), with %s = %s",
+                    i + 1, pszSchema, pszTable, pszColumn, pszPrimaryKeyName,
                     pszId));
         }
-    } 
-        
+    }
+
     // Subdatasets identified by upper left pixel
     else {
-        
+
         char * pszRes;
         char * pszFilteredRes;
         char ** papszParams;
-        
-        for(i = 0; i < nTiles; i++) {
-            
+
+        for(i = 0; i < l_nTiles; i++) {
+
             pszRes = CPLStrdup(PQgetvalue(poResult, i, 0));
-        
+
             // Skip first "("
             pszFilteredRes = pszRes + 1;
-            
+
             // Skip last ")"
             pszFilteredRes[strlen(pszFilteredRes)-1] = '\0';
-            
+
             // Tokenize
-            papszParams = 
-                CSLTokenizeString2(pszFilteredRes, ",", 
+            papszParams =
+                CSLTokenizeString2(pszFilteredRes, ",",
                     CSLT_HONOURSTRINGS);
-                    
+
             CPLFree(pszRes);
-        
+
             dfTileUpperLeftX = CPLAtof(papszParams[POS_UPPERLEFTX]);
             dfTileUpperLeftY = CPLAtof(papszParams[POS_UPPERLEFTY]);
-        
-            papszSubdatasets[2 * i] = 
+
+            papszSubdatasets[2 * i] =
                 CPLStrdup(CPLSPrintf("SUBDATASET_%d_NAME=PG:%s schema=%s table=%s column=%s "
                     "where='abs(ST_UpperLeftX(%s) - %.8f) < 1e-8 AND "
                     "abs(ST_UpperLeftY(%s) - %.8f) < 1e-8'",
-                    i + 1, pszValidConnectionString, pszSchema, pszTable, 
-                    pszColumn, pszColumn, dfTileUpperLeftX, pszColumn, 
+                    i + 1, pszValidConnectionString, pszSchema, pszTable,
+                    pszColumn, pszColumn, dfTileUpperLeftX, pszColumn,
                     dfTileUpperLeftY));
 
-             papszSubdatasets[2 * i + 1] = 
+             papszSubdatasets[2 * i + 1] =
                 CPLStrdup(CPLSPrintf("SUBDATASET_%d_DESC=PostGIS Raster at %s.%s (%s), "
-                "UpperLeft = %.8f, %.8f", i + 1, pszSchema, pszTable, pszColumn, 
+                "UpperLeft = %.8f, %.8f", i + 1, pszSchema, pszTable, pszColumn,
                 dfTileUpperLeftX, dfTileUpperLeftY));
-                
+
             CSLDestroy(papszParams);
         }
     }
-    
+
     /**
-     * Not a single raster fetched. Not really needed. Just to keep code clean 
+     * Not a single raster fetched. Not really needed. Just to keep code clean
      **/
     nRasterXSize = 0;
     nRasterYSize = 0;
@@ -1959,24 +1949,24 @@ const char * pszValidConnectionString)
 /***********************************************************************
  * \brief Set the general raster properties.
  *
- * This method is called when the driver working mode is 
+ * This method is called when the driver working mode is
  * ONE_RASTER_PER_ROW or ONE_RASTER_PER_TABLE.
- * 
+ *
  * We must distinguish between tiled and untiled raster coverages. In
- * PostGIS Raster, there's no real difference between 'tile' and 
- * 'raster'. There's only 'raster objects'. Each record of a raster 
- * table is a raster object, and has its own georeference information, 
- * whether if the record is a tile of a bigger raster coverage or is a 
- * complete raster. So, <b>there's no a way of knowing if the rows of a 
+ * PostGIS Raster, there's no real difference between 'tile' and
+ * 'raster'. There's only 'raster objects'. Each record of a raster
+ * table is a raster object, and has its own georeference information,
+ * whether if the record is a tile of a bigger raster coverage or is a
+ * complete raster. So, <b>there's no a way of knowing if the rows of a
  * raster table are related or not</b>. It's user's responsibility, and
  * it's managed by 'mode' parameter in connection string, which
  * determines the driver working mode.
  *
- * The user is responsible to ensure that the raster layer meets the 
- * minimum topological requirements for analysis. The ideal case is when 
- * all the raster tiles of a continuous layer are the same size, snap to 
- * the same grid and do not overlap. 
- * 
+ * The user is responsible to ensure that the raster layer meets the
+ * minimum topological requirements for analysis. The ideal case is when
+ * all the raster tiles of a continuous layer are the same size, snap to
+ * the same grid and do not overlap.
+ *
  **********************************************************************/
 GBool PostGISRasterDataset::SetRasterProperties
     (const char * pszValidConnectionString)
@@ -1987,12 +1977,12 @@ GBool PostGISRasterDataset::SetRasterProperties
     GBool bNeedToCheckWholeTable = false;
 
     /*******************************************************************
-     * Get the extent and the maximum number of bands of the requested 
+     * Get the extent and the maximum number of bands of the requested
      * raster-
-     * 
-     * TODO: The extent of rotated rasters could be a problem. We'll 
-     * need a ST_RotatedExtent function in PostGIS. Without that 
-     * function, we shouldn't allow rotated rasters
+     *
+     * TODO: The extent of rotated rasters could be a problem. We will
+     * need a ST_RotatedExtent function in PostGIS. Without that
+     * function, we should not allow rotated rasters.
      ******************************************************************/
     if (pszWhere != NULL) {
         osCommand.Printf(
@@ -2000,29 +1990,29 @@ GBool PostGISRasterDataset::SetRasterProperties
             "ST_XMax(geom) as xmax, ST_YMin(geom) as ymin, "
             "ST_YMax(geom) as ymax, scale_x, scale_y from (select ST_SRID(%s) srid, "
             "ST_Extent(%s::geometry) geom, max(ST_NumBands(%s)) "
-            "nbband, avg(ST_ScaleX(%s)) scale_x, avg(ST_ScaleY(%s)) scale_y from %s.%s where %s group by ST_SRID(%s)) foo", 
+            "nbband, avg(ST_ScaleX(%s)) scale_x, avg(ST_ScaleY(%s)) scale_y from %s.%s where %s group by ST_SRID(%s)) foo",
             pszColumn, pszColumn, pszColumn, pszColumn, pszColumn,
-            pszSchema, pszTable, pszWhere, 
+            pszSchema, pszTable, pszWhere,
             pszColumn);
-            
+
 #ifdef DEBUG_QUERY
-        CPLDebug("PostGIS_Raster", 
-        "PostGISRasterDataset::SetRasterProperties(): First query: %s", 
+        CPLDebug("PostGIS_Raster",
+        "PostGISRasterDataset::SetRasterProperties(): First query: %s",
         osCommand.c_str());
 #endif
 
         poResult = PQexec(poConn, osCommand.c_str());
     }
-    
+
     else {
-        
+
         /**
-         * Optimization: First, check raster_columns view (it makes 
+         * Optimization: First, check raster_columns view (it makes
          * things faster. See ticket #5046)
-         * 
-         * This can only be applied if we don't have a 'where' clause, 
+         *
+         * This can only be applied if we don't have a 'where' clause,
          * because raster_columns view stores statistics about the whole
-         * table. If the user specified 'where' clause is because is 
+         * table. If the user specified 'where' clause is because is
          * just interested in a subset of the table rows.
          **/
         osCommand.Printf(
@@ -2034,45 +2024,45 @@ GBool PostGISRasterDataset::SetRasterProperties
             "raster_columns where r_table_schema = '%s' and "
             "r_table_name = '%s' and r_raster_column = '%s' ) foo",
             pszSchema, pszTable, pszColumn);
-            
+
 #ifdef DEBUG_QUERY
-        CPLDebug("PostGIS_Raster", 
-        "PostGISRasterDataset::SetRasterProperties(): First query: %s", 
+        CPLDebug("PostGIS_Raster",
+        "PostGISRasterDataset::SetRasterProperties(): First query: %s",
         osCommand.c_str());
 #endif
-        
+
         poResult = PQexec(poConn, osCommand.c_str());
-            
+
         // Query execution error
-        if(poResult == NULL || 
-            PQresultStatus(poResult) != PGRES_TUPLES_OK || 
+        if(poResult == NULL ||
+            PQresultStatus(poResult) != PGRES_TUPLES_OK ||
             PQntuples(poResult) < 0) {
-            
+
             bNeedToCheckWholeTable = true;
-            
+
             if (poResult)
                 PQclear(poResult);
-        
+
         }
-        
+
         /**
          * We didn't find anything in raster_columns view. Need to check
          * the whole table for metadata
          **/
         else if (PQntuples(poResult) == 0) {
-            
+
             ReportError(CE_Warning, CPLE_AppDefined, "Cannot find "
             "information about %s.%s table in raster_columns view. The "
             "raster table load would take a lot of time. Please, "
             "execute AddRasterConstraints PostGIS function to register "
             "this table as raster table in raster_columns view. This "
             "will save a lot of time.", pszSchema, pszTable);
-            
+
             PQclear(poResult);
-            
+
             bNeedToCheckWholeTable = true;
         }
-        
+
         /* There's a result but the row has empty values */
         else if (PQntuples(poResult) == 1 &&
                  (PQgetvalue(poResult, 0, 1)[0] == '\0' ||
@@ -2087,13 +2077,12 @@ GBool PostGISRasterDataset::SetRasterProperties
             "execute AddRasterConstraints PostGIS function to register "
             "this table as raster table in raster_columns view. This "
             "will save a lot of time.", pszSchema, pszTable);
-            
+
             PQclear(poResult);
-            
+
             bNeedToCheckWholeTable = true;
         }
-        
-        
+
         // We should check whole table but we can't
         if (bNeedToCheckWholeTable && !bCheckAllTiles) {
             ReportError(CE_Failure, CPLE_AppDefined, "Cannot find "
@@ -2106,14 +2095,13 @@ GBool PostGISRasterDataset::SetRasterProperties
             "driver will work even without the table information "
             "stored in raster_columns view, but it could perform "
             "really slow.", pszSchema, pszTable);
-            
+
             PQclear(poResult);
-            
+
             return false;
-            
+
         }
-        
-        
+
         // We should check the whole table and we can
         else if (bNeedToCheckWholeTable) {
             osCommand.Printf(
@@ -2121,19 +2109,18 @@ GBool PostGISRasterDataset::SetRasterProperties
                 "st_xmax(geom) as xmax, st_ymin(geom) as ymin, "
                 "st_ymax(geom) as ymax, scale_x, scale_y from (select st_srid(%s) srid, "
                 "st_extent(%s::geometry) geom, max(ST_NumBands(%s)) "
-                "nbband, avg(ST_ScaleX(%s)) scale_x, avg(ST_ScaleY(%s)) scale_y from %s.%s group by st_srid(%s)) foo", 
+                "nbband, avg(ST_ScaleX(%s)) scale_x, avg(ST_ScaleY(%s)) scale_y from %s.%s group by st_srid(%s)) foo",
                 pszColumn, pszColumn, pszColumn, pszColumn, pszColumn, pszSchema, pszTable, pszColumn);
-                
+
 #ifdef DEBUG_QUERY
-            CPLDebug("PostGIS_Raster", 
+            CPLDebug("PostGIS_Raster",
                 "PostGISRasterDataset::SetRasterProperties(): "
                 "First query: %s", osCommand.c_str());
 #endif
 
-            poResult = PQexec(poConn, osCommand.c_str()); 
+            poResult = PQexec(poConn, osCommand.c_str());
         }
-        
-        
+
         // We already found the data in raster_columns
         else {
             bDataFoundInRasterColumns = true;
@@ -2141,36 +2128,35 @@ GBool PostGISRasterDataset::SetRasterProperties
     }
 
     // Query execution error
-    if(poResult == NULL || 
-        PQresultStatus(poResult) != PGRES_TUPLES_OK || 
+    if(poResult == NULL ||
+        PQresultStatus(poResult) != PGRES_TUPLES_OK ||
         PQntuples(poResult) < 0) {
-        
-        ReportError(CE_Failure, CPLE_AppDefined, 
+
+        ReportError(CE_Failure, CPLE_AppDefined,
             "Error browsing database for PostGIS Raster "
             "properties : %s",  PQerrorMessage(poConn));
 
         if (poResult != NULL)
             PQclear(poResult);
 
-        return false;                  
-    
+        return false;
     }
-    
+
     else if (PQntuples(poResult) == 0) {
-        ReportError(CE_Failure, CPLE_AppDefined, 
+        ReportError(CE_Failure, CPLE_AppDefined,
             "No results found in %s.%s. Did you specify a 'where' "
             "clause too restrictive?", pszSchema, pszTable);
-            
+
         PQclear(poResult);
-        
+
         return false;
     }
 
-    
+
     /**
      * Found more than one SRID value in the table. Not allowed.
-     * 
-     * TODO: We could provide an extra parameter, to transform all the 
+     *
+     * TODO: We could provide an extra parameter, to transform all the
      * tiles to the same SRID
      **/
     else if (PQntuples(poResult) > 1) {
@@ -2179,11 +2165,11 @@ GBool PostGISRasterDataset::SetRasterProperties
             "srid. This feature is not yet supported by the PostGIS "
             "Raster driver. Please, specify a table that contains only "
             "tiles with the same srid or provide a 'where' constraint "
-            "to select just the tiles with the same value for srid", 
+            "to select just the tiles with the same value for srid",
             pszSchema, pszTable);
 
         PQclear(poResult);
-        
+
         return false;
     }
 
@@ -2217,7 +2203,7 @@ GBool PostGISRasterDataset::SetRasterProperties
 
     double scale_x = CPLAtof(PQgetvalue(poResult, 0, 6));
     double scale_y = CPLAtof(PQgetvalue(poResult, 0, 7));
-    if( nOverviewFactor > 1 )
+    if( nOverviewFactor > 1 && poParentDS != NULL )
     {
         scale_x = poParentDS->adfGeoTransform[GEOTRSFRM_WE_RES] * nOverviewFactor;
         scale_y = poParentDS->adfGeoTransform[GEOTRSFRM_NS_RES] * nOverviewFactor;
@@ -2227,7 +2213,7 @@ GBool PostGISRasterDataset::SetRasterProperties
         scale_x = adfGeoTransform[GEOTRSFRM_WE_RES];
         scale_y = adfGeoTransform[GEOTRSFRM_NS_RES];
     }
-    
+
     // These fields can only be fetched from raster_columns view
     if (bDataFoundInRasterColumns)
     {
@@ -2237,26 +2223,26 @@ GBool PostGISRasterDataset::SetRasterProperties
             bTilesSameDimension = true;
 
         bAllTilesSnapToSameGrid =
-            EQUALN(PQgetvalue(poResult, 0, 10), "t", sizeof(char));
-        
-        bRegularBlocking = 
-            EQUALN(PQgetvalue(poResult, 0, 11), "t", sizeof(char));
+            EQUAL(PQgetvalue(poResult, 0, 10), "t");
+
+        bRegularBlocking =
+            EQUAL(PQgetvalue(poResult, 0, 11), "t");
     }
 
 #ifdef DEBUG_VERBOSE
-    CPLDebug("PostGIS_Raster", 
+    CPLDebug("PostGIS_Raster",
         "PostGISRasterDataset::SetRasterProperties: xmin = %f, "
         "xmax = %f, ymin = %f, ymax = %f, scale_x = %f, scale_y = %f",
              xmin, xmax, ymin, ymax, scale_x, scale_y);
 #endif
 
     PQclear(poResult);
-    
+
     /*******************************************************************
-     * Now, we fetch the metadata of all the raster tiles in the 
+     * Now, we fetch the metadata of all the raster tiles in the
      * database, that will allow us to construct VRT sources to the
      * PostGIS Raster bands.
-     * 
+     *
      * TODO: Improve this. If we have a big amount of tiles, it can be
      * a problem.
      ******************************************************************/
@@ -2275,21 +2261,21 @@ GBool PostGISRasterDataset::SetRasterProperties
                                  "(SELECT ST_ScaleX(%s) scale_x, ST_ScaleY(%s) scale_y FROM %s.%s LIMIT 10) foo",
                                  pszColumn, pszColumn, pszSchema, pszTable);
                 #ifdef DEBUG_QUERY
-                    CPLDebug("PostGIS_Raster", 
-                        "PostGISRasterDataset::SetRasterProperties(): Query: %s", 
+                    CPLDebug("PostGIS_Raster",
+                        "PostGISRasterDataset::SetRasterProperties(): Query: %s",
                         osCommand.c_str());
                 #endif
 
                 poResult = PQexec(poConn, osCommand.c_str());
-                if (poResult == NULL || 
+                if (poResult == NULL ||
                     PQresultStatus(poResult) != PGRES_TUPLES_OK ||
                     PQntuples(poResult) <= 0) {
 
-                    ReportError(CE_Failure, CPLE_AppDefined, 
+                    ReportError(CE_Failure, CPLE_AppDefined,
                         "Error retrieving raster metadata");
 
-                    CPLDebug("PostGIS_Raster", 
-                        "PostGISRasterDataset::SetRasterProperties(): %s", 
+                    CPLDebug("PostGIS_Raster",
+                        "PostGISRasterDataset::SetRasterProperties(): %s",
                         PQerrorMessage(poConn));
 
                     if (poResult != NULL)
@@ -2312,7 +2298,7 @@ GBool PostGISRasterDataset::SetRasterProperties
                immediately, and IRasterIO() queries will be able to retrieve quickly
                the PKID of the tiles to fetch, so we don't need to scan the whole table */
             if( bIsFastPK && nMode == ONE_RASTER_PER_TABLE && HasSpatialIndex() &&
-                scale_x != 0 && scale_y != 0 ) 
+                scale_x != 0 && scale_y != 0 )
             {
                 adfGeoTransform[GEOTRSFRM_TOPLEFT_X] = xmin;
                 adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1] = 0.0;
@@ -2322,33 +2308,35 @@ GBool PostGISRasterDataset::SetRasterProperties
                 adfGeoTransform[GEOTRSFRM_NS_RES] = scale_y;
 
                 // Calculate the raster size from the geotransform array
-                nRasterXSize = (int) 
-                    fabs(rint((xmax - xmin) / 
+                nRasterXSize = (int)
+                    fabs(rint((xmax - xmin) /
                         adfGeoTransform[GEOTRSFRM_WE_RES]));
-                
-                nRasterYSize = (int) 
-                    fabs(rint((ymax - ymin) / 
+
+                nRasterYSize = (int)
+                    fabs(rint((ymax - ymin) /
                         adfGeoTransform[GEOTRSFRM_NS_RES]));
 
             #ifdef DEBUG_VERBOSE
-                CPLDebug("PostGIS_Raster", 
+                CPLDebug( "PostGIS_Raster",
                     "PostGISRasterDataset::ConstructOneDatasetFromTiles: "
                     "Raster size: (%d, %d), ",nRasterXSize, nRasterYSize);
             #endif
 
                 if (nRasterXSize <= 0 || nRasterYSize <= 0) {
-                    ReportError(CE_Failure, CPLE_AppDefined, 
-                        "Computed PostGIS Raster dimension is invalid. You've "
-                        "probably specified unappropriate resolution.");
+                    ReportError(
+                        CE_Failure, CPLE_AppDefined,
+                        "Computed PostGIS Raster dimension is invalid. You "
+                        "have probably specified an inappropriate "
+                        "resolution." );
 
                     return false;
                 }
 
                 bBuildQuadTreeDynamically = true;
 
-                /*******************************************************************
+                /**************************************************************
                 * Now construct the dataset bands
-                ******************************************************************/
+                ***************************************************************/
                 int nBandsFetched = 0;
                 BandMetadata * poBandMetaData = GetBandsMetadata(&nBandsFetched);
 
@@ -2362,13 +2350,13 @@ GBool PostGISRasterDataset::SetRasterProperties
 
             osCommand.Printf("select %s, st_metadata(%s) from %s.%s",
                 pszPrimaryKeyName, pszColumn, pszSchema, pszTable);
-                        
-            // srid shouldn't be necessary. It was previously checked
+
+            // srid should not be necessary. It was previously checked
         }
-        
+
         else {
             osCommand.Printf("select %s, st_metadata(%s) from %s.%s "
-                "where %s", pszPrimaryKeyName, pszColumn, pszSchema, 
+                "where %s", pszPrimaryKeyName, pszColumn, pszSchema,
                 pszTable, pszWhere);
         }
     }
@@ -2379,29 +2367,29 @@ GBool PostGISRasterDataset::SetRasterProperties
             osCommand.Printf("select st_metadata(%s) from %s.%s",
                 pszColumn, pszSchema, pszTable);
         }
-        
+
         else {
             osCommand.Printf("select st_metadata(%s) from %s.%s "
                 "where %s", pszColumn, pszSchema, pszTable, pszWhere);
         }
     }
-   
+
 #ifdef DEBUG_QUERY
-    CPLDebug("PostGIS_Raster", 
-        "PostGISRasterDataset::SetRasterProperties(): Query: %s", 
+    CPLDebug("PostGIS_Raster",
+        "PostGISRasterDataset::SetRasterProperties(): Query: %s",
         osCommand.c_str());
 #endif
 
     poResult = PQexec(poConn, osCommand.c_str());
-    if (poResult == NULL || 
+    if (poResult == NULL ||
         PQresultStatus(poResult) != PGRES_TUPLES_OK ||
         PQntuples(poResult) <= 0) {
 
-        ReportError(CE_Failure, CPLE_AppDefined, 
+        ReportError(CE_Failure, CPLE_AppDefined,
             "Error retrieving raster metadata");
 
-        CPLDebug("PostGIS_Raster", 
-            "PostGISRasterDataset::SetRasterProperties(): %s", 
+        CPLDebug("PostGIS_Raster",
+            "PostGISRasterDataset::SetRasterProperties(): %s",
             PQerrorMessage(poConn));
 
         if (poResult != NULL)
@@ -2411,72 +2399,70 @@ GBool PostGISRasterDataset::SetRasterProperties
     }
 
     // Now we know the number of tiles that form our dataset
-    nTiles = PQntuples(poResult);
-    
-    
+    m_nTiles = PQntuples(poResult);
+
     /*******************************************************************
-     * We are going to create a whole dataset as a mosaic with all the 
-     * tiles. We'll consider each tile as a VRT source for 
-     * PostGISRasterRasterBand. The data will be actually read by each 
-     * of these sources, and it will be cached in the sources' caches, 
+     * We are going to create a whole dataset as a mosaic with all the
+     * tiles. We'll consider each tile as a VRT source for
+     * PostGISRasterRasterBand. The data will be actually read by each
+     * of these sources, and it will be cached in the sources' caches,
      * not in the PostGISRasterRasterBand cache
      ******************************************************************/
-    if (nTiles == 1 || nMode == ONE_RASTER_PER_TABLE)
+    if (m_nTiles == 1 || nMode == ONE_RASTER_PER_TABLE)
     {
 #ifdef DEBUG_VERBOSE
-        CPLDebug("PostGIS_Raster", 
+        CPLDebug("PostGIS_Raster",
             "PostGISRasterDataset::SetRasterProperties(): "
-            "Constructing one dataset from %d tiles", nTiles);
+            "Constructing one dataset from %d tiles", m_nTiles);
 #endif
 
         GBool res = ConstructOneDatasetFromTiles(poResult);
-        
+
         PQclear(poResult);
-        
+
         return res;
     }
-    
+
 
     /***************************************************************
-     * One raster per row: collect subdatasets 
-     **************************************************************/ 
+     * One raster per row: collect subdatasets
+     **************************************************************/
     else if (nMode == ONE_RASTER_PER_ROW) {
 #ifdef DEBUG_VERBOSE
-        CPLDebug("PostGIS_Raster", 
+        CPLDebug("PostGIS_Raster",
             "PostGISRasterDataset::SetRasterProperties(): "
-            "Reporting %d datasets", nTiles);
+            "Reporting %d datasets", m_nTiles);
 #endif
 
-        GBool res = YieldSubdatasets(poResult, 
+        GBool res = YieldSubdatasets(poResult,
             pszValidConnectionString);
-        
+
         PQclear(poResult);
-        
+
         return res;
     }
-        
+
     /***************************************************************
-     * Wrong mode: error 
+     * Wrong mode: error
      **************************************************************/
     else {
-        ReportError(CE_Failure, CPLE_AppDefined, 
+        ReportError(CE_Failure, CPLE_AppDefined,
             "Wrong driver working mode. You must specify mode = 1 or "
             "mode = 2 in the connection string. Check PostGIS Raster "
             "documentation at "
             "http://trac.osgeo.org/gdal/wiki/frmts_wtkraster.html "
             "for further information about working modes.");
-            
+
         PQclear(poResult);
-            
+
         return false;
     }
 }
-         
-    
+
 /***********************************************************************
- * \brief Get the connection information for a filename. 
- * 
- * This method extracts these dataset parameters from the connection 
+ * \brief Get the connection information for a filename.
+ *
+ * This method extracts these dataset parameters from the connection
  * string, if present:
  * - pszSchema: The schema where the table belongs
  * - pszTable: The table's name
@@ -2487,19 +2473,19 @@ GBool PostGISRasterDataset::SetRasterProperties
  * - pszUser: The PostgreSQL user
  * - pszPassword: The PostgreSQL password
  * - nMode: The connection mode
- * 
+ *
  * If any of there parameters is not present in the connection string,
  * default values are taken. nMode is deducted from the rest of
  * parameters if not provided.
- * 
- * Apart from that, bBrowseDatabase is set to TRUE if the mode is 
+ *
+ * Apart from that, bBrowseDatabase is set to TRUE if the mode is
  * BROWSE_SCHEMA or BROWSE_DATABASE
  **********************************************************************/
 static GBool
-GetConnectionInfo(const char * pszFilename, 
-    char ** ppszConnectionString, char ** ppszDbname, char ** ppszSchema, char ** ppszTable, 
-    char ** ppszColumn, char ** ppszWhere, char ** ppszHost, 
-    char ** ppszPort, char ** ppszUser, char ** ppszPassword, 
+GetConnectionInfo(const char * pszFilename,
+    char ** ppszConnectionString, char ** ppszDbname, char ** ppszSchema, char ** ppszTable,
+    char ** ppszColumn, char ** ppszWhere, char ** ppszHost,
+    char ** ppszPort, char ** ppszUser, char ** ppszPassword,
     WorkingMode * nMode, GBool * bBrowseDatabase)
 {
     int nPos = -1, i;
@@ -2511,19 +2497,19 @@ GetConnectionInfo(const char * pszFilename,
 
     /*******************************************************************
      * Get mode:
-     *  - 1. ONE_RASTER_PER_ROW: Each row is considered as a separate 
+     *  - 1. ONE_RASTER_PER_ROW: Each row is considered as a separate
      *      raster
-     *  - 2. ONE_RASTER_PER_TABLE: All the table rows are considered as 
+     *  - 2. ONE_RASTER_PER_TABLE: All the table rows are considered as
      *      a whole raster coverage
      ******************************************************************/
     nPos = CSLFindName(papszParams, "mode");
     if (nPos != -1) {
         int tmp;
         tmp = atoi(CPLParseNameValue(papszParams[nPos], NULL));
-        
+
         // default value
         *nMode = ONE_RASTER_PER_ROW;
-        
+
         if (tmp == 2) {
             *nMode = ONE_RASTER_PER_TABLE;
         }
@@ -2550,7 +2536,7 @@ GetConnectionInfo(const char * pszFilename,
         return false;
     }
 
-    *ppszDbname = 
+    *ppszDbname =
         CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
 
     /**
@@ -2565,15 +2551,15 @@ GetConnectionInfo(const char * pszFilename,
         /* Get schema name, if exist */
         nPos = CSLFindName(papszParams, "schema");
         if (nPos != -1) {
-            *ppszSchema = 
+            *ppszSchema =
                 CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
-                
+
             /* Delete this pair from params array */
             papszParams = CSLRemoveStrings(papszParams, nPos, 1, NULL);
         }
 
         /**
-         * Remove the rest of the parameters, if exist (they mustn't be 
+         * Remove the rest of the parameters, if exist (they must not be
          * present if we want a valid PQ connection string)
          **/
         nPos = CSLFindName(papszParams, "column");
@@ -2588,14 +2574,14 @@ GetConnectionInfo(const char * pszFilename,
             papszParams = CSLRemoveStrings(papszParams, nPos, 1, NULL);
         }
     } else {
-        *ppszTable = 
+        *ppszTable =
             CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
         /* Delete this pair from params array */
         papszParams = CSLRemoveStrings(papszParams, nPos, 1, NULL);
 
         /**
          * Case 3: There's database and table name, but no column
-         * name: Use a default column name and use the table to create 
+         * name: Use a default column name and use the table to create
          * the dataset
          **/
         nPos = CSLFindName(papszParams, "column");
@@ -2603,13 +2589,13 @@ GetConnectionInfo(const char * pszFilename,
             *ppszColumn = CPLStrdup(DEFAULT_COLUMN);
         }
         /**
-         * Case 4: There's database, table and column name: Use the 
+         * Case 4: There's database, table and column name: Use the
          * table to create a dataset
          **/
         else {
-            *ppszColumn = 
+            *ppszColumn =
                 CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
-                
+
             /* Delete this pair from params array */
             papszParams = CSLRemoveStrings(papszParams, nPos, 1, NULL);
         }
@@ -2619,18 +2605,18 @@ GetConnectionInfo(const char * pszFilename,
         if (nPos == -1) {
             *ppszSchema = CPLStrdup(DEFAULT_SCHEMA);
         } else {
-            *ppszSchema = 
+            *ppszSchema =
                 CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
-                
+
             /* Delete this pair from params array */
             papszParams = CSLRemoveStrings(papszParams, nPos, 1, NULL);
         }
 
         nPos = CSLFindName(papszParams, "where");
         if (nPos != -1) {
-            *ppszWhere = 
+            *ppszWhere =
                 CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
-                
+
             /* Delete this pair from params array */
             papszParams = CSLRemoveStrings(papszParams, nPos, 1, NULL);
         }
@@ -2638,7 +2624,7 @@ GetConnectionInfo(const char * pszFilename,
 
     /* Parse ppszWhere, if needed */
     if (*ppszWhere) {
-        pszTmp = ReplaceQuotes(*ppszWhere, strlen(*ppszWhere));
+        pszTmp = ReplaceQuotes(*ppszWhere, static_cast<int>(strlen(*ppszWhere)));
         CPLFree(*ppszWhere);
         *ppszWhere = pszTmp;
     }
@@ -2649,17 +2635,17 @@ GetConnectionInfo(const char * pszFilename,
     *ppszConnectionString = (char*) CPLCalloc(strlen(pszFilename),
             sizeof (char));
     for (i = 0; i < CSLCount(papszParams); i++) {
-        *ppszConnectionString = 
-            strncat(*ppszConnectionString, papszParams[i], 
+        *ppszConnectionString =
+            strncat(*ppszConnectionString, papszParams[i],
                 strlen(papszParams[i]));
-                
-        *ppszConnectionString = 
+
+        *ppszConnectionString =
             strncat(*ppszConnectionString, " ", strlen(" "));
     }
 
     nPos = CSLFindName(papszParams, "host");
     if (nPos != -1) {
-        *ppszHost = 
+        *ppszHost =
             CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
     }
     else if (CPLGetConfigOption("PGHOST", NULL) != NULL) {
@@ -2679,7 +2665,7 @@ GetConnectionInfo(const char * pszFilename,
 
     nPos = CSLFindName(papszParams, "port");
     if (nPos != -1) {
-        *ppszPort = 
+        *ppszPort =
             CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
     }
     else if (CPLGetConfigOption("PGPORT", NULL) != NULL ) {
@@ -2699,7 +2685,7 @@ GetConnectionInfo(const char * pszFilename,
 
     nPos = CSLFindName(papszParams, "user");
     if (nPos != -1) {
-        *ppszUser = 
+        *ppszUser =
             CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
     }
     else if (CPLGetConfigOption("PGUSER", NULL) != NULL ) {
@@ -2719,7 +2705,7 @@ GetConnectionInfo(const char * pszFilename,
 
     nPos = CSLFindName(papszParams, "password");
     if (nPos != -1) {
-        *ppszPassword = 
+        *ppszPassword =
             CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
     }
     else if (CPLGetConfigOption("PGPASSWORD", NULL) != NULL ) {
@@ -2731,20 +2717,20 @@ GetConnectionInfo(const char * pszFilename,
     CSLDestroy(papszParams);
 
 #ifdef DEBUG_VERBOSE
-    CPLDebug("PostGIS_Raster", 
+    CPLDebug("PostGIS_Raster",
         "PostGISRasterDataset::GetConnectionInfo(): "
         "Mode: %d\nDbname: %s\nSchema: %s\nTable: %s\nColumn: %s\nWhere: %s\n"
         "Host: %s\nPort: %s\nUser: %s\nPassword: %s\n"
-        "Connection String: %s\n", 
+        "Connection String: %s\n",
         *nMode, *ppszDbname,
         *ppszSchema ? *ppszSchema : "(null)",
         *ppszTable ? *ppszTable : "(null)",
         *ppszColumn ? *ppszColumn : "(null)",
-        *ppszWhere ? *ppszWhere : "(null)", 
+        *ppszWhere ? *ppszWhere : "(null)",
         *ppszHost ? *ppszHost : "(null)",
         *ppszPort ? *ppszPort : "(null)",
         *ppszUser ? *ppszUser : "(null)",
-        *ppszPassword ? *ppszPassword : "(null)", 
+        *ppszPassword ? *ppszPassword : "(null)",
         *ppszConnectionString);
 #endif
 
@@ -2756,8 +2742,8 @@ GetConnectionInfo(const char * pszFilename,
  **********************************************************************/
 static PGconn *
 GetConnection(const char * pszFilename, char ** ppszConnectionString,
-    char ** ppszSchema, char ** ppszTable, char ** ppszColumn, 
-    char ** ppszWhere, WorkingMode * nMode, GBool * bBrowseDatabase) 
+    char ** ppszSchema, char ** ppszTable, char ** ppszColumn,
+    char ** ppszWhere, WorkingMode * nMode, GBool * bBrowseDatabase)
 {
     PostGISRasterDriver * poDriver;
     PGconn * poConn = NULL;
@@ -2767,16 +2753,16 @@ GetConnection(const char * pszFilename, char ** ppszConnectionString,
     char * pszUser = NULL;
     char * pszPassword = NULL;
 
-    if (GetConnectionInfo(pszFilename, ppszConnectionString, &pszDbname, ppszSchema, 
-        ppszTable, ppszColumn, ppszWhere, &pszHost, &pszPort, &pszUser, 
-        &pszPassword, nMode, bBrowseDatabase)) 
+    if (GetConnectionInfo(pszFilename, ppszConnectionString, &pszDbname, ppszSchema,
+        ppszTable, ppszColumn, ppszWhere, &pszHost, &pszPort, &pszUser,
+        &pszPassword, nMode, bBrowseDatabase))
     {
         /**************************************************************
          * Open a new database connection
          **************************************************************/
-        poDriver = 
+        poDriver =
             (PostGISRasterDriver *)GDALGetDriverByName("PostGISRaster");
-            
+
         poConn = poDriver->GetConnection(*ppszConnectionString,
                 pszDbname, pszHost, pszPort, pszUser);
 
@@ -2803,11 +2789,11 @@ int PostGISRasterDataset::Identify(GDALOpenInfo* poOpenInfo)
 {
     if (poOpenInfo->pszFilename == NULL ||
         poOpenInfo->fpL != NULL ||
-        !EQUALN(poOpenInfo->pszFilename, "PG:", 3))
+        !STARTS_WITH_CI(poOpenInfo->pszFilename, "PG:"))
     {
         return FALSE;
     }
-    
+
     // Will avoid a OGR PostgreSQL connection string to be recognized as a
     // PostgisRaster one and later fail (#6034)
     if( strstr(poOpenInfo->pszFilename, " schemas=") ||
@@ -2815,12 +2801,12 @@ int PostGISRasterDataset::Identify(GDALOpenInfo* poOpenInfo)
     {
         return FALSE;
     }
-    
+
     return TRUE;
 }
 
 /***********************************************************************
- * \brief Open a connection with PostgreSQL. The connection string will 
+ * \brief Open a connection with PostgreSQL. The connection string will
  * have the PostgreSQL accepted format, plus the next key=value pairs:
  *  schema = <schema_name>
  *  table = <table_name>
@@ -2849,7 +2835,7 @@ GDALDataset* PostGISRasterDataset::Open(GDALOpenInfo* poOpenInfo) {
         return NULL;
 
     poConn = GetConnection(poOpenInfo->pszFilename,
-        &pszConnectionString, &pszSchema, &pszTable, &pszColumn, 
+        &pszConnectionString, &pszSchema, &pszTable, &pszColumn,
         &pszWhere, &nMode, &bBrowseDatabase);
     if (poConn == NULL) {
         CPLFree(pszConnectionString);
@@ -2859,10 +2845,10 @@ GDALDataset* PostGISRasterDataset::Open(GDALOpenInfo* poOpenInfo) {
         CPLFree(pszWhere);
         return NULL;
     }
-    
+
 
     /*******************************************************************
-     * No table will be read. Only shows information about the existent 
+     * No table will be read. Only shows information about the existent
      * raster tables
      ******************************************************************/
     if (bBrowseDatabase) {
@@ -2904,9 +2890,9 @@ GDALDataset* PostGISRasterDataset::Open(GDALOpenInfo* poOpenInfo) {
         if (pszWhere)
             CPLFree(pszWhere);
     }
-    
+
     /*******************************************************************
-     * A table will be read as dataset: Fetch raster properties from db. 
+     * A table will be read as dataset: Fetch raster properties from db.
      ******************************************************************/
     else {
         poDS = new PostGISRasterDataset();
@@ -2957,7 +2943,7 @@ char **PostGISRasterDataset::GetMetadataDomainList()
  * calling ST_Metadata, for example)
  *****************************************/
 char** PostGISRasterDataset::GetMetadata(const char *pszDomain) {
-    if (pszDomain != NULL && EQUALN(pszDomain, "SUBDATASETS", 11))
+    if (pszDomain != NULL && STARTS_WITH_CI(pszDomain, "SUBDATASETS"))
         return papszSubdatasets;
     else
         return GDALDataset::GetMetadata(pszDomain);
@@ -3111,10 +3097,10 @@ CPLErr PostGISRasterDataset::GetGeoTransform(double * padfGeoTransform) {
 
     // copy necessary values in supplied buffer
     memcpy(padfGeoTransform, adfGeoTransform, 6 * sizeof(double));
-    
+
     if( nRasterXSize == 0 && nRasterYSize == 0 )
         return CE_Failure;
-    
+
     /* To avoid QGIS trying to create a warped VRT for what is really */
     /* an ungeoreferenced dataset */
     if( CPLIsEqual(padfGeoTransform[0], 0.0) &&
@@ -3132,8 +3118,8 @@ CPLErr PostGISRasterDataset::GetGeoTransform(double * padfGeoTransform) {
 
 
 /*********************************************************
- * \brief Fetch files forming dataset. 
- * 
+ * \brief Fetch files forming dataset.
+ *
  * We need to define this method because the VRTDataset
  * method doesn't check for NULL FileList before trying
  * to collect the names of all sources' file list.
@@ -3174,27 +3160,27 @@ PostGISRasterDataset::CreateCopy( CPL_UNUSED const char * pszFilename,
             "datasets that are PostGISRaster" );
         return NULL;
     }
-    
+
     // Now we can do the cast
     PostGISRasterDataset *poSrcDS = (PostGISRasterDataset *)poGSrcDS;
     PostGISRasterDataset *poSubDS;
 
     // Check connection string
     if (pszFilename == NULL ||
-        !EQUALN(pszFilename, "PG:", 3)) {
+        !STARTS_WITH_CI(pszFilename, "PG:")) {
         /**
-         * The connection string provided is not a valid connection 
+         * The connection string provided is not a valid connection
          * string.
          */
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
             "PostGIS Raster driver was unable to parse the provided "
             "connection string." );
         return NULL;
     }
 
-    poConn = GetConnection(pszFilename, &pszConnectionString, &pszSchema, 
+    poConn = GetConnection(pszFilename, &pszConnectionString, &pszSchema,
         &pszTable, &pszColumn, &pszWhere, &nMode, &bBrowseDatabase);
-    if (poConn == NULL || bBrowseDatabase || pszTable == NULL) 
+    if (poConn == NULL || bBrowseDatabase || pszTable == NULL)
     {
         CPLFree(pszConnectionString);
         CPLFree(pszSchema);
@@ -3277,7 +3263,7 @@ PostGISRasterDataset::CreateCopy( CPL_UNUSED const char * pszFilename,
     PQclear(poResult);
 
     osCommand.Printf("create index %s_%s_gist ON %s.%s USING gist "
-        "(public.st_convexhull(%s));", pszTable, pszColumn, 
+        "(public.st_convexhull(%s));", pszTable, pszColumn,
         pszSchema, pszTable, pszColumn);
     poResult = PQexec(poConn, osCommand.c_str());
     if (
@@ -3370,7 +3356,7 @@ PostGISRasterDataset::CreateCopy( CPL_UNUSED const char * pszFilename,
             if (poSubDS == NULL) {
                 // notify!
                 CPLDebug("PostGIS_Raster", "PostGISRasterDataset::CreateCopy(): "
-                    "Could not open a subdataset: %s", 
+                    "Could not open a subdataset: %s",
                     pszSubdatasetName);
                 continue;
             }
@@ -3446,9 +3432,9 @@ PostGISRasterDataset::CreateCopy( CPL_UNUSED const char * pszFilename,
 /********************************************************
  * \brief Helper method to insert a new raster.
  ********************************************************/
-GBool 
-PostGISRasterDataset::InsertRaster(PGconn * poConn, 
-    PostGISRasterDataset * poSrcDS, const char *pszSchema, 
+GBool
+PostGISRasterDataset::InsertRaster(PGconn * poConn,
+    PostGISRasterDataset * poSrcDS, const char *pszSchema,
     const char * pszTable, const char * pszColumn)
 {
     CPLString osCommand;
@@ -3456,12 +3442,12 @@ PostGISRasterDataset::InsertRaster(PGconn * poConn,
 
     if (poSrcDS->pszWhere == NULL) {
         osCommand.Printf("insert into %s.%s (%s) (select %s from %s.%s)",
-            pszSchema, pszTable, pszColumn, poSrcDS->pszColumn, 
+            pszSchema, pszTable, pszColumn, poSrcDS->pszColumn,
             poSrcDS->pszSchema, poSrcDS->pszTable);
     }
     else {
         osCommand.Printf("insert into %s.%s (%s) (select %s from %s.%s where %s)",
-            pszSchema, pszTable, pszColumn, poSrcDS->pszColumn, 
+            pszSchema, pszTable, pszColumn, poSrcDS->pszColumn,
             poSrcDS->pszSchema, poSrcDS->pszTable, poSrcDS->pszWhere);
     }
 
@@ -3490,10 +3476,10 @@ PostGISRasterDataset::InsertRaster(PGconn * poConn,
 }
 
 /*********************************************************
- * \brief Delete a PostGIS Raster dataset. 
+ * \brief Delete a PostGIS Raster dataset.
  *********************************************************/
 CPLErr
-PostGISRasterDataset::Delete(const char* pszFilename) 
+PostGISRasterDataset::Delete(const char* pszFilename)
 {
     char* pszSchema = NULL;
     char* pszTable = NULL;
@@ -3509,18 +3495,18 @@ PostGISRasterDataset::Delete(const char* pszFilename)
 
     // Check connection string
     if (pszFilename == NULL ||
-        !EQUALN(pszFilename, "PG:", 3)) { 
+        !STARTS_WITH_CI(pszFilename, "PG:")) {
         /**
-         * The connection string provided is not a valid connection 
+         * The connection string provided is not a valid connection
          * string.
          */
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
             "PostGIS Raster driver was unable to parse the provided "
             "connection string. Nothing was deleted." );
         return CE_Failure;
     }
 
-    poConn = GetConnection(pszFilename, &pszConnectionString, 
+    poConn = GetConnection(pszFilename, &pszConnectionString,
         &pszSchema, &pszTable, &pszColumn, &pszWhere,
         &nMode, &bBrowseDatabase);
     if (poConn == NULL || pszSchema == NULL || pszTable == NULL) {
@@ -3547,7 +3533,7 @@ PostGISRasterDataset::Delete(const char* pszFilename)
 
     PQclear(poResult);
 
-    if ( nMode == ONE_RASTER_PER_TABLE || 
+    if ( nMode == ONE_RASTER_PER_TABLE ||
         (nMode == ONE_RASTER_PER_ROW && pszWhere == NULL)) {
         // without a where clause, this delete command shall delete
         // all subdatasets, even if the mode is ONE_RASTER_PER_ROW
@@ -3555,7 +3541,7 @@ PostGISRasterDataset::Delete(const char* pszFilename)
         // drop table <schema>.<table>;
         osCommand.Printf("drop table %s.%s", pszSchema, pszTable);
         poResult = PQexec(poConn, osCommand.c_str());
-        if (poResult == NULL || 
+        if (poResult == NULL ||
             PQresultStatus(poResult) != PGRES_COMMAND_OK) {
             CPLError(CE_Failure, CPLE_AppDefined,
                     "Couldn't drop the table %s.%s: %s",
@@ -3569,10 +3555,10 @@ PostGISRasterDataset::Delete(const char* pszFilename)
     else if (nMode == ONE_RASTER_PER_ROW) {
 
         // delete from <schema>.<table> where <where>
-        osCommand.Printf("delete from %s.%s where %s", pszSchema, 
+        osCommand.Printf("delete from %s.%s where %s", pszSchema,
             pszTable, pszWhere);
         poResult = PQexec(poConn, osCommand.c_str());
-        if (poResult == NULL || 
+        if (poResult == NULL ||
             PQresultStatus(poResult) != PGRES_COMMAND_OK) {
             CPLError(CE_Failure, CPLE_AppDefined,
                     "Couldn't delete records from the table %s.%s: %s",
@@ -3590,7 +3576,7 @@ PostGISRasterDataset::Delete(const char* pszFilename)
         poResult = PQexec(poConn, "commit");
         if (poResult == NULL ||
             PQresultStatus(poResult) != PGRES_COMMAND_OK) {
-                
+
             CPLError(CE_Failure, CPLE_AppDefined,
                 "Error committing database transaction: %s",
                 PQerrorMessage(poConn));
@@ -3621,7 +3607,7 @@ PostGISRasterDataset::Delete(const char* pszFilename)
  * a polygon using ST_PolygonFromText.
  **********************************************************************/
 GBool PostGISRasterDataset::PolygonFromCoords(
-    int nXOff, int nYOff, int nXEndOff, int nYEndOff, 
+    int nXOff, int nYOff, int nXEndOff, int nYEndOff,
     double adfProjWin[8])
 {
     // We first construct a polygon to intersect with
@@ -3630,40 +3616,40 @@ GBool PostGISRasterDataset::PolygonFromCoords(
     int lrx = nXEndOff;
     int lry = nYEndOff;
 
-    double xRes = adfGeoTransform[GEOTRSFRM_WE_RES]; 
-    double yRes = adfGeoTransform[GEOTRSFRM_NS_RES]; 
+    double xRes = adfGeoTransform[GEOTRSFRM_WE_RES];
+    double yRes = adfGeoTransform[GEOTRSFRM_NS_RES];
 
-    adfProjWin[0] = adfGeoTransform[GEOTRSFRM_TOPLEFT_X] + 
-                    ulx * xRes + 
+    adfProjWin[0] = adfGeoTransform[GEOTRSFRM_TOPLEFT_X] +
+                    ulx * xRes +
                     uly * adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1];
-    adfProjWin[1] = adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] + 
-                    ulx * adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] + 
+    adfProjWin[1] = adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] +
+                    ulx * adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] +
                     uly * yRes;
-    adfProjWin[2] = adfGeoTransform[GEOTRSFRM_TOPLEFT_X] + 
-                    lrx * xRes + 
+    adfProjWin[2] = adfGeoTransform[GEOTRSFRM_TOPLEFT_X] +
+                    lrx * xRes +
                     uly * adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1];
-    adfProjWin[3] = adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] + 
-                    lrx * adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] + 
+    adfProjWin[3] = adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] +
+                    lrx * adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] +
                     uly * yRes;
-    adfProjWin[4] = adfGeoTransform[GEOTRSFRM_TOPLEFT_X] + 
-                    lrx * xRes + 
+    adfProjWin[4] = adfGeoTransform[GEOTRSFRM_TOPLEFT_X] +
+                    lrx * xRes +
                     lry * adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1];
-    adfProjWin[5] = adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] + 
-                    lrx * adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] + 
+    adfProjWin[5] = adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] +
+                    lrx * adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] +
                     lry * yRes;
-    adfProjWin[6] = adfGeoTransform[GEOTRSFRM_TOPLEFT_X] + 
-                    ulx * xRes + 
+    adfProjWin[6] = adfGeoTransform[GEOTRSFRM_TOPLEFT_X] +
+                    ulx * xRes +
                     lry * adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1];
-    adfProjWin[7] = adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] + 
-                    ulx * adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] + 
+    adfProjWin[7] = adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] +
+                    ulx * adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] +
                     lry * yRes;
 
 #ifdef DEBUG_VERBOSE
-    CPLDebug("PostGIS_Raster", 
+    CPLDebug("PostGIS_Raster",
         "PostGISRasterDataset::PolygonFromCoords: constructed "
         "polygon: POLYGON((%.17f %.17f, %.17f %.17f, %.17f %.17f, "
-        "%.17f %.17f, %.17f %.17f))", adfProjWin[0], adfProjWin[1], 
-        adfProjWin[2], adfProjWin[3], adfProjWin[4], adfProjWin[5], 
+        "%.17f %.17f, %.17f %.17f))", adfProjWin[0], adfProjWin[1],
+        adfProjWin[2], adfProjWin[3], adfProjWin[4], adfProjWin[5],
         adfProjWin[6], adfProjWin[7], adfProjWin[0], adfProjWin[1]);
 #endif
 
@@ -3671,28 +3657,29 @@ GBool PostGISRasterDataset::PolygonFromCoords(
 }
 
 /***********************************************************************
- * GDALRegister_PostGISRaster()                
+ * GDALRegister_PostGISRaster()
  **********************************************************************/
-void GDALRegister_PostGISRaster() {
-    GDALDriver *poDriver;
-    
-    if (! GDAL_CHECK_VERSION("PostGISRaster driver"))
+void GDALRegister_PostGISRaster()
+
+{
+    if( !GDAL_CHECK_VERSION( "PostGISRaster driver" ) )
+        return;
+
+    if( GDALGetDriverByName( "PostGISRaster" ) != NULL )
         return;
 
-    if (GDALGetDriverByName("PostGISRaster") == NULL) {
-        poDriver = new PostGISRasterDriver();
+    GDALDriver *poDriver = new PostGISRasterDriver();
 
-        poDriver->SetDescription("PostGISRaster");
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
-                "PostGIS Raster driver");
-        poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
+    poDriver->SetDescription("PostGISRaster");
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
+                              "PostGIS Raster driver");
+    poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
 
-        poDriver->pfnOpen = PostGISRasterDataset::Open;
-        poDriver->pfnIdentify = PostGISRasterDataset::Identify;
-        poDriver->pfnCreateCopy = PostGISRasterDataset::CreateCopy;
-        poDriver->pfnDelete = PostGISRasterDataset::Delete;
+    poDriver->pfnOpen = PostGISRasterDataset::Open;
+    poDriver->pfnIdentify = PostGISRasterDataset::Identify;
+    poDriver->pfnCreateCopy = PostGISRasterDataset::CreateCopy;
+    poDriver->pfnDelete = PostGISRasterDataset::Delete;
 
-        GetGDALDriverManager()->RegisterDriver(poDriver);
-    }
+    GetGDALDriverManager()->RegisterDriver(poDriver);
 }
diff --git a/frmts/postgisraster/postgisrasterdriver.cpp b/frmts/postgisraster/postgisrasterdriver.cpp
index aec1fa1..81999ba 100644
--- a/frmts/postgisraster/postgisrasterdriver.cpp
+++ b/frmts/postgisraster/postgisrasterdriver.cpp
@@ -1,9 +1,9 @@
 /******************************************************************************
  * File :    PostGISRasterDriver.cpp
  * Project:  PostGIS Raster driver
- * Purpose:  Implements PostGIS Raster driver class methods 
+ * Purpose:  Implements PostGIS Raster driver class methods
  * Author:   Jorge Arevalo, jorge.arevalo at deimos-space.com
- * 
+ *
  * Last changes: $Id: $
  *
  ******************************************************************************
@@ -53,15 +53,15 @@ PostGISRasterDriver::~PostGISRasterDriver() {
 
 /***************************************************************************
  * \brief Create a PQconn object and store it in a list
- * 
+ *
  * The PostGIS Raster driver keeps the connection with the PostgreSQL database
- * server for as long it leaves. Following PostGISRasterDataset instance 
- * can re-use the existing connection as long it used the same database, 
+ * server for as long it leaves. Following PostGISRasterDataset instance
+ * can re-use the existing connection as long it used the same database,
  * same host, port and user name.
  *
- * The PostGIS Raster driver will keep a list of all the successful 
+ * The PostGIS Raster driver will keep a list of all the successful
  * connections so, when connection is requested and it does not exist
- * on the list a new one will be instantiated, added to the list and 
+ * on the list a new one will be instantiated, added to the list and
  * returned to the caller.
  *
  * All connection will be destroyed when the PostGISRasterDriver is destroyed.
@@ -71,7 +71,7 @@ PGconn* PostGISRasterDriver::GetConnection(const char* pszConnectionString,
         const char * pszDbnameIn, const char * pszHostIn, const char * pszPortIn, const char * pszUserIn)
 {
     PGconn * poConn = NULL;
-    
+
     if( pszHostIn == NULL ) pszHostIn = "(null)";
     if( pszPortIn == NULL ) pszPortIn = "(null)";
     if( pszUserIn == NULL ) pszUserIn = "(null)";
@@ -112,6 +112,3 @@ PGconn* PostGISRasterDriver::GetConnection(const char* pszConnectionString,
     oMapConnection[osKey] = poConn;
     return poConn;
 }
-
-
-
diff --git a/frmts/postgisraster/postgisrasterrasterband.cpp b/frmts/postgisraster/postgisrasterrasterband.cpp
index 95e8014..b682c17 100644
--- a/frmts/postgisraster/postgisrasterrasterband.cpp
+++ b/frmts/postgisraster/postgisrasterrasterband.cpp
@@ -4,7 +4,7 @@
  * Purpose:  GDAL RasterBand implementation for PostGIS Raster driver
  * Author:   Jorge Arevalo, jorge.arevalo at deimos-space.com
  *                          jorgearevalo at libregis.org
- * 
+ *
  * Author:	 David Zwarg, dzwarg at azavea.com
  *
  * Last changes: $Id: $
@@ -13,7 +13,7 @@
  * Copyright (c) 2009 - 2013, Jorge Arevalo, David Zwarg
  * Copyright (c) 2013, Even Rouault
  *
- * Permission is hereby granted, free of charge, to any person obtaining 
+ * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
  * "Software"), to deal in the Software without restriction, including
  * without limitation the rights to use, copy, modify, merge, publish,
@@ -21,55 +21,55 @@
  * permit persons to whom the Software is furnished to do so, subject to
  * the following conditions:
  *
- * The above copyright notice and this permission notice shall be 
+ * The above copyright notice and this permission notice shall be
  * included in all copies or substantial portions of the Software.
  *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
- * NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  **********************************************************************/
 #include "postgisraster.h"
 
 /**
  * \brief Constructor.
- * 
+ *
  * nBand it's just necessary for overview band creation
  */
 PostGISRasterRasterBand::PostGISRasterRasterBand(
-    PostGISRasterDataset * poDS, int nBand,
-    GDALDataType eDataType, GBool bNoDataValueSet, double dfNodata, 
-    GBool bIsOffline = false) : 
-    VRTSourcedRasterBand(poDS, nBand)
+    PostGISRasterDataset * poDSIn, int nBandIn,
+    GDALDataType eDataTypeIn, GBool bNoDataValueSetIn, double dfNodata,
+    GBool bIsOfflineIn = false) :
+    VRTSourcedRasterBand(poDSIn, nBandIn)
 {
     /* Basic properties */
-    this->poDS = poDS;
-    this->bIsOffline = bIsOffline;
-    this->nBand = nBand;
-    
-    this->eDataType = eDataType;
-    this->bNoDataValueSet = bNoDataValueSet;
-    this->dfNoDataValue = dfNodata;
-
-    this->pszSchema = poDS->pszSchema;
-    this->pszTable = poDS->pszTable;
-    this->pszColumn = poDS->pszColumn; 
+    this->poDS = poDSIn;
+    this->bIsOffline = bIsOfflineIn;
+    this->nBand = nBandIn;
+
+    this->eDataType = eDataTypeIn;
+    this->m_bNoDataValueSet = bNoDataValueSetIn;
+    this->m_dfNoDataValue = dfNodata;
+
+    this->pszSchema = poDSIn->pszSchema;
+    this->pszTable = poDSIn->pszTable;
+    this->pszColumn = poDSIn->pszColumn;
 
     nRasterXSize = poDS->GetRasterXSize();
     nRasterYSize = poDS->GetRasterYSize();
 
     /*******************************************************************
-     * Finally, set the block size. We apply the same logic than in VRT 
+     * Finally, set the block size. We apply the same logic than in VRT
      * driver.
-     * 
+     *
      * We limit the size of a block with MAX_BLOCK_SIZE here to prevent
      * arrangements of just one big tile.
-     * 
-     * This value is just used in case whe only have 1 tile in the
+     *
+     * This value is just used in case we only have 1 tile in the
      * table. Otherwise, the reading operations are performed by the
      * sources, not the PostGISRasterBand object itself.
      ******************************************************************/
@@ -77,14 +77,14 @@ PostGISRasterRasterBand::PostGISRasterRasterBand(
     this->nBlockYSize = MIN(MAX_BLOCK_SIZE, this->nRasterYSize);
 
 #ifdef DEBUG_VERBOSE
-    CPLDebug("PostGIS_Raster", 
-        "PostGISRasterRasterBand constructor: Band created (srid = %d)", 
+    CPLDebug("PostGIS_Raster",
+        "PostGISRasterRasterBand constructor: Band created (srid = %d)",
         poDS->nSrid);
-    
-    CPLDebug("PostGIS_Raster", 
-        "PostGISRasterRasterBand constructor: Band size: (%d X %d)", 
+
+    CPLDebug("PostGIS_Raster",
+        "PostGISRasterRasterBand constructor: Band size: (%d X %d)",
         nRasterXSize, nRasterYSize);
-        
+
     CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand::Constructor: "
         "Block size (%dx%d)", this->nBlockXSize, this->nBlockYSize);
 #endif
@@ -96,26 +96,26 @@ PostGISRasterRasterBand::PostGISRasterRasterBand(
 PostGISRasterRasterBand::~PostGISRasterRasterBand()
 {
 }
- 
+
 #ifdef notdef
 /***********************************************************************
- * \brief Set the block data to the null value if it is set, or zero if 
+ * \brief Set the block data to the null value if it is set, or zero if
  * there is no null data value.
  * Parameters:
  *  - void *: the block data
  * Returns: nothing
  **********************************************************************/
-void PostGISRasterRasterBand::NullBlock(void *pData) 
+void PostGISRasterRasterBand::NullBlock(void *pData)
 {
     int nWords = nBlockXSize * nBlockYSize;
     int nDataTypeSize = GDALGetDataTypeSize(eDataType) / 8;
-    
+
     int bNoDataSet;
     double dfNoData = GetNoDataValue(&bNoDataSet);
     if (!bNoDataSet) {
         memset(pData, 0, nWords * nDataTypeSize);
-    } 
-    
+    }
+
     else {
         GDALCopyWords(&dfNoData, GDT_Float64, 0,
                       pData, eDataType, nDataTypeSize,
@@ -125,11 +125,11 @@ void PostGISRasterRasterBand::NullBlock(void *pData)
 
 /***********************************************************************
  * \brief Returns the metadata for this band
- * 
- * If the metadata is actually stored in band's properties, simply 
+ *
+ * If the metadata is actually stored in band's properties, simply
  * returns them. Otherwise, it raises a query to fetch metadata
  * FROM db
- **********************************************************************/ 
+ **********************************************************************/
 GBool PostGISRasterRasterBand::GetBandMetadata(
     GDALDataType * peDataType, GBool * pbHasNoData, double * pdfNoData)
 {
@@ -137,78 +137,78 @@ GBool PostGISRasterRasterBand::GetBandMetadata(
     if (eDataType != GDT_Unknown) {
         if (peDataType)
             *peDataType = eDataType;
-            
+
         if (pbHasNoData)
             *pbHasNoData = bNoDataValueSet;
-            
+
         if (pdfNoData)
             *pdfNoData = dfNoDataValue;
-            
+
         return true;
     }
-    
+
     /**
-     * Queries are expensive. So, we only raise them if all parameters 
+     * Queries are expensive. So, we only raise them if all parameters
      * are not null
      **/
     if (!peDataType || !pbHasNoData || !pdfNoData) {
         return false;
     }
-    
+
     /**
      * It is safe to assume all the tiles will have the same values for
      * metadata properties. That was checked during band's construction
-     * (or we simply trusted the user, to avoid expensive checkings). 
+     * (or we simply trusted the user, to avoid expensive checks).
      * So, we can limit the results to just one.
      **/
     int nTuples = 0;
     CPLString osCommand = NULL;
     PGresult * poResult = NULL;
     PostGISRasterDataset * poRDS = (PostGISRasterDataset *)poDS;
-    
+
     osCommand.Printf("st_bandpixeltype(%s, %d), "
         "st_bandnodatavalue(%s, %d) is not null, "
-        "st_bandnodatavalue(%s, %d) FROM %s.%s limit 1", pszColumn, 
+        "st_bandnodatavalue(%s, %d) FROM %s.%s limit 1", pszColumn,
         nBand, pszColumn, nBand, pszColumn, nBand, pszSchema, pszTable);
-        
+
 #ifdef DEBUG_QUERY
-    CPLDebug("PostGIS_Raster", 
-        "PostGISRasterRasterBand::GetBandMetadata(): Query: %s", 
+    CPLDebug("PostGIS_Raster",
+        "PostGISRasterRasterBand::GetBandMetadata(): Query: %s",
         osCommand.c_str());
 #endif
-    
+
     poResult = PQexec(poRDS->poConn, osCommand.c_str());
     nTuples = PQntuples(poResult);
-    
+
     /* Error getting info FROM database */
-    if (poResult == NULL || 
+    if (poResult == NULL ||
         PQresultStatus(poResult) != PGRES_TUPLES_OK ||
         nTuples <= 0) {
-        
-        ReportError(CE_Failure, CPLE_AppDefined, 
+
+        ReportError(CE_Failure, CPLE_AppDefined,
             "Error getting band metadata while creating raster "
             "bands");
-            
-        CPLDebug("PostGIS_Raster", 
-            "PostGISRasterDataset::GetBandMetadata(): %s", 
+
+        CPLDebug("PostGIS_Raster",
+            "PostGISRasterDataset::GetBandMetadata(): %s",
             PQerrorMessage(poRDS->poConn));
-        
+
         if (poResult)
             PQclear(poResult);
 
         return false;
     }
-    
+
     // Fill band metadata values
     GBool bSignedByte = false;
     int nBitsDepth = 8;
     char* pszDataType = NULL;
-    
+
     pszDataType = CPLStrdup(PQgetvalue(poResult, 0, 0));
-    
-    TranslateDataType(pszDataType, &eDataType, &nBitsDepth, 
+
+    TranslateDataType(pszDataType, &eDataType, &nBitsDepth,
             &bSignedByte);
-            
+
     // Add pixeltype to image structure domain
     if (bSignedByte) {
         SetMetadataItem("PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" );
@@ -218,19 +218,19 @@ GBool PostGISRasterRasterBand::GetBandMetadata(
     if (nBitsDepth < 8)
         SetMetadataItem("NBITS", CPLString().Printf( "%d", nBitsDepth ),
             "IMAGE_STRUCTURE" );
-            
+
     CPLFree(pszDataType);
-            
-    bNoDataValueSet = 
-            EQUALN(PQgetvalue(poResult, 0, 1), "t", sizeof(char));
-            
+
+    bNoDataValueSet =
+            EQUAL(PQgetvalue(poResult, 0, 1), "t");
+
     dfNoDataValue = CPLAtof(PQgetvalue(poResult, 0, 2));
-    
+
     // Fill output arguments
     *peDataType = eDataType;
     *pbHasNoData = bNoDataValueSet;
     *pdfNoData = dfNoDataValue;
-    
+
     return true;
 }
 #endif
@@ -241,7 +241,7 @@ GBool PostGISRasterRasterBand::GetBandMetadata(
 void PostGISRasterRasterBand::NullBuffer(void* pData,
                                          int nBufXSize,
                                          int nBufYSize,
-                                         GDALDataType eBufType, 
+                                         GDALDataType eBufType,
                                          int nPixelSpace,
                                          int nLineSpace)
 {
@@ -249,8 +249,8 @@ void PostGISRasterRasterBand::NullBuffer(void* pData,
     for(j = 0; j < nBufYSize; j++)
     {
         double dfVal = 0.0;
-        if( bNoDataValueSet )
-            dfVal = dfNoDataValue;
+        if( m_bNoDataValueSet )
+            dfVal = m_dfNoDataValue;
         GDALCopyWords(&dfVal, GDT_Float64, 0,
                     (GByte*)pData + j * nLineSpace, eBufType, nPixelSpace,
                     nBufXSize);
@@ -271,7 +271,7 @@ static int SortTilesByPKID(const void* a, const void* b)
 /**
  * Read/write a region of image data for this band.
  *
- * This method allows reading a region of a PostGISRasterBand into a buffer. 
+ * This method allows reading a region of a PostGISRasterBand into a buffer.
  * The write support is still under development
  *
  * The function fetches all the raster data that intersects with the region
@@ -280,7 +280,7 @@ static int SortTilesByPKID(const void* a, const void* b)
  * It automatically takes care of data type translation if the data type
  * (eBufType) of the buffer is different than that of the PostGISRasterRasterBand.
  *
- * The nPixelSpace and nLineSpace parameters allow reading into FROM various 
+ * The nPixelSpace and nLineSpace parameters allow reading into FROM various
  * organization of buffers.
  *
  * @param eRWFlag Either GF_Read to read a region of data (GF_Write, to write
@@ -323,8 +323,8 @@ static int SortTilesByPKID(const void* a, const void* b)
  * @return CE_Failure if the access fails, otherwise CE_None.
  */
 
-CPLErr PostGISRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff, 
-    int nYOff, int nXSize, int nYSize, void * pData, int nBufXSize, 
+CPLErr PostGISRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff,
+    int nYOff, int nXSize, int nYSize, void * pData, int nBufXSize,
     int nBufYSize, GDALDataType eBufType,
     GSpacing nPixelSpace, GSpacing nLineSpace, GDALRasterIOExtraArg* psExtraArg)
 {
@@ -334,21 +334,21 @@ CPLErr PostGISRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff,
     if (eRWFlag == GF_Write) {
         ReportError(CE_Failure, CPLE_NotSupported,
             "Writing through PostGIS Raster band not supported yet");
-        
+
         return CE_Failure;
     }
 
     /*******************************************************************
      * Do we have overviews that would be appropriate to satisfy this
-     * request?                                                   
+     * request?
      ******************************************************************/
-    if( (nBufXSize < nXSize || nBufYSize < nYSize) && 
+    if( (nBufXSize < nXSize || nBufYSize < nYSize) &&
         GetOverviewCount() > 0 )
     {
-        if(OverviewRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, 
-            pData, nBufXSize, nBufYSize, eBufType, nPixelSpace, 
+        if(OverviewRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
+            pData, nBufXSize, nBufYSize, eBufType, nPixelSpace,
             nLineSpace, psExtraArg) == CE_None)
-                
+
         return CE_None;
     }
 
@@ -395,9 +395,9 @@ CPLErr PostGISRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff,
             }
         }
     }
-    
+
 #ifdef DEBUG_VERBOSE
-    CPLDebug("PostGIS_Raster", 
+    CPLDebug("PostGIS_Raster",
             "PostGISRasterRasterBand::IRasterIO: "
             "nBand = %d, nXOff = %d, nYOff = %d, nXSize = %d, nYSize = %d, nBufXSize = %d, nBufYSize = %d",
              nBand, nXOff, nYOff, nXSize,  nYSize, nBufXSize, nBufYSize);
@@ -407,19 +407,19 @@ CPLErr PostGISRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff,
     /*******************************************************************
      * Optimization: We just have one tile. So, we can read it with
      * IReadBlock
-     * 
-     * TODO: Review it. It's not working (see comment in 
+     *
+     * TODO: Review it. It's not working (see comment in
      * PostGISRasterDataset::ConstructOneDatasetFromTiles)
      ******************************************************************/
-    
+
     if (poRDS->nTiles == 1) {
-        
-        return GDALRasterBand::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, 
-            nYSize, pData, nBufXSize, nBufYSize, eBufType, nPixelSpace, 
+
+        return GDALRasterBand::IRasterIO(eRWFlag, nXOff, nYOff, nXSize,
+            nYSize, pData, nBufXSize, nBufYSize, eBufType, nPixelSpace,
             nLineSpace, psExtraArg);
     }
-#endif    
-    
+#endif
+
     /*******************************************************************
      * Several tiles: we first look in all our sources caches. Missing
      * blocks are queried
@@ -428,7 +428,7 @@ CPLErr PostGISRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff,
     int nFeatureCount = 0;
     CPLRectObj sAoi;
 
-    poRDS->PolygonFromCoords(nXOff, nYOff, nXOff + nXSize, nYOff + nYSize, adfProjWin); 
+    poRDS->PolygonFromCoords(nXOff, nYOff, nXOff + nXSize, nYOff + nYSize, adfProjWin);
     // (p[6], p[7]) is the minimum (x, y), and (p[2], p[3]) the max
     sAoi.minx = adfProjWin[6];
     sAoi.maxx = adfProjWin[2];
@@ -444,9 +444,9 @@ CPLErr PostGISRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff,
     }
 
 #ifdef DEBUG_VERBOSE
-    CPLDebug("PostGIS_Raster", 
+    CPLDebug("PostGIS_Raster",
             "PostGISRasterRasterBand::IRasterIO: "
-            "Intersection box: (%f, %f) - (%f, %f)", sAoi.minx, 
+            "Intersection box: (%f, %f) - (%f, %f)", sAoi.minx,
             sAoi.miny, sAoi.maxx, sAoi.maxy);
 #endif
 
@@ -454,10 +454,10 @@ CPLErr PostGISRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff,
     {
         ReportError(CE_Failure, CPLE_AppDefined,
             "Could not read metadata index.");
-        return CE_Failure; 
+        return CE_Failure;
     }
 
-    NullBuffer(pData, nBufXSize, nBufYSize, eBufType, nPixelSpace, nLineSpace);
+    NullBuffer(pData, nBufXSize, nBufYSize, eBufType, static_cast<int>(nPixelSpace), static_cast<int>(nLineSpace));
 
     if( poRDS->bBuildQuadTreeDynamically && !bSameWindowAsOtherBand )
     {
@@ -466,15 +466,15 @@ CPLErr PostGISRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff,
     }
 
     // Matching sources, to avoid a dumb for loop over the sources
-    PostGISRasterTileDataset ** papsMatchingTiles = 
+    PostGISRasterTileDataset ** papsMatchingTiles =
         (PostGISRasterTileDataset **)
             CPLQuadTreeSearch(poRDS->hQuadTree, &sAoi, &nFeatureCount);
-         
+
     // No blocks found. This is not an error (the raster may have holes)
     if (nFeatureCount == 0) {
         CPLFree(papsMatchingTiles);
- 
-        return CE_None; 
+
+        return CE_None;
     }
 
     int i;
@@ -482,12 +482,12 @@ CPLErr PostGISRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff,
     /**
      * We need to store the max, min coords for the missing tiles in
      * any place. This is as good as any other
-     **/ 
+     **/
     sAoi.minx = 0.0;
     sAoi.miny = 0.0;
     sAoi.maxx = 0.0;
     sAoi.maxy = 0.0;
-    
+
     GIntBig nMemoryRequiredForTiles = 0;
     CPLString osIDsToFetch;
     int nTilesToFetch = 0;
@@ -496,15 +496,15 @@ CPLErr PostGISRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff,
     // Loop just over the intersecting sources
     for(i = 0; i < nFeatureCount; i++) {
         PostGISRasterTileDataset *poTile = papsMatchingTiles[i];
-        PostGISRasterTileRasterBand* poTileBand = 
+        PostGISRasterTileRasterBand* poTileBand =
             (PostGISRasterTileRasterBand *)poTile->GetRasterBand(nBand);
 
         nMemoryRequiredForTiles += poTileBand->GetXSize() * poTileBand->GetYSize() *
             nBandDataTypeSize;
-        
+
         // Missing tile: we'll need to query for it
         if (!poTileBand->IsCached()) {
-            
+
             // If we have a PKID, add the tile PKID to the list
             if (poTile->pszPKID != NULL)
             {
@@ -522,16 +522,16 @@ CPLErr PostGISRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff,
             /**
              * We keep the general max and min values of all the missing
              * tiles, to raise a query that intersect just that area.
-             * 
+             *
              * TODO: In case of just a few tiles and very separated,
              * this strategy is clearly suboptimal. We'll get our
              * missing tiles, but with a lot of other not needed tiles.
-             * 
+             *
              * A possible optimization will be to simply rely on the
              * I/O method of the source (must be implemented), in case
              * we have minus than a reasonable amount of tiles missing.
              * Another criteria to decide would be how separated the
-             * tiles are. Two queries for just two adjacent tiles is 
+             * tiles are. Two queries for just two adjacent tiles is
              * also a dumb strategy.
              **/
             if( nTilesToFetch == 0 )
@@ -545,19 +545,18 @@ CPLErr PostGISRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff,
             {
                 if (dfTileMinX < sAoi.minx)
                     sAoi.minx = dfTileMinX;
-                    
+
                 if (dfTileMinY < sAoi.miny)
                     sAoi.miny = dfTileMinY;
-                    
+
                 if (dfTileMaxX > sAoi.maxx)
                     sAoi.maxx = dfTileMaxX;
-                    
+
                 if (dfTileMaxY > sAoi.maxy)
                     sAoi.maxy = dfTileMaxY;
             }
-            
+
             nTilesToFetch ++;
-            
         }
     }
 
@@ -575,7 +574,7 @@ CPLErr PostGISRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff,
                     nMemoryRequiredForTiles, nCacheMax );
             nTilesToFetch = 0;
         }
-        
+
         if( poRDS->GetRasterCount() > 1 && poRDS->bAssumeMultiBandReadPattern )
         {
             GIntBig nMemoryRequiredForTilesAllBands =
@@ -592,25 +591,25 @@ CPLErr PostGISRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff,
             }
         }
     }
-    
+
     // Raise a query for missing tiles and cache them
     if (nTilesToFetch > 0) {
-        
+
         /**
          * There are several options here, to raise the query.
-         * - Get all the tiles which PKID is in a list of missing 
+         * - Get all the tiles which PKID is in a list of missing
          *   PKIDs.
          * - Get all the tiles that intersect a polygon constructed
          *   based on the (min - max) values calculated before.
          * - Get all the tiles with upper left pixel included in the
          *   range (min - max) calculated before.
-         * 
+         *
          * The first option is the most efficient one when a PKID exists.
          * After that, the second one is the most efficient one when a
          * spatial index exists.
          * The third one is the only one available when neither a PKID or spatial
          * index exist.
-         **/ 
+         **/
         CPLString osCommand;
         PGresult * poResult;
 
@@ -626,7 +625,7 @@ CPLErr PostGISRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff,
                 "ST_Metadata(%s), %s FROM %s.%s",
                 osRasterToFetch.c_str(), pszColumn,
                 poRDS->GetPrimaryKeyRef(), pszSchema, pszTable);
-            if( nTilesToFetch < poRDS->nTiles || poRDS->bBuildQuadTreeDynamically )
+            if( nTilesToFetch < poRDS->m_nTiles || poRDS->bBuildQuadTreeDynamically )
             {
                 bHasWhere = TRUE;
                 osCommand += " WHERE ";
@@ -635,8 +634,8 @@ CPLErr PostGISRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff,
                 osCommand += osIDsToFetch;
                 osCommand += ")";
             }
-        } 
-        
+        }
+
         else {
             bHasWhere = TRUE;
             osCommand.Printf("SELECT %s, ST_Metadata(%s), %s FROM %s.%s WHERE ",
@@ -659,11 +658,11 @@ CPLErr PostGISRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff,
                 #define EPS 1e-5
                 osCommand += CPLSPrintf("ST_UpperLeftX(%s)"
                     " BETWEEN %f AND %f AND ST_UpperLeftY(%s) BETWEEN "
-                    "%f AND %f", pszColumn, sAoi.minx-EPS, sAoi.maxx+EPS, 
+                    "%f AND %f", pszColumn, sAoi.minx-EPS, sAoi.maxx+EPS,
                     pszColumn, sAoi.miny-EPS, sAoi.maxy+EPS);
             }
         }
-    
+
         if( poRDS->pszWhere != NULL )
         {
             if( bHasWhere )
@@ -673,29 +672,29 @@ CPLErr PostGISRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff,
             osCommand += poRDS->pszWhere;
             osCommand += ")";
         }
-        
+
         poResult = PQexec(poRDS->poConn, osCommand.c_str());
-         
+
 #ifdef DEBUG_QUERY
-        CPLDebug("PostGIS_Raster", 
-            "PostGISRasterRasterBand::IRasterIO(): Query = \"%s\" --> number of rows = %d", 
+        CPLDebug("PostGIS_Raster",
+            "PostGISRasterRasterBand::IRasterIO(): Query = \"%s\" --> number of rows = %d",
             osCommand.c_str(), poResult ? PQntuples(poResult) : 0 );
 #endif
-        
-        if (poResult == NULL || 
-            PQresultStatus(poResult) != PGRES_TUPLES_OK || 
+
+        if (poResult == NULL ||
+            PQresultStatus(poResult) != PGRES_TUPLES_OK ||
             PQntuples(poResult) < 0) {
-            
+
             if (poResult)
                 PQclear(poResult);
-     
-            CPLError(CE_Failure, CPLE_AppDefined, 
-                "PostGISRasterRasterBand::IRasterIO(): %s", 
+
+            CPLError(CE_Failure, CPLE_AppDefined,
+                "PostGISRasterRasterBand::IRasterIO(): %s",
                 PQerrorMessage(poRDS->poConn));
-            
+
             // Free the object that holds pointers to matching tiles
             CPLFree(papsMatchingTiles);
-            return CE_Failure;  
+            return CE_Failure;
         }
 
         /**
@@ -706,9 +705,9 @@ CPLErr PostGISRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff,
 
             // Free the object that holds pointers to matching tiles
             CPLFree(papsMatchingTiles);
-            return CE_None; 
+            return CE_None;
         }
-    
+
         /**
          * Ok, we loop over the results
          **/
@@ -729,7 +728,7 @@ CPLErr PostGISRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff,
 /* -------------------------------------------------------------------- */
 
     CPLErr eErr = CE_None;
-    /* Sort tiles by ascending PKID, so that the draw order is determinist */
+    /* Sort tiles by ascending PKID, so that the draw order is deterministic. */
     if( poRDS->GetPrimaryKeyRef() != NULL )
     {
         qsort(papsMatchingTiles, nFeatureCount, sizeof(PostGISRasterTileDataset*),
@@ -739,14 +738,14 @@ CPLErr PostGISRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff,
     for(i = 0; i < nFeatureCount && eErr == CE_None; i++)
     {
         PostGISRasterTileDataset *poTile = papsMatchingTiles[i];
-        PostGISRasterTileRasterBand* poTileBand = 
+        PostGISRasterTileRasterBand* poTileBand =
             (PostGISRasterTileRasterBand *)poTile->GetRasterBand(nBand);
-        eErr = 
-            poTileBand->poSource->RasterIO( nXOff, nYOff, nXSize, nYSize, 
-                                            pData, nBufXSize, nBufYSize, 
+        eErr =
+            poTileBand->poSource->RasterIO( nXOff, nYOff, nXSize, nYSize,
+                                            pData, nBufXSize, nBufYSize,
                                             eBufType, nPixelSpace, nLineSpace, NULL);
     }
-    
+
     // Free the object that holds pointers to matching tiles
     CPLFree(papsMatchingTiles);
 
@@ -761,7 +760,7 @@ CPLErr PostGISRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff,
  *  - CE_None.
  */
 CPLErr PostGISRasterRasterBand::SetNoDataValue(double dfNewValue) {
-    dfNoDataValue = dfNewValue;
+    m_dfNoDataValue = dfNewValue;
 
     return CE_None;
 }
@@ -776,9 +775,9 @@ CPLErr PostGISRasterRasterBand::SetNoDataValue(double dfNewValue) {
  */
 double PostGISRasterRasterBand::GetNoDataValue(int *pbSuccess) {
     if (pbSuccess != NULL)
-        *pbSuccess = (int) bNoDataValueSet;
+        *pbSuccess = (int) m_bNoDataValueSet;
 
-    return dfNoDataValue;
+    return m_dfNoDataValue;
 }
 
 /***************************************************
@@ -797,7 +796,7 @@ GDALRasterBand * PostGISRasterRasterBand::GetOverview(int i)
 {
     if (i < 0 || i >= GetOverviewCount())
         return NULL;
-    
+
     PostGISRasterDataset* poRDS = (PostGISRasterDataset *)poDS;
     PostGISRasterDataset* poOverviewDS = poRDS->GetOverviewDS(i);
     if( poOverviewDS->nBands == 0 )
@@ -818,7 +817,7 @@ GDALRasterBand * PostGISRasterRasterBand::GetOverview(int i)
 /*****************************************************
  * \brief Read a natural block of raster band data
  *****************************************************/
-CPLErr PostGISRasterRasterBand::IReadBlock(int nBlockXOff, 
+CPLErr PostGISRasterRasterBand::IReadBlock(int nBlockXOff,
         int nBlockYOff, void * pImage)
 {
     PGresult * poResult = NULL;
@@ -829,26 +828,26 @@ CPLErr PostGISRasterRasterBand::IReadBlock(int nBlockXOff,
     int nNaturalBlockYSize = 0;
     double adfProjWin[8];
     PostGISRasterDataset * poRDS = (PostGISRasterDataset *)poDS;
-    
+
     int nPixelSize = GDALGetDataTypeSize(eDataType) / 8;
-    
+
     // Construct a polygon to intersect with
     GetBlockSize(&nNaturalBlockXSize, &nNaturalBlockYSize);
-    
+
     nXOff = nBlockXOff * nNaturalBlockXSize;
     nYOff = nBlockYOff * nNaturalBlockYSize;
-    
+
     poRDS->PolygonFromCoords(nXOff, nYOff, nXOff + nNaturalBlockXSize, nYOff + nNaturalBlockYSize, adfProjWin);
-    
+
     // Raise the query
     if (poRDS->pszWhere == NULL) {
         osCommand.Printf("SELECT st_band(%s, %d) FROM %s.%s "
             "WHERE st_intersects(%s, ST_PolygonFromText"
             "('POLYGON((%.17f %.17f, %.17f %.17f, %.17f %.17f, %.17f "
-            "%.17f, %.17f %.17f))', %d))", pszColumn, nBand, pszSchema, 
-            pszTable, pszColumn, adfProjWin[0], adfProjWin[1], 
-            adfProjWin[2], adfProjWin[3],  adfProjWin[4], adfProjWin[5], 
-            adfProjWin[6], adfProjWin[7], adfProjWin[0], adfProjWin[1], 
+            "%.17f, %.17f %.17f))', %d))", pszColumn, nBand, pszSchema,
+            pszTable, pszColumn, adfProjWin[0], adfProjWin[1],
+            adfProjWin[2], adfProjWin[3],  adfProjWin[4], adfProjWin[5],
+            adfProjWin[6], adfProjWin[7], adfProjWin[0], adfProjWin[1],
             poRDS->nSrid);
     }
 
@@ -856,35 +855,35 @@ CPLErr PostGISRasterRasterBand::IReadBlock(int nBlockXOff,
         osCommand.Printf("SELECT st_band(%s, %d) FROM %s.%s WHERE (%s) "
             "AND st_intersects(%s, ST_PolygonFromText"
             "('POLYGON((%.17f %.17f, %.17f %.17f, %.17f %.17f, %.17f "
-            "%.17f, %.17f %.17f))', %d))", pszColumn, nBand, pszSchema, 
-            pszTable, poRDS->pszWhere, pszColumn, adfProjWin[0], 
-            adfProjWin[1], adfProjWin[2], adfProjWin[3], adfProjWin[4], 
-            adfProjWin[5], adfProjWin[6], adfProjWin[7], adfProjWin[0], 
+            "%.17f, %.17f %.17f))', %d))", pszColumn, nBand, pszSchema,
+            pszTable, poRDS->pszWhere, pszColumn, adfProjWin[0],
+            adfProjWin[1], adfProjWin[2], adfProjWin[3], adfProjWin[4],
+            adfProjWin[5], adfProjWin[6], adfProjWin[7], adfProjWin[0],
             adfProjWin[1], poRDS->nSrid);
     }
 
 #ifdef DEBUG_QUERY
-    CPLDebug("PostGIS_Raster", 
-        "PostGISRasterRasterBand::IReadBlock(): Query = %s", 
+    CPLDebug("PostGIS_Raster",
+        "PostGISRasterRasterBand::IReadBlock(): Query = %s",
             osCommand.c_str());
 #endif
 
     poResult = PQexec(poRDS->poConn, osCommand.c_str());
-    if (poResult == NULL || 
-        PQresultStatus(poResult) != PGRES_TUPLES_OK || 
+    if (poResult == NULL ||
+        PQresultStatus(poResult) != PGRES_TUPLES_OK ||
         PQntuples(poResult) < 0) {
-        
+
         if (poResult)
             PQclear(poResult);
- 
-        ReportError(CE_Failure, CPLE_AppDefined, 
+
+        ReportError(CE_Failure, CPLE_AppDefined,
             "Error retrieving raster data FROM database");
 
-        CPLDebug("PostGIS_Raster", 
-            "PostGISRasterRasterBand::IRasterIO(): %s", 
+        CPLDebug("PostGIS_Raster",
+            "PostGISRasterRasterBand::IRasterIO(): %s",
                 PQerrorMessage(poRDS->poConn));
-        
-        return CE_Failure;  
+
+        return CE_Failure;
     }
 
     /**
@@ -892,36 +891,35 @@ CPLErr PostGISRasterRasterBand::IReadBlock(int nBlockXOff,
      **/
     else if (PQntuples(poResult) == 0) {
         PQclear(poResult);
-        
-        CPLDebug("PostGIS_Raster", 
+
+        CPLDebug("PostGIS_Raster",
             "PostGISRasterRasterBand::IRasterIO(): Null block");
 
         NullBlock(pImage);
 
-        return CE_None; 
+        return CE_None;
     }
-    
-    
+
     /**
-     * Ok, we get the data. Only data size, without payload 
-     * 
+     * Ok, we get the data. Only data size, without payload
+     *
      * TODO: Check byte order
      **/
     int nExpectedDataSize = nNaturalBlockXSize * nNaturalBlockYSize *
         nPixelSize;
-        
+
     int nWKBLength = 0;
-    
-    GByte * pbyData = CPLHexToBinary(PQgetvalue(poResult, 0, 0), 
+
+    GByte * pbyData = CPLHexToBinary(PQgetvalue(poResult, 0, 0),
         &nWKBLength);
-        
-    char * pbyDataToRead = (char*)GET_BAND_DATA(pbyData,nBand, 
+
+    char * pbyDataToRead = (char*)GET_BAND_DATA(pbyData,nBand,
             nPixelSize, nExpectedDataSize);
 
     memcpy(pImage, pbyDataToRead, nExpectedDataSize * sizeof(char));
-    
+
     CPLDebug("PostGIS_Raster", "IReadBlock: Copied %d bytes FROM block "
-            "(%d, %d) to %p", nExpectedDataSize, nBlockXOff, 
+            "(%d, %d) to %p", nExpectedDataSize, nBlockXOff,
             nBlockYOff, pImage);
 
     CPLFree(pbyData);
@@ -933,31 +931,31 @@ CPLErr PostGISRasterRasterBand::IReadBlock(int nBlockXOff,
 
 /**
  * \brief How should this band be interpreted as color?
- * GCI_Undefined is returned when the format doesn't know anything about the 
- * color interpretation. 
+ * GCI_Undefined is returned when the format doesn't know anything about the
+ * color interpretation.
  **/
 GDALColorInterp PostGISRasterRasterBand::GetColorInterpretation()
 {
     if (poDS->GetRasterCount() == 1) {
-        eColorInterp = GCI_GrayIndex;
+        m_eColorInterp = GCI_GrayIndex;
     }
 
     else if (poDS->GetRasterCount() == 3) {
         if (nBand == 1)
-            eColorInterp = GCI_RedBand;
+            m_eColorInterp = GCI_RedBand;
         else if( nBand == 2 )
-            eColorInterp = GCI_GreenBand;
+            m_eColorInterp = GCI_GreenBand;
         else if( nBand == 3 )
-            eColorInterp = GCI_BlueBand;
+            m_eColorInterp = GCI_BlueBand;
         else
-            eColorInterp = GCI_Undefined;
+            m_eColorInterp = GCI_Undefined;
     }
 
     else {
-        eColorInterp = GCI_Undefined;
+        m_eColorInterp = GCI_Undefined;
     }
-    
-    return eColorInterp; 
+
+    return m_eColorInterp;
 }
 
 /************************************************************************/
@@ -967,7 +965,7 @@ GDALColorInterp PostGISRasterRasterBand::GetColorInterpretation()
 double PostGISRasterRasterBand::GetMinimum( int *pbSuccess )
 {
     PostGISRasterDataset * poRDS = (PostGISRasterDataset *)poDS;
-    if( poRDS->bBuildQuadTreeDynamically && poRDS->nTiles == 0 )
+    if( poRDS->bBuildQuadTreeDynamically && poRDS->m_nTiles == 0 )
     {
         if( pbSuccess )
             *pbSuccess = FALSE;
@@ -983,7 +981,7 @@ double PostGISRasterRasterBand::GetMinimum( int *pbSuccess )
 double PostGISRasterRasterBand::GetMaximum( int *pbSuccess )
 {
     PostGISRasterDataset * poRDS = (PostGISRasterDataset *)poDS;
-    if( poRDS->bBuildQuadTreeDynamically && poRDS->nTiles == 0 )
+    if( poRDS->bBuildQuadTreeDynamically && poRDS->m_nTiles == 0 )
     {
         if( pbSuccess )
             *pbSuccess = FALSE;
@@ -1007,6 +1005,6 @@ CPLErr PostGISRasterRasterBand::ComputeRasterMinMax( int bApproxOK, double* adfM
         if( GetOverview(i)->GetXSize() < 1024 && GetOverview(i)->GetYSize() < 1024 )
             return GetOverview(i)->ComputeRasterMinMax(bApproxOK, adfMinMax);
     }
-    
+
     return CE_Failure;
 }
diff --git a/frmts/postgisraster/postgisrastertiledataset.cpp b/frmts/postgisraster/postgisrastertiledataset.cpp
index 3520602..abc3038 100644
--- a/frmts/postgisraster/postgisrastertiledataset.cpp
+++ b/frmts/postgisraster/postgisrastertiledataset.cpp
@@ -11,7 +11,7 @@
  * Copyright (c) 2013, Jorge Arevalo
  * Copyright (c) 2013, Even Rouault
  *
- * Permission is hereby granted, free of charge, to any person obtaining 
+ * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
  * "Software"), to deal in the Software without restriction, including
  * without limitation the rights to use, copy, modify, merge, publish,
@@ -19,16 +19,16 @@
  * permit persons to whom the Software is furnished to do so, subject to
  * the following conditions:
  *
- * The above copyright notice and this permission notice shall be 
+ * The above copyright notice and this permission notice shall be
  * included in all copies or substantial portions of the Software.
  *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
- * NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  ************************************************************************/
 #include "postgisraster.h"
@@ -36,11 +36,11 @@
 /************************
  * \brief Constructor
  ************************/
-PostGISRasterTileDataset::PostGISRasterTileDataset(PostGISRasterDataset* poRDS,
-                                                   int nXSize, 
+PostGISRasterTileDataset::PostGISRasterTileDataset(PostGISRasterDataset* poRDSIn,
+                                                   int nXSize,
                                                    int nYSize)
 {
-    this->poRDS = poRDS;
+    this->poRDS = poRDSIn;
     this->pszPKID = NULL;
     this->nRasterXSize = nXSize;
     this->nRasterYSize = nYSize;
@@ -91,12 +91,12 @@ void PostGISRasterTileDataset::GetExtent(double* pdfMinX, double* pdfMinY,
     double dfMinX = adfGeoTransform[GEOTRSFRM_TOPLEFT_X];
     double dfMaxY = adfGeoTransform[GEOTRSFRM_TOPLEFT_Y];
 
-    double dfMaxX = adfGeoTransform[GEOTRSFRM_TOPLEFT_X] + 
-            nRasterXSize * adfGeoTransform[GEOTRSFRM_WE_RES] + 
+    double dfMaxX = adfGeoTransform[GEOTRSFRM_TOPLEFT_X] +
+            nRasterXSize * adfGeoTransform[GEOTRSFRM_WE_RES] +
             nRasterYSize * adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1];
-            
-    double dfMinY = adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] + 
-            nRasterXSize * adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] +  
+
+    double dfMinY = adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] +
+            nRasterXSize * adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] +
             nRasterYSize * adfGeoTransform[GEOTRSFRM_NS_RES];
 
     // In case yres > 0
@@ -106,7 +106,7 @@ void PostGISRasterTileDataset::GetExtent(double* pdfMinX, double* pdfMinY,
         dfMinY = dfMaxY;
         dfMaxY = dfTemp;
     }
-    
+
     *pdfMinX = dfMinX;
     *pdfMinY = dfMinY;
     *pdfMaxX = dfMaxX;
diff --git a/frmts/postgisraster/postgisrastertilerasterband.cpp b/frmts/postgisraster/postgisrastertilerasterband.cpp
index 8a8b7de..1c1f5cd 100644
--- a/frmts/postgisraster/postgisrastertilerasterband.cpp
+++ b/frmts/postgisraster/postgisrastertilerasterband.cpp
@@ -1,7 +1,7 @@
 /***********************************************************************
  * File :    postgisrastertilerasterband.cpp
  * Project:  PostGIS Raster driver
- * Purpose:  GDAL Tile RasterBand implementation for PostGIS Raster 
+ * Purpose:  GDAL Tile RasterBand implementation for PostGIS Raster
  * driver
  * Author:   Jorge Arevalo, jorge.arevalo at deimos-space.com
  *                          jorgearevalo at libregis.org
@@ -11,7 +11,7 @@
  * Copyright (c) 2009 - 2013, Jorge Arevalo
  * Copyright (c) 2013, Even Rouault
  *
- * Permission is hereby granted, free of charge, to any person obtaining 
+ * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
  * "Software"), to deal in the Software without restriction, including
  * without limitation the rights to use, copy, modify, merge, publish,
@@ -19,16 +19,16 @@
  * permit persons to whom the Software is furnished to do so, subject to
  * the following conditions:
  *
- * The above copyright notice and this permission notice shall be 
+ * The above copyright notice and this permission notice shall be
  * included in all copies or substantial portions of the Software.
  *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
- * NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  **********************************************************************/
 #include "postgisraster.h"
@@ -37,28 +37,29 @@
  * \brief Constructor
  ************************/
 PostGISRasterTileRasterBand::PostGISRasterTileRasterBand(
-    PostGISRasterTileDataset * poRTDS, int nBand,
-    GDALDataType eDataType, GBool bIsOffline)
+    PostGISRasterTileDataset * poRTDSIn, int nBandIn,
+    GDALDataType eDataTypeIn, GBool bIsOfflineIn)
 {
     /* Basic properties */
-    this->poDS = poRTDS;
-    this->bIsOffline = bIsOffline;
-    this->nBand = nBand;
-    
+    this->poDS = poRTDSIn;
+    this->bIsOffline = bIsOfflineIn;
+    this->nBand = nBandIn;
+
 #if 0
-    CPLDebug("PostGIS_Raster", 
+    CPLDebug("PostGIS_Raster",
         "PostGISRasterTileRasterBand::Constructor: Raster tile dataset "
-        "of dimensions %dx%d", poRTDS->GetRasterXSize(), 
+        "of dimensions %dx%d", poRTDS->GetRasterXSize(),
         poRTDS->GetRasterYSize());
 #endif
 
-    this->eDataType = eDataType;
+    this->eDataType = eDataTypeIn;
 
-    nRasterXSize = poRTDS->GetRasterXSize();
-    nRasterYSize = poRTDS->GetRasterYSize();
+    nRasterXSize = poRTDSIn->GetRasterXSize();
+    nRasterYSize = poRTDSIn->GetRasterYSize();
 
     nBlockXSize = nRasterXSize;
     nBlockYSize = nRasterYSize;
+    poSource = NULL;
 }
 
 
@@ -71,7 +72,7 @@ PostGISRasterTileRasterBand::~PostGISRasterTileRasterBand()
 
 /***********************************************************************
  * \brief Returns true if the (only) block is stored in the cache
- **********************************************************************/ 
+ **********************************************************************/
 GBool PostGISRasterTileRasterBand::IsCached()
 {
     GDALRasterBlock * poBlock = TryGetLockedBlockRef(0, 0);
@@ -79,7 +80,7 @@ GBool PostGISRasterTileRasterBand::IsCached()
         poBlock->DropLock();
         return true;
     }
-    
+
     return false;
 }
 
@@ -98,45 +99,45 @@ CPLErr PostGISRasterTileRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff,
 
     PostGISRasterTileDataset * poRTDS =
         (PostGISRasterTileDataset *)poDS;
-        
+
     // Get by PKID
     if (poRTDS->poRDS->pszPrimaryKeyName) {
+        //osCommand.Printf("select ST_AsBinary(st_band(%s, %d),TRUE) from %s.%s where "
         osCommand.Printf("select st_band(%s, %d) from %s.%s where "
             "%s = '%s'", poRTDS->poRDS->pszColumn, nBand, poRTDS->poRDS->pszSchema, poRTDS->poRDS->pszTable,
             poRTDS->poRDS->pszPrimaryKeyName, poRTDS->pszPKID);
 
     }
-    
+
     // Get by upperleft
     else {
         osCommand.Printf("select st_band(%s, %d) from %s.%s where "
-            "abs(ST_UpperLeftX(%s) - %.8f) < 1e-8 and abs(ST_UpperLeftY(%s) - %.8f) < 1e-8", 
-            poRTDS->poRDS->pszColumn, nBand, poRTDS->poRDS->pszSchema, poRTDS->poRDS->pszTable, poRTDS->poRDS->pszColumn, 
-            poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_X], poRTDS->poRDS->pszColumn, 
+            "abs(ST_UpperLeftX(%s) - %.8f) < 1e-8 and abs(ST_UpperLeftY(%s) - %.8f) < 1e-8",
+            poRTDS->poRDS->pszColumn, nBand, poRTDS->poRDS->pszSchema, poRTDS->poRDS->pszTable, poRTDS->poRDS->pszColumn,
+            poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_X], poRTDS->poRDS->pszColumn,
             poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_Y]);
-        
     }
-    
+
     poResult = PQexec(poRTDS->poRDS->poConn, osCommand.c_str());
-    
+
 #ifdef DEBUG_QUERY
     CPLDebug("PostGIS_Raster", "PostGISRasterTileRasterBand::IReadBlock(): "
              "Query = \"%s\" --> number of rows = %d",
              osCommand.c_str(), poResult ? PQntuples(poResult) : 0 );
 #endif
 
-    if (poResult == NULL || 
+    if (poResult == NULL ||
         PQresultStatus(poResult) != PGRES_TUPLES_OK ||
         PQntuples(poResult) <= 0) {
-            
+
         if (poResult)
             PQclear(poResult);
-            
+
         ReportError(CE_Failure, CPLE_AppDefined,
             "Error getting block of data (upperpixel = %f, %f)",
-                poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_X], 
+                poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_X],
                 poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_Y]);
-            
+
         return CE_Failure;
     }
 
@@ -145,16 +146,16 @@ CPLErr PostGISRasterTileRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff,
     if (bIsOffline) {
         CPLError(CE_Failure, CPLE_AppDefined, "This raster has outdb "
             "storage. This feature isn't still available");
-        
-        PQclear(poResult);    
+
+        PQclear(poResult);
         return CE_Failure;
     }
-    
+
     /* Copy only data size, without payload */
-    int nExpectedDataSize = 
+    int nExpectedDataSize =
         nBlockXSize * nBlockYSize * nPixelSize;
-        
-    GByte * pbyData = CPLHexToBinary(PQgetvalue(poResult, 0, 0), 
+
+    GByte * pbyData = CPLHexToBinary(PQgetvalue(poResult, 0, 0),
         &nWKBLength);
     int nExpectedWKBLength = RASTER_HEADER_SIZE + BAND_SIZE(nPixelSize, nExpectedDataSize);
     CPLErr eRet = CE_None;
@@ -165,8 +166,8 @@ CPLErr PostGISRasterTileRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff,
     }
     else
     {
-        GByte * pbyDataToRead = 
-        (GByte*)GET_BAND_DATA(pbyData,1, nPixelSize, 
+        GByte * pbyDataToRead =
+        (GByte*)GET_BAND_DATA(pbyData,1, nPixelSize,
             nExpectedDataSize);
 
         // Do byte-swapping if necessary */
diff --git a/frmts/postgisraster/postgisrastertools.cpp b/frmts/postgisraster/postgisrastertools.cpp
index 5b4d58d..c409cca 100644
--- a/frmts/postgisraster/postgisrastertools.cpp
+++ b/frmts/postgisraster/postgisrastertools.cpp
@@ -4,7 +4,7 @@
  * Purpose:  Tools for PostGIS Raster driver
  * Author:   Jorge Arevalo, jorge.arevalo at deimos-space.com
  *                          jorgearevalo at libregis.org
- * 
+ *
  * Author:	 David Zwarg, dzwarg at azavea.com
  *
  * Last changes: $Id: $
@@ -12,7 +12,7 @@
  ***********************************************************************
  * Copyright (c) 2009 - 2013, Jorge Arevalo, David Zwarg
  *
- * Permission is hereby granted, free of charge, to any person obtaining 
+ * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
  * "Software"), to deal in the Software without restriction, including
  * without limitation the rights to use, copy, modify, merge, publish,
@@ -20,21 +20,20 @@
  * permit persons to whom the Software is furnished to do so, subject to
  * the following conditions:
  *
- * The above copyright notice and this permission notice shall be 
+ * The above copyright notice and this permission notice shall be
  * included in all copies or substantial portions of the Software.
  *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
- * NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  **********************************************************************/
  #include "postgisraster.h"
- 
- 
+
  /**********************************************************************
  * \brief Replace the quotes by single quotes in the input string
  *
@@ -45,7 +44,7 @@ char * ReplaceQuotes(const char * pszInput, int nLength) {
     char * pszOutput = NULL;
 
     if (nLength == -1)
-        nLength = strlen(pszInput);
+        nLength = static_cast<int>(strlen(pszInput));
 
     pszOutput = (char*) CPLCalloc(nLength + 1, sizeof (char));
 
@@ -69,7 +68,7 @@ char * ReplaceSingleQuotes(const char * pszInput, int nLength) {
     char* pszOutput = NULL;
 
     if (nLength == -1)
-        nLength = strlen(pszInput);
+        nLength = static_cast<int>(strlen(pszInput));
 
     pszOutput = (char*) CPLCalloc(nLength + 1, sizeof (char));
 
@@ -97,15 +96,15 @@ char** ParseConnectionString(const char * pszConnectionString) {
     char * pszEscapedConnectionString = NULL;
 
     /* Escape string following SQL scheme */
-    pszEscapedConnectionString = 
+    pszEscapedConnectionString =
         ReplaceSingleQuotes(pszConnectionString, -1);
 
     /* Avoid PG: part */
-    char* pszStartPos = (char*) 
+    char* pszStartPos = (char*)
         strstr(pszEscapedConnectionString, ":") + 1;
 
     /* Tokenize */
-    char** papszParams = 
+    char** papszParams =
         CSLTokenizeString2(pszStartPos, " ", CSLT_HONOURSTRINGS);
 
     /* Free */
@@ -115,7 +114,7 @@ char** ParseConnectionString(const char * pszConnectionString) {
 }
 
 /***********************************************************************
- * \brief Translate a PostGIS Raster datatype string in a valid 
+ * \brief Translate a PostGIS Raster datatype string in a valid
  * GDALDataType object.
  **********************************************************************/
 GBool TranslateDataType(const char * pszDataType,
@@ -128,35 +127,35 @@ GBool TranslateDataType(const char * pszDataType,
     if (pbSignedByte)
         *pbSignedByte = false;
 
-    if (EQUALN(pszDataType, "1BB", 3 * sizeof(char))) {
+    if (EQUAL(pszDataType, "1BB")) {
         if (pnBitsDepth)
             *pnBitsDepth = 1;
         if (poDataType)
             *poDataType = GDT_Byte;
     }
 
-    else if (EQUALN(pszDataType, "2BUI", 4 * sizeof (char))) {
+    else if (EQUAL(pszDataType, "2BUI")) {
         if (pnBitsDepth)
             *pnBitsDepth = 2;
         if (poDataType)
             *poDataType = GDT_Byte;
     }
 
-    else if (EQUALN(pszDataType, "4BUI", 4 * sizeof (char))) {
+    else if (EQUAL(pszDataType, "4BUI")) {
         if (pnBitsDepth)
             *pnBitsDepth = 4;
         if (poDataType)
             *poDataType = GDT_Byte;
     }
 
-    else if (EQUALN(pszDataType, "8BUI", 4 * sizeof (char))) {
+    else if (EQUAL(pszDataType, "8BUI")) {
         if (pnBitsDepth)
             *pnBitsDepth = 8;
         if (poDataType)
             *poDataType = GDT_Byte;
     }
 
-    else if (EQUALN(pszDataType, "8BSI", 4 * sizeof (char))) {
+    else if (EQUAL(pszDataType, "8BSI")) {
         if (pnBitsDepth)
             *pnBitsDepth = 8;
         if (poDataType)
@@ -170,42 +169,42 @@ GBool TranslateDataType(const char * pszDataType,
         if (pbSignedByte)
             *pbSignedByte = true;
     }
-    else if (EQUALN(pszDataType, "16BSI", 5 * sizeof (char))) {
+    else if (EQUAL(pszDataType, "16BSI")) {
         if (pnBitsDepth)
             *pnBitsDepth = 16;
         if (poDataType)
             *poDataType = GDT_Int16;
     }
 
-    else if (EQUALN(pszDataType, "16BUI", 5 * sizeof (char))) {
+    else if (EQUAL(pszDataType, "16BUI")) {
         if (pnBitsDepth)
             *pnBitsDepth = 16;
         if (poDataType)
             *poDataType = GDT_UInt16;
     }
 
-    else if (EQUALN(pszDataType, "32BSI", 5 * sizeof (char))) {
+    else if (EQUAL(pszDataType, "32BSI")) {
         if (pnBitsDepth)
             *pnBitsDepth = 32;
         if (poDataType)
             *poDataType = GDT_Int32;
     }
 
-    else if (EQUALN(pszDataType, "32BUI", 5 * sizeof (char))) {
+    else if (EQUAL(pszDataType, "32BUI")) {
         if (pnBitsDepth)
             *pnBitsDepth = 32;
         if (poDataType)
             *poDataType = GDT_UInt32;
     }
 
-    else if (EQUALN(pszDataType, "32BF", 4 * sizeof (char))) {
+    else if (EQUAL(pszDataType, "32BF")) {
         if (pnBitsDepth)
             *pnBitsDepth = 32;
         if (poDataType)
             *poDataType = GDT_Float32;
     }
 
-    else if (EQUALN(pszDataType, "64BF", 4 * sizeof (char))) {
+    else if (EQUAL(pszDataType, "64BF")) {
         if (pnBitsDepth)
             *pnBitsDepth = 64;
         if (poDataType)
@@ -223,4 +222,3 @@ GBool TranslateDataType(const char * pszDataType,
 
     return true;
 }
-
diff --git a/frmts/r/frmt_r.html b/frmts/r/frmt_r.html
index 9507ed7..530eb17 100644
--- a/frmts/r/frmt_r.html
+++ b/frmts/r/frmt_r.html
@@ -7,14 +7,14 @@
 
 <h1>R -- R Object Data Store</h1>
 
-The R Object File Format is supported for write access, and limited 
+The R Object File Format is supported for write access, and limited
 read access by GDAL.  This format is the native format R uses for objects
 saved with the <i>save</i> command and loaded with the <i>load</i> command.
-GDAL supports writing a dataset as an array object in this format, and 
-supports reading files with simple rasters in essentially the same 
+GDAL supports writing a dataset as an array object in this format, and
+supports reading files with simple rasters in essentially the same
 organization.  It will not read most R object files.<p>
 
-Currently there is no support for reading or writing georeferencing 
+Currently there is no support for reading or writing georeferencing
 information. <p>
 
 <h2>Creation Options</h2>
diff --git a/frmts/r/rcreatecopy.cpp b/frmts/r/rcreatecopy.cpp
index a4d07f1..67db898 100644
--- a/frmts/r/rcreatecopy.cpp
+++ b/frmts/r/rcreatecopy.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rcreatecopy.cpp 28785 2015-03-26 20:46:45Z goatbar $
+ * $Id: rcreatecopy.cpp 33841 2016-04-01 01:16:15Z goatbar $
  *
  * Project:  R Format Driver
  * Purpose:  CreateCopy() implementation for R stats package object format.
@@ -27,10 +27,16 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
 #include "cpl_string.h"
+#include "gdal_pam.h"
+
+CPL_CVSID("$Id: rcreatecopy.cpp 33841 2016-04-01 01:16:15Z goatbar $");
 
-CPL_CVSID("$Id: rcreatecopy.cpp 28785 2015-03-26 20:46:45Z goatbar $");
+
+GDALDataset *
+RCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
+             int bStrict, char ** papszOptions,
+             GDALProgressFunc pfnProgress, void * pProgressData );
 
 /************************************************************************/
 /* ==================================================================== */
@@ -47,8 +53,8 @@ static void RWriteInteger( VSILFILE *fp, int bASCII, int nValue )
 {
     if( bASCII )
     {
-        char szOutput[50];
-        sprintf( szOutput, "%d\n", nValue );
+        char szOutput[50] = { '\0' };
+        snprintf( szOutput, sizeof(szOutput), "%d\n", nValue );
         VSIFWriteL( szOutput, 1, strlen(szOutput), fp );
     }
     else
@@ -67,7 +73,7 @@ static void RWriteString( VSILFILE *fp, int bASCII, const char *pszValue )
 {
     RWriteInteger( fp, bASCII, 4105 );
     RWriteInteger( fp, bASCII, (int) strlen(pszValue) );
-    
+
     if( bASCII )
     {
         VSIFWriteL( pszValue, 1, strlen(pszValue), fp );
@@ -91,11 +97,12 @@ RCreateCopy( const char * pszFilename,
              GDALProgressFunc pfnProgress,
              void * pProgressData )
 {
-    int  nBands = poSrcDS->GetRasterCount();
-    int  nXSize = poSrcDS->GetRasterXSize();
-    int  nYSize = poSrcDS->GetRasterYSize();
-    int  bASCII = CSLFetchBoolean( papszOptions, "ASCII", FALSE );
-    int  bCompressed = CSLFetchBoolean( papszOptions, "COMPRESS", !bASCII );
+    const int nBands = poSrcDS->GetRasterCount();
+    const int nXSize = poSrcDS->GetRasterXSize();
+    const int nYSize = poSrcDS->GetRasterYSize();
+    const int bASCII = CSLFetchBoolean( papszOptions, "ASCII", FALSE );
+    const bool bCompressed =
+        CPL_TO_BOOL( CSLFetchBoolean( papszOptions, "COMPRESS", !bASCII ) );
 
 /* -------------------------------------------------------------------- */
 /*      Some some rudimentary checks                                    */
@@ -115,13 +122,11 @@ RCreateCopy( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Create the file.                                                */
 /* -------------------------------------------------------------------- */
-    VSILFILE	*fp;
-
-    fp = VSIFOpenL( osAdjustedFilename, "wb" );
+    VSILFILE *fp = VSIFOpenL( osAdjustedFilename, "wb" );
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Unable to create file %s.\n", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Unable to create file %s.",
                   pszFilename );
         return NULL;
     }
@@ -148,7 +153,7 @@ RCreateCopy( const char * pszFilename,
 /*      Establish the primary pairlist with one component object.       */
 /* -------------------------------------------------------------------- */
     RWriteInteger( fp, bASCII, 1026 );
-    RWriteInteger( fp, bASCII, 1 );  
+    RWriteInteger( fp, bASCII, 1 );
 
 /* -------------------------------------------------------------------- */
 /*      Write the object name.  Eventually we should derive this        */
@@ -167,21 +172,20 @@ RCreateCopy( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Write the raster data.                                          */
 /* -------------------------------------------------------------------- */
-    double 	*padfScanline;
-    CPLErr      eErr = CE_None;
-    int         iLine;
+    CPLErr eErr = CE_None;
 
-    padfScanline = (double *) CPLMalloc( nXSize * sizeof(double) );
+    double *padfScanline =
+        static_cast<double *>( CPLMalloc( nXSize * sizeof(double) ) );
 
     for( int iBand = 0; iBand < nBands; iBand++ )
     {
-        GDALRasterBand * poBand = poSrcDS->GetRasterBand( iBand+1 );
+        GDALRasterBand *poBand = poSrcDS->GetRasterBand( iBand+1 );
 
-        for( iLine = 0; iLine < nYSize && eErr == CE_None; iLine++ )
+        for( int iLine = 0; iLine < nYSize && eErr == CE_None; iLine++ )
         {
             int iValue;
 
-            eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, 
+            eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1,
                                      padfScanline, nXSize, 1, GDT_Float64,
                                      sizeof(double), 0, NULL );
 
@@ -189,8 +193,9 @@ RCreateCopy( const char * pszFilename,
             {
                 for( iValue = 0; iValue < nXSize; iValue++ )
                 {
-                    char szValue[128];
-                    CPLsprintf(szValue,"%.16g\n", padfScanline[iValue] );
+                    char szValue[128] = { '\0' };
+                    CPLsnprintf( szValue, sizeof(szValue), "%.16g\n",
+                                 padfScanline[iValue] );
                     VSIFWriteL( szValue, 1, strlen(szValue), fp );
                 }
             }
@@ -201,7 +206,7 @@ RCreateCopy( const char * pszFilename,
 
                 VSIFWriteL( padfScanline, 8, nXSize, fp );
             }
-            
+
             if( eErr == CE_None
                 && !pfnProgress( (iLine+1) / (double) nYSize,
                                  NULL, pProgressData ) )
@@ -219,8 +224,8 @@ RCreateCopy( const char * pszFilename,
 /*      Write out the dims attribute.                                   */
 /* -------------------------------------------------------------------- */
     RWriteInteger( fp, bASCII, 1026 );
-    RWriteInteger( fp, bASCII, 1 );  
-    
+    RWriteInteger( fp, bASCII, 1 );
+
     RWriteString( fp, bASCII, "dim" );
 
     RWriteInteger( fp, bASCII, 13 );
@@ -248,7 +253,7 @@ RCreateCopy( const char * pszFilename,
 /*      Re-open dataset, and copy any auxiliary pam information.         */
 /* -------------------------------------------------------------------- */
     GDALPamDataset *poDS =
-        (GDALPamDataset *) GDALOpen( pszFilename, GA_ReadOnly );
+        static_cast<GDALPamDataset *>( GDALOpen( pszFilename, GA_ReadOnly ) );
 
     if( poDS )
         poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
diff --git a/frmts/r/rdataset.cpp b/frmts/r/rdataset.cpp
index 2e1af14..869c9d3 100644
--- a/frmts/r/rdataset.cpp
+++ b/frmts/r/rdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rdataset.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: rdataset.cpp 33841 2016-04-01 01:16:15Z goatbar $
  *
  * Project:  R Format Driver
  * Purpose:  Read/write R stats package object format.
@@ -28,27 +28,24 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
 #include "../raw/rawdataset.h"
 
-CPL_CVSID("$Id: rdataset.cpp 27942 2014-11-11 00:57:41Z rouault $");
-
-CPL_C_START
-void    GDALRegister_R(void);
-CPL_C_END
+CPL_CVSID("$Id: rdataset.cpp 33841 2016-04-01 01:16:15Z goatbar $");
 
 GDALDataset *
-RCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
-             int bStrict, char ** papszOptions, 
+RCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
+             int bStrict, char ** papszOptions,
              GDALProgressFunc pfnProgress, void * pProgressData );
 
-#define R_NILSXP        0
-#define R_LISTSXP       2
-#define R_CHARSXP       9
-#define R_INTSXP        13
-#define R_REALSXP       14
-#define R_STRSXP        16
+// static const int R_NILSXP = 0;
+static const int R_LISTSXP = 2;
+static const int R_CHARSXP = 9;
+static const int R_INTSXP = 13;
+static const int R_REALSXP = 14;
+static const int R_STRSXP = 16;
 
 /************************************************************************/
 /* ==================================================================== */
@@ -59,7 +56,7 @@ RCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 class RDataset : public GDALPamDataset
 {
     friend class RRasterBand;
-    VSILFILE       *fp;
+    VSILFILE   *fp;
     int         bASCII;
     CPLString   osLastStringRead;
 
@@ -94,9 +91,8 @@ class RRasterBand : public GDALPamRasterBand
     const double *padfMatrixValues;
 
   public:
-
                 RRasterBand( RDataset *, int, const double * );
-                ~RRasterBand();
+    virtual ~RRasterBand() {}
 
     virtual CPLErr          IReadBlock( int, int, void * );
 };
@@ -105,32 +101,24 @@ class RRasterBand : public GDALPamRasterBand
 /*                            RRasterBand()                             */
 /************************************************************************/
 
-RRasterBand::RRasterBand( RDataset *poDS, int nBand, 
-                          const double *padfMatrixValues )
+RRasterBand::RRasterBand( RDataset *poDSIn, int nBandIn,
+                          const double *padfMatrixValuesIn ) :
+    padfMatrixValues(padfMatrixValuesIn)
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
-    this->padfMatrixValues = padfMatrixValues;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
     eDataType = GDT_Float64;
 
-    nBlockXSize = poDS->nRasterXSize;
+    nBlockXSize = poDSIn->nRasterXSize;
     nBlockYSize = 1;
 }
 
 /************************************************************************/
-/*                            ~RRasterBand()                            */
-/************************************************************************/
-
-RRasterBand::~RRasterBand()
-{
-}
-
-/************************************************************************/
 /*                             IReadBlock()                             */
 /************************************************************************/
 
-CPLErr RRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
+CPLErr RRasterBand::IReadBlock( int /* nBlockXOff */,
                                 int nBlockYOff,
                                 void * pImage )
 {
@@ -149,11 +137,12 @@ CPLErr RRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /*                              RDataset()                              */
 /************************************************************************/
 
-RDataset::RDataset()
-{
-    fp = NULL;
-    padfMatrixValues = NULL;
-}
+RDataset::RDataset() :
+    fp(NULL),
+    bASCII(FALSE),
+    nStartOfData(0),
+    padfMatrixValues(NULL)
+{ }
 
 /************************************************************************/
 /*                             ~RDataset()                              */
@@ -163,7 +152,7 @@ RDataset::~RDataset()
 {
     FlushCache();
     CPLFree(padfMatrixValues);
-    
+
     if( fp )
         VSIFCloseL( fp );
 }
@@ -177,11 +166,11 @@ RDataset::~RDataset()
 const char *RDataset::ASCIIFGets()
 
 {
-    char chNextChar;
+    char chNextChar = '\0';
 
     osLastStringRead.resize(0);
 
-    do 
+    do
     {
         chNextChar = '\n';
         VSIFReadL( &chNextChar, 1, 1, fp );
@@ -228,7 +217,7 @@ double RDataset::ReadFloat()
     }
     else
     {
-        double  dfValue;
+        double dfValue = 0.0;
 
         if( VSIFReadL( &dfValue, 8, 1, fp ) != 1 )
             return -1;
@@ -251,9 +240,15 @@ const char *RDataset::ReadString()
         return "";
     }
 
-    size_t nLen = ReadInteger();
-        
-    char *pachWrkBuf = (char *) VSIMalloc(nLen);
+    const int nLenSigned = ReadInteger();
+    if( nLenSigned < 0 )
+    {
+        osLastStringRead = "";
+        return "";
+    }
+    const size_t nLen = static_cast<size_t>(nLenSigned);
+
+    char *pachWrkBuf = static_cast<char *>( VSIMalloc(nLen) );
     if (pachWrkBuf == NULL)
     {
         osLastStringRead = "";
@@ -265,13 +260,13 @@ const char *RDataset::ReadString()
         CPLFree( pachWrkBuf );
         return "";
     }
-    
+
     if( bASCII )
     {
-        /* suck up newline and any extra junk */
+        // Suck up newline and any extra junk.
         ASCIIFGets();
     }
-    
+
     osLastStringRead.assign( pachWrkBuf, nLen );
     CPLFree( pachWrkBuf );
 
@@ -291,7 +286,7 @@ int RDataset::ReadPair( CPLString &osObjName, int &nObjCode )
 
     if( (nObjCode % 256) != R_LISTSXP )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "Did not find expected object pair object." );
         return FALSE;
     }
@@ -299,7 +294,7 @@ int RDataset::ReadPair( CPLString &osObjName, int &nObjCode )
     int nPairCount = ReadInteger();
     if( nPairCount != 1 )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "Did not find expected pair count of 1." );
         return FALSE;
     }
@@ -332,17 +327,17 @@ int RDataset::Identify( GDALOpenInfo *poOpenInfo )
 
 /* -------------------------------------------------------------------- */
 /*      If the extension is .rda and the file type is gzip              */
-/*      compressed we assume it is a gziped R binary file.              */
+/*      compressed we assume it is a gzipped R binary file.              */
 /* -------------------------------------------------------------------- */
-    if( memcmp(poOpenInfo->pabyHeader,"\037\213\b",3) == 0 
+    if( memcmp(poOpenInfo->pabyHeader,"\037\213\b",3) == 0
         && EQUAL(CPLGetExtension(poOpenInfo->pszFilename),"rda") )
         return TRUE;
 
 /* -------------------------------------------------------------------- */
 /*      Is this an ASCII or XDR binary R file?                          */
 /* -------------------------------------------------------------------- */
-    if( !EQUALN((const char *)poOpenInfo->pabyHeader,"RDA2\nA\n",7) 
-        && !EQUALN((const char *)poOpenInfo->pabyHeader,"RDX2\nX\n",7) )
+    if( !STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "RDA2\nA\n")
+        && !STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "RDX2\nX\n") )
         return FALSE;
 
     return TRUE;
@@ -362,12 +357,12 @@ GDALDataset *RDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The R driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Do we need to route the file through the decompression          */
 /*      machinery?                                                      */
@@ -391,7 +386,8 @@ GDALDataset *RDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    poDS->bASCII = EQUALN((const char *)poOpenInfo->pabyHeader,"RDA2\nA\n",7);
+    poDS->bASCII =
+        STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "RDA2\nA\n");
 
 /* -------------------------------------------------------------------- */
 /*      Confirm this is a version 2 file.                               */
@@ -400,7 +396,7 @@ GDALDataset *RDataset::Open( GDALOpenInfo * poOpenInfo )
     if( poDS->ReadInteger() != R_LISTSXP )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "It appears %s is not a version 2 R object file after all!",
                   poOpenInfo->pszFilename );
         return NULL;
@@ -506,13 +502,13 @@ GDALDataset *RDataset::Open( GDALOpenInfo * poOpenInfo )
             while( nCount-- > 0 && !VSIFEofL(poDS->fp) )
                 poDS->ReadInteger();
         }
-        else if( nObjCode % 256 == R_STRSXP )			
+        else if( nObjCode % 256 == R_STRSXP )
         {
             int nCount = poDS->ReadInteger();
             while( nCount-- > 0 && !VSIFEofL(poDS->fp) )
                 poDS->ReadString();
         }
-        else if( nObjCode % 256 == R_CHARSXP )			
+        else if( nObjCode % 256 == R_CHARSXP )
         {
             poDS->ReadString();
         }
@@ -533,7 +529,7 @@ GDALDataset *RDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    if( nValueCount 
+    if( nValueCount
         < ((GIntBig) nBandCount) * poDS->nRasterXSize * poDS->nRasterYSize )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -550,16 +546,16 @@ GDALDataset *RDataset::Open( GDALOpenInfo * poOpenInfo )
         GDALRasterBand *poBand;
 
         if( poDS->bASCII )
-            poBand = new RRasterBand( poDS, iBand+1, 
+            poBand = new RRasterBand( poDS, iBand+1,
                                       poDS->padfMatrixValues + iBand * poDS->nRasterXSize * poDS->nRasterYSize );
         else
             poBand = new RawRasterBand( poDS, iBand+1, poDS->fp,
-                                        poDS->nStartOfData 
-                                        + poDS->nRasterXSize*poDS->nRasterYSize*8*iBand, 
+                                        poDS->nStartOfData
+                                        + poDS->nRasterXSize*poDS->nRasterYSize*8*iBand,
                                         8, poDS->nRasterXSize * 8,
                                         GDT_Float64, !CPL_IS_LSB,
                                         TRUE, FALSE );
-                                      
+
         poDS->SetBand( iBand+1, poBand );
     }
 
@@ -584,32 +580,28 @@ GDALDataset *RDataset::Open( GDALOpenInfo * poOpenInfo )
 void GDALRegister_R()
 
 {
-    GDALDriver  *poDriver;
-
-    if( GDALGetDriverByName( "R" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-
-        poDriver->SetDescription( "R" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "R Object Data Store" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "frmt_r.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "rda" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Float32" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    if( GDALGetDriverByName( "R" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "R" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "R Object Data Store" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_r.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "rda" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Float32" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "   <Option name='ASCII' type='boolean' description='For ASCII output, default NO'/>"
 "   <Option name='COMPRESS' type='boolean' description='Produced Compressed output, default YES'/>"
 "</CreationOptionList>" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = RDataset::Open;
-        poDriver->pfnIdentify = RDataset::Identify;
-        poDriver->pfnCreateCopy = RCreateCopy;
+    poDriver->pfnOpen = RDataset::Open;
+    poDriver->pfnIdentify = RDataset::Identify;
+    poDriver->pfnCreateCopy = RCreateCopy;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/rasdaman/frmt_rasdaman.html b/frmts/rasdaman/frmt_rasdaman.html
index ae966ff..4787762 100644
--- a/frmts/rasdaman/frmt_rasdaman.html
+++ b/frmts/rasdaman/frmt_rasdaman.html
@@ -9,8 +9,8 @@
 
 <p>Rasdaman is a raster database middleware offering an SQL-style query
 language on multi-dimensional arrays of unlimited size, stored in a
-relational database. See <a href="http://www.rasdaman.org">www.rasdaman.org</a> 
-for the open-source code, documentation, etc. Currently rasdaman is under 
+relational database. See <a href="http://www.rasdaman.org">www.rasdaman.org</a>
+for the open-source code, documentation, etc. Currently rasdaman is under
 consideration for OSGeo incubation.</p>
 
 <p>In our driver implementation, GDAL connects to rasdaman by defining a
@@ -23,11 +23,11 @@ more technical details are given below.</p>
 
 <p>The connect string syntax follows the WKT Raster pattern and goes
 like this: <br/>
-    rasdaman: 
-        query='select a[$x_lo:$x_hi,$y_lo:$y_hi] from MyImages as a' 
-        [tileXSize=1024] [tileYSize=1024] 
-        [host='localhost'] [port=7001] [database='RASBASE'] 
-        [user='rasguest'] [password='rasguest'] 
+    rasdaman:
+        query='select a[$x_lo:$x_hi,$y_lo:$y_hi] from MyImages as a'
+        [tileXSize=1024] [tileYSize=1024]
+        [host='localhost'] [port=7001] [database='RASBASE']
+        [user='rasguest'] [password='rasguest']
 
 <p>The rasdaman query language (rasql) string in this case only performs
 subsetting. Upon image access by GDAL, the $ parameters are substituted
@@ -36,10 +36,10 @@ by the concrete bounding box computed from the input tile coordinates.</p>
 <p>However, the query provided can include any kind of processing, as long
 as it returns something 2-D. For example, this determines the average of
 red and near-infrared pixels from the oldest image time series:<br/>
-        query='select ( a.red+a.nir ) /2 [$x_lo:$x_hi,$y_lo:$y_hi, 0 ] 
+        query='select ( a.red+a.nir ) /2 [$x_lo:$x_hi,$y_lo:$y_hi, 0 ]
 from SatStack as a' </p>
 
-<p>Currently there is no support for reading or writing georeferencing 
+<p>Currently there is no support for reading or writing georeferencing
 information. </p>
 
 See Also:
diff --git a/frmts/rasdaman/makefile.vc b/frmts/rasdaman/makefile.vc
index 7ebfcf6..f5d7831 100644
--- a/frmts/rasdaman/makefile.vc
+++ b/frmts/rasdaman/makefile.vc
@@ -1,8 +1,6 @@
 
 OBJ	=	rasdamandataset.obj
 
-EXTRAFLAGS = 	-I..\iso8211
-
 GDAL_ROOT	=	..\..
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
diff --git a/frmts/rasdaman/rasdamandataset.cpp b/frmts/rasdaman/rasdamandataset.cpp
index 3c2efad..4c23c37 100644
--- a/frmts/rasdaman/rasdamandataset.cpp
+++ b/frmts/rasdaman/rasdamandataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rasdamandataset.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: rasdamandataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  * Project:  rasdaman Driver
  * Purpose:  Implement Rasdaman GDAL driver
  * Author:   Constantin Jucovschi, jucovschi at yahoo.com
@@ -27,36 +27,28 @@
  * DEALINGS IN THE SOFTWARE.
  ******************************************************************************/
 
+#include "rasdamandataset.h"
 
-#include "gdal_pam.h"
 #include "cpl_string.h"
+#include "gdal_pam.h"
+#include "gdal_frmts.h"
 #include "regex.h"
 #include <string>
 #include <memory>
 #include <map>
 
+#include "gdal.h"
 
-#define __EXECUTABLE__
-#define EARLY_TEMPLATE
-#include "raslib/template_inst.hh"
-#include "raslib/structuretype.hh"
-#include "raslib/type.hh"
-
-#include "rasodmg/database.hh"
+void CPL_DLL CPL_STDCALL GDALRegister_RASDAMAN();
 
-CPL_CVSID("$Id: rasdamandataset.cpp 28053 2014-12-04 09:31:07Z rouault $");
-
-
-CPL_C_START
-void	GDALRegister_RASDAMAN(void);
-CPL_C_END
+CPL_CVSID("$Id: rasdamandataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 
 class Subset
 {
 public:
-  Subset(int x_lo, int x_hi, int y_lo, int y_hi)
-    : m_x_lo(x_lo), m_x_hi(x_hi),  m_y_lo(y_lo),  m_y_hi(y_hi)
+  Subset(int x_loIn, int x_hiIn, int y_loIn, int y_hiIn)
+    : m_x_lo(x_loIn), m_x_hi(x_hiIn),  m_y_lo(y_loIn),  m_y_hi(y_hiIn)
   {}
 
   bool operator < (const Subset& rhs) const {
@@ -143,7 +135,7 @@ private:
 
   r_Database database;
   r_Transaction transaction;
-  
+
   CPLString queryParam;
   CPLString host;
   int port;
@@ -187,7 +179,7 @@ RasdamanDataset::~RasdamanDataset()
 CPLErr RasdamanDataset::IRasterIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
                                void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType, 
+                               GDALDataType eBufType,
                                int nBandCount, int *panBandMap,
                                GSpacing nPixelSpace, GSpacing nLineSpace,
                                GSpacing nBandSpace,
@@ -197,9 +189,9 @@ CPLErr RasdamanDataset::IRasterIO( GDALRWFlag eRWFlag,
     CPLError(CE_Failure, CPLE_NoWriteAccess, "Write support is not implemented.");
     return CE_Failure;
   }
-  
+
   transaction.begin(r_Transaction::read_only);
-  
+
   /* TODO: Setup database access/transaction */
   int dummyX, dummyY;
   /* Cache the whole image region */
@@ -212,7 +204,7 @@ CPLErr RasdamanDataset::IRasterIO( GDALRWFlag eRWFlag,
                                       psExtraArg);
 
   transaction.commit();
-  
+
   /* Clear the cache */
   clear_array_cache();
 
@@ -229,7 +221,7 @@ r_Ref<r_GMarray>& RasdamanDataset::request_array(const Subset& subset, int& offs
 {
   // set the offsets to 0
   offsetX = 0; offsetY = 0;
-  
+
   // check whether or not the subset was already requested
   ArrayCache::iterator it = m_array_cache.find(subset);
   if (it != m_array_cache.end()) {
@@ -247,13 +239,12 @@ r_Ref<r_GMarray>& RasdamanDataset::request_array(const Subset& subset, int& offs
       // TODO: check if offsets are correct
       offsetX = subset.x_lo() - existing.x_lo();
       offsetY = subset.y_lo() - existing.y_lo();
-      
+
       CPLDebug("rasdaman", "Found matching tile (%d, %d, %d, %d) for requested tile (%d, %d, %d, %d). Offests are (%d, %d).",
             existing.x_lo(), existing.x_hi(), existing.y_lo(), existing.y_hi(),
             subset.x_lo(), subset.x_hi(), subset.y_lo(), subset.y_hi(),
             offsetX, offsetY);
-      
-      
+
       return it->second;
     }
   }
@@ -282,13 +273,13 @@ r_Ref<r_GMarray>& RasdamanDataset::request_array(const Subset& subset, int& offs
   if (result_set.cardinality() != 1) {
     // TODO: throw exception
   }
-  
+
   r_Ref<r_GMarray> result_array = r_Ref<r_GMarray>(*result_set.create_iterator());
   //std::auto_ptr<r_GMarray> ptr(new r_GMarray);
   //r_GMarray* ptr_ = ptr.get();
   //(*ptr) = *result_array;
   //std::pair<ArrayCache::iterator, bool> inserted = m_array_cache.insert(ArrayCache::value_type(subset, ptr));
-  
+
   std::pair<ArrayCache::iterator, bool> inserted = m_array_cache.insert(ArrayCache::value_type(subset, result_array));
 
   return inserted.first->second;//*(ptr);
@@ -343,17 +334,17 @@ public:
 /*                           RasdamanRasterBand()                       */
 /************************************************************************/
 
-RasdamanRasterBand::RasdamanRasterBand( RasdamanDataset *poDS, int nBand, GDALDataType type, int offset, int size, int nBlockXSize, int nBlockYSize )
+RasdamanRasterBand::RasdamanRasterBand( RasdamanDataset *poDSIn, int nBandIn, GDALDataType type, int offset, int size, int nBlockXSizeIn, int nBlockYSizeIn )
 {
-  this->poDS = poDS;
-  this->nBand = nBand;
+  this->poDS = poDSIn;
+  this->nBand = nBandIn;
 
   eDataType = type;
   typeSize = size;
   typeOffset = offset;
 
-  this->nBlockXSize = nBlockXSize;
-  this->nBlockYSize = nBlockYSize;
+  this->nBlockXSize = nBlockXSizeIn;
+  this->nBlockYSize = nBlockYSizeIn;
 
   nRecordSize = nBlockXSize * nBlockYSize * typeSize;
 }
@@ -382,16 +373,16 @@ CPLErr RasdamanRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         y_lo = nBlockYOff * nBlockYSize,
         y_hi = MIN(poGDS->nRasterYSize, (nBlockYOff + 1) * nBlockYSize),
         offsetX = 0, offsetY = 0;
-    
+
     r_Ref<r_GMarray>& gmdd = poGDS->request_array(x_lo, x_hi, y_lo, y_hi, offsetX, offsetY);
 
     int xPos = poGDS->xPos;
     int yPos = poGDS->yPos;
-  
+
     r_Minterval sp = gmdd->spatial_domain();
     r_Point extent = sp.get_extent();
     r_Point base = sp.get_origin();
-    
+
     int extentX = extent[xPos];
     int extentY = extent[yPos];
 
@@ -415,7 +406,7 @@ CPLErr RasdamanRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     CPLError(CE_Failure, CPLE_AppDefined, "%s", error.what());
     return CPLGetLastErrorType();
   }
-  
+
   return CE_None;
 }
 
@@ -447,7 +438,7 @@ static int getOption(const char *string, regmatch_t cMatch, int defaultValue) {
   return nRet;
 }
 
-void replace(CPLString& str, const char *from, const char *to) {
+static void replace(CPLString& str, const char *from, const char *to) {
   if(strlen(from) == 0)
     return;
   size_t start_pos = 0;
@@ -465,11 +456,11 @@ static CPLString getQuery(const char *templateString, const char* x_lo, const ch
   replace(result, "$x_hi", x_hi);
   replace(result, "$y_lo", y_lo);
   replace(result, "$y_hi", y_hi);
-  
+
   return result;
 }
 
-GDALDataType mapRasdamanTypesToGDAL(r_Type::r_Type_Id typeId) {
+static GDALDataType mapRasdamanTypesToGDAL(r_Type::r_Type_Id typeId) {
   switch (typeId) {
   case r_Type::ULONG:
     return GDT_UInt32;
@@ -578,7 +569,7 @@ GDALDataset *RasdamanDataset::Open( GDALOpenInfo * poOpenInfo )
   }
   // check 2: the request contains --collection
   char* connString = poOpenInfo->pszFilename;
-  if (!EQUALN(connString, "rasdaman", 8)) {
+  if (!STARTS_WITH_CI(connString, "rasdaman")) {
     return NULL;
   }
 
@@ -701,7 +692,6 @@ GDALDataset *RasdamanDataset::Open( GDALOpenInfo * poOpenInfo )
     delete rasDataset;
     return NULL;
   }
-  
 
   return rasDataset;
 }
@@ -710,25 +700,20 @@ GDALDataset *RasdamanDataset::Open( GDALOpenInfo * poOpenInfo )
 /*                          GDALRegister_RASDAMAN()                     */
 /************************************************************************/
 
-extern void GDALRegister_RASDAMAN()
+void GDALRegister_RASDAMAN()
 
 {
-  GDALDriver	*poDriver;
+  if( GDALGetDriverByName( "RASDAMAN" ) != NULL )
+      return;
 
-  if( GDALGetDriverByName( "RASDAMAN" ) == NULL )
-  {
-    poDriver = new GDALDriver();
+  GDALDriver *poDriver = new GDALDriver();
 
-    poDriver->SetDescription( "RASDAMAN" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                               "RASDAMAN" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                               "frmt_rasdaman.html" );
+  poDriver->SetDescription( "RASDAMAN" );
+  poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+  poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "RASDAMAN" );
+  poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_rasdaman.html" );
 
-    poDriver->pfnOpen = RasdamanDataset::Open;
+  poDriver->pfnOpen = RasdamanDataset::Open;
 
-    GetGDALDriverManager()->RegisterDriver( poDriver );
-  }
+  GetGDALDriverManager()->RegisterDriver( poDriver );
 }
-
diff --git a/frmts/rasdaman/rasdamandataset.h b/frmts/rasdaman/rasdamandataset.h
index c557eb1..71f93d9 100644
--- a/frmts/rasdaman/rasdamandataset.h
+++ b/frmts/rasdaman/rasdamandataset.h
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Project:  rasdaman Driver
- * Purpose:  Implement Rasdaman GDAL driver 
+ * Purpose:  Implement Rasdaman GDAL driver
  * Author:   Constantin Jucovschi, jucovschi at yahoo.com
  *
  ******************************************************************************
@@ -26,10 +26,20 @@
  * DEALINGS IN THE SOFTWARE.
  ******************************************************************************/
 
-#ifndef _RASDAMAN_DATASET_H_
-#define _RASDAMAN_DATASET_H_
-#include "gdal.h"
+#ifndef RASDAMAN_DATASET_H_
+#define RASDAMAN_DATASET_H_
 
-void CPL_DLL CPL_STDCALL GDALRegister_RASDAMAN();
+#define __EXECUTABLE__
+#define EARLY_TEMPLATE
+
+#if ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) && !defined(_MSC_VER))
+#pragma GCC system_header
+#endif
+
+#include "raslib/template_inst.hh"
+#include "raslib/structuretype.hh"
+#include "raslib/type.hh"
+
+#include "rasodmg/database.hh"
 
 #endif
diff --git a/frmts/rasterlite/frmt_rasterlite.html b/frmts/rasterlite/frmt_rasterlite.html
index 95f22ad..0abeb5b 100644
--- a/frmts/rasterlite/frmt_rasterlite.html
+++ b/frmts/rasterlite/frmt_rasterlite.html
@@ -1,213 +1,213 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<title>Rasterlite - Rasters in SQLite DB</title>
-</head>
-
-<body>
-
-<h1>Rasterlite - Rasters in SQLite DB</h1>
-
-<p>Starting with GDAL 1.7.0, the Rasterlite driver allows reading and creating Rasterlite databases.</p>
-<p>
-  Those databases can be produced by the utilities of the
-  <a href="http://www.gaia-gis.it/spatialite">rasterlite</a> distribution,
-  such as rasterlite_load, rasterlite_pyramids, ....<br>
-  The driver supports reading grayscale, paletted and RGB images stored as GIF, PNG, TIFF or JPEG tiles.
-  The driver also supports reading overviews/pyramids, spatial reference system and spatial extent.
-</p>
-<p>Wavelet compressed tiles are not supported by default by GDAL, unless the <a href="frmt_epsilon.html">EPSILON</a> driver is compiled.
-</p>
-
-<p>GDAL/OGR must be compiled with OGR SQLite driver support. For read support, linking against spatialite library is not required, but
-recent enough sqlite3 library is needed to read rasterlite databases. rasterlite library is not required either.</p>
-<p>For write support a new table, linking against spatialite library *is* required.</p>
-
-<p>
-  Although the Rasterlite documentation only mentions GIF, PNG, TIFF, JPEG and WAVELET (EPSILON driver) as
-  compression formats for tiles, the driver supports reading and writing internal tiles in any format handled by GDAL.
-  Furthermore, the Rasterlite driver also allow reading and writing as many bands and as many band types as supported by
-  the driver for the internal tiles.
-<p>
-
-<h2>Connexion string syntax in read mode </h2>
-
-<p>Syntax: 'rasterlitedb_name' or 'RASTERLITE:rasterlitedb_name[,table=raster_table_prefix][,minx=minx_val,miny=miny_val,maxx=maxx_val,maxy=maxy_val][,level=level_number]</p>
-
-<p>where :</p>
-<ul>
-<li><i>rasterlitedb_name</i> is the filename of the rasterlite DB.</li>
-<li><i>raster_table_prefix</i> is the prefix of the raster table to open. For each raster, there are 2 correspondings SQLite tables, suffixed with _rasters and _metadata</li>
-<li><i>minx_val,miny_val,maxx_val,maxy_val</i> set a user-defined extent (expressed in coordinate system units) for the raster that can be different from the default extent.</li>
-<li><i>level_number</i> is the level of the pyramid/overview to open, 0 being the base pyramid.</li>
-</ul>
-
-<h2>Creation issues</h2>
-
-<p>The driver can create a new database if necessary, create a new raster table if necessary and copy a source dataset into the specified raster table.</p>
-
-<p>If data already exists in the raster table, the new data will be added. You can use the WIPE=YES creation options to erase existing data.</p>
-
-<p>The driver does not support updating a block in an existing raster table. It can only append new data.</p>
-
-<p>Syntax for the name of the output dataset: 'RASTERLITE:rasterlitedb_name,table=raster_table_prefix' or 'rasterlitedb_name' </p>
-
-<p>It is possible to specify only the DB name as in the later form, but only if the database does not already exists. In that case, the raster table name will be base on the DB name itself.</p>
-
-<h3>Creation options</h3>
-
-<ul>
-<li><p><b>WIPE</b> (=NO by default): Set to YES to erase all prexisting data in the specified table</p></li>
-<li><p><b>TILED</b> (=YES by default) : Set to NO if the source dataset must be written as a single tile in the raster table</p></li>
-<li><p><b>BLOCKXSIZE</b>=n: Sets tile width, defaults to 256.</p></li>
-<li><p><b>BLOCKYSIZE</b>=n: Sets tile height, defaults to 256.</p></li>
-<li><p><b>DRIVER</b>=[GTiff/GIF/PNG/JPEG/EPSILON/...] : name of the GDAL driver to use for storing tiles. Defaults to GTiff</p></li>
-<li><p><b>COMPRESS</b>=[LZW/JPEG/DEFLATE/...] : (GTiff driver) name of the compression method</p></li>
-<li><p><b>PHOTOMETRIC</b>=[RGB/YCbCr/...] : (GTiff driver) photometric interpretation</p></li>
-<li><p><b>QUALITY</b> : (JPEG-compressed GTiff, JPEG and WEBP drivers) JPEG/WEBP quality 1-100. Defaults to 75</p></li>
-<li><p><b>TARGET</b> : (EPSILON driver) target size reduction as a percentage of the original (0-100). Defaults to 96.</p></li>
-<li><p><b>FILTER</b> : (EPSILON driver) Filter ID. Defaults to 'daub97lift'.</p></li>
-</ul>
-
-<h2>Overviews</h2>
-
-<p>The driver supports building (if the dataset is opened in update mode) and reading internal overviews.</p>
-
-<p>If no internal overview is detected, the driver will try using external overviews (.ovr files).</p>
-
-<p>Starting with GDAL 1.10, options can be used for internal overviews building. They can be specified with the
-RASTERLITE_OVR_OPTIONS configuration option, as a comma separated list of the above creation options. See below
-examples.</p>
-
-<p>Starting with GDAL 1.10, all resampling methods supported by GDAL overviews are available.</p>
-
-<h2>Performance hints</h2>
-
-Some of the performance hints of the OGR SQLite driver apply. In particular setting the OGR_SQLITE_SYNCHRONOUS
-configuration option to OFF when creating a dataset or adding overviews might increase performance on some
-filesystems.<p>
-
-After having added all the raster tables and building all the needed overview levels, it is advised to run :
-<pre>
-ogrinfo rasterlitedb.sqlite -sql "VACUUM"
-</pre>
-in order to optimize the database, and increase read performances afterwards. This is particularly true with big rasterlite datasets.
-Note that the operation might take a long time.<p>
-
-<h2>Examples:</h2>
-
-<ul>
-<li>Accessing a rasterlite DB with a single raster table :
-<pre>
-$ gdalinfo rasterlitedb.sqlite -noct
-</pre>
-Output:
-<pre>
-Driver: Rasterlite/Rasterlite
-Files: rasterlitedb.sqlite
-Size is 7200, 7200
-Coordinate System is:
-GEOGCS["WGS 84",
-    DATUM["WGS_1984",
-        SPHEROID["WGS 84",6378137,298.257223563,
-            AUTHORITY["EPSG","7030"]],
-        AUTHORITY["EPSG","6326"]],
-    PRIMEM["Greenwich",0,
-        AUTHORITY["EPSG","8901"]],
-    UNIT["degree",0.01745329251994328,
-        AUTHORITY["EPSG","9122"]],
-    AUTHORITY["EPSG","4326"]]
-Origin = (-5.000000000000000,55.000000000000000)
-Pixel Size = (0.002083333333333,-0.002083333333333)
-Metadata:
-  TILE_FORMAT=GIF
-Image Structure Metadata:
-  INTERLEAVE=PIXEL
-Corner Coordinates:
-Upper Left  (  -5.0000000,  55.0000000) (  5d 0'0.00"W, 55d 0'0.00"N)
-Lower Left  (  -5.0000000,  40.0000000) (  5d 0'0.00"W, 40d 0'0.00"N)
-Upper Right (  10.0000000,  55.0000000) ( 10d 0'0.00"E, 55d 0'0.00"N)
-Lower Right (  10.0000000,  40.0000000) ( 10d 0'0.00"E, 40d 0'0.00"N)
-Center      (   2.5000000,  47.5000000) (  2d30'0.00"E, 47d30'0.00"N)
-Band 1 Block=480x480 Type=Byte, ColorInterp=Palette
-  Color Table (RGB with 256 entries)
-
-</pre>
-</li>
-
-<li>Listing a multi-raster table DB :
-<pre>
-$ gdalinfo multirasterdb.sqlite
-</pre>
-Output:
-<pre>
-Driver: Rasterlite/Rasterlite
-Files:
-Size is 512, 512
-Coordinate System is `'
-Subdatasets:
-  SUBDATASET_1_NAME=RASTERLITE:multirasterdb.sqlite,table=raster1
-  SUBDATASET_1_DESC=RASTERLITE:multirasterdb.sqlite,table=raster1
-  SUBDATASET_2_NAME=RASTERLITE:multirasterdb.sqlite,table=raster2
-  SUBDATASET_2_DESC=RASTERLITE:multirasterdb.sqlite,table=raster2
-Corner Coordinates:
-Upper Left  (    0.0,    0.0)
-Lower Left  (    0.0,  512.0)
-Upper Right (  512.0,    0.0)
-Lower Right (  512.0,  512.0)
-Center      (  256.0,  256.0)
-
-</pre>
-</li>
-
-<li>Accessing a raster table within a multi-raster table DB:
-<pre>
-$ gdalinfo RASTERLITE:multirasterdb.sqlite,table=raster1
-</pre>
-</li>
-
-<li>Creating a new rasterlite DB with data encoded in JPEG tiles :
-<pre>
-$ gdal_translate -of Rasterlite source.tif RASTERLITE:my_db.sqlite,table=source -co DRIVER=JPEG
-</pre>
-</li>
-
-<li>Creating internal overviews :
-<pre>
-$ gdaladdo RASTERLITE:my_db.sqlite,table=source 2 4 8 16
-</pre>
-</li>
-
-<li>Cleaning internal overviews :
-<pre>
-$ gdaladdo -clean RASTERLITE:my_db.sqlite,table=source
-</pre>
-</li>
-
-<li>Creating external overviews in a .ovr file:
-<pre>
-$ gdaladdo -ro RASTERLITE:my_db.sqlite,table=source 2 4 8 16
-</pre>
-</li>
-
-<li>Creating internal overviews with options (GDAL 1.10 or later):
-<pre>
-$ gdaladdo RASTERLITE:my_db.sqlite,table=source 2 4 8 16 --config RASTERLITE_OVR_OPTIONS DRIVER=GTiff,COMPRESS=JPEG,PHOTOMETRIC=YCbCr
-</pre>
-</li>
-
-</ul>
-
-<p>See Also:</p>
-
-<ul>
-<li><a href="http://www.gaia-gis.it/spatialite">Spatialite and Rasterlite home page</a></li>
-<li><a href="http://www.gaia-gis.it/gaia-sins/rasterlite-docs/rasterlite-man.pdf">Rasterlite manual</a></li> 
-<li><a href="http://www.gaia-gis.it/gaia-sins/rasterlite-docs/rasterlite-how-to.pdf">Rasterlite howto</a></li> 
-<li><a href="http://www.gaia-gis.it/spatialite-2.3.1/resources.html">Sample databases</a></li> 
-<li><a href="http://gdal.org/ogr/drv_sqlite.html">OGR SQLite driver</a></li>
-</ul>
-
-</body>
-</html>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Rasterlite - Rasters in SQLite DB</title>
+</head>
+
+<body>
+
+<h1>Rasterlite - Rasters in SQLite DB</h1>
+
+<p>Starting with GDAL 1.7.0, the Rasterlite driver allows reading and creating Rasterlite databases.</p>
+<p>
+  Those databases can be produced by the utilities of the
+  <a href="http://www.gaia-gis.it/spatialite">rasterlite</a> distribution,
+  such as rasterlite_load, rasterlite_pyramids, ....<br>
+  The driver supports reading grayscale, paletted and RGB images stored as GIF, PNG, TIFF or JPEG tiles.
+  The driver also supports reading overviews/pyramids, spatial reference system and spatial extent.
+</p>
+<p>Wavelet compressed tiles are not supported by default by GDAL, unless the <a href="frmt_epsilon.html">EPSILON</a> driver is compiled.
+</p>
+
+<p>GDAL/OGR must be compiled with OGR SQLite driver support. For read support, linking against spatialite library is not required, but
+recent enough sqlite3 library is needed to read rasterlite databases. rasterlite library is not required either.</p>
+<p>For write support a new table, linking against spatialite library *is* required.</p>
+
+<p>
+  Although the Rasterlite documentation only mentions GIF, PNG, TIFF, JPEG and WAVELET (EPSILON driver) as
+  compression formats for tiles, the driver supports reading and writing internal tiles in any format handled by GDAL.
+  Furthermore, the Rasterlite driver also allow reading and writing as many bands and as many band types as supported by
+  the driver for the internal tiles.
+<p>
+
+<h2>Connection string syntax in read mode </h2>
+
+<p>Syntax: 'rasterlitedb_name' or 'RASTERLITE:rasterlitedb_name[,table=raster_table_prefix][,minx=minx_val,miny=miny_val,maxx=maxx_val,maxy=maxy_val][,level=level_number]</p>
+
+<p>where :</p>
+<ul>
+<li><i>rasterlitedb_name</i> is the filename of the RasterLite DB.</li>
+<li><i>raster_table_prefix</i> is the prefix of the raster table to open. For each raster, there are 2 corresponding SQLite tables, suffixed with _rasters and _metadata</li>
+<li><i>minx_val,miny_val,maxx_val,maxy_val</i> set a user-defined extent (expressed in coordinate system units) for the raster that can be different from the default extent.</li>
+<li><i>level_number</i> is the level of the pyramid/overview to open, 0 being the base pyramid.</li>
+</ul>
+
+<h2>Creation issues</h2>
+
+<p>The driver can create a new database if necessary, create a new raster table if necessary and copy a source dataset into the specified raster table.</p>
+
+<p>If data already exists in the raster table, the new data will be added. You can use the WIPE=YES creation options to erase existing data.</p>
+
+<p>The driver does not support updating a block in an existing raster table. It can only append new data.</p>
+
+<p>Syntax for the name of the output dataset: 'RASTERLITE:rasterlitedb_name,table=raster_table_prefix' or 'rasterlitedb_name' </p>
+
+<p>It is possible to specify only the DB name as in the later form, but only if the database does not already exists. In that case, the raster table name will be base on the DB name itself.</p>
+
+<h3>Creation options</h3>
+
+<ul>
+<li><p><b>WIPE</b> (=NO by default): Set to YES to erase all preexisting data in the specified table</p></li>
+<li><p><b>TILED</b> (=YES by default) : Set to NO if the source dataset must be written as a single tile in the raster table</p></li>
+<li><p><b>BLOCKXSIZE</b>=n: Sets tile width, defaults to 256.</p></li>
+<li><p><b>BLOCKYSIZE</b>=n: Sets tile height, defaults to 256.</p></li>
+<li><p><b>DRIVER</b>=[GTiff/GIF/PNG/JPEG/EPSILON/...] : name of the GDAL driver to use for storing tiles. Defaults to GTiff</p></li>
+<li><p><b>COMPRESS</b>=[LZW/JPEG/DEFLATE/...] : (GTiff driver) name of the compression method</p></li>
+<li><p><b>PHOTOMETRIC</b>=[RGB/YCbCr/...] : (GTiff driver) photometric interpretation</p></li>
+<li><p><b>QUALITY</b> : (JPEG-compressed GTiff, JPEG and WEBP drivers) JPEG/WEBP quality 1-100. Defaults to 75</p></li>
+<li><p><b>TARGET</b> : (EPSILON driver) target size reduction as a percentage of the original (0-100). Defaults to 96.</p></li>
+<li><p><b>FILTER</b> : (EPSILON driver) Filter ID. Defaults to 'daub97lift'.</p></li>
+</ul>
+
+<h2>Overviews</h2>
+
+<p>The driver supports building (if the dataset is opened in update mode) and reading internal overviews.</p>
+
+<p>If no internal overview is detected, the driver will try using external overviews (.ovr files).</p>
+
+<p>Starting with GDAL 1.10, options can be used for internal overviews building. They can be specified with the
+RASTERLITE_OVR_OPTIONS configuration option, as a comma separated list of the above creation options. See below
+examples.</p>
+
+<p>Starting with GDAL 1.10, all resampling methods supported by GDAL overviews are available.</p>
+
+<h2>Performance hints</h2>
+
+Some of the performance hints of the OGR SQLite driver apply. In particular setting the OGR_SQLITE_SYNCHRONOUS
+configuration option to OFF when creating a dataset or adding overviews might increase performance on some
+filesystems.<p>
+
+After having added all the raster tables and building all the needed overview levels, it is advised to run :
+<pre>
+ogrinfo rasterlitedb.sqlite -sql "VACUUM"
+</pre>
+in order to optimize the database, and increase read performances afterwards. This is particularly true with big rasterlite datasets.
+Note that the operation might take a long time.<p>
+
+<h2>Examples:</h2>
+
+<ul>
+<li>Accessing a rasterlite DB with a single raster table :
+<pre>
+$ gdalinfo rasterlitedb.sqlite -noct
+</pre>
+Output:
+<pre>
+Driver: Rasterlite/Rasterlite
+Files: rasterlitedb.sqlite
+Size is 7200, 7200
+Coordinate System is:
+GEOGCS["WGS 84",
+    DATUM["WGS_1984",
+        SPHEROID["WGS 84",6378137,298.257223563,
+            AUTHORITY["EPSG","7030"]],
+        AUTHORITY["EPSG","6326"]],
+    PRIMEM["Greenwich",0,
+        AUTHORITY["EPSG","8901"]],
+    UNIT["degree",0.01745329251994328,
+        AUTHORITY["EPSG","9122"]],
+    AUTHORITY["EPSG","4326"]]
+Origin = (-5.000000000000000,55.000000000000000)
+Pixel Size = (0.002083333333333,-0.002083333333333)
+Metadata:
+  TILE_FORMAT=GIF
+Image Structure Metadata:
+  INTERLEAVE=PIXEL
+Corner Coordinates:
+Upper Left  (  -5.0000000,  55.0000000) (  5d 0'0.00"W, 55d 0'0.00"N)
+Lower Left  (  -5.0000000,  40.0000000) (  5d 0'0.00"W, 40d 0'0.00"N)
+Upper Right (  10.0000000,  55.0000000) ( 10d 0'0.00"E, 55d 0'0.00"N)
+Lower Right (  10.0000000,  40.0000000) ( 10d 0'0.00"E, 40d 0'0.00"N)
+Center      (   2.5000000,  47.5000000) (  2d30'0.00"E, 47d30'0.00"N)
+Band 1 Block=480x480 Type=Byte, ColorInterp=Palette
+  Color Table (RGB with 256 entries)
+
+</pre>
+</li>
+
+<li>Listing a multi-raster table DB :
+<pre>
+$ gdalinfo multirasterdb.sqlite
+</pre>
+Output:
+<pre>
+Driver: Rasterlite/Rasterlite
+Files:
+Size is 512, 512
+Coordinate System is `'
+Subdatasets:
+  SUBDATASET_1_NAME=RASTERLITE:multirasterdb.sqlite,table=raster1
+  SUBDATASET_1_DESC=RASTERLITE:multirasterdb.sqlite,table=raster1
+  SUBDATASET_2_NAME=RASTERLITE:multirasterdb.sqlite,table=raster2
+  SUBDATASET_2_DESC=RASTERLITE:multirasterdb.sqlite,table=raster2
+Corner Coordinates:
+Upper Left  (    0.0,    0.0)
+Lower Left  (    0.0,  512.0)
+Upper Right (  512.0,    0.0)
+Lower Right (  512.0,  512.0)
+Center      (  256.0,  256.0)
+
+</pre>
+</li>
+
+<li>Accessing a raster table within a multi-raster table DB:
+<pre>
+$ gdalinfo RASTERLITE:multirasterdb.sqlite,table=raster1
+</pre>
+</li>
+
+<li>Creating a new rasterlite DB with data encoded in JPEG tiles :
+<pre>
+$ gdal_translate -of Rasterlite source.tif RASTERLITE:my_db.sqlite,table=source -co DRIVER=JPEG
+</pre>
+</li>
+
+<li>Creating internal overviews :
+<pre>
+$ gdaladdo RASTERLITE:my_db.sqlite,table=source 2 4 8 16
+</pre>
+</li>
+
+<li>Cleaning internal overviews :
+<pre>
+$ gdaladdo -clean RASTERLITE:my_db.sqlite,table=source
+</pre>
+</li>
+
+<li>Creating external overviews in a .ovr file:
+<pre>
+$ gdaladdo -ro RASTERLITE:my_db.sqlite,table=source 2 4 8 16
+</pre>
+</li>
+
+<li>Creating internal overviews with options (GDAL 1.10 or later):
+<pre>
+$ gdaladdo RASTERLITE:my_db.sqlite,table=source 2 4 8 16 --config RASTERLITE_OVR_OPTIONS DRIVER=GTiff,COMPRESS=JPEG,PHOTOMETRIC=YCbCr
+</pre>
+</li>
+
+</ul>
+
+<p>See Also:</p>
+
+<ul>
+<li><a href="http://www.gaia-gis.it/spatialite">Spatialite and Rasterlite home page</a></li>
+<li><a href="http://www.gaia-gis.it/gaia-sins/rasterlite-docs/rasterlite-man.pdf">Rasterlite manual</a></li>
+<li><a href="http://www.gaia-gis.it/gaia-sins/rasterlite-docs/rasterlite-how-to.pdf">Rasterlite howto</a></li>
+<li><a href="http://www.gaia-gis.it/spatialite-2.3.1/resources.html">Sample databases</a></li>
+<li><a href="http://gdal.org/drv_sqlite.html">OGR SQLite driver</a></li>
+</ul>
+
+</body>
+</html>
diff --git a/frmts/rasterlite/rasterlitecreatecopy.cpp b/frmts/rasterlite/rasterlitecreatecopy.cpp
index 64f5980..0a47428 100644
--- a/frmts/rasterlite/rasterlitecreatecopy.cpp
+++ b/frmts/rasterlite/rasterlitecreatecopy.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rasterlitecreatecopy.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: rasterlitecreatecopy.cpp 32984 2016-01-14 19:08:12Z goatbar $
  *
  * Project:  GDAL Rasterlite driver
  * Purpose:  Implement GDAL Rasterlite support using OGR SQLite driver
@@ -33,7 +33,7 @@
 
 #include "rasterlitedataset.h"
 
-CPL_CVSID("$Id: rasterlitecreatecopy.cpp 28053 2014-12-04 09:31:07Z rouault $");
+CPL_CVSID("$Id: rasterlitecreatecopy.cpp 32984 2016-01-14 19:08:12Z goatbar $");
 
 /************************************************************************/
 /*                  RasterliteGetTileDriverOptions ()                   */
@@ -66,17 +66,16 @@ static char** RasterliteAddTileDriverOptionsForDriver(char** papszOptions,
 
 char** RasterliteGetTileDriverOptions(char** papszOptions)
 {
-    char** papszTileDriverOptions = NULL;
-
     const char* pszDriverName =
         CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff");
-        
+
+    char** papszTileDriverOptions = NULL;
     if (EQUAL(pszDriverName, "EPSILON"))
     {
         papszTileDriverOptions = CSLSetNameValue(papszTileDriverOptions,
                                                 "RASTERLITE_OUTPUT", "YES");
     }
-    
+
     const char* pszQuality = CSLFetchNameValue(papszOptions, "QUALITY");
     if (pszQuality)
     {
@@ -97,7 +96,7 @@ char** RasterliteGetTileDriverOptions(char** papszOptions)
                      "QUALITY", pszDriverName);
         }
     }
-    
+
     papszTileDriverOptions = RasterliteAddTileDriverOptionsForDriver(
                 papszOptions, papszTileDriverOptions, "COMPRESS", "GTiff");
     papszTileDriverOptions = RasterliteAddTileDriverOptionsForDriver(
@@ -106,7 +105,7 @@ char** RasterliteGetTileDriverOptions(char** papszOptions)
                 papszOptions, papszTileDriverOptions, "TARGET", "EPSILON");
     papszTileDriverOptions = RasterliteAddTileDriverOptionsForDriver(
                 papszOptions, papszTileDriverOptions, "FILTER", "EPSILON");
-    
+
     return papszTileDriverOptions;
 }
 
@@ -116,8 +115,6 @@ char** RasterliteGetTileDriverOptions(char** papszOptions)
 
 static int RasterliteInsertSRID(OGRDataSourceH hDS, const char* pszWKT)
 {
-    CPLString osSQL;
-    
     int nAuthorityCode = 0;
     CPLString osAuthorityName, osProjCS, osProj4;
     if (pszWKT != NULL && strlen(pszWKT) != 0)
@@ -127,22 +124,26 @@ static int RasterliteInsertSRID(OGRDataSourceH hDS, const char* pszWKT)
         {
             const char* pszAuthorityName = OSRGetAuthorityName(hSRS, NULL);
             if (pszAuthorityName) osAuthorityName = pszAuthorityName;
-            
+
             const char* pszProjCS = OSRGetAttrValue(hSRS, "PROJCS", 0);
             if (pszProjCS) osProjCS = pszProjCS;
-            
+
             const char* pszAuthorityCode = OSRGetAuthorityCode(hSRS, NULL);
             if (pszAuthorityCode) nAuthorityCode = atoi(pszAuthorityCode);
-            
+
             char    *pszProj4 = NULL;
             if( OSRExportToProj4( hSRS, &pszProj4 ) != OGRERR_NONE )
+            {
+                CPLFree(pszProj4);
                 pszProj4 = CPLStrdup("");
+            }
             osProj4 = pszProj4;
             CPLFree(pszProj4);
         }
         OSRDestroySpatialReference(hSRS);
     }
-        
+
+    CPLString osSQL;
     int nSRSId = -1;
     if (nAuthorityCode != 0 && osAuthorityName.size() != 0)
     {
@@ -151,7 +152,7 @@ static int RasterliteInsertSRID(OGRDataSourceH hDS, const char* pszWKT)
         if (hLyr == NULL)
         {
             nSRSId = nAuthorityCode;
-            
+
             if ( osProjCS.size() != 0 )
                 osSQL.Printf(
                     "INSERT INTO spatial_ref_sys "
@@ -167,7 +168,6 @@ static int RasterliteInsertSRID(OGRDataSourceH hDS, const char* pszWKT)
                     nSRSId, osAuthorityName.c_str(),
                     nAuthorityCode, osProj4.c_str() );
 
-            
             OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
         }
         else
@@ -181,7 +181,7 @@ static int RasterliteInsertSRID(OGRDataSourceH hDS, const char* pszWKT)
             OGR_DS_ReleaseResultSet(hDS, hLyr);
         }
     }
-    
+
     return nSRSId;
 }
 
@@ -189,18 +189,19 @@ static int RasterliteInsertSRID(OGRDataSourceH hDS, const char* pszWKT)
 /*                     RasterliteCreateTables ()                        */
 /************************************************************************/
 
+static 
 OGRDataSourceH RasterliteCreateTables(OGRDataSourceH hDS, const char* pszTableName,
                                       int nSRSId, int bWipeExistingData)
 {
     CPLString osSQL;
-    
-    CPLString osDBName = OGR_DS_GetName(hDS);
-    
+
+    const CPLString osDBName = OGR_DS_GetName(hDS);
+
     CPLString osRasterLayer;
     osRasterLayer.Printf("%s_rasters", pszTableName);
-    
-    CPLString osMetatadataLayer;
-    osMetatadataLayer.Printf("%s_metadata", pszTableName);
+
+    CPLString osMetadataLayer;
+    osMetadataLayer.Printf("%s_metadata", pszTableName);
 
     OGRLayerH hLyr;
 
@@ -215,7 +216,7 @@ OGRDataSourceH RasterliteCreateTables(OGRDataSourceH hDS, const char* pszTableNa
                         "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                         "raster BLOB NOT NULL)", osRasterLayer.c_str());
         OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-            
+
         /* Create _metadata table */
         osSQL.Printf   ("CREATE TABLE \"%s\" ("
                         "id INTEGER NOT NULL PRIMARY KEY,"
@@ -225,12 +226,12 @@ OGRDataSourceH RasterliteCreateTables(OGRDataSourceH hDS, const char* pszTableNa
                         "height INTEGER NOT NULL,"
                         "pixel_x_size DOUBLE NOT NULL,"
                         "pixel_y_size DOUBLE NOT NULL)",
-                        osMetatadataLayer.c_str());
+                        osMetadataLayer.c_str());
         OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
 
         /* Add geometry column to _metadata table */
         osSQL.Printf("SELECT AddGeometryColumn('%s', 'geometry', %d, 'POLYGON', 2)",
-                      osMetatadataLayer.c_str(), nSRSId);
+                      osMetadataLayer.c_str(), nSRSId);
         if ((hLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL)) == NULL)
         {
             CPLError(CE_Failure, CPLE_AppDefined,
@@ -239,10 +240,10 @@ OGRDataSourceH RasterliteCreateTables(OGRDataSourceH hDS, const char* pszTableNa
             return NULL;
         }
         OGR_DS_ReleaseResultSet(hDS, hLyr);
-                
+
         /* Create spatial index on _metadata table */
         osSQL.Printf("SELECT CreateSpatialIndex('%s', 'geometry')",
-                      osMetatadataLayer.c_str());
+                      osMetadataLayer.c_str());
         if ((hLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL)) == NULL)
         {
             OGRReleaseDataSource(hDS);
@@ -259,7 +260,7 @@ OGRDataSourceH RasterliteCreateTables(OGRDataSourceH hDS, const char* pszTableNa
 
         /* Re-open the DB to take into account the new tables*/
         OGRReleaseDataSource(hDS);
-        
+
         hDS = RasterliteOpenSQLiteDB(osDBName.c_str(), GA_Update);
     }
     else
@@ -267,7 +268,7 @@ OGRDataSourceH RasterliteCreateTables(OGRDataSourceH hDS, const char* pszTableNa
         /* Check that the existing SRS is consistent with the one of the new */
         /* data to be inserted */
         osSQL.Printf("SELECT srid FROM geometry_columns WHERE f_table_name = '%s'",
-                     osMetatadataLayer.c_str());
+                     osMetadataLayer.c_str());
         hLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
         if (hLyr)
         {
@@ -286,12 +287,12 @@ OGRDataSourceH RasterliteCreateTables(OGRDataSourceH hDS, const char* pszTableNa
                 {
                     osSQL.Printf("UPDATE geometry_columns SET srid = %d "
                                  "WHERE f_table_name = \"%s\"",
-                                 nSRSId, osMetatadataLayer.c_str());
+                                 nSRSId, osMetadataLayer.c_str());
                     OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-        
+
                     /* Re-open the DB to take into account the change of SRS */
                     OGRReleaseDataSource(hDS);
-                    
+
                     hDS = RasterliteOpenSQLiteDB(osDBName.c_str(), GA_Update);
                 }
                 else
@@ -301,15 +302,15 @@ OGRDataSourceH RasterliteCreateTables(OGRDataSourceH hDS, const char* pszTableNa
                     OGRReleaseDataSource(hDS);
                     return NULL;
                 }
-            }            
+            }
         }
-        
+
         if (bWipeExistingData)
         {
             osSQL.Printf("DELETE FROM \"%s\"", osRasterLayer.c_str());
             OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-            
-            osSQL.Printf("DELETE FROM \"%s\"", osMetatadataLayer.c_str());
+
+            osSQL.Printf("DELETE FROM \"%s\"", osMetadataLayer.c_str());
             OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
         }
     }
@@ -327,13 +328,13 @@ RasterliteCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                       char ** papszOptions,
                       GDALProgressFunc pfnProgress, void * pProgressData )
 {
-    int nBands = poSrcDS->GetRasterCount();
+    const int nBands = poSrcDS->GetRasterCount();
     if (nBands == 0)
     {
         CPLError(CE_Failure, CPLE_NotSupported, "nBands == 0");
         return NULL;
     }
-    
+
     const char* pszDriverName = CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff");
     if (EQUAL(pszDriverName, "MEM") || EQUAL(pszDriverName, "VRT"))
     {
@@ -348,17 +349,17 @@ RasterliteCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL %s driver", pszDriverName);
         return NULL;
     }
-    
+
     GDALDriverH hMemDriver = GDALGetDriverByName("MEM");
     if (hMemDriver == NULL)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL MEM driver");
         return NULL;
-    }   
+    }
+
+    const int nXSize = GDALGetRasterXSize(poSrcDS);
+    const int nYSize = GDALGetRasterYSize(poSrcDS);
 
-    int nXSize = GDALGetRasterXSize(poSrcDS);
-    int nYSize = GDALGetRasterYSize(poSrcDS);
-    
     double adfGeoTransform[6];
     if (poSrcDS->GetGeoTransform(adfGeoTransform) != CE_None)
     {
@@ -375,7 +376,7 @@ RasterliteCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         return NULL;
     }
 
-    int bTiled = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "TILED", "YES"));
+    const bool bTiled = CPLTestBool(CSLFetchNameValueDef(papszOptions, "TILED", "YES"));
     int nBlockXSize, nBlockYSize;
     if (bTiled)
     {
@@ -391,24 +392,21 @@ RasterliteCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         nBlockXSize = nXSize;
         nBlockYSize = nYSize;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Analyze arguments                                               */
 /* -------------------------------------------------------------------- */
-    
-    CPLString osDBName;
-    CPLString osTableName;
-    VSIStatBuf sBuf;
-    int bExists;
 
-    /* Skip optionnal RASTERLITE: prefix */
+    /* Skip optional RASTERLITE: prefix */
     const char* pszFilenameWithoutPrefix = pszFilename;
-    if (EQUALN(pszFilename, "RASTERLITE:", 11))
+    if (STARTS_WITH_CI(pszFilename, "RASTERLITE:"))
         pszFilenameWithoutPrefix += 11;
-    
-    char** papszTokens = CSLTokenizeStringComplex( 
+
+    char** papszTokens = CSLTokenizeStringComplex(
                 pszFilenameWithoutPrefix, ",", FALSE, FALSE );
-    int nTokens = CSLCount(papszTokens);
+    const int nTokens = CSLCount(papszTokens);
+    CPLString osDBName;
+    CPLString osTableName;
     if (nTokens == 0)
     {
         osDBName = pszFilenameWithoutPrefix;
@@ -417,11 +415,11 @@ RasterliteCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     else
     {
         osDBName = papszTokens[0];
-        
+
         int i;
         for(i=1;i<nTokens;i++)
         {
-            if (EQUALN(papszTokens[i], "table=", 6))
+            if (STARTS_WITH_CI(papszTokens[i], "table="))
                 osTableName = papszTokens[i] + 6;
             else
             {
@@ -430,11 +428,12 @@ RasterliteCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             }
         }
     }
-    
+
     CSLDestroy(papszTokens);
     papszTokens = NULL;
-    
-    bExists = (VSIStat(osDBName.c_str(), &sBuf) == 0);
+
+    VSIStatBuf sBuf;
+    const bool bExists = (VSIStat(osDBName.c_str(), &sBuf) == 0);
 
     if (osTableName.size() == 0)
     {
@@ -445,30 +444,30 @@ RasterliteCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             return NULL;
         }
         osTableName = CPLGetBasename(osDBName.c_str());
-    }    
-    
+    }
+
     CPLString osRasterLayer;
     osRasterLayer.Printf("%s_rasters", osTableName.c_str());
-    
-    CPLString osMetatadataLayer;
-    osMetatadataLayer.Printf("%s_metadata", osTableName.c_str());
+
+    CPLString osMetadataLayer;
+    osMetadataLayer.Printf("%s_metadata", osTableName.c_str());
 
 /* -------------------------------------------------------------------- */
 /*      Create or open the SQLite DB                                    */
 /* -------------------------------------------------------------------- */
-    
+
     if (OGRGetDriverCount() == 0)
         OGRRegisterAll();
-        
+
     OGRSFDriverH hSQLiteDriver = OGRGetDriverByName("SQLite");
     if (hSQLiteDriver == NULL)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Cannot load OGR SQLite driver");
         return NULL;
-    }   
-    
+    }
+
     OGRDataSourceH hDS;
-    
+
     if (!bExists)
     {
         char** papszOGROptions = CSLAddString(NULL, "SPATIALITE=YES");
@@ -480,7 +479,7 @@ RasterliteCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     {
         hDS = RasterliteOpenSQLiteDB(osDBName.c_str(), GA_Update);
     }
-    
+
     if (hDS == NULL)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -489,7 +488,7 @@ RasterliteCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     }
 
     CPLString osSQL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Get the SRID for the SRS                                        */
 /* -------------------------------------------------------------------- */
@@ -498,16 +497,16 @@ RasterliteCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Create or wipe existing tables                                  */
 /* -------------------------------------------------------------------- */
-    int bWipeExistingData =
-        CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "WIPE", "NO"));
-        
+    const int bWipeExistingData =
+        CPLTestBool(CSLFetchNameValueDef(papszOptions, "WIPE", "NO"));
+
     hDS = RasterliteCreateTables(hDS, osTableName.c_str(),
                                  nSRSId, bWipeExistingData);
     if (hDS == NULL)
         return NULL;
 
     OGRLayerH hRasterLayer = OGR_DS_GetLayerByName(hDS, osRasterLayer.c_str());
-    OGRLayerH hMetadataLayer = OGR_DS_GetLayerByName(hDS, osMetatadataLayer.c_str());
+    OGRLayerH hMetadataLayer = OGR_DS_GetLayerByName(hDS, osMetadataLayer.c_str());
     if (hRasterLayer == NULL || hMetadataLayer == NULL)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -523,16 +522,16 @@ RasterliteCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     double maxx = adfGeoTransform[0] + nXSize * adfGeoTransform[1];
     double maxy = adfGeoTransform[3];
     double miny = adfGeoTransform[3] + nYSize * adfGeoTransform[5];
-    
+
     osSQL.Printf("SELECT COUNT(geometry) FROM \"%s\" "
                  "WHERE rowid IN "
                  "(SELECT pkid FROM \"idx_%s_metadata_geometry\" "
                   "WHERE %s) AND %s",
-                  osMetatadataLayer.c_str(),
+                  osMetadataLayer.c_str(),
                   osTableName.c_str(),
                   RasterliteGetSpatialFilterCond(minx, miny, maxx, maxy).c_str(),
                   RasterliteGetPixelSizeCond(adfGeoTransform[1], -adfGeoTransform[5]).c_str());
-    
+
     int nOverlappingGeoms = 0;
     OGRLayerH hCountLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
     if (hCountLyr)
@@ -545,7 +544,7 @@ RasterliteCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         }
         OGR_DS_ReleaseResultSet(hDS, hCountLyr);
     }
-    
+
     if (nOverlappingGeoms != 0)
     {
         CPLError(CE_Warning, CPLE_AppDefined,
@@ -553,7 +552,7 @@ RasterliteCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                  "the extent of the data to be inserted in",
                  osTableName.c_str());
     }
-   
+
 /* -------------------------------------------------------------------- */
 /*      Iterate over blocks to add data into raster and metadata tables */
 /* -------------------------------------------------------------------- */
@@ -563,29 +562,29 @@ RasterliteCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     GDALDataType eDataType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
     int nDataTypeSize = GDALGetDataTypeSize(eDataType) / 8;
     GByte* pabyMEMDSBuffer =
-        (GByte*)VSIMalloc3(nBlockXSize, nBlockYSize, nBands * nDataTypeSize);
+        reinterpret_cast<GByte *>(
+            VSIMalloc3(nBlockXSize, nBlockYSize, nBands * nDataTypeSize) );
     if (pabyMEMDSBuffer == NULL)
     {
         OGRReleaseDataSource(hDS);
         return NULL;
     }
-    
+
     CPLString osTempFileName;
     osTempFileName.Printf("/vsimem/%p", hDS);
-    
+
     int nTileId = 0;
     int nBlocks = 0;
     int nTotalBlocks = nXBlocks * nYBlocks;
 
     char** papszTileDriverOptions = RasterliteGetTileDriverOptions(papszOptions);
-    
+
     OGR_DS_ExecuteSQL(hDS, "BEGIN", NULL, NULL);
-    
+
     CPLErr eErr = CE_None;
-    int nBlockXOff, nBlockYOff;
-    for(nBlockYOff=0;eErr == CE_None && nBlockYOff<nYBlocks;nBlockYOff++)
+    for(int nBlockYOff=0;eErr == CE_None && nBlockYOff<nYBlocks;nBlockYOff++)
     {
-        for(nBlockXOff=0;eErr == CE_None && nBlockXOff<nXBlocks;nBlockXOff++)
+        for(int nBlockXOff=0;eErr == CE_None && nBlockXOff<nXBlocks;nBlockXOff++)
         {
 /* -------------------------------------------------------------------- */
 /*      Create in-memory tile                                           */
@@ -607,7 +606,7 @@ RasterliteCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             {
                 break;
             }
-            
+
             GDALDatasetH hMemDS = GDALCreate(hMemDriver, "MEM:::",
                                               nReqXSize, nReqYSize, 0, 
                                               eDataType, NULL);
@@ -616,57 +615,58 @@ RasterliteCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                 eErr = CE_Failure;
                 break;
             }
-            
-            int iBand;
-            for(iBand = 0; iBand < nBands; iBand ++)
+
+            for( int iBand = 0; iBand < nBands; iBand ++)
             {
-                char** papszMEMDSOptions = NULL;
                 char szTmp[64];
                 memset(szTmp, 0, sizeof(szTmp));
                 CPLPrintPointer(szTmp,
                                 pabyMEMDSBuffer + iBand * nDataTypeSize *
                                 nReqXSize * nReqYSize, sizeof(szTmp));
-                papszMEMDSOptions = CSLSetNameValue(papszMEMDSOptions, "DATAPOINTER", szTmp);
+                char** papszMEMDSOptions
+                    = CSLSetNameValue(NULL, "DATAPOINTER", szTmp);
                 GDALAddBand(hMemDS, eDataType, papszMEMDSOptions);
                 CSLDestroy(papszMEMDSOptions);
             }
-            
+
             GDALDatasetH hOutDS = GDALCreateCopy(hTileDriver,
                                         osTempFileName.c_str(), hMemDS, FALSE,
                                         papszTileDriverOptions, NULL, NULL);
 
             GDALClose(hMemDS);
-            if (hOutDS)
-                GDALClose(hOutDS);
-            else
+            if ( !hOutDS )
             {
                 eErr = CE_Failure;
                 break;
             }
+            GDALClose(hOutDS);
 
 /* -------------------------------------------------------------------- */
 /*      Insert new entry into raster table                              */
 /* -------------------------------------------------------------------- */
-
             vsi_l_offset nDataLength = 0;
             GByte *pabyData = VSIGetMemFileBuffer( osTempFileName.c_str(),
                                                    &nDataLength, FALSE);
 
             OGRFeatureH hFeat = OGR_F_Create( OGR_L_GetLayerDefn(hRasterLayer) );
-            OGR_F_SetFieldBinary(hFeat, 0, (int)nDataLength, pabyData);
-            
-            OGR_L_CreateFeature(hRasterLayer, hFeat);
+            OGR_F_SetFieldBinary(
+                hFeat, 0, static_cast<int>( nDataLength ), pabyData);
+
+            if( OGR_L_CreateFeature(hRasterLayer, hFeat) != OGRERR_NONE )
+                eErr = CE_Failure;
             /* Query raster ID to set it as the ID of the associated metadata */
-            int nRasterID = (int)OGR_F_GetFID(hFeat);
-            
+            int nRasterID = static_cast<int>( OGR_F_GetFID( hFeat ) );
+
             OGR_F_Destroy(hFeat);
-            
+
             VSIUnlink(osTempFileName.c_str());
-            
+            if( eErr == CE_Failure )
+                break;
+
 /* -------------------------------------------------------------------- */
 /*      Insert new entry into metadata table                            */
 /* -------------------------------------------------------------------- */
-            
+
             hFeat = OGR_F_Create( OGR_L_GetLayerDefn(hMetadataLayer) );
             OGR_F_SetFID(hFeat, nRasterID);
             OGR_F_SetFieldString(hFeat, 0, GDALGetDescription(poSrcDS));
@@ -675,7 +675,7 @@ RasterliteCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             OGR_F_SetFieldInteger(hFeat, 3, nReqYSize);
             OGR_F_SetFieldDouble(hFeat, 4, adfGeoTransform[1]);
             OGR_F_SetFieldDouble(hFeat, 5, -adfGeoTransform[5]);
-            
+
             minx = adfGeoTransform[0] +
                 (nBlockXSize * nBlockXOff) * adfGeoTransform[1];
             maxx = adfGeoTransform[0] +
@@ -684,7 +684,7 @@ RasterliteCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                 (nBlockYSize * nBlockYOff) * adfGeoTransform[5];
             miny = adfGeoTransform[3] +
                 (nBlockYSize * nBlockYOff + nReqYSize) * adfGeoTransform[5];
-            
+
             OGRGeometryH hRectangle = OGR_G_CreateGeometry(wkbPolygon);
             OGRGeometryH hLinearRing = OGR_G_CreateGeometry(wkbLinearRing);
             OGR_G_AddPoint_2D(hLinearRing, minx, miny);
@@ -693,31 +693,36 @@ RasterliteCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             OGR_G_AddPoint_2D(hLinearRing, maxx, miny);
             OGR_G_AddPoint_2D(hLinearRing, minx, miny);
             OGR_G_AddGeometryDirectly(hRectangle, hLinearRing);
-            
+
             OGR_F_SetGeometryDirectly(hFeat, hRectangle);
-            
-            OGR_L_CreateFeature(hMetadataLayer, hFeat);
+
+            if( OGR_L_CreateFeature(hMetadataLayer, hFeat) != OGRERR_NONE )
+                eErr = CE_Failure;
             OGR_F_Destroy(hFeat);
-            
+
             nBlocks++;
             if (pfnProgress && !pfnProgress(1.0 * nBlocks / nTotalBlocks,
                                             NULL, pProgressData))
                 eErr = CE_Failure;
         }
     }
-    
+
     if (eErr == CE_None)
         OGR_DS_ExecuteSQL(hDS, "COMMIT", NULL, NULL);
     else
         OGR_DS_ExecuteSQL(hDS, "ROLLBACK", NULL, NULL);
-    
+
     CSLDestroy(papszTileDriverOptions);
-    
+
     VSIFree(pabyMEMDSBuffer);
-    
+
     OGRReleaseDataSource(hDS);
-        
-    return (GDALDataset*) GDALOpen(pszFilename, GA_Update);
+
+    if( eErr == CE_Failure )
+        return NULL;
+
+    return reinterpret_cast<GDALDataset *>(
+        GDALOpen( pszFilename, GA_Update ) );
 }
 
 /************************************************************************/
diff --git a/frmts/rasterlite/rasterlitedataset.cpp b/frmts/rasterlite/rasterlitedataset.cpp
index 90f6913..1392eaa 100644
--- a/frmts/rasterlite/rasterlitedataset.cpp
+++ b/frmts/rasterlite/rasterlitedataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rasterlitedataset.cpp 29265 2015-05-29 10:49:34Z rouault $
+ * $Id: rasterlitedataset.cpp 33010 2016-01-15 19:41:09Z rouault $
  *
  * Project:  GDAL Rasterlite driver
  * Purpose:  Implement GDAL Rasterlite support using OGR SQLite driver
@@ -27,14 +27,16 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_frmts.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
 #include "ogr_api.h"
 #include "ogr_srs_api.h"
 
 #include "rasterlitedataset.h"
 
-CPL_CVSID("$Id: rasterlitedataset.cpp 29265 2015-05-29 10:49:34Z rouault $");
+#include <algorithm>
+
+CPL_CVSID("$Id: rasterlitedataset.cpp 33010 2016-01-15 19:41:09Z rouault $");
 
 
 /************************************************************************/
@@ -45,10 +47,11 @@ OGRDataSourceH RasterliteOpenSQLiteDB(const char* pszFilename,
                                       GDALAccess eAccess)
 {
     const char* const apszAllowedDrivers[] = { "SQLITE", NULL };
-    return (OGRDataSourceH)GDALOpenEx(pszFilename,
-                                      GDAL_OF_VECTOR |
-                                      ((eAccess == GA_Update) ? GDAL_OF_UPDATE : 0),
-                                      apszAllowedDrivers, NULL, NULL);
+    return reinterpret_cast<OGRDataSourceH>(
+        GDALOpenEx( pszFilename,
+                    GDAL_OF_VECTOR |
+                    ((eAccess == GA_Update) ? GDAL_OF_UPDATE : 0),
+                    apszAllowedDrivers, NULL, NULL ));
 }
 
 /************************************************************************/
@@ -92,15 +95,15 @@ CPLString RasterliteGetSpatialFilterCond(double minx, double miny,
 /*                            RasterliteBand()                          */
 /************************************************************************/
 
-RasterliteBand::RasterliteBand(RasterliteDataset* poDS, int nBand,
-                                GDALDataType eDataType,
-                                int nBlockXSize, int nBlockYSize)
+RasterliteBand::RasterliteBand(RasterliteDataset* poDSIn, int nBandIn,
+                                GDALDataType eDataTypeIn,
+                                int nBlockXSizeIn, int nBlockYSizeIn)
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
-    this->eDataType = eDataType;
-    this->nBlockXSize = nBlockXSize;
-    this->nBlockYSize = nBlockYSize;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
+    this->eDataType = eDataTypeIn;
+    this->nBlockXSize = nBlockXSizeIn;
+    this->nBlockYSize = nBlockYSizeIn;
 }
 
 /************************************************************************/
@@ -111,8 +114,8 @@ RasterliteBand::RasterliteBand(RasterliteDataset* poDS, int nBand,
 
 CPLErr RasterliteBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage)
 {
-    RasterliteDataset* poGDS = (RasterliteDataset*) poDS;
-    
+    RasterliteDataset* poGDS = reinterpret_cast<RasterliteDataset *>( poDS );
+
     double minx = poGDS->adfGeoTransform[0] +
                   nBlockXOff * nBlockXSize * poGDS->adfGeoTransform[1];
     double maxx = poGDS->adfGeoTransform[0] +
@@ -131,7 +134,7 @@ CPLErr RasterliteBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage
                 nBlockXOff, nBlockYOff, nBlockXSize, nBlockYSize, minx, miny, maxx, maxy);
     }
 #endif
-    
+
     CPLString osSQL;
     osSQL.Printf("SELECT m.geometry, r.raster, m.id, m.width, m.height FROM \"%s_metadata\" AS m, "
                  "\"%s_rasters\" AS r WHERE m.rowid IN "
@@ -142,7 +145,7 @@ CPLErr RasterliteBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage
                  poGDS->osTableName.c_str(),
                  RasterliteGetSpatialFilterCond(minx, miny, maxx, maxy).c_str(),
                  RasterliteGetPixelSizeCond(poGDS->adfGeoTransform[1], -poGDS->adfGeoTransform[5], "m.").c_str());
-    
+
     OGRLayerH hSQLLyr = OGR_DS_ExecuteSQL(poGDS->hDS, osSQL.c_str(), NULL, NULL);
     if (hSQLLyr == NULL)
     {
@@ -152,19 +155,21 @@ CPLErr RasterliteBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage
 
     CPLString osMemFileName;
     osMemFileName.Printf("/vsimem/%p", this);
-    
-    int bHasFoundTile = FALSE;
-    int bHasMemsetTile = FALSE;
 
 #ifdef RASTERLITE_DEBUG
     if (nBand == 1)
     {
-        printf("nTiles = %d\n", OGR_L_GetFeatureCount(hSQLLyr, TRUE));
+        printf("nTiles = %d\n", static_cast<int>(
+            OGR_L_GetFeatureCount(hSQLLyr, TRUE) ));
     }
 #endif
 
+    bool bHasFoundTile = false;
+    bool bHasMemsetTile = false;
+
     OGRFeatureH hFeat;
-    while( (hFeat = OGR_L_GetNextFeature(hSQLLyr)) != NULL )
+    CPLErr eErr = CE_None;
+    while( (hFeat = OGR_L_GetNextFeature(hSQLLyr)) != NULL && eErr == CE_None )
     {
         OGRGeometryH hGeom = OGR_F_GetGeometryRef(hFeat);
         if (hGeom == NULL)
@@ -174,22 +179,22 @@ CPLErr RasterliteBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage
             OGR_DS_ReleaseResultSet(poGDS->hDS, hSQLLyr);
             return CE_Failure;
         }
-        
+
         OGREnvelope oEnvelope;
         OGR_G_GetEnvelope(hGeom, &oEnvelope);
 
-        int nTileId = OGR_F_GetFieldAsInteger(hFeat, 1);
-        int nTileXSize = OGR_F_GetFieldAsInteger(hFeat, 2);
-        int nTileYSize = OGR_F_GetFieldAsInteger(hFeat, 3);
-        
-        int nDstXOff =
-            (int)((oEnvelope.MinX - minx) / poGDS->adfGeoTransform[1] + 0.5);
-        int nDstYOff =
-            (int)((maxy - oEnvelope.MaxY) / (-poGDS->adfGeoTransform[5]) + 0.5);
-        
+        const int nTileId = OGR_F_GetFieldAsInteger(hFeat, 1);
+        const int nTileXSize = OGR_F_GetFieldAsInteger(hFeat, 2);
+        const int nTileYSize = OGR_F_GetFieldAsInteger(hFeat, 3);
+
+        int nDstXOff = static_cast<int>(
+            ( oEnvelope.MinX - minx ) / poGDS->adfGeoTransform[1] + 0.5 );
+        int nDstYOff = static_cast<int>(
+            ( maxy - oEnvelope.MaxY ) / ( -poGDS->adfGeoTransform[5] ) + 0.5 );
+
         int nReqXSize = nTileXSize;
         int nReqYSize = nTileYSize;
-        
+
         int nSrcXOff, nSrcYOff;
 
         if (nDstXOff >= 0)
@@ -202,8 +207,7 @@ CPLErr RasterliteBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage
             nReqXSize += nDstXOff;
             nDstXOff = 0;
         }
-        
-        
+
         if (nDstYOff >= 0)
         {
             nSrcYOff = 0;
@@ -214,10 +218,10 @@ CPLErr RasterliteBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage
             nReqYSize += nDstYOff;
             nDstYOff = 0;
         }
-        
+
         if (nDstXOff + nReqXSize > nBlockXSize)
             nReqXSize = nBlockXSize - nDstXOff;
-            
+
         if (nDstYOff + nReqYSize > nBlockYSize)
             nReqYSize = nBlockYSize - nDstYOff;
 
@@ -237,7 +241,7 @@ CPLErr RasterliteBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage
         if (nReqXSize > 0 && nReqYSize > 0 &&
             nSrcXOff < nTileXSize && nSrcYOff < nTileYSize)
         {
-                
+
 #ifdef RASTERLITE_DEBUG
             if (nBand == 1)
             {
@@ -250,7 +254,7 @@ CPLErr RasterliteBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage
             VSILFILE * fp = VSIFileFromMemBuffer( osMemFileName.c_str(), pabyData,
                                               nDataSize, FALSE);
             VSIFCloseL(fp);
-            
+
             GDALDatasetH hDSTile = GDALOpenEx(osMemFileName.c_str(),
                                               GDAL_OF_RASTER | GDAL_OF_INTERNAL,
                                               NULL, NULL, NULL);
@@ -265,7 +269,7 @@ CPLErr RasterliteBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage
                 CPLError(CE_Failure, CPLE_AppDefined, "Can't open tile %d", 
                          nTileId);
             }
-            
+
             int nReqBand = 1;
             if (nTileBands == poGDS->nBands)
                 nReqBand = nBand;
@@ -276,16 +280,25 @@ CPLErr RasterliteBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage
                 GDALClose(hDSTile);
                 hDSTile = NULL;
             }
-                
+            
+            if( hDSTile )
+            {
+                if( GDALGetRasterXSize(hDSTile) != nTileXSize ||
+                    GDALGetRasterYSize(hDSTile) != nTileYSize )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined, "Invalid dimensions for tile %d", 
+                             nTileId);
+                    GDALClose(hDSTile);
+                    hDSTile = NULL;
+                }
+            }
+
             if (hDSTile)
             {
-                CPLAssert(GDALGetRasterXSize(hDSTile) == nTileXSize);
-                CPLAssert(GDALGetRasterYSize(hDSTile) == nTileYSize);
+                bHasFoundTile = true;
+
+                bool bHasJustMemsetTileBand1 = false;
 
-                bHasFoundTile = TRUE;
-                
-                int bHasJustMemsetTileBand1 = FALSE;
-                
                 /* If the source tile doesn't fit the entire block size, then */
                 /* we memset 0 before */
                 if (!(nDstXOff == 0 && nDstYOff == 0 &&
@@ -293,40 +306,45 @@ CPLErr RasterliteBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage
                     !bHasMemsetTile)
                 {
                     memset(pImage, 0, nBlockXSize * nBlockYSize * nDataTypeSize);
-                    bHasMemsetTile = TRUE;
-                    bHasJustMemsetTileBand1 = TRUE;
+                    bHasMemsetTile = true;
+                    bHasJustMemsetTileBand1 = true;
                 }
-                
+
                 GDALColorTable* poTileCT =
-                    (GDALColorTable* )GDALGetRasterColorTable(GDALGetRasterBand(hDSTile, 1));
+                    reinterpret_cast<GDALColorTable *>(
+                        GDALGetRasterColorTable(
+                            GDALGetRasterBand( hDSTile, 1 ) ) );
                 unsigned char* pabyTranslationTable = NULL;
                 if (poGDS->nBands == 1 && poGDS->poCT != NULL && poTileCT != NULL)
                 {
                     pabyTranslationTable =
-                        ((GDALRasterBand*)GDALGetRasterBand(hDSTile, 1))->
+                        reinterpret_cast<GDALRasterBand *>(
+                            GDALGetRasterBand( hDSTile, 1 ) )->
                                 GetIndexColorTranslationTo(this, NULL, NULL);
                 }
-                    
+
 /* -------------------------------------------------------------------- */
 /*      Read tile data                                                  */
 /* -------------------------------------------------------------------- */
-                GDALRasterIO(GDALGetRasterBand(hDSTile, nReqBand), GF_Read,
-                             nSrcXOff, nSrcYOff, nReqXSize, nReqYSize,
-                             ((char*) pImage) + (nDstXOff + nDstYOff * nBlockXSize) * nDataTypeSize,
-                             nReqXSize, nReqYSize,
-                             eDataType, nDataTypeSize, nBlockXSize * nDataTypeSize);
+                eErr = GDALRasterIO(
+                    GDALGetRasterBand(hDSTile, nReqBand), GF_Read,
+                    nSrcXOff, nSrcYOff, nReqXSize, nReqYSize,
+                    reinterpret_cast<char*>( pImage )
+                    + (nDstXOff + nDstYOff * nBlockXSize) * nDataTypeSize,
+                    nReqXSize, nReqYSize,
+                    eDataType, nDataTypeSize, nBlockXSize * nDataTypeSize);
 
                 if (eDataType == GDT_Byte && pabyTranslationTable)
                 {
 /* -------------------------------------------------------------------- */
 /*      Convert from tile CT to band CT                                 */
 /* -------------------------------------------------------------------- */
-                    int i, j;
-                    for(j=nDstYOff;j<nDstYOff + nReqYSize;j++)
+                    for( int j = nDstYOff; j < nDstYOff + nReqYSize; j++ )
                     {
-                        for(i=nDstXOff;i<nDstXOff + nReqXSize;i++)
+                        for( int i = nDstXOff; i < nDstXOff + nReqXSize; i++ )
                         {
-                            GByte* pPixel = ((GByte*) pImage) + i + j * nBlockXSize;
+                            GByte* pPixel = reinterpret_cast<GByte *>( pImage )
+                                + i + j * nBlockXSize;
                             *pPixel = pabyTranslationTable[*pPixel];
                         }
                     }
@@ -339,55 +357,56 @@ CPLErr RasterliteBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage
 /* -------------------------------------------------------------------- */
 /*      Expand from PCT to RGB                                          */
 /* -------------------------------------------------------------------- */
-                    int i, j;
                     GByte abyCT[256];
-                    int nEntries = MIN(256, poTileCT->GetColorEntryCount());
-                    for(i=0;i<nEntries;i++)
+                    const int nEntries = std::min(256, poTileCT->GetColorEntryCount());
+                    for( int i = 0; i < nEntries; i++ )
                     {
                         const GDALColorEntry* psEntry = poTileCT->GetColorEntry(i);
                         if (nBand == 1)
-                            abyCT[i] = (GByte)psEntry->c1;
+                            abyCT[i] = static_cast<GByte>( psEntry->c1 );
                         else if (nBand == 2)
-                            abyCT[i] = (GByte)psEntry->c2;
+                            abyCT[i] = static_cast<GByte>( psEntry->c2 );
                         else
-                            abyCT[i] = (GByte)psEntry->c3;
+                            abyCT[i] = static_cast<GByte>( psEntry->c3 );
                     }
-                    for(;i<256;i++)
+                    for( int i = nEntries; i < 256; i++ )
                         abyCT[i] = 0;
-                    
-                    for(j=nDstYOff;j<nDstYOff + nReqYSize;j++)
+
+                    for( int j = nDstYOff; j < nDstYOff + nReqYSize; j++ )
                     {
-                        for(i=nDstXOff;i<nDstXOff + nReqXSize;i++)
+                        for( int i = nDstXOff; i < nDstXOff + nReqXSize; i++ )
                         {
-                            GByte* pPixel = ((GByte*) pImage) + i + j * nBlockXSize;
+                            GByte* pPixel = reinterpret_cast<GByte *>( pImage )
+                                + i + j * nBlockXSize;
                             *pPixel = abyCT[*pPixel];
                         }
                     }
                 }
-                
+
 /* -------------------------------------------------------------------- */
 /*      Put in the block cache the data for this block into other bands */
 /*      while the underlying dataset is opened                          */
 /* -------------------------------------------------------------------- */
                 if (nBand == 1 && poGDS->nBands > 1)
                 {
-                    int iOtherBand;
-                    for(iOtherBand=2;iOtherBand<=poGDS->nBands;iOtherBand++)
+                    for( int iOtherBand = 2;
+                         iOtherBand<=poGDS->nBands && eErr == CE_None;
+                         iOtherBand++ )
                     {
-                        GDALRasterBlock *poBlock;
-
-                        poBlock = poGDS->GetRasterBand(iOtherBand)->
+                        GDALRasterBlock *poBlock
+                            = poGDS->GetRasterBand(iOtherBand)->
                             GetLockedBlockRef(nBlockXOff,nBlockYOff, TRUE);
                         if (poBlock == NULL)
                             break;
-                            
-                        GByte* pabySrcBlock = (GByte *) poBlock->GetDataRef();
+
+                        GByte* pabySrcBlock = reinterpret_cast<GByte *>(
+                            poBlock->GetDataRef() );
                         if( pabySrcBlock == NULL )
                         {
                             poBlock->DropLock();
                             break;
                         }
-            
+
                         if (nTileBands == 1)
                             nReqBand = 1;
                         else
@@ -396,17 +415,19 @@ CPLErr RasterliteBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage
                         if (bHasJustMemsetTileBand1)
                             memset(pabySrcBlock, 0,
                                    nBlockXSize * nBlockYSize * nDataTypeSize);
-            
+
 /* -------------------------------------------------------------------- */
 /*      Read tile data                                                  */
 /* -------------------------------------------------------------------- */
-                        GDALRasterIO(GDALGetRasterBand(hDSTile, nReqBand), GF_Read,
-                                     nSrcXOff, nSrcYOff, nReqXSize, nReqYSize,
-                                     ((char*) pabySrcBlock) +
-                                     (nDstXOff + nDstYOff * nBlockXSize) * nDataTypeSize,
-                                     nReqXSize, nReqYSize,
-                                     eDataType, nDataTypeSize, nBlockXSize * nDataTypeSize);
-                        
+                        eErr = GDALRasterIO(
+                            GDALGetRasterBand(hDSTile, nReqBand), GF_Read,
+                            nSrcXOff, nSrcYOff, nReqXSize, nReqYSize,
+                            reinterpret_cast<char *>( pabySrcBlock ) +
+                            (nDstXOff + nDstYOff * nBlockXSize) * nDataTypeSize,
+                            nReqXSize, nReqYSize,
+                            eDataType, nDataTypeSize,
+                            nBlockXSize * nDataTypeSize);
+
                         if (eDataType == GDT_Byte && nTileBands == 1 &&
                             poGDS->nBands == 3 && poTileCT != NULL)
                         {
@@ -414,39 +435,41 @@ CPLErr RasterliteBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage
 /*      Expand from PCT to RGB                                          */
 /* -------------------------------------------------------------------- */
 
-                            int i, j;
                             GByte abyCT[256];
-                            int nEntries = MIN(256, poTileCT->GetColorEntryCount());
-                            for(i=0;i<nEntries;i++)
+                            const int nEntries
+                                = std::min(256, poTileCT->GetColorEntryCount());
+                            for( int i=0; i < nEntries; i++ )
                             {
                                 const GDALColorEntry* psEntry = poTileCT->GetColorEntry(i);
                                 if (iOtherBand == 1)
-                                    abyCT[i] = (GByte)psEntry->c1;
+                                    abyCT[i] = static_cast<GByte>( psEntry->c1 );
                                 else if (iOtherBand == 2)
-                                    abyCT[i] = (GByte)psEntry->c2;
+                                    abyCT[i] = static_cast<GByte>( psEntry->c2 );
                                 else
-                                    abyCT[i] = (GByte)psEntry->c3;
+                                    abyCT[i] = static_cast<GByte>( psEntry->c3 );
                             }
-                            for(;i<256;i++)
+                            for( int i = nEntries; i < 256; i++ )
                                 abyCT[i] = 0;
-                            
-                            for(j=nDstYOff;j<nDstYOff + nReqYSize;j++)
+
+                            for( int j = nDstYOff; j < nDstYOff + nReqYSize; j++ )
                             {
-                                for(i=nDstXOff;i<nDstXOff + nReqXSize;i++)
+                                for( int i = nDstXOff; i < nDstXOff + nReqXSize; i++ )
                                 {
-                                    GByte* pPixel = ((GByte*) pabySrcBlock) + i + j * nBlockXSize;
+                                  GByte* pPixel
+                                      = reinterpret_cast<GByte*>( pabySrcBlock )
+                                      + i + j * nBlockXSize;
                                     *pPixel = abyCT[*pPixel];
                                 }
                             }
                         }
-                        
+
                         poBlock->DropLock();
                     }
-                  
+
                 }
                 GDALClose(hDSTile);
             }
-            
+
             VSIUnlink(osMemFileName.c_str());
         }
         else
@@ -458,23 +481,22 @@ CPLErr RasterliteBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage
             }
 #endif
         }
-        
         OGR_F_Destroy(hFeat);
     }
-    
+
     if (!bHasFoundTile)
     {
         memset(pImage, 0, nBlockXSize * nBlockYSize * nDataTypeSize);
     }
-            
+
     OGR_DS_ReleaseResultSet(poGDS->hDS, hSQLLyr);
-    
+
 #ifdef RASTERLITE_DEBUG
     if (nBand == 1)
         printf("\n");
 #endif
 
-    return CE_None;
+    return eErr;
 }
 
 /************************************************************************/
@@ -483,8 +505,8 @@ CPLErr RasterliteBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage
 
 int RasterliteBand::GetOverviewCount()
 {
-    RasterliteDataset* poGDS = (RasterliteDataset*) poDS;
-    
+    RasterliteDataset* poGDS = reinterpret_cast<RasterliteDataset *>( poDS );
+
     if (poGDS->nLimitOvrCount >= 0)
         return poGDS->nLimitOvrCount;
     else if (poGDS->nResolutions > 1)
@@ -499,25 +521,25 @@ int RasterliteBand::GetOverviewCount()
 
 GDALRasterBand* RasterliteBand::GetOverview(int nLevel)
 {
-    RasterliteDataset* poGDS = (RasterliteDataset*) poDS;
-    
+    RasterliteDataset* poGDS = reinterpret_cast<RasterliteDataset *>( poDS );
+
     if (poGDS->nLimitOvrCount >= 0)
     {
         if (nLevel < 0 || nLevel >= poGDS->nLimitOvrCount)
             return NULL;
     }
-    
+
     if (poGDS->nResolutions == 1)
         return GDALPamRasterBand::GetOverview(nLevel);
-    
+
     if (nLevel < 0 || nLevel >= poGDS->nResolutions - 1)
         return NULL;
-        
+
     GDALDataset* poOvrDS = poGDS->papoOverviews[nLevel];
     if (poOvrDS)
         return poOvrDS->GetRasterBand(nBand);
-    else
-        return NULL;
+
+    return NULL;
 }
 
 /************************************************************************/
@@ -526,13 +548,13 @@ GDALRasterBand* RasterliteBand::GetOverview(int nLevel)
 
 GDALColorInterp RasterliteBand::GetColorInterpretation()
 {
-    RasterliteDataset* poGDS = (RasterliteDataset*) poDS;
+    RasterliteDataset* poGDS = reinterpret_cast<RasterliteDataset *>( poDS );
     if (poGDS->nBands == 1)
     {
         if (poGDS->poCT != NULL)
             return GCI_PaletteIndex;
-        else
-            return GCI_GrayIndex;
+
+        return GCI_GrayIndex;
     }
     else if (poGDS->nBands == 3)
     {
@@ -543,7 +565,7 @@ GDALColorInterp RasterliteBand::GetColorInterpretation()
         else if (nBand == 3)
             return GCI_BlueBand;
     }
-    
+
     return GCI_Undefined;
 }
 
@@ -553,69 +575,68 @@ GDALColorInterp RasterliteBand::GetColorInterpretation()
 
 GDALColorTable* RasterliteBand::GetColorTable()
 {
-    RasterliteDataset* poGDS = (RasterliteDataset*) poDS;
+    RasterliteDataset* poGDS = reinterpret_cast<RasterliteDataset *>( poDS );
     if (poGDS->nBands == 1)
         return poGDS->poCT;
-    else
-        return NULL;
+
+    return NULL;
 }
 
 /************************************************************************/
 /*                         RasterliteDataset()                          */
 /************************************************************************/
 
-RasterliteDataset::RasterliteDataset()
+RasterliteDataset::RasterliteDataset() :
+    bMustFree(FALSE),
+    poMainDS(NULL),
+    nLevel(0),
+    papszMetadata(NULL),
+    papszSubDatasets(NULL),
+    nResolutions(0),
+    padfXResolutions(NULL),
+    padfYResolutions(NULL),
+    papoOverviews(NULL),
+    nLimitOvrCount(-1),
+    bValidGeoTransform(FALSE),
+    pszSRS(NULL),
+    poCT(NULL),
+    bCheckForExistingOverview(TRUE),
+    hDS(NULL)
 {
-    nLimitOvrCount = -1;
-    bValidGeoTransform = FALSE;
-    bMustFree = FALSE;
-    nLevel = 0;
-    poMainDS = NULL;
-    nResolutions = 0;
-    padfXResolutions = NULL;
-    padfYResolutions = NULL;
-    pszSRS = NULL;
-    hDS = NULL;
-    papoOverviews = NULL;
-    papszMetadata = NULL;
-    papszSubDatasets = NULL;
     papszImageStructure =
         CSLAddString(NULL, "INTERLEAVE=PIXEL");
-    poCT = NULL;
-    bCheckForExistingOverview = TRUE;
 }
 
 /************************************************************************/
 /*                         RasterliteDataset()                          */
 /************************************************************************/
 
-RasterliteDataset::RasterliteDataset(RasterliteDataset* poMainDS, int nLevel)
+RasterliteDataset::RasterliteDataset(RasterliteDataset* poMainDSIn, int nLevelIn) :
+    bMustFree(FALSE),
+    poMainDS(poMainDSIn),
+    nLevel(nLevelIn),
+    papszMetadata(poMainDSIn->papszMetadata),
+    papszImageStructure(poMainDSIn->papszImageStructure),
+    papszSubDatasets(poMainDS->papszSubDatasets),
+    nResolutions(poMainDSIn->nResolutions - nLevelIn),
+    padfXResolutions(poMainDSIn->padfXResolutions + nLevelIn),
+    padfYResolutions(poMainDSIn->padfYResolutions + nLevelIn),
+    papoOverviews(poMainDSIn->papoOverviews + nLevelIn),
+    nLimitOvrCount(-1),
+    bValidGeoTransform(TRUE),
+    pszSRS(poMainDSIn->pszSRS),
+    poCT(poMainDSIn->poCT),
+    osTableName(poMainDSIn->osTableName),
+    osFileName(poMainDSIn->osFileName),
+    bCheckForExistingOverview(TRUE),
+    // TODO: osOvrFileName?
+    hDS(poMainDSIn->hDS)
 {
-    nLimitOvrCount = -1;
-    bMustFree = FALSE;
-    this->nLevel = nLevel;
-    this->poMainDS = poMainDS;
-    nResolutions = poMainDS->nResolutions - nLevel;
-    padfXResolutions = poMainDS->padfXResolutions + nLevel;
-    padfYResolutions = poMainDS->padfYResolutions + nLevel;
-    pszSRS = poMainDS->pszSRS;
-    hDS = poMainDS->hDS;
-    papoOverviews = poMainDS->papoOverviews + nLevel;
-    papszMetadata = poMainDS->papszMetadata;
-    papszSubDatasets = poMainDS->papszSubDatasets;
-    papszImageStructure =  poMainDS->papszImageStructure;
-    poCT =  poMainDS->poCT;
-    bCheckForExistingOverview = TRUE;
-
-    osTableName = poMainDS->osTableName;
-    osFileName = poMainDS->osFileName;
-    
-    nRasterXSize = (int)(poMainDS->nRasterXSize *
+    nRasterXSize = static_cast<int>(poMainDS->nRasterXSize *
         (poMainDS->padfXResolutions[0] / padfXResolutions[0]) + 0.5);
-    nRasterYSize = (int)(poMainDS->nRasterYSize *
+    nRasterYSize = static_cast<int>(poMainDS->nRasterYSize *
         (poMainDS->padfYResolutions[0] / padfYResolutions[0]) + 0.5);
 
-    bValidGeoTransform = TRUE;
     memcpy(adfGeoTransform, poMainDS->adfGeoTransform, 6 * sizeof(double));
     adfGeoTransform[1] = padfXResolutions[0];
     adfGeoTransform[5] = - padfYResolutions[0];
@@ -651,8 +672,7 @@ int RasterliteDataset::CloseDependentDatasets()
 
         if (papoOverviews)
         {
-            int i;
-            for(i=1;i<nResolutions;i++)
+            for( int i = 1; i < nResolutions; i++ )
             {
                 if (papoOverviews[i-1] != NULL &&
                     papoOverviews[i-1]->bMustFree)
@@ -696,13 +716,13 @@ int RasterliteDataset::CloseDependentDatasets()
 void RasterliteDataset::AddSubDataset( const char* pszDSName)
 {
     char	szName[80];
-    int		nCount = CSLCount(papszSubDatasets ) / 2;
+    const int nCount = CSLCount(papszSubDatasets ) / 2;
 
-    sprintf( szName, "SUBDATASET_%d_NAME", nCount+1 );
+    snprintf( szName, sizeof(szName), "SUBDATASET_%d_NAME", nCount+1 );
     papszSubDatasets = 
         CSLSetNameValue( papszSubDatasets, szName, pszDSName);
 
-    sprintf( szName, "SUBDATASET_%d_DESC", nCount+1 );
+    snprintf( szName, sizeof(szName), "SUBDATASET_%d_DESC", nCount+1 );
     papszSubDatasets = 
         CSLSetNameValue( papszSubDatasets, szName, pszDSName);
 }
@@ -727,14 +747,14 @@ char **RasterliteDataset::GetMetadata( const char *pszDomain )
 {
     if( pszDomain != NULL && EQUAL(pszDomain,"SUBDATASETS") )
         return papszSubDatasets;
-        
+
     if( CSLCount(papszSubDatasets) < 2 &&
         pszDomain != NULL && EQUAL(pszDomain,"IMAGE_STRUCTURE") )
         return papszImageStructure;
-        
+
     if ( pszDomain == NULL || EQUAL(pszDomain, "") )
         return papszMetadata;
-        
+
     return GDALPamDataset::GetMetadata( pszDomain );
 }
 
@@ -749,16 +769,15 @@ const char *RasterliteDataset::GetMetadataItem( const char *pszName,
     {
         if (nResolutions > 1 || CSLCount(papszSubDatasets) > 2)
             return NULL;
-        else
-        {
-            osOvrFileName.Printf("%s_%s", osFileName.c_str(), osTableName.c_str());
-            if (bCheckForExistingOverview == FALSE ||
-                CPLCheckForFile((char*) osOvrFileName.c_str(), NULL))
-                return osOvrFileName.c_str();
-            else
-                return NULL;
-        }
+
+        osOvrFileName.Printf("%s_%s", osFileName.c_str(), osTableName.c_str());
+        if (bCheckForExistingOverview == FALSE ||
+            CPLCheckForFile(const_cast<char *>( osOvrFileName.c_str() ), NULL))
+            return osOvrFileName.c_str();
+
+        return NULL;
     }
+
     return GDALPamDataset::GetMetadataItem(pszName, pszDomain);
 }
 
@@ -773,8 +792,8 @@ CPLErr RasterliteDataset::GetGeoTransform( double* padfGeoTransform )
         memcpy(padfGeoTransform, adfGeoTransform, 6 * sizeof(double));
         return CE_None;
     }
-    else
-        return CE_Failure;
+
+    return CE_Failure;
 }
 
 /************************************************************************/
@@ -785,8 +804,8 @@ const char* RasterliteDataset::GetProjectionRef()
 {
     if (pszSRS)
         return pszSRS;
-    else
-        return "";
+
+    return "";
 }
 
 /************************************************************************/
@@ -795,8 +814,8 @@ const char* RasterliteDataset::GetProjectionRef()
 
 char** RasterliteDataset::GetFileList()
 {
-    char** papszFileList = NULL;
-    papszFileList = CSLAddString(papszFileList, osFileName);
+    char** papszFileList
+        = CSLAddString(NULL, osFileName);
     return papszFileList;
 }
 
@@ -804,53 +823,54 @@ char** RasterliteDataset::GetFileList()
 /*                         GetBlockParams()                             */
 /************************************************************************/
 
-int RasterliteDataset::GetBlockParams(OGRLayerH hRasterLyr, int nLevel,
+int RasterliteDataset::GetBlockParams(OGRLayerH hRasterLyr, int nLevelIn,
                                       int* pnBands, GDALDataType* peDataType,
                                       int* pnBlockXSize, int* pnBlockYSize)
 {
     CPLString osSQL;
-    
     osSQL.Printf("SELECT m.geometry, r.raster, m.id "
                  "FROM \"%s_metadata\" AS m, \"%s_rasters\" AS r "
                  "WHERE %s AND r.id = m.id",
                  osTableName.c_str(), osTableName.c_str(),
-                 RasterliteGetPixelSizeCond(padfXResolutions[nLevel],padfYResolutions[nLevel], "m.").c_str());
-    
+                 RasterliteGetPixelSizeCond(padfXResolutions[nLevelIn],padfYResolutions[nLevelIn], "m.").c_str());
+
     OGRLayerH hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
     if (hSQLLyr == NULL)
     {
         return FALSE;
     }
-    
+
     OGRFeatureH hFeat = OGR_L_GetNextFeature(hRasterLyr);
     if (hFeat == NULL)
     {
         OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
         return FALSE;
     }
-    
+
     int nDataSize;
     GByte* pabyData = OGR_F_GetFieldAsBinary(hFeat, 0, &nDataSize);
-    
+
     if (nDataSize > 32 &&
-        EQUALN((const char*)pabyData, "StartWaveletsImage$$", strlen("StartWaveletsImage$$")))
+        STARTS_WITH_CI(reinterpret_cast<const char *>(pabyData),
+                       "StartWaveletsImage$$"))
     {
         if (GDALGetDriverByName("EPSILON") == NULL)
         {
             CPLError(CE_Failure, CPLE_NotSupported,
-                     "Rasterlite driver doesn't support WAVELET compressed images if EPSILON driver is not compiled");
+                     "Rasterlite driver doesn't support WAVELET compressed "
+                     "images if EPSILON driver is not compiled");
             OGR_F_Destroy(hFeat);
             OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
             return FALSE;
         }
     }
-    
+
     CPLString osMemFileName;
     osMemFileName.Printf("/vsimem/%p", this);
-    VSILFILE * fp = VSIFileFromMemBuffer( osMemFileName.c_str(), pabyData,
-                                      nDataSize, FALSE);
+    VSILFILE *fp = VSIFileFromMemBuffer( osMemFileName.c_str(), pabyData,
+                                         nDataSize, FALSE);
     VSIFCloseL(fp);
-    
+
     GDALDatasetH hDSTile = GDALOpen(osMemFileName.c_str(), GA_ReadOnly);
     if (hDSTile)
     {
@@ -866,13 +886,12 @@ int RasterliteDataset::GetBlockParams(OGRLayerH hRasterLyr, int nLevel,
         CPLError(CE_Failure, CPLE_AppDefined, "Can't open tile %d", 
                  OGR_F_GetFieldAsInteger(hFeat, 1));
     }
-    
+
     if (hDSTile)
     {
-        int iBand;
         *peDataType = GDALGetRasterDataType(GDALGetRasterBand(hDSTile, 1));
-        
-        for(iBand=2;iBand<=*pnBands;iBand++)
+
+        for( int iBand = 2; iBand <= *pnBands; iBand++ )
         {
             if (*peDataType != GDALGetRasterDataType(GDALGetRasterBand(hDSTile, 1)))
             {
@@ -882,7 +901,7 @@ int RasterliteDataset::GetBlockParams(OGRLayerH hRasterLyr, int nLevel,
                 goto end;
             }
         }
-        
+
         *pnBlockXSize = GDALGetRasterXSize(hDSTile);
         *pnBlockYSize = GDALGetRasterYSize(hDSTile);
         if (CSLFindName(papszImageStructure, "COMPRESSION") == -1)
@@ -893,32 +912,32 @@ int RasterliteDataset::GetBlockParams(OGRLayerH hRasterLyr, int nLevel,
                 papszImageStructure =
                     CSLAddString(papszImageStructure, "COMPRESSION=JPEG");
         }
-        
+
         if (CSLFindName(papszMetadata, "TILE_FORMAT") == -1)
         {
             papszMetadata =
                 CSLSetNameValue(papszMetadata, "TILE_FORMAT",
                            GDALGetDriverShortName(GDALGetDatasetDriver(hDSTile)));
         }
-        
-        
+
         if (*pnBands == 1 && this->poCT == NULL)
         {
-            GDALColorTable* poCT =
-                (GDALColorTable*)GDALGetRasterColorTable(GDALGetRasterBand(hDSTile, 1));
-            if (poCT)
-                this->poCT = poCT->Clone();
+            GDALColorTable* l_poCT =
+                reinterpret_cast<GDALColorTable *>(
+                    GDALGetRasterColorTable(GDALGetRasterBand(hDSTile, 1) ) );
+            if (l_poCT)
+                this->poCT = l_poCT->Clone();
         }
 
         GDALClose(hDSTile);
     }
-end:    
+end:
     VSIUnlink(osMemFileName.c_str());
-    
+
     OGR_F_Destroy(hFeat);
-    
+
     OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
-    
+
     return hDSTile != NULL;
 }
 
@@ -931,16 +950,16 @@ int RasterliteDataset::Identify(GDALOpenInfo* poOpenInfo)
     if (!EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "MBTILES") &&
         !EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "GPKG") &&
         poOpenInfo->nHeaderBytes >= 1024 &&
-        EQUALN((const char*)poOpenInfo->pabyHeader, "SQLite Format 3", 15))
+        STARTS_WITH_CI((const char*)poOpenInfo->pabyHeader, "SQLite Format 3"))
     {
         // Could be a SQLite/Spatialite file as well
         return -1;
     }
-    else if (EQUALN(poOpenInfo->pszFilename, "RASTERLITE:", 11))
+    else if (STARTS_WITH_CI(poOpenInfo->pszFilename, "RASTERLITE:"))
     {
         return TRUE;
     }
-    
+
     return FALSE;
 }
 
@@ -950,6 +969,9 @@ int RasterliteDataset::Identify(GDALOpenInfo* poOpenInfo)
 
 GDALDataset* RasterliteDataset::Open(GDALOpenInfo* poOpenInfo)
 {
+    if( Identify(poOpenInfo) == FALSE )
+        return NULL;
+
     CPLString osFileName;
     CPLString osTableName;
     char **papszTokens = NULL;
@@ -958,14 +980,12 @@ GDALDataset* RasterliteDataset::Open(GDALOpenInfo* poOpenInfo)
     int bMinXSet = FALSE, bMinYSet = FALSE, bMaxXSet = FALSE, bMaxYSet = FALSE;
     int nReqBands = 0;
 
-    if( Identify(poOpenInfo) == FALSE )
-        return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Parse "file name"                                               */
 /* -------------------------------------------------------------------- */
     if (poOpenInfo->nHeaderBytes >= 1024 &&
-        EQUALN((const char*)poOpenInfo->pabyHeader, "SQLite Format 3", 15))
+        STARTS_WITH_CI((const char*)poOpenInfo->pabyHeader, "SQLite Format 3"))
     {
         osFileName = poOpenInfo->pszFilename;
     }
@@ -979,37 +999,36 @@ GDALDataset* RasterliteDataset::Open(GDALOpenInfo* poOpenInfo)
             CSLDestroy(papszTokens);
             return NULL;
         }
-                
+
         osFileName = papszTokens[0];
-        
-        int i;
-        for(i=1;i<nTokens;i++)
+
+        for( int i=1; i < nTokens; i++)
         {
-            if (EQUALN(papszTokens[i], "table=", 6))
+            if (STARTS_WITH_CI(papszTokens[i], "table="))
                 osTableName = papszTokens[i] + 6;
-            else if (EQUALN(papszTokens[i], "level=", 6))
+            else if (STARTS_WITH_CI(papszTokens[i], "level="))
                 nLevel = atoi(papszTokens[i] + 6);
-            else if (EQUALN(papszTokens[i], "minx=", 5))
+            else if (STARTS_WITH_CI(papszTokens[i], "minx="))
             {
                 bMinXSet = TRUE;
                 minx = CPLAtof(papszTokens[i] + 5);
             }
-            else if (EQUALN(papszTokens[i], "miny=", 5))
+            else if (STARTS_WITH_CI(papszTokens[i], "miny="))
             {
                 bMinYSet = TRUE;
                 miny = CPLAtof(papszTokens[i] + 5);
             }
-            else if (EQUALN(papszTokens[i], "maxx=", 5))
+            else if (STARTS_WITH_CI(papszTokens[i], "maxx="))
             {
                 bMaxXSet = TRUE;
                 maxx = CPLAtof(papszTokens[i] + 5);
             }
-            else if (EQUALN(papszTokens[i], "maxy=", 5))
+            else if (STARTS_WITH_CI(papszTokens[i], "maxy="))
             {
                 bMaxYSet = TRUE;
                 maxy = CPLAtof(papszTokens[i] + 5);
             }
-            else if (EQUALN(papszTokens[i], "bands=", 6))
+            else if (STARTS_WITH_CI(papszTokens[i], "bands="))
             {
                 nReqBands = atoi(papszTokens[i] + 6);
             }
@@ -1020,39 +1039,38 @@ GDALDataset* RasterliteDataset::Open(GDALOpenInfo* poOpenInfo)
             }
         }
     }
-    
+
     if (OGRGetDriverCount() == 0)
         OGRRegisterAll();
-    
+
 /* -------------------------------------------------------------------- */
 /*      Open underlying OGR DB                                          */
 /* -------------------------------------------------------------------- */
 
     OGRDataSourceH hDS = RasterliteOpenSQLiteDB(osFileName.c_str(), poOpenInfo->eAccess);
     CPLDebug("RASTERLITE", "SQLite DB Open");
-    
+
     RasterliteDataset* poDS = NULL;
 
     if (hDS == NULL)
         goto end;
-    
+
     if (strlen(osTableName) == 0)
     {
         int nCountSubdataset = 0;
         int nLayers = OGR_DS_GetLayerCount(hDS);
-        int i;
 /* -------------------------------------------------------------------- */
 /*      Add raster layers as subdatasets                                */
 /* -------------------------------------------------------------------- */
-        for(i=0;i<nLayers;i++)
-        {   
+        for( int i=0; i < nLayers; i++ )
+        {
             OGRLayerH hLyr = OGR_DS_GetLayer(hDS, i);
             const char* pszLayerName = OGR_FD_GetName(OGR_L_GetLayerDefn(hLyr));
             if (strstr(pszLayerName, "_metadata"))
             {
                 char* pszShortName = CPLStrdup(pszLayerName);
                 *strstr(pszShortName, "_metadata") = '\0';
-                
+
                 CPLString osRasterTableName = pszShortName;
                 osRasterTableName += "_rasters";
 
@@ -1063,22 +1081,22 @@ GDALDataset* RasterliteDataset::Open(GDALOpenInfo* poOpenInfo)
                         poDS = new RasterliteDataset();
                         osTableName = pszShortName;
                     }
-                        
+
                     CPLString osSubdatasetName;
-                    if (!EQUALN(poOpenInfo->pszFilename, "RASTERLITE:", 11))
+                    if (!STARTS_WITH_CI(poOpenInfo->pszFilename, "RASTERLITE:"))
                         osSubdatasetName += "RASTERLITE:";
                     osSubdatasetName += poOpenInfo->pszFilename;
                     osSubdatasetName += ",table=";
                     osSubdatasetName += pszShortName;
                     poDS->AddSubDataset(osSubdatasetName.c_str());
-                    
+
                     nCountSubdataset++;
                 }
-                
+
                 CPLFree(pszShortName);
             }
         }
-        
+
         if (nCountSubdataset == 0)
         {
             goto end;
@@ -1088,46 +1106,43 @@ GDALDataset* RasterliteDataset::Open(GDALOpenInfo* poOpenInfo)
             poDS->SetDescription( poOpenInfo->pszFilename );
             goto end;
         }
-        
+
 /* -------------------------------------------------------------------- */
 /*      If just one subdataset, then open it                            */
 /* -------------------------------------------------------------------- */
         delete poDS;
         poDS = NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Build dataset                                                   */
 /* -------------------------------------------------------------------- */
     {
-        CPLString osMetadataTableName, osRasterTableName;
-        CPLString osSQL;
-        OGRLayerH hMetadataLyr, hRasterLyr, hRasterPyramidsLyr;
-        OGRLayerH hSQLLyr;
-        OGRFeatureH hFeat;
-        int i, nResolutions = 0;
-        int iBand, nBands, nBlockXSize, nBlockYSize;
         GDALDataType eDataType;
 
-        osMetadataTableName = osTableName;
-        osMetadataTableName += "_metadata";
-        
-        hMetadataLyr = OGR_DS_GetLayerByName(hDS, osMetadataTableName.c_str());
+        const CPLString osMetadataTableName = osTableName + "_metadata";
+
+        OGRLayerH hMetadataLyr
+            = OGR_DS_GetLayerByName(hDS, osMetadataTableName.c_str());
         if (hMetadataLyr == NULL)
             goto end;
-            
-        osRasterTableName = osTableName;
-        osRasterTableName += "_rasters";
-        
-        hRasterLyr = OGR_DS_GetLayerByName(hDS, osRasterTableName.c_str());
+
+        const CPLString osRasterTableName = osTableName + "_rasters";
+
+        OGRLayerH hRasterLyr
+            = OGR_DS_GetLayerByName(hDS, osRasterTableName.c_str());
         if (hRasterLyr == NULL)
             goto end;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Fetch resolutions                                               */
 /* -------------------------------------------------------------------- */
+        CPLString osSQL;
+        OGRLayerH hSQLLyr;
+        int nResolutions = 0;
 
-        hRasterPyramidsLyr = OGR_DS_GetLayerByName(hDS, "raster_pyramids");
+        OGRLayerH hRasterPyramidsLyr
+            = OGR_DS_GetLayerByName(hDS, "raster_pyramids");
         if (hRasterPyramidsLyr)
         {
             osSQL.Printf("SELECT pixel_x_size, pixel_y_size "
@@ -1138,7 +1153,7 @@ GDALDataset* RasterliteDataset::Open(GDALOpenInfo* poOpenInfo)
             hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
             if (hSQLLyr != NULL)
             {
-                nResolutions = OGR_L_GetFeatureCount(hSQLLyr, TRUE);
+                nResolutions = static_cast<int>(OGR_L_GetFeatureCount(hSQLLyr, TRUE));
                 if( nResolutions == 0 )
                 {
                     OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
@@ -1160,7 +1175,7 @@ GDALDataset* RasterliteDataset::Open(GDALOpenInfo* poOpenInfo)
             if (hSQLLyr == NULL)
                 goto end;
 
-            nResolutions = OGR_L_GetFeatureCount(hSQLLyr, TRUE);
+            nResolutions = static_cast<int>(OGR_L_GetFeatureCount(hSQLLyr, TRUE));
 
             if (nResolutions == 0)
             {
@@ -1179,10 +1194,10 @@ GDALDataset* RasterliteDataset::Open(GDALOpenInfo* poOpenInfo)
         poDS->osTableName = osTableName;
         poDS->osFileName = osFileName;
         poDS->hDS = hDS;
-        
+
         /* poDS will release it from now */
         hDS = NULL;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Fetch spatial extent or use the one provided by the user        */
 /* -------------------------------------------------------------------- */
@@ -1203,38 +1218,44 @@ GDALDataset* RasterliteDataset::Open(GDALOpenInfo* poOpenInfo)
             //printf("minx=%.15f miny=%.15f maxx=%.15f maxy=%.15f\n",
             //       oEnvelope.MinX, oEnvelope.MinY, oEnvelope.MaxX, oEnvelope.MaxY);
         }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Store resolutions                                               */
 /* -------------------------------------------------------------------- */
         poDS->nResolutions = nResolutions;
-        poDS->padfXResolutions =
-            (double*)CPLMalloc(sizeof(double) * poDS->nResolutions);
-        poDS->padfYResolutions =
-            (double*)CPLMalloc(sizeof(double) * poDS->nResolutions);
+        poDS->padfXResolutions = reinterpret_cast<double *>(
+            CPLMalloc( sizeof(double) * poDS->nResolutions ) );
+        poDS->padfYResolutions = reinterpret_cast<double *>(
+            CPLMalloc( sizeof(double) * poDS->nResolutions ) );
 
-        i = 0;
-        while((hFeat = OGR_L_GetNextFeature(hSQLLyr)) != NULL)
         {
+          // Add a scope for i.
+          OGRFeatureH hFeat;
+          int i = 0;
+          while((hFeat = OGR_L_GetNextFeature(hSQLLyr)) != NULL)
+          {
             poDS->padfXResolutions[i] = OGR_F_GetFieldAsDouble(hFeat, 0);
             poDS->padfYResolutions[i] = OGR_F_GetFieldAsDouble(hFeat, 1);
 
             OGR_F_Destroy(hFeat);
-            
-            //printf("[%d] xres=%.15f yres=%.15f\n", i,
-            //       poDS->padfXResolutions[i], poDS->padfYResolutions[i]);
-            
+
+#ifdef RASTERLITE_DEBUG
+            printf("[%d] xres=%.15f yres=%.15f\n", i,
+                   poDS->padfXResolutions[i], poDS->padfYResolutions[i]);
+#endif
+
             if (poDS->padfXResolutions[i] <= 0 || poDS->padfYResolutions[i] <= 0)
             {
                 CPLError(CE_Failure, CPLE_NotSupported,
                          "res=%d, xres=%.15f, yres=%.15f",
                          i, poDS->padfXResolutions[i], poDS->padfYResolutions[i]);
-                OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
+                OGR_DS_ReleaseResultSet(poDS->hDS, hSQLLyr);
                 delete poDS;
                 poDS = NULL;
                 goto end;
             }
-            i ++;
+            i++;
+          }
         }
 
         OGR_DS_ReleaseResultSet(poDS->hDS, hSQLLyr);
@@ -1243,10 +1264,10 @@ GDALDataset* RasterliteDataset::Open(GDALOpenInfo* poOpenInfo)
 /* -------------------------------------------------------------------- */
 /*      Compute raster size, geotransform and projection                */
 /* -------------------------------------------------------------------- */
-        poDS->nRasterXSize =
-            (int)((oEnvelope.MaxX - oEnvelope.MinX) / poDS->padfXResolutions[0] + 0.5);
-        poDS->nRasterYSize =
-            (int)((oEnvelope.MaxY - oEnvelope.MinY) / poDS->padfYResolutions[0] + 0.5);
+        poDS->nRasterXSize = static_cast<int>(
+            (oEnvelope.MaxX - oEnvelope.MinX) / poDS->padfXResolutions[0] + 0.5 );
+        poDS->nRasterYSize = static_cast<int>(
+            (oEnvelope.MaxY - oEnvelope.MinY) / poDS->padfYResolutions[0] + 0.5 );
 
         poDS->bValidGeoTransform = TRUE;
         poDS->adfGeoTransform[0] = oEnvelope.MinX;
@@ -1255,17 +1276,19 @@ GDALDataset* RasterliteDataset::Open(GDALOpenInfo* poOpenInfo)
         poDS->adfGeoTransform[3] = oEnvelope.MaxY;
         poDS->adfGeoTransform[4] = 0;
         poDS->adfGeoTransform[5] = - poDS->padfYResolutions[0];
-        
+
         OGRSpatialReferenceH hSRS = OGR_L_GetSpatialRef(hMetadataLyr);
         if (hSRS)
         {
             OSRExportToWkt(hSRS, &poDS->pszSRS);
         }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Get number of bands and block size                              */
 /* -------------------------------------------------------------------- */
 
+        int nBands;
+        int nBlockXSize, nBlockYSize;
         if (poDS->GetBlockParams(hRasterLyr, 0, &nBands, &eDataType,
                                  &nBlockXSize, &nBlockYSize) == FALSE)
         {
@@ -1274,7 +1297,7 @@ GDALDataset* RasterliteDataset::Open(GDALOpenInfo* poOpenInfo)
             poDS = NULL;
             goto end;
         }
-        
+
         if (eDataType == GDT_Byte && nBands == 1 && nReqBands == 3)
             nBands = 3;
         else if (nReqBands != 0)
@@ -1282,24 +1305,23 @@ GDALDataset* RasterliteDataset::Open(GDALOpenInfo* poOpenInfo)
             CPLError(CE_Warning, CPLE_NotSupported,
                      "Parameters bands=%d ignored", nReqBands);
         }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Add bands                                                       */
 /* -------------------------------------------------------------------- */
-        
-        for(iBand=0;iBand<nBands;iBand++)
-            poDS->SetBand(iBand+1, new RasterliteBand(poDS, iBand+1, eDataType, 
-                                                  nBlockXSize, nBlockYSize));
-        
+
+        for( int iBand=0; iBand < nBands; iBand++ )
+            poDS->SetBand(iBand+1, new RasterliteBand(poDS, iBand+1, eDataType,
+                                                      nBlockXSize, nBlockYSize));
+
 /* -------------------------------------------------------------------- */
 /*      Add overview levels as internal datasets                        */
 /* -------------------------------------------------------------------- */
         if (nResolutions > 1)
         {
-            poDS->papoOverviews = (RasterliteDataset**)
-                CPLCalloc(nResolutions - 1, sizeof(RasterliteDataset*));
-            int nLev;
-            for(nLev=1;nLev<nResolutions;nLev++)
+            poDS->papoOverviews = reinterpret_cast<RasterliteDataset **>(
+                CPLCalloc(nResolutions - 1, sizeof(RasterliteDataset*)) );
+            for( int nLev = 1; nLev < nResolutions; nLev++ )
             {
                 int nOvrBands;
                 GDALDataType eOvrDataType;
@@ -1312,10 +1334,10 @@ GDALDataset* RasterliteDataset::Open(GDALOpenInfo* poOpenInfo)
                     poDS = NULL;
                     goto end;
                 }
-                
+
                 if (eDataType == GDT_Byte && nOvrBands == 1 && nReqBands == 3)
                     nOvrBands = 3;
-                    
+
                 if (nBands != nOvrBands || eDataType != eOvrDataType)
                 {
                     CPLError(CE_Failure, CPLE_AppDefined,
@@ -1324,10 +1346,10 @@ GDALDataset* RasterliteDataset::Open(GDALOpenInfo* poOpenInfo)
                     poDS = NULL;
                     goto end;
                 }
-                
+
                 poDS->papoOverviews[nLev-1] = new RasterliteDataset(poDS, nLev);
-                    
-                for(iBand=0;iBand<nBands;iBand++)
+
+                for( int iBand = 0; iBand < nBands; iBand++ )
                 {
                     poDS->papoOverviews[nLev-1]->SetBand(iBand+1,
                         new RasterliteBand(poDS->papoOverviews[nLev-1], iBand+1, eDataType,
@@ -1335,7 +1357,7 @@ GDALDataset* RasterliteDataset::Open(GDALOpenInfo* poOpenInfo)
                 }
             }
         }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Select an overview if the user has requested so                 */
 /* -------------------------------------------------------------------- */
@@ -1364,7 +1386,7 @@ GDALDataset* RasterliteDataset::Open(GDALOpenInfo* poOpenInfo)
 /*      Setup PAM info for this subdatasets                             */
 /* -------------------------------------------------------------------- */
         poDS->SetPhysicalFilename( osFileName.c_str() );
-        
+
         CPLString osSubdatasetName;
         osSubdatasetName.Printf("RASTERLITE:%s:table=%s",
                                 osFileName.c_str(), osTableName.c_str());
@@ -1373,12 +1395,11 @@ GDALDataset* RasterliteDataset::Open(GDALOpenInfo* poOpenInfo)
         poDS->oOvManager.Initialize( poDS, ":::VIRTUAL:::" );
     }
 
-    
 end:
     if (hDS)
         OGRReleaseDataSource(hDS);
     CSLDestroy(papszTokens);
-    
+
     return poDS;
 }
 
@@ -1389,29 +1410,26 @@ end:
 void GDALRegister_Rasterlite()
 
 {
-    GDALDriver  *poDriver;
-    
-    if (! GDAL_CHECK_VERSION("Rasterlite driver"))
+    if( !GDAL_CHECK_VERSION("Rasterlite driver") )
         return;
 
-    if( GDALGetDriverByName( "Rasterlite" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "Rasterlite" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Rasterlite" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_rasterlite.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "sqlite" );
-        poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte UInt16 Int16 UInt32 Int32 Float32 "
-                                   "Float64 CInt16 CInt32 CFloat32 CFloat64" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
+    if( GDALGetDriverByName( "Rasterlite" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "Rasterlite" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Rasterlite" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_rasterlite.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "sqlite" );
+    poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte UInt16 Int16 UInt32 Int32 Float32 "
+                               "Float64 CInt16 CInt32 CFloat32 CFloat64" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
-"   <Option name='WIPE' type='boolean' default='NO' description='Erase all prexisting data in the specified table'/>"
+"   <Option name='WIPE' type='boolean' default='NO' description='Erase all preexisting data in the specified table'/>"
 "   <Option name='TILED' type='boolean' default='YES' description='Use tiling'/>"
 "   <Option name='BLOCKXSIZE' type='int' default='256' description='Tile Width'/>"
 "   <Option name='BLOCKYSIZE' type='int' default='256' description='Tile Height'/>"
@@ -1433,11 +1451,10 @@ void GDALRegister_Rasterlite()
 "   <Option name='FILTER' type='string' description='(EPSILON driver) Filter ID' default='daub97lift'/>"
 "</CreationOptionList>" );
 
-        poDriver->pfnOpen = RasterliteDataset::Open;
-        poDriver->pfnIdentify = RasterliteDataset::Identify;
-        poDriver->pfnCreateCopy = RasterliteCreateCopy;
-        poDriver->pfnDelete = RasterliteDelete;
+    poDriver->pfnOpen = RasterliteDataset::Open;
+    poDriver->pfnIdentify = RasterliteDataset::Identify;
+    poDriver->pfnCreateCopy = RasterliteCreateCopy;
+    poDriver->pfnDelete = RasterliteDelete;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/rasterlite/rasterlitedataset.h b/frmts/rasterlite/rasterlitedataset.h
index 9fa44a9..f7430f5 100644
--- a/frmts/rasterlite/rasterlitedataset.h
+++ b/frmts/rasterlite/rasterlitedataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rasterlitedataset.h 27566 2014-08-05 09:37:57Z rouault $
+ * $Id: rasterlitedataset.h 31167 2015-10-27 21:33:35Z goatbar $
  *
  * Project:  GDAL Rasterlite driver
  * Purpose:  Implement GDAL Rasterlite support using OGR SQLite driver
@@ -54,22 +54,22 @@ class RasterliteBand;
 class RasterliteDataset : public GDALPamDataset
 {
     friend class RasterliteBand;
-    
+
   public:
                  RasterliteDataset();
                  RasterliteDataset(RasterliteDataset* poMainDS, int nLevel);
-                 
+
     virtual     ~RasterliteDataset();
-    
+
     virtual char      **GetMetadataDomainList();
     virtual char **GetMetadata( const char *pszDomain );
     virtual const char *GetMetadataItem( const char *pszName, 
                                          const char *pszDomain );
     virtual CPLErr GetGeoTransform( double* padfGeoTransform );
     virtual const char* GetProjectionRef();
-    
+
     virtual char** GetFileList();
-    
+
     virtual CPLErr IBuildOverviews( const char * pszResampling, 
                                     int nOverviews, int * panOverviewList,
                                     int nBands, int * panBandList,
@@ -82,34 +82,34 @@ class RasterliteDataset : public GDALPamDataset
     virtual int         CloseDependentDatasets();
 
   private:
-  
     int bMustFree;
     RasterliteDataset* poMainDS;
     int nLevel;
-    
+
     char** papszMetadata;
     char** papszImageStructure;
     char** papszSubDatasets;
-    
+
     int nResolutions;
-    double* padfXResolutions, *padfYResolutions;
+    double *padfXResolutions;
+    double *padfYResolutions;
     RasterliteDataset** papoOverviews;
     int nLimitOvrCount;
-    
+
     int bValidGeoTransform;
     double adfGeoTransform[6];
     char* pszSRS;
-    
+
     GDALColorTable* poCT;
-    
+
     CPLString osTableName;
     CPLString osFileName;
-    
+
     int bCheckForExistingOverview;
     CPLString osOvrFileName;
 
     OGRDataSourceH hDS;
-    
+
     void AddSubDataset( const char* pszDSName);
     int  GetBlockParams(OGRLayerH hRasterLyr, int nLevel, int* pnBands,
                         GDALDataType* peDataType,
diff --git a/frmts/rasterlite/rasterliteoverviews.cpp b/frmts/rasterlite/rasterliteoverviews.cpp
index 1b77788..ef98363 100644
--- a/frmts/rasterlite/rasterliteoverviews.cpp
+++ b/frmts/rasterlite/rasterliteoverviews.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rasterliteoverviews.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: rasterliteoverviews.cpp 32984 2016-01-14 19:08:12Z goatbar $
  *
  * Project:  GDAL Rasterlite driver
  * Purpose:  Implement GDAL Rasterlite support using OGR SQLite driver
@@ -33,7 +33,7 @@
 
 #include "rasterlitedataset.h"
 
-CPL_CVSID("$Id: rasterliteoverviews.cpp 28053 2014-12-04 09:31:07Z rouault $");
+CPL_CVSID("$Id: rasterliteoverviews.cpp 32984 2016-01-14 19:08:12Z goatbar $");
 
 /************************************************************************/
 /*                         ReloadOverviews()                            */
@@ -43,7 +43,7 @@ CPLErr RasterliteDataset::ReloadOverviews()
 {
     if (nLevel != 0)
         return CE_Failure;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Fetch resolutions                                               */
 /* -------------------------------------------------------------------- */
@@ -70,12 +70,12 @@ CPLErr RasterliteDataset::ReloadOverviews()
     {
         if (hRasterPyramidsLyr == NULL)
             return CE_Failure;
-            
+
         osSQL.Printf("SELECT DISTINCT(pixel_x_size), pixel_y_size "
                      "FROM \"%s_metadata\" WHERE pixel_x_size != 0  "
                      "ORDER BY pixel_x_size ASC",
                      osTableName.c_str());
-                     
+
         hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
         if (hSQLLyr == NULL)
             return CE_Failure;
@@ -84,9 +84,7 @@ CPLErr RasterliteDataset::ReloadOverviews()
 /* -------------------------------------------------------------------- */
 /*      Cleanup                                                         */
 /* -------------------------------------------------------------------- */
-
-    int i;
-    for(i=1;i<nResolutions;i++)
+    for( int i = 1; i < nResolutions; i++ )
         delete papoOverviews[i-1];
     CPLFree(papoOverviews);
     papoOverviews = NULL;
@@ -94,28 +92,31 @@ CPLErr RasterliteDataset::ReloadOverviews()
     padfXResolutions = NULL;
     CPLFree(padfYResolutions);
     padfYResolutions = NULL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Rebuild arrays                                                  */
 /* -------------------------------------------------------------------- */
 
-    nResolutions = OGR_L_GetFeatureCount(hSQLLyr, TRUE);
-    
+    nResolutions = static_cast<int>(OGR_L_GetFeatureCount(hSQLLyr, TRUE));
+
     padfXResolutions =
-        (double*)CPLMalloc(sizeof(double) * nResolutions);
+        reinterpret_cast<double *>( CPLMalloc(sizeof(double) * nResolutions) );
     padfYResolutions =
-        (double*)CPLMalloc(sizeof(double) * nResolutions);
+        reinterpret_cast<double *>( CPLMalloc(sizeof(double) * nResolutions) );
 
-    i = 0;
-    OGRFeatureH hFeat;
-    while((hFeat = OGR_L_GetNextFeature(hSQLLyr)) != NULL)
     {
-        padfXResolutions[i] = OGR_F_GetFieldAsDouble(hFeat, 0);
-        padfYResolutions[i] = OGR_F_GetFieldAsDouble(hFeat, 1);
+        // Exstra scope for i.
+        int i = 0;
+        OGRFeatureH hFeat;
+        while((hFeat = OGR_L_GetNextFeature(hSQLLyr)) != NULL)
+        {
+            padfXResolutions[i] = OGR_F_GetFieldAsDouble(hFeat, 0);
+            padfYResolutions[i] = OGR_F_GetFieldAsDouble(hFeat, 1);
 
-        OGR_F_Destroy(hFeat);
+            OGR_F_Destroy(hFeat);
 
-        i ++;
+            i++;
+        }
     }
 
     OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
@@ -128,13 +129,12 @@ CPLErr RasterliteDataset::ReloadOverviews()
     {
         CPLString osRasterTableName = osTableName;
         osRasterTableName += "_rasters";
-        
+
         OGRLayerH hRasterLyr = OGR_DS_GetLayerByName(hDS, osRasterTableName.c_str());
-        
-        papoOverviews = (RasterliteDataset**)
-            CPLCalloc(nResolutions - 1, sizeof(RasterliteDataset*));
-        int nLev;
-        for(nLev=1;nLev<nResolutions;nLev++)
+
+        papoOverviews = reinterpret_cast<RasterliteDataset **>(
+            CPLCalloc( nResolutions - 1, sizeof(RasterliteDataset*) ) );
+        for( int nLev = 1; nLev < nResolutions; nLev++ )
         {
             int nOvrBands;
             GDALDataType eOvrDataType;
@@ -146,9 +146,8 @@ CPLErr RasterliteDataset::ReloadOverviews()
                     nOvrBands = 3;
 
                 papoOverviews[nLev-1] = new RasterliteDataset(this, nLev);
-                  
-                int iBand;
-                for(iBand=0;iBand<nBands;iBand++)
+
+                for( int iBand = 0; iBand < nBands; iBand++ )
                 {
                     papoOverviews[nLev-1]->SetBand(iBand+1,
                         new RasterliteBand(papoOverviews[nLev-1], iBand+1, eOvrDataType,
@@ -163,7 +162,7 @@ CPLErr RasterliteDataset::ReloadOverviews()
             }
         }
     }
-    
+
     return CE_None;
 }
 
@@ -173,15 +172,13 @@ CPLErr RasterliteDataset::ReloadOverviews()
 
 CPLErr RasterliteDataset::CleanOverviews()
 {
-    CPLString osSQL;
-    
     if (nLevel != 0)
         return CE_Failure;
-        
-    osSQL.Printf("BEGIN");
+
+    CPLString osSQL("BEGIN");;
     OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-    
-    CPLString osResolutionCond =
+
+    const CPLString osResolutionCond =
         "NOT " + RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0]);
 
     osSQL.Printf("DELETE FROM \"%s_rasters\" WHERE id "
@@ -193,7 +190,7 @@ CPLErr RasterliteDataset::CleanOverviews()
     osSQL.Printf("DELETE FROM \"%s_metadata\" WHERE %s",
                   osTableName.c_str(), osResolutionCond.c_str());
     OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-    
+
     OGRLayerH hRasterPyramidsLyr = OGR_DS_GetLayerByName(hDS, "raster_pyramids");
     if (hRasterPyramidsLyr)
     {
@@ -201,17 +198,16 @@ CPLErr RasterliteDataset::CleanOverviews()
                       osTableName.c_str(), osResolutionCond.c_str());
         OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
     }
-    
-    osSQL.Printf("COMMIT");
+
+    osSQL = "COMMIT";
     OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-    
-    int i;
-    for(i=1;i<nResolutions;i++)
+
+    for( int i = 1; i < nResolutions; i++ )
         delete papoOverviews[i-1];
     CPLFree(papoOverviews);
     papoOverviews = NULL;
     nResolutions = 1;
-    
+
     return CE_None;
 }
 
@@ -221,35 +217,33 @@ CPLErr RasterliteDataset::CleanOverviews()
 
 CPLErr RasterliteDataset::CleanOverviewLevel(int nOvrFactor)
 {
-    CPLString osSQL;
-    
     if (nLevel != 0)
         return CE_Failure;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Find the index of the overview matching the overview factor     */
 /* -------------------------------------------------------------------- */
-    int iLev;
-    for(iLev=1;iLev<nResolutions;iLev++)
+    int iLev = 1;
+    for( ; iLev < nResolutions; iLev++ )
     {
         if (fabs(padfXResolutions[0] * nOvrFactor - padfXResolutions[iLev]) < 1e-15 &&
             fabs(padfYResolutions[0] * nOvrFactor - padfYResolutions[iLev]) < 1e-15)
             break;
     }
-    
+
     if (iLev == nResolutions)
         return CE_None;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Now clean existing overviews at that resolution                 */
 /* -------------------------------------------------------------------- */
 
-    osSQL.Printf("BEGIN");
+    CPLString osSQL("BEGIN");
     OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-    
+
     CPLString osResolutionCond =
         RasterliteGetPixelSizeCond(padfXResolutions[iLev], padfYResolutions[iLev]);
-    
+
     osSQL.Printf("DELETE FROM \"%s_rasters\" WHERE id "
                  "IN(SELECT id FROM \"%s_metadata\" WHERE %s)",
                   osTableName.c_str(), osTableName.c_str(),
@@ -259,7 +253,7 @@ CPLErr RasterliteDataset::CleanOverviewLevel(int nOvrFactor)
     osSQL.Printf("DELETE FROM \"%s_metadata\" WHERE %s",
                   osTableName.c_str(), osResolutionCond.c_str());
     OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-    
+
     OGRLayerH hRasterPyramidsLyr = OGR_DS_GetLayerByName(hDS, "raster_pyramids");
     if (hRasterPyramidsLyr)
     {
@@ -267,10 +261,10 @@ CPLErr RasterliteDataset::CleanOverviewLevel(int nOvrFactor)
                       osTableName.c_str(), osResolutionCond.c_str());
         OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
     }
-    
-    osSQL.Printf("COMMIT");
+
+    osSQL = "COMMIT";
     OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-    
+
     return CE_None;
 }
 
@@ -284,19 +278,14 @@ CPLErr RasterliteDataset::CreateOverviewLevel(const char * pszResampling,
                                               GDALProgressFunc pfnProgress,
                                               void * pProgressData)
 {
+    const int nOvrXSize = nRasterXSize / nOvrFactor;
+    const int nOvrYSize = nRasterYSize / nOvrFactor;
 
-    double dfXResolution = padfXResolutions[0] * nOvrFactor;
-    double dfYResolution = padfXResolutions[0] * nOvrFactor;
-    
-    CPLString osSQL;
-
-    int nOvrXSize = nRasterXSize / nOvrFactor;
-    int nOvrYSize = nRasterYSize / nOvrFactor;
-    
     if (nOvrXSize == 0 || nOvrYSize == 0)
         return CE_Failure;
 
-    int bTiled = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "TILED", "YES"));
+    const bool bTiled
+        = CPLTestBool(CSLFetchNameValueDef(papszOptions, "TILED", "YES"));
     int nBlockXSize, nBlockYSize;
     if (bTiled)
     {
@@ -312,10 +301,7 @@ CPLErr RasterliteDataset::CreateOverviewLevel(const char * pszResampling,
         nBlockXSize = nOvrXSize;
         nBlockYSize = nOvrYSize;
     }
-    
-    int nXBlocks = (nOvrXSize + nBlockXSize - 1) / nBlockXSize;
-    int nYBlocks = (nOvrYSize + nBlockYSize - 1) / nBlockYSize;
-    
+
     const char* pszDriverName = CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff");
     if (EQUAL(pszDriverName, "MEM") || EQUAL(pszDriverName, "VRT"))
     {
@@ -335,35 +321,42 @@ CPLErr RasterliteDataset::CreateOverviewLevel(const char * pszResampling,
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL MEM driver");
         return CE_Failure;
-    }   
+    }
 
-    GDALDataType eDataType = GetRasterBand(1)->GetRasterDataType();
+    const GDALDataType eDataType = GetRasterBand(1)->GetRasterDataType();
     int nDataTypeSize = GDALGetDataTypeSize(eDataType) / 8;
-    GByte* pabyMEMDSBuffer =
-        (GByte*)VSIMalloc3(nBlockXSize, nBlockYSize, nBands * nDataTypeSize);
+    GByte* pabyMEMDSBuffer = reinterpret_cast<GByte *>(
+        VSIMalloc3( nBlockXSize, nBlockYSize, nBands * nDataTypeSize ) );
     if (pabyMEMDSBuffer == NULL)
     {
         return CE_Failure;
     }
-    
+
     CPLString osTempFileName;
     osTempFileName.Printf("/vsimem/%p", hDS);
-    
+
     int nTileId = 0;
     int nBlocks = 0;
+
+    const int nXBlocks = (nOvrXSize + nBlockXSize - 1) / nBlockXSize;
+    const int nYBlocks = (nOvrYSize + nBlockYSize - 1) / nBlockYSize;
     int nTotalBlocks = nXBlocks * nYBlocks;
-    
+
     CPLString osRasterLayer;
     osRasterLayer.Printf("%s_rasters", osTableName.c_str());
-    
+
     CPLString osMetatadataLayer;
     osMetatadataLayer.Printf("%s_metadata", osTableName.c_str());
-    
+
     OGRLayerH hRasterLayer = OGR_DS_GetLayerByName(hDS, osRasterLayer.c_str());
     OGRLayerH hMetadataLayer = OGR_DS_GetLayerByName(hDS, osMetatadataLayer.c_str());
-    
+
     CPLString osSourceName = "unknown";
-    
+
+    const double dfXResolution = padfXResolutions[0] * nOvrFactor;
+    const double dfYResolution = padfXResolutions[0] * nOvrFactor;
+
+    CPLString osSQL;
     osSQL.Printf("SELECT source_name FROM \"%s\" WHERE "
                  "%s LIMIT 1",
                  osMetatadataLayer.c_str(),
@@ -381,14 +374,14 @@ CPLErr RasterliteDataset::CreateOverviewLevel(const char * pszResampling,
         }
         OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Compute up to which existing overview level we can use for      */
 /*      computing the requested overview                                */
 /* -------------------------------------------------------------------- */
-    int iLev;
     nLimitOvrCount = 0;
-    for(iLev=1;iLev<nResolutions;iLev++)
+    int iLev = 1;
+    for( ; iLev < nResolutions; iLev++ )
     {
         if (!(padfXResolutions[iLev] < dfXResolution - 1e-10 &&
               padfYResolutions[iLev] < dfYResolution - 1e-10))
@@ -404,15 +397,15 @@ CPLErr RasterliteDataset::CreateOverviewLevel(const char * pszResampling,
     GDALDataset* poPrevOvrLevel =
         (papoOverviews != NULL && iLev >= 2 && iLev <= nResolutions && papoOverviews[iLev-2]) ?
             papoOverviews[iLev-2] : this;
-    double dfRatioPrevOvr = poPrevOvrLevel->GetRasterBand(1)->GetXSize() / nOvrXSize;
-    int nPrevOvrBlockXSize = (int)(nBlockXSize * dfRatioPrevOvr + 0.5);
-    int nPrevOvrBlockYSize = (int)(nBlockYSize * dfRatioPrevOvr + 0.5);
+    const double dfRatioPrevOvr = static_cast<double>(poPrevOvrLevel->GetRasterBand(1)->GetXSize()) / nOvrXSize;
+    const int nPrevOvrBlockXSize = static_cast<int>( nBlockXSize * dfRatioPrevOvr + 0.5 );
+    const int nPrevOvrBlockYSize = static_cast<int>(nBlockYSize * dfRatioPrevOvr + 0.5 );
     GByte* pabyPrevOvrMEMDSBuffer = NULL;
 
-    if( !EQUALN(pszResampling, "NEAR", 4))
+    if( !STARTS_WITH_CI(pszResampling, "NEAR"))
     {
-        pabyPrevOvrMEMDSBuffer =
-            (GByte*)VSIMalloc3(nPrevOvrBlockXSize, nPrevOvrBlockYSize, nBands * nDataTypeSize);
+        pabyPrevOvrMEMDSBuffer = reinterpret_cast<GByte*>(
+            VSIMalloc3( nPrevOvrBlockXSize, nPrevOvrBlockYSize, nBands * nDataTypeSize ) );
         if (pabyPrevOvrMEMDSBuffer == NULL)
         {
             VSIFree(pabyMEMDSBuffer);
@@ -427,19 +420,19 @@ CPLErr RasterliteDataset::CreateOverviewLevel(const char * pszResampling,
     char** papszTileDriverOptions = RasterliteGetTileDriverOptions(papszOptions);
 
     OGR_DS_ExecuteSQL(hDS, "BEGIN", NULL, NULL);
-    
+
     CPLErr eErr = CE_None;
-    int nBlockXOff, nBlockYOff;
-    for(nBlockYOff=0;eErr == CE_None && nBlockYOff<nYBlocks;nBlockYOff++)
+    for( int nBlockYOff = 0; eErr == CE_None && nBlockYOff < nYBlocks; nBlockYOff++ )
     {
-        for(nBlockXOff=0;eErr == CE_None && nBlockXOff<nXBlocks;nBlockXOff++)
+        for( int nBlockXOff = 0; eErr == CE_None && nBlockXOff < nXBlocks; nBlockXOff++ )
         {
             GDALDatasetH hPrevOvrMemDS = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Create in-memory tile                                           */
 /* -------------------------------------------------------------------- */
-            int nReqXSize = nBlockXSize, nReqYSize = nBlockYSize;
+            int nReqXSize = nBlockXSize;
+            int nReqYSize = nBlockYSize;
             if ((nBlockXOff+1) * nBlockXSize > nOvrXSize)
                 nReqXSize = nOvrXSize - nBlockXOff * nBlockXSize;
             if ((nBlockYOff+1) * nBlockYSize > nOvrYSize)
@@ -448,9 +441,9 @@ CPLErr RasterliteDataset::CreateOverviewLevel(const char * pszResampling,
             if( pabyPrevOvrMEMDSBuffer != NULL )
             {
                 int nPrevOvrReqXSize =
-                    (int)(nReqXSize * dfRatioPrevOvr + 0.5);
+                    static_cast<int>( nReqXSize * dfRatioPrevOvr + 0.5 );
                 int nPrevOvrReqYSize =
-                    (int)(nReqYSize * dfRatioPrevOvr + 0.5);
+                    static_cast<int>(nReqYSize * dfRatioPrevOvr + 0.5 );
 
                 eErr = RasterIO(GF_Read,
                                 nBlockXOff * nBlockXSize * nOvrFactor,
@@ -475,18 +468,17 @@ CPLErr RasterliteDataset::CreateOverviewLevel(const char * pszResampling,
                     break;
                 }
 
-                int iBand;
-                for(iBand = 0; iBand < nBands; iBand ++)
+                for( int iBand = 0; iBand < nBands; iBand++ )
                 {
-                    char** papszOptions = NULL;
                     char szTmp[64];
                     memset(szTmp, 0, sizeof(szTmp));
                     CPLPrintPointer(szTmp,
                                     pabyPrevOvrMEMDSBuffer + iBand * nDataTypeSize *
                                     nPrevOvrReqXSize * nPrevOvrReqYSize, sizeof(szTmp));
-                    papszOptions = CSLSetNameValue(papszOptions, "DATAPOINTER", szTmp);
-                    GDALAddBand(hPrevOvrMemDS, eDataType, papszOptions);
-                    CSLDestroy(papszOptions);
+                    char** l_papszOptions
+                        = CSLSetNameValue(NULL, "DATAPOINTER", szTmp);
+                    GDALAddBand(hPrevOvrMemDS, eDataType, l_papszOptions);
+                    CSLDestroy(l_papszOptions);
                 }
             }
             else
@@ -512,24 +504,24 @@ CPLErr RasterliteDataset::CreateOverviewLevel(const char * pszResampling,
                 eErr = CE_Failure;
                 break;
             }
-            
-            int iBand;
-            for(iBand = 0; iBand < nBands; iBand ++)
+
+
+            for(int iBand = 0; iBand < nBands; iBand ++)
             {
-                char** papszOptions = NULL;
                 char szTmp[64];
                 memset(szTmp, 0, sizeof(szTmp));
                 CPLPrintPointer(szTmp,
                                 pabyMEMDSBuffer + iBand * nDataTypeSize *
                                 nReqXSize * nReqYSize, sizeof(szTmp));
-                papszOptions = CSLSetNameValue(papszOptions, "DATAPOINTER", szTmp);
-                GDALAddBand(hMemDS, eDataType, papszOptions);
-                CSLDestroy(papszOptions);
+                char** l_papszOptions
+                    = CSLSetNameValue(NULL, "DATAPOINTER", szTmp);
+                GDALAddBand(hMemDS, eDataType, l_papszOptions);
+                CSLDestroy(l_papszOptions);
             }
 
             if( hPrevOvrMemDS != NULL )
             {
-                for(iBand = 0; iBand < nBands; iBand ++)
+                for(int iBand = 0; iBand < nBands; iBand ++)
                 {
                     GDALRasterBandH hDstOvrBand = GDALGetRasterBand(hMemDS, iBand+1);
 
@@ -549,14 +541,14 @@ CPLErr RasterliteDataset::CreateOverviewLevel(const char * pszResampling,
                                         papszTileDriverOptions, NULL, NULL);
 
             GDALClose(hMemDS);
-            if (hOutDS)
-                GDALClose(hOutDS);
-            else
+            if (! hOutDS)
             {
                 eErr = CE_Failure;
                 break;
             }
 
+            GDALClose(hOutDS);
+
 /* -------------------------------------------------------------------- */
 /*      Insert new entry into raster table                              */
 /* -------------------------------------------------------------------- */
@@ -566,20 +558,23 @@ CPLErr RasterliteDataset::CreateOverviewLevel(const char * pszResampling,
                                                    &nDataLength, FALSE);
 
             OGRFeatureH hFeat = OGR_F_Create( OGR_L_GetLayerDefn(hRasterLayer) );
-            OGR_F_SetFieldBinary(hFeat, 0, (int)nDataLength, pabyData);
-            
-            OGR_L_CreateFeature(hRasterLayer, hFeat);
+            OGR_F_SetFieldBinary(hFeat, 0, static_cast<int>( nDataLength ), pabyData);
+
+            if( OGR_L_CreateFeature(hRasterLayer, hFeat) != OGRERR_NONE )
+                eErr = CE_Failure;
             /* Query raster ID to set it as the ID of the associated metadata */
-            int nRasterID = (int)OGR_F_GetFID(hFeat);
-            
+            const int nRasterID = static_cast<int>( OGR_F_GetFID(hFeat) );
+
             OGR_F_Destroy(hFeat);
-            
+
             VSIUnlink(osTempFileName.c_str());
-            
+            if( eErr == CE_Failure )
+                break;
+
 /* -------------------------------------------------------------------- */
 /*      Insert new entry into metadata table                            */
 /* -------------------------------------------------------------------- */
-            
+
             hFeat = OGR_F_Create( OGR_L_GetLayerDefn(hMetadataLayer) );
             OGR_F_SetFID(hFeat, nRasterID);
             OGR_F_SetFieldString(hFeat, 0, osSourceName);
@@ -588,17 +583,16 @@ CPLErr RasterliteDataset::CreateOverviewLevel(const char * pszResampling,
             OGR_F_SetFieldInteger(hFeat, 3, nReqYSize);
             OGR_F_SetFieldDouble(hFeat, 4, dfXResolution);
             OGR_F_SetFieldDouble(hFeat, 5, dfYResolution);
-            
-            double minx, maxx, maxy, miny;
-            minx = adfGeoTransform[0] +
+
+            const double minx = adfGeoTransform[0] +
                 (nBlockXSize * nBlockXOff) * dfXResolution;
-            maxx = adfGeoTransform[0] +
+            const double maxx = adfGeoTransform[0] +
                 (nBlockXSize * nBlockXOff + nReqXSize) * dfXResolution;
-            maxy = adfGeoTransform[3] +
+            const double maxy = adfGeoTransform[3] +
                 (nBlockYSize * nBlockYOff) * (-dfYResolution);
-            miny = adfGeoTransform[3] +
+            const double miny = adfGeoTransform[3] +
                 (nBlockYSize * nBlockYOff + nReqYSize) * (-dfYResolution);
-            
+
             OGRGeometryH hRectangle = OGR_G_CreateGeometry(wkbPolygon);
             OGRGeometryH hLinearRing = OGR_G_CreateGeometry(wkbLinearRing);
             OGR_G_AddPoint_2D(hLinearRing, minx, miny);
@@ -607,12 +601,13 @@ CPLErr RasterliteDataset::CreateOverviewLevel(const char * pszResampling,
             OGR_G_AddPoint_2D(hLinearRing, maxx, miny);
             OGR_G_AddPoint_2D(hLinearRing, minx, miny);
             OGR_G_AddGeometryDirectly(hRectangle, hLinearRing);
-            
+
             OGR_F_SetGeometryDirectly(hFeat, hRectangle);
-            
-            OGR_L_CreateFeature(hMetadataLayer, hFeat);
+
+            if( OGR_L_CreateFeature(hMetadataLayer, hFeat) != OGRERR_NONE )
+                eErr = CE_Failure;
             OGR_F_Destroy(hFeat);
-            
+
             nBlocks++;
             if (pfnProgress && !pfnProgress(1.0 * nBlocks / nTotalBlocks,
                                             NULL, pProgressData))
@@ -621,12 +616,12 @@ CPLErr RasterliteDataset::CreateOverviewLevel(const char * pszResampling,
     }
 
     nLimitOvrCount = -1;
-    
+
     if (eErr == CE_None)
         OGR_DS_ExecuteSQL(hDS, "COMMIT", NULL, NULL);
     else
         OGR_DS_ExecuteSQL(hDS, "ROLLBACK", NULL, NULL);
-    
+
     VSIFree(pabyMEMDSBuffer);
     VSIFree(pabyPrevOvrMEMDSBuffer);
 
@@ -636,85 +631,87 @@ CPLErr RasterliteDataset::CreateOverviewLevel(const char * pszResampling,
 /* -------------------------------------------------------------------- */
 /*      Update raster_pyramids table                                    */
 /* -------------------------------------------------------------------- */
-    if (eErr == CE_None)
+    if (eErr != CE_None)
+        return eErr;
+
+    OGRLayerH hRasterPyramidsLyr = OGR_DS_GetLayerByName(hDS, "raster_pyramids");
+    if (hRasterPyramidsLyr == NULL)
     {
-        OGRLayerH hRasterPyramidsLyr = OGR_DS_GetLayerByName(hDS, "raster_pyramids");
+        osSQL.Printf   ("CREATE TABLE raster_pyramids ("
+                        "table_prefix TEXT NOT NULL,"
+                        "pixel_x_size DOUBLE NOT NULL,"
+                        "pixel_y_size DOUBLE NOT NULL,"
+                        "tile_count INTEGER NOT NULL)");
+        OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+
+        /* Re-open the DB to take into account the new tables*/
+        OGRReleaseDataSource(hDS);
+
+        hDS = RasterliteOpenSQLiteDB(osFileName.c_str(), GA_Update);
+
+        hRasterPyramidsLyr = OGR_DS_GetLayerByName(hDS, "raster_pyramids");
         if (hRasterPyramidsLyr == NULL)
+            return CE_Failure;
+    }
+    OGRFeatureDefnH hFDefn = OGR_L_GetLayerDefn(hRasterPyramidsLyr);
+
+    /* Insert base resolution into raster_pyramids if not already done */
+    bool bHasBaseResolution = false;
+    osSQL.Printf("SELECT * FROM raster_pyramids WHERE "
+                 "table_prefix = '%s' AND %s",
+                 osTableName.c_str(),
+                 RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0]).c_str());
+    hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+    if (hSQLLyr)
+    {
+        OGRFeatureH hFeat = OGR_L_GetNextFeature(hSQLLyr);
+        if (hFeat)
         {
-            osSQL.Printf   ("CREATE TABLE raster_pyramids ("
-                            "table_prefix TEXT NOT NULL,"
-                            "pixel_x_size DOUBLE NOT NULL,"
-                            "pixel_y_size DOUBLE NOT NULL,"
-                            "tile_count INTEGER NOT NULL)");
-            OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-            
-            /* Re-open the DB to take into account the new tables*/
-            OGRReleaseDataSource(hDS);
-            
-            hDS = RasterliteOpenSQLiteDB(osFileName.c_str(), GA_Update);
-
-            hRasterPyramidsLyr = OGR_DS_GetLayerByName(hDS, "raster_pyramids");
-            if (hRasterPyramidsLyr == NULL)
-                return CE_Failure;
+            bHasBaseResolution = true;
+            OGR_F_Destroy(hFeat);
         }
-        OGRFeatureDefnH hFDefn = OGR_L_GetLayerDefn(hRasterPyramidsLyr);
-
-        /* Insert base resolution into raster_pyramids if not already done */
-        int bHasBaseResolution = FALSE;
-        osSQL.Printf("SELECT * FROM raster_pyramids WHERE "
-                     "table_prefix = '%s' AND %s",
-                     osTableName.c_str(),
-                     RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0]).c_str());
+        OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
+    }
+
+    if (!bHasBaseResolution)
+    {
+        osSQL.Printf("SELECT COUNT(*) FROM \"%s\" WHERE %s",
+                      osMetatadataLayer.c_str(),
+                      RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0]).c_str());
+
+        int nBlocksMainRes = 0;
+
         hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
         if (hSQLLyr)
         {
             OGRFeatureH hFeat = OGR_L_GetNextFeature(hSQLLyr);
             if (hFeat)
             {
-                bHasBaseResolution = TRUE;
+                nBlocksMainRes = OGR_F_GetFieldAsInteger(hFeat, 0);
                 OGR_F_Destroy(hFeat);
             }
             OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
         }
 
-        if (!bHasBaseResolution)
-        {
-            osSQL.Printf("SELECT COUNT(*) FROM \"%s\" WHERE %s",
-                          osMetatadataLayer.c_str(),
-                          RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0]).c_str());
-
-            int nBlocksMainRes = 0;
-
-            hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-            if (hSQLLyr)
-            {
-                OGRFeatureH hFeat = OGR_L_GetNextFeature(hSQLLyr);
-                if (hFeat)
-                {
-                    nBlocksMainRes = OGR_F_GetFieldAsInteger(hFeat, 0);
-                    OGR_F_Destroy(hFeat);
-                }
-                OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
-            }
-
-            OGRFeatureH hFeat = OGR_F_Create( hFDefn );
-            OGR_F_SetFieldString(hFeat, OGR_FD_GetFieldIndex(hFDefn, "table_prefix"), osTableName.c_str());
-            OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_x_size"), padfXResolutions[0]);
-            OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_y_size"), padfYResolutions[0]);
-            OGR_F_SetFieldInteger(hFeat, OGR_FD_GetFieldIndex(hFDefn, "tile_count"), nBlocksMainRes);
-            OGR_L_CreateFeature(hRasterPyramidsLyr, hFeat);
-            OGR_F_Destroy(hFeat);
-        }
-
         OGRFeatureH hFeat = OGR_F_Create( hFDefn );
         OGR_F_SetFieldString(hFeat, OGR_FD_GetFieldIndex(hFDefn, "table_prefix"), osTableName.c_str());
-        OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_x_size"), dfXResolution);
-        OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_y_size"), dfYResolution);
-        OGR_F_SetFieldInteger(hFeat, OGR_FD_GetFieldIndex(hFDefn, "tile_count"), nTotalBlocks);
-        OGR_L_CreateFeature(hRasterPyramidsLyr, hFeat);
+        OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_x_size"), padfXResolutions[0]);
+        OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_y_size"), padfYResolutions[0]);
+        OGR_F_SetFieldInteger(hFeat, OGR_FD_GetFieldIndex(hFDefn, "tile_count"), nBlocksMainRes);
+        if( OGR_L_CreateFeature(hRasterPyramidsLyr, hFeat) != OGRERR_NONE )
+            eErr = CE_Failure;
         OGR_F_Destroy(hFeat);
     }
 
+    OGRFeatureH hFeat = OGR_F_Create( hFDefn );
+    OGR_F_SetFieldString(hFeat, OGR_FD_GetFieldIndex(hFDefn, "table_prefix"), osTableName.c_str());
+    OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_x_size"), dfXResolution);
+    OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_y_size"), dfYResolution);
+    OGR_F_SetFieldInteger(hFeat, OGR_FD_GetFieldIndex(hFDefn, "tile_count"), nTotalBlocks);
+    if( OGR_L_CreateFeature(hRasterPyramidsLyr, hFeat) != OGRERR_NONE )
+        eErr = CE_Failure;
+    OGR_F_Destroy(hFeat);
+
     return eErr;
 }
 
@@ -724,22 +721,20 @@ CPLErr RasterliteDataset::CreateOverviewLevel(const char * pszResampling,
 
 CPLErr RasterliteDataset::IBuildOverviews( const char * pszResampling, 
                                            int nOverviews, int * panOverviewList,
-                                           int nBands, int * panBandList,
+                                           int nBandsIn, int * panBandList,
                                            GDALProgressFunc pfnProgress,
                                            void * pProgressData )
 {
-    CPLErr eErr = CE_None;
-    
     if (nLevel != 0)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Overviews can only be computed on the base dataset");
         return CE_Failure;
     }
-        
+
     if (osTableName.size() == 0)
         return CE_Failure;
-    
+
 /* -------------------------------------------------------------------- */
 /*      If we don't have read access, then create the overviews         */
 /*      externally.                                                     */
@@ -749,7 +744,7 @@ CPLErr RasterliteDataset::IBuildOverviews( const char * pszResampling,
         CPLDebug( "Rasterlite",
                   "File open for read-only accessing, "
                   "creating overviews externally." );
-                  
+
         if (nResolutions != 1)
         {
             CPLError(CE_Failure, CPLE_NotSupported,
@@ -759,13 +754,13 @@ CPLErr RasterliteDataset::IBuildOverviews( const char * pszResampling,
         }
 
         bCheckForExistingOverview = FALSE;
-        eErr = GDALDataset::IBuildOverviews( 
+        CPLErr eErr = GDALDataset::IBuildOverviews( 
                             pszResampling, nOverviews, panOverviewList, 
-                            nBands, panBandList, pfnProgress, pProgressData );
+                            nBandsIn, panBandList, pfnProgress, pProgressData );
         bCheckForExistingOverview = TRUE;
         return eErr;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      If zero overviews were requested, we need to clear all          */
 /*      existing overviews.                                             */
@@ -774,8 +769,8 @@ CPLErr RasterliteDataset::IBuildOverviews( const char * pszResampling,
     {
         return CleanOverviews();
     }
-    
-    if( nBands != GetRasterCount() )
+
+    if( nBandsIn != GetRasterCount() )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
                   "Generation of overviews in RASTERLITE only"
@@ -788,8 +783,8 @@ CPLErr RasterliteDataset::IBuildOverviews( const char * pszResampling,
     char** papszOptions = (pszOvrOptions) ? CSLTokenizeString2( pszOvrOptions, ",", 0) : NULL;
     GDALValidateCreationOptions( GetDriver(), papszOptions);
 
-    int i;
-    for(i=0;i<nOverviews && eErr == CE_None;i++)
+    CPLErr eErr = CE_None;
+    for( int i = 0; i < nOverviews && eErr == CE_None; i++)
     {
         if (panOverviewList[i] <= 1)
             continue;
@@ -797,11 +792,11 @@ CPLErr RasterliteDataset::IBuildOverviews( const char * pszResampling,
         eErr = CleanOverviewLevel(panOverviewList[i]);
         if (eErr == CE_None)
             eErr = CreateOverviewLevel(pszResampling, panOverviewList[i], papszOptions, pfnProgress, pProgressData);
-    
+
         ReloadOverviews();
     }
 
     CSLDestroy(papszOptions);
-    
+
     return eErr;
 }
diff --git a/frmts/raw/GNUmakefile b/frmts/raw/GNUmakefile
index b02c166..85cc878 100644
--- a/frmts/raw/GNUmakefile
+++ b/frmts/raw/GNUmakefile
@@ -9,7 +9,7 @@ OBJ	=	rawdataset.o ehdrdataset.o pauxdataset.o doq1dataset.o \
 		idadataset.o ndfdataset.o dipxdataset.o genbindataset.o \
 		lcpdataset.o eirdataset.o gtxdataset.o loslasdataset.o \
 		ntv2dataset.o ace2dataset.o snodasdataset.o ctable2dataset.o \
-		krodataset.o roipacdataset.o
+		krodataset.o roipacdataset.o iscedataset.o
 
 
 
diff --git a/frmts/raw/ace2dataset.cpp b/frmts/raw/ace2dataset.cpp
index d772fc6..e63fb78 100644
--- a/frmts/raw/ace2dataset.cpp
+++ b/frmts/raw/ace2dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ace2dataset.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ace2dataset.cpp 32215 2015-12-18 06:30:54Z goatbar $
  *
  * Project:  ACE2 Driver
  * Purpose:  Implementation of ACE2 elevation format read support.
@@ -28,24 +28,23 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "rawdataset.h"
+#include "gdal_frmts.h"
 #include "ogr_spatialref.h"
+#include "rawdataset.h"
 
-CPL_CVSID("$Id: ace2dataset.cpp 27384 2014-05-24 12:28:12Z rouault $");
-
-CPL_C_START
-void    GDALRegister_ACE2(void);
-CPL_C_END
+CPL_CVSID("$Id: ace2dataset.cpp 32215 2015-12-18 06:30:54Z goatbar $");
 
 static const char * const apszCategorySource[] =
 {
-    "Pure SRTM (above 60deg N pure GLOBE data, below 60S pure ACE [original] data)",
+    "Pure SRTM (above 60deg N pure GLOBE data, below 60S pure ACE [original] "
+    "data)",
     "SRTM voids filled by interpolation and/or altimeter data",
     "SRTM data warped using the ERS-1 Geodetic Mission",
     "SRTM data warped using EnviSat & ERS-2 data",
     "Mean lake level data derived from Altimetry",
     "GLOBE/ACE data warped using combined altimetry (only above 60deg N)",
-    "Pure altimetry data (derived from ERS-1 Geodetic Mission, ERS-2 and EnviSat data using Delaunay Triangulation",
+    "Pure altimetry data (derived from ERS-1 Geodetic Mission, ERS-2 and "
+    "EnviSat data using Delaunay Triangulation",
     NULL
 };
 
@@ -100,7 +99,6 @@ class ACE2Dataset : public GDALPamDataset
     double       adfGeoTransform[6];
 
   public:
-
                 ACE2Dataset();
 
     virtual const char *GetProjectionRef(void);
@@ -172,11 +170,11 @@ const char *ACE2Dataset::GetProjectionRef()
 /*                          ACE2RasterBand()                            */
 /************************************************************************/
 
-ACE2RasterBand::ACE2RasterBand(VSILFILE* fpRaw,
-                               GDALDataType eDataType,
+ACE2RasterBand::ACE2RasterBand(VSILFILE* fpRawIn,
+                               GDALDataType eDataTypeIn,
                                int nXSize, int nYSize) :
-    RawRasterBand( fpRaw, 0, GDALGetDataTypeSize(eDataType) / 8,
-                   nXSize * GDALGetDataTypeSize(eDataType) / 8, eDataType,
+    RawRasterBand( fpRawIn, 0, GDALGetDataTypeSize(eDataTypeIn) / 8,
+                   nXSize * GDALGetDataTypeSize(eDataTypeIn) / 8, eDataTypeIn,
                    CPL_IS_LSB, nXSize, nYSize, TRUE, TRUE)
 {
 }
@@ -189,8 +187,8 @@ const char *ACE2RasterBand::GetUnitType()
 {
     if (eDataType == GDT_Float32)
         return "m";
-    else
-        return "";
+
+    return "";
 }
 
 /************************************************************************/
@@ -199,16 +197,17 @@ const char *ACE2RasterBand::GetUnitType()
 
 char **ACE2RasterBand::GetCategoryNames()
 {
-    if (eDataType == GDT_Int16)
-    {
-        const char* pszName = poDS->GetDescription();
-        if (strstr(pszName, "_SOURCE_"))
-            return (char**) apszCategorySource;
-        else if (strstr(pszName, "_QUALITY_"))
-            return (char**) apszCategoryQuality;
-        else if (strstr(pszName, "_CONF_"))
-            return (char**) apszCategoryConfidence;
-    }
+    if (eDataType != GDT_Int16)
+        return NULL;
+
+    const char* pszName = poDS->GetDescription();
+
+    if (strstr(pszName, "_SOURCE_"))
+        return const_cast<char **>( apszCategorySource );
+    if (strstr(pszName, "_QUALITY_"))
+        return const_cast<char **>( apszCategoryQuality );
+    if (strstr(pszName, "_CONF_"))
+        return const_cast<char **>( apszCategoryConfidence );
 
     return NULL;
 }
@@ -329,7 +328,7 @@ GDALDataset *ACE2Dataset::Open( GDALOpenInfo * poOpenInfo )
     CPLString osFilename = poOpenInfo->pszFilename;
     if ((strstr(poOpenInfo->pszFilename, ".ACE2.gz") ||
          strstr(poOpenInfo->pszFilename, ".ace2.gz")) &&
-        strncmp(poOpenInfo->pszFilename, "/vsigzip/", 9) != 0)
+        !STARTS_WITH(poOpenInfo->pszFilename, "/vsigzip/"))
         osFilename = "/vsigzip/" + osFilename;
 
     VSILFILE* fpImage = VSIFOpenL( osFilename, "rb+" );
@@ -339,9 +338,8 @@ GDALDataset *ACE2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create the dataset.                                             */
 /* -------------------------------------------------------------------- */
-    ACE2Dataset  *poDS;
+    ACE2Dataset  *poDS = new ACE2Dataset();
 
-    poDS = new ACE2Dataset();
     poDS->nRasterXSize = nXSize;
     poDS->nRasterYSize = nYSize;
 
@@ -378,24 +376,20 @@ GDALDataset *ACE2Dataset::Open( GDALOpenInfo * poOpenInfo )
 void GDALRegister_ACE2()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "ACE2" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "ACE2" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "ACE2" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "ACE2" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "frmt_various.html#ACE2" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "ACE2" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetDescription( "ACE2" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "ACE2" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#ACE2" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "ACE2" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = ACE2Dataset::Open;
-        poDriver->pfnIdentify = ACE2Dataset::Identify;
+    poDriver->pfnOpen = ACE2Dataset::Open;
+    poDriver->pfnIdentify = ACE2Dataset::Identify;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/raw/atlsci_spheroid.cpp b/frmts/raw/atlsci_spheroid.cpp
index a64de12..e70cd9d 100644
--- a/frmts/raw/atlsci_spheroid.cpp
+++ b/frmts/raw/atlsci_spheroid.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: atlsci_spheroid.cpp 22381 2011-05-16 21:14:22Z rouault $
+ * $Id: atlsci_spheroid.cpp 33673 2016-03-07 20:40:54Z goatbar $
  *
  * Project:  Spheroid classes
  * Purpose:  Provide spheroid lookup table base classes.
@@ -30,7 +30,7 @@
 #include "atlsci_spheroid.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: atlsci_spheroid.cpp 22381 2011-05-16 21:14:22Z rouault $");
+CPL_CVSID("$Id: atlsci_spheroid.cpp 33673 2016-03-07 20:40:54Z goatbar $");
 
 /**********************************************************************/
 /* ================================================================== */
@@ -68,9 +68,11 @@ SpheroidItem :: ~SpheroidItem()
       CPLFree(spheroid_name);
 }
 
-SpheroidList :: SpheroidList()
+SpheroidList :: SpheroidList() :
+    num_spheroids(0),
+    epsilonR(0.0),
+    epsilonI(0.0)
 {
-  num_spheroids=0;
 }
 
 SpheroidList :: ~SpheroidList()
@@ -79,78 +81,62 @@ SpheroidList :: ~SpheroidList()
 
 char *SpheroidList :: GetSpheroidNameByRadii( double eq_radius, double polar_radius )
 {
-  int index=0;
-  double er=0.0;
-  double pr=0.0;
-
-  for(index=0;index<num_spheroids;index++)
+  for( int index = 0; index < num_spheroids; index++ )
   {
-    er = spheroids[index].equitorial_radius;
-    pr = spheroids[index].polar_radius;
+    const double er = spheroids[index].equitorial_radius;
+    const double pr = spheroids[index].polar_radius;
     if ((fabs(er - eq_radius) < epsilonR) && (fabs(pr - polar_radius) < epsilonR))
       return CPLStrdup(spheroids[index].spheroid_name);
   }
-  
+
   return NULL;
 
 }
 
 char *SpheroidList :: GetSpheroidNameByEqRadiusAndInvFlattening( double eq_radius, double inverse_flattening )
 {
-  int index=0;
-  double er=0.0;
-  double invf=0.0;
-
-  for(index=0;index<num_spheroids;index++)
+  for( int index = 0; index < num_spheroids; index++ )
   {
-    er = spheroids[index].equitorial_radius;
-    invf = spheroids[index].inverse_flattening;
+    const double er = spheroids[index].equitorial_radius;
+    const double invf = spheroids[index].inverse_flattening;
     if ((fabs(er - eq_radius) < epsilonR) && (fabs(invf - inverse_flattening) < epsilonI))
       return CPLStrdup(spheroids[index].spheroid_name);
   }
-  
-  return NULL;
 
+  return NULL;
 }
 
 double SpheroidList :: GetSpheroidEqRadius( const char *spheroid_name )
 {
-  int index=0;
-
-  for(index=0;index<num_spheroids;index++)
+  for( int index = 0; index < num_spheroids; index++ )
   {
     if EQUAL(spheroids[index].spheroid_name,spheroid_name)
       return spheroids[index].equitorial_radius;
   }
-  
-  return -1.0;
 
+  return -1.0;
 }
 
 int SpheroidList :: SpheroidInList( const char *spheroid_name )
 {
   /* Return 1 if the spheroid name is recognized; 0 otherwise */
-  int index=0;
-
-  for(index=0;index<num_spheroids;index++)
+  for( int index = 0; index < num_spheroids; index++)
   {
-    if EQUAL(spheroids[index].spheroid_name,spheroid_name) 
+    if EQUAL(spheroids[index].spheroid_name,spheroid_name)
       return 1;
   }
-  
+
   return 0;
 }
 
 double SpheroidList :: GetSpheroidInverseFlattening( const char *spheroid_name )
 {
-  int index=0;
-
-  for(index=0;index<num_spheroids;index++)
+  for( int index = 0; index < num_spheroids; index++ )
   {
     if  EQUAL(spheroids[index].spheroid_name,spheroid_name)
       return spheroids[index].inverse_flattening;
   }
-  
+
   return -1.0;
 
 }
@@ -164,8 +150,6 @@ double SpheroidList :: GetSpheroidPolarRadius( const char *spheroid_name )
     if (strcmp(spheroids[index].spheroid_name,spheroid_name) == 0)
       return spheroids[index].polar_radius;
   }
-  
-  return -1.0;
 
+  return -1.0;
 }
-
diff --git a/frmts/raw/atlsci_spheroid.h b/frmts/raw/atlsci_spheroid.h
index 06ba285..2fa6c20 100644
--- a/frmts/raw/atlsci_spheroid.h
+++ b/frmts/raw/atlsci_spheroid.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: atlsci_spheroid.h 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: atlsci_spheroid.h 33673 2016-03-07 20:40:54Z goatbar $
  *
  * Project:  Spheroid classes
  * Purpose:  Provide spheroid lookup table base classes.
@@ -37,7 +37,7 @@
 /* Maximum number of expected spheroids */
 # define MAX_RECOGNIZED_SPHEROIDS 256
 
-class SpheroidItem 
+class SpheroidItem
 {
 
 public:
@@ -45,16 +45,15 @@ public:
    ~SpheroidItem();
 
    char *spheroid_name;
-   double equitorial_radius;
+   double equitorial_radius;  // TODO: Spelling.
    double polar_radius;
    double inverse_flattening;
 
    void SetValuesByRadii(const char *spheroidname, double eq_radius, double p_radius);
    void SetValuesByEqRadiusAndInvFlattening(const char *spheroidname, double eq_radius, double inverseflattening);
-
 };
 
-class SpheroidList 
+class SpheroidList
 {
 
 public:
@@ -63,7 +62,6 @@ public:
   double epsilonR;
   double epsilonI;
 
-
   SpheroidItem spheroids[MAX_RECOGNIZED_SPHEROIDS];
 
   SpheroidList();
@@ -74,8 +72,6 @@ public:
 
   int SpheroidInList( const char *spheroid_name );
   double GetSpheroidEqRadius( const char *spheroid_name );
-  double GetSpheroidPolarRadius( const char *spheroid_name ); 
+  double GetSpheroidPolarRadius( const char *spheroid_name );
   double GetSpheroidInverseFlattening( const char *spheroid_name );
-
 };
-
diff --git a/frmts/raw/btdataset.cpp b/frmts/raw/btdataset.cpp
index a15b64e..df56a4d 100644
--- a/frmts/raw/btdataset.cpp
+++ b/frmts/raw/btdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: btdataset.cpp 30887 2015-10-07 15:52:20Z rouault $
+ * $Id: btdataset.cpp 33673 2016-03-07 20:40:54Z goatbar $
  *
  * Project:  VTP .bt Driver
  * Purpose:  Implementation of VTP .bt elevation format read/write support.
@@ -29,14 +29,11 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "rawdataset.h"
+#include "gdal_frmts.h"
 #include "ogr_spatialref.h"
+#include "rawdataset.h"
 
-CPL_CVSID("$Id: btdataset.cpp 30887 2015-10-07 15:52:20Z rouault $");
-
-CPL_C_START
-void    GDALRegister_BT(void);
-CPL_C_END
+CPL_CVSID("$Id: btdataset.cpp 33673 2016-03-07 20:40:54Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -54,7 +51,7 @@ class BTDataset : public GDALPamDataset
     double      adfGeoTransform[6];
 
     char        *pszProjection;
-    
+
     int         nVersionCode;  // version times 10.
 
     int         bHeaderModified;
@@ -91,7 +88,6 @@ class BTRasterBand : public GDALPamRasterBand
     VSILFILE          *fpImage;
 
   public:
-
                    BTRasterBand( GDALDataset * poDS, VSILFILE * fp,
                                  GDALDataType eType );
 
@@ -104,18 +100,16 @@ class BTRasterBand : public GDALPamRasterBand
     virtual CPLErr SetNoDataValue( double );
 };
 
-
 /************************************************************************/
 /*                           BTRasterBand()                             */
 /************************************************************************/
 
-BTRasterBand::BTRasterBand( GDALDataset *poDS, VSILFILE *fp, GDALDataType eType )
-
+BTRasterBand::BTRasterBand( GDALDataset *poDSIn, VSILFILE *fp, GDALDataType eType ) :
+    fpImage(fp)
 {
-    this->poDS = poDS;
-    this->nBand = 1;
-    this->eDataType = eType;
-    this->fpImage = fp;
+    poDS = poDSIn;
+    nBand = 1;
+    eDataType = eType;
 
     nBlockXSize = 1;
     nBlockYSize = poDS->GetRasterYSize();
@@ -137,11 +131,11 @@ CPLErr BTRasterBand::IReadBlock( int nBlockXOff,
 /* -------------------------------------------------------------------- */
 /*      Seek to profile.                                                */
 /* -------------------------------------------------------------------- */
-    if( VSIFSeekL( fpImage, 
-                   256 + nBlockXOff * nDataSize * (vsi_l_offset) nRasterYSize, 
+    if( VSIFSeekL( fpImage,
+                   256 + nBlockXOff * nDataSize * (vsi_l_offset) nRasterYSize,
                    SEEK_SET ) != 0 )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   ".bt Seek failed:%s", VSIStrerror( errno ) );
         return CE_Failure;
     }
@@ -149,10 +143,10 @@ CPLErr BTRasterBand::IReadBlock( int nBlockXOff,
 /* -------------------------------------------------------------------- */
 /*      Read the profile.                                               */
 /* -------------------------------------------------------------------- */
-    if( VSIFReadL( pImage, nDataSize, nRasterYSize, fpImage ) != 
+    if( VSIFReadL( pImage, nDataSize, nRasterYSize, fpImage ) !=
         (size_t) nRasterYSize )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   ".bt Read failed:%s", VSIStrerror( errno ) );
         return CE_Failure;
     }
@@ -160,9 +154,9 @@ CPLErr BTRasterBand::IReadBlock( int nBlockXOff,
 /* -------------------------------------------------------------------- */
 /*      Swap on MSB platforms.                                          */
 /* -------------------------------------------------------------------- */
-#ifdef CPL_MSB 
+#ifdef CPL_MSB
     GDALSwapWords( pImage, nDataSize, nRasterYSize, nDataSize );
-#endif    
+#endif
 
 /* -------------------------------------------------------------------- */
 /*      Vertical flip, since GDAL expects values from top to bottom,    */
@@ -173,10 +167,10 @@ CPLErr BTRasterBand::IReadBlock( int nBlockXOff,
         GByte abyWrk[8];
 
         memcpy( abyWrk, ((GByte *) pImage) + i * nDataSize, nDataSize );
-        memcpy( ((GByte *) pImage) + i * nDataSize, 
-                ((GByte *) pImage) + (nRasterYSize - i - 1) * nDataSize, 
+        memcpy( ((GByte *) pImage) + i * nDataSize,
+                ((GByte *) pImage) + (nRasterYSize - i - 1) * nDataSize,
                 nDataSize );
-        memcpy( ((GByte *) pImage) + (nRasterYSize - i - 1) * nDataSize, 
+        memcpy( ((GByte *) pImage) + (nRasterYSize - i - 1) * nDataSize,
                 abyWrk, nDataSize );
     }
 
@@ -201,11 +195,11 @@ CPLErr BTRasterBand::IWriteBlock( int nBlockXOff,
 /* -------------------------------------------------------------------- */
 /*      Seek to profile.                                                */
 /* -------------------------------------------------------------------- */
-    if( VSIFSeekL( fpImage, 
-                   256 + nBlockXOff * nDataSize * nRasterYSize, 
+    if( VSIFSeekL( fpImage,
+                   256 + nBlockXOff * nDataSize * nRasterYSize,
                    SEEK_SET ) != 0 )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   ".bt Seek failed:%s", VSIStrerror( errno ) );
         return CE_Failure;
     }
@@ -222,25 +216,25 @@ CPLErr BTRasterBand::IWriteBlock( int nBlockXOff,
 /* -------------------------------------------------------------------- */
     for( i = 0; i < nRasterYSize; i++ )
     {
-        memcpy( pabyWrkBlock + (nRasterYSize - i - 1) * nDataSize, 
+        memcpy( pabyWrkBlock + (nRasterYSize - i - 1) * nDataSize,
                 ((GByte *) pImage) + i * nDataSize, nDataSize );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Swap on MSB platforms.                                          */
 /* -------------------------------------------------------------------- */
-#ifdef CPL_MSB 
+#ifdef CPL_MSB
     GDALSwapWords( pabyWrkBlock, nDataSize, nRasterYSize, nDataSize );
-#endif    
+#endif
 
 /* -------------------------------------------------------------------- */
 /*      Read the profile.                                               */
 /* -------------------------------------------------------------------- */
-    if( VSIFWriteL( pabyWrkBlock, nDataSize, nRasterYSize, fpImage ) != 
+    if( VSIFWriteL( pabyWrkBlock, nDataSize, nRasterYSize, fpImage ) !=
         (size_t) nRasterYSize )
     {
         CPLFree( pabyWrkBlock );
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   ".bt Write failed:%s", VSIStrerror( errno ) );
         return CE_Failure;
     }
@@ -293,7 +287,7 @@ const char* BTRasterBand::GetUnitType(void)
     // But m/ft/sft seem to be the top three.
 
     return "";
-} 
+}
 
 /************************************************************************/
 /*                            SetUnitType()                             */
@@ -321,7 +315,7 @@ CPLErr BTRasterBand::SetUnitType(const char* psz)
 
     ds.bHeaderModified = TRUE;
     return CE_None;
-} 
+}
 
 /************************************************************************/
 /* ==================================================================== */
@@ -333,19 +327,20 @@ CPLErr BTRasterBand::SetUnitType(const char* psz)
 /*                             BTDataset()                              */
 /************************************************************************/
 
-BTDataset::BTDataset()
+BTDataset::BTDataset() :
+    fpImage(NULL),
+    bGeoTransformValid(FALSE),
+    pszProjection(NULL),
+    nVersionCode(0),
+    bHeaderModified(FALSE),
+    m_fVscale(0.0)
 {
-    fpImage = NULL;
-    bGeoTransformValid = FALSE;
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
-    pszProjection = NULL;
-
-    bHeaderModified = FALSE;
 }
 
 /************************************************************************/
@@ -357,7 +352,12 @@ BTDataset::~BTDataset()
 {
     FlushCache();
     if( fpImage != NULL )
-        VSIFCloseL( fpImage );
+    {
+        if( VSIFCloseL( fpImage ) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        }
+    }
     CPLFree( pszProjection );
 }
 
@@ -377,8 +377,8 @@ void BTDataset::FlushCache()
 
     bHeaderModified = FALSE;
 
-    VSIFSeekL( fpImage, 0, SEEK_SET );
-    VSIFWriteL( abyHeader, 256, 1, fpImage );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( fpImage, 0, SEEK_SET ));
+    CPL_IGNORE_RET_VAL(VSIFWriteL( abyHeader, 256, 1, fpImage ));
 }
 
 /************************************************************************/
@@ -408,7 +408,7 @@ CPLErr BTDataset::SetGeoTransform( double *padfTransform )
     memcpy( adfGeoTransform, padfTransform, sizeof(double) * 6 );
     if( adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   ".bt format does not support rotational coefficients in geotransform, ignoring." );
         eErr = CE_Failure;
     }
@@ -432,7 +432,7 @@ CPLErr BTDataset::SetGeoTransform( double *padfTransform )
     CPL_LSBPTR64( abyHeader + 36 );
     CPL_LSBPTR64( abyHeader + 44 );
     CPL_LSBPTR64( abyHeader + 52 );
-    
+
     bHeaderModified = TRUE;
 
     return eErr;
@@ -476,7 +476,7 @@ CPLErr BTDataset::SetProjection( const char *pszNewProjection )
 /* -------------------------------------------------------------------- */
     if( oSRS.IsGeographic() )
         nShortTemp = 0;
-    else 
+    else
     {
         double dfLinear = oSRS.GetLinearUnits();
 
@@ -490,7 +490,7 @@ CPLErr BTDataset::SetProjection( const char *pszNewProjection )
 
     nShortTemp = CPL_LSBWORD16( 1 );
     memcpy( abyHeader + 22, &nShortTemp, 2 );
-    
+
 /* -------------------------------------------------------------------- */
 /*      UTM Zone                                                        */
 /* -------------------------------------------------------------------- */
@@ -502,7 +502,7 @@ CPLErr BTDataset::SetProjection( const char *pszNewProjection )
 
     nShortTemp = CPL_LSBWORD16( nShortTemp );
     memcpy( abyHeader + 24, &nShortTemp, 2 );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Datum                                                           */
 /* -------------------------------------------------------------------- */
@@ -518,18 +518,16 @@ CPLErr BTDataset::SetProjection( const char *pszNewProjection )
 /*      Write out the projection to a .prj file.                        */
 /* -------------------------------------------------------------------- */
     const char  *pszPrjFile = CPLResetExtension( GetDescription(), "prj" );
-    VSILFILE * fp;
-
-    fp = VSIFOpenL( pszPrjFile, "wt" );
+    VSILFILE * fp = VSIFOpenL( pszPrjFile, "wt" );
     if( fp != NULL )
     {
-        VSIFPrintfL( fp, "%s\n", pszProjection );
-        VSIFCloseL( fp );
+        CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "%s\n", pszProjection ));
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
         abyHeader[60] = 1;
     }
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to write out .prj file." );
         eErr = CE_Failure;
     }
@@ -551,16 +549,14 @@ GDALDataset *BTDataset::Open( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->nHeaderBytes < 256)
         return NULL;
 
-    if( strncmp( (const char *) poOpenInfo->pabyHeader, "binterr", 7 ) != 0 )
+    if( !STARTS_WITH((const char *) poOpenInfo->pabyHeader, "binterr") )
         return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Create the dataset.                                             */
 /* -------------------------------------------------------------------- */
-    BTDataset  *poDS;
+    BTDataset  *poDS = new BTDataset();
 
-    poDS = new BTDataset();
- 
     memcpy( poDS->abyHeader, poOpenInfo->pabyHeader, 256 );
 
 /* -------------------------------------------------------------------- */
@@ -582,7 +578,7 @@ GDALDataset *BTDataset::Open( GDALOpenInfo * poOpenInfo )
 
     memcpy( &nIntTemp, poDS->abyHeader + 10, 4 );
     poDS->nRasterXSize = CPL_LSBWORD32( nIntTemp );
-    
+
     memcpy( &nIntTemp, poDS->abyHeader + 14, 4 );
     poDS->nRasterYSize = CPL_LSBWORD32( nIntTemp );
 
@@ -603,8 +599,8 @@ GDALDataset *BTDataset::Open( GDALOpenInfo * poOpenInfo )
         eType = GDT_Int16;
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  ".bt file data type unknown, got datasize=%d.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  ".bt file data type unknown, got datasize=%d.",
                   nDataSize );
         delete poDS;
         return NULL;
@@ -618,16 +614,16 @@ GDALDataset *BTDataset::Open( GDALOpenInfo * poOpenInfo )
     memcpy( &poDS->m_fVscale, poDS->abyHeader + 62, 4 );
     CPL_LSBPTR32(&poDS->m_fVscale);
     if(poDS->m_fVscale == 0.0f)
-        poDS->m_fVscale = 1.0f; 
+        poDS->m_fVscale = 1.0f;
 
 /* -------------------------------------------------------------------- */
 /*      Try to read a .prj file if it is indicated.                     */
 /* -------------------------------------------------------------------- */
-    OGRSpatialReference oSRS;						
+    OGRSpatialReference oSRS;
 
     if( poDS->nVersionCode >= 12 && poDS->abyHeader[60] != 0 )
     {
-        const char  *pszPrjFile = CPLResetExtension( poOpenInfo->pszFilename, 
+        const char  *pszPrjFile = CPLResetExtension( poOpenInfo->pszFilename,
                                                      "prj" );
         VSILFILE *fp;
 
@@ -639,15 +635,15 @@ GDALDataset *BTDataset::Open( GDALOpenInfo * poOpenInfo )
             int nBytes;
 
             pszBuffer = (char *) CPLMalloc(nBufMax);
-            nBytes = VSIFReadL( pszBuffer, 1, nBufMax-1, fp );
-            VSIFCloseL( fp );
+            nBytes = static_cast<int>(VSIFReadL( pszBuffer, 1, nBufMax-1, fp ));
+            CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
 
             pszBuffer[nBytes] = '\0';
 
             pszBufPtr = pszBuffer;
             if( oSRS.importFromWkt( &pszBufPtr ) != OGRERR_NONE )
             {
-                CPLError( CE_Warning, CPLE_AppDefined, 
+                CPLError( CE_Warning, CPLE_AppDefined,
                           "Unable to parse .prj file, coordinate system missing." );
             }
             CPLFree( pszBuffer );
@@ -660,13 +656,13 @@ GDALDataset *BTDataset::Open( GDALOpenInfo * poOpenInfo )
     if( oSRS.GetRoot() == NULL )
     {
         GInt16 nUTMZone, nDatum, nHUnits;
-        
+
         memcpy( &nUTMZone, poDS->abyHeader + 24, 2 );
         nUTMZone = CPL_LSBWORD16( nUTMZone );
-        
+
         memcpy( &nDatum, poDS->abyHeader + 26, 2 );
         nDatum = CPL_LSBWORD16( nDatum );
-        
+
         memcpy( &nHUnits, poDS->abyHeader + 22, 2 );
         nHUnits = CPL_LSBWORD16( nHUnits );
 
@@ -674,7 +670,7 @@ GDALDataset *BTDataset::Open( GDALOpenInfo * poOpenInfo )
             oSRS.SetUTM( ABS(nUTMZone), nUTMZone > 0 );
         else if( nHUnits != 0 )
             oSRS.SetLocalCS( "Unknown" );
-        
+
         if( nHUnits == 1 )
             oSRS.SetLinearUnits( SRS_UL_METER, 1.0 );
         else if( nHUnits == 2 )
@@ -682,7 +678,7 @@ GDALDataset *BTDataset::Open( GDALOpenInfo * poOpenInfo )
         else if( nHUnits == 3 )
             oSRS.SetLinearUnits( SRS_UL_US_FOOT, CPLAtof(SRS_UL_US_FOOT_CONV) );
 
-        // Translate some of the more obvious old USGS datum codes 
+        // Translate some of the more obvious old USGS datum codes
         if( nDatum == 0 )
             nDatum = 6201;
         else if( nDatum == 1 )
@@ -717,12 +713,12 @@ GDALDataset *BTDataset::Open( GDALOpenInfo * poOpenInfo )
             if( nDatum >= 6000 )
             {
                 char szName[32];
-                sprintf( szName, "EPSG:%d", nDatum-2000 );
+                snprintf( szName, sizeof(szName), "EPSG:%d", nDatum-2000 );
                 oSRS.SetWellKnownGeogCS( szName );
             }
             else
                 oSRS.SetWellKnownGeogCS( "WGS84" );
-        }                
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -740,13 +736,13 @@ GDALDataset *BTDataset::Open( GDALOpenInfo * poOpenInfo )
 
         memcpy( &dfLeft, poDS->abyHeader + 28, 8 );
         CPL_LSBPTR64( &dfLeft );
-        
+
         memcpy( &dfRight, poDS->abyHeader + 36, 8 );
         CPL_LSBPTR64( &dfRight );
-        
+
         memcpy( &dfBottom, poDS->abyHeader + 44, 8 );
         CPL_LSBPTR64( &dfBottom );
-        
+
         memcpy( &dfTop, poDS->abyHeader + 52, 8 );
         CPL_LSBPTR64( &dfTop );
 
@@ -756,10 +752,10 @@ GDALDataset *BTDataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->adfGeoTransform[3] = dfTop;
         poDS->adfGeoTransform[4] = 0.0;
         poDS->adfGeoTransform[5] = (dfBottom - dfTop) / poDS->nRasterYSize;
-        
+
         poDS->bGeoTransformValid = TRUE;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Re-open the file with the desired access.                       */
 /* -------------------------------------------------------------------- */
@@ -774,6 +770,7 @@ GDALDataset *BTDataset::Open( GDALOpenInfo * poOpenInfo )
         CPLError( CE_Failure, CPLE_OpenFailed,
                   "Failed to re-open %s within BT driver.\n",
                   poOpenInfo->pszFilename );
+        delete poDS;
         return NULL;
     }
     poDS->eAccess = poOpenInfo->eAccess;
@@ -784,8 +781,8 @@ GDALDataset *BTDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->SetBand( 1, new BTRasterBand( poDS, poDS->fpImage, eType ) );
 
 #ifdef notdef
-    poDS->bGeoTransformValid = 
-        GDALReadWorldFile( poOpenInfo->pszFilename, ".wld", 
+    poDS->bGeoTransformValid =
+        GDALReadWorldFile( poOpenInfo->pszFilename, ".wld",
                            poDS->adfGeoTransform );
 #endif
 
@@ -840,9 +837,7 @@ GDALDataset *BTDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Try to create the file.                                         */
 /* -------------------------------------------------------------------- */
-    VSILFILE        *fp;
-
-    fp = VSIFOpenL( pszFilename, "wb" );
+    VSILFILE *fp = VSIFOpenL( pszFilename, "wb" );
 
     if( fp == NULL )
     {
@@ -861,30 +856,30 @@ GDALDataset *BTDataset::Create( const char * pszFilename,
 
     memset( abyHeader, 0, 256 );
     memcpy( abyHeader, "binterr1.3", 10 );
-    
+
     nTemp = CPL_LSBWORD32( nXSize );
     memcpy( abyHeader+10, &nTemp, 4 );
-    
+
     nTemp = CPL_LSBWORD32( nYSize );
     memcpy( abyHeader+14, &nTemp, 4 );
 
-    nShortTemp = (GInt16) (CPL_LSBWORD16( GDALGetDataTypeSize( eType ) / 8 ));
+    nShortTemp = (GInt16) (CPL_LSBWORD16( (GInt16)(GDALGetDataTypeSize( eType ) / 8 )) );
     memcpy( abyHeader + 18, &nShortTemp, 2 );
-    
+
     if( eType == GDT_Float32 )
         abyHeader[20] = 1;
     else
         abyHeader[20] = 0;
-    
+
     nShortTemp = CPL_LSBWORD16( 1 ); /* meters */
     memcpy( abyHeader + 22, &nShortTemp, 2 );
-    
+
     nShortTemp = CPL_LSBWORD16( 0 ); /* not utm */
     memcpy( abyHeader + 24, &nShortTemp, 2 );
-    
+
     nShortTemp = CPL_LSBWORD16( -2 ); /* datum unknown */
     memcpy( abyHeader + 26, &nShortTemp, 2 );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Set dummy extents.                                              */
 /* -------------------------------------------------------------------- */
@@ -899,7 +894,7 @@ GDALDataset *BTDataset::Create( const char * pszFilename,
     CPL_LSBPTR64( abyHeader + 36 );
     CPL_LSBPTR64( abyHeader + 44 );
     CPL_LSBPTR64( abyHeader + 52 );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Set dummy scale.                                                */
 /* -------------------------------------------------------------------- */
@@ -907,25 +902,32 @@ GDALDataset *BTDataset::Create( const char * pszFilename,
 
     memcpy( abyHeader + 62, &fScale, 4 );
     CPL_LSBPTR32( abyHeader + 62 );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Write to disk.                                                  */
 /* -------------------------------------------------------------------- */
-    VSIFWriteL( (void *) abyHeader, 256, 1, fp );
-    if( VSIFSeekL( fp, (GDALGetDataTypeSize(eType)/8) * nXSize * (vsi_l_offset)nYSize - 1, 
-                   SEEK_CUR ) != 0 
+    if( VSIFWriteL( (void *) abyHeader, 256, 1, fp ) != 1 ||
+        VSIFSeekL( fp, (GDALGetDataTypeSize(eType)/8) * nXSize * (vsi_l_offset)nYSize - 1,
+                   SEEK_CUR ) != 0
         || VSIFWriteL( abyHeader+255, 1, 1, fp ) != 1 )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   "Failed to extent file to its full size, out of disk space?"
                   );
 
-        VSIFCloseL( fp );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
         VSIUnlink( pszFilename );
         return NULL;
     }
 
-    VSIFCloseL( fp );
+    if( VSIFCloseL( fp ) != 0 )
+    {
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Failed to extent file to its full size, out of disk space?"
+                  );
+        VSIUnlink( pszFilename );
+        return NULL;
+    }
 
     return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
 }
@@ -937,26 +939,24 @@ GDALDataset *BTDataset::Create( const char * pszFilename,
 void GDALRegister_BT()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "BT" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "BT" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "BT" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+    poDriver->SetDescription( "BT" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
                                    "VTP .bt (Binary Terrain) 1.3 Format" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
                                    "frmt_various.html#BT" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "bt" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
-                                   "Int16 Int32 Float32" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "bt" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Int16 Int32 Float32" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = BTDataset::Open;
-        poDriver->pfnCreate = BTDataset::Create;
+    poDriver->pfnOpen = BTDataset::Open;
+    poDriver->pfnCreate = BTDataset::Create;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/raw/cpgdataset.cpp b/frmts/raw/cpgdataset.cpp
index b5d760e..74f4072 100644
--- a/frmts/raw/cpgdataset.cpp
+++ b/frmts/raw/cpgdataset.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: cpgdataset.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: cpgdataset.cpp 33673 2016-03-07 20:40:54Z goatbar $
  *
  * Project:  Polarimetric Workstation
- * Purpose:  Convair PolGASP data (.img/.hdr format). 
+ * Purpose:  Convair PolGASP data (.img/.hdr format).
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -28,16 +28,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "rawdataset.h"
-#include "ogr_spatialref.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "ogr_spatialref.h"
+#include "rawdataset.h"
 
-CPL_CVSID("$Id: cpgdataset.cpp 27942 2014-11-11 00:57:41Z rouault $");
-
-CPL_C_START
-void	GDALRegister_CPG(void);
-CPL_C_END
-
+CPL_CVSID("$Id: cpgdataset.cpp 33673 2016-03-07 20:40:54Z goatbar $");
 
 enum Interleave {BSQ, BIL, BIP};
 
@@ -73,20 +69,22 @@ class CPGDataset : public RawDataset
     static int FindType2( const char *pszWorkname );
     static int FindType3( const char *pszWorkname );
     static GDALDataset *InitializeType1Or2Dataset( const char *pszWorkname );
+#ifdef notdef
     static GDALDataset *InitializeType3Dataset( const char *pszWorkname );
+#endif
   CPLErr LoadStokesLine( int iLine, int bNativeOrder );
 
   public:
 		CPGDataset();
 	        ~CPGDataset();
-    
+
     virtual int    GetGCPCount();
     virtual const char *GetGCPProjection();
     virtual const GDAL_GCP *GetGCPs();
 
     virtual const char *GetProjectionRef(void);
     virtual CPLErr GetGeoTransform( double * );
-    
+
     static GDALDataset *Open( GDALOpenInfo * );
 };
 
@@ -94,12 +92,13 @@ class CPGDataset : public RawDataset
 /*                            CPGDataset()                             */
 /************************************************************************/
 
-CPGDataset::CPGDataset()
+CPGDataset::CPGDataset() :
+    nGCPCount(0),
+    pasGCPList(NULL),
+    nLoadedStokesLine(-1),
+    padfStokesMatrix(NULL),
+    nInterleave(0)
 {
-    int iBand;
-
-    nGCPCount = 0;
-    pasGCPList = NULL;
     pszProjection = CPLStrdup("");
     pszGCPProjection = CPLStrdup("");
     adfGeoTransform[0] = 0.0;
@@ -109,10 +108,7 @@ CPGDataset::CPGDataset()
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
 
-    nLoadedStokesLine = -1;
-    padfStokesMatrix = NULL;
-
-    for( iBand = 0; iBand < 4; iBand++ )
+    for( int iBand = 0; iBand < 4; iBand++ )
         afpImage[iBand] = NULL;
 }
 
@@ -123,11 +119,9 @@ CPGDataset::CPGDataset()
 CPGDataset::~CPGDataset()
 
 {
-    int iBand;
-
     FlushCache();
 
-    for( iBand = 0; iBand < 4; iBand++ )
+    for( int iBand = 0; iBand < 4; iBand++ )
     {
         if( afpImage[iBand] != NULL )
             VSIFClose( afpImage[iBand] );
@@ -141,10 +135,7 @@ CPGDataset::~CPGDataset()
 
     CPLFree( pszProjection );
     CPLFree( pszGCPProjection );
-
-    if (padfStokesMatrix != NULL)
-        CPLFree( padfStokesMatrix );
-
+    CPLFree( padfStokesMatrix );
 }
 
 /************************************************************************/
@@ -163,22 +154,22 @@ class SIRC_QSLCRasterBand : public GDALRasterBand
     virtual CPLErr IReadBlock( int, int, void * );
 };
 
-#define M11 0
-#define M12 1
-#define M13 2
-#define M14 3
-#define M21 4
-#define M22 5
-#define M23 6
-#define M24 7
-#define M31 8
-#define M32 9
-#define M33 10
-#define M34 11
-#define M41 12
-#define M42 13
-#define M43 14
-#define M44 15
+static const int M11 = 0;
+//static const int M12 = 1;
+static const int M13 = 2;
+static const int M14 = 3;
+//static const int M21 = 4;
+static const int M22 = 5;
+static const int M23 = 6;
+static const int M24 = 7;
+static const int M31 = 8;
+static const int M32 = 9;
+static const int M33 = 10;
+static const int M34 = 11;
+static const int M41 = 12;
+static const int M42 = 13;
+static const int M43 = 14;
+static const int M44 = 15;
 
 /************************************************************************/
 /* ==================================================================== */
@@ -197,7 +188,7 @@ class CPG_STOKESRasterBand : public GDALRasterBand
                    CPG_STOKESRasterBand( GDALDataset *poDS, int nBand,
                                          GDALDataType eType,
                                          int bNativeOrder );
-    virtual ~CPG_STOKESRasterBand();
+    virtual ~CPG_STOKESRasterBand() {};
 
     virtual CPLErr IReadBlock( int, int, void * );
 };
@@ -206,19 +197,17 @@ class CPG_STOKESRasterBand : public GDALRasterBand
 /*                           AdjustFilename()                           */
 /*                                                                      */
 /*      Try to find the file with the request polarization and          */
-/*      extention and update the passed filename accordingly.           */
+/*      extension and update the passed filename accordingly.           */
 /*                                                                      */
 /*      Return TRUE if file found otherwise FALSE.                      */
 /************************************************************************/
 
-int CPGDataset::AdjustFilename( char **pszFilename, 
+int CPGDataset::AdjustFilename( char **pszFilename,
                                 const char *pszPolarization,
                                 const char *pszExtension )
 
 {
-    VSIStatBuf  sStatBuf;
     const char *pszNewName;
-    char *subptr;
 
     /* eventually we should handle upper/lower case ... */
 
@@ -230,8 +219,8 @@ int CPGDataset::AdjustFilename( char **pszFilename,
         *pszFilename = CPLStrdup(pszNewName);
     }
     else if (strlen(pszPolarization) == 2)
-    { 
-        subptr = strstr(*pszFilename,"hh");
+    {
+        char *subptr = strstr(*pszFilename,"hh");
         if (subptr == NULL)
             subptr = strstr(*pszFilename,"hv");
         if (subptr == NULL)
@@ -246,7 +235,6 @@ int CPGDataset::AdjustFilename( char **pszFilename,
                                                 (const char *) pszExtension);
         CPLFree(*pszFilename);
         *pszFilename = CPLStrdup(pszNewName);
-    
     }
     else
     {
@@ -255,6 +243,7 @@ int CPGDataset::AdjustFilename( char **pszFilename,
         CPLFree(*pszFilename);
         *pszFilename = CPLStrdup(pszNewName);
     }
+    VSIStatBuf sStatBuf;
     return VSIStat( *pszFilename, &sStatBuf ) == 0;
 }
 
@@ -264,11 +253,9 @@ int CPGDataset::AdjustFilename( char **pszFilename,
 /************************************************************************/
 int CPGDataset::FindType1( const char *pszFilename )
 {
-  int nNameLen;
+  const int nNameLen = static_cast<int>(strlen(pszFilename));
 
-  nNameLen = strlen(pszFilename);
-
-  if ((strstr(pszFilename,"sso") == NULL) && 
+  if ((strstr(pszFilename,"sso") == NULL) &&
       (strstr(pszFilename,"polgasp") == NULL))
       return FALSE;
 
@@ -280,28 +267,23 @@ int CPGDataset::FindType1( const char *pszFilename )
   /* Expect all bands and headers to be present */
   char* pszTemp = CPLStrdup(pszFilename);
 
-  int bNotFound = !AdjustFilename( &pszTemp, "hh", "img" ) 
-    || !AdjustFilename( &pszTemp, "hh", "hdr" ) 
-    || !AdjustFilename( &pszTemp, "hv", "img" ) 
-    || !AdjustFilename( &pszTemp, "hv", "hdr" ) 
-    || !AdjustFilename( &pszTemp, "vh", "img" ) 
-    || !AdjustFilename( &pszTemp, "vh", "hdr" ) 
-    || !AdjustFilename( &pszTemp, "vv", "img" ) 
-    || !AdjustFilename( &pszTemp, "vv", "hdr" );
+  const bool bNotFound = !AdjustFilename( &pszTemp, "hh", "img" )
+      || !AdjustFilename( &pszTemp, "hh", "hdr" )
+      || !AdjustFilename( &pszTemp, "hv", "img" )
+      || !AdjustFilename( &pszTemp, "hv", "hdr" )
+      || !AdjustFilename( &pszTemp, "vh", "img" )
+      || !AdjustFilename( &pszTemp, "vh", "hdr" )
+      || !AdjustFilename( &pszTemp, "vv", "img" )
+      || !AdjustFilename( &pszTemp, "vv", "hdr" );
 
   CPLFree(pszTemp);
 
-  if (bNotFound)
-      return FALSE;
-
-  return TRUE;
+  return !bNotFound;
 }
 
 int CPGDataset::FindType2( const char *pszFilename )
 {
-  int nNameLen;
-
-  nNameLen = strlen( pszFilename );
+  const int nNameLen = static_cast<int>(strlen( pszFilename ));
 
   if (( strlen(pszFilename) < 9) ||
       (!EQUAL(pszFilename+nNameLen-8,"SIRC.hdr")
@@ -309,23 +291,18 @@ int CPGDataset::FindType2( const char *pszFilename )
       return FALSE;
 
   char* pszTemp = CPLStrdup(pszFilename);
-  int bNotFound =  !AdjustFilename( &pszTemp, "", "img" ) 
-                || !AdjustFilename( &pszTemp, "", "hdr" );
+  const bool bNotFound = !AdjustFilename( &pszTemp, "", "img" )
+      || !AdjustFilename( &pszTemp, "", "hdr" );
   CPLFree(pszTemp);
 
-  if (bNotFound)
-      return FALSE;
-
-  return TRUE;
+  return !bNotFound;
 }
 
 int CPGDataset::FindType3( const char *pszFilename )
 {
-  int nNameLen;
-
-  nNameLen = strlen( pszFilename );
+  const int nNameLen = static_cast<int>(strlen( pszFilename ));
 
-  if ((strstr(pszFilename,"sso") == NULL) && 
+  if ((strstr(pszFilename,"sso") == NULL) &&
       (strstr(pszFilename,"polgasp") == NULL))
       return FALSE;
 
@@ -335,14 +312,11 @@ int CPGDataset::FindType3( const char *pszFilename )
       return FALSE;
 
   char* pszTemp = CPLStrdup(pszFilename);
-  int bNotFound =  !AdjustFilename( &pszTemp, "stokes", "img" ) 
-                || !AdjustFilename( &pszTemp, "stokes", "img_def" );
+  const bool bNotFound = !AdjustFilename( &pszTemp, "stokes", "img" )
+      || !AdjustFilename( &pszTemp, "stokes", "img_def" );
   CPLFree(pszTemp);
 
-  if (bNotFound)
-      return FALSE;
-
-  return TRUE;
+  return !bNotFound;
 }
 
 /************************************************************************/
@@ -352,18 +326,18 @@ int CPGDataset::FindType3( const char *pszFilename )
 CPLErr CPGDataset::LoadStokesLine( int iLine, int bNativeOrder )
 
 {
-    int offset, nBytesToRead, band_index;
-    int	nDataSize = GDALGetDataTypeSize(GDT_Float32)/8;
-
     if( iLine == nLoadedStokesLine )
         return CE_None;
 
+    const int nDataSize = GDALGetDataTypeSize(GDT_Float32) / 8;
+
 /* -------------------------------------------------------------------- */
 /*      allocate working buffers if we don't have them already.         */
 /* -------------------------------------------------------------------- */
     if( padfStokesMatrix == NULL )
     {
-        padfStokesMatrix = (float *) CPLMalloc(sizeof(float) * nRasterXSize*16);
+        padfStokesMatrix = reinterpret_cast<float *>(
+            CPLMalloc( sizeof(float) * nRasterXSize * 16 ) );
     }
 
 /* -------------------------------------------------------------------- */
@@ -372,15 +346,16 @@ CPLErr CPGDataset::LoadStokesLine( int iLine, int bNativeOrder )
 /* -------------------------------------------------------------------- */
     if ( nInterleave == BIP )
     {
-        offset = nRasterXSize*iLine*nDataSize*16;
-        nBytesToRead = nDataSize*nRasterXSize*16;
-        if (( VSIFSeek( afpImage[0], offset, SEEK_SET ) != 0 ) || 
-           (int) VSIFRead( ( GByte *) padfStokesMatrix, 1, nBytesToRead, 
-                           afpImage[0] ) != nBytesToRead )
+        const int offset = nRasterXSize * iLine * nDataSize * 16;
+        const int nBytesToRead = nDataSize * nRasterXSize*16;
+        if (( VSIFSeek( afpImage[0], offset, SEEK_SET ) != 0 ) ||
+            static_cast<int>( VSIFRead(
+                reinterpret_cast<GByte *>( padfStokesMatrix ),
+                1, nBytesToRead, afpImage[0] ) ) != nBytesToRead )
         {
-            CPLError( CE_Failure, CPLE_FileIO, 
+            CPLError( CE_Failure, CPLE_FileIO,
                   "Error reading %d bytes of Stokes Convair at offset %d.\n"
-                  "Reading file %s failed.", 
+                  "Reading file %s failed.",
                   nBytesToRead, offset, GetDescription() );
             CPLFree( padfStokesMatrix );
             padfStokesMatrix = NULL;
@@ -390,20 +365,20 @@ CPLErr CPGDataset::LoadStokesLine( int iLine, int bNativeOrder )
     }
     else if ( nInterleave == BIL )
     {
-        for ( band_index = 0; band_index < 16; band_index++)
-        { 
-            offset = nDataSize * (nRasterXSize*iLine +
-                    nRasterXSize*band_index);
-            nBytesToRead = nDataSize*nRasterXSize;
-            if (( VSIFSeek( afpImage[0], offset, SEEK_SET ) != 0 ) || 
-               (int) VSIFRead( 
-                ( GByte *) padfStokesMatrix + nBytesToRead*band_index, 
-                               1, nBytesToRead, 
-                  afpImage[0] ) != nBytesToRead )
+        for ( int band_index = 0; band_index < 16; band_index++)
+        {
+            const int offset = nDataSize * (nRasterXSize * iLine +
+                                            nRasterXSize*band_index);
+            const int nBytesToRead = nDataSize * nRasterXSize;
+            if (( VSIFSeek( afpImage[0], offset, SEEK_SET ) != 0 ) ||
+               static_cast<int>( VSIFRead(
+                   reinterpret_cast<GByte *>(
+                       padfStokesMatrix + nBytesToRead*band_index ),
+                   1, nBytesToRead, afpImage[0] ) ) != nBytesToRead )
             {
-                CPLError( CE_Failure, CPLE_FileIO, 
+                CPLError( CE_Failure, CPLE_FileIO,
                   "Error reading %d bytes of Stokes Convair at offset %d.\n"
-                  "Reading file %s failed.", 
+                  "Reading file %s failed.",
                   nBytesToRead, offset, GetDescription() );
                 CPLFree( padfStokesMatrix );
                 padfStokesMatrix = NULL;
@@ -415,20 +390,21 @@ CPLErr CPGDataset::LoadStokesLine( int iLine, int bNativeOrder )
     }
     else
     {
-        for ( band_index = 0; band_index < 16; band_index++)
-        { 
-            offset = nDataSize * (nRasterXSize*iLine +
-                    nRasterXSize*nRasterYSize*band_index);
-            nBytesToRead = nDataSize*nRasterXSize;
-            if (( VSIFSeek( afpImage[0], offset, SEEK_SET ) != 0 ) || 
-               (int) VSIFRead( 
-                   ( GByte *) padfStokesMatrix + nBytesToRead*band_index, 
-                              1, nBytesToRead, 
-                     afpImage[0] ) != nBytesToRead )
+        for ( int band_index = 0; band_index < 16; band_index++)
+        {
+            const int offset =
+                nDataSize * ( nRasterXSize * iLine +
+                              nRasterXSize * nRasterYSize * band_index );
+            const int nBytesToRead = nDataSize * nRasterXSize;
+            if (( VSIFSeek( afpImage[0], offset, SEEK_SET ) != 0 ) ||
+               static_cast<int>( VSIFRead(
+                   reinterpret_cast<GByte *>(
+                       padfStokesMatrix + nBytesToRead * band_index ),
+                   1, nBytesToRead, afpImage[0] ) ) != nBytesToRead )
             {
-                CPLError( CE_Failure, CPLE_FileIO, 
+                CPLError( CE_Failure, CPLE_FileIO,
                   "Error reading %d bytes of Stokes Convair at offset %d.\n"
-                  "Reading file %s failed.", 
+                  "Reading file %s failed.",
                   nBytesToRead, offset, GetDescription() );
                 CPLFree( padfStokesMatrix );
                 padfStokesMatrix = NULL;
@@ -460,11 +436,9 @@ GDALDataset* CPGDataset::InitializeType1Or2Dataset( const char *pszFilename )
 /*      Read the .hdr file (the hh one for the .sso and polgasp cases)  */
 /*      and parse it.                                                   */
 /* -------------------------------------------------------------------- */
-    char **papszHdrLines;
-    int iLine;
-    int nLines = 0, nSamples = 0;
+    int nLines = 0;
+    int nSamples = 0;
     int nError = 0;
-    int nNameLen = 0;
 
     /* Parameters required for pseudo-geocoding.  GCPs map */
     /* slant range to ground range at 16 points.           */
@@ -478,9 +452,9 @@ GDALDataset* CPGDataset::InitializeType1Or2Dataset( const char *pszFilename )
 
     char* pszWorkname = CPLStrdup(pszFilename);
     AdjustFilename( &pszWorkname, "hh", "hdr" );
-    papszHdrLines = CSLLoad( pszWorkname );
+    char **papszHdrLines = CSLLoad( pszWorkname );
 
-    for( iLine = 0; papszHdrLines && papszHdrLines[iLine] != NULL; iLine++ )
+    for( int iLine = 0; papszHdrLines && papszHdrLines[iLine] != NULL; iLine++ )
     {
         char **papszTokens = CSLTokenizeString( papszHdrLines[iLine] );
 
@@ -505,7 +479,7 @@ GDALDataset* CPGDataset::InitializeType1Or2Dataset( const char *pszFilename )
         {
             dfeast = CPLAtof(papszTokens[2]);
             iUTMParamsFound++;
-        }  
+        }
         else if ( ( CSLCount( papszTokens ) >= 5 ) &&
                EQUAL(papszTokens[0],"reference") &&
                EQUAL(papszTokens[1],"projection") &&
@@ -514,33 +488,33 @@ GDALDataset* CPGDataset::InitializeType1Or2Dataset( const char *pszFilename )
         {
             iUTMZone = atoi(papszTokens[4]);
             iUTMParamsFound++;
-        } 
+        }
         else if ( ( CSLCount( papszTokens ) >= 3 ) &&
                EQUAL(papszTokens[0],"reference") &&
                EQUAL(papszTokens[1],"corner") &&
-               EQUALN(papszTokens[2],"Upper_Left",10) )
+               STARTS_WITH_CI(papszTokens[2], "Upper_Left") )
         {
             /* iCorner = 0; */
             iUTMParamsFound++;
-        }  
+        }
         else if( EQUAL(papszTokens[0],"number_lines") )
             nLines = atoi(papszTokens[1]);
-        
+
         else if( EQUAL(papszTokens[0],"number_samples") )
             nSamples = atoi(papszTokens[1]);
 
-        else if( (EQUAL(papszTokens[0],"header_offset") 
-                  && atoi(papszTokens[1]) != 0) 
-                 || (EQUAL(papszTokens[0],"number_channels") 
+        else if( (EQUAL(papszTokens[0],"header_offset")
+                  && atoi(papszTokens[1]) != 0)
+                 || (EQUAL(papszTokens[0],"number_channels")
                      && (atoi(papszTokens[1]) != 1)
-                     && (atoi(papszTokens[1]) != 10)) 
-                 || (EQUAL(papszTokens[0],"datatype") 
-                     && atoi(papszTokens[1]) != 1) 
-                 || (EQUAL(papszTokens[0],"number_format") 
+                     && (atoi(papszTokens[1]) != 10))
+                 || (EQUAL(papszTokens[0],"datatype")
+                     && atoi(papszTokens[1]) != 1)
+                 || (EQUAL(papszTokens[0],"number_format")
                      && !EQUAL(papszTokens[1],"float32")
                      && !EQUAL(papszTokens[1],"int8")))
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
        "Keyword %s has value %s which does not match CPG driver expectation.",
                       papszTokens[0], papszTokens[1] );
             nError = 1;
@@ -575,8 +549,6 @@ GDALDataset* CPGDataset::InitializeType1Or2Dataset( const char *pszFilename )
             iUTMParamsFound++;
         }
 
-
-
         CSLDestroy( papszTokens );
     }
     CSLDestroy( papszHdrLines );
@@ -591,7 +563,7 @@ GDALDataset* CPGDataset::InitializeType1Or2Dataset( const char *pszFilename )
 
     if( nLines <= 0 || nSamples <= 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
           "Did not find valid number_lines or number_samples keywords in %s.",
                   pszWorkname );
         CPLFree(pszWorkname);
@@ -601,10 +573,7 @@ GDALDataset* CPGDataset::InitializeType1Or2Dataset( const char *pszFilename )
 /* -------------------------------------------------------------------- */
 /*      Initialize dataset.                                             */
 /* -------------------------------------------------------------------- */
-    int iBand=0;
-    CPGDataset     *poDS;
-
-    poDS = new CPGDataset();
+    CPGDataset *poDS = new CPGDataset();
 
     poDS->nRasterXSize = nSamples;
     poDS->nRasterYSize = nLines;
@@ -612,9 +581,9 @@ GDALDataset* CPGDataset::InitializeType1Or2Dataset( const char *pszFilename )
 /* -------------------------------------------------------------------- */
 /*      Open the four bands.                                            */
 /* -------------------------------------------------------------------- */
-    static const char *apszPolarizations[4] = { "hh", "hv", "vv", "vh" };
+    static const char * const apszPolarizations[4] = { "hh", "hv", "vv", "vh" };
 
-    nNameLen = strlen(pszWorkname);
+    const int nNameLen = static_cast<int>(strlen(pszWorkname));
 
     if ( EQUAL(pszWorkname+nNameLen-7,"IRC.hdr") ||
          EQUAL(pszWorkname+nNameLen-7,"IRC.img") )
@@ -624,49 +593,47 @@ GDALDataset* CPGDataset::InitializeType1Or2Dataset( const char *pszFilename )
         poDS->afpImage[0] = VSIFOpen( pszWorkname, "rb" );
         if( poDS->afpImage[0] == NULL )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
-                      "Failed to open .img file: %s", 
+            CPLError( CE_Failure, CPLE_OpenFailed,
+                      "Failed to open .img file: %s",
                       pszWorkname );
             CPLFree(pszWorkname);
             delete poDS;
             return NULL;
         }
-        for( iBand = 0; iBand < 4; iBand++ )
+        for( int iBand = 0; iBand < 4; iBand++ )
         {
             SIRC_QSLCRasterBand	*poBand;
 
             poBand = new SIRC_QSLCRasterBand( poDS, iBand+1, GDT_CFloat32 );
             poDS->SetBand( iBand+1, poBand );
-            poBand->SetMetadataItem( "POLARIMETRIC_INTERP", 
+            poBand->SetMetadataItem( "POLARIMETRIC_INTERP",
                                  apszPolarizations[iBand] );
         }
     }
     else
     {
-        for( iBand = 0; iBand < 4; iBand++ )
+        for( int iBand = 0; iBand < 4; iBand++ )
         {
-            RawRasterBand	*poBand;
-        
             AdjustFilename( &pszWorkname, apszPolarizations[iBand], "img" );
-          
+
             poDS->afpImage[iBand] = VSIFOpen( pszWorkname, "rb" );
             if( poDS->afpImage[iBand] == NULL )
             {
-                CPLError( CE_Failure, CPLE_OpenFailed, 
-                          "Failed to open .img file: %s", 
+                CPLError( CE_Failure, CPLE_OpenFailed,
+                          "Failed to open .img file: %s",
                           pszWorkname );
                 CPLFree(pszWorkname);
                 delete poDS;
                 return NULL;
             }
 
-            poBand = 
-                new RawRasterBand( poDS, iBand+1, poDS->afpImage[iBand], 
-                                   0, 8, 8*nSamples, 
-                                   GDT_CFloat32, !CPL_IS_LSB, FALSE );
+            RawRasterBand *poBand
+                = new RawRasterBand( poDS, iBand+1, poDS->afpImage[iBand],
+                                     0, 8, 8*nSamples,
+                                     GDT_CFloat32, !CPL_IS_LSB, FALSE );
             poDS->SetBand( iBand+1, poBand );
 
-            poBand->SetMetadataItem( "POLARIMETRIC_INTERP", 
+            poBand->SetMetadataItem( "POLARIMETRIC_INTERP",
                                  apszPolarizations[iBand] );
         }
     }
@@ -681,18 +648,17 @@ GDALDataset* CPGDataset::InitializeType1Or2Dataset( const char *pszFilename )
 /* ------------------------------------------------------------------------- */
     if (iUTMParamsFound == 7)
     {
-        OGRSpatialReference oUTM;
-        double dfnorth_center;
-
         poDS->adfGeoTransform[1] = 0.0;
         poDS->adfGeoTransform[2] = 0.0;
         poDS->adfGeoTransform[4] = 0.0;
         poDS->adfGeoTransform[5] = 0.0;
- 
+
+        double dfnorth_center;
         if (itransposed == 1)
         {
-            printf("Warning- did not have a convair SIRC-style test dataset\n"
-                 "with transposed=1 for testing.  Georefencing may be wrong.\n");
+            printf( "Warning: did not have a convair SIRC-style test dataset\n"
+                    "with transposed=1 for testing.  Georeferencing may be "
+                    "wrong.\n" );
             dfnorth_center = dfnorth - nSamples*dfsample_size/2.0;
             poDS->adfGeoTransform[0] = dfeast;
             poDS->adfGeoTransform[2] = dfsample_size_az;
@@ -707,6 +673,8 @@ GDALDataset* CPGDataset::InitializeType1Or2Dataset( const char *pszFilename )
             poDS->adfGeoTransform[3] = dfnorth;
             poDS->adfGeoTransform[5] = -1*dfsample_size;
         }
+
+        OGRSpatialReference oUTM;
         if (dfnorth_center < 0)
             oUTM.SetUTM(iUTMZone, 0);
         else
@@ -717,24 +685,21 @@ GDALDataset* CPGDataset::InitializeType1Or2Dataset( const char *pszFilename )
         CPLFree( poDS->pszProjection );
         poDS->pszProjection = NULL;
         oUTM.exportToWkt( &(poDS->pszProjection) );
-
-
-
     }
     else if (iGeoParamsFound == 5)
     {
-        int ngcp;
         double dfgcpLine, dfgcpPixel, dfgcpX, dfgcpY, dftemp;
 
         poDS->nGCPCount = 16;
-        poDS->pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),poDS->nGCPCount);
+        poDS->pasGCPList = reinterpret_cast<GDAL_GCP *>(
+            CPLCalloc( sizeof(GDAL_GCP), poDS->nGCPCount ) );
         GDALInitGCPs(poDS->nGCPCount, poDS->pasGCPList);
 
-        for( ngcp = 0; ngcp < 16; ngcp ++ )
+        for( int ngcp = 0; ngcp < 16; ngcp ++ )
         {
             char szID[32];
 
-            sprintf(szID,"%d",ngcp+1);
+            snprintf( szID, sizeof(szID), "%d",ngcp+1);
             if (itransposed == 1)
             {
                 if (ngcp < 4)
@@ -785,7 +750,9 @@ GDALDataset* CPGDataset::InitializeType1Or2Dataset( const char *pszFilename )
         }
 
         CPLFree(poDS->pszGCPProjection);
-        poDS->pszGCPProjection = CPLStrdup("LOCAL_CS[\"Ground range view / unreferenced meters\",UNIT[\"Meter\",1.0]]"); 
+        poDS->pszGCPProjection = CPLStrdup(
+            "LOCAL_CS[\"Ground range view / unreferenced meters\","
+            "UNIT[\"Meter\",1.0]]");
 
     }
 
@@ -794,11 +761,10 @@ GDALDataset* CPGDataset::InitializeType1Or2Dataset( const char *pszFilename )
     return poDS;
 }
 
+#ifdef notdef
 GDALDataset *CPGDataset::InitializeType3Dataset( const char *pszFilename )
 {
-
-    char **papszHdrLines;
-    int iLine, iBytesPerPixel = 0, iInterleave=-1;
+    int iBytesPerPixel = 0, iInterleave=-1;
     int nLines = 0, nSamples = 0, nBands = 0;
     int nError = 0;
 
@@ -809,13 +775,13 @@ GDALDataset *CPGDataset::InitializeType3Dataset( const char *pszFilename )
 
     char* pszWorkname = CPLStrdup(pszFilename);
     AdjustFilename( &pszWorkname, "stokes", "img_def" );
-    papszHdrLines = CSLLoad( pszWorkname );
+    char **papszHdrLines = CSLLoad( pszWorkname );
 
-    for( iLine = 0; papszHdrLines && papszHdrLines[iLine] != NULL; iLine++ )
+    for( int iLine = 0; papszHdrLines && papszHdrLines[iLine] != NULL; iLine++ )
     {
-      char **papszTokens = CSLTokenizeString2( papszHdrLines[iLine],
-                                               " \t", 
-                             CSLT_HONOURSTRINGS & CSLT_ALLOWEMPTYTOKENS );
+        char **papszTokens
+            = CSLTokenizeString2( papszHdrLines[iLine], " \t",
+                                  CSLT_HONOURSTRINGS & CSLT_ALLOWEMPTYTOKENS );
 
         /* Note: some cv580 file seem to have comments with #, hence the >=
          * instead of = for token checking, and the equalN for the corner.
@@ -826,51 +792,50 @@ GDALDataset *CPGDataset::InitializeType3Dataset( const char *pszFilename )
                EQUAL(papszTokens[1],"organization:"))
         {
 
-            if( EQUALN(papszTokens[2], "BSQ", 3) )
+            if( STARTS_WITH_CI(papszTokens[2], "BSQ") )
                 iInterleave = BSQ;
-            else if( EQUALN(papszTokens[2], "BIL", 3) )
+            else if( STARTS_WITH_CI(papszTokens[2], "BIL") )
                 iInterleave = BIL;
-            else if( EQUALN(papszTokens[2], "BIP", 3) )
+            else if( STARTS_WITH_CI(papszTokens[2], "BIP") )
                 iInterleave = BIP;
             else
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                   "The interleaving type of the file (%s) is not supported.",
                   papszTokens[2] );
                 nError = 1;
-            } 
-              
-        } 
+            }
+        }
         else if ( ( CSLCount( papszTokens ) >= 3 ) &&
                EQUAL(papszTokens[0],"data") &&
                EQUAL(papszTokens[1],"state:") )
         {
 
-            if( !EQUALN(papszTokens[2], "RAW", 3) &&
-                !EQUALN(papszTokens[2], "GEO", 3) )
+            if( !STARTS_WITH_CI(papszTokens[2], "RAW") &&
+                !STARTS_WITH_CI(papszTokens[2], "GEO") )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                  "The data state of the file (%s) is not supported.\n.  Only RAW and GEO are currently recognized.",
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "The data state of the file (%s) is not "
+                          "supported.\n.  Only RAW and GEO are currently "
+                          "recognized.",
                   papszTokens[2] );
                 nError = 1;
-            }   
-
-
-        }  
+            }
+        }
         else if ( ( CSLCount( papszTokens ) >= 4 ) &&
                EQUAL(papszTokens[0],"data") &&
                EQUAL(papszTokens[1],"origin") &&
                EQUAL(papszTokens[2],"point:")  )
         {
-          if (!EQUALN(papszTokens[3], "Upper_Left", 10))
+          if (!STARTS_WITH_CI(papszTokens[3], "Upper_Left"))
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
             "Unexpected value (%s) for data origin point- expect Upper_Left.",
                   papszTokens[3] );
                 nError = 1;
-            } 
-            iUTMParamsFound++;  
-        } 
+            }
+            iUTMParamsFound++;
+        }
         else if ( ( CSLCount( papszTokens ) >= 5 ) &&
                EQUAL(papszTokens[0],"map") &&
                EQUAL(papszTokens[1],"projection:") &&
@@ -879,7 +844,7 @@ GDALDataset *CPGDataset::InitializeType3Dataset( const char *pszFilename )
         {
             iUTMZone = atoi(papszTokens[4]);
             iUTMParamsFound++;
-        } 
+        }
         else if ( ( CSLCount( papszTokens ) >= 4 ) &&
                  EQUAL(papszTokens[0],"project") &&
                  EQUAL(papszTokens[1],"origin:") )
@@ -895,7 +860,7 @@ GDALDataset *CPGDataset::InitializeType3Dataset( const char *pszFilename )
             dfOffsetX =  CPLAtof(papszTokens[2]);
             dfOffsetY = CPLAtof(papszTokens[3]);
             iUTMParamsFound+=2;
-        }  
+        }
         else if ( ( CSLCount( papszTokens ) >= 6 ) &&
                EQUAL(papszTokens[0],"pixel") &&
                EQUAL(papszTokens[1],"size") &&
@@ -905,22 +870,21 @@ GDALDataset *CPGDataset::InitializeType3Dataset( const char *pszFilename )
             dfxsize = CPLAtof(papszTokens[4]);
             dfysize = CPLAtof(papszTokens[5]);
             iUTMParamsFound+=2;
- 
-        }   
+        }
         else if ( ( CSLCount( papszTokens ) >= 4 ) &&
                EQUAL(papszTokens[0],"number") &&
                EQUAL(papszTokens[1],"of") &&
                EQUAL(papszTokens[2],"pixels:"))
         {
             nSamples = atoi(papszTokens[3]);
-        }     
+        }
         else if ( ( CSLCount( papszTokens ) >= 4 ) &&
                EQUAL(papszTokens[0],"number") &&
                EQUAL(papszTokens[1],"of") &&
                EQUAL(papszTokens[2],"lines:"))
         {
-            nLines = atoi(papszTokens[3]); 
-        }     
+            nLines = atoi(papszTokens[3]);
+        }
         else if ( ( CSLCount( papszTokens ) >= 4 ) &&
                EQUAL(papszTokens[0],"number") &&
                EQUAL(papszTokens[1],"of") &&
@@ -929,12 +893,13 @@ GDALDataset *CPGDataset::InitializeType3Dataset( const char *pszFilename )
             nBands = atoi(papszTokens[3]);
             if ( nBands != 16)
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
-               "Number of bands has a value %s which does not match CPG driver\nexpectation (expect a value of 16).",
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Number of bands has a value %s which does not match "
+                          "CPG driver\nexpectation (expect a value of 16).",
                       papszTokens[3] );
                 nError = 1;
             }
-        }     
+        }
         else if ( ( CSLCount( papszTokens ) >= 4 ) &&
                EQUAL(papszTokens[0],"bytes") &&
                EQUAL(papszTokens[1],"per") &&
@@ -943,12 +908,13 @@ GDALDataset *CPGDataset::InitializeType3Dataset( const char *pszFilename )
             iBytesPerPixel = atoi(papszTokens[3]);
             if (iBytesPerPixel != 4)
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
-               "Bytes per pixel has a value %s which does not match CPG driver\nexpectation (expect a value of 4).",
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Bytes per pixel has a value %s which does not match "
+                          "CPG driver\nexpectation (expect a value of 4).",
                       papszTokens[1] );
                 nError = 1;
             }
-        }  
+        }
         CSLDestroy( papszTokens );
     }
 
@@ -967,8 +933,10 @@ GDALDataset *CPGDataset::InitializeType3Dataset( const char *pszFilename )
         !GDALCheckBandCount(nBands, FALSE) || iInterleave == -1 ||
         iBytesPerPixel == 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-          "%s is missing a required parameter (number of pixels, number of lines,\nnumber of bands, bytes per pixel, or data organization).",
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "%s is missing a required parameter (number of pixels, "
+                  "number of lines,\nnumber of bands, bytes per pixel, or "
+                  "data organization).",
                   pszWorkname );
         CPLFree(pszWorkname);
         return NULL;
@@ -977,14 +945,11 @@ GDALDataset *CPGDataset::InitializeType3Dataset( const char *pszFilename )
 /* -------------------------------------------------------------------- */
 /*      Initialize dataset.                                             */
 /* -------------------------------------------------------------------- */
-    int iBand=0;
-    CPGDataset     *poDS;
-
-    poDS = new CPGDataset();
+    CPGDataset *poDS = new CPGDataset();
 
     poDS->nRasterXSize = nSamples;
     poDS->nRasterYSize = nLines;
-   
+
     if( iInterleave == BSQ )
         poDS->nInterleave = BSQ;
     else if( iInterleave == BIL )
@@ -1000,19 +965,18 @@ GDALDataset *CPGDataset::InitializeType3Dataset( const char *pszFilename )
     poDS->afpImage[0] = VSIFOpen( pszWorkname, "rb" );
     if( poDS->afpImage[0] == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Failed to open .img file: %s", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to open .img file: %s",
                   pszWorkname );
         CPLFree(pszWorkname);
         delete poDS;
         return NULL;
     }
-    for( iBand = 0; iBand < 16; iBand++ )
+    for( int iBand = 0; iBand < 16; iBand++ )
     {
-        CPG_STOKESRasterBand	*poBand;
-
-        poBand = new CPG_STOKESRasterBand( poDS, iBand+1, GDT_CFloat32,
-                                           !CPL_IS_LSB );
+        CPG_STOKESRasterBand *poBand
+            = new CPG_STOKESRasterBand( poDS, iBand+1, GDT_CFloat32,
+                                        !CPL_IS_LSB );
         poDS->SetBand( iBand+1, poBand );
     }
 
@@ -1020,21 +984,15 @@ GDALDataset *CPGDataset::InitializeType3Dataset( const char *pszFilename )
 /*      Set appropriate MATRIX_REPRESENTATION.                          */
 /* -------------------------------------------------------------------- */
     if ( poDS->GetRasterCount() == 6 ) {
-        poDS->SetMetadataItem( "MATRIX_REPRESENTATION", 
-            "COVARIANCE" );
+        poDS->SetMetadataItem( "MATRIX_REPRESENTATION", "COVARIANCE" );
     }
 
-
 /* ------------------------------------------------------------------------- */
 /*  Add georeferencing, if enough information found.                         */
 /* ------------------------------------------------------------------------- */
     if (iUTMParamsFound == 8)
     {
-        OGRSpatialReference oUTM;
-        double dfnorth_center;
-
- 
-        dfnorth_center = dfnorth - nLines*dfysize/2.0;
+        double dfnorth_center = dfnorth - nLines*dfysize/2.0;
         poDS->adfGeoTransform[0] = dfeast + dfOffsetX;
         poDS->adfGeoTransform[1] = dfxsize;
         poDS->adfGeoTransform[2] = 0.0;
@@ -1042,6 +1000,7 @@ GDALDataset *CPGDataset::InitializeType3Dataset( const char *pszFilename )
         poDS->adfGeoTransform[4] = 0.0;
         poDS->adfGeoTransform[5] = -1*dfysize;
 
+        OGRSpatialReference oUTM;
         if (dfnorth_center < 0)
             oUTM.SetUTM(iUTMZone, 0);
         else
@@ -1056,6 +1015,7 @@ GDALDataset *CPGDataset::InitializeType3Dataset( const char *pszFilename )
 
     return poDS;
 }
+#endif
 
 /************************************************************************/
 /*                                Open()                                */
@@ -1078,14 +1038,12 @@ GDALDataset *CPGDataset::Open( GDALOpenInfo * poOpenInfo )
 /*                  where <stuff> should contain the                    */
 /*                  substring "sso" or "polgasp"                        */
 /* -------------------------------------------------------------------- */
-    int nNameLen = strlen(poOpenInfo->pszFilename);
     int CPGType = 0;
-
     if ( FindType1( poOpenInfo->pszFilename ))
       CPGType = 1;
     else if ( FindType2( poOpenInfo->pszFilename ))
       CPGType = 2;
-   
+
     /* Stokes matrix convair data: not quite working yet- something
      * is wrong in the interpretation of the matrix elements in terms
      * of hh, hv, vv, vh.  Data will load if the next two lines are
@@ -1100,56 +1058,63 @@ GDALDataset *CPGDataset::Open( GDALOpenInfo * poOpenInfo )
 
     if ( CPGType == 0 )
     {
-      nNameLen = strlen(poOpenInfo->pszFilename);
-      if ( (nNameLen > 8) && 
+      int nNameLen = static_cast<int>(strlen(poOpenInfo->pszFilename));
+      if ( (nNameLen > 8) &&
            ( ( strstr(poOpenInfo->pszFilename,"sso") != NULL ) ||
              ( strstr(poOpenInfo->pszFilename,"polgasp") != NULL ) ) &&
            ( EQUAL(poOpenInfo->pszFilename+nNameLen-4,"img") ||
              EQUAL(poOpenInfo->pszFilename+nNameLen-4,"hdr") ||
              EQUAL(poOpenInfo->pszFilename+nNameLen-7,"img_def") ) )
       {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
               "Apparent attempt to open Convair PolGASP data failed as\n"
               "one or more of the required files is missing (eight files\n"
               "are expected for scattering matrix format, two for Stokes)." );
       }
-      else if ( (nNameLen > 8) && 
+      else if ( (nNameLen > 8) &&
                 ( strstr(poOpenInfo->pszFilename,"SIRC") != NULL )  &&
            ( EQUAL(poOpenInfo->pszFilename+nNameLen-4,"img") ||
              EQUAL(poOpenInfo->pszFilename+nNameLen-4,"hdr")))
       {
-          CPLError( CE_Failure, CPLE_OpenFailed, 
+          CPLError( CE_Failure, CPLE_OpenFailed,
                 "Apparent attempt to open SIRC Convair PolGASP data failed \n"
                 "as one of the expected files is missing (hdr or img)!" );
       }
       return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The CPG driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
     }
 
     /* Read the header info and create the dataset */
-    CPGDataset     *poDS;
- 
+    CPGDataset *poDS;
+
+#ifdef notdef
     if ( CPGType < 3 )
-      poDS = (CPGDataset *) InitializeType1Or2Dataset( poOpenInfo->pszFilename );
+#endif
+      poDS = reinterpret_cast<CPGDataset *>(
+          InitializeType1Or2Dataset( poOpenInfo->pszFilename ) );
+#ifdef notdef
     else
-      poDS = (CPGDataset *) InitializeType3Dataset( poOpenInfo->pszFilename );
-
+      poDS = reinterpret_cast<CPGDataset *>(
+          InitializeType3Dataset( poOpenInfo->pszFilename ) );
     if (poDS == NULL)
         return NULL;
+#endif
+
+
 /* -------------------------------------------------------------------- */
 /*      Check for overviews.                                            */
 /* -------------------------------------------------------------------- */
-    // Need to think about this. 
+    // Need to think about this.
     // poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
 /* -------------------------------------------------------------------- */
@@ -1198,7 +1163,7 @@ const GDAL_GCP *CPGDataset::GetGCPs()
 const char *CPGDataset::GetProjectionRef()
 
 {
-    return( pszProjection );
+    return pszProjection;
 }
 
 /************************************************************************/
@@ -1208,7 +1173,7 @@ const char *CPGDataset::GetProjectionRef()
 CPLErr CPGDataset::GetGeoTransform( double * padfTransform )
 
 {
-    memcpy( padfTransform,  adfGeoTransform, sizeof(double) * 6 ); 
+    memcpy( padfTransform,  adfGeoTransform, sizeof(double) * 6 );
     return( CE_None );
 }
 
@@ -1216,16 +1181,16 @@ CPLErr CPGDataset::GetGeoTransform( double * padfTransform )
 /*                           SIRC_QSLCRasterBand()                      */
 /************************************************************************/
 
-SIRC_QSLCRasterBand::SIRC_QSLCRasterBand( CPGDataset *poGDS, int nBand,
+SIRC_QSLCRasterBand::SIRC_QSLCRasterBand( CPGDataset *poGDSIn, int nBandIn,
                                           GDALDataType eType )
 
 {
-    this->poDS = poGDS;
-    this->nBand = nBand;
+    poDS = poGDSIn;
+    nBand = nBandIn;
 
     eDataType = eType;
 
-    nBlockXSize = poGDS->nRasterXSize;
+    nBlockXSize = poGDSIn->nRasterXSize;
     nBlockYSize = 1;
 
     if( nBand == 1 )
@@ -1245,51 +1210,40 @@ SIRC_QSLCRasterBand::SIRC_QSLCRasterBand( CPGDataset *poGDS, int nBand,
 /* From: http://southport.jpl.nasa.gov/software/dcomp/dcomp.html
 
 ysca = sqrt{ [ (Byte(2) / 254 ) + 1.5] 2Byte(1) }
-
 Re(SHH) = byte(3) ysca/127
-
 Im(SHH) = byte(4) ysca/127
-
 Re(SHV) = byte(5) ysca/127
-
 Im(SHV) = byte(6) ysca/127
-
 Re(SVH) = byte(7) ysca/127
-
 Im(SVH) = byte(8) ysca/127
-
 Re(SVV) = byte(9) ysca/127
-
 Im(SVV) = byte(10) ysca/127
-
 */
 
 CPLErr SIRC_QSLCRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                                         int nBlockYOff,
                                         void * pImage )
 {
-    int	   offset, nBytesPerSample=10;
-    GByte  *pabyRecord;
-    CPGDataset *poGDS = (CPGDataset *) poDS;
-    static float afPowTable[256];
-    static int bPowTableInitialized = FALSE;
-
-    offset = nBlockXSize* nBlockYOff*nBytesPerSample;
+    const int nBytesPerSample = 10;
+    CPGDataset *poGDS = reinterpret_cast<CPGDataset *>( poDS );
+    const int offset = nBlockXSize* nBlockYOff*nBytesPerSample;
 
 /* -------------------------------------------------------------------- */
 /*      Load all the pixel data associated with this scanline.          */
 /* -------------------------------------------------------------------- */
-    int	        nBytesToRead = nBytesPerSample * nBlockXSize;
+    const int nBytesToRead = nBytesPerSample * nBlockXSize;
 
-    pabyRecord = (GByte *) CPLMalloc( nBytesToRead );
+    GByte *pabyRecord = reinterpret_cast<GByte *>(
+        CPLMalloc( nBytesToRead ) );
 
-    if( VSIFSeek( poGDS->afpImage[0], offset, SEEK_SET ) != 0 
-        || (int) VSIFRead( pabyRecord, 1, nBytesToRead, 
-                           poGDS->afpImage[0] ) != nBytesToRead )
+    if( VSIFSeek( poGDS->afpImage[0], offset, SEEK_SET ) != 0
+        || static_cast<int>( VSIFRead(
+            pabyRecord, 1, nBytesToRead, poGDS->afpImage[0] ) )
+        != nBytesToRead )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   "Error reading %d bytes of SIRC Convair at offset %d.\n"
-                  "Reading file %s failed.", 
+                  "Reading file %s failed.",
                   nBytesToRead, offset, poGDS->GetDescription() );
         CPLFree( pabyRecord );
         return CE_Failure;
@@ -1298,15 +1252,16 @@ CPLErr SIRC_QSLCRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /* -------------------------------------------------------------------- */
 /*      Initialize our power table if this is our first time through.   */
 /* -------------------------------------------------------------------- */
+    static float afPowTable[256];
+    static bool bPowTableInitialized = false;
+
     if( !bPowTableInitialized )
     {
-        int i;
-
-        bPowTableInitialized = TRUE;
+        bPowTableInitialized = true;
 
-        for( i = 0; i < 256; i++ )
+        for( int i = 0; i < 256; i++ )
         {
-            afPowTable[i] = (float) pow( 2.0, i-128 );
+            afPowTable[i] = static_cast<float>( pow( 2.0, i-128 ) );
         }
     }
 
@@ -1314,48 +1269,49 @@ CPLErr SIRC_QSLCRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /*      Copy the desired band out based on the size of the type, and    */
 /*      the interleaving mode.                                          */
 /* -------------------------------------------------------------------- */
-    int iX;
-
-    for( iX = 0; iX < nBlockXSize; iX++ )
+    for( int iX = 0; iX < nBlockXSize; iX++ )
     {
         unsigned char *pabyGroup = pabyRecord + iX * nBytesPerSample;
-        signed char *Byte = (signed char*)pabyGroup-1; /* A ones based alias */
-        double dfReSHH, dfImSHH, dfReSHV, dfImSHV, 
-            dfReSVH, dfImSVH, dfReSVV, dfImSVV, dfScale;
+        const signed char *Byte = reinterpret_cast<signed char *>(
+            pabyGroup - 1 ); /* A ones based alias */
+
+        /* coverity[tainted_data] */
+        const double dfScale
+            = sqrt( (static_cast<double>(Byte[2]) / 254 + 1.5) * afPowTable[Byte[1] + 128] );
+
+        float *pafImage = reinterpret_cast<float *>( pImage );
 
-        dfScale = sqrt( (Byte[2] / 254 + 1.5) * afPowTable[Byte[1] + 128] );
-        
         if( nBand == 1 )
         {
-            dfReSHH = Byte[3] * dfScale / 127.0;
-            dfImSHH = Byte[4] * dfScale / 127.0;
+            const float fReSHH = static_cast<float>(Byte[3] * dfScale / 127.0);
+            const float fImSHH = static_cast<float>(Byte[4] * dfScale / 127.0);
 
-            ((float *) pImage)[iX*2  ] = (float) dfReSHH;
-            ((float *) pImage)[iX*2+1] = (float) dfImSHH;
-        }        
+            pafImage[iX*2  ] = fReSHH;
+            pafImage[iX*2+1] = fImSHH;
+        }
         else if( nBand == 2 )
         {
-            dfReSHV = Byte[5] * dfScale / 127.0;
-            dfImSHV = Byte[6] * dfScale / 127.0;
+            const float fReSHV = static_cast<float>(Byte[5] * dfScale / 127.0);
+            const float fImSHV = static_cast<float>(Byte[6] * dfScale / 127.0);
 
-            ((float *) pImage)[iX*2  ] = (float) dfReSHV;
-            ((float *) pImage)[iX*2+1] = (float) dfImSHV;
+            pafImage[iX*2  ] = fReSHV;
+            pafImage[iX*2+1] = fImSHV;
         }
         else if( nBand == 3 )
         {
-            dfReSVH = Byte[7] * dfScale / 127.0;
-            dfImSVH = Byte[8] * dfScale / 127.0;
+            const float fReSVH = static_cast<float>(Byte[7] * dfScale / 127.0);
+            const float fImSVH = static_cast<float>(Byte[8] * dfScale / 127.0);
 
-            ((float *) pImage)[iX*2  ] = (float) dfReSVH;
-            ((float *) pImage)[iX*2+1] = (float) dfImSVH;
+            pafImage[iX*2  ] = fReSVH;
+            pafImage[iX*2+1] = fImSVH;
         }
         else if( nBand == 4 )
         {
-            dfReSVV = Byte[9] * dfScale / 127.0;
-            dfImSVV = Byte[10]* dfScale / 127.0;
+            const float fReSVV = static_cast<float>(Byte[9] * dfScale / 127.0);
+            const float fImSVV = static_cast<float>(Byte[10]* dfScale / 127.0);
 
-            ((float *) pImage)[iX*2  ] = (float) dfReSVV;
-            ((float *) pImage)[iX*2+1] = (float) dfImSVV;
+            pafImage[iX*2  ] = fReSVV;
+            pafImage[iX*2+1] = fImSVV;
         }
     }
 
@@ -1368,12 +1324,13 @@ CPLErr SIRC_QSLCRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /*                        CPG_STOKESRasterBand()                        */
 /************************************************************************/
 
-CPG_STOKESRasterBand::CPG_STOKESRasterBand( GDALDataset *poDS, int nBand, 
+CPG_STOKESRasterBand::CPG_STOKESRasterBand( GDALDataset *poDSIn, int nBandIn,
                                             GDALDataType eType,
-                                            int bNativeOrder  )
-
+                                            int bNativeOrderIn ) :
+    nBand(nBandIn),
+    bNativeOrder(bNativeOrderIn)
 {
-    static const char *apszPolarizations[16] = { "Covariance_11",
+    static const char * const apszPolarizations[16] = { "Covariance_11",
                                                  "Covariance_12",
                                                  "Covariance_13",
                                                  "Covariance_14",
@@ -1390,28 +1347,17 @@ CPG_STOKESRasterBand::CPG_STOKESRasterBand( GDALDataset *poDS, int nBand,
                                                  "Covariance_43",
                                                  "Covariance_44" };
 
-    this->poDS = poDS;
-    this->nBand = nBand;
-    this->eDataType = eType;
-    this->bNativeOrder = bNativeOrder;
+    poDS = poDSIn;
+    eDataType = eType;
 
-    nBlockXSize = poDS->GetRasterXSize();
+    nBlockXSize = poDSIn->GetRasterXSize();
     nBlockYSize = 1;
 
-    SetMetadataItem( "POLARIMETRIC_INTERP",apszPolarizations[nBand-1] );
+    SetMetadataItem( "POLARIMETRIC_INTERP", apszPolarizations[nBand-1] );
     SetDescription( apszPolarizations[nBand-1] );
 }
 
 /************************************************************************/
-/*                         ~CPG_STOKESRasterBand()                      */
-/************************************************************************/
-
-CPG_STOKESRasterBand::~CPG_STOKESRasterBand()
-
-{
-}
-
-/************************************************************************/
 /*                             IReadBlock()                             */
 /************************************************************************/
 
@@ -1422,22 +1368,18 @@ CPLErr CPG_STOKESRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                                          void * pImage )
 
 {
-    int iPixel;
+    CPLAssert( nBlockXOff == 0 );
+
     int m11, /* m12, */ m13, m14, /* m21, */ m22, m23, m24, step;
     int m31, m32, m33, m34, m41, m42, m43, m44;
-    CPGDataset *poGDS = (CPGDataset *) poDS;
-    float *M;
-    float *pafLine;
-    CPLErr eErr;
-
-    CPLAssert( nBlockXOff == 0 );
+    CPGDataset *poGDS = reinterpret_cast<CPGDataset *>( poDS );
 
-    eErr = poGDS->LoadStokesLine(nBlockYOff, bNativeOrder);
+    CPLErr eErr = poGDS->LoadStokesLine(nBlockYOff, bNativeOrder);
     if( eErr != CE_None )
         return eErr;
 
-    M = poGDS->padfStokesMatrix;
-    pafLine = ( float * ) pImage;
+    float *M = poGDS->padfStokesMatrix;
+    float *pafLine = reinterpret_cast<float *>( pImage );
 
     if ( poGDS->nInterleave == BIP)
     {
@@ -1481,7 +1423,7 @@ CPLErr CPG_STOKESRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     }
     if ( nBand == 1 ) /* C11 */
     {
-        for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
+        for ( int iPixel = 0; iPixel < nRasterXSize; iPixel++ )
         {
             pafLine[iPixel*2+0] = M[m11]-M[m22]-M[m33]+M[m44];
             pafLine[iPixel*2+1] = 0.0;
@@ -1493,7 +1435,7 @@ CPLErr CPG_STOKESRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     }
     else if ( nBand == 2 ) /* C12 */
     {
-        for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
+        for ( int iPixel = 0; iPixel < nRasterXSize; iPixel++ )
         {
             pafLine[iPixel*2+0] = M[m13]-M[m23];
             pafLine[iPixel*2+1] = M[m14]-M[m24];
@@ -1505,7 +1447,7 @@ CPLErr CPG_STOKESRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     }
     else if ( nBand == 3 ) /* C13 */
     {
-        for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
+        for ( int iPixel = 0; iPixel < nRasterXSize; iPixel++ )
         {
             pafLine[iPixel*2+0] = M[m33]-M[m44];
             pafLine[iPixel*2+1] = M[m43]+M[m34];
@@ -1517,7 +1459,7 @@ CPLErr CPG_STOKESRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     }
     else if ( nBand == 4 ) /* C14 */
     {
-        for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
+        for ( int iPixel = 0; iPixel < nRasterXSize; iPixel++ )
         {
             pafLine[iPixel*2+0] = M[m31]-M[m32];
             pafLine[iPixel*2+1] = M[m41]-M[m42];
@@ -1529,7 +1471,7 @@ CPLErr CPG_STOKESRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     }
     else if ( nBand == 5 ) /* C21 */
     {
-        for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
+        for ( int iPixel = 0; iPixel < nRasterXSize; iPixel++ )
         {
             pafLine[iPixel*2+0] = M[m13]-M[m23];
             pafLine[iPixel*2+1] = M[m24]-M[m14];
@@ -1541,7 +1483,7 @@ CPLErr CPG_STOKESRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     }
     else if ( nBand == 6 ) /* C22 */
     {
-        for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
+        for ( int iPixel = 0; iPixel < nRasterXSize; iPixel++ )
         {
             pafLine[iPixel*2+0] = M[m11]+M[m22]-M[m33]-M[m44];
             pafLine[iPixel*2+1] = 0.0;
@@ -1553,7 +1495,7 @@ CPLErr CPG_STOKESRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     }
     else if ( nBand == 7 ) /* C23 */
     {
-        for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
+        for ( int iPixel = 0; iPixel < nRasterXSize; iPixel++ )
         {
             pafLine[iPixel*2+0] = M[m31]+M[m32];
             pafLine[iPixel*2+1] = M[m41]+M[m42];
@@ -1565,7 +1507,7 @@ CPLErr CPG_STOKESRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     }
     else if ( nBand == 8 ) /* C24 */
     {
-        for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
+        for ( int iPixel = 0; iPixel < nRasterXSize; iPixel++ )
         {
             pafLine[iPixel*2+0] = M[m33]+M[m44];
             pafLine[iPixel*2+1] = M[m43]-M[m34];
@@ -1577,7 +1519,7 @@ CPLErr CPG_STOKESRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     }
     else if ( nBand == 9 ) /* C31 */
     {
-        for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
+        for ( int iPixel = 0; iPixel < nRasterXSize; iPixel++ )
         {
             pafLine[iPixel*2+0] = M[m33]-M[m44];
             pafLine[iPixel*2+1] = -1*M[m43]-M[m34];
@@ -1589,7 +1531,7 @@ CPLErr CPG_STOKESRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     }
     else if ( nBand == 10 ) /* C32 */
     {
-        for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
+        for ( int iPixel = 0; iPixel < nRasterXSize; iPixel++ )
         {
             pafLine[iPixel*2+0] = M[m31]+M[m32];
             pafLine[iPixel*2+1] = -1*M[m41]-M[m42];
@@ -1601,7 +1543,7 @@ CPLErr CPG_STOKESRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     }
     else if ( nBand == 11 ) /* C33 */
     {
-        for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
+        for ( int iPixel = 0; iPixel < nRasterXSize; iPixel++ )
         {
             pafLine[iPixel*2+0] = M[m11]+M[m22]+M[m33]+M[m44];
             pafLine[iPixel*2+1] = 0.0;
@@ -1614,7 +1556,7 @@ CPLErr CPG_STOKESRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     }
     else if ( nBand == 12 ) /* C34 */
     {
-        for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
+        for ( int iPixel = 0; iPixel < nRasterXSize; iPixel++ )
         {
             pafLine[iPixel*2+0] = M[m13]-M[m23];
             pafLine[iPixel*2+1] = -1*M[m14]-M[m24];
@@ -1626,7 +1568,7 @@ CPLErr CPG_STOKESRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     }
     else if ( nBand == 13 ) /* C41 */
     {
-        for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
+        for ( int iPixel = 0; iPixel < nRasterXSize; iPixel++ )
         {
             pafLine[iPixel*2+0] = M[m31]-M[m32];
             pafLine[iPixel*2+1] = M[m42]-M[m41];
@@ -1638,7 +1580,7 @@ CPLErr CPG_STOKESRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     }
     else if ( nBand == 14 ) /* C42 */
     {
-        for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
+        for ( int iPixel = 0; iPixel < nRasterXSize; iPixel++ )
         {
             pafLine[iPixel*2+0] = M[m33]+M[m44];
             pafLine[iPixel*2+1] = M[m34]-M[m43];
@@ -1650,7 +1592,7 @@ CPLErr CPG_STOKESRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     }
     else if ( nBand == 15 ) /* C43 */
     {
-        for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
+        for ( int iPixel = 0; iPixel < nRasterXSize; iPixel++ )
         {
             pafLine[iPixel*2+0] = M[m13]-M[m23];
             pafLine[iPixel*2+1] = M[m14]+M[m24];
@@ -1662,7 +1604,7 @@ CPLErr CPG_STOKESRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     }
     else /* C44 */
     {
-        for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
+        for ( int iPixel = 0; iPixel < nRasterXSize; iPixel++ )
         {
             pafLine[iPixel*2+0] = M[m11]-M[m22]+M[m33]-M[m44];
             pafLine[iPixel*2+1] = 0.0;
@@ -1677,25 +1619,22 @@ CPLErr CPG_STOKESRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 }
 
 /************************************************************************/
-/*                         GDALRegister_CPG()                          */
+/*                         GDALRegister_CPG()                           */
 /************************************************************************/
 
 void GDALRegister_CPG()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "CPG" ) != NULL )
+      return;
 
-    if( GDALGetDriverByName( "CPG" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "CPG" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Convair PolGASP" );
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->pfnOpen = CPGDataset::Open;
+    poDriver->SetDescription( "CPG" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Convair PolGASP" );
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    poDriver->pfnOpen = CPGDataset::Open;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/raw/ctable2dataset.cpp b/frmts/raw/ctable2dataset.cpp
index ea39ce9..06f6dbf 100644
--- a/frmts/raw/ctable2dataset.cpp
+++ b/frmts/raw/ctable2dataset.cpp
@@ -28,16 +28,13 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "rawdataset.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
 #include "ogr_srs_api.h"
+#include "rawdataset.h"
 
 CPL_CVSID("$Id$");
 
-#ifndef M_PI
-#define M_PI		3.14159265358979323846
-#endif
-
 /************************************************************************/
 /* ==================================================================== */
 /*				CTable2Dataset				*/
@@ -54,7 +51,7 @@ class CTable2Dataset : public RawDataset
   public:
     		CTable2Dataset();
     	        ~CTable2Dataset();
-    
+
     virtual CPLErr SetGeoTransform( double * padfTransform );
     virtual CPLErr GetGeoTransform( double * padfTransform );
     virtual const char *GetProjectionRef();
@@ -77,10 +74,9 @@ class CTable2Dataset : public RawDataset
 /*                             CTable2Dataset()                          */
 /************************************************************************/
 
-CTable2Dataset::CTable2Dataset()
-{
-    fpImage = NULL;
-}
+CTable2Dataset::CTable2Dataset() :
+    fpImage(NULL)
+{}
 
 /************************************************************************/
 /*                            ~CTable2Dataset()                          */
@@ -92,7 +88,12 @@ CTable2Dataset::~CTable2Dataset()
     FlushCache();
 
     if( fpImage != NULL )
-        VSIFCloseL( fpImage );
+    {
+        if( VSIFCloseL( fpImage ) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        }
+    }
 }
 
 /************************************************************************/
@@ -115,7 +116,9 @@ int CTable2Dataset::Identify( GDALOpenInfo *poOpenInfo )
     if( poOpenInfo->nHeaderBytes < 64 )
         return FALSE;
 
-    if( !EQUALN((const char *)poOpenInfo->pabyHeader + 0, "CTABLE V2", 9 ) )
+    if( !STARTS_WITH_CI(
+           reinterpret_cast<const char *>( poOpenInfo->pabyHeader + 0 ),
+           "CTABLE V2") )
         return FALSE;
 
     return TRUE;
@@ -130,21 +133,18 @@ GDALDataset *CTable2Dataset::Open( GDALOpenInfo * poOpenInfo )
 {
     if( !Identify( poOpenInfo ) )
         return NULL;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    CTable2Dataset 	*poDS;
-
-    poDS = new CTable2Dataset();
+    CTable2Dataset *poDS = new CTable2Dataset();
     poDS->eAccess = poOpenInfo->eAccess;
 
 /* -------------------------------------------------------------------- */
 /*      Open the file.                                                  */
 /* -------------------------------------------------------------------- */
-    CPLString osFilename;
-    osFilename = poOpenInfo->pszFilename;
-    
+    CPLString osFilename = poOpenInfo->pszFilename;
+
     if( poOpenInfo->eAccess == GA_ReadOnly )
         poDS->fpImage = VSIFOpenL( osFilename, "rb" );
     else
@@ -159,14 +159,14 @@ GDALDataset *CTable2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Read the file header.                                           */
 /* -------------------------------------------------------------------- */
-    char  achHeader[160];
-    CPLString osDescription;
 
-    VSIFSeekL( poDS->fpImage, 0, SEEK_SET );
-    VSIFReadL( achHeader, 1, 160, poDS->fpImage );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( poDS->fpImage, 0, SEEK_SET ));
 
+    char  achHeader[160];
+    CPL_IGNORE_RET_VAL(VSIFReadL( achHeader, 1, 160, poDS->fpImage ));
     achHeader[16+79] = '\0';
-    osDescription = (const char *) achHeader+16;
+
+    CPLString osDescription = reinterpret_cast<const char *>( achHeader + 16 );
     osDescription.Trim();
     poDS->SetMetadataItem( "DESCRIPTION", osDescription );
 
@@ -183,20 +183,23 @@ GDALDataset *CTable2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Extract size, and geotransform.                                 */
 /* -------------------------------------------------------------------- */
-    GUInt32 nRasterXSize, nRasterYSize;
-    
+    int nRasterXSize, nRasterYSize;
     memcpy( &nRasterXSize, achHeader + 128, 4 );
     memcpy( &nRasterYSize, achHeader + 132, 4 );
+    if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize))
+    {
+        delete poDS;
+        return NULL;
+    }
+
     poDS->nRasterXSize = nRasterXSize;
     poDS->nRasterYSize = nRasterYSize;
 
-    int i;
     double adfValues[4];
     memcpy( adfValues, achHeader + 96, sizeof(double)*4 );
 
-    for( i = 0; i < 4; i++ )
+    for( int i = 0; i < 4; i++ )
         adfValues[i] *= 180/M_PI; // Radians to degrees.
-    
 
     poDS->adfGeoTransform[0] = adfValues[0] - adfValues[2]*0.5;
     poDS->adfGeoTransform[1] = adfValues[2];
@@ -208,18 +211,18 @@ GDALDataset *CTable2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Setup the bands.                                                */
 /* -------------------------------------------------------------------- */
-    RawRasterBand *poBand = 
-        new RawRasterBand( poDS, 1, poDS->fpImage, 
+    RawRasterBand *poBand =
+        new RawRasterBand( poDS, 1, poDS->fpImage,
                            160 + 4 + nRasterXSize * (nRasterYSize-1) * 2 * 4,
-                           8, -8 * nRasterXSize, 
+                           8, -8 * nRasterXSize,
                            GDT_Float32, CPL_IS_LSB, TRUE, FALSE );
     poBand->SetDescription( "Latitude Offset (radians)" );
     poDS->SetBand( 1, poBand );
-    
-    poBand = 
-        new RawRasterBand( poDS, 2, poDS->fpImage, 
+
+    poBand =
+        new RawRasterBand( poDS, 2, poDS->fpImage,
                            160 + nRasterXSize * (nRasterYSize-1) * 2 * 4,
-                           8, -8 * nRasterXSize, 
+                           8, -8 * nRasterXSize,
                            GDT_Float32, CPL_IS_LSB, TRUE, FALSE );
     poBand->SetDescription( "Longitude Offset (radians)" );
     poDS->SetBand( 2, poBand );
@@ -259,14 +262,14 @@ CPLErr CTable2Dataset::SetGeoTransform( double * padfTransform )
     if( eAccess == GA_ReadOnly )
     {
         CPLError( CE_Failure, CPLE_NoWriteAccess,
-                  "Unable to update geotransform on readonly file." ); 
+                  "Unable to update geotransform on readonly file." );
         return CE_Failure;
     }
 
     if( padfTransform[2] != 0.0 || padfTransform[4] != 0.0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Rotated and sheared geotransforms not supported for CTable2."); 
+                  "Rotated and sheared geotransforms not supported for CTable2.");
         return CE_Failure;
     }
 
@@ -275,21 +278,22 @@ CPLErr CTable2Dataset::SetGeoTransform( double * padfTransform )
 /* -------------------------------------------------------------------- */
 /*      Update grid header.                                             */
 /* -------------------------------------------------------------------- */
-    double dfValue;
-    char   achHeader[160];
-    double dfDegToRad = M_PI / 180.0;
+    const double dfDegToRad = M_PI / 180.0;
 
     // read grid header
-    VSIFSeekL( fpImage, 0, SEEK_SET );
-    VSIFReadL( achHeader, 1, sizeof(achHeader), fpImage );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( fpImage, 0, SEEK_SET ));
+
+    char achHeader[160];
+    CPL_IGNORE_RET_VAL(VSIFReadL( achHeader, 1, sizeof(achHeader), fpImage ));
 
     // lower left origin (longitude, center of pixel, radians)
-    dfValue = (adfGeoTransform[0] + adfGeoTransform[1]*0.5) * dfDegToRad;
+    double dfValue = (adfGeoTransform[0] + adfGeoTransform[1]*0.5) * dfDegToRad;
     CPL_LSBPTR64( &dfValue );
     memcpy( achHeader + 96, &dfValue, 8 );
 
     // lower left origin (latitude, center of pixel, radians)
-    dfValue = (adfGeoTransform[3] + adfGeoTransform[5] * (nRasterYSize-0.5)) * dfDegToRad;
+    dfValue = (adfGeoTransform[3] + adfGeoTransform[5] * (nRasterYSize-0.5))
+        * dfDegToRad;
     CPL_LSBPTR64( &dfValue );
     memcpy( achHeader + 104, &dfValue, 8 );
 
@@ -304,8 +308,8 @@ CPLErr CTable2Dataset::SetGeoTransform( double * padfTransform )
     memcpy( achHeader + 120, &dfValue, 8 );
 
     // write grid header.
-    VSIFSeekL( fpImage, 0, SEEK_SET );
-    VSIFWriteL( achHeader, 11, 16, fpImage );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( fpImage, 0, SEEK_SET ));
+    CPL_IGNORE_RET_VAL(VSIFWriteL( achHeader, 11, 16, fpImage ));
 
     return CE_None;
 }
@@ -343,10 +347,8 @@ GDALDataset *CTable2Dataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Try to open or create file.                                     */
 /* -------------------------------------------------------------------- */
-    VSILFILE	*fp;
+    VSILFILE *fp = VSIFOpenL( pszFilename, "wb" );
 
-    fp = VSIFOpenL( pszFilename, "wb" );
-    
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
@@ -359,20 +361,18 @@ GDALDataset *CTable2Dataset::Create( const char * pszFilename,
 /*      Create a file header, with a defaulted georeferencing.          */
 /* -------------------------------------------------------------------- */
     char achHeader[160];
-    int nValue32;
-    double dfValue;
 
     memset( achHeader, 0, sizeof(achHeader));
 
     memcpy( achHeader+0, "CTABLE V2.0     ", 16 );
-    
+
     if( CSLFetchNameValue( papszOptions, "DESCRIPTION" ) != NULL )
-        strncpy( achHeader + 16, 
-                 CSLFetchNameValue( papszOptions, "DESCRIPTION" ), 
+        strncpy( achHeader + 16,
+                 CSLFetchNameValue( papszOptions, "DESCRIPTION" ),
                  80 );
-    
+
     // lower left origin (longitude, center of pixel, radians)
-    dfValue = 0;
+    double dfValue = 0;
     CPL_LSBPTR64( &dfValue );
     memcpy( achHeader + 96, &dfValue, 8 );
 
@@ -392,7 +392,7 @@ GDALDataset *CTable2Dataset::Create( const char * pszFilename,
     memcpy( achHeader + 120, &dfValue, 8 );
 
     // raster width in pixels
-    nValue32 = nXSize;
+    int nValue32 = nXSize;
     CPL_LSBPTR32( &nValue32 );
     memcpy( achHeader + 128, &nValue32, 4 );
 
@@ -401,61 +401,61 @@ GDALDataset *CTable2Dataset::Create( const char * pszFilename,
     CPL_LSBPTR32( &nValue32 );
     memcpy( achHeader + 132, &nValue32, 4 );
 
-    VSIFWriteL( achHeader, 1, sizeof(achHeader), fp );
+    CPL_IGNORE_RET_VAL(VSIFWriteL( achHeader, 1, sizeof(achHeader), fp ));
 
 /* -------------------------------------------------------------------- */
 /*      Write zeroed grid data.                                         */
 /* -------------------------------------------------------------------- */
     float *pafLine = (float *) CPLCalloc(sizeof(float)*2,nXSize);
-    int i;
 
-    for( i = 0; i < nYSize; i++ )
+    for( int i = 0; i < nYSize; i++ )
     {
-        if( (int)VSIFWriteL( pafLine, sizeof(float)*2, nXSize, fp ) != nXSize ) 
+        if( static_cast<int>( VSIFWriteL(
+               pafLine, sizeof(float)*2, nXSize, fp ) ) != nXSize )
         {
-            CPLError( CE_Failure, CPLE_FileIO, 
+            CPLError( CE_Failure, CPLE_FileIO,
                       "Write failed at line %d, perhaps the disk is full?",
                       i );
             return NULL;
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Cleanup and return.                                             */
 /* -------------------------------------------------------------------- */
     CPLFree( pafLine );
 
-    VSIFCloseL( fp );
+    if( VSIFCloseL( fp ) != 0 )
+    {
+        CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        return NULL;
+    }
 
     return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
 }
 
 /************************************************************************/
-/*                         GDALRegister_CTable2()                          */
+/*                         GDALRegister_CTable2()                       */
 /************************************************************************/
 
 void GDALRegister_CTable2()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "CTable2" ) != NULL )
+      return;
 
-    if( GDALGetDriverByName( "CTable2" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "CTable2" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "CTable2 Datum Grid Shift" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Float32" );
-
-        poDriver->pfnOpen = CTable2Dataset::Open;
-        poDriver->pfnIdentify = CTable2Dataset::Identify;
-        poDriver->pfnCreate = CTable2Dataset::Create;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "CTable2" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "CTable2 Datum Grid Shift" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Float32" );
+
+    poDriver->pfnOpen = CTable2Dataset::Open;
+    poDriver->pfnIdentify = CTable2Dataset::Identify;
+    poDriver->pfnCreate = CTable2Dataset::Create;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/raw/dipxdataset.cpp b/frmts/raw/dipxdataset.cpp
index b47334d..3e978a5 100644
--- a/frmts/raw/dipxdataset.cpp
+++ b/frmts/raw/dipxdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dipxdataset.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: dipxdataset.cpp 33673 2016-03-07 20:40:54Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Implementation for ELAS DIPEx format variant.
@@ -28,18 +28,19 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "rawdataset.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
 #include "ogr_spatialref.h"
+#include "rawdataset.h"
+
+#include <algorithm>
 
-CPL_CVSID("$Id: dipxdataset.cpp 27384 2014-05-24 12:28:12Z rouault $");
+using std::fill;
 
-CPL_C_START
-void	GDALRegister_DIPEx(void);
-CPL_C_END
+CPL_CVSID("$Id: dipxdataset.cpp 33673 2016-03-07 20:40:54Z goatbar $");
 
 typedef struct {
-    GInt32	NBIH;	/* bytes in header, normaly 1024 */
+    GInt32      NBIH;   /* bytes in header, normally 1024 */
     GInt32      NBPR;	/* bytes per data record (all bands of scanline) */
     GInt32	IL;	/* initial line - normally 1 */
     GInt32	LL;	/* last line */
@@ -47,13 +48,13 @@ typedef struct {
     GInt32	LE;	/* last element (pixel) */
     GInt32	NC;	/* number of channels (bands) */
     GInt32	H4322;	/* header record identifier - always 4322. */
-    char        unused1[40]; 
+    char        unused1[40];
     GByte	IH19[4];/* data type, and size flags */
     GInt32	IH20;	/* number of secondary headers */
-    GInt32	SRID;	
+    GInt32	SRID;
     char        unused2[12];
     double      YOffset;
-    double      XOffset; 
+    double      XOffset;
     double      YPixSize;
     double      XPixSize;
     double      Matrix[4];
@@ -104,10 +105,47 @@ class DIPExDataset : public GDALPamDataset
 /*                            DIPExDataset()                             */
 /************************************************************************/
 
-DIPExDataset::DIPExDataset()
 
+DIPExDataset::DIPExDataset() :
+    fp(NULL),
+    eRasterDataType(GDT_Unknown)
 {
-    fp = NULL;
+    sHeader.NBIH = 0;
+    sHeader.NBPR = 0;
+    sHeader.IL = 0;
+    sHeader.LL = 0;
+    sHeader.IE = 0;
+    sHeader.LE = 0;
+    sHeader.NC = 0;
+    sHeader.H4322 = 0;
+    fill( sHeader.unused1,
+          sHeader.unused1 + CPL_ARRAYSIZE(sHeader.unused1),
+          0 );
+    fill( sHeader.IH19,
+          sHeader.IH19 + CPL_ARRAYSIZE(sHeader.IH19),
+          0 );
+    sHeader.IH20 = 0;
+    sHeader.SRID = 0;
+    fill( sHeader.unused2,
+          sHeader.unused2 + CPL_ARRAYSIZE(sHeader.unused2),
+          0 );
+    sHeader.YOffset = 0.0;
+    sHeader.XOffset = 0.0;
+    sHeader.YPixSize = 0.0;
+    sHeader.XPixSize = 0.0;
+    sHeader.Matrix[0] = 0.0;
+    sHeader.Matrix[1] = 0.0;
+    sHeader.Matrix[2] = 0.0;
+    sHeader.Matrix[3] = 0.0;
+    fill( sHeader.unused3,
+          sHeader.unused3 + CPL_ARRAYSIZE(sHeader.unused3),
+          0 );
+    fill( sHeader.ColorTable,
+          sHeader.ColorTable + CPL_ARRAYSIZE(sHeader.ColorTable),
+          0 );
+    fill( sHeader.unused4,
+          sHeader.unused4 + CPL_ARRAYSIZE(sHeader.unused4),
+          0 );
 
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
@@ -125,7 +163,7 @@ DIPExDataset::~DIPExDataset()
 
 {
     if (fp)
-        VSIFCloseL( fp );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
     fp = NULL;
 }
 
@@ -137,36 +175,37 @@ GDALDataset *DIPExDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
 /* -------------------------------------------------------------------- */
-/*	First we check to see if the file has the expected header	*/
-/*	bytes.								*/    
+/*      First we check to see if the file has the expected header       */
+/*      bytes.                                                          */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->nHeaderBytes < 256 )
         return NULL;
 
-    if( CPL_LSBWORD32(*((GInt32 *) (poOpenInfo->pabyHeader+0))) != 1024 )
+    if( CPL_LSBWORD32(*( reinterpret_cast<GInt32 *>( poOpenInfo->pabyHeader + 0 )))
+        != 1024 )
         return NULL;
 
-    if( CPL_LSBWORD32(*((GInt32 *) (poOpenInfo->pabyHeader+28))) != 4322 )
+    if( CPL_LSBWORD32(*( reinterpret_cast<GInt32 *>( poOpenInfo->pabyHeader + 28 )))
+        != 4322 )
         return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    DIPExDataset 	*poDS;
-    const char	 	*pszAccess;
+    const char *pszAccess;
 
     if( poOpenInfo->eAccess == GA_Update )
         pszAccess = "r+b";
     else
         pszAccess = "rb";
 
-    poDS = new DIPExDataset();
+    DIPExDataset *poDS = new DIPExDataset();
 
     poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, pszAccess );
     if( poDS->fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Attempt to open `%s' with acces `%s' failed.\n",
+                  "Attempt to open `%s' with access `%s' failed.\n",
                   poOpenInfo->pszFilename, pszAccess );
         delete poDS;
         return NULL;
@@ -189,31 +228,28 @@ GDALDataset *DIPExDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Extract information of interest from the header.                */
 /* -------------------------------------------------------------------- */
-    int		nStart, nEnd, nDIPExDataType, nBytesPerSample;
-    int         nLineOffset;
-    
-    nLineOffset = CPL_LSBWORD32( poDS->sHeader.NBPR );
+    const int nLineOffset = CPL_LSBWORD32( poDS->sHeader.NBPR );
 
-    nStart = CPL_LSBWORD32( poDS->sHeader.IL );
-    nEnd = CPL_LSBWORD32( poDS->sHeader.LL );
+    int nStart = CPL_LSBWORD32( poDS->sHeader.IL );
+    int nEnd = CPL_LSBWORD32( poDS->sHeader.LL );
     poDS->nRasterYSize = nEnd - nStart + 1;
 
     nStart = CPL_LSBWORD32( poDS->sHeader.IE );
     nEnd = CPL_LSBWORD32( poDS->sHeader.LE );
     poDS->nRasterXSize = nEnd - nStart + 1;
 
-    poDS->nBands = CPL_LSBWORD32( poDS->sHeader.NC );
+    int nBands = CPL_LSBWORD32( poDS->sHeader.NC );
 
     if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) ||
-        !GDALCheckBandCount(poDS->nBands, FALSE))
+        !GDALCheckBandCount(nBands, FALSE))
     {
         delete poDS;
         return NULL;
     }
 
-    nDIPExDataType = (poDS->sHeader.IH19[1] & 0x7e) >> 2;
-    nBytesPerSample = poDS->sHeader.IH19[0];
-    
+    const int nDIPExDataType = (poDS->sHeader.IH19[1] & 0x7e) >> 2;
+    const int nBytesPerSample = poDS->sHeader.IH19[0];
+
     if( nDIPExDataType == 0 && nBytesPerSample == 1 )
         poDS->eRasterDataType = GDT_Byte;
     else if( nDIPExDataType == 1 && nBytesPerSample == 1 )
@@ -226,25 +262,38 @@ GDALDataset *DIPExDataset::Open( GDALOpenInfo * poOpenInfo )
     {
         delete poDS;
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unrecognised image data type %d, with BytesPerSample=%d.\n",
+                  "Unrecognized image data type %d, with BytesPerSample=%d.\n",
                   nDIPExDataType, nBytesPerSample );
         return NULL;
     }
-    
+
+    if( nLineOffset <= 0 || nLineOffset > INT_MAX / nBands )
+    {
+        delete poDS;
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Invalid values: nLineOffset = %d, nBands = %d.",
+                  nLineOffset, nBands );
+        return NULL;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    int		iBand;
-
-    for( iBand = 0; iBand < poDS->nBands; iBand++ )
+    CPLErrorReset();
+    for( int iBand = 0; iBand < nBands; iBand++ )
     {
-        poDS->SetBand( iBand+1, 
-                       new RawRasterBand( poDS, iBand+1, poDS->fp, 
-                                          1024 + iBand * nLineOffset, 
-                                          nBytesPerSample, 
-                                          nLineOffset * poDS->nBands,
-                                          poDS->eRasterDataType, 
+        poDS->SetBand( iBand+1,
+                       new RawRasterBand( poDS, iBand+1, poDS->fp,
+                                          1024 + iBand * nLineOffset,
+                                          nBytesPerSample,
+                                          nLineOffset * nBands,
+                                          poDS->eRasterDataType,
                                           CPL_IS_LSB, TRUE ) );
+        if( CPLGetLastErrorType() != CE_None )
+        {
+            delete poDS;
+            return NULL;
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -276,12 +325,12 @@ GDALDataset *DIPExDataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->adfGeoTransform[4] = 0.0;
         poDS->adfGeoTransform[5] = 1.0;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Look for SRID.                                                  */
 /* -------------------------------------------------------------------- */
     CPL_LSBPTR32( &(poDS->sHeader.SRID) );
-    
+
     if( poDS->sHeader.SRID > 0 && poDS->sHeader.SRID < 33000 )
     {
         OGRSpatialReference oSR;
@@ -338,20 +387,17 @@ CPLErr DIPExDataset::GetGeoTransform( double * padfTransform )
 void GDALRegister_DIPEx()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "DIPEx" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "DIPEx" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "DIPEx" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "DIPEx" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->pfnOpen = DIPExDataset::Open;
+    poDriver->SetDescription( "DIPEx" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "DIPEx" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    poDriver->pfnOpen = DIPExDataset::Open;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/raw/doq1dataset.cpp b/frmts/raw/doq1dataset.cpp
index 76ef58d..001974f 100644
--- a/frmts/raw/doq1dataset.cpp
+++ b/frmts/raw/doq1dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: doq1dataset.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: doq1dataset.cpp 33673 2016-03-07 20:40:54Z goatbar $
  *
  * Project:  USGS DOQ Driver (First Generation Format)
  * Purpose:  Implementation of DOQ1Dataset
@@ -28,18 +28,15 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "rawdataset.h"
+#include "gdal_frmts.h"
 #include "cpl_string.h"
+#include "rawdataset.h"
 
-CPL_CVSID("$Id: doq1dataset.cpp 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: doq1dataset.cpp 33673 2016-03-07 20:40:54Z goatbar $");
 
 static double DOQGetField( unsigned char *, int );
 static void DOQGetDescription( GDALDataset *, unsigned char * );
 
-CPL_C_START
-void	GDALRegister_DOQ1(void);
-CPL_C_END
-
 #define UTM_FORMAT \
 "PROJCS[\"%s / UTM zone %dN\",GEOGCS[%s,PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",%d],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",0],%s]"
 
@@ -64,19 +61,19 @@ CPL_C_END
 class DOQ1Dataset : public RawDataset
 {
     VSILFILE	*fpImage;	// image data file.
-    
+
     double	dfULX, dfULY;
     double	dfXPixelSize, dfYPixelSize;
 
     char	*pszProjection;
-    
+
   public:
     		DOQ1Dataset();
     	        ~DOQ1Dataset();
 
     CPLErr 	GetGeoTransform( double * padfTransform );
     const char  *GetProjectionRef( void );
-    
+
     static GDALDataset *Open( GDALOpenInfo * );
 };
 
@@ -84,11 +81,14 @@ class DOQ1Dataset : public RawDataset
 /*                            DOQ1Dataset()                             */
 /************************************************************************/
 
-DOQ1Dataset::DOQ1Dataset()
-{
-    pszProjection = NULL;
-    fpImage = NULL;
-}
+DOQ1Dataset::DOQ1Dataset() :
+    fpImage(NULL),
+    dfULX(0.0),
+    dfULY(0.0),
+    dfXPixelSize(0.0),
+    dfYPixelSize(0.0),
+    pszProjection(NULL)
+{ }
 
 /************************************************************************/
 /*                            ~DOQ1Dataset()                            */
@@ -101,7 +101,7 @@ DOQ1Dataset::~DOQ1Dataset()
 
     CPLFree( pszProjection );
     if( fpImage != NULL )
-        VSIFCloseL( fpImage );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fpImage ));
 }
 
 /************************************************************************/
@@ -117,8 +117,8 @@ CPLErr DOQ1Dataset::GetGeoTransform( double * padfTransform )
     padfTransform[3] = dfULY;
     padfTransform[4] = 0.0;
     padfTransform[5] = -1 * dfYPixelSize;
-    
-    return( CE_None );
+
+    return CE_None;
 }
 
 /************************************************************************/
@@ -138,10 +138,8 @@ const char *DOQ1Dataset::GetProjectionRef()
 GDALDataset *DOQ1Dataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    int		nWidth, nHeight, nBandStorage, nBandTypes;
-    
 /* -------------------------------------------------------------------- */
-/*	We assume the user is pointing to the binary (ie. .bil) file.	*/
+/*      We assume the user is pointing to the binary (i.e. .bil) file.  */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->nHeaderBytes < 212 )
         return NULL;
@@ -149,21 +147,26 @@ GDALDataset *DOQ1Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*	Attempt to extract a few key values from the header.		*/
 /* -------------------------------------------------------------------- */
-    nWidth = (int) DOQGetField(poOpenInfo->pabyHeader + 150, 6);
-    nHeight = (int) DOQGetField(poOpenInfo->pabyHeader + 144, 6);
-    nBandStorage = (int) DOQGetField(poOpenInfo->pabyHeader + 162, 3);
-    nBandTypes = (int) DOQGetField(poOpenInfo->pabyHeader + 156, 3);
+    const double dfWidth = DOQGetField(poOpenInfo->pabyHeader + 150, 6 );
+    const double dfHeight = DOQGetField(poOpenInfo->pabyHeader + 144, 6 );
+    const double dfBandStorage = DOQGetField(poOpenInfo->pabyHeader + 162, 3 );
+    const double dfBandTypes = DOQGetField(poOpenInfo->pabyHeader + 156, 3 );
 
 /* -------------------------------------------------------------------- */
 /*      Do these values look coherent for a DOQ file?  It would be      */
 /*      nice to do a more comprehensive test than this!                 */
 /* -------------------------------------------------------------------- */
-    if( nWidth < 500 || nWidth > 25000
-        || nHeight < 500 || nHeight > 25000
-        || nBandStorage < 0 || nBandStorage > 4
-        || nBandTypes < 1 || nBandTypes > 9 )
+    if( dfWidth < 500 || dfWidth > 25000 || CPLIsNan(dfWidth)
+        || dfHeight < 500 || dfHeight > 25000 || CPLIsNan(dfHeight)
+        || dfBandStorage < 0 || dfBandStorage > 4 || CPLIsNan(dfBandStorage)
+        || dfBandTypes < 1 || dfBandTypes > 9 || CPLIsNan(dfBandTypes) )
         return NULL;
 
+    const int nWidth = static_cast<int>(dfWidth);
+    const int nHeight = static_cast<int>(dfHeight);
+    /*const int nBandStorage = static_cast<int>(dfBandStorage);*/
+    const int nBandTypes = static_cast<int>(dfBandTypes);
+
 /* -------------------------------------------------------------------- */
 /*      Check the configuration.  We don't currently handle all         */
 /*      variations, only the common ones.                               */
@@ -175,31 +178,29 @@ GDALDataset *DOQ1Dataset::Open( GDALOpenInfo * poOpenInfo )
                   nBandTypes );
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The DOQ1 driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    DOQ1Dataset 	*poDS;
-
-    poDS = new DOQ1Dataset();
+    DOQ1Dataset *poDS = new DOQ1Dataset();
 
 /* -------------------------------------------------------------------- */
 /*      Capture some information from the file that is of interest.     */
 /* -------------------------------------------------------------------- */
     poDS->nRasterXSize = nWidth;
     poDS->nRasterYSize = nHeight;
-    
+
     poDS->fpImage = VSIFOpenL(poOpenInfo->pszFilename, "rb");
     if (poDS->fpImage == NULL)
     {
@@ -210,23 +211,23 @@ GDALDataset *DOQ1Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Compute layout of data.                                         */
 /* -------------------------------------------------------------------- */
-    int		nSkipBytes, nBytesPerPixel=0, nBytesPerLine, i;
+    int nBytesPerPixel=0;
 
     if( nBandTypes < 5 )
         nBytesPerPixel = 1;
     else if( nBandTypes == 5 )
         nBytesPerPixel = 3;
 
-    nBytesPerLine = nBytesPerPixel * nWidth;
-    nSkipBytes = 4 * nBytesPerLine;
-    
+    const int nBytesPerLine = nBytesPerPixel * nWidth;
+    const int nSkipBytes = 4 * nBytesPerLine;
+
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
     poDS->nBands = nBytesPerPixel;
-    for( i = 0; i < poDS->nBands; i++ )
+    for( int i = 0; i < poDS->nBands; i++ )
     {
-        poDS->SetBand( i+1, 
+        poDS->SetBand( i+1,
             new RawRasterBand( poDS, i+1, poDS->fpImage,
                                nSkipBytes + i, nBytesPerPixel, nBytesPerLine,
                                GDT_Byte, TRUE, TRUE ) );
@@ -240,38 +241,39 @@ GDALDataset *DOQ1Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Establish the projection string.                                */
 /* -------------------------------------------------------------------- */
-    if( ((int) DOQGetField(poOpenInfo->pabyHeader + 195, 3)) != 1 )
+    if( static_cast<int>( DOQGetField(poOpenInfo->pabyHeader + 195, 3) ) != 1 )
         poDS->pszProjection = VSIStrdup("");
     else
     {
-        const char *pszDatumLong, *pszDatumShort;
-        const char *pszUnits;
-        int	   nZone;
-
-        nZone = (int) DOQGetField(poOpenInfo->pabyHeader + 198, 6);
+        int nZone = static_cast<int>(
+            DOQGetField(poOpenInfo->pabyHeader + 198, 6) );
+        if( nZone < 0 || nZone > 60 )
+            nZone = 0;
 
-        if( ((int) DOQGetField(poOpenInfo->pabyHeader + 204, 3)) == 1 )
+        const char *pszUnits;
+        if( static_cast<int>( DOQGetField(poOpenInfo->pabyHeader + 204, 3)) == 1 )
             pszUnits = "UNIT[\"US survey foot\",0.304800609601219]";
         else
             pszUnits = "UNIT[\"metre\",1]";
 
-        switch( (int) DOQGetField(poOpenInfo->pabyHeader + 167, 2) )
+        const char *pszDatumLong, *pszDatumShort;
+        switch( static_cast<int>( DOQGetField(poOpenInfo->pabyHeader + 167, 2) ) )
         {
           case 1:
             pszDatumLong = NAD27_DATUM;
             pszDatumShort = "NAD 27";
             break;
-            
+
           case 2:
             pszDatumLong = WGS72_DATUM;
             pszDatumShort = "WGS 72";
             break;
-            
+
           case 3:
             pszDatumLong = WGS84_DATUM;
             pszDatumShort = "WGS 84";
             break;
-            
+
           case 4:
             pszDatumLong = NAD83_DATUM;
             pszDatumShort = "NAD 83";
@@ -282,17 +284,17 @@ GDALDataset *DOQ1Dataset::Open( GDALOpenInfo * poOpenInfo )
             pszDatumShort = "unknown";
             break;
         }
-        
-        poDS->pszProjection = 
+
+        poDS->pszProjection =
             CPLStrdup(CPLSPrintf( UTM_FORMAT, pszDatumShort, nZone,
                                   pszDatumLong, nZone * 6 - 183, pszUnits ));
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read the georeferencing information.                            */
 /* -------------------------------------------------------------------- */
-    unsigned char	abyRecordData[500];
-    
+    unsigned char abyRecordData[500];
+
     if( VSIFSeekL( poDS->fpImage, nBytesPerLine * 2, SEEK_SET ) != 0
         || VSIFReadL(abyRecordData,sizeof(abyRecordData),1,poDS->fpImage) != 1 )
     {
@@ -340,24 +342,20 @@ GDALDataset *DOQ1Dataset::Open( GDALOpenInfo * poOpenInfo )
 void GDALRegister_DOQ1()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "DOQ1" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "DOQ1" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "DOQ1" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "USGS DOQ (Old Style)" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#DOQ1" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-        
-        poDriver->pfnOpen = DOQ1Dataset::Open;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "DOQ1" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "USGS DOQ (Old Style)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#DOQ1" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = DOQ1Dataset::Open;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
 
 /************************************************************************/
@@ -368,12 +366,11 @@ static double DOQGetField( unsigned char *pabyData, int nBytes )
 
 {
     char	szWork[128];
-    int		i;
 
-    strncpy( szWork, (const char *) pabyData, nBytes );
+    strncpy( szWork, reinterpret_cast<const char *>( pabyData ), nBytes );
     szWork[nBytes] = '\0';
 
-    for( i = 0; i < nBytes; i++ )
+    for( int i = 0; i < nBytes; i++ )
     {
         if( szWork[i] == 'D' || szWork[i] == 'd' )
             szWork[i] = 'E';
@@ -390,17 +387,19 @@ static void DOQGetDescription( GDALDataset *poDS, unsigned char *pabyData )
 
 {
     char	szWork[128];
-    int i = 0;
 
     memset( szWork, ' ', 128 );
     strncpy( szWork, "USGS GeoTIFF DOQ 1:12000 Q-Quad of ", 35 );
-    strncpy( szWork + 35, (const char *) pabyData + 0, 38 );
+    strncpy( szWork + 35, reinterpret_cast<const char *>( pabyData + 0 ), 38 );
+
+    int i = 0;
     while ( *(szWork + 72 - i) == ' ' ) {
       i++;
     }
     i--;
-    strncpy( szWork + 73 - i, (const char *) pabyData + 38, 2 );
-    strncpy( szWork + 76 - i, (const char *) pabyData + 44, 2 );
+
+    strncpy( szWork + 73 - i, reinterpret_cast<const char *>( pabyData + 38 ), 2 );
+    strncpy( szWork + 76 - i, reinterpret_cast<const char *>( pabyData + 44 ), 2 );
     szWork[77-i] = '\0';
 
     poDS->SetMetadataItem( "DOQ_DESC", szWork );
diff --git a/frmts/raw/doq2dataset.cpp b/frmts/raw/doq2dataset.cpp
index aab6686..3c36e4f 100644
--- a/frmts/raw/doq2dataset.cpp
+++ b/frmts/raw/doq2dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: doq2dataset.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: doq2dataset.cpp 33673 2016-03-07 20:40:54Z goatbar $
  *
  * Project:  USGS DOQ Driver (Second Generation Format)
  * Purpose:  Implementation of DOQ2Dataset
@@ -28,13 +28,14 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "rawdataset.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "rawdataset.h"
 
-CPL_CVSID("$Id: doq2dataset.cpp 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: doq2dataset.cpp 33673 2016-03-07 20:40:54Z goatbar $");
 
 CPL_C_START
-void	GDALRegister_DOQ2(void);
+void GDALRegister_DOQ2();
 CPL_C_END
 
 #define UTM_FORMAT \
@@ -61,7 +62,7 @@ CPL_C_END
 class DOQ2Dataset : public RawDataset
 {
     VSILFILE	*fpImage;	// image data file.
-    
+
     double	dfULX, dfULY;
     double	dfXPixelSize, dfYPixelSize;
 
@@ -73,7 +74,7 @@ class DOQ2Dataset : public RawDataset
 
     CPLErr 	GetGeoTransform( double * padfTransform );
     const char  *GetProjectionRef( void );
-    
+
     static GDALDataset *Open( GDALOpenInfo * );
 };
 
@@ -81,11 +82,14 @@ class DOQ2Dataset : public RawDataset
 /*                            DOQ2Dataset()                             */
 /************************************************************************/
 
-DOQ2Dataset::DOQ2Dataset()
-{
-    pszProjection = NULL;
-    fpImage = NULL;
-}
+DOQ2Dataset::DOQ2Dataset() :
+    fpImage(NULL),
+    dfULX(0.0),
+    dfULY(0.0),
+    dfXPixelSize(0.0),
+    dfYPixelSize(0.0),
+    pszProjection(NULL)
+{ }
 
 /************************************************************************/
 /*                            ~DOQ2Dataset()                            */
@@ -98,7 +102,7 @@ DOQ2Dataset::~DOQ2Dataset()
 
     CPLFree( pszProjection );
     if( fpImage != NULL )
-        VSIFCloseL( fpImage );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fpImage ));
 }
 
 /************************************************************************/
@@ -114,7 +118,7 @@ CPLErr DOQ2Dataset::GetGeoTransform( double * padfTransform )
     padfTransform[3] = dfULY;
     padfTransform[4] = 0.0;
     padfTransform[5] = -1 * dfYPixelSize;
-    
+
     return( CE_None );
 }
 
@@ -135,39 +139,37 @@ const char *DOQ2Dataset::GetProjectionRef()
 GDALDataset *DOQ2Dataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    int		nWidth=0, nHeight=0, nBandStorage=0, nBandTypes=0;
-    
 /* -------------------------------------------------------------------- */
-/*	We assume the user is pointing to the binary (ie. .bil) file.	*/
+/*      We assume the user is pointing to the binary (i.e. .bil) file.  */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->nHeaderBytes < 212 )
         return NULL;
 
-    int         nLineCount = 0;
-    const char *pszLine;
-    int		nBytesPerPixel=0;
-    const char *pszDatumLong=NULL, *pszDatumShort=NULL;
-    const char *pszUnits=NULL;
-    char *pszQuadname = NULL;
-    char *pszQuadquad = NULL;
-    char *pszState = NULL;
-    int	        nZone=0, nProjType=0;
-    int		nSkipBytes=0, nBytesPerLine, i, nBandCount = 0;
-    double      dfULXMap=0.0, dfULYMap = 0.0;
-    double      dfXDim=0.0, dfYDim=0.0;
-    char	**papszMetadata = NULL;
-
-    if(! EQUALN((const char *) poOpenInfo->pabyHeader,
-                "BEGIN_USGS_DOQ_HEADER", 21) )
+    if(! STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "BEGIN_USGS_DOQ_HEADER") )
         return NULL;
 
     VSILFILE* fp = VSIFOpenL(poOpenInfo->pszFilename, "rb");
     if (fp == NULL)
         return NULL;
 
+    int nLineCount = 0;
+    int	nBytesPerPixel=0;
+    int nWidth=0, nHeight=0, nBandStorage=0, nBandTypes=0;
+    const char *pszDatumLong=NULL, *pszDatumShort=NULL;
+    const char *pszUnits=NULL;
+    char *pszQuadname = NULL;
+    char *pszQuadquad = NULL;
+    char *pszState = NULL;
+    int nZone=0, nProjType=0;
+    int nSkipBytes=0, nBandCount = 0;
+    double dfULXMap=0.0, dfULYMap = 0.0;
+    double dfXDim=0.0, dfYDim=0.0;
+    char **papszMetadata = NULL;
+
     /* read and discard the first line */
-    pszLine = CPLReadLineL( fp );
+    CPL_IGNORE_RET_VAL(CPLReadLineL( fp ));
 
+    const char *pszLine;
     while( (pszLine = CPLReadLineL( fp )) != NULL )
     {
 	char    **papszTokens;
@@ -183,7 +185,7 @@ GDALDataset *DOQ2Dataset::Open( GDALOpenInfo * poOpenInfo )
             CSLDestroy( papszTokens );
             break;
         }
-        
+
         if( EQUAL(papszTokens[0],"SAMPLES_AND_LINES") && CSLCount(papszTokens) >= 3 )
         {
             nWidth = atoi(papszTokens[1]);
@@ -236,11 +238,11 @@ GDALDataset *DOQ2Dataset::Open( GDALOpenInfo * poOpenInfo )
         }
         else if( EQUAL(papszTokens[0],"HORIZONTAL_COORDINATE_SYSTEM") )
         {
-	    if( EQUAL(papszTokens[1],"UTM") ) 
+	    if( EQUAL(papszTokens[1],"UTM") )
                 nProjType = 1;
-	    else if( EQUAL(papszTokens[1],"SPCS") ) 
+	    else if( EQUAL(papszTokens[1],"SPCS") )
                 nProjType = 2;
-	    else if( EQUAL(papszTokens[1],"GEOGRAPHIC") ) 
+	    else if( EQUAL(papszTokens[1],"GEOGRAPHIC") )
                 nProjType = 0;
         }
         else if( EQUAL(papszTokens[0],"COORDINATE_ZONE") )
@@ -256,22 +258,22 @@ GDALDataset *DOQ2Dataset::Open( GDALOpenInfo * poOpenInfo )
         }
         else if( EQUAL(papszTokens[0],"HORIZONTAL_DATUM") )
         {
-	    if( EQUAL(papszTokens[1],"NAD27") ) 
+	    if( EQUAL(papszTokens[1],"NAD27") )
             {
 		pszDatumLong = NAD27_DATUM;
 		pszDatumShort = "NAD 27";
             }
-	    else if( EQUAL(papszTokens[1],"WGS72") ) 
+	    else if( EQUAL(papszTokens[1],"WGS72") )
             {
 		pszDatumLong = WGS72_DATUM;
 		pszDatumShort = "WGS 72";
             }
-	    else if( EQUAL(papszTokens[1],"WGS84") ) 
+	    else if( EQUAL(papszTokens[1],"WGS84") )
             {
 		pszDatumLong = WGS84_DATUM;
 		pszDatumShort = "WGS 84";
             }
-	    else if( EQUAL(papszTokens[1],"NAD83") ) 
+	    else if( EQUAL(papszTokens[1],"NAD83") )
             {
 		pszDatumLong = NAD83_DATUM;
 		pszDatumShort = "NAD 83";
@@ -281,7 +283,7 @@ GDALDataset *DOQ2Dataset::Open( GDALOpenInfo * poOpenInfo )
 		pszDatumLong = "DATUM[\"unknown\"]";
 		pszDatumShort = "unknown";
             }
-        }    
+        }
         else
         {
             /* we want to generically capture all the other metadata */
@@ -297,11 +299,11 @@ GDALDataset *DOQ2Dataset::Open( GDALOpenInfo * poOpenInfo )
                     osMetaDataValue += " " ;
                 osMetaDataValue += papszTokens[iToken];
             }
-            papszMetadata = CSLAddNameValue( papszMetadata, 
-                                             papszTokens[0], 
+            papszMetadata = CSLAddNameValue( papszMetadata,
+                                             papszTokens[0],
                                              osMetaDataValue );
         }
-	
+
         CSLDestroy( papszTokens );
     }
 
@@ -317,7 +319,7 @@ GDALDataset *DOQ2Dataset::Open( GDALOpenInfo * poOpenInfo )
         || nBandTypes < 1 || nBandTypes > 9 )
     {
         CSLDestroy( papszMetadata );
-        VSIFCloseL(fp);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
         return NULL;
     }
 
@@ -331,28 +333,26 @@ GDALDataset *DOQ2Dataset::Open( GDALOpenInfo * poOpenInfo )
                   "DOQ Data Type (%d) is not a supported configuration.\n",
                   nBandTypes );
         CSLDestroy( papszMetadata );
-        VSIFCloseL(fp);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
         CSLDestroy( papszMetadata );
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The DOQ2 driver does not support update access to existing"
                   " datasets.\n" );
-        VSIFCloseL(fp);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
         return NULL;
     }
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    DOQ2Dataset 	*poDS;
-
-    poDS = new DOQ2Dataset();
+    DOQ2Dataset *poDS = new DOQ2Dataset();
 
     poDS->nRasterXSize = nWidth;
     poDS->nRasterYSize = nHeight;
@@ -370,26 +370,37 @@ GDALDataset *DOQ2Dataset::Open( GDALOpenInfo * poOpenInfo )
     else
         nBytesPerPixel *= nBandCount;
 
-    nBytesPerLine = nBytesPerPixel * nWidth;
-    
+    const int nBytesPerLine = nBytesPerPixel * nWidth;
+
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < nBandCount; i++ )
+    CPLErrorReset();
+    for( int i = 0; i < nBandCount; i++ )
     {
-        poDS->SetBand( i+1, 
+        poDS->SetBand( i+1,
             new RawRasterBand( poDS, i+1, poDS->fpImage,
                                nSkipBytes + i, nBytesPerPixel, nBytesPerLine,
                                GDT_Byte, TRUE, TRUE ) );
+        if( CPLGetLastErrorType() != CE_None )
+        {
+            delete poDS;
+            CPLFree( pszQuadname );
+            CPLFree( pszQuadquad );
+            CPLFree( pszState );
+            return NULL;
+        }
     }
 
     if (nProjType == 1)
     {
-	poDS->pszProjection = 
-            CPLStrdup(CPLSPrintf( UTM_FORMAT, pszDatumShort, nZone, 
-                                  pszDatumLong, nZone * 6 - 183, pszUnits ));
-    } 
-    else 
+	poDS->pszProjection =
+            CPLStrdup(CPLSPrintf( UTM_FORMAT, pszDatumShort ? pszDatumShort : "", nZone,
+                                  pszDatumLong ? pszDatumLong : "",
+                                  (nZone >= 1 && nZone <= 60) ? nZone * 6 - 183 : 0,
+                                  pszUnits ? pszUnits : ""));
+    }
+    else
     {
 	poDS->pszProjection = CPLStrdup("");
     }
@@ -400,9 +411,9 @@ GDALDataset *DOQ2Dataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->dfXPixelSize = dfXDim;
     poDS->dfYPixelSize = dfYDim;
 
-    if ( pszQuadname ) CPLFree( pszQuadname );
-    if ( pszQuadquad) CPLFree( pszQuadquad );
-    if ( pszState) CPLFree( pszState );
+    CPLFree( pszQuadname );
+    CPLFree( pszQuadquad );
+    CPLFree( pszState );
 
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
@@ -425,23 +436,18 @@ GDALDataset *DOQ2Dataset::Open( GDALOpenInfo * poOpenInfo )
 void GDALRegister_DOQ2()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "DOQ2" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "DOQ2" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "DOQ2" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "USGS DOQ (New Style)" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#DOQ2" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = DOQ2Dataset::Open;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
-}
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "DOQ2" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "USGS DOQ (New Style)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#DOQ2" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
+    poDriver->pfnOpen = DOQ2Dataset::Open;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/frmts/raw/ehdrdataset.cpp b/frmts/raw/ehdrdataset.cpp
index bdf669d..ecc054f 100644
--- a/frmts/raw/ehdrdataset.cpp
+++ b/frmts/raw/ehdrdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ehdrdataset.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: ehdrdataset.cpp 33825 2016-03-31 13:55:56Z goatbar $
  *
  * Project:  ESRI .hdr Driver
  * Purpose:  Implementation of EHdrDataset
@@ -28,25 +28,23 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "rawdataset.h"
-#include "ogr_spatialref.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "ogr_spatialref.h"
+#include "rawdataset.h"
 
-CPL_CVSID("$Id: ehdrdataset.cpp 28053 2014-12-04 09:31:07Z rouault $");
-
-CPL_C_START
-void	GDALRegister_EHdr(void);
-CPL_C_END
+CPL_CVSID("$Id: ehdrdataset.cpp 33825 2016-03-31 13:55:56Z goatbar $");
 
-#define HAS_MIN_FLAG    0x1
-#define HAS_MAX_FLAG    0x2
-#define HAS_MEAN_FLAG   0x4
-#define HAS_STDDEV_FLAG 0x8
-#define HAS_ALL_FLAGS   (HAS_MIN_FLAG | HAS_MAX_FLAG | HAS_MEAN_FLAG | HAS_STDDEV_FLAG)
+static const int HAS_MIN_FLAG = 0x1;
+static const int HAS_MAX_FLAG = 0x2;
+static const int HAS_MEAN_FLAG = 0x4;
+static const int HAS_STDDEV_FLAG = 0x8;
+static const int HAS_ALL_FLAGS =
+    HAS_MIN_FLAG | HAS_MAX_FLAG | HAS_MEAN_FLAG | HAS_STDDEV_FLAG;
 
 /************************************************************************/
 /* ==================================================================== */
-/*				EHdrDataset				*/
+/*                       EHdrDataset                                    */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -56,7 +54,7 @@ class EHdrDataset : public RawDataset
 {
     friend class EHdrRasterBand;
 
-    VSILFILE	*fpImage;	// image data file.
+    VSILFILE   *fpImage;  // image data file.
 
     CPLString   osHeaderExt;
 
@@ -78,21 +76,21 @@ class EHdrDataset : public RawDataset
 
   public:
     EHdrDataset();
-    ~EHdrDataset();
-    
+    virtual ~EHdrDataset();
+
     virtual CPLErr GetGeoTransform( double * padfTransform );
     virtual CPLErr SetGeoTransform( double *padfTransform );
     virtual const char *GetProjectionRef(void);
     virtual CPLErr SetProjection( const char * );
-    
+
     virtual char **GetFileList();
 
     static GDALDataset *Open( GDALOpenInfo * );
     static GDALDataset *Create( const char * pszFilename,
                                 int nXSize, int nYSize, int nBands,
                                 GDALDataType eType, char ** papszParmList );
-    static GDALDataset *CreateCopy( const char * pszFilename, 
-                                    GDALDataset * poSrcDS, 
+    static GDALDataset *CreateCopy( const char * pszFilename,
+                                    GDALDataset * poSrcDS,
                                     int bStrict, char ** papszOptions,
                                     GDALProgressFunc pfnProgress,
                                     void * pProgressData );
@@ -110,9 +108,9 @@ class EHdrRasterBand : public RawRasterBand
    friend class EHdrDataset;
 
     int            nBits;
-    long           nStartBit;
+    vsi_l_offset   nStartBit;
     int            nPixelOffsetBits;
-    int            nLineOffsetBits;
+    vsi_l_offset   nLineOffsetBits;
 
     int            bNoDataSet;
     double         dfNoData;
@@ -135,6 +133,7 @@ class EHdrRasterBand : public RawRasterBand
                     int nLineOffset,
                     GDALDataType eDataType, int bNativeOrder,
                     int nBits);
+    virtual ~EHdrRasterBand() {}
 
     virtual CPLErr IReadBlock( int, int, void * );
     virtual CPLErr IWriteBlock( int, int, void * );
@@ -143,9 +142,9 @@ class EHdrRasterBand : public RawRasterBand
     virtual double GetMinimum( int *pbSuccess = NULL );
     virtual double GetMaximum(int *pbSuccess = NULL );
     virtual CPLErr GetStatistics( int bApproxOK, int bForce,
-                                  double *pdfMin, double *pdfMax, 
+                                  double *pdfMin, double *pdfMax,
                                   double *pdfMean, double *pdfStdDev );
-    virtual CPLErr SetStatistics( double dfMin, double dfMax, 
+    virtual CPLErr SetStatistics( double dfMin, double dfMax,
                                   double dfMean, double dfStdDev );
     virtual CPLErr SetColorTable( GDALColorTable *poNewCT );
 
@@ -155,49 +154,88 @@ class EHdrRasterBand : public RawRasterBand
 /*                           EHdrRasterBand()                           */
 /************************************************************************/
 
-EHdrRasterBand::EHdrRasterBand( GDALDataset *poDS,
-                                int nBand, VSILFILE * fpRaw,
-                                vsi_l_offset nImgOffset, int nPixelOffset,
-                                int nLineOffset,
-                                GDALDataType eDataType, int bNativeOrder,
-                                int nBits)
-: RawRasterBand( poDS, nBand, fpRaw, nImgOffset, nPixelOffset, nLineOffset, 
-                         eDataType, bNativeOrder, TRUE ),
-  nBits(nBits),
+EHdrRasterBand::EHdrRasterBand( GDALDataset *poDSIn,
+                                int nBandIn, VSILFILE * fpRawIn,
+                                vsi_l_offset nImgOffsetIn, int nPixelOffsetIn,
+                                int nLineOffsetIn,
+                                GDALDataType eDataTypeIn, int bNativeOrderIn,
+                                int nBitsIn) :
+  RawRasterBand( poDSIn, nBandIn, fpRawIn, nImgOffsetIn, nPixelOffsetIn,
+                 nLineOffsetIn, eDataTypeIn, bNativeOrderIn, TRUE ),
+  nBits(nBitsIn),
+  nStartBit(0),
+  nPixelOffsetBits(0),
+  nLineOffsetBits(0),
   bNoDataSet(FALSE),
-  dfNoData(0),
-  dfMin(0),
-  dfMax(0),
+  dfNoData(0.0),
+  dfMin(0.0),
+  dfMax(0.0),
+  dfMean(0.0),
+  dfStdDev(0.0),
   minmaxmeanstddev(0)
 {
-    EHdrDataset* poEDS = (EHdrDataset*)poDS;
+    EHdrDataset* poEDS = reinterpret_cast<EHdrDataset *>( poDS );
 
     if (nBits < 8)
     {
-        nStartBit = atoi(poEDS->GetKeyValue("SKIPBYTES")) * 8;
+        int nSkipBytes = atoi(poEDS->GetKeyValue("SKIPBYTES"));
+        if( nSkipBytes < 0 || nSkipBytes > INT_MAX / 8 )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Invalid SKIPBYTES: %d", nSkipBytes);
+            nStartBit = 0;
+        }
+        else
+        {
+            nStartBit = nSkipBytes * 8;
+        }
         if (nBand >= 2)
         {
-            long nRowBytes = atoi(poEDS->GetKeyValue("BANDROWBYTES"));
-            if (nRowBytes == 0)
-                nRowBytes = (nBits * poDS->GetRasterXSize() + 7) / 8;
+            GIntBig nBandRowBytes =
+                CPLAtoGIntBig(poEDS->GetKeyValue("BANDROWBYTES"));
+            if( nBandRowBytes < 0 )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Invalid BANDROWBYTES: " CPL_FRMT_GIB,
+                          nBandRowBytes );
+                nBandRowBytes = 0;
+            }
+            vsi_l_offset nRowBytes = 0;
+            if (nBandRowBytes == 0)
+                nRowBytes =
+                    (static_cast<vsi_l_offset>(nBits) *
+                     poDS->GetRasterXSize() + 7) / 8;
+            else
+                nRowBytes = static_cast<vsi_l_offset>(nBandRowBytes);
 
             nStartBit += nRowBytes * (nBand-1) * 8;
         }
 
         nPixelOffsetBits = nBits;
-        nLineOffsetBits = atoi(poEDS->GetKeyValue("TOTALROWBYTES")) * 8;
-        if( nLineOffsetBits == 0 )
-            nLineOffsetBits = nPixelOffsetBits * poDS->GetRasterXSize();
+        GIntBig nTotalRowBytes =
+            CPLAtoGIntBig(poEDS->GetKeyValue("TOTALROWBYTES"));
+        if( nTotalRowBytes < 0 )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Invalid TOTALROWBYTES: " CPL_FRMT_GIB, nTotalRowBytes);
+            nTotalRowBytes = 0;
+        }
+        if( nTotalRowBytes > 0 )
+            nLineOffsetBits = static_cast<vsi_l_offset>(nTotalRowBytes * 8);
+        else
+            nLineOffsetBits =
+                static_cast<vsi_l_offset>(nPixelOffsetBits) *
+                poDS->GetRasterXSize();
 
         nBlockXSize = poDS->GetRasterXSize();
         nBlockYSize = 1;
 
-        SetMetadataItem( "NBITS", 
+        SetMetadataItem( "NBITS",
                          CPLString().Printf( "%d", nBits ),
                          "IMAGE_STRUCTURE" );
     }
 
-    if( eDataType == GDT_Byte 
+    if( eDataType == GDT_Byte
         && EQUAL(poEDS->GetKeyValue("PIXELTYPE",""),"SIGNEDINT") )
         SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE",
                          "IMAGE_STRUCTURE" );
@@ -214,30 +252,33 @@ CPLErr EHdrRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     if (nBits >= 8)
       return RawRasterBand::IReadBlock(nBlockXOff, nBlockYOff, pImage);
 
-    vsi_l_offset   nLineStart;
-    unsigned int   nLineBytes;
-    int            iBitOffset;
-    GByte         *pabyBuffer;
-
 /* -------------------------------------------------------------------- */
 /*      Establish desired position.                                     */
 /* -------------------------------------------------------------------- */
-    nLineBytes = (nPixelOffsetBits*nBlockXSize + 7)/8;
-    nLineStart = (nStartBit + ((vsi_l_offset)nLineOffsetBits) * nBlockYOff) / 8;
-    iBitOffset = (int)
-      ((nStartBit + ((vsi_l_offset)nLineOffsetBits) * nBlockYOff) % 8);
+    const vsi_l_offset nLineBytesBig =
+        (static_cast<vsi_l_offset>(nPixelOffsetBits)*nBlockXSize + 7) / 8;
+    if( nLineBytesBig > INT_MAX )
+        return CE_Failure;
+    const unsigned int nLineBytes = static_cast<unsigned int>(nLineBytesBig);
+    const vsi_l_offset nLineStart =
+        (nStartBit + nLineOffsetBits * nBlockYOff) / 8;
+    int iBitOffset = static_cast<int>(
+        (nStartBit + nLineOffsetBits * nBlockYOff) % 8);
 
 /* -------------------------------------------------------------------- */
 /*      Read data into buffer.                                          */
 /* -------------------------------------------------------------------- */
-    pabyBuffer = (GByte *) CPLCalloc(nLineBytes,1);
+    GByte *pabyBuffer =
+        static_cast<GByte *>( VSI_MALLOC_VERBOSE(nLineBytes) );
+    if( pabyBuffer == NULL )
+        return CE_Failure;
 
     if( VSIFSeekL( GetFPL(), nLineStart, SEEK_SET ) != 0
         || VSIFReadL( pabyBuffer, 1, nLineBytes, GetFPL() ) != nLineBytes )
     {
         CPLError( CE_Failure, CPLE_FileIO,
                   "Failed to read %u bytes at offset %lu.\n%s",
-                  nLineBytes, (unsigned long)nLineStart, 
+                  nLineBytes, static_cast<unsigned long>(nLineStart),
                   VSIStrerror( errno ) );
         CPLFree( pabyBuffer );
         return CE_Failure;
@@ -246,22 +287,21 @@ CPLErr EHdrRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
 /*      Copy data, promoting to 8bit.                                   */
 /* -------------------------------------------------------------------- */
-    int iPixel = 0, iX;
-
-    for( iX = 0; iX < nBlockXSize; iX++ )
+    for( int iX = 0, iPixel = 0; iX < nBlockXSize; iX++ )
     {
-        int  nOutWord = 0, iBit;
+        int nOutWord = 0;
 
-        for( iBit = 0; iBit < nBits; iBit++ )
+        for( int iBit = 0; iBit < nBits; iBit++ )
         {
             if( pabyBuffer[iBitOffset>>3]  & (0x80 >>(iBitOffset & 7)) )
                 nOutWord |= (1 << (nBits - 1 - iBit));
             iBitOffset++;
-        } 
+        }
 
         iBitOffset = iBitOffset + nPixelOffsetBits - nBits;
-                
-        ((GByte *) pImage)[iPixel++] = (GByte) nOutWord;
+
+        reinterpret_cast<GByte *>( pImage )[iPixel++]
+            = static_cast<GByte>( nOutWord );
     }
 
     CPLFree( pabyBuffer );
@@ -274,53 +314,53 @@ CPLErr EHdrRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /************************************************************************/
 
 CPLErr EHdrRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
-                                   void * pImage )
+                                    void * pImage )
 
 {
     if (nBits >= 8)
       return RawRasterBand::IWriteBlock(nBlockXOff, nBlockYOff, pImage);
 
-    vsi_l_offset   nLineStart;
-    unsigned int   nLineBytes;
-    int            iBitOffset;
-    GByte         *pabyBuffer;
-
 /* -------------------------------------------------------------------- */
 /*      Establish desired position.                                     */
 /* -------------------------------------------------------------------- */
-    nLineBytes = (nPixelOffsetBits*nBlockXSize + 7)/8;
-    nLineStart = (nStartBit + ((vsi_l_offset)nLineOffsetBits) * nBlockYOff) / 8;
-    iBitOffset = (int) 
-      ((nStartBit + ((vsi_l_offset)nLineOffsetBits) * nBlockYOff) % 8);
+    const vsi_l_offset nLineBytesBig =
+        (static_cast<vsi_l_offset>(nPixelOffsetBits)*nBlockXSize + 7) / 8;
+    if( nLineBytesBig > INT_MAX )
+        return CE_Failure;
+    const unsigned int nLineBytes = static_cast<unsigned int>(nLineBytesBig);
+    const vsi_l_offset nLineStart =
+        (nStartBit + nLineOffsetBits * nBlockYOff) / 8;
+    int iBitOffset = static_cast<int>(
+        (nStartBit + nLineOffsetBits * nBlockYOff) % 8 );
 
 /* -------------------------------------------------------------------- */
 /*      Read data into buffer.                                          */
 /* -------------------------------------------------------------------- */
-    pabyBuffer = (GByte *) CPLCalloc(nLineBytes,1);
+    GByte *pabyBuffer =
+        static_cast<GByte *>( VSI_CALLOC_VERBOSE(nLineBytes, 1) );
+    if( pabyBuffer == NULL )
+        return CE_Failure;
 
     if( VSIFSeekL( GetFPL(), nLineStart, SEEK_SET ) != 0 )
     {
         CPLError( CE_Failure, CPLE_FileIO,
                   "Failed to read %u bytes at offset %lu.\n%s",
-                  nLineBytes, (unsigned long)nLineStart, 
+                  nLineBytes, static_cast<unsigned long>(nLineStart),
                   VSIStrerror( errno ) );
         CPLFree( pabyBuffer );
         return CE_Failure;
     }
 
-    VSIFReadL( pabyBuffer, 1, nLineBytes, GetFPL() );
+    CPL_IGNORE_RET_VAL(VSIFReadL( pabyBuffer, nLineBytes, 1, GetFPL() ));
 
 /* -------------------------------------------------------------------- */
 /*      Copy data, promoting to 8bit.                                   */
 /* -------------------------------------------------------------------- */
-    int iPixel = 0, iX;
-
-    for( iX = 0; iX < nBlockXSize; iX++ )
+    for( int iX = 0, iPixel = 0; iX < nBlockXSize; iX++ )
     {
-        int iBit;
-        int  nOutWord = ((GByte *) pImage)[iPixel++];
+        const int nOutWord = reinterpret_cast<GByte *>( pImage )[iPixel++];
 
-        for( iBit = 0; iBit < nBits; iBit++ )
+        for( int iBit = 0; iBit < nBits; iBit++ )
         {
             if( nOutWord & (1 << (nBits - 1 - iBit)) )
                 pabyBuffer[iBitOffset>>3] |= (0x80 >>(iBitOffset & 7));
@@ -328,7 +368,7 @@ CPLErr EHdrRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                 pabyBuffer[iBitOffset>>3] &= ~((0x80 >>(iBitOffset & 7)));
 
             iBitOffset++;
-        } 
+        }
 
         iBitOffset = iBitOffset + nPixelOffsetBits - nBits;
     }
@@ -341,7 +381,7 @@ CPLErr EHdrRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     {
         CPLError( CE_Failure, CPLE_FileIO,
                   "Failed to write %u bytes at offset %lu.\n%s",
-                  nLineBytes, (unsigned long)nLineStart, 
+                  nLineBytes, static_cast<unsigned long>(nLineStart),
                   VSIStrerror( errno ) );
         return CE_Failure;
     }
@@ -366,17 +406,18 @@ CPLErr EHdrRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 {
     // Defer to RawRasterBand
     if (nBits >= 8)
-        return RawRasterBand::IRasterIO( eRWFlag, 
+        return RawRasterBand::IRasterIO( eRWFlag,
                                          nXOff, nYOff, nXSize, nYSize,
-                                         pData, nBufXSize, nBufYSize, 
-                                         eBufType, nPixelSpace, nLineSpace, psExtraArg );
+                                         pData, nBufXSize, nBufYSize,
+                                         eBufType, nPixelSpace, nLineSpace,
+                                         psExtraArg );
 
     // Force use of IReadBlock() and IWriteBlock()
-    else
-        return GDALRasterBand::IRasterIO( eRWFlag, 
-                                          nXOff, nYOff, nXSize, nYSize,
-                                          pData, nBufXSize, nBufYSize, 
-                                          eBufType, nPixelSpace, nLineSpace, psExtraArg );
+    return GDALRasterBand::IRasterIO( eRWFlag,
+                                      nXOff, nYOff, nXSize, nYSize,
+                                      pData, nBufXSize, nBufYSize,
+                                      eBufType, nPixelSpace, nLineSpace,
+                                      psExtraArg );
 }
 
 /************************************************************************/
@@ -384,43 +425,38 @@ CPLErr EHdrRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 /************************************************************************/
 
 static const char*OSR_GDS( char* pszResult, int nResultLen,
-                           char **papszNV, const char * pszField, 
+                           char **papszNV, const char * pszField,
                            const char *pszDefaultValue )
 
 {
-    int         iLine;
-
     if( papszNV == NULL || papszNV[0] == NULL )
         return pszDefaultValue;
 
-    for( iLine = 0; 
-         papszNV[iLine] != NULL && 
+    int iLine = 0;  // Used after for.
+    for( ;
+         papszNV[iLine] != NULL &&
              !EQUALN(papszNV[iLine],pszField,strlen(pszField));
          iLine++ ) {}
 
     if( papszNV[iLine] == NULL )
         return pszDefaultValue;
+
+    char **papszTokens = CSLTokenizeString(papszNV[iLine]);
+
+    if( CSLCount(papszTokens) > 1 )
+        strncpy( pszResult, papszTokens[1], nResultLen);
     else
-    {
-        char    **papszTokens;
-        
-        papszTokens = CSLTokenizeString(papszNV[iLine]);
+        strncpy( pszResult, pszDefaultValue, nResultLen);
+    pszResult[nResultLen-1] = '\0';
 
-        if( CSLCount(papszTokens) > 1 )
-            strncpy( pszResult, papszTokens[1], nResultLen);
-        else
-            strncpy( pszResult, pszDefaultValue, nResultLen);
-        pszResult[nResultLen-1] = '\0';
-        
-        CSLDestroy( papszTokens );
-        return pszResult;
-    }
+    CSLDestroy( papszTokens );
+    return pszResult;
 }
 
 
 /************************************************************************/
 /* ==================================================================== */
-/*				EHdrDataset				*/
+/*                            EHdrDataset                               */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -428,21 +464,21 @@ static const char*OSR_GDS( char* pszResult, int nResultLen,
 /*                            EHdrDataset()                             */
 /************************************************************************/
 
-EHdrDataset::EHdrDataset()
+EHdrDataset::EHdrDataset() :
+    fpImage(NULL),
+    osHeaderExt("hdr"),
+    bGotTransform(FALSE),
+    pszProjection(CPLStrdup("")),
+    bHDRDirty(FALSE),
+    papszHDR(NULL),
+    bCLRDirty(FALSE)
 {
-    fpImage = NULL;
-    pszProjection = CPLStrdup("");
-    bGotTransform = FALSE;
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
-    papszHDR = NULL;
-    bHDRDirty = FALSE;
-    bCLRDirty = FALSE;
-    osHeaderExt = "hdr";
 }
 
 /************************************************************************/
@@ -457,13 +493,14 @@ EHdrDataset::~EHdrDataset()
     if( nBands > 0 && GetAccess() == GA_Update )
     {
         int bNoDataSet;
-        double dfNoData;
-        RawRasterBand *poBand = (RawRasterBand *) GetRasterBand( 1 );
+        RawRasterBand *poBand
+            = reinterpret_cast<RawRasterBand *>( GetRasterBand( 1 ) );
 
-        dfNoData = poBand->GetNoDataValue(&bNoDataSet);
+        const double dfNoData
+            = poBand->GetNoDataValue(&bNoDataSet);
         if( bNoDataSet )
         {
-            ResetKeyValue( "NODATA", 
+            ResetKeyValue( "NODATA",
                            CPLString().Printf( "%.8g", dfNoData ) );
         }
 
@@ -473,9 +510,14 @@ EHdrDataset::~EHdrDataset()
         if( bHDRDirty )
             RewriteHDR();
     }
-    
+
     if( fpImage != NULL )
-        VSIFCloseL( fpImage );
+    {
+        if( VSIFCloseL( fpImage ) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        }
+    }
 
     CPLFree( pszProjection );
     CSLDestroy( papszHDR );
@@ -485,13 +527,11 @@ EHdrDataset::~EHdrDataset()
 /*                            GetKeyValue()                             */
 /************************************************************************/
 
-const char *EHdrDataset::GetKeyValue( const char *pszKey, 
+const char *EHdrDataset::GetKeyValue( const char *pszKey,
                                       const char *pszDefault )
 
 {
-    int i;
-
-    for( i = 0; papszHDR[i] != NULL; i++ )
+    for( int i = 0; papszHDR[i] != NULL; i++ )
     {
         if( EQUALN(pszKey,papszHDR[i],strlen(pszKey))
             && isspace((unsigned char)papszHDR[i][strlen(pszKey)]) )
@@ -499,7 +539,7 @@ const char *EHdrDataset::GetKeyValue( const char *pszKey,
             const char *pszValue = papszHDR[i] + strlen(pszKey);
             while( isspace((unsigned char)*pszValue) )
                 pszValue++;
-            
+
             return pszValue;
         }
     }
@@ -517,20 +557,18 @@ const char *EHdrDataset::GetKeyValue( const char *pszKey,
 void EHdrDataset::ResetKeyValue( const char *pszKey, const char *pszValue )
 
 {
-    int i;
-    char szNewLine[82];
-
     if( strlen(pszValue) > 65 )
     {
         CPLAssert( strlen(pszValue) <= 65 );
         return;
     }
 
-    sprintf( szNewLine, "%-15s%s", pszKey, pszValue );
+  char szNewLine[82] = { '\0' };
+    snprintf( szNewLine, sizeof(szNewLine), "%-15s%s", pszKey, pszValue );
 
-    for( i = CSLCount(papszHDR)-1; i >= 0; i-- )
+    for( int i = CSLCount(papszHDR)-1; i >= 0; i-- )
     {
-        if( EQUALN(papszHDR[i],szNewLine,strlen(pszKey)+1 ) )
+        if( EQUALN(papszHDR[i], szNewLine, strlen(pszKey) + 1 ) )
         {
             if( strcmp(papszHDR[i],szNewLine) != 0 )
             {
@@ -559,24 +597,37 @@ void EHdrDataset::RewriteColorTable( GDALColorTable *poTable )
         VSILFILE *fp = VSIFOpenL( osCLRFilename, "wt" );
         if( fp != NULL )
         {
-            for( int iColor = 0; iColor < poTable->GetColorEntryCount(); iColor++ )
+            for( int iColor = 0;
+                 iColor < poTable->GetColorEntryCount();
+                 iColor++ )
             {
-                CPLString oLine;
                 GDALColorEntry sEntry;
-
                 poTable->GetColorEntryAsRGB( iColor, &sEntry );
 
                 // I wish we had a way to mark transparency.
+                CPLString oLine;
                 oLine.Printf( "%3d %3d %3d %3d\n",
                               iColor, sEntry.c1, sEntry.c2, sEntry.c3 );
-                VSIFWriteL( (void *) oLine.c_str(), 1, strlen(oLine), fp );
+                if( VSIFWriteL(
+                    reinterpret_cast<void *>(
+                        const_cast<char *>( oLine.c_str() ) ),
+                    strlen(oLine), 1, fp ) != 1 )
+                {
+                    CPLError( CE_Failure, CPLE_FileIO,
+                              "Error while write color table");
+                    CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
+                    return;
+                }
+            }
+            if( VSIFCloseL( fp ) != 0 )
+            {
+                CPLError(CE_Failure, CPLE_FileIO, "Error while write color table");
             }
-            VSIFCloseL( fp );
         }
         else
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
-                      "Unable to create color file %s.", 
+            CPLError( CE_Failure, CPLE_OpenFailed,
+                      "Unable to create color file %s.",
                       osCLRFilename.c_str() );
         }
     }
@@ -617,23 +668,28 @@ CPLErr EHdrDataset::SetProjection( const char *pszSRS )
 /*      Convert to ESRI WKT.                                            */
 /* -------------------------------------------------------------------- */
     OGRSpatialReference oSRS( pszSRS );
-    char *pszESRI_SRS = NULL;
-
     oSRS.morphToESRI();
+
+    char *pszESRI_SRS = NULL;
     oSRS.exportToWkt( &pszESRI_SRS );
 
 /* -------------------------------------------------------------------- */
 /*      Write to .prj file.                                             */
 /* -------------------------------------------------------------------- */
     CPLString osPrjFilename = CPLResetExtension( GetDescription(), "prj" );
-    VSILFILE *fp;
-
-    fp = VSIFOpenL( osPrjFilename.c_str(), "wt" );
+    VSILFILE *fp = VSIFOpenL( osPrjFilename.c_str(), "wt" );
     if( fp != NULL )
     {
-        VSIFWriteL( pszESRI_SRS, 1, strlen(pszESRI_SRS), fp );
-        VSIFWriteL( (void *) "\n", 1, 1, fp );
-        VSIFCloseL( fp );
+        size_t nCount = VSIFWriteL( pszESRI_SRS, strlen(pszESRI_SRS), 1, fp );
+        nCount += VSIFWriteL(
+            reinterpret_cast<void *>( const_cast<char *>( "\n" ) ),
+            1, 1, fp );
+        if( VSIFCloseL( fp ) != 0 ||
+            nCount != 2 )
+        {
+            CPLFree( pszESRI_SRS );
+            return CE_Failure;
+        }
     }
 
     CPLFree( pszESRI_SRS );
@@ -653,10 +709,8 @@ CPLErr EHdrDataset::GetGeoTransform( double * padfTransform )
         memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
         return CE_None;
     }
-    else
-    {
-        return GDALPamDataset::GetGeoTransform( padfTransform );
-    }
+
+    return GDALPamDataset::GetGeoTransform( padfTransform );
 }
 
 /************************************************************************/
@@ -669,8 +723,7 @@ CPLErr EHdrDataset::SetGeoTransform( double *padfGeoTransform )
 /* -------------------------------------------------------------------- */
 /*      We only support non-rotated images with info in the .HDR file.  */
 /* -------------------------------------------------------------------- */
-    if( padfGeoTransform[2] != 0.0 
-        || padfGeoTransform[4] != 0.0 )
+    if( padfGeoTransform[2] != 0.0 || padfGeoTransform[4] != 0.0 )
     {
         return GDALPamDataset::SetGeoTransform( padfGeoTransform );
     }
@@ -684,13 +737,12 @@ CPLErr EHdrDataset::SetGeoTransform( double *padfGeoTransform )
 /* -------------------------------------------------------------------- */
 /*      Strip out all old geotransform keywords from HDR records.       */
 /* -------------------------------------------------------------------- */
-    int i;
-    for( i = CSLCount(papszHDR)-1; i >= 0; i-- )
+    for( int i = CSLCount(papszHDR)-1; i >= 0; i-- )
     {
-        if( EQUALN(papszHDR[i],"ul",2)
-            || EQUALN(papszHDR[i]+1,"ll",2)
-            || EQUALN(papszHDR[i],"cell",4)
-            || EQUALN(papszHDR[i]+1,"dim",3) )
+        if( STARTS_WITH_CI(papszHDR[i], "ul")
+            || STARTS_WITH_CI(papszHDR[i]+1, "ll")
+            || STARTS_WITH_CI(papszHDR[i], "cell")
+            || STARTS_WITH_CI(papszHDR[i]+1, "dim") )
         {
             papszHDR = CSLRemoveStrings( papszHDR, i, 1, NULL );
         }
@@ -703,7 +755,7 @@ CPLErr EHdrDataset::SetGeoTransform( double *padfGeoTransform )
 
     oValue.Printf( "%.15g", adfGeoTransform[0] + adfGeoTransform[1] * 0.5 );
     ResetKeyValue( "ULXMAP", oValue );
-                   
+
     oValue.Printf( "%.15g", adfGeoTransform[3] + adfGeoTransform[5] * 0.5 );
     ResetKeyValue( "ULYMAP", oValue );
 
@@ -723,79 +775,87 @@ CPLErr EHdrDataset::SetGeoTransform( double *padfGeoTransform )
 CPLErr EHdrDataset::RewriteHDR()
 
 {
-    CPLString osPath = CPLGetPath( GetDescription() );
-    CPLString osName = CPLGetBasename( GetDescription() );
-    CPLString osHDRFilename = CPLFormCIFilename( osPath, osName, osHeaderExt );
+    const CPLString osPath = CPLGetPath( GetDescription() );
+    const CPLString osName = CPLGetBasename( GetDescription() );
+    const CPLString osHDRFilename = CPLFormCIFilename( osPath, osName, osHeaderExt );
 
 /* -------------------------------------------------------------------- */
 /*      Write .hdr file.                                                */
 /* -------------------------------------------------------------------- */
-    VSILFILE	*fp;
-    int i;
-
-    fp = VSIFOpenL( osHDRFilename, "wt" );
+    VSILFILE *fp = VSIFOpenL( osHDRFilename, "wt" );
 
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Failed to rewrite .hdr file %s.", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to rewrite .hdr file %s.",
                   osHDRFilename.c_str() );
         return CE_Failure;
     }
 
-    for( i = 0; papszHDR[i] != NULL; i++ )
+    for( int i = 0; papszHDR[i] != NULL; i++ )
     {
-        VSIFWriteL( papszHDR[i], 1, strlen(papszHDR[i]), fp );
-        VSIFWriteL( (void *) "\n", 1, 1, fp );
+        size_t nCount = VSIFWriteL( papszHDR[i], strlen(papszHDR[i]), 1, fp );
+        nCount += VSIFWriteL(
+            reinterpret_cast<void *>( const_cast<char *>( "\n" ) ),
+            1, 1, fp );
+        if( nCount != 2 )
+        {
+            CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
+            return CE_Failure;
+        }
     }
 
-    VSIFCloseL( fp );
-
     bHDRDirty = FALSE;
 
+    if( VSIFCloseL( fp ) != 0 )
+        return CE_Failure;
+
     return CE_None;
 }
 
 /************************************************************************/
 /*                             RewriteSTX()                             */
 /************************************************************************/
-    
+
 CPLErr EHdrDataset::RewriteSTX()
 {
-    CPLString osPath = CPLGetPath( GetDescription() );
-    CPLString osName = CPLGetBasename( GetDescription() );
-    CPLString osSTXFilename = CPLFormCIFilename( osPath, osName, "stx" );
+    const CPLString osPath = CPLGetPath( GetDescription() );
+    const CPLString osName = CPLGetBasename( GetDescription() );
+    const CPLString osSTXFilename = CPLFormCIFilename( osPath, osName, "stx" );
 
 /* -------------------------------------------------------------------- */
 /*      Write .stx file.                                                */
 /* -------------------------------------------------------------------- */
-    VSILFILE	*fp;
-    fp = VSIFOpenL( osSTXFilename, "wt" );
+    VSILFILE *fp = VSIFOpenL( osSTXFilename, "wt" );
     if( fp == NULL )
     {
-        CPLDebug( "EHDR", "Failed to rewrite .stx file %s.", 
+        CPLDebug( "EHDR", "Failed to rewrite .stx file %s.",
                   osSTXFilename.c_str() );
         return CE_Failure;
     }
 
-    for (int i = 0; i < nBands; ++i)
+    bool bOK = true;
+    for ( int i = 0; bOK && i < nBands; ++i )
     {
-        EHdrRasterBand* poBand = (EHdrRasterBand*)papoBands[i];
-        VSIFPrintfL( fp, "%d %.10f %.10f ", i+1, poBand->dfMin, poBand->dfMax );
+        EHdrRasterBand* poBand
+            = reinterpret_cast<EHdrRasterBand *>( papoBands[i] );
+        bOK &= VSIFPrintfL( fp, "%d %.10f %.10f ", i+1,
+                            poBand->dfMin, poBand->dfMax ) >= 0;
         if ( poBand->minmaxmeanstddev & HAS_MEAN_FLAG )
-            VSIFPrintfL( fp, "%.10f ", poBand->dfMean);
+            bOK &= VSIFPrintfL( fp, "%.10f ", poBand->dfMean) >= 0;
         else
-            VSIFPrintfL( fp, "# ");
+            bOK &= VSIFPrintfL( fp, "# ") >= 0;
 
         if ( poBand->minmaxmeanstddev & HAS_STDDEV_FLAG )
-            VSIFPrintfL( fp, "%.10f\n", poBand->dfStdDev);
+            bOK &= VSIFPrintfL( fp, "%.10f\n", poBand->dfStdDev) >= 0;
         else
-            VSIFPrintfL( fp, "#\n");
+            bOK &= VSIFPrintfL( fp, "#\n") >= 0;
     }
 
-    VSIFCloseL( fp );
+    if( VSIFCloseL( fp ) != 0 )
+        bOK = false;
 
-    return CE_None;
+    return bOK ? CE_None : CE_Failure;
 }
 
 /************************************************************************/
@@ -804,46 +864,49 @@ CPLErr EHdrDataset::RewriteSTX()
 
 CPLErr EHdrDataset::ReadSTX()
 {
-    CPLString osPath = CPLGetPath( GetDescription() );
-    CPLString osName = CPLGetBasename( GetDescription() );
-    CPLString osSTXFilename = CPLFormCIFilename( osPath, osName, "stx" );
+    const CPLString osPath = CPLGetPath( GetDescription() );
+    const CPLString osName = CPLGetBasename( GetDescription() );
+    const CPLString osSTXFilename = CPLFormCIFilename( osPath, osName, "stx" );
 
 /* -------------------------------------------------------------------- */
 /*      Read .stx file.                                                 */
 /* -------------------------------------------------------------------- */
-    VSILFILE	*fp;
-    if ((fp = VSIFOpenL( osSTXFilename, "rt" )) != NULL)
+    VSILFILE *fp = VSIFOpenL( osSTXFilename, "rt" );
+    if (fp == NULL)
+        return CE_None;
+
+    const char *pszLine = NULL;
+    while( (pszLine = CPLReadLineL( fp )) != NULL )
     {
-      const char *	pszLine;
-      while( (pszLine = CPLReadLineL( fp )) != NULL )
-      {
-          char	**papszTokens;
-          papszTokens = CSLTokenizeStringComplex( pszLine, " \t", TRUE, FALSE );
-          int nTokens = CSLCount( papszTokens );
-          if( nTokens >= 5 )
-          {
-            int i = atoi(papszTokens[0]);
+        char **papszTokens =
+            CSLTokenizeStringComplex( pszLine, " \t", TRUE, FALSE );
+        const int nTokens = CSLCount( papszTokens );
+        if( nTokens >= 5 )
+        {
+            const int i = atoi(papszTokens[0]);
             if (i > 0 && i <= nBands)
             {
-              EHdrRasterBand* poBand = (EHdrRasterBand*)papoBands[i-1];
+              EHdrRasterBand* poBand
+                  = reinterpret_cast<EHdrRasterBand *>( papoBands[i-1] );
               poBand->dfMin = CPLAtof(papszTokens[1]);
               poBand->dfMax = CPLAtof(papszTokens[2]);
 
               int bNoDataSet = FALSE;
-              double dfNoData = poBand->GetNoDataValue(&bNoDataSet);
+              const double dfNoData = poBand->GetNoDataValue(&bNoDataSet);
               if (bNoDataSet && dfNoData == poBand->dfMin)
               {
-                  /* Triggered by /vsicurl/http://eros.usgs.gov/archive/nslrsda/GeoTowns/HongKong/srtm/n22e113.zip/n22e113.bil */
-                  CPLDebug("EHDr", "Ignoring .stx file where min == nodata. "
-                           "The nodata value shouldn't be taken into account "
-                           "in minimum value computation.");
+                  // Triggered by
+                  // /vsicurl/http://eros.usgs.gov/archive/nslrsda/GeoTowns/HongKong/srtm/n22e113.zip/n22e113.bil
+                  CPLDebug( "EHDr", "Ignoring .stx file where min == nodata. "
+                            "The nodata value should not be taken into account "
+                            "in minimum value computation.");
                   CSLDestroy( papszTokens );
                   papszTokens = NULL;
                   break;
               }
 
               poBand->minmaxmeanstddev = HAS_MIN_FLAG | HAS_MAX_FLAG;
-              // reads optional mean and stddev
+              // Reads optional mean and stddev.
               if ( !EQUAL(papszTokens[3], "#") )
               {
                 poBand->dfMean   = CPLAtof(papszTokens[3]);
@@ -856,19 +919,20 @@ CPLErr EHdrDataset::ReadSTX()
               }
 
               if( nTokens >= 6 && !EQUAL(papszTokens[5], "#") )
-                poBand->SetMetadataItem( "STRETCHMIN", papszTokens[5], "RENDERING_HINTS" );
+                poBand->SetMetadataItem(
+                  "STRETCHMIN", papszTokens[5], "RENDERING_HINTS" );
 
               if( nTokens >= 7 && !EQUAL(papszTokens[6], "#") )
-                poBand->SetMetadataItem( "STRETCHMAX", papszTokens[6], "RENDERING_HINTS" );
+                poBand->SetMetadataItem(
+                  "STRETCHMAX", papszTokens[6], "RENDERING_HINTS" );
             }
           }
 
           CSLDestroy( papszTokens );
-      }
-
-      VSIFCloseL( fp );
     }
 
+    CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
+
     return CE_None;
 }
 
@@ -886,20 +950,23 @@ CPLErr EHdrDataset::ReadSTX()
 
 CPLString EHdrDataset::GetImageRepFilename(const char* pszFilename)
 {
-    VSIStatBufL sStatBuf;
 
-    CPLString osPath = CPLGetPath( pszFilename );
-    CPLString osName = CPLGetBasename( pszFilename );
-    CPLString osREPFilename =
+    const CPLString osPath = CPLGetPath( pszFilename );
+    const CPLString osName = CPLGetBasename( pszFilename );
+    const CPLString osREPFilename =
         CPLFormCIFilename( osPath, osName, "rep" );
-    if( VSIStatExL( osREPFilename.c_str(), &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 )
+
+    VSIStatBufL sStatBuf;
+    if( VSIStatExL(
+            osREPFilename.c_str(), &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 )
         return osREPFilename;
 
     if (EQUAL(CPLGetFilename(pszFilename), "imspatio.bil") ||
         EQUAL(CPLGetFilename(pszFilename), "haspatio.bil"))
     {
         CPLString osImageRepFilename(CPLFormCIFilename( osPath, "image", "rep" ));
-        if( VSIStatExL( osImageRepFilename.c_str(), &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 )
+        if( VSIStatExL(
+                osImageRepFilename.c_str(), &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 )
             return osImageRepFilename;
 
         /* Try in the upper directories if not found in the BIL image directory */
@@ -913,14 +980,18 @@ CPLString EHdrDataset::GetImageRepFilename(const char* pszFilename)
                 CPLFree(cwd);
             }
         }
-        while (dirName[0] != 0 && EQUAL(dirName, ".") == FALSE && EQUAL(dirName, "/") == FALSE)
+        while( dirName[0] != 0 && EQUAL(dirName, ".") == FALSE &&
+               EQUAL(dirName, "/") == FALSE )
         {
-            osImageRepFilename = CPLFormCIFilename( dirName.c_str(), "image", "rep" );
-            if( VSIStatExL( osImageRepFilename.c_str(), &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 )
+            osImageRepFilename =
+                CPLFormCIFilename( dirName.c_str(), "image", "rep" );
+            if( VSIStatExL(
+                    osImageRepFilename.c_str(), &sStatBuf,
+                    VSI_STAT_EXISTS_FLAG ) == 0 )
                 return osImageRepFilename;
 
             /* Don't try to recurse above the 'image' subdirectory */
-            if (EQUAL(dirName, "image"))
+            if( EQUAL(dirName, "image") )
             {
                 break;
             }
@@ -937,13 +1008,11 @@ CPLString EHdrDataset::GetImageRepFilename(const char* pszFilename)
 char **EHdrDataset::GetFileList()
 
 {
-    VSIStatBufL sStatBuf;
-    CPLString osPath = CPLGetPath( GetDescription() );
-    CPLString osName = CPLGetBasename( GetDescription() );
-    char **papszFileList = NULL;
+    const CPLString osPath = CPLGetPath( GetDescription() );
+    const CPLString osName = CPLGetBasename( GetDescription() );
 
-    // Main data file, etc. 
-    papszFileList = GDALPamDataset::GetFileList();
+    // Main data file, etc.
+    char **papszFileList = GDALPamDataset::GetFileList();
 
     // Header file.
     CPLString osFilename = CPLFormCIFilename( osPath, osName, osHeaderExt );
@@ -951,23 +1020,24 @@ char **EHdrDataset::GetFileList()
 
     // Statistics file
     osFilename = CPLFormCIFilename( osPath, osName, "stx" );
+    VSIStatBufL sStatBuf;
     if( VSIStatExL( osFilename, &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 )
         papszFileList = CSLAddString( papszFileList, osFilename );
-    
+
     // color table file.
     osFilename = CPLFormCIFilename( osPath, osName, "clr" );
     if( VSIStatExL( osFilename, &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 )
         papszFileList = CSLAddString( papszFileList, osFilename );
-    
+
     // projections file.
     osFilename = CPLFormCIFilename( osPath, osName, "prj" );
     if( VSIStatExL( osFilename, &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 )
         papszFileList = CSLAddString( papszFileList, osFilename );
-    
-    CPLString imageRepFilename = GetImageRepFilename( GetDescription() );
+
+    const CPLString imageRepFilename = GetImageRepFilename( GetDescription() );
     if (!imageRepFilename.empty())
         papszFileList = CSLAddString( papszFileList, imageRepFilename.c_str() );
-    
+
     return papszFileList;
 }
 
@@ -978,10 +1048,8 @@ char **EHdrDataset::GetFileList()
 GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    int		i, bSelectedHDR;
-    
 /* -------------------------------------------------------------------- */
-/*	We assume the user is pointing to the binary (ie. .bil) file.	*/
+/*      We assume the user is pointing to the binary (i.e. .bil) file.  */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->nHeaderBytes < 2 )
         return NULL;
@@ -990,31 +1058,34 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Now we need to tear apart the filename to form a .HDR           */
 /*      filename.                                                       */
 /* -------------------------------------------------------------------- */
-    CPLString osPath = CPLGetPath( poOpenInfo->pszFilename );
-    CPLString osName = CPLGetBasename( poOpenInfo->pszFilename );
-    CPLString osHDRFilename;
+    const CPLString osPath = CPLGetPath( poOpenInfo->pszFilename );
+    const CPLString osName = CPLGetBasename( poOpenInfo->pszFilename );
 
     const char* pszHeaderExt = "hdr";
     if( EQUAL( CPLGetExtension( poOpenInfo->pszFilename ), "SRC" ) &&
         osName.size() == 7 &&
-        (osName[0] == 'e' || osName[0] == 'E' || osName[0] == 'w' || osName[0] == 'W') &&
-        (osName[4] == 'n' || osName[4] == 'N' || osName[4] == 's' || osName[4] == 'S') )
+        (osName[0] == 'e' || osName[0] == 'E' ||
+         osName[0] == 'w' || osName[0] == 'W') &&
+        (osName[4] == 'n' || osName[4] == 'N' ||
+         osName[4] == 's' || osName[4] == 'S') )
     {
-        /* It is a GTOPO30 or SRTM30 source file, whose header extension is .sch */
-        /* see http://dds.cr.usgs.gov/srtm/version1/SRTM30/GTOPO30_Documentation */
+        // It is a GTOPO30 or SRTM30 source file, whose header extension is .sch
+        // see http://dds.cr.usgs.gov/srtm/version1/SRTM30/GTOPO30_Documentation
         pszHeaderExt = "sch";
     }
 
     char** papszSiblingFiles = poOpenInfo->GetSiblingFiles();
+    CPLString osHDRFilename;
     if( papszSiblingFiles )
     {
-        int iFile = CSLFindString(papszSiblingFiles, 
-                                  CPLFormFilename( NULL, osName, pszHeaderExt ) );
-        if( iFile < 0 ) // return if there is no corresponding .hdr file
+        const int iFile =
+            CSLFindString( papszSiblingFiles,
+                           CPLFormFilename( NULL, osName, pszHeaderExt ) );
+        if( iFile < 0 )  // Return if there is no corresponding .hdr file.
             return NULL;
-        
-        osHDRFilename = 
-            CPLFormFilename( osPath, papszSiblingFiles[iFile], 
+
+        osHDRFilename =
+            CPLFormFilename( osPath, papszSiblingFiles[iFile],
                              NULL );
     }
     else
@@ -1022,15 +1093,12 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
         osHDRFilename = CPLFormCIFilename( osPath, osName, pszHeaderExt );
     }
 
-    bSelectedHDR = EQUAL( osHDRFilename, poOpenInfo->pszFilename );
+    const bool bSelectedHDR = EQUAL( osHDRFilename, poOpenInfo->pszFilename );
 
 /* -------------------------------------------------------------------- */
 /*      Do we have a .hdr file?                                         */
 /* -------------------------------------------------------------------- */
-    VSILFILE	*fp;
-
-    fp = VSIFOpenL( osHDRFilename, "r" );
-    
+    VSILFILE *fp = VSIFOpenL( osHDRFilename, "r" );
     if( fp == NULL )
     {
         return NULL;
@@ -1040,28 +1108,34 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Is this file an ESRI header file?  Read a few lines of text     */
 /*      searching for something starting with nrows or ncols.           */
 /* -------------------------------------------------------------------- */
-    const char *	pszLine;
-    int			nRows = -1, nCols = -1, nBands = 1;
-    int			nSkipBytes = 0;
-    double		dfULXMap=0.5, dfULYMap = 0.5, dfYLLCorner = -123.456;
-    int                 bCenter = TRUE;
-    double		dfXDim = 1.0, dfYDim = 1.0, dfNoData = 0.0;
-    int			nLineCount = 0, bNoDataSet = FALSE;
-    GDALDataType	eDataType = GDT_Byte;
-    int                 nBits = -1;
-    char		chByteOrder = 'M';
-    char                chPixelType = 'N'; // not defined
-    char                szLayout[10] = "BIL";
-    char              **papszHDR = NULL;
-    int                 bHasInternalProjection = FALSE;
-    int                 bHasMin = FALSE;
-    int                 bHasMax = FALSE;
-    double              dfMin = 0, dfMax = 0;
-    
-    while( (pszLine = CPLReadLineL( fp )) != NULL )    
+    int nRows = -1;
+    int nCols = -1;
+    int nBands = 1;
+    int nSkipBytes = 0;
+    double dfULXMap = 0.5;
+    double dfULYMap = 0.5;
+    double dfYLLCorner = -123.456;
+    int bCenter = TRUE;
+    double dfXDim = 1.0;
+    double dfYDim = 1.0;
+    double dfNoData = 0.0;
+    int nLineCount = 0;
+    int bNoDataSet = FALSE;
+    GDALDataType eDataType = GDT_Byte;
+    int nBits = -1;
+    char chByteOrder = 'M';
+    char chPixelType = 'N'; // not defined
+    char szLayout[10] = "BIL";
+    char **papszHDR = NULL;
+    int bHasInternalProjection = FALSE;
+    int bHasMin = FALSE;
+    int bHasMax = FALSE;
+    double dfMin = 0;
+    double dfMax = 0;
+
+    const char *pszLine;
+    while( (pszLine = CPLReadLineL( fp )) != NULL )
     {
-        char	**papszTokens;
-
         nLineCount++;
 
         if( nLineCount > 50 || strlen(pszLine) > 1000 )
@@ -1069,13 +1143,14 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
 
         papszHDR = CSLAddString( papszHDR, pszLine );
 
-        papszTokens = CSLTokenizeStringComplex( pszLine, " \t", TRUE, FALSE );
+        char **papszTokens
+            = CSLTokenizeStringComplex( pszLine, " \t", TRUE, FALSE );
         if( CSLCount( papszTokens ) < 2 )
         {
             CSLDestroy( papszTokens );
             continue;
         }
-        
+
         if( EQUAL(papszTokens[0],"ncols") )
         {
             nCols = atoi(papszTokens[1]);
@@ -1088,8 +1163,8 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
         {
             nSkipBytes = atoi(papszTokens[1]);
         }
-        else if( EQUAL(papszTokens[0],"ulxmap") 
-                 || EQUAL(papszTokens[0],"xllcorner") 
+        else if( EQUAL(papszTokens[0],"ulxmap")
+                 || EQUAL(papszTokens[0],"xllcorner")
                  || EQUAL(papszTokens[0],"xllcenter") )
         {
             dfULXMap = CPLAtofM(papszTokens[1]);
@@ -1100,7 +1175,7 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
         {
             dfULYMap = CPLAtofM(papszTokens[1]);
         }
-        else if( EQUAL(papszTokens[0],"yllcorner") 
+        else if( EQUAL(papszTokens[0],"yllcorner")
                  || EQUAL(papszTokens[0],"yllcenter") )
         {
             dfYLLCorner = CPLAtofM(papszTokens[1]);
@@ -1128,7 +1203,7 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
             strncpy( szLayout, papszTokens[1], sizeof(szLayout) );
             szLayout[sizeof(szLayout)-1] = '\0';
         }
-        else if( EQUAL(papszTokens[0],"NODATA_value") 
+        else if( EQUAL(papszTokens[0],"NODATA_value")
                  || EQUAL(papszTokens[0],"NODATA") )
         {
             dfNoData = CPLAtofM(papszTokens[1]);
@@ -1140,11 +1215,11 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
         }
         else if( EQUAL(papszTokens[0],"PIXELTYPE") )
         {
-            chPixelType = (char) toupper(papszTokens[1][0]);
+            chPixelType = static_cast<char>( toupper(papszTokens[1][0]) );
         }
         else if( EQUAL(papszTokens[0],"byteorder") )
         {
-            chByteOrder = (char) toupper(papszTokens[1][0]);
+            chByteOrder = static_cast<char>( toupper(papszTokens[1][0]) );
         }
 
         /* http://www.worldclim.org/futdown.htm have the projection extensions */
@@ -1168,7 +1243,7 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
         CSLDestroy( papszTokens );
     }
 
-    VSIFCloseL( fp );
+    CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
 
 /* -------------------------------------------------------------------- */
 /*      Did we get the required keywords?  If not we return with        */
@@ -1193,12 +1268,12 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( bSelectedHDR )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "The selected file is an ESRI BIL header file, but to\n"
-                  "open ESRI BIL datasets, the data file should be selected\n"
-                  "instead of the .hdr file.  Please try again selecting\n"
-                  "the data file (often with the extension .bil) corresponding\n"
-                  "to the header file: %s\n", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "The selected file is an ESRI BIL header file, but to "
+                  "open ESRI BIL datasets, the data file should be selected "
+                  "instead of the .hdr file.  Please try again selecting "
+                  "the data file (often with the extension .bil) corresponding "
+                  "to the header file: %s",
                   poOpenInfo->pszFilename );
         CSLDestroy( papszHDR );
         return NULL;
@@ -1214,9 +1289,10 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
         VSIStatBufL sStatBuf;
         if( VSIStatL( poOpenInfo->pszFilename, &sStatBuf ) == 0 )
         {
-            size_t nBytes = (size_t) (sStatBuf.st_size/nCols/nRows/nBands);
+            const size_t nBytes
+                = static_cast<size_t>( sStatBuf.st_size/nCols/nRows/nBands );
             if( nBytes > 0 && nBytes != 3 )
-                nBits = nBytes*8;
+                nBits = static_cast<int>(nBytes * 8);
 
             if( nBytes == 4 )
                 chPixelType = 'F';
@@ -1245,9 +1321,7 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    EHdrDataset     *poDS;
-
-    poDS = new EHdrDataset();
+    EHdrDataset *poDS = new EHdrDataset();
 
     poDS->osHeaderExt = pszHeaderExt;
 
@@ -1268,8 +1342,8 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
 
     if( poDS->fpImage == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Failed to open %s with write permission.\n%s", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to open %s with write permission.\n%s",
                   osName.c_str(), VSIStrerror( errno ) );
         delete poDS;
         return NULL;
@@ -1294,7 +1368,7 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
         else if( chPixelType == 'F' )
             eDataType = GDT_Float32;
         else
-            eDataType = GDT_UInt32; // default 
+            eDataType = GDT_UInt32; // default
     }
     else if( nBits == 8 )
     {
@@ -1318,39 +1392,67 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
     }
     else
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
-                  "EHdr driver does not support %d NBITS value.", 
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "EHdr driver does not support %d NBITS value.",
                   nBits );
         delete poDS;
+        poDS = NULL;
         return NULL;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Compute the line offset.                                        */
 /* -------------------------------------------------------------------- */
-    int             nItemSize = GDALGetDataTypeSize(eDataType)/8;
-    int             nPixelOffset, nLineOffset;
+    const int nItemSize = GDALGetDataTypeSizeBytes(eDataType);
+    int nPixelOffset = 0;
+    int nLineOffset = 0;
     vsi_l_offset    nBandOffset;
+    CPLAssert(nItemSize != 0);
+    CPLAssert(nBands != 0);
 
-    if( EQUAL(szLayout,"BIP") )
+    if( EQUAL(szLayout, "BIP") )
     {
+        if (nCols > INT_MAX / (nItemSize * nBands))
+        {
+            delete poDS;
+            poDS = NULL;
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Int overflow occurred.");
+            return NULL;
+        }
         nPixelOffset = nItemSize * nBands;
         nLineOffset = nPixelOffset * nCols;
         nBandOffset = (vsi_l_offset)nItemSize;
     }
     else if( EQUAL(szLayout,"BSQ") )
     {
+        if (nCols > INT_MAX / nItemSize)
+        {
+            delete poDS;
+            poDS = NULL;
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Int overflow occurred.");
+            return NULL;
+        }
         nPixelOffset = nItemSize;
         nLineOffset = nPixelOffset * nCols;
         nBandOffset = (vsi_l_offset)nLineOffset * nRows;
     }
     else /* assume BIL */
     {
+        if (nCols > INT_MAX / (nItemSize * nBands))
+        {
+            delete poDS;
+            poDS = NULL;
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Int overflow occurred.");
+            return NULL;
+        }
         nPixelOffset = nItemSize;
         nLineOffset = nItemSize * nBands * nCols;
         nBandOffset = (vsi_l_offset)nItemSize * nCols;
     }
-    
+
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->PamInitialize();
 
@@ -1358,20 +1460,19 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
     poDS->nBands = nBands;
-    for( i = 0; i < poDS->nBands; i++ )
+    CPLErrorReset();
+    for( int i = 0; i < poDS->nBands; i++ )
     {
-        EHdrRasterBand	*poBand;
-            
-        poBand = 
+        EHdrRasterBand	*poBand =
             new EHdrRasterBand( poDS, i+1, poDS->fpImage,
-                                nSkipBytes + nBandOffset * i, 
+                                nSkipBytes + nBandOffset * i,
                                 nPixelOffset, nLineOffset, eDataType,
-#ifdef CPL_LSB                               
+#ifdef CPL_LSB
                                 chByteOrder == 'I' || chByteOrder == 'L',
 #else
                                 chByteOrder == 'M',
-#endif        
-                                nBits);
+#endif
+                                nBits );
 
         poBand->bNoDataSet = bNoDataSet;
         poBand->dfNoData = dfNoData;
@@ -1382,8 +1483,14 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
             poBand->dfMax = dfMax;
             poBand->minmaxmeanstddev = HAS_MIN_FLAG | HAS_MAX_FLAG;
         }
-            
+
         poDS->SetBand( i+1, poBand );
+        if( CPLGetLastErrorType() != CE_None )
+        {
+            poDS->nBands = i+1;
+            delete poDS;
+            return NULL;
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -1397,7 +1504,7 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
             dfULYMap = dfYLLCorner + nRows * dfYDim;
     }
 
-    if( dfULYMap != 0.5 || dfULYMap != 0.5 || dfXDim != 1.0 || dfYDim != 1.0 )
+    if( dfULXMap != 0.5 || dfULYMap != 0.5 || dfXDim != 1.0 || dfYDim != 1.0 )
     {
         poDS->bGotTransform = TRUE;
 
@@ -1420,26 +1527,26 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
             poDS->adfGeoTransform[5] = - dfYDim;
         }
     }
-    
+
     if( !poDS->bGotTransform )
-        poDS->bGotTransform = 
-            GDALReadWorldFile( poOpenInfo->pszFilename, 0, 
+        poDS->bGotTransform =
+            GDALReadWorldFile( poOpenInfo->pszFilename, NULL,
                                poDS->adfGeoTransform );
 
     if( !poDS->bGotTransform )
-        poDS->bGotTransform = 
-            GDALReadWorldFile( poOpenInfo->pszFilename, "wld", 
+        poDS->bGotTransform =
+            GDALReadWorldFile( poOpenInfo->pszFilename, "wld",
                                poDS->adfGeoTransform );
 
 /* -------------------------------------------------------------------- */
 /*      Check for a .prj file.                                          */
 /* -------------------------------------------------------------------- */
-    const char  *pszPrjFilename = CPLFormCIFilename( osPath, osName, "prj" );
+    const char *pszPrjFilename = CPLFormCIFilename( osPath, osName, "prj" );
 
     fp = VSIFOpenL( pszPrjFilename, "r" );
 
-    /* .hdr files from http://www.worldclim.org/futdown.htm have the projection */
-    /* info in the .hdr file itself ! */
+    // .hdr files from http://www.worldclim.org/futdown.htm have the projection
+    // info in the .hdr file itself.
     if (fp == NULL && bHasInternalProjection)
     {
         pszPrjFilename = osHDRFilename;
@@ -1448,19 +1555,18 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
 
     if( fp != NULL )
     {
-        char	**papszLines;
-        OGRSpatialReference oSRS;
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
+        fp = NULL;
 
-        VSIFCloseL( fp );
-        
-        papszLines = CSLLoad( pszPrjFilename );
+        char **papszLines = CSLLoad( pszPrjFilename );
 
+        OGRSpatialReference oSRS;
         if( oSRS.importFromESRI( papszLines ) == OGRERR_NONE )
         {
-            // If geographic values are in seconds, we must transform. 
-            // Is there a code for minutes too? 
-            char szResult[80];
-            if( oSRS.IsGeographic() 
+            // If geographic values are in seconds, we must transform.
+            // Is there a code for minutes too?
+            char szResult[80] = { '\0' };
+            if( oSRS.IsGeographic()
                 && EQUAL(OSR_GDS( szResult, sizeof(szResult),
                                   papszLines, "Units", ""), "DS") )
             {
@@ -1486,28 +1592,28 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
 /*  For the specification of SPDF (in French),                          */
 /*   see http://eden.ign.fr/download/pub/doc/emabgi/spdf10.pdf/download */
 /* -------------------------------------------------------------------- */
-        CPLString szImageRepFilename = GetImageRepFilename(poOpenInfo->pszFilename );
+        const CPLString szImageRepFilename =
+            GetImageRepFilename(poOpenInfo->pszFilename );
         if (!szImageRepFilename.empty())
         {
             fp = VSIFOpenL( szImageRepFilename.c_str(), "r" );
         }
         if (fp != NULL)
         {
-            const char  *pszLine;
-            int bUTM = FALSE;
-            int bWGS84 = FALSE;
+            bool bUTM = false;
+            bool bWGS84 = false;
             int bNorth = FALSE;
-            int bSouth = FALSE;
+            bool bSouth = false;
             int utmZone = 0;
 
             while( (pszLine = CPLReadLineL( fp )) != NULL )
             {
-                if (strncmp(pszLine, "PROJ_ID", strlen("PROJ_ID")) == 0 &&
+                if (STARTS_WITH(pszLine, "PROJ_ID") &&
                     strstr(pszLine, "UTM"))
                 {
-                    bUTM = TRUE;
+                    bUTM = true;
                 }
-                else if (strncmp(pszLine, "PROJ_ZONE", strlen("PROJ_ZONE")) == 0)
+                else if (STARTS_WITH(pszLine, "PROJ_ZONE"))
                 {
                     const char* c = strchr(pszLine, '"');
                     if (c)
@@ -1518,19 +1624,21 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
                             utmZone = atoi(c);
                             if (utmZone >= 1 && utmZone <= 60)
                             {
-                                if (strstr(pszLine, "Nord") || strstr(pszLine, "NORD"))
+                                if( strstr(pszLine, "Nord") ||
+                                    strstr(pszLine, "NORD") )
                                 {
                                     bNorth = TRUE;
                                 }
-                                else if (strstr(pszLine, "Sud") || strstr(pszLine, "SUD"))
+                                else if( strstr(pszLine, "Sud") ||
+                                         strstr(pszLine, "SUD") )
                                 {
-                                    bSouth = TRUE;
+                                    bSouth = true;
                                 }
                             }
                         }
                     }
                 }
-                else if (strncmp(pszLine, "PROJ_CODE", strlen("PROJ_CODE")) == 0 &&
+                else if (STARTS_WITH(pszLine, "PROJ_CODE") &&
                          strstr(pszLine, "FR-MINDEF"))
                 {
                     const char* c = strchr(pszLine, 'A');
@@ -1550,18 +1658,19 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
                                 else if (c[1] == 'S' ||
                                          (c[1] != '\0' && c[2] == 'S'))
                                 {
-                                    bSouth = TRUE;
+                                    bSouth = true;
                                 }
                             }
                         }
                     }
                 }
-                else if (strncmp(pszLine, "HORIZ_DATUM", strlen("HORIZ_DATUM")) == 0 &&
-                         (strstr(pszLine, "WGS 84") || strstr(pszLine, "WGS84")))
+                else if( STARTS_WITH(pszLine, "HORIZ_DATUM") &&
+                         (strstr(pszLine, "WGS 84") ||
+                          strstr(pszLine, "WGS84")) )
                 {
-                    bWGS84 = TRUE;
+                    bWGS84 = true;
                 }
-                else if (strncmp(pszLine, "MAP_NUMBER", strlen("MAP_NUMBER")) == 0)
+                else if(STARTS_WITH(pszLine, "MAP_NUMBER") )
                 {
                     const char* c = strchr(pszLine, '"');
                     if (c)
@@ -1573,7 +1682,7 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
                         CPLFree(pszMapNumber);
                     }
                 }
-                else if (strncmp(pszLine, "PRODUCTION_DATE", strlen("PRODUCTION_DATE")) == 0)
+                else if (STARTS_WITH(pszLine, "PRODUCTION_DATE"))
                 {
                     const char* c = pszLine + strlen("PRODUCTION_DATE");
                     while(*c == ' ')
@@ -1584,20 +1693,21 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
                     }
                 }
             }
-            
-            VSIFCloseL( fp );
+
+            CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
 
             if (utmZone != 0 && bUTM && bWGS84 && (bNorth || bSouth))
             {
-                char projCSStr[64];
-                OGRSpatialReference oSRS;
-
-                sprintf(projCSStr, "WGS 84 / UTM zone %d%c",
+                char projCSStr[64] = { '\0' };
+                snprintf(projCSStr, sizeof(projCSStr), "WGS 84 / UTM zone %d%c",
                         utmZone, (bNorth) ? 'N' : 'S');
+
+                OGRSpatialReference oSRS;
                 oSRS.SetProjCS(projCSStr);
                 oSRS.SetWellKnownGeogCS( "WGS84" );
                 oSRS.SetUTM(utmZone, bNorth);
-                oSRS.SetAuthority("PROJCS", "EPSG", ((bNorth) ? 32600 : 32700) + utmZone);
+                oSRS.SetAuthority("PROJCS", "EPSG",
+                                  (bNorth ? 32600 : 32700) + utmZone);
                 oSRS.AutoIdentifyEPSG();
 
                 CPLFree( poDS->pszProjection );
@@ -1605,7 +1715,8 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
             }
             else
             {
-                CPLError( CE_Warning, CPLE_NotSupported, "Cannot retrive projection from IMAGE.REP");
+                CPLError( CE_Warning, CPLE_NotSupported,
+                          "Cannot retrieve projection from IMAGE.REP" );
             }
         }
     }
@@ -1614,61 +1725,65 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Check for a color table.                                        */
 /* -------------------------------------------------------------------- */
     const char  *pszCLRFilename = CPLFormCIFilename( osPath, osName, "clr" );
-    
+
     /* Only read the .clr for byte, int16 or uint16 bands */
     if (nItemSize <= 2)
         fp = VSIFOpenL( pszCLRFilename, "r" );
     else
         fp = NULL;
-        
+
     if( fp != NULL )
     {
         GDALColorTable oColorTable;
         int bHasWarned = FALSE;
 
-        while(TRUE)
+        while( true )
         {
-            const char  *pszLine =  CPLReadLineL(fp);
+            pszLine =  CPLReadLineL(fp);
             if ( !pszLine )
                 break;
 
             if( *pszLine == '#' || *pszLine == '!' )
                 continue;
 
-            char	**papszValues = CSLTokenizeString2(pszLine, "\t ",
-                                                           CSLT_HONOURSTRINGS);
-            GDALColorEntry oEntry;
+            char **papszValues = CSLTokenizeString2(pszLine, "\t ",
+                                                    CSLT_HONOURSTRINGS);
+
 
             if ( CSLCount(papszValues) >= 4 )
             {
                 int nIndex = atoi( papszValues[0] ); // Index
                 if (nIndex >= 0 && nIndex < 65536)
                 {
-                    oEntry.c1 = (short) atoi( papszValues[1] ); // Red
-                    oEntry.c2 = (short) atoi( papszValues[2] ); // Green
-                    oEntry.c3 = (short) atoi( papszValues[3] ); // Blue
+                    GDALColorEntry oEntry;
+                    oEntry.c1 =
+                        static_cast<short>( atoi( papszValues[1] ) ); // Red
+                    oEntry.c2 =
+                        static_cast<short>( atoi( papszValues[2] ) ); // Green
+                    oEntry.c3 =
+                        static_cast<short>( atoi( papszValues[3] ) ); // Blue
                     oEntry.c4 = 255;
 
                     oColorTable.SetColorEntry( nIndex, &oEntry );
                 }
                 else
                 {
-                    /* Negative values are valid. At least we can find use of */
-                    /* them here : http://www.ngdc.noaa.gov/mgg/topo/elev/esri/clr/ */
-                    /* but there's no way of representing them with GDAL color */
-                    /* table model */
+                    // Negative values are valid. At least we can find use of
+                    // them here: http://www.ngdc.noaa.gov/mgg/topo/elev/esri/clr/
+                    // but there's no way of representing them with GDAL color
+                    // table model.
                     if (!bHasWarned)
-                        CPLDebug("EHdr", "Ignoring color index : %d", nIndex);
+                        CPLDebug( "EHdr", "Ignoring color index : %d", nIndex );
                     bHasWarned = TRUE;
                 }
             }
 
             CSLDestroy( papszValues );
         }
-    
-        VSIFCloseL( fp );
 
-        for( i = 1; i <= poDS->nBands; i++ )
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
+
+        for( int i = 1; i <= poDS->nBands; i++ )
         {
             GDALRasterBand *poBand = poDS->GetRasterBand( i );
             poBand->SetColorTable( &oColorTable );
@@ -1687,13 +1802,13 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
     poDS->TryLoadXML();
-    
+
 /* -------------------------------------------------------------------- */
 /*      Check for overviews.                                            */
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -1711,7 +1826,7 @@ GDALDataset *EHdrDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
     if (nBands <= 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "EHdr driver does not support %d bands.\n", nBands);
         return NULL;
     }
@@ -1720,9 +1835,9 @@ GDALDataset *EHdrDataset::Create( const char * pszFilename,
         && eType != GDT_Int16 && eType != GDT_Int32 && eType != GDT_UInt32 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-              "Attempt to create ESRI .hdr labelled dataset with an illegal\n"
-              "data type (%s).\n",
-              GDALGetDataTypeName(eType) );
+                  "Attempt to create ESRI .hdr labelled dataset with an illegal"
+                  "data type (%s).",
+                  GDALGetDataTypeName(eType) );
 
         return NULL;
     }
@@ -1730,14 +1845,12 @@ GDALDataset *EHdrDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Try to create the file.                                         */
 /* -------------------------------------------------------------------- */
-    VSILFILE	*fp;
-
-    fp = VSIFOpenL( pszFilename, "wb" );
+    VSILFILE *fp = VSIFOpenL( pszFilename, "wb" );
 
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Attempt to create file `%s' failed.\n",
+                  "Attempt to create file `%s' failed.",
                   pszFilename );
         return NULL;
     }
@@ -1746,16 +1859,20 @@ GDALDataset *EHdrDataset::Create( const char * pszFilename,
 /*      Just write out a couple of bytes to establish the binary        */
 /*      file, and then close it.                                        */
 /* -------------------------------------------------------------------- */
-    VSIFWriteL( (void *) "\0\0", 2, 1, fp );
-    VSIFCloseL( fp );
+    bool bOK =
+        VSIFWriteL( reinterpret_cast<void *>( const_cast<char *>( "\0\0" ) ),
+                    2, 1, fp ) == 1;
+    if( VSIFCloseL( fp ) != 0 )
+        bOK = false;
+    fp = NULL;
+    if( !bOK )
+        return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Create the hdr filename.                                        */
 /* -------------------------------------------------------------------- */
-    char *pszHdrFilename;
-
-    pszHdrFilename = 
-        CPLStrdup( CPLResetExtension( pszFilename, "hdr" ) );
+    char * const pszHdrFilename
+        = CPLStrdup( CPLResetExtension( pszFilename, "hdr" ) );
 
 /* -------------------------------------------------------------------- */
 /*      Open the file.                                                  */
@@ -1773,13 +1890,12 @@ GDALDataset *EHdrDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Decide how many bits the file should have.                      */
 /* -------------------------------------------------------------------- */
-    int nRowBytes;
     int nBits = GDALGetDataTypeSize(eType);
 
     if( CSLFetchNameValue( papszParmList, "NBITS" ) != NULL )
         nBits = atoi(CSLFetchNameValue( papszParmList, "NBITS" ));
 
-    nRowBytes = (nBits * nXSize + 7) / 8;
+    const int nRowBytes = (nBits * nXSize + 7) / 8;
 
 /* -------------------------------------------------------------------- */
 /*      Check for signed byte.                                          */
@@ -1791,97 +1907,107 @@ GDALDataset *EHdrDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Write out the raw definition for the dataset as a whole.        */
 /* -------------------------------------------------------------------- */
-    VSIFPrintfL( fp, "BYTEORDER      I\n" );
-    VSIFPrintfL( fp, "LAYOUT         BIL\n" );
-    VSIFPrintfL( fp, "NROWS          %d\n", nYSize );
-    VSIFPrintfL( fp, "NCOLS          %d\n", nXSize );
-    VSIFPrintfL( fp, "NBANDS         %d\n", nBands );
-    VSIFPrintfL( fp, "NBITS          %d\n", nBits );
-    VSIFPrintfL( fp, "BANDROWBYTES   %d\n", nRowBytes );
-    VSIFPrintfL( fp, "TOTALROWBYTES  %d\n", nRowBytes * nBands );
-    
+    bOK &= VSIFPrintfL( fp, "BYTEORDER      I\n" ) >= 0;
+    bOK &= VSIFPrintfL( fp, "LAYOUT         BIL\n" ) >= 0;
+    bOK &= VSIFPrintfL( fp, "NROWS          %d\n", nYSize ) >= 0;
+    bOK &= VSIFPrintfL( fp, "NCOLS          %d\n", nXSize ) >= 0;
+    bOK &= VSIFPrintfL( fp, "NBANDS         %d\n", nBands ) >= 0;
+    bOK &= VSIFPrintfL( fp, "NBITS          %d\n", nBits ) >= 0;
+    bOK &= VSIFPrintfL( fp, "BANDROWBYTES   %d\n", nRowBytes ) >= 0;
+    bOK &= VSIFPrintfL( fp, "TOTALROWBYTES  %d\n", nRowBytes * nBands ) >= 0;
+
     if( eType == GDT_Float32 )
-        VSIFPrintfL( fp, "PIXELTYPE      FLOAT\n");
+        bOK &= VSIFPrintfL( fp, "PIXELTYPE      FLOAT\n") >= 0;
     else if( eType == GDT_Int16 || eType == GDT_Int32 )
-        VSIFPrintfL( fp, "PIXELTYPE      SIGNEDINT\n");
+        bOK &= VSIFPrintfL( fp, "PIXELTYPE      SIGNEDINT\n") >= 0;
     else if( eType == GDT_Byte && EQUAL(pszPixelType,"SIGNEDBYTE") )
-        VSIFPrintfL( fp, "PIXELTYPE      SIGNEDINT\n");
+        bOK &= VSIFPrintfL( fp, "PIXELTYPE      SIGNEDINT\n") >= 0;
     else
-        VSIFPrintfL( fp, "PIXELTYPE      UNSIGNEDINT\n");
+        bOK &= VSIFPrintfL( fp, "PIXELTYPE      UNSIGNEDINT\n") >= 0;
 
 /* -------------------------------------------------------------------- */
 /*      Cleanup                                                         */
 /* -------------------------------------------------------------------- */
-    VSIFCloseL( fp );
+    if( VSIFCloseL( fp ) != 0 )
+        bOK = false;
 
     CPLFree( pszHdrFilename );
 
-    return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
+    if( !bOK )
+        return NULL;
+
+    return
+        reinterpret_cast<GDALDataset *>( GDALOpen( pszFilename, GA_Update ) );
 }
 
 /************************************************************************/
 /*                             CreateCopy()                             */
 /************************************************************************/
 
-GDALDataset *EHdrDataset::CreateCopy( const char * pszFilename, 
-                                      GDALDataset * poSrcDS, 
+GDALDataset *EHdrDataset::CreateCopy( const char * pszFilename,
+                                      GDALDataset * poSrcDS,
                                       int bStrict, char ** papszOptions,
                                       GDALProgressFunc pfnProgress,
                                       void * pProgressData )
 
 {
-    char **papszAdjustedOptions = CSLDuplicate( papszOptions );
-    GDALDataset *poOutDS;
-
-    int nBands = poSrcDS->GetRasterCount();
+    const int nBands = poSrcDS->GetRasterCount();
     if (nBands == 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
-                  "EHdr driver does not support source dataset with zero band.\n");
-        CSLDestroy( papszAdjustedOptions );
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "EHdr driver does not support source dataset without any "
+                  "bands.\n" );
         return NULL;
     }
 
+    char **papszAdjustedOptions = CSLDuplicate( papszOptions );
+
 /* -------------------------------------------------------------------- */
 /*      Ensure we pass on NBITS and PIXELTYPE structure information.    */
 /* -------------------------------------------------------------------- */
-    if( poSrcDS->GetRasterBand(1)->GetMetadataItem( "NBITS", 
+    if( poSrcDS->GetRasterBand(1)->GetMetadataItem( "NBITS",
                                                     "IMAGE_STRUCTURE" ) !=NULL
         && CSLFetchNameValue( papszOptions, "NBITS" ) == NULL )
     {
-        papszAdjustedOptions = 
-            CSLSetNameValue( papszAdjustedOptions, 
-                             "NBITS", 
-                             poSrcDS->GetRasterBand(1)->GetMetadataItem("NBITS","IMAGE_STRUCTURE") );
+        papszAdjustedOptions =
+            CSLSetNameValue(
+                papszAdjustedOptions,
+                "NBITS",
+                poSrcDS->GetRasterBand(1)->
+                    GetMetadataItem("NBITS","IMAGE_STRUCTURE") );
     }
-    
-    if( poSrcDS->GetRasterBand(1)->GetMetadataItem( "PIXELTYPE", 
+
+    if( poSrcDS->GetRasterBand(1)->GetMetadataItem( "PIXELTYPE",
                                                     "IMAGE_STRUCTURE" ) !=NULL
         && CSLFetchNameValue( papszOptions, "PIXELTYPE" ) == NULL )
     {
-        papszAdjustedOptions = 
-            CSLSetNameValue( papszAdjustedOptions, 
-                             "PIXELTYPE", 
-                             poSrcDS->GetRasterBand(1)->GetMetadataItem("PIXELTYPE","IMAGE_STRUCTURE") );
+        papszAdjustedOptions =
+            CSLSetNameValue(
+                papszAdjustedOptions,
+                "PIXELTYPE",
+                poSrcDS->GetRasterBand(1)->
+                    GetMetadataItem("PIXELTYPE","IMAGE_STRUCTURE") );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Proceed with normal copying using the default createcopy        */
 /*      operators.                                                      */
 /* -------------------------------------------------------------------- */
-    GDALDriver	*poDriver = (GDALDriver *) GDALGetDriverByName( "EHdr" );
+    GDALDriver *poDriver = reinterpret_cast<GDALDriver *>(
+        GDALGetDriverByName( "EHdr" ) );
 
-    poOutDS = poDriver->DefaultCreateCopy( pszFilename, poSrcDS, bStrict,
-                                           papszAdjustedOptions, 
-                                           pfnProgress, pProgressData );
+    GDALDataset *poOutDS
+        = poDriver->DefaultCreateCopy( pszFilename, poSrcDS, bStrict,
+                                       papszAdjustedOptions,
+                                       pfnProgress, pProgressData );
     CSLDestroy( papszAdjustedOptions );
-    
+
     if( poOutDS != NULL )
         poOutDS->FlushCache();
 
     return poOutDS;
 }
-    
+
 /************************************************************************/
 /*                        GetNoDataValue()                              */
 /************************************************************************/
@@ -1896,7 +2022,7 @@ double EHdrRasterBand::GetNoDataValue( int *pbSuccess )
 
     return RawRasterBand::GetNoDataValue( pbSuccess );
 }
-    
+
 /************************************************************************/
 /*                           GetMinimum()                               */
 /************************************************************************/
@@ -1931,70 +2057,74 @@ double EHdrRasterBand::GetMaximum( int *pbSuccess )
 /*                           GetStatistics()                            */
 /************************************************************************/
 
-CPLErr EHdrRasterBand::GetStatistics( int bApproxOK, int bForce, double *pdfMin, double *pdfMax, double *pdfMean, double *pdfStdDev )
+CPLErr EHdrRasterBand::GetStatistics(
+    int bApproxOK, int bForce,
+    double *pdfMin, double *pdfMax,
+    double *pdfMean, double *pdfStdDev )
 {
     if( (minmaxmeanstddev & HAS_ALL_FLAGS) == HAS_ALL_FLAGS)
     {
-        if ( pdfMin ) *pdfMin = dfMin;
-        if ( pdfMax ) *pdfMax = dfMax;
-        if ( pdfMean ) *pdfMean = dfMean;
-        if ( pdfStdDev ) *pdfStdDev = dfStdDev;
+        if( pdfMin ) *pdfMin = dfMin;
+        if( pdfMax ) *pdfMax = dfMax;
+        if( pdfMean ) *pdfMean = dfMean;
+        if( pdfStdDev ) *pdfStdDev = dfStdDev;
         return CE_None;
     }
 
-    CPLErr eErr = RawRasterBand::GetStatistics( bApproxOK, bForce, 
-                                                &dfMin, &dfMax, 
+    const CPLErr eErr = RawRasterBand::GetStatistics( bApproxOK, bForce,
+                                                &dfMin, &dfMax,
                                                 &dfMean, &dfStdDev );
+    if( eErr != CE_None )
+        return eErr;
 
-    if( eErr == CE_None )
-    {
-        EHdrDataset* poEDS = (EHdrDataset *) poDS;
+    EHdrDataset* poEDS = reinterpret_cast<EHdrDataset *>( poDS );
 
-        minmaxmeanstddev = HAS_ALL_FLAGS;
+    minmaxmeanstddev = HAS_ALL_FLAGS;
 
-        if( poEDS->RewriteSTX() != CE_None )
-            RawRasterBand::SetStatistics( dfMin, dfMax, dfMean, dfStdDev );
+    if( poEDS->RewriteSTX() != CE_None )
+        RawRasterBand::SetStatistics( dfMin, dfMax, dfMean, dfStdDev );
 
-        if( pdfMin )
-            *pdfMin = dfMin;
-        if( pdfMax )
-            *pdfMax = dfMax;
-        if( pdfMean )
-            *pdfMean = dfMean;
-        if( pdfStdDev )
-            *pdfStdDev = dfStdDev;
-    }
+    if( pdfMin )
+        *pdfMin = dfMin;
+    if( pdfMax )
+        *pdfMax = dfMax;
+    if( pdfMean )
+        *pdfMean = dfMean;
+    if( pdfStdDev )
+        *pdfStdDev = dfStdDev;
 
-    return eErr;
+    return CE_None;
 }
 
 /************************************************************************/
 /*                           SetStatistics()                            */
 /************************************************************************/
 
-CPLErr EHdrRasterBand::SetStatistics( double dfMin, double dfMax, double dfMean, double dfStdDev )
+CPLErr EHdrRasterBand::SetStatistics( double dfMinIn, double dfMaxIn,
+                                      double dfMeanIn, double dfStdDevIn )
 {
     // avoid churn if nothing is changing.
-    if( dfMin == this->dfMin
-        && dfMax == this->dfMax
-        && dfMean == this->dfMean
-        && dfStdDev == this->dfStdDev )
+    if( dfMin == dfMinIn
+        && dfMax == dfMaxIn
+        && dfMean == dfMeanIn
+        && dfStdDev == dfStdDevIn )
         return CE_None;
 
-    this->dfMin = dfMin;
-    this->dfMax = dfMax;
-    this->dfMean = dfMean;
-    this->dfStdDev = dfStdDev;
+    dfMin = dfMinIn;
+    dfMax = dfMaxIn;
+    dfMean = dfMeanIn;
+    dfStdDev = dfStdDevIn;
 
     // marks stats valid
     minmaxmeanstddev = HAS_ALL_FLAGS;
 
-    EHdrDataset* poEDS = (EHdrDataset *) poDS;
+    EHdrDataset* poEDS = reinterpret_cast<EHdrDataset *>( poDS );
 
     if( poEDS->RewriteSTX() != CE_None )
-        return RawRasterBand::SetStatistics( dfMin, dfMax, dfMean, dfStdDev );
-    else
-        return CE_None;
+        return RawRasterBand::SetStatistics(
+            dfMinIn, dfMaxIn, dfMeanIn, dfStdDevIn );
+
+    return CE_None;
 }
 
 /************************************************************************/
@@ -2003,12 +2133,12 @@ CPLErr EHdrRasterBand::SetStatistics( double dfMin, double dfMax, double dfMean,
 
 CPLErr EHdrRasterBand::SetColorTable( GDALColorTable *poNewCT )
 {
-    CPLErr err = RawRasterBand::SetColorTable( poNewCT );
+    const CPLErr err = RawRasterBand::SetColorTable( poNewCT );
     if( err != CE_None )
         return err;
-    
-    ((EHdrDataset*)poDS)->bCLRDirty = TRUE;
-   
+
+    reinterpret_cast<EHdrDataset *>( poDS )->bCLRDirty = TRUE;
+
     return CE_None;
 }
 
@@ -2019,32 +2149,28 @@ CPLErr EHdrRasterBand::SetColorTable( GDALColorTable *poNewCT )
 void GDALRegister_EHdr()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "EHdr" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "EHdr" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "EHdr" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "ESRI .hdr Labelled" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#EHdr" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte Int16 UInt16 Int32 UInt32 Float32" );
-
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "EHdr" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "ESRI .hdr Labelled" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#EHdr" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte Int16 UInt16 Int32 UInt32 Float32" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "   <Option name='NBITS' type='int' description='Special pixel bits (1-7)'/>"
 "   <Option name='PIXELTYPE' type='string' description='By setting this to SIGNEDBYTE, a new Byte file can be forced to be written as signed byte'/>"
 "</CreationOptionList>" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-        poDriver->pfnOpen = EHdrDataset::Open;
-        poDriver->pfnCreate = EHdrDataset::Create;
-        poDriver->pfnCreateCopy = EHdrDataset::CreateCopy;
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->pfnOpen = EHdrDataset::Open;
+    poDriver->pfnCreate = EHdrDataset::Create;
+    poDriver->pfnCreateCopy = EHdrDataset::CreateCopy;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/raw/eirdataset.cpp b/frmts/raw/eirdataset.cpp
index a3f96bd..d4b7e79 100644
--- a/frmts/raw/eirdataset.cpp
+++ b/frmts/raw/eirdataset.cpp
@@ -28,16 +28,13 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "rawdataset.h"
-#include "ogr_spatialref.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "ogr_spatialref.h"
+#include "rawdataset.h"
 
 CPL_CVSID("$Id:  $");
 
-CPL_C_START
-void GDALRegister_EIR(void);
-CPL_C_END
-
 /************************************************************************/
 /* ==================================================================== */
 /*              EIRDataset                                              */
@@ -54,18 +51,18 @@ class EIRDataset : public RawDataset
     int    bHDRDirty;
     char **papszHDR;
     char **papszExtraFiles;
-    
+
     void        ResetKeyValue( const char *pszKey, const char *pszValue );
     const char *GetKeyValue( const char *pszKey, const char *pszDefault = "" );
 
   public:
     EIRDataset();
     ~EIRDataset();
-    
+
     virtual CPLErr GetGeoTransform( double * padfTransform );
-    
+
     virtual char **GetFileList();
-    
+
     static int          Identify( GDALOpenInfo * );
     static GDALDataset *Open( GDALOpenInfo * );
 };
@@ -81,13 +78,13 @@ class EIRDataset : public RawDataset
 /*                            EIRDataset()                             */
 /************************************************************************/
 
-EIRDataset::EIRDataset()
+EIRDataset::EIRDataset() :
+    fpImage(NULL),
+    bGotTransform(FALSE),
+    bHDRDirty(FALSE),
+    papszHDR(NULL),
+    papszExtraFiles(NULL)
 {
-    fpImage = NULL;
-    bGotTransform = FALSE;
-    papszHDR = NULL;
-    papszExtraFiles = NULL;
-    bHDRDirty = FALSE;
 }
 
 /************************************************************************/
@@ -101,21 +98,21 @@ EIRDataset::~EIRDataset()
 
     if( nBands > 0 && GetAccess() == GA_Update )
     {
-        int bNoDataSet;
-        double dfNoData;
-        RawRasterBand *poBand = (RawRasterBand *) GetRasterBand( 1 );
+        RawRasterBand *poBand
+            = reinterpret_cast<RawRasterBand *>( GetRasterBand( 1 ) );
 
-        dfNoData = poBand->GetNoDataValue(&bNoDataSet);
+        int bNoDataSet;
+        const double dfNoData = poBand->GetNoDataValue(&bNoDataSet);
         if( bNoDataSet )
         {
-            ResetKeyValue( "NODATA", 
+            ResetKeyValue( "NODATA",
                            CPLString().Printf( "%.8g", dfNoData ) );
         }
     }
 
     if( fpImage != NULL )
-        VSIFCloseL( fpImage );
-    
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fpImage ));
+
     CSLDestroy( papszHDR );
     CSLDestroy( papszExtraFiles );
 }
@@ -124,13 +121,11 @@ EIRDataset::~EIRDataset()
 /*                            GetKeyValue()                             */
 /************************************************************************/
 
-const char *EIRDataset::GetKeyValue( const char *pszKey, 
-                                      const char *pszDefault )
+const char *EIRDataset::GetKeyValue( const char *pszKey,
+                                     const char *pszDefault )
 
 {
-    int i;
-
-    for( i = 0; papszHDR[i] != NULL; i++ )
+    for( int i = 0; papszHDR[i] != NULL; i++ )
     {
         if( EQUALN(pszKey,papszHDR[i],strlen(pszKey))
             && isspace((unsigned char)papszHDR[i][strlen(pszKey)]) )
@@ -138,7 +133,7 @@ const char *EIRDataset::GetKeyValue( const char *pszKey,
             const char *pszValue = papszHDR[i] + strlen(pszKey);
             while( isspace((unsigned char)*pszValue) )
                 pszValue++;
-            
+
             return pszValue;
         }
     }
@@ -156,18 +151,16 @@ const char *EIRDataset::GetKeyValue( const char *pszKey,
 void EIRDataset::ResetKeyValue( const char *pszKey, const char *pszValue )
 
 {
-    int i;
-    char szNewLine[82];
-
     if( strlen(pszValue) > 65 )
     {
         CPLAssert( strlen(pszValue) <= 65 );
         return;
     }
 
-    sprintf( szNewLine, "%-15s%s", pszKey, pszValue );
+    char szNewLine[82];
+    snprintf( szNewLine, sizeof(szNewLine), "%-15s%s", pszKey, pszValue );
 
-    for( i = CSLCount(papszHDR)-1; i >= 0; i-- )
+    for( int i = CSLCount(papszHDR)-1; i >= 0; i-- )
     {
         if( EQUALN(papszHDR[i],szNewLine,strlen(pszKey)+1 ) )
         {
@@ -198,10 +191,8 @@ CPLErr EIRDataset::GetGeoTransform( double * padfTransform )
         memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
         return CE_None;
     }
-    else
-    {
-        return GDALPamDataset::GetGeoTransform( padfTransform );
-    }
+
+    return GDALPamDataset::GetGeoTransform( padfTransform );
 }
 
 /************************************************************************/
@@ -211,17 +202,16 @@ CPLErr EIRDataset::GetGeoTransform( double * padfTransform )
 char **EIRDataset::GetFileList()
 
 {
-    CPLString osPath = CPLGetPath( GetDescription() );
-    CPLString osName = CPLGetBasename( GetDescription() );
-    char **papszFileList = NULL;
-    
-    // Main data file, etc. 
-    papszFileList = GDALPamDataset::GetFileList();
+    const CPLString osPath = CPLGetPath( GetDescription() );
+    const CPLString osName = CPLGetBasename( GetDescription() );
+
+    // Main data file, etc.
+    char **papszFileList = GDALPamDataset::GetFileList();
 
     // Header file.
     papszFileList = CSLInsertStrings( papszFileList, -1,
                                       papszExtraFiles );
-    
+
     return papszFileList;
 }
 
@@ -235,7 +225,7 @@ int EIRDataset::Identify( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->nHeaderBytes < 100 )
         return FALSE;
 
-    if( strstr((const char *) poOpenInfo->pabyHeader, 
+    if( strstr((const char *) poOpenInfo->pabyHeader,
                "IMAGINE_RAW_FILE" ) == NULL )
         return FALSE;
 
@@ -249,20 +239,15 @@ int EIRDataset::Identify( GDALOpenInfo * poOpenInfo )
 GDALDataset *EIRDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    int     i;
-    VSILFILE    *fp;
-    const char *    pszLine;
-    
-    
     if( !Identify( poOpenInfo ) )
         return NULL;
-                  
-    fp = VSIFOpenL( poOpenInfo->pszFilename, "r" );
+
+    VSILFILE *fp = VSIFOpenL( poOpenInfo->pszFilename, "r" );
     if( fp == NULL )
         return NULL;
-    
+
     /* header example and description
-    
+
     IMAGINE_RAW_FILE // must be on first line, by itself
     WIDTH 581        // number of columns in the image
     HEIGHT 695       // number of rows in the image
@@ -274,22 +259,21 @@ GDALDataset *EIRDataset::Open( GDALOpenInfo * poOpenInfo )
     BYTE_ORDER       // LSB MSB; required for U16 U32 S16 S32 F32 F64
     DATA_OFFSET      // start of image data in raster file; default 0 bytes
     END_RAW_FILE     // end RAW file - stop reading
-    
+
     For a true color image with three bands (R, G, B) stored using 8 bits
     for each pixel in each band, DATA_TYPE equals U8 and NUM_LAYERS equals
     3 for a total of 24 bits per pixel.
-    
+
     Note that the current version of ERDAS Raw Raster Reader/Writer does
-    not support the LAYER_SKIP_BYTES, RECORD_SKIP_BYTES, TILE_WIDTH and 
-    TILE_HEIGHT directives. Since the reader does not read the PIXEL_FILES 
-    directive, the reader always assumes that the raw binary file is the 
-    dataset, and the name of this file is the name of the header without the 
+    not support the LAYER_SKIP_BYTES, RECORD_SKIP_BYTES, TILE_WIDTH and
+    TILE_HEIGHT directives. Since the reader does not read the PIXEL_FILES
+    directive, the reader always assumes that the raw binary file is the
+    dataset, and the name of this file is the name of the header without the
     extension. Currently, the reader does not support multiple raw binary
-    files in one dataset or a single file with both the header and the raw 
+    files in one dataset or a single file with both the header and the raw
     binary data at the same time.
     */
-    
-    bool         bDone = FALSE;
+
     int          nRows = -1, nCols = -1, nBands = 1;
     int          nSkipBytes = 0;
     int          nLineCount = 0;
@@ -298,40 +282,39 @@ GDALDataset *EIRDataset::Open( GDALOpenInfo * poOpenInfo )
     char         chByteOrder = 'M';
     char         szLayout[10] = "BIL";
     char         **papszHDR = NULL;
-    
+
     // default raster file: same name with no extension
-    CPLString osPath = CPLGetPath( poOpenInfo->pszFilename );
-    CPLString osName = CPLGetBasename( poOpenInfo->pszFilename );
+    const CPLString osPath = CPLGetPath( poOpenInfo->pszFilename );
+    const CPLString osName = CPLGetBasename( poOpenInfo->pszFilename );
     CPLString osRasterFilename = CPLFormCIFilename( osPath, osName, "" );
-    
+
     // parse the header file
-    while( !bDone && (pszLine = CPLReadLineL( fp )) != NULL )
+    const char *pszLine;
+    while( (pszLine = CPLReadLineL( fp )) != NULL )
     {
-        char    **papszTokens;
-
         nLineCount++;
-        
+
         if ( (nLineCount == 1) && !EQUAL(pszLine,"IMAGINE_RAW_FILE") ) {
             return NULL;
         }
-            
+
         if ( (nLineCount > 50) || EQUAL(pszLine,"END_RAW_FILE") ) {
-            bDone = TRUE;
             break;
         }
-        
+
         if( strlen(pszLine) > 1000 )
             break;
 
         papszHDR = CSLAddString( papszHDR, pszLine );
 
-        papszTokens = CSLTokenizeStringComplex( pszLine, " \t", TRUE, FALSE );
+        char **papszTokens
+            = CSLTokenizeStringComplex( pszLine, " \t", TRUE, FALSE );
         if( CSLCount( papszTokens ) < 2 )
         {
             CSLDestroy( papszTokens );
             continue;
         }
-        
+
         if( EQUAL(papszTokens[0],"WIDTH") )
         {
             nCols = atoi(papszTokens[1]);
@@ -353,12 +336,12 @@ GDALDataset *EIRDataset::Open( GDALOpenInfo * poOpenInfo )
             strncpy( szLayout, papszTokens[1], sizeof(szLayout) );
             szLayout[sizeof(szLayout)-1] = '\0';
         }
-        else if( EQUAL(papszTokens[0],"DATATYPE") 
+        else if( EQUAL(papszTokens[0],"DATATYPE")
                  || EQUAL(papszTokens[0],"DATA_TYPE") )
         {
             if ( EQUAL(papszTokens[1], "U1")
-                 || EQUAL(papszTokens[1], "U2") 
-                 || EQUAL(papszTokens[1], "U4") 
+                 || EQUAL(papszTokens[1], "U2")
+                 || EQUAL(papszTokens[1], "U4")
                  || EQUAL(papszTokens[1], "U8") ) {
                 nBits = 8;
                 eDataType = GDT_Byte;
@@ -388,19 +371,19 @@ GDALDataset *EIRDataset::Open( GDALOpenInfo * poOpenInfo )
                 eDataType = GDT_Float64;
             }
             else {
-                CPLError( CE_Failure, CPLE_NotSupported, 
-                  "EIR driver does not support DATATYPE %s.", 
+                CPLError( CE_Failure, CPLE_NotSupported,
+                  "EIR driver does not support DATATYPE %s.",
                   papszTokens[1] );
                 CSLDestroy( papszTokens );
                 CSLDestroy( papszHDR );
-                VSIFCloseL( fp );
+                CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
                 return NULL;
             }
         }
         else if( EQUAL(papszTokens[0],"BYTE_ORDER") )
         {
             // M for MSB, L for LSB
-            chByteOrder = (char) toupper(papszTokens[1][0]);
+            chByteOrder = static_cast<char>( toupper(papszTokens[1][0]) );
         }
         else if( EQUAL(papszTokens[0],"DATA_OFFSET") )
         {
@@ -409,9 +392,9 @@ GDALDataset *EIRDataset::Open( GDALOpenInfo * poOpenInfo )
 
         CSLDestroy( papszTokens );
     }
-    
-    VSIFCloseL( fp );
-    
+
+    CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
+
 
 /* -------------------------------------------------------------------- */
 /*      Did we get the required keywords?  If not we return with        */
@@ -430,14 +413,14 @@ GDALDataset *EIRDataset::Open( GDALOpenInfo * poOpenInfo )
         CSLDestroy( papszHDR );
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
         CSLDestroy( papszHDR );
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The EIR driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
@@ -445,9 +428,7 @@ GDALDataset *EIRDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    EIRDataset     *poDS;
-
-    poDS = new EIRDataset();
+    EIRDataset *poDS = new EIRDataset();
 
 /* -------------------------------------------------------------------- */
 /*      Capture some information from the file that is of interest.     */
@@ -455,7 +436,6 @@ GDALDataset *EIRDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->nRasterXSize = nCols;
     poDS->nRasterYSize = nRows;
     poDS->papszHDR = papszHDR;
-    
 
 /* -------------------------------------------------------------------- */
 /*      Open target binary file.                                        */
@@ -463,18 +443,17 @@ GDALDataset *EIRDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->fpImage = VSIFOpenL( osRasterFilename.c_str(), "rb" );
     if( poDS->fpImage == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Failed to open %s.\n%s", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to open %s.\n%s",
                   osRasterFilename.c_str(), VSIStrerror( errno ) );
         delete poDS;
         return NULL;
     }
-    poDS->papszExtraFiles = 
-            CSLAddString( poDS->papszExtraFiles, 
+    poDS->papszExtraFiles =
+            CSLAddString( poDS->papszExtraFiles,
                           osRasterFilename );
 
     poDS->eAccess = poOpenInfo->eAccess;
-    
 
 /* -------------------------------------------------------------------- */
 /*      Compute the line offset.                                        */
@@ -501,7 +480,7 @@ GDALDataset *EIRDataset::Open( GDALOpenInfo * poOpenInfo )
         nLineOffset = nItemSize * nBands * nCols;
         nBandOffset = (vsi_l_offset)nItemSize * nCols;
     }
-    
+
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->PamInitialize();
 
@@ -509,45 +488,41 @@ GDALDataset *EIRDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
     poDS->nBands = nBands;
-    for( i = 0; i < poDS->nBands; i++ )
+    for( int i = 0; i < poDS->nBands; i++ )
     {
-        RawRasterBand   *poBand;
-            
-        poBand = 
-            new RawRasterBand( poDS, i+1, poDS->fpImage,
-                                nSkipBytes + nBandOffset * i, 
+        RawRasterBand *poBand
+            = new RawRasterBand( poDS, i+1, poDS->fpImage,
+                                nSkipBytes + nBandOffset * i,
                                 nPixelOffset, nLineOffset, eDataType,
-#ifdef CPL_LSB                               
+#ifdef CPL_LSB
                                 chByteOrder == 'I' || chByteOrder == 'L',
 #else
                                 chByteOrder == 'M',
-#endif        
+#endif
                                 nBits);
 
-            
         poDS->SetBand( i+1, poBand );
     }
 
-    
 /* -------------------------------------------------------------------- */
 /*      look for a worldfile                                            */
 /* -------------------------------------------------------------------- */
-    
+
     if( !poDS->bGotTransform )
-        poDS->bGotTransform = 
-            GDALReadWorldFile( poOpenInfo->pszFilename, 0, 
+        poDS->bGotTransform =
+            GDALReadWorldFile( poOpenInfo->pszFilename, NULL,
                                poDS->adfGeoTransform );
 
     if( !poDS->bGotTransform )
-        poDS->bGotTransform = 
-            GDALReadWorldFile( poOpenInfo->pszFilename, "wld", 
+        poDS->bGotTransform =
+            GDALReadWorldFile( poOpenInfo->pszFilename, "wld",
                                poDS->adfGeoTransform );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
     poDS->TryLoadXML();
-    
+
 /* -------------------------------------------------------------------- */
 /*      Check for overviews.                                            */
 /* -------------------------------------------------------------------- */
@@ -558,29 +533,25 @@ GDALDataset *EIRDataset::Open( GDALOpenInfo * poOpenInfo )
 
 
 /************************************************************************/
-/*                         GDALRegister_EIR()                          */
+/*                         GDALRegister_EIR()                           */
 /************************************************************************/
 
 void GDALRegister_EIR()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "EIR" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "EIR" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "EIR" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Erdas Imagine Raw" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#EIR" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = EIRDataset::Open;
-        poDriver->pfnIdentify = EIRDataset::Identify;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "EIR" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Erdas Imagine Raw" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#EIR" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = EIRDataset::Open;
+    poDriver->pfnIdentify = EIRDataset::Identify;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/raw/envidataset.cpp b/frmts/raw/envidataset.cpp
index b0b544c..7f94e05 100644
--- a/frmts/raw/envidataset.cpp
+++ b/frmts/raw/envidataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: envidataset.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: envidataset.cpp 33837 2016-03-31 19:46:49Z goatbar $
  *
  * Project:  ENVI .hdr Driver
  * Purpose:  Implementation of ENVI .hdr labelled raw raster support.
@@ -29,16 +29,13 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "rawdataset.h"
-#include "ogr_spatialref.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "ogr_spatialref.h"
+#include "rawdataset.h"
 #include <algorithm>
 
-CPL_CVSID("$Id: envidataset.cpp 27942 2014-11-11 00:57:41Z rouault $");
-
-CPL_C_START
-void GDALRegister_ENVI(void);
-CPL_C_END
+CPL_CVSID("$Id: envidataset.cpp 33837 2016-03-31 19:46:49Z goatbar $");
 
 static const int anUsgsEsriZones[] =
 {
@@ -180,7 +177,7 @@ static const int anUsgsEsriZones[] =
  5200, 6076,
  5201, 6051,
  5202, 6051,
- 5300,    0, 
+ 5300,    0,
  5400,    0
 };
 
@@ -189,33 +186,32 @@ static const int anUsgsEsriZones[] =
 /*                                                                      */
 /*      Convert ITTVIS style state plane zones to NOS style state       */
 /*      plane zones.  The ENVI default is to use the new NOS zones,     */
-/*      but the old state plane zones can be used.  Handle this.        */ 
+/*      but the old state plane zones can be used.  Handle this.        */
 /************************************************************************/
 
 static int ITTVISToUSGSZone( int nITTVISZone )
 
 {
-    int		nPairs = sizeof(anUsgsEsriZones) / (2*sizeof(int));
-    int		i;
-    
-	// Default is to use the zone as-is, as long as it is in the 
-	// available list
-    for( i = 0; i < nPairs; i++ )
+    const int nPairs = sizeof(anUsgsEsriZones) / (2*sizeof(int));
+
+    // Default is to use the zone as-is, as long as it is in the
+    // available list
+    for( int i = 0; i < nPairs; i++ )
     {
         if( anUsgsEsriZones[i*2] == nITTVISZone )
             return anUsgsEsriZones[i*2];
     }
 
-	// If not found in the new style, see if it is present in the
-	// old style list and convert it.  We don't expect to see this
-	// often, but older files allowed it and may still exist.
-    for( i = 0; i < nPairs; i++ )
+    // If not found in the new style, see if it is present in the
+    // old style list and convert it.  We don't expect to see this
+    // often, but older files allowed it and may still exist.
+    for( int i = 0; i < nPairs; i++ )
     {
         if( anUsgsEsriZones[i*2+1] == nITTVISZone )
             return anUsgsEsriZones[i*2];
     }
 
-    return nITTVISZone; // perhaps it *is* the USGS zone?
+    return nITTVISZone; // Perhaps it *is* the USGS zone?
 }
 
 /************************************************************************/
@@ -230,17 +226,17 @@ class ENVIDataset : public RawDataset
 {
     friend class ENVIRasterBand;
 
-    VSILFILE	*fpImage;	// image data file.
-    VSILFILE	*fp;		// header file
-    char	*pszHDRFilename;
+    VSILFILE   *fpImage;  // image data file.
+    VSILFILE   *fp;  // header file
+    char       *pszHDRFilename;
 
-    int		bFoundMapinfo;
+    int         bFoundMapinfo;
 
     int         bHeaderDirty;
 
     double      adfGeoTransform[6];
 
-    char	*pszProjection;
+    char       *pszProjection;
 
     char        **papszHeader;
 
@@ -256,10 +252,11 @@ class ENVIDataset : public RawDataset
     void        SetENVIDatum( OGRSpatialReference *, const char * );
     void        SetENVIEllipse( OGRSpatialReference *, char ** );
     void        WriteProjectionInfo();
-    int         ParseRpcCoeffsMetaDataString(const char *psName, char *papszVal[], int& idx);
+    int         ParseRpcCoeffsMetaDataString( const char *psName,
+                                              char *papszVal[], int& idx );
     int         WriteRpcInfo();
     int         WritePseudoGcpInfo();
-    
+
     char        **SplitList( const char * );
 
     enum Interleave { BSQ, BIL, BIP } interleave;
@@ -267,7 +264,7 @@ class ENVIDataset : public RawDataset
 
   public:
             ENVIDataset();
-            ~ENVIDataset();
+    virtual ~ENVIDataset();
 
     virtual void    FlushCache( void );
     virtual CPLErr  GetGeoTransform( double * padfTransform );
@@ -275,7 +272,7 @@ class ENVIDataset : public RawDataset
     virtual const char *GetProjectionRef(void);
     virtual CPLErr  SetProjection( const char * );
     virtual char  **GetFileList(void);
-    
+
     virtual void        SetDescription( const char * );
 
     virtual CPLErr      SetMetadata( char ** papszMetadata,
@@ -306,6 +303,7 @@ class ENVIRasterBand : public RawRasterBand
                                 int nLineOffset,
                                 GDALDataType eDataType, int bNativeOrder,
                                 int bIsVSIL = FALSE, int bOwnsFP = FALSE );
+    virtual ~ENVIRasterBand() {}
 
     virtual void        SetDescription( const char * );
 
@@ -316,25 +314,23 @@ class ENVIRasterBand : public RawRasterBand
 /*                            ENVIDataset()                             */
 /************************************************************************/
 
-ENVIDataset::ENVIDataset()
+ENVIDataset::ENVIDataset() :
+    fpImage(NULL),
+    fp(NULL),
+    pszHDRFilename(NULL),
+    bFoundMapinfo(FALSE),
+    bHeaderDirty(FALSE),
+    papszHeader(NULL),
+    interleave(BSQ)
 {
-    fpImage = NULL;
-    fp = NULL;
-    pszHDRFilename = NULL;
-    pszProjection = CPLStrdup("");
-
-    papszHeader = NULL;
-
-    bFoundMapinfo = FALSE;
-
-    bHeaderDirty = FALSE;
-
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
+
+    pszProjection = CPLStrdup("");
 }
 
 /************************************************************************/
@@ -346,9 +342,19 @@ ENVIDataset::~ENVIDataset()
 {
     FlushCache();
     if( fpImage )
-        VSIFCloseL( fpImage );
+    {
+        if( VSIFCloseL( fpImage ) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        }
+    }
     if( fp )
-        VSIFCloseL( fp );
+    {
+        if( VSIFCloseL( fp ) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        }
+    }
     CPLFree( pszProjection );
     CSLDestroy( papszHeader );
     CPLFree(pszHDRFilename);
@@ -371,62 +377,62 @@ void ENVIDataset::FlushCache()
     // If opening an existing file in Update mode (i.e. "r+") we need to make
     // sure any existing content is cleared, otherwise the file may contain
     // trailing content from the previous write.
-    VSIFTruncateL( fp, 0 ); 
+    if( VSIFTruncateL( fp, 0 ) != 0 )
+        return;
 
-    VSIFSeekL( fp, 0, SEEK_SET );
+    if( VSIFSeekL( fp, 0, SEEK_SET ) != 0 )
+        return;
 /* -------------------------------------------------------------------- */
 /*      Rewrite out the header.                                           */
 /* -------------------------------------------------------------------- */
-    int		iBigEndian;
-
-    const char	*pszInterleaving;
-    char** catNames;
-
+    const int iBigEndian =
 #ifdef CPL_LSB
-    iBigEndian = 0;
+    0
 #else
-    iBigEndian = 1;
+    1
 #endif
+        ;
 
-    VSIFPrintfL( fp, "ENVI\n" );
+    bool bOK = VSIFPrintfL( fp, "ENVI\n" ) >= 0;
     if ("" != sDescription)
-        VSIFPrintfL( fp, "description = {\n%s}\n", sDescription.c_str());
-    VSIFPrintfL( fp, "samples = %d\nlines   = %d\nbands   = %d\n",
-		nRasterXSize, nRasterYSize, nBands );
+        bOK &= VSIFPrintfL( fp, "description = {\n%s}\n", sDescription.c_str()) >= 0;
+    bOK &= VSIFPrintfL( fp, "samples = %d\nlines   = %d\nbands   = %d\n",
+                 nRasterXSize, nRasterYSize, nBands ) >= 0;
 
-    catNames = band->GetCategoryNames();
+    char** catNames = band->GetCategoryNames();
 
-    VSIFPrintfL( fp, "header offset = 0\n");
-    if (0 == catNames)
-        VSIFPrintfL( fp, "file type = ENVI Standard\n" );
+    bOK &= VSIFPrintfL( fp, "header offset = 0\n") >= 0;
+    if (NULL == catNames)
+        bOK &= VSIFPrintfL( fp, "file type = ENVI Standard\n" ) >= 0;
     else
-        VSIFPrintfL( fp, "file type = ENVI Classification\n" );
+        bOK &= VSIFPrintfL( fp, "file type = ENVI Classification\n" ) >= 0;
 
-    int iENVIType = GetEnviType(band->GetRasterDataType());
-    VSIFPrintfL( fp, "data type = %d\n", iENVIType );
+    const int iENVIType = GetEnviType(band->GetRasterDataType());
+    bOK &= VSIFPrintfL( fp, "data type = %d\n", iENVIType ) >= 0;
+    const char *pszInterleaving = NULL;
     switch (interleave)
     {
       case BIP:
-        pszInterleaving = "bip";		    // interleaved by pixel
+        pszInterleaving = "bip";  // interleaved by pixel
         break;
       case BIL:
-        pszInterleaving = "bil";		    // interleaved by line
+        pszInterleaving = "bil";  // interleaved by line
         break;
       case BSQ:
-        pszInterleaving = "bsq";		// band sequental by default
+        pszInterleaving = "bsq";  // band sequential by default
         break;
       default:
-    	pszInterleaving = "bsq";
+        pszInterleaving = "bsq";
         break;
     }
-    VSIFPrintfL( fp, "interleave = %s\n", pszInterleaving);
-    VSIFPrintfL( fp, "byte order = %d\n", iBigEndian );
+    bOK &= VSIFPrintfL( fp, "interleave = %s\n", pszInterleaving) >= 0;
+    bOK &= VSIFPrintfL( fp, "byte order = %d\n", iBigEndian ) >= 0;
 
 /* -------------------------------------------------------------------- */
 /*      Write class and color information                               */
 /* -------------------------------------------------------------------- */
     catNames = band->GetCategoryNames();
-    if (0 != catNames)
+    if (NULL != catNames)
     {
         int nrClasses = 0;
         while (*catNames++)
@@ -434,41 +440,44 @@ void ENVIDataset::FlushCache()
 
         if (nrClasses > 0)
         {
-            VSIFPrintfL( fp, "classes = %d\n", nrClasses );
+            bOK &= VSIFPrintfL( fp, "classes = %d\n", nrClasses ) >= 0;
 
             GDALColorTable* colorTable = band->GetColorTable();
-            if (0 != colorTable)
+            if (NULL != colorTable)
             {
                 int nrColors = colorTable->GetColorEntryCount();
                 if (nrColors > nrClasses)
                     nrColors = nrClasses;
-                VSIFPrintfL( fp, "class lookup = {\n");
+                bOK &= VSIFPrintfL( fp, "class lookup = {\n") >= 0;
                 for (int i = 0; i < nrColors; ++i)
                 {
                     const GDALColorEntry* color = colorTable->GetColorEntry(i);
-                    VSIFPrintfL(fp, "%d, %d, %d", color->c1, color->c2, color->c3);
+                    bOK &= VSIFPrintfL( fp, "%d, %d, %d",
+                                        color->c1, color->c2, color->c3) >= 0;
                     if (i < nrColors - 1)
                     {
-                        VSIFPrintfL(fp, ", ");
+                        bOK &= VSIFPrintfL(fp, ", ") >= 0;
                         if (0 == (i+1) % 5)
-                            VSIFPrintfL(fp, "\n");
+                            bOK &= VSIFPrintfL(fp, "\n") >= 0;
                     }
                 }
-                VSIFPrintfL(fp, "}\n");
+                bOK &= VSIFPrintfL(fp, "}\n") >= 0;
             }
 
             catNames = band->GetCategoryNames();
-            if (0 != *catNames)
+            if (NULL != *catNames)
             {
-                VSIFPrintfL( fp, "class names = {\n%s", *catNames++);
+                bOK &= VSIFPrintfL( fp, "class names = {\n%s", *catNames) >= 0;
+                catNames ++;
                 int i = 0;
                 while (*catNames) {
-                    VSIFPrintfL( fp, ",");
+                    bOK &= VSIFPrintfL( fp, ",") >= 0;
                     if (0 == (++i) % 5)
-                        VSIFPrintfL(fp, "\n");
-                    VSIFPrintfL( fp, " %s", *catNames++);
+                        bOK &= VSIFPrintfL(fp, "\n") >= 0;
+                    bOK &= VSIFPrintfL( fp, " %s", *catNames) >= 0;
+                    catNames ++;
                 }
-                VSIFPrintfL( fp, "}\n");
+                bOK &= VSIFPrintfL( fp, "}\n") >= 0;
             }
         }
     }
@@ -476,10 +485,10 @@ void ENVIDataset::FlushCache()
 /* -------------------------------------------------------------------- */
 /*      Write the rest of header.                                       */
 /* -------------------------------------------------------------------- */
-    
-    // only one map info type should be set
+
+    // Only one map info type should be set:
     //     - rpc
-    //     - pseudo/gcp 
+    //     - pseudo/gcp
     //     - standard
     if ( !WriteRpcInfo() ) // are rpcs in the metadata
     {
@@ -490,38 +499,40 @@ void ENVIDataset::FlushCache()
     }
 
 
-    VSIFPrintfL( fp, "band names = {\n" );
+    bOK &= VSIFPrintfL( fp, "band names = {\n" ) >= 0;
     for ( int i = 1; i <= nBands; i++ )
     {
         CPLString sBandDesc = GetRasterBand( i )->GetDescription();
 
         if ( sBandDesc == "" )
             sBandDesc = CPLSPrintf( "Band %d", i );
-        VSIFPrintfL( fp, "%s", sBandDesc.c_str() );
+        bOK &= VSIFPrintfL( fp, "%s", sBandDesc.c_str() ) >= 0;
         if ( i != nBands )
-            VSIFPrintfL( fp, ",\n" );
+            bOK &= VSIFPrintfL( fp, ",\n" ) >= 0;
     }
-    VSIFPrintfL( fp, "}\n" );
+    bOK &= VSIFPrintfL( fp, "}\n" ) >= 0;
 
 /* -------------------------------------------------------------------- */
 /*      Write the metadata that was read into the ENVI domain           */
 /* -------------------------------------------------------------------- */
     char** papszENVIMetadata = GetMetadata("ENVI");
 
-    int i;
-    int count = CSLCount(papszENVIMetadata);
-    char **papszTokens;
+    const int count = CSLCount(papszENVIMetadata);
 
     // For every item of metadata in the ENVI domain
-    for (i = 0; i < count; i++)
+    for (int i = 0; i < count; i++)
     {
         // Split the entry into two parts at the = character
         char *pszEntry = papszENVIMetadata[i];
-        papszTokens = CSLTokenizeString2( pszEntry, "=", CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES);
+        char **papszTokens
+            = CSLTokenizeString2( pszEntry, "=",
+                                  CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES);
 
         if (CSLCount(papszTokens) != 2)
         {
-            CPLDebug("ENVI", "Line of header file could not be split at = into two elements: %s", papszENVIMetadata[i]);
+            CPLDebug( "ENVI",
+                      "Line of header file could not be split at = into "
+                      "two elements: %s", papszENVIMetadata[i] );
             CSLDestroy( papszTokens );
             continue;
         }
@@ -529,20 +540,32 @@ void ENVIDataset::FlushCache()
         std::string poKey(papszTokens[0]);
         std::replace(poKey.begin(), poKey.end(), '_', ' ');
 
-        // Don't write it out if it is one of the bits of metadata that is written out elsewhere in this routine
-        if (poKey == "description" || poKey == "samples" || poKey == "lines" ||
-            poKey == "bands" || poKey == "header offset" || poKey == "file type" ||
-            poKey == "data type" || poKey == "interleave" || poKey == "byte order" ||
-            poKey == "class names" || poKey == "band names" || poKey == "map info" ||
-            poKey == "projection info")
+        // Don't write it out if it is one of the bits of metadata that is
+        // written out elsewhere in this routine.
+        if ( poKey == "description" ||
+             poKey == "samples" ||
+             poKey == "lines" ||
+             poKey == "bands" ||
+             poKey == "header offset" ||
+             poKey == "file type" ||
+             poKey == "data type" ||
+             poKey == "interleave" ||
+             poKey == "byte order" ||
+             poKey == "class names" ||
+             poKey == "band names" ||
+             poKey == "map info" ||
+             poKey == "projection info" )
         {
             CSLDestroy( papszTokens );
             continue;
         }
-        VSIFPrintfL( fp, "%s = %s\n", poKey.c_str(), papszTokens[1]);
+        bOK &= VSIFPrintfL( fp, "%s = %s\n", poKey.c_str(), papszTokens[1]) >= 0;
         CSLDestroy( papszTokens );
     }
 
+    if( !bOK )
+        return;
+
     /* Clean dirty flag */
     bHeaderDirty = FALSE;
 }
@@ -550,23 +573,21 @@ void ENVIDataset::FlushCache()
 /************************************************************************/
 /*                            GetFileList()                             */
 /************************************************************************/
-	 	 
-char **ENVIDataset::GetFileList() 
-    
-{ 
-    char **papszFileList = NULL; 
-    
-    // Main data file, etc.  
-    papszFileList = RawDataset::GetFileList(); 
-    
-    // Header file. 
+
+char **ENVIDataset::GetFileList()
+
+{
+    // Main data file, etc.
+    char **papszFileList = RawDataset::GetFileList();
+
+    // Header file.
     papszFileList = CSLAddString( papszFileList, pszHDRFilename );
 
     // Statistics file
     if (osStaFilename.size() != 0)
         papszFileList = CSLAddString( papszFileList, osStaFilename );
-    
-    return papszFileList; 
+
+    return papszFileList;
 }
 
 /************************************************************************/
@@ -603,21 +624,19 @@ static int ENVIGetEPSGGeogCS( OGRSpatialReference *poThis )
 /* -------------------------------------------------------------------- */
 /*      Is this a "well known" geographic coordinate system?            */
 /* -------------------------------------------------------------------- */
-    int bWGS, bNAD;
-
-    bWGS = strstr(pszGEOGCS,"WGS") != NULL
+    const bool bWGS = strstr(pszGEOGCS,"WGS") != NULL
         || strstr(pszDatum, "WGS")
-        || strstr(pszGEOGCS,"World Geodetic System")
-        || strstr(pszGEOGCS,"World_Geodetic_System")
+        || strstr(pszGEOGCS, "World Geodetic System")
+        || strstr(pszGEOGCS, "World_Geodetic_System")
         || strstr(pszDatum, "World Geodetic System")
-        || strstr(pszDatum, "World_Geodetic_System"); 
+        || strstr(pszDatum, "World_Geodetic_System");
 
-    bNAD = strstr(pszGEOGCS,"NAD") != NULL
+    const bool bNAD = strstr(pszGEOGCS,"NAD") != NULL
         || strstr(pszDatum, "NAD")
-        || strstr(pszGEOGCS,"North American")
-        || strstr(pszGEOGCS,"North_American")
+        || strstr(pszGEOGCS, "North American")
+        || strstr(pszGEOGCS, "North_American")
         || strstr(pszDatum, "North American")
-        || strstr(pszDatum, "North_American"); 
+        || strstr(pszDatum, "North_American");
 
     if( bWGS && (strstr(pszGEOGCS,"84") || strstr(pszDatum,"84")) )
         return 4326;
@@ -637,12 +656,12 @@ static int ENVIGetEPSGGeogCS( OGRSpatialReference *poThis )
 /* -------------------------------------------------------------------- */
     pszAuthName = poThis->GetAuthorityName( "GEOGCS|DATUM" );
 
-    if( pszAuthName != NULL 
-        && EQUAL(pszAuthName,"epsg") 
+    if( pszAuthName != NULL
+        && EQUAL(pszAuthName,"epsg")
         && poThis->GetPrimeMeridian() == 0.0 )
     {
-        int nDatum = atoi(poThis->GetAuthorityCode("GEOGCS|DATUM"));
-        
+        const int nDatum = atoi(poThis->GetAuthorityCode("GEOGCS|DATUM"));
+
         if( nDatum >= 6000 && nDatum <= 6999 )
             return nDatum - 2000;
     }
@@ -662,25 +681,25 @@ void ENVIDataset::WriteProjectionInfo()
 /*      line.                                                           */
 /* -------------------------------------------------------------------- */
     CPLString   osLocation;
-
-    osLocation.Printf( "1, 1, %.15g, %.15g, %.15g, %.15g", 
-                       adfGeoTransform[0], adfGeoTransform[3], 
+    osLocation.Printf( "1, 1, %.15g, %.15g, %.15g, %.15g",
+                       adfGeoTransform[0], adfGeoTransform[3],
                        adfGeoTransform[1], fabs(adfGeoTransform[5]) );
-                       
+
 /* -------------------------------------------------------------------- */
 /*      Minimal case - write out simple geotransform if we have a       */
 /*      non-default geotransform.                                       */
 /* -------------------------------------------------------------------- */
     if( pszProjection == NULL || strlen(pszProjection) == 0  ||
-        (strlen(pszProjection) >= 8 && strncmp(pszProjection, "LOCAL_CS", 8) == 0 ) )
+        (strlen(pszProjection) >= 8 && STARTS_WITH(pszProjection, "LOCAL_CS") ) )
     {
         if( adfGeoTransform[0] != 0.0 || adfGeoTransform[1] != 1.0
             || adfGeoTransform[2] != 0.0 || adfGeoTransform[3] != 0.0
             || adfGeoTransform[4] != 0.0 || adfGeoTransform[5] != 1.0 )
         {
             const char* pszHemisphere = "North";
-            VSIFPrintfL( fp, "map info = {Arbitrary, %s, %d, %s}\n",
-                         osLocation.c_str(), 0, pszHemisphere);
+            if( VSIFPrintfL( fp, "map info = {Arbitrary, %s, %d, %s}\n",
+                             osLocation.c_str(), 0, pszHemisphere) < 0 )
+                return;
         }
         return;
     }
@@ -689,9 +708,9 @@ void ENVIDataset::WriteProjectionInfo()
 /*      Ingest WKT.                                                     */
 /* -------------------------------------------------------------------- */
     OGRSpatialReference oSRS;
-    
-    char	*pszProj = pszProjection;
-    
+
+    char *pszProj = pszProjection;
+
     if( oSRS.importFromWkt( &pszProj ) != OGRERR_NONE )
         return;
 
@@ -699,9 +718,8 @@ void ENVIDataset::WriteProjectionInfo()
 /*      Try to translate the datum and get major/minor ellipsoid        */
 /*      values.                                                         */
 /* -------------------------------------------------------------------- */
-    int nEPSG_GCS = ENVIGetEPSGGeogCS( &oSRS );
-    CPLString osDatum, osCommaDatum;
-    double dfA, dfB;
+    const int nEPSG_GCS = ENVIGetEPSGGeogCS( &oSRS );
+    CPLString osDatum;
 
     if( nEPSG_GCS == 4326 )
         osDatum = "WGS-84";
@@ -722,28 +740,28 @@ void ENVIDataset::WriteProjectionInfo()
     else if( nEPSG_GCS == 4275 )
         osDatum = "Nouvelle Triangulation Francaise IGN";
 
+    CPLString osCommaDatum;
     if( osDatum != "" )
         osCommaDatum.Printf( ",%s", osDatum.c_str() );
 
-    dfA = oSRS.GetSemiMajor();
-    dfB = oSRS.GetSemiMinor();
+    const double dfA = oSRS.GetSemiMajor();
+    const double dfB = oSRS.GetSemiMinor();
 
 /* -------------------------------------------------------------------- */
 /*      Do we have unusual linear units?                                */
 /* -------------------------------------------------------------------- */
     CPLString osOptionalUnits;
-    if( fabs(oSRS.GetLinearUnits()-0.3048) < 0.0001 )
+    if( fabs(oSRS.GetLinearUnits() - 0.3048) < 0.0001 )
         osOptionalUnits = ", units=Feet";
 
 /* -------------------------------------------------------------------- */
 /*      Handle UTM case.                                                */
 /* -------------------------------------------------------------------- */
-    const char	*pszHemisphere;
+    const char *pszHemisphere = NULL;
     const char  *pszProjName = oSRS.GetAttrValue("PROJECTION");
-    int		bNorth;
-    int		iUTMZone;
-
-    iUTMZone = oSRS.GetUTMZone( &bNorth );
+    int bNorth = FALSE;
+    const int iUTMZone = oSRS.GetUTMZone( &bNorth );
+    bool bOK = true;
     if ( iUTMZone )
     {
         if ( bNorth )
@@ -751,192 +769,261 @@ void ENVIDataset::WriteProjectionInfo()
         else
             pszHemisphere = "South";
 
-        VSIFPrintfL( fp, "map info = {UTM, %s, %d, %s%s%s}\n",
-                     osLocation.c_str(), iUTMZone, pszHemisphere,
-                     osCommaDatum.c_str(), osOptionalUnits.c_str() );
+        bOK &=
+            VSIFPrintfL( fp, "map info = {UTM, %s, %d, %s%s%s}\n",
+                         osLocation.c_str(), iUTMZone, pszHemisphere,
+                         osCommaDatum.c_str(), osOptionalUnits.c_str() ) >= 0;
     }
     else if( oSRS.IsGeographic() )
     {
-        VSIFPrintfL( fp, "map info = {Geographic Lat/Lon, %s%s}\n",
-                     osLocation.c_str(), osCommaDatum.c_str());
+        bOK &=
+            VSIFPrintfL( fp, "map info = {Geographic Lat/Lon, %s%s}\n",
+                         osLocation.c_str(), osCommaDatum.c_str()) >= 0;
     }
     else if( pszProjName == NULL )
     {
-        // what to do? 
+        // what to do?
     }
     else if( EQUAL(pszProjName,SRS_PT_NEW_ZEALAND_MAP_GRID) )
     {
-        VSIFPrintfL( fp, "map info = {New Zealand Map Grid, %s%s%s}\n",
-                     osLocation.c_str(), 
-                     osCommaDatum.c_str(), osOptionalUnits.c_str() );
-
-        VSIFPrintfL( fp, "projection info = {39, %.16g, %.16g, %.16g, %.16g, %.16g, %.16g%s, New Zealand Map Grid}\n",
-                     dfA, dfB, 
-                     oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
-                     osCommaDatum.c_str() );
+        bOK &= VSIFPrintfL( fp, "map info = {New Zealand Map Grid, %s%s%s}\n",
+                     osLocation.c_str(),
+                     osCommaDatum.c_str(), osOptionalUnits.c_str() ) >= 0;
+
+        bOK &=
+            VSIFPrintfL(
+                fp,
+                "projection info = {39, %.16g, %.16g, %.16g, %.16g, "
+                "%.16g, %.16g%s, New Zealand Map Grid}\n",
+                dfA, dfB,
+                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
+                oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
+                osCommaDatum.c_str() ) >= 0;
     }
     else if( EQUAL(pszProjName,SRS_PT_TRANSVERSE_MERCATOR) )
     {
-        VSIFPrintfL( fp, "map info = {Transverse Mercator, %s%s%s}\n",
-                     osLocation.c_str(), 
-                     osCommaDatum.c_str(), osOptionalUnits.c_str() );
-
-        VSIFPrintfL( fp, "projection info = {3, %.16g, %.16g, %.16g, %.16g, %.16g, %.16g, %.16g%s, Transverse Mercator}\n",
-                     dfA, dfB, 
-                     oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
-                     osCommaDatum.c_str() );
+        bOK &= VSIFPrintfL( fp, "map info = {Transverse Mercator, %s%s%s}\n",
+                     osLocation.c_str(),
+                     osCommaDatum.c_str(), osOptionalUnits.c_str() ) >= 0;
+
+        bOK &=
+            VSIFPrintfL(
+                fp,
+                "projection info = {3, %.16g, %.16g, %.16g, ""%.16g, %.16g, "
+                "%.16g, %.16g%s, Transverse Mercator}\n",
+                dfA, dfB,
+                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
+                oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
+                oSRS.GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
+                osCommaDatum.c_str() ) >= 0;
     }
     else if( EQUAL(pszProjName,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP)
              || EQUAL(pszProjName,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM) )
     {
-        VSIFPrintfL( fp, "map info = {Lambert Conformal Conic, %s%s%s}\n",
-                     osLocation.c_str(), 
-                     osCommaDatum.c_str(), osOptionalUnits.c_str() );
-
-        VSIFPrintfL( fp, "projection info = {4, %.16g, %.16g, %.16g, %.16g, %.16g, %.16g, %.16g, %.16g%s, Lambert Conformal Conic}\n",
-                     dfA, dfB, 
-                     oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0),
-                     osCommaDatum.c_str() );
+        bOK &=
+            VSIFPrintfL(
+                fp, "map info = {Lambert Conformal Conic, %s%s%s}\n",
+                osLocation.c_str(),
+                osCommaDatum.c_str(), osOptionalUnits.c_str() ) >= 0;
+
+        bOK &=
+            VSIFPrintfL(
+                fp,
+                "projection info = {4, %.16g, %.16g, %.16g, %.16g, %.16g, "
+                "%.16g, %.16g, %.16g%s, Lambert Conformal Conic}\n",
+                dfA, dfB,
+                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
+                oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
+                oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
+                oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0),
+                osCommaDatum.c_str() ) >= 0;
     }
     else if( EQUAL(pszProjName,
                    SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN) )
     {
-        VSIFPrintfL( fp, "map info = {Hotine Oblique Mercator A, %s%s%s}\n",
-                     osLocation.c_str(), 
-                     osCommaDatum.c_str(), osOptionalUnits.c_str() );
-
-        VSIFPrintfL( fp, "projection info = {5, %.16g, %.16g, %.16g, %.16g, %.16g, %.16g, %.16g, %.16g, %.16g, %.16g%s, Hotine Oblique Mercator A}\n",
-                     dfA, dfB, 
-                     oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_POINT_1,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_LONGITUDE_OF_POINT_1,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_POINT_2,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_LONGITUDE_OF_POINT_2,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
-                     osCommaDatum.c_str() );
+        bOK &=
+            VSIFPrintfL(
+                fp,
+                "map info = {Hotine Oblique Mercator A, %s%s%s}\n",
+                osLocation.c_str(),
+                osCommaDatum.c_str(), osOptionalUnits.c_str() ) >= 0;
+
+        bOK &=
+            VSIFPrintfL(
+                fp,
+                "projection info = {5, %.16g, %.16g, %.16g, %.16g, %.16g, "
+                "%.16g, %.16g, %.16g, %.16g, %.16g%s, Hotine Oblique Mercator A}\n",
+                dfA, dfB,
+                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
+                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_POINT_1,0.0),
+                oSRS.GetNormProjParm(SRS_PP_LONGITUDE_OF_POINT_1,0.0),
+                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_POINT_2,0.0),
+                oSRS.GetNormProjParm(SRS_PP_LONGITUDE_OF_POINT_2,0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
+                oSRS.GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
+                osCommaDatum.c_str() ) >= 0;
     }
     else if( EQUAL(pszProjName,SRS_PT_HOTINE_OBLIQUE_MERCATOR) )
     {
-        VSIFPrintfL( fp, "map info = {Hotine Oblique Mercator B, %s%s%s}\n",
-                     osLocation.c_str(), 
-                     osCommaDatum.c_str(), osOptionalUnits.c_str() );
-
-        VSIFPrintfL( fp, "projection info = {6, %.16g, %.16g, %.16g, %.16g, %.16g, %.16g, %.16g, %.16g%s, Hotine Oblique Mercator B}\n",
-                     dfA, dfB, 
-                     oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_AZIMUTH,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
-                     osCommaDatum.c_str() );
-    }
-    else if( EQUAL(pszProjName,SRS_PT_STEREOGRAPHIC) 
+        bOK &=
+            VSIFPrintfL(
+                fp,
+                "map info = {Hotine Oblique Mercator B, %s%s%s}\n",
+                osLocation.c_str(),
+                osCommaDatum.c_str(), osOptionalUnits.c_str() ) >= 0;
+
+        bOK &=
+            VSIFPrintfL(
+                fp,
+                "projection info = {6, %.16g, %.16g, %.16g, %.16g, %.16g, "
+                "%.16g, %.16g, %.16g%s, Hotine Oblique Mercator B}\n",
+                dfA, dfB,
+                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
+                oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
+                oSRS.GetNormProjParm(SRS_PP_AZIMUTH,0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
+                oSRS.GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
+                osCommaDatum.c_str() ) >= 0;
+    }
+    else if( EQUAL(pszProjName,SRS_PT_STEREOGRAPHIC)
              || EQUAL(pszProjName,SRS_PT_OBLIQUE_STEREOGRAPHIC) )
     {
-        VSIFPrintfL( fp, "map info = {Stereographic (ellipsoid), %s%s%s}\n",
-                     osLocation.c_str(), 
-                     osCommaDatum.c_str(), osOptionalUnits.c_str() );
-
-        VSIFPrintfL( fp, "projection info = {7, %.16g, %.16g, %.16g, %.16g, %.16g, %.16g, %.16g, %s, Stereographic (ellipsoid)}\n",
-                     dfA, dfB, 
-                     oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
-                     osCommaDatum.c_str() );
+        bOK &=
+            VSIFPrintfL(
+                fp,
+                "map info = {Stereographic (ellipsoid), %s%s%s}\n",
+                osLocation.c_str(),
+                osCommaDatum.c_str(), osOptionalUnits.c_str() ) >= 0;
+
+        bOK &=
+            VSIFPrintfL(
+                fp,
+                "projection info = {7, %.16g, %.16g, %.16g, %.16g, %.16g, "
+                "%.16g, %.16g, %s, Stereographic (ellipsoid)}\n",
+                dfA, dfB,
+                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
+                oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
+                oSRS.GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
+                osCommaDatum.c_str() ) >= 0;
     }
     else if( EQUAL(pszProjName,SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
     {
-        VSIFPrintfL( fp, "map info = {Albers Conical Equal Area, %s%s%s}\n",
-                     osLocation.c_str(), 
-                     osCommaDatum.c_str(), osOptionalUnits.c_str() );
-
-        VSIFPrintfL( fp, "projection info = {9, %.16g, %.16g, %.16g, %.16g, %.16g, %.16g, %.16g, %.16g%s, Albers Conical Equal Area}\n",
-                     dfA, dfB, 
-                     oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0),
-                     osCommaDatum.c_str() );
+        bOK &=
+            VSIFPrintfL(
+                fp,
+                "map info = {Albers Conical Equal Area, %s%s%s}\n",
+                osLocation.c_str(),
+                osCommaDatum.c_str(), osOptionalUnits.c_str() ) >= 0;
+
+        bOK &=
+            VSIFPrintfL(
+                fp,
+                "projection info = {9, %.16g, %.16g, %.16g, %.16g, %.16g, "
+                "%.16g, %.16g, %.16g%s, Albers Conical Equal Area}\n",
+                dfA, dfB,
+                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
+                oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
+                oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
+                oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0),
+                osCommaDatum.c_str() ) >= 0;
     }
     else if( EQUAL(pszProjName,SRS_PT_POLYCONIC) )
     {
-        VSIFPrintfL( fp, "map info = {Polyconic, %s%s%s}\n",
-                     osLocation.c_str(), 
-                     osCommaDatum.c_str(), osOptionalUnits.c_str() );
-
-        VSIFPrintfL( fp, "projection info = {10, %.16g, %.16g, %.16g, %.16g, %.16g, %.16g%s, Polyconic}\n",
-                     dfA, dfB, 
-                     oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
-                     osCommaDatum.c_str() );
+        bOK &= VSIFPrintfL( fp, "map info = {Polyconic, %s%s%s}\n",
+                     osLocation.c_str(),
+                     osCommaDatum.c_str(), osOptionalUnits.c_str() ) >= 0;
+
+        bOK &=
+            VSIFPrintfL(
+                fp,
+                "projection info = {10, %.16g, %.16g, %.16g, %.16g, %.16g, "
+                "%.16g%s, Polyconic}\n",
+                dfA, dfB,
+                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
+                oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
+                osCommaDatum.c_str() ) >= 0;
     }
     else if( EQUAL(pszProjName,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
     {
-        VSIFPrintfL( fp, "map info = {Lambert Azimuthal Equal Area, %s%s%s}\n",
-                     osLocation.c_str(), 
-                     osCommaDatum.c_str(), osOptionalUnits.c_str() );
-
-        VSIFPrintfL( fp, "projection info = {11, %.16g, %.16g, %.16g, %.16g, %.16g, %.16g%s, Lambert Azimuthal Equal Area}\n",
-                     dfA, dfB, 
-                     oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
-                     osCommaDatum.c_str() );
+        bOK &=
+            VSIFPrintfL(
+                fp,
+                "map info = {Lambert Azimuthal Equal Area, %s%s%s}\n",
+                osLocation.c_str(),
+                osCommaDatum.c_str(), osOptionalUnits.c_str() ) >= 0;
+
+        bOK &=
+            VSIFPrintfL(
+                fp,
+                "projection info = {11, %.16g, %.16g, %.16g, %.16g, %.16g, "
+                "%.16g%s, Lambert Azimuthal Equal Area}\n",
+                dfA, dfB,
+                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
+                oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
+                osCommaDatum.c_str() ) >= 0;
     }
     else if( EQUAL(pszProjName,SRS_PT_AZIMUTHAL_EQUIDISTANT) )
     {
-        VSIFPrintfL( fp, "map info = {Azimuthal Equadistant, %s%s%s}\n",
-                     osLocation.c_str(), 
-                     osCommaDatum.c_str(), osOptionalUnits.c_str() );
-
-        VSIFPrintfL( fp, "projection info = {12, %.16g, %.16g, %.16g, %.16g, %.16g, %.16g%s, Azimuthal Equadistant}\n",
-                     dfA, dfB, 
-                     oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
-                     osCommaDatum.c_str() );
+        bOK &=
+            VSIFPrintfL(
+                fp,
+                "map info = {Azimuthal Equadistant, %s%s%s}\n",
+                osLocation.c_str(),
+                osCommaDatum.c_str(), osOptionalUnits.c_str() ) >= 0;
+
+        bOK &=
+            VSIFPrintfL(
+                fp,
+                "projection info = {12, %.16g, %.16g, %.16g, %.16g, %.16g, "
+                "%.16g%s, Azimuthal Equadistant}\n",
+                dfA, dfB,
+                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
+                oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
+                osCommaDatum.c_str() ) >= 0;
     }
     else if( EQUAL(pszProjName,SRS_PT_POLAR_STEREOGRAPHIC) )
     {
-        VSIFPrintfL( fp, "map info = {Polar Stereographic, %s%s%s}\n",
-                     osLocation.c_str(), 
-                     osCommaDatum.c_str(), osOptionalUnits.c_str() );
-
-        VSIFPrintfL( fp, "projection info = {31, %.16g, %.16g, %.16g, %.16g, %.16g, %.16g%s, Polar Stereographic}\n",
-                     dfA, dfB, 
-                     oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,90.0),
-                     oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                     oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
-                     osCommaDatum.c_str() );
+        bOK &=
+            VSIFPrintfL(
+                fp,
+                "map info = {Polar Stereographic, %s%s%s}\n",
+                osLocation.c_str(),
+                osCommaDatum.c_str(), osOptionalUnits.c_str() ) >= 0;
+
+        bOK &=
+            VSIFPrintfL(
+                fp,
+                "projection info = {31, %.16g, %.16g, %.16g, %.16g, %.16g, "
+                "%.16g%s, Polar Stereographic}\n",
+                dfA, dfB,
+                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,90.0),
+                oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
+                osCommaDatum.c_str() ) >= 0;
     }
     else
     {
-        VSIFPrintfL( fp, "map info = {%s, %s}\n",
-                     pszProjName, osLocation.c_str());
+        bOK &= VSIFPrintfL( fp, "map info = {%s, %s}\n",
+                            pszProjName, osLocation.c_str()) >= 0;
     }
 
     // write out coordinate system string
@@ -946,19 +1033,27 @@ void ENVIDataset::WriteProjectionInfo()
         if ( oSRS.exportToWkt(&pszProjESRI) == OGRERR_NONE )
         {
             if ( strlen(pszProjESRI) )
-                VSIFPrintfL( fp, "coordinate system string = {%s}\n", pszProjESRI);
+                bOK &=
+                    VSIFPrintfL(
+                        fp,
+                        "coordinate system string = {%s}\n", pszProjESRI) >= 0;
         }
         CPLFree(pszProjESRI);
         pszProjESRI = NULL;
     }
+
+    if( !bOK )
+    {
+        CPLError(CE_Failure, CPLE_FileIO, "Write error");
+    }
 }
 
 /************************************************************************/
 /*                ParseRpcCoeffsMetaDataString()                        */
 /************************************************************************/
 
-int ENVIDataset::ParseRpcCoeffsMetaDataString(const char *psName, char **papszVal,
-                                              int& idx)
+int ENVIDataset::ParseRpcCoeffsMetaDataString(
+    const char *psName, char **papszVal, int& idx)
 {
     // separate one string with 20 coefficients into an array of 20 strings.
     const char *psz20Vals = GetMetadataItem(psName, "RPC");
@@ -978,22 +1073,29 @@ int ENVIDataset::ParseRpcCoeffsMetaDataString(const char *psName, char **papszVa
 
     CSLDestroy(papszArr);
 
-    return (x == 20);
+    return x == 20;
+}
+
+static char *CPLStrdupIfNotNull( const char *pszString )
+{
+  if (! pszString )
+      return NULL;
+
+  return CPLStrdup( pszString );
 }
 
-#define CPLStrdupIfNotNull(x) ((x) ? CPLStrdup(x) : NULL)
 
 /************************************************************************/
 /*                          WriteRpcInfo()                              */
 /************************************************************************/
 
+// TODO: This whole function needs to be cleaned up.
 int ENVIDataset::WriteRpcInfo()
 {
-    // write out 90 rpc coeffs into the envi header plus 3 envi specific rpc values
-    // returns 0 if the coeffs are not present or not valid
-    int bRet = FALSE;
-    int x, idx = 0;
-    char* papszVal[93];
+    // Write out 90 rpc coeffs into the envi header plus 3 envi specific rpc
+    // values returns 0 if the coeffs are not present or not valid.
+    int idx = 0;
+  char* papszVal[93] = { NULL };
 
     papszVal[idx++] = CPLStrdupIfNotNull(GetMetadataItem("LINE_OFF", "RPC"));
     papszVal[idx++] = CPLStrdupIfNotNull(GetMetadataItem("SAMP_OFF", "RPC"));
@@ -1004,9 +1106,12 @@ int ENVIDataset::WriteRpcInfo()
     papszVal[idx++] = CPLStrdupIfNotNull(GetMetadataItem("SAMP_SCALE", "RPC"));
     papszVal[idx++] = CPLStrdupIfNotNull(GetMetadataItem("LAT_SCALE", "RPC"));
     papszVal[idx++] = CPLStrdupIfNotNull(GetMetadataItem("LONG_SCALE", "RPC"));
-    papszVal[idx++] = CPLStrdupIfNotNull(GetMetadataItem("HEIGHT_SCALE", "RPC"));
+    papszVal[idx++] =
+        CPLStrdupIfNotNull(GetMetadataItem("HEIGHT_SCALE", "RPC"));
+
+    bool bRet = false;
 
-    for (x=0; x<10; x++) // if we do not have 10 values we return 0
+    for ( int x = 0; x < 10; x++ ) // If we do not have 10 values we return 0.
     {
         if (!papszVal[x])
             goto end;
@@ -1024,44 +1129,48 @@ int ENVIDataset::WriteRpcInfo()
     if (!ParseRpcCoeffsMetaDataString("SAMP_DEN_COEFF", papszVal, idx))
         goto end;
 
-    papszVal[idx++] = CPLStrdupIfNotNull(GetMetadataItem("TILE_ROW_OFFSET", "RPC"));
-    papszVal[idx++] = CPLStrdupIfNotNull(GetMetadataItem("TILE_COL_OFFSET", "RPC"));
-    papszVal[idx++] = CPLStrdupIfNotNull(GetMetadataItem("ENVI_RPC_EMULATION", "RPC"));
+    papszVal[idx++] =
+        CPLStrdupIfNotNull(GetMetadataItem("TILE_ROW_OFFSET", "RPC"));
+    papszVal[idx++] =
+        CPLStrdupIfNotNull(GetMetadataItem("TILE_COL_OFFSET", "RPC"));
+    papszVal[idx++] =
+        CPLStrdupIfNotNull(GetMetadataItem("ENVI_RPC_EMULATION", "RPC"));
     CPLAssert(idx == 93);
-    for (x=90; x<93; x++)
+    for( int x = 90; x < 93; x++ )
     {
-        if (!papszVal[x])
+        if( !papszVal[x] )
             goto end;
     }
 
     // ok all the needed 93 values are present so write the rpcs into the envi header
-    x = 1;
-    VSIFPrintfL(fp, "rpc info = {\n");
-    for (int iR=0; iR<93; iR++)
+    bRet = true;
     {
-      if (papszVal[iR][0] == '-')
-        VSIFPrintfL(fp, " %s", papszVal[iR]);
-      else
-        VSIFPrintfL(fp, "  %s", papszVal[iR]);
-      
-      if (iR<92)
-        VSIFPrintfL(fp, ",");
+        int x = 1;
+        bRet &= VSIFPrintfL(fp, "rpc info = {\n") >= 0;
+        for( int iR=0; iR < 93; iR++ )
+        {
+          if( papszVal[iR][0] == '-' )
+              bRet &= VSIFPrintfL(fp, " %s", papszVal[iR]) >= 0;
+          else
+              bRet &= VSIFPrintfL(fp, "  %s", papszVal[iR]) >= 0;
 
-      if ((x % 4) == 0)
-          VSIFPrintfL(fp, "\n");
-     
-      x++;
-      if (x > 4) 
-        x = 1;
-    }
+          if( iR < 92 )
+              bRet &= VSIFPrintfL(fp, ",") >= 0;
 
-    VSIFPrintfL(fp, "}\n" );
+          if( (x % 4) == 0 )
+              bRet &= VSIFPrintfL(fp, "\n") >= 0;
 
-    bRet = TRUE;
+          x++;
+          if( x > 4 )
+              x = 1;
+        }
+    }
+    bRet &= VSIFPrintfL(fp, "}\n" ) >= 0;
 
+    // TODO(schwehr): Rewrite without goto.
 end:
-    for (x=0;x<idx;x++)
-        CPLFree(papszVal[x]);
+    for( int i = 0; i < idx; i++ )
+        CPLFree(papszVal[i]);
 
     return bRet;
 }
@@ -1072,33 +1181,34 @@ end:
 
 int ENVIDataset::WritePseudoGcpInfo()
 {
-    // write out gcps into the envi header
-    // returns 0 if the gcps are not present
+    // Write out gcps into the envi header
+    // returns 0 if the gcps are not present.
 
-    int iNum = GetGCPCount();
+    const int iNum = GetGCPCount();
     if (iNum == 0)
       return FALSE;
 
     const GDAL_GCP *pGcpStructs = GetGCPs();
 
-    //    double      dfGCPPixel; /** Pixel (x) location of GCP on raster */
-    //    double      dfGCPLine;  /** Line (y) location of GCP on raster */
-    //    double      dfGCPX;     /** X position of GCP in georeferenced space */
-    //    double      dfGCPY;     /** Y position of GCP in georeferenced space */
+    // double dfGCPPixel; /** Pixel (x) location of GCP on raster */
+    // double dfGCPLine;  /** Line (y) location of GCP on raster */
+    // double dfGCPX;     /** X position of GCP in georeferenced space */
+    // double dfGCPY;     /** Y position of GCP in georeferenced space */
 
-    VSIFPrintfL(fp, "geo points = {\n");
-    for (int iR=0; iR<iNum; iR++)
+    bool bRet = VSIFPrintfL(fp, "geo points = {\n") >= 0;
+    for( int iR = 0; iR < iNum; iR++ )
     {
-      VSIFPrintfL(fp, " %#0.4f, %#0.4f, %#0.8f, %#0.8f",
-                  pGcpStructs[iR].dfGCPPixel, pGcpStructs[iR].dfGCPLine,
-                  pGcpStructs[iR].dfGCPY, pGcpStructs[iR].dfGCPX);
-      if (iR<iNum-1)
-        VSIFPrintfL(fp, ",\n");
+      bRet &= VSIFPrintfL(
+          fp, " %#0.4f, %#0.4f, %#0.8f, %#0.8f",
+          pGcpStructs[iR].dfGCPPixel, pGcpStructs[iR].dfGCPLine,
+          pGcpStructs[iR].dfGCPY, pGcpStructs[iR].dfGCPX) >= 0;
+      if( iR < iNum - 1 )
+        bRet &= VSIFPrintfL(fp, ",\n") >= 0;
     }
 
-    VSIFPrintfL(fp, "}\n" );
+    bRet &= VSIFPrintfL(fp, "}\n" ) >= 0;
 
-    return TRUE;
+    return bRet;
 }
 
 /************************************************************************/
@@ -1134,11 +1244,11 @@ CPLErr ENVIDataset::GetGeoTransform( double * padfTransform )
 
 {
     memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
-    
+
     if( bFoundMapinfo )
         return CE_None;
-    else
-        return CE_Failure;
+
+    return CE_Failure;
 }
 
 /************************************************************************/
@@ -1151,7 +1261,7 @@ CPLErr ENVIDataset::SetGeoTransform( double * padfTransform )
 
     bHeaderDirty = TRUE;
     bFoundMapinfo = TRUE;
-    
+
     return CE_None;
 }
 
@@ -1171,7 +1281,7 @@ void ENVIDataset::SetDescription( const char * pszDescription )
 
 CPLErr ENVIDataset::SetMetadata( char ** papszMetadata,
                                  const char * pszDomain )
-{  
+{
     if( pszDomain && (EQUAL(pszDomain, "RPC") || EQUAL(pszDomain, "ENVI")) )
     {
         bHeaderDirty = TRUE;
@@ -1213,11 +1323,12 @@ CPLErr ENVIDataset::SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
 /*      white space.                                                    */
 /************************************************************************/
 
+// TODO: Why is this not a part of port/cpl_list.cpp?
+
 char **ENVIDataset::SplitList( const char *pszCleanInput )
 
 {
-    char	**papszReturn = NULL;
-    char	*pszInput = CPLStrdup(pszCleanInput);
+    char *pszInput = CPLStrdup(pszCleanInput);
 
     if( pszInput[0] != '{' )
     {
@@ -1225,20 +1336,17 @@ char **ENVIDataset::SplitList( const char *pszCleanInput )
         return NULL;
     }
 
-    int iChar=1;
-
-
+    int iChar = 1;
+    char **papszReturn = NULL;
     while( pszInput[iChar] != '}' && pszInput[iChar] != '\0' )
     {
-        int iFStart=-1, iFEnd=-1;
-
         // Find start of token.
-        iFStart = iChar;
+        int iFStart = iChar;
         while( pszInput[iFStart] == ' ' )
             iFStart++;
 
-        iFEnd = iFStart;
-        while( pszInput[iFEnd] != ',' 
+        int iFEnd = iFStart;
+        while( pszInput[iFEnd] != ','
                && pszInput[iFEnd] != '}'
                && pszInput[iFEnd] != '\0' )
             iFEnd++;
@@ -1265,22 +1373,22 @@ char **ENVIDataset::SplitList( const char *pszCleanInput )
 /*                            SetENVIDatum()                            */
 /************************************************************************/
 
-void ENVIDataset::SetENVIDatum( OGRSpatialReference *poSRS, 
+void ENVIDataset::SetENVIDatum( OGRSpatialReference *poSRS,
                                 const char *pszENVIDatumName )
 
 {
-    // datums
+    // Datums.
     if( EQUAL(pszENVIDatumName, "WGS-84") )
         poSRS->SetWellKnownGeogCS( "WGS84" );
     else if( EQUAL(pszENVIDatumName, "WGS-72") )
         poSRS->SetWellKnownGeogCS( "WGS72" );
     else if( EQUAL(pszENVIDatumName, "North America 1983") )
         poSRS->SetWellKnownGeogCS( "NAD83" );
-    else if( EQUAL(pszENVIDatumName, "North America 1927") 
-             || strstr(pszENVIDatumName,"NAD27") 
+    else if( EQUAL(pszENVIDatumName, "North America 1927")
+             || strstr(pszENVIDatumName,"NAD27")
              || strstr(pszENVIDatumName,"NAD-27") )
         poSRS->SetWellKnownGeogCS( "NAD27" );
-    else if( EQUALN(pszENVIDatumName, "European 1950",13) )
+    else if( STARTS_WITH_CI(pszENVIDatumName, "European 1950") )
         poSRS->SetWellKnownGeogCS( "EPSG:4230" );
     else if( EQUAL(pszENVIDatumName, "Ordnance Survey of Great Britain '36") )
         poSRS->SetWellKnownGeogCS( "EPSG:4277" );
@@ -1304,10 +1412,11 @@ void ENVIDataset::SetENVIDatum( OGRSpatialReference *poSRS,
         poSRS->SetWellKnownGeogCS( "EPSG:4004" );
     else if( EQUAL(pszENVIDatumName, "Clark 1866") )
         poSRS->SetWellKnownGeogCS( "EPSG:4008" );
-    else 
+    else
     {
         CPLError( CE_Warning, CPLE_AppDefined,
-                  "Unrecognised datum '%s', defaulting to WGS84.", pszENVIDatumName);
+                  "Unrecognized datum '%s', defaulting to WGS84.",
+                  pszENVIDatumName);
         poSRS->SetWellKnownGeogCS( "WGS84" );
     }
 }
@@ -1316,21 +1425,18 @@ void ENVIDataset::SetENVIDatum( OGRSpatialReference *poSRS,
 /*                           SetENVIEllipse()                           */
 /************************************************************************/
 
-void ENVIDataset::SetENVIEllipse( OGRSpatialReference *poSRS, 
+void ENVIDataset::SetENVIEllipse( OGRSpatialReference *poSRS,
                                   char **papszPI_EI )
 
 {
-    double dfA = CPLAtofM(papszPI_EI[0]);
-    double dfB = CPLAtofM(papszPI_EI[1]);
-    double dfInvF;
+    const double dfA = CPLAtofM(papszPI_EI[0]);
+    const double dfB = CPLAtofM(papszPI_EI[1]);
 
-    if( fabs(dfA-dfB) < 0.1 )
-        dfInvF = 0.0; // sphere
-    else
+    double dfInvF = 0.0;
+    if( fabs(dfA-dfB) >= 0.1 )
         dfInvF = dfA / (dfA - dfB);
-    
-    
-    poSRS->SetGeogCS( "Ellipse Based", "Ellipse Based", "Unnamed", 
+
+    poSRS->SetGeogCS( "Ellipse Based", "Ellipse Based", "Unnamed",
                       dfA, dfInvF );
 }
 
@@ -1344,12 +1450,8 @@ void ENVIDataset::SetENVIEllipse( OGRSpatialReference *poSRS,
 int ENVIDataset::ProcessMapinfo( const char *pszMapinfo )
 
 {
-    char	**papszFields;		
-    int         nCount;
-    OGRSpatialReference oSRS;
-
-    papszFields = SplitList( pszMapinfo );
-    nCount = CSLCount(papszFields);
+    char **papszFields = SplitList( pszMapinfo );
+    const int nCount = CSLCount(papszFields);
 
     if( nCount < 7 )
     {
@@ -1364,18 +1466,18 @@ int ENVIDataset::ProcessMapinfo( const char *pszMapinfo )
     if( CSLFetchNameValue( papszHeader, "coordinate_system_string" ) != NULL )
     {
         papszCSS = CSLTokenizeString2(
-            CSLFetchNameValue( papszHeader, "coordinate_system_string" ), 
+            CSLFetchNameValue( papszHeader, "coordinate_system_string" ),
             "{}", CSLT_PRESERVEQUOTES );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Check if we have projection info, and if so parse it.           */
 /* -------------------------------------------------------------------- */
-    char        **papszPI = NULL;
-    int         nPICount = 0;
+    char **papszPI = NULL;
+    int nPICount = 0;
     if( CSLFetchNameValue( papszHeader, "projection_info" ) != NULL )
     {
-        papszPI = SplitList( 
+        papszPI = SplitList(
             CSLFetchNameValue( papszHeader, "projection_info" ) );
         nPICount = CSLCount(papszPI);
     }
@@ -1383,42 +1485,47 @@ int ENVIDataset::ProcessMapinfo( const char *pszMapinfo )
 /* -------------------------------------------------------------------- */
 /*      Capture geotransform.                                           */
 /* -------------------------------------------------------------------- */
-    adfGeoTransform[1] = CPLAtof(papszFields[5]);	    // Pixel width
-    adfGeoTransform[5] = -CPLAtof(papszFields[6]);	    // Pixel height
-    adfGeoTransform[0] =			    // Upper left X coordinate
-	CPLAtof(papszFields[3]) - (CPLAtof(papszFields[1]) - 1) * adfGeoTransform[1];
-    adfGeoTransform[3] =			    // Upper left Y coordinate
-	CPLAtof(papszFields[4]) - (CPLAtof(papszFields[2]) - 1) * adfGeoTransform[5];
+    adfGeoTransform[1] = CPLAtof(papszFields[5]);  // Pixel width
+    adfGeoTransform[5] = -CPLAtof(papszFields[6]);  // Pixel height
+    // Upper left X coordinate.
+    adfGeoTransform[0] =
+        CPLAtof(papszFields[3]) -
+        (CPLAtof(papszFields[1]) - 1) * adfGeoTransform[1];
+    // Upper left Y coordinate.
+    adfGeoTransform[3] =
+        CPLAtof(papszFields[4]) -
+        (CPLAtof(papszFields[2]) - 1) * adfGeoTransform[5];
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[4] = 0.0;
 
 /* -------------------------------------------------------------------- */
 /*      Capture projection.                                             */
 /* -------------------------------------------------------------------- */
+    OGRSpatialReference oSRS;
     if ( oSRS.importFromESRI( papszCSS ) != OGRERR_NONE )
     {
         oSRS.Clear();
 
-        if( EQUALN(papszFields[0],"UTM",3) && nCount >= 9 )
+        if( STARTS_WITH_CI(papszFields[0], "UTM") && nCount >= 9 )
         {
-            oSRS.SetUTM( atoi(papszFields[7]), 
+            oSRS.SetUTM( atoi(papszFields[7]),
                          !EQUAL(papszFields[8],"South") );
             if( nCount >= 10 && strstr(papszFields[9],"=") == NULL )
                 SetENVIDatum( &oSRS, papszFields[9] );
             else
                 oSRS.SetWellKnownGeogCS( "NAD27" );
         }
-        else if( EQUALN(papszFields[0],"State Plane (NAD 27)",19)
+        else if( STARTS_WITH_CI(papszFields[0],"State Plane (NAD 27)")
                  && nCount >= 7 )
         {
             oSRS.SetStatePlane( ITTVISToUSGSZone(atoi(papszFields[7])), FALSE );
         }
-        else if( EQUALN(papszFields[0],"State Plane (NAD 83)",19)
+        else if( STARTS_WITH_CI(papszFields[0],"State Plane (NAD 83)")
                  && nCount >= 7 )
         {
             oSRS.SetStatePlane( ITTVISToUSGSZone(atoi(papszFields[7])), TRUE );
         }
-        else if( EQUALN(papszFields[0],"Geographic Lat",14) 
+        else if( STARTS_WITH_CI(papszFields[0], "Geographic Lat")
                  && nCount >= 8 )
         {
             if( nCount >= 8 && strstr(papszFields[7],"=") == NULL )
@@ -1432,25 +1539,27 @@ int ENVIDataset::ProcessMapinfo( const char *pszMapinfo )
                         CPLAtofM(papszPI[7]),
                         CPLAtofM(papszPI[5]), CPLAtofM(papszPI[6]) );
         }
-        else if( nPICount > 8 && atoi(papszPI[0]) == 4 ) // Lambert Conformal Conic
+        else if( nPICount > 8 && atoi(papszPI[0]) == 4 )
         {
+            // Lambert Conformal Conic
             oSRS.SetLCC( CPLAtofM(papszPI[7]), CPLAtofM(papszPI[8]),
                          CPLAtofM(papszPI[3]), CPLAtofM(papszPI[4]),
                          CPLAtofM(papszPI[5]), CPLAtofM(papszPI[6]) );
         }
-        else if( nPICount > 10 && atoi(papszPI[0]) == 5 ) // Oblique Merc (2 point)
+        else if( nPICount > 10 && atoi(papszPI[0]) == 5 )
         {
-            oSRS.SetHOM2PNO( CPLAtofM(papszPI[3]), 
-                             CPLAtofM(papszPI[4]), CPLAtofM(papszPI[5]), 
-                             CPLAtofM(papszPI[6]), CPLAtofM(papszPI[7]), 
-                             CPLAtofM(papszPI[10]), 
+            // Oblique Merc (2 point).
+            oSRS.SetHOM2PNO( CPLAtofM(papszPI[3]),
+                             CPLAtofM(papszPI[4]), CPLAtofM(papszPI[5]),
+                             CPLAtofM(papszPI[6]), CPLAtofM(papszPI[7]),
+                             CPLAtofM(papszPI[10]),
                              CPLAtofM(papszPI[8]), CPLAtofM(papszPI[9]) );
         }
-        else if( nPICount > 8 && atoi(papszPI[0]) == 6 ) // Oblique Merc 
+        else if( nPICount > 8 && atoi(papszPI[0]) == 6 ) // Oblique Merc
         {
-            oSRS.SetHOM(CPLAtofM(papszPI[3]), CPLAtofM(papszPI[4]), 
+            oSRS.SetHOM(CPLAtofM(papszPI[3]), CPLAtofM(papszPI[4]),
                         CPLAtofM(papszPI[5]), 0.0,
-                        CPLAtofM(papszPI[8]), 
+                        CPLAtofM(papszPI[8]),
                         CPLAtofM(papszPI[6]), CPLAtofM(papszPI[7]) );
         }
         else if( nPICount > 8 && atoi(papszPI[0]) == 7 ) // Stereographic
@@ -1467,22 +1576,22 @@ int ENVIDataset::ProcessMapinfo( const char *pszMapinfo )
         }
         else if( nPICount > 6 && atoi(papszPI[0]) == 10 ) // Polyconic
         {
-            oSRS.SetPolyconic(CPLAtofM(papszPI[3]), CPLAtofM(papszPI[4]), 
+            oSRS.SetPolyconic(CPLAtofM(papszPI[3]), CPLAtofM(papszPI[4]),
                               CPLAtofM(papszPI[5]), CPLAtofM(papszPI[6]) );
         }
         else if( nPICount > 6 && atoi(papszPI[0]) == 11 ) // LAEA
         {
-            oSRS.SetLAEA(CPLAtofM(papszPI[3]), CPLAtofM(papszPI[4]), 
+            oSRS.SetLAEA(CPLAtofM(papszPI[3]), CPLAtofM(papszPI[4]),
                          CPLAtofM(papszPI[5]), CPLAtofM(papszPI[6]) );
         }
         else if( nPICount > 6 && atoi(papszPI[0]) == 12 ) // Azimuthal Equid.
         {
-            oSRS.SetAE(CPLAtofM(papszPI[3]), CPLAtofM(papszPI[4]), 
+            oSRS.SetAE(CPLAtofM(papszPI[3]), CPLAtofM(papszPI[4]),
                        CPLAtofM(papszPI[5]), CPLAtofM(papszPI[6]) );
         }
         else if( nPICount > 6 && atoi(papszPI[0]) == 31 ) // Polar Stereographic
         {
-            oSRS.SetPS(CPLAtofM(papszPI[3]), CPLAtofM(papszPI[4]), 
+            oSRS.SetPS(CPLAtofM(papszPI[3]), CPLAtofM(papszPI[4]),
                        1.0,
                        CPLAtofM(papszPI[5]), CPLAtofM(papszPI[6]) );
         }
@@ -1493,7 +1602,7 @@ int ENVIDataset::ProcessMapinfo( const char *pszMapinfo )
     // Still lots more that could be added for someone with the patience.
 
 /* -------------------------------------------------------------------- */
-/*      fallback to localcs if we don't recognise things.               */
+/*      Fallback to localcs if we don't recognise things.               */
 /* -------------------------------------------------------------------- */
     if( oSRS.GetRoot() == NULL )
         oSRS.SetLocalCS( papszFields[0] );
@@ -1502,7 +1611,7 @@ int ENVIDataset::ProcessMapinfo( const char *pszMapinfo )
 /*      Try to set datum from projection info line if we have a         */
 /*      projected coordinate system without a GEOGCS.                   */
 /* -------------------------------------------------------------------- */
-    if( oSRS.IsProjected() && oSRS.GetAttrNode("GEOGCS") == NULL 
+    if( oSRS.IsProjected() && oSRS.GetAttrNode("GEOGCS") == NULL
         && nPICount > 3 )
     {
         // Do we have a datum on the projection info line?
@@ -1512,12 +1621,12 @@ int ENVIDataset::ProcessMapinfo( const char *pszMapinfo )
         if( strstr(papszPI[iDatum],"=") != NULL )
             iDatum--;
 
-        // Skip past the name. 
+        // Skip past the name.
         iDatum--;
-    
-        CPLString osDatumName = papszPI[iDatum];
+
+        const CPLString osDatumName = papszPI[iDatum];
         if( osDatumName.find_first_of("abcdefghijklmnopqrstuvwxyz"
-                                      "ABCDEFGHIJKLMNOPQRSTUVWXYZ") 
+                                      "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
             != CPLString::npos )
         {
             SetENVIDatum( &oSRS, osDatumName );
@@ -1528,41 +1637,46 @@ int ENVIDataset::ProcessMapinfo( const char *pszMapinfo )
         }
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Try to process specialized units.                               */
 /* -------------------------------------------------------------------- */
-    if( EQUALN( papszFields[nCount-1],"units",5))
+    if( STARTS_WITH_CI(papszFields[nCount-1], "units"))
     {
         /* Handle linear units first. */
-        if (EQUAL(papszFields[nCount-1],"units=Feet") )
-            oSRS.SetLinearUnitsAndUpdateParameters( SRS_UL_FOOT, CPLAtof(SRS_UL_FOOT_CONV) );
-        else if (EQUAL(papszFields[nCount-1],"units=Meters") )
+        if( EQUAL(papszFields[nCount-1], "units=Feet") )
+            oSRS.SetLinearUnitsAndUpdateParameters(
+                SRS_UL_FOOT, CPLAtof(SRS_UL_FOOT_CONV) );
+        else if( EQUAL(papszFields[nCount-1], "units=Meters") )
             oSRS.SetLinearUnitsAndUpdateParameters( SRS_UL_METER, 1. );
-        else if (EQUAL(papszFields[nCount-1],"units=Km") )
+        else if( EQUAL(papszFields[nCount-1], "units=Km") )
             oSRS.SetLinearUnitsAndUpdateParameters( "Kilometer", 1000.  );
-        else if (EQUAL(papszFields[nCount-1],"units=Yards") )
+        else if( EQUAL(papszFields[nCount-1], "units=Yards") )
             oSRS.SetLinearUnitsAndUpdateParameters( "Yard", .9144 );
-        else if (EQUAL(papszFields[nCount-1],"units=Miles") )
+        else if( EQUAL(papszFields[nCount-1], "units=Miles") )
             oSRS.SetLinearUnitsAndUpdateParameters( "Mile", 1609.344 );
-        else if (EQUAL(papszFields[nCount-1],"units=Nautical Miles") )
-            oSRS.SetLinearUnitsAndUpdateParameters( SRS_UL_NAUTICAL_MILE, CPLAtof(SRS_UL_NAUTICAL_MILE_CONV) );
-	    
+        else if( EQUAL(papszFields[nCount-1], "units=Nautical Miles") )
+            oSRS.SetLinearUnitsAndUpdateParameters(
+                SRS_UL_NAUTICAL_MILE, CPLAtof(SRS_UL_NAUTICAL_MILE_CONV) );
+
         /* Only handle angular units if we know the projection is geographic. */
-        if (oSRS.IsGeographic()) 
+        if (oSRS.IsGeographic())
         {
-            if (EQUAL(papszFields[nCount-1],"units=Radians") )
+            if (EQUAL(papszFields[nCount-1], "units=Radians") )
+            {
                 oSRS.SetAngularUnits( SRS_UA_RADIAN, 1. );
-            else 
+            }
+            else
             {
-                /* Degrees, minutes and seconds will all be represented as degrees. */
-                oSRS.SetAngularUnits( SRS_UA_DEGREE,  CPLAtof(SRS_UA_DEGREE_CONV));
-
-                double conversionFactor = 1.;
-                if (EQUAL(papszFields[nCount-1],"units=Minutes") )
-                    conversionFactor = 60.;
-                else if( EQUAL(papszFields[nCount-1],"units=Seconds") )
-                    conversionFactor = 3600.;
+                // Degrees, minutes and seconds will all be represented
+                // as degrees.
+                oSRS.SetAngularUnits(
+                    SRS_UA_DEGREE, CPLAtof(SRS_UA_DEGREE_CONV));
+
+                double conversionFactor = 1.0;
+                if( EQUAL(papszFields[nCount-1], "units=Minutes") )
+                    conversionFactor = 60.0;
+                else if( EQUAL(papszFields[nCount-1], "units=Seconds") )
+                    conversionFactor = 3600.0;
                 adfGeoTransform[0] /= conversionFactor;
                 adfGeoTransform[1] /= conversionFactor;
                 adfGeoTransform[2] /= conversionFactor;
@@ -1578,11 +1692,11 @@ int ENVIDataset::ProcessMapinfo( const char *pszMapinfo )
     if( oSRS.GetRoot() != NULL )
     {
         oSRS.Fixup();
-	if ( pszProjection )
-	{
-	    CPLFree( pszProjection );
-	    pszProjection = NULL;
-	}
+        if ( pszProjection )
+        {
+            CPLFree( pszProjection );
+            pszProjection = NULL;
+        }
         oSRS.exportToWkt( &pszProjection );
     }
 
@@ -1598,73 +1712,69 @@ int ENVIDataset::ProcessMapinfo( const char *pszMapinfo )
 /*      and sets into the standard metadata fields for RPC.             */
 /************************************************************************/
 
-void ENVIDataset::ProcessRPCinfo( const char *pszRPCinfo, 
-                                 int numCols, int numRows)
+void ENVIDataset::ProcessRPCinfo( const char *pszRPCinfo,
+                                  int numCols, int numRows)
 {
-    char	**papszFields;
-    char    sVal[1280];
-    int         nCount;
-
-    papszFields = SplitList( pszRPCinfo );
-    nCount = CSLCount(papszFields);
+    char **papszFields = SplitList( pszRPCinfo );
+    const int nCount = CSLCount(papszFields);
 
     if( nCount < 90 )
     {
         CSLDestroy( papszFields );
         return;
     }
-	
-    CPLsnprintf(sVal, sizeof(sVal),  "%.16g",CPLAtof(papszFields[0]));
+
+    char sVal[1280] = { '\0' };
+    CPLsnprintf(sVal, sizeof(sVal), "%.16g", CPLAtof(papszFields[0]));
     SetMetadataItem("LINE_OFF",sVal,"RPC");
-    CPLsnprintf(sVal, sizeof(sVal),  "%.16g",CPLAtof(papszFields[5]));
+    CPLsnprintf(sVal, sizeof(sVal), "%.16g", CPLAtof(papszFields[5]));
     SetMetadataItem("LINE_SCALE",sVal,"RPC");
-    CPLsnprintf(sVal, sizeof(sVal),  "%.16g",CPLAtof(papszFields[1]));
+    CPLsnprintf(sVal, sizeof(sVal), "%.16g", CPLAtof(papszFields[1]));
     SetMetadataItem("SAMP_OFF",sVal,"RPC");
-    CPLsnprintf(sVal, sizeof(sVal),  "%.16g",CPLAtof(papszFields[6]));
+    CPLsnprintf(sVal, sizeof(sVal), "%.16g", CPLAtof(papszFields[6]));
     SetMetadataItem("SAMP_SCALE",sVal,"RPC");
-    CPLsnprintf(sVal, sizeof(sVal),  "%.16g",CPLAtof(papszFields[2]));
+    CPLsnprintf(sVal, sizeof(sVal), "%.16g", CPLAtof(papszFields[2]));
     SetMetadataItem("LAT_OFF",sVal,"RPC");
-    CPLsnprintf(sVal, sizeof(sVal),  "%.16g",CPLAtof(papszFields[7]));
+    CPLsnprintf(sVal, sizeof(sVal), "%.16g", CPLAtof(papszFields[7]));
     SetMetadataItem("LAT_SCALE",sVal,"RPC");
-    CPLsnprintf(sVal, sizeof(sVal),  "%.16g",CPLAtof(papszFields[3]));
+    CPLsnprintf(sVal, sizeof(sVal), "%.16g", CPLAtof(papszFields[3]));
     SetMetadataItem("LONG_OFF",sVal,"RPC");
-    CPLsnprintf(sVal, sizeof(sVal),  "%.16g",CPLAtof(papszFields[8]));
+    CPLsnprintf(sVal, sizeof(sVal), "%.16g", CPLAtof(papszFields[8]));
     SetMetadataItem("LONG_SCALE",sVal,"RPC");
-    CPLsnprintf(sVal, sizeof(sVal),  "%.16g",CPLAtof(papszFields[4]));
-    SetMetadataItem("HEIGHT_OFF",sVal,"RPC");
-    CPLsnprintf(sVal, sizeof(sVal),  "%.16g",CPLAtof(papszFields[9]));
-    SetMetadataItem("HEIGHT_SCALE",sVal,"RPC");
-
-    sVal[0] = '\0'; 
-    int i;
-    for(i = 0; i < 20; i++ )
-       CPLsnprintf(sVal+strlen(sVal), sizeof(sVal),  "%.16g ", 
+    CPLsnprintf(sVal, sizeof(sVal), "%.16g", CPLAtof(papszFields[4]));
+    SetMetadataItem("HEIGHT_OFF", sVal, "RPC");
+    CPLsnprintf(sVal, sizeof(sVal), "%.16g", CPLAtof(papszFields[9]));
+    SetMetadataItem("HEIGHT_SCALE", sVal, "RPC");
+
+    sVal[0] = '\0';
+    for( int i = 0; i < 20; i++ )
+        CPLsnprintf(sVal+strlen(sVal), sizeof(sVal)-strlen(sVal),  "%.16g ",
            CPLAtof(papszFields[10+i]));
     SetMetadataItem("LINE_NUM_COEFF",sVal,"RPC");
 
-    sVal[0] = '\0'; 
-    for(i = 0; i < 20; i++ )
-       CPLsnprintf(sVal+strlen(sVal), sizeof(sVal),  "%.16g ",
+    sVal[0] = '\0';
+    for( int i = 0; i < 20; i++ )
+       CPLsnprintf(sVal+strlen(sVal), sizeof(sVal)-strlen(sVal),  "%.16g ",
            CPLAtof(papszFields[30+i]));
     SetMetadataItem("LINE_DEN_COEFF",sVal,"RPC");
-      
-    sVal[0] = '\0'; 
-    for(i = 0; i < 20; i++ )
-       CPLsnprintf(sVal+strlen(sVal), sizeof(sVal),  "%.16g ",
+
+    sVal[0] = '\0';
+    for( int i = 0; i < 20; i++ )
+       CPLsnprintf(sVal+strlen(sVal), sizeof(sVal)-strlen(sVal),  "%.16g ",
            CPLAtof(papszFields[50+i]));
     SetMetadataItem("SAMP_NUM_COEFF",sVal,"RPC");
-      
-    sVal[0] = '\0'; 
-    for(i = 0; i < 20; i++ )
-       CPLsnprintf(sVal+strlen(sVal), sizeof(sVal),  "%.16g ",
+
+    sVal[0] = '\0';
+    for( int i = 0; i < 20; i++ )
+       CPLsnprintf(sVal+strlen(sVal), sizeof(sVal)-strlen(sVal),  "%.16g ",
            CPLAtof(papszFields[70+i]));
-    SetMetadataItem("SAMP_DEN_COEFF",sVal,"RPC");
-	
-    CPLsnprintf(sVal, sizeof(sVal), "%.16g", 
+    SetMetadataItem("SAMP_DEN_COEFF", sVal, "RPC");
+
+    CPLsnprintf(sVal, sizeof(sVal), "%.16g",
         CPLAtof(papszFields[3]) - CPLAtof(papszFields[8]));
     SetMetadataItem("MIN_LONG",sVal,"RPC");
 
-    CPLsnprintf(sVal, sizeof(sVal), "%.16g", 
+    CPLsnprintf(sVal, sizeof(sVal), "%.16g",
         CPLAtof(papszFields[3]) + CPLAtof(papszFields[8]) );
     SetMetadataItem("MAX_LONG",sVal,"RPC");
 
@@ -1678,15 +1788,14 @@ void ENVIDataset::ProcessRPCinfo( const char *pszRPCinfo,
 
     if (nCount == 93)
     {
-        SetMetadataItem("TILE_ROW_OFFSET",papszFields[90],"RPC");
-        SetMetadataItem("TILE_COL_OFFSET",papszFields[91],"RPC");
-        SetMetadataItem("ENVI_RPC_EMULATION",papszFields[92],"RPC");
+        SetMetadataItem("TILE_ROW_OFFSET", papszFields[90], "RPC");
+        SetMetadataItem("TILE_COL_OFFSET", papszFields[91], "RPC");
+        SetMetadataItem("ENVI_RPC_EMULATION", papszFields[92], "RPC");
     }
 
-    /*   Handle the chipping case where the image is a subset. */
-    double rowOffset, colOffset;
-    rowOffset = (nCount == 93) ? CPLAtof(papszFields[90]) : 0;
-    colOffset = (nCount == 93) ? CPLAtof(papszFields[91]) : 0;
+    // Handle the chipping case where the image is a subset.
+    const double rowOffset = (nCount == 93) ? CPLAtof(papszFields[90]) : 0;
+    const double colOffset = (nCount == 93) ? CPLAtof(papszFields[91]) : 0;
     if (rowOffset || colOffset)
     {
         SetMetadataItem("ICHIP_SCALE_FACTOR", "1");
@@ -1722,10 +1831,8 @@ void ENVIDataset::ProcessRPCinfo( const char *pszRPCinfo,
 
 void ENVIDataset::ProcessStatsFile()
 {
-    VSILFILE	*fpStaFile;
-
     osStaFilename = CPLResetExtension( pszHDRFilename, "sta" );
-    fpStaFile = VSIFOpenL( osStaFilename, "rb" );
+    VSILFILE *fpStaFile = VSIFOpenL( osStaFilename, "rb" );
 
     if (!fpStaFile)
     {
@@ -1733,48 +1840,45 @@ void ENVIDataset::ProcessStatsFile()
         return;
     }
 
-    int lTestHeader[10],lOffset;
-
+    int lTestHeader[10] = { 0 };
     if( VSIFReadL( lTestHeader, sizeof(int), 10, fpStaFile ) != 10 )
     {
-        VSIFCloseL( fpStaFile );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fpStaFile ));
         osStaFilename = "";
         return;
     }
 
-    int isFloat;
-    isFloat = (byteSwapInt(lTestHeader[0]) == 1111838282);
+    const bool isFloat = byteSwapInt(lTestHeader[0]) == 1111838282;
+
+    int nb = byteSwapInt(lTestHeader[3]);
 
-    int nb,i;
-    float * fStats;
-    double * dStats, dMin, dMax, dMean, dStd;
-        
-    nb=byteSwapInt(lTestHeader[3]);
-    
     if (nb < 0 || nb > nBands)
     {
         CPLDebug("ENVI", ".sta file has statistics for %d bands, "
                          "whereas the dataset has only %d bands", nb, nBands);
         nb = nBands;
     }
-    
-    VSIFSeekL(fpStaFile,40+(nb+1)*4,SEEK_SET);
 
-    if (VSIFReadL(&lOffset,sizeof(int),1,fpStaFile) == 1)
+
+    int lOffset = 0;
+    if( VSIFSeekL(fpStaFile, 40+(nb+1)*4, SEEK_SET) == 0 &&
+        VSIFReadL(&lOffset, sizeof(int), 1, fpStaFile) == 1 &&
+        VSIFSeekL(fpStaFile, 40+(nb+1)*8+byteSwapInt(lOffset)+nb, SEEK_SET)
+            == 0)
     {
-        VSIFSeekL(fpStaFile,40+(nb+1)*8+byteSwapInt(lOffset)+nb,SEEK_SET);
-        // This should be the beginning of the statistics
+        // This should be the beginning of the statistics.
         if (isFloat)
         {
-            fStats = (float*)CPLCalloc(nb*4,4);
-            if ((int)VSIFReadL(fStats,4,nb*4,fpStaFile) == nb*4)
+            float *fStats = reinterpret_cast<float *>( CPLCalloc( nb * 4, 4 ) );
+            if ( static_cast<int>( VSIFReadL( fStats,4,nb*4,fpStaFile ) )
+                == nb*4)
             {
-                for (i=0;i<nb;i++)
+                for( int i=0; i < nb; i++ )
                 {
                     GetRasterBand(i+1)->SetStatistics(
                         byteSwapFloat(fStats[i]),
                         byteSwapFloat(fStats[nb+i]),
-                        byteSwapFloat(fStats[2*nb+i]), 
+                        byteSwapFloat(fStats[2*nb+i]),
                         byteSwapFloat(fStats[3*nb+i]));
                 }
             }
@@ -1782,23 +1886,26 @@ void ENVIDataset::ProcessStatsFile()
         }
         else
         {
-            dStats = (double*)CPLCalloc(nb*4,8);
-            if ((int)VSIFReadL(dStats,8,nb*4,fpStaFile) == nb*4)
+            double *dStats
+                = reinterpret_cast<double *>( CPLCalloc( nb * 4, 8 ) );
+            if ( static_cast<int>( VSIFReadL(dStats,8,nb*4,fpStaFile ) )
+                     == nb*4)
             {
-                for (i=0;i<nb;i++)
+                for( int i=0; i < nb; i++ )
                 {
-                    dMin = byteSwapDouble(dStats[i]);
-                    dMax = byteSwapDouble(dStats[nb+i]);
-                    dMean = byteSwapDouble(dStats[2*nb+i]);
-                    dStd = byteSwapDouble(dStats[3*nb+i]);
-                    if (dMin != dMax && dStd != 0) 
-                        GetRasterBand(i+1)->SetStatistics(dMin,dMax,dMean,dStd);
+                    const double dMin = byteSwapDouble(dStats[i]);
+                    const double dMax = byteSwapDouble(dStats[nb+i]);
+                    const double dMean = byteSwapDouble(dStats[2*nb+i]);
+                    const double dStd = byteSwapDouble(dStats[3*nb+i]);
+                    if (dMin != dMax && dStd != 0)
+                        GetRasterBand(i+1)->
+                            SetStatistics( dMin, dMax, dMean, dStd );
                 }
             }
             CPLFree(dStats);
         }
     }
-    VSIFCloseL( fpStaFile );
+    CPL_IGNORE_RET_VAL(VSIFCloseL( fpStaFile ));
 }
 
 int ENVIDataset::byteSwapInt(int swapMe)
@@ -1827,72 +1934,66 @@ double ENVIDataset::byteSwapDouble(double swapMe)
 int ENVIDataset::ReadHeader( VSILFILE * fpHdr )
 
 {
-
     CPLReadLineL( fpHdr );
 
 /* -------------------------------------------------------------------- */
 /*      Now start forming sets of name/value pairs.                     */
 /* -------------------------------------------------------------------- */
-    while( TRUE )
+    while( true )
     {
-        const char *pszNewLine;
-        char       *pszWorkingLine;
-
-        pszNewLine = CPLReadLineL( fpHdr );
+        const char *pszNewLine = CPLReadLineL( fpHdr );
         if( pszNewLine == NULL )
             break;
 
         if( strstr(pszNewLine,"=") == NULL )
             continue;
 
-        pszWorkingLine = CPLStrdup(pszNewLine);
+        char *pszWorkingLine = CPLStrdup(pszNewLine);
 
         // Collect additional lines if we have open sqiggly bracket.
-        if( strstr(pszWorkingLine,"{") != NULL 
+        if( strstr(pszWorkingLine,"{") != NULL
             && strstr(pszWorkingLine,"}") == NULL )
         {
-            do { 
+            do {
                 pszNewLine = CPLReadLineL( fpHdr );
                 if( pszNewLine )
                 {
-                    pszWorkingLine = (char *) 
-                        CPLRealloc(pszWorkingLine, 
-                                 strlen(pszWorkingLine)+strlen(pszNewLine)+1);
+                    pszWorkingLine = reinterpret_cast<char *>(
+                        CPLRealloc( pszWorkingLine,
+                                    strlen(pszWorkingLine)
+                                    + strlen(pszNewLine) + 1) );
                     strcat( pszWorkingLine, pszNewLine );
                 }
             } while( pszNewLine != NULL && strstr(pszNewLine,"}") == NULL );
         }
 
         // Try to break input into name and value portions.  Trim whitespace.
-        const char *pszValue;
-        int         iEqual;
+        int iEqual = 0;
 
-        for( iEqual = 0; 
+        for( ;
              pszWorkingLine[iEqual] != '\0' && pszWorkingLine[iEqual] != '=';
              iEqual++ ) {}
 
         if( pszWorkingLine[iEqual] == '=' )
         {
-            int		i;
-
-            pszValue = pszWorkingLine + iEqual + 1;
+            const char *pszValue = pszWorkingLine + iEqual + 1;
             while( *pszValue == ' ' || *pszValue == '\t' )
                 pszValue++;
-            
+
             pszWorkingLine[iEqual--] = '\0';
-            while( iEqual > 0 
+            while( iEqual > 0
                    && (pszWorkingLine[iEqual] == ' '
                        || pszWorkingLine[iEqual] == '\t') )
                 pszWorkingLine[iEqual--] = '\0';
 
             // Convert spaces in the name to underscores.
-            for( i = 0; pszWorkingLine[i] != '\0'; i++ )
+            for( int i = 0; pszWorkingLine[i] != '\0'; i++ )
             {
                 if( pszWorkingLine[i] == ' ' )
                     pszWorkingLine[i] = '_';
             }
 
-            papszHeader = CSLSetNameValue( papszHeader, 
+            papszHeader = CSLSetNameValue( papszHeader,
                                            pszWorkingLine, pszValue );
         }
 
@@ -1909,10 +2010,8 @@ int ENVIDataset::ReadHeader( VSILFILE * fpHdr )
 GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    int		i;
-    
 /* -------------------------------------------------------------------- */
-/*	We assume the user is pointing to the binary (ie. .bil) file.	*/
+/*      We assume the user is pointing to the binary (i.e. .bil) file.  */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->nHeaderBytes < 2 )
         return NULL;
@@ -1922,21 +2021,21 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      replacing the extension as well as appending the extension      */
 /*      to whatever we currently have.                                  */
 /* -------------------------------------------------------------------- */
-    const char	*pszMode;
-    CPLString   osHdrFilename;
-    VSILFILE	*fpHeader = NULL;
 
+    const char *pszMode = NULL;
     if( poOpenInfo->eAccess == GA_Update )
-	pszMode = "r+";
+        pszMode = "r+";
     else
-	pszMode = "r";
-    
+        pszMode = "r";
+
+    CPLString osHdrFilename;
+    VSILFILE *fpHeader = NULL;
     char** papszSiblingFiles = poOpenInfo->GetSiblingFiles();
     if (papszSiblingFiles == NULL)
     {
         osHdrFilename = CPLResetExtension( poOpenInfo->pszFilename, "hdr" );
         fpHeader = VSIFOpenL( osHdrFilename, pszMode );
-    
+
         if( fpHeader == NULL && VSIIsCaseSensitiveFS(osHdrFilename) )
         {
             osHdrFilename = CPLResetExtension( poOpenInfo->pszFilename, "HDR" );
@@ -1945,14 +2044,14 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
 
         if( fpHeader == NULL )
         {
-            osHdrFilename = CPLFormFilename( NULL, poOpenInfo->pszFilename, 
+            osHdrFilename = CPLFormFilename( NULL, poOpenInfo->pszFilename,
                                             "hdr" );
             fpHeader = VSIFOpenL( osHdrFilename, pszMode );
         }
 
         if( fpHeader == NULL && VSIIsCaseSensitiveFS(osHdrFilename) )
         {
-            osHdrFilename = CPLFormFilename( NULL, poOpenInfo->pszFilename, 
+            osHdrFilename = CPLFormFilename( NULL, poOpenInfo->pszFilename,
                                             "HDR" );
             fpHeader = VSIFOpenL( osHdrFilename, pszMode );
         }
@@ -1967,11 +2066,11 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
         CPLString osPath = CPLGetPath( poOpenInfo->pszFilename );
         CPLString osName = CPLGetFilename( poOpenInfo->pszFilename );
 
-        int iFile = CSLFindString(papszSiblingFiles, 
-                                  CPLResetExtension( osName, "hdr" ) );
+        int iFile = CSLFindString( papszSiblingFiles,
+                                   CPLResetExtension( osName, "hdr" ) );
         if( iFile >= 0 )
         {
-            osHdrFilename = CPLFormFilename( osPath, papszSiblingFiles[iFile], 
+            osHdrFilename = CPLFormFilename( osPath, papszSiblingFiles[iFile],
                                              NULL );
             fpHeader = VSIFOpenL( osHdrFilename, pszMode );
         }
@@ -1981,8 +2080,8 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
                                   CPLFormFilename( NULL, osName, "hdr" ));
             if( iFile >= 0 )
             {
-                osHdrFilename = CPLFormFilename( osPath, papszSiblingFiles[iFile], 
-                                                 NULL );
+                osHdrFilename =
+                    CPLFormFilename( osPath, papszSiblingFiles[iFile], NULL );
                 fpHeader = VSIFOpenL( osHdrFilename, pszMode );
             }
         }
@@ -1990,29 +2089,27 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
 
     if( fpHeader == NULL )
         return NULL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Check that the first line says "ENVI".                          */
 /* -------------------------------------------------------------------- */
-    char	szTestHdr[4];
+  char szTestHdr[4] = { '\0' };
 
     if( VSIFReadL( szTestHdr, 4, 1, fpHeader ) != 1 )
     {
-        VSIFCloseL( fpHeader );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fpHeader ));
         return NULL;
     }
-    if( strncmp(szTestHdr,"ENVI",4) != 0 )
+    if( !STARTS_WITH(szTestHdr, "ENVI") )
     {
-        VSIFCloseL( fpHeader );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fpHeader ));
         return NULL;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    ENVIDataset 	*poDS;
-
-    poDS = new ENVIDataset();
+    ENVIDataset *poDS = new ENVIDataset();
     poDS->pszHDRFilename = CPLStrdup(osHdrFilename);
     poDS->fp = fpHeader;
 
@@ -2031,12 +2128,12 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
     if( EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "hdr") )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "The selected file is an ENVI header file, but to\n"
-                  "open ENVI datasets, the data file should be selected\n"
-                  "instead of the .hdr file.  Please try again selecting\n"
-                  "the data file corresponding to the header file:\n"
-                  "  %s\n", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "The selected file is an ENVI header file, but to "
+                  "open ENVI datasets, the data file should be selected "
+                  "instead of the .hdr file.  Please try again selecting "
+                  "the data file corresponding to the header file:  "
+                  "%s",
                   poOpenInfo->pszFilename );
         return NULL;
     }
@@ -2047,12 +2144,12 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
     if( EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "sta") )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "The selected file is an ENVI statistics file.\n"
-                  "To open ENVI datasets, the data file should be selected\n"
-                  "instead of the .sta file.  Please try again selecting\n"
-                  "the data file corresponding to the statistics file:\n"
-                  "  %s\n", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "The selected file is an ENVI statistics file. "
+                  "To open ENVI datasets, the data file should be selected "
+                  "instead of the .sta file.  Please try again selecting "
+                  "the data file corresponding to the statistics file:  "
+                  "%s",
                   poOpenInfo->pszFilename );
         return NULL;
     }
@@ -2060,57 +2157,63 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Extract required values from the .hdr.                          */
 /* -------------------------------------------------------------------- */
-    int	nLines = 0, nSamples = 0, nBands = 0, nHeaderSize = 0;
-    const char   *pszInterleave = NULL;
-
+    int nLines = 0;
     if( CSLFetchNameValue(poDS->papszHeader,"lines") )
         nLines = atoi(CSLFetchNameValue(poDS->papszHeader,"lines"));
 
+    int nSamples = 0;
     if( CSLFetchNameValue(poDS->papszHeader,"samples") )
         nSamples = atoi(CSLFetchNameValue(poDS->papszHeader,"samples"));
 
+    int nBands = 0;
     if( CSLFetchNameValue(poDS->papszHeader,"bands") )
         nBands = atoi(CSLFetchNameValue(poDS->papszHeader,"bands"));
 
-    pszInterleave = CSLFetchNameValue(poDS->papszHeader,"interleave");
+    const char *pszInterleave =
+        CSLFetchNameValue(poDS->papszHeader,"interleave");
 
-    /* In case, there is no interleave keyword, we try to derive it from the */
-    /* file extension. */
+    // In case, there is no interleave keyword, we try to derive it from the
+    // file extension.
     if( pszInterleave == NULL )
     {
         const char* pszExtension = CPLGetExtension(poOpenInfo->pszFilename);
         pszInterleave = pszExtension;
     }
 
-    if ( !EQUALN(pszInterleave, "BSQ",3) &&
-         !EQUALN(pszInterleave, "BIP",3) &&
-         !EQUALN(pszInterleave, "BIL",3) )
+    if ( !STARTS_WITH_CI(pszInterleave, "BSQ") &&
+         !STARTS_WITH_CI(pszInterleave, "BIP") &&
+         !STARTS_WITH_CI(pszInterleave, "BIL") )
     {
-        CPLDebug("ENVI", "Unset or unknown value for 'interleave' keyword --> assuming BSQ interleaving");
+        CPLDebug( "ENVI",
+                  "Unset or unknown value for 'interleave' keyword --> "
+                  "assuming BSQ interleaving" );
         pszInterleave = "bsq";
     }
 
-    if (!GDALCheckDatasetDimensions(nSamples, nLines) || !GDALCheckBandCount(nBands, FALSE))
+    if( !GDALCheckDatasetDimensions(nSamples, nLines) ||
+        !GDALCheckBandCount(nBands, FALSE) )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "The file appears to have an associated ENVI header, but\n"
-                  "one or more of the samples, lines and bands\n"
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "The file appears to have an associated ENVI header, but "
+                  "one or more of the samples, lines and bands "
                   "keywords appears to be missing or invalid." );
         return NULL;
     }
 
-    if( CSLFetchNameValue(poDS->papszHeader,"header_offset") )
-        nHeaderSize = atoi(CSLFetchNameValue(poDS->papszHeader,"header_offset"));
+    int nHeaderSize = 0;
+    if( CSLFetchNameValue(poDS->papszHeader, "header_offset") )
+        nHeaderSize =
+            atoi(CSLFetchNameValue(poDS->papszHeader, "header_offset"));
 
 /* -------------------------------------------------------------------- */
 /*      Translate the datatype.                                         */
 /* -------------------------------------------------------------------- */
-    GDALDataType	eType = GDT_Byte;
+    GDALDataType eType = GDT_Byte;
 
-    if( CSLFetchNameValue(poDS->papszHeader,"data_type" ) != NULL )
+    if( CSLFetchNameValue(poDS->papszHeader, "data_type" ) != NULL )
     {
-        switch( atoi(CSLFetchNameValue(poDS->papszHeader,"data_type" )) )
+        switch( atoi(CSLFetchNameValue(poDS->papszHeader, "data_type" )) )
         {
           case 1:
             eType = GDT_Byte;
@@ -2152,21 +2255,21 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
 
           default:
             delete poDS;
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "The file does not have a value for the data_type\n"
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "The file does not have a value for the data_type "
                       "that is recognised by the GDAL ENVI driver.");
             return NULL;
         }
     }
 
 /* -------------------------------------------------------------------- */
-/*      Translate the byte order.					*/
+/*      Translate the byte order.                                       */
 /* -------------------------------------------------------------------- */
-    int		bNativeOrder = TRUE;
+    bool bNativeOrder = true;
 
     if( CSLFetchNameValue(poDS->papszHeader,"byte_order" ) != NULL )
     {
-#ifdef CPL_LSB                               
+#ifdef CPL_LSB
         bNativeOrder = atoi(CSLFetchNameValue(poDS->papszHeader,
                                               "byte_order" )) == 0;
 #else
@@ -2180,29 +2283,29 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( CSLFetchNameValue(poDS->papszHeader,"file_type" ) != NULL )
     {
-        // when the file type is one of these we return an invalid file type err
-            //'envi meta file'
-            //'envi virtual mosaic'
-            //'envi spectral library'
-            //'envi fft result'
+        // When the file type is one of these we return an invalid file type err
+            // 'envi meta file'
+            // 'envi virtual mosaic'
+            // 'envi spectral library'
+            // 'envi fft result'
 
-        // when the file type is one of these we open it 
-            //'envi standard'
-            //'envi classification' 
+        // When the file type is one of these we open it
+            // 'envi standard'
+            // 'envi classification'
 
-        // when the file type is anything else we attempt to open it as a raster.
+        // When the file type is anything else we attempt to open it as a raster.
 
-        const char * pszEnviFileType;
-        pszEnviFileType = CSLFetchNameValue(poDS->papszHeader,"file_type");
+        const char *pszEnviFileType
+            = CSLFetchNameValue(poDS->papszHeader, "file_type");
 
         // envi gdal does not support any of these
         // all others we will attempt to open
-        if(EQUAL(pszEnviFileType, "envi meta file") ||
-           EQUAL(pszEnviFileType, "envi virtual mosaic") ||
-           EQUAL(pszEnviFileType, "envi spectral library"))
+        if( EQUAL(pszEnviFileType, "envi meta file") ||
+            EQUAL(pszEnviFileType, "envi virtual mosaic") ||
+            EQUAL(pszEnviFileType, "envi spectral library") )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
-                      "File %s contains an invalid file type in the ENVI .hdr\n"
+            CPLError( CE_Failure, CPLE_OpenFailed,
+                      "File %s contains an invalid file type in the ENVI .hdr "
                       "GDAL does not support '%s' type files.",
                       poOpenInfo->pszFilename, pszEnviFileType );
             delete poDS;
@@ -2213,13 +2316,13 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Detect (gzipped) compressed datasets.                           */
 /* -------------------------------------------------------------------- */
-    int bIsCompressed = FALSE;
+    bool bIsCompressed = false;
     if( CSLFetchNameValue(poDS->papszHeader,"file_compression" ) != NULL )
     {
-        if( atoi(CSLFetchNameValue(poDS->papszHeader,"file_compression" )) 
+        if( atoi(CSLFetchNameValue(poDS->papszHeader,"file_compression" ))
             != 0 )
         {
-            bIsCompressed = TRUE;
+            bIsCompressed = true;
         }
     }
 
@@ -2234,27 +2337,29 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Reopen file in update mode if necessary.                        */
 /* -------------------------------------------------------------------- */
     CPLString osImageFilename(poOpenInfo->pszFilename);
-    if (bIsCompressed)
+    if ( bIsCompressed )
         osImageFilename = "/vsigzip/" + osImageFilename;
     if( poOpenInfo->eAccess == GA_Update )
     {
-        if (bIsCompressed)
+        if( bIsCompressed )
         {
             delete poDS;
-            CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Cannot open compressed file in update mode.\n");
+            CPLError( CE_Failure, CPLE_OpenFailed,
+                      "Cannot open compressed file in update mode.\n" );
             return NULL;
         }
         poDS->fpImage = VSIFOpenL( osImageFilename, "rb+" );
     }
     else
+    {
         poDS->fpImage = VSIFOpenL( osImageFilename, "rb" );
+    }
 
     if( poDS->fpImage == NULL )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Failed to re-open %s within ENVI driver.\n", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to re-open %s within ENVI driver.",
                   poOpenInfo->pszFilename );
         return NULL;
     }
@@ -2262,25 +2367,39 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Compute the line offset.                                        */
 /* -------------------------------------------------------------------- */
-    int	nDataSize = GDALGetDataTypeSize(eType)/8;
-    int nPixelOffset, nLineOffset;
-    vsi_l_offset nBandOffset;
-    int bIntOverflow = FALSE;
-    
-    if( EQUALN(pszInterleave, "bil", 3) )
+    const int nDataSize = GDALGetDataTypeSizeBytes(eType);
+    int nPixelOffset = 0;
+    int nLineOffset = 0;
+    vsi_l_offset nBandOffset = 0;
+    CPLAssert(nDataSize != 0);
+    CPLAssert(nBands != 0);
+
+    if( STARTS_WITH_CI(pszInterleave, "bil") )
     {
         poDS->interleave = BIL;
         poDS->SetMetadataItem( "INTERLEAVE", "LINE", "IMAGE_STRUCTURE" );
-        if (nSamples > INT_MAX / (nDataSize * nBands)) bIntOverflow = TRUE;
+        if (nSamples > INT_MAX / (nDataSize * nBands))
+        {
+            delete poDS;
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Int overflow occurred.");
+            return NULL;
+        }
         nLineOffset = nDataSize * nSamples * nBands;
         nPixelOffset = nDataSize;
-        nBandOffset = (vsi_l_offset)nDataSize * nSamples;
+        nBandOffset = static_cast<vsi_l_offset>(nDataSize) * nSamples;
     }
-    else if( EQUALN(pszInterleave, "bip", 3) )
+    else if( STARTS_WITH_CI(pszInterleave, "bip") )
     {
         poDS->interleave = BIP;
         poDS->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
-        if (nSamples > INT_MAX / (nDataSize * nBands)) bIntOverflow = TRUE;
+        if (nSamples > INT_MAX / (nDataSize * nBands))
+        {
+            delete poDS;
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Int overflow occurred.");
+            return NULL;
+        }
         nLineOffset = nDataSize * nSamples * nBands;
         nPixelOffset = nDataSize * nBands;
         nBandOffset = nDataSize;
@@ -2289,31 +2408,36 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
     {
         poDS->interleave = BSQ;
         poDS->SetMetadataItem( "INTERLEAVE", "BAND", "IMAGE_STRUCTURE" );
-        if (nSamples > INT_MAX / nDataSize) bIntOverflow = TRUE;
+        if (nSamples > INT_MAX / nDataSize)
+        {
+            delete poDS;
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Int overflow occurred.");
+            return NULL;
+        }
         nLineOffset = nDataSize * nSamples;
         nPixelOffset = nDataSize;
         nBandOffset = (vsi_l_offset)nLineOffset * nLines;
     }
 
-    if (bIntOverflow)
-    {
-        delete poDS;
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Int overflow occured.");
-        return NULL;
-    }
-    
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
     poDS->nBands = nBands;
-    for( i = 0; i < poDS->nBands; i++ )
+    CPLErrorReset();
+    for( int i = 0; i < poDS->nBands; i++ )
     {
         poDS->SetBand( i + 1,
                        new ENVIRasterBand(poDS, i + 1, poDS->fpImage,
                                          nHeaderSize + nBandOffset * i,
                                          nPixelOffset, nLineOffset, eType,
                                          bNativeOrder, TRUE) );
+        if( CPLGetLastErrorType() != CE_None )
+        {
+            poDS->nBands = i + 1;
+            delete poDS;
+            return NULL;
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -2323,54 +2447,54 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
     if( CSLFetchNameValue( poDS->papszHeader, "band_names" ) != NULL ||
         CSLFetchNameValue( poDS->papszHeader, "wavelength" ) != NULL)
     {
-        char	**papszBandNames = 
-            poDS->SplitList( CSLFetchNameValue( poDS->papszHeader, 
+        char **papszBandNames =
+            poDS->SplitList( CSLFetchNameValue( poDS->papszHeader,
                                                 "band_names" ) );
-        char	**papszWL = 
-            poDS->SplitList( CSLFetchNameValue( poDS->papszHeader, 
+        char **papszWL =
+            poDS->SplitList( CSLFetchNameValue( poDS->papszHeader,
                                                 "wavelength" ) );
 
         const char *pszWLUnits = NULL;
-        int nWLCount = CSLCount(papszWL);
-        if (papszWL) 
+        const int nWLCount = CSLCount(papszWL);
+        if (papszWL)
         {
-            /* If WL information is present, process wavelength units */
-            pszWLUnits = CSLFetchNameValue( poDS->papszHeader, 
+            /* If WL information is present, process wavelength units. */
+            pszWLUnits = CSLFetchNameValue( poDS->papszHeader,
                                             "wavelength_units" );
             if (pszWLUnits)
             {
                 /* Don't show unknown or index units */
                 if (EQUAL(pszWLUnits,"Unknown") ||
                     EQUAL(pszWLUnits,"Index") )
-                    pszWLUnits=0;
+                    pszWLUnits=NULL;
             }
             if (pszWLUnits)
             {
-                /* set wavelength units to dataset metadata */
+                /* Set wavelength units to dataset metadata. */
                 poDS->SetMetadataItem("wavelength_units", pszWLUnits);
             }
         }
 
-        for( i = 0; i < nBands; i++ )
+        for( int i = 0; i < nBands; i++ )
         {
-            CPLString osBandId, osBandName, osWavelength;
-
-            /* First set up the wavelength names and units if available */
-            if (papszWL && nWLCount > i) 
+            /* First set up the wavelength names and units if available. */
+            CPLString osWavelength;
+            if (papszWL && nWLCount > i)
             {
                 osWavelength = papszWL[i];
-                if (pszWLUnits) 
+                if (pszWLUnits)
                 {
                     osWavelength += " ";
                     osWavelength += pszWLUnits;
                 }
             }
 
-            /* Build the final name for this band */
+            /* Build the final name for this band. */
+            CPLString osBandName;
             if (papszBandNames && CSLCount(papszBandNames) > i)
             {
                 osBandName = papszBandNames[i];
-                if (strlen(osWavelength) > 0) 
+                if (strlen(osWavelength) > 0)
                 {
                     osBandName += " (";
                     osBandName += osWavelength;
@@ -2378,13 +2502,15 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
                 }
             }
             else   /* WL but no band names */
+            {
                 osBandName = osWavelength;
+            }
 
             /* Description is for internal GDAL usage */
             poDS->GetRasterBand(i + 1)->SetDescription( osBandName );
 
             /* Metadata field named Band_1, etc. needed for ArcGIS integration */
-            osBandId = CPLSPrintf("Band_%i", i+1);
+            CPLString osBandId = CPLSPrintf("Band_%i", i+1);
             poDS->SetMetadataItem(osBandId, osBandName);
 
             /* Set wavelength metadata to band */
@@ -2409,32 +2535,32 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( CSLFetchNameValue( poDS->papszHeader, "class_names" ) != NULL )
     {
-        char	**papszClassNames = 
-            poDS->SplitList( CSLFetchNameValue( poDS->papszHeader, 
+        char **papszClassNames =
+            poDS->SplitList( CSLFetchNameValue( poDS->papszHeader,
                                                 "class_names" ) );
 
         poDS->GetRasterBand(1)->SetCategoryNames( papszClassNames );
         CSLDestroy( papszClassNames );
     }
-    
+
 /* -------------------------------------------------------------------- */
-/*      Apply colormap if we have one.					*/
+/*      Apply colormap if we have one.                                  */
 /* -------------------------------------------------------------------- */
     if( CSLFetchNameValue( poDS->papszHeader, "class_lookup" ) != NULL )
     {
-        char	**papszClassColors = 
-            poDS->SplitList( CSLFetchNameValue( poDS->papszHeader, 
+        char **papszClassColors =
+            poDS->SplitList( CSLFetchNameValue( poDS->papszHeader,
                                                 "class_lookup" ) );
-        int nColorValueCount = CSLCount(papszClassColors);
+        const int nColorValueCount = CSLCount(papszClassColors);
         GDALColorTable oCT;
-		
-        for( i = 0; i*3+2 < nColorValueCount; i++ )
+
+        for( int i = 0; i*3+2 < nColorValueCount; i++ )
         {
             GDALColorEntry sEntry;
 
-            sEntry.c1 = (short) atoi(papszClassColors[i*3+0]);
-            sEntry.c2 = (short) atoi(papszClassColors[i*3+1]);
-            sEntry.c3 = (short) atoi(papszClassColors[i*3+2]);
+            sEntry.c1 = static_cast<short>( atoi(papszClassColors[i*3+0]) );
+            sEntry.c2 = static_cast<short>( atoi(papszClassColors[i*3+1]) );
+            sEntry.c3 = static_cast<short>( atoi(papszClassColors[i*3+2]) );
             sEntry.c4 = 255;
             oCT.SetColorEntry( i, &sEntry );
         }
@@ -2447,22 +2573,25 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
 
 /* -------------------------------------------------------------------- */
 /*      Set the nodata value if it is present                           */
-/* -------------------------------------------------------------------- */	
+/* -------------------------------------------------------------------- */
     if( CSLFetchNameValue(poDS->papszHeader,"data_ignore_value" ) != NULL )
     {
-        for( i = 0; i < poDS->nBands; i++ )
-            ((RawRasterBand*)poDS->GetRasterBand(i+1))->SetNoDataValue(CPLAtof(
-                                                                             CSLFetchNameValue(poDS->papszHeader,"data_ignore_value")));
+        for( int i = 0; i < poDS->nBands; i++ )
+            reinterpret_cast<RawRasterBand*>(
+                poDS->GetRasterBand(i+1) )->SetNoDataValue(CPLAtof(
+                    CSLFetchNameValue(poDS->papszHeader,"data_ignore_value")));
     }
 
 /* -------------------------------------------------------------------- */
 /*      Set all the header metadata into the ENVI domain                */
-/* -------------------------------------------------------------------- */	
+/* -------------------------------------------------------------------- */
     {
         char** pTmp = poDS->papszHeader;
-        while (*pTmp != NULL)
+        while( *pTmp != NULL )
         {
-            char** pTokens = CSLTokenizeString2(*pTmp, "=", CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES);
+            char** pTokens =
+                CSLTokenizeString2(
+                    *pTmp, "=", CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
             if (pTokens[0] != NULL && pTokens[1] != NULL && pTokens[2] == NULL)
             {
                 poDS->SetMetadataItem(pTokens[0], pTokens[1], "ENVI");
@@ -2470,11 +2599,11 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
             CSLDestroy(pTokens);
             pTmp++;
         }
-    } 
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Read the stats file if it is present                            */
-/* -------------------------------------------------------------------- */	
+/* -------------------------------------------------------------------- */
     poDS->ProcessStatsFile();
 
 /* -------------------------------------------------------------------- */
@@ -2482,9 +2611,9 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( CSLFetchNameValue( poDS->papszHeader, "map_info" ) != NULL )
     {
-        poDS->bFoundMapinfo = 
-            poDS->ProcessMapinfo( 
-                CSLFetchNameValue(poDS->papszHeader,"map_info") );
+        poDS->bFoundMapinfo =
+            poDS->ProcessMapinfo(
+                CSLFetchNameValue(poDS->papszHeader, "map_info") );
     }
 
 /* -------------------------------------------------------------------- */
@@ -2493,11 +2622,11 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
     if( !poDS->bFoundMapinfo &&
         CSLFetchNameValue( poDS->papszHeader, "rpc_info" ) != NULL )
     {
-        poDS->ProcessRPCinfo( 
-            CSLFetchNameValue(poDS->papszHeader,"rpc_info"), 
+        poDS->ProcessRPCinfo(
+            CSLFetchNameValue(poDS->papszHeader,"rpc_info"),
             poDS->nRasterXSize, poDS->nRasterYSize);
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
@@ -2509,54 +2638,54 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    // SetMetadata() calls in Open() makes the header dirty. 
-    // Don't re-write the header if nothing external has changed the metadata 
-    poDS->bHeaderDirty = FALSE; 
+    // SetMetadata() calls in Open() makes the header dirty.
+    // Don't re-write the header if nothing external has changed the metadata.
+    poDS->bHeaderDirty = FALSE;
 
     return( poDS );
 }
 
 int ENVIDataset::GetEnviType(GDALDataType eType)
 {
-  int iENVIType;
+  int iENVIType = 1;
   switch( eType )
   {
       case GDT_Byte:
-	      iENVIType = 1;
-	      break;
+          iENVIType = 1;
+          break;
       case GDT_Int16:
-	      iENVIType = 2;
-	      break;
+          iENVIType = 2;
+          break;
       case GDT_Int32:
-	      iENVIType = 3;
-	      break;
+          iENVIType = 3;
+          break;
       case GDT_Float32:
-	      iENVIType = 4;
-	      break;
+          iENVIType = 4;
+          break;
       case GDT_Float64:
-	      iENVIType = 5;
-	      break;
+          iENVIType = 5;
+          break;
       case GDT_CFloat32:
-	      iENVIType = 6;
-	      break;
+          iENVIType = 6;
+          break;
       case GDT_CFloat64:
-	      iENVIType = 9;
-	      break;
+          iENVIType = 9;
+          break;
       case GDT_UInt16:
-	      iENVIType = 12;
-	      break;
+          iENVIType = 12;
+          break;
       case GDT_UInt32:
-	      iENVIType = 13;
-	      break;
+          iENVIType = 13;
+          break;
 
-	/* 14=Int64, 15=UInt64 */
+      // 14=Int64, 15=UInt64
 
       default:
-        CPLError( CE_Failure, CPLE_AppDefined,
-              "Attempt to create ENVI .hdr labelled dataset with an illegal\n"
-              "data type (%s).\n",
-              GDALGetDataTypeName(eType) );
-      	return 1;
+          CPLError( CE_Failure, CPLE_AppDefined,
+                    "Attempt to create ENVI .hdr labelled dataset with an "
+                    "illegal data type (%s).",
+                    GDALGetDataTypeName(eType) );
+          return 1;
   }
   return iENVIType;
 }
@@ -2574,16 +2703,14 @@ GDALDataset *ENVIDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Verify input options.                                           */
 /* -------------------------------------------------------------------- */
-    int	iENVIType = GetEnviType(eType);
+    int iENVIType = GetEnviType(eType);
     if (0 == iENVIType)
-      return 0;
+        return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Try to create the file.                                         */
 /* -------------------------------------------------------------------- */
-    VSILFILE	*fp;
-
-    fp = VSIFOpenL( pszFilename, "wb" );
+    VSILFILE *fp = VSIFOpenL( pszFilename, "wb" );
 
     if( fp == NULL )
     {
@@ -2597,20 +2724,23 @@ GDALDataset *ENVIDataset::Create( const char * pszFilename,
 /*      Just write out a couple of bytes to establish the binary        */
 /*      file, and then close it.                                        */
 /* -------------------------------------------------------------------- */
-    VSIFWriteL( (void *) "\0\0", 2, 1, fp );
-    VSIFCloseL( fp );
+    bool bRet =
+        VSIFWriteL( reinterpret_cast<void *>( const_cast<char *>( "\0\0" ) ),
+                    2, 1, fp ) == 1;
+    if( VSIFCloseL( fp ) != 0 )
+        bRet = false;
+    if( !bRet )
+        return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Create the .hdr filename.                                       */
 /* -------------------------------------------------------------------- */
-    const char	*pszHDRFilename;
-    const char	*pszSuffix;
-
-    pszSuffix = CSLFetchNameValue( papszOptions, "SUFFIX" );
-    if ( pszSuffix && EQUALN( pszSuffix, "ADD", 3 ))
-	pszHDRFilename = CPLFormFilename( NULL, pszFilename, "hdr" );
+    const char *pszHDRFilename = NULL;
+    const char *pszSuffix = CSLFetchNameValue( papszOptions, "SUFFIX" );
+    if ( pszSuffix && STARTS_WITH_CI(pszSuffix, "ADD"))
+        pszHDRFilename = CPLFormFilename( NULL, pszFilename, "hdr" );
     else
-	pszHDRFilename = CPLResetExtension(pszFilename, "hdr" );
+        pszHDRFilename = CPLResetExtension(pszFilename, "hdr" );
 
 /* -------------------------------------------------------------------- */
 /*      Open the file.                                                  */
@@ -2619,7 +2749,7 @@ GDALDataset *ENVIDataset::Create( const char * pszFilename,
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Attempt to create file `%s' failed.\n",
+                  "Attempt to create file `%s' failed.",
                   pszHDRFilename );
         return NULL;
     }
@@ -2627,53 +2757,60 @@ GDALDataset *ENVIDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Write out the header.                                           */
 /* -------------------------------------------------------------------- */
-    int		iBigEndian;
-    const char	*pszInterleaving;
-    
+    const int iBigEndian =
 #ifdef CPL_LSB
-    iBigEndian = 0;
+    0
 #else
-    iBigEndian = 1;
+    1
 #endif
-
-    VSIFPrintfL( fp, "ENVI\n" );
-    VSIFPrintfL( fp, "samples = %d\nlines   = %d\nbands   = %d\n",
-		nXSize, nYSize, nBands );
-    VSIFPrintfL( fp, "header offset = 0\nfile type = ENVI Standard\n" );
-    VSIFPrintfL( fp, "data type = %d\n", iENVIType );
-    pszInterleaving = CSLFetchNameValue( papszOptions, "INTERLEAVE" );
+        ;
+
+    bRet = VSIFPrintfL( fp, "ENVI\n" ) > 0;
+    bRet &= VSIFPrintfL( fp, "samples = %d\nlines   = %d\nbands   = %d\n",
+                         nXSize, nYSize, nBands ) > 0;
+    bRet &=
+        VSIFPrintfL( fp, "header offset = 0\nfile type = ENVI Standard\n" ) > 0;
+    bRet &= VSIFPrintfL( fp, "data type = %d\n", iENVIType ) > 0;
+    const char *pszInterleaving =
+        CSLFetchNameValue( papszOptions, "INTERLEAVE" );
     if ( pszInterleaving )
     {
-	if ( EQUALN( pszInterleaving, "bip", 3 ) )
-	    pszInterleaving = "bip";		    // interleaved by pixel
-	else if ( EQUALN( pszInterleaving, "bil", 3 ) )
-	    pszInterleaving = "bil";		    // interleaved by line
-	else
-	    pszInterleaving = "bsq";		// band sequental by default
+        if( STARTS_WITH_CI(pszInterleaving, "bip") )
+            pszInterleaving = "bip";  // interleaved by pixel
+        else if( STARTS_WITH_CI(pszInterleaving, "bil") )
+            pszInterleaving = "bil";  // interleaved by line
+        else
+            pszInterleaving = "bsq";  // band sequential by default
     }
     else
-	pszInterleaving = "bsq";
-    VSIFPrintfL( fp, "interleave = %s\n", pszInterleaving);
-    VSIFPrintfL( fp, "byte order = %d\n", iBigEndian );
+        pszInterleaving = "bsq";
+    bRet &= VSIFPrintfL( fp, "interleave = %s\n", pszInterleaving) > 0;
+    bRet &= VSIFPrintfL( fp, "byte order = %d\n", iBigEndian ) > 0;
 
-    VSIFCloseL( fp );
+    if( VSIFCloseL( fp ) != 0 )
+        bRet = false;
 
-    return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
+    if( !bRet )
+        return NULL;
+
+    return reinterpret_cast<GDALDataset *>(
+        GDALOpen( pszFilename, GA_Update ) );
 }
 
 /************************************************************************/
 /*                           ENVIRasterBand()                           */
 /************************************************************************/
 
-ENVIRasterBand::ENVIRasterBand( GDALDataset *poDS, int nBand, void * fpRaw,
-                                vsi_l_offset nImgOffset, int nPixelOffset,
-                                int nLineOffset,
-                                GDALDataType eDataType, int bNativeOrder,
-                                int bIsVSIL, int bOwnsFP ) :
-        RawRasterBand(poDS, nBand, fpRaw, nImgOffset, nPixelOffset,
-                      nLineOffset, eDataType, bNativeOrder, bIsVSIL, bOwnsFP)
-{
-}
+ENVIRasterBand::ENVIRasterBand( GDALDataset *poDSIn, int nBandIn,
+                                void *fpRawIn,
+                                vsi_l_offset nImgOffsetIn, int nPixelOffsetIn,
+                                int nLineOffsetIn,
+                                GDALDataType eDataTypeIn, int bNativeOrderIn,
+                                int bIsVSILIn, int bOwnsFPIn ) :
+    RawRasterBand(poDSIn, nBandIn, fpRawIn, nImgOffsetIn, nPixelOffsetIn,
+                  nLineOffsetIn, eDataTypeIn, bNativeOrderIn, bIsVSILIn,
+                  bOwnsFPIn)
+{}
 
 /************************************************************************/
 /*                           SetDescription()                           */
@@ -2681,7 +2818,7 @@ ENVIRasterBand::ENVIRasterBand( GDALDataset *poDS, int nBand, void * fpRaw,
 
 void ENVIRasterBand::SetDescription( const char * pszDescription )
 {
-    ((ENVIDataset*)poDS)->bHeaderDirty = TRUE;
+    reinterpret_cast<ENVIDataset *>( poDS )->bHeaderDirty = TRUE;
     RawRasterBand::SetDescription(pszDescription);
 }
 
@@ -2689,10 +2826,10 @@ void ENVIRasterBand::SetDescription( const char * pszDescription )
 /*                           SetCategoryNames()                         */
 /************************************************************************/
 
-CPLErr ENVIRasterBand::SetCategoryNames( char ** papszCategoryNames )
+CPLErr ENVIRasterBand::SetCategoryNames( char ** papszCategoryNamesIn )
 {
-    ((ENVIDataset*)poDS)->bHeaderDirty = TRUE;
-    return RawRasterBand::SetCategoryNames(papszCategoryNames);
+    reinterpret_cast<ENVIDataset *>( poDS )->bHeaderDirty = TRUE;
+    return RawRasterBand::SetCategoryNames(papszCategoryNamesIn);
 }
 
 /************************************************************************/
@@ -2701,23 +2838,20 @@ CPLErr ENVIRasterBand::SetCategoryNames( char ** papszCategoryNames )
 
 void GDALRegister_ENVI()
 {
-    GDALDriver	*poDriver;
-
-    if( GDALGetDriverByName( "ENVI" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "ENVI" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "ENVI .hdr Labelled" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#ENVI" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte Int16 UInt16 Int32 UInt32 "
-                                   "Float32 Float64 CFloat32 CFloat64" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    if( GDALGetDriverByName( "ENVI" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "ENVI" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "ENVI .hdr Labelled" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#ENVI" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte Int16 UInt16 Int32 UInt32 "
+                               "Float32 Float64 CFloat32 CFloat64" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "   <Option name='SUFFIX' type='string-select'>"
 "       <Value>ADD</Value>"
@@ -2729,10 +2863,9 @@ void GDALRegister_ENVI()
 "   </Option>"
 "</CreationOptionList>" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-        poDriver->pfnOpen = ENVIDataset::Open;
-        poDriver->pfnCreate = ENVIDataset::Create;
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->pfnOpen = ENVIDataset::Open;
+    poDriver->pfnCreate = ENVIDataset::Create;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/raw/fastdataset.cpp b/frmts/raw/fastdataset.cpp
index fbc3621..bb0e51d 100644
--- a/frmts/raw/fastdataset.cpp
+++ b/frmts/raw/fastdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: fastdataset.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: fastdataset.cpp 33673 2016-03-07 20:40:54Z goatbar $
  *
  * Project:  EOSAT FAST Format reader
  * Purpose:  Reads Landsat FAST-L7A, IRS 1C/1D
@@ -27,60 +27,56 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-
-#include "cpl_string.h"
 #include "cpl_conv.h"
+#include "cpl_string.h"
+#include "gdal_frmts.h"
 #include "ogr_spatialref.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: fastdataset.cpp 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: fastdataset.cpp 33673 2016-03-07 20:40:54Z goatbar $");
 
-CPL_C_START
-void	GDALRegister_FAST(void);
-CPL_C_END
-
-#define ADM_STD_HEADER_SIZE	4608    // XXX: Format specification says it
-#define ADM_HEADER_SIZE		5000    // should be 4608, but some vendors
-                                        // ship broken large datasets.
-#define ADM_MIN_HEADER_SIZE     1536    // ...and sometimes it can be
-                                        // even 1/3 of standard size
+// static const int ADM_STD_HEADER_SIZE = 4608;  // XXX: Format specification says it
+static const int ADM_HEADER_SIZE = 5000;  // should be 4608, but some vendors
+                                          // ship broken large datasets.
+static const size_t ADM_MIN_HEADER_SIZE = 1536;  // ...and sometimes it can be
+                                              // even 1/3 of standard size
 
 #define ACQUISITION_DATE        "ACQUISITION DATE"
-#define ACQUISITION_DATE_SIZE   8
+static const int ACQUISITION_DATE_SIZE = 8;
 
 #define SATELLITE_NAME          "SATELLITE"
-#define SATELLITE_NAME_SIZE     10
+static const int SATELLITE_NAME_SIZE = 10;
 
 #define SENSOR_NAME             "SENSOR"
-#define SENSOR_NAME_SIZE        10
+static const int SENSOR_NAME_SIZE = 10;
 
 #define BANDS_PRESENT           "BANDS PRESENT"
-#define BANDS_PRESENT_SIZE      32
+static const int BANDS_PRESENT_SIZE = 32;
 
 #define FILENAME                "FILENAME"
-#define FILENAME_SIZE           29
+static const int FILENAME_SIZE = 29;
 
 #define PIXELS                  "PIXELS PER LINE"
-#define PIXELS_SIZE             5
+static const int PIXELS_SIZE = 5;
 
 #define LINES1                  "LINES PER BAND"
 #define LINES2                  "LINES PER IMAGE"
-#define LINES_SIZE              5
+static const int LINES_SIZE = 5;
 
 #define BITS_PER_PIXEL          "OUTPUT BITS PER PIXEL"
-#define BITS_PER_PIXEL_SIZE     2
+static const int BITS_PER_PIXEL_SIZE = 2;
 
 #define PROJECTION_NAME         "MAP PROJECTION"
-#define PROJECTION_NAME_SIZE    4
+static const int PROJECTION_NAME_SIZE = 4;
 
 #define ELLIPSOID_NAME          "ELLIPSOID"
-#define ELLIPSOID_NAME_SIZE     18
+static const int ELLIPSOID_NAME_SIZE = 18;
 
 #define DATUM_NAME              "DATUM"
-#define DATUM_NAME_SIZE         6
+static const int DATUM_NAME_SIZE = 6;
 
 #define ZONE_NUMBER             "USGS MAP ZONE"
-#define ZONE_NUMBER_SIZE        6
+static const int ZONE_NUMBER_SIZE = 6;
 
 #define USGS_PARAMETERS         "USGS PROJECTION PARAMETERS"
 
@@ -88,14 +84,15 @@ CPL_C_END
 #define CORNER_UPPER_RIGHT      "UR "
 #define CORNER_LOWER_LEFT       "LL "
 #define CORNER_LOWER_RIGHT      "LR "
-#define CORNER_VALUE_SIZE       13
+static const int CORNER_VALUE_SIZE = 13;
 
-#define VALUE_SIZE              24
+static const int VALUE_SIZE = 24;
 
 enum FASTSatellite  // Satellites:
 {
-    LANDSAT,	    // Landsat 7
-    IRS		    // IRS 1C/1D
+    LANDSAT,        // Landsat 7
+    IRS,            // IRS 1C/1D
+    FAST_UNKNOWN
 };
 
 /************************************************************************/
@@ -118,20 +115,20 @@ class FASTDataset : public GDALPamDataset
     char	*pszDirname;
     GDALDataType eDataType;
     FASTSatellite iSatellite;
-    
+
     int         OpenChannel( const char *pszFilename, int iBand );
 
   public:
                 FASTDataset();
 		~FASTDataset();
-    
+
     static GDALDataset *Open( GDALOpenInfo * );
 
     CPLErr 	GetGeoTransform( double * );
     const char	*GetProjectionRef();
     VSILFILE	*FOpenChannel( const char *, int iBand, int iFASTBand );
     void        TryEuromap_IRS_1C_1D_ChannelNameConvention();
-    
+
     virtual  char** GetFileList();
 };
 
@@ -156,12 +153,12 @@ class FASTRasterBand : public RawRasterBand
 /*                           FASTRasterBand()                           */
 /************************************************************************/
 
-FASTRasterBand::FASTRasterBand( FASTDataset *poDS, int nBand, VSILFILE * fpRaw,
-                                vsi_l_offset nImgOffset, int nPixelOffset,
-                                int nLineOffset, GDALDataType eDataType,
-				int bNativeOrder) :
-                 RawRasterBand( poDS, nBand, fpRaw, nImgOffset, nPixelOffset,
-                               nLineOffset, eDataType, bNativeOrder, TRUE)
+FASTRasterBand::FASTRasterBand( FASTDataset *poDSIn, int nBandIn, VSILFILE * fpRawIn,
+                                vsi_l_offset nImgOffsetIn, int nPixelOffsetIn,
+                                int nLineOffsetIn,
+                                GDALDataType eDataTypeIn, int bNativeOrderIn ) :
+        RawRasterBand(poDSIn, nBandIn, fpRawIn, nImgOffsetIn, nPixelOffsetIn,
+                      nLineOffsetIn, eDataTypeIn, bNativeOrderIn, TRUE)
 {
 
 }
@@ -176,12 +173,18 @@ FASTRasterBand::FASTRasterBand( FASTDataset *poDS, int nBand, VSILFILE * fpRaw,
 /*                           FASTDataset()                              */
 /************************************************************************/
 
-FASTDataset::FASTDataset()
-
+FASTDataset::FASTDataset() :
+    fpHeader(NULL),
+    pszFilename(NULL),
+    pszDirname(NULL),
+    eDataType(GDT_Unknown),
+    iSatellite(FAST_UNKNOWN)
 {
-    fpHeader = NULL;
-    pszDirname = NULL;
     pszProjection = CPLStrdup( "" );
+    // TODO: Why does this not work?
+    //   fill( fpChannels, fpChannels + CPL_ARRAYSIZE(fpChannels), NULL );
+    for (int i=0; i < 7; ++i)
+        fpChannels[i] = NULL;
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
@@ -198,19 +201,17 @@ FASTDataset::FASTDataset()
 FASTDataset::~FASTDataset()
 
 {
-    int i;
-
     FlushCache();
 
     if ( pszDirname )
 	CPLFree( pszDirname );
     if ( pszProjection )
 	CPLFree( pszProjection );
-    for ( i = 0; i < nBands; i++ )
+    for ( int i = 0; i < nBands; i++ )
 	if ( fpChannels[i] )
-	    VSIFCloseL( fpChannels[i] );
+	    CPL_IGNORE_RET_VAL(VSIFCloseL( fpChannels[i] ));
     if( fpHeader != NULL )
-        VSIFCloseL( fpHeader );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fpHeader ));
 }
 
 /************************************************************************/
@@ -233,8 +234,8 @@ const char *FASTDataset::GetProjectionRef()
 {
     if( pszProjection )
         return pszProjection;
-    else
-        return "";
+
+    return "";
 }
 
 /************************************************************************/
@@ -244,14 +245,14 @@ const char *FASTDataset::GetProjectionRef()
 char** FASTDataset::GetFileList()
 {
     char** papszFileList = GDALPamDataset::GetFileList();
-    int i;
-    for(i=0;i<6;i++)
+
+    for( int i = 0; i < 6; i++ )
     {
         if (apoChannelFilenames[i].size() > 0)
             papszFileList =
                 CSLAddString(papszFileList, apoChannelFilenames[i].c_str());
     }
-    
+
     return papszFileList;
 }
 
@@ -259,11 +260,11 @@ char** FASTDataset::GetFileList()
 /*                             OpenChannel()                            */
 /************************************************************************/
 
-int FASTDataset::OpenChannel( const char *pszFilename, int iBand )
+int FASTDataset::OpenChannel( const char *pszFilenameIn, int iBand )
 {
-    fpChannels[iBand] = VSIFOpenL( pszFilename, "rb" );
+    fpChannels[iBand] = VSIFOpenL( pszFilenameIn, "rb" );
     if (fpChannels[iBand])
-        apoChannelFilenames[iBand] = pszFilename;
+        apoChannelFilenames[iBand] = pszFilenameIn;
     return fpChannels[iBand] != NULL;
 }
 
@@ -279,7 +280,7 @@ VSILFILE *FASTDataset::FOpenChannel( const char *pszBandname, int iBand, int iFA
     char	*pszSuffix = CPLStrdup( CPLGetExtension( pszFilename ) );
 
     fpChannels[iBand] = NULL;
-    
+
     switch ( iSatellite )
     {
 	case LANDSAT:
@@ -293,7 +294,7 @@ VSILFILE *FASTDataset::FOpenChannel( const char *pszBandname, int iBand, int iFA
                     CPLFormFilename( pszDirname,
                             CPLSPrintf( "%s.b%02d", pszPrefix, iFASTBand ),
                             NULL );
-                OpenChannel( pszChannelFilename, iBand );
+                CPL_IGNORE_RET_VAL(OpenChannel( pszChannelFilename, iBand ));
             }
             break;
 	case IRS:
@@ -348,11 +349,11 @@ VSILFILE *FASTDataset::FOpenChannel( const char *pszBandname, int iBand, int iFA
                 break;
             pszChannelFilename = CPLFormFilename( pszDirname,
                 CPLSPrintf( "band%d.DAT", iFASTBand ), NULL );
-            OpenChannel( pszChannelFilename, iBand );
+            CPL_IGNORE_RET_VAL(OpenChannel( pszChannelFilename, iBand ));
             break;
     }
-    
-    CPLDebug( "FAST", "Band %d filename=%s", iBand + 1, pszChannelFilename);
+
+    CPLDebug( "FAST", "Band %d filename=%s", iBand + 1, pszChannelFilename ? pszChannelFilename : "(null)");
 
     CPLFree( pszPrefix );
     CPLFree( pszSuffix );
@@ -418,15 +419,16 @@ void FASTDataset::TryEuromap_IRS_1C_1D_ChannelNameConvention()
             { 'l', 'm', 'n', 'o', 'p' },
             { 'q', 'r', 's', 't', 'u' },
             { 'v', 'w', 'x', 'y', 'z' } };
-        int i;
-        for (i = 0; i < 7 ; i++)
+
+        int i = 0;
+        for ( ; i < 7 ; i++ )
         {
             if (chLastLetterHeader == apchLISSFilenames[i][0] ||
                 (apchLISSFilenames[i][0] >= 'a' && apchLISSFilenames[i][0] <= 'z' &&
                     (apchLISSFilenames[i][0] - chLastLetterHeader == 0 ||
                     apchLISSFilenames[i][0] - chLastLetterHeader == 32)))
             {
-                for (int j = 0; j < 4; j ++)
+                for ( int j = 0; j < 4; j ++ )
                 {
                     char* pszChannelFilename = CPLStrdup(pszFilename);
                     pszChannelFilename[strlen(pszChannelFilename)-1] = apchLISSFilenames[i][j+1];
@@ -464,8 +466,8 @@ void FASTDataset::TryEuromap_IRS_1C_1D_ChannelNameConvention()
             for (int j = 0; j < 2; j ++)
             {
                 char* pszChannelFilename = CPLStrdup(pszFilename);
-                pszChannelFilename[strlen(pszChannelFilename)-1] 
-                    = (char) ('1' + j);
+                pszChannelFilename[strlen(pszChannelFilename)-1]
+                    = static_cast<char>( '1' + j );
                 if (OpenChannel( pszChannelFilename, nBands ))
                     nBands++;
                 else
@@ -493,8 +495,7 @@ void FASTDataset::TryEuromap_IRS_1C_1D_ChannelNameConvention()
 static char *GetValue( const char *pszString, const char *pszName,
                        int iValueSize, int bNormalize )
 {
-    char    *pszTemp = strstr( (char *) pszString, pszName );
-
+    char *pszTemp = strstr( const_cast<char *>( pszString ), pszName );
     if ( pszTemp )
     {
         // Skip the parameter name
@@ -592,8 +593,6 @@ static long USGSEllipsoidToCode( const char* pszMnemonic )
 GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    int		i;
-
     if( poOpenInfo->nHeaderBytes < 1024)
         return NULL;
 
@@ -602,13 +601,11 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
         && !EQUALN((const char *) poOpenInfo->pabyHeader + 36,
 		"ACQUISITION DATE =", 18) )
         return NULL;
-    
+
 /* -------------------------------------------------------------------- */
 /*  Create a corresponding GDALDataset.                                 */
 /* -------------------------------------------------------------------- */
-    FASTDataset	*poDS;
-
-    poDS = new FASTDataset();
+    FASTDataset	*poDS = new FASTDataset();
 
     poDS->fpHeader = VSIFOpenL(poOpenInfo->pszFilename, "rb");
     if (poDS->fpHeader == NULL)
@@ -619,16 +616,16 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
 
     poDS->pszFilename = poOpenInfo->pszFilename;
     poDS->pszDirname = CPLStrdup( CPLGetDirname( poOpenInfo->pszFilename ) );
-    
+
 /* -------------------------------------------------------------------- */
 /*  Read the administrative record.                                     */
 /* -------------------------------------------------------------------- */
-    char	*pszTemp;
-    char	*pszHeader = (char *) CPLMalloc( ADM_HEADER_SIZE + 1 );
-    size_t      nBytesRead;
- 
-    VSIFSeekL( poDS->fpHeader, 0, SEEK_SET );
-    nBytesRead = VSIFReadL( pszHeader, 1, ADM_HEADER_SIZE, poDS->fpHeader );
+    char
+        *pszHeader = reinterpret_cast<char *>( CPLMalloc( ADM_HEADER_SIZE + 1 ) );
+
+    size_t nBytesRead = 0;
+    if( VSIFSeekL( poDS->fpHeader, 0, SEEK_SET ) >= 0 )
+        nBytesRead = VSIFReadL( pszHeader, 1, ADM_HEADER_SIZE, poDS->fpHeader );
     if ( nBytesRead < ADM_MIN_HEADER_SIZE )
     {
 	CPLDebug( "FAST", "Header file too short. Reading failed" );
@@ -639,8 +636,8 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
     pszHeader[nBytesRead] = '\0';
 
     // Read acquisition date
-    pszTemp = GetValue( pszHeader, ACQUISITION_DATE,
-                        ACQUISITION_DATE_SIZE, TRUE );
+    char *pszTemp = GetValue( pszHeader, ACQUISITION_DATE,
+                              ACQUISITION_DATE_SIZE, TRUE );
     if (pszTemp == NULL)
     {
         CPLDebug( "FAST", "Cannot get ACQUISITION_DATE, using empty value." );
@@ -657,9 +654,9 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
         pszTemp = CPLStrdup( "" );
     }
     poDS->SetMetadataItem( "SATELLITE", pszTemp );
-    if ( EQUALN(pszTemp, "LANDSAT", 7) )
+    if ( STARTS_WITH_CI(pszTemp, "LANDSAT") )
 	poDS->iSatellite = LANDSAT;
-    else if ( EQUALN(pszTemp, "IRS", 3) )
+    else if ( STARTS_WITH_CI(pszTemp, "IRS") )
 	poDS->iSatellite = IRS;
     else
 	poDS->iSatellite = IRS;
@@ -677,7 +674,7 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
 
     // Read filenames
     poDS->nBands = 0;
-    
+
     if (strstr( pszHeader, FILENAME ) == NULL)
     {
         if (strstr(pszHeader, "GENERATING AGENCY =EUROMAP"))
@@ -697,9 +694,9 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
                       EQUAL(poDS->GetMetadataItem("SENSOR"), "AFT")))
             {
                 /* See http://www.euromap.de/download/p5fast_20050301.pdf, appendix F */
-                CPLString     osSuffix = CPLGetExtension( poDS->pszFilename );
+                const CPLString osSuffix = CPLGetExtension( poDS->pszFilename );
                 const char    *papszBasenames[] = { "BANDF", "bandf", "BANDA", "banda" };
-                for ( i=0;i<4;i++)
+                for ( int i=0;i<4;i++)
                 {
                     CPLString osChannelFilename = CPLFormFilename( poDS->pszDirname, papszBasenames[i], osSuffix );
                     if (poDS->OpenChannel( osChannelFilename, 0 ))
@@ -715,7 +712,7 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
                 pszTemp = GetValue( pszHeader, BANDS_PRESENT, BANDS_PRESENT_SIZE, TRUE );
                 if (pszTemp)
                 {
-                    for( i=0; pszTemp[i] != '\0'; i++)
+                    for( int i=0; pszTemp[i] != '\0'; i++)
                     {
                         if (pszTemp[i] >= '2' && pszTemp[i] <= '5')
                         {
@@ -728,14 +725,14 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
             }
         }
     }
-    
+
     /* If the previous lookup for band files didn't success, fallback to the */
     /* standard way of finding them, either by the FILENAME field, either with */
     /* the usual patterns like bandX.dat, etc... */
     if ( !poDS->nBands )
     {
         pszTemp = pszHeader;
-        for ( i = 0; i < 7; i++ )
+        for ( int i = 0; i < 7; i++ )
         {
             char *pszFilename = NULL ;
             if ( pszTemp )
@@ -800,8 +797,6 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
 	return NULL;
     }
 
-
-    
     if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
     {
         CPLFree(pszHeader);
@@ -836,7 +831,15 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
     // Read gains and biases. This is a trick!
     pszTemp = strstr( pszHeader, "BIASES" );// It may be "BIASES AND GAINS"
                                             // or "GAINS AND BIASES"
-    if ( pszTemp > strstr( pszHeader, "GAINS" ) )
+    const char* pszGains = strstr( pszHeader, "GAINS" );
+    if( pszTemp == NULL || pszGains == NULL )
+    {
+        CPLDebug("FAST", "No BIASES and/or GAINS");
+        CPLFree(pszHeader);
+        delete poDS;
+        return NULL;
+    }
+    if ( pszTemp > pszGains )
     {
         pszFirst = "GAIN%d";
         pszSecond = "BIAS%d";
@@ -847,8 +850,8 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
         pszSecond = "GAIN%d";
     }
 
-    // Now search for the first number occurance after that string
-    for ( i = 1; i <= poDS->nBands; i++ )
+    // Now search for the first number occurrence after that string.
+    for ( int i = 1; i <= poDS->nBands; i++ )
     {
         char    *pszValue = NULL;
         size_t  nValueLen = VALUE_SIZE;
@@ -857,7 +860,7 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
         if ( pszTemp )
         {
             nValueLen = strspn( pszTemp, "+-.0123456789" );
-            pszValue = CPLScanString( pszTemp, nValueLen, TRUE, TRUE );
+            pszValue = CPLScanString( pszTemp, static_cast<int>(nValueLen), TRUE, TRUE );
             poDS->SetMetadataItem( CPLSPrintf(pszFirst, i ), pszValue );
             CPLFree( pszValue );
         }
@@ -866,7 +869,7 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
         if ( pszTemp )
         {
             nValueLen = strspn( pszTemp, "+-.0123456789" );
-            pszValue = CPLScanString( pszTemp, nValueLen, TRUE, TRUE );
+            pszValue = CPLScanString( pszTemp, static_cast<int>(nValueLen), TRUE, TRUE );
             poDS->SetMetadataItem( CPLSPrintf(pszSecond, i ), pszValue );
             CPLFree( pszValue );
         }
@@ -876,18 +879,16 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*  Read geometric record.					        */
 /* -------------------------------------------------------------------- */
-    OGRSpatialReference oSRS;
-    long        iProjSys, iZone, iDatum;
-    // Coordinates of pixel's centers
+   // Coordinates of pixel's centers
     double	dfULX = 0.0, dfULY = 0.0;
     double	dfURX = 0.0, dfURY = 0.0;
     double	dfLLX = 0.0, dfLLY = 0.0;
     double	dfLRX = 0.0, dfLRY = 0.0;
-    double      adfProjParms[15];
 
     // Read projection name
     pszTemp = GetValue( pszHeader, PROJECTION_NAME,
                         PROJECTION_NAME_SIZE, FALSE );
+    long iProjSys;
     if ( pszTemp && !EQUAL( pszTemp, "" ) )
         iProjSys = USGSMnemonicToCode( pszTemp );
     else
@@ -896,6 +897,7 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
 
     // Read ellipsoid name
     pszTemp = GetValue( pszHeader, ELLIPSOID_NAME, ELLIPSOID_NAME_SIZE, FALSE );
+    long iDatum;
     if ( pszTemp && !EQUAL( pszTemp, "" ) )
         iDatum = USGSEllipsoidToCode( pszTemp );
     else
@@ -904,6 +906,7 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
 
     // Read zone number
     pszTemp = GetValue( pszHeader, ZONE_NUMBER, ZONE_NUMBER_SIZE, FALSE );
+    long iZone;
     if ( pszTemp && !EQUAL( pszTemp, "" ) )
         iZone = atoi( pszTemp );
     else
@@ -911,13 +914,14 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
     CPLFree( pszTemp );
 
     // Read 15 USGS projection parameters
-    for ( i = 0; i < 15; i++ )
+    double adfProjParms[15];
+    for ( int i = 0; i < 15; i++ )
         adfProjParms[i] = 0.0;
     pszTemp = strstr( pszHeader, USGS_PARAMETERS );
     if ( pszTemp && !EQUAL( pszTemp, "" ) )
     {
         pszTemp += strlen( USGS_PARAMETERS );
-        for ( i = 0; i < 15; i++ )
+        for ( int i = 0; i < 15; i++ )
         {
             pszTemp = strpbrk( pszTemp, "-.0123456789" );
             if ( pszTemp )
@@ -927,7 +931,7 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
     // Coordinates should follow the word "PROJECTION", otherwise we can
-    // be confused by other occurences of the corner keywords.
+    // be confused by other occurrences of the corner keywords.
     char        *pszGeomRecord = strstr( pszHeader, "PROJECTION" );
     // Read corner coordinates
     pszTemp = strstr( pszGeomRecord, CORNER_UPPER_LEFT );
@@ -971,34 +975,29 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
          && dfLLX != 0.0 && dfLLY != 0.0
          && dfLRX != 0.0 && dfLRY != 0.0 )
     {
-        int transform_ok=FALSE;
-        GDAL_GCP *pasGCPList;
-        int bAnglesInPackedDMSFormat;
-
         // Strip out zone number from the easting values, if either
         if ( dfULX >= 1000000.0 )
-            dfULX -= (double)iZone * 1000000.0;
+            dfULX -= static_cast<double>( iZone ) * 1000000.0;
         if ( dfURX >= 1000000.0 )
-            dfURX -= (double)iZone * 1000000.0;
+            dfURX -= static_cast<double>( iZone ) * 1000000.0;
         if ( dfLLX >= 1000000.0 )
-            dfLLX -= (double)iZone * 1000000.0;
+            dfLLX -= static_cast<double>( iZone ) * 1000000.0;
         if ( dfLRX >= 1000000.0 )
-            dfLRX -= (double)iZone * 1000000.0;
+            dfLRX -= static_cast<double>( iZone ) * 1000000.0;
 
         // In EOSAT FAST Rev C, the angles are in decimal degrees
         // otherwise they are in packed DMS format.
-        if (strstr(pszHeader, "REV            C") != NULL)
-            bAnglesInPackedDMSFormat = FALSE;
-        else
-            bAnglesInPackedDMSFormat = TRUE;
+        const int bAnglesInPackedDMSFormat =
+            strstr( pszHeader, "REV            C" ) == NULL;
 
         // Create projection definition
+        OGRSpatialReference oSRS;
         OGRErr eErr =
             oSRS.importFromUSGS( iProjSys, iZone, adfProjParms, iDatum, bAnglesInPackedDMSFormat );
         if ( eErr != OGRERR_NONE )
             CPLDebug("FAST", "Import projection from USGS failed: %d", eErr);
         oSRS.SetLinearUnits( SRS_UL_METER, 1.0 );
-        
+
         // Read datum name
         pszTemp = GetValue( pszHeader, DATUM_NAME, DATUM_NAME_SIZE, FALSE );
         if ( pszTemp )
@@ -1024,7 +1023,8 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
             CPLDebug("FAST", "Export projection to WKT USGS failed: %d", eErr);
 
         // Generate GCPs
-        pasGCPList = (GDAL_GCP *) CPLCalloc( sizeof( GDAL_GCP ), 4 );
+        GDAL_GCP *pasGCPList
+            = reinterpret_cast<GDAL_GCP *>( CPLCalloc( sizeof( GDAL_GCP ), 4 ) );
         GDALInitGCPs( 4, pasGCPList );
         CPLFree(pasGCPList[0].pszId);
         CPLFree(pasGCPList[1].pszId);
@@ -1032,7 +1032,7 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
         CPLFree(pasGCPList[3].pszId);
 
         /* Let's order the GCP in TL, TR, BR, BL order to benefit from the */
-        /* GDALGCPsToGeoTransform optimization */ 
+        /* GDALGCPsToGeoTransform optimization */
         pasGCPList[0].pszId = CPLStrdup("UPPER_LEFT");
         pasGCPList[0].dfGCPX = dfULX;
         pasGCPList[0].dfGCPY = dfULY;
@@ -1059,11 +1059,10 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
         pasGCPList[3].dfGCPLine = poDS->nRasterYSize-0.5;
 
         // Calculate transformation matrix, if accurate
-        transform_ok =
-            GDALGCPsToGeoTransform(4,pasGCPList,poDS->adfGeoTransform,0);
-        if (transform_ok == FALSE)
+        const bool transform_ok
+            = CPL_TO_BOOL(GDALGCPsToGeoTransform(4,pasGCPList,poDS->adfGeoTransform,0));
+        if( !transform_ok )
         {
-            
             poDS->adfGeoTransform[0] = 0.0;
             poDS->adfGeoTransform[1] = 1.0;
             poDS->adfGeoTransform[2] = 0.0;
@@ -1082,10 +1081,10 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    int	nPixelOffset = GDALGetDataTypeSize(poDS->eDataType) / 8;
-    int nLineOffset = poDS->nRasterXSize * nPixelOffset;
+    const int nPixelOffset = GDALGetDataTypeSize(poDS->eDataType) / 8;
+    const int nLineOffset = poDS->nRasterXSize * nPixelOffset;
 
-    for( i = 1; i <= poDS->nBands; i++ )
+    for( int i = 1; i <= poDS->nBands; i++ )
     {
         poDS->SetBand( i, new FASTRasterBand( poDS, i, poDS->fpChannels[i - 1],
 	    0, nPixelOffset, nLineOffset, poDS->eDataType, TRUE));
@@ -1098,49 +1097,46 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->TryLoadXML();
-    
+
     // opens overviews.
     poDS->oOvManager.Initialize(poDS, poDS->pszFilename);
-    
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The FAST driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
     }
-    
+
     return( poDS );
 }
 
 /************************************************************************/
-/*                        GDALRegister_FAST()				*/
+/*                        GDALRegister_FAST()                           */
 /************************************************************************/
 
 void GDALRegister_FAST()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "FAST" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "FAST" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "FAST" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "EOSAT FAST Format" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_fast.html" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = FASTDataset::Open;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
-}
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "FAST" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "EOSAT FAST Format" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_fast.html" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
+    poDriver->pfnOpen = FASTDataset::Open;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/frmts/raw/frmt_fast.html b/frmts/raw/frmt_fast.html
index 6ae5c44..8ff8475 100644
--- a/frmts/raw/frmt_fast.html
+++ b/frmts/raw/frmt_fast.html
@@ -77,7 +77,7 @@ B80 = band 8<br>
 FST = FAST file extension<br>
 </tt><p>
 
-So you should give to driver one of the <tt>L7fppprrr_rrrYYYYMMDD_HPN.FST</tt>, 
+So you should give to driver one of the <tt>L7fppprrr_rrrYYYYMMDD_HPN.FST</tt>,
 <tt>L7fppprrr_rrrYYYYMMDD_HRF.FST</tt> or
 <tt>L7fppprrr_rrrYYYYMMDD_HTM.FST</tt> files.
 
@@ -159,9 +159,9 @@ Calibration coefficients for each band reported as metadata items.
 
 	<li> <b>SENSOR</b>: First scene sensor name.<p>
 
-	<li> <b>BIASn</b>: Bias value for the channel <b>n</b>.<p> 
+	<li> <b>BIASn</b>: Bias value for the channel <b>n</b>.<p>
 
-	<li> <b>GAINn</b>: Gain value for the channel <b>n</b>.<p> 
+	<li> <b>GAINn</b>: Gain value for the channel <b>n</b>.<p>
 
 </ul>
 
diff --git a/frmts/raw/frmt_lcp.html b/frmts/raw/frmt_lcp.html
index d094954..b965b7e 100644
--- a/frmts/raw/frmt_lcp.html
+++ b/frmts/raw/frmt_lcp.html
@@ -1,649 +1,649 @@
-<html>
-
-<head>
-<title>GDAL Driver for FARSITE LCP</title>
-</head>
-
-<body>
-
-<h2>GDAL Driver for FARSITE v.4 LCP Format</h2>
-<p>FARSITE v. 4 landscape file (LCP) is a multi-band raster format used by 
-wildland fire behavior and fire effect simulation models such as FARSITE, 
-FLAMMAP, and FBAT (<a href="http://www.fire.org">www.fire.org</a>). The bands of an LCP file store data describing 
-terrain, tree canopy, and surface fuel. The
-<a href="http://landfire.cr.usgs.gov/viewer">USGS National Map for LANDFIRE</a>
-distributes data in LCP format, and 
-programs such as FARSITE and <a href="http://www.landfire.gov/datatool.php">LFDAT</a> can create LCP files from a set of input rasters.</p>
-<p>An LCP file (.lcp) is basically a raw format with a 7,316-byte header 
-described below. The data type for all bands is 16-bit signed integer. Bands are 
-interleaved by pixel. Five bands are required: elevation, slope, aspect, fuel 
-model, and tree canopy cover. Crown fuel bands (canopy height, canopy base 
-height, canopy bulk density), and surface fuel bands (duff, coarse woody debris) 
-are optional.</p>
-<p>The LCP driver reads the linear unit, cell size, and extent, but the LCP file 
-does not specify the projection. UTM projections are typical, but other 
-projections are possible.</p>
-<p>The GDAL LCP driver reports dataset- and band-level metadata:</p>
-<h3>Dataset</h3>
-<blockquote>
-  <p>LATITUDE: Latitude of the dataset, negative for southern hemisphere<br>
-  LINEAR_UNIT: Feet or meters<br>
-  DESCRIPTION: LCP file description </p>
-</blockquote>
-<h3>Band</h3>
-<blockquote>
-  <p><band>_UNIT or <band>_OPTION: units or options code for the band<br>
-  <band>_UNIT_NAME or <band>_OPTION_DESC: descriptive name of 
-  units/options<br>
-  <band>_MIN: minimum value<br>
-  <band>_MAX: maximum value<br>
-  <band>_NUM_CLASSES: number of classes, -1 if > 100<br>
-  <band>_VALUES: comma-delimited list of class values (fuel model band 
-  only)<br>
-  <band>_FILE: original input raster file name for the band </p>
-</blockquote>
-<p><b>Note:</b> The LCP driver derives from the RawDataset helper class declared 
-in gdal/frmts/raw. It should be implemented as gdal/frmts/raw/lcpdataset.cpp.</p>
-<h3>Creation Options</h3>
-The LCP driver supports CreateCopy() and metadata values can be set via
-creation options.  Below is a list of options with default values listed first.
-<li><p><b>ELEVATION_UNIT=[METERS/FEET]</b>: Vertical unit for elevation
-band.</p></li>
-
-<li><p><b>SLOPE_UNIT=[DEGREES/PERCENT]</b></p></li>
-<li><p><b>ASPECT_UNIT=[AZIMUTH_DEGREES/GRASS_CATEGORIES/GRASS_DEGRESS]</b></p></li>
-<li><p><b>FUEL_MODEL_OPTION=[NO_CUSTOM_AND_NO_FILE/CUSTOM_AND_NO_FILE/
-    NO_CUSTOM_AND_FILE/CUSTOM_AND_FILE]</b>: Specify whether or not custom
-    fuel models are used, and if a custom fuel model file is present.</p></li>
-<li><p><b>CANOPY_COV_UNIT=[PERCENT/CATEGORIES]</b></p></li>
-<li><p><b>CANOPY_HT_UNIT=[METERS_X_10/FEET/METERS/FEET_X_10]</b></p></li>
-<li><p><b>CBH_UNIT=[METERS_X_10/METERS/FEET/FEET_X_10]</b></p></li>
-<li><p><b>CBD_UNIT=[KG_PER_CUBIC_METER_X_100/POUND_PER_CUBIC_FOOT/
-    KG_PER_CUBIC_METER/POUND_PER_CUBIC_FOOT_X_1000/TONS_PER_ACRE_X_100]</b></p></li>
-<li><p><b>DUFF_UNIT=[MG_PER_HECTARE_X_10/TONS_PER_ACRE_X_10]</b></p></li>
-<li><p><b>CALCULATE_STATS=[YES/NO]</b>: Calculate and write the min/max for
-    each band and write the appropriate flags and values in the header.  This is
-    mostly a legacy feature used for creating legends.</p></li>
-<li><p><b>CLASSIFY_DATA=[YES/NO]</b>: Classify the data into 100 unique values
-    or less and write and write the appropriate flags and values in the header.
-    This is mostly a legacy feature used for creating legends.</p></li>
-<li><p><b>LINEAR_UNIT=[SET_FROM_SRS/METER/FOOT/KILOMETER]</b>: Set the
-    linear unit, overriding (if it can be calculated) the value in the
-    associated spatial reference.  If no spatial reference is available, it
-    defaults to METER.</p></li>
-<li><p><b>LATITUDE=[-90-90]</b>: Override the latitude from the spatial
-    reference.  If no spatial reference is available, this should be set,
-    otherwise creation will fail.</p></li>
-<li><p><b>DESCRIPTION=[...]</b>: A short description(less than 512 characters)
-    of the dataset</p></li>
-
-Creation options that are units of linear measure are fairly lenient.
-METERS=METER and FOOT=FEET for the most part.
-
-<p><b>Note:</b> CreateCopy does not scale or change any data.  By setting the
-units for various bands, it is assumed that the values are in the specified
-units.</p>
-
-<p><b>LCP header format:</b></p>
-<table border="1" cellspacing="1" width="885">
-  <tr>
-    <td width="48"><b>Start byte</b> </td>
-    <td width="55"><b>No. of bytes</b> </td>
-    <td width="51"><b>Format</b> </td>
-    <td width="114"><b>Name</b> </td>
-    <td width="583"><b>Description</b> </td>
-  </tr>
-  <tr>
-    <td width="48">0 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">crown fuels </td>
-    <td width="583">20 if no crown fuels, 21 if crown fuels exist (crown fuels = 
-    canopy height, canopy base height, canopy bulk density) </td>
-  </tr>
-  <tr>
-    <td width="48">4 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">ground fuels </td>
-    <td width="583">20 if no ground fuels, 21 if ground fuels exist (ground 
-    fuels = duff loading, coarse woody) </td>
-  </tr>
-  <tr>
-    <td width="48">8 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">latitude </td>
-    <td width="583">latitude (negative for southern hemisphere) </td>
-  </tr>
-  <tr>
-    <td width="48">12 </td>
-    <td width="55">8 </td>
-    <td width="51">double </td>
-    <td width="114">loeast </td>
-    <td width="583">offset to preserve coordinate precision (legacy from 16-bit OS days) </td>
-  </tr>
-  <tr>
-    <td width="48">20 </td>
-    <td width="55">8 </td>
-    <td width="51">double </td>
-    <td width="114">hieast </td>
-    <td width="583">offset to preserve coordinate precision (legacy from 16-bit OS days) </td>
-  </tr>
-  <tr>
-    <td width="48">28 </td>
-    <td width="55">8 </td>
-    <td width="51">double </td>
-    <td width="114">lonorth </td>
-    <td width="583">offset to preserve coordinate precision (legacy from 16-bit OS days) </td>
-  </tr>
-  <tr>
-    <td width="48">36 </td>
-    <td width="55">8 </td>
-    <td width="51">double </td>
-    <td width="114">hinorth </td>
-    <td width="583">offset to preserve coordinate precision (legacy from 16-bit OS days) </td>
-  </tr>
-  <tr>
-    <td width="48">44 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">loelev </td>
-    <td width="583">minimum elevation </td>
-  </tr>
-  <tr>
-    <td width="48">48 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">hielev </td>
-    <td width="583">maximum elevation </td>
-  </tr>
-  <tr>
-    <td width="48">52 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">numelev </td>
-    <td width="583">number of elevation classes, -1 if > 100 </td>
-  </tr>
-  <tr>
-    <td width="48">56 </td>
-    <td width="55">400 </td>
-    <td width="51">long </td>
-    <td width="114">elevation values </td>
-    <td width="583">list of elevation values as longs </td>
-  </tr>
-  <tr>
-    <td width="48">456 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">loslope </td>
-    <td width="583">minimum slope </td>
-  </tr>
-  <tr>
-    <td width="48">460 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">hislope </td>
-    <td width="583">maximum slope </td>
-  </tr>
-  <tr>
-    <td width="48">464 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">numslope </td>
-    <td width="583">number of slope classes, -1 if > 100 </td>
-  </tr>
-  <tr>
-    <td width="48">468 </td>
-    <td width="55">400 </td>
-    <td width="51">long </td>
-    <td width="114">slope values </td>
-    <td width="583">list of slope values as longs </td>
-  </tr>
-  <tr>
-    <td width="48">868 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">loaspect </td>
-    <td width="583">minimum aspect </td>
-  </tr>
-  <tr>
-    <td width="48">872 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">hiaspect </td>
-    <td width="583">maximum aspect </td>
-  </tr>
-  <tr>
-    <td width="48">876 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">numaspects </td>
-    <td width="583">number of aspect classes, -1 if > 100 </td>
-  </tr>
-  <tr>
-    <td width="48">880 </td>
-    <td width="55">400 </td>
-    <td width="51">long </td>
-    <td width="114">aspect values </td>
-    <td width="583">list of aspect values as longs </td>
-  </tr>
-  <tr>
-    <td width="48">1280 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">lofuel </td>
-    <td width="583">minimum fuel model value </td>
-  </tr>
-  <tr>
-    <td width="48">1284 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">hifuel </td>
-    <td width="583">maximum fuel model value </td>
-  </tr>
-  <tr>
-    <td width="48">1288 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">numfuel </td>
-    <td width="583">number of fuel models -1 if > 100 </td>
-  </tr>
-  <tr>
-    <td width="48">1292 </td>
-    <td width="55">400 </td>
-    <td width="51">long </td>
-    <td width="114">fuel values </td>
-    <td width="583">list of fuel model values as longs </td>
-  </tr>
-  <tr>
-    <td width="48">1692 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">locover </td>
-    <td width="583">minimum canopy cover </td>
-  </tr>
-  <tr>
-    <td width="48">1696 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">hicover </td>
-    <td width="583">maximum canopy cover </td>
-  </tr>
-  <tr>
-    <td width="48">1700 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">numcover </td>
-    <td width="583">number of canopy cover classes, -1 if > 100 </td>
-  </tr>
-  <tr>
-    <td width="48">1704 </td>
-    <td width="55">400 </td>
-    <td width="51">long </td>
-    <td width="114">cover values </td>
-    <td width="583">list of canopy cover values as longs </td>
-  </tr>
-  <tr>
-    <td width="48">2104 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">loheight </td>
-    <td width="583">minimum canopy height </td>
-  </tr>
-  <tr>
-    <td width="48">2108 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">hiheight </td>
-    <td width="583">maximum canopy height </td>
-  </tr>
-  <tr>
-    <td width="48">2112 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">numheight </td>
-    <td width="583">number of canopy height classes, -1 if > 100 </td>
-  </tr>
-  <tr>
-    <td width="48">2116 </td>
-    <td width="55">400 </td>
-    <td width="51">long </td>
-    <td width="114">height values </td>
-    <td width="583">list of canopy height values as longs </td>
-  </tr>
-  <tr>
-    <td width="48">2516 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">lobase </td>
-    <td width="583">minimum canopy base height </td>
-  </tr>
-  <tr>
-    <td width="48">2520 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">hibase </td>
-    <td width="583">maximum canopy base height </td>
-  </tr>
-  <tr>
-    <td width="48">2524 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">numbase </td>
-    <td width="583">number of canopy base height classes, -1 if > 100 </td>
-  </tr>
-  <tr>
-    <td width="48">2528 </td>
-    <td width="55">400 </td>
-    <td width="51">long </td>
-    <td width="114">base values </td>
-    <td width="583">list of canopy base height values as longs </td>
-  </tr>
-  <tr>
-    <td width="48">2928 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">lodensity </td>
-    <td width="583">minimum canopy bulk density </td>
-  </tr>
-  <tr>
-    <td width="48">2932 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">hidensity </td>
-    <td width="583">maximum canopy bulk density </td>
-  </tr>
-  <tr>
-    <td width="48">2936 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">numdensity </td>
-    <td width="583">number of canopy bulk density classes, -1 if >100 </td>
-  </tr>
-  <tr>
-    <td width="48">2940 </td>
-    <td width="55">400 </td>
-    <td width="51">long </td>
-    <td width="114">density values </td>
-    <td width="583">list of canopy bulk density values as longs </td>
-  </tr>
-  <tr>
-    <td width="48">3340 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">loduff </td>
-    <td width="583">minimum duff </td>
-  </tr>
-  <tr>
-    <td width="48">3344 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">hiduff </td>
-    <td width="583">maximum duff </td>
-  </tr>
-  <tr>
-    <td width="48">3348 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">numduff </td>
-    <td width="583">number of duff classes, -1 if > 100 </td>
-  </tr>
-  <tr>
-    <td width="48">3352 </td>
-    <td width="55">400 </td>
-    <td width="51">long </td>
-    <td width="114">duff values </td>
-    <td width="583">list of duff values as longs </td>
-  </tr>
-  <tr>
-    <td width="48">3752 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">lowoody </td>
-    <td width="583">minimum coarse woody </td>
-  </tr>
-  <tr>
-    <td width="48">3756 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">hiwoody </td>
-    <td width="583">maximum coarse woody </td>
-  </tr>
-  <tr>
-    <td width="48">3760 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">numwoodies </td>
-    <td width="583">number of coarse woody classes, -1 if > 100 </td>
-  </tr>
-  <tr>
-    <td width="48">3764 </td>
-    <td width="55">400 </td>
-    <td width="51">long </td>
-    <td width="114">woody values </td>
-    <td width="583">list of coarse woody values as longs </td>
-  </tr>
-  <tr>
-    <td width="48">4164 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">numeast </td>
-    <td width="583">number of raster columns </td>
-  </tr>
-  <tr>
-    <td width="48">4168 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">numnorth </td>
-    <td width="583">number of raster rows </td>
-  </tr>
-  <tr>
-    <td width="48">4172 </td>
-    <td width="55">8 </td>
-    <td width="51">double </td>
-    <td width="114">EastUtm </td>
-    <td width="583">max X </td>
-  </tr>
-  <tr>
-    <td width="48">4180 </td>
-    <td width="55">8 </td>
-    <td width="51">double </td>
-    <td width="114">WestUtm </td>
-    <td width="583">min X </td>
-  </tr>
-  <tr>
-    <td width="48">4188 </td>
-    <td width="55">8 </td>
-    <td width="51">double </td>
-    <td width="114">NorthUtm </td>
-    <td width="583">max Y </td>
-  </tr>
-  <tr>
-    <td width="48">4196 </td>
-    <td width="55">8 </td>
-    <td width="51">double </td>
-    <td width="114">SouthUtm </td>
-    <td width="583">min Y </td>
-  </tr>
-  <tr>
-    <td width="48">4204 </td>
-    <td width="55">4 </td>
-    <td width="51">long </td>
-    <td width="114">GridUnits </td>
-    <td width="583">linear unit: 0 = meters, 1 = feet, 2 = kilometers </td>
-  </tr>
-  <tr>
-    <td width="48">4208 </td>
-    <td width="55">8 </td>
-    <td width="51">double </td>
-    <td width="114">XResol </td>
-    <td width="583">cell size width in GridUnits </td>
-  </tr>
-  <tr>
-    <td width="48">4216 </td>
-    <td width="55">8 </td>
-    <td width="51">double </td>
-    <td width="114">YResol </td>
-    <td width="583">cell size height in GridUnits </td>
-  </tr>
-  <tr>
-    <td width="48">4224 </td>
-    <td width="55">2 </td>
-    <td width="51">short </td>
-    <td width="114">EUnits </td>
-    <td width="583">elevation units: 0 = meters, 1 = feet </td>
-  </tr>
-  <tr>
-    <td width="48">4226 </td>
-    <td width="55">2 </td>
-    <td width="51">short </td>
-    <td width="114">SUnits </td>
-    <td width="583">slope units: 0 = degrees, 1 = percent </td>
-  </tr>
-  <tr>
-    <td width="48">4228 </td>
-    <td width="55">2 </td>
-    <td width="51">short </td>
-    <td width="114">AUnits </td>
-    <td width="583">aspect units: 0 = Grass categories, 1 = Grass degrees, 2 = 
-    azimuth degrees </td>
-  </tr>
-  <tr>
-    <td width="48">4230 </td>
-    <td width="55">2 </td>
-    <td width="51">short </td>
-    <td width="114">FOptions </td>
-    <td width="583">fuel model options: 0 = no custom models AND no conversion 
-    file, 1 = custom models BUT no conversion file, 2 = no custom models BUT 
-    conversion file, 3 = custom models AND conversion file needed </td>
-  </tr>
-  <tr>
-    <td width="48">4232 </td>
-    <td width="55">2 </td>
-    <td width="51">short </td>
-    <td width="114">CUnits </td>
-    <td width="583">canopy cover units: 0 = categories (0-4), 1 = percent </td>
-  </tr>
-  <tr>
-    <td width="48">4234 </td>
-    <td width="55">2 </td>
-    <td width="51">short </td>
-    <td width="114">HUnits </td>
-    <td width="583">canopy height units: 1 = meters, 2 = feet, 3 = m x 10, 4 = 
-    ft x 10 </td>
-  </tr>
-  <tr>
-    <td width="48">4236 </td>
-    <td width="55">2 </td>
-    <td width="51">short </td>
-    <td width="114">BUnits </td>
-    <td width="583">canopy base height units: 1 = meters, 2 = feet, 3 = m x 10, 
-    4 = ft x 10 </td>
-  </tr>
-  <tr>
-    <td width="48">4238 </td>
-    <td width="55">2 </td>
-    <td width="51">short </td>
-    <td width="114">PUnits </td>
-    <td width="583">canopy bulk density units: 1 = kg/m^3, 2 = lb/ft^3, 3 = 
-    kg/m^3 x 100, 4 = lb/ft^3 x 1000 </td>
-  </tr>
-  <tr>
-    <td width="48">4240 </td>
-    <td width="55">2 </td>
-    <td width="51">short </td>
-    <td width="114">DUnits </td>
-    <td width="583">duff units: 1 = Mg/ha x 10, 2 = t/ac x 10 </td>
-  </tr>
-  <tr>
-    <td width="48">4242 </td>
-    <td width="55">2 </td>
-    <td width="51">short </td>
-    <td width="114">WOptions </td>
-    <td width="583">coarse woody options (1 if coarse woody band is present) </td>
-  </tr>
-  <tr>
-    <td width="48">4244 </td>
-    <td width="55">256 </td>
-    <td width="51">char[] </td>
-    <td width="114">ElevFile </td>
-    <td width="583">elevation file name </td>
-  </tr>
-  <tr>
-    <td width="48">4500 </td>
-    <td width="55">256 </td>
-    <td width="51">char[] </td>
-    <td width="114">SlopeFile </td>
-    <td width="583">slope file name </td>
-  </tr>
-  <tr>
-    <td width="48">4756 </td>
-    <td width="55">256 </td>
-    <td width="51">char[] </td>
-    <td width="114">AspectFile </td>
-    <td width="583">aspect file name </td>
-  </tr>
-  <tr>
-    <td width="48">5012 </td>
-    <td width="55">256 </td>
-    <td width="51">char[] </td>
-    <td width="114">FuelFile </td>
-    <td width="583">fuel model file name </td>
-  </tr>
-  <tr>
-    <td width="48">5268 </td>
-    <td width="55">256 </td>
-    <td width="51">char[] </td>
-    <td width="114">CoverFile </td>
-    <td width="583">canopy cover file name </td>
-  </tr>
-  <tr>
-    <td width="48">5524 </td>
-    <td width="55">256 </td>
-    <td width="51">char[] </td>
-    <td width="114">HeightFile </td>
-    <td width="583">canopy height file name </td>
-  </tr>
-  <tr>
-    <td width="48">5780 </td>
-    <td width="55">256 </td>
-    <td width="51">char[] </td>
-    <td width="114">BaseFile </td>
-    <td width="583">canopy base file name </td>
-  </tr>
-  <tr>
-    <td width="48">6036 </td>
-    <td width="55">256 </td>
-    <td width="51">char[] </td>
-    <td width="114">DensityFile </td>
-    <td width="583">canopy bulk density file name </td>
-  </tr>
-  <tr>
-    <td width="48">6292 </td>
-    <td width="55">256 </td>
-    <td width="51">char[] </td>
-    <td width="114">DuffFile </td>
-    <td width="583">duff file name </td>
-  </tr>
-  <tr>
-    <td width="48">6548 </td>
-    <td width="55">256 </td>
-    <td width="51">char[] </td>
-    <td width="114">WoodyFile </td>
-    <td width="583">coarse woody file name </td>
-  </tr>
-  <tr>
-    <td width="48">6804 </td>
-    <td width="55">512 </td>
-    <td width="51">char[] </td>
-    <td width="114">Description </td>
-    <td width="583">LCP file description </td>
-  </tr>
-</table>
-
-<p><i>Chris Toney, 2009-02-14</i></p>
-
-</body>
-
-</html>
+<html>
+
+<head>
+<title>GDAL Driver for FARSITE LCP</title>
+</head>
+
+<body>
+
+<h2>GDAL Driver for FARSITE v.4 LCP Format</h2>
+<p>FARSITE v. 4 landscape file (LCP) is a multi-band raster format used by
+wildland fire behavior and fire effect simulation models such as FARSITE,
+FLAMMAP, and FBAT (<a href="http://www.fire.org">www.fire.org</a>). The bands of an LCP file store data describing
+terrain, tree canopy, and surface fuel. The
+<a href="http://landfire.cr.usgs.gov/viewer">USGS National Map for LANDFIRE</a>
+distributes data in LCP format, and
+programs such as FARSITE and <a href="http://www.landfire.gov/datatool.php">LFDAT</a> can create LCP files from a set of input rasters.</p>
+<p>An LCP file (.lcp) is basically a raw format with a 7,316-byte header
+described below. The data type for all bands is 16-bit signed integer. Bands are
+interleaved by pixel. Five bands are required: elevation, slope, aspect, fuel
+model, and tree canopy cover. Crown fuel bands (canopy height, canopy base
+height, canopy bulk density), and surface fuel bands (duff, coarse woody debris)
+are optional.</p>
+<p>The LCP driver reads the linear unit, cell size, and extent, but the LCP file
+does not specify the projection. UTM projections are typical, but other
+projections are possible.</p>
+<p>The GDAL LCP driver reports dataset- and band-level metadata:</p>
+<h3>Dataset</h3>
+<blockquote>
+  <p>LATITUDE: Latitude of the dataset, negative for southern hemisphere<br>
+  LINEAR_UNIT: Feet or meters<br>
+  DESCRIPTION: LCP file description </p>
+</blockquote>
+<h3>Band</h3>
+<blockquote>
+  <p><band>_UNIT or <band>_OPTION: units or options code for the band<br>
+  <band>_UNIT_NAME or <band>_OPTION_DESC: descriptive name of
+  units/options<br>
+  <band>_MIN: minimum value<br>
+  <band>_MAX: maximum value<br>
+  <band>_NUM_CLASSES: number of classes, -1 if > 100<br>
+  <band>_VALUES: comma-delimited list of class values (fuel model band
+  only)<br>
+  <band>_FILE: original input raster file name for the band </p>
+</blockquote>
+<p><b>Note:</b> The LCP driver derives from the RawDataset helper class declared
+in gdal/frmts/raw. It should be implemented as gdal/frmts/raw/lcpdataset.cpp.</p>
+<h3>Creation Options</h3>
+The LCP driver supports CreateCopy() and metadata values can be set via
+creation options.  Below is a list of options with default values listed first.
+<li><p><b>ELEVATION_UNIT=[METERS/FEET]</b>: Vertical unit for elevation
+band.</p></li>
+
+<li><p><b>SLOPE_UNIT=[DEGREES/PERCENT]</b></p></li>
+<li><p><b>ASPECT_UNIT=[AZIMUTH_DEGREES/GRASS_CATEGORIES/GRASS_DEGREES]</b></p></li>
+<li><p><b>FUEL_MODEL_OPTION=[NO_CUSTOM_AND_NO_FILE/CUSTOM_AND_NO_FILE/
+    NO_CUSTOM_AND_FILE/CUSTOM_AND_FILE]</b>: Specify whether or not custom
+    fuel models are used, and if a custom fuel model file is present.</p></li>
+<li><p><b>CANOPY_COV_UNIT=[PERCENT/CATEGORIES]</b></p></li>
+<li><p><b>CANOPY_HT_UNIT=[METERS_X_10/FEET/METERS/FEET_X_10]</b></p></li>
+<li><p><b>CBH_UNIT=[METERS_X_10/METERS/FEET/FEET_X_10]</b></p></li>
+<li><p><b>CBD_UNIT=[KG_PER_CUBIC_METER_X_100/POUND_PER_CUBIC_FOOT/
+    KG_PER_CUBIC_METER/POUND_PER_CUBIC_FOOT_X_1000/TONS_PER_ACRE_X_100]</b></p></li>
+<li><p><b>DUFF_UNIT=[MG_PER_HECTARE_X_10/TONS_PER_ACRE_X_10]</b></p></li>
+<li><p><b>CALCULATE_STATS=[YES/NO]</b>: Calculate and write the min/max for
+    each band and write the appropriate flags and values in the header.  This is
+    mostly a legacy feature used for creating legends.</p></li>
+<li><p><b>CLASSIFY_DATA=[YES/NO]</b>: Classify the data into 100 unique values
+    or less and write and write the appropriate flags and values in the header.
+    This is mostly a legacy feature used for creating legends.</p></li>
+<li><p><b>LINEAR_UNIT=[SET_FROM_SRS/METER/FOOT/KILOMETER]</b>: Set the
+    linear unit, overriding (if it can be calculated) the value in the
+    associated spatial reference.  If no spatial reference is available, it
+    defaults to METER.</p></li>
+<li><p><b>LATITUDE=[-90-90]</b>: Override the latitude from the spatial
+    reference.  If no spatial reference is available, this should be set,
+    otherwise creation will fail.</p></li>
+<li><p><b>DESCRIPTION=[...]</b>: A short description(less than 512 characters)
+    of the dataset</p></li>
+
+Creation options that are units of linear measure are fairly lenient.
+METERS=METER and FOOT=FEET for the most part.
+
+<p><b>Note:</b> CreateCopy does not scale or change any data.  By setting the
+units for various bands, it is assumed that the values are in the specified
+units.</p>
+
+<p><b>LCP header format:</b></p>
+<table border="1" cellspacing="1" width="885">
+  <tr>
+    <td width="48"><b>Start byte</b> </td>
+    <td width="55"><b>No. of bytes</b> </td>
+    <td width="51"><b>Format</b> </td>
+    <td width="114"><b>Name</b> </td>
+    <td width="583"><b>Description</b> </td>
+  </tr>
+  <tr>
+    <td width="48">0 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">crown fuels </td>
+    <td width="583">20 if no crown fuels, 21 if crown fuels exist (crown fuels =
+    canopy height, canopy base height, canopy bulk density) </td>
+  </tr>
+  <tr>
+    <td width="48">4 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">ground fuels </td>
+    <td width="583">20 if no ground fuels, 21 if ground fuels exist (ground
+    fuels = duff loading, coarse woody) </td>
+  </tr>
+  <tr>
+    <td width="48">8 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">latitude </td>
+    <td width="583">latitude (negative for southern hemisphere) </td>
+  </tr>
+  <tr>
+    <td width="48">12 </td>
+    <td width="55">8 </td>
+    <td width="51">double </td>
+    <td width="114">loeast </td>
+    <td width="583">offset to preserve coordinate precision (legacy from 16-bit OS days) </td>
+  </tr>
+  <tr>
+    <td width="48">20 </td>
+    <td width="55">8 </td>
+    <td width="51">double </td>
+    <td width="114">hieast </td>
+    <td width="583">offset to preserve coordinate precision (legacy from 16-bit OS days) </td>
+  </tr>
+  <tr>
+    <td width="48">28 </td>
+    <td width="55">8 </td>
+    <td width="51">double </td>
+    <td width="114">lonorth </td>
+    <td width="583">offset to preserve coordinate precision (legacy from 16-bit OS days) </td>
+  </tr>
+  <tr>
+    <td width="48">36 </td>
+    <td width="55">8 </td>
+    <td width="51">double </td>
+    <td width="114">hinorth </td>
+    <td width="583">offset to preserve coordinate precision (legacy from 16-bit OS days) </td>
+  </tr>
+  <tr>
+    <td width="48">44 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">loelev </td>
+    <td width="583">minimum elevation </td>
+  </tr>
+  <tr>
+    <td width="48">48 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">hielev </td>
+    <td width="583">maximum elevation </td>
+  </tr>
+  <tr>
+    <td width="48">52 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">numelev </td>
+    <td width="583">number of elevation classes, -1 if > 100 </td>
+  </tr>
+  <tr>
+    <td width="48">56 </td>
+    <td width="55">400 </td>
+    <td width="51">long </td>
+    <td width="114">elevation values </td>
+    <td width="583">list of elevation values as longs </td>
+  </tr>
+  <tr>
+    <td width="48">456 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">loslope </td>
+    <td width="583">minimum slope </td>
+  </tr>
+  <tr>
+    <td width="48">460 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">hislope </td>
+    <td width="583">maximum slope </td>
+  </tr>
+  <tr>
+    <td width="48">464 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">numslope </td>
+    <td width="583">number of slope classes, -1 if > 100 </td>
+  </tr>
+  <tr>
+    <td width="48">468 </td>
+    <td width="55">400 </td>
+    <td width="51">long </td>
+    <td width="114">slope values </td>
+    <td width="583">list of slope values as longs </td>
+  </tr>
+  <tr>
+    <td width="48">868 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">loaspect </td>
+    <td width="583">minimum aspect </td>
+  </tr>
+  <tr>
+    <td width="48">872 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">hiaspect </td>
+    <td width="583">maximum aspect </td>
+  </tr>
+  <tr>
+    <td width="48">876 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">numaspects </td>
+    <td width="583">number of aspect classes, -1 if > 100 </td>
+  </tr>
+  <tr>
+    <td width="48">880 </td>
+    <td width="55">400 </td>
+    <td width="51">long </td>
+    <td width="114">aspect values </td>
+    <td width="583">list of aspect values as longs </td>
+  </tr>
+  <tr>
+    <td width="48">1280 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">lofuel </td>
+    <td width="583">minimum fuel model value </td>
+  </tr>
+  <tr>
+    <td width="48">1284 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">hifuel </td>
+    <td width="583">maximum fuel model value </td>
+  </tr>
+  <tr>
+    <td width="48">1288 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">numfuel </td>
+    <td width="583">number of fuel models -1 if > 100 </td>
+  </tr>
+  <tr>
+    <td width="48">1292 </td>
+    <td width="55">400 </td>
+    <td width="51">long </td>
+    <td width="114">fuel values </td>
+    <td width="583">list of fuel model values as longs </td>
+  </tr>
+  <tr>
+    <td width="48">1692 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">locover </td>
+    <td width="583">minimum canopy cover </td>
+  </tr>
+  <tr>
+    <td width="48">1696 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">hicover </td>
+    <td width="583">maximum canopy cover </td>
+  </tr>
+  <tr>
+    <td width="48">1700 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">numcover </td>
+    <td width="583">number of canopy cover classes, -1 if > 100 </td>
+  </tr>
+  <tr>
+    <td width="48">1704 </td>
+    <td width="55">400 </td>
+    <td width="51">long </td>
+    <td width="114">cover values </td>
+    <td width="583">list of canopy cover values as longs </td>
+  </tr>
+  <tr>
+    <td width="48">2104 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">loheight </td>
+    <td width="583">minimum canopy height </td>
+  </tr>
+  <tr>
+    <td width="48">2108 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">hiheight </td>
+    <td width="583">maximum canopy height </td>
+  </tr>
+  <tr>
+    <td width="48">2112 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">numheight </td>
+    <td width="583">number of canopy height classes, -1 if > 100 </td>
+  </tr>
+  <tr>
+    <td width="48">2116 </td>
+    <td width="55">400 </td>
+    <td width="51">long </td>
+    <td width="114">height values </td>
+    <td width="583">list of canopy height values as longs </td>
+  </tr>
+  <tr>
+    <td width="48">2516 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">lobase </td>
+    <td width="583">minimum canopy base height </td>
+  </tr>
+  <tr>
+    <td width="48">2520 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">hibase </td>
+    <td width="583">maximum canopy base height </td>
+  </tr>
+  <tr>
+    <td width="48">2524 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">numbase </td>
+    <td width="583">number of canopy base height classes, -1 if > 100 </td>
+  </tr>
+  <tr>
+    <td width="48">2528 </td>
+    <td width="55">400 </td>
+    <td width="51">long </td>
+    <td width="114">base values </td>
+    <td width="583">list of canopy base height values as longs </td>
+  </tr>
+  <tr>
+    <td width="48">2928 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">lodensity </td>
+    <td width="583">minimum canopy bulk density </td>
+  </tr>
+  <tr>
+    <td width="48">2932 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">hidensity </td>
+    <td width="583">maximum canopy bulk density </td>
+  </tr>
+  <tr>
+    <td width="48">2936 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">numdensity </td>
+    <td width="583">number of canopy bulk density classes, -1 if >100 </td>
+  </tr>
+  <tr>
+    <td width="48">2940 </td>
+    <td width="55">400 </td>
+    <td width="51">long </td>
+    <td width="114">density values </td>
+    <td width="583">list of canopy bulk density values as longs </td>
+  </tr>
+  <tr>
+    <td width="48">3340 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">loduff </td>
+    <td width="583">minimum duff </td>
+  </tr>
+  <tr>
+    <td width="48">3344 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">hiduff </td>
+    <td width="583">maximum duff </td>
+  </tr>
+  <tr>
+    <td width="48">3348 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">numduff </td>
+    <td width="583">number of duff classes, -1 if > 100 </td>
+  </tr>
+  <tr>
+    <td width="48">3352 </td>
+    <td width="55">400 </td>
+    <td width="51">long </td>
+    <td width="114">duff values </td>
+    <td width="583">list of duff values as longs </td>
+  </tr>
+  <tr>
+    <td width="48">3752 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">lowoody </td>
+    <td width="583">minimum coarse woody </td>
+  </tr>
+  <tr>
+    <td width="48">3756 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">hiwoody </td>
+    <td width="583">maximum coarse woody </td>
+  </tr>
+  <tr>
+    <td width="48">3760 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">numwoodies </td>
+    <td width="583">number of coarse woody classes, -1 if > 100 </td>
+  </tr>
+  <tr>
+    <td width="48">3764 </td>
+    <td width="55">400 </td>
+    <td width="51">long </td>
+    <td width="114">woody values </td>
+    <td width="583">list of coarse woody values as longs </td>
+  </tr>
+  <tr>
+    <td width="48">4164 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">numeast </td>
+    <td width="583">number of raster columns </td>
+  </tr>
+  <tr>
+    <td width="48">4168 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">numnorth </td>
+    <td width="583">number of raster rows </td>
+  </tr>
+  <tr>
+    <td width="48">4172 </td>
+    <td width="55">8 </td>
+    <td width="51">double </td>
+    <td width="114">EastUtm </td>
+    <td width="583">max X </td>
+  </tr>
+  <tr>
+    <td width="48">4180 </td>
+    <td width="55">8 </td>
+    <td width="51">double </td>
+    <td width="114">WestUtm </td>
+    <td width="583">min X </td>
+  </tr>
+  <tr>
+    <td width="48">4188 </td>
+    <td width="55">8 </td>
+    <td width="51">double </td>
+    <td width="114">NorthUtm </td>
+    <td width="583">max Y </td>
+  </tr>
+  <tr>
+    <td width="48">4196 </td>
+    <td width="55">8 </td>
+    <td width="51">double </td>
+    <td width="114">SouthUtm </td>
+    <td width="583">min Y </td>
+  </tr>
+  <tr>
+    <td width="48">4204 </td>
+    <td width="55">4 </td>
+    <td width="51">long </td>
+    <td width="114">GridUnits </td>
+    <td width="583">linear unit: 0 = meters, 1 = feet, 2 = kilometers </td>
+  </tr>
+  <tr>
+    <td width="48">4208 </td>
+    <td width="55">8 </td>
+    <td width="51">double </td>
+    <td width="114">XResol </td>
+    <td width="583">cell size width in GridUnits </td>
+  </tr>
+  <tr>
+    <td width="48">4216 </td>
+    <td width="55">8 </td>
+    <td width="51">double </td>
+    <td width="114">YResol </td>
+    <td width="583">cell size height in GridUnits </td>
+  </tr>
+  <tr>
+    <td width="48">4224 </td>
+    <td width="55">2 </td>
+    <td width="51">short </td>
+    <td width="114">EUnits </td>
+    <td width="583">elevation units: 0 = meters, 1 = feet </td>
+  </tr>
+  <tr>
+    <td width="48">4226 </td>
+    <td width="55">2 </td>
+    <td width="51">short </td>
+    <td width="114">SUnits </td>
+    <td width="583">slope units: 0 = degrees, 1 = percent </td>
+  </tr>
+  <tr>
+    <td width="48">4228 </td>
+    <td width="55">2 </td>
+    <td width="51">short </td>
+    <td width="114">AUnits </td>
+    <td width="583">aspect units: 0 = Grass categories, 1 = Grass degrees, 2 =
+    azimuth degrees </td>
+  </tr>
+  <tr>
+    <td width="48">4230 </td>
+    <td width="55">2 </td>
+    <td width="51">short </td>
+    <td width="114">FOptions </td>
+    <td width="583">fuel model options: 0 = no custom models AND no conversion
+    file, 1 = custom models BUT no conversion file, 2 = no custom models BUT
+    conversion file, 3 = custom models AND conversion file needed </td>
+  </tr>
+  <tr>
+    <td width="48">4232 </td>
+    <td width="55">2 </td>
+    <td width="51">short </td>
+    <td width="114">CUnits </td>
+    <td width="583">canopy cover units: 0 = categories (0-4), 1 = percent </td>
+  </tr>
+  <tr>
+    <td width="48">4234 </td>
+    <td width="55">2 </td>
+    <td width="51">short </td>
+    <td width="114">HUnits </td>
+    <td width="583">canopy height units: 1 = meters, 2 = feet, 3 = m x 10, 4 =
+    ft x 10 </td>
+  </tr>
+  <tr>
+    <td width="48">4236 </td>
+    <td width="55">2 </td>
+    <td width="51">short </td>
+    <td width="114">BUnits </td>
+    <td width="583">canopy base height units: 1 = meters, 2 = feet, 3 = m x 10,
+    4 = ft x 10 </td>
+  </tr>
+  <tr>
+    <td width="48">4238 </td>
+    <td width="55">2 </td>
+    <td width="51">short </td>
+    <td width="114">PUnits </td>
+    <td width="583">canopy bulk density units: 1 = kg/m^3, 2 = lb/ft^3, 3 =
+    kg/m^3 x 100, 4 = lb/ft^3 x 1000 </td>
+  </tr>
+  <tr>
+    <td width="48">4240 </td>
+    <td width="55">2 </td>
+    <td width="51">short </td>
+    <td width="114">DUnits </td>
+    <td width="583">duff units: 1 = Mg/ha x 10, 2 = t/ac x 10 </td>
+  </tr>
+  <tr>
+    <td width="48">4242 </td>
+    <td width="55">2 </td>
+    <td width="51">short </td>
+    <td width="114">WOptions </td>
+    <td width="583">coarse woody options (1 if coarse woody band is present) </td>
+  </tr>
+  <tr>
+    <td width="48">4244 </td>
+    <td width="55">256 </td>
+    <td width="51">char[] </td>
+    <td width="114">ElevFile </td>
+    <td width="583">elevation file name </td>
+  </tr>
+  <tr>
+    <td width="48">4500 </td>
+    <td width="55">256 </td>
+    <td width="51">char[] </td>
+    <td width="114">SlopeFile </td>
+    <td width="583">slope file name </td>
+  </tr>
+  <tr>
+    <td width="48">4756 </td>
+    <td width="55">256 </td>
+    <td width="51">char[] </td>
+    <td width="114">AspectFile </td>
+    <td width="583">aspect file name </td>
+  </tr>
+  <tr>
+    <td width="48">5012 </td>
+    <td width="55">256 </td>
+    <td width="51">char[] </td>
+    <td width="114">FuelFile </td>
+    <td width="583">fuel model file name </td>
+  </tr>
+  <tr>
+    <td width="48">5268 </td>
+    <td width="55">256 </td>
+    <td width="51">char[] </td>
+    <td width="114">CoverFile </td>
+    <td width="583">canopy cover file name </td>
+  </tr>
+  <tr>
+    <td width="48">5524 </td>
+    <td width="55">256 </td>
+    <td width="51">char[] </td>
+    <td width="114">HeightFile </td>
+    <td width="583">canopy height file name </td>
+  </tr>
+  <tr>
+    <td width="48">5780 </td>
+    <td width="55">256 </td>
+    <td width="51">char[] </td>
+    <td width="114">BaseFile </td>
+    <td width="583">canopy base file name </td>
+  </tr>
+  <tr>
+    <td width="48">6036 </td>
+    <td width="55">256 </td>
+    <td width="51">char[] </td>
+    <td width="114">DensityFile </td>
+    <td width="583">canopy bulk density file name </td>
+  </tr>
+  <tr>
+    <td width="48">6292 </td>
+    <td width="55">256 </td>
+    <td width="51">char[] </td>
+    <td width="114">DuffFile </td>
+    <td width="583">duff file name </td>
+  </tr>
+  <tr>
+    <td width="48">6548 </td>
+    <td width="55">256 </td>
+    <td width="51">char[] </td>
+    <td width="114">WoodyFile </td>
+    <td width="583">coarse woody file name </td>
+  </tr>
+  <tr>
+    <td width="48">6804 </td>
+    <td width="55">512 </td>
+    <td width="51">char[] </td>
+    <td width="114">Description </td>
+    <td width="583">LCP file description </td>
+  </tr>
+</table>
+
+<p><i>Chris Toney, 2009-02-14</i></p>
+
+</body>
+
+</html>
diff --git a/frmts/raw/frmt_mff2.html b/frmts/raw/frmt_mff2.html
index 13e684e..d6fe0fd 100644
--- a/frmts/raw/frmt_mff2.html
+++ b/frmts/raw/frmt_mff2.html
@@ -7,19 +7,19 @@
 
 <h1>MFF2 -- Vexcel MFF2 Image</h1>
 GDAL supports MFF2 Image raster file format for read, update, and creation.
-The MFF2 (Multi-File Format 2) format was designed to fit into 
-Vexcel Hierarchical Key-Value (HKV) databases, which can store 
-binary data as well as ASCII parameters. 
+The MFF2 (Multi-File Format 2) format was designed to fit into
+Vexcel Hierarchical Key-Value (HKV) databases, which can store
+binary data as well as ASCII parameters.
 This format is primarily used internally to the Vexcel InSAR
 processing system.<p>
 
-To select an MFF2 dataset, select the directory containing the <tt>attrib</tt>, 
+To select an MFF2 dataset, select the directory containing the <tt>attrib</tt>,
 and <tt>image_data</tt> files for the dataset.<p>
 
-Currently only latitude/longitude and UTM projection are supported 
+Currently only latitude/longitude and UTM projection are supported
 (georef.projection.name = ll or georef.projection.name = utm),
 with the affine transform computed from the lat/long control points.   In
-any event, if GCPs are available in a georef file, they are returned with 
+any event, if GCPs are available in a georef file, they are returned with
 the dataset.<p>
 
 Newly created files (with a type of <tt>MFF2</tt>) are always just raw rasters
@@ -34,13 +34,13 @@ NOTE: Implemented as <tt>gdal/frmts/raw/hkvdataset.cpp</tt>.<p>
 
 <h3>MFF2 Top-level Structure</h3>
 
-An MFF2 "file" is actually a set of files stored in a directory 
-containing an ASCII header file entitled "attrib", and binary 
-image data entitled "image_data".  Optionally, there may be 
-an ASCII "georef" file containing georeferencing and projection 
+An MFF2 "file" is actually a set of files stored in a directory
+containing an ASCII header file entitled "attrib", and binary
+image data entitled "image_data".  Optionally, there may be
+an ASCII "georef" file containing georeferencing and projection
 information, and an "image_data_ovr" (for "image_data" binary image data)
 file containing tiled overviews of the image in TIFF format.
-The ASCII files are arranged in key=value pairs. The allowable 
+The ASCII files are arranged in key=value pairs. The allowable
 pairs for each file are described below.
 
 
@@ -63,7 +63,7 @@ version        = 1.1
 specifies an image that is 1040 lines by 800 pixels in extent.  The
 pixels are 32 bits of real data in "most significant byte first" (msbf)
 order, encoded according to the ieee_754 specification.  In MFF2, when
-a value must belong to a certain subset (eg. pixel.order must be either 
+a value must belong to a certain subset (eg. pixel.order must be either
 lsbf or msbf), all options are displayed between curly brackets, and
 the one appropriate for the current file is indicated with a "*".
 <p>
@@ -125,10 +125,10 @@ bottom_right: (Npix,Nline)
 centre: (Npix/2.0,Nline/2.0)
 </pre>
 
-These calculations are done using floating point arithmetic (ie.
+These calculations are done using floating point arithmetic (i.e.
 centre coordinates may take on non-integer values).
 <p>
-Note that the corners are always expressed in latitudes/longitudes, even 
+Note that the corners are always expressed in latitudes/longitudes, even
 for projected images.
 <p>
 
@@ -137,16 +137,16 @@ for projected images.
 ll- Orthogonal latitude/longitude projected image, with latitude
 parallel to the rows, longitude parallel to the columns. Parameters:
 spheroid name, projection.origin_longitude (longitude at the origin of
-the projection coordinates).  If not set, this should default to the 
+the projection coordinates).  If not set, this should default to the
 central longitude of the output image based on its projection boundaries.
 <p>
 utm- Universal Transverse Mercator projected image.  Parameters:
 spheroid name, projection.origin_longitude (central meridian for the
-utm projection).  The central meridian must be the  meridian at the 
-centre of a UTM zone, ie. 3 degrees, 9 degrees, 12 degrees, etc.  If 
-this is not specified or set a valid UTM central meridian, the reader 
-should reset the value to the nearest valid central meridian based on 
-the central longitude of the output image.  The latitude at the origin 
+utm projection).  The central meridian must be the  meridian at the
+centre of a UTM zone, i.e. 3 degrees, 9 degrees, 12 degrees, etc.  If
+this is not specified or set a valid UTM central meridian, the reader
+should reset the value to the nearest valid central meridian based on
+the central longitude of the output image.  The latitude at the origin
 of the UTM projection is always 0 degrees.
 <p>
 
@@ -195,13 +195,13 @@ ev-bessel:             6377397          299.1976073
 channel.enumeration:  (optional- only needed for multiband)
 Number of channels of data (eg. 3 for rgb)
 
-channel.interleave = { *pixel tile sequential } :  (optional- only 
+channel.interleave = { *pixel tile sequential } :  (optional- only
 needed for multiband)
 
-For multiband data, indicates how the channels are interleaved.  *pixel 
-indicates that data is stored red value, green value, blue value, red 
-value, green value, blue value etc. as opposed to (line of red values) 
-(line of green values) (line of blue values) or (entire red channel) 
+For multiband data, indicates how the channels are interleaved.  *pixel
+indicates that data is stored red value, green value, blue value, red
+value, green value, blue value etc. as opposed to (line of red values)
+(line of green values) (line of blue values) or (entire red channel)
 (entire green channel) (entire blue channel)
 
 extent.cols:
@@ -233,8 +233,8 @@ Whether the data is real or complex.
 pixel.order = { *lsbf msbf }:
 Byte ordering of the data (least or most significant byte first).
 
-version: (only in newer versions- if not present, older version is 
-assumed) Version of mff2.  
+version: (only in newer versions- if not present, older version is
+assumed) Version of mff2.
 </pre>
 
 </body>
diff --git a/frmts/raw/fujibasdataset.cpp b/frmts/raw/fujibasdataset.cpp
index af2bb09..c0f2fbf 100644
--- a/frmts/raw/fujibasdataset.cpp
+++ b/frmts/raw/fujibasdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: fujibasdataset.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: fujibasdataset.cpp 33673 2016-03-07 20:40:54Z goatbar $
  *
  * Project:  eCognition
  * Purpose:  Implementation of FUJI BAS Format
@@ -28,13 +28,14 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "rawdataset.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "rawdataset.h"
 
-CPL_CVSID("$Id: fujibasdataset.cpp 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: fujibasdataset.cpp 33673 2016-03-07 20:40:54Z goatbar $");
 
 CPL_C_START
-void	GDALRegister_FujiBAS(void);
+void GDALRegister_FujiBAS();
 CPL_C_END
 
 /************************************************************************/
@@ -46,13 +47,13 @@ CPL_C_END
 class FujiBASDataset : public RawDataset
 {
     FILE	*fpImage;	// image data file.
-    
+
     char	**papszHeader;
 
   public:
     		FujiBASDataset();
     	        ~FujiBASDataset();
-    
+
     static GDALDataset *Open( GDALOpenInfo * );
 };
 
@@ -60,11 +61,10 @@ class FujiBASDataset : public RawDataset
 /*                            FujiBASDataset()                          */
 /************************************************************************/
 
-FujiBASDataset::FujiBASDataset()
-{
-    fpImage = NULL;
-    papszHeader = NULL;
-}
+FujiBASDataset::FujiBASDataset() :
+    fpImage(NULL),
+    papszHeader(NULL)
+{}
 
 /************************************************************************/
 /*                            ~FujiBASDataset()                            */
@@ -93,18 +93,14 @@ GDALDataset *FujiBASDataset::Open( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->nHeaderBytes < 80 || poOpenInfo->fpL == NULL )
         return NULL;
 
-    if( !EQUALN((const char *)poOpenInfo->pabyHeader,"[Raw data]",10)
+    if( !STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "[Raw data]")
         || strstr((const char *)poOpenInfo->pabyHeader, "Fuji BAS") == NULL )
         return NULL;
 
 /* -------------------------------------------------------------------- */
 /*	Load the header file.						*/
 /* -------------------------------------------------------------------- */
-    char	**papszHeader;
-    int		nXSize, nYSize;
-    const char  *pszOrgFile;
-
-    papszHeader = CSLLoad( poOpenInfo->pszFilename );
+    char **papszHeader = CSLLoad( poOpenInfo->pszFilename );
 
     if( papszHeader == NULL )
         return NULL;
@@ -112,9 +108,7 @@ GDALDataset *FujiBASDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Munge header information into form suitable for CSL functions.  */
 /* -------------------------------------------------------------------- */
-    int		i;
-
-    for( i = 0; papszHeader[i] != NULL; i++ )
+    for( int i = 0; papszHeader[i] != NULL; i++ )
     {
         char	*pszSep = strstr(papszHeader[i]," = ");
 
@@ -136,10 +130,10 @@ GDALDataset *FujiBASDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    nYSize = atoi(CSLFetchNameValue(papszHeader,"width"));
-    nXSize = atoi(CSLFetchNameValue(papszHeader,"height"));
+    const int nYSize = atoi(CSLFetchNameValue(papszHeader,"width"));
+    const int nXSize = atoi(CSLFetchNameValue(papszHeader,"height"));
 
-    pszOrgFile = CSLFetchNameValue(papszHeader,"OrgFile");
+    const char *pszOrgFile = CSLFetchNameValue(papszHeader,"OrgFile");
 
     if( nXSize < 1 || nYSize < 1 )
     {
@@ -152,32 +146,29 @@ GDALDataset *FujiBASDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The FUJIBAS driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Try to open the original data file.                             */
 /* -------------------------------------------------------------------- */
-    const char *pszRawFile;
     char       *pszPath = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
-    FILE       *fpRaw;
-    
-    pszRawFile = CPLFormCIFilename( pszPath, pszOrgFile, "IMG" );
+    const char *pszRawFile = CPLFormCIFilename( pszPath, pszOrgFile, "IMG" );
     CPLFree( pszPath );
-    
-    fpRaw = VSIFOpen( pszRawFile, "rb" );
+
+    FILE *fpRaw = VSIFOpen( pszRawFile, "rb" );
     if( fpRaw == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "Trying to open Fuji BAS image with the header file:\n"
                   "  Header=%s\n"
                   "but expected raw image file doesn't appear to exist.  Trying to open:\n"
                   "  Raw File=%s\n"
                   "Perhaps the raw file needs to be renamed to match expected?",
-                  poOpenInfo->pszFilename, 
+                  poOpenInfo->pszFilename,
                   pszRawFile );
         CSLDestroy( papszHeader );
         return NULL;
@@ -186,9 +177,7 @@ GDALDataset *FujiBASDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    FujiBASDataset 	*poDS;
-
-    poDS = new FujiBASDataset();
+    FujiBASDataset *poDS = new FujiBASDataset();
 
 /* -------------------------------------------------------------------- */
 /*      Capture some information from the file that is of interest.     */
@@ -201,14 +190,15 @@ GDALDataset *FujiBASDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create band information object.                                 */
 /* -------------------------------------------------------------------- */
-    int bNativeOrder;
+    const int bNativeOrder =
 #ifdef CPL_MSB
-    bNativeOrder = TRUE;
+    TRUE
 #else
-    bNativeOrder = FALSE;
+    FALSE
 #endif
-    poDS->SetBand( 1, 
-                   new RawRasterBand( poDS, 1, poDS->fpImage, 
+        ;
+    poDS->SetBand( 1,
+                   new RawRasterBand( poDS, 1, poDS->fpImage,
                                       0, 2, nXSize * 2, GDT_UInt16, bNativeOrder ));
 
 /* -------------------------------------------------------------------- */
@@ -216,7 +206,7 @@ GDALDataset *FujiBASDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->TryLoadXML();
-    
+
 /* -------------------------------------------------------------------- */
 /*      Check for overviews.                                            */
 /* -------------------------------------------------------------------- */
@@ -232,22 +222,18 @@ GDALDataset *FujiBASDataset::Open( GDALOpenInfo * poOpenInfo )
 void GDALRegister_FujiBAS()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "FujiBAS" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "FujiBAS" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "FujiBAS" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Fuji BAS Scanner Image" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#FujiBAS" );
-        
-        poDriver->pfnOpen = FujiBASDataset::Open;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
-}
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "FujiBAS" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Fuji BAS Scanner Image" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_various.html#FujiBAS" );
 
+    poDriver->pfnOpen = FujiBASDataset::Open;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/frmts/raw/genbindataset.cpp b/frmts/raw/genbindataset.cpp
index 7046953..047c309 100644
--- a/frmts/raw/genbindataset.cpp
+++ b/frmts/raw/genbindataset.cpp
@@ -28,16 +28,13 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "rawdataset.h"
-#include "ogr_spatialref.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "ogr_spatialref.h"
+#include "rawdataset.h"
 
 CPL_CVSID("$Id: ehdrdataset.cpp 12350 2007-10-08 17:41:32Z rouault $");
 
-CPL_C_START
-void	GDALRegister_GenBin(void);
-CPL_C_END
-
 /* ==================================================================== */
 /*      Table relating USGS and ESRI state plane zones.                 */
 /* ==================================================================== */
@@ -208,10 +205,10 @@ class GenBinDataset : public RawDataset
   public:
     GenBinDataset();
     ~GenBinDataset();
-    
+
     virtual CPLErr GetGeoTransform( double * padfTransform );
     virtual const char *GetProjectionRef(void);
-    
+
     virtual char **GetFileList();
 
     static GDALDataset *Open( GDALOpenInfo * );
@@ -237,19 +234,19 @@ class GenBinBitRasterBand : public GDALPamRasterBand
 /*                        GenBinBitRasterBand()                         */
 /************************************************************************/
 
-GenBinBitRasterBand::GenBinBitRasterBand( GenBinDataset *poDS, int nBitsIn )
+GenBinBitRasterBand::GenBinBitRasterBand( GenBinDataset *poDSIn, int nBitsIn ) :
+    nBits(nBitsIn)
 {
-    SetMetadataItem( "NBITS", 
-                     CPLString().Printf("%d",nBitsIn), 
+    SetMetadataItem( "NBITS",
+                     CPLString().Printf("%d",nBitsIn),
                      "IMAGE_STRUCTURE" );
 
-    this->poDS = poDS;
-    nBits = nBitsIn;
+    poDS = poDSIn;
     nBand = 1;
 
     eDataType = GDT_Byte;
 
-    nBlockXSize = poDS->nRasterXSize;
+    nBlockXSize = poDSIn->nRasterXSize;
     nBlockYSize = 1;
 }
 
@@ -262,65 +259,65 @@ CPLErr GenBinBitRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                                         void * pImage )
 
 {
-    GenBinDataset *poGDS = (GenBinDataset *) poDS;
-    vsi_l_offset   nLineStart;
-    unsigned int   nLineBytes;
-    int            iBitOffset;
-    GByte         *pabyBuffer;
+    GenBinDataset *poGDS = reinterpret_cast<GenBinDataset *>( poDS );
 
 /* -------------------------------------------------------------------- */
 /*      Establish desired position.                                     */
 /* -------------------------------------------------------------------- */
-    nLineStart = (((vsi_l_offset)nBlockXSize) * nBlockYOff * nBits) / 8;
-    iBitOffset = (int)((((vsi_l_offset)nBlockXSize) * nBlockYOff * nBits) % 8);
-    nLineBytes = (int) ((((vsi_l_offset)nBlockXSize) * (nBlockYOff+1) * nBits + 7) / 8 - nLineStart);
+    const vsi_l_offset nLineStart
+        = (static_cast<vsi_l_offset>( nBlockXSize ) * nBlockYOff * nBits) / 8;
+    int iBitOffset = static_cast<int>(
+        ( static_cast<vsi_l_offset>( nBlockXSize ) * nBlockYOff * nBits) % 8 );
+    const unsigned int nLineBytes = static_cast<unsigned int>(
+        ( static_cast<vsi_l_offset>( nBlockXSize ) * (nBlockYOff+1) * nBits + 7)
+        / 8 - nLineStart);
 
 /* -------------------------------------------------------------------- */
 /*      Read data into buffer.                                          */
 /* -------------------------------------------------------------------- */
-    pabyBuffer = (GByte *) CPLCalloc(nLineBytes,1);
+    GByte *pabyBuffer = reinterpret_cast<GByte *>( CPLCalloc( nLineBytes, 1 ) );
 
-    if( VSIFSeekL( poGDS->fpImage, nLineStart, SEEK_SET ) != 0 
+    if( VSIFSeekL( poGDS->fpImage, nLineStart, SEEK_SET ) != 0
         || VSIFReadL( pabyBuffer, 1, nLineBytes, poGDS->fpImage) != nLineBytes )
     {
         CPLError( CE_Failure, CPLE_FileIO,
                   "Failed to read %u bytes at offset %lu.\n%s",
-                  nLineBytes, (unsigned long)nLineStart, 
+                  nLineBytes, (unsigned long)nLineStart,
                   VSIStrerror( errno ) );
+        CPLFree( pabyBuffer );
         return CE_Failure;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Copy data, promoting to 8bit.                                   */
 /* -------------------------------------------------------------------- */
-    int iX;
-
+    GByte *pafImage = reinterpret_cast<GByte *>( pImage );
     if( nBits == 1 )
     {
-        for( iX = 0; iX < nBlockXSize; iX++, iBitOffset += nBits )
+        for( int iX = 0; iX < nBlockXSize; iX++, iBitOffset += nBits )
         {
             if( pabyBuffer[iBitOffset>>3]  & (0x80 >>(iBitOffset & 7)) )
-                ((GByte *) pImage)[iX] = 1;
+                pafImage[iX] = 1;
             else
-                ((GByte *) pImage)[iX] = 0;
+                pafImage[iX] = 0;
         }
     }
     else if( nBits == 2 )
     {
-        for( iX = 0; iX < nBlockXSize; iX++, iBitOffset += nBits )
+        for( int iX = 0; iX < nBlockXSize; iX++, iBitOffset += nBits )
         {
-            ((GByte *) pImage)[iX] =
+            pafImage[iX] =
                 ((pabyBuffer[iBitOffset>>3]) >> (6-(iBitOffset&0x7)) & 0x3);
         }
     }
     else if( nBits == 4 )
     {
-        for( iX = 0; iX < nBlockXSize; iX++, iBitOffset += nBits )
+        for( int iX = 0; iX < nBlockXSize; iX++, iBitOffset += nBits )
         {
             if( iBitOffset == 0 )
-                ((GByte *) pImage)[iX] = (pabyBuffer[iBitOffset>>3]) >> 4;
+                pafImage[iX] = (pabyBuffer[iBitOffset>>3]) >> 4;
             else
-                ((GByte *) pImage)[iX] = (pabyBuffer[iBitOffset>>3]) & 0xf;
+                pafImage[iX] = (pabyBuffer[iBitOffset>>3]) & 0xf;
         }
     }
     else {
@@ -342,18 +339,18 @@ CPLErr GenBinBitRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /*                            GenBinDataset()                             */
 /************************************************************************/
 
-GenBinDataset::GenBinDataset()
+GenBinDataset::GenBinDataset() :
+    fpImage(NULL),
+    bGotTransform(FALSE),
+    pszProjection(CPLStrdup("")),
+    papszHDR(NULL)
 {
-    fpImage = NULL;
-    pszProjection = CPLStrdup("");
-    bGotTransform = FALSE;
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
-    papszHDR = NULL;
 }
 
 /************************************************************************/
@@ -366,7 +363,7 @@ GenBinDataset::~GenBinDataset()
     FlushCache();
 
     if( fpImage != NULL )
-        VSIFCloseL( fpImage );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fpImage ));
 
     CPLFree( pszProjection );
     CSLDestroy( papszHDR );
@@ -397,10 +394,8 @@ CPLErr GenBinDataset::GetGeoTransform( double * padfTransform )
         memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
         return CE_None;
     }
-    else
-    {
-        return GDALPamDataset::GetGeoTransform( padfTransform );
-    }
+
+    return GDALPamDataset::GetGeoTransform( padfTransform );
 }
 
 /************************************************************************/
@@ -410,15 +405,14 @@ CPLErr GenBinDataset::GetGeoTransform( double * padfTransform )
 char **GenBinDataset::GetFileList()
 
 {
-    CPLString osPath = CPLGetPath( GetDescription() );
-    CPLString osName = CPLGetBasename( GetDescription() );
-    char **papszFileList = NULL;
+    const CPLString osPath = CPLGetPath( GetDescription() );
+    const CPLString osName = CPLGetBasename( GetDescription() );
 
-    // Main data file, etc. 
-    papszFileList = GDALPamDataset::GetFileList();
+    // Main data file, etc.
+    char **papszFileList = GDALPamDataset::GetFileList();
 
     // Header file.
-    CPLString osFilename = CPLFormCIFilename( osPath, osName, "hdr" );
+    const CPLString osFilename = CPLFormCIFilename( osPath, osName, "hdr" );
     papszFileList = CSLAddString( papszFileList, osFilename );
 
     return papszFileList;
@@ -432,8 +426,6 @@ void GenBinDataset::ParseCoordinateSystem( char **papszHdr )
 
 {
     const char *pszProjName = CSLFetchNameValue( papszHdr, "PROJECTION_NAME" );
-    OGRSpatialReference oSRS;
-
     if( pszProjName == NULL )
         return;
 
@@ -441,18 +433,15 @@ void GenBinDataset::ParseCoordinateSystem( char **papszHdr )
 /*      Translate zone and parameters into numeric form.                */
 /* -------------------------------------------------------------------- */
     int nZone = 0;
-    double adfProjParms[15];
-    const char *pszUnits = CSLFetchNameValue( papszHdr, "MAP_UNITS" );
-    const char *pszDatumName = CSLFetchNameValue( papszHdr, "DATUM_NAME" );
-
     if( CSLFetchNameValue( papszHdr, "PROJECTION_ZONE" ) )
         nZone = atoi(CSLFetchNameValue( papszHdr, "PROJECTION_ZONE" ));
 
+    double adfProjParms[15];
     memset( adfProjParms, 0, sizeof(adfProjParms) );
     if( CSLFetchNameValue( papszHdr, "PROJECTION_PARAMETERS" ) )
     {
         int i;
-        char **papszTokens = CSLTokenizeString( 
+        char **papszTokens = CSLTokenizeString(
             CSLFetchNameValue( papszHdr, "PROJECTION_PARAMETERS" ) );
 
         for( i = 0; i < 15 && papszTokens[i] != NULL; i++ )
@@ -464,37 +453,39 @@ void GenBinDataset::ParseCoordinateSystem( char **papszHdr )
 /* -------------------------------------------------------------------- */
 /*      Handle projections.                                             */
 /* -------------------------------------------------------------------- */
+    const char *pszDatumName = CSLFetchNameValue( papszHdr, "DATUM_NAME" );
+    OGRSpatialReference oSRS;
+
     if( EQUAL(pszProjName,"UTM") && nZone != 0 )
     {
-        // honestly, I'm just getting that the negative zone for 
+        // honestly, I'm just getting that the negative zone for
         // southern hemisphere is used.
         oSRS.SetUTM( ABS(nZone), nZone > 0 );
     }
 
     else if( EQUAL(pszProjName,"State Plane") && nZone != 0 )
     {
-        int		nPairs = sizeof(anUsgsEsriZones) / (2*sizeof(int));
-        int		i;
-        double          dfUnits = 0.0;
-        
-        for( i = 0; i < nPairs; i++ )
+        const int nPairs = sizeof(anUsgsEsriZones) / (2*sizeof(int));
+
+        for( int i = 0; i < nPairs; i++ )
         {
             if( anUsgsEsriZones[i*2+1] == nZone )
             {
                 nZone = anUsgsEsriZones[i*2];
                 break;
             }
-            
         }
 
+        const char *pszUnits = CSLFetchNameValue( papszHdr, "MAP_UNITS" );
+        double dfUnits = 0.0;
         if( EQUAL(pszUnits,"feet") )
             dfUnits = CPLAtofM(SRS_UL_US_FOOT_CONV);
-        else if( EQUALN(pszUnits,"MET",3) )
+        else if( STARTS_WITH_CI(pszUnits, "MET") )
             dfUnits = 1.0;
         else
             pszUnits = NULL;
 
-        oSRS.SetStatePlane( ABS(nZone), 
+        oSRS.SetStatePlane( ABS(nZone),
                             pszDatumName==NULL || !EQUAL(pszDatumName,"NAD27"),
                             pszUnits, dfUnits );
     }
@@ -504,22 +495,24 @@ void GenBinDataset::ParseCoordinateSystem( char **papszHdr )
 /* -------------------------------------------------------------------- */
     if( oSRS.GetAttrNode( "GEOGCS" ) == NULL )
     {
-        if( pszDatumName != NULL 
+        if( pszDatumName != NULL
             && oSRS.SetWellKnownGeogCS( pszDatumName ) == OGRERR_NONE )
         {
             // good
         }
-        else if( CSLFetchNameValue( papszHdr, "SPHEROID_NAME" ) 
+        else if( CSLFetchNameValue( papszHdr, "SPHEROID_NAME" )
                  && CSLFetchNameValue( papszHdr, "SEMI_MAJOR_AXIS" )
                  && CSLFetchNameValue( papszHdr, "SEMI_MINOR_AXIS" ) )
         {
-            double dfSemiMajor = CPLAtofM(CSLFetchNameValue( papszHdr, "SEMI_MAJOR_AXIS"));
-            double dfSemiMinor = CPLAtofM(CSLFetchNameValue( papszHdr, "SEMI_MINOR_AXIS"));
-            
+            const double dfSemiMajor
+                = CPLAtofM(CSLFetchNameValue( papszHdr, "SEMI_MAJOR_AXIS"));
+            const double dfSemiMinor
+                = CPLAtofM(CSLFetchNameValue( papszHdr, "SEMI_MINOR_AXIS"));
+
             oSRS.SetGeogCS( CSLFetchNameValue( papszHdr, "SPHEROID_NAME" ),
                             CSLFetchNameValue( papszHdr, "SPHEROID_NAME" ),
                             CSLFetchNameValue( papszHdr, "SPHEROID_NAME" ),
-                            dfSemiMajor, 
+                            dfSemiMajor,
                             1.0 / (1.0 - dfSemiMinor/dfSemiMajor) );
         }
         else // fallback default.
@@ -531,7 +524,7 @@ void GenBinDataset::ParseCoordinateSystem( char **papszHdr )
 /* -------------------------------------------------------------------- */
     CPLFree( pszProjection );
     pszProjection = NULL;
-    
+
     oSRS.exportToWkt( &pszProjection );
 }
 
@@ -542,48 +535,42 @@ void GenBinDataset::ParseCoordinateSystem( char **papszHdr )
 GDALDataset *GenBinDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    int		i, bSelectedHDR;
-    
 /* -------------------------------------------------------------------- */
-/*	We assume the user is pointing to the binary (ie. .bil) file.	*/
+/*      We assume the user is pointing to the binary (i.e. .bil) file.  */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->nHeaderBytes < 2 )
         return NULL;
 
 /* -------------------------------------------------------------------- */
-/*      Now we need to tear apart tfhe filename to form a .HDR           */
+/*      Now we need to tear apart the filename to form a .HDR           */
 /*      filename.                                                       */
 /* -------------------------------------------------------------------- */
-    CPLString osPath = CPLGetPath( poOpenInfo->pszFilename );
-    CPLString osName = CPLGetBasename( poOpenInfo->pszFilename );
+    const CPLString osPath = CPLGetPath( poOpenInfo->pszFilename );
+    const CPLString osName = CPLGetBasename( poOpenInfo->pszFilename );
     CPLString osHDRFilename;
 
     char** papszSiblingFiles = poOpenInfo->GetSiblingFiles();
     if( papszSiblingFiles )
     {
-        int iFile = CSLFindString(papszSiblingFiles, 
-                                  CPLFormFilename( NULL, osName, "hdr" ) );
+        const int iFile = CSLFindString(
+            papszSiblingFiles, CPLFormFilename( NULL, osName, "hdr" ) );
         if( iFile < 0 ) // return if there is no corresponding .hdr file
             return NULL;
 
-        osHDRFilename = 
-            CPLFormFilename( osPath, papszSiblingFiles[iFile],
-                             NULL );
+        osHDRFilename =
+            CPLFormFilename( osPath, papszSiblingFiles[iFile], NULL );
     }
     else
     {
         osHDRFilename = CPLFormCIFilename( osPath, osName, "hdr" );
     }
 
-    bSelectedHDR = EQUAL( osHDRFilename, poOpenInfo->pszFilename );
+    const bool bSelectedHDR = EQUAL( osHDRFilename, poOpenInfo->pszFilename );
 
 /* -------------------------------------------------------------------- */
 /*      Do we have a .hdr file?                                         */
 /* -------------------------------------------------------------------- */
-    VSILFILE	*fp;
-
-    fp = VSIFOpenL( osHDRFilename, "r" );
-    
+    VSILFILE *fp = VSIFOpenL( osHDRFilename, "r" );
     if( fp == NULL )
     {
         return NULL;
@@ -593,16 +580,16 @@ GDALDataset *GenBinDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Read a chunk to skim for expected keywords.                     */
 /* -------------------------------------------------------------------- */
     char achHeader[1000];
-    
-    int nRead = VSIFReadL( achHeader, 1, sizeof(achHeader) - 1, fp );
+
+    int nRead = static_cast<int>(VSIFReadL( achHeader, 1, sizeof(achHeader) - 1, fp ));
     achHeader[nRead] = '\0';
-    VSIFSeekL( fp, 0, SEEK_SET );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 0, SEEK_SET ));
 
-    if( strstr( achHeader, "BANDS:" ) == NULL 
-        || strstr( achHeader, "ROWS:" ) == NULL 
+    if( strstr( achHeader, "BANDS:" ) == NULL
+        || strstr( achHeader, "ROWS:" ) == NULL
         || strstr( achHeader, "COLS:" ) == NULL )
     {
-        VSIFCloseL( fp );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
         return NULL;
     }
 
@@ -611,13 +598,13 @@ GDALDataset *GenBinDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( bSelectedHDR )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "The selected file is an Generic Binary header file, but to\n"
                   "open Generic Binary datasets, the data file should be selected\n"
                   "instead of the .hdr file.  Please try again selecting\n"
-                  "the raw data file corresponding to the header file: %s\n", 
+                  "the raw data file corresponding to the header file: %s\n",
                   poOpenInfo->pszFilename );
-        VSIFCloseL( fp );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
         return NULL;
     }
 
@@ -634,7 +621,7 @@ GDALDataset *GenBinDataset::Open( GDALOpenInfo * poOpenInfo )
             CPLString osPP = pszLine;
 
             pszLine = CPLReadLineL(fp);
-            while( pszLine != NULL 
+            while( pszLine != NULL
                    && (*pszLine == '\t' || *pszLine == ' ') )
             {
                 osPP += pszLine;
@@ -645,19 +632,17 @@ GDALDataset *GenBinDataset::Open( GDALOpenInfo * poOpenInfo )
         else
         {
             char *pszName;
-            CPLString osValue;
-            
-            osValue = CPLParseNameValue( pszLine, &pszName );
+            CPLString osValue = CPLParseNameValue( pszLine, &pszName );
             osValue.Trim();
-            
+
             papszHdr = CSLSetNameValue( papszHdr, pszName, osValue );
             CPLFree( pszName );
-            
+
             pszLine = CPLReadLineL( fp );
         }
     }
 
-    VSIFCloseL( fp );
+    CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
 
     if( CSLFetchNameValue( papszHdr, "COLS" ) == NULL
         || CSLFetchNameValue( papszHdr, "ROWS" ) == NULL
@@ -670,14 +655,12 @@ GDALDataset *GenBinDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    GenBinDataset     *poDS;
-
-    poDS = new GenBinDataset();
+    GenBinDataset *poDS = new GenBinDataset();
 
 /* -------------------------------------------------------------------- */
 /*      Capture some information from the file that is of interest.     */
 /* -------------------------------------------------------------------- */
-    int nBands = atoi(CSLFetchNameValue( papszHdr, "BANDS" ));
+    const int nBands = atoi(CSLFetchNameValue( papszHdr, "BANDS" ));
 
     poDS->nRasterXSize = atoi(CSLFetchNameValue( papszHdr, "COLS" ));
     poDS->nRasterYSize = atoi(CSLFetchNameValue( papszHdr, "ROWS" ));
@@ -700,8 +683,8 @@ GDALDataset *GenBinDataset::Open( GDALOpenInfo * poOpenInfo )
 
     if( poDS->fpImage == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Failed to open %s with write permission.\n%s", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to open %s with write permission.\n%s",
                   osName.c_str(), VSIStrerror( errno ) );
         delete poDS;
         return NULL;
@@ -728,7 +711,7 @@ GDALDataset *GenBinDataset::Open( GDALOpenInfo * poOpenInfo )
         eDataType = GDT_Float64;
     else if( EQUAL(pszDataType,"U8") )
         eDataType = GDT_Byte;
-    else if( EQUAL(pszDataType,"U1") 
+    else if( EQUAL(pszDataType,"U1")
              || EQUAL(pszDataType,"U2")
              || EQUAL(pszDataType,"U4") )
     {
@@ -736,7 +719,7 @@ GDALDataset *GenBinDataset::Open( GDALOpenInfo * poOpenInfo )
         eDataType = GDT_Byte;
         if( nBands != 1 )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
+            CPLError( CE_Failure, CPLE_OpenFailed,
                       "Only one band is supported for U1/U2/U4 data type" );
             delete poDS;
             return NULL;
@@ -755,20 +738,20 @@ GDALDataset *GenBinDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     const char *pszBYTE_ORDER = CSLFetchNameValue(papszHdr,"BYTE_ORDER");
     int bNative = TRUE;
-    
+
     if( pszBYTE_ORDER != NULL )
     {
 #ifdef CPL_LSB
-        bNative = EQUALN(pszBYTE_ORDER,"LSB",3);
+        bNative = STARTS_WITH_CI(pszBYTE_ORDER, "LSB");
 #else
-        bNative = !EQUALN(pszBYTE_ORDER,"LSB",3);
-#endif        
+        bNative = !STARTS_WITH_CI(pszBYTE_ORDER, "LSB");
+#endif
     }
 
 /* -------------------------------------------------------------------- */
 /*	Work out interleaving info.					*/
 /* -------------------------------------------------------------------- */
-    int nItemSize = GDALGetDataTypeSize(eDataType)/8;
+    const int nItemSize = GDALGetDataTypeSize(eDataType)/8;
     const char *pszInterleaving = CSLFetchNameValue(papszHdr,"INTERLEAVING");
     int             nPixelOffset, nLineOffset;
     vsi_l_offset    nBandOffset;
@@ -776,13 +759,13 @@ GDALDataset *GenBinDataset::Open( GDALOpenInfo * poOpenInfo )
 
     if( pszInterleaving == NULL )
         pszInterleaving = "BIL";
-    
+
     if( EQUAL(pszInterleaving,"BSQ") || EQUAL(pszInterleaving,"NA") )
     {
         nPixelOffset = nItemSize;
         if (poDS->nRasterXSize > INT_MAX / nItemSize) bIntOverflow = TRUE;
         nLineOffset = nItemSize * poDS->nRasterXSize;
-        nBandOffset = nLineOffset * poDS->nRasterYSize;
+        nBandOffset = nLineOffset * static_cast<vsi_l_offset>(poDS->nRasterYSize);
     }
     else if( EQUAL(pszInterleaving,"BIP") )
     {
@@ -801,14 +784,14 @@ GDALDataset *GenBinDataset::Open( GDALOpenInfo * poOpenInfo )
         nPixelOffset = nItemSize;
         if (poDS->nRasterXSize > INT_MAX / (nPixelOffset * nBands)) bIntOverflow = TRUE;
         nLineOffset = nPixelOffset * nBands * poDS->nRasterXSize;
-        nBandOffset = nItemSize * poDS->nRasterXSize;
+        nBandOffset = nItemSize * static_cast<vsi_l_offset>(poDS->nRasterXSize);
     }
 
     if (bIntOverflow)
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Int overflow occured.");
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Int overflow occurred.");
         return NULL;
     }
 
@@ -819,15 +802,15 @@ GDALDataset *GenBinDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
     poDS->nBands = nBands;
-    for( i = 0; i < poDS->nBands; i++ )
+    for( int i = 0; i < poDS->nBands; i++ )
     {
         if( nBits != -1 )
         {
             poDS->SetBand( i+1, new GenBinBitRasterBand( poDS, nBits ) );
         }
         else
-            poDS->SetBand( 
-                i+1, 
+            poDS->SetBand(
+                i+1,
                 new RawRasterBand( poDS, i+1, poDS->fpImage,
                                    nBandOffset * i, nPixelOffset, nLineOffset,
                                    eDataType, bNative, TRUE ) );
@@ -841,10 +824,10 @@ GDALDataset *GenBinDataset::Open( GDALOpenInfo * poOpenInfo )
         && CSLFetchNameValue(papszHdr,"LR_X_COORDINATE") != NULL
         && CSLFetchNameValue(papszHdr,"LR_Y_COORDINATE") != NULL )
     {
-        double dfULX = CPLAtofM(CSLFetchNameValue(papszHdr,"UL_X_COORDINATE"));
-        double dfULY = CPLAtofM(CSLFetchNameValue(papszHdr,"UL_Y_COORDINATE"));
-        double dfLRX = CPLAtofM(CSLFetchNameValue(papszHdr,"LR_X_COORDINATE"));
-        double dfLRY = CPLAtofM(CSLFetchNameValue(papszHdr,"LR_Y_COORDINATE"));
+        const double dfULX = CPLAtofM(CSLFetchNameValue(papszHdr,"UL_X_COORDINATE"));
+        const double dfULY = CPLAtofM(CSLFetchNameValue(papszHdr,"UL_Y_COORDINATE"));
+        const double dfLRX = CPLAtofM(CSLFetchNameValue(papszHdr,"LR_X_COORDINATE"));
+        const double dfLRY = CPLAtofM(CSLFetchNameValue(papszHdr,"LR_Y_COORDINATE"));
 
         poDS->adfGeoTransform[1] = (dfLRX - dfULX) / (poDS->nRasterXSize-1);
         poDS->adfGeoTransform[2] = 0.0;
@@ -866,7 +849,7 @@ GDALDataset *GenBinDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
     poDS->TryLoadXML();
-    
+
 /* -------------------------------------------------------------------- */
 /*      Check for overviews.                                            */
 /* -------------------------------------------------------------------- */
@@ -876,28 +859,26 @@ GDALDataset *GenBinDataset::Open( GDALOpenInfo * poOpenInfo )
 }
 
 /************************************************************************/
-/*                         GDALRegister_GenBin()                          */
+/*                         GDALRegister_GenBin()                        */
 /************************************************************************/
 
 void GDALRegister_GenBin()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "GenBin" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "GenBin" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "GenBin" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Generic Binary (.hdr Labelled)" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#GenBin" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = GenBinDataset::Open;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "GenBin" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Generic Binary (.hdr Labelled)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_various.html#GenBin" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = GenBinDataset::Open;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/raw/gscdataset.cpp b/frmts/raw/gscdataset.cpp
index 38112f1..f3e540e 100644
--- a/frmts/raw/gscdataset.cpp
+++ b/frmts/raw/gscdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gscdataset.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: gscdataset.cpp 33673 2016-03-07 20:40:54Z goatbar $
  *
  * Project:  GSC Geogrid format driver.
  * Purpose:  Implements support for reading and writing GSC Geogrid format.
@@ -28,10 +28,11 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "rawdataset.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "rawdataset.h"
 
-CPL_CVSID("$Id: gscdataset.cpp 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: gscdataset.cpp 33673 2016-03-07 20:40:54Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -42,7 +43,7 @@ CPL_CVSID("$Id: gscdataset.cpp 27384 2014-05-24 12:28:12Z rouault $");
 class GSCDataset : public RawDataset
 {
     VSILFILE	*fpImage;	// image data file.
-    
+
     double	adfGeoTransform[6];
 
   public:
@@ -50,7 +51,7 @@ class GSCDataset : public RawDataset
     	        ~GSCDataset();
 
     CPLErr 	GetGeoTransform( double * padfTransform );
-    
+
     static GDALDataset *Open( GDALOpenInfo * );
 };
 
@@ -58,7 +59,8 @@ class GSCDataset : public RawDataset
 /*                            GSCDataset()                             */
 /************************************************************************/
 
-GSCDataset::GSCDataset()
+GSCDataset::GSCDataset() :
+    fpImage(NULL)
 {
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
@@ -66,7 +68,6 @@ GSCDataset::GSCDataset()
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
-    fpImage = NULL;
 }
 
 /************************************************************************/
@@ -78,7 +79,7 @@ GSCDataset::~GSCDataset()
 {
     FlushCache();
     if( fpImage != NULL )
-        VSIFCloseL( fpImage );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fpImage ));
 }
 
 /************************************************************************/
@@ -100,7 +101,6 @@ CPLErr GSCDataset::GetGeoTransform( double * padfTransform )
 GDALDataset *GSCDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    int		nPixels, nLines, i, nRecordLen;
 
 /* -------------------------------------------------------------------- */
 /*      Does this plausible look like a GSC Geogrid file?               */
@@ -114,35 +114,36 @@ GDALDataset *GSCDataset::Open( GDALOpenInfo * poOpenInfo )
         || poOpenInfo->pabyHeader[15] != 0x00 )
         return NULL;
 
-    nRecordLen = CPL_LSBWORD32(((GInt32 *) poOpenInfo->pabyHeader)[0]);
-    nPixels = CPL_LSBWORD32(((GInt32 *) poOpenInfo->pabyHeader)[1]);
-    nLines  = CPL_LSBWORD32(((GInt32 *) poOpenInfo->pabyHeader)[2]);
+    int nRecordLen =
+        CPL_LSBWORD32(reinterpret_cast<GInt32 *>( poOpenInfo->pabyHeader)[0] );
+    const int nPixels =
+        CPL_LSBWORD32(reinterpret_cast<GInt32 *>( poOpenInfo->pabyHeader)[1] );
+    const int nLines =
+        CPL_LSBWORD32(reinterpret_cast<GInt32 *>( poOpenInfo->pabyHeader)[2] );
 
     if( nPixels < 1 || nLines < 1 || nPixels > 100000 || nLines > 100000 )
         return NULL;
 
     if( nRecordLen != nPixels * 4 )
         return NULL;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The GSC driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
     }
-    
+
     nRecordLen += 8; /* for record length markers */
 
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    GSCDataset 	*poDS;
-
-    poDS = new GSCDataset();
+    GSCDataset *poDS = new GSCDataset();
 
     poDS->nRasterXSize = nPixels;
     poDS->nRasterYSize = nLines;
@@ -165,14 +166,14 @@ GDALDataset *GSCDataset::Open( GDALOpenInfo * poOpenInfo )
     if( VSIFSeekL( poDS->fpImage, nRecordLen + 12, SEEK_SET ) != 0
         || VSIFReadL( afHeaderInfo, sizeof(float), 8, poDS->fpImage ) != 8 )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   "Failure reading second record of GSC file with %d record length.",
                   nRecordLen );
         delete poDS;
         return NULL;
     }
 
-    for( i = 0; i < 8; i++ )
+    for( int i = 0; i < 8; i++ )
     {
         CPL_LSBPTR32( afHeaderInfo + i );
     }
@@ -183,21 +184,20 @@ GDALDataset *GSCDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->adfGeoTransform[3] = afHeaderInfo[5];
     poDS->adfGeoTransform[4] = 0.0;
     poDS->adfGeoTransform[5] = -afHeaderInfo[1];
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    RawRasterBand *poBand;
 #ifdef CPL_LSB
-    int	bNative = TRUE;
+    const int bNative = TRUE;
 #else
-    int bNative = FALSE;
+    const int bNative = FALSE;
 #endif
 
-    poBand = new RawRasterBand( poDS, 1, poDS->fpImage,
-                                nRecordLen * 2 + 4,
-                                sizeof(float), nRecordLen,
-                                GDT_Float32, bNative, TRUE );
+    RawRasterBand *poBand = new RawRasterBand( poDS, 1, poDS->fpImage,
+                                               nRecordLen * 2 + 4,
+                                               sizeof(float), nRecordLen,
+                                               GDT_Float32, bNative, TRUE );
     poDS->SetBand( 1, poBand );
 
     poBand->SetNoDataValue( -1.0000000150474662199e+30 );
@@ -207,7 +207,7 @@ GDALDataset *GSCDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->TryLoadXML();
-    
+
 /* -------------------------------------------------------------------- */
 /*      Check for overviews.                                            */
 /* -------------------------------------------------------------------- */
@@ -223,23 +223,20 @@ GDALDataset *GSCDataset::Open( GDALOpenInfo * poOpenInfo )
 void GDALRegister_GSC()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "GSC" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "GSC" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "GSC" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "GSC" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
                                    "GSC Geogrid" );
-//        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-//                                   "frmt_various.html#GSC" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    // poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+    //                            "frmt_various.html#GSC" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = GSCDataset::Open;
+    poDriver->pfnOpen = GSCDataset::Open;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
-
diff --git a/frmts/raw/gtxdataset.cpp b/frmts/raw/gtxdataset.cpp
index b0efc30..f6fc736 100644
--- a/frmts/raw/gtxdataset.cpp
+++ b/frmts/raw/gtxdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gtxdataset.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: gtxdataset.cpp 33673 2016-03-07 20:40:54Z goatbar $
  *
  * Project:  Vertical Datum Transformation
  * Purpose:  Implementation of NOAA .gtx vertical datum shift file format.
@@ -28,11 +28,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "rawdataset.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
 #include "ogr_srs_api.h"
+#include "rawdataset.h"
 
-CPL_CVSID("$Id: gtxdataset.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: gtxdataset.cpp 33673 2016-03-07 20:40:54Z goatbar $");
 
 /**
 
@@ -53,7 +54,7 @@ int32    width in pixels
 Data
 ----
 
-float32  * width in pixels * length in pixels 
+float32  * width in pixels * length in pixels
 
 Values are an offset in meters between two vertical datums.
 
@@ -69,13 +70,13 @@ class GTXDataset : public RawDataset
 {
   public:
     VSILFILE	*fpImage;	// image data file.
-    
+
     double      adfGeoTransform[6];
 
   public:
-    		GTXDataset();
+    		GTXDataset() : fpImage(NULL) {}
     	        ~GTXDataset();
-    
+
     virtual CPLErr GetGeoTransform( double * padfTransform );
     virtual CPLErr SetGeoTransform( double * padfTransform );
     virtual const char *GetProjectionRef();
@@ -94,15 +95,6 @@ class GTXDataset : public RawDataset
 /************************************************************************/
 
 /************************************************************************/
-/*                             GTXDataset()                             */
-/************************************************************************/
-
-GTXDataset::GTXDataset()
-{
-    fpImage = NULL;
-}
-
-/************************************************************************/
 /*                            ~GTXDataset()                             */
 /************************************************************************/
 
@@ -112,7 +104,12 @@ GTXDataset::~GTXDataset()
     FlushCache();
 
     if( fpImage != NULL )
-        VSIFCloseL( fpImage );
+    {
+        if( VSIFCloseL( fpImage ) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        }
+    }
 }
 
 /************************************************************************/
@@ -140,13 +137,11 @@ GDALDataset *GTXDataset::Open( GDALOpenInfo * poOpenInfo )
 {
     if( !Identify( poOpenInfo ) )
         return NULL;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    GTXDataset 	*poDS;
-
-    poDS = new GTXDataset();
+    GTXDataset *poDS = new GTXDataset();
 
     poDS->eAccess = poOpenInfo->eAccess;
 
@@ -170,13 +165,13 @@ GDALDataset *GTXDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->adfGeoTransform[2] = 0.0;
     poDS->adfGeoTransform[4] = 0.0;
 
-    VSIFReadL( poDS->adfGeoTransform+3, 8, 1, poDS->fpImage );
-    VSIFReadL( poDS->adfGeoTransform+0, 8, 1, poDS->fpImage );
-    VSIFReadL( poDS->adfGeoTransform+5, 8, 1, poDS->fpImage );
-    VSIFReadL( poDS->adfGeoTransform+1, 8, 1, poDS->fpImage );
+    CPL_IGNORE_RET_VAL(VSIFReadL( poDS->adfGeoTransform+3, 8, 1, poDS->fpImage ));
+    CPL_IGNORE_RET_VAL(VSIFReadL( poDS->adfGeoTransform+0, 8, 1, poDS->fpImage ));
+    CPL_IGNORE_RET_VAL(VSIFReadL( poDS->adfGeoTransform+5, 8, 1, poDS->fpImage ));
+    CPL_IGNORE_RET_VAL(VSIFReadL( poDS->adfGeoTransform+1, 8, 1, poDS->fpImage ));
 
-    VSIFReadL( &(poDS->nRasterYSize), 4, 1, poDS->fpImage );
-    VSIFReadL( &(poDS->nRasterXSize), 4, 1, poDS->fpImage );
+    CPL_IGNORE_RET_VAL(VSIFReadL( &(poDS->nRasterYSize), 4, 1, poDS->fpImage ));
+    CPL_IGNORE_RET_VAL(VSIFReadL( &(poDS->nRasterXSize), 4, 1, poDS->fpImage ));
 
     CPL_MSBPTR32( &(poDS->nRasterYSize) );
     CPL_MSBPTR32( &(poDS->nRasterXSize) );
@@ -186,7 +181,7 @@ GDALDataset *GTXDataset::Open( GDALOpenInfo * poOpenInfo )
     CPL_MSBPTR64( poDS->adfGeoTransform + 3 );
     CPL_MSBPTR64( poDS->adfGeoTransform + 5 );
 
-    poDS->adfGeoTransform[3] += 
+    poDS->adfGeoTransform[3] +=
         poDS->adfGeoTransform[5] * (poDS->nRasterYSize-1);
 
     poDS->adfGeoTransform[0] -= poDS->adfGeoTransform[1] * 0.5;
@@ -204,17 +199,18 @@ GDALDataset *GTXDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Guess the data type. Since October 1, 2009, it should be        */
 /*      Float32. Before it was double.                                  */
 /* -------------------------------------------------------------------- */
+    CPL_IGNORE_RET_VAL(VSIFSeekL(poDS->fpImage, 0, SEEK_END));
+    const vsi_l_offset nSize = VSIFTellL(poDS->fpImage);
+
     GDALDataType eDT = GDT_Float32;
-    VSIFSeekL(poDS->fpImage, 0, SEEK_END);
-    vsi_l_offset nSize = VSIFTellL(poDS->fpImage);
     if( nSize == 40 + 8 * (vsi_l_offset)poDS->nRasterXSize * poDS->nRasterYSize )
         eDT = GDT_Float64;
-    int nDTSize = GDALGetDataTypeSize(eDT) / 8;
+    const int nDTSize = GDALGetDataTypeSize(eDT) / 8;
 
 /* -------------------------------------------------------------------- */
 /*      Create band information object.                                 */
 /* -------------------------------------------------------------------- */
-    RawRasterBand *poBand = new RawRasterBand( poDS, 1, poDS->fpImage, 
+    RawRasterBand *poBand = new RawRasterBand( poDS, 1, poDS->fpImage,
                               (poDS->nRasterYSize-1)*poDS->nRasterXSize*nDTSize + 40,
                               nDTSize, poDS->nRasterXSize * -nDTSize,
                               eDT,
@@ -223,7 +219,7 @@ GDALDataset *GTXDataset::Open( GDALOpenInfo * poOpenInfo )
       poBand->SetNoDataValue( -88.8888 );
     else
       /* GDT_Float32 */
-      poBand->SetNoDataValue( (double)-88.8888f );
+      poBand->SetNoDataValue( -88.8888 );
     poDS->SetBand( 1, poBand );
 
 /* -------------------------------------------------------------------- */
@@ -267,15 +263,12 @@ CPLErr GTXDataset::SetGeoTransform( double * padfTransform )
 
     memcpy( adfGeoTransform, padfTransform, sizeof(double)*6 );
 
-    unsigned char header[32];
-    double dfXOrigin, dfYOrigin, dfWidth, dfHeight;
-
-    dfXOrigin = adfGeoTransform[0] + 0.5 * adfGeoTransform[1];
-    dfYOrigin = adfGeoTransform[3] + (nRasterYSize-0.5) * adfGeoTransform[5];
-    dfWidth = adfGeoTransform[1];
-    dfHeight = - adfGeoTransform[5];
-    
+    const double dfXOrigin = adfGeoTransform[0] + 0.5 * adfGeoTransform[1];
+    const double dfYOrigin = adfGeoTransform[3] + (nRasterYSize-0.5) * adfGeoTransform[5];
+    const double dfWidth = adfGeoTransform[1];
+    const double dfHeight = - adfGeoTransform[5];
 
+    unsigned char header[32];
     memcpy( header + 0, &dfYOrigin, 8 );
     CPL_MSBPTR64( header + 0 );
 
@@ -288,11 +281,11 @@ CPLErr GTXDataset::SetGeoTransform( double * padfTransform )
     memcpy( header + 24, &dfWidth, 8 );
     CPL_MSBPTR64( header + 24 );
 
-    if( VSIFSeekL( fpImage, SEEK_SET, 0 ) != 0 
+    if( VSIFSeekL( fpImage, SEEK_SET, 0 ) != 0
         || VSIFWriteL( header, 32, 1, fpImage ) != 1 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Attempt to write geotrasform header to gtx failed." );
+                  "Attempt to write geotransform header to GTX failed." );
         return CE_Failure;
     }
 
@@ -338,10 +331,7 @@ GDALDataset *GTXDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Try to create the file.                                         */
 /* -------------------------------------------------------------------- */
-    VSILFILE	*fp;
-
-    fp = VSIFOpenL( pszFilename, "wb" );
-
+    VSILFILE *fp = VSIFOpenL( pszFilename, "wb" );
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
@@ -353,31 +343,37 @@ GDALDataset *GTXDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Write out the header with stub georeferencing.                  */
 /* -------------------------------------------------------------------- */
-    unsigned char header[40];
-    double dfXOrigin=0, dfYOrigin=0, dfXSize=0.01, dfYSize=0.01;
-    GInt32 nXSize32 = nXSize, nYSize32 = nYSize;
 
+    unsigned char header[40];
+    double dfYOrigin=0;
     memcpy( header + 0, &dfYOrigin, 8 );
     CPL_MSBPTR64( header + 0 );
 
+    double dfXOrigin=0;
     memcpy( header + 8, &dfXOrigin, 8 );
     CPL_MSBPTR64( header + 8 );
 
+    double dfYSize=0.01;
     memcpy( header + 16, &dfYSize, 8 );
     CPL_MSBPTR64( header + 16 );
 
+    double dfXSize=0.01;
     memcpy( header + 24, &dfXSize, 8 );
     CPL_MSBPTR64( header + 24 );
 
+    GInt32 nYSize32 = nYSize;
     memcpy( header + 32, &nYSize32, 4 );
     CPL_MSBPTR32( header + 32 );
+
+    GInt32 nXSize32 = nXSize;
     memcpy( header + 36, &nXSize32, 4 );
     CPL_MSBPTR32( header + 36 );
 
-    VSIFWriteL( header, 40, 1, fp );
-    VSIFCloseL( fp );
+    CPL_IGNORE_RET_VAL(VSIFWriteL( header, 40, 1, fp ));
+    CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
 
-    return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
+    return reinterpret_cast<GDALDataset *>(
+        GDALOpen( pszFilename, GA_Update ) );
 }
 
 
@@ -388,28 +384,25 @@ GDALDataset *GTXDataset::Create( const char * pszFilename,
 void GDALRegister_GTX()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "GTX" ) != NULL )
+      return;
 
-    if( GDALGetDriverByName( "GTX" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "GTX" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "NOAA Vertical Datum .GTX" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gtx" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-//        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-//                                   "frmt_various.html#GTX" );
-        
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Float32" );
-
-        poDriver->pfnOpen = GTXDataset::Open;
-        poDriver->pfnIdentify = GTXDataset::Identify;
-        poDriver->pfnCreate = GTXDataset::Create;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "GTX" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "NOAA Vertical Datum .GTX" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gtx" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    // poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+    //                            "frmt_various.html#GTX" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Float32" );
+
+    poDriver->pfnOpen = GTXDataset::Open;
+    poDriver->pfnIdentify = GTXDataset::Identify;
+    poDriver->pfnCreate = GTXDataset::Create;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/raw/hkvdataset.cpp b/frmts/raw/hkvdataset.cpp
index 5bb67cd..bf4c11a 100644
--- a/frmts/raw/hkvdataset.cpp
+++ b/frmts/raw/hkvdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hkvdataset.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: hkvdataset.cpp 33712 2016-03-12 10:51:56Z goatbar $
  *
  * Project:  GView
  * Purpose:  Implementation of Atlantis HKV labelled blob support
@@ -28,17 +28,14 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "rawdataset.h"
 #include "cpl_string.h"
 #include <ctype.h>
+#include "gdal_frmts.h"
 #include "ogr_spatialref.h"
+#include "rawdataset.h"
 #include "atlsci_spheroid.h"
 
-CPL_CVSID("$Id: hkvdataset.cpp 28053 2014-12-04 09:31:07Z rouault $");
-
-CPL_C_START
-void	GDALRegister_HKV(void);
-CPL_C_END
+CPL_CVSID("$Id: hkvdataset.cpp 33712 2016-03-12 10:51:56Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -53,11 +50,11 @@ class HKVRasterBand : public RawRasterBand
     friend class HKVDataset;
 
   public:
-    		HKVRasterBand( HKVDataset *poDS, int nBand, VSILFILE * fpRaw, 
+    		HKVRasterBand( HKVDataset *poDS, int nBand, VSILFILE * fpRaw,
                                unsigned int nImgOffset, int nPixelOffset,
                                int nLineOffset,
                                GDALDataType eDataType, int bNativeOrder );
-    virtual     ~HKVRasterBand();
+    virtual     ~HKVRasterBand() {};
 
     virtual CPLErr SetNoDataValue( double );
 };
@@ -68,12 +65,10 @@ class HKVRasterBand : public RawRasterBand
 
 class HKVSpheroidList : public SpheroidList
 {
-
 public:
 
   HKVSpheroidList();
-  ~HKVSpheroidList();
-
+  ~HKVSpheroidList() {};
 };
 
 HKVSpheroidList :: HKVSpheroidList()
@@ -110,7 +105,7 @@ HKVSpheroidList :: HKVSpheroidList()
   spheroids[25].SetValuesByEqRadiusAndInvFlattening("south-american-1969",6378160,298.25);
   spheroids[26].SetValuesByEqRadiusAndInvFlattening("wgs-72",6378135,298.26);
   spheroids[27].SetValuesByEqRadiusAndInvFlattening("wgs-84",6378137,298.257223563);
-  spheroids[28].SetValuesByEqRadiusAndInvFlattening("ev-wgs-84",6378137.0,298.252841); 
+  spheroids[28].SetValuesByEqRadiusAndInvFlattening("ev-wgs-84",6378137.0,298.252841);
   spheroids[29].SetValuesByEqRadiusAndInvFlattening("ev-bessel",6377397.0,299.1976073);
 
   spheroids[30].SetValuesByEqRadiusAndInvFlattening("airy_1830",6377563.396,299.3249646);
@@ -139,14 +134,8 @@ HKVSpheroidList :: HKVSpheroidList()
   spheroids[53].SetValuesByEqRadiusAndInvFlattening("south_american_1969",6378160,298.25);
   spheroids[54].SetValuesByEqRadiusAndInvFlattening("wgs_72",6378135,298.26);
   spheroids[55].SetValuesByEqRadiusAndInvFlattening("wgs_84",6378137,298.257223563);
-  spheroids[56].SetValuesByEqRadiusAndInvFlattening("ev_wgs_84",6378137.0,298.252841); 
+  spheroids[56].SetValuesByEqRadiusAndInvFlattening("ev_wgs_84",6378137.0,298.252841);
   spheroids[57].SetValuesByEqRadiusAndInvFlattening("ev_bessel",6377397.0,299.1976073);
-
-}
-
-HKVSpheroidList::~HKVSpheroidList()
-
-{
 }
 
 CPLErr SaveHKVAttribFile( const char *pszFilenameIn,
@@ -172,14 +161,14 @@ class HKVDataset : public RawDataset
 
     void        ProcessGeoref(const char *);
     void        ProcessGeorefGCP(char **, const char *, double, double);
-  void      SetVersion( float version_number );
-  float      GetVersion();
-  float    MFF2version;
+    void        SetVersion( float version_number );
+    float       GetVersion();
+    float       MFF2version;
 
     CPLErr      SetGCPProjection(const char *); /* for use in CreateCopy */
 
     GDALDataType eRasterType;
- 
+
     void SetNoDataValue( double );
 
     char        *pszProjection;
@@ -190,21 +179,21 @@ class HKVDataset : public RawDataset
 
     int		bGeorefChanged;
     char	**papszGeoref;
-   
+
    /* NOTE: The MFF2 format goes against GDAL's API in that nodata values are set
     *       per-dataset rather than per-band.  To compromise, for writing out, the
     *       dataset's nodata value will be set to the last value set on any of the
     *       raster bands.
     */
- 
+
     int         bNoDataSet;
     int         bNoDataChanged;
     double      dfNoDataValue;
-    
+
   public:
     		HKVDataset();
     virtual     ~HKVDataset();
-    
+
     virtual int    GetGCPCount();
     virtual const char *GetGCPProjection();
     virtual const GDAL_GCP *GetGCPs();
@@ -219,10 +208,10 @@ class HKVDataset : public RawDataset
     static GDALDataset *Create( const char * pszFilename,
                                 int nXSize, int nYSize, int nBands,
                                 GDALDataType eType, char ** papszParmList );
-    static GDALDataset *CreateCopy( const char * pszFilename, 
-                                    GDALDataset *poSrcDS, 
-                                    int bStrict, char ** papszOptions, 
-                                    GDALProgressFunc pfnProgress, 
+    static GDALDataset *CreateCopy( const char * pszFilename,
+                                    GDALDataset *poSrcDS,
+                                    int bStrict, char ** papszOptions,
+                                    GDALProgressFunc pfnProgress,
                                     void * pProgressData );
 
     static CPLErr Delete( const char * pszName );
@@ -238,18 +227,18 @@ class HKVDataset : public RawDataset
 /*                           HKVRasterBand()                            */
 /************************************************************************/
 
-HKVRasterBand::HKVRasterBand( HKVDataset *poDS, int nBand, VSILFILE * fpRaw,
-                              unsigned int nImgOffset, int nPixelOffset,
-                              int nLineOffset,
-                              GDALDataType eDataType, int bNativeOrder )
-        : RawRasterBand( (GDALDataset *) poDS, nBand, 
-                         fpRaw, nImgOffset, nPixelOffset, 
-                         nLineOffset, eDataType, bNativeOrder, TRUE )
+HKVRasterBand::HKVRasterBand( HKVDataset *poDSIn, int nBandIn, VSILFILE * fpRawIn,
+                              unsigned int nImgOffsetIn, int nPixelOffsetIn,
+                              int nLineOffsetIn,
+                              GDALDataType eDataTypeIn, int bNativeOrderIn ) :
+    RawRasterBand( reinterpret_cast<GDALDataset *>( poDSIn ), nBandIn, fpRawIn,
+                   nImgOffsetIn, nPixelOffsetIn, nLineOffsetIn, eDataTypeIn,
+                   bNativeOrderIn, TRUE )
 
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
-    
+    poDS = poDSIn;
+    nBand = nBandIn;
+
     nBlockXSize = poDS->GetRasterXSize();
     nBlockYSize = 1;
 }
@@ -261,23 +250,14 @@ HKVRasterBand::HKVRasterBand( HKVDataset *poDS, int nBand, VSILFILE * fpRaw,
 CPLErr HKVRasterBand::SetNoDataValue( double dfNewValue )
 
 {
-    HKVDataset *poHKVDS = (HKVDataset *) poDS;
-    this->RawRasterBand::SetNoDataValue( dfNewValue );
+    HKVDataset *poHKVDS = reinterpret_cast<HKVDataset *>( poDS );
+    RawRasterBand::SetNoDataValue( dfNewValue );
     poHKVDS->SetNoDataValue( dfNewValue );
 
     return CE_None;
 }
 
 /************************************************************************/
-/*                           ~HKVRasterBand()                           */
-/************************************************************************/
-
-HKVRasterBand::~HKVRasterBand()
-
-{
-}
-
-/************************************************************************/
 /* ==================================================================== */
 /*				HKVDataset				*/
 /* ==================================================================== */
@@ -287,29 +267,29 @@ HKVRasterBand::~HKVRasterBand()
 /*                            HKVDataset()                             */
 /************************************************************************/
 
-HKVDataset::HKVDataset()
+HKVDataset::HKVDataset() :
+    pszPath(NULL),
+    fpBlob(NULL),
+    nGCPCount(0),
+    pasGCPList(NULL),
+    // Initialize datasets to new version; change if necessary.
+    MFF2version(1.1f),
+    eRasterType(GDT_Unknown),
+    pszProjection(CPLStrdup("")),
+    pszGCPProjection(CPLStrdup("")),
+    papszAttrib(NULL),
+    bGeorefChanged(FALSE),
+    papszGeoref(NULL),
+    bNoDataSet(FALSE),
+    bNoDataChanged(FALSE),
+    dfNoDataValue(0.0)
 {
-    pszPath = NULL;
-    papszAttrib = NULL;
-    papszGeoref = NULL;
-    bGeorefChanged = FALSE;
-
-    nGCPCount = 0;
-    pasGCPList = NULL;
-    pszProjection = CPLStrdup("");
-    pszGCPProjection = CPLStrdup("");
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
-
-    bNoDataSet = FALSE;
-    bNoDataChanged = FALSE;
-
-    /* Initialize datasets to new version; change if necessary */
-    MFF2version = (float) 1.1;
 }
 
 /************************************************************************/
@@ -322,28 +302,29 @@ HKVDataset::~HKVDataset()
     FlushCache();
     if( bGeorefChanged )
     {
-        const char	*pszFilename;
-
-        pszFilename = CPLFormFilename(pszPath, "georef", NULL );
-
+        const char *pszFilename = CPLFormFilename(pszPath, "georef", NULL );
         CSLSave( papszGeoref, pszFilename );
     }
 
     if( bNoDataChanged )
     {
-        SaveHKVAttribFile(pszPath, 
+        SaveHKVAttribFile(pszPath,
                              this->nRasterXSize,
                              this->nRasterYSize,
                              this->nBands,
                              this->eRasterType,
-                             this->bNoDataSet, 
+                             this->bNoDataSet,
                              this->dfNoDataValue );
-
     }
 
     if( fpBlob != NULL )
-        VSIFCloseL( fpBlob );
- 
+    {
+        if( VSIFCloseL( fpBlob ) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        }
+    }
+
     if( nGCPCount > 0 )
     {
         GDALDeinitGCPs( nGCPCount, pasGCPList );
@@ -385,10 +366,9 @@ float HKVDataset::GetVersion()
 void HKVDataset::SetNoDataValue( double dfNewValue )
 
 {
-
-    this->bNoDataSet = TRUE;
-    this->bNoDataChanged = TRUE;
-    this->dfNoDataValue = dfNewValue;
+    bNoDataSet = TRUE;
+    bNoDataChanged = TRUE;
+    dfNoDataValue = dfNewValue;
 }
 
 /************************************************************************/
@@ -401,25 +381,21 @@ CPLErr SaveHKVAttribFile( const char *pszFilenameIn,
                                     double dfNoDataValue )
 
 {
+    const char *pszFilename = CPLFormFilename( pszFilenameIn, "attrib", NULL );
 
-    FILE       *fp;
-    const char *pszFilename;
-
-    pszFilename = CPLFormFilename( pszFilenameIn, "attrib", NULL );
-
-    fp = VSIFOpen( pszFilename, "wt" );
+    FILE *fp = VSIFOpen( pszFilename, "wt" );
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "Couldn't create %s.\n", pszFilename );
         return CE_Failure;
     }
-    
+
     fprintf( fp, "channel.enumeration = %d\n", nBands );
     fprintf( fp, "channel.interleave = { *pixel tile sequential }\n" );
     fprintf( fp, "extent.cols = %d\n", nXSize );
     fprintf( fp, "extent.rows = %d\n", nYSize );
-    
+
     switch( eType )
     {
       case GDT_Byte:
@@ -454,7 +430,7 @@ CPLErr SaveHKVAttribFile( const char *pszFilenameIn,
     else
         fprintf( fp, "pixel.field = { *real complex }\n" );
 
-#ifdef CPL_MSB     
+#ifdef CPL_MSB
     fprintf( fp, "pixel.order = { lsbf *msbf }\n" );
 #else
     fprintf( fp, "pixel.order = { *lsbf msbf }\n" );
@@ -466,8 +442,8 @@ CPLErr SaveHKVAttribFile( const char *pszFilenameIn,
     /* version information- only create the new style */
     fprintf( fp, "version = 1.1");
 
-
-    VSIFClose( fp );
+    if( VSIFClose( fp ) != 0 )
+        return CE_Failure;
     return CE_None;
 }
 
@@ -489,7 +465,7 @@ const char *HKVDataset::GetProjectionRef()
 CPLErr HKVDataset::GetGeoTransform( double * padfTransform )
 
 {
-    memcpy( padfTransform,  adfGeoTransform, sizeof(double) * 6 ); 
+    memcpy( padfTransform,  adfGeoTransform, sizeof(double) * 6 );
     return( CE_None );
 }
 
@@ -500,17 +476,15 @@ CPLErr HKVDataset::GetGeoTransform( double * padfTransform )
 CPLErr HKVDataset::SetGeoTransform( double * padfTransform )
 
 {
-    char	szValue[128];
-
     /* NOTE:  Geotransform coordinates must match the current projection   */
     /* of the dataset being changed (not the geotransform source).         */
-    /* ie. be in lat/longs for LL projected; UTM for UTM projected.        */
+    /* i.e. be in lat/longs for LL projected; UTM for UTM projected.       */
     /* SET PROJECTION BEFORE SETTING GEOTRANSFORM TO AVOID SYNCHRONIZATION */
     /* PROBLEMS!                                                           */
 
     /* Update the geotransform itself */
     memcpy( adfGeoTransform, padfTransform, sizeof(double)*6 );
- 
+
     /* Clear previous gcps */
     if( nGCPCount > 0 )
     {
@@ -528,31 +502,29 @@ CPLErr HKVDataset::SetGeoTransform( double * padfTransform )
 
     /* Update georef text info for saving later, and */
     /* update GCPs to match geotransform.            */
-    
-    double temp_lat, temp_long;
-    OGRSpatialReference oUTM;
-    OGRSpatialReference oLL;
+
     OGRCoordinateTransformation *poTransform = NULL;
-    int bSuccess=TRUE;
-    char *pszPtemp;
-    char *pszGCPtemp;
+    int bSuccess = true;
 
     /* Projection parameter checking will have been done */
     /* in SetProjection.                                 */
     if(( CSLFetchNameValue( papszGeoref, "projection.name" ) != NULL ) &&
        ( EQUAL(CSLFetchNameValue( papszGeoref, "projection.name" ),"UTM" )))
-
     {
         /* pass copies of projection info, not originals (pointers */
         /* get updated by importFromWkt)                           */
-        pszPtemp = CPLStrdup(pszProjection);
+        char *pszPtemp = CPLStrdup(pszProjection);
+        OGRSpatialReference oUTM;
         oUTM.importFromWkt(&pszPtemp);
+    char *pszGCPtemp;
         (oUTM.GetAttrNode("GEOGCS"))->exportToWkt(&pszGCPtemp);
+
+        OGRSpatialReference oLL;
         oLL.importFromWkt(&pszGCPtemp);
         poTransform = OGRCreateCoordinateTransformation( &oUTM, &oLL );
         if( poTransform == NULL )
         {
-            bSuccess = FALSE;
+            bSuccess = false;
             CPLErrorReset();
         }
     }
@@ -564,15 +536,16 @@ CPLErr HKVDataset::SetGeoTransform( double * padfTransform )
     }
 
     nGCPCount = 0;
-    pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),5);
+    pasGCPList = reinterpret_cast<GDAL_GCP *>( CPLCalloc( sizeof(GDAL_GCP), 5 ) );
 
     /* -------------------------------------------------------------------- */
     /*      top left                                                        */
     /* -------------------------------------------------------------------- */
-    GDALInitGCPs( 1, pasGCPList + nGCPCount );            
+    GDALInitGCPs( 1, pasGCPList + nGCPCount );
     CPLFree( pasGCPList[nGCPCount].pszId );
     pasGCPList[nGCPCount].pszId = CPLStrdup( "top_left" );
 
+    double temp_lat, temp_long;
     if (MFF2version > 1.0)
     {
         temp_lat = padfTransform[3];
@@ -595,24 +568,25 @@ CPLErr HKVDataset::SetGeoTransform( double * padfTransform )
     if (poTransform != NULL)
     {
         if( !bSuccess || !poTransform->Transform( 1, &temp_long, &temp_lat ) )
-            bSuccess = FALSE;
+            bSuccess = false;
     }
 
     if (bSuccess)
     {
-        CPLsprintf( szValue, "%.10f", temp_lat );
-        papszGeoref = CSLSetNameValue( papszGeoref, "top_left.latitude", 
+        char szValue[128];
+        CPLsnprintf( szValue, sizeof(szValue), "%.10f", temp_lat );
+        papszGeoref = CSLSetNameValue( papszGeoref, "top_left.latitude",
                                        szValue );
 
-        CPLsprintf( szValue, "%.10f", temp_long );
-        papszGeoref = CSLSetNameValue( papszGeoref, "top_left.longitude", 
+        CPLsnprintf( szValue, sizeof(szValue), "%.10f", temp_long );
+        papszGeoref = CSLSetNameValue( papszGeoref, "top_left.longitude",
                                        szValue );
     }
 
     /* -------------------------------------------------------------------- */
     /*      top_right                                                       */
     /* -------------------------------------------------------------------- */
-    GDALInitGCPs( 1, pasGCPList + nGCPCount );            
+    GDALInitGCPs( 1, pasGCPList + nGCPCount );
     CPLFree( pasGCPList[nGCPCount].pszId );
     pasGCPList[nGCPCount].pszId = CPLStrdup( "top_right" );
 
@@ -634,28 +608,29 @@ CPLErr HKVDataset::SetGeoTransform( double * padfTransform )
     pasGCPList[nGCPCount].dfGCPY = temp_lat;
     pasGCPList[nGCPCount].dfGCPZ = 0.0;
     nGCPCount++;
-    
+
     if (poTransform != NULL)
     {
         if( !bSuccess || !poTransform->Transform( 1, &temp_long, &temp_lat ) )
-            bSuccess = FALSE;
+            bSuccess = false;
     }
 
     if (bSuccess)
     {
-        CPLsprintf( szValue, "%.10f", temp_lat );
-        papszGeoref = CSLSetNameValue( papszGeoref, "top_right.latitude", 
+        char szValue[128];
+        CPLsnprintf( szValue, sizeof(szValue), "%.10f", temp_lat );
+        papszGeoref = CSLSetNameValue( papszGeoref, "top_right.latitude",
                                        szValue );
 
-        CPLsprintf( szValue, "%.10f", temp_long );
-        papszGeoref = CSLSetNameValue( papszGeoref, "top_right.longitude", 
+        CPLsnprintf( szValue, sizeof(szValue), "%.10f", temp_long );
+        papszGeoref = CSLSetNameValue( papszGeoref, "top_right.longitude",
                                        szValue );
     }
 
     /* -------------------------------------------------------------------- */
     /*      bottom_left                                                     */
     /* -------------------------------------------------------------------- */
-    GDALInitGCPs( 1, pasGCPList + nGCPCount );            
+    GDALInitGCPs( 1, pasGCPList + nGCPCount );
     CPLFree( pasGCPList[nGCPCount].pszId );
     pasGCPList[nGCPCount].pszId = CPLStrdup( "bottom_left" );
 
@@ -686,37 +661,37 @@ CPLErr HKVDataset::SetGeoTransform( double * padfTransform )
 
     if (bSuccess)
     {
-        CPLsprintf( szValue, "%.10f", temp_lat );
-        papszGeoref = CSLSetNameValue( papszGeoref, "bottom_left.latitude", 
+        char szValue[128];
+        CPLsnprintf( szValue, sizeof(szValue), "%.10f", temp_lat );
+        papszGeoref = CSLSetNameValue( papszGeoref, "bottom_left.latitude",
                                        szValue );
 
-        CPLsprintf( szValue, "%.10f", temp_long );
-        papszGeoref = CSLSetNameValue( papszGeoref, "bottom_left.longitude", 
+        CPLsnprintf( szValue, sizeof(szValue), "%.10f", temp_long );
+        papszGeoref = CSLSetNameValue( papszGeoref, "bottom_left.longitude",
                                        szValue );
     }
 
     /* -------------------------------------------------------------------- */
     /*      bottom_right                                                    */
     /* -------------------------------------------------------------------- */
-    GDALInitGCPs( 1, pasGCPList + nGCPCount );            
+    GDALInitGCPs( 1, pasGCPList + nGCPCount );
     CPLFree( pasGCPList[nGCPCount].pszId );
     pasGCPList[nGCPCount].pszId = CPLStrdup( "bottom_right" );
 
     if (MFF2version > 1.0)
     {
-        temp_lat = padfTransform[3] + GetRasterXSize() * padfTransform[4] + 
+        temp_lat = padfTransform[3] + GetRasterXSize() * padfTransform[4] +
           GetRasterYSize() * padfTransform[5];
-        temp_long = padfTransform[0] + GetRasterXSize() * padfTransform[1] + 
+        temp_long = padfTransform[0] + GetRasterXSize() * padfTransform[1] +
           GetRasterYSize() * padfTransform[2];
         pasGCPList[nGCPCount].dfGCPPixel = GetRasterXSize();
         pasGCPList[nGCPCount].dfGCPLine = GetRasterYSize();
-
     }
     else
     {
-        temp_lat = padfTransform[3] + (GetRasterXSize()-0.5) * padfTransform[4] + 
+        temp_lat = padfTransform[3] + (GetRasterXSize()-0.5) * padfTransform[4] +
           (GetRasterYSize()-0.5) * padfTransform[5];
-        temp_long = padfTransform[0] + (GetRasterXSize()-0.5) * padfTransform[1] + 
+        temp_long = padfTransform[0] + (GetRasterXSize()-0.5) * padfTransform[1] +
           (GetRasterYSize()-0.5) * padfTransform[2];
         pasGCPList[nGCPCount].dfGCPPixel = GetRasterXSize()-0.5;
         pasGCPList[nGCPCount].dfGCPLine = GetRasterYSize()-0.5;
@@ -734,40 +709,30 @@ CPLErr HKVDataset::SetGeoTransform( double * padfTransform )
 
     if (bSuccess)
     {
-        CPLsprintf( szValue, "%.10f", temp_lat );
-        papszGeoref = CSLSetNameValue( papszGeoref, "bottom_right.latitude", 
+        char szValue[128];
+        CPLsnprintf( szValue, sizeof(szValue), "%.10f", temp_lat );
+        papszGeoref = CSLSetNameValue( papszGeoref, "bottom_right.latitude",
                                        szValue );
 
-        CPLsprintf( szValue, "%.10f", temp_long );
-        papszGeoref = CSLSetNameValue( papszGeoref, "bottom_right.longitude", 
+        CPLsnprintf( szValue, sizeof(szValue), "%.10f", temp_long );
+        papszGeoref = CSLSetNameValue( papszGeoref, "bottom_right.longitude",
                                        szValue );
     }
 
     /* -------------------------------------------------------------------- */
     /*      Center                                                          */
     /* -------------------------------------------------------------------- */
-    GDALInitGCPs( 1, pasGCPList + nGCPCount );            
+    GDALInitGCPs( 1, pasGCPList + nGCPCount );
     CPLFree( pasGCPList[nGCPCount].pszId );
     pasGCPList[nGCPCount].pszId = CPLStrdup( "centre" );
 
-    if (MFF2version > 1.0)
-    {
-        temp_lat = padfTransform[3] + GetRasterXSize() * padfTransform[4] * 0.5 +
-          GetRasterYSize() * padfTransform[5] * 0.5;
-        temp_long = padfTransform[0] + GetRasterXSize() * padfTransform[1] * 0.5 +
-                 GetRasterYSize() * padfTransform[2] * 0.5; 
-        pasGCPList[nGCPCount].dfGCPPixel = GetRasterXSize()/2.0;
-        pasGCPList[nGCPCount].dfGCPLine = GetRasterYSize()/2.0;
-    }
-    else
-    {
-        temp_lat = padfTransform[3] + GetRasterXSize() * padfTransform[4] * 0.5 +
-          GetRasterYSize() * padfTransform[5] * 0.5;
-        temp_long = padfTransform[0] + GetRasterXSize() * padfTransform[1] * 0.5 +
-                 GetRasterYSize() * padfTransform[2] * 0.5; 
-        pasGCPList[nGCPCount].dfGCPPixel = GetRasterXSize()/2.0;
-        pasGCPList[nGCPCount].dfGCPLine = GetRasterYSize()/2.0;
-    }
+    temp_lat = padfTransform[3] + GetRasterXSize() * padfTransform[4] * 0.5 +
+      GetRasterYSize() * padfTransform[5] * 0.5;
+    temp_long = padfTransform[0] + GetRasterXSize() * padfTransform[1] * 0.5 +
+             GetRasterYSize() * padfTransform[2] * 0.5;
+    pasGCPList[nGCPCount].dfGCPPixel = GetRasterXSize()/2.0;
+    pasGCPList[nGCPCount].dfGCPLine = GetRasterYSize()/2.0;
+
     pasGCPList[nGCPCount].dfGCPX = temp_long;
     pasGCPList[nGCPCount].dfGCPY = temp_lat;
     pasGCPList[nGCPCount].dfGCPZ = 0.0;
@@ -781,26 +746,25 @@ CPLErr HKVDataset::SetGeoTransform( double * padfTransform )
 
     if (bSuccess)
     {
-        CPLsprintf( szValue, "%.10f", temp_lat );
-        papszGeoref = CSLSetNameValue( papszGeoref, "centre.latitude", 
+        char szValue[128];
+        CPLsnprintf( szValue, sizeof(szValue), "%.10f", temp_lat );
+        papszGeoref = CSLSetNameValue( papszGeoref, "centre.latitude",
                                        szValue );
 
-        CPLsprintf( szValue, "%.10f", temp_long );
-        papszGeoref = CSLSetNameValue( papszGeoref, "centre.longitude", 
+        CPLsnprintf( szValue, sizeof(szValue), "%.10f", temp_long );
+        papszGeoref = CSLSetNameValue( papszGeoref, "centre.longitude",
                                        szValue );
     }
-    
+
     if (!bSuccess)
     {
       CPLError(CE_Warning,CPLE_AppDefined,
-               "Warning- error setting header info in SetGeoTransform. Changes may not be saved properly.\n"); 
+               "Warning- error setting header info in SetGeoTransform. Changes may not be saved properly.\n");
     }
-     
+
     if (poTransform != NULL)
         delete poTransform;
 
-
-
     bGeorefChanged = TRUE;
 
     return( CE_None );
@@ -808,7 +772,6 @@ CPLErr HKVDataset::SetGeoTransform( double * padfTransform )
 
 CPLErr HKVDataset::SetGCPProjection( const char *pszNewProjection )
 {
-    
     CPLFree( pszGCPProjection );
     this->pszGCPProjection = CPLStrdup(pszNewProjection);
 
@@ -824,53 +787,42 @@ CPLErr HKVDataset::SetGCPProjection( const char *pszNewProjection )
 CPLErr HKVDataset::SetProjection( const char * pszNewProjection )
 
 {
-    HKVSpheroidList *hkvEllipsoids;
-    double eq_radius, inv_flattening;
-    OGRErr ogrerrorEq=OGRERR_NONE;
-    OGRErr ogrerrorInvf=OGRERR_NONE;
-    OGRErr ogrerrorOl=OGRERR_NONE;
-
-    char *spheroid_name = NULL;
-
     /* This function is used to update a georef file */
 
+#ifdef DEBUG_VERBOSE
+    printf( "HKVDataset::SetProjection(%s)\n", pszNewProjection );
+#endif
 
-    /* printf( "HKVDataset::SetProjection(%s)\n", pszNewProjection ); */
-
-    if( !EQUALN(pszNewProjection,"GEOGCS",6)
-        && !EQUALN(pszNewProjection,"PROJCS",6)
+    if( !STARTS_WITH_CI(pszNewProjection, "GEOGCS")
+        && !STARTS_WITH_CI(pszNewProjection, "PROJCS")
         && !EQUAL(pszNewProjection,"") )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                 "Only OGC WKT Projections supported for writing to HKV.\n"
                 "%s not supported.",
                   pszNewProjection );
-        
+
         return CE_Failure;
     }
     else if (EQUAL(pszNewProjection,""))
     {
       CPLFree( pszProjection );
-      pszProjection = (char *) CPLStrdup(pszNewProjection); 
+      pszProjection = reinterpret_cast<char *>( CPLStrdup( pszNewProjection ) );
 
       return CE_None;
     }
     CPLFree( pszProjection );
-    pszProjection = (char *) CPLStrdup(pszNewProjection);
-   
+    pszProjection = reinterpret_cast<char *>( CPLStrdup( pszNewProjection ) );
 
     OGRSpatialReference oSRS(pszNewProjection);
 
-    if ((oSRS.GetAttrValue("PROJECTION") != NULL) && 
+    if ((oSRS.GetAttrValue("PROJECTION") != NULL) &&
         (EQUAL(oSRS.GetAttrValue("PROJECTION"),SRS_PT_TRANSVERSE_MERCATOR)))
     {
-      char *ol_txt;
-        ol_txt=(char *) CPLMalloc(255);
         papszGeoref = CSLSetNameValue( papszGeoref, "projection.name", "utm" );
-        CPLsprintf(ol_txt,"%f",oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0,&ogrerrorOl));
+        OGRErr ogrerrorOl = OGRERR_NONE;
         papszGeoref = CSLSetNameValue( papszGeoref, "projection.origin_longitude",
-        ol_txt );
-        CPLFree(ol_txt);
+                        CPLSPrintf("%f",oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0,&ogrerrorOl)));
     }
     else if ((oSRS.GetAttrValue("PROJECTION") == NULL) && (oSRS.IsGeographic()))
     {
@@ -882,15 +834,22 @@ CPLErr HKVDataset::SetProjection( const char * pszNewProjection )
                 "Unrecognized projection.");
       return CE_Failure;
     }
-    eq_radius = oSRS.GetSemiMajor(&ogrerrorEq);
-    inv_flattening = oSRS.GetInvFlattening(&ogrerrorInvf);
-    if ((ogrerrorEq == OGRERR_NONE) && (ogrerrorInvf == OGRERR_NONE)) 
+
+    OGRErr ogrerrorEq = OGRERR_NONE;
+    const double eq_radius = oSRS.GetSemiMajor(&ogrerrorEq);
+
+    OGRErr ogrerrorInvf = OGRERR_NONE;
+    const double inv_flattening = oSRS.GetInvFlattening(&ogrerrorInvf);
+
+    if ((ogrerrorEq == OGRERR_NONE) && (ogrerrorInvf == OGRERR_NONE))
     {
-        hkvEllipsoids = new HKVSpheroidList;
-        spheroid_name = hkvEllipsoids->GetSpheroidNameByEqRadiusAndInvFlattening(eq_radius,inv_flattening);
+        HKVSpheroidList *hkvEllipsoids = new HKVSpheroidList;
+        char *spheroid_name =
+            hkvEllipsoids->GetSpheroidNameByEqRadiusAndInvFlattening(
+                eq_radius, inv_flattening);
         if (spheroid_name != NULL)
         {
-            papszGeoref = CSLSetNameValue( papszGeoref, "spheroid.name", 
+            papszGeoref = CSLSetNameValue( papszGeoref, "spheroid.name",
                                            spheroid_name );
         }
         CPLFree(spheroid_name);
@@ -903,14 +862,14 @@ CPLErr HKVDataset::SetProjection( const char * pszNewProjection )
 
         if( strstr(pszNewProjection,"Bessel") != NULL )
         {
-            papszGeoref = CSLSetNameValue( papszGeoref, "spheroid.name", 
+            papszGeoref = CSLSetNameValue( papszGeoref, "spheroid.name",
                                        "ev-bessel" );
         }
         else
         {
-            papszGeoref = CSLSetNameValue( papszGeoref, "spheroid.name", 
+            papszGeoref = CSLSetNameValue( papszGeoref, "spheroid.name",
                                        "ev-wgs-84" );
-        }                                   
+        }
     }
     bGeorefChanged = TRUE;
     return CE_None;
@@ -950,37 +909,37 @@ const GDAL_GCP *HKVDataset::GetGCPs()
 /*                          ProcessGeorefGCP()                          */
 /************************************************************************/
 
-void HKVDataset::ProcessGeorefGCP( char **papszGeoref, const char *pszBase,
+void HKVDataset::ProcessGeorefGCP( char **papszGeorefIn, const char *pszBase,
                                    double dfRasterX, double dfRasterY )
 
 {
-    char      szFieldName[128];
-    double    dfLat, dfLong;
-
 /* -------------------------------------------------------------------- */
 /*      Fetch the GCP from the string list.                             */
 /* -------------------------------------------------------------------- */
-    sprintf( szFieldName, "%s.latitude", pszBase );
-    if( CSLFetchNameValue(papszGeoref, szFieldName) == NULL )
+    char szFieldName[128];
+    snprintf( szFieldName, sizeof(szFieldName), "%s.latitude", pszBase );
+    double dfLat;
+    if( CSLFetchNameValue(papszGeorefIn, szFieldName) == NULL )
         return;
     else
-        dfLat = CPLAtof(CSLFetchNameValue(papszGeoref, szFieldName));
+        dfLat = CPLAtof(CSLFetchNameValue(papszGeorefIn, szFieldName));
 
-    sprintf( szFieldName, "%s.longitude", pszBase );
-    if( CSLFetchNameValue(papszGeoref, szFieldName) == NULL )
+    snprintf( szFieldName, sizeof(szFieldName), "%s.longitude", pszBase );
+    double dfLong;
+    if( CSLFetchNameValue(papszGeorefIn, szFieldName) == NULL )
         return;
     else
-        dfLong = CPLAtof(CSLFetchNameValue(papszGeoref, szFieldName));
+        dfLong = CPLAtof(CSLFetchNameValue(papszGeorefIn, szFieldName));
 
 /* -------------------------------------------------------------------- */
 /*      Add the gcp to the internal list.                               */
 /* -------------------------------------------------------------------- */
     GDALInitGCPs( 1, pasGCPList + nGCPCount );
-            
+
     CPLFree( pasGCPList[nGCPCount].pszId );
 
     pasGCPList[nGCPCount].pszId = CPLStrdup( pszBase );
-                
+
     pasGCPList[nGCPCount].dfGCPX = dfLong;
     pasGCPList[nGCPCount].dfGCPY = dfLat;
     pasGCPList[nGCPCount].dfGCPZ = 0.0;
@@ -998,9 +957,6 @@ void HKVDataset::ProcessGeorefGCP( char **papszGeoref, const char *pszBase,
 void HKVDataset::ProcessGeoref( const char * pszFilename )
 
 {
-    int   i;
-    HKVSpheroidList *hkvEllipsoids = NULL;
-
 /* -------------------------------------------------------------------- */
 /*      Load the georef file, and boil white space away from around     */
 /*      the equal sign.                                                 */
@@ -1010,23 +966,19 @@ void HKVDataset::ProcessGeoref( const char * pszFilename )
     if( papszGeoref == NULL )
         return;
 
-    hkvEllipsoids = new HKVSpheroidList;
+    HKVSpheroidList *hkvEllipsoids = new HKVSpheroidList;
 
-    for( i = 0; papszGeoref[i] != NULL; i++ )
+    for( int i = 0; papszGeoref[i] != NULL; i++ )
     {
-        int       bAfterEqual = FALSE;
-        int       iSrc, iDst;
+        int iDst = 0;
         char     *pszLine = papszGeoref[i];
 
-        for( iSrc=0, iDst=0; pszLine[iSrc] != '\0'; iSrc++ )
+        for( int iSrc = 0; pszLine[iSrc] != '\0'; iSrc++ )
         {
-            if( bAfterEqual || pszLine[iSrc] != ' ' )
+            if( pszLine[iSrc] != ' ' )
             {
                 pszLine[iDst++] = pszLine[iSrc];
             }
-
-            if( iDst > 0 && pszLine[iDst-1] == '=' )
-                bAfterEqual = FALSE;
         }
         pszLine[iDst] = '\0';
     }
@@ -1035,32 +987,32 @@ void HKVDataset::ProcessGeoref( const char * pszFilename )
 /*      Try to get GCPs, in lat/longs                     .             */
 /* -------------------------------------------------------------------- */
     nGCPCount = 0;
-    pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),5);
+    pasGCPList = reinterpret_cast<GDAL_GCP *>( CPLCalloc( sizeof(GDAL_GCP), 5) );
 
     if (MFF2version > 1.0)
     {
-        ProcessGeorefGCP( papszGeoref, "top_left", 
+        ProcessGeorefGCP( papszGeoref, "top_left",
                           0, 0 );
-        ProcessGeorefGCP( papszGeoref, "top_right", 
+        ProcessGeorefGCP( papszGeoref, "top_right",
                           GetRasterXSize(), 0 );
-        ProcessGeorefGCP( papszGeoref, "bottom_left", 
+        ProcessGeorefGCP( papszGeoref, "bottom_left",
                           0, GetRasterYSize() );
-        ProcessGeorefGCP( papszGeoref, "bottom_right", 
+        ProcessGeorefGCP( papszGeoref, "bottom_right",
                           GetRasterXSize(), GetRasterYSize() );
-        ProcessGeorefGCP( papszGeoref, "centre", 
+        ProcessGeorefGCP( papszGeoref, "centre",
                           GetRasterXSize()/2.0, GetRasterYSize()/2.0 );
     }
     else
     {
-        ProcessGeorefGCP( papszGeoref, "top_left", 
+        ProcessGeorefGCP( papszGeoref, "top_left",
                           0.5, 0.5 );
-        ProcessGeorefGCP( papszGeoref, "top_right", 
+        ProcessGeorefGCP( papszGeoref, "top_right",
                           GetRasterXSize()-0.5, 0.5 );
-        ProcessGeorefGCP( papszGeoref, "bottom_left", 
+        ProcessGeorefGCP( papszGeoref, "bottom_left",
                           0.5, GetRasterYSize()-0.5 );
-        ProcessGeorefGCP( papszGeoref, "bottom_right", 
+        ProcessGeorefGCP( papszGeoref, "bottom_right",
                           GetRasterXSize()-0.5, GetRasterYSize()-0.5 );
-        ProcessGeorefGCP( papszGeoref, "centre", 
+        ProcessGeorefGCP( papszGeoref, "centre",
                           GetRasterXSize()/2.0, GetRasterYSize()/2.0 );
     }
 
@@ -1073,15 +1025,12 @@ void HKVDataset::ProcessGeoref( const char * pszFilename )
 /* -------------------------------------------------------------------- */
 /*      Do we have a recognised projection?                             */
 /* -------------------------------------------------------------------- */
-    const char *pszProjName, *pszOriginLong, *pszSpheroidName;
     /* double eq_radius, inv_flattening; */
 
-    pszProjName = CSLFetchNameValue(papszGeoref,
-                                    "projection.name");
-    pszOriginLong = CSLFetchNameValue(papszGeoref, 
-                                      "projection.origin_longitude");
-    pszSpheroidName = CSLFetchNameValue(papszGeoref, 
-                                      "spheroid.name");
+    const char *pszProjName = CSLFetchNameValue(papszGeoref, "projection.name");
+    const char *pszOriginLong = CSLFetchNameValue(
+        papszGeoref, "projection.origin_longitude");
+    const char *pszSpheroidName = CSLFetchNameValue(papszGeoref, "spheroid.name");
 
 
     if ((pszSpheroidName != NULL) && (hkvEllipsoids->SpheroidInList(pszSpheroidName)))
@@ -1109,21 +1058,16 @@ void HKVDataset::ProcessGeoref( const char * pszFilename )
             nZone = 31;
         }
         else
-            nZone = 31 + (int) floor(CPLAtof(pszOriginLong)/6.0);
+            nZone = 31 + static_cast<int>( floor( CPLAtof( pszOriginLong ) / 6.0) );
 
         OGRSpatialReference oUTM;
-        OGRSpatialReference oLL;
-        OGRCoordinateTransformation *poTransform = NULL;
-        double dfUtmX[5], dfUtmY[5]; 
-        int gcp_index;
-
-        int    bSuccess = TRUE;
 
         if( pasGCPList[4].dfGCPY < 0 )
             oUTM.SetUTM( nZone, 0 );
         else
             oUTM.SetUTM( nZone, 1 );
-     
+
+        OGRSpatialReference oLL;
         if (pszOriginLong != NULL)
         {
             oUTM.SetProjParm(SRS_PP_CENTRAL_MERIDIAN,CPLAtof(pszOriginLong));
@@ -1139,13 +1083,13 @@ void HKVDataset::ProcessGeoref( const char * pszFilename )
         else
         {
           if (hkvEllipsoids->SpheroidInList(pszSpheroidName))
-          { 
+          {
             oUTM.SetGeogCS( "unknown","unknown",pszSpheroidName,
-                            hkvEllipsoids->GetSpheroidEqRadius(pszSpheroidName), 
+                            hkvEllipsoids->GetSpheroidEqRadius(pszSpheroidName),
                             hkvEllipsoids->GetSpheroidInverseFlattening(pszSpheroidName)
                           );
             oLL.SetGeogCS( "unknown","unknown",pszSpheroidName,
-                            hkvEllipsoids->GetSpheroidEqRadius(pszSpheroidName), 
+                            hkvEllipsoids->GetSpheroidEqRadius(pszSpheroidName),
                             hkvEllipsoids->GetSpheroidInverseFlattening(pszSpheroidName)
                            );
           }
@@ -1155,31 +1099,33 @@ void HKVDataset::ProcessGeoref( const char * pszFilename )
             oUTM.SetWellKnownGeogCS( "WGS84" );
             oLL.SetWellKnownGeogCS( "WGS84" );
           }
-        }  
-  
-        poTransform = OGRCreateCoordinateTransformation( &oLL, &oUTM );
+        }
+
+        OGRCoordinateTransformation *poTransform
+            = OGRCreateCoordinateTransformation( &oLL, &oUTM );
+
+        bool bSuccess = true;
         if( poTransform == NULL )
         {
             CPLErrorReset();
-            bSuccess = FALSE;
+            bSuccess = false;
         }
 
-        for(gcp_index=0;gcp_index<5;gcp_index++)
+        double dfUtmX[5], dfUtmY[5];
+
+        for( int gcp_index=0;gcp_index<5;gcp_index++ )
         {
             dfUtmX[gcp_index] = pasGCPList[gcp_index].dfGCPX;
             dfUtmY[gcp_index] = pasGCPList[gcp_index].dfGCPY;
 
             if( bSuccess && !poTransform->Transform( 1, &(dfUtmX[gcp_index]), &(dfUtmY[gcp_index]) ) )
-                bSuccess = FALSE;
- 
+                bSuccess = false;
         }
 
         if( bSuccess )
         {
-            int transform_ok = FALSE;
-
             /* update GCPS to proper projection */
-            for(gcp_index=0;gcp_index<5;gcp_index++)
+            for( int gcp_index = 0; gcp_index < 5; gcp_index++ )
             {
                 pasGCPList[gcp_index].dfGCPX = dfUtmX[gcp_index];
                 pasGCPList[gcp_index].dfGCPY = dfUtmY[gcp_index];
@@ -1188,8 +1134,8 @@ void HKVDataset::ProcessGeoref( const char * pszFilename )
             CPLFree( pszGCPProjection );
             pszGCPProjection = NULL;
             oUTM.exportToWkt( &pszGCPProjection );
-             
-            transform_ok = GDALGCPsToGeoTransform(5,pasGCPList,adfGeoTransform,0);
+
+            int transform_ok = GDALGCPsToGeoTransform(5,pasGCPList,adfGeoTransform,0);
 
             CPLFree( pszProjection );
             pszProjection = NULL;
@@ -1215,9 +1161,7 @@ void HKVDataset::ProcessGeoref( const char * pszFilename )
     else if ((pszProjName != NULL) && (nGCPCount == 5))
     {
         OGRSpatialReference oLL;
-        int transform_ok = FALSE;
 
-     
         if (pszOriginLong != NULL)
         {
             oLL.SetProjParm(SRS_PP_LONGITUDE_OF_ORIGIN,CPLAtof(pszOriginLong));
@@ -1231,9 +1175,9 @@ void HKVDataset::ProcessGeoref( const char * pszFilename )
         else
         {
           if (hkvEllipsoids->SpheroidInList(pszSpheroidName))
-          { 
+          {
             oLL.SetGeogCS( "","",pszSpheroidName,
-                            hkvEllipsoids->GetSpheroidEqRadius(pszSpheroidName), 
+                            hkvEllipsoids->GetSpheroidEqRadius(pszSpheroidName),
                             hkvEllipsoids->GetSpheroidInverseFlattening(pszSpheroidName)
                            );
           }
@@ -1244,12 +1188,13 @@ void HKVDataset::ProcessGeoref( const char * pszFilename )
           }
         }
 
-        transform_ok = GDALGCPsToGeoTransform(5,pasGCPList,adfGeoTransform,0);
+        const bool transform_ok
+            = CPL_TO_BOOL(GDALGCPsToGeoTransform(5,pasGCPList,adfGeoTransform,0));
 
         CPLFree( pszProjection );
         pszProjection = NULL;
 
-        if (transform_ok == FALSE)
+        if( !transform_ok )
         {
             adfGeoTransform[0] = 0.0;
             adfGeoTransform[1] = 1.0;
@@ -1266,7 +1211,6 @@ void HKVDataset::ProcessGeoref( const char * pszFilename )
         CPLFree( pszGCPProjection );
         pszGCPProjection = NULL;
         oLL.exportToWkt( &pszGCPProjection );
-          
     }
 
     delete hkvEllipsoids;
@@ -1279,20 +1223,15 @@ void HKVDataset::ProcessGeoref( const char * pszFilename )
 GDALDataset *HKVDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    int		i, bNoDataSet = FALSE;
-    double      dfNoDataValue = 0.0;
-    char        **papszAttrib;
-    const char  *pszFilename, *pszValue;
-    VSIStatBuf  sStat;
-    
 /* -------------------------------------------------------------------- */
 /*      We assume the dataset is passed as a directory.  Check for      */
 /*      an attrib and blob file as a minimum.                           */
 /* -------------------------------------------------------------------- */
     if( !poOpenInfo->bIsDirectory )
         return NULL;
-    
-    pszFilename = CPLFormFilename(poOpenInfo->pszFilename, "image_data", NULL);
+
+    const char *pszFilename = CPLFormFilename(poOpenInfo->pszFilename, "image_data", NULL);
+    VSIStatBuf sStat;
     if( VSIStat(pszFilename,&sStat) != 0 )
         pszFilename = CPLFormFilename(poOpenInfo->pszFilename, "blob", NULL );
     if( VSIStat(pszFilename,&sStat) != 0 )
@@ -1306,25 +1245,21 @@ GDALDataset *HKVDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Load the attrib file, and boil white space away from around     */
 /*      the equal sign.                                                 */
 /* -------------------------------------------------------------------- */
-    papszAttrib = CSLLoad( pszFilename );
+    char **papszAttrib = CSLLoad( pszFilename );
     if( papszAttrib == NULL )
         return NULL;
 
-    for( i = 0; papszAttrib[i] != NULL; i++ )
+    for( int i = 0; papszAttrib[i] != NULL; i++ )
     {
-        int       bAfterEqual = FALSE;
-        int       iSrc, iDst;
-        char     *pszLine = papszAttrib[i];
+        int iDst = 0;
+        char *pszLine = papszAttrib[i];
 
-        for( iSrc=0, iDst=0; pszLine[iSrc] != '\0'; iSrc++ )
+        for( int iSrc = 0; pszLine[iSrc] != '\0'; iSrc++ )
         {
-            if( bAfterEqual || pszLine[iSrc] != ' ' )
+            if( pszLine[iSrc] != ' ' )
             {
                 pszLine[iDst++] = pszLine[iSrc];
             }
-
-            if( iDst > 0 && pszLine[iDst-1] == '=' )
-                bAfterEqual = FALSE;
         }
         pszLine[iDst] = '\0';
     }
@@ -1332,24 +1267,25 @@ GDALDataset *HKVDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    HKVDataset 	*poDS;
-
-    poDS = new HKVDataset();
+    HKVDataset *poDS = new HKVDataset();
 
     poDS->pszPath = CPLStrdup( poOpenInfo->pszFilename );
     poDS->papszAttrib = papszAttrib;
 
     poDS->eAccess = poOpenInfo->eAccess;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Set some dataset wide information.                              */
 /* -------------------------------------------------------------------- */
     int bNative, bComplex;
     int nRawBands = 0;
 
-    if( CSLFetchNameValue( papszAttrib, "extent.cols" ) == NULL 
+    if( CSLFetchNameValue( papszAttrib, "extent.cols" ) == NULL
         || CSLFetchNameValue( papszAttrib, "extent.rows" ) == NULL )
+    {
+        delete poDS;
         return NULL;
+    }
 
     poDS->nRasterXSize = atoi(CSLFetchNameValue(papszAttrib,"extent.cols"));
     poDS->nRasterYSize = atoi(CSLFetchNameValue(papszAttrib,"extent.rows"));
@@ -1360,7 +1296,7 @@ GDALDataset *HKVDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    pszValue = CSLFetchNameValue(papszAttrib,"pixel.order");
+    const char *pszValue = CSLFetchNameValue(papszAttrib,"pixel.order");
     if( pszValue == NULL )
         bNative = TRUE;
     else
@@ -1372,10 +1308,12 @@ GDALDataset *HKVDataset::Open( GDALOpenInfo * poOpenInfo )
 #endif
     }
 
+    bool bNoDataSet = false;
+    double dfNoDataValue = 0.0;
     pszValue = CSLFetchNameValue(papszAttrib,"pixel.no_data");
     if( pszValue != NULL )
     {
-        bNoDataSet = TRUE;
+        bNoDataSet = true;
         dfNoDataValue = CPLAtof(pszValue);
     }
 
@@ -1399,34 +1337,32 @@ GDALDataset *HKVDataset::Open( GDALOpenInfo * poOpenInfo )
 
     /* Get the version number, if present (if not, assume old version. */
     /* Versions differ in their interpretation of corner coordinates.  */
-  
+
     if  (CSLFetchNameValue( papszAttrib, "version" ) != NULL)
-      poDS->SetVersion((float)
-                       CPLAtof(CSLFetchNameValue(papszAttrib, "version")));
+      poDS->SetVersion( static_cast<float>(
+          CPLAtof( CSLFetchNameValue( papszAttrib, "version") ) ) );
     else
       poDS->SetVersion(1.0);
 
 /* -------------------------------------------------------------------- */
 /*      Figure out the datatype                                         */
 /* -------------------------------------------------------------------- */
-    const char * pszEncoding;
-    int          nSize = 1;
-    /* int          nPseudoBands; */
-    GDALDataType eType;
-
-    pszEncoding = CSLFetchNameValue(papszAttrib,"pixel.encoding");
+    const char *pszEncoding = CSLFetchNameValue(papszAttrib,"pixel.encoding");
     if( pszEncoding == NULL )
         pszEncoding = "{ *unsigned }";
 
+    int          nSize = 1;
     if( CSLFetchNameValue(papszAttrib,"pixel.size") != NULL )
         nSize = atoi(CSLFetchNameValue(papszAttrib,"pixel.size"))/8;
 #if 0
+    int nPseudoBands;
     if( bComplex )
         nPseudoBands = 2;
     else
         nPseudoBands = 1;
 #endif
 
+    GDALDataType eType;
     if( nSize == 1 )
         eType = GDT_Byte;
     else if( nSize == 2 && strstr(pszEncoding,"*unsigned") != NULL )
@@ -1451,9 +1387,9 @@ GDALDataset *HKVDataset::Open( GDALOpenInfo * poOpenInfo )
         eType = GDT_Float64;
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unsupported pixel data type in %s.\n"
-                  "pixel.size=%d pixel.encoding=%s\n", 
+                  "pixel.size=%d pixel.encoding=%s\n",
                   poDS->pszPath, nSize, pszEncoding );
         delete poDS;
         return NULL;
@@ -1470,7 +1406,7 @@ GDALDataset *HKVDataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->fpBlob = VSIFOpenL( pszFilename, "rb" );
         if( poDS->fpBlob == NULL )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
+            CPLError( CE_Failure, CPLE_OpenFailed,
                       "Unable to open file %s for read access.\n",
                       pszFilename );
             delete poDS;
@@ -1482,7 +1418,7 @@ GDALDataset *HKVDataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->fpBlob = VSIFOpenL( pszFilename, "rb+" );
         if( poDS->fpBlob == NULL )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
+            CPLError( CE_Failure, CPLE_OpenFailed,
                       "Unable to open file %s for update access.\n",
                       pszFilename );
             delete poDS;
@@ -1493,26 +1429,24 @@ GDALDataset *HKVDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Build the overview filename, as blob file = "_ovr".             */
 /* -------------------------------------------------------------------- */
-    char	*pszOvrFilename = (char *) CPLMalloc(strlen(pszFilename)+5);
+    const size_t nOvrFilenameLen = strlen( pszFilename ) + 5;
+    char *pszOvrFilename = reinterpret_cast<char *>(
+        CPLMalloc( nOvrFilenameLen ) );
 
-    sprintf( pszOvrFilename, "%s_ovr", pszFilename );
+    snprintf( pszOvrFilename, nOvrFilenameLen, "%s_ovr", pszFilename );
 
 /* -------------------------------------------------------------------- */
 /*      Define the bands.                                               */
 /* -------------------------------------------------------------------- */
-    int    nPixelOffset, nLineOffset, nOffset;
-
-    nPixelOffset = nRawBands * nSize;
-    nLineOffset = nPixelOffset * poDS->GetRasterXSize();
-    nOffset = 0;
+    const int nPixelOffset = nRawBands * nSize;
+    const int nLineOffset = nPixelOffset * poDS->GetRasterXSize();
+    int nOffset = 0;
 
     for( int iRawBand=0; iRawBand < nRawBands; iRawBand++ )
     {
-        HKVRasterBand *poBand;
-
-        poBand = 
-            new HKVRasterBand( poDS, poDS->GetRasterCount()+1, poDS->fpBlob,
-                               nOffset, nPixelOffset, nLineOffset, 
+        HKVRasterBand *poBand
+            = new HKVRasterBand( poDS, poDS->GetRasterCount()+1, poDS->fpBlob,
+                               nOffset, nPixelOffset, nLineOffset,
                                eType, bNative );
         poDS->SetBand( poDS->GetRasterCount()+1, poBand );
         nOffset += GDALGetDataTypeSize( eType ) / 8;
@@ -1535,7 +1469,7 @@ GDALDataset *HKVDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->SetDescription( pszOvrFilename );
     poDS->TryLoadXML();
-    
+
 /* -------------------------------------------------------------------- */
 /*      Handle overviews.                                               */
 /* -------------------------------------------------------------------- */
@@ -1561,13 +1495,13 @@ GDALDataset *HKVDataset::Create( const char * pszFilenameIn,
 /* -------------------------------------------------------------------- */
     if (nBands <= 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "HKV driver does not support %d bands.\n", nBands);
         return NULL;
     }
 
     if( eType != GDT_Byte
-        && eType != GDT_UInt16 && eType != GDT_Int16 
+        && eType != GDT_UInt16 && eType != GDT_Int16
         && eType != GDT_CInt16 && eType != GDT_Float32
         && eType != GDT_CFloat32 )
     {
@@ -1584,18 +1518,18 @@ GDALDataset *HKVDataset::Create( const char * pszFilenameIn,
 /*      new HKV directory in.  Verify that this is a directory.         */
 /* -------------------------------------------------------------------- */
     char	*pszBaseDir;
-    VSIStatBuf  sStat;
 
     if( strlen(CPLGetPath(pszFilenameIn)) == 0 )
         pszBaseDir = CPLStrdup(".");
     else
         pszBaseDir = CPLStrdup(CPLGetPath(pszFilenameIn));
 
+    VSIStatBuf  sStat;
     if( CPLStat( pszBaseDir, &sStat ) != 0 || !VSI_ISDIR( sStat.st_mode ) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Attempt to create HKV dataset under %s,\n"
-                  "but this is not a valid directory.\n", 
+                  "but this is not a valid directory.\n",
                   pszBaseDir);
         CPLFree( pszBaseDir );
         return NULL;
@@ -1606,8 +1540,8 @@ GDALDataset *HKVDataset::Create( const char * pszFilenameIn,
 
     if( VSIMkdir( pszFilenameIn, 0755 ) != 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Unable to create directory %s.\n", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Unable to create directory %s.\n",
                   pszFilenameIn );
         return NULL;
     }
@@ -1615,11 +1549,10 @@ GDALDataset *HKVDataset::Create( const char * pszFilenameIn,
 /* -------------------------------------------------------------------- */
 /*      Create the header file.                                         */
 /* -------------------------------------------------------------------- */
-    CPLErr CEHeaderCreated;
+    CPLErr CEHeaderCreated
+        = SaveHKVAttribFile( pszFilenameIn, nXSize, nYSize,
+                             nBands, eType, FALSE, 0.0 );
 
-    CEHeaderCreated = SaveHKVAttribFile( pszFilenameIn, nXSize, nYSize, 
-                                            nBands, eType, FALSE, 0.0 ); 
-                                    
     if (CEHeaderCreated != CE_None )
         return NULL;
 
@@ -1627,25 +1560,27 @@ GDALDataset *HKVDataset::Create( const char * pszFilenameIn,
 /*      Create the blob file.                                           */
 /* -------------------------------------------------------------------- */
 
-    FILE       *fp;
-    const char *pszFilename;
-
-    pszFilename = CPLFormFilename( pszFilenameIn, "image_data", NULL );
-    fp = VSIFOpen( pszFilename, "wb" );
+    const char *pszFilename
+        = CPLFormFilename( pszFilenameIn, "image_data", NULL );
+    FILE *fp = VSIFOpen( pszFilename, "wb" );
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "Couldn't create %s.\n", pszFilename );
         return NULL;
     }
-    
-    VSIFWrite( (void*)"", 1, 1, fp );
-    VSIFClose( fp );
 
+    bool bOK = VSIFWrite( reinterpret_cast<void *>( const_cast<char *>( "" ) ), 1, 1, fp ) == 1;
+    if( VSIFClose( fp ) != 0 )
+        bOK = false;
+
+    if( !bOK )
+        return NULL;
 /* -------------------------------------------------------------------- */
 /*      Open the dataset normally.                                      */
 /* -------------------------------------------------------------------- */
-    return (GDALDataset *) GDALOpen( pszFilenameIn, GA_Update );
+    return reinterpret_cast<GDALDataset *>(
+        GDALOpen( pszFilenameIn, GA_Update ) );
 }
 
 /************************************************************************/
@@ -1660,34 +1595,28 @@ CPLErr HKVDataset::Delete( const char * pszName )
 
 {
     VSIStatBuf	sStat;
-    char        **papszFiles;
-    int         i;
-
-    if( CPLStat( pszName, &sStat ) != 0 
-        || !VSI_ISDIR(sStat.st_mode) )
+    if( CPLStat( pszName, &sStat ) != 0 || !VSI_ISDIR(sStat.st_mode) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "%s does not appear to be an HKV Dataset, as it is not\n"
-                  "a path to a directory.", 
+                  "a path to a directory.",
                   pszName );
         return CE_Failure;
     }
 
-    papszFiles = CPLReadDir( pszName );
-    for( i = 0; i < CSLCount(papszFiles); i++ )
+    char **papszFiles = VSIReadDir( pszName );
+    for( int i = 0; i < CSLCount(papszFiles); i++ )
     {
-        const char *pszTarget;
-
         if( EQUAL(papszFiles[i],".") || EQUAL(papszFiles[i],"..") )
             continue;
 
-        pszTarget = CPLFormFilename(pszName, papszFiles[i], NULL );
+        const char *pszTarget = CPLFormFilename(pszName, papszFiles[i], NULL );
         if( VSIUnlink(pszTarget) != 0 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Unable to delete file %s,\n"
-                      "HKVDataset Delete(%s) failed.\n", 
-                      pszTarget, 
+                      "HKVDataset Delete(%s) failed.\n",
+                      pszTarget,
                       pszName );
             CSLDestroy( papszFiles );
             return CE_Failure;
@@ -1698,9 +1627,9 @@ CPLErr HKVDataset::Delete( const char * pszName )
 
     if( VSIRmdir( pszName ) != 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to delete directory %s,\n"
-                  "HKVDataset Delete() failed.\n", 
+                  "HKVDataset Delete() failed.\n",
                   pszName );
         return CE_Failure;
     }
@@ -1720,36 +1649,33 @@ HKVDataset::CreateCopy( const char * pszFilename,
                         GDALProgressFunc pfnProgress,
                         void * pProgressData )
 {
-    HKVDataset	*poDS;
-    GDALDataType eType;
-    int          iBand;
-
     int nBands = poSrcDS->GetRasterCount();
     if (nBands == 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "HKV driver does not support source dataset with zero band.\n");
         return NULL;
     }
 
-    eType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
+    GDALDataType eType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
 
     if( !pfnProgress( 0.0, NULL, pProgressData ) )
         return NULL;
 
     /* check that other bands match type- sets type */
     /* to unknown if they differ.                  */
-    for( iBand = 1; iBand < poSrcDS->GetRasterCount(); iBand++ )
+    for( int iBand = 1; iBand < poSrcDS->GetRasterCount(); iBand++ )
     {
         GDALRasterBand *poBand = poSrcDS->GetRasterBand( iBand+1 );
         eType = GDALDataTypeUnion( eType, poBand->GetRasterDataType() );
     }
 
-    poDS = (HKVDataset *) Create( pszFilename, 
-                                  poSrcDS->GetRasterXSize(), 
-                                  poSrcDS->GetRasterYSize(), 
-                                  poSrcDS->GetRasterCount(), 
-                                  eType, papszOptions );
+    HKVDataset	*poDS
+        = reinterpret_cast<HKVDataset *>( Create( pszFilename,
+                                                  poSrcDS->GetRasterXSize(),
+                                                  poSrcDS->GetRasterYSize(),
+                                                  poSrcDS->GetRasterCount(),
+                                                  eType, papszOptions ) );
 
    /* Check that Create worked- return Null if it didn't */
     if (poDS == NULL)
@@ -1758,60 +1684,57 @@ HKVDataset::CreateCopy( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Copy the image data.                                            */
 /* -------------------------------------------------------------------- */
-    int         nXSize = poDS->GetRasterXSize();
-    int         nYSize = poDS->GetRasterYSize();
-    int  	nBlockXSize, nBlockYSize, nBlockTotal, nBlocksDone;
+    const int nXSize = poDS->GetRasterXSize();
+    const int nYSize = poDS->GetRasterYSize();
 
+    int nBlockXSize, nBlockYSize;
     poDS->GetRasterBand(1)->GetBlockSize( &nBlockXSize, &nBlockYSize );
 
-    nBlockTotal = ((nXSize + nBlockXSize - 1) / nBlockXSize)
+    const int nBlockTotal = ((nXSize + nBlockXSize - 1) / nBlockXSize)
         * ((nYSize + nBlockYSize - 1) / nBlockYSize)
         * poSrcDS->GetRasterCount();
 
-    nBlocksDone = 0;
-    for( iBand = 0; iBand < poSrcDS->GetRasterCount(); iBand++ )
+    int nBlocksDone = 0;
+    for( int iBand = 0; iBand < poSrcDS->GetRasterCount(); iBand++ )
     {
         GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand+1 );
         GDALRasterBand *poDstBand = poDS->GetRasterBand( iBand+1 );
-        int	       iYOffset, iXOffset;
-        void           *pData;
-        CPLErr  eErr;
-        int pbSuccess;
-        double dfSrcNoDataValue =0.0;
 
         /* Get nodata value, if relevant */
-        dfSrcNoDataValue = poSrcBand->GetNoDataValue( &pbSuccess );
+        int pbSuccess;
+        double dfSrcNoDataValue = poSrcBand->GetNoDataValue( &pbSuccess );
         if ( pbSuccess )
   	    poDS->SetNoDataValue( dfSrcNoDataValue );
 
-        pData = CPLMalloc(nBlockXSize * nBlockYSize
-                          * GDALGetDataTypeSize(eType) / 8);
+        void *pData = CPLMalloc(
+            nBlockXSize * nBlockYSize * GDALGetDataTypeSize(eType) / 8);
 
-        for( iYOffset = 0; iYOffset < nYSize; iYOffset += nBlockYSize )
+        CPLErr eErr;
+        for( int iYOffset = 0; iYOffset < nYSize; iYOffset += nBlockYSize )
         {
-            for( iXOffset = 0; iXOffset < nXSize; iXOffset += nBlockXSize )
+            for( int iXOffset = 0; iXOffset < nXSize; iXOffset += nBlockXSize )
             {
-                int	nTBXSize, nTBYSize;
-
-                if( !pfnProgress( (nBlocksDone++) / (float) nBlockTotal,
-                                  NULL, pProgressData ) )
+                if( !pfnProgress(
+                       (nBlocksDone++) / static_cast<float>( nBlockTotal ),
+                       NULL, pProgressData ) )
                 {
-                    CPLError( CE_Failure, CPLE_UserInterrupt, 
+                    CPLError( CE_Failure, CPLE_UserInterrupt,
                               "User terminated" );
                     delete poDS;
                     CPLFree(pData);
 
-                    GDALDriver *poHKVDriver = 
-                        (GDALDriver *) GDALGetDriverByName( "MFF2" );
+                    GDALDriver *poHKVDriver =
+                        reinterpret_cast<GDALDriver *>(
+                            GDALGetDriverByName( "MFF2" ) );
                     poHKVDriver->Delete( pszFilename );
                     return NULL;
                 }
 
-                nTBXSize = MIN(nBlockXSize,nXSize-iXOffset);
-                nTBYSize = MIN(nBlockYSize,nYSize-iYOffset);
+                const int nTBXSize = MIN(nBlockXSize,nXSize-iXOffset);
+                const int nTBYSize = MIN(nBlockYSize,nYSize-iYOffset);
 
-                eErr = poSrcBand->RasterIO( GF_Read, 
-                                            iXOffset, iYOffset, 
+                eErr = poSrcBand->RasterIO( GF_Read,
+                                            iXOffset, iYOffset,
                                             nTBXSize, nTBYSize,
                                             pData, nTBXSize, nTBYSize,
                                             eType, 0, 0, NULL );
@@ -1821,9 +1744,9 @@ HKVDataset::CreateCopy( const char * pszFilename,
                     CPLFree(pData);
                     return NULL;
                 }
-            
-                eErr = poDstBand->RasterIO( GF_Write, 
-                                            iXOffset, iYOffset, 
+
+                eErr = poDstBand->RasterIO( GF_Write,
+                                            iXOffset, iYOffset,
                                             nTBXSize, nTBYSize,
                                             pData, nTBXSize, nTBYSize,
                                             eType, 0, 0, NULL );
@@ -1845,9 +1768,8 @@ HKVDataset::CreateCopy( const char * pszFilename,
 /*      Only copy geotransform-style info (won't work for slant range). */
 /* -------------------------------------------------------------------- */
 
-    double *tempGeoTransform=NULL; 
-
-    tempGeoTransform = (double *) CPLMalloc(6*sizeof(double));
+    double *tempGeoTransform
+        = reinterpret_cast<double *>( CPLMalloc( 6 * sizeof(double) ) );
 
     if (( poSrcDS->GetGeoTransform( tempGeoTransform ) == CE_None)
         && (tempGeoTransform[0] != 0.0 || tempGeoTransform[1] != 1.0
@@ -1868,24 +1790,24 @@ HKVDataset::CreateCopy( const char * pszFilename,
     else
     {
           CPLFree(tempGeoTransform);
-    }    
+    }
 
     /* Make sure image data gets flushed */
-    for( iBand = 0; iBand < poDS->GetRasterCount(); iBand++ )
+    for( int iBand = 0; iBand < poDS->GetRasterCount(); iBand++ )
     {
-        RawRasterBand *poDstBand = (RawRasterBand *) poDS->GetRasterBand( iBand+1 );
+        RawRasterBand *poDstBand = reinterpret_cast<RawRasterBand *>(
+            poDS->GetRasterBand( iBand+1 ) );
         poDstBand->FlushCache();
     }
 
-   
+
     if( !pfnProgress( 1.0, NULL, pProgressData ) )
     {
-        CPLError( CE_Failure, CPLE_UserInterrupt, 
-                  "User terminated" );
+        CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
         delete poDS;
 
-        GDALDriver *poHKVDriver = 
-            (GDALDriver *) GDALGetDriverByName( "MFF2" );
+        GDALDriver *poHKVDriver =
+            reinterpret_cast<GDALDriver *>( GDALGetDriverByName( "MFF2" ) );
         poHKVDriver->Delete( pszFilename );
         return NULL;
     }
@@ -1897,32 +1819,29 @@ HKVDataset::CreateCopy( const char * pszFilename,
 
 
 /************************************************************************/
-/*                         GDALRegister_HKV()                          */
+/*                         GDALRegister_HKV()                           */
 /************************************************************************/
 
 void GDALRegister_HKV()
 
 {
-    GDALDriver	*poDriver;
-
-    if( GDALGetDriverByName( "MFF2" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "MFF2" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Vexcel MFF2 (HKV) Raster" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_mff2.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte Int16 UInt16 Int32 UInt32 CInt16 CInt32 Float32 Float64 CFloat32 CFloat64" );
-        
-        poDriver->pfnOpen = HKVDataset::Open;
-        poDriver->pfnCreate = HKVDataset::Create;
-        poDriver->pfnDelete = HKVDataset::Delete;
-        poDriver->pfnCreateCopy = HKVDataset::CreateCopy;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    if( GDALGetDriverByName( "MFF2" ) != NULL )
+        return;
+
+    GDALDriver*poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "MFF2" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Vexcel MFF2 (HKV) Raster" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_mff2.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte Int16 UInt16 Int32 UInt32 CInt16 "
+                               "CInt32 Float32 Float64 CFloat32 CFloat64" );
+
+    poDriver->pfnOpen = HKVDataset::Open;
+    poDriver->pfnCreate = HKVDataset::Create;
+    poDriver->pfnDelete = HKVDataset::Delete;
+    poDriver->pfnCreateCopy = HKVDataset::CreateCopy;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/raw/idadataset.cpp b/frmts/raw/idadataset.cpp
index c065649..be3d03e 100644
--- a/frmts/raw/idadataset.cpp
+++ b/frmts/raw/idadataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: idadataset.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: idadataset.cpp 33673 2016-03-07 20:40:54Z goatbar $
  *
  * Project:  IDA Raster Driver
  * Purpose:  Implemenents IDA driver/dataset/rasterband.
@@ -29,13 +29,10 @@
 
 #include "rawdataset.h"
 #include "ogr_spatialref.h"
+#include "gdal_frmts.h"
 #include "gdal_rat.h"
 
-CPL_CVSID("$Id: idadataset.cpp 27384 2014-05-24 12:28:12Z rouault $");
-
-CPL_C_START
-void	GDALRegister_IDA(void);
-CPL_C_END
+CPL_CVSID("$Id: idadataset.cpp 33673 2016-03-07 20:40:54Z goatbar $");
 
 // convert a Turbo Pascal real into a double
 static double tp2c(GByte *r);
@@ -79,11 +76,11 @@ class IDADataset : public RawDataset
     int         bHeaderDirty;
 
     void        ReadColorTable();
-    
+
   public:
     		IDADataset();
     	        ~IDADataset();
-    
+
     virtual void FlushCache();
     virtual const char *GetProjectionRef(void);
     virtual CPLErr SetProjection( const char * );
@@ -131,14 +128,12 @@ class IDARasterBand : public RawRasterBand
 /************************************************************************/
 
 IDARasterBand::IDARasterBand( IDADataset *poDSIn,
-                              VSILFILE *fpRaw, int nXSize )
-        : RawRasterBand( poDSIn, 1, fpRaw, 512, 1, nXSize, 
-                         GDT_Byte, FALSE, TRUE )
-
-{
-    poColorTable = NULL;
-    poRAT = NULL;
-}
+                              VSILFILE *fpRawIn, int nXSize ) :
+    RawRasterBand( poDSIn, 1, fpRawIn, 512, 1, nXSize,
+                   GDT_Byte, FALSE, TRUE ),
+    poRAT(NULL),
+    poColorTable(NULL)
+{}
 
 /************************************************************************/
 /*                           ~IDARasterBand()                           */
@@ -160,7 +155,7 @@ double IDARasterBand::GetNoDataValue( int *pbSuccess )
 {
     if( pbSuccess != NULL )
         *pbSuccess = TRUE;
-    return ((IDADataset *) poDS)->nMissing;
+    return reinterpret_cast<IDADataset *>( poDS )->nMissing;
 }
 
 /************************************************************************/
@@ -172,7 +167,7 @@ double IDARasterBand::GetOffset( int *pbSuccess )
 {
     if( pbSuccess != NULL )
         *pbSuccess = TRUE;
-    return ((IDADataset *) poDS)->dfB;
+    return reinterpret_cast<IDADataset *>( poDS )->dfB;
 }
 
 /************************************************************************/
@@ -182,14 +177,14 @@ double IDARasterBand::GetOffset( int *pbSuccess )
 CPLErr IDARasterBand::SetOffset( double dfNewValue )
 
 {
-    IDADataset *poIDS = (IDADataset *) poDS;
+    IDADataset *poIDS = reinterpret_cast<IDADataset *>( poDS );
 
     if( dfNewValue == poIDS->dfB )
         return CE_None;
 
     if( poIDS->nImageType != 200 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Setting explicit offset only support for image type 200.");
         return CE_Failure;
     }
@@ -210,7 +205,7 @@ double IDARasterBand::GetScale( int *pbSuccess )
 {
     if( pbSuccess != NULL )
         *pbSuccess = TRUE;
-    return ((IDADataset *) poDS)->dfM;
+    return reinterpret_cast<IDADataset *>( poDS )->dfM;
 }
 
 /************************************************************************/
@@ -220,14 +215,14 @@ double IDARasterBand::GetScale( int *pbSuccess )
 CPLErr IDARasterBand::SetScale( double dfNewValue )
 
 {
-    IDADataset *poIDS = (IDADataset *) poDS;
+    IDADataset *poIDS = reinterpret_cast<IDADataset *>( poDS );
 
     if( dfNewValue == poIDS->dfM )
         return CE_None;
 
     if( poIDS->nImageType != 200 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Setting explicit scale only support for image type 200.");
         return CE_Failure;
     }
@@ -248,8 +243,8 @@ GDALColorTable *IDARasterBand::GetColorTable()
 {
     if( poColorTable )
         return poColorTable;
-    else
-        return RawRasterBand::GetColorTable();
+
+    return RawRasterBand::GetColorTable();
 }
 
 /************************************************************************/
@@ -261,21 +256,21 @@ GDALColorInterp IDARasterBand::GetColorInterpretation()
 {
     if( poColorTable )
         return GCI_PaletteIndex;
-    else
-        return RawRasterBand::GetColorInterpretation();
+
+    return RawRasterBand::GetColorInterpretation();
 }
 
 /************************************************************************/
 /*                           GetDefaultRAT()                            */
 /************************************************************************/
 
-GDALRasterAttributeTable *IDARasterBand::GetDefaultRAT() 
+GDALRasterAttributeTable *IDARasterBand::GetDefaultRAT()
 
 {
     if( poRAT )
         return poRAT;
-    else
-        return RawRasterBand::GetDefaultRAT();
+
+    return RawRasterBand::GetDefaultRAT();
 }
 
 /************************************************************************/
@@ -288,19 +283,18 @@ GDALRasterAttributeTable *IDARasterBand::GetDefaultRAT()
 /*                             IDADataset()                             */
 /************************************************************************/
 
-IDADataset::IDADataset()
+IDADataset::IDADataset() :
+    nImageType(0), nProjection(0), dfLatCenter(0.0), dfLongCenter(0.0),
+    dfXCenter(0.0), dfYCenter(0.0), dfDX(0.0), dfDY(0.0), dfParallel1(0.0),
+    dfParallel2(0.0), nMissing(0), dfM(0.0), dfB(0.0), fpRaw(NULL),
+    pszProjection(NULL), bHeaderDirty(FALSE)
 {
-    fpRaw = NULL;
-    pszProjection = NULL;
-
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
-
-    bHeaderDirty = FALSE;
 }
 
 /************************************************************************/
@@ -313,7 +307,12 @@ IDADataset::~IDADataset()
     FlushCache();
 
     if( fpRaw != NULL )
-        VSIFCloseL( fpRaw );
+    {
+        if( VSIFCloseL( fpRaw ) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        }
+    }
     CPLFree( pszProjection );
 }
 
@@ -326,36 +325,36 @@ void IDADataset::ProcessGeoref()
 {
     OGRSpatialReference oSRS;
 
-    if( nProjection == 3 ) 
+    if( nProjection == 3 )
     {
         oSRS.SetWellKnownGeogCS( "WGS84" );
     }
-    else if( nProjection == 4 ) 
+    else if( nProjection == 4 )
     {
-        oSRS.SetLCC( dfParallel1, dfParallel2, 
-                     dfLatCenter, dfLongCenter, 
+        oSRS.SetLCC( dfParallel1, dfParallel2,
+                     dfLatCenter, dfLongCenter,
                      0.0, 0.0 );
-        oSRS.SetGeogCS( "Clarke 1866", "Clarke 1866", "Clarke 1866", 
+        oSRS.SetGeogCS( "Clarke 1866", "Clarke 1866", "Clarke 1866",
                         6378206.4, 293.97869821389662 );
     }
-    else if( nProjection == 6 ) 
+    else if( nProjection == 6 )
     {
         oSRS.SetLAEA( dfLatCenter, dfLongCenter, 0.0, 0.0 );
-        oSRS.SetGeogCS( "Sphere", "Sphere", "Sphere", 
+        oSRS.SetGeogCS( "Sphere", "Sphere", "Sphere",
                         6370997.0, 0.0 );
     }
     else if( nProjection == 8 )
     {
-        oSRS.SetACEA( dfParallel1, dfParallel2, 
-                      dfLatCenter, dfLongCenter, 
+        oSRS.SetACEA( dfParallel1, dfParallel2,
+                      dfLatCenter, dfLongCenter,
                       0.0, 0.0 );
-        oSRS.SetGeogCS( "Clarke 1866", "Clarke 1866", "Clarke 1866", 
+        oSRS.SetGeogCS( "Clarke 1866", "Clarke 1866", "Clarke 1866",
                         6378206.4, 293.97869821389662 );
     }
-    else if( nProjection == 9 ) 
+    else if( nProjection == 9 )
     {
         oSRS.SetGH( dfLongCenter, 0.0, 0.0 );
-        oSRS.SetGeogCS( "Sphere", "Sphere", "Sphere", 
+        oSRS.SetGeogCS( "Sphere", "Sphere", "Sphere",
                         6370997.0, 0.0 );
     }
 
@@ -389,11 +388,11 @@ void IDADataset::FlushCache()
 
 {
     RawDataset::FlushCache();
-    
+
     if( bHeaderDirty )
     {
-        VSIFSeekL( fpRaw, 0, SEEK_SET );
-        VSIFWriteL( abyHeader, 512, 1, fpRaw );
+        CPL_IGNORE_RET_VAL(VSIFSeekL( fpRaw, 0, SEEK_SET ));
+        CPL_IGNORE_RET_VAL(VSIFWriteL( abyHeader, 512, 1, fpRaw ));
         bHeaderDirty = FALSE;
     }
 }
@@ -444,8 +443,8 @@ const char *IDADataset::GetProjectionRef()
 {
     if( pszProjection )
         return pszProjection;
-    else
-        return "";
+
+    return "";
 }
 
 /************************************************************************/
@@ -475,7 +474,7 @@ CPLErr IDADataset::SetProjection( const char *pszWKTIn )
 /* -------------------------------------------------------------------- */
     if( oSRS.IsGeographic() )
     {
-        // If no change, just return. 
+        // If no change, just return.
         if( nProjection == 3 )
             return CE_None;
 
@@ -499,13 +498,13 @@ CPLErr IDADataset::SetProjection( const char *pszWKTIn )
 /*      Lambert Conformal Conic.  Note that we don't support false      */
 /*      eastings or nothings.                                           */
 /* -------------------------------------------------------------------- */
-    const char *pszProjection = oSRS.GetAttrValue( "PROJECTION" );
+    const char *l_pszProjection = oSRS.GetAttrValue( "PROJECTION" );
 
-    if( pszProjection == NULL )
+    if( l_pszProjection == NULL )
     {
         /* do nothing - presumably geographic  */;
     }
-    else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP) )
+    else if( EQUAL(l_pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP) )
     {
         nProjection = 4;
         dfParallel1 = oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0);
@@ -513,13 +512,13 @@ CPLErr IDADataset::SetProjection( const char *pszWKTIn )
         dfLatCenter = oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
         dfLongCenter = oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
     }
-    else if( EQUAL(pszProjection,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
+    else if( EQUAL(l_pszProjection,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
     {
         nProjection = 6;
         dfLatCenter = oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
         dfLongCenter = oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
     }
-    else if( EQUAL(pszProjection,SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
+    else if( EQUAL(l_pszProjection,SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
     {
         nProjection = 8;
         dfParallel1 = oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0);
@@ -527,7 +526,7 @@ CPLErr IDADataset::SetProjection( const char *pszWKTIn )
         dfLatCenter = oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
         dfLongCenter = oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
     }
-    else if( EQUAL(pszProjection,SRS_PT_GOODE_HOMOLOSINE) )
+    else if( EQUAL(l_pszProjection,SRS_PT_GOODE_HOMOLOSINE) )
     {
         nProjection = 9;
         dfLongCenter = oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
@@ -542,7 +541,7 @@ CPLErr IDADataset::SetProjection( const char *pszWKTIn )
 /* -------------------------------------------------------------------- */
     bHeaderDirty = TRUE;
 
-    abyHeader[23] = (GByte) nProjection;
+    abyHeader[23] = static_cast<GByte>( nProjection );
     c2tp( dfLatCenter, abyHeader + 120 );
     c2tp( dfLongCenter, abyHeader + 126 );
     c2tp( dfParallel1, abyHeader + 156 );
@@ -561,18 +560,15 @@ void IDADataset::ReadColorTable()
 /* -------------------------------------------------------------------- */
 /*      Decide what .clr file to look for and try to open.              */
 /* -------------------------------------------------------------------- */
-    CPLString osCLRFilename;
-
-    osCLRFilename = CPLGetConfigOption( "IDA_COLOR_FILE", "" );
+    CPLString osCLRFilename = CPLGetConfigOption( "IDA_COLOR_FILE", "" );
     if( strlen(osCLRFilename) == 0 )
         osCLRFilename = CPLResetExtension(GetDescription(), "clr" );
 
-
-    FILE *fp = VSIFOpen( osCLRFilename, "r" );
+    VSILFILE *fp = VSIFOpenL( osCLRFilename, "r" );
     if( fp == NULL )
     {
         osCLRFilename = CPLResetExtension(osCLRFilename, "CLR" );
-        fp = VSIFOpen( osCLRFilename, "r" );
+        fp = VSIFOpenL( osCLRFilename, "r" );
     }
 
     if( fp == NULL )
@@ -581,7 +577,7 @@ void IDADataset::ReadColorTable()
 /* -------------------------------------------------------------------- */
 /*      Skip first line, with the column titles.                        */
 /* -------------------------------------------------------------------- */
-    CPLReadLine( fp );
+    CPLReadLineL( fp );
 
 /* -------------------------------------------------------------------- */
 /*      Create a RAT to populate.                                       */
@@ -598,14 +594,14 @@ void IDADataset::ReadColorTable()
 /* -------------------------------------------------------------------- */
 /*      Apply lines.                                                    */
 /* -------------------------------------------------------------------- */
-    const char *pszLine = CPLReadLine( fp );
+    const char *pszLine = CPLReadLineL( fp );
     int iRow = 0;
 
     while( pszLine != NULL )
     {
-        char **papszTokens = 
+        char **papszTokens =
             CSLTokenizeStringComplex( pszLine, " \t", FALSE, FALSE );
-        
+
         if( CSLCount( papszTokens ) >= 5 )
         {
             poRAT->SetValue( iRow, 0, atoi(papszTokens[0]) );
@@ -614,7 +610,7 @@ void IDADataset::ReadColorTable()
             poRAT->SetValue( iRow, 3, atoi(papszTokens[3]) );
             poRAT->SetValue( iRow, 4, atoi(papszTokens[4]) );
 
-            // find name, first nonspace after 5th token. 
+            // find name, first nonspace after 5th token.
             const char *pszName = pszLine;
 
             // skip from
@@ -622,25 +618,25 @@ void IDADataset::ReadColorTable()
                 pszName++;
             while( *pszName != ' ' && *pszName != '\t' && *pszName != '\0' )
                 pszName++;
-            
+
             // skip to
             while( *pszName == ' ' || *pszName == '\t' )
                 pszName++;
             while( *pszName != ' ' && *pszName != '\t' && *pszName != '\0' )
                 pszName++;
-            
+
             // skip red
             while( *pszName == ' ' || *pszName == '\t' )
                 pszName++;
             while( *pszName != ' ' && *pszName != '\t' && *pszName != '\0' )
                 pszName++;
-            
+
             // skip green
             while( *pszName == ' ' || *pszName == '\t' )
                 pszName++;
             while( *pszName != ' ' && *pszName != '\t' && *pszName != '\0' )
                 pszName++;
-            
+
             // skip blue
             while( *pszName == ' ' || *pszName == '\t' )
                 pszName++;
@@ -652,25 +648,25 @@ void IDADataset::ReadColorTable()
                 pszName++;
 
             poRAT->SetValue( iRow, 5, pszName );
-            
+
             iRow++;
         }
 
         CSLDestroy( papszTokens );
-        pszLine = CPLReadLine( fp );
+        pszLine = CPLReadLineL( fp );
     }
 
-    VSIFClose( fp );
+    VSIFCloseL( fp );
 
 /* -------------------------------------------------------------------- */
 /*      Attach RAT to band.                                             */
 /* -------------------------------------------------------------------- */
-    ((IDARasterBand *) GetRasterBand( 1 ))->poRAT = poRAT;
+    reinterpret_cast<IDARasterBand *>( GetRasterBand( 1 ) )->poRAT = poRAT;
 
 /* -------------------------------------------------------------------- */
 /*      Build a conventional color table from this.                     */
 /* -------------------------------------------------------------------- */
-    ((IDARasterBand *) GetRasterBand( 1 ))->poColorTable = 
+    reinterpret_cast<IDARasterBand *>( GetRasterBand( 1 ) )->poColorTable =
         poRAT->TranslateToColorTable();
 }
 
@@ -684,68 +680,67 @@ GDALDataset *IDADataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Is this an IDA file?                                            */
 /* -------------------------------------------------------------------- */
-    int      nXSize, nYSize;
-    GIntBig  nExpectedFileSize, nActualFileSize;
-
     if( poOpenInfo->fpL == NULL )
         return NULL;
 
     if( poOpenInfo->nHeaderBytes < 512 )
         return NULL;
 
-    // projection legal? 
+    // projection legal?
     if( poOpenInfo->pabyHeader[23] > 10 )
         return NULL;
 
-    // imagetype legal? 
-    if( (poOpenInfo->pabyHeader[22] > 14 
+    // imagetype legal?
+    if( (poOpenInfo->pabyHeader[22] > 14
          && poOpenInfo->pabyHeader[22] < 100)
-        || (poOpenInfo->pabyHeader[22] > 114 
+        || (poOpenInfo->pabyHeader[22] > 114
             && poOpenInfo->pabyHeader[22] != 200 ) )
         return NULL;
 
-    nXSize = poOpenInfo->pabyHeader[30] + poOpenInfo->pabyHeader[31] * 256;
-    nYSize = poOpenInfo->pabyHeader[32] + poOpenInfo->pabyHeader[33] * 256;
+    const int nXSize
+        = poOpenInfo->pabyHeader[30] + poOpenInfo->pabyHeader[31] * 256;
+    const int nYSize
+        = poOpenInfo->pabyHeader[32] + poOpenInfo->pabyHeader[33] * 256;
 
     if( nXSize == 0 || nYSize == 0 )
         return NULL;
 
     // The file just be exactly the image size + header size in length.
-    nExpectedFileSize = nXSize * nYSize + 512;
-    
-    VSIFSeekL( poOpenInfo->fpL, 0, SEEK_END );
-    nActualFileSize = VSIFTellL( poOpenInfo->fpL );
+    vsi_l_offset nExpectedFileSize = static_cast<vsi_l_offset>(nXSize) * nYSize + 512;
+
+    CPL_IGNORE_RET_VAL(VSIFSeekL( poOpenInfo->fpL, 0, SEEK_END ));
+    const vsi_l_offset nActualFileSize = VSIFTellL( poOpenInfo->fpL );
     VSIRewindL( poOpenInfo->fpL );
-    
+
     if( nActualFileSize != nExpectedFileSize )
         return NULL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create the dataset.                                             */
 /* -------------------------------------------------------------------- */
-    IDADataset *poDS = new IDADataset();				
+    IDADataset *poDS = new IDADataset();
 
     memcpy( poDS->abyHeader, poOpenInfo->pabyHeader, 512 );
-        
+
 /* -------------------------------------------------------------------- */
 /*      Parse various values out of the header.                         */
 /* -------------------------------------------------------------------- */
     poDS->nImageType = poOpenInfo->pabyHeader[22];
     poDS->nProjection = poOpenInfo->pabyHeader[23];
 
-    poDS->nRasterYSize = poOpenInfo->pabyHeader[30] 
+    poDS->nRasterYSize = poOpenInfo->pabyHeader[30]
         + poOpenInfo->pabyHeader[31] * 256;
-    poDS->nRasterXSize = poOpenInfo->pabyHeader[32] 
+    poDS->nRasterXSize = poOpenInfo->pabyHeader[32]
         + poOpenInfo->pabyHeader[33] * 256;
 
     strncpy( poDS->szTitle, (const char *) poOpenInfo->pabyHeader+38, 80 );
     poDS->szTitle[80] = '\0';
 
-    int nLastTitleChar = strlen(poDS->szTitle)-1;
-    while( nLastTitleChar > -1 
-           && (poDS->szTitle[nLastTitleChar] == 10 
-               || poDS->szTitle[nLastTitleChar] == 13 
-               || poDS->szTitle[nLastTitleChar] == ' ') ) 
+    int nLastTitleChar = static_cast<int>(strlen(poDS->szTitle))-1;
+    while( nLastTitleChar > -1
+           && (poDS->szTitle[nLastTitleChar] == 10
+               || poDS->szTitle[nLastTitleChar] == 13
+               || poDS->szTitle[nLastTitleChar] == ' ') )
         poDS->szTitle[nLastTitleChar--] = '\0';
 
     poDS->dfLatCenter = tp2c( poOpenInfo->pabyHeader + 120 );
@@ -784,7 +779,7 @@ ARTEMIS FEWS DIFF = 113
 ARTEMIS NEWNASA DIFF = 114
 CALCULATED =200
 */
- 
+
     poDS->nMissing = 0;
 
     switch( poDS->nImageType )
@@ -905,14 +900,14 @@ CALCULATED =200
         poDS->eAccess = GA_Update;
         if( poDS->fpRaw == NULL )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
-                      "Failed to open %s for write access.", 
+            CPLError( CE_Failure, CPLE_OpenFailed,
+                      "Failed to open %s for write access.",
                       poOpenInfo->pszFilename );
             return NULL;
         }
     }
 
-    poDS->SetBand( 1, new IDARasterBand( poDS, poDS->fpRaw, 
+    poDS->SetBand( 1, new IDARasterBand( poDS, poDS->fpRaw,
                                          poDS->nRasterXSize ) );
 
 /* -------------------------------------------------------------------- */
@@ -942,24 +937,21 @@ CALCULATED =200
 
 static double tp2c(GByte *r)
 {
-  double mant;
-  int sign, exp, i;
-
   // handle 0 case
   if (r[0] == 0)
     return 0.0;
 
   // extract sign: bit 7 of byte 5
-  sign = r[5] & 0x80 ? -1 : 1;
+  const int sign = r[5] & 0x80 ? -1 : 1;
 
   // extract mantissa from first bit of byte 1 to bit 7 of byte 5
-  mant = 0;
-  for (i = 1; i < 5; i++)
+  double mant = 0.0;
+  for ( int i = 1; i < 5; i++ )
     mant = (r[i] + mant) / 256;
   mant = (mant + (r[5] & 0x7F)) / 128 + 1;
 
    // extract exponent
-  exp = r[0] - 129;
+  const int exp = r[0] - 129;
 
   // compute the damned number
   return sign * ldexp(mant, exp);
@@ -973,39 +965,38 @@ static double tp2c(GByte *r)
 
 static void c2tp(double x, GByte *r)
 {
-  double mant, temp;
-  int negative, exp, i;
-
   // handle 0 case
   if (x == 0.0)
   {
-    for (i = 0; i < 6; r[i++] = 0);
+    for (int i = 0; i < 6; r[i++] = 0);
     return;
   }
 
   // compute mantissa, sign and exponent
-  mant = frexp(x, &exp) * 2 - 1;
+  int exp;
+  double mant = frexp(x, &exp) * 2 - 1;
   exp--;
-  negative = 0;
+  int negative = 0;
   if (mant < 0)
   {
     mant = -mant;
     negative = 1;
   }
   // stuff mantissa into Turbo Pascal real
+  double temp;
   mant = modf(mant * 128, &temp);
-  r[5] = (unsigned char) temp;
-  for (i = 4; i >= 1; i--)
+  r[5] = static_cast<unsigned char>( static_cast<int>(temp) & 0xff);
+  for ( int i = 4; i >= 1; i-- )
   {
     mant = modf(mant * 256, &temp);
-    r[i] = (unsigned char) temp;
+    r[i] = static_cast<unsigned char>( temp );
   }
   // add sign
   if (negative)
     r[5] |= 0x80;
 
   // put exponent
-  r[0] = (GByte) (exp + 129);
+  r[0] = static_cast<GByte>( exp + 129 );
 }
 
 /************************************************************************/
@@ -1032,10 +1023,7 @@ GDALDataset *IDADataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Try to create the file.                                         */
 /* -------------------------------------------------------------------- */
-    FILE	*fp;
-
-    fp = VSIFOpen( pszFilename, "wb" );
-
+    FILE *fp = VSIFOpen( pszFilename, "wb" );
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
@@ -1048,15 +1036,13 @@ GDALDataset *IDADataset::Create( const char * pszFilename,
 /*      Prepare formatted header.                                       */
 /* -------------------------------------------------------------------- */
     GByte abyHeader[512];
-    
     memset( abyHeader, 0, sizeof(abyHeader) );
-    
     abyHeader[22] = 200; /* image type - CALCULATED */
     abyHeader[23] = 0; /* projection - NONE */
     abyHeader[30] = nYSize % 256;
-    abyHeader[31] = (GByte) (nYSize / 256);
+    abyHeader[31] = static_cast<GByte>( nYSize / 256 );
     abyHeader[32] = nXSize % 256;
-    abyHeader[33] = (GByte) (nXSize / 256);
+    abyHeader[33] = static_cast<GByte>( nXSize / 256 );
 
     abyHeader[170] = 255; /* missing = 255 */
     c2tp( 1.0, abyHeader + 171 ); /* slope = 1.0 */
@@ -1070,10 +1056,10 @@ GDALDataset *IDADataset::Create( const char * pszFilename,
 
     if( VSIFWrite( abyHeader, 1, 512, fp ) != 512 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "IO error writing %s.\n%s", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "IO error writing %s.\n%s",
                   pszFilename, VSIStrerror( errno ) );
-        VSIFClose( fp );
+        CPL_IGNORE_RET_VAL(VSIFClose( fp ));
         return NULL;
     }
 
@@ -1085,45 +1071,48 @@ GDALDataset *IDADataset::Create( const char * pszFilename,
     if( VSIFSeek( fp, nXSize * nYSize - 1, SEEK_CUR ) != 0
         || VSIFWrite( abyHeader, 1, 1, fp ) != 1 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "IO error writing %s.\n%s", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "IO error writing %s.\n%s",
                   pszFilename, VSIStrerror( errno ) );
         VSIFClose( fp );
         return NULL;
     }
 
-    VSIFClose( fp );
+    if( VSIFClose( fp ) != 0 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "IO error writing %s.\n%s",
+                  pszFilename, VSIStrerror( errno ) );
+        return NULL;
+    }
 
     return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
 }
 
 /************************************************************************/
-/*                         GDALRegister_IDA()                          */
+/*                         GDALRegister_IDA()                           */
 /************************************************************************/
 
 void GDALRegister_IDA()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "IDA" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "IDA" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "IDA" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Image Data and Analysis" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#IDA" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte" );
-
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = IDADataset::Open;
-        poDriver->pfnCreate = IDADataset::Create;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
-}
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "IDA" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Image Data and Analysis" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_various.html#IDA" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte" );
 
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = IDADataset::Open;
+    poDriver->pfnCreate = IDADataset::Create;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/frmts/raw/iscedataset.cpp b/frmts/raw/iscedataset.cpp
new file mode 100644
index 0000000..e4364de
--- /dev/null
+++ b/frmts/raw/iscedataset.cpp
@@ -0,0 +1,676 @@
+/******************************************************************************
+ * $Id: iscedataset.cpp 33673 2016-03-07 20:40:54Z goatbar $
+ *
+ * Project:  ISCE Raster Reader
+ * Purpose:  Implementation of the ISCE raster reader
+ * Author:   Matthieu Volat (ISTerre), matthieu.volat at ujf-grenoble.fr
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Matthieu Volat <matthieu.volat at ujf-grenoble.fr>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gdal_frmts.h"
+#include "rawdataset.h"
+
+CPL_CVSID("$Id: iscedataset.cpp 33673 2016-03-07 20:40:54Z goatbar $");
+
+static const char * const apszISCE2GDALDatatypes[] = {
+    "BYTE:Byte",
+    "CHAR:Byte",
+    "SHORT:Int16",
+    "INT:Int32",
+    "LONG:Int64",
+    "FLOAT:Float32",
+    "DOUBLE:Float64",
+    "CBYTE:Unknown",
+    "CCHAR:Unknown",
+    "CSHORT:CInt16",
+    "CINT:CInt32",
+    "CLONG:CInt64",
+    "CFLOAT:CFloat32",
+    "CDOUBLE:CFloat64",
+    NULL };
+
+static const char * const apszGDAL2ISCEDatatypes[] = {
+    "Byte:BYTE",
+    "Int16:SHORT",
+    "Int32:INT",
+    "Int64:LONG",
+    "Float32:FLOAT",
+    "Float64:DOUBLE",
+    "CInt16:CSHORT",
+    "CInt32:CINT",
+    "CInt64:CLONG",
+    "CFloat32:CFLOAT",
+    "CFloat64:CDOUBLE",
+    NULL };
+
+enum Scheme { BIL = 0, BIP = 1, BSQ = 2 };
+static const char * const apszSchemeNames[] = { "BIL", "BIP", "BSQ", NULL };
+
+/************************************************************************/
+/* ==================================================================== */
+/*                              ISCEDataset                             */
+/* ==================================================================== */
+/************************************************************************/
+
+class ISCERasterBand;
+
+class ISCEDataset : public RawDataset
+{
+    friend class ISCERasterBand;
+
+    VSILFILE    *fpImage;
+
+    char        *pszXMLFilename;
+
+    enum Scheme eScheme;
+
+  public:
+                ISCEDataset();
+                ~ISCEDataset();
+
+    virtual void        FlushCache();
+    virtual char      **GetFileList();
+
+    static int          Identify( GDALOpenInfo *poOpenInfo );
+    static GDALDataset *Open( GDALOpenInfo *poOpenInfo );
+    static GDALDataset *Create( const char *pszFilename,
+                                int nXSize, int nYSize, int nBands,
+                                GDALDataType eType, char **papszOptions );
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                            ISCERasterBand                            */
+/* ==================================================================== */
+/************************************************************************/
+
+class ISCERasterBand : public RawRasterBand
+{
+    public:
+                ISCERasterBand( GDALDataset *poDS, int nBand, void *fpRaw,
+                                  vsi_l_offset nImgOffset, int nPixelOffset,
+                                  int nLineOffset,
+                                  GDALDataType eDataType, int bNativeOrder,
+                                  int bIsVSIL = FALSE, int bOwnsFP = FALSE );
+};
+
+/************************************************************************/
+/*                           getXMLFilename()                           */
+/************************************************************************/
+
+static CPLString getXMLFilename( GDALOpenInfo *poOpenInfo )
+{
+    CPLString osXMLFilename;
+
+    char **papszSiblingFiles = poOpenInfo->GetSiblingFiles();
+    if ( papszSiblingFiles == NULL )
+    {
+        osXMLFilename = CPLFormFilename( NULL, poOpenInfo->pszFilename,
+                                         "xml" );
+        VSIStatBufL psXMLStatBuf;
+        if ( VSIStatL( osXMLFilename, &psXMLStatBuf ) != 0 )
+        {
+            osXMLFilename = "";
+        }
+    }
+    else
+    {
+        /* ------------------------------------------------------------ */
+        /*      We need to tear apart the filename to form a .xml       */
+        /*      filename.                                               */
+        /* ------------------------------------------------------------ */
+        const CPLString osPath = CPLGetPath( poOpenInfo->pszFilename );
+        const CPLString osName = CPLGetFilename( poOpenInfo->pszFilename );
+
+        int iFile = CSLFindString( papszSiblingFiles,
+                                   CPLFormFilename( NULL, osName, "xml" ) );
+        if( iFile >= 0 )
+        {
+            osXMLFilename = CPLFormFilename( osPath,
+                                             papszSiblingFiles[iFile],
+                                             NULL );
+        }
+    }
+
+    return osXMLFilename;
+}
+
+/************************************************************************/
+/*                             ISCEDataset()                            */
+/************************************************************************/
+
+ISCEDataset::ISCEDataset() :
+    fpImage(NULL),
+    pszXMLFilename(NULL),
+    eScheme(BIL)
+{ }
+
+/************************************************************************/
+/*                            ~ISCEDataset()                          */
+/************************************************************************/
+
+ISCEDataset::~ISCEDataset( void )
+{
+    FlushCache();
+    if ( fpImage != NULL )
+    {
+        if( VSIFCloseL( fpImage ) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        }
+    }
+    CPLFree( pszXMLFilename );
+}
+
+/************************************************************************/
+/*                            FlushCache()                              */
+/************************************************************************/
+
+void ISCEDataset::FlushCache( void )
+{
+    RawDataset::FlushCache();
+
+    GDALRasterBand *band = (GetRasterCount() > 0) ? GetRasterBand(1) : NULL;
+
+    if ( eAccess == GA_ReadOnly || band == NULL )
+        return;
+
+/* -------------------------------------------------------------------- */
+/*      Recreate a XML doc with the dataset information.                */
+/* -------------------------------------------------------------------- */
+    char sBuf[64];
+    CPLXMLNode *psDocNode = CPLCreateXMLNode( NULL, CXT_Element, "imageFile" );
+
+    CPLXMLNode *psTmpNode
+        = CPLCreateXMLNode( psDocNode, CXT_Element, "property" );
+    CPLAddXMLAttributeAndValue( psTmpNode, "name", "WIDTH" );
+    snprintf(sBuf, sizeof(sBuf), "%d", nRasterXSize);
+    CPLCreateXMLElementAndValue( psTmpNode, "value", sBuf );
+
+    psTmpNode = CPLCreateXMLNode( psDocNode, CXT_Element, "property" );
+    CPLAddXMLAttributeAndValue( psTmpNode, "name", "LENGTH" );
+    snprintf(sBuf, sizeof(sBuf), "%d", nRasterYSize);
+    CPLCreateXMLElementAndValue( psTmpNode, "value", sBuf );
+
+    psTmpNode = CPLCreateXMLNode( psDocNode, CXT_Element, "property" );
+    CPLAddXMLAttributeAndValue( psTmpNode, "name", "NUMBER_BANDS" );
+    snprintf(sBuf, sizeof(sBuf), "%d", nBands);
+    CPLCreateXMLElementAndValue( psTmpNode, "value", sBuf );
+
+    const char *sType = GDALGetDataTypeName( band->GetRasterDataType() );
+    psTmpNode = CPLCreateXMLNode( psDocNode, CXT_Element, "property" );
+    CPLAddXMLAttributeAndValue( psTmpNode, "name", "DATA_TYPE" );
+    CPLCreateXMLElementAndValue( psTmpNode, "value",
+                                 CSLFetchNameValue(
+                                         (char **)apszGDAL2ISCEDatatypes,
+                                         sType ) );
+
+    const char *sScheme = apszSchemeNames[eScheme];
+    psTmpNode = CPLCreateXMLNode( psDocNode, CXT_Element, "property" );
+    CPLAddXMLAttributeAndValue( psTmpNode, "name", "SCHEME" );
+    CPLCreateXMLElementAndValue( psTmpNode, "value", sScheme );
+
+    psTmpNode = CPLCreateXMLNode( psDocNode, CXT_Element, "property" );
+    CPLAddXMLAttributeAndValue( psTmpNode, "name", "BYTE_ORDER" );
+#ifdef CPL_LSB
+    CPLCreateXMLElementAndValue( psTmpNode, "value", "l" );
+#else
+    CPLCreateXMLElementAndValue( psTmpNode, "value", "b" );
+#endif
+
+/* -------------------------------------------------------------------- */
+/*      Then, add the ISCE domain metadata.                             */
+/* -------------------------------------------------------------------- */
+    char **papszISCEMetadata = GetMetadata( "ISCE" );
+    for (int i = 0; i < CSLCount( papszISCEMetadata ); i++)
+    {
+        /* Get the tokens from the metadata item */
+        char **papszTokens = CSLTokenizeString2( papszISCEMetadata[i],
+                                                 "=",
+                                                 CSLT_STRIPLEADSPACES
+                                                 | CSLT_STRIPENDSPACES);
+        if ( CSLCount( papszTokens ) != 2 )
+        {
+            CPLDebug( "ISCE",
+                      "Line of header file could not be split at = into two"
+                          " elements: %s",
+                      papszISCEMetadata[i] );
+            CSLDestroy( papszTokens );
+            continue;
+        }
+
+        /* Don't write it out if it is one of the bits of metadata that is
+         * written out elsewhere in this routine */
+        if ( strcmp( papszTokens[0], "WIDTH" ) == 0
+              || strcmp( papszTokens[0], "LENGTH" ) == 0
+              || strcmp( papszTokens[0], "NUMBER_BANDS" ) == 0
+              || strcmp( papszTokens[0], "DATA_TYPE" ) == 0
+              || strcmp( papszTokens[0], "SCHEME" ) == 0
+              || strcmp( papszTokens[0], "BYTE_ORDER" ) == 0 )
+        {
+            CSLDestroy( papszTokens );
+            continue;
+        }
+
+        psTmpNode = CPLCreateXMLNode( psDocNode, CXT_Element, "property" );
+        CPLAddXMLAttributeAndValue( psTmpNode, "name", papszTokens[0] );
+        CPLCreateXMLElementAndValue( psTmpNode, "value", papszTokens[1] );
+
+        CSLDestroy( papszTokens );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Write the XML file.                                             */
+/* -------------------------------------------------------------------- */
+    CPLSerializeXMLTreeToFile( psDocNode, pszXMLFilename );
+
+/* -------------------------------------------------------------------- */
+/*      Free the XML Doc.                                               */
+/* -------------------------------------------------------------------- */
+    CPLDestroyXMLNode( psDocNode );
+}
+
+/************************************************************************/
+/*                            GetFileList()                             */
+/************************************************************************/
+
+char **ISCEDataset::GetFileList()
+{
+    /* Main data file, etc. */
+    char **papszFileList = RawDataset::GetFileList();
+
+    /* XML file. */
+    papszFileList = CSLAddString( papszFileList, pszXMLFilename );
+
+    return papszFileList;
+}
+
+/************************************************************************/
+/*                             Identify()                               */
+/************************************************************************/
+
+int ISCEDataset::Identify( GDALOpenInfo *poOpenInfo )
+{
+/* -------------------------------------------------------------------- */
+/*      TODO: This function is unusable now:                            */
+/*          * we can't just check for the presence of a XML file        */
+/*            the presence of a XML file                                */
+/*          * we cannot parse it to check basic tree (Identify() is     */
+/*            supposed to be faster than this                           */
+/*          * we could read only a few bytes and strstr() for           */
+/*            "imageData", but what if a file is padded with comments   */
+/*            and/or whitespaces? it would still be legit, but the      */
+/*            driver would fail...                                      */
+/* -------------------------------------------------------------------- */
+/* -------------------------------------------------------------------- */
+/*      Check if there is a .xml file                                   */
+/* -------------------------------------------------------------------- */
+    CPLString osXMLFilename = getXMLFilename( poOpenInfo );
+    if ( osXMLFilename.empty() )
+    {
+        return false;
+    }
+
+    return true;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *ISCEDataset::Open( GDALOpenInfo *poOpenInfo )
+{
+/* -------------------------------------------------------------------- */
+/*      Confirm that the header is compatible with a ISCE dataset.    */
+/* -------------------------------------------------------------------- */
+    if ( !Identify(poOpenInfo) )
+    {
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Open and parse the .xml file                                    */
+/* -------------------------------------------------------------------- */
+    const CPLString osXMLFilename = getXMLFilename( poOpenInfo );
+    CPLXMLNode *psNode = CPLParseXMLFile( osXMLFilename );
+    if ( psNode == NULL || CPLGetXMLNode( psNode, "=imageFile" ) == NULL )
+    {
+        CPLDestroyXMLNode( psNode );
+        return NULL;
+    }
+    CPLXMLNode *psCur  = CPLGetXMLNode( psNode, "=imageFile" )->psChild;
+    char **papszXmlProps = NULL;
+    while ( psCur != NULL ) {
+        const char *name, *value;
+        if ( strcmp(psCur->pszValue, "property") != 0) {
+            psCur = psCur->psNext;
+            continue;
+        }
+        name = CPLGetXMLValue( psCur, "name", NULL );
+        value = CPLGetXMLValue( psCur, "value.", NULL );
+        papszXmlProps = CSLSetNameValue( papszXmlProps,
+                                         name, value );
+        psCur = psCur->psNext;
+    }
+    /* TODO: extract <component name=Coordinate[12]> for georeferencing */
+    CPLDestroyXMLNode( psNode );
+
+/* -------------------------------------------------------------------- */
+/*      Fetch required fields.                                          */
+/* -------------------------------------------------------------------- */
+    if ( CSLFetchNameValue( papszXmlProps, "WIDTH" ) == NULL
+        || CSLFetchNameValue( papszXmlProps, "LENGTH" ) == NULL
+        || CSLFetchNameValue( papszXmlProps, "NUMBER_BANDS" ) == NULL
+        || CSLFetchNameValue( papszXmlProps, "DATA_TYPE" ) == NULL
+        || CSLFetchNameValue( papszXmlProps, "SCHEME" ) == NULL )
+    {
+        CSLDestroy( papszXmlProps );
+        return NULL;
+    }
+    const int nWidth = atoi( CSLFetchNameValue( papszXmlProps, "WIDTH" ) );
+    const int nFileLength = atoi( CSLFetchNameValue( papszXmlProps, "LENGTH" ) );
+
+/* -------------------------------------------------------------------- */
+/*      Update byte order info if image specify something.              */
+/* -------------------------------------------------------------------- */
+    bool bNativeOrder = true;
+
+    if ( CSLFetchNameValue( papszXmlProps, "BYTE_ORDER" ) != NULL )
+    {
+        const char *sByteOrder = CSLFetchNameValue( papszXmlProps,
+                                                    "BYTE_ORDER" );
+#ifdef CPL_LSB
+        if ( EQUAL( sByteOrder, "b" ) )
+#else
+        if ( EQUAL( sByteOrder, "l" ) )
+#endif
+            bNativeOrder = false;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create a corresponding GDALDataset.                             */
+/* -------------------------------------------------------------------- */
+    ISCEDataset *poDS = new ISCEDataset();
+    poDS->nRasterXSize = nWidth;
+    poDS->nRasterYSize = nFileLength;
+    poDS->eAccess = poOpenInfo->eAccess;
+    poDS->pszXMLFilename = CPLStrdup( osXMLFilename.c_str() );
+
+/* -------------------------------------------------------------------- */
+/*      Reopen file in update mode if necessary.                        */
+/* -------------------------------------------------------------------- */
+    if( poOpenInfo->eAccess == GA_Update )
+    {
+        poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb+" );
+    }
+    else
+    {
+        poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
+    }
+    if( poDS->fpImage == NULL )
+    {
+        CSLDestroy( papszXmlProps );
+        delete poDS;
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to re-open %s within ISCE driver.\n",
+                  poOpenInfo->pszFilename );
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create band information objects.                                */
+/* -------------------------------------------------------------------- */
+    const char *sDataType =
+        CSLFetchNameValue( (char **)apszISCE2GDALDatatypes,
+                           CSLFetchNameValue( papszXmlProps, "DATA_TYPE" ) );
+    const GDALDataType eDataType = GDALGetDataTypeByName( sDataType );
+    const int nBands = atoi( CSLFetchNameValue( papszXmlProps, "NUMBER_BANDS" ) );
+    const char *sScheme = CSLFetchNameValue( papszXmlProps, "SCHEME" );
+    int nPixelOffset, nLineOffset, nBandOffset;
+    if ( EQUAL( sScheme, "BIL" ) )
+    {
+		poDS->eScheme = BIL;
+        nPixelOffset = GDALGetDataTypeSize(eDataType)/8;
+        nLineOffset = nPixelOffset * nWidth * nBands;
+        nBandOffset = GDALGetDataTypeSize(eDataType)/8 * nWidth;
+    }
+    else if ( EQUAL( sScheme, "BIP" ) )
+    {
+		poDS->eScheme = BIP;
+        nPixelOffset = GDALGetDataTypeSize(eDataType)/8 * nBands;
+        nLineOffset = nPixelOffset * nWidth * nBands;
+        nBandOffset = GDALGetDataTypeSize(eDataType)/8;
+    }
+    else if ( EQUAL( sScheme, "BSQ" ) )
+    {
+		poDS->eScheme = BSQ;
+        nPixelOffset = GDALGetDataTypeSize(eDataType)/8;
+        nLineOffset = nPixelOffset * nWidth;
+        nBandOffset = nLineOffset * nFileLength;
+    }
+    else
+    {
+        CSLDestroy( papszXmlProps );
+        delete poDS;
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Unknown scheme \"%s\" within ISCE raster.\n",
+                  CSLFetchNameValue( papszXmlProps, "SCHEME" ) );
+        return NULL;
+    }
+    poDS->nBands = nBands;
+    for (int b = 0; b < nBands; b++)
+    {
+        poDS->SetBand( b + 1,
+                       new ISCERasterBand( poDS, b + 1, poDS->fpImage,
+                                             nBandOffset * b,
+                                             nPixelOffset, nLineOffset,
+                                             eDataType, TRUE,
+                                             bNativeOrder, FALSE ) );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Interpret georeferencing, if present.                           */
+/* -------------------------------------------------------------------- */
+   /* TODO */
+
+/* -------------------------------------------------------------------- */
+/*      Set all the other header metadata into the ISCE domain       */
+/* -------------------------------------------------------------------- */
+    for (int i = 0; papszXmlProps != NULL && papszXmlProps[i] != NULL; i++)
+    {
+        char **papszTokens;
+        papszTokens = CSLTokenizeString2( papszXmlProps[i],
+                                          "=",
+                                          CSLT_STRIPLEADSPACES
+                                            | CSLT_STRIPENDSPACES);
+        if ( strcmp( papszTokens[0], "WIDTH" ) == 0
+              || strcmp( papszTokens[0], "LENGTH" ) == 0
+              || strcmp( papszTokens[0], "NUMBER_BANDS" ) == 0
+              || strcmp( papszTokens[0], "DATA_TYPE" ) == 0
+              || strcmp( papszTokens[0], "SCHEME" ) == 0 )
+        {
+            CSLDestroy( papszTokens );
+            continue;
+        }
+        poDS->SetMetadataItem(papszTokens[0], papszTokens[1], "ISCE");
+        CSLDestroy( papszTokens );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Free papszXmlProps                                              */
+/* -------------------------------------------------------------------- */
+    CSLDestroy( papszXmlProps );
+
+/* -------------------------------------------------------------------- */
+/*      Initialize any PAM information.                                 */
+/* -------------------------------------------------------------------- */
+    poDS->SetDescription( poOpenInfo->pszFilename );
+    poDS->TryLoadXML();
+
+/* -------------------------------------------------------------------- */
+/*      Check for overviews.                                            */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
+
+    return( poDS );
+}
+
+/************************************************************************/
+/*                              Create()                                */
+/************************************************************************/
+
+GDALDataset *ISCEDataset::Create( const char *pszFilename,
+                                    int nXSize, int nYSize, int nBands,
+                                    GDALDataType eType,
+                                    char **papszOptions )
+{
+    const char *sType = GDALGetDataTypeName( eType );
+    const char *sScheme = CSLFetchNameValueDef( papszOptions,
+                                                "SCHEME",
+                                                "BIP" );
+
+/* -------------------------------------------------------------------- */
+/*      Try to create the file.                                         */
+/* -------------------------------------------------------------------- */
+    VSILFILE *fp = VSIFOpenL( pszFilename, "wb" );
+    if( fp == NULL )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Attempt to create file `%s' failed.\n",
+                  pszFilename );
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Just write out a couple of bytes to establish the binary        */
+/*      file, and then close it.                                        */
+/* -------------------------------------------------------------------- */
+    CPL_IGNORE_RET_VAL(VSIFWriteL( (void *) "\0\0", 2, 1, fp ));
+    CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
+
+/* -------------------------------------------------------------------- */
+/*      Create a minimal XML document.                                  */
+/* -------------------------------------------------------------------- */
+    CPLXMLNode *psDocNode = CPLCreateXMLNode( NULL, CXT_Element, "imageFile" );
+
+    CPLXMLNode *psTmpNode
+        = CPLCreateXMLNode( psDocNode, CXT_Element, "property" );
+    CPLAddXMLAttributeAndValue( psTmpNode, "name", "WIDTH" );
+    char sBuf[64];
+    snprintf(sBuf, sizeof(sBuf), "%d", nXSize);
+    CPLCreateXMLElementAndValue( psTmpNode, "value", sBuf );
+
+    psTmpNode = CPLCreateXMLNode( psDocNode, CXT_Element, "property" );
+    CPLAddXMLAttributeAndValue( psTmpNode, "name", "LENGTH" );
+    snprintf(sBuf, sizeof(sBuf), "%d", nYSize);
+    CPLCreateXMLElementAndValue( psTmpNode, "value", sBuf );
+
+    psTmpNode = CPLCreateXMLNode( psDocNode, CXT_Element, "property" );
+    CPLAddXMLAttributeAndValue( psTmpNode, "name", "NUMBER_BANDS" );
+    snprintf(sBuf, sizeof(sBuf), "%d", nBands);
+    CPLCreateXMLElementAndValue( psTmpNode, "value", sBuf );
+
+    psTmpNode = CPLCreateXMLNode( psDocNode, CXT_Element, "property" );
+    CPLAddXMLAttributeAndValue( psTmpNode, "name", "DATA_TYPE" );
+    CPLCreateXMLElementAndValue( psTmpNode, "value",
+                                 CSLFetchNameValue(
+                                         (char **)apszGDAL2ISCEDatatypes,
+                                         sType ));
+
+    psTmpNode = CPLCreateXMLNode( psDocNode, CXT_Element, "property" );
+    CPLAddXMLAttributeAndValue( psTmpNode, "name", "SCHEME" );
+    CPLCreateXMLElementAndValue( psTmpNode, "value", sScheme );
+
+    psTmpNode = CPLCreateXMLNode( psDocNode, CXT_Element, "property" );
+    CPLAddXMLAttributeAndValue( psTmpNode, "name", "BYTE_ORDER" );
+#ifdef CPL_LSB
+    CPLCreateXMLElementAndValue( psTmpNode, "value", "l" );
+#else
+    CPLCreateXMLElementAndValue( psTmpNode, "value", "b" );
+#endif
+
+/* -------------------------------------------------------------------- */
+/*      Write the XML file.                                             */
+/* -------------------------------------------------------------------- */
+    const char  *pszXMLFilename = CPLFormFilename( NULL, pszFilename, "xml" );
+    CPLSerializeXMLTreeToFile( psDocNode, pszXMLFilename );
+
+/* -------------------------------------------------------------------- */
+/*      Free the XML Doc.                                               */
+/* -------------------------------------------------------------------- */
+    CPLDestroyXMLNode( psDocNode );
+
+    return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
+}
+
+/************************************************************************/
+/*                          ISCERasterBand()                            */
+/************************************************************************/
+
+ISCERasterBand::ISCERasterBand( GDALDataset *poDSIn, int nBandIn, void *fpRawIn,
+                                    vsi_l_offset nImgOffsetIn, int nPixelOffsetIn,
+                                    int nLineOffsetIn,
+                                    GDALDataType eDataTypeIn, int bNativeOrderIn,
+                                    int bIsVSILIn, int bOwnsFPIn ) :
+        RawRasterBand(poDSIn, nBandIn, fpRawIn, nImgOffsetIn, nPixelOffsetIn,
+                      nLineOffsetIn, eDataTypeIn, bNativeOrderIn, bIsVSILIn, bOwnsFPIn)
+{
+}
+
+/************************************************************************/
+/*                         GDALRegister_ISCE()                          */
+/************************************************************************/
+
+void GDALRegister_ISCE()
+{
+    if( !GDAL_CHECK_VERSION( "ISCE" ) )
+        return;
+
+    if( GDALGetDriverByName( "ISCE" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "ISCE" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "ISCE raster" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#ISCE" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte Int16 Int32 Int64 Float32"
+                               " Float64 CInt16 CInt64 CFloat32 "
+                               " CFloat64" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+"<CreationOptionList>"
+"   <Option name='SCHEME' type='string-select'>"
+"       <Value>BIP</Value>"
+"       <Value>BIL</Value>"
+"       <Value>BSQ</Value>"
+"   </Option>"
+"</CreationOptionList>" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = ISCEDataset::Open;
+    poDriver->pfnCreate = ISCEDataset::Create;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/frmts/raw/krodataset.cpp b/frmts/raw/krodataset.cpp
index 86f468f..814f3f9 100644
--- a/frmts/raw/krodataset.cpp
+++ b/frmts/raw/krodataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: krodataset.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: krodataset.cpp 33673 2016-03-07 20:40:54Z goatbar $
  *
  * Project:  KRO format reader/writer
  * Purpose:  Implementation of KOLOR Raw Format
@@ -28,10 +28,11 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "rawdataset.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "rawdataset.h"
 
-CPL_CVSID("$Id: krodataset.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: krodataset.cpp 33673 2016-03-07 20:40:54Z goatbar $");
 
 /* http://www.autopano.net/wiki-en/Format_KRO */
 
@@ -47,7 +48,7 @@ class KRODataset : public RawDataset
     VSILFILE	*fpImage;	// image data file.
 
   public:
-                    KRODataset();
+                    KRODataset() : fpImage(NULL) {};
                    ~KRODataset();
 
     static GDALDataset *Open( GDALOpenInfo * );
@@ -64,15 +65,6 @@ class KRODataset : public RawDataset
 /************************************************************************/
 
 /************************************************************************/
-/*                              KRODataset()                            */
-/************************************************************************/
-
-KRODataset::KRODataset()
-{
-    fpImage = NULL;
-}
-
-/************************************************************************/
 /*                             ~KRODataset()                            */
 /************************************************************************/
 
@@ -82,7 +74,12 @@ KRODataset::~KRODataset()
     FlushCache();
 
     if( fpImage != NULL )
-        VSIFCloseL( fpImage );
+    {
+        if( VSIFCloseL( fpImage ) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        }
+    }
 }
 
 /************************************************************************/
@@ -95,7 +92,7 @@ int KRODataset::Identify( GDALOpenInfo *poOpenInfo )
     if( poOpenInfo->nHeaderBytes < 20 )
         return FALSE;
 
-    if( !EQUALN((const char *)poOpenInfo->pabyHeader, "KRO\x01", 4 ) )
+    if( !STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "KRO\x01") )
         return FALSE;
 
     return TRUE;
@@ -114,9 +111,7 @@ GDALDataset *KRODataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    KRODataset 	*poDS;
-
-    poDS = new KRODataset();
+    KRODataset 	*poDS = new KRODataset();
     poDS->eAccess = poOpenInfo->eAccess;
 
 /* -------------------------------------------------------------------- */
@@ -137,23 +132,25 @@ GDALDataset *KRODataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Read the file header.                                           */
 /* -------------------------------------------------------------------- */
     char  achHeader[20];
-    int   nXSize, nYSize, nDepth, nComp;
-
-    VSIFReadL( achHeader, 1, 20, poDS->fpImage );
+    CPL_IGNORE_RET_VAL(VSIFReadL( achHeader, 1, 20, poDS->fpImage ));
 
+    int nXSize;
     memcpy(&nXSize, achHeader + 4, 4);
     CPL_MSBPTR32( &nXSize );
 
+    int nYSize;
     memcpy(&nYSize, achHeader + 8, 4);
     CPL_MSBPTR32( &nYSize );
 
+    int nDepth;
     memcpy(&nDepth, achHeader + 12, 4);
     CPL_MSBPTR32( &nDepth );
 
+    int nComp;
     memcpy(&nComp, achHeader + 16, 4);
     CPL_MSBPTR32( &nComp );
 
-    if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) ||
+    if (!GDALCheckDatasetDimensions(nXSize, nYSize) ||
         !GDALCheckBandCount(nComp, FALSE))
     {
         delete poDS;
@@ -178,15 +175,25 @@ GDALDataset *KRODataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    int nDataTypeSize = nDepth / 8;
+    const int nDataTypeSize = nDepth / 8;
+
+    if( nComp == 0 || nDataTypeSize == 0 ||
+        poDS->nRasterXSize > INT_MAX / (nComp * nDataTypeSize) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Too large width / number of bands");
+        delete poDS;
+        return NULL;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Create bands.                                                   */
 /* -------------------------------------------------------------------- */
+    CPLErrorReset();
     for( int iBand = 0; iBand < nComp; iBand++ )
     {
-        RawRasterBand *poBand = 
-            new RawRasterBand( poDS, iBand+1, poDS->fpImage, 
+        RawRasterBand *poBand =
+            new RawRasterBand( poDS, iBand+1, poDS->fpImage,
                                20 + nDataTypeSize * iBand,
                                nComp * nDataTypeSize,
                                poDS->nRasterXSize * nComp * nDataTypeSize,
@@ -196,6 +203,11 @@ GDALDataset *KRODataset::Open( GDALOpenInfo * poOpenInfo )
             poBand->SetColorInterpretation( (GDALColorInterp) (GCI_RedBand + iBand) );
         }
         poDS->SetBand( iBand+1, poBand );
+        if( CPLGetLastErrorType() != CE_None )
+        {
+            delete poDS;
+            return NULL;
+        }
     }
 
     if( nComp > 1 )
@@ -234,13 +246,10 @@ GDALDataset *KRODataset::Create( const char * pszFilename,
         return NULL;
     }
 
-    VSILFILE    *fp;
-    
 /* -------------------------------------------------------------------- */
 /*      Try to create file.                                             */
 /* -------------------------------------------------------------------- */
-    fp = VSIFOpenL( pszFilename, "wb" );
-    
+    VSILFILE *fp = VSIFOpenL( pszFilename, "wb" );
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
@@ -249,14 +258,12 @@ GDALDataset *KRODataset::Create( const char * pszFilename,
         return NULL;
     }
 
-    int nRet = 0;
-    nRet += VSIFWriteL("KRO\01", 4, 1, fp);
+    size_t nRet = VSIFWriteL("KRO\01", 4, 1, fp);
 
-    int nTmp;
 /* -------------------------------------------------------------------- */
 /*      Create a file level header.                                     */
 /* -------------------------------------------------------------------- */
-    nTmp = nXSize;
+    int nTmp = nXSize;
     CPL_MSBPTR32(&nTmp);
     nRet += VSIFWriteL(&nTmp, 4, 1, fp);
 
@@ -276,16 +283,20 @@ GDALDataset *KRODataset::Create( const char * pszFilename,
 /*      Zero out image data                                             */
 /* -------------------------------------------------------------------- */
 
-    VSIFSeekL(fp, (vsi_l_offset)nXSize * nYSize * (GDALGetDataTypeSize(eType) / 8) * nBands - 1,
-              SEEK_CUR);
+    CPL_IGNORE_RET_VAL(VSIFSeekL(fp, (vsi_l_offset)nXSize * nYSize * (GDALGetDataTypeSize(eType) / 8) * nBands - 1,
+              SEEK_CUR));
     GByte byNul = 0;
     nRet += VSIFWriteL(&byNul, 1, 1, fp);
-    VSIFCloseL(fp);
+    if( VSIFCloseL(fp) != 0 )
+    {
+        CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        return NULL;
+    }
 
     if( nRet != 6 )
         return NULL;
 
-    return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
+    return reinterpret_cast<GDALDataset *>( GDALOpen( pszFilename, GA_Update ) );
 }
 
 /************************************************************************/
@@ -295,25 +306,22 @@ GDALDataset *KRODataset::Create( const char * pszFilename,
 void GDALRegister_KRO()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "KRO" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "KRO" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-
-        poDriver->SetDescription( "KRO" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "KOLOR Raw" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "kro" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte UInt16 Float32" );
-
-        poDriver->pfnIdentify = KRODataset::Identify;
-        poDriver->pfnOpen = KRODataset::Open;
-        poDriver->pfnCreate = KRODataset::Create;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "KRO" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "KOLOR Raw" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "kro" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte UInt16 Float32" );
+
+    poDriver->pfnIdentify = KRODataset::Identify;
+    poDriver->pfnOpen = KRODataset::Open;
+    poDriver->pfnCreate = KRODataset::Create;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/raw/landataset.cpp b/frmts/raw/landataset.cpp
index b0bd156..aa1eeb5 100644
--- a/frmts/raw/landataset.cpp
+++ b/frmts/raw/landataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: landataset.cpp 28435 2015-02-07 14:35:34Z rouault $
+ * $Id: landataset.cpp 33673 2016-03-07 20:40:54Z goatbar $
  *
  * Project:  eCognition
  * Purpose:  Implementation of Erdas .LAN / .GIS format.
@@ -28,15 +28,17 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "rawdataset.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
 #include "ogr_spatialref.h"
+#include "rawdataset.h"
+
+#include <cmath>
 
-CPL_CVSID("$Id: landataset.cpp 28435 2015-02-07 14:35:34Z rouault $");
+#include <algorithm>
+
+CPL_CVSID("$Id: landataset.cpp 33673 2016-03-07 20:40:54Z goatbar $");
 
-CPL_C_START
-void	GDALRegister_LAN(void);
-CPL_C_END
 
 /**
 
@@ -44,9 +46,9 @@ Erdas Header format: "HEAD74"
 
 Offset   Size    Type      Description
 ------   ----    ----      -----------
-0          6     char      magic cookie / version (ie. HEAD74). 
+0          6     char      magic cookie / version (i.e. HEAD74).
 6          2    Int16      Pixel type, 0=8bit, 1=4bit, 2=16bit
-8          2    Int16      Number of Bands. 
+8          2    Int16      Number of Bands.
 10         6     char      Unknown.
 16         4    Int32      Width
 20         4    Int32      Height
@@ -57,7 +59,7 @@ Offset   Size    Type      Description
 90         2    Int16      Classes in coverage.
 92        14     char      Unknown.
 106        2    Int16      Area Unit (0=none, 1=Acre, 2=Hectare, 3=Other)
-108        4  Float32      Pixel area. 
+108        4  Float32      Pixel area.
 112        4  Float32      Upper Left corner X (center of pixel?)
 116        4  Float32      Upper Left corner Y (center of pixel?)
 120        4  Float32      Width of a pixel.
@@ -67,9 +69,9 @@ Erdas Header format: "HEADER"
 
 Offset   Size    Type      Description
 ------   ----    ----      -----------
-0          6     char      magic cookie / version (ie. HEAD74). 
+0          6     char      magic cookie / version (i.e. HEAD74).
 6          2    Int16      Pixel type, 0=8bit, 1=4bit, 2=16bit
-8          2    Int16      Number of Bands. 
+8          2    Int16      Number of Bands.
 10         6     char      Unknown.
 16         4  Float32      Width
 20         4  Float32      Height
@@ -80,7 +82,7 @@ Offset   Size    Type      Description
 90         2    Int16      Classes in coverage.
 92        14     char      Unknown.
 106        2    Int16      Area Unit (0=none, 1=Acre, 2=Hectare, 3=Other)
-108        4  Float32      Pixel area. 
+108        4  Float32      Pixel area.
 112        4  Float32      Upper Left corner X (center of pixel?)
 116        4  Float32      Upper Left corner Y (center of pixel?)
 120        4  Float32      Width of a pixel.
@@ -89,7 +91,7 @@ Offset   Size    Type      Description
 All binary fields are in the same byte order but it may be big endian or
 little endian depending on what platform the file was written on.  Usually
 this can be checked against the number of bands though this test won't work
-if there are more than 255 bands. 
+if there are more than 255 bands.
 
 There is also some information on .STA and .TRL files at:
 
@@ -97,7 +99,7 @@ There is also some information on .STA and .TRL files at:
 
 **/
 
-#define ERD_HEADER_SIZE  128
+static const int ERD_HEADER_SIZE = 128;
 
 /************************************************************************/
 /* ==================================================================== */
@@ -118,7 +120,7 @@ class LAN4BitRasterBand : public GDALPamRasterBand
 
     virtual GDALColorTable *GetColorTable();
     virtual GDALColorInterp GetColorInterpretation();
-    virtual CPLErr SetColorTable( GDALColorTable * ); 
+    virtual CPLErr SetColorTable( GDALColorTable * );
     virtual CPLErr SetColorInterpretation( GDALColorInterp );
 
     virtual CPLErr IReadBlock( int, int, void * );
@@ -134,11 +136,11 @@ class LANDataset : public RawDataset
 {
   public:
     VSILFILE	*fpImage;	// image data file.
-    
+
     char	pachHeader[ERD_HEADER_SIZE];
 
     char        *pszProjection;
-    
+
     double      adfGeoTransform[6];
 
     CPLString   osSTAFilename;
@@ -149,7 +151,7 @@ class LANDataset : public RawDataset
   public:
     		LANDataset();
     	        ~LANDataset();
-    
+
     virtual CPLErr GetGeoTransform( double * padfTransform );
     virtual CPLErr SetGeoTransform( double * padfTransform );
     virtual const char *GetProjectionRef();
@@ -171,18 +173,16 @@ class LANDataset : public RawDataset
 /*                         LAN4BitRasterBand()                          */
 /************************************************************************/
 
-LAN4BitRasterBand::LAN4BitRasterBand( LANDataset *poDS, int nBandIn )
-
+LAN4BitRasterBand::LAN4BitRasterBand( LANDataset *poDSIn, int nBandIn ) :
+    poCT(NULL),
+    eInterp(GCI_Undefined)
 {
-    this->poDS = poDS;
-    this->nBand = nBandIn;
-    this->eDataType = GDT_Byte;
+    poDS = poDSIn;
+    nBand = nBandIn;
+    eDataType = GDT_Byte;
 
-    nBlockXSize = poDS->GetRasterXSize();;
+    nBlockXSize = poDSIn->GetRasterXSize();;
     nBlockYSize = 1;
-
-    poCT = NULL;
-    eInterp = GCI_Undefined;
 }
 
 /************************************************************************/
@@ -205,22 +205,20 @@ CPLErr LAN4BitRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                                       void * pImage )
 
 {
-    LANDataset *poLAN_DS = (LANDataset *) poDS;
+    LANDataset *poLAN_DS = reinterpret_cast<LANDataset *>( poDS );
     CPLAssert( nBlockXOff == 0  );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Seek to profile.                                                */
 /* -------------------------------------------------------------------- */
-    int nOffset;
-
-    nOffset = 
+    const vsi_l_offset nOffset =
         ERD_HEADER_SIZE
-        + (nBlockYOff * nRasterXSize * poLAN_DS->GetRasterCount()) / 2
-        + ((nBand - 1) * nRasterXSize) / 2;
+        + (static_cast<vsi_l_offset>(nBlockYOff) * nRasterXSize * poLAN_DS->GetRasterCount()) / 2
+        + (static_cast<vsi_l_offset>(nBand - 1) * nRasterXSize) / 2;
 
     if( VSIFSeekL( poLAN_DS->fpImage, nOffset, SEEK_SET ) != 0 )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   "LAN Seek failed:%s", VSIStrerror( errno ) );
         return CE_Failure;
     }
@@ -228,10 +226,10 @@ CPLErr LAN4BitRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /* -------------------------------------------------------------------- */
 /*      Read the profile.                                               */
 /* -------------------------------------------------------------------- */
-    if( VSIFReadL( pImage, 1, nRasterXSize/2, poLAN_DS->fpImage ) != 
+    if( VSIFReadL( pImage, 1, nRasterXSize/2, poLAN_DS->fpImage ) !=
         (size_t) nRasterXSize / 2 )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   "LAN Read failed:%s", VSIStrerror( errno ) );
         return CE_Failure;
     }
@@ -239,14 +237,12 @@ CPLErr LAN4BitRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /* -------------------------------------------------------------------- */
 /*      Convert 4bit to 8bit.                                           */
 /* -------------------------------------------------------------------- */
-    int i;
-
-    for( i = nRasterXSize-1; i >= 0; i-- )
+    for( int i = nRasterXSize-1; i >= 0; i-- )
     {
         if( (i & 0x01) != 0 )
-            ((GByte *) pImage)[i] = ((GByte *) pImage)[i/2] & 0x0f;
+            reinterpret_cast<GByte *>( pImage )[i] = ((GByte *) pImage)[i/2] & 0x0f;
         else
-            ((GByte *) pImage)[i] = (((GByte *) pImage)[i/2] & 0xf0)/16;
+            reinterpret_cast<GByte *>( pImage )[i] = (((GByte *) pImage)[i/2] & 0xf0)/16;
     }
 
     return CE_None;
@@ -278,8 +274,8 @@ GDALColorTable *LAN4BitRasterBand::GetColorTable()
 {
     if( poCT != NULL )
         return poCT;
-    else
-        return GDALPamRasterBand::GetColorTable();
+
+    return GDALPamRasterBand::GetColorTable();
 }
 
 /************************************************************************/
@@ -314,10 +310,10 @@ GDALColorInterp LAN4BitRasterBand::GetColorInterpretation()
 /*                             LANDataset()                             */
 /************************************************************************/
 
-LANDataset::LANDataset()
+LANDataset::LANDataset() :
+    fpImage(NULL),
+    pszProjection(NULL)
 {
-    fpImage = NULL;
-    pszProjection = NULL;
 }
 
 /************************************************************************/
@@ -330,7 +326,12 @@ LANDataset::~LANDataset()
     FlushCache();
 
     if( fpImage != NULL )
-        VSIFCloseL( fpImage );
+    {
+        if( VSIFCloseL( fpImage ) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        }
+    }
 
     CPLFree( pszProjection );
 }
@@ -349,16 +350,14 @@ GDALDataset *LANDataset::Open( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->nHeaderBytes < ERD_HEADER_SIZE )
         return NULL;
 
-    if( !EQUALN((const char *)poOpenInfo->pabyHeader,"HEADER",6)
-        && !EQUALN((const char *)poOpenInfo->pabyHeader,"HEAD74",6) )
+    if( !STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "HEADER")
+        && !STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "HEAD74") )
         return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    LANDataset 	*poDS;
-
-    poDS = new LANDataset();
+    LANDataset *poDS = new LANDataset();
 
     poDS->eAccess = poOpenInfo->eAccess;
 
@@ -371,22 +370,24 @@ GDALDataset *LANDataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb+" );
 
     if( poDS->fpImage == NULL )
+    {
+        delete poDS;
         return NULL;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Do we need to byte swap the headers to local machine order?     */
 /* -------------------------------------------------------------------- */
     int bBigEndian = poOpenInfo->pabyHeader[8] == 0;
-    int bNeedSwap;
 
     memcpy( poDS->pachHeader, poOpenInfo->pabyHeader, ERD_HEADER_SIZE );
 
 #ifdef CPL_LSB
-    bNeedSwap = bBigEndian;
+    const int bNeedSwap = bBigEndian;
 #else
-    bNeedSwap = !bBigEndian;
+    const int bNeedSwap = !bBigEndian;
 #endif
-        
+
     if( bNeedSwap )
     {
         CPL_SWAP16PTR( poDS->pachHeader + 6 );
@@ -411,10 +412,7 @@ GDALDataset *LANDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Capture some information from the file that is of interest.     */
 /* -------------------------------------------------------------------- */
-    int  nBandCount, nPixelOffset;
-    GDALDataType eDataType;
-
-    if( EQUALN(poDS->pachHeader,"HEADER",7) )
+    if( STARTS_WITH_CI(poDS->pachHeader,"HEADER") )
     {
         float fTmp;
         memcpy(&fTmp, poDS->pachHeader + 16, 4);
@@ -439,6 +437,8 @@ GDALDataset *LANDataset::Open( GDALOpenInfo * poOpenInfo )
     memcpy(&nTmp16, poDS->pachHeader + 6, 2);
     CPL_LSBPTR16(&nTmp16);
 
+    int nPixelOffset;
+    GDALDataType eDataType;
     if( nTmp16 == 0 )
     {
         eDataType = GDT_Byte;
@@ -456,17 +456,17 @@ GDALDataset *LANDataset::Open( GDALOpenInfo * poOpenInfo )
     }
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Unsupported pixel type (%d).", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Unsupported pixel type (%d).",
                   nTmp16 );
-                  
+
         delete poDS;
         return NULL;
     }
 
     memcpy(&nTmp16, poDS->pachHeader + 8, 2);
     CPL_LSBPTR16(&nTmp16);
-    nBandCount = nTmp16;
+    const int nBandCount = nTmp16;
 
     if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) ||
         !GDALCheckBandCount(nBandCount, FALSE))
@@ -475,23 +475,37 @@ GDALDataset *LANDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
+    if( nPixelOffset != -1 && poDS->nRasterXSize > INT_MAX / (nPixelOffset*nBandCount) )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Int overflow occurred.");
+        delete poDS;
+        return NULL;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Create band information object.                                 */
 /* -------------------------------------------------------------------- */
+    CPLErrorReset();
     for( int iBand = 1; iBand <= nBandCount; iBand++ )
     {
         if( nPixelOffset == -1 ) /* 4 bit case */
-            poDS->SetBand( iBand, 
+            poDS->SetBand( iBand,
                            new LAN4BitRasterBand( poDS, iBand ) );
         else
-            poDS->SetBand( 
-                iBand, 
-                new RawRasterBand( poDS, iBand, poDS->fpImage, 
-                                   ERD_HEADER_SIZE + (iBand-1) 
+            poDS->SetBand(
+                iBand,
+                new RawRasterBand( poDS, iBand, poDS->fpImage,
+                                   ERD_HEADER_SIZE + (iBand-1)
                                    * nPixelOffset * poDS->nRasterXSize,
-                                   nPixelOffset, 
+                                   nPixelOffset,
                                    poDS->nRasterXSize*nPixelOffset*nBandCount,
                                    eDataType, !bNeedSwap, TRUE ));
+        if( CPLGetLastErrorType() != CE_None )
+        {
+            delete poDS;
+            return NULL;
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -507,7 +521,7 @@ GDALDataset *LANDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
 /* -------------------------------------------------------------------- */
-/*      Try to interprete georeferencing.                               */
+/*      Try to interpret georeferencing.                                */
 /* -------------------------------------------------------------------- */
     float fTmp;
 
@@ -536,9 +550,9 @@ GDALDataset *LANDataset::Open( GDALOpenInfo * poOpenInfo )
     if( poDS->adfGeoTransform[1] == 0.0
         || poDS->adfGeoTransform[5] == 0.0 )
     {
-        if( !GDALReadWorldFile( poOpenInfo->pszFilename, NULL, 
+        if( !GDALReadWorldFile( poOpenInfo->pszFilename, NULL,
                                 poDS->adfGeoTransform ) )
-            GDALReadWorldFile( poOpenInfo->pszFilename, ".wld", 
+            GDALReadWorldFile( poOpenInfo->pszFilename, ".wld",
                                poDS->adfGeoTransform );
     }
 
@@ -552,20 +566,19 @@ GDALDataset *LANDataset::Open( GDALOpenInfo * poOpenInfo )
     if( nCoordSys == 0 )
     {
         poDS->pszProjection = CPLStrdup(SRS_WKT_WGS84);
-            
     }
     else if( nCoordSys == 1 )
     {
-        poDS->pszProjection = 
+        poDS->pszProjection =
             CPLStrdup("LOCAL_CS[\"UTM - Zone Unknown\",UNIT[\"Meter\",1]]");
     }
     else if( nCoordSys == 2 )
     {
         poDS->pszProjection = CPLStrdup("LOCAL_CS[\"State Plane - Zone Unknown\",UNIT[\"US survey foot\",0.3048006096012192]]");
     }
-    else 
+    else
     {
-        poDS->pszProjection = 
+        poDS->pszProjection =
             CPLStrdup("LOCAL_CS[\"Unknown\",UNIT[\"Meter\",1]]");
     }
 
@@ -574,22 +587,18 @@ GDALDataset *LANDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     char *pszPath = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
     char *pszBasename = CPLStrdup(CPLGetBasename(poOpenInfo->pszFilename));
-    const char *pszTRLFilename = 
+    const char *pszTRLFilename =
         CPLFormCIFilename( pszPath, pszBasename, "trl" );
-    VSILFILE *fpTRL;
-
-    fpTRL = VSIFOpenL( pszTRLFilename, "rb" );
+    VSILFILE *fpTRL = VSIFOpenL( pszTRLFilename, "rb" );
     if( fpTRL != NULL )
     {
         char szTRLData[896];
-        int iColor;
-        GDALColorTable *poCT;
-
-        VSIFReadL( szTRLData, 1, 896, fpTRL );
-        VSIFCloseL( fpTRL );
-        
-        poCT = new GDALColorTable();
-        for( iColor = 0; iColor < 256; iColor++ )
+
+        CPL_IGNORE_RET_VAL(VSIFReadL( szTRLData, 1, 896, fpTRL ));
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fpTRL ));
+
+        GDALColorTable *poCT = new GDALColorTable();
+        for( int iColor = 0; iColor < 256; iColor++ )
         {
             GDALColorEntry sEntry;
 
@@ -606,7 +615,7 @@ GDALDataset *LANDataset::Open( GDALOpenInfo * poOpenInfo )
 
         poDS->GetRasterBand(1)->SetColorTable( poCT );
         poDS->GetRasterBand(1)->SetColorInterpretation( GCI_PaletteIndex );
-        
+
         delete poCT;
     }
 
@@ -643,36 +652,36 @@ CPLErr LANDataset::SetGeoTransform( double * padfTransform )
 
     memcpy( adfGeoTransform, padfTransform, sizeof(double) * 6 );
 
-    VSIFSeekL( fpImage, 0, SEEK_SET );
-    VSIFReadL( abyHeader, 128, 1, fpImage );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( fpImage, 0, SEEK_SET ));
+    CPL_IGNORE_RET_VAL(VSIFReadL( abyHeader, 128, 1, fpImage ));
 
     // Upper Left X
-    float f32Val;
-
-    f32Val = (float) (adfGeoTransform[0] + 0.5 * adfGeoTransform[1]);
+    float f32Val = static_cast<float>(
+        adfGeoTransform[0] + 0.5 * adfGeoTransform[1] );
     memcpy( abyHeader + 112, &f32Val, 4 );
-    
+
     // Upper Left Y
-    f32Val = (float) (adfGeoTransform[3] + 0.5 * adfGeoTransform[5]);
+    f32Val = static_cast<float>(
+        adfGeoTransform[3] + 0.5 * adfGeoTransform[5] );
     memcpy( abyHeader + 116, &f32Val, 4 );
-    
+
     // width of pixel
-    f32Val = (float) adfGeoTransform[1];
+    f32Val = static_cast<float>( adfGeoTransform[1] );
     memcpy( abyHeader + 120, &f32Val, 4 );
-    
+
     // height of pixel
-    f32Val = (float) fabs(adfGeoTransform[5]);
+    f32Val = static_cast<float>( std::abs( adfGeoTransform[5] ) );
     memcpy( abyHeader + 124, &f32Val, 4 );
 
-    if( VSIFSeekL( fpImage, 0, SEEK_SET ) != 0 
+    if( VSIFSeekL( fpImage, 0, SEEK_SET ) != 0
         || VSIFWriteL( abyHeader, 128, 1, fpImage ) != 1 )
     {
         CPLError( CE_Failure, CPLE_FileIO,
                   "File IO Error writing header with new geotransform." );
         return CE_Failure;
     }
-    else
-        return CE_None;
+
+    return CE_None;
 }
 
 /************************************************************************/
@@ -689,8 +698,8 @@ const char *LANDataset::GetProjectionRef()
 
     if( pszProjection != NULL && strlen(pszPamPrj) == 0 )
         return pszProjection;
-    else
-        return pszPamPrj;
+
+    return pszPamPrj;
 }
 
 /************************************************************************/
@@ -702,11 +711,11 @@ CPLErr LANDataset::SetProjection( const char * pszWKT )
 {
     unsigned char abyHeader[128];
 
-    VSIFSeekL( fpImage, 0, SEEK_SET );
-    VSIFReadL( abyHeader, 128, 1, fpImage );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( fpImage, 0, SEEK_SET ));
+    CPL_IGNORE_RET_VAL(VSIFReadL( abyHeader, 128, 1, fpImage ));
 
     OGRSpatialReference oSRS( pszWKT );
-    
+
     GUInt16 nProjCode = 0;
 
     if( oSRS.IsGeographic() )
@@ -715,72 +724,72 @@ CPLErr LANDataset::SetProjection( const char * pszWKT )
     else if( oSRS.GetUTMZone() != 0 )
         nProjCode = 1;
 
-    // Too bad we have no way of recognising state plane projections. 
+    // Too bad we have no way of recognising state plane projections.
 
-    else 
+    else
     {
-        const char *pszProjection = oSRS.GetAttrValue("PROJECTION");
+        const char *l_pszProjection = oSRS.GetAttrValue("PROJECTION");
 
-        if( pszProjection == NULL )
+        if( l_pszProjection == NULL )
             ;
-        else if( EQUAL(pszProjection,
+        else if( EQUAL(l_pszProjection,
                        SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
             nProjCode = 3;
-        else if( EQUAL(pszProjection,
+        else if( EQUAL(l_pszProjection,
                        SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP) )
             nProjCode = 4;
-        else if( EQUAL(pszProjection,
+        else if( EQUAL(l_pszProjection,
                        SRS_PT_MERCATOR_1SP) )
             nProjCode = 5;
-        else if( EQUAL(pszProjection,
+        else if( EQUAL(l_pszProjection,
                        SRS_PT_POLAR_STEREOGRAPHIC) )
             nProjCode = 6;
-        else if( EQUAL(pszProjection,
+        else if( EQUAL(l_pszProjection,
                        SRS_PT_POLYCONIC) )
             nProjCode = 7;
-        else if( EQUAL(pszProjection,
+        else if( EQUAL(l_pszProjection,
                        SRS_PT_EQUIDISTANT_CONIC) )
             nProjCode = 8;
-        else if( EQUAL(pszProjection,
+        else if( EQUAL(l_pszProjection,
                        SRS_PT_TRANSVERSE_MERCATOR) )
             nProjCode = 9;
-        else if( EQUAL(pszProjection,
+        else if( EQUAL(l_pszProjection,
                        SRS_PT_STEREOGRAPHIC) )
             nProjCode = 10;
-        else if( EQUAL(pszProjection,
+        else if( EQUAL(l_pszProjection,
                        SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
             nProjCode = 11;
-        else if( EQUAL(pszProjection,
+        else if( EQUAL(l_pszProjection,
                        SRS_PT_AZIMUTHAL_EQUIDISTANT) )
             nProjCode = 12;
-        else if( EQUAL(pszProjection,
+        else if( EQUAL(l_pszProjection,
                        SRS_PT_GNOMONIC) )
             nProjCode = 13;
-        else if( EQUAL(pszProjection,
+        else if( EQUAL(l_pszProjection,
                        SRS_PT_ORTHOGRAPHIC) )
             nProjCode = 14;
         // we don't have GVNP.
-        else if( EQUAL(pszProjection,
+        else if( EQUAL(l_pszProjection,
                        SRS_PT_SINUSOIDAL) )
             nProjCode = 16;
-        else if( EQUAL(pszProjection,
+        else if( EQUAL(l_pszProjection,
                        SRS_PT_EQUIRECTANGULAR) )
             nProjCode = 17;
-        else if( EQUAL(pszProjection,
+        else if( EQUAL(l_pszProjection,
                        SRS_PT_MILLER_CYLINDRICAL) )
             nProjCode = 18;
-        else if( EQUAL(pszProjection,
+        else if( EQUAL(l_pszProjection,
                        SRS_PT_VANDERGRINTEN) )
             nProjCode = 19;
-        else if( EQUAL(pszProjection,
+        else if( EQUAL(l_pszProjection,
                        SRS_PT_HOTINE_OBLIQUE_MERCATOR) )
             nProjCode = 20;
     }
 
     memcpy( abyHeader + 88, &nProjCode, 2 );
 
-    VSIFSeekL( fpImage, 0, SEEK_SET );
-    VSIFWriteL( abyHeader, 128, 1, fpImage );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( fpImage, 0, SEEK_SET ));
+    CPL_IGNORE_RET_VAL(VSIFWriteL( abyHeader, 128, 1, fpImage ));
 
     return GDALPamDataset::SetProjection( pszWKT );
 }
@@ -792,10 +801,8 @@ CPLErr LANDataset::SetProjection( const char * pszWKT )
 char **LANDataset::GetFileList()
 
 {
-    char **papszFileList = NULL;
-
-    // Main data file, etc. 
-    papszFileList = GDALPamDataset::GetFileList();
+    // Main data file, etc.
+    char **papszFileList = GDALPamDataset::GetFileList();
 
     if( strlen(osSTAFilename) > 0 )
         papszFileList = CSLAddString( papszFileList, osSTAFilename );
@@ -833,19 +840,17 @@ void LANDataset::CheckForStatistics()
 /*      Read it one band at a time.                                     */
 /* -------------------------------------------------------------------- */
     GByte abyBandInfo[1152];
-    int iBand;
 
-    for( iBand = 0; iBand < nBands; iBand++ )
+    for( int iBand = 0; iBand < nBands; iBand++ )
     {
         if( VSIFReadL( abyBandInfo, 1152, 1, fpSTA ) != 1 )
             break;
 
-        int nBandNumber = abyBandInfo[7];
+        const int nBandNumber = abyBandInfo[7];
         GDALRasterBand *poBand = GetRasterBand(nBandNumber);
         if( poBand == NULL )
             break;
 
-        float fMean, fStdDev;
         GInt16 nMin, nMax;
 
         if( poBand->GetRasterDataType() != GDT_Byte )
@@ -860,16 +865,17 @@ void LANDataset::CheckForStatistics()
             nMin = abyBandInfo[9];
             nMax = abyBandInfo[8];
         }
-        
+
+        float fMean, fStdDev;
         memcpy( &fMean, abyBandInfo + 12, 4 );
         memcpy( &fStdDev, abyBandInfo + 24, 4 );
         CPL_LSBPTR32( &fMean );
         CPL_LSBPTR32( &fStdDev );
-        
+
         poBand->SetStatistics( nMin, nMax, fMean, fStdDev );
     }
-    
-    VSIFCloseL( fpSTA );
+
+    CPL_IGNORE_RET_VAL(VSIFCloseL( fpSTA ));
 }
 
 /************************************************************************/
@@ -894,10 +900,7 @@ GDALDataset *LANDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Try to create the file.                                         */
 /* -------------------------------------------------------------------- */
-    VSILFILE	*fp;
-
-    fp = VSIFOpenL( pszFilename, "wb" );
-
+    VSILFILE *fp = VSIFOpenL( pszFilename, "wb" );
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
@@ -910,14 +913,13 @@ GDALDataset *LANDataset::Create( const char * pszFilename,
 /*      Write out the header.                                           */
 /* -------------------------------------------------------------------- */
     unsigned char abyHeader[128];
-    GInt16  n16Val;
-    GInt32  n32Val;
 
     memset( abyHeader, 0, sizeof(abyHeader) );
-    
+
     memcpy( abyHeader + 0, "HEAD74", 6 );
 
     // Pixel type
+    GInt16  n16Val;
     if( eType == GDT_Byte ) // do we want 4bit?
         n16Val = 0;
     else
@@ -931,9 +933,9 @@ GDALDataset *LANDataset::Create( const char * pszFilename,
     // Unknown (6)
 
     // Width
-    n32Val = nXSize;
+    GInt32  n32Val = nXSize;
     memcpy( abyHeader + 16, &n32Val, 4 );
-    
+
     // Height
     n32Val = nYSize;
     memcpy( abyHeader + 20, &n32Val, 4 );
@@ -947,7 +949,7 @@ GDALDataset *LANDataset::Create( const char * pszFilename,
     n16Val = 0;
     memcpy( abyHeader + 88, &n16Val, 2 );
 
-    // Classes in coverage 
+    // Classes in coverage
     n16Val = 0;
     memcpy( abyHeader + 90, &n16Val, 2 );
 
@@ -958,28 +960,26 @@ GDALDataset *LANDataset::Create( const char * pszFilename,
     memcpy( abyHeader + 106, &n16Val, 2 );
 
     // Pixel Area
-    float f32Val;
-
-    f32Val = 0.0f;
+    float f32Val = 0.0f;
     memcpy( abyHeader + 108, &f32Val, 4 );
 
     // Upper Left X
     f32Val = 0.5f;
     memcpy( abyHeader + 112, &f32Val, 4 );
-    
+
     // Upper Left Y
     f32Val = (float) (nYSize - 0.5);
     memcpy( abyHeader + 116, &f32Val, 4 );
-    
+
     // width of pixel
     f32Val = 1.0f;
     memcpy( abyHeader + 120, &f32Val, 4 );
-    
+
     // height of pixel
     f32Val = 1.0f;
     memcpy( abyHeader + 124, &f32Val, 4 );
 
-    VSIFWriteL( abyHeader, sizeof(abyHeader), 1, fp );
+    CPL_IGNORE_RET_VAL(VSIFWriteL( abyHeader, sizeof(abyHeader), 1, fp ));
 
 /* -------------------------------------------------------------------- */
 /*      Extend the file to the target size.                             */
@@ -987,20 +987,21 @@ GDALDataset *LANDataset::Create( const char * pszFilename,
     vsi_l_offset nImageBytes;
 
     if( eType != GDT_Byte )
-        nImageBytes = nXSize * (vsi_l_offset) nYSize * 2;
+        nImageBytes = nXSize * static_cast<vsi_l_offset>( nYSize ) * 2;
     else
-        nImageBytes = nXSize * (vsi_l_offset) nYSize;
+        nImageBytes = nXSize * static_cast<vsi_l_offset>( nYSize );
 
     memset( abyHeader, 0, sizeof(abyHeader) );
-    
+
     while( nImageBytes > 0 )
     {
-        vsi_l_offset nWriteThisTime = MIN(nImageBytes,sizeof(abyHeader));
-        
-        if( VSIFWriteL( abyHeader, 1, (size_t)nWriteThisTime, fp ) 
+        const vsi_l_offset nWriteThisTime
+            = std::min( static_cast<size_t>( nImageBytes ), sizeof(abyHeader) );
+
+        if( VSIFWriteL( abyHeader, 1, (size_t)nWriteThisTime, fp )
             != nWriteThisTime )
         {
-            VSIFCloseL( fp );
+            CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
             CPLError( CE_Failure, CPLE_FileIO,
                       "Failed to write whole Istar file." );
             return NULL;
@@ -1008,7 +1009,12 @@ GDALDataset *LANDataset::Create( const char * pszFilename,
         nImageBytes -= nWriteThisTime;
     }
 
-    VSIFCloseL( fp );
+    if( VSIFCloseL( fp ) != 0 )
+    {
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Failed to write whole Istar file." );
+        return NULL;
+    }
 
     return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
 }
@@ -1020,25 +1026,20 @@ GDALDataset *LANDataset::Create( const char * pszFilename,
 void GDALRegister_LAN()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "LAN" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "LAN" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "LAN" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Erdas .LAN/.GIS" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#LAN" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte Int16" );
-        
-        poDriver->pfnOpen = LANDataset::Open;
-        poDriver->pfnCreate = LANDataset::Create;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "LAN" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Erdas .LAN/.GIS" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#LAN" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte Int16" );
+
+    poDriver->pfnOpen = LANDataset::Open;
+    poDriver->pfnCreate = LANDataset::Create;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/raw/lcpdataset.cpp b/frmts/raw/lcpdataset.cpp
index ac48c08..3ae6426 100644
--- a/frmts/raw/lcpdataset.cpp
+++ b/frmts/raw/lcpdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: lcpdataset.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: lcpdataset.cpp 32883 2016-01-09 18:24:40Z rouault $
  *
  * Project:  LCP Driver
  * Purpose:  FARSITE v.4 Landscape file (.lcp) reader for GDAL
@@ -29,22 +29,19 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "rawdataset.h"
 #include "cpl_port.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
 #include "ogr_spatialref.h"
+#include "rawdataset.h"
 
-CPL_CVSID("$Id: lcpdataset.cpp 28053 2014-12-04 09:31:07Z rouault $");
-
-CPL_C_START
-void    GDALRegister_LCP(void);
-CPL_C_END
+CPL_CVSID("$Id: lcpdataset.cpp 32883 2016-01-09 18:24:40Z rouault $");
 
-#define LCP_HEADER_SIZE 7316
-#define LCP_MAX_BANDS   10
-#define LCP_MAX_PATH    256
-#define LCP_MAX_DESC    512
-#define LCP_MAX_CLASSES 100
+static const size_t LCP_HEADER_SIZE = 7316;
+static const int LCP_MAX_BANDS = 10;
+static const int LCP_MAX_PATH = 256;
+static const int LCP_MAX_DESC = 512;
+static const int LCP_MAX_CLASSES = 100;
 
 /************************************************************************/
 /* ==================================================================== */
@@ -88,10 +85,10 @@ class LCPDataset : public RawDataset
 /*                            LCPDataset()                             */
 /************************************************************************/
 
-LCPDataset::LCPDataset()
+LCPDataset::LCPDataset() :
+    fpImage(NULL),
+    pszProjection(CPLStrdup( "" ))
 {
-    fpImage = NULL;
-    pszProjection = CPLStrdup( "" );
     bHaveProjection = FALSE;
 }
 
@@ -104,7 +101,12 @@ LCPDataset::~LCPDataset()
 {
     FlushCache();
     if( fpImage != NULL )
-        VSIFCloseL( fpImage );
+    {
+        if( VSIFCloseL( fpImage ) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        }
+    }
     CPLFree(pszProjection);
 }
 
@@ -196,7 +198,7 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( !Identify( poOpenInfo ) )
         return NULL;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
@@ -210,36 +212,26 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    LCPDataset  *poDS;
-    VSILFILE        *fpImage;
-
-    fpImage = VSIFOpenL(poOpenInfo->pszFilename, "rb");
+    VSILFILE *fpImage = VSIFOpenL(poOpenInfo->pszFilename, "rb");
     if (fpImage == NULL)
         return NULL;
 
-    poDS = new LCPDataset();
+    LCPDataset  *poDS = new LCPDataset();
     poDS->fpImage = fpImage;
 
 /* -------------------------------------------------------------------- */
 /*      Read the header and extract some information.                   */
 /* -------------------------------------------------------------------- */
-   int bHaveCrownFuels, bHaveGroundFuels;
-   int nBands, i;
-   long nWidth = -1, nHeight = -1;
-   int nTemp, nTemp2;
-   char szTemp[32];
-   char* pszList;
-
-   VSIFSeekL( poDS->fpImage, 0, SEEK_SET );
-   if (VSIFReadL( poDS->pachHeader, 1, LCP_HEADER_SIZE, poDS->fpImage ) != LCP_HEADER_SIZE)
+   if (VSIFSeekL( poDS->fpImage, 0, SEEK_SET ) < 0 ||
+       VSIFReadL( poDS->pachHeader, 1, LCP_HEADER_SIZE, poDS->fpImage ) != LCP_HEADER_SIZE)
    {
        CPLError(CE_Failure, CPLE_FileIO, "File too short");
        delete poDS;
        return NULL;
    }
 
-   nWidth = CPL_LSBINT32PTR (poDS->pachHeader + 4164);
-   nHeight = CPL_LSBINT32PTR (poDS->pachHeader + 4168);
+   int nWidth = CPL_LSBINT32PTR (poDS->pachHeader + 4164);
+   int nHeight = CPL_LSBINT32PTR (poDS->pachHeader + 4168);
 
    poDS->nRasterXSize = nWidth;
    poDS->nRasterYSize = nHeight;
@@ -252,10 +244,11 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
 
    // crown fuels = canopy height, canopy base height, canopy bulk density
    // 21 = have them, 20 = don't have them
-   bHaveCrownFuels = ( CPL_LSBINT32PTR (poDS->pachHeader + 0) - 20 );
+   const bool bHaveCrownFuels = CPL_TO_BOOL( CPL_LSBINT32PTR (poDS->pachHeader + 0) - 20 );
    // ground fuels = duff loading, coarse woody
-   bHaveGroundFuels = ( CPL_LSBINT32PTR (poDS->pachHeader + 4) - 20 );
+   const bool bHaveGroundFuels = CPL_TO_BOOL( CPL_LSBINT32PTR (poDS->pachHeader + 4) - 20 );
 
+   int nBands;
    if( bHaveCrownFuels )
    {
        if( bHaveGroundFuels )
@@ -273,8 +266,9 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
 
    // add dataset-level metadata
 
-   nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 8);
-   sprintf(szTemp, "%d", nTemp);
+   int nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 8);
+   char szTemp[32];
+   snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
    poDS->SetMetadataItem( "LATITUDE", szTemp );
 
    nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 4204);
@@ -297,7 +291,7 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
 
    if (nWidth > INT_MAX / iPixelSize)
    {
-       CPLError( CE_Failure, CPLE_AppDefined,  "Int overflow occured");
+       CPLError( CE_Failure, CPLE_AppDefined,  "Int overflow occurred");
        delete poDS;
        return NULL;
    }
@@ -308,16 +302,14 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
    bNativeOrder = FALSE;
 #endif
 
-   pszList = (char*)CPLMalloc(2048);
+   char* pszList = reinterpret_cast<char *>( CPLMalloc(2048) );
    pszList[0] = '\0';
 
    for( int iBand = 1; iBand <= nBands; iBand++ )
    {
-        GDALRasterBand  *poBand = NULL;
-
-        poBand = new RawRasterBand(
-                     poDS, iBand, poDS->fpImage, LCP_HEADER_SIZE + ((iBand-1)*2),
-                     iPixelSize, iPixelSize * nWidth, GDT_Int16, bNativeOrder, TRUE );
+        GDALRasterBand  *poBand = new RawRasterBand(
+            poDS, iBand, poDS->fpImage, LCP_HEADER_SIZE + ((iBand-1)*2),
+            iPixelSize, iPixelSize * nWidth, GDT_Int16, bNativeOrder, TRUE );
 
         poDS->SetBand(iBand, poBand);
 
@@ -326,7 +318,7 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
            poBand->SetDescription("Elevation");
 
            nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4224);
-           sprintf(szTemp, "%d", nTemp);
+           snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "ELEVATION_UNIT", szTemp );
 
            if ( nTemp == 0 )
@@ -335,15 +327,15 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
               poBand->SetMetadataItem( "ELEVATION_UNIT_NAME", "Feet" );
 
            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 44);
-           sprintf(szTemp, "%d", nTemp);
+           snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "ELEVATION_MIN", szTemp );
 
            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 48);
-           sprintf(szTemp, "%d", nTemp);
+           snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "ELEVATION_MAX", szTemp );
 
            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 52);
-           sprintf(szTemp, "%d", nTemp);
+           snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "ELEVATION_NUM_CLASSES", szTemp );
 
            *(poDS->pachHeader + 4244 + 255) = '\0';
@@ -355,7 +347,7 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
            poBand->SetDescription("Slope");
 
            nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4226);
-           sprintf(szTemp, "%d", nTemp);
+           snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "SLOPE_UNIT", szTemp );
 
            if ( nTemp == 0 )
@@ -364,15 +356,15 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
               poBand->SetMetadataItem( "SLOPE_UNIT_NAME", "Percent" );
 
            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 456);
-           sprintf(szTemp, "%d", nTemp);
+           snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "SLOPE_MIN", szTemp );
 
            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 460);
-           sprintf(szTemp, "%d", nTemp);
+           snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "SLOPE_MAX", szTemp );
 
            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 464);
-           sprintf(szTemp, "%d", nTemp);
+           snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "SLOPE_NUM_CLASSES", szTemp );
 
            *(poDS->pachHeader + 4500 + 255) = '\0';
@@ -384,7 +376,7 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
            poBand->SetDescription("Aspect");
 
            nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4228);
-           sprintf(szTemp, "%d", nTemp);
+           snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "ASPECT_UNIT", szTemp );
 
            if ( nTemp == 0 )
@@ -395,15 +387,15 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
               poBand->SetMetadataItem( "ASPECT_UNIT_NAME", "Azimuth degrees" );
 
            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 868);
-           sprintf(szTemp, "%d", nTemp);
+           snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "ASPECT_MIN", szTemp );
 
            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 872);
-           sprintf(szTemp, "%d", nTemp);
+           snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "ASPECT_MAX", szTemp );
 
            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 876);
-           sprintf(szTemp, "%d", nTemp);
+           snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "ASPECT_NUM_CLASSES", szTemp );
 
            *(poDS->pachHeader + 4756 + 255) = '\0';
@@ -412,12 +404,11 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
            break;
 
         case 4:
-           int nMinFM, nMaxFM;
-
+        {
            poBand->SetDescription("Fuel models");
 
            nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4230);
-           sprintf(szTemp, "%d", nTemp);
+           snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "FUEL_MODEL_OPTION", szTemp );
 
            if ( nTemp == 0 )
@@ -429,24 +420,24 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
            if ( nTemp == 3 )
               poBand->SetMetadataItem( "FUEL_MODEL_OPTION_DESC", "custom models AND conversion file needed" );
 
-           nMinFM = CPL_LSBINT32PTR (poDS->pachHeader + 1280);
-           sprintf(szTemp, "%d", nMinFM);
+           const int nMinFM = CPL_LSBINT32PTR (poDS->pachHeader + 1280);
+           snprintf( szTemp, sizeof(szTemp), "%d", nMinFM);
            poBand->SetMetadataItem( "FUEL_MODEL_MIN", szTemp );
 
-           nMaxFM = CPL_LSBINT32PTR (poDS->pachHeader + 1284);
-           sprintf(szTemp, "%d", nMaxFM);
+           const int nMaxFM = CPL_LSBINT32PTR (poDS->pachHeader + 1284);
+           snprintf( szTemp, sizeof(szTemp), "%d", nMaxFM);
            poBand->SetMetadataItem( "FUEL_MODEL_MAX", szTemp );
 
            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 1288);
-           sprintf(szTemp, "%d", nTemp);
+           snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "FUEL_MODEL_NUM_CLASSES", szTemp );
 
            if (nTemp > 0 && nTemp <= 100) {
               strcpy(pszList, "");
-              for ( i = 0; i <= nTemp; i++ ) {
-                  nTemp2 = CPL_LSBINT32PTR (poDS->pachHeader + (1292+(i*4))) ;
+              for ( int i = 0; i <= nTemp; i++ ) {
+                  const int nTemp2 = CPL_LSBINT32PTR (poDS->pachHeader + (1292+(i*4))) ;
                   if ( nTemp2 >= nMinFM && nTemp2 <= nMaxFM ) {
-                     sprintf(szTemp, "%d", nTemp2);
+                     snprintf( szTemp, sizeof(szTemp), "%d", nTemp2);
                      strcat(pszList, szTemp);
                      if (i < (nTemp) )
                         strcat(pszList, ",");
@@ -459,12 +450,12 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
            poBand->SetMetadataItem( "FUEL_MODEL_FILE", poDS->pachHeader + 5012 );
 
            break;
-
+        }
         case 5:
            poBand->SetDescription("Canopy cover");
 
            nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4232);
-           sprintf(szTemp, "%d", nTemp);
+           snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "CANOPY_COV_UNIT", szTemp );
 
            if ( nTemp == 0 )
@@ -473,15 +464,15 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
               poBand->SetMetadataItem( "CANOPY_COV_UNIT_NAME", "Percent" );
 
            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 1692);
-           sprintf(szTemp, "%d", nTemp);
+           snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "CANOPY_COV_MIN", szTemp );
 
            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 1696);
-           sprintf(szTemp, "%d", nTemp);
+           snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "CANOPY_COV_MAX", szTemp );
 
            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 1700);
-           sprintf(szTemp, "%d", nTemp);
+           snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "CANOPY_COV_NUM_CLASSES", szTemp );
 
            *(poDS->pachHeader + 5268 + 255) = '\0';
@@ -494,7 +485,7 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
               poBand->SetDescription("Canopy height");
 
               nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4234);
-              sprintf(szTemp, "%d", nTemp);
+              snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "CANOPY_HT_UNIT", szTemp );
 
               if ( nTemp == 1 )
@@ -507,15 +498,15 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
                  poBand->SetMetadataItem( "CANOPY_HT_UNIT_NAME", "Feet x 10" );
 
               nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2104);
-              sprintf(szTemp, "%d", nTemp);
+              snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "CANOPY_HT_MIN", szTemp );
 
               nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2108);
-              sprintf(szTemp, "%d", nTemp);
+              snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "CANOPY_HT_MAX", szTemp );
 
               nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2112);
-              sprintf(szTemp, "%d", nTemp);
+              snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "CANOPY_HT_NUM_CLASSES", szTemp );
 
               *(poDS->pachHeader + 5524 + 255) = '\0';
@@ -525,7 +516,7 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
               poBand->SetDescription("Duff");
 
               nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4240);
-              sprintf(szTemp, "%d", nTemp);
+              snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "DUFF_UNIT", szTemp );
 
               if ( nTemp == 1 )
@@ -534,15 +525,15 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
                  poBand->SetMetadataItem( "DUFF_UNIT_NAME", "t/ac" );
 
               nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3340);
-              sprintf(szTemp, "%d", nTemp);
+              snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "DUFF_MIN", szTemp );
 
               nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3344);
-              sprintf(szTemp, "%d", nTemp);
+              snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "DUFF_MAX", szTemp );
 
               nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3348);
-              sprintf(szTemp, "%d", nTemp);
+              snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "DUFF_NUM_CLASSES", szTemp );
 
               *(poDS->pachHeader + 6292 + 255) = '\0';
@@ -555,7 +546,7 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
               poBand->SetDescription("Canopy base height");
 
               nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4236);
-              sprintf(szTemp, "%d", nTemp);
+              snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "CBH_UNIT", szTemp );
 
               if ( nTemp == 1 )
@@ -568,15 +559,15 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
                  poBand->SetMetadataItem( "CBH_UNIT_NAME", "Feet x 10" );
 
               nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2516);
-              sprintf(szTemp, "%d", nTemp);
+              snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "CBH_MIN", szTemp );
 
               nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2520);
-              sprintf(szTemp, "%d", nTemp);
+              snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "CBH_MAX", szTemp );
 
               nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2524);
-              sprintf(szTemp, "%d", nTemp);
+              snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "CBH_NUM_CLASSES", szTemp );
 
               *(poDS->pachHeader + 5780 + 255) = '\0';
@@ -586,7 +577,7 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
               poBand->SetDescription("Coarse woody debris");
 
               nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4242);
-              sprintf(szTemp, "%d", nTemp);
+              snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "CWD_OPTION", szTemp );
 
               //if ( nTemp == 1 )
@@ -595,15 +586,15 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
               //   poBand->SetMetadataItem( "CWD_UNIT_DESC", "?" );
 
               nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3752);
-              sprintf(szTemp, "%d", nTemp);
+              snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "CWD_MIN", szTemp );
 
               nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3756);
-              sprintf(szTemp, "%d", nTemp);
+              snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "CWD_MAX", szTemp );
 
               nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3760);
-              sprintf(szTemp, "%d", nTemp);
+              snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "CWD_NUM_CLASSES", szTemp );
 
               *(poDS->pachHeader + 6548 + 255) = '\0';
@@ -615,7 +606,7 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
            poBand->SetDescription("Canopy bulk density");
 
            nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4238);
-           sprintf(szTemp, "%d", nTemp);
+           snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "CBD_UNIT", szTemp );
 
            if ( nTemp == 1 )
@@ -628,15 +619,15 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
               poBand->SetMetadataItem( "CBD_UNIT_NAME", "lb/ft^3 x 1000" );
 
            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2928);
-           sprintf(szTemp, "%d", nTemp);
+           snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "CBD_MIN", szTemp );
 
            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2932);
-           sprintf(szTemp, "%d", nTemp);
+           snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "CBD_MAX", szTemp );
 
            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2936);
-           sprintf(szTemp, "%d", nTemp);
+           snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "CBD_NUM_CLASSES", szTemp );
 
            *(poDS->pachHeader + 6036 + 255) = '\0';
@@ -648,7 +639,7 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
            poBand->SetDescription("Duff");
 
            nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4240);
-           sprintf(szTemp, "%d", nTemp);
+           snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "DUFF_UNIT", szTemp );
 
            if ( nTemp == 1 )
@@ -657,15 +648,15 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
               poBand->SetMetadataItem( "DUFF_UNIT_NAME", "t/ac" );
 
            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3340);
-           sprintf(szTemp, "%d", nTemp);
+           snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "DUFF_MIN", szTemp );
 
            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3344);
-           sprintf(szTemp, "%d", nTemp);
+           snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "DUFF_MAX", szTemp );
 
            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3348);
-           sprintf(szTemp, "%d", nTemp);
+           snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "DUFF_NUM_CLASSES", szTemp );
 
            *(poDS->pachHeader + 6292 + 255) = '\0';
@@ -677,7 +668,7 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
            poBand->SetDescription("Coarse woody debris");
 
            nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4242);
-           sprintf(szTemp, "%d", nTemp);
+           snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "CWD_OPTION", szTemp );
 
            //if ( nTemp == 1 )
@@ -686,15 +677,15 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
            //   poBand->SetMetadataItem( "CWD_UNIT_DESC", "?" );
 
            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3752);
-           sprintf(szTemp, "%d", nTemp);
+           snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "CWD_MIN", szTemp );
 
            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3756);
-           sprintf(szTemp, "%d", nTemp);
+           snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "CWD_MAX", szTemp );
 
            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3760);
-           sprintf(szTemp, "%d", nTemp);
+           snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "CWD_NUM_CLASSES", szTemp );
 
            *(poDS->pachHeader + 6548 + 255) = '\0';
@@ -703,17 +694,15 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
            break;
         }
    }
-   
+
 /* -------------------------------------------------------------------- */
 /*      Try to read projection file.                                    */
 /* -------------------------------------------------------------------- */
-    char        *pszDirname, *pszBasename;
-    VSIStatBufL   sStatBuf;
-
-    pszDirname = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
-    pszBasename = CPLStrdup(CPLGetBasename(poOpenInfo->pszFilename));
+    char *pszDirname = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
+    char *pszBasename = CPLStrdup(CPLGetBasename(poOpenInfo->pszFilename));
 
     poDS->osPrjFilename = CPLFormFilename( pszDirname, pszBasename, "prj" );
+    VSIStatBufL   sStatBuf;
     int nRet = VSIStatL( poDS->osPrjFilename, &sStatBuf );
 
     if( nRet != 0 && VSIIsCaseSensitiveFS(poDS->osPrjFilename))
@@ -724,13 +713,11 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
 
     if( nRet == 0 )
     {
-        OGRSpatialReference     oSRS;
-
         char** papszPrj = CSLLoad( poDS->osPrjFilename );
 
-        CPLDebug( "LCP", "Loaded SRS from %s", 
-                  poDS->osPrjFilename.c_str() );
+        CPLDebug( "LCP", "Loaded SRS from %s", poDS->osPrjFilename.c_str() );
 
+        OGRSpatialReference oSRS;
         if( oSRS.importFromESRI( papszPrj ) == OGRERR_NONE )
         {
             CPLFree( poDS->pszProjection );
@@ -797,18 +784,18 @@ CPLErr LCPDataset::ClassifyBandData( GDALRasterBand *poBand,
         return CE_Failure;
     }
 
-    int nXSize = poBand->GetXSize();
-    int nYSize = poBand->GetYSize();
+    const int nXSize = poBand->GetXSize();
+    const int nYSize = poBand->GetYSize();
     double dfMax, dfDummy;
     poBand->GetStatistics( FALSE, TRUE, &dfDummy, &dfMax, &dfDummy, &dfDummy );
 
-    int nSpan = (int)dfMax;
+    const int nSpan = static_cast<int>( dfMax );
     GInt16 *panValues = (GInt16*)CPLMalloc( sizeof( GInt16 ) * nXSize );
     GByte *pabyFlags = (GByte*)CPLMalloc( sizeof( GByte ) * nSpan + 1 );
     memset( pabyFlags, 0, nSpan + 1 );
 
     int nFound = 0;
-    int bTooMany = FALSE;
+    bool bTooMany = false;
     CPLErr eErr = CE_None;
     for( int iLine = 0; iLine < nYSize; iLine++ )
     {
@@ -827,7 +814,7 @@ CPLErr LCPDataset::ClassifyBandData( GDALRasterBand *poBand,
                                  "band %d.  Not 'classifying' the data.",
                                  poBand->GetBand() );
                 nFound = -1;
-                bTooMany = TRUE;
+                bTooMany = true;
                 break;
             }
             if( bTooMany )
@@ -847,8 +834,7 @@ CPLErr LCPDataset::ClassifyBandData( GDALRasterBand *poBand,
     ** offsets, or making it a 1-based array instead of 0-based.
     */
     panClasses[0] = 0;
-    int nIndex = 1;
-    for( int j = 0; j < nSpan + 1; j++ )
+    for( int j = 0, nIndex = 1; j < nSpan + 1; j++ )
     {
         if( pabyFlags[j] == 1 )
         {
@@ -856,8 +842,8 @@ CPLErr LCPDataset::ClassifyBandData( GDALRasterBand *poBand,
         }
     }
     *pnNumClasses = nFound;
-    CPLFree( (void*)pabyFlags );
-    CPLFree( (void*)panValues );
+    CPLFree( reinterpret_cast<void *>( pabyFlags ) );
+    CPLFree( reinterpret_cast<void *>( panValues ) );
 
     return eErr;
 }
@@ -873,14 +859,10 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
                                      void * pProgressData )
 
 {
-
-    int  nBands = poSrcDS->GetRasterCount();
-    int  nXSize = poSrcDS->GetRasterXSize();
-    int  nYSize = poSrcDS->GetRasterYSize();
-
 /* -------------------------------------------------------------------- */
 /*      Verify input options.                                           */
 /* -------------------------------------------------------------------- */
+    const int nBands = poSrcDS->GetRasterCount();
     if( nBands != 5 && nBands != 7 && nBands != 8 && nBands != 10 )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
@@ -924,10 +906,6 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
     ** default units every chance we get.
     */
     GInt16 panMetadata[LCP_MAX_BANDS];
-    int i;
-    GInt32 nTemp;
-    double dfTemp;
-    const char *pszTemp;
 
     panMetadata[0] = 0; /* ELEVATION_UNIT */
     panMetadata[1] = 0; /* SLOPE_UNIT */
@@ -939,9 +917,11 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
     panMetadata[7] = 3; /* CBD_UNIT */
     panMetadata[8] = 1; /* DUFF_UNIT */
     panMetadata[9] = 0; /* CWD_OPTION */
+
     /* Check the units/options for user overrides */
-    pszTemp = CSLFetchNameValueDef( papszOptions, "ELEVATION_UNIT", "METERS" );
-    if( EQUALN( pszTemp, "METER", 5 ) )
+    const char *pszTemp
+        = CSLFetchNameValueDef( papszOptions, "ELEVATION_UNIT", "METERS" );
+    if( STARTS_WITH_CI(pszTemp, "METER") )
     {
         panMetadata[0] = 0;
     }
@@ -1143,24 +1123,17 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
             return NULL;
         }
 
-        if( bHaveGroundFuels )
-        {
-            panMetadata[9] = 1;
-        }
-        else
-        {
-            panMetadata[9] = 0;
-        }
+        panMetadata[9] = 1;
     }
 
     /*
     ** Calculate the stats for each band.  The binary file carries along
     ** these metadata for display purposes(?).
     */
-    int bCalculateStats = CSLFetchBoolean( papszOptions, "CALCULATE_STATS",
-                                           TRUE );
-    int bClassifyData = CSLFetchBoolean( papszOptions, "CLASSIFY_DATA",
-                                         TRUE );
+    bool bCalculateStats = CPL_TO_BOOL(CSLFetchBoolean( papszOptions, "CALCULATE_STATS",
+                                            TRUE ));
+    const bool bClassifyData = CPL_TO_BOOL(CSLFetchBoolean( papszOptions, "CLASSIFY_DATA",
+                                                TRUE ));
     /*
     ** We should have stats if we classify, we'll get them anyway.
     */
@@ -1169,18 +1142,18 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
         CPLError( CE_Warning, CPLE_AppDefined,
                   "Ignoring request to not calculate statistics, " \
                   "because CLASSIFY_DATA was set to ON" );
-        bCalculateStats = TRUE;
+        bCalculateStats = true;
     }
 
     pszTemp = CSLFetchNameValueDef( papszOptions, "LINEAR_UNIT",
                                     "SET_FROM_SRS" );
     int nLinearUnits = 0;
-    int bSetLinearUnits = FALSE;
+    bool bSetLinearUnits = false;
     if( EQUAL( pszTemp, "SET_FROM_SRS" ) )
     {
-        bSetLinearUnits = TRUE;
+        bSetLinearUnits = true;
     }
-    else if( EQUALN( pszTemp, "METER", 5 ) )
+    else if( STARTS_WITH_CI(pszTemp, "METER") )
     {
         nLinearUnits = 0;
     }
@@ -1188,15 +1161,15 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
     {
         nLinearUnits = 1;
     }
-    else if( EQUALN( pszTemp, "KILOMETER", 9 ) )
+    else if( STARTS_WITH_CI(pszTemp, "KILOMETER") )
     {
         nLinearUnits = 2;
     }
-    int bCalculateLatitude = TRUE;
-    int nLatitude;
+    bool bCalculateLatitude = true;
+    int nLatitude = 0;
     if( CSLFetchNameValue( papszOptions, "LATITUDE" ) != NULL )
     {
-        bCalculateLatitude = FALSE;
+        bCalculateLatitude = false;
         nLatitude = atoi( CSLFetchNameValue( papszOptions, "LATITUDE" ) );
         if( nLatitude > 90 || nLatitude < -90 )
         {
@@ -1212,10 +1185,13 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
     */
     double adfSrcGeoTransform[6];
     poSrcDS->GetGeoTransform( adfSrcGeoTransform );
-    OGRSpatialReference oSrcSRS, oDstSRS;
+    OGRSpatialReference oSrcSRS;
     const char *pszWkt = poSrcDS->GetProjectionRef();
     double dfLongitude = 0.0;
     double dfLatitude = 0.0;
+
+    const int nYSize = poSrcDS->GetRasterYSize();
+
     if( !bCalculateLatitude )
     {
         dfLatitude = nLatitude;
@@ -1223,15 +1199,16 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
     else if( !EQUAL( pszWkt, "" ) )
     {
         oSrcSRS.importFromWkt( (char**)&pszWkt );
+        OGRSpatialReference oDstSRS;
         oDstSRS.importFromEPSG( 4269 );
-        OGRCoordinateTransformation *poCT;
-        poCT = (OGRCoordinateTransformation*)
-            OGRCreateCoordinateTransformation( &oSrcSRS, &oDstSRS );
-        int nErr;
+        OGRCoordinateTransformation *poCT
+            = reinterpret_cast<OGRCoordinateTransformation *>(
+                OGRCreateCoordinateTransformation( &oSrcSRS, &oDstSRS ) );
         if( poCT != NULL )
         {
             dfLatitude = adfSrcGeoTransform[3] + adfSrcGeoTransform[5] * nYSize / 2;
-            nErr = (int)poCT->Transform( 1, &dfLongitude, &dfLatitude );
+            const int nErr = static_cast<int>(
+                poCT->Transform( 1, &dfLongitude, &dfLatitude ) );
             if( !nErr )
             {
                 dfLatitude = 0.0;
@@ -1259,13 +1236,12 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
         return NULL;
     }
     /*
-    ** Set the linear units if the metadata item wasn't already set, and we
+    ** Set the linear units if the metadata item was not already set, and we
     ** have an SRS.
     */
     if( bSetLinearUnits && !EQUAL( pszWkt, "" ) )
     {
-        const char *pszUnit;
-        pszUnit = oSrcSRS.GetAttrValue( "UNIT", 0 );
+        const char *pszUnit = oSrcSRS.GetAttrValue( "UNIT", 0 );
         if( pszUnit == NULL )
         {
             if( bStrict )
@@ -1292,7 +1268,7 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
             {
                 nLinearUnits = 1;
             }
-            else if( EQUALN( pszUnit, "kilomet", 7 ) )
+            else if( STARTS_WITH_CI(pszUnit, "kilomet") )
             {
                 nLinearUnits = 2;
             }
@@ -1359,29 +1335,29 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
     ** how these data are used though, so we will implement that at some point
     ** if need be.
     */
-    GDALRasterBand *poBand;
-    double *padfMin = (double*)CPLMalloc( sizeof( double ) * nBands );
-    double *padfMax = (double*)CPLMalloc( sizeof( double ) * nBands );
-    double dfDummy;
-    GInt32 *panFound = (GInt32*)VSIMalloc2( sizeof( GInt32 ), nBands );
-    GInt32 *panClasses = (GInt32*)VSIMalloc3( sizeof( GInt32 ), nBands, LCP_MAX_CLASSES );
+    double *padfMin = reinterpret_cast<double *>( CPLMalloc( sizeof( double ) * nBands ) );
+    double *padfMax = reinterpret_cast<double *>( CPLMalloc( sizeof( double ) * nBands ) );
     /*
     ** Initialize these arrays to zeros
     */
+    GInt32 *panFound = reinterpret_cast<GInt32 *>( VSIMalloc2( sizeof( GInt32 ), nBands ) );
     memset( panFound, 0, sizeof( GInt32 ) * nBands );
+    GInt32 *panClasses = reinterpret_cast<GInt32 *>( VSIMalloc3( sizeof( GInt32 ), nBands, LCP_MAX_CLASSES ) );
     memset( panClasses, 0, sizeof( GInt32 ) * nBands * LCP_MAX_CLASSES );
 
     CPLErr eErr;
     if( bCalculateStats )
     {
-        for( i = 0; i < nBands; i++ )
+
+        for( int i = 0; i < nBands; i++ )
         {
-            poBand = poSrcDS->GetRasterBand( i + 1 );
+            GDALRasterBand *poBand = poSrcDS->GetRasterBand( i + 1 );
+            double dfDummy;
             eErr = poBand->GetStatistics( FALSE, TRUE, &padfMin[i],
                                           &padfMax[i], &dfDummy, &dfDummy );
             if( eErr != CE_None )
             {
-                CPLError( CE_Warning, CPLE_AppDefined, "Failed to properly " \
+                CPLError( CE_Warning, CPLE_AppDefined, "Failed to properly "
                                                        "calculate statistics "
                                                        "on band %d", i );
                 padfMin[i] = 0.0;
@@ -1394,13 +1370,16 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
             {
                 eErr = ClassifyBandData( poBand, panFound+ i,
                                          panClasses + ( i * LCP_MAX_CLASSES ) );
+                if ( eErr != CE_None )
+                {
+                  CPLError( CE_Warning, CPLE_AppDefined,
+                            "Failed to classify band data on band %d.", i );
+                }
             }
         }
     }
 
-    VSILFILE *fp;
-
-    fp = VSIFOpenL( pszFilename, "wb" );
+    VSILFILE *fp = VSIFOpenL( pszFilename, "wb" );
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed, 
@@ -1416,28 +1395,29 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
 /*      Write the header                                                */
 /* -------------------------------------------------------------------- */
 
-    nTemp = bHaveCrownFuels ? 21 : 20;
-    CPL_LSBINT32PTR( &nTemp );
-    VSIFWriteL( &nTemp, 4, 1, fp );
+    GInt32 nTemp = bHaveCrownFuels ? 21 : 20;
+    CPL_LSBPTR32( &nTemp );
+    CPL_IGNORE_RET_VAL(VSIFWriteL( &nTemp, 4, 1, fp ));
     nTemp = bHaveGroundFuels ? 21 : 20;
-    CPL_LSBINT32PTR( &nTemp );
-    VSIFWriteL( &nTemp, 4, 1, fp );
+    CPL_LSBPTR32( &nTemp );
+    CPL_IGNORE_RET_VAL(VSIFWriteL( &nTemp, 4, 1, fp ));
 
-    nTemp = (GInt32)( dfLatitude + 0.5 );
-    CPL_LSBINT32PTR( &nTemp );
-    VSIFWriteL( &nTemp, 4, 1, fp );
+    const int nXSize = poSrcDS->GetRasterXSize();
+    nTemp = static_cast<GInt32>( dfLatitude + 0.5 );
+    CPL_LSBPTR32( &nTemp );
+    CPL_IGNORE_RET_VAL(VSIFWriteL( &nTemp, 4, 1, fp ));
     dfLongitude = adfSrcGeoTransform[0] + adfSrcGeoTransform[1] * nXSize;
     CPL_LSBPTR64( &dfLongitude );
-    VSIFWriteL( &dfLongitude, 8, 1, fp );
+    CPL_IGNORE_RET_VAL(VSIFWriteL( &dfLongitude, 8, 1, fp ));
     dfLongitude = adfSrcGeoTransform[0];
     CPL_LSBPTR64( &dfLongitude );
-    VSIFWriteL( &dfLongitude, 8, 1, fp );
+    CPL_IGNORE_RET_VAL(VSIFWriteL( &dfLongitude, 8, 1, fp ));
     dfLatitude = adfSrcGeoTransform[3];
     CPL_LSBPTR64( &dfLatitude );
-    VSIFWriteL( &dfLatitude, 8, 1, fp );
+    CPL_IGNORE_RET_VAL(VSIFWriteL( &dfLatitude, 8, 1, fp ));
     dfLatitude = adfSrcGeoTransform[3] + adfSrcGeoTransform[5] * nYSize;
     CPL_LSBPTR64( &dfLatitude );
-    VSIFWriteL( &dfLatitude, 8, 1, fp );
+    CPL_IGNORE_RET_VAL(VSIFWriteL( &dfLatitude, 8, 1, fp ));
 
     /*
     ** Swap the two classification arrays if we are writing them, and they need
@@ -1453,7 +1433,7 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
 
     if( bCalculateStats )
     {
-        for( i = 0; i < nBands; i++ )
+        for( int i = 0; i < nBands; i++ )
         {
             /*
             ** If we don't have Crown fuels, but do have Ground fuels, we
@@ -1461,39 +1441,39 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
             */
             if( i == 5 && !bHaveCrownFuels && bHaveGroundFuels )
             {
-                VSIFSeekL( fp, 3340, SEEK_SET );
+                CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 3340, SEEK_SET ));
             }
             nTemp = (GInt32)padfMin[i];
-            CPL_LSBINT32PTR( &nTemp );
-            VSIFWriteL( &nTemp, 4, 1, fp );
+            CPL_LSBPTR32( &nTemp );
+            CPL_IGNORE_RET_VAL(VSIFWriteL( &nTemp, 4, 1, fp ));
             nTemp = (GInt32)padfMax[i];
-            CPL_LSBINT32PTR( &nTemp );
-            VSIFWriteL( &nTemp, 4, 1, fp );
+            CPL_LSBPTR32( &nTemp );
+            CPL_IGNORE_RET_VAL(VSIFWriteL( &nTemp, 4, 1, fp ));
             if( bClassifyData )
             {
                 /*
                 ** These two arrays were swapped in their entirety above.
                 */
-                VSIFWriteL( panFound + i, 4, 1, fp );
-                VSIFWriteL( panClasses + ( i * LCP_MAX_CLASSES ), 4, 100, fp );
+                CPL_IGNORE_RET_VAL(VSIFWriteL( panFound + i, 4, 1, fp ));
+                CPL_IGNORE_RET_VAL(VSIFWriteL( panClasses + ( i * LCP_MAX_CLASSES ), 4, 100, fp ));
             }
             else
             {
                 nTemp = -1;
-                CPL_LSBINT32PTR( &nTemp );
-                VSIFWriteL( &nTemp, 4, 1, fp );
-                VSIFSeekL( fp, 400, SEEK_CUR );
+                CPL_LSBPTR32( &nTemp );
+                CPL_IGNORE_RET_VAL(VSIFWriteL( &nTemp, 4, 1, fp ));
+                CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 400, SEEK_CUR ));
             }
         }
     }
     else
     {
-        VSIFSeekL( fp, 4164, SEEK_SET );
+        CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 4164, SEEK_SET ));
     }
-    CPLFree( (void*)padfMin );
-    CPLFree( (void*)padfMax );
-    CPLFree( (void*)panFound );
-    CPLFree( (void*)panClasses );
+    CPLFree( reinterpret_cast<void *>( padfMin ) );
+    CPLFree( reinterpret_cast<void *>( padfMax ) );
+    CPLFree( reinterpret_cast<void *>( panFound ) );
+    CPLFree( reinterpret_cast<void *>( panClasses ) );
 
     /*
     ** Should be at one of 3 locations, 2104, 3340, or 4164.
@@ -1501,66 +1481,66 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
     CPLAssert( VSIFTellL( fp ) == 2104  ||
                VSIFTellL( fp ) == 3340  ||
                VSIFTellL( fp ) == 4164 );
-    VSIFSeekL( fp, 4164, SEEK_SET );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 4164, SEEK_SET ));
 
     /* Image size */
     nTemp = (GInt32)nXSize;
-    CPL_LSBINT32PTR( &nTemp );
-    VSIFWriteL( &nTemp, 4, 1, fp );
+    CPL_LSBPTR32( &nTemp );
+    CPL_IGNORE_RET_VAL(VSIFWriteL( &nTemp, 4, 1, fp ));
     nTemp = (GInt32)nYSize;
-    CPL_LSBINT32PTR( &nTemp );
-    VSIFWriteL( &nTemp, 4, 1, fp );
+    CPL_LSBPTR32( &nTemp );
+    CPL_IGNORE_RET_VAL(VSIFWriteL( &nTemp, 4, 1, fp ));
 
     /* X and Y boundaries */
     /* max x */
-    dfTemp = adfSrcGeoTransform[0] + adfSrcGeoTransform[1] * nXSize;
+    double dfTemp = adfSrcGeoTransform[0] + adfSrcGeoTransform[1] * nXSize;
     CPL_LSBPTR64( &dfTemp );
-    VSIFWriteL( &dfTemp, 8, 1, fp );
+    CPL_IGNORE_RET_VAL(VSIFWriteL( &dfTemp, 8, 1, fp ));
     /* min x */
     dfTemp = adfSrcGeoTransform[0];
     CPL_LSBPTR64( &dfTemp );
-    VSIFWriteL( &dfTemp, 8, 1, fp );
+    CPL_IGNORE_RET_VAL(VSIFWriteL( &dfTemp, 8, 1, fp ));
     /* max y */
     dfTemp = adfSrcGeoTransform[3];
     CPL_LSBPTR64( &dfTemp );
-    VSIFWriteL( &dfTemp, 8, 1, fp );
+    CPL_IGNORE_RET_VAL(VSIFWriteL( &dfTemp, 8, 1, fp ));
     /* min y */
     dfTemp = adfSrcGeoTransform[3] + adfSrcGeoTransform[5] * nYSize;
     CPL_LSBPTR64( &dfTemp );
-    VSIFWriteL( &dfTemp, 8, 1, fp );
+    CPL_IGNORE_RET_VAL(VSIFWriteL( &dfTemp, 8, 1, fp ));
 
     nTemp = nLinearUnits;
-    CPL_LSBINT32PTR( &nTemp );
-    VSIFWriteL( &nTemp, 4, 1, fp );
+    CPL_LSBPTR32( &nTemp );
+    CPL_IGNORE_RET_VAL(VSIFWriteL( &nTemp, 4, 1, fp ));
 
     /* Resolution */
     /* x resolution */
     dfTemp = adfSrcGeoTransform[1];
     CPL_LSBPTR64( &dfTemp );
-    VSIFWriteL( &dfTemp, 8, 1, fp );
+    CPL_IGNORE_RET_VAL(VSIFWriteL( &dfTemp, 8, 1, fp ));
     /* y resolution */
     dfTemp = fabs( adfSrcGeoTransform[5] );
     CPL_LSBPTR64( &dfTemp );
-    VSIFWriteL( &dfTemp, 8, 1, fp );
+    CPL_IGNORE_RET_VAL(VSIFWriteL( &dfTemp, 8, 1, fp ));
 
 #ifdef CPL_MSB
     GDALSwapWords( panMetadata, 2, LCP_MAX_BANDS, 2 );
 #endif
-    VSIFWriteL( panMetadata, 2, LCP_MAX_BANDS, fp );
+    CPL_IGNORE_RET_VAL(VSIFWriteL( panMetadata, 2, LCP_MAX_BANDS, fp ));
 
     /* Write the source filenames */
     char **papszFileList = poSrcDS->GetFileList();
     if( papszFileList != NULL )
     {
-        for( i = 0; i < nBands; i++ )
+        for( int i = 0; i < nBands; i++ )
         {
             if( i == 5 && !bHaveCrownFuels && bHaveGroundFuels )
             {
-                VSIFSeekL( fp, 6292, SEEK_SET );
+                CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 6292, SEEK_SET ));
             }
-            VSIFWriteL( papszFileList[0], 1,
-                        CPLStrnlen( papszFileList[0], LCP_MAX_PATH ), fp );
-            VSIFSeekL( fp, 4244 + ( 256 * ( i+1 ) ), SEEK_SET );
+            CPL_IGNORE_RET_VAL(VSIFWriteL( papszFileList[0], 1,
+                        CPLStrnlen( papszFileList[0], LCP_MAX_PATH ), fp ));
+            CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 4244 + ( 256 * ( i+1 ) ), SEEK_SET ));
         }
     }
     /*
@@ -1568,7 +1548,7 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
     */
     else
     {
-        VSIFSeekL( fp, 6804, SEEK_SET );
+        CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 6804, SEEK_SET ));
     }
     CSLDestroy( papszFileList );
     /*
@@ -1577,16 +1557,16 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
     CPLAssert( VSIFTellL( fp ) == 5524 ||
                VSIFTellL( fp ) == 6292 ||
                VSIFTellL( fp ) == 6804 );
-    VSIFSeekL( fp, 6804, SEEK_SET );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 6804, SEEK_SET ));
 
     /* Description */
-    VSIFWriteL( pszDescription, 1, CPLStrnlen( pszDescription, LCP_MAX_DESC ),
-                fp );
+    CPL_IGNORE_RET_VAL(VSIFWriteL( pszDescription, 1, CPLStrnlen( pszDescription, LCP_MAX_DESC ),
+                fp ));
     /*
     ** Should be at or below location 7316, all done with the header.
     */
     CPLAssert( VSIFTellL( fp ) <= 7316 );
-    VSIFSeekL( fp, 7316, SEEK_SET );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 7316, SEEK_SET ));
 
 /* -------------------------------------------------------------------- */
 /*      Loop over image, copying image data.                            */
@@ -1596,8 +1576,8 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
 
     if( !pfnProgress( 0.0, NULL, pProgressData ) )
     {
-        VSIFCloseL( fp );
-        VSIFree( (void*)panScanline );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
+        VSIFree( reinterpret_cast<void *>( panScanline ) );
         return NULL;
     }
     for( int iLine = 0; iLine < nYSize; iLine++ )
@@ -1622,17 +1602,17 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
 #ifdef CPL_MSB
         GDALSwapWords( panScanline, 2, nBands * nXSize, 2 );
 #endif
-        VSIFWriteL( panScanline, 2, nBands * nXSize, fp );
+        CPL_IGNORE_RET_VAL(VSIFWriteL( panScanline, 2, nBands * nXSize, fp ));
 
         if( !pfnProgress( iLine / (double)nYSize, NULL, pProgressData ) )
         {
-            VSIFree( (void*)panScanline );
-            VSIFCloseL( fp );
+            VSIFree( reinterpret_cast<void *>( panScanline ) );
+            CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
             return NULL;
         }
     }
     VSIFree( panScanline );
-    VSIFCloseL( fp );
+    CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
     if( !pfnProgress( 1.0, NULL, pProgressData ) )
     {
         return NULL;
@@ -1647,25 +1627,22 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
     pszOriginalProjection = (char *)poSrcDS->GetProjectionRef();
     if( !EQUAL( pszOriginalProjection, "" ) )
     {
-        char                    *pszDirname, *pszBasename;
-        char                    *pszPrjFilename;
-        char                    *pszESRIProjection = NULL;
-        VSILFILE                *fp;
         OGRSpatialReference     oSRS;
 
-        pszDirname = CPLStrdup( CPLGetPath(pszFilename) );
-        pszBasename = CPLStrdup( CPLGetBasename(pszFilename) );
+        char *pszDirname = CPLStrdup( CPLGetPath(pszFilename) );
+        char *pszBasename = CPLStrdup( CPLGetBasename(pszFilename) );
 
-        pszPrjFilename = CPLStrdup( CPLFormFilename( pszDirname, pszBasename, "prj" ) );
+        char *pszPrjFilename = CPLStrdup( CPLFormFilename( pszDirname, pszBasename, "prj" ) );
         fp = VSIFOpenL( pszPrjFilename, "wt" );
         if (fp != NULL)
         {
             oSRS.importFromWkt( (char **) &pszOriginalProjection );
             oSRS.morphToESRI();
+            char *pszESRIProjection = NULL;
             oSRS.exportToWkt( &pszESRIProjection );
-            VSIFWriteL( pszESRIProjection, 1, strlen(pszESRIProjection), fp );
+            CPL_IGNORE_RET_VAL(VSIFWriteL( pszESRIProjection, 1, strlen(pszESRIProjection), fp ));
 
-            VSIFCloseL( fp );
+            CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
             CPLFree( pszESRIProjection );
         }
         else
@@ -1683,7 +1660,7 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
 /************************************************************************/
 /*                          GetProjectionRef()                          */
 /************************************************************************/
- 
+
 const char *LCPDataset::GetProjectionRef()
 
 {
@@ -1697,24 +1674,22 @@ const char *LCPDataset::GetProjectionRef()
 void GDALRegister_LCP()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "LCP" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "LCP" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "LCP" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "FARSITE v.4 Landscape File (.lcp)" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "lcp" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_lcp.html" );
+    poDriver->SetDescription( "LCP" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "FARSITE v.4 Landscape File (.lcp)" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "lcp" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_lcp.html" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Int16" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Int16" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "   <Option name='ELEVATION_UNIT' type='string-select' default='METERS' description='Elevation units'>"
 "       <Value>METERS</Value>"
@@ -1774,11 +1749,10 @@ void GDALRegister_LCP()
 "   <Option name='LATITUDE' type='int' default='' description='Set the latitude for the dataset, this overrides the driver trying to set it programmatically in EPSG:4269'/>"
 "   <Option name='DESCRIPTION' type='string' default='LCP file created by GDAL' description='A short description of the lcp file'/>"
 "</CreationOptionList>" );
-        poDriver->pfnOpen = LCPDataset::Open;
-        poDriver->pfnCreateCopy = LCPDataset::CreateCopy;
-        poDriver->pfnIdentify = LCPDataset::Identify;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-   }
-}
+    poDriver->pfnOpen = LCPDataset::Open;
+    poDriver->pfnCreateCopy = LCPDataset::CreateCopy;
+    poDriver->pfnIdentify = LCPDataset::Identify;
 
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/frmts/raw/loslasdataset.cpp b/frmts/raw/loslasdataset.cpp
index 52c2368..2324720 100644
--- a/frmts/raw/loslasdataset.cpp
+++ b/frmts/raw/loslasdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: loslasdataset.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: loslasdataset.cpp 33673 2016-03-07 20:40:54Z goatbar $
  *
  * Project:  Horizontal Datum Formats
  * Purpose:  Implementation of NOAA/NADCON los/las datum shift format.
@@ -28,11 +28,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "rawdataset.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
 #include "ogr_srs_api.h"
+#include "rawdataset.h"
 
-CPL_CVSID("$Id: loslasdataset.cpp 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: loslasdataset.cpp 33673 2016-03-07 20:40:54Z goatbar $");
 
 /**
 
@@ -77,13 +78,13 @@ class LOSLASDataset : public RawDataset
     VSILFILE	*fpImage;	// image data file.
 
     int         nRecordLength;
-    
+
     double      adfGeoTransform[6];
 
   public:
     		LOSLASDataset();
     	        ~LOSLASDataset();
-    
+
     virtual CPLErr GetGeoTransform( double * padfTransform );
     virtual const char *GetProjectionRef();
 
@@ -101,10 +102,7 @@ class LOSLASDataset : public RawDataset
 /*                             LOSLASDataset()                          */
 /************************************************************************/
 
-LOSLASDataset::LOSLASDataset()
-{
-    fpImage = NULL;
-}
+LOSLASDataset::LOSLASDataset() : fpImage(NULL), nRecordLength(0) { }
 
 /************************************************************************/
 /*                            ~LOSLASDataset()                          */
@@ -116,7 +114,7 @@ LOSLASDataset::~LOSLASDataset()
     FlushCache();
 
     if( fpImage != NULL )
-        VSIFCloseL( fpImage );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fpImage ));
 }
 
 /************************************************************************/
@@ -129,11 +127,11 @@ int LOSLASDataset::Identify( GDALOpenInfo *poOpenInfo )
     if( poOpenInfo->nHeaderBytes < 64 )
         return FALSE;
 
-    if( !EQUAL(CPLGetExtension(poOpenInfo->pszFilename),"las") 
+    if( !EQUAL(CPLGetExtension(poOpenInfo->pszFilename),"las")
         && !EQUAL(CPLGetExtension(poOpenInfo->pszFilename),"los") )
         return FALSE;
 
-    if( !EQUALN((const char *)poOpenInfo->pabyHeader + 56, "NADGRD", 6 ) )
+    if( !STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader + 56, "NADGRD") )
         return FALSE;
 
     return TRUE;
@@ -148,13 +146,11 @@ GDALDataset *LOSLASDataset::Open( GDALOpenInfo * poOpenInfo )
 {
     if( !Identify( poOpenInfo ) )
         return NULL;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    LOSLASDataset 	*poDS;
-
-    poDS = new LOSLASDataset();
+    LOSLASDataset *poDS = new LOSLASDataset();
 
 /* -------------------------------------------------------------------- */
 /*      Open the file.                                                  */
@@ -170,10 +166,10 @@ GDALDataset *LOSLASDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Read the header.                                                */
 /* -------------------------------------------------------------------- */
-    VSIFSeekL( poDS->fpImage, 64, SEEK_SET );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( poDS->fpImage, 64, SEEK_SET ));
 
-    VSIFReadL( &(poDS->nRasterXSize), 4, 1, poDS->fpImage );
-    VSIFReadL( &(poDS->nRasterYSize), 4, 1, poDS->fpImage );
+    CPL_IGNORE_RET_VAL(VSIFReadL( &(poDS->nRasterXSize), 4, 1, poDS->fpImage ));
+    CPL_IGNORE_RET_VAL(VSIFReadL( &(poDS->nRasterYSize), 4, 1, poDS->fpImage ));
 
     CPL_LSBPTR32( &(poDS->nRasterXSize) );
     CPL_LSBPTR32( &(poDS->nRasterYSize) );
@@ -184,14 +180,14 @@ GDALDataset *LOSLASDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    VSIFSeekL( poDS->fpImage, 76, SEEK_SET );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( poDS->fpImage, 76, SEEK_SET ));
 
     float min_lon, min_lat, delta_lon, delta_lat;
 
-    VSIFReadL( &min_lon, 4, 1, poDS->fpImage );
-    VSIFReadL( &delta_lon, 4, 1, poDS->fpImage );
-    VSIFReadL( &min_lat, 4, 1, poDS->fpImage );
-    VSIFReadL( &delta_lat, 4, 1, poDS->fpImage );
+    CPL_IGNORE_RET_VAL(VSIFReadL( &min_lon, 4, 1, poDS->fpImage ));
+    CPL_IGNORE_RET_VAL(VSIFReadL( &delta_lon, 4, 1, poDS->fpImage ));
+    CPL_IGNORE_RET_VAL(VSIFReadL( &min_lat, 4, 1, poDS->fpImage ));
+    CPL_IGNORE_RET_VAL(VSIFReadL( &delta_lat, 4, 1, poDS->fpImage ));
 
     CPL_LSBPTR32( &min_lon );
     CPL_LSBPTR32( &delta_lon );
@@ -207,8 +203,8 @@ GDALDataset *LOSLASDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      the first since the data comes with the southern most record    */
 /*      first, not the northernmost like we would want.                 */
 /* -------------------------------------------------------------------- */
-    poDS->SetBand( 
-        1, new RawRasterBand( poDS, 1, poDS->fpImage, 
+    poDS->SetBand(
+        1, new RawRasterBand( poDS, 1, poDS->fpImage,
                               poDS->nRasterYSize * poDS->nRecordLength + 4,
                               4, -1 * poDS->nRecordLength,
                               GDT_Float32,
@@ -266,22 +262,19 @@ const char *LOSLASDataset::GetProjectionRef()
 void GDALRegister_LOSLAS()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "LOSLAS" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "LOSLAS" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "LOSLAS" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "NADCON .los/.las Datum Grid Shift" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = LOSLASDataset::Open;
-        poDriver->pfnIdentify = LOSLASDataset::Identify;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
-}
+    GDALDriver *poDriver = new GDALDriver();
 
+    poDriver->SetDescription( "LOSLAS" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "NADCON .los/.las Datum Grid Shift" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = LOSLASDataset::Open;
+    poDriver->pfnIdentify = LOSLASDataset::Identify;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/frmts/raw/makefile.vc b/frmts/raw/makefile.vc
index 0d7cd72..189209f 100644
--- a/frmts/raw/makefile.vc
+++ b/frmts/raw/makefile.vc
@@ -7,7 +7,7 @@ OBJ	=	rawdataset.obj ehdrdataset.obj pauxdataset.obj doq1dataset.obj\
 		ndfdataset.obj dipxdataset.obj genbindataset.obj \
 		lcpdataset.obj eirdataset.obj gtxdataset.obj loslasdataset.obj \
 		ntv2dataset.obj ace2dataset.obj snodasdataset.obj \
-		ctable2dataset.obj krodataset.obj roipacdataset.obj
+		ctable2dataset.obj krodataset.obj roipacdataset.obj iscedataset.obj
 
 GDAL_ROOT	=	..\..
 
diff --git a/frmts/raw/mffdataset.cpp b/frmts/raw/mffdataset.cpp
index 754725e..7ddb3c8 100644
--- a/frmts/raw/mffdataset.cpp
+++ b/frmts/raw/mffdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: mffdataset.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: mffdataset.cpp 33712 2016-03-12 10:51:56Z goatbar $
  *
  * Project:  GView
  * Purpose:  Implementation of Atlantis MFF Support
@@ -30,15 +30,14 @@
 
 #include "rawdataset.h"
 #include "cpl_string.h"
-#include <ctype.h>
+#include "gdal_frmts.h"
 #include "ogr_spatialref.h"
 #include "atlsci_spheroid.h"
 
-CPL_CVSID("$Id: mffdataset.cpp 28053 2014-12-04 09:31:07Z rouault $");
+#include <cctype>
+#include <algorithm>
 
-CPL_C_START
-void	GDALRegister_MFF(void);
-CPL_C_END
+CPL_CVSID("$Id: mffdataset.cpp 33712 2016-03-12 10:51:56Z goatbar $");
 
 enum {
   MFFPRJ_NONE,
@@ -62,20 +61,19 @@ class MFFDataset : public RawDataset
 
     char *pszProjection;
     char *pszGCPProjection;
-    double adfGeoTransform[6]; 
+    double adfGeoTransform[6];
 
     void        ScanForGCPs();
     void        ScanForProjectionInfo();
- 
 
   public:
     		MFFDataset();
     	        ~MFFDataset();
-    
+
     char	**papszHdrLines;
-    
+
     VSILFILE        **pafpBandFiles;
-    
+
     virtual int    GetGCPCount();
     virtual const char *GetGCPProjection();
     virtual const GDAL_GCP *GetGCPs();
@@ -87,10 +85,10 @@ class MFFDataset : public RawDataset
     static GDALDataset *Create( const char * pszFilename,
                                 int nXSize, int nYSize, int nBands,
                                 GDALDataType eType, char ** papszParmList );
-    static GDALDataset *CreateCopy( const char * pszFilename, 
-                                    GDALDataset *poSrcDS, 
-                                    int bStrict, char ** papszOptions, 
-                                    GDALProgressFunc pfnProgress, 
+    static GDALDataset *CreateCopy( const char * pszFilename,
+                                    GDALDataset *poSrcDS,
+                                    int bStrict, char ** papszOptions,
+                                    GDALProgressFunc pfnProgress,
                                     void * pProgressData );
 
 };
@@ -122,22 +120,19 @@ class MFFTiledBand : public GDALRasterBand
 /*                            MFFTiledBand()                            */
 /************************************************************************/
 
-MFFTiledBand::MFFTiledBand( MFFDataset *poDS, int nBand, VSILFILE *fp, 
-                            int nTileXSize, int nTileYSize, 
-                            GDALDataType eDataType, int bNative )
-
+MFFTiledBand::MFFTiledBand( MFFDataset *poDSIn, int nBandIn, VSILFILE *fp,
+                            int nTileXSize, int nTileYSize,
+                            GDALDataType eDataTypeIn, int bNativeIn ) :
+    fpRaw(fp),
+    bNative(bNativeIn)
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
-    this->eDataType = eDataType; 
+    eDataType = eDataTypeIn;
 
-    this->bNative = bNative;
-
-    this->nBlockXSize = nTileXSize;
-    this->nBlockYSize = nTileYSize;
-
-    this->fpRaw = fp;
+    nBlockXSize = nTileXSize;
+    nBlockYSize = nTileYSize;
 }
 
 /************************************************************************/
@@ -147,7 +142,10 @@ MFFTiledBand::MFFTiledBand( MFFDataset *poDS, int nBand, VSILFILE *fp,
 MFFTiledBand::~MFFTiledBand()
 
 {
-    VSIFCloseL( fpRaw );
+    if( VSIFCloseL( fpRaw ) != 0 )
+    {
+        CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+    }
 }
 
 
@@ -159,39 +157,35 @@ CPLErr MFFTiledBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                  void * pImage )
 
 {
-    long    nOffset;
-    int     nTilesPerRow;
-    int     nWordSize, nBlockSize;
+    const int nTilesPerRow = (nRasterXSize + nBlockXSize - 1) / nBlockXSize;
+    const int nWordSize = GDALGetDataTypeSize( eDataType ) / 8;
+    const int nBlockSize = nWordSize * nBlockXSize * nBlockYSize;
 
-    nTilesPerRow = (nRasterXSize + nBlockXSize - 1) / nBlockXSize;
-    nWordSize = GDALGetDataTypeSize( eDataType ) / 8;
-    nBlockSize = nWordSize * nBlockXSize * nBlockYSize;
+    const long nOffset = nBlockSize * (nBlockXOff + nBlockYOff*nTilesPerRow);
 
-    nOffset = nBlockSize * (nBlockXOff + nBlockYOff*nTilesPerRow);
-
-    if( VSIFSeekL( fpRaw, nOffset, SEEK_SET ) == -1 
+    if( VSIFSeekL( fpRaw, nOffset, SEEK_SET ) == -1
         || VSIFReadL( pImage, 1, nBlockSize, fpRaw ) < 1 )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
-                  "Read of tile %d/%d failed with fseek or fread error.", 
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Read of tile %d/%d failed with fseek or fread error.",
                   nBlockXOff, nBlockYOff );
         return CE_Failure;
     }
-    
+
     if( !bNative && nWordSize > 1 )
     {
         if( GDALDataTypeIsComplex( eDataType ) )
         {
-            GDALSwapWords( pImage, nWordSize/2, nBlockXSize*nBlockYSize, 
+            GDALSwapWords( pImage, nWordSize/2, nBlockXSize*nBlockYSize,
                            nWordSize );
-            GDALSwapWords( ((GByte *) pImage)+nWordSize/2, 
+            GDALSwapWords( reinterpret_cast<GByte *>( pImage ) + nWordSize / 2,
                            nWordSize/2, nBlockXSize*nBlockYSize, nWordSize );
         }
         else
             GDALSwapWords( pImage, nWordSize,
                            nBlockXSize * nBlockYSize, nWordSize );
     }
-    
+
     return CE_None;
 }
 
@@ -201,12 +195,9 @@ CPLErr MFFTiledBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
 class MFFSpheroidList : public SpheroidList
 {
-
 public:
-
   MFFSpheroidList();
-  ~MFFSpheroidList();
-
+  ~MFFSpheroidList() {};
 };
 
 MFFSpheroidList :: MFFSpheroidList()
@@ -214,7 +205,7 @@ MFFSpheroidList :: MFFSpheroidList()
   num_spheroids = 18;
 
   epsilonR = 0.1;
-  epsilonI = 0.000001;   
+  epsilonI = 0.000001;
 
   spheroids[0].SetValuesByRadii("SPHERE",6371007.0,6371007.0);
   spheroids[1].SetValuesByRadii("EVEREST",6377304.0,6356103.0);
@@ -233,12 +224,7 @@ MFFSpheroidList :: MFFSpheroidList()
   spheroids[14].SetValuesByRadii("WGS_72",6378135.0,6356751.0);
   spheroids[15].SetValuesByRadii("IUGG_75",6378140.0,6356755.0);
   spheroids[16].SetValuesByRadii("WGS_84",6378137.0,6356752.0);
-  spheroids[17].SetValuesByRadii("HUGHES",6378273.0,6356889.4); 
-}
-
-MFFSpheroidList::~MFFSpheroidList()
-
-{
+  spheroids[17].SetValuesByRadii("HUGHES",6378273.0,6356889.4);
 }
 
 /************************************************************************/
@@ -251,15 +237,14 @@ MFFSpheroidList::~MFFSpheroidList()
 /*                            MFFDataset()                             */
 /************************************************************************/
 
-MFFDataset::MFFDataset()
+MFFDataset::MFFDataset() :
+    nGCPCount(0),
+    pasGCPList(NULL),
+    pszProjection(CPLStrdup("")),
+    pszGCPProjection(CPLStrdup("")),
+    papszHdrLines(NULL),
+    pafpBandFiles(NULL)
 {
-    papszHdrLines = NULL;
-    pafpBandFiles = NULL;
-    nGCPCount = 0;
-    pasGCPList = NULL;
-
-    pszProjection = CPLStrdup("");
-    pszGCPProjection = CPLStrdup("");
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
@@ -282,7 +267,12 @@ MFFDataset::~MFFDataset()
         for( int i = 0; i < GetRasterCount(); i++ )
         {
             if( pafpBandFiles[i] != NULL )
-                VSIFCloseL( pafpBandFiles[i] );
+            {
+                if( VSIFCloseL( pafpBandFiles[i] ) != 0 )
+                {
+                    CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+                }
+            }
         }
         CPLFree( pafpBandFiles );
     }
@@ -316,8 +306,8 @@ const char *MFFDataset::GetGCPProjection()
 {
     if( nGCPCount > 0 )
         return pszGCPProjection;
-    else
-        return "";
+
+    return "";
 }
 
 /************************************************************************/
@@ -327,7 +317,7 @@ const char *MFFDataset::GetGCPProjection()
 const char *MFFDataset::GetProjectionRef()
 
 {
-   return ( pszProjection );
+   return pszProjection;
 }
 
 /************************************************************************/
@@ -337,8 +327,8 @@ const char *MFFDataset::GetProjectionRef()
 CPLErr MFFDataset::GetGeoTransform( double * padfTransform )
 
 {
-    memcpy( padfTransform,  adfGeoTransform, sizeof(double) * 6 ); 
-    return( CE_None );
+    memcpy( padfTransform,  adfGeoTransform, sizeof(double) * 6 );
+    return CE_None;
 }
 
 /************************************************************************/
@@ -358,24 +348,23 @@ const GDAL_GCP *MFFDataset::GetGCPs()
 void MFFDataset::ScanForGCPs()
 
 {
-    int     nCorner;
     int	    NUM_GCPS = 0;
-    
+
     if( CSLFetchNameValue(papszHdrLines, "NUM_GCPS") != NULL )
         NUM_GCPS = atoi(CSLFetchNameValue(papszHdrLines, "NUM_GCPS"));
     if (NUM_GCPS < 0)
         return;
 
     nGCPCount = 0;
-    pasGCPList = (GDAL_GCP *) VSICalloc(sizeof(GDAL_GCP),5+NUM_GCPS);
+    pasGCPList = reinterpret_cast<GDAL_GCP *>(
+        VSICalloc( sizeof(GDAL_GCP) , 5 + NUM_GCPS ) );
     if (pasGCPList == NULL)
         return;
 
-    for( nCorner = 0; nCorner < 5; nCorner++ )
+    for( int nCorner = 0; nCorner < 5; nCorner++ )
     {
         const char * pszBase=NULL;
         double       dfRasterX=0.0, dfRasterY=0.0;
-        char         szLatName[40], szLongName[40];
 
         if( nCorner == 0 )
         {
@@ -408,21 +397,22 @@ void MFFDataset::ScanForGCPs()
             pszBase = "CENTRE";
         }
 
-        sprintf( szLatName, "%s_LATITUDE", pszBase );
-        sprintf( szLongName, "%s_LONGITUDE", pszBase );
-        
+        char szLatName[40], szLongName[40];
+        snprintf( szLatName, sizeof(szLatName), "%s_LATITUDE", pszBase );
+        snprintf( szLongName, sizeof(szLongName), "%s_LONGITUDE", pszBase );
+
         if( CSLFetchNameValue(papszHdrLines, szLatName) != NULL
             && CSLFetchNameValue(papszHdrLines, szLongName) != NULL )
         {
             GDALInitGCPs( 1, pasGCPList + nGCPCount );
-            
+
             CPLFree( pasGCPList[nGCPCount].pszId );
 
             pasGCPList[nGCPCount].pszId = CPLStrdup( pszBase );
-                
-            pasGCPList[nGCPCount].dfGCPX = 
+
+            pasGCPList[nGCPCount].dfGCPX =
                 CPLAtof(CSLFetchNameValue(papszHdrLines, szLongName));
-            pasGCPList[nGCPCount].dfGCPY = 
+            pasGCPList[nGCPCount].dfGCPY =
                 CPLAtof(CSLFetchNameValue(papszHdrLines, szLatName));
             pasGCPList[nGCPCount].dfGCPZ = 0.0;
 
@@ -431,7 +421,6 @@ void MFFDataset::ScanForGCPs()
 
             nGCPCount++;
         }
-       
     }
 
 /* -------------------------------------------------------------------- */
@@ -440,19 +429,15 @@ void MFFDataset::ScanForGCPs()
 /*      GCPn = row, col, lat, long                                      */
 /*      GCP1 = 1, 1, 45.0, -75.0                                        */
 /* -------------------------------------------------------------------- */
-    int i;
-
-    for( i = 0; i < NUM_GCPS; i++ )
+    for( int i = 0; i < NUM_GCPS; i++ )
     {
         char	szName[25];
-        char    **papszTokens;
-
-        sprintf( szName, "GCP%d", i+1 );
+        snprintf( szName, sizeof(szName), "GCP%d", i+1 );
         if( CSLFetchNameValue( papszHdrLines, szName ) == NULL )
             continue;
 
-        papszTokens = CSLTokenizeStringComplex( 
-            CSLFetchNameValue( papszHdrLines, szName ), 
+        char **papszTokens = CSLTokenizeStringComplex(
+            CSLFetchNameValue( papszHdrLines, szName ),
             ",", FALSE, FALSE );
         if( CSLCount(papszTokens) == 4 )
         {
@@ -480,19 +465,12 @@ void MFFDataset::ScanForGCPs()
 
 void MFFDataset::ScanForProjectionInfo()
 {
-    const char *pszProjName, *pszOriginLong, *pszSpheroidName;
-    const char *pszSpheroidEqRadius, *pszSpheroidPolarRadius;
-    double eq_radius, polar_radius;
-    OGRSpatialReference oProj;
-    OGRSpatialReference oLL;
-    MFFSpheroidList *mffEllipsoids;
-
-    pszProjName = CSLFetchNameValue(papszHdrLines, 
-                                    "PROJECTION_NAME");
-    pszOriginLong = CSLFetchNameValue(papszHdrLines, 
-                                      "PROJECTION_ORIGIN_LONGITUDE");
-    pszSpheroidName = CSLFetchNameValue(papszHdrLines, 
-                                      "SPHEROID_NAME");
+    const char *pszProjName
+        = CSLFetchNameValue(papszHdrLines, "PROJECTION_NAME");
+    const char *pszOriginLong
+        = CSLFetchNameValue(papszHdrLines, "PROJECTION_ORIGIN_LONGITUDE");
+    const char *pszSpheroidName
+        = CSLFetchNameValue(papszHdrLines, "SPHEROID_NAME");
 
     if (pszProjName == NULL)
     {
@@ -512,8 +490,9 @@ void MFFDataset::ScanForProjectionInfo()
         pszGCPProjection=CPLStrdup("");
         return;
     }
-    mffEllipsoids = new MFFSpheroidList;
+    MFFSpheroidList *mffEllipsoids = new MFFSpheroidList;
 
+    OGRSpatialReference oProj;
     if( EQUAL(pszProjName,"utm") )
     {
         int nZone;
@@ -526,19 +505,19 @@ void MFFDataset::ScanForProjectionInfo()
             nZone = 31;
         }
         else
-            nZone = 31 + (int) floor(CPLAtof(pszOriginLong)/6.0);
-
+            nZone = 31 + static_cast<int>(
+                floor( CPLAtof( pszOriginLong ) / 6.0) );
 
         if( nGCPCount >= 5 && pasGCPList[4].dfGCPY < 0 )
             oProj.SetUTM( nZone, 0 );
         else
             oProj.SetUTM( nZone, 1 );
-     
+
         if (pszOriginLong != NULL)
             oProj.SetProjParm(SRS_PP_CENTRAL_MERIDIAN,CPLAtof(pszOriginLong));
-        
     }
 
+    OGRSpatialReference oLL;
     if (pszOriginLong != NULL)
         oLL.SetProjParm(SRS_PP_LONGITUDE_OF_ORIGIN,CPLAtof(pszOriginLong));
 
@@ -553,30 +532,30 @@ void MFFDataset::ScanForProjectionInfo()
     else
     {
       if (mffEllipsoids->SpheroidInList(pszSpheroidName))
-      { 
+      {
          oProj.SetGeogCS( "unknown","unknown",pszSpheroidName,
-                         mffEllipsoids->GetSpheroidEqRadius(pszSpheroidName), 
+                         mffEllipsoids->GetSpheroidEqRadius(pszSpheroidName),
                          mffEllipsoids->GetSpheroidInverseFlattening(pszSpheroidName)
                        );
          oLL.SetGeogCS( "unknown","unknown",pszSpheroidName,
-                         mffEllipsoids->GetSpheroidEqRadius(pszSpheroidName), 
+                         mffEllipsoids->GetSpheroidEqRadius(pszSpheroidName),
                          mffEllipsoids->GetSpheroidInverseFlattening(pszSpheroidName)
                       );
       }
       else if (EQUAL(pszSpheroidName,"USER_DEFINED"))
       {
-          pszSpheroidEqRadius = CSLFetchNameValue(papszHdrLines,
-                                                  "SPHEROID_EQUATORIAL_RADIUS");
-          pszSpheroidPolarRadius = CSLFetchNameValue(papszHdrLines,
-                                                  "SPHEROID_POLAR_RADIUS");
+          const char *pszSpheroidEqRadius
+              = CSLFetchNameValue(papszHdrLines, "SPHEROID_EQUATORIAL_RADIUS");
+          const char *pszSpheroidPolarRadius
+              = CSLFetchNameValue(papszHdrLines, "SPHEROID_POLAR_RADIUS");
           if ((pszSpheroidEqRadius != NULL) && (pszSpheroidPolarRadius != NULL))
           {
-            eq_radius = CPLAtof( pszSpheroidEqRadius );
-            polar_radius = CPLAtof( pszSpheroidPolarRadius );
+            const double eq_radius = CPLAtof( pszSpheroidEqRadius );
+            const double polar_radius = CPLAtof( pszSpheroidPolarRadius );
             oProj.SetGeogCS( "unknown","unknown","unknown",
                          eq_radius, eq_radius/(eq_radius - polar_radius));
             oLL.SetGeogCS( "unknown","unknown","unknown",
-                         eq_radius, eq_radius/(eq_radius - polar_radius));          
+                         eq_radius, eq_radius/(eq_radius - polar_radius));
           }
           else
           {
@@ -593,56 +572,50 @@ void MFFDataset::ScanForProjectionInfo()
          oProj.SetWellKnownGeogCS( "WGS84" );
          oLL.SetWellKnownGeogCS( "WGS84" );
       }
-    }  
+    }
 
-    /* If a geotransform is sufficient to represent the GCP's (ie. each  */
+    /* If a geotransform is sufficient to represent the GCP's (i.e. each */
     /* estimated gcp is within 0.25*pixel size of the actual value- this */
     /* is the test applied by GDALGCPsToGeoTransform), store the         */
     /* geotransform.                                                     */
-    int transform_ok = FALSE;
+    bool transform_ok = false;
 
     if (EQUAL(pszProjName,"LL"))
     {
-        transform_ok = GDALGCPsToGeoTransform(nGCPCount,pasGCPList,adfGeoTransform,0);
+        transform_ok = CPL_TO_BOOL(GDALGCPsToGeoTransform(nGCPCount,pasGCPList,adfGeoTransform,0));
     }
     else
     {
-        OGRCoordinateTransformation *poTransform = NULL;
-        double *dfPrjX, *dfPrjY; 
-        int gcp_index;
-        int    bSuccess = TRUE;
-
-        dfPrjX = (double *) CPLMalloc(nGCPCount*sizeof(double));
-        dfPrjY = (double *) CPLMalloc(nGCPCount*sizeof(double));
-
-
-        poTransform = OGRCreateCoordinateTransformation( &oLL, &oProj );
+        OGRCoordinateTransformation *poTransform
+            = OGRCreateCoordinateTransformation( &oLL, &oProj );
+        bool bSuccess = true;
         if( poTransform == NULL )
         {
             CPLErrorReset();
             bSuccess = FALSE;
         }
 
-        for(gcp_index=0;gcp_index<nGCPCount;gcp_index++)
+        double *dfPrjX = reinterpret_cast<double *>( CPLMalloc(nGCPCount*sizeof(double)) );
+        double *dfPrjY = reinterpret_cast<double *>( CPLMalloc(nGCPCount*sizeof(double)) );
+
+        for( int gcp_index = 0; gcp_index < nGCPCount; gcp_index++ )
         {
             dfPrjX[gcp_index] = pasGCPList[gcp_index].dfGCPX;
             dfPrjY[gcp_index] = pasGCPList[gcp_index].dfGCPY;
 
             if( bSuccess && !poTransform->Transform( 1, &(dfPrjX[gcp_index]), &(dfPrjY[gcp_index]) ) )
                 bSuccess = FALSE;
- 
         }
 
         if( bSuccess )
         {
-
-            for(gcp_index=0;gcp_index<nGCPCount;gcp_index++)
+            for(int gcp_index = 0; gcp_index < nGCPCount; gcp_index++ )
             {
                 pasGCPList[gcp_index].dfGCPX = dfPrjX[gcp_index];
                 pasGCPList[gcp_index].dfGCPY = dfPrjY[gcp_index];
 
             }
-            transform_ok = GDALGCPsToGeoTransform(nGCPCount,pasGCPList,adfGeoTransform,0);
+            transform_ok = CPL_TO_BOOL(GDALGCPsToGeoTransform(nGCPCount,pasGCPList,adfGeoTransform,0));
 
         }
 
@@ -661,7 +634,7 @@ void MFFDataset::ScanForProjectionInfo()
     oProj.exportToWkt( &pszProjection );
     oProj.exportToWkt( &pszGCPProjection );
 
-    if (transform_ok == FALSE)
+    if( !transform_ok )
     {
     /* transform is sufficient in some cases (slant range, standalone gcps) */
         adfGeoTransform[0] = 0.0;
@@ -675,7 +648,7 @@ void MFFDataset::ScanForProjectionInfo()
     }
 
     delete mffEllipsoids;
-  
+
 }
 
 
@@ -686,9 +659,6 @@ void MFFDataset::ScanForProjectionInfo()
 GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    int		i, bNative = TRUE;
-    char        **papszHdrLines;
-
 /* -------------------------------------------------------------------- */
 /*      We assume the user is pointing to the header file.              */
 /* -------------------------------------------------------------------- */
@@ -702,25 +672,23 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Load the .hdr file, and compress white space out around the     */
 /*      equal sign.                                                     */
 /* -------------------------------------------------------------------- */
-    papszHdrLines = CSLLoad( poOpenInfo->pszFilename );
+    char **papszHdrLines = CSLLoad( poOpenInfo->pszFilename );
     if( papszHdrLines == NULL )
         return NULL;
 
-    for( i = 0; papszHdrLines[i] != NULL; i++ )
+    // Remove spaces.  e.g.
+    // SPHEROID_NAME = CLARKE_1866 -> SPHEROID_NAME=CLARKE_1866
+    for( int i = 0; papszHdrLines[i] != NULL; i++ )
     {
-        int       bAfterEqual = FALSE;
-        int       iSrc, iDst;
+        int iDst = 0;
         char     *pszLine = papszHdrLines[i];
 
-        for( iSrc=0, iDst=0; pszLine[iSrc] != '\0'; iSrc++ )
+        for( int iSrc=0; pszLine[iSrc] != '\0'; iSrc++ )
         {
-            if( bAfterEqual || pszLine[iSrc] != ' ' )
+            if( pszLine[iSrc] != ' ' )
             {
                 pszLine[iDst++] = pszLine[iSrc];
             }
-
-            if( iDst > 0 && pszLine[iDst-1] == '=' )
-                bAfterEqual = FALSE;
         }
         pszLine[iDst] = '\0';
     }
@@ -735,26 +703,24 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    if( (CSLFetchNameValue( papszHdrLines, "IMAGE_LINES" ) == NULL 
+    if( (CSLFetchNameValue( papszHdrLines, "IMAGE_LINES" ) == NULL
          || CSLFetchNameValue(papszHdrLines,"LINE_SAMPLES") == NULL)
-        && (CSLFetchNameValue( papszHdrLines, "no_rows" ) == NULL 
+        && (CSLFetchNameValue( papszHdrLines, "no_rows" ) == NULL
             || CSLFetchNameValue(papszHdrLines,"no_columns") == NULL) )
     {
         CSLDestroy( papszHdrLines );
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    MFFDataset 	*poDS;
-
-    poDS = new MFFDataset();
+    MFFDataset	*poDS = new MFFDataset();
 
     poDS->papszHdrLines = papszHdrLines;
 
     poDS->eAccess = poOpenInfo->eAccess;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Set some dataset wide information.                              */
 /* -------------------------------------------------------------------- */
@@ -776,6 +742,7 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
+    int bNative = TRUE;
     if( CSLFetchNameValue( papszHdrLines, "BYTE_ORDER" ) != NULL )
     {
 #ifdef CPL_MSB
@@ -788,24 +755,23 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Get some information specific to APP tiled files.               */
 /* -------------------------------------------------------------------- */
-    int bTiled, nTileXSize=0, nTileYSize=0;
-    const char *pszRefinedType = NULL;
+    int nTileXSize = 0;
+    int nTileYSize = 0;
+    const char *pszRefinedType = CSLFetchNameValue(papszHdrLines, "type" );
+    const bool bTiled = CSLFetchNameValue(papszHdrLines,"no_rows") != NULL;
 
-    pszRefinedType = CSLFetchNameValue(papszHdrLines, "type" );
-
-    bTiled = CSLFetchNameValue(papszHdrLines,"no_rows") != NULL;
     if( bTiled )
     {
         if( CSLFetchNameValue(papszHdrLines,"tile_size_rows") )
-            nTileYSize = 
+            nTileYSize =
                 atoi(CSLFetchNameValue(papszHdrLines,"tile_size_rows"));
         if( CSLFetchNameValue(papszHdrLines,"tile_size_columns") )
-            nTileXSize = 
+            nTileXSize =
                 atoi(CSLFetchNameValue(papszHdrLines,"tile_size_columns"));
 
         if (nTileXSize <= 0 || nTileYSize <= 0 ||
-            poDS->nRasterXSize > INT_MAX - (nTileXSize - 1) ||
-            poDS->nRasterYSize > INT_MAX - (nTileYSize - 1))
+            poDS->nRasterXSize-1 > INT_MAX - nTileXSize ||
+            poDS->nRasterYSize-1 > INT_MAX - nTileYSize )
         {
             delete poDS;
             return NULL;
@@ -815,13 +781,9 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Read the directory to find matching band files.                 */
 /* -------------------------------------------------------------------- */
-    char       **papszDirFiles;
-    char       *pszTargetBase, *pszTargetPath;
-    int        nRawBand, nSkipped=0;
-
-    pszTargetPath = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
-    pszTargetBase = CPLStrdup(CPLGetBasename( poOpenInfo->pszFilename ));
-    papszDirFiles = CPLReadDir( CPLGetPath( poOpenInfo->pszFilename ) );
+    char *pszTargetPath = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
+    char *pszTargetBase = CPLStrdup(CPLGetBasename( poOpenInfo->pszFilename ));
+    char **papszDirFiles = VSIReadDir( CPLGetPath( poOpenInfo->pszFilename ) );
     if( papszDirFiles == NULL )
     {
         CPLFree(pszTargetPath);
@@ -830,14 +792,15 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    for( nRawBand = 0; TRUE; nRawBand++ )
+    int nSkipped = 0;
+    for( int nRawBand = 0; true; nRawBand++ )
     {
-        const char  *pszExtension;
-        int          nBand;
-        GDALDataType eDataType;
+        const char *pszExtension = NULL;
 
         /* Find the next raw band file. */
-        for( i = 0; papszDirFiles[i] != NULL; i++ )
+
+        int i = 0;
+        for( ; papszDirFiles[i] != NULL; i++ )
         {
             if( !EQUAL(CPLGetBasename(papszDirFiles[i]),pszTargetBase) )
                 continue;
@@ -845,7 +808,7 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
             pszExtension = CPLGetExtension(papszDirFiles[i]);
             if( strlen(pszExtension) >= 2
                 && isdigit(pszExtension[1])
-                && atoi(pszExtension+1) == nRawBand 
+                && atoi(pszExtension+1) == nRawBand
                 && strchr("bBcCiIjJrRxXzZ",pszExtension[0]) != NULL )
                 break;
         }
@@ -854,24 +817,25 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
             break;
 
         /* open the file for required level of access */
-        VSILFILE     *fpRaw;
-        const char *pszRawFilename = CPLFormFilename(pszTargetPath, 
+        const char *pszRawFilename = CPLFormFilename(pszTargetPath,
                                                      papszDirFiles[i], NULL );
 
+        VSILFILE *fpRaw;
         if( poOpenInfo->eAccess == GA_Update )
             fpRaw = VSIFOpenL( pszRawFilename, "rb+" );
         else
             fpRaw = VSIFOpenL( pszRawFilename, "rb" );
-        
+
         if( fpRaw == NULL )
         {
-            CPLError( CE_Warning, CPLE_OpenFailed, 
-                      "Unable to open %s ... skipping.\n", 
+            CPLError( CE_Warning, CPLE_OpenFailed,
+                      "Unable to open %s ... skipping.\n",
                       pszRawFilename );
             nSkipped++;
             continue;
         }
 
+        GDALDataType eDataType;
         pszExtension = CPLGetExtension(papszDirFiles[i]);
         if( pszRefinedType != NULL )
         {
@@ -895,11 +859,11 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
                 eDataType = GDT_UInt32;
             else if( EQUAL(pszRefinedType,"J*1") )
             {
-                CPLError( CE_Warning, CPLE_OpenFailed, 
-                        "Unable to open band %d because type J*1 is not handled ... skipping.\n", 
+                CPLError( CE_Warning, CPLE_OpenFailed,
+                        "Unable to open band %d because type J*1 is not handled ... skipping.\n",
                          nRawBand + 1 );
                 nSkipped++;
-                VSIFCloseL(fpRaw);
+                CPL_IGNORE_RET_VAL(VSIFCloseL(fpRaw));
                 continue; /* we don't support 1 byte complex */
             }
             else if( EQUAL(pszRefinedType,"J*2") )
@@ -908,52 +872,53 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
                 eDataType = GDT_CInt32;
             else
             {
-                CPLError( CE_Warning, CPLE_OpenFailed, 
-                        "Unable to open band %d because type %s is not handled ... skipping.\n", 
+                CPLError( CE_Warning, CPLE_OpenFailed,
+                        "Unable to open band %d because type %s is not handled ... skipping.\n",
                          nRawBand + 1, pszRefinedType );
                 nSkipped++;
-                VSIFCloseL(fpRaw);
+                CPL_IGNORE_RET_VAL(VSIFCloseL(fpRaw));
                 continue;
             }
         }
-        else if( EQUALN(pszExtension,"b",1) )
+        else if( STARTS_WITH_CI(pszExtension, "b") )
         {
             eDataType = GDT_Byte;
         }
-        else if( EQUALN(pszExtension,"i",1) )
+        else if( STARTS_WITH_CI(pszExtension, "i") )
         {
             eDataType = GDT_UInt16;
         }
-        else if( EQUALN(pszExtension,"j",1) )
+        else if( STARTS_WITH_CI(pszExtension, "j") )
         {
             eDataType = GDT_CInt16;
         }
-        else if( EQUALN(pszExtension,"r",1) )
+        else if( STARTS_WITH_CI(pszExtension, "r") )
         {
             eDataType = GDT_Float32;
         }
-        else if( EQUALN(pszExtension,"x",1) )
+        else if( STARTS_WITH_CI(pszExtension, "x") )
         {
             eDataType = GDT_CFloat32;
         }
         else
         {
-            CPLError( CE_Warning, CPLE_OpenFailed, 
-                    "Unable to open band %d because extension %s is not handled ... skipping.\n", 
+            CPLError( CE_Warning, CPLE_OpenFailed,
+                      "Unable to open band %d because extension %s is not "
+                      "handled ... skipping.\n",
                       nRawBand + 1, pszExtension );
             nSkipped++;
-            VSIFCloseL(fpRaw);
+            CPL_IGNORE_RET_VAL(VSIFCloseL(fpRaw));
             continue;
         }
 
-        nBand = poDS->GetRasterCount() + 1;
+        const int nBand = poDS->GetRasterCount() + 1;
 
-        int nPixelOffset = GDALGetDataTypeSize(eDataType)/8;
+        const int nPixelOffset = GDALGetDataTypeSize(eDataType)/8;
         GDALRasterBand *poBand = NULL;
-        
+
         if( bTiled )
         {
-            poBand = 
+            poBand =
                 new MFFTiledBand( poDS, nBand, fpRaw, nTileXSize, nTileYSize,
                                   eDataType, bNative );
         }
@@ -961,13 +926,14 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
         {
             if (poDS->GetRasterXSize() > INT_MAX / nPixelOffset)
             {
-                CPLError( CE_Warning, CPLE_AppDefined,  "Int overflow occured... skipping");
+                CPLError( CE_Warning, CPLE_AppDefined,
+                          "Int overflow occurred... skipping");
                 nSkipped++;
-                VSIFCloseL(fpRaw);
+                CPL_IGNORE_RET_VAL(VSIFCloseL(fpRaw));
                 continue;
             }
 
-            poBand = 
+            poBand =
                 new RawRasterBand( poDS, nBand, fpRaw, 0, nPixelOffset,
                                    nPixelOffset * poDS->GetRasterXSize(),
                                    eDataType, bNative, TRUE, TRUE );
@@ -987,16 +953,16 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
     {
         if( nSkipped > 0 && poOpenInfo->eAccess )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
+            CPLError( CE_Failure, CPLE_OpenFailed,
                       "Failed to open %d files that were apparently bands.\n"
-                      "Perhaps this dataset is readonly?\n", 
+                      "Perhaps this dataset is readonly?\n",
                       nSkipped );
             delete poDS;
             return NULL;
         }
         else
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
+            CPLError( CE_Failure, CPLE_OpenFailed,
                       "MFF header file read successfully, but no bands\n"
                       "were successfully found and opened." );
             delete poDS;
@@ -1008,25 +974,24 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Set all information from the .hdr that isn't well know to be    */
 /*      metadata.                                                       */
 /* -------------------------------------------------------------------- */
-    for( i = 0; papszHdrLines[i] != NULL; i++ )
+    for( int i = 0; papszHdrLines[i] != NULL; i++ )
     {
-        const char *pszValue;
         char       *pszName;
 
-        pszValue = CPLParseNameValue(papszHdrLines[i], &pszName);
+        const char *pszValue = CPLParseNameValue(papszHdrLines[i], &pszName);
         if( pszName == NULL || pszValue == NULL )
             continue;
 
-        if( !EQUAL(pszName,"END") 
-            && !EQUAL(pszName,"FILE_TYPE") 
-            && !EQUAL(pszName,"BYTE_ORDER") 
-            && !EQUAL(pszName,"no_columns") 
-            && !EQUAL(pszName,"no_rows") 
-            && !EQUAL(pszName,"type") 
-            && !EQUAL(pszName,"tile_size_rows") 
-            && !EQUAL(pszName,"tile_size_columns") 
-            && !EQUAL(pszName,"IMAGE_FILE_FORMAT") 
-            && !EQUAL(pszName,"IMAGE_LINES") 
+        if( !EQUAL(pszName,"END")
+            && !EQUAL(pszName,"FILE_TYPE")
+            && !EQUAL(pszName,"BYTE_ORDER")
+            && !EQUAL(pszName,"no_columns")
+            && !EQUAL(pszName,"no_rows")
+            && !EQUAL(pszName,"type")
+            && !EQUAL(pszName,"tile_size_rows")
+            && !EQUAL(pszName,"tile_size_columns")
+            && !EQUAL(pszName,"IMAGE_FILE_FORMAT")
+            && !EQUAL(pszName,"IMAGE_LINES")
             && !EQUAL(pszName,"LINE_SAMPLES") )
         {
             poDS->SetMetadataItem( pszName, pszValue );
@@ -1040,7 +1005,7 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->ScanForGCPs();
     poDS->ScanForProjectionInfo();
-    
+
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
@@ -1059,19 +1024,19 @@ int GetMFFProjectionType(const char *pszNewProjection)
 {
     OGRSpatialReference oSRS(pszNewProjection);
 
-    if( !EQUALN(pszNewProjection,"GEOGCS",6)
-       && !EQUALN(pszNewProjection,"PROJCS",6)
+    if( !STARTS_WITH_CI(pszNewProjection, "GEOGCS")
+       && !STARTS_WITH_CI(pszNewProjection, "PROJCS")
        && !EQUAL(pszNewProjection,"") )
       {
-          return MFFPRJ_UNRECOGNIZED;       
+          return MFFPRJ_UNRECOGNIZED;
       }
       else if (EQUAL(pszNewProjection,""))
-      { 
-          return MFFPRJ_NONE;  
+      {
+          return MFFPRJ_NONE;
       }
       else
       {
-             if ((oSRS.GetAttrValue("PROJECTION") != NULL) && 
+             if ((oSRS.GetAttrValue("PROJECTION") != NULL) &&
                  (EQUAL(oSRS.GetAttrValue("PROJECTION"),SRS_PT_TRANSVERSE_MERCATOR)))
              {
                return MFFPRJ_UTM;
@@ -1102,12 +1067,12 @@ GDALDataset *MFFDataset::Create( const char * pszFilenameIn,
 /* -------------------------------------------------------------------- */
     if (nBands <= 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "MFF driver does not support %d bands.\n", nBands);
         return NULL;
     }
 
-    if( eType != GDT_Byte && eType != GDT_Float32 && eType != GDT_UInt16 
+    if( eType != GDT_Byte && eType != GDT_Float32 && eType != GDT_UInt16
         && eType != GDT_CInt16 && eType != GDT_CFloat32 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -1121,13 +1086,11 @@ GDALDataset *MFFDataset::Create( const char * pszFilenameIn,
 /* -------------------------------------------------------------------- */
 /*      Establish the base filename (path+filename, less extension).    */
 /* -------------------------------------------------------------------- */
-    char	*pszBaseFilename;
-    int         i;
-
-    pszBaseFilename = (char *) CPLMalloc(strlen(pszFilenameIn)+5);
+    char *pszBaseFilename
+        = reinterpret_cast<char *>( CPLMalloc( strlen( pszFilenameIn ) + 5 ) );
     strcpy( pszBaseFilename, pszFilenameIn );
-    
-    for( i = strlen(pszBaseFilename)-1; i > 0; i-- )
+
+    for( int i = static_cast<int>(strlen(pszBaseFilename))-1; i > 0; i-- )
     {
         if( pszBaseFilename[i] == '.' )
         {
@@ -1138,80 +1101,85 @@ GDALDataset *MFFDataset::Create( const char * pszFilenameIn,
         if( pszBaseFilename[i] == '/' || pszBaseFilename[i] == '\\' )
             break;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create the header file.                                         */
 /* -------------------------------------------------------------------- */
-    VSILFILE       *fp;
-    const char *pszFilename;
+    const char *pszFilename = CPLFormFilename( NULL, pszBaseFilename, "hdr" );
 
-    pszFilename = CPLFormFilename( NULL, pszBaseFilename, "hdr" );
-
-    fp = VSIFOpenL( pszFilename, "wt" );
+    VSILFILE *fp = VSIFOpenL( pszFilename, "wt" );
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "Couldn't create %s.\n", pszFilename );
         CPLFree(pszBaseFilename);
         return NULL;
     }
 
-    VSIFPrintfL( fp, "IMAGE_FILE_FORMAT = MFF\n" );
-    VSIFPrintfL( fp, "FILE_TYPE = IMAGE\n" );
-    VSIFPrintfL( fp, "IMAGE_LINES = %d\n", nYSize );
-    VSIFPrintfL( fp, "LINE_SAMPLES = %d\n", nXSize );
-#ifdef CPL_MSB     
-    VSIFPrintfL( fp, "BYTE_ORDER = MSB\n" );
+    bool bOK = VSIFPrintfL( fp, "IMAGE_FILE_FORMAT = MFF\n" ) >= 0;
+    bOK &= VSIFPrintfL( fp, "FILE_TYPE = IMAGE\n" ) >= 0;
+    bOK &= VSIFPrintfL( fp, "IMAGE_LINES = %d\n", nYSize ) >= 0;
+    bOK &= VSIFPrintfL( fp, "LINE_SAMPLES = %d\n", nXSize ) >= 0;
+#ifdef CPL_MSB
+    bOK &= VSIFPrintfL( fp, "BYTE_ORDER = MSB\n" ) >= 0;
 #else
-    VSIFPrintfL( fp, "BYTE_ORDER = LSB\n" );
+    bOK &= VSIFPrintfL( fp, "BYTE_ORDER = LSB\n" ) >= 0;
 #endif
 
     if (CSLFetchNameValue(papszParmList,"NO_END") == NULL)
-        VSIFPrintfL( fp, "END\n" );
-    
-    VSIFCloseL( fp );
-   
+        bOK &= VSIFPrintfL( fp, "END\n" ) >= 0;
+
+    if( VSIFCloseL( fp ) != 0 )
+        bOK = false;
+
 /* -------------------------------------------------------------------- */
 /*      Create the data files, but don't bother writing any data to them.*/
 /* -------------------------------------------------------------------- */
-    for( int iBand = 0; iBand < nBands; iBand++ )
+    for( int iBand = 0; bOK && iBand < nBands; iBand++ )
     {
         char       szExtension[4];
 
         if( eType == GDT_Byte )
-            sprintf( szExtension, "b%02d", iBand );
+            snprintf( szExtension, sizeof(szExtension), "b%02d", iBand );
         else if( eType == GDT_UInt16 )
-            sprintf( szExtension, "i%02d", iBand );
+            snprintf( szExtension, sizeof(szExtension), "i%02d", iBand );
         else if( eType == GDT_Float32 )
-            sprintf( szExtension, "r%02d", iBand );
+            snprintf( szExtension, sizeof(szExtension),  "r%02d", iBand );
         else if( eType == GDT_CInt16 )
-            sprintf( szExtension, "j%02d", iBand );
+            snprintf( szExtension, sizeof(szExtension), "j%02d", iBand );
         else if( eType == GDT_CFloat32 )
-            sprintf( szExtension, "x%02d", iBand );
+            snprintf( szExtension, sizeof(szExtension), "x%02d", iBand );
 
         pszFilename = CPLFormFilename( NULL, pszBaseFilename, szExtension );
         fp = VSIFOpenL( pszFilename, "wb" );
         if( fp == NULL )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
+            CPLError( CE_Failure, CPLE_OpenFailed,
                       "Couldn't create %s.\n", pszFilename );
             CPLFree(pszBaseFilename);
             return NULL;
         }
 
-        VSIFWriteL( (void *) "", 1, 1, fp );
-        VSIFCloseL( fp );
+        bOK &= VSIFWriteL( reinterpret_cast<void *>( const_cast<char *>( "" ) ),
+                    1, 1, fp ) == 1;
+        if( VSIFCloseL( fp ) != 0 )
+            bOK = false;
+    }
+
+    if( !bOK )
+    {
+        CPLFree( pszBaseFilename );
+        return NULL;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Open the dataset normally.                                      */
 /* -------------------------------------------------------------------- */
-    GDALDataset *poDS;
-
     strcat( pszBaseFilename, ".hdr" );
-    poDS = (GDALDataset *) GDALOpen( pszBaseFilename, GA_Update );
+    GDALDataset *poDS = reinterpret_cast<GDALDataset *>(
+        GDALOpen( pszBaseFilename, GA_Update ) );
     CPLFree( pszBaseFilename );
-    
+
     return poDS;
 }
 
@@ -1227,111 +1195,99 @@ MFFDataset::CreateCopy( const char * pszFilename,
                         GDALProgressFunc pfnProgress,
                         void * pProgressData )
 {
-    MFFDataset	*poDS;
-    GDALDataType eType;
-    int          iBand;
-    char **newpapszOptions=NULL;
-
-    int nBands = poSrcDS->GetRasterCount();
+    const int nBands = poSrcDS->GetRasterCount();
     if (nBands == 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "MFF driver does not support source dataset with zero band.\n");
         return NULL;
     }
 
-    eType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
+    GDALDataType eType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
     if( !pfnProgress( 0.0, NULL, pProgressData ) )
         return NULL;
 
     /* check that other bands match type- sets type */
     /* to unknown if they differ.                  */
-    for( iBand = 1; iBand < poSrcDS->GetRasterCount(); iBand++ )
+    for( int iBand = 1; iBand < poSrcDS->GetRasterCount(); iBand++ )
      {
          GDALRasterBand *poBand = poSrcDS->GetRasterBand( iBand+1 );
          eType = GDALDataTypeUnion( eType, poBand->GetRasterDataType() );
      }
 
-    newpapszOptions=CSLDuplicate(papszOptions);
+    char **newpapszOptions = CSLDuplicate(papszOptions);
     newpapszOptions=CSLSetNameValue(newpapszOptions,"NO_END","TRUE");
 
-    poDS = (MFFDataset *) Create( pszFilename, 
-                                  poSrcDS->GetRasterXSize(), 
-                                  poSrcDS->GetRasterYSize(), 
-                                  poSrcDS->GetRasterCount(), 
-                                  eType, newpapszOptions );
-    
+    MFFDataset *poDS = reinterpret_cast<MFFDataset *>(
+        Create( pszFilename,
+                poSrcDS->GetRasterXSize(),
+                poSrcDS->GetRasterYSize(),
+                poSrcDS->GetRasterCount(),
+                eType, newpapszOptions ) );
+
     CSLDestroy(newpapszOptions);
-   
 
     /* Check that Create worked- return Null if it didn't */
     if (poDS == NULL)
         return NULL;
 
-
 /* -------------------------------------------------------------------- */
 /*      Copy the image data.                                            */
 /* -------------------------------------------------------------------- */
-    int         nXSize = poDS->GetRasterXSize();
-    int         nYSize = poDS->GetRasterYSize();
-    int  	nBlockXSize, nBlockYSize, nBlockTotal, nBlocksDone;
+    const int nXSize = poDS->GetRasterXSize();
+    const int nYSize = poDS->GetRasterYSize();
 
+    int nBlockXSize, nBlockYSize;
     poDS->GetRasterBand(1)->GetBlockSize( &nBlockXSize, &nBlockYSize );
 
-    nBlockTotal = ((nXSize + nBlockXSize - 1) / nBlockXSize)
+    const int nBlockTotal = ((nXSize + nBlockXSize - 1) / nBlockXSize)
         * ((nYSize + nBlockYSize - 1) / nBlockYSize)
         * poSrcDS->GetRasterCount();
 
-    nBlocksDone = 0;
-    for( iBand = 0; iBand < poSrcDS->GetRasterCount(); iBand++ )
+    int nBlocksDone = 0;
+    for( int iBand = 0; iBand < poSrcDS->GetRasterCount(); iBand++ )
     {
         GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand+1 );
         GDALRasterBand *poDstBand = poDS->GetRasterBand( iBand+1 );
-        int	       iYOffset, iXOffset;
-        void           *pData;
-        CPLErr  eErr;
-
 
-        pData = CPLMalloc(nBlockXSize * nBlockYSize
-                          * GDALGetDataTypeSize(eType) / 8);
+        void *pData = CPLMalloc(nBlockXSize * nBlockYSize
+                                * GDALGetDataTypeSize(eType) / 8);
 
-        for( iYOffset = 0; iYOffset < nYSize; iYOffset += nBlockYSize )
+        for( int iYOffset = 0; iYOffset < nYSize; iYOffset += nBlockYSize )
         {
-            for( iXOffset = 0; iXOffset < nXSize; iXOffset += nBlockXSize )
+            for( int iXOffset = 0; iXOffset < nXSize; iXOffset += nBlockXSize )
             {
-                int	nTBXSize, nTBYSize;
-
-                if( !pfnProgress( (nBlocksDone++) / (float) nBlockTotal,
-                                  NULL, pProgressData ) )
+                if( !pfnProgress(
+                       (nBlocksDone++) / static_cast<float>( nBlockTotal ),
+                       NULL, pProgressData ) )
                 {
-                    CPLError( CE_Failure, CPLE_UserInterrupt, 
+                    CPLError( CE_Failure, CPLE_UserInterrupt,
                               "User terminated" );
                     delete poDS;
                     CPLFree( pData );
 
-                    GDALDriver *poMFFDriver = 
-                        (GDALDriver *) GDALGetDriverByName( "MFF" );
+                    GDALDriver *poMFFDriver = reinterpret_cast<GDALDriver *>(
+                        GDALGetDriverByName( "MFF" ) );
                     poMFFDriver->Delete( pszFilename );
                     return NULL;
                 }
 
-                nTBXSize = MIN(nBlockXSize,nXSize-iXOffset);
-                nTBYSize = MIN(nBlockYSize,nYSize-iYOffset);
+                const int nTBXSize = std::min( nBlockXSize, nXSize - iXOffset );
+                const int nTBYSize = std::min( nBlockYSize, nYSize - iYOffset );
+
+                CPLErr eErr = poSrcBand->RasterIO(
+                    GF_Read, iXOffset, iYOffset, nTBXSize, nTBYSize,
+                    pData, nTBXSize, nTBYSize, eType, 0, 0, NULL );
 
-                eErr = poSrcBand->RasterIO( GF_Read, 
-                                            iXOffset, iYOffset, 
-                                            nTBXSize, nTBYSize,
-                                            pData, nTBXSize, nTBYSize,
-                                            eType, 0, 0, NULL );
                 if( eErr != CE_None )
                 {
                     delete poDS;
                     CPLFree( pData );
                     return NULL;
                 }
-            
-                eErr = poDstBand->RasterIO( GF_Write, 
-                                            iXOffset, iYOffset, 
+
+                eErr = poDstBand->RasterIO( GF_Write,
+                                            iXOffset, iYOffset,
                                             nTBXSize, nTBYSize,
                                             pData, nTBXSize, nTBYSize,
                                             eType, 0, 0, NULL );
@@ -1352,19 +1308,14 @@ MFFDataset::CreateCopy( const char * pszFilename,
 /*      Copy georeferencing information, if enough is available.        */
 /* -------------------------------------------------------------------- */
 
-
 /* -------------------------------------------------------------------- */
 /*      Establish the base filename (path+filename, less extension).    */
 /* -------------------------------------------------------------------- */
-    char	*pszBaseFilename;
-    int         i;
-    VSILFILE       *fp;
-    const char *pszFilenameGEO;
-
-    pszBaseFilename = (char *) CPLMalloc(strlen(pszFilename)+5);
+    char *pszBaseFilename = reinterpret_cast<char *>(
+        CPLMalloc(strlen(pszFilename)+5) );
     strcpy( pszBaseFilename, pszFilename );
-    
-    for( i = strlen(pszBaseFilename)-1; i > 0; i-- )
+
+    for( int i = static_cast<int>(strlen(pszBaseFilename))-1; i > 0; i-- )
     {
         if( pszBaseFilename[i] == '.' )
         {
@@ -1376,41 +1327,36 @@ MFFDataset::CreateCopy( const char * pszFilename,
             break;
     }
 
-    pszFilenameGEO = CPLFormFilename( NULL, pszBaseFilename, "hdr" );
+    const char *pszFilenameGEO
+        = CPLFormFilename( NULL, pszBaseFilename, "hdr" );
 
-    fp = VSIFOpenL( pszFilenameGEO, "at" );
+    VSILFILE *fp = VSIFOpenL( pszFilenameGEO, "at" );
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "Couldn't open %s for appending.\n", pszFilenameGEO );
         CPLFree(pszBaseFilename);
         return NULL;
-    }  
-    
+    }
 
     /* MFF requires corner and center gcps */
-    double	*padfTiepoints;
-    int         src_prj;
-    int         georef_created = FALSE;
+    bool georef_created = false;
 
-    padfTiepoints = (double *) CPLMalloc(2*sizeof(double)*5);
+    double *padfTiepoints = reinterpret_cast<double *>(
+        CPLMalloc( 2 * sizeof(double) * 5 ) );
 
-    src_prj = GetMFFProjectionType(poSrcDS->GetProjectionRef());
+    const int src_prj = GetMFFProjectionType(poSrcDS->GetProjectionRef());
 
     if ((src_prj != MFFPRJ_NONE) && (src_prj != MFFPRJ_UNRECOGNIZED))
     {
-      double    *tempGeoTransform = NULL; 
-
-      tempGeoTransform = (double *) CPLMalloc(6*sizeof(double));
+      double *tempGeoTransform = reinterpret_cast<double *>(
+          CPLMalloc( 6 * sizeof(double) ) );
 
       if (( poSrcDS->GetGeoTransform( tempGeoTransform ) == CE_None)
           && (tempGeoTransform[0] != 0.0 || tempGeoTransform[1] != 1.0
           || tempGeoTransform[2] != 0.0 || tempGeoTransform[3] != 0.0
               || tempGeoTransform[4] != 0.0 || ABS(tempGeoTransform[5]) != 1.0 ))
       {
-          OGRCoordinateTransformation *poTransform = NULL;          
-          char *newGCPProjection=NULL;
-
           padfTiepoints[0]=tempGeoTransform[0] + tempGeoTransform[1]*0.5 +\
                            tempGeoTransform[2]*0.5;
 
@@ -1446,79 +1392,76 @@ MFFDataset::CreateCopy( const char * pszFilename,
                            tempGeoTransform[5]*(poSrcDS->GetRasterYSize())/2.0;
 
           OGRSpatialReference oUTMorLL(poSrcDS->GetProjectionRef());
+          char *newGCPProjection = NULL;
           (oUTMorLL.GetAttrNode("GEOGCS"))->exportToWkt(&newGCPProjection);
           OGRSpatialReference oLL(newGCPProjection);
           CPLFree(newGCPProjection);
           newGCPProjection = NULL;
 
-          if EQUALN(poSrcDS->GetProjectionRef(),"PROJCS",6)
+          if STARTS_WITH_CI(poSrcDS->GetProjectionRef(), "PROJCS")
           {
             // projected coordinate system- need to translate gcps */
-            int bSuccess=TRUE;
-            int index;
+            bool bSuccess = true;
 
-            poTransform = OGRCreateCoordinateTransformation( &oUTMorLL, &oLL );
+            OGRCoordinateTransformation *poTransform
+                = OGRCreateCoordinateTransformation( &oUTMorLL, &oLL );
             if( poTransform == NULL )
-                bSuccess = FALSE;
+                bSuccess = false;
 
-            for (index=0;index<5;index++)
+            for ( int index = 0; index < 5; index++ )
             {
+                // TODO: If bSuccess is false, set it to false?
                 if( !bSuccess || !poTransform->Transform( 1, &(padfTiepoints[index*2]), &(padfTiepoints[index*2+1]) ) )
-                  bSuccess = FALSE;
+                  bSuccess = false;
             }
             if (bSuccess == TRUE)
-               georef_created = TRUE;
+               georef_created = true;
           }
           else
           {
-            georef_created = TRUE;
+            georef_created = true;
           }
       }
       CPLFree(tempGeoTransform);
-    } 
-  
-    if (georef_created == TRUE)
+    }
+
+    bool bOK = true;
+    if (georef_created == true)
     {
     /* -------------------------------------------------------------------- */
     /*      top left                                                        */
     /* -------------------------------------------------------------------- */
-          VSIFPrintfL( fp, "TOP_LEFT_CORNER_LATITUDE = %.10f\n", padfTiepoints[1] );
-          VSIFPrintfL( fp, "TOP_LEFT_CORNER_LONGITUDE = %.10f\n", padfTiepoints[0] );
+          bOK &= VSIFPrintfL( fp, "TOP_LEFT_CORNER_LATITUDE = %.10f\n", padfTiepoints[1] ) >= 0;
+          bOK &= VSIFPrintfL( fp, "TOP_LEFT_CORNER_LONGITUDE = %.10f\n", padfTiepoints[0] ) >= 0;
     /* -------------------------------------------------------------------- */
     /*      top_right                                                       */
     /* -------------------------------------------------------------------- */
-          VSIFPrintfL( fp, "TOP_RIGHT_CORNER_LATITUDE = %.10f\n", padfTiepoints[3] );
-          VSIFPrintfL( fp, "TOP_RIGHT_CORNER_LONGITUDE = %.10f\n", padfTiepoints[2] );
+          bOK &= VSIFPrintfL( fp, "TOP_RIGHT_CORNER_LATITUDE = %.10f\n", padfTiepoints[3] ) >= 0;
+          bOK &= VSIFPrintfL( fp, "TOP_RIGHT_CORNER_LONGITUDE = %.10f\n", padfTiepoints[2] ) >= 0;
     /* -------------------------------------------------------------------- */
     /*      bottom_left                                                     */
     /* -------------------------------------------------------------------- */
-          VSIFPrintfL( fp, "BOTTOM_LEFT_CORNER_LATITUDE = %.10f\n", padfTiepoints[5] );
-          VSIFPrintfL( fp, "BOTTOM_LEFT_CORNER_LONGITUDE = %.10f\n", padfTiepoints[4] );
+          bOK &= VSIFPrintfL( fp, "BOTTOM_LEFT_CORNER_LATITUDE = %.10f\n", padfTiepoints[5] ) >= 0;
+          bOK &= VSIFPrintfL( fp, "BOTTOM_LEFT_CORNER_LONGITUDE = %.10f\n", padfTiepoints[4] ) >= 0;
     /* -------------------------------------------------------------------- */
     /*      bottom_right                                                    */
     /* -------------------------------------------------------------------- */
-          VSIFPrintfL( fp, "BOTTOM_RIGHT_CORNER_LATITUDE = %.10f\n", padfTiepoints[7] );
-          VSIFPrintfL( fp, "BOTTOM_RIGHT_CORNER_LONGITUDE = %.10f\n", padfTiepoints[6] );
+          bOK &= VSIFPrintfL( fp, "BOTTOM_RIGHT_CORNER_LATITUDE = %.10f\n", padfTiepoints[7] ) >= 0;
+          bOK &= VSIFPrintfL( fp, "BOTTOM_RIGHT_CORNER_LONGITUDE = %.10f\n", padfTiepoints[6] ) >= 0;
     /* -------------------------------------------------------------------- */
     /*      Center                                                          */
     /* -------------------------------------------------------------------- */
-          VSIFPrintfL( fp, "CENTRE_LATITUDE = %.10f\n", padfTiepoints[9] );
-          VSIFPrintfL( fp, "CENTRE_LONGITUDE = %.10f\n", padfTiepoints[8] );
+          bOK &= VSIFPrintfL( fp, "CENTRE_LATITUDE = %.10f\n", padfTiepoints[9] ) >= 0;
+          bOK &= VSIFPrintfL( fp, "CENTRE_LONGITUDE = %.10f\n", padfTiepoints[8] ) >= 0;
     /* ------------------------------------------------------------------- */
     /*     Ellipsoid/projection                                            */
     /* --------------------------------------------------------------------*/
 
-          
-          MFFSpheroidList *mffEllipsoids;
-          double eq_radius, inv_flattening;
-          OGRErr ogrerrorEq=OGRERR_NONE;
-          OGRErr ogrerrorInvf=OGRERR_NONE;
-          OGRErr ogrerrorOl=OGRERR_NONE;
           const char *pszSrcProjection = poSrcDS->GetProjectionRef();
           char *spheroid_name = NULL;
 
-          if( !EQUALN(pszSrcProjection,"GEOGCS",6)
-           && !EQUALN(pszSrcProjection,"PROJCS",6)
+          if( !STARTS_WITH_CI(pszSrcProjection, "GEOGCS")
+           && !STARTS_WITH_CI(pszSrcProjection, "PROJCS")
            && !EQUAL(pszSrcProjection,"") )
           {
             CPLError( CE_Warning, CPLE_AppDefined,
@@ -1530,67 +1473,82 @@ MFFDataset::CreateCopy( const char * pszFilename,
           {
              OGRSpatialReference oSRS(pszSrcProjection);
 
-             if ((oSRS.GetAttrValue("PROJECTION") != NULL) && 
+             if ((oSRS.GetAttrValue("PROJECTION") != NULL) &&
                  (EQUAL(oSRS.GetAttrValue("PROJECTION"),SRS_PT_TRANSVERSE_MERCATOR)))
              {
-                 VSIFPrintfL(fp,"PROJECTION_NAME = UTM\n");
-                 VSIFPrintfL(fp,"PROJECTION_ORIGIN_LONGITUDE = %f\n",
-                         oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0,&ogrerrorOl));
+                 bOK &= VSIFPrintfL(fp,"PROJECTION_NAME = UTM\n") >= 0;
+                 OGRErr ogrerrorOl = OGRERR_NONE;
+                 bOK &= VSIFPrintfL(fp,"PROJECTION_ORIGIN_LONGITUDE = %f\n",
+                         oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0,&ogrerrorOl)) >= 0;
              }
              else if ((oSRS.GetAttrValue("PROJECTION") == NULL) && (oSRS.IsGeographic()))
              {
-                  VSIFPrintfL(fp,"PROJECTION_NAME = LL\n");
+                  bOK &= VSIFPrintfL(fp,"PROJECTION_NAME = LL\n") >= 0;
              }
              else
              {
                   CPLError( CE_Warning, CPLE_AppDefined,
-                  "Unrecognized projection- no georeferencing information transferred.");
-                  VSIFPrintfL(fp,"PROJECTION_NAME = LL\n");
+                            "Unrecognized projection- no georeferencing "
+                            "information transferred." );
+                  bOK &= VSIFPrintfL(fp,"PROJECTION_NAME = LL\n") >= 0;
              }
-             eq_radius = oSRS.GetSemiMajor(&ogrerrorEq);
-             inv_flattening = oSRS.GetInvFlattening(&ogrerrorInvf);
-             if ((ogrerrorEq == OGRERR_NONE) && (ogrerrorInvf == OGRERR_NONE)) 
+             OGRErr ogrerrorEq = OGRERR_NONE;
+             const double eq_radius = oSRS.GetSemiMajor(&ogrerrorEq);
+             OGRErr ogrerrorInvf = OGRERR_NONE;
+             const double inv_flattening = oSRS.GetInvFlattening(&ogrerrorInvf);
+             if ((ogrerrorEq == OGRERR_NONE) && (ogrerrorInvf == OGRERR_NONE))
              {
-                 mffEllipsoids = new MFFSpheroidList;
+                 MFFSpheroidList *mffEllipsoids = new MFFSpheroidList;
                  spheroid_name = mffEllipsoids->GetSpheroidNameByEqRadiusAndInvFlattening(eq_radius,inv_flattening);
                  if (spheroid_name != NULL)
                  {
-                     VSIFPrintfL(fp,"SPHEROID_NAME = %s\n",spheroid_name );
-                 } 
+                     bOK &= VSIFPrintfL(fp,"SPHEROID_NAME = %s\n",spheroid_name ) >= 0;
+                 }
                  else
                  {
-                     VSIFPrintfL(fp,
-       "SPHEROID_NAME = USER_DEFINED\nSPHEROID_EQUATORIAL_RADIUS = %.10f\nSPHEROID_POLAR_RADIUS = %.10f\n",
-                     eq_radius,eq_radius*(1-1.0/inv_flattening) );
+                     bOK &= VSIFPrintfL(
+                         fp, "SPHEROID_NAME = USER_DEFINED\n"
+                         "SPHEROID_EQUATORIAL_RADIUS = %.10f\n"
+                         "SPHEROID_POLAR_RADIUS = %.10f\n",
+                     eq_radius,eq_radius*(1-1.0/inv_flattening) ) >= 0;
                  }
                  delete mffEllipsoids;
                  CPLFree(spheroid_name);
               }
-          } 
-    } 
-      
+          }
+    }
+
     CPLFree( padfTiepoints );
-    VSIFPrintfL( fp, "END\n" );
-    VSIFCloseL( fp );
-   
+    bOK &= VSIFPrintfL( fp, "END\n" ) >= 0;
+    if( VSIFCloseL( fp ) != 0 )
+        bOK = false;
+
+    if( !bOK )
+    {
+        delete poDS;
+        CPLFree(pszBaseFilename);
+        return NULL;
+    }
+
     /* End of georeferencing stuff */
 
     /* Make sure image data gets flushed */
-    for( iBand = 0; iBand < poDS->GetRasterCount(); iBand++ )
+    for( int iBand = 0; iBand < poDS->GetRasterCount(); iBand++ )
     {
-        RawRasterBand *poDstBand =  (RawRasterBand *) poDS->GetRasterBand( iBand+1 );
+        RawRasterBand *poDstBand = reinterpret_cast<RawRasterBand *>(
+            poDS->GetRasterBand( iBand+1 ) );
         poDstBand->FlushCache();
     }
 
 
     if( !pfnProgress( 1.0, NULL, pProgressData ) )
     {
-        CPLError( CE_Failure, CPLE_UserInterrupt, 
+        CPLError( CE_Failure, CPLE_UserInterrupt,
                   "User terminated" );
         delete poDS;
 
-        GDALDriver *poMFFDriver = 
-            (GDALDriver *) GDALGetDriverByName( "MFF" );
+        GDALDriver *poMFFDriver = reinterpret_cast<GDALDriver *>(
+            GDALGetDriverByName( "MFF" ) );
         poMFFDriver->Delete( pszFilename );
         CPLFree(pszBaseFilename);
         return NULL;
@@ -1604,34 +1562,30 @@ MFFDataset::CreateCopy( const char * pszFilename,
 
 
 /************************************************************************/
-/*                         GDALRegister_MFF()                          */
+/*                         GDALRegister_MFF()                           */
 /************************************************************************/
 
 void GDALRegister_MFF()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "MFF" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "MFF" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "MFF" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Vexcel MFF Raster" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#MFF" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "hdr" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte UInt16 Float32 CInt16 CFloat32" );
-
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = MFFDataset::Open;
-        poDriver->pfnCreate = MFFDataset::Create;
-        poDriver->pfnCreateCopy = MFFDataset::CreateCopy;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "MFF" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Vexcel MFF Raster" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#MFF" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "hdr" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte UInt16 Float32 CInt16 CFloat32" );
+
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = MFFDataset::Open;
+    poDriver->pfnCreate = MFFDataset::Create;
+    poDriver->pfnCreateCopy = MFFDataset::CreateCopy;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/raw/ndfdataset.cpp b/frmts/raw/ndfdataset.cpp
index e5286a1..52cecc1 100644
--- a/frmts/raw/ndfdataset.cpp
+++ b/frmts/raw/ndfdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ndfdataset.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: ndfdataset.cpp 33673 2016-03-07 20:40:54Z goatbar $
  *
  * Project:  NDF Driver
  * Purpose:  Implementation of NLAPS Data Format read support.
@@ -28,11 +28,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "rawdataset.h"
-#include "ogr_spatialref.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "ogr_spatialref.h"
+#include "rawdataset.h"
 
-CPL_CVSID("$Id: ndfdataset.cpp 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: ndfdataset.cpp 33673 2016-03-07 20:40:54Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -65,13 +66,11 @@ class NDFDataset : public RawDataset
 /*                            NDFDataset()                             */
 /************************************************************************/
 
-NDFDataset::NDFDataset()
+NDFDataset::NDFDataset() :
+    pszProjection(CPLStrdup("")),
+    papszExtraFiles(NULL),
+    papszHeader(NULL)
 {
-    pszProjection = CPLStrdup("");
-
-    papszHeader = NULL;
-    papszExtraFiles = NULL;
-
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
@@ -94,7 +93,8 @@ NDFDataset::~NDFDataset()
 
     for( int i = 0; i < GetRasterCount(); i++ )
     {
-        VSIFCloseL( ((RawRasterBand *) GetRasterBand(i+1))->GetFPL() );
+       CPL_IGNORE_RET_VAL(VSIFCloseL( reinterpret_cast<RawRasterBand *>(
+           GetRasterBand(i+1) )->GetFPL() ));
     }
 }
 
@@ -132,8 +132,8 @@ const char *NDFDataset::Get( const char *pszKey, const char *pszDefault )
 
     if( pszResult == NULL )
         return pszDefault;
-    else
-        return pszResult;
+
+    return pszResult;
 }
 
 /************************************************************************/
@@ -143,10 +143,8 @@ const char *NDFDataset::Get( const char *pszKey, const char *pszDefault )
 char **NDFDataset::GetFileList()
 
 {
-    char **papszFileList = NULL;
-
-    // Main data file, etc. 
-    papszFileList = GDALPamDataset::GetFileList();
+    // Main data file, etc.
+    char **papszFileList = GDALPamDataset::GetFileList();
 
     // Header file.
     papszFileList = CSLInsertStrings( papszFileList, -1,
@@ -163,19 +161,19 @@ GDALDataset *NDFDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
 /* -------------------------------------------------------------------- */
-/*      The user must select the header file (ie. .H1).                 */
+/*      The user must select the header file (i.e. .H1).                */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->nHeaderBytes < 50 )
         return NULL;
 
-    if( !EQUALN((const char *)poOpenInfo->pabyHeader,"NDF_REVISION=2",14) 
-        && !EQUALN((const char *)poOpenInfo->pabyHeader,"NDF_REVISION=0",14) )
+    if( !STARTS_WITH_CI(reinterpret_cast<const char *>( poOpenInfo->pabyHeader ), "NDF_REVISION=2")
+        && !STARTS_WITH_CI(reinterpret_cast<const char *>( poOpenInfo->pabyHeader ), "NDF_REVISION=0") )
         return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Read and process the header into a local name/value             */
 /*      stringlist.  We just take off the trailing semicolon.  The      */
-/*      keyword is already seperated from the value by an equal         */
+/*      keyword is already separated from the value by an equal         */
 /*      sign.                                                           */
 /* -------------------------------------------------------------------- */
 
@@ -186,66 +184,62 @@ GDALDataset *NDFDataset::Open( GDALOpenInfo * poOpenInfo )
     const char *pszLine;
     const int nHeaderMax = 1000;
     int nHeaderLines = 0;
-    char **papszHeader = (char **) CPLMalloc(sizeof(char *) * (nHeaderMax+1));
+    char **papszHeader = reinterpret_cast<char **>(
+        CPLMalloc( sizeof(char *) * (nHeaderMax+1) ) );
 
     while( nHeaderLines < nHeaderMax
            && (pszLine = CPLReadLineL( fp )) != NULL
            && !EQUAL(pszLine,"END_OF_HDR;") )
     {
-        char *pszFixed;
-
         if( strstr(pszLine,"=") == NULL )
             break;
 
-        pszFixed = CPLStrdup( pszLine );
+        char *pszFixed = CPLStrdup( pszLine );
         if( pszFixed[strlen(pszFixed)-1] == ';' )
             pszFixed[strlen(pszFixed)-1] = '\0';
-        
+
         papszHeader[nHeaderLines++] = pszFixed;
         papszHeader[nHeaderLines] = NULL;
     }
-    VSIFCloseL(fp);
+    CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
     fp = NULL;
-    
-    if( CSLFetchNameValue( papszHeader, "PIXELS_PER_LINE" ) == NULL 
-        || CSLFetchNameValue( papszHeader, "LINES_PER_DATA_FILE" ) == NULL 
-        || CSLFetchNameValue( papszHeader, "BITS_PER_PIXEL" ) == NULL 
+
+    if( CSLFetchNameValue( papszHeader, "PIXELS_PER_LINE" ) == NULL
+        || CSLFetchNameValue( papszHeader, "LINES_PER_DATA_FILE" ) == NULL
+        || CSLFetchNameValue( papszHeader, "BITS_PER_PIXEL" ) == NULL
         || CSLFetchNameValue( papszHeader, "PIXEL_FORMAT" ) == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
               "Dataset appears to be NDF but is missing a required field.");
         CSLDestroy( papszHeader );
         return NULL;
     }
 
-    if( !EQUAL(CSLFetchNameValue( papszHeader, "PIXEL_FORMAT"),
-               "BYTE" ) 
+    if( !EQUAL(CSLFetchNameValue( papszHeader, "PIXEL_FORMAT"), "BYTE" )
         || !EQUAL(CSLFetchNameValue( papszHeader, "BITS_PER_PIXEL"),"8") )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Currently NDF driver supports only 8bit BYTE format." );
         CSLDestroy( papszHeader );
         return NULL;
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
         CSLDestroy( papszHeader );
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The NDF driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    NDFDataset 	*poDS;
-
-    poDS = new NDFDataset();
+    NDFDataset 	*poDS = new NDFDataset();
     poDS->papszHeader = papszHeader;
 
     poDS->nRasterXSize = atoi(poDS->Get("PIXELS_PER_LINE",""));
@@ -254,16 +248,15 @@ GDALDataset *NDFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a raw raster band for each file.                         */
 /* -------------------------------------------------------------------- */
-    int iBand;
-    const char* pszBand = CSLFetchNameValue(papszHeader, 
-                                        "NUMBER_OF_BANDS_IN_VOLUME");
+    const char* pszBand = CSLFetchNameValue(papszHeader,
+                                            "NUMBER_OF_BANDS_IN_VOLUME");
     if (pszBand == NULL)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Cannot find band count");
         delete poDS;
         return NULL;
     }
-    int nBands = atoi(pszBand);
+    const int nBands = atoi(pszBand);
 
     if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) ||
         !GDALCheckBandCount(nBands, FALSE))
@@ -272,24 +265,22 @@ GDALDataset *NDFDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    for( iBand = 0; iBand < nBands; iBand++ )
+    for( int iBand = 0; iBand < nBands; iBand++ )
     {
         char szKey[100];
-        CPLString osFilename;
-
-        sprintf( szKey, "BAND%d_FILENAME", iBand+1 );
-        osFilename = poDS->Get(szKey,"");
+        snprintf( szKey, sizeof(szKey), "BAND%d_FILENAME", iBand+1 );
+        CPLString osFilename = poDS->Get(szKey,"");
 
         // NDF1 file do not include the band filenames.
         if( osFilename.size() == 0 )
         {
             char szBandExtension[15];
-            sprintf( szBandExtension, "I%d", iBand+1 );
-            osFilename = CPLResetExtension( poOpenInfo->pszFilename, 
+            snprintf( szBandExtension, sizeof(szBandExtension), "I%d", iBand+1 );
+            osFilename = CPLResetExtension( poOpenInfo->pszFilename,
                                             szBandExtension );
         }
         else
-        {      
+        {
             CPLString osBasePath = CPLGetPath(poOpenInfo->pszFilename);
             osFilename = CPLFormFilename( osBasePath, osFilename, NULL);
         }
@@ -297,28 +288,28 @@ GDALDataset *NDFDataset::Open( GDALOpenInfo * poOpenInfo )
         VSILFILE *fpRaw = VSIFOpenL( osFilename, "rb" );
         if( fpRaw == NULL )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Failed to open band file: %s", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Failed to open band file: %s",
                       osFilename.c_str() );
             delete poDS;
             return NULL;
         }
-        poDS->papszExtraFiles = 
-            CSLAddString( poDS->papszExtraFiles, 
+        poDS->papszExtraFiles =
+            CSLAddString( poDS->papszExtraFiles,
                           osFilename );
 
-        RawRasterBand *poBand = 
+        RawRasterBand *poBand =
             new RawRasterBand( poDS, iBand+1, fpRaw, 0, 1, poDS->nRasterXSize,
                                GDT_Byte, TRUE, TRUE );
-        
-        sprintf( szKey, "BAND%d_NAME", iBand+1 );
+
+        snprintf( szKey, sizeof(szKey), "BAND%d_NAME", iBand+1 );
         poBand->SetDescription( poDS->Get(szKey, "") );
 
-        sprintf( szKey, "BAND%d_WAVELENGTHS", iBand+1 );
+        snprintf( szKey, sizeof(szKey), "BAND%d_WAVELENGTHS", iBand+1 );
         poBand->SetMetadataItem( "WAVELENGTHS", poDS->Get(szKey,"") );
 
-        sprintf( szKey, "BAND%d_RADIOMETRIC_GAINS/BIAS", iBand+1 );
-        poBand->SetMetadataItem( "RADIOMETRIC_GAINS_BIAS", 
+        snprintf( szKey, sizeof(szKey), "BAND%d_RADIOMETRIC_GAINS/BIAS", iBand+1 );
+        poBand->SetMetadataItem( "RADIOMETRIC_GAINS_BIAS",
                                  poDS->Get(szKey,"") );
 
         poDS->SetBand( iBand+1, poBand );
@@ -328,14 +319,13 @@ GDALDataset *NDFDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Fetch and parse USGS projection parameters.                     */
 /* -------------------------------------------------------------------- */
     double adfUSGSParms[15] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-    char **papszParmTokens = 
+    char **papszParmTokens =
         CSLTokenizeStringComplex( poDS->Get( "USGS_PROJECTION_NUMBER", "" ),
                                   ",", FALSE, TRUE );
 
     if( CSLCount( papszParmTokens ) >= 15 )
     {
-        int i;
-        for( i = 0; i < 15; i++ )
+        for( int i = 0; i < 15; i++ )
             adfUSGSParms[i] = CPLAtof(papszParmTokens[i]);
     }
     CSLDestroy(papszParmTokens);
@@ -345,26 +335,27 @@ GDALDataset *NDFDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Minimal georef support ... should add full USGS style           */
 /*      support at some point.                                          */
 /* -------------------------------------------------------------------- */
-    OGRSpatialReference oSRS;
-    int nUSGSProjection = atoi(poDS->Get( "USGS_PROJECTION_NUMBER", "" ));
-    int nZone = atoi(poDS->Get("USGS_MAP_ZONE","0"));
+    const int nUSGSProjection = atoi(poDS->Get( "USGS_PROJECTION_NUMBER", "" ));
+    const int nZone = atoi(poDS->Get("USGS_MAP_ZONE","0"));
 
+    OGRSpatialReference oSRS;
     oSRS.importFromUSGS( nUSGSProjection, nZone, adfUSGSParms, 12 );
 
-    CPLString osDatum = poDS->Get( "HORIZONTAL_DATUM", "" );
-    if( EQUAL(osDatum,"WGS84") || EQUAL(osDatum,"NAD83") 
+    const CPLString osDatum = poDS->Get( "HORIZONTAL_DATUM", "" );
+    if( EQUAL(osDatum,"WGS84") || EQUAL(osDatum,"NAD83")
         || EQUAL(osDatum,"NAD27") )
     {
         oSRS.SetWellKnownGeogCS( osDatum );
     }
-    else if( EQUALN(osDatum,"NAD27",5) )
+    else if( STARTS_WITH_CI(osDatum, "NAD27") )
     {
         oSRS.SetWellKnownGeogCS( "NAD27" );
     }
     else
     {
         CPLError( CE_Warning, CPLE_AppDefined,
-                  "Unrecognised datum name in NLAPS/NDF file:%s, assuming WGS84.", 
+                  "Unrecognized datum name in NLAPS/NDF file:%s, "
+                  "assuming WGS84.",
                   osDatum.c_str() );
         oSRS.SetWellKnownGeogCS( "WGS84" );
     }
@@ -379,27 +370,27 @@ GDALDataset *NDFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Get geotransform.                                               */
 /* -------------------------------------------------------------------- */
-    char **papszUL = CSLTokenizeString2( 
+    char **papszUL = CSLTokenizeString2(
         poDS->Get("UPPER_LEFT_CORNER",""), ",", 0 );
-    char **papszUR = CSLTokenizeString2( 
+    char **papszUR = CSLTokenizeString2(
         poDS->Get("UPPER_RIGHT_CORNER",""), ",", 0 );
-    char **papszLL = CSLTokenizeString2( 
+    char **papszLL = CSLTokenizeString2(
         poDS->Get("LOWER_LEFT_CORNER",""), ",", 0 );
-    
-    if( CSLCount(papszUL) == 4 
-        && CSLCount(papszUR) == 4 
+
+    if( CSLCount(papszUL) == 4
+        && CSLCount(papszUR) == 4
         && CSLCount(papszLL) == 4 )
     {
         poDS->adfGeoTransform[0] = CPLAtof(papszUL[2]);
-        poDS->adfGeoTransform[1] = 
+        poDS->adfGeoTransform[1] =
             (CPLAtof(papszUR[2]) - CPLAtof(papszUL[2])) / (poDS->nRasterXSize-1);
-        poDS->adfGeoTransform[2] = 
+        poDS->adfGeoTransform[2] =
             (CPLAtof(papszUR[3]) - CPLAtof(papszUL[3])) / (poDS->nRasterXSize-1);
 
         poDS->adfGeoTransform[3] = CPLAtof(papszUL[3]);
-        poDS->adfGeoTransform[4] = 
+        poDS->adfGeoTransform[4] =
             (CPLAtof(papszLL[2]) - CPLAtof(papszUL[2])) / (poDS->nRasterYSize-1);
-        poDS->adfGeoTransform[5] = 
+        poDS->adfGeoTransform[5] =
             (CPLAtof(papszLL[3]) - CPLAtof(papszUL[3])) / (poDS->nRasterYSize-1);
 
         // Move origin up-left half a pixel.
@@ -412,7 +403,7 @@ GDALDataset *NDFDataset::Open( GDALOpenInfo * poOpenInfo )
     CSLDestroy( papszUL );
     CSLDestroy( papszLL );
     CSLDestroy( papszUR );
-                      
+
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
@@ -424,7 +415,7 @@ GDALDataset *NDFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -434,23 +425,18 @@ GDALDataset *NDFDataset::Open( GDALOpenInfo * poOpenInfo )
 void GDALRegister_NDF()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "NDF" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "NDF" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "NDF" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "NLAPS Data Format" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#NDF" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = NDFDataset::Open;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
-}
+    GDALDriver *poDriver = new GDALDriver();
 
+    poDriver->SetDescription( "NDF" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "NLAPS Data Format" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#NDF" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = NDFDataset::Open;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/frmts/raw/ntv2dataset.cpp b/frmts/raw/ntv2dataset.cpp
index c403749..0b996b4 100644
--- a/frmts/raw/ntv2dataset.cpp
+++ b/frmts/raw/ntv2dataset.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: ntv2dataset.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: ntv2dataset.cpp 33673 2016-03-07 20:40:54Z goatbar $
  *
  * Project:  Horizontal Datum Formats
- * Purpose:  Implementation of NTv2 datum shift format used in Canada, France, 
+ * Purpose:  Implementation of NTv2 datum shift format used in Canada, France,
  *           Australia and elsewhere.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  * Financial Support: i-cubed (http://www.i-cubed.com)
@@ -30,16 +30,17 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "rawdataset.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
 #include "ogr_srs_api.h"
+#include "rawdataset.h"
 
-CPL_CVSID("$Id: ntv2dataset.cpp 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: ntv2dataset.cpp 33673 2016-03-07 20:40:54Z goatbar $");
 
-/** 
+/**
  * The header for the file, and each grid consists of 11 16byte records.
  * The first half is an ASCII label, and the second half is the value
- * often in a little endian int or float. 
+ * often in a little endian int or float.
  *
  * Example:
 
@@ -84,11 +85,12 @@ these both in the more conventional orientation.
 class NTv2Dataset : public RawDataset
 {
   public:
+    bool        m_bMustSwap;
     VSILFILE	*fpImage;	// image data file.
 
     int         nRecordLength;
     vsi_l_offset nGridOffset;
-    
+
     double      adfGeoTransform[6];
 
     void        CaptureMetadataItem( char *pszItem );
@@ -98,7 +100,7 @@ class NTv2Dataset : public RawDataset
   public:
     		NTv2Dataset();
     	        ~NTv2Dataset();
-    
+
     virtual CPLErr SetGeoTransform( double * padfTransform );
     virtual CPLErr GetGeoTransform( double * padfTransform );
     virtual const char *GetProjectionRef();
@@ -121,10 +123,7 @@ class NTv2Dataset : public RawDataset
 /*                             NTv2Dataset()                          */
 /************************************************************************/
 
-NTv2Dataset::NTv2Dataset()
-{
-    fpImage = NULL;
-}
+NTv2Dataset::NTv2Dataset() : m_bMustSwap(false), fpImage(NULL), nRecordLength(0), nGridOffset(0) { }
 
 /************************************************************************/
 /*                            ~NTv2Dataset()                          */
@@ -136,7 +135,36 @@ NTv2Dataset::~NTv2Dataset()
     FlushCache();
 
     if( fpImage != NULL )
-        VSIFCloseL( fpImage );
+    {
+        if( VSIFCloseL( fpImage ) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        }
+    }
+}
+
+/************************************************************************/
+/*                        SwapPtr32IfNecessary()                        */
+/************************************************************************/
+
+static void SwapPtr32IfNecessary( bool bMustSwap, void* ptr )
+{
+    if( bMustSwap )
+    {
+        CPL_SWAP32PTR( (GByte*)ptr );
+    }
+}
+
+/************************************************************************/
+/*                        SwapPtr64IfNecessary()                        */
+/************************************************************************/
+
+static void SwapPtr64IfNecessary( bool bMustSwap, void* ptr )
+{
+    if( bMustSwap )
+    {
+        CPL_SWAP64PTR( (GByte*)ptr );
+    }
 }
 
 /************************************************************************/
@@ -162,11 +190,11 @@ void NTv2Dataset::FlushCache()
     char achFileHeader[11*16];
     char achGridHeader[11*16];
 
-    VSIFSeekL( fpImage, 0, SEEK_SET );
-    VSIFReadL( achFileHeader, 11, 16, fpImage );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( fpImage, 0, SEEK_SET ));
+    CPL_IGNORE_RET_VAL(VSIFReadL( achFileHeader, 11, 16, fpImage ));
 
-    VSIFSeekL( fpImage, nGridOffset, SEEK_SET );
-    VSIFReadL( achGridHeader, 11, 16, fpImage );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( fpImage, nGridOffset, SEEK_SET ));
+    CPL_IGNORE_RET_VAL(VSIFReadL( achGridHeader, 11, 16, fpImage ));
 
 /* -------------------------------------------------------------------- */
 /*      Update the grid, and file headers with any available            */
@@ -174,10 +202,9 @@ void NTv2Dataset::FlushCache()
 /*      things "clean" from a PAM point of view.                        */
 /* -------------------------------------------------------------------- */
     char **papszMD = GetMetadata();
-    int i;
-    int bSomeLeftOver = FALSE;
+    bool bSomeLeftOver = false;
 
-    for( i = 0; papszMD != NULL && papszMD[i] != NULL; i++ )
+    for( int i = 0; papszMD != NULL && papszMD[i] != NULL; i++ )
     {
         char *pszKey = NULL;
         const char *pszValue = CPLParseNameValue( papszMD[i], &pszKey );
@@ -207,25 +234,25 @@ void NTv2Dataset::FlushCache()
         else if( EQUAL(pszKey,"MAJOR_F") )
         {
             double dfValue = CPLAtof(pszValue);
-            CPL_LSBPTR64( &dfValue );
+            SwapPtr64IfNecessary( m_bMustSwap, &dfValue );
             memcpy( achFileHeader + 7*16+8, &dfValue, 8 );
         }
         else if( EQUAL(pszKey,"MINOR_F") )
         {
             double dfValue = CPLAtof(pszValue);
-            CPL_LSBPTR64( &dfValue );
+            SwapPtr64IfNecessary( m_bMustSwap, &dfValue );
             memcpy( achFileHeader + 8*16+8, &dfValue, 8 );
         }
         else if( EQUAL(pszKey,"MAJOR_T") )
         {
             double dfValue = CPLAtof(pszValue);
-            CPL_LSBPTR64( &dfValue );
+            SwapPtr64IfNecessary( m_bMustSwap, &dfValue );
             memcpy( achFileHeader + 9*16+8, &dfValue, 8 );
         }
         else if( EQUAL(pszKey,"MINOR_T") )
         {
             double dfValue = CPLAtof(pszValue);
-            CPL_LSBPTR64( &dfValue );
+            SwapPtr64IfNecessary( m_bMustSwap, &dfValue );
             memcpy( achFileHeader + 10*16+8, &dfValue, 8 );
         }
         else if( EQUAL(pszKey,"SUB_NAME") )
@@ -250,20 +277,20 @@ void NTv2Dataset::FlushCache()
         }
         else
         {
-            bSomeLeftOver = TRUE;
+            bSomeLeftOver = true;
         }
-        
+
         CPLFree( pszKey );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Load grid and file headers.                                     */
 /* -------------------------------------------------------------------- */
-    VSIFSeekL( fpImage, 0, SEEK_SET );
-    VSIFWriteL( achFileHeader, 11, 16, fpImage );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( fpImage, 0, SEEK_SET ));
+    CPL_IGNORE_RET_VAL(VSIFWriteL( achFileHeader, 11, 16, fpImage ));
 
-    VSIFSeekL( fpImage, nGridOffset, SEEK_SET );
-    VSIFWriteL( achGridHeader, 11, 16, fpImage );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( fpImage, nGridOffset, SEEK_SET ));
+    CPL_IGNORE_RET_VAL(VSIFWriteL( achGridHeader, 11, 16, fpImage ));
 
 /* -------------------------------------------------------------------- */
 /*      Clear flags if we got everything, then let pam and below do     */
@@ -282,16 +309,16 @@ void NTv2Dataset::FlushCache()
 int NTv2Dataset::Identify( GDALOpenInfo *poOpenInfo )
 
 {
-    if( EQUALN(poOpenInfo->pszFilename,"NTv2:",5) )
+    if( STARTS_WITH_CI(poOpenInfo->pszFilename, "NTv2:") )
         return TRUE;
-    
+
     if( poOpenInfo->nHeaderBytes < 64 )
         return FALSE;
 
-    if( !EQUALN((const char *)poOpenInfo->pabyHeader + 0, "NUM_OREC", 8 ) )
+    if( !STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader + 0, "NUM_OREC") )
         return FALSE;
 
-    if( !EQUALN((const char *)poOpenInfo->pabyHeader +16, "NUM_SREC", 8 ) )
+    if( !STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader +16, "NUM_SREC") )
         return FALSE;
 
     return TRUE;
@@ -306,35 +333,33 @@ GDALDataset *NTv2Dataset::Open( GDALOpenInfo * poOpenInfo )
 {
     if( !Identify( poOpenInfo ) )
         return NULL;
-        
+
 /* -------------------------------------------------------------------- */
-/*      Are we targetting a particular grid?                            */
+/*      Are we targeting a particular grid?                             */
 /* -------------------------------------------------------------------- */
     CPLString osFilename;
     int iTargetGrid = -1;
 
-    if( EQUALN(poOpenInfo->pszFilename,"NTv2:",5) )
+    if( STARTS_WITH_CI(poOpenInfo->pszFilename, "NTv2:") )
     {
         const char *pszRest = poOpenInfo->pszFilename+5;
-        
+
         iTargetGrid = atoi(pszRest);
         while( *pszRest != '\0' && *pszRest != ':' )
             pszRest++;
-     
+
         if( *pszRest == ':' )
             pszRest++;
-        
+
         osFilename = pszRest;
     }
     else
         osFilename = poOpenInfo->pszFilename;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    NTv2Dataset 	*poDS;
-
-    poDS = new NTv2Dataset();
+    NTv2Dataset *poDS = new NTv2Dataset();
     poDS->eAccess = poOpenInfo->eAccess;
 
 /* -------------------------------------------------------------------- */
@@ -354,15 +379,30 @@ GDALDataset *NTv2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Read the file header.                                           */
 /* -------------------------------------------------------------------- */
-    char  achHeader[11*16];
-    GInt32 nSubFileCount;
-    double dfValue;
-    CPLString osFValue;
-
-    VSIFSeekL( poDS->fpImage, 0, SEEK_SET );
-    VSIFReadL( achHeader, 11, 16, poDS->fpImage );
+    char achHeader[11*16];
+    if (VSIFSeekL( poDS->fpImage, 0, SEEK_SET ) != 0 ||
+        VSIFReadL( achHeader, 11, 16, poDS->fpImage ) != 16 )
+    {
+        delete poDS;
+        return NULL;
+    }
 
-    CPL_LSBPTR32( achHeader + 2*16 + 8 );
+    const bool bIsLE = (achHeader[8] == 11 && achHeader[9] == 0 && achHeader[10] == 0 && achHeader[11] == 0);
+    const bool bIsBE = (achHeader[8] == 0 && achHeader[9] == 0 && achHeader[10] == 0 && achHeader[11] == 11);
+    if( !bIsLE && !bIsBE )
+    {
+        delete poDS;
+        return NULL;
+    }
+#ifdef CPL_LSB
+    const bool bMustSwap = bIsBE;
+#else
+    const bool bMustSwap = bIsLE;
+#endif
+    poDS->m_bMustSwap = bMustSwap;
+
+    SwapPtr32IfNecessary( bMustSwap, achHeader + 2*16 + 8 );
+    GInt32 nSubFileCount;
     memcpy( &nSubFileCount, achHeader + 2*16 + 8, 4 );
     if (nSubFileCount <= 0 || nSubFileCount >= 1024)
     {
@@ -377,40 +417,37 @@ GDALDataset *NTv2Dataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->CaptureMetadataItem( achHeader + 5*16 );
     poDS->CaptureMetadataItem( achHeader + 6*16 );
 
+    double dfValue;
     memcpy( &dfValue, achHeader + 7*16 + 8, 8 );
-    CPL_LSBPTR64( &dfValue );
+    SwapPtr64IfNecessary( bMustSwap, &dfValue );
+    CPLString osFValue;
     osFValue.Printf( "%.15g", dfValue );
     poDS->SetMetadataItem( "MAJOR_F", osFValue );
-    
+
     memcpy( &dfValue, achHeader + 8*16 + 8, 8 );
-    CPL_LSBPTR64( &dfValue );
+    SwapPtr64IfNecessary( bMustSwap, &dfValue );
     osFValue.Printf( "%.15g", dfValue );
     poDS->SetMetadataItem( "MINOR_F", osFValue );
-    
+
     memcpy( &dfValue, achHeader + 9*16 + 8, 8 );
-    CPL_LSBPTR64( &dfValue );
+    SwapPtr64IfNecessary( bMustSwap, &dfValue );
     osFValue.Printf( "%.15g", dfValue );
     poDS->SetMetadataItem( "MAJOR_T", osFValue );
-    
+
     memcpy( &dfValue, achHeader + 10*16 + 8, 8 );
-    CPL_LSBPTR64( &dfValue );
+    SwapPtr64IfNecessary( bMustSwap, &dfValue );
     osFValue.Printf( "%.15g", dfValue );
     poDS->SetMetadataItem( "MINOR_T", osFValue );
 
 /* ==================================================================== */
 /*      Loop over grids.                                                */
 /* ==================================================================== */
-    int iGrid;
     vsi_l_offset nGridOffset = sizeof(achHeader);
 
-    for( iGrid = 0; iGrid < nSubFileCount; iGrid++ )
+    for( int iGrid = 0; iGrid < nSubFileCount; iGrid++ )
     {
-        CPLString  osSubName;
-        int i;
-        GUInt32 nGSCount;
-
-        VSIFSeekL( poDS->fpImage, nGridOffset, SEEK_SET );
-        if (VSIFReadL( achHeader, 11, 16, poDS->fpImage ) != 16)
+        if (VSIFSeekL( poDS->fpImage, nGridOffset, SEEK_SET ) < 0 ||
+            VSIFReadL( achHeader, 11, 16, poDS->fpImage ) != 16)
         {
             CPLError(CE_Failure, CPLE_AppDefined,
                      "Cannot read header for subfile %d", iGrid);
@@ -418,13 +455,15 @@ GDALDataset *NTv2Dataset::Open( GDALOpenInfo * poOpenInfo )
             return NULL;
         }
 
-        for( i = 4; i <= 9; i++ )
-            CPL_LSBPTR64( achHeader + i*16 + 8 );
-        
-        CPL_LSBPTR32( achHeader + 10*16 + 8 );
-        
+        for( int i = 4; i <= 9; i++ )
+            SwapPtr64IfNecessary( bMustSwap, achHeader + i*16 + 8 );
+
+        SwapPtr32IfNecessary( bMustSwap, achHeader + 10*16 + 8 );
+
+        GUInt32 nGSCount;
         memcpy( &nGSCount, achHeader + 10*16 + 8, 4 );
 
+        CPLString osSubName;
         osSubName.assign( achHeader + 8, 8 );
         osSubName.Trim();
 
@@ -452,7 +491,7 @@ GDALDataset *NTv2Dataset::Open( GDALOpenInfo * poOpenInfo )
             poDS->SetMetadataItem( osKey, osValue, "SUBDATASETS" );
         }
 
-        nGridOffset += (11+(vsi_l_offset)nGSCount) * 16;
+        nGridOffset += (11 + static_cast<vsi_l_offset>( nGSCount ) ) * 16;
     }
 
 /* -------------------------------------------------------------------- */
@@ -476,21 +515,20 @@ GDALDataset *NTv2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /*      portions of the header.                                         */
 /************************************************************************/
 
-int NTv2Dataset::OpenGrid( char *pachHeader, vsi_l_offset nGridOffset )
+int NTv2Dataset::OpenGrid( char *pachHeader, vsi_l_offset nGridOffsetIn )
 
 {
-    this->nGridOffset = nGridOffset;
+    nGridOffset = nGridOffsetIn;
 
 /* -------------------------------------------------------------------- */
 /*      Read the grid header.                                           */
 /* -------------------------------------------------------------------- */
-    double s_lat, n_lat, e_long, w_long, lat_inc, long_inc;
-
     CaptureMetadataItem( pachHeader + 0*16 );
     CaptureMetadataItem( pachHeader + 1*16 );
     CaptureMetadataItem( pachHeader + 2*16 );
     CaptureMetadataItem( pachHeader + 3*16 );
 
+    double s_lat, n_lat, e_long, w_long, lat_inc, long_inc;
     memcpy( &s_lat,  pachHeader + 4*16 + 8, 8 );
     memcpy( &n_lat,  pachHeader + 5*16 + 8, 8 );
     memcpy( &e_long, pachHeader + 6*16 + 8, 8 );
@@ -501,8 +539,8 @@ int NTv2Dataset::OpenGrid( char *pachHeader, vsi_l_offset nGridOffset )
     e_long *= -1;
     w_long *= -1;
 
-    nRasterXSize = (int) floor((e_long - w_long) / long_inc + 1.5);
-    nRasterYSize = (int) floor((n_lat - s_lat) / lat_inc + 1.5);
+    nRasterXSize = static_cast<int>( floor((e_long - w_long) / long_inc + 1.5) );
+    nRasterYSize = static_cast<int>( floor((n_lat - s_lat) / lat_inc + 1.5) );
 
     if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize))
         return FALSE;
@@ -514,25 +552,23 @@ int NTv2Dataset::OpenGrid( char *pachHeader, vsi_l_offset nGridOffset )
 /*      to bottom orientation, and also to remap east to west, to       */
 /*      west to east.                                                   */
 /* -------------------------------------------------------------------- */
-    int iBand;
-    
-    for( iBand = 0; iBand < 4; iBand++ )
+    for( int iBand = 0; iBand < 4; iBand++ )
     {
-        RawRasterBand *poBand = 
-            new RawRasterBand( this, iBand+1, fpImage, 
+        RawRasterBand *poBand =
+            new RawRasterBand( this, iBand+1, fpImage,
                                nGridOffset + 4*iBand + 11*16
                                + (nRasterXSize-1) * 16
                                + (nRasterYSize-1) * 16 * nRasterXSize,
                                -16, -16 * nRasterXSize,
-                               GDT_Float32, CPL_IS_LSB, TRUE, FALSE );
+                               GDT_Float32, !m_bMustSwap, TRUE, FALSE );
         SetBand( iBand+1, poBand );
     }
-    
+
     GetRasterBand(1)->SetDescription( "Latitude Offset (arc seconds)" );
     GetRasterBand(2)->SetDescription( "Longitude Offset (arc seconds)" );
     GetRasterBand(3)->SetDescription( "Latitude Error" );
     GetRasterBand(4)->SetDescription( "Longitude Error" );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Setup georeferencing.                                           */
 /* -------------------------------------------------------------------- */
@@ -582,14 +618,14 @@ CPLErr NTv2Dataset::SetGeoTransform( double * padfTransform )
     if( eAccess == GA_ReadOnly )
     {
         CPLError( CE_Failure, CPLE_NoWriteAccess,
-                  "Unable to update geotransform on readonly file." ); 
+                  "Unable to update geotransform on readonly file." );
         return CE_Failure;
     }
 
     if( padfTransform[2] != 0.0 || padfTransform[4] != 0.0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Rotated and sheared geotransforms not supported for NTv2."); 
+                  "Rotated and sheared geotransforms not supported for NTv2.");
         return CE_Failure;
     }
 
@@ -602,42 +638,42 @@ CPLErr NTv2Dataset::SetGeoTransform( double * padfTransform )
     char   achHeader[11*16];
 
     // read grid header
-    VSIFSeekL( fpImage, nGridOffset, SEEK_SET );
-    VSIFReadL( achHeader, 11, 16, fpImage );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( fpImage, nGridOffset, SEEK_SET ));
+    CPL_IGNORE_RET_VAL(VSIFReadL( achHeader, 11, 16, fpImage ));
 
     // S_LAT
     dfValue = 3600 * (adfGeoTransform[3] + (nRasterYSize-0.5) * adfGeoTransform[5]);
-    CPL_LSBPTR64( &dfValue );
+    SwapPtr64IfNecessary( m_bMustSwap, &dfValue );
     memcpy( achHeader +  4*16 + 8, &dfValue, 8 );
 
     // N_LAT
     dfValue = 3600 * (adfGeoTransform[3] + 0.5 * adfGeoTransform[5]);
-    CPL_LSBPTR64( &dfValue );
+    SwapPtr64IfNecessary( m_bMustSwap, &dfValue );
     memcpy( achHeader +  5*16 + 8, &dfValue, 8 );
 
     // E_LONG
     dfValue = -3600 * (adfGeoTransform[0] + (nRasterXSize-0.5)*adfGeoTransform[1]);
-    CPL_LSBPTR64( &dfValue );
+    SwapPtr64IfNecessary( m_bMustSwap, &dfValue );
     memcpy( achHeader +  6*16 + 8, &dfValue, 8 );
 
     // W_LONG
     dfValue = -3600 * (adfGeoTransform[0] + 0.5 * adfGeoTransform[1]);
-    CPL_LSBPTR64( &dfValue );
+    SwapPtr64IfNecessary( m_bMustSwap, &dfValue );
     memcpy( achHeader +  7*16 + 8, &dfValue, 8 );
 
     // LAT_INC
     dfValue = -3600 * adfGeoTransform[5];
-    CPL_LSBPTR64( &dfValue );
+    SwapPtr64IfNecessary( m_bMustSwap, &dfValue );
     memcpy( achHeader +  8*16 + 8, &dfValue, 8 );
-    
+
     // LONG_INC
     dfValue = 3600 * adfGeoTransform[1];
-    CPL_LSBPTR64( &dfValue );
+    SwapPtr64IfNecessary( m_bMustSwap, &dfValue );
     memcpy( achHeader +  9*16 + 8, &dfValue, 8 );
-    
+
     // write grid header.
-    VSIFSeekL( fpImage, nGridOffset, SEEK_SET );
-    VSIFWriteL( achHeader, 11, 16, fpImage );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( fpImage, nGridOffset, SEEK_SET ));
+    CPL_IGNORE_RET_VAL(VSIFWriteL( achHeader, 11, 16, fpImage ));
 
     return CE_None;
 }
@@ -659,7 +695,7 @@ const char *NTv2Dataset::GetProjectionRef()
 
 GDALDataset *NTv2Dataset::Create( const char * pszFilename,
                                   int nXSize, int nYSize,
-                                  CPL_UNUSED int nBands,
+                                  int nBands,
                                   GDALDataType eType,
                                   char ** papszOptions )
 {
@@ -670,23 +706,28 @@ GDALDataset *NTv2Dataset::Create( const char * pszFilename,
                  GDALGetDataTypeName( eType ) );
         return NULL;
     }
+    if( nBands != 4 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Attempt to create NTv2 file with unsupported band number '%d'.",
+                 nBands);
+        return NULL;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Are we extending an existing file?                              */
 /* -------------------------------------------------------------------- */
-    VSILFILE	*fp;
-    GUInt32   nNumFile = 1;
-
     int bAppend = CSLFetchBoolean(papszOptions,"APPEND_SUBDATASET",FALSE);
-    
+
 /* -------------------------------------------------------------------- */
 /*      Try to open or create file.                                     */
 /* -------------------------------------------------------------------- */
+    VSILFILE *fp;
     if( bAppend )
         fp = VSIFOpenL( pszFilename, "rb+" );
     else
         fp = VSIFOpenL( pszFilename, "wb" );
-    
+
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
@@ -700,19 +741,35 @@ GDALDataset *NTv2Dataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
     char achHeader[11*16];
     const char *pszValue;
+    GUInt32 nNumFile = 1;
+    bool bMustSwap = false;
+    bool bIsLE = false;
 
     if( !bAppend )
     {
         memset( achHeader, 0, sizeof(achHeader) );
-        
+
+        bIsLE = EQUAL(CSLFetchNameValueDef(papszOptions,"ENDIANNESS", "LE"), "LE");
+#ifdef CPL_LSB
+        bMustSwap = !bIsLE;
+#else
+        bMustSwap = bIsLE;
+#endif
+
         memcpy( achHeader +  0*16, "NUM_OREC", 8 );
-        achHeader[ 0*16 + 8] = 0xb;
+        int nNumOrec = 11;
+        SwapPtr32IfNecessary( bMustSwap, &nNumOrec );
+        memcpy( achHeader + 0*16 + 8, &nNumOrec, 4 );
 
         memcpy( achHeader +  1*16, "NUM_SREC", 8 );
-        achHeader[ 1*16 + 8] = 0xb;
+        int nNumSrec = 11;
+        SwapPtr32IfNecessary( bMustSwap, &nNumSrec );
+        memcpy( achHeader + 1*16 + 8, &nNumSrec, 4 );
 
         memcpy( achHeader +  2*16, "NUM_FILE", 8 );
-        achHeader[ 2*16 + 8] = 0x1;
+        SwapPtr32IfNecessary( bMustSwap, &nNumFile );
+        memcpy( achHeader + 2*16 + 8, &nNumFile, 4 );
+        SwapPtr32IfNecessary( bMustSwap, &nNumFile );
 
         memcpy( achHeader +  3*16, "GS_TYPE         ", 16 );
         pszValue = CSLFetchNameValueDef( papszOptions, "GS_TYPE", "SECONDS");
@@ -735,7 +792,7 @@ GDALDataset *NTv2Dataset::Create( const char * pszFilename,
         memcpy( achHeader +  9*16, "MAJOR_T ", 8 );
         memcpy( achHeader + 10*16, "MINOR_T ", 8 );
 
-        VSIFWriteL( achHeader, 1, sizeof(achHeader), fp );
+        CPL_IGNORE_RET_VAL(VSIFWriteL( achHeader, 1, sizeof(achHeader), fp ));
     }
 
 /* -------------------------------------------------------------------- */
@@ -744,21 +801,36 @@ GDALDataset *NTv2Dataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
     else
     {
-        VSIFSeekL( fp, 2*16 + 8, SEEK_SET );
-        VSIFReadL( &nNumFile, 1, 4, fp );
-        CPL_LSBPTR32( &nNumFile );
+        CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 0, SEEK_SET ));
+        CPL_IGNORE_RET_VAL(VSIFReadL( achHeader, 1, 16, fp ));
+
+        bIsLE = (achHeader[8] == 11 && achHeader[9] == 0 && achHeader[10] == 0 && achHeader[11] == 0);
+        const bool bIsBE = (achHeader[8] == 0 && achHeader[9] == 0 && achHeader[10] == 0 && achHeader[11] == 11);
+        if( !bIsLE && !bIsBE )
+        {
+            VSIFCloseL(fp);
+            return NULL;
+        }
+#ifdef CPL_LSB
+        bMustSwap = bIsBE;
+#else
+        bMustSwap = bIsLE;
+#endif
+
+        CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 2*16 + 8, SEEK_SET ));
+        CPL_IGNORE_RET_VAL(VSIFReadL( &nNumFile, 1, 4, fp ));
+        SwapPtr32IfNecessary( bMustSwap, &nNumFile );
 
         nNumFile++;
-        
-        CPL_LSBPTR32( &nNumFile );
-        VSIFSeekL( fp, 2*16 + 8, SEEK_SET );
-        VSIFWriteL( &nNumFile, 1, 4, fp );
 
-        vsi_l_offset nEnd;
+        SwapPtr32IfNecessary( bMustSwap, &nNumFile );
+        CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 2*16 + 8, SEEK_SET ));
+        CPL_IGNORE_RET_VAL(VSIFWriteL( &nNumFile, 1, 4, fp ));
+        SwapPtr32IfNecessary( bMustSwap, &nNumFile );
 
-        VSIFSeekL( fp, 0, SEEK_END );
-        nEnd = VSIFTellL( fp );
-        VSIFSeekL( fp, nEnd-16, SEEK_SET );
+        CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 0, SEEK_END ));
+        vsi_l_offset nEnd = VSIFTellL( fp );
+        CPL_IGNORE_RET_VAL(VSIFSeekL( fp, nEnd-16, SEEK_SET ));
     }
 
 /* -------------------------------------------------------------------- */
@@ -769,15 +841,15 @@ GDALDataset *NTv2Dataset::Create( const char * pszFilename,
     memcpy( achHeader +  0*16, "SUB_NAME        ", 16 );
     pszValue = CSLFetchNameValueDef( papszOptions, "SUB_NAME", "" );
     memcpy( achHeader +  0*16+8, pszValue, MIN(16,strlen(pszValue)) );
-    
+
     memcpy( achHeader +  1*16, "PARENT          ", 16 );
     pszValue = CSLFetchNameValueDef( papszOptions, "PARENT", "NONE" );
     memcpy( achHeader +  1*16+8, pszValue, MIN(16,strlen(pszValue)) );
-    
+
     memcpy( achHeader +  2*16, "CREATED         ", 16 );
     pszValue = CSLFetchNameValueDef( papszOptions, "CREATED", "" );
     memcpy( achHeader +  2*16+8, pszValue, MIN(16,strlen(pszValue)) );
-    
+
     memcpy( achHeader +  3*16, "UPDATED         ", 16 );
     pszValue = CSLFetchNameValueDef( papszOptions, "UPDATED", "" );
     memcpy( achHeader +  3*16+8, pszValue, MIN(16,strlen(pszValue)) );
@@ -786,71 +858,69 @@ GDALDataset *NTv2Dataset::Create( const char * pszFilename,
 
     memcpy( achHeader +  4*16, "S_LAT   ", 8 );
     dfValue = 0;
-    CPL_LSBPTR64( &dfValue );
+    SwapPtr64IfNecessary( bMustSwap, &dfValue );
     memcpy( achHeader +  4*16 + 8, &dfValue, 8 );
 
     memcpy( achHeader +  5*16, "N_LAT   ", 8 );
     dfValue = nYSize-1;
-    CPL_LSBPTR64( &dfValue );
+    SwapPtr64IfNecessary( bMustSwap, &dfValue );
     memcpy( achHeader +  5*16 + 8, &dfValue, 8 );
 
     memcpy( achHeader +  6*16, "E_LONG  ", 8 );
     dfValue = -1*(nXSize-1);
-    CPL_LSBPTR64( &dfValue );
+    SwapPtr64IfNecessary( bMustSwap, &dfValue );
     memcpy( achHeader +  6*16 + 8, &dfValue, 8 );
 
     memcpy( achHeader +  7*16, "W_LONG  ", 8 );
     dfValue = 0;
-    CPL_LSBPTR64( &dfValue );
+    SwapPtr64IfNecessary( bMustSwap, &dfValue );
     memcpy( achHeader +  7*16 + 8, &dfValue, 8 );
 
     memcpy( achHeader +  8*16, "LAT_INC ", 8 );
     dfValue = 1;
-    CPL_LSBPTR64( &dfValue );
+    SwapPtr64IfNecessary( bMustSwap, &dfValue );
     memcpy( achHeader +  8*16 + 8, &dfValue, 8 );
-    
+
     memcpy( achHeader +  9*16, "LONG_INC", 8 );
     memcpy( achHeader +  9*16 + 8, &dfValue, 8 );
-    
+
     memcpy( achHeader + 10*16, "GS_COUNT", 8 );
     GUInt32 nGSCount = nXSize * nYSize;
-    CPL_LSBPTR32( &nGSCount );
+    SwapPtr32IfNecessary( bMustSwap, &nGSCount );
     memcpy( achHeader + 10*16+8, &nGSCount, 4 );
-    
-    VSIFWriteL( achHeader, 1, sizeof(achHeader), fp );
+
+    CPL_IGNORE_RET_VAL(VSIFWriteL( achHeader, 1, sizeof(achHeader), fp ));
 
 /* -------------------------------------------------------------------- */
 /*      Write zeroed grid data.                                         */
 /* -------------------------------------------------------------------- */
-    int i;
-
     memset( achHeader, 0, 16 );
 
     // Use -1 (0x000080bf) as the default error value.
-    memset( achHeader + 10, 0x80, 1 );
-    memset( achHeader + 11, 0xbf, 1 );
-    memset( achHeader + 14, 0x80, 1 );
-    memset( achHeader + 15, 0xbf, 1 );
+    memset( achHeader + ((bIsLE) ? 10 : 9), 0x80, 1 );
+    memset( achHeader + ((bIsLE) ? 11 : 8), 0xbf, 1 );
+    memset( achHeader + ((bIsLE) ? 14 : 13), 0x80, 1 );
+    memset( achHeader + ((bIsLE) ? 15 : 12), 0xbf, 1 );
+
+    for( int i = 0; i < nXSize * nYSize; i++ )
+        CPL_IGNORE_RET_VAL(VSIFWriteL( achHeader, 1, 16, fp ));
 
-    for( i = 0; i < nXSize * nYSize; i++ )
-        VSIFWriteL( achHeader, 1, 16, fp );
-    
 /* -------------------------------------------------------------------- */
 /*      Write the end record.                                           */
 /* -------------------------------------------------------------------- */
     memset( achHeader, 0, 16 );
     memcpy( achHeader, "END     ", 8 );
-    VSIFWriteL( achHeader, 1, 16, fp );
-    VSIFCloseL( fp );
+    CPL_IGNORE_RET_VAL(VSIFWriteL( achHeader, 1, 16, fp ));
+    CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
 
     if( nNumFile == 1 )
-        return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
-    else
-    {
-        CPLString osSubDSName;
-        osSubDSName.Printf( "NTv2:%d:%s", nNumFile-1, pszFilename );
-        return (GDALDataset *) GDALOpen( osSubDSName, GA_Update );
-    }
+      return reinterpret_cast<GDALDataset *>(
+          GDALOpen( pszFilename, GA_Update ) );
+
+    CPLString osSubDSName;
+    osSubDSName.Printf( "NTv2:%d:%s", nNumFile-1, pszFilename );
+    return reinterpret_cast<GDALDataset *>(
+        GDALOpen( osSubDSName, GA_Update ) );
 }
 
 /************************************************************************/
@@ -860,26 +930,22 @@ GDALDataset *NTv2Dataset::Create( const char * pszFilename,
 void GDALRegister_NTv2()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "NTv2" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "NTv2" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "NTv2" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "NTv2 Datum Grid Shift" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gsb" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Float32" );
-
-        poDriver->pfnOpen = NTv2Dataset::Open;
-        poDriver->pfnIdentify = NTv2Dataset::Identify;
-        poDriver->pfnCreate = NTv2Dataset::Create;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "NTv2" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "NTv2 Datum Grid Shift" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gsb" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Float32" );
+
+    poDriver->pfnOpen = NTv2Dataset::Open;
+    poDriver->pfnIdentify = NTv2Dataset::Identify;
+    poDriver->pfnCreate = NTv2Dataset::Create;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/raw/pauxdataset.cpp b/frmts/raw/pauxdataset.cpp
index 7868281..28407a4 100644
--- a/frmts/raw/pauxdataset.cpp
+++ b/frmts/raw/pauxdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pauxdataset.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: pauxdataset.cpp 33673 2016-03-07 20:40:54Z goatbar $
  *
  * Project:  PCI .aux Driver
  * Purpose:  Implementation of PAuxDataset
@@ -28,15 +28,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "rawdataset.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
 #include "ogr_spatialref.h"
+#include "rawdataset.h"
 
-CPL_CVSID("$Id: pauxdataset.cpp 27942 2014-11-11 00:57:41Z rouault $");
-
-CPL_C_START
-void	GDALRegister_PAux(void);
-CPL_C_END
+CPL_CVSID("$Id: pauxdataset.cpp 33673 2016-03-07 20:40:54Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -64,11 +61,11 @@ class PAuxDataset : public RawDataset
   public:
     		PAuxDataset();
     	        ~PAuxDataset();
-    
+
     char	*pszAuxFilename;
     char	**papszAuxLines;
     int		bAuxUpdated;
-    
+
     virtual const char *GetProjectionRef();
     virtual CPLErr GetGeoTransform( double * );
     virtual CPLErr SetGeoTransform( double * );
@@ -115,57 +112,52 @@ class PAuxRasterBand : public RawRasterBand
 /*                           PAuxRasterBand()                           */
 /************************************************************************/
 
-PAuxRasterBand::PAuxRasterBand( GDALDataset *poDS, int nBand,
-                                VSILFILE * fpRaw, vsi_l_offset nImgOffset,
-                                int nPixelOffset, int nLineOffset,
-                                GDALDataType eDataType, int bNativeOrder )
-        : RawRasterBand( poDS, nBand, fpRaw, 
-                         nImgOffset, nPixelOffset, nLineOffset, 
-                         eDataType, bNativeOrder, TRUE )
-
+PAuxRasterBand::PAuxRasterBand( GDALDataset *poDSIn, int nBandIn,
+                                VSILFILE * fpRawIn, vsi_l_offset nImgOffsetIn,
+                                int nPixelOffsetIn, int nLineOffsetIn,
+                                GDALDataType eDataTypeIn, int bNativeOrderIn ) :
+    RawRasterBand( poDSIn, nBandIn, fpRawIn,
+                   nImgOffsetIn, nPixelOffsetIn, nLineOffsetIn,
+                   eDataTypeIn, bNativeOrderIn, TRUE ),
+    poCT(NULL)
 {
-    PAuxDataset *poPDS = (PAuxDataset *) poDS;
-
-    poCT = NULL;
+    PAuxDataset *poPDS = reinterpret_cast<PAuxDataset *>( poDS );
 
 /* -------------------------------------------------------------------- */
 /*      Does this channel have a description?                           */
 /* -------------------------------------------------------------------- */
     char	szTarget[128];
 
-    sprintf( szTarget, "ChanDesc-%d", nBand );
+    snprintf( szTarget, sizeof(szTarget), "ChanDesc-%d", nBand );
     if( CSLFetchNameValue( poPDS->papszAuxLines, szTarget ) != NULL )
-        GDALRasterBand::SetDescription( 
+        GDALRasterBand::SetDescription(
             CSLFetchNameValue( poPDS->papszAuxLines, szTarget ) );
 
 /* -------------------------------------------------------------------- */
 /*      See if we have colors.  Currently we must have color zero,      */
-/*      but this shouldn't really be a limitation.                      */
+/*      but this should not really be a limitation.                     */
 /* -------------------------------------------------------------------- */
-    sprintf( szTarget, "METADATA_IMG_%d_Class_%d_Color", nBand, 0 );
+    snprintf( szTarget, sizeof(szTarget), "METADATA_IMG_%d_Class_%d_Color", nBand, 0 );
     if( CSLFetchNameValue( poPDS->papszAuxLines, szTarget ) != NULL )
     {
-        const char *pszLine;
-        int         i;
-
         poCT = new GDALColorTable();
 
-        for( i = 0; i < 256; i++ )
+        for( int i = 0; i < 256; i++ )
         {
-            int	nRed, nGreen, nBlue;
-
-            sprintf( szTarget, "METADATA_IMG_%d_Class_%d_Color", nBand, i );
-            pszLine = CSLFetchNameValue( poPDS->papszAuxLines, szTarget );
+            snprintf( szTarget, sizeof(szTarget), "METADATA_IMG_%d_Class_%d_Color", nBand, i );
+            const char *pszLine
+                = CSLFetchNameValue( poPDS->papszAuxLines, szTarget );
             while( pszLine && *pszLine == ' ' )
                 pszLine++;
 
+            int	nRed, nGreen, nBlue;
             if( pszLine != NULL
-                && EQUALN(pszLine, "(RGB:",5)
-                && sscanf( pszLine+5, "%d %d %d", 
+                && STARTS_WITH_CI(pszLine, "(RGB:")
+                && sscanf( pszLine+5, "%d %d %d",
                            &nRed, &nGreen, &nBlue ) == 3 )
             {
                 GDALColorEntry    oColor;
-                
+
                 oColor.c1 = (short) nRed;
                 oColor.c2 = (short) nGreen;
                 oColor.c3 = (short) nBlue;
@@ -195,21 +187,19 @@ PAuxRasterBand::~PAuxRasterBand()
 double PAuxRasterBand::GetNoDataValue( int *pbSuccess )
 
 {
-    PAuxDataset *poPDS = (PAuxDataset *) poDS;
     char	szTarget[128];
-    const char  *pszLine;
-
-    sprintf( szTarget, "METADATA_IMG_%d_NO_DATA_VALUE", nBand );
+    snprintf( szTarget, sizeof(szTarget), "METADATA_IMG_%d_NO_DATA_VALUE", nBand );
 
-    pszLine = CSLFetchNameValue( poPDS->papszAuxLines, szTarget );
+    PAuxDataset *poPDS = reinterpret_cast<PAuxDataset *>( poDS );
+    const char  *pszLine = CSLFetchNameValue( poPDS->papszAuxLines, szTarget );
 
     if( pbSuccess != NULL )
         *pbSuccess = (pszLine != NULL);
 
     if( pszLine == NULL )
         return -1e8;
-    else
-        return CPLAtof(pszLine);
+
+    return CPLAtof(pszLine);
 }
 
 /************************************************************************/
@@ -219,22 +209,22 @@ double PAuxRasterBand::GetNoDataValue( int *pbSuccess )
 CPLErr PAuxRasterBand::SetNoDataValue( double dfNewValue )
 
 {
-    PAuxDataset *poPDS = (PAuxDataset *) poDS;
-    char	szTarget[128];
-    char	szValue[128];
-
     if( GetAccess() == GA_ReadOnly )
     {
-        CPLError( CE_Failure, CPLE_NoWriteAccess, 
+        CPLError( CE_Failure, CPLE_NoWriteAccess,
                   "Can't update readonly dataset." );
         return CE_Failure;
     }
 
-    sprintf( szTarget, "METADATA_IMG_%d_NO_DATA_VALUE", nBand );
-    CPLsprintf( szValue, "%24.12f", dfNewValue );
-    poPDS->papszAuxLines = 
+    char szTarget[128];
+    char szValue[128];
+    snprintf( szTarget, sizeof(szTarget), "METADATA_IMG_%d_NO_DATA_VALUE", nBand );
+    CPLsnprintf( szValue, sizeof(szValue), "%24.12f", dfNewValue );
+
+    PAuxDataset *poPDS = reinterpret_cast<PAuxDataset *>( poDS );
+    poPDS->papszAuxLines =
         CSLSetNameValue( poPDS->papszAuxLines, szTarget, szValue );
-    
+
     poPDS->bAuxUpdated = TRUE;
 
     return CE_None;
@@ -250,17 +240,16 @@ CPLErr PAuxRasterBand::SetNoDataValue( double dfNewValue )
 void PAuxRasterBand::SetDescription( const char *pszNewDescription )
 
 {
-    PAuxDataset *poPDS = (PAuxDataset *) poDS;
-
     if( GetAccess() == GA_Update )
     {
         char	szTarget[128];
+        snprintf( szTarget, sizeof(szTarget), "ChanDesc-%d", nBand );
 
-        sprintf( szTarget, "ChanDesc-%d", nBand );
-        poPDS->papszAuxLines = 
-            CSLSetNameValue( poPDS->papszAuxLines, 
+        PAuxDataset *poPDS = reinterpret_cast<PAuxDataset *>( poDS );
+        poPDS->papszAuxLines =
+            CSLSetNameValue( poPDS->papszAuxLines,
                              szTarget, pszNewDescription  );
-    
+
         poPDS->bAuxUpdated = TRUE;
     }
 
@@ -287,8 +276,8 @@ GDALColorInterp PAuxRasterBand::GetColorInterpretation()
 {
     if( poCT == NULL )
         return GCI_Undefined;
-    else
-        return GCI_PaletteIndex;
+
+    return GCI_PaletteIndex;
 }
 
 /************************************************************************/
@@ -301,18 +290,16 @@ GDALColorInterp PAuxRasterBand::GetColorInterpretation()
 /*                            PAuxDataset()                             */
 /************************************************************************/
 
-PAuxDataset::PAuxDataset()
-{
-    papszAuxLines = NULL;
-    fpImage = NULL;
-    bAuxUpdated = FALSE;
-    pszAuxFilename = NULL;
-    nGCPCount = 0;
-    pasGCPList = NULL;
-
-    pszProjection = NULL;
-    pszGCPProjection = NULL;
-}
+PAuxDataset::PAuxDataset() :
+    fpImage(NULL),
+    nGCPCount(0),
+    pasGCPList(NULL),
+    pszGCPProjection(NULL),
+    pszProjection(NULL),
+    pszAuxFilename(NULL),
+    papszAuxLines(NULL),
+    bAuxUpdated(FALSE)
+{}
 
 /************************************************************************/
 /*                            ~PAuxDataset()                            */
@@ -323,7 +310,12 @@ PAuxDataset::~PAuxDataset()
 {
     FlushCache();
     if( fpImage != NULL )
-        VSIFCloseL( fpImage );
+    {
+        if( VSIFCloseL( fpImage ) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        }
+    }
 
     if( bAuxUpdated )
     {
@@ -348,12 +340,10 @@ PAuxDataset::~PAuxDataset()
 /*      incomplete, but can be filled out in the future.                */
 /************************************************************************/
 
-char *PAuxDataset::PCI2WKT( const char *pszGeosys, 
+char *PAuxDataset::PCI2WKT( const char *pszGeosys,
                             const char *pszProjParms )
 
 {
-    OGRSpatialReference oSRS;
-
     while( *pszGeosys == ' ' )
         pszGeosys++;
 
@@ -361,25 +351,23 @@ char *PAuxDataset::PCI2WKT( const char *pszGeosys,
 /*      Parse projection parameters array.                              */
 /* -------------------------------------------------------------------- */
     double adfProjParms[16];
-    
+
     memset( adfProjParms, 0, sizeof(adfProjParms) );
 
     if( pszProjParms != NULL )
     {
-        char **papszTokens;
-        int i;
+        char **papszTokens = CSLTokenizeString( pszProjParms );
 
-        papszTokens = CSLTokenizeString( pszProjParms );
-        
-        for( i=0; papszTokens != NULL && papszTokens[i] != NULL && i < 16; i++)
+        for( int i=0; papszTokens != NULL && papszTokens[i] != NULL && i < 16; i++)
             adfProjParms[i] = CPLAtof(papszTokens[i]);
 
         CSLDestroy( papszTokens );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Convert to SRS.                                                 */
 /* -------------------------------------------------------------------- */
+    OGRSpatialReference oSRS;
     if( oSRS.importFromPCI( pszGeosys, NULL, adfProjParms ) == OGRERR_NONE )
     {
         char *pszResult = NULL;
@@ -388,8 +376,8 @@ char *PAuxDataset::PCI2WKT( const char *pszGeosys,
 
         return pszResult;
     }
-    else
-        return NULL;
+
+    return NULL;
 }
 
 /************************************************************************/
@@ -399,40 +387,35 @@ char *PAuxDataset::PCI2WKT( const char *pszGeosys,
 void PAuxDataset::ScanForGCPs()
 
 {
-#define MAX_GCP		256
+    static const int MAX_GCP = 256;
 
     nGCPCount = 0;
-    pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),MAX_GCP);
+    pasGCPList = reinterpret_cast<GDAL_GCP *>(
+        CPLCalloc( sizeof(GDAL_GCP), MAX_GCP ) );
 
 /* -------------------------------------------------------------------- */
 /*      Get the GCP coordinate system.                                  */
 /* -------------------------------------------------------------------- */
-    const char	*pszMapUnits, *pszProjParms;
+    const char *pszMapUnits = CSLFetchNameValue( papszAuxLines, "GCP_1_MapUnits" );
+    const char *pszProjParms = CSLFetchNameValue( papszAuxLines, "GCP_1_ProjParms" );
 
-    pszMapUnits = CSLFetchNameValue( papszAuxLines, "GCP_1_MapUnits" );
-    pszProjParms = CSLFetchNameValue( papszAuxLines, "GCP_1_ProjParms" );
-    
     if( pszMapUnits != NULL )
         pszGCPProjection = PCI2WKT( pszMapUnits, pszProjParms );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Collect standalone GCPs.  They look like:                       */
 /*                                                                      */
 /*      GCP_1_n = row, col, x, y [,z [,"id"[, "desc"]]]			*/
 /* -------------------------------------------------------------------- */
-    int i;
-
-    for( i = 0; nGCPCount < MAX_GCP; i++ )
+    for( int i = 0; nGCPCount < MAX_GCP; i++ )
     {
         char	szName[50];
-        char    **papszTokens;
-
-        sprintf( szName, "GCP_1_%d", i+1 );
+        snprintf( szName, sizeof(szName), "GCP_1_%d", i+1 );
         if( CSLFetchNameValue( papszAuxLines, szName ) == NULL )
             break;
 
-        papszTokens = CSLTokenizeStringComplex( 
-            CSLFetchNameValue( papszAuxLines, szName ), 
+        char **papszTokens = CSLTokenizeStringComplex(
+            CSLFetchNameValue( papszAuxLines, szName ),
             " ", TRUE, FALSE );
 
         if( CSLCount(papszTokens) >= 4 )
@@ -454,7 +437,7 @@ void PAuxDataset::ScanForGCPs()
             }
             else
             {
-                sprintf( szName, "GCP_%d", i+1 );
+                snprintf( szName, sizeof(szName), "GCP_%d", i+1 );
                 pasGCPList[nGCPCount].pszId = CPLStrdup( szName );
             }
 
@@ -490,8 +473,8 @@ const char *PAuxDataset::GetGCPProjection()
 {
     if( nGCPCount > 0 && pszGCPProjection != NULL )
         return pszGCPProjection;
-    else
-        return "";
+
+    return "";
 }
 
 /************************************************************************/
@@ -513,8 +496,8 @@ const char *PAuxDataset::GetProjectionRef()
 {
     if( pszProjection )
         return pszProjection;
-    else
-        return GDALPamDataset::GetProjectionRef();
+
+    return GDALPamDataset::GetProjectionRef();
 }
 
 /************************************************************************/
@@ -524,17 +507,15 @@ const char *PAuxDataset::GetProjectionRef()
 CPLErr PAuxDataset::GetGeoTransform( double * padfGeoTransform )
 
 {
-    if( CSLFetchNameValue(papszAuxLines, "UpLeftX") != NULL 
-        && CSLFetchNameValue(papszAuxLines, "UpLeftY") != NULL 
-        && CSLFetchNameValue(papszAuxLines, "LoRightX") != NULL 
+    if( CSLFetchNameValue(papszAuxLines, "UpLeftX") != NULL
+        && CSLFetchNameValue(papszAuxLines, "UpLeftY") != NULL
+        && CSLFetchNameValue(papszAuxLines, "LoRightX") != NULL
         && CSLFetchNameValue(papszAuxLines, "LoRightY") != NULL )
     {
-        double	dfUpLeftX, dfUpLeftY, dfLoRightX, dfLoRightY;
-
-        dfUpLeftX = CPLAtof(CSLFetchNameValue(papszAuxLines, "UpLeftX" ));
-        dfUpLeftY = CPLAtof(CSLFetchNameValue(papszAuxLines, "UpLeftY" ));
-        dfLoRightX = CPLAtof(CSLFetchNameValue(papszAuxLines, "LoRightX" ));
-        dfLoRightY = CPLAtof(CSLFetchNameValue(papszAuxLines, "LoRightY" ));
+        const double dfUpLeftX = CPLAtof(CSLFetchNameValue(papszAuxLines, "UpLeftX" ));
+        const double dfUpLeftY = CPLAtof(CSLFetchNameValue(papszAuxLines, "UpLeftY" ));
+        const double dfLoRightX = CPLAtof(CSLFetchNameValue(papszAuxLines, "LoRightX" ));
+        const double dfLoRightY = CPLAtof(CSLFetchNameValue(papszAuxLines, "LoRightY" ));
 
         padfGeoTransform[0] = dfUpLeftX;
         padfGeoTransform[1] = (dfLoRightX - dfUpLeftX) / GetRasterXSize();
@@ -570,34 +551,30 @@ CPLErr PAuxDataset::SetGeoTransform( double * padfGeoTransform )
     char	szLoRightX[128];
     char	szLoRightY[128];
 
-    if( ABS(padfGeoTransform[0]) < 181 
+    if( ABS(padfGeoTransform[0]) < 181
         && ABS(padfGeoTransform[1]) < 1 )
     {
-        CPLsprintf( szUpLeftX, "%.12f", padfGeoTransform[0] );
-        CPLsprintf( szUpLeftY, "%.12f", padfGeoTransform[3] );
-        CPLsprintf( szLoRightX, "%.12f", 
+        CPLsnprintf( szUpLeftX, sizeof(szUpLeftX), "%.12f", padfGeoTransform[0] );
+        CPLsnprintf( szUpLeftY, sizeof(szUpLeftY), "%.12f", padfGeoTransform[3] );
+        CPLsnprintf( szLoRightX, sizeof(szLoRightX), "%.12f",
                padfGeoTransform[0] + padfGeoTransform[1] * GetRasterXSize() );
-        CPLsprintf( szLoRightY, "%.12f", 
+        CPLsnprintf( szLoRightY, sizeof(szLoRightY), "%.12f",
                padfGeoTransform[3] + padfGeoTransform[5] * GetRasterYSize() );
     }
     else
     {
-        CPLsprintf( szUpLeftX, "%.3f", padfGeoTransform[0] );
-        CPLsprintf( szUpLeftY, "%.3f", padfGeoTransform[3] );
-        CPLsprintf( szLoRightX, "%.3f", 
+        CPLsnprintf( szUpLeftX, sizeof(szUpLeftX), "%.3f", padfGeoTransform[0] );
+        CPLsnprintf( szUpLeftY, sizeof(szUpLeftY), "%.3f", padfGeoTransform[3] );
+        CPLsnprintf( szLoRightX, sizeof(szLoRightX), "%.3f",
                padfGeoTransform[0] + padfGeoTransform[1] * GetRasterXSize() );
-        CPLsprintf( szLoRightY, "%.3f", 
+        CPLsnprintf( szLoRightY, sizeof(szLoRightY), "%.3f",
                padfGeoTransform[3] + padfGeoTransform[5] * GetRasterYSize() );
     }
-        
-    papszAuxLines = CSLSetNameValue( papszAuxLines, 
-                                     "UpLeftX", szUpLeftX );
-    papszAuxLines = CSLSetNameValue( papszAuxLines, 
-                                     "UpLeftY", szUpLeftY );
-    papszAuxLines = CSLSetNameValue( papszAuxLines, 
-                                     "LoRightX", szLoRightX );
-    papszAuxLines = CSLSetNameValue( papszAuxLines, 
-                                     "LoRightY", szLoRightY );
+
+    papszAuxLines = CSLSetNameValue( papszAuxLines, "UpLeftX", szUpLeftX );
+    papszAuxLines = CSLSetNameValue( papszAuxLines, "UpLeftY", szUpLeftY );
+    papszAuxLines = CSLSetNameValue( papszAuxLines, "LoRightX", szLoRightX );
+    papszAuxLines = CSLSetNameValue( papszAuxLines, "LoRightY", szLoRightY );
 
     bAuxUpdated = TRUE;
 
@@ -611,11 +588,6 @@ CPLErr PAuxDataset::SetGeoTransform( double * padfGeoTransform )
 GDALDataset *PAuxDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    int		i;
-    CPLString   osAuxFilename;
-    char	**papszTokens;
-    CPLString   osTarget;
-    
     if( poOpenInfo->nHeaderBytes < 1 )
         return NULL;
 
@@ -624,25 +596,26 @@ GDALDataset *PAuxDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      file it references.                                             */
 /* -------------------------------------------------------------------- */
 
-    osTarget = poOpenInfo->pszFilename;
+    CPLString osTarget = poOpenInfo->pszFilename;
 
     if( EQUAL(CPLGetExtension( poOpenInfo->pszFilename ),"aux")
-        && EQUALN((const char *) poOpenInfo->pabyHeader,"AuxilaryTarget: ",16))
+        && STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "AuxilaryTarget: "))
     {
         char	szAuxTarget[1024];
-        char    *pszPath;
-        const char *pszSrc = (const char *) poOpenInfo->pabyHeader+16;
+        const char *pszSrc = reinterpret_cast<const char *>(
+            poOpenInfo->pabyHeader+16 );
 
-        for( i = 0; 
+        int i = 0;
+        for( ;
              pszSrc[i] != 10 && pszSrc[i] != 13 && pszSrc[i] != '\0'
-                 && i < (int) sizeof(szAuxTarget)-1;
+                 && i < static_cast<int>( sizeof(szAuxTarget) ) - 1;
              i++ )
         {
             szAuxTarget[i] = pszSrc[i];
         }
         szAuxTarget[i] = '\0';
 
-        pszPath = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
+        char *pszPath = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
         osTarget = CPLFormFilename(pszPath, szAuxTarget, NULL);
         CPLFree(pszPath);
     }
@@ -651,22 +624,20 @@ GDALDataset *PAuxDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Now we need to tear apart the filename to form a .aux           */
 /*      filename.                                                       */
 /* -------------------------------------------------------------------- */
-    osAuxFilename = CPLResetExtension(osTarget,"aux");
+    CPLString osAuxFilename = CPLResetExtension(osTarget,"aux");
 
 /* -------------------------------------------------------------------- */
 /*      Do we have a .aux file?                                         */
 /* -------------------------------------------------------------------- */
     char** papszSiblingFiles = poOpenInfo->GetSiblingFiles();
     if( papszSiblingFiles != NULL
-        && CSLFindString( papszSiblingFiles, 
+        && CSLFindString( papszSiblingFiles,
                           CPLGetFilename(osAuxFilename) ) == -1 )
     {
         return NULL;
     }
-    
-    VSILFILE	*fp;
 
-    fp = VSIFOpenL( osAuxFilename, "r" );
+    VSILFILE *fp = VSIFOpenL( osAuxFilename, "r" );
     if( fp == NULL )
     {
         osAuxFilename = CPLResetExtension(osTarget,"AUX");
@@ -683,25 +654,21 @@ GDALDataset *PAuxDataset::Open( GDALOpenInfo * poOpenInfo )
 /*	At this point we should be verifying that it refers to our	*/
 /*	binary file, but that is a pretty involved test.		*/
 /* -------------------------------------------------------------------- */
-    const char *	pszLine;
-
-    pszLine = CPLReadLineL( fp );
+    const char *pszLine = CPLReadLineL( fp );
 
-    VSIFCloseL( fp );
+    CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
 
-    if( pszLine == NULL 
-        || (!EQUALN(pszLine,"AuxilaryTarget",14) 
-            && !EQUALN(pszLine,"AuxiliaryTarget",15)) ) 
+    if( pszLine == NULL
+        || (!STARTS_WITH_CI(pszLine, "AuxilaryTarget")
+            && !STARTS_WITH_CI(pszLine, "AuxiliaryTarget")) )
     {
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    PAuxDataset 	*poDS;
-
-    poDS = new PAuxDataset();
+    PAuxDataset *poDS = new PAuxDataset();
 
 /* -------------------------------------------------------------------- */
 /*      Load the .aux file into a string list suitable to be            */
@@ -709,13 +676,13 @@ GDALDataset *PAuxDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->papszAuxLines = CSLLoad( osAuxFilename );
     poDS->pszAuxFilename = CPLStrdup(osAuxFilename);
-    
+
 /* -------------------------------------------------------------------- */
 /*      Find the RawDefinition line to establish overall parameters.    */
 /* -------------------------------------------------------------------- */
     pszLine = CSLFetchNameValue(poDS->papszAuxLines, "RawDefinition");
 
-    // It seems PCI now writes out .aux files without RawDefinition in 
+    // It seems PCI now writes out .aux files without RawDefinition in
     // some cases.  See bug 947.
     if( pszLine == NULL )
     {
@@ -723,13 +690,14 @@ GDALDataset *PAuxDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    papszTokens = CSLTokenizeString(pszLine);
+    char **papszTokens = CSLTokenizeString(pszLine);
 
     if( CSLCount(papszTokens) < 3 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "RawDefinition missing or corrupt in %s.",
                   poOpenInfo->pszFilename );
+        delete poDS;
         CSLDestroy( papszTokens );
         return NULL;
     }
@@ -760,7 +728,6 @@ GDALDataset *PAuxDataset::Open( GDALOpenInfo * poOpenInfo )
             CPLError( CE_Failure, CPLE_OpenFailed,
                       "File %s is missing or read-only, check permissions.",
                       osTarget.c_str() );
-            
             delete poDS;
             return NULL;
         }
@@ -774,7 +741,6 @@ GDALDataset *PAuxDataset::Open( GDALOpenInfo * poOpenInfo )
             CPLError( CE_Failure, CPLE_OpenFailed,
                       "File %s is missing or unreadable.",
                       osTarget.c_str() );
-            
             delete poDS;
             return NULL;
         }
@@ -785,13 +751,10 @@ GDALDataset *PAuxDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      corresponding bands.                                            */
 /* -------------------------------------------------------------------- */
     int iBand = 0;
-    for( i = 0; i < poDS->nBands; i++ )
+    for( int i = 0; i < poDS->nBands; i++ )
     {
         char	szDefnName[32];
-        GDALDataType eType;
-        int	bNative = TRUE;
-
-        sprintf( szDefnName, "ChanDefinition-%d", i+1 );
+        snprintf( szDefnName, sizeof(szDefnName), "ChanDefinition-%d", i+1 );
 
         pszLine = CSLFetchNameValue(poDS->papszAuxLines, szDefnName);
         if (pszLine == NULL)
@@ -807,6 +770,7 @@ GDALDataset *PAuxDataset::Open( GDALOpenInfo * poOpenInfo )
             continue;
         }
 
+        GDALDataType eType;
         if( EQUAL(papszTokens[0],"16U") )
             eType = GDT_UInt16;
         else if( EQUAL(papszTokens[0],"16S") )
@@ -816,6 +780,7 @@ GDALDataset *PAuxDataset::Open( GDALOpenInfo * poOpenInfo )
         else
             eType = GDT_Byte;
 
+        int bNative = TRUE;
         if( CSLCount(papszTokens) > 4 )
         {
 #ifdef CPL_LSB
@@ -825,10 +790,10 @@ GDALDataset *PAuxDataset::Open( GDALOpenInfo * poOpenInfo )
 #endif
         }
 
-        vsi_l_offset nBandOffset = CPLScanUIntBig(papszTokens[1],
-                                               strlen(papszTokens[1]));
-        int nPixelOffset = atoi(papszTokens[2]);
-        int nLineOffset = atoi(papszTokens[3]);
+        const vsi_l_offset nBandOffset = CPLScanUIntBig(papszTokens[1],
+                                               static_cast<int>(strlen(papszTokens[1])));
+        const int nPixelOffset = atoi(papszTokens[2]);
+        const int nLineOffset = atoi(papszTokens[3]);
 
         if (nPixelOffset <= 0 || nLineOffset <= 0)
         {
@@ -837,12 +802,12 @@ GDALDataset *PAuxDataset::Open( GDALOpenInfo * poOpenInfo )
             continue;
         }
 
-        poDS->SetBand( iBand+1, 
+        poDS->SetBand( iBand+1,
             new PAuxRasterBand( poDS, iBand+1, poDS->fpImage,
                                 nBandOffset,
                                 nPixelOffset,
                                 nLineOffset, eType, bNative ) );
-        iBand ++;
+        iBand++;
 
         CSLDestroy( papszTokens );
     }
@@ -852,14 +817,12 @@ GDALDataset *PAuxDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Get the projection.                                             */
 /* -------------------------------------------------------------------- */
-    const char	*pszMapUnits, *pszProjParms;
+    const char *pszMapUnits = CSLFetchNameValue( poDS->papszAuxLines, "MapUnits" );
+    const char *pszProjParms = CSLFetchNameValue( poDS->papszAuxLines, "ProjParms" );
 
-    pszMapUnits = CSLFetchNameValue( poDS->papszAuxLines, "MapUnits" );
-    pszProjParms = CSLFetchNameValue( poDS->papszAuxLines, "ProjParms" );
-    
     if( pszMapUnits != NULL )
         poDS->pszProjection = poDS->PCI2WKT( pszMapUnits, pszProjParms );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
@@ -887,11 +850,9 @@ GDALDataset *PAuxDataset::Create( const char * pszFilename,
                                   char **papszOptions )
 
 {
-    char	*pszAuxFilename;
-
-	const char *pszInterleave = CSLFetchNameValue( papszOptions, "INTERLEAVE" );
-	if( pszInterleave == NULL )
-		pszInterleave = "BAND";
+    const char *pszInterleave = CSLFetchNameValue( papszOptions, "INTERLEAVE" );
+    if( pszInterleave == NULL )
+        pszInterleave = "BAND";
 
 /* -------------------------------------------------------------------- */
 /*      Verify input options.                                           */
@@ -910,19 +871,15 @@ GDALDataset *PAuxDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Sum the sizes of the band pixel types.                          */
 /* -------------------------------------------------------------------- */
-	int nPixelSizeSum = 0;
-	int iBand;
+    int nPixelSizeSum = 0;
 
-    for( iBand = 0; iBand < nBands; iBand++ )
+    for( int iBand = 0; iBand < nBands; iBand++ )
         nPixelSizeSum += (GDALGetDataTypeSize(eType)/8);
 
 /* -------------------------------------------------------------------- */
 /*      Try to create the file.                                         */
 /* -------------------------------------------------------------------- */
-    VSILFILE	*fp;
-
-    fp = VSIFOpenL( pszFilename, "w" );
-
+    VSILFILE *fp = VSIFOpenL( pszFilename, "w" );
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
@@ -935,16 +892,18 @@ GDALDataset *PAuxDataset::Create( const char * pszFilename,
 /*      Just write out a couple of bytes to establish the binary        */
 /*      file, and then close it.                                        */
 /* -------------------------------------------------------------------- */
-    VSIFWriteL( (void *) "\0\0", 2, 1, fp );
-    VSIFCloseL( fp );
+    CPL_IGNORE_RET_VAL(VSIFWriteL( reinterpret_cast<void *>( const_cast<char *>( "\0\0" ) ),
+                2, 1, fp ));
+    CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
 
 /* -------------------------------------------------------------------- */
 /*      Create the aux filename.                                        */
 /* -------------------------------------------------------------------- */
-    pszAuxFilename = (char *) CPLMalloc(strlen(pszFilename)+5);
+    char *pszAuxFilename = reinterpret_cast<char *>(
+        CPLMalloc( strlen( pszFilename ) + 5 ) );
     strcpy( pszAuxFilename, pszFilename );;
 
-    for( int i = strlen(pszAuxFilename)-1; i > 0; i-- )
+    for( int i = static_cast<int>(strlen(pszAuxFilename))-1; i > 0; i-- )
     {
         if( pszAuxFilename[i] == '.' )
         {
@@ -967,25 +926,23 @@ GDALDataset *PAuxDataset::Create( const char * pszFilename,
         return NULL;
     }
     CPLFree( pszAuxFilename );
-    
+
 /* -------------------------------------------------------------------- */
 /*      We need to write out the original filename but without any      */
 /*      path components in the AuxilaryTarget line.  Do so now.         */
 /* -------------------------------------------------------------------- */
-    int		iStart;
-
-    iStart = strlen(pszFilename)-1;
+    int iStart = static_cast<int>(strlen(pszFilename))-1;
     while( iStart > 0 && pszFilename[iStart-1] != '/'
            && pszFilename[iStart-1] != '\\' )
         iStart--;
 
-    VSIFPrintfL( fp, "AuxilaryTarget: %s\n", pszFilename + iStart );
+    CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "AuxilaryTarget: %s\n", pszFilename + iStart ));
 
 /* -------------------------------------------------------------------- */
 /*      Write out the raw definition for the dataset as a whole.        */
 /* -------------------------------------------------------------------- */
-    VSIFPrintfL( fp, "RawDefinition: %d %d %d\n",
-                nXSize, nYSize, nBands );
+    CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "RawDefinition: %d %d %d\n",
+                nXSize, nYSize, nBands ));
 
 /* -------------------------------------------------------------------- */
 /*      Write out a definition for each band.  We always write band     */
@@ -993,12 +950,13 @@ GDALDataset *PAuxDataset::Create( const char * pszFilename,
 /*      handled by GDAL.                                                */
 /* -------------------------------------------------------------------- */
     vsi_l_offset    nImgOffset = 0;
-    
-    for( iBand = 0; iBand < nBands; iBand++ )
+
+    for( int iBand = 0; iBand < nBands; iBand++ )
     {
         const char  *pszTypeName;
-        int         nPixelOffset, nLineOffset;
-		vsi_l_offset nNextImgOffset;
+        int nPixelOffset;
+        int nLineOffset;
+        vsi_l_offset nNextImgOffset;
 
 /* -------------------------------------------------------------------- */
 /*      Establish our file layout based on supplied interleaving.       */
@@ -1034,7 +992,7 @@ GDALDataset *PAuxDataset::Create( const char * pszFilename,
         else
             pszTypeName = "8U";
 
-        VSIFPrintfL( fp, "ChanDefinition-%d: %s " CPL_FRMT_GIB " %d %d %s\n", 
+        CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "ChanDefinition-%d: %s " CPL_FRMT_GIB " %d %d %s\n",
 					 iBand+1,
 					 pszTypeName, (GIntBig) nImgOffset,
 					 nPixelOffset, nLineOffset,
@@ -1043,7 +1001,7 @@ GDALDataset *PAuxDataset::Create( const char * pszFilename,
 #else
                     "Unswapped"
 #endif
-                    );
+                    ));
 
         nImgOffset = nNextImgOffset;
     }
@@ -1051,36 +1009,34 @@ GDALDataset *PAuxDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Cleanup                                                         */
 /* -------------------------------------------------------------------- */
-    VSIFCloseL( fp );
+    CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
 
-    return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
+    return reinterpret_cast<GDALDataset *>(
+        GDALOpen( pszFilename, GA_Update ) );
 }
 
 /************************************************************************/
 /*                             PAuxDelete()                             */
 /************************************************************************/
 
-CPLErr PAuxDelete( const char * pszBasename )
+static CPLErr PAuxDelete( const char * pszBasename )
 
 {
-    VSILFILE	*fp;
-    const char *pszLine;
-
-    fp = VSIFOpenL( CPLResetExtension( pszBasename, "aux" ), "r" );
+    VSILFILE *fp = VSIFOpenL( CPLResetExtension( pszBasename, "aux" ), "r" );
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "%s does not appear to be a PAux dataset, there is no .aux file.",
                   pszBasename );
         return CE_Failure;
     }
 
-    pszLine = CPLReadLineL( fp );
-    VSIFCloseL( fp );
-    
-    if( pszLine == NULL || !EQUALN(pszLine,"AuxilaryTarget",14) )
+    const char *pszLine = CPLReadLineL( fp );
+    CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
+
+    if( pszLine == NULL || !STARTS_WITH_CI(pszLine, "AuxilaryTarget") )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "%s does not appear to be a PAux dataset,\n"
                   "the .aux file does not start with AuxilaryTarget",
                   pszBasename );
@@ -1089,7 +1045,7 @@ CPLErr PAuxDelete( const char * pszBasename )
 
     if( VSIUnlink( pszBasename ) != 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "OS unlinking file %s.", pszBasename );
         return CE_Failure;
     }
@@ -1106,21 +1062,18 @@ CPLErr PAuxDelete( const char * pszBasename )
 void GDALRegister_PAux()
 
 {
-    GDALDriver	*poDriver;
-
-    if( GDALGetDriverByName( "PAux" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "PAux" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "PCI .aux Labelled" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#PAux" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte Int16 UInt16 Float32" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
+    if( GDALGetDriverByName( "PAux" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "PAux" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "PCI .aux Labelled" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#PAux" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte Int16 UInt16 Float32" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "   <Option name='INTERLEAVE' type='string-select' default='BAND'>"
 "       <Value>BAND</Value>"
@@ -1129,11 +1082,9 @@ void GDALRegister_PAux()
 "   </Option>"
 "</CreationOptionList>" );
 
-        poDriver->pfnOpen = PAuxDataset::Open;
-        poDriver->pfnCreate = PAuxDataset::Create;
-        poDriver->pfnDelete = PAuxDelete;
+    poDriver->pfnOpen = PAuxDataset::Open;
+    poDriver->pfnCreate = PAuxDataset::Create;
+    poDriver->pfnDelete = PAuxDelete;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
-
diff --git a/frmts/raw/pnmdataset.cpp b/frmts/raw/pnmdataset.cpp
index 26bf627..02b1ac2 100644
--- a/frmts/raw/pnmdataset.cpp
+++ b/frmts/raw/pnmdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pnmdataset.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: pnmdataset.cpp 33673 2016-03-07 20:40:54Z goatbar $
  *
  * Project:  PNM Driver
  * Purpose:  Portable anymap file format imlementation
@@ -28,14 +28,15 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "rawdataset.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "rawdataset.h"
 #include <ctype.h>
 
-CPL_CVSID("$Id: pnmdataset.cpp 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: pnmdataset.cpp 33673 2016-03-07 20:40:54Z goatbar $");
 
 CPL_C_START
-void    GDALRegister_PNM(void);
+void GDALRegister_PNM();
 CPL_C_END
 
 /************************************************************************/
@@ -68,10 +69,10 @@ class PNMDataset : public RawDataset
 /*                            PNMDataset()                             */
 /************************************************************************/
 
-PNMDataset::PNMDataset()
+PNMDataset::PNMDataset() :
+    fpImage(NULL),
+    bGeoTransformValid(FALSE)
 {
-    fpImage = NULL;
-    bGeoTransformValid = FALSE;
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
@@ -89,7 +90,12 @@ PNMDataset::~PNMDataset()
 {
     FlushCache();
     if( fpImage != NULL )
-        VSIFCloseL( fpImage );
+    {
+        if( VSIFCloseL( fpImage ) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        }
+    }
 }
 
 /************************************************************************/
@@ -99,14 +105,13 @@ PNMDataset::~PNMDataset()
 CPLErr PNMDataset::GetGeoTransform( double * padfTransform )
 
 {
-
     if( bGeoTransformValid )
     {
         memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
         return CE_None;
     }
-    else
-        return CE_Failure;
+
+    return CE_Failure;
 }
 
 /************************************************************************/
@@ -155,11 +160,14 @@ GDALDataset *PNMDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Parse out the tokens from the header.                           */
 /* -------------------------------------------------------------------- */
     const char  *pszSrc = (const char *) poOpenInfo->pabyHeader;
-    char        szToken[512];
-    int         iIn, iToken = 0, nWidth =-1, nHeight=-1, nMaxValue=-1;
+    char szToken[512];
+    int iToken = 0;
+    int nWidth = -1;
+    int nHeight = -1;
+    int nMaxValue = -1;
     unsigned int iOut;
 
-    iIn = 2;
+    int iIn = 2;
     while( iIn < poOpenInfo->nHeaderBytes && iToken < 3 )
     {
         iOut = 0;
@@ -207,9 +215,7 @@ GDALDataset *PNMDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    PNMDataset  *poDS;
-
-    poDS = new PNMDataset();
+    PNMDataset *poDS = new PNMDataset();
 
 /* -------------------------------------------------------------------- */
 /*      Capture some information from the file that is of interest.     */
@@ -239,26 +245,26 @@ GDALDataset *PNMDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    int         bMSBFirst = TRUE, iPixelSize;
-    GDALDataType eDataType;
-
 #ifdef CPL_LSB
-    bMSBFirst = FALSE;
+    const int bMSBFirst = FALSE;
+#else
+    const int bMSBFirst = TRUE;
 #endif
 
+    GDALDataType eDataType;
     if ( nMaxValue < 256 )
         eDataType = GDT_Byte;
     else
         eDataType = GDT_UInt16;
 
-    iPixelSize = GDALGetDataTypeSize( eDataType ) / 8;
+    const int iPixelSize = GDALGetDataTypeSize( eDataType ) / 8;
 
     if( poOpenInfo->pabyHeader[1] == '5' )
     {
         if (nWidth > INT_MAX / iPixelSize)
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Int overflow occured.");
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Int overflow occurred.");
             delete poDS;
             return NULL;
         }
@@ -271,8 +277,8 @@ GDALDataset *PNMDataset::Open( GDALOpenInfo * poOpenInfo )
     {
         if (nWidth > INT_MAX / (3 * iPixelSize))
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Int overflow occured.");
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Int overflow occurred.");
             delete poDS;
             return NULL;
         }
@@ -296,8 +302,8 @@ GDALDataset *PNMDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Check for world file.                                           */
 /* -------------------------------------------------------------------- */
-    poDS->bGeoTransformValid = 
-        GDALReadWorldFile( poOpenInfo->pszFilename, ".wld", 
+    poDS->bGeoTransformValid =
+        GDALReadWorldFile( poOpenInfo->pszFilename, ".wld",
                            poDS->adfGeoTransform );
 
 /* -------------------------------------------------------------------- */
@@ -350,10 +356,7 @@ GDALDataset *PNMDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Try to create the file.                                         */
 /* -------------------------------------------------------------------- */
-    VSILFILE        *fp;
-
-    fp = VSIFOpenL( pszFilename, "wb" );
-
+    VSILFILE *fp = VSIFOpenL( pszFilename, "wb" );
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
@@ -365,11 +368,9 @@ GDALDataset *PNMDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Write out the header.                                           */
 /* -------------------------------------------------------------------- */
-    char        szHeader[500];
-    const char  *pszMaxValue = NULL;
     int         nMaxValue = 0;
 
-    pszMaxValue = CSLFetchNameValue( papszOptions, "MAXVAL" );
+    const char *pszMaxValue = CSLFetchNameValue( papszOptions, "MAXVAL" );
     if ( pszMaxValue )
     {
         nMaxValue = atoi( pszMaxValue );
@@ -386,54 +387,53 @@ GDALDataset *PNMDataset::Create( const char * pszFilename,
             nMaxValue = 65535;
     }
 
-
+    char szHeader[500];
     memset( szHeader, 0, sizeof(szHeader) );
 
     if( nBands == 3 )
-        sprintf( szHeader, "P6\n%d %d\n%d\n", nXSize, nYSize, nMaxValue );
+        snprintf( szHeader, sizeof(szHeader), "P6\n%d %d\n%d\n", nXSize, nYSize, nMaxValue );
     else
-        sprintf( szHeader, "P5\n%d %d\n%d\n", nXSize, nYSize, nMaxValue );
+        snprintf( szHeader, sizeof(szHeader), "P5\n%d %d\n%d\n", nXSize, nYSize, nMaxValue );
 
-    VSIFWriteL( (void *) szHeader, strlen(szHeader) + 2, 1, fp );
-    VSIFCloseL( fp );
+    bool bOK = VSIFWriteL( reinterpret_cast<void *>( szHeader ),
+                strlen(szHeader) + 2, 1, fp ) == 1;
+    if( VSIFCloseL( fp ) != 0 )
+        bOK = false;
 
-    return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
+    if( !bOK )
+        return NULL;
+    return reinterpret_cast<GDALDataset *>( GDALOpen( pszFilename, GA_Update ) );
 }
 
 /************************************************************************/
-/*                         GDALRegister_PNM()                          */
+/*                         GDALRegister_PNM()                           */
 /************************************************************************/
 
 void GDALRegister_PNM()
 
 {
-    GDALDriver  *poDriver;
-
-    if( GDALGetDriverByName( "PNM" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-
-        poDriver->SetDescription( "PNM" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Portable Pixmap Format (netpbm)" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "frmt_various.html#PNM" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "pnm" );
-        poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE,
-                                   "image/x-portable-anymap" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
-                                   "Byte UInt16" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    if( GDALGetDriverByName( "PNM" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "PNM" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Portable Pixmap Format (netpbm)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#PNM" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "pnm" );
+    poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/x-portable-anymap" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte UInt16" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "   <Option name='MAXVAL' type='unsigned int' description='Maximum color value'/>"
 "</CreationOptionList>" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = PNMDataset::Open;
-        poDriver->pfnCreate = PNMDataset::Create;
-        poDriver->pfnIdentify = PNMDataset::Identify;
+    poDriver->pfnOpen = PNMDataset::Open;
+    poDriver->pfnCreate = PNMDataset::Create;
+    poDriver->pfnIdentify = PNMDataset::Identify;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/raw/rawdataset.cpp b/frmts/raw/rawdataset.cpp
index 338272b..e8bedf9 100644
--- a/frmts/raw/rawdataset.cpp
+++ b/frmts/raw/rawdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rawdataset.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: rawdataset.cpp 33840 2016-04-01 00:47:00Z goatbar $
  *
  * Project:  Generic Raw Binary Driver
  * Purpose:  Implementation of RawDataset and RawRasterBand classes.
@@ -32,45 +32,50 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: rawdataset.cpp 28053 2014-12-04 09:31:07Z rouault $");
+#include <cmath>
+#include <cstddef>
+#include <cstdlib>
+
+#include <algorithm>
+
+CPL_CVSID("$Id: rawdataset.cpp 33840 2016-04-01 00:47:00Z goatbar $");
 
 /************************************************************************/
 /*                           RawRasterBand()                            */
 /************************************************************************/
 
-RawRasterBand::RawRasterBand( GDALDataset *poDS, int nBand,
-                              void * fpRaw, vsi_l_offset nImgOffset,
-                              int nPixelOffset, int nLineOffset,
-                              GDALDataType eDataType, int bNativeOrder,
-                              int bIsVSIL, int bOwnsFP )
-
+RawRasterBand::RawRasterBand( GDALDataset *poDSIn, int nBandIn,
+                              void *fpRawIn, vsi_l_offset nImgOffsetIn,
+                              int nPixelOffsetIn, int nLineOffsetIn,
+                              GDALDataType eDataTypeIn, int bNativeOrderIn,
+                              int bIsVSILIn, int bOwnsFPIn ) :
+    fpRaw(NULL),
+    fpRawL(NULL),
+    bIsVSIL(bIsVSILIn),
+    nImgOffset(nImgOffsetIn),
+    nPixelOffset(nPixelOffsetIn),
+    nLineOffset(nLineOffsetIn),
+    bNativeOrder(bNativeOrderIn),
+    bOwnsFP(bOwnsFPIn)
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
-    this->eDataType = eDataType;
-    this->bIsVSIL = bIsVSIL;
-    this->bOwnsFP =bOwnsFP;
+    poDS = poDSIn;
+    nBand = nBandIn;
+    eDataType = eDataTypeIn;
 
     if (bIsVSIL)
     {
-        this->fpRaw = NULL;
-        this->fpRawL = (VSILFILE*) fpRaw;
+        fpRawL = reinterpret_cast<VSILFILE *>( fpRawIn );
     }
     else
     {
-        this->fpRaw = (FILE*) fpRaw;
-        this->fpRawL = NULL;
+        fpRaw = reinterpret_cast<FILE *>( fpRawIn );
     }
-    this->nImgOffset = nImgOffset;
-    this->nPixelOffset = nPixelOffset;
-    this->nLineOffset = nLineOffset;
-    this->bNativeOrder = bNativeOrder;
 
-    CPLDebug( "GDALRaw", 
+    CPLDebug( "GDALRaw",
               "RawRasterBand(%p,%d,%p,\n"
-              "              Off=%d,PixOff=%d,LineOff=%d,%s,%d)\n",
-              poDS, nBand, fpRaw, 
-              (unsigned int) nImgOffset, nPixelOffset, nLineOffset, 
+              "              Off=%d,PixOff=%d,LineOff=%d,%s,%d)",
+              poDS, nBand, fpRaw,
+              static_cast<unsigned int>(nImgOffset), nPixelOffset, nLineOffset,
               GDALGetDataTypeName(eDataType), bNativeOrder );
 
 /* -------------------------------------------------------------------- */
@@ -89,37 +94,44 @@ RawRasterBand::RawRasterBand( GDALDataset *poDS, int nBand,
 /*                           RawRasterBand()                            */
 /************************************************************************/
 
-RawRasterBand::RawRasterBand( void * fpRaw, vsi_l_offset nImgOffset,
-                              int nPixelOffset, int nLineOffset,
-                              GDALDataType eDataType, int bNativeOrder,
-                              int nXSize, int nYSize, int bIsVSIL, int bOwnsFP )
-
+RawRasterBand::RawRasterBand( void *fpRawIn, vsi_l_offset nImgOffsetIn,
+                              int nPixelOffsetIn, int nLineOffsetIn,
+                              GDALDataType eDataTypeIn, int bNativeOrderIn,
+                              int nXSize, int nYSize, int bIsVSILIn,
+                              int bOwnsFPIn ) :
+    fpRaw(NULL),
+    fpRawL(NULL),
+    bIsVSIL(bIsVSILIn),
+    nImgOffset(nImgOffsetIn),
+    nPixelOffset(nPixelOffsetIn),
+    nLineOffset(nLineOffsetIn),
+    nLineSize(0),
+    bNativeOrder(bNativeOrderIn),
+    nLoadedScanline(0),
+    pLineStart(NULL),
+    bDirty(FALSE),
+    poCT(NULL),
+    eInterp(GCI_Undefined),
+    papszCategoryNames(NULL),
+    bOwnsFP(bOwnsFPIn)
 {
-    this->poDS = NULL;
-    this->nBand = 1;
-    this->eDataType = eDataType;
-    this->bIsVSIL = bIsVSIL;
-    this->bOwnsFP =bOwnsFP;
+    poDS = NULL;
+    nBand = 1;
+    eDataType = eDataTypeIn;
 
     if (bIsVSIL)
     {
-        this->fpRaw = NULL;
-        this->fpRawL = (VSILFILE*) fpRaw;
+        fpRawL = reinterpret_cast<VSILFILE *>( fpRawIn );
     }
     else
     {
-        this->fpRaw = (FILE*) fpRaw;
-        this->fpRawL = NULL;
+        fpRaw = reinterpret_cast<FILE *>( fpRawIn );
     }
-    this->nImgOffset = nImgOffset;
-    this->nPixelOffset = nPixelOffset;
-    this->nLineOffset = nLineOffset;
-    this->bNativeOrder = bNativeOrder;
-
 
-    CPLDebug( "GDALRaw", 
-              "RawRasterBand(floating,Off=%d,PixOff=%d,LineOff=%d,%s,%d)\n",
-              (unsigned int) nImgOffset, nPixelOffset, nLineOffset, 
+    CPLDebug( "GDALRaw",
+              "RawRasterBand(floating,Off=%d,PixOff=%d,LineOff=%d,%s,%d)",
+              static_cast<unsigned int>( nImgOffset ),
+              nPixelOffset, nLineOffset,
               GDALGetDataTypeName(eDataType), bNativeOrder );
 
 /* -------------------------------------------------------------------- */
@@ -159,27 +171,30 @@ void RawRasterBand::Initialize()
 /*      Allocate working scanline.                                      */
 /* -------------------------------------------------------------------- */
     nLoadedScanline = -1;
-    if (nBlockXSize <= 0 || nPixelOffset > INT_MAX / nBlockXSize)
+    if (nBlockXSize <= 0 || std::abs(nPixelOffset) > INT_MAX / nBlockXSize)
     {
         nLineSize = 0;
         pLineBuffer = NULL;
     }
     else
     {
-        nLineSize = ABS(nPixelOffset) * nBlockXSize;
-        pLineBuffer = VSIMalloc2( ABS(nPixelOffset), nBlockXSize );
+        nLineSize = std::abs(nPixelOffset) * nBlockXSize;
+        pLineBuffer = VSIMalloc2( std::abs(nPixelOffset), nBlockXSize );
     }
     if (pLineBuffer == NULL)
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Could not allocate line buffer : nPixelOffset=%d, nBlockXSize=%d",
-                 nPixelOffset, nBlockXSize);
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Could not allocate line buffer: "
+                  "nPixelOffset=%d, nBlockXSize=%d",
+                  nPixelOffset, nBlockXSize);
     }
 
     if( nPixelOffset >= 0 )
         pLineStart = pLineBuffer;
     else
-        pLineStart = ((char *) pLineBuffer) + ABS(nPixelOffset) * (nBlockXSize-1);
+        pLineStart = reinterpret_cast<char *> (pLineBuffer )
+            + static_cast<std::ptrdiff_t>( std::abs( nPixelOffset ) )
+            * ( nBlockXSize - 1 );
 }
 
 /************************************************************************/
@@ -195,15 +210,22 @@ RawRasterBand::~RawRasterBand()
     CSLDestroy( papszCategoryNames );
 
     FlushCache();
-    
+
     if (bOwnsFP)
     {
         if ( bIsVSIL )
-            VSIFCloseL( fpRawL );
+        {
+            if( VSIFCloseL( fpRawL ) != 0 )
+            {
+                CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+            }
+        }
         else
+        {
             VSIFClose( fpRaw );
+        }
     }
-    
+
     CPLFree( pLineBuffer );
 }
 
@@ -212,9 +234,9 @@ RawRasterBand::~RawRasterBand()
 /*                             SetAccess()                              */
 /************************************************************************/
 
-void  RawRasterBand::SetAccess( GDALAccess eAccess )
+void  RawRasterBand::SetAccess( GDALAccess eAccessIn )
 {
-    this->eAccess = eAccess;
+    eAccess = eAccessIn;
 }
 
 /************************************************************************/
@@ -228,21 +250,22 @@ void  RawRasterBand::SetAccess( GDALAccess eAccess )
 CPLErr RawRasterBand::FlushCache()
 
 {
-    CPLErr eErr;
-
-    eErr = GDALRasterBand::FlushCache();
+    CPLErr eErr = GDALRasterBand::FlushCache();
     if( eErr != CE_None )
         return eErr;
 
     // If we have unflushed raw, flush it to disk now.
     if ( bDirty )
     {
+        int nRet = 0;
         if( bIsVSIL )
-            VSIFFlushL( fpRawL );
+            nRet = VSIFFlushL( fpRawL );
         else
-            VSIFFlush( fpRaw );
+            /*nRet = */VSIFFlush( fpRaw );
 
         bDirty = FALSE;
+        if( nRet < 0 )
+            return CE_Failure;
     }
 
     return CE_None;
@@ -266,11 +289,13 @@ CPLErr RawRasterBand::AccessLine( int iLine )
 /* -------------------------------------------------------------------- */
     vsi_l_offset nReadStart;
     if( nPixelOffset >= 0 )
+    {
         nReadStart = nImgOffset + (vsi_l_offset)iLine * nLineOffset;
+    }
     else
     {
         nReadStart = nImgOffset + (vsi_l_offset)iLine * nLineOffset
-            - ABS(nPixelOffset) * (nBlockXSize-1);
+            - std::abs(nPixelOffset) * (nBlockXSize-1);
     }
 
 /* -------------------------------------------------------------------- */
@@ -281,13 +306,13 @@ CPLErr RawRasterBand::AccessLine( int iLine )
         if (poDS != NULL && poDS->GetAccess() == GA_ReadOnly)
         {
             CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to seek to scanline %d @ " CPL_FRMT_GUIB ".\n",
+                  "Failed to seek to scanline %d @ " CPL_FRMT_GUIB ".",
                   iLine, nImgOffset + (vsi_l_offset)iLine * nLineOffset );
             return CE_Failure;
         }
         else
         {
-            memset( pLineBuffer, 0, nPixelOffset * nBlockXSize );
+            memset( pLineBuffer, 0, nLineSize );
             nLoadedScanline = iLine;
             return CE_None;
         }
@@ -298,25 +323,24 @@ CPLErr RawRasterBand::AccessLine( int iLine )
 /*      are needed, and not to lose a partially successful scanline     */
 /*      read.                                                           */
 /* -------------------------------------------------------------------- */
-    int	nBytesToRead, nBytesActuallyRead;
-
-    nBytesToRead = ABS(nPixelOffset) * (nBlockXSize - 1) 
-        + GDALGetDataTypeSize(GetRasterDataType()) / 8;
+    const size_t nBytesToRead = std::abs(nPixelOffset) * (nBlockXSize - 1)
+        + GDALGetDataTypeSizeBytes(GetRasterDataType());
 
-    nBytesActuallyRead = Read( pLineBuffer, 1, nBytesToRead );
-    if( nBytesActuallyRead < nBlockXSize )
+    const size_t nBytesActuallyRead = Read( pLineBuffer, 1, nBytesToRead );
+    if( nBytesActuallyRead < nBytesToRead )
     {
         if (poDS != NULL && poDS->GetAccess() == GA_ReadOnly)
         {
             CPLError( CE_Failure, CPLE_FileIO,
-                      "Failed to read scanline %d.\n",
+                      "Failed to read scanline %d.",
                       iLine);
             return CE_Failure;
         }
         else
         {
-            memset( ((GByte *) pLineBuffer) + nBytesActuallyRead, 
-                    0, nBytesToRead - nBytesActuallyRead );
+            memset(
+                reinterpret_cast<GByte *>( pLineBuffer ) + nBytesActuallyRead,
+                0, nBytesToRead - nBytesActuallyRead );
         }
     }
 
@@ -327,16 +351,18 @@ CPLErr RawRasterBand::AccessLine( int iLine )
     {
         if( GDALDataTypeIsComplex( eDataType ) )
         {
-            int nWordSize;
-
-            nWordSize = GDALGetDataTypeSize(eDataType)/16;
-            GDALSwapWords( pLineBuffer, nWordSize, nBlockXSize, ABS(nPixelOffset) );
-            GDALSwapWords( ((GByte *) pLineBuffer)+nWordSize, 
-                           nWordSize, nBlockXSize, ABS(nPixelOffset) );
+            const int nWordSize = GDALGetDataTypeSize(eDataType)/16;
+            GDALSwapWords( pLineBuffer, nWordSize, nBlockXSize,
+                           std::abs(nPixelOffset) );
+            GDALSwapWords(
+                reinterpret_cast<GByte *>( pLineBuffer ) + nWordSize,
+                nWordSize, nBlockXSize, std::abs(nPixelOffset) );
         }
         else
-            GDALSwapWords( pLineBuffer, GDALGetDataTypeSize(eDataType)/8,
-                           nBlockXSize, ABS(nPixelOffset) );
+        {
+            GDALSwapWords( pLineBuffer, GDALGetDataTypeSizeBytes(eDataType),
+                           nBlockXSize, std::abs(nPixelOffset) );
+        }
     }
 
     nLoadedScanline = iLine;
@@ -352,20 +378,20 @@ CPLErr RawRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                                   int nBlockYOff,
                                   void * pImage )
 {
-    CPLErr		eErr;
-
     CPLAssert( nBlockXOff == 0 );
 
     if (pLineBuffer == NULL)
         return CE_Failure;
 
-    eErr = AccessLine( nBlockYOff );
+    const CPLErr eErr = AccessLine( nBlockYOff );
+    if( eErr == CE_Failure )
+        return eErr;
 
 /* -------------------------------------------------------------------- */
 /*      Copy data from disk buffer to user block buffer.                */
 /* -------------------------------------------------------------------- */
     GDALCopyWords( pLineStart, eDataType, nPixelOffset,
-                   pImage, eDataType, GDALGetDataTypeSize(eDataType)/8,
+                   pImage, eDataType, GDALGetDataTypeSizeBytes(eDataType),
                    nBlockXSize );
 
     return eErr;
@@ -379,8 +405,6 @@ CPLErr RawRasterBand::IWriteBlock( CPL_UNUSED int nBlockXOff,
                                    int nBlockYOff,
                                    void * pImage )
 {
-    CPLErr		eErr = CE_None;
-
     CPLAssert( nBlockXOff == 0 );
 
     if (pLineBuffer == NULL)
@@ -390,13 +414,14 @@ CPLErr RawRasterBand::IWriteBlock( CPL_UNUSED int nBlockXOff,
 /*      If the data for this band is completely contiguous we don't     */
 /*      have to worry about pre-reading from disk.                      */
 /* -------------------------------------------------------------------- */
-    if( ABS(nPixelOffset) > GDALGetDataTypeSize(eDataType) / 8 )
+    CPLErr eErr = CE_None;
+    if( std::abs(nPixelOffset) > GDALGetDataTypeSizeBytes(eDataType) )
         eErr = AccessLine( nBlockYOff );
 
 /* -------------------------------------------------------------------- */
-/*	Copy data from user buffer into disk buffer.                    */
+/*      Copy data from user buffer into disk buffer.                    */
 /* -------------------------------------------------------------------- */
-    GDALCopyWords( pImage, eDataType, GDALGetDataTypeSize(eDataType)/8,
+    GDALCopyWords( pImage, eDataType, GDALGetDataTypeSizeBytes(eDataType),
                    pLineStart, eDataType, nPixelOffset,
                    nBlockXSize );
 
@@ -407,61 +432,62 @@ CPLErr RawRasterBand::IWriteBlock( CPL_UNUSED int nBlockXOff,
     {
         if( GDALDataTypeIsComplex( eDataType ) )
         {
-            int nWordSize;
-
-            nWordSize = GDALGetDataTypeSize(eDataType)/16;
-            GDALSwapWords( pLineBuffer, nWordSize, nBlockXSize, 
-                           ABS(nPixelOffset) );
-            GDALSwapWords( ((GByte *) pLineBuffer)+nWordSize, 
-                           nWordSize, nBlockXSize, ABS(nPixelOffset) );
+            const int nWordSize = GDALGetDataTypeSize(eDataType)/16;
+            GDALSwapWords( pLineBuffer, nWordSize, nBlockXSize,
+                           std::abs(nPixelOffset) );
+            GDALSwapWords(
+                reinterpret_cast<GByte *>( pLineBuffer ) + nWordSize,
+                nWordSize, nBlockXSize, std::abs(nPixelOffset) );
         }
         else
-            GDALSwapWords( pLineBuffer, GDALGetDataTypeSize(eDataType)/8,
-                           nBlockXSize, ABS(nPixelOffset) );
+            GDALSwapWords( pLineBuffer, GDALGetDataTypeSizeBytes(eDataType),
+                           nBlockXSize, std::abs(nPixelOffset) );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Figure out where to start reading.                              */
 /* -------------------------------------------------------------------- */
-    vsi_l_offset nWriteStart;
+    vsi_l_offset nWriteStart = 0;
     if( nPixelOffset >= 0 )
         nWriteStart = nImgOffset + (vsi_l_offset)nBlockYOff * nLineOffset;
     else
     {
-        nWriteStart = nImgOffset + (vsi_l_offset)nBlockYOff * nLineOffset
-            - ABS(nPixelOffset) * (nBlockXSize-1);
+        nWriteStart =
+            nImgOffset
+            + static_cast<vsi_l_offset>(nBlockYOff) * nLineOffset
+            - std::abs(nPixelOffset) * (nBlockXSize-1);
     }
 
 /* -------------------------------------------------------------------- */
 /*      Seek to correct location.                                       */
 /* -------------------------------------------------------------------- */
-    if( Seek( nWriteStart, SEEK_SET ) == -1 ) 
+    if( Seek( nWriteStart, SEEK_SET ) == -1 )
     {
         CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to seek to scanline %d @ " CPL_FRMT_GUIB " to write to file.\n",
+                  "Failed to seek to scanline %d @ " CPL_FRMT_GUIB
+                  " to write to file.",
                   nBlockYOff, nImgOffset + nBlockYOff * nLineOffset );
-        
+
         eErr = CE_Failure;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Write data buffer.                                              */
 /* -------------------------------------------------------------------- */
-    int	nBytesToWrite;
-
-    nBytesToWrite = ABS(nPixelOffset) * (nBlockXSize - 1) 
-        + GDALGetDataTypeSize(GetRasterDataType()) / 8;
+    const int nBytesToWrite = std::abs(nPixelOffset) * (nBlockXSize - 1)
+        + GDALGetDataTypeSizeBytes(GetRasterDataType());
 
-    if( eErr == CE_None 
-        && Write( pLineBuffer, 1, nBytesToWrite ) < (size_t) nBytesToWrite )
+    if( eErr == CE_None
+        && Write( pLineBuffer, 1, nBytesToWrite )
+        < static_cast<size_t>( nBytesToWrite ) )
     {
         CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to write scanline %d to file.\n",
+                  "Failed to write scanline %d to file.",
                   nBlockYOff );
-        
+
         eErr = CE_Failure;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Byte swap (if necessary) back into machine order so the         */
 /*      buffer is still usable for reading purposes.                    */
@@ -470,18 +496,18 @@ CPLErr RawRasterBand::IWriteBlock( CPL_UNUSED int nBlockXOff,
     {
         if( GDALDataTypeIsComplex( eDataType ) )
         {
-            int nWordSize;
-
-            nWordSize = GDALGetDataTypeSize(eDataType)/16;
-            GDALSwapWords( pLineBuffer, nWordSize, nBlockXSize, 
-                           ABS(nPixelOffset) );
-            GDALSwapWords( ((GByte *) pLineBuffer)+nWordSize, 
-                           nWordSize, nBlockXSize, 
-                           ABS(nPixelOffset) );
+            const int nWordSize = GDALGetDataTypeSize(eDataType)/16;
+            GDALSwapWords( pLineBuffer, nWordSize, nBlockXSize,
+                           std::abs(nPixelOffset) );
+            GDALSwapWords( reinterpret_cast<GByte *>( pLineBuffer ) +
+                           nWordSize, nWordSize, nBlockXSize,
+                           std::abs(nPixelOffset) );
         }
         else
-            GDALSwapWords( pLineBuffer, GDALGetDataTypeSize(eDataType)/8,
-                           nBlockXSize, ABS(nPixelOffset) );
+        {
+            GDALSwapWords( pLineBuffer, GDALGetDataTypeSizeBytes(eDataType),
+                           nBlockXSize, std::abs(nPixelOffset) );
+        }
     }
 
     bDirty = TRUE;
@@ -492,11 +518,9 @@ CPLErr RawRasterBand::IWriteBlock( CPL_UNUSED int nBlockXOff,
 /*                             AccessBlock()                            */
 /************************************************************************/
 
-CPLErr RawRasterBand::AccessBlock( vsi_l_offset nBlockOff, int nBlockSize,
+CPLErr RawRasterBand::AccessBlock( vsi_l_offset nBlockOff, size_t nBlockSize,
                                    void * pData )
 {
-    int         nBytesActuallyRead;
-
 /* -------------------------------------------------------------------- */
 /*      Seek to the right block.                                        */
 /* -------------------------------------------------------------------- */
@@ -509,11 +533,11 @@ CPLErr RawRasterBand::AccessBlock( vsi_l_offset nBlockOff, int nBlockSize,
 /* -------------------------------------------------------------------- */
 /*      Read the block.                                                 */
 /* -------------------------------------------------------------------- */
-    nBytesActuallyRead = Read( pData, 1, nBlockSize );
+    const size_t nBytesActuallyRead = Read( pData, 1, nBlockSize );
     if( nBytesActuallyRead < nBlockSize )
     {
 
-        memset( ((GByte *) pData) + nBytesActuallyRead, 
+        memset( reinterpret_cast<GByte *>( pData ) + nBytesActuallyRead,
                 0, nBlockSize - nBytesActuallyRead );
         return CE_None;
     }
@@ -525,17 +549,17 @@ CPLErr RawRasterBand::AccessBlock( vsi_l_offset nBlockOff, int nBlockSize,
     {
         if( GDALDataTypeIsComplex( eDataType ) )
         {
-            int nWordSize;
-
-            nWordSize = GDALGetDataTypeSize(eDataType)/16;
-            GDALSwapWords( pData, nWordSize, nBlockSize / nPixelOffset,
-                           nPixelOffset );
-            GDALSwapWords( ((GByte *) pData) + nWordSize, 
+            const int nWordSize = GDALGetDataTypeSize(eDataType)/16;
+            GDALSwapWordsEx( pData, nWordSize, nBlockSize / nPixelOffset,
+                             nPixelOffset );
+            GDALSwapWordsEx( reinterpret_cast<GByte *>( pData ) + nWordSize,
                            nWordSize, nBlockSize / nPixelOffset, nPixelOffset );
         }
         else
-            GDALSwapWords( pData, GDALGetDataTypeSize(eDataType) / 8,
-                           nBlockSize / nPixelOffset, nPixelOffset );
+        {
+            GDALSwapWordsEx( pData, GDALGetDataTypeSizeBytes(eDataType),
+                             nBlockSize / nPixelOffset, nPixelOffset );
+        }
     }
 
     return CE_None;
@@ -550,16 +574,15 @@ CPLErr RawRasterBand::AccessBlock( vsi_l_offset nBlockOff, int nBlockSize,
 
 int RawRasterBand::IsSignificantNumberOfLinesLoaded( int nLineOff, int nLines )
 {
-    int         iLine;
-    int         nCountLoaded = 0;
+    int nCountLoaded = 0;
 
-    for ( iLine = nLineOff; iLine < nLineOff + nLines; iLine++ )
+    for ( int iLine = nLineOff; iLine < nLineOff + nLines; iLine++ )
     {
         GDALRasterBlock *poBlock = TryGetLockedBlockRef( 0, iLine );
         if( poBlock != NULL )
         {
             poBlock->DropLock();
-            nCountLoaded ++;
+            nCountLoaded++;
             if( nCountLoaded > nLines / 20 )
             {
                 return TRUE;
@@ -574,11 +597,11 @@ int RawRasterBand::IsSignificantNumberOfLinesLoaded( int nLineOff, int nLines )
 /*                           CanUseDirectIO()                           */
 /************************************************************************/
 
-int RawRasterBand::CanUseDirectIO(CPL_UNUSED int nXOff,
+int RawRasterBand::CanUseDirectIO(int /* nXOff */,
                                   int nYOff,
                                   int nXSize,
                                   int nYSize,
-                                  CPL_UNUSED GDALDataType eBufType)
+                                  GDALDataType /* eBufType*/)
 {
 
 /* -------------------------------------------------------------------- */
@@ -598,21 +621,21 @@ int RawRasterBand::CanUseDirectIO(CPL_UNUSED int nXOff,
         return FALSE;
     }
 
-    const char* pszGDAL_ONE_BIG_READ = CPLGetConfigOption( "GDAL_ONE_BIG_READ", NULL);
+    const char* pszGDAL_ONE_BIG_READ =
+        CPLGetConfigOption( "GDAL_ONE_BIG_READ", NULL);
     if ( pszGDAL_ONE_BIG_READ == NULL )
     {
-        int         nBytesToRW = nPixelOffset * nXSize;
+        const int nBytesToRW = nPixelOffset * nXSize;
         if ( nLineSize < 50000
              || nBytesToRW > nLineSize / 5 * 2
              || IsSignificantNumberOfLinesLoaded( nYOff, nYSize ) )
         {
-
             return FALSE;
         }
         return TRUE;
     }
-    else
-        return CSLTestBoolean(pszGDAL_ONE_BIG_READ);
+
+    return CPLTestBool(pszGDAL_ONE_BIG_READ);
 }
 
 /************************************************************************/
@@ -627,9 +650,14 @@ CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                                  GDALRasterIOExtraArg* psExtraArg )
 
 {
-    int         nBandDataSize = GDALGetDataTypeSize(eDataType) / 8;
-    int         nBufDataSize = GDALGetDataTypeSize( eBufType ) / 8;
-    int         nBytesToRW = nPixelOffset * nXSize;
+    const int nBandDataSize = GDALGetDataTypeSizeBytes(eDataType);
+#ifdef DEBUG
+    // Otherwise Coverity thinks that a divide by zero is possible in
+    // AccessBlock() in the complex data type wapping case.
+    if( nBandDataSize == 0 )
+        return CE_Failure;
+#endif
+    const int nBufDataSize = GDALGetDataTypeSizeBytes( eBufType );
 
     if( !CanUseDirectIO(nXOff, nYOff, nXSize, nYSize, eBufType ) )
     {
@@ -654,9 +682,10 @@ CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
         if( (nBufXSize < nXSize || nBufYSize < nYSize)
             && GetOverviewCount() > 0 )
         {
-            if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, 
-                                  pData, nBufXSize, nBufYSize, 
-                                  eBufType, nPixelSpace, nLineSpace, psExtraArg ) == CE_None )
+            if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                                  pData, nBufXSize, nBufYSize,
+                                  eBufType, nPixelSpace, nLineSpace,
+                                  psExtraArg ) == CE_None )
                 return CE_None;
         }
 
@@ -664,7 +693,7 @@ CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 /*   1. Simplest case when we should get contiguous block               */
 /*   of uninterleaved pixels.                                           */
 /* ==================================================================== */
-        if ( nXSize == GetXSize() 
+        if ( nXSize == GetXSize()
              && nXSize == nBufXSize
              && nYSize == nBufYSize
              && eBufType == eDataType
@@ -672,14 +701,18 @@ CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
              && nPixelSpace == nBufDataSize
              && nLineSpace == nPixelSpace * nXSize )
         {
-            vsi_l_offset nOffset = nImgOffset
-                              + (vsi_l_offset)nYOff * nLineOffset + nXOff;
-            if ( AccessBlock( nOffset,
-                              nXSize * nYSize * nBandDataSize, pData ) != CE_None )
+            const vsi_l_offset nOffset =
+                nImgOffset
+                + static_cast<vsi_l_offset>(nYOff) * nLineOffset + nXOff;
+            const size_t nBytesToRead =
+                static_cast<size_t>(nXSize) * nYSize * nBandDataSize;
+            if ( AccessBlock( nOffset, nBytesToRead, pData ) != CE_None )
             {
                 CPLError( CE_Failure, CPLE_FileIO,
-                          "Failed to read %d bytes at " CPL_FRMT_GUIB ".",
-                          nXSize * nYSize * nBandDataSize, nOffset);
+                          "Failed to read " CPL_FRMT_GUIB
+                          " bytes at " CPL_FRMT_GUIB ".",
+                          static_cast<GUIntBig>(nBytesToRead), nOffset );
+                return CE_Failure;
             }
         }
 
@@ -688,28 +721,34 @@ CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 /* ==================================================================== */
         else
         {
-            GByte   *pabyData;
-            double  dfSrcXInc, dfSrcYInc;
-            int     iLine;
-            
-            dfSrcXInc = (double)nXSize / nBufXSize;
-            dfSrcYInc = (double)nYSize / nBufYSize;
-
-
-            pabyData = (GByte *) CPLMalloc( nBytesToRW );
+            const double dfSrcXInc =
+                static_cast<double>( nXSize ) / nBufXSize;
+            const double dfSrcYInc =
+                static_cast<double>( nYSize ) / nBufYSize;
+
+            const size_t nBytesToRW =
+                static_cast<size_t>(nPixelOffset) * nXSize;
+            GByte *pabyData = reinterpret_cast<GByte *>(
+                VSI_MALLOC_VERBOSE( nBytesToRW ) );
+            if( pabyData == NULL )
+                return CE_Failure;
 
-            for ( iLine = 0; iLine < nBufYSize; iLine++ )
+            for ( int iLine = 0; iLine < nBufYSize; iLine++ )
             {
-                vsi_l_offset nOffset = nImgOffset
-                                  + ((vsi_l_offset)nYOff
-                                  + (vsi_l_offset)(iLine * dfSrcYInc)) * nLineOffset
-                                  + nXOff * nPixelOffset;
+                const vsi_l_offset nOffset = nImgOffset
+                    +  ( (static_cast<vsi_l_offset>( nYOff )
+                          + static_cast<vsi_l_offset>( iLine * dfSrcYInc ) )
+                         * nLineOffset )
+                    + nXOff * nPixelOffset;
                 if ( AccessBlock( nOffset,
                                   nBytesToRW, pabyData ) != CE_None )
                 {
                     CPLError( CE_Failure, CPLE_FileIO,
-                              "Failed to read %d bytes at " CPL_FRMT_GUIB ".",
-                              nBytesToRW, nOffset );
+                              "Failed to read " CPL_FRMT_GUIB
+                              " bytes at " CPL_FRMT_GUIB ".",
+                              static_cast<GUIntBig>(nBytesToRW), nOffset );
+                    CPLFree( pabyData );
+                    return CE_Failure;
                 }
 
 /* -------------------------------------------------------------------- */
@@ -719,21 +758,26 @@ CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                 if ( nXSize == nBufXSize && nYSize == nBufYSize )
                 {
                     GDALCopyWords( pabyData, eDataType, nPixelOffset,
-                                   (GByte *)pData + (vsi_l_offset)iLine * nLineSpace,
-                                   eBufType, nPixelSpace, nXSize );
+                                   reinterpret_cast<GByte *>( pData ) +
+                                   static_cast<vsi_l_offset>( iLine ) *
+                                   nLineSpace,
+                                   eBufType, static_cast<int>(nPixelSpace),
+                                   nXSize );
                 }
                 else
                 {
-                    int     iPixel;
-
-                    for ( iPixel = 0; iPixel < nBufXSize; iPixel++ )
+                    for ( int iPixel = 0; iPixel < nBufXSize; iPixel++ )
                     {
-                        GDALCopyWords( pabyData +
-                                       (vsi_l_offset)(iPixel * dfSrcXInc) * nPixelOffset,
-                                       eDataType, nPixelOffset,
-                                       (GByte *)pData + (vsi_l_offset)iLine * nLineSpace +
-                                       (vsi_l_offset)iPixel * nPixelSpace,
-                                       eBufType, nPixelSpace, 1 );
+                        GDALCopyWords(
+                            pabyData +
+                            static_cast<vsi_l_offset>( iPixel * dfSrcXInc ) *
+                            nPixelOffset,
+                            eDataType, nPixelOffset,
+                            reinterpret_cast<GByte *>( pData ) +
+                            static_cast<vsi_l_offset>( iLine ) *
+                            nLineSpace +
+                            static_cast<vsi_l_offset>( iPixel) * nPixelSpace,
+                            eBufType, static_cast<int>(nPixelSpace), 1 );
                     }
                 }
 
@@ -755,13 +799,11 @@ CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 /* ==================================================================== */
     else
     {
-        int nBytesActuallyWritten;
-
 /* ==================================================================== */
 /*   1. Simplest case when we should write contiguous block             */
 /*   of uninterleaved pixels.                                           */
 /* ==================================================================== */
-        if ( nXSize == GetXSize() 
+        if ( nXSize == GetXSize()
              && nXSize == nBufXSize
              && nYSize == nBufYSize
              && eBufType == eDataType
@@ -776,42 +818,48 @@ CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
             {
                 if( GDALDataTypeIsComplex( eDataType ) )
                 {
-                    int nWordSize;
-
-                    nWordSize = GDALGetDataTypeSize(eDataType)/16;
+                    const int nWordSize = GDALGetDataTypeSize(eDataType)/16;
                     GDALSwapWords( pData, nWordSize, nXSize, nPixelOffset );
-                    GDALSwapWords( ((GByte *) pData) + nWordSize, 
-                                   nWordSize, nXSize, nPixelOffset );
+                    GDALSwapWords(
+                        reinterpret_cast<GByte *>( pData ) + nWordSize,
+                        nWordSize, nXSize, nPixelOffset );
                 }
                 else
+                {
                     GDALSwapWords( pData, nBandDataSize, nXSize, nPixelOffset );
+                }
             }
 
 /* -------------------------------------------------------------------- */
 /*      Seek to the right block.                                        */
 /* -------------------------------------------------------------------- */
-            vsi_l_offset nOffset = nImgOffset + (vsi_l_offset)nYOff * nLineOffset + nXOff;
+            vsi_l_offset nOffset =
+                nImgOffset +
+                static_cast<vsi_l_offset>(nYOff) * nLineOffset + nXOff;
             if( Seek( nOffset, SEEK_SET) == -1 )
             {
                 CPLError( CE_Failure, CPLE_FileIO,
-                          "Failed to seek to " CPL_FRMT_GUIB " to write data.\n",
+                          "Failed to seek to " CPL_FRMT_GUIB " to write data.",
                           nOffset);
-        
+
                 return CE_Failure;
             }
 
 /* -------------------------------------------------------------------- */
 /*      Write the block.                                                */
 /* -------------------------------------------------------------------- */
-            nBytesToRW = nXSize * nYSize * nBandDataSize;
+            const size_t nBytesToRW =
+                static_cast<size_t>(nXSize) * nYSize * nBandDataSize;
 
-            nBytesActuallyWritten = Write( pData, 1, nBytesToRW );
+            const size_t nBytesActuallyWritten = Write( pData, 1, nBytesToRW );
             if( nBytesActuallyWritten < nBytesToRW )
             {
                 CPLError( CE_Failure, CPLE_FileIO,
-                          "Failed to write %d bytes to file. %d bytes written",
-                          nBytesToRW, nBytesActuallyWritten );
-        
+                          "Failed to write " CPL_FRMT_GUIB
+                          " bytes to file. " CPL_FRMT_GUIB " bytes written",
+                          static_cast<GUIntBig>(nBytesToRW),
+                          static_cast<GUIntBig>(nBytesActuallyWritten) );
+
                 return CE_Failure;
             }
 
@@ -823,15 +871,16 @@ CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
             {
                 if( GDALDataTypeIsComplex( eDataType ) )
                 {
-                    int nWordSize;
-
-                    nWordSize = GDALGetDataTypeSize(eDataType)/16;
+                    const int nWordSize = GDALGetDataTypeSize(eDataType) / 16;
                     GDALSwapWords( pData, nWordSize, nXSize, nPixelOffset );
-                    GDALSwapWords( ((GByte *) pData) + nWordSize, 
-                                   nWordSize, nXSize, nPixelOffset );
+                    GDALSwapWords(
+                        reinterpret_cast<GByte *>( pData ) + nWordSize,
+                        nWordSize, nXSize, nPixelOffset );
                 }
                 else
+                {
                     GDALSwapWords( pData, nBandDataSize, nXSize, nPixelOffset );
+                }
             }
         }
 
@@ -840,21 +889,23 @@ CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 /* ==================================================================== */
         else
         {
-            GByte   *pabyData;
-            double  dfSrcXInc, dfSrcYInc;
-            vsi_l_offset nBlockOff;
-            int     iLine;
-            
-            dfSrcXInc = (double)nXSize / nBufXSize;
-            dfSrcYInc = (double)nYSize / nBufYSize;
+            const double dfSrcXInc = static_cast<double>( nXSize ) / nBufXSize;
+            const double dfSrcYInc = static_cast<double>( nYSize ) / nBufYSize;
 
-            pabyData = (GByte *) CPLMalloc( nBytesToRW );
+            const size_t nBytesToRW = static_cast<size_t>(nPixelOffset) * nXSize;
+            GByte *pabyData = reinterpret_cast<GByte *>(
+                VSI_MALLOC_VERBOSE( nBytesToRW ) );
+            if( pabyData == NULL )
+                return CE_Failure;
 
-            for ( iLine = 0; iLine < nBufYSize; iLine++ )
+            for ( int iLine = 0; iLine < nBufYSize; iLine++ )
             {
-                nBlockOff = nImgOffset
-                    + ((vsi_l_offset)nYOff + (vsi_l_offset)(iLine*dfSrcYInc))*nLineOffset
-                    + nXOff * nPixelOffset;
+                const vsi_l_offset nBlockOff =
+                    nImgOffset
+                    + ( static_cast<vsi_l_offset>(nYOff) +
+                        static_cast<vsi_l_offset>(iLine*dfSrcYInc) )
+                    * nLineOffset
+                    + static_cast<vsi_l_offset>(nXOff) * nPixelOffset;
 
 /* -------------------------------------------------------------------- */
 /*      If the data for this band is completely contiguous we don't     */
@@ -869,22 +920,25 @@ CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 /* -------------------------------------------------------------------- */
                 if ( nXSize == nBufXSize && nYSize == nBufYSize )
                 {
-                    GDALCopyWords( (GByte *)pData + (vsi_l_offset)iLine * nLineSpace,
-                                   eBufType, nPixelSpace,
-                                   pabyData, eDataType, nPixelOffset, nXSize );
+                    GDALCopyWords(
+                        reinterpret_cast<GByte *>( pData ) +
+                        static_cast<vsi_l_offset>( iLine ) * nLineSpace,
+                        eBufType, static_cast<int>(nPixelSpace),
+                        pabyData, eDataType, nPixelOffset, nXSize );
                 }
                 else
                 {
-                    int     iPixel;
-
-                    for ( iPixel = 0; iPixel < nBufXSize; iPixel++ )
+                    for ( int iPixel = 0; iPixel < nBufXSize; iPixel++ )
                     {
-                        GDALCopyWords( (GByte *)pData+(vsi_l_offset)iLine*nLineSpace +
-                                       (vsi_l_offset)iPixel * nPixelSpace,
-                                       eBufType, nPixelSpace,
-                                       pabyData +
-                                       (vsi_l_offset)(iPixel * dfSrcXInc) * nPixelOffset,
-                                       eDataType, nPixelOffset, 1 );
+                        GDALCopyWords(
+                            reinterpret_cast<GByte *>(pData) +
+                            static_cast<vsi_l_offset>( iLine ) * nLineSpace +
+                            static_cast<vsi_l_offset>( iPixel ) * nPixelSpace,
+                            eBufType, static_cast<int>(nPixelSpace),
+                            pabyData +
+                            static_cast<vsi_l_offset>( iPixel * dfSrcXInc ) *
+                            nPixelOffset,
+                            eDataType, nPixelOffset, 1 );
                     }
                 }
 
@@ -895,12 +949,12 @@ CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                 {
                     if( GDALDataTypeIsComplex( eDataType ) )
                     {
-                        int nWordSize;
-
-                        nWordSize = GDALGetDataTypeSize(eDataType)/16;
-                        GDALSwapWords( pabyData, nWordSize, nXSize, nPixelOffset );
-                        GDALSwapWords( ((GByte *) pabyData) + nWordSize, 
-                                       nWordSize, nXSize, nPixelOffset );
+                        const int nWordSize = GDALGetDataTypeSize(eDataType)/16;
+                        GDALSwapWords(
+                            pabyData, nWordSize, nXSize, nPixelOffset );
+                        GDALSwapWords(
+                            reinterpret_cast<GByte *>( pabyData ) + nWordSize,
+                            nWordSize, nXSize, nPixelOffset );
                     }
                     else
                         GDALSwapWords( pabyData, nBandDataSize, nXSize,
@@ -913,22 +967,25 @@ CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                 if( Seek( nBlockOff, SEEK_SET) == -1 )
                 {
                     CPLError( CE_Failure, CPLE_FileIO,
-                              "Failed to seek to " CPL_FRMT_GUIB " to read.\n",
+                              "Failed to seek to " CPL_FRMT_GUIB " to read.",
                               nBlockOff );
-
+                    CPLFree( pabyData );
                     return CE_Failure;
                 }
 
 /* -------------------------------------------------------------------- */
 /*      Write the line of block.                                        */
 /* -------------------------------------------------------------------- */
-                nBytesActuallyWritten = Write( pabyData, 1, nBytesToRW );
+                const size_t nBytesActuallyWritten =
+                    Write( pabyData, 1, nBytesToRW );
                 if( nBytesActuallyWritten < nBytesToRW )
                 {
                     CPLError( CE_Failure, CPLE_FileIO,
-                              "Failed to write %d bytes to file. %d bytes written",
-                              nBytesToRW, nBytesActuallyWritten );
-            
+                              "Failed to write " CPL_FRMT_GUIB
+                              " bytes to file. " CPL_FRMT_GUIB " bytes written",
+                              static_cast<GUIntBig>(nBytesToRW),
+                              static_cast<GUIntBig>(nBytesActuallyWritten) );
+                    CPLFree( pabyData );
                     return CE_Failure;
                 }
 
@@ -940,16 +997,18 @@ CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                 {
                     if( GDALDataTypeIsComplex( eDataType ) )
                     {
-                        int nWordSize;
-
-                        nWordSize = GDALGetDataTypeSize(eDataType)/16;
-                        GDALSwapWords( pabyData, nWordSize, nXSize, nPixelOffset );
-                        GDALSwapWords( ((GByte *) pabyData) + nWordSize, 
-                                       nWordSize, nXSize, nPixelOffset );
+                        const int nWordSize = GDALGetDataTypeSize(eDataType)/16;
+                        GDALSwapWords(
+                            pabyData, nWordSize, nXSize, nPixelOffset );
+                        GDALSwapWords(
+                            reinterpret_cast<GByte *>( pabyData ) + nWordSize,
+                            nWordSize, nXSize, nPixelOffset );
                     }
                     else
+                    {
                         GDALSwapWords( pabyData, nBandDataSize, nXSize,
                                        nPixelOffset );
+                    }
                 }
 
             }
@@ -971,8 +1030,8 @@ int RawRasterBand::Seek( vsi_l_offset nOffset, int nSeekMode )
 {
     if( bIsVSIL )
         return VSIFSeekL( fpRawL, nOffset, nSeekMode );
-    else
-        return VSIFSeek( fpRaw, (long) nOffset, nSeekMode );
+
+    return VSIFSeek( fpRaw, static_cast<long>( nOffset ), nSeekMode );
 }
 
 /************************************************************************/
@@ -984,8 +1043,8 @@ size_t RawRasterBand::Read( void *pBuffer, size_t nSize, size_t nCount )
 {
     if( bIsVSIL )
         return VSIFReadL( pBuffer, nSize, nCount, fpRawL );
-    else
-        return VSIFRead( pBuffer, nSize, nCount, fpRaw );
+
+    return VSIFRead( pBuffer, nSize, nCount, fpRaw );
 }
 
 /************************************************************************/
@@ -997,8 +1056,8 @@ size_t RawRasterBand::Write( void *pBuffer, size_t nSize, size_t nCount )
 {
     if( bIsVSIL )
         return VSIFWriteL( pBuffer, nSize, nCount, fpRawL );
-    else
-        return VSIFWrite( pBuffer, nSize, nCount, fpRaw );
+
+    return VSIFWrite( pBuffer, nSize, nCount, fpRaw );
 }
 
 /************************************************************************/
@@ -1099,16 +1158,21 @@ CPLVirtualMem  *RawRasterBand::GetVirtualMemAuto( GDALRWFlag eRWFlag,
     CPLAssert(pnPixelSpace);
     CPLAssert(pnLineSpace);
 
-    vsi_l_offset nSize =  (vsi_l_offset)(nRasterYSize - 1) * nLineOffset +
-        (nRasterXSize - 1) * nPixelOffset + GDALGetDataTypeSize(eDataType) / 8;
+    const vsi_l_offset nSize =
+        static_cast<vsi_l_offset>(nRasterYSize - 1) * nLineOffset +
+        (nRasterXSize - 1) * nPixelOffset + GDALGetDataTypeSizeBytes(eDataType);
 
     if( !bIsVSIL || VSIFGetNativeFileDescriptorL(fpRawL) == NULL ||
-        !CPLIsVirtualMemFileMapAvailable() || (eDataType != GDT_Byte && !bNativeOrder) ||
-        (size_t)nSize != nSize || nPixelOffset < 0 || nLineOffset < 0 ||
-        CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "USE_DEFAULT_IMPLEMENTATION", "NO")) )
+        !CPLIsVirtualMemFileMapAvailable() ||
+        (eDataType != GDT_Byte && !bNativeOrder) ||
+        static_cast<size_t>(nSize) != nSize ||
+        nPixelOffset < 0 ||
+        nLineOffset < 0 ||
+        CPLTestBool( CSLFetchNameValueDef(
+            papszOptions, "USE_DEFAULT_IMPLEMENTATION", "NO") ) )
     {
-        return GDALRasterBand::GetVirtualMemAuto(eRWFlag, pnPixelSpace,
-                                                 pnLineSpace, papszOptions);
+        return GDALRasterBand::GetVirtualMemAuto( eRWFlag, pnPixelSpace,
+                                                  pnLineSpace, papszOptions);
     }
 
     FlushCache();
@@ -1119,8 +1183,8 @@ CPLVirtualMem  *RawRasterBand::GetVirtualMemAuto( GDALRWFlag eRWFlag,
         NULL, NULL);
     if( pVMem == NULL )
     {
-        return GDALRasterBand::GetVirtualMemAuto(eRWFlag, pnPixelSpace,
-                                                 pnLineSpace, papszOptions);
+        return GDALRasterBand::GetVirtualMemAuto( eRWFlag, pnPixelSpace,
+                                                  pnLineSpace, papszOptions);
     }
     else
     {
@@ -1141,20 +1205,14 @@ CPLVirtualMem  *RawRasterBand::GetVirtualMemAuto( GDALRWFlag eRWFlag,
 /*                            RawDataset()                              */
 /************************************************************************/
 
-RawDataset::RawDataset()
-
-{
-}
+RawDataset::RawDataset() {}
 
 /************************************************************************/
 /*                           ~RawDataset()                              */
 /************************************************************************/
 
-RawDataset::~RawDataset()
-
-{
     /* It's pure virtual function but must be defined, even if empty. */
-}
+RawDataset::~RawDataset() {}
 
 /************************************************************************/
 /*                             IRasterIO()                              */
@@ -1162,30 +1220,32 @@ RawDataset::~RawDataset()
 /*      Multi-band raster io handler.                                   */
 /************************************************************************/
 
-CPLErr RawDataset::IRasterIO( GDALRWFlag eRWFlag, 
+CPLErr RawDataset::IRasterIO( GDALRWFlag eRWFlag,
                               int nXOff, int nYOff, int nXSize, int nYSize,
-                              void *pData, int nBufXSize, int nBufYSize, 
+                              void *pData, int nBufXSize, int nBufYSize,
                               GDALDataType eBufType,
-                              int nBandCount, int *panBandMap, 
+                              int nBandCount, int *panBandMap,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
                               GSpacing nBandSpace,
                               GDALRasterIOExtraArg* psExtraArg )
 
 {
-    const char* pszInterleave;
+    const char* pszInterleave = NULL;
 
-    /* The default GDALDataset::IRasterIO() implementation would go to */
-    /* BlockBasedRasterIO if the dataset is interleaved. However if the */
-    /* access pattern is compatible with DirectIO() we don't want to go */
-    /* BlockBasedRasterIO, but rather used our optimized path in RawRasterBand::IRasterIO() */
+    // The default GDALDataset::IRasterIO() implementation would go to
+    // BlockBasedRasterIO if the dataset is interleaved. However if the
+    // access pattern is compatible with DirectIO() we don't want to go
+    // BlockBasedRasterIO, but rather used our optimized path in
+    // RawRasterBand::IRasterIO()
     if (nXSize == nBufXSize && nYSize == nBufYSize && nBandCount > 1 &&
         (pszInterleave = GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE")) != NULL &&
         EQUAL(pszInterleave, "PIXEL"))
     {
-        int iBandIndex;
-        for(iBandIndex = 0; iBandIndex < nBandCount; iBandIndex ++ )
+        int iBandIndex = 0;
+        for( ; iBandIndex < nBandCount; iBandIndex++ )
         {
-            RawRasterBand* poBand = (RawRasterBand*) GetRasterBand(panBandMap[iBandIndex]);
+            RawRasterBand* poBand = reinterpret_cast<RawRasterBand *>(
+                GetRasterBand(panBandMap[iBandIndex]) );
             if( !poBand->CanUseDirectIO(nXOff, nYOff, nXSize, nYSize, eBufType ) )
             {
                 break;
@@ -1195,15 +1255,14 @@ CPLErr RawDataset::IRasterIO( GDALRWFlag eRWFlag,
         {
 
             GDALProgressFunc  pfnProgressGlobal = psExtraArg->pfnProgress;
-            void             *pProgressDataGlobal = psExtraArg->pProgressData;
+            void *pProgressDataGlobal = psExtraArg->pProgressData;
 
             CPLErr eErr = CE_None;
-            for( iBandIndex = 0; 
-                iBandIndex < nBandCount && eErr == CE_None; 
-                iBandIndex++ )
+            for( iBandIndex = 0;
+                 iBandIndex < nBandCount && eErr == CE_None;
+                 iBandIndex++ )
             {
                 GDALRasterBand *poBand = GetRasterBand(panBandMap[iBandIndex]);
-                GByte *pabyBandData;
 
                 if (poBand == NULL)
                 {
@@ -1211,18 +1270,23 @@ CPLErr RawDataset::IRasterIO( GDALRWFlag eRWFlag,
                     break;
                 }
 
-                pabyBandData = ((GByte *) pData) + iBandIndex * nBandSpace;
+                GByte *pabyBandData = reinterpret_cast<GByte *>( pData )
+                    + iBandIndex * nBandSpace;
 
                 psExtraArg->pfnProgress = GDALScaledProgress;
-                psExtraArg->pProgressData = 
-                    GDALCreateScaledProgress( 1.0 * iBandIndex / nBandCount,
-                                            1.0 * (iBandIndex + 1) / nBandCount,
-                                            pfnProgressGlobal,
-                                            pProgressDataGlobal );
-
-                eErr = poBand->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, 
-                                        (void *) pabyBandData, nBufXSize, nBufYSize,
-                                        eBufType, nPixelSpace, nLineSpace, psExtraArg );
+                psExtraArg->pProgressData =
+                    GDALCreateScaledProgress(
+                        1.0 * iBandIndex / nBandCount,
+                        1.0 * (iBandIndex + 1) / nBandCount,
+                        pfnProgressGlobal,
+                        pProgressDataGlobal );
+
+                eErr = poBand->RasterIO(
+                    eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                    reinterpret_cast<void *>( pabyBandData ),
+                    nBufXSize, nBufYSize,
+                    eBufType, nPixelSpace, nLineSpace,
+                    psExtraArg );
 
                 GDALDestroyScaledProgress( psExtraArg->pProgressData );
             }
@@ -1235,8 +1299,8 @@ CPLErr RawDataset::IRasterIO( GDALRWFlag eRWFlag,
     }
 
     return  GDALDataset::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                                    pData, nBufXSize, nBufYSize, eBufType, 
-                                    nBandCount, panBandMap, 
+                                    pData, nBufXSize, nBufYSize, eBufType,
+                                    nBandCount, panBandMap,
                                     nPixelSpace, nLineSpace, nBandSpace,
                                     psExtraArg);
 }
diff --git a/frmts/raw/rawdataset.h b/frmts/raw/rawdataset.h
index bdd00b8..9a52b73 100644
--- a/frmts/raw/rawdataset.h
+++ b/frmts/raw/rawdataset.h
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: rawdataset.h 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: rawdataset.h 33673 2016-03-07 20:40:54Z goatbar $
  *
  * Project:  Raw Translator
- * Purpose:  Implementation of RawDataset class.  Intented to be subclassed
+ * Purpose:  Implementation of RawDataset class.  Intended to be subclassed
  *           by other raw formats.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -60,6 +60,8 @@ class CPL_DLL RawDataset : public GDALPamDataset
                  RawDataset();
                  ~RawDataset() = 0;
 
+  private:
+    CPL_DISALLOW_COPY_ASSIGN(RawDataset);
 };
 
 /************************************************************************/
@@ -97,14 +99,14 @@ protected:
     GDALColorInterp eInterp;
 
     char           **papszCategoryNames;
-    
+
     int         bOwnsFP;
 
     int         Seek( vsi_l_offset, int );
     size_t      Read( void *, size_t, size_t );
     size_t      Write( void *, size_t, size_t );
 
-    CPLErr      AccessBlock( vsi_l_offset nBlockOff, int nBlockSize,
+    CPLErr      AccessBlock( vsi_l_offset nBlockOff, size_t nBlockSize,
                              void * pData );
     int         IsSignificantNumberOfLinesLoaded( int nLineOff, int nLines );
     void        Initialize();
@@ -134,13 +136,13 @@ public:
                  ~RawRasterBand() /* = 0 */ ;
 
     // should override RasterIO eventually.
-    
+
     virtual CPLErr  IReadBlock( int, int, void * );
     virtual CPLErr  IWriteBlock( int, int, void * );
 
     virtual GDALColorTable *GetColorTable();
     virtual GDALColorInterp GetColorInterpretation();
-    virtual CPLErr SetColorTable( GDALColorTable * ); 
+    virtual CPLErr SetColorTable( GDALColorTable * );
     virtual CPLErr SetColorInterpretation( GDALColorInterp );
 
     virtual char **GetCategoryNames();
@@ -156,19 +158,22 @@ public:
     CPLErr          AccessLine( int iLine );
 
     void            SetAccess( GDALAccess eAccess );
-    
+
     // this is deprecated.
     void	 StoreNoDataValue( double );
 
-    // Query methods for internal data. 
+    // Query methods for internal data.
     vsi_l_offset GetImgOffset() { return nImgOffset; }
     int          GetPixelOffset() { return nPixelOffset; }
     int          GetLineOffset() { return nLineOffset; }
     int          GetNativeOrder() { return bNativeOrder; }
     int          GetIsVSIL() { return bIsVSIL; }
-    FILE        *GetFP() { return (bIsVSIL) ? (FILE*)fpRawL : fpRaw; }
+    FILE        *GetFP() { return (bIsVSIL) ? reinterpret_cast<FILE *>( fpRawL ) : fpRaw; }
     VSILFILE    *GetFPL() { CPLAssert(bIsVSIL); return fpRawL; }
     int          GetOwnsFP() { return bOwnsFP; }
+
+  private:
+    CPL_DISALLOW_COPY_ASSIGN(RawRasterBand);
 };
 
 #endif // GDAL_FRMTS_RAW_RAWDATASET_H_INCLUDED
diff --git a/frmts/raw/roipacdataset.cpp b/frmts/raw/roipacdataset.cpp
index c63d69e..2881231 100644
--- a/frmts/raw/roipacdataset.cpp
+++ b/frmts/raw/roipacdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: roipacdataset.cpp 28974 2015-04-22 17:57:26Z rouault $
+ * $Id: roipacdataset.cpp 33718 2016-03-14 17:19:28Z rouault $
  *
  * Project:  ROI_PAC Raster Reader
  * Purpose:  Implementation of the ROI_PAC raster reader
@@ -27,14 +27,11 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "rawdataset.h"
+#include "gdal_frmts.h"
 #include "ogr_spatialref.h"
+#include "rawdataset.h"
 
-CPL_CVSID("$Id: roipacdataset.cpp 28974 2015-04-22 17:57:26Z rouault $");
-
-CPL_C_START
-void    GDALRegister_ROIPAC(void);
-CPL_C_END
+CPL_CVSID("$Id: roipacdataset.cpp 33718 2016-03-14 17:19:28Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -50,7 +47,7 @@ class ROIPACDataset : public RawDataset
 
     VSILFILE    *fpImage;
     VSILFILE    *fpRsc;
-    
+
     char        *pszRscFilename;
 
     double      adfGeoTransform[6];
@@ -60,7 +57,7 @@ class ROIPACDataset : public RawDataset
   public:
                 ROIPACDataset( void );
                 ~ROIPACDataset( void );
-    
+
     static GDALDataset *Open( GDALOpenInfo *poOpenInfo );
     static int          Identify( GDALOpenInfo *poOpenInfo );
     static GDALDataset *Create( const char *pszFilename,
@@ -102,10 +99,10 @@ static CPLString getRscFilename( GDALOpenInfo *poOpenInfo )
     char **papszSiblingFiles = poOpenInfo->GetSiblingFiles();
     if ( papszSiblingFiles == NULL )
     {
-        osRscFilename = CPLFormFilename( NULL, poOpenInfo->pszFilename, 
+        osRscFilename = CPLFormFilename( NULL, poOpenInfo->pszFilename,
                                         "rsc" );
         VSIStatBufL psRscStatBuf;
-        if ( VSIStatL( osRscFilename, &psRscStatBuf ) != 0 ) 
+        if ( VSIStatL( osRscFilename, &psRscStatBuf ) != 0 )
         {
             osRscFilename = "";
         }
@@ -136,35 +133,41 @@ static CPLString getRscFilename( GDALOpenInfo *poOpenInfo )
 /*                            ROIPACDataset()                           */
 /************************************************************************/
 
-ROIPACDataset::ROIPACDataset( void )
+ROIPACDataset::ROIPACDataset() :
+    fpImage(NULL),
+    fpRsc(NULL),
+    pszRscFilename(NULL),
+    bValidGeoTransform(false),
+    pszProjection(NULL)
 {
-    fpImage = NULL;
-    fpRsc = NULL;
-    pszRscFilename = NULL;
     adfGeoTransform[0] =  0.0;
     adfGeoTransform[1] =  1.0;
     adfGeoTransform[2] =  0.0;
     adfGeoTransform[3] =  0.0;
     adfGeoTransform[4] =  0.0;
     adfGeoTransform[5] =  1.0;
-    pszProjection = NULL;
-    bValidGeoTransform = false;
 }
 
 /************************************************************************/
 /*                            ~ROIPACDataset()                          */
 /************************************************************************/
 
-ROIPACDataset::~ROIPACDataset( void )
+ROIPACDataset::~ROIPACDataset()
 {
     FlushCache();
     if ( fpRsc != NULL )
     {
-        VSIFCloseL( fpRsc );
+        if( VSIFCloseL( fpRsc ) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        }
     }
     if ( fpImage != NULL )
     {
-        VSIFCloseL( fpImage );
+        if( VSIFCloseL( fpImage ) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        }
     }
     CPLFree( pszRscFilename );
     CPLFree( pszProjection );
@@ -212,21 +215,18 @@ GDALDataset *ROIPACDataset::Open( GDALOpenInfo *poOpenInfo )
     char **papszRsc = NULL;
     while ( true )
     {
-        const char *pszLine;
-        char **papszTokens;
-
-        pszLine = CPLReadLineL( fpRsc );
+        const char *pszLine = CPLReadLineL( fpRsc );
         if (pszLine == NULL)
         {
             break;
         }
 
-        papszTokens = CSLTokenizeString2( pszLine, " \t",
-                                          CSLT_STRIPLEADSPACES
-                                            | CSLT_STRIPENDSPACES
-                                            | CSLT_PRESERVEQUOTES
-                                            | CSLT_PRESERVEESCAPES );
-        if ( papszTokens == NULL 
+        char **papszTokens = CSLTokenizeString2( pszLine, " \t",
+                                                 CSLT_STRIPLEADSPACES
+                                                 | CSLT_STRIPENDSPACES
+                                                 | CSLT_PRESERVEQUOTES
+                                                 | CSLT_PRESERVEESCAPES );
+        if ( papszTokens == NULL
              || papszTokens[0] == NULL || papszTokens[1] == NULL )
         {
             CSLDestroy ( papszTokens );
@@ -241,22 +241,20 @@ GDALDataset *ROIPACDataset::Open( GDALOpenInfo *poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Fetch required fields.                                          */
 /* -------------------------------------------------------------------- */
-    int nWidth = 0, nFileLength = 0;
     if ( CSLFetchNameValue( papszRsc, "WIDTH" ) == NULL
         || CSLFetchNameValue( papszRsc, "FILE_LENGTH" ) == NULL )
     {
         CSLDestroy( papszRsc );
-        VSIFCloseL( fpRsc );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fpRsc ));
         return NULL;
     }
-    nWidth = atoi( CSLFetchNameValue( papszRsc, "WIDTH" ) ); 
-    nFileLength = atoi( CSLFetchNameValue( papszRsc, "FILE_LENGTH" ) );
+    const int nWidth = atoi( CSLFetchNameValue( papszRsc, "WIDTH" ) );
+    const int nFileLength = atoi( CSLFetchNameValue( papszRsc, "FILE_LENGTH" ) );
 
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    ROIPACDataset *poDS;
-    poDS = new ROIPACDataset();
+    ROIPACDataset *poDS = new ROIPACDataset();
     poDS->nRasterXSize = nWidth;
     poDS->nRasterYSize = nFileLength;
     poDS->eAccess = poOpenInfo->eAccess;
@@ -324,10 +322,10 @@ GDALDataset *ROIPACDataset::Open( GDALOpenInfo *poOpenInfo )
         nBands = 2;
         eInterleave = PIXEL;
     }
-    else if ( strcmp( pszExtension, "cor" ) == 0 
-                || strcmp( pszExtension, "hgt" ) == 0 
-                || strcmp( pszExtension, "unw" ) == 0 
-                || strcmp( pszExtension, "msk" ) == 0 
+    else if ( strcmp( pszExtension, "cor" ) == 0
+                || strcmp( pszExtension, "hgt" ) == 0
+                || strcmp( pszExtension, "unw" ) == 0
+                || strcmp( pszExtension, "msk" ) == 0
                 || strcmp( pszExtension, "trans" ) == 0 )
     {
         eDataType = GDT_Float32;
@@ -345,6 +343,7 @@ GDALDataset *ROIPACDataset::Open( GDALOpenInfo *poOpenInfo )
         CSLDestroy( papszRsc );
         return NULL;
     }
+
     int nPixelOffset;
     int nLineOffset;
     int nBandOffset;
@@ -380,13 +379,13 @@ GDALDataset *ROIPACDataset::Open( GDALOpenInfo *poOpenInfo )
     {
         poDS->adfGeoTransform[0] = CPLAtof( CSLFetchNameValue( papszRsc,
                                                                "X_FIRST" ) );
-        poDS->adfGeoTransform[1] = CPLAtof( CSLFetchNameValue( papszRsc, 
+        poDS->adfGeoTransform[1] = CPLAtof( CSLFetchNameValue( papszRsc,
                                                                "X_STEP" ) );
         poDS->adfGeoTransform[2] = 0.0;
-        poDS->adfGeoTransform[3] = CPLAtof( CSLFetchNameValue( papszRsc, 
+        poDS->adfGeoTransform[3] = CPLAtof( CSLFetchNameValue( papszRsc,
                                                                "Y_FIRST" ) );
         poDS->adfGeoTransform[4] = 0.0;
-        poDS->adfGeoTransform[5] = CPLAtof( CSLFetchNameValue( papszRsc, 
+        poDS->adfGeoTransform[5] = CPLAtof( CSLFetchNameValue( papszRsc,
                                                                "Y_STEP" ) );
         poDS->bValidGeoTransform = true;
     }
@@ -404,22 +403,21 @@ GDALDataset *ROIPACDataset::Open( GDALOpenInfo *poOpenInfo )
         {
             if ( CSLFetchNameValue( papszRsc, "DATUM" ) != NULL )
             {
-                oSRS.SetWellKnownGeogCS( CSLFetchNameValue( papszRsc, 
+                oSRS.SetWellKnownGeogCS( CSLFetchNameValue( papszRsc,
                                                             "DATUM" ) );
             }
             else {
                 oSRS.SetWellKnownGeogCS( "WGS84" );
             }
         }
-        else if( strncmp( CSLFetchNameValue( papszRsc, "PROJECTION" ),
-                          "UTM", 3 ) == 0 )
+        else if( STARTS_WITH(CSLFetchNameValue( papszRsc, "PROJECTION" ), "UTM") )
         {
-            const char *pszZone = CSLFetchNameValue( papszRsc, 
+            const char *pszZone = CSLFetchNameValue( papszRsc,
                                                      "PROJECTION" ) + 3;
             oSRS.SetUTM( atoi( pszZone ), TRUE ); /* FIXME: north/south? */
             if ( CSLFetchNameValue( papszRsc, "DATUM" ) != NULL )
             {
-                oSRS.SetWellKnownGeogCS( CSLFetchNameValue( papszRsc, 
+                oSRS.SetWellKnownGeogCS( CSLFetchNameValue( papszRsc,
                                                             "DATUM" ) );
             }
             else {
@@ -428,6 +426,26 @@ GDALDataset *ROIPACDataset::Open( GDALOpenInfo *poOpenInfo )
         }
         oSRS.exportToWkt( &poDS->pszProjection );
     }
+    if ( CSLFetchNameValue( papszRsc, "Z_OFFSET" ) != NULL )
+    {
+        const double dfOffset
+            = strtod( CSLFetchNameValue( papszRsc, "Z_OFFSET" ), NULL);
+        for (int b = 1; b <= nBands; b++)
+        {
+            GDALRasterBand *poBand = poDS->GetRasterBand(b);
+            poBand->SetOffset( dfOffset );
+        }
+    }
+    if ( CSLFetchNameValue( papszRsc, "Z_SCALE" ) != NULL )
+    {
+        const double dfScale
+            = strtod( CSLFetchNameValue( papszRsc, "Z_SCALE" ), NULL);
+        for (int b = 1; b <= nBands; b++)
+        {
+            GDALRasterBand *poBand = poDS->GetRasterBand(b);
+            poBand->SetScale( dfScale );
+        }
+    }
 
 
 /* -------------------------------------------------------------------- */
@@ -435,19 +453,20 @@ GDALDataset *ROIPACDataset::Open( GDALOpenInfo *poOpenInfo )
 /* -------------------------------------------------------------------- */
     for (int i = 0; i < CSLCount( papszRsc ); i++)
     {
-        char **papszTokens;
-        papszTokens = CSLTokenizeString2( papszRsc[i],
-                                          "=",
-                                          CSLT_STRIPLEADSPACES
-                                            | CSLT_STRIPENDSPACES);
+        char **papszTokens = CSLTokenizeString2( papszRsc[i],
+                                                 "=",
+                                                 CSLT_STRIPLEADSPACES
+                                                 | CSLT_STRIPENDSPACES);
         if ( strcmp( papszTokens[0], "WIDTH" ) == 0
               || strcmp( papszTokens[0], "FILE_LENGTH" ) == 0
               || strcmp( papszTokens[0], "X_FIRST" ) == 0
               || strcmp( papszTokens[0], "X_STEP" ) == 0
               || strcmp( papszTokens[0], "Y_FIRST" ) == 0
               || strcmp( papszTokens[0], "Y_STEP" ) == 0
-              || strcmp( papszTokens[0], "PROJECTION" ) == 0 
-              || strcmp( papszTokens[0], "DATUM" ) == 0 )
+              || strcmp( papszTokens[0], "PROJECTION" ) == 0
+              || strcmp( papszTokens[0], "DATUM" ) == 0
+              || strcmp( papszTokens[0], "Z_OFFSET" ) == 0
+              || strcmp( papszTokens[0], "Z_SCALE" ) == 0 )
         {
             CSLDestroy( papszTokens );
             continue;
@@ -465,7 +484,7 @@ GDALDataset *ROIPACDataset::Open( GDALOpenInfo *poOpenInfo )
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
     poDS->SetDescription( poOpenInfo->pszFilename );
-    poDS->TryLoadXML(); 
+    poDS->TryLoadXML();
 
 /* -------------------------------------------------------------------- */
 /*      Check for overviews.                                            */
@@ -525,7 +544,7 @@ int ROIPACDataset::Identify( GDALOpenInfo *poOpenInfo )
 GDALDataset *ROIPACDataset::Create( const char *pszFilename,
                                     int nXSize, int nYSize, int nBands,
                                     GDALDataType eType,
-                                    char **papszOptions )
+                                    CPL_UNUSED char **papszOptions )
 {
 /* -------------------------------------------------------------------- */
 /*      Verify input options.                                           */
@@ -554,10 +573,10 @@ GDALDataset *ROIPACDataset::Create( const char *pszFilename,
             return NULL;
         }
     }
-    else if ( strcmp( pszExtension, "cor" ) == 0 
-                || strcmp( pszExtension, "hgt" ) == 0 
-                || strcmp( pszExtension, "unw" ) == 0 
-                || strcmp( pszExtension, "msk" ) == 0 
+    else if ( strcmp( pszExtension, "cor" ) == 0
+                || strcmp( pszExtension, "hgt" ) == 0
+                || strcmp( pszExtension, "unw" ) == 0
+                || strcmp( pszExtension, "msk" ) == 0
                 || strcmp( pszExtension, "trans" ) == 0 )
     {
         if ( nBands != 2 || eType != GDT_Float32 )
@@ -590,8 +609,7 @@ GDALDataset *ROIPACDataset::Create( const char *pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Try to create the file.                                         */
 /* -------------------------------------------------------------------- */
-    VSILFILE *fp;
-    fp = VSIFOpenL( pszFilename, "wb" );
+    VSILFILE *fp = VSIFOpenL( pszFilename, "wb" );
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
@@ -604,14 +622,14 @@ GDALDataset *ROIPACDataset::Create( const char *pszFilename,
 /*      Just write out a couple of bytes to establish the binary        */
 /*      file, and then close it.                                        */
 /* -------------------------------------------------------------------- */
-    VSIFWriteL( (void *) "\0\0", 2, 1, fp );
-    VSIFCloseL( fp );
+    CPL_IGNORE_RET_VAL(VSIFWriteL( reinterpret_cast<void *>( const_cast<char *>( "\0\0" ) ),
+                2, 1, fp ));
+    CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
 
 /* -------------------------------------------------------------------- */
 /*      Open the RSC file.                                              */
 /* -------------------------------------------------------------------- */
-    const char  *pszRSCFilename;
-    pszRSCFilename = CPLFormFilename( NULL, pszFilename, "rsc" );
+    const char *pszRSCFilename = CPLFormFilename( NULL, pszFilename, "rsc" );
     fp = VSIFOpenL( pszRSCFilename, "wt" );
     if( fp == NULL )
     {
@@ -624,11 +642,12 @@ GDALDataset *ROIPACDataset::Create( const char *pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Write out the header.                                           */
 /* -------------------------------------------------------------------- */
-    VSIFPrintfL( fp, "%-40s %d\n", "WIDTH", nXSize );
-    VSIFPrintfL( fp, "%-40s %d\n", "FILE_LENGTH", nYSize );
-    VSIFCloseL( fp );
+    CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "%-40s %d\n", "WIDTH", nXSize ));
+    CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "%-40s %d\n", "FILE_LENGTH", nYSize ));
+    CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
 
-    return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
+    return reinterpret_cast<GDALDataset *>(
+        GDALOpen( pszFilename, GA_Update ) );
 }
 
 /************************************************************************/
@@ -647,17 +666,17 @@ void ROIPACDataset::FlushCache( void )
     // If opening an existing file in Update mode (i.e. "r+") we need to make
     // sure any existing content is cleared, otherwise the file may contain
     // trailing content from the previous write.
-    VSIFTruncateL( fpRsc, 0 );
+    CPL_IGNORE_RET_VAL(VSIFTruncateL( fpRsc, 0 ));
 
-    VSIFSeekL( fpRsc, 0, SEEK_SET );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( fpRsc, 0, SEEK_SET ));
 /* -------------------------------------------------------------------- */
 /*      Rewrite out the header.                                         */
 /* -------------------------------------------------------------------- */
 /* -------------------------------------------------------------------- */
 /*      Raster dimensions.                                              */
 /* -------------------------------------------------------------------- */
-    VSIFPrintfL( fpRsc, "%-40s %d\n", "WIDTH", nRasterXSize );
-    VSIFPrintfL( fpRsc, "%-40s %d\n", "FILE_LENGTH", nRasterYSize );
+    CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %d\n", "WIDTH", nRasterXSize ));
+    CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %d\n", "FILE_LENGTH", nRasterYSize ));
 
 /* -------------------------------------------------------------------- */
 /*      Georeferencing.                                                 */
@@ -669,16 +688,14 @@ void ROIPACDataset::FlushCache( void )
         if( oSRS.importFromWkt( &pszProjectionTmp ) == OGRERR_NONE )
         {
             int bNorth;
-            int iUTMZone;
-
-            iUTMZone = oSRS.GetUTMZone( &bNorth );
+            int iUTMZone = oSRS.GetUTMZone( &bNorth );
             if ( iUTMZone != 0 )
             {
-                VSIFPrintfL( fpRsc, "%-40s %s%d\n", "PROJECTION", "UTM", iUTMZone );
+                CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %s%d\n", "PROJECTION", "UTM", iUTMZone ));
             }
             else if ( oSRS.IsGeographic() )
             {
-                VSIFPrintfL( fpRsc, "%-40s %s\n", "PROJECTION", "LL" );
+                CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %s\n", "PROJECTION", "LL" ));
             }
             else
             {
@@ -691,7 +708,7 @@ void ROIPACDataset::FlushCache( void )
             {
                 if ( strcmp( oSRS.GetAttrValue( "DATUM" ), "WGS_1984" ) == 0 )
                 {
-                    VSIFPrintfL( fpRsc, "%-40s %s\n", "DATUM", "WGS84" );
+                    CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %s\n", "DATUM", "WGS84" ));
                 }
                 else
                 {
@@ -699,13 +716,13 @@ void ROIPACDataset::FlushCache( void )
                               "Datum \"%s\" probably not supported in the "
                                   "ROI_PAC format, saving it anyway",
                                   oSRS.GetAttrValue( "DATUM" ) );
-                    VSIFPrintfL( fpRsc, "%-40s %s\n", "DATUM", oSRS.GetAttrValue( "DATUM" ) );
+                    CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %s\n", "DATUM", oSRS.GetAttrValue( "DATUM" ) ));
                 }
             }
             if ( oSRS.GetAttrValue( "UNIT" ) != NULL )
             {
-                VSIFPrintfL( fpRsc, "%-40s %s\n", "X_UNIT", oSRS.GetAttrValue( "UNIT" ) );
-                VSIFPrintfL( fpRsc, "%-40s %s\n", "Y_UNIT", oSRS.GetAttrValue( "UNIT" ) );
+                CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %s\n", "X_UNIT", oSRS.GetAttrValue( "UNIT" ) ));
+                CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %s\n", "Y_UNIT", oSRS.GetAttrValue( "UNIT" ) ));
             }
         }
     }
@@ -719,10 +736,12 @@ void ROIPACDataset::FlushCache( void )
         }
         else
         {
-            VSIFPrintfL( fpRsc, "%-40s %.16g\n", "X_FIRST", adfGeoTransform[0] );
-            VSIFPrintfL( fpRsc, "%-40s %.16g\n", "X_STEP", adfGeoTransform[1] );
-            VSIFPrintfL( fpRsc, "%-40s %.16g\n", "Y_FIRST", adfGeoTransform[3] );
-            VSIFPrintfL( fpRsc, "%-40s %.16g\n", "Y_STEP", adfGeoTransform[5] );
+            CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %.16g\n", "X_FIRST", adfGeoTransform[0] ));
+            CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %.16g\n", "X_STEP", adfGeoTransform[1] ));
+            CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %.16g\n", "Y_FIRST", adfGeoTransform[3] ));
+            CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %.16g\n", "Y_STEP", adfGeoTransform[5] ));
+            CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %.16g\n", "Z_OFFSET", band->GetOffset(NULL) ));
+            CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %.16g\n", "Z_SCALE", band->GetScale(NULL) ));
         }
     }
 
@@ -731,16 +750,14 @@ void ROIPACDataset::FlushCache( void )
 /* -------------------------------------------------------------------- */
     char** papszROIPACMetadata = GetMetadata( "ROI_PAC" );
     for (int i = 0; i < CSLCount( papszROIPACMetadata ); i++)
-    {   
-        char **papszTokens;
-
+    {
         /* Get the tokens from the metadata item */
-        papszTokens = CSLTokenizeString2( papszROIPACMetadata[i], 
-                                          "=", 
-                                          CSLT_STRIPLEADSPACES 
-                                            | CSLT_STRIPENDSPACES);
+        char **papszTokens = CSLTokenizeString2( papszROIPACMetadata[i],
+                                                 "=",
+                                                 CSLT_STRIPLEADSPACES
+                                                 | CSLT_STRIPENDSPACES);
         if ( CSLCount( papszTokens ) != 2 )
-        {   
+        {
             CPLDebug("ROI_PAC",
                      "Line of header file could not be split at = into two elements: %s",
                      papszROIPACMetadata[i]);
@@ -752,11 +769,11 @@ void ROIPACDataset::FlushCache( void )
          * written out elsewhere in this routine */
         if ( strcmp( papszTokens[0], "WIDTH" ) == 0
               || strcmp( papszTokens[0], "FILE_LENGTH" ) == 0 )
-        {   
+        {
             CSLDestroy( papszTokens );
             continue;
         }
-        VSIFPrintfL( fpRsc, "%-40s %s\n", papszTokens[0], papszTokens[1] );
+        CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %s\n", papszTokens[0], papszTokens[1] ));
         CSLDestroy( papszTokens );
     }
 }
@@ -809,12 +826,10 @@ CPLErr ROIPACDataset::SetProjection( const char *pszNewProjection )
 
 char **ROIPACDataset::GetFileList()
 {
-    char **papszFileList = NULL;
+    // Main data file, etc.
+    char **papszFileList = RawDataset::GetFileList();
 
-    // Main data file, etc.  
-    papszFileList = RawDataset::GetFileList();
-
-    // RSC file. 
+    // RSC file.
     papszFileList = CSLAddString( papszFileList, pszRscFilename );
 
     return papszFileList;
@@ -824,13 +839,13 @@ char **ROIPACDataset::GetFileList()
 /*                         ROIPACRasterBand()                           */
 /************************************************************************/
 
-ROIPACRasterBand::ROIPACRasterBand( GDALDataset *poDS, int nBand, void *fpRaw,
-                                    vsi_l_offset nImgOffset, int nPixelOffset,
-                                    int nLineOffset,
-                                    GDALDataType eDataType, int bNativeOrder,
-                                    int bIsVSIL, int bOwnsFP ) :
-        RawRasterBand(poDS, nBand, fpRaw, nImgOffset, nPixelOffset,
-                      nLineOffset, eDataType, bNativeOrder, bIsVSIL, bOwnsFP)
+ROIPACRasterBand::ROIPACRasterBand( GDALDataset *poDSIn, int nBandIn, void *fpRawIn,
+                                    vsi_l_offset nImgOffsetIn, int nPixelOffsetIn,
+                                    int nLineOffsetIn,
+                                    GDALDataType eDataTypeIn, int bNativeOrderIn,
+                                    int bIsVSILIn, int bOwnsFPIn ) :
+        RawRasterBand(poDSIn, nBandIn, fpRawIn, nImgOffsetIn, nPixelOffsetIn,
+                      nLineOffsetIn, eDataTypeIn, bNativeOrderIn, bIsVSILIn, bOwnsFPIn)
 {
 }
 
@@ -838,31 +853,26 @@ ROIPACRasterBand::ROIPACRasterBand( GDALDataset *poDS, int nBand, void *fpRaw,
 /*                        GDALRegister_ROIPAC()                         */
 /************************************************************************/
 
-void GDALRegister_ROIPAC( void )
+void GDALRegister_ROIPAC()
 {
-    GDALDriver  *poDriver;
+    if( !GDAL_CHECK_VERSION( "ROI_PAC" ) )
+        return;
 
-    if (!GDAL_CHECK_VERSION("ROI_PAC"))
-    {
+    if( GDALGetDriverByName( "ROI_PAC" ) != NULL )
         return;
-    }
 
-    if ( GDALGetDriverByName( "ROI_PAC" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "ROI_PAC" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "ROI_PAC raster" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#ROI_PAC" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->pfnOpen = ROIPACDataset::Open;
-        poDriver->pfnIdentify = ROIPACDataset::Identify;
-        poDriver->pfnCreate = ROIPACDataset::Create;
+    poDriver->SetDescription( "ROI_PAC" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "ROI_PAC raster" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_various.html#ROI_PAC" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    poDriver->pfnOpen = ROIPACDataset::Open;
+    poDriver->pfnIdentify = ROIPACDataset::Identify;
+    poDriver->pfnCreate = ROIPACDataset::Create;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/raw/snodasdataset.cpp b/frmts/raw/snodasdataset.cpp
index 194196f..302032e 100644
--- a/frmts/raw/snodasdataset.cpp
+++ b/frmts/raw/snodasdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: snodasdataset.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: snodasdataset.cpp 32883 2016-01-09 18:24:40Z rouault $
  *
  * Project:  SNODAS driver
  * Purpose:  Implementation of SNODASDataset
@@ -27,18 +27,15 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "rawdataset.h"
-#include "ogr_srs_api.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "ogr_srs_api.h"
+#include "rawdataset.h"
 
-CPL_CVSID("$Id: snodasdataset.cpp 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: snodasdataset.cpp 32883 2016-01-09 18:24:40Z rouault $");
 
 // g++ -g -Wall -fPIC frmts/raw/snodasdataset.cpp -shared -o gdal_SNODAS.so -Iport -Igcore -Ifrmts/raw -Iogr -L. -lgdal
 
-CPL_C_START
-void    GDALRegister_SNODAS(void);
-CPL_C_END
-
 /************************************************************************/
 /* ==================================================================== */
 /*                            SNODASDataset                             */
@@ -96,9 +93,9 @@ class SNODASRasterBand : public RawRasterBand
 /*                         SNODASRasterBand()                           */
 /************************************************************************/
 
-SNODASRasterBand::SNODASRasterBand(VSILFILE* fpRaw,
+SNODASRasterBand::SNODASRasterBand(VSILFILE* fpRawIn,
                                    int nXSize, int nYSize) :
-    RawRasterBand( fpRaw, 0, 2,
+    RawRasterBand( fpRawIn, 0, 2,
                    nXSize * 2, GDT_Int16,
                    !CPL_IS_LSB, nXSize, nYSize, TRUE, TRUE)
 {
@@ -110,13 +107,14 @@ SNODASRasterBand::SNODASRasterBand(VSILFILE* fpRaw,
 
 double SNODASRasterBand::GetNoDataValue( int *pbSuccess )
 {
-    SNODASDataset* poGDS = (SNODASDataset*) poDS;
+    SNODASDataset* poGDS = reinterpret_cast<SNODASDataset *>( poDS );
     if (pbSuccess)
         *pbSuccess = poGDS->bHasNoData;
+
     if (poGDS->bHasNoData)
         return poGDS->dfNoData;
-    else
-        return RawRasterBand::GetNoDataValue(pbSuccess);
+
+    return RawRasterBand::GetNoDataValue(pbSuccess);
 }
 
 /************************************************************************/
@@ -125,13 +123,14 @@ double SNODASRasterBand::GetNoDataValue( int *pbSuccess )
 
 double SNODASRasterBand::GetMinimum( int *pbSuccess )
 {
-    SNODASDataset* poGDS = (SNODASDataset*) poDS;
+    SNODASDataset* poGDS = reinterpret_cast<SNODASDataset *>( poDS );
     if (pbSuccess)
         *pbSuccess = poGDS->bHasMin;
+
     if (poGDS->bHasMin)
         return poGDS->dfMin;
-    else
-        return RawRasterBand::GetMinimum(pbSuccess);
+
+    return RawRasterBand::GetMinimum(pbSuccess);
 }
 
 /************************************************************************/
@@ -140,13 +139,14 @@ double SNODASRasterBand::GetMinimum( int *pbSuccess )
 
 double SNODASRasterBand::GetMaximum( int *pbSuccess )
 {
-    SNODASDataset* poGDS = (SNODASDataset*) poDS;
+    SNODASDataset* poGDS = reinterpret_cast<SNODASDataset *>( poDS );
     if (pbSuccess)
         *pbSuccess = poGDS->bHasMax;
+
     if (poGDS->bHasMax)
         return poGDS->dfMax;
-    else
-        return RawRasterBand::GetMaximum(pbSuccess);
+
+    return RawRasterBand::GetMaximum(pbSuccess);
 }
 
 /************************************************************************/
@@ -159,21 +159,21 @@ double SNODASRasterBand::GetMaximum( int *pbSuccess )
 /*                           SNODASDataset()                            */
 /************************************************************************/
 
-SNODASDataset::SNODASDataset()
+SNODASDataset::SNODASDataset() :
+    bGotTransform(FALSE),
+    bHasNoData(FALSE),
+    dfNoData(0.0),
+    bHasMin(FALSE),
+    dfMin(0.0),
+    bHasMax(FALSE),
+    dfMax(0.0)
 {
-    bGotTransform = FALSE;
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
-    bHasNoData = FALSE;
-    dfNoData = 0.0;
-    bHasMin = FALSE;
-    dfMin = 0.0;
-    bHasMax = FALSE;
-    dfMax = 0.0;
 }
 
 /************************************************************************/
@@ -208,10 +208,9 @@ CPLErr SNODASDataset::GetGeoTransform( double * padfTransform )
         memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
         return CE_None;
     }
-    else
-    {
-        return GDALPamDataset::GetGeoTransform( padfTransform );
-    }
+
+    return GDALPamDataset::GetGeoTransform( padfTransform );
+
 }
 
 
@@ -238,10 +237,7 @@ int SNODASDataset::Identify( GDALOpenInfo * poOpenInfo )
     if (poOpenInfo->nHeaderBytes == 0)
         return FALSE;
 
-    return EQUALN((const char*)poOpenInfo->pabyHeader,
-                  "Format version: NOHRSC GIS/RS raster file v1.1",
-                  strlen("Format version: NOHRSC GIS/RS raster file v1.1"));
-}
+    return STARTS_WITH_CI((const char*)poOpenInfo->pabyHeader, "Format version: NOHRSC GIS/RS raster file v1.1");}
 
 /************************************************************************/
 /*                                Open()                                */
@@ -253,34 +249,36 @@ GDALDataset *SNODASDataset::Open( GDALOpenInfo * poOpenInfo )
     if( !Identify(poOpenInfo) )
         return NULL;
 
-    VSILFILE    *fp;
-
-    fp = VSIFOpenL( poOpenInfo->pszFilename, "r" );
-
+    VSILFILE *fp = VSIFOpenL( poOpenInfo->pszFilename, "r" );
     if( fp == NULL )
     {
         return NULL;
     }
 
-    const char *    pszLine;
     int             nRows = -1, nCols = -1;
     CPLString       osDataFilename;
-    int             bIsInteger = FALSE, bIs2Bytes = FALSE;
+    bool bIsInteger = false;
+    bool bIs2Bytes = false;
     double          dfNoData = 0;
-    int             bHasNoData = FALSE;
+    bool bHasNoData = false;
     double          dfMin = 0;
-    int             bHasMin = FALSE;
+    bool bHasMin = false;
     double          dfMax = 0;
-    int             bHasMax = FALSE;
+    bool bHasMax = false;
     double          dfMinX = 0.0, dfMinY = 0.0, dfMaxX = 0.0, dfMaxY = 0.0;
-    int             bHasMinX = FALSE, bHasMinY = FALSE, bHasMaxX = FALSE, bHasMaxY = FALSE;
-    int             bNotProjected = FALSE, bIsWGS84 = FALSE;
+    bool bHasMinX = false;
+    bool bHasMinY = false;
+    bool bHasMaxX = false;
+    bool bHasMaxY = false;
+    bool bNotProjected = false;
+    bool bIsWGS84 = false;
     CPLString       osDescription, osDataUnits;
     int             nStartYear = -1, nStartMonth = -1, nStartDay = -1,
                     nStartHour = -1, nStartMinute = -1, nStartSecond = -1;
     int             nStopYear = -1, nStopMonth = -1, nStopDay = -1,
                     nStopHour = -1, nStopMinute = -1, nStopSecond = -1;
 
+    const char *pszLine;
     while( (pszLine = CPLReadLine2L( fp, 256, NULL )) != NULL )
     {
         char** papszTokens = CSLTokenizeStringComplex( pszLine, ":", TRUE, FALSE );
@@ -357,44 +355,44 @@ GDALDataset *SNODASDataset::Open( GDALOpenInfo * poOpenInfo )
         }
         else if( EQUAL(papszTokens[0],"No data value"))
         {
-            bHasNoData = TRUE;
+            bHasNoData = true;
             dfNoData = CPLAtofM(papszTokens[1]);
         }
         else if( EQUAL(papszTokens[0],"Minimum data value"))
         {
-            bHasMin = TRUE;
+            bHasMin = true;
             dfMin = CPLAtofM(papszTokens[1]);
         }
         else if( EQUAL(papszTokens[0],"Maximum data value"))
         {
-            bHasMax = TRUE;
+            bHasMax = true;
             dfMax = CPLAtofM(papszTokens[1]);
         }
         else if( EQUAL(papszTokens[0],"Minimum x-axis coordinate") )
         {
-            bHasMinX = TRUE;
+            bHasMinX = true;
             dfMinX = CPLAtofM(papszTokens[1]);
         }
         else if( EQUAL(papszTokens[0],"Minimum y-axis coordinate") )
         {
-            bHasMinY = TRUE;
+            bHasMinY = true;
             dfMinY = CPLAtofM(papszTokens[1]);
         }
         else if( EQUAL(papszTokens[0],"Maximum x-axis coordinate") )
         {
-            bHasMaxX = TRUE;
+            bHasMaxX = true;
             dfMaxX = CPLAtofM(papszTokens[1]);
         }
         else if( EQUAL(papszTokens[0],"Maximum y-axis coordinate") )
         {
-            bHasMaxY = TRUE;
+            bHasMaxY = true;
             dfMaxY = CPLAtofM(papszTokens[1]);
         }
 
         CSLDestroy( papszTokens );
     }
 
-    VSIFCloseL( fp );
+    CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
 
 /* -------------------------------------------------------------------- */
 /*      Did we get the required keywords?  If not we return with        */
@@ -427,9 +425,7 @@ GDALDataset *SNODASDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    SNODASDataset     *poDS;
-
-    poDS = new SNODASDataset();
+    SNODASDataset *poDS = new SNODASDataset();
 
     poDS->nRasterXSize = nCols;
     poDS->nRasterYSize = nRows;
@@ -483,7 +479,7 @@ GDALDataset *SNODASDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Check for overviews.                                            */
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
-   
+
     return( poDS );
 }
 
@@ -494,24 +490,21 @@ GDALDataset *SNODASDataset::Open( GDALOpenInfo * poOpenInfo )
 void GDALRegister_SNODAS()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "SNODAS" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "SNODAS" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "SNODAS" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Snow Data Assimilation System" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "frmt_various.html#SNODAS" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "hdr" );
+    poDriver->SetDescription( "SNODAS" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Snow Data Assimilation System" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#SNODAS" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "hdr" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-        poDriver->pfnOpen = SNODASDataset::Open;
-        poDriver->pfnIdentify = SNODASDataset::Identify;
+    poDriver->pfnOpen = SNODASDataset::Open;
+    poDriver->pfnIdentify = SNODASDataset::Identify;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/rik/frmt_rik.html b/frmts/rik/frmt_rik.html
index ce9172a..57227e5 100644
--- a/frmts/rik/frmt_rik.html
+++ b/frmts/rik/frmt_rik.html
@@ -1,5 +1,6 @@
 <html>
 <head>
+<meta http-equiv=Content-Type content="text/html; charset=utf-8">
 <title>RIK -- Swedish Grid Maps</title>
 </head>
 
@@ -8,7 +9,7 @@
 <h1>RIK -- Swedish Grid Maps</h1>
 
 Supported by GDAL for read access. This format is used in maps issued by the
-swedish organization Lantm�teriet. Supports versions 1, 2 and 3 of the RIK
+swedish organization Lantmäteriet. Supports versions 1, 2 and 3 of the RIK
 format, but only 8 bits per pixel.<p>
 
 This driver is based on the work done in the
diff --git a/frmts/rik/rikdataset.cpp b/frmts/rik/rikdataset.cpp
index b0d0817..177674f 100644
--- a/frmts/rik/rikdataset.cpp
+++ b/frmts/rik/rikdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rikdataset.cpp 29720 2015-08-21 20:57:27Z rouault $
+ * $Id: rikdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  RIK Reader
  * Purpose:  All code for RIK Reader
@@ -28,15 +28,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include <float.h>
+#include <cfloat>
 #include <zlib.h>
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: rikdataset.cpp 29720 2015-08-21 20:57:27Z rouault $");
-
-CPL_C_START
-void	GDALRegister_RIK(void);
-CPL_C_END
+CPL_CVSID("$Id: rikdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 #define RIK_HEADER_DEBUG 0
 #define RIK_CLEAR_DEBUG 0
@@ -169,16 +166,16 @@ class RIKRasterBand : public GDALPamRasterBand
 /*                           RIKRasterBand()                            */
 /************************************************************************/
 
-RIKRasterBand::RIKRasterBand( RIKDataset *poDS, int nBand )
+RIKRasterBand::RIKRasterBand( RIKDataset *poDSIn, int nBandIn )
 
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
     eDataType = GDT_Byte;
 
-    nBlockXSize = poDS->nBlockXSize;
-    nBlockYSize = poDS->nBlockYSize;
+    nBlockXSize = poDSIn->nBlockXSize;
+    nBlockYSize = poDSIn->nBlockYSize;
 }
 
 /************************************************************************/
@@ -206,9 +203,7 @@ static int GetNextLZWCode( int codeBits,
 
     while( bitsLeftToGo > 0 )
     {
-        int tmp;
-
-        tmp = blockData[filePos];
+        int tmp = blockData[filePos];
         tmp = tmp >> bitsTaken;
 
         if( bitsLeftToGo < 8 )
@@ -248,7 +243,8 @@ static void OutputPixel( GByte pixel,
 
 {
     if( imagePos < imageWidth && imageLine >= 0)
-        ((GByte *) image)[imagePos + imageLine * imageWidth] = pixel;
+      reinterpret_cast<GByte *>( image )[imagePos + imageLine * imageWidth]
+          = pixel;
 
     imagePos++;
 
@@ -278,18 +274,13 @@ CPLErr RIKRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                   void * pImage )
 
 {
-    RIKDataset *poRDS = (RIKDataset *) poDS;
-    GByte *blockData;
-    GUInt32 blocks;
-    GUInt32 nBlockIndex;
-    GUInt32 nBlockOffset;
-    GUInt32 nBlockSize;
-
-    blocks = poRDS->nHorBlocks * poRDS->nVertBlocks;
-    nBlockIndex = nBlockXOff + nBlockYOff * poRDS->nHorBlocks;
-    nBlockOffset = poRDS->pOffsets[nBlockIndex];
-
-    nBlockSize = poRDS->nFileSize;
+    RIKDataset *poRDS = reinterpret_cast<RIKDataset *>( poDS );
+
+    const GUInt32 blocks = poRDS->nHorBlocks * poRDS->nVertBlocks;
+    const GUInt32 nBlockIndex = nBlockXOff + nBlockYOff * poRDS->nHorBlocks;
+    const GUInt32 nBlockOffset = poRDS->pOffsets[nBlockIndex];
+
+    GUInt32 nBlockSize = poRDS->nFileSize;
     for( GUInt32 bi = nBlockIndex + 1; bi < blocks; bi++ )
     {
         if( poRDS->pOffsets[bi] )
@@ -311,7 +302,7 @@ CPLErr RIKRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         )
     {
         for( GUInt32 i = 0; i < pixels; i++ )
-        ((GByte *) pImage)[i] = 0;
+            reinterpret_cast<GByte *>( pImage )[i] = 0;
         return CE_None;
     }
 
@@ -323,32 +314,40 @@ CPLErr RIKRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
     if( poRDS->options == 0x00 || poRDS->options == 0x40 )
     {
-        VSIFReadL( pImage, 1, nBlockSize, poRDS->fp );
+        VSIFReadL( pImage, 1, nBlockXSize * nBlockYSize, poRDS->fp );
         return CE_None;
     }
 
     // Read block to memory
-    blockData = (GByte *) CPLMalloc(nBlockSize);
-    VSIFReadL( blockData, 1, nBlockSize, poRDS->fp );
-
-    GUInt32 filePos = 0;
-    GUInt32 imagePos = 0;
+    GByte *blockData = reinterpret_cast<GByte *>( VSI_MALLOC_VERBOSE(nBlockSize) );
+    if( blockData == NULL )
+        return CE_Failure;
+    if( VSIFReadL( blockData, 1, nBlockSize, poRDS->fp ) != nBlockSize )
+    {
+        VSIFree(blockData);
+        return CE_Failure;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Read RLE block.                                                 */
 /* -------------------------------------------------------------------- */
+    GUInt32 filePos = 0;
+    GUInt32 imagePos = 0;
 
     if( poRDS->options == 0x01 ||
-        poRDS->options == 0x41 ) do
+        poRDS->options == 0x41 )
     {
-        GByte count = blockData[filePos++];
-        GByte color = blockData[filePos++];
-
-        for (GByte i = 0; i <= count; i++)
+        while( filePos+1 < nBlockSize && imagePos < pixels )
         {
-            ((GByte *) pImage)[imagePos++] = color;
+            GByte count = blockData[filePos++];
+            GByte color = blockData[filePos++];
+
+            for (GByte i = 0; imagePos < pixels && i <= count; i++)
+            {
+                reinterpret_cast<GByte *>( pImage )[imagePos++] = color;
+            }
         }
-    } while( filePos < nBlockSize && imagePos < pixels );
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Read LZW block.                                                 */
@@ -358,6 +357,14 @@ CPLErr RIKRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     {
         const bool LZW_HAS_CLEAR_CODE = !!(blockData[4] & 0x80);
         const int LZW_MAX_BITS = blockData[4] & 0x1f; // Max 13
+        if( LZW_MAX_BITS > 13 )
+        {
+            CPLFree( blockData );
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "RIK decompression failed. "
+                      "Invalid LZW_MAX_BITS." );
+            return CE_Failure;
+        }
         const int LZW_BITS_PER_PIXEL = 8;
         const int LZW_OFFSET = 5;
 
@@ -376,11 +383,9 @@ CPLErr RIKRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         int prefix[8192];      // only need LZW_CODES for size.
         GByte character[8192]; // only need LZW_CODES for size.
 
-        int i;
-
-        for( i = 0; i < LZW_CLEAR; i++ )
-            character[i] = (GByte)i;
-        for( i = 0; i < LZW_CODES; i++ )
+        for( int i = 0; i < LZW_CLEAR; i++ )
+          character[i] = static_cast<GByte>( i );
+        for( int i = 0; i < LZW_CODES; i++ )
             prefix[i] = LZW_NO_SUCH_CODE;
 
         filePos = LZW_OFFSET;
@@ -396,9 +401,9 @@ CPLErr RIKRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         code = GetNextLZWCode( codeBits, blockData, filePos,
                                fileAlign, bitsTaken );
 
-        OutputPixel( (GByte)code, pImage, poRDS->nBlockXSize,
+        OutputPixel( static_cast<GByte>( code ), pImage, poRDS->nBlockXSize,
                      lineBreak, imageLine, imagePos );
-        lastOutput = (GByte)code;
+        lastOutput = static_cast<GByte>( code );
 
         while( imageLine >= 0 &&
                (imageLine || imagePos < poRDS->nBlockXSize) &&
@@ -429,7 +434,7 @@ CPLErr RIKRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 #endif
 
                 // Clear prefix table
-                for( i = LZW_CLEAR; i < LZW_CODES; i++ )
+                for( int i = LZW_CLEAR; i < LZW_CODES; i++ )
                     prefix[i] = LZW_NO_SUCH_CODE;
                 lastAdded = LZW_CLEAR;
                 codeBits = LZW_BITS_PER_PIXEL + 1;
@@ -472,7 +477,7 @@ CPLErr RIKRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
                 // Decode
 
-                i = 0;
+                int i = 0;
                 while( ++i < LZW_CODES &&
        	               decodeCode >= LZW_CLEAR &&
        	               decodeCode < LZW_NO_SUCH_CODE )
@@ -480,7 +485,7 @@ CPLErr RIKRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                     stack[stackPtr++] = character[decodeCode];
                     decodeCode = prefix[decodeCode];
                 }
-                stack[stackPtr++] = (GByte)decodeCode;
+                stack[stackPtr++] = static_cast<GByte>( decodeCode );
 
                 if( i == LZW_CODES || decodeCode >= LZW_NO_SUCH_CODE )
                 {
@@ -547,13 +552,13 @@ CPLErr RIKRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     else if( poRDS->options == 0x0d )
     {
         uLong destLen = pixels;
-        Byte *upsideDown = (Byte *) CPLMalloc( pixels );
+        Byte *upsideDown = static_cast<Byte *>( CPLMalloc( pixels ) );
 
         uncompress( upsideDown, &destLen, blockData, nBlockSize );
 
         for (GUInt32 i = 0; i < poRDS->nBlockYSize; i++)
         {
-            memcpy( ((Byte *)pImage) + poRDS->nBlockXSize * i,
+          memcpy( reinterpret_cast<Byte *>( pImage ) + poRDS->nBlockXSize * i,
                     upsideDown + poRDS->nBlockXSize *
                                  (poRDS->nBlockYSize - i - 1),
                     poRDS->nBlockXSize );
@@ -584,7 +589,7 @@ GDALColorInterp RIKRasterBand::GetColorInterpretation()
 GDALColorTable *RIKRasterBand::GetColorTable()
 
 {
-    RIKDataset *poRDS = (RIKDataset *) poDS;
+    RIKDataset *poRDS = reinterpret_cast<RIKDataset *>( poDS );
 
     return poRDS->poColorTable;
 }
@@ -669,7 +674,7 @@ int RIKDataset::Identify( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->fpL == NULL || poOpenInfo->nHeaderBytes < 50 )
         return FALSE;
 
-    if( EQUALN((const char *) poOpenInfo->pabyHeader, "RIK3", 4) )
+    if( STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "RIK3") )
     {
         return TRUE;
     }
@@ -686,7 +691,7 @@ int RIKDataset::Identify( GDALOpenInfo * poOpenInfo )
         }
         if( actLength == 0 )
             return -1;
-        
+
         for( int i=0;i<actLength;i++ )
         {
             if( poOpenInfo->pabyHeader[2+i] == 0 )
@@ -713,7 +718,7 @@ GDALDataset *RIKDataset::Open( GDALOpenInfo * poOpenInfo )
 
     bool rik3header = false;
 
-    if( EQUALN((const char *) poOpenInfo->pabyHeader, "RIK3", 4) )
+    if( STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "RIK3") )
     {
         rik3header = true;
         VSIFSeekL( poOpenInfo->fpL, 4, SEEK_SET );
@@ -770,7 +775,7 @@ GDALDataset *RIKDataset::Open( GDALOpenInfo * poOpenInfo )
 
         // Read unknown string
 
-        projLength = GetRikString( poOpenInfo->fpL, projection, sizeof(projection) );
+        /*projLength =*/ GetRikString( poOpenInfo->fpL, projection, sizeof(projection) );
 
         // Read map north edge
 
@@ -851,15 +856,13 @@ GDALDataset *RIKDataset::Open( GDALOpenInfo * poOpenInfo )
         CPL_SWAP32PTR( &header.iMPPNum );
 #endif
 
-        if (!CPLIsFinite(header.fSouth) |
-            !CPLIsFinite(header.fWest) |
-            !CPLIsFinite(header.fNorth) |
+        if (!CPLIsFinite(header.fSouth) ||
+            !CPLIsFinite(header.fWest) ||
+            !CPLIsFinite(header.fNorth) ||
             !CPLIsFinite(header.fEast))
             return NULL;
 
-        bool offsetBounds;
-
-        offsetBounds = header.fSouth < 4000000;
+        const bool offsetBounds = header.fSouth < 4000000;
 
         header.iMPPDen = 1;
 
@@ -882,7 +885,7 @@ GDALDataset *RIKDataset::Open( GDALOpenInfo * poOpenInfo )
             headerType = "RIK2";
         }
 
-        metersPerPixel = header.iMPPNum / double(header.iMPPDen);
+        metersPerPixel = header.iMPPNum / static_cast<double>( header.iMPPDen );
 
         VSIFReadL( &header.iBlockWidth, 1, sizeof(header.iBlockWidth), poOpenInfo->fpL );
         VSIFReadL( &header.iBlockHeight, 1, sizeof(header.iBlockHeight), poOpenInfo->fpL );
@@ -907,9 +910,11 @@ GDALDataset *RIKDataset::Open( GDALOpenInfo * poOpenInfo )
 
         if( offsetBounds || !header.iVertBlocks )
         {
-            header.iVertBlocks = (GUInt32)
-                ceil( (header.fNorth - header.fSouth) /
+            double dfVertBlocks = ceil( (header.fNorth - header.fSouth) /
                       (header.iBlockHeight * metersPerPixel) );
+            if( dfVertBlocks < 1 || dfVertBlocks > INT_MAX )
+                return NULL;
+            header.iVertBlocks = static_cast<GUInt32>(dfVertBlocks);
         }
 
 #if RIK_HEADER_DEBUG
@@ -930,9 +935,6 @@ GDALDataset *RIKDataset::Open( GDALOpenInfo * poOpenInfo )
 
         VSIFReadL( &header.iOptions, 1, sizeof(header.iOptions), poOpenInfo->fpL );
 
-        if( !header.iHorBlocks || !header.iVertBlocks )
-           return NULL;
-
         if( header.iOptions != 0x00 && // Uncompressed
             header.iOptions != 0x40 && // Uncompressed
             header.iOptions != 0x01 && // RLE
@@ -947,14 +949,26 @@ GDALDataset *RIKDataset::Open( GDALOpenInfo * poOpenInfo )
         }
     }
 
+    if( header.iBlockWidth == 0 ||
+        header.iHorBlocks == 0 ||
+        header.iBlockWidth >= INT_MAX / header.iHorBlocks ||
+        header.iBlockHeight == 0 ||
+        header.iVertBlocks == 0 ||
+        header.iBlockHeight >= INT_MAX / header.iVertBlocks ||
+        header.iBlockHeight >= INT_MAX / header.iBlockWidth ||
+        header.iVertBlocks >= INT_MAX / (int)sizeof(GUInt32) ||
+        header.iHorBlocks >= INT_MAX / (header.iVertBlocks * (int)sizeof(GUInt32)) )
+    {
+        return NULL;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Read the palette.                                               */
 /* -------------------------------------------------------------------- */
 
     GByte palette[768];
 
-    GUInt16 i;
-    for( i = 0; i < 256; i++ )
+    for( GUInt16 i = 0; i < 256; i++ )
     {
         VSIFReadL( &palette[i * 3 + 2], 1, 1, poOpenInfo->fpL );
         VSIFReadL( &palette[i * 3 + 1], 1, 1, poOpenInfo->fpL );
@@ -965,11 +979,9 @@ GDALDataset *RIKDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Find block offsets.                                             */
 /* -------------------------------------------------------------------- */
 
-    GUInt32 blocks;
-    GUInt32 *offsets;
-
-    blocks = header.iHorBlocks * header.iVertBlocks;
-    offsets = (GUInt32 *)CPLMalloc( blocks * sizeof(GUInt32) );
+    GUInt32 blocks = header.iHorBlocks * header.iVertBlocks;
+    GUInt32 *offsets = reinterpret_cast<GUInt32 *>(
+        VSIMalloc( blocks * sizeof(GUInt32) ) );
 
     if( !offsets )
     {
@@ -981,7 +993,38 @@ GDALDataset *RIKDataset::Open( GDALOpenInfo * poOpenInfo )
 
     if( header.iOptions == 0x00 )
     {
-        offsets[0] = VSIFTellL( poOpenInfo->fpL );
+        offsets[0] = static_cast<GUInt32>(VSIFTellL( poOpenInfo->fpL ));
+
+        if( VSIFEofL( poOpenInfo->fpL ) )
+        {
+            CPLError( CE_Failure, CPLE_OpenFailed,
+                    "File %s. Read past end of file.\n",
+                    poOpenInfo->pszFilename );
+            CPLFree(offsets);
+            return NULL;
+        }
+
+        VSIFSeekL( poOpenInfo->fpL, 0, SEEK_END );
+        vsi_l_offset nBigFileSize = VSIFTellL( poOpenInfo->fpL );
+        if( nBigFileSize > 0xFFFFFFFFU )
+            nBigFileSize = 0xFFFFFFFFU;
+        GUInt32 fileSize = static_cast<GUInt32>(nBigFileSize);
+
+        GUInt32 nBlocksFromFileSize = (fileSize - offsets[0]) / (header.iBlockWidth * header.iBlockHeight);
+        if( nBlocksFromFileSize < blocks )
+        {
+            blocks = nBlocksFromFileSize;
+            header.iVertBlocks = blocks / header.iHorBlocks;
+        }
+
+        if( header.iVertBlocks == 0 )
+        {
+            CPLError( CE_Failure, CPLE_OpenFailed,
+                        "File %s too short.\n",
+                        poOpenInfo->pszFilename );
+            CPLFree( offsets );
+            return NULL;
+        }
 
         for( GUInt32 i = 1; i < blocks; i++ )
         {
@@ -993,14 +1036,16 @@ GDALDataset *RIKDataset::Open( GDALOpenInfo * poOpenInfo )
     {
         for( GUInt32 i = 0; i < blocks; i++ )
         {
-            VSIFReadL( &offsets[i], 1, sizeof(offsets[i]), poOpenInfo->fpL );
+            if( VSIFReadL( &offsets[i], sizeof(offsets[i]), 1, poOpenInfo->fpL ) != 1 )
+                break;
 #ifdef CPL_MSB
             CPL_SWAP32PTR( &offsets[i] );
 #endif
             if( rik3header )
             {
                 GUInt32 blockSize;
-                VSIFReadL( &blockSize, 1, sizeof(blockSize), poOpenInfo->fpL );
+                if( VSIFReadL( &blockSize, sizeof(blockSize), 1, poOpenInfo->fpL ) != 1 )
+                    break;
 #ifdef CPL_MSB
                 CPL_SWAP32PTR( &blockSize );
 #endif
@@ -1019,11 +1064,12 @@ GDALDataset *RIKDataset::Open( GDALOpenInfo * poOpenInfo )
         CPLError( CE_Failure, CPLE_OpenFailed,
                   "File %s. Read past end of file.\n",
                   poOpenInfo->pszFilename );
+        CPLFree(offsets);
         return NULL;
     }
 
     VSIFSeekL( poOpenInfo->fpL, 0, SEEK_END );
-    GUInt32 fileSize = VSIFTellL( poOpenInfo->fpL );
+    GUInt32 fileSize = static_cast<GUInt32>(VSIFTellL( poOpenInfo->fpL ));
 
 #if RIK_HEADER_DEBUG
     CPLDebug( "RIK",
@@ -1051,6 +1097,7 @@ GDALDataset *RIKDataset::Open( GDALOpenInfo * poOpenInfo )
                     CPLError( CE_Failure, CPLE_OpenFailed,
                               "File %s too short.\n",
                               poOpenInfo->pszFilename );
+                    CPLFree( offsets );
                     return NULL;
                 }
                 header.iVertBlocks = y;
@@ -1064,6 +1111,7 @@ GDALDataset *RIKDataset::Open( GDALOpenInfo * poOpenInfo )
                     CPLError( CE_Failure, CPLE_OpenFailed,
                               "File %s. Corrupt offset table.\n",
                               poOpenInfo->pszFilename );
+                    CPLFree( offsets );
                     return NULL;
                 }
                 header.iVertBlocks = y;
@@ -1121,9 +1169,7 @@ GDALDataset *RIKDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
 
-    RIKDataset 	*poDS;
-
-    poDS = new RIKDataset();
+    RIKDataset 	*poDS = new RIKDataset();
 
     poDS->fp = poOpenInfo->fpL;
     poOpenInfo->fpL = NULL;
@@ -1150,7 +1196,7 @@ GDALDataset *RIKDataset::Open( GDALOpenInfo * poOpenInfo )
 
     GDALColorEntry oEntry;
     poDS->poColorTable = new GDALColorTable();
-    for( i = 0; i < 256; i++ )
+    for( GUInt16 i = 0; i < 256; i++ )
     {
         oEntry.c1 = palette[i * 3 + 2]; // Red
         oEntry.c2 = palette[i * 3 + 1]; // Green
@@ -1184,12 +1230,12 @@ GDALDataset *RIKDataset::Open( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->eAccess == GA_Update )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The RIK driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
     }
-    
+
     return( poDS );
 }
 
@@ -1200,25 +1246,20 @@ GDALDataset *RIKDataset::Open( GDALOpenInfo * poOpenInfo )
 void GDALRegister_RIK()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "RIK" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "RIK" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-
-        poDriver->SetDescription( "RIK" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Swedish Grid RIK (.rik)" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "frmt_various.html#RIK" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "rik" );
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetDescription( "RIK" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Swedish Grid RIK (.rik)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#RIK" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "rik" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = RIKDataset::Open;
-        poDriver->pfnIdentify = RIKDataset::Identify;
+    poDriver->pfnOpen = RIKDataset::Open;
+    poDriver->pfnIdentify = RIKDataset::Identify;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/rmf/frmt_rmf.html b/frmts/rmf/frmt_rmf.html
index 3914d9d..37c17d0 100644
--- a/frmts/rmf/frmt_rmf.html
+++ b/frmts/rmf/frmt_rmf.html
@@ -12,7 +12,7 @@ RMF is a simple tiled raster format used in the GIS "Integration" and
 
 There are two flavours of RMF called MTW and RSW. MTW supports 16-bit integer
 and 32/64-bit floating point data in a single channel and aimed to store DEM
-data. RSW is a general purpose raster, it supports single channel colormapped
+data. RSW is a general purpose raster. It supports single channel colormapped
 or three channel RGB images. Only 8-bit data can be stored in RSW. Simple
 georeferencing can be provided for both image types.<p>
 
@@ -30,7 +30,7 @@ georeferencing can be provided for both image types.<p>
 	or 1 (total elevation). MTW only.<p>
 
 </ul>
-	
+
 <h2>Creation Options</h2>
 <ul>
 	<li> <b>MTW=ON</b>: Force the generation of MTW matrix (RSW will be
diff --git a/frmts/rmf/rmfdataset.cpp b/frmts/rmf/rmfdataset.cpp
index 337083a..3e31e61 100644
--- a/frmts/rmf/rmfdataset.cpp
+++ b/frmts/rmf/rmfdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rmfdataset.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: rmfdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Raster Matrix Format
  * Purpose:  Read/write raster files used in GIS "Integratsia"
@@ -28,19 +28,16 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_spatialref.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "ogr_spatialref.h"
 
 #include "rmfdataset.h"
 
-CPL_CVSID("$Id: rmfdataset.cpp 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: rmfdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
-CPL_C_START
-void    GDALRegister_RMF(void);
-CPL_C_END
-
-#define RMF_DEFAULT_BLOCKXSIZE 256
-#define RMF_DEFAULT_BLOCKYSIZE 256
+static const int RMF_DEFAULT_BLOCKXSIZE = 256;
+static const int RMF_DEFAULT_BLOCKYSIZE = 256;
 
 static const char RMF_SigRSW[] = { 'R', 'S', 'W', '\0' };
 static const char RMF_SigRSW_BE[] = { '\0', 'W', 'S', 'R' };
@@ -62,30 +59,29 @@ static const char RMF_UnitsMM[] = "mm";
 /*                           RMFRasterBand()                            */
 /************************************************************************/
 
-RMFRasterBand::RMFRasterBand( RMFDataset *poDS, int nBand,
-                              GDALDataType eType )
+RMFRasterBand::RMFRasterBand( RMFDataset *poDSIn, int nBandIn,
+                              GDALDataType eType ) :
+    nBytesPerPixel(poDSIn->sHeader.nBitDepth / 8),
+    nLastTileWidth(poDSIn->GetRasterXSize() % poDSIn->sHeader.nTileWidth),
+    nLastTileHeight(poDSIn->GetRasterYSize() % poDSIn->sHeader.nTileHeight),
+    nDataSize(GDALGetDataTypeSize( eType ) / 8)
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
     eDataType = eType;
-    nBytesPerPixel = poDS->sHeader.nBitDepth / 8;
-    nDataSize = GDALGetDataTypeSize( eDataType ) / 8;
-    nBlockXSize = poDS->sHeader.nTileWidth;
-    nBlockYSize = poDS->sHeader.nTileHeight;
+    nBlockXSize = poDSIn->sHeader.nTileWidth;
+    nBlockYSize = poDSIn->sHeader.nTileHeight;
     nBlockSize = nBlockXSize * nBlockYSize;
     nBlockBytes = nBlockSize * nDataSize;
-    nLastTileXBytes =
-        (poDS->GetRasterXSize() % poDS->sHeader.nTileWidth) * nDataSize;
-    nLastTileHeight = poDS->GetRasterYSize() % poDS->sHeader.nTileHeight;
 
 #ifdef DEBUG
     CPLDebug( "RMF",
               "Band %d: tile width is %d, tile height is %d, "
-              " last tile width %d, last tile height %d, "
+              " last tile width %u, last tile height %u, "
               "bytes per pixel is %d, data type size is %d",
               nBand, nBlockXSize, nBlockYSize,
-              poDS->sHeader.nLastTileWidth, poDS->sHeader.nLastTileHeight,
+              nLastTileWidth, nLastTileHeight,
               nBytesPerPixel, nDataSize );
 #endif
 }
@@ -94,24 +90,22 @@ RMFRasterBand::RMFRasterBand( RMFDataset *poDS, int nBand,
 /*                           ~RMFRasterBand()                           */
 /************************************************************************/
 
-RMFRasterBand::~RMFRasterBand()
-{
-}
+RMFRasterBand::~RMFRasterBand() {}
 
 /************************************************************************/
 /*                              ReadBuffer()                            */
 /*                                                                      */
-/* Helper fucntion to read specified amount of bytes from the input     */
+/* Helper function to read specified amount of bytes from the input     */
 /* file stream.                                                         */
 /************************************************************************/
 
 CPLErr RMFRasterBand::ReadBuffer( GByte *pabyBuf, GUInt32 nBytes ) const
 {
-    RMFDataset  *poGDS = (RMFDataset *) poDS;
+    RMFDataset  *poGDS = reinterpret_cast<RMFDataset *>( poDS );
 
-    CPLAssert( pabyBuf != NULL && poGDS->fp != 0 );
+    CPLAssert( pabyBuf != NULL && poGDS->fp != NULL );
 
-    vsi_l_offset nOffset = VSIFTellL( poGDS->fp );
+    const vsi_l_offset nOffset = VSIFTellL( poGDS->fp );
 
     if ( VSIFReadL( pabyBuf, 1, nBytes, poGDS->fp ) < nBytes )
     {
@@ -124,7 +118,7 @@ CPLErr RMFRasterBand::ReadBuffer( GByte *pabyBuf, GUInt32 nBytes ) const
         {
             CPLError( CE_Failure, CPLE_FileIO,
                       "Can't read at offset %ld from input file.\n%s\n",
-                      (long)nOffset, VSIStrerror( errno ) );
+                      static_cast<long>( nOffset ), VSIStrerror( errno ) );
             return CE_Failure;
         }
     }
@@ -132,23 +126,21 @@ CPLErr RMFRasterBand::ReadBuffer( GByte *pabyBuf, GUInt32 nBytes ) const
 #ifdef CPL_MSB
     if ( poGDS->eRMFType == RMFT_MTW )
     {
-        GUInt32     i;
-
         if ( poGDS->sHeader.nBitDepth == 16 )
         {
-            for ( i = 0; i < nBytes; i += 2 )
+            for ( GUInt32 i = 0; i < nBytes; i += 2 )
                 CPL_SWAP16PTR( pabyBuf + i );
         }
 
         else if ( poGDS->sHeader.nBitDepth == 32 )
         {
-            for ( i = 0; i < nBytes; i += 4 )
+            for ( GUInt32 i = 0; i < nBytes; i += 4 )
                 CPL_SWAP32PTR( pabyBuf + i );
         }
 
         else if ( poGDS->sHeader.nBitDepth == 64 )
         {
-            for ( i = 0; i < nBytes; i += 8 )
+            for ( GUInt32 i = 0; i < nBytes; i += 8 )
                 CPL_SWAPDOUBLE( pabyBuf + i );
         }
     }
@@ -164,10 +156,7 @@ CPLErr RMFRasterBand::ReadBuffer( GByte *pabyBuf, GUInt32 nBytes ) const
 CPLErr RMFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                   void * pImage )
 {
-    RMFDataset  *poGDS = (RMFDataset *) poDS;
-    GUInt32     nTile = nBlockYOff * poGDS->nXTiles + nBlockXOff;
-    GUInt32     nTileBytes;
-    GUInt32     nCurBlockYSize;
+    RMFDataset  *poGDS = reinterpret_cast<RMFDataset *>( poDS );
 
     CPLAssert( poGDS != NULL
                && nBlockXOff >= 0
@@ -176,16 +165,18 @@ CPLErr RMFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
     memset( pImage, 0, nBlockBytes );
 
+    GUInt32 nTile = nBlockYOff * poGDS->nXTiles + nBlockXOff;
     if (2 * nTile + 1 >= poGDS->sHeader.nTileTblSize / sizeof(GUInt32))
     {
         return CE_Failure;
     }
 
-    nTileBytes = poGDS->paiTiles[2 * nTile + 1];
+    GUInt32 nTileBytes = poGDS->paiTiles[2 * nTile + 1];
+    GUInt32 nCurBlockYSize;
 
-    if ( poGDS->sHeader.nLastTileHeight
-         && (GUInt32) nBlockYOff == poGDS->nYTiles - 1 )
-        nCurBlockYSize = poGDS->sHeader.nLastTileHeight;
+    if ( nLastTileHeight
+         && static_cast<GUInt32>( nBlockYOff ) == poGDS->nYTiles - 1 )
+        nCurBlockYSize = nLastTileHeight;
     else
         nCurBlockYSize = nBlockYSize;
 
@@ -195,13 +186,12 @@ CPLErr RMFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 	// in update state and data for this block will be available later
         if( poGDS->eAccess == GA_Update )
             return CE_None;
-        else
-        {
-            CPLError( CE_Failure, CPLE_FileIO,
-                "Can't seek to offset %ld in input file to read data.\n%s\n",
-                (long) poGDS->paiTiles[2 * nTile], VSIStrerror( errno ) );
-            return CE_Failure;
-        }
+
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Can't seek to offset %ld in input file to read data.\n%s\n",
+                  static_cast<long>( poGDS->paiTiles[2 * nTile] ),
+                  VSIStrerror( errno ) );
+        return CE_Failure;
     }
 
     if ( poGDS->nBands == 1 &&
@@ -220,8 +210,8 @@ CPLErr RMFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         {
             GUInt32 nRawBytes;
 
-            if ( nLastTileXBytes && (GUInt32)nBlockXOff == poGDS->nXTiles - 1 )
-                nRawBytes = nLastTileXBytes;
+            if ( nLastTileWidth && (GUInt32)nBlockXOff == poGDS->nXTiles - 1 )
+                nRawBytes = poGDS->nBands * nLastTileWidth * nDataSize;
             else
                 nRawBytes = poGDS->nBands * nBlockXSize * nDataSize;
 
@@ -232,7 +222,8 @@ CPLErr RMFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
             if ( nRawBytes > nTileBytes )
             {
-                GByte   *pabyTile = (GByte *) VSIMalloc( nTileBytes );
+                GByte *pabyTile = reinterpret_cast<GByte *>(
+                    VSIMalloc( nTileBytes ) );
 
                 if ( !pabyTile )
                 {
@@ -251,13 +242,15 @@ CPLErr RMFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                 }
 
                 (*poGDS->Decompress)( pabyTile, nTileBytes,
-                                      (GByte*)pImage, nRawBytes );
+                                      reinterpret_cast<GByte*>( pImage ),
+                                      nRawBytes );
                 CPLFree( pabyTile );
-                nTileBytes = nRawBytes;
+                /*nTileBytes = nRawBytes;*/
             }
             else
             {
-                if ( ReadBuffer( (GByte *)pImage, nTileBytes ) == CE_Failure )
+              if ( ReadBuffer( reinterpret_cast<GByte *>( pImage ),
+                               nTileBytes ) == CE_Failure )
                 {
                     // XXX: Do not fail here, just return empty block
                     // and continue reading.
@@ -269,7 +262,8 @@ CPLErr RMFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         else
         {
 
-            if ( ReadBuffer( (GByte *)pImage, nTileBytes ) == CE_Failure )
+          if ( ReadBuffer( reinterpret_cast<GByte *>( pImage ),
+                           nTileBytes ) == CE_Failure )
             {
                 // XXX: Do not fail here, just return empty block
                 // and continue reading.
@@ -282,7 +276,7 @@ CPLErr RMFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
     else if ( poGDS->eRMFType == RMFT_RSW )
     {
-        GByte   *pabyTile = (GByte *) VSIMalloc( nTileBytes );
+        GByte *pabyTile = reinterpret_cast<GByte *>( VSIMalloc( nTileBytes ) );
 
         if ( !pabyTile )
         {
@@ -308,8 +302,8 @@ CPLErr RMFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         {
             GUInt32 nRawBytes;
 
-            if ( nLastTileXBytes && (GUInt32)nBlockXOff == poGDS->nXTiles - 1 )
-                nRawBytes = nLastTileXBytes;
+            if ( nLastTileWidth && (GUInt32)nBlockXOff == poGDS->nXTiles - 1 )
+                nRawBytes = poGDS->nBands * nLastTileWidth * nDataSize;
             else
                 nRawBytes = poGDS->nBands * nBlockXSize * nDataSize;
 
@@ -320,12 +314,15 @@ CPLErr RMFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
             if ( nRawBytes > nTileBytes )
             {
-                GByte *pszRawBuf = (GByte *)VSIMalloc( nRawBytes );
+                GByte *pszRawBuf = reinterpret_cast<GByte *>(
+                    VSIMalloc( nRawBytes ) );
                 if (pszRawBuf == NULL)
                 {
                     CPLError( CE_Failure, CPLE_FileIO,
-                      "Can't allocate a buffer for raw data of size %lu.\n%s\n",
-                      (unsigned long) nRawBytes, VSIStrerror( errno ) );
+                              "Can't allocate a buffer for raw data of "
+                              "size %lu.\n%s\n",
+                              static_cast<unsigned long>( nRawBytes ),
+                              VSIStrerror( errno ) );
 
                     VSIFree( pabyTile );
                     return CE_Failure;
@@ -342,8 +339,6 @@ CPLErr RMFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
 /*  Deinterleave pixels from input buffer.                              */
 /* -------------------------------------------------------------------- */
-        GUInt32     i;
-
         if ( poGDS->sHeader.nBitDepth == 24 || poGDS->sHeader.nBitDepth == 32 )
         {
             GUInt32 nTileSize = nTileBytes / nBytesPerPixel;
@@ -351,14 +346,14 @@ CPLErr RMFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             if ( nTileSize > nBlockSize )
                 nTileSize = nBlockSize;
 
-            for ( i = 0; i < nTileSize; i++ )
+            for( GUInt32 i = 0; i < nTileSize; i++ )
             {
                 // Colour triplets in RMF file organized in reverse order:
                 // blue, green, red. When we have 32-bit RMF the forth byte
-                // in quadriplet should be discarded as it has no meaning.
+                // in quadruplet should be discarded as it has no meaning.
                 // That is why we always use 3 byte count in the following
                 // pabyTemp index.
-                ((GByte *) pImage)[i] =
+                reinterpret_cast<GByte *>( pImage )[i] =
                     pabyTile[i * nBytesPerPixel + 3 - nBand];
             }
         }
@@ -370,21 +365,24 @@ CPLErr RMFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             if ( nTileSize > nBlockSize )
                 nTileSize = nBlockSize;
 
-            for ( i = 0; i < nTileSize; i++ )
+            for( GUInt32 i = 0; i < nTileSize; i++ )
             {
                 switch ( nBand )
                 {
                     case 1:
-                        ((GByte *) pImage)[i] =
-                            (GByte)((((GUInt16*)pabyTile)[i] & 0x7c00) >> 7);
+                        reinterpret_cast<GByte *>( pImage )[i] =
+                            static_cast<GByte>((reinterpret_cast<GUInt16 *>(
+                                pabyTile )[i] & 0x7c00) >> 7);
                         break;
                     case 2:
-                        ((GByte *) pImage)[i] =
-                            (GByte)((((GUInt16*)pabyTile)[i] & 0x03e0) >> 2);
+                        reinterpret_cast<GByte *>( pImage )[i] =
+                            static_cast<GByte>((reinterpret_cast<GUInt16 *>(
+                                pabyTile )[i] & 0x03e0) >> 2);
                         break;
                     case 3:
-                        ((GByte *) pImage)[i] =
-                            (GByte)(((GUInt16*)pabyTile)[i] & 0x1F) << 3;
+                        reinterpret_cast<GByte *>( pImage )[i] =
+                            static_cast<GByte>((reinterpret_cast<GUInt16 *>(
+                                pabyTile)[i] & 0x1F) << 3);
                         break;
                     default:
                         break;
@@ -396,13 +394,23 @@ CPLErr RMFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         {
             GByte *pabyTemp = pabyTile;
 
-            for ( i = 0; i < nBlockSize; i++ )
+            if( nTileBytes != (nBlockSize+1) / 2 )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Tile has %d bytes, %d were expected",
+                         nTileBytes, (nBlockSize+1) / 2 );
+                CPLFree( pabyTile );
+                return CE_Failure;
+            }
+
+            for( GUInt32 i = 0; i < nBlockSize; i++ )
             {
                 // Most significant part of the byte represents leftmost pixel
                 if ( i & 0x01 )
-                    ((GByte *) pImage)[i] = *pabyTemp++ & 0x0F;
+                    reinterpret_cast<GByte *>( pImage )[i] = *pabyTemp++ & 0x0F;
                 else
-                    ((GByte *) pImage)[i] = (*pabyTemp & 0xF0) >> 4;
+                    reinterpret_cast<GByte *>( pImage )[i]
+                        = (*pabyTemp & 0xF0) >> 4;
             }
         }
 
@@ -410,33 +418,42 @@ CPLErr RMFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         {
             GByte *pabyTemp = pabyTile;
 
-            for ( i = 0; i < nBlockSize; i++ )
+            if( nTileBytes != (nBlockSize+7) / 8 )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Tile has %d bytes, %d were expected",
+                         nTileBytes, (nBlockSize+7) / 8 );
+                CPLFree( pabyTile );
+                return CE_Failure;
+            }
+
+            for( GUInt32 i = 0; i < nBlockSize; i++ )
             {
                 switch ( i & 0x7 )
                 {
                     case 0:
-                        ((GByte *) pImage)[i] = (*pabyTemp & 0x80) >> 7;
+                        reinterpret_cast<GByte *>( pImage )[i] = (*pabyTemp & 0x80) >> 7;
                         break;
                     case 1:
-                        ((GByte *) pImage)[i] = (*pabyTemp & 0x40) >> 6;
+                        reinterpret_cast<GByte *>( pImage )[i] = (*pabyTemp & 0x40) >> 6;
                         break;
                     case 2:
-                        ((GByte *) pImage)[i] = (*pabyTemp & 0x20) >> 5;
+                        reinterpret_cast<GByte *>( pImage )[i] = (*pabyTemp & 0x20) >> 5;
                         break;
                     case 3:
-                        ((GByte *) pImage)[i] = (*pabyTemp & 0x10) >> 4;
+                        reinterpret_cast<GByte *>( pImage )[i] = (*pabyTemp & 0x10) >> 4;
                         break;
                     case 4:
-                        ((GByte *) pImage)[i] = (*pabyTemp & 0x08) >> 3;
+                        reinterpret_cast<GByte *>( pImage )[i] = (*pabyTemp & 0x08) >> 3;
                         break;
                     case 5:
-                        ((GByte *) pImage)[i] = (*pabyTemp & 0x04) >> 2;
+                        reinterpret_cast<GByte *>( pImage )[i] = (*pabyTemp & 0x04) >> 2;
                         break;
                     case 6:
-                        ((GByte *) pImage)[i] = (*pabyTemp & 0x02) >> 1;
+                        reinterpret_cast<GByte *>( pImage )[i] = (*pabyTemp & 0x02) >> 1;
                         break;
                     case 7:
-                        ((GByte *) pImage)[i] = *pabyTemp++ & 0x01;
+                        reinterpret_cast<GByte *>( pImage )[i] = *pabyTemp++ & 0x01;
                         break;
                     default:
                         break;
@@ -447,16 +464,16 @@ CPLErr RMFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         CPLFree( pabyTile );
     }
 
-    if ( nLastTileXBytes
-         && (GUInt32) nBlockXOff == poGDS->nXTiles - 1 )
+    if ( nLastTileWidth
+         && static_cast<GUInt32>( nBlockXOff ) == poGDS->nXTiles - 1 )
     {
-        GUInt32 iRow;
-
-        for ( iRow = nCurBlockYSize - 1; iRow > 0; iRow-- )
+        for ( GUInt32 iRow = nCurBlockYSize - 1; iRow > 0; iRow-- )
         {
-            memmove( (GByte *)pImage + nBlockXSize * iRow * nDataSize,
-                     (GByte *)pImage + iRow * nLastTileXBytes,
-                     nLastTileXBytes );
+            memmove( reinterpret_cast<GByte *>( pImage )
+                     + nBlockXSize * iRow * nDataSize,
+                     reinterpret_cast<GByte *>( pImage ) +
+                     iRow * nLastTileWidth * nDataSize,
+                     nLastTileWidth * nDataSize );
         }
 
     }
@@ -471,7 +488,7 @@ CPLErr RMFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 CPLErr RMFRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                                    void * pImage )
 {
-    RMFDataset  *poGDS = (RMFDataset *)poDS;
+    RMFDataset  *poGDS = reinterpret_cast<RMFDataset *>( poDS );
     GUInt32     nTile = nBlockYOff * poGDS->nXTiles + nBlockXOff;
     GUInt32     nTileBytes = nDataSize * poGDS->nBands;
     GUInt32     iInPixel, iOutPixel, nCurBlockYSize;
@@ -488,7 +505,7 @@ CPLErr RMFRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
         {
             CPLError( CE_Failure, CPLE_FileIO,
                 "Can't seek to offset %ld in output file to write data.\n%s",
-                      (long) poGDS->paiTiles[2 * nTile],
+                      static_cast<long>( poGDS->paiTiles[2 * nTile] ),
                       VSIStrerror( errno ) );
             return CE_Failure;
         }
@@ -499,7 +516,7 @@ CPLErr RMFRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
         {
             CPLError( CE_Failure, CPLE_FileIO,
                 "Can't seek to offset %ld in output file to write data.\n%s",
-                      (long) poGDS->paiTiles[2 * nTile],
+                      static_cast<long>( poGDS->paiTiles[2 * nTile] ),
                       VSIStrerror( errno ) );
             return CE_Failure;
         }
@@ -508,31 +525,32 @@ CPLErr RMFRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
         poGDS->bHeaderDirty = TRUE;
     }
 
-    if ( nLastTileXBytes
-         && (GUInt32) nBlockXOff == poGDS->nXTiles - 1 )
-        nTileBytes *= poGDS->sHeader.nLastTileWidth;
+    if ( nLastTileWidth
+         && static_cast<GUInt32>( nBlockXOff ) == poGDS->nXTiles - 1 )
+        nTileBytes *= nLastTileWidth;
     else
         nTileBytes *= nBlockXSize;
 
-    if ( poGDS->sHeader.nLastTileHeight
-         && (GUInt32) nBlockYOff == poGDS->nYTiles - 1 )
-        nCurBlockYSize = poGDS->sHeader.nLastTileHeight;
+    if ( nLastTileHeight
+         && static_cast<GUInt32>( nBlockYOff ) == poGDS->nYTiles - 1 )
+        nCurBlockYSize = nLastTileHeight;
     else
         nCurBlockYSize = nBlockYSize;
 
     nTileBytes *= nCurBlockYSize;
 
-    pabyTile = (GByte *) VSICalloc( nTileBytes, 1 );
+    pabyTile = reinterpret_cast<GByte *>( VSICalloc( nTileBytes, 1 ) );
     if ( !pabyTile )
     {
         CPLError( CE_Failure, CPLE_FileIO,
-                  "Can't allocate space for the tile blocak of size %lu.\n%s",
-                 (unsigned long) nTileBytes,  VSIStrerror( errno ) );
+                  "Can't allocate space for the tile block of size %lu.\n%s",
+                  static_cast<unsigned long>( nTileBytes ),
+                  VSIStrerror( errno ) );
         return CE_Failure;
     }
 
-    if ( nLastTileXBytes
-         && (GUInt32) nBlockXOff == poGDS->nXTiles - 1 )
+    if ( nLastTileWidth
+         && static_cast<GUInt32>( nBlockXOff ) == poGDS->nXTiles - 1 )
     {
         GUInt32 iRow;
 
@@ -540,9 +558,9 @@ CPLErr RMFRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
         {
             for ( iRow = 0; iRow < nCurBlockYSize; iRow++ )
             {
-                memcpy( pabyTile + iRow * nLastTileXBytes,
-                         (GByte*)pImage + nBlockXSize * iRow * nDataSize,
-                         nLastTileXBytes );
+                memcpy( pabyTile + iRow * nLastTileWidth * nDataSize,
+                        reinterpret_cast<GByte *>( pImage )
+                        + nBlockXSize * iRow * nDataSize, nLastTileWidth * nDataSize );
             }
         }
         else
@@ -556,10 +574,11 @@ CPLErr RMFRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
             for ( iRow = 0; iRow < nCurBlockYSize; iRow++ )
             {
                 for ( iInPixel = 0, iOutPixel = nBytesPerPixel - nBand;
-                      iOutPixel < nLastTileXBytes * poGDS->nBands;
+                      iOutPixel < nLastTileWidth * nDataSize * poGDS->nBands;
                       iInPixel++, iOutPixel += poGDS->nBands )
-                    (pabyTile + iRow * nLastTileXBytes * poGDS->nBands)[iOutPixel] =
-                        ((GByte *) pImage + nBlockXSize * iRow * nDataSize)[iInPixel];
+                    (pabyTile + iRow * nLastTileWidth * nDataSize * poGDS->nBands)[iOutPixel] =
+                        (reinterpret_cast<GByte *>( pImage ) + nBlockXSize
+                         * iRow * nDataSize)[iInPixel];
             }
         }
     }
@@ -578,31 +597,29 @@ CPLErr RMFRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
             for ( iInPixel = 0, iOutPixel = nBytesPerPixel - nBand;
                   iOutPixel < nTileBytes;
                   iInPixel++, iOutPixel += poGDS->nBands )
-                pabyTile[iOutPixel] = ((GByte *) pImage)[iInPixel];
+                pabyTile[iOutPixel] = reinterpret_cast<GByte *>( pImage )[iInPixel];
 
         }
     }
 
 #ifdef CPL_MSB
     if ( poGDS->eRMFType == RMFT_MTW )
-    {
-        GUInt32 i;
-
+    {;
         if ( poGDS->sHeader.nBitDepth == 16 )
         {
-            for ( i = 0; i < nTileBytes; i += 2 )
+            for( GUInt32 i = 0; i < nTileBytes; i += 2 )
                 CPL_SWAP16PTR( pabyTile + i );
         }
 
         else if ( poGDS->sHeader.nBitDepth == 32 )
         {
-            for ( i = 0; i < nTileBytes; i += 4 )
+            for( GUInt32 i = 0; i < nTileBytes; i += 4 )
                 CPL_SWAP32PTR( pabyTile + i );
         }
 
         else if ( poGDS->sHeader.nBitDepth == 64 )
         {
-            for ( i = 0; i < nTileBytes; i += 8 )
+            for( GUInt32 i = 0; i < nTileBytes; i += 8 )
                 CPL_SWAPDOUBLE( pabyTile + i );
         }
     }
@@ -626,13 +643,28 @@ CPLErr RMFRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
 }
 
 /************************************************************************/
+/*                          GetNoDataValue()                            */
+/************************************************************************/
+
+double RMFRasterBand::GetNoDataValue( int *pbSuccess )
+
+{
+    RMFDataset *poGDS = reinterpret_cast<RMFDataset *>( poDS );
+
+    if ( pbSuccess )
+        *pbSuccess = TRUE;
+
+    return poGDS->sHeader.dfNoData;
+}
+
+/************************************************************************/
 /*                            GetUnitType()                             */
 /************************************************************************/
 
 const char *RMFRasterBand::GetUnitType()
 
 {
-    RMFDataset   *poGDS = (RMFDataset *) poDS;
+    RMFDataset *poGDS = reinterpret_cast<RMFDataset *>( poDS );
 
     return (const char *)poGDS->pszUnitType;
 }
@@ -644,7 +676,7 @@ const char *RMFRasterBand::GetUnitType()
 CPLErr RMFRasterBand::SetUnitType( const char *pszNewValue )
 
 {
-    RMFDataset   *poGDS = (RMFDataset *) poDS;
+    RMFDataset *poGDS = reinterpret_cast<RMFDataset *>( poDS );
 
     CPLFree(poGDS->pszUnitType);
     poGDS->pszUnitType = CPLStrdup( pszNewValue );
@@ -658,7 +690,7 @@ CPLErr RMFRasterBand::SetUnitType( const char *pszNewValue )
 
 GDALColorTable *RMFRasterBand::GetColorTable()
 {
-    RMFDataset   *poGDS = (RMFDataset *) poDS;
+    RMFDataset *poGDS = reinterpret_cast<RMFDataset *>( poDS );
 
     return poGDS->poColorTable;
 }
@@ -669,19 +701,17 @@ GDALColorTable *RMFRasterBand::GetColorTable()
 
 CPLErr RMFRasterBand::SetColorTable( GDALColorTable *poColorTable )
 {
-    RMFDataset  *poGDS = (RMFDataset *) poDS;
+    RMFDataset *poGDS = reinterpret_cast<RMFDataset *>( poDS );
 
     if ( poColorTable )
     {
         if ( poGDS->eRMFType == RMFT_RSW && poGDS->nBands == 1 )
         {
-            GDALColorEntry  oEntry;
-            GUInt32         i;
-
             if ( !poGDS->pabyColorTable )
                 return CE_Failure;
 
-            for( i = 0; i < poGDS->nColorTableSize; i++ )
+            GDALColorEntry  oEntry;
+            for( GUInt32 i = 0; i < poGDS->nColorTableSize; i++ )
             {
                 poColorTable->GetColorEntryAsRGB( i, &oEntry );
                 poGDS->pabyColorTable[i * 4] = (GByte) oEntry.c1;     // Red
@@ -692,11 +722,10 @@ CPLErr RMFRasterBand::SetColorTable( GDALColorTable *poColorTable )
 
             poGDS->bHeaderDirty = TRUE;
         }
+        return CE_None;
     }
-    else
-        return CE_Failure;
 
-    return CE_None;
+    return CE_Failure;
 }
 
 /************************************************************************/
@@ -705,7 +734,7 @@ CPLErr RMFRasterBand::SetColorTable( GDALColorTable *poColorTable )
 
 GDALColorInterp RMFRasterBand::GetColorInterpretation()
 {
-    RMFDataset      *poGDS = (RMFDataset *) poDS;
+    RMFDataset *poGDS = reinterpret_cast<RMFDataset *>( poDS );
 
     if( poGDS->nBands == 3 )
     {
@@ -715,16 +744,14 @@ GDALColorInterp RMFRasterBand::GetColorInterpretation()
             return GCI_GreenBand;
         else if( nBand == 3 )
             return GCI_BlueBand;
-        else
-            return GCI_Undefined;
-    }
-    else
-    {
-        if ( poGDS->eRMFType == RMFT_RSW )
-            return GCI_PaletteIndex;
-        else
-            return GCI_Undefined;
+
+        return GCI_Undefined;
     }
+
+    if ( poGDS->eRMFType == RMFT_RSW )
+        return GCI_PaletteIndex;
+
+    return GCI_Undefined;
 }
 
 /************************************************************************/
@@ -737,32 +764,31 @@ GDALColorInterp RMFRasterBand::GetColorInterpretation()
 /*                           RMFDataset()                               */
 /************************************************************************/
 
-RMFDataset::RMFDataset()
+RMFDataset::RMFDataset() :
+    eRMFType(RMFT_RSW),
+    nXTiles(0),
+    nYTiles(0),
+    paiTiles(NULL),
+    nColorTableSize(0),
+    pabyColorTable(NULL),
+    poColorTable(NULL),
+    pszProjection(CPLStrdup( "" )),
+    pszUnitType(CPLStrdup( RMF_UnitsEmpty )),
+    bBigEndian(FALSE),
+    bHeaderDirty(FALSE),
+    pszFilename(NULL),
+    fp(NULL),
+    Decompress(NULL)
 {
-    pszFilename = NULL;
-    fp = NULL;
     nBands = 0;
-    nXTiles = 0;
-    nYTiles = 0;
-    paiTiles = NULL;
-    pszProjection = CPLStrdup( "" );
-    pszUnitType = CPLStrdup( RMF_UnitsEmpty );
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
-    pabyColorTable = NULL;
-    poColorTable = NULL;
-    eRMFType = RMFT_RSW;
     memset( &sHeader, 0, sizeof(sHeader) );
     memset( &sExtHeader, 0, sizeof(sExtHeader) );
-
-    Decompress = NULL;
-
-    bBigEndian = FALSE;
-    bHeaderDirty = FALSE;
 }
 
 /************************************************************************/
@@ -773,17 +799,13 @@ RMFDataset::~RMFDataset()
 {
     FlushCache();
 
-    if ( paiTiles )
-        CPLFree( paiTiles );
-    if ( pszProjection )
-        CPLFree( pszProjection );
-    if ( pszUnitType )
-        CPLFree( pszUnitType );
-    if ( pabyColorTable )
-        CPLFree( pabyColorTable );
+    CPLFree( paiTiles );
+    CPLFree( pszProjection );
+    CPLFree( pszUnitType );
+    CPLFree( pabyColorTable );
     if ( poColorTable != NULL )
         delete poColorTable;
-    if( fp != NULL )
+    if ( fp )
         VSIFCloseL( fp );
 }
 
@@ -797,8 +819,8 @@ CPLErr RMFDataset::GetGeoTransform( double * padfTransform )
 
     if( sHeader.iGeorefFlag )
         return CE_None;
-    else
-        return CE_Failure;
+
+    return CE_Failure;
 }
 
 /************************************************************************/
@@ -828,8 +850,8 @@ const char *RMFDataset::GetProjectionRef()
 {
     if( pszProjection )
         return pszProjection;
-    else
-        return "";
+
+    return "";
 }
 
 /************************************************************************/
@@ -860,24 +882,24 @@ CPLErr RMFDataset::WriteHeader()
     if( pszProjection && !EQUAL( pszProjection, "" ) )
     {
         OGRSpatialReference oSRS;
-        long            iProjection, iDatum, iEllips, iZone;
-        char            *pszProj =  pszProjection;
+        char *pszProj = pszProjection;
 
         if ( oSRS.importFromWkt( &pszProj ) == OGRERR_NONE )
         {
+            long iProjection, iDatum, iEllips, iZone;
             double  adfPrjParams[7];
 
             oSRS.exportToPanorama( &iProjection, &iDatum, &iEllips, &iZone,
                                    adfPrjParams );
-            sHeader.iProjection = iProjection;
+            sHeader.iProjection = static_cast<int>(iProjection);
             sHeader.dfStdP1 = adfPrjParams[0];
             sHeader.dfStdP2 = adfPrjParams[1];
             sHeader.dfCenterLat = adfPrjParams[2];
             sHeader.dfCenterLong = adfPrjParams[3];
 
-            sExtHeader.nEllipsoid = iEllips;
-            sExtHeader.nDatum = iDatum;
-            sExtHeader.nZone = iZone;
+            sExtHeader.nEllipsoid = static_cast<int>(iEllips);
+            sExtHeader.nDatum = static_cast<int>(iDatum);
+            sExtHeader.nZone = static_cast<int>(iZone);
         }
     }
 
@@ -971,7 +993,8 @@ do {                                                    \
 
     if ( sHeader.nExtHdrOffset && sHeader.nExtHdrSize )
     {
-        GByte   *pabyExtHeader = (GByte *)CPLCalloc( sHeader.nExtHdrSize, 1 );
+        GByte *pabyExtHeader = reinterpret_cast<GByte *>(
+            CPLCalloc( sHeader.nExtHdrSize, 1 ) );
 
         RMF_WRITE_LONG( pabyExtHeader, sExtHeader.nEllipsoid, 24 );
         RMF_WRITE_LONG( pabyExtHeader, sExtHeader.nDatum, 32 );
@@ -1004,14 +1027,13 @@ do {                                                    \
     VSIFSeekL( fp, sHeader.nTileTblOffset, SEEK_SET );
 
 #ifdef CPL_MSB
-    GUInt32 i;
-    GUInt32 *paiTilesSwapped = (GUInt32 *)CPLMalloc( sHeader.nTileTblSize );
-
+    GUInt32 *paiTilesSwapped = reinterpret_cast<GUInt32 *>(
+        CPLMalloc( sHeader.nTileTblSize ) );
     if ( !paiTilesSwapped )
         return CE_Failure;
 
     memcpy( paiTilesSwapped, paiTiles, sHeader.nTileTblSize );
-    for ( i = 0; i < sHeader.nTileTblSize / sizeof(GUInt32); i++ )
+    for ( GUInt32 i = 0; i < sHeader.nTileTblSize / sizeof(GUInt32); i++ )
         CPL_SWAP32PTR( paiTilesSwapped + i );
     VSIFWriteL( paiTilesSwapped, 1, sHeader.nTileTblSize, fp );
 
@@ -1080,9 +1102,7 @@ GDALDataset *RMFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*  Create a corresponding GDALDataset.                                 */
 /* -------------------------------------------------------------------- */
-    RMFDataset      *poDS;
-
-    poDS = new RMFDataset();
+    RMFDataset *poDS = new RMFDataset();
 
     if( poOpenInfo->eAccess == GA_ReadOnly )
         poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
@@ -1094,6 +1114,18 @@ GDALDataset *RMFDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
+#define RMF_READ_SHORT(ptr, value, offset)                              \
+do {                                                                    \
+    if ( poDS->bBigEndian )                                             \
+    {                                                                   \
+        (value) = CPL_MSBWORD16(*(GInt16*)((ptr) + (offset)));          \
+    }                                                                   \
+    else                                                                \
+    {                                                                   \
+        (value) = CPL_LSBWORD16(*(GInt16*)((ptr) + (offset)));          \
+    }                                                                   \
+} while(0);
+
 #define RMF_READ_ULONG(ptr, value, offset)                              \
 do {                                                                    \
     if ( poDS->bBigEndian )                                             \
@@ -1120,7 +1152,7 @@ do {                                                                    \
 
 #define RMF_READ_DOUBLE(ptr, value, offset)                             \
 do {                                                                    \
-    (value) = *(double*)((ptr) + (offset));                             \
+    (value) = *reinterpret_cast<double*>((ptr) + (offset));             \
     if ( poDS->bBigEndian )                                             \
     {                                                                   \
         CPL_MSBPTR64(&(value));                                         \
@@ -1139,7 +1171,11 @@ do {                                                                    \
         GByte   abyHeader[RMF_HEADER_SIZE];
 
         VSIFSeekL( poDS->fp, 0, SEEK_SET );
-        VSIFReadL( abyHeader, 1, sizeof(abyHeader), poDS->fp );
+        if( VSIFReadL( abyHeader, 1, sizeof(abyHeader), poDS->fp ) != sizeof(abyHeader) )
+        {
+            delete poDS;
+            return NULL;
+        }
 
         if ( memcmp(abyHeader, RMF_SigMTW, sizeof(RMF_SigMTW)) == 0 )
             poDS->eRMFType = RMFT_MTW;
@@ -1200,7 +1236,24 @@ do {                                                                    \
                 abyHeader + 248, sizeof(poDS->sHeader.abyInvisibleColors) );
         RMF_READ_DOUBLE( abyHeader, poDS->sHeader.adfElevMinMax[0], 280 );
         RMF_READ_DOUBLE( abyHeader, poDS->sHeader.adfElevMinMax[1], 288 );
-        RMF_READ_DOUBLE( abyHeader, poDS->sHeader.dfNoData, 296 );
+
+        if (poDS->sHeader.nBitDepth == 8)
+        {
+            poDS->sHeader.dfNoData = *reinterpret_cast<char *>(abyHeader + 296);
+        }
+        else if (poDS->sHeader.nBitDepth == 16)
+        {
+            RMF_READ_SHORT(abyHeader, poDS->sHeader.dfNoData, 296);
+        }
+        else if (poDS->sHeader.nBitDepth == 32)
+        {
+            RMF_READ_LONG(abyHeader, poDS->sHeader.dfNoData, 296);
+        }
+        else if (poDS->sHeader.nBitDepth == 64)
+        {
+            RMF_READ_DOUBLE(abyHeader, poDS->sHeader.dfNoData, 296);
+        }
+
         RMF_READ_ULONG( abyHeader, poDS->sHeader.iElevationUnit, 304 );
         poDS->sHeader.iElevationType = *(abyHeader + 308);
         RMF_READ_ULONG( abyHeader, poDS->sHeader.nExtHdrOffset, 312 );
@@ -1213,8 +1266,9 @@ do {                                                                    \
 
     if ( poDS->sHeader.nExtHdrOffset && poDS->sHeader.nExtHdrSize )
     {
-        GByte *pabyExtHeader =
-            (GByte *)VSICalloc( poDS->sHeader.nExtHdrSize, 1 );
+        /* coverity[tainted_data] */
+        GByte *pabyExtHeader = reinterpret_cast<GByte *>(
+            VSICalloc( poDS->sHeader.nExtHdrSize, 1 ) );
         if (pabyExtHeader == NULL)
         {
             delete poDS;
@@ -1246,8 +1300,10 @@ do {                                                                    \
               poDS->sHeader.dfNoData );
     CPLDebug( "RMF", "Size %d, offset to overview %#lx, user ID %d, "
               "ROI offset %#lx, ROI size %d",
-              poDS->sHeader.nSize, (unsigned long)poDS->sHeader.nOvrOffset,
-              poDS->sHeader.iUserID, (unsigned long)poDS->sHeader.nROIOffset,
+              poDS->sHeader.nSize,
+              static_cast<unsigned long>( poDS->sHeader.nOvrOffset ),
+              poDS->sHeader.iUserID,
+              static_cast<unsigned long>( poDS->sHeader.nROIOffset ),
               poDS->sHeader.nROISize );
     CPLDebug( "RMF", "Map type %d, projection %d, scale %f, resolution %f, ",
               poDS->sHeader.iMapType, poDS->sHeader.iProjection,
@@ -1257,16 +1313,18 @@ do {                                                                    \
               poDS->sHeader.dfLLX, poDS->sHeader.dfLLY );
     if ( poDS->sHeader.nROIOffset && poDS->sHeader.nROISize )
     {
-        GUInt32     i;
-        GInt32     nValue;
+        GInt32 nValue;
 
         CPLDebug( "RMF", "ROI coordinates:" );
-        for ( i = 0; i < poDS->sHeader.nROISize; i += sizeof(nValue) )
+        /* coverity[tainted_data] */
+        for ( GUInt32 i = 0; i < poDS->sHeader.nROISize; i += sizeof(nValue) )
         {
-            GUInt32  nValue;
-
-            VSIFSeekL( poDS->fp, poDS->sHeader.nROIOffset + i, SEEK_SET );
-            VSIFReadL( &nValue, 1, sizeof(nValue), poDS->fp );
+            if( VSIFSeekL( poDS->fp, poDS->sHeader.nROIOffset + i, SEEK_SET ) != 0 ||
+                VSIFReadL( &nValue, 1, sizeof(nValue), poDS->fp ) != sizeof(nValue) )
+            {
+                delete poDS;
+                return NULL;
+            }
 
             CPLDebug( "RMF", "%d", nValue );
         }
@@ -1276,15 +1334,15 @@ do {                                                                    \
 /* -------------------------------------------------------------------- */
 /*  Read array of blocks offsets/sizes.                                 */
 /* -------------------------------------------------------------------- */
-    GUInt32 i;
-
     if ( VSIFSeekL( poDS->fp, poDS->sHeader.nTileTblOffset, SEEK_SET ) < 0)
     {
         delete poDS;
         return NULL;
     }
 
-    poDS->paiTiles = (GUInt32 *)VSIMalloc( poDS->sHeader.nTileTblSize );
+    /* coverity[tainted_data] */
+    poDS->paiTiles = reinterpret_cast<GUInt32 *>(
+        VSIMalloc( poDS->sHeader.nTileTblSize ) );
     if ( !poDS->paiTiles )
     {
         delete poDS;
@@ -1302,13 +1360,13 @@ do {                                                                    \
 #ifdef CPL_MSB
     if ( !poDS->bBigEndian )
     {
-        for ( i = 0; i < poDS->sHeader.nTileTblSize / sizeof(GUInt32); i++ )
+        for ( GUInt32 i = 0; i < poDS->sHeader.nTileTblSize / sizeof(GUInt32); i++ )
             CPL_SWAP32PTR( poDS->paiTiles + i );
     }
 #else
     if ( poDS->bBigEndian )
     {
-        for ( i = 0; i < poDS->sHeader.nTileTblSize / sizeof(GUInt32); i++ )
+        for ( GUInt32 i = 0; i < poDS->sHeader.nTileTblSize / sizeof(GUInt32); i++ )
             CPL_SWAP32PTR( poDS->paiTiles + i );
     }
 #endif
@@ -1316,7 +1374,7 @@ do {                                                                    \
 #ifdef DEBUG
     CPLDebug( "RMF", "List of block offsets/sizes:" );
 
-    for ( i = 0; i < poDS->sHeader.nTileTblSize / sizeof(GUInt32); i += 2 )
+    for ( GUInt32 i = 0; i < poDS->sHeader.nTileTblSize / sizeof(GUInt32); i += 2 )
     {
         CPLDebug( "RMF", "    %d / %d",
                   poDS->paiTiles[i], poDS->paiTiles[i + 1] );
@@ -1361,8 +1419,9 @@ do {                                                                    \
                         delete poDS;
                         return NULL;
                     }
-                    poDS->pabyColorTable =
-                        (GByte *)VSIMalloc( poDS->sHeader.nClrTblSize );
+                    /* coverity[tainted_data] */
+                    poDS->pabyColorTable = reinterpret_cast<GByte *>(
+                        VSIMalloc( poDS->sHeader.nClrTblSize ) );
                     if (poDS->pabyColorTable == NULL)
                     {
                         CPLDebug( "RMF", "Can't allocate color table." );
@@ -1387,7 +1446,7 @@ do {                                                                    \
 
                     GDALColorEntry oEntry;
                     poDS->poColorTable = new GDALColorTable();
-                    for( i = 0; i < poDS->nColorTableSize; i++ )
+                    for( GUInt32 i = 0; i < poDS->nColorTableSize; i++ )
                     {
                         oEntry.c1 = poDS->pabyColorTable[i * 4];     // Red
                         oEntry.c2 = poDS->pabyColorTable[i * 4 + 1]; // Green
@@ -1417,19 +1476,30 @@ do {                                                                    \
             eType = GDT_Float64;
     }
 
-    if (poDS->sHeader.nTileWidth == 0 ||
-        poDS->sHeader.nTileHeight == 0)
+    if (poDS->sHeader.nTileWidth == 0 || poDS->sHeader.nTileWidth > INT_MAX ||
+        poDS->sHeader.nTileHeight == 0 || poDS->sHeader.nTileHeight > INT_MAX)
     {
-        CPLDebug ("RMF", "Invalid tile dimension : %d x %d",
+        CPLDebug ("RMF", "Invalid tile dimension : %u x %u",
                   poDS->sHeader.nTileWidth, poDS->sHeader.nTileHeight);
         delete poDS;
         return NULL;
     }
 
-    poDS->nXTiles = ( poDS->nRasterXSize + poDS->sHeader.nTileWidth - 1 ) /
-        poDS->sHeader.nTileWidth;
-    poDS->nYTiles = ( poDS->nRasterYSize + poDS->sHeader.nTileHeight - 1 ) /
-        poDS->sHeader.nTileHeight;
+    const int nDataSize = GDALGetDataTypeSize( eType ) / 8;
+    const int nBlockXSize = static_cast<int>(poDS->sHeader.nTileWidth);
+    const int nBlockYSize = static_cast<int>(poDS->sHeader.nTileHeight);
+    if( nDataSize == 0 ||
+        nBlockXSize > INT_MAX / nBlockYSize ||
+        nBlockYSize > INT_MAX / nDataSize ||
+        nBlockXSize > INT_MAX / (nBlockYSize * nDataSize) )
+    {
+        CPLDebug ("RMF", "Too big raster / tile dimension");
+        delete poDS;
+        return NULL;
+    }
+
+    poDS->nXTiles = DIV_ROUND_UP( poDS->nRasterXSize, nBlockXSize );
+    poDS->nYTiles = DIV_ROUND_UP( poDS->nRasterYSize, nBlockYSize );
 
 #ifdef DEBUG
     CPLDebug( "RMF", "Image is %d tiles wide, %d tiles long",
@@ -1452,9 +1522,7 @@ do {                                                                    \
 /* -------------------------------------------------------------------- */
 /*  Create band information objects.                                    */
 /* -------------------------------------------------------------------- */
-    int iBand;
-
-    for( iBand = 1; iBand <= poDS->nBands; iBand++ )
+    for( int iBand = 1; iBand <= poDS->nBands; iBand++ )
         poDS->SetBand( iBand, new RMFRasterBand( poDS, iBand, eType ) );
 
 /* -------------------------------------------------------------------- */
@@ -1470,7 +1538,7 @@ do {                                                                    \
     {
         OGRSpatialReference oSRS;
         GInt32  nProj =
-            (poDS->sHeader.iProjection) ? poDS->sHeader.iProjection : 1L;
+            (poDS->sHeader.iProjection) ? poDS->sHeader.iProjection : 1;
         double  padfPrjParams[8];
 
         padfPrjParams[0] = poDS->sHeader.dfStdP1;
@@ -1621,9 +1689,7 @@ GDALDataset *RMFDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*  Create the dataset.                                                 */
 /* -------------------------------------------------------------------- */
-    RMFDataset      *poDS;
-
-    poDS = new RMFDataset();
+    RMFDataset *poDS = new RMFDataset();
 
     poDS->fp = VSIFOpenL( pszFilename, "w+b" );
     if( poDS->fp == NULL )
@@ -1639,12 +1705,10 @@ GDALDataset *RMFDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*  Fill the RMFHeader                                                  */
 /* -------------------------------------------------------------------- */
-    GUInt32     nTileSize, nCurPtr = 0;
-    GUInt32     nBlockXSize =
+    GUInt32 nBlockXSize =
         ( nXSize < RMF_DEFAULT_BLOCKXSIZE ) ? nXSize : RMF_DEFAULT_BLOCKXSIZE;
-    GUInt32     nBlockYSize =
+    GUInt32 nBlockYSize =
         ( nYSize < RMF_DEFAULT_BLOCKYSIZE ) ? nYSize : RMF_DEFAULT_BLOCKYSIZE;
-    const char  *pszValue;
 
     if ( CSLFetchBoolean( papszParmList, "MTW", FALSE) )
         poDS->eRMFType = RMFT_MTW;
@@ -1662,13 +1726,17 @@ GDALDataset *RMFDataset::Create( const char * pszFilename,
     poDS->sHeader.nHeight = nYSize;
     poDS->sHeader.nWidth = nXSize;
 
-    pszValue = CSLFetchNameValue(papszParmList,"BLOCKXSIZE");
+    const char *pszValue = CSLFetchNameValue(papszParmList,"BLOCKXSIZE");
     if( pszValue != NULL )
         nBlockXSize = atoi( pszValue );
+    if( nBlockXSize <= 0 )
+        nBlockXSize = RMF_DEFAULT_BLOCKXSIZE;
 
     pszValue = CSLFetchNameValue(papszParmList,"BLOCKYSIZE");
     if( pszValue != NULL )
         nBlockYSize = atoi( pszValue );
+    if( nBlockYSize <= 0 )
+        nBlockYSize = RMF_DEFAULT_BLOCKXSIZE;
 
     poDS->sHeader.nTileWidth = nBlockXSize;
     poDS->sHeader.nTileHeight = nBlockYSize;
@@ -1687,7 +1755,7 @@ GDALDataset *RMFDataset::Create( const char * pszFilename,
     poDS->sHeader.nROIOffset = 0x00;
     poDS->sHeader.nROISize = 0x00;
 
-    nCurPtr += RMF_HEADER_SIZE;
+    GUInt32 nCurPtr = RMF_HEADER_SIZE;
 
     // Extended header
     poDS->sHeader.nExtHdrOffset = nCurPtr;
@@ -1697,8 +1765,6 @@ GDALDataset *RMFDataset::Create( const char * pszFilename,
     // Color table
     if ( poDS->eRMFType == RMFT_RSW && nBands == 1 )
     {
-        GUInt32 i;
-
         if ( poDS->sHeader.nBitDepth > 8 )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -1711,14 +1777,14 @@ GDALDataset *RMFDataset::Create( const char * pszFilename,
         poDS->sHeader.nClrTblOffset = nCurPtr;
         poDS->nColorTableSize = 1 << poDS->sHeader.nBitDepth;
         poDS->sHeader.nClrTblSize = poDS->nColorTableSize * 4;
-        poDS->pabyColorTable = (GByte *) VSIMalloc( poDS->sHeader.nClrTblSize );
+        poDS->pabyColorTable = reinterpret_cast<GByte *>(
+            VSI_MALLOC_VERBOSE( poDS->sHeader.nClrTblSize ) );
         if (poDS->pabyColorTable == NULL)
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
             delete poDS;
             return NULL;
         }
-        for ( i = 0; i < poDS->nColorTableSize; i++ )
+        for( GUInt32 i = 0; i < poDS->nColorTableSize; i++ )
         {
             poDS->pabyColorTable[i * 4] =
                 poDS->pabyColorTable[i * 4 + 1] =
@@ -1737,9 +1803,10 @@ GDALDataset *RMFDataset::Create( const char * pszFilename,
     poDS->sHeader.nTileTblOffset = nCurPtr;
     poDS->sHeader.nTileTblSize =
         poDS->sHeader.nXTiles * poDS->sHeader.nYTiles * 4 * 2;
-    poDS->paiTiles = (GUInt32 *)CPLCalloc( poDS->sHeader.nTileTblSize, 1 );
-    nCurPtr += poDS->sHeader.nTileTblSize;
-    nTileSize = poDS->sHeader.nTileWidth * poDS->sHeader.nTileHeight
+    poDS->paiTiles = reinterpret_cast<GUInt32 *>(
+        CPLCalloc( poDS->sHeader.nTileTblSize, 1 ) );
+    /*nCurPtr += poDS->sHeader.nTileTblSize;*/
+    const GUInt32 nTileSize = poDS->sHeader.nTileWidth * poDS->sHeader.nTileHeight
         * GDALGetDataTypeSize( eType ) / 8;
     poDS->sHeader.nSize =
         poDS->paiTiles[poDS->sHeader.nTileTblSize / 4 - 2] + nTileSize;
@@ -1788,12 +1855,10 @@ GDALDataset *RMFDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    int         iBand;
-
-    for( iBand = 1; iBand <= poDS->nBands; iBand++ )
+    for( int iBand = 1; iBand <= poDS->nBands; iBand++ )
         poDS->SetBand( iBand, new RMFRasterBand( poDS, iBand, eType ) );
 
-    return (GDALDataset *) poDS;
+    return reinterpret_cast<GDALDataset *>( poDS );
 }
 
 /************************************************************************/
@@ -1803,34 +1868,29 @@ GDALDataset *RMFDataset::Create( const char * pszFilename,
 void GDALRegister_RMF()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "RMF" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "RMF" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-
-        poDriver->SetDescription( "RMF" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Raster Matrix Format" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "frmt_rmf.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "rsw" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
-                                   "Byte Int16 Int32 Float64" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "RMF" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Raster Matrix Format" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_rmf.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "rsw" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte Int16 Int32 Float64" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "   <Option name='MTW' type='boolean' description='Create MTW DEM matrix'/>"
 "   <Option name='BLOCKXSIZE' type='int' description='Tile Width'/>"
 "   <Option name='BLOCKYSIZE' type='int' description='Tile Height'/>"
 "</CreationOptionList>" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnIdentify = RMFDataset::Identify;
-        poDriver->pfnOpen = RMFDataset::Open;
-        poDriver->pfnCreate = RMFDataset::Create;
+    poDriver->pfnIdentify = RMFDataset::Identify;
+    poDriver->pfnOpen = RMFDataset::Open;
+    poDriver->pfnCreate = RMFDataset::Create;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
-
diff --git a/frmts/rmf/rmfdataset.h b/frmts/rmf/rmfdataset.h
index 35c3beb..0f785eb 100644
--- a/frmts/rmf/rmfdataset.h
+++ b/frmts/rmf/rmfdataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rmfdataset.h 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: rmfdataset.h 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Raster Matrix Format
  * Purpose:  Private class declarations for the RMF classes used to read/write
@@ -72,7 +72,7 @@ typedef struct
     GUInt32     nClrTblOffset;                  // Position and size
     GUInt32     nClrTblSize;                    // of the colour table
     GUInt32     nTileTblOffset;                 // Position and size of the
-    GUInt32     nTileTblSize;                   // tile offsets/sizes table 
+    GUInt32     nTileTblSize;                   // tile offsets/sizes table
     GInt32      iMapType;
     GInt32      iProjection;
     double      dfScale;
@@ -130,7 +130,7 @@ class RMFDataset : public GDALDataset
     GUInt32         nXTiles;
     GUInt32         nYTiles;
     GUInt32         *paiTiles;
-    
+
     GUInt32         nColorTableSize;
     GByte           *pabyColorTable;
     GDALColorTable  *poColorTable;
@@ -178,7 +178,7 @@ class RMFRasterBand : public GDALRasterBand
 
     GUInt32     nBytesPerPixel;
     GUInt32     nBlockSize, nBlockBytes;
-    GUInt32     nLastTileXBytes, nLastTileHeight;
+    GUInt32     nLastTileWidth, nLastTileHeight;
     GUInt32     nDataSize;
 
     CPLErr   ReadBuffer( GByte *, GUInt32 ) const;
@@ -190,10 +190,10 @@ class RMFRasterBand : public GDALRasterBand
 
     virtual CPLErr          IReadBlock( int, int, void * );
     virtual CPLErr          IWriteBlock( int, int, void * );
+    virtual double          GetNoDataValue(int *pbSuccess = NULL);
     virtual const char      *GetUnitType();
     virtual GDALColorInterp GetColorInterpretation();
     virtual GDALColorTable  *GetColorTable();
     virtual CPLErr          SetUnitType(const char *);
     virtual CPLErr          SetColorTable( GDALColorTable * );
 };
-
diff --git a/frmts/rmf/rmfdem.cpp b/frmts/rmf/rmfdem.cpp
index 78779a9..ac788b9 100644
--- a/frmts/rmf/rmfdem.cpp
+++ b/frmts/rmf/rmfdem.cpp
@@ -86,6 +86,18 @@
 #define INV_INT24   0xFF000000L
 
 
+// Not sure which behaviour we wish for int32 overflow, so just do the
+// addition as uint32 to workaround -ftrapv
+static GInt32 AddInt32(GInt32& nTarget, GInt32 nVal)
+{
+    GUInt32 nTargetU, nValU;
+    memcpy(&nTargetU, &nTarget, 4);
+    memcpy(&nValU, &nVal, 4);
+    nTargetU += nValU;
+    memcpy(&nTarget, &nTargetU, 4);
+    return nTarget;
+}
+
 /************************************************************************/
 /*                           DEMDecompress()                            */
 /************************************************************************/
@@ -100,8 +112,8 @@ int RMFDataset::DEMDecompress( const GByte* pabyIn, GUInt32 nSizeIn,
     GInt32 iPrev = 0;           // The last data value decoded
     GInt32 nCode;
 
-    if ( pabyIn == 0 ||
-         pabyOut == 0 ||
+    if ( pabyIn == NULL ||
+         pabyOut == NULL ||
          nSizeOut < nSizeIn ||
          nSizeIn < 2 )
         return 0;
@@ -143,11 +155,11 @@ int RMFDataset::DEMDecompress( const GByte* pabyIn, GUInt32 nSizeIn,
                 break;
 
             case TYPE_INT4:
-                if ( nSizeIn < nCount / 2 )
+                if ( nSizeIn < (nCount + 1) / 2 )
                     break;
                 if ( nSizeOut < nCount )
                     break;
-                nSizeIn -= nCount / 2;
+                nSizeIn -= (nCount + 1) / 2;
                 nSizeOut -= nCount;
                 while ( nCount-- > 0 )
                 {
@@ -155,12 +167,15 @@ int RMFDataset::DEMDecompress( const GByte* pabyIn, GUInt32 nSizeIn,
                     if ( nCode > RANGE_INT4 )
                         nCode |= INV_INT4;
                     *paiOut++ = ( nCode == OUT_INT4 ) ?
-                        OUT_INT32 : iPrev += nCode;
+                        OUT_INT32 : AddInt32(iPrev, nCode);
 
                     if ( nCount-- == 0 )
                     {
-                        pabyTempIn++;
-                        nSizeIn--;
+                        if( nSizeIn )
+                        {
+                            pabyTempIn++;
+                            nSizeIn--;
+                        }
                         break;
                     }
 
@@ -168,7 +183,7 @@ int RMFDataset::DEMDecompress( const GByte* pabyIn, GUInt32 nSizeIn,
                     if ( nCode > RANGE_INT4 )
                         nCode |= INV_INT4;
                     *paiOut++ = ( nCode == OUT_INT4 ) ?
-                        OUT_INT32 : iPrev += nCode;
+                        OUT_INT32 : AddInt32(iPrev, nCode);
                 }
                 break;
 
@@ -182,16 +197,16 @@ int RMFDataset::DEMDecompress( const GByte* pabyIn, GUInt32 nSizeIn,
                 while ( nCount-- > 0 )
                 {
                     *paiOut++ = ( (nCode = *pabyTempIn++) == OUT_INT8 ) ?
-                        OUT_INT32 : iPrev += nCode;
+                        OUT_INT32 : AddInt32(iPrev, nCode);
                 }
                 break;
 
             case TYPE_INT12:
-                if ( nSizeIn < 3 * nCount / 2 )
+                if ( nSizeIn < (3 * nCount + 1) / 2 )
                     break;
                 if ( nSizeOut < nCount )
                     break;
-                nSizeIn -= 3 * nCount / 2;
+                nSizeIn -= (3 * nCount + 1) / 2;
                 nSizeOut -= nCount;
 
                 while ( nCount-- > 0 )
@@ -200,12 +215,15 @@ int RMFDataset::DEMDecompress( const GByte* pabyIn, GUInt32 nSizeIn,
                     if ( nCode > RANGE_INT12 )
                         nCode |= INV_INT12;
                     *paiOut++ = ( nCode == OUT_INT12 ) ?
-                        OUT_INT32 : iPrev += nCode;
+                        OUT_INT32 : AddInt32(iPrev, nCode);
 
                     if ( nCount-- == 0 )
                     {
-                        pabyTempIn++;
-                        nSizeIn--;
+                        if( nSizeIn )
+                        {
+                            pabyTempIn++;
+                            nSizeIn--;
+                        }
                         break;
                     }
 
@@ -214,7 +232,7 @@ int RMFDataset::DEMDecompress( const GByte* pabyIn, GUInt32 nSizeIn,
                     if ( nCode > RANGE_INT12 )
                         nCode |= INV_INT12;
                     *paiOut++ = ( nCode == OUT_INT12 ) ?
-                        OUT_INT32 : iPrev += nCode;
+                        OUT_INT32 : AddInt32(iPrev, nCode);
                 }
                 break;
 
@@ -231,7 +249,7 @@ int RMFDataset::DEMDecompress( const GByte* pabyIn, GUInt32 nSizeIn,
                     nCode = *((GInt16*)pabyTempIn);
                     pabyTempIn += 2;
                     *paiOut++ = ( nCode == OUT_INT16 ) ?
-                        OUT_INT32 : iPrev += nCode;
+                        OUT_INT32 : AddInt32(iPrev, nCode);
                 }
                 break;
 
@@ -250,7 +268,7 @@ int RMFDataset::DEMDecompress( const GByte* pabyIn, GUInt32 nSizeIn,
                     if ( nCode > RANGE_INT24 )
                         nCode |= INV_INT24;
                     *paiOut++ = ( nCode == OUT_INT24 ) ?
-                        OUT_INT32 : iPrev += nCode;
+                        OUT_INT32 : AddInt32(iPrev, nCode);
                 }
                 break;
 
@@ -267,12 +285,12 @@ int RMFDataset::DEMDecompress( const GByte* pabyIn, GUInt32 nSizeIn,
                     nCode = *(GInt32 *)pabyTempIn;
                     pabyTempIn += 4;
                     *paiOut++ = ( nCode == OUT_INT32 ) ?
-                        OUT_INT32 : iPrev += nCode;
+                        OUT_INT32 : AddInt32(iPrev, nCode);
                 }
                 break;
     }
   }
 
-  return ((GByte*)paiOut - pabyOut);
+  return static_cast<int>((GByte*)paiOut - pabyOut);
 }
 
diff --git a/frmts/rmf/rmflzw.cpp b/frmts/rmf/rmflzw.cpp
index e471e6f..1721d36 100644
--- a/frmts/rmf/rmflzw.cpp
+++ b/frmts/rmf/rmflzw.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rmflzw.cpp 11865 2007-08-09 11:53:57Z warmerdam $
+ * $Id: rmflzw.cpp 33105 2016-01-23 15:27:32Z rouault $
  *
  * Project:  Raster Matrix Format
  * Purpose:  Implementation of the LZW compression algorithm as used in
@@ -92,7 +92,7 @@ static void LZWUpdateTab(LZWStringTab *poCodeTab, GUInt32 iPred, char bFoll)
         nNext = nLocal;
     else
     {
-        // If collision has occured
+        // If collision has occurred
         while ( (nNext = poCodeTab[nLocal].iNext) != 0 )
             nLocal = nNext;
 
@@ -127,8 +127,8 @@ int RMFDataset::LZWDecompress( const GByte* pabyIn, GUInt32 nSizeIn,
     LZWStringTab    *poCodeTab;
     int             bBitsleft;
 
-    if ( pabyIn == 0 ||
-         pabyOut == 0 ||
+    if ( pabyIn == NULL ||
+         pabyOut == NULL ||
          nSizeOut < nSizeIn ||
          nSizeIn < 2 )
         return 0;
diff --git a/frmts/rs2/frmt_rs2.html b/frmts/rs2/frmt_rs2.html
index a5413d9..377f877 100644
--- a/frmts/rs2/frmt_rs2.html
+++ b/frmts/rs2/frmt_rs2.html
@@ -13,24 +13,24 @@ particular complex products, and 16bit magnitude detected products.<p>
 The RadarSat 2 XML products are distributed with a primary XML file called
 product.xml, and a set of supporting XML data files with the actual imagery
 stored in TIFF files.  The RS2 driver will be used if the product.xml or
-the containing directory is selected, and it can treat all the imagery as 
+the containing directory is selected, and it can treat all the imagery as
 one consistent dataset.<p>
 
-The complex products use "32bit void typed" TIFF files which are not 
+The complex products use "32bit void typed" TIFF files which are not
 meaningfully readable normally.  The RS2 driver takes care of converting
 this into useful CInt16 format internally.<p>
 
 The RS2 driver also reads geolocation tiepoints from the product.xml file
 and represents them as GCPs on the dataset. <p>
 
-It is very likely that RadarSat International will be distributing 
+It is very likely that RadarSat International will be distributing
 other sorts of datasets in this format; however, at this time this driver
-only supports specific RadarSat 2 polarimetric products.  All other will 
+only supports specific RadarSat 2 polarimetric products.  All other will
 be ignored, or result in various runtime errors.  It is hoped that this
 driver can be generalized when other product samples become available. <p>
 
 <h2>Data Calibration</h2>
-If you wish to have GDAL apply a particular calibration LUT to the data when you open it, you have to open the appropriate subdatasets. The following subdatasets exist within the SUBDATASET domain for RS2 products: 
+If you wish to have GDAL apply a particular calibration LUT to the data when you open it, you have to open the appropriate subdatasets. The following subdatasets exist within the SUBDATASET domain for RS2 products:
 <ul>
 <li>uncalibrated - open with RADARSAT_2_CALIB:UNCALIB: prepended to filename
 <li>beta<sub>0</sub> - open with RADARSAT_2_CALIB:BETA0: prepended to filename
diff --git a/frmts/rs2/rs2dataset.cpp b/frmts/rs2/rs2dataset.cpp
index 525ad1f..0c418a3 100644
--- a/frmts/rs2/rs2dataset.cpp
+++ b/frmts/rs2/rs2dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rs2dataset.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: rs2dataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Polarimetric Workstation
  * Purpose:  Radarsat 2 - XML Products (product.xml) driver
@@ -28,15 +28,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
 #include "cpl_minixml.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: rs2dataset.cpp 28053 2014-12-04 09:31:07Z rouault $");
-
-CPL_C_START
-void    GDALRegister_RS2(void);
-CPL_C_END
+CPL_CVSID("$Id: rs2dataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 typedef enum eCalibration_t {
     Sigma0 = 0,
@@ -50,24 +47,14 @@ typedef enum eCalibration_t {
 static bool IsValidXMLFile( const char *pszPath, const char *pszLut)
 {
     /* Return true for valid xml file, false otherwise */
+    char *pszLutFile
+        = VSIStrdup(CPLFormFilename(pszPath, pszLut, NULL));
 
-    CPLXMLNode *psLut;
-    char *pszLutFile;
-    bool retVal = false;
-
-    pszLutFile = VSIStrdup(CPLFormFilename(pszPath, pszLut, NULL));
-
-    psLut = CPLParseXMLFile(pszLutFile);
-    
-    if (psLut != NULL)
-    {
-        CPLDestroyXMLNode(psLut);
-        retVal = true;
-    }
+    CPLXMLTreeCloser psLut(CPLParseXMLFile(pszLutFile));
 
     CPLFree(pszLutFile);
-    
-    return retVal;
+
+    return psLut.get() != NULL;;
 }
 
 /************************************************************************/
@@ -96,12 +83,11 @@ class RS2Dataset : public GDALPamDataset
   public:
             RS2Dataset();
            ~RS2Dataset();
-    
+
     virtual int    GetGCPCount();
     virtual const char *GetGCPProjection();
     virtual const GDAL_GCP *GetGCPs();
 
-    
     virtual const char *GetProjectionRef(void);
     virtual CPLErr GetGeoTransform( double * );
 
@@ -126,12 +112,12 @@ class RS2RasterBand : public GDALPamRasterBand
     GDALDataset     *poBandFile;
 
   public:
-            RS2RasterBand( RS2Dataset *poDSIn, 
+            RS2RasterBand( RS2Dataset *poDSIn,
                                GDALDataType eDataTypeIn,
-                               const char *pszPole, 
+                               const char *pszPole,
                                GDALDataset *poBandFile );
     virtual     ~RS2RasterBand();
-    
+
     virtual CPLErr IReadBlock( int, int, void * );
 
     static GDALDataset *Open( GDALOpenInfo * );
@@ -144,19 +130,16 @@ class RS2RasterBand : public GDALPamRasterBand
 
 RS2RasterBand::RS2RasterBand( RS2Dataset *poDSIn,
                               GDALDataType eDataTypeIn,
-                              const char *pszPole, 
-                              GDALDataset *poBandFileIn )
-
+                              const char *pszPole,
+                              GDALDataset *poBandFileIn ) :
+    poBandFile(poBandFileIn)
 {
-    GDALRasterBand *poSrcBand;
-
     poDS = poDSIn;
-    poBandFile = poBandFileIn;
 
-    poSrcBand = poBandFile->GetRasterBand( 1 );
+    GDALRasterBand *poSrcBand = poBandFile->GetRasterBand( 1 );
 
     poSrcBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
-    
+
     eDataType = eDataTypeIn;
 
     if( *pszPole != '\0' )
@@ -171,7 +154,7 @@ RS2RasterBand::~RS2RasterBand()
 
 {
     if( poBandFile != NULL )
-        GDALClose( (GDALRasterBandH) poBandFile );
+        GDALClose( reinterpret_cast<GDALRasterBandH>( poBandFile ) );
 }
 
 /************************************************************************/
@@ -182,18 +165,16 @@ CPLErr RS2RasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                   void * pImage )
 
 {
-    int nRequestYSize;
-    int nRequestXSize;
-
 /* -------------------------------------------------------------------- */
 /*      If the last strip is partial, we need to avoid                  */
 /*      over-requesting.  We also need to initialize the extra part     */
 /*      of the block to zero.                                           */
 /* -------------------------------------------------------------------- */
+    int nRequestYSize;
     if( (nBlockYOff + 1) * nBlockYSize > nRasterYSize )
     {
         nRequestYSize = nRasterYSize - nBlockYOff * nBlockYSize;
-        memset( pImage, 0, (GDALGetDataTypeSize( eDataType ) / 8) * 
+        memset( pImage, 0, (GDALGetDataTypeSize( eDataType ) / 8) *
             nBlockXSize * nBlockYSize );
     }
     else
@@ -205,10 +186,11 @@ CPLErr RS2RasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /*      If the input imagery is tiled, also need to avoid over-        */
 /*      requesting in the X-direction.                                 */
 /* ------------------------------------------------------------------- */
-   if( (nBlockXOff + 1) * nBlockXSize > nRasterXSize )
+    int nRequestXSize;
+    if( (nBlockXOff + 1) * nBlockXSize > nRasterXSize )
     {
         nRequestXSize = nRasterXSize - nBlockXOff * nBlockXSize;
-        memset( pImage, 0, (GDALGetDataTypeSize( eDataType ) / 8) * 
+        memset( pImage, 0, (GDALGetDataTypeSize( eDataType ) / 8) *
             nBlockXSize * nBlockYSize );
     }
     else
@@ -216,12 +198,12 @@ CPLErr RS2RasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         nRequestXSize = nBlockXSize;
     }
     if( eDataType == GDT_CInt16 && poBandFile->GetRasterCount() == 2 )
-        return 
-            poBandFile->RasterIO( GF_Read, 
-                                  nBlockXOff * nBlockXSize, 
+        return
+            poBandFile->RasterIO( GF_Read,
+                                  nBlockXOff * nBlockXSize,
                                   nBlockYOff * nBlockYSize,
                                   nRequestXSize, nRequestYSize,
-                                  pImage, nRequestXSize, nRequestYSize, 
+                                  pImage, nRequestXSize, nRequestYSize,
                                   GDT_Int16,
                                   2, NULL, 4, nBlockXSize * 4, 2, NULL );
 
@@ -230,14 +212,12 @@ CPLErr RS2RasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
     else if( eDataType == GDT_CInt16 && poBandFile->GetRasterCount() == 1 )
     {
-        CPLErr eErr;
-
-        eErr = 
-            poBandFile->RasterIO( GF_Read, 
-                                  nBlockXOff * nBlockXSize, 
+        CPLErr eErr =
+            poBandFile->RasterIO( GF_Read,
+                                  nBlockXOff * nBlockXSize,
                                   nBlockYOff * nBlockYSize,
-                                  nRequestXSize, nRequestYSize, 
-                                  pImage, nRequestXSize, nRequestYSize, 
+                                  nRequestXSize, nRequestYSize,
+                                  pImage, nRequestXSize, nRequestYSize,
                                   GDT_UInt32,
                                   1, NULL, 4, nBlockXSize * 4, 0, NULL );
 
@@ -247,7 +227,7 @@ CPLErr RS2RasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
         /* Then apply 16 bit swap. */
         GDALSwapWords( pImage, 2, nBlockXSize * nBlockYSize * 2, 2 );
-#endif        
+#endif
 
         return eErr;
     }
@@ -257,15 +237,15 @@ CPLErr RS2RasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /*      looks like a 16bit unsigned data too.                           */
 /* -------------------------------------------------------------------- */
     else if( eDataType == GDT_UInt16 )
-        return 
-            poBandFile->RasterIO( GF_Read, 
-                                  nBlockXOff * nBlockXSize, 
+        return
+            poBandFile->RasterIO( GF_Read,
+                                  nBlockXOff * nBlockXSize,
                                   nBlockYOff * nBlockYSize,
-                                  nRequestXSize, nRequestYSize, 
+                                  nRequestXSize, nRequestYSize,
                                   pImage, nRequestXSize, nRequestYSize,
                                   GDT_UInt16,
                                   1, NULL, 2, nBlockXSize * 2, 0, NULL );
-    else if ( eDataType == GDT_Byte ) 
+    else if ( eDataType == GDT_Byte )
         /* Ticket #2104: Support for ScanSAR products */
         return
             poBandFile->RasterIO( GF_Read,
@@ -275,11 +255,9 @@ CPLErr RS2RasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                   pImage, nRequestXSize, nRequestYSize,
                                   GDT_Byte,
                                   1, NULL, 1, nBlockXSize, 0, NULL );
-    else
-    {
-        CPLAssert( FALSE );
-        return CE_Failure;
-    }
+
+    CPLAssert( FALSE );
+    return CE_Failure;
 }
 
 /************************************************************************/
@@ -293,7 +271,7 @@ CPLErr RS2RasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
 class RS2CalibRasterBand : public GDALPamRasterBand {
 private:
-    eCalibration m_eCalib;
+    // eCalibration m_eCalib;
     GDALDataset *m_poBandDataset;
     GDALDataType m_eType; /* data type of data being ingested */
     float *m_nfTable;
@@ -317,23 +295,21 @@ public:
 /* Read the provided LUT in to m_ndTable                                */
 /************************************************************************/
 void RS2CalibRasterBand::ReadLUT() {
-    CPLXMLNode *psLUT;
-    char **papszLUTList;
+    CPLXMLNode *psLUT = CPLParseXMLFile(m_pszLUTFile);
 
-    psLUT = CPLParseXMLFile(m_pszLUTFile);
-    
-    this->m_nfOffset = (float) CPLAtof(CPLGetXMLValue(psLUT, "=lut.offset",
-        "0.0"));
+    this->m_nfOffset = static_cast<float>(
+        CPLAtof( CPLGetXMLValue( psLUT, "=lut.offset", "0.0" ) ) );
 
-    papszLUTList = CSLTokenizeString2( CPLGetXMLValue(psLUT,
+    char **papszLUTList = CSLTokenizeString2( CPLGetXMLValue(psLUT,
         "=lut.gains", ""), " ", CSLT_HONOURSTRINGS);
 
-    this->m_nTableSize = CSLCount(papszLUTList);
+    m_nTableSize = CSLCount(papszLUTList);
 
-    this->m_nfTable = (float *)CPLMalloc(sizeof(float) * this->m_nTableSize);
+    m_nfTable = reinterpret_cast<float *>(
+        CPLMalloc( sizeof(float) * m_nTableSize ) );
 
-    for (int i = 0; i < this->m_nTableSize; i++) {
-        m_nfTable[i] = (float) CPLAtof(papszLUTList[i]);
+    for (int i = 0; i < m_nTableSize; i++) {
+        m_nfTable[i] = static_cast<float>( CPLAtof(papszLUTList[i]) );
     }
 
     CPLDestroyXMLNode(psLUT);
@@ -345,34 +321,33 @@ void RS2CalibRasterBand::ReadLUT() {
 /*                        RS2CalibRasterBand()                          */
 /************************************************************************/
 
-RS2CalibRasterBand::RS2CalibRasterBand( RS2Dataset *poDataset, 
-    const char *pszPolarization, GDALDataType eType, GDALDataset *poBandDataset,
-    eCalibration eCalib, const char *pszLUT )
+RS2CalibRasterBand::RS2CalibRasterBand(
+    RS2Dataset *poDataset, const char *pszPolarization, GDALDataType eType,
+    GDALDataset *poBandDataset, eCalibration /* eCalib */,
+    const char *pszLUT ) :
+    // m_eCalib(eCalib),
+    m_poBandDataset(poBandDataset),
+    m_eType(eType),
+    m_nfTable(NULL),
+    m_nTableSize(0)
 {
-    this->poDS = poDataset;
+    poDS = poDataset;
 
     if (*pszPolarization != '\0') {
-        this->SetMetadataItem( "POLARIMETRIC_INTERP", pszPolarization );
+        SetMetadataItem( "POLARIMETRIC_INTERP", pszPolarization );
     }
 
-    this->m_eType = eType;
-    this->m_poBandDataset = poBandDataset;
-    this->m_eCalib = eCalib;
-    this->m_pszLUTFile = VSIStrdup(pszLUT);
-
-    this->m_nfTable = NULL;
-    this->m_nTableSize = 0;
+    m_pszLUTFile = VSIStrdup(pszLUT);
 
-    if (eType == GDT_CInt16) 
-        this->eDataType = GDT_CFloat32;
+    if (eType == GDT_CInt16)
+        eDataType = GDT_CFloat32;
     else
-        this->eDataType = GDT_Float32;
+        eDataType = GDT_Float32;
 
     GDALRasterBand *poRasterBand = poBandDataset->GetRasterBand( 1 );
     poRasterBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
-    
 
-    this->ReadLUT();
+    ReadLUT();
 }
 
 /************************************************************************/
@@ -380,14 +355,9 @@ RS2CalibRasterBand::RS2CalibRasterBand( RS2Dataset *poDataset,
 /************************************************************************/
 
 RS2CalibRasterBand::~RS2CalibRasterBand() {
-    if (this->m_nfTable != NULL) 
-        CPLFree(this->m_nfTable);
-
-    if (this->m_pszLUTFile != NULL)
-        CPLFree(this->m_pszLUTFile);
-
-    if (this->m_poBandDataset != NULL)
-        GDALClose( this->m_poBandDataset );
+    CPLFree(m_nfTable);
+    CPLFree(m_pszLUTFile);
+    GDALClose( m_poBandDataset );
 }
 
 /************************************************************************/
@@ -397,18 +367,16 @@ RS2CalibRasterBand::~RS2CalibRasterBand() {
 CPLErr RS2CalibRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     void *pImage )
 {
-    CPLErr eErr;
-    int nRequestYSize;
-
 /* -------------------------------------------------------------------- */
 /*      If the last strip is partial, we need to avoid                  */
 /*      over-requesting.  We also need to initialize the extra part     */
 /*      of the block to zero.                                           */
 /* -------------------------------------------------------------------- */
+    int nRequestYSize;
     if( (nBlockYOff + 1) * nBlockYSize > nRasterYSize )
     {
         nRequestYSize = nRasterYSize - nBlockYOff * nBlockYSize;
-        memset( pImage, 0, (GDALGetDataTypeSize( eDataType ) / 8) * 
+        memset( pImage, 0, (GDALGetDataTypeSize( eDataType ) / 8) *
             nBlockXSize * nBlockYSize );
     }
     else
@@ -416,38 +384,40 @@ CPLErr RS2CalibRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         nRequestYSize = nBlockYSize;
     }
 
-    if (this->m_eType == GDT_CInt16) {
-        GInt16 *pnImageTmp;
+    CPLErr eErr;
+    if (m_eType == GDT_CInt16) {
         /* read in complex values */
-        pnImageTmp = (GInt16 *)CPLMalloc(2 * nBlockXSize * nBlockYSize * 
-            GDALGetDataTypeSize( GDT_Int16 ) / 8);
+        GInt16 *pnImageTmp
+            = reinterpret_cast<GInt16 *>(
+                CPLMalloc( 2 * nBlockXSize * nBlockYSize
+                           * GDALGetDataTypeSize( GDT_Int16 ) / 8 ) );
         if (m_poBandDataset->GetRasterCount() == 2) {
-            eErr = m_poBandDataset->RasterIO( GF_Read, 
-                                  nBlockXOff * nBlockXSize, 
+            eErr = m_poBandDataset->RasterIO( GF_Read,
+                                  nBlockXOff * nBlockXSize,
                                   nBlockYOff * nBlockYSize,
                                   nBlockXSize, nRequestYSize,
-                                  pnImageTmp, nBlockXSize, nRequestYSize, 
+                                  pnImageTmp, nBlockXSize, nRequestYSize,
                                   GDT_Int16,
                                   2, NULL, 4, nBlockXSize * 4, 2, NULL );
 
         }
         else {
-            eErr = 
-                m_poBandDataset->RasterIO( GF_Read, 
-                                      nBlockXOff * nBlockXSize, 
+            eErr =
+                m_poBandDataset->RasterIO( GF_Read,
+                                      nBlockXOff * nBlockXSize,
                                       nBlockYOff * nBlockYSize,
-                                      nBlockXSize, nRequestYSize, 
-                                      pnImageTmp, nBlockXSize, nRequestYSize, 
+                                      nBlockXSize, nRequestYSize,
+                                      pnImageTmp, nBlockXSize, nRequestYSize,
                                       GDT_UInt32,
                                       1, NULL, 4, nBlockXSize * 4, 0, NULL );
 
 #ifdef CPL_LSB
-            /* First, undo the 32bit swap. */ 
+            /* First, undo the 32bit swap. */
             GDALSwapWords( pImage, 4, nBlockXSize * nBlockYSize, 4 );
 
             /* Then apply 16 bit swap. */
             GDALSwapWords( pImage, 2, nBlockXSize * nBlockYSize * 2, 2 );
-#endif        
+#endif
         }
 
         /* calibrate the complex values */
@@ -456,23 +426,25 @@ CPLErr RS2CalibRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                 /* calculate pixel offset in memory*/
                 int nPixOff = (2 * (i * nBlockXSize)) + (j * 2);
 
-                ((float *)pImage)[nPixOff] = (float)pnImageTmp[nPixOff]/
-                    (m_nfTable[nBlockXOff + j]);
-                ((float *)pImage)[nPixOff + 1] = 
-                    (float)pnImageTmp[nPixOff + 1]/(m_nfTable[nBlockXOff + j]);
+                reinterpret_cast<float *>( pImage )[nPixOff]
+                    = static_cast<float>( pnImageTmp[nPixOff] )
+                    / (m_nfTable[nBlockXOff + j]);
+                reinterpret_cast<float *>( pImage )[nPixOff + 1] =
+                    static_cast<float>( pnImageTmp[nPixOff + 1] )
+                    / (m_nfTable[nBlockXOff + j]);
             }
         }
         CPLFree(pnImageTmp);
     }
-    else if (this->m_eType == GDT_UInt16) {
-        GUInt16 *pnImageTmp;
+    else if (m_eType == GDT_UInt16) {
         /* read in detected values */
-        pnImageTmp = (GUInt16 *)CPLMalloc(nBlockXSize * nBlockYSize *
-            GDALGetDataTypeSize( GDT_UInt16 ) / 8);
-        eErr = m_poBandDataset->RasterIO( GF_Read, 
-                              nBlockXOff * nBlockXSize, 
+        GUInt16 *pnImageTmp = reinterpret_cast<GUInt16 *>(
+            CPLMalloc(nBlockXSize * nBlockYSize
+                      * GDALGetDataTypeSize( GDT_UInt16 ) / 8) );
+        eErr = m_poBandDataset->RasterIO( GF_Read,
+                              nBlockXOff * nBlockXSize,
                               nBlockYOff * nBlockYSize,
-                              nBlockXSize, nRequestYSize, 
+                              nBlockXSize, nRequestYSize,
                               pnImageTmp, nBlockXSize, nRequestYSize,
                               GDT_UInt16,
                               1, NULL, 2, nBlockXSize * 2, 0, NULL );
@@ -482,17 +454,20 @@ CPLErr RS2CalibRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             for (int j = 0; j < nBlockXSize; j++) {
                 int nPixOff = (i * nBlockXSize) + j;
 
-                ((float *)pImage)[nPixOff] = (((float)pnImageTmp[nPixOff] * 
-                    (float)pnImageTmp[nPixOff]) +
-                    this->m_nfOffset)/m_nfTable[nBlockXOff + j];
+                reinterpret_cast<float *>( pImage )[nPixOff]
+                    = ((static_cast<float>( pnImageTmp[nPixOff] ) *
+                       static_cast<float>( pnImageTmp[nPixOff] ) ) +
+                       m_nfOffset)
+                    / m_nfTable[nBlockXOff + j];
             }
         }
         CPLFree(pnImageTmp);
     } /* Ticket #2104: Support for ScanSAR products */
-    else if (this->m_eType == GDT_Byte) {
-        GByte *pnImageTmp;
-        pnImageTmp = (GByte *)CPLMalloc(nBlockXSize * nBlockYSize *
-            GDALGetDataTypeSize( GDT_Byte ) / 8);
+    else if (m_eType == GDT_Byte) {
+        GByte *pnImageTmp
+            = reinterpret_cast<GByte *>(
+                CPLMalloc(nBlockXSize * nBlockYSize *
+                          GDALGetDataTypeSize( GDT_Byte ) / 8) );
         eErr = m_poBandDataset->RasterIO( GF_Read,
                             nBlockXOff * nBlockXSize,
                             nBlockYOff * nBlockYSize,
@@ -506,9 +481,9 @@ CPLErr RS2CalibRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             for (int j = 0; j < nBlockXSize; j++) {
                 int nPixOff = (i * nBlockXSize) + j;
 
-                ((float *)pImage)[nPixOff] = ((pnImageTmp[nPixOff] *
-                    pnImageTmp[nPixOff]) +
-                    this->m_nfOffset)/m_nfTable[nBlockXOff + j];
+                reinterpret_cast<float *>( pImage )[nPixOff]
+                    = ((pnImageTmp[nPixOff] * pnImageTmp[nPixOff]) +
+                    m_nfOffset)/m_nfTable[nBlockXOff + j];
             }
         }
         CPLFree(pnImageTmp);
@@ -531,24 +506,22 @@ CPLErr RS2CalibRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /*                             RS2Dataset()                             */
 /************************************************************************/
 
-RS2Dataset::RS2Dataset()
+RS2Dataset::RS2Dataset() :
+    psProduct(NULL),
+    nGCPCount(0),
+    pasGCPList(NULL),
+    pszGCPProjection(CPLStrdup("")),
+    papszSubDatasets(NULL),
+    pszProjection(CPLStrdup("")),
+    bHaveGeoTransform(FALSE),
+    papszExtraFiles(NULL)
 {
-    psProduct = NULL;
-
-    nGCPCount = 0;
-    pasGCPList = NULL;
-    pszGCPProjection = CPLStrdup("");
-    pszProjection = CPLStrdup("");
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
-    bHaveGeoTransform = FALSE;
-
-    papszSubDatasets = NULL;
-    papszExtraFiles = NULL;
 }
 
 /************************************************************************/
@@ -571,7 +544,7 @@ RS2Dataset::~RS2Dataset()
     }
 
     CloseDependentDatasets();
-    
+
     CSLDestroy( papszSubDatasets );
     CSLDestroy( papszExtraFiles );
 }
@@ -614,44 +587,41 @@ char **RS2Dataset::GetFileList()
 /*                             Identify()                               */
 /************************************************************************/
 
-int RS2Dataset::Identify( GDALOpenInfo *poOpenInfo ) 
+int RS2Dataset::Identify( GDALOpenInfo *poOpenInfo )
 {
-
-    /* Check for the case where we're trying to read the calibrated data: */
-    if (EQUALN("RADARSAT_2_CALIB:",poOpenInfo->pszFilename,17)) {
-        return 1;
+   /* Check for the case where we're trying to read the calibrated data: */
+    if (STARTS_WITH_CI(poOpenInfo->pszFilename, "RADARSAT_2_CALIB:")) {
+        return TRUE;
     }
 
     /* Check for directory access when there is a product.xml file in the
        directory. */
     if( poOpenInfo->bIsDirectory )
     {
-        VSIStatBufL sStat;
-
-        CPLString osMDFilename = 
+        CPLString osMDFilename =
             CPLFormCIFilename( poOpenInfo->pszFilename, "product.xml", NULL );
-        
+
+        VSIStatBufL sStat;
         if( VSIStatL( osMDFilename, &sStat ) == 0 )
             return TRUE;
-        else
-            return FALSE;
+
+        return FALSE;
     }
 
     /* otherwise, do our normal stuff */
     if( strlen(poOpenInfo->pszFilename) < 11
         || !EQUAL(poOpenInfo->pszFilename + strlen(poOpenInfo->pszFilename)-11,
                   "product.xml") )
-        return 0;
+        return FALSE;
 
     if( poOpenInfo->nHeaderBytes < 100 )
-        return 0;
+        return FALSE;
 
     if( strstr((const char *) poOpenInfo->pabyHeader, "/rs2" ) == NULL
         || strstr((const char *) poOpenInfo->pabyHeader, "<product" ) == NULL)
-        return 0;
-
-    return 1;
+        return FALSE;
 
+    return TRUE;
 }
 
 
@@ -672,26 +642,25 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*        Get subdataset information, if relevant                            */
 /* -------------------------------------------------------------------- */
-    CPLString osMDFilename;
     const char *pszFilename = poOpenInfo->pszFilename;
     eCalibration eCalib = None;
 
-    if (EQUALN("RADARSAT_2_CALIB:",pszFilename,17)) {
+    if (STARTS_WITH_CI(pszFilename, "RADARSAT_2_CALIB:")) {
         pszFilename += 17;
 
-        if (EQUALN("BETA0",pszFilename,5))
+        if (STARTS_WITH_CI(pszFilename, "BETA0"))
             eCalib = Beta0;
-        else if (EQUALN("SIGMA0",pszFilename,6))
+        else if (STARTS_WITH_CI(pszFilename, "SIGMA0"))
             eCalib = Sigma0;
-        else if (EQUALN("GAMMA", pszFilename,5))
+        else if (STARTS_WITH_CI(pszFilename, "GAMMA"))
             eCalib = Gamma;
-        else if (EQUALN("UNCALIB", pszFilename,7))
+        else if (STARTS_WITH_CI(pszFilename, "UNCALIB"))
             eCalib = Uncalib;
         else
             eCalib = None;
 
         /* advance the pointer to the actual filename */
-        while ( *pszFilename != '\0' && *pszFilename != ':' ) 
+        while ( *pszFilename != '\0' && *pszFilename != ':' )
             pszFilename++;
 
         if (*pszFilename == ':')
@@ -704,9 +673,10 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
         	poOpenInfo->bIsDirectory = VSI_ISDIR( sStat.st_mode );
     }
 
+    CPLString osMDFilename;
     if( poOpenInfo->bIsDirectory )
     {
-        osMDFilename = 
+        osMDFilename =
             CPLFormCIFilename( pszFilename, "product.xml", NULL );
     }
     else
@@ -715,34 +685,32 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Ingest the Product.xml file.                                    */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psProduct, *psImageAttributes, *psImageGenerationParameters;
-
-    psProduct = CPLParseXMLFile( osMDFilename );
+    CPLXMLNode *psProduct = CPLParseXMLFile( osMDFilename );
     if( psProduct == NULL )
         return NULL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
         CPLDestroyXMLNode( psProduct );
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The RS2 driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
     }
-    
-    psImageAttributes = CPLGetXMLNode(psProduct, "=product.imageAttributes" );
+
+    CPLXMLNode *psImageAttributes = CPLGetXMLNode(psProduct, "=product.imageAttributes" );
     if( psImageAttributes == NULL )
     {
         CPLDestroyXMLNode( psProduct );
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "Failed to find <imageAttributes> in document." );
         return NULL;
     }
 
-    psImageGenerationParameters = CPLGetXMLNode( psProduct, 
+    CPLXMLNode *psImageGenerationParameters = CPLGetXMLNode( psProduct,
                                                  "=product.imageGenerationParameters" );
     if (psImageGenerationParameters == NULL) {
         CPLDestroyXMLNode( psProduct );
@@ -761,13 +729,13 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Get overall image information.                                  */
 /* -------------------------------------------------------------------- */
-    poDS->nRasterXSize = 
-        atoi(CPLGetXMLValue( psImageAttributes, 
-                             "rasterAttributes.numberOfSamplesPerLine", 
+    poDS->nRasterXSize =
+        atoi(CPLGetXMLValue( psImageAttributes,
+                             "rasterAttributes.numberOfSamplesPerLine",
                              "-1" ));
-    poDS->nRasterYSize = 
-        atoi(CPLGetXMLValue( psImageAttributes, 
-                             "rasterAttributes.numberofLines", 
+    poDS->nRasterYSize =
+        atoi(CPLGetXMLValue( psImageAttributes,
+                             "rasterAttributes.numberofLines",
                              "-1" ));
     if (poDS->nRasterXSize <= 1 || poDS->nRasterYSize <= 1) {
         CPLError( CE_Failure, CPLE_OpenFailed,
@@ -783,50 +751,45 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /*      calibration purposes.                                           */
 /* -------------------------------------------------------------------- */
 
-    char *pszBeta0LUT = NULL;
-    char *pszGammaLUT = NULL;
-    char *pszSigma0LUT = NULL;
-    int bCanCalib = 0;
-
     const char *pszProductType = CPLGetXMLValue( psImageGenerationParameters,
                                                  "generalProcessingInformation.productType",
                                                  "UNK" );
 
     poDS->SetMetadataItem("PRODUCT_TYPE", pszProductType);
 
-    /* the following cases can be assumed to have no LUTs, as per 
+    /* the following cases can be assumed to have no LUTs, as per
      * RN-RP-51-2713, but also common sense
      */
-    if (!(EQUALN(pszProductType, "UNK", 3) || 
-          EQUALN(pszProductType, "SSG", 3) ||
-          EQUALN(pszProductType, "SPG", 3)))
+    bool bCanCalib = false;
+    if (!(STARTS_WITH_CI(pszProductType, "UNK") ||
+          STARTS_WITH_CI(pszProductType, "SSG") ||
+          STARTS_WITH_CI(pszProductType, "SPG")))
     {
-        bCanCalib = 1;
+        bCanCalib = true;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Get dataType (so we can recognise complex data), and the        */
 /*      bitsPerSample.                                                  */
 /* -------------------------------------------------------------------- */
-    GDALDataType eDataType;
-
-    const char *pszDataType = 
-        CPLGetXMLValue( psImageAttributes, "rasterAttributes.dataType", 
+    const char *pszDataType =
+        CPLGetXMLValue( psImageAttributes, "rasterAttributes.dataType",
                         "" );
-    int nBitsPerSample = 
-        atoi( CPLGetXMLValue( psImageAttributes, 
+    const int nBitsPerSample =
+        atoi( CPLGetXMLValue( psImageAttributes,
                               "rasterAttributes.bitsPerSample", "" ) );
 
+    GDALDataType eDataType;
     if( nBitsPerSample == 16 && EQUAL(pszDataType,"Complex") )
         eDataType = GDT_CInt16;
-    else if( nBitsPerSample == 16 && EQUALN(pszDataType,"Mag",3) )
+    else if( nBitsPerSample == 16 && STARTS_WITH_CI(pszDataType, "Mag") )
         eDataType = GDT_UInt16;
-    else if( nBitsPerSample == 8 && EQUALN(pszDataType,"Mag",3) )
+    else if( nBitsPerSample == 8 && STARTS_WITH_CI(pszDataType, "Mag") )
         eDataType = GDT_Byte;
     else
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "dataType=%s, bitsPerSample=%d: not a supported configuration.",
                   pszDataType, nBitsPerSample );
         return NULL;
@@ -844,18 +807,21 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Open each of the data files as a complex band.                  */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psNode;
+    char *pszBeta0LUT = NULL;
+    char *pszGammaLUT = NULL;
+    char *pszSigma0LUT = NULL;
+
     char *pszPath = CPLStrdup(CPLGetPath( osMDFilename ));
-    char *pszBuf;
-    int nFLen = strlen(osMDFilename);
+    const int nFLen = static_cast<int>(strlen(osMDFilename));
 
-    for( psNode = psImageAttributes->psChild;
+    CPLXMLNode *psNode = psImageAttributes->psChild;
+    for( ;
          psNode != NULL;
          psNode = psNode->psNext )
     {
         const char *pszBasename;
-        if( psNode->eType != CXT_Element 
-            || !(EQUAL(psNode->pszValue,"fullResolutionImageData") 
+        if( psNode->eType != CXT_Element
+            || !(EQUAL(psNode->pszValue,"fullResolutionImageData")
                  || EQUAL(psNode->pszValue,"lookupTable")) )
             continue;
 
@@ -864,64 +830,67 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
             const char *pszLUTType = CPLGetXMLValue( psNode,
                                                      "incidenceAngleCorrection", "" );
             const char *pszLUTFile = CPLGetXMLValue( psNode, "", "" );
-            CPLString osLUTFilePath = CPLFormFilename( pszPath, pszLUTFile, 
+            CPLString osLUTFilePath = CPLFormFilename( pszPath, pszLUTFile,
                                                        NULL );
 
-            if (EQUAL(pszLUTType, "")) 
+            if (EQUAL(pszLUTType, ""))
                 continue;
-            else if (EQUAL(pszLUTType, "Beta Nought") && 
-                     IsValidXMLFile(pszPath,pszLUTFile)) 
+            else if (EQUAL(pszLUTType, "Beta Nought") &&
+                     IsValidXMLFile(pszPath,pszLUTFile))
             {
-                poDS->papszExtraFiles = 
+                poDS->papszExtraFiles =
                     CSLAddString( poDS->papszExtraFiles, osLUTFilePath );
 
-                pszBuf = (char *)CPLMalloc(nFLen + 27);
+                const size_t nBufLen = nFLen + 27;
+                char *pszBuf = reinterpret_cast<char *>( CPLMalloc(nBufLen) );
                 pszBeta0LUT = VSIStrdup( pszLUTFile );
                 poDS->SetMetadataItem( "BETA_NOUGHT_LUT", pszLUTFile );
-                
-                sprintf(pszBuf, "RADARSAT_2_CALIB:BETA0:%s", 
+
+                snprintf(pszBuf, nBufLen, "RADARSAT_2_CALIB:BETA0:%s",
                         osMDFilename.c_str() );
-                poDS->papszSubDatasets = CSLSetNameValue( 
+                poDS->papszSubDatasets = CSLSetNameValue(
                     poDS->papszSubDatasets, "SUBDATASET_3_NAME", pszBuf );
-                poDS->papszSubDatasets = CSLSetNameValue( 
-                    poDS->papszSubDatasets, "SUBDATASET_3_DESC", 
+                poDS->papszSubDatasets = CSLSetNameValue(
+                    poDS->papszSubDatasets, "SUBDATASET_3_DESC",
                     "Beta Nought calibrated" );
                 CPLFree(pszBuf);
             }
-            else if (EQUAL(pszLUTType, "Sigma Nought") && 
-                     IsValidXMLFile(pszPath,pszLUTFile)) 
+            else if (EQUAL(pszLUTType, "Sigma Nought") &&
+                     IsValidXMLFile(pszPath,pszLUTFile))
             {
-                poDS->papszExtraFiles = 
+                poDS->papszExtraFiles =
                     CSLAddString( poDS->papszExtraFiles, osLUTFilePath );
 
-                pszBuf = (char *)CPLMalloc(nFLen + 27);
+                const size_t nBufLen = nFLen + 27;
+                char *pszBuf = reinterpret_cast<char *>( CPLMalloc(nBufLen) );
                 pszSigma0LUT = VSIStrdup( pszLUTFile );
                 poDS->SetMetadataItem( "SIGMA_NOUGHT_LUT", pszLUTFile );
 
-                sprintf(pszBuf, "RADARSAT_2_CALIB:SIGMA0:%s", 
+                snprintf(pszBuf, nBufLen,"RADARSAT_2_CALIB:SIGMA0:%s",
                         osMDFilename.c_str() );
-                poDS->papszSubDatasets = CSLSetNameValue( 
+                poDS->papszSubDatasets = CSLSetNameValue(
                     poDS->papszSubDatasets, "SUBDATASET_2_NAME", pszBuf );
-                poDS->papszSubDatasets = CSLSetNameValue( 
-                    poDS->papszSubDatasets, "SUBDATASET_2_DESC", 
+                poDS->papszSubDatasets = CSLSetNameValue(
+                    poDS->papszSubDatasets, "SUBDATASET_2_DESC",
                     "Sigma Nought calibrated" );
                 CPLFree(pszBuf);
             }
-            else if (EQUAL(pszLUTType, "Gamma") && 
-                     IsValidXMLFile(pszPath,pszLUTFile)) 
+            else if (EQUAL(pszLUTType, "Gamma") &&
+                     IsValidXMLFile(pszPath,pszLUTFile))
             {
-                poDS->papszExtraFiles = 
+                poDS->papszExtraFiles =
                     CSLAddString( poDS->papszExtraFiles, osLUTFilePath );
 
-                pszBuf = (char *)CPLMalloc(nFLen + 27);
+                const size_t nBufLen = nFLen + 27;
+                char *pszBuf = reinterpret_cast<char *>( CPLMalloc(nBufLen) );
                 pszGammaLUT = VSIStrdup( pszLUTFile );
                 poDS->SetMetadataItem( "GAMMA_LUT", pszLUTFile );
-                sprintf(pszBuf, "RADARSAT_2_CALIB:GAMMA:%s", 
+                snprintf(pszBuf, nBufLen,"RADARSAT_2_CALIB:GAMMA:%s",
                         osMDFilename.c_str());
-                poDS->papszSubDatasets = CSLSetNameValue( 
+                poDS->papszSubDatasets = CSLSetNameValue(
                     poDS->papszSubDatasets, "SUBDATASET_4_NAME", pszBuf );
-                poDS->papszSubDatasets = CSLSetNameValue( 
-                    poDS->papszSubDatasets, "SUBDATASET_4_DESC", 
+                poDS->papszSubDatasets = CSLSetNameValue(
+                    poDS->papszSubDatasets, "SUBDATASET_4_DESC",
                     "Gamma calibrated" );
                 CPLFree(pszBuf);
             }
@@ -938,15 +907,14 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Form full filename (path of product.xml + basename).            */
 /* -------------------------------------------------------------------- */
-        char *pszFullname = 
+        char *pszFullname =
             CPLStrdup(CPLFormFilename( pszPath, pszBasename, NULL ));
 
 /* -------------------------------------------------------------------- */
 /*      Try and open the file.                                          */
 /* -------------------------------------------------------------------- */
-        GDALDataset *poBandFile;
-
-        poBandFile = (GDALDataset *) GDALOpen( pszFullname, GA_ReadOnly );
+        GDALDataset *poBandFile = reinterpret_cast<GDALDataset *>(
+            GDALOpen( pszFullname, GA_ReadOnly ) );
         if( poBandFile == NULL )
         {
             CPLFree(pszFullname);
@@ -954,11 +922,11 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
         }
         if (poBandFile->GetRasterCount() == 0)
         {
-            GDALClose( (GDALRasterBandH) poBandFile );
+            GDALClose( reinterpret_cast<GDALRasterBandH>( poBandFile ) );
             CPLFree(pszFullname);
             continue;
         }
-        
+
         poDS->papszExtraFiles = CSLAddString( poDS->papszExtraFiles,
                                               pszFullname );
 
@@ -966,11 +934,11 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Create the band.                                                */
 /* -------------------------------------------------------------------- */
         if (eCalib == None || eCalib == Uncalib) {
-            RS2RasterBand *poBand;
-            poBand = new RS2RasterBand( poDS, eDataType,
-                                        CPLGetXMLValue( psNode, "pole", "" ), 
-                                        poBandFile ); 
-    
+            RS2RasterBand *poBand
+                = new RS2RasterBand( poDS, eDataType,
+                                     CPLGetXMLValue( psNode, "pole", "" ),
+                                     poBandFile );
+
             poDS->SetBand( poDS->GetRasterCount() + 1, poBand );
         }
         else {
@@ -989,10 +957,10 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
                 /* we should bomb gracefully... */
                 pszLUT = pszSigma0LUT;
             }
-            RS2CalibRasterBand *poBand;
-            poBand = new RS2CalibRasterBand( poDS, CPLGetXMLValue( psNode,
-                                                                   "pole", "" ), eDataType, poBandFile, eCalib, 
-                                             CPLFormFilename(pszPath, pszLUT, NULL) );
+            RS2CalibRasterBand *poBand
+                = new RS2CalibRasterBand( poDS, CPLGetXMLValue( psNode,
+                                                                "pole", "" ), eDataType, poBandFile, eCalib,
+                                          CPLFormFilename(pszPath, pszLUT, NULL) );
             poDS->SetBand( poDS->GetRasterCount() + 1, poBand );
         }
 
@@ -1000,9 +968,9 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
     if (poDS->papszSubDatasets != NULL && eCalib == None) {
-        char *pszBuf;
-        pszBuf = (char *)CPLMalloc(nFLen + 28);
-        sprintf(pszBuf, "RADARSAT_2_CALIB:UNCALIB:%s", 
+        const size_t nBufLen = nFLen + 28;
+        char *pszBuf = reinterpret_cast<char *>( CPLMalloc(nBufLen) );
+        snprintf(pszBuf, nBufLen, "RADARSAT_2_CALIB:UNCALIB:%s",
                 osMDFilename.c_str() );
         poDS->papszSubDatasets = CSLSetNameValue( poDS->papszSubDatasets,
                                                   "SUBDATASET_1_NAME", pszBuf );
@@ -1020,20 +988,18 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 
     if ( poDS->GetRasterCount() == 4 && (eDataType == GDT_CInt16 ||
-                                         eDataType == GDT_CFloat32) ) 
+                                         eDataType == GDT_CFloat32) )
     {
         poDS->SetMetadataItem( "MATRIX_REPRESENTATION", "SCATTERING" );
     }
- 
+
 /* -------------------------------------------------------------------- */
 /*      Collect a few useful metadata items                             */
 /* -------------------------------------------------------------------- */
 
     CPLXMLNode *psSourceAttrs = CPLGetXMLNode( psProduct,
                                                "=product.sourceAttributes");
-    const char *pszItem;
-
-    pszItem = CPLGetXMLValue( psSourceAttrs,
+    const char *pszItem = CPLGetXMLValue( psSourceAttrs,
                               "satellite", "" );
     poDS->SetMetadataItem( "SATELLITE_IDENTIFIER", pszItem );
 
@@ -1068,7 +1034,7 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
 
     if (psSarProcessingInformation != NULL) {
         /* Get incidence angle information */
-        pszItem = CPLGetXMLValue( psSarProcessingInformation, 
+        pszItem = CPLGetXMLValue( psSarProcessingInformation,
                                   "sarProcessingInformation.incidenceAngleNearRange", "UNK" );
         poDS->SetMetadataItem( "NEAR_RANGE_INCIDENCE_ANGLE", pszItem );
 
@@ -1107,12 +1073,12 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /*--------------------------------------------------------------------- */
 /*      Collect Map projection/Geotransform information, if present     */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psMapProjection = 
+    CPLXMLNode *psMapProjection =
         CPLGetXMLNode( psImageAttributes,
                        "geographicInformation.mapProjection" );
 
     if ( psMapProjection != NULL ) {
-        CPLXMLNode *psPos = 
+        CPLXMLNode *psPos =
             CPLGetXMLNode( psMapProjection, "positioningInformation" );
 
         pszItem = CPLGetXMLValue( psMapProjection,
@@ -1132,50 +1098,47 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->SetMetadataItem( "SATELLITE_HEADING", pszItem );
 
         if (psPos != NULL) {
-            double testx, testy, br_x, br_y, tl_x, tl_y, tr_x, tr_y, 
-                bl_x, bl_y; 
-
-            tl_x = CPLStrtod(CPLGetXMLValue( psPos, 
-                                          "upperLeftCorner.mapCoordinate.easting", "0.0" ), NULL);
-            tl_y = CPLStrtod(CPLGetXMLValue( psPos, 
-                                          "upperLeftCorner.mapCoordinate.northing", "0.0" ), NULL);
-            bl_x = CPLStrtod(CPLGetXMLValue( psPos, 
-                                          "lowerLeftCorner.mapCoordinate.easting", "0.0" ), NULL);
-            bl_y = CPLStrtod(CPLGetXMLValue( psPos, 
-                                          "lowerLeftCorner.mapCoordinate.northing", "0.0" ), NULL);
-            tr_x = CPLStrtod(CPLGetXMLValue( psPos, 
-                                          "upperRightCorner.mapCoordinate.easting", "0.0" ), NULL);
-            tr_y = CPLStrtod(CPLGetXMLValue( psPos, 
-                                          "upperRightCorner.mapCoordinate.northing", "0.0" ), NULL);
+            const double tl_x = CPLStrtod(CPLGetXMLValue(
+                psPos, "upperLeftCorner.mapCoordinate.easting", "0.0" ), NULL);
+            const double tl_y = CPLStrtod(CPLGetXMLValue(
+                psPos, "upperLeftCorner.mapCoordinate.northing", "0.0" ), NULL);
+            const double bl_x = CPLStrtod(CPLGetXMLValue(
+                psPos, "lowerLeftCorner.mapCoordinate.easting", "0.0" ), NULL);
+            const double bl_y = CPLStrtod(CPLGetXMLValue(
+                psPos, "lowerLeftCorner.mapCoordinate.northing", "0.0" ), NULL);
+            const double tr_x = CPLStrtod(CPLGetXMLValue(
+                psPos, "upperRightCorner.mapCoordinate.easting", "0.0" ), NULL);
+            const double tr_y = CPLStrtod(CPLGetXMLValue(
+                psPos, "upperRightCorner.mapCoordinate.northing", "0.0" ), NULL);
             poDS->adfGeoTransform[1] = (tr_x - tl_x)/(poDS->nRasterXSize - 1);
             poDS->adfGeoTransform[4] = (tr_y - tl_y)/(poDS->nRasterXSize - 1);
             poDS->adfGeoTransform[2] = (bl_x - tl_x)/(poDS->nRasterYSize - 1);
             poDS->adfGeoTransform[5] = (bl_y - tl_y)/(poDS->nRasterYSize - 1);
-            poDS->adfGeoTransform[0] = (tl_x - 0.5*poDS->adfGeoTransform[1] 
+            poDS->adfGeoTransform[0] = (tl_x - 0.5*poDS->adfGeoTransform[1]
                                         - 0.5*poDS->adfGeoTransform[2]);
-            poDS->adfGeoTransform[3] = (tl_y - 0.5*poDS->adfGeoTransform[4] 
+            poDS->adfGeoTransform[3] = (tl_y - 0.5*poDS->adfGeoTransform[4]
                                         - 0.5*poDS->adfGeoTransform[5]);
 
             /* Use bottom right pixel to test geotransform */
-            br_x = CPLStrtod(CPLGetXMLValue( psPos, 
-                                          "lowerRightCorner.mapCoordinate.easting", "0.0"  ), NULL);
-            br_y = CPLStrtod(CPLGetXMLValue( psPos, 
-                                          "lowerRightCorner.mapCoordinate.northing", "0.0"  ), NULL);
-            testx = poDS->adfGeoTransform[0] + poDS->adfGeoTransform[1] *
+            const double br_x = CPLStrtod(CPLGetXMLValue(
+                psPos, "lowerRightCorner.mapCoordinate.easting", "0.0"  ), NULL);
+            const double br_y = CPLStrtod(CPLGetXMLValue(
+                psPos, "lowerRightCorner.mapCoordinate.northing", "0.0"  ), NULL);
+            const double testx = poDS->adfGeoTransform[0] + poDS->adfGeoTransform[1] *
                 (poDS->nRasterXSize - 0.5) + poDS->adfGeoTransform[2] *
                 (poDS->nRasterYSize - 0.5);
-            testy = poDS->adfGeoTransform[3] + poDS->adfGeoTransform[4] *
+            const double testy = poDS->adfGeoTransform[3] + poDS->adfGeoTransform[4] *
                 (poDS->nRasterXSize - 0.5) + poDS->adfGeoTransform[5] *
                 (poDS->nRasterYSize - 0.5);
 
-            /* Give 1/4 pixel numerical error leeway in calculating location 
+            /* Give 1/4 pixel numerical error leeway in calculating location
                based on affine transform */
-            if ( (fabs(testx - br_x) > 
-                  fabs(0.25*(poDS->adfGeoTransform[1]+poDS->adfGeoTransform[2]))) 
-                 || (fabs(testy - br_y) > fabs(0.25*(poDS->adfGeoTransform[4] + 
+            if ( (fabs(testx - br_x) >
+                  fabs(0.25*(poDS->adfGeoTransform[1]+poDS->adfGeoTransform[2])))
+                 || (fabs(testy - br_y) > fabs(0.25*(poDS->adfGeoTransform[4] +
                                                      poDS->adfGeoTransform[5]))) )
             {
-                CPLError( CE_Warning, CPLE_AppDefined, 
+                CPLError( CE_Warning, CPLE_AppDefined,
                           "Unexpected error in calculating affine transform: "
                           "corner coordinates inconsistent.");
             }
@@ -1183,29 +1146,26 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
                 poDS->bHaveGeoTransform = TRUE;
 
         }
-        
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Collect Projection String Information                           */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psEllipsoid = 
+    CPLXMLNode *psEllipsoid =
         CPLGetXMLNode( psImageAttributes,
                        "geographicInformation.referenceEllipsoidParameters" );
 
     if ( psEllipsoid != NULL ) {
-        const char *pszEllipsoidName;
-        double minor_axis, major_axis, inv_flattening;
         OGRSpatialReference oLL, oPrj;
 
-        pszEllipsoidName = CPLGetXMLValue( psEllipsoid, "ellipsoidName", "" );
-        minor_axis = CPLAtof(CPLGetXMLValue( psEllipsoid, "semiMinorAxis", 
-                                          "0.0" ));
-        major_axis = CPLAtof(CPLGetXMLValue( psEllipsoid, "semiMajorAxis", 
-                                          "0.0" ));
+        const char *pszEllipsoidName
+            = CPLGetXMLValue( psEllipsoid, "ellipsoidName", "" );
+        double minor_axis
+            = CPLAtof(CPLGetXMLValue( psEllipsoid, "semiMinorAxis", "0.0" ));
+        double major_axis
+            = CPLAtof(CPLGetXMLValue( psEllipsoid, "semiMajorAxis", "0.0" ));
 
-        if ( EQUAL(pszEllipsoidName, "") || ( minor_axis == 0.0 ) || 
+        if ( EQUAL(pszEllipsoidName, "") || ( minor_axis == 0.0 ) ||
              ( major_axis == 0.0 ) )
         {
             CPLError(CE_Warning,CPLE_AppDefined,"Warning- incomplete"
@@ -1218,17 +1178,17 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
             oPrj.SetWellKnownGeogCS( "WGS84" );
         }
         else {
-            inv_flattening = major_axis/(major_axis - minor_axis);
-            oLL.SetGeogCS( "","",pszEllipsoidName, major_axis, 
+            const double inv_flattening = major_axis/(major_axis - minor_axis);
+            oLL.SetGeogCS( "","",pszEllipsoidName, major_axis,
                            inv_flattening);
-            oPrj.SetGeogCS( "","",pszEllipsoidName, major_axis, 
+            oPrj.SetGeogCS( "","",pszEllipsoidName, major_axis,
                             inv_flattening);
         }
-   
+
         if ( psMapProjection != NULL ) {
             const char *pszProj = CPLGetXMLValue(
                 psMapProjection, "mapProjectionDescriptor", "" );
-            bool bUseProjInfo = FALSE;
+            bool bUseProjInfo = false;
 
             CPLXMLNode *psUtmParams =
                 CPLGetXMLNode( psMapProjection,
@@ -1239,71 +1199,67 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
                                "nspProjectionParameters" );
 
             if ((psUtmParams != NULL) && poDS->bHaveGeoTransform ) {
-                const char *pszHemisphere;
-                int utmZone;
                 /* double origEasting, origNorthing; */
-                bool bNorth = TRUE;
+                bool bNorth = true;
 
-                utmZone = atoi(CPLGetXMLValue( psUtmParams, "utmZone", "" ));
-                pszHemisphere = CPLGetXMLValue( psUtmParams,
-                                                "hemisphere", "" );
+                const int utmZone = atoi(CPLGetXMLValue( psUtmParams, "utmZone", "" ));
+                const char *pszHemisphere = CPLGetXMLValue(
+                    psUtmParams, "hemisphere", "" );
 #if 0
-                origEasting = CPLStrtod(CPLGetXMLValue( psUtmParams,
-                                                     "mapOriginFalseEasting", "0.0" ), NULL);
-                origNorthing = CPLStrtod(CPLGetXMLValue( psUtmParams,
-                                                      "mapOriginFalseNorthing", "0.0" ), NULL);
+                origEasting = CPLStrtod(CPLGetXMLValue(
+                    psUtmParams, "mapOriginFalseEasting", "0.0" ), NULL);
+                origNorthing = CPLStrtod(CPLGetXMLValue(
+                    psUtmParams, "mapOriginFalseNorthing", "0.0" ), NULL);
 #endif
-                if ( EQUALN(pszHemisphere,"southern",8) )
+                if ( STARTS_WITH_CI(pszHemisphere, "southern") )
                     bNorth = FALSE;
 
-                if (EQUALN(pszProj,"UTM",3)) {
+                if (STARTS_WITH_CI(pszProj, "UTM")) {
                     oPrj.SetUTM(utmZone, bNorth);
-                    bUseProjInfo = TRUE;
+                    bUseProjInfo = true;
                 }
             }
             else if ((psNspParams != NULL) && poDS->bHaveGeoTransform) {
-                double origEasting, origNorthing, copLong, copLat, sP1, sP2;
-
-                origEasting = CPLStrtod(CPLGetXMLValue( psNspParams, 
-                                                     "mapOriginFalseEasting", "0.0" ), NULL);
-                origNorthing = CPLStrtod(CPLGetXMLValue( psNspParams, 
-                                                      "mapOriginFalseNorthing", "0.0" ), NULL);
-                copLong = CPLStrtod(CPLGetXMLValue( psNspParams,  
-                                                 "centerOfProjectionLongitude", "0.0" ), NULL);
-                copLat = CPLStrtod(CPLGetXMLValue( psNspParams, 
-                                                "centerOfProjectionLatitude", "0.0" ), NULL);
-                sP1 = CPLStrtod(CPLGetXMLValue( psNspParams, 
+                const double origEasting = CPLStrtod(CPLGetXMLValue(
+                    psNspParams, "mapOriginFalseEasting", "0.0" ), NULL);
+                const double origNorthing = CPLStrtod(CPLGetXMLValue(
+                    psNspParams, "mapOriginFalseNorthing", "0.0" ), NULL);
+                const double copLong = CPLStrtod(CPLGetXMLValue(
+                    psNspParams, "centerOfProjectionLongitude", "0.0" ), NULL);
+                const double copLat = CPLStrtod(CPLGetXMLValue(
+                    psNspParams, "centerOfProjectionLatitude", "0.0" ), NULL);
+                const double sP1 = CPLStrtod(CPLGetXMLValue( psNspParams,
                                              "standardParallels1", "0.0" ), NULL);
-                sP2 = CPLStrtod(CPLGetXMLValue( psNspParams, 
+                const double sP2 = CPLStrtod(CPLGetXMLValue( psNspParams,
                                              "standardParallels2", "0.0" ), NULL);
 
-                if (EQUALN(pszProj,"ARC",3)) {
+                if (STARTS_WITH_CI(pszProj, "ARC")) {
                     /* Albers Conical Equal Area */
-                    oPrj.SetACEA(sP1, sP2, copLat, copLong, origEasting, 
+                    oPrj.SetACEA(sP1, sP2, copLat, copLong, origEasting,
                                  origNorthing);
-                    bUseProjInfo = TRUE;
+                    bUseProjInfo = true;
                 }
-                else if (EQUALN(pszProj,"LCC",3)) {
+                else if (STARTS_WITH_CI(pszProj, "LCC")) {
                     /* Lambert Conformal Conic */
-                    oPrj.SetLCC(sP1, sP2, copLat, copLong, origEasting, 
+                    oPrj.SetLCC(sP1, sP2, copLat, copLong, origEasting,
                                 origNorthing);
-                    bUseProjInfo = TRUE;
+                    bUseProjInfo = true;
                 }
-                else if (EQUALN(pszProj,"STPL",3)) {
+                else if (STARTS_WITH_CI(pszProj,"STPL")) {
                     /* State Plate
-                       ASSUMPTIONS: "zone" in product.xml matches USGS 
-                       definition as expected by ogr spatial reference; NAD83 
+                       ASSUMPTIONS: "zone" in product.xml matches USGS
+                       definition as expected by ogr spatial reference; NAD83
                        zones (versus NAD27) are assumed. */
 
-                    int nSPZone = atoi(CPLGetXMLValue( psNspParams, 
-                                                       "zone", "1" ));
+                    const int nSPZone = atoi(CPLGetXMLValue( psNspParams,
+                                                             "zone", "1" ));
 
                     oPrj.SetStatePlane( nSPZone, TRUE, NULL, 0.0 );
-                    bUseProjInfo = TRUE;
+                    bUseProjInfo = true;
                 }
             }
 
-            if (bUseProjInfo) {       
+            if (bUseProjInfo) {
                 CPLFree( poDS->pszProjection );
                 poDS->pszProjection = NULL;
                 oPrj.exportToWkt( &(poDS->pszProjection) );
@@ -1318,20 +1274,19 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
         CPLFree( poDS->pszGCPProjection );
         poDS->pszGCPProjection = NULL;
         oLL.exportToWkt( &(poDS->pszGCPProjection) );
-
     }
 
 /* -------------------------------------------------------------------- */
 /*      Collect GCPs.                                                   */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psGeoGrid = 
-        CPLGetXMLNode( psImageAttributes, 
+    CPLXMLNode *psGeoGrid =
+        CPLGetXMLNode( psImageAttributes,
                        "geographicInformation.geolocationGrid" );
 
     if( psGeoGrid != NULL ) {
         /* count GCPs */
         poDS->nGCPCount = 0;
-        
+
         for( psNode = psGeoGrid->psChild; psNode != NULL;
              psNode = psNode->psNext )
         {
@@ -1339,34 +1294,34 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
                 poDS->nGCPCount++ ;
         }
 
-        poDS->pasGCPList = (GDAL_GCP *) 
-            CPLCalloc(sizeof(GDAL_GCP),poDS->nGCPCount);
-        
+        poDS->pasGCPList = reinterpret_cast<GDAL_GCP *>(
+            CPLCalloc( sizeof(GDAL_GCP), poDS->nGCPCount ) );
+
         poDS->nGCPCount = 0;
-        
+
         for( psNode = psGeoGrid->psChild; psNode != NULL;
              psNode = psNode->psNext )
         {
-            char    szID[32];
             GDAL_GCP   *psGCP = poDS->pasGCPList + poDS->nGCPCount;
-            
+
             if( !EQUAL(psNode->pszValue,"imageTiePoint") )
                 continue;
 
             poDS->nGCPCount++ ;
 
-            sprintf( szID, "%d", poDS->nGCPCount );
+            char szID[32];
+            snprintf( szID, sizeof(szID), "%d", poDS->nGCPCount );
             psGCP->pszId = CPLStrdup( szID );
             psGCP->pszInfo = CPLStrdup("");
-            psGCP->dfGCPPixel = 
+            psGCP->dfGCPPixel =
                 CPLAtof(CPLGetXMLValue(psNode,"imageCoordinate.pixel","0"));
-            psGCP->dfGCPLine = 
+            psGCP->dfGCPLine =
                 CPLAtof(CPLGetXMLValue(psNode,"imageCoordinate.line","0"));
-            psGCP->dfGCPX = 
+            psGCP->dfGCPX =
                 CPLAtof(CPLGetXMLValue(psNode,"geodeticCoordinate.longitude",""));
-            psGCP->dfGCPY = 
+            psGCP->dfGCPY =
                 CPLAtof(CPLGetXMLValue(psNode,"geodeticCoordinate.latitude",""));
-            psGCP->dfGCPZ = 
+            psGCP->dfGCPZ =
                 CPLAtof(CPLGetXMLValue(psNode,"geodeticCoordinate.height",""));
         }
     }
@@ -1383,11 +1338,11 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
 
     switch (eCalib) {
       case Sigma0:
-        osDescription.Printf( "RADARSAT_2_CALIB:SIGMA0:%s", 
+        osDescription.Printf( "RADARSAT_2_CALIB:SIGMA0:%s",
                               osMDFilename.c_str() );
         break;
       case Beta0:
-        osDescription.Printf( "RADARSAT_2_CALIB:BETA0:%s", 
+        osDescription.Printf( "RADARSAT_2_CALIB:BETA0:%s",
                               osMDFilename.c_str());
         break;
       case Gamma:
@@ -1395,7 +1350,7 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
                               osMDFilename.c_str() );
         break;
       case Uncalib:
-        osDescription.Printf( "RADARSAT_2_CALIB:UNCALIB:%s", 
+        osDescription.Printf( "RADARSAT_2_CALIB:UNCALIB:%s",
                               osMDFilename.c_str() );
         break;
       default:
@@ -1403,7 +1358,7 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
     if( eCalib != None )
-        poDS->papszExtraFiles = 
+        poDS->papszExtraFiles =
             CSLAddString( poDS->papszExtraFiles, osMDFilename );
 
 /* -------------------------------------------------------------------- */
@@ -1472,11 +1427,11 @@ const char *RS2Dataset::GetProjectionRef()
 CPLErr RS2Dataset::GetGeoTransform( double * padfTransform )
 
 {
-    memcpy( padfTransform,  adfGeoTransform, sizeof(double) * 6 ); 
+    memcpy( padfTransform,  adfGeoTransform, sizeof(double) * 6 );
 
     if (bHaveGeoTransform)
         return( CE_None );
-   
+
     return( CE_Failure );
 }
 
@@ -1499,11 +1454,11 @@ char **RS2Dataset::GetMetadataDomainList()
 char **RS2Dataset::GetMetadata( const char *pszDomain )
 
 {
-    if( pszDomain != NULL && EQUALN( pszDomain, "SUBDATASETS", 11 ) &&
+    if( pszDomain != NULL && STARTS_WITH_CI(pszDomain, "SUBDATASETS") &&
         papszSubDatasets != NULL)
         return papszSubDatasets;
-    else
-        return GDALDataset::GetMetadata( pszDomain );
+
+    return GDALDataset::GetMetadata( pszDomain );
 }
 
 /************************************************************************/
@@ -1513,22 +1468,19 @@ char **RS2Dataset::GetMetadata( const char *pszDomain )
 void GDALRegister_RS2()
 
 {
-    GDALDriver *poDriver;
+    if( GDALGetDriverByName( "RS2" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "RS2" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "RS2" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "RadarSat 2 XML Product" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_rs2.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
-
-        poDriver->pfnOpen = RS2Dataset::Open;
-        poDriver->pfnIdentify = RS2Dataset::Identify;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "RS2" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "RadarSat 2 XML Product" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_rs2.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
+
+    poDriver->pfnOpen = RS2Dataset::Open;
+    poDriver->pfnIdentify = RS2Dataset::Identify;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/safe/GNUmakefile b/frmts/safe/GNUmakefile
new file mode 100644
index 0000000..32f948e
--- /dev/null
+++ b/frmts/safe/GNUmakefile
@@ -0,0 +1,13 @@
+
+include ../../GDALmake.opt
+
+OBJ	=	safedataset.o
+
+
+
+default:	$(OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
diff --git a/frmts/safe/frmt_safe.html b/frmts/safe/frmt_safe.html
new file mode 100644
index 0000000..f9b1dc0
--- /dev/null
+++ b/frmts/safe/frmt_safe.html
@@ -0,0 +1,49 @@
+<html>
+<head>
+<title>SAFE -- Sentinel-1 SAFE XML Product</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>SAFE -- Sentinel-1 SAFE XML Product</h1>
+
+<p>Driver for Sentinel products.
+    Currently supports only Sentinel-1 SAR products. See also the <a href="frmt_sentinel2.html">GDAL Sentinel-2 driver</a></p>
+
+<p>SENTINEL data products are distributed using a SENTINEL-specific variation of
+the Standard Archive Format for Europe (SAFE) format specification.
+The SAFE format has been designed to act as a common format for archiving
+and conveying data within ESA Earth Observation archiving facilities. </p>
+
+<p>The SAFE driver will be used if the manifest.safe or
+the containing directory is selected, and it can treat all the imagery as
+one consistent dataset.</p>
+
+<p>The SAFE driver also reads geolocation grid points from the metadata
+and represents them as GCPs on the dataset. <p>
+
+<p>ESA will be distributing other satellite datasets in this format;
+however, at this time this driver only supports specific Sentinel-1 SAR products.
+All other will be ignored, or result in various runtime errors.</p>
+
+<h2>Multiple measurements</h2>
+<p>If the product contains multiple measurements (for example multiple
+polarizations), each one is available as a raster band</p>
+
+
+<h2>Data Calibration</h2>
+<p>Currently the driver does not apply calibration information.</p>
+
+<h2>See Also:</h2>
+
+<ul>
+    <li><a href="https://sentinel.esa.int/web/sentinel/user-guides/sentinel-1-sar/data-formats/sar-formats">SAR Formats (ESA Sentinel Online)</a></li>
+
+    <li><a href="https://sentinel.esa.int/web/sentinel/user-guides/sentinel-1-sar/data-formats/safe-specification">SAFE Specification (ESA Sentinel Online)</a></li>
+
+    <li><a href="frmt_sentinel2.html">GDAL Sentinel-2 driver</a></li>
+</ul>
+
+
+</body>
+</html>
diff --git a/frmts/safe/makefile.vc b/frmts/safe/makefile.vc
new file mode 100644
index 0000000..c65015c
--- /dev/null
+++ b/frmts/safe/makefile.vc
@@ -0,0 +1,13 @@
+
+OBJ = safedataset.obj
+
+GDAL_ROOT	=	..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+default:	$(OBJ)
+	xcopy /D  /Y *.obj ..\o
+
+clean:
+	-del *.obj
+
diff --git a/frmts/safe/safedataset.cpp b/frmts/safe/safedataset.cpp
new file mode 100644
index 0000000..bea1cc5
--- /dev/null
+++ b/frmts/safe/safedataset.cpp
@@ -0,0 +1,1096 @@
+/******************************************************************************
+ * $Id: safedataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
+ *
+ * Project:  Sentinel SAFE products
+ * Purpose:  Sentinel Products (manifest.safe) driver
+ * Author:   Delfim Rego, delfimrego at gmail.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Delfim Rego <delfimrego at gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_minixml.h"
+#include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
+#include "ogr_spatialref.h"
+
+CPL_CVSID("$Id: safedataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+
+/************************************************************************/
+/* ==================================================================== */
+/*                               SAFEDataset                            */
+/* ==================================================================== */
+/************************************************************************/
+
+class SAFEDataset : public GDALPamDataset
+{
+    CPLXMLNode *psManifest;
+
+    int           nGCPCount;
+    GDAL_GCP     *pasGCPList;
+    char         *pszGCPProjection;
+    char        **papszSubDatasets;
+    char         *pszProjection;
+    double        adfGeoTransform[6];
+    bool          bHaveGeoTransform;
+
+    char        **papszExtraFiles;
+
+  protected:
+    virtual int         CloseDependentDatasets();
+
+    static CPLXMLNode * GetMetaDataObject(CPLXMLNode *, const char *);
+
+    static CPLXMLNode * GetDataObject(CPLXMLNode *, const char *);
+    static CPLXMLNode * GetDataObject(CPLXMLNode *, CPLXMLNode *, const char *);
+
+  public:
+            SAFEDataset();
+           ~SAFEDataset();
+
+    virtual int    GetGCPCount();
+    virtual const char *GetGCPProjection();
+    virtual const GDAL_GCP *GetGCPs();
+
+    virtual const char *GetProjectionRef(void);
+    virtual CPLErr GetGeoTransform( double * );
+
+#ifdef notdef
+    virtual char      **GetMetadataDomainList();
+    virtual char **GetMetadata( const char * pszDomain = "" );
+#endif
+    virtual char **GetFileList(void);
+
+    static GDALDataset *Open( GDALOpenInfo * );
+    static int Identify( GDALOpenInfo * );
+
+    CPLXMLNode *GetManifest() { return psManifest; }
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                    SAFERasterBand                                    */
+/* ==================================================================== */
+/************************************************************************/
+
+class SAFERasterBand : public GDALPamRasterBand
+{
+    GDALDataset     *poBandFile;
+
+  public:
+            SAFERasterBand( SAFEDataset *poDSIn,
+                               GDALDataType eDataTypeIn,
+                               const char *pszPole,
+                               GDALDataset *poBandFile );
+    virtual     ~SAFERasterBand();
+
+    virtual CPLErr IReadBlock( int, int, void * );
+
+    static GDALDataset *Open( GDALOpenInfo * );
+};
+
+/************************************************************************/
+/*                            SAFERasterBand                            */
+/************************************************************************/
+
+SAFERasterBand::SAFERasterBand( SAFEDataset *poDSIn,
+                              GDALDataType eDataTypeIn,
+                              const char *pszPolarisation,
+                              GDALDataset *poBandFileIn )
+
+{
+    poDS = poDSIn;
+    poBandFile = poBandFileIn;
+
+    GDALRasterBand *poSrcBand = poBandFile->GetRasterBand( 1 );
+
+    poSrcBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
+
+    eDataType = eDataTypeIn;
+
+    if( *pszPolarisation != '\0' ) {
+        SetMetadataItem( "POLARISATION", pszPolarisation );
+    }
+}
+
+/************************************************************************/
+/*                            RSRasterBand()                            */
+/************************************************************************/
+
+SAFERasterBand::~SAFERasterBand()
+
+{
+    if( poBandFile != NULL )
+        GDALClose( reinterpret_cast<GDALRasterBandH>( poBandFile ) );
+}
+
+/************************************************************************/
+/*                             IReadBlock()                             */
+/************************************************************************/
+
+CPLErr SAFERasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
+                                  void * pImage )
+
+{
+/* -------------------------------------------------------------------- */
+/*      If the last strip is partial, we need to avoid                  */
+/*      over-requesting.  We also need to initialize the extra part     */
+/*      of the block to zero.                                           */
+/* -------------------------------------------------------------------- */
+    int nRequestYSize;
+    if( (nBlockYOff + 1) * nBlockYSize > nRasterYSize )
+    {
+        nRequestYSize = nRasterYSize - nBlockYOff * nBlockYSize;
+        memset( pImage, 0, (GDALGetDataTypeSize( eDataType ) / 8) *
+            nBlockXSize * nBlockYSize );
+    }
+    else
+    {
+        nRequestYSize = nBlockYSize;
+    }
+
+/*-------------------------------------------------------------------- */
+/*      If the input imagery is tiled, also need to avoid over-        */
+/*      requesting in the X-direction.                                 */
+/* ------------------------------------------------------------------- */
+    int nRequestXSize;
+    if( (nBlockXOff + 1) * nBlockXSize > nRasterXSize )
+    {
+        nRequestXSize = nRasterXSize - nBlockXOff * nBlockXSize;
+        memset( pImage, 0, (GDALGetDataTypeSize( eDataType ) / 8) *
+            nBlockXSize * nBlockYSize );
+    }
+    else
+    {
+        nRequestXSize = nBlockXSize;
+    }
+    if( eDataType == GDT_CInt16 && poBandFile->GetRasterCount() == 2 )
+        return
+            poBandFile->RasterIO( GF_Read,
+                                  nBlockXOff * nBlockXSize,
+                                  nBlockYOff * nBlockYSize,
+                                  nRequestXSize, nRequestYSize,
+                                  pImage, nRequestXSize, nRequestYSize,
+                                  GDT_Int16,
+                                  2, NULL, 4, nBlockXSize * 4, 2, NULL );
+
+/* -------------------------------------------------------------------- */
+/*      File has one sample marked as sample format void, a 32bits.     */
+/* -------------------------------------------------------------------- */
+    else if( eDataType == GDT_CInt16 && poBandFile->GetRasterCount() == 1 )
+    {
+        CPLErr eErr
+            = poBandFile->RasterIO( GF_Read,
+                                  nBlockXOff * nBlockXSize,
+                                  nBlockYOff * nBlockYSize,
+                                  nRequestXSize, nRequestYSize,
+                                  pImage, nRequestXSize, nRequestYSize,
+                                  GDT_UInt32,
+                                  1, NULL, 4, nBlockXSize * 4, 0, NULL );
+
+#ifdef CPL_LSB
+        /* First, undo the 32bit swap. */
+        GDALSwapWords( pImage, 4, nBlockXSize * nBlockYSize, 4 );
+
+        /* Then apply 16 bit swap. */
+        GDALSwapWords( pImage, 2, nBlockXSize * nBlockYSize * 2, 2 );
+#endif
+
+        return eErr;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      The 16bit case is straight forward.  The underlying file        */
+/*      looks like a 16bit unsigned data too.                           */
+/* -------------------------------------------------------------------- */
+    else if( eDataType == GDT_UInt16 )
+        return
+            poBandFile->RasterIO( GF_Read,
+                                  nBlockXOff * nBlockXSize,
+                                  nBlockYOff * nBlockYSize,
+                                  nRequestXSize, nRequestYSize,
+                                  pImage, nRequestXSize, nRequestYSize,
+                                  GDT_UInt16,
+                                  1, NULL, 2, nBlockXSize * 2, 0, NULL );
+    else if ( eDataType == GDT_Byte )
+        return
+            poBandFile->RasterIO( GF_Read,
+                                  nBlockXOff * nBlockXSize,
+                                  nBlockYOff * nBlockYSize,
+                                  nRequestXSize, nRequestYSize,
+                                  pImage, nRequestXSize, nRequestYSize,
+                                  GDT_Byte,
+                                  1, NULL, 1, nBlockXSize, 0, NULL );
+
+    CPLAssert( FALSE );
+    return CE_Failure;
+}
+
+/************************************************************************/
+/* ==================================================================== */
+/*                              SAFEDataset                              */
+/* ==================================================================== */
+/************************************************************************/
+
+/************************************************************************/
+/*                             SAFEDataset()                            */
+/************************************************************************/
+
+SAFEDataset::SAFEDataset() :
+    psManifest(NULL),
+    nGCPCount(0),
+    pasGCPList(NULL),
+    pszGCPProjection(CPLStrdup("")),
+    papszSubDatasets(NULL),
+    pszProjection(CPLStrdup("")),
+    bHaveGeoTransform(false),
+    papszExtraFiles(NULL)
+{
+    adfGeoTransform[0] = 0.0;
+    adfGeoTransform[1] = 1.0;
+    adfGeoTransform[2] = 0.0;
+    adfGeoTransform[3] = 0.0;
+    adfGeoTransform[4] = 0.0;
+    adfGeoTransform[5] = 1.0;
+}
+
+/************************************************************************/
+/*                            ~SAFEDataset()                            */
+/************************************************************************/
+
+SAFEDataset::~SAFEDataset()
+
+{
+    FlushCache();
+
+    CPLDestroyXMLNode( psManifest );
+    CPLFree( pszProjection );
+
+    CPLFree( pszGCPProjection );
+    if( nGCPCount > 0 )
+    {
+        GDALDeinitGCPs( nGCPCount, pasGCPList );
+        CPLFree( pasGCPList );
+    }
+
+    CloseDependentDatasets();
+
+    CSLDestroy( papszSubDatasets );
+    CSLDestroy( papszExtraFiles );
+}
+
+/************************************************************************/
+/*                      CloseDependentDatasets()                        */
+/************************************************************************/
+
+int SAFEDataset::CloseDependentDatasets()
+{
+    int bHasDroppedRef = GDALPamDataset::CloseDependentDatasets();
+
+    if (nBands != 0)
+        bHasDroppedRef = TRUE;
+
+    for( int iBand = 0; iBand < nBands; iBand++ )
+    {
+       delete papoBands[iBand];
+    }
+    nBands = 0;
+
+    return bHasDroppedRef;
+}
+
+/************************************************************************/
+/*                      GetMetaDataObject()                             */
+/************************************************************************/
+
+CPLXMLNode * SAFEDataset::GetMetaDataObject(
+    CPLXMLNode *psMetaDataObjects, const char *metadataObjectId)
+{
+/* -------------------------------------------------------------------- */
+/*      Look for DataObject Element by ID.                              */
+/* -------------------------------------------------------------------- */
+    for( CPLXMLNode *psMDO = psMetaDataObjects->psChild;
+         psMDO != NULL;
+         psMDO = psMDO->psNext )
+    {
+        if( psMDO->eType != CXT_Element
+            || !(EQUAL(psMDO->pszValue,"metadataObject")) ) {
+            continue;
+        }
+
+        const char *pszElementID = CPLGetXMLValue( psMDO, "ID", "" );
+
+        if (EQUAL(pszElementID, metadataObjectId)) {
+            return psMDO;
+        }
+    }
+
+    CPLError( CE_Warning, CPLE_AppDefined,
+              "MetadataObject not found with ID=%s",
+              metadataObjectId);
+
+    return NULL;
+}
+
+/************************************************************************/
+/*                      GetDataObject()                                 */
+/************************************************************************/
+
+CPLXMLNode * SAFEDataset::GetDataObject(
+    CPLXMLNode *psDataObjects, const char *dataObjectId)
+{
+/* -------------------------------------------------------------------- */
+/*      Look for DataObject Element by ID.                              */
+/* -------------------------------------------------------------------- */
+    for( CPLXMLNode *psDO = psDataObjects->psChild;
+         psDO != NULL;
+         psDO = psDO->psNext )
+    {
+        if( psDO->eType != CXT_Element
+            || !(EQUAL(psDO->pszValue,"dataObject")) ) {
+            continue;
+        }
+
+        const char *pszElementID = CPLGetXMLValue( psDO, "ID", "" );
+
+        if (EQUAL(pszElementID, dataObjectId)) {
+            return psDO;
+        }
+    }
+
+    CPLError( CE_Warning, CPLE_AppDefined,
+              "DataObject not found with ID=%s",
+              dataObjectId);
+
+    return NULL;
+}
+
+CPLXMLNode * SAFEDataset::GetDataObject(
+    CPLXMLNode *psMetaDataObjects, CPLXMLNode *psDataObjects,
+    const char *metadataObjectId)
+{
+/* -------------------------------------------------------------------- */
+/*      Look for MetadataObject Element by ID.                          */
+/* -------------------------------------------------------------------- */
+    CPLXMLNode *psMDO = SAFEDataset::GetMetaDataObject(
+            psMetaDataObjects, metadataObjectId);
+
+    if (psMDO!=NULL) {
+        const char *dataObjectId = CPLGetXMLValue(
+            psMDO, "dataObjectPointer.dataObjectID", "" );
+        if( *dataObjectId != '\0' ) {
+            return SAFEDataset::GetDataObject(psDataObjects, dataObjectId);
+        }
+    }
+
+    CPLError( CE_Warning, CPLE_AppDefined,
+              "DataObject not found with MetaID=%s",
+              metadataObjectId);
+
+    return NULL;
+}
+
+/************************************************************************/
+/*                            GetFileList()                             */
+/************************************************************************/
+
+char **SAFEDataset::GetFileList()
+
+{
+    char **papszFileList = GDALPamDataset::GetFileList();
+
+    papszFileList = CSLInsertStrings( papszFileList, -1, papszExtraFiles );
+
+    return papszFileList;
+}
+
+/************************************************************************/
+/*                             Identify()                               */
+/************************************************************************/
+
+int SAFEDataset::Identify( GDALOpenInfo *poOpenInfo )
+{
+    /* Check for the case where we're trying to read the calibrated data: */
+    if (STARTS_WITH_CI(poOpenInfo->pszFilename, "SENTINEL_1_CALIB:")) {
+        return TRUE;
+    }
+
+    /* Check for directory access when there is a manifest.safe file in the
+       directory. */
+    if( poOpenInfo->bIsDirectory )
+    {
+        VSIStatBufL sStat;
+
+        CPLString osMDFilename =
+            CPLFormCIFilename( poOpenInfo->pszFilename, "manifest.safe", NULL );
+
+        if( VSIStatL( osMDFilename, &sStat ) == 0 && VSI_ISREG(sStat.st_mode) )
+        {
+            GDALOpenInfo oOpenInfo( osMDFilename, GA_ReadOnly, NULL );
+            return Identify(&oOpenInfo);
+        }
+
+        return FALSE;
+    }
+
+    /* otherwise, do our normal stuff */
+    if( !EQUAL(CPLGetFilename(poOpenInfo->pszFilename), "manifest.safe") )
+        return FALSE;
+
+    if( poOpenInfo->nHeaderBytes < 100 )
+        return FALSE;
+
+    if( strstr((const char *) poOpenInfo->pabyHeader, "<xfdu:XFDU" ) == NULL)
+        return FALSE;
+
+    // This driver doesn't handle Sentinel-2 data
+    if( strstr((const char *) poOpenInfo->pabyHeader, "sentinel-2" ) != NULL)
+        return FALSE;
+
+    return TRUE;
+}
+
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *SAFEDataset::Open( GDALOpenInfo * poOpenInfo )
+
+{
+/* -------------------------------------------------------------------- */
+/*      Is this a SENTINEL-1 manifest.safe definition?                  */
+/* -------------------------------------------------------------------- */
+    if ( !SAFEDataset::Identify( poOpenInfo ) ) {
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*        Get subdataset information, if relevant                       */
+/* -------------------------------------------------------------------- */
+    CPLString osMDFilename;
+    const char *pszFilename = poOpenInfo->pszFilename;
+
+    if( poOpenInfo->bIsDirectory )
+    {
+        osMDFilename =
+            CPLFormCIFilename( pszFilename, "manifest.safe", NULL );
+    }
+    else
+        osMDFilename = pszFilename;
+
+/* -------------------------------------------------------------------- */
+/*      Ingest the manifest.safe file.                                  */
+/* -------------------------------------------------------------------- */
+    //TODO REMOVE CPLXMLNode *psImageAttributes, *psImageGenerationParameters;
+    CPLXMLNode *psManifest = CPLParseXMLFile( osMDFilename );
+    if( psManifest == NULL )
+        return NULL;
+
+    CPLString osPath(CPLGetPath( osMDFilename ));
+
+/* -------------------------------------------------------------------- */
+/*      Confirm the requested access is supported.                      */
+/* -------------------------------------------------------------------- */
+    if( poOpenInfo->eAccess == GA_Update )
+    {
+        CPLDestroyXMLNode( psManifest );
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "The SAFE driver does not support update access to existing"
+                  " datasets.\n" );
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Get contentUnit parent element.                                 */
+/* -------------------------------------------------------------------- */
+    CPLXMLNode *psContentUnits = CPLGetXMLNode(
+            psManifest,
+            "=xfdu:XFDU.informationPackageMap.xfdu:contentUnit" );
+    if( psContentUnits == NULL )
+    {
+        CPLDestroyXMLNode( psManifest );
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to find <xfdu:XFDU><informationPackageMap>"
+                  "<xfdu:contentUnit> in manifest file." );
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Get Metadata Objects element.                                   */
+/* -------------------------------------------------------------------- */
+    CPLXMLNode *psMetaDataObjects
+        = CPLGetXMLNode( psManifest, "=xfdu:XFDU.metadataSection" );
+    if( psMetaDataObjects == NULL )
+    {
+        CPLDestroyXMLNode( psManifest );
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to find <xfdu:XFDU><metadataSection>"
+                  "in manifest file." );
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Get Data Objects element.                                       */
+/* -------------------------------------------------------------------- */
+    CPLXMLNode *psDataObjects
+        = CPLGetXMLNode( psManifest, "=xfdu:XFDU.dataObjectSection" );
+    if( psDataObjects == NULL )
+    {
+        CPLDestroyXMLNode( psManifest );
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                "Failed to find <xfdu:XFDU><dataObjectSection> in document." );
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create the dataset.                                             */
+/* -------------------------------------------------------------------- */
+    SAFEDataset *poDS = new SAFEDataset();
+
+    poDS->psManifest = psManifest;
+
+/* -------------------------------------------------------------------- */
+/*      Look for "Measurement Data Unit" contentUnit elements.          */
+/* -------------------------------------------------------------------- */
+    CPLXMLNode *psAnnotation = NULL;
+
+    for( CPLXMLNode *psContentUnit = psContentUnits->psChild;
+         psContentUnit != NULL;
+         psContentUnit = psContentUnit->psNext )
+    {
+        if( psContentUnit->eType != CXT_Element
+            || !(EQUAL(psContentUnit->pszValue,"xfdu:contentUnit")) ) {
+            continue;
+        }
+
+        const char *pszUnitType = CPLGetXMLValue( psContentUnit,
+                "unitType", "" );
+
+        const char *pszAnnotation  = NULL;
+        const char *pszCalibration = NULL;
+        const char *pszMeasurement = NULL;
+
+        if ( EQUAL(pszUnitType, "Measurement Data Unit") ) {
+            /* Get dmdID and dataObjectID */
+            const char *pszDmdID = CPLGetXMLValue(psContentUnit, "dmdID", "");
+
+            const char *pszDataObjectID = CPLGetXMLValue(
+                psContentUnit,
+                "dataObjectPointer.dataObjectID", "" );
+            if( *pszDataObjectID == '\0' || *pszDmdID == '\0' ) {
+                continue;
+            }
+
+            CPLXMLNode *psDataObject = SAFEDataset::GetDataObject(
+                    psDataObjects, pszDataObjectID);
+
+            const char *pszRepId = CPLGetXMLValue( psDataObject, "repID", "" );
+            if ( !EQUAL(pszRepId, "s1Level1MeasurementSchema") ) {
+                continue;
+            }
+            pszMeasurement = CPLGetXMLValue(
+                    psDataObject, "byteStream.fileLocation.href", "");
+            if( *pszMeasurement == '\0' ) {
+                continue;
+            }
+
+            char** papszTokens = CSLTokenizeString2( pszDmdID, " ",
+                CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES
+                | CSLT_STRIPENDSPACES );
+
+            for( int j = 0; j < CSLCount( papszTokens ); j++ ) {
+                const char* pszId = papszTokens[j];
+                if( *pszId == '\0' ) {
+                    continue;
+                }
+
+                //Map the metadata ID to the object element
+                CPLXMLNode *psDO = SAFEDataset::GetDataObject(
+                        psMetaDataObjects, psDataObjects, pszId);
+
+                if (psDO == NULL) {
+                    continue;
+                }
+
+                //check object type
+                pszRepId = CPLGetXMLValue( psDO, "repID", "" );
+
+                if ( EQUAL(pszRepId, "s1Level1ProductSchema") ) {
+                    /* Get annotation filename */
+                    pszAnnotation = CPLGetXMLValue(
+                            psDO, "byteStream.fileLocation.href", "");
+                    if( *pszAnnotation == '\0' ) {
+                        continue;
+                    }
+
+                } else if ( EQUAL(pszRepId, "s1Level1CalibrationSchema") ) {
+                    pszCalibration = CPLGetXMLValue(
+                            psDO, "byteStream.fileLocation.href", "");
+                    if( *pszCalibration == '\0' ) {
+                        continue;
+                    }
+
+                } else {
+                    continue;
+                }
+            }
+
+            CSLDestroy(papszTokens);
+
+            if (pszAnnotation == NULL || pszCalibration == NULL ) {
+                continue;
+            }
+
+            //open Annotation XML file
+            CPLString osAnnotationFilePath = CPLFormFilename( osPath,
+                                                       pszAnnotation, NULL );
+            if( psAnnotation )
+                CPLDestroyXMLNode(psAnnotation);
+            psAnnotation = CPLParseXMLFile( osAnnotationFilePath );
+            if( psAnnotation == NULL )
+                continue;
+
+/* -------------------------------------------------------------------- */
+/*      Get overall image information.                                  */
+/* -------------------------------------------------------------------- */
+            poDS->nRasterXSize =
+                atoi(CPLGetXMLValue( psAnnotation,
+                    "=product.imageAnnotation.imageInformation.numberOfSamples",
+                    "-1" ));
+            poDS->nRasterYSize =
+                atoi(CPLGetXMLValue( psAnnotation,
+                    "=product.imageAnnotation.imageInformation.numberOfLines",
+                    "-1" ));
+            if (poDS->nRasterXSize <= 1 || poDS->nRasterYSize <= 1) {
+                CPLError( CE_Failure, CPLE_OpenFailed,
+                    "Non-sane raster dimensions provided in manifest.safe. "
+                    "If this is a valid SENTINEL-1 scene, please contact your "
+                    "data provider for a corrected dataset." );
+                delete poDS;
+                CPLDestroyXMLNode(psAnnotation);
+                return NULL;
+            }
+
+            const char *pszProductType = CPLGetXMLValue(
+                psAnnotation, "=product.adsHeader.productType", "UNK" );
+            const char *pszMissionId = CPLGetXMLValue(
+                psAnnotation, "=product.adsHeader.missionId", "UNK" );
+            const char *pszPolarisation = CPLGetXMLValue(
+                psAnnotation, "=product.adsHeader.polarisation", "UNK" );
+            const char *pszMode = CPLGetXMLValue(
+                psAnnotation, "=product.adsHeader.mode", "UNK" );
+            const char *pszSwath = CPLGetXMLValue(
+                psAnnotation, "=product.adsHeader.swath", "UNK" );
+
+            poDS->SetMetadataItem("PRODUCT_TYPE", pszProductType);
+            poDS->SetMetadataItem("MISSION_ID", pszMissionId);
+            poDS->SetMetadataItem("MODE", pszMode);
+            poDS->SetMetadataItem("SWATH", pszSwath);
+
+/* -------------------------------------------------------------------- */
+/*      Get dataType (so we can recognize complex data), and the        */
+/*      bitsPerSample.                                                  */
+/* -------------------------------------------------------------------- */
+
+            const char *pszDataType = CPLGetXMLValue(
+                psAnnotation,
+                "=product.imageAnnotation.imageInformation.outputPixels",
+                "" );
+
+            GDALDataType eDataType;
+            if( EQUAL(pszDataType,"16 bit Signed Integer") )
+                eDataType = GDT_CInt16;
+            else if( EQUAL(pszDataType,"16 bit Unsigned Integer") )
+                eDataType = GDT_UInt16;
+            else
+            {
+                delete poDS;
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "dataType=%s: not a supported configuration.",
+                          pszDataType );
+                CPLDestroyXMLNode(psAnnotation);
+                return NULL;
+            }
+
+            /* Extract pixel spacing information */
+            const char *pszPixelSpacing = CPLGetXMLValue(
+                psAnnotation,
+                "=product.imageAnnotation.imageInformation.rangePixelSpacing",
+                "UNK" );
+            poDS->SetMetadataItem( "PIXEL_SPACING", pszPixelSpacing );
+
+            const char *pszLineSpacing = CPLGetXMLValue(
+                psAnnotation,
+                "=product.imageAnnotation.imageInformation.azimuthPixelSpacing",
+                "UNK" );
+            poDS->SetMetadataItem( "LINE_SPACING", pszLineSpacing );
+
+/* -------------------------------------------------------------------- */
+/*      Form full filename (path of manifest.safe + measurement file).  */
+/* -------------------------------------------------------------------- */
+            char *pszFullname =
+                CPLStrdup(CPLFormFilename( osPath, pszMeasurement, NULL ));
+
+/* -------------------------------------------------------------------- */
+/*      Try and open the file.                                          */
+/* -------------------------------------------------------------------- */
+            GDALDataset *poBandFile = reinterpret_cast<GDALDataset *>(
+                GDALOpen( pszFullname, GA_ReadOnly ) );
+            if( poBandFile == NULL )
+            {
+                // NOP
+            }
+            else
+            if (poBandFile->GetRasterCount() == 0)
+            {
+                GDALClose( (GDALRasterBandH) poBandFile );
+             }
+            else {
+
+                poDS->papszExtraFiles = CSLAddString( poDS->papszExtraFiles,
+                                                  pszFullname );
+
+/* -------------------------------------------------------------------- */
+/*      Create the band.                                                */
+/* -------------------------------------------------------------------- */
+                SAFERasterBand *poBand
+                    = new SAFERasterBand( poDS, eDataType,
+                                          pszPolarisation,
+                                          poBandFile );
+
+                poDS->SetBand( poDS->GetRasterCount() + 1, poBand );
+            }
+
+            CPLFree( pszFullname );
+        }
+    }
+
+    if (poDS->GetRasterCount() == 0) {
+        CPLError( CE_Failure, CPLE_OpenFailed, "Measurement bands not found." );
+        delete poDS;
+        if( psAnnotation )
+            CPLDestroyXMLNode(psAnnotation);
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Collect more metadata elements                                  */
+/* -------------------------------------------------------------------- */
+
+/* -------------------------------------------------------------------- */
+/*      Platform information                                            */
+/* -------------------------------------------------------------------- */
+    CPLXMLNode *psPlatformAttrs = SAFEDataset::GetMetaDataObject(
+        psMetaDataObjects, "platform");
+
+    if (psPlatformAttrs != NULL) {
+        const char *pszItem = CPLGetXMLValue(
+                psPlatformAttrs,
+                "metadataWrap.xmlData.safe:platform"
+                ".safe:familyName", "" );
+        poDS->SetMetadataItem( "SATELLITE_IDENTIFIER", pszItem );
+
+        pszItem = CPLGetXMLValue(
+                psPlatformAttrs,
+                "metadataWrap.xmlData.safe:platform"
+                ".safe:instrument.safe:familyName.abbreviation", "" );
+        poDS->SetMetadataItem( "SENSOR_IDENTIFIER", pszItem );
+
+        pszItem = CPLGetXMLValue(
+                psPlatformAttrs,
+                "metadataWrap.xmlData.safe:platform"
+                ".safe:instrument.safe:extension"
+                ".s1sarl1:instrumentMode.s1sarl1:mode", "UNK" );
+        poDS->SetMetadataItem( "BEAM_MODE", pszItem );
+
+        pszItem = CPLGetXMLValue(
+                psPlatformAttrs,
+                "metadataWrap.xmlData.safe:platform"
+                ".safe:instrument.safe:extension"
+                ".s1sarl1:instrumentMode.s1sarl1:swath", "UNK" );
+        poDS->SetMetadataItem( "BEAM_SWATH", pszItem );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Acquisition Period information                                  */
+/* -------------------------------------------------------------------- */
+    CPLXMLNode *psAcquisitionAttrs = SAFEDataset::GetMetaDataObject(
+        psMetaDataObjects, "acquisitionPeriod");
+
+    if (psAcquisitionAttrs != NULL) {
+            const char *pszItem = CPLGetXMLValue(
+            psAcquisitionAttrs,
+            "metadataWrap.xmlData.safe:acquisitionPeriod"
+            ".safe:startTime", "UNK" );
+        poDS->SetMetadataItem( "ACQUISITION_START_TIME", pszItem );
+        pszItem = CPLGetXMLValue(
+            psAcquisitionAttrs,
+            "metadataWrap.xmlData.safe:acquisitionPeriod"
+            ".safe:stopTime", "UNK" );
+        poDS->SetMetadataItem( "ACQUISITION_STOP_TIME", pszItem );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Processing information                                          */
+/* -------------------------------------------------------------------- */
+    CPLXMLNode *psProcessingAttrs = SAFEDataset::GetMetaDataObject(
+        psMetaDataObjects, "processing");
+
+    if (psProcessingAttrs != NULL) {
+        const char *pszItem = CPLGetXMLValue(
+            psProcessingAttrs,
+            "metadataWrap.xmlData.safe:processing.safe:facility.name", "UNK" );
+        poDS->SetMetadataItem( "FACILITY_IDENTIFIER", pszItem );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Measurement Orbit Reference information                         */
+/* -------------------------------------------------------------------- */
+    CPLXMLNode *psOrbitAttrs = SAFEDataset::GetMetaDataObject(
+        psMetaDataObjects, "measurementOrbitReference");
+
+    if (psOrbitAttrs != NULL) {
+        const char *pszItem = CPLGetXMLValue( psOrbitAttrs,
+            "metadataWrap.xmlData.safe:orbitReference"
+            ".safe:orbitNumber", "UNK" );
+        poDS->SetMetadataItem( "ORBIT_NUMBER", pszItem );
+        pszItem = CPLGetXMLValue( psOrbitAttrs,
+            "metadataWrap.xmlData.safe:orbitReference"
+            ".safe:extension.s1:orbitProperties.s1:pass", "UNK" );
+        poDS->SetMetadataItem( "ORBIT_DIRECTION", pszItem );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Collect Annotation Processing Information                       */
+/* -------------------------------------------------------------------- */
+    CPLXMLNode *psProcessingInfo =
+        CPLGetXMLNode( psAnnotation,
+                       "=product.imageAnnotation.processingInformation" );
+
+    if ( psProcessingInfo != NULL ) {
+        OGRSpatialReference oLL, oPrj;
+
+        const char *pszEllipsoidName = CPLGetXMLValue(
+            psProcessingInfo, "ellipsoidName", "" );
+        const double minor_axis = CPLAtof(CPLGetXMLValue(
+            psProcessingInfo, "ellipsoidSemiMinorAxis", "0.0" ));
+        const double major_axis = CPLAtof(CPLGetXMLValue(
+            psProcessingInfo, "ellipsoidSemiMajorAxis", "0.0" ));
+
+        if ( EQUAL(pszEllipsoidName, "") || ( minor_axis == 0.0 ) ||
+             ( major_axis == 0.0 ) )
+        {
+            CPLError(CE_Warning,CPLE_AppDefined,"Warning- incomplete"
+                     " ellipsoid information.  Using wgs-84 parameters.\n");
+            oLL.SetWellKnownGeogCS( "WGS84" );
+            oPrj.SetWellKnownGeogCS( "WGS84" );
+        }
+        else if ( EQUAL( pszEllipsoidName, "WGS84" ) ) {
+            oLL.SetWellKnownGeogCS( "WGS84" );
+            oPrj.SetWellKnownGeogCS( "WGS84" );
+        }
+        else {
+            const double inv_flattening = major_axis/(major_axis - minor_axis);
+            oLL.SetGeogCS( "","",pszEllipsoidName, major_axis,
+                           inv_flattening);
+            oPrj.SetGeogCS( "","",pszEllipsoidName, major_axis,
+                            inv_flattening);
+        }
+
+        CPLFree( poDS->pszGCPProjection );
+        poDS->pszGCPProjection = NULL;
+        oLL.exportToWkt( &(poDS->pszGCPProjection) );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Collect GCPs.                                                   */
+/* -------------------------------------------------------------------- */
+    CPLXMLNode *psGeoGrid =
+        CPLGetXMLNode( psAnnotation,
+                       "=product.geolocationGrid.geolocationGridPointList" );
+
+    if( psGeoGrid != NULL ) {
+        /* count GCPs */
+        poDS->nGCPCount = 0;
+
+        for( CPLXMLNode *psNode = psGeoGrid->psChild; psNode != NULL;
+             psNode = psNode->psNext )
+        {
+            if( EQUAL(psNode->pszValue,"geolocationGridPoint") )
+                poDS->nGCPCount++ ;
+        }
+
+        poDS->pasGCPList = reinterpret_cast<GDAL_GCP *>(
+            CPLCalloc( sizeof(GDAL_GCP), poDS->nGCPCount ) );
+
+        poDS->nGCPCount = 0;
+
+        for( CPLXMLNode *psNode = psGeoGrid->psChild; psNode != NULL;
+             psNode = psNode->psNext )
+        {
+            GDAL_GCP *psGCP = poDS->pasGCPList + poDS->nGCPCount;
+
+            if( !EQUAL(psNode->pszValue,"geolocationGridPoint") )
+                continue;
+
+            poDS->nGCPCount++ ;
+
+            char szID[32];
+            snprintf( szID, sizeof(szID), "%d", poDS->nGCPCount );
+            psGCP->pszId = CPLStrdup( szID );
+            psGCP->pszInfo = CPLStrdup("");
+            psGCP->dfGCPPixel = CPLAtof(CPLGetXMLValue(psNode,"pixel","0"));
+            psGCP->dfGCPLine = CPLAtof(CPLGetXMLValue(psNode,"line","0"));
+            psGCP->dfGCPX = CPLAtof(CPLGetXMLValue(psNode,"longitude",""));
+            psGCP->dfGCPY = CPLAtof(CPLGetXMLValue(psNode,"latitude",""));
+            psGCP->dfGCPZ = CPLAtof(CPLGetXMLValue(psNode,"height",""));
+        }
+    }
+
+    CPLDestroyXMLNode(psAnnotation);
+
+/* -------------------------------------------------------------------- */
+/*      Initialize any PAM information.                                 */
+/* -------------------------------------------------------------------- */
+    const CPLString osDescription = osMDFilename;
+
+/* -------------------------------------------------------------------- */
+/*      Initialize any PAM information.                                 */
+/* -------------------------------------------------------------------- */
+    poDS->SetDescription( osDescription );
+
+    poDS->SetPhysicalFilename( osMDFilename );
+    poDS->SetSubdatasetName( osDescription );
+
+    poDS->TryLoadXML();
+
+/* -------------------------------------------------------------------- */
+/*      Check for overviews.                                            */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, ":::VIRTUAL:::" );
+
+    return( poDS );
+}
+
+/************************************************************************/
+/*                            GetGCPCount()                             */
+/************************************************************************/
+
+int SAFEDataset::GetGCPCount()
+{
+    return nGCPCount;
+}
+
+/************************************************************************/
+/*                          GetGCPProjection()                          */
+/************************************************************************/
+
+const char *SAFEDataset::GetGCPProjection()
+{
+    return pszGCPProjection;
+}
+
+/************************************************************************/
+/*                               GetGCPs()                              */
+/************************************************************************/
+
+const GDAL_GCP *SAFEDataset::GetGCPs()
+
+{
+    return pasGCPList;
+}
+
+
+/************************************************************************/
+/*                          GetProjectionRef()                          */
+/************************************************************************/
+
+const char *SAFEDataset::GetProjectionRef()
+{
+    return( pszProjection );
+}
+
+/************************************************************************/
+/*                          GetGeoTransform()                           */
+/************************************************************************/
+
+CPLErr SAFEDataset::GetGeoTransform( double * padfTransform )
+{
+    memcpy( padfTransform,  adfGeoTransform, sizeof(double) * 6 );
+
+    if (bHaveGeoTransform)
+        return CE_None;
+
+    return CE_Failure;
+}
+
+#ifdef notdef
+/************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **SAFEDataset::GetMetadataDomainList()
+{
+    return BuildMetadataDomainList(GDALDataset::GetMetadataDomainList(),
+                                   TRUE,
+                                   "SUBDATASETS", NULL);
+}
+
+/************************************************************************/
+/*                            GetMetadata()                             */
+/************************************************************************/
+
+char **SAFEDataset::GetMetadata( const char *pszDomain )
+{
+    if( pszDomain != NULL && STARTS_WITH_CI(pszDomain, "SUBDATASETS") &&
+        papszSubDatasets != NULL)
+        return papszSubDatasets;
+
+    return GDALDataset::GetMetadata( pszDomain );
+}
+#endif
+
+/************************************************************************/
+/*                         GDALRegister_SAFE()                          */
+/************************************************************************/
+
+void GDALRegister_SAFE()
+{
+    if( GDALGetDriverByName( "SAFE" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "SAFE" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Sentinel-1 SAR SAFE Product" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_safe.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "NO" );
+
+    poDriver->pfnOpen = SAFEDataset::Open;
+    poDriver->pfnIdentify = SAFEDataset::Identify;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/frmts/saga/sagadataset.cpp b/frmts/saga/sagadataset.cpp
index 26db273..0566ba8 100644
--- a/frmts/saga/sagadataset.cpp
+++ b/frmts/saga/sagadataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sagadataset.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: sagadataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  * Project:  SAGA GIS Binary Driver
  * Purpose:  Implements the SAGA GIS Binary Grid Format.
  * Author:   Volker Wichmann, wichmann at laserdata.at
@@ -30,14 +30,15 @@
 
 #include "cpl_conv.h"
 
-#include <float.h>
-#include <limits.h>
-#include <assert.h>
+#include <cassert>
+#include <cfloat>
+#include <climits>
 
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: sagadataset.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: sagadataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 #ifndef INT_MAX
 # define INT_MAX 2147483647
@@ -45,7 +46,7 @@ CPL_CVSID("$Id: sagadataset.cpp 27745 2014-09-27 16:38:57Z goatbar $");
 
 /* NODATA Values */
 //#define	SG_NODATA_GDT_Bit	0.0
-#define SG_NODATA_GDT_Byte		255
+static const GByte SG_NODATA_GDT_Byte = 255;
 #define	SG_NODATA_GDT_UInt16	65535
 #define	SG_NODATA_GDT_Int16		-32767
 #define	SG_NODATA_GDT_UInt32	4294967295U
@@ -53,12 +54,6 @@ CPL_CVSID("$Id: sagadataset.cpp 27745 2014-09-27 16:38:57Z goatbar $");
 #define	SG_NODATA_GDT_Float32	-99999.0
 #define	SG_NODATA_GDT_Float64	-99999.0
 
-
-CPL_C_START
-void	GDALRegister_SAGA(void);
-CPL_C_END
-
-
 /************************************************************************/
 /* ==================================================================== */
 /*                              SAGADataset                             */
@@ -69,37 +64,37 @@ class SAGARasterBand;
 
 class SAGADataset : public GDALPamDataset
 {
-    friend class		SAGARasterBand;
+    friend class SAGARasterBand;
 
-	static CPLErr		WriteHeader( CPLString osHDRFilename, GDALDataType eType,
-									int nXSize, int nYSize,
-									double dfMinX, double dfMinY,
-									double dfCellsize, double dfNoData,
-									double dfZFactor, bool bTopToBottom );
-    VSILFILE				*fp;
-    char                *pszProjection;
+    static CPLErr WriteHeader( CPLString osHDRFilename, GDALDataType eType,
+                               int nXSize, int nYSize,
+                               double dfMinX, double dfMinY,
+                               double dfCellsize, double dfNoData,
+                               double dfZFactor, bool bTopToBottom );
+    VSILFILE *fp;
+    char     *pszProjection;
 
   public:
         SAGADataset();
-		~SAGADataset();
-
-		static GDALDataset		*Open( GDALOpenInfo * );
-		static GDALDataset		*Create( const char * pszFilename,
-			 							int nXSize, int nYSize, int nBands,
-										GDALDataType eType,
-										char **papszParmList );
-		static GDALDataset		*CreateCopy( const char *pszFilename,
-										GDALDataset *poSrcDS,
-										int bStrict, char **papszOptions,
-										GDALProgressFunc pfnProgress,
-										void *pProgressData );
-		
-        virtual const char     *GetProjectionRef(void);
-        virtual CPLErr          SetProjection( const char * );
-        virtual char          **GetFileList();
-
-		CPLErr					GetGeoTransform( double *padfGeoTransform );
-		CPLErr					SetGeoTransform( double *padfGeoTransform );
+        ~SAGADataset();
+
+    static GDALDataset *Open( GDALOpenInfo * );
+    static GDALDataset *Create( const char * pszFilename,
+                                int nXSize, int nYSize, int nBands,
+                                GDALDataType eType,
+                                char **papszParmList );
+    static GDALDataset *CreateCopy( const char *pszFilename,
+                                    GDALDataset *poSrcDS,
+                                    int bStrict, char **papszOptions,
+                                    GDALProgressFunc pfnProgress,
+                                    void *pProgressData );
+
+    virtual const char *GetProjectionRef(void);
+    virtual CPLErr SetProjection( const char * );
+    virtual char **GetFileList();
+
+    CPLErr GetGeoTransform( double *padfGeoTransform );
+    CPLErr SetGeoTransform( double *padfGeoTransform );
 };
 
 
@@ -112,7 +107,7 @@ class SAGADataset : public GDALPamDataset
 class SAGARasterBand : public GDALPamRasterBand
 {
     friend class	SAGADataset;
-    
+
     int				m_Cols;
     int				m_Rows;
     double			m_Xmin;
@@ -124,11 +119,10 @@ class SAGARasterBand : public GDALPamRasterBand
 
     void			SetDataType( GDALDataType eType );
     void            SwapBuffer(void* pImage);
-public:
 
+public:
     SAGARasterBand( SAGADataset *, int );
-    ~SAGARasterBand();
-    
+
     CPLErr		IReadBlock( int, int, void * );
     CPLErr		IWriteBlock( int, int, void * );
 
@@ -139,12 +133,19 @@ public:
 /*                           SAGARasterBand()                           */
 /************************************************************************/
 
-SAGARasterBand::SAGARasterBand( SAGADataset *poDS, int nBand )
-
+SAGARasterBand::SAGARasterBand( SAGADataset *poDS_, int nBand_ ) :
+    m_Cols(0),
+    m_Rows(0),
+    m_Xmin(0.0),
+    m_Ymin(0.0),
+    m_Cellsize(0.0),
+    m_NoData(0.0),
+    m_ByteOrder(0),
+    m_nBits(0)
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
-    
+    poDS = poDS_;
+    nBand = nBand_;
+
     eDataType = GDT_Float32;
 
     nBlockXSize = poDS->GetRasterXSize();
@@ -152,15 +153,6 @@ SAGARasterBand::SAGARasterBand( SAGADataset *poDS, int nBand )
 }
 
 /************************************************************************/
-/*                           ~SAGARasterBand()                          */
-/************************************************************************/
-
-SAGARasterBand::~SAGARasterBand( )
-
-{
-}
-
-/************************************************************************/
 /*                            SetDataType()                             */
 /************************************************************************/
 
@@ -179,16 +171,16 @@ void SAGARasterBand::SwapBuffer(void* pImage)
 {
 
 #ifdef CPL_LSB
-    int bSwap = ( m_ByteOrder == 1);
+    const bool bSwap = ( m_ByteOrder == 1);
 #else
-    int bSwap = ( m_ByteOrder == 0);
+    const bool bSwap = ( m_ByteOrder == 0);
 #endif
 
     if (bSwap)
     {
         if ( m_nBits == 16 )
         {
-            short* pImage16 = (short*) pImage;
+            short* pImage16 = reinterpret_cast<short *>( pImage );
             for( int iPixel=0; iPixel<nBlockXSize; iPixel++ )
             {
                 CPL_SWAP16PTR( pImage16 + iPixel );
@@ -196,7 +188,7 @@ void SAGARasterBand::SwapBuffer(void* pImage)
         }
         else if ( m_nBits == 32 )
         {
-            int* pImage32 = (int*) pImage;
+            int* pImage32 = reinterpret_cast<int *>( pImage );
             for( int iPixel=0; iPixel<nBlockXSize; iPixel++ )
             {
                 CPL_SWAP32PTR( pImage32 + iPixel );
@@ -204,14 +196,14 @@ void SAGARasterBand::SwapBuffer(void* pImage)
         }
         else if ( m_nBits == 64 )
         {
-            double* pImage64 = (double*) pImage;
+            double* pImage64 = reinterpret_cast<double *>( pImage );
             for( int iPixel=0; iPixel<nBlockXSize; iPixel++ )
             {
                 CPL_SWAP64PTR( pImage64 + iPixel );
             }
         }
     }
-    
+
 }
 
 /************************************************************************/
@@ -225,8 +217,9 @@ CPLErr SAGARasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     if( nBlockYOff < 0 || nBlockYOff > nRasterYSize - 1 || nBlockXOff != 0 )
 		return CE_Failure;
 
-    SAGADataset *poGDS = dynamic_cast<SAGADataset *>(poDS);
-    vsi_l_offset offset = (vsi_l_offset) (m_nBits / 8) * nRasterXSize * (nRasterYSize - nBlockYOff - 1);
+    SAGADataset *poGDS = static_cast<SAGADataset *>( poDS );
+    vsi_l_offset offset = static_cast<vsi_l_offset>( m_nBits / 8 )
+        * nRasterXSize * (nRasterYSize - nBlockYOff - 1);
 
     if( VSIFSeekL( poGDS->fp, offset, SEEK_SET ) != 0 )
     {
@@ -265,8 +258,9 @@ CPLErr SAGARasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     if( nBlockYOff < 0 || nBlockYOff > nRasterYSize - 1 || nBlockXOff != 0 )
 		return CE_Failure;
 
-    vsi_l_offset offset = (vsi_l_offset) (m_nBits / 8) * nRasterXSize * (nRasterYSize - nBlockYOff - 1);
-    SAGADataset *poGDS = dynamic_cast<SAGADataset *>(poDS);
+    const vsi_l_offset offset = static_cast<vsi_l_offset> (m_nBits / 8)
+        * nRasterXSize * (nRasterYSize - nBlockYOff - 1);
+    SAGADataset *poGDS = static_cast<SAGADataset *>(poDS);
     assert( poGDS != NULL );
 
     if( VSIFSeekL( poGDS->fp, offset, SEEK_SET ) != 0 )
@@ -275,14 +269,15 @@ CPLErr SAGARasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
               "Unable to seek to beginning of grid row.\n" );
         return CE_Failure;
     }
-    
+
     SwapBuffer(pImage);
-    
-    int bSuccess = ( VSIFWriteL( pImage, m_nBits / 8, nBlockXSize,
-                    poGDS->fp ) == static_cast<unsigned>(nBlockXSize) );
+
+    const bool bSuccess = (
+        VSIFWriteL( pImage, m_nBits / 8, nBlockXSize, poGDS->fp )
+        == static_cast<unsigned>(nBlockXSize) );
 
     SwapBuffer(pImage);
-    
+
     if (!bSuccess)
     {
         CPLError( CE_Failure, CPLE_FileIO,
@@ -312,11 +307,10 @@ double SAGARasterBand::GetNoDataValue( int * pbSuccess )
 /************************************************************************/
 
 
-SAGADataset::SAGADataset()
-
-{
-    pszProjection = CPLStrdup("");
-}
+SAGADataset::SAGADataset() :
+    fp(NULL),
+    pszProjection(CPLStrdup(""))
+{}
 
 SAGADataset::~SAGADataset()
 
@@ -334,14 +328,12 @@ SAGADataset::~SAGADataset()
 
 char** SAGADataset::GetFileList()
 {
-    CPLString osPath = CPLGetPath( GetDescription() );
-    CPLString osName = CPLGetBasename( GetDescription() );
-    VSIStatBufL sStatBuf;
+    const CPLString osPath = CPLGetPath( GetDescription() );
+    const CPLString osName = CPLGetBasename( GetDescription() );
 
-    char **papszFileList = NULL;
 
-    // Main data file, etc. 
-    papszFileList = GDALPamDataset::GetFileList();
+    // Main data file, etc.
+    char **papszFileList = GDALPamDataset::GetFileList();
 
     // Header file.
     CPLString osFilename = CPLFormCIFilename( osPath, osName, ".sgrd" );
@@ -349,9 +341,10 @@ char** SAGADataset::GetFileList()
 
     // projections file.
     osFilename = CPLFormCIFilename( osPath, osName, "prj" );
+    VSIStatBufL sStatBuf;
     if( VSIStatExL( osFilename, &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 )
         papszFileList = CSLAddString( papszFileList, osFilename );
-    
+
     return papszFileList;
 }
 
@@ -396,15 +389,14 @@ CPLErr SAGADataset::SetProjection( const char *pszSRS )
 /* -------------------------------------------------------------------- */
 /*      Write to .prj file.                                             */
 /* -------------------------------------------------------------------- */
-    CPLString osPrjFilename = CPLResetExtension( GetDescription(), "prj" );
-    VSILFILE *fp;
-
-    fp = VSIFOpenL( osPrjFilename.c_str(), "wt" );
-    if( fp != NULL )
+    const CPLString osPrjFilename = CPLResetExtension( GetDescription(), "prj" );
+    VSILFILE *l_fp = VSIFOpenL( osPrjFilename.c_str(), "wt" );
+    if( l_fp != NULL )
     {
-        VSIFWriteL( pszESRI_SRS, 1, strlen(pszESRI_SRS), fp );
-        VSIFWriteL( (void *) "\n", 1, 1, fp );
-        VSIFCloseL( fp );
+        VSIFWriteL( pszESRI_SRS, 1, strlen(pszESRI_SRS), l_fp );
+        VSIFWriteL( reinterpret_cast<void *>( const_cast<char *>(  "\n" ) ),
+                    1, 1, l_fp );
+        VSIFCloseL( l_fp );
     }
 
     CPLFree( pszESRI_SRS );
@@ -420,24 +412,18 @@ GDALDataset *SAGADataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
     /* -------------------------------------------------------------------- */
-    /*	We assume the user is pointing to the binary (ie. .sdat) file.	    */
+    /*  We assume the user is pointing to the binary (i.e. .sdat) file.     */
     /* -------------------------------------------------------------------- */
     if( !EQUAL(CPLGetExtension( poOpenInfo->pszFilename ), "sdat"))
     {
         return NULL;
     }
 
-    CPLString osPath = CPLGetPath( poOpenInfo->pszFilename );
-    CPLString osName = CPLGetBasename( poOpenInfo->pszFilename );
-    CPLString osHDRFilename;
-
-    osHDRFilename = CPLFormCIFilename( osPath, osName, ".sgrd" );
-
-
-    VSILFILE	*fp;
+    const CPLString osPath = CPLGetPath( poOpenInfo->pszFilename );
+    const CPLString osName = CPLGetBasename( poOpenInfo->pszFilename );
+    const CPLString osHDRFilename = CPLFormCIFilename( osPath, osName, ".sgrd" );
 
-    fp = VSIFOpenL( osHDRFilename, "r" );
-    
+    VSILFILE *fp = VSIFOpenL( osHDRFilename, "r" );
     if( fp == NULL )
     {
         return NULL;
@@ -447,61 +433,58 @@ GDALDataset *SAGADataset::Open( GDALOpenInfo * poOpenInfo )
     /*      Is this file a SAGA header file?  Read a few lines of text      */
     /*      searching for something starting with nrows or ncols.           */
     /* -------------------------------------------------------------------- */
-    const char		*pszLine;
     int				nRows = -1, nCols = -1;
     double			dXmin = 0.0, dYmin = 0.0, dCellsize = 0.0, dNoData = 0.0, dZFactor = 0.0;
     int				nLineCount			= 0;
     char			szDataFormat[20]	= "DOUBLE";
     char            szByteOrderBig[10]	= "FALSE";
     char			szTopToBottom[10]	= "FALSE";
-    char            **papszHDR			= NULL;
-    
-	
-    while( (pszLine = CPLReadLineL( fp )) != NULL )    
-    {
-        char	**papszTokens;
 
+    const char		*pszLine;
+    while( (pszLine = CPLReadLineL( fp )) != NULL )
+    {
         nLineCount++;
 
         if( nLineCount > 50 || strlen(pszLine) > 1000 )
             break;
 
-        papszHDR = CSLAddString( papszHDR, pszLine );
-
-        papszTokens = CSLTokenizeStringComplex( pszLine, " =", TRUE, FALSE );
+        char **papszTokens
+            = CSLTokenizeStringComplex( pszLine, " =", TRUE, FALSE );
         if( CSLCount( papszTokens ) < 2 )
-        {		
+        {
             CSLDestroy( papszTokens );
             continue;
         }
 
-        if( EQUALN(papszTokens[0],"CELLCOUNT_X",strlen("CELLCOUNT_X")) )
+        char **papszHDR = CSLAddString( NULL, pszLine );
+
+        if( STARTS_WITH_CI(papszTokens[0], "CELLCOUNT_X") )
             nCols = atoi(papszTokens[1]);
-        else if( EQUALN(papszTokens[0],"CELLCOUNT_Y",strlen("CELLCOUNT_Y")) )
+        else if( STARTS_WITH_CI(papszTokens[0], "CELLCOUNT_Y") )
             nRows = atoi(papszTokens[1]);
-        else if( EQUALN(papszTokens[0],"POSITION_XMIN",strlen("POSITION_XMIN")) )
+        else if( STARTS_WITH_CI(papszTokens[0], "POSITION_XMIN") )
             dXmin = CPLAtofM(papszTokens[1]);
-        else if( EQUALN(papszTokens[0],"POSITION_YMIN",strlen("POSITION_YMIN")) )
+        else if( STARTS_WITH_CI(papszTokens[0], "POSITION_YMIN") )
             dYmin = CPLAtofM(papszTokens[1]);
-        else if( EQUALN(papszTokens[0],"CELLSIZE",strlen("CELLSIZE")) )
+        else if( STARTS_WITH_CI(papszTokens[0], "CELLSIZE") )
             dCellsize = CPLAtofM(papszTokens[1]);
-        else if( EQUALN(papszTokens[0],"NODATA_VALUE",strlen("NODATA_VALUE")) )
+        else if( STARTS_WITH_CI(papszTokens[0], "NODATA_VALUE") )
             dNoData = CPLAtofM(papszTokens[1]);
-        else if( EQUALN(papszTokens[0],"DATAFORMAT",strlen("DATAFORMAT")) )
+        else if( STARTS_WITH_CI(papszTokens[0], "DATAFORMAT") )
             strncpy( szDataFormat, papszTokens[1], sizeof(szDataFormat)-1 );
-        else if( EQUALN(papszTokens[0],"BYTEORDER_BIG",strlen("BYTEORDER_BIG")) )
+        else if( STARTS_WITH_CI(papszTokens[0], "BYTEORDER_BIG") )
             strncpy( szByteOrderBig, papszTokens[1], sizeof(szByteOrderBig)-1 );
-        else if( EQUALN(papszTokens[0],"TOPTOBOTTOM",strlen("TOPTOBOTTOM")) )
+        else if( STARTS_WITH_CI(papszTokens[0], "TOPTOBOTTOM") )
             strncpy( szTopToBottom, papszTokens[1], sizeof(szTopToBottom)-1 );
-        else if( EQUALN(papszTokens[0],"Z_FACTOR",strlen("Z_FACTOR")) )
+        else if( STARTS_WITH_CI(papszTokens[0], "Z_FACTOR") )
             dZFactor = CPLAtofM(papszTokens[1]);
 
         CSLDestroy( papszTokens );
+        CSLDestroy( papszHDR );
     }
 
     VSIFCloseL( fp );
 
-    CSLDestroy( papszHDR );
 
     /* -------------------------------------------------------------------- */
     /*      Did we get the required keywords?  If not we return with        */
@@ -517,23 +500,21 @@ GDALDataset *SAGADataset::Open( GDALOpenInfo * poOpenInfo )
     {
         return NULL;
     }
-    
-    if( EQUALN(szTopToBottom,"TRUE",strlen("TRUE")) )
+
+    if( STARTS_WITH_CI(szTopToBottom, "TRUE") )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Currently the SAGA Binary Grid driver does not support\n"
                   "SAGA grids written TOPTOBOTTOM.\n");
         return NULL;
     }
     if( dZFactor != 1.0)
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "Currently the SAGA Binary Grid driver does not support\n"
                   "ZFACTORs other than 1.\n");
     }
-	
-	
-	
+
     /* -------------------------------------------------------------------- */
     /*      Create a corresponding GDALDataset.                             */
     /* -------------------------------------------------------------------- */
@@ -548,8 +529,8 @@ GDALDataset *SAGADataset::Open( GDALOpenInfo * poOpenInfo )
     if( poDS->fp == NULL )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "VSIFOpenL(%s) failed unexpectedly.", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "VSIFOpenL(%s) failed unexpectedly.",
                   poOpenInfo->pszFilename );
         return NULL;
     }
@@ -559,13 +540,12 @@ GDALDataset *SAGADataset::Open( GDALOpenInfo * poOpenInfo )
 
     SAGARasterBand *poBand = new SAGARasterBand( poDS, 1 );
 
-
     /* -------------------------------------------------------------------- */
     /*      Figure out the byte order.                                      */
     /* -------------------------------------------------------------------- */
-    if( EQUALN(szByteOrderBig,"TRUE",strlen("TRUE")) )
+    if( STARTS_WITH_CI(szByteOrderBig, "TRUE") )
         poBand->m_ByteOrder = 1;
-    else if( EQUALN(szByteOrderBig,"FALSE",strlen("FALSE")) )
+    else if( STARTS_WITH_CI(szByteOrderBig, "FALSE") )
         poBand->m_ByteOrder = 0;
 
 
@@ -619,13 +599,13 @@ GDALDataset *SAGADataset::Open( GDALOpenInfo * poOpenInfo )
     }
     else
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
-                  "SAGA driver does not support the dataformat %s.", 
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "SAGA driver does not support the dataformat %s.",
                   szDataFormat );
         delete poBand;
         delete poDS;
         return NULL;
-    }	
+    }
 
     /* -------------------------------------------------------------------- */
     /*      Save band information                                           */
@@ -636,7 +616,7 @@ GDALDataset *SAGADataset::Open( GDALOpenInfo * poOpenInfo )
     poBand->m_Cellsize	= dCellsize;
     poBand->m_Rows		= nRows;
     poBand->m_Cols		= nCols;
-	
+
     poDS->SetBand( 1, poBand );
 
 /* -------------------------------------------------------------------- */
@@ -654,13 +634,11 @@ GDALDataset *SAGADataset::Open( GDALOpenInfo * poOpenInfo )
 
     if( fp != NULL )
     {
-        char  **papszLines;
-        OGRSpatialReference oSRS;
-
         VSIFCloseL( fp );
-        
-        papszLines = CSLLoad( pszPrjFilename );
 
+        char **papszLines = CSLLoad( pszPrjFilename );
+
+        OGRSpatialReference oSRS;
         if( oSRS.importFromESRI( papszLines ) == OGRERR_NONE )
         {
             CPLFree( poDS->pszProjection );
@@ -687,7 +665,7 @@ CPLErr SAGADataset::GetGeoTransform( double *padfGeoTransform )
     if( padfGeoTransform == NULL )
 		return CE_Failure;
 
-    SAGARasterBand *poGRB = dynamic_cast<SAGARasterBand *>(GetRasterBand( 1 ));
+    SAGARasterBand *poGRB = static_cast<SAGARasterBand *>(GetRasterBand( 1 ));
 
     if( poGRB == NULL )
     {
@@ -734,7 +712,7 @@ CPLErr SAGADataset::SetGeoTransform( double *padfGeoTransform )
         return CE_Failure;
     }
 
-    SAGARasterBand *poGRB = dynamic_cast<SAGARasterBand *>(GetRasterBand( 1 ));
+    SAGARasterBand *poGRB = static_cast<SAGARasterBand *>(GetRasterBand( 1 ));
 
     if( poGRB == NULL || padfGeoTransform == NULL)
         return CE_Failure;
@@ -747,20 +725,19 @@ CPLErr SAGADataset::SetGeoTransform( double *padfGeoTransform )
         return CE_Failure;
     }
 
-    double dfMinX = padfGeoTransform[0] + padfGeoTransform[1] / 2;
-    double dfMinY =
+    const double dfMinX = padfGeoTransform[0] + padfGeoTransform[1] / 2;
+    const double dfMinY =
         padfGeoTransform[5] * (nRasterYSize - 0.5) + padfGeoTransform[3];
 
-    CPLString osPath		= CPLGetPath( GetDescription() );
-    CPLString osName		= CPLGetBasename( GetDescription() );
-    CPLString osHDRFilename = CPLFormCIFilename( osPath, osName, ".sgrd" );
+    const CPLString osPath = CPLGetPath( GetDescription() );
+    const CPLString osName = CPLGetBasename( GetDescription() );
+    const CPLString osHDRFilename = CPLFormCIFilename( osPath, osName, ".sgrd" );
 
     CPLErr eErr = WriteHeader( osHDRFilename, poGRB->GetRasterDataType(),
                                poGRB->nRasterXSize, poGRB->nRasterYSize,
                                dfMinX, dfMinY, padfGeoTransform[1],
                                poGRB->m_NoData, 1.0, false );
 
-
     if( eErr == CE_None )
     {
         poGRB->m_Xmin = dfMinX;
@@ -784,14 +761,12 @@ CPLErr SAGADataset::WriteHeader( CPLString osHDRFilename, GDALDataType eType,
                                  double dfZFactor, bool bTopToBottom )
 
 {
-    VSILFILE	*fp;
-
-    fp = VSIFOpenL( osHDRFilename, "wt" );
+    VSILFILE	*fp = VSIFOpenL( osHDRFilename, "wt" );
 
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Failed to write .sgrd file %s.", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to write .sgrd file %s.",
                   osHDRFilename.c_str() );
         return CE_Failure;
     }
@@ -800,7 +775,7 @@ CPLErr SAGADataset::WriteHeader( CPLString osHDRFilename, GDALDataType eType,
     VSIFPrintfL( fp, "DESCRIPTION\t=\n" );
     VSIFPrintfL( fp, "UNIT\t=\n" );
     VSIFPrintfL( fp, "DATAFILE_OFFSET\t= 0\n" );
-    
+
     if( eType == GDT_Int32 )
         VSIFPrintfL( fp, "DATAFORMAT\t= INTEGER\n" );
     else if( eType == GDT_UInt32 )
@@ -812,7 +787,7 @@ CPLErr SAGADataset::WriteHeader( CPLString osHDRFilename, GDALDataType eType,
     else if( eType == GDT_Byte )
         VSIFPrintfL( fp, "DATAFORMAT\t= BYTE_UNSIGNED\n" );
     else if( eType == GDT_Float32 )
-        VSIFPrintfL( fp, "DATAFORMAT\t= FLOAT\n" );		
+        VSIFPrintfL( fp, "DATAFORMAT\t= FLOAT\n" );
     else //if( eType == GDT_Float64 )
         VSIFPrintfL( fp, "DATAFORMAT\t= DOUBLE\n" );
 #ifdef CPL_LSB
@@ -858,7 +833,7 @@ GDALDataset *SAGADataset::Create( const char * pszFilename,
 
         return NULL;
     }
-    
+
     if( nBands != 1 )
     {
         CPLError( CE_Failure, CPLE_IllegalArg,
@@ -887,8 +862,7 @@ GDALDataset *SAGADataset::Create( const char * pszFilename,
                   pszFilename );
         return NULL;
     }
-    
-    char abyNoData[8];
+
     double dfNoDataVal = 0.0;
 
     const char* pszNoDataValue = CSLFetchNameValue(papszParmList, "NODATA_VALUE");
@@ -939,10 +913,11 @@ GDALDataset *SAGADataset::Create( const char * pszFilename,
       }
     }
 
+    char abyNoData[8];
     GDALCopyWords(&dfNoDataVal, GDT_Float64, 0,
                   abyNoData, eType, 0, 1);
 
-    CPLString osHdrFilename = CPLResetExtension( pszFilename, "sgrd" );
+    const CPLString osHdrFilename = CPLResetExtension( pszFilename, "sgrd" );
     CPLErr eErr = WriteHeader( osHdrFilename, eType,
                                nXSize, nYSize,
                                0.0, 0.0, 1.0,
@@ -956,14 +931,15 @@ GDALDataset *SAGADataset::Create( const char * pszFilename,
 
     if (CSLFetchBoolean( papszParmList , "FILL_NODATA", TRUE ))
     {
-        int nDataTypeSize = GDALGetDataTypeSize(eType) / 8;
-        GByte* pabyNoDataBuf = (GByte*) VSIMalloc2(nDataTypeSize, nXSize);
+        const int nDataTypeSize = GDALGetDataTypeSize(eType) / 8;
+        GByte* pabyNoDataBuf = reinterpret_cast<GByte *>(
+            VSIMalloc2(nDataTypeSize, nXSize ) );
         if (pabyNoDataBuf == NULL)
         {
             VSIFCloseL( fp );
             return NULL;
         }
-        
+
         for( int iCol = 0; iCol < nXSize; iCol++)
         {
             memcpy(pabyNoDataBuf + iCol * nDataTypeSize, abyNoData, nDataTypeSize);
@@ -971,7 +947,8 @@ GDALDataset *SAGADataset::Create( const char * pszFilename,
 
         for( int iRow = 0; iRow < nYSize; iRow++ )
         {
-            if( VSIFWriteL( pabyNoDataBuf, nDataTypeSize, nXSize, fp ) != (unsigned)nXSize )
+            if( VSIFWriteL( pabyNoDataBuf, nDataTypeSize, nXSize, fp )
+                != static_cast<unsigned>( nXSize ) )
             {
                 VSIFCloseL( fp );
                 VSIFree(pabyNoDataBuf);
@@ -980,13 +957,14 @@ GDALDataset *SAGADataset::Create( const char * pszFilename,
                 return NULL;
             }
         }
-        
+
         VSIFree(pabyNoDataBuf);
     }
 
     VSIFCloseL( fp );
 
-    return (GDALDataset *)GDALOpen( pszFilename, GA_Update );
+    return reinterpret_cast<GDALDataset *>(
+        GDALOpen( pszFilename, GA_Update ) );
 }
 
 /************************************************************************/
@@ -1005,7 +983,7 @@ GDALDataset *SAGADataset::CreateCopy( const char *pszFilename,
     int nBands = poSrcDS->GetRasterCount();
     if (nBands == 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "SAGA driver does not support source dataset with zero band.\n");
         return NULL;
     }
@@ -1025,21 +1003,20 @@ GDALDataset *SAGADataset::CreateCopy( const char *pszFilename,
     }
 
     GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( 1 );
-    
-    char** papszCreateOptions = NULL;
-    papszCreateOptions = CSLSetNameValue(papszCreateOptions, "FILL_NODATA", "NO");
+
+    char** papszCreateOptions = CSLSetNameValue( NULL, "FILL_NODATA", "NO" );
 
     int bHasNoDataValue = FALSE;
-    double dfNoDataValue = poSrcBand->GetNoDataValue(&bHasNoDataValue);
+    const double dfNoDataValue = poSrcBand->GetNoDataValue(&bHasNoDataValue);
     if (bHasNoDataValue)
         papszCreateOptions = CSLSetNameValue(papszCreateOptions, "NODATA_VALUE",
                                              CPLSPrintf("%.16g", dfNoDataValue));
-    
+
     GDALDataset* poDstDS =
         Create(pszFilename, poSrcBand->GetXSize(), poSrcBand->GetYSize(),
                1, poSrcBand->GetRasterDataType(), papszCreateOptions);
     CSLDestroy(papszCreateOptions);
-    
+
     if (poDstDS == NULL)
         return NULL;
 
@@ -1047,13 +1024,11 @@ GDALDataset *SAGADataset::CreateCopy( const char *pszFilename,
     /*      Copy band data.	                                                */
     /* -------------------------------------------------------------------- */
 
-    CPLErr	eErr;
-    
-    eErr = GDALDatasetCopyWholeRaster( (GDALDatasetH) poSrcDS, 
-                                       (GDALDatasetH) poDstDS,
-                                       NULL,
-                                       pfnProgress, pProgressData );
-                                       
+    CPLErr eErr = GDALDatasetCopyWholeRaster( (GDALDatasetH) poSrcDS,
+                                              (GDALDatasetH) poDstDS,
+                                              NULL,
+                                              pfnProgress, pProgressData );
+
     if (eErr == CE_Failure)
     {
         delete poDstDS;
@@ -1064,7 +1039,7 @@ GDALDataset *SAGADataset::CreateCopy( const char *pszFilename,
 
     poSrcDS->GetGeoTransform( adfGeoTransform );
     poDstDS->SetGeoTransform( adfGeoTransform );
-    
+
     poDstDS->SetProjection( poSrcDS->GetProjectionRef() );
 
     return poDstDS;
@@ -1077,28 +1052,25 @@ GDALDataset *SAGADataset::CreateCopy( const char *pszFilename,
 void GDALRegister_SAGA()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "SAGA" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "SAGA" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "SAGA" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "SAGA GIS Binary Grid (.sdat)" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#SAGA" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "sdat" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
-				   "Byte Int16 UInt16 Int32 UInt32 Float32 Float64" );
-
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = SAGADataset::Open;
-        poDriver->pfnCreate = SAGADataset::Create;
-        poDriver->pfnCreateCopy = SAGADataset::CreateCopy;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "SAGA" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "SAGA GIS Binary Grid (.sdat)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#SAGA" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "sdat" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte Int16 "
+                               "UInt16 Int32 UInt32 Float32 Float64" );
+
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = SAGADataset::Open;
+    poDriver->pfnCreate = SAGADataset::Create;
+    poDriver->pfnCreateCopy = SAGADataset::CreateCopy;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/sde/frmt_sde.html b/frmts/sde/frmt_sde.html
index 69c7aa8..b3c1d5f 100644
--- a/frmts/sde/frmt_sde.html
+++ b/frmts/sde/frmt_sde.html
@@ -1,93 +1,93 @@
-<!-- $Id: frmt_sde.html 14166 2008-03-31 17:52:04Z rouault $ -->
-
-<html>
-<head>
-<title>ESRI ArcSDE Raster</title>
-</head>
-
-<body bgcolor="#ffffff">
-
-<h1>ESRI ArcSDE Raster</h1>
-<p>
-    ESRI ArcSDE provides an abstraction layer over numerous databases that 
-    allows the storage of raster data.  ArcSDE supports n-band imagery at many bit depths, 
-    and the current implementation of the GDAL driver should support 
-    as many bands as you can throw at it.  ArcSDE supports the storage of 
-    LZW, JP2K, and uncompressed data and transparently presents this through its 
-    C API SDK.  
-</p>
-<h2>GDAL ArcSDE Raster driver features</h2>
-<p>
-    The current driver <b>supports</b> the following features:
-</p>
-<ul>
-    <li><b>Read</b> support only. </li>
-    <li>GeoTransform information for rasters that have defined it.</li>
-    <li>Coordinate reference information.</li>
-    <li>Color interpretation (palette for datasets with colormaps, greyscale otherwise).</li>
-    <li>Band statistics if ArcSDE has cached them, otherwise GDAL will calculate.</li>
-    <li>ArcSDE overview (pyramid) support</li>
-    <li>1 bit, 4 bit, 8 bit, 16 bit, and 32 bit data</li>
-    <li>IReadBlock support that maps to ArcSDE's representation of the data in the database.</li>
-    <li>ArcSDE 9.1 and 9.2 SDK's.  Older versions may also work, but they have not been tested.</li>
-</ul>
-<p>
-    The current driver <b>does not support</b> the following:
-</p>
-<ul>
-    <li><b>Writing</b> GDAL datasets into the database.</li>
-    <li>Large, fast, single-pass reads from the database.</li>
-    <li>Reading from "ESRI ArcSDE Raster Catalogs."</li>
-    <li>NODATA masks.</li>
-</ul>
-
-<h2>Performance considerations</h2>
-<p>
-    The ArcSDE raster driver currently only supports block read methods.  
-    Each call to this method results in a request for a 
-    block of raster data for <b>each</b> band of data in the raster, and single-pass requests 
-    for all of the bands for a block or given area is not currently done.  
-    This approach consequently results in extra network overhead.  It is hoped 
-    that the driver will be improved to support single-pass reads in the 
-    near future.  
-</p>
-<p>
-    The ArcSDE raster driver should only consume a single ArcSDE connection 
-    throughout the lifespan of the dataset.  Each connection to the database has 
-    an overhead of approximately 2 seconds, with additional overhead that is 
-    taken for calculating dataset information.  Therefore, usage of the 
-    driver in situations where there is a lot of opening and closing of 
-    datasets is not expected to be very performant.
-</p>
-<p>
-    Although the ArcSDE C SDK does support threading and locking, the 
-    GDAL ArcSDE raster driver does not utilize this capability.  Therefore, 
-    the ArcSDE raster driver should be considered <b>not threadsafe</b>, and 
-    sharing datasets between threads will have undefined (and often disasterous) 
-    results.
-</p>
-
-<h2>Dataset specification</h2>
-<p>
-    SDE datasets are specified with the following information:
-</p>
-<pre>
- SDE:sdemachine.iastate.edu,5151,database,username,password,fully.specified.tablename,RASTER
-</pre>
-<p>
-<ul>
-    <li><b>SDE:</b> -- this is the prefix that tips off GDAL to use the SDE driver.</li>
-    <li><b>sdemachine.iastate.edu</b> -- the DNS name or IP address of the server we are connecting to.</li>
-    <li><b>5151</b> -- the port number (5151 or port:5151) or service entry (typically <i>esri_sde</i>).</li>
-    <li><b>database</b> -- the database to connect to.  This can also be blank and specified as ,,. </li>
-    <li><b>username</b> -- username.</li>
-    <li><b>password</b> -- password.</li>
-    <li><b>fully.specified.tablename</b> -- It is prudent to use a fully specified tablename wherever possible, although it is not absolutely required.</li>
-    <li><b>RASTER</b> -- </i>Optional</i> raster column name. </li>
-</ul>
-
-
-
-
-</body>
-</html>
+<!-- $Id: frmt_sde.html 33795 2016-03-27 03:34:36Z goatbar $ -->
+
+<html>
+<head>
+<title>ESRI ArcSDE Raster</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>ESRI ArcSDE Raster</h1>
+<p>
+    ESRI ArcSDE provides an abstraction layer over numerous databases that
+    allows the storage of raster data.  ArcSDE supports n-band imagery at many bit depths,
+    and the current implementation of the GDAL driver should support
+    as many bands as you can throw at it.  ArcSDE supports the storage of
+    LZW, JP2K, and uncompressed data and transparently presents this through its
+    C API SDK.
+</p>
+<h2>GDAL ArcSDE Raster driver features</h2>
+<p>
+    The current driver <b>supports</b> the following features:
+</p>
+<ul>
+    <li><b>Read</b> support only. </li>
+    <li>GeoTransform information for rasters that have defined it.</li>
+    <li>Coordinate reference information.</li>
+    <li>Color interpretation (palette for datasets with colormaps, greyscale otherwise).</li>
+    <li>Band statistics if ArcSDE has cached them, otherwise GDAL will calculate.</li>
+    <li>ArcSDE overview (pyramid) support</li>
+    <li>1 bit, 4 bit, 8 bit, 16 bit, and 32 bit data</li>
+    <li>IReadBlock support that maps to ArcSDE's representation of the data in the database.</li>
+    <li>ArcSDE 9.1 and 9.2 SDK's.  Older versions may also work, but they have not been tested.</li>
+</ul>
+<p>
+    The current driver <b>does not support</b> the following:
+</p>
+<ul>
+    <li><b>Writing</b> GDAL datasets into the database.</li>
+    <li>Large, fast, single-pass reads from the database.</li>
+    <li>Reading from "ESRI ArcSDE Raster Catalogs."</li>
+    <li>NODATA masks.</li>
+</ul>
+
+<h2>Performance considerations</h2>
+<p>
+    The ArcSDE raster driver currently only supports block read methods.
+    Each call to this method results in a request for a
+    block of raster data for <b>each</b> band of data in the raster, and single-pass requests
+    for all of the bands for a block or given area is not currently done.
+    This approach consequently results in extra network overhead.  It is hoped
+    that the driver will be improved to support single-pass reads in the
+    near future.
+</p>
+<p>
+    The ArcSDE raster driver should only consume a single ArcSDE connection
+    throughout the lifespan of the dataset.  Each connection to the database has
+    an overhead of approximately 2 seconds, with additional overhead that is
+    taken for calculating dataset information.  Therefore, usage of the
+    driver in situations where there is a lot of opening and closing of
+    datasets is not expected to be very performant.
+</p>
+<p>
+    Although the ArcSDE C SDK does support threading and locking, the
+    GDAL ArcSDE raster driver does not utilize this capability.  Therefore,
+    the ArcSDE raster driver should be considered <b>not threadsafe</b>, and
+    sharing datasets between threads will have undefined (and often disastrous)
+    results.
+</p>
+
+<h2>Dataset specification</h2>
+<p>
+    SDE datasets are specified with the following information:
+</p>
+<pre>
+ SDE:sdemachine.iastate.edu,5151,database,username,password,fully.specified.tablename,RASTER
+</pre>
+<p>
+<ul>
+    <li><b>SDE:</b> -- this is the prefix that tips off GDAL to use the SDE driver.</li>
+    <li><b>sdemachine.iastate.edu</b> -- the DNS name or IP address of the server we are connecting to.</li>
+    <li><b>5151</b> -- the port number (5151 or port:5151) or service entry (typically <i>esri_sde</i>).</li>
+    <li><b>database</b> -- the database to connect to.  This can also be blank and specified as ,,. </li>
+    <li><b>username</b> -- username.</li>
+    <li><b>password</b> -- password.</li>
+    <li><b>fully.specified.tablename</b> -- It is prudent to use a fully specified tablename wherever possible, although it is not absolutely required.</li>
+    <li><b>RASTER</b> -- </i>Optional</i> raster column name. </li>
+</ul>
+
+
+
+
+</body>
+</html>
diff --git a/frmts/sde/gdal_sde.h b/frmts/sde/gdal_sde.h
index ac6968d..20a8698 100644
--- a/frmts/sde/gdal_sde.h
+++ b/frmts/sde/gdal_sde.h
@@ -4,12 +4,10 @@
 #include "gdal_pam.h"
 
 
-CPL_CVSID("$Id: gdal_sde.h 10726 2007-01-30 04:43:45Z hobu $");
+CPL_CVSID("$Id: gdal_sde.h 32190 2015-12-16 13:50:27Z goatbar $");
 
 CPL_C_START
-void    GDALRegister_SDE(void);
-
-
+void GDALRegister_SDE();
 CPL_C_END
 
 #include <sdetype.h>
diff --git a/frmts/sde/sdedataset.cpp b/frmts/sde/sdedataset.cpp
index 7c4dc68..255e80f 100644
--- a/frmts/sde/sdedataset.cpp
+++ b/frmts/sde/sdedataset.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: sdedataset.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: sdedataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  ESRI ArcSDE Raster reader
- * Purpose:  Dataset implementaion for ESRI ArcSDE Rasters
+ * Purpose:  Dataset implementation for ESRI ArcSDE Rasters
  * Author:   Howard Butler, hobu at hobu.net
  *
  * This work was sponsored by the Geological Survey of Canada, Natural
@@ -30,9 +30,9 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "gdal_frmts.h"
 #include "sdedataset.h"
 
-
 /************************************************************************/
 /*                          GetRastercount()                            */
 /************************************************************************/
@@ -41,7 +41,7 @@ int SDEDataset::GetRasterCount( void )
 
 {
     return nBands;
-}    
+}
 
 /************************************************************************/
 /*                          GetRasterXSize()                            */
@@ -51,7 +51,7 @@ int SDEDataset::GetRasterXSize( void )
 
 {
     return nRasterXSize;
-}  
+}
 
 /************************************************************************/
 /*                          GetRasterYSize()                            */
@@ -70,38 +70,38 @@ int SDEDataset::GetRasterYSize( void )
 CPLErr SDEDataset::ComputeRasterInfo() {
     long nSDEErr;
     SE_RASTERINFO raster;
-    
+
     nSDEErr = SE_rasterinfo_create(&raster);
     if( nSDEErr != SE_SUCCESS )
     {
         IssueSDEError( nSDEErr, "SE_rasterinfo_create" );
         return CE_Fatal;
     }
-    
+
     LONG nRasterColumnId = 0;
 
-    nSDEErr = SE_rascolinfo_get_id( hRasterColumn, 
+    nSDEErr = SE_rascolinfo_get_id( hRasterColumn,
                                     &nRasterColumnId);
     if( nSDEErr != SE_SUCCESS )
     {
         IssueSDEError( nSDEErr, "SE_rascolinfo_get_id" );
         return CE_Fatal;
-    }        
+    }
 
-    nSDEErr = SE_raster_get_info_by_id( hConnection, 
-                                        nRasterColumnId, 
-                                        1, 
+    nSDEErr = SE_raster_get_info_by_id( hConnection,
+                                        nRasterColumnId,
+                                        1,
                                         raster);
     if( nSDEErr != SE_SUCCESS )
     {
         IssueSDEError( nSDEErr, "SE_rascolinfo_get_id" );
         return CE_Fatal;
     }
-    
+
     LONG nBandsRet;
-    nSDEErr = SE_raster_get_bands(  hConnection, 
-                                    raster, 
-                                    &paohSDERasterBands, 
+    nSDEErr = SE_raster_get_bands(  hConnection,
+                                    raster,
+                                    &paohSDERasterBands,
                                     &nBandsRet);
     if( nSDEErr != SE_SUCCESS )
     {
@@ -110,12 +110,12 @@ CPLErr SDEDataset::ComputeRasterInfo() {
     }
 
     nBands = nBandsRet;
-    
+
     SE_RASBANDINFO band;
-    
+
     // grab our other stuff from the first band and hope for the best
     band = paohSDERasterBands[0];
-    
+
     LONG nXSRet, nYSRet;
     nSDEErr = SE_rasbandinfo_get_band_size( band, &nXSRet, &nYSRet );
     if( nSDEErr != SE_SUCCESS )
@@ -126,7 +126,7 @@ CPLErr SDEDataset::ComputeRasterInfo() {
 
     nRasterXSize = nXSRet;
     nRasterYSize = nYSRet;
-    
+
     SE_ENVELOPE extent;
     nSDEErr = SE_rasbandinfo_get_extent(band, &extent);
     if( nSDEErr != SE_SUCCESS )
@@ -143,22 +143,22 @@ CPLErr SDEDataset::ComputeRasterInfo() {
 
     // x0 roughly corresponds to dfMinX
     // y0 roughly corresponds to dfMaxY
-    // They can be different than the extent parameters because 
-    // SDE uses offsets.  The following info is from Duarte Carreira 
+    // They can be different than the extent parameters because
+    // SDE uses offsets.  The following info is from Duarte Carreira
     // in relation to bug #2063 http://trac.osgeo.org/gdal/ticket/2063 :
 
-    // Depending on how the data was loaded, the pixel width 
+    // Depending on how the data was loaded, the pixel width
     // or pixel height may include a pixel offset from the nearest
-    // tile boundary. An offset will be indicated by aplus sign 
-    // "+" followed by a value. The value indicates the number 
+    // tile boundary. An offset will be indicated by aplus sign
+    // "+" followed by a value. The value indicates the number
     // of pixels the nearest tile boundary is to the left of
     // the image for the x dimension or the number of
-    // pixels the nearest tile boundary is above the image for 
-    // the y dimension. The offset information is only useful 
-    // for advanced application developers who need to know 
+    // pixels the nearest tile boundary is above the image for
+    // the y dimension. The offset information is only useful
+    // for advanced application developers who need to know
     // where the image begins in relation to the underlying tile structure
 
-    LFLOAT x0, y0; 
+    LFLOAT x0, y0;
     nSDEErr = SE_rasbandinfo_get_tile_origin(band, &x0, &y0);
     if( nSDEErr != SE_SUCCESS )
     {
@@ -181,7 +181,7 @@ CPLErr SDEDataset::ComputeRasterInfo() {
         IssueSDEError( nSDEErr, "SE_rasterattr_create" );
         return CE_Fatal;
     }
-    
+
     // Grab the pointer for our member variable
 
     nSDEErr = SE_stream_create(hConnection, &hStream);
@@ -191,15 +191,15 @@ CPLErr SDEDataset::ComputeRasterInfo() {
         return CE_Fatal;
     }
 
-    
+
     for (int i=0; i < nBands; i++) {
         SetBand( i+1, new SDERasterBand( this, i+1, -1, &(paohSDERasterBands[i]) ));
     }
 
     GDALRasterBand* b = GetRasterBand(1);
-    
+
     eDataType = b->GetRasterDataType();
-    
+
     SE_rasterinfo_free(raster);
 
     return CE_None;
@@ -213,19 +213,19 @@ CPLErr SDEDataset::ComputeRasterInfo() {
 CPLErr SDEDataset::GetGeoTransform( double * padfTransform )
 
 {
-    
+
     if (dfMinX == 0.0 && dfMinY == 0.0 && dfMaxX == 0.0 && dfMaxY == 0.0)
         return CE_Fatal;
- 
+
     padfTransform[0] = dfMinX - 0.5*(dfMaxX - dfMinX) / (GetRasterXSize()-1);
     padfTransform[3] = dfMaxY + 0.5*(dfMaxY - dfMinY) / (GetRasterYSize()-1);
-    
+
     padfTransform[1] = (dfMaxX - dfMinX) / (GetRasterXSize()-1);
     padfTransform[2] = 0.0;
-        
+
     padfTransform[4] = 0.0;
     padfTransform[5] = -1 * (dfMaxY - dfMinY) / (GetRasterYSize()-1);
-    
+
     return CE_None;
 }
 
@@ -245,24 +245,24 @@ const char *SDEDataset::GetProjectionRef()
         IssueSDEError( nSDEErr, "SE_coordref_create" );
         return FALSE;
     }
-    
+
     if (!hRasterColumn){
         CPLError ( CE_Failure, CPLE_AppDefined,
-                   "Raster Column not defined");        
-        return ("");   
+                   "Raster Column not defined");
+        return ("");
     }
-    
+
     nSDEErr = SE_rascolinfo_get_coordref(hRasterColumn, coordref);
 
     if (nSDEErr == SE_NO_COORDREF) {
         return ("");
     }
-    
+
     if( nSDEErr != SE_SUCCESS )
     {
         IssueSDEError( nSDEErr, "SE_rascolinfo_get_coordref" );
-    }    
-    
+    }
+
     char szWKT[SE_MAX_SPATIALREF_SRTEXT_LEN];
     nSDEErr = SE_coordref_get_description(coordref, szWKT);
     if (nSDEErr != SE_SUCCESS )
@@ -278,7 +278,7 @@ const char *SDEDataset::GetProjectionRef()
 
     poSRS->exportToWkt(&pszWKT);
     poSRS->Release();
-    
+
     return pszWKT;
 }
 
@@ -304,7 +304,7 @@ SDEDataset::SDEDataset(  )
     nBands              = 0;
     nRasterXSize        = 0;
     nRasterYSize        = 0;
-    
+
     dfMinX              = 0.0;
     dfMinY              = 0.0;
     dfMaxX              = 0.0;
@@ -328,19 +328,19 @@ SDEDataset::~SDEDataset()
 
     if (hRasterColumn)
         SE_rascolinfo_free(hRasterColumn);
-    
+
     if (hStream)
         SE_stream_free(hStream);
-        
+
     if (hAttributes)
         SE_rasterattr_free(hAttributes);
 
     if (hConnection)
         SE_connection_free(hConnection);
-        
+
     if (pszWKT)
         CPLFree(pszWKT);
-    
+
     if (pszLayerName)
         CPLFree(pszLayerName);
 
@@ -356,33 +356,33 @@ SDEDataset::~SDEDataset()
 GDALDataset *SDEDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    
+
 /* -------------------------------------------------------------------- */
 /*      If we aren't prefixed with SDE: then ignore this datasource.    */
 /* -------------------------------------------------------------------- */
-    if( !EQUALN(poOpenInfo->pszFilename,"SDE:",4) )
+    if( !STARTS_WITH_CI(poOpenInfo->pszFilename, "SDE:") )
         return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Parse arguments on comma.  We expect (layer is optional):       */
 /*        SDE:server,instance,database,username,password,layer          */
 /* -------------------------------------------------------------------- */
-    char **papszTokens = CSLTokenizeStringComplex(  poOpenInfo->pszFilename+4, 
+    char **papszTokens = CSLTokenizeStringComplex(  poOpenInfo->pszFilename+4,
                                                     ",",
-                                                    TRUE, 
+                                                    TRUE,
                                                     TRUE );
-    CPLDebug(   "SDERASTER", "Open(\"%s\") revealed %d tokens.", 
+    CPLDebug(   "SDERASTER", "Open(\"%s\") revealed %d tokens.",
                 poOpenInfo->pszFilename,
                 CSLCount( papszTokens ) );
 
 
     if( CSLCount( papszTokens ) < 5 || CSLCount( papszTokens ) > 7 )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "SDE connect string had wrong number of arguments.\n"
                   "Expected 'SDE:server,instance,database,username,password,layer'\n"
                   "The layer name value is optional.\n"
-                  "Got '%s'", 
+                  "Got '%s'",
                   poOpenInfo->pszFilename );
         return NULL;
     }
@@ -399,12 +399,12 @@ GDALDataset *SDEDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     int         nSDEErr;
     SE_ERROR    hSDEErrorInfo;
-    nSDEErr = SE_connection_create( papszTokens[0], 
-                                    papszTokens[1], 
-                                    papszTokens[2], 
+    nSDEErr = SE_connection_create( papszTokens[0],
+                                    papszTokens[1],
+                                    papszTokens[2],
                                     papszTokens[3],
                                     papszTokens[4],
-                                    &(hSDEErrorInfo), 
+                                    &(hSDEErrorInfo),
                                     &(poDS->hConnection) );
 
     if( nSDEErr != SE_SUCCESS )
@@ -438,14 +438,13 @@ GDALDataset *SDEDataset::Open( GDALOpenInfo * poOpenInfo )
     else {
         poDS->pszColumnName = CPLStrdup( "RASTER" );
     }
-    
+
     CPLDebug ("SDERASTER", "SDE Column name is '%s'", poDS->pszColumnName);
 
     if (CSLCount( papszTokens ) >= 6 ) {
 
         poDS->pszLayerName = CPLStrdup( papszTokens[5] );
 
-        
         nSDEErr =   SE_rascolinfo_create  (&(poDS->hRasterColumn));
         if( nSDEErr != SE_SUCCESS )
         {
@@ -453,12 +452,12 @@ GDALDataset *SDEDataset::Open( GDALOpenInfo * poOpenInfo )
             return NULL;
         }
         CPLDebug( "SDERASTER", "'%s' raster layer specified... "\
-                               "using it directly with '%s' as the raster column name.", 
+                               "using it directly with '%s' as the raster column name.",
                   poDS->pszLayerName,
                   poDS->pszColumnName);
-        nSDEErr = SE_rastercolumn_get_info_by_name( poDS->hConnection, 
-                                                    poDS->pszLayerName, 
-                                                    poDS->pszColumnName, 
+        nSDEErr = SE_rastercolumn_get_info_by_name( poDS->hConnection,
+                                                    poDS->pszLayerName,
+                                                    poDS->pszColumnName,
                                                     poDS->hRasterColumn);
         if( nSDEErr != SE_SUCCESS )
         {
@@ -470,9 +469,9 @@ GDALDataset *SDEDataset::Open( GDALOpenInfo * poOpenInfo )
 
 
     } else {
- 
-        nSDEErr = SE_rastercolumn_get_info_list(poDS->hConnection, 
-                                                &(poDS->paohSDERasterColumns), 
+
+        nSDEErr = SE_rastercolumn_get_info_list(poDS->hConnection,
+                                                &(poDS->paohSDERasterColumns),
                                                 &(poDS->nSubDataCount));
         if( nSDEErr != SE_SUCCESS )
         {
@@ -480,20 +479,19 @@ GDALDataset *SDEDataset::Open( GDALOpenInfo * poOpenInfo )
             return NULL;
         }
 
-        CPLDebug( "SDERASTER", "No layername specified, %d subdatasets available.", 
+        CPLDebug( "SDERASTER", "No layername specified, %d subdatasets available.",
                   poDS->nSubDataCount);
-                  
 
         for (int i = 0; i < poDS->nSubDataCount; i++) {
 
               char         szTableName[SE_QUALIFIED_TABLE_NAME+1];
               char         szColumnName[SE_MAX_COLUMN_LEN+1];
-            nSDEErr = SE_rascolinfo_get_raster_column (poDS->paohSDERasterColumns[i], 
-                                                       szTableName, 
-                                                       szColumnName); 
-            CPLDebug(   "SDERASTER", 
-                        "Layer '%s' with column '%s' found.", 
-                        szTableName, 
+            nSDEErr = SE_rascolinfo_get_raster_column (poDS->paohSDERasterColumns[i],
+                                                       szTableName,
+                                                       szColumnName);
+            CPLDebug(   "SDERASTER",
+                        "Layer '%s' with column '%s' found.",
+                        szTableName,
                         szColumnName);
 
             if( nSDEErr != SE_SUCCESS )
@@ -516,24 +514,20 @@ GDALDataset *SDEDataset::Open( GDALOpenInfo * poOpenInfo )
 void GDALRegister_SDE()
 
 {
-    GDALDriver  *poDriver;
-    
-    if (! GDAL_CHECK_VERSION("SDE driver"))
+    if( !GDAL_CHECK_VERSION( "SDE driver" ) )
         return;
 
-    if( GDALGetDriverByName( "SDE" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "SDE" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "ESRI ArcSDE" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#SDE" );
-
-        poDriver->pfnOpen = SDEDataset::Open;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    if( GDALGetDriverByName( "SDE" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "SDE" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "ESRI ArcSDE" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,  "frmt_various.html#SDE" );
+
+    poDriver->pfnOpen = SDEDataset::Open;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/sde/sdedataset.h b/frmts/sde/sdedataset.h
index ac70e74..39de68b 100644
--- a/frmts/sde/sdedataset.h
+++ b/frmts/sde/sdedataset.h
@@ -9,35 +9,31 @@ class SDEDataset : public GDALDataset
     friend class SDERasterBand;
 
     private:
-        
-
         LONG                nSubDataCount;
         char*               pszWKT;
-        
+
         double              dfMinX, dfMaxX, dfMinY, dfMaxY;
-        
+
         GDALDataType        eDataType;
         SE_RASCOLINFO*      paohSDERasterColumns;
         SE_RASCOLINFO       hRasterColumn;
-    
-        
+
+
         CPLErr              ComputeRasterInfo(void);
         SE_RASBANDINFO*     paohSDERasterBands;
-        
+
     public:
         SDEDataset();
         ~SDEDataset();
-        
-        static GDALDataset *Open( GDALOpenInfo * );
- 
 
-    protected:        
+        static GDALDataset *Open( GDALOpenInfo * );
 
+    protected:
         // SDE-specific stuff
         SE_CONNECTION      hConnection;
         SE_RASTERATTR      hAttributes;
         SE_STREAM          hStream;
-        
+
         char                *pszLayerName;
         char                *pszColumnName;
 
@@ -45,10 +41,8 @@ class SDEDataset : public GDALDataset
         virtual int     GetRasterCount(void);
         virtual int     GetRasterXSize(void);
         virtual int     GetRasterYSize(void);
-        
+
         const char *GetProjectionRef();
 };
 
-
-
 #endif
diff --git a/frmts/sde/sdeerror.cpp b/frmts/sde/sdeerror.cpp
index 3999327..d55b898 100644
--- a/frmts/sde/sdeerror.cpp
+++ b/frmts/sde/sdeerror.cpp
@@ -6,7 +6,7 @@
 /* from ogrsdedatasource.cpp                                            */
 /************************************************************************/
 
-void IssueSDEError( int nErrorCode, 
+void IssueSDEError( int nErrorCode,
                     const char *pszFunction )
 
 {
@@ -17,8 +17,8 @@ void IssueSDEError( int nErrorCode,
 
     SE_error_get_string( nErrorCode, szErrorMsg );
 
-    CPLError( CE_Failure, CPLE_AppDefined, 
-              "%s: %d/%s", 
+    CPLError( CE_Failure, CPLE_AppDefined,
+              "%s: %d/%s",
               pszFunction, nErrorCode, szErrorMsg );
 }
 
@@ -29,7 +29,7 @@ void IssueSDEExtendedError ( int nErrorCode,
                            const char *pszFunction,
                            SE_CONNECTION* connection,
                            SE_STREAM* stream) {
- 
+
     SE_ERROR err;
     char szErrorMsg[SE_MAX_MESSAGE_LENGTH+1];
 
@@ -38,22 +38,21 @@ void IssueSDEExtendedError ( int nErrorCode,
 
     SE_error_get_string( nErrorCode, szErrorMsg );
 
-        
     if (connection)
         SE_connection_get_ext_error( *connection, &err );
     if (stream)
         SE_stream_get_ext_error( *stream, &err );
-    
+
     if (connection || stream) {
         CPLError ( CE_Failure, CPLE_AppDefined,
                    "%s: %d/%s ---- %s ---- %s ---- %s ---- %s",
-                   pszFunction, nErrorCode, szErrorMsg, 
+                   pszFunction, nErrorCode, szErrorMsg,
                    err.sde_error, err.ext_error,
-                   err.err_msg1, err.err_msg2 );           
+                   err.err_msg1, err.err_msg2 );
 
     } else {
         CPLError ( CE_Failure, CPLE_AppDefined,
            "%s: %d/%s",
            pszFunction, nErrorCode, szErrorMsg );
-    } 
+    }
 }
diff --git a/frmts/sde/sdeerror.h b/frmts/sde/sdeerror.h
index 9e1422d..900320d 100644
--- a/frmts/sde/sdeerror.h
+++ b/frmts/sde/sdeerror.h
@@ -4,12 +4,10 @@
 
 #include "gdal_sde.h"
 
-void IssueSDEError( int nErrorCode, 
+void IssueSDEError( int nErrorCode,
                     const char *pszFunction );
 void IssueSDEExtendedError ( int nErrorCode,
                            const char *pszFunction,
                            SE_CONNECTION* connection,
                            SE_STREAM* stream);
-                           
-
 #endif
diff --git a/frmts/sde/sderasterband.cpp b/frmts/sde/sderasterband.cpp
index 647f794..6ab6fb4 100644
--- a/frmts/sde/sderasterband.cpp
+++ b/frmts/sde/sderasterband.cpp
@@ -2,7 +2,7 @@
  * $Id: sdedataset.cpp 10804 2007-02-08 23:24:59Z hobu $
  *
  * Project:  ESRI ArcSDE Raster reader
- * Purpose:  Rasterband implementaion for ESRI ArcSDE Rasters
+ * Purpose:  Rasterband implementation for ESRI ArcSDE Rasters
  * Author:   Howard Butler, hobu at hobu.net
  *
  * This work was sponsored by the Geological Survey of Canada, Natural
@@ -30,11 +30,9 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-
 #include "sderasterband.h"
 
 
-
 /************************************************************************/
 /*  SDERasterBand implements a GDAL RasterBand for ArcSDE.  This class  */
 /*  carries around a pointer to SDE's internal band representation      */
@@ -59,14 +57,14 @@
 /*  large overhead.                                                     */
 /*                                                                      */
 /*  Once the band or overview band is established, querying raster      */
-/*  blocks does not carry much more network overhead than that requied  */
+/*  blocks does not carry much more network overhead than that required */
 /*  to actually download the bytes.                                     */
 /*                                                                      */
 /*  Overview of internal methods:                                       */
 /*      -- InitializeBand - does most of the work of construction       */
 /*                          of the band and communication with SDE.     */
 /*                          Calls InitializeConstraint and              */
-/*                          IntializeQuery.                             */
+/*                          InitializeQuery.                             */
 /*      -- InitializeQuery -    Initializes a SDE queryinfo object      */
 /*                              that contains information about which   */
 /*                              tables we are querying from.            */
@@ -90,30 +88,30 @@
 /*                           SDERasterBand()                            */
 /************************************************************************/
 
-SDERasterBand::SDERasterBand(   SDEDataset *poDS, 
-                                int nBand, 
-                                int nOverview, 
+SDERasterBand::SDERasterBand(   SDEDataset *poDS,
+                                int nBand,
+                                int nOverview,
                                 const SE_RASBANDINFO* band )
 
 {
-    // Carry some of the data we were given at construction.  
-    // If we were passed -1 for an overview at construction, reset it 
+    // Carry some of the data we were given at construction.
+    // If we were passed -1 for an overview at construction, reset it
     // to 0 to ensure we get the zero'th level from SDE.
-    // The SE_RASBANDINFO* we were given is actually owned by the 
+    // The SE_RASBANDINFO* we were given is actually owned by the
     // dataset.  We want it around for convenience.
     this->poDS = poDS;
     this->nBand = nBand;
     this->nOverview = nOverview;
     this->poBand = band;
-    
+
     // Initialize our SDE opaque object pointers to NULL.
-    // The nOverviews private data member will be updated when 
-    // GetOverviewCount is called and subsequently returned immediately in 
+    // The nOverviews private data member will be updated when
+    // GetOverviewCount is called and subsequently returned immediately in
     // later calls if it has been set to anything other than 0.
     this->hConstraint = NULL;
     this->hQuery = NULL;
     this->poColorTable = NULL;
-    
+
     if (this->nOverview == -1 || this->nOverview == 0)
         this->nOverviews = GetOverviewCount();
     else
@@ -126,12 +124,12 @@ SDERasterBand::SDERasterBand(   SDEDataset *poDS,
         this->papoOverviews = NULL;
     }
     this->eDataType = GetRasterDataType();
-    
+
     // nSDERasterType is set by GetRasterDataType
     this->dfDepth = MorphESRIRasterDepth(nSDERasterType);
     InitializeBand(this->nOverview);
 
-    
+
 }
 
 /************************************************************************/
@@ -139,7 +137,7 @@ SDERasterBand::SDERasterBand(   SDEDataset *poDS,
 /************************************************************************/
 SDERasterBand::~SDERasterBand( void )
 
-{ 
+{
 
     if (hQuery)
         SE_queryinfo_free(hQuery);
@@ -151,7 +149,7 @@ SDERasterBand::~SDERasterBand( void )
         for (int i=0; i < nOverviews; i++)
             delete papoOverviews[i];
         CPLFree(papoOverviews);
-    
+
     if (poColorTable != NULL)
         delete poColorTable;
 }
@@ -160,9 +158,8 @@ SDERasterBand::~SDERasterBand( void )
 /************************************************************************/
 /*                             GetColorTable()                          */
 /************************************************************************/
-GDALColorTable* SDERasterBand::GetColorTable(void) 
+GDALColorTable* SDERasterBand::GetColorTable(void)
 {
-    
     if (SE_rasbandinfo_has_colormap(*poBand)) {
         if (poColorTable == NULL)
             ComputeColorTable();
@@ -179,9 +176,9 @@ GDALColorTable* SDERasterBand::GetColorTable(void)
 GDALColorInterp SDERasterBand::GetColorInterpretation()
 {
     // Only return Paletted images when SDE has a colormap.  Otherwise,
-    // just return gray, even in the instance where we have 3 or 4 band, 
+    // just return gray, even in the instance where we have 3 or 4 band,
     // imagery.  Let the client be smart instead of trying to do too much.
-    if (SE_rasbandinfo_has_colormap(*poBand)) 
+    if (SE_rasbandinfo_has_colormap(*poBand))
         return GCI_PaletteIndex;
     else
         return GCI_GrayIndex;
@@ -198,8 +195,6 @@ GDALRasterBand* SDERasterBand::GetOverview( int nOverviewValue )
     }
     else
         return NULL;
-
-    
 }
 
 /************************************************************************/
@@ -212,7 +207,7 @@ int SDERasterBand::GetOverviewCount( void )
     long nSDEErr;
     BOOL bSkipLevel;
     LONG nOvRet;
-    
+
     // return nothing if we were an overview band
     if (nOverview != -1)
         return 0;
@@ -222,20 +217,20 @@ int SDERasterBand::GetOverviewCount( void )
     {
         IssueSDEError( nSDEErr, "SE_rasbandinfo_get_band_size" );
     }
-    
+
     nOverviews = nOvRet;
 
     return nOverviews;
-} 
+}
 
 /************************************************************************/
 /*                             GetRasterDataType()                      */
 /************************************************************************/
-GDALDataType SDERasterBand::GetRasterDataType(void) 
+GDALDataType SDERasterBand::GetRasterDataType(void)
 {
     // Always ask SDE what it thinks our type is.
     LONG nSDEErr;
-    
+
     nSDEErr = SE_rasbandinfo_get_pixel_type(*poBand, &nSDERasterType);
     if( nSDEErr != SE_SUCCESS )
     {
@@ -251,14 +246,14 @@ GDALDataType SDERasterBand::GetRasterDataType(void)
 /************************************************************************/
 
 CPLErr SDERasterBand::GetStatistics( int bApproxOK, int bForce,
-                                      double *pdfMin, double *pdfMax, 
-                                      double *pdfMean, double *pdfStdDev ) 
+                                      double *pdfMin, double *pdfMax,
+                                      double *pdfMean, double *pdfStdDev )
 {
-    // if SDE hasn't already cached our statistics, we'll depend on the 
+    // if SDE hasn't already cached our statistics, we'll depend on the
     // GDALRasterBands's method for getting them.
     bool bHasStats;
     bHasStats = SE_rasbandinfo_has_stats (*poBand);
-    if (!bHasStats) 
+    if (!bHasStats)
         return GDALRasterBand::GetStatistics(    bApproxOK,
                                                     bForce,
                                                     pdfMin,
@@ -266,10 +261,10 @@ CPLErr SDERasterBand::GetStatistics( int bApproxOK, int bForce,
                                                     pdfMean,
                                                     pdfStdDev);
 
-    // bForce has no effect currently.  We always go to SDE to get our 
+    // bForce has no effect currently.  We always go to SDE to get our
     // stats if SDE has them.
-    
-    // bApproxOK has no effect currently.  If we're getting stats from 
+
+    // bApproxOK has no effect currently.  If we're getting stats from
     // SDE, we're hoping SDE calculates them in the way we want.
     long nSDEErr;
     nSDEErr = SE_rasbandinfo_get_stats_min(*poBand, pdfMin);
@@ -277,14 +272,14 @@ CPLErr SDERasterBand::GetStatistics( int bApproxOK, int bForce,
     {
         IssueSDEError( nSDEErr, "SE_rasbandinfo_get_stats_min" );
         return CE_Fatal;
-    }  
+    }
 
     nSDEErr = SE_rasbandinfo_get_stats_max(*poBand, pdfMax);
     if( nSDEErr != SE_SUCCESS )
     {
         IssueSDEError( nSDEErr, "SE_rasbandinfo_get_stats_max" );
         return CE_Fatal;
-    } 
+    }
 
     nSDEErr = SE_rasbandinfo_get_stats_mean(*poBand, pdfMean);
     if( nSDEErr != SE_SUCCESS )
@@ -298,7 +293,7 @@ CPLErr SDERasterBand::GetStatistics( int bApproxOK, int bForce,
     {
         IssueSDEError( nSDEErr, "SE_rasbandinfo_get_stats_stddev" );
         return CE_Fatal;
-    } 
+    }
     return CE_None;
 }
 
@@ -306,13 +301,13 @@ CPLErr SDERasterBand::GetStatistics( int bApproxOK, int bForce,
 /*                             GetMinimum()                             */
 /************************************************************************/
 
-double SDERasterBand::GetMinimum(int *pbSuccess) 
+double SDERasterBand::GetMinimum(int *pbSuccess)
 {
     double dfMin, dfMax, dfMean, dfStdDev;
-    CPLErr error = GetStatistics( TRUE, TRUE, 
+    CPLErr error = GetStatistics( TRUE, TRUE,
                                   &dfMin,
-                                  &dfMax, 
-                                  &dfMean, 
+                                  &dfMax,
+                                  &dfMean,
                                   &dfStdDev );
     if (error == CE_None) {
         *pbSuccess = TRUE;
@@ -326,13 +321,13 @@ double SDERasterBand::GetMinimum(int *pbSuccess)
 /*                             GetMaximum()                             */
 /************************************************************************/
 
-double SDERasterBand::GetMaximum(int *pbSuccess) 
+double SDERasterBand::GetMaximum(int *pbSuccess)
 {
     double dfMin, dfMax, dfMean, dfStdDev;
-    CPLErr error = GetStatistics( TRUE, TRUE, 
+    CPLErr error = GetStatistics( TRUE, TRUE,
                                   &dfMin,
-                                  &dfMax, 
-                                  &dfMean, 
+                                  &dfMax,
+                                  &dfMean,
                                   &dfStdDev );
     if (error == CE_None) {
         *pbSuccess = TRUE;
@@ -346,7 +341,7 @@ double SDERasterBand::GetMaximum(int *pbSuccess)
 /*                             IReadBlock()                             */
 /************************************************************************/
 
-CPLErr SDERasterBand::IReadBlock( int nBlockXOff, 
+CPLErr SDERasterBand::IReadBlock( int nBlockXOff,
                                   int nBlockYOff,
                                   void * pImage )
 
@@ -355,9 +350,9 @@ CPLErr SDERasterBand::IReadBlock( int nBlockXOff,
     SDEDataset *poGDS = (SDEDataset *) poDS;
 
 
-    // SDE manages the acquisition of raster data in "TileInfo" objects.  
-    // The hTile is the only heap-allocated object in this method, and 
-    // we should make sure to delete it at the end.  Once we get the 
+    // SDE manages the acquisition of raster data in "TileInfo" objects.
+    // The hTile is the only heap-allocated object in this method, and
+    // we should make sure to delete it at the end.  Once we get the
     // pixel data, we'll memcopy it back on to the pImage pointer.
 
     SE_RASTILEINFO hTile;
@@ -369,10 +364,10 @@ CPLErr SDERasterBand::IReadBlock( int nBlockXOff,
         return CE_Fatal;
     }
 
-    hConstraint = InitializeConstraint( (long*) &nBlockXOff, (long*) &nBlockYOff );  
+    hConstraint = InitializeConstraint( (long*) &nBlockXOff, (long*) &nBlockYOff );
     if (!hConstraint)
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "ConstraintInfo initialization failed");   
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "ConstraintInfo initialization failed");
 
     CPLErr error = QueryRaster(hConstraint);
     if (error != CE_None)
@@ -384,14 +379,14 @@ CPLErr SDERasterBand::IReadBlock( int nBlockXOff,
     {
         IssueSDEError( nSDEErr, "SE_rastileinfo_get_level" );
         return CE_Fatal;
-    }   
+    }
 
     nSDEErr = SE_stream_get_raster_tile(poGDS->hStream, hTile);
     if( nSDEErr != SE_SUCCESS )
     {
         IssueSDEError( nSDEErr, "SE_stream_get_raster_tile" );
         return CE_Fatal;
-    }        
+    }
 
     LONG row, column;
     nSDEErr = SE_rastileinfo_get_rowcol(hTile, &row, &column);
@@ -399,7 +394,7 @@ CPLErr SDERasterBand::IReadBlock( int nBlockXOff,
     {
         IssueSDEError( nSDEErr, "SE_rastileinfo_get_level" );
         return CE_Fatal;
-    }     
+    }
 
     LONG length;
     unsigned char* pixels;
@@ -408,7 +403,7 @@ CPLErr SDERasterBand::IReadBlock( int nBlockXOff,
     {
         IssueSDEError( nSDEErr, "SE_rastileinfo_get_pixel_data" );
         return CE_Fatal;
-    }           
+    }
 
     int bits_per_pixel = static_cast<int>(dfDepth * 8 + 0.0001);
     int block_size = (nBlockXSize * bits_per_pixel + 7) / 8 * nBlockYSize;
@@ -418,7 +413,7 @@ CPLErr SDERasterBand::IReadBlock( int nBlockXOff,
     if (length == 0) {
         // ArcSDE says the block has no data in it.
         // Write 0's and be done with it
-        memset( pImage, 0, 
+        memset( pImage, 0,
                 nBlockXSize*nBlockYSize*GDALGetDataTypeSize(eDataType)/8);
         return CE_None;
     }
@@ -439,9 +434,9 @@ CPLErr SDERasterBand::IReadBlock( int nBlockXOff,
     }
     } else {
 
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Bit size calculation failed... "\
-                      "SDE's length:%d With bitmap length: %d Without bitmap length: %d", 
+                      "SDE's length:%d With bitmap length: %d Without bitmap length: %d",
                       length, block_size + bitmap_size, block_size );
             return CE_Fatal;
         }
@@ -452,27 +447,26 @@ CPLErr SDERasterBand::IReadBlock( int nBlockXOff,
 }
 
 
-
 /* ---------------------------------------------------------------------*/
 /* Private Methods                                                      */
 
 /************************************************************************/
 /*                             ComputeColorTable()                      */
 /************************************************************************/
-void SDERasterBand::ComputeColorTable(void) 
+void SDERasterBand::ComputeColorTable(void)
 {
 
     SE_COLORMAP_TYPE eCMap_Type;
     SE_COLORMAP_DATA_TYPE eCMap_DataType;
-    
+
     LONG nCMapEntries;
     void * phSDEColormapData;
-    
+
     unsigned char* puszSDECMapData;
     unsigned short* pushSDECMapData;
-    
+
     long nSDEErr;
-    
+
     nSDEErr = SE_rasbandinfo_get_colormap(  *poBand,
                                             &eCMap_Type,
                                             &eCMap_DataType,
@@ -481,18 +475,18 @@ void SDERasterBand::ComputeColorTable(void)
     if( nSDEErr != SE_SUCCESS )
     {
         IssueSDEError( nSDEErr, "SE_rasbandinfo_get_colormap" );
-    }                                            
+    }
 
-    // Assign both the short and char pointers 
-    // to the void*, and we'll switch and read based 
+    // Assign both the short and char pointers
+    // to the void*, and we'll switch and read based
     // on the eCMap_DataType
     puszSDECMapData = (unsigned char*) phSDEColormapData;
     pushSDECMapData = (unsigned short*) phSDEColormapData;
-    
+
     poColorTable = new GDALColorTable(GPI_RGB);
-    
+
     int red, green, blue, alpha;
-    
+
     CPLDebug("SDERASTER", "%d colormap entries specified", nCMapEntries);
     switch (eCMap_DataType) {
         case SE_COLORMAP_DATA_BYTE:
@@ -508,11 +502,11 @@ void SDERasterBand::ComputeColorTable(void)
                         sColor.c2 = green;
                         sColor.c3 = blue;
                         sColor.c4 = 255;
-                        
+
                         // sColor is copied
                         poColorTable->SetColorEntry(i,&sColor);
                         CPLDebug ("SDERASTER", "SE_COLORMAP_DATA_BYTE "\
-                                  "SE_COLORMAP_RGB Colormap Entry: %d %d %d", 
+                                  "SE_COLORMAP_RGB Colormap Entry: %d %d %d",
                                   red, blue, green);
                     }
                     break;
@@ -528,16 +522,16 @@ void SDERasterBand::ComputeColorTable(void)
                         sColor.c2 = green;
                         sColor.c3 = blue;
                         sColor.c4 = alpha;
-                        
+
                         // sColor is copied
                         poColorTable->SetColorEntry(i,&sColor);
                         CPLDebug ("SDERASTER", "SE_COLORMAP_DATA_BYTE "\
-                                  "SE_COLORMAP_RGBA Colormap Entry: %d %d %d %d", 
+                                  "SE_COLORMAP_RGBA Colormap Entry: %d %d %d %d",
                                   red, blue, green, alpha);
                     }
-                    break;  
+                    break;
                 case SE_COLORMAP_NONE:
-                    break;                 
+                    break;
             }
             break;
         case SE_COLORMAP_DATA_SHORT:
@@ -553,11 +547,11 @@ void SDERasterBand::ComputeColorTable(void)
                         sColor.c2 = green;
                         sColor.c3 = blue;
                         sColor.c4 = 255;
-                        
+
                         // sColor is copied
                         poColorTable->SetColorEntry(i,&sColor);
                         CPLDebug ("SDERASTER", "SE_COLORMAP_DATA_SHORT "\
-                                  "SE_COLORMAP_RGB Colormap Entry: %d %d %d", 
+                                  "SE_COLORMAP_RGB Colormap Entry: %d %d %d",
                                   red, blue, green);
                     }
                     break;
@@ -573,16 +567,16 @@ void SDERasterBand::ComputeColorTable(void)
                         sColor.c2 = green;
                         sColor.c3 = blue;
                         sColor.c4 = alpha;
-                        
+
                         // sColor is copied
                         poColorTable->SetColorEntry(i,&sColor);
                         CPLDebug ("SDERASTER", "SE_COLORMAP_DATA_SHORT "\
-                                  "SE_COLORMAP_RGBA Colormap Entry: %d %d %d %d", 
+                                  "SE_COLORMAP_RGBA Colormap Entry: %d %d %d %d",
                                   red, blue, green, alpha);
                     }
                     break;
                 case SE_COLORMAP_NONE:
-                    break;    
+                    break;
             }
             break;
     }
@@ -595,22 +589,22 @@ void SDERasterBand::ComputeColorTable(void)
 /************************************************************************/
 CPLErr SDERasterBand::InitializeBand( int nOverview )
 
-{    
+{
 
     SDEDataset *poGDS = (SDEDataset *) poDS;
-    
+
     long nSDEErr;
 
 
-    hConstraint = InitializeConstraint( NULL, NULL );  
+    hConstraint = InitializeConstraint( NULL, NULL );
     if (!hConstraint)
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "ConstraintInfo initialization failed");   
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "ConstraintInfo initialization failed");
 
     if (!hQuery) {
         hQuery = InitializeQuery();
         if (!hQuery)
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "QueryInfo initialization failed");
     }
 
@@ -620,7 +614,7 @@ CPLErr SDERasterBand::InitializeBand( int nOverview )
         IssueSDEError( nSDEErr, "SE_stream_close" );
         return CE_Fatal;
     }
-                      
+
     nSDEErr = SE_stream_query_with_info(poGDS->hStream, hQuery);
     if( nSDEErr != SE_SUCCESS )
     {
@@ -640,14 +634,14 @@ CPLErr SDERasterBand::InitializeBand( int nOverview )
         IssueSDEError( nSDEErr, "SE_stream_fetch" );
         return CE_Fatal;
     }
-    
+
 
     CPLErr error = QueryRaster(hConstraint);
     if (error != CE_None)
         return error;
 
     LONG nBXRet, nBYRet;
-    nSDEErr = SE_rasterattr_get_tile_size (poGDS->hAttributes, 
+    nSDEErr = SE_rasterattr_get_tile_size (poGDS->hAttributes,
                                            &nBXRet, &nBYRet);
     if( nSDEErr != SE_SUCCESS )
     {
@@ -657,9 +651,9 @@ CPLErr SDERasterBand::InitializeBand( int nOverview )
 
     nBlockXSize = nBXRet;
     nBlockYSize = nBYRet;
-    
+
     LONG offset_x, offset_y, num_bands, nXSRet, nYSRet;
-    
+
     nSDEErr = SE_rasterattr_get_image_size_by_level (poGDS->hAttributes,
                                                      &nXSRet, &nYSRet,
                                                      &offset_x,
@@ -691,24 +685,24 @@ CPLErr SDERasterBand::InitializeBand( int nOverview )
 /************************************************************************/
 /*                           InitializeConstraint()                     */
 /************************************************************************/
-SE_RASCONSTRAINT& SDERasterBand::InitializeConstraint( long* nBlockXOff, 
-                                                       long* nBlockYOff) 
+SE_RASCONSTRAINT& SDERasterBand::InitializeConstraint( long* nBlockXOff,
+                                                       long* nBlockYOff)
 {
 
-    long nSDEErr;   
-    
+    long nSDEErr;
+
     if (!hConstraint) {
         nSDEErr = SE_rasconstraint_create(&hConstraint);
         if( nSDEErr != SE_SUCCESS )
         {
             IssueSDEError( nSDEErr, "SE_rasconstraint_create" );
         }
-        
+
         nSDEErr = SE_rasconstraint_set_level(hConstraint, (nOverview == -1) ? (0): (nOverview));
         if( nSDEErr != SE_SUCCESS )
         {
             IssueSDEError( nSDEErr, "SE_rasconstraint_create" );
-        }       
+        }
 
         LONG nBandIn = nBand;
         nSDEErr = SE_rasconstraint_set_bands(hConstraint, 1, &nBandIn);
@@ -723,17 +717,17 @@ SE_RASCONSTRAINT& SDERasterBand::InitializeConstraint( long* nBlockXOff,
         }
 
     }
-    
+
     if (nBlockXSize != -1 && nBlockYSize != -1) { // we aren't initialized yet
-        if (nBlockXSize >= 0 && nBlockYSize >= 0) { 
+        if (nBlockXSize >= 0 && nBlockYSize >= 0) {
             if (*nBlockXOff >= 0 &&  *nBlockYOff >= 0) {
                 long nMinX, nMinY, nMaxX, nMaxY;
-                
+
                 nMinX = *nBlockXOff;
                 nMinY = *nBlockYOff;
                 nMaxX = *nBlockXOff;
                 nMaxY = *nBlockYOff;
-                                                                            
+
                 nSDEErr = SE_rasconstraint_set_envelope (hConstraint,
                                                         nMinX,
                                                         nMinY,
@@ -752,7 +746,7 @@ SE_RASCONSTRAINT& SDERasterBand::InitializeConstraint( long* nBlockXOff,
 /************************************************************************/
 /*                           InitializeQuery()                          */
 /************************************************************************/
-SE_QUERYINFO& SDERasterBand::InitializeQuery( void ) 
+SE_QUERYINFO& SDERasterBand::InitializeQuery( void )
 {
     SDEDataset *poGDS = (SDEDataset *) poDS;
     long nSDEErr;
@@ -762,10 +756,10 @@ SE_QUERYINFO& SDERasterBand::InitializeQuery( void )
     {
         IssueSDEError( nSDEErr, "SE_queryinfo_create" );
     }
-    
-    nSDEErr = SE_queryinfo_set_tables(hQuery, 
-                                      1, 
-                                      (const char**) &(poGDS->pszLayerName), 
+
+    nSDEErr = SE_queryinfo_set_tables(hQuery,
+                                      1,
+                                      (const char**) &(poGDS->pszLayerName),
                                       NULL);
     if( nSDEErr != SE_SUCCESS )
     {
@@ -778,23 +772,22 @@ SE_QUERYINFO& SDERasterBand::InitializeQuery( void )
         IssueSDEError( nSDEErr, "SE_queryinfo_set_where" );
     }
 
-    nSDEErr = SE_queryinfo_set_columns(hQuery, 
-                                       1, 
+    nSDEErr = SE_queryinfo_set_columns(hQuery,
+                                       1,
                                        (const char**) &(poGDS->pszColumnName));
     if( nSDEErr != SE_SUCCESS )
     {
         IssueSDEError( nSDEErr, "SE_queryinfo_set_where" );
     }
-    return hQuery;        
+    return hQuery;
 }
 
 
-
 /************************************************************************/
 /*                             MorphESRIRasterDepth()                   */
 /************************************************************************/
 double SDERasterBand::MorphESRIRasterDepth(int gtype) {
-    
+
     switch (gtype) {
         case SE_PIXEL_TYPE_1BIT:
             return 0.125;
@@ -825,7 +818,7 @@ double SDERasterBand::MorphESRIRasterDepth(int gtype) {
 /*                             MorphESRIRasterType()                    */
 /************************************************************************/
 GDALDataType SDERasterBand::MorphESRIRasterType(int gtype) {
-    
+
     switch (gtype) {
         case SE_PIXEL_TYPE_1BIT:
             return GDT_Byte;
@@ -855,22 +848,20 @@ GDALDataType SDERasterBand::MorphESRIRasterType(int gtype) {
 /************************************************************************/
 /*                           QueryRaster()                              */
 /************************************************************************/
-CPLErr SDERasterBand::QueryRaster( SE_RASCONSTRAINT& constraint ) 
+CPLErr SDERasterBand::QueryRaster( SE_RASCONSTRAINT& constraint )
 {
 
     SDEDataset *poGDS = (SDEDataset *) poDS;
-    
-    long nSDEErr;
 
+    long nSDEErr;
 
-                          
     nSDEErr = SE_stream_query_raster_tile(poGDS->hStream, constraint);
     if( nSDEErr != SE_SUCCESS )
     {
         IssueSDEError( nSDEErr, "SE_stream_query_raster_tile" );
         return CE_Fatal;
     }
-    
+
     nSDEErr = SE_stream_get_raster (poGDS->hStream, 1, poGDS->hAttributes);
     if( nSDEErr != SE_SUCCESS )
     {
@@ -881,5 +872,5 @@ CPLErr SDERasterBand::QueryRaster( SE_RASCONSTRAINT& constraint )
     return CE_None;
 }
 
-//T:\>gdal_translate -of GTiff SDE:nakina.gis.iastate.edu,5151,,geoservwrite,EsrI4ever,sde_master.geoservwrite.century foo.tif  
-//T:\>gdalinfo SDE:nakina.gis.iastate.edu,5151,,geoservwrite,EsrI4ever,sde_master.geoservwrite.century  
+//T:\>gdal_translate -of GTiff SDE:nakina.gis.iastate.edu,5151,,geoservwrite,EsrI4ever,sde_master.geoservwrite.century foo.tif
+//T:\>gdalinfo SDE:nakina.gis.iastate.edu,5151,,geoservwrite,EsrI4ever,sde_master.geoservwrite.century
diff --git a/frmts/sde/sderasterband.h b/frmts/sde/sderasterband.h
index 4edc616..21bc73e 100644
--- a/frmts/sde/sderasterband.h
+++ b/frmts/sde/sderasterband.h
@@ -13,20 +13,19 @@ class SDEDataset;
 class SDERasterBand : public GDALRasterBand
 {
     friend class SDEDataset;
-    
+
     private:
         const SE_RASBANDINFO* poBand;
 
-        double                  MorphESRIRasterDepth( int gtype );        
+        double                  MorphESRIRasterDepth( int gtype );
         GDALDataType            MorphESRIRasterType( int gtype );
-        void                    ComputeColorTable( void );  
+        void                    ComputeColorTable( void );
         CPLErr                  InitializeBand( int nOverview );
-        SE_QUERYINFO&           InitializeQuery( void ); 
+        SE_QUERYINFO&           InitializeQuery( void );
         SE_RASCONSTRAINT&       InitializeConstraint (  long* nBlockXOff,
                                                         long* nBlockYOff);
         CPLErr                  QueryRaster( SE_RASCONSTRAINT& constraint );
-        
-        
+
         int                     nOverview;
         int                     nOverviews;
         long                    nBlockSize;
@@ -36,20 +35,18 @@ class SDERasterBand : public GDALRasterBand
         SE_RASCONSTRAINT        hConstraint;
         GDALRasterBand**        papoOverviews;
         GDALColorTable*         poColorTable;
-        
-    public:
 
-        SDERasterBand( SDEDataset* poDS, 
-                       int nBand, 
-                       int nOverview, 
+    public:
+        SDERasterBand( SDEDataset* poDS,
+                       int nBand,
+                       int nOverview,
                        const SE_RASBANDINFO* band);
-                       
+
         ~SDERasterBand( void );
-    
 
     virtual CPLErr IReadBlock( int, int, void * );
     virtual CPLErr GetStatistics( int bApproxOK, int bForce,
-                                  double *pdfMin, double *pdfMax, 
+                                  double *pdfMin, double *pdfMax,
                                   double *pdfMean, double *pdfStdDev );
     virtual GDALDataType GetRasterDataType(void);
     virtual GDALColorTable *GetColorTable();
diff --git a/frmts/sdts/Makefile.in b/frmts/sdts/Makefile.in
index 3868db6..6d50b9d 100644
--- a/frmts/sdts/Makefile.in
+++ b/frmts/sdts/Makefile.in
@@ -23,81 +23,81 @@ libsdts_al.a:	$(OBJ)
 
 
 #
-#	SDTS library 
+#	SDTS library
 #
 sdtsiref.o:	sdtsiref.cpp
-	$(CXX) -c $(CXXFLAGS) sdtsiref.cpp 
+	$(CXX) -c $(CXXFLAGS) sdtsiref.cpp
 
 sdtscatd.o:	sdtscatd.cpp
-	$(CXX) -c $(CXXFLAGS) sdtscatd.cpp 
+	$(CXX) -c $(CXXFLAGS) sdtscatd.cpp
 
 sdtslinereader.o:	sdtslinereader.cpp
-	$(CXX) -c $(CXXFLAGS) sdtslinereader.cpp 
+	$(CXX) -c $(CXXFLAGS) sdtslinereader.cpp
 
 sdtslib.o:	sdtslib.cpp
-	$(CXX) -c $(CXXFLAGS) sdtslib.cpp 
+	$(CXX) -c $(CXXFLAGS) sdtslib.cpp
 
 sdtspointreader.o:	sdtspointreader.cpp
-	$(CXX) -c $(CXXFLAGS) sdtspointreader.cpp 
+	$(CXX) -c $(CXXFLAGS) sdtspointreader.cpp
 
 sdtsattrreader.o:	sdtsattrreader.cpp
-	$(CXX) -c $(CXXFLAGS) sdtsattrreader.cpp 
+	$(CXX) -c $(CXXFLAGS) sdtsattrreader.cpp
 
 sdtstransfer.o:	sdtstransfer.cpp
-	$(CXX) -c $(CXXFLAGS) sdtstransfer.cpp 
+	$(CXX) -c $(CXXFLAGS) sdtstransfer.cpp
 
 sdtspolygonreader.o:	sdtspolygonreader.cpp
-	$(CXX) -c $(CXXFLAGS) sdtspolygonreader.cpp 
+	$(CXX) -c $(CXXFLAGS) sdtspolygonreader.cpp
 
 sdtsxref.o:	sdtsxref.cpp
-	$(CXX) -c $(CXXFLAGS) sdtsxref.cpp 
+	$(CXX) -c $(CXXFLAGS) sdtsxref.cpp
 
 sdtsrasterreader.o:	sdtsrasterreader.cpp
-	$(CXX) -c $(CXXFLAGS) sdtsrasterreader.cpp 
+	$(CXX) -c $(CXXFLAGS) sdtsrasterreader.cpp
 
 sdtsindexedreader.o:	sdtsindexedreader.cpp
-	$(CXX) -c $(CXXFLAGS) sdtsindexedreader.cpp 
+	$(CXX) -c $(CXXFLAGS) sdtsindexedreader.cpp
 
 #
 # 	from iso8211 library
 #
 
 ddfmodule.o:	ddfmodule.cpp
-	$(CXX) -c $(CXXFLAGS) ddfmodule.cpp 
+	$(CXX) -c $(CXXFLAGS) ddfmodule.cpp
 
 ddfutils.o:	ddfutils.cpp
-	$(CXX) -c $(CXXFLAGS) ddfutils.cpp 
+	$(CXX) -c $(CXXFLAGS) ddfutils.cpp
 
 ddffielddefn.o:	ddffielddefn.cpp
-	$(CXX) -c $(CXXFLAGS) ddffielddefn.cpp 
+	$(CXX) -c $(CXXFLAGS) ddffielddefn.cpp
 
 ddfrecord.o:	ddfrecord.cpp
-	$(CXX) -c $(CXXFLAGS) ddfrecord.cpp 
+	$(CXX) -c $(CXXFLAGS) ddfrecord.cpp
 
 ddffield.o:	ddffield.cpp
-	$(CXX) -c $(CXXFLAGS) ddffield.cpp 
+	$(CXX) -c $(CXXFLAGS) ddffield.cpp
 
 ddfsubfielddefn.o:	ddfsubfielddefn.cpp
-	$(CXX) -c $(CXXFLAGS) ddfsubfielddefn.cpp 
+	$(CXX) -c $(CXXFLAGS) ddfsubfielddefn.cpp
 
 #
 #	Common Portability Library
 #
 
 cpl_error.o:	cpl_error.cpp
-	$(CXX) -c $(CXXFLAGS) cpl_error.cpp 
+	$(CXX) -c $(CXXFLAGS) cpl_error.cpp
 
 cpl_string.o:	cpl_string.cpp
-	$(CXX) -c $(CXXFLAGS) cpl_string.cpp 
+	$(CXX) -c $(CXXFLAGS) cpl_string.cpp
 
 cpl_conv.o:	cpl_conv.cpp
-	$(CXX) -c $(CXXFLAGS) cpl_conv.cpp 
+	$(CXX) -c $(CXXFLAGS) cpl_conv.cpp
 
 cpl_vsisimple.o:	cpl_vsisimple.cpp
-	$(CXX) -c $(CXXFLAGS) cpl_vsisimple.cpp 
+	$(CXX) -c $(CXXFLAGS) cpl_vsisimple.cpp
 
 cpl_path.o:	cpl_path.cpp
-	$(CXX) -c $(CXXFLAGS) cpl_path.cpp 
+	$(CXX) -c $(CXXFLAGS) cpl_path.cpp
 
 #
 #	Shapefile access
@@ -113,13 +113,13 @@ dbfopen.o:	dbfopen.c
 #
 
 sdts2shp.o:	sdts2shp.cpp
-	$(CXX) -c $(CXXFLAGS) sdts2shp.cpp 
+	$(CXX) -c $(CXXFLAGS) sdts2shp.cpp
 
 8211view.o:	8211view.cpp
-	$(CXX) -c $(CXXFLAGS) 8211view.cpp 
+	$(CXX) -c $(CXXFLAGS) 8211view.cpp
 
 8211dump.o:	8211dump.cpp
-	$(CXX) -c $(CXXFLAGS) 8211dump.cpp 
+	$(CXX) -c $(CXXFLAGS) 8211dump.cpp
 
 sdts2shp:	sdts2shp.o libsdts_al.a
 	$(CXX) $(CXXFLAGS) sdts2shp.o libsdts_al.a $(LIBS) -o sdts2shp
diff --git a/frmts/sdts/sdts2shp.cpp b/frmts/sdts/sdts2shp.cpp
index a23c906..955b4a8 100644
--- a/frmts/sdts/sdts2shp.cpp
+++ b/frmts/sdts/sdts2shp.cpp
@@ -1,5 +1,5 @@
 /* ****************************************************************************
- * $Id: sdts2shp.cpp 28831 2015-04-01 16:46:05Z rouault $
+ * $Id: sdts2shp.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Mainline for converting to ArcView Shapefiles.
@@ -31,7 +31,7 @@
 #include "shapefil.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: sdts2shp.cpp 28831 2015-04-01 16:46:05Z rouault $");
+CPL_CVSID("$Id: sdts2shp.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 static int  bVerbose = FALSE;
 
@@ -41,17 +41,17 @@ static void WritePointShapefile( const char *, SDTSTransfer *,
                                  const char * );
 static void WriteAttributeDBF( const char *, SDTSTransfer *,
                                const char * );
-static void WritePolygonShapefile( const char *, SDTSTransfer *, 
+static void WritePolygonShapefile( const char *, SDTSTransfer *,
                                    const char * );
 
 static void
 AddPrimaryAttrToDBFSchema( DBFHandle hDBF, SDTSTransfer * poTransfer,
                            char ** papszModuleList );
 static void
-WritePrimaryAttrToDBF( DBFHandle hDBF, int nRecord, 
+WritePrimaryAttrToDBF( DBFHandle hDBF, int nRecord,
                        SDTSTransfer *, SDTSFeature * poFeature );
 static void
-WriteAttrRecordToDBF( DBFHandle hDBF, int nRecord, 
+WriteAttrRecordToDBF( DBFHandle hDBF, int nRecord,
                       SDTSTransfer *, DDFField * poAttributes );
 
 /* **********************************************************************/
@@ -65,7 +65,7 @@ static void Usage()
             "                [-m module_name] [-v]\n"
             "\n"
             "Modules include `LE01', `PC01', `NP01' and `ARDF'\n" );
-    
+
     exit( 1 );
 }
 
@@ -82,7 +82,6 @@ int main( int nArgc, char ** papszArgv )
     const char  *pszMODN = "LE01";
     char        *pszShapefile = "sdts_out.shp";
     SDTSTransfer oTransfer;
-   
 
 /* -------------------------------------------------------------------- */
 /*      Interpret commandline switches.                                 */
@@ -143,7 +142,7 @@ int main( int nArgc, char ** papszArgv )
         for( i = 0; i < oTransfer.GetLayerCount(); i++ )
         {
             int         iCATDEntry = oTransfer.GetLayerCATDEntry(i);
-            
+
             printf( "  %s: `%s'\n",
                     oTransfer.GetCATD()->GetEntryModule(iCATDEntry),
                     oTransfer.GetCATD()->GetEntryTypeDesc(iCATDEntry) );
@@ -171,8 +170,8 @@ int main( int nArgc, char ** papszArgv )
 /* -------------------------------------------------------------------- */
 /*      If the module is an attribute primary one, dump to DBF.         */
 /* -------------------------------------------------------------------- */
-    else if( pszMODN[0] == 'A' || pszMODN[0] == 'a' 
-             || pszMODN[0] == 'B' || pszMODN[0] == 'b' ) 
+    else if( pszMODN[0] == 'A' || pszMODN[0] == 'a'
+             || pszMODN[0] == 'B' || pszMODN[0] == 'b' )
     {
         WriteAttributeDBF( pszShapefile, &oTransfer, pszMODN );
     }
@@ -195,11 +194,11 @@ int main( int nArgc, char ** papszArgv )
 
     else
     {
-        fprintf( stderr, "Unrecognised module name: %s\n", pszMODN );
+        fprintf( stderr, "Unrecognized module name: %s\n", pszMODN );
     }
 
     CPLFree( pszShapefile );
-}    
+}
 #ifdef DBMALLOC
     malloc_dump(1);
 #endif
@@ -215,13 +214,13 @@ static void WriteLineShapefile( const char * pszShapefile,
 
 {
     SDTSLineReader      *poLineReader;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Fetch a reference to the indexed Pointgon reader.                */
 /* -------------------------------------------------------------------- */
-    poLineReader = (SDTSLineReader *) 
+    poLineReader = (SDTSLineReader *)
         poTransfer->GetLayerIndexedReader( poTransfer->FindLayer( pszMODN ) );
-    
+
     if( poLineReader == NULL )
     {
         fprintf( stderr, "Failed to open %s.\n",
@@ -271,16 +270,16 @@ static void WriteLineShapefile( const char * pszShapefile,
     char  **papszModRefs = poLineReader->ScanModuleReferences();
     AddPrimaryAttrToDBFSchema( hDBF, poTransfer, papszModRefs );
     CSLDestroy( papszModRefs );
-    
+
 /* ==================================================================== */
 /*      Process all the line features in the module.                    */
 /* ==================================================================== */
     SDTSRawLine *poRawLine;
-        
+
     while( (poRawLine = poLineReader->GetNextLine()) != NULL )
     {
         int             iShape;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Write out a shape with the vertices.                            */
 /* -------------------------------------------------------------------- */
@@ -301,7 +300,7 @@ static void WriteLineShapefile( const char * pszShapefile,
 
         DBFWriteIntegerAttribute( hDBF, iShape, nSDTSRecordField,
                                   poRawLine->oModId.nRecord );
-        
+
         sprintf( szID, "%s:%ld",
                  poRawLine->oLeftPoly.szModule,
                  poRawLine->oLeftPoly.nRecord );
@@ -333,7 +332,7 @@ static void WriteLineShapefile( const char * pszShapefile,
 /* -------------------------------------------------------------------- */
     DBFClose( hDBF );
     SHPClose( hSHP );
-}    
+}
 
 /* **********************************************************************/
 /*                        WritePointShapefile()                         */
@@ -349,9 +348,9 @@ static void WritePointShapefile( const char * pszShapefile,
 /* -------------------------------------------------------------------- */
 /*      Fetch a reference to the indexed Pointgon reader.                */
 /* -------------------------------------------------------------------- */
-    poPointReader = (SDTSPointReader *) 
+    poPointReader = (SDTSPointReader *)
         poTransfer->GetLayerIndexedReader( poTransfer->FindLayer( pszMODN ) );
-    
+
     if( poPointReader == NULL )
     {
         fprintf( stderr, "Failed to open %s.\n",
@@ -393,7 +392,7 @@ static void WritePointShapefile( const char * pszShapefile,
 
     nSDTSRecordField = DBFAddField( hDBF, "SDTSRecId", FTInteger, 8, 0 );
     nAreaField = DBFAddField( hDBF, "AreaId", FTString, 12, 0 );
-    
+
     char  **papszModRefs = poPointReader->ScanModuleReferences();
     AddPrimaryAttrToDBFSchema( hDBF, poTransfer, papszModRefs );
     CSLDestroy( papszModRefs );
@@ -402,11 +401,11 @@ static void WritePointShapefile( const char * pszShapefile,
 /*      Process all the line features in the module.                    */
 /* ==================================================================== */
     SDTSRawPoint        *poRawPoint;
-        
+
     while( (poRawPoint = poPointReader->GetNextPoint()) != NULL )
     {
         int             iShape;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Write out a shape with the vertices.                            */
 /* -------------------------------------------------------------------- */
@@ -428,7 +427,7 @@ static void WritePointShapefile( const char * pszShapefile,
 
         DBFWriteIntegerAttribute( hDBF, iShape, nSDTSRecordField,
                                   poRawPoint->oModId.nRecord );
-        
+
         sprintf( szID, "%s:%ld",
                  poRawPoint->oAreaId.szModule,
                  poRawPoint->oAreaId.nRecord );
@@ -445,7 +444,7 @@ static void WritePointShapefile( const char * pszShapefile,
 /* -------------------------------------------------------------------- */
     DBFClose( hDBF );
     SHPClose( hSHP );
-}    
+}
 
 /* **********************************************************************/
 /*                         WriteAttributeDBF()                          */
@@ -461,9 +460,9 @@ static void WriteAttributeDBF( const char * pszShapefile,
 /* -------------------------------------------------------------------- */
 /*      Fetch a reference to the indexed Pointgon reader.                */
 /* -------------------------------------------------------------------- */
-    poAttrReader = (SDTSAttrReader *) 
+    poAttrReader = (SDTSAttrReader *)
         poTransfer->GetLayerIndexedReader( poTransfer->FindLayer( pszMODN ) );
-    
+
     if( poAttrReader == NULL )
     {
         fprintf( stderr, "Failed to open %s.\n",
@@ -499,7 +498,7 @@ static void WriteAttributeDBF( const char * pszShapefile,
     AddPrimaryAttrToDBFSchema( hDBF, poTransfer, papszMODNList );
 
     CSLDestroy( papszMODNList );
-    
+
 /* ==================================================================== */
 /*      Process all the records in the module.                          */
 /* ==================================================================== */
@@ -515,7 +514,7 @@ static void WriteAttributeDBF( const char * pszShapefile,
 
         if( !poAttrReader->IsIndexed() )
             delete poRecord;
-        
+
         iRecord++;
     }
 
@@ -523,14 +522,14 @@ static void WriteAttributeDBF( const char * pszShapefile,
 /*      Close, and cleanup.                                             */
 /* -------------------------------------------------------------------- */
     DBFClose( hDBF );
-}    
+}
 
 /* **********************************************************************/
 /*                       WritePolygonShapefile()                        */
 /* **********************************************************************/
 
 static void WritePolygonShapefile( const char * pszShapefile,
-                                   SDTSTransfer * poTransfer, 
+                                   SDTSTransfer * poTransfer,
                                    const char * pszMODN )
 
 {
@@ -539,9 +538,9 @@ static void WritePolygonShapefile( const char * pszShapefile,
 /* -------------------------------------------------------------------- */
 /*      Fetch a reference to the indexed polygon reader.                */
 /* -------------------------------------------------------------------- */
-    poPolyReader = (SDTSPolygonReader *) 
+    poPolyReader = (SDTSPolygonReader *)
         poTransfer->GetLayerIndexedReader( poTransfer->FindLayer( pszMODN ) );
-    
+
     if( poPolyReader == NULL )
     {
         fprintf( stderr, "Failed to open %s.\n",
@@ -553,7 +552,7 @@ static void WritePolygonShapefile( const char * pszShapefile,
 /*      Assemble polygon geometries from all the line layers.           */
 /* -------------------------------------------------------------------- */
     poPolyReader->AssembleRings( poTransfer, poTransfer->FindLayer(pszMODN) );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create the Shapefile.                                           */
 /* -------------------------------------------------------------------- */
@@ -609,8 +608,8 @@ static void WritePolygonShapefile( const char * pszShapefile,
         psShape = SHPCreateObject( SHPT_POLYGON, -1, poRawPoly->nRings,
                                    poRawPoly->panRingStart, NULL,
                                    poRawPoly->nVertices,
-                                   poRawPoly->padfX, 
-                                   poRawPoly->padfY, 
+                                   poRawPoly->padfX,
+                                   poRawPoly->padfY,
                                    poRawPoly->padfZ,
                                    NULL );
 
@@ -634,7 +633,7 @@ static void WritePolygonShapefile( const char * pszShapefile,
 /* -------------------------------------------------------------------- */
     DBFClose( hDBF );
     SHPClose( hSHP );
-}    
+}
 
 /* **********************************************************************/
 /*                        AddPrimaryAttrToDBF()                         */
@@ -669,7 +668,7 @@ AddPrimaryAttrToDBFSchema( DBFHandle hDBF, SDTSTransfer *poTransfer,
         }
 
         poAttrReader->Rewind();
-        
+
 /* -------------------------------------------------------------------- */
 /*      Read the first record so we can clone schema information off    */
 /*      of it.                                                          */
@@ -682,7 +681,7 @@ AddPrimaryAttrToDBFSchema( DBFHandle hDBF, SDTSTransfer *poTransfer,
             fprintf( stderr,
                      "Didn't find any meaningful attribute records in %s.\n",
                      papszModuleList[iModule] );
-        
+
             continue;
         }
 
@@ -700,26 +699,26 @@ AddPrimaryAttrToDBFSchema( DBFHandle hDBF, SDTSTransfer *poTransfer,
         DDFFieldDefn    *poFDefn = poAttrFeature->poATTR->GetFieldDefn();
         int             iSF;
         DDFField        *poSR = poAttrFeature->poATTR;
-    
+
         for( iSF=0; iSF < poFDefn->GetSubfieldCount(); iSF++ )
         {
             DDFSubfieldDefn     *poSFDefn = poFDefn->GetSubfield( iSF );
             int         nWidth = poSFDefn->GetWidth();
-            
+
             switch( poSFDefn->GetType() )
             {
               case DDFString:
                 if( nWidth == 0 )
                 {
                     int         nMaxBytes;
-                
+
                     const char * pachData = poSR->GetSubfieldData(poSFDefn,
                                                                   &nMaxBytes);
 
                     nWidth = strlen(poSFDefn->ExtractStringData(pachData,
                                                                 nMaxBytes, NULL ));
                 }
-            
+
                 DBFAddField( hDBF, poSFDefn->GetName(), FTString, nWidth, 0 );
                 break;
 
@@ -755,7 +754,7 @@ AddPrimaryAttrToDBFSchema( DBFHandle hDBF, SDTSTransfer *poTransfer,
 /* **********************************************************************/
 
 static void
-WritePrimaryAttrToDBF( DBFHandle hDBF, int iRecord, 
+WritePrimaryAttrToDBF( DBFHandle hDBF, int iRecord,
                        SDTSTransfer * poTransfer, SDTSFeature * poFeature )
 
 {
@@ -763,13 +762,13 @@ WritePrimaryAttrToDBF( DBFHandle hDBF, int iRecord,
 /*      Loop over all the attribute records linked to this feature.     */
 /* ==================================================================== */
     int         iAttrRecord;
-    
+
     for( iAttrRecord = 0; iAttrRecord < poFeature->nAttributes; iAttrRecord++)
     {
         DDFField        *poSR;
 
         poSR = poTransfer->GetAttr( poFeature->paoATID+iAttrRecord );
-          
+
         WriteAttrRecordToDBF( hDBF, iRecord, poTransfer, poSR );
     }
 }
@@ -779,7 +778,7 @@ WritePrimaryAttrToDBF( DBFHandle hDBF, int iRecord,
 /* **********************************************************************/
 
 static void
-WriteAttrRecordToDBF( DBFHandle hDBF, int iRecord, 
+WriteAttrRecordToDBF( DBFHandle hDBF, int iRecord,
                       SDTSTransfer * poTransfer, DDFField * poSR )
 
 {
@@ -787,7 +786,7 @@ WriteAttrRecordToDBF( DBFHandle hDBF, int iRecord,
 /*      Process each subfield in the record.                            */
 /* -------------------------------------------------------------------- */
     DDFFieldDefn        *poFDefn = poSR->GetFieldDefn();
-        
+
     for( int iSF=0; iSF < poFDefn->GetSubfieldCount(); iSF++ )
     {
         DDFSubfieldDefn *poSFDefn = poFDefn->GetSubfield( iSF );
@@ -808,7 +807,7 @@ WriteAttrRecordToDBF( DBFHandle hDBF, int iRecord,
 
         if( iField == hDBF->nFields )
             iField = -1;
-            
+
 /* -------------------------------------------------------------------- */
 /*      Handle each of the types.                                       */
 /* -------------------------------------------------------------------- */
diff --git a/frmts/sdts/sdts_al.h b/frmts/sdts/sdts_al.h
index faa83cf..59a7ba4 100644
--- a/frmts/sdts/sdts_al.h
+++ b/frmts/sdts/sdts_al.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sdts_al.h 26613 2013-11-14 17:42:08Z goatbar $
+ * $Id: sdts_al.h 32067 2015-12-07 15:34:53Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Include file for entire SDTS Abstraction Layer functions.
@@ -48,12 +48,12 @@ char **SDTSScanModuleReferences( DDFModule *, const char * );
 /**
   Class holding SDTS IREF (internal reference) information, internal
   coordinate system format, scaling and resolution.  This object isn't
-  normally needed by applications. 
+  normally needed by applications.
 */
 class SDTS_IREF
 {
     int         nDefaultSADRFormat;
-    
+
   public:
                 SDTS_IREF();
                 ~SDTS_IREF();
@@ -97,15 +97,14 @@ class SDTS_XREF
 
     /** Projection system name, from the RSNM field.  One of GEO, SPCS, UTM,
         UPS, OTHR, UNSP. */
-    char        *pszSystemName;         
-                                  
+    char        *pszSystemName;
 
     /** Horizontal datum name, from the HDAT field.  One of NAS, NAX, WGA,
         WGB, WGC, WGE. */
-    char        *pszDatum;              
-                                  
+    char        *pszDatum;
+
     /** Zone number for UTM and SPCS projections, from the ZONE field. */
-    int         nZone;                        
+    int         nZone;
 };
 
 /************************************************************************/
@@ -136,7 +135,7 @@ class SDTS_CATD
 
     int         nEntries;
     SDTS_CATDEntry **papoEntries;
-    
+
   public:
                 SDTS_CATD();
                 ~SDTS_CATD();
@@ -177,16 +176,14 @@ class SDTSModId
 
     /** The record within the module referred to.  This is -1 for unused
         SDTSModIds. */
-    long        nRecord;
+    int         nRecord;
 
     /** The "role" of this record within the module.  This is normally empty
         for references, but set in the oModId member of a feature.  */
-    char        szOBRP[8]; 
+    char        szOBRP[8];
 
     /** String "szModule:nRecord" */
     char        szName[20];
-
-
 };
 
 /************************************************************************/
@@ -216,8 +213,7 @@ public:
 
     void        ApplyATID( DDFField * );
 
-
-    /** Dump reable description of feature to indicated stream. */
+    /** Dump readable description of feature to indicated stream. */
     virtual void Dump( FILE * ) = 0;
 };
 
@@ -237,19 +233,19 @@ class SDTSIndexedReader
 
     int                 iCurrentFeature;
 
-protected:    
+protected:
     DDFModule           oDDFModule;
 
 public:
                         SDTSIndexedReader();
     virtual            ~SDTSIndexedReader();
-    
+
     virtual SDTSFeature  *GetNextRawFeature() = 0;
-    
+
     SDTSFeature        *GetNextFeature();
 
     virtual void        Rewind();
-    
+
     void                FillIndex();
     void                ClearIndex();
     int                 IsIndexed();
@@ -260,7 +256,6 @@ public:
     DDFModule          *GetModule() { return &oDDFModule; }
 };
 
-
 /************************************************************************/
 /*                             SDTSRawLine                              */
 /************************************************************************/
@@ -287,7 +282,7 @@ class SDTSRawLine : public SDTSFeature
 
     /** Identifier of polygon to left of this line.  This is the SDTS PIDL
         subfield. */
-    SDTSModId   oLeftPoly;             
+    SDTSModId   oLeftPoly;
 
     /** Identifier of polygon to right of this line.  This is the SDTS PIDR
         subfield. */
@@ -321,15 +316,15 @@ class SDTSRawLine : public SDTSFeature
 class SDTSLineReader : public SDTSIndexedReader
 {
     SDTS_IREF   *poIREF;
-    
+
   public:
-                SDTSLineReader( SDTS_IREF * );
+                explicit SDTSLineReader( SDTS_IREF * );
                 ~SDTSLineReader();
 
     int         Open( const char * );
     SDTSRawLine *GetNextLine( void );
     void        Close();
-    
+
     SDTSFeature *GetNextRawFeature( void ) { return GetNextLine(); }
 
     void        AttachToPolygons( SDTSTransfer *, int iPolyLayer  );
@@ -376,12 +371,10 @@ class SDTSAttrRecord : public SDTSFeature
 
 class SDTSAttrReader : public SDTSIndexedReader
 {
-    SDTS_IREF   *poIREF;
-
     int         bIsSecondary;
-    
+
   public:
-                SDTSAttrReader( SDTS_IREF * );
+                SDTSAttrReader();
    virtual     ~SDTSAttrReader();
 
     int         Open( const char * );
@@ -396,7 +389,7 @@ class SDTSAttrReader : public SDTSIndexedReader
       an Attribute Primary layer.
       */
     int         IsSecondary() { return bIsSecondary; }
-    
+
     SDTSFeature *GetNextRawFeature( void ) { return GetNextAttrRecord(); }
 };
 
@@ -422,7 +415,7 @@ class SDTSRawPoint : public SDTSFeature
     /** Z coordinate of point. */
     double      dfZ;
 
-    /** Optional identifier of area marked by this point (ie. PC01:27). */
+    /** Optional identifier of area marked by this point (i.e. PC01:27). */
     SDTSModId   oAreaId;                /* ARID */
 
     virtual void Dump( FILE * );
@@ -440,9 +433,9 @@ class SDTSRawPoint : public SDTSFeature
 class SDTSPointReader : public SDTSIndexedReader
 {
     SDTS_IREF   *poIREF;
-    
+
   public:
-                SDTSPointReader( SDTS_IREF * );
+                explicit SDTSPointReader( SDTS_IREF * );
     virtual    ~SDTSPointReader();
 
     int         Open( const char * );
@@ -470,13 +463,13 @@ class SDTSPointReader : public SDTSIndexedReader
   ring geometry.
 
   Note that the rings may not appear in any particular order, nor with any
-  meaningful direction (clockwise or counterclockwise).  
+  meaningful direction (clockwise or counterclockwise).
   */
 
 class SDTSRawPolygon : public SDTSFeature
 {
     void        AddEdgeToRing( int, double *, double *, double *, int, int );
-    
+
   public:
                 SDTSRawPolygon();
     virtual    ~SDTSRawPolygon();
@@ -522,7 +515,7 @@ class SDTSRawPolygon : public SDTSFeature
 class SDTSPolygonReader : public SDTSIndexedReader
 {
     int         bRingsAssembled;
-    
+
   public:
                 SDTSPolygonReader();
     virtual    ~SDTSPolygonReader();
@@ -543,7 +536,7 @@ class SDTSPolygonReader : public SDTSIndexedReader
 /**
   Class for reading raster data from a raster layer.
 
-  This class is somewhat unique amoung the reader classes in that it isn't
+  This class is somewhat unique among the reader classes in that it isn't
   derived from SDTSIndexedFeature, and it doesn't return "features".  Instead
   it is used to read raster blocks, in the natural block size of the dataset.
   */
@@ -563,7 +556,7 @@ class SDTSRasterReader
     int         nYStart;                /* SORI */
 
     double      adfTransform[6];
-    
+
   public:
     char        szINTR[4];              /* CE is center, TL is top left */
     char        szFMT[32];
@@ -578,7 +571,7 @@ class SDTSRasterReader
     void        Close();
 
     int         GetRasterType();        /* 1 = int16, see GDAL types */
-#define SDTS_RT_INT16   1   
+#define SDTS_RT_INT16   1
 #define SDTS_RT_FLOAT32 6
 
     int         GetTransform( double * );
@@ -660,12 +653,12 @@ class SDTSTransfer
 
     SDTSFeature *GetIndexedFeatureRef( SDTSModId *,
                                        SDTSLayerType *peType = NULL);
-                
+
     DDFField *GetAttr( SDTSModId * );
 
     int          GetBounds( double *pdfMinX, double *pdfMinY,
                             double *pdfMaxX, double *pdfMaxY );
-    
+
   private:
 
     SDTS_CATD   oCATD;
diff --git a/frmts/sdts/sdts_main.dox b/frmts/sdts/sdts_main.dox
index 98d2728..e68a3b3 100644
--- a/frmts/sdts/sdts_main.dox
+++ b/frmts/sdts/sdts_main.dox
@@ -18,7 +18,7 @@ of open source, easy to compile and integrate C++ code.<p>
 
 The USGS SDTS Page at 
 <a href="http://mcmcweb.er.usgs.gov/sdts/">http://mcmcweb.er.usgs.gov/sdts</a>
-is the definative source of information on the SDTS format.  The SDTS
+is the definitive source of information on the SDTS format.  The SDTS
 format is based on the 
 <a href="http://starship.skyport.net/crew/tibs/iso8211/faq.html">ISO 8211</a>
 encoding scheme for the underlying files, and the SDTS Abstraction Library
@@ -71,7 +71,7 @@ on how to use this library.<p>
 
 <ol>
 
-<li> First, fetch the source.  The most recent source should be accessable
+<li> First, fetch the source.  The most recent source should be accessible
 at an url such as 
 <a href="ftp://gdal.velocet.ca/pub/outgoing/sdts_1_3.tar.gz">
 ftp://gdal.velocet.ca/pub/outgoing/sdts_1_3.tar.gz</a>.<p>
@@ -100,7 +100,7 @@ on how to use this library.<p>
 
 <ol>
 
-<li> First, fetch the source.  The most recent source should be accessable
+<li> First, fetch the source.  The most recent source should be accessible
 at an url such as 
 <a href="ftp://gdal.velocet.ca/pub/outgoing/sdts_1_3.zip">
 ftp://gdal.velocet.ca/pub/outgoing/sdts_1_3.zip</a>.<p>
diff --git a/frmts/sdts/sdts_tut.dox b/frmts/sdts/sdts_tut.dox
index a929e04..6f260a0 100644
--- a/frmts/sdts/sdts_tut.dox
+++ b/frmts/sdts/sdts_tut.dox
@@ -378,7 +378,7 @@ and will be define later.<p>
 
 <h2>Write User Attributes</h2>
 
-In a manner analygous to the definition of the fields from the prototype
+In a manner analogous to the definition of the fields from the prototype
 attribute record, the following code loops over the subfields, and fetches
 the data for each.  The data extraction via poSR->GetSubfieldData() is
 a bit involved, and more information can be found on the DDFField reference
diff --git a/frmts/sdts/sdtsattrreader.cpp b/frmts/sdts/sdtsattrreader.cpp
index d77bcb5..90745bd 100644
--- a/frmts/sdts/sdtsattrreader.cpp
+++ b/frmts/sdts/sdtsattrreader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sdtsattrreader.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: sdtsattrreader.cpp 31596 2015-11-18 11:40:37Z rouault $
  *
  * Project:  SDTS Translator
  * Purpose:  Implementation of SDTSAttrReader class.
@@ -29,7 +29,7 @@
 
 #include "sdts_al.h"
 
-CPL_CVSID("$Id: sdtsattrreader.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: sdtsattrreader.cpp 31596 2015-11-18 11:40:37Z rouault $");
 
 
 /************************************************************************/
@@ -42,12 +42,10 @@ CPL_CVSID("$Id: sdtsattrreader.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
 /*                           SDTSAttrRecord()                           */
 /************************************************************************/
 
-SDTSAttrRecord::SDTSAttrRecord()
-
-{
-    poWholeRecord = NULL;
-    poATTR = NULL;
-}
+SDTSAttrRecord::SDTSAttrRecord() :
+    poWholeRecord(NULL),
+    poATTR(NULL)
+{}
 
 /************************************************************************/
 /*                          ~SDTSAttrRecord()                           */
@@ -84,11 +82,9 @@ void SDTSAttrRecord::Dump( FILE * fp )
 /*                           SDTSAttrReader()                           */
 /************************************************************************/
 
-SDTSAttrReader::SDTSAttrReader( SDTS_IREF * poIREFIn )
-
-{
-    poIREF = poIREFIn;
-}
+SDTSAttrReader::SDTSAttrReader() :
+    bIsSecondary(FALSE)
+{ }
 
 /************************************************************************/
 /*                          ~SDTSAttrReader()                           */
@@ -120,9 +116,7 @@ void SDTSAttrReader::Close()
 int SDTSAttrReader::Open( const char *pszFilename )
 
 {
-    int         bSuccess;
-
-    bSuccess = oDDFModule.Open( pszFilename );
+    bool bSuccess = CPL_TO_BOOL(oDDFModule.Open( pszFilename ));
 
     if( bSuccess )
         bIsSecondary = (oDDFModule.FindFieldDefn("ATTS") != NULL);
@@ -139,19 +133,16 @@ DDFField *SDTSAttrReader::GetNextRecord( SDTSModId * poModId,
                                          int bDuplicate )
 
 {
-    DDFRecord   *poRecord;
-    DDFField    *poATTP;
-    
 /* -------------------------------------------------------------------- */
 /*      Fetch a record.                                                 */
 /* -------------------------------------------------------------------- */
     if( ppoRecord != NULL )
         *ppoRecord = NULL;
-    
+
     if( oDDFModule.GetFP() == NULL )
         return NULL;
 
-    poRecord = oDDFModule.ReadRecord();
+    DDFRecord *poRecord = oDDFModule.ReadRecord();
 
     if( poRecord == NULL )
         return NULL;
@@ -166,7 +157,7 @@ DDFField *SDTSAttrReader::GetNextRecord( SDTSModId * poModId,
 /* -------------------------------------------------------------------- */
 /*      Find the ATTP field.                                            */
 /* -------------------------------------------------------------------- */
-    poATTP = poRecord->FindField( "ATTP", 0 );
+    DDFField *poATTP = poRecord->FindField( "ATTP", 0 );
     if( poATTP == NULL )
     {
         poATTP = poRecord->FindField( "ATTS", 0 );
@@ -180,7 +171,7 @@ DDFField *SDTSAttrReader::GetNextRecord( SDTSModId * poModId,
 /* -------------------------------------------------------------------- */
     if( poModId != NULL )
     {
-        DDFField        *poATPR = poRecord->FindField( "ATPR" );
+        DDFField *poATPR = poRecord->FindField( "ATPR" );
 
         if( poATPR == NULL )
             poATPR = poRecord->FindField( "ATSC" );
@@ -205,17 +196,15 @@ DDFField *SDTSAttrReader::GetNextRecord( SDTSModId * poModId,
 SDTSAttrRecord *SDTSAttrReader::GetNextAttrRecord()
 
 {
-    DDFRecord   *poRawRecord;
-    DDFField    *poATTRField;
     SDTSModId   oModId;
-    SDTSAttrRecord *poAttrRecord;
+    DDFRecord   *poRawRecord;
 
-    poATTRField = GetNextRecord( &oModId, &poRawRecord, TRUE );
+    DDFField *poATTRField = GetNextRecord( &oModId, &poRawRecord, TRUE );
 
     if( poATTRField == NULL )
         return NULL;
 
-    poAttrRecord = new SDTSAttrRecord();
+    SDTSAttrRecord *poAttrRecord = new SDTSAttrRecord();
 
     poAttrRecord->poWholeRecord = poRawRecord;
     poAttrRecord->poATTR = poATTRField;
@@ -223,4 +212,3 @@ SDTSAttrRecord *SDTSAttrReader::GetNextAttrRecord()
 
     return poAttrRecord;
 }
-
diff --git a/frmts/sdts/sdtscatd.cpp b/frmts/sdts/sdtscatd.cpp
index c6e5477..91db36a 100644
--- a/frmts/sdts/sdtscatd.cpp
+++ b/frmts/sdts/sdtscatd.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sdtscatd.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: sdtscatd.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Implementation of SDTS_CATD and SDTS_CATDEntry classes for
@@ -30,7 +30,7 @@
 
 #include "sdts_al.h"
 
-CPL_CVSID("$Id: sdtscatd.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: sdtscatd.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 
 /************************************************************************/
@@ -65,13 +65,11 @@ class SDTS_CATDEntry
 /*                             SDTS_CATD()                              */
 /************************************************************************/
 
-SDTS_CATD::SDTS_CATD()
-
-{
-    nEntries = 0;
-    papoEntries = NULL;
-    pszPrefixPath = NULL;
-}
+SDTS_CATD::SDTS_CATD() :
+    pszPrefixPath(NULL),
+    nEntries(0),
+    papoEntries(NULL)
+{}
 
 /************************************************************************/
 /*                             ~SDTS_CATD()                             */
@@ -79,10 +77,8 @@ SDTS_CATD::SDTS_CATD()
 
 SDTS_CATD::~SDTS_CATD()
 {
-    int         i;
-
-    for( i = 0; i < nEntries; i++ )
-    { 
+    for( int i = 0; i < nEntries; i++ )
+    {
         CPLFree( papoEntries[i]->pszModule );
         CPLFree( papoEntries[i]->pszType );
         CPLFree( papoEntries[i]->pszFile );
@@ -104,16 +100,14 @@ SDTS_CATD::~SDTS_CATD()
 int SDTS_CATD::Read( const char * pszFilename )
 
 {
-    DDFModule   oCATDFile;
-    DDFRecord   *poRecord;
-
 /* -------------------------------------------------------------------- */
 /*      Open the file.                                                  */
 /* -------------------------------------------------------------------- */
+    DDFModule oCATDFile;
     if( !oCATDFile.Open( pszFilename ) )
         return FALSE;
 
-    CPLErrorReset();  // clear any ADRG "unrecognised data_struct_code" errors
+    CPLErrorReset();  // Clear any ADRG "unrecognized data_struct_code" errors.
 
 /* -------------------------------------------------------------------- */
 /*      Does this file have a CATD field?  If not, it isn't an SDTS     */
@@ -122,14 +116,13 @@ int SDTS_CATD::Read( const char * pszFilename )
 /* -------------------------------------------------------------------- */
     if( oCATDFile.FindFieldDefn( "CATD" ) == NULL )
         return FALSE;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Strip off the filename, and keep the path prefix.               */
 /* -------------------------------------------------------------------- */
-    int         i;
-
     pszPrefixPath = CPLStrdup( pszFilename );
-    for( i = strlen(pszPrefixPath)-1; i > 0; i-- )
+    int i = static_cast<int>(strlen(pszPrefixPath)) - 1;
+    for( ; i > 0; i-- )
     {
         if( pszPrefixPath[i] == '\\' || pszPrefixPath[i] == '/' )
         {
@@ -142,11 +135,12 @@ int SDTS_CATD::Read( const char * pszFilename )
     {
         strcpy( pszPrefixPath, "." );
     }
-    
+
 /* ==================================================================== */
 /*      Loop reading CATD records, and adding to our list of entries    */
 /*      for each.                                                       */
 /* ==================================================================== */
+    DDFRecord *poRecord;
     while( (poRecord = oCATDFile.ReadRecord()) != NULL )
     {
 /* -------------------------------------------------------------------- */
@@ -154,11 +148,11 @@ int SDTS_CATD::Read( const char * pszFilename )
 /* -------------------------------------------------------------------- */
         if( poRecord->GetStringSubfield( "CATD", 0, "MODN", 0 ) == NULL )
             continue;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Create a new entry, and get the module and file name.           */
 /* -------------------------------------------------------------------- */
-        SDTS_CATDEntry  *poEntry = new SDTS_CATDEntry;
+        SDTS_CATDEntry *poEntry = new SDTS_CATDEntry;
 
         poEntry->pszModule =
             CPLStrdup(poRecord->GetStringSubfield( "CATD", 0, "NAME", 0 ));
@@ -172,15 +166,15 @@ int SDTS_CATD::Read( const char * pszFilename )
 /* -------------------------------------------------------------------- */
 /*      Create a full path to the file.                                 */
 /* -------------------------------------------------------------------- */
-        poEntry->pszFullPath = 
+        poEntry->pszFullPath =
             CPLStrdup(CPLFormCIFilename( pszPrefixPath, poEntry->pszFile,
                                          NULL ));
-        
+
 /* -------------------------------------------------------------------- */
 /*      Add the entry to the list.                                      */
 /* -------------------------------------------------------------------- */
-        papoEntries = (SDTS_CATDEntry **)
-            CPLRealloc(papoEntries, sizeof(void*) * ++nEntries );
+        papoEntries = reinterpret_cast<SDTS_CATDEntry **>(
+            CPLRealloc( papoEntries, sizeof(void*) * ++nEntries ) );
         papoEntries[nEntries-1] = poEntry;
     }
 
@@ -195,9 +189,7 @@ int SDTS_CATD::Read( const char * pszFilename )
 const char * SDTS_CATD::GetModuleFilePath( const char * pszModule )
 
 {
-    int         i;
-
-    for( i = 0; i < nEntries; i++ )
+    for( int i = 0; i < nEntries; i++ )
     {
         if( EQUAL(papoEntries[i]->pszModule,pszModule) )
             return papoEntries[i]->pszFullPath;
@@ -215,8 +207,8 @@ const char * SDTS_CATD::GetEntryModule( int iEntry )
 {
     if( iEntry < 0 || iEntry >= nEntries )
         return NULL;
-    else
-        return papoEntries[iEntry]->pszModule;
+
+    return papoEntries[iEntry]->pszModule;
 }
 
 /************************************************************************/
@@ -239,8 +231,8 @@ const char * SDTS_CATD::GetEntryTypeDesc( int iEntry )
 {
     if( iEntry < 0 || iEntry >= nEntries )
         return NULL;
-    else
-        return papoEntries[iEntry]->pszType;
+
+    return papoEntries[iEntry]->pszType;
 }
 
 /************************************************************************/
@@ -265,7 +257,7 @@ const char * SDTS_CATD::GetEntryTypeDesc( int iEntry )
  * <tt>Attribute Primary</tt> or <tt>Attribute Secondary</tt>.
  * <li> SLTPolygon: Read with SDTSPolygonReader, underlying type of
  * <tt>Polygon</tt>.
- * </ul> 
+ * </ul>
  */
 
 SDTSLayerType SDTS_CATD::GetEntryType( int iEntry )
@@ -274,23 +266,23 @@ SDTSLayerType SDTS_CATD::GetEntryType( int iEntry )
     if( iEntry < 0 || iEntry >= nEntries )
         return SLTUnknown;
 
-    else if( EQUALN(papoEntries[iEntry]->pszType,"Attribute Primary",17) )
+    else if( STARTS_WITH_CI(papoEntries[iEntry]->pszType, "Attribute Primary") )
         return SLTAttr;
-    
-    else if( EQUALN(papoEntries[iEntry]->pszType,"Attribute Secondary",17) )
+
+    else if( STARTS_WITH_CI(papoEntries[iEntry]->pszType,"Attribute Secondary") )
         return SLTAttr;
-    
+
     else if( EQUAL(papoEntries[iEntry]->pszType,"Line")
-             || EQUALN(papoEntries[iEntry]->pszType,"Line ",5) )
+             || STARTS_WITH_CI(papoEntries[iEntry]->pszType, "Line ") )
         return SLTLine;
-    
-    else if( EQUALN(papoEntries[iEntry]->pszType,"Point-Node",10) )
+
+    else if( STARTS_WITH_CI(papoEntries[iEntry]->pszType, "Point-Node") )
         return SLTPoint;
 
-    else if( EQUALN(papoEntries[iEntry]->pszType,"Polygon",7) )
+    else if( STARTS_WITH_CI(papoEntries[iEntry]->pszType, "Polygon") )
         return SLTPoly;
 
-    else if( EQUALN(papoEntries[iEntry]->pszType,"Cell",4) )
+    else if( STARTS_WITH_CI(papoEntries[iEntry]->pszType, "Cell") )
         return SLTRaster;
 
     else
@@ -316,6 +308,6 @@ const char * SDTS_CATD::GetEntryFilePath( int iEntry )
 {
     if( iEntry < 0 || iEntry >= nEntries )
         return NULL;
-    else
-        return papoEntries[iEntry]->pszFullPath;
+
+    return papoEntries[iEntry]->pszFullPath;
 }
diff --git a/frmts/sdts/sdtsdataset.cpp b/frmts/sdts/sdtsdataset.cpp
index 66df9a7..d2a9e55 100644
--- a/frmts/sdts/sdtsdataset.cpp
+++ b/frmts/sdts/sdtsdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sdtsdataset.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: sdtsdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  GDALDataset driver for SDTS Raster translator.
@@ -28,11 +28,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "sdts_al.h"
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
+#include "sdts_al.h"
 
-CPL_CVSID("$Id: sdtsdataset.cpp 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: sdtsdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 /**
  \file sdtsdataset.cpp
@@ -40,10 +41,6 @@ CPL_CVSID("$Id: sdtsdataset.cpp 27384 2014-05-24 12:28:12Z rouault $");
  exclude
 */
 
-CPL_C_START
-void    GDALRegister_SDTS(void);
-CPL_C_END
-
 /************************************************************************/
 /* ==================================================================== */
 /*                              SDTSDataset                             */
@@ -55,7 +52,7 @@ class SDTSRasterBand;
 class SDTSDataset : public GDALPamDataset
 {
     friend class SDTSRasterBand;
-    
+
     SDTSTransfer *poTransfer;
     SDTSRasterReader *poRL;
 
@@ -63,7 +60,7 @@ class SDTSDataset : public GDALPamDataset
 
   public:
     virtual     ~SDTSDataset();
-    
+
     static GDALDataset *Open( GDALOpenInfo * );
 
     virtual const char *GetProjectionRef(void);
@@ -75,11 +72,11 @@ class SDTSRasterBand : public GDALPamRasterBand
     friend class SDTSDataset;
 
     SDTSRasterReader *poRL;
-    
+
   public:
 
                 SDTSRasterBand( SDTSDataset *, int, SDTSRasterReader * );
-    
+
     virtual CPLErr IReadBlock( int, int, void * );
 
     virtual double GetNoDataValue( int *pbSuccess );
@@ -102,8 +99,7 @@ SDTSDataset::~SDTSDataset()
     if( poRL != NULL )
         delete poRL;
 
-    if( pszProjection != NULL )
-        CPLFree( pszProjection );
+    CPLFree( pszProjection );
 }
 
 /************************************************************************/
@@ -113,17 +109,14 @@ SDTSDataset::~SDTSDataset()
 GDALDataset *SDTSDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    int         i;
-    
 /* -------------------------------------------------------------------- */
 /*      Before trying SDTSOpen() we first verify that the first         */
 /*      record is in fact a SDTS file descriptor record.                */
 /* -------------------------------------------------------------------- */
-    char        *pachLeader = (char *) poOpenInfo->pabyHeader;
-    
     if( poOpenInfo->nHeaderBytes < 24 )
         return NULL;
 
+    char *pachLeader = reinterpret_cast<char *>( poOpenInfo->pabyHeader );
     if( pachLeader[5] != '1' && pachLeader[5] != '2' && pachLeader[5] != '3' )
         return NULL;
 
@@ -136,33 +129,33 @@ GDALDataset *SDTSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Try opening the dataset.                                        */
 /* -------------------------------------------------------------------- */
-    SDTSTransfer        *poTransfer = new SDTSTransfer;
-    
+    SDTSTransfer *poTransfer = new SDTSTransfer;
+
     if( !poTransfer->Open( poOpenInfo->pszFilename ) )
     {
         delete poTransfer;
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
         delete poTransfer;
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The SDTS driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Find the first raster layer.  If there are none, abort          */
 /*      returning an error.                                             */
 /* -------------------------------------------------------------------- */
     SDTSRasterReader    *poRL = NULL;
 
-    for( i = 0; i < poTransfer->GetLayerCount(); i++ )
+    for( int i = 0; i < poTransfer->GetLayerCount(); i++ )
     {
         if( poTransfer->GetLayerType( i ) == SLTRaster )
         {
@@ -174,7 +167,7 @@ GDALDataset *SDTSDataset::Open( GDALOpenInfo * poOpenInfo )
     if( poRL == NULL )
     {
         delete poTransfer;
-        
+
         CPLError( CE_Warning, CPLE_AppDefined,
                   "%s is an SDTS transfer, but has no raster cell layers.\n"
                   "Perhaps it is a vector transfer?\n",
@@ -189,21 +182,21 @@ GDALDataset *SDTSDataset::Open( GDALOpenInfo * poOpenInfo )
 
     poDS->poTransfer = poTransfer;
     poDS->poRL = poRL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Capture some information from the file that is of interest.     */
 /* -------------------------------------------------------------------- */
     poDS->nRasterXSize = poRL->GetXSize();
     poDS->nRasterYSize = poRL->GetYSize();
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
     poDS->nBands = 1;
-    poDS->papoBands = (GDALRasterBand **)
-        VSICalloc(sizeof(GDALRasterBand *),poDS->nBands);
+    poDS->papoBands = reinterpret_cast<GDALRasterBand **>(
+        VSICalloc( sizeof(GDALRasterBand *), poDS->nBands ) );
 
-    for( i = 0; i < poDS->nBands; i++ )
+    for( int i = 0; i < poDS->nBands; i++ )
         poDS->SetBand( i+1, new SDTSRasterBand( poDS, i+1, poRL ) );
 
 /* -------------------------------------------------------------------- */
@@ -214,7 +207,7 @@ GDALDataset *SDTSDataset::Open( GDALOpenInfo * poOpenInfo )
     SDTS_XREF   *poXREF = poTransfer->GetXREF();
 
     if( EQUAL(poXREF->pszSystemName,"UTM") )
-    {									
+    {
         oSRS.SetUTM( poXREF->nZone );
     }
     else if( EQUAL(poXREF->pszSystemName,"GEO") )
@@ -261,13 +254,16 @@ GDALDataset *SDTSDataset::Open( GDALOpenInfo * poOpenInfo )
                 if( poRecord->GetStringSubfield( "IDEN", 0, "MODN", 0 ) == NULL )
                     continue;
 
-                static const char* fields[][2] = { { "TITL", "TITLE" },
+                static const char* const fields[][2] = { { "TITL", "TITLE" },
                                                    { "DAID", "DATASET_ID" },
                                                    { "DAST", "DATA_STRUCTURE" },
                                                    { "MPDT", "MAP_DATE" },
                                                    { "DCDT", "DATASET_CREATION_DATE" } };
 
-                for (i = 0; i < (int)sizeof(fields) / (int)sizeof(fields[0]) ; i++)
+                for ( int i = 0;
+                      i < static_cast<int>( sizeof(fields) )
+                          / static_cast<int>( sizeof(fields[0] ) );
+                      i++)
                 {
                     const char* pszFieldValue =
                             poRecord->GetStringSubfield( "IDEN", 0, fields[i][0], 0 );
@@ -291,7 +287,7 @@ GDALDataset *SDTSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles() );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -303,8 +299,8 @@ CPLErr SDTSDataset::GetGeoTransform( double * padfTransform )
 {
     if( poRL->GetTransform( padfTransform ) )
         return CE_None;
-    else
-        return CE_Failure;
+
+    return CE_Failure;
 }
 
 /************************************************************************/
@@ -327,13 +323,12 @@ const char *SDTSDataset::GetProjectionRef()
 /*                           SDTSRasterBand()                            */
 /************************************************************************/
 
-SDTSRasterBand::SDTSRasterBand( SDTSDataset *poDS, int nBand,
-                                SDTSRasterReader * poRL )
-
+SDTSRasterBand::SDTSRasterBand( SDTSDataset *poDSIn, int nBandIn,
+                                SDTSRasterReader * poRLIn ) :
+    poRL(poRLIn)
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
-    this->poRL = poRL;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
     if( poRL->GetRasterType() == SDTS_RT_INT16 )
         eDataType = GDT_Int16;
@@ -354,8 +349,8 @@ CPLErr SDTSRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 {
     if( poRL->GetBlock( nBlockXOff, nBlockYOff, pImage ) )
         return CE_None;
-    else
-        return CE_Failure;
+
+    return CE_Failure;
 }
 
 /************************************************************************/
@@ -367,7 +362,7 @@ double SDTSRasterBand::GetNoDataValue( int *pbSuccess )
 {
     if( pbSuccess != NULL )
         *pbSuccess = TRUE;
-    
+
     return -32766.0;
 }
 
@@ -380,10 +375,10 @@ const char *SDTSRasterBand::GetUnitType()
 {
     if( EQUAL(poRL->szUNITS,"FEET") )
         return "ft";
-    else if( EQUALN(poRL->szUNITS,"MET",3) )
+    else if( STARTS_WITH_CI(poRL->szUNITS, "MET") )
         return "m";
-    else
-        return poRL->szUNITS;
+
+    return poRL->szUNITS;
 }
 
 /************************************************************************/
@@ -393,24 +388,19 @@ const char *SDTSRasterBand::GetUnitType()
 void GDALRegister_SDTS()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "SDTS" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "SDTS" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "SDTS" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "SDTS Raster" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#SDTS" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "ddf" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = SDTSDataset::Open;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
-}
+    GDALDriver *poDriver = new GDALDriver();
 
+    poDriver->SetDescription( "SDTS" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "SDTS Raster" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#SDTS" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "ddf" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = SDTSDataset::Open;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/frmts/sdts/sdtsindexedreader.cpp b/frmts/sdts/sdtsindexedreader.cpp
index 3c10ea9..db177cd 100644
--- a/frmts/sdts/sdtsindexedreader.cpp
+++ b/frmts/sdts/sdtsindexedreader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sdtsindexedreader.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: sdtsindexedreader.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Implmementation of SDTSIndexedReader class.  This base class for
@@ -32,19 +32,17 @@
 
 #include "sdts_al.h"
 
-CPL_CVSID("$Id: sdtsindexedreader.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: sdtsindexedreader.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 /************************************************************************/
 /*                         SDTSIndexedReader()                          */
 /************************************************************************/
 
-SDTSIndexedReader::SDTSIndexedReader()
-
-{
-    nIndexSize = 0;
-    papoFeatures = NULL;
-    iCurrentFeature = 0;
-}
+SDTSIndexedReader::SDTSIndexedReader() :
+    nIndexSize(0),
+    papoFeatures(NULL),
+    iCurrentFeature(0)
+{}
 
 /************************************************************************/
 /*                         ~SDTSIndexedReader()                         */
@@ -82,7 +80,7 @@ int SDTSIndexedReader::IsIndexed()
   Free all features in the index (if filled).
 
   After this the reader is considered to not be indexed, and IsIndexed()
-  will return FALSE untill the index is forcably filled again. 
+  will return FALSE until the index is forcibly filled again.
   */
 
 void SDTSIndexedReader::ClearIndex()
@@ -93,7 +91,7 @@ void SDTSIndexedReader::ClearIndex()
         if( papoFeatures[i] != NULL )
             delete papoFeatures[i];
     }
-    
+
     CPLFree( papoFeatures );
 
     papoFeatures = NULL;
@@ -124,18 +122,16 @@ SDTSFeature *SDTSIndexedReader::GetNextFeature()
 {
     if( nIndexSize == 0 )
         return GetNextRawFeature();
-    else
-    {
-        while( iCurrentFeature < nIndexSize )
-        {
-            if( papoFeatures[iCurrentFeature] != NULL )
-                return papoFeatures[iCurrentFeature++];
-            else
-                iCurrentFeature++;
-        }
 
-        return NULL;
+    while( iCurrentFeature < nIndexSize )
+    {
+        if( papoFeatures[iCurrentFeature] != NULL )
+            return papoFeatures[iCurrentFeature++];
+        else
+            iCurrentFeature++;
     }
+
+    return NULL;
 }
 
 /************************************************************************/
@@ -145,13 +141,13 @@ SDTSFeature *SDTSIndexedReader::GetNextFeature()
 /**
  Fetch a feature based on it's record number.
 
- This method will forceably fill the feature cache, reading all the
+ This method will forcibly fill the feature cache, reading all the
  features in the file into memory, if they haven't already been loaded.
  The ClearIndex() method can be used to flush this cache when no longer
- needed. 
+ needed.
 
  @param iRecordId the record to fetch, normally based on the nRecord
- field of an SDTSModId. 
+ field of an SDTSModId.
 
  @return a pointer to an internal feature (not to be deleted) or NULL
  if there is no matching feature.
@@ -165,8 +161,8 @@ SDTSFeature *SDTSIndexedReader::GetIndexedFeatureRef( int iRecordId )
 
     if( iRecordId < 0 || iRecordId >= nIndexSize )
         return NULL;
-    else
-        return papoFeatures[iRecordId];
+
+    return papoFeatures[iRecordId];
 }
 
 /************************************************************************/
@@ -183,16 +179,16 @@ SDTSFeature *SDTSIndexedReader::GetIndexedFeatureRef( int iRecordId )
 void SDTSIndexedReader::FillIndex()
 
 {
-    SDTSFeature         *poFeature;
 
     if( nIndexSize != 0 )
         return;
 
     Rewind();
-    
+
+    SDTSFeature *poFeature;
     while( (poFeature = GetNextRawFeature()) != NULL )
     {
-        int     iRecordId = poFeature->oModId.nRecord;
+        const int iRecordId = poFeature->oModId.nRecord;
 
         CPLAssert( iRecordId < 1000000 );
         if( iRecordId >= 1000000 )
@@ -203,10 +199,10 @@ void SDTSIndexedReader::FillIndex()
 
         if( iRecordId >= nIndexSize )
         {
-            int         nNewSize = (int) (iRecordId * 1.25 + 100);
+            const int nNewSize = static_cast<int>(iRecordId * 1.25 + 100);
 
-            papoFeatures = (SDTSFeature **)
-                CPLRealloc( papoFeatures, sizeof(void*) * nNewSize);
+            papoFeatures = reinterpret_cast<SDTSFeature **>(
+                CPLRealloc( papoFeatures, sizeof(void*) * nNewSize ) );
 
             for( int i = nIndexSize; i < nNewSize; i++ )
                 papoFeatures[i] = NULL;
@@ -235,8 +231,8 @@ void SDTSIndexedReader::FillIndex()
 
   This method will have the side effect of rewinding unindexed readers
   because the scanning operation requires reading all records in the module
-  from disk. 
-  
+  from disk.
+
   @param pszFName the field name to search for.  By default "ATID" is
   used.
 
diff --git a/frmts/sdts/sdtsiref.cpp b/frmts/sdts/sdtsiref.cpp
index 1d03bb4..2194f4a 100644
--- a/frmts/sdts/sdtsiref.cpp
+++ b/frmts/sdts/sdtsiref.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sdtsiref.cpp 17434 2009-07-23 19:55:45Z chaitanya $
+ * $Id: sdtsiref.cpp 31332 2015-11-03 17:34:39Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Implementation of SDTS_IREF class for reading IREF module.
@@ -29,26 +29,24 @@
 
 #include "sdts_al.h"
 
-CPL_CVSID("$Id: sdtsiref.cpp 17434 2009-07-23 19:55:45Z chaitanya $");
+CPL_CVSID("$Id: sdtsiref.cpp 31332 2015-11-03 17:34:39Z goatbar $");
 
 /************************************************************************/
 /*                             SDTS_IREF()                              */
 /************************************************************************/
 
-SDTS_IREF::SDTS_IREF()
-
-{
-    dfXScale = 1.0;
-    dfYScale = 1.0;
-    dfXOffset = 0.0;
-    dfYOffset = 0.0;
-    dfXRes = 1.0;
-    dfYRes = 1.0;
-
-    pszXAxisName = CPLStrdup("");
-    pszYAxisName = CPLStrdup("");
-    pszCoordinateFormat = CPLStrdup("");
-}
+SDTS_IREF::SDTS_IREF() :
+    nDefaultSADRFormat(0),
+    pszXAxisName(CPLStrdup("")),
+    pszYAxisName(CPLStrdup("")),
+    dfXScale(1.0),
+    dfYScale(1.0),
+    dfXOffset(0.0),
+    dfYOffset(0.0),
+    dfXRes(1.0),
+    dfYRes(1.0),
+    pszCoordinateFormat(CPLStrdup(""))
+{}
 
 /************************************************************************/
 /*                             ~SDTS_IREF()                             */
@@ -70,19 +68,17 @@ SDTS_IREF::~SDTS_IREF()
 int SDTS_IREF::Read( const char * pszFilename )
 
 {
-    DDFModule   oIREFFile;
-    DDFRecord   *poRecord;
-
 /* -------------------------------------------------------------------- */
 /*      Open the file, and read the header.                             */
 /* -------------------------------------------------------------------- */
+    DDFModule oIREFFile;
     if( !oIREFFile.Open( pszFilename ) )
         return FALSE;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read the first record, and verify that this is an IREF record.  */
 /* -------------------------------------------------------------------- */
-    poRecord = oIREFFile.ReadRecord();
+    DDFRecord *poRecord = oIREFFile.ReadRecord();
     if( poRecord == NULL )
         return FALSE;
 
@@ -98,7 +94,7 @@ int SDTS_IREF::Read( const char * pszFilename )
     CPLFree( pszYAxisName );
     pszYAxisName = CPLStrdup( poRecord->GetStringSubfield( "IREF", 0,
                                                            "YLBL", 0 ) );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Get the coordinate encoding.                                    */
 /* -------------------------------------------------------------------- */
@@ -134,8 +130,8 @@ int SDTS_IREF::GetSADRCount( DDFField * poField )
 {
     if( nDefaultSADRFormat )
         return poField->GetDataSize() / SDTS_SIZEOF_SADR;
-    else
-        return poField->GetRepeatCount();
+
+    return poField->GetRepeatCount();
 }
 
 /************************************************************************/
@@ -154,23 +150,23 @@ int SDTS_IREF::GetSADR( DDFField * poField, int nVertices,
     if( nDefaultSADRFormat
         && poField->GetFieldDefn()->GetSubfieldCount() == 2 )
     {
+        CPLAssert( poField->GetDataSize() >= nVertices * SDTS_SIZEOF_SADR );
+
         GInt32          anXY[2];
         const char      *pachRawData = poField->GetData();
-        
-        CPLAssert( poField->GetDataSize() >= nVertices * SDTS_SIZEOF_SADR );
 
         for( int iVertex = 0; iVertex < nVertices; iVertex++ )
         {
             // we copy to a temp buffer to ensure it is world aligned.
             memcpy( anXY, pachRawData, 8 );
             pachRawData += 8;
-            
+
             // possibly byte swap, and always apply scale factor
             padfX[iVertex] = dfXOffset
-                + dfXScale * ((int) CPL_MSBWORD32( anXY[0] ));
+                + dfXScale * static_cast<int>( CPL_MSBWORD32( anXY[0] ) );
             padfY[iVertex] = dfYOffset
-                + dfYScale * ((int) CPL_MSBWORD32( anXY[1] ));
-            
+                + dfYScale * static_cast<int>( CPL_MSBWORD32( anXY[1] ) );
+
             padfZ[iVertex] = 0.0;
         }
     }
@@ -185,17 +181,14 @@ int SDTS_IREF::GetSADR( DDFField * poField, int nVertices,
         DDFFieldDefn    *poFieldDefn = poField->GetFieldDefn();
         int             nBytesRemaining = poField->GetDataSize();
         const char     *pachFieldData = poField->GetData();
-        int             iVertex;
-            
+
         CPLAssert( poFieldDefn->GetSubfieldCount() == 2
                    || poFieldDefn->GetSubfieldCount() == 3 );
-        
-        for( iVertex = 0; iVertex < nVertices; iVertex++ )
+
+        for( int iVertex = 0; iVertex < nVertices; iVertex++ )
         {
-            double      adfXYZ[3];
-            GByte       *pabyBString;
+            double adfXYZ[3] = {0.0, 0.0, 0.0};
 
-            adfXYZ[2] = 0.0;
 
             for( int iEntry = 0;
                  iEntry < poFieldDefn->GetSubfieldCount();
@@ -212,48 +205,54 @@ int SDTS_IREF::GetSADR( DDFField * poField, int nVertices,
                                               nBytesRemaining,
                                               &nBytesConsumed );
                     break;
-                    
+
                   case DDFFloat:
                     adfXYZ[iEntry] =
                         poSF->ExtractFloatData( pachFieldData,
                                                 nBytesRemaining,
                                                 &nBytesConsumed );
                     break;
-                    
+
                   case DDFBinaryString:
-                    pabyBString = (GByte *) 
-                        poSF->ExtractStringData( pachFieldData,
-                                                 nBytesRemaining,
-                                                 &nBytesConsumed );
+                    {
+                      GByte *pabyBString = reinterpret_cast<GByte *> (
+                          const_cast<char *>(
+                              poSF->ExtractStringData( pachFieldData,
+                                                       nBytesRemaining,
+                                                       &nBytesConsumed ) ) );
 
                     if( EQUAL(pszCoordinateFormat,"BI32") )
                     {
                         GInt32  nValue;
                         memcpy( &nValue, pabyBString, 4 );
-                        adfXYZ[iEntry] = ((int) CPL_MSBWORD32( nValue ));
+                        adfXYZ[iEntry]
+                            = static_cast<int>( CPL_MSBWORD32( nValue ) );
                     }
                     else if( EQUAL(pszCoordinateFormat,"BI16") )
                     {
                         GInt16  nValue;
                         memcpy( &nValue, pabyBString, 2 );
-                        adfXYZ[iEntry] = ((int) CPL_MSBWORD16( nValue ));
+                        adfXYZ[iEntry]
+                            = static_cast<int>( CPL_MSBWORD16( nValue ) );
                     }
                     else if( EQUAL(pszCoordinateFormat,"BU32") )
                     {
                         GUInt32 nValue;
                         memcpy( &nValue, pabyBString, 4 );
-                        adfXYZ[iEntry] = ((GUInt32) CPL_MSBWORD32( nValue ));
+                        adfXYZ[iEntry]
+                            = static_cast<GUInt32>( CPL_MSBWORD32( nValue ) );
                     }
                     else if( EQUAL(pszCoordinateFormat,"BU16") )
                     {
                         GUInt16 nValue;
                         memcpy( &nValue, pabyBString, 2 );
-                        adfXYZ[iEntry] = ((GUInt16) CPL_MSBWORD16( nValue ));
+                        adfXYZ[iEntry]
+                            = static_cast<GUInt16>( CPL_MSBWORD16( nValue ) );
                     }
                     else if( EQUAL(pszCoordinateFormat,"BFP32") )
                     {
                         float   fValue;
-                        
+
                         memcpy( &fValue, pabyBString, 4 );
                         CPL_MSBPTR32( &fValue );
                         adfXYZ[iEntry] = fValue;
@@ -261,11 +260,12 @@ int SDTS_IREF::GetSADR( DDFField * poField, int nVertices,
                     else if( EQUAL(pszCoordinateFormat,"BFP64") )
                     {
                         double  dfValue;
-                        
+
                         memcpy( &dfValue, pabyBString, 8 );
                         CPL_MSBPTR64( &dfValue );
                         adfXYZ[iEntry] = dfValue;
                     }
+                    }
                     break;
 
                   default:
@@ -282,7 +282,6 @@ int SDTS_IREF::GetSADR( DDFField * poField, int nVertices,
             padfZ[iVertex] = adfXYZ[2];
         } /* next iVertex */
     }
-    
+
     return TRUE;
 }
-
diff --git a/frmts/sdts/sdtslib.cpp b/frmts/sdts/sdtslib.cpp
index e2ef9ba..80d147a 100644
--- a/frmts/sdts/sdtslib.cpp
+++ b/frmts/sdts/sdtslib.cpp
@@ -1,9 +1,9 @@
 /******************************************************************************
- * $Id: sdtslib.cpp 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: sdtslib.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Various utility functions that apply to all SDTS profiles.
- *           SDTSModId, and SDTSFeature methods. 
+ *           SDTSModId, and SDTSFeature methods.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -32,18 +32,16 @@
 #include "sdts_al.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: sdtslib.cpp 27044 2014-03-16 23:41:27Z rouault $");
+CPL_CVSID("$Id: sdtslib.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 /************************************************************************/
 /*                            SDTSFeature()                             */
 /************************************************************************/
 
-SDTSFeature::SDTSFeature()
-
-{
-    nAttributes = 0;
-    paoATID = NULL;
-}
+SDTSFeature::SDTSFeature() :
+    nAttributes(0),
+    paoATID(NULL)
+{}
 
 /************************************************************************/
 /*                       SDTSFeature::ApplyATID()                       */
@@ -52,30 +50,28 @@ SDTSFeature::SDTSFeature()
 void SDTSFeature::ApplyATID( DDFField * poField )
 
 {
-    int         nRepeatCount = poField->GetRepeatCount();
-    int         bUsualFormat;
-    DDFSubfieldDefn *poMODN;
-
-    poMODN = poField->GetFieldDefn()->FindSubfieldDefn( "MODN" );
+    DDFSubfieldDefn *poMODN
+        = poField->GetFieldDefn()->FindSubfieldDefn( "MODN" );
     if( poMODN == NULL )
     {
         //CPLAssert( FALSE );
         return;
     }
-    
-    bUsualFormat = poMODN->GetWidth() == 4;
+
+    bool bUsualFormat = poMODN->GetWidth() == 4;
+    const int nRepeatCount = poField->GetRepeatCount();
     for( int iRepeat = 0; iRepeat < nRepeatCount; iRepeat++ )
     {
-        paoATID = (SDTSModId *) CPLRealloc(paoATID,
-                                           sizeof(SDTSModId)*(nAttributes+1));
+      paoATID = reinterpret_cast<SDTSModId *>(
+          CPLRealloc( paoATID, sizeof(SDTSModId)*(nAttributes+1) ) );
 
-        const char * pabyData;
         SDTSModId *poModId = paoATID + nAttributes;
 
         if( bUsualFormat )
         {
-            pabyData = poField->GetSubfieldData( poMODN, NULL, iRepeat );
-            
+            const char * pabyData
+                = poField->GetSubfieldData( poMODN, NULL, iRepeat );
+
             memcpy( poModId->szModule, pabyData, 4 );
             poModId->szModule[4] = '\0';
             poModId->nRecord = atoi(pabyData + 4);
@@ -85,7 +81,7 @@ void SDTSFeature::ApplyATID( DDFField * poField )
         {
             poModId->Set( poField );
         }
-        
+
         nAttributes++;
     }
 }
@@ -114,7 +110,7 @@ int SDTSModId::Set( DDFField *poField )
     const char  *pachData = poField->GetData();
     DDFFieldDefn *poDefn = poField->GetFieldDefn();
 
-    if( poDefn->GetSubfieldCount() >= 2 
+    if( poDefn->GetSubfieldCount() >= 2
         && poDefn->GetSubfield(0)->GetWidth() == 4 )
     {
         memcpy( szModule, pachData, 4 );
@@ -124,11 +120,9 @@ int SDTSModId::Set( DDFField *poField )
     }
     else
     {
-        DDFSubfieldDefn *poSF;
-        int             nBytesRemaining;
-        const char  *pachData;
-
-        poSF = poField->GetFieldDefn()->FindSubfieldDefn( "MODN" );
+        DDFSubfieldDefn *poSF
+            = poField->GetFieldDefn()->FindSubfieldDefn( "MODN" );
+        int nBytesRemaining;
         pachData = poField->GetSubfieldData(poSF, &nBytesRemaining);
         strncpy( szModule,
                  poSF->ExtractStringData( pachData, nBytesRemaining, NULL),
@@ -146,21 +140,18 @@ int SDTSModId::Set( DDFField *poField )
 
     if( poDefn->GetSubfieldCount() == 3 )
     {
-        DDFSubfieldDefn         *poSF;
-
-        poSF = poField->GetFieldDefn()->FindSubfieldDefn( "OBRP" );
+        DDFSubfieldDefn *poSF = poField->GetFieldDefn()->FindSubfieldDefn( "OBRP" );
         if( poSF != NULL )
         {
-            int         nBytesRemaining;
-            const char  *pachData;
-
-            pachData = poField->GetSubfieldData(poSF, &nBytesRemaining);
+            int nBytesRemaining;
+            pachData
+                = poField->GetSubfieldData(poSF, &nBytesRemaining);
             if( pachData != NULL )
             {
-                strncpy( szOBRP, 
+                strncpy( szOBRP,
                         poSF->ExtractStringData( pachData, nBytesRemaining, NULL),
                         sizeof(szOBRP) );
-                
+
                 szOBRP[sizeof(szOBRP)-1] = '\0';
             }
         }
@@ -176,7 +167,7 @@ int SDTSModId::Set( DDFField *poField )
 const char * SDTSModId::GetName()
 
 {
-    sprintf( szName, "%s:%ld", szModule, nRecord );
+    snprintf( szName, sizeof(szName), "%s:%d", szModule, nRecord );
 
     return szName;
 }
@@ -195,47 +186,40 @@ char **SDTSScanModuleReferences( DDFModule * poModule, const char * pszFName )
 /* -------------------------------------------------------------------- */
 /*      Identify the field, and subfield we are interested in.          */
 /* -------------------------------------------------------------------- */
-    DDFFieldDefn        *poIDField;
-    DDFSubfieldDefn     *poMODN;
-
-    poIDField = poModule->FindFieldDefn( pszFName );
+    DDFFieldDefn *poIDField = poModule->FindFieldDefn( pszFName );
 
     if( poIDField == NULL )
         return NULL;
 
-    poMODN = poIDField->FindSubfieldDefn( "MODN" );
+    DDFSubfieldDefn *poMODN = poIDField->FindSubfieldDefn( "MODN" );
     if( poMODN == NULL )
         return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Scan the file.                                                  */
 /* -------------------------------------------------------------------- */
-    DDFRecord   *poRecord;
-    char        **papszModnList = NULL;
-    
+
     poModule->Rewind();
+
+    DDFRecord *poRecord;
+    char **papszModnList = NULL;
     while( (poRecord = poModule->ReadRecord()) != NULL )
     {
-        int     iField;
-        
-        for( iField = 0; iField < poRecord->GetFieldCount(); iField++ )
+        for( int iField = 0; iField < poRecord->GetFieldCount(); iField++ )
         {
             DDFField    *poField = poRecord->GetField( iField );
 
             if( poField->GetFieldDefn() == poIDField )
             {
-                const char      *pszModName;
-                int             i;
-
-                for( i = 0; i < poField->GetRepeatCount(); i++ )
+                for( int i = 0; i < poField->GetRepeatCount(); i++ )
                 {
-                    char        szName[5];
-                    
-                    pszModName = poField->GetSubfieldData(poMODN,NULL,i);
+                    const char *pszModName
+                        = poField->GetSubfieldData(poMODN, NULL, i);
 
+                    char szName[5];
                     strncpy( szName, pszModName, 4 );
                     szName[4] = '\0';
-                    
+
                     if( CSLFindString( papszModnList, szName ) == -1 )
                         papszModnList = CSLAddString( papszModnList, szName );
                 }
@@ -247,5 +231,3 @@ char **SDTSScanModuleReferences( DDFModule * poModule, const char * pszFName )
 
     return papszModnList;
 }
-
-
diff --git a/frmts/sdts/sdtslinereader.cpp b/frmts/sdts/sdtslinereader.cpp
index 1d7ad75..78f672e 100644
--- a/frmts/sdts/sdtslinereader.cpp
+++ b/frmts/sdts/sdtslinereader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sdtslinereader.cpp 28039 2014-11-30 18:24:59Z rouault $
+ * $Id: sdtslinereader.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Implementation of SDTSLineReader and SDTSRawLine classes.
@@ -29,7 +29,7 @@
 
 #include "sdts_al.h"
 
-CPL_CVSID("$Id: sdtslinereader.cpp 28039 2014-11-30 18:24:59Z rouault $");
+CPL_CVSID("$Id: sdtslinereader.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -44,11 +44,12 @@ CPL_CVSID("$Id: sdtslinereader.cpp 28039 2014-11-30 18:24:59Z rouault $");
 /*                            SDTSRawLine()                             */
 /************************************************************************/
 
-SDTSRawLine::SDTSRawLine()
-
+SDTSRawLine::SDTSRawLine() :
+    nVertices(0),
+    padfX(NULL),
+    padfY(NULL),
+    padfZ(NULL)
 {
-    nVertices = 0;
-    padfX = padfY = padfZ = NULL;
     nAttributes = 0;
 }
 
@@ -76,7 +77,7 @@ int SDTSRawLine::Read( SDTS_IREF * poIREF, DDFRecord * poRecord )
     // E.Rouault: Not sure if this test is really useful
     if( poRecord->GetStringSubfield( "LINE", 0, "MODN", 0 ) == NULL )
         return FALSE;
-    
+
 /* ==================================================================== */
 /*      Loop over fields in this record, looking for those we           */
 /*      recognise, and need.  I don't use the getSubfield()             */
@@ -99,24 +100,25 @@ int SDTSRawLine::Read( SDTS_IREF * poIREF, DDFRecord * poRecord )
 
         else if( EQUAL(pszFieldName,"PIDL") )
             oLeftPoly.Set( poField );
-        
+
         else if( EQUAL(pszFieldName,"PIDR") )
             oRightPoly.Set( poField );
-        
+
         else if( EQUAL(pszFieldName,"SNID") )
             oStartNode.Set( poField );
-        
+
         else if( EQUAL(pszFieldName,"ENID") )
             oEndNode.Set( poField );
 
         else if( EQUAL(pszFieldName,"SADR") )
         {
             nVertices = poIREF->GetSADRCount( poField );
-            
-            padfX = (double*) CPLRealloc(padfX,sizeof(double)*nVertices*3);
+
+            padfX = reinterpret_cast<double *>(
+                CPLRealloc( padfX, sizeof(double) * nVertices*3 ) );
             padfY = padfX + nVertices;
             padfZ = padfX + 2*nVertices;
-            
+
             poIREF->GetSADR( poField, nVertices, padfX, padfY, padfZ );
         }
     }
@@ -133,28 +135,26 @@ int SDTSRawLine::Read( SDTS_IREF * poIREF, DDFRecord * poRecord )
 void SDTSRawLine::Dump( FILE * fp )
 
 {
-    int    i;
-
     fprintf( fp, "SDTSRawLine\n" );
-    fprintf( fp, "  Module=%s, Record#=%ld\n",
+    fprintf( fp, "  Module=%s, Record#=%d\n",
              oModId.szModule, oModId.nRecord );
     if( oLeftPoly.nRecord != -1 )
-        fprintf( fp, "  LeftPoly (Module=%s, Record=%ld)\n", 
+        fprintf( fp, "  LeftPoly (Module=%s, Record=%d)\n",
                  oLeftPoly.szModule, oLeftPoly.nRecord );
     if( oRightPoly.nRecord != -1 )
-        fprintf( fp, "  RightPoly (Module=%s, Record=%ld)\n", 
+        fprintf( fp, "  RightPoly (Module=%s, Record=%d)\n",
                  oRightPoly.szModule, oRightPoly.nRecord );
     if( oStartNode.nRecord != -1 )
-        fprintf( fp, "  StartNode (Module=%s, Record=%ld)\n", 
+        fprintf( fp, "  StartNode (Module=%s, Record=%d)\n",
                  oStartNode.szModule, oStartNode.nRecord );
     if( oEndNode.nRecord != -1 )
-        fprintf( fp, "  EndNode (Module=%s, Record=%ld)\n", 
+        fprintf( fp, "  EndNode (Module=%s, Record=%d)\n",
                  oEndNode.szModule, oEndNode.nRecord );
-    for( i = 0; i < nAttributes; i++ )
-        fprintf( fp, "  Attribute (Module=%s, Record=%ld)\n", 
+    for( int i = 0; i < nAttributes; i++ )
+        fprintf( fp, "  Attribute (Module=%s, Record=%d)\n",
                  paoATID[i].szModule, paoATID[i].nRecord );
 
-    for( i = 0; i < nVertices; i++ )
+    for( int i = 0; i < nVertices; i++ )
     {
         fprintf( fp, "  Vertex[%3d] = (%.2f,%.2f,%.2f)\n",
                  i, padfX[i], padfY[i], padfZ[i] );
@@ -217,7 +217,7 @@ int SDTSLineReader::Open( const char * pszFilename )
 /*      Fetch the next line feature as an STDSRawLine.                  */
 /************************************************************************/
 
-SDTSRawLine * SDTSLineReader::GetNextLine()
+SDTSRawLine *SDTSLineReader::GetNextLine()
 
 {
 /* -------------------------------------------------------------------- */
@@ -229,25 +229,23 @@ SDTSRawLine * SDTSLineReader::GetNextLine()
 /* -------------------------------------------------------------------- */
 /*      Read the record.                                                */
 /* -------------------------------------------------------------------- */
-    DDFRecord   *poRecord = oDDFModule.ReadRecord();
-    
+    DDFRecord *poRecord = oDDFModule.ReadRecord();
+
     if( poRecord == NULL )
         return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Transform into a line feature.                                  */
 /* -------------------------------------------------------------------- */
-    SDTSRawLine         *poRawLine = new SDTSRawLine();
+    SDTSRawLine *poRawLine = new SDTSRawLine();
 
     if( poRawLine->Read( poIREF, poRecord ) )
     {
         return( poRawLine );
     }
-    else
-    {
-        delete poRawLine;
-        return NULL;
-    }
+
+    delete poRawLine;
+    return NULL;
 }
 
 /************************************************************************/
@@ -265,12 +263,12 @@ SDTSRawLine * SDTSLineReader::GetNextLine()
 
   @param poTransfer the SDTSTransfer of this SDTSLineReader, and from
   which the related SDTSPolygonReader will be instantiated.
-  @param iTargetPolyLayer the polygon reader instance number, used to avoid 
+  @param iTargetPolyLayer the polygon reader instance number, used to avoid
   processing lines for other layers.
 
 */
 
-void SDTSLineReader::AttachToPolygons( SDTSTransfer * poTransfer, 
+void SDTSLineReader::AttachToPolygons( SDTSTransfer * poTransfer,
                                        int iTargetPolyLayer )
 
 {
@@ -286,11 +284,11 @@ void SDTSLineReader::AttachToPolygons( SDTSTransfer * poTransfer,
 /*      Loop over all lines, attaching them to the polygons they        */
 /*      have as right and left faces.                                   */
 /* ==================================================================== */
+    Rewind();
     SDTSRawLine *poLine;
     SDTSPolygonReader *poPolyReader = NULL;
-    
-    Rewind();
-    while( (poLine = (SDTSRawLine *) GetNextFeature()) != NULL )
+    while( (poLine = reinterpret_cast<SDTSRawLine *>( GetNextFeature()) )
+           != NULL )
     {
 /* -------------------------------------------------------------------- */
 /*      Skip lines with the same left and right polygon face.  These    */
@@ -307,7 +305,7 @@ void SDTSLineReader::AttachToPolygons( SDTSTransfer * poTransfer,
         if( poPolyReader == NULL )
         {
             int         iPolyLayer = -1;
-            
+
             if( poLine->oLeftPoly.nRecord != -1 )
             {
                 iPolyLayer = poTransfer->FindLayer(poLine->oLeftPoly.szModule);
@@ -323,8 +321,8 @@ void SDTSLineReader::AttachToPolygons( SDTSTransfer * poTransfer,
             if( iPolyLayer != iTargetPolyLayer )
                 continue;
 
-            poPolyReader = (SDTSPolygonReader *)
-                poTransfer->GetLayerIndexedReader(iPolyLayer);
+            poPolyReader = reinterpret_cast<SDTSPolygonReader *>(
+                poTransfer->GetLayerIndexedReader(iPolyLayer) );
 
             if( poPolyReader == NULL )
                 return;
@@ -335,20 +333,17 @@ void SDTSLineReader::AttachToPolygons( SDTSTransfer * poTransfer,
 /* -------------------------------------------------------------------- */
         if( poLine->oLeftPoly.nRecord != -1 )
         {
-            SDTSRawPolygon      *poPoly;
-
-            poPoly = (SDTSRawPolygon *) poPolyReader->GetIndexedFeatureRef(
-                poLine->oLeftPoly.nRecord );
+          SDTSRawPolygon *poPoly = reinterpret_cast<SDTSRawPolygon *>(
+              poPolyReader->GetIndexedFeatureRef( poLine->oLeftPoly.nRecord ) );
             if( poPoly != NULL )
                 poPoly->AddEdge( poLine );
         }
-            
+
         if( poLine->oRightPoly.nRecord != -1 )
         {
-            SDTSRawPolygon      *poPoly;
-
-            poPoly = (SDTSRawPolygon *) poPolyReader->GetIndexedFeatureRef(
-                poLine->oRightPoly.nRecord );
+            SDTSRawPolygon *poPoly = reinterpret_cast<SDTSRawPolygon *>(
+                poPolyReader->GetIndexedFeatureRef(
+                    poLine->oRightPoly.nRecord ) );
 
             if( poPoly != NULL )
                 poPoly->AddEdge( poLine );
diff --git a/frmts/sdts/sdtspointreader.cpp b/frmts/sdts/sdtspointreader.cpp
index 0d5ad24..3385cf9 100644
--- a/frmts/sdts/sdtspointreader.cpp
+++ b/frmts/sdts/sdtspointreader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sdtspointreader.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: sdtspointreader.cpp 31332 2015-11-03 17:34:39Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Implementation of SDTSPointReader and SDTSRawPoint classes.
@@ -29,7 +29,7 @@
 
 #include "sdts_al.h"
 
-CPL_CVSID("$Id: sdtspointreader.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: sdtspointreader.cpp 31332 2015-11-03 17:34:39Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -44,8 +44,10 @@ CPL_CVSID("$Id: sdtspointreader.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
 /*                            SDTSRawPoint()                            */
 /************************************************************************/
 
-SDTSRawPoint::SDTSRawPoint()
-
+SDTSRawPoint::SDTSRawPoint() :
+    dfX(0.0),
+    dfY(0.0),
+    dfZ(0.0)
 {
     nAttributes = 0;
 }
@@ -54,10 +56,7 @@ SDTSRawPoint::SDTSRawPoint()
 /*                           ~STDSRawPoint()                            */
 /************************************************************************/
 
-SDTSRawPoint::~SDTSRawPoint()
-
-{
-}
+SDTSRawPoint::~SDTSRawPoint() {}
 
 /************************************************************************/
 /*                                Read()                                */
@@ -77,10 +76,10 @@ int SDTSRawPoint::Read( SDTS_IREF * poIREF, DDFRecord * poRecord )
     for( int iField = 0; iField < poRecord->GetFieldCount(); iField++ )
     {
         DDFField        *poField = poRecord->GetField( iField );
-        const char      *pszFieldName;
 
         CPLAssert( poField != NULL );
-        pszFieldName = poField->GetFieldDefn()->GetName();
+
+        const char *pszFieldName = poField->GetFieldDefn()->GetName();
 
         if( EQUAL(pszFieldName,"PNTS") )
             oModId.Set( poField );
@@ -108,16 +107,14 @@ int SDTSRawPoint::Read( SDTS_IREF * poIREF, DDFRecord * poRecord )
 void SDTSRawPoint::Dump( FILE * fp )
 
 {
-    int         i;
-    
     fprintf( fp, "SDTSRawPoint %s: ", oModId.GetName() );
 
     if( oAreaId.nRecord != -1 )
         fprintf( fp, " AreaId=%s", oAreaId.GetName() );
 
-    for( i = 0; i < nAttributes; i++ )
+    for( int i = 0; i < nAttributes; i++ )
         fprintf( fp, "  ATID[%d]=%s", i, paoATID[i].GetName() );
-    
+
     fprintf( fp, "  Vertex = (%.2f,%.2f,%.2f)\n", dfX, dfY, dfZ );
 }
 
@@ -134,19 +131,15 @@ void SDTSRawPoint::Dump( FILE * fp )
 /*                           SDTSPointReader()                          */
 /************************************************************************/
 
-SDTSPointReader::SDTSPointReader( SDTS_IREF * poIREFIn )
-
-{
-    poIREF = poIREFIn;
-}
+SDTSPointReader::SDTSPointReader( SDTS_IREF * poIREFIn ) :
+    poIREF(poIREFIn)
+{}
 
 /************************************************************************/
 /*                             ~SDTSLineReader()                        */
 /************************************************************************/
 
-SDTSPointReader::~SDTSPointReader()
-{
-}
+SDTSPointReader::~SDTSPointReader() {}
 
 /************************************************************************/
 /*                               Close()                                */
@@ -180,32 +173,27 @@ int SDTSPointReader::Open( const char * pszFilename )
 SDTSRawPoint * SDTSPointReader::GetNextPoint()
 
 {
-    DDFRecord   *poRecord;
-    
 /* -------------------------------------------------------------------- */
 /*      Read a record.                                                  */
 /* -------------------------------------------------------------------- */
     if( oDDFModule.GetFP() == NULL )
         return NULL;
 
-    poRecord = oDDFModule.ReadRecord();
+    DDFRecord *poRecord = oDDFModule.ReadRecord();
 
     if( poRecord == NULL )
         return NULL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Transform into a point feature.                                 */
 /* -------------------------------------------------------------------- */
-    SDTSRawPoint        *poRawPoint = new SDTSRawPoint();
+    SDTSRawPoint *poRawPoint = new SDTSRawPoint();
 
     if( poRawPoint->Read( poIREF, poRecord ) )
     {
         return( poRawPoint );
     }
-    else
-    {
-        delete poRawPoint;
-        return NULL;
-    }
-}
 
+    delete poRawPoint;
+    return NULL;
+}
diff --git a/frmts/sdts/sdtspolygonreader.cpp b/frmts/sdts/sdtspolygonreader.cpp
index ee6f56f..ae3a853 100644
--- a/frmts/sdts/sdtspolygonreader.cpp
+++ b/frmts/sdts/sdtspolygonreader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sdtspolygonreader.cpp 25138 2012-10-15 23:12:05Z rouault $
+ * $Id: sdtspolygonreader.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Implementation of SDTSPolygonReader and SDTSRawPolygon classes.
@@ -29,7 +29,9 @@
 
 #include "sdts_al.h"
 
-CPL_CVSID("$Id: sdtspolygonreader.cpp 25138 2012-10-15 23:12:05Z rouault $");
+#include <cmath>
+
+CPL_CVSID("$Id: sdtspolygonreader.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -44,15 +46,17 @@ CPL_CVSID("$Id: sdtspolygonreader.cpp 25138 2012-10-15 23:12:05Z rouault $");
 /*                           SDTSRawPolygon()                           */
 /************************************************************************/
 
-SDTSRawPolygon::SDTSRawPolygon()
-
+SDTSRawPolygon::SDTSRawPolygon() :
+    nEdges(0),
+    papoEdges(NULL),
+    nRings(0),
+    nVertices(0),
+    panRingStart(NULL),
+    padfX(NULL),
+    padfY(NULL),
+    padfZ(NULL)
 {
     nAttributes = 0;
-    nEdges = nRings = nVertices = 0;
-    papoEdges = NULL;
-    
-    panRingStart = NULL;
-    padfX = padfY = padfZ = NULL;
 }
 
 /************************************************************************/
@@ -87,10 +91,9 @@ int SDTSRawPolygon::Read( DDFRecord * poRecord )
     for( int iField = 0; iField < poRecord->GetFieldCount(); iField++ )
     {
         DDFField        *poField = poRecord->GetField( iField );
-        const char      *pszFieldName;
-
         CPLAssert( poField != NULL );
-        pszFieldName = poField->GetFieldDefn()->GetName();
+
+        const char *pszFieldName = poField->GetFieldDefn()->GetName();
 
         if( EQUAL(pszFieldName,"POLY") )
         {
@@ -114,8 +117,9 @@ void SDTSRawPolygon::AddEdge( SDTSRawLine * poNewLine )
 
 {
     nEdges++;
-    
-    papoEdges = (SDTSRawLine **) CPLRealloc(papoEdges, sizeof(void*)*nEdges );
+
+    papoEdges = reinterpret_cast<SDTSRawLine **>(
+        CPLRealloc(papoEdges, sizeof(void*)*nEdges ) );
     papoEdges[nEdges-1] = poNewLine;
 }
 
@@ -130,7 +134,9 @@ void SDTSRawPolygon::AddEdgeToRing( int nVertToAdd,
                                     int bReverse, int bDropVertex )
 
 {
-    int         iStart=0, iEnd=nVertToAdd-1, iStep=1;
+    int iStart = 0;
+    int iEnd = nVertToAdd-1;
+    int iStep = 1;
 
     if( bDropVertex && bReverse )
     {
@@ -209,7 +215,7 @@ void SDTSRawPolygon::AddEdgeToRing( int nVertToAdd,
  * direction of rings.
  *
  * @return TRUE if all rings assembled without problems or FALSE if a problem
- * occured.  If a problem occurs rings are still formed from all lines, but
+ * occurred.  If a problem occurs rings are still formed from all lines, but
  * some of the rings will not be closed, and rings will have no particular
  * order or direction.
  */
@@ -217,9 +223,6 @@ void SDTSRawPolygon::AddEdgeToRing( int nVertToAdd,
 int SDTSRawPolygon::AssembleRings()
 
 {
-    int         iEdge;
-    int         bSuccess = TRUE;
-    
     if( nRings > 0 )
         return TRUE;
 
@@ -229,17 +232,17 @@ int SDTSRawPolygon::AssembleRings()
 /* -------------------------------------------------------------------- */
 /*      Allocate ring arrays.                                           */
 /* -------------------------------------------------------------------- */
-    panRingStart = (int *) CPLMalloc(sizeof(int) * nEdges);
+    panRingStart = reinterpret_cast<int *>( CPLMalloc( sizeof(int) * nEdges ) );
 
     nVertices = 0;
-    for( iEdge = 0; iEdge < nEdges; iEdge++ )
+    for( int iEdge = 0; iEdge < nEdges; iEdge++ )
     {
         nVertices += papoEdges[iEdge]->nVertices;
     }
 
-    padfX = (double *) CPLMalloc(sizeof(double) * nVertices);
-    padfY = (double *) CPLMalloc(sizeof(double) * nVertices);
-    padfZ = (double *) CPLMalloc(sizeof(double) * nVertices);
+    padfX = reinterpret_cast<double *>( CPLMalloc( sizeof(double) * nVertices ) );
+    padfY = reinterpret_cast<double *>( CPLMalloc( sizeof(double) * nVertices ) );
+    padfZ = reinterpret_cast<double *>( CPLMalloc( sizeof(double) * nVertices ) );
 
     nVertices = 0;
 
@@ -247,25 +250,25 @@ int SDTSRawPolygon::AssembleRings()
 /*      Setup array of line markers indicating if they have been        */
 /*      added to a ring yet.                                            */
 /* -------------------------------------------------------------------- */
-    int *panEdgeConsumed, nRemainingEdges = nEdges;
+    int nRemainingEdges = nEdges;
 
-    panEdgeConsumed = (int *) CPLCalloc(sizeof(int),nEdges);
+    int *panEdgeConsumed = reinterpret_cast<int *>(
+        CPLCalloc( sizeof(int), nEdges ) );
 
 /* ==================================================================== */
 /*      Loop generating rings.                                          */
 /* ==================================================================== */
+    bool bSuccess = true;
+
     while( nRemainingEdges > 0 )
     {
-        int             nStartNode, nLinkNode;
-        
 /* -------------------------------------------------------------------- */
 /*      Find the first unconsumed edge.                                 */
 /* -------------------------------------------------------------------- */
-        SDTSRawLine     *poEdge;
-        
-        for( iEdge = 0; panEdgeConsumed[iEdge]; iEdge++ ) {}
+        int iEdge = 0;
+        for( ; panEdgeConsumed[iEdge]; iEdge++ ) {}
 
-        poEdge = papoEdges[iEdge];
+        SDTSRawLine *poEdge = papoEdges[iEdge];
 
 /* -------------------------------------------------------------------- */
 /*      Start a new ring, copying in the current line directly          */
@@ -278,22 +281,22 @@ int SDTSRawPolygon::AssembleRings()
 
         panEdgeConsumed[iEdge] = TRUE;
         nRemainingEdges--;
-        
-        nStartNode = poEdge->oStartNode.nRecord;
-        nLinkNode = poEdge->oEndNode.nRecord;
+
+        const int nStartNode = poEdge->oStartNode.nRecord;
+        int nLinkNode = poEdge->oEndNode.nRecord;
 
 /* ==================================================================== */
 /*      Loop adding edges to this ring until we make a whole pass       */
 /*      within finding anything to add.                                 */
 /* ==================================================================== */
-        int             bWorkDone = TRUE;
+        bool bWorkDone = true;
 
         while( nLinkNode != nStartNode
                && nRemainingEdges > 0
                && bWorkDone )
         {
-            bWorkDone = FALSE;
-            
+            bWorkDone = false;
+
             for( iEdge = 0; iEdge < nEdges; iEdge++ )
             {
                 if( panEdgeConsumed[iEdge] )
@@ -318,10 +321,10 @@ int SDTSRawPolygon::AssembleRings()
                 {
                     continue;
                 }
-                    
+
                 panEdgeConsumed[iEdge] = TRUE;
                 nRemainingEdges--;
-                bWorkDone = TRUE;
+                bWorkDone = true;
             }
         }
 
@@ -329,8 +332,7 @@ int SDTSRawPolygon::AssembleRings()
 /*      Did we fail to complete the ring?                               */
 /* -------------------------------------------------------------------- */
         if( nLinkNode != nStartNode )
-            bSuccess = FALSE;
-        
+            bSuccess = false;
     } /* next ring */
 
     CPLFree( panEdgeConsumed );
@@ -346,22 +348,23 @@ int SDTSRawPolygon::AssembleRings()
 /*      Gems II_, James Arvo, 1991, Academic Press, Inc., section 1.1,  */
 /*      "The Area of a Simple Polygon", Jon Rokne, pp. 5-6.             */
 /* ==================================================================== */
-    double      *padfRingArea, dfMaxArea = 0.0;
-    int         iRing, iBiggestRing = -1;
+    double dfMaxArea = 0.0;
+    int iBiggestRing = -1;
 
-    padfRingArea = (double *) CPLCalloc(sizeof(double),nRings);
+    double *padfRingArea
+        = reinterpret_cast<double *>( CPLCalloc( sizeof(double), nRings ) );
 
-    for( iRing = 0; iRing < nRings; iRing++ )
+    for( int iRing = 0; iRing < nRings; iRing++ )
     {
-        double  dfSum1 = 0.0, dfSum2 = 0.0;
-        int     i, nRingVertices;
-
+        int nRingVertices;
         if( iRing == nRings - 1 )
             nRingVertices = nVertices - panRingStart[iRing];
         else
             nRingVertices = panRingStart[iRing+1] - panRingStart[iRing];
-        
-        for( i = panRingStart[iRing];
+
+        double dfSum1 = 0.0;
+        double dfSum2 = 0.0;
+        for( int i = panRingStart[iRing];
              i < panRingStart[iRing] + nRingVertices - 1;
              i++)
         {
@@ -371,9 +374,9 @@ int SDTSRawPolygon::AssembleRings()
 
         padfRingArea[iRing] = (dfSum1 - dfSum2) / 2;
 
-        if( ABS(padfRingArea[iRing]) > dfMaxArea )
+        if( std::abs(padfRingArea[iRing]) > dfMaxArea )
         {
-            dfMaxArea = ABS(padfRingArea[iRing]);
+            dfMaxArea = std::abs(padfRingArea[iRing]);
             iBiggestRing = iRing;
         }
     }
@@ -395,15 +398,15 @@ int SDTSRawPolygon::AssembleRings()
     int         *panRawRingStart = panRingStart;
     int         nRawVertices = nVertices;
     int         nRawRings = nRings;
-    int         nRingVertices;
 
-    padfX = (double *) CPLMalloc(sizeof(double) * nVertices);
-    padfY = (double *) CPLMalloc(sizeof(double) * nVertices);
-    padfZ = (double *) CPLMalloc(sizeof(double) * nVertices);
-    panRingStart = (int *) CPLMalloc(sizeof(int) * nRawRings);
+    padfX = reinterpret_cast<double *>( CPLMalloc( sizeof(double) * nVertices ) );
+    padfY = reinterpret_cast<double *>( CPLMalloc( sizeof(double) * nVertices ) );
+    padfZ = reinterpret_cast<double *>( CPLMalloc( sizeof(double) * nVertices ) );
+    panRingStart = reinterpret_cast<int *>( CPLMalloc(sizeof(int) * nRawRings ) );
     nVertices = 0;
     nRings = 0;
 
+    int nRingVertices;
     if( iBiggestRing == nRawRings - 1 )
         nRingVertices = nRawVertices - panRawRingStart[iBiggestRing];
     else
@@ -421,11 +424,11 @@ int SDTSRawPolygon::AssembleRings()
 /*      Add the rest of the rings, which must be holes, in clockwise    */
 /*      order.                                                          */
 /* ==================================================================== */
-    for( iRing = 0; iRing < nRawRings; iRing++ )
+    for( int iRing = 0; iRing < nRawRings; iRing++ )
     {
         if( iRing == iBiggestRing )
             continue;
-        
+
         if( iRing == nRawRings - 1 )
             nRingVertices = nRawVertices - panRawRingStart[iRing];
         else
@@ -438,7 +441,7 @@ int SDTSRawPolygon::AssembleRings()
                        padfZRaw + panRawRingStart[iRing],
                        padfRingArea[iRing] > 0.0, FALSE );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Cleanup                                                         */
 /* -------------------------------------------------------------------- */
@@ -462,11 +465,9 @@ int SDTSRawPolygon::AssembleRings()
 void SDTSRawPolygon::Dump( FILE * fp )
 
 {
-    int         i;
-    
     fprintf( fp, "SDTSRawPolygon %s: ", oModId.GetName() );
 
-    for( i = 0; i < nAttributes; i++ )
+    for( int i = 0; i < nAttributes; i++ )
         fprintf( fp, "  ATID[%d]=%s", i, paoATID[i].GetName() );
 
     fprintf( fp, "\n" );
@@ -484,19 +485,15 @@ void SDTSRawPolygon::Dump( FILE * fp )
 /*                           SDTSPolygonReader()                          */
 /************************************************************************/
 
-SDTSPolygonReader::SDTSPolygonReader()
-
-{
-    bRingsAssembled = FALSE;
-}
+SDTSPolygonReader::SDTSPolygonReader() :
+    bRingsAssembled(FALSE)
+{}
 
 /************************************************************************/
 /*                             ~SDTSPolygonReader()                     */
 /************************************************************************/
 
-SDTSPolygonReader::~SDTSPolygonReader()
-{
-}
+SDTSPolygonReader::~SDTSPolygonReader() {}
 
 /************************************************************************/
 /*                               Close()                                */
@@ -530,33 +527,29 @@ int SDTSPolygonReader::Open( const char * pszFilename )
 SDTSRawPolygon * SDTSPolygonReader::GetNextPolygon()
 
 {
-    DDFRecord   *poRecord;
-    
 /* -------------------------------------------------------------------- */
 /*      Read a record.                                                  */
 /* -------------------------------------------------------------------- */
     if( oDDFModule.GetFP() == NULL )
         return NULL;
 
-    poRecord = oDDFModule.ReadRecord();
+    DDFRecord *poRecord = oDDFModule.ReadRecord();
 
     if( poRecord == NULL )
         return NULL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Transform into a Polygon feature.                                 */
 /* -------------------------------------------------------------------- */
-    SDTSRawPolygon      *poRawPolygon = new SDTSRawPolygon();
+    SDTSRawPolygon *poRawPolygon = new SDTSRawPolygon();
 
     if( poRawPolygon->Read( poRecord ) )
     {
         return( poRawPolygon );
     }
-    else
-    {
-        delete poRawPolygon;
-        return NULL;
-    }
+
+    delete poRawPolygon;
+    return NULL;
 }
 
 /************************************************************************/
@@ -587,7 +580,7 @@ SDTSRawPolygon * SDTSPolygonReader::GetNextPolygon()
  * lines for other layers.
  */
 
-void SDTSPolygonReader::AssembleRings( SDTSTransfer * poTransfer, 
+void SDTSPolygonReader::AssembleRings( SDTSTransfer * poTransfer,
                                        int iPolyLayer )
 
 {
@@ -595,7 +588,7 @@ void SDTSPolygonReader::AssembleRings( SDTSTransfer * poTransfer,
         return;
 
     bRingsAssembled = TRUE;
-    
+
 /* -------------------------------------------------------------------- */
 /*      To write polygons we need to build them from their related      */
 /*      arcs.  We don't know off hand which arc (line) layers           */
@@ -606,13 +599,11 @@ void SDTSPolygonReader::AssembleRings( SDTSTransfer * poTransfer,
          iLineLayer < poTransfer->GetLayerCount();
          iLineLayer++ )
     {
-        SDTSLineReader  *poLineReader;
-        
         if( poTransfer->GetLayerType(iLineLayer) != SLTLine )
             continue;
 
-        poLineReader = (SDTSLineReader *)
-            poTransfer->GetLayerIndexedReader( iLineLayer );
+        SDTSLineReader *poLineReader = reinterpret_cast<SDTSLineReader *>(
+            poTransfer->GetLayerIndexedReader( iLineLayer ) );
         if( poLineReader == NULL )
             continue;
 
@@ -624,15 +615,16 @@ void SDTSPolygonReader::AssembleRings( SDTSTransfer * poTransfer,
 /*      Scan all polygons indexed on this reader, and assemble their    */
 /*      rings.                                                          */
 /* -------------------------------------------------------------------- */
-    SDTSFeature *poFeature;
-    
     Rewind();
+
+    SDTSFeature *poFeature;
     while( (poFeature = GetNextFeature()) != NULL )
     {
-        SDTSRawPolygon  *poPoly = (SDTSRawPolygon *) poFeature;
+        SDTSRawPolygon  *poPoly
+            = reinterpret_cast<SDTSRawPolygon *>( poFeature );
 
         poPoly->AssembleRings();
     }
-    
+
     Rewind();
 }
diff --git a/frmts/sdts/sdtsrasterreader.cpp b/frmts/sdts/sdtsrasterreader.cpp
index 3d514b4..cbbebd3 100644
--- a/frmts/sdts/sdtsrasterreader.cpp
+++ b/frmts/sdts/sdtsrasterreader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sdtsrasterreader.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: sdtsrasterreader.cpp 31332 2015-11-03 17:34:39Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Implementation of SDTSRasterReader class.
@@ -30,22 +30,22 @@
 
 #include "sdts_al.h"
 
-CPL_CVSID("$Id: sdtsrasterreader.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+#include <algorithm>
+
+CPL_CVSID("$Id: sdtsrasterreader.cpp 31332 2015-11-03 17:34:39Z goatbar $");
 
 /************************************************************************/
 /*                          SDTSRasterReader()                          */
 /************************************************************************/
 
-SDTSRasterReader::SDTSRasterReader()
-
+SDTSRasterReader::SDTSRasterReader() :
+    nXSize(0),
+    nYSize(0),
+    nXBlockSize(0),
+    nYBlockSize(0),
+    nXStart(0),
+    nYStart(0)
 {
-    nXSize = 0;
-    nYSize = 0;
-    nXBlockSize = 0;
-    nYBlockSize = 0;
-    nXStart = 0;
-    nYStart = 0;
-    
     strcpy( szINTR, "CE" );
 }
 
@@ -53,9 +53,7 @@ SDTSRasterReader::SDTSRasterReader()
 /*                             ~SDTSRasterReader()                     */
 /************************************************************************/
 
-SDTSRasterReader::~SDTSRasterReader()
-{
-}
+SDTSRasterReader::~SDTSRasterReader() {}
 
 /************************************************************************/
 /*                               Close()                                */
@@ -80,12 +78,10 @@ int SDTSRasterReader::Open( SDTS_CATD * poCATD, SDTS_IREF * poIREF,
 {
     strncpy( szModule, pszModule, sizeof(szModule) );
     szModule[sizeof(szModule) - 1] = '\0';
-    
+
 /* ==================================================================== */
 /*      Search the LDEF module for the requested cell module.           */
 /* ==================================================================== */
-    DDFModule   oLDEF;
-    DDFRecord   *poRecord;
 
 /* -------------------------------------------------------------------- */
 /*      Open the LDEF module, and report failure if it is missing.      */
@@ -97,13 +93,15 @@ int SDTSRasterReader::Open( SDTS_CATD * poCATD, SDTS_IREF * poIREF,
                   "can't treat as raster.\n" );
         return FALSE;
     }
-    
+
+    DDFModule oLDEF;
     if( !oLDEF.Open( poCATD->GetModuleFilePath("LDEF") ) )
         return FALSE;
 
 /* -------------------------------------------------------------------- */
 /*      Read each record, till we find what we want.                    */
 /* -------------------------------------------------------------------- */
+    DDFRecord *poRecord;
     while( (poRecord = oLDEF.ReadRecord() ) != NULL )
     {
         const char* pszCandidateModule = poRecord->GetStringSubfield("LDEF",0,"CMNM",0);
@@ -123,7 +121,7 @@ int SDTSRasterReader::Open( SDTS_CATD * poCATD, SDTS_IREF * poIREF,
                   pszModule );
         return FALSE;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Extract raster dimensions, and origin offset (0/1).             */
 /* -------------------------------------------------------------------- */
@@ -146,7 +144,7 @@ int SDTSRasterReader::Open( SDTS_CATD * poCATD, SDTS_IREF * poIREF,
     strcpy( szINTR, pszINTR );
     if( EQUAL(szINTR,"") )
         strcpy( szINTR, "CE" );
-    
+
     if( !EQUAL(szINTR,"CE") && !EQUAL(szINTR,"TL") )
     {
         CPLError( CE_Warning, CPLE_AppDefined,
@@ -160,16 +158,13 @@ int SDTSRasterReader::Open( SDTS_CATD * poCATD, SDTS_IREF * poIREF,
 /*      Record the LDEF record number we used so we can find the        */
 /*      corresponding RSDF record.                                      */
 /* -------------------------------------------------------------------- */
-    int         nLDEF_RCID;
+    int nLDEF_RCID = poRecord->GetIntSubfield( "LDEF", 0, "RCID", 0 );
 
-    nLDEF_RCID = poRecord->GetIntSubfield( "LDEF", 0, "RCID", 0 );
-    
     oLDEF.Close();
 
 /* ==================================================================== */
 /*      Search the RSDF module for the requested cell module.           */
 /* ==================================================================== */
-    DDFModule   oRSDF;
 
 /* -------------------------------------------------------------------- */
 /*      Open the RSDF module, and report failure if it is missing.      */
@@ -181,7 +176,8 @@ int SDTSRasterReader::Open( SDTS_CATD * poCATD, SDTS_IREF * poIREF,
                   "can't treat as raster.\n" );
         return FALSE;
     }
-    
+
+    DDFModule oRSDF;
     if( !oRSDF.Open( poCATD->GetModuleFilePath("RSDF") ) )
         return FALSE;
 
@@ -201,19 +197,19 @@ int SDTSRasterReader::Open( SDTS_CATD * poCATD, SDTS_IREF * poIREF,
                   nLDEF_RCID );
         return FALSE;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Establish the raster pixel/line to georef transformation.       */
 /* -------------------------------------------------------------------- */
-    double      dfZ;
-        
+
     if( poRecord->FindField( "SADR" ) == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Can't find SADR field in RSDF record.\n" );
         return FALSE;
     }
-    
+
+    double dfZ;
     poIREF->GetSADR( poRecord->FindField( "SADR" ), 1,
                      adfTransform + 0, adfTransform + 3, &dfZ );
 
@@ -235,20 +231,20 @@ int SDTSRasterReader::Open( SDTS_CATD * poCATD, SDTS_IREF * poIREF,
 /* -------------------------------------------------------------------- */
 /*      Verify some other assumptions.                                  */
 /* -------------------------------------------------------------------- */
-    const char  *pszString;
-    
-    pszString = poRecord->GetStringSubfield( "RSDF", 0, "OBRP", 0); 
-    if( pszString == NULL ) pszString = "";
-    if( !EQUAL(pszString,"G2") )
+    const char *pszString = poRecord->GetStringSubfield( "RSDF", 0, "OBRP", 0);
+    if( pszString == NULL )
+        pszString = "";
+    if( !EQUAL(pszString, "G2") )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "OBRP value of `%s' not expected 2D raster code (G2).\n",
                   pszString );
         return FALSE;
     }
-    
-    pszString = poRecord->GetStringSubfield( "RSDF", 0, "SCOR", 0); 
-    if( pszString == NULL ) pszString = "";
+
+    pszString = poRecord->GetStringSubfield( "RSDF", 0, "SCOR", 0);
+    if( pszString == NULL )
+        pszString = "";
     if( !EQUAL(pszString,"TL") )
     {
         CPLError( CE_Warning, CPLE_AppDefined,
@@ -258,7 +254,7 @@ int SDTSRasterReader::Open( SDTS_CATD * poCATD, SDTS_IREF * poIREF,
     }
 
     oRSDF.Close();
-    
+
 /* -------------------------------------------------------------------- */
 /*      For now we will assume that the block size is one scanline.     */
 /*      We will blow a gasket later while reading the cell file if      */
@@ -273,7 +269,6 @@ int SDTSRasterReader::Open( SDTS_CATD * poCATD, SDTS_IREF * poIREF,
 /*      Fetch the data type used for the raster, and the units from     */
 /*      the data dictionary/schema record (DDSH).                       */
 /* ==================================================================== */
-    DDFModule   oDDSH;
 
 /* -------------------------------------------------------------------- */
 /*      Open the DDSH module, and report failure if it is missing.      */
@@ -285,7 +280,8 @@ int SDTSRasterReader::Open( SDTS_CATD * poCATD, SDTS_IREF * poIREF,
                   "can't treat as raster.\n" );
         return FALSE;
     }
-    
+
+    DDFModule oDDSH;
     if( !oDDSH.Open( poCATD->GetModuleFilePath("DDSH") ) )
         return FALSE;
 
@@ -329,7 +325,7 @@ int SDTSRasterReader::Open( SDTS_CATD * poCATD, SDTS_IREF * poIREF,
         strcpy( szLabel, poRecord->GetStringSubfield("DDSH",0,"ATLB",0) );
     else
         strcpy( szLabel, "" );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Open the cell file.                                             */
 /* -------------------------------------------------------------------- */
@@ -367,10 +363,6 @@ int SDTSRasterReader::GetBlock( CPL_UNUSED int nXOffset,
                                 int nYOffset,
                                 void * pData )
 {
-    DDFRecord   *poRecord = NULL;
-    int         nBytesPerValue;
-    int         iTry;
-
     CPLAssert( nXOffset == 0 );
 
 /* -------------------------------------------------------------------- */
@@ -378,12 +370,15 @@ int SDTSRasterReader::GetBlock( CPL_UNUSED int nXOffset,
 /* -------------------------------------------------------------------- */
     CPLAssert( EQUAL(szFMT,"BI16") || EQUAL(szFMT,"BFP32") );
 
+    int nBytesPerValue;
     if( EQUAL(szFMT,"BI16") )
         nBytesPerValue = 2;
     else
         nBytesPerValue = 4;
 
-    for(iTry=0;iTry<2;iTry++)
+    DDFRecord *poRecord = NULL;
+
+    for( int iTry = 0; iTry < 2; iTry++ )
     {
     /* -------------------------------------------------------------------- */
     /*      Read through till we find the desired record.                   */
@@ -426,9 +421,7 @@ int SDTSRasterReader::GetBlock( CPL_UNUSED int nXOffset,
 /*      Validate the records size.  Does it represent exactly one       */
 /*      scanline?                                                       */
 /* -------------------------------------------------------------------- */
-    DDFField    *poCVLS;
-
-    poCVLS = poRecord->FindField( "CVLS" );
+    DDFField *poCVLS = poRecord->FindField( "CVLS" );
     if( poCVLS == NULL )
         return FALSE;
 
@@ -465,18 +458,19 @@ int SDTSRasterReader::GetBlock( CPL_UNUSED int nXOffset,
     {
         for( int i = 0; i < nXSize; i++ )
         {
-            ((GInt16 *) pData)[i] = CPL_MSBWORD16(((GInt16 *) pData)[i]);
+            reinterpret_cast<GInt16 *>( pData )[i] = CPL_MSBWORD16(
+                reinterpret_cast<GInt16 *>( pData )[i] );
         }
     }
     else
     {
         for( int i = 0; i < nXSize; i++ )
         {
-            CPL_MSBPTR32( ((GByte *)pData) + i*4 );
+            CPL_MSBPTR32( reinterpret_cast<GByte *>( pData ) + i*4 );
         }
     }
 #endif
-    
+
     return TRUE;
 }
 
@@ -533,8 +527,8 @@ int SDTSRasterReader::GetRasterType()
 {
     if( EQUAL(szFMT,"BFP32") )
         return 6;
-    else
-        return 1;
+
+    return 1;
 }
 
 /************************************************************************/
@@ -558,13 +552,11 @@ int SDTSRasterReader::GetMinMax( double * pdfMin, double * pdfMax,
                                  double dfNoData )
 
 {
-    void	*pBuffer;
-    int		bFirst = TRUE;
-    int		b32Bit = GetRasterType() == SDTS_RT_FLOAT32;
-
     CPLAssert( GetBlockXSize() == GetXSize() && GetBlockYSize() == 1 );
-    
-    pBuffer = CPLMalloc(sizeof(float) * GetXSize());
+
+    bool bFirst = true;
+    const bool b32Bit = GetRasterType() == SDTS_RT_FLOAT32;
+    void *pBuffer = CPLMalloc(sizeof(float) * GetXSize());
 
     for( int iLine = 0; iLine < GetYSize(); iLine++ )
     {
@@ -576,30 +568,31 @@ int SDTSRasterReader::GetMinMax( double * pdfMin, double * pdfMax,
 
         for( int iPixel = 0; iPixel < GetXSize(); iPixel++ )
         {
-            double	dfValue;
-            
+            double dfValue;
+
             if( b32Bit )
-                dfValue = ((float *) pBuffer)[iPixel];
+                dfValue = reinterpret_cast<float *>( pBuffer )[iPixel];
             else
-                dfValue = ((short *) pBuffer)[iPixel];
+                dfValue = reinterpret_cast<short *>( pBuffer )[iPixel];
 
             if( dfValue != dfNoData )
             {
                 if( bFirst )
                 {
-                    *pdfMin = *pdfMax = dfValue;
-                    bFirst = FALSE;
+                    *pdfMin = dfValue;
+                    *pdfMax = dfValue;
+                    bFirst = false;
                 }
                 else
                 {
-                    *pdfMin = MIN(*pdfMin,dfValue);
-                    *pdfMax = MAX(*pdfMax,dfValue);
+                    *pdfMin = std::min( *pdfMin, dfValue );
+                    *pdfMax = std::max( *pdfMax, dfValue );
                 }
             }
         }
     }
 
     CPLFree( pBuffer );
-    
+
     return !bFirst;
 }
diff --git a/frmts/sdts/sdtstransfer.cpp b/frmts/sdts/sdtstransfer.cpp
index 6494f5b..da66468 100644
--- a/frmts/sdts/sdtstransfer.cpp
+++ b/frmts/sdts/sdtstransfer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sdtstransfer.cpp 21298 2010-12-20 10:58:34Z rouault $
+ * $Id: sdtstransfer.cpp 31955 2015-12-02 06:07:22Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Implementation of SDTSTransfer class.
@@ -29,19 +29,19 @@
 
 #include "sdts_al.h"
 
-CPL_CVSID("$Id: sdtstransfer.cpp 21298 2010-12-20 10:58:34Z rouault $");
+#include <algorithm>
+
+CPL_CVSID("$Id: sdtstransfer.cpp 31955 2015-12-02 06:07:22Z goatbar $");
 
 /************************************************************************/
 /*                            SDTSTransfer()                            */
 /************************************************************************/
 
-SDTSTransfer::SDTSTransfer()
-
-{
-    nLayers = 0;
-    panLayerCATDEntry = NULL;
-    papoLayerReader = NULL;
-}
+SDTSTransfer::SDTSTransfer() :
+    nLayers(0),
+    panLayerCATDEntry(NULL),
+    papoLayerReader(NULL)
+{}
 
 /************************************************************************/
 /*                           ~SDTSTransfer()                            */
@@ -76,7 +76,6 @@ int SDTSTransfer::Open( const char * pszFilename )
     if( !oCATD.Read( pszFilename ) )
         return FALSE;
 
-    
 /* -------------------------------------------------------------------- */
 /*      Read the IREF file.                                             */
 /* -------------------------------------------------------------------- */
@@ -87,7 +86,7 @@ int SDTSTransfer::Open( const char * pszFilename )
                   pszFilename );
         return FALSE;
     }
-    
+
     if( !oIREF.Read( oCATD.GetModuleFilePath( "IREF" ) ) )
         return FALSE;
 
@@ -110,11 +109,10 @@ int SDTSTransfer::Open( const char * pszFilename )
 /* -------------------------------------------------------------------- */
 /*      Build an index of layer types we recognise and care about.      */
 /* -------------------------------------------------------------------- */
-    int iCATDLayer;
-
-    panLayerCATDEntry = (int *) CPLMalloc(sizeof(int) * oCATD.GetEntryCount());
+    panLayerCATDEntry = reinterpret_cast<int *>(
+        CPLMalloc( sizeof(int) * oCATD.GetEntryCount() ) );
 
-    for( iCATDLayer = 0; iCATDLayer < oCATD.GetEntryCount(); iCATDLayer++ )
+    for( int iCATDLayer = 0; iCATDLayer < oCATD.GetEntryCount(); iCATDLayer++ )
     {
         switch( oCATD.GetEntryType(iCATDLayer) )
         {
@@ -135,8 +133,8 @@ int SDTSTransfer::Open( const char * pszFilename )
 /* -------------------------------------------------------------------- */
 /*      Initialized the related indexed readers list.                   */
 /* -------------------------------------------------------------------- */
-    papoLayerReader = (SDTSIndexedReader **)
-        CPLCalloc(sizeof(SDTSIndexedReader*),oCATD.GetEntryCount());
+    papoLayerReader = reinterpret_cast<SDTSIndexedReader **>(
+        CPLCalloc( sizeof(SDTSIndexedReader*), oCATD.GetEntryCount() ) );
 
     return TRUE;
 }
@@ -188,7 +186,6 @@ void SDTSTransfer::Close()
   <li> SLTRaster: A raster layer.  SDTSTransfer::GetLayerIndexedReader()
   is not implemented.  Use SDTSTransfer::GetLayerRasterReader() instead.
   </ul>
-  
  */
 
 SDTSLayerType SDTSTransfer::GetLayerType( int iEntry )
@@ -231,8 +228,6 @@ int SDTSTransfer::GetLayerCATDEntry( int iEntry )
 SDTSLineReader *SDTSTransfer::GetLayerLineReader( int iEntry )
 
 {
-    SDTSLineReader      *poLineReader;
-    
     if( iEntry < 0
         || iEntry >= nLayers
         || oCATD.GetEntryType( panLayerCATDEntry[iEntry] ) != SLTLine )
@@ -240,19 +235,16 @@ SDTSLineReader *SDTSTransfer::GetLayerLineReader( int iEntry )
         return NULL;
     }
 
-    
-    poLineReader = new SDTSLineReader( &oIREF );
-    
+    SDTSLineReader *poLineReader = new SDTSLineReader( &oIREF );
+
     if( !poLineReader->Open(
                         oCATD.GetEntryFilePath( panLayerCATDEntry[iEntry] ) ) )
     {
         delete poLineReader;
         return NULL;
     }
-    else
-    {
-        return poLineReader;
-    }
+
+    return poLineReader;
 }
 
 /************************************************************************/
@@ -262,8 +254,6 @@ SDTSLineReader *SDTSTransfer::GetLayerLineReader( int iEntry )
 SDTSPointReader *SDTSTransfer::GetLayerPointReader( int iEntry )
 
 {
-    SDTSPointReader     *poPointReader;
-    
     if( iEntry < 0
         || iEntry >= nLayers
         || oCATD.GetEntryType( panLayerCATDEntry[iEntry] ) != SLTPoint )
@@ -271,19 +261,16 @@ SDTSPointReader *SDTSTransfer::GetLayerPointReader( int iEntry )
         return NULL;
     }
 
-    
-    poPointReader = new SDTSPointReader( &oIREF );
-    
+    SDTSPointReader *poPointReader = new SDTSPointReader( &oIREF );
+
     if( !poPointReader->Open(
                         oCATD.GetEntryFilePath( panLayerCATDEntry[iEntry] ) ) )
     {
         delete poPointReader;
         return NULL;
     }
-    else
-    {
-        return poPointReader;
-    }
+
+    return poPointReader;
 }
 
 /************************************************************************/
@@ -293,8 +280,6 @@ SDTSPointReader *SDTSTransfer::GetLayerPointReader( int iEntry )
 SDTSPolygonReader *SDTSTransfer::GetLayerPolygonReader( int iEntry )
 
 {
-    SDTSPolygonReader   *poPolyReader;
-    
     if( iEntry < 0
         || iEntry >= nLayers
         || oCATD.GetEntryType( panLayerCATDEntry[iEntry] ) != SLTPoly )
@@ -302,19 +287,16 @@ SDTSPolygonReader *SDTSTransfer::GetLayerPolygonReader( int iEntry )
         return NULL;
     }
 
-    
-    poPolyReader = new SDTSPolygonReader();
-    
+    SDTSPolygonReader *poPolyReader = new SDTSPolygonReader();
+
     if( !poPolyReader->Open(
                         oCATD.GetEntryFilePath( panLayerCATDEntry[iEntry] ) ) )
     {
         delete poPolyReader;
         return NULL;
     }
-    else
-    {
-        return poPolyReader;
-    }
+
+    return poPolyReader;
 }
 
 /************************************************************************/
@@ -324,8 +306,6 @@ SDTSPolygonReader *SDTSTransfer::GetLayerPolygonReader( int iEntry )
 SDTSAttrReader *SDTSTransfer::GetLayerAttrReader( int iEntry )
 
 {
-    SDTSAttrReader      *poAttrReader;
-    
     if( iEntry < 0
         || iEntry >= nLayers
         || oCATD.GetEntryType( panLayerCATDEntry[iEntry] ) != SLTAttr )
@@ -333,19 +313,16 @@ SDTSAttrReader *SDTSTransfer::GetLayerAttrReader( int iEntry )
         return NULL;
     }
 
-    
-    poAttrReader = new SDTSAttrReader( &oIREF );
-    
+    SDTSAttrReader *poAttrReader = new SDTSAttrReader();
+
     if( !poAttrReader->Open(
                         oCATD.GetEntryFilePath( panLayerCATDEntry[iEntry] ) ) )
     {
         delete poAttrReader;
         return NULL;
     }
-    else
-    {
-        return poAttrReader;
-    }
+
+    return poAttrReader;
 }
 
 /************************************************************************/
@@ -370,8 +347,6 @@ SDTSAttrReader *SDTSTransfer::GetLayerAttrReader( int iEntry )
 SDTSRasterReader *SDTSTransfer::GetLayerRasterReader( int iEntry )
 
 {
-    SDTSRasterReader    *poRasterReader;
-    
     if( iEntry < 0
         || iEntry >= nLayers
         || oCATD.GetEntryType( panLayerCATDEntry[iEntry] ) != SLTRaster )
@@ -379,18 +354,16 @@ SDTSRasterReader *SDTSTransfer::GetLayerRasterReader( int iEntry )
         return NULL;
     }
 
-    poRasterReader = new SDTSRasterReader();
-    
+    SDTSRasterReader *poRasterReader = new SDTSRasterReader();
+
     if( !poRasterReader->Open( &oCATD, &oIREF,
                          oCATD.GetEntryModule(panLayerCATDEntry[iEntry] ) ) )
     {
         delete poRasterReader;
         return NULL;
     }
-    else
-    {
-        return poRasterReader;
-    }
+
+    return poRasterReader;
 }
 
 /************************************************************************/
@@ -400,26 +373,21 @@ SDTSRasterReader *SDTSTransfer::GetLayerRasterReader( int iEntry )
 DDFModule *SDTSTransfer::GetLayerModuleReader( int iEntry )
 
 {
-    DDFModule   *poModuleReader;
-    
     if( iEntry < 0 || iEntry >= nLayers )
     {
         return NULL;
     }
 
-    
-    poModuleReader = new DDFModule;
-    
+    DDFModule *poModuleReader = new DDFModule;
+
     if( !poModuleReader->Open(
                         oCATD.GetEntryFilePath( panLayerCATDEntry[iEntry] ) ) )
     {
         delete poModuleReader;
         return NULL;
     }
-    else
-    {
-        return poModuleReader;
-    }
+
+    return poModuleReader;
 }
 
 /************************************************************************/
@@ -434,18 +402,17 @@ DDFModule *SDTSTransfer::GetLayerModuleReader( int iEntry )
   <ul>
   <li> The returned reader remains owned by the SDTSTransfer, and will be
   destroyed when the SDTSTransfer is destroyed.  It should not be
-  destroyed by the application. 
+  destroyed by the application.
 
   <li> If an indexed reader was already created for this layer using
   GetLayerIndexedReader(), it will be returned instead of creating a new
-  reader.  Amoung other things this means that the returned reader may not
+  reader.  Among other things this means that the returned reader may not
   be positioned to read from the beginning of the module, and may already
   have it's index filled.
 
   <li> The returned reader will be of a type appropriate to the layer.
   See SDTSTransfer::GetLayerType() to see what reader classes correspond
-  to what layer types, so it can be cast accordingly (if necessary). 
- 
+  to what layer types, so it can be cast accordingly (if necessary).
   </ul>
 
   @param iEntry the index of the layer to instantiate a reader for.  A
@@ -481,7 +448,7 @@ SDTSIndexedReader *SDTSTransfer::GetLayerIndexedReader( int iEntry )
             break;
         }
     }
-    
+
     return papoLayerReader[iEntry];
 }
 
@@ -501,9 +468,7 @@ SDTSIndexedReader *SDTSTransfer::GetLayerIndexedReader( int iEntry )
 int SDTSTransfer::FindLayer( const char * pszModule )
 
 {
-    int         iLayer;
-
-    for( iLayer = 0; iLayer < nLayers; iLayer++ )
+    for( int iLayer = 0; iLayer < nLayers; iLayer++ )
     {
         if( EQUAL(pszModule,
                   oCATD.GetEntryModule( panLayerCATDEntry[iLayer] ) ) )
@@ -528,16 +493,14 @@ SDTSFeature *SDTSTransfer::GetIndexedFeatureRef( SDTSModId *poModId,
 /*      point in the whole process ... perhaps the last found could     */
 /*      be cached or something.                                         */
 /* -------------------------------------------------------------------- */
-    int         iLayer = FindLayer( poModId->szModule );
+    const int iLayer = FindLayer( poModId->szModule );
     if( iLayer == -1 )
         return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Get the reader, and read a feature from it.                     */
 /* -------------------------------------------------------------------- */
-    SDTSIndexedReader  *poReader;
-
-    poReader = GetLayerIndexedReader( iLayer );
+    SDTSIndexedReader *poReader = GetLayerIndexedReader( iLayer );
     if( poReader == NULL )
         return NULL;
 
@@ -560,7 +523,7 @@ SDTSFeature *SDTSTransfer::GetIndexedFeatureRef( SDTSModId *poModId,
 /**
   Fetch the attribute fields given a particular module/record id.
 
-  @param poModId an attribute record identifer, normally taken from the
+  @param poModId an attribute record identifier, normally taken from the
   aoATID[] array of an SDTSIndexedFeature.
 
   @return a pointer to the DDFField containing the user attribute values as
@@ -570,9 +533,8 @@ SDTSFeature *SDTSTransfer::GetIndexedFeatureRef( SDTSModId *poModId,
 DDFField *SDTSTransfer::GetAttr( SDTSModId *poModId )
 
 {
-    SDTSAttrRecord *poAttrRecord;
-
-    poAttrRecord = (SDTSAttrRecord *) GetIndexedFeatureRef( poModId );
+    SDTSAttrRecord *poAttrRecord = reinterpret_cast<SDTSAttrRecord *>(
+        GetIndexedFeatureRef( poModId ) );
 
     if( poAttrRecord == NULL )
         return NULL;
@@ -592,70 +554,72 @@ DDFField *SDTSTransfer::GetAttr( SDTSModId *poModId )
   theory miss some lines that go outside the bounds of the point layers.
   However, this isn't common since most TVP sets contain a bounding rectangle
   whose corners will define the most extreme extents.
-  
+
   @param pdfMinX western edge of dataset
   @param pdfMinY southern edge of dataset
   @param pdfMaxX eastern edge of dataset
   @param pdfMaxY northern edge of dataset
 
-  @return TRUE if success, or FALSE on a failure. 
+  @return TRUE if success, or FALSE on a failure.
   */
 
 int SDTSTransfer::GetBounds( double *pdfMinX, double *pdfMinY,
                              double *pdfMaxX, double *pdfMaxY )
 
 {
-    int         bFirst = TRUE;
-    
+    bool bFirst = true;
+
     for( int iLayer = 0; iLayer < GetLayerCount(); iLayer++ )
     {
         if( GetLayerType( iLayer ) == SLTPoint )
         {
-            SDTSPointReader     *poLayer;
-            SDTSRawPoint    *poPoint;
-        
-            poLayer = (SDTSPointReader *) GetLayerIndexedReader( iLayer );
+
+            SDTSPointReader *poLayer = reinterpret_cast<SDTSPointReader *>(
+                GetLayerIndexedReader( iLayer ) );
             if( poLayer == NULL )
                 continue;
-            
+
             poLayer->Rewind();
-            while( (poPoint = (SDTSRawPoint*) poLayer->GetNextFeature()) != NULL )
+
+            SDTSRawPoint *poPoint;
+            while( (poPoint = reinterpret_cast<SDTSRawPoint *>(
+                      poLayer->GetNextFeature() ) ) != NULL )
             {
                 if( bFirst )
                 {
-                    *pdfMinX = *pdfMaxX = poPoint->dfX;
-                    *pdfMinY = *pdfMaxY = poPoint->dfY;
-                    bFirst = FALSE;
+                    *pdfMinX = poPoint->dfX;
+                    *pdfMaxX = poPoint->dfX;
+                    *pdfMinY = poPoint->dfY;
+                    *pdfMaxY = poPoint->dfY;
+                    bFirst = false;
                 }
                 else
                 {
-                    *pdfMinX = MIN(*pdfMinX,poPoint->dfX);
-                    *pdfMaxX = MAX(*pdfMaxX,poPoint->dfX);
-                    *pdfMinY = MIN(*pdfMinY,poPoint->dfY);
-                    *pdfMaxY = MAX(*pdfMaxY,poPoint->dfY);
+                    *pdfMinX = std::min( *pdfMinX, poPoint->dfX );
+                    *pdfMaxX = std::max( *pdfMaxX, poPoint->dfX );
+                    *pdfMinY = std::min( *pdfMinY, poPoint->dfY );
+                    *pdfMaxY = std::max( *pdfMaxY, poPoint->dfY );
                 }
-                
+
                 if( !poLayer->IsIndexed() )
                     delete poPoint;
             }
         }
-        
         else if( GetLayerType( iLayer ) == SLTRaster )
         {
-            SDTSRasterReader    *poRL;
-            double              adfGeoTransform[6];
-            double              dfMinX, dfMaxX, dfMinY, dfMaxY;
-
-            poRL = GetLayerRasterReader( iLayer );
+            SDTSRasterReader *poRL = GetLayerRasterReader( iLayer );
             if( poRL == NULL )
                 continue;
 
+            double adfGeoTransform[6];
             poRL->GetTransform( adfGeoTransform );
 
-            dfMinX = adfGeoTransform[0];
-            dfMaxY = adfGeoTransform[3];
-            dfMaxX = adfGeoTransform[0] + poRL->GetXSize()*adfGeoTransform[1];
-            dfMinY = adfGeoTransform[3] + poRL->GetYSize()*adfGeoTransform[5];
+            const double dfMinX = adfGeoTransform[0];
+            const double dfMaxY = adfGeoTransform[3];
+            const double dfMaxX = adfGeoTransform[0]
+                + poRL->GetXSize() * adfGeoTransform[1];
+            const double dfMinY = adfGeoTransform[3]
+                + poRL->GetYSize() * adfGeoTransform[5];
 
             if( bFirst )
             {
@@ -663,14 +627,14 @@ int SDTSTransfer::GetBounds( double *pdfMinX, double *pdfMinY,
                 *pdfMaxX = dfMaxX;
                 *pdfMinY = dfMinY;
                 *pdfMaxY = dfMaxY;
-                bFirst = FALSE;
+                bFirst = false;
             }
             else
             {
-                *pdfMinX = MIN(dfMinX,*pdfMinX);
-                *pdfMaxX = MAX(dfMaxX,*pdfMaxX);
-                *pdfMinY = MIN(dfMinY,*pdfMinY);
-                *pdfMaxY = MAX(dfMaxY,*pdfMaxY);
+                *pdfMinX = std::min( dfMinX, *pdfMinX );
+                *pdfMaxX = std::max( dfMaxX, *pdfMaxX );
+                *pdfMinY = std::min( dfMinY, *pdfMinY );
+                *pdfMaxY = std::max( dfMaxY, *pdfMaxY );
             }
 
             delete poRL;
@@ -679,4 +643,3 @@ int SDTSTransfer::GetBounds( double *pdfMinX, double *pdfMinY,
 
     return !bFirst;
 }
-
diff --git a/frmts/sdts/sdtsxref.cpp b/frmts/sdts/sdtsxref.cpp
index 40b9c1e..68a14d4 100644
--- a/frmts/sdts/sdtsxref.cpp
+++ b/frmts/sdts/sdtsxref.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sdtsxref.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: sdtsxref.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Implementation of SDTS_XREF class for reading XREF module.
@@ -29,19 +29,17 @@
 
 #include "sdts_al.h"
 
-CPL_CVSID("$Id: sdtsxref.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: sdtsxref.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 /************************************************************************/
 /*                             SDTS_XREF()                              */
 /************************************************************************/
 
-SDTS_XREF::SDTS_XREF()
-
-{
-    pszSystemName = CPLStrdup( "" );
-    pszDatum = CPLStrdup( "" );
-    nZone = 0;
-}
+SDTS_XREF::SDTS_XREF() :
+    pszSystemName(CPLStrdup("")),
+    pszDatum(CPLStrdup("")),
+    nZone(0)
+{}
 
 /************************************************************************/
 /*                             ~SDTS_XREF()                             */
@@ -62,19 +60,17 @@ SDTS_XREF::~SDTS_XREF()
 int SDTS_XREF::Read( const char * pszFilename )
 
 {
-    DDFModule   oXREFFile;
-    DDFRecord   *poRecord;
-
 /* -------------------------------------------------------------------- */
 /*      Open the file, and read the header.                             */
 /* -------------------------------------------------------------------- */
+    DDFModule oXREFFile;
     if( !oXREFFile.Open( pszFilename ) )
         return FALSE;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read the first record, and verify that this is an XREF record.  */
 /* -------------------------------------------------------------------- */
-    poRecord = oXREFFile.ReadRecord();
+    DDFRecord *poRecord = oXREFFile.ReadRecord();
     if( poRecord == NULL )
         return FALSE;
 
@@ -86,11 +82,11 @@ int SDTS_XREF::Read( const char * pszFilename )
 /* -------------------------------------------------------------------- */
 
     CPLFree( pszSystemName );
-    pszSystemName = 
+    pszSystemName =
         CPLStrdup( poRecord->GetStringSubfield( "XREF", 0, "RSNM", 0 ) );
 
     CPLFree( pszDatum );
-    pszDatum = 
+    pszDatum =
         CPLStrdup( poRecord->GetStringSubfield( "XREF", 0, "HDAT", 0 ) );
 
     nZone = poRecord->GetIntSubfield( "XREF", 0, "ZONE", 0 );
diff --git a/frmts/sentinel2/GNUmakefile b/frmts/sentinel2/GNUmakefile
new file mode 100644
index 0000000..c5bf2e4
--- /dev/null
+++ b/frmts/sentinel2/GNUmakefile
@@ -0,0 +1,11 @@
+
+include ../../GDALmake.opt
+
+OBJ	=	sentinel2dataset.o
+
+default:	$(OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
diff --git a/frmts/sentinel2/frmt_sentinel2.html b/frmts/sentinel2/frmt_sentinel2.html
new file mode 100644
index 0000000..aaa359a
--- /dev/null
+++ b/frmts/sentinel2/frmt_sentinel2.html
@@ -0,0 +1,458 @@
+<html>
+<head>
+<title>SENTINEL2 -- Sentinel-2 Products</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>SENTINEL2 -- Sentinel-2 Products</h1>
+
+<p>Driver for Sentinel-2 Level-1B, Level-1C and Level-2A products. (GDAL >= 2.1)</p>
+
+<p>The SENTINEL2 driver will be used if the main metadata .xml file at the
+root of a SENTINEL2 data product is opened (whose name is typically
+S2A_OPER_MTD_SAFL1C_....xml). It can also accept directly .zip files downloaded
+from the <a href="https://scihub.esa.int/">Sentinels Scientific Data Hub</a></p>
+
+<p>To be able to read the imagery, GDAL must be configured with at least one of
+the JPEG2000 capable drivers.</p>
+
+<p>
+SENTINEL-2 data are acquired on 13 spectral bands in the
+visible and near-infrared (VNIR) and Short-wavelength infrared (SWIR) spectrum,
+as show in the below table:
+</p>
+
+<p>
+<table border=1">
+<tr><th>Band name</th><th>Resolution (m)</th><th>Central wavelength (nm)</th><th>Band width (nm)</th><th>Purpose</th></tr>
+<tr><td>B01</td>      <td>60</td>            <td>443</td>                    <td>20</td>             <td>Aerosol detection</td></tr>
+<tr><td>B02</td>      <td>10</td>            <td>490</td>                    <td>65</td>             <td>Blue</td></tr>
+<tr><td>B03</td>      <td>10</td>            <td>560</td>                    <td>35</td>             <td>Green</td></tr>
+<tr><td>B04</td>      <td>10</td>            <td>665</td>                    <td>30</td>             <td>Red</td></tr>
+<tr><td>B05</td>      <td>20</td>            <td>705</td>                    <td>15</td>             <td>Vegetation classification</td></tr>
+<tr><td>B06</td>      <td>20</td>            <td>740</td>                    <td>15</td>             <td>Vegetation classification</td></tr>
+<tr><td>B07</td>      <td>20</td>            <td>783</td>                    <td>20</td>             <td>Vegetation classification</td></tr>
+<tr><td>B08</td>      <td>10</td>            <td>842</td>                    <td>115</td>            <td>Near infrared</td></tr>
+<tr><td>B08A</td>     <td>20</td>            <td>865</td>                    <td>20</td>             <td>Vegetation classification</td></tr>
+<tr><td>B09</td>      <td>60</td>            <td>945</td>                    <td>20</td>             <td>Water vapour</td></tr>
+<tr><td>B10</td>      <td>60</td>            <td>1375</td>                   <td>30</td>             <td>Cirrus</td></tr>
+<tr><td>B11</td>      <td>20</td>            <td>1610</td>                   <td>90</td>             <td>Snow / ice / cloud discrimination</td></tr>
+<tr><td>B12</td>      <td>20</td>            <td>2190</td>                   <td>180</td>            <td>Snow / ice / cloud discrimination</td></tr>
+</table>
+</p>
+
+<h2>Level-1B</h2>
+
+<p>Level-1B products are composed of several "granules" of ~ 25 km across-track x
+~ 23km along-track, in sensor geometry (i.e. non ortho-rectified).
+Each granule correspond to the imagery captured
+by one of the 12 detectors accros-track (for a total 290 km swath width).
+The imagery of each band is put in a separate JPEG2000 file.</p>
+
+<p>Level-1B products are aimed at advanced users.</p>
+
+<p>When opening the main
+metadata .xml file, the driver will typically expose N * 3 sub-datasets, where N
+is the number of granules composing the user product, and 3 corresponds to the
+number of spatial resolutions. There's one for the 4
+10m bands, one for the 6 20m bands and one for the 3 60m bands. Caution: the
+number of such subdatasets can be typically of several hundreds or more.</p>
+
+<p>It is also possible to open the metadata .xml of a given granule, in which
+case 3 subdatasets will be reported for each of the 3 spatial resolutions.</p>
+
+<p>When opening a subdataset, the georeferencing is made of 5 ground control points
+for the 4 corner of the images and the center of image.</p>
+
+<h2>Level-1C</h2>
+
+<p>Level-1C products are organized in ortho-rectified tiles of 100 km x 100 km
+in UTM WGS84 projections. The imagery of each band is put in a separate JPEG2000 file.
+</p>
+
+<p>When opening the main
+metadata .xml file, the driver will typically expose 4 sub-datasets:
+<ul>
+<li>one for the 4 10m bands,</li>
+<li>one for the 6 20m bands, </li>
+<li>one for the 3 60m bands and,</li>
+<li> one for a preview of the R,G,B bands at a 320m resolution</li>
+</ul>
+</p>
+<p>
+All tiles of same resolution and projection are mosaiced together.
+If a product spans over several UTM zones,
+they will be exposed as separate subdatasets.</p>
+
+<p>It is also possible to open the metadata .xml file of each tile, in which case
+the driver will typically expose the 4 above mentioned types of sub-datasets.</p>
+
+<h2>Level-2A</h2>
+
+<p>Similarly to Level-1C, Level-2A products are organized in ortho-rectified
+tiles of 100 km x 100 km in UTM WGS84 projections. The imagery of each band is
+put in a separate JPEG2000 file.
+The values are Bottom-Of-Atmosphere (BOA) reflectances. L2A specific bands are
+also computed:
+<ul>
+<li>AOT: Aerosol Optical Thickness map (at 550nm)</li>
+<li>CLD: Raster mask values range from 0 for high confidence clear sky to 100
+for high confidence cloudy</li>
+<li>SCL: Scene Classification. The meaning of the values is indicated in the
+Category Names of the band.</li>
+<li>SNW: Raster mask values range from 0 for high confidence NO snow/ice to 100
+for high confidence snow/ice</li>
+<li>WVP: Scene-average Water Vapour map</li>
+</ul></p>
+
+<p>When opening the main
+metadata .xml file, the driver will typically expose 4 sub-datasets:
+<ul>
+<li>one for the 4 native 10m bands, and L2A specific bands (AOT and WVP)</li>
+<li>one for the 6 native 20m bands, plus the 10m bands, except B8, resampled to
+20m, and L2A specific bands (AOT, WVP, SCL, CLD and SNW), </li>
+<li>one for the 3 native 60m bands, plus the 10m&20m bands, except B8,
+resampled to 60m, and L2A specific bands (AOT, WVP, SCL, CLD and SNW),</li>
+<li> one for a preview of the R,G,B bands at a 320m resolution</li>
+</ul>
+</p>
+<p>
+All tiles of same resolution and projection are mosaiced together.
+If a product spans over several UTM zones,
+they will be exposed as separate subdatasets.</p>
+
+<p>Note: at the time of writing (December 2015), the exact format of Level-2A
+has not been yet decided by ESA. The driver is based on the output of the
+<a href="https://github.com/umwilm/SEN2COR">sen2cor</a> v2.0.5 (Sentinel 2 Level 2A
+Prototype Processor) software that processes Level-1C datasets into Level-2A.</p>
+
+<h2>Metadata</h2>
+
+<p>Metadata of the main metadata .xml file is available in the general metadata
+domain. The whole XML file is also accessible through the xml:SENTINEL2 metadata
+domain.</p>
+
+<p>Subdatasets are based on the VRT format, so the definition of this VRT can
+be obtained by querying the xml:VRT metadata domain.</p>
+
+<h2>Performance issues for L1C and L2A</h2>
+
+<p>Due to the way Sentinel-2 products are structured, in particular because of
+the number of JPEG2000 files involved, zoom-out operations can be very slow for
+products made of many tiles. For interactive
+display, it can be useful to generate overviews (can be a slow operation by
+itself). This can be done with the gdaladdo utility on the subdataset name.
+The overview file is created next to the main metadata .xml file, with the same
+name, but prefixed with _XX_EPSG_YYYYY.tif.ovr where XX=10m,20m,60m or PREVIEW
+and YYYYY is the EPSG code.
+</p>
+<p>Trick: if the content of the zoom-out preview is not important for the use case,
+blank overviews can be created instantaneously
+by using the NONE resampling method ('-r none' as gdaladdo switch).</p>
+
+<p>When converting a subdataset to another format like tiled GeoTIFF, if using
+the JP2OpenJPEG driver, the recommended minimum value for the GDAL_CACHEMAX
+configuration option is (subdataset_width * 2048 * 2 ) / 10000000 if generating a
+INTERLEAVE=BAND GeoTIFF, or that value multiplied by the number of bands for
+the default INTERLEAVE=PIXEL configuration.
+The current versions of the OpenJPEG libraries can also consume a lot of memory
+to decode a JPEG2000 tile (up to 600MB), so you might want to specify the
+GDAL_NUM_THREADS configuration option to a reasonable number of threads if you
+are short of memory (the default value is the total number of virtual CPUs).
+</p>
+
+<h2>Open options</h2>
+
+The driver can be passed the following open options:
+<ul>
+<li><b>ALPHA</b>=YES/NO: whether to expose an alpha band. Defaults to NO. If set,
+an extra band is added after the Sentinel2 bands with an alpha channel. Its value
+are:
+<ul>
+<li>0 on areas with no tiles, or when the tile data is set to the NODATA or SATURATED
+special values,</li>
+<li>4095 on areas with valid data.</li>
+</ul>
+</ul>
+
+<p>
+Note: above open options can also be specified as configuration options, by
+prefixing the open option name with SENTINEL2_ (e.g. SENTINEL2_ALPHA).
+</p>
+
+<h2>Examples</h2>
+
+<ul>
+
+<li>Opening the main metadata file of a Sentinel2 product:
+
+<pre>
+$ gdalinfo S2A_OPER_MTD_SAFL1C_PDMC_20150818T101440_R022_V20150813T102406_20150813T102406.xml
+</pre>
+
+<pre>
+Driver: SENTINEL2/Sentinel 2
+Files: S2A_OPER_MTD_SAFL1C_PDMC_20150818T101440_R022_V20150813T102406_20150813T102406.xml
+Size is 512, 512
+Coordinate System is `'
+Metadata:
+  CLOUD_COVERAGE_ASSESSMENT=0.0
+  DATATAKE_1_DATATAKE_SENSING_START=2015-08-13T10:10:26.027Z
+  DATATAKE_1_DATATAKE_TYPE=INS-NOBS
+  DATATAKE_1_ID=GS2A_20150813T101026_000734_N01.03
+  DATATAKE_1_SENSING_ORBIT_DIRECTION=DESCENDING
+  DATATAKE_1_SENSING_ORBIT_NUMBER=22
+  DATATAKE_1_SPACECRAFT_NAME=Sentinel-2A
+  DEGRADED_ANC_DATA_PERCENTAGE=0
+  DEGRADED_MSI_DATA_PERCENTAGE=0
+  FOOTPRINT=POLYGON((11.583573986577191 46.02490454425771, 11.538730738326866 45.03757398414644, 12.93007028286133 44.99812645604949, 12.999359413660665 45.98408391203724, 11.583573986577191 46.02490454425771, 11.583573986577191 46.02490454425771))
+  FORMAT_CORRECTNESS_FLAG=PASSED
+  GENERAL_QUALITY_FLAG=PASSED
+  GENERATION_TIME=2015-08-18T10:14:40.000283Z
+  GEOMETRIC_QUALITY_FLAG=PASSED
+  PREVIEW_GEO_INFO=BrowseImageFootprint
+  PREVIEW_IMAGE_URL=https://pdmcdam2.sentinel2.eo.esa.int/s2pdgs_geoserver/geo_service.php?service=WMS&version=1.1.0&request=GetMap&layers=S2A_A000022_N0103:S2A_A000022_N0103&styles=&bbox=11.538730738326866,44.99812645604949,12.999359413660665,46.02490454425771&width=1579&height=330&srs=EPSG:4326&format=image/png&time=2015-08-13T10:24:06.0Z/2015-08-13T10:24:06.0Z
+  PROCESSING_BASELINE=01.03
+  PROCESSING_LEVEL=Level-1C
+  PRODUCT_START_TIME=2015-08-13T10:24:06.637Z
+  PRODUCT_STOP_TIME=2015-08-13T10:24:06.637Z
+  PRODUCT_TYPE=S2MSI1C
+  QUANTIFICATION_VALUE=1000
+  RADIOMETRIC_QUALITY_FLAG=PASSED
+  REFERENCE_BAND=B1
+  REFLECTANCE_CONVERSION_U=0.973195961910065
+  SENSOR_QUALITY_FLAG=PASSED
+  SPECIAL_VALUE_NODATA=1
+  SPECIAL_VALUE_SATURATED=0
+Subdatasets:
+  SUBDATASET_1_NAME=SENTINEL2_L1C:S2A_OPER_MTD_SAFL1C_PDMC_20150818T101440_R022_V20150813T102406_20150813T102406.xml:10m:EPSG_32632
+  SUBDATASET_1_DESC=Bands B2, B3, B4, B8 with 10m resolution, UTM 32N
+  SUBDATASET_2_NAME=SENTINEL2_L1C:S2A_OPER_MTD_SAFL1C_PDMC_20150818T101440_R022_V20150813T102406_20150813T102406.xml:20m:EPSG_32632
+  SUBDATASET_2_DESC=Bands B5, B6, B7, B8A, B11, B12 with 20m resolution, UTM 32N
+  SUBDATASET_3_NAME=SENTINEL2_L1C:S2A_OPER_MTD_SAFL1C_PDMC_20150818T101440_R022_V20150813T102406_20150813T102406.xml:60m:EPSG_32632
+  SUBDATASET_3_DESC=Bands B1, B9, B10 with 60m resolution, UTM 32N
+  SUBDATASET_4_NAME=SENTINEL2_L1C:S2A_OPER_MTD_SAFL1C_PDMC_20150818T101440_R022_V20150813T102406_20150813T102406.xml:PREVIEW:EPSG_32632
+  SUBDATASET_4_DESC=RGB preview, UTM 32N
+Corner Coordinates:
+Upper Left  (    0.0,    0.0)
+Lower Left  (    0.0,  512.0)
+Upper Right (  512.0,    0.0)
+Lower Right (  512.0,  512.0)
+Center      (  256.0,  256.0)
+</pre>
+</li>
+
+<li>Opening the .zip file directly:
+
+<pre>
+$ gdalinfo S2A_OPER_PRD_MSIL1C_PDMC_20150818T101440_R022_V20150813T102406_20150813T102406.zip
+</pre>
+
+<li>Opening the 10 meters resolution bands of a L1C subdataset:
+
+<pre>
+$ gdalinfo SENTINEL2_L1C:S2A_OPER_MTD_SAFL1C_PDMC_20150818T101440_R022_V20150813T102406_20150813T102406.xml:10m:EPSG_32632
+</pre>
+
+<pre>
+Driver: SENTINEL2/Sentinel 2
+Files: S2A_OPER_MTD_SAFL1C_PDMC_20150818T101440_R022_V20150813T102406_20150813T102406.xml
+       ./GRANULE/S2A_OPER_MSI_L1C_TL_MTI__20150813T201603_A000734_T32TQR_N01.03/S2A_OPER_MTD_L1C_TL_MTI__20150813T201603_A000734_T32TQR.xml
+       ./GRANULE/S2A_OPER_MSI_L1C_TL_MTI__20150813T201603_A000734_T32TQR_N01.03/IMG_DATA/S2A_OPER_MSI_L1C_TL_MTI__20150813T201603_A000734_T32TQR_B04.jp2
+       ./GRANULE/S2A_OPER_MSI_L1C_TL_MTI__20150813T201603_A000734_T32TQR_N01.03/IMG_DATA/S2A_OPER_MSI_L1C_TL_MTI__20150813T201603_A000734_T32TQR_B03.jp2
+       ./GRANULE/S2A_OPER_MSI_L1C_TL_MTI__20150813T201603_A000734_T32TQR_N01.03/IMG_DATA/S2A_OPER_MSI_L1C_TL_MTI__20150813T201603_A000734_T32TQR_B02.jp2
+       ./GRANULE/S2A_OPER_MSI_L1C_TL_MTI__20150813T201603_A000734_T32TQR_N01.03/IMG_DATA/S2A_OPER_MSI_L1C_TL_MTI__20150813T201603_A000734_T32TQR_B08.jp2
+Size is 10980, 10980
+Coordinate System is:
+PROJCS["WGS 84 / UTM zone 32N",
+    GEOGCS["WGS 84",
+        DATUM["WGS_1984",
+            SPHEROID["WGS 84",6378137,298.257223563,
+                AUTHORITY["EPSG","7030"]],
+            AUTHORITY["EPSG","6326"]],
+        PRIMEM["Greenwich",0,
+            AUTHORITY["EPSG","8901"]],
+        UNIT["degree",0.0174532925199433,
+            AUTHORITY["EPSG","9122"]],
+        AUTHORITY["EPSG","4326"]],
+    PROJECTION["Transverse_Mercator"],
+    PARAMETER["latitude_of_origin",0],
+    PARAMETER["central_meridian",9],
+    PARAMETER["scale_factor",0.9996],
+    PARAMETER["false_easting",500000],
+    PARAMETER["false_northing",0],
+    UNIT["metre",1,
+        AUTHORITY["EPSG","9001"]],
+    AXIS["Easting",EAST],
+    AXIS["Northing",NORTH],
+    AUTHORITY["EPSG","32632"]]
+Origin = (699960.000000000000000,5100060.000000000000000)
+Pixel Size = (10.000000000000000,-10.000000000000000)
+Metadata:
+[... same as above ...]
+Image Structure Metadata:
+  COMPRESSION=JPEG2000
+Corner Coordinates:
+Upper Left  (  699960.000, 5100060.000) ( 11d35' 0.87"E, 46d 1'29.66"N)
+Lower Left  (  699960.000, 4990260.000) ( 11d32'19.43"E, 45d 2'15.27"N)
+Upper Right (  809760.000, 5100060.000) ( 12d59'57.69"E, 45d59' 2.70"N)
+Lower Right (  809760.000, 4990260.000) ( 12d55'48.25"E, 44d59'53.26"N)
+Center      (  754860.000, 5045160.000) ( 12d15'46.56"E, 45d30'48.07"N)
+Band 1 Block=128x128 Type=UInt16, ColorInterp=Red
+  Description = B4, central wavelength 665 nm
+  Overviews: 5490x5490, 2745x2745, 1373x1373, 687x687, 344x344
+  Metadata:
+    BANDNAME=B4
+    BANDWIDTH=30
+    BANDWIDTH_UNIT=nm
+    SOLAR_IRRADIANCE=1512.79
+    SOLAR_IRRADIANCE_UNIT=W/m2/um
+    WAVELENGTH=665
+    WAVELENGTH_UNIT=nm
+  Image Structure Metadata:
+    NBITS=12
+Band 2 Block=128x128 Type=UInt16, ColorInterp=Green
+  Description = B3, central wavelength 560 nm
+[...]
+Band 3 Block=128x128 Type=UInt16, ColorInterp=Blue
+  Description = B2, central wavelength 490 nm
+[...]
+Band 4 Block=128x128 Type=UInt16, ColorInterp=Undefined
+  Description = B8, central wavelength 842 nm
+[...]
+</pre>
+</li>
+
+<li>Conversion of a L1C subdataset to tiled GeoTIFF
+<pre>
+$ gdal_translate SENTINEL2_L1C:S2A_OPER_MTD_SAFL1C_PDMC_20150818T101440_R022_V20150813T102406_20150813T102406.xml:10m:EPSG_32632 \
+                 10m.tif \
+                 -co TILED=YES --config GDAL_CACHEMAX 1000 --config GDAL_NUM_THREADS 2
+</pre>
+
+<li>Generating blank overviews for a L1C subdataset:
+<pre>
+$ gdaladdo -r NONE SENTINEL2_L1C:S2A_OPER_MTD_SAFL1C_PDMC_20150818T101440_R022_V20150813T102406_20150813T102406.xml:10m:EPSG_32632 4
+</pre>
+
+<li>Creating a VRT file from the subdataset (can be convenient to have the subdatasets as files):
+<pre>
+$ python -c "import sys; from osgeo import gdal; ds = gdal.Open(sys.argv[1]); open(sys.argv[2], 'wb').write(ds.GetMetadata('xml:VRT')[0].encode('utf-8'))" \
+         SENTINEL2_L1C:S2A_OPER_MTD_SAFL1C_PDMC_20150818T101440_R022_V20150813T102406_20150813T102406.xml:10m:EPSG_32632 10m.vrt
+</pre>
+
+<li>Opening the 10 meters resolution bands of a L1B subdataset:
+<pre>
+$ gdalinfo SENTINEL2_L1B:S2A_OPER_MTD_L1B_GR_SGS__20151024T023555_S20151024T011315_D02.xml:10m
+</pre>
+
+<pre>
+Driver: SENTINEL2/Sentinel 2
+Files: S2A_OPER_MTD_L1B_GR_SGS__20151024T023555_S20151024T011315_D02.xml
+       IMG_DATA/S2A_OPER_MSI_L1B_GR_SGS__20151024T023555_S20151024T011315_D02_B04.jp2
+       IMG_DATA/S2A_OPER_MSI_L1B_GR_SGS__20151024T023555_S20151024T011315_D02_B03.jp2
+       IMG_DATA/S2A_OPER_MSI_L1B_GR_SGS__20151024T023555_S20151024T011315_D02_B02.jp2
+       IMG_DATA/S2A_OPER_MSI_L1B_GR_SGS__20151024T023555_S20151024T011315_D02_B08.jp2
+Size is 2552, 2304
+Coordinate System is `'
+GCP Projection =
+GEOGCS["WGS 84",
+    DATUM["WGS_1984",
+        SPHEROID["WGS 84",6378137,298.257223563,
+            AUTHORITY["EPSG","7030"]],
+        AUTHORITY["EPSG","6326"]],
+    PRIMEM["Greenwich",0,
+        AUTHORITY["EPSG","8901"]],
+    UNIT["degree",0.0174532925199433,
+        AUTHORITY["EPSG","9122"]],
+    AUTHORITY["EPSG","4326"]]
+GCP[  0]: Id=, Info=
+          (0,0) -> (134.635194391036,-21.4282083310724,0)
+GCP[  1]: Id=, Info=
+          (0,2304) -> (134.581480136827,-21.6408640426055,0)
+GCP[  2]: Id=, Info=
+          (2552,2304) -> (134.833308274251,-21.686125031254,0)
+GCP[  3]: Id=, Info=
+          (2552,0) -> (134.886750925145,-21.4734274382519,0)
+GCP[  4]: Id=, Info=
+          (1276,1152) -> (134.734115530986,-21.5571457404287,0)
+Metadata:
+  CLOUDY_PIXEL_PERCENTAGE=0
+  DATASTRIP_ID=S2A_OPER_MSI_L1B_DS_SGS__20151024T023555_S20151024T011312_N01.04
+  DATATAKE_1_DATATAKE_SENSING_START=2015-10-24T01:13:12.027Z
+  DATATAKE_1_DATATAKE_TYPE=INS-NOBS
+  DATATAKE_1_ID=GS2A_20151024T011312_001758_N01.04
+  DATATAKE_1_SENSING_ORBIT_DIRECTION=DESCENDING
+  DATATAKE_1_SENSING_ORBIT_NUMBER=45
+  DATATAKE_1_SPACECRAFT_NAME=Sentinel-2A
+  DEGRADED_ANC_DATA_PERCENTAGE=0
+  DEGRADED_MSI_DATA_PERCENTAGE=0
+  DETECTOR_ID=02
+  DOWNLINK_PRIORITY=NOMINAL
+  FOOTPRINT=POLYGON((134.635194391036 -21.4282083310724, 134.581480136827 -21.6408640426055, 134.833308274251 -21.686125031254, 134.886750925145 -21.4734274382519, 134.635194391036 -21.4282083310724))
+  FORMAT_CORRECTNESS_FLAG=PASSED
+  GENERAL_QUALITY_FLAG=PASSED
+  GENERATION_TIME=2015-11-12T10:55:12.000947Z
+  GEOMETRIC_QUALITY_FLAG=PASSED
+  GRANULE_ID=S2A_OPER_MSI_L1B_GR_SGS__20151024T023555_S20151024T011315_D02_N01.04
+  PREVIEW_GEO_INFO=BrowseImageFootprint
+  PREVIEW_IMAGE_URL=https://pdmcdam2.sentinel2.eo.esa.int/s2pdgs_geoserver/geo_service.php?service=WMS&version=1.1.0&request=GetMap&layers=S2A_A000045_N0104:S2A_A000045_N0104&styles=&bbox=133.512786023161,-25.3930035889714,137.184847290108,-21.385906922696&width=1579&height=330&srs=EPSG:4326&format=image/png&time=2015-10-24T01:13:15.0Z/2015-10-24T01:14:13.0Z
+  PROCESSING_BASELINE=01.04
+  PROCESSING_LEVEL=Level-1B
+  PRODUCT_START_TIME=2015-10-24T01:13:15.497656Z
+  PRODUCT_STOP_TIME=2015-10-24T01:14:13.70431Z
+  PRODUCT_TYPE=S2MSI1B
+  RADIOMETRIC_QUALITY_FLAG=PASSED
+  SENSING_TIME=2015-10-24T01:13:15.497656Z
+  SENSOR_QUALITY_FLAG=PASSED
+  SPECIAL_VALUE_NODATA=1
+  SPECIAL_VALUE_SATURATED=0
+Corner Coordinates:
+Upper Left  (    0.0,    0.0)
+Lower Left  (    0.0, 2304.0)
+Upper Right ( 2552.0,    0.0)
+Lower Right ( 2552.0, 2304.0)
+Center      ( 1276.0, 1152.0)
+Band 1 Block=128x128 Type=UInt16, ColorInterp=Red
+  Description = B4, central wavelength 665 nm
+  Overviews: 1276x1152, 638x576, 319x288, 160x144
+  Metadata:
+    BANDNAME=B4
+    BANDWIDTH=30
+    BANDWIDTH_UNIT=nm
+    WAVELENGTH=665
+    WAVELENGTH_UNIT=nm
+  Image Structure Metadata:
+    NBITS=12
+Band 2 Block=128x128 Type=UInt16, ColorInterp=Green
+  Description = B3, central wavelength 560 nm
+[...]
+Band 3 Block=128x128 Type=UInt16, ColorInterp=Blue
+  Description = B2, central wavelength 490 nm
+[...]
+Band 4 Block=128x128 Type=UInt16, ColorInterp=Undefined
+  Description = B8, central wavelength 842 nm
+[...]
+</pre>
+
+</li>
+
+</ul>
+
+
+<h2>See Also:</h2>
+
+<ul>
+    <li><a href="https://scihub.esa.int/">Sentinels Scientific Data Hub</a></li>
+    <li><a href="https://sentinels.copernicus.eu/web/sentinel/user-guides/sentinel-2-msi">Sentinel 2 User guide</a></li>
+    <li><a href="https://sentinels.copernicus.eu/web/sentinel/user-guides/document-library/-/asset_publisher/xlslt4309D5h/content/sentinel-2-user-handbook">Sentinel 2 User Handbook</a></li>
+</ul>
+
+<h2>Credits</h2>
+
+This driver has been developed by <a href="http://spatialys.com">Spatialys</a> with funding from
+<a href="https://cnes.fr">Centre National d'Etudes Spatiales (CNES)</a>
+
+</body>
+</html>
diff --git a/frmts/sentinel2/makefile.vc b/frmts/sentinel2/makefile.vc
new file mode 100644
index 0000000..3daceba
--- /dev/null
+++ b/frmts/sentinel2/makefile.vc
@@ -0,0 +1,13 @@
+
+OBJ = sentinel2dataset.obj
+
+GDAL_ROOT	=	..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+default:	$(OBJ)
+	xcopy /D  /Y *.obj ..\o
+
+clean:
+	-del *.obj
+
diff --git a/frmts/sentinel2/sentinel2dataset.cpp b/frmts/sentinel2/sentinel2dataset.cpp
new file mode 100644
index 0000000..2d378da
--- /dev/null
+++ b/frmts/sentinel2/sentinel2dataset.cpp
@@ -0,0 +1,3231 @@
+/******************************************************************************
+ * $Id: sentinel2dataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
+ *
+ * Project:  GDAL
+ * Purpose:  Sentinel2 products
+ * Author:   Even Rouault, <even.rouault at spatialys.com>
+ * Funded by: Centre National d'Etudes Spatiales (CNES)
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Even Rouault, <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_minixml.h"
+#include "cpl_string.h"
+#include "gdal_pam.h"
+#include "gdal_proxy.h"
+#include "ogr_spatialref.h"
+#include "ogr_geometry.h"
+#include "gdaljp2metadata.h"
+#include "../vrt/vrtdataset.h"
+#include <set>
+#include <map>
+#include <vector>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifndef STARTS_WITH_CI
+#define STARTS_WITH_CI(a,b) EQUALN(a,b,strlen(b))
+#endif
+
+CPL_CVSID("$Id: sentinel2dataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+
+CPL_C_START
+// TODO: Leave this declaration while Sentinel2 folks use this as a
+// plugin with GDAL 1.x.
+void GDALRegister_SENTINEL2();
+CPL_C_END
+
+typedef enum
+{
+    SENTINEL2_L1B,
+    SENTINEL2_L1C,
+    SENTINEL2_L2A
+} SENTINEL2Level;
+
+typedef struct
+{
+    const char* pszBandName;
+    int         nResolution; /* meters */
+    int         nWaveLength; /* nanometers */
+    int         nBandWidth;  /* nanometers */
+    GDALColorInterp eColorInterp;
+} SENTINEL2BandDescription;
+
+static const SENTINEL2BandDescription asBandDesc[] =
+{
+    { "B1", 60, 443, 20, GCI_Undefined },
+    { "B2", 10, 490, 65, GCI_BlueBand },
+    { "B3", 10, 560, 35, GCI_GreenBand },
+    { "B4", 10, 665, 30, GCI_RedBand },
+    { "B5", 20, 705, 15, GCI_Undefined },
+    { "B6", 20, 740, 15, GCI_Undefined },
+    { "B7", 20, 783, 20, GCI_Undefined },
+    { "B8", 10, 842, 115, GCI_Undefined },
+    { "B8A", 20, 865, 20, GCI_Undefined },
+    { "B9", 60, 945, 20, GCI_Undefined },
+    { "B10", 60, 1375, 30, GCI_Undefined },
+    { "B11", 20, 1610, 90, GCI_Undefined },
+    { "B12", 20, 2190, 180, GCI_Undefined },
+};
+
+#define NB_BANDS (sizeof(asBandDesc)/sizeof(asBandDesc[0]))
+
+typedef enum
+{
+    TL_IMG_DATA,                /* Tile is located in IMG_DATA/ */
+    TL_IMG_DATA_Rxxm,           /* Tile is located in IMG_DATA/Rxxm/ */
+    TL_QI_DATA                  /* Tile is located in QI_DATA/ */
+} SENTINEL2_L2A_Tilelocation;
+
+typedef struct
+{
+    const char* pszBandName;
+    const char* pszBandDescription;
+    SENTINEL2_L2A_Tilelocation eLocation;
+} SENTINEL2_L2A_BandDescription;
+
+static const SENTINEL2_L2A_BandDescription asL2ABandDesc[] =
+{
+    { "AOT", "Aerosol Optical Thickness map (at 550nm)", TL_IMG_DATA_Rxxm },
+    { "WVP", "Scene-average Water Vapour map", TL_IMG_DATA_Rxxm },
+    { "SCL", "Scene Classification", TL_IMG_DATA },
+    { "CLD", "Raster mask values range from 0 for high confidence clear sky to 100 for high confidence cloudy", TL_QI_DATA },
+    { "SNW", "Raster mask values range from 0 for high confidence NO snow/ice to 100 for high confidence snow/ice", TL_QI_DATA },
+};
+
+#define NB_L2A_BANDS (sizeof(asL2ABandDesc)/sizeof(asL2ABandDesc[0]))
+
+static
+const char* SENTINEL2GetOption( GDALOpenInfo* poOpenInfo,
+                                const char* pszName,
+                                const char* pszDefaultVal = NULL );
+static bool SENTINEL2GetTileInfo(const char* pszFilename,
+                                 int* pnWidth, int* pnHeight, int *pnBits);
+
+/************************************************************************/
+/*                           SENTINEL2GranuleInfo                       */
+/************************************************************************/
+
+class SENTINEL2GranuleInfo
+{
+    public:
+        CPLString osPath;
+        double    dfMinX, dfMinY, dfMaxX, dfMaxY;
+        int       nWidth, nHeight;
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                         SENTINEL2Dataset                             */
+/* ==================================================================== */
+/************************************************************************/
+
+class SENTINEL2DatasetContainer: public GDALPamDataset
+{
+    public:
+        SENTINEL2DatasetContainer() {}
+};
+
+class SENTINEL2Dataset : public VRTDataset
+{
+        std::vector<CPLString>   aosNonJP2Files;
+
+        void   AddL1CL2ABandMetadata(SENTINEL2Level eLevel,
+                                     CPLXMLNode* psRoot,
+                                     const std::vector<CPLString>& aosBands);
+
+        static SENTINEL2Dataset *CreateL1CL2ADataset(
+                SENTINEL2Level eLevel,
+                const std::vector<CPLString>& aosGranuleList,
+                std::vector<CPLString>& aosNonJP2Files,
+                int nSubDSPrecision,
+                bool bIsPreview,
+                int nSubDSEPSGCode,
+                bool bAlpha,
+                const std::vector<CPLString>& aosBands,
+                int nSaturatedVal,
+                int nNodataVal);
+
+    public:
+                    SENTINEL2Dataset(int nXSize, int nYSize);
+                    ~SENTINEL2Dataset();
+
+        virtual char** GetFileList();
+
+        static GDALDataset *Open( GDALOpenInfo * );
+        static GDALDataset *OpenL1BUserProduct( GDALOpenInfo * );
+        static GDALDataset *OpenL1BGranule( const char* pszFilename,
+                                            CPLXMLNode** ppsRoot = NULL,
+                                            int nResolutionOfInterest = 0,
+                                            std::set<CPLString> *poBandSet = NULL);
+        static GDALDataset *OpenL1BSubdataset( GDALOpenInfo * );
+        static GDALDataset *OpenL1C_L2A( const char* pszFilename,
+                                         SENTINEL2Level eLevel );
+        static GDALDataset *OpenL1CTile( const char* pszFilename,
+                                         CPLXMLNode** ppsRootMainMTD = NULL,
+                                         int nResolutionOfInterest = 0,
+                                         std::set<CPLString>* poBandSet = NULL);
+        static GDALDataset *OpenL1CTileSubdataset( GDALOpenInfo * );
+        static GDALDataset *OpenL1C_L2ASubdataset( GDALOpenInfo *,
+                                                   SENTINEL2Level eLevel );
+
+        static int Identify( GDALOpenInfo * );
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                         SENTINEL2AlphaBand                           */
+/* ==================================================================== */
+/************************************************************************/
+
+class SENTINEL2AlphaBand: public VRTSourcedRasterBand
+{
+                    int m_nSaturatedVal;
+                    int m_nNodataVal;
+
+    public:
+                     SENTINEL2AlphaBand( GDALDataset *poDS, int nBand,
+                                         GDALDataType eType,
+                                         int nXSize, int nYSize,
+                                         int nSaturatedVal, int nNodataVal );
+
+    virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
+                              void *, int, int, GDALDataType,
+#ifdef GDAL_DCAP_RASTER
+                              GSpacing nPixelSpace, GSpacing nLineSpace,
+                              GDALRasterIOExtraArg* psExtraArg
+#else
+                              int nPixelSpace, int nLineSpace
+#endif
+                              );
+
+};
+
+/************************************************************************/
+/*                         SENTINEL2AlphaBand()                         */
+/************************************************************************/
+
+SENTINEL2AlphaBand::SENTINEL2AlphaBand( GDALDataset *poDSIn, int nBandIn,
+                                        GDALDataType eType,
+                                        int nXSize, int nYSize,
+                                        int nSaturatedVal, int nNodataVal ) :
+                            VRTSourcedRasterBand(poDSIn, nBandIn, eType,
+                                                 nXSize, nYSize),
+                            m_nSaturatedVal(nSaturatedVal),
+                            m_nNodataVal(nNodataVal)
+{
+}
+
+/************************************************************************/
+/*                             IRasterIO()                              */
+/************************************************************************/
+
+CPLErr SENTINEL2AlphaBand::IRasterIO( GDALRWFlag eRWFlag,
+                                      int nXOff, int nYOff, int nXSize, int nYSize,
+                                      void * pData, int nBufXSize, int nBufYSize,
+                                      GDALDataType eBufType,
+#ifdef GDAL_DCAP_RASTER
+                                      GSpacing nPixelSpace, GSpacing nLineSpace,
+                                      GDALRasterIOExtraArg* psExtraArg
+#else
+                                      int nPixelSpace, int nLineSpace
+#endif
+                                      )
+{
+    // Query the first band. Quite arbitrary, but hopefully all bands have
+    // the same nodata/saturated pixels.
+    CPLErr eErr = poDS->GetRasterBand(1)->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                                            pData, nBufXSize, nBufYSize,
+                                            eBufType, nPixelSpace, nLineSpace
+#ifdef GDAL_DCAP_RASTER
+                                            ,psExtraArg
+#endif
+                                            );
+    if( eErr == CE_None )
+    {
+        const char* pszNBITS = GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
+        const int nBits = (pszNBITS) ? atoi(pszNBITS) : 16;
+        const GUInt16 nMaxVal = (GUInt16)((1 << nBits) - 1);
+
+        // Replace pixels matching m_nSaturatedVal and m_nNodataVal by 0
+        // and others by the maxVal.
+        for(int iY = 0; iY < nBufYSize; iY ++)
+        {
+            for(int iX = 0; iX < nBufXSize; iX ++)
+            {
+                // Optimized path for likely most common case
+                if( eBufType == GDT_UInt16 )
+                {
+                    GUInt16* panPtr = (GUInt16*)
+                           ((GByte*)pData + iY * nLineSpace + iX * nPixelSpace);
+                    if( *panPtr == 0 ||
+                        *panPtr == m_nSaturatedVal || *panPtr == m_nNodataVal )
+                    {
+                        *panPtr = 0;
+                    }
+                    else
+                        *panPtr = nMaxVal;
+                }
+                // Generic path for other datatypes
+                else
+                {
+                    double dfVal;
+                    GDALCopyWords((GByte*)pData + iY * nLineSpace + iX * nPixelSpace,
+                                   eBufType, 0,
+                                   &dfVal, GDT_Float64, 0,
+                                   1);
+                    if( dfVal == 0.0 || dfVal == m_nSaturatedVal ||
+                        dfVal == m_nNodataVal )
+                    {
+                        dfVal = 0;
+                    }
+                    else
+                        dfVal = nMaxVal;
+                    GDALCopyWords(&dfVal, GDT_Float64, 0,
+                                  (GByte*)pData + iY * nLineSpace + iX * nPixelSpace,
+                                  eBufType, 0,
+                                  1);
+                }
+            }
+        }
+    }
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                          SENTINEL2Dataset()                          */
+/************************************************************************/
+
+SENTINEL2Dataset::SENTINEL2Dataset(int nXSize, int nYSize) : VRTDataset(nXSize,nYSize)
+{
+    poDriver = NULL;
+    SetWritable(FALSE);
+}
+
+/************************************************************************/
+/*                         ~SENTINEL2Dataset()                          */
+/************************************************************************/
+
+SENTINEL2Dataset::~SENTINEL2Dataset()
+{
+}
+
+/************************************************************************/
+/*                            GetFileList()                             */
+/************************************************************************/
+
+char** SENTINEL2Dataset::GetFileList()
+{
+    CPLStringList aosList;
+    for(size_t i=0;i<aosNonJP2Files.size();i++)
+        aosList.AddString(aosNonJP2Files[i]);
+    char** papszFileList = VRTDataset::GetFileList();
+    for(char** papszIter = papszFileList; papszIter && *papszIter; ++papszIter)
+        aosList.AddString(*papszIter);
+    CSLDestroy(papszFileList);
+    return aosList.StealList();
+}
+
+/************************************************************************/
+/*                             Identify()                               */
+/************************************************************************/
+
+int SENTINEL2Dataset::Identify( GDALOpenInfo *poOpenInfo )
+{
+    if( STARTS_WITH_CI(poOpenInfo->pszFilename, "SENTINEL2_L1B:") )
+        return TRUE;
+    if( STARTS_WITH_CI(poOpenInfo->pszFilename, "SENTINEL2_L1C:") )
+        return TRUE;
+    if( STARTS_WITH_CI(poOpenInfo->pszFilename, "SENTINEL2_L1C_TILE:") )
+        return TRUE;
+    if( STARTS_WITH_CI(poOpenInfo->pszFilename, "SENTINEL2_L2A:") )
+        return TRUE;
+
+    /* Accept directly .zip as provided by https://scihub.esa.int/ */
+    const char* pszJustFilename = CPLGetFilename(poOpenInfo->pszFilename);
+    if( (STARTS_WITH_CI(pszJustFilename, "S2A_OPER_PRD_MSI") ||
+         STARTS_WITH_CI(pszJustFilename, "S2B_OPER_PRD_MSI") ||
+         STARTS_WITH_CI(pszJustFilename, "S2A_USER_PRD_MSI") ||
+         STARTS_WITH_CI(pszJustFilename, "S2B_USER_PRD_MSI") ) &&
+         EQUAL(CPLGetExtension(pszJustFilename), "zip") )
+    {
+        return TRUE;
+    }
+
+    if( poOpenInfo->nHeaderBytes < 100 )
+        return FALSE;
+
+    const char* pszHeader = reinterpret_cast<const char*>(poOpenInfo->pabyHeader);
+
+    if( strstr(pszHeader,  "<n1:Level-1B_User_Product" ) != NULL &&
+        strstr(pszHeader, "User_Product_Level-1B.xsd" ) != NULL )
+        return TRUE;
+
+    if( strstr(pszHeader,  "<n1:Level-1B_Granule_ID" ) != NULL &&
+        strstr(pszHeader, "S2_PDI_Level-1B_Granule_Metadata.xsd" ) != NULL )
+        return TRUE;
+
+    if( strstr(pszHeader,  "<n1:Level-1C_User_Product" ) != NULL &&
+        strstr(pszHeader, "User_Product_Level-1C.xsd" ) != NULL )
+        return TRUE;
+
+    if( strstr(pszHeader,  "<n1:Level-1C_Tile_ID" ) != NULL &&
+        strstr(pszHeader, "S2_PDI_Level-1C_Tile_Metadata.xsd" ) != NULL )
+        return TRUE;
+
+    if( strstr(pszHeader,  "<n1:Level-2A_User_Product" ) != NULL &&
+        strstr(pszHeader, "User_Product_Level-2A" ) != NULL )
+        return TRUE;
+
+    return FALSE;
+}
+
+/************************************************************************/
+/*                         SENTINEL2_CPLXMLNodeHolder                   */
+/************************************************************************/
+
+class SENTINEL2_CPLXMLNodeHolder
+{
+    CPLXMLNode* m_psNode;
+    public:
+        SENTINEL2_CPLXMLNodeHolder(CPLXMLNode* psNode) : m_psNode(psNode) {}
+       ~SENTINEL2_CPLXMLNodeHolder() { if(m_psNode) CPLDestroyXMLNode(m_psNode); }
+
+       CPLXMLNode* Release() { CPLXMLNode* psRet = m_psNode; m_psNode = NULL; return psRet; }
+};
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *SENTINEL2Dataset::Open( GDALOpenInfo * poOpenInfo )
+{
+    if ( !Identify( poOpenInfo ) )
+    {
+        return NULL;
+    }
+
+    if( STARTS_WITH_CI(poOpenInfo->pszFilename, "SENTINEL2_L1B:") )
+        return OpenL1BSubdataset(poOpenInfo);
+
+    if( STARTS_WITH_CI(poOpenInfo->pszFilename, "SENTINEL2_L1C:") )
+        return OpenL1C_L2ASubdataset(poOpenInfo, SENTINEL2_L1C);
+
+    if( STARTS_WITH_CI(poOpenInfo->pszFilename, "SENTINEL2_L1C_TILE:") )
+        return OpenL1CTileSubdataset(poOpenInfo);
+
+    if( STARTS_WITH_CI(poOpenInfo->pszFilename, "SENTINEL2_L2A:") )
+        return OpenL1C_L2ASubdataset(poOpenInfo, SENTINEL2_L2A);
+
+    const char* pszJustFilename = CPLGetFilename(poOpenInfo->pszFilename);
+    if( (STARTS_WITH_CI(pszJustFilename, "S2A_OPER_PRD_MSI") ||
+         STARTS_WITH_CI(pszJustFilename, "S2B_OPER_PRD_MSI") ||
+         STARTS_WITH_CI(pszJustFilename, "S2A_USER_PRD_MSI") ||
+         STARTS_WITH_CI(pszJustFilename, "S2B_USER_PRD_MSI") ) &&
+         EQUAL(CPLGetExtension(pszJustFilename), "zip") )
+    {
+        CPLString osBasename(CPLGetBasename(pszJustFilename));
+        CPLString osFilename(poOpenInfo->pszFilename);
+        CPLString osMTD(osBasename);
+        osMTD[9] = 'M';
+        osMTD[10] = 'T';
+        osMTD[11] = 'D';
+        osMTD[13] = 'S';
+        osMTD[14] = 'A';
+        osMTD[15] = 'F';
+        CPLString osSAFE(CPLString(osBasename) + ".SAFE");
+        osFilename = osFilename + "/" + osSAFE +"/" + osMTD + ".xml";
+        if( strncmp(osFilename, "/vsizip/", strlen("/vsizip/")) != 0 )
+            osFilename = "/vsizip/" + osFilename;
+        CPLDebug("SENTINEL2", "Trying %s", osFilename.c_str());
+        GDALOpenInfo oOpenInfo(osFilename, GA_ReadOnly);
+        return Open(&oOpenInfo);
+    }
+
+    const char* pszHeader = reinterpret_cast<const char*>(poOpenInfo->pabyHeader);
+
+    if( strstr(pszHeader,  "<n1:Level-1B_User_Product" ) != NULL &&
+        strstr(pszHeader, "User_Product_Level-1B.xsd" ) != NULL )
+    {
+        return OpenL1BUserProduct(poOpenInfo);
+    }
+
+    if( strstr(pszHeader,  "<n1:Level-1B_Granule_ID" ) != NULL &&
+        strstr(pszHeader, "S2_PDI_Level-1B_Granule_Metadata.xsd" ) != NULL )
+    {
+        return OpenL1BGranule(poOpenInfo->pszFilename);
+    }
+
+    if( strstr(pszHeader,  "<n1:Level-1C_User_Product" ) != NULL &&
+        strstr(pszHeader, "User_Product_Level-1C.xsd" ) != NULL )
+    {
+        return OpenL1C_L2A(poOpenInfo->pszFilename, SENTINEL2_L1C);
+    }
+
+    if( strstr(pszHeader,  "<n1:Level-1C_Tile_ID" ) != NULL &&
+        strstr(pszHeader, "S2_PDI_Level-1C_Tile_Metadata.xsd" ) != NULL )
+        return OpenL1CTile(poOpenInfo->pszFilename);
+
+    if( strstr(pszHeader,  "<n1:Level-2A_User_Product" ) != NULL &&
+        strstr(pszHeader, "User_Product_Level-2A" ) != NULL )
+        return OpenL1C_L2A(poOpenInfo->pszFilename, SENTINEL2_L2A);
+
+    return NULL;
+}
+
+/************************************************************************/
+/*                        SENTINEL2GetBandDesc()                        */
+/************************************************************************/
+
+static const SENTINEL2BandDescription* SENTINEL2GetBandDesc(const char* pszBandName)
+{
+    for(size_t i=0; i < NB_BANDS; i++)
+    {
+        if( EQUAL(asBandDesc[i].pszBandName, pszBandName) )
+            return &(asBandDesc[i]);
+    }
+    return NULL;
+}
+
+/************************************************************************/
+/*                       SENTINEL2GetL2ABandDesc()                      */
+/************************************************************************/
+
+static const SENTINEL2_L2A_BandDescription* SENTINEL2GetL2ABandDesc(const char* pszBandName)
+{
+    for(size_t i=0; i < NB_L2A_BANDS; i++)
+    {
+        if( EQUAL(asL2ABandDesc[i].pszBandName, pszBandName) )
+            return &(asL2ABandDesc[i]);
+    }
+    return NULL;
+}
+
+/************************************************************************/
+/*                        SENTINEL2GetGranuleInfo()                     */
+/************************************************************************/
+
+static bool SENTINEL2GetGranuleInfo(SENTINEL2Level eLevel,
+                                    const CPLString& osGranuleMTDPath,
+                                    int nDesiredResolution,
+                                    int* pnEPSGCode = NULL,
+                                    double* pdfULX = NULL,
+                                    double* pdfULY = NULL,
+                                    int* pnResolution = NULL,
+                                    int* pnWidth = NULL,
+                                    int* pnHeight = NULL)
+{
+    static bool bTryOptimization = true;
+    CPLXMLNode *psRoot = NULL;
+
+    if( bTryOptimization )
+    {
+        /* Small optimization: in practice the interesting info are in the */
+        /* first bytes of the Granule MTD, which can be very long sometimes */
+        /* so only read them, and hack the buffer a bit to form a valid XML */
+        char szBuffer[3072];
+        VSILFILE* fp = VSIFOpenL( osGranuleMTDPath, "rb" );
+        size_t nRead = 0;
+        if( fp == NULL ||
+            (nRead = VSIFReadL( szBuffer, 1, sizeof(szBuffer)-1, fp )) == 0 )
+        {
+            if( fp )
+                VSIFCloseL(fp);
+            CPLError(CE_Failure, CPLE_AppDefined, "Cannot read %s",
+                     osGranuleMTDPath.c_str());
+            return false;
+        }
+        szBuffer[nRead] = 0;
+        VSIFCloseL(fp);
+        char* pszTileGeocoding = strstr(szBuffer, "</Tile_Geocoding>");
+        if( eLevel == SENTINEL2_L1C &&
+            pszTileGeocoding != NULL &&
+            strstr(szBuffer, "<n1:Level-1C_Tile_ID") != NULL &&
+            strstr(szBuffer, "<n1:Geometric_Info") != NULL &&
+            static_cast<size_t>(pszTileGeocoding - szBuffer) <
+                sizeof(szBuffer) - strlen("</Tile_Geocoding></n1:Geometric_Info></n1:Level-1C_Tile_ID>") - 1 )
+        {
+            strcpy(pszTileGeocoding,
+                "</Tile_Geocoding></n1:Geometric_Info></n1:Level-1C_Tile_ID>");
+            psRoot = CPLParseXMLString( szBuffer );
+        }
+        else if( eLevel == SENTINEL2_L2A &&
+            pszTileGeocoding != NULL &&
+            strstr(szBuffer, "<n1:Level-2A_Tile_ID") != NULL &&
+            strstr(szBuffer, "<n1:Geometric_Info") != NULL &&
+            static_cast<size_t>(pszTileGeocoding - szBuffer) <
+                sizeof(szBuffer) - strlen("</Tile_Geocoding></n1:Geometric_Info></n1:Level-2A_Tile_ID>") - 1 )
+        {
+            strcpy(pszTileGeocoding,
+                "</Tile_Geocoding></n1:Geometric_Info></n1:Level-2A_Tile_ID>");
+            psRoot = CPLParseXMLString( szBuffer );
+        }
+        else
+            bTryOptimization = false;
+    }
+
+    // If the above doesn't work, then read the whole file...
+    if( psRoot == NULL )
+        psRoot = CPLParseXMLFile( osGranuleMTDPath );
+    if( psRoot == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot XML parse %s",
+                 osGranuleMTDPath.c_str());
+        return false;
+    }
+    SENTINEL2_CPLXMLNodeHolder oXMLHolder(psRoot);
+    CPLStripXMLNamespace(psRoot, NULL, TRUE);
+
+    const char* pszNodePath =
+        (eLevel == SENTINEL2_L1C ) ?
+             "=Level-1C_Tile_ID.Geometric_Info.Tile_Geocoding" :
+             "=Level-2A_Tile_ID.Geometric_Info.Tile_Geocoding";
+    CPLXMLNode* psTileGeocoding = CPLGetXMLNode(psRoot, pszNodePath);
+    if( psTileGeocoding == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s in %s",
+                 pszNodePath,
+                 osGranuleMTDPath.c_str());
+        return false;
+    }
+
+    const char* pszCSCode = CPLGetXMLValue(psTileGeocoding, "HORIZONTAL_CS_CODE", NULL);
+    if( pszCSCode == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s in %s",
+                 "HORIZONTAL_CS_CODE",
+                 osGranuleMTDPath.c_str());
+        return false;
+    }
+    if( !STARTS_WITH_CI(pszCSCode, "EPSG:") )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Invalid CS code (%s) for %s",
+                 pszCSCode,
+                 osGranuleMTDPath.c_str());
+        return false;
+    }
+    int nEPSGCode = atoi(pszCSCode + strlen("EPSG:"));
+    if( pnEPSGCode != NULL )
+        *pnEPSGCode = nEPSGCode;
+
+    for(CPLXMLNode* psIter = psTileGeocoding->psChild; psIter != NULL;
+                                                       psIter = psIter->psNext)
+    {
+        if( psIter->eType != CXT_Element )
+            continue;
+        if( EQUAL(psIter->pszValue, "Size") &&
+            (nDesiredResolution == 0 ||
+             atoi(CPLGetXMLValue(psIter, "resolution", "")) == nDesiredResolution) )
+        {
+            nDesiredResolution = atoi(CPLGetXMLValue(psIter, "resolution", ""));
+            const char* pszRows = CPLGetXMLValue(psIter, "NROWS", NULL);
+            if( pszRows == NULL )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s in %s",
+                        "NROWS",
+                        osGranuleMTDPath.c_str());
+                return false;
+            }
+            const char* pszCols = CPLGetXMLValue(psIter, "NCOLS", NULL);
+            if( pszCols == NULL )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s in %s",
+                        "NCOLS",
+                        osGranuleMTDPath.c_str());
+                return false;
+            }
+            if( pnResolution )
+                *pnResolution = nDesiredResolution;
+            if( pnWidth )
+                *pnWidth = atoi(pszCols);
+            if( pnHeight )
+                *pnHeight = atoi(pszRows);
+        }
+        else if( EQUAL(psIter->pszValue, "Geoposition") &&
+                 (nDesiredResolution == 0 ||
+                  atoi(CPLGetXMLValue(psIter, "resolution", "")) == nDesiredResolution) )
+        {
+            nDesiredResolution = atoi(CPLGetXMLValue(psIter, "resolution", ""));
+            const char* pszULX = CPLGetXMLValue(psIter, "ULX", NULL);
+            if( pszULX == NULL )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s in %s",
+                        "ULX",
+                        osGranuleMTDPath.c_str());
+                return false;
+            }
+            const char* pszULY = CPLGetXMLValue(psIter, "ULY", NULL);
+            if( pszULY == NULL )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s in %s",
+                        "ULY",
+                        osGranuleMTDPath.c_str());
+                return false;
+            }
+            if( pnResolution )
+                *pnResolution = nDesiredResolution;
+            if( pdfULX )
+                *pdfULX = CPLAtof(pszULX);
+            if( pdfULY )
+                *pdfULY = CPLAtof(pszULY);
+        }
+    }
+
+    return true;
+}
+
+/************************************************************************/
+/*                      SENTINEL2GetPathSeparator()                     */
+/************************************************************************/
+
+// For the sake of simplifying our unit tests, we limit the use of \\ to when
+// it is strictly necessary. Otherwise we could use CPLFormFilename()...
+static char SENTINEL2GetPathSeparator(const char* pszBasename)
+{
+    if( STARTS_WITH_CI(pszBasename, "\\\\?\\") )
+        return '\\';
+    else
+        return '/';
+}
+
+/************************************************************************/
+/*                      SENTINEL2GetGranuleList()                       */
+/************************************************************************/
+
+static bool SENTINEL2GetGranuleList(CPLXMLNode* psMainMTD,
+                                    SENTINEL2Level eLevel,
+                                    const char* pszFilename,
+                                    std::vector<CPLString>& osList,
+                                    std::set<int>* poSetResolutions = NULL,
+                                    std::map<int, std::set<CPLString> >*
+                                                poMapResolutionsToBands = NULL)
+{
+    const char* pszNodePath =
+        (eLevel == SENTINEL2_L1B ) ? "Level-1B_User_Product" :
+        (eLevel == SENTINEL2_L1C ) ? "Level-1C_User_Product" :
+                                     "Level-2A_User_Product";
+
+    CPLXMLNode* psRoot =  CPLGetXMLNode(psMainMTD,
+                                        CPLSPrintf("=%s", pszNodePath));
+    if( psRoot == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find =%s", pszNodePath);
+        return false;
+    }
+    pszNodePath = (eLevel == SENTINEL2_L2A) ?
+            "General_Info.L2A_Product_Info" : "General_Info.Product_Info";
+    CPLXMLNode* psProductInfo = CPLGetXMLNode(psRoot, pszNodePath);
+    if( psProductInfo == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s", pszNodePath);
+        return false;
+    }
+
+    pszNodePath = (eLevel == SENTINEL2_L2A) ?
+            "L2A_Product_Organisation" : "Product_Organisation";
+    CPLXMLNode* psProductOrganisation =
+                        CPLGetXMLNode(psProductInfo, pszNodePath);
+    if( psProductOrganisation == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s", pszNodePath);
+        return false;
+    }
+
+    CPLString osDirname( CPLGetDirname(pszFilename) );
+#ifdef HAVE_READLINK
+    char szPointerFilename[2048];
+    int nBytes = static_cast<int>(readlink(pszFilename, szPointerFilename,
+                                           sizeof(szPointerFilename)));
+    if (nBytes != -1)
+    {
+        szPointerFilename[MIN(nBytes,
+                            static_cast<int>(sizeof(szPointerFilename)-1))] = 0;
+        osDirname = CPLGetDirname(szPointerFilename);
+    }
+#endif
+
+    std::set<CPLString> aoSetGranuleId;
+    for(CPLXMLNode* psIter = psProductOrganisation->psChild; psIter != NULL;
+                                                    psIter = psIter->psNext )
+    {
+        if( psIter->eType != CXT_Element ||
+            !EQUAL(psIter->pszValue, "Granule_List") )
+        {
+            continue;
+        }
+        for(CPLXMLNode* psIter2 = psIter->psChild; psIter2 != NULL;
+                                                     psIter2 = psIter2->psNext )
+        {
+            if( psIter2->eType != CXT_Element ||
+                !EQUAL(psIter2->pszValue, "Granules") )
+            {
+                continue;
+            }
+            const char* pszGranuleId = CPLGetXMLValue(psIter2, "granuleIdentifier", NULL);
+            if( pszGranuleId == NULL )
+            {
+                CPLDebug("SENTINEL2", "Missing granuleIdentifier attribute");
+                continue;
+            }
+
+            if( eLevel == SENTINEL2_L2A )
+            {
+                for(CPLXMLNode* psIter3 = psIter2->psChild; psIter3 != NULL;
+                                                     psIter3 = psIter3->psNext )
+                {
+                    if( psIter3->eType != CXT_Element ||
+                        !EQUAL(psIter3->pszValue, "IMAGE_ID_2A") )
+                    {
+                        continue;
+                    }
+                    const char* pszTileName = CPLGetXMLValue(psIter3, NULL, "");
+                    size_t nLen = strlen(pszTileName);
+                    if( nLen > 4 && pszTileName[nLen-4] == '_' &&
+                        pszTileName[nLen-1] == 'm' )
+                    {
+                        int nResolution = atoi(pszTileName + nLen - 3);
+                        if( poSetResolutions != NULL )
+                            (*poSetResolutions).insert(nResolution);
+                        if( poMapResolutionsToBands != NULL )
+                        {
+                            nLen -= 4;
+                            if( nLen > 4 && pszTileName[nLen-4] == '_' &&
+                                pszTileName[nLen-3] == 'B' )
+                            {
+                                (*poMapResolutionsToBands)[nResolution].
+                                    insert(CPLString(pszTileName).substr(nLen-2,2));
+                            }
+                            else if ( nLen > strlen("S2A_USER_MSI_") &&
+                                      pszTileName[8] == '_' &&
+                                      pszTileName[12] == '_' &&
+                                      !EQUALN(pszTileName+9, "MSI", 3) )
+                            {
+                                (*poMapResolutionsToBands)[nResolution].
+                                    insert(CPLString(pszTileName).substr(9,3));
+                            }
+                        }
+                    }
+                }
+            }
+
+            // For L2A we can have several time the same granuleIdentifier
+            // for the different resolutions
+            if( aoSetGranuleId.find(pszGranuleId) != aoSetGranuleId.end() )
+                continue;
+            aoSetGranuleId.insert(pszGranuleId);
+
+            /* S2A_OPER_MSI_L1C_TL_SGS__20151024T023555_A001758_T53JLJ_N01.04 --> */
+            /* S2A_OPER_MTD_L1C_TL_SGS__20151024T023555_A001758_T53JLJ */
+            CPLString osGranuleMTD = pszGranuleId;
+            if( osGranuleMTD.size() > strlen("S2A_OPER_MSI_") &&
+                osGranuleMTD[8] == '_' && osGranuleMTD[12] == '_' &&
+                osGranuleMTD[osGranuleMTD.size()-7] == '_' &&
+                osGranuleMTD[osGranuleMTD.size()-6] == 'N' )
+            {
+                osGranuleMTD[9] = 'M';
+                osGranuleMTD[10] = 'T';
+                osGranuleMTD[11] = 'D';
+                osGranuleMTD.resize(osGranuleMTD.size()-7);
+            }
+            else
+            {
+                CPLDebug("SENTINEL2", "Invalid granule ID: %s", pszGranuleId);
+                continue;
+            }
+            osGranuleMTD += ".xml";
+
+            const char chSeparator = SENTINEL2GetPathSeparator(osDirname);
+            CPLString osGranuleMTDPath = osDirname;
+            osGranuleMTDPath += chSeparator;
+            osGranuleMTDPath += "GRANULE";
+            osGranuleMTDPath += chSeparator;
+            osGranuleMTDPath += pszGranuleId;
+            osGranuleMTDPath += chSeparator;
+            osGranuleMTDPath += osGranuleMTD;
+            osList.push_back(osGranuleMTDPath);
+        }
+    }
+
+    return true;
+}
+
+/************************************************************************/
+/*                     SENTINEL2GetUserProductMetadata()                */
+/************************************************************************/
+
+static
+char** SENTINEL2GetUserProductMetadata( CPLXMLNode* psMainMTD,
+                                    const char* pszRootNode )
+{
+    CPLStringList aosList;
+
+    CPLXMLNode* psRoot =  CPLGetXMLNode(psMainMTD,
+                                        CPLSPrintf("=%s", pszRootNode));
+    if( psRoot == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find =%s", pszRootNode);
+        return NULL;
+    }
+    CPLXMLNode* psProductInfo = CPLGetXMLNode(psRoot,
+        EQUAL(pszRootNode, "Level-2A_User_Product") ?
+            "General_Info.L2A_Product_Info" : "General_Info.Product_Info");
+    int nDataTakeCounter = 1;
+    for( CPLXMLNode* psIter = (psProductInfo ? psProductInfo->psChild : NULL);
+                     psIter != NULL;
+                     psIter = psIter->psNext )
+    {
+        if( psIter->eType != CXT_Element )
+            continue;
+        if( psIter->psChild != NULL && psIter->psChild->eType == CXT_Text )
+        {
+            aosList.AddNameValue( psIter->pszValue,
+                                  psIter->psChild->pszValue );
+        }
+        else if( EQUAL(psIter->pszValue, "Datatake") )
+        {
+            CPLString osPrefix(CPLSPrintf("DATATAKE_%d_", nDataTakeCounter));
+            nDataTakeCounter ++;
+            const char* pszId = CPLGetXMLValue(psIter, "datatakeIdentifier", NULL);
+            if( pszId )
+                aosList.AddNameValue( (osPrefix + "ID").c_str(), pszId );
+            for( CPLXMLNode* psIter2 = psIter->psChild;
+                     psIter2 != NULL;
+                     psIter2 = psIter2->psNext )
+            {
+                if( psIter2->eType != CXT_Element )
+                    continue;
+                if( psIter2->psChild != NULL && psIter2->psChild->eType == CXT_Text )
+                {
+                    aosList.AddNameValue( (osPrefix + psIter2->pszValue).c_str(),
+                                          psIter2->psChild->pszValue );
+                }
+            }
+        }
+    }
+
+    CPLXMLNode* psIC = CPLGetXMLNode(psRoot,
+            EQUAL(pszRootNode, "Level-2A_User_Product") ?
+                "General_Info.L2A_Product_Image_Characteristics" :
+                "General_Info.Product_Image_Characteristics");
+    if( psIC != NULL )
+    {
+        for( CPLXMLNode* psIter = psIC->psChild; psIter != NULL;
+                                                 psIter = psIter->psNext )
+        {
+            if( psIter->eType != CXT_Element ||
+                !EQUAL(psIter->pszValue, "Special_Values") )
+            {
+                continue;
+            }
+            const char* pszText = CPLGetXMLValue(psIter, "SPECIAL_VALUE_TEXT", NULL);
+            const char* pszIndex = CPLGetXMLValue(psIter, "SPECIAL_VALUE_INDEX", NULL);
+            if( pszText && pszIndex )
+            {
+                aosList.AddNameValue( (CPLString("SPECIAL_VALUE_") + pszText).c_str(),
+                                       pszIndex );
+            }
+        }
+
+        const char* pszQuantValue =
+            CPLGetXMLValue(psIC, "QUANTIFICATION_VALUE", NULL);
+        if( pszQuantValue != NULL )
+            aosList.AddNameValue("QUANTIFICATION_VALUE", pszQuantValue);
+
+        const char* pszRCU =
+            CPLGetXMLValue(psIC, "Reflectance_Conversion.U", NULL);
+        if( pszRCU != NULL )
+            aosList.AddNameValue("REFLECTANCE_CONVERSION_U", pszRCU);
+
+        // L2A specific
+        CPLXMLNode* psQVL = CPLGetXMLNode(psIC, "L1C_L2A_Quantification_Values_List");
+        for( CPLXMLNode* psIter = psQVL ? psQVL->psChild : NULL; psIter != NULL;
+                                                 psIter = psIter->psNext )
+        {
+            if( psIter->eType != CXT_Element )
+            {
+                continue;
+            }
+            aosList.AddNameValue( psIter->pszValue,
+                                  CPLGetXMLValue(psIter, NULL, NULL));
+            const char* pszUnit = CPLGetXMLValue(psIter, "unit", NULL);
+            if( pszUnit )
+                aosList.AddNameValue( CPLSPrintf("%s_UNIT", psIter->pszValue), pszUnit);
+        }
+
+        const char* pszRefBand =
+            CPLGetXMLValue(psIC, "REFERENCE_BAND", NULL);
+        if( pszRefBand != NULL )
+        {
+            int nIdx = atoi(pszRefBand);
+            if( nIdx >= 0 && nIdx < (int)NB_BANDS )
+                aosList.AddNameValue("REFERENCE_BAND", asBandDesc[nIdx].pszBandName );
+        }
+    }
+
+    CPLXMLNode* psQII = CPLGetXMLNode(psRoot, "Quality_Indicators_Info");
+    if( psQII != NULL )
+    {
+        const char* pszCC = CPLGetXMLValue(psQII, "Cloud_Coverage_Assessment", NULL);
+        if( pszCC )
+            aosList.AddNameValue("CLOUD_COVERAGE_ASSESSMENT",
+                                 pszCC);
+
+        const char* pszDegradedAnc = CPLGetXMLValue(psQII,
+            "Technical_Quality_Assessment.DEGRADED_ANC_DATA_PERCENTAGE", NULL);
+        if( pszDegradedAnc )
+            aosList.AddNameValue("DEGRADED_ANC_DATA_PERCENTAGE", pszDegradedAnc);
+
+        const char* pszDegradedMSI = CPLGetXMLValue(psQII,
+            "Technical_Quality_Assessment.DEGRADED_MSI_DATA_PERCENTAGE", NULL);
+        if( pszDegradedMSI )
+            aosList.AddNameValue("DEGRADED_MSI_DATA_PERCENTAGE", pszDegradedMSI);
+
+        CPLXMLNode* psQualInspect = CPLGetXMLNode(psQII,
+                            "Quality_Control_Checks.Quality_Inspections");
+        for( CPLXMLNode* psIter = (psQualInspect ? psQualInspect->psChild : NULL);
+                     psIter != NULL;
+                     psIter = psIter->psNext )
+        {
+            if( psIter->eType != CXT_Element )
+                continue;
+            if( psIter->psChild != NULL && psIter->psChild->eType == CXT_Text )
+            {
+                aosList.AddNameValue( psIter->pszValue,
+                                    psIter->psChild->pszValue );
+            }
+        }
+    }
+
+    CPLXMLNode* psL2A_QII = CPLGetXMLNode(psRoot, "L2A_Quality_Indicators_Info");
+    if( psL2A_QII != NULL )
+    {
+        CPLXMLNode* psICCQI = CPLGetXMLNode(psL2A_QII, "Image_Content_QI");
+        for( CPLXMLNode* psIter = (psICCQI ? psICCQI->psChild : NULL);
+                    psIter != NULL;
+                    psIter = psIter->psNext )
+        {
+            if( psIter->eType != CXT_Element )
+                continue;
+            if( psIter->psChild != NULL && psIter->psChild->eType == CXT_Text )
+            {
+                aosList.AddNameValue( psIter->pszValue,
+                                    psIter->psChild->pszValue );
+            }
+        }
+    }
+
+    return aosList.StealList();
+}
+
+/************************************************************************/
+/*                        SENTINEL2GetResolutionSet()                   */
+/************************************************************************/
+
+static bool SENTINEL2GetResolutionSet(CPLXMLNode* psProductInfo,
+                                      std::set<int>& oSetResolutions,
+                                      std::map<int, std::set<CPLString> >&
+                                                        oMapResolutionsToBands)
+{
+
+    CPLXMLNode* psBandList = CPLGetXMLNode(psProductInfo,
+                                           "Query_Options.Band_List");
+    if( psBandList == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s",
+                 "Query_Options.Band_List");
+        return false;
+    }
+
+    for(CPLXMLNode* psIter = psBandList->psChild; psIter != NULL;
+                                                  psIter = psIter->psNext )
+    {
+        if( psIter->eType != CXT_Element ||
+            !EQUAL(psIter->pszValue, "BAND_NAME") )
+        {
+            continue;
+        }
+        const char* pszBandName = CPLGetXMLValue(psIter, NULL, "");
+        const SENTINEL2BandDescription* psBandDesc =
+                                        SENTINEL2GetBandDesc(pszBandName);
+        if( psBandDesc == NULL )
+        {
+            CPLDebug("SENTINEL2", "Unknown band name %s", pszBandName);
+            continue;
+        }
+        oSetResolutions.insert( psBandDesc->nResolution );
+        CPLString osName = psBandDesc->pszBandName + 1; /* skip B character */
+        if( atoi(osName) < 10 )
+            osName = "0" + osName;
+        oMapResolutionsToBands[psBandDesc->nResolution].insert(osName);
+    }
+    if( oSetResolutions.size() == 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find any band");
+        return false;
+    }
+    return true;
+}
+
+/************************************************************************/
+/*                  SENTINEL2GetPolygonWKTFromPosList()                 */
+/************************************************************************/
+
+static CPLString SENTINEL2GetPolygonWKTFromPosList(const char* pszPosList)
+{
+    CPLString osPolygon;
+    char** papszTokens = CSLTokenizeString(pszPosList);
+    int nTokens = CSLCount(papszTokens);
+    int nDim = 2;
+    if( (nTokens % 3) == 0 && nTokens >= 3 * 4 &&
+        EQUAL(papszTokens[0], papszTokens[nTokens-3]) &&
+        EQUAL(papszTokens[1], papszTokens[nTokens-2]) &&
+        EQUAL(papszTokens[2], papszTokens[nTokens-1]) )
+    {
+        nDim = 3;
+    }
+    if( (nTokens % nDim) == 0 )
+    {
+        osPolygon = "POLYGON((";
+        for(char** papszIter = papszTokens; *papszIter; papszIter += nDim )
+        {
+            if( papszIter != papszTokens )
+                osPolygon += ", ";
+            osPolygon += papszIter[1];
+            osPolygon += " ";
+            osPolygon += papszIter[0];
+            if( nDim == 3 )
+            {
+                osPolygon += " ";
+                osPolygon += papszIter[2];
+            }
+        }
+        osPolygon += "))";
+    }
+    CSLDestroy(papszTokens);
+    return osPolygon;
+}
+
+/************************************************************************/
+/*                    SENTINEL2GetBandListForResolution()               */
+/************************************************************************/
+
+static CPLString SENTINEL2GetBandListForResolution(
+                                        const std::set<CPLString>& oBandnames)
+{
+    CPLString osBandNames;
+    for(std::set<CPLString>::const_iterator oIterBandnames = oBandnames.begin();
+                                            oIterBandnames != oBandnames.end();
+                                        ++oIterBandnames)
+    {
+        if( osBandNames.size() )
+            osBandNames += ", ";
+        const char* pszName = *oIterBandnames;
+        if( *pszName == '0' )
+            pszName ++;
+        if( atoi(pszName) > 0 )
+            osBandNames += "B" + CPLString(pszName);
+        else
+            osBandNames += pszName;
+    }
+    return osBandNames;
+}
+
+/************************************************************************/
+/*                         OpenL1BUserProduct()                         */
+/************************************************************************/
+
+GDALDataset *SENTINEL2Dataset::OpenL1BUserProduct( GDALOpenInfo * poOpenInfo )
+{
+    CPLXMLNode *psRoot = CPLParseXMLFile( poOpenInfo->pszFilename );
+    if( psRoot == NULL )
+        return NULL;
+
+    char* pszOriginalXML = CPLSerializeXMLTree(psRoot);
+    CPLString osOriginalXML;
+    if( pszOriginalXML )
+        osOriginalXML = pszOriginalXML;
+    CPLFree(pszOriginalXML);
+
+    SENTINEL2_CPLXMLNodeHolder oXMLHolder(psRoot);
+    CPLStripXMLNamespace(psRoot, NULL, TRUE);
+
+    CPLXMLNode* psProductInfo = CPLGetXMLNode(psRoot,
+                            "=Level-1B_User_Product.General_Info.Product_Info");
+    if( psProductInfo == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s",
+                 "=Level-1B_User_Product.General_Info.Product_Info");
+        return NULL;
+    }
+
+    std::set<int> oSetResolutions;
+    std::map<int, std::set<CPLString> > oMapResolutionsToBands;
+    if( !SENTINEL2GetResolutionSet(psProductInfo,
+                                   oSetResolutions,
+                                   oMapResolutionsToBands) )
+    {
+        return NULL;
+    }
+
+    std::vector<CPLString> aosGranuleList;
+    if( !SENTINEL2GetGranuleList(psRoot,
+                                 SENTINEL2_L1B,
+                                 poOpenInfo->pszFilename,
+                                 aosGranuleList) )
+    {
+        return NULL;
+    }
+
+    SENTINEL2DatasetContainer* poDS = new SENTINEL2DatasetContainer();
+    char** papszMD = SENTINEL2GetUserProductMetadata(psRoot,
+                                                 "Level-1B_User_Product");
+    poDS->GDALDataset::SetMetadata(papszMD);
+    CSLDestroy(papszMD);
+
+    if( osOriginalXML.size() )
+    {
+        char* apszXMLMD[2];
+        apszXMLMD[0] = const_cast<char*>(osOriginalXML.c_str());
+        apszXMLMD[1] = NULL;
+        poDS->GDALDataset::SetMetadata(apszXMLMD, "xml:SENTINEL2");
+    }
+
+    /* Create subdatsets per granules and resolution (10, 20, 60m) */
+    int iSubDSNum = 1;
+    for(size_t i = 0; i < aosGranuleList.size(); i++ )
+    {
+        for(std::set<int>::const_iterator oIterRes = oSetResolutions.begin();
+                                    oIterRes != oSetResolutions.end();
+                                ++oIterRes )
+        {
+            const int nResolution = *oIterRes;
+
+            poDS->GDALDataset::SetMetadataItem(
+                CPLSPrintf("SUBDATASET_%d_NAME", iSubDSNum),
+                CPLSPrintf("SENTINEL2_L1B:%s:%dm",
+                           aosGranuleList[i].c_str(),
+                           nResolution),
+                "SUBDATASETS");
+
+            CPLString osBandNames = SENTINEL2GetBandListForResolution(
+                                            oMapResolutionsToBands[nResolution]);
+
+            CPLString osDesc(CPLSPrintf("Bands %s of granule %s with %dm resolution",
+                                        osBandNames.c_str(),
+                                        CPLGetFilename(aosGranuleList[i]),
+                                        nResolution));
+            poDS->GDALDataset::SetMetadataItem(
+                CPLSPrintf("SUBDATASET_%d_DESC", iSubDSNum),
+                osDesc.c_str(),
+                "SUBDATASETS");
+
+            iSubDSNum ++;
+        }
+    }
+
+    const char* pszPosList = CPLGetXMLValue(psRoot,
+        "=Level-1B_User_Product.Geometric_Info.Product_Footprint."
+        "Product_Footprint.Global_Footprint.EXT_POS_LIST", NULL);
+    if( pszPosList != NULL )
+    {
+        CPLString osPolygon = SENTINEL2GetPolygonWKTFromPosList(pszPosList);
+        if( osPolygon.size() )
+            poDS->GDALDataset::SetMetadataItem("FOOTPRINT", osPolygon.c_str());
+    }
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                    SENTINEL2GetL1BGranuleMetadata()                  */
+/************************************************************************/
+
+static
+char** SENTINEL2GetL1BGranuleMetadata( CPLXMLNode* psMainMTD )
+{
+    CPLStringList aosList;
+
+    CPLXMLNode* psRoot =  CPLGetXMLNode(psMainMTD,
+                                        "=Level-1B_Granule_ID");
+    if( psRoot == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot find =Level-1B_Granule_ID");
+        return NULL;
+    }
+    CPLXMLNode* psGeneralInfo = CPLGetXMLNode(psRoot,
+                                              "General_Info");
+    for( CPLXMLNode* psIter = (psGeneralInfo ? psGeneralInfo->psChild : NULL);
+                     psIter != NULL;
+                     psIter = psIter->psNext )
+    {
+        if( psIter->eType != CXT_Element )
+            continue;
+        const char* pszValue = CPLGetXMLValue(psIter, NULL, NULL);
+        if( pszValue != NULL )
+        {
+            aosList.AddNameValue( psIter->pszValue, pszValue );
+        }
+    }
+
+    CPLXMLNode* psGeometryHeader = CPLGetXMLNode(psRoot,
+                        "Geometric_Info.Granule_Position.Geometric_Header");
+    if( psGeometryHeader != NULL )
+    {
+        const char* pszVal = CPLGetXMLValue(psGeometryHeader,
+                                            "Incidence_Angles.ZENITH_ANGLE", NULL);
+        if( pszVal )
+            aosList.AddNameValue( "INCIDENCE_ZENITH_ANGLE", pszVal );
+
+        pszVal = CPLGetXMLValue(psGeometryHeader,
+                                            "Incidence_Angles.AZIMUTH_ANGLE", NULL);
+        if( pszVal )
+            aosList.AddNameValue( "INCIDENCE_AZIMUTH_ANGLE", pszVal );
+
+        pszVal = CPLGetXMLValue(psGeometryHeader,
+                                            "Solar_Angles.ZENITH_ANGLE", NULL);
+        if( pszVal )
+            aosList.AddNameValue( "SOLAR_ZENITH_ANGLE", pszVal );
+
+        pszVal = CPLGetXMLValue(psGeometryHeader,
+                                            "Solar_Angles.AZIMUTH_ANGLE", NULL);
+        if( pszVal )
+            aosList.AddNameValue( "SOLAR_AZIMUTH_ANGLE", pszVal );
+    }
+
+    CPLXMLNode* psQII = CPLGetXMLNode(psRoot, "Quality_Indicators_Info");
+    if( psQII != NULL )
+    {
+        CPLXMLNode* psICCQI = CPLGetXMLNode(psQII, "Image_Content_QI");
+        for( CPLXMLNode* psIter = (psICCQI ? psICCQI->psChild : NULL);
+                     psIter != NULL;
+                     psIter = psIter->psNext )
+        {
+            if( psIter->eType != CXT_Element )
+                continue;
+            if( psIter->psChild != NULL && psIter->psChild->eType == CXT_Text )
+            {
+                aosList.AddNameValue( psIter->pszValue,
+                                    psIter->psChild->pszValue );
+            }
+        }
+    }
+
+    return aosList.StealList();
+}
+
+/************************************************************************/
+/*                        SENTINEL2GetTilename()                        */
+/************************************************************************/
+
+static CPLString SENTINEL2GetTilename(const CPLString& osGranulePath,
+                                      const CPLString& osGranuleName,
+                                      const CPLString& osBandName,
+                                      bool bIsPreview = false,
+                                      int nPrecisionL2A = 0)
+{
+    CPLString osJPEG2000Name(osGranuleName);
+    if( osJPEG2000Name.size() > 7 &&
+        osJPEG2000Name[osJPEG2000Name.size()-7] == '_' &&
+        osJPEG2000Name[osJPEG2000Name.size()-6] == 'N' )
+    {
+        osJPEG2000Name.resize(osJPEG2000Name.size()-7);
+    }
+
+    const SENTINEL2_L2A_BandDescription* psL2ABandDesc =
+                    (nPrecisionL2A) ? SENTINEL2GetL2ABandDesc(osBandName): NULL;
+
+    CPLString osTile(osGranulePath);
+    const char chSeparator = SENTINEL2GetPathSeparator(osTile);
+    if( osTile.size() )
+        osTile += chSeparator;
+    if( bIsPreview ||
+        (psL2ABandDesc != NULL && psL2ABandDesc->eLocation == TL_QI_DATA ) )
+    {
+        osTile += "QI_DATA";
+        osTile += chSeparator;
+        if( osJPEG2000Name.size() > 12 &&
+            osJPEG2000Name[8] == '_' && osJPEG2000Name[12] == '_' )
+        {
+            if( atoi(osBandName) > 0 )
+            {
+                osJPEG2000Name[9] = 'P';
+                osJPEG2000Name[10] = 'V';
+                osJPEG2000Name[11] = 'I';
+            }
+            else if( nPrecisionL2A && osBandName.size() == 3 )
+            {
+                osJPEG2000Name[9] = osBandName[0];
+                osJPEG2000Name[10] = osBandName[1];
+                osJPEG2000Name[11] = osBandName[2];
+            }
+        }
+        else
+        {
+            CPLDebug("SENTINEL2", "Invalid granule path: %s",
+                     osGranulePath.c_str());
+        }
+        osTile += osJPEG2000Name;
+        if( nPrecisionL2A && !bIsPreview )
+            osTile += CPLSPrintf("_%02dm", nPrecisionL2A);
+    }
+    else
+    {
+        osTile += "IMG_DATA";
+        osTile += chSeparator;
+        if( (psL2ABandDesc != NULL && psL2ABandDesc->eLocation == TL_IMG_DATA_Rxxm) ||
+            (psL2ABandDesc == NULL && nPrecisionL2A != 0) )
+        {
+            osTile += CPLSPrintf("R%02dm", nPrecisionL2A);
+            osTile += chSeparator;
+        }
+        if( osJPEG2000Name.size() > 12 &&
+            osJPEG2000Name[8] == '_' && osJPEG2000Name[12] == '_' )
+        {
+            if( atoi(osBandName) > 0 )
+            {
+                osJPEG2000Name[9] = 'M';
+                osJPEG2000Name[10] = 'S';
+                osJPEG2000Name[11] = 'I';
+            }
+            else if( nPrecisionL2A && osBandName.size() == 3 )
+            {
+                osJPEG2000Name[9] = osBandName[0];
+                osJPEG2000Name[10] = osBandName[1];
+                osJPEG2000Name[11] = osBandName[2];
+            }
+        }
+        else
+        {
+            CPLDebug("SENTINEL2", "Invalid granule path: %s",
+                     osGranulePath.c_str());
+        }
+        osTile += osJPEG2000Name;
+        if( atoi(osBandName) > 0 )
+        {
+            osTile += "_B";
+            if( osBandName.size() == 3 && osBandName[0] == '0' )
+                osTile += osBandName.substr(1);
+            else
+                osTile += osBandName;
+        }
+        if( nPrecisionL2A )
+            osTile += CPLSPrintf("_%02dm", nPrecisionL2A);
+    }
+    osTile += ".jp2";
+    return osTile;
+}
+
+/************************************************************************/
+/*                 SENTINEL2GetMainMTDFilenameFromGranuleMTD()          */
+/************************************************************************/
+
+static CPLString SENTINEL2GetMainMTDFilenameFromGranuleMTD(const char* pszFilename)
+{
+    // Look for product MTD file
+    CPLString osTopDir(CPLFormFilename(
+        CPLFormFilename( CPLGetDirname(pszFilename), "..", NULL ),
+        "..", NULL ));
+
+    // Workaround to avoid long filenames on Windows
+    if( CPLIsFilenameRelative(pszFilename) )
+    {
+        // GRANULE/bla/bla.xml
+        const char* pszPath = CPLGetPath(pszFilename);
+        if( strchr(pszPath, '/') || strchr(pszPath, '\\') )
+        {
+            osTopDir = CPLGetPath(CPLGetPath(pszPath));
+            if( osTopDir == "" )
+                osTopDir = ".";
+        }
+    }
+
+    char** papszContents = VSIReadDir(osTopDir);
+    CPLString osMainMTD;
+    for(char** papszIter = papszContents; papszIter && *papszIter; ++papszIter)
+    {
+        if( strlen(*papszIter) >= strlen("S2A_XXXX_MTD") &&
+            (STARTS_WITH_CI(*papszIter, "S2A_") ||
+             STARTS_WITH_CI(*papszIter, "S2B_")) &&
+             EQUALN(*papszIter + strlen("S2A_XXXX"), "_MTD", 4) )
+        {
+            osMainMTD = CPLFormFilename(osTopDir, *papszIter, NULL);
+            break;
+        }
+    }
+    CSLDestroy(papszContents);
+    return osMainMTD;
+}
+
+/************************************************************************/
+/*            SENTINEL2GetResolutionSetAndMainMDFromGranule()           */
+/************************************************************************/
+
+static void SENTINEL2GetResolutionSetAndMainMDFromGranule(
+                    const char* pszFilename,
+                    const char* pszRootPathWithoutEqual,
+                    int nResolutionOfInterest,
+                    std::set<int>& oSetResolutions,
+                    std::map<int, std::set<CPLString> >& oMapResolutionsToBands,
+                    char**& papszMD,
+                    CPLXMLNode** ppsRootMainMTD)
+{
+    CPLString osMainMTD(SENTINEL2GetMainMTDFilenameFromGranuleMTD(pszFilename));
+
+    // Parse product MTD if available
+    papszMD = NULL;
+    if( osMainMTD.size() != 0 &&
+        /* env var for debug only */
+        CPLTestBool(CPLGetConfigOption("SENTINEL2_USE_MAIN_MTD", "YES")) )
+    {
+        CPLXMLNode *psRootMainMTD = CPLParseXMLFile( osMainMTD );
+        if( psRootMainMTD != NULL )
+        {
+            CPLStripXMLNamespace(psRootMainMTD, NULL, TRUE);
+
+            CPLXMLNode* psProductInfo = CPLGetXMLNode(psRootMainMTD,
+                CPLSPrintf("=%s.General_Info.Product_Info", pszRootPathWithoutEqual));
+            if( psProductInfo != NULL )
+            {
+                SENTINEL2GetResolutionSet(psProductInfo,
+                                          oSetResolutions,
+                                          oMapResolutionsToBands);
+            }
+
+            papszMD = SENTINEL2GetUserProductMetadata(psRootMainMTD,
+                                                      pszRootPathWithoutEqual);
+            if( ppsRootMainMTD != NULL )
+                *ppsRootMainMTD = psRootMainMTD;
+            else
+                CPLDestroyXMLNode(psRootMainMTD);
+        }
+    }
+    else
+    {
+        // If no main MTD file found, then probe all bands for resolution (of
+        // interest if there's one, or all resolutions otherwise)
+        for(size_t i=0;i<NB_BANDS;i++)
+        {
+            if( nResolutionOfInterest != 0 &&
+                asBandDesc[i].nResolution != nResolutionOfInterest )
+            {
+                continue;
+            }
+            CPLString osBandName = asBandDesc[i].pszBandName + 1; /* skip B character */
+            if( atoi(osBandName) < 10 )
+                osBandName = "0" + osBandName;
+
+            CPLString osTile(SENTINEL2GetTilename(CPLGetPath(pszFilename),
+                                                  CPLGetBasename(pszFilename),
+                                                  osBandName));
+            VSIStatBufL sStat;
+            if( VSIStatExL(osTile, &sStat, VSI_STAT_EXISTS_FLAG) == 0 )
+            {
+                oMapResolutionsToBands[asBandDesc[i].nResolution].insert(osBandName);
+                oSetResolutions.insert(asBandDesc[i].nResolution);
+            }
+        }
+    }
+}
+
+/************************************************************************/
+/*                           OpenL1BGranule()                           */
+/************************************************************************/
+
+GDALDataset *SENTINEL2Dataset::OpenL1BGranule( const char* pszFilename,
+                                               CPLXMLNode** ppsRoot,
+                                               int nResolutionOfInterest,
+                                               std::set<CPLString> *poBandSet )
+{
+    CPLXMLNode *psRoot = CPLParseXMLFile( pszFilename );
+    if( psRoot == NULL )
+        return NULL;
+
+    char* pszOriginalXML = CPLSerializeXMLTree(psRoot);
+    CPLString osOriginalXML;
+    if( pszOriginalXML )
+        osOriginalXML = pszOriginalXML;
+    CPLFree(pszOriginalXML);
+
+    SENTINEL2_CPLXMLNodeHolder oXMLHolder(psRoot);
+    CPLStripXMLNamespace(psRoot, NULL, TRUE);
+
+    CPLString osMainMTD(SENTINEL2GetMainMTDFilenameFromGranuleMTD(pszFilename));
+
+    SENTINEL2DatasetContainer* poDS = new SENTINEL2DatasetContainer();
+
+    if( osOriginalXML.size() )
+    {
+        char* apszXMLMD[2];
+        apszXMLMD[0] = const_cast<char*>(osOriginalXML.c_str());
+        apszXMLMD[1] = NULL;
+        poDS->GDALDataset::SetMetadata(apszXMLMD, "xml:SENTINEL2");
+    }
+
+    std::set<int> oSetResolutions;
+    std::map<int, std::set<CPLString> > oMapResolutionsToBands;
+    char** papszMD = NULL;
+    SENTINEL2GetResolutionSetAndMainMDFromGranule(pszFilename,
+                                                  "Level-1B_User_Product",
+                                                  nResolutionOfInterest,
+                                                  oSetResolutions,
+                                                  oMapResolutionsToBands,
+                                                  papszMD,
+                                                  NULL);
+    if( poBandSet != NULL )
+        *poBandSet = oMapResolutionsToBands[nResolutionOfInterest];
+
+    char** papszGranuleMD = SENTINEL2GetL1BGranuleMetadata(psRoot);
+    papszMD = CSLMerge(papszMD, papszGranuleMD);
+    CSLDestroy(papszGranuleMD);
+
+    // Remove CLOUD_COVERAGE_ASSESSMENT that comes from main metadata, if granule
+    // CLOUDY_PIXEL_PERCENTAGE is present.
+    if( CSLFetchNameValue(papszMD, "CLOUDY_PIXEL_PERCENTAGE") != NULL &&
+        CSLFetchNameValue(papszMD, "CLOUD_COVERAGE_ASSESSMENT") != NULL )
+    {
+        papszMD = CSLSetNameValue(papszMD, "CLOUD_COVERAGE_ASSESSMENT", NULL);
+    }
+
+    poDS->GDALDataset::SetMetadata(papszMD);
+    CSLDestroy(papszMD);
+
+    // Get the footprint
+    const char* pszPosList = CPLGetXMLValue(psRoot,
+        "=Level-1B_Granule_ID.Geometric_Info.Granule_Footprint."
+        "Granule_Footprint.Footprint.EXT_POS_LIST", NULL);
+    if( pszPosList != NULL )
+    {
+        CPLString osPolygon = SENTINEL2GetPolygonWKTFromPosList(pszPosList);
+        if( osPolygon.size() )
+            poDS->GDALDataset::SetMetadataItem("FOOTPRINT", osPolygon.c_str());
+    }
+
+    /* Create subdatsets per resolution (10, 20, 60m) */
+    int iSubDSNum = 1;
+    for(std::set<int>::const_iterator oIterRes = oSetResolutions.begin();
+                                oIterRes != oSetResolutions.end();
+                            ++oIterRes )
+    {
+        const int nResolution = *oIterRes;
+
+        poDS->GDALDataset::SetMetadataItem(
+            CPLSPrintf("SUBDATASET_%d_NAME", iSubDSNum),
+            CPLSPrintf("SENTINEL2_L1B:%s:%dm",
+                        pszFilename,
+                        nResolution),
+            "SUBDATASETS");
+
+        CPLString osBandNames = SENTINEL2GetBandListForResolution(
+                                        oMapResolutionsToBands[nResolution]);
+
+        CPLString osDesc(CPLSPrintf("Bands %s with %dm resolution",
+                                    osBandNames.c_str(),
+                                    nResolution));
+        poDS->GDALDataset::SetMetadataItem(
+            CPLSPrintf("SUBDATASET_%d_DESC", iSubDSNum),
+            osDesc.c_str(),
+            "SUBDATASETS");
+
+        iSubDSNum ++;
+    }
+
+    if( ppsRoot != NULL )
+    {
+        *ppsRoot = oXMLHolder.Release();
+    }
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                     SENTINEL2SetBandMetadata()                       */
+/************************************************************************/
+
+static void SENTINEL2SetBandMetadata(GDALRasterBand* poBand,
+                                     const CPLString& osBandName)
+{
+    CPLString osLookupBandName(osBandName);
+    if( osLookupBandName[0] == '0' )
+        osLookupBandName = osLookupBandName.substr(1);
+    if( atoi(osLookupBandName) > 0 )
+        osLookupBandName = "B" + osLookupBandName;
+
+    CPLString osBandDesc(osLookupBandName);
+    const SENTINEL2BandDescription* psBandDesc =
+                            SENTINEL2GetBandDesc(osLookupBandName);
+    if( psBandDesc != NULL )
+    {
+        osBandDesc += CPLSPrintf(", central wavelength %d nm",
+                                    psBandDesc->nWaveLength);
+        poBand->SetColorInterpretation(psBandDesc->eColorInterp);
+        poBand->SetMetadataItem("BANDNAME", psBandDesc->pszBandName);
+        poBand->SetMetadataItem("BANDWIDTH", CPLSPrintf("%d",
+                                                psBandDesc->nBandWidth));
+        poBand->SetMetadataItem("BANDWIDTH_UNIT", "nm");
+        poBand->SetMetadataItem("WAVELENGTH", CPLSPrintf("%d",
+                                                psBandDesc->nWaveLength));
+        poBand->SetMetadataItem("WAVELENGTH_UNIT", "nm");
+    }
+    else
+    {
+        const SENTINEL2_L2A_BandDescription* psL2ABandDesc =
+                                        SENTINEL2GetL2ABandDesc(osBandName);
+        if(psL2ABandDesc != NULL )
+        {
+            osBandDesc += ", ";
+            osBandDesc += psL2ABandDesc->pszBandDescription;
+        }
+
+        poBand->SetMetadataItem("BANDNAME", osBandName);
+    }
+    poBand->SetDescription(osBandDesc);
+}
+
+/************************************************************************/
+/*                         OpenL1BSubdataset()                          */
+/************************************************************************/
+
+GDALDataset *SENTINEL2Dataset::OpenL1BSubdataset( GDALOpenInfo * poOpenInfo )
+{
+    CPLString osFilename;
+    CPLAssert( STARTS_WITH_CI(poOpenInfo->pszFilename, "SENTINEL2_L1B:") );
+    osFilename = poOpenInfo->pszFilename + strlen("SENTINEL2_L1B:");
+    const char* pszPrecision = strrchr(osFilename.c_str(), ':');
+    if( pszPrecision == NULL || pszPrecision == osFilename.c_str() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Invalid syntax for SENTINEL2_L1B:");
+        return NULL;
+    }
+    const int nSubDSPrecision = atoi(pszPrecision + 1);
+    if( nSubDSPrecision != 10 && nSubDSPrecision != 20 && nSubDSPrecision != 60 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, "Unsupported precision: %d",
+                 nSubDSPrecision);
+        return NULL;
+    }
+    osFilename.resize( pszPrecision - osFilename.c_str() );
+
+    CPLXMLNode* psRoot = NULL;
+    std::set<CPLString> oSetBands;
+    GDALDataset* poTmpDS = OpenL1BGranule( osFilename, &psRoot,
+                                           nSubDSPrecision, &oSetBands);
+    if( poTmpDS == NULL )
+        return NULL;
+
+    SENTINEL2_CPLXMLNodeHolder oXMLHolder(psRoot);
+
+    std::vector<CPLString> aosBands;
+    for(std::set<CPLString>::const_iterator oIterBandnames = oSetBands.begin();
+                                            oIterBandnames != oSetBands.end();
+                                        ++oIterBandnames)
+    {
+        aosBands.push_back(*oIterBandnames);
+    }
+    /* Put 2=Blue, 3=Green, 4=Band bands in RGB order for conveniency */
+    if( aosBands.size() >= 3 &&
+        aosBands[0] == "02" &&
+        aosBands[1] == "03" &&
+        aosBands[2] == "04" )
+    {
+        aosBands[0] = "04";
+        aosBands[2] = "02";
+    }
+
+    int nBits = 0; /* 0 = unknown yet*/
+    int nValMax = 0; /* 0 = unknown yet*/
+    int nRows = 0, nCols = 0;
+    CPLXMLNode* psGranuleDimensions =
+        CPLGetXMLNode(psRoot, "=Level-1B_Granule_ID.Geometric_Info.Granule_Dimensions");
+    if( psGranuleDimensions == NULL )
+    {
+        for( size_t i=0; i<aosBands.size(); i++ )
+        {
+            CPLString osTile(SENTINEL2GetTilename(CPLGetPath(osFilename),
+                                                  CPLGetBasename(osFilename),
+                                                  aosBands[i]));
+            if( SENTINEL2GetTileInfo(osTile, &nCols, &nRows, &nBits) )
+            {
+                if( nBits <= 16 )
+                    nValMax = (1 << nBits) - 1;
+                else
+                {
+                    CPLDebug("SENTINEL2", "Unexpected bit depth %d", nBits);
+                    nValMax = 65535;
+                }
+                break;
+            }
+        }
+    }
+    else
+    {
+        for(CPLXMLNode* psIter = psGranuleDimensions->psChild; psIter != NULL;
+                                                        psIter = psIter->psNext)
+        {
+            if( psIter->eType != CXT_Element )
+                continue;
+            if( EQUAL(psIter->pszValue, "Size") &&
+                atoi(CPLGetXMLValue(psIter, "resolution", "")) == nSubDSPrecision )
+            {
+                const char* pszRows = CPLGetXMLValue(psIter, "NROWS", NULL);
+                if( pszRows == NULL )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s",
+                            "NROWS");
+                    delete poTmpDS;
+                    return NULL;
+                }
+                const char* pszCols = CPLGetXMLValue(psIter, "NCOLS", NULL);
+                if( pszCols == NULL )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s",
+                            "NCOLS");
+                    delete poTmpDS;
+                    return NULL;
+                }
+                nRows = atoi(pszRows);
+                nCols = atoi(pszCols);
+                break;
+            }
+        }
+    }
+    if( nRows <= 0 || nCols <= 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find granule dimension");
+        delete poTmpDS;
+        return NULL;
+    }
+
+    SENTINEL2Dataset* poDS = new SENTINEL2Dataset(nCols, nRows);
+    poDS->aosNonJP2Files.push_back(osFilename);
+
+    // Transfer metadata
+    poDS->GDALDataset::SetMetadata( poTmpDS->GetMetadata() );
+    poDS->GDALDataset::SetMetadata( poTmpDS->GetMetadata("xml:SENTINEL2"), "xml:SENTINEL2" );
+
+    delete poTmpDS;
+
+/* -------------------------------------------------------------------- */
+/*      Initialize bands.                                               */
+/* -------------------------------------------------------------------- */
+
+    int nSaturatedVal = atoi(CSLFetchNameValueDef(poDS->GetMetadata(), "SPECIAL_VALUE_SATURATED", "-1"));
+    int nNodataVal = atoi(CSLFetchNameValueDef(poDS->GetMetadata(), "SPECIAL_VALUE_NODATA", "-1"));
+
+    const bool bAlpha =
+        CPLTestBool(SENTINEL2GetOption(poOpenInfo, "ALPHA", "FALSE"));
+    const int nBands = ((bAlpha) ? 1 : 0) + static_cast<int>(aosBands.size());
+    const int nAlphaBand = (!bAlpha) ? 0 : nBands;
+    const GDALDataType eDT = GDT_UInt16;
+
+    for(int nBand=1;nBand<=nBands;nBand++)
+    {
+        VRTSourcedRasterBand* poBand;
+
+        if( nBand != nAlphaBand )
+        {
+            poBand = new VRTSourcedRasterBand( poDS, nBand, eDT,
+                                               poDS->nRasterXSize,
+                                               poDS->nRasterYSize );
+        }
+        else
+        {
+            poBand = new SENTINEL2AlphaBand ( poDS, nBand, eDT,
+                                              poDS->nRasterXSize,
+                                              poDS->nRasterYSize,
+                                              nSaturatedVal,
+                                              nNodataVal );
+        }
+
+        poDS->SetBand(nBand, poBand);
+        if( nBand == nAlphaBand )
+            poBand->SetColorInterpretation(GCI_AlphaBand);
+
+        CPLString osBandName;
+        if( nBand != nAlphaBand )
+        {
+            osBandName = aosBands[nBand-1];
+            SENTINEL2SetBandMetadata( poBand, osBandName);
+        }
+        else
+            osBandName = aosBands[0];
+
+        CPLString osTile(SENTINEL2GetTilename(CPLGetPath(osFilename),
+                                              CPLGetBasename(osFilename),
+                                              osBandName));
+
+        bool bTileFound = false;
+        if( nValMax == 0 )
+        {
+            /* It is supposed to be 12 bits, but some products have 15 bits */
+            if( SENTINEL2GetTileInfo(osTile, NULL, NULL, &nBits) )
+            {
+                bTileFound = true;
+                if( nBits <= 16 )
+                    nValMax = (1 << nBits) - 1;
+                else
+                {
+                    CPLDebug("SENTINEL2", "Unexpected bit depth %d", nBits);
+                    nValMax = 65535;
+                }
+            }
+        }
+        else
+        {
+            VSIStatBufL sStat;
+            if( VSIStatExL(osTile, &sStat, VSI_STAT_EXISTS_FLAG) == 0 )
+                bTileFound = true;
+        }
+        if( !bTileFound )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                    "Tile %s not found on filesystem. Skipping it",
+                    osTile.c_str());
+            continue;
+        }
+
+        GDALProxyPoolDataset* proxyDS;
+        proxyDS = new GDALProxyPoolDataset(         osTile,
+                                                    poDS->nRasterXSize,
+                                                    poDS->nRasterYSize,
+                                                    GA_ReadOnly,
+                                                    TRUE);
+        proxyDS->AddSrcBandDescription(eDT, 128, 128);
+
+        if( nBand != nAlphaBand )
+        {
+            poBand->AddSimpleSource( proxyDS->GetRasterBand(1),
+                                    0, 0,
+                                    poDS->nRasterXSize,
+                                    poDS->nRasterYSize,
+                                    0,
+                                    0,
+                                    poDS->nRasterXSize,
+                                    poDS->nRasterYSize);
+        }
+        else
+        {
+            poBand->AddComplexSource( proxyDS->GetRasterBand(1),
+                                        0, 0,
+                                        poDS->nRasterXSize,
+                                        poDS->nRasterYSize,
+                                        0,
+                                        0,
+                                        poDS->nRasterXSize,
+                                        poDS->nRasterYSize,
+                                        nValMax /* offset */,
+                                        0 /* scale */);
+        }
+
+        proxyDS->Dereference();
+
+        if( (nBits % 8) != 0 )
+        {
+            poBand->SetMetadataItem("NBITS",
+                                CPLSPrintf("%d", nBits), "IMAGE_STRUCTURE");
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Add georeferencing.                                             */
+/* -------------------------------------------------------------------- */
+    //const char* pszDirection = poDS->GetMetadataItem("DATATAKE_1_SENSING_ORBIT_DIRECTION");
+    const char* pszFootprint = poDS->GetMetadataItem("FOOTPRINT");
+    if( pszFootprint != NULL )
+    {
+        // For descending orbits, we have observed that the order of points in
+        // the polygon is UL, LL, LR, UR. That might not be true for ascending orbits
+        // but let's assume it...
+        char* pszFootprintC = const_cast<char*>(pszFootprint);
+        OGRGeometry* poGeom = NULL;
+        if( OGRGeometryFactory::createFromWkt( &pszFootprintC, NULL, &poGeom)
+                                                                == OGRERR_NONE &&
+            poGeom != NULL &&
+            wkbFlatten(poGeom->getGeometryType()) == wkbPolygon )
+        {
+            OGRLinearRing* poRing =
+                reinterpret_cast<OGRPolygon*>(poGeom)->getExteriorRing();
+            if( poRing != NULL && poRing->getNumPoints() == 5 )
+            {
+                GDAL_GCP    asGCPList[5];
+                memset( asGCPList, 0, sizeof(asGCPList) );
+                for(int i=0;i<4;i++)
+                {
+                    asGCPList[i].dfGCPX = poRing->getX(i);
+                    asGCPList[i].dfGCPY = poRing->getY(i);
+                    asGCPList[i].dfGCPZ = poRing->getZ(i);
+                }
+                asGCPList[0].dfGCPPixel = 0;
+                asGCPList[0].dfGCPLine = 0;
+                asGCPList[1].dfGCPPixel = 0;
+                asGCPList[1].dfGCPLine = poDS->nRasterYSize;
+                asGCPList[2].dfGCPPixel = poDS->nRasterXSize;
+                asGCPList[2].dfGCPLine = poDS->nRasterYSize;
+                asGCPList[3].dfGCPPixel = poDS->nRasterXSize;
+                asGCPList[3].dfGCPLine = 0;
+
+                int nGCPCount = 4;
+                CPLXMLNode* psGeometryHeader =
+                    CPLGetXMLNode(psRoot,
+                                  "=Level-1B_Granule_ID.Geometric_Info."
+                                  "Granule_Position.Geometric_Header");
+                if( psGeometryHeader != NULL )
+                {
+                    const char* pszGC =
+                        CPLGetXMLValue(psGeometryHeader, "GROUND_CENTER", NULL);
+                    const char* pszQLCenter =
+                        CPLGetXMLValue(psGeometryHeader, "QL_CENTER", NULL);
+                    if( pszGC != NULL && pszQLCenter != NULL && EQUAL(pszQLCenter, "0 0") )
+                    {
+                        char** papszTokens = CSLTokenizeString(pszGC);
+                        if( CSLCount(papszTokens) >= 2 )
+                        {
+                            nGCPCount = 5;
+                            asGCPList[4].dfGCPX = CPLAtof(papszTokens[1]);
+                            asGCPList[4].dfGCPY = CPLAtof(papszTokens[0]);
+                            if( CSLCount(papszTokens) >= 3 )
+                                asGCPList[4].dfGCPZ = CPLAtof(papszTokens[2]);
+                            asGCPList[4].dfGCPLine = poDS->nRasterYSize / 2.0;
+                            asGCPList[4].dfGCPPixel = poDS->nRasterXSize / 2.0;
+                        }
+                        CSLDestroy(papszTokens);
+                    }
+                }
+
+                poDS->SetGCPs( nGCPCount, asGCPList, SRS_WKT_WGS84 );
+                GDALDeinitGCPs( nGCPCount, asGCPList );
+            }
+        }
+        delete poGeom;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Initialize overview information.                                */
+/* -------------------------------------------------------------------- */
+    poDS->SetDescription( poOpenInfo->pszFilename );
+    CPLString osOverviewFile;
+    osOverviewFile = CPLSPrintf("%s_%dm.tif.ovr",
+                                osFilename.c_str(), nSubDSPrecision);
+    poDS->SetMetadataItem( "OVERVIEW_FILE", osOverviewFile, "OVERVIEWS" );
+    poDS->oOvManager.Initialize( poDS, ":::VIRTUAL:::" );
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                           OpenL1C_L2A()                              */
+/************************************************************************/
+
+GDALDataset *SENTINEL2Dataset::OpenL1C_L2A( const char* pszFilename,
+                                            SENTINEL2Level eLevel )
+{
+    CPLXMLNode *psRoot = CPLParseXMLFile( pszFilename );
+    if( psRoot == NULL )
+        return NULL;
+
+    char* pszOriginalXML = CPLSerializeXMLTree(psRoot);
+    CPLString osOriginalXML;
+    if( pszOriginalXML )
+        osOriginalXML = pszOriginalXML;
+    CPLFree(pszOriginalXML);
+
+    SENTINEL2_CPLXMLNodeHolder oXMLHolder(psRoot);
+    CPLStripXMLNamespace(psRoot, NULL, TRUE);
+
+    const char* pszNodePath = (eLevel == SENTINEL2_L1C ) ?
+                "=Level-1C_User_Product.General_Info.Product_Info" :
+                "=Level-2A_User_Product.General_Info.L2A_Product_Info";
+    CPLXMLNode* psProductInfo = CPLGetXMLNode(psRoot, pszNodePath);
+    if( psProductInfo == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s", pszNodePath);
+        return NULL;
+    }
+
+    std::set<int> oSetResolutions;
+    std::map<int, std::set<CPLString> > oMapResolutionsToBands;
+    if( eLevel == SENTINEL2_L1C &&
+        !SENTINEL2GetResolutionSet(psProductInfo,
+                                   oSetResolutions,
+                                   oMapResolutionsToBands) )
+    {
+        return NULL;
+    }
+
+    std::vector<CPLString> aosGranuleList;
+    if( !SENTINEL2GetGranuleList(psRoot,
+                                 eLevel,
+                                 pszFilename,
+                                 aosGranuleList,
+                                 (eLevel == SENTINEL2_L1C) ? NULL :
+                                                    &oSetResolutions,
+                                 (eLevel == SENTINEL2_L1C) ? NULL :
+                                                    &oMapResolutionsToBands) )
+    {
+        return NULL;
+    }
+
+    std::set<int> oSetEPSGCodes;
+    for(size_t i=0;i<aosGranuleList.size();i++)
+    {
+        int nEPSGCode = 0;
+        if( SENTINEL2GetGranuleInfo(eLevel,
+                                    aosGranuleList[i],
+                                    *(oSetResolutions.begin()), &nEPSGCode) )
+        {
+            oSetEPSGCodes.insert(nEPSGCode);
+        }
+    }
+
+    SENTINEL2DatasetContainer* poDS = new SENTINEL2DatasetContainer();
+    char** papszMD = SENTINEL2GetUserProductMetadata(psRoot,
+        (eLevel == SENTINEL2_L1C ) ? "Level-1C_User_Product" :
+                                     "Level-2A_User_Product");
+    poDS->GDALDataset::SetMetadata(papszMD);
+    CSLDestroy(papszMD);
+
+    if( osOriginalXML.size() )
+    {
+        char* apszXMLMD[2];
+        apszXMLMD[0] = const_cast<char*>(osOriginalXML.c_str());
+        apszXMLMD[1] = NULL;
+        poDS->GDALDataset::SetMetadata(apszXMLMD, "xml:SENTINEL2");
+    }
+
+    const char* pszPrefix = (eLevel == SENTINEL2_L1C) ? "SENTINEL2_L1C" :
+                                                        "SENTINEL2_L2A";
+
+    /* Create subdatsets per resolution (10, 20, 60m) and EPSG codes */
+    int iSubDSNum = 1;
+    for(std::set<int>::const_iterator oIterRes = oSetResolutions.begin();
+                                oIterRes != oSetResolutions.end();
+                              ++oIterRes )
+    {
+        const int nResolution = *oIterRes;
+
+        for(std::set<int>::const_iterator oIterEPSG = oSetEPSGCodes.begin();
+                                    oIterEPSG != oSetEPSGCodes.end();
+                                  ++oIterEPSG )
+        {
+            const int nEPSGCode = *oIterEPSG;
+            poDS->GDALDataset::SetMetadataItem(
+                CPLSPrintf("SUBDATASET_%d_NAME", iSubDSNum),
+                CPLSPrintf("%s:%s:%dm:EPSG_%d",
+                            pszPrefix, pszFilename, nResolution, nEPSGCode),
+                "SUBDATASETS");
+
+            CPLString osBandNames = SENTINEL2GetBandListForResolution(
+                                            oMapResolutionsToBands[nResolution]);
+
+            CPLString osDesc(CPLSPrintf("Bands %s with %dm resolution",
+                                        osBandNames.c_str(), nResolution));
+            if( nEPSGCode >= 32601 && nEPSGCode <= 32660 )
+                osDesc += CPLSPrintf(", UTM %dN", nEPSGCode - 32600);
+            else if( nEPSGCode >= 32701 && nEPSGCode <= 32760 )
+                osDesc += CPLSPrintf(", UTM %dS", nEPSGCode - 32700);
+            else
+                osDesc += CPLSPrintf(", EPSG:%d", nEPSGCode);
+            poDS->GDALDataset::SetMetadataItem(
+                CPLSPrintf("SUBDATASET_%d_DESC", iSubDSNum),
+                osDesc.c_str(),
+                "SUBDATASETS");
+
+            iSubDSNum ++;
+        }
+    }
+
+    /* Expose PREVIEW subdatasets */
+    for(std::set<int>::const_iterator oIterEPSG = oSetEPSGCodes.begin();
+                                    oIterEPSG != oSetEPSGCodes.end();
+                                  ++oIterEPSG )
+    {
+        const int nEPSGCode = *oIterEPSG;
+        poDS->GDALDataset::SetMetadataItem(
+            CPLSPrintf("SUBDATASET_%d_NAME", iSubDSNum),
+            CPLSPrintf("%s:%s:PREVIEW:EPSG_%d",
+                        pszPrefix, pszFilename, nEPSGCode),
+            "SUBDATASETS");
+
+        CPLString osDesc("RGB preview");
+        if( nEPSGCode >= 32601 && nEPSGCode <= 32660 )
+            osDesc += CPLSPrintf(", UTM %dN", nEPSGCode - 32600);
+        else if( nEPSGCode >= 32701 && nEPSGCode <= 32760 )
+            osDesc += CPLSPrintf(", UTM %dS", nEPSGCode - 32700);
+        else
+            osDesc += CPLSPrintf(", EPSG:%d", nEPSGCode);
+        poDS->GDALDataset::SetMetadataItem(
+            CPLSPrintf("SUBDATASET_%d_DESC", iSubDSNum),
+            osDesc.c_str(),
+            "SUBDATASETS");
+
+        iSubDSNum ++;
+    }
+
+    pszNodePath = (eLevel == SENTINEL2_L1C ) ?
+        "=Level-1C_User_Product.Geometric_Info.Product_Footprint."
+        "Product_Footprint.Global_Footprint.EXT_POS_LIST" :
+        "=Level-2A_User_Product.Geometric_Info.Product_Footprint."
+        "Product_Footprint.Global_Footprint.EXT_POS_LIST";
+    const char* pszPosList = CPLGetXMLValue(psRoot, pszNodePath, NULL);
+    if( pszPosList != NULL )
+    {
+        CPLString osPolygon = SENTINEL2GetPolygonWKTFromPosList(pszPosList);
+        if( osPolygon.size() )
+            poDS->GDALDataset::SetMetadataItem("FOOTPRINT", osPolygon.c_str());
+    }
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                    SENTINEL2GetL1BCTileMetadata()                    */
+/************************************************************************/
+
+static
+char** SENTINEL2GetL1BCTileMetadata( CPLXMLNode* psMainMTD )
+{
+    CPLStringList aosList;
+
+    CPLXMLNode* psRoot =  CPLGetXMLNode(psMainMTD,
+                                        "=Level-1C_Tile_ID");
+    if( psRoot == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot find =Level-1C_Tile_ID");
+        return NULL;
+    }
+    CPLXMLNode* psGeneralInfo = CPLGetXMLNode(psRoot,
+                                              "General_Info");
+    for( CPLXMLNode* psIter = (psGeneralInfo ? psGeneralInfo->psChild : NULL);
+                     psIter != NULL;
+                     psIter = psIter->psNext )
+    {
+        if( psIter->eType != CXT_Element )
+            continue;
+        const char* pszValue = CPLGetXMLValue(psIter, NULL, NULL);
+        if( pszValue != NULL )
+        {
+            aosList.AddNameValue( psIter->pszValue, pszValue );
+        }
+    }
+
+    CPLXMLNode* psQII = CPLGetXMLNode(psRoot, "Quality_Indicators_Info");
+    if( psQII != NULL )
+    {
+        CPLXMLNode* psICCQI = CPLGetXMLNode(psQII, "Image_Content_QI");
+        for( CPLXMLNode* psIter = (psICCQI ? psICCQI->psChild : NULL);
+                     psIter != NULL;
+                     psIter = psIter->psNext )
+        {
+            if( psIter->eType != CXT_Element )
+                continue;
+            if( psIter->psChild != NULL && psIter->psChild->eType == CXT_Text )
+            {
+                aosList.AddNameValue( psIter->pszValue,
+                                    psIter->psChild->pszValue );
+            }
+        }
+    }
+
+    return aosList.StealList();
+}
+
+/************************************************************************/
+/*                              OpenL1CTile()                           */
+/************************************************************************/
+
+GDALDataset *SENTINEL2Dataset::OpenL1CTile( const char* pszFilename,
+                                            CPLXMLNode** ppsRootMainMTD,
+                                            int nResolutionOfInterest,
+                                            std::set<CPLString>* poBandSet )
+{
+    CPLXMLNode *psRoot = CPLParseXMLFile( pszFilename );
+    if( psRoot == NULL )
+        return NULL;
+
+    char* pszOriginalXML = CPLSerializeXMLTree(psRoot);
+    CPLString osOriginalXML;
+    if( pszOriginalXML )
+        osOriginalXML = pszOriginalXML;
+    CPLFree(pszOriginalXML);
+
+    SENTINEL2_CPLXMLNodeHolder oXMLHolder(psRoot);
+    CPLStripXMLNamespace(psRoot, NULL, TRUE);
+
+    std::set<int> oSetResolutions;
+    std::map<int, std::set<CPLString> > oMapResolutionsToBands;
+    char** papszMD = NULL;
+    SENTINEL2GetResolutionSetAndMainMDFromGranule(pszFilename,
+                                                  "Level-1C_User_Product",
+                                                  nResolutionOfInterest,
+                                                  oSetResolutions,
+                                                  oMapResolutionsToBands,
+                                                  papszMD,
+                                                  ppsRootMainMTD);
+    if( poBandSet != NULL )
+        *poBandSet = oMapResolutionsToBands[nResolutionOfInterest];
+
+    SENTINEL2DatasetContainer* poDS = new SENTINEL2DatasetContainer();
+
+    char** papszGranuleMD = SENTINEL2GetL1BCTileMetadata(psRoot);
+    papszMD = CSLMerge(papszMD, papszGranuleMD);
+    CSLDestroy(papszGranuleMD);
+
+    // Remove CLOUD_COVERAGE_ASSESSMENT that comes from main metadata, if granule
+    // CLOUDY_PIXEL_PERCENTAGE is present.
+    if( CSLFetchNameValue(papszMD, "CLOUDY_PIXEL_PERCENTAGE") != NULL &&
+        CSLFetchNameValue(papszMD, "CLOUD_COVERAGE_ASSESSMENT") != NULL )
+    {
+        papszMD = CSLSetNameValue(papszMD, "CLOUD_COVERAGE_ASSESSMENT", NULL);
+    }
+
+    poDS->GDALDataset::SetMetadata(papszMD);
+    CSLDestroy(papszMD);
+
+    if( osOriginalXML.size() )
+    {
+        char* apszXMLMD[2];
+        apszXMLMD[0] = const_cast<char*>(osOriginalXML.c_str());
+        apszXMLMD[1] = NULL;
+        poDS->GDALDataset::SetMetadata(apszXMLMD, "xml:SENTINEL2");
+    }
+
+    /* Create subdatsets per resolution (10, 20, 60m) */
+    int iSubDSNum = 1;
+    for(std::set<int>::const_iterator oIterRes = oSetResolutions.begin();
+                                oIterRes != oSetResolutions.end();
+                              ++oIterRes )
+    {
+        const int nResolution = *oIterRes;
+
+        poDS->GDALDataset::SetMetadataItem(
+            CPLSPrintf("SUBDATASET_%d_NAME", iSubDSNum),
+            CPLSPrintf("%s:%s:%dm",
+                        "SENTINEL2_L1C_TILE", pszFilename, nResolution),
+                        "SUBDATASETS");
+
+        CPLString osBandNames = SENTINEL2GetBandListForResolution(
+                                        oMapResolutionsToBands[nResolution]);
+
+        CPLString osDesc(CPLSPrintf("Bands %s with %dm resolution",
+                                    osBandNames.c_str(), nResolution));
+        poDS->GDALDataset::SetMetadataItem(
+            CPLSPrintf("SUBDATASET_%d_DESC", iSubDSNum),
+            osDesc.c_str(),
+            "SUBDATASETS");
+
+        iSubDSNum ++;
+    }
+
+    /* Expose PREVIEW subdataset */
+    poDS->GDALDataset::SetMetadataItem(
+        CPLSPrintf("SUBDATASET_%d_NAME", iSubDSNum),
+        CPLSPrintf("%s:%s:PREVIEW",
+                    "SENTINEL2_L1C_TILE", pszFilename),
+        "SUBDATASETS");
+
+    CPLString osDesc("RGB preview");
+    poDS->GDALDataset::SetMetadataItem(
+        CPLSPrintf("SUBDATASET_%d_DESC", iSubDSNum),
+        osDesc.c_str(),
+        "SUBDATASETS");
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                         SENTINEL2GetOption()                         */
+/************************************************************************/
+
+static
+const char* SENTINEL2GetOption( GDALOpenInfo* poOpenInfo,
+                                const char* pszName,
+                                const char* pszDefaultVal )
+{
+#ifdef GDAL_DMD_OPENOPTIONLIST
+    const char* pszVal = CSLFetchNameValue(poOpenInfo->papszOpenOptions, pszName);
+    if( pszVal != NULL )
+        return pszVal;
+#else
+    (void) poOpenInfo;
+#endif
+    return CPLGetConfigOption( CPLSPrintf("SENTINEL2_%s", pszName), pszDefaultVal );
+}
+
+/************************************************************************/
+/*                            LaunderUnit()                             */
+/************************************************************************/
+
+static CPLString LaunderUnit(const char* pszUnit)
+{
+    CPLString osUnit;
+    for(int i=0; pszUnit[i] != '\0'; )
+    {
+        if( strncmp(pszUnit + i, "\xC2" "\xB2", 2) == 0 ) /* square / 2 */
+        {
+            i += 2;
+            osUnit += "2";
+        }
+        else if( strncmp(pszUnit + i, "\xC2" "\xB5", 2) == 0 ) /* micro */
+        {
+            i += 2;
+            osUnit += "u";
+        }
+        else
+        {
+            osUnit += pszUnit[i];
+            i ++;
+        }
+    }
+    return osUnit;
+}
+
+/************************************************************************/
+/*                       SENTINEL2GetTileInfo()                         */
+/************************************************************************/
+
+static bool SENTINEL2GetTileInfo(const char* pszFilename,
+                                int* pnWidth, int* pnHeight, int *pnBits)
+{
+    static const unsigned char jp2_box_jp[] = {0x6a,0x50,0x20,0x20}; /* 'jP  ' */
+    VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
+    if( fp == NULL )
+        return false;
+    GByte abyHeader[8];
+    if( VSIFReadL(abyHeader, 8, 1, fp) != 1 )
+    {
+        VSIFCloseL(fp);
+        return false;
+    }
+    if( memcmp(abyHeader + 4, jp2_box_jp, 4) == 0 )
+    {
+        bool bRet = false;
+        /* Just parse the ihdr box instead of doing a full dataset opening */
+        GDALJP2Box oBox( fp );
+        if( oBox.ReadFirst() )
+        {
+            while( strlen(oBox.GetType()) > 0 )
+            {
+                if( EQUAL(oBox.GetType(),"jp2h") )
+                {
+                    GDALJP2Box oChildBox( fp );
+                    if( !oChildBox.ReadFirstChild( &oBox ) )
+                        break;
+
+                    while( strlen(oChildBox.GetType()) > 0 )
+                    {
+                        if( EQUAL(oChildBox.GetType(),"ihdr") )
+                        {
+                            GByte* pabyData = oChildBox.ReadBoxData();
+                            GIntBig nLength = oChildBox.GetDataLength();
+                            if( pabyData != NULL && nLength >= 4 + 4 + 2 + 1 )
+                            {
+                                bRet = true;
+                                if( pnHeight )
+                                {
+                                    memcpy(pnHeight, pabyData, 4);
+                                    CPL_MSBPTR32(pnHeight);
+                                }
+                                if( pnWidth )
+                                {
+                                    memcpy(pnWidth, pabyData+4, 4);
+                                    CPL_MSBPTR32(pnWidth);
+                                }
+                                if( pnBits )
+                                {
+                                    GByte byPBC = pabyData[4+4+2];
+                                    if( byPBC != 255 )
+                                    {
+                                        *pnBits = 1 + (byPBC & 0x7f);
+                                    }
+                                    else
+                                        *pnBits = 0;
+                                }
+                            }
+                            CPLFree(pabyData);
+                            break;
+                        }
+                        if( !oChildBox.ReadNextChild( &oBox ) )
+                            break;
+                    }
+                    break;
+                }
+
+                if (!oBox.ReadNext())
+                    break;
+            }
+        }
+        VSIFCloseL(fp);
+        return bRet;
+    }
+    else /* for unit tests, we use TIFF */
+    {
+        VSIFCloseL(fp);
+        GDALDataset* poDS = (GDALDataset*)GDALOpen(pszFilename, GA_ReadOnly);
+        bool bRet = false;
+        if( poDS != NULL )
+        {
+            if( poDS->GetRasterCount() != 0 )
+            {
+                bRet = true;
+                if( pnWidth )
+                    *pnWidth = poDS->GetRasterXSize();
+                if( pnHeight )
+                    *pnHeight = poDS->GetRasterYSize();
+                if( pnBits )
+                {
+                    const char* pszNBits = poDS->GetRasterBand(1)->GetMetadataItem(
+                                                            "NBITS", "IMAGE_STRUCTURE");
+                    if( pszNBits == NULL )
+                    {
+                        GDALDataType eDT = poDS->GetRasterBand(1)->GetRasterDataType();
+                        pszNBits = CPLSPrintf( "%d", GDALGetDataTypeSize(eDT) );
+                    }
+                    *pnBits = atoi(pszNBits);
+                }
+            }
+            GDALClose(poDS);
+        }
+        return bRet;
+    }
+}
+
+/************************************************************************/
+/*                         OpenL1C_L2ASubdataset()                      */
+/************************************************************************/
+
+GDALDataset *SENTINEL2Dataset::OpenL1C_L2ASubdataset( GDALOpenInfo * poOpenInfo,
+                                                      SENTINEL2Level eLevel )
+{
+    CPLString osFilename;
+    const char* pszPrefix = (eLevel == SENTINEL2_L1C) ? "SENTINEL2_L1C" :
+                                                        "SENTINEL2_L2A";
+    CPLAssert( STARTS_WITH_CI(poOpenInfo->pszFilename, pszPrefix) );
+    osFilename = poOpenInfo->pszFilename + strlen(pszPrefix) + 1;
+    const char* pszEPSGCode = strrchr(osFilename.c_str(), ':');
+    if( pszEPSGCode == NULL || pszEPSGCode == osFilename.c_str() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Invalid syntax for %s:", pszPrefix);
+        return NULL;
+    }
+    osFilename[ (size_t)(pszEPSGCode - osFilename.c_str()) ] = '\0';
+    const char* pszPrecision = strrchr(osFilename.c_str(), ':');
+    if( pszPrecision == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Invalid syntax for %s:", pszPrefix);
+        return NULL;
+    }
+
+    if( !STARTS_WITH_CI(pszEPSGCode+1, "EPSG_") )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Invalid syntax for %s:", pszPrefix);
+        return NULL;
+    }
+
+    const int nSubDSEPSGCode = atoi(pszEPSGCode + 1 + strlen("EPSG_"));
+    const bool bIsPreview = STARTS_WITH_CI(pszPrecision + 1, "PREVIEW");
+    const int nSubDSPrecision = (bIsPreview) ? 320 : atoi(pszPrecision + 1);
+    if( !bIsPreview &&
+        nSubDSPrecision != 10 && nSubDSPrecision != 20 && nSubDSPrecision != 60 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, "Unsupported precision: %d",
+                 nSubDSPrecision);
+        return NULL;
+    }
+
+    osFilename.resize( pszPrecision - osFilename.c_str() );
+    std::vector<CPLString> aosNonJP2Files;
+    aosNonJP2Files.push_back(osFilename);
+
+    CPLXMLNode *psRoot = CPLParseXMLFile( osFilename );
+    if( psRoot == NULL )
+        return NULL;
+
+    char* pszOriginalXML = CPLSerializeXMLTree(psRoot);
+    CPLString osOriginalXML;
+    if( pszOriginalXML )
+        osOriginalXML = pszOriginalXML;
+    CPLFree(pszOriginalXML);
+
+    SENTINEL2_CPLXMLNodeHolder oXMLHolder(psRoot);
+    CPLStripXMLNamespace(psRoot, NULL, TRUE);
+
+    std::vector<CPLString> aosGranuleList;
+    std::set<int> oSetResolutions;
+    std::map<int, std::set<CPLString> > oMapResolutionsToBands;
+    if( !SENTINEL2GetGranuleList(psRoot,
+                                 eLevel,
+                                 osFilename,
+                                 aosGranuleList,
+                                 NULL,
+                                 (eLevel == SENTINEL2_L1C) ? NULL :
+                                                    &oMapResolutionsToBands) )
+    {
+        return NULL;
+    }
+
+    std::vector<CPLString> aosBands;
+    std::set<CPLString> oSetBands;
+    if( bIsPreview )
+    {
+        aosBands.push_back("04");
+        aosBands.push_back("03");
+        aosBands.push_back("02");
+    }
+    else if( eLevel == SENTINEL2_L1C )
+    {
+        CPLXMLNode* psBandList = CPLGetXMLNode(psRoot,
+            "=Level-1C_User_Product.General_Info.Product_Info.Query_Options.Band_List");
+        if( psBandList == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s",
+                    "Query_Options.Band_List");
+            return NULL;
+        }
+
+        for(CPLXMLNode* psIter = psBandList->psChild; psIter != NULL;
+                                                      psIter = psIter->psNext )
+        {
+            if( psIter->eType != CXT_Element ||
+                !EQUAL(psIter->pszValue, "BAND_NAME") )
+                continue;
+            const char* pszBandName = CPLGetXMLValue(psIter, NULL, "");
+            const SENTINEL2BandDescription* psBandDesc =
+                                SENTINEL2GetBandDesc(pszBandName);
+            if( psBandDesc == NULL )
+            {
+                CPLDebug("SENTINEL2", "Unknown band name %s", pszBandName);
+                continue;
+            }
+            if( psBandDesc->nResolution != nSubDSPrecision )
+                continue;
+            CPLString osName = psBandDesc->pszBandName + 1; /* skip B character */
+            if( atoi(osName) < 10 )
+                osName = "0" + osName;
+            oSetBands.insert(osName);
+        }
+        if( oSetBands.size() == 0 )
+            return NULL;
+    }
+    else
+    {
+        oSetBands = oMapResolutionsToBands[nSubDSPrecision];
+    }
+
+    if( aosBands.size() == 0 )
+    {
+        for(std::set<CPLString>::const_iterator oIterBandnames = oSetBands.begin();
+                                                oIterBandnames != oSetBands.end();
+                                            ++oIterBandnames)
+        {
+            aosBands.push_back(*oIterBandnames);
+        }
+        /* Put 2=Blue, 3=Green, 4=Band bands in RGB order for conveniency */
+        if( aosBands.size() >= 3 &&
+            aosBands[0] == "02" &&
+            aosBands[1] == "03" &&
+            aosBands[2] == "04" )
+        {
+            aosBands[0] = "04";
+            aosBands[2] = "02";
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create dataset.                                                 */
+/* -------------------------------------------------------------------- */
+
+    char** papszMD = SENTINEL2GetUserProductMetadata(psRoot,
+        (eLevel == SENTINEL2_L1C ) ? "Level-1C_User_Product" : "Level-2A_User_Product");
+
+    const int nSaturatedVal = atoi(CSLFetchNameValueDef(papszMD,
+                                                  "SPECIAL_VALUE_SATURATED", "-1"));
+    const int nNodataVal = atoi(CSLFetchNameValueDef(papszMD,
+                                               "SPECIAL_VALUE_NODATA", "-1"));
+
+    const bool bAlpha =
+        CPLTestBool(SENTINEL2GetOption(poOpenInfo, "ALPHA", "FALSE"));
+
+    SENTINEL2Dataset* poDS = CreateL1CL2ADataset(eLevel,
+                                                 aosGranuleList,
+                                                 aosNonJP2Files,
+                                                 nSubDSPrecision,
+                                                 bIsPreview,
+                                                 nSubDSEPSGCode,
+                                                 bAlpha,
+                                                 aosBands,
+                                                 nSaturatedVal,
+                                                 nNodataVal);
+    if( poDS == NULL )
+    {
+        CSLDestroy(papszMD);
+        return NULL;
+    }
+
+    if( osOriginalXML.size() )
+    {
+        char* apszXMLMD[2];
+        apszXMLMD[0] = const_cast<char*>(osOriginalXML.c_str());
+        apszXMLMD[1] = NULL;
+        poDS->GDALDataset::SetMetadata(apszXMLMD, "xml:SENTINEL2");
+    }
+
+    poDS->GDALDataset::SetMetadata(papszMD);
+    CSLDestroy(papszMD);
+
+/* -------------------------------------------------------------------- */
+/*      Add extra band metadata.                                        */
+/* -------------------------------------------------------------------- */
+    poDS->AddL1CL2ABandMetadata(eLevel, psRoot, aosBands);
+
+/* -------------------------------------------------------------------- */
+/*      Initialize overview information.                                */
+/* -------------------------------------------------------------------- */
+    poDS->SetDescription( poOpenInfo->pszFilename );
+    CPLString osOverviewFile;
+    if( bIsPreview )
+        osOverviewFile = CPLSPrintf("%s_PREVIEW_EPSG_%d.tif.ovr",
+                                    osFilename.c_str(), nSubDSEPSGCode);
+    else
+        osOverviewFile = CPLSPrintf("%s_%dm_EPSG_%d.tif.ovr",
+                                    osFilename.c_str(), nSubDSPrecision,
+                                    nSubDSEPSGCode);
+    poDS->SetMetadataItem( "OVERVIEW_FILE", osOverviewFile, "OVERVIEWS" );
+    poDS->oOvManager.Initialize( poDS, ":::VIRTUAL:::" );
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                         AddL1CL2ABandMetadata()                      */
+/************************************************************************/
+
+void SENTINEL2Dataset::AddL1CL2ABandMetadata(SENTINEL2Level eLevel,
+                                             CPLXMLNode* psRoot,
+                                             const std::vector<CPLString>& aosBands)
+{
+    CPLXMLNode* psIC = CPLGetXMLNode(psRoot,
+        (eLevel == SENTINEL2_L1C) ?
+            "=Level-1C_User_Product.General_Info.Product_Image_Characteristics" :
+            "=Level-2A_User_Product.General_Info.L2A_Product_Image_Characteristics");
+    if( psIC != NULL )
+    {
+        CPLXMLNode* psSIL = CPLGetXMLNode(psIC,
+                            "Reflectance_Conversion.Solar_Irradiance_List");
+        if( psSIL != NULL )
+        {
+            for(CPLXMLNode* psIter = psSIL->psChild; psIter != NULL;
+                                                     psIter = psIter->psNext )
+            {
+                if( psIter->eType != CXT_Element ||
+                    !EQUAL(psIter->pszValue, "SOLAR_IRRADIANCE") )
+                {
+                    continue;
+                }
+                const char* pszBandId = CPLGetXMLValue(psIter, "bandId", NULL);
+                const char* pszUnit = CPLGetXMLValue(psIter, "unit", NULL);
+                const char* pszValue = CPLGetXMLValue(psIter, NULL, NULL);
+                if( pszBandId != NULL && pszUnit != NULL && pszValue != NULL )
+                {
+                    int nIdx = atoi(pszBandId);
+                    if( nIdx >= 0 && nIdx < (int)NB_BANDS )
+                    {
+                        for(int i=0;i<nBands;i++)
+                        {
+                            GDALRasterBand* poBand = GetRasterBand(i+1);
+                            const char* pszBandName =
+                                poBand->GetMetadataItem("BANDNAME");
+                            if( pszBandName != NULL &&
+                                EQUAL(asBandDesc[nIdx].pszBandName, pszBandName) )
+                            {
+                                poBand->GDALRasterBand::SetMetadataItem(
+                                    "SOLAR_IRRADIANCE", pszValue);
+                                poBand->GDALRasterBand::SetMetadataItem(
+                                    "SOLAR_IRRADIANCE_UNIT",
+                                     LaunderUnit(pszUnit));
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Add Scene Classification category values (L2A)                  */
+/* -------------------------------------------------------------------- */
+    CPLXMLNode* psSCL = CPLGetXMLNode(psRoot,
+            "=Level-2A_User_Product.General_Info."
+            "L2A_Product_Image_Characteristics.L2A_Scene_Classification_List");
+    int nSCLBand = 0;
+    for(int nBand=1;nBand<=static_cast<int>(aosBands.size());nBand++)
+    {
+        if( EQUAL(aosBands[nBand-1], "SCL") )
+        {
+            nSCLBand = nBand;
+            break;
+        }
+    }
+    if( psSCL != NULL && nSCLBand > 0 )
+    {
+        std::vector<CPLString> osCategories;
+        for(CPLXMLNode* psIter = psSCL->psChild; psIter != NULL;
+                                                     psIter = psIter->psNext )
+        {
+            if( psIter->eType != CXT_Element ||
+                !EQUAL(psIter->pszValue, "L2A_Scene_Classification_ID") )
+            {
+                continue;
+            }
+            const char* pszText = CPLGetXMLValue(psIter,
+                                        "L2A_SCENE_CLASSIFICATION_TEXT", NULL);
+            const char* pszIdx = CPLGetXMLValue(psIter,
+                                        "L2A_SCENE_CLASSIFICATION_INDEX", NULL);
+            if( pszText && pszIdx && atoi(pszIdx) >= 0 && atoi(pszIdx) < 100 )
+            {
+                int nIdx = atoi(pszIdx);
+                if( nIdx >= (int)osCategories.size() )
+                    osCategories.resize(nIdx + 1);
+                if( STARTS_WITH_CI(pszText, "SC_") )
+                    osCategories[nIdx] = pszText + 3;
+                else
+                    osCategories[nIdx] = pszText;
+            }
+        }
+        char** papszCategories =
+                    (char**)CPLCalloc(osCategories.size()+1,sizeof(char*));
+        for(size_t i=0;i<osCategories.size();i++)
+            papszCategories[i] = CPLStrdup(osCategories[i]);
+        GetRasterBand(nSCLBand)->SetCategoryNames(papszCategories);
+        CSLDestroy(papszCategories);
+    }
+}
+
+/************************************************************************/
+/*                         CreateL1CL2ADataset()                        */
+/************************************************************************/
+
+SENTINEL2Dataset* SENTINEL2Dataset::CreateL1CL2ADataset(
+                SENTINEL2Level eLevel,
+                const std::vector<CPLString>& aosGranuleList,
+                std::vector<CPLString>& aosNonJP2Files,
+                int nSubDSPrecision,
+                bool bIsPreview,
+                int nSubDSEPSGCode, /* or -1 if not known at this point */
+                bool bAlpha,
+                const std::vector<CPLString>& aosBands,
+                int nSaturatedVal,
+                int nNodataVal)
+{
+
+    /* Iterate over granule metadata to know the layer extent */
+    /* and the location of each granule */
+    double dfMinX = 1e20, dfMinY = 1e20, dfMaxX = -1e20, dfMaxY = -1e20;
+    std::vector<SENTINEL2GranuleInfo> aosGranuleInfoList;
+    const int nDesiredResolution = (bIsPreview) ? 0 : nSubDSPrecision;
+    for(size_t i=0;i<aosGranuleList.size();i++)
+    {
+        int nEPSGCode = 0;
+        double dfULX = 0.0, dfULY = 0.0;
+        int nResolution = 0;
+        int nWidth = 0, nHeight = 0;
+        if( SENTINEL2GetGranuleInfo(eLevel,
+                                    aosGranuleList[i],
+                                    nDesiredResolution,
+                                    &nEPSGCode,
+                                    &dfULX, &dfULY,
+                                    &nResolution,
+                                    &nWidth, &nHeight) &&
+            (nSubDSEPSGCode == nEPSGCode || nSubDSEPSGCode < 0) &&
+            nResolution != 0 )
+        {
+            nSubDSEPSGCode = nEPSGCode;
+            aosNonJP2Files.push_back(aosGranuleList[i]);
+
+            if( dfULX < dfMinX ) dfMinX = dfULX;
+            if( dfULY > dfMaxY ) dfMaxY = dfULY;
+            const double dfLRX = dfULX + nResolution * nWidth;
+            const double dfLRY = dfULY - nResolution * nHeight;
+            if( dfLRX > dfMaxX ) dfMaxX = dfLRX;
+            if( dfLRY < dfMinY ) dfMinY = dfLRY;
+
+            SENTINEL2GranuleInfo oGranuleInfo;
+            oGranuleInfo.osPath = CPLGetPath(aosGranuleList[i]);
+            oGranuleInfo.dfMinX = dfULX;
+            oGranuleInfo.dfMinY = dfLRY;
+            oGranuleInfo.dfMaxX = dfLRX;
+            oGranuleInfo.dfMaxY = dfULY;
+            oGranuleInfo.nWidth = nWidth / (nSubDSPrecision / nResolution);
+            oGranuleInfo.nHeight = nHeight / (nSubDSPrecision / nResolution);
+            aosGranuleInfoList.push_back(oGranuleInfo);
+        }
+    }
+    if( dfMinX > dfMaxX )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "No granule found for EPSG code %d",
+                 nSubDSEPSGCode);
+        return NULL;
+    }
+
+    const int nRasterXSize = static_cast<int>
+                                    ((dfMaxX - dfMinX) / nSubDSPrecision + 0.5);
+    const int nRasterYSize = static_cast<int>
+                                    ((dfMaxY - dfMinY) / nSubDSPrecision + 0.5);
+    SENTINEL2Dataset* poDS = new SENTINEL2Dataset(nRasterXSize, nRasterYSize);
+
+    poDS->aosNonJP2Files = aosNonJP2Files;
+
+    OGRSpatialReference oSRS;
+    char* pszProjection = NULL;
+    if( oSRS.importFromEPSG(nSubDSEPSGCode) == OGRERR_NONE &&
+        oSRS.exportToWkt(&pszProjection) == OGRERR_NONE )
+    {
+        poDS->SetProjection(pszProjection);
+        CPLFree(pszProjection);
+    }
+    else
+    {
+        CPLDebug("SENTINEL2", "Invalid EPSG code %d", nSubDSEPSGCode);
+    }
+
+    double adfGeoTransform[6];
+    adfGeoTransform[0] = dfMinX;
+    adfGeoTransform[1] = nSubDSPrecision;
+    adfGeoTransform[2] = 0;
+    adfGeoTransform[3] = dfMaxY;
+    adfGeoTransform[4] = 0;
+    adfGeoTransform[5] = -nSubDSPrecision;
+    poDS->SetGeoTransform(adfGeoTransform);
+    poDS->GDALDataset::SetMetadataItem("COMPRESSION", "JPEG2000", "IMAGE_STRUCTURE");
+    if( bIsPreview )
+        poDS->GDALDataset::SetMetadataItem("INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE");
+
+    int nBits = (bIsPreview) ? 8 : 0 /* 0 = unknown yet*/;
+    int nValMax = (bIsPreview) ? 255 : 0 /* 0 = unknown yet*/;
+    const int nBands = (bIsPreview) ? 3 : ((bAlpha) ? 1 : 0) + static_cast<int>(aosBands.size());
+    const int nAlphaBand = (bIsPreview || !bAlpha) ? 0 : nBands;
+    const GDALDataType eDT = (bIsPreview) ? GDT_Byte: GDT_UInt16;
+
+    std::map<CPLString, GDALProxyPoolDataset*> oMapPVITile;
+
+    for(int nBand=1;nBand<=nBands;nBand++)
+    {
+        VRTSourcedRasterBand* poBand;
+
+        if( nBand != nAlphaBand )
+        {
+            poBand = new VRTSourcedRasterBand( poDS, nBand, eDT,
+                                               poDS->nRasterXSize,
+                                               poDS->nRasterYSize );
+        }
+        else
+        {
+            poBand = new SENTINEL2AlphaBand ( poDS, nBand, eDT,
+                                              poDS->nRasterXSize,
+                                              poDS->nRasterYSize,
+                                              nSaturatedVal,
+                                              nNodataVal );
+        }
+
+        poDS->SetBand(nBand, poBand);
+        if( nBand == nAlphaBand )
+            poBand->SetColorInterpretation(GCI_AlphaBand);
+
+        CPLString osBandName;
+        if( nBand != nAlphaBand )
+        {
+            osBandName = aosBands[nBand-1];
+            SENTINEL2SetBandMetadata( poBand, osBandName);
+        }
+        else
+            osBandName = aosBands[0];
+
+        for(size_t iSrc=0;iSrc<aosGranuleInfoList.size();iSrc++)
+        {
+            const SENTINEL2GranuleInfo& oGranuleInfo = aosGranuleInfoList[iSrc];
+            CPLString osTile(SENTINEL2GetTilename(
+                    oGranuleInfo.osPath,
+                    CPLGetFilename(oGranuleInfo.osPath),
+                    osBandName,
+                    bIsPreview,
+                    (eLevel == SENTINEL2_L1C) ? 0 : nSubDSPrecision));
+
+            bool bTileFound = false;
+            if( nValMax == 0 )
+            {
+                /* It is supposed to be 12 bits, but some products have 15 bits */
+                if( SENTINEL2GetTileInfo(osTile, NULL, NULL, &nBits) )
+                {
+                    bTileFound = true;
+                    if( nBits <= 16 )
+                        nValMax = (1 << nBits) - 1;
+                    else
+                    {
+                        CPLDebug("SENTINEL2", "Unexpected bit depth %d", nBits);
+                        nValMax = 65535;
+                    }
+                }
+            }
+            else
+            {
+                VSIStatBufL sStat;
+                if( VSIStatExL(osTile, &sStat, VSI_STAT_EXISTS_FLAG) == 0 )
+                    bTileFound = true;
+            }
+            if( !bTileFound )
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                        "Tile %s not found on filesystem. Skipping it",
+                        osTile.c_str());
+                continue;
+            }
+
+            GDALProxyPoolDataset* proxyDS;
+            if( bIsPreview )
+            {
+                proxyDS = oMapPVITile[osTile];
+                if( proxyDS == NULL )
+                {
+                    proxyDS = new GDALProxyPoolDataset( osTile,
+                                                        oGranuleInfo.nWidth,
+                                                        oGranuleInfo.nHeight,
+                                                        GA_ReadOnly,
+                                                        TRUE);
+                    for(int j=0;j<nBands;j++)
+                        proxyDS->AddSrcBandDescription(eDT, 128, 128);
+                    oMapPVITile[osTile] = proxyDS;
+                }
+                else
+                    proxyDS->Reference();
+            }
+            else
+            {
+                proxyDS = new GDALProxyPoolDataset( osTile,
+                                                    oGranuleInfo.nWidth,
+                                                    oGranuleInfo.nHeight,
+                                                    GA_ReadOnly,
+                                                    TRUE);
+                proxyDS->AddSrcBandDescription(eDT, 128, 128);
+            }
+
+            const int nDstXOff = static_cast<int>(
+                    (oGranuleInfo.dfMinX - dfMinX) / nSubDSPrecision + 0.5);
+            const int nDstYOff = static_cast<int>(
+                    (dfMaxY - oGranuleInfo.dfMaxY) / nSubDSPrecision + 0.5);
+
+            if( nBand != nAlphaBand )
+            {
+                poBand->AddSimpleSource( proxyDS->GetRasterBand((bIsPreview) ? nBand : 1),
+                                        0, 0,
+                                        oGranuleInfo.nWidth,
+                                        oGranuleInfo.nHeight,
+                                        nDstXOff,
+                                        nDstYOff,
+                                        oGranuleInfo.nWidth,
+                                        oGranuleInfo.nHeight);
+            }
+            else
+            {
+                poBand->AddComplexSource( proxyDS->GetRasterBand(1),
+                                          0, 0,
+                                          oGranuleInfo.nWidth,
+                                          oGranuleInfo.nHeight,
+                                          nDstXOff,
+                                          nDstYOff,
+                                          oGranuleInfo.nWidth,
+                                          oGranuleInfo.nHeight,
+                                          nValMax /* offset */,
+                                          0 /* scale */);
+            }
+
+            proxyDS->Dereference();
+        }
+
+        if( (nBits % 8) != 0 )
+        {
+            poBand->SetMetadataItem("NBITS",
+                                CPLSPrintf("%d", nBits), "IMAGE_STRUCTURE");
+        }
+    }
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                      OpenL1CTileSubdataset()                         */
+/************************************************************************/
+
+GDALDataset* SENTINEL2Dataset::OpenL1CTileSubdataset( GDALOpenInfo * poOpenInfo )
+{
+    CPLString osFilename;
+    CPLAssert( STARTS_WITH_CI(poOpenInfo->pszFilename, "SENTINEL2_L1C_TILE:") );
+    osFilename = poOpenInfo->pszFilename + strlen("SENTINEL2_L1C_TILE:");
+    const char* pszPrecision = strrchr(osFilename.c_str(), ':');
+    if( pszPrecision == NULL || pszPrecision == osFilename.c_str() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Invalid syntax for SENTINEL2_L1C_TILE:");
+        return NULL;
+    }
+    const bool bIsPreview = STARTS_WITH_CI(pszPrecision + 1, "PREVIEW");
+    const int nSubDSPrecision = (bIsPreview) ? 320 : atoi(pszPrecision + 1);
+    if( !bIsPreview && nSubDSPrecision != 10 && nSubDSPrecision != 20 && nSubDSPrecision != 60 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, "Unsupported precision: %d",
+                 nSubDSPrecision);
+        return NULL;
+    }
+    osFilename.resize( pszPrecision - osFilename.c_str() );
+
+    std::set<CPLString> oSetBands;
+    CPLXMLNode* psRootMainMTD = NULL;
+    GDALDataset* poTmpDS = OpenL1CTile( osFilename, &psRootMainMTD, nSubDSPrecision, &oSetBands);
+    SENTINEL2_CPLXMLNodeHolder oXMLHolder(psRootMainMTD);
+    if( poTmpDS == NULL )
+        return NULL;
+
+    std::vector<CPLString> aosBands;
+    if( bIsPreview )
+    {
+        aosBands.push_back("04");
+        aosBands.push_back("03");
+        aosBands.push_back("02");
+    }
+    else
+    {
+        for(std::set<CPLString>::const_iterator oIterBandnames = oSetBands.begin();
+                                                oIterBandnames != oSetBands.end();
+                                            ++oIterBandnames)
+        {
+            aosBands.push_back(*oIterBandnames);
+        }
+        /* Put 2=Blue, 3=Green, 4=Band bands in RGB order for conveniency */
+        if( aosBands.size() >= 3 &&
+            aosBands[0] == "02" &&
+            aosBands[1] == "03" &&
+            aosBands[2] == "04" )
+        {
+            aosBands[0] = "04";
+            aosBands[2] = "02";
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create dataset.                                                 */
+/* -------------------------------------------------------------------- */
+
+    std::vector<CPLString> aosGranuleList;
+    aosGranuleList.push_back(osFilename);
+
+    const int nSaturatedVal = atoi(CSLFetchNameValueDef(poTmpDS->GetMetadata(),
+                                                  "SPECIAL_VALUE_SATURATED", "-1"));
+    const int nNodataVal = atoi(CSLFetchNameValueDef(poTmpDS->GetMetadata(),
+                                               "SPECIAL_VALUE_NODATA", "-1"));
+
+    const bool bAlpha =
+        CPLTestBool(SENTINEL2GetOption(poOpenInfo, "ALPHA", "FALSE"));
+
+    std::vector<CPLString> aosNonJP2Files;
+    SENTINEL2Dataset* poDS = CreateL1CL2ADataset(SENTINEL2_L1C,
+                                                 aosGranuleList,
+                                                 aosNonJP2Files,
+                                                 nSubDSPrecision,
+                                                 bIsPreview,
+                                                 -1 /*nSubDSEPSGCode*/,
+                                                 bAlpha,
+                                                 aosBands,
+                                                 nSaturatedVal,
+                                                 nNodataVal);
+    if( poDS == NULL )
+    {
+        delete poTmpDS;
+        return NULL;
+    }
+
+    // Transfer metadata
+    poDS->GDALDataset::SetMetadata( poTmpDS->GetMetadata() );
+    poDS->GDALDataset::SetMetadata( poTmpDS->GetMetadata("xml:SENTINEL2"), "xml:SENTINEL2" );
+
+    delete poTmpDS;
+
+/* -------------------------------------------------------------------- */
+/*      Add extra band metadata.                                        */
+/* -------------------------------------------------------------------- */
+    if( psRootMainMTD != NULL )
+        poDS->AddL1CL2ABandMetadata(SENTINEL2_L1C, psRootMainMTD, aosBands);
+
+/* -------------------------------------------------------------------- */
+/*      Initialize overview information.                                */
+/* -------------------------------------------------------------------- */
+    poDS->SetDescription( poOpenInfo->pszFilename );
+    CPLString osOverviewFile;
+    if( bIsPreview )
+        osOverviewFile = CPLSPrintf("%s_PREVIEW.tif.ovr",
+                                    osFilename.c_str());
+    else
+        osOverviewFile = CPLSPrintf("%s_%dm.tif.ovr",
+                                    osFilename.c_str(), nSubDSPrecision);
+    poDS->SetMetadataItem( "OVERVIEW_FILE", osOverviewFile, "OVERVIEWS" );
+    poDS->oOvManager.Initialize( poDS, ":::VIRTUAL:::" );
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                      GDALRegister_SENTINEL2()                        */
+/************************************************************************/
+
+void GDALRegister_SENTINEL2()
+{
+    if( GDALGetDriverByName( "SENTINEL2" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "SENTINEL2" );
+#ifdef GDAL_DCAP_RASTER
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+#endif
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Sentinel 2" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_sentinel2.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
+
+#ifdef GDAL_DMD_OPENOPTIONLIST
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+"<OpenOptionList>"
+"  <Option name='ALPHA' type='boolean' description='Whether to expose an alpha band' default='NO'/>"
+"</OpenOptionList>" );
+#endif
+
+    poDriver->pfnOpen = SENTINEL2Dataset::Open;
+    poDriver->pfnIdentify = SENTINEL2Dataset::Identify;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/frmts/sgi/sgidataset.cpp b/frmts/sgi/sgidataset.cpp
index c7e938f..d116a19 100644
--- a/frmts/sgi/sgidataset.cpp
+++ b/frmts/sgi/sgidataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sgidataset.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: sgidataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  SGI Image Driver
  * Purpose:  Implement SGI Image Support based on Paul Bourke's SGI Image code.
@@ -32,15 +32,14 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
 #include "cpl_port.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
 
-CPL_CVSID("$Id: sgidataset.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+#include <algorithm>
 
-CPL_C_START
-void	GDALRegister_SGI(void);
-CPL_C_END
+CPL_CVSID("$Id: sgidataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 struct ImageRec
 {
@@ -59,6 +58,7 @@ struct ImageRec
 
     VSILFILE* file;
     std::string fileName;
+    int tmpSize;
     unsigned char* tmp;
     GUInt32 rleEnd;
     int     rleTableDirty;
@@ -78,6 +78,7 @@ struct ImageRec
               colorMap(0),
               file(NULL),
               fileName(""),
+              tmpSize(0),
               tmp(NULL),
               rleEnd(0),
               rleTableDirty(FALSE),
@@ -105,85 +106,103 @@ struct ImageRec
 /************************************************************************/
 /*                            ConvertLong()                             */
 /************************************************************************/
-static void ConvertLong(GUInt32* array, GInt32 length) 
-{
 #ifdef CPL_LSB
-   GUInt32* ptr;
-   ptr = (GUInt32*)array;
+static void ConvertLong(GUInt32* array, GInt32 length)
+{
+   GUInt32* ptr = reinterpret_cast<GUInt32*>( array );
    while(length--)
      CPL_SWAP32PTR(ptr++);
-#endif
 }
+#else
+static void ConvertLong(GUInt32* /*array*/, GInt32 /*length */)
+{
+}
+#endif
 
 /************************************************************************/
 /*                            ImageGetRow()                             */
 /************************************************************************/
-static CPLErr ImageGetRow(ImageRec* image, unsigned char* buf, int y, int z) 
+static CPLErr ImageGetRow(ImageRec* image, unsigned char* buf, int y, int z)
 {
-    unsigned char *iPtr, *oPtr, pixel;
-    int count;
-
     y = image->ysize - 1 - y;
 
-    if(int(image->type) == 1)
+    if( static_cast<int>( image->type ) != 1)
     {
-        // reads row
-        VSIFSeekL(image->file, (long)image->rowStart[y+z*image->ysize], SEEK_SET);
-        if(VSIFReadL(image->tmp, 1, (GUInt32)image->rowSize[y+z*image->ysize], image->file) != (GUInt32)image->rowSize[y+z*image->ysize])
+        VSIFSeekL(image->file, 512+(y*static_cast<vsi_l_offset>(image->xsize))+(z*static_cast<vsi_l_offset>(image->xsize)*static_cast<vsi_l_offset>(image->ysize)), SEEK_SET);
+        if(VSIFReadL(buf, 1, image->xsize, image->file) != image->xsize)
         {
             CPLError(CE_Failure, CPLE_OpenFailed, "file read error: row (%d) of (%s)\n", y, image->fileName.empty() ? "none" : image->fileName.c_str());
             return CE_Failure;
         }
+        return CE_None;
+    }
 
-        // expands row
-        iPtr = image->tmp;
-        oPtr = buf;
-        int xsizeCount = 0;
-        for(;;)
-        {
-            pixel = *iPtr++;
-            count = (int)(pixel & 0x7F);
-            if(!count)
-            {
-                if(xsizeCount != image->xsize)
-                {
-                    CPLError(CE_Failure, CPLE_OpenFailed, "file read error: row (%d) of (%s)\n", y, image->fileName.empty() ? "none" : image->fileName.c_str());
-                    return CE_Failure;
-                }
-                else
-                {
-                    return CE_None;
-                }
-            }
+    // Image type 1.
 
-            if( xsizeCount + count > image->xsize )
-            {
-                CPLError(CE_Failure, CPLE_AppDefined, "Wrong repetition number that would overflow data at line %d", y);
-                return CE_Failure;
-            }
+    // reads row
+    if( image->rowSize[y+z*image->ysize] < 0 ||
+        image->rowSize[y+z*image->ysize] > image->tmpSize )
+    {
+        return CE_Failure;
+    }
+    VSIFSeekL( image->file,
+               static_cast<long>( image->rowStart[y+z*image->ysize] ),
+               SEEK_SET);
+    if( VSIFReadL( image->tmp, 1, static_cast<GUInt32>(
+           image->rowSize[y+z*image->ysize]), image->file )
+        != static_cast<GUInt32>( image->rowSize[y+z*image->ysize] ) )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "file read error: row (%d) of (%s)\n",
+                  y,
+                  image->fileName.empty() ? "none" : image->fileName.c_str() );
+        return CE_Failure;
+    }
 
-            if(pixel & 0x80)
+    // expands row
+    unsigned char *iPtr = image->tmp;
+    unsigned char *oPtr = buf;
+    int xsizeCount = 0;
+    for(;;)
+    {
+        unsigned char pixel = *iPtr++;
+        int count = static_cast<int>( pixel & 0x7F );
+        if(!count)
+        {
+            if(xsizeCount != image->xsize)
             {
-	      memcpy(oPtr, iPtr, count);
-	      iPtr += count;
+                CPLError( CE_Failure, CPLE_OpenFailed,
+                          "file read error: row (%d) of (%s)\n",
+                          y,
+                          image->fileName.empty() ? "none" : image->fileName.c_str() );
+                return CE_Failure;
             }
             else
             {
-                pixel = *iPtr++;
-		memset(oPtr, pixel, count);
+                break;
             }
-	    oPtr += count;
-	    xsizeCount += count;
         }
-    }
-    else
-    {
-        VSIFSeekL(image->file, 512+(y*image->xsize)+(z*image->xsize*image->ysize), SEEK_SET);
-        if(VSIFReadL(buf, 1, image->xsize, image->file) != image->xsize)
+
+        if( xsizeCount + count > image->xsize )
         {
-            CPLError(CE_Failure, CPLE_OpenFailed, "file read error: row (%d) of (%s)\n", y, image->fileName.empty() ? "none" : image->fileName.c_str());
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Wrong repetition number that would overflow data "
+                      "at line %d", y );
             return CE_Failure;
         }
+
+        if(pixel & 0x80)
+        {
+          memcpy(oPtr, iPtr, count);
+          iPtr += count;
+        }
+        else
+        {
+            pixel = *iPtr++;
+    	memset(oPtr, pixel, count);
+        }
+        oPtr += count;
+        xsizeCount += count;
     }
 
     return CE_None;
@@ -242,23 +261,18 @@ public:
 /*                           SGIRasterBand()                            */
 /************************************************************************/
 
-SGIRasterBand::SGIRasterBand(SGIDataset* poDS, int nBand)
+SGIRasterBand::SGIRasterBand(SGIDataset* poDSIn, int nBandIn)
 
 {
-  this->poDS = poDS;
-  this->nBand = nBand;
-  if(poDS == NULL)
-  {
-    eDataType = GDT_Byte;
-  }
-  else
-  {
-    if(int(poDS->image.bpc) == 1)
+  poDS = poDSIn;
+  nBand = nBandIn;
+
+  if(static_cast<int>( poDSIn->image.bpc ) == 1)
       eDataType = GDT_Byte;
-    else
+  else
       eDataType = GDT_Int16;
-  }
-  nBlockXSize = poDS->nRasterXSize;;
+
+  nBlockXSize = poDSIn->nRasterXSize;
   nBlockYSize = 1;
 }
 
@@ -270,14 +284,16 @@ CPLErr SGIRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff,
                                  int nBlockYOff,
 				 void*  pImage)
 {
-    SGIDataset* poGDS = (SGIDataset*) poDS;
+    SGIDataset* poGDS = reinterpret_cast<SGIDataset *>( poDS );
 
     CPLAssert(nBlockXOff == 0);
 
 /* -------------------------------------------------------------------- */
 /*      Load the desired data into the working buffer.              */
 /* -------------------------------------------------------------------- */
-    return ImageGetRow(&(poGDS->image), (unsigned char*)pImage, nBlockYOff, nBand-1);
+    return ImageGetRow( &(poGDS->image),
+                        reinterpret_cast<unsigned char*>( pImage ),
+                        nBlockYOff, nBand - 1 );
 }
 
 /************************************************************************/
@@ -288,23 +304,23 @@ CPLErr SGIRasterBand::IWriteBlock(CPL_UNUSED int nBlockXOff,
                                   int nBlockYOff,
                                   void*  pImage)
 {
-    SGIDataset* poGDS = (SGIDataset*) poDS;
-    ImageRec *image = &(poGDS->image);
-    
     CPLAssert(nBlockXOff == 0);
 
+    SGIDataset* poGDS = reinterpret_cast<SGIDataset *>( poDS);
+    ImageRec *image = &(poGDS->image);
+
 /* -------------------------------------------------------------------- */
 /*      Handle the fairly trivial non-RLE case.                         */
 /* -------------------------------------------------------------------- */
     if( image->type == 0 )
     {
-        VSIFSeekL(image->file, 
-                  512 + (nBlockYOff*image->xsize)
-                  + ((nBand-1)*image->xsize*image->ysize ), 
+        VSIFSeekL(image->file,
+                  512 + (nBlockYOff*static_cast<vsi_l_offset>(image->xsize))
+                  + ((nBand-1)*static_cast<vsi_l_offset>(image->xsize)*static_cast<vsi_l_offset>(image->ysize) ),
                   SEEK_SET);
         if(VSIFWriteL(pImage, 1, image->xsize, image->file) != image->xsize)
         {
-            CPLError(CE_Failure, CPLE_OpenFailed, 
+            CPLError(CE_Failure, CPLE_OpenFailed,
                      "file write error: row (%d)\n", nBlockYOff );
             return CE_Failure;
         }
@@ -314,9 +330,12 @@ CPLErr SGIRasterBand::IWriteBlock(CPL_UNUSED int nBlockXOff,
 /* -------------------------------------------------------------------- */
 /*      Handle RLE case.                                                */
 /* -------------------------------------------------------------------- */
-    const GByte *pabyRawBuf = (const GByte *) pImage;
-    GByte *pabyRLEBuf = (GByte *) CPLMalloc(image->xsize * 2 + 6);
-    int iX = 0, nRLEBytes = 0;
+    const GByte *pabyRawBuf = reinterpret_cast<const GByte *>( pImage );
+    GByte *pabyRLEBuf = reinterpret_cast<GByte *>(
+        CPLMalloc( image->xsize * 2 + 6 ) );
+
+    int iX = 0;
+    int nRLEBytes = 0;
 
     while( iX < image->xsize )
     {
@@ -327,22 +346,20 @@ CPLErr SGIRasterBand::IWriteBlock(CPL_UNUSED int nBlockXOff,
                && pabyRawBuf[iX + nRepeatCount] == pabyRawBuf[iX] )
             nRepeatCount++;
 
-        if( nRepeatCount > 2 
+        if( nRepeatCount > 2
             || iX + nRepeatCount == image->xsize
             || (iX + nRepeatCount < image->xsize - 2
-                && pabyRawBuf[iX + nRepeatCount + 1] 
+                && pabyRawBuf[iX + nRepeatCount + 1]
                 == pabyRawBuf[iX + nRepeatCount + 2]
-                && pabyRawBuf[iX + nRepeatCount + 1] 
+                && pabyRawBuf[iX + nRepeatCount + 1]
                 == pabyRawBuf[iX + nRepeatCount + 3]) )
         { // encode a constant run.
-            pabyRLEBuf[nRLEBytes++] = (GByte) nRepeatCount; 
+            pabyRLEBuf[nRLEBytes++] = static_cast<GByte>( nRepeatCount );
             pabyRLEBuf[nRLEBytes++] = pabyRawBuf[iX];
             iX += nRepeatCount;
         }
-        else 
-        { // copy over mixed data. 
-            nRepeatCount = 1;
-
+        else
+        { // copy over mixed data.
             for( nRepeatCount = 1;
                  iX + nRepeatCount < image->xsize && nRepeatCount < 127;
                  nRepeatCount++ )
@@ -351,18 +368,18 @@ CPLErr SGIRasterBand::IWriteBlock(CPL_UNUSED int nBlockXOff,
                     continue;
 
                 // quit if the next 3 pixels match
-                if( pabyRawBuf[iX + nRepeatCount] 
-                    == pabyRawBuf[iX + nRepeatCount+1] 
-                    && pabyRawBuf[iX + nRepeatCount] 
+                if( pabyRawBuf[iX + nRepeatCount]
+                    == pabyRawBuf[iX + nRepeatCount+1]
+                    && pabyRawBuf[iX + nRepeatCount]
                     == pabyRawBuf[iX + nRepeatCount+2] )
                     break;
             }
 
-            pabyRLEBuf[nRLEBytes++] = (GByte) (0x80 | nRepeatCount); 
-            memcpy( pabyRLEBuf + nRLEBytes, 
-                    pabyRawBuf + iX, 
+            pabyRLEBuf[nRLEBytes++] = static_cast<GByte>( 0x80 | nRepeatCount );
+            memcpy( pabyRLEBuf + nRLEBytes,
+                    pabyRawBuf + iX,
                     nRepeatCount );
-            
+
             nRLEBytes += nRepeatCount;
             iX += nRepeatCount;
         }
@@ -374,18 +391,19 @@ CPLErr SGIRasterBand::IWriteBlock(CPL_UNUSED int nBlockXOff,
 /* -------------------------------------------------------------------- */
 /*      Write RLE Buffer at end of file.                                */
 /* -------------------------------------------------------------------- */
-    int row = (image->ysize - nBlockYOff - 1) + (nBand-1) * image->ysize;
+    const int row = (image->ysize - nBlockYOff - 1) + (nBand-1) * image->ysize;
 
     VSIFSeekL(image->file, 0, SEEK_END );
 
-    image->rowStart[row] = (GUInt32) VSIFTellL( image->file );
+    image->rowStart[row] = static_cast<GUInt32>( VSIFTellL( image->file ) );
     image->rowSize[row] = nRLEBytes;
     image->rleTableDirty = TRUE;
 
-    if( (int) VSIFWriteL(pabyRLEBuf, 1, nRLEBytes, image->file) != nRLEBytes )
+    if( static_cast<int>( VSIFWriteL(pabyRLEBuf, 1, nRLEBytes, image->file) )
+        != nRLEBytes )
     {
         CPLFree( pabyRLEBuf );
-        CPLError(CE_Failure, CPLE_OpenFailed, 
+        CPLError(CE_Failure, CPLE_OpenFailed,
                  "file write error: row (%d)\n", nBlockYOff );
         return CE_Failure;
     }
@@ -402,7 +420,7 @@ CPLErr SGIRasterBand::IWriteBlock(CPL_UNUSED int nBlockXOff,
 GDALColorInterp SGIRasterBand::GetColorInterpretation()
 
 {
-    SGIDataset* poGDS = (SGIDataset*)poDS;
+    SGIDataset* poGDS = reinterpret_cast<SGIDataset *>( poDS );
 
     if(poGDS->nBands == 1)
         return GCI_GrayIndex;
@@ -473,11 +491,13 @@ SGIDataset::~SGIDataset()
     {
         CPLDebug( "SGI", "Flushing RLE offset table." );
         ConvertLong( image.rowStart, image.ysize * image.zsize );
-        ConvertLong( (GUInt32 *) image.rowSize, image.ysize * image.zsize );
+        ConvertLong( reinterpret_cast<GUInt32 *>( image.rowSize ),
+                     image.ysize * image.zsize );
 
         VSIFSeekL( fpImage, 512, SEEK_SET );
-        VSIFWriteL( image.rowStart, 4, image.ysize * image.zsize, fpImage );
-        VSIFWriteL( image.rowSize, 4, image.ysize * image.zsize, fpImage );
+        size_t nSize = static_cast<size_t>(image.ysize) * static_cast<size_t>(image.zsize);
+        VSIFWriteL( image.rowStart, 4, nSize, fpImage );
+        VSIFWriteL( image.rowSize, 4, nSize, fpImage );
         image.rleTableDirty = FALSE;
     }
 
@@ -499,11 +519,10 @@ CPLErr SGIDataset::GetGeoTransform(double * padfTransform)
     if(bGeoTransformValid)
     {
         memcpy(padfTransform, adfGeoTransform, sizeof(double)*6);
-        
         return CE_None;
     }
-    else 
-        return GDALPamDataset::GetGeoTransform(padfTransform);
+
+    return GDALPamDataset::GetGeoTransform(padfTransform);
 }
 
 /************************************************************************/
@@ -515,7 +534,7 @@ GDALDataset* SGIDataset::Open(GDALOpenInfo* poOpenInfo)
 {
 /* -------------------------------------------------------------------- */
 /*	First we check to see if the file has the expected header	*/
-/*	bytes.								*/    
+/*	bytes.								*/
 /* -------------------------------------------------------------------- */
     if(poOpenInfo->nHeaderBytes < 12)
         return NULL;
@@ -538,17 +557,15 @@ GDALDataset* SGIDataset::Open(GDALOpenInfo* poOpenInfo)
 
     if(tmpImage.bpc != 1)
     {
-        CPLError(CE_Failure, CPLE_NotSupported, 
+        CPLError(CE_Failure, CPLE_NotSupported,
                  "The SGI driver only supports 1 byte channel values.\n");
         return NULL;
     }
-  
+
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    SGIDataset* poDS;
-
-    poDS = new SGIDataset();
+    SGIDataset* poDS = new SGIDataset();
     poDS->eAccess = poOpenInfo->eAccess;
 
 /* -------------------------------------------------------------------- */
@@ -560,8 +577,8 @@ GDALDataset* SGIDataset::Open(GDALOpenInfo* poOpenInfo)
         poDS->fpImage = VSIFOpenL(poOpenInfo->pszFilename, "rb+");
     if(poDS->fpImage == NULL)
     {
-        CPLError(CE_Failure, CPLE_OpenFailed, 
-                 "VSIFOpenL(%s) failed unexpectedly in sgidataset.cpp\n%s", 
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "VSIFOpenL(%s) failed unexpectedly in sgidataset.cpp\n%s",
                  poOpenInfo->pszFilename,
                  VSIStrerror( errno ) );
         delete poDS;
@@ -572,7 +589,9 @@ GDALDataset* SGIDataset::Open(GDALOpenInfo* poOpenInfo)
 /*	Read pre-image data after ensuring the file is rewound.         */
 /* -------------------------------------------------------------------- */
     VSIFSeekL(poDS->fpImage, 0, SEEK_SET);
-    if(VSIFReadL((void*)(&(poDS->image)), 1, 12, poDS->fpImage) != 12)
+    if(VSIFReadL(reinterpret_cast<void*>( &(poDS->image) ),
+                 1, 12, poDS->fpImage)
+       != 12)
     {
         CPLError(CE_Failure, CPLE_OpenFailed, "file read error while reading header in sgidataset.cpp");
         delete poDS;
@@ -589,7 +608,7 @@ GDALDataset* SGIDataset::Open(GDALOpenInfo* poOpenInfo)
     poDS->nRasterYSize = poDS->image.ysize;
     if (poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0)
     {
-        CPLError(CE_Failure, CPLE_OpenFailed, 
+        CPLError(CE_Failure, CPLE_OpenFailed,
                      "Invalid image dimensions : %d x %d", poDS->nRasterXSize, poDS->nRasterYSize);
         delete poDS;
         return NULL;
@@ -597,17 +616,23 @@ GDALDataset* SGIDataset::Open(GDALOpenInfo* poOpenInfo)
     poDS->nBands = MAX(1,poDS->image.zsize);
     if (poDS->nBands > 256)
     {
-        CPLError(CE_Failure, CPLE_OpenFailed, 
+        CPLError(CE_Failure, CPLE_OpenFailed,
                      "Too many bands : %d", poDS->nBands);
         delete poDS;
         return NULL;
     }
 
-    int numItems = (int(poDS->image.bpc) == 1) ? 256 : 65536;
-    poDS->image.tmp = (unsigned char*)VSICalloc(poDS->image.xsize,numItems);
+    const int numItems
+        = (static_cast<int>( poDS->image.bpc ) == 1) ? 256 : 65536;
+    if( poDS->image.xsize > INT_MAX / numItems )
+    {
+        delete poDS;
+        return NULL;
+    }
+    poDS->image.tmpSize = poDS->image.xsize * numItems;
+    poDS->image.tmp = (unsigned char*)VSI_CALLOC_VERBOSE(poDS->image.xsize,numItems);
     if (poDS->image.tmp == NULL)
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
         delete poDS;
         return NULL;
     }
@@ -615,37 +640,40 @@ GDALDataset* SGIDataset::Open(GDALOpenInfo* poOpenInfo)
 /* -------------------------------------------------------------------- */
 /*      Read RLE Pointer tables.                                        */
 /* -------------------------------------------------------------------- */
-    if(int(poDS->image.type) == 1) // RLE compressed
+    if( static_cast<int>( poDS->image.type ) == 1 ) // RLE compressed
     {
-        int x = poDS->image.ysize * poDS->nBands * sizeof(GUInt32);
-        poDS->image.rowStart = (GUInt32*)VSIMalloc2(poDS->image.ysize, poDS->nBands * sizeof(GUInt32));
-        poDS->image.rowSize = (GInt32*)VSIMalloc2(poDS->image.ysize, poDS->nBands * sizeof(GUInt32));
+        const size_t x = static_cast<size_t>(poDS->image.ysize) * poDS->nBands * sizeof(GUInt32);
+        poDS->image.rowStart = reinterpret_cast<GUInt32*>(
+            VSI_MALLOC2_VERBOSE(poDS->image.ysize, poDS->nBands * sizeof(GUInt32) ) );
+        poDS->image.rowSize = reinterpret_cast<GInt32 *>(
+            VSI_MALLOC2_VERBOSE(poDS->image.ysize, poDS->nBands * sizeof(GUInt32) ) );
         if (poDS->image.rowStart == NULL || poDS->image.rowSize == NULL)
         {
-            CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
             delete poDS;
             return NULL;
         }
         memset(poDS->image.rowStart, 0, x);
         memset(poDS->image.rowSize, 0, x);
-        poDS->image.rleEnd = 512 + (2 * x);
+        poDS->image.rleEnd = static_cast<GUInt32>(512 + (2 * x));
         VSIFSeekL(poDS->fpImage, 512, SEEK_SET);
-        if((int) VSIFReadL(poDS->image.rowStart, 1, x, poDS->image.file) != x)
+        if( VSIFReadL(poDS->image.rowStart, 1, x, poDS->image.file ) != x )
         {
             delete poDS;
-            CPLError(CE_Failure, CPLE_OpenFailed, 
+            CPLError(CE_Failure, CPLE_OpenFailed,
                      "file read error while reading start positions in sgidataset.cpp");
             return NULL;
         }
-        if((int) VSIFReadL(poDS->image.rowSize, 1, x, poDS->image.file) != x)
+        if( VSIFReadL(poDS->image.rowSize, 1, x, poDS->image.file) != x)
         {
             delete poDS;
-            CPLError(CE_Failure, CPLE_OpenFailed, 
+            CPLError(CE_Failure, CPLE_OpenFailed,
                      "file read error while reading row lengths in sgidataset.cpp");
             return NULL;
         }
-        ConvertLong(poDS->image.rowStart, x/(int)sizeof(GUInt32));
-        ConvertLong((GUInt32*)poDS->image.rowSize, x/(int)sizeof(GInt32));
+        ConvertLong(poDS->image.rowStart,
+                    static_cast<int>(x / static_cast<int>( sizeof(GUInt32))) );
+        ConvertLong(reinterpret_cast<GUInt32 *>( poDS->image.rowSize ),
+                    static_cast<int>(x / static_cast<int>( sizeof(GInt32) )) );
     }
     else // uncompressed.
     {
@@ -662,8 +690,8 @@ GDALDataset* SGIDataset::Open(GDALOpenInfo* poOpenInfo)
 /* -------------------------------------------------------------------- */
 /*      Check for world file.                                           */
 /* -------------------------------------------------------------------- */
-    poDS->bGeoTransformValid = 
-        GDALReadWorldFile(poOpenInfo->pszFilename, ".wld", 
+    poDS->bGeoTransformValid =
+        GDALReadWorldFile(poOpenInfo->pszFilename, ".wld",
                           poDS->adfGeoTransform);
 
 /* -------------------------------------------------------------------- */
@@ -707,18 +735,16 @@ GDALDataset *SGIDataset::Create( const char * pszFilename,
     VSILFILE *fp = VSIFOpenL( pszFilename, "w" );
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Failed to create file '%s': %s", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to create file '%s': %s",
                   pszFilename, VSIStrerror( errno ) );
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Prepare and write 512 byte header.                              */
 /* -------------------------------------------------------------------- */
     GByte abyHeader[512];
-    GInt16 nShortValue;
-    GInt32 nIntValue;
 
     memset( abyHeader, 0, 512 );
 
@@ -727,12 +753,13 @@ GDALDataset *SGIDataset::Create( const char * pszFilename,
     abyHeader[2] = 1; // RLE
     abyHeader[3] = 1;  // 8bit
 
+    GInt16 nShortValue;
     if( nBands == 1 )
         nShortValue = CPL_MSBWORD16(2);
     else
         nShortValue = CPL_MSBWORD16(3);
     memcpy( abyHeader + 4, &nShortValue, 2 );
-    
+
     nShortValue = CPL_MSBWORD16(nXSize);
     memcpy( abyHeader + 6, &nShortValue, 2 );
 
@@ -742,26 +769,26 @@ GDALDataset *SGIDataset::Create( const char * pszFilename,
     nShortValue = CPL_MSBWORD16(nBands);
     memcpy( abyHeader + 10, &nShortValue, 2 );
 
-    nIntValue = CPL_MSBWORD32(0);
+    GInt32 nIntValue = CPL_MSBWORD32(0);
     memcpy( abyHeader + 12, &nIntValue, 4 );
-    
+
     nIntValue = CPL_MSBWORD32(255);
     memcpy( abyHeader + 16, &nIntValue, 4 );
-    
+
     VSIFWriteL( abyHeader, 1, 512, fp );
 
 /* -------------------------------------------------------------------- */
 /*      Create our RLE compressed zero-ed dummy line.                   */
 /* -------------------------------------------------------------------- */
-    GByte *pabyRLELine;
-    GInt32 nRLEBytes = 0;
-    int   nPixelsRemaining = nXSize;
+    GByte *pabyRLELine = reinterpret_cast<GByte *>(
+        CPLMalloc( ( nXSize / 127 ) * 2 + 4 ) );
 
-    pabyRLELine = (GByte *) CPLMalloc((nXSize/127) * 2 + 4);
-    
+    int nPixelsRemaining = nXSize;
+    GInt32 nRLEBytes = 0;
     while( nPixelsRemaining > 0 )
     {
-        pabyRLELine[nRLEBytes] = (GByte) MIN(127,nPixelsRemaining);
+        pabyRLELine[nRLEBytes] = static_cast<GByte>(
+            std::min( 127, nPixelsRemaining  ) );
         pabyRLELine[nRLEBytes+1] = 0;
         nPixelsRemaining -= pabyRLELine[nRLEBytes];
 
@@ -772,28 +799,28 @@ GDALDataset *SGIDataset::Create( const char * pszFilename,
 /*      Prepare and write RLE offset/size tables with everything        */
 /*      zeroed indicating dummy lines.                                  */
 /* -------------------------------------------------------------------- */
-    int i;
-    int nTableLen = nYSize * nBands;
+    const int nTableLen = nYSize * nBands;
     GInt32 nDummyRLEOffset = 512 + 4 * nTableLen * 2;
 
     CPL_MSBPTR32( &nRLEBytes );
     CPL_MSBPTR32( &nDummyRLEOffset );
-    
-    for( i = 0; i < nTableLen; i++ )
+
+    for( int i = 0; i < nTableLen; i++ )
         VSIFWriteL( &nDummyRLEOffset, 1, 4, fp );
 
-    for( i = 0; i < nTableLen; i++ )
+    for( int i = 0; i < nTableLen; i++ )
         VSIFWriteL( &nRLEBytes, 1, 4, fp );
 
 /* -------------------------------------------------------------------- */
 /*      write the dummy RLE blank line.                                 */
 /* -------------------------------------------------------------------- */
     CPL_MSBPTR32( &nRLEBytes );
-    if( (GInt32) VSIFWriteL( pabyRLELine, 1, nRLEBytes, fp ) != nRLEBytes )
+    if( static_cast<GInt32>( VSIFWriteL( pabyRLELine, 1, nRLEBytes, fp ) )
+        != nRLEBytes )
     {
-        CPLError( CE_Failure, CPLE_FileIO,  
-                  "Failure writing SGI file '%s'.\n%s", 
-                  pszFilename, 
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Failure writing SGI file '%s'.\n%s",
+                  pszFilename,
                   VSIStrerror( errno ) );
         return NULL;
     }
@@ -801,33 +828,32 @@ GDALDataset *SGIDataset::Create( const char * pszFilename,
     VSIFCloseL( fp );
     CPLFree( pabyRLELine );
 
-    return (GDALDataset*) GDALOpen( pszFilename, GA_Update );
+    return reinterpret_cast<GDALDataset *>(
+        GDALOpen( pszFilename, GA_Update ) );
 }
 
 /************************************************************************/
-/*                         GDALRegister_SGI()                          */
+/*                         GDALRegister_SGI()                           */
 /************************************************************************/
 
 void GDALRegister_SGI()
 
 {
-    GDALDriver*  poDriver;
+    if( GDALGetDriverByName( "SGI" ) != NULL )
+        return;
 
-    if(GDALGetDriverByName("SGI") == NULL)
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription("SGI");
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, 
-                                  "SGI Image File Format 1.0");
-        poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "rgb");
-        poDriver->SetMetadataItem(GDAL_DMD_MIMETYPE, "image/rgb");
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "frmt_various.html#SGI" );
-        poDriver->pfnOpen = SGIDataset::Open;
-        poDriver->pfnCreate = SGIDataset::Create;
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte" );
-        GetGDALDriverManager()->RegisterDriver(poDriver);
-    }
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription("SGI");
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "SGI Image File Format 1.0" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "rgb" );
+    poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/rgb" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#SGI" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte" );
+
+    poDriver->pfnOpen = SGIDataset::Open;
+    poDriver->pfnCreate = SGIDataset::Create;
+
+    GetGDALDriverManager()->RegisterDriver(poDriver);
 }
diff --git a/frmts/srtmhgt/srtmhgtdataset.cpp b/frmts/srtmhgt/srtmhgtdataset.cpp
index 9a0044c..8638f38 100644
--- a/frmts/srtmhgt/srtmhgtdataset.cpp
+++ b/frmts/srtmhgt/srtmhgtdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: srtmhgtdataset.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: srtmhgtdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  SRTM HGT Driver
  * Purpose:  SRTM HGT File Read Support.
@@ -31,18 +31,17 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
 #include "cpl_port.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
-#define SRTMHG_NODATA_VALUE -32768
+#include <cmath>
 
-CPL_CVSID("$Id: srtmhgtdataset.cpp 28053 2014-12-04 09:31:07Z rouault $");
+static const GInt16 SRTMHG_NODATA_VALUE = -32768;
 
-CPL_C_START
-void	GDALRegister_SRTMHGT(void);
-CPL_C_END
+CPL_CVSID("$Id: srtmhgtdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -66,11 +65,11 @@ class SRTMHGTDataset : public GDALPamDataset
 
     virtual const char *GetProjectionRef(void);
     virtual CPLErr GetGeoTransform(double*);
-    
+
     static int Identify( GDALOpenInfo * poOpenInfo );
     static GDALDataset* Open(GDALOpenInfo*);
-    static GDALDataset* CreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
-                                    int bStrict, char ** papszOptions, 
+    static GDALDataset* CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
+                                    int bStrict, char ** papszOptions,
                                     GDALProgressFunc pfnProgress, void * pProgressData );
 
 };
@@ -105,15 +104,15 @@ class SRTMHGTRasterBand : public GDALPamRasterBand
 /*                           SRTMHGTRasterBand()                            */
 /************************************************************************/
 
-SRTMHGTRasterBand::SRTMHGTRasterBand(SRTMHGTDataset* poDS, int nBand)
+SRTMHGTRasterBand::SRTMHGTRasterBand(SRTMHGTDataset* poDSIn, int nBandIn) :
+    bNoDataSet(TRUE),
+    dfNoDataValue(SRTMHG_NODATA_VALUE)
 {
-  this->poDS = poDS;
-  this->nBand = nBand;
-  eDataType = GDT_Int16;
-  nBlockXSize = poDS->nRasterXSize;
-  nBlockYSize = 1;
-  bNoDataSet = TRUE;
-  dfNoDataValue = SRTMHG_NODATA_VALUE;
+    poDS = poDSIn;
+    nBand = nBandIn;
+    eDataType = GDT_Int16;
+    nBlockXSize = poDSIn->nRasterXSize;
+    nBlockYSize = 1;
 }
 
 /************************************************************************/
@@ -123,7 +122,7 @@ SRTMHGTRasterBand::SRTMHGTRasterBand(SRTMHGTDataset* poDS, int nBand)
 CPLErr SRTMHGTRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff,
                                      void* pImage)
 {
-  SRTMHGTDataset* poGDS = (SRTMHGTDataset*) poDS;
+  SRTMHGTDataset* poGDS = reinterpret_cast<SRTMHGTDataset *>( poDS );
 
   CPLAssert(nBlockXOff == 0);
   if(nBlockXOff != 0)
@@ -154,7 +153,7 @@ CPLErr SRTMHGTRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff,
 
 CPLErr SRTMHGTRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff, void* pImage)
 {
-    SRTMHGTDataset* poGDS = (SRTMHGTDataset*) poDS;
+    SRTMHGTDataset* poGDS = reinterpret_cast<SRTMHGTDataset *>( poDS );
 
     CPLAssert(nBlockXOff == 0);
     if(nBlockXOff != 0)
@@ -171,9 +170,11 @@ CPLErr SRTMHGTRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff, void* pIma
 #ifdef CPL_LSB
     memcpy(poGDS->panBuffer, pImage, nBlockXSize*sizeof(GInt16));
     GDALSwapWords(poGDS->panBuffer, 2, nBlockXSize, 2);
-    VSIFWriteL((unsigned char*)poGDS->panBuffer, nBlockXSize, 2, poGDS->fpImage);
+    VSIFWriteL( reinterpret_cast<unsigned char *>( poGDS->panBuffer ),
+                nBlockXSize, 2, poGDS->fpImage );
 #else
-    VSIFWriteL((unsigned char*)pImage, nBlockXSize, 2, poGDS->fpImage);
+    VSIFWriteL( reinterpret_cast<unsigned char *>( pImage ),
+                nBlockXSize, 2, poGDS->fpImage );
 #endif
 
     return CE_None;
@@ -211,7 +212,9 @@ GDALColorInterp SRTMHGTRasterBand::GetColorInterpretation()
 /*                            SRTMHGTDataset()                              */
 /************************************************************************/
 
-SRTMHGTDataset::SRTMHGTDataset()
+SRTMHGTDataset::SRTMHGTDataset() :
+    fpImage(NULL),
+    panBuffer(NULL)
 {
   adfGeoTransform[0] = 0.0;
   adfGeoTransform[1] = 1.0;
@@ -219,8 +222,6 @@ SRTMHGTDataset::SRTMHGTDataset()
   adfGeoTransform[3] = 0.0;
   adfGeoTransform[4] = 0.0;
   adfGeoTransform[5] = 1.0;
-  fpImage = NULL;
-  panBuffer = NULL;
 }
 
 /************************************************************************/
@@ -263,12 +264,12 @@ int SRTMHGTDataset::Identify( GDALOpenInfo * poOpenInfo )
 
 {
   const char* fileName = CPLGetFilename(poOpenInfo->pszFilename);
-  if( strlen(fileName) < 11 || !EQUALN(&fileName[7], ".hgt", 4) )
+  if( strlen(fileName) < 11 || !STARTS_WITH_CI(&fileName[7], ".hgt") )
     return FALSE;
 
 /* -------------------------------------------------------------------- */
 /*	We check the file size to see if it is 25,934,402 bytes	        */
-/*	(SRTM 1) or 2,884,802 bytes (SRTM 3)				*/    
+/*	(SRTM 1) or 2,884,802 bytes (SRTM 3)				*/
 /* -------------------------------------------------------------------- */
   VSIStatBufL fileStat;
 
@@ -288,7 +289,7 @@ GDALDataset* SRTMHGTDataset::Open(GDALOpenInfo* poOpenInfo)
 {
   if (!Identify(poOpenInfo))
       return NULL;
-  
+
   const char* fileName = CPLGetFilename(poOpenInfo->pszFilename);
 
   char latLonValueString[4];
@@ -316,32 +317,37 @@ GDALDataset* SRTMHGTDataset::Open(GDALOpenInfo* poOpenInfo)
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-  SRTMHGTDataset* poDS;
-
-  poDS = new SRTMHGTDataset();
+  SRTMHGTDataset* poDS  = new SRTMHGTDataset();
 
 /* -------------------------------------------------------------------- */
 /*      Open the file using the large file api.                         */
 /* -------------------------------------------------------------------- */
-  poDS->fpImage = VSIFOpenL(poOpenInfo->pszFilename, (poOpenInfo->eAccess == GA_Update) ? "rb+" : "rb");
+  poDS->fpImage = VSIFOpenL(
+      poOpenInfo->pszFilename,
+      (poOpenInfo->eAccess == GA_Update) ? "rb+" : "rb" );
   if(poDS->fpImage == NULL)
   {
-    CPLError(CE_Failure, CPLE_OpenFailed, "VSIFOpenL(%s) failed unexpectedly in srtmhgtdataset.cpp", poOpenInfo->pszFilename);
-    return NULL;
+      CPLError( CE_Failure, CPLE_OpenFailed,
+                "VSIFOpenL(%s) failed unexpectedly in srtmhgtdataset.cpp",
+                poOpenInfo->pszFilename );
+      delete poDS;
+      return NULL;
   }
 
   VSIStatBufL fileStat;
   if(VSIStatL(poOpenInfo->pszFilename, &fileStat) != 0)
   {
+      delete poDS;
       return NULL;
   }
-  int numPixels = (fileStat.st_size == 25934402) ? 3601 : /* 2884802 */ 1201;
+  const int numPixels = (fileStat.st_size == 25934402) ? 3601 : /* 2884802 */ 1201;
 
   poDS->eAccess = poOpenInfo->eAccess;
 #ifdef CPL_LSB
   if(poDS->eAccess == GA_Update)
   {
-      poDS->panBuffer = (GInt16*) CPLMalloc(numPixels * sizeof(GInt16));
+      poDS->panBuffer
+          = reinterpret_cast<GInt16 *>( CPLMalloc(numPixels * sizeof(GInt16)) );
   }
 #endif
 
@@ -360,7 +366,7 @@ GDALDataset* SRTMHGTDataset::Open(GDALOpenInfo* poOpenInfo)
   poDS->adfGeoTransform[5] = -1.0 / (numPixels-1);
 
   poDS->SetMetadataItem( GDALMD_AREA_OR_POINT, GDALMD_AOP_POINT );
-  
+
 /* -------------------------------------------------------------------- */
 /*      Create band information object.                                 */
 /* -------------------------------------------------------------------- */
@@ -392,25 +398,22 @@ GDALDataset * SRTMHGTDataset::CreateCopy( const char * pszFilename,
                                           GDALProgressFunc pfnProgress,
                                           void * pProgressData )
 {
-    int  nBands = poSrcDS->GetRasterCount();
-    int  nXSize = poSrcDS->GetRasterXSize();
-    int  nYSize = poSrcDS->GetRasterYSize();
-
     if( pfnProgress && !pfnProgress( 0.0, NULL, pProgressData ) )
         return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Some some rudimentary checks                                    */
 /* -------------------------------------------------------------------- */
+    const int nBands = poSrcDS->GetRasterCount();
     if (nBands == 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "SRTMHGT driver does not support source dataset with zero band.\n");
         return NULL;
     }
     else if (nBands != 1)
     {
-        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, 
+        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
                   "SRTMHGT driver only uses the first band of the dataset.\n");
         if (bStrict)
             return NULL;
@@ -420,42 +423,46 @@ GDALDataset * SRTMHGTDataset::CreateCopy( const char * pszFilename,
 /*      Checks the input SRS                                            */
 /* -------------------------------------------------------------------- */
     OGRSpatialReference ogrsr_input;
-    OGRSpatialReference ogrsr_wgs84;
-    char* c = (char*)poSrcDS->GetProjectionRef();
+    char* c = const_cast<char *>( poSrcDS->GetProjectionRef() );
     ogrsr_input.importFromWkt(&c);
+
+    OGRSpatialReference ogrsr_wgs84;
     ogrsr_wgs84.SetWellKnownGeogCS( "WGS84" );
+
     if ( ogrsr_input.IsSameGeogCS(&ogrsr_wgs84) == FALSE)
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
-                  "The source projection coordinate system is %s. Only WGS 84 is supported.\n"
-                  "The SRTMHGT driver will generate a file as if the source was WGS 84 projection coordinate system.",
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "The source projection coordinate system is %s. Only WGS 84 "
+                  "is supported.\nThe SRTMHGT driver will generate a file as "
+                  "if the source was WGS 84 projection coordinate system.",
                   poSrcDS->GetProjectionRef() );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Work out the LL origin.                                         */
 /* -------------------------------------------------------------------- */
-    int  nLLOriginLat, nLLOriginLong;
     double adfGeoTransform[6];
-
     if (poSrcDS->GetGeoTransform( adfGeoTransform ) != CE_None)
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Source image must have a geo transform matrix.");
         return NULL;
     }
 
-    nLLOriginLat = (int) 
-        floor(adfGeoTransform[3] 
-              + poSrcDS->GetRasterYSize() * adfGeoTransform[5] + 0.5);
+    const int nLLOriginLat = static_cast<int>(
+        std::floor(adfGeoTransform[3]
+              + poSrcDS->GetRasterYSize() * adfGeoTransform[5] + 0.5) );
 
-    nLLOriginLong = (int) floor(adfGeoTransform[0] + 0.5);
+    int nLLOriginLong = static_cast<int>(
+        std::floor(adfGeoTransform[0] + 0.5) );
 
-    if (fabs(nLLOriginLat - (adfGeoTransform[3] 
-              + (poSrcDS->GetRasterYSize() - 0.5) * adfGeoTransform[5])) > 1e-10 ||
-        fabs(nLLOriginLong - (adfGeoTransform[0] + 0.5 * adfGeoTransform[1])) > 1e-10)
+    if (std::abs(nLLOriginLat - (
+            adfGeoTransform[3] + (poSrcDS->GetRasterYSize() - 0.5 )
+            * adfGeoTransform[5] ) ) > 1e-10 ||
+        std::abs(nLLOriginLong - (
+            adfGeoTransform[0] + 0.5 * adfGeoTransform[1])) > 1e-10 )
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                "The corner coordinates of the source are not properly "
                "aligned on plain latitude/longitude boundaries.");
     }
@@ -463,9 +470,12 @@ GDALDataset * SRTMHGTDataset::CreateCopy( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Check image dimensions.                                         */
 /* -------------------------------------------------------------------- */
+    const int nXSize = poSrcDS->GetRasterXSize();
+    const int nYSize = poSrcDS->GetRasterYSize();
+
     if (!((nXSize == 1201 && nYSize == 1201) || (nXSize == 3601 && nYSize == 3601)))
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Image dimensions should be 1201x1201 or 3601x3601.");
         return NULL;
     }
@@ -481,7 +491,7 @@ GDALDataset * SRTMHGTDataset::CreateCopy( const char * pszFilename,
              (nLLOriginLong >= 0) ? nLLOriginLong : -nLLOriginLong);
     if (!EQUAL(expectedFileName, CPLGetFilename(pszFilename)))
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "Expected output filename is %s.", expectedFileName);
     }
 
@@ -496,7 +506,8 @@ GDALDataset * SRTMHGTDataset::CreateCopy( const char * pszFilename,
         return NULL;
     }
 
-    GInt16* panData = (GInt16*) CPLMalloc(sizeof(GInt16) * nXSize);
+    GInt16* panData
+        = reinterpret_cast<GInt16 *>( CPLMalloc(sizeof(GInt16) * nXSize) );
     GDALRasterBand* poSrcBand = poSrcDS->GetRasterBand(1);
 
     int bSrcBandHasNoData;
@@ -504,9 +515,14 @@ GDALDataset * SRTMHGTDataset::CreateCopy( const char * pszFilename,
 
     for( int iY = 0; iY < nYSize; iY++ )
     {
-        poSrcBand->RasterIO( GF_Read, 0, iY, nXSize, 1,
-                            (void *) panData, nXSize, 1,
-                            GDT_Int16, 0, 0, NULL );
+        if( poSrcBand->RasterIO( GF_Read, 0, iY, nXSize, 1,
+                                 reinterpret_cast<void *>( panData ), nXSize, 1,
+                                 GDT_Int16, 0, 0, NULL ) != CE_None )
+        {
+            VSIFCloseL(fp);
+            CPLFree( panData );
+            return NULL;
+        }
 
         /* Translate nodata values */
         if (bSrcBandHasNoData && srcBandNoData != SRTMHG_NODATA_VALUE)
@@ -532,9 +548,10 @@ GDALDataset * SRTMHGTDataset::CreateCopy( const char * pszFilename,
             return NULL;
         }
 
-        if( pfnProgress && !pfnProgress((iY+1) / (double) nYSize, NULL, pProgressData ) )
+        if( pfnProgress && !pfnProgress( (iY+1) / static_cast<double>( nYSize ),
+                                         NULL, pProgressData ) )
         {
-            CPLError( CE_Failure, CPLE_UserInterrupt, 
+            CPLError( CE_Failure, CPLE_UserInterrupt,
                         "User terminated CreateCopy()" );
             VSIFCloseL(fp);
             CPLFree( panData );
@@ -548,8 +565,8 @@ GDALDataset * SRTMHGTDataset::CreateCopy( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Reopen and copy missing information into a PAM file.            */
 /* -------------------------------------------------------------------- */
-    GDALPamDataset *poDS = (GDALPamDataset *) 
-        GDALOpen( pszFilename, GA_ReadOnly );
+    GDALPamDataset *poDS = reinterpret_cast<GDALPamDataset *>(
+        GDALOpen( pszFilename, GA_ReadOnly ) );
 
     if( poDS )
         poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT);
@@ -558,24 +575,23 @@ GDALDataset * SRTMHGTDataset::CreateCopy( const char * pszFilename,
 }
 
 /************************************************************************/
-/*                         GDALRegister_SRTMHGT()                          */
+/*                         GDALRegister_SRTMHGT()                       */
 /************************************************************************/
 void GDALRegister_SRTMHGT()
 {
-  GDALDriver*  poDriver;
-
-  if(GDALGetDriverByName("SRTMHGT") == NULL)
-  {
-    poDriver = new GDALDriver();
-    poDriver->SetDescription("SRTMHGT");
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "SRTMHGT File Format");
-    poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "hgt");
-    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, 
-                              "frmt_various.html#SRTMHGT" );
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte Int16 UInt16" );
-
+    if( GDALGetDriverByName( "SRTMHGT" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "SRTMHGT" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "SRTMHGT File Format");
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "hgt");
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_various.html#SRTMHGT" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte Int16 UInt16" );
     poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
     poDriver->pfnIdentify = SRTMHGTDataset::Identify;
@@ -583,5 +599,4 @@ void GDALRegister_SRTMHGT()
     poDriver->pfnCreateCopy = SRTMHGTDataset::CreateCopy;
 
     GetGDALDriverManager()->RegisterDriver(poDriver);
-  }
 }
diff --git a/frmts/terragen/frmt_terragen.html b/frmts/terragen/frmt_terragen.html
index ecaa9fc..b3756de 100644
--- a/frmts/terragen/frmt_terragen.html
+++ b/frmts/terragen/frmt_terragen.html
@@ -7,9 +7,9 @@
 
 <h1>Terragen --- Terragen™ Terrain File</h1>
 
-Terragen terrain files store 16-bit elevation values with 
+Terragen terrain files store 16-bit elevation values with
 optional gridspacing (but not positioning).
-The file extension for Terragen heightfields is "TER" or "TERRAIN" (which 
+The file extension for Terragen heightfields is "TER" or "TERRAIN" (which
 in the former case is the same as Leveller, but the driver only recognizes Terragen files). The driver ID is "Terragen".
 The dataset is file-based and has only one elevation band.
 Void elevations are not supported. Pixels are considered points.
@@ -17,30 +17,30 @@ Void elevations are not supported. Pixels are considered points.
 
 <h2>Reading</h2>
 <blockquote>
-<tt>dataset::GetProjectionRef()</tt> returns a local coordinate system 
+<tt>dataset::GetProjectionRef()</tt> returns a local coordinate system
 using meters.
 <p>
 <tt>band::GetUnitType()</tt> returns meters.
 <p>
-Elevations are <tt>Int16</tt>. You must use the <tt>band::GetScale()</tt> and 
+Elevations are <tt>Int16</tt>. You must use the <tt>band::GetScale()</tt> and
 <tt>band::GetOffset()</tt> to convert them to meters.
 <p> <br>
 </blockquote>
 
 <h2>Writing</h2>
 <blockquote>
-Use the <tt>Create</tt> call. Set the <tt>MINUSERPIXELVALUE</tt> option (a float) 
-to the lowest elevation of your elevation data, and 
-<tt>MAXUSERPIXELVALUE</tt> to the highest. The units must match 
+Use the <tt>Create</tt> call. Set the <tt>MINUSERPIXELVALUE</tt> option (a float)
+to the lowest elevation of your elevation data, and
+<tt>MAXUSERPIXELVALUE</tt> to the highest. The units must match
 the elevation units you will give to <tt>band::SetUnitType()</tt>.
 <p>
 Call <tt>dataset::SetProjection()</tt> and <tt>dataset::SetGeoTransform()</tt>
-with your coordinate system details. Otherwise, the driver 
-will not encode physical elevations properly. Geographic 
-(degree-based) coordinate systems will be converted to 
+with your coordinate system details. Otherwise, the driver
+will not encode physical elevations properly. Geographic
+(degree-based) coordinate systems will be converted to
 a local meter-based system.
 <p>
-To maintain precision, a best-fit baseheight and scaling will 
+To maintain precision, a best-fit baseheight and scaling will
 be used to use as much of the 16-bit range as possible.
 <p>
 Elevations are <tt>Float32</tt>.
@@ -50,10 +50,10 @@ Elevations are <tt>Float32</tt>.
 
 <h2>Roundtripping</h2>
 <blockquote>
-Errors per trip tend to be a few centimeters for elevations 
-and up to one or two meters for ground extents if 
-degree-based coordinate systems are written. Large degree-based 
-DEMs incur unavoidable distortions since the driver currently 
+Errors per trip tend to be a few centimeters for elevations
+and up to one or two meters for ground extents if
+degree-based coordinate systems are written. Large degree-based
+DEMs incur unavoidable distortions since the driver currently
 only uses meters.
 <p> <br>
 </blockquote>
@@ -63,7 +63,7 @@ only uses meters.
 <h2>History</h2>
 v1.0 (Mar 26/06): Created.<br>
 v1.1 (Apr 20/06): Added Create() support and SIZE-only read fix.<br>
-v1.2 (Jun  6/07): Improved baseheight/scale determination when writing. 
+v1.2 (Jun  6/07): Improved baseheight/scale determination when writing.
 <p>
 
 <h2>See Also:</h2>
@@ -72,7 +72,7 @@ v1.2 (Jun  6/07): Improved baseheight/scale determination when writing.
 <li> Implemented as <tt>gdal/frmts/terragen/terragendataset.cpp</tt>.<p>
 
 <li>
-See <a href="./readme.txt">readme.txt</a> 
+See <a href="./readme.txt">readme.txt</a>
 for installation and support information.<p>
 
 <li> <a href="http://www.planetside.co.uk/terragen/dev/tgterrain.html">
diff --git a/frmts/terragen/terragendataset.cpp b/frmts/terragen/terragendataset.cpp
index 57e3ecc..1750a62 100644
--- a/frmts/terragen/terragendataset.cpp
+++ b/frmts/terragen/terragendataset.cpp
@@ -5,7 +5,7 @@
  * Purpose:  Reader for Terragen TER documents
  * Author:   Ray Gardener, Daylon Graphics Ltd.
  *
- * Portions of this module derived from GDAL drivers by 
+ * Portions of this module derived from GDAL drivers by
  * Frank Warmerdam, see http://www.gdal.org
 
  rcg	apr 19/06	Fixed bug with hf size being misread by one
@@ -38,7 +38,6 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ******************************************************************************
- * 
  */
 
 /*
@@ -52,12 +51,12 @@
 	can indicate something other than 30.
 	Note that uniform scaling should be used.
 
-	The offset (base height) in the ALTW chunk 
+	The offset (base height) in the ALTW chunk
 	is in terrain units, and the scale (height scale)
 	is a normalized value using unsigned 16-bit notation.
 	The physical terrain value for a read pixel is
 		hv' = hv * scale / 65536 + offset.
-		It still needs to be scaled by SCAL to 
+		It still needs to be scaled by SCAL to
 		get to meters.
 
 	For writing:
@@ -72,20 +71,20 @@
 
 	We tell callers that:
 
-		Elevations are Int16 when reading, 
-		and Float32 when writing. We need logical 
-		elevations when writing so that we can 
-		encode them with as much precision as possible 
+		Elevations are Int16 when reading,
+		and Float32 when writing. We need logical
+		elevations when writing so that we can
+		encode them with as much precision as possible
 		when going down to physical 16-bit ints.
-		Implementing band::SetScale/SetOffset won't work because 
+		Implementing band::SetScale/SetOffset won't work because
 		it requires callers to know format write details.
-		So we've added two Create() options that let the 
-		caller tell us the span's logical extent, and with 
+		So we've added two Create() options that let the
+		caller tell us the span's logical extent, and with
 		those two values we can convert to physical pixels.
 
 		band::GetUnitType() returns meters.
 		band::GetScale() returns SCAL * (scale/65536)
-		band::GetOffset() returns SCAL * offset 
+		band::GetOffset() returns SCAL * offset
 		ds::GetProjectionRef() returns a local CS
 			using meters.
 		ds::GetGeoTransform() returns a scale matrix
@@ -94,7 +93,7 @@
 		ds::SetGeoTransform() lets us establish the
 			size of ground pixels.
 		ds::SetProjection() lets us establish what
-			units ground measures are in (also needed 
+			units ground measures are in (also needed
 			to calc the size of ground pixels).
 		band::SetUnitType() tells us what units
 			the given Float32 elevations are in.
@@ -103,45 +102,36 @@
 */
 
 #include "cpl_string.h"
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
-// CPL_CVSID("$Id: terragendataset.cpp 27942 2014-11-11 00:57:41Z rouault $");
+#include <cmath>
 
-CPL_C_START
-void	GDALRegister_Terragen(void);
-CPL_C_END
+#include <algorithm>
 
+// CPL_CVSID("$Id: terragendataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 const double kdEarthCircumPolar = 40007849;
 const double kdEarthCircumEquat = 40075004;
 
-#define str_equal(_s1, _s2)	(0 == strcmp((_s1),(_s2)))
-#define array_size(_a)		(sizeof(_a) / sizeof(_a[0]))
-
-#ifndef min
-	#define min(a, b)	( (a) < (b) ? (a) : (b) )
-#endif
-
 static double average(double a, double b)
 {
 	return 0.5 * (a + b);
 }
 
-
-static double degrees_to_radians(double d) 
+static double degrees_to_radians(double d)
 {
-	return (d * 0.017453292);
+    return d * 0.017453292;
 }
 
 static bool approx_equal(double a, double b)
 {
-	const double epsilon = 1e-5;
-	return (fabs(a-b) <= epsilon);
+    const double epsilon = 1e-5;
+    return std::abs(a-b) <= epsilon;
 }
 
 
-
 /************************************************************************/
 /* ==================================================================== */
 /*				TerragenDataset				*/
@@ -154,42 +144,39 @@ class TerragenDataset : public GDALPamDataset
 {
     friend class TerragenRasterBand;
 
-
-	double		m_dScale,
-				m_dOffset,
-				m_dSCAL, // 30.0 normally, from SCAL chunk
-	   			m_adfTransform[6],
-				m_dGroundScale,
-				m_dMetersPerGroundUnit,
-				m_dMetersPerElevUnit,
-				m_dLogSpan[2], 
-				m_span_m[2], 
-				m_span_px[2];
-
-    VSILFILE*			m_fp;
+    double		m_dScale,
+                        m_dOffset,
+                        m_dSCAL, // 30.0 normally, from SCAL chunk
+                        m_adfTransform[6],
+                        m_dGroundScale,
+                        m_dMetersPerGroundUnit,
+                        m_dMetersPerElevUnit,
+                        m_dLogSpan[2],
+                        m_span_m[2],
+                        m_span_px[2];
+
+    VSILFILE*           m_fp;
     vsi_l_offset	m_nDataOffset;
 
     GInt16		m_nHeightScale;
     GInt16		m_nBaseHeight;
 
-	char*		m_pszFilename;
+    char*		m_pszFilename;
     char*		m_pszProjection;
     char		m_szUnits[32];
 
-	bool		m_bIsGeo;
-
+    bool		m_bIsGeo;
 
     int         LoadFromFile();
 
-
 	public:
 		TerragenDataset();
 		~TerragenDataset();
-    
+
 		static GDALDataset* Open( GDALOpenInfo* );
 		static GDALDataset* Create( const char* pszFilename,
-									int nXSize, int nYSize, int nBands,
-									GDALDataType eType, char** papszOptions );
+                                            int nXSize, int nYSize, int nBands,
+                                            GDALDataType eType, char** papszOptions );
 
 		virtual CPLErr 	GetGeoTransform( double* );
 		virtual const char*	GetProjectionRef(void);
@@ -203,7 +190,7 @@ class TerragenDataset : public GDALPamDataset
 		bool put(GInt16);
 		bool put(float);
 		bool skip(size_t n) { return ( 0 == VSIFSeekL(m_fp, n, SEEK_CUR) ); }
-		bool pad(size_t n) { return this->skip(n); }
+		bool pad(size_t n) { return skip( n ); }
 
 		bool read_next_tag(char*);
 		bool write_next_tag(const char*);
@@ -227,13 +214,13 @@ class TerragenRasterBand : public GDALPamRasterBand
 
 public:
 
-    TerragenRasterBand(TerragenDataset*);
+    explicit TerragenRasterBand(TerragenDataset*);
 	virtual ~TerragenRasterBand()
 	{
 		if(m_pvLine != NULL)
 			CPLFree(m_pvLine);
 	}
-    
+
     // Geomeasure support.
     virtual CPLErr IReadBlock( int, int, void * );
     virtual const char* GetUnitType();
@@ -241,7 +228,7 @@ public:
     virtual double GetScale(int* pbSuccess = NULL);
 
     virtual CPLErr IWriteBlock( int, int, void * );
-	virtual CPLErr SetUnitType( const char* );
+    virtual CPLErr SetUnitType( const char* );
 };
 
 
@@ -249,20 +236,20 @@ public:
 /*                         TerragenRasterBand()                         */
 /************************************************************************/
 
-TerragenRasterBand::TerragenRasterBand( TerragenDataset *poDS )
+TerragenRasterBand::TerragenRasterBand( TerragenDataset *poDSIn )
 {
-	m_bFirstTime = true;
-    this->poDS = poDS;
-    this->nBand = 1;
+    m_bFirstTime = true;
+    poDS = poDSIn;
+    nBand = 1;
 
-    eDataType = poDS->GetAccess() == GA_ReadOnly 
+    eDataType = poDSIn->GetAccess() == GA_ReadOnly
 		? GDT_Int16
 		: GDT_Float32;
 
-    nBlockXSize = poDS->GetRasterXSize();
+    nBlockXSize = poDSIn->GetRasterXSize();
     nBlockYSize = 1;
 
-	m_pvLine = CPLMalloc(sizeof(GInt16) * nBlockXSize);
+    m_pvLine = CPLMalloc( sizeof(GInt16) * nBlockXSize );
 }
 
 
@@ -278,22 +265,22 @@ CPLErr TerragenRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     CPLAssert( nBlockXOff == 0  );
     CPLAssert( pImage != NULL );
 
-    TerragenDataset& ds = *(TerragenDataset *) poDS;
+    TerragenDataset& ds = *reinterpret_cast<TerragenDataset *>( poDS );
 
 /* -------------------------------------------------------------------- */
-/*      Seek to scanline.                                               
+/*      Seek to scanline.
 	Terragen is a bottom-top format, so we have to
 	invert the row location.
  -------------------------------------------------------------------- */
     const size_t rowbytes = nBlockXSize * sizeof(GInt16);
 
     if(0 != VSIFSeekL(
-           ds.m_fp, 
-           ds.m_nDataOffset + 
-			  (ds.GetRasterYSize() -1 - nBlockYOff) * rowbytes, 
+           ds.m_fp,
+           ds.m_nDataOffset +
+			  (ds.GetRasterYSize() -1 - nBlockYOff) * rowbytes,
            SEEK_SET))
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   "Terragen Seek failed:%s", VSIStrerror( errno ) );
         return CE_Failure;
     }
@@ -305,7 +292,7 @@ CPLErr TerragenRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 
     if( VSIFReadL( pImage, rowbytes, 1, ds.m_fp ) != 1 )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   "Terragen read failed:%s", VSIStrerror( errno ) );
         return CE_Failure;
     }
@@ -313,9 +300,9 @@ CPLErr TerragenRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /* -------------------------------------------------------------------- */
 /*      Swap on MSB platforms.                                          */
 /* -------------------------------------------------------------------- */
-#ifdef CPL_MSB 
+#ifdef CPL_MSB
     GDALSwapWords( pImage, sizeof(GInt16), nRasterXSize, sizeof(GInt16) );
-#endif    
+#endif
 
     return CE_None;
 }
@@ -329,7 +316,7 @@ const char *TerragenRasterBand::GetUnitType()
 {
 	// todo: Return elevation units.
 	// For Terragen documents, it's the same as the ground units.
-    TerragenDataset *poGDS = (TerragenDataset *) poDS;
+    TerragenDataset *poGDS = reinterpret_cast<TerragenDataset *>( poDS );
 
     return poGDS->m_szUnits;
 }
@@ -341,10 +328,11 @@ const char *TerragenRasterBand::GetUnitType()
 
 double TerragenRasterBand::GetScale(int* pbSuccess)
 {
-    const TerragenDataset& ds = *(TerragenDataset *) poDS;
-	if(pbSuccess != NULL)
-		*pbSuccess = TRUE;
-	return ds.m_dScale;
+    const TerragenDataset& ds = *reinterpret_cast<TerragenDataset *>( poDS );
+    if(pbSuccess != NULL)
+        *pbSuccess = TRUE;
+
+    return ds.m_dScale;
 }
 
 /************************************************************************/
@@ -353,10 +341,11 @@ double TerragenRasterBand::GetScale(int* pbSuccess)
 
 double TerragenRasterBand::GetOffset(int* pbSuccess)
 {
-    const TerragenDataset& ds = *(TerragenDataset *) poDS;
-	if(pbSuccess != NULL)
-		*pbSuccess = TRUE;
-	return ds.m_dOffset;
+    const TerragenDataset& ds = *reinterpret_cast<TerragenDataset *>( poDS );
+    if(pbSuccess != NULL)
+        *pbSuccess = TRUE;
+
+    return ds.m_dOffset;
 }
 
 
@@ -374,61 +363,53 @@ CPLErr TerragenRasterBand::IWriteBlock
 {
     CPLAssert( nBlockXOff == 0  );
     CPLAssert( pImage != NULL );
-	CPLAssert( m_pvLine != NULL );
+    CPLAssert( m_pvLine != NULL );
 
-	#define sgn(_n) ((_n) < 0 ? -1 : ((_n) > 0 ? 1 : 0) )
-	#define sround(_f)	\
-		(int)((_f) + (0.5 * sgn(_f)))
+    const size_t pixelsize = sizeof(GInt16);
 
-	const size_t pixelsize = sizeof(GInt16);
-
-
-	TerragenDataset& ds = *(TerragenDataset*)poDS;
-	if(m_bFirstTime)
-	{
+    TerragenDataset& ds = *reinterpret_cast<TerragenDataset *>(poDS );
+    if( m_bFirstTime )
+    {
 		m_bFirstTime = false;
 		ds.write_header();
 		ds.m_nDataOffset = VSIFTellL(ds.m_fp);
-	}
+    }
 	const size_t rowbytes = nBlockXSize * pixelsize;
 
-	GInt16* pLine = (GInt16*)m_pvLine;
-
+    GInt16* pLine = reinterpret_cast<GInt16 *>( m_pvLine );
 
 	if(0 == VSIFSeekL(
-       ds.m_fp, 
-       ds.m_nDataOffset + 
+       ds.m_fp,
+       ds.m_nDataOffset +
 		// Terragen is Y inverted.
-		(ds.GetRasterYSize()-1-nBlockYOff) * rowbytes, 
+		(ds.GetRasterYSize()-1-nBlockYOff) * rowbytes,
        SEEK_SET))
-	{
-		// Convert each float32 to int16.
-		float* pfImage = (float*)pImage;
-		for(size_t x = 0; x < (size_t)nBlockXSize; x++)
-		{
-			double f = pfImage[x];
-			f *= ds.m_dMetersPerElevUnit;
-			f /= ds.m_dSCAL;
-			GInt16 hv = 
-				(GInt16)((f - ds.m_nBaseHeight) *
-					65536.0 / ds.m_nHeightScale /*+ ds.m_nShift*/);
-			pLine[x] = hv;
-		}
-
-#ifdef CPL_MSB 
+    {
+        // Convert each float32 to int16.
+        float* pfImage = reinterpret_cast<float *>( pImage );
+        for( size_t x = 0; x < static_cast<size_t>( nBlockXSize ); x++ )
+        {
+            const double f = pfImage[x] * ds.m_dMetersPerElevUnit / ds.m_dSCAL;
+            const GInt16 hv = static_cast<GInt16>(
+                ( f - ds.m_nBaseHeight ) * 65536.0 / ds.m_nHeightScale
+                /*+ ds.m_nShift*/ );
+            pLine[x] = hv;
+        }
+
+#ifdef CPL_MSB
 		GDALSwapWords( m_pvLine, pixelsize, nBlockXSize, pixelsize );
-#endif    
+#endif
 		if(1 == VSIFWriteL(m_pvLine, rowbytes, 1, ds.m_fp))
 			return CE_None;
-	}
+    }
 
-	return CE_Failure;
+    return CE_Failure;
 }
 
 
 CPLErr TerragenRasterBand::SetUnitType( const char* psz )
 {
-	TerragenDataset& ds = *(TerragenDataset*)poDS;
+    TerragenDataset& ds = *reinterpret_cast<TerragenDataset *>( poDS );
 
 	if(EQUAL(psz, "m"))
 		ds.m_dMetersPerElevUnit = 1.0;
@@ -454,17 +435,14 @@ CPLErr TerragenRasterBand::SetUnitType( const char* psz )
 /*                          TerragenDataset()                           */
 /************************************************************************/
 
-TerragenDataset::TerragenDataset()
+TerragenDataset::TerragenDataset() :
+    m_dScale(0.0), m_dOffset(0.0), m_dSCAL(30.0), m_dGroundScale(0.0),
+    m_dMetersPerGroundUnit(1.0), m_dMetersPerElevUnit(0.0), m_fp(NULL),
+    m_nDataOffset(0),  m_nHeightScale(0), m_nBaseHeight(0), m_pszFilename(NULL),
+    m_pszProjection(NULL), m_bIsGeo(false)
 {
-	m_pszFilename = NULL;
-    m_fp = NULL;
-	m_bIsGeo = false;
-	m_pszProjection = NULL;
-	m_nHeightScale = 0; // fix for ticket 2119
-	m_nBaseHeight = 0;
-	m_dMetersPerGroundUnit = 1.0;
-	m_dSCAL = 30.0;
-	m_dLogSpan[0] = m_dLogSpan[1] = 0.0;
+    m_dLogSpan[0] = 0.0;
+    m_dLogSpan[1] = 0.0;
 
     m_adfTransform[0] = 0.0;
     m_adfTransform[1] = m_dSCAL;
@@ -483,23 +461,22 @@ TerragenDataset::~TerragenDataset()
 {
     FlushCache();
 
-	CPLFree(m_pszProjection);
-	CPLFree(m_pszFilename);
+    CPLFree(m_pszProjection);
+    CPLFree(m_pszFilename);
 
     if( m_fp != NULL )
         VSIFCloseL( m_fp );
 }
 
 
-
 bool TerragenDataset::write_header()
 {
-	char szHeader[16];
-	memcpy(szHeader, "TERRAGENTERRAIN ", sizeof(szHeader));
+    char szHeader[16];
+    memcpy(szHeader, "TERRAGENTERRAIN ", sizeof(szHeader));
 
-    if(1 != VSIFWriteL( (void *) szHeader, sizeof(szHeader), 1, m_fp ))
-	{
-        CPLError( CE_Failure, CPLE_FileIO, 
+    if(1 != VSIFWriteL( reinterpret_cast<void *>( szHeader ), sizeof(szHeader), 1, m_fp ))
+    {
+        CPLError( CE_Failure, CPLE_FileIO,
                   "Couldn't write to Terragen file %s.\n"
                   "Is file system full?",
                   m_pszFilename );
@@ -508,28 +485,29 @@ bool TerragenDataset::write_header()
         return false;
     }
 
-    
-// -------------------------------------------------------------------- 
+// --------------------------------------------------------------------
 //      Write out the heightfield dimensions, etc.
-// -------------------------------------------------------------------- 
+// --------------------------------------------------------------------
 
-	const int nXSize = this->GetRasterXSize();
-	const int nYSize = this->GetRasterYSize();
+    const int nXSize = GetRasterXSize();
+    const int nYSize = GetRasterYSize();
 
-	this->write_next_tag("SIZE");
-	this->put((GInt16)(min(nXSize, nYSize)-1));
-	this->pad(sizeof(GInt16));
+    write_next_tag( "SIZE" );
+    put( static_cast<GInt16>( std::min( nXSize, nYSize ) - 1 ) );
+    pad( sizeof(GInt16) );
 
-	if(nXSize != nYSize)
-	{
-		this->write_next_tag("XPTS");
-		this->put((GInt16)nXSize); this->pad(sizeof(GInt16));
-		this->write_next_tag("YPTS");
-		this->put((GInt16)nYSize); this->pad(sizeof(GInt16));
-	}
+    if(nXSize != nYSize)
+    {
+        write_next_tag( "XPTS" );
+        put( static_cast<GInt16>( nXSize ) );
+        pad( sizeof(GInt16) );
+        write_next_tag( "YPTS" );
+        put( static_cast<GInt16>( nYSize ) );
+        pad( sizeof(GInt16) );
+    }
 
 	if(m_bIsGeo)
-	{
+    {
 		/*
 			With a geographic projection (degrees),
 			m_dGroundScale will be in degrees and
@@ -537,68 +515,66 @@ bool TerragenDataset::write_header()
 			So we're going to estimate a m_dMetersPerGroundUnit
 			value here (i.e., meters per degree).
 
-			We figure out the degree size of one 
-			pixel, and then the latitude degrees 
+			We figure out the degree size of one
+			pixel, and then the latitude degrees
 			of the heightfield's center. The circumference of
 			the latitude's great circle lets us know how
-			wide the pixel is in meters, and we 
+			wide the pixel is in meters, and we
 			average that with the pixel's meter breadth,
 			which is based on the polar circumference.
 		*/
 
-		/*const double m_dDegLongPerPixel = 
+		/*const double m_dDegLongPerPixel =
 			fabs(m_adfTransform[1]);*/
 
-		const double m_dDegLatPerPixel = 
-			fabs(m_adfTransform[5]);
+        const double m_dDegLatPerPixel = std::abs(m_adfTransform[5]);
 
 		/*const double m_dCenterLongitude =
-			m_adfTransform[0] + 
+			m_adfTransform[0] +
 			(0.5 * m_dDegLongPerPixel * (nXSize-1));*/
 
 		const double m_dCenterLatitude =
-			m_adfTransform[3] + 
+			m_adfTransform[3] +
 			(0.5 * m_dDegLatPerPixel * (nYSize-1));
 
 
-		const double dLatCircum = kdEarthCircumEquat 
-			* sin(degrees_to_radians(90.0 - m_dCenterLatitude));
+        const double dLatCircum = kdEarthCircumEquat
+            * std::sin( degrees_to_radians( 90.0 - m_dCenterLatitude ) );
 
 		const double dMetersPerDegLongitude = dLatCircum / 360;
-		/*const double dMetersPerPixelX = 
+		/*const double dMetersPerPixelX =
 			(m_dDegLongPerPixel / 360) * dLatCircum;*/
 
-		const double dMetersPerDegLatitude = 
+		const double dMetersPerDegLatitude =
 			kdEarthCircumPolar / 360;
-		/*const double dMetersPerPixelY = 
+		/*const double dMetersPerPixelY =
 			(m_dDegLatPerPixel / 360) * kdEarthCircumPolar;*/
 
-		m_dMetersPerGroundUnit = 
+		m_dMetersPerGroundUnit =
 			average(dMetersPerDegLongitude, dMetersPerDegLatitude);
+    }
 
-	}
-		
 	m_dSCAL = m_dGroundScale * m_dMetersPerGroundUnit;
 
 	if(m_dSCAL != 30.0)
-	{
-		const float sc = (float)m_dSCAL;
-		this->write_next_tag("SCAL");
-		this->put(sc);
-		this->put(sc);
-		this->put(sc);
-	}
+    {
+        const float sc = static_cast<float>( m_dSCAL );
+        write_next_tag( "SCAL" );
+        put( sc );
+        put( sc );
+        put( sc );
+    }
 
-	if(!this->write_next_tag("ALTW"))
-	{
-        CPLError( CE_Failure, CPLE_FileIO, 
+    if( !write_next_tag( "ALTW" ) )
+    {
+        CPLError( CE_Failure, CPLE_FileIO,
                   "Couldn't write to Terragen file %s.\n"
                   "Is file system full?",
                   m_pszFilename );
         VSIFCloseL( m_fp );
 
         return false;
-	}
+    }
 
 	// Compute physical scales and offsets.
 	m_span_m[0] = m_dLogSpan[0] * m_dMetersPerElevUnit;
@@ -608,70 +584,69 @@ bool TerragenDataset::write_header()
 	m_span_px[1] = m_span_m[1] / m_dSCAL;
 
 	const double span_px = m_span_px[1] - m_span_px[0];
-	m_nHeightScale = (GInt16)span_px;
+    m_nHeightScale = static_cast<GInt16>( span_px );
 	if(m_nHeightScale == 0)
 		m_nHeightScale++;
 
-	#define P2L_PX(n, hs, bh)	\
-		((double)(n) / 65536.0 * (hs) + (bh))
+// TODO(schwehr): Make static functions.
+#define P2L_PX(n, hs, bh) (static_cast<double>( n ) / 65536.0 * (hs) + (bh))
 
-	#define L2P_PX(n, hs, bh)	\
-		((int)(((n)-(bh)) * 65536.0 / (hs)))
+#define L2P_PX(n, hs, bh) (static_cast<int>( ((n)-(bh)) * 65536.0 / (hs) ) )
 
 	// Increase the heightscale until the physical span
 	// fits within a 16-bit range. The smaller the logical span,
 	// the more necessary this becomes.
-	int hs, bh=0;
-	for(hs = m_nHeightScale; hs <= 32767; hs++)
-	{
-		double prevdelta = 1.0e30;
-		for(bh = -32768; bh <= 32767; bh++)
-		{
-			int nValley = L2P_PX(m_span_px[0], hs, bh);
-			if(nValley < -32768) continue;
-			int nPeak = L2P_PX(m_span_px[1], hs, bh);
-			if(nPeak > 32767) continue;
+    int hs = m_nHeightScale;
+    int bh = 0;
+    for( ; hs <= 32767; hs++)
+    {
+        double prevdelta = 1.0e30;
+        for( bh = -32768; bh <= 32767; bh++ )
+        {
+            const int nValley = L2P_PX(m_span_px[0], hs, bh);
+            if(nValley < -32768) continue;
+            const int nPeak = L2P_PX(m_span_px[1], hs, bh);
+            if(nPeak > 32767) continue;
 
 			// now see how closely the baseheight gets
 			// to the pixel span.
-			double d = P2L_PX(nValley, hs, bh);
-			double delta = fabs(d - m_span_px[0]);
+            const double d = P2L_PX(nValley, hs, bh);
+            const double delta = std::abs(d - m_span_px[0]);
 			if(delta < prevdelta) // Converging?
 				prevdelta = delta;
-			else 
+			else
 			{
 				// We're diverging, so use the previous bh
 				// and stop looking.
 				bh--;
 				break;
 			}
-		}
-		if(bh != 32768) break;
-	}
-	if(hs == 32768)
-	{
-        CPLError( CE_Failure, CPLE_FileIO, 
+        }
+        if(bh != 32768) break;
+    }
+    if(hs == 32768)
+    {
+        CPLError( CE_Failure, CPLE_FileIO,
                   "Couldn't write to Terragen file %s.\n"
                   "Cannot find adequate heightscale/baseheight combination.",
                   m_pszFilename );
         VSIFCloseL( m_fp );
 
         return false;
-	}
-		
-	m_nHeightScale = (GInt16) hs;
-	m_nBaseHeight = (GInt16) bh;
+    }
+
+    m_nHeightScale = static_cast<GInt16>( hs );
+    m_nBaseHeight = static_cast<GInt16>( bh );
 
 
-	// m_nHeightScale is the one that gives us the 
+	// m_nHeightScale is the one that gives us the
 	// widest use of the 16-bit space. However, there
 	// might be larger heightscales that, even though
 	// the reduce the space usage, give us a better fit
 	// for preserving the span extents.
 
 
-	return (this->put(m_nHeightScale) &&
-			this->put(m_nBaseHeight));
+    return put(m_nHeightScale) && put(m_nBaseHeight);
 }
 
 
@@ -720,14 +695,14 @@ bool TerragenDataset::get(float& value)
 bool TerragenDataset::put(GInt16 n)
 {
     CPL_LSBPTR16(&n);
-    return (1 == VSIFWriteL(&n, sizeof(n), 1, m_fp));
+    return 1 == VSIFWriteL(&n, sizeof(n), 1, m_fp);
 }
 
 
 bool TerragenDataset::put(float f)
 {
     CPL_LSBPTR32(&f);
-    return( 1 == VSIFWriteL(&f, sizeof(f), 1, m_fp) );
+    return 1 == VSIFWriteL(&f, sizeof(f), 1, m_fp);
 }
 
 /************************************************************************/
@@ -737,19 +712,20 @@ bool TerragenDataset::put(float f)
 
 bool TerragenDataset::read_next_tag(char* szTag)
 {
-	return (1 == VSIFReadL(szTag, 4, 1, m_fp));
+    return 1 == VSIFReadL(szTag, 4, 1, m_fp);
 }
 
 
 bool TerragenDataset::write_next_tag(const char* szTag)
 {
-	return (1 == VSIFWriteL((void*)szTag, 4, 1, m_fp));
+  return 1 == VSIFWriteL(
+      reinterpret_cast<void *>( const_cast<char *> ( szTag ) ), 4, 1, m_fp);
 }
 
 
 bool TerragenDataset::tag_is(const char* szTag, const char* sz)
 {
-	return (0 == memcmp(szTag, sz, 4));
+    return 0 == memcmp(szTag, sz, 4);
 }
 
 
@@ -760,75 +736,76 @@ bool TerragenDataset::tag_is(const char* szTag, const char* sz)
 
 int TerragenDataset::LoadFromFile()
 {
-    GUInt16	nSize, xpts=0, ypts=0;
     m_dSCAL = 30.0;
     m_nDataOffset = 0;
 
     if(0 != VSIFSeekL(m_fp, 16, SEEK_SET))
-        return 0;
+        return FALSE;
 
     char szTag[4];
-    if(!this->read_next_tag(szTag) || !tag_is(szTag, "SIZE"))
-        return 0;
+    if( !read_next_tag(szTag) || !tag_is(szTag, "SIZE") )
+        return FALSE;
 
-    if(!this->get(nSize) || !this->skip(2))
-        return 0;
+    GUInt16 nSize;
+    if( !get(nSize) || !skip(2) )
+        return FALSE;
 
-    // Set dimensions to SIZE chunk. If we don't 
+    // Set dimensions to SIZE chunk. If we don't
     // encounter XPTS/YPTS chunks, we can assume
     // the terrain to be square.
-    xpts = ypts = nSize+1;
+    GUInt16 xpts = nSize+1;
+    GUInt16 ypts = nSize+1;
 
-    while(this->read_next_tag(szTag))
+    while( read_next_tag(szTag) )
     {
-        if(this->tag_is(szTag, "XPTS"))
+        if( tag_is(szTag, "XPTS") )
         {
-            this->get(xpts);
-            if(xpts < nSize || !this->skip(2))
-                return 0;
+            get(xpts);
+            if( xpts < nSize || !skip(2) )
+                return FALSE;
             continue;
         }
 
-        if(this->tag_is(szTag, "YPTS"))
+        if( tag_is(szTag, "YPTS") )
         {
-            this->get(ypts);
-            if(ypts < nSize || !this->skip(2))
-                return 0;
+            get( ypts );
+            if( ypts < nSize || !skip(2) )
+                return FALSE;
             continue;
         }
 
-        if(this->tag_is(szTag, "SCAL"))
+        if( tag_is(szTag, "SCAL") )
         {
             float sc[3];
-            this->get(sc[0]);
-            this->get(sc[1]);
-            this->get(sc[2]);
+            get(sc[0]);
+            get(sc[1]);
+            get(sc[2]);
             m_dSCAL = sc[1];
             continue;
         }
 
-        if(this->tag_is(szTag, "CRAD"))
+        if( tag_is(szTag, "CRAD") )
         {
-            if(!this->skip(sizeof(float)))
-                return 0;
+            if( !skip(sizeof(float)) )
+                return FALSE;
             continue;
         }
-        if(this->tag_is(szTag, "CRVM"))
+        if( tag_is(szTag, "CRVM") )
         {
-            if(!this->skip(sizeof(GUInt32)))
-                return 0;
+            if( !skip(sizeof(GUInt32)) )
+                return FALSE;
             continue;
         }
-        if(this->tag_is(szTag, "ALTW"))
+        if( tag_is(szTag, "ALTW") )
         {
-            this->get(m_nHeightScale);
-            this->get(m_nBaseHeight);
+            get(m_nHeightScale);
+            get(m_nBaseHeight);
             m_nDataOffset = VSIFTellL(m_fp);
-            if(!this->skip(xpts * ypts * sizeof(GInt16)))
-                return 0;
+            if( !skip(static_cast<size_t>(xpts) * static_cast<size_t>(ypts) * sizeof(GInt16)) )
+                return FALSE;
             continue;
         }
-        if(this->tag_is(szTag, "EOF "))
+        if( tag_is(szTag, "EOF ") )
         {
             break;
         }
@@ -836,7 +813,7 @@ int TerragenDataset::LoadFromFile()
 
 
     if(xpts == 0 || ypts == 0 || m_nDataOffset == 0)
-        return 0;
+        return FALSE;
 
     nRasterXSize = xpts;
     nRasterYSize = ypts;
@@ -858,7 +835,6 @@ int TerragenDataset::LoadFromFile()
     m_adfTransform[4] = 0.0;
     m_adfTransform[5] = m_dSCAL;
 
-
 /* -------------------------------------------------------------------- */
 /*      Set projection.							*/
 /* -------------------------------------------------------------------- */
@@ -868,25 +844,22 @@ int TerragenDataset::LoadFromFile()
 
     sr.SetLocalCS("Terragen world space");
     if(OGRERR_NONE != sr.SetLinearUnits("m", 1.0))
-        return 0;
+        return FALSE;
 
     if(OGRERR_NONE != sr.exportToWkt(&m_pszProjection))
-        return 0;
+        return FALSE;
 
     return TRUE;
 }
 
-
-
-
 /************************************************************************/
 /*                           SetProjection()                            */
 /************************************************************************/
 
 CPLErr TerragenDataset::SetProjection( const char * pszNewProjection )
 {
-    // Terragen files aren't really georeferenced, but 
-    // we should get the projection's linear units so 
+    // Terragen files aren't really georeferenced, but
+    // we should get the projection's linear units so
     // that we can scale elevations correctly.
 
     //m_dSCAL = 30.0; // default
@@ -896,17 +869,17 @@ CPLErr TerragenDataset::SetProjection( const char * pszNewProjection )
 /* -------------------------------------------------------------------- */
 /*      Linear units.                                                   */
 /* -------------------------------------------------------------------- */
-    m_bIsGeo = (oSRS.IsGeographic() != FALSE);
+    m_bIsGeo = oSRS.IsGeographic() != FALSE;
     if(m_bIsGeo)
     {
-        // The caller is using degrees. We need to convert 
+        // The caller is using degrees. We need to convert
         // to meters, otherwise we can't derive a SCAL
         // value to scale elevations with.
         m_bIsGeo = true;
     }
     else
     {
-        double dfLinear = oSRS.GetLinearUnits();
+        const double dfLinear = oSRS.GetLinearUnits();
 
         if( approx_equal(dfLinear, 0.3048))
             m_dMetersPerGroundUnit = 0.3048;
@@ -927,8 +900,8 @@ const char*	TerragenDataset::GetProjectionRef(void)
 {
     if(m_pszProjection == NULL )
         return "";
-    else
-        return m_pszProjection;
+
+    return m_pszProjection;
 }
 
 /************************************************************************/
@@ -937,11 +910,11 @@ const char*	TerragenDataset::GetProjectionRef(void)
 
 CPLErr TerragenDataset::SetGeoTransform( double *padfGeoTransform )
 {
-	memcpy(m_adfTransform, padfGeoTransform, 
+	memcpy(m_adfTransform, padfGeoTransform,
 		sizeof(m_adfTransform));
 
 	// Average the projection scales.
-	m_dGroundScale = 
+	m_dGroundScale =
 		average(fabs(m_adfTransform[1]), fabs(m_adfTransform[5]));
 	return CE_None;
 }
@@ -964,48 +937,45 @@ CPLErr TerragenDataset::GetGeoTransform(double* padfTransform)
 /************************************************************************/
 GDALDataset* TerragenDataset::Create
 (
-	const char* pszFilename,
+    const char* pszFilename,
     int nXSize, int nYSize, int nBands,
-    GDALDataType eType, char** papszOptions 
+    GDALDataType eType, char** papszOptions
 )
 {
     TerragenDataset* poDS = new TerragenDataset();
 
     poDS->eAccess = GA_Update;
-	
+
 	poDS->m_pszFilename = CPLStrdup(pszFilename);
 
-	// -------------------------------------------------------------------- 
-	//      Verify input options.                                           
-	// -------------------------------------------------------------------- 
-    const char* pszValue = CSLFetchNameValue( 
-		papszOptions,"MINUSERPIXELVALUE");
+	// --------------------------------------------------------------------
+	//      Verify input options.
+	// --------------------------------------------------------------------
+    const char* pszValue = CSLFetchNameValue( papszOptions,"MINUSERPIXELVALUE");
     if( pszValue != NULL )
         poDS->m_dLogSpan[0] = CPLAtof( pszValue );
 
-    pszValue = CSLFetchNameValue( 
-		papszOptions,"MAXUSERPIXELVALUE");
+    pszValue = CSLFetchNameValue( papszOptions,"MAXUSERPIXELVALUE");
     if( pszValue != NULL )
         poDS->m_dLogSpan[1] = CPLAtof( pszValue );
 
-
-	if( poDS->m_dLogSpan[1] <= poDS->m_dLogSpan[0] )
-	{
+    if( poDS->m_dLogSpan[1] <= poDS->m_dLogSpan[0] )
+    {
         CPLError( CE_Failure, CPLE_AppDefined,
               "Inverted, flat, or unspecified span for Terragen file." );
 
-		delete poDS;
+        delete poDS;
         return NULL;
-	}
+    }
 
     if( eType != GDT_Float32 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
               "Attempt to create Terragen dataset with a non-float32\n"
               "data type (%s).\n",
-              GDALGetDataTypeName(eType) );
+                  GDALGetDataTypeName(eType) );
 
-		delete poDS;
+        delete poDS;
         return NULL;
     }
 
@@ -1020,11 +990,9 @@ GDALDataset* TerragenDataset::Create
         return NULL;
     }
 
-
-// -------------------------------------------------------------------- 
-//      Try to create the file.                                         
-// -------------------------------------------------------------------- 
-    
+// --------------------------------------------------------------------
+//      Try to create the file.
+// --------------------------------------------------------------------
 
     poDS->m_fp = VSIFOpenL( pszFilename, "wb+" );
 
@@ -1040,26 +1008,23 @@ GDALDataset* TerragenDataset::Create
     poDS->nRasterXSize = nXSize;
     poDS->nRasterYSize = nYSize;
 
-    // Don't bother writing the header here; the first 
-	// call to IWriteBlock will do that instead, since 
+    // Don't bother writing the header here; the first
+	// call to IWriteBlock will do that instead, since
 	// the elevation data's location depends on the
 	// header size.
 
 
-// -------------------------------------------------------------------- 
-//      Instance a band.                                                
-// -------------------------------------------------------------------- 
+// --------------------------------------------------------------------
+//      Instance a band.
+// --------------------------------------------------------------------
     poDS->SetBand( 1, new TerragenRasterBand( poDS ) );
-	 
 
     //VSIFClose( poDS->m_fp );
 
     //return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
-    return (GDALDataset *) poDS;
-
+    return reinterpret_cast<GDALDataset *>( poDS );
 }
 
-
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
@@ -1071,17 +1036,14 @@ GDALDataset *TerragenDataset::Open( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->nHeaderBytes < 32 )
         return NULL;
 
-    if( !EQUALN((const char *) poOpenInfo->pabyHeader, 
+    if( !EQUALN(reinterpret_cast<const char *>( poOpenInfo->pabyHeader ),
 		"TERRAGENTERRAIN ", 16) )
         return NULL;
 
-
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    TerragenDataset 	*poDS;
-
-    poDS = new TerragenDataset();
+    TerragenDataset *poDS = new TerragenDataset();
 
     // Reopen for large file access.
     if( poOpenInfo->eAccess == GA_Update )
@@ -1094,11 +1056,11 @@ GDALDataset *TerragenDataset::Open( GDALOpenInfo * poOpenInfo )
         CPLError( CE_Failure, CPLE_OpenFailed,
                   "Failed to re-open %s within Terragen driver.\n",
                   poOpenInfo->pszFilename );
+        delete poDS;
         return NULL;
     }
     poDS->eAccess = poOpenInfo->eAccess;
 
-    
 /* -------------------------------------------------------------------- */
 /*	Read the file.							*/
 /* -------------------------------------------------------------------- */
@@ -1136,30 +1098,25 @@ GDALDataset *TerragenDataset::Open( GDALOpenInfo * poOpenInfo )
 void GDALRegister_Terragen()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "Terragen" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "Terragen" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "Terragen" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, 
-                                   "ter" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Terragen heightfield" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_terragen.html" );
-
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "Terragen" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "ter" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Terragen heightfield" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_terragen.html" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "   <Option name='MINUSERPIXELVALUE' type='float' description='Lowest logical elevation'/>"
 "   <Option name='MAXUSERPIXELVALUE' type='float' description='Highest logical elevation'/>"
 "</CreationOptionList>" );
-        
-        poDriver->pfnOpen = TerragenDataset::Open;
-        poDriver->pfnCreate = TerragenDataset::Create;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    poDriver->pfnOpen = TerragenDataset::Open;
+    poDriver->pfnCreate = TerragenDataset::Create;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/til/tildataset.cpp b/frmts/til/tildataset.cpp
index e329e67..7be6cdd 100644
--- a/frmts/til/tildataset.cpp
+++ b/frmts/til/tildataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tildataset.cpp 29198 2015-05-15 08:45:00Z rouault $
+ * $Id: tildataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  EarthWatch .TIL Driver
  * Purpose:  Implementation of the TILDataset class.
@@ -28,16 +28,17 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_multiproc.h"
+#include "cpl_string.h"
+#include "cplkeywordparser.h"
+#include "gdal_mdreader.h"
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 #include "gdal_proxy.h"
 #include "ogr_spatialref.h"
-#include "cpl_string.h"
 #include "vrtdataset.h"
-#include "cpl_multiproc.h"
-#include "cplkeywordparser.h"
-#include "gdal_mdreader.h"
 
-CPL_CVSID("$Id: tildataset.cpp 29198 2015-05-15 08:45:00Z rouault $");
+CPL_CVSID("$Id: tildataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -92,16 +93,16 @@ class TILRasterBand : public GDALPamRasterBand
 /*                           TILRasterBand()                            */
 /************************************************************************/
 
-TILRasterBand::TILRasterBand( TILDataset *poTILDS, int nBand, 
-                              VRTSourcedRasterBand *poVRTBand )
+TILRasterBand::TILRasterBand( TILDataset *poTILDS, int nBandIn,
+                              VRTSourcedRasterBand *poVRTBandIn )
 
 {
-    this->poDS = poTILDS;
-    this->poVRTBand = poVRTBand;
-    this->nBand = nBand;
-    this->eDataType = poVRTBand->GetRasterDataType();
+    poDS = poTILDS;
+    poVRTBand = poVRTBandIn;
+    nBand = nBandIn;
+    eDataType = poVRTBandIn->GetRasterDataType();
 
-    poVRTBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
+    poVRTBandIn->GetBlockSize( &nBlockXSize, &nBlockYSize );
 }
 
 /************************************************************************/
@@ -123,7 +124,7 @@ CPLErr TILRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                                  void * pData, int nBufXSize, int nBufYSize,
                                  GDALDataType eBufType,
                                  GSpacing nPixelSpace, GSpacing nLineSpace,
-                                GDALRasterIOExtraArg* psExtraArg )
+                                 GDALRasterIOExtraArg* psExtraArg )
 
 {
     if(GetOverviewCount() > 0)
@@ -132,12 +133,11 @@ CPLErr TILRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                                  pData, nBufXSize, nBufYSize, eBufType,
                                  nPixelSpace, nLineSpace, psExtraArg );
     }
-    else //if not exist TIL overviews, try to use band source overviews
-    {
-        return poVRTBand->IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
+
+    // If not exist TIL overviews, try to use band source overviews.
+    return poVRTBand->IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
                                  pData, nBufXSize, nBufYSize, eBufType,
                                  nPixelSpace, nLineSpace, psExtraArg );
-    }
 }
 
 /************************************************************************/
@@ -150,12 +150,10 @@ CPLErr TILRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 /*                             TILDataset()                             */
 /************************************************************************/
 
-TILDataset::TILDataset()
-
-{
-    poVRTDS = NULL;
-    papszMetadataFiles = NULL;
-}
+TILDataset::TILDataset() :
+    poVRTDS(NULL),
+    papszMetadataFiles(NULL)
+{}
 
 /************************************************************************/
 /*                            ~TILDataset()                             */
@@ -199,14 +197,14 @@ int TILDataset::CloseDependentDatasets()
 int TILDataset::Identify( GDALOpenInfo *poOpenInfo )
 
 {
-    if( poOpenInfo->nHeaderBytes < 200 
+    if( poOpenInfo->nHeaderBytes < 200
         || !EQUAL(CPLGetExtension(poOpenInfo->pszFilename),"TIL") )
         return FALSE;
 
     if( strstr((const char *) poOpenInfo->pabyHeader,"numTiles") == NULL )
         return FALSE;
-    else
-        return TRUE;
+
+    return TRUE;
 }
 
 /************************************************************************/
@@ -224,26 +222,26 @@ GDALDataset *TILDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The TIL driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
     }
-    
+
     CPLString osDirname = CPLGetDirname(poOpenInfo->pszFilename);
 
 // get metadata reader
 
     GDALMDReaderManager mdreadermanager;
-    GDALMDReaderBase* mdreader = mdreadermanager.GetReader(poOpenInfo->pszFilename, 
+    GDALMDReaderBase* mdreader = mdreadermanager.GetReader(poOpenInfo->pszFilename,
                                          poOpenInfo->GetSiblingFiles(), MDR_DG);
-                                              
-    if(NULL == mdreader)    
+
+    if(NULL == mdreader)
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
                   "Unable to open .TIL dataset due to missing metadata file." );
         return NULL;
-    }                                     
+    }
 /* -------------------------------------------------------------------- */
 /*      Try to find the corresponding .IMD file.                        */
 /* -------------------------------------------------------------------- */
@@ -269,7 +267,7 @@ GDALDataset *TILDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Try to load and parse the .TIL file.                            */
 /* -------------------------------------------------------------------- */
     VSILFILE *fp = VSIFOpenL( poOpenInfo->pszFilename, "r" );
-    
+
     if( fp == NULL )
     {
         return NULL;
@@ -290,9 +288,7 @@ GDALDataset *TILDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    TILDataset 	*poDS;
-
-    poDS = new TILDataset();
+    TILDataset *poDS = new TILDataset();
     poDS->papszMetadataFiles = mdreader->GetMetadataFiles();
     mdreader->FillMetadata(&poDS->oMDMD);
     poDS->nRasterXSize = atoi(CSLFetchNameValueDef(papszIMD,"numColumns","0"));
@@ -307,7 +303,6 @@ GDALDataset *TILDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      We need to open one of the images in order to establish         */
 /*      details like the band count and types.                          */
 /* -------------------------------------------------------------------- */
-    GDALDataset *poTemplateDS;
     const char *pszFilename = CSLFetchNameValue( papszTIL, "TILE_1.filename" );
     if( pszFilename == NULL )
     {
@@ -317,14 +312,15 @@ GDALDataset *TILDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    // trim double quotes. 
+    // trim double quotes.
     if( pszFilename[0] == '"' )
         pszFilename++;
     if( pszFilename[strlen(pszFilename)-1] == '"' )
-        ((char *) pszFilename)[strlen(pszFilename)-1] = '\0';
+        const_cast<char *>( pszFilename )[strlen(pszFilename)-1] = '\0';
 
     CPLString osFilename = CPLFormFilename(osDirname, pszFilename, NULL);
-    poTemplateDS = (GDALDataset *) GDALOpen( osFilename, GA_ReadOnly );
+    GDALDataset *poTemplateDS = reinterpret_cast<GDALDataset *>(
+        GDALOpen( osFilename, GA_ReadOnly ) );
     if( poTemplateDS == NULL || poTemplateDS->GetRasterCount() == 0)
     {
         delete poDS;
@@ -334,8 +330,8 @@ GDALDataset *TILDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
     GDALRasterBand *poTemplateBand = poTemplateDS->GetRasterBand(1);
-    GDALDataType eDT = poTemplateBand->GetRasterDataType();
-    int          nBandCount = poTemplateDS->GetRasterCount();
+    const GDALDataType eDT = poTemplateBand->GetRasterDataType();
+    const int nBandCount = poTemplateDS->GetRasterCount();
 
     //we suppose the first tile have the same projection as others (usually so)
     CPLString pszProjection(poTemplateDS->GetProjectionRef());
@@ -346,7 +342,7 @@ GDALDataset *TILDataset::Open( GDALOpenInfo * poOpenInfo )
     double      adfGeoTransform[6];
     if( poTemplateDS->GetGeoTransform( adfGeoTransform ) == CE_None )
     {
-        // According to https://www.digitalglobe.com/sites/default/files/ISD_External.pdf, ulx=originX and 
+        // According to https://www.digitalglobe.com/sites/default/files/ISD_External.pdf, ulx=originX and
         // is "Easting of the center of the upper left pixel of the image."
         adfGeoTransform[0] = CPLAtof(CSLFetchNameValueDef(papszIMD,"MAP_PROJECTED_PRODUCT.ULX","0")) - adfGeoTransform[1] / 2;
         adfGeoTransform[3] = CPLAtof(CSLFetchNameValueDef(papszIMD,"MAP_PROJECTED_PRODUCT.ULY","0")) - adfGeoTransform[5] / 2;
@@ -360,11 +356,9 @@ GDALDataset *TILDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Create and initialize the corresponding VRT dataset used to     */
 /*      manage the tiled data access.                                   */
 /* -------------------------------------------------------------------- */
-    int iBand;
-     
     poDS->poVRTDS = new VRTDataset(poDS->nRasterXSize,poDS->nRasterYSize);
 
-    for( iBand = 0; iBand < nBandCount; iBand++ )
+    for( int iBand = 0; iBand < nBandCount; iBand++ )
         poDS->poVRTDS->AddBand( eDT, NULL );
 
     /* Don't try to write a VRT file */
@@ -373,21 +367,24 @@ GDALDataset *TILDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    for( iBand = 1; iBand <= nBandCount; iBand++ )
-        poDS->SetBand( iBand, 
-                       new TILRasterBand( poDS, iBand, 
-                (VRTSourcedRasterBand *) poDS->poVRTDS->GetRasterBand(iBand)));
+    for( int iBand = 1; iBand <= nBandCount; iBand++ )
+        poDS->SetBand(
+            iBand,
+            new TILRasterBand(
+                poDS,
+                iBand,
+                reinterpret_cast<VRTSourcedRasterBand *>(
+                    poDS->poVRTDS->GetRasterBand(iBand) ) ) );
 
 /* -------------------------------------------------------------------- */
 /*      Add tiles as sources for each band.                             */
 /* -------------------------------------------------------------------- */
-    int nTileCount = atoi(CSLFetchNameValueDef(papszTIL,"numTiles","0"));
+    const int nTileCount = atoi(CSLFetchNameValueDef(papszTIL,"numTiles","0"));
     int iTile = 0;
 
     for( iTile = 1; iTile <= nTileCount; iTile++ )
     {
         CPLString osKey;
-
         osKey.Printf( "TILE_%d.filename", iTile );
         pszFilename = CSLFetchNameValue( papszTIL, osKey );
         if( pszFilename == NULL )
@@ -397,48 +394,49 @@ GDALDataset *TILDataset::Open( GDALOpenInfo * poOpenInfo )
             delete poDS;
             return NULL;
         }
-        
-        // trim double quotes. 
+
+        // trim double quotes.
         if( pszFilename[0] == '"' )
             pszFilename++;
         if( pszFilename[strlen(pszFilename)-1] == '"' )
-            ((char *) pszFilename)[strlen(pszFilename)-1] = '\0';
+            const_cast<char *>( pszFilename )[strlen(pszFilename)-1] = '\0';
         osFilename = CPLFormFilename(osDirname, pszFilename, NULL);
 
         osKey.Printf( "TILE_%d.ULColOffset", iTile );
-        int nULX = atoi(CSLFetchNameValueDef(papszTIL, osKey, "0"));
-        
+        const int nULX = atoi(CSLFetchNameValueDef(papszTIL, osKey, "0"));
+
         osKey.Printf( "TILE_%d.ULRowOffset", iTile );
-        int nULY = atoi(CSLFetchNameValueDef(papszTIL, osKey, "0"));
+        const int nULY = atoi(CSLFetchNameValueDef(papszTIL, osKey, "0"));
 
         osKey.Printf( "TILE_%d.LRColOffset", iTile );
-        int nLRX = atoi(CSLFetchNameValueDef(papszTIL, osKey, "0"));
-        
+        const int nLRX = atoi(CSLFetchNameValueDef(papszTIL, osKey, "0"));
+
         osKey.Printf( "TILE_%d.LRRowOffset", iTile );
-        int nLRY = atoi(CSLFetchNameValueDef(papszTIL, osKey, "0"));
+        const int nLRY = atoi(CSLFetchNameValueDef(papszTIL, osKey, "0"));
 
-        GDALDataset *poTileDS = 
-            new GDALProxyPoolDataset( osFilename, 
+        GDALDataset *poTileDS =
+            new GDALProxyPoolDataset( osFilename,
                                       nLRX - nULX + 1, nLRY - nULY + 1 );
         if( poTileDS == NULL )
             continue;
 
         poDS->apoTileDS.push_back( poTileDS );
 
-        for( iBand = 1; iBand <= nBandCount; iBand++ )
+        for( int iBand = 1; iBand <= nBandCount; iBand++ )
         {
-            ((GDALProxyPoolDataset *) poTileDS)->
+            reinterpret_cast<GDALProxyPoolDataset *>( poTileDS )->
                 AddSrcBandDescription( eDT, nLRX - nULX + 1, 1 );
 
             GDALRasterBand *poSrcBand = poTileDS->GetRasterBand(iBand);
 
-            VRTSourcedRasterBand *poVRTBand = 
-                (VRTSourcedRasterBand *) poDS->poVRTDS->GetRasterBand(iBand);
-            
+            VRTSourcedRasterBand *poVRTBand =
+                reinterpret_cast<VRTSourcedRasterBand *>(
+                    poDS->poVRTDS->GetRasterBand(iBand) );
+
             poVRTBand->AddSimpleSource( poSrcBand,
-                                        0, 0, 
-                                        nLRX - nULX + 1, nLRY - nULY + 1, 
-                                        nULX, nULY, 
+                                        0, 0,
+                                        nLRX - nULX + 1, nLRY - nULY + 1,
+                                        nULX, nULY,
                                         nLRX - nULX + 1, nLRY - nULY + 1 );
         }
     }
@@ -454,7 +452,7 @@ GDALDataset *TILDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -464,13 +462,12 @@ GDALDataset *TILDataset::Open( GDALOpenInfo * poOpenInfo )
 char **TILDataset::GetFileList()
 
 {
-    unsigned int  i;
     char **papszFileList = GDALPamDataset::GetFileList();
 
-    for( i = 0; i < apoTileDS.size(); i++ )
+    for( unsigned int i = 0; i < apoTileDS.size(); i++ )
         papszFileList = CSLAddString( papszFileList,
                                       apoTileDS[i]->GetDescription() );
-                                      
+
     if(NULL != papszMetadataFiles)
     {
         for( int i = 0; papszMetadataFiles[i] != NULL; i++ )
@@ -489,26 +486,19 @@ char **TILDataset::GetFileList()
 void GDALRegister_TIL()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "TIL" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "TIL" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "TIL" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "EarthWatch .TIL" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_til.html" );
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetDescription( "TIL" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "EarthWatch .TIL" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_til.html" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = TILDataset::Open;
-        poDriver->pfnIdentify = TILDataset::Identify;
+    poDriver->pfnOpen = TILDataset::Open;
+    poDriver->pfnIdentify = TILDataset::Identify;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
-
-
diff --git a/frmts/tsx/tsxdataset.cpp b/frmts/tsx/tsxdataset.cpp
index 949cf02..b878e28 100644
--- a/frmts/tsx/tsxdataset.cpp
+++ b/frmts/tsx/tsxdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tsxdataset.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: tsxdataset.cpp 32237 2015-12-18 13:41:27Z goatbar $
  *
  * Project:     TerraSAR-X XML Product Support
  * Purpose:     Support for TerraSAR-X XML Metadata files
@@ -30,18 +30,14 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
 #include "cpl_minixml.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
 #define MAX_GCPS 5000    //this should be more than enough ground control points
 
-CPL_CVSID("$Id: tsxdataset.cpp 28053 2014-12-04 09:31:07Z rouault $");
-
-CPL_C_START
-void GDALRegister_TSX(void);
-CPL_C_END
-
+CPL_CVSID("$Id: tsxdataset.cpp 32237 2015-12-18 13:41:27Z goatbar $");
 
 enum ePolarization {
     HH=0,
@@ -65,11 +61,9 @@ enum eProductType {
 /* GetFilePath: return a relative path to a file within an XML node.
  * Returns Null on failure
  */
-const char *GetFilePath(CPLXMLNode *psXMLNode, const char **pszNodeType) {
-    const char *pszDirectory, *pszFilename;
-
-    pszDirectory = CPLGetXMLValue( psXMLNode, "file.location.path", "" );
-    pszFilename = CPLGetXMLValue( psXMLNode, "file.location.filename", "" );
+static const char *GetFilePath(CPLXMLNode *psXMLNode, const char **pszNodeType) {
+    const char *pszDirectory = CPLGetXMLValue( psXMLNode, "file.location.path", "" );
+    const char *pszFilename = CPLGetXMLValue( psXMLNode, "file.location.filename", "" );
     *pszNodeType = CPLGetXMLValue (psXMLNode, "type", " " );
 
     if (pszDirectory == NULL || pszFilename == NULL) {
@@ -136,12 +130,13 @@ public:
 /*                            TSXRasterBand                             */
 /************************************************************************/
 
-TSXRasterBand::TSXRasterBand( TSXDataset *poDS, GDALDataType eDataType,
-                              ePolarization ePol, GDALDataset *poBand )
+TSXRasterBand::TSXRasterBand( TSXDataset *poDSIn, GDALDataType eDataTypeIn,
+                              ePolarization ePolIn, GDALDataset *poBandIn ) :
+    poBand(poBandIn),
+    ePol(ePolIn)
 {
-    this->poDS = poDS;
-    this->eDataType = eDataType;
-    this->ePol = ePol;
+    poDS = poDSIn;
+    eDataType = eDataTypeIn;
 
     switch (ePol) {
         case HH:
@@ -158,11 +153,8 @@ TSXRasterBand::TSXRasterBand( TSXDataset *poDS, GDALDataType eDataType,
             break;
     }
 
-
     /* now setup the actual raster reader */
-    this->poBand = poBand;
-
-    GDALRasterBand *poSrcBand = poBand->GetRasterBand( 1 );
+    GDALRasterBand *poSrcBand = poBandIn->GetRasterBand( 1 );
     poSrcBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
 }
 
@@ -172,7 +164,7 @@ TSXRasterBand::TSXRasterBand( TSXDataset *poDS, GDALDataType eDataType,
 
 TSXRasterBand::~TSXRasterBand() {
     if( poBand != NULL )
-        GDALClose( (GDALRasterBandH) poBand );
+        GDALClose( reinterpret_cast<GDALRasterBandH>( poBand ) );
 }
 
 /************************************************************************/
@@ -201,12 +193,12 @@ CPLErr TSXRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             pImage, nBlockXSize, nRequestYSize, GDT_CInt16, 1, NULL, 4,
             nBlockXSize * 4, 0, NULL );
     }
-    else { /* Detected Product */
-        return poBand->RasterIO( GF_Read, nBlockXOff * nBlockXSize,
-            nBlockYOff * nBlockYSize, nBlockXSize, nRequestYSize,
-            pImage, nBlockXSize, nRequestYSize, GDT_UInt16, 1, NULL, 2,
-            nBlockXSize * 2, 0, NULL );
-    }
+
+    // Detected Product
+    return poBand->RasterIO( GF_Read, nBlockXOff * nBlockXSize,
+                             nBlockYOff * nBlockYSize, nBlockXSize,
+                             nRequestYSize, pImage, nBlockXSize, nRequestYSize,
+                             GDT_UInt16, 1, NULL, 2, nBlockXSize * 2, 0, NULL );
 }
 
 /************************************************************************/
@@ -219,18 +211,20 @@ CPLErr TSXRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /*                             TSXDataset()                             */
 /************************************************************************/
 
-TSXDataset::TSXDataset() {
-    nGCPCount = 0;
-    pasGCPList = NULL;
-    pszGCPProjection = CPLStrdup("");
-    pszProjection = CPLStrdup("");
+TSXDataset::TSXDataset() :
+    nGCPCount(0),
+    pasGCPList(NULL),
+    pszGCPProjection(CPLStrdup("")),
+    pszProjection(CPLStrdup("")),
+    bHaveGeoTransform(false),
+    nProduct(eUnknown)
+{
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
-    bHaveGeoTransform = FALSE;
 }
 
 /************************************************************************/
@@ -260,12 +254,12 @@ int TSXDataset::Identify( GDALOpenInfo *poOpenInfo )
     {
         if( poOpenInfo->bIsDirectory )
         {
-            CPLString osFilename =
+            const CPLString osFilename =
                 CPLFormCIFilename( poOpenInfo->pszFilename, CPLGetFilename( poOpenInfo->pszFilename ), "xml" );
 
             /* Check if the filename contains TSX1_SAR (TerraSAR-X) or TDX1_SAR (TanDEM-X) */
-            if (!(EQUALN(CPLGetBasename( osFilename ), "TSX1_SAR", 8) ||
-                  EQUALN(CPLGetBasename( osFilename ), "TDX1_SAR", 8)))
+            if (!(STARTS_WITH_CI(CPLGetBasename( osFilename ), "TSX1_SAR") ||
+                  STARTS_WITH_CI(CPLGetBasename( osFilename ), "TDX1_SAR")))
                 return 0;
 
             VSIStatBufL sStat;
@@ -277,12 +271,13 @@ int TSXDataset::Identify( GDALOpenInfo *poOpenInfo )
     }
 
     /* Check if the filename contains TSX1_SAR (TerraSAR-X) or TDX1_SAR (TanDEM-X) */
-    if (!(EQUALN(CPLGetBasename( poOpenInfo->pszFilename ), "TSX1_SAR", 8) ||
-          EQUALN(CPLGetBasename( poOpenInfo->pszFilename ), "TDX1_SAR", 8)))
+    if (!(STARTS_WITH_CI(CPLGetBasename( poOpenInfo->pszFilename ), "TSX1_SAR") ||
+          STARTS_WITH_CI(CPLGetBasename( poOpenInfo->pszFilename ), "TDX1_SAR")))
         return 0;
 
     /* finally look for the <level1Product tag */
-    if (!EQUALN((char *)poOpenInfo->pabyHeader, "<level1Product", 14))
+    if (!STARTS_WITH_CI(reinterpret_cast<char *>( poOpenInfo->pabyHeader ),
+                        "<level1Product") )
         return 0;
 
     return 1;
@@ -298,22 +293,19 @@ int TSXDataset::Identify( GDALOpenInfo *poOpenInfo )
 bool TSXDataset::getGCPsFromGEOREF_XML(char *pszGeorefFilename)
 {
     //open GEOREF.xml
-    CPLXMLNode *psGeorefData;
-    psGeorefData = CPLParseXMLFile( pszGeorefFilename );
+    CPLXMLNode *psGeorefData = CPLParseXMLFile( pszGeorefFilename );
     if (psGeorefData==NULL)
         return false;
 
     //get the ellipsoid and semi-major, semi-minor axes
-    CPLXMLNode *psSphere;
-    const char *pszEllipsoidName;
-    double minor_axis, major_axis, inv_flattening;
     OGRSpatialReference osr;
-    psSphere = CPLGetXMLNode( psGeorefData, "=geoReference.referenceFrames.sphere" );
+    CPLXMLNode *psSphere = CPLGetXMLNode( psGeorefData, "=geoReference.referenceFrames.sphere" );
     if (psSphere!=NULL)
     {
-        pszEllipsoidName = CPLGetXMLValue( psSphere, "ellipsoidID", "" );
-        minor_axis = CPLAtof(CPLGetXMLValue( psSphere, "semiMinorAxis", "0.0" ));
-        major_axis = CPLAtof(CPLGetXMLValue( psSphere, "semiMajorAxis", "0.0" ));
+        const char *pszEllipsoidName
+            = CPLGetXMLValue( psSphere, "ellipsoidID", "" );
+        const double minor_axis = CPLAtof(CPLGetXMLValue( psSphere, "semiMinorAxis", "0.0" ));
+        const double major_axis = CPLAtof(CPLGetXMLValue( psSphere, "semiMajorAxis", "0.0" ));
         //save datum parameters to the spatial reference
         if ( EQUAL(pszEllipsoidName, "") || minor_axis==0.0 || major_axis==0.0 )
         {
@@ -325,21 +317,23 @@ bool TSXDataset::getGCPsFromGEOREF_XML(char *pszGeorefFilename)
             osr.SetWellKnownGeogCS( "WGS84" );
         }
         else {
-            inv_flattening = major_axis/(major_axis - minor_axis);
+            const double inv_flattening = major_axis/(major_axis - minor_axis);
             osr.SetGeogCS( "","",pszEllipsoidName, major_axis, inv_flattening);
         }
     }
 
     //get gcps
-    CPLXMLNode *psNode;
-    CPLXMLNode *psGeolocationGrid = CPLGetXMLNode( psGeorefData, "=geoReference.geolocationGrid" );
+    CPLXMLNode *psGeolocationGrid
+        = CPLGetXMLNode( psGeorefData, "=geoReference.geolocationGrid" );
     if (psGeolocationGrid==NULL)
     {
         CPLDestroyXMLNode( psGeorefData );
         return false;
     }
-    nGCPCount = atoi(CPLGetXMLValue( psGeolocationGrid, "numberOfGridPoints.total", "0" ));
+    nGCPCount
+        = atoi(CPLGetXMLValue( psGeolocationGrid, "numberOfGridPoints.total", "0" ));
     //count the gcps if the given count value is invalid
+    CPLXMLNode *psNode;
     if (nGCPCount<=0)
     {
         for( psNode = psGeolocationGrid->psChild; psNode != NULL; psNode = psNode->psNext )
@@ -357,9 +351,13 @@ bool TSXDataset::getGCPsFromGEOREF_XML(char *pszGeorefFilename)
     if (nGCPCount>MAX_GCPS )
         nGCPCount=MAX_GCPS;
     //allocate memory for the gcps
-    pasGCPList = (GDAL_GCP *)CPLCalloc(sizeof(GDAL_GCP),nGCPCount);
+    pasGCPList = reinterpret_cast<GDAL_GCP *>(
+        CPLCalloc(sizeof(GDAL_GCP), nGCPCount) );
+
     //loop through all gcps and set info
-    int gcps_allocated = nGCPCount;    //save the number allocated to ensure it does not run off the end of the array
+
+    //save the number allocated to ensure it does not run off the end of the array
+    const int gcps_allocated = nGCPCount;
     nGCPCount=0;    //reset to zero and count
     //do a check on the grid point to make sure it has lat,long row, and column
     //it seems that only SSC products contain row, col - how to map lat long otherwise??
@@ -387,7 +385,6 @@ bool TSXDataset::getGCPsFromGEOREF_XML(char *pszGeorefFilename)
             break;
         }
 
-         char    szID[32];
          GDAL_GCP   *psGCP = pasGCPList + nGCPCount;
 
          if( !EQUAL(psNode->pszValue,"gridPoint") )
@@ -395,17 +392,14 @@ bool TSXDataset::getGCPsFromGEOREF_XML(char *pszGeorefFilename)
 
          nGCPCount++ ;
 
-         sprintf( szID, "%d", nGCPCount );
+         char szID[32];
+         snprintf( szID, sizeof(szID), "%d", nGCPCount );
          psGCP->pszId = CPLStrdup( szID );
          psGCP->pszInfo = CPLStrdup("");
-         psGCP->dfGCPPixel =
-             CPLAtof(CPLGetXMLValue(psNode,"col","0"));
-         psGCP->dfGCPLine =
-             CPLAtof(CPLGetXMLValue(psNode,"row","0"));
-         psGCP->dfGCPX =
-             CPLAtof(CPLGetXMLValue(psNode,"lon",""));
-         psGCP->dfGCPY =
-             CPLAtof(CPLGetXMLValue(psNode,"lat",""));
+         psGCP->dfGCPPixel = CPLAtof(CPLGetXMLValue(psNode,"col","0"));
+         psGCP->dfGCPLine = CPLAtof(CPLGetXMLValue(psNode,"row","0"));
+         psGCP->dfGCPX = CPLAtof(CPLGetXMLValue(psNode,"lon",""));
+         psGCP->dfGCPY = CPLAtof(CPLGetXMLValue(psNode,"lat",""));
          //looks like height is in meters - should it be converted so xyz are all on the same scale??
          psGCP->dfGCPZ = 0;
              //CPLAtof(CPLGetXMLValue(psNode,"height",""));
@@ -448,19 +442,21 @@ GDALDataset *TSXDataset::Open( GDALOpenInfo *poOpenInfo ) {
     if( poOpenInfo->bIsDirectory )
     {
         osFilename =
-                CPLFormCIFilename( poOpenInfo->pszFilename, CPLGetFilename( poOpenInfo->pszFilename ), "xml" );
+            CPLFormCIFilename( poOpenInfo->pszFilename,
+                               CPLGetFilename( poOpenInfo->pszFilename ),
+                               "xml" );
     }
     else
         osFilename = poOpenInfo->pszFilename;
 
     /* Ingest the XML */
-    CPLXMLNode *psData, *psComponents, *psProductInfo;
-    psData = CPLParseXMLFile( osFilename );
+    CPLXMLNode *psData = CPLParseXMLFile( osFilename );
     if (psData == NULL)
         return NULL;
 
     /* find the product components */
-    psComponents = CPLGetXMLNode( psData, "=level1Product.productComponents" );
+    CPLXMLNode *psComponents
+        = CPLGetXMLNode( psData, "=level1Product.productComponents" );
     if (psComponents == NULL) {
         CPLError( CE_Failure, CPLE_OpenFailed,
             "Unable to find <productComponents> tag in file.\n" );
@@ -469,7 +465,8 @@ GDALDataset *TSXDataset::Open( GDALOpenInfo *poOpenInfo ) {
     }
 
     /* find the product info tag */
-    psProductInfo = CPLGetXMLNode( psData, "=level1Product.productInfo" );
+    CPLXMLNode *psProductInfo
+        = CPLGetXMLNode( psData, "=level1Product.productInfo" );
     if (psProductInfo == NULL) {
         CPLError( CE_Failure, CPLE_OpenFailed,
             "Unable to find <productInfo> tag in file.\n" );
@@ -527,77 +524,74 @@ GDALDataset *TSXDataset::Open( GDALOpenInfo *poOpenInfo ) {
     poDS->SetMetadataItem( "RANGE_LOOKS", CPLGetXMLValue( psProductInfo,
         "imageDataInfo.imageRaster.rangeLooks", "unknown" ) );
 
-    const char *pszProductVariant;
-    pszProductVariant = CPLGetXMLValue( psProductInfo,
+    const char *pszProductVariant = CPLGetXMLValue( psProductInfo,
         "productVariantInfo.productVariant", "unknown" );
 
     poDS->SetMetadataItem( "PRODUCT_VARIANT", pszProductVariant );
 
     /* Determine what product variant this is */
-    if (EQUALN(pszProductVariant,"SSC",3))
+    if (STARTS_WITH_CI(pszProductVariant, "SSC"))
         poDS->nProduct = eSSC;
-    else if (EQUALN(pszProductVariant,"MGD",3))
+    else if (STARTS_WITH_CI(pszProductVariant, "MGD"))
         poDS->nProduct = eMGD;
-    else if (EQUALN(pszProductVariant,"EEC",3))
+    else if (STARTS_WITH_CI(pszProductVariant, "EEC"))
         poDS->nProduct = eEEC;
-    else if (EQUALN(pszProductVariant,"GEC",3))
+    else if (STARTS_WITH_CI(pszProductVariant, "GEC"))
         poDS->nProduct = eGEC;
     else
         poDS->nProduct = eUnknown;
 
     /* Start reading in the product components */
-    const char *pszPath;
     char *pszGeorefFile = NULL;
-    CPLXMLNode *psComponent;
     CPLErr geoTransformErr=CE_Failure;
-    for (psComponent = psComponents->psChild; psComponent != NULL;
-         psComponent = psComponent->psNext)
+    for ( CPLXMLNode *psComponent = psComponents->psChild;
+          psComponent != NULL;
+          psComponent = psComponent->psNext)
     {
         const char *pszType = NULL;
-        pszPath = CPLFormFilename(
+        const char *pszPath = CPLFormFilename(
                 CPLGetDirname( osFilename ),
                 GetFilePath(psComponent, &pszType),
                 "" );
         const char *pszPolLayer = CPLGetXMLValue(psComponent, "polLayer", " ");
 
-        if ( !EQUALN(pszType," ",1) ) {
-            if (EQUALN(pszType, "MAPPING_GRID", 12) ) {
+        if ( !STARTS_WITH_CI(pszType, " ") ) {
+            if (STARTS_WITH_CI(pszType, "MAPPING_GRID") ) {
                 /* the mapping grid... save as a metadata item this path */
                 poDS->SetMetadataItem( "MAPPING_GRID", pszPath );
             }
-            else if (EQUALN(pszType, "GEOREF", 6)) {
+            else if (STARTS_WITH_CI(pszType, "GEOREF")) {
                 /* save the path to the georef data for later use */
+                CPLFree( pszGeorefFile );
                 pszGeorefFile = CPLStrdup( pszPath );
             }
         }
-        else if( !EQUALN(pszPolLayer, " ", 1) &&
-            EQUALN(psComponent->pszValue, "imageData", 9) ) {
+        else if( !STARTS_WITH_CI(pszPolLayer, " ") &&
+            STARTS_WITH_CI(psComponent->pszValue, "imageData") ) {
             /* determine the polarization of this band */
             ePolarization ePol;
-            if ( EQUALN(pszPolLayer, "HH", 2) ) {
+            if ( STARTS_WITH_CI(pszPolLayer, "HH") ) {
                 ePol = HH;
             }
-            else if ( EQUALN(pszPolLayer, "HV" , 2) ) {
+            else if ( STARTS_WITH_CI(pszPolLayer, "HV") ) {
                 ePol = HV;
             }
-            else if ( EQUALN(pszPolLayer, "VH", 2) ) {
+            else if ( STARTS_WITH_CI(pszPolLayer, "VH") ) {
                 ePol = VH;
             }
             else {
                 ePol = VV;
             }
 
-            GDALDataType eDataType = EQUALN(pszDataType, "COMPLEX", 7) ?
+            GDALDataType eDataType = STARTS_WITH_CI(pszDataType, "COMPLEX") ?
                 GDT_CInt16 : GDT_UInt16;
 
             /* try opening the file that represents that band */
-            TSXRasterBand *poBand;
-            GDALDataset *poBandData;
-
-            poBandData = (GDALDataset *) GDALOpen( pszPath, GA_ReadOnly );
+            GDALDataset *poBandData = reinterpret_cast<GDALDataset *>(
+                GDALOpen( pszPath, GA_ReadOnly ) );
             if ( poBandData != NULL ) {
-                poBand = new TSXRasterBand( poDS, eDataType, ePol,
-                    poBandData );
+                TSXRasterBand *poBand
+                    = new TSXRasterBand( poDS, eDataType, ePol, poBandData );
                 poDS->SetBand( poDS->GetRasterCount() + 1, poBand );
 
                 //copy georeferencing info from the band
@@ -630,7 +624,6 @@ GDALDataset *TSXDataset::Open( GDALOpenInfo *poOpenInfo ) {
 
     CPLFree(pszDataType);
 
-
 /* -------------------------------------------------------------------- */
 /*      Check and set matrix representation.                            */
 /* -------------------------------------------------------------------- */
@@ -656,14 +649,14 @@ GDALDataset *TSXDataset::Open( GDALOpenInfo *poOpenInfo ) {
         //for now just SSC because the others don't have refColumn and refRow
         if (!success && poDS->nProduct == eSSC)
         {
-            CPLXMLNode *psNode;
             int nGCP = 0;
             double dfAvgHeight = CPLAtof(CPLGetXMLValue(psSceneInfo,
                 "sceneAverageHeight", "0.0"));
 
             //count and allocate gcps - there should be five - 4 corners and a centre
             poDS->nGCPCount = 0;
-            for (psNode = psSceneInfo->psChild; psNode != NULL; psNode = psNode->psNext )
+            CPLXMLNode *psNode = psSceneInfo->psChild;
+            for ( ; psNode != NULL; psNode = psNode->psNext )
             {
                 if (!EQUAL(psNode->pszValue, "sceneCenterCoord") &&
                     !EQUAL(psNode->pszValue, "sceneCornerCoord"))
@@ -792,25 +785,21 @@ CPLErr TSXDataset::GetGeoTransform(double* padfTransform)
 /*                         GDALRegister_TSX()                           */
 /************************************************************************/
 
-void GDALRegister_TSX() {
-    GDALDriver    *poDriver;
-
-    if( GDALGetDriverByName( "TSX" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+void GDALRegister_TSX()
+{
+    if( GDALGetDriverByName( "TSX" ) != NULL )
+        return;
 
-        poDriver->SetDescription( "TSX" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "TerraSAR-X Product" );
-/*        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_tsx.html" ); */
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetDescription( "TSX" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "TerraSAR-X Product" );
+    // poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_tsx.html" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = TSXDataset::Open;
-        poDriver->pfnIdentify = TSXDataset::Identify;
+    poDriver->pfnOpen = TSXDataset::Open;
+    poDriver->pfnIdentify = TSXDataset::Identify;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
-
diff --git a/frmts/usgsdem/CDED.notes b/frmts/usgsdem/CDED.notes
index a332550..68c108f 100644
--- a/frmts/usgsdem/CDED.notes
+++ b/frmts/usgsdem/CDED.notes
@@ -31,7 +31,7 @@ Offset Length Name                    Notes
   156     6   Horizontal Reference    Hardcoded to "0" (Geographic)
               System
 
-  162     6   UTM/SP Zone             Harcoded to "0".
+  162     6   UTM/SP Zone             Hardcoded to "0".
 
   168   360   Projection Parameters   Each hardcoded to 0.0.
 
diff --git a/frmts/usgsdem/frmt_usgsdem.html b/frmts/usgsdem/frmt_usgsdem.html
index e6b254d..f8c91e3 100644
--- a/frmts/usgsdem/frmt_usgsdem.html
+++ b/frmts/usgsdem/frmt_usgsdem.html
@@ -16,7 +16,7 @@ recognition of coordinate system, and georeferenced positioning.<p>
 The 7.5 minute (UTM grid) USGS DEM files will generally have regions of
 missing data around the edges, and these are properly marked with
 a nodata value.  Elevation values in USGS DEM files may be in meters or
-feet, and this will be indicated by the return value of 
+feet, and this will be indicated by the return value of
 GDALRasterBand::GetUnitType() (either "m" or "ft").<p>
 
 Note that USGS DEM files are represented as one big tile.  This may cause
@@ -24,7 +24,7 @@ cache thrashing problems if the GDAL tile cache size is small.  It will also
 result in a substantial delay when the first pixel is read as the whole file
 will be ingested. <p>
 
-Some of the code for implementing usgsdemdataset.cpp was derived from 
+Some of the code for implementing usgsdemdataset.cpp was derived from
 VTP code by Ben Discoe.  See the <a href="http://www.vterrain.org/">Virtual
 Terrain</a> project for more information on VTP.<p>
 
@@ -39,28 +39,28 @@ system.  By default the entire area of the input file will be output,
 but for CDED50K products the output file will be sampled at the
 production specified resolution and on product tile boundaries.<P>
 
-If the input file has appropriate coordinate system information set, 
+If the input file has appropriate coordinate system information set,
 export to specific product formats can take input in different coordinate
-systems (ie. from Albers projection to NAD83 geographic for CDED50K 
+systems (i.e. from Albers projection to NAD83 geographic for CDED50K
 production).<p>
 
 Creation Options:<p>
 
 <ul>
 
-<li> <b>PRODUCT=DEFAULT/CDED50K</b>: When CDED50K is specified, the output file will be forced to 
+<li> <b>PRODUCT=DEFAULT/CDED50K</b>: When CDED50K is specified, the output file will be forced to
 adhere to CDED 50K product specifications.  The output will always be 1201x1201
 and generally a 15 minute by 15 minute tile (though wider in longitude in
 far north areas). <p>
 
-<li> <b>TOPLEFT=long,lat</b>: For CDED50K products, this is used to 
-specify the top left corner of the tile to be generated.  It should be 
-on a 15 minute boundary and can be given in decimal degrees or degrees and 
+<li> <b>TOPLEFT=long,lat</b>: For CDED50K products, this is used to
+specify the top left corner of the tile to be generated.  It should be
+on a 15 minute boundary and can be given in decimal degrees or degrees and
 minutes (eg. TOPLEFT=117d15w,52d30n). <P>
 
 <li> <b>RESAMPLE=Nearest/Bilinear/Cubic/CubicSpline</b>: Set the resampling
 kernel used for resampling the data to the target grid.  Only has an effect
-when particular products like CDED50K are being produced.  Defaults to 
+when particular products like CDED50K are being produced.  Defaults to
 Bilinear.<p>
 
 <li> <b>DEMLevelCode=integer</b> DEM Level (1, 2 or 3 if set). Defaults to 1.<p>
@@ -73,7 +73,7 @@ field of the generated file .<p>
 <li> <b>OriginCode=text</b>: Up to 4 characters to be put into the origin
 code field of the generated file (YT for Yukon).<p>
 
-<li> <b>ProcessCode=code</b>: One character to be put into the process 
+<li> <b>ProcessCode=code</b>: One character to be put into the process
 code field of the generated file (8=ANUDEM, 9=FME, A=TopoGrid).<p>
 
 <li> <b>TEMPLATE=filename</b>: For any output file, a template file can be
@@ -96,10 +96,10 @@ when particular products like CDED50K are being produced.<p>
 
 Example:
 
-The following would generate a single CDED50K tile, extracting from the 
+The following would generate a single CDED50K tile, extracting from the
 larger DEM coverage yk_3arcsec for a tile with the top left corner -117w,60n.
 The file yk_template.dem is used to set some product fields including the
-Producer of Data, Process Code and Origin Code fields. 
+Producer of Data, Process Code and Origin Code fields.
 
 <pre>
 gdal_translate -of USGSDEM -co PRODUCT=CDED50K -co TEMPLATE=yk_template.dem \
@@ -112,8 +112,8 @@ NOTE: Implemented as <tt>gdal/frmts/usgsdem/usgsdemdataset.cpp</tt>.<p>
 
 The USGS DEM reading code in GDAL was derived from the importer in the
 <a href="http://www.vterrain.org/">VTP</a> software.  The export capability
-was developed with the financial support of the Yukon Department of  
-Environment.<p> 
+was developed with the financial support of the Yukon Department of
+Environment.<p>
 
 </body>
 </html>
diff --git a/frmts/usgsdem/usgsdem_create.cpp b/frmts/usgsdem/usgsdem_create.cpp
index 5b77118..e1a7c66 100644
--- a/frmts/usgsdem/usgsdem_create.cpp
+++ b/frmts/usgsdem/usgsdem_create.cpp
@@ -1,11 +1,11 @@
 /******************************************************************************
- * $Id: usgsdem_create.cpp 32029 2015-12-06 14:38:26Z rouault $
+ * $Id: usgsdem_create.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  USGS DEM Driver
  * Purpose:  CreateCopy() implementation.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
- * This writing code based on the format specification: 
+ * This writing code based on the format specification:
  *   Canadian Digital Elevation Data Product Specification - Edition 2.0
  *
  ******************************************************************************
@@ -31,15 +31,25 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
-#include "ogr_spatialref.h"
+#include "cpl_csv.h"
 #include "cpl_string.h"
+#include "gdal_pam.h"
 #include "gdalwarper.h"
-#include "cpl_csv.h"
+#include "ogr_spatialref.h"
+
+#include <cmath>
+
+#include <algorithm>
+
+
+CPL_CVSID("$Id: usgsdem_create.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
-CPL_CVSID("$Id: usgsdem_create.cpp 32029 2015-12-06 14:38:26Z rouault $");
+/* used by usgsdemdataset.cpp */
+GDALDataset *USGSDEMCreateCopy( const char *, GDALDataset *, int, char **,
+                                GDALProgressFunc pfnProgress,
+                                void * pProgressData );
 
-typedef struct 
+typedef struct
 {
     GDALDataset *poSrcDS;
     char        *pszFilename;
@@ -47,7 +57,7 @@ typedef struct
 
     char       *pszDstSRS;
 
-    double      dfLLX, dfLLY;  // These are adjusted in to center of 
+    double      dfLLX, dfLLY;  // These are adjusted in to center of
     double      dfULX, dfULY;  // corner pixels, and in decimal degrees.
     double      dfURX, dfURY;
     double      dfLRX, dfLRY;
@@ -65,7 +75,6 @@ typedef struct
     VSILFILE  *fp;
 
     GInt16     *panData;
-    
 } USGSDEMWriteInfo;
 
 #define DEM_NODATA -32767
@@ -81,7 +90,12 @@ static void USGSDEMWriteCleanup( USGSDEMWriteInfo *psWInfo )
     CPLFree( psWInfo->pszDstSRS );
     CPLFree( psWInfo->pszFilename );
     if( psWInfo->fp != NULL )
-        VSIFCloseL( psWInfo->fp );
+    {
+        if( VSIFCloseL( psWInfo->fp ) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        }
+    }
     if( psWInfo->panData != NULL )
         VSIFree( psWInfo->panData );
 }
@@ -89,15 +103,11 @@ static void USGSDEMWriteCleanup( USGSDEMWriteInfo *psWInfo )
 /************************************************************************/
 /*                       USGSDEMDectoPackedDMS()                        */
 /************************************************************************/
-const char *USGSDEMDecToPackedDMS( double dfDec )
+static const char *USGSDEMDecToPackedDMS( double dfDec )
 {
-    double  dfSeconds;
-    int nDegrees, nMinutes, nSign;
-    static char szPackBuf[100];
+    const int nSign = ( dfDec < 0.0  )? -1 : 1;
 
-    nSign = ( dfDec < 0.0 )? -1 : 1;
-
-    dfDec = ABS( dfDec );
+    dfDec = std::abs( dfDec );
     /* If the difference between the value and the nearest degree
        is less than 1e-5 second, then we force to round to the
        nearest degree, to avoid result strings like '40 59 60.0000' instead of '41'.
@@ -105,14 +115,19 @@ const char *USGSDEMDecToPackedDMS( double dfDec )
        Valgrind bug when running usgsdem_6 where the value of psDInfo->dfULCornerY
        computed in DTEDOpen() differ between Valgrind and non-Valgrind executions.
     */
-    if (fabs(dfDec - (int) floor( dfDec + .5)) < 1e-5 / 3600)
-        dfDec = nDegrees = (int) floor( dfDec + .5);
-    else
-        nDegrees = (int) floor( dfDec );
-    nMinutes = (int) floor( ( dfDec - nDegrees ) * 60.0 );
-    dfSeconds = (dfDec - nDegrees) * 3600.0 - nMinutes * 60.0;
+    int nDegrees;
+    if (std::abs(dfDec - static_cast<int>( std::floor( dfDec + .5))) < 1e-5 / 3600)
+    {
+        nDegrees = static_cast<int>( std::floor( dfDec + .5) );
+        dfDec = nDegrees;
+    } else
+        nDegrees = static_cast<int>( std::floor( dfDec ) );
+    const int nMinutes
+        = static_cast<int>( std::floor( ( dfDec - nDegrees ) * 60.0 ) );
+    const double dfSeconds = (dfDec - nDegrees) * 3600.0 - nMinutes * 60.0;
 
-    CPLsprintf( szPackBuf, "%4d%2d%7.4f", 
+    static char szPackBuf[100];
+    CPLsnprintf( szPackBuf, sizeof(szPackBuf), "%4d%2d%7.4f",
              nSign * nDegrees, nMinutes, dfSeconds );
     return szPackBuf;
 }
@@ -121,7 +136,7 @@ const char *USGSDEMDecToPackedDMS( double dfDec )
 /*                              TextFill()                              */
 /************************************************************************/
 
-static void TextFill( char *pszTarget, unsigned int nMaxChars, 
+static void TextFill( char *pszTarget, unsigned int nMaxChars,
                       const char *pszSrc )
 
 {
@@ -142,14 +157,14 @@ static void TextFill( char *pszTarget, unsigned int nMaxChars,
 /*      Right justified.                                                */
 /************************************************************************/
 
-static void TextFillR( char *pszTarget, unsigned int nMaxChars, 
+static void TextFillR( char *pszTarget, unsigned int nMaxChars,
                        const char *pszSrc )
 
 {
     if( strlen(pszSrc) < nMaxChars )
     {
         memset( pszTarget, ' ', nMaxChars - strlen(pszSrc) );
-        memcpy( pszTarget + nMaxChars - strlen(pszSrc), pszSrc, 
+        memcpy( pszTarget + nMaxChars - strlen(pszSrc), pszSrc,
                 strlen(pszSrc) );
     }
     else
@@ -171,40 +186,36 @@ static void TextFillR( char *pszTarget, unsigned int nMaxChars,
 static void USGSDEMPrintDouble( char *pszBuffer, double dfValue )
 
 {
-#define DOUBLE_BUFFER_SIZE 64
+    if ( !pszBuffer )
+        return;
 
-    char    szTemp[DOUBLE_BUFFER_SIZE];
-    int     i;
 #ifdef MSVC_HACK
     const char *pszFormat = "%25.15e";
 #else
     const char *pszFormat = "%24.15e";
 #endif
 
-    if ( !pszBuffer )
-        return;
+    const int DOUBLE_BUFFER_SIZE = 64;
+    char szTemp[DOUBLE_BUFFER_SIZE];
     int nOffset = 0;
-#if defined(HAVE_SNPRINTF)
     if( CPLsnprintf( szTemp, DOUBLE_BUFFER_SIZE, pszFormat, dfValue ) == 25 &&
         szTemp[0] == ' ' )
     {
         nOffset = 1;
     }
-#else
-    CPLsprintf( szTemp, pszFormat, dfValue );
-#endif
     szTemp[DOUBLE_BUFFER_SIZE - 1] = '\0';
 
-    for( i = 0; szTemp[i] != '\0'; i++ )
+    for( int i = 0; szTemp[i] != '\0'; i++ )
     {
         if( szTemp[i] == 'E' || szTemp[i] == 'e' )
             szTemp[i] = 'D';
 #ifdef MSVC_HACK
         if( (szTemp[i] == '+' || szTemp[i] == '-')
-            && szTemp[i+1] == '0' && isdigit(szTemp[i+2]) 
+            && szTemp[i+1] == '0' && isdigit(szTemp[i+2])
             && isdigit(szTemp[i+3]) && szTemp[i+4] == '\0' )
         {
-            memmove( szTemp+i+1, szTemp+i+2, 2 );
+            szTemp[i+1] = szTemp[i+2];
+            szTemp[i+2] = szTemp[i+3];
             szTemp[i+3] = '\0';
             break;
         }
@@ -225,40 +236,36 @@ static void USGSDEMPrintDouble( char *pszBuffer, double dfValue )
 static void USGSDEMPrintSingle( char *pszBuffer, double dfValue )
 
 {
-#define DOUBLE_BUFFER_SIZE 64
+    if ( !pszBuffer )
+        return;
 
-    char    szTemp[DOUBLE_BUFFER_SIZE];
-    int     i;
 #ifdef MSVC_HACK
     const char *pszFormat = "%13.6e";
 #else
     const char *pszFormat = "%12.6e";
 #endif
 
-    if ( !pszBuffer )
-        return;
+    const int DOUBLE_BUFFER_SIZE = 64;
+    char szTemp[DOUBLE_BUFFER_SIZE];
     int nOffset = 0;
-#if defined(HAVE_SNPRINTF)
     if( CPLsnprintf( szTemp, DOUBLE_BUFFER_SIZE, pszFormat, dfValue ) == 13 &&
         szTemp[0] == ' ' )
     {
         nOffset = 1;
     }
-#else
-    CPLsprintf( szTemp, pszFormat, dfValue );
-#endif
     szTemp[DOUBLE_BUFFER_SIZE - 1] = '\0';
 
-    for( i = 0; szTemp[i] != '\0'; i++ )
+    for( int i = 0; szTemp[i] != '\0'; i++ )
     {
         if( szTemp[i] == 'E' || szTemp[i] == 'e' )
             szTemp[i] = 'D';
 #ifdef MSVC_HACK
         if( (szTemp[i] == '+' || szTemp[i] == '-')
-            && szTemp[i+1] == '0' && isdigit(szTemp[i+2]) 
+            && szTemp[i+1] == '0' && isdigit(szTemp[i+2])
             && isdigit(szTemp[i+3]) && szTemp[i+4] == '\0' )
         {
-            memmove( szTemp+i+1, szTemp+i+2, 2 );
+            szTemp[i+1] = szTemp[i+2];
+            szTemp[i+2] = szTemp[i+3];
             szTemp[i+3] = '\0';
             break;
         }
@@ -275,19 +282,16 @@ static void USGSDEMPrintSingle( char *pszBuffer, double dfValue )
 static int USGSDEMWriteARecord( USGSDEMWriteInfo *psWInfo )
 
 {
-    char achARec[1024];
-    int  i;
-    const char *pszOption;
-
 /* -------------------------------------------------------------------- */
 /*      Init to blanks.                                                 */
 /* -------------------------------------------------------------------- */
+    char achARec[1024];
     memset( achARec, ' ', sizeof(achARec) );
 
 /* -------------------------------------------------------------------- */
 /*      Load template file, if one is indicated.                        */
 /* -------------------------------------------------------------------- */
-    const char *pszTemplate = 
+    const char *pszTemplate =
         CSLFetchNameValue( psWInfo->papszOptions, "TEMPLATE" );
     if( pszTemplate != NULL )
     {
@@ -297,21 +301,21 @@ static int USGSDEMWriteARecord( USGSDEMWriteInfo *psWInfo )
         if( fpTemplate == NULL )
         {
             CPLError( CE_Failure, CPLE_OpenFailed,
-                      "Unable to open template file '%s'.\n%s", 
+                      "Unable to open template file '%s'.\n%s",
                       pszTemplate, VSIStrerror( errno ) );
             return FALSE;
         }
 
         if( VSIFReadL( achARec, 1, 1024, fpTemplate ) != 1024 )
         {
-            CPLError( CE_Failure, CPLE_FileIO, 
+            CPLError( CE_Failure, CPLE_FileIO,
                       "Unable to read 1024 byte A Record from template file '%s'.\n%s",
                       pszTemplate, VSIStrerror( errno ) );
             return FALSE;
         }
-        VSIFCloseL( fpTemplate );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fpTemplate ));
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Filename (right justify)                                        */
 /* -------------------------------------------------------------------- */
@@ -320,7 +324,8 @@ static int USGSDEMWriteARecord( USGSDEMWriteInfo *psWInfo )
 /* -------------------------------------------------------------------- */
 /*      Producer                                                        */
 /* -------------------------------------------------------------------- */
-    pszOption = CSLFetchNameValue( psWInfo->papszOptions, "PRODUCER" );
+    const char *pszOption
+        = CSLFetchNameValue( psWInfo->papszOptions, "PRODUCER" );
 
     if( pszOption != NULL )
         TextFillR( achARec +  40, 60, pszOption );
@@ -338,9 +343,9 @@ static int USGSDEMWriteARecord( USGSDEMWriteInfo *psWInfo )
 /* -------------------------------------------------------------------- */
     if ( ! psWInfo->utmzone )
     {
-        TextFill( achARec + 109, 13, 
+        TextFill( achARec + 109, 13,
             USGSDEMDecToPackedDMS( psWInfo->dfLLX ) ); // longitude
-        TextFill( achARec + 122, 13, 
+        TextFill( achARec + 122, 13,
             USGSDEMDecToPackedDMS( psWInfo->dfLLY ) ); // latitude
     }
     /* this may not be best according to the spec.  But for now,
@@ -356,7 +361,7 @@ static int USGSDEMWriteARecord( USGSDEMWriteInfo *psWInfo )
         TextFill( achARec + 135, 1, pszOption );
 
     else if( pszTemplate == NULL )
-        TextFill( achARec + 135, 1, " " ); 
+        TextFill( achARec + 135, 1, " " );
 
 /* -------------------------------------------------------------------- */
 /*      Filler                                                          */
@@ -368,7 +373,7 @@ static int USGSDEMWriteARecord( USGSDEMWriteInfo *psWInfo )
 /* -------------------------------------------------------------------- */
     if( pszTemplate == NULL )
         TextFill( achARec + 137, 3, "" );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Origin code                                                     */
 /* -------------------------------------------------------------------- */
@@ -387,18 +392,18 @@ static int USGSDEMWriteARecord( USGSDEMWriteInfo *psWInfo )
 
     if( pszOption != NULL )
         TextFillR( achARec + 144, 6, pszOption );  // 1, 2 or 3.
-        
+
     else if( pszTemplate == NULL )
         TextFillR( achARec + 144, 6, "1" );  // 1, 2 or 3.
         /* some DEM readers require a value, 1 seems to be a
          * default
          */
-    
+
 /* -------------------------------------------------------------------- */
 /*      Elevation Pattern                                               */
 /* -------------------------------------------------------------------- */
     TextFillR( achARec + 150, 6, "1" );  // "1" for regular (random is 2)
-    
+
 /* -------------------------------------------------------------------- */
 /*      Horizontal Reference System.                                    */
 /*                                                                      */
@@ -426,12 +431,12 @@ static int USGSDEMWriteARecord( USGSDEMWriteInfo *psWInfo )
     {
         TextFillR( achARec + 162, 6,
             CPLSPrintf( "%02d", psWInfo->utmzone) );
-    } 
-    
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Map Projection Parameters (all 0.0).                            */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < 15; i++ )
+    for( int i = 0; i < 15; i++ )
         TextFillR( achARec + 168 + i*24, 24, "0.0" );
 
 /* -------------------------------------------------------------------- */
@@ -515,10 +520,11 @@ static int USGSDEMWriteARecord( USGSDEMWriteInfo *psWInfo )
 /*      Minimum and Maximum elevations for this cell.                   */
 /*      24.15 format.                                                   */
 /* -------------------------------------------------------------------- */
-    GInt16  nMin = DEM_NODATA, nMax = DEM_NODATA;
+    GInt16  nMin = DEM_NODATA;
+    GInt16  nMax = DEM_NODATA;
     int     nVoid = 0;
 
-    for( i = psWInfo->nXSize*psWInfo->nYSize-1; i >= 0; i-- )
+    for( int i = psWInfo->nXSize*psWInfo->nYSize-1; i >= 0; i-- )
     {
         if( psWInfo->panData[i] != DEM_NODATA )
         {
@@ -528,8 +534,8 @@ static int USGSDEMWriteARecord( USGSDEMWriteInfo *psWInfo )
             }
             else
             {
-                nMin = MIN(nMin,psWInfo->panData[i]);
-                nMax = MAX(nMax,psWInfo->panData[i]);
+                nMin = std::min(nMin,psWInfo->panData[i]);
+                nMax = std::max(nMax,psWInfo->panData[i]);
             }
         }
         else
@@ -537,11 +543,11 @@ static int USGSDEMWriteARecord( USGSDEMWriteInfo *psWInfo )
     }
 
     /* take into account z resolutions that are not 1.0 */
-    nMin = (GInt16) floor(nMin * psWInfo->dfElevStepSize);
-    nMax = (GInt16) ceil(nMax * psWInfo->dfElevStepSize);
-    
-    USGSDEMPrintDouble( achARec + 738, (double) nMin );
-    USGSDEMPrintDouble( achARec + 762, (double) nMax );
+    nMin = static_cast<GInt16>( std::floor(nMin * psWInfo->dfElevStepSize) );
+    nMax = static_cast<GInt16>( std::ceil(nMax * psWInfo->dfElevStepSize) );
+
+    USGSDEMPrintDouble( achARec + 738, static_cast<double>( nMin ) );
+    USGSDEMPrintDouble( achARec + 762, static_cast<double>( nMax ) );
 
 /* -------------------------------------------------------------------- */
 /*      Counter Clockwise angle (in radians).  Normally 0               */
@@ -669,7 +675,7 @@ static int USGSDEMWriteARecord( USGSDEMWriteInfo *psWInfo )
 
     if( pszOption != NULL )
         TextFill( achARec + 892, 4, pszOption );
-        
+
     else if( pszTemplate == NULL )
         TextFill( achARec + 892, 4, "" );
 
@@ -678,11 +684,9 @@ static int USGSDEMWriteARecord( USGSDEMWriteInfo *psWInfo )
 /*                                                                      */
 /*      Round to nearest integer percentage.                            */
 /* -------------------------------------------------------------------- */
-    int nPercent;
-
-    nPercent = (int) 
+    int nPercent = static_cast<int>
         (((nVoid * 100.0) / (psWInfo->nXSize * psWInfo->nYSize)) + 0.5);
-        
+
     TextFillR( achARec + 896, 4, CPLSPrintf( "%4d", nPercent ) );
 
 /* -------------------------------------------------------------------- */
@@ -701,8 +705,8 @@ static int USGSDEMWriteARecord( USGSDEMWriteInfo *psWInfo )
 /* -------------------------------------------------------------------- */
     if( VSIFWriteL( achARec, 1, 1024, psWInfo->fp ) != 1024 )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
-                  "Error writing DEM/CDED A record.\n%s", 
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Error writing DEM/CDED A record.\n%s",
                   VSIStrerror( errno ) );
         return FALSE;
     }
@@ -747,8 +751,8 @@ static int USGSDEMWriteProfile( USGSDEMWriteInfo *psWInfo, int iProfile )
     if( ! psWInfo->utmzone )
     {
         // longitude
-        USGSDEMPrintDouble( achBuffer +  24, 
-                        3600 * (psWInfo->dfLLX 
+        USGSDEMPrintDouble( achBuffer +  24,
+                        3600 * (psWInfo->dfLLX
                                 + iProfile * psWInfo->dfHorizStepSize) );
 
         // latitude
@@ -757,8 +761,8 @@ static int USGSDEMWriteProfile( USGSDEMWriteInfo *psWInfo, int iProfile )
     else
     {
         // easting
-        USGSDEMPrintDouble( achBuffer +  24, 
-                        (psWInfo->dfLLX 
+        USGSDEMPrintDouble( achBuffer +  24,
+                        (psWInfo->dfLLX
                             + iProfile * psWInfo->dfHorizStepSize) );
 
         // northing
@@ -774,12 +778,12 @@ static int USGSDEMWriteProfile( USGSDEMWriteInfo *psWInfo, int iProfile )
 /* -------------------------------------------------------------------- */
 /*      Min/Max elevation values for this profile.                      */
 /* -------------------------------------------------------------------- */
-    int iY; 
-    GInt16  nMin = DEM_NODATA, nMax = DEM_NODATA;
+    GInt16  nMin = DEM_NODATA;
+    GInt16  nMax = DEM_NODATA;
 
-    for( iY = 0; iY < psWInfo->nYSize; iY++ )
+    for( int iY = 0; iY < psWInfo->nYSize; iY++ )
     {
-        int iData = (psWInfo->nYSize-iY-1) * psWInfo->nXSize + iProfile; 
+        const int iData = (psWInfo->nYSize-iY-1) * psWInfo->nXSize + iProfile;
 
         if( psWInfo->panData[iData] != DEM_NODATA )
         {
@@ -789,18 +793,18 @@ static int USGSDEMWriteProfile( USGSDEMWriteInfo *psWInfo, int iProfile )
             }
             else
             {
-                nMin = MIN(nMin,psWInfo->panData[iData]);
-                nMax = MAX(nMax,psWInfo->panData[iData]);
+                nMin = std::min(nMin,psWInfo->panData[iData]);
+                nMax = std::max(nMax,psWInfo->panData[iData]);
             }
         }
     }
-    
+
     /* take into account z resolutions that are not 1.0 */
-    nMin = (GInt16) floor(nMin * psWInfo->dfElevStepSize);
-    nMax = (GInt16) ceil(nMax * psWInfo->dfElevStepSize);
+    nMin = static_cast<GInt16>( std::floor(nMin * psWInfo->dfElevStepSize) );
+    nMax = static_cast<GInt16>( std::ceil(nMax * psWInfo->dfElevStepSize) );
 
-    USGSDEMPrintDouble( achBuffer +  96, (double) nMin );
-    USGSDEMPrintDouble( achBuffer +  120, (double) nMax );
+    USGSDEMPrintDouble( achBuffer +  96, static_cast<double>( nMin ) );
+    USGSDEMPrintDouble( achBuffer +  120, static_cast<double>( nMax ) );
 
 /* -------------------------------------------------------------------- */
 /*      Output all the actually elevation values, flushing blocks       */
@@ -808,17 +812,16 @@ static int USGSDEMWriteProfile( USGSDEMWriteInfo *psWInfo, int iProfile )
 /* -------------------------------------------------------------------- */
     int iOffset = 144;
 
-    for( iY = 0; iY < psWInfo->nYSize; iY++ )
+    for( int iY = 0; iY < psWInfo->nYSize; iY++ )
     {
-        int iData = (psWInfo->nYSize-iY-1) * psWInfo->nXSize + iProfile; 
-        char szWord[10];
+        const int iData = (psWInfo->nYSize-iY-1) * psWInfo->nXSize + iProfile;
 
         if( iOffset + 6 > 1024 )
         {
             if( VSIFWriteL( achBuffer, 1, 1024, psWInfo->fp ) != 1024 )
             {
-                CPLError( CE_Failure, CPLE_FileIO, 
-                          "Failure writing profile to disk.\n%s", 
+                CPLError( CE_Failure, CPLE_FileIO,
+                          "Failure writing profile to disk.\n%s",
                           VSIStrerror( errno ) );
                 return FALSE;
             }
@@ -826,9 +829,10 @@ static int USGSDEMWriteProfile( USGSDEMWriteInfo *psWInfo, int iProfile )
             memset( achBuffer, ' ', 1024 );
         }
 
-        sprintf( szWord, "%d", psWInfo->panData[iData] );
+        char szWord[10];
+        snprintf( szWord, sizeof(szWord), "%d", psWInfo->panData[iData] );
         TextFillR( achBuffer + iOffset, 6, szWord );
-        
+
         iOffset += 6;
     }
 
@@ -837,8 +841,8 @@ static int USGSDEMWriteProfile( USGSDEMWriteInfo *psWInfo, int iProfile )
 /* -------------------------------------------------------------------- */
     if( VSIFWriteL( achBuffer, 1, 1024, psWInfo->fp ) != 1024 )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
-                  "Failure writing profile to disk.\n%s", 
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Failure writing profile to disk.\n%s",
                   VSIStrerror( errno ) );
         return FALSE;
     }
@@ -850,7 +854,7 @@ static int USGSDEMWriteProfile( USGSDEMWriteInfo *psWInfo, int iProfile )
 /*                      USGSDEM_LookupNTSByLoc()                        */
 /************************************************************************/
 
-static int 
+static int
 USGSDEM_LookupNTSByLoc( double dfULLong, double dfULLat,
                         char *pszTile, char *pszName )
 
@@ -859,12 +863,11 @@ USGSDEM_LookupNTSByLoc( double dfULLong, double dfULLat,
 /*      Access NTS 1:50k sheet CSV file.                                */
 /* -------------------------------------------------------------------- */
     const char *pszNTSFilename = CSVFilename( "NTS-50kindex.csv" );
-    FILE *fpNTS;
 
-    fpNTS = VSIFOpen( pszNTSFilename, "rb" );
+    FILE *fpNTS = VSIFOpen( pszNTSFilename, "rb" );
     if( fpNTS == NULL )
     {
-        CPLError( CE_Failure, CPLE_FileIO, "Unable to find NTS mapsheet lookup file: %s", 
+        CPLError( CE_Failure, CPLE_FileIO, "Unable to find NTS mapsheet lookup file: %s",
                   pszNTSFilename );
         return FALSE;
     }
@@ -880,13 +883,16 @@ USGSDEM_LookupNTSByLoc( double dfULLong, double dfULLat,
     int  bGotHit = FALSE;
     char **papszTokens;
 
-    while( !bGotHit 
+    while( !bGotHit
            && (papszTokens = CSVReadParseLine( fpNTS )) != NULL )
     {
         if( CSLCount( papszTokens ) != 4 )
+        {
+            CSLDestroy( papszTokens );
             continue;
+        }
 
-        if( ABS(dfULLong - CPLAtof(papszTokens[2])) < 0.01 
+        if( ABS(dfULLong - CPLAtof(papszTokens[2])) < 0.01
             && ABS(dfULLat - CPLAtof(papszTokens[3])) < 0.01 )
         {
             bGotHit = TRUE;
@@ -898,7 +904,7 @@ USGSDEM_LookupNTSByLoc( double dfULLong, double dfULLat,
         CSLDestroy( papszTokens );
     }
 
-    VSIFClose( fpNTS );
+    CPL_IGNORE_RET_VAL(VSIFClose( fpNTS ));
 
     return bGotHit;
 }
@@ -907,7 +913,7 @@ USGSDEM_LookupNTSByLoc( double dfULLong, double dfULLat,
 /*                      USGSDEM_LookupNTSByTile()                       */
 /************************************************************************/
 
-static int 
+static int
 USGSDEM_LookupNTSByTile( const char *pszTile, char *pszName,
                          double *pdfULLong, double *pdfULLat )
 
@@ -921,7 +927,7 @@ USGSDEM_LookupNTSByTile( const char *pszTile, char *pszName,
     fpNTS = VSIFOpen( pszNTSFilename, "rb" );
     if( fpNTS == NULL )
     {
-        CPLError( CE_Failure, CPLE_FileIO, "Unable to find NTS mapsheet lookup file: %s", 
+        CPLError( CE_Failure, CPLE_FileIO, "Unable to find NTS mapsheet lookup file: %s",
                   pszNTSFilename );
         return FALSE;
     }
@@ -934,18 +940,21 @@ USGSDEM_LookupNTSByTile( const char *pszTile, char *pszName,
 /* -------------------------------------------------------------------- */
 /*      Find desired sheet.                                             */
 /* -------------------------------------------------------------------- */
-    int  bGotHit = FALSE;
+    bool bGotHit = false;
     char **papszTokens;
 
-    while( !bGotHit 
+    while( !bGotHit
            && (papszTokens = CSVReadParseLine( fpNTS )) != NULL )
     {
         if( CSLCount( papszTokens ) != 4 )
+        {
+            CSLDestroy( papszTokens );
             continue;
+        }
 
         if( EQUAL(pszTile,papszTokens[0]) )
         {
-            bGotHit = TRUE;
+            bGotHit = true;
             if( pszName != NULL )
                 strncpy( pszName, papszTokens[1], 100 );
             *pdfULLong = CPLAtof(papszTokens[2]);
@@ -955,7 +964,7 @@ USGSDEM_LookupNTSByTile( const char *pszTile, char *pszName,
         CSLDestroy( papszTokens );
     }
 
-    VSIFClose( fpNTS );
+    CPL_IGNORE_RET_VAL(VSIFClose( fpNTS ));
 
     return bGotHit;
 }
@@ -971,14 +980,13 @@ static int USGSDEMProductSetup_CDED50K( USGSDEMWriteInfo *psWInfo )
 /*      Fetch TOPLEFT location so we know what cell we are dealing      */
 /*      with.                                                           */
 /* -------------------------------------------------------------------- */
-    const char *pszNTS = 
-        CSLFetchNameValue( psWInfo->papszOptions, "NTS" );
-    const char *pszTOPLEFT = CSLFetchNameValue( psWInfo->papszOptions, 
+    const char *pszNTS = CSLFetchNameValue( psWInfo->papszOptions, "NTS" );
+    const char *pszTOPLEFT = CSLFetchNameValue( psWInfo->papszOptions,
                                                 "TOPLEFT" );
     double dfULX = (psWInfo->dfULX+psWInfo->dfURX)*0.5;
     double dfULY = (psWInfo->dfULY+psWInfo->dfURY)*0.5;
 
-    // Have we been given an explicit NTS mapsheet name? 
+    // Have we been given an explicit NTS mapsheet name?
     if( pszNTS != NULL )
     {
         char szTrimmedTile[7];
@@ -989,7 +997,7 @@ static int USGSDEMProductSetup_CDED50K( USGSDEMWriteInfo *psWInfo )
         if( !USGSDEM_LookupNTSByTile( szTrimmedTile, NULL, &dfULX, &dfULY ) )
             return FALSE;
 
-        if( EQUALN(pszNTS+6,"e",1) )
+        if( STARTS_WITH_CI(pszNTS+6, "e") )
             dfULX += (( dfULY < 68.1 ) ? 0.25 : ( dfULY < 80.1 ) ? 0.5 : 1);
     }
 
@@ -1017,7 +1025,7 @@ static int USGSDEMProductSetup_CDED50K( USGSDEMWriteInfo *psWInfo )
         if( CSLCount( papszTokens ) != 2 )
         {
             CSLDestroy( papszTokens );
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Failed to parse TOPLEFT, should have form like '138d15W,59d0N'." );
             return FALSE;
         }
@@ -1026,15 +1034,15 @@ static int USGSDEMProductSetup_CDED50K( USGSDEMWriteInfo *psWInfo )
         dfULY = CPLDMSToDec( papszTokens[1] );
         CSLDestroy( papszTokens );
 
-        if( ABS(dfULX*4-floor(dfULX*4+0.00005)) > 0.0001 
+        if( ABS(dfULX*4-floor(dfULX*4+0.00005)) > 0.0001
             || ABS(dfULY*4-floor(dfULY*4+0.00005)) > 0.0001 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "TOPLEFT must be on a 15\" boundary for CDED50K, but is not." );
             return FALSE;
         }
     }
-    else if( strlen(psWInfo->pszFilename) == 12 
+    else if( strlen(psWInfo->pszFilename) == 12
              && psWInfo->pszFilename[6] == '_'
              && EQUAL(psWInfo->pszFilename+8,".dem") )
     {
@@ -1046,12 +1054,12 @@ static int USGSDEMProductSetup_CDED50K( USGSDEMWriteInfo *psWInfo )
         if( !USGSDEM_LookupNTSByTile( szTrimmedTile, NULL, &dfULX, &dfULY ) )
             return FALSE;
 
-        if( EQUALN(psWInfo->pszFilename+7,"e",1) )
+        if( STARTS_WITH_CI(psWInfo->pszFilename+7, "e") )
             dfULX += (( dfULY < 68.1 ) ? 0.25 : ( dfULY < 80.1 ) ? 0.5 : 1);
     }
-             
-    else if( strlen(psWInfo->pszFilename) == 14 
-             && EQUALN(psWInfo->pszFilename+6,"DEM",3)
+
+    else if( strlen(psWInfo->pszFilename) == 14
+             && STARTS_WITH_CI(psWInfo->pszFilename+6, "DEM")
              && EQUAL(psWInfo->pszFilename+10,".dem") )
     {
         char szTrimmedTile[7];
@@ -1062,7 +1070,7 @@ static int USGSDEMProductSetup_CDED50K( USGSDEMWriteInfo *psWInfo )
         if( !USGSDEM_LookupNTSByTile( szTrimmedTile, NULL, &dfULX, &dfULY ) )
             return FALSE;
 
-        if( EQUALN(psWInfo->pszFilename+9,"e",1) )
+        if( STARTS_WITH_CI(psWInfo->pszFilename+9, "e") )
             dfULX += (( dfULY < 68.1 ) ? 0.25 : ( dfULY < 80.1 ) ? 0.5 : 1);
     }
 
@@ -1114,7 +1122,7 @@ static int USGSDEMProductSetup_CDED50K( USGSDEMWriteInfo *psWInfo )
 /*      Can we find the NTS 50k tile name that corresponds with         */
 /*      this?                                                           */
 /* -------------------------------------------------------------------- */
-    const char *pszINTERNAL = 
+    const char *pszINTERNAL =
         CSLFetchNameValue( psWInfo->papszOptions, "INTERNALNAME" );
     char szTile[10];
     char chEWFlag = ' ';
@@ -1136,13 +1144,13 @@ static int USGSDEMProductSetup_CDED50K( USGSDEMWriteInfo *psWInfo )
     else if( chEWFlag != ' ' )
     {
         CPLFree( psWInfo->pszFilename );
-        psWInfo->pszFilename = 
+        psWInfo->pszFilename =
             CPLStrdup( CPLSPrintf("%sDEM%c", szTile, chEWFlag ) );
     }
     else
     {
         const char *pszBasename = CPLGetFilename( psWInfo->pszFilename);
-        if( !EQUALN(pszBasename+6,"DEM",3) 
+        if( !STARTS_WITH_CI(pszBasename+6, "DEM")
             || strlen(pszBasename) != 10 )
             CPLError( CE_Warning, CPLE_AppDefined,
                       "Internal filename required to be of 'nnnannDEMz', the output\n"
@@ -1154,12 +1162,12 @@ static int USGSDEMProductSetup_CDED50K( USGSDEMWriteInfo *psWInfo )
 /* -------------------------------------------------------------------- */
 /*      Set some specific options for CDED 50K.                         */
 /* -------------------------------------------------------------------- */
-    psWInfo->papszOptions = 
+    psWInfo->papszOptions =
         CSLSetNameValue( psWInfo->papszOptions, "DEMLevelCode", "1" );
 
     if( CSLFetchNameValue( psWInfo->papszOptions, "DataSpecVersion" ) == NULL )
-        psWInfo->papszOptions = 
-            CSLSetNameValue( psWInfo->papszOptions, "DataSpecVersion", 
+        psWInfo->papszOptions =
+            CSLSetNameValue( psWInfo->papszOptions, "DataSpecVersion",
                              "1020" );
 
 /* -------------------------------------------------------------------- */
@@ -1201,35 +1209,34 @@ static int USGSDEMProductSetup_DEFAULT( USGSDEMWriteInfo *psWInfo )
 /* -------------------------------------------------------------------- */
     OGRSpatialReference DstoSRS;
     OGRSpatialReference SrcoSRS;
-    char                *sourceWkt;
     int                 bNorth = TRUE;
         /* XXX here we are assume (!) northern hemisphere UTM datasets  */
-    char                **readSourceWkt;
-    int                 i;
     int                 numdatums = 4;
     const char          DatumCodes[4][2] = { "1", "2", "3", "4" };
     char                Datums[4][6] = { "NAD27", "WGS72", "WGS84",
                                             "NAD83" };
 
     /* get the source dataset's projection */
-    sourceWkt = (char *) psWInfo->poSrcDS->GetProjectionRef();
-    readSourceWkt = &sourceWkt;
+    char *sourceWkt
+        = const_cast<char *>( psWInfo->poSrcDS->GetProjectionRef() );
+    char **readSourceWkt = &sourceWkt;
     if (SrcoSRS.importFromWkt(readSourceWkt) != OGRERR_NONE)
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
             "DEM Default Setup: Importing source dataset projection failed" );
         return FALSE;
     }
-    
+
     /* Set the destination dataset's projection.  If the source datum
      * used is DEM compatible, just use it.  Otherwise, default to the
      * last datum in the Datums array.
      */
-    for( i=0; i < numdatums; i++ )
+    int i = 0;
+    for( ; i < numdatums; i++ )
     {
         if (DstoSRS.SetWellKnownGeogCS(Datums[i]) != OGRERR_NONE)
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                 "DEM Default Setup: Failed to set datum of destination" );
             return FALSE;
         }
@@ -1242,15 +1249,15 @@ static int USGSDEMProductSetup_DEFAULT( USGSDEMWriteInfo *psWInfo )
             break;
         }
     }
-    strncpy( psWInfo->horizdatum, DatumCodes[i], 2 );
-    
+    CPLStrlcpy( psWInfo->horizdatum, DatumCodes[i], 2 );
+
     /* get the UTM zone, if any */
     psWInfo->utmzone = SrcoSRS.GetUTMZone(&bNorth);
     if (psWInfo->utmzone)
     {
         if (DstoSRS.SetUTM(psWInfo->utmzone) != OGRERR_NONE)
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
               "DEM Default Setup: Failed to set utm zone of destination" );
             /* SetUTM isn't documented to return OGRERR_NONE
              * on success, but it does, so, we'll check for it.
@@ -1258,11 +1265,11 @@ static int USGSDEMProductSetup_DEFAULT( USGSDEMWriteInfo *psWInfo )
             return FALSE;
         }
     }
-    
+
     /* export the projection to sWInfo */
     if (DstoSRS.exportToWkt( &(psWInfo->pszDstSRS) ) != OGRERR_NONE)
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
             "UTMDEM: Failed to export destination Wkt to psWInfo" );
     }
     return TRUE;
@@ -1279,30 +1286,24 @@ static int USGSDEMProductSetup_DEFAULT( USGSDEMWriteInfo *psWInfo )
 static int USGSDEMLoadRaster( CPL_UNUSED USGSDEMWriteInfo *psWInfo,
                               CPL_UNUSED GDALRasterBand *poSrcBand )
 {
-    CPLErr eErr;
-    int i;
-
 /* -------------------------------------------------------------------- */
 /*      Allocate output array, and pre-initialize to NODATA value.      */
 /* -------------------------------------------------------------------- */
-    psWInfo->panData = 
-        (GInt16 *) VSIMalloc3( 2, psWInfo->nXSize, psWInfo->nYSize );
+    psWInfo->panData = reinterpret_cast<GInt16 *>(
+        VSI_MALLOC3_VERBOSE( 2, psWInfo->nXSize, psWInfo->nYSize ) );
     if( psWInfo->panData == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory, 
-                  "Out of memory allocating %d byte internal copy of DEM.", 
-                  2 * psWInfo->nXSize * psWInfo->nYSize );
         return FALSE;
     }
 
-    for( i = 0; i < psWInfo->nXSize * psWInfo->nYSize; i++ )
+    for( int i = 0; i < psWInfo->nXSize * psWInfo->nYSize; i++ )
         psWInfo->panData[i] = DEM_NODATA;
 
 /* -------------------------------------------------------------------- */
 /*      Make a "memory dataset" wrapper for this data array.            */
 /* -------------------------------------------------------------------- */
-    GDALDriver  *poMemDriver = (GDALDriver *) GDALGetDriverByName( "MEM" );
-    GDALDataset *poMemDS;
+    GDALDriver  *poMemDriver = reinterpret_cast<GDALDriver *>(
+        GDALGetDriverByName( "MEM" ) );
 
     if( poMemDriver == NULL )
     {
@@ -1310,10 +1311,10 @@ static int USGSDEMLoadRaster( CPL_UNUSED USGSDEMWriteInfo *psWInfo,
                   "Failed to find MEM driver." );
         return FALSE;
     }
-   
-    poMemDS = 
-        poMemDriver->Create( "USGSDEM_temp", psWInfo->nXSize, psWInfo->nYSize, 
-                         0, GDT_Int16, NULL );
+
+    GDALDataset *poMemDS
+        = poMemDriver->Create( "USGSDEM_temp", psWInfo->nXSize, psWInfo->nYSize,
+                               0, GDT_Int16, NULL );
     if( poMemDS == NULL )
         return FALSE;
 
@@ -1324,10 +1325,10 @@ static int USGSDEMLoadRaster( CPL_UNUSED USGSDEMWriteInfo *psWInfo,
     char *apszOptions[] = { szDataPointer, NULL };
 
     memset( szDataPointer, 0, sizeof(szDataPointer) );
-    sprintf( szDataPointer, "DATAPOINTER=" );
-    CPLPrintPointer( szDataPointer+strlen(szDataPointer), 
-                     psWInfo->panData, 
-                     sizeof(szDataPointer) - strlen(szDataPointer) );
+    snprintf( szDataPointer, sizeof(szDataPointer), "DATAPOINTER=" );
+    CPLPrintPointer( szDataPointer+strlen(szDataPointer),
+                     psWInfo->panData,
+                     static_cast<int>(sizeof(szDataPointer) - strlen(szDataPointer)) );
 
     if( poMemDS->AddBand( GDT_Int16, apszOptions ) != CE_None )
         return FALSE;
@@ -1356,7 +1357,7 @@ static int USGSDEMLoadRaster( CPL_UNUSED USGSDEMWriteInfo *psWInfo,
 /*      Establish the resampling kernel to use.                         */
 /* -------------------------------------------------------------------- */
     GDALResampleAlg eResampleAlg = GRA_Bilinear;
-    const char *pszResample = CSLFetchNameValue( psWInfo->papszOptions, 
+    const char *pszResample = CSLFetchNameValue( psWInfo->papszOptions,
                                                  "RESAMPLE" );
 
     if( pszResample == NULL )
@@ -1371,21 +1372,21 @@ static int USGSDEMLoadRaster( CPL_UNUSED USGSDEMWriteInfo *psWInfo,
         eResampleAlg = GRA_CubicSpline;
     else
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
-                  "RESAMPLE=%s, not a supported resampling kernel.", 
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "RESAMPLE=%s, not a supported resampling kernel.",
                   pszResample );
         return FALSE;
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Perform a warp from source dataset to destination buffer        */
 /*      (memory dataset).                                               */
 /* -------------------------------------------------------------------- */
-    eErr = GDALReprojectImage( (GDALDatasetH) psWInfo->poSrcDS, 
+    CPLErr eErr = GDALReprojectImage( (GDALDatasetH) psWInfo->poSrcDS,
                                psWInfo->poSrcDS->GetProjectionRef(),
-                               (GDALDatasetH) poMemDS, 
+                               (GDALDatasetH) poMemDS,
                                psWInfo->pszDstSRS,
-                               eResampleAlg, 0.0, 0.0, NULL, NULL, 
+                               eResampleAlg, 0.0, 0.0, NULL, NULL,
                                NULL );
 
 /* -------------------------------------------------------------------- */
@@ -1409,11 +1410,9 @@ USGSDEMCreateCopy( const char *pszFilename,
                    CPL_UNUSED GDALProgressFunc pfnProgress,
                    CPL_UNUSED void * pProgressData )
 {
-    USGSDEMWriteInfo sWInfo;
-
     if( poSrcDS->GetRasterCount() != 1 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to create multi-band USGS DEM / CDED files." );
         return NULL;
     }
@@ -1421,6 +1420,7 @@ USGSDEMCreateCopy( const char *pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Capture some preliminary information.                           */
 /* -------------------------------------------------------------------- */
+    USGSDEMWriteInfo sWInfo;
     memset( &sWInfo, 0, sizeof(sWInfo) );
 
     sWInfo.poSrcDS = poSrcDS;
@@ -1434,7 +1434,7 @@ USGSDEMCreateCopy( const char *pszFilename,
 
     if ( sWInfo.nXSize <= 1 || sWInfo.nYSize <= 1 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Source dataset dimensions must be at least 2x2." );
         return NULL;
     }
@@ -1445,21 +1445,21 @@ USGSDEMCreateCopy( const char *pszFilename,
     double adfGeoTransform[6];
 
     poSrcDS->GetGeoTransform( adfGeoTransform );
-    
+
     sWInfo.dfLLX = adfGeoTransform[0] + adfGeoTransform[1] * 0.5;
-    sWInfo.dfLLY = adfGeoTransform[3] 
+    sWInfo.dfLLY = adfGeoTransform[3]
         + adfGeoTransform[5] * (sWInfo.nYSize - 0.5);
 
     sWInfo.dfULX = adfGeoTransform[0] + adfGeoTransform[1] * 0.5;
     sWInfo.dfULY = adfGeoTransform[3] + adfGeoTransform[5] * 0.5;
-    
+
     sWInfo.dfURX = adfGeoTransform[0]
         + adfGeoTransform[1] * (sWInfo.nXSize - 0.5);
     sWInfo.dfURY = adfGeoTransform[3] + adfGeoTransform[5] * 0.5;
-    
-    sWInfo.dfLRX = adfGeoTransform[0] 
+
+    sWInfo.dfLRX = adfGeoTransform[0]
         + adfGeoTransform[1] * (sWInfo.nXSize - 0.5);
-    sWInfo.dfLRY = adfGeoTransform[3] 
+    sWInfo.dfLRY = adfGeoTransform[3]
         + adfGeoTransform[5] * (sWInfo.nYSize - 0.5);
 
     sWInfo.dfHorizStepSize = (sWInfo.dfURX - sWInfo.dfULX) / (sWInfo.nXSize-1);
@@ -1475,7 +1475,7 @@ USGSDEMCreateCopy( const char *pszFilename,
      {
          sWInfo.dfElevStepSize = 1.0;
      }
-     else 
+     else
      {
          // XXX: We are using CPLAtof() here instead of CPLAtof() because
          // zResolution value comes from user's input and supposed to be
@@ -1488,11 +1488,11 @@ USGSDEMCreateCopy( const char *pszFilename,
              sWInfo.dfElevStepSize = 1.0;
          }
      }
- 
+
 /* -------------------------------------------------------------------- */
 /*      Initialize for special product configurations.                  */
 /* -------------------------------------------------------------------- */
-    const char *pszProduct = CSLFetchNameValue( sWInfo.papszOptions, 
+    const char *pszProduct = CSLFetchNameValue( sWInfo.papszOptions,
                                                 "PRODUCT" );
 
     if( pszProduct == NULL || EQUAL(pszProduct,"DEFAULT") )
@@ -1513,13 +1513,13 @@ USGSDEMCreateCopy( const char *pszFilename,
     }
     else
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
-                  "DEM PRODUCT='%s' not recognised.", 
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "DEM PRODUCT='%s' not recognised.",
                   pszProduct );
         USGSDEMWriteCleanup( &sWInfo );
         return NULL;
     }
-    
+
 
 /* -------------------------------------------------------------------- */
 /*      Read the whole area of interest into memory.                    */
@@ -1536,7 +1536,7 @@ USGSDEMCreateCopy( const char *pszFilename,
     sWInfo.fp = VSIFOpenL( pszFilename, "wb" );
     if( sWInfo.fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "%s", VSIStrerror( errno ) );
         USGSDEMWriteCleanup( &sWInfo );
         return NULL;
@@ -1545,7 +1545,7 @@ USGSDEMCreateCopy( const char *pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Write the A record.                                             */
 /* -------------------------------------------------------------------- */
-    if( !USGSDEMWriteARecord( &sWInfo ) ) 
+    if( !USGSDEMWriteARecord( &sWInfo ) )
     {
         USGSDEMWriteCleanup( &sWInfo );
         return NULL;
@@ -1554,9 +1554,7 @@ USGSDEMCreateCopy( const char *pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Write profiles.                                                 */
 /* -------------------------------------------------------------------- */
-    int iProfile;
-
-    for( iProfile = 0; iProfile < sWInfo.nXSize; iProfile++ )
+    for( int iProfile = 0; iProfile < sWInfo.nXSize; iProfile++ )
     {
         if( !USGSDEMWriteProfile( &sWInfo, iProfile ) )
         {
@@ -1564,7 +1562,7 @@ USGSDEMCreateCopy( const char *pszFilename,
             return NULL;
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Cleanup.                                                        */
 /* -------------------------------------------------------------------- */
@@ -1573,8 +1571,8 @@ USGSDEMCreateCopy( const char *pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Re-open dataset, and copy any auxiliary pam information.         */
 /* -------------------------------------------------------------------- */
-    GDALPamDataset *poDS = (GDALPamDataset *)
-        GDALOpen( pszFilename, GA_ReadOnly );
+    GDALPamDataset *poDS = reinterpret_cast<GDALPamDataset *>(
+        GDALOpen( pszFilename, GA_ReadOnly ) );
 
     if( poDS )
         poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
diff --git a/frmts/usgsdem/usgsdemdataset.cpp b/frmts/usgsdem/usgsdemdataset.cpp
index 0da5164..edc27ce 100644
--- a/frmts/usgsdem/usgsdemdataset.cpp
+++ b/frmts/usgsdem/usgsdemdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: usgsdemdataset.cpp 28351 2015-01-23 18:47:42Z rouault $
+ * $Id: usgsdemdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  USGS DEM Driver
  * Purpose:  All reader for USGS DEM Reader
@@ -31,76 +31,64 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: usgsdemdataset.cpp 28351 2015-01-23 18:47:42Z rouault $");
+#include <algorithm>
 
-CPL_C_START
-void	GDALRegister_USGSDEM(void);
-CPL_C_END
+CPL_CVSID("$Id: usgsdemdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 typedef struct {
     double	x;
     double	y;
 } DPoint2;
 
-#define USGSDEM_NODATA	-32767
+static const int USGSDEM_NODATA = -32767;
 
 GDALDataset *USGSDEMCreateCopy( const char *, GDALDataset *, int, char **,
-                                GDALProgressFunc pfnProgress, 
+                                GDALProgressFunc pfnProgress,
                                 void * pProgressData );
 
-
 /************************************************************************/
 /*                              ReadInt()                               */
 /************************************************************************/
 
 static int ReadInt( VSILFILE *fp )
 {
-    int nVal = 0;
     char c;
     int nRead = 0;
-    vsi_l_offset nOffset = VSIFTellL(fp);
+    char szBuffer[12];
+    bool bInProlog = true;
 
-    while (TRUE)
+    while( true )
     {
         if (VSIFReadL(&c, 1, 1, fp) != 1)
         {
             return 0;
         }
-        else
-            nRead ++;
-        if (!isspace((int)c))
-            break;
-    }
-
-    int nSign = 1;
-    if (c == '-')
-        nSign = -1;
-    else if (c == '+')
-        nSign = 1;
-    else if (c >= '0' && c <= '9')
-        nVal = c - '0';
-    else
-    {
-        VSIFSeekL(fp, nOffset + nRead, SEEK_SET);
-        return 0;
-    }
-
-    while (TRUE)
-    {
-        if (VSIFReadL(&c, 1, 1, fp) != 1)
-            return nSign * nVal;
-        nRead ++;
-        if (c >= '0' && c <= '9')
-            nVal = nVal * 10 + (c - '0');
-        else
+        if( bInProlog )
         {
-            VSIFSeekL(fp, nOffset + (nRead - 1), SEEK_SET);
-            return nSign * nVal;
+            if ( !isspace( static_cast<int>(c) ) )
+            {
+                bInProlog = false;
+            }
         }
+        if( !bInProlog )
+        {
+            if( c != '-' && c != '+' && !(c >= '0' && c <= '9') )
+            {
+                CPL_IGNORE_RET_VAL(VSIFSeekL(fp, VSIFTellL(fp) - 1, SEEK_SET));
+                break;
+            }
+            if( nRead < 11 )
+                szBuffer[nRead] = c;
+            nRead ++;
+        }
+
     }
+    szBuffer[MIN(nRead, 11)] = 0;
+    return atoi(szBuffer);
 }
 
 typedef struct
@@ -122,9 +110,9 @@ static void USGSDEMRefillBuffer( Buffer* psBuffer )
             psBuffer->buffer_size - psBuffer->cur_index);
 
     psBuffer->buffer_size -= psBuffer->cur_index;
-    psBuffer->buffer_size += VSIFReadL(psBuffer->buffer + psBuffer->buffer_size,
+    psBuffer->buffer_size += static_cast<int>(VSIFReadL(psBuffer->buffer + psBuffer->buffer_size,
                                        1, psBuffer->max_size - psBuffer->buffer_size,
-                                       psBuffer->fp);
+                                       psBuffer->fp));
     psBuffer->cur_index = 0;
 }
 
@@ -134,10 +122,9 @@ static void USGSDEMRefillBuffer( Buffer* psBuffer )
 
 static int USGSDEMReadIntFromBuffer( Buffer* psBuffer, int* pbSuccess = NULL )
 {
-    int nVal = 0;
     char c;
 
-    while (TRUE)
+    while (true)
     {
         if (psBuffer->cur_index >= psBuffer->buffer_size)
         {
@@ -151,10 +138,11 @@ static int USGSDEMReadIntFromBuffer( Buffer* psBuffer, int* pbSuccess = NULL )
 
         c = psBuffer->buffer[psBuffer->cur_index];
         psBuffer->cur_index ++;
-        if (!isspace((int)c))
+        if ( !isspace( static_cast<int>(c) ) )
             break;
     }
 
+    GIntBig nVal = 0;
     int nSign = 1;
     if (c == '-')
         nSign = -1;
@@ -168,7 +156,7 @@ static int USGSDEMReadIntFromBuffer( Buffer* psBuffer, int* pbSuccess = NULL )
         return 0;
     }
 
-    while (TRUE)
+    while (true)
     {
         if (psBuffer->cur_index >= psBuffer->buffer_size)
         {
@@ -176,7 +164,7 @@ static int USGSDEMReadIntFromBuffer( Buffer* psBuffer, int* pbSuccess = NULL )
             if (psBuffer->cur_index >= psBuffer->buffer_size)
             {
                 if( pbSuccess ) *pbSuccess = TRUE;
-                return nSign * nVal;
+                return static_cast<int>(nSign * nVal);
             }
         }
 
@@ -184,12 +172,25 @@ static int USGSDEMReadIntFromBuffer( Buffer* psBuffer, int* pbSuccess = NULL )
         if (c >= '0' && c <= '9')
         {
             psBuffer->cur_index ++;
-            nVal = nVal * 10 + (c - '0');
+            if( nVal * nSign < INT_MAX && nVal * nSign > INT_MIN )
+            {
+                nVal = nVal * 10 + (c - '0');
+                if( nVal * nSign > INT_MAX )
+                {
+                    nVal = INT_MAX;
+                    nSign = 1;
+                }
+                else if( nVal * nSign < INT_MIN )
+                {
+                    nVal = INT_MIN;
+                    nSign = 1;
+                }
+            }
         }
         else
         {
             if( pbSuccess ) *pbSuccess = TRUE;
-            return nSign * nVal;
+            return static_cast<int>(nSign * nVal);
         }
     }
 }
@@ -198,16 +199,15 @@ static int USGSDEMReadIntFromBuffer( Buffer* psBuffer, int* pbSuccess = NULL )
 /*                USGSDEMReadDoubleFromBuffer()                         */
 /************************************************************************/
 
-static double USGSDEMReadDoubleFromBuffer( Buffer* psBuffer, int nCharCount )
+static double USGSDEMReadDoubleFromBuffer( Buffer* psBuffer, int nCharCount, int *pbSuccess = NULL)
 
 {
-    int     i;
-
     if (psBuffer->cur_index + nCharCount > psBuffer->buffer_size)
     {
         USGSDEMRefillBuffer(psBuffer);
         if (psBuffer->cur_index + nCharCount > psBuffer->buffer_size)
         {
+            if( pbSuccess ) *pbSuccess = FALSE;
             return 0;
         }
     }
@@ -215,7 +215,7 @@ static double USGSDEMReadDoubleFromBuffer( Buffer* psBuffer, int nCharCount )
     char* szPtr = psBuffer->buffer + psBuffer->cur_index;
     char backupC = szPtr[nCharCount];
     szPtr[nCharCount] = 0;
-    for( i = 0; i < nCharCount; i++ )
+    for( int i = 0; i < nCharCount; i++ )
     {
         if( szPtr[i] == 'D' )
             szPtr[i] = 'E';
@@ -225,6 +225,7 @@ static double USGSDEMReadDoubleFromBuffer( Buffer* psBuffer, int nCharCount )
     szPtr[nCharCount] = backupC;
     psBuffer->cur_index += nCharCount;
 
+    if( pbSuccess ) *pbSuccess = TRUE;
     return dfVal;
 }
 
@@ -236,12 +237,11 @@ static double DConvert( VSILFILE *fp, int nCharCount )
 
 {
     char	szBuffer[100];
-    int		i;
 
-    VSIFReadL( szBuffer, nCharCount, 1, fp );
+    CPL_IGNORE_RET_VAL(VSIFReadL( szBuffer, nCharCount, 1, fp ));
     szBuffer[nCharCount] = '\0';
 
-    for( i = 0; i < nCharCount; i++ )
+    for( int i = 0; i < nCharCount; i++ )
     {
         if( szBuffer[i] == 'D' )
             szBuffer[i] = 'E';
@@ -266,11 +266,11 @@ class USGSDEMDataset : public GDALPamDataset
     GDALDataType eNaturalDataFormat;
 
     double      adfGeoTransform[6];
-    char        *pszProjection; 
+    char        *pszProjection;
 
     double      fVRes;
 
-    const char  *pszUnits; 
+    const char  *pszUnits;
 
     int         LoadFromFile( VSILFILE * );
 
@@ -279,7 +279,7 @@ class USGSDEMDataset : public GDALPamDataset
   public:
                 USGSDEMDataset();
 		~USGSDEMDataset();
-    
+
     static int  Identify( GDALOpenInfo * );
     static GDALDataset *Open( GDALOpenInfo * );
     CPLErr 	GetGeoTransform( double * padfTransform );
@@ -297,9 +297,8 @@ class USGSDEMRasterBand : public GDALPamRasterBand
     friend class USGSDEMDataset;
 
   public:
+                explicit USGSDEMRasterBand( USGSDEMDataset * );
 
-    		USGSDEMRasterBand( USGSDEMDataset * );
-    
     virtual const char *GetUnitType();
     virtual double GetNoDataValue( int *pbSuccess = NULL );
     virtual CPLErr IReadBlock( int, int, void * );
@@ -310,16 +309,16 @@ class USGSDEMRasterBand : public GDALPamRasterBand
 /*                           USGSDEMRasterBand()                            */
 /************************************************************************/
 
-USGSDEMRasterBand::USGSDEMRasterBand( USGSDEMDataset *poDS )
+USGSDEMRasterBand::USGSDEMRasterBand( USGSDEMDataset *poDSIn )
 
 {
-    this->poDS = poDS;
+    this->poDS = poDSIn;
     this->nBand = 1;
 
-    eDataType = poDS->eNaturalDataFormat;
+    eDataType = poDSIn->eNaturalDataFormat;
 
-    nBlockXSize = poDS->GetRasterXSize();
-    nBlockYSize = poDS->GetRasterYSize();
+    nBlockXSize = poDSIn->GetRasterXSize();
+    nBlockYSize = poDSIn->GetRasterYSize();
 
 }
 
@@ -332,9 +331,8 @@ CPLErr USGSDEMRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                                       void * pImage )
 
 {
-    double	dfYMin;
     /* int		bad = FALSE; */
-    USGSDEMDataset *poGDS = (USGSDEMDataset *) poDS;
+    USGSDEMDataset *poGDS = reinterpret_cast<USGSDEMDataset *>( poDS );
 
 /* -------------------------------------------------------------------- */
 /*      Initialize image buffer to nodata value.                        */
@@ -342,17 +340,17 @@ CPLErr USGSDEMRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     for( int k = GetXSize() * GetYSize() - 1; k >= 0; k-- )
     {
         if( GetRasterDataType() == GDT_Int16 )
-            ((GInt16 *) pImage)[k] = USGSDEM_NODATA;
+            reinterpret_cast<GInt16 *>( pImage )[k] = USGSDEM_NODATA;
         else
-            ((float *) pImage)[k] = USGSDEM_NODATA;
+            reinterpret_cast<float *>( pImage )[k] = USGSDEM_NODATA;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Seek to data.                                                   */
 /* -------------------------------------------------------------------- */
-    VSIFSeekL(poGDS->fp, poGDS->nDataStartOffset, 0);
+    CPL_IGNORE_RET_VAL(VSIFSeekL(poGDS->fp, poGDS->nDataStartOffset, 0));
 
-    dfYMin = poGDS->adfGeoTransform[3] 
+    double dfYMin = poGDS->adfGeoTransform[3]
         + (GetYSize()-0.5) * poGDS->adfGeoTransform[5];
 
 /* -------------------------------------------------------------------- */
@@ -361,39 +359,55 @@ CPLErr USGSDEMRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 
     Buffer sBuffer;
     sBuffer.max_size = 32768;
-    sBuffer.buffer = (char*) CPLMalloc(sBuffer.max_size + 1);
+    sBuffer.buffer
+        = reinterpret_cast<char *>( CPLMalloc( sBuffer.max_size + 1 ) );
     sBuffer.fp = poGDS->fp;
     sBuffer.buffer_size = 0;
     sBuffer.cur_index = 0;
 
     for( int i = 0; i < GetXSize(); i++)
     {
-        int	/* njunk, */ nCPoints, lygap;
-        double	/* djunk, dxStart, */ dyStart, dfElevOffset;
-
-        /* njunk = */ USGSDEMReadIntFromBuffer(&sBuffer);
-        /* njunk = */ USGSDEMReadIntFromBuffer(&sBuffer);
-        nCPoints = USGSDEMReadIntFromBuffer(&sBuffer);
-        /* njunk = */ USGSDEMReadIntFromBuffer(&sBuffer);
-
-        /* dxStart = */ USGSDEMReadDoubleFromBuffer(&sBuffer, 24);
-        dyStart = USGSDEMReadDoubleFromBuffer(&sBuffer, 24);
-        dfElevOffset = USGSDEMReadDoubleFromBuffer(&sBuffer, 24);
-        /* djunk = */ USGSDEMReadDoubleFromBuffer(&sBuffer, 24);
-        /* djunk = */ USGSDEMReadDoubleFromBuffer(&sBuffer, 24);
+        int bSuccess;
+        /* njunk = */ USGSDEMReadIntFromBuffer(&sBuffer, &bSuccess);
+        if( bSuccess )
+        /* njunk = */ USGSDEMReadIntFromBuffer(&sBuffer, &bSuccess);
+        const int nCPoints = (bSuccess) ? USGSDEMReadIntFromBuffer(&sBuffer, &bSuccess) : 0;
+        /* njunk = */ USGSDEMReadIntFromBuffer(&sBuffer, &bSuccess);
+
+        if( bSuccess )
+        /* dxStart = */ USGSDEMReadDoubleFromBuffer(&sBuffer, 24, &bSuccess);
+        double dyStart = (bSuccess) ? USGSDEMReadDoubleFromBuffer(&sBuffer, 24, &bSuccess) : 0;
+        const double dfElevOffset = (bSuccess) ? USGSDEMReadDoubleFromBuffer(&sBuffer, 24, &bSuccess) : 0;
+        if( bSuccess )
+        /* djunk = */ USGSDEMReadDoubleFromBuffer(&sBuffer, 24, &bSuccess);
+        if( bSuccess )
+        /* djunk = */ USGSDEMReadDoubleFromBuffer(&sBuffer, 24, &bSuccess);
+        if( !bSuccess )
+        {
+            CPLFree(sBuffer.buffer);
+            return CE_Failure;
+        }
 
-        if( EQUALN(poGDS->pszProjection,"GEOGCS",6) )
+        if( STARTS_WITH_CI(poGDS->pszProjection, "GEOGCS") )
             dyStart = dyStart / 3600.0;
 
-        lygap = (int)((dfYMin - dyStart)/poGDS->adfGeoTransform[5]+ 0.5);
+        double dygap = (dfYMin - dyStart)/poGDS->adfGeoTransform[5]+ 0.5;
+        if( dygap <= INT_MIN || dygap >= INT_MAX || !CPLIsFinite(dygap) )
+        {
+            CPLFree(sBuffer.buffer);
+            return CE_Failure;
+        }
+        int lygap = static_cast<int>(dygap);
+        if( nCPoints <= 0 )
+            continue;
+        if( lygap > INT_MAX - nCPoints )
+            lygap = INT_MAX - nCPoints;
 
-        for (int j=lygap; j < (nCPoints+(int)lygap); j++)
+        for (int j=lygap; j < (nCPoints + lygap); j++)
         {
-            int		iY = GetYSize() - j - 1;
-            int         nElev;
-            int     bSuccess;
+            const int iY = GetYSize() - j - 1;
 
-            nElev = USGSDEMReadIntFromBuffer(&sBuffer, &bSuccess);
+            const int nElev = USGSDEMReadIntFromBuffer(&sBuffer, &bSuccess);
             if( !bSuccess )
             {
                 CPLFree(sBuffer.buffer);
@@ -406,17 +420,21 @@ CPLErr USGSDEMRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                 /* leave in output buffer as nodata */;
             else
             {
-                float fComputedElev =
-                    (float)(nElev * poGDS->fVRes + dfElevOffset);
+                const float fComputedElev =
+                    static_cast<float>(nElev * poGDS->fVRes + dfElevOffset);
 
                 if( GetRasterDataType() == GDT_Int16 )
                 {
-                    ((GInt16 *) pImage)[i + iY*GetXSize()] =
-                        (GInt16) fComputedElev;
+                    GUInt16 nVal = ( fComputedElev < -32768 ) ? -32768 :
+                                   ( fComputedElev > 32767 ) ? 32767 :
+                                   static_cast<GInt16>( fComputedElev );
+                    reinterpret_cast<GInt16 *>( pImage )[i + iY*GetXSize()]
+                        = nVal;
                 }
                 else
                 {
-                    ((float *) pImage)[i + iY*GetXSize()] = fComputedElev;
+                    reinterpret_cast<float *>( pImage )[i + iY*GetXSize()]
+                        = fComputedElev;
                 }
             }
         }
@@ -444,7 +462,7 @@ double USGSDEMRasterBand::GetNoDataValue( int *pbSuccess )
 /************************************************************************/
 const char *USGSDEMRasterBand::GetUnitType()
 {
-    USGSDEMDataset *poGDS = (USGSDEMDataset *) poDS;
+    USGSDEMDataset *poGDS = reinterpret_cast<USGSDEMDataset *>( poDS );
 
     return poGDS->pszUnits;
 }
@@ -459,12 +477,14 @@ const char *USGSDEMRasterBand::GetUnitType()
 /*                           USGSDEMDataset()                           */
 /************************************************************************/
 
-USGSDEMDataset::USGSDEMDataset()
-
-{
-    fp = NULL;
-    pszProjection = NULL;
-}
+USGSDEMDataset::USGSDEMDataset() :
+    nDataStartOffset(0),
+    eNaturalDataFormat(GDT_Unknown),
+    pszProjection(NULL),
+    fVRes(0.0),
+    pszUnits(NULL),
+    fp(NULL)
+{ }
 
 /************************************************************************/
 /*                            ~USGSDEMDataset()                         */
@@ -477,7 +497,7 @@ USGSDEMDataset::~USGSDEMDataset()
 
     CPLFree( pszProjection );
     if( fp != NULL )
-        VSIFCloseL( fp );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
 }
 
 /************************************************************************/
@@ -492,37 +512,24 @@ USGSDEMDataset::~USGSDEMDataset()
 
 int USGSDEMDataset::LoadFromFile(VSILFILE *InDem)
 {
-    int		i, j;
-    int		nRow, nColumn;
-    int		nVUnit, nGUnit;
-    double 	dxdelta, dydelta;
-    /* double	dElevMax, dElevMin; */
-    int 	bNewFormat;
-    int		nCoordSystem;
-    int		nProfiles;
-    char	szDateBuffer[5];
-    DPoint2	corners[4];			// SW, NW, NE, SE
-    DPoint2	extent_min, extent_max;
-    int		iUTMZone;
-
     // check for version of DEM format
-    VSIFSeekL(InDem, 864, 0);
+    CPL_IGNORE_RET_VAL(VSIFSeekL(InDem, 864, 0));
 
     // Read DEM into matrix
-    nRow = ReadInt(InDem);
-    nColumn = ReadInt(InDem);
-    bNewFormat = ((nRow!=1)||(nColumn!=1));
+    const int nRow = ReadInt(InDem);
+    const int nColumn = ReadInt(InDem);
+    const bool bNewFormat = nRow != 1 || nColumn != 1;
     if (bNewFormat)
     {
-        VSIFSeekL(InDem, 1024, 0); 	// New Format
-        i = ReadInt(InDem);
-        j = ReadInt(InDem);
-        if ((i!=1)||(j!=1 && j != 0))	// File OK?
+        CPL_IGNORE_RET_VAL(VSIFSeekL(InDem, 1024, 0)); 	// New Format
+        int i = ReadInt(InDem);
+        int j = ReadInt(InDem);
+        if ( i != 1 || ( j != 1 && j != 0 ) )	// File OK?
         {
-            VSIFSeekL(InDem, 893, 0); 	// Undocumented Format (39109h1.dem)
+            CPL_IGNORE_RET_VAL(VSIFSeekL(InDem, 893, 0)); 	// Undocumented Format (39109h1.dem)
             i = ReadInt(InDem);
             j = ReadInt(InDem);
-            if ((i!=1)||(j!=1))			// File OK?
+            if ( i != 1 || j != 1 )  // File OK?
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
                           "Does not appear to be a USGS DEM file." );
@@ -537,13 +544,13 @@ int USGSDEMDataset::LoadFromFile(VSILFILE *InDem)
     else
         nDataStartOffset = 864;
 
-    VSIFSeekL(InDem, 156, 0);
-    nCoordSystem = ReadInt(InDem);
-    iUTMZone = ReadInt(InDem);
+    CPL_IGNORE_RET_VAL(VSIFSeekL(InDem, 156, 0));
+    const int nCoordSystem = ReadInt(InDem);
+    const int iUTMZone = ReadInt(InDem);
 
-    VSIFSeekL(InDem, 528, 0);
-    nGUnit = ReadInt(InDem);
-    nVUnit = ReadInt(InDem);
+    CPL_IGNORE_RET_VAL(VSIFSeekL(InDem, 528, 0));
+    const int nGUnit = ReadInt(InDem);
+    const int nVUnit = ReadInt(InDem);
 
     // Vertical Units in meters
     if (nVUnit==1)
@@ -551,9 +558,9 @@ int USGSDEMDataset::LoadFromFile(VSILFILE *InDem)
     else
         pszUnits = "m";
 
-    VSIFSeekL(InDem, 816, 0);
-    dxdelta = DConvert(InDem, 12);
-    dydelta = DConvert(InDem, 12);
+    CPL_IGNORE_RET_VAL(VSIFSeekL(InDem, 816, 0));
+    const double dxdelta = DConvert(InDem, 12);
+    const double dydelta = DConvert(InDem, 12);
     fVRes = DConvert(InDem, 12);
 
 /* -------------------------------------------------------------------- */
@@ -567,39 +574,40 @@ int USGSDEMDataset::LoadFromFile(VSILFILE *InDem)
 /* -------------------------------------------------------------------- */
 /*      Read four corner coordinates.                                   */
 /* -------------------------------------------------------------------- */
-    VSIFSeekL(InDem, 546, 0);
-    for (i = 0; i < 4; i++)
+    CPL_IGNORE_RET_VAL(VSIFSeekL(InDem, 546, 0));
+    DPoint2 corners[4];  // SW, NW, NE, SE
+    for (int i = 0; i < 4; i++)
     {
         corners[i].x = DConvert(InDem, 24);
         corners[i].y = DConvert(InDem, 24);
     }
 
     // find absolute extents of raw vales
-    extent_min.x = MIN(corners[0].x, corners[1].x);
-    extent_max.x = MAX(corners[2].x, corners[3].x);
-    extent_min.y = MIN(corners[0].y, corners[3].y);
-    extent_max.y = MAX(corners[1].y, corners[2].y);
+    DPoint2 extent_min, extent_max;
+    extent_min.x = std::min(corners[0].x, corners[1].x);
+    extent_max.x = std::max(corners[2].x, corners[3].x);
+    extent_min.y = std::min(corners[0].y, corners[3].y);
+    extent_max.y = std::max(corners[1].y, corners[2].y);
 
     /* dElevMin = */ DConvert(InDem, 48);
     /* dElevMax = */ DConvert(InDem, 48);
 
-    VSIFSeekL(InDem, 858, 0);
-    nProfiles = ReadInt(InDem);
+    CPL_IGNORE_RET_VAL(VSIFSeekL(InDem, 858, 0));
+    const int nProfiles = ReadInt(InDem);
 
 /* -------------------------------------------------------------------- */
 /*      Collect the spatial reference system.                           */
 /* -------------------------------------------------------------------- */
     OGRSpatialReference sr;
-    int bNAD83 =TRUE;
+    bool bNAD83 = true;
 
     // OLD format header ends at byte 864
     if (bNewFormat)
     {
-        char szHorzDatum[3];
-
         // year of data compilation
-        VSIFSeekL(InDem, 876, 0);
-        VSIFReadL(szDateBuffer, 4, 1, InDem);
+        CPL_IGNORE_RET_VAL(VSIFSeekL(InDem, 876, 0));
+        char szDateBuffer[5];
+        CPL_IGNORE_RET_VAL(VSIFReadL(szDateBuffer, 4, 1, InDem));
         szDateBuffer[4] = 0;
 
         // Horizontal datum
@@ -609,16 +617,17 @@ int USGSDEMDataset::LoadFromFile(VSILFILE *InDem)
         // 4=NAD 83
         // 5=Old Hawaii Datum
         // 6=Puerto Rico Datum
-        int datum;
-        VSIFSeekL(InDem, 890, 0);
-        VSIFReadL( szHorzDatum, 1, 2, InDem );
+        CPL_IGNORE_RET_VAL(VSIFSeekL(InDem, 890, 0));
+
+        char szHorzDatum[3];
+        CPL_IGNORE_RET_VAL(VSIFReadL( szHorzDatum, 1, 2, InDem ));
         szHorzDatum[2] = '\0';
-        datum = atoi(szHorzDatum);
+        const int datum = atoi(szHorzDatum);
         switch (datum)
         {
           case 1:
             sr.SetWellKnownGeogCS( "NAD27" );
-            bNAD83 = FALSE;
+            bNAD83 = false;
             break;
 
           case 2:
@@ -644,7 +653,7 @@ int USGSDEMDataset::LoadFromFile(VSILFILE *InDem)
     else
     {
         sr.SetWellKnownGeogCS( "NAD27" );
-        bNAD83 = FALSE;
+        bNAD83 = false;
     }
 
     if (nCoordSystem == 1)	// UTM
@@ -654,7 +663,7 @@ int USGSDEMDataset::LoadFromFile(VSILFILE *InDem)
         {
             sr.SetLinearUnitsAndUpdateParameters( SRS_UL_US_FOOT, CPLAtof(SRS_UL_US_FOOT_CONV) );
             char    szUTMName[128];
-            sprintf( szUTMName, "UTM Zone %d, Northern Hemisphere, us-ft", iUTMZone );
+            snprintf( szUTMName, sizeof(szUTMName), "UTM Zone %d, Northern Hemisphere, us-ft", iUTMZone );
             sr.SetNode( "PROJCS", szUTMName );
         }
     }
@@ -677,25 +686,23 @@ int USGSDEMDataset::LoadFromFile(VSILFILE *InDem)
 /*      the pixel size which what really gets used.                     */
 /* -------------------------------------------------------------------- */
     if (nCoordSystem == 1          // UTM
-        || nCoordSystem == 2 	   // State Plane
+        || nCoordSystem == 2       // State Plane
         || nCoordSystem == -9999 ) // unknown
     {
-        /* int	njunk; */
-        double  dxStart;
-
         // expand extents modulus the pixel size.
         extent_min.y = floor(extent_min.y/dydelta) * dydelta;
         extent_max.y = ceil(extent_max.y/dydelta) * dydelta;
 
-        // Forceably compute X extents based on first profile and pixelsize.
-        VSIFSeekL(InDem, nDataStartOffset, 0);
+        // Forcibly compute X extents based on first profile and pixelsize.
+        CPL_IGNORE_RET_VAL(VSIFSeekL(InDem, nDataStartOffset, 0));
         /* njunk = */ ReadInt(InDem);
         /* njunk = */ ReadInt(InDem);
         /* njunk = */ ReadInt(InDem);
         /* njunk = */ ReadInt(InDem);
-        dxStart = DConvert(InDem, 24);
+        const double dxStart = DConvert(InDem, 24);
 
-        nRasterYSize = (int) ((extent_max.y - extent_min.y)/dydelta + 1.5);
+        nRasterYSize = static_cast<int>(
+            ( extent_max.y - extent_min.y ) / dydelta + 1.5 );
         nRasterXSize = nProfiles;
 
         adfGeoTransform[0] = dxStart - dxdelta/2.0;
@@ -710,7 +717,8 @@ int USGSDEMDataset::LoadFromFile(VSILFILE *InDem)
 /* -------------------------------------------------------------------- */
     else
     {
-        nRasterYSize = (int) ((extent_max.y - extent_min.y)/dydelta + 1.5);
+        nRasterYSize = static_cast<int>(
+            ( extent_max.y - extent_min.y ) / dydelta + 1.5 );
         nRasterXSize = nProfiles;
 
         // Translate extents from arc-seconds to decimal degrees.
@@ -762,15 +770,15 @@ int USGSDEMDataset::Identify( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->nHeaderBytes < 200 )
         return FALSE;
 
-    if( !EQUALN((const char *) poOpenInfo->pabyHeader+156, "     0",6)
-        && !EQUALN((const char *) poOpenInfo->pabyHeader+156, "     1",6)
-        && !EQUALN((const char *) poOpenInfo->pabyHeader+156, "     2",6) 
-        && !EQUALN((const char *) poOpenInfo->pabyHeader+156, "     3",6)
-        && !EQUALN((const char *) poOpenInfo->pabyHeader+156, " -9999",6) )
+    if( !STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader+156, "     0")
+        && !STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader+156, "     1")
+        && !STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader+156, "     2")
+        && !STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader+156, "     3")
+        && !STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader+156, " -9999") )
         return FALSE;
 
-    if( !EQUALN((const char *) poOpenInfo->pabyHeader+150, "     1",6) 
-        && !EQUALN((const char *) poOpenInfo->pabyHeader+150, "     4",6))
+    if( !STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader+150, "     1")
+        && !STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader+150, "     4"))
         return FALSE;
 
     return TRUE;
@@ -793,12 +801,10 @@ GDALDataset *USGSDEMDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    USGSDEMDataset 	*poDS;
-
-    poDS = new USGSDEMDataset();
+    USGSDEMDataset *poDS = new USGSDEMDataset();
 
     poDS->fp = fp;
-    
+
 /* -------------------------------------------------------------------- */
 /*	Read the file.							*/
 /* -------------------------------------------------------------------- */
@@ -807,19 +813,19 @@ GDALDataset *USGSDEMDataset::Open( GDALOpenInfo * poOpenInfo )
         delete poDS;
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The USGSDEM driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
@@ -848,28 +854,25 @@ GDALDataset *USGSDEMDataset::Open( GDALOpenInfo * poOpenInfo )
 void GDALRegister_USGSDEM()
 
 {
-    GDALDriver	*poDriver;
-
-    if( GDALGetDriverByName( "USGSDEM" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "USGSDEM" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, 
-                                   "dem" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "USGS Optional ASCII DEM (and CDED)" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_usgsdem.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Int16" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
+    if( GDALGetDriverByName( "USGSDEM" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "USGSDEM" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "dem" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "USGS Optional ASCII DEM (and CDED)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_usgsdem.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Int16" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "   <Option name='PRODUCT' type='string-select' description='Specific Product Type'>"
 "       <Value>DEFAULT</Value>"
 "       <Value>CDED50K</Value>"
 "   </Option>"
-"   <Option name='TOPLEFT' type='string' description='Top left product corner (ie. 117d15w,52d30n'/>"
+"   <Option name='TOPLEFT' type='string' description='Top left product corner (i.e. 117d15w,52d30n'/>"
 "   <Option name='RESAMPLE' type='string-select' description='Resampling kernel to use if resampled.'>"
 "       <Value>Nearest</Value>"
 "       <Value>Bilinear</Value>"
@@ -886,13 +889,11 @@ void GDALRegister_USGSDEM()
 "   <Option name='NTS' type='string' description='NTS Mapsheet name, used to derive TOPLEFT.'/>"
 "   <Option name='INTERNALNAME' type='string' description='Dataset name written into file header.'/>"
 "</CreationOptionList>" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = USGSDEMDataset::Open;
-        poDriver->pfnCreateCopy = USGSDEMCreateCopy;
-        poDriver->pfnIdentify = USGSDEMDataset::Identify;
+    poDriver->pfnOpen = USGSDEMDataset::Open;
+    poDriver->pfnCreateCopy = USGSDEMCreateCopy;
+    poDriver->pfnIdentify = USGSDEMDataset::Identify;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/vrt/GNUmakefile b/frmts/vrt/GNUmakefile
index 95722bf..ff18e0d 100644
--- a/frmts/vrt/GNUmakefile
+++ b/frmts/vrt/GNUmakefile
@@ -4,7 +4,7 @@ include ../../GDALmake.opt
 
 OBJ	=	vrtdataset.o vrtrasterband.o vrtdriver.o vrtsources.o \
 		vrtfilters.o vrtsourcedrasterband.o vrtrawrasterband.o \
-		vrtwarped.o vrtderivedrasterband.o
+		vrtwarped.o vrtderivedrasterband.o vrtpansharpened.o
 
 CPPFLAGS	:=	-I../raw  $(CPPFLAGS)
 
diff --git a/frmts/vrt/gdal_vrt.h b/frmts/vrt/gdal_vrt.h
index 2ae9162..63f76ff 100644
--- a/frmts/vrt/gdal_vrt.h
+++ b/frmts/vrt/gdal_vrt.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_vrt.h 12156 2007-09-14 14:05:58Z dron $
+ * $Id: gdal_vrt.h 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  C/Public declarations of virtual GDAL dataset objects.
@@ -45,7 +45,7 @@
 
 CPL_C_START
 
-void    GDALRegister_VRT(void);
+void GDALRegister_VRT();
 typedef CPLErr
 (*VRTImageReadFunc)( void *hCBData,
                      int nXOff, int nYOff, int nXSize, int nYSize,
@@ -91,7 +91,7 @@ CPLErr CPL_DLL CPL_STDCALL VRTAddSimpleSource( VRTSourcedRasterBandH,
                                                int, int, int, int,
                                                const char *, double );
 CPLErr CPL_DLL CPL_STDCALL VRTAddComplexSource( VRTSourcedRasterBandH,
-                                                GDALRasterBandH, 
+                                                GDALRasterBandH,
                                                 int, int, int, int,
                                                 int, int, int, int,
                                                 double, double, double );
@@ -102,4 +102,3 @@ CPLErr CPL_DLL CPL_STDCALL VRTAddFuncSource( VRTSourcedRasterBandH,
 CPL_C_END
 
 #endif /* GDAL_VRT_H_INCLUDED */
-
diff --git a/frmts/vrt/makefile.vc b/frmts/vrt/makefile.vc
index e84f5d5..442da64 100644
--- a/frmts/vrt/makefile.vc
+++ b/frmts/vrt/makefile.vc
@@ -1,7 +1,8 @@
 
 OBJ	=	vrtdataset.obj vrtrasterband.obj vrtdriver.obj \
 		vrtsources.obj vrtfilters.obj vrtsourcedrasterband.obj \
-		vrtrawrasterband.obj vrtderivedrasterband.obj vrtwarped.obj
+		vrtrawrasterband.obj vrtderivedrasterband.obj vrtwarped.obj \
+		vrtpansharpened.obj
 
 GDAL_ROOT	=	..\..
 
diff --git a/frmts/vrt/vrt_tutorial.dox b/frmts/vrt/vrt_tutorial.dox
index 6b0d220..efb55c7 100644
--- a/frmts/vrt/vrt_tutorial.dox
+++ b/frmts/vrt/vrt_tutorial.dox
@@ -1,11 +1,25 @@
 #ifndef DOXYGEN_SKIP
-/* $Id: vrt_tutorial.dox 29342 2015-06-14 18:00:24Z rouault $ */
+/* $Id: vrt_tutorial.dox 33123 2016-01-23 18:59:28Z rouault $ */
 #endif /* DOXYGEN_SKIP */
 
 /*!
 
 \page gdal_vrttut GDAL Virtual Format Tutorial
 
+\section gdal_vrttut_toc Contents
+
+<ol>
+<li> \ref gdal_vrttut_intro
+<li> \ref gdal_vrttut_format
+<li> \ref gdal_vrttut_overviews
+<li> \ref gdal_vrttut_raw
+<li> \ref gdal_vrttut_creation
+<li> \ref gdal_vrttut_warped
+<li> \ref gdal_vrttut_pansharpen
+<li> \ref gdal_vrttut_mt
+<li> \ref gdal_vrttut_perf
+</ol>
+
 \section gdal_vrttut_intro Introduction
 
 The VRT driver is a format driver for GDAL that allows a virtual GDAL dataset
@@ -14,6 +28,9 @@ potentially applied as well as various kinds of metadata altered or added.
 VRT descriptions of datasets can be saved in an XML format normally given the
 extension .vrt.<p>
 
+The VRT format can also describe \ref gdal_vrttut_warped "warping operations"
+and \ref gdal_vrttut_pansharpen "pansharpening operations".<p>
+
 An example of a simple .vrt file referring to a 512x512 dataset with one band
 loaded from utm.tif might look like this:
 
@@ -54,8 +71,11 @@ elements.<p>
 
 <b>VRTDataset</b>: This is the root element for the whole GDAL dataset. 
 It must have the attributes rasterXSize and rasterYSize describing the width 
-and height of the dataset in pixels.  It may have SRS, GeoTransform, 
-GCPList, Metadata, MaskBand and VRTRasterBand subelements.
+and height of the dataset in pixels.
+It may have a subClass attributes with values VRTWarpedDataset (\ref gdal_vrttut_warped) or 
+VRTPansharpenedDataset (\ref gdal_vrttut_pansharpen).
+It may have SRS, GeoTransform, 
+GCPList, Metadata, MaskBand and VRTRasterBand subelements. 
 
 \code
 <VRTDataset rasterXSize="512" rasterYSize="512">
@@ -267,7 +287,7 @@ or not relative to the .vrt file (value is 0).  The default is 0.
 
 The shared attribute, added in GDAL 2.0.0, on the SourceFilename indicates whether the
 dataset should be shared (value is 1) or not (value is 0). The default is 1.
-If several VRT datasets refering to the same underlying sources are used in a multithreaded context,
+If several VRT datasets referring to the same underlying sources are used in a multithreaded context,
 shared should be set to 0. Alternatively, the VRT_SHARED_SOURCE configuration
 option can be set to 0 to force non-shared mode.
 
@@ -279,7 +299,7 @@ raster dimensions, the size of the blocks and the data type. If the SourceProper
 tag is not present, the source dataset will be opened at the same time as the VRT itself.
 
 Starting with GDAL 1.8.0, the content of the SourceBand subelement can refer to
-a mask band. For example mask,1 means the the mask band of the first band of the source.
+a mask band. For example mask,1 means the mask band of the first band of the source.
 
 \code
     <SimpleSource>
@@ -435,7 +455,23 @@ child element, that is the description of the mask band itself.
 
 </ul>
 
-\section gdal_vrttut_vrt .vrt Descriptions for Raw Files
+\section gdal_vrttut_overviews Overviews
+
+GDAL can make efficient use of overviews available in the sources that compose
+the bands when dealing with RasterIO() requests that involve downsampling.
+But in the general case, the VRT bands themselves will not expose overviews.
+
+Except if (from top priority to lesser priority) :
+<ol>
+<li>The <b>Overview</b> element is present in the VRTRasterBand element. See above.
+</li>
+<li>or external .vrt.ovr overviews are built</li>
+<li>(starting with GDAL 2.1) if the VRTRasterBand are made of a single SimpleSource
+or ComplexSource that has overviews. Those "virtual" overviews will be hidden
+by external .vrt.ovr overviews that might be built later.</li>
+</ol>
+
+\section gdal_vrttut_raw .vrt Descriptions for Raw Files
 
 So far we have described how to derive new virtual datasets from existing
 files supports by GDAL.  However, it is also common to need to utilize 
@@ -465,7 +501,7 @@ from the start of one line to the start of the next is 9376 bytes
 Some things to note are that the VRTRasterBand has a subClass specifier
 of "VRTRawRasterBand".  Also, the VRTRawRasterBand contains a number of 
 previously unseen elements but no "source" information.  VRTRawRasterBands
-may never have sources (ie. SimpleSource), but should contain the following
+may never have sources (i.e. SimpleSource), but should contain the following
 elements in addition to all the normal "metadata" elements previously 
 described which are still supported. 
 
@@ -684,11 +720,11 @@ should be specified with the above SetMetadata() / SetMetadataItem() examples.
   char** papszOptions = NULL;
   papszOptions = CSLAddNameValue(papszOptions, "subclass", "VRTRawRasterBand"); // if not specified, default to VRTRasterBand
   papszOptions = CSLAddNameValue(papszOptions, "SourceFilename", "src.tif"); // mandatory
-  papszOptions = CSLAddNameValue(papszOptions, "ImageOffset", "156"); // optionnal. default = 0 
-  papszOptions = CSLAddNameValue(papszOptions, "PixelOffset", "2"); // optionnal. default = size of band type 
-  papszOptions = CSLAddNameValue(papszOptions, "LineOffset", "1024"); // optionnal. default = size of band type * width 
-  papszOptions = CSLAddNameValue(papszOptions, "ByteOrder", "LSB"); // optionnal. default = machine order
-  papszOptions = CSLAddNameValue(papszOptions, "relativeToVRT", "true"); // optionnal. default = false
+  papszOptions = CSLAddNameValue(papszOptions, "ImageOffset", "156"); // optional. default = 0 
+  papszOptions = CSLAddNameValue(papszOptions, "PixelOffset", "2"); // optional. default = size of band type 
+  papszOptions = CSLAddNameValue(papszOptions, "LineOffset", "1024"); // optional. default = size of band type * width 
+  papszOptions = CSLAddNameValue(papszOptions, "ByteOrder", "LSB"); // optional. default = machine order
+  papszOptions = CSLAddNameValue(papszOptions, "relativeToVRT", "true"); // optional. default = false
   poVRTDS->AddBand(GDT_Byte, papszOptions);
   CSLDestroy(papszOptions);
 
@@ -867,6 +903,233 @@ CPLErr TestFunction(void **papoSources, int nSources, void *pData,
 }
 \endcode
 
+\section gdal_vrttut_warped Warped VRT
+
+A warped VRT is a VRTDataset with subClass="VRTWarpedDataset". It has a
+GDALWarpOptions element which describe the warping options.
+
+\code
+<VRTDataset rasterXSize="20" rasterYSize="20" subClass="VRTWarpedDataset">
+  <SRS>PROJCS["NAD27 / UTM zone 11N",GEOGCS["NAD27",DATUM["North_American_Datum_1927",SPHEROID["Clarke 1866",6378206.4,294.9786982138982,AUTHORITY["EPSG","7008"]],AUTHORITY["EPSG","6267"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4267"]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",-117],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],P [...]
+  <GeoTransform>  4.4072000000000000e+05,  6.0000000000000000e+01,  0.0000000000000000e+00,  3.7513200000000000e+06,  0.0000000000000000e+00, -6.0000000000000000e+01</GeoTransform>
+  <Metadata>
+    <MDI key="AREA_OR_POINT">Area</MDI>
+  </Metadata>
+  <VRTRasterBand dataType="Byte" band="1" subClass="VRTWarpedRasterBand">
+    <ColorInterp>Gray</ColorInterp>
+  </VRTRasterBand>
+  <BlockXSize>20</BlockXSize>
+  <BlockYSize>20</BlockYSize>
+  <GDALWarpOptions>
+    <WarpMemoryLimit>6.71089e+07</WarpMemoryLimit>
+    <ResampleAlg>NearestNeighbour</ResampleAlg>
+    <WorkingDataType>Byte</WorkingDataType>
+    <Option name="INIT_DEST">0</Option>
+    <SourceDataset relativeToVRT="1">byte.vrt</SourceDataset>
+    <Transformer>
+      <ApproxTransformer>
+        <MaxError>0.125</MaxError>
+        <BaseTransformer>
+          <GenImgProjTransformer>
+            <SrcGeoTransform>440720,60,0,3751320,0,-60</SrcGeoTransform>
+            <SrcInvGeoTransform>-7345.33333333333303,0.0166666666666666664,0,62522,0,-0.0166666666666666664</SrcInvGeoTransform>
+            <DstGeoTransform>440720,60,0,3751320,0,-60</DstGeoTransform>
+            <DstInvGeoTransform>-7345.33333333333303,0.0166666666666666664,0,62522,0,-0.0166666666666666664</DstInvGeoTransform>
+          </GenImgProjTransformer>
+        </BaseTransformer>
+      </ApproxTransformer>
+    </Transformer>
+    <BandList>
+      <BandMapping src="1" dst="1" />
+    </BandList>
+  </GDALWarpOptions>
+</VRTDataset>
+\endcode
+
+\section gdal_vrttut_pansharpen Pansharpened VRT
+
+(Since GDAL 2.1)
+
+A VRT can describe a dataset resulting from a
+<a href="https://en.wikipedia.org/wiki/Pansharpened_image">pansharpening operation</a>.
+The pansharpening VRT combines a panchromatic band with several spectral bands
+of lower resolution to generate output spectral bands of the same resolution as
+the panchromatic band.
+
+VRT pansharpening assumes that the panchromatic and spectral bands have the same
+projection (or no projection). If that is not the case, reprojection must be done in a prior step.
+Bands might have different geotransform matrices, in which case, by default, the
+resulting dataset will have as extent the union of all extents.
+
+Currently the only supported pansharpening algorithm is a "weighted" Brovey algorithm.
+The general principle of this algorithm is that, after resampling the spectral bands
+to the resolution of the panchromatic band, a pseudo panchromatic intensity is computed
+from a weighted average of the spectral bands. Then the output value of the spectral
+band is its input value multiplied by the ratio of the real panchromatic intensity
+over the pseudo panchromatic intensity.
+
+Corresponding pseudo code:
+\code
+pseudo_panchro[pixel] = sum(weight[i] * spectral[pixel][i] for i=0 to nb_spectral_bands-1) 
+ratio = panchro[pixel] / pseudo_panchro[pixel]
+for i=0 to nb_spectral_bands-1:
+    output_value[pixel][i] = input_value[pixel][i] * ratio
+\endcode
+
+A valid pansharpened VRT must declare subClass="VRTPansharpenedDataset" as an
+attribute of the VRTDataset top element. The VRTDataset element must have a
+child <b>PansharpeningOptions</b> element. This PansharpeningOptions element must have
+a <b>PanchroBand</b> child element and one of several <b>SpectralBand</b> elements.
+PanchroBand and SpectralBand elements must have at least a <b>SourceFilename</b> child
+element to specify the name of the dataset. They may also have a <b>SourceBand</b> child
+element to specify the number of the band in the dataset (starting with 1). If not
+specify, the first band will be assumed. 
+
+The SpectralBand element must generally have a <b>dstBand</b> attribute to specify the
+number of the output band (starting with 1) to which the input spectral band must be mapped.
+If the attribute is not specified, the spectral band will be taken into account
+in the computation of the pansharpening, but not exposed as an output band.
+
+Panchromatic and spectral bands should generally come from different datasets,
+since bands of a GDAL dataset are assumed to have all the same dimensions.
+Spectral bands themselves can come from one or several datasets. The only
+constraint is that they have all the same dimensions.
+
+An example of a minimalist working VRT is the following. It will generates a dataset with 3 output
+bands corresponding to the 3 input spectral bands of multispectral.tif, pansharpened
+with panchromatic.tif.
+
+\code
+<VRTDataset subClass="VRTPansharpenedDataset">
+  <PansharpeningOptions>
+    <PanchroBand>
+      <SourceFilename relativeToVRT="1">panchromatic.tif</SourceFilename>
+      <SourceBand>1</SourceBand>
+    </PanchroBand>
+    <SpectralBand dstBand="1">
+      <SourceFilename relativeToVRT="1">multispectral.tif</SourceFilename>
+      <SourceBand>1</SourceBand>
+    </SpectralBand>
+    <SpectralBand dstBand="2">
+      <SourceFilename relativeToVRT="1">multispectral.tif</SourceFilename>
+      <SourceBand>2</SourceBand>
+    </SpectralBand>
+    <SpectralBand dstBand="3">
+      <SourceFilename relativeToVRT="1">multispectral.tif</SourceFilename>
+      <SourceBand>3</SourceBand>
+    </SpectralBand>
+  </PansharpeningOptions>
+</VRTDataset>
+\endcode
+
+In the above example, 3 output pansharpend bands will be created from the 3 declared
+input spectral bands. The weights will be 1/3. Cubic resampling will be used. The
+projection and geotransform from the panchromatic band will be reused for the VRT
+dataset.
+
+It is possible to create more explicit and declarative pansharpened VRT, allowing
+for example to only output part of the input spectral bands (e.g. only RGB when
+the input multispectral dataset is RGBNir). It is also possible to add "classic"
+VRTRasterBands, in addition to the pansharpened bands.
+
+In addition to the above mentioned required PanchroBand and SpectralBand elements,
+the PansharpeningOptions element may have the following children elements :
+<ul>
+<li> <b>Algorithm</b>: to specify the pansharpening algorithm. Currently, only
+WeightedBrovey is supported.</li>
+<li> <b>AlgorithmOptions</b>: to specify the options of the pansharpening algorithm.
+With WeightedBrovey algorithm, the only supported option is a <b>Weights</b> child
+element whose content must be a comma separated list of real values assigning the
+weight of each of the declared input spectral bands. There must be as many values
+as declared input spectral bands.</li>
+<li> <b>Resampling</b>: the resampling kernel used to resample the spectral bands
+to the resolution of the panchromatic band. Can be one of Cubic (default), Average,
+Near, CubicSpline, Bilinear, Lanczos.</li>
+<li> <b>NumThreads</b>: Number of worker threads. Integer number or ALL_CPUS.
+If this option is not set, the GDAL_NUM_THREADS configuration option will be queried
+(its value can also be set to an integer or ALL_CPUS)</li>
+<li> <b>BitDepth</b>: Can be used to specify the bit depth of the panchromatic and
+spectral bands (e.g. 12). If not specified, the NBITS metadata item from the
+panchromatic band will be used if it exists.</li>
+<li> <b>NoData</b>: Nodata value to take into account for panchromatic and
+spectral bands. It will be also used as the output nodata value. If not specified and
+all input bands have the same nodata value, it will be implicitly used (unless
+the special None value is put in NoData to prevent that).</li>
+<li> <b>SpatialExtentAdjustment</b>: Can be one of <i>Union</i> (default), <i>Intersection</i>,
+<i>None</i> or <i>NoneWithoutWarning</i>. Controls the behaviour when panchromatic
+and spectral bands have not the same geospatial extent. By default, Union will take
+the union of all spatial extents. Intersection the intersection of all spatial extents.
+None will not proceed to any adjustment at all (might be useful if the geotransform are
+somehow dummy, and the top-left and bottom-right corners of all bands match), but will
+emmit a warning. NoneWithoutWarning is the same as None, but in a silent way.</li>
+</li>
+</ul>
+
+
+The below examples creates a VRT dataset with 4 bands. The first band is the
+panchromatic band. The 3 following bands are than red, green, blue pansharpened
+bands computed from a multispectral raster with red, green, blue and near-infrared
+bands. The near-infrared bands is taken into account for the computation of the
+pseudo panchromatic intensity, but not bound to an output band.
+
+\code
+<VRTDataset rasterXSize="800" rasterYSize="400" subClass="VRTPansharpenedDataset">
+  <SRS>WGS84</SRS>
+  <GeoTransform>-180, 0.45, 0, 90, 0, -0.45</GeoTransform>
+  <Metadata>
+    <MDI key="DESCRIPTION">Panchromatic band + pan-sharpened red, green and blue bands</MDI>
+  </Metadata>
+  <VRTRasterBand dataType="Byte" band="1" >
+    <SimpleSource>
+      <SourceFilename relativeToVRT="1">world_pan.tif</SourceFilename>
+      <SourceBand>1</SourceBand>
+    </SimpleSource>
+  </VRTRasterBand>
+  <VRTRasterBand dataType="Byte" band="2" subClass="VRTPansharpenedRasterBand">
+      <ColorInterp>Red</ColorInterp>
+  </VRTRasterBand>
+  <VRTRasterBand dataType="Byte" band="3" subClass="VRTPansharpenedRasterBand">
+      <ColorInterp>Green</ColorInterp>
+  </VRTRasterBand>
+  <VRTRasterBand dataType="Byte" band="4" subClass="VRTPansharpenedRasterBand">
+      <ColorInterp>Blue</ColorInterp>
+  </VRTRasterBand>
+  <BlockXSize>256</BlockXSize>
+  <BlockYSize>256</BlockYSize>
+  <PansharpeningOptions>
+    <Algorithm>WeightedBrovey</Algorithm>
+    <AlgorithmOptions>
+      <Weights>0.25,0.25,0.25,0.25</Weights>
+    </AlgorithmOptions>
+    <Resampling>Cubic</Resampling>
+    <NumThreads>ALL_CPUS</NumThreads>
+    <BitDepth>8</BitDepth>
+    <NoData>0</NoData>
+    <SpatialExtentAdjustment>Union</SpatialExtentAdjustment>
+    <PanchroBand>
+      <SourceFilename relativeToVRT="1">world_pan.tif</SourceFilename>
+     <SourceBand>1</SourceBand>
+    </PanchroBand>
+    <SpectralBand dstBand="2">
+      <SourceFilename relativeToVRT="1">world_rgbnir.tif</SourceFilename>
+      <SourceBand>1</SourceBand>
+    </SpectralBand>
+    <SpectralBand dstBand="3">
+      <SourceFilename relativeToVRT="1">world_rgbnir.tif</SourceFilename>
+      <SourceBand>2</SourceBand>
+    </SpectralBand>
+    <SpectralBand dstBand="4">
+      <SourceFilename relativeToVRT="1">world_rgbnir.tif</SourceFilename>
+      <SourceBand>3</SourceBand>
+    </SpectralBand>
+    <SpectralBand> <!-- note the absence of the dstBand attribute, to indicate
+                        that the NIR band is not bound to any output band -->
+      <SourceFilename relativeToVRT="1">world_rgbnir.tif</SourceFilename>
+      <SourceBand>4</SourceBand>
+    </SpectralBand>
+  </PansharpeningOptions>
+</VRTDataset>
+\endcode
 
 \section gdal_vrttut_mt Multi-threading issues
 
@@ -879,7 +1142,7 @@ datasets.
 
 The shared attribute, added in GDAL 2.0.0, on the SourceFilename indicates whether the
 dataset should be shared (value is 1) or not (value is 0). The default is 1.
-If several VRT datasets refering to the same underlying sources are used in a multithreaded context,
+If several VRT datasets referring to the same underlying sources are used in a multithreaded context,
 shared should be set to 0. Alternatively, the VRT_SHARED_SOURCE configuration
 option can be set to 0 to force non-shared mode.
 
diff --git a/frmts/vrt/vrtdataset.cpp b/frmts/vrt/vrtdataset.cpp
index d851c5d..fb398d5 100644
--- a/frmts/vrt/vrtdataset.cpp
+++ b/frmts/vrt/vrtdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtdataset.cpp 32756 2016-01-05 16:03:53Z rouault $
+ * $Id: vrtdataset.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTDataset
@@ -29,46 +29,44 @@
  ****************************************************************************/
 
 #include "vrtdataset.h"
-#include "cpl_string.h"
+
 #include "cpl_minixml.h"
+#include "cpl_string.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: vrtdataset.cpp 32756 2016-01-05 16:03:53Z rouault $");
+#include <algorithm>
+
+CPL_CVSID("$Id: vrtdataset.cpp 33808 2016-03-29 21:15:28Z goatbar $");
 
 /************************************************************************/
 /*                            VRTDataset()                             */
 /************************************************************************/
 
-VRTDataset::VRTDataset( int nXSize, int nYSize )
-
+VRTDataset::VRTDataset( int nXSize, int nYSize ) :
+    m_pszProjection(NULL),
+    m_bGeoTransformSet(FALSE),
+    m_nGCPCount(0),
+    m_pasGCPList(NULL),
+    m_pszGCPProjection(NULL),
+    m_bNeedsFlush(FALSE),
+    m_bWritable(TRUE),
+    m_pszVRTPath(NULL),
+    m_poMaskBand(NULL),
+    m_bCompatibleForDatasetIO(-1)
 {
     nRasterXSize = nXSize;
     nRasterYSize = nYSize;
-    pszProjection = NULL;
-
-    bNeedsFlush = FALSE;
-    bWritable = TRUE;
-
-    bGeoTransformSet = FALSE;
-    adfGeoTransform[0] = 0.0;
-    adfGeoTransform[1] = 1.0;
-    adfGeoTransform[2] = 0.0;
-    adfGeoTransform[3] = 0.0;
-    adfGeoTransform[4] = 0.0;
-    adfGeoTransform[5] = 1.0;
 
-    nGCPCount = 0;
-    pasGCPList = NULL;
-    pszGCPProjection = NULL;
-
-    pszVRTPath = NULL;
-
-    poMaskBand = NULL;
+    m_adfGeoTransform[0] = 0.0;
+    m_adfGeoTransform[1] = 1.0;
+    m_adfGeoTransform[2] = 0.0;
+    m_adfGeoTransform[3] = 0.0;
+    m_adfGeoTransform[4] = 0.0;
+    m_adfGeoTransform[5] = 1.0;
 
     GDALRegister_VRT();
-    poDriver = (GDALDriver *) GDALGetDriverByName( "VRT" );
 
-    bCompatibleForDatasetIO = -1;
+    poDriver = reinterpret_cast<GDALDriver *>( GDALGetDriverByName( "VRT" ) );
 }
 
 /************************************************************************/
@@ -93,17 +91,22 @@ VRTDataset::~VRTDataset()
 
 {
     FlushCache();
-    CPLFree( pszProjection );
+    CPLFree( m_pszProjection );
 
-    CPLFree( pszGCPProjection );
-    if( nGCPCount > 0 )
+    CPLFree( m_pszGCPProjection );
+    if( m_nGCPCount > 0 )
     {
-        GDALDeinitGCPs( nGCPCount, pasGCPList );
-        CPLFree( pasGCPList );
+        GDALDeinitGCPs( m_nGCPCount, m_pasGCPList );
+        CPLFree( m_pasGCPList );
     }
-    CPLFree( pszVRTPath );
+    CPLFree( m_pszVRTPath );
+
+    delete m_poMaskBand;
 
-    delete poMaskBand;
+    for(size_t i=0;i<m_apoOverviews.size();i++)
+        delete m_apoOverviews[i];
+    for(size_t i=0;i<m_apoOverviewsBak.size();i++)
+        delete m_apoOverviewsBak[i];
 }
 
 /************************************************************************/
@@ -115,26 +118,24 @@ void VRTDataset::FlushCache()
 {
     GDALDataset::FlushCache();
 
-    if( !bNeedsFlush || bWritable == FALSE)
+    if( !m_bNeedsFlush || m_bWritable == FALSE)
         return;
 
-    bNeedsFlush = FALSE;
+    m_bNeedsFlush = FALSE;
 
-    // We don't write to disk if there is no filename.  This is a 
+    // We don't write to disk if there is no filename.  This is a
     // memory only dataset.
-    if( strlen(GetDescription()) == 0 
-        || EQUALN(GetDescription(),"<VRTDataset",11) )
+    if( strlen(GetDescription()) == 0
+        || STARTS_WITH_CI(GetDescription(), "<VRTDataset") )
         return;
 
     /* -------------------------------------------------------------------- */
     /*      Create the output file.                                         */
     /* -------------------------------------------------------------------- */
-    VSILFILE *fpVRT;
-
-    fpVRT = VSIFOpenL( GetDescription(), "w" );
+    VSILFILE *fpVRT = VSIFOpenL( GetDescription(), "w" );
     if( fpVRT == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Failed to write .vrt file in FlushCache()." );
         return;
     }
@@ -142,23 +143,50 @@ void VRTDataset::FlushCache()
     /* -------------------------------------------------------------------- */
     /*      Convert tree to a single block of XML text.                     */
     /* -------------------------------------------------------------------- */
-    char *pszVRTPath = CPLStrdup(CPLGetPath(GetDescription()));
-    CPLXMLNode *psDSTree = SerializeToXML( pszVRTPath );
-    char *pszXML;
+    char** papszContent = GetMetadata("xml:VRT");
+    bool bOK = true;
+    if( papszContent && papszContent[0] )
+    {
+        /* ------------------------------------------------------------------ */
+        /*      Write to disk.                                                */
+        /* ------------------------------------------------------------------ */
+        bOK &= VSIFWriteL( papszContent[0], 1, strlen(papszContent[0]), fpVRT ) == strlen(papszContent[0]);
+    }
+    if( VSIFCloseL( fpVRT ) != 0 )
+        bOK = false;
+    if( !bOK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Failed to write .vrt file in FlushCache()." );
+        return;
+    }
+}
 
-    pszXML = CPLSerializeXMLTree( psDSTree );
+/************************************************************************/
+/*                            GetMetadata()                             */
+/************************************************************************/
 
-    CPLDestroyXMLNode( psDSTree );
+char** VRTDataset::GetMetadata( const char *pszDomain )
+{
+    if( pszDomain != NULL && EQUAL(pszDomain, "xml:VRT") )
+    {
+        /* ------------------------------------------------------------------ */
+        /*      Convert tree to a single block of XML text.                   */
+        /* ------------------------------------------------------------------ */
+        char *l_pszVRTPath = CPLStrdup(CPLGetPath(GetDescription()));
+        CPLXMLNode *psDSTree = SerializeToXML( l_pszVRTPath );
+        char *pszXML = CPLSerializeXMLTree( psDSTree );
 
-    CPLFree( pszVRTPath );
+        CPLDestroyXMLNode( psDSTree );
 
-    /* -------------------------------------------------------------------- */
-    /*      Write to disk.                                                  */
-    /* -------------------------------------------------------------------- */
-    VSIFWriteL( pszXML, 1, strlen(pszXML), fpVRT );
-    VSIFCloseL( fpVRT );
+        CPLFree( l_pszVRTPath );
 
-    CPLFree( pszXML );
+        char* apszContent[2] = { pszXML, NULL };
+        GDALDataset::SetMetadata(apszContent, "xml:VRT");
+        CPLFree(pszXML);
+    }
+
+    return GDALDataset::GetMetadata(pszDomain);
 }
 
 /************************************************************************/
@@ -173,56 +201,54 @@ void CPL_STDCALL VRTFlushCache( VRTDatasetH hDataset )
 {
     VALIDATE_POINTER0( hDataset, "VRTFlushCache" );
 
-    ((VRTDataset *)hDataset)->FlushCache();
+    reinterpret_cast<VRTDataset *>( hDataset )->FlushCache();
 }
 
 /************************************************************************/
 /*                           SerializeToXML()                           */
 /************************************************************************/
 
-CPLXMLNode *VRTDataset::SerializeToXML( const char *pszVRTPath )
+CPLXMLNode *VRTDataset::SerializeToXML( const char *pszVRTPathIn )
 
 {
     /* -------------------------------------------------------------------- */
     /*      Setup root node and attributes.                                 */
     /* -------------------------------------------------------------------- */
-    CPLXMLNode *psDSTree = NULL;
-    CPLXMLNode *psMD = NULL;
-    char       szNumber[128];
+    CPLXMLNode *psDSTree = CPLCreateXMLNode( NULL, CXT_Element, "VRTDataset" );
 
-    psDSTree = CPLCreateXMLNode( NULL, CXT_Element, "VRTDataset" );
-
-    sprintf( szNumber, "%d", GetRasterXSize() );
+    char szNumber[128];
+    snprintf( szNumber, sizeof(szNumber), "%d", GetRasterXSize() );
     CPLSetXMLValue( psDSTree, "#rasterXSize", szNumber );
 
-    sprintf( szNumber, "%d", GetRasterYSize() );
+    snprintf( szNumber, sizeof(szNumber), "%d", GetRasterYSize() );
     CPLSetXMLValue( psDSTree, "#rasterYSize", szNumber );
 
  /* -------------------------------------------------------------------- */
  /*      SRS                                                             */
  /* -------------------------------------------------------------------- */
-    if( pszProjection != NULL && strlen(pszProjection) > 0 )
-        CPLSetXMLValue( psDSTree, "SRS", pszProjection );
+    if( m_pszProjection != NULL && strlen(m_pszProjection) > 0 )
+        CPLSetXMLValue( psDSTree, "SRS", m_pszProjection );
 
  /* -------------------------------------------------------------------- */
  /*      Geotransform.                                                   */
  /* -------------------------------------------------------------------- */
-    if( bGeoTransformSet )
+    if( m_bGeoTransformSet )
     {
-        CPLSetXMLValue( psDSTree, "GeoTransform", 
-                        CPLSPrintf( "%24.16e,%24.16e,%24.16e,%24.16e,%24.16e,%24.16e",
-                                    adfGeoTransform[0],
-                                    adfGeoTransform[1],
-                                    adfGeoTransform[2],
-                                    adfGeoTransform[3],
-                                    adfGeoTransform[4],
-                                    adfGeoTransform[5] ) );
+        CPLSetXMLValue(
+            psDSTree, "GeoTransform",
+            CPLSPrintf( "%24.16e,%24.16e,%24.16e,%24.16e,%24.16e,%24.16e",
+                        m_adfGeoTransform[0],
+                        m_adfGeoTransform[1],
+                        m_adfGeoTransform[2],
+                        m_adfGeoTransform[3],
+                        m_adfGeoTransform[4],
+                        m_adfGeoTransform[5] ) );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Metadata                                                        */
 /* -------------------------------------------------------------------- */
-    psMD = oMDMD.Serialize();
+    CPLXMLNode *psMD = oMDMD.Serialize();
     if( psMD != NULL )
     {
         CPLAddXMLChild( psDSTree, psMD );
@@ -231,12 +257,12 @@ CPLXMLNode *VRTDataset::SerializeToXML( const char *pszVRTPath )
  /* -------------------------------------------------------------------- */
  /*      GCPs                                                            */
  /* -------------------------------------------------------------------- */
-    if( nGCPCount > 0 )
+    if( m_nGCPCount > 0 )
     {
         GDALSerializeGCPListToXML( psDSTree,
-                                   pasGCPList,
-                                   nGCPCount,
-                                   pszGCPProjection );
+                                   m_pasGCPList,
+                                   m_nGCPCount,
+                                   m_pszGCPProjection );
     }
 
     /* -------------------------------------------------------------------- */
@@ -244,8 +270,9 @@ CPLXMLNode *VRTDataset::SerializeToXML( const char *pszVRTPath )
     /* -------------------------------------------------------------------- */
     for( int iBand = 0; iBand < nBands; iBand++ )
     {
-        CPLXMLNode *psBandTree = 
-            ((VRTRasterBand *) papoBands[iBand])->SerializeToXML(pszVRTPath);
+        CPLXMLNode *psBandTree =
+            reinterpret_cast<VRTRasterBand *>(
+                papoBands[iBand])->SerializeToXML( pszVRTPathIn );
 
         if( psBandTree != NULL )
             CPLAddXMLChild( psDSTree, psBandTree );
@@ -254,15 +281,15 @@ CPLXMLNode *VRTDataset::SerializeToXML( const char *pszVRTPath )
     /* -------------------------------------------------------------------- */
     /*      Serialize dataset mask band.                                    */
     /* -------------------------------------------------------------------- */
-    if (poMaskBand)
+    if (m_poMaskBand)
     {
         CPLXMLNode *psBandTree =
-            poMaskBand->SerializeToXML(pszVRTPath);
+            m_poMaskBand->SerializeToXML(pszVRTPathIn);
 
         if( psBandTree != NULL )
         {
-            CPLXMLNode *psMaskBandElement = CPLCreateXMLNode( psDSTree, CXT_Element, 
-                                                              "MaskBand" );
+            CPLXMLNode *psMaskBandElement
+                = CPLCreateXMLNode( psDSTree, CXT_Element, "MaskBand" );
             CPLAddXMLChild( psMaskBandElement, psBandTree );
         }
     }
@@ -283,32 +310,32 @@ CPLXMLNode * CPL_STDCALL VRTSerializeToXML( VRTDatasetH hDataset,
 {
     VALIDATE_POINTER1( hDataset, "VRTSerializeToXML", NULL );
 
-    return ((VRTDataset *)hDataset)->SerializeToXML(pszVRTPath);
+    return reinterpret_cast<VRTDataset *>(
+        hDataset )->SerializeToXML(pszVRTPath);
 }
 
 /************************************************************************/
 /*                              XMLInit()                               */
 /************************************************************************/
 
-CPLErr VRTDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPath )
+CPLErr VRTDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPathIn )
 
 {
-    if( pszVRTPath != NULL )
-        this->pszVRTPath = CPLStrdup(pszVRTPath);
+    if( pszVRTPathIn != NULL )
+        m_pszVRTPath = CPLStrdup(pszVRTPathIn);
 
 /* -------------------------------------------------------------------- */
 /*      Check for an SRS node.                                          */
 /* -------------------------------------------------------------------- */
     if( strlen(CPLGetXMLValue(psTree, "SRS", "")) > 0 )
     {
-        OGRSpatialReference oSRS;
-
-        CPLFree( pszProjection );
-        pszProjection = NULL;
+        CPLFree( m_pszProjection );
+        m_pszProjection = NULL;
 
+        OGRSpatialReference oSRS;
         if( oSRS.SetFromUserInput( CPLGetXMLValue(psTree, "SRS", "") )
             == OGRERR_NONE )
-            oSRS.exportToWkt( &pszProjection );
+            oSRS.exportToWkt( &m_pszProjection );
     }
 
 /* -------------------------------------------------------------------- */
@@ -317,9 +344,8 @@ CPLErr VRTDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPath )
     if( strlen(CPLGetXMLValue(psTree, "GeoTransform", "")) > 0 )
     {
         const char *pszGT = CPLGetXMLValue(psTree, "GeoTransform", "");
-        char	**papszTokens;
-
-        papszTokens = CSLTokenizeStringComplex( pszGT, ",", FALSE, FALSE );
+        char **papszTokens
+            = CSLTokenizeStringComplex( pszGT, ",", FALSE, FALSE );
         if( CSLCount(papszTokens) != 6 )
         {
             CPLError( CE_Warning, CPLE_AppDefined,
@@ -328,8 +354,8 @@ CPLErr VRTDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPath )
         else
         {
             for( int iTA = 0; iTA < 6; iTA++ )
-                adfGeoTransform[iTA] = CPLAtof(papszTokens[iTA]);
-            bGeoTransformSet = TRUE;
+                m_adfGeoTransform[iTA] = CPLAtof(papszTokens[iTA]);
+            m_bGeoTransformSet = TRUE;
         }
 
         CSLDestroy( papszTokens );
@@ -343,9 +369,9 @@ CPLErr VRTDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPath )
     if( psGCPList != NULL )
     {
         GDALDeserializeGCPListFromXML( psGCPList,
-                                       &pasGCPList,
-                                       &nGCPCount,
-                                       &pszGCPProjection );
+                                       &m_pasGCPList,
+                                       &m_nGCPCount,
+                                       &m_pszGCPProjection );
     }
 
 /* -------------------------------------------------------------------- */
@@ -356,38 +382,43 @@ CPLErr VRTDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPath )
 /* -------------------------------------------------------------------- */
 /*      Create dataset mask band.                                       */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psChild;
 
     /* Parse dataset mask band first */
     CPLXMLNode* psMaskBandNode = CPLGetXMLNode(psTree, "MaskBand");
+
+    CPLXMLNode *psChild;
     if (psMaskBandNode)
         psChild = psMaskBandNode->psChild;
     else
         psChild = NULL;
+
     for( ; psChild != NULL; psChild=psChild->psNext )
     {
         if( psChild->eType == CXT_Element
             && EQUAL(psChild->pszValue,"VRTRasterBand") )
         {
-            VRTRasterBand  *poBand = NULL;
             const char *pszSubclass = CPLGetXMLValue( psChild, "subclass",
                                                       "VRTSourcedRasterBand" );
 
+            VRTRasterBand  *poBand = NULL;
             if( EQUAL(pszSubclass,"VRTSourcedRasterBand") )
                 poBand = new VRTSourcedRasterBand( this, 0 );
             else if( EQUAL(pszSubclass, "VRTDerivedRasterBand") )
                 poBand = new VRTDerivedRasterBand( this, 0 );
             else if( EQUAL(pszSubclass, "VRTRawRasterBand") )
                 poBand = new VRTRawRasterBand( this, 0 );
-            else if( EQUAL(pszSubclass, "VRTWarpedRasterBand") )
+            else if( EQUAL(pszSubclass, "VRTWarpedRasterBand") &&
+                     dynamic_cast<VRTWarpedDataset*>(this) != NULL )
                 poBand = new VRTWarpedRasterBand( this, 0 );
+            //else if( EQUAL(pszSubclass, "VRTPansharpenedRasterBand") )
+            //    poBand = new VRTPansharpenedRasterBand( this, 0 );
             else
                 CPLError( CE_Failure, CPLE_AppDefined,
-                          "VRTRasterBand of unrecognised subclass '%s'.",
+                          "VRTRasterBand of unrecognized subclass '%s'.",
                           pszSubclass );
 
             if( poBand != NULL
-                && poBand->XMLInit( psChild, pszVRTPath ) == CE_None )
+                && poBand->XMLInit( psChild, pszVRTPathIn ) == CE_None )
             {
                 SetMaskBand(poBand);
                 break;
@@ -404,43 +435,47 @@ CPLErr VRTDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPath )
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    int		nBands = 0;
+    int		l_nBands = 0;
     for( psChild=psTree->psChild; psChild != NULL; psChild=psChild->psNext )
     {
         if( psChild->eType == CXT_Element
             && EQUAL(psChild->pszValue,"VRTRasterBand") )
         {
-            VRTRasterBand  *poBand = NULL;
-            const char *pszSubclass = CPLGetXMLValue( psChild, "subclass", 
+            const char *pszSubclass = CPLGetXMLValue( psChild, "subclass",
                                                       "VRTSourcedRasterBand" );
 
+            VRTRasterBand  *poBand = NULL;
             if( EQUAL(pszSubclass,"VRTSourcedRasterBand") )
-                poBand = new VRTSourcedRasterBand( this, nBands+1 );
+                poBand = new VRTSourcedRasterBand( this, l_nBands+1 );
             else if( EQUAL(pszSubclass, "VRTDerivedRasterBand") )
-                poBand = new VRTDerivedRasterBand( this, nBands+1 );
+                poBand = new VRTDerivedRasterBand( this, l_nBands+1 );
             else if( EQUAL(pszSubclass, "VRTRawRasterBand") )
-                poBand = new VRTRawRasterBand( this, nBands+1 );
-            else if( EQUAL(pszSubclass, "VRTWarpedRasterBand") )
-                poBand = new VRTWarpedRasterBand( this, nBands+1 );
+                poBand = new VRTRawRasterBand( this, l_nBands+1 );
+            else if( EQUAL(pszSubclass, "VRTWarpedRasterBand") &&
+                     dynamic_cast<VRTWarpedDataset*>(this) != NULL )
+                poBand = new VRTWarpedRasterBand( this, l_nBands+1 );
+            else if( EQUAL(pszSubclass, "VRTPansharpenedRasterBand") &&
+                     dynamic_cast<VRTPansharpenedDataset*>(this) != NULL )
+                poBand = new VRTPansharpenedRasterBand( this, l_nBands+1 );
             else
                 CPLError( CE_Failure, CPLE_AppDefined,
-                          "VRTRasterBand of unrecognised subclass '%s'.",
+                          "VRTRasterBand of unrecognized subclass '%s'.",
                           pszSubclass );
 
-            if( poBand != NULL 
-                && poBand->XMLInit( psChild, pszVRTPath ) == CE_None )
+            if( poBand != NULL
+                && poBand->XMLInit( psChild, pszVRTPathIn ) == CE_None )
             {
-                SetBand( ++nBands, poBand );
+                SetBand( ++l_nBands, poBand );
             }
             else
             {
                 if( poBand )
-                    delete poBand; 
+                    delete poBand;
                 return CE_Failure;
             }
         }
     }
-    
+
     return CE_None;
 }
 
@@ -451,7 +486,7 @@ CPLErr VRTDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPath )
 int VRTDataset::GetGCPCount()
 
 {
-    return nGCPCount;
+    return m_nGCPCount;
 }
 
 /************************************************************************/
@@ -461,10 +496,10 @@ int VRTDataset::GetGCPCount()
 const char *VRTDataset::GetGCPProjection()
 
 {
-    if( pszGCPProjection == NULL )
+    if( m_pszGCPProjection == NULL )
         return "";
-    else
-        return pszGCPProjection;
+
+    return m_pszGCPProjection;
 }
 
 /************************************************************************/
@@ -474,31 +509,31 @@ const char *VRTDataset::GetGCPProjection()
 const GDAL_GCP *VRTDataset::GetGCPs()
 
 {
-    return pasGCPList;
+    return m_pasGCPList;
 }
 
 /************************************************************************/
 /*                              SetGCPs()                               */
 /************************************************************************/
 
-CPLErr VRTDataset::SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
-                            const char *pszGCPProjection )
+CPLErr VRTDataset::SetGCPs( int nGCPCountIn, const GDAL_GCP *pasGCPListIn,
+                            const char *pszGCPProjectionIn )
 
 {
-    CPLFree( this->pszGCPProjection );
-    if( this->nGCPCount > 0 )
+    CPLFree( m_pszGCPProjection );
+    if( m_nGCPCount > 0 )
     {
-        GDALDeinitGCPs( this->nGCPCount, this->pasGCPList );
-        CPLFree( this->pasGCPList );
+        GDALDeinitGCPs( m_nGCPCount, m_pasGCPList );
+        CPLFree( m_pasGCPList );
     }
 
-    this->pszGCPProjection = CPLStrdup(pszGCPProjection);
+    m_pszGCPProjection = CPLStrdup(pszGCPProjectionIn);
 
-    this->nGCPCount = nGCPCount;
+    m_nGCPCount = nGCPCountIn;
 
-    this->pasGCPList = GDALDuplicateGCPs( nGCPCount, pasGCPList );
+    m_pasGCPList = GDALDuplicateGCPs( nGCPCountIn, pasGCPListIn );
 
-    this->bNeedsFlush = TRUE;
+    m_bNeedsFlush = TRUE;
 
     return CE_None;
 }
@@ -510,13 +545,13 @@ CPLErr VRTDataset::SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
 CPLErr VRTDataset::SetProjection( const char *pszWKT )
 
 {
-    CPLFree( pszProjection );
-    pszProjection = NULL;
+    CPLFree( m_pszProjection );
+    m_pszProjection = NULL;
 
     if( pszWKT != NULL )
-        pszProjection = CPLStrdup(pszWKT);
+        m_pszProjection = CPLStrdup(pszWKT);
 
-    bNeedsFlush = TRUE;
+    m_bNeedsFlush = TRUE;
 
     return CE_None;
 }
@@ -528,10 +563,10 @@ CPLErr VRTDataset::SetProjection( const char *pszWKT )
 const char *VRTDataset::GetProjectionRef()
 
 {
-    if( pszProjection == NULL )
+    if( m_pszProjection == NULL )
         return "";
-    else
-        return pszProjection;
+
+    return m_pszProjection;
 }
 
 /************************************************************************/
@@ -541,10 +576,10 @@ const char *VRTDataset::GetProjectionRef()
 CPLErr VRTDataset::SetGeoTransform( double *padfGeoTransformIn )
 
 {
-    memcpy( adfGeoTransform, padfGeoTransformIn, sizeof(double) * 6 );
-    bGeoTransformSet = TRUE;
+    memcpy( m_adfGeoTransform, padfGeoTransformIn, sizeof(double) * 6 );
+    m_bGeoTransformSet = TRUE;
 
-    bNeedsFlush = TRUE;
+    m_bNeedsFlush = TRUE;
 
     return CE_None;
 }
@@ -556,20 +591,17 @@ CPLErr VRTDataset::SetGeoTransform( double *padfGeoTransformIn )
 CPLErr VRTDataset::GetGeoTransform( double * padfGeoTransform )
 
 {
-    memcpy( padfGeoTransform, adfGeoTransform, sizeof(double) * 6 );
+    memcpy( padfGeoTransform, m_adfGeoTransform, sizeof(double) * 6 );
 
-    if( bGeoTransformSet )
-        return CE_None;
-    else
-        return CE_Failure;
+    return m_bGeoTransformSet ? CE_None : CE_Failure;
 }
 
 /************************************************************************/
 /*                            SetMetadata()                             */
 /************************************************************************/
 
-CPLErr VRTDataset::SetMetadata( char **papszMetadata, 
-                                   const char *pszDomain )
+CPLErr VRTDataset::SetMetadata( char **papszMetadata,
+                                const char *pszDomain )
 
 {
     SetNeedsFlush();
@@ -581,8 +613,8 @@ CPLErr VRTDataset::SetMetadata( char **papszMetadata,
 /*                          SetMetadataItem()                           */
 /************************************************************************/
 
-CPLErr VRTDataset::SetMetadataItem( const char *pszName, 
-                                    const char *pszValue, 
+CPLErr VRTDataset::SetMetadataItem( const char *pszName,
+                                    const char *pszValue,
                                     const char *pszDomain )
 
 {
@@ -615,8 +647,6 @@ int VRTDataset::Identify( GDALOpenInfo * poOpenInfo )
 GDALDataset *VRTDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    char *pszVRTPath = NULL;
-
 /* -------------------------------------------------------------------- */
 /*      Does this appear to be a virtual dataset definition XML         */
 /*      file?                                                           */
@@ -627,26 +657,29 @@ GDALDataset *VRTDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*	Try to read the whole file into memory.				*/
 /* -------------------------------------------------------------------- */
-    char        *pszXML;
+    char *pszXML = NULL;
+    VSILFILE *fp = poOpenInfo->fpL;
 
-    VSILFILE        *fp = poOpenInfo->fpL;
+    char *pszVRTPath = NULL;
     if( fp != NULL )
     {
         unsigned int nLength;
 
         poOpenInfo->fpL = NULL;
-        
+
         if( strcmp(poOpenInfo->pszFilename, "/vsistdin/") == 0 )
         {
             nLength = 0;
-            pszXML = (char *) VSIMalloc(1024+1);
-            while( TRUE )
+            pszXML = reinterpret_cast<char *>( VSIMalloc(1024+1) );
+            while( true )
             {
-                int nRead = (int) VSIFReadL( pszXML + nLength, 1, 1024, fp);
+                const int nRead = static_cast<int>(
+                    VSIFReadL( pszXML + nLength, 1, 1024, fp) );
                 nLength += nRead;
                 if( nRead < 1024 )
                     break;
-                char* pszXMLNew = (char*) VSIRealloc( pszXML, nLength + 1024 + 1);
+                char* pszXMLNew = reinterpret_cast<char *>(
+                    VSIRealloc( pszXML, nLength + 1024 + 1) );
                 if( pszXMLNew == NULL )
                 {
                     VSIFree(pszXML);
@@ -657,24 +690,21 @@ GDALDataset *VRTDataset::Open( GDALOpenInfo * poOpenInfo )
         }
         else
         {
-            VSIFSeekL( fp, 0, SEEK_END );
-            nLength = (int) VSIFTellL( fp );
-            VSIFSeekL( fp, 0, SEEK_SET );
+            CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 0, SEEK_END ));
+            nLength = static_cast<int>( VSIFTellL( fp ) );
+            CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 0, SEEK_SET ));
 
-            pszXML = (char *) VSIMalloc(nLength+1);
+            pszXML = reinterpret_cast<char *>( VSI_MALLOC_VERBOSE(nLength+1) );
 
             if( pszXML == NULL )
             {
-                VSIFCloseL(fp);
-                CPLError( CE_Failure, CPLE_OutOfMemory,
-                          "Failed to allocate %d byte buffer to hold VRT xml file.",
-                          nLength );
+                CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
                 return NULL;
             }
-            
+
             if( VSIFReadL( pszXML, 1, nLength, fp ) != nLength )
             {
-                VSIFCloseL(fp);
+                CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
                 CPLFree( pszXML );
                 CPLError( CE_Failure, CPLE_FileIO,
                           "Failed to read %d bytes from VRT xml file.",
@@ -684,22 +714,24 @@ GDALDataset *VRTDataset::Open( GDALOpenInfo * poOpenInfo )
         }
 
         pszXML[nLength] = '\0';
-        
+
         char* pszCurDir = CPLGetCurrentDir();
-        const char *currentVrtFilename = CPLProjectRelativeFilename(pszCurDir, poOpenInfo->pszFilename);
+        const char *currentVrtFilename
+            = CPLProjectRelativeFilename(pszCurDir, poOpenInfo->pszFilename);
         CPLFree(pszCurDir);
+
 #if defined(HAVE_READLINK) && defined(HAVE_LSTAT)
-        VSIStatBuf statBuffer;
         char filenameBuffer[2048];
 
         while( true ) {
+            VSIStatBuf statBuffer;
             int lstatCode = lstat( currentVrtFilename, &statBuffer );
             if ( lstatCode == -1 ) {
                 if (errno == ENOENT) {
                     // The file could be a virtual file, let later checks handle it.
                     break;
                 } else {
-                    VSIFCloseL(fp);
+                    CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
                     CPLFree( pszXML );
                     CPLError( CE_Failure, CPLE_FileIO,
                               "Failed to lstat %s: %s",
@@ -713,13 +745,18 @@ GDALDataset *VRTDataset::Open( GDALOpenInfo * poOpenInfo )
                 break;
             }
 
-            int bufferSize = readlink(currentVrtFilename, filenameBuffer, sizeof(filenameBuffer));
+            const int bufferSize = static_cast<int>(readlink( currentVrtFilename,
+                                             filenameBuffer,
+                                             sizeof(filenameBuffer) ));
             if (bufferSize != -1) {
-                filenameBuffer[MIN(bufferSize, (int) sizeof(filenameBuffer) - 1)] = 0;
-                // The filename in filenameBuffer might be a relative path from the linkfile resolve it before looping
-                currentVrtFilename = CPLProjectRelativeFilename(CPLGetDirname(currentVrtFilename), filenameBuffer);
+                filenameBuffer[std::min(bufferSize, static_cast<int>(
+                    sizeof(filenameBuffer) ) - 1)] = 0;
+                // The filename in filenameBuffer might be a relative path
+                // from the linkfile resolve it before looping
+                currentVrtFilename = CPLProjectRelativeFilename(
+                    CPLGetDirname( currentVrtFilename ), filenameBuffer);
             } else {
-                VSIFCloseL(fp);
+                CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
                 CPLFree( pszXML );
                 CPLError( CE_Failure, CPLE_FileIO,
                           "Failed to read filename from symlink %s: %s",
@@ -728,11 +765,11 @@ GDALDataset *VRTDataset::Open( GDALOpenInfo * poOpenInfo )
                 return NULL;
             }
         }
-#endif
+#endif  // HAVE_READLINK && HAVE_LSTAT
 
         pszVRTPath = CPLStrdup(CPLGetPath(currentVrtFilename));
 
-        VSIFCloseL(fp);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
     }
 /* -------------------------------------------------------------------- */
 /*      Or use the filename as the XML input.                           */
@@ -741,30 +778,35 @@ GDALDataset *VRTDataset::Open( GDALOpenInfo * poOpenInfo )
     {
         pszXML = CPLStrdup( poOpenInfo->pszFilename );
     }
-    
+
     if( CSLFetchNameValue(poOpenInfo->papszOpenOptions, "ROOT_PATH") != NULL )
     {
         CPLFree(pszVRTPath);
-        pszVRTPath = CPLStrdup(CSLFetchNameValue(poOpenInfo->papszOpenOptions, "ROOT_PATH"));
+        pszVRTPath = CPLStrdup(
+            CSLFetchNameValue( poOpenInfo->papszOpenOptions, "ROOT_PATH" ) );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Turn the XML representation into a VRTDataset.                  */
 /* -------------------------------------------------------------------- */
-    VRTDataset *poDS = (VRTDataset *) OpenXML( pszXML, pszVRTPath, poOpenInfo->eAccess );
+    VRTDataset *poDS = reinterpret_cast<VRTDataset *>(
+        OpenXML( pszXML, pszVRTPath, poOpenInfo->eAccess ) );
 
     if( poDS != NULL )
-        poDS->bNeedsFlush = FALSE;
+        poDS->m_bNeedsFlush = FALSE;
 
     CPLFree( pszXML );
     CPLFree( pszVRTPath );
 
 /* -------------------------------------------------------------------- */
-/*      Open overviews.                                                 */
+/*      Initialize info for later overview discovery.                   */
 /* -------------------------------------------------------------------- */
     if( fp != NULL && poDS != NULL )
-        poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename,
-                                     poOpenInfo->GetSiblingFiles() );
+    {
+        poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
+        if( poOpenInfo->AreSiblingFilesLoaded() )
+            poDS->oOvManager.TransferSiblingFiles( poOpenInfo->StealSiblingFiles() );
+    }
 
     return poDS;
 }
@@ -783,10 +825,7 @@ GDALDataset *VRTDataset::OpenXML( const char *pszXML, const char *pszVRTPath,
  /* -------------------------------------------------------------------- */
  /*      Parse the XML.                                                  */
  /* -------------------------------------------------------------------- */
-    CPLXMLNode	*psTree;
-
-    psTree = CPLParseXMLString( pszXML );
-
+    CPLXMLNode	*psTree = CPLParseXMLString( pszXML );
     if( psTree == NULL )
         return NULL;
 
@@ -799,11 +838,15 @@ GDALDataset *VRTDataset::OpenXML( const char *pszXML, const char *pszVRTPath,
         return NULL;
     }
 
-    if( CPLGetXMLNode( psRoot, "rasterXSize" ) == NULL
+    const bool bIsPansharpened
+        = strstr( pszXML, "VRTPansharpenedDataset" ) != NULL;
+
+    if( !bIsPansharpened &&
+        (CPLGetXMLNode( psRoot, "rasterXSize" ) == NULL
         || CPLGetXMLNode( psRoot, "rasterYSize" ) == NULL
-        || CPLGetXMLNode( psRoot, "VRTRasterBand" ) == NULL )
+        || CPLGetXMLNode( psRoot, "VRTRasterBand" ) == NULL) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Missing one of rasterXSize, rasterYSize or bands on"
                   " VRTDataset." );
         CPLDestroyXMLNode( psTree );
@@ -813,18 +856,21 @@ GDALDataset *VRTDataset::OpenXML( const char *pszXML, const char *pszVRTPath,
 /* -------------------------------------------------------------------- */
 /*      Create the new virtual dataset object.                          */
 /* -------------------------------------------------------------------- */
-    VRTDataset *poDS;
-    int nXSize = atoi(CPLGetXMLValue(psRoot,"rasterXSize","0"));
-    int nYSize = atoi(CPLGetXMLValue(psRoot,"rasterYSize","0"));
-    
-    if ( !GDALCheckDatasetDimensions(nXSize, nYSize) )
+    const int nXSize = atoi(CPLGetXMLValue(psRoot,"rasterXSize","0"));
+    const int nYSize = atoi(CPLGetXMLValue(psRoot,"rasterYSize","0"));
+
+    if ( !bIsPansharpened &&
+         !GDALCheckDatasetDimensions( nXSize, nYSize ) )
     {
         CPLDestroyXMLNode( psTree );
         return NULL;
     }
 
+    VRTDataset *poDS;
     if( strstr(pszXML,"VRTWarpedDataset") != NULL )
         poDS = new VRTWarpedDataset( nXSize, nYSize );
+    else if( bIsPansharpened )
+        poDS = new VRTPansharpenedDataset( nXSize, nYSize );
     else
     {
         poDS = new VRTDataset( nXSize, nYSize );
@@ -852,64 +898,69 @@ GDALDataset *VRTDataset::OpenXML( const char *pszXML, const char *pszVRTPath,
 CPLErr VRTDataset::AddBand( GDALDataType eType, char **papszOptions )
 
 {
-    int i;
-
-    const char *pszSubClass = CSLFetchNameValue(papszOptions, "subclass");
-
-    bNeedsFlush = 1;
+    m_bNeedsFlush = TRUE;
 
 /* ==================================================================== */
 /*      Handle a new raw band.                                          */
 /* ==================================================================== */
+    const char *pszSubClass = CSLFetchNameValue(papszOptions, "subclass");
+
     if( pszSubClass != NULL && EQUAL(pszSubClass,"VRTRawRasterBand") )
     {
-        int nWordDataSize = GDALGetDataTypeSize( eType ) / 8;
-        int nPixelOffset = nWordDataSize;
-        int nLineOffset = nWordDataSize * GetRasterXSize();
-        const char *pszFilename;
-        const char *pszByteOrder = NULL;
-        int bRelativeToVRT = FALSE;
+        const int nWordDataSize = GDALGetDataTypeSizeBytes( eType );
 
 /* -------------------------------------------------------------------- */
 /*      Collect required information.                                   */
 /* -------------------------------------------------------------------- */
         const char* pszImageOffset = CSLFetchNameValueDef(papszOptions, "ImageOffset", "0");
         vsi_l_offset nImageOffset = CPLScanUIntBig(
-                                    pszImageOffset, strlen(pszImageOffset));
+                        pszImageOffset, static_cast<int>(strlen(pszImageOffset)));
 
+        int nPixelOffset = nWordDataSize;
         if( CSLFetchNameValue(papszOptions, "PixelOffset") != NULL )
             nPixelOffset = atoi(CSLFetchNameValue(papszOptions,"PixelOffset"));
 
+        int nLineOffset = nWordDataSize * GetRasterXSize();
         if( CSLFetchNameValue(papszOptions, "LineOffset") != NULL )
             nLineOffset = atoi(CSLFetchNameValue(papszOptions, "LineOffset"));
 
+        const char *pszByteOrder = NULL;
         if( CSLFetchNameValue(papszOptions, "ByteOrder") != NULL )
             pszByteOrder = CSLFetchNameValue(papszOptions, "ByteOrder");
 
+        const char *pszFilename;
         if( CSLFetchNameValue(papszOptions, "SourceFilename") != NULL )
             pszFilename = CSLFetchNameValue(papszOptions, "SourceFilename");
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "AddBand() requires a SourceFilename option for VRTRawRasterBands." );
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "AddBand() requires a SourceFilename option for "
+                      "VRTRawRasterBands." );
             return CE_Failure;
         }
-        
-        bRelativeToVRT = 
-            CSLFetchBoolean( papszOptions, "relativeToVRT", FALSE );
+
+        const bool bRelativeToVRT =
+            CPL_TO_BOOL(CSLFetchBoolean( papszOptions, "relativeToVRT", FALSE ));
 
 /* -------------------------------------------------------------------- */
 /*      Create and initialize the band.                                 */
 /* -------------------------------------------------------------------- */
-        CPLErr eErr;
 
-        VRTRawRasterBand *poBand = 
+        VRTRawRasterBand *poBand =
             new VRTRawRasterBand( this, GetRasterCount() + 1, eType );
 
-        eErr = 
-            poBand->SetRawLink( pszFilename, NULL, bRelativeToVRT,
-                                nImageOffset, nPixelOffset, nLineOffset, 
+        char* l_pszVRTPath = CPLStrdup(CPLGetPath(GetDescription()));
+        if EQUAL(l_pszVRTPath, "")
+        {
+            CPLFree(l_pszVRTPath);
+            l_pszVRTPath = NULL;
+        }
+
+        CPLErr eErr =
+            poBand->SetRawLink( pszFilename, l_pszVRTPath, bRelativeToVRT,
+                                nImageOffset, nPixelOffset, nLineOffset,
                                 pszByteOrder );
+        CPLFree(l_pszVRTPath);
         if( eErr != CE_None )
         {
             delete poBand;
@@ -933,11 +984,9 @@ CPLErr VRTDataset::AddBand( GDALDataType eType, char **papszOptions )
 
             /* We'll need a pointer to the subclass in case we need */
             /* to set the new band's pixel function below. */
-            VRTDerivedRasterBand* poDerivedBand;
-
-            poDerivedBand = new VRTDerivedRasterBand
-                (this, GetRasterCount() + 1, eType,
-                 GetRasterXSize(), GetRasterYSize());
+            VRTDerivedRasterBand* poDerivedBand = new VRTDerivedRasterBand(
+                this, GetRasterCount() + 1, eType,
+                GetRasterXSize(), GetRasterYSize());
 
             /* Set the pixel function options it provided. */
             const char* pszFuncName =
@@ -948,7 +997,7 @@ CPLErr VRTDataset::AddBand( GDALDataType eType, char **papszOptions )
             const char* pszTransferTypeName =
                 CSLFetchNameValue(papszOptions, "SourceTransferType");
             if (pszTransferTypeName != NULL) {
-                GDALDataType eTransferType =
+                const GDALDataType eTransferType =
                     GDALGetDataTypeByName(pszTransferTypeName);
                 if (eTransferType == GDT_Unknown) {
                     CPLError( CE_Failure, CPLE_AppDefined,
@@ -964,40 +1013,45 @@ CPLErr VRTDataset::AddBand( GDALDataType eType, char **papszOptions )
             /* we can assigned the base class pointer now. */
             poBand = poDerivedBand;
         }
-	else {
+        else {
 
-	    /* ---- Standard sourced band ---- */
-	    poBand = new VRTSourcedRasterBand
-		(this, GetRasterCount() + 1, eType, 
-		 GetRasterXSize(), GetRasterYSize());
-	}
+            /* ---- Standard sourced band ---- */
+            poBand = new VRTSourcedRasterBand(
+                this, GetRasterCount() + 1, eType,
+                GetRasterXSize(), GetRasterYSize());
+        }
 
         SetBand( GetRasterCount() + 1, poBand );
 
-        for( i=0; papszOptions != NULL && papszOptions[i] != NULL; i++ )
+        for( int i=0; papszOptions != NULL && papszOptions[i] != NULL; i++ )
         {
-            if( EQUALN(papszOptions[i],"AddFuncSource=", 14) )
+            if( STARTS_WITH_CI(papszOptions[i], "AddFuncSource=") )
             {
-                VRTImageReadFunc pfnReadFunc = NULL;
-                void             *pCBData = NULL;
-                double           dfNoDataValue = VRT_NODATA_UNSET;
-
-                char **papszTokens = CSLTokenizeStringComplex( papszOptions[i]+14,
-                                                               ",", TRUE, FALSE );
-
+                char **papszTokens
+                    = CSLTokenizeStringComplex( papszOptions[i]+14,
+                                                ",", TRUE, FALSE );
                 if( CSLCount(papszTokens) < 1 )
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined, 
-                              "AddFuncSource() ... required argument missing." );
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                              "AddFuncSource(): required argument missing." );
+                    // TODO: How should this error be handled?  Return
+                    // CE_Failure?
                 }
 
+                VRTImageReadFunc pfnReadFunc = NULL;
                 sscanf( papszTokens[0], "%p", &pfnReadFunc );
+
+                void *pCBData = NULL;
                 if( CSLCount(papszTokens) > 1 )
                     sscanf( papszTokens[1], "%p", &pCBData );
-                if( CSLCount(papszTokens) > 2 )
-                    dfNoDataValue = CPLAtof( papszTokens[2] );
+
+                const double dfNoDataValue =
+                    ( CSLCount(papszTokens) > 2 ) ?
+                    CPLAtof( papszTokens[2] ) : VRT_NODATA_UNSET;
 
                 poBand->AddFuncSource( pfnReadFunc, pCBData, dfNoDataValue );
+
+                CSLDestroy( papszTokens );
             }
         }
 
@@ -1013,13 +1067,14 @@ CPLErr VRTDataset::AddBand( GDALDataType eType, char **papszOptions )
  * @see VRTDataset::VRTAddBand().
  */
 
-int CPL_STDCALL VRTAddBand( VRTDatasetH hDataset, GDALDataType eType, 
+int CPL_STDCALL VRTAddBand( VRTDatasetH hDataset, GDALDataType eType,
                             char **papszOptions )
 
 {
     VALIDATE_POINTER1( hDataset, "VRTAddBand", 0 );
 
-    return ((VRTDataset *) hDataset)->AddBand(eType, papszOptions);
+    return reinterpret_cast<VRTDataset *>(
+        hDataset )->AddBand( eType, papszOptions );
 }
 
 /************************************************************************/
@@ -1032,49 +1087,45 @@ VRTDataset::Create( const char * pszName,
                     GDALDataType eType, char ** papszOptions )
 
 {
-    VRTDataset *poDS = NULL;
-    int        iBand = 0;
-
-    (void) papszOptions;
 
-    if( EQUALN(pszName,"<VRTDataset",11) )
+    if( STARTS_WITH_CI(pszName, "<VRTDataset") )
     {
         GDALDataset *poDS = OpenXML( pszName, NULL, GA_Update );
-        if (poDS)
+        if ( poDS != NULL )
             poDS->SetDescription( "<FromXML>" );
         return poDS;
     }
+
+    const char *pszSubclass = CSLFetchNameValue( papszOptions,
+                                                 "SUBCLASS" );
+
+    VRTDataset *poDS = NULL;
+
+    if( pszSubclass == NULL || EQUAL(pszSubclass,"VRTDataset") )
+        poDS = new VRTDataset( nXSize, nYSize );
+    else if( EQUAL(pszSubclass,"VRTWarpedDataset") )
+    {
+        poDS = new VRTWarpedDataset( nXSize, nYSize );
+    }
     else
     {
-        const char *pszSubclass = CSLFetchNameValue( papszOptions,
-                                                     "SUBCLASS" );
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "SUBCLASS=%s not recognised.",
+                  pszSubclass );
+        return NULL;
+    }
+    poDS->eAccess = GA_Update;
 
-        if( pszSubclass == NULL || EQUAL(pszSubclass,"VRTDataset") )
-            poDS = new VRTDataset( nXSize, nYSize );
-        else if( EQUAL(pszSubclass,"VRTWarpedDataset") )
-        {
-            poDS = new VRTWarpedDataset( nXSize, nYSize );
-        }
-        else
-        {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "SUBCLASS=%s not recognised.", 
-                      pszSubclass );
-            return NULL;
-        }
-        poDS->eAccess = GA_Update;
+    poDS->SetDescription( pszName );
 
-        poDS->SetDescription( pszName );
-        
-        for( iBand = 0; iBand < nBands; iBand++ )
-            poDS->AddBand( eType, NULL );
-        
-        poDS->bNeedsFlush = 1;
+    for( int iBand = 0; iBand < nBands; iBand++ )
+        poDS->AddBand( eType, NULL );
 
-        poDS->oOvManager.Initialize( poDS, pszName );
-        
-        return poDS;
-    }
+    poDS->m_bNeedsFlush = TRUE;
+
+    poDS->oOvManager.Initialize( poDS, pszName );
+
+    return poDS;
 }
 
 /************************************************************************/
@@ -1084,24 +1135,25 @@ VRTDataset::Create( const char * pszName,
 char** VRTDataset::GetFileList()
 {
     char** papszFileList = GDALDataset::GetFileList();
-    
+
     int nSize = CSLCount(papszFileList);
     int nMaxSize = nSize;
-    
-    /* Don't need an element desallocator as each string points to an */
-    /* element of the papszFileList */
+
+    // Do not need an element deallocator as each string points to an
+    // element of the papszFileList.
     CPLHashSet* hSetFiles = CPLHashSetNew(CPLHashSetHashStr,
                                           CPLHashSetEqualStr,
                                           NULL);
-                                          
+
     for( int iBand = 0; iBand < nBands; iBand++ )
     {
-       ((VRTRasterBand *) papoBands[iBand])->GetFileList(
-                                &papszFileList, &nSize, &nMaxSize, hSetFiles);
+      reinterpret_cast<VRTRasterBand *>(
+          papoBands[iBand])->GetFileList(
+              &papszFileList, &nSize, &nMaxSize, hSetFiles );
     }
-                                          
+
     CPLHashSetDestroy(hSetFiles);
-    
+
     return papszFileList;
 }
 
@@ -1115,31 +1167,30 @@ char** VRTDataset::GetFileList()
 CPLErr VRTDataset::Delete( const char * pszFilename )
 {
     GDALDriverH hDriver = GDALIdentifyDriver(pszFilename, NULL);
-    if (hDriver && EQUAL(GDALGetDriverShortName(hDriver), "VRT"))
+
+    if (!hDriver || !EQUAL( GDALGetDriverShortName(hDriver), "VRT" ) )
+        return CE_Failure;
+
+    if( strstr(pszFilename, "<VRTDataset") == NULL &&
+        VSIUnlink( pszFilename ) != 0 )
     {
-        if( strstr(pszFilename, "<VRTDataset") == NULL &&
-            VSIUnlink( pszFilename ) != 0 )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Deleting %s failed:\n%s",
-                      pszFilename,
-                      VSIStrerror(errno) );
-            return CE_Failure;
-        }
-        
-        return CE_None;
-    }
-    else
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Deleting %s failed:\n%s",
+                  pszFilename,
+                  VSIStrerror(errno) );
         return CE_Failure;
+    }
+
+    return CE_None;
 }
 
 /************************************************************************/
 /*                          CreateMaskBand()                            */
 /************************************************************************/
 
-CPLErr VRTDataset::CreateMaskBand( CPL_UNUSED int nFlags )
+CPLErr VRTDataset::CreateMaskBand( int )
 {
-    if (poMaskBand != NULL)
+    if (m_poMaskBand != NULL)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "This VRT dataset has already a mask band");
@@ -1155,11 +1206,11 @@ CPLErr VRTDataset::CreateMaskBand( CPL_UNUSED int nFlags )
 /*                           SetMaskBand()                              */
 /************************************************************************/
 
-void VRTDataset::SetMaskBand(VRTRasterBand* poMaskBand)
+void VRTDataset::SetMaskBand(VRTRasterBand* poMaskBandIn)
 {
-    delete this->poMaskBand;
-    this->poMaskBand = poMaskBand;
-    poMaskBand->SetIsMaskBand();
+    delete m_poMaskBand;
+    m_poMaskBand = poMaskBandIn;
+    m_poMaskBand->SetIsMaskBand();
 }
 
 /************************************************************************/
@@ -1176,9 +1227,10 @@ int VRTDataset::CloseDependentDatasets()
 
     for( int iBand = 0; iBand < nBands; iBand++ )
     {
-       bHasDroppedRef |= ((VRTRasterBand *) papoBands[iBand])->
-                                                CloseDependentDatasets();
+        bHasDroppedRef |= reinterpret_cast<VRTRasterBand *>(
+            papoBands[iBand] )->CloseDependentDatasets();
     }
+
     return bHasDroppedRef;
 }
 
@@ -1192,21 +1244,18 @@ int VRTDataset::CloseDependentDatasets()
 
 int VRTDataset::CheckCompatibleForDatasetIO()
 {
-    int iBand;
     int nSources = 0;
     VRTSource    **papoSources = NULL;
     CPLString osResampling;
-    for(iBand = 0; iBand < nBands; iBand++)
+
+    for(int iBand = 0; iBand < nBands; iBand++)
     {
-        if (!((VRTRasterBand *) papoBands[iBand])->IsSourcedRasterBand())
+        if (!reinterpret_cast<VRTRasterBand *>(
+                papoBands[iBand] )->IsSourcedRasterBand() )
             return FALSE;
 
-        VRTSourcedRasterBand* poBand = (VRTSourcedRasterBand* )papoBands[iBand];
-
-        /* If there are overviews, let's VRTSourcedRasterBand::IRasterIO() */
-        /* do the job */
-        if (poBand->GetOverviewCount() != 0)
-            return FALSE;
+        VRTSourcedRasterBand* poBand
+            = reinterpret_cast<VRTSourcedRasterBand*>( papoBands[iBand] );
 
         if (iBand == 0)
         {
@@ -1217,7 +1266,8 @@ int VRTDataset::CheckCompatibleForDatasetIO()
                 if (!papoSources[iSource]->IsSimpleSource())
                     return FALSE;
 
-                VRTSimpleSource* poSource = (VRTSimpleSource* )papoSources[iSource];
+                VRTSimpleSource* poSource = reinterpret_cast<VRTSimpleSource *>(
+                    papoSources[iSource] );
                 if (!EQUAL(poSource->GetType(), "SimpleSource"))
                     return FALSE;
 
@@ -1241,8 +1291,14 @@ int VRTDataset::CheckCompatibleForDatasetIO()
         {
             for(int iSource = 0; iSource < nSources; iSource++)
             {
-                VRTSimpleSource* poRefSource = (VRTSimpleSource* )papoSources[iSource];
-                VRTSimpleSource* poSource = (VRTSimpleSource* )poBand->papoSources[iSource];
+                if (!poBand->papoSources[iSource]->IsSimpleSource())
+                    return FALSE;
+                VRTSimpleSource* poRefSource
+                    = reinterpret_cast<VRTSimpleSource *>(
+                        papoSources[iSource] );
+
+                VRTSimpleSource* poSource = reinterpret_cast<VRTSimpleSource *>(
+                    poBand->papoSources[iSource] );
                 if (!EQUAL(poSource->GetType(), "SimpleSource"))
                     return FALSE;
                 if (!poSource->IsSameExceptBandNumber(poRefSource))
@@ -1280,13 +1336,18 @@ GDALDataset* VRTDataset::GetSingleSimpleSource()
     if (!CheckCompatibleForDatasetIO())
         return NULL;
 
-    VRTSourcedRasterBand* poVRTBand = (VRTSourcedRasterBand* )papoBands[0];
+    VRTSourcedRasterBand* poVRTBand
+        = reinterpret_cast<VRTSourcedRasterBand *>( papoBands[0] );
     if( poVRTBand->nSources != 1 )
         return NULL;
-    VRTSimpleSource* poSource = (VRTSimpleSource* )poVRTBand->papoSources[0];
+
+    VRTSimpleSource* poSource = reinterpret_cast<VRTSimpleSource *>(
+        poVRTBand->papoSources[0] );
+
     GDALRasterBand* poBand = poSource->GetBand();
     if (poBand == NULL)
         return NULL;
+
     GDALDataset* poSrcDS = poBand->GetDataset();
     if (poSrcDS == NULL)
         return NULL;
@@ -1295,14 +1356,18 @@ GDALDataset* VRTDataset::GetSingleSimpleSource()
     double dfReqXOff, dfReqYOff, dfReqXSize, dfReqYSize;
     int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
     int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
-    poSource->GetSrcDstWindow( 0, 0,
-                               poSrcDS->GetRasterXSize(), poSrcDS->GetRasterYSize(),
-                               poSrcDS->GetRasterXSize(), poSrcDS->GetRasterYSize(),
-                               &dfReqXOff, &dfReqYOff, &dfReqXSize, &dfReqYSize,
-                               &nReqXOff, &nReqYOff,
-                               &nReqXSize, &nReqYSize,
-                               &nOutXOff, &nOutYOff,
-                               &nOutXSize, &nOutYSize );
+    if (! poSource->GetSrcDstWindow( 0, 0,
+                                     poSrcDS->GetRasterXSize(),
+                                     poSrcDS->GetRasterYSize(),
+                                     poSrcDS->GetRasterXSize(),
+                                     poSrcDS->GetRasterYSize(),
+                                     &dfReqXOff, &dfReqYOff,
+                                     &dfReqXSize, &dfReqYSize,
+                                     &nReqXOff, &nReqYOff,
+                                     &nReqXSize, &nReqYSize,
+                                     &nOutXOff, &nOutYOff,
+                                     &nOutXSize, &nOutYSize ) )
+        return NULL;
 
     if (nReqXOff != 0 || nReqYOff != 0 ||
         nReqXSize != poSrcDS->GetRasterXSize() ||
@@ -1330,23 +1395,94 @@ CPLErr VRTDataset::IRasterIO( GDALRWFlag eRWFlag,
                                GSpacing nBandSpace,
                                GDALRasterIOExtraArg* psExtraArg)
 {
-    if (bCompatibleForDatasetIO < 0)
+    if (m_bCompatibleForDatasetIO < 0)
     {
-        bCompatibleForDatasetIO = CheckCompatibleForDatasetIO();
+        m_bCompatibleForDatasetIO = CheckCompatibleForDatasetIO();
     }
-    if (bCompatibleForDatasetIO && eRWFlag == GF_Read)
+
+    bool bLocalCompatibleForDatasetIO = CPL_TO_BOOL(m_bCompatibleForDatasetIO);
+    if (bLocalCompatibleForDatasetIO && eRWFlag == GF_Read &&
+        (nBufXSize < nXSize || nBufYSize < nYSize))
+    {
+        int bTried;
+        CPLErr eErr = TryOverviewRasterIO( eRWFlag,
+                                    nXOff, nYOff, nXSize, nYSize,
+                                    pData, nBufXSize, nBufYSize,
+                                    eBufType,
+                                    nBandCount, panBandMap,
+                                    nPixelSpace, nLineSpace,
+                                    nBandSpace,
+                                    psExtraArg,
+                                    &bTried );
+        if( bTried )
+            return eErr;
+
+        for(int iBand = 0; iBand < nBands; iBand++)
+        {
+            VRTSourcedRasterBand* poBand
+                = reinterpret_cast<VRTSourcedRasterBand *>( papoBands[iBand] );
+
+            // If there are overviews, let VRTSourcedRasterBand::IRasterIO()
+            // do the job.
+            if( poBand->GetOverviewCount() != 0 )
+            {
+                bLocalCompatibleForDatasetIO = false;
+                break;
+            }
+        }
+    }
+
+    // If resampling with non-nearest neighbour, we need to be careful
+    // if the VRT band exposes a nodata value, but the sources do not have it
+    if (bLocalCompatibleForDatasetIO && eRWFlag == GF_Read &&
+        (nXSize != nBufXSize || nYSize != nBufYSize) &&
+        psExtraArg->eResampleAlg != GRIORA_NearestNeighbour )
     {
         for(int iBandIndex=0; iBandIndex<nBandCount; iBandIndex++)
         {
             VRTSourcedRasterBand* poBand =
-                    (VRTSourcedRasterBand*)GetRasterBand(panBandMap[iBandIndex]);
+                reinterpret_cast<VRTSourcedRasterBand*>(
+                    GetRasterBand(panBandMap[iBandIndex]) );
+            int bHasNoData = FALSE;
+            const double dfNoDataValue = poBand->GetNoDataValue(&bHasNoData);
+            if( bHasNoData )
+            {
+                for( int i = 0; i < poBand->nSources; i++ )
+                {
+                    VRTSimpleSource* poSource
+                        = reinterpret_cast<VRTSimpleSource *>(
+                            poBand->papoSources[i] );
+                    int bSrcHasNoData = FALSE;
+                    const double dfSrcNoData
+                        = poSource->GetBand()->GetNoDataValue(&bSrcHasNoData);
+                    if( !bSrcHasNoData || dfSrcNoData != dfNoDataValue )
+                    {
+                        bLocalCompatibleForDatasetIO = false;
+                        break;
+                    }
+                }
+                if( !bLocalCompatibleForDatasetIO )
+                    break;
+            }
+        }
+    }
+
+    if (bLocalCompatibleForDatasetIO && eRWFlag == GF_Read)
+    {
+        for(int iBandIndex=0; iBandIndex<nBandCount; iBandIndex++)
+        {
+            VRTSourcedRasterBand* poBand
+                = reinterpret_cast<VRTSourcedRasterBand *>(
+                    GetRasterBand( panBandMap[iBandIndex] ) );
 
             /* Dirty little trick to initialize the buffer without doing */
             /* any real I/O */
-            int nSavedSources = poBand->nSources;
+            const int nSavedSources = poBand->nSources;
             poBand->nSources = 0;
 
-            GByte *pabyBandData = ((GByte *) pData) + iBandIndex * nBandSpace;
+            GByte *pabyBandData
+                = reinterpret_cast<GByte *>( pData ) + iBandIndex * nBandSpace;
+
             poBand->IRasterIO(GF_Read, nXOff, nYOff, nXSize, nYSize,
                                 pabyBandData, nBufXSize, nBufYSize,
                                 eBufType,
@@ -1360,19 +1496,24 @@ CPLErr VRTDataset::IRasterIO( GDALRWFlag eRWFlag,
         GDALProgressFunc  pfnProgressGlobal = psExtraArg->pfnProgress;
         void             *pProgressDataGlobal = psExtraArg->pProgressData;
 
-        /* Use the last band, because when sources reference a GDALProxyDataset, they */
-        /* don't necessary instanciate all underlying rasterbands */
-        VRTSourcedRasterBand* poBand = (VRTSourcedRasterBand* )papoBands[nBands - 1];
-        for(int iSource = 0; eErr == CE_None && iSource < poBand->nSources; iSource++)
+        // Use the last band, because when sources reference a GDALProxyDataset,
+        // they don't necessary instantiate all underlying rasterbands.
+        VRTSourcedRasterBand* poBand = reinterpret_cast<VRTSourcedRasterBand *>(
+            papoBands[nBands - 1] );
+        for( int iSource = 0;
+             eErr == CE_None && iSource < poBand->nSources;
+             iSource++ )
         {
             psExtraArg->pfnProgress = GDALScaledProgress;
-            psExtraArg->pProgressData = 
+            psExtraArg->pProgressData =
                 GDALCreateScaledProgress( 1.0 * iSource / poBand->nSources,
                                         1.0 * (iSource + 1) / poBand->nSources,
                                         pfnProgressGlobal,
                                         pProgressDataGlobal );
 
-            VRTSimpleSource* poSource = (VRTSimpleSource* )poBand->papoSources[iSource];
+            VRTSimpleSource* poSource = reinterpret_cast<VRTSimpleSource *>(
+                poBand->papoSources[iSource] );
+
             eErr = poSource->DatasetRasterIO( nXOff, nYOff, nXSize, nYSize,
                                               pData, nBufXSize, nBufYSize,
                                               eBufType,
@@ -1393,7 +1534,8 @@ CPLErr VRTDataset::IRasterIO( GDALRWFlag eRWFlag,
                                   pData, nBufXSize, nBufYSize,
                                   eBufType,
                                   nBandCount, panBandMap,
-                                  nPixelSpace, nLineSpace, nBandSpace, psExtraArg);
+                                  nPixelSpace, nLineSpace, nBandSpace,
+                                  psExtraArg);
 }
 
 /************************************************************************/
@@ -1404,19 +1546,156 @@ void VRTDataset::UnsetPreservedRelativeFilenames()
 {
     for(int iBand = 0; iBand < nBands; iBand++)
     {
-        if (!((VRTRasterBand *) papoBands[iBand])->IsSourcedRasterBand())
+        if( !reinterpret_cast<VRTRasterBand *>(
+               papoBands[iBand] )->IsSourcedRasterBand() )
             continue;
 
-        VRTSourcedRasterBand* poBand = (VRTSourcedRasterBand* )papoBands[iBand];
-        int nSources = poBand->nSources;
+        VRTSourcedRasterBand* poBand
+            = reinterpret_cast<VRTSourcedRasterBand *>( papoBands[iBand] );
+        const int nSources = poBand->nSources;
         VRTSource** papoSources = poBand->papoSources;
         for(int iSource = 0; iSource < nSources; iSource++)
         {
             if (!papoSources[iSource]->IsSimpleSource())
                 continue;
 
-            VRTSimpleSource* poSource = (VRTSimpleSource* )papoSources[iSource];
+            VRTSimpleSource* poSource = reinterpret_cast<VRTSimpleSource *>(
+                papoSources[iSource] );
             poSource->UnsetPreservedRelativeFilenames();
         }
     }
 }
+
+/************************************************************************/
+/*                        BuildVirtualOverviews()                       */
+/************************************************************************/
+
+void VRTDataset::BuildVirtualOverviews()
+{
+    // Currently we expose virtual overviews only if the dataset is made of
+    // a single SimpleSource/ComplexSource, in each band.
+    // And if the underlying sources have overviews of course
+    if( m_apoOverviews.size() || m_apoOverviewsBak.size() )
+        return;
+
+    int nOverviews = 0;
+    GDALRasterBand* poFirstBand = NULL;
+    for(int iBand = 0; iBand < nBands; iBand++)
+    {
+        if( !reinterpret_cast<VRTRasterBand *>(
+               papoBands[iBand] )->IsSourcedRasterBand())
+            return;
+
+        VRTSourcedRasterBand* poVRTBand
+            = reinterpret_cast<VRTSourcedRasterBand *>( papoBands[iBand] );
+        if( poVRTBand->nSources != 1 )
+            return;
+        if (!poVRTBand->papoSources[0]->IsSimpleSource())
+            return;
+
+        VRTSimpleSource* poSource
+            = reinterpret_cast<VRTSimpleSource *>( poVRTBand->papoSources[0] );
+        if (!EQUAL(poSource->GetType(), "SimpleSource") &&
+            !EQUAL(poSource->GetType(), "ComplexSource"))
+            return;
+        GDALRasterBand* poSrcBand = poSource->GetBand();
+        if (poSrcBand == NULL)
+            return;
+
+        // To prevent recursion
+        m_apoOverviewsBak.push_back(NULL);
+        const int nOvrCount = poSrcBand->GetOverviewCount();
+        m_apoOverviewsBak.resize(0);
+
+        if( nOvrCount == 0 )
+            return;
+        if( iBand == 0 )
+        {
+            poFirstBand = poSrcBand;
+            nOverviews = nOvrCount;
+        }
+        else if( nOvrCount < nOverviews )
+            nOverviews = nOvrCount;
+    }
+
+    for(int j=0;j<nOverviews;j++)
+    {
+        const double dfXRatio = static_cast<double>(
+            poFirstBand->GetOverview(j)->GetXSize() ) / poFirstBand->GetXSize();
+        const double dfYRatio = static_cast<double>(
+            poFirstBand->GetOverview(j)->GetYSize() ) / poFirstBand->GetYSize();
+        const int nOvrXSize = static_cast<int>(0.5 + nRasterXSize * dfXRatio);
+        const int nOvrYSize = static_cast<int>(0.5 + nRasterYSize * dfYRatio);
+        if( nOvrXSize < 128 || nOvrYSize < 128 )
+            break;
+        VRTDataset* poOvrVDS = new VRTDataset(nOvrXSize, nOvrYSize);
+        m_apoOverviews.push_back(poOvrVDS);
+
+        for(int i=0;i<nBands;i++)
+        {
+            VRTSourcedRasterBand* poVRTBand
+                = reinterpret_cast<VRTSourcedRasterBand *>(
+                    GetRasterBand(i+1) );
+            VRTSourcedRasterBand* poOvrVRTBand = new VRTSourcedRasterBand(
+                poOvrVDS,
+                poOvrVDS->GetRasterCount() + 1,
+                poVRTBand->GetRasterDataType(),
+                nOvrXSize, nOvrYSize);
+            poOvrVDS->SetBand( poOvrVDS->GetRasterCount() + 1, poOvrVRTBand );
+
+            VRTSimpleSource* poSrcSource = reinterpret_cast<VRTSimpleSource *>(
+                poVRTBand->papoSources[0] );
+            VRTSimpleSource* poNewSource = NULL;
+            if( EQUAL(poSrcSource->GetType(), "SimpleSource") )
+                poNewSource = new VRTSimpleSource(poSrcSource, dfXRatio, dfYRatio);
+            else if( EQUAL(poSrcSource->GetType(), "ComplexSource") )
+              poNewSource = new VRTComplexSource(
+                  reinterpret_cast<VRTComplexSource *>( poSrcSource ),
+                  dfXRatio, dfYRatio );
+            else
+            {
+                CPLAssert(FALSE);
+            }
+            if( poNewSource->GetBand()->GetDataset() )
+                poNewSource->GetBand()->GetDataset()->Reference();
+            poOvrVRTBand->AddSource(poNewSource);
+        }
+    }
+}
+
+/************************************************************************/
+/*                          IBuildOverviews()                           */
+/************************************************************************/
+
+CPLErr
+VRTDataset::IBuildOverviews( const char *pszResampling,
+                             int nOverviews,
+                             int *panOverviewList,
+                             int nListBands,
+                             int *panBandList,
+                             GDALProgressFunc pfnProgress,
+                             void * pProgressData )
+{
+    /* Make implicit overviews invisible, but do not destroy */
+    /* them in case they are already used (not sure that the client */
+    /* has the right to do that. behaviour undefined in GDAL API I think) */
+    if( m_apoOverviews.size() )
+    {
+        m_apoOverviewsBak = m_apoOverviews;
+        m_apoOverviews.resize(0);
+    }
+    else
+    {
+        // Add a dummy overview so that GDALDataset::IBuildOverviews()
+        // doesn't manage to get a virtual implicit overview
+        m_apoOverviews.push_back(NULL);
+    }
+
+    return GDALDataset::IBuildOverviews(pszResampling,
+                                               nOverviews,
+                                               panOverviewList,
+                                               nListBands,
+                                               panBandList,
+                                               pfnProgress,
+                                               pProgressData);
+}
diff --git a/frmts/vrt/vrtdataset.h b/frmts/vrt/vrtdataset.h
index cf45bef..eea6f28 100644
--- a/frmts/vrt/vrtdataset.h
+++ b/frmts/vrt/vrtdataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtdataset.h 29294 2015-06-05 08:52:15Z rouault $
+ * $Id: vrtdataset.h 33794 2016-03-26 13:19:07Z goatbar $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Declaration of virtual gdal dataset classes.
@@ -31,10 +31,13 @@
 #ifndef VIRTUALDATASET_H_INCLUDED
 #define VIRTUALDATASET_H_INCLUDED
 
-#include "gdal_priv.h"
+#include "cpl_hash_set.h"
 #include "gdal_pam.h"
+#include "gdal_priv.h"
 #include "gdal_vrt.h"
-#include "cpl_hash_set.h"
+
+#include <map>
+#include <vector>
 
 int VRTApplyMetadata( CPLXMLNode *, GDALMajorObject * );
 CPLXMLNode *VRTSerializeMetadata( GDALMajorObject * );
@@ -57,10 +60,10 @@ public:
     int             nBand;
     GDALRasterBand *poBand;
     int             bTriedToOpen;
-    
-    VRTOverviewInfo() : poBand(NULL), bTriedToOpen(FALSE) {}
+
+    VRTOverviewInfo() : nBand(0), poBand(NULL), bTriedToOpen(FALSE) {}
     ~VRTOverviewInfo() {
-        if( poBand == NULL ) 
+        if( poBand == NULL )
             /* do nothing */;
         else if( poBand->GetDataset()->GetShared() )
             GDALClose( (GDALDatasetH) poBand->GetDataset() );
@@ -74,14 +77,14 @@ public:
 /*                              VRTSource                               */
 /************************************************************************/
 
-class CPL_DLL VRTSource 
+class CPL_DLL VRTSource
 {
 public:
     virtual ~VRTSource();
 
-    virtual CPLErr  RasterIO( int nXOff, int nYOff, int nXSize, int nYSize, 
-                              void *pData, int nBufXSize, int nBufYSize, 
-                              GDALDataType eBufType, 
+    virtual CPLErr  RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
+                              void *pData, int nBufXSize, int nBufYSize,
+                              GDALDataType eBufType,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
                               GDALRasterIOExtraArg* psExtraArg ) = 0;
 
@@ -89,8 +92,8 @@ public:
     virtual double GetMaximum( int nXSize, int nYSize, int *pbSuccess ) = 0;
     virtual CPLErr ComputeRasterMinMax( int nXSize, int nYSize, int bApproxOK, double* adfMinMax ) = 0;
     virtual CPLErr ComputeStatistics( int nXSize, int nYSize,
-                                      int bApproxOK, 
-                                      double *pdfMin, double *pdfMax, 
+                                      int bApproxOK,
+                                      double *pdfMin, double *pdfMax,
                                       double *pdfMean, double *pdfStdDev,
                                       GDALProgressFunc pfnProgress, void *pProgressData ) = 0;
     virtual CPLErr  GetHistogram( int nXSize, int nYSize,
@@ -101,7 +104,7 @@ public:
 
     virtual CPLErr  XMLInit( CPLXMLNode *psTree, const char * ) = 0;
     virtual CPLXMLNode *SerializeToXML( const char *pszVRTPath ) = 0;
-    
+
     virtual void   GetFileList(char*** ppapszFileList, int *pnSize,
                                int *pnMaxSize, CPLHashSet* hSetFiles);
 
@@ -123,36 +126,38 @@ class CPL_DLL VRTDataset : public GDALDataset
 {
     friend class VRTRasterBand;
 
-    char           *pszProjection;
+    char           *m_pszProjection;
 
-    int            bGeoTransformSet;
-    double         adfGeoTransform[6];
+    int            m_bGeoTransformSet;
+    double         m_adfGeoTransform[6];
 
-    int           nGCPCount;
-    GDAL_GCP      *pasGCPList;
-    char          *pszGCPProjection;
+    int           m_nGCPCount;
+    GDAL_GCP      *m_pasGCPList;
+    char          *m_pszGCPProjection;
 
-    int            bNeedsFlush;
-    int            bWritable;
-    
-    char          *pszVRTPath;
+    int            m_bNeedsFlush;
+    int            m_bWritable;
 
-    VRTRasterBand *poMaskBand;
+    char          *m_pszVRTPath;
 
-    int            bCompatibleForDatasetIO;
+    VRTRasterBand *m_poMaskBand;
+
+    int            m_bCompatibleForDatasetIO;
     int            CheckCompatibleForDatasetIO();
+    std::vector<GDALDataset*> m_apoOverviews;
+    std::vector<GDALDataset*> m_apoOverviewsBak;
 
   protected:
     virtual int         CloseDependentDatasets();
 
   public:
                  VRTDataset(int nXSize, int nYSize);
-                ~VRTDataset();
+    virtual ~VRTDataset();
 
-    void          SetNeedsFlush() { bNeedsFlush = TRUE; }
+    void          SetNeedsFlush() { m_bNeedsFlush = TRUE; }
     virtual void  FlushCache();
-    
-    void SetWritable(int bWritable) { this->bWritable = bWritable; }
+
+    void SetWritable(int bWritableIn) { m_bWritable = bWritableIn; }
 
     virtual CPLErr          CreateMaskBand( int nFlags );
     void SetMaskBand(VRTRasterBand* poMaskBand);
@@ -166,15 +171,17 @@ class CPL_DLL VRTDataset : public GDALDataset
     virtual CPLErr SetMetadataItem( const char *pszName, const char *pszValue,
                                     const char *pszDomain = "" );
 
+    virtual char** GetMetadata( const char *pszDomain = "" );
+
     virtual int    GetGCPCount();
     virtual const char *GetGCPProjection();
     virtual const GDAL_GCP *GetGCPs();
     virtual CPLErr SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
                             const char *pszGCPProjection );
 
-    virtual CPLErr AddBand( GDALDataType eType, 
+    virtual CPLErr AddBand( GDALDataType eType,
                             char **papszOptions=NULL );
-                            
+
     virtual char      **GetFileList();
 
     virtual CPLErr  IRasterIO( GDALRWFlag eRWFlag,
@@ -189,11 +196,15 @@ class CPL_DLL VRTDataset : public GDALDataset
     virtual CPLXMLNode *SerializeToXML( const char *pszVRTPath);
     virtual CPLErr      XMLInit( CPLXMLNode *, const char * );
 
+    virtual CPLErr IBuildOverviews( const char *, int, int *,
+                                    int, int *, GDALProgressFunc, void * );
+
     /* Used by PDF driver for example */
     GDALDataset*        GetSingleSimpleSource();
-    
+    void                BuildVirtualOverviews();
+
     void                UnsetPreservedRelativeFilenames();
- 
+
     static int          Identify( GDALOpenInfo * );
     static GDALDataset *Open( GDALOpenInfo * );
     static GDALDataset *OpenXML( const char *, const char * = NULL, GDALAccess eAccess = GA_ReadOnly );
@@ -212,14 +223,14 @@ class VRTWarpedRasterBand;
 
 class CPL_DLL VRTWarpedDataset : public VRTDataset
 {
-    int               nBlockXSize;
-    int               nBlockYSize;
-    GDALWarpOperation *poWarper;
-
-    int               nOverviewCount;
-    VRTWarpedDataset **papoOverviews;
-    int               nSrcOvrLevel;
-    
+    int               m_nBlockXSize;
+    int               m_nBlockYSize;
+    GDALWarpOperation *m_poWarper;
+
+    int               m_nOverviewCount;
+    VRTWarpedDataset **m_papoOverviews;
+    int               m_nSrcOvrLevel;
+
     void              CreateImplicitOverviews();
 
     friend class VRTWarpedRasterBand;
@@ -229,30 +240,103 @@ class CPL_DLL VRTWarpedDataset : public VRTDataset
 
 public:
                       VRTWarpedDataset( int nXSize, int nYSize );
-                     ~VRTWarpedDataset();
+    virtual ~VRTWarpedDataset();
 
     CPLErr            Initialize( /* GDALWarpOptions */ void * );
 
     virtual CPLErr IBuildOverviews( const char *, int, int *,
                                     int, int *, GDALProgressFunc, void * );
-    
+
     virtual CPLErr SetMetadataItem( const char *pszName, const char *pszValue,
                                     const char *pszDomain = "" );
 
     virtual CPLXMLNode *SerializeToXML( const char *pszVRTPath );
     virtual CPLErr    XMLInit( CPLXMLNode *, const char * );
 
-    virtual CPLErr AddBand( GDALDataType eType, 
+    virtual CPLErr AddBand( GDALDataType eType,
                             char **papszOptions=NULL );
-                            
+
     virtual char      **GetFileList();
-    
+
     CPLErr            ProcessBlock( int iBlockX, int iBlockY );
 
     void              GetBlockSize( int *, int * );
 };
 
 /************************************************************************/
+/*                        VRTPansharpenedDataset                        */
+/************************************************************************/
+
+class GDALPansharpenOperation;
+
+typedef enum
+{
+    GTAdjust_Union,
+    GTAdjust_Intersection,
+    GTAdjust_None,
+    GTAdjust_NoneWithoutWarning
+} GTAdjustment;
+
+class VRTPansharpenedDataset : public VRTDataset
+{
+    friend class      VRTPansharpenedRasterBand;
+
+    int               m_nBlockXSize;
+    int               m_nBlockYSize;
+    GDALPansharpenOperation* m_poPansharpener;
+    VRTPansharpenedDataset* m_poMainDataset;
+    std::vector<VRTPansharpenedDataset*> m_apoOverviewDatasets;
+    std::map<CPLString,CPLString> m_oMapToRelativeFilenames; // map from absolute to relative
+
+    int               m_bLoadingOtherBands;
+
+    GByte            *m_pabyLastBufferBandRasterIO;
+    int               m_nLastBandRasterIOXOff;
+    int               m_nLastBandRasterIOYOff;
+    int               m_nLastBandRasterIOXSize;
+    int               m_nLastBandRasterIOYSize;
+    GDALDataType      m_eLastBandRasterIODataType;
+
+    GTAdjustment      m_eGTAdjustment;
+    int               m_bNoDataDisabled;
+
+    std::vector<GDALDataset*> m_apoDatasetsToClose;
+
+  protected:
+    virtual int         CloseDependentDatasets();
+
+public:
+                      VRTPansharpenedDataset( int nXSize, int nYSize );
+                     ~VRTPansharpenedDataset();
+
+    virtual CPLErr    XMLInit( CPLXMLNode *, const char * );
+    virtual CPLXMLNode *   SerializeToXML( const char *pszVRTPath );
+
+    CPLErr            XMLInit( CPLXMLNode *psTree, const char *pszVRTPath,
+                                        GDALRasterBandH hPanchroBandIn,
+                                        int nInputSpectralBandsIn,
+                                        GDALRasterBandH* pahInputSpectralBandsIn );
+
+    virtual CPLErr AddBand( GDALDataType eType,
+                            char **papszOptions=NULL );
+
+    virtual char      **GetFileList();
+
+    virtual CPLErr  IRasterIO( GDALRWFlag eRWFlag,
+                               int nXOff, int nYOff, int nXSize, int nYSize,
+                               void * pData, int nBufXSize, int nBufYSize,
+                               GDALDataType eBufType,
+                               int nBandCount, int *panBandMap,
+                               GSpacing nPixelSpace, GSpacing nLineSpace,
+                               GSpacing nBandSpace,
+                               GDALRasterIOExtraArg* psExtraArg);
+
+    void              GetBlockSize( int *, int * );
+
+    GDALPansharpenOperation* GetPansharpener() { return m_poPansharpener; }
+};
+
+/************************************************************************/
 /*                            VRTRasterBand                             */
 /*                                                                      */
 /*      Provides support for all the various kinds of metadata but      */
@@ -262,29 +346,29 @@ public:
 class CPL_DLL VRTRasterBand : public GDALRasterBand
 {
   protected:
-    int            bIsMaskBand;
+    int            m_bIsMaskBand;
+
+    int            m_bNoDataValueSet;
+    int            m_bHideNoDataValue; // If set to true, will not report the existence of nodata
+    double         m_dfNoDataValue;
 
-    int            bNoDataValueSet;
-    int            bHideNoDataValue; // If set to true, will not report the existance of nodata
-    double         dfNoDataValue;
+    GDALColorTable *m_poColorTable;
 
-    GDALColorTable *poColorTable;
+    GDALColorInterp m_eColorInterp;
 
-    GDALColorInterp eColorInterp;
+    char           *m_pszUnitType;
+    char           **m_papszCategoryNames;
 
-    char           *pszUnitType;
-    char           **papszCategoryNames;
-    
-    double         dfOffset;
-    double         dfScale;
+    double         m_dfOffset;
+    double         m_dfScale;
 
-    CPLXMLNode    *psSavedHistograms;
+    CPLXMLNode    *m_psSavedHistograms;
 
     void           Initialize( int nXSize, int nYSize );
 
-    std::vector<VRTOverviewInfo> apoOverviews;
+    std::vector<VRTOverviewInfo> m_apoOverviews;
 
-    VRTRasterBand *poMaskBand;
+    VRTRasterBand *m_poMaskBand;
 
   public:
 
@@ -296,15 +380,16 @@ class CPL_DLL VRTRasterBand : public GDALRasterBand
 
     virtual CPLErr SetNoDataValue( double );
     virtual double GetNoDataValue( int *pbSuccess = NULL );
+    virtual CPLErr DeleteNoDataValue();
 
-    virtual CPLErr SetColorTable( GDALColorTable * ); 
+    virtual CPLErr SetColorTable( GDALColorTable * );
     virtual GDALColorTable *GetColorTable();
 
     virtual CPLErr SetColorInterpretation( GDALColorInterp );
     virtual GDALColorInterp GetColorInterpretation();
 
     virtual const char *GetUnitType();
-    CPLErr SetUnitType( const char * ); 
+    CPLErr SetUnitType( const char * );
 
     virtual char **GetCategoryNames();
     virtual CPLErr SetCategoryNames( char ** );
@@ -320,7 +405,7 @@ class CPL_DLL VRTRasterBand : public GDALRasterBand
 
     virtual int GetOverviewCount();
     virtual GDALRasterBand *GetOverview(int);
-    
+
     virtual CPLErr  GetHistogram( double dfMin, double dfMax,
                           int nBuckets, GUIntBig * panHistogram,
                           int bIncludeOutOfRange, int bApproxOK,
@@ -335,17 +420,17 @@ class CPL_DLL VRTRasterBand : public GDALRasterBand
                                         int nBuckets, GUIntBig *panHistogram );
 
     CPLErr         CopyCommonInfoFrom( GDALRasterBand * );
-    
+
     virtual void   GetFileList(char*** ppapszFileList, int *pnSize,
                                int *pnMaxSize, CPLHashSet* hSetFiles);
-    
+
     virtual void   SetDescription( const char * );
 
     virtual GDALRasterBand *GetMaskBand();
     virtual int             GetMaskFlags();
 
     virtual CPLErr          CreateMaskBand( int nFlags );
-    
+
     void SetMaskBand(VRTRasterBand* poMaskBand);
 
     void SetIsMaskBand();
@@ -355,6 +440,7 @@ class CPL_DLL VRTRasterBand : public GDALRasterBand
     virtual int         CloseDependentDatasets();
 
     virtual int         IsSourcedRasterBand() { return FALSE; }
+    virtual int         IsPansharpenRasterBand() { return FALSE; }
 };
 
 /************************************************************************/
@@ -366,9 +452,9 @@ class VRTSimpleSource;
 class CPL_DLL VRTSourcedRasterBand : public VRTRasterBand
 {
   private:
-    int            nRecursionCounter;
-    CPLString      osLastLocationInfo;
-    char         **papszSourceList;
+    int            m_nRecursionCounter;
+    CPLString      m_osLastLocationInfo;
+    char         **m_papszSourceList;
 
     void           Initialize( int nXSize, int nYSize );
 
@@ -380,10 +466,10 @@ class CPL_DLL VRTSourcedRasterBand : public VRTRasterBand
     int            bEqualAreas;
 
                    VRTSourcedRasterBand( GDALDataset *poDS, int nBand );
-                   VRTSourcedRasterBand( GDALDataType eType, 
+                   VRTSourcedRasterBand( GDALDataType eType,
                                          int nXSize, int nYSize );
-                   VRTSourcedRasterBand( GDALDataset *poDS, int nBand, 
-                                         GDALDataType eType, 
+                   VRTSourcedRasterBand( GDALDataset *poDS, int nBand,
+                                         GDALDataType eType,
                                          int nXSize, int nYSize );
     virtual        ~VRTSourcedRasterBand();
 
@@ -408,8 +494,8 @@ class CPL_DLL VRTSourcedRasterBand : public VRTRasterBand
     virtual double GetMinimum( int *pbSuccess = NULL );
     virtual double GetMaximum(int *pbSuccess = NULL );
     virtual CPLErr ComputeRasterMinMax( int bApproxOK, double* adfMinMax );
-    virtual CPLErr ComputeStatistics( int bApproxOK, 
-                                      double *pdfMin, double *pdfMax, 
+    virtual CPLErr ComputeStatistics( int bApproxOK,
+                                      double *pdfMin, double *pdfMax,
                                       double *pdfMean, double *pdfStdDev,
                                       GDALProgressFunc pfnProgress, void *pProgressData );
     virtual CPLErr  GetHistogram( double dfMin, double dfMax,
@@ -418,28 +504,28 @@ class CPL_DLL VRTSourcedRasterBand : public VRTRasterBand
                                   GDALProgressFunc pfnProgress, void *pProgressData );
 
     CPLErr         AddSource( VRTSource * );
-    CPLErr         AddSimpleSource( GDALRasterBand *poSrcBand, 
-                                    int nSrcXOff=-1, int nSrcYOff=-1, 
-                                    int nSrcXSize=-1, int nSrcYSize=-1, 
-                                    int nDstXOff=-1, int nDstYOff=-1, 
-                                    int nDstXSize=-1, int nDstYSize=-1,
+    CPLErr         AddSimpleSource( GDALRasterBand *poSrcBand,
+                                    double dfSrcXOff=-1, double dfSrcYOff=-1,
+                                    double dfSrcXSize=-1, double dfSrcYSize=-1,
+                                    double dfDstXOff=-1, double dfDstYOff=-1,
+                                    double dfDstXSize=-1, double dfDstYSize=-1,
                                     const char *pszResampling = "near",
                                     double dfNoDataValue = VRT_NODATA_UNSET);
-    CPLErr         AddComplexSource( GDALRasterBand *poSrcBand, 
-                                     int nSrcXOff=-1, int nSrcYOff=-1, 
-                                     int nSrcXSize=-1, int nSrcYSize=-1, 
-                                     int nDstXOff=-1, int nDstYOff=-1, 
-                                     int nDstXSize=-1, int nDstYSize=-1,
-                                     double dfScaleOff=0.0, 
+    CPLErr         AddComplexSource( GDALRasterBand *poSrcBand,
+                                     double dfSrcXOff=-1, double dfSrcYOff=-1,
+                                     double dfSrcXSize=-1, double dfSrcYSize=-1,
+                                     double dfDstXOff=-1, double dfDstYOff=-1,
+                                     double dfDstXSize=-1, double dfDstYSize=-1,
+                                     double dfScaleOff=0.0,
                                      double dfScaleRatio=1.0,
                                      double dfNoDataValue = VRT_NODATA_UNSET,
                                      int nColorTableComponent = 0);
 
     CPLErr         AddMaskBandSource( GDALRasterBand *poSrcBand,
-                                      int nSrcXOff=-1, int nSrcYOff=-1,
-                                      int nSrcXSize=-1, int nSrcYSize=-1,
-                                      int nDstXOff=-1, int nDstYOff=-1,
-                                      int nDstXSize=-1, int nDstYSize=-1 );
+                                      double dfSrcXOff=-1, double dfSrcYOff=-1,
+                                      double dfSrcXSize=-1, double dfSrcYSize=-1,
+                                      double dfDstXOff=-1, double dfDstYOff=-1,
+                                      double dfDstXSize=-1, double dfDstYSize=-1 );
 
     CPLErr         AddFuncSource( VRTImageReadFunc pfnReadFunc, void *hCBData,
                                   double dfNoDataValue = VRT_NODATA_UNSET );
@@ -447,13 +533,13 @@ class CPL_DLL VRTSourcedRasterBand : public VRTRasterBand
     void           ConfigureSource(VRTSimpleSource *poSimpleSource,
                                            GDALRasterBand *poSrcBand,
                                            int bAddAsMaskBand,
-                                           int nSrcXOff, int nSrcYOff,
-                                           int nSrcXSize, int nSrcYSize,
-                                           int nDstXOff, int nDstYOff,
-                                           int nDstXSize, int nDstYSize);
+                                           double dfSrcXOff, double dfSrcYOff,
+                                           double dfSrcXSize, double dfSrcYSize,
+                                           double dfDstXOff, double dfDstYOff,
+                                           double dfDstXSize, double dfDstYSize);
 
     virtual CPLErr IReadBlock( int, int, void * );
-    
+
     virtual void   GetFileList(char*** ppapszFileList, int *pnSize,
                                int *pnMaxSize, CPLHashSet* hSetFiles);
 
@@ -482,6 +568,39 @@ class CPL_DLL VRTWarpedRasterBand : public VRTRasterBand
     virtual int GetOverviewCount();
     virtual GDALRasterBand *GetOverview(int);
 };
+/************************************************************************/
+/*                        VRTPansharpenedRasterBand                     */
+/************************************************************************/
+
+class VRTPansharpenedRasterBand : public VRTRasterBand
+{
+    int               m_nIndexAsPansharpenedBand;
+
+  public:
+                   VRTPansharpenedRasterBand( GDALDataset *poDS, int nBand,
+                                              GDALDataType eDataType = GDT_Unknown );
+    virtual        ~VRTPansharpenedRasterBand();
+
+    virtual CPLErr         XMLInit( CPLXMLNode *, const char * );
+    virtual CPLXMLNode *   SerializeToXML( const char *pszVRTPath );
+
+    virtual CPLErr IReadBlock( int, int, void * );
+
+    virtual CPLErr  IRasterIO( GDALRWFlag eRWFlag,
+                               int nXOff, int nYOff, int nXSize, int nYSize,
+                               void * pData, int nBufXSize, int nBufYSize,
+                               GDALDataType eBufType,
+                               GSpacing nPixelSpace, GSpacing nLineSpace,
+                               GDALRasterIOExtraArg* psExtraArg);
+
+    virtual int GetOverviewCount();
+    virtual GDALRasterBand *GetOverview(int);
+
+    virtual int         IsPansharpenRasterBand() { return TRUE; }
+
+    void                SetIndexAsPansharpenedBand(int nIdx) { m_nIndexAsPansharpenedBand = nIdx; }
+    int                 GetIndexAsPansharpenedBand() const { return m_nIndexAsPansharpenedBand; }
+};
 
 /************************************************************************/
 /*                         VRTDerivedRasterBand                         */
@@ -495,7 +614,7 @@ class CPL_DLL VRTDerivedRasterBand : public VRTSourcedRasterBand
     GDALDataType eSourceTransferType;
 
     VRTDerivedRasterBand(GDALDataset *poDS, int nBand);
-    VRTDerivedRasterBand(GDALDataset *poDS, int nBand, 
+    VRTDerivedRasterBand(GDALDataset *poDS, int nBand,
                          GDALDataType eType, int nXSize, int nYSize);
     virtual        ~VRTDerivedRasterBand();
 
@@ -524,10 +643,10 @@ class RawRasterBand;
 
 class CPL_DLL VRTRawRasterBand : public VRTRasterBand
 {
-    RawRasterBand  *poRawRaster;
+    RawRasterBand  *m_poRawRaster;
 
-    char           *pszSourceFilename;
-    int            bRelativeToVRT;
+    char           *m_pszSourceFilename;
+    int            m_bRelativeToVRT;
 
   public:
                    VRTRawRasterBand( GDALDataset *poDS, int nBand,
@@ -545,11 +664,11 @@ class CPL_DLL VRTRawRasterBand : public VRTRasterBand
     virtual CPLErr IReadBlock( int, int, void * );
     virtual CPLErr IWriteBlock( int, int, void * );
 
-    CPLErr         SetRawLink( const char *pszFilename, 
+    CPLErr         SetRawLink( const char *pszFilename,
                                const char *pszVRTPath,
-                               int bRelativeToVRT, 
-                               vsi_l_offset nImageOffset, 
-                               int nPixelOffset, int nLineOffset, 
+                               int bRelativeToVRT,
+                               vsi_l_offset nImageOffset,
+                               int nPixelOffset, int nLineOffset,
                                const char *pszByteOrder );
 
     void           ClearRawLink();
@@ -564,7 +683,7 @@ class CPL_DLL VRTRawRasterBand : public VRTRasterBand
 
 class VRTDriver : public GDALDriver
 {
-    void        *pDeserializerData;
+    void        *m_pDeserializerData;
 
   public:
                  VRTDriver();
@@ -578,7 +697,7 @@ class VRTDriver : public GDALDriver
                                      const char * pszDomain = "" );
 
     VRTSource   *ParseSource( CPLXMLNode *psSrc, const char *pszVRTPath );
-    void         AddSourceParser( const char *pszElementName, 
+    void         AddSourceParser( const char *pszElementName,
                                   VRTSourceParser pfnParser );
 };
 
@@ -589,31 +708,37 @@ class VRTDriver : public GDALDriver
 class CPL_DLL VRTSimpleSource : public VRTSource
 {
 protected:
-    GDALRasterBand      *poRasterBand;
+    GDALRasterBand      *m_poRasterBand;
 
     /* when poRasterBand is a mask band, poMaskBandMainBand is the band */
     /* from which the mask band is taken */
-    GDALRasterBand      *poMaskBandMainBand; 
+    GDALRasterBand      *m_poMaskBandMainBand;
+
+    double              m_dfSrcXOff;
+    double              m_dfSrcYOff;
+    double              m_dfSrcXSize;
+    double              m_dfSrcYSize;
 
-    int                 nSrcXOff;
-    int                 nSrcYOff;
-    int                 nSrcXSize;
-    int                 nSrcYSize;
+    double              m_dfDstXOff;
+    double              m_dfDstYOff;
+    double              m_dfDstXSize;
+    double              m_dfDstYSize;
 
-    int                 nDstXOff;
-    int                 nDstYOff;
-    int                 nDstXSize;
-    int                 nDstYSize;
+    int                 m_bNoDataSet;
+    double              m_dfNoDataValue;
+    CPLString           m_osResampling;
 
-    int                 bNoDataSet;
-    double              dfNoDataValue;
-    CPLString           osResampling;
-    
-    int                 bRelativeToVRTOri;
-    CPLString           osSourceFileNameOri;
+    int                 m_nMaxValue;
+
+    int                 m_bRelativeToVRTOri;
+    CPLString           m_osSourceFileNameOri;
+
+    int                 NeedMaxValAdjustment() const;
 
 public:
             VRTSimpleSource();
+            VRTSimpleSource(const VRTSimpleSource* poSrcSource,
+                                 double dfXDstRatio, double dfYDstRatio);
     virtual ~VRTSimpleSource();
 
     virtual CPLErr  XMLInit( CPLXMLNode *psTree, const char * );
@@ -621,21 +746,21 @@ public:
 
     void           SetSrcBand( GDALRasterBand * );
     void           SetSrcMaskBand( GDALRasterBand * );
-    void           SetSrcWindow( int, int, int, int );
-    void           SetDstWindow( int, int, int, int );
+    void           SetSrcWindow( double, double, double, double );
+    void           SetDstWindow( double, double, double, double );
     void           SetNoDataValue( double dfNoDataValue );
-    const CPLString& GetResampling() const { return osResampling; }
+    const CPLString& GetResampling() const { return m_osResampling; }
     void           SetResampling( const char* pszResampling );
 
-    int            GetSrcDstWindow( int, int, int, int, int, int, 
+    int            GetSrcDstWindow( int, int, int, int, int, int,
                                     double *pdfReqXOff, double *pdfReqYOff,
                                     double *pdfReqXSize, double *pdfReqYSize,
                                     int *, int *, int *, int *,
                                     int *, int *, int *, int * );
 
-    virtual CPLErr  RasterIO( int nXOff, int nYOff, int nXSize, int nYSize, 
-                              void *pData, int nBufXSize, int nBufYSize, 
-                              GDALDataType eBufType, 
+    virtual CPLErr  RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
+                              void *pData, int nBufXSize, int nBufYSize,
+                              GDALDataType eBufType,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
                               GDALRasterIOExtraArg* psExtraArg );
 
@@ -643,8 +768,8 @@ public:
     virtual double GetMaximum( int nXSize, int nYSize, int *pbSuccess );
     virtual CPLErr ComputeRasterMinMax( int nXSize, int nYSize, int bApproxOK, double* adfMinMax );
     virtual CPLErr ComputeStatistics( int nXSize, int nYSize,
-                                      int bApproxOK, 
-                                      double *pdfMin, double *pdfMax, 
+                                      int bApproxOK,
+                                      double *pdfMin, double *pdfMax,
                                       double *pdfMean, double *pdfStdDev,
                                       GDALProgressFunc pfnProgress, void *pProgressData );
     virtual CPLErr  GetHistogram( int nXSize, int nYSize,
@@ -657,7 +782,7 @@ public:
                               double &dfXOut, double &dfYOut );
     void            SrcToDst( double dfX, double dfY,
                               double &dfXOut, double &dfYOut );
-    
+
     virtual void   GetFileList(char*** ppapszFileList, int *pnSize,
                                int *pnMaxSize, CPLHashSet* hSetFiles);
 
@@ -676,6 +801,8 @@ public:
                                GDALRasterIOExtraArg* psExtraArg);
 
     void             UnsetPreservedRelativeFilenames();
+
+    void                SetMaxValue(int nVal) { m_nMaxValue = nVal; }
 };
 
 /************************************************************************/
@@ -686,9 +813,9 @@ class VRTAveragedSource : public VRTSimpleSource
 {
 public:
                     VRTAveragedSource();
-    virtual CPLErr  RasterIO( int nXOff, int nYOff, int nXSize, int nYSize, 
-                              void *pData, int nBufXSize, int nBufYSize, 
-                              GDALDataType eBufType, 
+    virtual CPLErr  RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
+                              void *pData, int nBufXSize, int nBufYSize,
+                              GDALDataType eBufType,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
                               GDALRasterIOExtraArg* psExtraArg );
 
@@ -696,8 +823,8 @@ public:
     virtual double GetMaximum( int nXSize, int nYSize, int *pbSuccess );
     virtual CPLErr ComputeRasterMinMax( int nXSize, int nYSize, int bApproxOK, double* adfMinMax );
     virtual CPLErr ComputeStatistics( int nXSize, int nYSize,
-                                      int bApproxOK, 
-                                      double *pdfMin, double *pdfMax, 
+                                      int bApproxOK,
+                                      double *pdfMin, double *pdfMax,
                                       double *pdfMean, double *pdfStdDev,
                                       GDALProgressFunc pfnProgress, void *pProgressData );
     virtual CPLErr  GetHistogram( int nXSize, int nYSize,
@@ -724,19 +851,19 @@ typedef enum
 class CPL_DLL VRTComplexSource : public VRTSimpleSource
 {
 protected:
-    VRTComplexSourceScaling eScalingType;
-    double         dfScaleOff; /* for linear scaling */
-    double         dfScaleRatio; /* for linear scaling */
+    VRTComplexSourceScaling m_eScalingType;
+    double         m_dfScaleOff; /* for linear scaling */
+    double         m_dfScaleRatio; /* for linear scaling */
 
     /* For non-linear scaling with a power function. */
-    int            bSrcMinMaxDefined;
-    double         dfSrcMin;
-    double         dfSrcMax;
-    double         dfDstMin;
-    double         dfDstMax;
-    double         dfExponent;
+    int            m_bSrcMinMaxDefined;
+    double         m_dfSrcMin;
+    double         m_dfSrcMax;
+    double         m_dfDstMin;
+    double         m_dfDstMax;
+    double         m_dfExponent;
 
-    int            nColorTableComponent;
+    int            m_nColorTableComponent;
 
     CPLErr          RasterIOInternal( int nReqXOff, int nReqYOff,
                                       int nReqXSize, int nReqYSize,
@@ -747,11 +874,13 @@ protected:
 
 public:
                    VRTComplexSource();
+                   VRTComplexSource(const VRTComplexSource* poSrcSource,
+                                    double dfXDstRatio, double dfYDstRatio);
     virtual        ~VRTComplexSource();
 
-    virtual CPLErr RasterIO( int nXOff, int nYOff, int nXSize, int nYSize, 
-                             void *pData, int nBufXSize, int nBufYSize, 
-                             GDALDataType eBufType, 
+    virtual CPLErr RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
+                             void *pData, int nBufXSize, int nBufYSize,
+                             GDALDataType eBufType,
                              GSpacing nPixelSpace, GSpacing nLineSpace,
                              GDALRasterIOExtraArg* psExtraArg );
 
@@ -759,8 +888,8 @@ public:
     virtual double GetMaximum( int nXSize, int nYSize, int *pbSuccess );
     virtual CPLErr ComputeRasterMinMax( int nXSize, int nYSize, int bApproxOK, double* adfMinMax );
     virtual CPLErr ComputeStatistics( int nXSize, int nYSize,
-                                      int bApproxOK, 
-                                      double *pdfMin, double *pdfMax, 
+                                      int bApproxOK,
+                                      double *pdfMin, double *pdfMax,
                                       double *pdfMean, double *pdfStdDev,
                                       GDALProgressFunc pfnProgress, void *pProgressData );
     virtual CPLErr  GetHistogram( int nXSize, int nYSize,
@@ -774,7 +903,7 @@ public:
     virtual const char* GetType() { return "ComplexSource"; }
 
     double  LookupValue( double dfInput );
-    
+
     void    SetLinearScaling(double dfOffset, double dfScale);
     void    SetPowerScaling(double dfExponent,
                             double dfSrcMin,
@@ -783,9 +912,9 @@ public:
                             double dfDstMax);
     void    SetColorTableComponent(int nComponent);
 
-    double         *padfLUTInputs;
-    double         *padfLUTOutputs;
-    int            nLUTItemCount;
+    double         *m_padfLUTInputs;
+    double         *m_padfLUTOutputs;
+    int            m_nLUTItemCount;
 
 };
 
@@ -799,10 +928,10 @@ private:
     int          IsTypeSupported( GDALDataType eType );
 
 protected:
-    int          nSupportedTypesCount;
-    GDALDataType aeSupportedTypes[20];
+    int          m_nSupportedTypesCount;
+    GDALDataType m_aeSupportedTypes[20];
 
-    int          nExtraEdgePixels;
+    int          m_nExtraEdgePixels;
 
 public:
             VRTFilteredSource();
@@ -811,12 +940,12 @@ public:
     void    SetExtraEdgePixels( int );
     void    SetFilteringDataTypesSupported( int, GDALDataType * );
 
-    virtual CPLErr  FilterData( int nXSize, int nYSize, GDALDataType eType, 
+    virtual CPLErr  FilterData( int nXSize, int nYSize, GDALDataType eType,
                                 GByte *pabySrcData, GByte *pabyDstData ) = 0;
 
-    virtual CPLErr  RasterIO( int nXOff, int nYOff, int nXSize, int nYSize, 
-                              void *pData, int nBufXSize, int nBufYSize, 
-                              GDALDataType eBufType, 
+    virtual CPLErr  RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
+                              void *pData, int nBufXSize, int nBufYSize,
+                              GDALDataType eBufType,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
                               GDALRasterIOExtraArg* psExtraArg );
 };
@@ -828,11 +957,11 @@ public:
 class VRTKernelFilteredSource : public VRTFilteredSource
 {
 protected:
-    int     nKernelSize;
+    int     m_nKernelSize;
 
-    double  *padfKernelCoefs;
+    double  *m_padfKernelCoefs;
 
-    int     bNormalized;
+    int     m_bNormalized;
 
 public:
             VRTKernelFilteredSource();
@@ -841,7 +970,7 @@ public:
     virtual CPLErr  XMLInit( CPLXMLNode *psTree, const char * );
     virtual CPLXMLNode *SerializeToXML( const char *pszVRTPath );
 
-    virtual CPLErr  FilterData( int nXSize, int nYSize, GDALDataType eType, 
+    virtual CPLErr  FilterData( int nXSize, int nYSize, GDALDataType eType,
                                 GByte *pabySrcData, GByte *pabyDstData );
 
     CPLErr          SetKernel( int nKernelSize, double *padfCoefs );
@@ -855,7 +984,7 @@ public:
 class VRTAverageFilteredSource : public VRTKernelFilteredSource
 {
 public:
-            VRTAverageFilteredSource( int nKernelSize );
+            explicit VRTAverageFilteredSource( int nKernelSize );
     virtual ~VRTAverageFilteredSource();
 
     virtual CPLErr  XMLInit( CPLXMLNode *psTree, const char * );
@@ -874,9 +1003,9 @@ public:
     virtual CPLErr  XMLInit( CPLXMLNode *, const char *) { return CE_Failure; }
     virtual CPLXMLNode *SerializeToXML( const char *pszVRTPath );
 
-    virtual CPLErr  RasterIO( int nXOff, int nYOff, int nXSize, int nYSize, 
-                              void *pData, int nBufXSize, int nBufYSize, 
-                              GDALDataType eBufType, 
+    virtual CPLErr  RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
+                              void *pData, int nBufXSize, int nBufYSize,
+                              GDALDataType eBufType,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
                               GDALRasterIOExtraArg* psExtraArg );
 
@@ -884,8 +1013,8 @@ public:
     virtual double GetMaximum( int nXSize, int nYSize, int *pbSuccess );
     virtual CPLErr ComputeRasterMinMax( int nXSize, int nYSize, int bApproxOK, double* adfMinMax );
     virtual CPLErr ComputeStatistics( int nXSize, int nYSize,
-                                      int bApproxOK, 
-                                      double *pdfMin, double *pdfMax, 
+                                      int bApproxOK,
+                                      double *pdfMin, double *pdfMax,
                                       double *pdfMean, double *pdfStdDev,
                                       GDALProgressFunc pfnProgress, void *pProgressData );
     virtual CPLErr  GetHistogram( int nXSize, int nYSize,
@@ -897,7 +1026,7 @@ public:
     VRTImageReadFunc    pfnReadFunc;
     void               *pCBData;
     GDALDataType        eType;
-    
+
     float               fNoDataValue;
 };
 
diff --git a/frmts/vrt/vrtderivedrasterband.cpp b/frmts/vrt/vrtderivedrasterband.cpp
index 2459b2b..d42f2eb 100644
--- a/frmts/vrt/vrtderivedrasterband.cpp
+++ b/frmts/vrt/vrtderivedrasterband.cpp
@@ -45,27 +45,23 @@ static std::map<CPLString, GDALDerivedPixelFunc> osMapPixelFunction;
 /*                        VRTDerivedRasterBand()                        */
 /************************************************************************/
 
-VRTDerivedRasterBand::VRTDerivedRasterBand(GDALDataset *poDS, int nBand)
-    : VRTSourcedRasterBand( poDS, nBand )
-
-{
-    this->pszFuncName = NULL;
-    this->eSourceTransferType = GDT_Unknown;
-}
+VRTDerivedRasterBand::VRTDerivedRasterBand(GDALDataset *poDSIn, int nBandIn) :
+    VRTSourcedRasterBand( poDSIn, nBandIn ),
+    pszFuncName(NULL),
+    eSourceTransferType(GDT_Unknown)
+{}
 
 /************************************************************************/
 /*                        VRTDerivedRasterBand()                        */
 /************************************************************************/
 
-VRTDerivedRasterBand::VRTDerivedRasterBand(GDALDataset *poDS, int nBand,
-					   GDALDataType eType, 
-					   int nXSize, int nYSize)
-    : VRTSourcedRasterBand(poDS, nBand, eType, nXSize, nYSize)
-
-{
-    this->pszFuncName = NULL;
-    this->eSourceTransferType = GDT_Unknown;
-}
+VRTDerivedRasterBand::VRTDerivedRasterBand(GDALDataset *poDSIn, int nBandIn,
+					   GDALDataType eType,
+					   int nXSize, int nYSize) :
+    VRTSourcedRasterBand(poDSIn, nBandIn, eType, nXSize, nYSize),
+    pszFuncName(NULL),
+    eSourceTransferType(GDT_Unknown)
+{}
 
 /************************************************************************/
 /*                       ~VRTDerivedRasterBand()                        */
@@ -74,10 +70,7 @@ VRTDerivedRasterBand::VRTDerivedRasterBand(GDALDataset *poDS, int nBand,
 VRTDerivedRasterBand::~VRTDerivedRasterBand()
 
 {
-    if (this->pszFuncName != NULL) {
-        CPLFree(this->pszFuncName);
-        this->pszFuncName = NULL;
-    }
+    CPLFree( pszFuncName );
 }
 
 /************************************************************************/
@@ -89,7 +82,7 @@ VRTDerivedRasterBand::~VRTDerivedRasterBand()
  * functions for derived bands.  Pixel functions must be registered
  * in this way before a derived band tries to access data.
  *
- * Derived bands are stored with only the name of the pixel function 
+ * Derived bands are stored with only the name of the pixel function
  * that it will apply, and if a pixel function matching the name is not
  * found the IRasterIO() call will do nothing.
  *
@@ -114,6 +107,7 @@ CPLErr CPL_STDCALL GDALAddDerivedBandPixelFunc
 
     return CE_None;
 }
+
 /**
  * This adds a pixel function to the global list of available pixel
  * functions for derived bands.
@@ -175,9 +169,9 @@ GDALDerivedPixelFunc VRTDerivedRasterBand::GetPixelFunction
  * @param pszFuncName Name of pixel function to be applied to this derived
  * band.
  */
-void VRTDerivedRasterBand::SetPixelFunctionName(const char *pszFuncName)
+void VRTDerivedRasterBand::SetPixelFunctionName(const char *pszFuncNameIn)
 {
-    this->pszFuncName = CPLStrdup( pszFuncName );
+    pszFuncName = CPLStrdup( pszFuncNameIn );
 }
 
 /************************************************************************/
@@ -195,9 +189,9 @@ void VRTDerivedRasterBand::SetPixelFunctionName(const char *pszFuncName)
  * @param eDataType Data type to use to obtain pixel information from
  * the sources to be passed to the derived band pixel function.
  */
-void VRTDerivedRasterBand::SetSourceTransferType(GDALDataType eDataType)
+void VRTDerivedRasterBand::SetSourceTransferType(GDALDataType eDataTypeIn)
 {
-    this->eSourceTransferType = eDataType;
+    this->eSourceTransferType = eDataTypeIn;
 }
 
 /************************************************************************/
@@ -258,55 +252,48 @@ void VRTDerivedRasterBand::SetSourceTransferType(GDALDataType eDataType)
  * @return CE_Failure if the access fails, otherwise CE_None.
  */
 CPLErr VRTDerivedRasterBand::IRasterIO(GDALRWFlag eRWFlag,
-				       int nXOff, int nYOff, int nXSize, 
+				       int nXOff, int nYOff, int nXSize,
 				       int nYSize, void * pData, int nBufXSize,
 				       int nBufYSize, GDALDataType eBufType,
 				       GSpacing nPixelSpace,
-                       GSpacing nLineSpace,
-                       GDALRasterIOExtraArg* psExtraArg )
+                                       GSpacing nLineSpace,
+                                       GDALRasterIOExtraArg* psExtraArg )
 {
-    GDALDerivedPixelFunc pfnPixelFunc;
-    void **pBuffers;
-    CPLErr eErr = CE_None;
-    int iSource, ii, typesize, sourcesize;
-    GDALDataType eSrcType;
-
     if( eRWFlag == GF_Write )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Writing through VRTSourcedRasterBand is not supported." );
         return CE_Failure;
     }
 
-    typesize = GDALGetDataTypeSize(eBufType) / 8;
+    int typesize = GDALGetDataTypeSizeBytes(eBufType);
     if (GDALGetDataTypeSize(eBufType) % 8 > 0) typesize++;
-    eSrcType = this->eSourceTransferType;
+    GDALDataType eSrcType = eSourceTransferType;
     if ((eSrcType == GDT_Unknown) || (eSrcType >= GDT_TypeCount)) {
 	eSrcType = eBufType;
     }
-    sourcesize = GDALGetDataTypeSize(eSrcType) / 8;
+    const int sourcesize = GDALGetDataTypeSizeBytes(eSrcType);
 
 /* -------------------------------------------------------------------- */
 /*      Initialize the buffer to some background value. Use the         */
 /*      nodata value if available.                                      */
 /* -------------------------------------------------------------------- */
     if ( nPixelSpace == typesize &&
-         (!bNoDataValueSet || dfNoDataValue == 0) ) {
-        memset( pData, 0, nBufXSize * nBufYSize * nPixelSpace );
+         (!m_bNoDataValueSet || m_dfNoDataValue == 0) ) {
+        memset( pData, 0, static_cast<size_t>(nBufXSize * nBufYSize * nPixelSpace) );
     }
-    else if ( !bEqualAreas || bNoDataValueSet )
+    else if ( !bEqualAreas || m_bNoDataValueSet )
     {
         double dfWriteValue = 0.0;
-        int    iLine;
+        if( m_bNoDataValueSet )
+            dfWriteValue = m_dfNoDataValue;
 
-        if( bNoDataValueSet )
-            dfWriteValue = dfNoDataValue;
-
-        for( iLine = 0; iLine < nBufYSize; iLine++ )
+        for( int iLine = 0; iLine < nBufYSize; iLine++ )
         {
-            GDALCopyWords( &dfWriteValue, GDT_Float64, 0, 
-                           ((GByte *)pData) + nLineSpace * iLine, 
-                           eBufType, nPixelSpace, nBufXSize );
+            GDALCopyWords(
+                &dfWriteValue, GDT_Float64, 0,
+                reinterpret_cast<GByte *>( pData ) + nLineSpace * iLine,
+                eBufType, static_cast<int>(nPixelSpace), nBufXSize );
         }
     }
 
@@ -317,17 +304,18 @@ CPLErr VRTDerivedRasterBand::IRasterIO(GDALRWFlag eRWFlag,
     if( (nBufXSize < nXSize || nBufYSize < nYSize)
         && GetOverviewCount() > 0 )
     {
-        if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, 
-                              pData, nBufXSize, nBufYSize, 
+        if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                              pData, nBufXSize, nBufYSize,
                               eBufType, nPixelSpace, nLineSpace, psExtraArg ) == CE_None )
             return CE_None;
     }
 
     /* ---- Get pixel function for band ---- */
-    pfnPixelFunc = VRTDerivedRasterBand::GetPixelFunction(this->pszFuncName);
+    GDALDerivedPixelFunc pfnPixelFunc
+        = VRTDerivedRasterBand::GetPixelFunction(this->pszFuncName);
     if (pfnPixelFunc == NULL) {
-	CPLError( CE_Failure, CPLE_IllegalArg, 
-		  "VRTDerivedRasterBand::IRasterIO:" \
+	CPLError( CE_Failure, CPLE_IllegalArg,
+		  "VRTDerivedRasterBand::IRasterIO:"
 		  "Derived band pixel function '%s' not registered.\n",
 		  this->pszFuncName);
 	return CE_Failure;
@@ -341,19 +329,17 @@ CPLErr VRTDerivedRasterBand::IRasterIO(GDALRWFlag eRWFlag,
        of the allocated blocks. */
 
     /* ---- Get buffers for each source ---- */
-    pBuffers = (void **) CPLMalloc(sizeof(void *) * nSources);
-    for (iSource = 0; iSource < nSources; iSource++) {
-        pBuffers[iSource] = (void *) 
-            VSIMalloc(sourcesize * nBufXSize * nBufYSize);
+    void **pBuffers
+        = reinterpret_cast<void **>( CPLMalloc(sizeof(void *) * nSources) );
+    for( int iSource = 0; iSource < nSources; iSource++ ) {
+        pBuffers[iSource] =
+            VSI_MALLOC_VERBOSE(sourcesize * nBufXSize * nBufYSize);
         if (pBuffers[iSource] == NULL)
         {
-            for (ii = 0; ii < iSource; ii++) {
-                VSIFree(pBuffers[iSource]);
+            for (int i = 0; i < iSource; i++) {
+                VSIFree(pBuffers[i]);
             }
-            CPLError( CE_Failure, CPLE_OutOfMemory,
-                "VRTDerivedRasterBand::IRasterIO:" \
-                "Out of memory allocating " CPL_FRMT_GIB " bytes.\n",
-                (GIntBig)nPixelSpace * nBufXSize * nBufYSize);
+            CPLFree(pBuffers);
             return CE_Failure;
         }
 
@@ -363,14 +349,14 @@ CPLErr VRTDerivedRasterBand::IRasterIO(GDALRWFlag eRWFlag,
         /* don't need any special line-by-line handling when a nonzero  */
         /* nodata value is set.                                         */
         /* ------------------------------------------------------------ */
-        if ( !bNoDataValueSet || dfNoDataValue == 0 )
+        if ( !m_bNoDataValueSet || m_dfNoDataValue == 0 )
         {
             memset( pBuffers[iSource], 0, sourcesize * nBufXSize * nBufYSize );
         }
         else
         {
-            GDALCopyWords( &dfNoDataValue, GDT_Float64, 0,
-                           (GByte *) pBuffers[iSource], eSrcType, sourcesize,
+            GDALCopyWords( &m_dfNoDataValue, GDT_Float64, 0,
+                           reinterpret_cast<GByte *>( pBuffers[iSource] ), eSrcType, sourcesize,
                            nBufXSize * nBufYSize);
         }
     }
@@ -379,23 +365,24 @@ CPLErr VRTDerivedRasterBand::IRasterIO(GDALRWFlag eRWFlag,
     INIT_RASTERIO_EXTRA_ARG(sExtraArg);
 
     /* ---- Load values for sources into packed buffers ---- */
-    for(iSource = 0; iSource < nSources; iSource++) {
-        eErr = ((VRTSource *)papoSources[iSource])->RasterIO
-	    (nXOff, nYOff, nXSize, nYSize, 
-	     pBuffers[iSource], nBufXSize, nBufYSize, 
-	     eSrcType, GDALGetDataTypeSize( eSrcType ) / 8,
-             (GDALGetDataTypeSize( eSrcType ) / 8) * nBufXSize, &sExtraArg);
+    CPLErr eErr = CE_None;
+    for( int iSource = 0; iSource < nSources && eErr == CE_None; iSource++ ) {
+        eErr = reinterpret_cast<VRTSource *>( papoSources[iSource] )->RasterIO(
+	    nXOff, nYOff, nXSize, nYSize,
+            pBuffers[iSource], nBufXSize, nBufYSize,
+            eSrcType, GDALGetDataTypeSizeBytes( eSrcType ),
+            GDALGetDataTypeSizeBytes( eSrcType ) * nBufXSize, &sExtraArg);
     }
 
     /* ---- Apply pixel function ---- */
     if (eErr == CE_None) {
-	eErr = pfnPixelFunc((void **)pBuffers, nSources,
-			    pData, nBufXSize, nBufYSize,
-			    eSrcType, eBufType, nPixelSpace, nLineSpace);
+        eErr = pfnPixelFunc( reinterpret_cast<void **>( pBuffers ), nSources,
+			     pData, nBufXSize, nBufYSize,
+			     eSrcType, eBufType, static_cast<int>(nPixelSpace), static_cast<int>(nLineSpace) );
     }
 
     /* ---- Release buffers ---- */
-    for (iSource = 0; iSource < nSources; iSource++) {
+    for ( int iSource = 0; iSource < nSources; iSource++ ) {
         VSIFree(pBuffers[iSource]);
     }
     CPLFree(pBuffers);
@@ -407,25 +394,21 @@ CPLErr VRTDerivedRasterBand::IRasterIO(GDALRWFlag eRWFlag,
 /*                              XMLInit()                               */
 /************************************************************************/
 
-CPLErr VRTDerivedRasterBand::XMLInit(CPLXMLNode *psTree, 
-				     const char *pszVRTPath)
+CPLErr VRTDerivedRasterBand::XMLInit( CPLXMLNode *psTree,
+				      const char *pszVRTPath )
 
 {
-    CPLErr eErr;
-    const char *pszTypeName;
-
-    eErr = VRTSourcedRasterBand::XMLInit( psTree, pszVRTPath );
+    CPLErr eErr = VRTSourcedRasterBand::XMLInit( psTree, pszVRTPath );
     if( eErr != CE_None )
         return eErr;
 
     /* ---- Read derived pixel function type ---- */
-    this->SetPixelFunctionName
-	(CPLGetXMLValue(psTree, "PixelFunctionType", NULL));
+    SetPixelFunctionName( CPLGetXMLValue( psTree, "PixelFunctionType", NULL ) );
 
     /* ---- Read optional source transfer data type ---- */
-    pszTypeName = CPLGetXMLValue(psTree, "SourceTransferType", NULL);
+    const char *pszTypeName = CPLGetXMLValue(psTree, "SourceTransferType", NULL);
     if (pszTypeName != NULL) {
-	this->eSourceTransferType = GDALGetDataTypeByName(pszTypeName);
+	eSourceTransferType = GDALGetDataTypeByName( pszTypeName );
     }
 
     return CE_None;
@@ -437,24 +420,21 @@ CPLErr VRTDerivedRasterBand::XMLInit(CPLXMLNode *psTree,
 
 CPLXMLNode *VRTDerivedRasterBand::SerializeToXML(const char *pszVRTPath)
 {
-    CPLXMLNode *psTree;
-
-    psTree = VRTSourcedRasterBand::SerializeToXML( pszVRTPath );
+    CPLXMLNode *psTree = VRTSourcedRasterBand::SerializeToXML( pszVRTPath );
 
 /* -------------------------------------------------------------------- */
 /*      Set subclass.                                                   */
 /* -------------------------------------------------------------------- */
-    CPLCreateXMLNode( 
-        CPLCreateXMLNode( psTree, CXT_Attribute, "subClass" ), 
+    CPLCreateXMLNode(
+        CPLCreateXMLNode( psTree, CXT_Attribute, "subClass" ),
         CXT_Text, "VRTDerivedRasterBand" );
 
     /* ---- Encode DerivedBand-specific fields ---- */
     if( pszFuncName != NULL && strlen(pszFuncName) > 0 )
-        CPLSetXMLValue(psTree, "PixelFunctionType", this->pszFuncName);
+        CPLSetXMLValue( psTree, "PixelFunctionType", pszFuncName );
     if( this->eSourceTransferType != GDT_Unknown)
-        CPLSetXMLValue(psTree, "SourceTransferType", 
-		       GDALGetDataTypeName(this->eSourceTransferType));
+        CPLSetXMLValue( psTree, "SourceTransferType",
+		        GDALGetDataTypeName( eSourceTransferType ) );
 
     return psTree;
 }
-
diff --git a/frmts/vrt/vrtdriver.cpp b/frmts/vrt/vrtdriver.cpp
index 38f9523..35cd485 100644
--- a/frmts/vrt/vrtdriver.cpp
+++ b/frmts/vrt/vrtdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtdriver.cpp 29294 2015-06-05 08:52:15Z rouault $
+ * $Id: vrtdriver.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTDriver
@@ -31,9 +31,10 @@
 #include "vrtdataset.h"
 #include "cpl_minixml.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
 #include "gdal_alg_priv.h"
 
-CPL_CVSID("$Id: vrtdriver.cpp 29294 2015-06-05 08:52:15Z rouault $");
+CPL_CVSID("$Id: vrtdriver.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /*                             VRTDriver()                              */
@@ -44,11 +45,12 @@ VRTDriver::VRTDriver()
 {
     papszSourceParsers = NULL;
 #if 0
-    pDeserializerData = GDALRegisterTransformDeserializer("WarpedOverviewTransformer",
-                                                          VRTWarpedOverviewTransform,
-                                                          VRTDeserializeWarpedOverviewTransformer);
+    pDeserializerData = GDALRegisterTransformDeserializer(
+        "WarpedOverviewTransformer",
+        VRTWarpedOverviewTransform,
+        VRTDeserializeWarpedOverviewTransformer );
 #else
-    pDeserializerData = NULL;
+    m_pDeserializerData = NULL;
 #endif
 }
 
@@ -74,9 +76,9 @@ VRTDriver::~VRTDriver()
 
 char **VRTDriver::GetMetadataDomainList()
 {
-    return BuildMetadataDomainList(GDALDriver::GetMetadataDomainList(),
-                                   TRUE,
-                                   "SourceParsers", NULL);
+    return BuildMetadataDomainList( GDALDriver::GetMetadataDomainList(),
+                                    TRUE,
+                                    "SourceParsers", NULL);
 }
 
 /************************************************************************/
@@ -88,8 +90,8 @@ char **VRTDriver::GetMetadata( const char *pszDomain )
 {
     if( pszDomain && EQUAL(pszDomain,"SourceParsers") )
         return papszSourceParsers;
-    else
-        return GDALDriver::GetMetadata( pszDomain );
+
+    return GDALDriver::GetMetadata( pszDomain );
 }
 
 /************************************************************************/
@@ -105,22 +107,25 @@ CPLErr VRTDriver::SetMetadata( char **papszMetadata, const char *pszDomain )
         papszSourceParsers = CSLDuplicate( papszMetadata );
         return CE_None;
     }
-    else
-        return GDALDriver::SetMetadata( papszMetadata, pszDomain );
+
+    return GDALDriver::SetMetadata( papszMetadata, pszDomain );
 }
 
 /************************************************************************/
 /*                          AddSourceParser()                           */
 /************************************************************************/
 
-void VRTDriver::AddSourceParser( const char *pszElementName, 
+void VRTDriver::AddSourceParser( const char *pszElementName,
                                  VRTSourceParser pfnParser )
 
 {
     char szPtrValue[128];
+    int nRet = CPLPrintPointer( szPtrValue,
+                                reinterpret_cast<void*>(pfnParser),
+                                sizeof(szPtrValue) );
+    szPtrValue[nRet] = 0;
 
-    sprintf( szPtrValue, "%p", pfnParser );
-    papszSourceParsers = CSLSetNameValue( papszSourceParsers, 
+    papszSourceParsers = CSLSetNameValue( papszSourceParsers,
                                           pszElementName, szPtrValue );
 }
 
@@ -131,27 +136,27 @@ void VRTDriver::AddSourceParser( const char *pszElementName,
 VRTSource *VRTDriver::ParseSource( CPLXMLNode *psSrc, const char *pszVRTPath )
 
 {
-    const char *pszParserFunc;
 
     if( psSrc == NULL || psSrc->eType != CXT_Element )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Corrupt or empty VRT source XML document." );
         return NULL;
     }
 
-    pszParserFunc = CSLFetchNameValue( papszSourceParsers, psSrc->pszValue );
+    const char *pszParserFunc
+        = CSLFetchNameValue( papszSourceParsers, psSrc->pszValue );
     if( pszParserFunc == NULL )
         return NULL;
 
-    VRTSourceParser pfnParser = NULL;
-
-    sscanf( pszParserFunc, "%p", &pfnParser );
+    VRTSourceParser pfnParser = reinterpret_cast<VRTSourceParser>
+                        (CPLScanPointer(pszParserFunc,
+                                        static_cast<int>(strlen(pszParserFunc))));
 
     if( pfnParser == NULL )
         return NULL;
-    else
-        return pfnParser( psSrc, pszVRTPath );
+
+    return pfnParser( psSrc, pszVRTPath );
 }
 
 /************************************************************************/
@@ -161,16 +166,11 @@ VRTSource *VRTDriver::ParseSource( CPLXMLNode *psSrc, const char *pszVRTPath )
 static GDALDataset *
 VRTCreateCopy( const char * pszFilename,
                GDALDataset *poSrcDS,
-               int bStrict,
-               char ** papszOptions,
-               CPL_UNUSED GDALProgressFunc pfnProgress,
-               CPL_UNUSED void * pProgressData )
+               int /* bStrict */,
+               char ** /* papszOptions */,
+               GDALProgressFunc /* pfnProgress */,
+               void * /* pProgressData */ )
 {
-    VRTDataset *poVRTDS = NULL;
-
-    (void) bStrict;
-    (void) papszOptions;
-
     CPLAssert( NULL != poSrcDS );
 
 /* -------------------------------------------------------------------- */
@@ -186,15 +186,17 @@ VRTCreateCopy( const char * pszFilename,
     /*      Convert tree to a single block of XML text.                     */
     /* -------------------------------------------------------------------- */
         char *pszVRTPath = CPLStrdup(CPLGetPath(pszFilename));
-        ((VRTDataset *) poSrcDS)->UnsetPreservedRelativeFilenames();
-        CPLXMLNode *psDSTree = ((VRTDataset *) poSrcDS)->SerializeToXML( pszVRTPath );
+        reinterpret_cast<VRTDataset *>(
+            poSrcDS )->UnsetPreservedRelativeFilenames();
+        CPLXMLNode *psDSTree = reinterpret_cast<VRTDataset *>(
+            poSrcDS )->SerializeToXML( pszVRTPath );
 
         char *pszXML = CPLSerializeXMLTree( psDSTree );
-        
+
         CPLDestroyXMLNode( psDSTree );
 
         CPLFree( pszVRTPath );
-        
+
     /* -------------------------------------------------------------------- */
     /*      Write to disk.                                                  */
     /* -------------------------------------------------------------------- */
@@ -202,9 +204,7 @@ VRTCreateCopy( const char * pszFilename,
 
         if( 0 != strlen( pszFilename ) )
         {
-            VSILFILE *fpVRT = NULL;
-
-            fpVRT = VSIFOpenL( pszFilename, "wb" );
+            VSILFILE *fpVRT = VSIFOpenL( pszFilename, "wb" );
             if (fpVRT == NULL)
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
@@ -213,16 +213,20 @@ VRTCreateCopy( const char * pszFilename,
                 return NULL;
             }
 
-            VSIFWriteL( pszXML, 1, strlen(pszXML), fpVRT );
-            VSIFCloseL( fpVRT );
+            bool bRet = VSIFWriteL( pszXML, strlen(pszXML), 1, fpVRT ) > 0;
+            if( VSIFCloseL( fpVRT ) != 0 )
+                bRet = false;
 
-            pCopyDS = (GDALDataset *) GDALOpen( pszFilename, GA_Update );
+            if( bRet )
+                pCopyDS = reinterpret_cast<GDALDataset *>(
+                    GDALOpen( pszFilename, GA_Update ) );
         }
         else
         {
             /* No destination file is given, so pass serialized XML directly. */
 
-            pCopyDS = (GDALDataset *) GDALOpen( pszXML, GA_Update );
+            pCopyDS = reinterpret_cast<GDALDataset *>(
+                GDALOpen( pszXML, GA_Update ) );
         }
 
         CPLFree( pszXML );
@@ -233,11 +237,11 @@ VRTCreateCopy( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Create the virtual dataset.                                     */
 /* -------------------------------------------------------------------- */
-    poVRTDS = (VRTDataset *) 
-        VRTDataset::Create( pszFilename, 
+    VRTDataset *poVRTDS = reinterpret_cast<VRTDataset *>(
+        VRTDataset::Create( pszFilename,
                             poSrcDS->GetRasterXSize(),
                             poSrcDS->GetRasterYSize(),
-                            0, GDT_Byte, NULL );
+                            0, GDT_Byte, NULL ) );
     if (poVRTDS == NULL)
         return NULL;
 
@@ -264,9 +268,7 @@ VRTCreateCopy( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Copy any special domains that should be transportable.          */
 /* -------------------------------------------------------------------- */
-    char **papszMD;
-
-    papszMD = poSrcDS->GetMetadata( "RPC" );
+    char **papszMD = poSrcDS->GetMetadata( "RPC" );
     if( papszMD )
         poVRTDS->SetMetadata( papszMD, "RPC" );
 
@@ -283,7 +285,7 @@ VRTCreateCopy( const char * pszFilename,
 /* -------------------------------------------------------------------- */
     if( poSrcDS->GetGCPCount() > 0 )
     {
-        poVRTDS->SetGCPs( poSrcDS->GetGCPCount(), 
+        poVRTDS->SetGCPs( poSrcDS->GetGCPCount(),
                           poSrcDS->GetGCPs(),
                           poSrcDS->GetGCPProjection() );
     }
@@ -300,8 +302,9 @@ VRTCreateCopy( const char * pszFilename,
 /* -------------------------------------------------------------------- */
         poVRTDS->AddBand( poSrcBand->GetRasterDataType(), NULL );
 
-        VRTSourcedRasterBand *poVRTBand = 
-            (VRTSourcedRasterBand *) poVRTDS->GetRasterBand( iBand+1 );
+        VRTSourcedRasterBand *poVRTBand
+            = reinterpret_cast<VRTSourcedRasterBand *>(
+                poVRTDS->GetRasterBand( iBand+1 ) );
 
 /* -------------------------------------------------------------------- */
 /*      Setup source mapping.                                           */
@@ -318,7 +321,8 @@ VRTCreateCopy( const char * pszFilename,
 /* -------------------------------------------------------------------- */
         if ( (poSrcBand->GetMaskFlags() & (GMF_PER_DATASET | GMF_ALL_VALID | GMF_NODATA)) == 0)
         {
-            VRTSourcedRasterBand* poVRTMaskBand = new VRTSourcedRasterBand(poVRTDS, 0,
+            VRTSourcedRasterBand* poVRTMaskBand = new VRTSourcedRasterBand(
+                poVRTDS, 0,
                 poSrcBand->GetMaskBand()->GetRasterDataType(),
                 poSrcDS->GetRasterXSize(), poSrcDS->GetRasterYSize());
             poVRTMaskBand->AddMaskBandSource( poSrcBand );
@@ -334,9 +338,10 @@ VRTCreateCopy( const char * pszFilename,
         poSrcDS->GetRasterBand(1)->GetMaskFlags() == GMF_PER_DATASET)
     {
         GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand(1);
-        VRTSourcedRasterBand* poVRTMaskBand = new VRTSourcedRasterBand(poVRTDS, 0,
+        VRTSourcedRasterBand* poVRTMaskBand = new VRTSourcedRasterBand(
+            poVRTDS, 0,
             poSrcBand->GetMaskBand()->GetRasterDataType(),
-            poSrcDS->GetRasterXSize(), poSrcDS->GetRasterYSize());
+            poSrcDS->GetRasterXSize(), poSrcDS->GetRasterYSize() );
         poVRTMaskBand->AddMaskBandSource( poSrcBand );
         poVRTDS->SetMaskBand( poVRTMaskBand );
     }
@@ -353,44 +358,39 @@ VRTCreateCopy( const char * pszFilename,
 void GDALRegister_VRT()
 
 {
-    VRTDriver	*poDriver;
-
-    if( GDALGetDriverByName( "VRT" ) == NULL )
-    {
-        poDriver = new VRTDriver();
-        
-        poDriver->SetDescription( "VRT" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Virtual Raster" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "vrt" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "gdal_vrttut.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte Int16 UInt16 Int32 UInt32 Float32 Float64 CInt16 CInt32 CFloat32 CFloat64" );
-        
-        poDriver->pfnOpen = VRTDataset::Open;
-        poDriver->pfnCreateCopy = VRTCreateCopy;
-        poDriver->pfnCreate = VRTDataset::Create;
-        poDriver->pfnIdentify = VRTDataset::Identify;
-        poDriver->pfnDelete = VRTDataset::Delete;
-
-        poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
-"<OpenOptionList>"
-"  <Option name='ROOT_PATH' type='string' description='Root path to evaluate relative paths inside the VRT. Mainly useful for inlined VRT, or in-memory VRT, where their own directory does not make sense'/>"
-"</OpenOptionList>" );
-
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->AddSourceParser( "SimpleSource", 
-                                   VRTParseCoreSources );
-        poDriver->AddSourceParser( "ComplexSource", 
-                                   VRTParseCoreSources );
-        poDriver->AddSourceParser( "AveragedSource", 
-                                   VRTParseCoreSources );
-
-        poDriver->AddSourceParser( "KernelFilteredSource", 
-                                   VRTParseFilterSources );
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    if( GDALGetDriverByName( "VRT" ) != NULL )
+        return;
+
+    VRTDriver *poDriver = new VRTDriver();
+
+    poDriver->SetDescription( "VRT" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Virtual Raster" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "vrt" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "gdal_vrttut.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte Int16 UInt16 Int32 UInt32 Float32 Float64 "
+                               "CInt16 CInt32 CFloat32 CFloat64" );
+
+    poDriver->pfnOpen = VRTDataset::Open;
+    poDriver->pfnCreateCopy = VRTCreateCopy;
+    poDriver->pfnCreate = VRTDataset::Create;
+    poDriver->pfnIdentify = VRTDataset::Identify;
+    poDriver->pfnDelete = VRTDataset::Delete;
+
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+"<OptionList>"
+"  <on name='ROOT_PATH' type='string' description='Root path to evaluate "
+"relative paths inside the VRT. Mainly useful for inlined VRT, or in-memory "
+"VRT, where their own directory does not make sense'/>"
+"</OptionList>" );
+
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->AddSourceParser( "SimpleSource", VRTParseCoreSources );
+    poDriver->AddSourceParser( "ComplexSource", VRTParseCoreSources );
+    poDriver->AddSourceParser( "AveragedSource", VRTParseCoreSources );
+    poDriver->AddSourceParser( "KernelFilteredSource", VRTParseFilterSources );
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/vrt/vrtfilters.cpp b/frmts/vrt/vrtfilters.cpp
index ad291c9..266f569 100644
--- a/frmts/vrt/vrtfilters.cpp
+++ b/frmts/vrt/vrtfilters.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtfilters.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: vrtfilters.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of some filter types.
@@ -32,7 +32,7 @@
 #include "cpl_minixml.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: vrtfilters.cpp 28053 2014-12-04 09:31:07Z rouault $");
+CPL_CVSID("$Id: vrtfilters.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -44,22 +44,18 @@ CPL_CVSID("$Id: vrtfilters.cpp 28053 2014-12-04 09:31:07Z rouault $");
 /*                         VRTFilteredSource()                          */
 /************************************************************************/
 
-VRTFilteredSource::VRTFilteredSource()
-
+VRTFilteredSource::VRTFilteredSource() :
+    m_nSupportedTypesCount(1),
+    m_nExtraEdgePixels(0)
 {
-    nExtraEdgePixels = 0;
-    nSupportedTypesCount = 1;
-    aeSupportedTypes[0] = GDT_Float32;
+    m_aeSupportedTypes[0] = GDT_Float32;
 }
 
 /************************************************************************/
 /*                         ~VRTFilteredSource()                         */
 /************************************************************************/
 
-VRTFilteredSource::~VRTFilteredSource()
-
-{
-}
+VRTFilteredSource::~VRTFilteredSource() {}
 
 /************************************************************************/
 /*                         SetExtraEdgePixels()                         */
@@ -68,27 +64,27 @@ VRTFilteredSource::~VRTFilteredSource()
 void VRTFilteredSource::SetExtraEdgePixels( int nEdgePixels )
 
 {
-    nExtraEdgePixels = nEdgePixels;
+    m_nExtraEdgePixels = nEdgePixels;
 }
 
 /************************************************************************/
 /*                   SetFilteringDataTypesSupported()                   */
 /************************************************************************/
 
-void VRTFilteredSource::SetFilteringDataTypesSupported( int nTypeCount, 
+void VRTFilteredSource::SetFilteringDataTypesSupported( int nTypeCount,
                                                         GDALDataType *paeTypes)
 
 {
-    if( nTypeCount > 
-        (int) (sizeof(aeSupportedTypes)/sizeof(GDALDataType)) )
+    if( nTypeCount >
+        static_cast<int>( sizeof(m_aeSupportedTypes) / sizeof(GDALDataType) ) )
     {
         CPLAssert( FALSE );
-        nTypeCount = (int) 
-            (sizeof(aeSupportedTypes)/sizeof(GDALDataType));
+        nTypeCount = static_cast<int>(
+            sizeof(m_aeSupportedTypes) / sizeof(GDALDataType) );
     }
 
-    nSupportedTypesCount = nTypeCount;
-    memcpy( aeSupportedTypes, paeTypes, sizeof(GDALDataType) * nTypeCount );
+    m_nSupportedTypesCount = nTypeCount;
+    memcpy( m_aeSupportedTypes, paeTypes, sizeof(GDALDataType) * nTypeCount );
 }
 
 /************************************************************************/
@@ -98,11 +94,9 @@ void VRTFilteredSource::SetFilteringDataTypesSupported( int nTypeCount,
 int VRTFilteredSource::IsTypeSupported( GDALDataType eTestType )
 
 {
-    int i;
-
-    for( i = 0; i < nSupportedTypesCount; i++ )
+    for( int i = 0; i < m_nSupportedTypesCount; i++ )
     {
-        if( eTestType == aeSupportedTypes[i] )
+        if( eTestType == m_aeSupportedTypes[i] )
             return TRUE;
     }
 
@@ -114,9 +108,9 @@ int VRTFilteredSource::IsTypeSupported( GDALDataType eTestType )
 /************************************************************************/
 
 CPLErr
-VRTFilteredSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize, 
-                             void *pData, int nBufXSize, int nBufYSize, 
-                             GDALDataType eBufType, 
+VRTFilteredSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
+                             void *pData, int nBufXSize, int nBufYSize,
+                             GDALDataType eBufType,
                              GSpacing nPixelSpace,
                              GSpacing nLineSpace,
                              GDALRasterIOExtraArg* psExtraArg )
@@ -129,8 +123,8 @@ VRTFilteredSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
 /* -------------------------------------------------------------------- */
     if( nBufXSize != nXSize || nBufYSize != nYSize )
     {
-        return VRTComplexSource::RasterIO( nXOff, nYOff, nXSize, nYSize, 
-                                           pData, nBufXSize, nBufYSize, 
+        return VRTComplexSource::RasterIO( nXOff, nYOff, nXSize, nYSize,
+                                           pData, nBufXSize, nBufYSize,
                                            eBufType, nPixelSpace, nLineSpace, psExtraArg );
     }
 
@@ -147,9 +141,9 @@ VRTFilteredSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
                         &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) )
         return CE_None;
 
-    pData = ((GByte *)pData)
-                            + nPixelSpace * nOutXOff
-                            + nLineSpace * nOutYOff;
+    pData = reinterpret_cast<GByte *>( pData )
+        + nPixelSpace * nOutXOff
+        + nLineSpace * nOutYOff;
 
 /* -------------------------------------------------------------------- */
 /*      Determine the data type we want to request.  We try to match    */
@@ -158,37 +152,36 @@ VRTFilteredSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
 /*      as the request.                                                 */
 /* -------------------------------------------------------------------- */
     GDALDataType eOperDataType = GDT_Unknown;
-    int i;
-    
+
     if( IsTypeSupported( eBufType ) )
         eOperDataType = eBufType;
 
-    if( eOperDataType == GDT_Unknown 
-        && IsTypeSupported( poRasterBand->GetRasterDataType() ) )
-        eOperDataType = poRasterBand->GetRasterDataType();
+    if( eOperDataType == GDT_Unknown
+        && IsTypeSupported( m_poRasterBand->GetRasterDataType() ) )
+        eOperDataType = m_poRasterBand->GetRasterDataType();
 
     if( eOperDataType == GDT_Unknown )
     {
-        for( i = 0; i < nSupportedTypesCount; i++ )
+        for( int i = 0; i < m_nSupportedTypesCount; i++ )
         {
-            if( GDALDataTypeUnion( aeSupportedTypes[i], eBufType ) 
-                == aeSupportedTypes[i] )
+            if( GDALDataTypeUnion( m_aeSupportedTypes[i], eBufType )
+                == m_aeSupportedTypes[i] )
             {
-                eOperDataType = aeSupportedTypes[i];
+                eOperDataType = m_aeSupportedTypes[i];
             }
         }
     }
 
     if( eOperDataType == GDT_Unknown )
     {
-        eOperDataType = aeSupportedTypes[0];
+        eOperDataType = m_aeSupportedTypes[0];
 
-        for( i = 1; i < nSupportedTypesCount; i++ )
+        for( int i = 1; i < m_nSupportedTypesCount; i++ )
         {
-            if( GDALGetDataTypeSize( aeSupportedTypes[i] ) 
+            if( GDALGetDataTypeSize( m_aeSupportedTypes[i] )
                 > GDALGetDataTypeSize( eOperDataType ) )
             {
-                eOperDataType = aeSupportedTypes[i];
+                eOperDataType = m_aeSupportedTypes[i];
             }
         }
     }
@@ -198,61 +191,58 @@ VRTFilteredSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
 /*      read, with the extra edge pixels as well. This will be the      */
 /*      source data fed into the filter.                                */
 /* -------------------------------------------------------------------- */
-    int nPixelOffset, nLineOffset;
-    int nExtraXSize = nOutXSize + 2 * nExtraEdgePixels;
-    int nExtraYSize = nOutYSize + 2 * nExtraEdgePixels;
-    GByte *pabyWorkData;
+    const int nExtraXSize = nOutXSize + 2 * m_nExtraEdgePixels;
+    const int nExtraYSize = nOutYSize + 2 * m_nExtraEdgePixels;
 
     // FIXME? : risk of multiplication overflow
-    pabyWorkData = (GByte *) 
-        VSICalloc( nExtraXSize * nExtraYSize,
-                   (GDALGetDataTypeSize(eOperDataType) / 8) );
-    
+    GByte *pabyWorkData = reinterpret_cast<GByte *>(
+        VSI_CALLOC_VERBOSE( nExtraXSize * nExtraYSize,
+                   GDALGetDataTypeSize(eOperDataType) / 8 ) );
+
     if( pabyWorkData == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory, 
-                  "Work buffer allocation failed." );
         return CE_Failure;
     }
 
-    nPixelOffset = GDALGetDataTypeSize( eOperDataType ) / 8;
-    nLineOffset = nPixelOffset * nExtraXSize;
+    const int nPixelOffset = GDALGetDataTypeSize( eOperDataType ) / 8;
+    const int nLineOffset = nPixelOffset * nExtraXSize;
 
 /* -------------------------------------------------------------------- */
 /*      Allocate the output buffer if the passed in output buffer is    */
 /*      not of the same type as our working format, or if the passed    */
 /*      in buffer has an unusual organization.                          */
 /* -------------------------------------------------------------------- */
-    GByte *pabyOutData;
+    GByte *pabyOutData = NULL;
 
     if( nPixelSpace != nPixelOffset || nLineSpace != nLineOffset
         || eOperDataType != eBufType )
     {
-        pabyOutData = (GByte *) 
-            VSIMalloc3(nOutXSize, nOutYSize, nPixelOffset );
+        pabyOutData = reinterpret_cast<GByte *>(
+            VSI_MALLOC3_VERBOSE( nOutXSize, nOutYSize, nPixelOffset ) );
 
         if( pabyOutData == NULL )
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory, 
-                      "Work buffer allocation failed." );
+            CPLFree( pabyWorkData );
             return CE_Failure;
         }
     }
     else
-        pabyOutData = (GByte *) pData;
+        pabyOutData = reinterpret_cast<GByte *>( pData );
 
 /* -------------------------------------------------------------------- */
 /*      Figure out the extended window that we want to load.  Note      */
 /*      that we keep track of the file window as well as the amount     */
 /*      we will need to edge fill past the edge of the source dataset.  */
 /* -------------------------------------------------------------------- */
-    int nTopFill=0, nLeftFill=0, nRightFill=0, nBottomFill=0;
-    int nFileXOff, nFileYOff, nFileXSize, nFileYSize;
+    int nFileXOff = nReqXOff - m_nExtraEdgePixels;
+    int nFileYOff = nReqYOff - m_nExtraEdgePixels;
+    int nFileXSize = nExtraXSize;
+    int nFileYSize = nExtraYSize;
 
-    nFileXOff = nReqXOff - nExtraEdgePixels;
-    nFileYOff = nReqYOff - nExtraEdgePixels;
-    nFileXSize = nExtraXSize;
-    nFileYSize = nExtraYSize;
+    int nTopFill=0;
+    int nLeftFill=0;
+    int nRightFill=0;
+    int nBottomFill=0;
 
     if( nFileXOff < 0 )
     {
@@ -268,36 +258,36 @@ VRTFilteredSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
         nFileYSize -= nTopFill;
     }
 
-    if( nFileXOff + nFileXSize > poRasterBand->GetXSize() )
+    if( nFileXOff + nFileXSize > m_poRasterBand->GetXSize() )
     {
-        nRightFill = nFileXOff + nFileXSize - poRasterBand->GetXSize();
+        nRightFill = nFileXOff + nFileXSize - m_poRasterBand->GetXSize();
         nFileXSize -= nRightFill;
     }
 
-    if( nFileYOff + nFileYSize > poRasterBand->GetYSize() )
+    if( nFileYOff + nFileYSize > m_poRasterBand->GetYSize() )
     {
-        nBottomFill = nFileYOff + nFileYSize - poRasterBand->GetYSize();
+        nBottomFill = nFileYOff + nFileYSize - m_poRasterBand->GetYSize();
         nFileYSize -= nBottomFill;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Load the data.                                                  */
 /* -------------------------------------------------------------------- */
-    CPLErr eErr;
-
-    eErr =
-        VRTComplexSource::RasterIOInternal( nFileXOff, nFileYOff, nFileXSize, nFileYSize,
-                                            pabyWorkData
-                                              + nLineOffset * nTopFill
-                                              + nPixelOffset * nLeftFill,
-                                            nFileXSize, nFileYSize, eOperDataType,
-                                            nPixelOffset, nLineOffset, psExtraArg );
+    CPLErr eErr
+        = VRTComplexSource::RasterIOInternal(
+            nFileXOff, nFileYOff, nFileXSize, nFileYSize,
+            pabyWorkData + nLineOffset * nTopFill + nPixelOffset * nLeftFill,
+            nFileXSize, nFileYSize, eOperDataType,
+            nPixelOffset, nLineOffset, psExtraArg );
 
     if( eErr != CE_None )
     {
         if( pabyWorkData != pData )
             VSIFree( pabyWorkData );
 
+        if( pabyOutData != pData )
+            VSIFree( pabyOutData );
+
         return eErr;
     }
 
@@ -309,38 +299,38 @@ VRTFilteredSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
 /* -------------------------------------------------------------------- */
     if( nLeftFill != 0 || nRightFill != 0 )
     {
-        for( i = nTopFill; i < nExtraYSize - nBottomFill; i++ )
+        for( int i = nTopFill; i < nExtraYSize - nBottomFill; i++ )
         {
             if( nLeftFill != 0 )
                 GDALCopyWords( pabyWorkData + nPixelOffset * nLeftFill
-                               + i * nLineOffset, eOperDataType, 0, 
-                               pabyWorkData + i * nLineOffset, eOperDataType, 
+                               + i * nLineOffset, eOperDataType, 0,
+                               pabyWorkData + i * nLineOffset, eOperDataType,
                                nPixelOffset, nLeftFill );
 
             if( nRightFill != 0 )
                 GDALCopyWords( pabyWorkData + i * nLineOffset
                                + nPixelOffset * (nExtraXSize - nRightFill - 1),
-                               eOperDataType, 0, 
+                               eOperDataType, 0,
                                pabyWorkData + i * nLineOffset
                                + nPixelOffset * (nExtraXSize - nRightFill),
                                eOperDataType, nPixelOffset, nRightFill );
         }
     }
 
-    for( i = 0; i < nTopFill; i++ )
+    for( int i = 0; i < nTopFill; i++ )
     {
-        memcpy( pabyWorkData + i * nLineOffset, 
-                pabyWorkData + nTopFill * nLineOffset, 
+        memcpy( pabyWorkData + i * nLineOffset,
+                pabyWorkData + nTopFill * nLineOffset,
                 nLineOffset );
     }
 
-    for( i = nExtraYSize - nBottomFill; i < nExtraYSize; i++ )
+    for( int i = nExtraYSize - nBottomFill; i < nExtraYSize; i++ )
     {
-        memcpy( pabyWorkData + i * nLineOffset, 
-                pabyWorkData + (nExtraYSize - nBottomFill - 1) * nLineOffset, 
+        memcpy( pabyWorkData + i * nLineOffset,
+                pabyWorkData + (nExtraYSize - nBottomFill - 1) * nLineOffset,
                 nLineOffset );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Filter the data.                                                */
 /* -------------------------------------------------------------------- */
@@ -355,18 +345,18 @@ VRTFilteredSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
 
         return eErr;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Copy from work buffer to target buffer.                         */
 /* -------------------------------------------------------------------- */
     if( pabyOutData != pData )
     {
-        for( i = 0; i < nOutYSize; i++ )
+        for( int i = 0; i < nOutYSize; i++ )
         {
             GDALCopyWords( pabyOutData + i * (nPixelOffset * nOutXSize),
                            eOperDataType, nPixelOffset,
-                           ((GByte *) pData) + i * nLineSpace, 
-                           eBufType, nPixelSpace, nOutXSize );
+                           reinterpret_cast<GByte *>( pData ) + i * nLineSpace,
+                           eBufType, static_cast<int>(nPixelSpace), nOutXSize );
         }
 
         VSIFree( pabyOutData );
@@ -385,14 +375,12 @@ VRTFilteredSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
 /*                      VRTKernelFilteredSource()                       */
 /************************************************************************/
 
-VRTKernelFilteredSource::VRTKernelFilteredSource()
-
+VRTKernelFilteredSource::VRTKernelFilteredSource() :
+    m_nKernelSize(0),
+    m_padfKernelCoefs(NULL),
+    m_bNormalized(FALSE)
 {
     GDALDataType aeSupTypes[] = { GDT_Float32 };
-    padfKernelCoefs = NULL;
-    nKernelSize = 0;
-    bNormalized = FALSE;
-
     SetFilteringDataTypesSupported( 1, aeSupTypes );
 }
 
@@ -400,10 +388,10 @@ VRTKernelFilteredSource::VRTKernelFilteredSource()
 /*                      ~VRTKernelFilteredSource()                      */
 /************************************************************************/
 
-VRTKernelFilteredSource::~VRTKernelFilteredSource() 
+VRTKernelFilteredSource::~VRTKernelFilteredSource()
 
 {
-    CPLFree( padfKernelCoefs );
+    CPLFree( m_padfKernelCoefs );
 }
 
 /************************************************************************/
@@ -413,32 +401,32 @@ VRTKernelFilteredSource::~VRTKernelFilteredSource()
 void VRTKernelFilteredSource::SetNormalized( int bNormalizedIn )
 
 {
-    bNormalized = bNormalizedIn;
+    m_bNormalized = bNormalizedIn;
 }
 
 /************************************************************************/
 /*                             SetKernel()                              */
 /************************************************************************/
 
-CPLErr VRTKernelFilteredSource::SetKernel( int nNewKernelSize, 
+CPLErr VRTKernelFilteredSource::SetKernel( int nNewKernelSize,
                                            double *padfNewCoefs )
 
 {
     if( nNewKernelSize < 1 || (nNewKernelSize % 2) != 1 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Illegal filtering kernel size %d, must be odd positive number.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Illegal filtering kernel size %d, must be odd positive number.",
                   nNewKernelSize );
         return CE_Failure;
     }
 
-    CPLFree( padfKernelCoefs );
-    nKernelSize = nNewKernelSize;
+    CPLFree( m_padfKernelCoefs );
+    m_nKernelSize = nNewKernelSize;
 
-    padfKernelCoefs = (double *) 
-        CPLMalloc(sizeof(double) * nKernelSize * nKernelSize );
-    memcpy( padfKernelCoefs, padfNewCoefs, 
-            sizeof(double) * nKernelSize * nKernelSize );
+    m_padfKernelCoefs = reinterpret_cast<double *>(
+        CPLMalloc(sizeof(double) * m_nKernelSize * m_nKernelSize ) );
+    memcpy( m_padfKernelCoefs, padfNewCoefs,
+            sizeof(double) * m_nKernelSize * m_nKernelSize );
 
     SetExtraEdgePixels( (nNewKernelSize - 1) / 2 );
 
@@ -450,7 +438,7 @@ CPLErr VRTKernelFilteredSource::SetKernel( int nNewKernelSize,
 /************************************************************************/
 
 CPLErr VRTKernelFilteredSource::
-FilterData( int nXSize, int nYSize, GDALDataType eType, 
+FilterData( int nXSize, int nYSize, GDALDataType eType,
             GByte *pabySrcData, GByte *pabyDstData )
 
 {
@@ -459,67 +447,74 @@ FilterData( int nXSize, int nYSize, GDALDataType eType,
 /* -------------------------------------------------------------------- */
     if( eType != GDT_Float32 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Unsupported data type (%s) in VRTKernelFilteredSource::FilterData()", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Unsupported data type (%s) in "
+                  "VRTKernelFilteredSource::FilterData()",
                   GDALGetDataTypeName( eType ) );
-        return CE_Failure; 
+        return CE_Failure;
     }
 
-    CPLAssert( nExtraEdgePixels*2 + 1 == nKernelSize ||
-               (nKernelSize == 0 && nExtraEdgePixels == 0) );
+    CPLAssert( m_nExtraEdgePixels*2 + 1 == m_nKernelSize ||
+               (m_nKernelSize == 0 && m_nExtraEdgePixels == 0) );
 
 /* -------------------------------------------------------------------- */
 /*      Float32 case.                                                   */
 /* -------------------------------------------------------------------- */
     if( eType == GDT_Float32 )
     {
-        int iX, iY;
-
         int bHasNoData;
-        float fNoData = (float) poRasterBand->GetNoDataValue(&bHasNoData);
+        float fNoData
+            = static_cast<float>( m_poRasterBand->GetNoDataValue(&bHasNoData) );
 
-        for( iY = 0; iY < nYSize; iY++ )
+        for( int iY = 0; iY < nYSize; iY++ )
         {
-            for( iX = 0; iX < nXSize; iX++ )
+            for( int iX = 0; iX < nXSize; iX++ )
             {
-                int    iYY, iKern = 0;
-                double dfSum = 0.0, dfKernSum = 0.0;
-                float  fResult;
-                int    iIndex = (iY+nKernelSize/2 ) * (nXSize+2*nExtraEdgePixels) + iX + nKernelSize/2;
-                float  fCenter = ((float *)pabySrcData)[iIndex];
+                const int iIndex
+                    = (iY+m_nKernelSize/2 ) * (nXSize+2*m_nExtraEdgePixels)
+                    + iX + m_nKernelSize/2;
+                const float  fCenter
+                    = reinterpret_cast<float *>( pabySrcData )[iIndex];
+
+                int iKern = 0;
+                double dfSum = 0.0;
+                double dfKernSum = 0.0;
+                float fResult = 0.0;
 
                 // Check if center srcpixel is NoData
                 if(!bHasNoData || fCenter != fNoData)
                 {
-                    for( iYY = 0; iYY < nKernelSize; iYY++ )
+                    for( int iYY = 0; iYY < m_nKernelSize; iYY++ )
                     {
-                        int i;
-                        float *pafData = ((float *)pabySrcData) 
-                                + (iY+iYY) * (nXSize+2*nExtraEdgePixels) + iX;
+                        float *pafData
+                            = reinterpret_cast<float *>( pabySrcData )
+                            + (iY+iYY) * (nXSize+2*m_nExtraEdgePixels) + iX;
 
-                        for( i = 0; i < nKernelSize; i++, pafData++, iKern++ )
+                        for( int i = 0; i < m_nKernelSize; i++, pafData++, iKern++ )
                         {
                             if(!bHasNoData || *pafData != fNoData)
                             {
-                                dfSum += *pafData * padfKernelCoefs[iKern];
-                                dfKernSum += padfKernelCoefs[iKern];
+                                dfSum += *pafData * m_padfKernelCoefs[iKern];
+                                dfKernSum += m_padfKernelCoefs[iKern];
                             }
                         }
                     }
-                    if( bNormalized )
+                    if( m_bNormalized )
                     {
                         if( dfKernSum != 0.0 )
-                            fResult = (float) (dfSum / dfKernSum);
+                            fResult = static_cast<float>( dfSum / dfKernSum );
                         else
                             fResult = 0.0;
                     }
                     else
-                        fResult = (float) dfSum;
+                        fResult = static_cast<float>( dfSum );
 
-                    ((float *) pabyDstData)[iX + iY * nXSize] = fResult;
+                    reinterpret_cast<float *>( pabyDstData )[iX + iY * nXSize]
+                        = fResult;
                 }
                 else
-                    ((float *) pabyDstData)[iX + iY * nXSize] = fNoData;
+                    reinterpret_cast<float *>( pabyDstData )[iX + iY * nXSize]
+                        = fNoData;
             }
         }
     }
@@ -531,41 +526,39 @@ FilterData( int nXSize, int nYSize, GDALDataType eType,
 /*                              XMLInit()                               */
 /************************************************************************/
 
-CPLErr VRTKernelFilteredSource::XMLInit( CPLXMLNode *psTree, 
+CPLErr VRTKernelFilteredSource::XMLInit( CPLXMLNode *psTree,
                                          const char *pszVRTPath )
 
 {
     CPLErr eErr = VRTFilteredSource::XMLInit( psTree, pszVRTPath );
-    int    nNewKernelSize, i, nCoefs;
-    double *padfNewCoefs;
-
     if( eErr != CE_None )
         return eErr;
 
-    nNewKernelSize = atoi(CPLGetXMLValue(psTree,"Kernel.Size","0"));
+    const int nNewKernelSize = atoi(CPLGetXMLValue(psTree,"Kernel.Size","0"));
 
     if( nNewKernelSize == 0 )
         return CE_None;
 
-    char **papszCoefItems = 
+    char **papszCoefItems =
         CSLTokenizeString( CPLGetXMLValue(psTree,"Kernel.Coefs","") );
 
-    nCoefs = CSLCount(papszCoefItems);
+    const int nCoefs = CSLCount(papszCoefItems);
 
     if( nCoefs != nNewKernelSize * nNewKernelSize )
     {
         CSLDestroy( papszCoefItems );
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Got wrong number of filter kernel coefficients (%s).\n"
-                  "Expected %d, got %d.", 
+                  "Expected %d, got %d.",
                   CPLGetXMLValue(psTree,"Kernel.Coefs",""),
                   nNewKernelSize * nNewKernelSize, nCoefs );
         return CE_Failure;
     }
 
-    padfNewCoefs = (double *) CPLMalloc(sizeof(double) * nCoefs);
+    double *padfNewCoefs = reinterpret_cast<double *>(
+        CPLMalloc( sizeof(double) * nCoefs ) );
 
-    for( i = 0; i < nCoefs; i++ )
+    for( int i = 0; i < nCoefs; i++ )
         padfNewCoefs[i] = CPLAtof(papszCoefItems[i]);
 
     eErr = SetKernel( nNewKernelSize, padfNewCoefs );
@@ -586,9 +579,6 @@ CPLXMLNode *VRTKernelFilteredSource::SerializeToXML( const char *pszVRTPath )
 
 {
     CPLXMLNode *psSrc = VRTFilteredSource::SerializeToXML( pszVRTPath );
-    CPLXMLNode *psKernel;
-    char *pszKernelCoefs;
-    int iCoef, nCoefCount = nKernelSize * nKernelSize;
 
     if( psSrc == NULL )
         return NULL;
@@ -596,28 +586,32 @@ CPLXMLNode *VRTKernelFilteredSource::SerializeToXML( const char *pszVRTPath )
     CPLFree( psSrc->pszValue );
     psSrc->pszValue = CPLStrdup("KernelFilteredSource" );
 
-    if( nKernelSize == 0 )
+    if( m_nKernelSize == 0 )
         return psSrc;
 
-    psKernel = CPLCreateXMLNode( psSrc, CXT_Element, "Kernel" );
+    CPLXMLNode *psKernel = CPLCreateXMLNode( psSrc, CXT_Element, "Kernel" );
 
-    if( bNormalized )
-        CPLCreateXMLNode( 
-            CPLCreateXMLNode( psKernel, CXT_Attribute, "normalized" ), 
+    if( m_bNormalized )
+        CPLCreateXMLNode(
+            CPLCreateXMLNode( psKernel, CXT_Attribute, "normalized" ),
             CXT_Text, "1" );
     else
-        CPLCreateXMLNode( 
-            CPLCreateXMLNode( psKernel, CXT_Attribute, "normalized" ), 
+        CPLCreateXMLNode(
+            CPLCreateXMLNode( psKernel, CXT_Attribute, "normalized" ),
             CXT_Text, "0" );
 
-    pszKernelCoefs = (char *) CPLMalloc(nCoefCount * 32);
+    const int nCoefCount = m_nKernelSize * m_nKernelSize;
+    const size_t nBufLen = nCoefCount * 32;
+    char *pszKernelCoefs = reinterpret_cast<char *>(
+        CPLMalloc(nBufLen) );
 
     strcpy( pszKernelCoefs, "" );
-    for( iCoef = 0; iCoef < nCoefCount; iCoef++ )
-        CPLsprintf( pszKernelCoefs + strlen(pszKernelCoefs), 
-                 "%.8g ", padfKernelCoefs[iCoef] );
-    
-    CPLSetXMLValue( psKernel, "Size", CPLSPrintf( "%d", nKernelSize ) );
+    for( int iCoef = 0; iCoef < nCoefCount; iCoef++ )
+        CPLsnprintf( pszKernelCoefs + strlen(pszKernelCoefs),
+                     nBufLen - strlen(pszKernelCoefs),
+                 "%.8g ", m_padfKernelCoefs[iCoef] );
+
+    CPLSetXMLValue( psKernel, "Size", CPLSPrintf( "%d", m_nKernelSize ) );
     CPLSetXMLValue( psKernel, "Coefs", pszKernelCoefs );
 
     CPLFree( pszKernelCoefs );
@@ -632,11 +626,9 @@ CPLXMLNode *VRTKernelFilteredSource::SerializeToXML( const char *pszVRTPath )
 VRTSource *VRTParseFilterSources( CPLXMLNode *psChild, const char *pszVRTPath )
 
 {
-    VRTSource *poSrc;
-
     if( EQUAL(psChild->pszValue,"KernelFilteredSource") )
     {
-        poSrc = new VRTKernelFilteredSource();
+        VRTSource *poSrc = new VRTKernelFilteredSource();
         if( poSrc->XMLInit( psChild, pszVRTPath ) == CE_None )
             return poSrc;
         else
@@ -645,4 +637,3 @@ VRTSource *VRTParseFilterSources( CPLXMLNode *psChild, const char *pszVRTPath )
 
     return NULL;
 }
-
diff --git a/frmts/vrt/vrtpansharpened.cpp b/frmts/vrt/vrtpansharpened.cpp
new file mode 100644
index 0000000..a0c2419
--- /dev/null
+++ b/frmts/vrt/vrtpansharpened.cpp
@@ -0,0 +1,1755 @@
+/******************************************************************************
+ * $Id: vrtpansharpened.cpp 33720 2016-03-15 00:39:53Z goatbar $
+ *
+ * Project:  Virtual GDAL Datasets
+ * Purpose:  Implementation of VRTPansharpenedRasterBand and VRTPansharpenedDataset.
+ * Author:   Even Rouault <even.rouault at spatialys.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "vrtdataset.h"
+
+#include "gdal_vrt.h"
+#include "gdalpansharpen.h"
+#include "ogr_spatialref.h"
+
+#include <cassert>
+#include <cmath>
+
+#include <algorithm>
+#include <map>
+#include <set>
+
+CPL_CVSID("$Id: vrtpansharpened.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+
+/************************************************************************/
+/*                    GDALCreatePansharpenedVRT()                       */
+/************************************************************************/
+
+/**
+ * Create a virtual pansharpened dataset.
+ *
+ * This function will create a virtual pansharpened dataset.
+ *
+ * Note that no reference will be taken on the passed bands. Consequently,
+ * they or their dataset to which they belong to must be kept open until
+ * this virtual pansharpened dataset is closed.
+ *
+ * The returned dataset will have no associated filename for itself.  If you
+ * want to write the virtual dataset description to a file, use the
+ * GDALSetDescription() function (or SetDescription() method) on the dataset
+ * to assign a filename before it is closed.
+ *
+ * @param pszXML Pansharpened VRT XML where <SpectralBand> elements have
+ * no explicit SourceFilename and SourceBand. The spectral bands in the XML will be assigned
+ * the successive values of the pahInputSpectralBands array. Must not be NULL.
+ *
+ * @param hPanchroBand Panchromatic band. Must not be NULL.
+ *
+ * @param nInputSpectralBands Number of input spectral bands.  Must be greater than zero.
+ *
+ * @param pahInputSpectralBands Array of nInputSpectralBands spectral bands.
+ *
+ * @return NULL on failure, or a new virtual dataset handle on success to be closed
+ * with GDALClose().
+ *
+ * @since GDAL 2.1
+ */
+
+GDALDatasetH GDALCreatePansharpenedVRT( const char* pszXML,
+                                            GDALRasterBandH hPanchroBand,
+                                            int nInputSpectralBands,
+                                            GDALRasterBandH* pahInputSpectralBands )
+{
+    VALIDATE_POINTER1( pszXML, "GDALCreatePansharpenedVRT", NULL );
+    VALIDATE_POINTER1( hPanchroBand, "GDALCreatePansharpenedVRT", NULL );
+    VALIDATE_POINTER1( pahInputSpectralBands, "GDALCreatePansharpenedVRT", NULL );
+
+    CPLXMLNode* psTree = CPLParseXMLString(pszXML);
+    if( psTree == NULL )
+        return NULL;
+    VRTPansharpenedDataset* poDS = new VRTPansharpenedDataset(0,0);
+    CPLErr eErr = poDS->XMLInit(psTree, NULL, hPanchroBand,
+                                  nInputSpectralBands, pahInputSpectralBands);
+    CPLDestroyXMLNode(psTree);
+    if( eErr != CE_None )
+    {
+        delete poDS;
+        return NULL;
+    }
+    return reinterpret_cast<GDALDatasetH>( poDS );
+}
+
+/************************************************************************/
+/* ==================================================================== */
+/*                        VRTPansharpenedDataset                        */
+/* ==================================================================== */
+/************************************************************************/
+
+/************************************************************************/
+/*                       VRTPansharpenedDataset()                       */
+/************************************************************************/
+
+VRTPansharpenedDataset::VRTPansharpenedDataset( int nXSize, int nYSize ) :
+    VRTDataset( nXSize, nYSize ),
+    m_nBlockXSize(std::min(nXSize, 512)),
+    m_nBlockYSize(std::min(nYSize, 512)),
+    m_poPansharpener(NULL),
+    m_poMainDataset(NULL),
+    m_bLoadingOtherBands(FALSE),
+    m_pabyLastBufferBandRasterIO(NULL),
+    m_nLastBandRasterIOXOff(0),
+    m_nLastBandRasterIOYOff(0),
+    m_nLastBandRasterIOXSize(0),
+    m_nLastBandRasterIOYSize(0),
+    m_eLastBandRasterIODataType(GDT_Unknown),
+    m_eGTAdjustment(GTAdjust_Union),
+    m_bNoDataDisabled(FALSE)
+{
+    eAccess = GA_Update;
+    m_poMainDataset = this;
+}
+
+/************************************************************************/
+/*                    ~VRTPansharpenedDataset()                         */
+/************************************************************************/
+
+VRTPansharpenedDataset::~VRTPansharpenedDataset()
+
+{
+    CloseDependentDatasets();
+    CPLFree(m_pabyLastBufferBandRasterIO);
+}
+
+/************************************************************************/
+/*                        CloseDependentDatasets()                      */
+/************************************************************************/
+
+int VRTPansharpenedDataset::CloseDependentDatasets()
+{
+    if( m_poMainDataset == NULL )
+        return FALSE;
+    FlushCache();
+
+    VRTPansharpenedDataset* poMainDatasetLocal = m_poMainDataset;
+    m_poMainDataset = NULL;
+    int bHasDroppedRef = VRTDataset::CloseDependentDatasets();
+
+/* -------------------------------------------------------------------- */
+/*      Destroy the raster bands if they exist.                         */
+/* -------------------------------------------------------------------- */
+    for( int iBand = 0; iBand < nBands; iBand++ )
+    {
+       delete papoBands[iBand];
+    }
+    nBands = 0;
+
+    if( m_poPansharpener != NULL )
+    {
+        // Delete the pansharper object before closing the dataset
+        // because it may have warped the bands into an intermediate VRT
+        delete m_poPansharpener;
+        m_poPansharpener = NULL;
+
+        // Close in reverse order (VRT firsts and real datasets after)
+        for( int i = static_cast<int>( m_apoDatasetsToClose.size() ) - 1;
+             i >= 0;
+             i--)
+        {
+            bHasDroppedRef = TRUE;
+            GDALClose(m_apoDatasetsToClose[i]);
+        }
+        m_apoDatasetsToClose.resize(0);
+    }
+
+    for( size_t i=0; i<m_apoOverviewDatasets.size();i++)
+    {
+        bHasDroppedRef = TRUE;
+        delete m_apoOverviewDatasets[i];
+    }
+    m_apoOverviewDatasets.resize(0);
+
+    if( poMainDatasetLocal != this )
+    {
+        // To avoid killing us
+        for( size_t i=0; i<poMainDatasetLocal->m_apoOverviewDatasets.size();i++)
+        {
+            if( poMainDatasetLocal->m_apoOverviewDatasets[i] == this )
+            {
+                poMainDatasetLocal->m_apoOverviewDatasets[i] = NULL;
+                break;
+            }
+        }
+        bHasDroppedRef |= poMainDatasetLocal->CloseDependentDatasets();
+    }
+
+    return bHasDroppedRef;
+}
+
+
+/************************************************************************/
+/*                            GetFileList()                             */
+/************************************************************************/
+
+char** VRTPansharpenedDataset::GetFileList()
+{
+    char** papszFileList = GDALDataset::GetFileList();
+
+    if( m_poPansharpener != NULL )
+    {
+        GDALPansharpenOptions* psOptions = m_poPansharpener->GetOptions();
+        if( psOptions != NULL )
+        {
+            std::set<CPLString> oSetNames;
+            if( psOptions->hPanchroBand != NULL )
+            {
+                GDALDatasetH hDS = GDALGetBandDataset(psOptions->hPanchroBand);
+                if( hDS != NULL )
+                {
+                    papszFileList = CSLAddString(papszFileList, GDALGetDescription(hDS));
+                    oSetNames.insert(GDALGetDescription(hDS));
+                }
+            }
+            for(int i=0;i<psOptions->nInputSpectralBands;i++)
+            {
+                if( psOptions->pahInputSpectralBands[i] != NULL )
+                {
+                    GDALDatasetH hDS = GDALGetBandDataset(psOptions->pahInputSpectralBands[i]);
+                    if( hDS != NULL && oSetNames.find(GDALGetDescription(hDS)) == oSetNames.end() )
+                    {
+                        papszFileList = CSLAddString(papszFileList, GDALGetDescription(hDS));
+                        oSetNames.insert(GDALGetDescription(hDS));
+                    }
+                }
+            }
+        }
+    }
+
+    return papszFileList;
+}
+
+/************************************************************************/
+/*                              XMLInit()                               */
+/************************************************************************/
+
+CPLErr VRTPansharpenedDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPathIn )
+
+{
+    return XMLInit(psTree, pszVRTPathIn, NULL, 0, NULL );
+}
+
+CPLErr VRTPansharpenedDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPathIn,
+                                        GDALRasterBandH hPanchroBandIn,
+                                        int nInputSpectralBandsIn,
+                                        GDALRasterBandH* pahInputSpectralBandsIn )
+{
+    CPLErr eErr;
+    GDALPansharpenOptions* psPanOptions;
+
+/* -------------------------------------------------------------------- */
+/*      Initialize blocksize before calling sub-init so that the        */
+/*      band initializers can get it from the dataset object when       */
+/*      they are created.                                               */
+/* -------------------------------------------------------------------- */
+    m_nBlockXSize = atoi(CPLGetXMLValue(psTree,"BlockXSize","512"));
+    m_nBlockYSize = atoi(CPLGetXMLValue(psTree,"BlockYSize","512"));
+
+/* -------------------------------------------------------------------- */
+/*      Parse PansharpeningOptions                                      */
+/* -------------------------------------------------------------------- */
+
+    CPLXMLNode* psOptions = CPLGetXMLNode(psTree, "PansharpeningOptions");
+    if( psOptions == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Missing PansharpeningOptions");
+        return CE_Failure;
+    }
+
+    CPLString osSourceFilename;
+    GDALDataset* poPanDataset = NULL;
+    GDALDataset* poPanDatasetToClose = NULL;
+    GDALRasterBand* poPanBand = NULL;
+    std::map<CPLString, GDALDataset*> oMapNamesToDataset;
+    int nPanBand;
+
+    if( hPanchroBandIn == NULL )
+    {
+        CPLXMLNode* psPanchroBand = CPLGetXMLNode(psOptions, "PanchroBand");
+        if( psPanchroBand == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "PanchroBand missing");
+            return CE_Failure;
+        }
+
+        const char* pszSourceFilename = CPLGetXMLValue(psPanchroBand, "SourceFilename", NULL);
+        if( pszSourceFilename == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "PanchroBand.SourceFilename missing");
+            return CE_Failure;
+        }
+        const bool bRelativeToVRT = CPL_TO_BOOL(atoi(CPLGetXMLValue(
+            psPanchroBand, "SourceFilename.relativetoVRT", "0")));
+        if( bRelativeToVRT )
+        {
+            const char* pszAbs = CPLProjectRelativeFilename( pszVRTPathIn, pszSourceFilename );
+            m_oMapToRelativeFilenames[pszAbs] = pszSourceFilename;
+            pszSourceFilename = pszAbs;
+        }
+        osSourceFilename = pszSourceFilename;
+        poPanDataset = reinterpret_cast<GDALDataset *>(
+            GDALOpen( osSourceFilename, GA_ReadOnly ) );
+        if( poPanDataset == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "%s not a valid dataset",
+                     osSourceFilename.c_str());
+            return CE_Failure;
+        }
+        poPanDatasetToClose = poPanDataset;
+
+        const char* pszSourceBand = CPLGetXMLValue(psPanchroBand,"SourceBand","1");
+        nPanBand = atoi(pszSourceBand);
+        if( poPanBand == NULL )
+            poPanBand = poPanDataset->GetRasterBand(nPanBand);
+        if( poPanBand == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "%s invalid band of %s",
+                     pszSourceBand, osSourceFilename.c_str());
+            GDALClose(poPanDatasetToClose);
+            return CE_Failure;
+        }
+        oMapNamesToDataset[osSourceFilename] = poPanDataset;
+        m_apoDatasetsToClose.push_back(poPanDataset);
+    }
+    else
+    {
+        poPanBand = reinterpret_cast<GDALRasterBand *>( hPanchroBandIn );
+        nPanBand = poPanBand->GetBand();
+        poPanDataset = poPanBand->GetDataset();
+        if( poPanDataset )
+            oMapNamesToDataset[CPLSPrintf("%p", poPanDataset)] = poPanDataset;
+    }
+
+    // Figure out which kind of adjustment we should do if the pan and spectral
+    // bands do not share the same geotransform
+    const char* pszGTAdjustment = CPLGetXMLValue(psOptions, "SpatialExtentAdjustment", "Union");
+    if( EQUAL(pszGTAdjustment, "Union") )
+        m_eGTAdjustment = GTAdjust_Union;
+    else if( EQUAL(pszGTAdjustment, "Intersection") )
+        m_eGTAdjustment = GTAdjust_Intersection;
+    else if( EQUAL(pszGTAdjustment, "None") )
+        m_eGTAdjustment = GTAdjust_None;
+    else if( EQUAL(pszGTAdjustment, "NoneWithoutWarning") )
+        m_eGTAdjustment = GTAdjust_NoneWithoutWarning;
+    else
+    {
+        m_eGTAdjustment = GTAdjust_Union;
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unsupported value for GeoTransformAdjustment. Defaulting to Union");
+    }
+
+    const char* pszNumThreads = CPLGetXMLValue(psOptions, "NumThreads", NULL);
+    int nThreads = 0;
+    if( pszNumThreads != NULL )
+    {
+        if( EQUAL(pszNumThreads, "ALL_CPUS") )
+            nThreads = -1;
+        else
+            nThreads = atoi(pszNumThreads);
+    }
+
+    const char* pszAlgorithm = CPLGetXMLValue(psOptions,
+                                              "Algorithm", "WeightedBrovey");
+    if( !EQUAL(pszAlgorithm, "WeightedBrovey") )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Algorithm %s unsupported", pszAlgorithm);
+        GDALClose(poPanDatasetToClose);
+        m_apoDatasetsToClose.resize(0);
+        return CE_Failure;
+    }
+
+    std::vector<double> adfWeights;
+    CPLXMLNode* psAlgOptions = CPLGetXMLNode(psOptions, "AlgorithmOptions");
+    if( psAlgOptions != NULL )
+    {
+        const char* pszWeights = CPLGetXMLValue(psAlgOptions, "Weights", NULL);
+        if( pszWeights != NULL )
+        {
+            char** papszTokens = CSLTokenizeString2(pszWeights, " ,", 0);
+            for(int i=0; papszTokens && papszTokens[i]; i++)
+                adfWeights.push_back(CPLAtof(papszTokens[i]));
+            CSLDestroy(papszTokens);
+        }
+    }
+
+    GDALRIOResampleAlg eResampleAlg = GDALRasterIOGetResampleAlg(
+                    CPLGetXMLValue(psOptions, "Resampling", "Cubic"));
+
+    std::vector<GDALRasterBand*> ahSpectralBands;
+    std::map<int, int> aMapDstBandToSpectralBand;
+    std::map<int,int>::iterator aMapDstBandToSpectralBandIter;
+    int nBitDepth = 0;
+    int bFoundNonMatchingGT = FALSE;
+    double adfPanGT[6] = { 0, 0, 0, 0, 0, 0 };
+    int bPanGeoTransformValid = FALSE;
+    if( poPanDataset )
+        bPanGeoTransformValid = ( poPanDataset->GetGeoTransform(adfPanGT) == CE_None );
+    int nPanXSize = poPanBand->GetXSize();
+    int nPanYSize = poPanBand->GetYSize();
+    double dfMinX = 0.0, dfMinY = 0.0, dfMaxX = 0.0, dfMaxY = 0.0;
+    int bFoundRotatingTerms = FALSE;
+    int bHasNoData = FALSE;
+    double dfNoData = poPanBand->GetNoDataValue(&bHasNoData);
+    double dfLRPanX = adfPanGT[0] +
+                        nPanXSize * adfPanGT[1] +
+                        nPanYSize * adfPanGT[2];
+    double dfLRPanY = adfPanGT[3] +
+                        nPanXSize * adfPanGT[4] +
+                        nPanYSize * adfPanGT[5];
+    if( bPanGeoTransformValid )
+    {
+        bFoundRotatingTerms |= (adfPanGT[2] != 0.0 || adfPanGT[4] != 0.0);
+        dfMinX = adfPanGT[0];
+        dfMaxX = dfLRPanX;
+        dfMaxY = adfPanGT[3];
+        dfMinY = dfLRPanY;
+    }
+
+    CPLString osPanProjection, osPanProjectionProj4;
+    if( poPanDataset && poPanDataset->GetProjectionRef() )
+    {
+        osPanProjection = poPanDataset->GetProjectionRef();
+        char* pszProj4 = NULL;
+        OGRSpatialReference oSRS(osPanProjection);
+        if( oSRS.exportToProj4(&pszProj4) == OGRERR_NONE )
+            osPanProjectionProj4 = pszProj4;
+        CPLFree(pszProj4);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      First pass on spectral datasets to check their georeferencing.  */
+/* -------------------------------------------------------------------- */
+    int iSpectralBand = 0;
+    for(CPLXMLNode* psIter = psOptions->psChild; psIter; psIter = psIter->psNext )
+    {
+        GDALDataset* poDataset;
+        if( psIter->eType != CXT_Element || !EQUAL(psIter->pszValue, "SpectralBand") )
+            continue;
+
+        if( nInputSpectralBandsIn  )
+        {
+            if( iSpectralBand == nInputSpectralBandsIn )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "More SpectralBand elements than in source array");
+                goto error;
+            }
+            poDataset = reinterpret_cast<GDALRasterBand *>(
+                pahInputSpectralBandsIn[iSpectralBand])->GetDataset();
+            if( poDataset )
+                osSourceFilename = poDataset->GetDescription();
+
+            oMapNamesToDataset[CPLSPrintf("%p", poDataset)] = poDataset;
+        }
+        else
+        {
+            const char* pszSourceFilename = CPLGetXMLValue(psIter, "SourceFilename", NULL);
+            if( pszSourceFilename == NULL )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "SpectralBand.SourceFilename missing");
+                goto error;
+            }
+            int bRelativeToVRT = atoi(CPLGetXMLValue( psIter, "SourceFilename.relativetoVRT", "0"));
+            if( bRelativeToVRT )
+            {
+                const char* pszAbs = CPLProjectRelativeFilename( pszVRTPathIn, pszSourceFilename );
+                m_oMapToRelativeFilenames[pszAbs] = pszSourceFilename;
+                pszSourceFilename = pszAbs;
+            }
+            osSourceFilename = pszSourceFilename;
+            poDataset = oMapNamesToDataset[osSourceFilename];
+            if( poDataset == NULL )
+            {
+                poDataset = reinterpret_cast<GDALDataset *>(
+                    GDALOpen( osSourceFilename, GA_ReadOnly ) );
+                if( poDataset == NULL )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined, "%s not a valid dataset",
+                             osSourceFilename.c_str());
+                    goto error;
+                }
+                oMapNamesToDataset[osSourceFilename] = poDataset;
+                m_apoDatasetsToClose.push_back(poDataset);
+            }
+        }
+
+        if( poDataset != NULL )
+        {
+            // Check that the spectral band has a georeferencing consistent
+            // of the pan band. Allow an error of at most the size of one pixel
+            // of the spectral band.
+            if( bPanGeoTransformValid )
+            {
+                CPLString osProjection;
+                if( poDataset->GetProjectionRef() )
+                    osProjection = poDataset->GetProjectionRef();
+
+                if( osPanProjection.size() )
+                {
+                    if( osProjection.size() )
+                    {
+                        if( osPanProjection != osProjection )
+                        {
+                            CPLString osProjectionProj4;
+                            char* pszProj4 = NULL;
+                            OGRSpatialReference oSRS(osProjection);
+                            if( oSRS.exportToProj4(&pszProj4) == OGRERR_NONE )
+                                osProjectionProj4 = pszProj4;
+                            CPLFree(pszProj4);
+
+                            if( osPanProjectionProj4 != osProjectionProj4 )
+                            {
+                                CPLError(CE_Warning, CPLE_AppDefined,
+                                         "Pan dataset and %s do not seem to have same projection. Results might be incorrect",
+                                         osSourceFilename.c_str());
+                            }
+                        }
+                    }
+                    else
+                    {
+                        CPLError(CE_Warning, CPLE_AppDefined,
+                                 "Pan dataset has a projection, whereas %s not. Results might be incorrect",
+                                 osSourceFilename.c_str());
+                    }
+                }
+                else if( osProjection.size() )
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "Pan dataset has no projection, whereas %s has one. Results might be incorrect",
+                             osSourceFilename.c_str());
+                }
+
+                double adfSpectralGeoTransform[6];
+                if( poDataset->GetGeoTransform(adfSpectralGeoTransform) == CE_None )
+                {
+                    int bIsThisOneNonMatching = FALSE;
+                    double dfPixelSize
+                        = std::max( adfSpectralGeoTransform[1],
+                                    std::abs(adfSpectralGeoTransform[5] ) );
+                    if( std::abs(adfPanGT[0] - adfSpectralGeoTransform[0]) > dfPixelSize ||
+                        std::abs(adfPanGT[3] - adfSpectralGeoTransform[3]) > dfPixelSize )
+                    {
+                        bIsThisOneNonMatching = TRUE;
+                        if( m_eGTAdjustment == GTAdjust_None )
+                        {
+                            CPLError(CE_Warning, CPLE_AppDefined,
+                                    "Georeferencing of top-left corner of pan dataset and %s do not match",
+                                    osSourceFilename.c_str());
+                        }
+                    }
+                    bFoundRotatingTerms |= (adfSpectralGeoTransform[2] != 0.0 || adfSpectralGeoTransform[4] != 0.0);
+                    double dfLRSpectralX = adfSpectralGeoTransform[0] +
+                                      poDataset->GetRasterXSize() * adfSpectralGeoTransform[1] +
+                                      poDataset->GetRasterYSize() * adfSpectralGeoTransform[2];
+                    double dfLRSpectralY = adfSpectralGeoTransform[3] +
+                                      poDataset->GetRasterXSize() * adfSpectralGeoTransform[4] +
+                                      poDataset->GetRasterYSize() * adfSpectralGeoTransform[5];
+                    if( std::abs(dfLRPanX - dfLRSpectralX) > dfPixelSize ||
+                        std::abs(dfLRPanY - dfLRSpectralY) > dfPixelSize )
+                    {
+                        bIsThisOneNonMatching = TRUE;
+                        if( m_eGTAdjustment == GTAdjust_None )
+                        {
+                            CPLError(CE_Warning, CPLE_AppDefined,
+                                    "Georeferencing of bottom-right corner of pan dataset and %s do not match",
+                                    osSourceFilename.c_str());
+                        }
+                    }
+
+                    if( bIsThisOneNonMatching && m_eGTAdjustment == GTAdjust_Union )
+                    {
+                        dfMinX = std::min(dfMinX, adfSpectralGeoTransform[0]);
+                        dfMinY = std::min(dfMinY, dfLRSpectralY);
+                        dfMaxX = std::max(dfMaxX, dfLRSpectralX);
+                        dfMaxY = std::max(dfMaxY, adfSpectralGeoTransform[3]);
+                    }
+                    else if( bIsThisOneNonMatching && m_eGTAdjustment == GTAdjust_Intersection )
+                    {
+                        dfMinX = std::max(dfMinX, adfSpectralGeoTransform[0]);
+                        dfMinY = std::max(dfMinY, dfLRSpectralY);
+                        dfMaxX = std::min(dfMaxX, dfLRSpectralX);
+                        dfMaxY = std::min(dfMaxY, adfSpectralGeoTransform[3]);
+                    }
+
+                    bFoundNonMatchingGT |= bIsThisOneNonMatching;
+                }
+            }
+        }
+
+        iSpectralBand ++;
+    }
+
+    if( nInputSpectralBandsIn && iSpectralBand != nInputSpectralBandsIn )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Less SpectralBand elements than in source array");
+        goto error;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      On-the-fly spatial extent adjustment if needed and asked.       */
+/* -------------------------------------------------------------------- */
+
+    if( bFoundNonMatchingGT &&
+            (m_eGTAdjustment == GTAdjust_Union || m_eGTAdjustment == GTAdjust_Intersection) )
+    {
+        if( bFoundRotatingTerms )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "One of the panchromatic or spectral datasets has rotating "
+                     "terms in their geotransform matrix. Adjustment not possible");
+            goto error;
+        }
+        if( m_eGTAdjustment == GTAdjust_Intersection &&
+            (dfMinX >= dfMaxX || dfMinY >= dfMaxY) )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "One of the panchromatic or spectral datasets has rotating "
+                     "terms in their geotransform matrix. Adjustment not possible");
+            goto error;
+        }
+        if( m_eGTAdjustment == GTAdjust_Union )
+            CPLDebug("VRT", "Do union of bounding box of panchromatic and spectral datasets");
+        else
+            CPLDebug("VRT", "Do intersection of bounding box of panchromatic and spectral datasets");
+
+        // If the pandataset needs adjustments, make sure the coordinates of the
+        // union/intersection properly align with the grid of the pandataset
+        // to avoid annoying sub-pixel shifts on the panchro band.
+        double dfPixelSize = std::max( adfPanGT[1], std::abs(adfPanGT[5]) );
+        if( std::abs(adfPanGT[0] - dfMinX) > dfPixelSize ||
+            std::abs(adfPanGT[3] - dfMaxY) > dfPixelSize ||
+            std::abs(dfLRPanX - dfMaxX) > dfPixelSize ||
+            std::abs(dfLRPanY - dfMinY) > dfPixelSize )
+        {
+            dfMinX = adfPanGT[0] + std::floor((dfMinX - adfPanGT[0]) / adfPanGT[1] + 0.5) * adfPanGT[1];
+            dfMaxY = adfPanGT[3] + std::floor((dfMaxY - adfPanGT[3]) / adfPanGT[5] + 0.5) * adfPanGT[5];
+            dfMaxX = dfLRPanX + std::floor((dfMaxX - dfLRPanX) / adfPanGT[1] + 0.5) * adfPanGT[1];
+            dfMinY = dfLRPanY + std::floor((dfMinY - dfLRPanY) / adfPanGT[5] + 0.5) * adfPanGT[5];
+        }
+
+        std::map<CPLString, GDALDataset*>::iterator oIter = oMapNamesToDataset.begin();
+        for(; oIter != oMapNamesToDataset.end(); ++oIter)
+        {
+            GDALDataset* poSrcDS = oIter->second;
+            double adfGT[6];
+            if( poSrcDS->GetGeoTransform(adfGT) != CE_None )
+                continue;
+
+            // Check if this dataset needs adjustments
+            dfPixelSize = std::max( adfGT[1], std::abs(adfGT[5]) );
+            dfPixelSize = std::max( adfPanGT[1], dfPixelSize );
+            dfPixelSize = std::max( std::abs(adfPanGT[5]), dfPixelSize );
+            if( std::abs(adfGT[0] - dfMinX) <= dfPixelSize &&
+                std::abs(adfGT[3] - dfMaxY) <= dfPixelSize &&
+                std::abs(adfGT[0] + poSrcDS->GetRasterXSize() * adfGT[1] - dfMaxX) <= dfPixelSize &&
+                std::abs(adfGT[3] + poSrcDS->GetRasterYSize() * adfGT[5] - dfMinY) <= dfPixelSize )
+            {
+                continue;
+            }
+
+            double adfAdjustedGT[6];
+            adfAdjustedGT[0] = dfMinX;
+            adfAdjustedGT[1] = adfGT[1];
+            adfAdjustedGT[2] = 0;
+            adfAdjustedGT[3] = dfMaxY;
+            adfAdjustedGT[4] = 0;
+            adfAdjustedGT[5] = adfGT[5];
+            int nAdjustRasterXSize = static_cast<int>(0.5 + (dfMaxX - dfMinX) / adfAdjustedGT[1]);
+            int nAdjustRasterYSize = static_cast<int>(0.5 + (dfMaxY - dfMinY) / (-adfAdjustedGT[5]));
+
+            VRTDataset* poVDS = new VRTDataset(nAdjustRasterXSize, nAdjustRasterYSize);
+            poVDS->SetWritable(FALSE);
+            poVDS->SetDescription(poSrcDS->GetDescription());
+            poVDS->SetGeoTransform(adfAdjustedGT);
+            poVDS->SetProjection(poPanDataset->GetProjectionRef());
+
+            for(int i=0;i<poSrcDS->GetRasterCount();i++)
+            {
+                GDALRasterBand* poSrcBand = poSrcDS->GetRasterBand(i+1);
+                poVDS->AddBand(poSrcBand->GetRasterDataType(), NULL);
+                VRTSourcedRasterBand* poVRTBand =
+                    reinterpret_cast<VRTSourcedRasterBand *>(
+                        poVDS->GetRasterBand(i+1) );
+
+                const char* pszNBITS = poSrcBand->GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
+                if( pszNBITS )
+                    poVRTBand->SetMetadataItem("NBITS", pszNBITS, "IMAGE_STRUCTURE");
+
+                VRTSimpleSource* poSimpleSource = new VRTSimpleSource();
+                poVRTBand->ConfigureSource( poSimpleSource,
+                                            poSrcBand,
+                                            FALSE,
+                                            static_cast<int>( std::floor((dfMinX - adfGT[0]) / adfGT[1] + 0.001) ),
+                                            static_cast<int>( std::floor((dfMaxY - adfGT[3]) / adfGT[5] + 0.001) ),
+                                            static_cast<int>(0.5 + (dfMaxX - dfMinX) / adfGT[1]),
+                                            static_cast<int>(0.5 + (dfMaxY - dfMinY) / (-adfGT[5])),
+                                            0, 0,
+                                            nAdjustRasterXSize, nAdjustRasterYSize );
+
+                poVRTBand->AddSource( poSimpleSource );
+            }
+
+            oIter->second = poVDS;
+            if( poSrcDS == poPanDataset )
+            {
+                memcpy(adfPanGT, adfAdjustedGT, 6*sizeof(double));
+                poPanDataset = poVDS;
+                poPanBand = poPanDataset->GetRasterBand(nPanBand);
+                nPanXSize = poPanDataset->GetRasterXSize();
+                nPanYSize = poPanDataset->GetRasterYSize();
+            }
+
+            m_apoDatasetsToClose.push_back(poVDS);
+        }
+    }
+
+    if( nRasterXSize == 0 && nRasterYSize == 0 )
+    {
+        nRasterXSize = nPanXSize;
+        nRasterYSize = nPanYSize;
+    }
+    else if( nRasterXSize != nPanXSize ||
+             nRasterYSize != nPanYSize )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Inconsistent declared VRT dimensions with panchro dataset");
+        goto error;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Initialize all the general VRT stuff.  This will even           */
+/*      create the VRTPansharpenedRasterBands and initialize them.      */
+/* -------------------------------------------------------------------- */
+    eErr = VRTDataset::XMLInit( psTree, pszVRTPathIn );
+
+    if( eErr != CE_None )
+    {
+        goto error;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Inherit georeferencing info from panchro band if not defined    */
+/*      in VRT.                                                         */
+/* -------------------------------------------------------------------- */
+
+    {
+        double adfOutGT[6];
+        if( GetGeoTransform(adfOutGT) != CE_None &&
+            GetGCPCount() == 0 &&
+            GetProjectionRef()[0] == '\0' )
+        {
+            if( bPanGeoTransformValid )
+            {
+                SetGeoTransform(adfPanGT);
+            }
+            if( poPanDataset &&
+                poPanDataset->GetProjectionRef() != NULL &&
+                poPanDataset->GetProjectionRef()[0] != '\0' )
+            {
+                SetProjection(poPanDataset->GetProjectionRef());
+            }
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Parse rest of PansharpeningOptions                              */
+/* -------------------------------------------------------------------- */
+    iSpectralBand = 0;
+    for(CPLXMLNode* psIter = psOptions->psChild; psIter; psIter = psIter->psNext )
+    {
+        if( psIter->eType != CXT_Element || !EQUAL(psIter->pszValue, "SpectralBand") )
+            continue;
+
+        GDALDataset* poDataset;
+        GDALRasterBand* poBand;
+
+        const char* pszDstBand = CPLGetXMLValue(psIter, "dstBand", NULL);
+        int nDstBand = -1;
+        if( pszDstBand != NULL )
+        {
+            nDstBand = atoi(pszDstBand);
+            if( nDstBand <= 0 )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "SpectralBand.dstBand = '%s' invalid",
+                         pszDstBand);
+                goto error;
+            }
+        }
+
+        if( nInputSpectralBandsIn  )
+        {
+            poBand = reinterpret_cast<GDALRasterBand *>(
+                pahInputSpectralBandsIn[iSpectralBand] );
+            poDataset = poBand->GetDataset();
+            if( poDataset )
+            {
+                poDataset = oMapNamesToDataset[CPLSPrintf("%p", poDataset)];
+                CPLAssert(poDataset);
+                if( poDataset )
+                    poBand = poDataset->GetRasterBand(poBand->GetBand());
+            }
+        }
+        else
+        {
+            const char* pszSourceFilename = CPLGetXMLValue(psIter, "SourceFilename", NULL);
+            CPLAssert(pszSourceFilename);
+            const bool bRelativeToVRT = CPL_TO_BOOL(atoi(
+                CPLGetXMLValue( psIter, "SourceFilename.relativetoVRT", "0")));
+            if( bRelativeToVRT )
+                pszSourceFilename = CPLProjectRelativeFilename( pszVRTPathIn, pszSourceFilename );
+            osSourceFilename = pszSourceFilename;
+            poDataset = oMapNamesToDataset[osSourceFilename];
+            CPLAssert(poDataset);
+            const char* pszSourceBand = CPLGetXMLValue(psIter,"SourceBand","1");
+            const int nBand = atoi(pszSourceBand);
+            poBand = poDataset->GetRasterBand(nBand);
+            if( poBand == NULL )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "%s invalid band of %s",
+                        pszSourceBand, osSourceFilename.c_str());
+                goto error;
+            }
+        }
+
+        if( bHasNoData )
+        {
+            double dfSpectralNoData = poPanBand->GetNoDataValue(&bHasNoData);
+            if( bHasNoData && dfSpectralNoData != dfNoData )
+                bHasNoData = FALSE;
+        }
+
+        ahSpectralBands.push_back(poBand);
+        if( nDstBand >= 1 )
+        {
+            if( aMapDstBandToSpectralBand.find(nDstBand-1) != aMapDstBandToSpectralBand.end() )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Another spectral band is already mapped to output band %d",
+                         nDstBand);
+                goto error;
+            }
+            aMapDstBandToSpectralBand[nDstBand-1]
+                = static_cast<int>( ahSpectralBands.size() - 1 );
+        }
+
+        iSpectralBand ++;
+    }
+
+    if( ahSpectralBands.size() == 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "No spectral band defined");
+        goto error;
+    }
+
+    {
+        const char* pszNoData = CPLGetXMLValue(psOptions, "NoData", NULL);
+        if( pszNoData )
+        {
+            if( EQUAL(pszNoData, "NONE") )
+            {
+                m_bNoDataDisabled = TRUE;
+                bHasNoData = FALSE;
+            }
+            else
+            {
+                bHasNoData = TRUE;
+                dfNoData = CPLAtof(pszNoData);
+            }
+        }
+    }
+
+    if( GetRasterCount() == 0 )
+    {
+        for( int i = 0;
+             i < static_cast<int>( aMapDstBandToSpectralBand.size()) ;
+             i++ )
+        {
+            if( aMapDstBandToSpectralBand.find(i) == aMapDstBandToSpectralBand.end() )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "Hole in SpectralBand.dstBand numbering");
+                goto error;
+            }
+            GDALRasterBand* poInputBand = reinterpret_cast<GDALRasterBand *>(
+                ahSpectralBands[aMapDstBandToSpectralBand[i]] );
+            GDALRasterBand* poBand = new VRTPansharpenedRasterBand(this, i+1,
+                                            poInputBand->GetRasterDataType());
+            poBand->SetColorInterpretation(poInputBand->GetColorInterpretation());
+            if( bHasNoData )
+                poBand->SetNoDataValue(dfNoData);
+            SetBand(i+1, poBand);
+        }
+    }
+    else
+    {
+        int nIdxAsPansharpenedBand = 0;
+        for(int i=0;i<nBands;i++)
+        {
+            if( reinterpret_cast<VRTRasterBand *>( GetRasterBand(i+1) )->IsPansharpenRasterBand() )
+            {
+                if( aMapDstBandToSpectralBand.find(i) == aMapDstBandToSpectralBand.end() )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                            "Band %d of type VRTPansharpenedRasterBand, but no corresponding SpectralBand",
+                            i+1);
+                    goto error;
+                }
+                else
+                {
+                    reinterpret_cast<VRTPansharpenedRasterBand *>( GetRasterBand(i+1) )->
+                        SetIndexAsPansharpenedBand(nIdxAsPansharpenedBand);
+                    nIdxAsPansharpenedBand ++;
+                }
+            }
+        }
+    }
+
+    // Figure out bit depth
+    {
+        const char* pszBitDepth = CPLGetXMLValue(psOptions, "BitDepth", NULL);
+        if( pszBitDepth == NULL )
+            pszBitDepth = reinterpret_cast<GDALRasterBand *>(
+                ahSpectralBands[0] )->GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
+        if( pszBitDepth )
+            nBitDepth = atoi(pszBitDepth);
+        if( nBitDepth )
+        {
+            for(int i=0;i<nBands;i++)
+            {
+                if( !reinterpret_cast<VRTRasterBand *>(
+                       GetRasterBand(i+1) )->IsPansharpenRasterBand() )
+                    continue;
+                if( GetRasterBand(i+1)->GetMetadataItem("NBITS", "IMAGE_STRUCTURE") == NULL )
+                {
+                    if( nBitDepth != 8 && nBitDepth != 16 && nBitDepth != 32 )
+                    {
+                        GetRasterBand(i+1)->SetMetadataItem("NBITS",
+                                        CPLSPrintf("%d", nBitDepth), "IMAGE_STRUCTURE");
+                    }
+                }
+                else if( nBitDepth == 8 || nBitDepth == 16 || nBitDepth == 32 )
+                {
+                    GetRasterBand(i+1)->SetMetadataItem("NBITS", NULL, "IMAGE_STRUCTURE");
+                }
+            }
+        }
+    }
+
+    if( GDALGetRasterBandXSize(ahSpectralBands[0]) > GDALGetRasterBandXSize(poPanBand) ||
+        GDALGetRasterBandYSize(ahSpectralBands[0]) > GDALGetRasterBandYSize(poPanBand) )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Dimensions of spectral band larger than panchro band");
+    }
+
+    aMapDstBandToSpectralBandIter = aMapDstBandToSpectralBand.begin();
+    for(; aMapDstBandToSpectralBandIter != aMapDstBandToSpectralBand.end();
+          ++aMapDstBandToSpectralBandIter )
+    {
+        const int nDstBand = 1 + aMapDstBandToSpectralBandIter->first;
+        if( nDstBand > nBands || !reinterpret_cast<VRTRasterBand*>(
+               GetRasterBand(nDstBand) )->IsPansharpenRasterBand() )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "SpectralBand.dstBand = '%d' invalid",
+                        nDstBand);
+            goto error;
+        }
+    }
+
+    if( adfWeights.size() == 0 )
+    {
+        for( int i = 0; i < static_cast<int>( ahSpectralBands.size() ); i++ )
+        {
+            adfWeights.push_back(1.0 / ahSpectralBands.size());
+        }
+    }
+    else if( adfWeights.size() != ahSpectralBands.size() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "%d weights defined, but %d input spectral bands",
+                 static_cast<int>( adfWeights.size() ),
+                 static_cast<int>( ahSpectralBands.size() ) );
+        goto error;
+    }
+
+    if( aMapDstBandToSpectralBand.size() == 0 )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "No spectral band is mapped to an output band");
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Instantiate poPansharpener                                      */
+/* -------------------------------------------------------------------- */
+    psPanOptions = GDALCreatePansharpenOptions();
+    psPanOptions->ePansharpenAlg = GDAL_PSH_WEIGHTED_BROVEY;
+    psPanOptions->eResampleAlg = eResampleAlg;
+    psPanOptions->nBitDepth = nBitDepth;
+    psPanOptions->nWeightCount = static_cast<int>( adfWeights.size() );
+    psPanOptions->padfWeights = reinterpret_cast<double *>(
+        CPLMalloc( sizeof(double) * adfWeights.size() ) );
+    memcpy(psPanOptions->padfWeights, &adfWeights[0],
+           sizeof(double)*adfWeights.size());
+    psPanOptions->hPanchroBand = poPanBand;
+    psPanOptions->nInputSpectralBands
+        = static_cast<int>( ahSpectralBands.size() );
+    psPanOptions->pahInputSpectralBands = reinterpret_cast<GDALRasterBandH *>(
+        CPLMalloc( sizeof(GDALRasterBandH) * ahSpectralBands.size() ) );
+    memcpy(psPanOptions->pahInputSpectralBands, &ahSpectralBands[0],
+           sizeof(GDALRasterBandH)*ahSpectralBands.size());
+    psPanOptions->nOutPansharpenedBands
+        = static_cast<int>( aMapDstBandToSpectralBand.size() );
+    psPanOptions->panOutPansharpenedBands = reinterpret_cast<int *>(
+        CPLMalloc( sizeof(int) * aMapDstBandToSpectralBand.size() ) );
+    aMapDstBandToSpectralBandIter = aMapDstBandToSpectralBand.begin();
+    for(int i = 0; aMapDstBandToSpectralBandIter != aMapDstBandToSpectralBand.end();
+          ++aMapDstBandToSpectralBandIter, ++i )
+    {
+        psPanOptions->panOutPansharpenedBands[i] = aMapDstBandToSpectralBandIter->second;
+    }
+    psPanOptions->bHasNoData = bHasNoData;
+    psPanOptions->dfNoData = dfNoData;
+    psPanOptions->nThreads = nThreads;
+    psPanOptions->dfMSShiftX = CPLAtof(CPLGetXMLValue(psOptions, "MSShiftX", "0"));
+    psPanOptions->dfMSShiftY = CPLAtof(CPLGetXMLValue(psOptions, "MSShiftY", "0"));
+
+    if( nBands == psPanOptions->nOutPansharpenedBands )
+        SetMetadataItem("INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE");
+
+    m_poPansharpener = new GDALPansharpenOperation();
+    eErr = m_poPansharpener->Initialize(psPanOptions);
+    if( eErr != CE_None )
+    {
+        // Close in reverse order (VRT firsts and real datasets after)
+        for( int i = static_cast<int>( m_apoDatasetsToClose.size() ) - 1;
+             i >= 0;
+             i-- )
+        {
+            GDALClose(m_apoDatasetsToClose[i]);
+        }
+        m_apoDatasetsToClose.resize(0);
+
+        delete m_poPansharpener;
+        m_poPansharpener = NULL;
+    }
+    GDALDestroyPansharpenOptions(psPanOptions);
+
+    return eErr;
+
+error:
+    // Close in reverse order (VRT firsts and real datasets after)
+    for( int i = static_cast<int>( m_apoDatasetsToClose.size() ) - 1;
+         i >= 0;
+         i-- )
+    {
+        GDALClose(m_apoDatasetsToClose[i]);
+    }
+    m_apoDatasetsToClose.resize(0);
+    return CE_Failure;
+}
+
+/************************************************************************/
+/*                           SerializeToXML()                           */
+/************************************************************************/
+
+CPLXMLNode *VRTPansharpenedDataset::SerializeToXML( const char *pszVRTPathIn )
+
+{
+    CPLXMLNode *psTree = VRTDataset::SerializeToXML( pszVRTPathIn );
+
+    if( psTree == NULL )
+        return psTree;
+
+/* -------------------------------------------------------------------- */
+/*      Set subclass.                                                   */
+/* -------------------------------------------------------------------- */
+    CPLCreateXMLNode(
+        CPLCreateXMLNode( psTree, CXT_Attribute, "subClass" ),
+        CXT_Text, "VRTPansharpenedDataset" );
+
+/* -------------------------------------------------------------------- */
+/*      Serialize the block size.                                       */
+/* -------------------------------------------------------------------- */
+    CPLCreateXMLElementAndValue( psTree, "BlockXSize",
+                                 CPLSPrintf( "%d", m_nBlockXSize ) );
+    CPLCreateXMLElementAndValue( psTree, "BlockYSize",
+                                 CPLSPrintf( "%d", m_nBlockYSize ) );
+
+/* -------------------------------------------------------------------- */
+/*      Serialize the options.                                          */
+/* -------------------------------------------------------------------- */
+    if( m_poPansharpener == NULL )
+        return psTree;
+    GDALPansharpenOptions* psOptions = m_poPansharpener->GetOptions();
+    if( psOptions == NULL )
+        return psTree;
+
+    CPLXMLNode* psOptionsNode = CPLCreateXMLNode(psTree, CXT_Element, "PansharpeningOptions");
+
+    if( psOptions->ePansharpenAlg == GDAL_PSH_WEIGHTED_BROVEY )
+    {
+        CPLCreateXMLElementAndValue( psOptionsNode, "Algorithm", "WeightedBrovey" );
+    }
+    else
+    {
+        CPLAssert(FALSE);
+    }
+    if( psOptions->nWeightCount )
+    {
+        CPLString osWeights;
+        for(int i=0;i<psOptions->nWeightCount;i++)
+        {
+            if( i ) osWeights += ",";
+            osWeights += CPLSPrintf("%.16g", psOptions->padfWeights[i]);
+        }
+        CPLCreateXMLElementAndValue(
+            CPLCreateXMLNode(psOptionsNode, CXT_Element, "AlgorithmOptions"),
+            "Weights", osWeights.c_str() );
+    }
+    CPLCreateXMLElementAndValue( psOptionsNode, "Resampling",
+                                 GDALRasterIOGetResampleAlg(psOptions->eResampleAlg) );
+
+    if( psOptions->nThreads == -1 )
+    {
+        CPLCreateXMLElementAndValue( psOptionsNode, "NumThreads", "ALL_CPUS" );
+    }
+    else if( psOptions->nThreads > 1 )
+    {
+        CPLCreateXMLElementAndValue( psOptionsNode, "NumThreads",
+                                     CPLSPrintf("%d", psOptions->nThreads) );
+    }
+
+    if( psOptions->nBitDepth )
+        CPLCreateXMLElementAndValue( psOptionsNode, "BitDepth",
+                                     CPLSPrintf("%d", psOptions->nBitDepth) );
+
+    const char* pszAdjust = NULL;
+    switch( m_eGTAdjustment )
+    {
+        case GTAdjust_Union:
+            pszAdjust = "Union";
+            break;
+        case GTAdjust_Intersection:
+            pszAdjust = "Intersection";
+            break;
+        case GTAdjust_None:
+            pszAdjust = "None";
+            break;
+        case GTAdjust_NoneWithoutWarning:
+            pszAdjust = "NoneWithoutWarning";
+            break;
+        default:
+            break;
+    }
+
+    if( psOptions->bHasNoData )
+    {
+        CPLCreateXMLElementAndValue( psOptionsNode, "NoData",
+                                     CPLSPrintf("%.16g", psOptions->dfNoData) );
+    }
+    else if( m_bNoDataDisabled )
+    {
+        CPLCreateXMLElementAndValue( psOptionsNode, "NoData", "None" );
+    }
+
+    if( psOptions->dfMSShiftX )
+    {
+        CPLCreateXMLElementAndValue( psOptionsNode, "MSShiftX",
+                                     CPLSPrintf("%.16g", psOptions->dfMSShiftX) );
+    }
+    if( psOptions->dfMSShiftY )
+    {
+        CPLCreateXMLElementAndValue( psOptionsNode, "MSShiftY",
+                                     CPLSPrintf("%.16g", psOptions->dfMSShiftY) );
+    }
+
+    if( pszAdjust )
+        CPLCreateXMLElementAndValue( psOptionsNode, "SpatialExtentAdjustment", pszAdjust);
+
+    if( psOptions->hPanchroBand )
+    {
+         CPLXMLNode* psBand = CPLCreateXMLNode(psOptionsNode, CXT_Element, "PanchroBand");
+         GDALRasterBand* poBand = reinterpret_cast<GDALRasterBand *>(
+             psOptions->hPanchroBand );
+         if( poBand->GetDataset() )
+         {
+             std::map<CPLString,CPLString>::iterator oIter =
+                m_oMapToRelativeFilenames.find(poBand->GetDataset()->GetDescription());
+             if( oIter == m_oMapToRelativeFilenames.end() )
+             {
+                CPLCreateXMLElementAndValue( psBand, "SourceFilename", poBand->GetDataset()->GetDescription() );
+             }
+             else
+             {
+                 CPLXMLNode* psSourceFilename =
+                    CPLCreateXMLElementAndValue( psBand, "SourceFilename", oIter->second );
+                 CPLCreateXMLNode(
+                    CPLCreateXMLNode( psSourceFilename,
+                                      CXT_Attribute, "relativeToVRT" ),
+                    CXT_Text, "1" );
+             }
+             CPLCreateXMLElementAndValue( psBand, "SourceBand", CPLSPrintf("%d", poBand->GetBand()) );
+         }
+    }
+    for(int i=0;i<psOptions->nInputSpectralBands;i++)
+    {
+        CPLXMLNode* psBand = CPLCreateXMLNode(psOptionsNode, CXT_Element, "SpectralBand");
+
+        for(int j=0;j<psOptions->nOutPansharpenedBands;j++)
+        {
+            if( psOptions->panOutPansharpenedBands[j] == i )
+            {
+                for(int k=0;k<nBands;k++)
+                {
+                    if( reinterpret_cast<VRTRasterBand *>(
+                           GetRasterBand(k+1) )->IsPansharpenRasterBand() )
+                    {
+                        if( reinterpret_cast<VRTPansharpenedRasterBand *>(
+                               GetRasterBand(k+1) )->GetIndexAsPansharpenedBand() == j )
+                        {
+                            CPLCreateXMLNode(
+                                CPLCreateXMLNode( psBand,
+                                                  CXT_Attribute, "dstBand" ),
+                                CXT_Text, CPLSPrintf("%d", k+1) );
+                            break;
+                        }
+                    }
+                }
+                break;
+            }
+        }
+
+        GDALRasterBand* poBand = reinterpret_cast<GDALRasterBand *>(
+            psOptions->pahInputSpectralBands[i] );
+        if( poBand->GetDataset() )
+        {
+            std::map<CPLString,CPLString>::iterator oIter =
+                m_oMapToRelativeFilenames.find(poBand->GetDataset()->GetDescription());
+            if( oIter == m_oMapToRelativeFilenames.end() )
+            {
+                CPLCreateXMLElementAndValue( psBand, "SourceFilename", poBand->GetDataset()->GetDescription() );
+            }
+            else
+            {
+                CPLXMLNode* psSourceFilename =
+                    CPLCreateXMLElementAndValue( psBand, "SourceFilename", oIter->second );
+                CPLCreateXMLNode(
+                    CPLCreateXMLNode( psSourceFilename,
+                                      CXT_Attribute, "relativeToVRT" ),
+                    CXT_Text, "1" );
+            }
+            CPLCreateXMLElementAndValue( psBand, "SourceBand", CPLSPrintf("%d", poBand->GetBand()) );
+        }
+    }
+
+    return psTree;
+}
+
+/************************************************************************/
+/*                            GetBlockSize()                            */
+/************************************************************************/
+
+void VRTPansharpenedDataset::GetBlockSize( int *pnBlockXSize, int *pnBlockYSize )
+
+{
+    assert( NULL != pnBlockXSize );
+    assert( NULL != pnBlockYSize );
+
+    *pnBlockXSize = m_nBlockXSize;
+    *pnBlockYSize = m_nBlockYSize;
+}
+
+/************************************************************************/
+/*                              AddBand()                               */
+/************************************************************************/
+
+CPLErr VRTPansharpenedDataset::AddBand( CPL_UNUSED GDALDataType eType,
+                                        CPL_UNUSED char **papszOptions )
+
+{
+    CPLError(CE_Failure, CPLE_NotSupported, "AddBand() not supported");
+
+    return CE_Failure;
+}
+
+
+/************************************************************************/
+/*                              IRasterIO()                             */
+/************************************************************************/
+
+CPLErr VRTPansharpenedDataset::IRasterIO( GDALRWFlag eRWFlag,
+                               int nXOff, int nYOff, int nXSize, int nYSize,
+                               void * pData, int nBufXSize, int nBufYSize,
+                               GDALDataType eBufType,
+                               int nBandCount, int *panBandMap,
+                               GSpacing nPixelSpace, GSpacing nLineSpace,
+                               GSpacing nBandSpace,
+                               GDALRasterIOExtraArg* psExtraArg)
+{
+    if( eRWFlag == GF_Write )
+        return CE_Failure;
+
+    /* Try to pass the request to the most appropriate overview dataset */
+    if( nBufXSize < nXSize && nBufYSize < nYSize )
+    {
+        int bTried;
+        CPLErr eErr = TryOverviewRasterIO( eRWFlag,
+                                    nXOff, nYOff, nXSize, nYSize,
+                                    pData, nBufXSize, nBufYSize,
+                                    eBufType,
+                                    nBandCount, panBandMap,
+                                    nPixelSpace, nLineSpace,
+                                    nBandSpace,
+                                    psExtraArg,
+                                    &bTried );
+        if( bTried )
+            return eErr;
+    }
+
+    const int nDataTypeSize = GDALGetDataTypeSize(eBufType) / 8;
+    if( nXSize == nBufXSize &&
+        nYSize == nBufYSize &&
+        nDataTypeSize == nPixelSpace &&
+        nLineSpace == nPixelSpace * nBufXSize &&
+        nBandSpace == nLineSpace * nBufYSize &&
+        nBandCount == nBands )
+    {
+        for(int i=0;i<nBands;i++)
+        {
+            if( panBandMap[i] != i + 1 ||
+                !reinterpret_cast<VRTRasterBand *>(
+                    GetRasterBand(i+1) )->IsPansharpenRasterBand() )
+            {
+                goto default_path;
+            }
+        }
+
+        //{static int bDone = 0; if (!bDone) printf("(2)\n"); bDone = 1; }
+        return m_poPansharpener->ProcessRegion(
+                    nXOff, nYOff, nXSize, nYSize, pData, eBufType);
+
+    }
+
+default_path:
+    //{static int bDone = 0; if (!bDone) printf("(3)\n"); bDone = 1; }
+    return VRTDataset::IRasterIO(
+            eRWFlag, nXOff, nYOff, nXSize, nYSize,
+            pData, nBufXSize, nBufYSize, eBufType,
+            nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace, psExtraArg);
+}
+
+/************************************************************************/
+/* ==================================================================== */
+/*                        VRTPansharpenedRasterBand                     */
+/* ==================================================================== */
+/************************************************************************/
+
+/************************************************************************/
+/*                        VRTPansharpenedRasterBand()                   */
+/************************************************************************/
+
+VRTPansharpenedRasterBand::VRTPansharpenedRasterBand( GDALDataset *poDSIn, int nBandIn,
+                                                      GDALDataType eDataTypeIn ) :
+    m_nIndexAsPansharpenedBand(nBandIn - 1)
+{
+    Initialize( poDSIn->GetRasterXSize(), poDSIn->GetRasterYSize() );
+
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
+    this->eAccess = GA_Update;
+    this->eDataType = eDataTypeIn;
+
+    reinterpret_cast<VRTPansharpenedDataset *>(
+        poDS )->GetBlockSize( &nBlockXSize, &nBlockYSize );
+}
+
+/************************************************************************/
+/*                        ~VRTPansharpenedRasterBand()                  */
+/************************************************************************/
+
+VRTPansharpenedRasterBand::~VRTPansharpenedRasterBand()
+
+{
+    FlushCache();
+}
+
+/************************************************************************/
+/*                             IReadBlock()                             */
+/************************************************************************/
+
+CPLErr VRTPansharpenedRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
+                                              void * pImage )
+
+{
+    const int nReqXOff = nBlockXOff * nBlockXSize;
+    const int nReqYOff = nBlockYOff * nBlockYSize;
+    int nReqXSize = nBlockXSize;
+    int nReqYSize = nBlockYSize;
+    if( nReqXOff + nReqXSize > nRasterXSize )
+        nReqXSize = nRasterXSize - nReqXOff;
+    if( nReqYOff + nReqYSize > nRasterYSize )
+        nReqYSize = nRasterYSize - nReqYOff;
+
+    //{static int bDone = 0; if (!bDone) printf("(4)\n"); bDone = 1; }
+    const int nDataTypeSize = GDALGetDataTypeSize(eDataType) / 8;
+    GDALRasterIOExtraArg sExtraArg;
+    INIT_RASTERIO_EXTRA_ARG(sExtraArg);
+    if( IRasterIO( GF_Read, nReqXOff, nReqYOff, nReqXSize, nReqYSize,
+                   pImage, nReqXSize, nReqYSize, eDataType,
+                   nDataTypeSize, nDataTypeSize * nReqXSize,
+                   &sExtraArg ) != CE_None )
+    {
+        return CE_Failure;
+    }
+
+    if( nReqXSize < nBlockXSize )
+    {
+        for(int j=nReqYSize-1;j>=0;j--)
+        {
+            memmove( reinterpret_cast<GByte *>( pImage ) + j * nDataTypeSize * nBlockXSize,
+                     reinterpret_cast<GByte *>( pImage ) + j * nDataTypeSize * nReqXSize,
+                     nReqXSize * nDataTypeSize );
+            memset( reinterpret_cast<GByte *>( pImage ) + (j * nBlockXSize + nReqXSize) * nDataTypeSize,
+                    0,
+                    (nBlockXSize - nReqXSize) * nDataTypeSize );
+        }
+    }
+    if( nReqYSize < nBlockYSize )
+    {
+        memset( reinterpret_cast<GByte *>( pImage ) + nReqYSize * nBlockXSize * nDataTypeSize,
+                0,
+                (nBlockYSize - nReqYSize ) * nBlockXSize * nDataTypeSize );
+    }
+
+    // Cache other bands
+    CPLErr eErr = CE_None;
+    VRTPansharpenedDataset* poGDS
+        = reinterpret_cast<VRTPansharpenedDataset *>( poDS );
+    if( poGDS->nBands != 1 && !poGDS->m_bLoadingOtherBands )
+    {
+        poGDS->m_bLoadingOtherBands = TRUE;
+
+        for( int iOtherBand = 1; iOtherBand <= poGDS->nBands; iOtherBand++ )
+        {
+            if( iOtherBand == nBand )
+                continue;
+
+            GDALRasterBlock *poBlock;
+
+            poBlock = poGDS->GetRasterBand(iOtherBand)->
+                GetLockedBlockRef(nBlockXOff,nBlockYOff);
+            if (poBlock == NULL)
+            {
+                eErr = CE_Failure;
+                break;
+            }
+            poBlock->DropLock();
+        }
+
+        poGDS->m_bLoadingOtherBands = FALSE;
+    }
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                              IRasterIO()                             */
+/************************************************************************/
+
+CPLErr VRTPansharpenedRasterBand::IRasterIO( GDALRWFlag eRWFlag,
+                               int nXOff, int nYOff, int nXSize, int nYSize,
+                               void * pData, int nBufXSize, int nBufYSize,
+                               GDALDataType eBufType,
+                               GSpacing nPixelSpace, GSpacing nLineSpace,
+                               GDALRasterIOExtraArg* psExtraArg)
+{
+    if( eRWFlag == GF_Write )
+        return CE_Failure;
+
+    VRTPansharpenedDataset* poGDS
+        = reinterpret_cast<VRTPansharpenedDataset *>( poDS );
+
+    /* Try to pass the request to the most appropriate overview dataset */
+    if( nBufXSize < nXSize && nBufYSize < nYSize )
+    {
+        int bTried;
+        CPLErr eErr = TryOverviewRasterIO( eRWFlag,
+                                    nXOff, nYOff, nXSize, nYSize,
+                                    pData, nBufXSize, nBufYSize,
+                                    eBufType,
+                                    nPixelSpace, nLineSpace,
+                                    psExtraArg,
+                                    &bTried );
+        if( bTried )
+            return eErr;
+    }
+
+    const int nDataTypeSize = GDALGetDataTypeSize(eBufType) / 8;
+    if( nXSize == nBufXSize &&
+        nYSize == nBufYSize &&
+        nDataTypeSize == nPixelSpace &&
+        nLineSpace == nPixelSpace * nBufXSize )
+    {
+        GDALPansharpenOptions* psOptions = poGDS->m_poPansharpener->GetOptions();
+
+        // Have we already done this request for another band ?
+        // If so use the cached result
+        const size_t nBufferSizePerBand
+            = static_cast<size_t>( nXSize * nYSize * nDataTypeSize );
+        if( nXOff == poGDS->m_nLastBandRasterIOXOff &&
+            nYOff >= poGDS->m_nLastBandRasterIOYOff &&
+            nXSize == poGDS->m_nLastBandRasterIOXSize &&
+            nYOff + nYSize <= poGDS->m_nLastBandRasterIOYOff + poGDS->m_nLastBandRasterIOYSize &&
+            eBufType == poGDS->m_eLastBandRasterIODataType )
+        {
+            //{static int bDone = 0; if (!bDone) printf("(6)\n"); bDone = 1; }
+            if( poGDS->m_pabyLastBufferBandRasterIO == NULL )
+                return CE_Failure;
+            const size_t nBufferSizePerBandCached
+                = static_cast<size_t>( nXSize ) * poGDS->m_nLastBandRasterIOYSize
+                * nDataTypeSize;
+            memcpy(pData,
+                   poGDS->m_pabyLastBufferBandRasterIO +
+                        nBufferSizePerBandCached * m_nIndexAsPansharpenedBand +
+                        (nYOff - poGDS->m_nLastBandRasterIOYOff) * nXSize * nDataTypeSize,
+                   nBufferSizePerBand);
+            return CE_None;
+        }
+
+        int nYSizeToCache = nYSize;
+        if( nYSize == 1 && nXSize == nRasterXSize )
+        {
+            //{static int bDone = 0; if (!bDone) printf("(7)\n"); bDone = 1; }
+            // For efficiency, try to cache at leak 256 K
+            nYSizeToCache = (256 * 1024) / (nXSize * nDataTypeSize);
+            if( nYSizeToCache == 0 )
+                nYSizeToCache = 1;
+            else if( nYOff + nYSizeToCache > nRasterYSize )
+                nYSizeToCache = nRasterYSize - nYOff;
+        }
+        const GIntBig nBufferSize
+            = static_cast<GIntBig>( nXSize ) * nYSizeToCache * nDataTypeSize
+            * psOptions->nOutPansharpenedBands;
+        // TODO: This double static cast seems bogus.
+        if( static_cast<GIntBig>( static_cast<size_t>( nBufferSize ) )
+            != nBufferSize )
+        {
+            CPLError(CE_Failure, CPLE_OutOfMemory,
+                 "Out of memory error while allocating working buffers");
+            return CE_Failure;
+        }
+        GByte* pabyTemp = reinterpret_cast<GByte *>(
+            VSI_REALLOC_VERBOSE( poGDS->m_pabyLastBufferBandRasterIO,
+                        static_cast<size_t>( nBufferSize) ) );
+        if( pabyTemp == NULL )
+        {
+            return CE_Failure;
+        }
+        poGDS->m_nLastBandRasterIOXOff = nXOff;
+        poGDS->m_nLastBandRasterIOYOff = nYOff;
+        poGDS->m_nLastBandRasterIOXSize = nXSize;
+        poGDS->m_nLastBandRasterIOYSize = nYSizeToCache;
+        poGDS->m_eLastBandRasterIODataType = eBufType;
+        poGDS->m_pabyLastBufferBandRasterIO = pabyTemp;
+
+        CPLErr eErr = poGDS->m_poPansharpener->ProcessRegion(
+                            nXOff, nYOff, nXSize, nYSizeToCache,
+                            poGDS->m_pabyLastBufferBandRasterIO, eBufType);
+        if( eErr == CE_None )
+        {
+            //{static int bDone = 0; if (!bDone) printf("(8)\n"); bDone = 1; }
+            size_t nBufferSizePerBandCached
+                = static_cast<size_t>( nXSize ) * poGDS->m_nLastBandRasterIOYSize
+                * nDataTypeSize;
+            memcpy(pData,
+                   poGDS->m_pabyLastBufferBandRasterIO +
+                        nBufferSizePerBandCached * m_nIndexAsPansharpenedBand,
+                   nBufferSizePerBand);
+        }
+        else
+        {
+            VSIFree(poGDS->m_pabyLastBufferBandRasterIO);
+            poGDS->m_pabyLastBufferBandRasterIO = NULL;
+        }
+        return eErr;
+    }
+
+    //{static int bDone = 0; if (!bDone) printf("(9)\n"); bDone = 1; }
+    CPLErr eErr = VRTRasterBand::IRasterIO(
+            eRWFlag, nXOff, nYOff, nXSize, nYSize,
+            pData, nBufXSize, nBufYSize, eBufType,
+            nPixelSpace, nLineSpace, psExtraArg);
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                              XMLInit()                               */
+/************************************************************************/
+
+CPLErr VRTPansharpenedRasterBand::XMLInit( CPLXMLNode * psTree,
+                                  const char *pszVRTPathIn )
+
+{
+    return VRTRasterBand::XMLInit( psTree, pszVRTPathIn );
+}
+
+/************************************************************************/
+/*                           SerializeToXML()                           */
+/************************************************************************/
+
+CPLXMLNode *VRTPansharpenedRasterBand::SerializeToXML( const char *pszVRTPathIn )
+
+{
+    CPLXMLNode *psTree = VRTRasterBand::SerializeToXML( pszVRTPathIn );
+
+/* -------------------------------------------------------------------- */
+/*      Set subclass.                                                   */
+/* -------------------------------------------------------------------- */
+    CPLCreateXMLNode(
+        CPLCreateXMLNode( psTree, CXT_Attribute, "subClass" ),
+        CXT_Text, "VRTPansharpenedRasterBand" );
+
+    return psTree;
+}
+
+/************************************************************************/
+/*                         GetOverviewCount()                           */
+/************************************************************************/
+
+int VRTPansharpenedRasterBand::GetOverviewCount()
+{
+    VRTPansharpenedDataset* poGDS
+        = reinterpret_cast<VRTPansharpenedDataset *>( poDS );
+
+    // Build on-the-fly overviews from overviews of pan and spectral bands
+    if( poGDS->m_poPansharpener != NULL &&
+        poGDS->m_apoOverviewDatasets.size() == 0 &&
+        poGDS->m_poMainDataset == poGDS )
+    {
+        GDALPansharpenOptions* psOptions = poGDS->m_poPansharpener->GetOptions();
+
+        GDALRasterBand* poPanBand
+            = reinterpret_cast<GDALRasterBand *>( psOptions->hPanchroBand );
+        const int nPanOvrCount = poPanBand->GetOverviewCount();
+        if( nPanOvrCount > 0 )
+        {
+            for(int i=0;i<poGDS->GetRasterCount();i++)
+            {
+                if( !reinterpret_cast<VRTRasterBand *>(
+                       poGDS->GetRasterBand(i+1) )->IsPansharpenRasterBand() )
+                {
+                    return 0;
+                }
+            }
+
+            int nSpectralOvrCount = reinterpret_cast<GDALRasterBand *>(
+                psOptions->pahInputSpectralBands[0] )->GetOverviewCount();
+            // JP2KAK overviews are not bound to a dataset, so let the full resolution bands
+            // and rely on JP2KAK IRasterIO() to select the appropriate resolution
+            if( nSpectralOvrCount && reinterpret_cast<GDALRasterBand *>( psOptions->pahInputSpectralBands[0] )->GetOverview(0)->GetDataset() == NULL )
+                nSpectralOvrCount = 0;
+            for(int i=1;i<psOptions->nInputSpectralBands;i++)
+            {
+                if( reinterpret_cast<GDALRasterBand *>(
+                       psOptions->pahInputSpectralBands[i])->GetOverviewCount()
+                    != nSpectralOvrCount )
+                {
+                    nSpectralOvrCount = 0;
+                    break;
+                }
+            }
+            for(int j=0;j<nPanOvrCount;j++)
+            {
+                GDALRasterBand* poPanOvrBand = poPanBand->GetOverview(j);
+                VRTPansharpenedDataset* poOvrDS
+                    = new VRTPansharpenedDataset( poPanOvrBand->GetXSize(),
+                                                  poPanOvrBand->GetYSize() );
+                poOvrDS->m_poMainDataset = poGDS;
+                for(int i=0;i<poGDS->GetRasterCount();i++)
+                {
+                    GDALRasterBand* poSrcBand = poGDS->GetRasterBand(i+1);
+                    GDALRasterBand* poBand
+                        = new VRTPansharpenedRasterBand(
+                            poOvrDS, i+1, poSrcBand->GetRasterDataType());
+                    const char* pszNBITS
+                        = poSrcBand->GetMetadataItem("NBITS",
+                                                     "IMAGE_STRUCTURE");
+                    if( pszNBITS )
+                        poBand->SetMetadataItem("NBITS", pszNBITS,
+                                                "IMAGE_STRUCTURE");
+                    poOvrDS->SetBand(i+1, poBand);
+                }
+
+                GDALPansharpenOptions* psPanOvrOptions
+                    = GDALClonePansharpenOptions(psOptions);
+                psPanOvrOptions->hPanchroBand = poPanOvrBand;
+                if( nSpectralOvrCount > 0 )
+                {
+                    for(int i=0;i<psOptions->nInputSpectralBands;i++)
+                    {
+                        psPanOvrOptions->pahInputSpectralBands[i] =
+                            reinterpret_cast<GDALRasterBand *>(
+                                psOptions->pahInputSpectralBands[i] )->GetOverview(
+                                    (j < nSpectralOvrCount) ? j : nSpectralOvrCount - 1 );
+                    }
+                }
+                poOvrDS->m_poPansharpener = new GDALPansharpenOperation();
+                if (poOvrDS->m_poPansharpener->Initialize(psPanOvrOptions) != CE_None)
+                {
+                    CPLError( CE_Warning, CPLE_AppDefined,
+                              "Unable to initialize pansharpener." );
+                }
+                GDALDestroyPansharpenOptions(psPanOvrOptions);
+
+                poOvrDS->SetMetadataItem("INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE");
+
+                poGDS->m_apoOverviewDatasets.push_back(poOvrDS);
+            }
+        }
+    }
+    return static_cast<int>( poGDS->m_apoOverviewDatasets.size() );
+}
+
+/************************************************************************/
+/*                            GetOverview()                             */
+/************************************************************************/
+
+GDALRasterBand* VRTPansharpenedRasterBand::GetOverview(int iOvr)
+{
+    if( iOvr < 0 || iOvr >= GetOverviewCount() )
+        return NULL;
+
+    VRTPansharpenedDataset* poGDS
+        = reinterpret_cast<VRTPansharpenedDataset *>( poDS );
+
+    return poGDS->m_apoOverviewDatasets[iOvr]->GetRasterBand(nBand);
+}
diff --git a/frmts/vrt/vrtrasterband.cpp b/frmts/vrt/vrtrasterband.cpp
index 4be9ccb..b2fbd1b 100644
--- a/frmts/vrt/vrtrasterband.cpp
+++ b/frmts/vrt/vrtrasterband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtrasterband.cpp 31003 2015-10-14 16:19:20Z rouault $
+ * $Id: vrtrasterband.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTRasterBand
@@ -32,7 +32,9 @@
 #include "cpl_minixml.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: vrtrasterband.cpp 31003 2015-10-14 16:19:20Z rouault $");
+#include <algorithm>
+
+CPL_CVSID("$Id: vrtrasterband.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -64,25 +66,25 @@ void VRTRasterBand::Initialize( int nXSize, int nYSize )
 
     nRasterXSize = nXSize;
     nRasterYSize = nYSize;
-    
-    nBlockXSize = MIN(128,nXSize);
-    nBlockYSize = MIN(128,nYSize);
 
-    bIsMaskBand = FALSE;
-    bNoDataValueSet = FALSE;
-    bHideNoDataValue = FALSE;
-    dfNoDataValue = -10000.0;
-    poColorTable = NULL;
-    eColorInterp = GCI_Undefined;
+    nBlockXSize = std::min( 128, nXSize );
+    nBlockYSize = std::min( 128, nYSize );
+
+    m_bIsMaskBand = FALSE;
+    m_bNoDataValueSet = FALSE;
+    m_bHideNoDataValue = FALSE;
+    m_dfNoDataValue = -10000.0;
+    m_poColorTable = NULL;
+    m_eColorInterp = GCI_Undefined;
 
-    pszUnitType = NULL;
-    papszCategoryNames = NULL;
-    dfOffset = 0.0;
-    dfScale = 1.0;
+    m_pszUnitType = NULL;
+    m_papszCategoryNames = NULL;
+    m_dfOffset = 0.0;
+    m_dfScale = 1.0;
 
-    psSavedHistograms = NULL;
+    m_psSavedHistograms = NULL;
 
-    poMaskBand = NULL;
+    m_poMaskBand = NULL;
 }
 
 /************************************************************************/
@@ -92,16 +94,16 @@ void VRTRasterBand::Initialize( int nXSize, int nYSize )
 VRTRasterBand::~VRTRasterBand()
 
 {
-    CPLFree( pszUnitType );
+    CPLFree( m_pszUnitType );
 
-    if( poColorTable != NULL )
-        delete poColorTable;
+    if( m_poColorTable != NULL )
+        delete m_poColorTable;
 
-    CSLDestroy( papszCategoryNames );
-    if( psSavedHistograms != NULL )
-        CPLDestroyXMLNode( psSavedHistograms );
+    CSLDestroy( m_papszCategoryNames );
+    if( m_psSavedHistograms != NULL )
+        CPLDestroyXMLNode( m_psSavedHistograms );
 
-    delete poMaskBand;
+    delete m_poMaskBand;
 }
 
 /************************************************************************/
@@ -114,14 +116,16 @@ VRTRasterBand::~VRTRasterBand()
 CPLErr VRTRasterBand::CopyCommonInfoFrom( GDALRasterBand * poSrcBand )
 
 {
-    int bSuccess;
-    double dfNoData;
-
     SetMetadata( poSrcBand->GetMetadata() );
+    const char* pszNBits = poSrcBand->GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
+    SetMetadataItem( "NBITS", pszNBits, "IMAGE_STRUCTURE" );
     SetColorTable( poSrcBand->GetColorTable() );
     SetColorInterpretation(poSrcBand->GetColorInterpretation());
     if( strlen(poSrcBand->GetDescription()) > 0 )
         SetDescription( poSrcBand->GetDescription() );
+
+    int bSuccess;
+    double dfNoData;
     dfNoData = poSrcBand->GetNoDataValue( &bSuccess );
     if( bSuccess )
         SetNoDataValue( dfNoData );
@@ -139,11 +143,11 @@ CPLErr VRTRasterBand::CopyCommonInfoFrom( GDALRasterBand * poSrcBand )
 /*                            SetMetadata()                             */
 /************************************************************************/
 
-CPLErr VRTRasterBand::SetMetadata( char **papszMetadata, 
+CPLErr VRTRasterBand::SetMetadata( char **papszMetadata,
                                    const char *pszDomain )
 
 {
-    ((VRTDataset *) poDS)->SetNeedsFlush();
+    reinterpret_cast<VRTDataset *>( poDS )->SetNeedsFlush();
 
     return GDALRasterBand::SetMetadata( papszMetadata, pszDomain );
 }
@@ -152,20 +156,20 @@ CPLErr VRTRasterBand::SetMetadata( char **papszMetadata,
 /*                          SetMetadataItem()                           */
 /************************************************************************/
 
-CPLErr VRTRasterBand::SetMetadataItem( const char *pszName, 
-                                       const char *pszValue, 
+CPLErr VRTRasterBand::SetMetadataItem( const char *pszName,
+                                       const char *pszValue,
                                        const char *pszDomain )
 
 {
-    ((VRTDataset *) poDS)->SetNeedsFlush();
+    reinterpret_cast<VRTDataset *>( poDS )->SetNeedsFlush();
 
     if( EQUAL(pszName,"HideNoDataValue") )
     {
-        bHideNoDataValue = CSLTestBoolean( pszValue );
+        m_bHideNoDataValue = CPLTestBool( pszValue );
         return CE_None;
     }
-    else
-        return GDALRasterBand::SetMetadataItem( pszName, pszValue, pszDomain );
+
+    return GDALRasterBand::SetMetadataItem( pszName, pszValue, pszDomain );
 }
 
 /************************************************************************/
@@ -175,10 +179,10 @@ CPLErr VRTRasterBand::SetMetadataItem( const char *pszName,
 const char *VRTRasterBand::GetUnitType()
 
 {
-    if( pszUnitType == NULL )
+    if( m_pszUnitType == NULL )
         return "";
-    else
-        return pszUnitType;
+
+    return m_pszUnitType;
 }
 
 /************************************************************************/
@@ -188,14 +192,14 @@ const char *VRTRasterBand::GetUnitType()
 CPLErr VRTRasterBand::SetUnitType( const char *pszNewValue )
 
 {
-    ((VRTDataset *) poDS)->SetNeedsFlush();
+    reinterpret_cast<VRTDataset *>( poDS )->SetNeedsFlush();
+
+    CPLFree( m_pszUnitType );
 
-    CPLFree( pszUnitType );
-    
     if( pszNewValue == NULL )
-        pszUnitType = NULL;
+        m_pszUnitType = NULL;
     else
-        pszUnitType = CPLStrdup(pszNewValue);
+        m_pszUnitType = CPLStrdup(pszNewValue);
 
     return CE_None;
 }
@@ -210,7 +214,7 @@ double VRTRasterBand::GetOffset( int *pbSuccess )
     if( pbSuccess != NULL )
         *pbSuccess = TRUE;
 
-    return dfOffset;
+    return m_dfOffset;
 }
 
 /************************************************************************/
@@ -220,9 +224,9 @@ double VRTRasterBand::GetOffset( int *pbSuccess )
 CPLErr VRTRasterBand::SetOffset( double dfNewOffset )
 
 {
-    ((VRTDataset *) poDS)->SetNeedsFlush();
+    reinterpret_cast<VRTDataset *>( poDS )->SetNeedsFlush();
 
-    dfOffset = dfNewOffset;
+    m_dfOffset = dfNewOffset;
     return CE_None;
 }
 
@@ -236,7 +240,7 @@ double VRTRasterBand::GetScale( int *pbSuccess )
     if( pbSuccess != NULL )
         *pbSuccess = TRUE;
 
-    return dfScale;
+    return m_dfScale;
 }
 
 /************************************************************************/
@@ -246,9 +250,9 @@ double VRTRasterBand::GetScale( int *pbSuccess )
 CPLErr VRTRasterBand::SetScale( double dfNewScale )
 
 {
-    ((VRTDataset *) poDS)->SetNeedsFlush();
+    reinterpret_cast<VRTDataset *>( poDS )->SetNeedsFlush();
 
-    dfScale = dfNewScale;
+    m_dfScale = dfNewScale;
     return CE_None;
 }
 
@@ -259,7 +263,7 @@ CPLErr VRTRasterBand::SetScale( double dfNewScale )
 char **VRTRasterBand::GetCategoryNames()
 
 {
-    return papszCategoryNames;
+    return m_papszCategoryNames;
 }
 
 /************************************************************************/
@@ -269,10 +273,10 @@ char **VRTRasterBand::GetCategoryNames()
 CPLErr VRTRasterBand::SetCategoryNames( char ** papszNewNames )
 
 {
-    ((VRTDataset *) poDS)->SetNeedsFlush();
+    reinterpret_cast<VRTDataset *>( poDS )->SetNeedsFlush();
 
-    CSLDestroy( papszCategoryNames );
-    papszCategoryNames = CSLDuplicate( papszNewNames );
+    CSLDestroy( m_papszCategoryNames );
+    m_papszCategoryNames = CSLDuplicate( papszNewNames );
 
     return CE_None;
 }
@@ -281,7 +285,7 @@ CPLErr VRTRasterBand::SetCategoryNames( char ** papszNewNames )
 /*                              XMLInit()                               */
 /************************************************************************/
 
-CPLErr VRTRasterBand::XMLInit( CPLXMLNode * psTree, 
+CPLErr VRTRasterBand::XMLInit( CPLXMLNode * psTree,
                                const char *pszVRTPath )
 
 {
@@ -291,7 +295,7 @@ CPLErr VRTRasterBand::XMLInit( CPLXMLNode * psTree,
     if( psTree == NULL || psTree->eType != CXT_Element
         || !EQUAL(psTree->pszValue,"VRTRasterBand") )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Invalid node passed to VRTRasterBand::XMLInit()." );
         return CE_Failure;
     }
@@ -323,12 +327,12 @@ CPLErr VRTRasterBand::XMLInit( CPLXMLNode * psTree,
 /*      Collect various other items of metadata.                        */
 /* -------------------------------------------------------------------- */
     SetDescription( CPLGetXMLValue( psTree, "Description", "" ) );
-    
+
     if( CPLGetXMLValue( psTree, "NoDataValue", NULL ) != NULL )
         SetNoDataValue( CPLAtofM(CPLGetXMLValue( psTree, "NoDataValue", "0" )) );
 
     if( CPLGetXMLValue( psTree, "HideNoDataValue", NULL ) != NULL )
-        bHideNoDataValue = CSLTestBoolean( CPLGetXMLValue( psTree, "HideNoDataValue", "0" ) );
+        m_bHideNoDataValue = CPLTestBool( CPLGetXMLValue( psTree, "HideNoDataValue", "0" ) );
 
     SetUnitType( CPLGetXMLValue( psTree, "UnitType", NULL ) );
 
@@ -346,26 +350,24 @@ CPLErr VRTRasterBand::XMLInit( CPLXMLNode * psTree,
 /* -------------------------------------------------------------------- */
     if( CPLGetXMLNode( psTree, "CategoryNames" ) != NULL )
     {
-        CPLXMLNode *psEntry;
-
-        CSLDestroy( papszCategoryNames );
-        papszCategoryNames = NULL;
+        CSLDestroy( m_papszCategoryNames );
+        m_papszCategoryNames = NULL;
 
         CPLStringList oCategoryNames;
 
-        for( psEntry = CPLGetXMLNode( psTree, "CategoryNames" )->psChild;
+        for( CPLXMLNode *psEntry = CPLGetXMLNode( psTree, "CategoryNames" )->psChild;
              psEntry != NULL; psEntry = psEntry->psNext )
         {
-            if( psEntry->eType != CXT_Element 
-                || !EQUAL(psEntry->pszValue,"Category") 
+            if( psEntry->eType != CXT_Element
+                || !EQUAL(psEntry->pszValue,"Category")
                 || (psEntry->psChild != NULL && psEntry->psChild->eType != CXT_Text) )
                 continue;
-            
+
             oCategoryNames.AddString(
                                 (psEntry->psChild) ? psEntry->psChild->pszValue : "");
         }
 
-        papszCategoryNames = oCategoryNames.StealList();
+        m_papszCategoryNames = oCategoryNames.StealList();
     }
 
 /* -------------------------------------------------------------------- */
@@ -373,11 +375,10 @@ CPLErr VRTRasterBand::XMLInit( CPLXMLNode * psTree,
 /* -------------------------------------------------------------------- */
     if( CPLGetXMLNode( psTree, "ColorTable" ) != NULL )
     {
-        CPLXMLNode *psEntry;
         GDALColorTable oTable;
         int        iEntry = 0;
 
-        for( psEntry = CPLGetXMLNode( psTree, "ColorTable" )->psChild;
+        for( CPLXMLNode *psEntry = CPLGetXMLNode( psTree, "ColorTable" )->psChild;
              psEntry != NULL; psEntry = psEntry->psNext )
         {
             GDALColorEntry sCEntry;
@@ -389,7 +390,7 @@ CPLErr VRTRasterBand::XMLInit( CPLXMLNode * psTree,
 
             oTable.SetColorEntry( iEntry++, &sCEntry );
         }
-        
+
         SetColorTable( &oTable );
     }
 
@@ -402,16 +403,16 @@ CPLErr VRTRasterBand::XMLInit( CPLXMLNode * psTree,
         CPLXMLNode *psNext = psHist->psNext;
         psHist->psNext = NULL;
 
-        psSavedHistograms = CPLCloneXMLTree( psHist );
+        m_psSavedHistograms = CPLCloneXMLTree( psHist );
         psHist->psNext = psNext;
     }
 
 /* ==================================================================== */
 /*      Overviews                                                       */
 /* ==================================================================== */
-    CPLXMLNode *psNode;
+    CPLXMLNode *psNode = psTree->psChild;
 
-    for( psNode = psTree->psChild; psNode != NULL; psNode = psNode->psNext )
+    for( ; psNode != NULL; psNode = psNode->psNext )
     {
         if( psNode->eType != CXT_Element
             || !EQUAL(psNode->pszValue,"Overview") )
@@ -420,20 +421,19 @@ CPLErr VRTRasterBand::XMLInit( CPLXMLNode * psTree,
 /* -------------------------------------------------------------------- */
 /*      Prepare filename.                                               */
 /* -------------------------------------------------------------------- */
-        char *pszSrcDSName = NULL;
         CPLXMLNode* psFileNameNode=CPLGetXMLNode(psNode,"SourceFilename");
-        const char *pszFilename = 
+        const char *pszFilename =
             psFileNameNode ? CPLGetXMLValue(psFileNameNode,NULL, NULL) : NULL;
 
         if( pszFilename == NULL )
         {
-            CPLError( CE_Warning, CPLE_AppDefined, 
+            CPLError( CE_Warning, CPLE_AppDefined,
                       "Missing <SourceFilename> element in Overview." );
             return CE_Failure;
         }
 
-        if (EQUALN(pszFilename, "MEM:::", 6) && pszVRTPath != NULL &&
-            !CSLTestBoolean(CPLGetConfigOption("VRT_ALLOW_MEM_DRIVER", "NO")))
+        if (STARTS_WITH_CI(pszFilename, "MEM:::") && pszVRTPath != NULL &&
+            !CPLTestBool(CPLGetConfigOption("VRT_ALLOW_MEM_DRIVER", "NO")))
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                     "<SourceFilename> points to a MEM dataset, which is rather suspect! "
@@ -441,6 +441,7 @@ CPLErr VRTRasterBand::XMLInit( CPLXMLNode * psTree,
             return CE_Failure;
         }
 
+        char *pszSrcDSName = NULL;
         if( pszVRTPath != NULL
             && atoi(CPLGetXMLValue( psFileNameNode, "relativetoVRT", "0")) )
         {
@@ -453,12 +454,12 @@ CPLErr VRTRasterBand::XMLInit( CPLXMLNode * psTree,
 /* -------------------------------------------------------------------- */
 /*      Get the raster band.                                            */
 /* -------------------------------------------------------------------- */
-        int nSrcBand = atoi(CPLGetXMLValue(psNode,"SourceBand","1"));
+        const int nSrcBand = atoi(CPLGetXMLValue( psNode, "SourceBand", "1" ) );
+
+        m_apoOverviews.resize( m_apoOverviews.size() + 1 );
+        m_apoOverviews[m_apoOverviews.size()-1].osFilename = pszSrcDSName;
+        m_apoOverviews[m_apoOverviews.size()-1].nBand = nSrcBand;
 
-        apoOverviews.resize( apoOverviews.size() + 1 );
-        apoOverviews[apoOverviews.size()-1].osFilename = pszSrcDSName;
-        apoOverviews[apoOverviews.size()-1].nBand = nSrcBand;
-        
         CPLFree( pszSrcDSName );
     }
 
@@ -476,7 +477,7 @@ CPLErr VRTRasterBand::XMLInit( CPLXMLNode * psTree,
             || !EQUAL(psNode->pszValue,"VRTRasterBand") )
             continue;
 
-        if( ((VRTDataset*)poDS)->poMaskBand != NULL)
+        if( reinterpret_cast<VRTDataset *>( poDS )->m_poMaskBand != NULL)
         {
             CPLError( CE_Warning, CPLE_AppDefined,
                        "Illegal mask band at raster band level when a dataset mask band already exists." );
@@ -484,7 +485,7 @@ CPLErr VRTRasterBand::XMLInit( CPLXMLNode * psTree,
         }
 
         const char *pszSubclass = CPLGetXMLValue( psNode, "subclass",
-                                                    "VRTSourcedRasterBand" );
+                                                  "VRTSourcedRasterBand" );
         VRTRasterBand  *poBand = NULL;
 
         if( EQUAL(pszSubclass,"VRTSourcedRasterBand") )
@@ -498,7 +499,7 @@ CPLErr VRTRasterBand::XMLInit( CPLXMLNode * psTree,
         else
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                        "VRTRasterBand of unrecognised subclass '%s'.",
+                        "VRTRasterBand of unrecognized subclass '%s'.",
                         pszSubclass );
             break;
         }
@@ -522,22 +523,18 @@ CPLErr VRTRasterBand::XMLInit( CPLXMLNode * psTree,
 CPLXMLNode *VRTRasterBand::SerializeToXML( const char *pszVRTPath )
 
 {
-    CPLXMLNode *psTree;
-
-    psTree = CPLCreateXMLNode( NULL, CXT_Element, "VRTRasterBand" );
+    CPLXMLNode *psTree = CPLCreateXMLNode( NULL, CXT_Element, "VRTRasterBand" );
 
 /* -------------------------------------------------------------------- */
 /*      Various kinds of metadata.                                      */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psMD;
-
-    CPLSetXMLValue( psTree, "#dataType", 
+    CPLSetXMLValue( psTree, "#dataType",
                     GDALGetDataTypeName( GetRasterDataType() ) );
 
     if( nBand > 0 )
         CPLSetXMLValue( psTree, "#band", CPLSPrintf( "%d", GetBand() ) );
 
-    psMD = oMDMD.Serialize();
+    CPLXMLNode *psMD = oMDMD.Serialize();
     if( psMD != NULL )
     {
         CPLAddXMLChild( psTree, psMD );
@@ -546,47 +543,47 @@ CPLXMLNode *VRTRasterBand::SerializeToXML( const char *pszVRTPath )
     if( strlen(GetDescription()) > 0 )
         CPLSetXMLValue( psTree, "Description", GetDescription() );
 
-    if( bNoDataValueSet )
+    if( m_bNoDataValueSet )
     {
-        if (CPLIsNan(dfNoDataValue))
+        if (CPLIsNan(m_dfNoDataValue))
             CPLSetXMLValue( psTree, "NoDataValue", "nan");
         else
-            CPLSetXMLValue( psTree, "NoDataValue", 
-                            CPLSPrintf( "%.16g", dfNoDataValue ) );
+            CPLSetXMLValue( psTree, "NoDataValue",
+                            CPLSPrintf( "%.16g", m_dfNoDataValue ) );
     }
-    
-    if( bHideNoDataValue )
-        CPLSetXMLValue( psTree, "HideNoDataValue", 
-                        CPLSPrintf( "%d", bHideNoDataValue ) );
 
-    if( pszUnitType != NULL )
-        CPLSetXMLValue( psTree, "UnitType", pszUnitType );
+    if( m_bHideNoDataValue )
+        CPLSetXMLValue( psTree, "HideNoDataValue",
+                        CPLSPrintf( "%d", m_bHideNoDataValue ) );
+
+    if( m_pszUnitType != NULL )
+        CPLSetXMLValue( psTree, "UnitType", m_pszUnitType );
 
-    if( dfOffset != 0.0 )
-        CPLSetXMLValue( psTree, "Offset", 
-                        CPLSPrintf( "%.16g", dfOffset ) );
+    if( m_dfOffset != 0.0 )
+        CPLSetXMLValue( psTree, "Offset",
+                        CPLSPrintf( "%.16g", m_dfOffset ) );
 
-    if( dfScale != 1.0 )
-        CPLSetXMLValue( psTree, "Scale", 
-                        CPLSPrintf( "%.16g", dfScale ) );
+    if( m_dfScale != 1.0 )
+        CPLSetXMLValue( psTree, "Scale",
+                        CPLSPrintf( "%.16g", m_dfScale ) );
 
-    if( eColorInterp != GCI_Undefined )
-        CPLSetXMLValue( psTree, "ColorInterp", 
-                        GDALGetColorInterpretationName( eColorInterp ) );
+    if( m_eColorInterp != GCI_Undefined )
+        CPLSetXMLValue( psTree, "ColorInterp",
+                        GDALGetColorInterpretationName( m_eColorInterp ) );
 
 /* -------------------------------------------------------------------- */
 /*      Category names.                                                 */
 /* -------------------------------------------------------------------- */
-    if( papszCategoryNames != NULL )
+    if( m_papszCategoryNames != NULL )
     {
-        CPLXMLNode *psCT_XML = CPLCreateXMLNode( psTree, CXT_Element, 
+        CPLXMLNode *psCT_XML = CPLCreateXMLNode( psTree, CXT_Element,
                                                  "CategoryNames" );
         CPLXMLNode* psLastChild = NULL;
 
-        for( int iEntry=0; papszCategoryNames[iEntry] != NULL; iEntry++ )
+        for( int iEntry=0; m_papszCategoryNames[iEntry] != NULL; iEntry++ )
         {
             CPLXMLNode *psNode = CPLCreateXMLElementAndValue( NULL, "Category",
-                                         papszCategoryNames[iEntry] );
+                                         m_papszCategoryNames[iEntry] );
             if( psLastChild == NULL )
                 psCT_XML->psChild = psNode;
             else
@@ -598,22 +595,21 @@ CPLXMLNode *VRTRasterBand::SerializeToXML( const char *pszVRTPath )
 /* -------------------------------------------------------------------- */
 /*      Histograms.                                                     */
 /* -------------------------------------------------------------------- */
-    if( psSavedHistograms != NULL )
-        CPLAddXMLChild( psTree, CPLCloneXMLTree( psSavedHistograms ) );
+    if( m_psSavedHistograms != NULL )
+        CPLAddXMLChild( psTree, CPLCloneXMLTree( m_psSavedHistograms ) );
 
 /* -------------------------------------------------------------------- */
 /*      Color Table.                                                    */
 /* -------------------------------------------------------------------- */
-    if( poColorTable != NULL )
+    if( m_poColorTable != NULL )
     {
-        CPLXMLNode *psCT_XML = CPLCreateXMLNode( psTree, CXT_Element, 
+        CPLXMLNode *psCT_XML = CPLCreateXMLNode( psTree, CXT_Element,
                                                  "ColorTable" );
         CPLXMLNode* psLastChild = NULL;
 
-        for( int iEntry=0; iEntry < poColorTable->GetColorEntryCount(); 
+        for( int iEntry=0; iEntry < m_poColorTable->GetColorEntryCount();
              iEntry++ )
         {
-            GDALColorEntry sEntry;
             CPLXMLNode *psEntry_XML = CPLCreateXMLNode( NULL, CXT_Element,
                                                         "Entry" );
             if( psLastChild == NULL )
@@ -622,8 +618,9 @@ CPLXMLNode *VRTRasterBand::SerializeToXML( const char *pszVRTPath )
                 psLastChild->psNext = psEntry_XML;
             psLastChild = psEntry_XML;
 
-            poColorTable->GetColorEntryAsRGB( iEntry, &sEntry );
-            
+            GDALColorEntry sEntry;
+            m_poColorTable->GetColorEntryAsRGB( iEntry, &sEntry );
+
             CPLSetXMLValue( psEntry_XML, "#c1", CPLSPrintf("%d",sEntry.c1) );
             CPLSetXMLValue( psEntry_XML, "#c2", CPLSPrintf("%d",sEntry.c2) );
             CPLSetXMLValue( psEntry_XML, "#c3", CPLSPrintf("%d",sEntry.c3) );
@@ -635,7 +632,7 @@ CPLXMLNode *VRTRasterBand::SerializeToXML( const char *pszVRTPath )
 /*      Overviews                                                       */
 /* ==================================================================== */
 
-    for( int iOvr = 0; iOvr < (int)apoOverviews.size(); iOvr ++ )
+    for( int iOvr = 0; iOvr < static_cast<int>( m_apoOverviews.size() ); iOvr ++ )
     {
         CPLXMLNode *psOVR_XML = CPLCreateXMLNode( psTree, CXT_Element,
                                                  "Overview" );
@@ -644,15 +641,15 @@ CPLXMLNode *VRTRasterBand::SerializeToXML( const char *pszVRTPath )
         const char      *pszRelativePath;
         VSIStatBufL sStat;
 
-        if( VSIStatExL( apoOverviews[iOvr].osFilename, &sStat, VSI_STAT_EXISTS_FLAG ) != 0 )
+        if( VSIStatExL( m_apoOverviews[iOvr].osFilename, &sStat, VSI_STAT_EXISTS_FLAG ) != 0 )
         {
-            pszRelativePath = apoOverviews[iOvr].osFilename;
+            pszRelativePath = m_apoOverviews[iOvr].osFilename;
             bRelativeToVRT = FALSE;
         }
         else
         {
             pszRelativePath =
-                CPLExtractRelativePath( pszVRTPath, apoOverviews[iOvr].osFilename,
+                CPLExtractRelativePath( pszVRTPath, m_apoOverviews[iOvr].osFilename,
                                         &bRelativeToVRT );
         }
 
@@ -664,21 +661,21 @@ CPLXMLNode *VRTRasterBand::SerializeToXML( const char *pszVRTPath )
             CXT_Text, bRelativeToVRT ? "1" : "0" );
 
         CPLSetXMLValue( psOVR_XML, "SourceBand",
-                        CPLSPrintf("%d",apoOverviews[iOvr].nBand) );
+                        CPLSPrintf("%d",m_apoOverviews[iOvr].nBand) );
     }
-    
+
 /* ==================================================================== */
 /*      Mask band (specific to that raster band)                        */
 /* ==================================================================== */
 
-    if( poMaskBand != NULL )
+    if( m_poMaskBand != NULL )
     {
         CPLXMLNode *psBandTree =
-            poMaskBand->SerializeToXML(pszVRTPath);
+            m_poMaskBand->SerializeToXML(pszVRTPath);
 
         if( psBandTree != NULL )
         {
-            CPLXMLNode *psMaskBandElement = CPLCreateXMLNode( psTree, CXT_Element, 
+            CPLXMLNode *psMaskBandElement = CPLCreateXMLNode( psTree, CXT_Element,
                                                               "MaskBand" );
             CPLAddXMLChild( psMaskBandElement, psBandTree );
         }
@@ -694,27 +691,35 @@ CPLXMLNode *VRTRasterBand::SerializeToXML( const char *pszVRTPath )
 CPLErr VRTRasterBand::SetNoDataValue( double dfNewValue )
 
 {
-    bNoDataValueSet = TRUE;
-    dfNoDataValue = dfNewValue;
-    
-    ((VRTDataset *)poDS)->SetNeedsFlush();
+    m_bNoDataValueSet = TRUE;
+    m_dfNoDataValue = dfNewValue;
+
+    reinterpret_cast<VRTDataset *>( poDS )->SetNeedsFlush();
 
     return CE_None;
 }
 
 /************************************************************************/
-/*                         UnsetNoDataValue()                           */
+/*                         DeleteNoDataValue()                          */
 /************************************************************************/
 
-CPLErr VRTRasterBand::UnsetNoDataValue()
+CPLErr VRTRasterBand::DeleteNoDataValue()
 {
-    bNoDataValueSet = FALSE;
-    dfNoDataValue = -10000.0;
+    m_bNoDataValueSet = FALSE;
+    m_dfNoDataValue = -10000.0;
 
-    ((VRTDataset *)poDS)->SetNeedsFlush();
+    reinterpret_cast<VRTDataset *>( poDS )->SetNeedsFlush();
 
     return CE_None;
 }
+/************************************************************************/
+/*                         UnsetNoDataValue()                           */
+/************************************************************************/
+
+CPLErr VRTRasterBand::UnsetNoDataValue()
+{
+    return DeleteNoDataValue();
+}
 
 /************************************************************************/
 /*                           GetNoDataValue()                           */
@@ -724,9 +729,9 @@ double VRTRasterBand::GetNoDataValue( int *pbSuccess )
 
 {
     if( pbSuccess )
-        *pbSuccess = bNoDataValueSet && !bHideNoDataValue;
+        *pbSuccess = m_bNoDataValueSet && !m_bHideNoDataValue;
 
-    return dfNoDataValue;
+    return m_dfNoDataValue;
 }
 
 /************************************************************************/
@@ -736,19 +741,19 @@ double VRTRasterBand::GetNoDataValue( int *pbSuccess )
 CPLErr VRTRasterBand::SetColorTable( GDALColorTable *poTableIn )
 
 {
-    if( poColorTable != NULL )
+    if( m_poColorTable != NULL )
     {
-        delete poColorTable;
-        poColorTable = NULL;
+        delete m_poColorTable;
+        m_poColorTable = NULL;
     }
 
     if( poTableIn )
     {
-        poColorTable = poTableIn->Clone();
-        eColorInterp = GCI_PaletteIndex;
+        m_poColorTable = poTableIn->Clone();
+        m_eColorInterp = GCI_PaletteIndex;
     }
 
-    ((VRTDataset *)poDS)->SetNeedsFlush();
+    reinterpret_cast<VRTDataset *>( poDS )->SetNeedsFlush();
 
     return CE_None;
 }
@@ -760,7 +765,7 @@ CPLErr VRTRasterBand::SetColorTable( GDALColorTable *poTableIn )
 GDALColorTable *VRTRasterBand::GetColorTable()
 
 {
-    return poColorTable;
+    return m_poColorTable;
 }
 
 /************************************************************************/
@@ -770,9 +775,9 @@ GDALColorTable *VRTRasterBand::GetColorTable()
 CPLErr VRTRasterBand::SetColorInterpretation( GDALColorInterp eInterpIn )
 
 {
-    ((VRTDataset *)poDS)->SetNeedsFlush();
+    reinterpret_cast<VRTDataset *>( poDS )->SetNeedsFlush();
 
-    eColorInterp = eInterpIn;
+    m_eColorInterp = eInterpIn;
 
     return CE_None;
 }
@@ -784,7 +789,7 @@ CPLErr VRTRasterBand::SetColorInterpretation( GDALColorInterp eInterpIn )
 GDALColorInterp VRTRasterBand::GetColorInterpretation()
 
 {
-    return eColorInterp;
+    return m_eColorInterp;
 }
 
 /************************************************************************/
@@ -794,23 +799,21 @@ GDALColorInterp VRTRasterBand::GetColorInterpretation()
 CPLErr VRTRasterBand::GetHistogram( double dfMin, double dfMax,
                                     int nBuckets, GUIntBig * panHistogram,
                                     int bIncludeOutOfRange, int bApproxOK,
-                                    GDALProgressFunc pfnProgress, 
+                                    GDALProgressFunc pfnProgress,
                                     void *pProgressData )
 
 {
 /* -------------------------------------------------------------------- */
 /*      Check if we have a matching histogram.                          */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psHistItem;
-
-    psHistItem = PamFindMatchingHistogram( psSavedHistograms, 
-                                           dfMin, dfMax, nBuckets, 
+    CPLXMLNode *psHistItem = PamFindMatchingHistogram( m_psSavedHistograms,
+                                           dfMin, dfMax, nBuckets,
                                            bIncludeOutOfRange, bApproxOK );
     if( psHistItem != NULL )
     {
         GUIntBig *panTempHist = NULL;
 
-        if( PamParseHistogram( psHistItem, &dfMin, &dfMax, &nBuckets, 
+        if( PamParseHistogram( psHistItem, &dfMin, &dfMax, &nBuckets,
                                &panTempHist,
                                &bIncludeOutOfRange, &bApproxOK ) )
         {
@@ -824,10 +827,8 @@ CPLErr VRTRasterBand::GetHistogram( double dfMin, double dfMax,
 /*      We don't have an existing histogram matching the request, so    */
 /*      generate one manually.                                          */
 /* -------------------------------------------------------------------- */
-    CPLErr eErr;
-
-    eErr = GDALRasterBand::GetHistogram( dfMin, dfMax, 
-                                         nBuckets, panHistogram, 
+    CPLErr eErr = GDALRasterBand::GetHistogram( dfMin, dfMax,
+                                         nBuckets, panHistogram,
                                          bIncludeOutOfRange, bApproxOK,
                                          pfnProgress, pProgressData );
 
@@ -836,20 +837,18 @@ CPLErr VRTRasterBand::GetHistogram( double dfMin, double dfMax,
 /* -------------------------------------------------------------------- */
     if( eErr == CE_None )
     {
-        CPLXMLNode *psXMLHist;
-
-        psXMLHist = PamHistogramToXMLTree( dfMin, dfMax, nBuckets, 
-                                           panHistogram, 
+        CPLXMLNode *psXMLHist = PamHistogramToXMLTree( dfMin, dfMax, nBuckets,
+                                           panHistogram,
                                            bIncludeOutOfRange, bApproxOK );
         if( psXMLHist != NULL )
         {
-            ((VRTDataset *) poDS)->SetNeedsFlush();
+            reinterpret_cast<VRTDataset *>( poDS )->SetNeedsFlush();
 
-            if( psSavedHistograms == NULL )
-                psSavedHistograms = CPLCreateXMLNode( NULL, CXT_Element,
+            if( m_psSavedHistograms == NULL )
+                m_psSavedHistograms = CPLCreateXMLNode( NULL, CXT_Element,
                                                       "Histograms" );
-            
-            CPLAddXMLChild( psSavedHistograms, psXMLHist );
+
+            CPLAddXMLChild( m_psSavedHistograms, psXMLHist );
         }
     }
 
@@ -860,31 +859,27 @@ CPLErr VRTRasterBand::GetHistogram( double dfMin, double dfMax,
 /*                        SetDefaultHistogram()                         */
 /************************************************************************/
 
-CPLErr VRTRasterBand::SetDefaultHistogram( double dfMin, double dfMax, 
+CPLErr VRTRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
                                            int nBuckets, GUIntBig *panHistogram)
 
 {
-    CPLXMLNode *psNode;
-
 /* -------------------------------------------------------------------- */
 /*      Do we have a matching histogram we should replace?              */
 /* -------------------------------------------------------------------- */
-    psNode = PamFindMatchingHistogram( psSavedHistograms, 
+    CPLXMLNode *psNode = PamFindMatchingHistogram( m_psSavedHistograms,
                                        dfMin, dfMax, nBuckets,
                                        TRUE, TRUE );
     if( psNode != NULL )
     {
         /* blow this one away */
-        CPLRemoveXMLChild( psSavedHistograms, psNode );
+        CPLRemoveXMLChild( m_psSavedHistograms, psNode );
         CPLDestroyXMLNode( psNode );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Translate into a histogram XML tree.                            */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psHistItem;
-
-    psHistItem = PamHistogramToXMLTree( dfMin, dfMax, nBuckets, 
+    CPLXMLNode *psHistItem = PamHistogramToXMLTree( dfMin, dfMax, nBuckets,
                                         panHistogram, TRUE, FALSE );
     if( psHistItem == NULL )
         return CE_Failure;
@@ -893,15 +888,15 @@ CPLErr VRTRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
 /*      Insert our new default histogram at the front of the            */
 /*      histogram list so that it will be the default histogram.        */
 /* -------------------------------------------------------------------- */
-    ((VRTDataset *) poDS)->SetNeedsFlush();
+    reinterpret_cast<VRTDataset *>( poDS )->SetNeedsFlush();
 
-    if( psSavedHistograms == NULL )
-        psSavedHistograms = CPLCreateXMLNode( NULL, CXT_Element,
+    if( m_psSavedHistograms == NULL )
+        m_psSavedHistograms = CPLCreateXMLNode( NULL, CXT_Element,
                                               "Histograms" );
-            
-    psHistItem->psNext = psSavedHistograms->psChild;
-    psSavedHistograms->psChild = psHistItem;
-    
+
+    psHistItem->psNext = m_psSavedHistograms->psChild;
+    m_psSavedHistograms->psChild = psHistItem;
+
     return CE_None;
 }
 
@@ -909,38 +904,36 @@ CPLErr VRTRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
 /*                        GetDefaultHistogram()                         */
 /************************************************************************/
 
-CPLErr 
-VRTRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax, 
-                                    int *pnBuckets, GUIntBig **ppanHistogram, 
+CPLErr
+VRTRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
+                                    int *pnBuckets, GUIntBig **ppanHistogram,
                                     int bForce,
-                                    GDALProgressFunc pfnProgress, 
+                                    GDALProgressFunc pfnProgress,
                                     void *pProgressData )
-    
+
 {
-    if( psSavedHistograms != NULL )
+    if( m_psSavedHistograms != NULL )
     {
-        CPLXMLNode *psXMLHist;
-
-        for( psXMLHist = psSavedHistograms->psChild;
+        for( CPLXMLNode *psXMLHist = m_psSavedHistograms->psChild;
              psXMLHist != NULL; psXMLHist = psXMLHist->psNext )
         {
-            int bApprox, bIncludeOutOfRange;
-
             if( psXMLHist->eType != CXT_Element
                 || !EQUAL(psXMLHist->pszValue,"HistItem") )
                 continue;
 
-            if( PamParseHistogram( psXMLHist, pdfMin, pdfMax, pnBuckets, 
+            int bIncludeOutOfRange;
+            int bApprox;
+            if( PamParseHistogram( psXMLHist, pdfMin, pdfMax, pnBuckets,
                                    ppanHistogram, &bIncludeOutOfRange,
                                    &bApprox ) )
                 return CE_None;
-            else
-                return CE_Failure;
+
+            return CE_Failure;
         }
     }
 
-    return GDALRasterBand::GetDefaultHistogram( pdfMin, pdfMax, pnBuckets, 
-                                                ppanHistogram, bForce, 
+    return GDALRasterBand::GetDefaultHistogram( pdfMin, pdfMax, pnBuckets,
+                                                ppanHistogram, bForce,
                                                 pfnProgress,pProgressData);
 }
 
@@ -951,9 +944,9 @@ VRTRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
 void VRTRasterBand::GetFileList(char*** ppapszFileList, int *pnSize,
                                 int *pnMaxSize, CPLHashSet* hSetFiles)
 {
-    for( unsigned int iOver = 0; iOver < apoOverviews.size(); iOver++ )
+    for( unsigned int iOver = 0; iOver < m_apoOverviews.size(); iOver++ )
     {
-        CPLString &osFilename = apoOverviews[iOver].osFilename;
+        const CPLString &osFilename = m_apoOverviews[iOver].osFilename;
 
 /* -------------------------------------------------------------------- */
 /*      Is the filename even a real filesystem object?                  */
@@ -961,30 +954,30 @@ void VRTRasterBand::GetFileList(char*** ppapszFileList, int *pnSize,
         VSIStatBufL  sStat;
         if( VSIStatL( osFilename, &sStat ) != 0 )
             return;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Is it already in the list ?                                     */
 /* -------------------------------------------------------------------- */
         if( CPLHashSetLookup(hSetFiles, osFilename) != NULL )
             return;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Grow array if necessary                                         */
 /* -------------------------------------------------------------------- */
         if (*pnSize + 1 >= *pnMaxSize)
         {
             *pnMaxSize = 2 + 2 * (*pnMaxSize);
-            *ppapszFileList = (char **) CPLRealloc(
-                *ppapszFileList, sizeof(char*)  * (*pnMaxSize) );
+            *ppapszFileList = reinterpret_cast<char **>( CPLRealloc(
+                *ppapszFileList, sizeof(char*)  * (*pnMaxSize) ) );
         }
-            
+
 /* -------------------------------------------------------------------- */
 /*      Add the string to the list                                      */
 /* -------------------------------------------------------------------- */
         (*ppapszFileList)[*pnSize] = CPLStrdup(osFilename);
         (*ppapszFileList)[(*pnSize + 1)] = NULL;
         CPLHashSetInsert(hSetFiles, (*ppapszFileList)[*pnSize]);
-        
+
         (*pnSize) ++;
     }
 }
@@ -996,10 +989,22 @@ void VRTRasterBand::GetFileList(char*** ppapszFileList, int *pnSize,
 int VRTRasterBand::GetOverviewCount()
 
 {
-    if( apoOverviews.size() > 0 )
-        return apoOverviews.size();
-    else
-        return GDALRasterBand::GetOverviewCount();
+    // First: overviews declared in <Overview> element
+    if( m_apoOverviews.size() > 0 )
+        return static_cast<int>(m_apoOverviews.size());
+
+    // If not found, external .ovr overviews
+    const int nOverviewCount = GDALRasterBand::GetOverviewCount();
+    if( nOverviewCount )
+        return nOverviewCount;
+
+    // If not found, implicit virtual overviews
+    VRTDataset* poVRTDS = reinterpret_cast<VRTDataset *>( poDS );
+    poVRTDS->BuildVirtualOverviews();
+    if( poVRTDS->m_apoOverviews.size() && poVRTDS->m_apoOverviews[0] )
+        return static_cast<int>( poVRTDS->m_apoOverviews.size() );
+
+    return 0;
 }
 
 /************************************************************************/
@@ -1009,35 +1014,55 @@ int VRTRasterBand::GetOverviewCount()
 GDALRasterBand *VRTRasterBand::GetOverview( int iOverview )
 
 {
-    if( apoOverviews.size() > 0 )
+    // First: overviews declared in <Overview> element
+    if( m_apoOverviews.size() > 0 )
     {
-        if( iOverview < 0 || iOverview >= (int) apoOverviews.size() )
+        if( iOverview < 0
+            || iOverview >= static_cast<int>( m_apoOverviews.size() ) )
             return NULL;
 
-        if( apoOverviews[iOverview].poBand == NULL 
-            && !apoOverviews[iOverview].bTriedToOpen )
+        if( m_apoOverviews[iOverview].poBand == NULL
+            && !m_apoOverviews[iOverview].bTriedToOpen )
         {
-            apoOverviews[iOverview].bTriedToOpen = TRUE;
+            m_apoOverviews[iOverview].bTriedToOpen = TRUE;
+
+            GDALDataset *poSrcDS = reinterpret_cast<GDALDataset *>(
+                GDALOpenShared( m_apoOverviews[iOverview].osFilename,
+                                GA_ReadOnly ) );
 
-            GDALDataset *poSrcDS = (GDALDataset *)
-                GDALOpenShared( apoOverviews[iOverview].osFilename, GA_ReadOnly );
-            
             if( poSrcDS == NULL )
                 return NULL;
 
-            apoOverviews[iOverview].poBand = poSrcDS->GetRasterBand( 
-                apoOverviews[iOverview].nBand );
+            m_apoOverviews[iOverview].poBand = poSrcDS->GetRasterBand(
+                m_apoOverviews[iOverview].nBand );
 
-            if (apoOverviews[iOverview].poBand == NULL)
+            if (m_apoOverviews[iOverview].poBand == NULL)
             {
                 GDALClose( (GDALDatasetH)poSrcDS );
             }
         }
 
-        return apoOverviews[iOverview].poBand;
+        return m_apoOverviews[iOverview].poBand;
     }
-    else
-        return GDALRasterBand::GetOverview( iOverview );
+
+    // If not found, external .ovr overviews
+    GDALRasterBand* poRet = GDALRasterBand::GetOverview( iOverview );
+    if( poRet )
+        return poRet;
+
+    // If not found, implicit virtual overviews
+    VRTDataset* poVRTDS = reinterpret_cast<VRTDataset *>( poDS );
+    poVRTDS->BuildVirtualOverviews();
+    if( poVRTDS->m_apoOverviews.size() && poVRTDS->m_apoOverviews[0] )
+    {
+        if( iOverview < 0
+            || iOverview >= static_cast<int>( poVRTDS->m_apoOverviews.size() ) )
+            return NULL;
+
+        return poVRTDS->m_apoOverviews[iOverview]->GetRasterBand(nBand);
+    }
+
+    return NULL;
 }
 
 /************************************************************************/
@@ -1047,7 +1072,7 @@ GDALRasterBand *VRTRasterBand::GetOverview( int iOverview )
 void VRTRasterBand::SetDescription(const char* pszDescription)
 
 {
-    ((VRTDataset *)poDS)->SetNeedsFlush();
+    reinterpret_cast<VRTDataset *>( poDS )->SetNeedsFlush();
 
     GDALRasterBand::SetDescription(pszDescription);
 }
@@ -1056,26 +1081,26 @@ void VRTRasterBand::SetDescription(const char* pszDescription)
 /*                          CreateMaskBand()                            */
 /************************************************************************/
 
-CPLErr VRTRasterBand::CreateMaskBand( int nFlags )
+CPLErr VRTRasterBand::CreateMaskBand( int nFlagsIn )
 {
-    VRTDataset* poGDS = (VRTDataset *)poDS;
-    
-    if (poGDS->poMaskBand)
+    VRTDataset* poGDS = reinterpret_cast<VRTDataset *>( poDS );
+
+    if (poGDS->m_poMaskBand)
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Cannot create mask band at raster band level when a dataset mask band already exists." );
         return CE_Failure;
     }
-    
-    if (poMaskBand != NULL)
+
+    if (m_poMaskBand != NULL)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "This VRT band has already a mask band");
         return CE_Failure;
     }
-    
-    if ((nFlags & GMF_PER_DATASET) != 0)
-        return poGDS->CreateMaskBand(nFlags);
+
+    if ((nFlagsIn & GMF_PER_DATASET) != 0)
+        return poGDS->CreateMaskBand(nFlagsIn);
 
     SetMaskBand(new VRTSourcedRasterBand( poGDS, 0 ));
 
@@ -1088,11 +1113,12 @@ CPLErr VRTRasterBand::CreateMaskBand( int nFlags )
 
 GDALRasterBand* VRTRasterBand::GetMaskBand()
 {
-    VRTDataset* poGDS = (VRTDataset *)poDS;
-    if (poGDS->poMaskBand)
-        return poGDS->poMaskBand;
-    else if (poMaskBand)
-        return poMaskBand;
+    VRTDataset* poGDS = reinterpret_cast<VRTDataset *>( poDS );
+
+    if (poGDS->m_poMaskBand)
+        return poGDS->m_poMaskBand;
+    else if (m_poMaskBand)
+        return m_poMaskBand;
     else
         return GDALRasterBand::GetMaskBand();
 }
@@ -1103,10 +1129,11 @@ GDALRasterBand* VRTRasterBand::GetMaskBand()
 
 int VRTRasterBand::GetMaskFlags()
 {
-    VRTDataset* poGDS = (VRTDataset *)poDS;
-    if (poGDS->poMaskBand)
+    VRTDataset* poGDS = reinterpret_cast<VRTDataset *>( poDS );
+
+    if (poGDS->m_poMaskBand)
         return GMF_PER_DATASET;
-    else if (poMaskBand)
+    else if (m_poMaskBand)
         return 0;
     else
         return GDALRasterBand::GetMaskFlags();
@@ -1116,11 +1143,11 @@ int VRTRasterBand::GetMaskFlags()
 /*                           SetMaskBand()                              */
 /************************************************************************/
 
-void VRTRasterBand::SetMaskBand(VRTRasterBand* poMaskBand)
+void VRTRasterBand::SetMaskBand(VRTRasterBand* poMaskBandIn)
 {
-    delete this->poMaskBand;
-    this->poMaskBand = poMaskBand;
-    poMaskBand->SetIsMaskBand();
+    delete m_poMaskBand;
+    m_poMaskBand = poMaskBandIn;
+    m_poMaskBand->SetIsMaskBand();
 }
 
 /************************************************************************/
@@ -1130,7 +1157,7 @@ void VRTRasterBand::SetMaskBand(VRTRasterBand* poMaskBand)
 void VRTRasterBand::SetIsMaskBand()
 {
     nBand = 0;
-    bIsMaskBand = TRUE;
+    m_bIsMaskBand = TRUE;
 }
 
 /************************************************************************/
diff --git a/frmts/vrt/vrtrawrasterband.cpp b/frmts/vrt/vrtrawrasterband.cpp
index cf1c1e7..6cd8f4b 100644
--- a/frmts/vrt/vrtrawrasterband.cpp
+++ b/frmts/vrt/vrtrawrasterband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtrawrasterband.cpp 32756 2016-01-05 16:03:53Z rouault $
+ * $Id: vrtrawrasterband.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTRawRasterBand
@@ -33,7 +33,7 @@
 #include "cpl_string.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: vrtrawrasterband.cpp 32756 2016-01-05 16:03:53Z rouault $");
+CPL_CVSID("$Id: vrtrawrasterband.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -45,20 +45,17 @@ CPL_CVSID("$Id: vrtrawrasterband.cpp 32756 2016-01-05 16:03:53Z rouault $");
 /*                          VRTRawRasterBand()                          */
 /************************************************************************/
 
-VRTRawRasterBand::VRTRawRasterBand( GDALDataset *poDS, int nBand,
-                                    GDALDataType eType )
-
+VRTRawRasterBand::VRTRawRasterBand( GDALDataset *poDSIn, int nBandIn,
+                                    GDALDataType eType ) :
+    m_poRawRaster(NULL), m_pszSourceFilename(NULL), m_bRelativeToVRT(FALSE)
 {
-    Initialize( poDS->GetRasterXSize(), poDS->GetRasterYSize() );
+    Initialize( poDSIn->GetRasterXSize(), poDSIn->GetRasterYSize() );
 
-    this->poDS = poDS;
-    this->nBand = nBand;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
 
     if( eType != GDT_Unknown )
-        this->eDataType = eType;
-
-    poRawRaster = NULL;
-    pszSourceFilename = NULL;
+        eDataType = eType;
 }
 
 /************************************************************************/
@@ -84,9 +81,9 @@ CPLErr VRTRawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                                  GSpacing nLineSpace,
                                  GDALRasterIOExtraArg* psExtraArg)
 {
-    if( poRawRaster == NULL )
+    if( m_poRawRaster == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "No raw raster band configured on VRTRawRasterBand." );
         return CE_Failure;
     }
@@ -99,7 +96,7 @@ CPLErr VRTRawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 
         return( CE_Failure );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Do we have overviews that would be appropriate to satisfy       */
 /*      this request?                                                   */
@@ -107,16 +104,16 @@ CPLErr VRTRawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     if( (nBufXSize < nXSize || nBufYSize < nYSize)
         && GetOverviewCount() > 0 )
     {
-        if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, 
-                              pData, nBufXSize, nBufYSize, 
+        if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                              pData, nBufXSize, nBufYSize,
                               eBufType, nPixelSpace, nLineSpace, psExtraArg ) == CE_None )
             return CE_None;
     }
-    
-    poRawRaster->SetAccess(eAccess);
 
-    return poRawRaster->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, 
-                                  pData, nBufXSize, nBufYSize, 
+    m_poRawRaster->SetAccess(eAccess);
+
+    return m_poRawRaster->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                                  pData, nBufXSize, nBufYSize,
                                   eBufType, nPixelSpace, nLineSpace, psExtraArg );
 }
 
@@ -128,14 +125,14 @@ CPLErr VRTRawRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                    void * pImage )
 
 {
-    if( poRawRaster == NULL )
+    if( m_poRawRaster == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "No raw raster band configured on VRTRawRasterBand." );
         return CE_Failure;
     }
 
-    return poRawRaster->ReadBlock( nBlockXOff, nBlockYOff, pImage );
+    return m_poRawRaster->ReadBlock( nBlockXOff, nBlockYOff, pImage );
 }
 
 /************************************************************************/
@@ -146,47 +143,46 @@ CPLErr VRTRawRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                                       void * pImage )
 
 {
-    if( poRawRaster == NULL )
+    if( m_poRawRaster == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "No raw raster band configured on VRTRawRasterBand." );
         return CE_Failure;
     }
-    
-    poRawRaster->SetAccess(eAccess);
-    
-    return poRawRaster->WriteBlock( nBlockXOff, nBlockYOff, pImage );
+
+    m_poRawRaster->SetAccess(eAccess);
+
+    return m_poRawRaster->WriteBlock( nBlockXOff, nBlockYOff, pImage );
 }
 
 /************************************************************************/
 /*                             SetRawLink()                             */
 /************************************************************************/
 
-CPLErr VRTRawRasterBand::SetRawLink( const char *pszFilename, 
+CPLErr VRTRawRasterBand::SetRawLink( const char *pszFilename,
                                      const char *pszVRTPath,
-                                     int bRelativeToVRT, 
-                                     vsi_l_offset nImageOffset, 
-                                     int nPixelOffset, int nLineOffset, 
+                                     int bRelativeToVRTIn,
+                                     vsi_l_offset nImageOffset,
+                                     int nPixelOffset, int nLineOffset,
                                      const char *pszByteOrder )
 
 {
     ClearRawLink();
 
-    ((VRTDataset *)poDS)->SetNeedsFlush();
+    reinterpret_cast<VRTDataset *>( poDS )->SetNeedsFlush();
 
 /* -------------------------------------------------------------------- */
 /*      Prepare filename.                                               */
 /* -------------------------------------------------------------------- */
-    char *pszExpandedFilename = NULL;
-
     if( pszFilename == NULL )
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "Missing <SourceFilename> element in VRTRasterBand." );
         return CE_Failure;
     }
-    
-    if( pszVRTPath != NULL && bRelativeToVRT )
+
+    char *pszExpandedFilename = NULL;
+    if( pszVRTPath != NULL && bRelativeToVRTIn )
     {
         pszExpandedFilename = CPLStrdup(
             CPLProjectRelativeFilename( pszVRTPath, pszFilename ) );
@@ -202,26 +198,27 @@ CPLErr VRTRawRasterBand::SetRawLink( const char *pszFilename,
     if( fp == NULL )
         fp = CPLOpenShared( pszExpandedFilename, "rb", TRUE );
 
-    if( fp == NULL && ((VRTDataset *)poDS)->GetAccess() == GA_Update )
+    if( fp == NULL
+        && reinterpret_cast<VRTDataset *>( poDS )->GetAccess() == GA_Update )
     {
         fp = CPLOpenShared( pszExpandedFilename, "wb+", TRUE );
     }
 
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Unable to open %s.\n%s", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Unable to open %s.\n%s",
                   pszExpandedFilename,
                   VSIStrerror( errno ) );
-        
+
         CPLFree( pszExpandedFilename );
         return CE_Failure;
     }
 
     CPLFree( pszExpandedFilename );
 
-    pszSourceFilename = CPLStrdup(pszFilename);
-    this->bRelativeToVRT = bRelativeToVRT;
+    m_pszSourceFilename = CPLStrdup(pszFilename);
+    m_bRelativeToVRT = bRelativeToVRTIn;
 
 /* -------------------------------------------------------------------- */
 /*      Work out if we are in native mode or not.                       */
@@ -236,8 +233,8 @@ CPLErr VRTRawRasterBand::SetRawLink( const char *pszFilename,
             bNative = !CPL_IS_LSB;
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Illegal ByteOrder value '%s', should be LSB or MSB.", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Illegal ByteOrder value '%s', should be LSB or MSB.",
                       pszByteOrder );
             return CE_Failure;
         }
@@ -246,14 +243,14 @@ CPLErr VRTRawRasterBand::SetRawLink( const char *pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding RawRasterBand.                           */
 /* -------------------------------------------------------------------- */
-    poRawRaster = new RawRasterBand( fp, nImageOffset, nPixelOffset, 
-                                     nLineOffset, GetRasterDataType(), 
+    m_poRawRaster = new RawRasterBand( fp, nImageOffset, nPixelOffset,
+                                     nLineOffset, GetRasterDataType(),
                                      bNative, GetXSize(), GetYSize(), TRUE );
 
 /* -------------------------------------------------------------------- */
 /*      Reset block size to match the raw raster.                       */
 /* -------------------------------------------------------------------- */
-    poRawRaster->GetBlockSize( &nBlockXSize, &nBlockYSize );
+    m_poRawRaster->GetBlockSize( &nBlockXSize, &nBlockYSize );
 
     return CE_None;
 }
@@ -265,45 +262,42 @@ CPLErr VRTRawRasterBand::SetRawLink( const char *pszFilename,
 void VRTRawRasterBand::ClearRawLink()
 
 {
-    if( poRawRaster != NULL )
+    if( m_poRawRaster != NULL )
     {
-        VSILFILE* fp = poRawRaster->GetFPL();
-        delete poRawRaster;
-        poRawRaster = NULL;
+        VSILFILE* fp = m_poRawRaster->GetFPL();
+        delete m_poRawRaster;
+        m_poRawRaster = NULL;
         /* We close the file after deleting the raster band */
         /* since data can be flushed in the destructor */
         if( fp != NULL )
         {
-            CPLCloseShared( (FILE*) fp );
+            CPLCloseShared( reinterpret_cast<FILE*>( fp ) );
         }
     }
-    CPLFree( pszSourceFilename );
-    pszSourceFilename = NULL;
+    CPLFree( m_pszSourceFilename );
+    m_pszSourceFilename = NULL;
 }
 
 /************************************************************************/
 /*                              XMLInit()                               */
 /************************************************************************/
 
-CPLErr VRTRawRasterBand::XMLInit( CPLXMLNode * psTree, 
+CPLErr VRTRawRasterBand::XMLInit( CPLXMLNode * psTree,
                                       const char *pszVRTPath )
 
 {
-    CPLErr eErr;
-
-    eErr = VRTRasterBand::XMLInit( psTree, pszVRTPath );
+    CPLErr eErr = VRTRasterBand::XMLInit( psTree, pszVRTPath );
     if( eErr != CE_None )
         return eErr;
-    
 
 /* -------------------------------------------------------------------- */
 /*      Validate a bit.                                                 */
 /* -------------------------------------------------------------------- */
     if( psTree == NULL || psTree->eType != CXT_Element
-        || !EQUAL(psTree->pszValue,"VRTRasterBand") 
+        || !EQUAL(psTree->pszValue,"VRTRasterBand")
         || !EQUAL(CPLGetXMLValue(psTree,"subClass",""),"VRTRawRasterBand") )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Invalid node passed to VRTRawRasterBand::XMLInit()." );
         return CE_Failure;
     }
@@ -311,30 +305,28 @@ CPLErr VRTRawRasterBand::XMLInit( CPLXMLNode * psTree,
 /* -------------------------------------------------------------------- */
 /*      Prepare filename.                                               */
 /* -------------------------------------------------------------------- */
-    int  bRelativeToVRT;
-
-    const char *pszFilename = 
+    const char *pszFilename =
         CPLGetXMLValue(psTree, "SourceFilename", NULL);
 
     if( pszFilename == NULL )
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "Missing <SourceFilename> element in VRTRasterBand." );
         return CE_Failure;
     }
 
-    bRelativeToVRT = atoi(CPLGetXMLValue(psTree,"SourceFilename.relativeToVRT",
-                                         "1"));
-    
+    const int l_bRelativeToVRT
+        = atoi(CPLGetXMLValue( psTree, "SourceFilename.relativeToVRT", "1" ) );
+
 /* -------------------------------------------------------------------- */
 /*      Collect layout information.                                     */
 /* -------------------------------------------------------------------- */
-    int nPixelOffset, nLineOffset;
+    int nPixelOffset;
     int nWordDataSize = GDALGetDataTypeSize( GetRasterDataType() ) / 8;
 
     const char* pszImageOffset = CPLGetXMLValue( psTree, "ImageOffset", "0");
     const vsi_l_offset nImageOffset = CPLScanUIntBig(
-                                    pszImageOffset, strlen(pszImageOffset));
+                        pszImageOffset, static_cast<int>(strlen(pszImageOffset)));
 
     if( CPLGetXMLValue( psTree, "PixelOffset", NULL ) == NULL )
         nPixelOffset = nWordDataSize;
@@ -342,11 +334,12 @@ CPLErr VRTRawRasterBand::XMLInit( CPLXMLNode * psTree,
         nPixelOffset = atoi(CPLGetXMLValue( psTree, "PixelOffset", "0") );
     if (nPixelOffset <= 0)
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Invalid value for <PixelOffset> element : %d", nPixelOffset );
         return CE_Failure;
     }
-    
+
+    int nLineOffset;
     if( CPLGetXMLValue( psTree, "LineOffset", NULL ) == NULL )
         nLineOffset = nWordDataSize * GetXSize();
     else
@@ -357,8 +350,8 @@ CPLErr VRTRawRasterBand::XMLInit( CPLXMLNode * psTree,
 /* -------------------------------------------------------------------- */
 /*      Open the file, and setup the raw layer access to the data.      */
 /* -------------------------------------------------------------------- */
-    return SetRawLink( pszFilename, pszVRTPath, bRelativeToVRT, 
-                       nImageOffset, nPixelOffset, nLineOffset, 
+    return SetRawLink( pszFilename, pszVRTPath, l_bRelativeToVRT,
+                       nImageOffset, nPixelOffset, nLineOffset,
                        pszByteOrder );
 }
 
@@ -380,66 +373,63 @@ static const char* VRTRawStripSpace(const char* pszStr)
 CPLXMLNode *VRTRawRasterBand::SerializeToXML( const char *pszVRTPath )
 
 {
-    CPLXMLNode *psTree;
 
-    psTree = VRTRasterBand::SerializeToXML( pszVRTPath );
+/* -------------------------------------------------------------------- */
+/*      We can't set the layout if there is no open rawband.            */
+/* -------------------------------------------------------------------- */
+    if( m_poRawRaster == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "VRTRawRasterBand::SerializeToXML() fails because m_poRawRaster is NULL." );
+        return NULL;
+    }
+
+    CPLXMLNode *psTree = VRTRasterBand::SerializeToXML( pszVRTPath );
 
 /* -------------------------------------------------------------------- */
 /*      Set subclass.                                                   */
 /* -------------------------------------------------------------------- */
-    CPLCreateXMLNode( 
-        CPLCreateXMLNode( psTree, CXT_Attribute, "subClass" ), 
+    CPLCreateXMLNode(
+        CPLCreateXMLNode( psTree, CXT_Attribute, "subClass" ),
         CXT_Text, "VRTRawRasterBand" );
 
 /* -------------------------------------------------------------------- */
 /*      Setup the filename with relative flag.                          */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psNode;
+    CPLXMLNode *psNode
+        = CPLCreateXMLElementAndValue( psTree, "SourceFilename",
+                                       m_pszSourceFilename );
 
-    psNode = 
-        CPLCreateXMLElementAndValue( psTree, "SourceFilename", 
-                                     pszSourceFilename );
-    
-    CPLCreateXMLNode( 
-        CPLCreateXMLNode( psNode, CXT_Attribute, "relativeToVRT" ), 
-        CXT_Text, bRelativeToVRT ? "1" : "0"  );
-
-/* -------------------------------------------------------------------- */
-/*      We can't set the layout if there is no open rawband.            */
-/* -------------------------------------------------------------------- */
-    if( poRawRaster == NULL )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "VRTRawRasterBand::SerializeToXML() fails because poRawRaster is NULL." );
-        return NULL;
-    }
+    CPLCreateXMLNode(
+        CPLCreateXMLNode( psNode, CXT_Attribute, "relativeToVRT" ),
+        CXT_Text, m_bRelativeToVRT ? "1" : "0"  );
 
 /* -------------------------------------------------------------------- */
 /*      Set other layout information.                                   */
 /* -------------------------------------------------------------------- */
     char szOffset[22];
-    
-    CPLPrintUIntBig(szOffset, poRawRaster->GetImgOffset(), sizeof(szOffset)-1);
+
+    CPLPrintUIntBig(szOffset, m_poRawRaster->GetImgOffset(), sizeof(szOffset)-1);
     szOffset[sizeof(szOffset)-1] = '\0';
     CPLCreateXMLElementAndValue(psTree, "ImageOffset", VRTRawStripSpace(szOffset));
-    
-    CPLPrintUIntBig(szOffset, poRawRaster->GetPixelOffset(),sizeof(szOffset)-1);
+
+    CPLPrintUIntBig(szOffset, m_poRawRaster->GetPixelOffset(),sizeof(szOffset)-1);
     szOffset[sizeof(szOffset)-1] = '\0';
     CPLCreateXMLElementAndValue(psTree, "PixelOffset", VRTRawStripSpace(szOffset));
-    
-    CPLPrintUIntBig(szOffset, poRawRaster->GetLineOffset(), sizeof(szOffset)-1);
+
+    CPLPrintUIntBig(szOffset, m_poRawRaster->GetLineOffset(), sizeof(szOffset)-1);
     szOffset[sizeof(szOffset)-1] = '\0';
     CPLCreateXMLElementAndValue(psTree, "LineOffset", VRTRawStripSpace(szOffset));
 
 #if CPL_IS_LSB == 1
-    if( poRawRaster->GetNativeOrder() )
+    if( m_poRawRaster->GetNativeOrder() )
 #else
-    if( !poRawRaster->GetNativeOrder() )
+    if( !m_poRawRaster->GetNativeOrder() )
 #endif
         CPLCreateXMLElementAndValue( psTree, "ByteOrder", "LSB" );
     else
         CPLCreateXMLElementAndValue( psTree, "ByteOrder", "MSB" );
-    
+
     return psTree;
 }
 
@@ -450,32 +440,32 @@ CPLXMLNode *VRTRawRasterBand::SerializeToXML( const char *pszVRTPath )
 void VRTRawRasterBand::GetFileList(char*** ppapszFileList, int *pnSize,
                                 int *pnMaxSize, CPLHashSet* hSetFiles)
 {
-    if (pszSourceFilename == NULL)
+    if (m_pszSourceFilename == NULL)
         return;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Is it already in the list ?                                     */
 /* -------------------------------------------------------------------- */
-    if( CPLHashSetLookup(hSetFiles, pszSourceFilename) != NULL )
+    if( CPLHashSetLookup(hSetFiles, m_pszSourceFilename) != NULL )
         return;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Grow array if necessary                                         */
 /* -------------------------------------------------------------------- */
     if (*pnSize + 1 >= *pnMaxSize)
     {
         *pnMaxSize = 2 + 2 * (*pnMaxSize);
-        *ppapszFileList = (char **) CPLRealloc(
-                    *ppapszFileList, sizeof(char*)  * (*pnMaxSize) );
+        *ppapszFileList = reinterpret_cast<char **>(
+            CPLRealloc( *ppapszFileList, sizeof(char*) * (*pnMaxSize) ) );
     }
-            
+
 /* -------------------------------------------------------------------- */
 /*      Add the string to the list                                      */
 /* -------------------------------------------------------------------- */
-    (*ppapszFileList)[*pnSize] = CPLStrdup(pszSourceFilename);
+    (*ppapszFileList)[*pnSize] = CPLStrdup(m_pszSourceFilename);
     (*ppapszFileList)[(*pnSize + 1)] = NULL;
     CPLHashSetInsert(hSetFiles, (*ppapszFileList)[*pnSize]);
-    
+
     (*pnSize) ++;
 
     VRTRasterBand::GetFileList( ppapszFileList, pnSize,
diff --git a/frmts/vrt/vrtsourcedrasterband.cpp b/frmts/vrt/vrtsourcedrasterband.cpp
index 6869d46..d863860 100644
--- a/frmts/vrt/vrtsourcedrasterband.cpp
+++ b/frmts/vrt/vrtsourcedrasterband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtsourcedrasterband.cpp 29907 2015-08-29 19:39:38Z rouault $
+ * $Id: vrtsourcedrasterband.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTSourcedRasterBand
@@ -32,7 +32,7 @@
 #include "cpl_minixml.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: vrtsourcedrasterband.cpp 29907 2015-08-29 19:39:38Z rouault $");
+CPL_CVSID("$Id: vrtsourcedrasterband.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -44,20 +44,20 @@ CPL_CVSID("$Id: vrtsourcedrasterband.cpp 29907 2015-08-29 19:39:38Z rouault $");
 /*                        VRTSourcedRasterBand()                        */
 /************************************************************************/
 
-VRTSourcedRasterBand::VRTSourcedRasterBand( GDALDataset *poDS, int nBand )
+VRTSourcedRasterBand::VRTSourcedRasterBand( GDALDataset *poDSIn, int nBandIn )
 
 {
-    Initialize( poDS->GetRasterXSize(), poDS->GetRasterYSize() );
+    Initialize( poDSIn->GetRasterXSize(), poDSIn->GetRasterYSize() );
 
-    this->poDS = poDS;
-    this->nBand = nBand;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
 }
 
 /************************************************************************/
 /*                        VRTSourcedRasterBand()                        */
 /************************************************************************/
 
-VRTSourcedRasterBand::VRTSourcedRasterBand( GDALDataType eType, 
+VRTSourcedRasterBand::VRTSourcedRasterBand( GDALDataType eType,
                                             int nXSize, int nYSize )
 
 {
@@ -70,15 +70,15 @@ VRTSourcedRasterBand::VRTSourcedRasterBand( GDALDataType eType,
 /*                        VRTSourcedRasterBand()                        */
 /************************************************************************/
 
-VRTSourcedRasterBand::VRTSourcedRasterBand( GDALDataset *poDS, int nBand,
-                                            GDALDataType eType, 
+VRTSourcedRasterBand::VRTSourcedRasterBand( GDALDataset *poDSIn, int nBandIn,
+                                            GDALDataType eType,
                                             int nXSize, int nYSize )
 
 {
     Initialize( nXSize, nYSize );
 
-    this->poDS = poDS;
-    this->nBand = nBand;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
 
     eDataType = eType;
 }
@@ -95,8 +95,8 @@ void VRTSourcedRasterBand::Initialize( int nXSize, int nYSize )
     nSources = 0;
     papoSources = NULL;
     bEqualAreas = FALSE;
-    nRecursionCounter = 0;
-    papszSourceList = NULL;
+    m_nRecursionCounter = 0;
+    m_papszSourceList = NULL;
 }
 
 /************************************************************************/
@@ -107,7 +107,7 @@ VRTSourcedRasterBand::~VRTSourcedRasterBand()
 
 {
     CloseDependentDatasets();
-    CSLDestroy(papszSourceList);
+    CSLDestroy(m_papszSourceList);
 }
 
 /************************************************************************/
@@ -123,24 +123,55 @@ CPLErr VRTSourcedRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                                  GDALRasterIOExtraArg* psExtraArg )
 
 {
-    int         iSource;
-    CPLErr      eErr = CE_None;
+    // If resampling with non-nearest neighbour, we need to be careful
+    // if the VRT band exposes a nodata value, but the sources do not have it
+    if (eRWFlag == GF_Read &&
+        (nXSize != nBufXSize || nYSize != nBufYSize) &&
+        psExtraArg->eResampleAlg != GRIORA_NearestNeighbour &&
+        m_bNoDataValueSet )
+    {
+        for( int i = 0; i < nSources; i++ )
+        {
+            bool bFallbackToBase = false;
+            if( !papoSources[i]->IsSimpleSource() )
+                bFallbackToBase = true;
+            else
+            {
+                VRTSimpleSource* poSource
+                    = reinterpret_cast<VRTSimpleSource *>( papoSources[i] );
+                int bSrcHasNoData = FALSE;
+                double dfSrcNoData = poSource->GetBand()->GetNoDataValue(&bSrcHasNoData);
+                if( !bSrcHasNoData || dfSrcNoData != m_dfNoDataValue )
+                    bFallbackToBase = true;
+            }
+            if( bFallbackToBase )
+            {
+                return GDALRasterBand::IRasterIO( eRWFlag,
+                                                nXOff, nYOff, nXSize, nYSize,
+                                                pData, nBufXSize, nBufYSize,
+                                                eBufType,
+                                                nPixelSpace,
+                                                nLineSpace,
+                                                psExtraArg );
+            }
+        }
+    }
 
     if( eRWFlag == GF_Write )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Writing through VRTSourcedRasterBand is not supported." );
         return CE_Failure;
     }
-    
-    /* When using GDALProxyPoolDataset for sources, the recusion will not be */
-    /* detected at VRT opening but when doing RasterIO. As the proxy pool will */
-    /* return the already opened dataset, we can just test a member variable. */
-    /* We allow 1, since IRasterIO() can be called from ComputeStatistics(), which */
-    /* itselfs increments the recursion counter */
-    if ( nRecursionCounter > 1 )
+
+    // When using GDALProxyPoolDataset for sources, the recursion will not be
+    // detected at VRT opening but when doing RasterIO. As the proxy pool will
+    // return the already opened dataset, we can just test a member variable.
+    // We allow 1, since IRasterIO() can be called from ComputeStatistics(),
+    // which itself increments the recursion counter.
+    if ( m_nRecursionCounter > 1 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "VRTSourcedRasterBand::IRasterIO() called recursively on the same band. "
                   "It looks like the VRT is referencing itself." );
         return CE_Failure;
@@ -153,8 +184,8 @@ CPLErr VRTSourcedRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     if( (nBufXSize < nXSize || nBufYSize < nYSize)
         && GetOverviewCount() > 0 )
     {
-        if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, 
-                              pData, nBufXSize, nBufYSize, 
+        if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                              pData, nBufXSize, nBufYSize,
                               eBufType, nPixelSpace, nLineSpace, psExtraArg ) == CE_None )
             return CE_None;
     }
@@ -164,38 +195,39 @@ CPLErr VRTSourcedRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 /*      nodata value if available.                                      */
 /* -------------------------------------------------------------------- */
     if ( nPixelSpace == GDALGetDataTypeSize(eBufType)/8 &&
-         (!bNoDataValueSet || (!CPLIsNan(dfNoDataValue) && dfNoDataValue == 0)) )
+         (!m_bNoDataValueSet || (!CPLIsNan(m_dfNoDataValue) && m_dfNoDataValue == 0)) )
     {
         if (nLineSpace == nBufXSize * nPixelSpace)
         {
-             memset( pData, 0, (GIntBig)nBufYSize * nLineSpace );
+             memset( pData, 0, static_cast<size_t>(nBufYSize * nLineSpace) );
         }
         else
         {
-            int    iLine;
-            for( iLine = 0; iLine < nBufYSize; iLine++ )
+            for( int iLine = 0; iLine < nBufYSize; iLine++ )
             {
-                memset( ((GByte*)pData) + (GIntBig)iLine * nLineSpace, 0, nBufXSize * nPixelSpace );
+                memset( reinterpret_cast<GByte *>( pData )
+                        + static_cast<GIntBig>(iLine) * nLineSpace,
+                        0,
+                        static_cast<size_t>(nBufXSize * nPixelSpace) );
             }
         }
     }
-    else if ( !bEqualAreas || bNoDataValueSet )
+    else if ( !bEqualAreas || m_bNoDataValueSet )
     {
         double dfWriteValue = 0.0;
-        int    iLine;
+        if( m_bNoDataValueSet )
+            dfWriteValue = m_dfNoDataValue;
 
-        if( bNoDataValueSet )
-            dfWriteValue = dfNoDataValue;
-        
-        for( iLine = 0; iLine < nBufYSize; iLine++ )
+        for( int iLine = 0; iLine < nBufYSize; iLine++ )
         {
-            GDALCopyWords( &dfWriteValue, GDT_Float64, 0, 
-                           ((GByte *)pData) + (GIntBig)nLineSpace * iLine, 
-                           eBufType, nPixelSpace, nBufXSize );
+            GDALCopyWords( &dfWriteValue, GDT_Float64, 0,
+                           reinterpret_cast<GByte *>( pData )
+                           + static_cast<GIntBig>( nLineSpace ) * iLine,
+                           eBufType, static_cast<int>(nPixelSpace), nBufXSize );
         }
     }
-    
-    nRecursionCounter ++;
+
+    m_nRecursionCounter ++;
 
     GDALProgressFunc  pfnProgressGlobal = psExtraArg->pfnProgress;
     void             *pProgressDataGlobal = psExtraArg->pProgressData;
@@ -203,10 +235,11 @@ CPLErr VRTSourcedRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 /* -------------------------------------------------------------------- */
 /*      Overlay each source in turn over top this.                      */
 /* -------------------------------------------------------------------- */
-    for( iSource = 0; eErr == CE_None && iSource < nSources; iSource++ )
+    CPLErr eErr = CE_None;
+    for( int iSource = 0; eErr == CE_None && iSource < nSources; iSource++ )
     {
         psExtraArg->pfnProgress = GDALScaledProgress;
-        psExtraArg->pProgressData = 
+        psExtraArg->pProgressData =
                 GDALCreateScaledProgress( 1.0 * iSource / nSources,
                                         1.0 * (iSource + 1) / nSources,
                                         pfnProgressGlobal,
@@ -214,9 +247,9 @@ CPLErr VRTSourcedRasterBand::IRasterIO( GDALRWFlag eRWFlag,
         if( psExtraArg->pProgressData == NULL )
             psExtraArg->pfnProgress = NULL;
 
-        eErr = 
-            papoSources[iSource]->RasterIO( nXOff, nYOff, nXSize, nYSize, 
-                                            pData, nBufXSize, nBufYSize, 
+        eErr =
+            papoSources[iSource]->RasterIO( nXOff, nYOff, nXSize, nYSize,
+                                            pData, nBufXSize, nBufYSize,
                                             eBufType, nPixelSpace, nLineSpace,
                                             psExtraArg);
 
@@ -226,8 +259,8 @@ CPLErr VRTSourcedRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     psExtraArg->pfnProgress = pfnProgressGlobal;
     psExtraArg->pProgressData = pProgressDataGlobal;
 
-    nRecursionCounter --;
-    
+    m_nRecursionCounter --;
+
     return eErr;
 }
 
@@ -239,14 +272,15 @@ CPLErr VRTSourcedRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                    void * pImage )
 
 {
-    int nPixelSize = GDALGetDataTypeSize(eDataType)/8;
-    int nReadXSize, nReadYSize;
+    const int nPixelSize = GDALGetDataTypeSize(eDataType)/8;
 
+    int nReadXSize;
     if( (nBlockXOff+1) * nBlockXSize > GetXSize() )
         nReadXSize = GetXSize() - nBlockXOff * nBlockXSize;
     else
         nReadXSize = nBlockXSize;
 
+    int nReadYSize;
     if( (nBlockYOff+1) * nBlockYSize > GetYSize() )
         nReadYSize = GetYSize() - nBlockYOff * nBlockYSize;
     else
@@ -255,10 +289,10 @@ CPLErr VRTSourcedRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     GDALRasterIOExtraArg sExtraArg;
     INIT_RASTERIO_EXTRA_ARG(sExtraArg);
 
-    return IRasterIO( GF_Read, 
-                      nBlockXOff * nBlockXSize, nBlockYOff * nBlockYSize, 
-                      nReadXSize, nReadYSize, 
-                      pImage, nReadXSize, nReadYSize, eDataType, 
+    return IRasterIO( GF_Read,
+                      nBlockXOff * nBlockXSize, nBlockYOff * nBlockYSize,
+                      nReadXSize, nReadYSize,
+                      pImage, nReadXSize, nReadYSize, eDataType,
                       nPixelSize, nPixelSize * nBlockXSize, &sExtraArg );
 }
 
@@ -271,7 +305,7 @@ int VRTSourcedRasterBand::CanUseSourcesMinMaxImplementations()
 {
     const char* pszUseSources = CPLGetConfigOption("VRT_MIN_MAX_FROM_SOURCES", NULL);
     if( pszUseSources )
-        return CSLTestBoolean(pszUseSources);
+        return CPLTestBool(pszUseSources);
 
     // Use heuristics to determine if we are going to use the source GetMinimum()
     // or GetMaximum() implementation: all the sources must be "simple" sources
@@ -283,7 +317,8 @@ int VRTSourcedRasterBand::CanUseSourcesMinMaxImplementations()
     {
         if( !(papoSources[iSource]->IsSimpleSource()) )
             return FALSE;
-        VRTSimpleSource* poSimpleSource = (VRTSimpleSource*) papoSources[iSource];
+        VRTSimpleSource* poSimpleSource
+            = reinterpret_cast<VRTSimpleSource *>( papoSources[iSource] );
         GDALRasterBand* poBand = poSimpleSource->GetBand();
         if( poBand == NULL )
             return FALSE;
@@ -293,16 +328,15 @@ int VRTSourcedRasterBand::CanUseSourcesMinMaxImplementations()
         if( pszFilename == NULL )
             return FALSE;
         /* /vsimem/ should be fast */
-        if( strncmp(pszFilename, "/vsimem/", 8) == 0 )
+        if( STARTS_WITH(pszFilename, "/vsimem/") )
             continue;
         /* but not other /vsi filesystems */
-        if( strncmp(pszFilename, "/vsi", 4) == 0 )
+        if( STARTS_WITH(pszFilename, "/vsi") )
             return FALSE;
-        int i = 0;
         char ch;
         /* We will assume that filenames that are only with ascii characters */
         /* are real filenames and so we will not try to 'stat' them */
-        for( i = 0; (ch = pszFilename[i]) != '\0'; i++ )
+        for( int i = 0; (ch = pszFilename[i]) != '\0'; i++ )
         {
             if( !((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
                   (ch >= '0' && ch <= '9') || ch == ':' || ch == '/' || ch == '\\' ||
@@ -326,12 +360,11 @@ int VRTSourcedRasterBand::CanUseSourcesMinMaxImplementations()
 
 double VRTSourcedRasterBand::GetMinimum( int *pbSuccess )
 {
-    const char *pszValue = NULL;
-
     if( !CanUseSourcesMinMaxImplementations() )
         return GDALRasterBand::GetMinimum(pbSuccess);
 
-    if( (pszValue = GetMetadataItem("STATISTICS_MINIMUM")) != NULL )
+    const char *pszValue = GetMetadataItem("STATISTICS_MINIMUM");
+    if( pszValue != NULL )
     {
         if( pbSuccess != NULL )
             *pbSuccess = TRUE;
@@ -339,7 +372,7 @@ double VRTSourcedRasterBand::GetMinimum( int *pbSuccess )
         return CPLAtofM(pszValue);
     }
 
-    if ( nRecursionCounter > 0 )
+    if ( m_nRecursionCounter > 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "VRTSourcedRasterBand::GetMinimum() called recursively on the same band. "
@@ -348,17 +381,19 @@ double VRTSourcedRasterBand::GetMinimum( int *pbSuccess )
             *pbSuccess = FALSE;
         return 0.0;
     }
-    nRecursionCounter ++;
+    m_nRecursionCounter ++;
 
     double dfMin = 0;
     for( int iSource = 0; iSource < nSources; iSource++ )
     {
         int bSuccess = FALSE;
-        double dfSourceMin = papoSources[iSource]->GetMinimum(GetXSize(), GetYSize(), &bSuccess);
+        double dfSourceMin
+            = papoSources[iSource]->GetMinimum(GetXSize(), GetYSize(),
+                                               &bSuccess);
         if (!bSuccess)
         {
             dfMin = GDALRasterBand::GetMinimum(pbSuccess);
-            nRecursionCounter --;
+            m_nRecursionCounter --;
             return dfMin;
         }
 
@@ -366,7 +401,7 @@ double VRTSourcedRasterBand::GetMinimum( int *pbSuccess )
             dfMin = dfSourceMin;
     }
 
-    nRecursionCounter --;
+    m_nRecursionCounter --;
 
     if( pbSuccess != NULL )
         *pbSuccess = TRUE;
@@ -380,12 +415,11 @@ double VRTSourcedRasterBand::GetMinimum( int *pbSuccess )
 
 double VRTSourcedRasterBand::GetMaximum(int *pbSuccess )
 {
-    const char *pszValue = NULL;
-
     if( !CanUseSourcesMinMaxImplementations() )
         return GDALRasterBand::GetMaximum(pbSuccess);
 
-    if( (pszValue = GetMetadataItem("STATISTICS_MAXIMUM")) != NULL )
+    const char *pszValue = GetMetadataItem("STATISTICS_MAXIMUM");
+    if( pszValue != NULL )
     {
         if( pbSuccess != NULL )
             *pbSuccess = TRUE;
@@ -393,7 +427,7 @@ double VRTSourcedRasterBand::GetMaximum(int *pbSuccess )
         return CPLAtofM(pszValue);
     }
 
-    if ( nRecursionCounter > 0 )
+    if ( m_nRecursionCounter > 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "VRTSourcedRasterBand::GetMaximum() called recursively on the same band. "
@@ -402,7 +436,7 @@ double VRTSourcedRasterBand::GetMaximum(int *pbSuccess )
             *pbSuccess = FALSE;
         return 0.0;
     }
-    nRecursionCounter ++;
+    m_nRecursionCounter ++;
 
     double dfMax = 0;
     for( int iSource = 0; iSource < nSources; iSource++ )
@@ -412,7 +446,7 @@ double VRTSourcedRasterBand::GetMaximum(int *pbSuccess )
         if (!bSuccess)
         {
             dfMax = GDALRasterBand::GetMaximum(pbSuccess);
-            nRecursionCounter --;
+            m_nRecursionCounter --;
             return dfMax;
         }
 
@@ -420,7 +454,7 @@ double VRTSourcedRasterBand::GetMaximum(int *pbSuccess )
             dfMax = dfSourceMax;
     }
 
-    nRecursionCounter --;
+    m_nRecursionCounter --;
 
     if( pbSuccess != NULL )
         *pbSuccess = TRUE;
@@ -454,31 +488,30 @@ CPLErr VRTSourcedRasterBand::ComputeRasterMinMax( int bApproxOK, double* adfMinM
             return CE_None;
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      If we have overview bands, use them for min/max.                */
 /* -------------------------------------------------------------------- */
     if ( bApproxOK && GetOverviewCount() > 0 && !HasArbitraryOverviews() )
     {
-        GDALRasterBand *poBand;
-
-        poBand = GetRasterSampleOverview( GDALSTAT_APPROX_NUMSAMPLES );
+        GDALRasterBand *poBand
+            = GetRasterSampleOverview( GDALSTAT_APPROX_NUMSAMPLES );
 
         if ( poBand != this )
-            return poBand->ComputeRasterMinMax( FALSE, adfMinMax );
+            return poBand->ComputeRasterMinMax( TRUE, adfMinMax );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Try with source bands.                                          */
 /* -------------------------------------------------------------------- */
-    if ( nRecursionCounter > 0 )
+    if ( m_nRecursionCounter > 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "VRTSourcedRasterBand::ComputeRasterMinMax() called recursively on the same band. "
                   "It looks like the VRT is referencing itself." );
         return CE_Failure;
     }
-    nRecursionCounter ++;
+    m_nRecursionCounter ++;
 
     adfMinMax[0] = 0.0;
     adfMinMax[1] = 0.0;
@@ -489,7 +522,7 @@ CPLErr VRTSourcedRasterBand::ComputeRasterMinMax( int bApproxOK, double* adfMinM
         if (eErr != CE_None)
         {
             eErr = GDALRasterBand::ComputeRasterMinMax(bApproxOK, adfMinMax);
-            nRecursionCounter --;
+            m_nRecursionCounter --;
             return eErr;
         }
 
@@ -499,7 +532,7 @@ CPLErr VRTSourcedRasterBand::ComputeRasterMinMax( int bApproxOK, double* adfMinM
             adfMinMax[1] = adfSourceMinMax[1];
     }
 
-    nRecursionCounter --;
+    m_nRecursionCounter --;
 
     return CE_None;
 }
@@ -508,17 +541,17 @@ CPLErr VRTSourcedRasterBand::ComputeRasterMinMax( int bApproxOK, double* adfMinM
 /*                         ComputeStatistics()                          */
 /************************************************************************/
 
-CPLErr 
+CPLErr
 VRTSourcedRasterBand::ComputeStatistics( int bApproxOK,
-                                   double *pdfMin, double *pdfMax, 
+                                   double *pdfMin, double *pdfMax,
                                    double *pdfMean, double *pdfStdDev,
-                                   GDALProgressFunc pfnProgress, 
+                                   GDALProgressFunc pfnProgress,
                                    void *pProgressData )
 
 {
-    if( nSources != 1 || bNoDataValueSet )
-        return GDALRasterBand::ComputeStatistics(  bApproxOK,  
-                                              pdfMin, pdfMax, 
+    if( nSources != 1 || m_bNoDataValueSet )
+        return GDALRasterBand::ComputeStatistics(  bApproxOK,
+                                              pdfMin, pdfMax,
                                               pdfMean, pdfStdDev,
                                               pfnProgress, pProgressData );
 
@@ -530,13 +563,12 @@ VRTSourcedRasterBand::ComputeStatistics( int bApproxOK,
 /* -------------------------------------------------------------------- */
     if( bApproxOK && GetOverviewCount() > 0 && !HasArbitraryOverviews() )
     {
-        GDALRasterBand *poBand;
-
-        poBand = GetRasterSampleOverview( GDALSTAT_APPROX_NUMSAMPLES );
+        GDALRasterBand *poBand
+            = GetRasterSampleOverview( GDALSTAT_APPROX_NUMSAMPLES );
 
         if( poBand != this )
-            return poBand->ComputeStatistics( FALSE,  
-                                              pdfMin, pdfMax, 
+            return poBand->ComputeStatistics( TRUE,
+                                              pdfMin, pdfMax,
                                               pdfMean, pdfStdDev,
                                               pfnProgress, pProgressData );
     }
@@ -544,32 +576,32 @@ VRTSourcedRasterBand::ComputeStatistics( int bApproxOK,
 /* -------------------------------------------------------------------- */
 /*      Try with source bands.                                          */
 /* -------------------------------------------------------------------- */
-    if ( nRecursionCounter > 0 )
+    if ( m_nRecursionCounter > 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "VRTSourcedRasterBand::ComputeStatistics() called recursively on the same band. "
                   "It looks like the VRT is referencing itself." );
         return CE_Failure;
     }
-    nRecursionCounter ++;
-    
+    m_nRecursionCounter ++;
+
     double dfMin = 0.0, dfMax = 0.0, dfMean = 0.0, dfStdDev = 0.0;
 
-    CPLErr eErr = papoSources[0]->ComputeStatistics(GetXSize(), GetYSize(), bApproxOK,  
-                                                    &dfMin, &dfMax, 
+    CPLErr eErr = papoSources[0]->ComputeStatistics(GetXSize(), GetYSize(), bApproxOK,
+                                                    &dfMin, &dfMax,
                                                     &dfMean, &dfStdDev,
                                                     pfnProgress, pProgressData);
     if (eErr != CE_None)
     {
-        eErr = GDALRasterBand::ComputeStatistics(bApproxOK,  
-                                                 pdfMin, pdfMax, 
+        eErr = GDALRasterBand::ComputeStatistics(bApproxOK,
+                                                 pdfMin, pdfMax,
                                                  pdfMean, pdfStdDev,
                                                  pfnProgress, pProgressData);
-        nRecursionCounter --;
+        m_nRecursionCounter --;
         return eErr;
     }
 
-    nRecursionCounter --;
+    m_nRecursionCounter --;
 
     SetStatistics( dfMin, dfMax, dfMean, dfStdDev );
 
@@ -594,10 +626,10 @@ VRTSourcedRasterBand::ComputeStatistics( int bApproxOK,
 /*                            GetHistogram()                            */
 /************************************************************************/
 
-CPLErr VRTSourcedRasterBand::GetHistogram( double dfMin, double dfMax, 
-                                     int nBuckets, GUIntBig *panHistogram, 
+CPLErr VRTSourcedRasterBand::GetHistogram( double dfMin, double dfMax,
+                                     int nBuckets, GUIntBig *panHistogram,
                                      int bIncludeOutOfRange, int bApproxOK,
-                                     GDALProgressFunc pfnProgress, 
+                                     GDALProgressFunc pfnProgress,
                                      void *pProgressData )
 
 {
@@ -619,7 +651,7 @@ CPLErr VRTSourcedRasterBand::GetHistogram( double dfMin, double dfMax,
         // minimum number of samples like GDALRasterBand::ComputeStatistics()
         // does?
         GDALRasterBand *poBestOverview = GetRasterSampleOverview( 0 );
-        
+
         if( poBestOverview != this )
         {
             return poBestOverview->GetHistogram( dfMin, dfMax, nBuckets,
@@ -632,14 +664,14 @@ CPLErr VRTSourcedRasterBand::GetHistogram( double dfMin, double dfMax,
 /* -------------------------------------------------------------------- */
 /*      Try with source bands.                                          */
 /* -------------------------------------------------------------------- */
-    if ( nRecursionCounter > 0 )
+    if ( m_nRecursionCounter > 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "VRTSourcedRasterBand::GetHistogram() called recursively on the same band. "
                   "It looks like the VRT is referencing itself." );
         return CE_Failure;
     }
-    nRecursionCounter ++;
+    m_nRecursionCounter ++;
 
     CPLErr eErr = papoSources[0]->GetHistogram(GetXSize(), GetYSize(), dfMin, dfMax, nBuckets,
                                                panHistogram,
@@ -651,12 +683,12 @@ CPLErr VRTSourcedRasterBand::GetHistogram( double dfMin, double dfMax,
                                                   nBuckets, panHistogram,
                                                   bIncludeOutOfRange, bApproxOK,
                                                   pfnProgress, pProgressData );
-        nRecursionCounter --;
+        m_nRecursionCounter --;
         return eErr;
     }
 
-    nRecursionCounter --;
-    
+    m_nRecursionCounter --;
+
     SetDefaultHistogram( dfMin, dfMax, nBuckets, panHistogram );
 
     return CE_None;
@@ -671,11 +703,18 @@ CPLErr VRTSourcedRasterBand::AddSource( VRTSource *poNewSource )
 {
     nSources++;
 
-    papoSources = (VRTSource **) 
-        CPLRealloc(papoSources, sizeof(void*) * nSources);
+    papoSources = reinterpret_cast<VRTSource **>(
+        CPLRealloc(papoSources, sizeof(void*) * nSources) );
     papoSources[nSources-1] = poNewSource;
 
-    ((VRTDataset *)poDS)->SetNeedsFlush();
+    reinterpret_cast<VRTDataset *>( poDS )->SetNeedsFlush();
+
+    if( poNewSource->IsSimpleSource() &&
+        GetMetadataItem("NBITS", "IMAGE_STRUCTURE") != NULL)
+    {
+        reinterpret_cast<VRTSimpleSource*>( poNewSource )->SetMaxValue(
+                (1 << atoi(GetMetadataItem("NBITS", "IMAGE_STRUCTURE")))-1);
+    }
 
     return CE_None;
 }
@@ -693,33 +732,31 @@ CPLErr CPL_STDCALL VRTAddSource( VRTSourcedRasterBandH hVRTBand,
 {
     VALIDATE_POINTER1( hVRTBand, "VRTAddSource", CE_Failure );
 
-    return ((VRTSourcedRasterBand *) hVRTBand)->
-        AddSource( (VRTSource *)hNewSource );
+    return reinterpret_cast<VRTSourcedRasterBand *>( hVRTBand )->
+        AddSource( reinterpret_cast<VRTSource *>( hNewSource ) );
 }
 
 /************************************************************************/
 /*                              XMLInit()                               */
 /************************************************************************/
 
-CPLErr VRTSourcedRasterBand::XMLInit( CPLXMLNode * psTree, 
+CPLErr VRTSourcedRasterBand::XMLInit( CPLXMLNode * psTree,
                                       const char *pszVRTPath )
 
 {
-    CPLErr eErr;
-
-    eErr = VRTRasterBand::XMLInit( psTree, pszVRTPath );
+    CPLErr eErr = VRTRasterBand::XMLInit( psTree, pszVRTPath );
     if( eErr != CE_None )
         return eErr;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Validate a bit.                                                 */
 /* -------------------------------------------------------------------- */
     if( psTree == NULL || psTree->eType != CXT_Element
-        || (!EQUAL(psTree->pszValue,"VRTSourcedRasterBand") 
+        || (!EQUAL(psTree->pszValue,"VRTSourcedRasterBand")
             && !EQUAL(psTree->pszValue,"VRTRasterBand")
 	    && !EQUAL(psTree->pszValue,"VRTDerivedRasterBand")) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Invalid node passed to VRTSourcedRasterBand::XMLInit()." );
         return CE_Failure;
     }
@@ -727,20 +764,18 @@ CPLErr VRTSourcedRasterBand::XMLInit( CPLXMLNode * psTree,
 /* -------------------------------------------------------------------- */
 /*      Process sources.                                                */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode  *psChild;
-    VRTDriver *poDriver = (VRTDriver *) GDALGetDriverByName( "VRT" );
-    
-    for( psChild = psTree->psChild; 
-         psChild != NULL && poDriver != NULL; 
+    VRTDriver *poDriver = reinterpret_cast<VRTDriver *>(
+        GDALGetDriverByName( "VRT" ) );
+
+    for( CPLXMLNode *psChild = psTree->psChild;
+         psChild != NULL && poDriver != NULL;
          psChild = psChild->psNext)
     {
-        VRTSource *poSource;
-
         if( psChild->eType != CXT_Element )
             continue;
 
         CPLErrorReset();
-        poSource = poDriver->ParseSource( psChild, pszVRTPath );
+        VRTSource *poSource = poDriver->ParseSource( psChild, pszVRTPath );
         if( poSource != NULL )
             AddSource( poSource );
         else if( CPLGetLastErrorType() != CE_None )
@@ -764,9 +799,7 @@ CPLErr VRTSourcedRasterBand::XMLInit( CPLXMLNode * psTree,
 CPLXMLNode *VRTSourcedRasterBand::SerializeToXML( const char *pszVRTPath )
 
 {
-    CPLXMLNode *psTree;
-
-    psTree = VRTRasterBand::SerializeToXML( pszVRTPath );
+    CPLXMLNode *psTree = VRTRasterBand::SerializeToXML( pszVRTPath );
     CPLXMLNode* psLastChild = psTree->psChild;
     while( psLastChild != NULL && psLastChild->psNext != NULL )
         psLastChild = psLastChild->psNext;
@@ -776,10 +809,9 @@ CPLXMLNode *VRTSourcedRasterBand::SerializeToXML( const char *pszVRTPath )
 /* -------------------------------------------------------------------- */
     for( int iSource = 0; iSource < nSources; iSource++ )
     {
-        CPLXMLNode      *psXMLSrc;
+        CPLXMLNode *psXMLSrc
+            = papoSources[iSource]->SerializeToXML( pszVRTPath );
 
-        psXMLSrc = papoSources[iSource]->SerializeToXML( pszVRTPath );
-        
         if( psXMLSrc != NULL )
         {
             if( psLastChild == NULL )
@@ -800,42 +832,42 @@ CPLXMLNode *VRTSourcedRasterBand::SerializeToXML( const char *pszVRTPath )
 void VRTSourcedRasterBand::ConfigureSource(VRTSimpleSource *poSimpleSource,
                                            GDALRasterBand *poSrcBand,
                                            int bAddAsMaskBand,
-                                           int nSrcXOff, int nSrcYOff,
-                                           int nSrcXSize, int nSrcYSize,
-                                           int nDstXOff, int nDstYOff,
-                                           int nDstXSize, int nDstYSize)
+                                           double dfSrcXOff, double dfSrcYOff,
+                                           double dfSrcXSize, double dfSrcYSize,
+                                           double dfDstXOff, double dfDstYOff,
+                                           double dfDstXSize, double dfDstYSize)
 {
 /* -------------------------------------------------------------------- */
 /*      Default source and dest rectangles.                             */
 /* -------------------------------------------------------------------- */
-    if( nSrcYSize == -1 )
+    if( dfSrcYSize == -1 )
     {
-        nSrcXOff = 0;
-        nSrcYOff = 0;
-        nSrcXSize = poSrcBand->GetXSize();
-        nSrcYSize = poSrcBand->GetYSize();
+        dfSrcXOff = 0;
+        dfSrcYOff = 0;
+        dfSrcXSize = poSrcBand->GetXSize();
+        dfSrcYSize = poSrcBand->GetYSize();
     }
 
-    if( nDstYSize == -1 )
+    if( dfDstYSize == -1 )
     {
-        nDstXOff = 0;
-        nDstYOff = 0;
-        nDstXSize = nRasterXSize;
-        nDstYSize = nRasterYSize;
+        dfDstXOff = 0;
+        dfDstYOff = 0;
+        dfDstXSize = nRasterXSize;
+        dfDstYSize = nRasterYSize;
     }
 
     if( bAddAsMaskBand )
         poSimpleSource->SetSrcMaskBand( poSrcBand );
     else
         poSimpleSource->SetSrcBand( poSrcBand );
-    poSimpleSource->SetSrcWindow( nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize );
-    poSimpleSource->SetDstWindow( nDstXOff, nDstYOff, nDstXSize, nDstYSize );
+    poSimpleSource->SetSrcWindow( dfSrcXOff, dfSrcYOff, dfSrcXSize, dfSrcYSize );
+    poSimpleSource->SetDstWindow( dfDstXOff, dfDstYOff, dfDstXSize, dfDstYSize );
 
 /* -------------------------------------------------------------------- */
 /*      Default source and dest rectangles.                             */
 /* -------------------------------------------------------------------- */
-    if ( nSrcXOff == nDstXOff && nSrcYOff == nDstYOff &&
-         nSrcXSize == nDstXSize && nSrcYSize == nRasterYSize )
+    if ( dfSrcXOff == dfDstXOff && dfSrcYOff == dfDstYOff &&
+         dfSrcXSize == dfDstXSize && dfSrcYSize == nRasterYSize )
         bEqualAreas = TRUE;
 
 /* -------------------------------------------------------------------- */
@@ -850,13 +882,13 @@ void VRTSourcedRasterBand::ConfigureSource(VRTSimpleSource *poSimpleSource,
 /*                          AddSimpleSource()                           */
 /************************************************************************/
 
-CPLErr VRTSourcedRasterBand::AddSimpleSource( GDALRasterBand *poSrcBand, 
-                                       int nSrcXOff, int nSrcYOff, 
-                                       int nSrcXSize, int nSrcYSize, 
-                                       int nDstXOff, int nDstYOff, 
-                                       int nDstXSize, int nDstYSize,
-                                       const char *pszResampling, 
-                                       double dfNoDataValue )
+CPLErr VRTSourcedRasterBand::AddSimpleSource( GDALRasterBand *poSrcBand,
+                                       double dfSrcXOff, double dfSrcYOff,
+                                       double dfSrcXSize, double dfSrcYSize,
+                                       double dfDstXOff, double dfDstYOff,
+                                       double dfDstXSize, double dfDstYSize,
+                                       const char *pszResampling,
+                                       double dfNoDataValueIn )
 
 {
 /* -------------------------------------------------------------------- */
@@ -864,14 +896,14 @@ CPLErr VRTSourcedRasterBand::AddSimpleSource( GDALRasterBand *poSrcBand,
 /* -------------------------------------------------------------------- */
     VRTSimpleSource *poSimpleSource;
 
-    if( pszResampling != NULL && EQUALN(pszResampling,"aver",4) )
+    if( pszResampling != NULL && STARTS_WITH_CI(pszResampling, "aver") )
         poSimpleSource = new VRTAveragedSource();
     else
     {
         poSimpleSource = new VRTSimpleSource();
-        if( dfNoDataValue != VRT_NODATA_UNSET )
-            CPLError( 
-                CE_Warning, CPLE_AppDefined, 
+        if( dfNoDataValueIn != VRT_NODATA_UNSET )
+            CPLError(
+                CE_Warning, CPLE_AppDefined,
                 "NODATA setting not currently supported for nearest\n"
                 "neighbour sampled simple sources on Virtual Datasources." );
     }
@@ -879,13 +911,13 @@ CPLErr VRTSourcedRasterBand::AddSimpleSource( GDALRasterBand *poSrcBand,
     ConfigureSource(poSimpleSource,
                     poSrcBand,
                     FALSE,
-                    nSrcXOff, nSrcYOff,
-                    nSrcXSize, nSrcYSize,
-                    nDstXOff, nDstYOff,
-                    nDstXSize, nDstYSize);
+                    dfSrcXOff, dfSrcYOff,
+                    dfSrcXSize, dfSrcYSize,
+                    dfDstXOff, dfDstYOff,
+                    dfDstXSize, dfDstYSize);
 
-    if( dfNoDataValue != VRT_NODATA_UNSET )
-        poSimpleSource->SetNoDataValue( dfNoDataValue );
+    if( dfNoDataValueIn != VRT_NODATA_UNSET )
+        poSimpleSource->SetNoDataValue( dfNoDataValueIn );
 
 /* -------------------------------------------------------------------- */
 /*      add to list.                                                    */
@@ -899,10 +931,10 @@ CPLErr VRTSourcedRasterBand::AddSimpleSource( GDALRasterBand *poSrcBand,
 
 /* poSrcBand is not the mask band, but the band from which the mask band is taken */
 CPLErr VRTSourcedRasterBand::AddMaskBandSource( GDALRasterBand *poSrcBand,
-                                                int nSrcXOff, int nSrcYOff,
-                                                int nSrcXSize, int nSrcYSize,
-                                                int nDstXOff, int nDstYOff,
-                                                int nDstXSize, int nDstYSize )
+                                                double dfSrcXOff, double dfSrcYOff,
+                                                double dfSrcXSize, double dfSrcYSize,
+                                                double dfDstXOff, double dfDstYOff,
+                                                double dfDstXSize, double dfDstYSize )
 {
 /* -------------------------------------------------------------------- */
 /*      Create source.                                                  */
@@ -912,10 +944,10 @@ CPLErr VRTSourcedRasterBand::AddMaskBandSource( GDALRasterBand *poSrcBand,
     ConfigureSource(poSimpleSource,
                     poSrcBand,
                     TRUE,
-                    nSrcXOff, nSrcYOff,
-                    nSrcXSize, nSrcYSize,
-                    nDstXOff, nDstYOff,
-                    nDstXSize, nDstYSize);
+                    dfSrcXOff, dfSrcYOff,
+                    dfSrcXSize, dfSrcYSize,
+                    dfDstXOff, dfDstYOff,
+                    dfDstXSize, dfDstYSize);
 
 /* -------------------------------------------------------------------- */
 /*      add to list.                                                    */
@@ -932,60 +964,59 @@ CPLErr VRTSourcedRasterBand::AddMaskBandSource( GDALRasterBand *poSrcBand,
  */
 
 CPLErr CPL_STDCALL VRTAddSimpleSource( VRTSourcedRasterBandH hVRTBand,
-                                       GDALRasterBandH hSrcBand, 
-                                       int nSrcXOff, int nSrcYOff, 
-                                       int nSrcXSize, int nSrcYSize, 
-                                       int nDstXOff, int nDstYOff, 
+                                       GDALRasterBandH hSrcBand,
+                                       int nSrcXOff, int nSrcYOff,
+                                       int nSrcXSize, int nSrcYSize,
+                                       int nDstXOff, int nDstYOff,
                                        int nDstXSize, int nDstYSize,
                                        const char *pszResampling,
                                        double dfNoDataValue )
 {
     VALIDATE_POINTER1( hVRTBand, "VRTAddSimpleSource", CE_Failure );
 
-    return ((VRTSourcedRasterBand *) hVRTBand)->AddSimpleSource(
-                                            (GDALRasterBand *)hSrcBand, 
-                                            nSrcXOff, nSrcYOff, 
-                                            nSrcXSize, nSrcYSize, 
-                                            nDstXOff, nDstYOff, 
-                                            nDstXSize, nDstYSize,
-                                            pszResampling, dfNoDataValue );
+    return
+        reinterpret_cast<VRTSourcedRasterBand *>( hVRTBand )->AddSimpleSource(
+            reinterpret_cast<GDALRasterBand *>( hSrcBand ),
+            nSrcXOff, nSrcYOff,
+            nSrcXSize, nSrcYSize,
+            nDstXOff, nDstYOff,
+            nDstXSize, nDstYSize,
+            pszResampling, dfNoDataValue );
 }
 
 /************************************************************************/
 /*                          AddComplexSource()                          */
 /************************************************************************/
 
-CPLErr VRTSourcedRasterBand::AddComplexSource( GDALRasterBand *poSrcBand, 
-                                               int nSrcXOff, int nSrcYOff, 
-                                               int nSrcXSize, int nSrcYSize, 
-                                               int nDstXOff, int nDstYOff, 
-                                               int nDstXSize, int nDstYSize,
+CPLErr VRTSourcedRasterBand::AddComplexSource( GDALRasterBand *poSrcBand,
+                                               double dfSrcXOff, double dfSrcYOff,
+                                               double dfSrcXSize, double dfSrcYSize,
+                                               double dfDstXOff, double dfDstYOff,
+                                               double dfDstXSize, double dfDstYSize,
                                                double dfScaleOff,
                                                double dfScaleRatio,
-                                               double dfNoDataValue,
+                                               double dfNoDataValueIn,
                                                int nColorTableComponent)
 
 {
 /* -------------------------------------------------------------------- */
 /*      Create source.                                                  */
 /* -------------------------------------------------------------------- */
-    VRTComplexSource *poSource;
-
-    poSource = new VRTComplexSource();
+    VRTComplexSource *poSource = new VRTComplexSource();
 
     ConfigureSource(poSource,
                     poSrcBand,
                     FALSE,
-                    nSrcXOff, nSrcYOff,
-                    nSrcXSize, nSrcYSize,
-                    nDstXOff, nDstYOff,
-                    nDstXSize, nDstYSize);
+                    dfSrcXOff, dfSrcYOff,
+                    dfSrcXSize, dfSrcYSize,
+                    dfDstXOff, dfDstYOff,
+                    dfDstXSize, dfDstYSize);
 
 /* -------------------------------------------------------------------- */
 /*      Set complex parameters.                                         */
 /* -------------------------------------------------------------------- */
-    if( dfNoDataValue != VRT_NODATA_UNSET )
-        poSource->SetNoDataValue( dfNoDataValue );
+    if( dfNoDataValueIn != VRT_NODATA_UNSET )
+        poSource->SetNoDataValue( dfNoDataValueIn );
 
     if( dfScaleOff != 0.0 || dfScaleRatio != 1.0 )
         poSource->SetLinearScaling(dfScaleOff, dfScaleRatio);
@@ -1007,33 +1038,34 @@ CPLErr VRTSourcedRasterBand::AddComplexSource( GDALRasterBand *poSrcBand,
  */
 
 CPLErr CPL_STDCALL VRTAddComplexSource( VRTSourcedRasterBandH hVRTBand,
-                                        GDALRasterBandH hSrcBand, 
-                                        int nSrcXOff, int nSrcYOff, 
-                                        int nSrcXSize, int nSrcYSize, 
-                                        int nDstXOff, int nDstYOff, 
+                                        GDALRasterBandH hSrcBand,
+                                        int nSrcXOff, int nSrcYOff,
+                                        int nSrcXSize, int nSrcYSize,
+                                        int nDstXOff, int nDstYOff,
                                         int nDstXSize, int nDstYSize,
-                                        double dfScaleOff, 
+                                        double dfScaleOff,
                                         double dfScaleRatio,
                                         double dfNoDataValue )
 {
     VALIDATE_POINTER1( hVRTBand, "VRTAddComplexSource", CE_Failure );
 
-    return ((VRTSourcedRasterBand *) hVRTBand)->AddComplexSource(
-                                            (GDALRasterBand *)hSrcBand, 
-                                            nSrcXOff, nSrcYOff, 
-                                            nSrcXSize, nSrcYSize, 
-                                            nDstXOff, nDstYOff, 
-                                            nDstXSize, nDstYSize,
-                                            dfScaleOff, dfScaleRatio,
-                                            dfNoDataValue );
+    return
+        reinterpret_cast<VRTSourcedRasterBand *>( hVRTBand )->AddComplexSource(
+            reinterpret_cast<GDALRasterBand *>( hSrcBand ),
+            nSrcXOff, nSrcYOff,
+            nSrcXSize, nSrcYSize,
+            nDstXOff, nDstYOff,
+            nDstXSize, nDstYSize,
+            dfScaleOff, dfScaleRatio,
+            dfNoDataValue );
 }
 
 /************************************************************************/
 /*                           AddFuncSource()                            */
 /************************************************************************/
 
-CPLErr VRTSourcedRasterBand::AddFuncSource( VRTImageReadFunc pfnReadFunc, 
-                                     void *pCBData, double dfNoDataValue )
+CPLErr VRTSourcedRasterBand::AddFuncSource( VRTImageReadFunc pfnReadFunc,
+                                     void *pCBData, double dfNoDataValueIn )
 
 {
 /* -------------------------------------------------------------------- */
@@ -1041,7 +1073,7 @@ CPLErr VRTSourcedRasterBand::AddFuncSource( VRTImageReadFunc pfnReadFunc,
 /* -------------------------------------------------------------------- */
     VRTFuncSource *poFuncSource = new VRTFuncSource;
 
-    poFuncSource->fNoDataValue = (float) dfNoDataValue;
+    poFuncSource->fNoDataValue = static_cast<float>( dfNoDataValueIn );
     poFuncSource->pfnReadFunc = pfnReadFunc;
     poFuncSource->pCBData = pCBData;
     poFuncSource->eType = GetRasterDataType();
@@ -1061,12 +1093,12 @@ CPLErr VRTSourcedRasterBand::AddFuncSource( VRTImageReadFunc pfnReadFunc,
  */
 
 CPLErr CPL_STDCALL VRTAddFuncSource( VRTSourcedRasterBandH hVRTBand,
-                                     VRTImageReadFunc pfnReadFunc, 
+                                     VRTImageReadFunc pfnReadFunc,
                                      void *pCBData, double dfNoDataValue )
 {
     VALIDATE_POINTER1( hVRTBand, "VRTAddFuncSource", CE_Failure );
 
-    return ((VRTSourcedRasterBand *) hVRTBand)->
+    return reinterpret_cast<VRTSourcedRasterBand *>( hVRTBand )->
         AddFuncSource( pfnReadFunc, pCBData, dfNoDataValue );
 }
 
@@ -1092,54 +1124,52 @@ const char *VRTSourcedRasterBand::GetMetadataItem( const char * pszName,
 /* ==================================================================== */
 /*      LocationInfo handling.                                          */
 /* ==================================================================== */
-    if( pszDomain != NULL 
+    if( pszDomain != NULL
         && EQUAL(pszDomain,"LocationInfo")
-        && (EQUALN(pszName,"Pixel_",6) || EQUALN(pszName,"GeoPixel_",9)) )
+        && (STARTS_WITH_CI(pszName, "Pixel_") || STARTS_WITH_CI(pszName, "GeoPixel_")) )
     {
-        int iPixel, iLine;
-
 /* -------------------------------------------------------------------- */
 /*      What pixel are we aiming at?                                    */
 /* -------------------------------------------------------------------- */
-        if( EQUALN(pszName,"Pixel_",6) )
+        int iPixel, iLine;
+
+        if( STARTS_WITH_CI(pszName, "Pixel_") )
         {
             if( sscanf( pszName+6, "%d_%d", &iPixel, &iLine ) != 2 )
                 return NULL;
         }
-        else if( EQUALN(pszName,"GeoPixel_",9) )
+        else if( STARTS_WITH_CI(pszName, "GeoPixel_") )
         {
-            double adfGeoTransform[6];
-            double adfInvGeoTransform[6];
-            double dfGeoX, dfGeoY;
-
-            dfGeoX = CPLAtof(pszName + 9);
+            const double dfGeoX = CPLAtof(pszName + 9);
             const char* pszUnderscore = strchr(pszName + 9, '_');
             if( !pszUnderscore )
                 return NULL;
-            dfGeoY = CPLAtof(pszUnderscore + 1);
+            const double dfGeoY = CPLAtof(pszUnderscore + 1);
 
             if( GetDataset() == NULL )
                 return NULL;
-            
+
+            double adfGeoTransform[6];
             if( GetDataset()->GetGeoTransform( adfGeoTransform ) != CE_None )
                 return NULL;
-            
+
+            double adfInvGeoTransform[6];
             if( !GDALInvGeoTransform( adfGeoTransform, adfInvGeoTransform ) )
                 return NULL;
-                
-            iPixel = (int) floor(
-                adfInvGeoTransform[0] 
+
+            iPixel = static_cast<int>( floor(
+                adfInvGeoTransform[0]
                 + adfInvGeoTransform[1] * dfGeoX
-                + adfInvGeoTransform[2] * dfGeoY );
-            iLine = (int) floor(
-                adfInvGeoTransform[3] 
+                + adfInvGeoTransform[2] * dfGeoY ) );
+            iLine = static_cast<int>( floor(
+                adfInvGeoTransform[3]
                 + adfInvGeoTransform[4] * dfGeoX
-                + adfInvGeoTransform[5] * dfGeoY );
+                + adfInvGeoTransform[5] * dfGeoY ) );
         }
         else
             return NULL;
 
-        if( iPixel < 0 || iLine < 0 
+        if( iPixel < 0 || iLine < 0
             || iPixel >= GetXSize()
             || iLine >= GetYSize() )
             return NULL;
@@ -1148,61 +1178,61 @@ const char *VRTSourcedRasterBand::GetMetadataItem( const char * pszName,
 /*      Find the file(s) at this location.                              */
 /* -------------------------------------------------------------------- */
         char **papszFileList = NULL;
-        int nListMaxSize = 0, nListSize = 0;
+        int nListSize = 0;
         CPLHashSet* hSetFiles = CPLHashSetNew(CPLHashSetHashStr,
                                               CPLHashSetEqualStr,
                                               NULL);
-        
+
         for( int iSource = 0; iSource < nSources; iSource++ )
         {
-            double dfReqXOff, dfReqYOff, dfReqXSize, dfReqYSize;
-            int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
-            int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
-
             if (!papoSources[iSource]->IsSimpleSource())
                 continue;
 
-            VRTSimpleSource *poSrc = (VRTSimpleSource *) papoSources[iSource];
+            VRTSimpleSource *poSrc
+                = reinterpret_cast<VRTSimpleSource *>( papoSources[iSource] );
+
+            double dfReqXOff, dfReqYOff, dfReqXSize, dfReqYSize;
+            int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
+            int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
 
             if( !poSrc->GetSrcDstWindow( iPixel, iLine, 1, 1, 1, 1,
                                          &dfReqXOff, &dfReqYOff, &dfReqXSize, &dfReqYSize,
-                                         &nReqXOff, &nReqYOff, 
+                                         &nReqXOff, &nReqYOff,
                                          &nReqXSize, &nReqYSize,
-                                         &nOutXOff, &nOutYOff, 
+                                         &nOutXOff, &nOutYOff,
                                          &nOutXSize, &nOutYSize ) )
                 continue;
 
+            int nListMaxSize = 0;
             poSrc->GetFileList( &papszFileList, &nListSize, &nListMaxSize,
                                 hSetFiles );
         }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Format into XML.                                                */
 /* -------------------------------------------------------------------- */
-        int i;
-
-        osLastLocationInfo = "<LocationInfo>";
-        for( i = 0; i < nListSize; i++ )
+        m_osLastLocationInfo = "<LocationInfo>";
+        for( int i = 0; i < nListSize; i++ )
         {
-            osLastLocationInfo += "<File>";
+            m_osLastLocationInfo += "<File>";
             char* pszXMLEscaped = CPLEscapeString(papszFileList[i], -1, CPLES_XML);
-            osLastLocationInfo += pszXMLEscaped;
+            m_osLastLocationInfo += pszXMLEscaped;
             CPLFree(pszXMLEscaped);
-            osLastLocationInfo += "</File>";
+            m_osLastLocationInfo += "</File>";
         }
-        osLastLocationInfo += "</LocationInfo>";
+        m_osLastLocationInfo += "</LocationInfo>";
 
         CSLDestroy( papszFileList );
         CPLHashSetDestroy( hSetFiles );
 
-        return osLastLocationInfo.c_str();
+        return m_osLastLocationInfo.c_str();
     }
 
 /* ==================================================================== */
 /*      Other domains.                                                  */
 /* ==================================================================== */
-    else
-        return GDALRasterBand::GetMetadataItem( pszName, pszDomain );
+
+    return GDALRasterBand::GetMetadataItem( pszName, pszDomain );
 }
 
 /************************************************************************/
@@ -1217,70 +1247,66 @@ char **VRTSourcedRasterBand::GetMetadata( const char *pszDomain )
 /* ==================================================================== */
     if( pszDomain != NULL && EQUAL(pszDomain,"vrt_sources") )
     {
-        CSLDestroy(papszSourceList);
-        papszSourceList = NULL;
+        CSLDestroy(m_papszSourceList);
+        m_papszSourceList = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Process SimpleSources.                                          */
 /* -------------------------------------------------------------------- */
         for( int iSource = 0; iSource < nSources; iSource++ )
         {
-            CPLXMLNode      *psXMLSrc;
-            char            *pszXML;
-            
-            psXMLSrc = papoSources[iSource]->SerializeToXML( NULL );
+            CPLXMLNode *psXMLSrc = papoSources[iSource]->SerializeToXML( NULL );
             if( psXMLSrc == NULL )
                 continue;
 
-            pszXML = CPLSerializeXMLTree( psXMLSrc );
+            char *pszXML = CPLSerializeXMLTree( psXMLSrc );
 
-            papszSourceList = 
-                CSLSetNameValue( papszSourceList, 
+            m_papszSourceList =
+                CSLSetNameValue( m_papszSourceList,
                                  CPLSPrintf( "source_%d", iSource ), pszXML );
             CPLFree( pszXML );
             CPLDestroyXMLNode( psXMLSrc );
         }
-        
-        return papszSourceList;
+
+        return m_papszSourceList;
     }
 
 /* ==================================================================== */
 /*      Other domains.                                                  */
 /* ==================================================================== */
-    else
-        return GDALRasterBand::GetMetadata( pszDomain );
+
+    return GDALRasterBand::GetMetadata( pszDomain );
 }
 
 /************************************************************************/
 /*                          SetMetadataItem()                           */
 /************************************************************************/
 
-CPLErr VRTSourcedRasterBand::SetMetadataItem( const char *pszName, 
-                                              const char *pszValue, 
+CPLErr VRTSourcedRasterBand::SetMetadataItem( const char *pszName,
+                                              const char *pszValue,
                                               const char *pszDomain )
 
 {
-    CPLDebug( "VRT", "VRTSourcedRasterBand::SetMetadataItem(%s,%s,%s)\n",
-              pszName, pszValue, pszDomain );
-              
+    //CPLDebug( "VRT", "VRTSourcedRasterBand::SetMetadataItem(%s,%s,%s)\n",
+    //          pszName, pszValue, pszDomain );
+
     if( pszDomain != NULL
         && EQUAL(pszDomain,"new_vrt_sources") )
     {
-        VRTDriver *poDriver = (VRTDriver *) GDALGetDriverByName( "VRT" );
+        VRTDriver *poDriver = reinterpret_cast<VRTDriver *>(
+            GDALGetDriverByName( "VRT" ) );
 
         CPLXMLNode *psTree = CPLParseXMLString( pszValue );
-        VRTSource *poSource;
-        
         if( psTree == NULL )
             return CE_Failure;
-        
-        poSource = poDriver->ParseSource( psTree, NULL );
+
+        VRTSource *poSource = poDriver->ParseSource( psTree, NULL );
         CPLDestroyXMLNode( psTree );
-        
+
         if( poSource != NULL )
             return AddSource( poSource );
-        else
-            return CE_Failure;
+
+        return CE_Failure;
     }
     else if( pszDomain != NULL
         && EQUAL(pszDomain,"vrt_sources") )
@@ -1296,29 +1322,28 @@ CPLErr VRTSourcedRasterBand::SetMetadataItem( const char *pszName,
             return CE_Failure;
         }
 
-        VRTDriver *poDriver = (VRTDriver *) GDALGetDriverByName( "VRT" );
+        VRTDriver *poDriver = reinterpret_cast<VRTDriver *>(
+            GDALGetDriverByName( "VRT" ) );
 
         CPLXMLNode *psTree = CPLParseXMLString( pszValue );
-        VRTSource *poSource;
-        
         if( psTree == NULL )
             return CE_Failure;
-        
-        poSource = poDriver->ParseSource( psTree, NULL );
+
+        VRTSource *poSource = poDriver->ParseSource( psTree, NULL );
         CPLDestroyXMLNode( psTree );
-        
+
         if( poSource != NULL )
         {
             delete papoSources[iSource];
             papoSources[iSource] = poSource;
-            ((VRTDataset *)poDS)->SetNeedsFlush();
+            reinterpret_cast<VRTDataset *>( poDS )->SetNeedsFlush();
             return CE_None;
         }
-        else
-            return CE_Failure;
+
+        return CE_Failure;
     }
-    else
-        return VRTRasterBand::SetMetadataItem( pszName, pszValue, pszDomain );
+
+    return VRTRasterBand::SetMetadataItem( pszName, pszValue, pszDomain );
 }
 
 /************************************************************************/
@@ -1329,12 +1354,11 @@ CPLErr VRTSourcedRasterBand::SetMetadata( char **papszNewMD, const char *pszDoma
 
 {
     if( pszDomain != NULL
-        && (EQUAL(pszDomain,"new_vrt_sources") 
+        && (EQUAL(pszDomain,"new_vrt_sources")
             || EQUAL(pszDomain,"vrt_sources")) )
     {
-        VRTDriver *poDriver = (VRTDriver *) GDALGetDriverByName( "VRT" );
-        CPLErr eErr;
-        int    i;
+        VRTDriver *poDriver
+            = reinterpret_cast<VRTDriver *>( GDALGetDriverByName( "VRT" ) );
 
         if( EQUAL(pszDomain,"vrt_sources") )
         {
@@ -1345,32 +1369,29 @@ CPLErr VRTSourcedRasterBand::SetMetadata( char **papszNewMD, const char *pszDoma
             nSources = 0;
         }
 
-        for( i = 0; i < CSLCount(papszNewMD); i++ )
+        for( int i = 0; i < CSLCount(papszNewMD); i++ )
         {
             const char *pszXML = CPLParseNameValue( papszNewMD[i], NULL );
+
             CPLXMLNode *psTree = CPLParseXMLString( pszXML );
-            VRTSource *poSource;
-            
             if( psTree == NULL )
                 return CE_Failure;
 
-            poSource = poDriver->ParseSource( psTree, NULL );
+            VRTSource *poSource = poDriver->ParseSource( psTree, NULL );
             CPLDestroyXMLNode( psTree );
 
-            if( poSource != NULL )
-            {
-                eErr = AddSource( poSource );
-                if( eErr != CE_None )
-                    return eErr;
-            }
-            else
+            if( poSource == NULL )
                 return CE_Failure;
+
+            CPLErr eErr = AddSource( poSource );
+            if( eErr != CE_None )
+                return eErr;
         }
 
         return CE_None;
     }
-    else
-        return VRTRasterBand::SetMetadata( papszNewMD, pszDomain );
+
+    return VRTRasterBand::SetMetadata( papszNewMD, pszDomain );
 }
 
 /************************************************************************/
diff --git a/frmts/vrt/vrtsources.cpp b/frmts/vrt/vrtsources.cpp
index 12272be..76e6874 100644
--- a/frmts/vrt/vrtsources.cpp
+++ b/frmts/vrt/vrtsources.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: vrtsources.cpp 31003 2015-10-14 16:19:20Z rouault $
+ * $Id: vrtsources.cpp 33826 2016-03-31 14:37:01Z rouault $
  *
  * Project:  Virtual GDAL Datasets
- * Purpose:  Implementation of VRTSimpleSource, VRTFuncSource and 
+ * Purpose:  Implementation of VRTSimpleSource, VRTFuncSource and
  *           VRTAveragedSource.
  * Author:   Frank Warmerdam <warmerdam at pobox.com>
  *
@@ -43,7 +43,7 @@
 #define isnan std::isnan
 #endif
 
-CPL_CVSID("$Id: vrtsources.cpp 31003 2015-10-14 16:19:20Z rouault $");
+CPL_CVSID("$Id: vrtsources.cpp 33826 2016-03-31 14:37:01Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -76,14 +76,45 @@ void VRTSource::GetFileList(CPL_UNUSED char*** ppapszFileList,
 /*                          VRTSimpleSource()                           */
 /************************************************************************/
 
-VRTSimpleSource::VRTSimpleSource()
+VRTSimpleSource::VRTSimpleSource() :
+    m_dfSrcXOff(0.0),
+    m_dfSrcYOff(0.0),
+    m_dfSrcXSize(0.0),
+    m_dfSrcYSize(0.0),
+    m_dfDstXOff(0.0),
+    m_dfDstYOff(0.0),
+    m_dfDstXSize(0.0),
+    m_dfDstYSize(0.0)
+{
+    m_poRasterBand = NULL;
+    m_poMaskBandMainBand = NULL;
+    m_bNoDataSet = FALSE;
+    m_dfNoDataValue = VRT_NODATA_UNSET;
+    m_bRelativeToVRTOri = -1;
+    m_nMaxValue = 0;
+}
 
+/************************************************************************/
+/*                          VRTSimpleSource()                           */
+/************************************************************************/
+
+VRTSimpleSource::VRTSimpleSource(const VRTSimpleSource* poSrcSource,
+                                 double dfXDstRatio, double dfYDstRatio)
 {
-    poRasterBand = NULL;
-    poMaskBandMainBand = NULL;
-    bNoDataSet = FALSE;
-    dfNoDataValue = VRT_NODATA_UNSET;
-    bRelativeToVRTOri = -1;
+    m_poRasterBand = poSrcSource->m_poRasterBand;
+    m_poMaskBandMainBand = poSrcSource->m_poMaskBandMainBand;
+    m_bNoDataSet = poSrcSource->m_bNoDataSet;
+    m_dfNoDataValue = poSrcSource->m_dfNoDataValue;
+    m_dfSrcXOff = poSrcSource->m_dfSrcXOff;
+    m_dfSrcYOff = poSrcSource->m_dfSrcYOff;
+    m_dfSrcXSize = poSrcSource->m_dfSrcXSize;
+    m_dfSrcYSize = poSrcSource->m_dfSrcYSize;
+    m_dfDstXOff = poSrcSource->m_dfDstXOff * dfXDstRatio;
+    m_dfDstYOff = poSrcSource->m_dfDstYOff * dfYDstRatio;
+    m_dfDstXSize = poSrcSource->m_dfDstXSize * dfXDstRatio;
+    m_dfDstYSize = poSrcSource->m_dfDstYSize * dfYDstRatio;
+    m_bRelativeToVRTOri = -1;
+    m_nMaxValue = poSrcSource->m_nMaxValue;
 }
 
 /************************************************************************/
@@ -96,22 +127,22 @@ VRTSimpleSource::~VRTSimpleSource()
     // We use bRelativeToVRTOri to know if the file has been opened from
     // XMLInit(), and thus we are sure that no other code has a direct reference
     // to the dataset
-    if( poMaskBandMainBand != NULL )
+    if( m_poMaskBandMainBand != NULL )
     {
-        if (poMaskBandMainBand->GetDataset() != NULL )
+        if (m_poMaskBandMainBand->GetDataset() != NULL )
         {
-            if( poMaskBandMainBand->GetDataset()->GetShared() || bRelativeToVRTOri >= 0 )
-                GDALClose( (GDALDatasetH) poMaskBandMainBand->GetDataset() );
+            if( m_poMaskBandMainBand->GetDataset()->GetShared() || m_bRelativeToVRTOri >= 0 )
+                GDALClose( (GDALDatasetH) m_poMaskBandMainBand->GetDataset() );
             else
-                poMaskBandMainBand->GetDataset()->Dereference();
+                m_poMaskBandMainBand->GetDataset()->Dereference();
         }
     }
-    else if( poRasterBand != NULL && poRasterBand->GetDataset() != NULL )
+    else if( m_poRasterBand != NULL && m_poRasterBand->GetDataset() != NULL )
     {
-        if( poRasterBand->GetDataset()->GetShared() || bRelativeToVRTOri >= 0 )
-            GDALClose( (GDALDatasetH) poRasterBand->GetDataset() );
+        if( m_poRasterBand->GetDataset()->GetShared() || m_bRelativeToVRTOri >= 0 )
+            GDALClose( (GDALDatasetH) m_poRasterBand->GetDataset() );
         else
-            poRasterBand->GetDataset()->Dereference();
+            m_poRasterBand->GetDataset()->Dereference();
     }
 }
 
@@ -121,8 +152,8 @@ VRTSimpleSource::~VRTSimpleSource()
 
 void VRTSimpleSource::UnsetPreservedRelativeFilenames()
 {
-    bRelativeToVRTOri = -1;
-    osSourceFileNameOri = "";
+    m_bRelativeToVRTOri = -1;
+    m_osSourceFileNameOri = "";
 }
 
 /************************************************************************/
@@ -132,7 +163,7 @@ void VRTSimpleSource::UnsetPreservedRelativeFilenames()
 void VRTSimpleSource::SetSrcBand( GDALRasterBand *poNewSrcBand )
 
 {
-    poRasterBand = poNewSrcBand;
+    m_poRasterBand = poNewSrcBand;
 }
 
 
@@ -144,36 +175,36 @@ void VRTSimpleSource::SetSrcBand( GDALRasterBand *poNewSrcBand )
 void VRTSimpleSource::SetSrcMaskBand( GDALRasterBand *poNewSrcBand )
 
 {
-    poRasterBand = poNewSrcBand->GetMaskBand();
-    poMaskBandMainBand = poNewSrcBand;
+    m_poRasterBand = poNewSrcBand->GetMaskBand();
+    m_poMaskBandMainBand = poNewSrcBand;
 }
 
 /************************************************************************/
 /*                            SetSrcWindow()                            */
 /************************************************************************/
 
-void VRTSimpleSource::SetSrcWindow( int nNewXOff, int nNewYOff, 
-                                    int nNewXSize, int nNewYSize )
+void VRTSimpleSource::SetSrcWindow( double dfNewXOff, double dfNewYOff,
+                                    double dfNewXSize, double dfNewYSize )
 
 {
-    nSrcXOff = nNewXOff;
-    nSrcYOff = nNewYOff;
-    nSrcXSize = nNewXSize;
-    nSrcYSize = nNewYSize;
+    m_dfSrcXOff = dfNewXOff;
+    m_dfSrcYOff = dfNewYOff;
+    m_dfSrcXSize = dfNewXSize;
+    m_dfSrcYSize = dfNewYSize;
 }
 
 /************************************************************************/
 /*                            SetDstWindow()                            */
 /************************************************************************/
 
-void VRTSimpleSource::SetDstWindow( int nNewXOff, int nNewYOff, 
-                                    int nNewXSize, int nNewYSize )
+void VRTSimpleSource::SetDstWindow( double dfNewXOff, double dfNewYOff,
+                                    double dfNewXSize, double dfNewYSize )
 
 {
-    nDstXOff = nNewXOff;
-    nDstYOff = nNewYOff;
-    nDstXSize = nNewXSize;
-    nDstYSize = nNewYSize;
+    m_dfDstXOff = dfNewXOff;
+    m_dfDstYOff = dfNewYOff;
+    m_dfDstXSize = dfNewXSize;
+    m_dfDstYSize = dfNewYSize;
 }
 
 /************************************************************************/
@@ -185,13 +216,13 @@ void VRTSimpleSource::SetNoDataValue( double dfNewNoDataValue )
 {
     if( dfNewNoDataValue == VRT_NODATA_UNSET )
     {
-        bNoDataSet = FALSE;
-        dfNoDataValue = VRT_NODATA_UNSET;
+        m_bNoDataSet = FALSE;
+        m_dfNoDataValue = VRT_NODATA_UNSET;
     }
     else
     {
-        bNoDataSet = TRUE;
-        dfNoDataValue = dfNewNoDataValue;
+        m_bNoDataSet = TRUE;
+        m_dfNoDataValue = dfNewNoDataValue;
     }
 }
 
@@ -199,7 +230,7 @@ void VRTSimpleSource::SetNoDataValue( double dfNewNoDataValue )
 /*                           SerializeToXML()                           */
 /************************************************************************/
 
-static const char* apszSpecialSyntax[] = { "HDF5:\"{FILENAME}\":{ANY}",
+static const char* const apszSpecialSyntax[] = { "HDF5:\"{FILENAME}\":{ANY}",
                                             "HDF5:{FILENAME}:{ANY}",
                                             "NETCDF:\"{FILENAME}\":{ANY}",
                                             "NETCDF:{FILENAME}:{ANY}",
@@ -215,39 +246,39 @@ CPLXMLNode *VRTSimpleSource::SerializeToXML( const char *pszVRTPath )
     const char      *pszRelativePath;
     int              nBlockXSize, nBlockYSize;
 
-    if( poRasterBand == NULL )
+    if( m_poRasterBand == NULL )
         return NULL;
 
     GDALDataset     *poDS;
 
-    if (poMaskBandMainBand)
+    if (m_poMaskBandMainBand)
     {
-        poDS = poMaskBandMainBand->GetDataset();
-        if( poDS == NULL || poMaskBandMainBand->GetBand() < 1 )
+        poDS = m_poMaskBandMainBand->GetDataset();
+        if( poDS == NULL || m_poMaskBandMainBand->GetBand() < 1 )
             return NULL;
     }
     else
     {
-        poDS = poRasterBand->GetDataset();
-        if( poDS == NULL || poRasterBand->GetBand() < 1 )
+        poDS = m_poRasterBand->GetDataset();
+        if( poDS == NULL || m_poRasterBand->GetBand() < 1 )
             return NULL;
     }
 
     psSrc = CPLCreateXMLNode( NULL, CXT_Element, "SimpleSource" );
 
-    if( osResampling.size() )
+    if( m_osResampling.size() )
     {
-        CPLCreateXMLNode( 
-            CPLCreateXMLNode( psSrc, CXT_Attribute, "resampling" ), 
-                CXT_Text, osResampling.c_str() );
+        CPLCreateXMLNode(
+            CPLCreateXMLNode( psSrc, CXT_Attribute, "resampling" ),
+                CXT_Text, m_osResampling.c_str() );
     }
 
     VSIStatBufL sStat;
     CPLString osTmp;
-    if( bRelativeToVRTOri >= 0 )
+    if( m_bRelativeToVRTOri >= 0 )
     {
-        pszRelativePath = osSourceFileNameOri;
-        bRelativeToVRT = bRelativeToVRTOri;
+        pszRelativePath = m_osSourceFileNameOri;
+        bRelativeToVRT = m_bRelativeToVRTOri;
     }
     else if ( strstr(poDS->GetDescription(), "/vsicurl/http") != NULL ||
          strstr(poDS->GetDescription(), "/vsicurl/ftp") != NULL )
@@ -275,7 +306,7 @@ CPLXMLNode *VRTSimpleSource::SerializeToXML( const char *pszVRTPath )
                 osPrefix += '"';
             if( EQUALN(pszRelativePath, osPrefix, osPrefix.size()) )
             {
-                if( EQUALN(pszSyntax + osPrefix.size(), "{ANY}", strlen("{ANY}")) )
+                if( STARTS_WITH_CI(pszSyntax + osPrefix.size(), "{ANY}") )
                 {
                     const char* pszLastPart = strrchr(pszRelativePath, ':') + 1;
                     /* CSV:z:/foo.xyz */
@@ -290,7 +321,7 @@ CPLXMLNode *VRTSimpleSource::SerializeToXML( const char *pszVRTPath )
                     osTmp = osPrefixFilename + pszRelativePath;
                     pszRelativePath = osTmp.c_str();
                 }
-                else if( EQUALN(pszSyntax + osPrefix.size(), "{FILENAME}", strlen("{FILENAME}")) )
+                else if( STARTS_WITH_CI(pszSyntax + osPrefix.size(), "{FILENAME}") )
                 {
                     CPLString osFilename(pszRelativePath + osPrefix.size());
                     size_t nPos = 0;
@@ -319,71 +350,71 @@ CPLXMLNode *VRTSimpleSource::SerializeToXML( const char *pszVRTPath )
             CPLExtractRelativePath( pszVRTPath, poDS->GetDescription(),
                                     &bRelativeToVRT );
     }
-    
+
     CPLSetXMLValue( psSrc, "SourceFilename", pszRelativePath );
-    
-    CPLCreateXMLNode( 
-        CPLCreateXMLNode( CPLGetXMLNode( psSrc, "SourceFilename" ), 
-                          CXT_Attribute, "relativeToVRT" ), 
+
+    CPLCreateXMLNode(
+        CPLCreateXMLNode( CPLGetXMLNode( psSrc, "SourceFilename" ),
+                          CXT_Attribute, "relativeToVRT" ),
         CXT_Text, bRelativeToVRT ? "1" : "0" );
-    
-    if( !CSLTestBoolean(CPLGetConfigOption("VRT_SHARED_SOURCE", "TRUE")) )
+
+    if( !CPLTestBool(CPLGetConfigOption("VRT_SHARED_SOURCE", "TRUE")) )
     {
-        CPLCreateXMLNode( 
-            CPLCreateXMLNode( CPLGetXMLNode( psSrc, "SourceFilename" ), 
-                              CXT_Attribute, "shared" ), 
+        CPLCreateXMLNode(
+            CPLCreateXMLNode( CPLGetXMLNode( psSrc, "SourceFilename" ),
+                              CXT_Attribute, "shared" ),
                               CXT_Text, "0" );
     }
 
     char** papszOpenOptions = poDS->GetOpenOptions();
     GDALSerializeOpenOptionsToXML(psSrc, papszOpenOptions);
 
-    if (poMaskBandMainBand)
+    if (m_poMaskBandMainBand)
         CPLSetXMLValue( psSrc, "SourceBand",
-                        CPLSPrintf("mask,%d",poMaskBandMainBand->GetBand()) );
+                        CPLSPrintf("mask,%d",m_poMaskBandMainBand->GetBand()) );
     else
         CPLSetXMLValue( psSrc, "SourceBand",
-                        CPLSPrintf("%d",poRasterBand->GetBand()) );
+                        CPLSPrintf("%d",m_poRasterBand->GetBand()) );
 
     /* Write a few additional useful properties of the dataset */
     /* so that we can use a proxy dataset when re-opening. See XMLInit() */
     /* below */
-    CPLSetXMLValue( psSrc, "SourceProperties.#RasterXSize", 
-                    CPLSPrintf("%d",poRasterBand->GetXSize()) );
-    CPLSetXMLValue( psSrc, "SourceProperties.#RasterYSize", 
-                    CPLSPrintf("%d",poRasterBand->GetYSize()) );
-    CPLSetXMLValue( psSrc, "SourceProperties.#DataType", 
-                GDALGetDataTypeName( poRasterBand->GetRasterDataType() ) );
-    poRasterBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
-    CPLSetXMLValue( psSrc, "SourceProperties.#BlockXSize", 
+    CPLSetXMLValue( psSrc, "SourceProperties.#RasterXSize",
+                    CPLSPrintf("%d",m_poRasterBand->GetXSize()) );
+    CPLSetXMLValue( psSrc, "SourceProperties.#RasterYSize",
+                    CPLSPrintf("%d",m_poRasterBand->GetYSize()) );
+    CPLSetXMLValue( psSrc, "SourceProperties.#DataType",
+                GDALGetDataTypeName( m_poRasterBand->GetRasterDataType() ) );
+    m_poRasterBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
+    CPLSetXMLValue( psSrc, "SourceProperties.#BlockXSize",
                     CPLSPrintf("%d",nBlockXSize) );
-    CPLSetXMLValue( psSrc, "SourceProperties.#BlockYSize", 
+    CPLSetXMLValue( psSrc, "SourceProperties.#BlockYSize",
                     CPLSPrintf("%d",nBlockYSize) );
 
-    if( nSrcXOff != -1 
-        || nSrcYOff != -1 
-        || nSrcXSize != -1 
-        || nSrcYSize != -1 )
+    if( m_dfSrcXOff != -1
+        || m_dfSrcYOff != -1
+        || m_dfSrcXSize != -1
+        || m_dfSrcYSize != -1 )
     {
-        CPLSetXMLValue( psSrc, "SrcRect.#xOff", 
-                        CPLSPrintf( "%d", nSrcXOff ) );
-        CPLSetXMLValue( psSrc, "SrcRect.#yOff", 
-                        CPLSPrintf( "%d", nSrcYOff ) );
-        CPLSetXMLValue( psSrc, "SrcRect.#xSize", 
-                        CPLSPrintf( "%d", nSrcXSize ) );
-        CPLSetXMLValue( psSrc, "SrcRect.#ySize", 
-                        CPLSPrintf( "%d", nSrcYSize ) );
+        CPLSetXMLValue( psSrc, "SrcRect.#xOff",
+                        CPLSPrintf( "%.15g", m_dfSrcXOff ) );
+        CPLSetXMLValue( psSrc, "SrcRect.#yOff",
+                        CPLSPrintf( "%.15g", m_dfSrcYOff ) );
+        CPLSetXMLValue( psSrc, "SrcRect.#xSize",
+                        CPLSPrintf( "%.15g", m_dfSrcXSize ) );
+        CPLSetXMLValue( psSrc, "SrcRect.#ySize",
+                        CPLSPrintf( "%.15g", m_dfSrcYSize ) );
     }
 
-    if( nDstXOff != -1 
-        || nDstYOff != -1 
-        || nDstXSize != -1 
-        || nDstYSize != -1 )
+    if( m_dfDstXOff != -1
+        || m_dfDstYOff != -1
+        || m_dfDstXSize != -1
+        || m_dfDstYSize != -1 )
     {
-        CPLSetXMLValue( psSrc, "DstRect.#xOff", CPLSPrintf( "%d", nDstXOff ) );
-        CPLSetXMLValue( psSrc, "DstRect.#yOff", CPLSPrintf( "%d", nDstYOff ) );
-        CPLSetXMLValue( psSrc, "DstRect.#xSize",CPLSPrintf( "%d", nDstXSize ));
-        CPLSetXMLValue( psSrc, "DstRect.#ySize",CPLSPrintf( "%d", nDstYSize ));
+        CPLSetXMLValue( psSrc, "DstRect.#xOff", CPLSPrintf( "%.15g", m_dfDstXOff ) );
+        CPLSetXMLValue( psSrc, "DstRect.#yOff", CPLSPrintf( "%.15g", m_dfDstYOff ) );
+        CPLSetXMLValue( psSrc, "DstRect.#xSize",CPLSPrintf( "%.15g", m_dfDstXSize ));
+        CPLSetXMLValue( psSrc, "DstRect.#ySize",CPLSPrintf( "%.15g", m_dfDstYSize ));
     }
 
     return psSrc;
@@ -396,36 +427,36 @@ CPLXMLNode *VRTSimpleSource::SerializeToXML( const char *pszVRTPath )
 CPLErr VRTSimpleSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
 
 {
-    osResampling = CPLGetXMLValue( psSrc, "resampling", "");
+    m_osResampling = CPLGetXMLValue( psSrc, "resampling", "");
 
 /* -------------------------------------------------------------------- */
 /*      Prepare filename.                                               */
 /* -------------------------------------------------------------------- */
     char *pszSrcDSName = NULL;
     CPLXMLNode* psSourceFileNameNode = CPLGetXMLNode(psSrc,"SourceFilename");
-    const char *pszFilename = 
+    const char *pszFilename =
         psSourceFileNameNode ? CPLGetXMLValue(psSourceFileNameNode,NULL, NULL) : NULL;
 
     if( pszFilename == NULL )
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "Missing <SourceFilename> element in VRTRasterBand." );
         return CE_Failure;
     }
-    
+
     // Backup original filename and relativeToVRT so as to be able to
     // serialize them identically again (#5985)
-    osSourceFileNameOri = pszFilename;
-    bRelativeToVRTOri = atoi(CPLGetXMLValue( psSourceFileNameNode, "relativetoVRT", "0"));
+    m_osSourceFileNameOri = pszFilename;
+    m_bRelativeToVRTOri = atoi(CPLGetXMLValue( psSourceFileNameNode, "relativetoVRT", "0"));
     const char* pszShared = CPLGetXMLValue( psSourceFileNameNode, "shared", NULL);
     int bShared = FALSE;
     if( pszShared != NULL )
-        bShared = CSLTestBoolean(pszShared);
+        bShared = CPLTestBool(pszShared);
     else
-        bShared = CSLTestBoolean(CPLGetConfigOption("VRT_SHARED_SOURCE", "TRUE"));
+        bShared = CPLTestBool(CPLGetConfigOption("VRT_SHARED_SOURCE", "TRUE"));
 
     if( pszVRTPath != NULL
-        && bRelativeToVRTOri )
+        && m_bRelativeToVRTOri )
     {
         int bDone = FALSE;
         for( size_t i = 0; i < sizeof(apszSpecialSyntax) / sizeof(apszSpecialSyntax[0]); i ++)
@@ -437,7 +468,7 @@ CPLErr VRTSimpleSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
                 osPrefix += '"';
             if( EQUALN(pszFilename, osPrefix, osPrefix.size()) )
             {
-                if( EQUALN(pszSyntax + osPrefix.size(), "{ANY}", strlen("{ANY}")) )
+                if( STARTS_WITH_CI(pszSyntax + osPrefix.size(), "{ANY}") )
                 {
                     const char* pszLastPart = strrchr(pszFilename, ':') + 1;
                     /* CSV:z:/foo.xyz */
@@ -450,7 +481,7 @@ CPLErr VRTSimpleSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
                         CPLProjectRelativeFilename( pszVRTPath, pszLastPart )).c_str() );
                     bDone = TRUE;
                 }
-                else if( EQUALN(pszSyntax + osPrefix.size(), "{FILENAME}", strlen("{FILENAME}")) )
+                else if( STARTS_WITH_CI(pszSyntax + osPrefix.size(), "{FILENAME}") )
                 {
                     CPLString osFilename(pszFilename + osPrefix.size());
                     size_t nPos = 0;
@@ -482,7 +513,7 @@ CPLErr VRTSimpleSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
     const char* pszSourceBand = CPLGetXMLValue(psSrc,"SourceBand","1");
     int nSrcBand = 0;
     int bGetMaskBand = FALSE;
-    if (EQUALN(pszSourceBand, "mask",4))
+    if (STARTS_WITH_CI(pszSourceBand, "mask"))
     {
         bGetMaskBand = TRUE;
         if (pszSourceBand[4] == ',')
@@ -529,6 +560,13 @@ CPLErr VRTSimpleSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
         }
         nBlockXSize = atoi(CPLGetXMLValue(psSrcProperties,"BlockXSize","0"));
         nBlockYSize = atoi(CPLGetXMLValue(psSrcProperties,"BlockYSize","0"));
+        if( nRasterXSize < 0 || nRasterYSize < 0 || nBlockXSize < 0 || nBlockYSize < 0 )
+        {
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Invalid <SourceProperties> element in VRTRasterBand." );
+            CPLFree( pszSrcDSName );
+            return CE_Failure;
+        }
     }
 
     char** papszOpenOptions = GDALDeserializeOpenOptionsFromXML(psSrc);
@@ -566,20 +604,20 @@ CPLErr VRTSimpleSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
         if (bGetMaskBand)
             ((GDALProxyPoolRasterBand*)proxyDS->GetRasterBand(nSrcBand))->AddSrcMaskBandDescription(eDataType, nBlockXSize, nBlockYSize);
     }
-    
+
     CSLDestroy(papszOpenOptions);
 
     CPLFree( pszSrcDSName );
-    
+
     if( poSrcDS == NULL )
         return CE_Failure;
 
 /* -------------------------------------------------------------------- */
 /*      Get the raster band.                                            */
 /* -------------------------------------------------------------------- */
-    
-    poRasterBand = poSrcDS->GetRasterBand(nSrcBand);
-    if( poRasterBand == NULL )
+
+    m_poRasterBand = poSrcDS->GetRasterBand(nSrcBand);
+    if( m_poRasterBand == NULL )
     {
         if( poSrcDS->GetShared() )
             GDALClose( (GDALDatasetH) poSrcDS );
@@ -587,9 +625,9 @@ CPLErr VRTSimpleSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
     }
     if (bGetMaskBand)
     {
-        poMaskBandMainBand = poRasterBand;
-        poRasterBand = poRasterBand->GetMaskBand();
-        if( poRasterBand == NULL )
+        m_poMaskBandMainBand = m_poRasterBand;
+        m_poRasterBand = m_poRasterBand->GetMaskBand();
+        if( m_poRasterBand == NULL )
             return CE_Failure;
     }
 
@@ -599,27 +637,27 @@ CPLErr VRTSimpleSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
     CPLXMLNode* psSrcRect = CPLGetXMLNode(psSrc,"SrcRect");
     if (psSrcRect)
     {
-        nSrcXOff = atoi(CPLGetXMLValue(psSrcRect,"xOff","-1"));
-        nSrcYOff = atoi(CPLGetXMLValue(psSrcRect,"yOff","-1"));
-        nSrcXSize = atoi(CPLGetXMLValue(psSrcRect,"xSize","-1"));
-        nSrcYSize = atoi(CPLGetXMLValue(psSrcRect,"ySize","-1"));
+        m_dfSrcXOff = CPLAtof(CPLGetXMLValue(psSrcRect,"xOff","-1"));
+        m_dfSrcYOff = CPLAtof(CPLGetXMLValue(psSrcRect,"yOff","-1"));
+        m_dfSrcXSize = CPLAtof(CPLGetXMLValue(psSrcRect,"xSize","-1"));
+        m_dfSrcYSize = CPLAtof(CPLGetXMLValue(psSrcRect,"ySize","-1"));
     }
     else
     {
-        nSrcXOff = nSrcYOff = nSrcXSize = nSrcYSize = -1;
+        m_dfSrcXOff = m_dfSrcYOff = m_dfSrcXSize = m_dfSrcYSize = -1;
     }
 
     CPLXMLNode* psDstRect = CPLGetXMLNode(psSrc,"DstRect");
     if (psDstRect)
     {
-        nDstXOff = atoi(CPLGetXMLValue(psDstRect,"xOff","-1"));
-        nDstYOff = atoi(CPLGetXMLValue(psDstRect,"yOff","-1"));
-        nDstXSize = atoi(CPLGetXMLValue(psDstRect,"xSize","-1"));
-        nDstYSize = atoi(CPLGetXMLValue(psDstRect,"ySize","-1"));
+        m_dfDstXOff = CPLAtof(CPLGetXMLValue(psDstRect,"xOff","-1"));
+        m_dfDstYOff = CPLAtof(CPLGetXMLValue(psDstRect,"yOff","-1"));
+        m_dfDstXSize = CPLAtof(CPLGetXMLValue(psDstRect,"xSize","-1"));
+        m_dfDstYSize = CPLAtof(CPLGetXMLValue(psDstRect,"ySize","-1"));
     }
     else
     {
-        nDstXOff = nDstYOff = nDstXSize = nDstYSize = -1;
+        m_dfDstXOff = m_dfDstYOff = m_dfDstXSize = m_dfDstYSize = -1;
     }
 
     return CE_None;
@@ -633,8 +671,8 @@ void VRTSimpleSource::GetFileList(char*** ppapszFileList, int *pnSize,
                                   int *pnMaxSize, CPLHashSet* hSetFiles)
 {
     const char* pszFilename;
-    if (poRasterBand != NULL && poRasterBand->GetDataset() != NULL &&
-        (pszFilename = poRasterBand->GetDataset()->GetDescription()) != NULL)
+    if (m_poRasterBand != NULL && m_poRasterBand->GetDataset() != NULL &&
+        (pszFilename = m_poRasterBand->GetDataset()->GetDescription()) != NULL)
     {
 /* -------------------------------------------------------------------- */
 /*      Is the filename even a real filesystem object?                  */
@@ -651,13 +689,13 @@ void VRTSimpleSource::GetFileList(char*** ppapszFileList, int *pnSize,
             if( VSIStatExL( pszFilename, &sStat, VSI_STAT_EXISTS_FLAG ) != 0 )
                 return;
         }
-            
+
 /* -------------------------------------------------------------------- */
 /*      Is it already in the list ?                                     */
 /* -------------------------------------------------------------------- */
         if( CPLHashSetLookup(hSetFiles, pszFilename) != NULL )
             return;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Grow array if necessary                                         */
 /* -------------------------------------------------------------------- */
@@ -667,14 +705,14 @@ void VRTSimpleSource::GetFileList(char*** ppapszFileList, int *pnSize,
             *ppapszFileList = (char **) CPLRealloc(
                         *ppapszFileList, sizeof(char*)  * (*pnMaxSize) );
         }
-            
+
 /* -------------------------------------------------------------------- */
 /*      Add the string to the list                                      */
 /* -------------------------------------------------------------------- */
         (*ppapszFileList)[*pnSize] = CPLStrdup(pszFilename);
         (*ppapszFileList)[(*pnSize + 1)] = NULL;
         CPLHashSetInsert(hSetFiles, (*ppapszFileList)[*pnSize]);
-        
+
         (*pnSize) ++;
     }
 }
@@ -685,7 +723,7 @@ void VRTSimpleSource::GetFileList(char*** ppapszFileList, int *pnSize,
 
 GDALRasterBand* VRTSimpleSource::GetBand()
 {
-    return poMaskBandMainBand ? NULL : poRasterBand;
+    return m_poMaskBandMainBand ? NULL : m_poRasterBand;
 }
 
 /************************************************************************/
@@ -694,16 +732,16 @@ GDALRasterBand* VRTSimpleSource::GetBand()
 
 int VRTSimpleSource::IsSameExceptBandNumber(VRTSimpleSource* poOtherSource)
 {
-    return nSrcXOff == poOtherSource->nSrcXOff &&
-           nSrcYOff == poOtherSource->nSrcYOff &&
-           nSrcXSize == poOtherSource->nSrcXSize &&
-           nSrcYSize == poOtherSource->nSrcYSize &&
-           nDstXOff == poOtherSource->nDstXOff &&
-           nDstYOff == poOtherSource->nDstYOff &&
-           nDstXSize == poOtherSource->nDstXSize &&
-           nDstYSize == poOtherSource->nDstYSize &&
-           bNoDataSet == poOtherSource->bNoDataSet &&
-           dfNoDataValue == poOtherSource->dfNoDataValue &&
+    return m_dfSrcXOff == poOtherSource->m_dfSrcXOff &&
+           m_dfSrcYOff == poOtherSource->m_dfSrcYOff &&
+           m_dfSrcXSize == poOtherSource->m_dfSrcXSize &&
+           m_dfSrcYSize == poOtherSource->m_dfSrcYSize &&
+           m_dfDstXOff == poOtherSource->m_dfDstXOff &&
+           m_dfDstYOff == poOtherSource->m_dfDstYOff &&
+           m_dfDstXSize == poOtherSource->m_dfDstXSize &&
+           m_dfDstYSize == poOtherSource->m_dfDstYSize &&
+           m_bNoDataSet == poOtherSource->m_bNoDataSet &&
+           m_dfNoDataValue == poOtherSource->m_dfNoDataValue &&
            GetBand() != NULL && poOtherSource->GetBand() != NULL &&
            GetBand()->GetDataset() != NULL &&
            poOtherSource->GetBand()->GetDataset() != NULL &&
@@ -721,8 +759,8 @@ void VRTSimpleSource::SrcToDst( double dfX, double dfY,
                                 double &dfXOut, double &dfYOut )
 
 {
-    dfXOut = ((dfX - nSrcXOff) / nSrcXSize) * nDstXSize + nDstXOff;
-    dfYOut = ((dfY - nSrcYOff) / nSrcYSize) * nDstYSize + nDstYOff;
+    dfXOut = ((dfX - m_dfSrcXOff) / m_dfSrcXSize) * m_dfDstXSize + m_dfDstXOff;
+    dfYOut = ((dfY - m_dfSrcYOff) / m_dfSrcYSize) * m_dfDstYSize + m_dfDstYOff;
 }
 
 /************************************************************************/
@@ -735,31 +773,37 @@ void VRTSimpleSource::DstToSrc( double dfX, double dfY,
                                 double &dfXOut, double &dfYOut )
 
 {
-    dfXOut = ((dfX - nDstXOff) / nDstXSize) * nSrcXSize + nSrcXOff;
-    dfYOut = ((dfY - nDstYOff) / nDstYSize) * nSrcYSize + nSrcYOff;
+    dfXOut = ((dfX - m_dfDstXOff) / m_dfDstXSize) * m_dfSrcXSize + m_dfSrcXOff;
+    dfYOut = ((dfY - m_dfDstYOff) / m_dfDstYSize) * m_dfSrcYSize + m_dfSrcYOff;
 }
 
 /************************************************************************/
 /*                          GetSrcDstWindow()                           */
 /************************************************************************/
 
-int 
+int
 VRTSimpleSource::GetSrcDstWindow( int nXOff, int nYOff, int nXSize, int nYSize,
                                   int nBufXSize, int nBufYSize,
                                   double *pdfReqXOff, double *pdfReqYOff,
                                   double *pdfReqXSize, double *pdfReqYSize,
                                   int *pnReqXOff, int *pnReqYOff,
                                   int *pnReqXSize, int *pnReqYSize,
-                                  int *pnOutXOff, int *pnOutYOff, 
+                                  int *pnOutXOff, int *pnOutYOff,
                                   int *pnOutXSize, int *pnOutYSize )
 
 {
-    int bDstWinSet = nDstXOff != -1 || nDstXSize != -1 
-        || nDstYOff != -1 || nDstYSize != -1;
+    if( m_dfSrcXSize == 0.0 || m_dfSrcYSize == 0.0 ||
+        m_dfDstXSize == 0.0 || m_dfDstYSize == 0.0 )
+    {
+        return FALSE;
+    }
+
+    const bool bDstWinSet = m_dfDstXOff != -1 || m_dfDstXSize != -1
+        || m_dfDstYOff != -1 || m_dfDstYSize != -1;
 
 #ifdef DEBUG
-    int bSrcWinSet = nSrcXOff != -1 || nSrcXSize != -1 
-        || nSrcYOff != -1 || nSrcYSize != -1;
+    const bool bSrcWinSet = m_dfSrcXOff != -1 || m_dfSrcXSize != -1
+        || m_dfSrcYOff != -1 || m_dfSrcYSize != -1;
 
     if( bSrcWinSet != bDstWinSet )
     {
@@ -773,10 +817,10 @@ VRTSimpleSource::GetSrcDstWindow( int nXOff, int nYOff, int nXSize, int nYSize,
 /* -------------------------------------------------------------------- */
     if( bDstWinSet )
     {
-        if( nXOff >= nDstXOff + nDstXSize
-            || nYOff >= nDstYOff + nDstYSize
-            || nXOff + nXSize < nDstXOff
-            || nYOff + nYSize < nDstYOff )
+        if( nXOff >= m_dfDstXOff + m_dfDstXSize
+            || nYOff >= m_dfDstYOff + m_dfDstYSize
+            || nXOff + nXSize < m_dfDstXOff
+            || nYOff + nYSize < m_dfDstYOff )
             return FALSE;
     }
 
@@ -794,37 +838,37 @@ VRTSimpleSource::GetSrcDstWindow( int nXOff, int nYOff, int nXSize, int nYSize,
 /*      the requested window.                                           */
 /* -------------------------------------------------------------------- */
     int bModifiedX = FALSE, bModifiedY = FALSE;
-    int nRXOff = nXOff;
-    int nRYOff = nYOff;
-    int nRXSize = nXSize;
-    int nRYSize = nYSize;
+    double dfRXOff = nXOff;
+    double dfRYOff = nYOff;
+    double dfRXSize = nXSize;
+    double dfRYSize = nYSize;
 
 
     if( bDstWinSet )
     {
-        if( nRXOff < nDstXOff )
+        if( dfRXOff < m_dfDstXOff )
         {
-            nRXSize = nRXSize + nRXOff - nDstXOff;
-            nRXOff = nDstXOff;
+            dfRXSize = dfRXSize + dfRXOff - m_dfDstXOff;
+            dfRXOff = m_dfDstXOff;
             bModifiedX = TRUE;
         }
 
-        if( nRYOff < nDstYOff )
+        if( dfRYOff < m_dfDstYOff )
         {
-            nRYSize = nRYSize + nRYOff - nDstYOff;
-            nRYOff = nDstYOff;
+            dfRYSize = dfRYSize + dfRYOff - m_dfDstYOff;
+            dfRYOff = m_dfDstYOff;
             bModifiedY = TRUE;
         }
 
-        if( nRXOff + nRXSize > nDstXOff + nDstXSize )
+        if( dfRXOff + dfRXSize > m_dfDstXOff + m_dfDstXSize )
         {
-            nRXSize = nDstXOff + nDstXSize - nRXOff;
+            dfRXSize = m_dfDstXOff + m_dfDstXSize - dfRXOff;
             bModifiedX = TRUE;
         }
 
-        if( nRYOff + nRYSize > nDstYOff + nDstYSize )
+        if( dfRYOff + dfRYSize > m_dfDstYOff + m_dfDstYSize )
         {
-            nRYSize = nDstYOff + nDstYSize - nRYOff;
+            dfRYSize = m_dfDstYOff + m_dfDstYSize - dfRYOff;
             bModifiedY = TRUE;
         }
     }
@@ -833,13 +877,25 @@ VRTSimpleSource::GetSrcDstWindow( int nXOff, int nYOff, int nXSize, int nYSize,
 /*      Translate requested region in virtual file into the source      */
 /*      band coordinates.                                               */
 /* -------------------------------------------------------------------- */
-    double      dfScaleX = nSrcXSize / (double) nDstXSize;
-    double      dfScaleY = nSrcYSize / (double) nDstYSize;
-    
-    *pdfReqXOff = (nRXOff - nDstXOff) * dfScaleX + nSrcXOff;
-    *pdfReqYOff = (nRYOff - nDstYOff) * dfScaleY + nSrcYOff;
-    *pdfReqXSize = nRXSize * dfScaleX;
-    *pdfReqYSize = nRYSize * dfScaleY;
+    const double      dfScaleX = m_dfSrcXSize / m_dfDstXSize;
+    const double      dfScaleY = m_dfSrcYSize / m_dfDstYSize;
+
+    *pdfReqXOff = (dfRXOff - m_dfDstXOff) * dfScaleX + m_dfSrcXOff;
+    *pdfReqYOff = (dfRYOff - m_dfDstYOff) * dfScaleY + m_dfSrcYOff;
+    *pdfReqXSize = dfRXSize * dfScaleX;
+    *pdfReqYSize = dfRYSize * dfScaleY;
+
+    if( !CPLIsFinite(*pdfReqXOff) ||
+        !CPLIsFinite(*pdfReqYOff) ||
+        !CPLIsFinite(*pdfReqXSize) ||
+        !CPLIsFinite(*pdfReqYSize) ||
+        *pdfReqXOff > INT_MAX ||
+        *pdfReqYOff > INT_MAX ||
+        *pdfReqXSize < 0 ||
+        *pdfReqYSize < 0 )
+    {
+        return FALSE;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Clamp within the bounds of the available source data.           */
@@ -860,8 +916,15 @@ VRTSimpleSource::GetSrcDstWindow( int nXOff, int nYOff, int nXSize, int nYSize,
     *pnReqXOff = (int) floor(*pdfReqXOff);
     *pnReqYOff = (int) floor(*pdfReqYOff);
 
-    *pnReqXSize = (int) floor(*pdfReqXSize + 0.5);
-    *pnReqYSize = (int) floor(*pdfReqYSize + 0.5);
+    if( *pdfReqXSize > INT_MAX )
+        *pnReqXSize = INT_MAX;
+    else
+        *pnReqXSize = (int) floor(*pdfReqXSize + 0.5);
+
+    if( *pdfReqYSize > INT_MAX )
+        *pnReqYSize = INT_MAX;
+    else
+        *pnReqYSize = (int) floor(*pdfReqYSize + 0.5);
 
 /* -------------------------------------------------------------------- */
 /*      Clamp within the bounds of the available source data.           */
@@ -872,25 +935,27 @@ VRTSimpleSource::GetSrcDstWindow( int nXOff, int nYOff, int nXSize, int nYSize,
     if( *pnReqYSize == 0 )
         *pnReqYSize = 1;
 
-    if( *pnReqXOff + *pnReqXSize > poRasterBand->GetXSize() )
+    if( *pnReqXSize > INT_MAX - *pnReqXOff ||
+        *pnReqXOff + *pnReqXSize > m_poRasterBand->GetXSize() )
     {
-        *pnReqXSize = poRasterBand->GetXSize() - *pnReqXOff;
+        *pnReqXSize = m_poRasterBand->GetXSize() - *pnReqXOff;
         bModifiedX = TRUE;
     }
-    if( *pdfReqXOff + *pdfReqXSize > poRasterBand->GetXSize() )
+    if( *pdfReqXOff + *pdfReqXSize > m_poRasterBand->GetXSize() )
     {
-        *pdfReqXSize = poRasterBand->GetXSize() - *pdfReqXOff;
+        *pdfReqXSize = m_poRasterBand->GetXSize() - *pdfReqXOff;
         bModifiedX = TRUE;
     }
 
-    if( *pnReqYOff + *pnReqYSize > poRasterBand->GetYSize() )
+    if( *pnReqYSize > INT_MAX - *pnReqYOff ||
+        *pnReqYOff + *pnReqYSize > m_poRasterBand->GetYSize() )
     {
-        *pnReqYSize = poRasterBand->GetYSize() - *pnReqYOff;
+        *pnReqYSize = m_poRasterBand->GetYSize() - *pnReqYOff;
         bModifiedY = TRUE;
     }
-    if( *pdfReqYOff + *pdfReqYSize > poRasterBand->GetYSize() )
+    if( *pdfReqYOff + *pdfReqYSize > m_poRasterBand->GetYSize() )
     {
-        *pdfReqYSize = poRasterBand->GetYSize() - *pdfReqYOff;
+        *pdfReqYSize = m_poRasterBand->GetYSize() - *pdfReqYOff;
         bModifiedY = TRUE;
     }
 
@@ -898,8 +963,8 @@ VRTSimpleSource::GetSrcDstWindow( int nXOff, int nYOff, int nXSize, int nYSize,
 /*      Don't do anything if the requesting region is completely off    */
 /*      the source image.                                               */
 /* -------------------------------------------------------------------- */
-    if( *pnReqXOff >= poRasterBand->GetXSize()
-        || *pnReqYOff >= poRasterBand->GetYSize()
+    if( *pnReqXOff >= m_poRasterBand->GetXSize()
+        || *pnReqYOff >= m_poRasterBand->GetYSize()
         || *pnReqXSize <= 0 || *pnReqYSize <= 0 )
     {
         return FALSE;
@@ -920,20 +985,33 @@ VRTSimpleSource::GetSrcDstWindow( int nXOff, int nYOff, int nXSize, int nYSize,
     double dfDstULX, dfDstULY, dfDstLRX, dfDstLRY;
     double dfScaleWinToBufX, dfScaleWinToBufY;
 
-    SrcToDst( (double) *pnReqXOff, (double) *pnReqYOff, dfDstULX, dfDstULY );
-    SrcToDst( *pnReqXOff + *pnReqXSize, *pnReqYOff + *pnReqYSize, 
+    SrcToDst( *pdfReqXOff, *pdfReqYOff, dfDstULX, dfDstULY );
+    SrcToDst( *pdfReqXOff + *pdfReqXSize, *pdfReqYOff + *pdfReqYSize,
               dfDstLRX, dfDstLRY );
+    //CPLDebug("VRT", "dfDstULX=%g dfDstULY=%g dfDstLRX=%g dfDstLRY=%g",
+    //         dfDstULX, dfDstULY, dfDstLRX, dfDstLRY);
 
     if( bModifiedX )
     {
         dfScaleWinToBufX = nBufXSize / (double) nXSize;
 
-        *pnOutXOff = (int) ((dfDstULX - nXOff) * dfScaleWinToBufX+0.001);
-        *pnOutXSize = (int) ((dfDstLRX - nXOff) * dfScaleWinToBufX+0.5) 
-            - *pnOutXOff;
+        const double dfOutXOff = (dfDstULX - nXOff) * dfScaleWinToBufX+0.001;
+        if( dfOutXOff <= 0 )
+            *pnOutXOff = 0;
+        else if( dfOutXOff > INT_MAX )
+            *pnOutXOff = INT_MAX;
+        else
+            *pnOutXOff = (int) (dfOutXOff);
+        double dfOutRightXOff = (dfDstLRX - nXOff) * dfScaleWinToBufX-0.001;
+        if( dfOutRightXOff < dfOutXOff )
+            return FALSE;
+        if( dfOutRightXOff > INT_MAX )
+            dfOutRightXOff = INT_MAX;
+        *pnOutXSize = (int) ceil(dfOutRightXOff) - *pnOutXOff;
 
         *pnOutXOff = MAX(0,*pnOutXOff);
-        if( *pnOutXOff + *pnOutXSize > nBufXSize )
+        if( *pnOutXSize > INT_MAX - *pnOutXOff ||
+            *pnOutXOff + *pnOutXSize > nBufXSize )
             *pnOutXSize = nBufXSize - *pnOutXOff;
     }
 
@@ -941,12 +1019,24 @@ VRTSimpleSource::GetSrcDstWindow( int nXOff, int nYOff, int nXSize, int nYSize,
     {
         dfScaleWinToBufY = nBufYSize / (double) nYSize;
 
-        *pnOutYOff = (int) ((dfDstULY - nYOff) * dfScaleWinToBufY+0.001);
-        *pnOutYSize = (int) ((dfDstLRY - nYOff) * dfScaleWinToBufY+0.5) 
-            - *pnOutYOff;
+        const double dfOutYOff = (dfDstULY - nYOff) * dfScaleWinToBufY+0.001;
+        if( dfOutYOff <= 0 )
+            *pnOutYOff = 0;
+        else if( dfOutYOff > INT_MAX )
+            *pnOutYOff = INT_MAX;
+        else
+            *pnOutYOff = (int) (dfOutYOff);
+        *pnOutYOff = (int) (dfOutYOff);
+        double dfOutTopYOff = (dfDstLRY - nYOff) * dfScaleWinToBufY-0.001;
+        if( dfOutTopYOff < dfOutYOff )
+            return FALSE;
+        if( dfOutTopYOff > INT_MAX )
+            dfOutTopYOff = INT_MAX;
+        *pnOutYSize = (int) ceil(dfOutTopYOff) - *pnOutYOff;
 
         *pnOutYOff = MAX(0,*pnOutYOff);
-        if( *pnOutYOff + *pnOutYSize > nBufYSize )
+        if( *pnOutYSize > INT_MAX - *pnOutYOff ||
+            *pnOutYOff + *pnOutYSize > nBufYSize )
             *pnOutYSize = nBufYSize - *pnOutYOff;
     }
 
@@ -957,13 +1047,32 @@ VRTSimpleSource::GetSrcDstWindow( int nXOff, int nYOff, int nXSize, int nYSize,
 }
 
 /************************************************************************/
+/*                          NeedMaxValAdjustment()                      */
+/************************************************************************/
+
+int VRTSimpleSource::NeedMaxValAdjustment() const
+{
+    if( m_nMaxValue )
+    {
+        const char* pszNBITS = m_poRasterBand->GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
+        int nBits = (pszNBITS) ? atoi(pszNBITS) : 0;
+        int nBandMaxValue = (1 << nBits) - 1;
+        if( nBandMaxValue == 0 || nBandMaxValue > m_nMaxValue )
+        {
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+/************************************************************************/
 /*                              RasterIO()                              */
 /************************************************************************/
 
-CPLErr 
+CPLErr
 VRTSimpleSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
-                           void *pData, int nBufXSize, int nBufYSize, 
-                           GDALDataType eBufType, 
+                           void *pData, int nBufXSize, int nBufYSize,
+                           GDALDataType eBufType,
                            GSpacing nPixelSpace,
                            GSpacing nLineSpace,
                            GDALRasterIOExtraArg* psExtraArgIn )
@@ -982,22 +1091,29 @@ VRTSimpleSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
     int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
 
     if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize,
-                          nBufXSize, nBufYSize, 
+                          nBufXSize, nBufYSize,
                           &dfReqXOff, &dfReqYOff, &dfReqXSize, &dfReqYSize,
                           &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
                           &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) )
     {
         return CE_None;
     }
+    /*CPLDebug("VRT", "nXOff=%d, nYOff=%d, nXSize=%d, nYSize=%d, nBufXSize=%d, nBufYSize=%d, "
+                    "dfReqXOff=%g, dfReqYOff=%g, dfReqXSize=%g, dfReqYSize=%g, "
+                    "nOutXOff=%d, nOutYOff=%d, nOutXSize=%d, nOutYSize=%d",
+                    nXOff, nYOff, nXSize, nYSize,
+                    nBufXSize, nBufYSize,
+                    dfReqXOff, dfReqYOff, dfReqXSize, dfReqYSize,
+                    nOutXOff, nOutYOff, nOutXSize, nOutYSize);*/
 
 /* -------------------------------------------------------------------- */
 /*      Actually perform the IO request.                                */
 /* -------------------------------------------------------------------- */
     CPLErr eErr;
 
-    if( osResampling.size() )
+    if( m_osResampling.size() )
     {
-        psExtraArg->eResampleAlg = GDALRasterIOGetResampleAlg(osResampling);
+        psExtraArg->eResampleAlg = GDALRasterIOGetResampleAlg(m_osResampling);
     }
     else if( psExtraArgIn != NULL )
     {
@@ -1009,15 +1125,37 @@ VRTSimpleSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
     psExtraArg->dfXSize = dfReqXSize;
     psExtraArg->dfYSize = dfReqYSize;
 
-    eErr = 
-        poRasterBand->RasterIO( GF_Read, 
-                                nReqXOff, nReqYOff, nReqXSize, nReqYSize,
-                                ((unsigned char *) pData) 
+    GByte* pabyOut = ((unsigned char *) pData)
                                 + nOutXOff * nPixelSpace
-                                + (GPtrDiff_t)nOutYOff * nLineSpace, 
-                                nOutXSize, nOutYSize, 
+                                + (GPtrDiff_t)nOutYOff * nLineSpace;
+    eErr =
+        m_poRasterBand->RasterIO( GF_Read,
+                                nReqXOff, nReqYOff, nReqXSize, nReqYSize,
+                                pabyOut,
+                                nOutXSize, nOutYSize,
                                 eBufType, nPixelSpace, nLineSpace, psExtraArg );
 
+    if( NeedMaxValAdjustment() )
+    {
+        for(int j=0;j<nOutYSize;j++)
+        {
+            for(int i=0;i<nOutXSize;i++)
+            {
+                int nVal;
+                GDALCopyWords(pabyOut + j * nLineSpace + i * nPixelSpace,
+                                eBufType, 0,
+                                &nVal, GDT_Int32, 0,
+                                1);
+                if( nVal > m_nMaxValue )
+                    nVal = m_nMaxValue;
+                GDALCopyWords(&nVal, GDT_Int32, 0,
+                                pabyOut + j * nLineSpace + i * nPixelSpace,
+                                eBufType, 0,
+                                1);
+            }
+        }
+    }
+
     return eErr;
 }
 
@@ -1040,14 +1178,17 @@ double VRTSimpleSource::GetMinimum( int nXSize, int nYSize, int *pbSuccess )
                           &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
                           &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) ||
         nReqXOff != 0 || nReqYOff != 0 ||
-        nReqXSize != poRasterBand->GetXSize() ||
-        nReqYSize != poRasterBand->GetYSize())
+        nReqXSize != m_poRasterBand->GetXSize() ||
+        nReqYSize != m_poRasterBand->GetYSize())
     {
         *pbSuccess = FALSE;
         return 0;
     }
 
-    return poRasterBand->GetMinimum(pbSuccess);
+    double dfVal = m_poRasterBand->GetMinimum(pbSuccess);
+    if( NeedMaxValAdjustment() && dfVal > m_nMaxValue )
+        dfVal = m_nMaxValue;
+    return dfVal;
 }
 
 /************************************************************************/
@@ -1069,14 +1210,17 @@ double VRTSimpleSource::GetMaximum( int nXSize, int nYSize, int *pbSuccess )
                           &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
                           &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) ||
         nReqXOff != 0 || nReqYOff != 0 ||
-        nReqXSize != poRasterBand->GetXSize() ||
-        nReqYSize != poRasterBand->GetYSize())
+        nReqXSize != m_poRasterBand->GetXSize() ||
+        nReqYSize != m_poRasterBand->GetYSize())
     {
         *pbSuccess = FALSE;
         return 0;
     }
 
-    return poRasterBand->GetMaximum(pbSuccess);
+    double dfVal = m_poRasterBand->GetMaximum(pbSuccess);
+    if( NeedMaxValAdjustment() && dfVal > m_nMaxValue )
+        dfVal = m_nMaxValue;
+    return dfVal;
 }
 
 /************************************************************************/
@@ -1098,13 +1242,21 @@ CPLErr VRTSimpleSource::ComputeRasterMinMax( int nXSize, int nYSize, int bApprox
                           &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
                           &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) ||
         nReqXOff != 0 || nReqYOff != 0 ||
-        nReqXSize != poRasterBand->GetXSize() ||
-        nReqYSize != poRasterBand->GetYSize())
+        nReqXSize != m_poRasterBand->GetXSize() ||
+        nReqYSize != m_poRasterBand->GetYSize())
     {
         return CE_Failure;
     }
 
-    return poRasterBand->ComputeRasterMinMax(bApproxOK, adfMinMax);
+    CPLErr eErr = m_poRasterBand->ComputeRasterMinMax(bApproxOK, adfMinMax);
+    if( NeedMaxValAdjustment() )
+    {
+        if( adfMinMax[0] > m_nMaxValue )
+            adfMinMax[0] = m_nMaxValue;
+        if( adfMinMax[1] > m_nMaxValue )
+            adfMinMax[1] = m_nMaxValue;
+    }
+    return eErr;
 }
 
 /************************************************************************/
@@ -1112,8 +1264,8 @@ CPLErr VRTSimpleSource::ComputeRasterMinMax( int nXSize, int nYSize, int bApprox
 /************************************************************************/
 
 CPLErr VRTSimpleSource::ComputeStatistics( int nXSize, int nYSize,
-                                      int bApproxOK, 
-                                      double *pdfMin, double *pdfMax, 
+                                      int bApproxOK,
+                                      double *pdfMin, double *pdfMax,
                                       double *pdfMean, double *pdfStdDev,
                                       GDALProgressFunc pfnProgress, void *pProgressData )
 {
@@ -1124,19 +1276,20 @@ CPLErr VRTSimpleSource::ComputeStatistics( int nXSize, int nYSize,
     // The window we will actual set _within_ the pData buffer.
     int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
 
-    if( !GetSrcDstWindow( 0, 0, nXSize, nYSize,
+    if( NeedMaxValAdjustment() ||
+        !GetSrcDstWindow( 0, 0, nXSize, nYSize,
                           nXSize, nYSize,
                           &dfReqXOff, &dfReqYOff, &dfReqXSize, &dfReqYSize,
                           &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
                           &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) ||
         nReqXOff != 0 || nReqYOff != 0 ||
-        nReqXSize != poRasterBand->GetXSize() ||
-        nReqYSize != poRasterBand->GetYSize())
+        nReqXSize != m_poRasterBand->GetXSize() ||
+        nReqYSize != m_poRasterBand->GetYSize())
     {
         return CE_Failure;
     }
 
-    return poRasterBand->ComputeStatistics(bApproxOK, pdfMin, pdfMax,
+    return m_poRasterBand->ComputeStatistics(bApproxOK, pdfMin, pdfMax,
                                            pdfMean, pdfStdDev,
                                            pfnProgress, pProgressData);
 }
@@ -1158,19 +1311,20 @@ CPLErr VRTSimpleSource::GetHistogram( int nXSize, int nYSize,
     // The window we will actual set _within_ the pData buffer.
     int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
 
-    if( !GetSrcDstWindow( 0, 0, nXSize, nYSize,
+    if( NeedMaxValAdjustment() ||
+        !GetSrcDstWindow( 0, 0, nXSize, nYSize,
                           nXSize, nYSize,
                           &dfReqXOff, &dfReqYOff, &dfReqXSize, &dfReqYSize,
                           &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
                           &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) ||
         nReqXOff != 0 || nReqYOff != 0 ||
-        nReqXSize != poRasterBand->GetXSize() ||
-        nReqYSize != poRasterBand->GetYSize())
+        nReqXSize != m_poRasterBand->GetXSize() ||
+        nReqYSize != m_poRasterBand->GetYSize())
     {
         return CE_Failure;
     }
 
-    return poRasterBand->GetHistogram( dfMin, dfMax, nBuckets,
+    return m_poRasterBand->GetHistogram( dfMin, dfMax, nBuckets,
                                        panHistogram,
                                        bIncludeOutOfRange, bApproxOK,
                                        pfnProgress, pProgressData );
@@ -1217,13 +1371,13 @@ CPLErr VRTSimpleSource::DatasetRasterIO(
         return CE_None;
     }
 
-    GDALDataset* poDS = poRasterBand->GetDataset();
+    GDALDataset* poDS = m_poRasterBand->GetDataset();
     if (poDS == NULL)
         return CE_Failure;
 
-    if( osResampling.size() )
+    if( m_osResampling.size() )
     {
-        psExtraArg->eResampleAlg = GDALRasterIOGetResampleAlg(osResampling);
+        psExtraArg->eResampleAlg = GDALRasterIOGetResampleAlg(m_osResampling);
     }
     else if( psExtraArgIn != NULL )
     {
@@ -1235,15 +1389,40 @@ CPLErr VRTSimpleSource::DatasetRasterIO(
     psExtraArg->dfXSize = dfReqXSize;
     psExtraArg->dfYSize = dfReqYSize;
 
+    GByte* pabyOut = ((unsigned char *) pData)
+                           + nOutXOff * nPixelSpace
+                           + (GPtrDiff_t)nOutYOff * nLineSpace;
     CPLErr eErr = poDS->RasterIO( GF_Read,
                            nReqXOff, nReqYOff, nReqXSize, nReqYSize,
-                           ((unsigned char *) pData)
-                           + nOutXOff * nPixelSpace
-                           + (GPtrDiff_t)nOutYOff * nLineSpace,
+                           pabyOut,
                            nOutXSize, nOutYSize,
                            eBufType, nBandCount, panBandMap,
                            nPixelSpace, nLineSpace, nBandSpace, psExtraArg );
 
+    if( NeedMaxValAdjustment() )
+    {
+        for(int k=0;k<nBandCount;k++)
+        {
+            for(int j=0;j<nOutYSize;j++)
+            {
+                for(int i=0;i<nOutXSize;i++)
+                {
+                    int nVal;
+                    GDALCopyWords(pabyOut + k * nBandSpace + j * nLineSpace + i * nPixelSpace,
+                                eBufType, 0,
+                                &nVal, GDT_Int32, 0,
+                                1);
+                    if( nVal > m_nMaxValue )
+                        nVal = m_nMaxValue;
+                    GDALCopyWords(&nVal, GDT_Int32, 0,
+                                pabyOut + k * nBandSpace + j * nLineSpace + i * nPixelSpace,
+                                eBufType, 0,
+                                1);
+                }
+            }
+        }
+    }
+
     return eErr;
 }
 
@@ -1253,7 +1432,7 @@ CPLErr VRTSimpleSource::DatasetRasterIO(
 
 void VRTSimpleSource::SetResampling( const char* pszResampling )
 {
-    osResampling = (pszResampling) ? pszResampling : "";
+    m_osResampling = (pszResampling) ? pszResampling : "";
 }
 
 /************************************************************************/
@@ -1292,10 +1471,10 @@ CPLXMLNode *VRTAveragedSource::SerializeToXML( const char *pszVRTPath )
 /*                              RasterIO()                              */
 /************************************************************************/
 
-CPLErr 
+CPLErr
 VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
-                           void *pData, int nBufXSize, int nBufYSize, 
-                           GDALDataType eBufType, 
+                           void *pData, int nBufXSize, int nBufYSize,
+                           GDALDataType eBufType,
                            GSpacing nPixelSpace,
                            GSpacing nLineSpace,
                            GDALRasterIOExtraArg* psExtraArgIn )
@@ -1313,7 +1492,7 @@ VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
     // The window we will actual set _within_ the pData buffer.
     int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
 
-    if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, 
+    if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize,
                           &dfReqXOff, &dfReqYOff, &dfReqXSize, &dfReqYSize,
                           &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
                           &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) )
@@ -1325,11 +1504,9 @@ VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
 /* -------------------------------------------------------------------- */
     float *pafSrc;
 
-    pafSrc = (float *) VSIMalloc3(sizeof(float), nReqXSize, nReqYSize);
+    pafSrc = (float *) VSI_MALLOC3_VERBOSE(sizeof(float), nReqXSize, nReqYSize);
     if( pafSrc == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory, 
-                  "Out of memory allocating working buffer in VRTAveragedSource::RasterIO()." );
         return CE_Failure;
     }
 
@@ -1338,9 +1515,9 @@ VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
 /* -------------------------------------------------------------------- */
     CPLErr eErr;
 
-    if( osResampling.size() )
+    if( m_osResampling.size() )
     {
-        psExtraArg->eResampleAlg = GDALRasterIOGetResampleAlg(osResampling);
+        psExtraArg->eResampleAlg = GDALRasterIOGetResampleAlg(m_osResampling);
     }
     else if( psExtraArgIn != NULL )
     {
@@ -1353,9 +1530,9 @@ VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
     psExtraArg->dfXSize = dfReqXSize;
     psExtraArg->dfYSize = dfReqYSize;
 
-    eErr = poRasterBand->RasterIO( GF_Read, 
+    eErr = m_poRasterBand->RasterIO( GF_Read,
                                    nReqXOff, nReqYOff, nReqXSize, nReqYSize,
-                                   pafSrc, nReqXSize, nReqYSize, GDT_Float32, 
+                                   pafSrc, nReqXSize, nReqYSize, GDT_Float32,
                                    0, 0, psExtraArg );
 
     if( eErr != CE_None )
@@ -1372,9 +1549,9 @@ VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
         double  dfYDst;
 
         dfYDst = (iBufLine / (double) nBufYSize) * nYSize + nYOff;
-        
-        for( int iBufPixel = nOutXOff; 
-             iBufPixel < nOutXOff + nOutXSize; 
+
+        for( int iBufPixel = nOutXOff;
+             iBufPixel < nOutXOff + nOutXSize;
              iBufPixel++ )
         {
             double dfXDst;
@@ -1421,7 +1598,7 @@ VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
 
             double dfSum = 0.0;
             int    nPixelCount = 0;
-            
+
             for( int iY = iYSrcStart; iY < iYSrcEnd; iY++ )
             {
                 if( iY < 0 || iY >= nReqYSize )
@@ -1436,7 +1613,7 @@ VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
                     if (CPLIsNan(fSampledValue))
                         continue;
 
-                    if( bNoDataSet && ARE_REAL_EQUAL(fSampledValue, dfNoDataValue))
+                    if( m_bNoDataSet && ARE_REAL_EQUAL(fSampledValue, m_dfNoDataValue))
                         continue;
 
                     nPixelCount++;
@@ -1453,14 +1630,14 @@ VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
             // Put it in the output buffer.
             GByte *pDstLocation;
 
-            pDstLocation = ((GByte *)pData) 
+            pDstLocation = ((GByte *)pData)
                 + nPixelSpace * iBufPixel
                 + (GPtrDiff_t)nLineSpace * iBufLine;
 
             if( eBufType == GDT_Byte )
                 *pDstLocation = (GByte) MIN(255,MAX(0,dfOutputValue + 0.5));
             else
-                GDALCopyWords( &dfOutputValue, GDT_Float32, 4, 
+                GDALCopyWords( &dfOutputValue, GDT_Float32, 4,
                                pDstLocation, eBufType, 8, 1 );
         }
     }
@@ -1554,32 +1731,60 @@ CPLErr VRTAveragedSource::GetHistogram( CPL_UNUSED int nXSize,
 VRTComplexSource::VRTComplexSource()
 
 {
-    eScalingType = VRT_SCALING_NONE;
-    dfScaleOff = 0.0;
-    dfScaleRatio = 1.0;
-    
-    bNoDataSet = FALSE;
-    dfNoDataValue = 0.0;
-
-    padfLUTInputs = NULL;
-    padfLUTOutputs = NULL;
-    nLUTItemCount = 0;
-    nColorTableComponent = 0;
-
-    bSrcMinMaxDefined = FALSE;
-    dfSrcMin = 0.0;
-    dfSrcMax = 0.0;
-    dfDstMin = 0.0;
-    dfDstMax = 0.0;
-    dfExponent = 1.0;
+    m_eScalingType = VRT_SCALING_NONE;
+    m_dfScaleOff = 0.0;
+    m_dfScaleRatio = 1.0;
+
+    m_padfLUTInputs = NULL;
+    m_padfLUTOutputs = NULL;
+    m_nLUTItemCount = 0;
+    m_nColorTableComponent = 0;
+
+    m_bSrcMinMaxDefined = FALSE;
+    m_dfSrcMin = 0.0;
+    m_dfSrcMax = 0.0;
+    m_dfDstMin = 0.0;
+    m_dfDstMax = 0.0;
+    m_dfExponent = 1.0;
+}
+
+VRTComplexSource::VRTComplexSource(const VRTComplexSource* poSrcSource,
+                                   double dfXDstRatio, double dfYDstRatio) :
+                        VRTSimpleSource(poSrcSource, dfXDstRatio, dfYDstRatio)
+{
+    m_eScalingType = poSrcSource->m_eScalingType;
+    m_dfScaleOff = poSrcSource->m_dfScaleOff;
+    m_dfScaleRatio = poSrcSource->m_dfScaleRatio;
+
+    m_nLUTItemCount = poSrcSource->m_nLUTItemCount;
+    if( m_nLUTItemCount )
+    {
+        m_padfLUTInputs = (double*)CPLMalloc(sizeof(double) * m_nLUTItemCount);
+        memcpy(m_padfLUTInputs, poSrcSource->m_padfLUTInputs, sizeof(double) * m_nLUTItemCount);
+        m_padfLUTOutputs = (double*)CPLMalloc(sizeof(double) * m_nLUTItemCount);
+        memcpy(m_padfLUTOutputs, poSrcSource->m_padfLUTOutputs, sizeof(double) * m_nLUTItemCount);
+    }
+    else
+    {
+        m_padfLUTInputs = NULL;
+        m_padfLUTOutputs = NULL;
+    }
+    m_nColorTableComponent = poSrcSource->m_nColorTableComponent;
+
+    m_bSrcMinMaxDefined = poSrcSource->m_bSrcMinMaxDefined;
+    m_dfSrcMin = poSrcSource->m_dfSrcMin;
+    m_dfSrcMax = poSrcSource->m_dfSrcMax;
+    m_dfDstMin = poSrcSource->m_dfDstMin;
+    m_dfDstMax = poSrcSource->m_dfDstMax;
+    m_dfExponent = poSrcSource->m_dfExponent;
 }
 
 VRTComplexSource::~VRTComplexSource()
 {
-    if (padfLUTInputs)
-        VSIFree( padfLUTInputs );
-    if (padfLUTOutputs)
-        VSIFree( padfLUTOutputs );
+    if (m_padfLUTInputs)
+        VSIFree( m_padfLUTInputs );
+    if (m_padfLUTOutputs)
+        VSIFree( m_padfLUTOutputs );
 }
 
 /************************************************************************/
@@ -1597,58 +1802,71 @@ CPLXMLNode *VRTComplexSource::SerializeToXML( const char *pszVRTPath )
     CPLFree( psSrc->pszValue );
     psSrc->pszValue = CPLStrdup( "ComplexSource" );
 
-    if( bNoDataSet )
+    if( m_bNoDataSet )
     {
-        if (CPLIsNan(dfNoDataValue))
+        if (CPLIsNan(m_dfNoDataValue))
             CPLSetXMLValue( psSrc, "NODATA", "nan");
         else
-            CPLSetXMLValue( psSrc, "NODATA", 
-                            CPLSPrintf("%.16g", dfNoDataValue) );
+            CPLSetXMLValue( psSrc, "NODATA",
+                            CPLSPrintf("%.16g", m_dfNoDataValue) );
     }
-        
-    switch( eScalingType )
+
+    switch( m_eScalingType )
     {
         case VRT_SCALING_NONE:
             break;
 
         case VRT_SCALING_LINEAR:
         {
-            CPLSetXMLValue( psSrc, "ScaleOffset", 
-                            CPLSPrintf("%g", dfScaleOff) );
-            CPLSetXMLValue( psSrc, "ScaleRatio", 
-                            CPLSPrintf("%g", dfScaleRatio) );
+            CPLSetXMLValue( psSrc, "ScaleOffset",
+                            CPLSPrintf("%g", m_dfScaleOff) );
+            CPLSetXMLValue( psSrc, "ScaleRatio",
+                            CPLSPrintf("%g", m_dfScaleRatio) );
             break;
         }
 
         case VRT_SCALING_EXPONENTIAL:
         {
-            CPLSetXMLValue( psSrc, "Exponent", 
-                            CPLSPrintf("%g", dfExponent) );
-            CPLSetXMLValue( psSrc, "SrcMin", 
-                            CPLSPrintf("%g", dfSrcMin) );
-            CPLSetXMLValue( psSrc, "SrcMax", 
-                            CPLSPrintf("%g", dfSrcMax) );
-            CPLSetXMLValue( psSrc, "DstMin", 
-                            CPLSPrintf("%g", dfDstMin) );
-            CPLSetXMLValue( psSrc, "DstMax", 
-                            CPLSPrintf("%g", dfDstMax) );
+            CPLSetXMLValue( psSrc, "Exponent",
+                            CPLSPrintf("%g", m_dfExponent) );
+            CPLSetXMLValue( psSrc, "SrcMin",
+                            CPLSPrintf("%g", m_dfSrcMin) );
+            CPLSetXMLValue( psSrc, "SrcMax",
+                            CPLSPrintf("%g", m_dfSrcMax) );
+            CPLSetXMLValue( psSrc, "DstMin",
+                            CPLSPrintf("%g", m_dfDstMin) );
+            CPLSetXMLValue( psSrc, "DstMax",
+                            CPLSPrintf("%g", m_dfDstMax) );
             break;
         }
     }
 
-    if ( nLUTItemCount )
+    if ( m_nLUTItemCount )
     {
-        CPLString osLUT = CPLString().Printf("%g:%g", padfLUTInputs[0], padfLUTOutputs[0]);
+        // Make sure we print with sufficient precision to address really close
+        // entries (#6422)
+        CPLString osLUT;
+        if( m_nLUTItemCount > 0 &&
+            CPLString().Printf("%g", m_padfLUTInputs[0]) == CPLString().Printf("%g", m_padfLUTInputs[1]) )
+            osLUT = CPLString().Printf("%.18g:%g", m_padfLUTInputs[0], m_padfLUTOutputs[0]);
+        else
+            osLUT = CPLString().Printf("%g:%g", m_padfLUTInputs[0], m_padfLUTOutputs[0]);
         int i;
-        for ( i = 1; i < nLUTItemCount; i++ )
-            osLUT += CPLString().Printf(",%g:%g", padfLUTInputs[i], padfLUTOutputs[i]);
+        for ( i = 1; i < m_nLUTItemCount; i++ )
+        {
+            if( CPLString().Printf("%g", m_padfLUTInputs[i]) == CPLString().Printf("%g", m_padfLUTInputs[i-1]) ||
+                (i + 1 < m_nLUTItemCount && CPLString().Printf("%g", m_padfLUTInputs[i]) == CPLString().Printf("%g", m_padfLUTInputs[i+1])) )
+                osLUT += CPLString().Printf(",%.18g:%g", m_padfLUTInputs[i], m_padfLUTOutputs[i]);
+            else
+                osLUT += CPLString().Printf(",%g:%g", m_padfLUTInputs[i], m_padfLUTOutputs[i]);
+        }
         CPLSetXMLValue( psSrc, "LUT", osLUT );
     }
 
-    if ( nColorTableComponent )
+    if ( m_nColorTableComponent )
     {
-        CPLSetXMLValue( psSrc, "ColorTableComponent", 
-                        CPLSPrintf("%d", nColorTableComponent) );
+        CPLSetXMLValue( psSrc, "ColorTableComponent",
+                        CPLSPrintf("%d", m_nColorTableComponent) );
     }
 
     return psSrc;
@@ -1673,36 +1891,36 @@ CPLErr VRTComplexSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
 /* -------------------------------------------------------------------- */
 /*      Complex parameters.                                             */
 /* -------------------------------------------------------------------- */
-    if( CPLGetXMLValue(psSrc, "ScaleOffset", NULL) != NULL 
+    if( CPLGetXMLValue(psSrc, "ScaleOffset", NULL) != NULL
         || CPLGetXMLValue(psSrc, "ScaleRatio", NULL) != NULL )
     {
-        eScalingType = VRT_SCALING_LINEAR;
-        dfScaleOff = CPLAtof(CPLGetXMLValue(psSrc, "ScaleOffset", "0") );
-        dfScaleRatio = CPLAtof(CPLGetXMLValue(psSrc, "ScaleRatio", "1") );
+        m_eScalingType = VRT_SCALING_LINEAR;
+        m_dfScaleOff = CPLAtof(CPLGetXMLValue(psSrc, "ScaleOffset", "0") );
+        m_dfScaleRatio = CPLAtof(CPLGetXMLValue(psSrc, "ScaleRatio", "1") );
     }
     else if( CPLGetXMLValue(psSrc, "Exponent", NULL) != NULL &&
-             CPLGetXMLValue(psSrc, "DstMin", NULL) != NULL && 
+             CPLGetXMLValue(psSrc, "DstMin", NULL) != NULL &&
              CPLGetXMLValue(psSrc, "DstMax", NULL) != NULL )
     {
-        eScalingType = VRT_SCALING_EXPONENTIAL;
-        dfExponent = CPLAtof(CPLGetXMLValue(psSrc, "Exponent", "1.0") );
+        m_eScalingType = VRT_SCALING_EXPONENTIAL;
+        m_dfExponent = CPLAtof(CPLGetXMLValue(psSrc, "Exponent", "1.0") );
 
-        if( CPLGetXMLValue(psSrc, "SrcMin", NULL) != NULL 
+        if( CPLGetXMLValue(psSrc, "SrcMin", NULL) != NULL
          && CPLGetXMLValue(psSrc, "SrcMax", NULL) != NULL )
         {
-            dfSrcMin = CPLAtof(CPLGetXMLValue(psSrc, "SrcMin", "0.0") );
-            dfSrcMax = CPLAtof(CPLGetXMLValue(psSrc, "SrcMax", "0.0") );
-            bSrcMinMaxDefined = TRUE;
+            m_dfSrcMin = CPLAtof(CPLGetXMLValue(psSrc, "SrcMin", "0.0") );
+            m_dfSrcMax = CPLAtof(CPLGetXMLValue(psSrc, "SrcMax", "0.0") );
+            m_bSrcMinMaxDefined = TRUE;
         }
 
-        dfDstMin = CPLAtof(CPLGetXMLValue(psSrc, "DstMin", "0.0") );
-        dfDstMax = CPLAtof(CPLGetXMLValue(psSrc, "DstMax", "0.0") );
+        m_dfDstMin = CPLAtof(CPLGetXMLValue(psSrc, "DstMin", "0.0") );
+        m_dfDstMax = CPLAtof(CPLGetXMLValue(psSrc, "DstMax", "0.0") );
     }
 
     if( CPLGetXMLValue(psSrc, "NODATA", NULL) != NULL )
     {
-        bNoDataSet = TRUE;
-        dfNoDataValue = CPLAtofM(CPLGetXMLValue(psSrc, "NODATA", "0"));
+        m_bNoDataSet = TRUE;
+        m_dfNoDataValue = CPLAtofM(CPLGetXMLValue(psSrc, "NODATA", "0"));
     }
 
     if( CPLGetXMLValue(psSrc, "LUT", NULL) != NULL )
@@ -1710,65 +1928,65 @@ CPLErr VRTComplexSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
         int nIndex;
         char **papszValues = CSLTokenizeString2(CPLGetXMLValue(psSrc, "LUT", ""), ",:", CSLT_ALLOWEMPTYTOKENS);
 
-        if (nLUTItemCount)
+        if (m_nLUTItemCount)
         {
-            if (padfLUTInputs)
+            if (m_padfLUTInputs)
             {
-                VSIFree( padfLUTInputs );
-                padfLUTInputs = NULL;
+                VSIFree( m_padfLUTInputs );
+                m_padfLUTInputs = NULL;
             }
-            if (padfLUTOutputs)
+            if (m_padfLUTOutputs)
             {
-                VSIFree( padfLUTOutputs );
-                padfLUTOutputs = NULL;
+                VSIFree( m_padfLUTOutputs );
+                m_padfLUTOutputs = NULL;
             }
-            nLUTItemCount = 0;
+            m_nLUTItemCount = 0;
         }
 
-        nLUTItemCount = CSLCount(papszValues) / 2;
+        m_nLUTItemCount = CSLCount(papszValues) / 2;
 
-        padfLUTInputs = (double *) VSIMalloc2(nLUTItemCount, sizeof(double));
-        if ( !padfLUTInputs )
+        m_padfLUTInputs = (double *) VSIMalloc2(m_nLUTItemCount, sizeof(double));
+        if ( !m_padfLUTInputs )
         {
             CSLDestroy(papszValues);
-            nLUTItemCount = 0;
+            m_nLUTItemCount = 0;
             return CE_Failure;
         }
 
-        padfLUTOutputs = (double *) VSIMalloc2(nLUTItemCount, sizeof(double));
-        if ( !padfLUTOutputs )
+        m_padfLUTOutputs = (double *) VSIMalloc2(m_nLUTItemCount, sizeof(double));
+        if ( !m_padfLUTOutputs )
         {
             CSLDestroy(papszValues);
-            VSIFree( padfLUTInputs );
-            padfLUTInputs = NULL;
-            nLUTItemCount = 0;
+            VSIFree( m_padfLUTInputs );
+            m_padfLUTInputs = NULL;
+            m_nLUTItemCount = 0;
             return CE_Failure;
         }
-        
-        for ( nIndex = 0; nIndex < nLUTItemCount; nIndex++ )
+
+        for ( nIndex = 0; nIndex < m_nLUTItemCount; nIndex++ )
         {
-            padfLUTInputs[nIndex] = CPLAtof( papszValues[nIndex * 2] );
-            padfLUTOutputs[nIndex] = CPLAtof( papszValues[nIndex * 2 + 1] );
+            m_padfLUTInputs[nIndex] = CPLAtof( papszValues[nIndex * 2] );
+            m_padfLUTOutputs[nIndex] = CPLAtof( papszValues[nIndex * 2 + 1] );
 
 	    // Enforce the requirement that the LUT input array is monotonically non-decreasing.
-	    if ( nIndex > 0 && padfLUTInputs[nIndex] < padfLUTInputs[nIndex - 1] )
+	    if ( nIndex > 0 && m_padfLUTInputs[nIndex] < m_padfLUTInputs[nIndex - 1] )
 	    {
 		CSLDestroy(papszValues);
-		VSIFree( padfLUTInputs );
-		VSIFree( padfLUTOutputs );
-		padfLUTInputs = NULL;
-		padfLUTOutputs = NULL;
-		nLUTItemCount = 0;
+		VSIFree( m_padfLUTInputs );
+		VSIFree( m_padfLUTOutputs );
+		m_padfLUTInputs = NULL;
+		m_padfLUTOutputs = NULL;
+		m_nLUTItemCount = 0;
 		return CE_Failure;
 	    }
         }
-        
+
         CSLDestroy(papszValues);
     }
-    
+
     if( CPLGetXMLValue(psSrc, "ColorTableComponent", NULL) != NULL )
     {
-        nColorTableComponent = atoi(CPLGetXMLValue(psSrc, "ColorTableComponent", "0"));
+        m_nColorTableComponent = atoi(CPLGetXMLValue(psSrc, "ColorTableComponent", "0"));
     }
 
     return CE_None;
@@ -1783,22 +2001,22 @@ VRTComplexSource::LookupValue( double dfInput )
 {
     // Find the index of the first element in the LUT input array that
     // is not smaller than the input value.
-    int i = std::lower_bound(padfLUTInputs, padfLUTInputs + nLUTItemCount, dfInput) - padfLUTInputs;
+    int i = static_cast<int>(std::lower_bound(m_padfLUTInputs, m_padfLUTInputs + m_nLUTItemCount, dfInput) - m_padfLUTInputs);
 
     if (i == 0)
-	return padfLUTOutputs[0];
+	return m_padfLUTOutputs[0];
 
     // If the index is beyond the end of the LUT input array, the input
     // value is larger than all the values in the array.
-    if (i == nLUTItemCount)
-	return padfLUTOutputs[nLUTItemCount - 1];
+    if (i == m_nLUTItemCount)
+	return m_padfLUTOutputs[m_nLUTItemCount - 1];
 
-    if (padfLUTInputs[i] == dfInput)
-	return padfLUTOutputs[i];
+    if (m_padfLUTInputs[i] == dfInput)
+	return m_padfLUTOutputs[i];
 
     // Otherwise, interpolate.
-    return padfLUTOutputs[i - 1] + (dfInput - padfLUTInputs[i - 1]) *
-	((padfLUTOutputs[i] - padfLUTOutputs[i - 1]) / (padfLUTInputs[i] - padfLUTInputs[i - 1]));
+    return m_padfLUTOutputs[i - 1] + (dfInput - m_padfLUTInputs[i - 1]) *
+	((m_padfLUTOutputs[i] - m_padfLUTOutputs[i - 1]) / (m_padfLUTInputs[i] - m_padfLUTInputs[i - 1]));
 }
 
 /************************************************************************/
@@ -1807,28 +2025,28 @@ VRTComplexSource::LookupValue( double dfInput )
 
 void VRTComplexSource::SetLinearScaling(double dfOffset, double dfScale)
 {
-    eScalingType = VRT_SCALING_LINEAR;
-    dfScaleOff = dfOffset;
-    dfScaleRatio = dfScale;
+    m_eScalingType = VRT_SCALING_LINEAR;
+    m_dfScaleOff = dfOffset;
+    m_dfScaleRatio = dfScale;
 }
 
 /************************************************************************/
 /*                         SetPowerScaling()                           */
 /************************************************************************/
 
-void VRTComplexSource::SetPowerScaling(double dfExponent,
-                                       double dfSrcMin,
-                                       double dfSrcMax,
-                                       double dfDstMin,
-                                       double dfDstMax)
+void VRTComplexSource::SetPowerScaling(double dfExponentIn,
+                                       double dfSrcMinIn,
+                                       double dfSrcMaxIn,
+                                       double dfDstMinIn,
+                                       double dfDstMaxIn)
 {
-    eScalingType = VRT_SCALING_EXPONENTIAL;
-    this->dfExponent = dfExponent;
-    this->dfSrcMin = dfSrcMin;
-    this->dfSrcMax = dfSrcMax;
-    this->dfDstMin = dfDstMin;
-    this->dfDstMax = dfDstMax;
-    bSrcMinMaxDefined = TRUE;
+    m_eScalingType = VRT_SCALING_EXPONENTIAL;
+    m_dfExponent = dfExponentIn;
+    m_dfSrcMin = dfSrcMinIn;
+    m_dfSrcMax = dfSrcMaxIn;
+    m_dfDstMin = dfDstMinIn;
+    m_dfDstMax = dfDstMaxIn;
+    m_bSrcMinMaxDefined = TRUE;
 }
 
 /************************************************************************/
@@ -1837,21 +2055,21 @@ void VRTComplexSource::SetPowerScaling(double dfExponent,
 
 void VRTComplexSource::SetColorTableComponent(int nComponent)
 {
-    nColorTableComponent = nComponent;
+    m_nColorTableComponent = nComponent;
 }
 
 /************************************************************************/
 /*                              RasterIO()                              */
 /************************************************************************/
 
-CPLErr 
+CPLErr
 VRTComplexSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
-                            void *pData, int nBufXSize, int nBufYSize, 
-                            GDALDataType eBufType, 
+                            void *pData, int nBufXSize, int nBufYSize,
+                            GDALDataType eBufType,
                             GSpacing nPixelSpace,
                             GSpacing nLineSpace,
                             GDALRasterIOExtraArg* psExtraArgIn)
-    
+
 {
     GDALRasterIOExtraArg sExtraArg;
 
@@ -1865,15 +2083,15 @@ VRTComplexSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
     // The window we will actual set _within_ the pData buffer.
     int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
 
-    if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, 
+    if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize,
                           &dfReqXOff, &dfReqYOff, &dfReqXSize, &dfReqYSize,
                           &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
                           &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) )
         return CE_None;
 
-    if( osResampling.size() )
+    if( m_osResampling.size() )
     {
-        psExtraArg->eResampleAlg = GDALRasterIOGetResampleAlg(osResampling);
+        psExtraArg->eResampleAlg = GDALRasterIOGetResampleAlg(m_osResampling);
     }
     else if( psExtraArgIn != NULL )
     {
@@ -1916,39 +2134,40 @@ CPLErr VRTComplexSource::RasterIOInternal( int nReqXOff, int nReqYOff,
     float *pafData;
     CPLErr eErr;
     GDALColorTable* poColorTable = NULL;
-    int bIsComplex = GDALDataTypeIsComplex(eBufType);
-    GDALDataType eWrkDataType = (bIsComplex) ? GDT_CFloat32 : GDT_Float32;
-    int nWordSize = GDALGetDataTypeSize(eWrkDataType) / 8;
-    int bNoDataSetAndNotNan = bNoDataSet && !CPLIsNan(dfNoDataValue);
+    const int bIsComplex = GDALDataTypeIsComplex(eBufType);
+    const GDALDataType eWrkDataType = (bIsComplex) ? GDT_CFloat32 : GDT_Float32;
+    const int nWordSize = GDALGetDataTypeSize(eWrkDataType) / 8;
+    const int bNoDataSetIsNan = m_bNoDataSet && CPLIsNan(m_dfNoDataValue);
+    const int bNoDataSetAndNotNan = m_bNoDataSet && !CPLIsNan(m_dfNoDataValue);
 
-    if( eScalingType == VRT_SCALING_LINEAR && bNoDataSet == FALSE && dfScaleRatio == 0)
+    if( m_eScalingType == VRT_SCALING_LINEAR &&
+        m_bNoDataSet == FALSE && m_dfScaleRatio == 0)
     {
 /* -------------------------------------------------------------------- */
-/*      Optimization when outputing a constant value                    */
+/*      Optimization when writing a constant value                      */
 /*      (used by the -addalpha option of gdalbuildvrt)                  */
 /* -------------------------------------------------------------------- */
         pafData = NULL;
     }
     else
     {
-        pafData = (float *) VSIMalloc3(nOutXSize,nOutYSize,nWordSize);
+        pafData = (float *) VSI_MALLOC3_VERBOSE(nOutXSize,nOutYSize,nWordSize);
         if (pafData == NULL)
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
             return CE_Failure;
         }
 
         GDALRIOResampleAlg     eResampleAlgBack = psExtraArg->eResampleAlg;
-        if( osResampling.size() )
+        if( m_osResampling.size() )
         {
-            psExtraArg->eResampleAlg = GDALRasterIOGetResampleAlg(osResampling);
+            psExtraArg->eResampleAlg = GDALRasterIOGetResampleAlg(m_osResampling);
         }
 
-        eErr = poRasterBand->RasterIO( GF_Read, 
+        eErr = m_poRasterBand->RasterIO( GF_Read,
                                        nReqXOff, nReqYOff, nReqXSize, nReqYSize,
                                        pafData, nOutXSize, nOutYSize, eWrkDataType,
                                        nWordSize, nWordSize * (GSpacing)nOutXSize, psExtraArg );
-        if( osResampling.size() )
+        if( m_osResampling.size() )
             psExtraArg->eResampleAlg = eResampleAlgBack;
 
         if( eErr != CE_None )
@@ -1957,9 +2176,9 @@ CPLErr VRTComplexSource::RasterIOInternal( int nReqXOff, int nReqYOff,
             return eErr;
         }
 
-        if (nColorTableComponent != 0)
+        if (m_nColorTableComponent != 0)
         {
-            poColorTable = poRasterBand->GetColorTable();
+            poColorTable = m_poRasterBand->GetColorTable();
             if (poColorTable == NULL)
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
@@ -1989,23 +2208,23 @@ CPLErr VRTComplexSource::RasterIOInternal( int nReqXOff, int nReqYOff,
             if (pafData && !bIsComplex)
             {
                 float fResult = pafData[iX + iY * nOutXSize];
-                if( CPLIsNan(dfNoDataValue) && CPLIsNan(fResult) )
+                if( bNoDataSetIsNan && CPLIsNan(fResult) )
                     continue;
-                if( bNoDataSetAndNotNan && ARE_REAL_EQUAL(fResult, dfNoDataValue) )
+                if( bNoDataSetAndNotNan && ARE_REAL_EQUAL(fResult, m_dfNoDataValue) )
                     continue;
 
-                if (nColorTableComponent)
+                if (m_nColorTableComponent)
                 {
                     const GDALColorEntry* poEntry = poColorTable->GetColorEntry((int)fResult);
                     if (poEntry)
                     {
-                        if (nColorTableComponent == 1)
+                        if (m_nColorTableComponent == 1)
                             fResult = poEntry->c1;
-                        else if (nColorTableComponent == 2)
+                        else if (m_nColorTableComponent == 2)
                             fResult = poEntry->c2;
-                        else if (nColorTableComponent == 3)
+                        else if (m_nColorTableComponent == 3)
                             fResult = poEntry->c3;
-                        else if (nColorTableComponent == 4)
+                        else if (m_nColorTableComponent == 4)
                             fResult = poEntry->c4;
                     }
                     else
@@ -2021,22 +2240,22 @@ CPLErr VRTComplexSource::RasterIOInternal( int nReqXOff, int nReqYOff,
                     }
                 }
 
-                if( eScalingType == VRT_SCALING_LINEAR )
-                    fResult = (float) (fResult * dfScaleRatio + dfScaleOff);
-                else if( eScalingType == VRT_SCALING_EXPONENTIAL )
+                if( m_eScalingType == VRT_SCALING_LINEAR )
+                    fResult = (float) (fResult * m_dfScaleRatio + m_dfScaleOff);
+                else if( m_eScalingType == VRT_SCALING_EXPONENTIAL )
                 {
-                    if( !bSrcMinMaxDefined )
+                    if( !m_bSrcMinMaxDefined )
                     {
                         int bSuccessMin = FALSE, bSuccessMax = FALSE;
                         double adfMinMax[2];
-                        adfMinMax[0] = poRasterBand->GetMinimum(&bSuccessMin);
-                        adfMinMax[1] = poRasterBand->GetMaximum(&bSuccessMax);
+                        adfMinMax[0] = m_poRasterBand->GetMinimum(&bSuccessMin);
+                        adfMinMax[1] = m_poRasterBand->GetMaximum(&bSuccessMax);
                         if( (bSuccessMin && bSuccessMax) ||
-                            poRasterBand->ComputeRasterMinMax( TRUE, adfMinMax ) == CE_None )
+                            m_poRasterBand->ComputeRasterMinMax( TRUE, adfMinMax ) == CE_None )
                         {
-                            dfSrcMin = adfMinMax[0];
-                            dfSrcMax = adfMinMax[1];
-                            bSrcMinMaxDefined = TRUE;
+                            m_dfSrcMin = adfMinMax[0];
+                            m_dfSrcMax = adfMinMax[1];
+                            m_bSrcMinMaxDefined = TRUE;
                         }
                         else
                         {
@@ -2047,16 +2266,19 @@ CPLErr VRTComplexSource::RasterIOInternal( int nReqXOff, int nReqYOff,
                     }
 
                     double dfPowVal =
-                        (fResult - dfSrcMin) / (dfSrcMax - dfSrcMin);
+                        (fResult - m_dfSrcMin) / (m_dfSrcMax - m_dfSrcMin);
                     if( dfPowVal < 0.0 )
                         dfPowVal = 0.0;
                     else if( dfPowVal > 1.0 )
                         dfPowVal = 1.0;
-                    fResult = (float) (dfDstMax - dfDstMin) * pow( dfPowVal, dfExponent ) + dfDstMin;
+                    fResult = static_cast<float>((m_dfDstMax - m_dfDstMin) * pow( dfPowVal, m_dfExponent ) + m_dfDstMin);
                 }
 
-                if (nLUTItemCount)
-                    fResult = (float) LookupValue( fResult );
+                if (m_nLUTItemCount)
+                    fResult = static_cast<float>(LookupValue( fResult ));
+
+                if( m_nMaxValue != 0 && fResult > m_nMaxValue )
+                    fResult = static_cast<float>(m_nMaxValue);
 
                 if( eBufType == GDT_Byte )
                     *pDstLocation = (GByte) MIN(255,MAX(0,fResult + 0.5));
@@ -2072,10 +2294,10 @@ CPLErr VRTComplexSource::RasterIOInternal( int nReqXOff, int nReqYOff,
 
                 /* Do not use color table */
 
-                if( eScalingType == VRT_SCALING_LINEAR )
+                if( m_eScalingType == VRT_SCALING_LINEAR )
                 {
-                    afResult[0] = (float) (afResult[0] * dfScaleRatio + dfScaleOff);
-                    afResult[1] = (float) (afResult[1] * dfScaleRatio + dfScaleOff);
+                    afResult[0] = (float) (afResult[0] * m_dfScaleRatio + m_dfScaleOff);
+                    afResult[1] = (float) (afResult[1] * m_dfScaleRatio + m_dfScaleOff);
                 }
 
                 /* Do not use LUT */
@@ -2088,10 +2310,13 @@ CPLErr VRTComplexSource::RasterIOInternal( int nReqXOff, int nReqYOff,
             }
             else
             {
-                float fResult = (float) dfScaleOff;
+                float fResult = static_cast<float>(m_dfScaleOff);
+
+                if (m_nLUTItemCount)
+                    fResult = static_cast<float>(LookupValue( fResult ));
 
-                if (nLUTItemCount)
-                    fResult = (float) LookupValue( fResult );
+                if( m_nMaxValue != 0 && fResult > m_nMaxValue )
+                    fResult = static_cast<float>(m_nMaxValue);
 
                 if( eBufType == GDT_Byte )
                     *pDstLocation = (GByte) MIN(255,MAX(0,fResult + 0.5));
@@ -2114,8 +2339,8 @@ CPLErr VRTComplexSource::RasterIOInternal( int nReqXOff, int nReqYOff,
 
 double VRTComplexSource::GetMinimum( int nXSize, int nYSize, int *pbSuccess )
 {
-    if (dfScaleOff == 0.0 && dfScaleRatio == 1.0 &&
-        nLUTItemCount == 0 && nColorTableComponent == 0)
+    if (m_dfScaleOff == 0.0 && m_dfScaleRatio == 1.0 &&
+        m_nLUTItemCount == 0 && m_nColorTableComponent == 0)
     {
         return VRTSimpleSource::GetMinimum(nXSize, nYSize, pbSuccess);
     }
@@ -2130,8 +2355,8 @@ double VRTComplexSource::GetMinimum( int nXSize, int nYSize, int *pbSuccess )
 
 double VRTComplexSource::GetMaximum( int nXSize, int nYSize, int *pbSuccess )
 {
-    if (dfScaleOff == 0.0 && dfScaleRatio == 1.0 &&
-        nLUTItemCount == 0 && nColorTableComponent == 0)
+    if (m_dfScaleOff == 0.0 && m_dfScaleRatio == 1.0 &&
+        m_nLUTItemCount == 0 && m_nColorTableComponent == 0)
     {
         return VRTSimpleSource::GetMaximum(nXSize, nYSize, pbSuccess);
     }
@@ -2146,8 +2371,8 @@ double VRTComplexSource::GetMaximum( int nXSize, int nYSize, int *pbSuccess )
 
 CPLErr VRTComplexSource::ComputeRasterMinMax( int nXSize, int nYSize, int bApproxOK, double* adfMinMax )
 {
-    if (dfScaleOff == 0.0 && dfScaleRatio == 1.0 &&
-        nLUTItemCount == 0 && nColorTableComponent == 0)
+    if (m_dfScaleOff == 0.0 && m_dfScaleRatio == 1.0 &&
+        m_nLUTItemCount == 0 && m_nColorTableComponent == 0)
     {
         return VRTSimpleSource::ComputeRasterMinMax(nXSize, nYSize, bApproxOK, adfMinMax);
     }
@@ -2165,8 +2390,8 @@ CPLErr VRTComplexSource::GetHistogram( int nXSize, int nYSize,
                                   int bIncludeOutOfRange, int bApproxOK,
                                   GDALProgressFunc pfnProgress, void *pProgressData )
 {
-    if (dfScaleOff == 0.0 && dfScaleRatio == 1.0 &&
-        nLUTItemCount == 0 && nColorTableComponent == 0)
+    if (m_dfScaleOff == 0.0 && m_dfScaleRatio == 1.0 &&
+        m_nLUTItemCount == 0 && m_nColorTableComponent == 0)
     {
         return VRTSimpleSource::GetHistogram(nXSize, nYSize,
                                              dfMin, dfMax, nBuckets,
@@ -2183,13 +2408,13 @@ CPLErr VRTComplexSource::GetHistogram( int nXSize, int nYSize,
 /************************************************************************/
 
 CPLErr VRTComplexSource::ComputeStatistics( int nXSize, int nYSize,
-                                      int bApproxOK, 
-                                      double *pdfMin, double *pdfMax, 
+                                      int bApproxOK,
+                                      double *pdfMin, double *pdfMax,
                                       double *pdfMean, double *pdfStdDev,
                                       GDALProgressFunc pfnProgress, void *pProgressData )
 {
-    if (dfScaleOff == 0.0 && dfScaleRatio == 1.0 &&
-        nLUTItemCount == 0 && nColorTableComponent == 0)
+    if (m_dfScaleOff == 0.0 && m_dfScaleRatio == 1.0 &&
+        m_nLUTItemCount == 0 && m_nColorTableComponent == 0)
     {
         return VRTSimpleSource::ComputeStatistics(nXSize, nYSize, bApproxOK, pdfMin, pdfMax,
                                            pdfMean, pdfStdDev,
@@ -2351,10 +2576,9 @@ VRTSource *VRTParseCoreSources( CPLXMLNode *psChild, const char *pszVRTPath )
 {
     VRTSource * poSource;
 
-    if( EQUAL(psChild->pszValue,"AveragedSource") 
+    if( EQUAL(psChild->pszValue,"AveragedSource")
         || (EQUAL(psChild->pszValue,"SimpleSource")
-            && EQUALN(CPLGetXMLValue(psChild, "Resampling", "Nearest"),
-                      "Aver",4)) )
+            && STARTS_WITH_CI(CPLGetXMLValue(psChild, "Resampling", "Nearest"), "Aver")) )
     {
         poSource = new VRTAveragedSource();
     }
@@ -2368,7 +2592,7 @@ VRTSource *VRTParseCoreSources( CPLXMLNode *psChild, const char *pszVRTPath )
     }
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "VRTParseCoreSources() - Unknown source : %s", psChild->pszValue );
         return NULL;
     }
diff --git a/frmts/vrt/vrtwarped.cpp b/frmts/vrt/vrtwarped.cpp
index 86f050f..ea3b218 100644
--- a/frmts/vrt/vrtwarped.cpp
+++ b/frmts/vrt/vrtwarped.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtwarped.cpp 29769 2015-08-24 09:09:27Z rouault $
+ * $Id: vrtwarped.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTWarpedRasterBand *and VRTWarpedDataset.
@@ -31,11 +31,14 @@
 #include "vrtdataset.h"
 #include "cpl_minixml.h"
 #include "cpl_string.h"
-#include "gdalwarper.h"
 #include "gdal_alg_priv.h"
+#include "gdalwarper.h"
+
 #include <cassert>
 
-CPL_CVSID("$Id: vrtwarped.cpp 29769 2015-08-24 09:09:27Z rouault $");
+#include <algorithm>
+
+CPL_CVSID("$Id: vrtwarped.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /*                      GDALAutoCreateWarpedVRT()                       */
@@ -44,38 +47,38 @@ CPL_CVSID("$Id: vrtwarped.cpp 29769 2015-08-24 09:09:27Z rouault $");
 /**
  * Create virtual warped dataset automatically.
  *
- * This function will create a warped virtual file representing the 
+ * This function will create a warped virtual file representing the
  * input image warped into the target coordinate system.  A GenImgProj
  * transformation is created to accomplish any required GCP/Geotransform
  * warp and reprojection to the target coordinate system.  The output virtual
  * dataset will be "northup" in the target coordinate system.   The
  * GDALSuggestedWarpOutput() function is used to determine the bounds and
- * resolution of the output virtual file which should be large enough to 
- * include all the input image 
+ * resolution of the output virtual file which should be large enough to
+ * include all the input image
  *
- * Note that the constructed GDALDatasetH will acquire one or more references 
- * to the passed in hSrcDS.  Reference counting semantics on the source 
- * dataset should be honoured.  That is, don't just GDALClose() it unless it 
- * was opened with GDALOpenShared(). 
+ * Note that the constructed GDALDatasetH will acquire one or more references
+ * to the passed in hSrcDS.  Reference counting semantics on the source
+ * dataset should be honoured.  That is, don't just GDALClose() it unless it
+ * was opened with GDALOpenShared().
  *
  * The returned dataset will have no associated filename for itself.  If you
  * want to write the virtual dataset description to a file, use the
  * GDALSetDescription() function (or SetDescription() method) on the dataset
- * to assign a filename before it is closed.  
+ * to assign a filename before it is closed.
  *
- * @param hSrcDS The source dataset. 
+ * @param hSrcDS The source dataset.
  *
- * @param pszSrcWKT The coordinate system of the source image.  If NULL, it 
- * will be read from the source image. 
+ * @param pszSrcWKT The coordinate system of the source image.  If NULL, it
+ * will be read from the source image.
  *
- * @param pszDstWKT The coordinate system to convert to.  If NULL no change 
- * of coordinate system will take place.  
+ * @param pszDstWKT The coordinate system to convert to.  If NULL no change
+ * of coordinate system will take place.
  *
- * @param eResampleAlg One of GRA_NearestNeighbour, GRA_Bilinear, GRA_Cubic,  
- * GRA_CubicSpline, GRA_Lanczos, GRA_Average or GRA_Mode.  
+ * @param eResampleAlg One of GRA_NearestNeighbour, GRA_Bilinear, GRA_Cubic,
+ * GRA_CubicSpline, GRA_Lanczos, GRA_Average or GRA_Mode.
  * Controls the sampling method used.
  *
- * @param dfMaxError Maximum error measured in input pixels that is allowed in 
+ * @param dfMaxError Maximum error measured in input pixels that is allowed in
  * approximating the transformation (0.0 for exact calculations).
  *
  * @param psOptionsIn Additional warp options, normally NULL.
@@ -83,23 +86,21 @@ CPL_CVSID("$Id: vrtwarped.cpp 29769 2015-08-24 09:09:27Z rouault $");
  * @return NULL on failure, or a new virtual dataset handle on success.
  */
 
-GDALDatasetH CPL_STDCALL 
-GDALAutoCreateWarpedVRT( GDALDatasetH hSrcDS, 
+GDALDatasetH CPL_STDCALL
+GDALAutoCreateWarpedVRT( GDALDatasetH hSrcDS,
                          const char *pszSrcWKT,
                          const char *pszDstWKT,
-                         GDALResampleAlg eResampleAlg, 
-                         double dfMaxError, 
+                         GDALResampleAlg eResampleAlg,
+                         double dfMaxError,
                          const GDALWarpOptions *psOptionsIn )
-    
-{
-    GDALWarpOptions *psWO;
-    int i;
 
+{
     VALIDATE_POINTER1( hSrcDS, "GDALAutoCreateWarpedVRT", NULL );
 
 /* -------------------------------------------------------------------- */
 /*      Populate the warp options.                                      */
 /* -------------------------------------------------------------------- */
+    GDALWarpOptions *psWO;
     if( psOptionsIn != NULL )
         psWO = GDALCloneWarpOptions( psOptionsIn );
     else
@@ -110,10 +111,12 @@ GDALAutoCreateWarpedVRT( GDALDatasetH hSrcDS,
     psWO->hSrcDS = hSrcDS;
 
     psWO->nBandCount = GDALGetRasterCount( hSrcDS );
-    psWO->panSrcBands = (int *) CPLMalloc(sizeof(int) * psWO->nBandCount);
-    psWO->panDstBands = (int *) CPLMalloc(sizeof(int) * psWO->nBandCount);
+    psWO->panSrcBands = reinterpret_cast<int *>(
+        CPLMalloc( sizeof(int) * psWO->nBandCount ) );
+    psWO->panDstBands = reinterpret_cast<int *>(
+        CPLMalloc( sizeof(int) * psWO->nBandCount ) );
 
-    for( i = 0; i < psWO->nBandCount; i++ )
+    for( int i = 0; i < psWO->nBandCount; i++ )
     {
         psWO->panSrcBands[i] = i+1;
         psWO->panDstBands[i] = i+1;
@@ -125,8 +128,8 @@ GDALAutoCreateWarpedVRT( GDALDatasetH hSrcDS,
 /*      Create the transformer.                                         */
 /* -------------------------------------------------------------------- */
     psWO->pfnTransformer = GDALGenImgProjTransform;
-    psWO->pTransformerArg = 
-        GDALCreateGenImgProjTransformer( psWO->hSrcDS, pszSrcWKT, 
+    psWO->pTransformerArg =
+        GDALCreateGenImgProjTransformer( psWO->hSrcDS, pszSrcWKT,
                                          NULL, pszDstWKT,
                                          TRUE, 1.0, 0 );
 
@@ -141,11 +144,9 @@ GDALAutoCreateWarpedVRT( GDALDatasetH hSrcDS,
 /* -------------------------------------------------------------------- */
     double adfDstGeoTransform[6];
     int    nDstPixels, nDstLines;
-    CPLErr eErr;
-
-    eErr = 
-        GDALSuggestedWarpOutput( hSrcDS, psWO->pfnTransformer, 
-                                 psWO->pTransformerArg, 
+    CPLErr eErr =
+        GDALSuggestedWarpOutput( hSrcDS, psWO->pfnTransformer,
+                                 psWO->pTransformerArg,
                                  adfDstGeoTransform, &nDstPixels, &nDstLines );
     if( eErr != CE_None )
     {
@@ -159,7 +160,7 @@ GDALAutoCreateWarpedVRT( GDALDatasetH hSrcDS,
 /*      back to pixel/line coordinates.                                 */
 /*                                                                      */
 /* -------------------------------------------------------------------- */
-    GDALSetGenImgProjTransformerDstGeoTransform( 
+    GDALSetGenImgProjTransformerDstGeoTransform(
         psWO->pTransformerArg, adfDstGeoTransform );
 
 /* -------------------------------------------------------------------- */
@@ -167,9 +168,9 @@ GDALAutoCreateWarpedVRT( GDALDatasetH hSrcDS,
 /* -------------------------------------------------------------------- */
     if( dfMaxError > 0.0 )
     {
-        psWO->pTransformerArg = 
-            GDALCreateApproxTransformer( psWO->pfnTransformer, 
-                                         psWO->pTransformerArg, 
+        psWO->pTransformerArg =
+            GDALCreateApproxTransformer( psWO->pfnTransformer,
+                                         psWO->pTransformerArg,
                                          dfMaxError );
         psWO->pfnTransformer = GDALApproxTransform;
         GDALApproxTransformerOwnsSubtransformer(psWO->pTransformerArg, TRUE);
@@ -178,10 +179,9 @@ GDALAutoCreateWarpedVRT( GDALDatasetH hSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Create the VRT file.                                            */
 /* -------------------------------------------------------------------- */
-    GDALDatasetH hDstDS;
-
-    hDstDS = GDALCreateWarpedVRT( hSrcDS, nDstPixels, nDstLines, 
-                                  adfDstGeoTransform, psWO );
+    GDALDatasetH hDstDS
+        = GDALCreateWarpedVRT( hSrcDS, nDstPixels, nDstLines,
+                               adfDstGeoTransform, psWO );
 
     GDALDestroyWarpOptions( psWO );
 
@@ -191,9 +191,9 @@ GDALAutoCreateWarpedVRT( GDALDatasetH hSrcDS,
         GDALSetProjection( hDstDS, pszSrcWKT );
     else if( GDALGetGCPCount( hSrcDS ) > 0 )
         GDALSetProjection( hDstDS, GDALGetGCPProjection( hSrcDS ) );
-    else 
+    else
         GDALSetProjection( hDstDS, GDALGetProjectionRef( hSrcDS ) );
-    
+
     return hDstDS;
 }
 
@@ -204,16 +204,16 @@ GDALAutoCreateWarpedVRT( GDALDatasetH hSrcDS,
 /**
  * Create virtual warped dataset.
  *
- * This function will create a warped virtual file representing the 
+ * This function will create a warped virtual file representing the
  * input image warped based on a provided transformation.  Output bounds
  * and resolution are provided explicitly.
  *
- * Note that the constructed GDALDatasetH will acquire one or more references 
- * to the passed in hSrcDS.  Reference counting semantics on the source 
- * dataset should be honoured.  That is, don't just GDALClose() it unless it 
- * was opened with GDALOpenShared(). 
+ * Note that the constructed GDALDatasetH will acquire one or more references
+ * to the passed in hSrcDS.  Reference counting semantics on the source
+ * dataset should be honoured.  That is, don't just GDALClose() it unless it
+ * was opened with GDALOpenShared().
  *
- * @param hSrcDS The source dataset. 
+ * @param hSrcDS The source dataset.
  *
  * @param nPixels Width of the virtual warped dataset to create
  *
@@ -227,10 +227,10 @@ GDALAutoCreateWarpedVRT( GDALDatasetH hSrcDS,
  */
 
 GDALDatasetH CPL_STDCALL
-GDALCreateWarpedVRT( GDALDatasetH hSrcDS, 
+GDALCreateWarpedVRT( GDALDatasetH hSrcDS,
                      int nPixels, int nLines, double *padfGeoTransform,
                      GDALWarpOptions *psOptions )
-    
+
 {
     VALIDATE_POINTER1( hSrcDS, "GDALCreateWarpedVRT", NULL );
 
@@ -238,27 +238,27 @@ GDALCreateWarpedVRT( GDALDatasetH hSrcDS,
 /*      Create the VRTDataset and populate it with bands.               */
 /* -------------------------------------------------------------------- */
     VRTWarpedDataset *poDS = new VRTWarpedDataset( nPixels, nLines );
-    int i;
 
     psOptions->hDstDS = (GDALDatasetH) poDS;
 
     poDS->SetGeoTransform( padfGeoTransform );
 
-    for( i = 0; i < psOptions->nBandCount; i++ )
+    for( int i = 0; i < psOptions->nBandCount; i++ )
     {
-        VRTWarpedRasterBand *poBand;
-        GDALRasterBand *poSrcBand = (GDALRasterBand *) 
-            GDALGetRasterBand( hSrcDS, i+1 );
+        GDALRasterBand *poSrcBand = reinterpret_cast<GDALRasterBand *>(
+            GDALGetRasterBand( hSrcDS, i+1 ) );
 
         poDS->AddBand( poSrcBand->GetRasterDataType(), NULL );
 
-        poBand = (VRTWarpedRasterBand *) poDS->GetRasterBand( i+1 );
+        VRTWarpedRasterBand *poBand = reinterpret_cast<VRTWarpedRasterBand *>(
+            poDS->GetRasterBand( i+1 ) );
         poBand->CopyCommonInfoFrom( poSrcBand );
     }
 
     if( psOptions->nDstAlphaBand == psOptions->nBandCount + 1 )
     {
-        GDALRasterBand *poSrcBand = (GDALRasterBand*)GDALGetRasterBand( hSrcDS, 1);
+        GDALRasterBand *poSrcBand = reinterpret_cast<GDALRasterBand *>(
+            GDALGetRasterBand( hSrcDS, 1) );
         poDS->AddBand( poSrcBand->GetRasterDataType(), NULL );
     }
 
@@ -272,8 +272,8 @@ GDALCreateWarpedVRT( GDALDatasetH hSrcDS,
          delete poDS;
          return NULL;
     }
-    
-    return (GDALDatasetH) poDS;
+
+    return reinterpret_cast<GDALDatasetH>( poDS );
 }
 
 /************************************************************************/
@@ -286,18 +286,17 @@ GDALCreateWarpedVRT( GDALDatasetH hSrcDS,
 /*                          VRTWarpedDataset()                          */
 /************************************************************************/
 
-VRTWarpedDataset::VRTWarpedDataset( int nXSize, int nYSize )
-        : VRTDataset( nXSize, nYSize )
-
+VRTWarpedDataset::VRTWarpedDataset( int nXSize, int nYSize ) :
+    VRTDataset( nXSize, nYSize ),
+    m_nBlockXSize(std::min( nXSize, 512 )),
+    m_nBlockYSize(std::min( nYSize, 128 )),
+    m_poWarper(NULL),
+    m_nOverviewCount(0),
+    m_papoOverviews(NULL),
+    m_nSrcOvrLevel(-2)
 {
-    poWarper = NULL;
-    nBlockXSize = MIN(nXSize, 512);
-    nBlockYSize = MIN(nYSize, 128);
     eAccess = GA_Update;
-
-    nOverviewCount = 0;
-    papoOverviews = NULL;
-    nSrcOvrLevel = -2;
+    DisableReadWriteMutex();
 }
 
 /************************************************************************/
@@ -323,11 +322,10 @@ int VRTWarpedDataset::CloseDependentDatasets()
 /* -------------------------------------------------------------------- */
 /*      Cleanup overviews.                                              */
 /* -------------------------------------------------------------------- */
-    int iOverview;
-
-    for( iOverview = 0; iOverview < nOverviewCount; iOverview++ )
+    for( int iOverview = 0; iOverview < m_nOverviewCount; iOverview++ )
     {
-        GDALDatasetH hDS = (GDALDatasetH) papoOverviews[iOverview];
+        GDALDatasetH hDS
+            = reinterpret_cast<GDALDatasetH>( m_papoOverviews[iOverview] );
 
         if( GDALDereferenceDataset( hDS ) < 1 )
         {
@@ -337,16 +335,16 @@ int VRTWarpedDataset::CloseDependentDatasets()
         }
     }
 
-    CPLFree( papoOverviews );
-    nOverviewCount = 0;
-    papoOverviews = NULL;
+    CPLFree( m_papoOverviews );
+    m_nOverviewCount = 0;
+    m_papoOverviews = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Cleanup warper if one is in effect.                             */
 /* -------------------------------------------------------------------- */
-    if( poWarper != NULL )
+    if( m_poWarper != NULL )
     {
-        const GDALWarpOptions *psWO = poWarper->GetOptions();
+        const GDALWarpOptions *psWO = m_poWarper->GetOptions();
 
 /* -------------------------------------------------------------------- */
 /*      We take care to only call GDALClose() on psWO->hSrcDS if the    */
@@ -362,18 +360,18 @@ int VRTWarpedDataset::CloseDependentDatasets()
             {
                 GDALReferenceDataset( psWO->hSrcDS );
                 GDALClose( psWO->hSrcDS );
-                bHasDroppedRef = TRUE;
+                bHasDroppedRef = true;
             }
         }
 
 /* -------------------------------------------------------------------- */
-/*      We are responsible for cleaning up the transformer outselves.   */
+/*      We are responsible for cleaning up the transformer ourselves.   */
 /* -------------------------------------------------------------------- */
         if( psWO != NULL && psWO->pTransformerArg != NULL )
             GDALDestroyTransformer( psWO->pTransformerArg );
 
-        delete poWarper;
-        poWarper = NULL;
+        delete m_poWarper;
+        m_poWarper = NULL;
     }
 
 /* -------------------------------------------------------------------- */
@@ -399,16 +397,16 @@ CPLErr VRTWarpedDataset::SetMetadataItem( const char *pszName, const char *pszVa
 
     if( (pszDomain == NULL || EQUAL(pszDomain, "")) && EQUAL(pszName, "SrcOvrLevel") )
     {
-        int nOldValue = nSrcOvrLevel;
-        if( EQUAL(pszValue, "AUTO") )
-            nSrcOvrLevel = -2;
-        else if( EQUALN(pszValue,"AUTO-",5) )
-            nSrcOvrLevel = -2-atoi(pszValue + 5);
+        const int nOldValue = m_nSrcOvrLevel;
+        if( pszValue == NULL || EQUAL(pszValue, "AUTO") )
+            m_nSrcOvrLevel = -2;
+        else if( STARTS_WITH_CI(pszValue, "AUTO-") )
+            m_nSrcOvrLevel = -2-atoi(pszValue + 5);
         else if( EQUAL(pszValue, "NONE") )
-            nSrcOvrLevel = -1;
+            m_nSrcOvrLevel = -1;
         else if( CPLGetValueType(pszValue) == CPL_VALUE_INTEGER )
-            nSrcOvrLevel = atoi(pszValue); 
-        if( nSrcOvrLevel != nOldValue )
+            m_nSrcOvrLevel = atoi(pszValue);
+        if( m_nSrcOvrLevel != nOldValue )
             SetNeedsFlush();
         return CE_None;
     }
@@ -424,12 +422,13 @@ CPLErr VRTWarpedDataset::SetMetadataItem( const char *pszName, const char *pszVa
 CPLErr VRTWarpedDataset::Initialize( void *psWO )
 
 {
-    if( poWarper != NULL )
-        delete poWarper;
+    if( m_poWarper != NULL )
+        delete m_poWarper;
 
-    poWarper = new GDALWarpOperation();
+    m_poWarper = new GDALWarpOperation();
 
-    GDALWarpOptions* psWO_Dup = GDALCloneWarpOptions((GDALWarpOptions *) psWO);
+    GDALWarpOptions* psWO_Dup
+        = GDALCloneWarpOptions(reinterpret_cast<GDALWarpOptions *>( psWO ) );
 
     /* Avoid errors when adding an alpha band, but source dataset has */
     /* no alpha band (#4571) */
@@ -440,10 +439,10 @@ CPLErr VRTWarpedDataset::Initialize( void *psWO )
     // will result in our assuming ownership of a reference to the
     // hSrcDS.
 
-    if( ((GDALWarpOptions *) psWO)->hSrcDS != NULL )
+    if( reinterpret_cast<GDALWarpOptions *>( psWO )->hSrcDS != NULL )
         GDALReferenceDataset( psWO_Dup->hSrcDS );
 
-    CPLErr eErr = poWarper->Initialize( psWO_Dup );
+    CPLErr eErr = m_poWarper->Initialize( psWO_Dup );
 
     GDALDestroyWarpOptions(psWO_Dup);
 
@@ -459,60 +458,66 @@ CPLErr VRTWarpedDataset::Initialize( void *psWO )
 
 void VRTWarpedDataset::CreateImplicitOverviews()
 {
-    if( poWarper == NULL || nOverviewCount != 0 )
+    if( m_poWarper == NULL || m_nOverviewCount != 0 )
         return;
 
-    const GDALWarpOptions *psWO = poWarper->GetOptions();
+    const GDALWarpOptions *psWO = m_poWarper->GetOptions();
 
     if( psWO->hSrcDS == NULL || GDALGetRasterCount(psWO->hSrcDS) == 0 )
         return;
 
-    GDALDataset* poSrcDS = (GDALDataset*)psWO->hSrcDS;
-    int nOvrCount = poSrcDS->GetRasterBand(1)->GetOverviewCount();
+    GDALDataset* poSrcDS = reinterpret_cast<GDALDataset *>( psWO->hSrcDS );
+    const int nOvrCount = poSrcDS->GetRasterBand(1)->GetOverviewCount();
     for(int iOvr = 0; iOvr < nOvrCount; iOvr++)
     {
-        int bDeleteSrcOvrDataset = FALSE;
+        bool bDeleteSrcOvrDataset = false;
         GDALDataset* poSrcOvrDS = poSrcDS;
-        if( nSrcOvrLevel < -2 )
+        if( m_nSrcOvrLevel < -2 )
         {
-            if( iOvr + nSrcOvrLevel + 2 >= 0 )
+            if( iOvr + m_nSrcOvrLevel + 2 >= 0 )
             {
-                bDeleteSrcOvrDataset = TRUE;
+                bDeleteSrcOvrDataset = true;
                 poSrcOvrDS = GDALCreateOverviewDataset(poSrcDS,
-                                               iOvr + nSrcOvrLevel + 2, FALSE, FALSE);
+                                               iOvr + m_nSrcOvrLevel + 2, FALSE, FALSE);
             }
         }
-        else if( nSrcOvrLevel == -2 )
+        else if( m_nSrcOvrLevel == -2 )
         {
-            bDeleteSrcOvrDataset = TRUE;
+            bDeleteSrcOvrDataset = true;
             poSrcOvrDS = GDALCreateOverviewDataset(poSrcDS, iOvr, FALSE, FALSE);
         }
-        else if( nSrcOvrLevel >= 0 )
+        else if( m_nSrcOvrLevel >= 0 )
         {
-            bDeleteSrcOvrDataset = TRUE;
-            poSrcOvrDS = GDALCreateOverviewDataset(poSrcDS, nSrcOvrLevel, TRUE, FALSE);
+            bDeleteSrcOvrDataset = true;
+            poSrcOvrDS = GDALCreateOverviewDataset(poSrcDS, m_nSrcOvrLevel, TRUE, FALSE);
         }
         if( poSrcOvrDS == NULL )
             break;
 
-        double dfSrcRatioX = (double)poSrcDS->GetRasterXSize() / poSrcOvrDS->GetRasterXSize();
-        double dfSrcRatioY = (double)poSrcDS->GetRasterYSize() / poSrcOvrDS->GetRasterYSize();
-        double dfTargetRatio = (double)poSrcDS->GetRasterXSize() /
+        const double dfSrcRatioX = static_cast<double>(
+            poSrcDS->GetRasterXSize() ) / poSrcOvrDS->GetRasterXSize();
+        const double dfSrcRatioY = static_cast<double>(
+            poSrcDS->GetRasterYSize() ) / poSrcOvrDS->GetRasterYSize();
+        const double dfTargetRatio = static_cast<double>(
+            poSrcDS->GetRasterXSize() ) /
             poSrcDS->GetRasterBand(1)->GetOverview(iOvr)->GetXSize();
-                
+
 /* -------------------------------------------------------------------- */
 /*      Figure out the desired output bounds and resolution.            */
 /* -------------------------------------------------------------------- */
+        const int nDstPixels
+            = static_cast<int>(nRasterXSize / dfTargetRatio + 0.5);
+        const int nDstLines
+            = static_cast<int>(nRasterYSize / dfTargetRatio + 0.5);
+
         double adfDstGeoTransform[6];
-        int    nDstPixels, nDstLines;
-        
-        nDstPixels = (int)(nRasterXSize / dfTargetRatio + 0.5);
-        nDstLines = (int)(nRasterYSize / dfTargetRatio + 0.5);
         GetGeoTransform(adfDstGeoTransform);
         if( adfDstGeoTransform[2] == 0.0 && adfDstGeoTransform[4] == 0.0 )
         {
-            adfDstGeoTransform[1] *= (double)nRasterXSize / nDstPixels;
-            adfDstGeoTransform[5] *= (double)nRasterYSize / nDstLines;
+            adfDstGeoTransform[1]
+                *= static_cast<double>( nRasterXSize ) / nDstPixels;
+            adfDstGeoTransform[5]
+                *= static_cast<double>( nRasterYSize ) / nDstLines;
         }
         else
         {
@@ -521,14 +526,14 @@ void VRTWarpedDataset::CreateImplicitOverviews()
             adfDstGeoTransform[4] *= dfTargetRatio;
             adfDstGeoTransform[5] *= dfTargetRatio;
         }
-        
+
         if( nDstPixels < 1 || nDstLines < 1 )
         {
             if( bDeleteSrcOvrDataset )
                 delete poSrcOvrDS;
             break;
         }
-                
+
 /* -------------------------------------------------------------------- */
 /*      Create transformer and warping options.                         */
 /* -------------------------------------------------------------------- */
@@ -552,39 +557,40 @@ void VRTWarpedDataset::CreateImplicitOverviews()
 /*      back to pixel/line coordinates.                                 */
 /*                                                                      */
 /* -------------------------------------------------------------------- */
-        GDALSetTransformerDstGeoTransform( 
+        GDALSetTransformerDstGeoTransform(
             psWOOvr->pTransformerArg, adfDstGeoTransform );
 
 /* -------------------------------------------------------------------- */
 /*      Create the VRT file.                                            */
 /* -------------------------------------------------------------------- */
-        GDALDatasetH hDstDS;
+        GDALDatasetH hDstDS = GDALCreateWarpedVRT(
+            reinterpret_cast<GDALDatasetH>( poSrcOvrDS ),
+            nDstPixels, nDstLines,
+            adfDstGeoTransform, psWOOvr );
 
-        hDstDS = GDALCreateWarpedVRT( (GDALDatasetH)poSrcOvrDS,
-                                      nDstPixels, nDstLines, 
-                                      adfDstGeoTransform, psWOOvr );
-        
         if( bDeleteSrcOvrDataset )
         {
             if( hDstDS == NULL )
                 delete poSrcOvrDS;
             else
-                GDALDereferenceDataset( (GDALDatasetH)poSrcOvrDS );
+                GDALDereferenceDataset(
+                    reinterpret_cast<GDALDatasetH>( poSrcOvrDS ) );
         }
-        
+
         GDALDestroyWarpOptions(psWOOvr);
-        
+
         if( hDstDS == NULL )
         {
             GDALDestroyTransformer( pTransformerArg );
             break;
         }
-        
-        nOverviewCount++;
-        papoOverviews = (VRTWarpedDataset **)
-            CPLRealloc( papoOverviews, sizeof(void*) * nOverviewCount );
 
-        papoOverviews[nOverviewCount-1] = (VRTWarpedDataset*)hDstDS;
+        m_nOverviewCount++;
+        m_papoOverviews = reinterpret_cast<VRTWarpedDataset **>(
+            CPLRealloc( m_papoOverviews, sizeof(void*) * m_nOverviewCount ) );
+
+        m_papoOverviews[m_nOverviewCount-1]
+            = reinterpret_cast<VRTWarpedDataset *>( hDstDS );
     }
 }
 
@@ -595,15 +601,15 @@ void VRTWarpedDataset::CreateImplicitOverviews()
 char** VRTWarpedDataset::GetFileList()
 {
     char** papszFileList = GDALDataset::GetFileList();
-    
-    if( poWarper != NULL )
+
+    if( m_poWarper != NULL )
     {
-        const GDALWarpOptions *psWO = poWarper->GetOptions();
+        const GDALWarpOptions *psWO = m_poWarper->GetOptions();
         const char* pszFilename;
-        
+
         if( psWO->hSrcDS != NULL &&
             (pszFilename =
-                    ((GDALDataset*)psWO->hSrcDS)->GetDescription()) != NULL )
+             reinterpret_cast<GDALDataset*>(psWO->hSrcDS)->GetDescription()) != NULL )
         {
             VSIStatBufL  sStat;
             if( VSIStatL( pszFilename, &sStat ) == 0 )
@@ -612,7 +618,7 @@ char** VRTWarpedDataset::GetFileList()
             }
         }
     }
-    
+
     return papszFileList;
 }
 
@@ -649,8 +655,8 @@ int VRTWarpedOverviewTransform( void *pTransformArg, int bDstToSrc,
                                 int nPointCount,
                                 double *padfX, double *padfY, double *padfZ,
                                 int *panSuccess );
-                                
-#if 0
+
+#if 0  // TODO: Why?
 /************************************************************************/
 /*                VRTSerializeWarpedOverviewTransformer()               */
 /************************************************************************/
@@ -659,10 +665,10 @@ static CPLXMLNode *
 VRTSerializeWarpedOverviewTransformer( void *pTransformArg )
 
 {
-    CPLXMLNode *psTree;
-    VWOTInfo *psInfo = (VWOTInfo *) pTransformArg;
+    VWOTInfo *psInfo = reinterpret_cast<VWOTInfo *>( pTransformArg );
 
-    psTree = CPLCreateXMLNode( NULL, CXT_Element, "WarpedOverviewTransformer" );
+    CPLXMLNode *psTree
+        = CPLCreateXMLNode( NULL, CXT_Element, "WarpedOverviewTransformer" );
 
     CPLCreateXMLElementAndValue( psTree, "XFactor",
                                  CPLString().Printf("%g",psInfo->dfXOverviewFactor) );
@@ -672,13 +678,11 @@ VRTSerializeWarpedOverviewTransformer( void *pTransformArg )
 /* -------------------------------------------------------------------- */
 /*      Capture underlying transformer.                                 */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psTransformerContainer;
-    CPLXMLNode *psTransformer;
+    CPLXMLNode *psTransformerContainer
+        = CPLCreateXMLNode( psTree, CXT_Element, "BaseTransformer" );
 
-    psTransformerContainer =
-        CPLCreateXMLNode( psTree, CXT_Element, "BaseTransformer" );
-
-    psTransformer = GDALSerializeTransformer( psInfo->pfnBaseTransformer,
+    CPLXMLNode *psTransformer
+        = GDALSerializeTransformer( psInfo->pfnBaseTransformer,
                                               psInfo->pBaseTransformerArg );
     if( psTransformer != NULL )
         CPLAddXMLChild( psTransformerContainer, psTransformer );
@@ -693,8 +697,7 @@ VRTSerializeWarpedOverviewTransformer( void *pTransformArg )
 static void VRTWarpedOverviewTransformerOwnsSubtransformer( void *pTransformArg,
                                                           int bOwnFlag )
 {
-    VWOTInfo *psInfo =
-            (VWOTInfo *) pTransformArg;
+    VWOTInfo *psInfo = reinterpret_cast<VWOTInfo *>( pTransformArg );
 
     psInfo->bOwnSubtransformer = bOwnFlag;
 }
@@ -740,7 +743,7 @@ void* VRTDeserializeWarpedOverviewTransformer( CPLXMLNode *psTree )
         return pApproxCBData;
     }
 }
-#endif
+#endif  // TODO: Why disabled?
 
 /************************************************************************/
 /*                   VRTCreateWarpedOverviewTransformer()               */
@@ -753,13 +756,11 @@ void* VRTCreateWarpedOverviewTransformer( GDALTransformerFunc pfnBaseTransformer
                                           double dfYOverviewFactor)
 
 {
-    VWOTInfo *psSCTInfo;
-
     if (pfnBaseTransformer == NULL)
         return NULL;
 
-    psSCTInfo = (VWOTInfo*)
-                    CPLMalloc(sizeof(VWOTInfo));
+    VWOTInfo *psSCTInfo = reinterpret_cast<VWOTInfo*>(
+        CPLMalloc( sizeof(VWOTInfo) ) );
     psSCTInfo->pfnBaseTransformer = pfnBaseTransformer;
     psSCTInfo->pBaseTransformerArg = pBaseTransformerArg;
     psSCTInfo->dfXOverviewFactor = dfXOverviewFactor;
@@ -783,7 +784,7 @@ void* VRTCreateWarpedOverviewTransformer( GDALTransformerFunc pfnBaseTransformer
 static
 void VRTDestroyWarpedOverviewTransformer(void* pTransformArg)
 {
-    VWOTInfo *psInfo = (VWOTInfo *) pTransformArg;
+    VWOTInfo *psInfo = reinterpret_cast<VWOTInfo *>( pTransformArg );
 
     if( psInfo->bOwnSubtransformer )
         GDALDestroyTransformer( psInfo->pBaseTransformerArg );
@@ -802,26 +803,25 @@ int VRTWarpedOverviewTransform( void *pTransformArg, int bDstToSrc,
                                 int *panSuccess )
 
 {
-    VWOTInfo *psInfo = (VWOTInfo *) pTransformArg;
-    int i, bSuccess;
+    VWOTInfo *psInfo = reinterpret_cast<VWOTInfo *>( pTransformArg );
 
     if( bDstToSrc )
     {
-        for( i = 0; i < nPointCount; i++ )
+        for( int i = 0; i < nPointCount; i++ )
         {
             padfX[i] *= psInfo->dfXOverviewFactor;
             padfY[i] *= psInfo->dfYOverviewFactor;
         }
     }
 
-    bSuccess = psInfo->pfnBaseTransformer( psInfo->pBaseTransformerArg,
+    int bSuccess = psInfo->pfnBaseTransformer( psInfo->pBaseTransformerArg,
                                            bDstToSrc,
                                            nPointCount, padfX, padfY, padfZ,
                                            panSuccess );
 
     if( !bDstToSrc )
     {
-        for( i = 0; i < nPointCount; i++ )
+        for( int i = 0; i < nPointCount; i++ )
         {
             padfX[i] /= psInfo->dfXOverviewFactor;
             padfY[i] /= psInfo->dfYOverviewFactor;
@@ -848,7 +848,7 @@ VRTWarpedDataset::IBuildOverviews( CPL_UNUSED const char *pszResampling,
                                    GDALProgressFunc pfnProgress,
                                    void * pProgressData )
 {
-    if( poWarper == NULL )
+    if( m_poWarper == NULL )
         return CE_Failure;
 
 /* -------------------------------------------------------------------- */
@@ -864,27 +864,23 @@ VRTWarpedDataset::IBuildOverviews( CPL_UNUSED const char *pszResampling,
 /*      Establish which of the overview levels we already have, and     */
 /*      which are new.                                                  */
 /* -------------------------------------------------------------------- */
-    int   i, nNewOverviews, *panNewOverviewList = NULL;
-
-    nNewOverviews = 0;
-    panNewOverviewList = (int *) CPLCalloc(sizeof(int),nOverviews);
-    for( i = 0; i < nOverviews; i++ )
+    int nNewOverviews = 0;
+    int *panNewOverviewList = reinterpret_cast<int *>(
+        CPLCalloc( sizeof(int), nOverviews ) );
+    for( int i = 0; i < nOverviews; i++ )
     {
-        int   j;
-
-        for( j = 0; j < nOverviewCount; j++ )
+        for( int j = 0; j < m_nOverviewCount; j++ )
         {
-            int    nOvFactor;
-            GDALDataset *poOverview = papoOverviews[j];
+            GDALDataset *poOverview = m_papoOverviews[j];
 
-            nOvFactor = GDALComputeOvFactor(poOverview->GetRasterXSize(),
+            int nOvFactor = GDALComputeOvFactor(poOverview->GetRasterXSize(),
                                             GetRasterXSize(),
                                             poOverview->GetRasterYSize(),
                                             GetRasterYSize());
 
-            if( nOvFactor == panOverviewList[i] 
-                || nOvFactor == GDALOvLevelAdjust2( panOverviewList[i], 
-                                                   GetRasterXSize(), 
+            if( nOvFactor == panOverviewList[i]
+                || nOvFactor == GDALOvLevelAdjust2( panOverviewList[i],
+                                                   GetRasterXSize(),
                                                    GetRasterYSize() ) )
                 panOverviewList[i] *= -1;
         }
@@ -898,20 +894,17 @@ VRTWarpedDataset::IBuildOverviews( CPL_UNUSED const char *pszResampling,
 /*      to update existing overviews).                                  */
 /* -------------------------------------------------------------------- */
     CPLErr eErr = CE_None;
-    for( i = 0; i < nNewOverviews; i++ )
+    for( int i = 0; i < nNewOverviews; i++ )
     {
-        int    nOXSize, nOYSize, iBand;
-        VRTWarpedDataset *poOverviewDS;
-        
 /* -------------------------------------------------------------------- */
 /*      What size should this overview be.                              */
 /* -------------------------------------------------------------------- */
-        nOXSize = (GetRasterXSize() + panNewOverviewList[i] - 1) 
+        const int nOXSize = (GetRasterXSize() + panNewOverviewList[i] - 1)
             / panNewOverviewList[i];
-                                 
-        nOYSize = (GetRasterYSize() + panNewOverviewList[i] - 1) 
+
+        const int nOYSize = (GetRasterYSize() + panNewOverviewList[i] - 1)
             / panNewOverviewList[i];
-        
+
 /* -------------------------------------------------------------------- */
 /*      Find the most appropriate base dataset onto which to build the  */
 /*      new one. The preference will be an overview dataset with a ratio*/
@@ -920,29 +913,30 @@ VRTWarpedDataset::IBuildOverviews( CPL_UNUSED const char *pszResampling,
 /*      ones are based on overviews of the source dataset.              */
 /* -------------------------------------------------------------------- */
         VRTWarpedDataset* poBaseDataset = this;
-        for( int j = 0; j < nOverviewCount; j++ )
+        for( int j = 0; j < m_nOverviewCount; j++ )
         {
-            if( papoOverviews[j]->GetRasterXSize() > nOXSize &&
-                papoOverviews[j]->poWarper->GetOptions()->pfnTransformer !=
+            if( m_papoOverviews[j]->GetRasterXSize() > nOXSize &&
+                m_papoOverviews[j]->m_poWarper->GetOptions()->pfnTransformer !=
                                                 VRTWarpedOverviewTransform &&
-                papoOverviews[j]->GetRasterXSize() < poBaseDataset->GetRasterXSize() )
+                m_papoOverviews[j]->GetRasterXSize() < poBaseDataset->GetRasterXSize() )
             {
-                poBaseDataset = papoOverviews[j];
+                poBaseDataset = m_papoOverviews[j];
             }
         }
 
 /* -------------------------------------------------------------------- */
 /*      Create the overview dataset.                                    */
 /* -------------------------------------------------------------------- */
-        poOverviewDS = new VRTWarpedDataset( nOXSize, nOYSize );
-        
-        for( iBand = 0; iBand < GetRasterCount(); iBand++ )
+        VRTWarpedDataset *poOverviewDS
+            = new VRTWarpedDataset( nOXSize, nOYSize );
+
+        for( int iBand = 0; iBand < GetRasterCount(); iBand++ )
         {
             GDALRasterBand *poOldBand = GetRasterBand(iBand+1);
-            VRTWarpedRasterBand *poNewBand = 
-                new VRTWarpedRasterBand( poOverviewDS, iBand+1, 
+            VRTWarpedRasterBand *poNewBand =
+                new VRTWarpedRasterBand( poOverviewDS, iBand+1,
                                          poOldBand->GetRasterDataType() );
-            
+
             poNewBand->CopyCommonInfoFrom( poOldBand );
             poOverviewDS->SetBand( iBand+1, poNewBand );
         }
@@ -951,7 +945,8 @@ VRTWarpedDataset::IBuildOverviews( CPL_UNUSED const char *pszResampling,
 /*      Prepare update transformation information that will apply       */
 /*      the overview decimation.                                        */
 /* -------------------------------------------------------------------- */
-        GDALWarpOptions *psWO = (GDALWarpOptions *) poBaseDataset->poWarper->GetOptions();
+        GDALWarpOptions *psWO = const_cast<GDALWarpOptions *>(
+            poBaseDataset->m_poWarper->GetOptions() );
 
 /* -------------------------------------------------------------------- */
 /*      Initialize the new dataset with adjusted warp options, and      */
@@ -962,27 +957,27 @@ VRTWarpedDataset::IBuildOverviews( CPL_UNUSED const char *pszResampling,
 
         psWO->pfnTransformer = VRTWarpedOverviewTransform;
         psWO->pTransformerArg = VRTCreateWarpedOverviewTransformer(
-                                        pfnTransformerBase,
-                                        pTransformerBaseArg,
-                                        poBaseDataset->GetRasterXSize() / (double) nOXSize,
-                                        poBaseDataset->GetRasterYSize() / (double) nOYSize );
+            pfnTransformerBase,
+            pTransformerBaseArg,
+            poBaseDataset->GetRasterXSize() / static_cast<double>( nOXSize ),
+            poBaseDataset->GetRasterYSize() / static_cast<double>( nOYSize ) );
 
         eErr = poOverviewDS->Initialize( psWO );
 
         psWO->pfnTransformer = pfnTransformerBase;
         psWO->pTransformerArg = pTransformerBaseArg;
-        
+
         if( eErr != CE_None )
         {
             delete poOverviewDS;
             break;
         }
 
-        nOverviewCount++;
-        papoOverviews = (VRTWarpedDataset **)
-            CPLRealloc( papoOverviews, sizeof(void*) * nOverviewCount );
+        m_nOverviewCount++;
+        m_papoOverviews = reinterpret_cast<VRTWarpedDataset **>(
+            CPLRealloc( m_papoOverviews, sizeof(void*) * m_nOverviewCount ) );
 
-        papoOverviews[nOverviewCount-1] = poOverviewDS;
+        m_papoOverviews[m_nOverviewCount-1] = poOverviewDS;
 
     }
 
@@ -1009,47 +1004,46 @@ VRTWarpedDataset::IBuildOverviews( CPL_UNUSED const char *pszResampling,
  *
  * This method is the same as the C++ method VRTWarpedDataset::Initialize().
  *
- * @param hDS dataset previously created with the VRT driver, and a 
+ * @param hDS dataset previously created with the VRT driver, and a
  * SUBCLASS of "VRTWarpedDataset".
- * 
+ *
  * @param psWO the warp options to apply.  Note that ownership of the
  * transformation information is taken over by the function though everything
- * else remains the property of the caller. 
+ * else remains the property of the caller.
  *
- * @return CE_None on success or CE_Failure if an error occurs. 
+ * @return CE_None on success or CE_Failure if an error occurs.
  */
 
-CPLErr CPL_STDCALL 
+CPLErr CPL_STDCALL
 GDALInitializeWarpedVRT( GDALDatasetH hDS, GDALWarpOptions *psWO )
 
 {
     VALIDATE_POINTER1( hDS, "GDALInitializeWarpedVRT", CE_Failure );
 
-    return ((VRTWarpedDataset *) hDS)->Initialize( psWO );
+    return reinterpret_cast<VRTWarpedDataset *>( hDS )->Initialize( psWO );
 }
 
 /************************************************************************/
 /*                              XMLInit()                               */
 /************************************************************************/
 
-CPLErr VRTWarpedDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPath )
+CPLErr VRTWarpedDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPathIn )
 
 {
-    CPLErr eErr;
 
 /* -------------------------------------------------------------------- */
 /*      Initialize blocksize before calling sub-init so that the        */
 /*      band initializers can get it from the dataset object when       */
 /*      they are created.                                               */
 /* -------------------------------------------------------------------- */
-    nBlockXSize = atoi(CPLGetXMLValue(psTree,"BlockXSize","512"));
-    nBlockYSize = atoi(CPLGetXMLValue(psTree,"BlockYSize","128"));
+    m_nBlockXSize = atoi(CPLGetXMLValue(psTree,"BlockXSize","512"));
+    m_nBlockYSize = atoi(CPLGetXMLValue(psTree,"BlockYSize","128"));
 
 /* -------------------------------------------------------------------- */
 /*      Initialize all the general VRT stuff.  This will even           */
 /*      create the VRTWarpedRasterBands and initialize them.            */
 /* -------------------------------------------------------------------- */
-    eErr = VRTDataset::XMLInit( psTree, pszVRTPath );
+    CPLErr eErr = VRTDataset::XMLInit( psTree, pszVRTPathIn );
 
     if( eErr != CE_None )
         return eErr;
@@ -1057,8 +1051,7 @@ CPLErr VRTWarpedDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPath )
 /* -------------------------------------------------------------------- */
 /*      Find the GDALWarpOptions XML tree.                              */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psOptionsTree;
-    psOptionsTree = CPLGetXMLNode( psTree, "GDALWarpOptions" );
+    CPLXMLNode *psOptionsTree = CPLGetXMLNode( psTree, "GDALWarpOptions" );
     if( psOptionsTree == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -1070,17 +1063,17 @@ CPLErr VRTWarpedDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPath )
 /*      Adjust the SourceDataset in the warp options to take into       */
 /*      account that it is relative to the VRT if appropriate.          */
 /* -------------------------------------------------------------------- */
-    int bRelativeToVRT = 
-        atoi(CPLGetXMLValue(psOptionsTree,
-                            "SourceDataset.relativeToVRT", "0" ));
+    const bool bRelativeToVRT =
+        CPL_TO_BOOL(atoi(CPLGetXMLValue(psOptionsTree,
+                            "SourceDataset.relativeToVRT", "0" )));
 
     const char *pszRelativePath = CPLGetXMLValue(psOptionsTree,
                                                  "SourceDataset", "" );
     char *pszAbsolutePath;
 
     if( bRelativeToVRT )
-        pszAbsolutePath = 
-            CPLStrdup(CPLProjectRelativeFilename( pszVRTPath, 
+        pszAbsolutePath =
+            CPLStrdup(CPLProjectRelativeFilename( pszVRTPathIn,
                                                   pszRelativePath ) );
     else
         pszAbsolutePath = CPLStrdup(pszRelativePath);
@@ -1092,9 +1085,7 @@ CPLErr VRTWarpedDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPath )
 /*      And instantiate the warp options, and corresponding warp        */
 /*      operation.                                                      */
 /* -------------------------------------------------------------------- */
-    GDALWarpOptions *psWO;
-
-    psWO = GDALDeserializeWarpOptions( psOptionsTree );
+    GDALWarpOptions *psWO = GDALDeserializeWarpOptions( psOptionsTree );
     if( psWO == NULL )
         return CE_Failure;
 
@@ -1116,13 +1107,13 @@ CPLErr VRTWarpedDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPath )
 /* -------------------------------------------------------------------- */
 /*      Instantiate the warp operation.                                 */
 /* -------------------------------------------------------------------- */
-    poWarper = new GDALWarpOperation();
+    m_poWarper = new GDALWarpOperation();
 
-    eErr = poWarper->Initialize( psWO );
+    eErr = m_poWarper->Initialize( psWO );
     if( eErr != CE_None)
     {
 /* -------------------------------------------------------------------- */
-/*      We are responsible for cleaning up the transformer outselves.   */
+/*      We are responsible for cleaning up the transformer ourselves.   */
 /* -------------------------------------------------------------------- */
         if( psWO->pTransformerArg != NULL )
         {
@@ -1140,8 +1131,8 @@ CPLErr VRTWarpedDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPath )
     GDALDestroyWarpOptions( psWO );
     if( eErr != CE_None )
     {
-        delete poWarper;
-        poWarper = NULL;
+        delete m_poWarper;
+        m_poWarper = NULL;
     }
 
 /* -------------------------------------------------------------------- */
@@ -1156,16 +1147,15 @@ CPLErr VRTWarpedDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPath )
 /* -------------------------------------------------------------------- */
 /*      Generate overviews, if appropriate.                             */
 /* -------------------------------------------------------------------- */
-    
+
     CreateImplicitOverviews();
-    
+
     /* OverviewList is historical, and quite inefficient, since it uses */
     /* the full resolution source dataset, so only build it afterwards */
-    char **papszTokens = CSLTokenizeString( 
+    char **papszTokens = CSLTokenizeString(
         CPLGetXMLValue( psTree, "OverviewList", "" ));
-    int iOverview;
 
-    for( iOverview = 0; 
+    for( int iOverview = 0;
          papszTokens != NULL && papszTokens[iOverview] != NULL;
          iOverview++ )
     {
@@ -1187,12 +1177,10 @@ CPLErr VRTWarpedDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPath )
 /*                           SerializeToXML()                           */
 /************************************************************************/
 
-CPLXMLNode *VRTWarpedDataset::SerializeToXML( const char *pszVRTPath )
+CPLXMLNode *VRTWarpedDataset::SerializeToXML( const char *pszVRTPathIn )
 
 {
-    CPLXMLNode *psTree;
-
-    psTree = VRTDataset::SerializeToXML( pszVRTPath );
+    CPLXMLNode *psTree = VRTDataset::SerializeToXML( pszVRTPathIn );
 
     if( psTree == NULL )
         return psTree;
@@ -1200,48 +1188,50 @@ CPLXMLNode *VRTWarpedDataset::SerializeToXML( const char *pszVRTPath )
 /* -------------------------------------------------------------------- */
 /*      Set subclass.                                                   */
 /* -------------------------------------------------------------------- */
-    CPLCreateXMLNode( 
-        CPLCreateXMLNode( psTree, CXT_Attribute, "subClass" ), 
+    CPLCreateXMLNode(
+        CPLCreateXMLNode( psTree, CXT_Attribute, "subClass" ),
         CXT_Text, "VRTWarpedDataset" );
 
 /* -------------------------------------------------------------------- */
 /*      Serialize the block size.                                       */
 /* -------------------------------------------------------------------- */
     CPLCreateXMLElementAndValue( psTree, "BlockXSize",
-                                 CPLSPrintf( "%d", nBlockXSize ) );
+                                 CPLSPrintf( "%d", m_nBlockXSize ) );
     CPLCreateXMLElementAndValue( psTree, "BlockYSize",
-                                 CPLSPrintf( "%d", nBlockYSize ) );
+                                 CPLSPrintf( "%d", m_nBlockYSize ) );
 
 /* -------------------------------------------------------------------- */
 /*      Serialize the overview list (only for non implicit overviews)   */
 /* -------------------------------------------------------------------- */
-    if( nOverviewCount > 0 )
+    if( m_nOverviewCount > 0 )
     {
-        char *pszOverviewList;
-        int iOverview;
-                    
         int nSrcDSOvrCount = 0;
-        if( poWarper != NULL  && poWarper->GetOptions() != NULL &&
-            poWarper->GetOptions()->hSrcDS != NULL &&
-            GDALGetRasterCount(poWarper->GetOptions()->hSrcDS) > 0 )
+        if( m_poWarper != NULL  && m_poWarper->GetOptions() != NULL &&
+            m_poWarper->GetOptions()->hSrcDS != NULL &&
+            GDALGetRasterCount(m_poWarper->GetOptions()->hSrcDS) > 0 )
         {
-            nSrcDSOvrCount = ((GDALDataset*)poWarper->GetOptions()->hSrcDS)->
-                                        GetRasterBand(1)->GetOverviewCount();
+            nSrcDSOvrCount
+                = reinterpret_cast<GDALDataset*>(
+                    m_poWarper->GetOptions()->hSrcDS)->
+                GetRasterBand(1)->GetOverviewCount();
         }
 
-        if( nOverviewCount != nSrcDSOvrCount )
+        char *pszOverviewList;
+        if( m_nOverviewCount != nSrcDSOvrCount )
         {
-            pszOverviewList = (char *) CPLMalloc(nOverviewCount*8 + 10);
+            const size_t nLen = m_nOverviewCount*8 + 10;
+            pszOverviewList = reinterpret_cast<char *>(
+                CPLMalloc( nLen ) );
             pszOverviewList[0] = '\0';
-            for( iOverview = 0; iOverview < nOverviewCount; iOverview++ )
+            for( int iOverview = 0; iOverview < m_nOverviewCount; iOverview++ )
             {
-                int nOvFactor;
+                int nOvFactor = static_cast<int>(
+                    0.5 + GetRasterXSize()
+                    / static_cast<double>(
+                        m_papoOverviews[iOverview]->GetRasterXSize() ) );
 
-                nOvFactor = (int) 
-                    (0.5+GetRasterXSize() 
-                     / (double) papoOverviews[iOverview]->GetRasterXSize());
-
-                sprintf( pszOverviewList + strlen(pszOverviewList), 
+                snprintf( pszOverviewList + strlen(pszOverviewList),
+                          nLen - strlen(pszOverviewList),
                          "%d ", nOvFactor );
             }
 
@@ -1250,18 +1240,18 @@ CPLXMLNode *VRTWarpedDataset::SerializeToXML( const char *pszVRTPath )
             CPLFree( pszOverviewList );
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Serialize source overview level.                                */
 /* -------------------------------------------------------------------- */
-    if( nSrcOvrLevel != -2 )
+    if( m_nSrcOvrLevel != -2 )
     {
-        if( nSrcOvrLevel < -2 )
-            CPLCreateXMLElementAndValue( psTree, "SrcOvrLevel", CPLSPrintf("AUTO%d", nSrcOvrLevel+2) );
-        else if( nSrcOvrLevel == -1 )
+        if( m_nSrcOvrLevel < -2 )
+            CPLCreateXMLElementAndValue( psTree, "SrcOvrLevel", CPLSPrintf("AUTO%d", m_nSrcOvrLevel+2) );
+        else if( m_nSrcOvrLevel == -1 )
             CPLCreateXMLElementAndValue( psTree, "SrcOvrLevel", "NONE" );
         else
-            CPLCreateXMLElementAndValue( psTree, "SrcOvrLevel", CPLSPrintf("%d", nSrcOvrLevel) );
+            CPLCreateXMLElementAndValue( psTree, "SrcOvrLevel", CPLSPrintf("%d", m_nSrcOvrLevel) );
     }
 
 /* ==================================================================== */
@@ -1269,7 +1259,7 @@ CPLXMLNode *VRTWarpedDataset::SerializeToXML( const char *pszVRTPath )
 /* ==================================================================== */
     CPLXMLNode *psWOTree;
 
-    if( poWarper != NULL )
+    if( m_poWarper != NULL )
     {
 /* -------------------------------------------------------------------- */
 /*      We reset the destination dataset name so it doesn't get         */
@@ -1278,7 +1268,7 @@ CPLXMLNode *VRTWarpedDataset::SerializeToXML( const char *pszVRTPath )
         char *pszSavedName = CPLStrdup(GetDescription());
         SetDescription("");
 
-        psWOTree = GDALSerializeWarpOptions( poWarper->GetOptions() );
+        psWOTree = GDALSerializeWarpOptions( m_poWarper->GetOptions() );
         CPLAddXMLChild( psTree, psWOTree );
 
         SetDescription( pszSavedName );
@@ -1292,21 +1282,19 @@ CPLXMLNode *VRTWarpedDataset::SerializeToXML( const char *pszVRTPath )
         int bRelativeToVRT = FALSE;
         VSIStatBufL  sStat;
 
-        if( VSIStatExL( psSDS->psChild->pszValue, &sStat, 
-                        VSI_STAT_EXISTS_FLAG) == 0 ) 
+        if( VSIStatExL( psSDS->psChild->pszValue, &sStat,
+                        VSI_STAT_EXISTS_FLAG) == 0 )
         {
-            char *pszRelativePath;
-        
-            pszRelativePath = CPLStrdup(
-                CPLExtractRelativePath( pszVRTPath, psSDS->psChild->pszValue, 
+            char *pszRelativePath = CPLStrdup(
+                CPLExtractRelativePath( pszVRTPathIn, psSDS->psChild->pszValue,
                                         &bRelativeToVRT ) );
 
             CPLFree( psSDS->psChild->pszValue );
             psSDS->psChild->pszValue = pszRelativePath;
         }
 
-        CPLCreateXMLNode( 
-            CPLCreateXMLNode( psSDS, CXT_Attribute, "relativeToVRT" ), 
+        CPLCreateXMLNode(
+            CPLCreateXMLNode( psSDS, CXT_Attribute, "relativeToVRT" ),
             CXT_Text, bRelativeToVRT ? "1" : "0" );
     }
 
@@ -1323,8 +1311,8 @@ void VRTWarpedDataset::GetBlockSize( int *pnBlockXSize, int *pnBlockYSize )
     assert( NULL != pnBlockXSize );
     assert( NULL != pnBlockYSize );
 
-    *pnBlockXSize = nBlockXSize;
-    *pnBlockYSize = nBlockYSize;
+    *pnBlockXSize = m_nBlockXSize;
+    *pnBlockYSize = m_nBlockYSize;
 }
 
 /************************************************************************/
@@ -1337,32 +1325,28 @@ void VRTWarpedDataset::GetBlockSize( int *pnBlockXSize, int *pnBlockYSize )
 CPLErr VRTWarpedDataset::ProcessBlock( int iBlockX, int iBlockY )
 
 {
-    if( poWarper == NULL )
+    if( m_poWarper == NULL )
         return CE_Failure;
 
-    const GDALWarpOptions *psWO = poWarper->GetOptions();
+    const GDALWarpOptions *psWO = m_poWarper->GetOptions();
 
 /* -------------------------------------------------------------------- */
 /*      Allocate block of memory large enough to hold all the bands     */
 /*      for this block.                                                 */
 /* -------------------------------------------------------------------- */
-    int iBand;
-    GByte *pabyDstBuffer;
-    int   nDstBufferSize;
-    int   nWordSize = (GDALGetDataTypeSize(psWO->eWorkingDataType) / 8);
+    const int nWordSize = (GDALGetDataTypeSize(psWO->eWorkingDataType) / 8);
 
     // FIXME? : risk of overflow in multiplication if nBlockXSize or nBlockYSize are very large
-    nDstBufferSize = nBlockXSize * nBlockYSize * psWO->nBandCount * nWordSize;
+    const int nDstBufferSize
+        = m_nBlockXSize * m_nBlockYSize * psWO->nBandCount * nWordSize;
 
-    pabyDstBuffer = (GByte *) VSIMalloc(nDstBufferSize);
+    GByte *pabyDstBuffer = reinterpret_cast<GByte *>(
+        VSI_MALLOC_VERBOSE(nDstBufferSize) );
 
     if( pabyDstBuffer == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory,
-                  "Out of memory allocating %d byte buffer in VRTWarpedDataset::ProcessBlock()",
-                  nDstBufferSize );
         return CE_Failure;
-    }				
+    }
 
     memset( pabyDstBuffer, 0, nDstBufferSize );
 
@@ -1377,17 +1361,17 @@ CPLErr VRTWarpedDataset::ProcessBlock( int iBlockX, int iBlockY )
 
     if( pszInitDest != NULL && !EQUAL(pszInitDest, "") )
     {
-        char **papszInitValues = 
+        char **papszInitValues =
             CSLTokenizeStringComplex( pszInitDest, ",", FALSE, FALSE );
-        int nInitCount = CSLCount(papszInitValues);
-                                                           
-        for( iBand = 0; iBand < psWO->nBandCount; iBand++ )
+        const int nInitCount = CSLCount(papszInitValues);
+
+        for( int iBand = 0; iBand < psWO->nBandCount; iBand++ )
         {
-            double adfInitRealImag[2];
-            GByte *pBandData;
-            int nBandSize = nBlockXSize * nBlockYSize * nWordSize;
-            const char *pszBandInit = papszInitValues[MIN(iBand,nInitCount-1)];
+            const int nBandSize = m_nBlockXSize * m_nBlockYSize * nWordSize;
+            const char *pszBandInit
+                = papszInitValues[std::min( iBand, nInitCount - 1 )];
 
+            double adfInitRealImag[2];
             if( EQUAL(pszBandInit,"NO_DATA")
                 && psWO->padfDstNoDataReal != NULL )
             {
@@ -1400,11 +1384,12 @@ CPLErr VRTWarpedDataset::ProcessBlock( int iBlockX, int iBlockY )
                                     adfInitRealImag + 0, adfInitRealImag + 1);
             }
 
-            pBandData = ((GByte *) pabyDstBuffer) + iBand * nBandSize;
-            
+            GByte *pBandData = reinterpret_cast<GByte *>(
+                pabyDstBuffer ) + iBand * nBandSize;
+
             if( psWO->eWorkingDataType == GDT_Byte )
-                memset( pBandData, 
-                        MAX(0,MIN(255,(int)adfInitRealImag[0])), 
+                memset( pBandData,
+                        std::max(0,std::min(255,static_cast<int>( adfInitRealImag[0] ))),
                         nBandSize);
             else if( !CPLIsNan(adfInitRealImag[0]) && adfInitRealImag[0] == 0.0 &&
                      !CPLIsNan(adfInitRealImag[1]) && adfInitRealImag[1] == 0.0 )
@@ -1413,15 +1398,15 @@ CPLErr VRTWarpedDataset::ProcessBlock( int iBlockX, int iBlockY )
             }
             else if( !CPLIsNan(adfInitRealImag[1]) && adfInitRealImag[1] == 0.0 )
             {
-                GDALCopyWords( &adfInitRealImag, GDT_Float64, 0, 
+                GDALCopyWords( &adfInitRealImag, GDT_Float64, 0,
                                pBandData,psWO->eWorkingDataType,nWordSize,
-                               nBlockXSize * nBlockYSize );
+                               m_nBlockXSize * m_nBlockYSize );
             }
             else
             {
-                GDALCopyWords( &adfInitRealImag, GDT_CFloat64, 0, 
+                GDALCopyWords( &adfInitRealImag, GDT_CFloat64, 0,
                                pBandData,psWO->eWorkingDataType,nWordSize,
-                               nBlockXSize * nBlockYSize );
+                               m_nBlockXSize * m_nBlockYSize );
             }
         }
 
@@ -1431,18 +1416,16 @@ CPLErr VRTWarpedDataset::ProcessBlock( int iBlockX, int iBlockY )
 /* -------------------------------------------------------------------- */
 /*      Warp into this buffer.                                          */
 /* -------------------------------------------------------------------- */
-    CPLErr eErr;
-    
-    int nReqXSize = nBlockXSize;
-    if( iBlockX * nBlockXSize + nReqXSize > nRasterXSize )
-        nReqXSize = nRasterXSize - iBlockX * nBlockXSize;
-    int nReqYSize = nBlockYSize;
-    if( iBlockY * nBlockYSize + nReqYSize > nRasterYSize )
-        nReqYSize = nRasterYSize - iBlockY * nBlockYSize;
-
-    eErr = 
-        poWarper->WarpRegionToBuffer( 
-            iBlockX * nBlockXSize, iBlockY * nBlockYSize, 
+    int nReqXSize = m_nBlockXSize;
+    if( iBlockX * m_nBlockXSize + nReqXSize > nRasterXSize )
+        nReqXSize = nRasterXSize - iBlockX * m_nBlockXSize;
+    int nReqYSize = m_nBlockYSize;
+    if( iBlockY * m_nBlockYSize + nReqYSize > nRasterYSize )
+        nReqYSize = nRasterYSize - iBlockY * m_nBlockYSize;
+
+    CPLErr eErr
+        = m_poWarper->WarpRegionToBuffer(
+            iBlockX * m_nBlockXSize, iBlockY * m_nBlockYSize,
             nReqXSize, nReqYSize,
             pabyDstBuffer, psWO->eWorkingDataType );
 
@@ -1451,41 +1434,40 @@ CPLErr VRTWarpedDataset::ProcessBlock( int iBlockX, int iBlockY )
         VSIFree( pabyDstBuffer );
         return eErr;
     }
-                        
+
 /* -------------------------------------------------------------------- */
 /*      Copy out into cache blocks for each band.                       */
 /* -------------------------------------------------------------------- */
-    for( iBand = 0; iBand < MIN(nBands, psWO->nBandCount); iBand++ )
+    for( int iBand = 0; iBand < std::min(nBands, psWO->nBandCount); iBand++ )
     {
-        GDALRasterBand *poBand;
-        GDALRasterBlock *poBlock;
-
-        poBand = GetRasterBand(iBand+1);
-        poBlock = poBand->GetLockedBlockRef( iBlockX, iBlockY, TRUE );
+        GDALRasterBand *poBand = GetRasterBand(iBand+1);
+        GDALRasterBlock *poBlock
+            = poBand->GetLockedBlockRef( iBlockX, iBlockY, TRUE );
 
         if( poBlock != NULL )
         {
             if ( poBlock->GetDataRef() != NULL )
             {
-                if( nReqXSize == nBlockXSize && nReqYSize == nBlockYSize )
+                if( nReqXSize == m_nBlockXSize && nReqYSize == m_nBlockYSize )
                 {
-                    GDALCopyWords( pabyDstBuffer + iBand*nBlockXSize*nBlockYSize*nWordSize,
-                                psWO->eWorkingDataType, nWordSize, 
-                                poBlock->GetDataRef(), 
-                                poBlock->GetDataType(), 
+                    GDALCopyWords( pabyDstBuffer + iBand*m_nBlockXSize*m_nBlockYSize*nWordSize,
+                                psWO->eWorkingDataType, nWordSize,
+                                poBlock->GetDataRef(),
+                                poBlock->GetDataType(),
                                 GDALGetDataTypeSize(poBlock->GetDataType())/8,
-                                nBlockXSize * nBlockYSize );
+                                m_nBlockXSize * m_nBlockYSize );
                 }
                 else
                 {
-                    GByte* pabyBlock = (GByte*) poBlock->GetDataRef();
-                    int nDTSize = GDALGetDataTypeSize(poBlock->GetDataType())/8;
+                    GByte* pabyBlock = reinterpret_cast<GByte *>(
+                        poBlock->GetDataRef() );
+                    const int nDTSize = GDALGetDataTypeSize(poBlock->GetDataType())/8;
                     for(int iY=0;iY<nReqYSize;iY++)
                     {
                         GDALCopyWords( pabyDstBuffer + iBand*nReqXSize*nReqYSize*nWordSize + iY * nReqXSize*nWordSize,
-                                       psWO->eWorkingDataType, nWordSize, 
-                                       pabyBlock + iY * nBlockXSize * nDTSize, 
-                                       poBlock->GetDataType(), 
+                                       psWO->eWorkingDataType, nWordSize,
+                                       pabyBlock + iY * m_nBlockXSize * nDTSize,
+                                       poBlock->GetDataType(),
                                        nDTSize,
                                        nReqXSize );
                     }
@@ -1497,7 +1479,7 @@ CPLErr VRTWarpedDataset::ProcessBlock( int iBlockX, int iBlockY )
     }
 
     VSIFree( pabyDstBuffer );
-    
+
     return CE_None;
 }
 
@@ -1526,21 +1508,21 @@ CPLErr VRTWarpedDataset::AddBand( GDALDataType eType, char **papszOptions )
 /*                        VRTWarpedRasterBand()                         */
 /************************************************************************/
 
-VRTWarpedRasterBand::VRTWarpedRasterBand( GDALDataset *poDS, int nBand,
+VRTWarpedRasterBand::VRTWarpedRasterBand( GDALDataset *poDSIn, int nBandIn,
                                           GDALDataType eType )
 
 {
-    Initialize( poDS->GetRasterXSize(), poDS->GetRasterYSize() );
+    Initialize( poDSIn->GetRasterXSize(), poDSIn->GetRasterYSize() );
 
-    this->poDS = poDS;
-    this->nBand = nBand;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
     this->eAccess = GA_Update;
 
-    ((VRTWarpedDataset *) poDS)->GetBlockSize( &nBlockXSize, 
-                                               &nBlockYSize );
+    reinterpret_cast<VRTWarpedDataset *>( poDS )->GetBlockSize( &nBlockXSize,
+                                                                &nBlockYSize );
 
     if( eType != GDT_Unknown )
-        this->eDataType = eType;
+        eDataType = eType;
 }
 
 /************************************************************************/
@@ -1561,20 +1543,17 @@ CPLErr VRTWarpedRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                      void * pImage )
 
 {
-    CPLErr eErr;
-    VRTWarpedDataset *poWDS = (VRTWarpedDataset *) poDS;
-    GDALRasterBlock *poBlock;
-
-    poBlock = GetLockedBlockRef( nBlockXOff, nBlockYOff, TRUE );
+    VRTWarpedDataset *poWDS = reinterpret_cast<VRTWarpedDataset *>( poDS );
+    GDALRasterBlock *poBlock = GetLockedBlockRef( nBlockXOff, nBlockYOff, TRUE );
     if( poBlock == NULL )
         return CE_Failure;
 
-    eErr = poWDS->ProcessBlock( nBlockXOff, nBlockYOff );
+    CPLErr eErr = poWDS->ProcessBlock( nBlockXOff, nBlockYOff );
 
     if( eErr == CE_None && pImage != poBlock->GetDataRef() )
     {
-        int nDataBytes;
-        nDataBytes = (GDALGetDataTypeSize(poBlock->GetDataType()) / 8)
+        const int nDataBytes
+            = (GDALGetDataTypeSize(poBlock->GetDataType()) / 8)
             * poBlock->GetXSize() * poBlock->GetYSize();
         memcpy( pImage, poBlock->GetDataRef(), nDataBytes );
     }
@@ -1592,15 +1571,15 @@ CPLErr VRTWarpedRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                                      void * pImage )
 
 {
-    CPLErr eErr;
-    VRTWarpedDataset *poWDS = (VRTWarpedDataset *) poDS;
+    VRTWarpedDataset *poWDS = reinterpret_cast<VRTWarpedDataset *>( poDS );
 
     /* This is a bit tricky. In the case we are warping a VRTWarpedDataset */
     /* with a destination alpha band, IWriteBlock can be called on that alpha */
     /* band by GDALWarpDstAlphaMasker */
     /* We don't need to do anything since the data will be kept in the block */
     /* cache by VRTWarpedRasterBand::IReadBlock */
-    if (poWDS->poWarper->GetOptions()->nDstAlphaBand == nBand)
+    CPLErr eErr;
+    if (poWDS->m_poWarper->GetOptions()->nDstAlphaBand == nBand)
     {
         eErr = CE_None;
     }
@@ -1617,27 +1596,27 @@ CPLErr VRTWarpedRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
 /*                              XMLInit()                               */
 /************************************************************************/
 
-CPLErr VRTWarpedRasterBand::XMLInit( CPLXMLNode * psTree, 
-                                  const char *pszVRTPath )
+CPLErr VRTWarpedRasterBand::XMLInit( CPLXMLNode * psTree,
+                                  const char *pszVRTPathIn )
 
 {
-    return VRTRasterBand::XMLInit( psTree, pszVRTPath );
+    return VRTRasterBand::XMLInit( psTree, pszVRTPathIn );
 }
 
 /************************************************************************/
 /*                           SerializeToXML()                           */
 /************************************************************************/
 
-CPLXMLNode *VRTWarpedRasterBand::SerializeToXML( const char *pszVRTPath )
+CPLXMLNode *VRTWarpedRasterBand::SerializeToXML( const char *pszVRTPathIn )
 
 {
-    CPLXMLNode *psTree = VRTRasterBand::SerializeToXML( pszVRTPath );
+    CPLXMLNode *psTree = VRTRasterBand::SerializeToXML( pszVRTPathIn );
 
 /* -------------------------------------------------------------------- */
 /*      Set subclass.                                                   */
 /* -------------------------------------------------------------------- */
-    CPLCreateXMLNode( 
-        CPLCreateXMLNode( psTree, CXT_Attribute, "subClass" ), 
+    CPLCreateXMLNode(
+        CPLCreateXMLNode( psTree, CXT_Attribute, "subClass" ),
         CXT_Text, "VRTWarpedRasterBand" );
 
     return psTree;
@@ -1650,11 +1629,11 @@ CPLXMLNode *VRTWarpedRasterBand::SerializeToXML( const char *pszVRTPath )
 int VRTWarpedRasterBand::GetOverviewCount()
 
 {
-    VRTWarpedDataset *poWDS = (VRTWarpedDataset *) poDS;
-    
+    VRTWarpedDataset *poWDS = reinterpret_cast<VRTWarpedDataset *>( poDS );
+
     poWDS->CreateImplicitOverviews();
 
-    return poWDS->nOverviewCount;
+    return poWDS->m_nOverviewCount;
 }
 
 /************************************************************************/
@@ -1664,10 +1643,10 @@ int VRTWarpedRasterBand::GetOverviewCount()
 GDALRasterBand *VRTWarpedRasterBand::GetOverview( int iOverview )
 
 {
-    VRTWarpedDataset *poWDS = (VRTWarpedDataset *) poDS;
+    VRTWarpedDataset *poWDS = reinterpret_cast<VRTWarpedDataset *>( poDS );
 
     if( iOverview < 0 || iOverview >= GetOverviewCount() )
         return NULL;
-    else
-        return poWDS->papoOverviews[iOverview]->GetRasterBand( nBand );
+
+    return poWDS->m_papoOverviews[iOverview]->GetRasterBand( nBand );
 }
diff --git a/frmts/wcs/frmt_wcs.html b/frmts/wcs/frmt_wcs.html
index 600098c..ecb4f3f 100644
--- a/frmts/wcs/frmt_wcs.html
+++ b/frmts/wcs/frmt_wcs.html
@@ -7,11 +7,11 @@
 
 <h1>WCS -- OGC Web Coverage Service</h1>
 
-The optional GDAL WCS driver allows use of a coverage in a WCS server as a 
+The optional GDAL WCS driver allows use of a coverage in a WCS server as a
 raster dataset.  GDAL acts as a client to the WCS server.<p>
 
 Accessing a WCS server is accomplished by creating a local service description
-xml file looking something like the following, with the coverage server url, 
+xml file looking something like the following, with the coverage server url,
 and the name of the coverage to access.  It is important that there be no
 spaces or other content before the <tt><WCS_GDAL></tt> element.<p>
 
@@ -27,27 +27,27 @@ image to establish details about the raster.  This information will be cached
 in the service description file to make future opens faster - no server access
 should be required till imagery is read for future opens.<p>
 
-The WCS driver should support WCS 1.0.0 and 1.1.0 servers, but WCS 0.7 servers 
+The WCS driver should support WCS 1.0.0 and 1.1.0 servers, but WCS 0.7 servers
 are not supported.  Any return format that is a single file, and is in a format
-supported by GDAL should work.  The driver will prefer a format with "tiff" 
+supported by GDAL should work.  The driver will prefer a format with "tiff"
 in the name, otherwise
 it will fallback to the first offered format.   Coordinate systems are read
-from the DescribeCoverage result, and are expected to be in the form of 
+from the DescribeCoverage result, and are expected to be in the form of
 <tt>EPSG:n</tt> in the <tt><supportedCRSs></tt> element. <p>
 
-The service description file has the following additional elements as 
+The service description file has the following additional elements as
 immediate children of the <tt>WCS_GDAL</tt> element that may be optionally
 set.<p>
 
 <ul>
 <li> <b>PreferredFormat</b>: the format to use for GetCoverage calls.<p>
-<li> <b>BandCount</b>: Number of bands in the dataset, normally captured from the sample request. 
+<li> <b>BandCount</b>: Number of bands in the dataset, normally captured from the sample request.
 <li> <b>BandType</b>: The pixel data type to use.  Normally established from the sample request.
 <li> <b>BlockXSize</b>: The block width to use for block cached remote access.
 <li> <b>BlockYSize</b>: The block height to use for block cached remote access.
 <li> <b>NoDataValue</b>: The nodata value to use for all the bands (blank for none).  Normally defaulted from CoverageOffering info.
 <li> <b>Timeout</b>: The timeout to use for remote service requests.  If not provided, the libcurl default is used.
-<li> <b>UserPwd</b>: May be supplied with <i>userid:password</i> to pass a 
+<li> <b>UserPwd</b>: May be supplied with <i>userid:password</i> to pass a
 userid and password to the remote server.
 <li> <b>HttpAuth</b>: May be BASIC, NTLM or ANY to control the authentication scheme to be used.
 <li> <b>OverviewCount</b>: The number of overviews to represent bands as having.  Defaults to a number such that the top overview is fairly smaller (less than 1K x 1K or so).
@@ -55,8 +55,8 @@ userid and password to the remote server.
 <li> <b>DescribeCoverageExtra</b>: An additional set of keywords to add to DescribeCoverage requests in URL encoded form.  eg. "&CustNo=775"
 <li> <b>Version</b>:  Set a specific WCS version to use.  Currently defaults to 1.0.0 and 1.1.0 is also supported.
 <li> <b>FieldName</b>: Name of the field being accessed.  Used only with WCS 1.1.0+.  Defaults to the first field in the DescribeCoverage result.
-<li> <b>DefaultTime</b>: A timePosition to use by default when accessing 
-coverages with a time dimension.  Populated with the last offered time 
+<li> <b>DefaultTime</b>: A timePosition to use by default when accessing
+coverages with a time dimension.  Populated with the last offered time
 position by default.
 </ul>
 
diff --git a/frmts/wcs/httpdriver.cpp b/frmts/wcs/httpdriver.cpp
index 640bc66..3500a0e 100644
--- a/frmts/wcs/httpdriver.cpp
+++ b/frmts/wcs/httpdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: httpdriver.cpp 29102 2015-05-01 22:26:04Z rouault $
+ * $Id: httpdriver.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  WCS Client Driver
  * Purpose:  Implementation of an HTTP fetching driver.
@@ -28,12 +28,13 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
 #include "cpl_string.h"
 #include "cpl_http.h"
 #include "cpl_atomic_ops.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
 
-CPL_CVSID("$Id: httpdriver.cpp 29102 2015-05-01 22:26:04Z rouault $");
+CPL_CVSID("$Id: httpdriver.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 
 /************************************************************************/
@@ -46,12 +47,12 @@ static const char* HTTPFetchContentDispositionFilename(char** papszHeaders)
     while(papszIter && *papszIter)
     {
         /* For multipart, we have in raw format, but without end-of-line characters */
-        if (strncmp(*papszIter, "Content-Disposition: attachment; filename=", 42) == 0)
+        if (STARTS_WITH(*papszIter, "Content-Disposition: attachment; filename="))
         {
             return *papszIter + 42;
         }
         /* For single part, the headers are in KEY=VAL format, but with e-o-l ... */
-        else if (strncmp(*papszIter, "Content-Disposition=attachment; filename=", 41) == 0)
+        else if (STARTS_WITH(*papszIter, "Content-Disposition=attachment; filename="))
         {
             char* pszVal = (char*)(*papszIter + 41);
             char* pszEOL = strchr(pszVal, '\r');
@@ -77,22 +78,22 @@ static GDALDataset *HTTPOpen( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->nHeaderBytes != 0 )
         return NULL;
 
-    if( !EQUALN(poOpenInfo->pszFilename,"http:",5)
-        && !EQUALN(poOpenInfo->pszFilename,"https:",6)
-        && !EQUALN(poOpenInfo->pszFilename,"ftp:",4) )
+    if( !STARTS_WITH_CI(poOpenInfo->pszFilename, "http:")
+        && !STARTS_WITH_CI(poOpenInfo->pszFilename, "https:")
+        && !STARTS_WITH_CI(poOpenInfo->pszFilename, "ftp:") )
         return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Fetch the result.                                               */
 /* -------------------------------------------------------------------- */
     CPLErrorReset();
-    
+
     CPLHTTPResult *psResult = CPLHTTPFetch( poOpenInfo->pszFilename, NULL );
 
 /* -------------------------------------------------------------------- */
 /*      Try to handle errors.                                           */
 /* -------------------------------------------------------------------- */
-    if( psResult == NULL || psResult->nDataLen == 0 
+    if( psResult == NULL || psResult->nDataLen == 0
         || CPLGetLastErrorNo() != 0 )
     {
         CPLHTTPDestroyResult( psResult );
@@ -119,8 +120,8 @@ static GDALDataset *HTTPOpen( GDALOpenInfo * poOpenInfo )
                              nNewCounter, pszFilename );
 
     VSILFILE *fp = VSIFileFromMemBuffer( osResultFilename,
-                                     psResult->pabyData, 
-                                     psResult->nDataLen, 
+                                     psResult->pabyData,
+                                     psResult->nDataLen,
                                      TRUE );
 
     if( fp == NULL )
@@ -142,7 +143,7 @@ static GDALDataset *HTTPOpen( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     /* suppress errors as not all drivers support /vsimem */
     CPLPushErrorHandler( CPLQuietErrorHandler );
-    GDALDataset *poDS = (GDALDataset *) 
+    GDALDataset *poDS = (GDALDataset *)
         GDALOpenEx( osResultFilename, poOpenInfo->nOpenFlags, NULL,
                     poOpenInfo->papszOpenOptions, NULL);
     CPLPopErrorHandler();
@@ -163,13 +164,13 @@ static GDALDataset *HTTPOpen( GDALOpenInfo * poOpenInfo )
         osTempFilename = CPLFormFilename(pszPath, CPLGetFilename(osResultFilename), NULL );
         if( CPLCopyFile( osTempFilename, osResultFilename ) != 0 )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
-                      "Failed to create temporary file:%s", 
+            CPLError( CE_Failure, CPLE_OpenFailed,
+                      "Failed to create temporary file:%s",
                       osTempFilename.c_str() );
         }
         else
         {
-            poDS =  (GDALDataset *) 
+            poDS =  (GDALDataset *)
                 GDALOpenEx( osTempFilename, poOpenInfo->nOpenFlags, NULL,
                             poOpenInfo->papszOpenOptions, NULL );
             if( VSIUnlink( osTempFilename ) != 0 && poDS != NULL )
@@ -199,20 +200,17 @@ static GDALDataset *HTTPOpen( GDALOpenInfo * poOpenInfo )
 void GDALRegister_HTTP()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "HTTP" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "HTTP" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "HTTP" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "HTTP Fetching Wrapper" );
-        
-        poDriver->pfnOpen = HTTPOpen;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "HTTP" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "HTTP Fetching Wrapper" );
+
+    poDriver->pfnOpen = HTTPOpen;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/wcs/wcsdataset.cpp b/frmts/wcs/wcsdataset.cpp
index 0e2d0c9..1d6ecb8 100644
--- a/frmts/wcs/wcsdataset.cpp
+++ b/frmts/wcs/wcsdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: wcsdataset.cpp 28218 2014-12-25 18:09:13Z goatbar $
+ * $Id: wcsdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  WCS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WCS.
@@ -28,13 +28,14 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
 #include "cpl_string.h"
 #include "cpl_minixml.h"
 #include "cpl_http.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: wcsdataset.cpp 28218 2014-12-25 18:09:13Z goatbar $");
+CPL_CVSID("$Id: wcsdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -75,7 +76,7 @@ class CPL_DLL WCSDataset : public GDALPamDataset
                                 GSpacing nBandSpace,
                                 GDALRasterIOExtraArg* psExtraArg);
     CPLErr      GetCoverage( int nXOff, int nYOff, int nXSize, int nYSize,
-                             int nBufXSize, int nBufYSize, 
+                             int nBufXSize, int nBufYSize,
                              int nBandCount, int *panBandList,
                              CPLHTTPResult **ppsResult );
 
@@ -101,7 +102,7 @@ class CPL_DLL WCSDataset : public GDALPamDataset
 
     int         nMaxCols;
     int         nMaxRows;
-    
+
   public:
                 WCSDataset();
                 ~WCSDataset();
@@ -134,7 +135,7 @@ class WCSRasterBand : public GDALPamRasterBand
 
     int            nOverviewCount;
     WCSRasterBand **papoOverviews;
-    
+
     virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
                               void *, int, int, GDALDataType,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
@@ -157,19 +158,20 @@ class WCSRasterBand : public GDALPamRasterBand
 /*                           WCSRasterBand()                            */
 /************************************************************************/
 
-WCSRasterBand::WCSRasterBand( WCSDataset *poDS, int nBand, int iOverview )
+WCSRasterBand::WCSRasterBand( WCSDataset *poDSIn, int nBandIn, int iOverviewIn )
 
 {
-    poODS = poDS;
-    this->nBand = nBand;
+    poDS = poDSIn;
+    poODS = poDSIn;
+    this->nBand = nBandIn;
 
-    eDataType = GDALGetDataTypeByName( 
-        CPLGetXMLValue( poDS->psService, "BandType", "Byte" ) );
+    eDataType = GDALGetDataTypeByName(
+        CPLGetXMLValue( poDSIn->psService, "BandType", "Byte" ) );
 
 /* -------------------------------------------------------------------- */
 /*      Establish resolution reduction for this overview level.         */
 /* -------------------------------------------------------------------- */
-    this->iOverview = iOverview;
+    this->iOverview = iOverviewIn;
     nResFactor = 1 << (iOverview+1); // iOverview == -1 is base layer
 
 /* -------------------------------------------------------------------- */
@@ -177,9 +179,9 @@ WCSRasterBand::WCSRasterBand( WCSDataset *poDS, int nBand, int iOverview )
 /* -------------------------------------------------------------------- */
     nRasterXSize = poDS->GetRasterXSize() / nResFactor;
     nRasterYSize = poDS->GetRasterYSize() / nResFactor;
-    
-    nBlockXSize = atoi(CPLGetXMLValue( poDS->psService, "BlockXSize", "0" ) );
-    nBlockYSize = atoi(CPLGetXMLValue( poDS->psService, "BlockYSize", "0" ) );
+
+    nBlockXSize = atoi(CPLGetXMLValue( poDSIn->psService, "BlockXSize", "0" ) );
+    nBlockYSize = atoi(CPLGetXMLValue( poDSIn->psService, "BlockYSize", "0" ) );
 
     if( nBlockXSize < 1 )
     {
@@ -188,7 +190,7 @@ WCSRasterBand::WCSRasterBand( WCSDataset *poDS, int nBand, int iOverview )
         else
             nBlockXSize = nRasterXSize;
     }
-    
+
     if( nBlockYSize < 1 )
     {
         if( nRasterYSize > 900 )
@@ -208,7 +210,7 @@ WCSRasterBand::WCSRasterBand( WCSDataset *poDS, int nBand, int iOverview )
                                              "-1"));
         if( nOverviewCount < 0 )
         {
-            for( nOverviewCount = 0; 
+            for( nOverviewCount = 0;
                  (MAX(nRasterXSize,nRasterYSize) / (1 << nOverviewCount)) > 900;
                  nOverviewCount++ ) {}
         }
@@ -219,9 +221,9 @@ WCSRasterBand::WCSRasterBand( WCSDataset *poDS, int nBand, int iOverview )
             nOverviewCount = 30;
         }
 
-        papoOverviews = (WCSRasterBand **) 
+        papoOverviews = (WCSRasterBand **)
             CPLCalloc( nOverviewCount, sizeof(void*) );
-        
+
         for( i = 0; i < nOverviewCount; i++ )
             papoOverviews[i] = new WCSRasterBand( poODS, nBand, i );
     }
@@ -237,14 +239,14 @@ WCSRasterBand::WCSRasterBand( WCSDataset *poDS, int nBand, int iOverview )
 /************************************************************************/
 
 WCSRasterBand::~WCSRasterBand()
-    
+
 {
     FlushCache();
-    
+
     if( nOverviewCount > 0 )
     {
         int i;
-        
+
         for( i = 0; i < nOverviewCount; i++ )
             delete papoOverviews[i];
 
@@ -263,17 +265,17 @@ CPLErr WCSRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     CPLErr eErr;
     CPLHTTPResult *psResult = NULL;
 
-    eErr = poODS->GetCoverage( nBlockXOff * nBlockXSize * nResFactor, 
+    eErr = poODS->GetCoverage( nBlockXOff * nBlockXSize * nResFactor,
                                nBlockYOff * nBlockYSize * nResFactor,
-                               nBlockXSize * nResFactor, 
-                               nBlockYSize * nResFactor, 
-                               nBlockXSize, nBlockYSize, 
+                               nBlockXSize * nResFactor,
+                               nBlockYSize * nResFactor,
+                               nBlockXSize, nBlockYSize,
                                1, &nBand, &psResult );
     if( eErr != CE_None )
         return eErr;
 
 /* -------------------------------------------------------------------- */
-/*      Try and open result as a dataseat.                               */
+/*      Try and open result as a dataset.                               */
 /* -------------------------------------------------------------------- */
     GDALDataset *poTileDS = poODS->GDALOpenResult( psResult );
 
@@ -286,13 +288,13 @@ CPLErr WCSRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     if( poTileDS->GetRasterXSize() != nBlockXSize
         || poTileDS->GetRasterYSize() != nBlockYSize )
     {
-        CPLDebug( "WCS", "Got size=%dx%d instead of %dx%d.", 
+        CPLDebug( "WCS", "Got size=%dx%d instead of %dx%d.",
                   poTileDS->GetRasterXSize(), poTileDS->GetRasterYSize(),
                   nBlockXSize, nBlockYSize );
 
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Returned tile does not match expected configuration.\n"
-                  "Got %dx%d instead of %dx%d.", 
+                  "Got %dx%d instead of %dx%d.",
                   poTileDS->GetRasterXSize(), poTileDS->GetRasterYSize(),
                   nBlockXSize, nBlockYSize );
         delete poTileDS;
@@ -300,10 +302,10 @@ CPLErr WCSRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     }
 
     if( (strlen(poODS->osBandIdentifier) && poTileDS->GetRasterCount() != 1)
-        || (!strlen(poODS->osBandIdentifier) 
+        || (!strlen(poODS->osBandIdentifier)
             && poTileDS->GetRasterCount() != poODS->GetRasterCount()) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Returned tile does not match expected band configuration.");
         delete poTileDS;
         return CE_Failure;
@@ -315,27 +317,27 @@ CPLErr WCSRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
     int iBand;
     eErr = CE_None;
-    
-    for( iBand = 0; 
-         iBand < poTileDS->GetRasterCount() && eErr == CE_None; 
+
+    for( iBand = 0;
+         iBand < poTileDS->GetRasterCount() && eErr == CE_None;
          iBand++ )
     {
         GDALRasterBand *poTileBand = poTileDS->GetRasterBand( iBand+1 );
 
         if( iBand+1 == GetBand() || strlen(poODS->osBandIdentifier) )
         {
-            eErr = poTileBand->RasterIO( GF_Read, 
-                                         0, 0, nBlockXSize, nBlockYSize, 
-                                         pImage, nBlockXSize, nBlockYSize, 
+            eErr = poTileBand->RasterIO( GF_Read,
+                                         0, 0, nBlockXSize, nBlockYSize,
+                                         pImage, nBlockXSize, nBlockYSize,
                                          eDataType, 0, 0, NULL );
         }
         else
         {
             GDALRasterBand *poTargBand = poODS->GetRasterBand( iBand+1 );
-            
+
             if( iOverview != -1 )
                 poTargBand = poTargBand->GetOverview( iOverview );
-            
+
             GDALRasterBlock *poBlock = poTargBand->GetLockedBlockRef(
                 nBlockXOff, nBlockYOff, TRUE );
 
@@ -357,7 +359,7 @@ CPLErr WCSRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /*      Cleanup                                                         */
 /* -------------------------------------------------------------------- */
     delete poTileDS;
-    
+
     poODS->FlushMemoryResult();
 
     return eErr;
@@ -373,7 +375,7 @@ CPLErr WCSRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                                  GDALDataType eBufType,
                                  GSpacing nPixelSpace, GSpacing nLineSpace,
                                  GDALRasterIOExtraArg* psExtraArg)
-    
+
 {
     if( (poODS->nMaxCols > 0 && poODS->nMaxCols < nBufXSize)
         ||  (poODS->nMaxRows > 0 && poODS->nMaxRows < nBufYSize) )
@@ -381,16 +383,16 @@ CPLErr WCSRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 
     if( poODS->TestUseBlockIO( nXOff, nYOff, nXSize, nYSize,
                                nBufXSize,nBufYSize ) )
-        return GDALPamRasterBand::IRasterIO( 
+        return GDALPamRasterBand::IRasterIO(
             eRWFlag, nXOff, nYOff, nXSize, nYSize,
-            pData, nBufXSize, nBufYSize, eBufType, 
+            pData, nBufXSize, nBufYSize, eBufType,
             nPixelSpace, nLineSpace, psExtraArg );
     else
-        return poODS->DirectRasterIO( 
-            eRWFlag, 
-            nXOff * nResFactor, nYOff * nResFactor, 
+        return poODS->DirectRasterIO(
+            eRWFlag,
+            nXOff * nResFactor, nYOff * nResFactor,
             nXSize * nResFactor, nYSize * nResFactor,
-            pData, nBufXSize, nBufYSize, eBufType, 
+            pData, nBufXSize, nBufYSize, eBufType,
             1, &nBand, nPixelSpace, nLineSpace, 0, psExtraArg );
 }
 
@@ -417,8 +419,8 @@ double WCSRasterBand::GetNoDataValue( int *pbSuccess )
 /*                          GetOverviewCount()                          */
 /************************************************************************/
 
-int WCSRasterBand::GetOverviewCount() 
-    
+int WCSRasterBand::GetOverviewCount()
+
 {
     return nOverviewCount;
 }
@@ -427,13 +429,13 @@ int WCSRasterBand::GetOverviewCount()
 /*                            GetOverview()                             */
 /************************************************************************/
 
-GDALRasterBand *WCSRasterBand::GetOverview( int iOverview )
+GDALRasterBand *WCSRasterBand::GetOverview( int iOverviewIn )
 
 {
-    if( iOverview < 0 || iOverview >= nOverviewCount )
+    if( iOverviewIn < 0 || iOverviewIn >= nOverviewCount )
         return NULL;
     else
-        return papoOverviews[iOverview];
+        return papoOverviews[iOverviewIn];
 }
 
 /************************************************************************/
@@ -447,13 +449,11 @@ GDALRasterBand *WCSRasterBand::GetOverview( int iOverview )
 /*                             WCSDataset()                             */
 /************************************************************************/
 
-WCSDataset::WCSDataset()
-
+WCSDataset::WCSDataset() :
+    bServiceDirty(FALSE), psService(NULL), papszSDSModifiers(NULL),
+    nVersion(0), pszProjection(NULL), pabySavedDataBuffer(NULL),
+    papszHttpOptions(NULL), nMaxCols(-1), nMaxRows(-1)
 {
-    psService = NULL;
-    bServiceDirty = FALSE;
-    pszProjection = NULL;
-    
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
@@ -461,16 +461,8 @@ WCSDataset::WCSDataset()
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
 
-    pabySavedDataBuffer = NULL;
-    papszHttpOptions = NULL;
-
-    nMaxCols = -1;
-    nMaxRows = -1;
-
     apszCoverageOfferingMD[0] = NULL;
     apszCoverageOfferingMD[1] = NULL;
-
-    papszSDSModifiers = NULL;
 }
 
 /************************************************************************/
@@ -481,7 +473,7 @@ WCSDataset::~WCSDataset()
 
 {
     // perhaps this should be moved into a FlushCache() method.
-    if( bServiceDirty && !EQUALN(GetDescription(),"<WCS_GDAL>",10) )
+    if( bServiceDirty && !STARTS_WITH_CI(GetDescription(), "<WCS_GDAL>") )
     {
         CPLSerializeXMLTreeToFile( psService, GetDescription() );
         bServiceDirty = FALSE;
@@ -523,7 +515,7 @@ int WCSDataset::TestUseBlockIO( CPL_UNUSED int nXOff,
         bUseBlockedIO = TRUE;
 
     if( bUseBlockedIO
-        && CSLTestBoolean( CPLGetConfigOption( "GDAL_ONE_BIG_READ", "NO") ) )
+        && CPLTestBool( CPLGetConfigOption( "GDAL_ONE_BIG_READ", "NO") ) )
         bUseBlockedIO = FALSE;
 
     return bUseBlockedIO;
@@ -536,7 +528,7 @@ int WCSDataset::TestUseBlockIO( CPL_UNUSED int nXOff,
 CPLErr WCSDataset::IRasterIO( GDALRWFlag eRWFlag,
                               int nXOff, int nYOff, int nXSize, int nYSize,
                               void * pData, int nBufXSize, int nBufYSize,
-                              GDALDataType eBufType, 
+                              GDALDataType eBufType,
                               int nBandCount, int *panBandMap,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
                               GSpacing nBandSpace,
@@ -551,14 +543,14 @@ CPLErr WCSDataset::IRasterIO( GDALRWFlag eRWFlag,
 /*      We need various criteria to skip out to block based methods.    */
 /* -------------------------------------------------------------------- */
     if( TestUseBlockIO( nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize ) )
-        return GDALPamDataset::IRasterIO( 
+        return GDALPamDataset::IRasterIO(
             eRWFlag, nXOff, nYOff, nXSize, nYSize,
-            pData, nBufXSize, nBufYSize, eBufType, 
+            pData, nBufXSize, nBufYSize, eBufType,
             nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace, psExtraArg );
     else
-        return DirectRasterIO( 
+        return DirectRasterIO(
             eRWFlag, nXOff, nYOff, nXSize, nYSize,
-            pData, nBufXSize, nBufYSize, eBufType, 
+            pData, nBufXSize, nBufYSize, eBufType,
             nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace, psExtraArg );
 }
 
@@ -600,7 +592,7 @@ WCSDataset::DirectRasterIO( CPL_UNUSED GDALRWFlag eRWFlag,
         return eErr;
 
 /* -------------------------------------------------------------------- */
-/*      Try and open result as a dataseat.                               */
+/*      Try and open result as a dataset.                               */
 /* -------------------------------------------------------------------- */
     GDALDataset *poTileDS = GDALOpenResult( psResult );
 
@@ -613,13 +605,13 @@ WCSDataset::DirectRasterIO( CPL_UNUSED GDALRWFlag eRWFlag,
     if( poTileDS->GetRasterXSize() != nBufXSize
         || poTileDS->GetRasterYSize() != nBufYSize )
     {
-        CPLDebug( "WCS", "Got size=%dx%d instead of %dx%d.", 
+        CPLDebug( "WCS", "Got size=%dx%d instead of %dx%d.",
                   poTileDS->GetRasterXSize(), poTileDS->GetRasterYSize(),
                   nBufXSize, nBufYSize );
 
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Returned tile does not match expected configuration.\n"
-                  "Got %dx%d instead of %dx%d.", 
+                  "Got %dx%d instead of %dx%d.",
                   poTileDS->GetRasterXSize(), poTileDS->GetRasterYSize(),
                   nBufXSize, nBufYSize );
         delete poTileDS;
@@ -627,24 +619,24 @@ WCSDataset::DirectRasterIO( CPL_UNUSED GDALRWFlag eRWFlag,
     }
 
     if( (strlen(osBandIdentifier) && poTileDS->GetRasterCount() != nBandCount)
-        || (!strlen(osBandIdentifier) && poTileDS->GetRasterCount() != 
+        || (!strlen(osBandIdentifier) && poTileDS->GetRasterCount() !=
             GetRasterCount() ) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Returned tile does not match expected band count." );
         delete poTileDS;
         return CE_Failure;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Pull requested bands from the downloaded dataset.               */
 /* -------------------------------------------------------------------- */
     int iBand;
 
     eErr = CE_None;
-    
-    for( iBand = 0; 
-         iBand < nBandCount && eErr == CE_None; 
+
+    for( iBand = 0;
+         iBand < nBandCount && eErr == CE_None;
          iBand++ )
     {
         GDALRasterBand *poTileBand;
@@ -654,18 +646,18 @@ WCSDataset::DirectRasterIO( CPL_UNUSED GDALRWFlag eRWFlag,
         else
             poTileBand = poTileDS->GetRasterBand( panBandMap[iBand] );
 
-        eErr = poTileBand->RasterIO( GF_Read, 
+        eErr = poTileBand->RasterIO( GF_Read,
                                      0, 0, nBufXSize, nBufYSize,
-                                     ((GByte *) pData) + 
-                                     iBand * nBandSpace, nBufXSize, nBufYSize, 
+                                     ((GByte *) pData) +
+                                     iBand * nBandSpace, nBufXSize, nBufYSize,
                                      eBufType, nPixelSpace, nLineSpace, NULL );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Cleanup                                                         */
 /* -------------------------------------------------------------------- */
     delete poTileDS;
-    
+
     FlushMemoryResult();
 
     return eErr;
@@ -679,7 +671,7 @@ WCSDataset::DirectRasterIO( CPL_UNUSED GDALRWFlag eRWFlag,
 /************************************************************************/
 
 CPLErr WCSDataset::GetCoverage( int nXOff, int nYOff, int nXSize, int nYSize,
-                                int nBufXSize, int nBufYSize, 
+                                int nBufXSize, int nBufYSize,
                                 int nBandCount, int *panBandList,
                                 CPLHTTPResult **ppsResult )
 
@@ -688,15 +680,15 @@ CPLErr WCSDataset::GetCoverage( int nXOff, int nYOff, int nXSize, int nYSize,
 /*      Figure out the georeferenced extents.                           */
 /* -------------------------------------------------------------------- */
     double dfMinX, dfMaxX, dfMinY, dfMaxY;
-    
+
     // WCS 1.0 extents are the outer edges of outer pixels.
-    dfMinX = adfGeoTransform[0] + 
+    dfMinX = adfGeoTransform[0] +
         (nXOff) * adfGeoTransform[1];
-    dfMaxX = adfGeoTransform[0] + 
+    dfMaxX = adfGeoTransform[0] +
         (nXOff + nXSize) * adfGeoTransform[1];
-    dfMaxY = adfGeoTransform[3] + 
+    dfMaxY = adfGeoTransform[3] +
         (nYOff) * adfGeoTransform[5];
-    dfMinY = adfGeoTransform[3] + 
+    dfMinY = adfGeoTransform[3] +
         (nYOff + nYSize) * adfGeoTransform[5];
 
 /* -------------------------------------------------------------------- */
@@ -704,7 +696,7 @@ CPLErr WCSDataset::GetCoverage( int nXOff, int nYOff, int nXSize, int nYSize,
 /* -------------------------------------------------------------------- */
     CPLString osBandList;
     int       bSelectingBands = FALSE;
-    
+
     if( strlen(osBandIdentifier) && nBandCount > 0 )
     {
         int iBand;
@@ -723,27 +715,27 @@ CPLErr WCSDataset::GetCoverage( int nXOff, int nYOff, int nXSize, int nYSize,
 /*      URL encode strings that could have questionable characters.     */
 /* -------------------------------------------------------------------- */
     CPLString osCoverage, osFormat;
-    char *pszEncoded; 
+    char *pszEncoded;
 
     osCoverage = CPLGetXMLValue( psService, "CoverageName", "" );
 
     pszEncoded = CPLEscapeString( osCoverage, -1, CPLES_URL );
     osCoverage = pszEncoded;
     CPLFree( pszEncoded );
-    
+
     osFormat = CPLGetXMLValue( psService, "PreferredFormat", "" );
 
     pszEncoded = CPLEscapeString( osFormat, -1, CPLES_URL );
     osFormat = pszEncoded;
     CPLFree( pszEncoded );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Do we have a time we want to use?                               */
 /* -------------------------------------------------------------------- */
     CPLString osTime;
 
     osTime = CSLFetchNameValueDef( papszSDSModifiers, "time", osDefaultTime );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Construct a "simple" GetCoverage request (WCS 1.0).		*/
 /* -------------------------------------------------------------------- */
@@ -751,17 +743,17 @@ CPLErr WCSDataset::GetCoverage( int nXOff, int nYOff, int nXSize, int nYSize,
 
     if( nVersion == 100 )
     {
-        osRequest.Printf( 
+        osRequest.Printf(
             "%sSERVICE=WCS&VERSION=1.0.0&REQUEST=GetCoverage&COVERAGE=%s"
             "&FORMAT=%s&BBOX=%.15g,%.15g,%.15g,%.15g&WIDTH=%d&HEIGHT=%d&CRS=%s%s",
             CPLGetXMLValue( psService, "ServiceURL", "" ),
             osCoverage.c_str(),
             osFormat.c_str(),
             dfMinX, dfMinY, dfMaxX, dfMaxY,
-            nBufXSize, nBufYSize, 
+            nBufXSize, nBufYSize,
             osCRS.c_str(),
             CPLGetXMLValue( psService, "GetCoverageExtra", "" ) );
- 
+
         if( CPLGetXMLValue( psService, "Resample", NULL ) )
         {
             osRequest += "&INTERPOLATION=";
@@ -776,7 +768,7 @@ CPLErr WCSDataset::GetCoverage( int nXOff, int nYOff, int nXSize, int nYSize,
 
         if( bSelectingBands )
         {
-            osRequest += CPLString().Printf( "&%s=%s", 
+            osRequest += CPLString().Printf( "&%s=%s",
                                              osBandIdentifier.c_str(),
                                              osBandList.c_str() );
         }
@@ -789,9 +781,9 @@ CPLErr WCSDataset::GetCoverage( int nXOff, int nYOff, int nXSize, int nYSize,
     {
         CPLString osRangeSubset;
 
-        osRangeSubset.Printf("&RangeSubset=%s", 
+        osRangeSubset.Printf("&RangeSubset=%s",
                              CPLGetXMLValue(psService,"FieldName",""));
-        
+
         if( CPLGetXMLValue( psService, "Resample", NULL ) )
         {
             osRangeSubset += ":";
@@ -800,9 +792,9 @@ CPLErr WCSDataset::GetCoverage( int nXOff, int nYOff, int nXSize, int nYSize,
 
         if( bSelectingBands )
         {
-            osRangeSubset += 
+            osRangeSubset +=
                 CPLString().Printf( "[%s[%s]]",
-                                    osBandIdentifier.c_str(), 
+                                    osBandIdentifier.c_str(),
                                     osBandList.c_str() );
         }
 
@@ -812,7 +804,7 @@ CPLErr WCSDataset::GetCoverage( int nXOff, int nYOff, int nXSize, int nYSize,
         dfMinY -= adfGeoTransform[5] * 0.5;
         dfMaxY += adfGeoTransform[5] * 0.5;
 
-        // Carefully adjust bounds for pixel centered values at new 
+        // Carefully adjust bounds for pixel centered values at new
         // sampling density.
 
         double dfXStep = adfGeoTransform[1];
@@ -822,17 +814,17 @@ CPLErr WCSDataset::GetCoverage( int nXOff, int nYOff, int nXSize, int nYSize,
         {
             dfXStep = (nXSize/(double)nBufXSize) * adfGeoTransform[1];
             dfYStep = (nYSize/(double)nBufYSize) * adfGeoTransform[5];
-            
-            dfMinX  = nXOff * adfGeoTransform[1] + adfGeoTransform[0] 
+
+            dfMinX  = nXOff * adfGeoTransform[1] + adfGeoTransform[0]
                     + dfXStep * 0.5;
             dfMaxX  = dfMinX + (nBufXSize - 1) * dfXStep;
 
-            dfMaxY  = nYOff * adfGeoTransform[5] + adfGeoTransform[3] 
+            dfMaxY  = nYOff * adfGeoTransform[5] + adfGeoTransform[3]
                     + dfYStep * 0.5;
             dfMinY  = dfMaxY + (nBufYSize - 1) * dfYStep;
         }
 
-        osRequest.Printf( 
+        osRequest.Printf(
             "%sSERVICE=WCS&VERSION=%s&REQUEST=GetCoverage&IDENTIFIER=%s"
             "&FORMAT=%s&BOUNDINGBOX=%.15g,%.15g,%.15g,%.15g,%s%s%s",
             CPLGetXMLValue( psService, "ServiceURL", "" ),
@@ -846,14 +838,14 @@ CPLErr WCSDataset::GetCoverage( int nXOff, int nYOff, int nXSize, int nYSize,
 
         if( nBufXSize != nXSize || nBufYSize != nYSize )
         {
-            osRequest += CPLString().Printf( 
+            osRequest += CPLString().Printf(
                 "&GridBaseCRS=%s"
                 "&GridCS=%s"
                 "&GridType=urn:ogc:def:method:WCS:1.1:2dGridIn2dCrs"
                 "&GridOrigin=%.15g,%.15g"
                 "&GridOffsets=%.15g,%.15g",
-                osCRS.c_str(), 
-                osCRS.c_str(), 
+                osCRS.c_str(),
+                osCRS.c_str(),
                 dfMinX, dfMaxY,
                 dfXStep, dfYStep );
         }
@@ -888,27 +880,27 @@ int WCSDataset::DescribeCoverage()
 /*      Fetch coverage description for this coverage.                   */
 /* -------------------------------------------------------------------- */
     if( nVersion == 100 )
-        osRequest.Printf( 
-            "%sSERVICE=WCS&REQUEST=DescribeCoverage&VERSION=%s&COVERAGE=%s%s", 
+        osRequest.Printf(
+            "%sSERVICE=WCS&REQUEST=DescribeCoverage&VERSION=%s&COVERAGE=%s%s",
             CPLGetXMLValue( psService, "ServiceURL", "" ),
             CPLGetXMLValue( psService, "Version", "1.0.0" ),
             CPLGetXMLValue( psService, "CoverageName", "" ),
             CPLGetXMLValue( psService, "DescribeCoverageExtra", "" ) );
     else
-        osRequest.Printf( 
-            "%sSERVICE=WCS&REQUEST=DescribeCoverage&VERSION=%s&IDENTIFIERS=%s%s&FORMAT=text/xml", 
+        osRequest.Printf(
+            "%sSERVICE=WCS&REQUEST=DescribeCoverage&VERSION=%s&IDENTIFIERS=%s%s&FORMAT=text/xml",
             CPLGetXMLValue( psService, "ServiceURL", "" ),
             CPLGetXMLValue( psService, "Version", "1.0.0" ),
             CPLGetXMLValue( psService, "CoverageName", "" ),
             CPLGetXMLValue( psService, "DescribeCoverageExtra", "" ) );
 
     CPLErrorReset();
-    
+
     CPLHTTPResult *psResult = CPLHTTPFetch( osRequest, papszHttpOptions );
 
     if( ProcessError( psResult ) )
         return FALSE;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Parse result.                                                   */
 /* -------------------------------------------------------------------- */
@@ -934,8 +926,8 @@ int WCSDataset::DescribeCoverage()
     {
         CPLDestroyXMLNode( psDC );
 
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Failed to fetch a <CoverageOffering> back %s.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Failed to fetch a <CoverageOffering> back %s.",
                   osRequest.c_str() );
         return FALSE;
     }
@@ -945,7 +937,7 @@ int WCSDataset::DescribeCoverage()
 /* -------------------------------------------------------------------- */
     CPLXMLNode *psNext = psCO->psNext;
     psCO->psNext = NULL;
-    
+
     CPLAddXMLChild( psService, CPLCloneXMLTree( psCO ) );
     bServiceDirty = TRUE;
 
@@ -979,12 +971,12 @@ int WCSDataset::ExtractGridInfo100()
 /* -------------------------------------------------------------------- */
 /*      Verify we have a Rectified Grid.                                */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psRG = 
+    CPLXMLNode *psRG =
         CPLGetXMLNode( psCO, "domainSet.spatialDomain.RectifiedGrid" );
 
     if( psRG == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to find RectifiedGrid in CoverageOffering,\n"
                   "unable to process WCS Coverage." );
         return FALSE;
@@ -993,54 +985,54 @@ int WCSDataset::ExtractGridInfo100()
 /* -------------------------------------------------------------------- */
 /*      Extract size, geotransform and coordinate system.               */
 /* -------------------------------------------------------------------- */
-    if( GDALParseGMLCoverage( psRG, &nRasterXSize, &nRasterYSize, 
+    if( GDALParseGMLCoverage( psRG, &nRasterXSize, &nRasterYSize,
                               adfGeoTransform, &pszProjection ) != CE_None )
         return FALSE;
 
 /* -------------------------------------------------------------------- */
 /*      Fallback to nativeCRSs declaration.                             */
 /* -------------------------------------------------------------------- */
-    const char *pszNativeCRSs = 
+    const char *pszNativeCRSs =
         CPLGetXMLValue( psCO, "supportedCRSs.nativeCRSs", NULL );
 
     if( pszNativeCRSs == NULL )
-        pszNativeCRSs = 
+        pszNativeCRSs =
             CPLGetXMLValue( psCO, "supportedCRSs.requestResponseCRSs", NULL );
 
     if( pszNativeCRSs == NULL )
-        pszNativeCRSs = 
+        pszNativeCRSs =
             CPLGetXMLValue( psCO, "supportedCRSs.requestCRSs", NULL );
 
     if( pszNativeCRSs == NULL )
-        pszNativeCRSs = 
+        pszNativeCRSs =
             CPLGetXMLValue( psCO, "supportedCRSs.responseCRSs", NULL );
 
-    if( pszNativeCRSs != NULL  
+    if( pszNativeCRSs != NULL
         && (pszProjection == NULL || strlen(pszProjection) == 0) )
     {
         OGRSpatialReference oSRS;
-        
+
         if( oSRS.SetFromUserInput( pszNativeCRSs ) == OGRERR_NONE )
         {
             CPLFree( pszProjection );
             oSRS.exportToWkt( &pszProjection );
         }
         else
-            CPLDebug( "WCS", 
-                      "<nativeCRSs> element contents not parsable:\n%s", 
+            CPLDebug( "WCS",
+                      "<nativeCRSs> element contents not parsable:\n%s",
                       pszNativeCRSs );
     }
 
     // We should try to use the services name for the CRS if possible.
     if( pszNativeCRSs != NULL
-        && ( EQUALN(pszNativeCRSs,"EPSG:",5)
-             || EQUALN(pszNativeCRSs,"AUTO:",5)
-             || EQUALN(pszNativeCRSs,"Image ",6)
-             || EQUALN(pszNativeCRSs,"Engineering ",12)
-             || EQUALN(pszNativeCRSs,"OGC:",4) ) )
+        && ( STARTS_WITH_CI(pszNativeCRSs, "EPSG:")
+             || STARTS_WITH_CI(pszNativeCRSs, "AUTO:")
+             || STARTS_WITH_CI(pszNativeCRSs, "Image ")
+             || STARTS_WITH_CI(pszNativeCRSs, "Engineering ")
+             || STARTS_WITH_CI(pszNativeCRSs, "OGC:") ) )
     {
         osCRS = pszNativeCRSs;
-        
+
         size_t nDivider = osCRS.find( " " );
 
         if( nDivider != std::string::npos )
@@ -1051,15 +1043,15 @@ int WCSDataset::ExtractGridInfo100()
 /*      Do we have a coordinate system override?                        */
 /* -------------------------------------------------------------------- */
     const char *pszProjOverride = CPLGetXMLValue( psService, "SRS", NULL );
-    
+
     if( pszProjOverride )
     {
         OGRSpatialReference oSRS;
-        
+
         if( oSRS.SetFromUserInput( pszProjOverride ) != OGRERR_NONE )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "<SRS> element contents not parsable:\n%s", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "<SRS> element contents not parsable:\n%s",
                       pszProjOverride );
             return FALSE;
         }
@@ -1067,11 +1059,11 @@ int WCSDataset::ExtractGridInfo100()
         CPLFree( pszProjection );
         oSRS.exportToWkt( &pszProjection );
 
-        if( EQUALN(pszProjOverride,"EPSG:",5)
-            || EQUALN(pszProjOverride,"AUTO:",5)
-            || EQUALN(pszProjOverride,"OGC:",4)
-            || EQUALN(pszProjOverride,"Image ",6)
-            || EQUALN(pszProjOverride,"Engineering ",12) )
+        if( STARTS_WITH_CI(pszProjOverride, "EPSG:")
+            || STARTS_WITH_CI(pszProjOverride, "AUTO:")
+            || STARTS_WITH_CI(pszProjOverride, "OGC:")
+            || STARTS_WITH_CI(pszProjOverride, "Image ")
+            || STARTS_WITH_CI(pszProjOverride, "Engineering ") )
             osCRS = pszProjOverride;
     }
 
@@ -1085,7 +1077,7 @@ int WCSDataset::ExtractGridInfo100()
     {
         oSRS.SetFromUserInput( pszProjection );
         pszAuth = oSRS.GetAuthorityName(NULL);
-    
+
         if( pszAuth != NULL && EQUAL(pszAuth,"EPSG") )
         {
             pszAuth = oSRS.GetAuthorityCode(NULL);
@@ -1128,42 +1120,42 @@ int WCSDataset::ExtractGridInfo100()
 
         for( psNode = psSF->psChild; psNode != NULL; psNode = psNode->psNext )
         {
-            if( psNode->eType == CXT_Element 
-                && EQUAL(psNode->pszValue,"formats") 
-                && psNode->psChild != NULL 
+            if( psNode->eType == CXT_Element
+                && EQUAL(psNode->pszValue,"formats")
+                && psNode->psChild != NULL
                 && psNode->psChild->eType == CXT_Text )
             {
                 // This check is looking for deprecated WCS 1.0 capabilities
                 // with multiple formats space delimited in a single <formats>
                 // element per GDAL ticket 1748 (done by MapServer 4.10 and
-                // earlier for instance). 
+                // earlier for instance).
                 if( papszFormatList == NULL
                     && psNode->psNext == NULL
                     && strstr(psNode->psChild->pszValue," ") != NULL
                     && strstr(psNode->psChild->pszValue,";") == NULL )
                 {
-                    char **papszSubList = 
+                    char **papszSubList =
                         CSLTokenizeString( psNode->psChild->pszValue );
-                    papszFormatList = CSLInsertStrings( papszFormatList, 
+                    papszFormatList = CSLInsertStrings( papszFormatList,
                                                         -1, papszSubList );
                     CSLDestroy( papszSubList );
                 }
                 else
                 {
-                    papszFormatList = CSLAddString( papszFormatList, 
+                    papszFormatList = CSLAddString( papszFormatList,
                                                     psNode->psChild->pszValue);
                 }
             }
         }
-        
-        for( iFormat = 0; 
+
+        for( iFormat = 0;
              papszFormatList != NULL && papszFormatList[iFormat] != NULL;
              iFormat++ )
         {
             if( strlen(osPreferredFormat) == 0 )
                 osPreferredFormat = papszFormatList[iFormat];
-            
-            if( strstr(papszFormatList[iFormat],"tiff") != NULL 
+
+            if( strstr(papszFormatList[iFormat],"tiff") != NULL
                     || strstr(papszFormatList[iFormat],"TIFF") != NULL
                     || strstr(papszFormatList[iFormat],"Tiff") != NULL )
             {
@@ -1177,7 +1169,7 @@ int WCSDataset::ExtractGridInfo100()
         if( strlen(osPreferredFormat) > 0 )
         {
             bServiceDirty = TRUE;
-            CPLCreateXMLElementAndValue( psService, "PreferredFormat", 
+            CPLCreateXMLElementAndValue( psService, "PreferredFormat",
                                          osPreferredFormat );
         }
     }
@@ -1189,11 +1181,11 @@ int WCSDataset::ExtractGridInfo100()
     if( CPLGetXMLValue( psService, "NoDataValue", NULL ) == NULL )
     {
         const char *pszSV = CPLGetXMLValue( psCO, "rangeSet.RangeSet.nullValues.singleValue", NULL );
-        
+
         if( pszSV != NULL && (CPLAtof(pszSV) != 0.0 || *pszSV == '0') )
         {
             bServiceDirty = TRUE;
-            CPLCreateXMLElementAndValue( psService, "NoDataValue", 
+            CPLCreateXMLElementAndValue( psService, "NoDataValue",
                                          pszSV );
         }
     }
@@ -1204,13 +1196,13 @@ int WCSDataset::ExtractGridInfo100()
 /*      "Band", with a set of ascending numerical values.               */
 /* -------------------------------------------------------------------- */
     osBandIdentifier = CPLGetXMLValue( psService, "BandIdentifier", "" );
-    CPLXMLNode * psAD = CPLGetXMLNode( psService, 
+    CPLXMLNode * psAD = CPLGetXMLNode( psService,
       "CoverageOffering.rangeSet.RangeSet.axisDescription.AxisDescription" );
     CPLXMLNode *psValues;
 
     if( strlen(osBandIdentifier) == 0
-        && psAD != NULL 
-        && (EQUAL(CPLGetXMLValue(psAD,"name",""),"Band") 
+        && psAD != NULL
+        && (EQUAL(CPLGetXMLValue(psAD,"name",""),"Band")
             || EQUAL(CPLGetXMLValue(psAD,"name",""),"Bands"))
         && ( (psValues = CPLGetXMLNode( psAD, "values" )) != NULL ) )
     {
@@ -1219,12 +1211,12 @@ int WCSDataset::ExtractGridInfo100()
 
         osBandIdentifier = CPLGetXMLValue(psAD,"name","");
 
-        for( psSV = psValues->psChild, iBand = 1; 
-             psSV != NULL; 
+        for( psSV = psValues->psChild, iBand = 1;
+             psSV != NULL;
              psSV = psSV->psNext, iBand++ )
         {
-            if( psSV->eType != CXT_Element 
-                || !EQUAL(psSV->pszValue,"singleValue") 
+            if( psSV->eType != CXT_Element
+                || !EQUAL(psSV->pszValue,"singleValue")
                 || psSV->psChild == NULL
                 || psSV->psChild->eType != CXT_Text
                 || atoi(psSV->psChild->pszValue) != iBand )
@@ -1237,7 +1229,7 @@ int WCSDataset::ExtractGridInfo100()
         if( strlen(osBandIdentifier) )
         {
             bServiceDirty = TRUE;
-            CPLCreateXMLElementAndValue( psService, "BandIdentifier", 
+            CPLCreateXMLElementAndValue( psService, "BandIdentifier",
                                          osBandIdentifier );
         }
     }
@@ -1247,7 +1239,7 @@ int WCSDataset::ExtractGridInfo100()
 /*      default time value.                                             */
 /* -------------------------------------------------------------------- */
     osDefaultTime = CPLGetXMLValue( psService, "DefaultTime", "" );
-    CPLXMLNode * psTD = 
+    CPLXMLNode * psTD =
         CPLGetXMLNode( psService, "CoverageOffering.domainSet.temporalDomain" );
     CPLString osServiceURL = CPLGetXMLValue( psService, "ServiceURL", "" );
     CPLString osCoverageExtra = CPLGetXMLValue( psService, "GetCoverageExtra", "" );
@@ -1268,8 +1260,8 @@ int WCSDataset::ExtractGridInfo100()
         }
 
         // we will default to the last - likely the most recent - entry.
-        
-        if( aosTimePositions.size() > 0 
+
+        if( aosTimePositions.size() > 0
             && osDefaultTime == ""
             && osServiceURL.ifind("time=") == std::string::npos
             && osCoverageExtra.ifind("time=") == std::string::npos )
@@ -1277,7 +1269,7 @@ int WCSDataset::ExtractGridInfo100()
             osDefaultTime = aosTimePositions[aosTimePositions.size()-1];
 
             bServiceDirty = TRUE;
-            CPLCreateXMLElementAndValue( psService, "DefaultTime", 
+            CPLCreateXMLElementAndValue( psService, "DefaultTime",
                                          osDefaultTime );
         }
     }
@@ -1289,8 +1281,8 @@ int WCSDataset::ExtractGridInfo100()
 /*                          ParseBoundingBox()                          */
 /************************************************************************/
 
-static int ParseBoundingBox( CPLXMLNode *psBoundingBox, CPLString &osCRS, 
-                             double &dfLowerX, double &dfLowerY, 
+static int ParseBoundingBox( CPLXMLNode *psBoundingBox, CPLString &osCRS,
+                             double &dfLowerX, double &dfLowerY,
                              double &dfUpperX, double &dfUpperY )
 
 {
@@ -1298,10 +1290,10 @@ static int ParseBoundingBox( CPLXMLNode *psBoundingBox, CPLString &osCRS,
 
     osCRS = CPLGetXMLValue( psBoundingBox, "crs", "" );
 
-    char **papszLC = CSLTokenizeStringComplex( 
+    char **papszLC = CSLTokenizeStringComplex(
         CPLGetXMLValue( psBoundingBox, "LowerCorner", ""),
         " ", FALSE, FALSE );
-    char **papszUC = CSLTokenizeStringComplex( 
+    char **papszUC = CSLTokenizeStringComplex(
         CPLGetXMLValue( psBoundingBox, "UpperCorner", ""),
         " ", FALSE, FALSE );
 
@@ -1314,7 +1306,7 @@ static int ParseBoundingBox( CPLXMLNode *psBoundingBox, CPLString &osCRS,
     }
     else
         nRet = FALSE;
-    
+
     CSLDestroy( papszUC );
     CSLDestroy( papszLC );
 
@@ -1348,14 +1340,14 @@ int WCSDataset::ExtractGridInfo()
 /* -------------------------------------------------------------------- */
 /*      Verify we have a SpatialDomain and GridCRS.                     */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psSD = 
+    CPLXMLNode *psSD =
         CPLGetXMLNode( psCO, "Domain.SpatialDomain" );
-    CPLXMLNode *psGCRS = 
+    CPLXMLNode *psGCRS =
         CPLGetXMLNode( psSD, "GridCRS" );
 
     if( psSD == NULL || psGCRS == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to find GridCRS in CoverageDescription,\n"
                   "unable to process WCS Coverage." );
         return FALSE;
@@ -1367,14 +1359,14 @@ int WCSDataset::ExtractGridInfo()
     const char *pszGridType = CPLGetXMLValue( psGCRS, "GridType",
                                               "urn:ogc:def:method:WCS::2dSimpleGrid" );
 
-    char **papszOriginTokens = 
+    char **papszOriginTokens =
         CSLTokenizeStringComplex( CPLGetXMLValue( psGCRS, "GridOrigin", ""),
                                   " ", FALSE, FALSE );
-    char **papszOffsetTokens = 
+    char **papszOffsetTokens =
         CSLTokenizeStringComplex( CPLGetXMLValue( psGCRS, "GridOffsets", ""),
                                   " ", FALSE, FALSE );
 
-    if( strstr(pszGridType,":2dGridIn2dCrs") 
+    if( strstr(pszGridType,":2dGridIn2dCrs")
         || strstr(pszGridType,":2dGridin2dCrs") )
     {
         if( CSLCount(papszOffsetTokens) == 4
@@ -1389,9 +1381,11 @@ int WCSDataset::ExtractGridInfo()
         }
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "2dGridIn2dCrs does not have expected GridOrigin or\n"
                       "GridOffsets values - unable to process WCS coverage.");
+            CSLDestroy( papszOffsetTokens );
+            CSLDestroy( papszOriginTokens );
             return FALSE;
         }
     }
@@ -1410,13 +1404,15 @@ int WCSDataset::ExtractGridInfo()
         }
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "2dGridIn3dCrs does not have expected GridOrigin or\n"
                       "GridOffsets values - unable to process WCS coverage.");
+            CSLDestroy( papszOffsetTokens );
+            CSLDestroy( papszOriginTokens );
             return FALSE;
         }
     }
-    
+
     else if( strstr(pszGridType,":2dSimpleGrid") )
     {
         if( CSLCount(papszOffsetTokens) == 2
@@ -1431,35 +1427,39 @@ int WCSDataset::ExtractGridInfo()
         }
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "2dSimpleGrid does not have expected GridOrigin or\n"
                       "GridOffsets values - unable to process WCS coverage.");
+            CSLDestroy( papszOffsetTokens );
+            CSLDestroy( papszOriginTokens );
             return FALSE;
         }
     }
 
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Unrecognised GridCRS.GridType value '%s',\n"
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Unrecognized GridCRS.GridType value '%s',\n"
                   "unable to process WCS coverage.",
                   pszGridType );
+        CSLDestroy( papszOffsetTokens );
+        CSLDestroy( papszOriginTokens );
         return FALSE;
     }
 
     CSLDestroy( papszOffsetTokens );
     CSLDestroy( papszOriginTokens );
 
-    // GridOrigin is center of pixel ... offset half pixel to adjust. 
+    // GridOrigin is center of pixel ... offset half pixel to adjust.
 
-    adfGeoTransform[0] -= (adfGeoTransform[1]+adfGeoTransform[2]) * 0.5; 
-    adfGeoTransform[3] -= (adfGeoTransform[4]+adfGeoTransform[5]) * 0.5; 
+    adfGeoTransform[0] -= (adfGeoTransform[1]+adfGeoTransform[2]) * 0.5;
+    adfGeoTransform[3] -= (adfGeoTransform[4]+adfGeoTransform[5]) * 0.5;
 
 /* -------------------------------------------------------------------- */
 /*      Establish our coordinate system.                                */
 /* -------------------------------------------------------------------- */
     osCRS = CPLGetXMLValue( psGCRS, "GridBaseCRS", "" );
-    
+
     if( strlen(osCRS) == 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -1481,7 +1481,7 @@ int WCSDataset::ExtractGridInfo()
         else
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "Unable to interprete GridBaseCRS '%s'.",
+                      "Unable to interpret GridBaseCRS '%s'.",
                       osCRS.c_str() );
             return FALSE;
         }
@@ -1494,7 +1494,7 @@ int WCSDataset::ExtractGridInfo()
 
     nRasterXSize = -1;
     nRasterYSize = -1;
-    for( psNode = psSD->psChild; 
+    for( psNode = psSD->psChild;
          psNode != NULL && nRasterXSize == -1;
          psNode = psNode->psNext )
     {
@@ -1506,7 +1506,7 @@ int WCSDataset::ExtractGridInfo()
         CPLString osBBCRS;
 
         if( ParseBoundingBox( psNode, osBBCRS, dfLX, dfLY, dfUX, dfUY )
-            && strstr(osBBCRS,":imageCRS") 
+            && strstr(osBBCRS,":imageCRS")
             && dfLX == 0 && dfLY == 0 )
         {
             nRasterXSize = (int) (dfUX + 1.01);
@@ -1518,7 +1518,7 @@ int WCSDataset::ExtractGridInfo()
 /*      Otherwise we search for a bounding box in our coordinate        */
 /*      system and derive the size from that.                           */
 /* -------------------------------------------------------------------- */
-    for( psNode = psSD->psChild; 
+    for( psNode = psSD->psChild;
          psNode != NULL && nRasterXSize == -1;
          psNode = psNode->psNext )
     {
@@ -1534,9 +1534,9 @@ int WCSDataset::ExtractGridInfo()
             && adfGeoTransform[2] == 0.0
             && adfGeoTransform[4] == 0.0 )
         {
-            nRasterXSize = 
+            nRasterXSize =
                 (int) ((dfUX - dfLX) / adfGeoTransform[1] + 1.01);
-            nRasterYSize = 
+            nRasterYSize =
                 (int) ((dfUY - dfLY) / fabs(adfGeoTransform[5]) + 1.01);
         }
     }
@@ -1545,15 +1545,15 @@ int WCSDataset::ExtractGridInfo()
 /*      Do we have a coordinate system override?                        */
 /* -------------------------------------------------------------------- */
     const char *pszProjOverride = CPLGetXMLValue( psService, "SRS", NULL );
-    
+
     if( pszProjOverride )
     {
         OGRSpatialReference oSRS;
-        
+
         if( oSRS.SetFromUserInput( pszProjOverride ) != OGRERR_NONE )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "<SRS> element contents not parsable:\n%s", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "<SRS> element contents not parsable:\n%s",
                       pszProjOverride );
             return FALSE;
         }
@@ -1571,20 +1571,19 @@ int WCSDataset::ExtractGridInfo()
 /* -------------------------------------------------------------------- */
     if( CPLGetXMLValue( psService, "PreferredFormat", NULL ) == NULL )
     {
-        CPLXMLNode *psNode;
         CPLString osPreferredFormat;
 
         for( psNode = psCO->psChild; psNode != NULL; psNode = psNode->psNext )
         {
-            if( psNode->eType == CXT_Element 
-                && EQUAL(psNode->pszValue,"SupportedFormat") 
+            if( psNode->eType == CXT_Element
+                && EQUAL(psNode->pszValue,"SupportedFormat")
                 && psNode->psChild
                 && psNode->psChild->eType == CXT_Text )
             {
                 if( strlen(osPreferredFormat) == 0 )
                     osPreferredFormat = psNode->psChild->pszValue;
 
-                if( strstr(psNode->psChild->pszValue,"tiff") != NULL 
+                if( strstr(psNode->psChild->pszValue,"tiff") != NULL
                     || strstr(psNode->psChild->pszValue,"TIFF") != NULL
                     || strstr(psNode->psChild->pszValue,"Tiff") != NULL )
                 {
@@ -1597,7 +1596,7 @@ int WCSDataset::ExtractGridInfo()
         if( strlen(osPreferredFormat) > 0 )
         {
             bServiceDirty = TRUE;
-            CPLCreateXMLElementAndValue( psService, "PreferredFormat", 
+            CPLCreateXMLElementAndValue( psService, "PreferredFormat",
                                          osPreferredFormat );
         }
     }
@@ -1608,13 +1607,13 @@ int WCSDataset::ExtractGridInfo()
 /* -------------------------------------------------------------------- */
     if( CPLGetXMLValue( psService, "NoDataValue", NULL ) == NULL )
     {
-        const char *pszSV = 
+        const char *pszSV =
             CPLGetXMLValue( psCO, "Range.Field.NullValue", NULL );
-        
+
         if( pszSV != NULL && (CPLAtof(pszSV) != 0.0 || *pszSV == '0') )
         {
             bServiceDirty = TRUE;
-            CPLCreateXMLElementAndValue( psService, "NoDataValue", 
+            CPLCreateXMLElementAndValue( psService, "NoDataValue",
                                          pszSV );
         }
     }
@@ -1624,13 +1623,13 @@ int WCSDataset::ExtractGridInfo()
 /* -------------------------------------------------------------------- */
     if( CPLGetXMLValue( psService, "FieldName", NULL ) == NULL )
     {
-        CPLString osFieldName = 
+        CPLString osFieldName =
             CPLGetXMLValue( psCO, "Range.Field.Identifier", "" );
-        
+
         if( strlen(osFieldName) > 0 )
         {
             bServiceDirty = TRUE;
-            CPLCreateXMLElementAndValue( psService, "FieldName", 
+            CPLCreateXMLElementAndValue( psService, "FieldName",
                                          osFieldName );
         }
         else
@@ -1646,7 +1645,7 @@ int WCSDataset::ExtractGridInfo()
 /*      Do we have a "Band" axis?  If so try to grab the bandcount      */
 /*      and data type from it.                                          */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode * psAxis = CPLGetXMLNode( 
+    CPLXMLNode * psAxis = CPLGetXMLNode(
         psService, "CoverageDescription.Range.Field.Axis" );
 
     if( (EQUAL(CPLGetXMLValue(psAxis,"Identifier",""),"Band")
@@ -1654,18 +1653,18 @@ int WCSDataset::ExtractGridInfo()
         && CPLGetXMLNode(psAxis,"AvailableKeys") != NULL )
     {
         osBandIdentifier = CPLGetXMLValue(psAxis,"Identifier","");
-        
+
         // verify keys are ascending starting at 1
         CPLXMLNode *psValues = CPLGetXMLNode(psAxis,"AvailableKeys");
         CPLXMLNode *psSV;
         int iBand;
-        
-        for( psSV = psValues->psChild, iBand = 1; 
-             psSV != NULL; 
+
+        for( psSV = psValues->psChild, iBand = 1;
+             psSV != NULL;
              psSV = psSV->psNext, iBand++ )
         {
-            if( psSV->eType != CXT_Element 
-                || !EQUAL(psSV->pszValue,"Key") 
+            if( psSV->eType != CXT_Element
+                || !EQUAL(psSV->pszValue,"Key")
                 || psSV->psChild == NULL
                 || psSV->psChild->eType != CXT_Text
                 || atoi(psSV->psChild->pszValue) != iBand )
@@ -1674,22 +1673,22 @@ int WCSDataset::ExtractGridInfo()
                 break;
             }
         }
-        
+
         if( strlen(osBandIdentifier) )
         {
             bServiceDirty = TRUE;
             if( CPLGetXMLValue(psService,"BandIdentifier",NULL) == NULL )
-                CPLCreateXMLElementAndValue( psService, "BandIdentifier", 
+                CPLCreateXMLElementAndValue( psService, "BandIdentifier",
                                              osBandIdentifier );
 
             if( CPLGetXMLValue(psService,"BandCount",NULL) == NULL )
-                CPLCreateXMLElementAndValue( psService, "BandCount", 
+                CPLCreateXMLElementAndValue( psService, "BandCount",
                                              CPLString().Printf("%d",iBand-1));
         }
 
         // Is this an ESRI server returning a GDAL recognised data type?
         CPLString osDataType = CPLGetXMLValue( psAxis, "DataType", "" );
-        if( GDALGetDataTypeByName(osDataType) != GDT_Unknown 
+        if( GDALGetDataTypeByName(osDataType) != GDT_Unknown
             && CPLGetXMLValue(psService,"BandType",NULL) == NULL )
         {
             bServiceDirty = TRUE;
@@ -1726,7 +1725,7 @@ int WCSDataset::ProcessError( CPLHTTPResult *psResult )
 /*      message and report it verbatim up to a certain size limit.      */
 /* -------------------------------------------------------------------- */
 
-    if( psResult->pszContentType != NULL 
+    if( psResult->pszContentType != NULL
         && strstr(psResult->pszContentType, "html") != NULL )
     {
         CPLString osErrorMsg = (char *) psResult->pabyData;
@@ -1734,8 +1733,8 @@ int WCSDataset::ProcessError( CPLHTTPResult *psResult )
         if( osErrorMsg.size() > 2048 )
             osErrorMsg.resize( 2048 );
 
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Malformed Result:\n%s", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Malformed Result:\n%s",
                   osErrorMsg.c_str() );
         CPLHTTPDestroyResult( psResult );
         return TRUE;
@@ -1746,10 +1745,10 @@ int WCSDataset::ProcessError( CPLHTTPResult *psResult )
 /*      check based on the Content-type, but this seems quite           */
 /*      undependable, even from MapServer!                              */
 /* -------------------------------------------------------------------- */
-    if( strstr((const char *)psResult->pabyData, "ServiceException") 
+    if( strstr((const char *)psResult->pabyData, "ServiceException")
         || strstr((const char *)psResult->pabyData, "ExceptionReport") )
     {
-        CPLXMLNode *psTree = CPLParseXMLString( (const char *) 
+        CPLXMLNode *psTree = CPLParseXMLString( (const char *)
                                                 psResult->pabyData );
         const char *pszMsg = NULL;
 
@@ -1767,13 +1766,13 @@ int WCSDataset::ProcessError( CPLHTTPResult *psResult )
                                     NULL );
 
         if( pszMsg )
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "%s", pszMsg );
         else
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Corrupt Service Exception:\n%s",
                       (const char *) psResult->pabyData );
-        
+
         CPLDestroyXMLNode( psTree );
         CPLHTTPDestroyResult( psResult );
         return TRUE;
@@ -1815,7 +1814,7 @@ int WCSDataset::EstablishRasterDetails()
 /* -------------------------------------------------------------------- */
 /*      Do we already have bandcount and pixel type settings?           */
 /* -------------------------------------------------------------------- */
-    if( CPLGetXMLValue( psService, "BandCount", NULL ) != NULL 
+    if( CPLGetXMLValue( psService, "BandCount", NULL ) != NULL
         && CPLGetXMLValue( psService, "BandType", NULL ) != NULL )
         return TRUE;
 
@@ -1824,13 +1823,13 @@ int WCSDataset::EstablishRasterDetails()
 /* -------------------------------------------------------------------- */
     CPLHTTPResult *psResult = NULL;
     CPLErr eErr;
-    
+
     eErr = GetCoverage( 0, 0, 2, 2, 2, 2, 0, NULL, &psResult );
     if( eErr != CE_None )
         return FALSE;
 
 /* -------------------------------------------------------------------- */
-/*      Try and open result as a dataseat.                               */
+/*      Try and open result as a dataset.                               */
 /* -------------------------------------------------------------------- */
     GDALDataset *poDS = GDALOpenResult( psResult );
 
@@ -1854,23 +1853,23 @@ int WCSDataset::EstablishRasterDetails()
         delete poDS;
         return FALSE;
     }
-    
+
     if( CPLGetXMLValue(psService,"BandCount",NULL) == NULL )
-        CPLCreateXMLElementAndValue( 
-            psService, "BandCount", 
+        CPLCreateXMLElementAndValue(
+            psService, "BandCount",
             CPLString().Printf("%d",poDS->GetRasterCount()));
-    
-    CPLCreateXMLElementAndValue( 
-        psService, "BandType", 
+
+    CPLCreateXMLElementAndValue(
+        psService, "BandType",
         GDALGetDataTypeName(poDS->GetRasterBand(1)->GetRasterDataType()) );
 
     bServiceDirty = TRUE;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Cleanup                                                         */
 /* -------------------------------------------------------------------- */
     delete poDS;
-    
+
     FlushMemoryResult();
 
     return TRUE;
@@ -1882,8 +1881,8 @@ int WCSDataset::EstablishRasterDetails()
 /*      This actually either cleans up the in memory /vsimem/           */
 /*      temporary file, or the on disk temporary file.                  */
 /************************************************************************/
-void WCSDataset::FlushMemoryResult()    
-        
+void WCSDataset::FlushMemoryResult()
+
 {
     if( strlen(osResultFilename) > 0 )
     {
@@ -1924,8 +1923,8 @@ GDALDataset *WCSDataset::GDALOpenResult( CPLHTTPResult *psResult )
     GByte *pabyData = psResult->pabyData;
     int    nDataLen = psResult->nDataLen;
 
-    if( psResult->pszContentType 
-        && strstr(psResult->pszContentType,"multipart") 
+    if( psResult->pszContentType
+        && strstr(psResult->pszContentType,"multipart")
         && CPLHTTPParseMultipartMime(psResult) )
     {
         if( psResult->nMimePartCount > 1 )
@@ -1946,7 +1945,7 @@ GDALDataset *WCSDataset::GDALOpenResult( CPLHTTPResult *psResult )
 /* -------------------------------------------------------------------- */
     // Eventually we should be looking at mime info and stuff to figure
     // out an optimal filename, but for now we just use a fixed one.
-    osResultFilename.Printf( "/vsimem/wcs/%p/wcsresult.dat", 
+    osResultFilename.Printf( "/vsimem/wcs/%p/wcsresult.dat",
                              this );
 
     VSILFILE *fp = VSIFileFromMemBuffer( osResultFilename, pabyData, nDataLen,
@@ -1963,7 +1962,7 @@ GDALDataset *WCSDataset::GDALOpenResult( CPLHTTPResult *psResult )
 /* -------------------------------------------------------------------- */
 /*      Try opening this result as a gdaldataset.                       */
 /* -------------------------------------------------------------------- */
-    GDALDataset *poDS = (GDALDataset *) 
+    GDALDataset *poDS = (GDALDataset *)
         GDALOpen( osResultFilename, GA_ReadOnly );
 
 /* -------------------------------------------------------------------- */
@@ -1974,14 +1973,14 @@ GDALDataset *WCSDataset::GDALOpenResult( CPLHTTPResult *psResult )
     {
         CPLString osTempFilename;
         VSILFILE *fpTemp;
-        
+
         osTempFilename.Printf( "/tmp/%p_wcs.dat", this );
-                               
+
         fpTemp = VSIFOpenL( osTempFilename, "wb" );
         if( fpTemp == NULL )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
-                      "Failed to create temporary file:%s", 
+            CPLError( CE_Failure, CPLE_OpenFailed,
+                      "Failed to create temporary file:%s",
                       osTempFilename.c_str() );
         }
         else
@@ -1989,8 +1988,8 @@ GDALDataset *WCSDataset::GDALOpenResult( CPLHTTPResult *psResult )
             if( VSIFWriteL( pabyData, nDataLen, 1, fpTemp )
                 != 1 )
             {
-                CPLError( CE_Failure, CPLE_OpenFailed, 
-                          "Failed to write temporary file:%s", 
+                CPLError( CE_Failure, CPLE_OpenFailed,
+                          "Failed to write temporary file:%s",
                           osTempFilename.c_str() );
                 VSIFCloseL( fpTemp );
                 VSIUnlink( osTempFilename );
@@ -2001,7 +2000,7 @@ GDALDataset *WCSDataset::GDALOpenResult( CPLHTTPResult *psResult )
                 VSIUnlink( osResultFilename );
                 osResultFilename = osTempFilename;
 
-                poDS =  (GDALDataset *) 
+                poDS =  (GDALDataset *)
                     GDALOpen( osResultFilename, GA_ReadOnly );
             }
         }
@@ -2011,10 +2010,10 @@ GDALDataset *WCSDataset::GDALOpenResult( CPLHTTPResult *psResult )
 /*      Steal the memory buffer from HTTP result.                       */
 /* -------------------------------------------------------------------- */
     pabySavedDataBuffer = psResult->pabyData;
-        
+
     psResult->pabyData = NULL;
     psResult->nDataLen = psResult->nDataAlloc = 0;
-    
+
     if( poDS == NULL )
         FlushMemoryResult();
 
@@ -2032,20 +2031,20 @@ int WCSDataset::Identify( GDALOpenInfo * poOpenInfo )
 {
 /* -------------------------------------------------------------------- */
 /*      Is this a WCS_GDAL service description file or "in url"         */
-/*      equivelent?                                                     */
+/*      equivalent?                                                     */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->nHeaderBytes == 0
-        && EQUALN((const char *) poOpenInfo->pszFilename,"<WCS_GDAL>",10) )
+        && STARTS_WITH_CI((const char *) poOpenInfo->pszFilename, "<WCS_GDAL>") )
         return TRUE;
 
     else if( poOpenInfo->nHeaderBytes >= 10
-             && EQUALN((const char *) poOpenInfo->pabyHeader,"<WCS_GDAL>",10) )
+             && STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "<WCS_GDAL>") )
         return TRUE;
 
 /* -------------------------------------------------------------------- */
 /*      Is this apparently a WCS subdataset reference?                  */
 /* -------------------------------------------------------------------- */
-    else if( EQUALN((const char *) poOpenInfo->pszFilename,"WCS_SDS:",8) 
+    else if( STARTS_WITH_CI((const char *) poOpenInfo->pszFilename, "WCS_SDS:")
              && poOpenInfo->nHeaderBytes == 0 )
         return TRUE;
 
@@ -2064,24 +2063,24 @@ GDALDataset *WCSDataset::Open( GDALOpenInfo * poOpenInfo )
 
 /* -------------------------------------------------------------------- */
 /*      Is this a WCS_GDAL service description file or "in url"         */
-/*      equivelent?                                                     */
+/*      equivalent?                                                     */
 /* -------------------------------------------------------------------- */
     CPLXMLNode *psService = NULL;
 
-    if( poOpenInfo->nHeaderBytes == 0 
-        && EQUALN((const char *) poOpenInfo->pszFilename,"<WCS_GDAL>",10) )
+    if( poOpenInfo->nHeaderBytes == 0
+        && STARTS_WITH_CI((const char *) poOpenInfo->pszFilename, "<WCS_GDAL>") )
     {
         psService = CPLParseXMLString( poOpenInfo->pszFilename );
     }
     else if( poOpenInfo->nHeaderBytes >= 10
-             && EQUALN((const char *) poOpenInfo->pabyHeader,"<WCS_GDAL>",10) )
+             && STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "<WCS_GDAL>") )
     {
         psService = CPLParseXMLFile( poOpenInfo->pszFilename );
     }
 /* -------------------------------------------------------------------- */
 /*      Is this apparently a subdataset?                                */
 /* -------------------------------------------------------------------- */
-    else if( EQUALN((const char *) poOpenInfo->pszFilename,"WCS_SDS:",8) 
+    else if( STARTS_WITH_CI((const char *) poOpenInfo->pszFilename, "WCS_SDS:")
              && poOpenInfo->nHeaderBytes == 0 )
     {
         int iLast;
@@ -2107,7 +2106,7 @@ GDALDataset *WCSDataset::Open( GDALOpenInfo * poOpenInfo )
         CSLDestroy( papszModifiers );
         return NULL;
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
@@ -2115,12 +2114,12 @@ GDALDataset *WCSDataset::Open( GDALOpenInfo * poOpenInfo )
     {
         CSLDestroy( papszModifiers );
         CPLDestroyXMLNode( psService );
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The WCS driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Check for required minimum fields.                              */
 /* -------------------------------------------------------------------- */
@@ -2128,7 +2127,7 @@ GDALDataset *WCSDataset::Open( GDALOpenInfo * poOpenInfo )
         || !CPLGetXMLValue( psService, "CoverageName", NULL ) )
     {
         CSLDestroy( papszModifiers );
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "Missing one or both of ServiceURL and CoverageName elements.\n"
                   "See WCS driver documentation for details on service description file format." );
 
@@ -2153,7 +2152,7 @@ GDALDataset *WCSDataset::Open( GDALOpenInfo * poOpenInfo )
     else
     {
         CSLDestroy( papszModifiers );
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "WCS Version '%s' not supported.", pszVersion );
         CPLDestroyXMLNode( psService );
         return NULL;
@@ -2176,28 +2175,28 @@ GDALDataset *WCSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     const char  *pszParm;
 
-    poDS->papszHttpOptions = 
+    poDS->papszHttpOptions =
         CSLSetNameValue(poDS->papszHttpOptions,
                         "TIMEOUT",
                         CPLGetXMLValue( psService, "Timeout", "30" ) );
 
     pszParm = CPLGetXMLValue( psService, "HTTPAUTH", NULL );
     if( pszParm )
-        poDS->papszHttpOptions = 
-            CSLSetNameValue( poDS->papszHttpOptions, 
+        poDS->papszHttpOptions =
+            CSLSetNameValue( poDS->papszHttpOptions,
                              "HTTPAUTH", pszParm );
 
     pszParm = CPLGetXMLValue( psService, "USERPWD", NULL );
     if( pszParm )
-        poDS->papszHttpOptions = 
-            CSLSetNameValue( poDS->papszHttpOptions, 
+        poDS->papszHttpOptions =
+            CSLSetNameValue( poDS->papszHttpOptions,
                              "USERPWD", pszParm );
 
 /* -------------------------------------------------------------------- */
 /*      If we don't have the DescribeCoverage result for this           */
 /*      coverage, fetch it now.                                         */
 /* -------------------------------------------------------------------- */
-    if( CPLGetXMLNode( psService, "CoverageOffering" ) == NULL 
+    if( CPLGetXMLNode( psService, "CoverageOffering" ) == NULL
         && CPLGetXMLNode( psService, "CoverageDescription" ) == NULL )
     {
         if( !poDS->DescribeCoverage() )
@@ -2217,13 +2216,13 @@ GDALDataset *WCSDataset::Open( GDALOpenInfo * poOpenInfo )
         delete poDS;
         return NULL;
     }
-    
+
     if( !poDS->EstablishRasterDetails() )
     {
         delete poDS;
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
@@ -2235,7 +2234,7 @@ GDALDataset *WCSDataset::Open( GDALOpenInfo * poOpenInfo )
         delete poDS;
         return NULL;
     }
-     
+
     for( iBand = 0; iBand < nBandCount; iBand++ )
         poDS->SetBand( iBand+1, new WCSRasterBand( poDS, iBand+1, -1 ) );
 
@@ -2243,11 +2242,11 @@ GDALDataset *WCSDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Set time metadata on the dataset if we are selecting a          */
 /*      temporal slice.                                                 */
 /* -------------------------------------------------------------------- */
-    CPLString osTime = CSLFetchNameValueDef( poDS->papszSDSModifiers, "time", 
+    CPLString osTime = CSLFetchNameValueDef( poDS->papszSDSModifiers, "time",
                                              poDS->osDefaultTime );
-    
+
     if( osTime != "" )
-        poDS->GDALMajorObject::SetMetadataItem( "TIME_POSITION", 
+        poDS->GDALMajorObject::SetMetadataItem( "TIME_POSITION",
                                                 osTime.c_str() );
 
 /* -------------------------------------------------------------------- */
@@ -2260,8 +2259,8 @@ GDALDataset *WCSDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      metadata.  Note we don't do subdatasets if this is a            */
 /*      subdataset or if this is an all-in-memory service.              */
 /* -------------------------------------------------------------------- */
-    if( !EQUALN(poOpenInfo->pszFilename,"WCS_SDS:",8) 
-        && !EQUALN(poOpenInfo->pszFilename,"<WCS_GDAL>",10) 
+    if( !STARTS_WITH_CI(poOpenInfo->pszFilename, "WCS_SDS:")
+        && !STARTS_WITH_CI(poOpenInfo->pszFilename, "<WCS_GDAL>")
         && poDS->aosTimePositions.size() > 0 )
     {
         char **papszSubdatasets = NULL;
@@ -2271,28 +2270,28 @@ GDALDataset *WCSDataset::Open( GDALOpenInfo * poOpenInfo )
         {
             CPLString osName;
             CPLString osValue;
-            
+
             osName.Printf( "SUBDATASET_%d_NAME", iTime+1 );
-            osValue.Printf( "WCS_SDS:time=\"%s\",%s", 
-                           poDS->aosTimePositions[iTime].c_str(), 
+            osValue.Printf( "WCS_SDS:time=\"%s\",%s",
+                           poDS->aosTimePositions[iTime].c_str(),
                            poOpenInfo->pszFilename );
-            papszSubdatasets = CSLSetNameValue( papszSubdatasets, 
+            papszSubdatasets = CSLSetNameValue( papszSubdatasets,
                                                 osName, osValue );
 
-            CPLString osCoverage = 
+            CPLString osCoverage =
                 CPLGetXMLValue( poDS->psService, "CoverageName", "" );
 
             osName.Printf( "SUBDATASET_%d_DESC", iTime+1 );
-            osValue.Printf( "Coverage %s at time %s", 
-                            osCoverage.c_str(), 
+            osValue.Printf( "Coverage %s at time %s",
+                            osCoverage.c_str(),
                             poDS->aosTimePositions[iTime].c_str() );
-            papszSubdatasets = CSLSetNameValue( papszSubdatasets, 
+            papszSubdatasets = CSLSetNameValue( papszSubdatasets,
                                                 osName, osValue );
         }
-        
-        poDS->GDALMajorObject::SetMetadata( papszSubdatasets, 
+
+        poDS->GDALMajorObject::SetMetadata( papszSubdatasets,
                                             "SUBDATASETS" );
-        
+
         CSLDestroy( papszSubdatasets );
     }
 
@@ -2352,7 +2351,7 @@ char **WCSDataset::GetFileList()
                  CPLGetXMLValue( psService, "CoverageName", "" ) );
     papszFileList = CSLAddString( papszFileList, file.c_str() );
 #endif /* def ESRI_BUILD */
-    
+
     return papszFileList;
 }
 
@@ -2378,7 +2377,6 @@ char **WCSDataset::GetMetadata( const char *pszDomain )
         || !EQUAL(pszDomain,"xml:CoverageOffering") )
         return GDALPamDataset::GetMetadata( pszDomain );
 
-    
     CPLXMLNode *psNode = CPLGetXMLNode( psService, "CoverageOffering" );
 
     if( psNode == NULL )
@@ -2402,30 +2400,26 @@ char **WCSDataset::GetMetadata( const char *pszDomain )
 
 
 /************************************************************************/
-/*                          GDALRegister_WCS()                        */
+/*                          GDALRegister_WCS()                          */
 /************************************************************************/
 
 void GDALRegister_WCS()
 
 {
-    GDALDriver	*poDriver;
-
-    if( GDALGetDriverByName( "WCS" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "WCS" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "OGC Web Coverage Service" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_wcs.html" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
-        
-        poDriver->pfnOpen = WCSDataset::Open;
-        poDriver->pfnIdentify = WCSDataset::Identify;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    if( GDALGetDriverByName( "WCS" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "WCS" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "OGC Web Coverage Service" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_wcs.html" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
+
+    poDriver->pfnOpen = WCSDataset::Open;
+    poDriver->pfnIdentify = WCSDataset::Identify;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/webp/frmt_webp.html b/frmts/webp/frmt_webp.html
index 7f36fc6..08062e1 100644
--- a/frmts/webp/frmt_webp.html
+++ b/frmts/webp/frmt_webp.html
@@ -1,51 +1,51 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<title>WEBP - WEBP</title>
-</head>
-
-<body>
-
-<h1>WEBP - WEBP</h1>
-
-<p>Starting with GDAL 1.9.0, GDAL can read and write WebP images through the WebP library.</p>
-
-<p>WebP is a new image format that provides lossy compression for photographic images.
-A WebP file consists of VP8 image data, and a container based on RIFF.</p>
-
-<p>The driver rely on the Open Source WebP library (BSD licenced). The WebP library (at least in its
-version 0.1) only offers compression and decompression of whole images, so RAM might be a limitation
-when dealing with big images (which are limited to 16383x16383 pixels).</p>
-
-<p>The WEBP driver supports 3 bands (RGB) images. It also supports 4 bands (RGBA) starting with GDAL 1.10 and libwebp 0.1.4.</p>
-
-<p>The WEBP driver can be used as the internal format used by the <a href="frmt_rasterlite.html">Rasterlite</a> driver.</p>
-
-<p>Starting with GDAL 1.10, XMP metadata can be extracted from the file, and will be
-stored as XML raw content in the xml:XMP metadata domain.</p>
-
-<h2>Creation options</h2>
-
-Various creation options exists, among them :
-
-<ul>
-<li><p><b>QUALITY=n</b>: By default the quality flag is set to 75, but this
-option can be used to select other values.  Values must be in the
-range 1-100.  Low values result in higher compression ratios, but poorer
-image quality. <p></li>
-
-<li><p><b>LOSSLESS=True/False</b> (GDAL >= 1.10 and libwebp >= 0.1.4):
-By default, lossy compression is used. If set to True,
-lossless compression will be used.<p></li>
-
-</ul>
-
-<p>See Also:</p>
-
-<ul>
-<li><a href="https://developers.google.com/speed/webp/">WebP home page</a></li>
-</ul>
-
-</body>
-</html>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>WEBP - WEBP</title>
+</head>
+
+<body>
+
+<h1>WEBP - WEBP</h1>
+
+<p>Starting with GDAL 1.9.0, GDAL can read and write WebP images through the WebP library.</p>
+
+<p>WebP is a new image format that provides lossy compression for photographic images.
+A WebP file consists of VP8 image data, and a container based on RIFF.</p>
+
+<p>The driver rely on the Open Source WebP library (BSD licensed). The WebP library (at least in its
+version 0.1) only offers compression and decompression of whole images, so RAM might be a limitation
+when dealing with big images (which are limited to 16383x16383 pixels).</p>
+
+<p>The WEBP driver supports 3 bands (RGB) images. It also supports 4 bands (RGBA) starting with GDAL 1.10 and libwebp 0.1.4.</p>
+
+<p>The WEBP driver can be used as the internal format used by the <a href="frmt_rasterlite.html">Rasterlite</a> driver.</p>
+
+<p>Starting with GDAL 1.10, XMP metadata can be extracted from the file, and will be
+stored as XML raw content in the xml:XMP metadata domain.</p>
+
+<h2>Creation options</h2>
+
+Various creation options exists, among them :
+
+<ul>
+<li><p><b>QUALITY=n</b>: By default the quality flag is set to 75, but this
+option can be used to select other values.  Values must be in the
+range 1-100.  Low values result in higher compression ratios, but poorer
+image quality. <p></li>
+
+<li><p><b>LOSSLESS=True/False</b> (GDAL >= 1.10 and libwebp >= 0.1.4):
+By default, lossy compression is used. If set to True,
+lossless compression will be used.<p></li>
+
+</ul>
+
+<p>See Also:</p>
+
+<ul>
+<li><a href="https://developers.google.com/speed/webp/">WebP home page</a></li>
+</ul>
+
+</body>
+</html>
diff --git a/frmts/webp/webp_headers.h b/frmts/webp/webp_headers.h
new file mode 100644
index 0000000..5ad4b8b
--- /dev/null
+++ b/frmts/webp/webp_headers.h
@@ -0,0 +1,41 @@
+/******************************************************************************
+ *
+ * Project:  GDAL
+ * Purpose:  Includes libwebp headers
+ * Author:   Even Rouault <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+#ifndef GDAL_LIBWEBP_HEADERS_H
+#define GDAL_LIBWEBP_HEADERS_H
+
+#include "cpl_port.h"
+
+#ifdef HAVE_GCC_SYSTEM_HEADER
+#pragma GCC system_header
+#endif
+
+#include "webp/decode.h"
+#include "webp/encode.h"
+
+#endif /* GDAL_LIBWEBP_HEADERS_H */
diff --git a/frmts/webp/webpdataset.cpp b/frmts/webp/webpdataset.cpp
index 61e113c..7560963 100644
--- a/frmts/webp/webpdataset.cpp
+++ b/frmts/webp/webpdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: webpdataset.cpp 28785 2015-03-26 20:46:45Z goatbar $
+ * $Id: webpdataset.cpp 32827 2016-01-08 11:22:33Z rouault $
  *
  * Project:  GDAL WEBP Driver
  * Purpose:  Implement GDAL WEBP Support based on libwebp
@@ -27,17 +27,13 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
 
-#include "webp/decode.h"
-#include "webp/encode.h"
-
-CPL_CVSID("$Id: webpdataset.cpp 28785 2015-03-26 20:46:45Z goatbar $");
+#include "webp_headers.h"
 
-CPL_C_START
-void    GDALRegister_WEBP(void);
-CPL_C_END
+CPL_CVSID("$Id: webpdataset.cpp 32827 2016-01-08 11:22:33Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -93,7 +89,6 @@ class WEBPRasterBand : public GDALPamRasterBand
     friend class WEBPDataset;
 
   public:
-
                    WEBPRasterBand( WEBPDataset *, int );
 
     virtual CPLErr IReadBlock( int, int, void * );
@@ -104,13 +99,13 @@ class WEBPRasterBand : public GDALPamRasterBand
 /*                          WEBPRasterBand()                            */
 /************************************************************************/
 
-WEBPRasterBand::WEBPRasterBand( WEBPDataset *poDS, CPL_UNUSED int nBand )
+WEBPRasterBand::WEBPRasterBand( WEBPDataset *poDSIn, int )
 {
-    this->poDS = poDS;
+    poDS = poDSIn;
 
     eDataType = GDT_Byte;
 
-    nBlockXSize = poDS->nRasterXSize;
+    nBlockXSize = poDSIn->nRasterXSize;
     nBlockYSize = 1;
 }
 
@@ -121,16 +116,17 @@ WEBPRasterBand::WEBPRasterBand( WEBPDataset *poDS, CPL_UNUSED int nBand )
 CPLErr WEBPRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff, int nBlockYOff,
                                    void * pImage )
 {
-    WEBPDataset* poGDS = (WEBPDataset*) poDS;
+    WEBPDataset* poGDS = reinterpret_cast<WEBPDataset *>( poDS );
 
     if( poGDS->Uncompress() != CE_None )
         return CE_Failure;
 
-    int i;
     GByte* pabyUncompressed =
-        &poGDS->pabyUncompressed[nBlockYOff * nRasterXSize  * poGDS->nBands + nBand - 1];
-    for(i=0;i<nRasterXSize;i++)
-        ((GByte*)pImage)[i] = pabyUncompressed[poGDS->nBands * i];
+        &poGDS->pabyUncompressed[nBlockYOff * nRasterXSize  * poGDS->nBands
+                                 + nBand - 1];
+    for( int i = 0; i < nRasterXSize; i++ )
+        reinterpret_cast<GByte*>( pImage )[i]
+            = pabyUncompressed[poGDS->nBands * i];
 
     return CE_None;
 }
@@ -151,8 +147,7 @@ GDALColorInterp WEBPRasterBand::GetColorInterpretation()
     else if ( nBand == 3 )
         return GCI_BlueBand;
 
-    else
-        return GCI_AlphaBand;
+    return GCI_AlphaBand;
 }
 
 /************************************************************************/
@@ -166,15 +161,13 @@ GDALColorInterp WEBPRasterBand::GetColorInterpretation()
 /*                            WEBPDataset()                              */
 /************************************************************************/
 
-WEBPDataset::WEBPDataset()
-
-{
-    fpImage = NULL;
-    pabyUncompressed = NULL;
-    bHasBeenUncompressed = FALSE;
-    eUncompressErrRet = CE_None;
-    bHasReadXMPMetadata = FALSE;
-}
+WEBPDataset::WEBPDataset() :
+    fpImage(NULL),
+    pabyUncompressed(NULL),
+    bHasBeenUncompressed(FALSE),
+    eUncompressErrRet(CE_None),
+    bHasReadXMPMetadata(FALSE)
+{}
 
 /************************************************************************/
 /*                           ~WEBPDataset()                             */
@@ -206,14 +199,15 @@ char **WEBPDataset::GetMetadataDomainList()
 
 char  **WEBPDataset::GetMetadata( const char * pszDomain )
 {
-    if ((pszDomain != NULL && EQUAL(pszDomain, "xml:XMP")) && !bHasReadXMPMetadata)
+    if( (pszDomain != NULL && EQUAL(pszDomain, "xml:XMP") )
+        && !bHasReadXMPMetadata)
     {
         bHasReadXMPMetadata = TRUE;
 
         VSIFSeekL(fpImage, 12, SEEK_SET);
 
-        int bFirst = TRUE;
-        while(TRUE)
+        bool bFirst = true;
+        while( true )
         {
             char szHeader[5];
             GUInt32 nChunkSize;
@@ -230,27 +224,30 @@ char  **WEBPDataset::GetMetadata( const char * pszDomain )
                 if (strcmp(szHeader, "VP8X") != 0 || nChunkSize < 10)
                     break;
 
-                int nFlags;
-                if (VSIFReadL(&nFlags, 1, 4, fpImage) != 4)
+                int l_nFlags;
+                if (VSIFReadL(&l_nFlags, 1, 4, fpImage) != 4)
                     break;
-                CPL_LSBPTR32(&nFlags);
-                if ((nFlags & 8) == 0)
+                CPL_LSBPTR32(&l_nFlags);
+                if ((l_nFlags & 8) == 0)
                     break;
 
                 VSIFSeekL(fpImage, nChunkSize - 4, SEEK_CUR);
 
-                bFirst = FALSE;
+                bFirst = false;
             }
             else if (strcmp(szHeader, "META") == 0)
             {
                 if (nChunkSize > 1024 * 1024)
                     break;
 
-                char* pszXMP = (char*) VSIMalloc(nChunkSize + 1);
+                char* pszXMP
+                    = reinterpret_cast<char*>( VSIMalloc(nChunkSize + 1) );
                 if (pszXMP == NULL)
                     break;
 
-                if ((GUInt32)VSIFReadL(pszXMP, 1, nChunkSize, fpImage) != nChunkSize)
+                if( static_cast<GUInt32>( VSIFReadL(pszXMP, 1, nChunkSize,
+                                                    fpImage) )
+                    != nChunkSize )
                 {
                     VSIFree(pszXMP);
                     break;
@@ -258,11 +255,9 @@ char  **WEBPDataset::GetMetadata( const char * pszDomain )
                 pszXMP[nChunkSize] = '\0';
 
                 /* Avoid setting the PAM dirty bit just for that */
-                int nOldPamFlags = nPamFlags;
+                const int nOldPamFlags = nPamFlags;
 
-                char *apszMDList[2];
-                apszMDList[0] = pszXMP;
-                apszMDList[1] = NULL;
+                char *apszMDList[2] = { pszXMP, NULL };
                 SetMetadata(apszMDList, "xml:XMP");
 
                 nPamFlags = nOldPamFlags;
@@ -286,32 +281,42 @@ CPLErr WEBPDataset::Uncompress()
 {
     if (bHasBeenUncompressed)
         return eUncompressErrRet;
+
     bHasBeenUncompressed = TRUE;
     eUncompressErrRet = CE_Failure;
 
-    pabyUncompressed = (GByte*)VSIMalloc3(nRasterXSize, nRasterYSize, nBands);
+    pabyUncompressed = reinterpret_cast<GByte*>(
+        VSIMalloc3(nRasterXSize, nRasterYSize, nBands ) );
     if (pabyUncompressed == NULL)
         return CE_Failure;
 
     VSIFSeekL(fpImage, 0, SEEK_END);
-    vsi_l_offset nSize = VSIFTellL(fpImage);
-    if (nSize != (vsi_l_offset)(uint32_t)nSize)
+    vsi_l_offset nSizeLarge = VSIFTellL(fpImage);
+    if( nSizeLarge != static_cast<vsi_l_offset>( static_cast<uint32_t>( nSizeLarge ) ) )
         return CE_Failure;
     VSIFSeekL(fpImage, 0, SEEK_SET);
-    uint8_t* pabyCompressed = (uint8_t*)VSIMalloc(nSize);
+    uint32_t nSize = static_cast<uint32_t>( nSizeLarge );
+    uint8_t* pabyCompressed = reinterpret_cast<uint8_t*>( VSIMalloc(nSize) );
     if (pabyCompressed == NULL)
         return CE_Failure;
     VSIFReadL(pabyCompressed, 1, nSize, fpImage);
     uint8_t* pRet;
 
     if (nBands == 4)
-        pRet = WebPDecodeRGBAInto(pabyCompressed, (uint32_t)nSize,
-                        (uint8_t*)pabyUncompressed, nRasterXSize * nRasterYSize * nBands,
-                        nRasterXSize * nBands);
+        pRet = WebPDecodeRGBAInto(
+            pabyCompressed,
+            static_cast<uint32_t>( nSize ),
+            static_cast<uint8_t*>( pabyUncompressed),
+            nRasterXSize * nRasterYSize * nBands,
+            nRasterXSize * nBands );
     else
-        pRet = WebPDecodeRGBInto(pabyCompressed, (uint32_t)nSize,
-                        (uint8_t*)pabyUncompressed, nRasterXSize * nRasterYSize * nBands,
-                        nRasterXSize * nBands);
+        pRet = WebPDecodeRGBInto(
+            pabyCompressed,
+            static_cast<uint32_t>( nSize ),
+            static_cast<uint8_t*>( pabyUncompressed ),
+            nRasterXSize * nRasterYSize * nBands,
+            nRasterXSize * nBands );
+
     VSIFree(pabyCompressed);
     if (pRet == NULL)
     {
@@ -340,17 +345,19 @@ CPLErr WEBPDataset::IRasterIO( GDALRWFlag eRWFlag,
 {
     if((eRWFlag == GF_Read) &&
        (nBandCount == nBands) &&
-       (nXOff == 0) && (nXOff == 0) &&
+       (nXOff == 0) &&
+       (nYOff == 0) && // TODO: X -> Y on this was correct?
        (nXSize == nBufXSize) && (nXSize == nRasterXSize) &&
        (nYSize == nBufYSize) && (nYSize == nRasterYSize) &&
-       (eBufType == GDT_Byte) && 
+       (eBufType == GDT_Byte) &&
        (pData != NULL) &&
-       (panBandMap != NULL) &&
-       (panBandMap[0] == 1) && (panBandMap[1] == 2) && (panBandMap[2] == 3) && (nBands == 3 || panBandMap[3] == 4))
+       (panBandMap[0] == 1) && (panBandMap[1] == 2) && (panBandMap[2] == 3) &&
+       (nBands == 3 || panBandMap[3] == 4))
     {
         if( Uncompress() != CE_None )
             return CE_Failure;
-        if( nPixelSpace == nBands && nLineSpace == (nPixelSpace*nXSize) && nBandSpace == 1 )
+        if( nPixelSpace == nBands && nLineSpace == (nPixelSpace*nXSize) &&
+            nBandSpace == 1 )
         {
             memcpy(pData, pabyUncompressed, nBands * nXSize * nYSize);
         }
@@ -362,7 +369,10 @@ CPLErr WEBPDataset::IRasterIO( GDALRWFlag eRWFlag,
                 for(int x = 0; x < nXSize; ++x)
                 {
                     for(int iBand=0;iBand<nBands;iBand++)
-                        ((GByte*)pData)[(y*nLineSpace) + (x*nPixelSpace) + iBand * nBandSpace] = pabyScanline[x*nBands+iBand];
+                        reinterpret_cast<GByte *>(
+                            pData )[(y * nLineSpace) + (x * nPixelSpace) +
+                                    iBand * nBandSpace]
+                            = pabyScanline[x * nBands + iBand];
                 }
             }
         }
@@ -384,10 +394,9 @@ CPLErr WEBPDataset::IRasterIO( GDALRWFlag eRWFlag,
 int WEBPDataset::Identify( GDALOpenInfo * poOpenInfo )
 
 {
-    GByte  *pabyHeader = NULL;
     int    nHeaderBytes = poOpenInfo->nHeaderBytes;
 
-    pabyHeader = poOpenInfo->pabyHeader;
+    GByte  *pabyHeader = poOpenInfo->pabyHeader;
 
     if( nHeaderBytes < 20 )
         return FALSE;
@@ -410,18 +419,22 @@ GDALDataset *WEBPDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
 
     int nWidth, nHeight;
-    if (!WebPGetInfo((const uint8_t*)poOpenInfo->pabyHeader, (uint32_t)poOpenInfo->nHeaderBytes,
+    if( !WebPGetInfo(reinterpret_cast<const uint8_t*>( poOpenInfo->pabyHeader ),
+                     static_cast<uint32_t>( poOpenInfo->nHeaderBytes ),
                      &nWidth, &nHeight))
         return NULL;
 
     int nBands = 3;
 
 #if WEBP_DECODER_ABI_VERSION >= 0x0002
-     WebPDecoderConfig config;
-     if (!WebPInitDecoderConfig(&config))
-         return NULL;
+    WebPDecoderConfig config;
+    if( !WebPInitDecoderConfig(&config) )
+        return NULL;
 
-     int bOK = WebPGetFeatures(poOpenInfo->pabyHeader, poOpenInfo->nHeaderBytes, &config.input) == VP8_STATUS_OK;
+    const bool bOK
+        = WebPGetFeatures(poOpenInfo->pabyHeader,
+                          poOpenInfo->nHeaderBytes, &config.input)
+        == VP8_STATUS_OK;
 
     if (config.input.has_alpha)
         nBands = 4;
@@ -444,9 +457,7 @@ GDALDataset *WEBPDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    WEBPDataset  *poDS;
-
-    poDS = new WEBPDataset();
+    WEBPDataset *poDS = new WEBPDataset();
     poDS->nRasterXSize = nWidth;
     poDS->nRasterYSize = nHeight;
     poDS->fpImage = poOpenInfo->fpL;
@@ -468,7 +479,8 @@ GDALDataset *WEBPDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Open overviews.                                                 */
 /* -------------------------------------------------------------------- */
-    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles() );
+    poDS->oOvManager.Initialize(
+        poDS, poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles() );
 
     return poDS;
 }
@@ -492,7 +504,8 @@ static
 int WEBPDatasetWriter(const uint8_t* data, size_t data_size,
                       const WebPPicture* const picture)
 {
-    WebPUserData* pUserData = (WebPUserData*)picture->custom_ptr;
+    WebPUserData* pUserData
+        = reinterpret_cast<WebPUserData *>( picture->custom_ptr );
     return VSIFWriteL(data, 1, data_size, pUserData->fp) == data_size;
 }
 
@@ -504,8 +517,10 @@ int WEBPDatasetWriter(const uint8_t* data, size_t data_size,
 static
 int WEBPDatasetProgressHook(int percent, const WebPPicture* const picture)
 {
-    WebPUserData* pUserData = (WebPUserData*)picture->custom_ptr;
-    return pUserData->pfnProgress( percent / 100.0, NULL, pUserData->pProgressData );
+    WebPUserData* pUserData
+      = reinterpret_cast<WebPUserData *>( picture->custom_ptr );
+    return pUserData->pfnProgress(
+        percent / 100.0, NULL, pUserData->pProgressData );
 }
 #endif
 
@@ -519,9 +534,6 @@ WEBPDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                         GDALProgressFunc pfnProgress, void * pProgressData )
 
 {
-    int  nBands = poSrcDS->GetRasterCount();
-    int  nXSize = poSrcDS->GetRasterXSize();
-    int  nYSize = poSrcDS->GetRasterYSize();
 
 /* -------------------------------------------------------------------- */
 /*      WEBP library initialization                                     */
@@ -538,6 +550,8 @@ WEBPDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      Some some rudimentary checks                                    */
 /* -------------------------------------------------------------------- */
 
+    const int nXSize = poSrcDS->GetRasterXSize();
+    const int nYSize = poSrcDS->GetRasterYSize();
     if( nXSize > 16383 || nYSize > 16383 )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
@@ -546,6 +560,7 @@ WEBPDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         return NULL;
     }
 
+    const int nBands = poSrcDS->GetRasterCount();
     if( nBands != 3
 #if WEBP_ENCODER_ABI_VERSION >= 0x0100
         && nBands != 4
@@ -563,7 +578,7 @@ WEBPDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         return NULL;
     }
 
-    GDALDataType eDT = poSrcDS->GetRasterBand(1)->GetRasterDataType();
+    const GDALDataType eDT = poSrcDS->GetRasterBand(1)->GetRasterDataType();
 
     if( eDT != GDT_Byte )
     {
@@ -581,10 +596,10 @@ WEBPDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      What options has the user selected?                             */
 /* -------------------------------------------------------------------- */
     float fQuality = 75.0f;
-    const char* pszQUALITY = CSLFetchNameValue(papszOptions, "QUALITY"); 
+    const char* pszQUALITY = CSLFetchNameValue(papszOptions, "QUALITY");
     if( pszQUALITY != NULL )
     {
-        fQuality = (float) CPLAtof(pszQUALITY);
+        fQuality = static_cast<float>( CPLAtof(pszQUALITY) );
         if( fQuality < 0.0f || fQuality > 100.0f )
         {
             CPLError( CE_Failure, CPLE_IllegalArg,
@@ -594,7 +609,8 @@ WEBPDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     }
 
     WebPPreset nPreset = WEBP_PRESET_DEFAULT;
-    const char* pszPRESET = CSLFetchNameValueDef(papszOptions, "PRESET", "DEFAULT");
+    const char* pszPRESET = CSLFetchNameValueDef(
+        papszOptions, "PRESET", "DEFAULT" );
     if (EQUAL(pszPRESET, "DEFAULT"))
         nPreset = WEBP_PRESET_DEFAULT;
     else if (EQUAL(pszPRESET, "PICTURE"))
@@ -617,13 +633,14 @@ WEBPDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     }
 
     WebPConfig sConfig;
-    if (!WebPConfigInitInternal(&sConfig, nPreset, fQuality, WEBP_ENCODER_ABI_VERSION))
+    if (!WebPConfigInitInternal(&sConfig, nPreset, fQuality,
+                                WEBP_ENCODER_ABI_VERSION))
     {
         CPLError(CE_Failure, CPLE_AppDefined, "WebPConfigInit() failed");
         return NULL;
     }
 
-
+    // TODO: Get rid of this macro in a reasonable way.
 #define FETCH_AND_SET_OPTION_INT(name, fieldname, minval, maxval) \
 { \
     const char* pszVal = CSLFetchNameValue(papszOptions, name); \
@@ -639,12 +656,12 @@ WEBPDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     } \
 }
 
-    FETCH_AND_SET_OPTION_INT("TARGETSIZE", target_size, 0, INT_MAX);
+    FETCH_AND_SET_OPTION_INT("TARGETSIZE", target_size, 0, INT_MAX-1);
 
     const char* pszPSNR = CSLFetchNameValue(papszOptions, "PSNR");
     if (pszPSNR)
     {
-        sConfig.target_PSNR = CPLAtof(pszPSNR);
+        sConfig.target_PSNR = static_cast<float>(CPLAtof(pszPSNR));
         if (sConfig.target_PSNR < 0)
         {
             CPLError( CE_Failure, CPLE_IllegalArg,
@@ -681,9 +698,8 @@ WEBPDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Allocate memory                                                 */
 /* -------------------------------------------------------------------- */
-    GByte   *pabyBuffer;
-
-    pabyBuffer = (GByte *) VSIMalloc( nBands * nXSize * nYSize );
+    GByte *pabyBuffer = reinterpret_cast<GByte *>(
+        VSIMalloc( nBands * nXSize * nYSize ) );
     if (pabyBuffer == NULL)
     {
         return NULL;
@@ -692,9 +708,7 @@ WEBPDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Create the dataset.                                             */
 /* -------------------------------------------------------------------- */
-    VSILFILE    *fpImage;
-
-    fpImage = VSIFOpenL( pszFilename, "wb" );
+    VSILFILE *fpImage = VSIFOpenL( pszFilename, "wb" );
     if( fpImage == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
@@ -731,12 +745,10 @@ WEBPDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Acquire source imagery.                                         */
 /* -------------------------------------------------------------------- */
-    CPLErr      eErr = CE_None;
-
-    eErr = poSrcDS->RasterIO( GF_Read, 0, 0, nXSize, nYSize,
-                              pabyBuffer, nXSize, nYSize, GDT_Byte,
-                              nBands, NULL,
-                              nBands, nBands * nXSize, 1, NULL );
+    CPLErr eErr = poSrcDS->RasterIO( GF_Read, 0, 0, nXSize, nYSize,
+                                     pabyBuffer, nXSize, nYSize, GDT_Byte,
+                                     nBands, NULL,
+                                     nBands, nBands * nXSize, 1, NULL );
 
 /* -------------------------------------------------------------------- */
 /*      Import and write to file                                        */
@@ -746,7 +758,8 @@ WEBPDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     {
         if (!WebPPictureImportRGBA(&sPicture, pabyBuffer, nBands * nXSize))
         {
-            CPLError(CE_Failure, CPLE_AppDefined, "WebPPictureImportRGBA() failed");
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "WebPPictureImportRGBA() failed" );
             eErr = CE_Failure;
         }
     }
@@ -761,27 +774,46 @@ WEBPDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
     if (eErr == CE_None && !WebPEncode(&sConfig, &sPicture))
     {
-        const char* pszErrorMsg = NULL;
 #if WEBP_ENCODER_ABI_VERSION >= 0x0100
+        const char* pszErrorMsg = NULL;
         switch(sPicture.error_code)
         {
-            case VP8_ENC_ERROR_OUT_OF_MEMORY: pszErrorMsg = "Out of memory"; break;
-            case VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY: pszErrorMsg = "Out of memory while flushing bits"; break;
-            case VP8_ENC_ERROR_NULL_PARAMETER: pszErrorMsg = "A pointer parameter is NULL"; break;
-            case VP8_ENC_ERROR_INVALID_CONFIGURATION: pszErrorMsg = "Configuration is invalid"; break;
-            case VP8_ENC_ERROR_BAD_DIMENSION: pszErrorMsg = "Picture has invalid width/height"; break;
-            case VP8_ENC_ERROR_PARTITION0_OVERFLOW: pszErrorMsg = "Partition is bigger than 512k. Try using less SEGMENTS, or increase PARTITION_LIMIT value"; break;
-            case VP8_ENC_ERROR_PARTITION_OVERFLOW: pszErrorMsg = "Partition is bigger than 16M"; break;
-            case VP8_ENC_ERROR_BAD_WRITE: pszErrorMsg = "Error while flusing bytes"; break;
-            case VP8_ENC_ERROR_FILE_TOO_BIG: pszErrorMsg = "File is bigger than 4G"; break;
-            case VP8_ENC_ERROR_USER_ABORT: pszErrorMsg = "User interrupted"; break;
-            default: break;
+            case VP8_ENC_ERROR_OUT_OF_MEMORY:
+                pszErrorMsg = "Out of memory"; break;
+            case VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY:
+                pszErrorMsg = "Out of memory while flushing bits"; break;
+            case VP8_ENC_ERROR_NULL_PARAMETER:
+                pszErrorMsg = "A pointer parameter is NULL"; break;
+            case VP8_ENC_ERROR_INVALID_CONFIGURATION:
+                pszErrorMsg = "Configuration is invalid"; break;
+            case VP8_ENC_ERROR_BAD_DIMENSION:
+                pszErrorMsg = "Picture has invalid width/height"; break;
+            case VP8_ENC_ERROR_PARTITION0_OVERFLOW:
+                pszErrorMsg = "Partition is bigger than 512k. Try using less "
+                    "SEGMENTS, or increase PARTITION_LIMIT value";
+                break;
+            case VP8_ENC_ERROR_PARTITION_OVERFLOW:
+                pszErrorMsg = "Partition is bigger than 16M";
+                break;
+            case VP8_ENC_ERROR_BAD_WRITE:
+                pszErrorMsg = "Error while flushing bytes"; break;
+            case VP8_ENC_ERROR_FILE_TOO_BIG:
+                pszErrorMsg = "File is bigger than 4G"; break;
+            case VP8_ENC_ERROR_USER_ABORT:
+                pszErrorMsg = "User interrupted";
+                break;
+            default:
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "WebPEncode returned an unknown error code: %d",
+                         sPicture.error_code);
+                pszErrorMsg = "Unknown WebP error type.";
+                break;
         }
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "WebPEncode() failed : %s", pszErrorMsg);
+#else
+        CPLError(CE_Failure, CPLE_AppDefined, "WebPEncode() failed");
 #endif
-        if (pszErrorMsg)
-            CPLError(CE_Failure, CPLE_AppDefined, "WebPEncode() failed : %s", pszErrorMsg);
-        else
-            CPLError(CE_Failure, CPLE_AppDefined, "WebPEncode() failed");
         eErr = CE_Failure;
     }
 
@@ -801,14 +833,15 @@ WEBPDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     }
 
 /* -------------------------------------------------------------------- */
-/*      Re-open dataset, and copy any auxiliary pam information.         */
+/*      Re-open dataset, and copy any auxiliary pam information.        */
 /* -------------------------------------------------------------------- */
     GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly);
 
-    /* If outputing to stdout, we can't reopen it, so we'll return */
+    /* If writing to stdout, we can't reopen it, so return */
     /* a fake dataset to make the caller happy */
     CPLPushErrorHandler(CPLQuietErrorHandler);
-    WEBPDataset *poDS = (WEBPDataset*) WEBPDataset::Open( &oOpenInfo );
+    WEBPDataset *poDS
+        = reinterpret_cast<WEBPDataset*>( WEBPDataset::Open( &oOpenInfo ) );
     CPLPopErrorHandler();
     if( poDS )
     {
@@ -826,25 +859,20 @@ WEBPDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 void GDALRegister_WEBP()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "WEBP" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "WEBP" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-
-        poDriver->SetDescription( "WEBP" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "WEBP" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "frmt_webp.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "webp" );
-        poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/webp" );
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
-                                   "Byte" );
+    poDriver->SetDescription( "WEBP" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "WEBP" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_webp.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "webp" );
+    poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/webp" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte" );
 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>\n"
 "   <Option name='QUALITY' type='float' description='good=100, bad=0' default='75'/>\n"
 #if WEBP_ENCODER_ABI_VERSION >= 0x0100
@@ -875,12 +903,11 @@ void GDALRegister_WEBP()
 #endif
 "</CreationOptionList>\n" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnIdentify = WEBPDataset::Identify;
-        poDriver->pfnOpen = WEBPDataset::Open;
-        poDriver->pfnCreateCopy = WEBPDataset::CreateCopy;
+    poDriver->pfnIdentify = WEBPDataset::Identify;
+    poDriver->pfnOpen = WEBPDataset::Open;
+    poDriver->pfnCreateCopy = WEBPDataset::CreateCopy;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/wms/GNUmakefile b/frmts/wms/GNUmakefile
index 4b20a1f..6821d15 100644
--- a/frmts/wms/GNUmakefile
+++ b/frmts/wms/GNUmakefile
@@ -6,7 +6,8 @@ OBJ =	gdalwmscache.o gdalwmsdataset.o gdalwmsrasterband.o \
 	wmsutils.o wmsdriver.o minidriver_wms.o \
 	minidriver_tileservice.o minidriver_worldwind.o \
 	minidriver_tms.o minidriver_tiled_wms.o wmsmetadataset.o \
-	minidriver_virtualearth.o minidriver_arcgis_server.o
+	minidriver_virtualearth.o minidriver_arcgis_server.o \
+	minidriver_iip.o
 
 CPPFLAGS	:=	 $(CPPFLAGS) $(CURL_INC)
 
diff --git a/frmts/wms/frmt_wms.html b/frmts/wms/frmt_wms.html
index 12b2a72..a227c78 100644
--- a/frmts/wms/frmt_wms.html
+++ b/frmts/wms/frmt_wms.html
@@ -71,7 +71,7 @@
 		</tr>
 		<tr>
 			<td class="xml">        <BBoxOrder>xyXY</BBoxOrder></td>
-			<td class="desc">Reorder bbox coordinates arbitrarly. May be required for version 1.3 servers. (optional)<br>
+			<td class="desc">Reorder bbox coordinates arbitrarily. May be required for version 1.3 servers. (optional)<br>
 				x - low X coordinate, y - low Y coordinate, X - high X coordinate, Y - high Y coordinate
 			</td>
 		</tr>
@@ -138,7 +138,7 @@
 		<tr>
 			<td class="xml">    <Projection><span class="value">EPSG:4326</span></Projection></td>
 			<td class="desc">Image projection (optional, defaults to value reported by mini-driver or EPSG:4326)</td>
-		</tr>		
+		</tr>
 		<tr>
 			<td class="xml">    <IdentificationTolerance><span class="value">2</span></IdentificationTolerance></td>
 			<td class="desc">Identification tolerance (optional, defaults to 2)</td>
@@ -229,7 +229,7 @@
 		</tr>
 		<tr>
 			<td class="xml">    <ZeroBlockOnServerException><span class="value">true</span></ZeroBlockOnServerException></td>
-			<td class="desc">Wether to treat a Service Exception returned by the server as a 0 filled image instead of aborting the request. Added in 1.9.0. (optional, defaults to false)</td>
+			<td class="desc">Whether to treat a Service Exception returned by the server as a 0 filled image instead of aborting the request. Added in 1.9.0. (optional, defaults to false)</td>
 		</tr>
 		<tr>
 			<td class="xml"></GDAL_WMS></td>
@@ -393,7 +393,7 @@ Access to web-based Virtual Earth tile services. Access is always tile based.<p>
 
 <h3>ArcGIS REST API (GDAL 2.0 and later)</h3>
 <p>
-Access to ArcGIS REST <a href="http://resources.arcgis.com/en/help/rest/apiref/mapserver.html">map service resource</a> (untiled requests). 
+Access to ArcGIS REST <a href="http://resources.arcgis.com/en/help/rest/apiref/mapserver.html">map service resource</a> (untiled requests).
 </p>
 <p>AGS layers can be <a href="http://resources.arcgis.com/en/help/rest/apiref/identify.html">queried</a> (through a GetFeatureInfo request) with the gdallocationinfo utility, or with a GetMetadataItem("Pixel_iCol_iLine", "LocationInfo") call on a band object.
 </p>
@@ -402,6 +402,17 @@ Access to ArcGIS REST <a href="http://resources.arcgis.com/en/help/rest/apiref/m
      <pre>gdallocationinfo -wgs84 "<GDAL_WMS><Service name=\"AGS\"><ServerUrl>http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StateCityHighway_USA/MapServer</ServerUrl><BBoxOrder>xyXY</BBoxOrder><SRS>3857</SRS></Service><DataWindow><UpperLeftX>-20037508.34</UpperLeftX><UpperLeftY>20037508.34</UpperLeftY><LowerRightX>20037508.34</LowerRightX><LowerRightY>-2003750 [...]
     </pre>
 
+<h3>Internet Imaging Protocol (IIP) (GDAL 2.1 and later)</h3>
+<p>
+Access to images served through <a href="https://en.wikipedia.org/wiki/Internet_Imaging_Protocol">IIP protocol</a>. The server must support the
+JTL (Retrieve a tile as a complete JFIF image) extension of the IIP protocol.
+</p>
+<p>If using the XML syntax, the ServerURL must contain the FIF parameter.</p>
+<p>Otherwise it is also possible to use "IIP:http://foo.com/FIF=image_name" syntax
+as connection string, to retrieve from the server information on the full resolution
+dimension and the number of resolutions.</p>
+<p>The XML definition can then be generated with
+"gdal_translate IIP:http://foo.com/FIF=image_name out.xml -of WMS"</p>
 
 <h2>Examples</h2>
 
@@ -467,11 +478,14 @@ Access to ArcGIS REST <a href="http://resources.arcgis.com/en/help/rest/apiref/m
     <li><p>
      <a href="frmt_wms_virtualearth.xml">VirtualEarth Aerial Layer</a> accessed with the VirtualEarth minidriver.
     </p></li>
-    
+
     <li><p>
      <a href="frmt_ags_arcgisonline.xml">ArcGIS online sample server layer</a> accessed with the ArcGIS Server REST API minidriver.
     </p></li>
 
+    <li><p>
+     <a href="frmt_wms_iip.xml">IIP online sample server layer</a> accessed with the IIP minidriver.
+    </p></li>
 </ul>
 
 <h2>Open syntax</h2>
@@ -505,9 +519,14 @@ A list of subdatasets will be returned, resulting from the parsing of the GetTil
 </p></li>
 
 <li><p>
-(GDAL >= 1.9.0) the URL of a REST definition for a ArcGIS MapServer:
+(GDAL >= 2.0.0) the URL of a REST definition for a ArcGIS MapServer:
 <pre>gdalinfo "http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer?f=json&pretty=true"</pre><p>
 </p></li>
+
+<li><p>
+(GDAL >= 2.1.0) the URL of a IIP image:
+<pre>gdalinfo "IIP:http://merovingio.c2rmf.cnrs.fr/fcgi-bin/iipsrv.fcgi?FIF=globe.256x256.tif"</pre><p>
+</p></li>
 </ul>
 
 <h2>Generation of WMS service description XML file</h2>
diff --git a/frmts/wms/frmt_wms_iip.xml b/frmts/wms/frmt_wms_iip.xml
new file mode 100644
index 0000000..21fe4b4
--- /dev/null
+++ b/frmts/wms/frmt_wms_iip.xml
@@ -0,0 +1,14 @@
+<GDAL_WMS>
+    <Service name="IIP">
+        <ServerUrl>http://iipserver-genova.hdue.it/fast/iipsrv.fcgi?FIF=/mnt/links/ASGenova/./ArchiviodiStatodiGenova/RaccoltadeiTipidisegniemappedellArchiviodiStatodiGenova/Fondicartograficioriginari/MappeetipidellaRepubblicadiGenova/Cartericonducibiliallordinamentooriginario/AA%40[1]_0001_IMG1360.tif</ServerUrl>
+    </Service>
+    <DataWindow>
+        <SizeX>14658</SizeX>
+        <SizeY>6510</SizeY>
+        <TileLevel>6</TileLevel>
+    </DataWindow>
+    <BlockSizeX>256</BlockSizeX>
+    <BlockSizeY>256</BlockSizeY>
+    <BandsCount>3</BandsCount>
+    <Cache />
+</GDAL_WMS>
diff --git a/frmts/wms/gdalhttp.cpp b/frmts/wms/gdalhttp.cpp
index 71076c2..8024e2c 100644
--- a/frmts/wms/gdalhttp.cpp
+++ b/frmts/wms/gdalhttp.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalhttp.cpp 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: gdalhttp.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -15,7 +15,7 @@
  * to deal in the Software without restriction, including without limitation
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions: 
+ * Software is furnished to do so, subject to the following conditions:
  *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
@@ -70,14 +70,14 @@ void CPLHTTPInitializeRequest(CPLHTTPRequest *psRequest, const char *pszURL, con
     psRequest->pszURL = CPLStrdup(pszURL);
     psRequest->papszOptions = CSLDuplicate(const_cast<char **>(papszOptions));
     psRequest->nStatus = 0;
-    psRequest->pszContentType = 0;
-    psRequest->pszError = 0;
-    psRequest->pabyData = 0;
+    psRequest->pszContentType = NULL;
+    psRequest->pszError = NULL;
+    psRequest->pabyData = NULL;
     psRequest->nDataLen = 0;
     psRequest->nDataAlloc = 0;
-    psRequest->m_curl_handle = 0;
-    psRequest->m_headers = 0;
-    psRequest->m_curl_error = 0;
+    psRequest->m_curl_handle = NULL;
+    psRequest->m_headers = NULL;
+    psRequest->m_curl_error = NULL;
 
     psRequest->m_curl_handle = curl_easy_init();
     if (psRequest->m_curl_handle == NULL) {
@@ -108,7 +108,7 @@ void CPLHTTPInitializeRequest(CPLHTTPRequest *psRequest, const char *pszURL, con
     psRequest->m_curl_error = reinterpret_cast<char *>(CPLMalloc(CURL_ERROR_SIZE + 1));
     psRequest->m_curl_error[0] = '\0';
     curl_easy_setopt(psRequest->m_curl_handle, CURLOPT_ERRORBUFFER, psRequest->m_curl_error);
-    
+
     CPLHTTPSetOptions(psRequest->m_curl_handle, papszOptionsDup);
 
     CSLDestroy(papszOptionsDup);
@@ -117,48 +117,75 @@ void CPLHTTPInitializeRequest(CPLHTTPRequest *psRequest, const char *pszURL, con
 void CPLHTTPCleanupRequest(CPLHTTPRequest *psRequest) {
     if (psRequest->m_curl_handle) {
         curl_easy_cleanup(psRequest->m_curl_handle);
-        psRequest->m_curl_handle = 0;
+        psRequest->m_curl_handle = NULL;
     }
     if (psRequest->m_headers) {
         curl_slist_free_all(psRequest->m_headers);
-        psRequest->m_headers = 0;
+        psRequest->m_headers = NULL;
     }
     if (psRequest->m_curl_error) {
         CPLFree(psRequest->m_curl_error);
-        psRequest->m_curl_error = 0;
+        psRequest->m_curl_error = NULL;
     }
 
     if (psRequest->pszContentType) {
         CPLFree(psRequest->pszContentType);
-        psRequest->pszContentType = 0;
+        psRequest->pszContentType = NULL;
     }
     if (psRequest->pszError) {
         CPLFree(psRequest->pszError);
-        psRequest->pszError = 0;
+        psRequest->pszError = NULL;
     }
     if (psRequest->pabyData) {
         CPLFree(psRequest->pabyData);
-        psRequest->pabyData = 0;
+        psRequest->pabyData = NULL;
         psRequest->nDataLen = 0;
         psRequest->nDataAlloc = 0;
     }
     if (psRequest->papszOptions) {
         CSLDestroy(psRequest->papszOptions);
-        psRequest->papszOptions = 0;
+        psRequest->papszOptions = NULL;
     }
     if (psRequest->pszURL) {
         CPLFree(psRequest->pszURL);
-        psRequest->pszURL = 0;
+        psRequest->pszURL = NULL;
     }
 }
 
 CPLErr CPLHTTPFetchMulti(CPLHTTPRequest *pasRequest, int nRequestCount, const char *const *papszOptions) {
     CPLErr ret = CE_None;
-    CURLM *curl_multi = 0;
+    CURLM *curl_multi = NULL;
     int still_running;
     int max_conn;
     int i, conn_i;
 
+    if( nRequestCount > 0 &&
+        STARTS_WITH(pasRequest[0].pszURL, "/vsimem/") &&
+        /* Disabled by default for potential security issues */
+        CPLTestBool(CPLGetConfigOption("CPL_CURL_ENABLE_VSIMEM", "FALSE")) )
+    {
+        for(i = 0; i< nRequestCount;i++)
+        {
+            CPLHTTPResult* psResult = CPLHTTPFetch(pasRequest[i].pszURL, (char**)papszOptions);
+            pasRequest[i].pabyData = psResult->pabyData;
+            pasRequest[i].nDataLen = psResult->nDataLen;
+            pasRequest[i].pszError = psResult->pszErrBuf;
+            // Conventions a bit different between this module and cpl_http...
+            if( psResult->pszErrBuf != NULL &&
+                strcmp(psResult->pszErrBuf, "HTTP error code : 404") == 0 )
+                pasRequest[i].nStatus = 404;
+            else
+                pasRequest[i].nStatus = 200;
+            pasRequest[i].pszContentType = psResult->pszContentType;
+            psResult->pabyData = NULL;
+            psResult->nDataLen = 0;
+            psResult->pszErrBuf = NULL;
+            psResult->pszContentType = NULL;
+            CPLHTTPDestroyResult(psResult);
+        }
+        return CE_None;
+    }
+
     const char *max_conn_opt = CSLFetchNameValue(const_cast<char **>(papszOptions), "MAXCONN");
     if (max_conn_opt && (max_conn_opt[0] != '\0')) {
         max_conn = MAX(1, MIN(atoi(max_conn_opt), 1000));
@@ -207,7 +234,11 @@ CPLErr CPLHTTPFetchMulti(CPLHTTPRequest *pasRequest, int nRequestCount, const ch
         {
             timeout.tv_sec = 0;
             timeout.tv_usec = 100000;
-            select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
+            if( select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout) < 0 )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "select() failed");
+                break;
+            }
         }
         while (curl_multi_perform(curl_multi, &still_running) == CURLM_CALL_MULTI_PERFORM);
     }
@@ -220,9 +251,9 @@ CPLErr CPLHTTPFetchMulti(CPLHTTPRequest *pasRequest, int nRequestCount, const ch
 
         long response_code = 0;
         curl_easy_getinfo(psRequest->m_curl_handle, CURLINFO_RESPONSE_CODE, &response_code);
-        psRequest->nStatus = response_code;
+        psRequest->nStatus = static_cast<int>(response_code);
 
-        char *content_type = 0;
+        char *content_type = NULL;
         curl_easy_getinfo(psRequest->m_curl_handle, CURLINFO_CONTENT_TYPE, &content_type);
         if (content_type) psRequest->pszContentType = CPLStrdup(content_type);
 
@@ -232,7 +263,7 @@ CPLErr CPLHTTPFetchMulti(CPLHTTPRequest *pasRequest, int nRequestCount, const ch
 
         /* In the case of a file:// URL, curl will return a status == 0, so if there's no */
         /* error returned, patch the status code to be 200, as it would be for http:// */
-        if (strncmp(psRequest->pszURL, "file://", 7) == 0 && psRequest->nStatus == 0 &&
+        if (STARTS_WITH(psRequest->pszURL, "file://") && psRequest->nStatus == 0 &&
             psRequest->pszError == NULL)
         {
             psRequest->nStatus = 200;
diff --git a/frmts/wms/gdalhttp.h b/frmts/wms/gdalhttp.h
index 6c4ed71..811ba8e 100644
--- a/frmts/wms/gdalhttp.h
+++ b/frmts/wms/gdalhttp.h
@@ -1,5 +1,5 @@
-/***************************************************************************** 
- * $Id: gdalhttp.h 18020 2009-11-14 14:33:20Z rouault $
+/*****************************************************************************
+ * $Id: gdalhttp.h 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -51,6 +51,6 @@ typedef struct {
     char *m_curl_error;
 } CPLHTTPRequest;
 
-void CPL_DLL CPLHTTPInitializeRequest(CPLHTTPRequest *psRequest, const char *pszURL = 0, const char *const *papszOptions = 0);
+void CPL_DLL CPLHTTPInitializeRequest(CPLHTTPRequest *psRequest, const char *pszURL = NULL, const char *const *papszOptions = NULL);
 void CPL_DLL CPLHTTPCleanupRequest(CPLHTTPRequest *psRequest);
-CPLErr CPL_DLL CPLHTTPFetchMulti(CPLHTTPRequest *pasRequest, int nRequestCount = 1, const char *const *papszOptions = 0);
+CPLErr CPL_DLL CPLHTTPFetchMulti(CPLHTTPRequest *pasRequest, int nRequestCount = 1, const char *const *papszOptions = NULL);
diff --git a/frmts/wms/gdalwmscache.cpp b/frmts/wms/gdalwmscache.cpp
index 20026be..78a05a6 100644
--- a/frmts/wms/gdalwmscache.cpp
+++ b/frmts/wms/gdalwmscache.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalwmscache.cpp 27554 2014-08-02 17:46:37Z rouault $
+ * $Id: gdalwmscache.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -40,9 +40,9 @@ GDALWMSCache::~GDALWMSCache() {
 }
 
 CPLErr GDALWMSCache::Initialize(CPLXMLNode *config) {
-    const char *xmlcache_path = CPLGetXMLValue(config, "Path", NULL); 
-    const char *usercache_path = CPLGetConfigOption("GDAL_DEFAULT_WMS_CACHE_PATH", NULL); 
-    if(xmlcache_path) 
+    const char *xmlcache_path = CPLGetXMLValue(config, "Path", NULL);
+    const char *usercache_path = CPLGetConfigOption("GDAL_DEFAULT_WMS_CACHE_PATH", NULL);
+    if(xmlcache_path)
     {
         m_cache_path = xmlcache_path;
     }
@@ -54,7 +54,7 @@ CPLErr GDALWMSCache::Initialize(CPLXMLNode *config) {
         }
         else
         {
-            m_cache_path = "./gdalwmscache"; 
+            m_cache_path = "./gdalwmscache";
         }
     }
 
diff --git a/frmts/wms/gdalwmsdataset.cpp b/frmts/wms/gdalwmsdataset.cpp
index ff95daa..acf46a9 100644
--- a/frmts/wms/gdalwmsdataset.cpp
+++ b/frmts/wms/gdalwmsdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalwmsdataset.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: gdalwmsdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -30,10 +30,10 @@
  ****************************************************************************
  *
  * dataset.cpp:
- * Initialization of the GDALWMSdriver, parsing the XML configuration file, 
- * instantiation of the minidrivers and accessors used by minidrivers
+ * Initialization of the GDALWMSdriver, parsing the XML configuration file,
+ * instantiation of the minidrivers and accessors used by minidrivers.
  *
- ***************************************************************************/ 
+ ***************************************************************************/
 
 
 #include "wmsdriver.h"
@@ -48,9 +48,17 @@
 /************************************************************************/
 /*                           GDALWMSDataset()                           */
 /************************************************************************/
-GDALWMSDataset::GDALWMSDataset() {
-    m_mini_driver = 0;
-    m_cache = 0;
+GDALWMSDataset::GDALWMSDataset() :
+    m_block_size_x(0),
+    m_block_size_y(0),
+    m_use_advise_read(0),
+    m_verify_advise_read(0),
+    m_offline_mode(0),
+    m_http_max_conn(0),
+    m_http_timeout(0)
+{
+    m_mini_driver = NULL;
+    m_cache = NULL;
     m_hint.m_valid = false;
     m_data_type = GDT_Byte;
     m_clamp_requests = true;
@@ -364,8 +372,8 @@ CPLErr GDALWMSDataset::Initialize(CPLXMLNode *config) {
             }
         }
     }
-    
-    // UserPwd 
+
+    // UserPwd
     const char *pszUserPwd = CPLGetXMLValue(config, "UserPwd", "");
     if (pszUserPwd[0] != '\0')
         m_osUserPwd = pszUserPwd;
@@ -373,11 +381,11 @@ CPLErr GDALWMSDataset::Initialize(CPLXMLNode *config) {
     const char *pszUserAgent = CPLGetXMLValue(config, "UserAgent", "");
     if (pszUserAgent[0] != '\0')
         m_osUserAgent = pszUserAgent;
-    
+
     const char *pszReferer = CPLGetXMLValue(config, "Referer", "");
     if (pszReferer[0] != '\0')
         m_osReferer = pszReferer;
-    
+
     if (ret == CE_None) {
         const char *pszHttpZeroBlockCodes = CPLGetXMLValue(config, "ZeroBlockHttpCodes", "");
         if(pszHttpZeroBlockCodes[0] == '\0') {
@@ -492,7 +500,7 @@ CPLErr GDALWMSDataset::Initialize(CPLXMLNode *config) {
     if (ret == CE_None) {
         // Data values are attributes, they include NoData Min and Max
         // TODO: document those options
-        if (0!=CPLGetXMLNode(config,"DataValues")) {
+        if (NULL!=CPLGetXMLNode(config,"DataValues")) {
             const char *nodata=CPLGetXMLValue(config,"DataValues.NoData",NULL);
             if (nodata!=NULL) WMSSetNoDataValue(nodata);
             const char *min=CPLGetXMLValue(config,"DataValues.min",NULL);
@@ -514,19 +522,19 @@ CPLErr GDALWMSDataset::Initialize(CPLXMLNode *config) {
             }
         }
     }
-    
+
     if (ret == CE_None) {
     	const int v = StrToBool(CPLGetXMLValue(config, "UnsafeSSL", "false"));
     	if (v == -1) {
 	    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of UnsafeSSL: true or false expected.");
 	    ret = CE_Failure;
-	} else {
+        } else {
 	    m_unsafeSsl = v;
-	}
+        }
     }
 
     if (ret == CE_None) {
-        /* If we dont have projection already set ask mini-driver. */
+        /* If we do not have projection already set ask mini-driver. */
         if (!m_projection.size()) {
             const char *proj = m_mini_driver->GetProjectionInWKT();
             if (proj != NULL) {
@@ -585,6 +593,16 @@ CPLErr GDALWMSDataset::SetProjection(CPL_UNUSED const char *proj) {
 /*                          GetGeoTransform()                           */
 /************************************************************************/
 CPLErr GDALWMSDataset::GetGeoTransform(double *gt) {
+    if( !(m_mini_driver_caps.m_has_geotransform) )
+    {
+        gt[0] = 0;
+        gt[1] = 1;
+        gt[2] = 0;
+        gt[3] = 0;
+        gt[4] = 0;
+        gt[5] = 1;
+        return CE_Failure;
+    }
     gt[0] = m_data_window.m_x0;
     gt[1] = (m_data_window.m_x1 - m_data_window.m_x0) / static_cast<double>(m_data_window.m_sx);
     gt[2] = 0.0;
diff --git a/frmts/wms/gdalwmsrasterband.cpp b/frmts/wms/gdalwmsrasterband.cpp
index 16d0156..8a53692 100644
--- a/frmts/wms/gdalwmsrasterband.cpp
+++ b/frmts/wms/gdalwmsrasterband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalwmsrasterband.cpp 28562 2015-02-26 15:00:55Z rouault $
+ * $Id: gdalwmsrasterband.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  WMS Client Driver
  * Purpose:  GDALWMSRasterBand implementation.
@@ -41,8 +41,16 @@ GDALWMSRasterBand::GDALWMSRasterBand(GDALWMSDataset *parent_dataset, int band, d
         poDS = parent_dataset;
     else
         poDS = NULL;
-    nRasterXSize = static_cast<int>(m_parent_dataset->m_data_window.m_sx * scale + 0.5);
-    nRasterYSize = static_cast<int>(m_parent_dataset->m_data_window.m_sy * scale + 0.5);
+    if( parent_dataset->m_mini_driver_caps.m_overview_dim_computation_method == OVERVIEW_ROUNDED )
+    {
+        nRasterXSize = static_cast<int>(m_parent_dataset->m_data_window.m_sx * scale + 0.5);
+        nRasterYSize = static_cast<int>(m_parent_dataset->m_data_window.m_sy * scale + 0.5);
+    }
+    else
+    {
+        nRasterXSize = static_cast<int>(m_parent_dataset->m_data_window.m_sx * scale);
+        nRasterYSize = static_cast<int>(m_parent_dataset->m_data_window.m_sy * scale);
+    }
     nBand = band;
     eDataType = m_parent_dataset->m_data_type;
     nBlockXSize = m_parent_dataset->m_block_size_x;
@@ -80,7 +88,7 @@ char** GDALWMSRasterBand::BuildHTTPRequestOpts()
     if (m_parent_dataset->m_unsafeSsl >= 1) {
         http_request_opts = CSLAddString(http_request_opts, "UNSAFESSL=1");
     }
-    if (m_parent_dataset->m_osUserPwd.size() != 0) 
+    if (m_parent_dataset->m_osUserPwd.size() != 0)
     {
         CPLString osUserPwdOptStr("USERPWD=");
         osUserPwdOptStr += m_parent_dataset->m_osUserPwd;
@@ -132,16 +140,16 @@ CPLErr GDALWMSRasterBand::ReadBlocks(int x, int y, void *buffer, int bx0, int by
                     if (advise_read) {
                         need_this_block = false;
                     } else {
-                        void *p = 0;
+                        void *p = NULL;
                         if ((ix == x) && (iy == y)) p = buffer;
                         if (ReadBlockFromFile(ix, iy, file_name.c_str(), nBand, p, 0) == CE_None) need_this_block = false;
                     }
                 }
             }
             if (need_this_block) {
-                if (m_parent_dataset->m_offline_mode) {
+                if (/*m_parent_dataset->m_offline_mode */ download_blocks == NULL) {
                     if (!advise_read) {
-                        void *p = 0;
+                        void *p = NULL;
                         if ((ix == x) && (iy == y)) p = buffer;
                         if (ZeroBlock(ix, iy, nBand, p) != CE_None) {
                             CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: ZeroBlock failed.");
@@ -186,9 +194,9 @@ CPLErr GDALWMSRasterBand::ReadBlocks(int x, int y, void *buffer, int bx0, int by
                     /* check for error xml */
                     if (download_requests[i].nDataLen >= 20) {
                         const char *download_data = reinterpret_cast<char *>(download_requests[i].pabyData);
-                        if (EQUALN(download_data, "<?xml ", 6) 
-                        || EQUALN(download_data, "<!DOCTYPE ", 10)
-                        || EQUALN(download_data, "<ServiceException", 17)) {
+                        if (STARTS_WITH_CI(download_data, "<?xml ")
+                        || STARTS_WITH_CI(download_data, "<!DOCTYPE ")
+                        || STARTS_WITH_CI(download_data, "<ServiceException")) {
                             if (ReportWMSException(file_name.c_str()) != CE_None) {
                                 CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: The server returned unknown exception.");
                             }
@@ -202,7 +210,7 @@ CPLErr GDALWMSRasterBand::ReadBlocks(int x, int y, void *buffer, int bx0, int by
                                 cache->Write(download_requests[i].pszURL, file_name);
                             }
                         } else {
-                            void *p = 0;
+                            void *p = NULL;
                             if ((download_blocks[i].x == x) && (download_blocks[i].y == y)) p = buffer;
                             if (ReadBlockFromFile(download_blocks[i].x, download_blocks[i].y, file_name.c_str(), nBand, p, advise_read) == CE_None) {
                                 if (cache != NULL) {
@@ -215,7 +223,7 @@ CPLErr GDALWMSRasterBand::ReadBlocks(int x, int y, void *buffer, int bx0, int by
                             }
                         }
                     } else if( wms_exception && m_parent_dataset->m_zeroblock_on_serverexceptions ) {
-                         void *p = 0;
+                         void *p = NULL;
                          if ((download_blocks[i].x == x) && (download_blocks[i].y == y)) p = buffer;
                          if (ZeroBlock(download_blocks[i].x, download_blocks[i].y, nBand, p) != CE_None) {
                              CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: ZeroBlock failed.");
@@ -233,7 +241,7 @@ CPLErr GDALWMSRasterBand::ReadBlocks(int x, int y, void *buffer, int bx0, int by
                      download_requests[i].nStatus);
                if ( zero_it != m_parent_dataset->m_http_zeroblock_codes.end() ) {
                     if (!advise_read) {
-                        void *p = 0;
+                        void *p = NULL;
                         if ((download_blocks[i].x == x) && (download_blocks[i].y == y)) p = buffer;
                         if (ZeroBlock(download_blocks[i].x, download_blocks[i].y, nBand, p) != CE_None) {
                             CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: ZeroBlock failed.");
@@ -243,7 +251,7 @@ CPLErr GDALWMSRasterBand::ReadBlocks(int x, int y, void *buffer, int bx0, int by
                 } else {
                     CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Unable to download block %d, %d.\n  URL: %s\n  HTTP status code: %d, error: %s.\n"
                         "Add the HTTP status code to <ZeroBlockHttpCodes> to ignore that error (see http://www.gdal.org/frmt_wms.html).",
-                        download_blocks[i].x, download_blocks[i].y, download_requests[i].pszURL, download_requests[i].nStatus, 
+                        download_blocks[i].x, download_blocks[i].y, download_requests[i].pszURL, download_requests[i].nStatus,
 		    download_requests[i].pszError ? download_requests[i].pszError : "(null)");
                     ret = CE_Failure;
                 }
@@ -316,7 +324,7 @@ int GDALWMSRasterBand::HasArbitraryOverviews() {
 }
 
 int GDALWMSRasterBand::GetOverviewCount() {
-    return m_overviews.size();
+    return static_cast<int>(m_overviews.size());
 }
 
 GDALRasterBand *GDALWMSRasterBand::GetOverview(int n) {
@@ -374,7 +382,7 @@ void GDALWMSRasterBand::ComputeRequestInfo(GDALWMSImageRequestInfo &iri,
 	x1 = MIN(x1, nRasterXSize);
 	y1 = MIN(y1, nRasterYSize);
     }
-    
+
     const double rx = (m_parent_dataset->m_data_window.m_x1 - m_parent_dataset->m_data_window.m_x0) / static_cast<double>(nRasterXSize);
     const double ry = (m_parent_dataset->m_data_window.m_y1 - m_parent_dataset->m_data_window.m_y0) / static_cast<double>(nRasterYSize);
     /* Use different method for x0,y0 and x1,y1 to make sure calculated values are exact for corner requests */
@@ -409,19 +417,19 @@ const char *GDALWMSRasterBand::GetMetadataItem( const char * pszName,
 /* ==================================================================== */
     if( pszDomain != NULL
         && EQUAL(pszDomain,"LocationInfo")
-        && (EQUALN(pszName,"Pixel_",6) || EQUALN(pszName,"GeoPixel_",9)) )
+        && (STARTS_WITH_CI(pszName, "Pixel_") || STARTS_WITH_CI(pszName, "GeoPixel_")) )
     {
         int iPixel, iLine;
 
 /* -------------------------------------------------------------------- */
 /*      What pixel are we aiming at?                                    */
 /* -------------------------------------------------------------------- */
-        if( EQUALN(pszName,"Pixel_",6) )
+        if( STARTS_WITH_CI(pszName, "Pixel_") )
         {
             if( sscanf( pszName+6, "%d_%d", &iPixel, &iLine ) != 2 )
                 return NULL;
         }
-        else if( EQUALN(pszName,"GeoPixel_",9) )
+        else if( STARTS_WITH_CI(pszName, "GeoPixel_") )
         {
             double adfGeoTransform[6];
             double adfInvGeoTransform[6];
@@ -554,7 +562,7 @@ const char *GDALWMSRasterBand::GetMetadataItem( const char * pszName,
 
 CPLErr GDALWMSRasterBand::ReadBlockFromFile(int x, int y, const char *file_name, int to_buffer_band, void *buffer, int advise_read) {
     CPLErr ret = CE_None;
-    GDALDataset *ds = 0;
+    GDALDataset *ds = NULL;
     GByte *color_table = NULL;
     int i;
 
@@ -567,7 +575,7 @@ CPLErr GDALWMSRasterBand::ReadBlockFromFile(int x, int y, const char *file_name,
     if (ds != NULL) {
         int sx = ds->GetRasterXSize();
         int sy = ds->GetRasterYSize();
-        bool accepted_as_no_alpha = false;  // if the request is for 4 bands but the wms returns 3  
+        bool accepted_as_no_alpha = false;  // if the request is for 4 bands but the wms returns 3
         /* Allow bigger than expected so pre-tiled constant size images work on corners */
         if ((sx > nBlockXSize) || (sy > nBlockYSize) || (sx < esx) || (sy < esy)) {
             CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Incorrect size %d x %d of downloaded block, expected %d x %d, max %d x %d.",
@@ -613,7 +621,7 @@ CPLErr GDALWMSRasterBand::ReadBlockFromFile(int x, int y, const char *file_name,
                 }
                 else if (!accepted_as_ct) {
                    if (ds->GetRasterCount()==3 && m_parent_dataset->nBands == 4 && (eDataType == GDT_Byte))
-                   { // WMS returned a file with no alpha so we will fill the alpha band with "opaque" 
+                   { // WMS returned a file with no alpha so we will fill the alpha band with "opaque"
                       accepted_as_no_alpha = true;
                    }
                    else
@@ -671,9 +679,9 @@ CPLErr GDALWMSRasterBand::ReadBlockFromFile(int x, int y, const char *file_name,
                                {
                                   // the file had 3 bands and we are reading band 4 (Alpha) so fill with 255 (no alpha)
                                   GByte *byte_buffer = reinterpret_cast<GByte *>(p);
-                                  for (int y = 0; y < sy; ++y) {
-                                     for (int x = 0; x < sx; ++x) {
-                                        const int offset = x + y * line_space;
+                                  for (int l_y = 0; l_y < sy; ++l_y) {
+                                     for (int l_x = 0; l_x < sx; ++l_x) {
+                                        const int offset = l_x + l_y * line_space;
                                         byte_buffer[offset] = 255;  // fill with opaque
                                      }
                                   }
@@ -683,7 +691,7 @@ CPLErr GDALWMSRasterBand::ReadBlockFromFile(int x, int y, const char *file_name,
                                   CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Incorrect bands count %d in downloaded block, expected %d.",
                                      ds->GetRasterCount(), m_parent_dataset->nBands);
                                   ret = CE_Failure;
-                               }     
+                               }
                             }
                         } else if (ib <= 4) {
                             if (ds->RasterIO(GF_Read, 0, 0, sx, sy, p, sx, sy, eDataType, 1, NULL, pixel_space, line_space, 0, NULL) != CE_None) {
@@ -693,9 +701,9 @@ CPLErr GDALWMSRasterBand::ReadBlockFromFile(int x, int y, const char *file_name,
                             if (ret == CE_None) {
                                 GByte *band_color_table = color_table + 256 * (ib - 1);
                                 GByte *byte_buffer = reinterpret_cast<GByte *>(p);
-                                for (int y = 0; y < sy; ++y) {
-                                    for (int x = 0; x < sx; ++x) {
-                                        const int offset = x + y * line_space;
+                                for (int l_y = 0; l_y < sy; ++l_y) {
+                                    for (int l_x = 0; l_x < sx; ++l_x) {
+                                        const int offset = l_x + l_y * line_space;
                                         byte_buffer[offset] = band_color_table[byte_buffer[offset]];
                                     }
                                 }
@@ -748,9 +756,9 @@ CPLErr GDALWMSRasterBand::ZeroBlock(int x, int y, int to_buffer_band, void *buff
                 }
             }
             if (p != NULL) {
-                unsigned char *b = reinterpret_cast<unsigned char *>(p);
+                unsigned char *paby = reinterpret_cast<unsigned char *>(p);
                 int block_size = nBlockXSize * nBlockYSize * (GDALGetDataTypeSize(eDataType) / 8);
-                for (int i = 0; i < block_size; ++i) b[i] = 0;
+                for (int i = 0; i < block_size; ++i) paby[i] = 0;
             }
             if (b != NULL) {
                 b->DropLock();
diff --git a/frmts/wms/makefile.vc b/frmts/wms/makefile.vc
index 47da4d0..722eba6 100644
--- a/frmts/wms/makefile.vc
+++ b/frmts/wms/makefile.vc
@@ -4,7 +4,8 @@ OBJ	= \
 	gdalhttp.obj md5.obj minidriver.obj  wmsdriver.obj \
 	minidriver_wms.obj minidriver_tileservice.obj \
 	minidriver_worldwind.obj minidriver_tms.obj minidriver_tiled_wms.obj \
-	wmsmetadataset.obj minidriver_virtualearth.obj minidriver_arcgis_server.obj
+	wmsmetadataset.obj minidriver_virtualearth.obj minidriver_arcgis_server.obj \
+	minidriver_iip.obj
 
 EXTRAFLAGS = -DHAVE_CURL $(CURL_CFLAGS) $(CURL_INC)
 
diff --git a/frmts/wms/md5.cpp b/frmts/wms/md5.cpp
index 63dc7e1..dc2c2c2 100644
--- a/frmts/wms/md5.cpp
+++ b/frmts/wms/md5.cpp
@@ -58,10 +58,10 @@ putu32 (
         cvs_uint32 data,
         unsigned char *addr)
 {
-    addr[0] = (unsigned char)data;
-    addr[1] = (unsigned char)(data >> 8);
-    addr[2] = (unsigned char)(data >> 16);
-    addr[3] = (unsigned char)(data >> 24);
+    addr[0] = (unsigned char)(data & 0xff);
+    addr[1] = (unsigned char)((data >> 8) & 0xff);
+    addr[2] = (unsigned char)((data >> 16) & 0xff);
+    addr[3] = (unsigned char)((data >> 24) & 0xff); /* cvs_uint32 might be 64bit wide */
 }
 
 /*
@@ -115,7 +115,7 @@ struct cvs_MD5Context *ctx,
         memcpy(p, buf, t);
         cvs_MD5Transform (ctx->buf, ctx->in);
         buf += t;
-        len -= t;
+        len -= (unsigned)t;
     }
 
     /* Process data in 64-byte chunks */
@@ -133,7 +133,7 @@ struct cvs_MD5Context *ctx,
 }
 
 /*
-* Final wrapup - pad to 64-byte boundary with the bit pattern 
+* Final wrapup - pad to 64-byte boundary with the bit pattern
 * 1 0* (64-bit count of bits processed, MSB-first)
 */
 void
@@ -145,7 +145,7 @@ struct cvs_MD5Context *ctx)
     unsigned char *p;
 
     /* Compute number of bytes mod 64 */
-    count = (ctx->bits[0] >> 3) & 0x3F;
+    count = (unsigned)((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 */
@@ -204,7 +204,7 @@ cvs_MD5Transform (
                   cvs_uint32 buf[4],
                   const unsigned char inraw[64])
 {
-    register cvs_uint32 a, b, c, d;
+    cvs_uint32 a, b, c, d;
     cvs_uint32 in[16];
     int i;
 
diff --git a/frmts/wms/minidriver.cpp b/frmts/wms/minidriver.cpp
index 58d8856..6dbb7d0 100644
--- a/frmts/wms/minidriver.cpp
+++ b/frmts/wms/minidriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: minidriver.cpp 28459 2015-02-12 13:48:21Z rouault $
+ * $Id: minidriver.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  WMS Client Driver
  * Purpose:  GDALWMSMiniDriver base class implementation.
@@ -33,7 +33,7 @@ static volatile GDALWMSMiniDriverManager *g_mini_driver_manager = NULL;
 static CPLMutex *g_mini_driver_manager_mutex = NULL;
 
 GDALWMSMiniDriver::GDALWMSMiniDriver() {
-    m_parent_dataset = 0;
+    m_parent_dataset = NULL;
 }
 
 GDALWMSMiniDriver::~GDALWMSMiniDriver() {
@@ -86,12 +86,20 @@ GDALWMSMiniDriverManager *GetGDALWMSMiniDriverManager() {
 void DestroyWMSMiniDriverManager()
 
 {
-    CPLMutexHolderD(&g_mini_driver_manager_mutex);
+    {
+        CPLMutexHolderD(&g_mini_driver_manager_mutex);
+
+        if( g_mini_driver_manager != NULL )
+        {
+            delete g_mini_driver_manager;
+            g_mini_driver_manager = NULL;
+        }
+    }
 
-    if( g_mini_driver_manager != 0 )
+    if( g_mini_driver_manager_mutex != NULL )
     {
-        delete g_mini_driver_manager;
-        g_mini_driver_manager = NULL;
+        CPLDestroyMutex(g_mini_driver_manager_mutex);
+        g_mini_driver_manager_mutex = NULL;
     }
 }
 
@@ -99,7 +107,7 @@ GDALWMSMiniDriverManager::GDALWMSMiniDriverManager() {
 }
 
 GDALWMSMiniDriverManager::~GDALWMSMiniDriverManager() {
-    for (std::list<GDALWMSMiniDriverFactory *>::iterator it = m_mdfs.begin(); 
+    for (std::list<GDALWMSMiniDriverFactory *>::iterator it = m_mdfs.begin();
          it != m_mdfs.end(); ++it) {
         GDALWMSMiniDriverFactory *mdf = *it;
         delete mdf;
diff --git a/frmts/wms/minidriver_arcgis_server.cpp b/frmts/wms/minidriver_arcgis_server.cpp
index 6dd62c9..2c358e2 100644
--- a/frmts/wms/minidriver_arcgis_server.cpp
+++ b/frmts/wms/minidriver_arcgis_server.cpp
@@ -43,50 +43,50 @@ GDALWMSMiniDriver_AGS::~GDALWMSMiniDriver_AGS()
 
 CPLErr GDALWMSMiniDriver_AGS::Initialize(CPLXMLNode *config)
 {
-	CPLErr ret = CE_None;
-	int i;
+    CPLErr ret = CE_None;
+    int i;
 
-    if (ret == CE_None) 
+    if (ret == CE_None)
     {
         const char *base_url = CPLGetXMLValue(config, "ServerURL", "");
-        if (base_url[0] != '\0') 
+        if (base_url[0] != '\0')
         {
             /* Try the old name */
             base_url = CPLGetXMLValue(config, "ServerUrl", "");
         }
-        
-        if (base_url[0] != '\0') 
+
+        if (base_url[0] != '\0')
         {
             m_base_url = base_url;
         }
-        else 
+        else
         {
             CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS, ArcGIS Server mini-driver: ServerURL missing.");
             ret = CE_Failure;
         }
     }
 
-	if (ret == CE_None) 
+	if (ret == CE_None)
 	{
         m_image_format = CPLGetXMLValue(config, "ImageFormat", "png");
         m_transparent = CPLGetXMLValue(config, "Transparent","");
-		// the transparent flag needs to be "true" or "false" 
+		// the transparent flag needs to be "true" or "false"
 		// in lower case according to the ArcGIS Server REST API
         for(i = 0; i < (int)m_transparent.size(); i++)
         {
 			m_transparent[i] = (char) tolower(m_transparent[i]);
         }
-        
+
 		m_layers = CPLGetXMLValue(config, "Layers", "");
     }
-    
-	if (ret == CE_None) 
+
+	if (ret == CE_None)
 	{
 		const char* irs = CPLGetXMLValue(config, "SRS", "102100");
-		
+
 		if (irs != NULL)
 		{
-	        if(EQUALN(irs, "EPSG:", 5)) //if we have EPSG code just convert it to WKT
+	        if(STARTS_WITH_CI(irs, "EPSG:")) //if we have EPSG code just convert it to WKT
 	        {
 	            m_projection_wkt = ProjToWKT(irs);
 	            m_irs = irs + 5;
@@ -96,7 +96,7 @@ CPLErr GDALWMSMiniDriver_AGS::Initialize(CPLXMLNode *config)
 		        m_irs = irs;
 		        m_projection_wkt = ProjToWKT("EPSG:" + m_irs);
 		    }
-		    // TODO: if we have AGS JSON    
+		    // TODO: if we have AGS JSON
 		}
 		m_identification_tolerance = CPLGetXMLValue(config, "IdentificationTolerance", "2");
 	}
@@ -104,36 +104,36 @@ CPLErr GDALWMSMiniDriver_AGS::Initialize(CPLXMLNode *config)
 	if (ret == CE_None)
 	{
         const char *bbox_order = CPLGetXMLValue(config, "BBoxOrder", "xyXY");
-        if (bbox_order[0] != '\0') 
+        if (bbox_order[0] != '\0')
         {
-            for (i = 0; i < 4; ++i) 
+            for (i = 0; i < 4; ++i)
             {
-                if ((bbox_order[i] != 'x') && (bbox_order[i] != 'y') && 
-                    (bbox_order[i] != 'X') && (bbox_order[i] != 'Y')) 
+                if ((bbox_order[i] != 'x') && (bbox_order[i] != 'y') &&
+                    (bbox_order[i] != 'X') && (bbox_order[i] != 'Y'))
                     break;
             }
-            
-            if (i == 4) 
+
+            if (i == 4)
             {
                 m_bbox_order = bbox_order;
-            } 
-            else 
+            }
+            else
             {
                 CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS, ArcGIS Server mini-driver: Incorrect BBoxOrder.");
                 ret = CE_Failure;
             }
-        } 
+        }
         else
         {
             CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS, ArcGIS Server mini-driver: BBoxOrder missing.");
             ret = CE_Failure;
         }
     }
-	
+
     return ret;
 }
 
-void GDALWMSMiniDriver_AGS::GetCapabilities(GDALWMSMiniDriverCapabilities *caps) 
+void GDALWMSMiniDriver_AGS::GetCapabilities(GDALWMSMiniDriverCapabilities *caps)
 {
     caps->m_capabilities_version = 1;
     caps->m_has_arb_overviews = 1;
@@ -142,41 +142,41 @@ void GDALWMSMiniDriver_AGS::GetCapabilities(GDALWMSMiniDriverCapabilities *caps)
     caps->m_max_overview_count = 32;
 }
 
-void GDALWMSMiniDriver_AGS::ImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri) 
+void GDALWMSMiniDriver_AGS::ImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri)
 {
     *url = m_base_url;
 
     if (m_base_url.ifind( "/export?") == std::string::npos)
         URLAppend(url, "/export?");
-	
-	URLAppendF(url, "&f=image");
-	URLAppendF(url, "&bbox=%.8f,%.8f,%.8f,%.8f", 
-		GetBBoxCoord(iri, m_bbox_order[0]), GetBBoxCoord(iri, m_bbox_order[1]), 
-        GetBBoxCoord(iri, m_bbox_order[2]), GetBBoxCoord(iri, m_bbox_order[3]));
-	URLAppendF(url, "&size=%d,%d", iri.m_sx,iri.m_sy);
-	URLAppendF(url, "&dpi=");
-	URLAppendF(url, "&imageSR=%s", m_irs.c_str());
-	URLAppendF(url, "&bboxSR=%s", m_irs.c_str());
-	URLAppendF(url, "&format=%s", m_image_format.c_str());
-
-	URLAppendF(url, "&layerdefs=");
-	URLAppendF(url, "&layers=%s", m_layers.c_str());
+
+    URLAppendF(url, "&f=image");
+    URLAppendF(url, "&bbox=%.8f,%.8f,%.8f,%.8f",
+            GetBBoxCoord(iri, m_bbox_order[0]), GetBBoxCoord(iri, m_bbox_order[1]),
+    GetBBoxCoord(iri, m_bbox_order[2]), GetBBoxCoord(iri, m_bbox_order[3]));
+    URLAppendF(url, "&size=%d,%d", iri.m_sx,iri.m_sy);
+    URLAppendF(url, "&dpi=");
+    URLAppendF(url, "&imageSR=%s", m_irs.c_str());
+    URLAppendF(url, "&bboxSR=%s", m_irs.c_str());
+    URLAppendF(url, "&format=%s", m_image_format.c_str());
+
+    URLAppendF(url, "&layerdefs=");
+    URLAppendF(url, "&layers=%s", m_layers.c_str());
 
     if(m_transparent.size())
-	    URLAppendF(url, "&transparent=%s", m_transparent.c_str());
+        URLAppendF(url, "&transparent=%s", m_transparent.c_str());
     else
         URLAppendF(url, "&transparent=%s", "false");
-        
-	URLAppendF(url, "&time=");
-	URLAppendF(url, "&layerTimeOptions=");
-	URLAppendF(url, "&dynamicLayers=");
 
-	CPLDebug("AGS", "URL = %s\n", url->c_str());
+    URLAppendF(url, "&time=");
+    URLAppendF(url, "&layerTimeOptions=");
+    URLAppendF(url, "&dynamicLayers=");
+
+    CPLDebug("AGS", "URL = %s\n", url->c_str());
 }
 
-void GDALWMSMiniDriver_AGS::TiledImageRequest(CPLString *url, 
-                                      const GDALWMSImageRequestInfo &iri, 
-                                      const GDALWMSTiledImageRequestInfo &tiri) 
+void GDALWMSMiniDriver_AGS::TiledImageRequest(CPLString *url,
+                                      const GDALWMSImageRequestInfo &iri,
+                                      CPL_UNUSED const GDALWMSTiledImageRequestInfo &tiri)
 {
 	ImageRequest(url, iri);
 }
@@ -184,7 +184,7 @@ void GDALWMSMiniDriver_AGS::TiledImageRequest(CPLString *url,
 
 void GDALWMSMiniDriver_AGS::GetTiledImageInfo(CPLString *url,
                                               const GDALWMSImageRequestInfo &iri,
-                                              const GDALWMSTiledImageRequestInfo &tiri,
+                                              CPL_UNUSED const GDALWMSTiledImageRequestInfo &tiri,
                                               int nXInBlock,
                                               int nYInBlock)
 {
@@ -193,65 +193,65 @@ void GDALWMSMiniDriver_AGS::GetTiledImageInfo(CPLString *url,
     if (m_base_url.ifind( "/identify?") == std::string::npos)
         URLAppend(url, "/identify?");
 
-	URLAppendF(url, "&f=json");
+    URLAppendF(url, "&f=json");
+
+    double fX = GetBBoxCoord(iri, 'x') + nXInBlock * (GetBBoxCoord(iri, 'X') -
+                GetBBoxCoord(iri, 'x')) / iri.m_sx;
+    double fY = GetBBoxCoord(iri, 'y') + (iri.m_sy - nYInBlock) * (GetBBoxCoord(iri, 'Y') -
+                GetBBoxCoord(iri, 'y')) / iri.m_sy;
 
-	double fX = GetBBoxCoord(iri, 'x') + nXInBlock * (GetBBoxCoord(iri, 'X') - 
-	            GetBBoxCoord(iri, 'x')) / iri.m_sx;
-	double fY = GetBBoxCoord(iri, 'y') + (iri.m_sy - nYInBlock) * (GetBBoxCoord(iri, 'Y') - 
-	            GetBBoxCoord(iri, 'y')) / iri.m_sy;
-	            
     URLAppendF(url, "&geometry=%8f,%8f", fX, fY);
-	URLAppendF(url, "&geometryType=esriGeometryPoint");
+    URLAppendF(url, "&geometryType=esriGeometryPoint");
 
-	URLAppendF(url, "&sr=%s", m_irs.c_str());
-	URLAppendF(url, "&layerdefs=");
-	URLAppendF(url, "&time=");
-	URLAppendF(url, "&layerTimeOptions=");
+    URLAppendF(url, "&sr=%s", m_irs.c_str());
+    URLAppendF(url, "&layerdefs=");
+    URLAppendF(url, "&time=");
+    URLAppendF(url, "&layerTimeOptions=");
 
-	CPLString layers("visible");
-	if ( m_layers.find("show") != std::string::npos )
-	{
-		layers = m_layers;
-		layers.replace( layers.find("show"), 4, "all" );
-	}
-	
-	if ( m_layers.find("hide") != std::string::npos )
-	{
-		layers = "top";
-	}
-	
-	if ( m_layers.find("include") != std::string::npos )
-	{
-		layers = "top";
-	}
-	
-	if ( m_layers.find("exclude") != std::string::npos )
-	{
-		layers = "top";
-	}
+    CPLString layers("visible");
+    if ( m_layers.find("show") != std::string::npos )
+    {
+            layers = m_layers;
+            layers.replace( layers.find("show"), 4, "all" );
+    }
 
-	URLAppendF(url, "&layers=%s", layers.c_str());
+    if ( m_layers.find("hide") != std::string::npos )
+    {
+            layers = "top";
+    }
 
-	URLAppendF(url, "&tolerance=%s", m_identification_tolerance.c_str());
-	URLAppendF(url, "&mapExtent=%.8f,%.8f,%.8f,%.8f", 
-		GetBBoxCoord(iri, m_bbox_order[0]), GetBBoxCoord(iri, m_bbox_order[1]), 
-        GetBBoxCoord(iri, m_bbox_order[2]), GetBBoxCoord(iri, m_bbox_order[3]));
-	URLAppendF(url, "&imageDisplay=%d,%d,96", iri.m_sx,iri.m_sy);
-	URLAppendF(url, "&returnGeometry=false");
+    if ( m_layers.find("include") != std::string::npos )
+    {
+            layers = "top";
+    }
+
+    if ( m_layers.find("exclude") != std::string::npos )
+    {
+            layers = "top";
+    }
+
+    URLAppendF(url, "&layers=%s", layers.c_str());
 
-	URLAppendF(url, "&maxAllowableOffset=");
+    URLAppendF(url, "&tolerance=%s", m_identification_tolerance.c_str());
+    URLAppendF(url, "&mapExtent=%.8f,%.8f,%.8f,%.8f",
+            GetBBoxCoord(iri, m_bbox_order[0]), GetBBoxCoord(iri, m_bbox_order[1]),
+    GetBBoxCoord(iri, m_bbox_order[2]), GetBBoxCoord(iri, m_bbox_order[3]));
+    URLAppendF(url, "&imageDisplay=%d,%d,96", iri.m_sx,iri.m_sy);
+    URLAppendF(url, "&returnGeometry=false");
+
+    URLAppendF(url, "&maxAllowableOffset=");
     CPLDebug("AGS", "URL = %s", url->c_str());
 }
 
 
-const char *GDALWMSMiniDriver_AGS::GetProjectionInWKT() 
+const char *GDALWMSMiniDriver_AGS::GetProjectionInWKT()
 {
     return m_projection_wkt.c_str();
 }
 
-double GDALWMSMiniDriver_AGS::GetBBoxCoord(const GDALWMSImageRequestInfo &iri, char what) 
+double GDALWMSMiniDriver_AGS::GetBBoxCoord(const GDALWMSImageRequestInfo &iri, char what)
 {
-    switch (what) 
+    switch (what)
     {
         case 'x': return MIN(iri.m_x0, iri.m_x1);
         case 'y': return MIN(iri.m_y0, iri.m_y1);
@@ -260,4 +260,3 @@ double GDALWMSMiniDriver_AGS::GetBBoxCoord(const GDALWMSImageRequestInfo &iri, c
     }
     return 0.0;
 }
-
diff --git a/frmts/wms/minidriver_arcgis_server.h b/frmts/wms/minidriver_arcgis_server.h
index 28c0006..9806b56 100644
--- a/frmts/wms/minidriver_arcgis_server.h
+++ b/frmts/wms/minidriver_arcgis_server.h
@@ -40,7 +40,7 @@ public:
     virtual CPLErr Initialize(CPLXMLNode *config);
     virtual void GetCapabilities(GDALWMSMiniDriverCapabilities *caps);
     virtual void ImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri);
-    virtual void TiledImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri, 
+    virtual void TiledImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri,
                                    const GDALWMSTiledImageRequestInfo &tiri);
     virtual void GetTiledImageInfo(CPLString *url,
                                    const GDALWMSImageRequestInfo &iri,
@@ -54,10 +54,10 @@ protected:
 
 protected:
     CPLString m_base_url;
-	/* 
-	 * png | png8 | png24 | jpg | pdf | bmp | gif | svg | png32  
-	 * http://resources.arcgis.com/en/help/rest/apiref/  
-	 * Parameter - format 
+	/*
+	 * png | png8 | png24 | jpg | pdf | bmp | gif | svg | png32
+	 * http://resources.arcgis.com/en/help/rest/apiref/
+	 * Parameter - format
 	 */
 	CPLString m_image_format;
 	CPLString m_transparent;
@@ -71,4 +71,3 @@ protected:
 
 	CPLString m_identification_tolerance;
 };
-
diff --git a/frmts/wms/minidriver_iip.cpp b/frmts/wms/minidriver_iip.cpp
new file mode 100644
index 0000000..9598564
--- /dev/null
+++ b/frmts/wms/minidriver_iip.cpp
@@ -0,0 +1,81 @@
+/******************************************************************************
+ * $Id: minidriver_iip.cpp 33844 2016-04-01 08:42:13Z rouault $
+ *
+ * Project:  WMS Client Driver
+ * Purpose:  Mini driver for Internet Imaging Protocol (IIP)
+ * Author:   Even Rouault <even.rouault at spatialys.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "wmsdriver.h"
+#include "minidriver_iip.h"
+
+
+CPP_GDALWMSMiniDriverFactory(IIP)
+
+GDALWMSMiniDriver_IIP::GDALWMSMiniDriver_IIP() {
+}
+
+GDALWMSMiniDriver_IIP::~GDALWMSMiniDriver_IIP() {
+}
+
+CPLErr GDALWMSMiniDriver_IIP::Initialize(CPLXMLNode *config) {
+    CPLErr ret = CE_None;
+
+    if (ret == CE_None) {
+        const char *base_url = CPLGetXMLValue(config, "ServerURL", "");
+        if (base_url[0] != '\0') {
+            m_base_url = base_url;
+        } else {
+            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS, IIP mini-driver: ServerURL missing.");
+            ret = CE_Failure;
+        }
+    }
+
+    return ret;
+}
+
+void GDALWMSMiniDriver_IIP::GetCapabilities(GDALWMSMiniDriverCapabilities *caps) {
+    caps->m_capabilities_version = 1;
+    caps->m_has_arb_overviews = 0;
+    caps->m_has_image_request = 0;
+    caps->m_has_tiled_image_requeset = 1;
+    caps->m_max_overview_count = 32;
+    caps->m_overview_dim_computation_method = OVERVIEW_FLOOR;
+    caps->m_has_geotransform = false;
+}
+
+void GDALWMSMiniDriver_IIP::TiledImageRequest(
+    CPLString *url,
+    const GDALWMSImageRequestInfo & /* iri */,
+    const GDALWMSTiledImageRequestInfo &tiri)
+{
+    int nTileXCount = (
+        (m_parent_dataset->GetRasterXSize()
+         >> (m_parent_dataset->GetRasterBand(1)->GetOverviewCount()
+          - tiri.m_level)) + 255) / 256;
+    int numTile = tiri.m_x + tiri.m_y * nTileXCount;
+
+    *url = m_base_url;
+    *url += CPLSPrintf("&jtl=%d,%d", tiri.m_level, numTile);
+}
diff --git a/frmts/wms/minidriver_iip.h b/frmts/wms/minidriver_iip.h
new file mode 100644
index 0000000..99552f9
--- /dev/null
+++ b/frmts/wms/minidriver_iip.h
@@ -0,0 +1,44 @@
+/******************************************************************************
+ * $Id: minidriver_iip.h 33844 2016-04-01 08:42:13Z rouault $
+ *
+ * Project:  WMS Client Driver
+ * Purpose:  Mini driver for Internet Imaging Protocol (IIP)
+ * Author:   Even Rouault <even.rouault at spatialys.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+H_GDALWMSMiniDriverFactory(IIP)
+
+class GDALWMSMiniDriver_IIP : public GDALWMSMiniDriver {
+public:
+    GDALWMSMiniDriver_IIP();
+    virtual ~GDALWMSMiniDriver_IIP();
+
+public:
+    virtual CPLErr Initialize(CPLXMLNode *config);
+    virtual void GetCapabilities(GDALWMSMiniDriverCapabilities *caps);
+    virtual void TiledImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri, const GDALWMSTiledImageRequestInfo &tiri);
+
+protected:
+    CPLString m_base_url;
+};
diff --git a/frmts/wms/minidriver_tiled_wms.cpp b/frmts/wms/minidriver_tiled_wms.cpp
index e96d744..373f764 100644
--- a/frmts/wms/minidriver_tiled_wms.cpp
+++ b/frmts/wms/minidriver_tiled_wms.cpp
@@ -34,7 +34,7 @@
 
 CPP_GDALWMSMiniDriverFactory(TiledWMS)
 
-static char SIG[]="GDAL_WMS TiledWMS: ";
+static const char SIG[]="GDAL_WMS TiledWMS: ";
 
 /*
  *\brief Read a number from an xml element
@@ -70,14 +70,14 @@ static GDALColorEntry GetXMLColorEntry(CPLXMLNode *p)
  *
  * Searches only the next siblings of the node passed in for the named element or attribute.
  * If the first character of the pszElement is '=', the search includes the psRoot node
- * 
+ *
  * @param psRoot the root node to search.  This should be a node of type
  * CXT_Element.  NULL is safe.
  *
  * @param pszElement the name of the element or attribute to search for.
  *
  *
- * @return The first matching node or NULL on failure. 
+ * @return The first matching node or NULL on failure.
  */
 
 static CPLXMLNode *SearchXMLSiblings( CPLXMLNode *psRoot, const char *pszElement )
@@ -179,12 +179,12 @@ static GDALColorInterp BandInterp(int nbands, int band) {
 /************************************************************************/
 
 /*
- * \brief Utility function to find the position of the bbox parameter value 
+ * \brief Utility function to find the position of the bbox parameter value
  * within a request string.  The search for the bbox is case insensitive
  *
  * @param in, the string to search into
  *
- * @return The position from the begining of the string or -1 if not found
+ * @return The position from the beginning of the string or -1 if not found
  */
 
 static int FindBbox(CPLString in) {
@@ -229,7 +229,7 @@ static void FindChangePattern( char *cdata,char **substs, char **keys, CPLString
         ret=papszTokens[j];  // The target string
         bool matches=true;
 
-        for (int k=0;k<keycount;k++)
+        for (int k=0;k<keycount && keys != NULL;k++)
         {
             const char *key=keys[k];
             int sub_number=CSLPartialFindString(substs,key);
@@ -243,6 +243,7 @@ static void FindChangePattern( char *cdata,char **substs, char **keys, CPLString
                     if (std::string::npos==ret.find(key))
                     {
                         matches=false;
+                        CPLFree(found_key);
                         break;
                     }
                     // Execute the substitution on the "ret" string
@@ -269,9 +270,11 @@ static void FindChangePattern( char *cdata,char **substs, char **keys, CPLString
     CSLDestroy(papszTokens);
 }
 
-GDALWMSMiniDriver_TiledWMS::GDALWMSMiniDriver_TiledWMS() {
-    m_requests = NULL;
-}
+GDALWMSMiniDriver_TiledWMS::GDALWMSMiniDriver_TiledWMS() :
+    m_requests(NULL),
+    m_bsx(0),
+    m_bsy(0)
+{ }
 
 GDALWMSMiniDriver_TiledWMS::~GDALWMSMiniDriver_TiledWMS() {
     CSLDestroy(m_requests);
@@ -414,7 +417,7 @@ CPLErr GDALWMSMiniDriver_TiledWMS::Initialize(CPLXMLNode *config)
         }
 
        // Data values are attributes, they include NoData Min and Max
-       if (0!=CPLGetXMLNode(TG,"DataValues")) {
+       if (NULL!=CPLGetXMLNode(TG,"DataValues")) {
            const char *nodata=CPLGetXMLValue(TG,"DataValues.NoData",NULL);
            if (nodata!=NULL) m_parent_dataset->WMSSetNoDataValue(nodata);
            const char *min=CPLGetXMLValue(TG,"DataValues.min",NULL);
@@ -541,7 +544,7 @@ CPLErr GDALWMSMiniDriver_TiledWMS::Initialize(CPLXMLNode *config)
         m_bsx=m_bsy=-1;
         m_data_window.m_sx=m_data_window.m_sy=0;
 
-        for (int once=1;once;once--) { // Something to break out of
+        for (int once2=1;once2;once2--) { // Something to break out of
             while ((NULL!=Pattern)&&(NULL!=(Pattern=SearchXMLSiblings(Pattern,"=TilePattern")))) {
                 int mbsx,mbsy;
 
@@ -571,7 +574,7 @@ CPLErr GDALWMSMiniDriver_TiledWMS::Initialize(CPLXMLNode *config)
 
                 if (-1==m_bsx) m_bsx=mbsx;
                 if (-1==m_bsy) m_bsy=mbsy;
-                if ((m_bsy!=mbsy)||(m_bsy!=mbsy)) {
+                if ((m_bsx!=mbsx)||(m_bsy!=mbsy)) {
                     CPLError(ret=CE_Failure,CPLE_AppDefined,"%s%s",SIG,
                         "Tileset uses different block sizes.");
                     overview_count=0;
diff --git a/frmts/wms/minidriver_tiled_wms.h b/frmts/wms/minidriver_tiled_wms.h
index c63e1f7..78a5c90 100644
--- a/frmts/wms/minidriver_tiled_wms.h
+++ b/frmts/wms/minidriver_tiled_wms.h
@@ -49,6 +49,7 @@ protected:
     char **m_requests;
     CPLString m_base_url;
     CPLString m_end_url;
-    int m_bsx,m_bsy;
+    int m_bsx;
+    int m_bsy;
     CPLString m_projection_wkt;
 };
diff --git a/frmts/wms/minidriver_wms.cpp b/frmts/wms/minidriver_wms.cpp
index f9b3c97..656a21f 100644
--- a/frmts/wms/minidriver_wms.cpp
+++ b/frmts/wms/minidriver_wms.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: minidriver_wms.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: minidriver_wms.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -34,7 +34,7 @@
 
 CPP_GDALWMSMiniDriverFactory(WMS)
 
-GDALWMSMiniDriver_WMS::GDALWMSMiniDriver_WMS() {
+GDALWMSMiniDriver_WMS::GDALWMSMiniDriver_WMS() : m_iversion(0) {
 }
 
 GDALWMSMiniDriver_WMS::~GDALWMSMiniDriver_WMS() {
@@ -165,8 +165,8 @@ void GDALWMSMiniDriver_WMS::BuildURL(CPLString *url, const GDALWMSImageRequestIn
     URLAppendF(url, "&format=%s", m_image_format.c_str());
     URLAppendF(url, "&width=%d", iri.m_sx);
     URLAppendF(url, "&height=%d", iri.m_sy);
-    URLAppendF(url, "&bbox=%.8f,%.8f,%.8f,%.8f", 
-        GetBBoxCoord(iri, m_bbox_order[0]), GetBBoxCoord(iri, m_bbox_order[1]), 
+    URLAppendF(url, "&bbox=%.8f,%.8f,%.8f,%.8f",
+        GetBBoxCoord(iri, m_bbox_order[0]), GetBBoxCoord(iri, m_bbox_order[1]),
         GetBBoxCoord(iri, m_bbox_order[2]), GetBBoxCoord(iri, m_bbox_order[3]));
 }
 
diff --git a/frmts/wms/wmsdriver.cpp b/frmts/wms/wmsdriver.cpp
index cef3591..e5a67a9 100644
--- a/frmts/wms/wmsdriver.cpp
+++ b/frmts/wms/wmsdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: wmsdriver.cpp 31240 2015-10-29 03:32:45Z rouault $
+ * $Id: wmsdriver.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -29,6 +29,7 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "gdal_frmts.h"
 #include "wmsdriver.h"
 #include "wmsmetadataset.h"
 
@@ -39,6 +40,9 @@
 #include "minidriver_tiled_wms.h"
 #include "minidriver_virtualearth.h"
 #include "minidriver_arcgis_server.h"
+#include "minidriver_iip.h"
+
+#include <limits>
 
 /************************************************************************/
 /*              GDALWMSDatasetGetConfigFromURL()                        */
@@ -48,7 +52,7 @@ static
 CPLXMLNode * GDALWMSDatasetGetConfigFromURL(GDALOpenInfo *poOpenInfo)
 {
     const char* pszBaseURL = poOpenInfo->pszFilename;
-    if (EQUALN(pszBaseURL, "WMS:", 4))
+    if (STARTS_WITH_CI(pszBaseURL, "WMS:"))
         pszBaseURL += 4;
 
     CPLString osLayer = CPLURLGetValue(pszBaseURL, "LAYERS");
@@ -116,7 +120,7 @@ CPLXMLNode * GDALWMSDatasetGetConfigFromURL(GDALOpenInfo *poOpenInfo)
 
     if (osSRSValue.size() == 0)
         osSRSValue = "EPSG:4326";
-    
+
     if (osBBOX.size() == 0)
     {
         if (osBBOXOrder.compare("yxYX") == 0)
@@ -158,6 +162,7 @@ CPLXMLNode * GDALWMSDatasetGetConfigFromURL(GDALOpenInfo *poOpenInfo)
         nTileSize = 1024;
 
     int nXSize, nYSize;
+    double dXSize, dYSize;
 
     int nOverviewCount = (osOverviewCount.size()) ? atoi(osOverviewCount) : 20;
 
@@ -171,31 +176,52 @@ CPLXMLNode * GDALWMSDatasetGetConfigFromURL(GDALOpenInfo *poOpenInfo)
             dfMinResolution *= 2;
         }
 
-        nXSize = (int) ((dfMaxX - dfMinX) / dfMinResolution + 0.5);
-        nYSize = (int) ((dfMaxY - dfMinY) / dfMinResolution + 0.5);
+        // Determine a suitable size that doesn't overflow max int.
+        dXSize = ((dfMaxX - dfMinX) / dfMinResolution + 0.5);
+        dYSize = ((dfMaxY - dfMinY) / dfMinResolution + 0.5);
+
+        while (dXSize > (std::numeric_limits<int>::max)() ||
+               dYSize > (std::numeric_limits<int>::max)())
+        {
+            dfMinResolution *= 2;
+
+            dXSize = ((dfMaxX - dfMinX) / dfMinResolution + 0.5);
+            dYSize = ((dfMaxY - dfMinY) / dfMinResolution + 0.5);
+        }
     }
     else
     {
         double dfRatio = (dfMaxX - dfMinX) / (dfMaxY - dfMinY);
         if (dfRatio > 1)
         {
-            nXSize = nTileSize;
-            nYSize = (int) (nXSize / dfRatio);
+            dXSize = nTileSize;
+            dYSize = dXSize / dfRatio;
         }
         else
         {
-            nYSize = nTileSize;
-            nXSize = (int) (nYSize * dfRatio);
+            dYSize = nTileSize;
+            dXSize = dYSize * dfRatio;
         }
 
         if (nOverviewCount < 0 || nOverviewCount > 20)
             nOverviewCount = 20;
 
-        nXSize = nXSize * (1 << nOverviewCount);
-        nYSize = nYSize * (1 << nOverviewCount);
+        dXSize = dXSize * (1 << nOverviewCount);
+        dYSize = dYSize * (1 << nOverviewCount);
+
+        // Determine a suitable size that doesn't overflow max int.
+        while (dXSize > (std::numeric_limits<int>::max)() ||
+               dYSize > (std::numeric_limits<int>::max)())
+        {
+            dXSize /= 2;
+            dYSize /= 2;
+        }
     }
 
-    int bTransparent = osTransparent.size() ? CSLTestBoolean(osTransparent) : FALSE;
+    nXSize = (int) dXSize;
+    nYSize = (int) dYSize;
+
+    bool bTransparent = osTransparent.size() != 0 && CPLTestBool(osTransparent);
 
     if (osFormat.size() == 0)
     {
@@ -286,8 +312,7 @@ CPLXMLNode * GDALWMSDatasetGetConfigFromTileMap(CPLXMLNode* psXML)
         osURL = pszURL;
         /* Special hack for http://tilecache.osgeo.org/wms-c/Basic.py/1.0.0/basic/ */
         if (strlen(pszURL) > 10 &&
-            strncmp(pszURL, "http://tilecache.osgeo.org/wms-c/Basic.py/1.0.0/",
-                            strlen("http://tilecache.osgeo.org/wms-c/Basic.py/1.0.0/")) == 0 &&
+            STARTS_WITH(pszURL, "http://tilecache.osgeo.org/wms-c/Basic.py/1.0.0/") &&
             strcmp(pszURL + strlen(pszURL) - strlen("1.0.0/"), "1.0.0/") == 0)
         {
             osURL.resize(strlen(pszURL) - strlen("1.0.0/"));
@@ -398,7 +423,7 @@ CPLXMLNode * GDALWMSDatasetGetConfigFromTileMap(CPLXMLNode* psXML)
     }
 
     char* pszEscapedURL = CPLEscapeString(osURL.c_str(), -1, CPLES_XML);
-    
+
     CPLString osXML = CPLSPrintf(
             "<GDAL_WMS>\n"
             "  <Service name=\"TMS\">\n"
@@ -565,7 +590,7 @@ static CPLXMLNode* GDALWMSDatasetGetConfigFromArcGISJSON(const char* pszURL,
         CPLDebug("WMS", "Did not get max y");
         return NULL;
     }
-    
+
     if (nWKID == 102100)
         nWKID = 3857;
 
@@ -633,17 +658,17 @@ int GDALWMSDataset::Identify(GDALOpenInfo *poOpenInfo)
     const char* pszFilename = poOpenInfo->pszFilename;
     const char* pabyHeader = (const char *) poOpenInfo->pabyHeader;
     if (poOpenInfo->nHeaderBytes == 0 &&
-         EQUALN(pszFilename, "<GDAL_WMS>", 10))
+         STARTS_WITH_CI(pszFilename, "<GDAL_WMS>"))
     {
         return TRUE;
     }
     else if (poOpenInfo->nHeaderBytes >= 10 &&
-             EQUALN(pabyHeader, "<GDAL_WMS>", 10))
+             STARTS_WITH_CI(pabyHeader, "<GDAL_WMS>"))
     {
         return TRUE;
     }
     else if (poOpenInfo->nHeaderBytes == 0 &&
-             (EQUALN(pszFilename, "WMS:", 4) ||
+             (STARTS_WITH_CI(pszFilename, "WMS:") ||
              CPLString(pszFilename).ifind("SERVICE=WMS") != std::string::npos) )
     {
         return TRUE;
@@ -677,13 +702,18 @@ int GDALWMSDataset::Identify(GDALOpenInfo *poOpenInfo)
         return TRUE;
     }
     else if (poOpenInfo->nHeaderBytes == 0 &&
-             EQUALN(pszFilename, "http", 4) &&
+             STARTS_WITH_CI(pszFilename, "http") &&
              strstr(pszFilename, "/MapServer?f=json") != NULL)
     {
         return TRUE;
     }
     else if (poOpenInfo->nHeaderBytes == 0 &&
-              EQUALN(pszFilename, "AGS:", 4))
+              STARTS_WITH_CI(pszFilename, "AGS:"))
+    {
+        return TRUE;
+    }
+    else if (poOpenInfo->nHeaderBytes == 0 &&
+              STARTS_WITH_CI(pszFilename, "IIP:"))
     {
         return TRUE;
     }
@@ -704,21 +734,21 @@ GDALDataset *GDALWMSDataset::Open(GDALOpenInfo *poOpenInfo)
     const char* pabyHeader = (const char *) poOpenInfo->pabyHeader;
 
     if (poOpenInfo->nHeaderBytes == 0 &&
-        EQUALN(pszFilename, "<GDAL_WMS>", 10))
+        STARTS_WITH_CI(pszFilename, "<GDAL_WMS>"))
     {
         config = CPLParseXMLString(pszFilename);
     }
     else if (poOpenInfo->nHeaderBytes >= 10 &&
-             EQUALN(pabyHeader, "<GDAL_WMS>", 10))
+             STARTS_WITH_CI(pabyHeader, "<GDAL_WMS>"))
     {
         config = CPLParseXMLFile(pszFilename);
     }
     else if (poOpenInfo->nHeaderBytes == 0 &&
-             (EQUALN(pszFilename, "WMS:http", 8) ||
-              EQUALN(pszFilename, "http", 4)) &&
+             (STARTS_WITH_CI(pszFilename, "WMS:http") ||
+              STARTS_WITH_CI(pszFilename, "http")) &&
              strstr(pszFilename, "/MapServer?f=json") != NULL)
     {
-        if (EQUALN(pszFilename, "WMS:http", 8))
+        if (STARTS_WITH_CI(pszFilename, "WMS:http"))
             pszFilename += 4;
         CPLString osURL(pszFilename);
         if (strstr(pszFilename, "&pretty=true") == NULL)
@@ -737,7 +767,7 @@ GDALDataset *GDALWMSDataset::Open(GDALOpenInfo *poOpenInfo)
     }
 
     else if (poOpenInfo->nHeaderBytes == 0 &&
-             (EQUALN(pszFilename, "WMS:", 4) ||
+             (STARTS_WITH_CI(pszFilename, "WMS:") ||
               CPLString(pszFilename).ifind("SERVICE=WMS") != std::string::npos))
     {
         CPLString osLayers = CPLURLGetValue(pszFilename, "LAYERS");
@@ -815,10 +845,54 @@ GDALDataset *GDALWMSDataset::Open(GDALOpenInfo *poOpenInfo)
         return poRet;
     }
     else if (poOpenInfo->nHeaderBytes == 0 &&
-              EQUALN(pszFilename, "AGS:", 4))
+              STARTS_WITH_CI(pszFilename, "AGS:"))
     {
 		return NULL;
     }
+    else if (poOpenInfo->nHeaderBytes == 0 &&
+              STARTS_WITH_CI(pszFilename, "IIP:"))
+    {
+        CPLString osURL(pszFilename + 4);
+        osURL += "&obj=Basic-Info";
+        CPLHTTPResult *psResult = CPLHTTPFetch(osURL.c_str(), NULL);
+        if (psResult == NULL)
+            return NULL;
+        if (psResult->pabyData == NULL)
+        {
+            CPLHTTPDestroyResult(psResult);
+            return NULL;
+        }
+        int nXSize, nYSize;
+        const char* pszMaxSize = strstr((const char*)psResult->pabyData, "Max-size:");
+        const char* pszResolutionNumber = strstr((const char*)psResult->pabyData, "Resolution-number:");
+        if( pszMaxSize &&
+            sscanf(pszMaxSize + strlen("Max-size:"), "%d %d", &nXSize, &nYSize) == 2 &&
+            pszResolutionNumber )
+        {
+            int nResolutions = atoi(pszResolutionNumber + strlen("Resolution-number:"));
+            char* pszEscapedURL = CPLEscapeString(pszFilename + 4, -1, CPLES_XML);
+            CPLString osXML = CPLSPrintf(
+            "<GDAL_WMS>"
+            "    <Service name=\"IIP\">"
+            "        <ServerUrl>%s</ServerUrl>"
+            "    </Service>"
+            "    <DataWindow>"
+            "        <SizeX>%d</SizeX>"
+            "        <SizeY>%d</SizeY>"
+            "        <TileLevel>%d</TileLevel>"
+            "    </DataWindow>"
+            "    <BlockSizeX>256</BlockSizeX>"
+            "    <BlockSizeY>256</BlockSizeY>"
+            "    <BandsCount>3</BandsCount>"
+            "    <Cache />"
+            "</GDAL_WMS>",
+                pszEscapedURL,
+                nXSize, nYSize, nResolutions - 1);
+            config = CPLParseXMLString(osXML);
+            CPLFree(pszEscapedURL);
+        }
+        CPLHTTPDestroyResult(psResult);
+    }
     else
         return NULL;
     if (config == NULL) return NULL;
@@ -829,7 +903,7 @@ GDALDataset *GDALWMSDataset::Open(GDALOpenInfo *poOpenInfo)
     if( poOpenInfo->eAccess == GA_Update )
     {
         CPLDestroyXMLNode(config);
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The WMS poDriver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
@@ -907,32 +981,35 @@ static void GDALDeregister_WMS( GDALDriver * )
 /*                          GDALRegister_WMS()                          */
 /************************************************************************/
 
-void GDALRegister_WMS() {
-    GDALDriver *poDriver;
-    if (GDALGetDriverByName("WMS") == NULL) {
-        poDriver = new GDALDriver();
-
-        poDriver->SetDescription("WMS");
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "OGC Web Map Service");
-        poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "frmt_wms.html");
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
-
-        poDriver->pfnOpen = GDALWMSDataset::Open;
-        poDriver->pfnIdentify = GDALWMSDataset::Identify;
-        poDriver->pfnUnloadDriver = GDALDeregister_WMS;
-        poDriver->pfnCreateCopy = GDALWMSDataset::CreateCopy;
-
-        GetGDALDriverManager()->RegisterDriver(poDriver);
-
-        GDALWMSMiniDriverManager *const mdm = GetGDALWMSMiniDriverManager();
-        mdm->Register(new GDALWMSMiniDriverFactory_WMS());
-        mdm->Register(new GDALWMSMiniDriverFactory_TileService());
-        mdm->Register(new GDALWMSMiniDriverFactory_WorldWind());
-        mdm->Register(new GDALWMSMiniDriverFactory_TMS());
-        mdm->Register(new GDALWMSMiniDriverFactory_TiledWMS());
-        mdm->Register(new GDALWMSMiniDriverFactory_VirtualEarth());
-        mdm->Register(new GDALWMSMiniDriverFactory_AGS());
-    }
+void GDALRegister_WMS()
+
+{
+    if( GDALGetDriverByName( "WMS" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription("WMS");
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "OGC Web Map Service" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_wms.html" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
+
+    poDriver->pfnOpen = GDALWMSDataset::Open;
+    poDriver->pfnIdentify = GDALWMSDataset::Identify;
+    poDriver->pfnUnloadDriver = GDALDeregister_WMS;
+    poDriver->pfnCreateCopy = GDALWMSDataset::CreateCopy;
+
+    GetGDALDriverManager()->RegisterDriver(poDriver);
+
+    GDALWMSMiniDriverManager *const mdm = GetGDALWMSMiniDriverManager();
+    mdm->Register(new GDALWMSMiniDriverFactory_WMS());
+    mdm->Register(new GDALWMSMiniDriverFactory_TileService());
+    mdm->Register(new GDALWMSMiniDriverFactory_WorldWind());
+    mdm->Register(new GDALWMSMiniDriverFactory_TMS());
+    mdm->Register(new GDALWMSMiniDriverFactory_TiledWMS());
+    mdm->Register(new GDALWMSMiniDriverFactory_VirtualEarth());
+    mdm->Register(new GDALWMSMiniDriverFactory_AGS());
+    mdm->Register(new GDALWMSMiniDriverFactory_IIP());
 }
diff --git a/frmts/wms/wmsdriver.h b/frmts/wms/wmsdriver.h
index 7ce6a4a..e4e2cdc 100644
--- a/frmts/wms/wmsdriver.h
+++ b/frmts/wms/wmsdriver.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: wmsdriver.h 28432 2015-02-06 21:15:27Z rouault $
+ * $Id: wmsdriver.h 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -102,14 +102,40 @@ public:
 
 class GDALWMSRasterIOHint {
 public:
-    int m_x0, m_y0;
-    int m_sx, m_sy;
+  GDALWMSRasterIOHint() :
+      m_x0(0),
+      m_y0(0),
+      m_sx(0),
+      m_sy(0),
+      m_overview(0),
+      m_valid(false)
+  {}
+    int m_x0;
+    int m_y0;
+    int m_sx;
+    int m_sy;
     int m_overview;
     bool m_valid;
 };
 
+typedef enum
+{
+    OVERVIEW_ROUNDED,
+    OVERVIEW_FLOOR
+} GDALWMSOverviewDimComputationMethod;
+
 class GDALWMSMiniDriverCapabilities {
 public:
+  GDALWMSMiniDriverCapabilities() :
+      m_capabilities_version(0),
+      m_has_image_request(0),
+      m_has_tiled_image_requeset(0),
+      m_has_arb_overviews(0),
+      m_max_overview_count(-1),
+      m_overview_dim_computation_method(OVERVIEW_ROUNDED),
+      m_has_geotransform(true)
+  {}
+
 /* Version N capabilities require all version N and earlier variables to be set to correct values */
     int m_capabilities_version;
 
@@ -118,6 +144,8 @@ public:
     int m_has_tiled_image_requeset;     // 1 if TiledImageRequest method is implemented
     int m_has_arb_overviews;            // 1 if ImageRequest method supports arbitrary overviews / resolutions
     int m_max_overview_count;               // Maximum number of overviews supported if known, -1 otherwise
+    GDALWMSOverviewDimComputationMethod m_overview_dim_computation_method;
+    bool m_has_geotransform;
 };
 
 /* All data returned by mini-driver as pointer should remain valid for mini-driver lifetime
@@ -246,7 +274,7 @@ public:
     virtual CPLErr GetGeoTransform(double *gt);
     virtual CPLErr SetGeoTransform(double *gt);
     virtual CPLErr AdviseRead(int x0, int y0, int sx, int sy, int bsx, int bsy, GDALDataType bdt, int band_count, int *band_map, char **options);
-    
+
     virtual char      **GetMetadataDomainList();
     virtual const char *GetMetadataItem( const char * pszName,
                                          const char * pszDomain = "" );
@@ -314,7 +342,7 @@ public:
     void WMSSetNeedsDataWindow(int flag) {
         m_bNeedsDataWindow = flag;
     }
-    
+
     static void list2vec(std::vector<double> &v,const char *pszList) {
         if ((pszList==NULL)||(pszList[0]==0)) return;
         char **papszTokens=CSLTokenizeString2(pszList," \t\n\r",
@@ -362,7 +390,8 @@ protected:
     GDALColorTable *m_poColorTable;
     std::vector<double> vNoData, vMin, vMax;
     GDALDataType m_data_type;
-    int m_block_size_x, m_block_size_y;
+    int m_block_size_x;
+    int m_block_size_y;
     GDALWMSRasterIOHint m_hint;
     int m_use_advise_read;
     int m_verify_advise_read;
diff --git a/frmts/wms/wmsmetadataset.cpp b/frmts/wms/wmsmetadataset.cpp
index 777e8e9..1ed7879 100644
--- a/frmts/wms/wmsmetadataset.cpp
+++ b/frmts/wms/wmsmetadataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: wmsmetadataset.cpp 27892 2014-10-20 22:02:57Z rouault $
+ * $Id: wmsmetadataset.cpp 32078 2015-12-08 09:09:45Z rouault $
  *
  * Project:  WMS Client Driver
  * Purpose:  Definition of GDALWMSMetaDataset class
@@ -58,11 +58,11 @@ void GDALWMSMetaDataset::AddSubDataset(const char* pszName,
     char    szName[80];
     int     nCount = CSLCount(papszSubDatasets ) / 2;
 
-    sprintf( szName, "SUBDATASET_%d_NAME", nCount+1 );
+    snprintf( szName, sizeof(szName), "SUBDATASET_%d_NAME", nCount+1 );
     papszSubDatasets =
         CSLSetNameValue( papszSubDatasets, szName, pszName );
 
-    sprintf( szName, "SUBDATASET_%d_DESC", nCount+1 );
+    snprintf( szName, sizeof(szName), "SUBDATASET_%d_DESC", nCount+1 );
     papszSubDatasets =
         CSLSetNameValue( papszSubDatasets, szName, pszDesc);
 }
@@ -74,7 +74,7 @@ void GDALWMSMetaDataset::AddSubDataset(const char* pszName,
 GDALDataset *GDALWMSMetaDataset::DownloadGetCapabilities(GDALOpenInfo *poOpenInfo)
 {
     const char* pszURL = poOpenInfo->pszFilename;
-    if (EQUALN(pszURL, "WMS:", 4))
+    if (STARTS_WITH_CI(pszURL, "WMS:"))
         pszURL += 4;
 
     CPLString osFormat = CPLURLGetValue(pszURL, "FORMAT");
@@ -149,7 +149,7 @@ GDALDataset *GDALWMSMetaDataset::DownloadGetCapabilities(GDALOpenInfo *poOpenInf
 GDALDataset *GDALWMSMetaDataset::DownloadGetTileService(GDALOpenInfo *poOpenInfo)
 {
     const char* pszURL = poOpenInfo->pszFilename;
-    if (EQUALN(pszURL, "WMS:", 4))
+    if (STARTS_WITH_CI(pszURL, "WMS:"))
         pszURL += 4;
 
     CPLString osURL(pszURL);
diff --git a/frmts/wms/wmsmetadataset.h b/frmts/wms/wmsmetadataset.h
index 24f2634..9d06775 100644
--- a/frmts/wms/wmsmetadataset.h
+++ b/frmts/wms/wmsmetadataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: wmsmetadataset.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: wmsmetadataset.h 31777 2015-11-26 14:14:41Z rouault $
  *
  * Project:  WMS Client Driver
  * Purpose:  Declaration of GDALWMSMetaDataset class
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _WMS_METADATASET_H_INCLUDED
-#define _WMS_METADATASET_H_INCLUDED
+#ifndef WMS_METADATASET_H_INCLUDED
+#define WMS_METADATASET_H_INCLUDED
 
 #include "gdal_pam.h"
 #include "cpl_string.h"
@@ -119,4 +119,4 @@ class GDALWMSMetaDataset : public GDALPamDataset
     static GDALDataset* DownloadGetTileService(GDALOpenInfo *poOpenInfo);
 };
 
-#endif // _WMS_METADATASET_H_INCLUDED
+#endif // WMS_METADATASET_H_INCLUDED
diff --git a/frmts/wms/wmsutils.cpp b/frmts/wms/wmsutils.cpp
index 73d901a..4ac9fcd 100644
--- a/frmts/wms/wmsutils.cpp
+++ b/frmts/wms/wmsutils.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: wmsutils.cpp 26079 2013-06-13 01:31:48Z warmerdam $
+ * $Id: wmsutils.cpp 31640 2015-11-18 23:17:59Z rouault $
  *
  * Project:  WMS Client Driver
  * Purpose:  Supporting utility functions for GDAL WMS driver.
@@ -35,7 +35,7 @@ CPLString MD5String(const char *s) {
     const char *tohex = "0123456789abcdef";
     struct cvs_MD5Context context;
     cvs_MD5Init(&context);
-    cvs_MD5Update(&context, reinterpret_cast<unsigned char const *>(s), strlen(s));
+    cvs_MD5Update(&context, reinterpret_cast<unsigned char const *>(s), static_cast<int>(strlen(s)));
     cvs_MD5Final(hash, &context);
     for (int i = 0; i < 16; ++i) {
         hhash[i * 2] = tohex[(hash[i] >> 4) & 0xf];
@@ -147,5 +147,5 @@ int URLSearchAndReplace (CPLString *base, const char *search, const char *fmt, .
     va_end(args);
 
     base->replace(start, strlen(search), tmp);
-    return start;
+    return static_cast<int>(start);
 }
diff --git a/frmts/wmts/GNUmakefile b/frmts/wmts/GNUmakefile
new file mode 100644
index 0000000..5230b31
--- /dev/null
+++ b/frmts/wmts/GNUmakefile
@@ -0,0 +1,11 @@
+
+include ../../GDALmake.opt
+
+OBJ =	wmtsdataset.o
+
+default:	$(OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(OBJ) $(O_OBJ)
+
+install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
diff --git a/frmts/wmts/frmt_wmts.html b/frmts/wmts/frmt_wmts.html
new file mode 100644
index 0000000..fc70c3a
--- /dev/null
+++ b/frmts/wmts/frmt_wmts.html
@@ -0,0 +1,284 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>WMTS -- OGC Web Map Tile Service</title>
+        <STYLE type="text/css">
+                td.xml { font-family: monospace; white-space: pre; padding-right: 20px; }
+                td.desc { }
+                span.value { color: #00B000; }
+                body { background-color: #ffffff; }
+        </STYLE>
+</head>
+
+<body>
+
+<h1>WMTS -- OGC Web Map Tile Service</h1>
+
+<p>
+  Since GDAL 2.1, access to WMTS layers is possible with the GDAL WMTS client driver (needs Curl support).
+  It support both RESTful and KVP protocols.
+</p>
+
+<h2>Open syntax</h2>
+
+The WMTS driver can open :
+<ul>
+<li><p>
+a local service description XML file, whose syntax is described in the below section : <pre>gdalinfo gdal_wmts.xml</pre>
+</p></li>
+
+<li><p>
+the content of a description XML file provided as filename :
+<pre>gdalinfo "<GDAL_WMTS><GetCapabilitiesUrl>http://maps.wien.gv.at/wmts/1.0.0/WMTSCapabilities.xml</GetCapabilitiesUrl><Layer>lb</Layer></GDAL_WMTS>"</pre>
+</p></li>
+
+<li><p>
+a local GetCapabilities response of a WTMS service : <pre>gdalinfo WMTSCapabilities.xml</pre>
+</p></li>
+
+<li><p>
+the URL to the GetCapabilities response of a WTMS service:
+<pre>gdalinfo "http://maps.wien.gv.at/wmts/1.0.0/WMTSCapabilities.xml"</pre>
+<p></li>
+
+<li><p>
+the URL to the GetCapabilities response of a WTMS service, prefixed with <i>WMTS:</i>,
+and possibly with optional layer, tilematrixset, style and extendbeyonddateline parameters,
+with the following syntax
+<i>WMTS:url[,layer=layer_id][,tilematrixset=tms_id][,style=style_id][,extendbeyonddateline=yes/no]</i>.
+
+<pre>gdalinfo "WMTS:http://maps.wien.gv.at/wmts/1.0.0/WMTSCapabilities.xml"</pre>
+<pre>gdalinfo "WMTS:http://maps.wien.gv.at/wmts/1.0.0/WMTSCapabilities.xml,layer=lb"</pre>
+<p>
+
+
+<li><p>
+the <i>WMTS:</i> prefix with open options URL (required), LAYER, TILEMATRIXSET,
+STYLE, EXTENDBEYONDDATELINE.
+<pre>gdalinfo WMTS: -oo URL=http://maps.wien.gv.at/wmts/1.0.0/WMTSCapabilities.xml -oo LAYER=lb</pre>
+</p></li>
+
+</ul>
+
+In any of the above syntaxes, if several layers are present and no layer disambiguation
+was done with the layer parameter/open option, or if a layer
+has more than one style or a tile matrix set, a list of subdatasets will be returned.
+If there is only one layer, it will be opened on the default style and the
+first tile matrix set listed.
+
+<h2>Local service description XML file</h2>
+
+<p>
+It is important that there be no spaces or other content before the <tt><GDAL_WMTS></tt> element.
+</p>
+
+        <table>
+                <tr>
+                        <td class="xml"><GDAL_WMTS></td>
+                        <td class="desc"> </td>
+                </tr>
+                <tr>
+                        <td class="xml">  <GetCapabilitiesUrl><span class="value">http://foo/WMTSCapabilities.xml</span></GetCapabilitiesUrl></td>
+                        <td class="desc">URL (or filename for local files) to GetCapabilities response document (required).
+                                         For a KVP only server, will be like http://end_point?SERVICE=WMTS&amp;REQUEST=GetCapabilities .
+                         </td>
+                </tr>
+                <tr>
+                        <td class="xml">  <Layer><span class="value">layer_id</span></Layer></td>
+                        <td class="desc">Layer identifier (optional, but may be needed to disambiguate between several layers)</td>
+                </tr>
+                <tr>
+                        <td class="xml">  <Style><span class="value">style_id</span></Style></td>
+                        <td class="desc">Style identifier. Must be one of the listed styles for the layer. (optional, but may be needed to disambiguate between several styles)</td>
+                </tr>
+                <tr>
+                        <td class="xml">  <TileMatrixSet><span class="value">tile_matrix_set_id</span></TileMatrixSet></td>
+                        <td class="desc">Tile Matrix Set identifier. Must be one of the listed tile matrix set for the layer. (optional, but may be needed to disambiguate between several tile matrix sets)</td>
+                </tr>
+                <tr>
+                        <td class="xml">  <Format><span class="value">image/png</span></Format></td>
+                        <td class="desc">Tile format, used by GetTile requests. Must be one of the listed Format for the layer. (optional, but may be needed to disambiguate between several Format)</td>
+                </tr>
+                <tr>
+                        <td class="xml">  <InfoFormat><span class="value">application/xml</span></InfoFormat></td>
+                        <td class="desc">Info format, used by GetFeatureInfo requests. Must be one of the listed InfoFormat for the layer. (optional, but may be needed to disambiguate between several InfoFormat)</td>
+                </tr>
+                <tr>
+                        <td class="xml">  <DataWindow></td>
+                        <td class="desc">Define extents of the data. (optional, when not specified the driver will query the
+                                         declared extent of the layer, and if not present fallback to the extent of the select tile matrix set,
+                                         taking into account potential tile matrix set limits)</td>
+                </tr>
+                <tr>
+                        <td class="xml">    <UpperLeftX><span class="value">-180.0</span></UpperLeftX></td>
+                        <td class="desc">X (longitude/easting) coordinate of upper-left corner, in the SRS of the tile matrix set. (required if DataWindow is present)</td>
+                </tr>
+                <tr>
+                        <td class="xml">    <UpperLeftY><span class="value">90.0</span></UpperLeftY></td>
+                        <td class="desc">Y (latitude/northing) coordinate of upper-left corner, in the SRS of the tile matrix set. (required if DataWindow is present)</td>
+                </tr>
+                <tr>
+                        <td class="xml">    <LowerRightX><span class="value">180.0</span></LowerRightX></td>
+                        <td class="desc">X (longitude/easting) coordinate of lower-right corner, in the SRS of the tile matrix set. (required if DataWindow is present)</td>
+                </tr>
+                <tr>
+                        <td class="xml">    <LowerRightY><span class="value">-90.0</span></LowerRightY></td>
+                        <td class="desc">Y (latitude/northing) coordinate of lower-right corner, in the SRS of the tile matrix set. (required if DataWindow is present)</td>
+                </tr>
+                <tr>
+                        <td class="xml">  </DataWindow></td>
+                        <td class="desc"></td>
+                </tr>
+                <tr>
+                        <td class="xml">  <Projection><span class="value">EPSG:4326</span></Projection></td>
+                        <td class="desc">Declared projection, in case the one of the TileMatrixSet is not desirable (optional, defaults to value of the TileMatrixSet)</td>
+                </tr>
+                <tr>
+                        <td class="xml">  <BandsCount><span class="value">4</span></BandsCount></td>
+                        <td class="desc">Number of bands/channels, 1 for grayscale data, 3 for RGB, 4 for RGBA. (optional, defaults to 4)</td>
+                </tr>
+                <tr>
+                        <td class="xml">  <ExtendBeyondDateLine><span class="value">false</span></ExtendBeyondDateLine></td>
+                        <td class="desc">Whether to make the extent go over dateline and warp tile requests.
+                                         Only appropriate when the 2 following conditions are met (optional, defaults to false):
+                                         <ul>
+                                         <li>for a geodetic SRS or EPSG:3857, with tile matrix sets such as
+                                         the whole [-180,180] range of longitude is entirely covered by an integral number of tiles
+                                         (e.g. GoogleMapsCompatible).</li>
+                                         <li>AND
+                                         <ul>
+                                         <li>when the layer BoundingBox in the SRS of the tile matrix set covers the whole [-180,180] range
+                                         of longitude, and that there is another BoundingBox in another SRS that is centered around longitude 180.
+                                         If such alternate BoundingBox is not present in the GetCapabilities document, DataWindow must be explicitly specified</li>
+                                         <li>OR when the layer BoundingBox in the SRS of the tile matrix set extends beyond the dateline.</li>
+                                         </ul>
+                                         </li></ul></td>
+                </tr>
+                <tr>
+                        <td class="xml">  <Cache></td>
+                        <td class="desc">Enable local disk cache. Allows for offline operation.
+                                         (optional, absent by default, but enabled in autogenerated XML)</td>
+                </tr>
+                <tr>
+                        <td class="xml">    <Path><span class="value">./gdalwmscache</span></Path></td>
+                        <td class="desc">Location where to store cache files. It is safe to use same cache path for different data sources. (optional, defaults to ./gdalwmscache if GDAL_DEFAULT_WMS_CACHE_PATH configuration option is not specified)</td>
+                </tr>
+                <tr>
+                        <td class="xml">    <Depth><span class="value">2</span></Depth></td>
+                        <td class="desc">Number of directory layers. 2 will result in files being written as cache_path/A/B/ABCDEF... (optional, defaults to 2)</td>
+                </tr>
+                <tr>
+                        <td class="xml">    <Extension><span class="value">.jpg</span></Extension></td>
+                        <td class="desc">Append to cache files. (optional, defaults to none)</td>
+                </tr>
+                <tr>
+                        <td class="xml">  </Cache></td>
+                        <td class="desc"></td>
+                </tr>
+                <tr>
+                        <td class="xml">  <MaxConnections><span class="value">2</span></MaxConnections></td>
+                        <td class="desc">Maximum number of simultaneous connections. (optional, defaults to 2)</td>
+                </tr>
+                <tr>
+                        <td class="xml">  <Timeout><span class="value">300</span></Timeout></td>
+                        <td class="desc">Connection timeout in seconds. (optional, defaults to 300)</td>
+                </tr>
+                <tr>
+                        <td class="xml">  <OfflineMode><span class="value">true</span></OfflineMode></td>
+                        <td class="desc">Do not download any new images, use only what is in cache. Useful only with cache enabled. (optional, defaults to false)</td>
+                </tr>
+                <tr>
+                        <td class="xml">  <UserAgent><span class="value">GDAL WMS driver (http://www.gdal.org/frmt_wms.html)</span></UserAgent></td>
+                        <td class="desc">HTTP User-agent string. Some servers might require a well-known user-agent such as "Mozilla/5.0" (optional, defaults to "GDAL WMS driver (http://www.gdal.org/frmt_wms.html)").</td>
+                </tr>
+                <tr>
+                        <td class="xml">  <UserPwd><span class="value">user:password</span></UserPwd></td>
+                        <td class="desc">User and Password for HTTP authentication (optional).</td>
+                </tr>
+                <tr>
+                        <td class="xml">  <UnsafeSSL><span class="value">true</span></UnsafeSSL></td>
+                        <td class="desc">Skip SSL certificate verification. May be needed if server
+                                         is using a self signed certificate
+                                         (optional, defaults to false, but set to true in autogenerated XML).</td>
+                </tr>
+                <tr>
+                        <td class="xml">  <Referer><span class="value">http://example.foo/</span></Referer></td>
+                        <td class="desc">HTTP Referer string. Some servers might require it (optional).</td>
+                </tr>
+                <tr>
+                        <td class="xml">  <ZeroBlockHttpCodes><span class="value">204,404</span></ZeroBlockHttpCodes></td>
+                        <td class="desc">Comma separated list of HTTP response codes that will be
+                                          interpreted as a 0 filled image (i.e. black for 3 bands, and transparent
+                                          for 4 bands) instead of aborting the request.
+                                          (optional, defaults to non set, but set to 204,404 in autogenerated XML)</td>
+                </tr>
+                <tr>
+                        <td class="xml">  <ZeroBlockOnServerException><span class="value">true</span></ZeroBlockOnServerException></td>
+                        <td class="desc">Whether to treat a Service Exception returned by the server as a
+                                         0 filled image instead of aborting the request.
+                                         (optional, defaults to false, but set to true in autogenerated XML)</td>
+                </tr>
+                <tr>
+                        <td class="xml"></GDAL_WMTS></td>
+                        <td class="desc"></td>
+                </tr>
+                <tr>
+                        <td class="xml"></td>
+                        <td class="desc"></td>
+                </tr>
+        </table>
+
+<h2>GetFeatureInfo request</h2>
+
+<p>
+     WMTS layers can be queried (through a GetFeatureInfo request) with the gdallocationinfo utility, or
+     with a GetMetadataItem("Pixel_iCol_iLine", "LocationInfo") call on a band object.<p>
+     <pre>gdallocationinfo my_wmts.xml -geoloc -11547071.455 5528616 -xml -b 1</pre>
+</p>
+
+<h2>Generation of WMTS service description XML file</h2>
+
+The WMTS service description XML file can be generated manually, or created
+as the output of the CreateCopy() operation of the WMTS driver, only if the source
+dataset is itself a WMTS dataset. Said otherwise, you can use gdal_translate
+with as source dataset any of the above syntax mentioned in "Open syntax" and
+as output an XML file.
+
+For example:
+<pre>
+gdal_translate "WMTS:http://maps.wien.gv.at/wmts/1.0.0/WMTSCapabilities.xml,layer=lb" wmts.xml -of WMTS
+</pre>
+
+generates the following file:
+<pre>
+<GDAL_WMTS>
+  <GetCapabilitiesUrl>http://maps.wien.gv.at/wmts/1.0.0/WMTSCapabilities.xml</GetCapabilitiesUrl>
+  <Layer>lb</Layer>
+  <Style>farbe</Style>
+  <TileMatrixSet>google3857</TileMatrixSet>
+  <DataWindow>
+    <UpperLeftX>1800035.8827671</UpperLeftX>
+    <UpperLeftY>6161931.622311067</UpperLeftY>
+    <LowerRightX>1845677.148953537</LowerRightX>
+    <LowerRightY>6123507.385072636</LowerRightY>
+  </DataWindow>
+  <BandsCount>4</BandsCount>
+  <Cache />
+  <UnsafeSSL>true</UnsafeSSL>
+  <ZeroBlockHttpCodes>404</ZeroBlockHttpCodes>
+  <ZeroBlockOnServerException>true</ZeroBlockOnServerException>
+</GDAL_WMTS>
+</pre>
+
+The generated file will come with default values that you may need to edit.
+
+<h2>See Also:</h2>
+
+<ul>
+<li><a href="http://www.opengeospatial.org/standards/wmts">OGC WMTS Standard</a></li>
+<li><a href="frmt_wms.html">GDAL WMS driver documentation page</a></li>
+</ul>
+
+</body>
+</html>
diff --git a/frmts/wmts/makefile.vc b/frmts/wmts/makefile.vc
new file mode 100644
index 0000000..7f74718
--- /dev/null
+++ b/frmts/wmts/makefile.vc
@@ -0,0 +1,14 @@
+
+OBJ	= wmtsdataset.obj
+
+GDAL_ROOT	=	..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+
+default:	$(OBJ)
+	xcopy /D  /Y *.obj ..\o
+
+clean:
+	-del *.obj
+	-del *.dll
diff --git a/frmts/wmts/wmtsdataset.cpp b/frmts/wmts/wmtsdataset.cpp
new file mode 100644
index 0000000..c6dfbbf
--- /dev/null
+++ b/frmts/wmts/wmtsdataset.cpp
@@ -0,0 +1,2017 @@
+/******************************************************************************
+ * $Id: wmtsdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
+ *
+ * Project:  GDAL WMTS driver
+ * Purpose:  Implement GDAL WMTS support
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ * Funded by Land Information New Zealand (LINZ)
+ *
+ **********************************************************************
+ * Copyright (c) 2015, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_http.h"
+#include "cpl_minixml.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
+#include "ogr_spatialref.h"
+#include "../vrt/gdal_vrt.h"
+#include <vector>
+#include <set>
+#include <map>
+
+extern "C" void GDALRegister_WMTS();
+
+// g++ -g -Wall -fPIC frmts/wmts/wmtsdataset.cpp -shared -o gdal_WMTS.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -L. -lgdal
+
+/* Set in stone by WMTS spec. In pixel/meter */
+#define WMTS_PITCH                      0.00028
+
+#define WMTS_METERS_FOR_ONE_DEG         (6378137 * 2 * M_PI / 360)
+
+CPL_CVSID("$Id: wmtsdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+
+/************************************************************************/
+/* ==================================================================== */
+/*                            WMTSTileMatrix                            */
+/* ==================================================================== */
+/************************************************************************/
+
+class WMTSTileMatrix
+{
+    public:
+        CPLString osIdentifier;
+        double    dfScaleDenominator;
+        double    dfPixelSize;
+        double    dfTLX;
+        double    dfTLY;
+        int       nTileWidth;
+        int       nTileHeight;
+        int       nMatrixWidth;
+        int       nMatrixHeight;
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                          WMTSTileMatrixLimits                        */
+/* ==================================================================== */
+/************************************************************************/
+
+class WMTSTileMatrixLimits
+{
+    public:
+        CPLString osIdentifier;
+        int nMinTileRow;
+        int nMaxTileRow;
+        int nMinTileCol;
+        int nMaxTileCol;
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                          WMTSTileMatrixSet                           */
+/* ==================================================================== */
+/************************************************************************/
+
+class WMTSTileMatrixSet
+{
+    public:
+        OGRSpatialReference         oSRS;
+        CPLString                   osSRS;
+        int                         bBoundingBoxValid;
+        OGREnvelope                 sBoundingBox; /* expressed in TMS SRS */
+        std::vector<WMTSTileMatrix> aoTM;
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                              WMTSDataset                             */
+/* ==================================================================== */
+/************************************************************************/
+
+class WMTSDataset : public GDALPamDataset
+{
+  friend class WMTSBand;
+
+    CPLString                 osLayer;
+    CPLString                 osTMS;
+    CPLString                 osXML;
+    CPLString                 osURLFeatureInfoTemplate;
+    WMTSTileMatrixSet         oTMS;
+
+    char                    **papszHTTPOptions;
+
+    std::vector<GDALDataset*> apoDatasets;
+    CPLString                 osProjection;
+    double                    adfGT[6];
+
+    CPLString                 osLastGetFeatureInfoURL;
+    CPLString                 osMetadataItemGetFeatureInfo;
+
+    static char**       BuildHTTPRequestOpts(CPLString osOtherXML);
+    static CPLXMLNode*  GetCapabilitiesResponse(const CPLString& osFilename,
+                                                char** papszHTTPOptions);
+    static CPLString    FixCRSName(const char* pszCRS);
+    static CPLString    Replace(const CPLString& osStr, const char* pszOld, const char* pszNew);
+    static CPLString    GetOperationKVPURL(CPLXMLNode* psXML,
+                                           const char* pszOperation);
+    static int          ReadTMS(CPLXMLNode* psContents,
+                                const CPLString& osIdentifier,
+                                WMTSTileMatrixSet& oTMS);
+    static int          ReadTMLimits(CPLXMLNode* psTMSLimits,
+                                     std::map<CPLString, WMTSTileMatrixLimits>& aoMapTileMatrixLimits);
+
+  public:
+                 WMTSDataset();
+    virtual     ~WMTSDataset();
+
+    virtual CPLErr GetGeoTransform(double* padfGT);
+    virtual const char* GetProjectionRef();
+    virtual const char* GetMetadataItem(const char* pszName,
+                                        const char* pszDomain);
+
+    static GDALDataset *Open( GDALOpenInfo * );
+    static int          Identify( GDALOpenInfo * );
+    static GDALDataset *CreateCopy( const char * pszFilename,
+                                         GDALDataset *poSrcDS,
+                                         CPL_UNUSED int bStrict,
+                                         CPL_UNUSED char ** papszOptions,
+                                         CPL_UNUSED GDALProgressFunc pfnProgress,
+                                         CPL_UNUSED void * pProgressData );
+
+  protected:
+    virtual int         CloseDependentDatasets();
+
+    virtual CPLErr  IRasterIO( GDALRWFlag eRWFlag,
+                               int nXOff, int nYOff, int nXSize, int nYSize,
+                               void * pData, int nBufXSize, int nBufYSize,
+                               GDALDataType eBufType,
+                               int nBandCount, int *panBandMap,
+                               GSpacing nPixelSpace, GSpacing nLineSpace,
+                               GSpacing nBandSpace,
+                               GDALRasterIOExtraArg* psExtraArg);
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                               WMTSBand                               */
+/* ==================================================================== */
+/************************************************************************/
+
+class WMTSBand : public GDALPamRasterBand
+{
+  public:
+                  WMTSBand(WMTSDataset* poDS, int nBand);
+
+    virtual GDALRasterBand* GetOverview(int nLevel);
+    virtual int GetOverviewCount();
+    virtual GDALColorInterp GetColorInterpretation();
+    virtual const char* GetMetadataItem(const char* pszName,
+                                        const char* pszDomain);
+
+  protected:
+    virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage);
+    virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
+                              void *, int, int, GDALDataType,
+                              GSpacing, GSpacing,
+                              GDALRasterIOExtraArg* psExtraArg );
+
+};
+
+/************************************************************************/
+/*                            WMTSBand()                                */
+/************************************************************************/
+
+WMTSBand::WMTSBand(WMTSDataset* poDSIn, int nBandIn)
+{
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
+    eDataType = GDT_Byte;
+    poDSIn->apoDatasets[0]->GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
+}
+
+/************************************************************************/
+/*                            IReadBlock()                              */
+/************************************************************************/
+
+CPLErr WMTSBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage)
+{
+    WMTSDataset* poGDS = (WMTSDataset*) poDS;
+    return poGDS->apoDatasets[0]->GetRasterBand(nBand)->ReadBlock(nBlockXOff, nBlockYOff, pImage);
+}
+
+
+/************************************************************************/
+/*                             IRasterIO()                              */
+/************************************************************************/
+
+CPLErr WMTSBand::IRasterIO( GDALRWFlag eRWFlag,
+                            int nXOff, int nYOff, int nXSize, int nYSize,
+                            void * pData, int nBufXSize, int nBufYSize,
+                            GDALDataType eBufType,
+                            GSpacing nPixelSpace, GSpacing nLineSpace,
+                            GDALRasterIOExtraArg* psExtraArg )
+{
+    WMTSDataset* poGDS = (WMTSDataset*) poDS;
+
+    if( (nBufXSize < nXSize || nBufYSize < nYSize)
+        && poGDS->apoDatasets.size() > 1 && eRWFlag == GF_Read )
+    {
+        int bTried;
+        CPLErr eErr = TryOverviewRasterIO( eRWFlag,
+                                    nXOff, nYOff, nXSize, nYSize,
+                                    pData, nBufXSize, nBufYSize,
+                                    eBufType,
+                                    nPixelSpace, nLineSpace,
+                                    psExtraArg,
+                                    &bTried );
+        if( bTried )
+            return eErr;
+    }
+
+    return poGDS->apoDatasets[0]->GetRasterBand(nBand)->RasterIO(
+                                         eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                                         pData, nBufXSize, nBufYSize, eBufType,
+                                         nPixelSpace, nLineSpace, psExtraArg );
+}
+
+/************************************************************************/
+/*                         GetOverviewCount()                           */
+/************************************************************************/
+
+int WMTSBand::GetOverviewCount()
+{
+    WMTSDataset* poGDS = (WMTSDataset*) poDS;
+
+    if( poGDS->apoDatasets.size() > 1 )
+        return (int)poGDS->apoDatasets.size() - 1;
+    else
+        return 0;
+}
+
+/************************************************************************/
+/*                              GetOverview()                           */
+/************************************************************************/
+
+GDALRasterBand* WMTSBand::GetOverview(int nLevel)
+{
+    WMTSDataset* poGDS = (WMTSDataset*) poDS;
+
+    if (nLevel < 0 || nLevel >= GetOverviewCount())
+        return NULL;
+
+    GDALDataset* poOvrDS = poGDS->apoDatasets[nLevel+1];
+    if (poOvrDS)
+        return poOvrDS->GetRasterBand(nBand);
+    else
+        return NULL;
+}
+
+/************************************************************************/
+/*                   GetColorInterpretation()                           */
+/************************************************************************/
+
+GDALColorInterp WMTSBand::GetColorInterpretation()
+{
+    WMTSDataset* poGDS = (WMTSDataset*) poDS;
+    if (poGDS->nBands == 1)
+    {
+        return GCI_GrayIndex;
+    }
+    else if (poGDS->nBands == 3 || poGDS->nBands == 4)
+    {
+        if (nBand == 1)
+            return GCI_RedBand;
+        else if (nBand == 2)
+            return GCI_GreenBand;
+        else if (nBand == 3)
+            return GCI_BlueBand;
+        else if (nBand == 4)
+            return GCI_AlphaBand;
+    }
+
+    return GCI_Undefined;
+}
+
+/************************************************************************/
+/*                         GetMetadataItem()                            */
+/************************************************************************/
+
+const char *WMTSBand::GetMetadataItem( const char * pszName,
+                                       const char * pszDomain )
+{
+    WMTSDataset* poGDS = (WMTSDataset*) poDS;
+
+/* ==================================================================== */
+/*      LocationInfo handling.                                          */
+/* ==================================================================== */
+    if( pszDomain != NULL && EQUAL(pszDomain,"LocationInfo") &&
+        pszName != NULL && STARTS_WITH_CI(pszName, "Pixel_") &&
+        poGDS->oTMS.aoTM.size() &&
+        poGDS->osURLFeatureInfoTemplate.size() )
+    {
+        int iPixel, iLine;
+
+/* -------------------------------------------------------------------- */
+/*      What pixel are we aiming at?                                    */
+/* -------------------------------------------------------------------- */
+        if( sscanf( pszName+6, "%d_%d", &iPixel, &iLine ) != 2 )
+            return NULL;
+
+        const WMTSTileMatrix& oTM = poGDS->oTMS.aoTM[poGDS->oTMS.aoTM.size()-1];
+
+        iPixel += (int)floor(0.5 + (poGDS->adfGT[0] - oTM.dfTLX) / oTM.dfPixelSize);
+        iLine += (int)floor(0.5 + (oTM.dfTLY - poGDS->adfGT[3]) / oTM.dfPixelSize);
+
+        CPLString osURL(poGDS->osURLFeatureInfoTemplate);
+        osURL = WMTSDataset::Replace(osURL, "{TileMatrixSet}", poGDS->osTMS);
+        osURL = WMTSDataset::Replace(osURL, "{TileMatrix}", oTM.osIdentifier);
+        osURL = WMTSDataset::Replace(osURL, "{TileCol}",
+                                     CPLSPrintf("%d", iPixel / oTM.nTileWidth));
+        osURL = WMTSDataset::Replace(osURL, "{TileRow}",
+                                     CPLSPrintf("%d", iLine / oTM.nTileHeight));
+        osURL = WMTSDataset::Replace(osURL, "{I}",
+                                     CPLSPrintf("%d", iPixel % oTM.nTileWidth));
+        osURL = WMTSDataset::Replace(osURL, "{J}",
+                                     CPLSPrintf("%d", iLine % oTM.nTileHeight));
+
+        if( poGDS->osLastGetFeatureInfoURL.compare(osURL) != 0 )
+        {
+            poGDS->osLastGetFeatureInfoURL = osURL;
+            poGDS->osMetadataItemGetFeatureInfo = "";
+            char* pszRes = NULL;
+            CPLHTTPResult* psResult = CPLHTTPFetch( osURL, poGDS->papszHTTPOptions);
+            if( psResult && psResult->nStatus == 0 && psResult->pabyData )
+                pszRes = CPLStrdup((const char*) psResult->pabyData);
+            CPLHTTPDestroyResult(psResult);
+
+            if (pszRes)
+            {
+                poGDS->osMetadataItemGetFeatureInfo = "<LocationInfo>";
+                CPLPushErrorHandler(CPLQuietErrorHandler);
+                CPLXMLNode* psXML = CPLParseXMLString(pszRes);
+                CPLPopErrorHandler();
+                if (psXML != NULL && psXML->eType == CXT_Element)
+                {
+                    if (strcmp(psXML->pszValue, "?xml") == 0)
+                    {
+                        if (psXML->psNext)
+                        {
+                            char* pszXML = CPLSerializeXMLTree(psXML->psNext);
+                            poGDS->osMetadataItemGetFeatureInfo += pszXML;
+                            CPLFree(pszXML);
+                        }
+                    }
+                    else
+                    {
+                        poGDS->osMetadataItemGetFeatureInfo += pszRes;
+                    }
+                }
+                else
+                {
+                    char* pszEscapedXML = CPLEscapeString(pszRes, -1, CPLES_XML_BUT_QUOTES);
+                    poGDS->osMetadataItemGetFeatureInfo += pszEscapedXML;
+                    CPLFree(pszEscapedXML);
+                }
+                if (psXML != NULL)
+                    CPLDestroyXMLNode(psXML);
+
+                poGDS->osMetadataItemGetFeatureInfo += "</LocationInfo>";
+                CPLFree(pszRes);
+            }
+        }
+        return poGDS->osMetadataItemGetFeatureInfo.c_str();
+    }
+
+    return GDALPamRasterBand::GetMetadataItem(pszName, pszDomain);
+}
+
+/************************************************************************/
+/*                          WMTSDataset()                               */
+/************************************************************************/
+
+WMTSDataset::WMTSDataset()
+{
+    adfGT[0] = 0;
+    adfGT[1] = 1;
+    adfGT[2] = 0;
+    adfGT[3] = 0;
+    adfGT[4] = 0;
+    adfGT[5] = 1;
+    papszHTTPOptions = NULL;
+}
+
+/************************************************************************/
+/*                        ~WMTSDataset()                                */
+/************************************************************************/
+
+WMTSDataset::~WMTSDataset()
+{
+    CloseDependentDatasets();
+    CSLDestroy(papszHTTPOptions);
+}
+
+/************************************************************************/
+/*                      CloseDependentDatasets()                        */
+/************************************************************************/
+
+int WMTSDataset::CloseDependentDatasets()
+{
+    int bRet = GDALPamDataset::CloseDependentDatasets();
+    if( apoDatasets.size() )
+    {
+        for(size_t i=0;i<apoDatasets.size();i++)
+            delete apoDatasets[i];
+        apoDatasets.resize(0);
+        bRet = TRUE;
+    }
+    return bRet;
+}
+
+/************************************************************************/
+/*                             IRasterIO()                              */
+/************************************************************************/
+
+CPLErr  WMTSDataset::IRasterIO( GDALRWFlag eRWFlag,
+                               int nXOff, int nYOff, int nXSize, int nYSize,
+                               void * pData, int nBufXSize, int nBufYSize,
+                               GDALDataType eBufType,
+                               int nBandCount, int *panBandMap,
+                               GSpacing nPixelSpace, GSpacing nLineSpace,
+                               GSpacing nBandSpace,
+                               GDALRasterIOExtraArg* psExtraArg)
+{
+    if( (nBufXSize < nXSize || nBufYSize < nYSize)
+        && apoDatasets.size() > 1 && eRWFlag == GF_Read )
+    {
+        int bTried;
+        CPLErr eErr = TryOverviewRasterIO( eRWFlag,
+                                    nXOff, nYOff, nXSize, nYSize,
+                                    pData, nBufXSize, nBufYSize,
+                                    eBufType,
+                                    nBandCount, panBandMap,
+                                    nPixelSpace, nLineSpace,
+                                    nBandSpace,
+                                    psExtraArg,
+                                    &bTried );
+        if( bTried )
+            return eErr;
+    }
+
+    return apoDatasets[0]->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                                  pData, nBufXSize, nBufYSize,
+                                  eBufType, nBandCount, panBandMap,
+                                  nPixelSpace, nLineSpace, nBandSpace,
+                                  psExtraArg );
+}
+
+/************************************************************************/
+/*                          GetGeoTransform()                           */
+/************************************************************************/
+
+CPLErr WMTSDataset::GetGeoTransform(double* padfGT)
+{
+    memcpy(padfGT, adfGT, 6 * sizeof(double));
+    return CE_None;
+}
+
+/************************************************************************/
+/*                         GetProjectionRef()                           */
+/************************************************************************/
+
+const char* WMTSDataset::GetProjectionRef()
+{
+    return osProjection.c_str();
+}
+
+/************************************************************************/
+/*                          WMTSEscapeXML()                             */
+/************************************************************************/
+
+static CPLString WMTSEscapeXML(const char* pszUnescapedXML)
+{
+    CPLString osRet;
+    char* pszTmp = CPLEscapeString(pszUnescapedXML, -1, CPLES_XML);
+    osRet = pszTmp;
+    CPLFree(pszTmp);
+    return osRet;
+}
+
+/************************************************************************/
+/*                         GetMetadataItem()                            */
+/************************************************************************/
+
+const char* WMTSDataset::GetMetadataItem(const char* pszName,
+                                         const char* pszDomain)
+{
+    if( pszName != NULL && EQUAL(pszName, "XML") &&
+        pszDomain != NULL && EQUAL(pszDomain, "WMTS") )
+    {
+        return osXML.c_str();
+    }
+
+    return GDALPamDataset::GetMetadataItem(pszName, pszDomain);
+}
+
+/************************************************************************/
+/*                             Identify()                               */
+/************************************************************************/
+
+int WMTSDataset::Identify(GDALOpenInfo* poOpenInfo)
+{
+    if( STARTS_WITH_CI(poOpenInfo->pszFilename, "WMTS:") )
+        return TRUE;
+
+    if( STARTS_WITH_CI(poOpenInfo->pszFilename, "<GDAL_WMTS") )
+        return TRUE;
+
+    if( poOpenInfo->nHeaderBytes == 0 )
+        return FALSE;
+
+    if( strstr((const char*)poOpenInfo->pabyHeader, "<GDAL_WMTS") )
+        return TRUE;
+
+    return (strstr((const char*)poOpenInfo->pabyHeader,
+                  "<Capabilities") != NULL ||
+            strstr((const char*)poOpenInfo->pabyHeader,
+                  "<wmts:Capabilities") != NULL) &&
+            strstr((const char*)poOpenInfo->pabyHeader,
+                    "http://www.opengis.net/wmts/1.0") != NULL;
+}
+
+/************************************************************************/
+/*                          QuoteIfNecessary()                          */
+/************************************************************************/
+
+static CPLString QuoteIfNecessary(const char* pszVal)
+{
+    if( strchr(pszVal, ' ') || strchr(pszVal, ',') || strchr(pszVal, '=') )
+    {
+        CPLString osVal;
+        osVal += "\"";
+        osVal += pszVal;
+        osVal += "\"";
+        return osVal;
+    }
+    else
+        return pszVal;
+}
+
+/************************************************************************/
+/*                             FixCRSName()                             */
+/************************************************************************/
+
+CPLString WMTSDataset::FixCRSName(const char* pszCRS)
+{
+    while( *pszCRS == ' ' || *pszCRS == '\r' || *pszCRS == '\n' )
+        pszCRS ++;
+
+    /* http://maps.wien.gv.at/wmts/1.0.0/WMTSCapabilities.xml uses urn:ogc:def:crs:EPSG:6.18:3:3857 */
+    /* instead of urn:ogc:def:crs:EPSG:6.18.3:3857. Coming from an incorrect example of URN in WMTS spec */
+    /* https://portal.opengeospatial.org/files/?artifact_id=50398 */
+    if( STARTS_WITH_CI(pszCRS, "urn:ogc:def:crs:EPSG:6.18:3:") )    {
+        return CPLSPrintf("urn:ogc:def:crs:EPSG::%s",
+                          pszCRS + strlen("urn:ogc:def:crs:EPSG:6.18:3:"));
+    }
+
+    if( EQUAL(pszCRS, "urn:ogc:def:crs:EPSG::102100") )
+        return "EPSG:3857";
+
+    CPLString osRet(pszCRS);
+    while( osRet.size() &&
+           (osRet[osRet.size()-1] == ' ' || osRet[osRet.size()-1] == '\r' || osRet[osRet.size()-1] == '\n') )
+    {
+        osRet.resize(osRet.size() - 1);
+    }
+    return osRet;
+}
+
+/************************************************************************/
+/*                              ReadTMS()                               */
+/************************************************************************/
+
+int WMTSDataset::ReadTMS(CPLXMLNode* psContents,
+                         const CPLString& osIdentifier,
+                         WMTSTileMatrixSet& oTMS)
+{
+    for(CPLXMLNode* psIter = psContents->psChild; psIter != NULL; psIter = psIter->psNext )
+    {
+        if( psIter->eType != CXT_Element || strcmp(psIter->pszValue, "TileMatrixSet") != 0 )
+            continue;
+        const char* pszIdentifier = CPLGetXMLValue(psIter, "Identifier", "");
+        if( !EQUAL(osIdentifier, pszIdentifier) )
+            continue;
+        const char* pszSupportedCRS = CPLGetXMLValue(psIter, "SupportedCRS", NULL);
+        if( pszSupportedCRS == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Missing SupportedCRS");
+            return FALSE;
+        }
+        oTMS.osSRS = pszSupportedCRS;
+        if( oTMS.oSRS.SetFromUserInput(FixCRSName(pszSupportedCRS)) != OGRERR_NONE )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Cannot parse CRS '%s'",
+                     pszSupportedCRS);
+            return FALSE;
+        }
+        int bSwap = oTMS.oSRS.EPSGTreatsAsLatLong() || oTMS.oSRS.EPSGTreatsAsNorthingEasting();
+        CPLXMLNode* psBB = CPLGetXMLNode(psIter, "BoundingBox");
+        oTMS.bBoundingBoxValid = FALSE;
+        if( psBB != NULL )
+        {
+            CPLString osCRS = CPLGetXMLValue(psBB, "crs", "");
+            if( EQUAL(osCRS, "") || EQUAL(osCRS, pszSupportedCRS) )
+            {
+                CPLString osLowerCorner = CPLGetXMLValue(psBB, "LowerCorner", "");
+                CPLString osUpperCorner = CPLGetXMLValue(psBB, "UpperCorner", "");
+                if( osLowerCorner.size() && osUpperCorner.size() )
+                {
+                    char** papszLC = CSLTokenizeString(osLowerCorner);
+                    char** papszUC = CSLTokenizeString(osUpperCorner);
+                    if( CSLCount(papszLC) == 2 && CSLCount(papszUC) == 2 )
+                    {
+                        oTMS.sBoundingBox.MinX = CPLAtof(papszLC[(bSwap)? 1 : 0]);
+                        oTMS.sBoundingBox.MinY = CPLAtof(papszLC[(bSwap)? 0 : 1]);
+                        oTMS.sBoundingBox.MaxX = CPLAtof(papszUC[(bSwap)? 1 : 0]);
+                        oTMS.sBoundingBox.MaxY = CPLAtof(papszUC[(bSwap)? 0 : 1]);
+                        oTMS.bBoundingBoxValid = TRUE;
+                    }
+                    CSLDestroy(papszLC);
+                    CSLDestroy(papszUC);
+                }
+            }
+        }
+        else
+        {
+            const char* pszWellKnownScaleSet = CPLGetXMLValue(psIter, "WellKnownScaleSet", "");
+            if( EQUAL(pszIdentifier, "GoogleCRS84Quad") ||
+                EQUAL(pszWellKnownScaleSet, "urn:ogc:def:wkss:OGC:1.0:GoogleCRS84Quad") ||
+                EQUAL(pszIdentifier, "GlobalCRS84Scale") ||
+                EQUAL(pszWellKnownScaleSet, "urn:ogc:def:wkss:OGC:1.0:GlobalCRS84Scale") )
+            {
+                oTMS.sBoundingBox.MinX = -180;
+                oTMS.sBoundingBox.MinY = -90;
+                oTMS.sBoundingBox.MaxX = 180;
+                oTMS.sBoundingBox.MaxY = 90;
+                oTMS.bBoundingBoxValid = TRUE;
+            }
+        }
+
+        for(CPLXMLNode* psSubIter = psIter->psChild; psSubIter != NULL; psSubIter = psSubIter->psNext )
+        {
+            if( psSubIter->eType != CXT_Element || strcmp(psSubIter->pszValue, "TileMatrix") != 0 )
+                continue;
+            const char* l_pszIdentifier = CPLGetXMLValue(psSubIter, "Identifier", NULL);
+            const char* pszScaleDenominator = CPLGetXMLValue(psSubIter, "ScaleDenominator", NULL);
+            const char* pszTopLeftCorner = CPLGetXMLValue(psSubIter, "TopLeftCorner", NULL);
+            const char* pszTileWidth = CPLGetXMLValue(psSubIter, "TileWidth", NULL);
+            const char* pszTileHeight = CPLGetXMLValue(psSubIter, "TileHeight", NULL);
+            const char* pszMatrixWidth = CPLGetXMLValue(psSubIter, "MatrixWidth", NULL);
+            const char* pszMatrixHeight = CPLGetXMLValue(psSubIter, "MatrixHeight", NULL);
+            if( l_pszIdentifier == NULL || pszScaleDenominator == NULL ||
+                pszTopLeftCorner == NULL || strchr(pszTopLeftCorner, ' ') == NULL ||
+                pszTileWidth == NULL || pszTileHeight == NULL ||
+                pszMatrixWidth == NULL || pszMatrixHeight == NULL )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Missing required element in TileMatrix element");
+                return FALSE;
+            }
+            WMTSTileMatrix oTM;
+            oTM.osIdentifier = l_pszIdentifier;
+            oTM.dfScaleDenominator = CPLAtof(pszScaleDenominator);
+            oTM.dfPixelSize = oTM.dfScaleDenominator * WMTS_PITCH;
+            if( oTMS.oSRS.IsGeographic() )
+                oTM.dfPixelSize /= WMTS_METERS_FOR_ONE_DEG;
+            double dfVal1 = CPLAtof(pszTopLeftCorner);
+            double dfVal2 = CPLAtof(strchr(pszTopLeftCorner, ' ')+1);
+            if( !bSwap ||
+                /* Hack for http://osm.geobretagne.fr/gwc01/service/wmts?request=getcapabilities */
+                ( STARTS_WITH_CI(l_pszIdentifier, "EPSG:4326:") &&
+                  dfVal1 == -180.0 ) )
+            {
+                oTM.dfTLX = dfVal1;
+                oTM.dfTLY = dfVal2;
+            }
+            else
+            {
+                oTM.dfTLX = dfVal2;
+                oTM.dfTLY = dfVal1;
+            }
+            oTM.nTileWidth = atoi(pszTileWidth);
+            oTM.nTileHeight = atoi(pszTileHeight);
+            if( oTM.nTileWidth < 128 || oTM.nTileWidth > 4096 ||
+                oTM.nTileHeight < 128 || oTM.nTileHeight > 4096 )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Invalid TileWidth/TileHeight element");
+                return FALSE;
+            }
+            oTM.nMatrixWidth = atoi(pszMatrixWidth);
+            oTM.nMatrixHeight = atoi(pszMatrixHeight);
+            // http://datacarto.geonormandie.fr/mapcache/wmts?SERVICE=WMTS&REQUEST=GetCapabilities
+            // has a TileMatrix 0 with MatrixWidth = MatrixHeight = 0
+            if( oTM.nMatrixWidth < 1 || oTM.nMatrixHeight < 1 )
+                continue;
+            oTMS.aoTM.push_back(oTM);
+        }
+        if( oTMS.aoTM.size() == 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Cannot find TileMatrix in TileMatrixSet '%s'",
+                     osIdentifier.c_str());
+            return FALSE;
+        }
+        return TRUE;
+    }
+    CPLError(CE_Failure, CPLE_AppDefined, "Cannot find TileMatrixSet '%s'",
+             osIdentifier.c_str());
+    return FALSE;
+}
+
+/************************************************************************/
+/*                              ReadTMLimits()                          */
+/************************************************************************/
+
+int WMTSDataset::ReadTMLimits(CPLXMLNode* psTMSLimits,
+                              std::map<CPLString, WMTSTileMatrixLimits>& aoMapTileMatrixLimits)
+{
+    for(CPLXMLNode* psIter = psTMSLimits->psChild; psIter; psIter = psIter->psNext)
+    {
+        if( psIter->eType != CXT_Element || strcmp(psIter->pszValue, "TileMatrixLimits") != 0 )
+            continue;
+        WMTSTileMatrixLimits oTMLimits;
+        const char* pszTileMatrix = CPLGetXMLValue(psIter, "TileMatrix", NULL);
+        const char* pszMinTileRow = CPLGetXMLValue(psIter, "MinTileRow", NULL);
+        const char* pszMaxTileRow = CPLGetXMLValue(psIter, "MaxTileRow", NULL);
+        const char* pszMinTileCol = CPLGetXMLValue(psIter, "MinTileCol", NULL);
+        const char* pszMaxTileCol = CPLGetXMLValue(psIter, "MaxTileCol", NULL);
+        if( pszTileMatrix == NULL ||
+            pszMinTileRow == NULL || pszMaxTileRow == NULL ||
+            pszMinTileCol == NULL || pszMaxTileCol == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Missing required element in TileMatrixLimits element");
+            return FALSE;
+        }
+        oTMLimits.osIdentifier = pszTileMatrix;
+        oTMLimits.nMinTileRow = atoi(pszMinTileRow);
+        oTMLimits.nMaxTileRow = atoi(pszMaxTileRow);
+        oTMLimits.nMinTileCol = atoi(pszMinTileCol);
+        oTMLimits.nMaxTileCol = atoi(pszMaxTileCol);
+        aoMapTileMatrixLimits[pszTileMatrix] = oTMLimits;
+    }
+    return TRUE;
+}
+
+/************************************************************************/
+/*                               Replace()                              */
+/************************************************************************/
+
+CPLString WMTSDataset::Replace(const CPLString& osStr, const char* pszOld,
+                               const char* pszNew)
+{
+    size_t nPos = osStr.ifind(pszOld);
+    if( nPos == std::string::npos )
+        return osStr;
+    CPLString osRet(osStr.substr(0, nPos));
+    osRet += pszNew;
+    osRet += osStr.substr(nPos + strlen(pszOld));
+    return osRet;
+}
+
+/************************************************************************/
+/*                       GetCapabilitiesResponse()                      */
+/************************************************************************/
+
+CPLXMLNode* WMTSDataset::GetCapabilitiesResponse(const CPLString& osFilename,
+                                                 char** papszHTTPOptions)
+{
+    CPLXMLNode* psXML;
+    VSIStatBufL sStat;
+    if( VSIStatL(osFilename, &sStat) == 0 )
+        psXML = CPLParseXMLFile(osFilename);
+    else
+    {
+        CPLHTTPResult* psResult = CPLHTTPFetch(osFilename, papszHTTPOptions);
+        if( psResult == NULL )
+            return NULL;
+        if( psResult->pabyData == NULL )
+        {
+            CPLHTTPDestroyResult(psResult);
+            return NULL;
+        }
+        psXML = CPLParseXMLString((const char*)psResult->pabyData);
+        CPLHTTPDestroyResult(psResult);
+    }
+    return psXML;
+}
+
+/************************************************************************/
+/*                          WMTSAddOtherXML()                           */
+/************************************************************************/
+
+static void WMTSAddOtherXML(CPLXMLNode* psRoot, const char* pszElement,
+                            CPLString& osOtherXML)
+{
+    CPLXMLNode* psElement = CPLGetXMLNode(psRoot, pszElement);
+    if( psElement )
+    {
+        CPLXMLNode* psNext = psElement->psNext;
+        psElement->psNext = NULL;
+        char* pszTmp = CPLSerializeXMLTree(psElement);
+        osOtherXML += pszTmp;
+        CPLFree(pszTmp);
+        psElement->psNext = psNext;
+    }
+}
+
+/************************************************************************/
+/*                          GetOperationKVPURL()                        */
+/************************************************************************/
+
+CPLString WMTSDataset::GetOperationKVPURL(CPLXMLNode* psXML,
+                                          const char* pszOperation)
+{
+    CPLString osRet;
+    CPLXMLNode* psOM = CPLGetXMLNode(psXML, "=Capabilities.OperationsMetadata");
+    for(CPLXMLNode* psIter = psOM ? psOM->psChild : NULL;
+        psIter != NULL; psIter = psIter->psNext)
+    {
+        if( psIter->eType != CXT_Element ||
+            strcmp(psIter->pszValue, "Operation") != 0 ||
+            !EQUAL(CPLGetXMLValue(psIter, "name", ""), pszOperation) )
+        {
+            continue;
+        }
+        CPLXMLNode* psHTTP = CPLGetXMLNode(psIter, "DCP.HTTP");
+        for(CPLXMLNode* psGet = psHTTP ? psHTTP->psChild : NULL;
+                psGet != NULL; psGet = psGet->psNext)
+        {
+            if( psGet->eType != CXT_Element ||
+                strcmp(psGet->pszValue, "Get") != 0 )
+            {
+                continue;
+            }
+            if( !EQUAL(CPLGetXMLValue(psGet, "Constraint.AllowedValues.Value", "KVP"), "KVP") )
+                continue;
+            osRet = CPLGetXMLValue(psGet, "href", "");
+        }
+    }
+    return osRet;
+}
+
+/************************************************************************/
+/*                           BuildHTTPRequestOpts()                     */
+/************************************************************************/
+
+char** WMTSDataset::BuildHTTPRequestOpts(CPLString osOtherXML)
+{
+    osOtherXML = "<Root>" + osOtherXML + "</Root>";
+    CPLXMLNode* psXML = CPLParseXMLString(osOtherXML);
+    char **http_request_opts = NULL;
+    if (CPLGetXMLValue(psXML, "Timeout", NULL)) {
+        CPLString optstr;
+        optstr.Printf("TIMEOUT=%s", CPLGetXMLValue(psXML, "Timeout", NULL));
+        http_request_opts = CSLAddString(http_request_opts, optstr.c_str());
+    }
+    if (CPLGetXMLValue(psXML, "UserAgent", NULL)) {
+        CPLString optstr;
+        optstr.Printf("USERAGENT=%s", CPLGetXMLValue(psXML, "UserAgent", NULL));
+        http_request_opts = CSLAddString(http_request_opts, optstr.c_str());
+    }
+    if (CPLGetXMLValue(psXML, "Referer", NULL)) {
+        CPLString optstr;
+        optstr.Printf("REFERER=%s", CPLGetXMLValue(psXML, "Referer", NULL));
+        http_request_opts = CSLAddString(http_request_opts, optstr.c_str());
+    }
+    if (CPLTestBool(CPLGetXMLValue(psXML, "UnsafeSSL", "false"))) {
+        http_request_opts = CSLAddString(http_request_opts, "UNSAFESSL=1");
+    }
+    if (CPLGetXMLValue(psXML, "UserPwd", NULL)) {
+        CPLString optstr;
+        optstr.Printf("USERPWD=%s", CPLGetXMLValue(psXML, "UserPwd", NULL));
+        http_request_opts = CSLAddString(http_request_opts, optstr.c_str());
+    }
+    CPLDestroyXMLNode(psXML);
+    return http_request_opts;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
+{
+    if (!Identify(poOpenInfo))
+        return NULL;
+
+    CPLXMLNode* psXML = NULL;
+    CPLString osTileFormat;
+    CPLString osInfoFormat;
+
+    CPLString osGetCapabilitiesURL = CSLFetchNameValueDef(poOpenInfo->papszOpenOptions,
+                                                "URL", "");
+    CPLString osLayer = CSLFetchNameValueDef(poOpenInfo->papszOpenOptions,
+                                    "LAYER", "");
+    CPLString osTMS = CSLFetchNameValueDef(poOpenInfo->papszOpenOptions,
+                                    "TILEMATRIXSET", "");
+    CPLString osStyle = CSLFetchNameValueDef(poOpenInfo->papszOpenOptions,
+                                    "STYLE", "");
+    int bExtendBeyondDateLine = CSLFetchBoolean(poOpenInfo->papszOpenOptions,
+                                    "EXTENDBEYONDDATELINE", FALSE);
+
+    CPLString osOtherXML = "<Cache />"
+                     "<UnsafeSSL>true</UnsafeSSL>"
+                     "<ZeroBlockHttpCodes>204,404</ZeroBlockHttpCodes>"
+                     "<ZeroBlockOnServerException>true</ZeroBlockOnServerException>";
+
+    if( STARTS_WITH_CI(poOpenInfo->pszFilename, "WMTS:") )
+    {
+        char** papszTokens = CSLTokenizeString2( poOpenInfo->pszFilename + 5,
+                                                 ",", CSLT_HONOURSTRINGS );
+        if( papszTokens && papszTokens[0] )
+        {
+            osGetCapabilitiesURL = papszTokens[0];
+            for(char** papszIter = papszTokens+1; *papszIter; papszIter++)
+            {
+                char* pszKey = NULL;
+                const char* pszValue = CPLParseNameValue(*papszIter, &pszKey);
+                if( pszKey && pszValue )
+                {
+                    if( EQUAL(pszKey, "layer") )
+                        osLayer = pszValue;
+                    else if( EQUAL(pszKey, "tilematrixset") )
+                        osTMS = pszValue;
+                    else if( EQUAL(pszKey, "style") )
+                        osStyle = pszValue;
+                    else if( EQUAL(pszKey, "extendbeyonddateline") )
+                        bExtendBeyondDateLine = CPLTestBool(pszValue);
+                    else
+                        CPLError(CE_Warning, CPLE_AppDefined,
+                                 "Unknown parameter: %s'", pszKey);
+                }
+                CPLFree(pszKey);
+            }
+        }
+        CSLDestroy(papszTokens);
+
+        char** papszHTTPOptions = BuildHTTPRequestOpts(osOtherXML);
+        psXML = GetCapabilitiesResponse(osGetCapabilitiesURL, papszHTTPOptions);
+        CSLDestroy(papszHTTPOptions);
+    }
+
+    int bHasAOI = FALSE;
+    OGREnvelope sAOI;
+    int nBands = 4;
+    CPLString osProjection;
+
+    if( (psXML != NULL && CPLGetXMLNode(psXML, "=GDAL_WMTS") != NULL ) ||
+        STARTS_WITH_CI(poOpenInfo->pszFilename, "<GDAL_WMTS") ||
+        (poOpenInfo->nHeaderBytes > 0 &&
+         strstr((const char*)poOpenInfo->pabyHeader, "<GDAL_WMTS")) )
+    {
+        CPLXMLNode* psGDALWMTS;
+        if( psXML != NULL && CPLGetXMLNode(psXML, "=GDAL_WMTS") != NULL )
+            psGDALWMTS = CPLCloneXMLTree(psXML);
+        else if( STARTS_WITH_CI(poOpenInfo->pszFilename, "<GDAL_WMTS") )
+            psGDALWMTS = CPLParseXMLString(poOpenInfo->pszFilename);
+        else
+            psGDALWMTS = CPLParseXMLFile(poOpenInfo->pszFilename);
+        if( psGDALWMTS == NULL )
+            return NULL;
+        CPLXMLNode* psRoot = CPLGetXMLNode(psGDALWMTS, "=GDAL_WMTS");
+        if( psRoot == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Cannot find root <GDAL_WMTS>");
+            CPLDestroyXMLNode(psGDALWMTS);
+            return NULL;
+        }
+        osGetCapabilitiesURL = CPLGetXMLValue(psRoot, "GetCapabilitiesUrl", "");
+        if( osGetCapabilitiesURL.size() == 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Missing <GetCapabilitiesUrl>");
+            CPLDestroyXMLNode(psGDALWMTS);
+            return NULL;
+        }
+
+        osLayer = CPLGetXMLValue(psRoot, "Layer", osLayer);
+        osTMS = CPLGetXMLValue(psRoot, "TileMatrixSet", osTMS);
+        osStyle = CPLGetXMLValue(psRoot, "Style", osStyle);
+        osTileFormat = CPLGetXMLValue(psRoot, "Format", osTileFormat);
+        osInfoFormat = CPLGetXMLValue(psRoot, "InfoFormat", osInfoFormat);
+        osProjection = CPLGetXMLValue(psRoot, "Projection", osProjection);
+        bExtendBeyondDateLine = CPLTestBool(CPLGetXMLValue(psRoot, "ExtendBeyondDateLine",
+                                            (bExtendBeyondDateLine) ? "true": "false"));
+
+        osOtherXML = "";
+        WMTSAddOtherXML(psRoot, "Cache", osOtherXML);
+        WMTSAddOtherXML(psRoot, "MaxConnections", osOtherXML);
+        WMTSAddOtherXML(psRoot, "Timeout", osOtherXML);
+        WMTSAddOtherXML(psRoot, "OfflineMode", osOtherXML);
+        WMTSAddOtherXML(psRoot, "MaxConnections", osOtherXML);
+        WMTSAddOtherXML(psRoot, "UserAgent", osOtherXML);
+        WMTSAddOtherXML(psRoot, "UserPwd", osOtherXML);
+        WMTSAddOtherXML(psRoot, "UnsafeSSL", osOtherXML);
+        WMTSAddOtherXML(psRoot, "Referer", osOtherXML);
+        WMTSAddOtherXML(psRoot, "ZeroBlockHttpCodes", osOtherXML);
+        WMTSAddOtherXML(psRoot, "ZeroBlockOnServerException", osOtherXML);
+
+        nBands = atoi(CPLGetXMLValue(psRoot, "BandsCount", "4"));
+
+        const char* pszULX = CPLGetXMLValue(psRoot, "DataWindow.UpperLeftX", NULL);
+        const char* pszULY = CPLGetXMLValue(psRoot, "DataWindow.UpperLeftY", NULL);
+        const char* pszLRX = CPLGetXMLValue(psRoot, "DataWindow.LowerRightX", NULL);
+        const char* pszLRY = CPLGetXMLValue(psRoot, "DataWindow.LowerRightY", NULL);
+        if( pszULX && pszULY && pszLRX && pszLRY )
+        {
+            sAOI.MinX = CPLAtof(pszULX);
+            sAOI.MaxY = CPLAtof(pszULY);
+            sAOI.MaxX = CPLAtof(pszLRX);
+            sAOI.MinY = CPLAtof(pszLRY);
+            bHasAOI = TRUE;
+        }
+
+        CPLDestroyXMLNode(psGDALWMTS);
+
+        CPLDestroyXMLNode(psXML);
+        char** papszHTTPOptions = BuildHTTPRequestOpts(osOtherXML);
+        psXML = GetCapabilitiesResponse(osGetCapabilitiesURL, papszHTTPOptions);
+        CSLDestroy(papszHTTPOptions);
+    }
+    else if( !STARTS_WITH_CI(poOpenInfo->pszFilename, "WMTS:") )
+    {
+        osGetCapabilitiesURL = poOpenInfo->pszFilename;
+        psXML = CPLParseXMLFile(poOpenInfo->pszFilename);
+    }
+    if( psXML == NULL )
+        return NULL;
+    CPLStripXMLNamespace(psXML, NULL, TRUE);
+
+    CPLXMLNode* psContents = CPLGetXMLNode(psXML, "=Capabilities.Contents");
+    if( psContents == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Missing Capabilities.Contents element");
+        CPLDestroyXMLNode(psXML);
+        return NULL;
+    }
+
+    if( STARTS_WITH(osGetCapabilitiesURL, "/vsimem/") )
+    {
+        if( CPLGetXMLValue(psXML, "=Capabilities.ServiceMetadataURL.href", NULL) )
+            osGetCapabilitiesURL = CPLGetXMLValue(psXML, "=Capabilities.ServiceMetadataURL.href", NULL);
+        else
+        {
+            osGetCapabilitiesURL = GetOperationKVPURL(psXML, "GetCapabilities");
+            if( osGetCapabilitiesURL.size() )
+            {
+                osGetCapabilitiesURL = CPLURLAddKVP(osGetCapabilitiesURL, "service", "WMTS");
+                osGetCapabilitiesURL = CPLURLAddKVP(osGetCapabilitiesURL, "request", "GetCapabilities");
+            }
+        }
+    }
+    CPLString osCapabilitiesFilename(osGetCapabilitiesURL);
+    if( !STARTS_WITH_CI(osCapabilitiesFilename, "WMTS:") )
+        osCapabilitiesFilename = "WMTS:" + osGetCapabilitiesURL;
+
+    int nLayerCount = 0;
+    CPLStringList aosSubDatasets;
+    CPLString osSelectLayer(osLayer), osSelectTMS(osTMS), osSelectStyle(osStyle);
+    CPLString osSelectLayerTitle, osSelectLayerAbstract;
+    CPLString osSelectTileFormat(osTileFormat), osSelectInfoFormat(osInfoFormat);
+    int nCountTileFormat = 0, nCountInfoFormat = 0;
+    CPLString osURLTileTemplate;
+    CPLString osURLFeatureInfoTemplate;
+    std::set<CPLString> aoSetLayers;
+    std::map<CPLString, OGREnvelope> aoMapBoundingBox;
+    std::map<CPLString, WMTSTileMatrixLimits> aoMapTileMatrixLimits;
+    std::map<CPLString, CPLString> aoMapDimensions;
+
+    for(CPLXMLNode* psIter = psContents->psChild; psIter != NULL; psIter = psIter->psNext )
+    {
+        if( psIter->eType != CXT_Element || strcmp(psIter->pszValue, "Layer") != 0 )
+            continue;
+        const char* pszIdentifier = CPLGetXMLValue(psIter, "Identifier", "");
+        if( aoSetLayers.find(pszIdentifier) != aoSetLayers.end() )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Several layers with identifier '%s'. Only first one kept",
+                     pszIdentifier);
+        }
+        aoSetLayers.insert(pszIdentifier);
+        if( osLayer.size() && strcmp(osLayer, pszIdentifier) != 0 )
+            continue;
+        const char* pszTitle = CPLGetXMLValue(psIter, "Title", NULL);
+        if( osSelectLayer.size() == 0 )
+        {
+            osSelectLayer = pszIdentifier;
+        }
+        if( strcmp(osSelectLayer, pszIdentifier) == 0 )
+        {
+            if( pszTitle != NULL )
+                osSelectLayerTitle = pszTitle;
+            const char* pszAbstract = CPLGetXMLValue(psIter, "Abstract", NULL);
+            if( pszAbstract != NULL )
+                osSelectLayerAbstract = pszAbstract;
+        }
+
+        std::vector<CPLString> aosTMS;
+        std::vector<CPLString> aosStylesIdentifier;
+        std::vector<CPLString> aosStylesTitle;
+
+        CPLXMLNode* psSubIter = psIter->psChild;
+        for(; psSubIter != NULL; psSubIter = psSubIter->psNext )
+        {
+            if( psSubIter->eType != CXT_Element )
+                continue;
+            if( strcmp(osSelectLayer, pszIdentifier) == 0 &&
+                strcmp(psSubIter->pszValue, "Format") == 0 )
+            {
+                const char* pszValue = CPLGetXMLValue(psSubIter, "", "");
+                if( osTileFormat.size() && strcmp(osTileFormat, pszValue) != 0 )
+                    continue;
+                nCountTileFormat ++;
+                if( osSelectTileFormat.size() == 0 ||
+                    EQUAL(pszValue, "image/png") )
+                {
+                    osSelectTileFormat = pszValue;
+                }
+            }
+            else if( strcmp(osSelectLayer, pszIdentifier) == 0 &&
+                     strcmp(psSubIter->pszValue, "InfoFormat") == 0 )
+            {
+                const char* pszValue = CPLGetXMLValue(psSubIter, "", "");
+                if( osInfoFormat.size() && strcmp(osInfoFormat, pszValue) != 0 )
+                    continue;
+                nCountInfoFormat ++;
+                if( osSelectInfoFormat.size() == 0 ||
+                    (EQUAL(pszValue, "application/vnd.ogc.gml") &&
+                     !EQUAL(osSelectInfoFormat, "application/vnd.ogc.gml/3.1.1")) ||
+                    EQUAL(pszValue, "application/vnd.ogc.gml/3.1.1") )
+                {
+                    osSelectInfoFormat = pszValue;
+                }
+            }
+            else if( strcmp(osSelectLayer, pszIdentifier) == 0 &&
+                     strcmp(psSubIter->pszValue, "Dimension") == 0 )
+            {
+                /* Cf http://wmts.geo.admin.ch/1.0.0/WMTSCapabilities.xml */
+                const char* pszDimensionIdentifier = CPLGetXMLValue(psSubIter, "Identifier", NULL);
+                const char* pszDefault = CPLGetXMLValue(psSubIter, "Default", "");
+                if( pszDimensionIdentifier != NULL )
+                    aoMapDimensions[pszDimensionIdentifier] = pszDefault;
+            }
+            else if( strcmp(psSubIter->pszValue, "TileMatrixSetLink") == 0 )
+            {
+                const char* pszTMS = CPLGetXMLValue(
+                                            psSubIter, "TileMatrixSet", "");
+                if( osTMS.size() && strcmp(osTMS, pszTMS) != 0 )
+                    continue;
+                if( strcmp(osSelectLayer, pszIdentifier) == 0 &&
+                    osSelectTMS.size() == 0 )
+                {
+                    osSelectTMS = pszTMS;
+                }
+                if( strcmp(osSelectLayer, pszIdentifier) == 0 &&
+                    strcmp(osSelectTMS, pszTMS) == 0 )
+                {
+                    CPLXMLNode* psTMSLimits = CPLGetXMLNode(
+                                        psSubIter, "TileMatrixSetLimits");
+                    if( psTMSLimits )
+                        ReadTMLimits(psTMSLimits, aoMapTileMatrixLimits);
+                }
+                aosTMS.push_back(pszTMS);
+            }
+            else if( strcmp(psSubIter->pszValue, "Style") == 0 )
+            {
+                int bIsDefault = CPLTestBool(CPLGetXMLValue(
+                                            psSubIter, "isDefault", "false"));
+                const char* l_pszIdentifier = CPLGetXMLValue(
+                                            psSubIter, "Identifier", "");
+                if( osStyle.size() && strcmp(osStyle, l_pszIdentifier) != 0 )
+                    continue;
+                const char* pszStyleTitle = CPLGetXMLValue(
+                                        psSubIter, "Title", l_pszIdentifier);
+                if( bIsDefault )
+                {
+                    aosStylesIdentifier.insert(aosStylesIdentifier.begin(),
+                                                CPLString(l_pszIdentifier));
+                    aosStylesTitle.insert(aosStylesTitle.begin(),
+                                            CPLString(pszStyleTitle));
+                    if( strcmp(osSelectLayer, l_pszIdentifier) == 0 &&
+                        osSelectStyle.size() == 0 )
+                    {
+                        osSelectStyle = l_pszIdentifier;
+                    }
+                }
+                else
+                {
+                    aosStylesIdentifier.push_back(l_pszIdentifier);
+                    aosStylesTitle.push_back(pszStyleTitle);
+                }
+            }
+            else if( strcmp(osSelectLayer, pszIdentifier) == 0 &&
+                     (strcmp(psSubIter->pszValue, "BoundingBox") == 0 ||
+                      strcmp(psSubIter->pszValue, "WGS84BoundingBox") == 0) )
+            {
+                CPLString osCRS = CPLGetXMLValue(psSubIter, "crs", "");
+                if( osCRS.size() == 0 )
+                {
+                    if( strcmp(psSubIter->pszValue, "WGS84BoundingBox") == 0 )
+                    {
+                        osCRS = "EPSG:4326";
+                    }
+                    else
+                    {
+                        int nCountTileMatrixSet = 0;
+                        CPLString osSingleTileMatrixSet;
+                        for(CPLXMLNode* psIter3 = psContents->psChild; psIter3 != NULL; psIter3 = psIter3->psNext )
+                        {
+                            if( psIter3->eType != CXT_Element || strcmp(psIter3->pszValue, "TileMatrixSet") != 0 )
+                                continue;
+                            nCountTileMatrixSet ++;
+                            if( nCountTileMatrixSet == 1 )
+                                osSingleTileMatrixSet = CPLGetXMLValue(psIter3, "Identifier", "");
+                        }
+                        if( nCountTileMatrixSet == 1 )
+                        {
+                            // For 13-082_WMTS_Simple_Profile/schemas/wmts/1.0/profiles/WMTSSimple/examples/wmtsGetCapabilities_response_OSM.xml
+                            WMTSTileMatrixSet oTMS;
+                            if( ReadTMS(psContents, osSingleTileMatrixSet, oTMS) )
+                            {
+                                osCRS = oTMS.osSRS;
+                            }
+                        }
+                    }
+                }
+                CPLString osLowerCorner = CPLGetXMLValue(psSubIter, "LowerCorner", "");
+                CPLString osUpperCorner = CPLGetXMLValue(psSubIter, "UpperCorner", "");
+                OGRSpatialReference oSRS;
+                if( osCRS.size() && osLowerCorner.size() && osUpperCorner.size() &&
+                    oSRS.SetFromUserInput(FixCRSName(osCRS)) == OGRERR_NONE )
+                {
+                    int bSwap = oSRS.EPSGTreatsAsLatLong() ||
+                                oSRS.EPSGTreatsAsNorthingEasting();
+                    char** papszLC = CSLTokenizeString(osLowerCorner);
+                    char** papszUC = CSLTokenizeString(osUpperCorner);
+                    if( CSLCount(papszLC) == 2 && CSLCount(papszUC) == 2 )
+                    {
+                        OGREnvelope sEnvelope;
+                        sEnvelope.MinX = CPLAtof(papszLC[(bSwap)? 1 : 0]);
+                        sEnvelope.MinY = CPLAtof(papszLC[(bSwap)? 0 : 1]);
+                        sEnvelope.MaxX = CPLAtof(papszUC[(bSwap)? 1 : 0]);
+                        sEnvelope.MaxY = CPLAtof(papszUC[(bSwap)? 0 : 1]);
+                        aoMapBoundingBox[osCRS] = sEnvelope;
+                    }
+                    CSLDestroy(papszLC);
+                    CSLDestroy(papszUC);
+                }
+            }
+            else if( strcmp(osSelectLayer, pszIdentifier) == 0 &&
+                     strcmp(psSubIter->pszValue, "ResourceURL") == 0 )
+            {
+                if( EQUAL(CPLGetXMLValue(psSubIter, "resourceType", ""), "tile") )
+                {
+                    const char* pszFormat = CPLGetXMLValue(psSubIter, "format", "");
+                    if( osTileFormat.size() && strcmp(osTileFormat, pszFormat) != 0 )
+                        continue;
+                    if( osURLTileTemplate.size() == 0 )
+                        osURLTileTemplate = CPLGetXMLValue(psSubIter, "template", "");
+                }
+                else if( EQUAL(CPLGetXMLValue(psSubIter, "resourceType", ""), "FeatureInfo") )
+                {
+                    const char* pszFormat = CPLGetXMLValue(psSubIter, "format", "");
+                    if( osInfoFormat.size() && strcmp(osInfoFormat, pszFormat) != 0 )
+                        continue;
+                    if( osURLFeatureInfoTemplate.size() == 0 )
+                        osURLFeatureInfoTemplate = CPLGetXMLValue(psSubIter, "template", "");
+                }
+            }
+        }
+        if( strcmp(osSelectLayer, pszIdentifier) == 0 &&
+            osSelectStyle.size() == 0 && aosStylesIdentifier.size() > 0 )
+        {
+            osSelectStyle = aosStylesIdentifier[0];
+        }
+        for(size_t i=0;i<aosTMS.size();i++)
+        {
+            for(size_t j=0;j<aosStylesIdentifier.size();j++)
+            {
+                int nIdx = 1 + aosSubDatasets.size() / 2;
+                CPLString osName(osCapabilitiesFilename);
+                osName += ",layer=";
+                osName += QuoteIfNecessary(pszIdentifier);
+                if( aosTMS.size() > 1 )
+                {
+                    osName += ",tilematrixset=";
+                    osName += QuoteIfNecessary(aosTMS[i]);
+                }
+                if( aosStylesIdentifier.size() > 1 )
+                {
+                    osName += ",style=";
+                    osName += QuoteIfNecessary(aosStylesIdentifier[j]);
+                }
+                aosSubDatasets.AddNameValue(
+                    CPLSPrintf("SUBDATASET_%d_NAME", nIdx), osName);
+
+                CPLString osDesc("Layer ");
+                osDesc += pszTitle ? pszTitle : pszIdentifier;
+                if( aosTMS.size() > 1 )
+                {
+                    osDesc += ", tile matrix set ";
+                    osDesc += aosTMS[i];
+                }
+                if( aosStylesIdentifier.size() > 1 )
+                {
+                    osDesc += ", style ";
+                    osDesc += QuoteIfNecessary(aosStylesTitle[j]);
+                }
+                aosSubDatasets.AddNameValue(
+                    CPLSPrintf("SUBDATASET_%d_DESC", nIdx), osDesc);
+            }
+        }
+        if( aosTMS.size() && aosStylesIdentifier.size() )
+            nLayerCount ++;
+        else
+            CPLError(CE_Failure, CPLE_AppDefined, "Missing TileMatrixSetLink and/or Style");
+    }
+
+    if( nLayerCount == 0 )
+    {
+        CPLDestroyXMLNode(psXML);
+        return NULL;
+    }
+
+    WMTSDataset* poDS = new WMTSDataset();
+
+    if( aosSubDatasets.size() > 2 )
+        poDS->SetMetadata(aosSubDatasets.List(), "SUBDATASETS");
+
+    if( nLayerCount == 1 )
+    {
+        if( osSelectLayerTitle.size() )
+            poDS->SetMetadataItem("TITLE", osSelectLayerTitle);
+        if( osSelectLayerAbstract.size() )
+            poDS->SetMetadataItem("ABSTRACT", osSelectLayerAbstract);
+
+        poDS->papszHTTPOptions = BuildHTTPRequestOpts(osOtherXML);
+        poDS->osLayer = osSelectLayer;
+        poDS->osTMS = osSelectTMS;
+
+        WMTSTileMatrixSet oTMS;
+        if( !ReadTMS(psContents, osSelectTMS, oTMS) )
+        {
+            CPLDestroyXMLNode(psXML);
+            delete poDS;
+            return NULL;
+        }
+
+        // Use in priority layer bounding box expressed in the SRS of the TMS
+        if( (!bHasAOI || bExtendBeyondDateLine) &&
+            aoMapBoundingBox.find(oTMS.osSRS) != aoMapBoundingBox.end() )
+        {
+            if( !bHasAOI )
+            {
+                sAOI = aoMapBoundingBox[oTMS.osSRS];
+                bHasAOI = TRUE;
+            }
+
+            int bRecomputeAOI = FALSE;
+            if( bExtendBeyondDateLine )
+            {
+                bExtendBeyondDateLine = FALSE;
+
+                OGRSpatialReference oWGS84;
+                    oWGS84.SetFromUserInput(SRS_WKT_WGS84);
+                OGRCoordinateTransformation* poCT =
+                    OGRCreateCoordinateTransformation(&oTMS.oSRS, &oWGS84);
+                if( poCT != NULL )
+                {
+                    double dfX1 = sAOI.MinX;
+                    double dfY1 = sAOI.MinY;
+                    double dfX2 = sAOI.MaxX;
+                    double dfY2 = sAOI.MaxY;
+                    if( poCT->Transform(1, &dfX1, &dfY1) &&
+                        poCT->Transform(1, &dfX2, &dfY2) )
+                    {
+                        if( fabs(dfX1 + 180) < 1e-8 &&
+                            fabs(dfX2 - 180) < 1e-8 )
+                        {
+                            bExtendBeyondDateLine = TRUE;
+                            bRecomputeAOI = TRUE;
+                        }
+                        else if( dfX2 < dfX1 )
+                        {
+                            bExtendBeyondDateLine = TRUE;
+                        }
+                        else
+                        {
+                            CPLError(CE_Warning, CPLE_AppDefined,
+                                    "ExtendBeyondDateLine disabled, since longitudes of %s "
+                                    "BoundingBox do not span from -180 to 180 but from %.16g to %.16g, "
+                                    "or longitude of upper right corner is not lesser than the one of lower left corner",
+                                    oTMS.osSRS.c_str(), dfX1, dfX2);
+                        }
+                    }
+                    delete poCT;
+                }
+            }
+            if( bExtendBeyondDateLine && bRecomputeAOI )
+            {
+                bExtendBeyondDateLine = FALSE;
+
+                std::map<CPLString, OGREnvelope>::iterator oIter = aoMapBoundingBox.begin();
+                for(; oIter != aoMapBoundingBox.end(); ++oIter )
+                {
+                    OGRSpatialReference oSRS;
+                    if( oSRS.SetFromUserInput(FixCRSName(oIter->first)) == OGRERR_NONE )
+                    {
+                        OGRSpatialReference oWGS84;
+                        oWGS84.SetFromUserInput(SRS_WKT_WGS84);
+                        OGRCoordinateTransformation* poCT =
+                            OGRCreateCoordinateTransformation(&oSRS, &oWGS84);
+                        double dfX1 = oIter->second.MinX;
+                        double dfY1 = oIter->second.MinY;
+                        double dfX2 = oIter->second.MaxX;
+                        double dfY2 = oIter->second.MaxY;
+                        if( poCT != NULL &&
+                            poCT->Transform(1, &dfX1, &dfY1) &&
+                            poCT->Transform(1, &dfX2, &dfY2) &&
+                            dfX2 < dfX1 )
+                        {
+                            delete poCT;
+                            dfX2 += 360;
+                            char* pszProj4 = NULL;
+                            oTMS.oSRS.exportToProj4(&pszProj4);
+                            oSRS.SetFromUserInput(CPLSPrintf("%s +over +wktext", pszProj4));
+                            CPLFree(pszProj4);
+                            poCT = OGRCreateCoordinateTransformation(&oWGS84, &oSRS);
+                            if( poCT &&
+                                poCT->Transform(1, &dfX1, &dfY1) &&
+                                poCT->Transform(1, &dfX2, &dfY2) )
+                            {
+                                bExtendBeyondDateLine = TRUE;
+                                sAOI.MinX = MIN(dfX1, dfX2);
+                                sAOI.MinY = MIN(dfY1, dfY2);
+                                sAOI.MaxX = MAX(dfX1, dfX2);
+                                sAOI.MaxY = MAX(dfY1, dfY2);
+                                CPLDebug("WMTS",
+                                         "ExtendBeyondDateLine using %s bounding box",
+                                         oIter->first.c_str());
+                            }
+                            delete poCT;
+                            break;
+                        }
+                        delete poCT;
+                    }
+                }
+            }
+        }
+        else
+        {
+            if( bExtendBeyondDateLine )
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "ExtendBeyondDateLine disabled, since BoundingBox of %s is missing",
+                         oTMS.osSRS.c_str());
+                bExtendBeyondDateLine = FALSE;
+            }
+        }
+
+        // Otherwise default to reprojection a layer bounding box expressed in
+        // another SRS
+        if( !bHasAOI && aoMapBoundingBox.size() )
+        {
+            std::map<CPLString, OGREnvelope>::iterator oIter = aoMapBoundingBox.begin();
+            for(; oIter != aoMapBoundingBox.end(); ++oIter )
+            {
+                OGRSpatialReference oSRS;
+                if( oSRS.SetFromUserInput(FixCRSName(oIter->first)) == OGRERR_NONE )
+                {
+                    OGRCoordinateTransformation* poCT =
+                        OGRCreateCoordinateTransformation(&oSRS, &oTMS.oSRS);
+                    if( poCT != NULL )
+                    {
+                        double dfX1 = oIter->second.MinX;
+                        double dfY1 = oIter->second.MinY;
+                        double dfX2 = oIter->second.MaxX;
+                        double dfY2 = oIter->second.MinY;
+                        double dfX3 = oIter->second.MaxX;
+                        double dfY3 = oIter->second.MaxY;
+                        double dfX4 = oIter->second.MinX;
+                        double dfY4 = oIter->second.MaxY;
+                        if( poCT->Transform(1, &dfX1, &dfY1) &&
+                            poCT->Transform(1, &dfX2, &dfY2) &&
+                            poCT->Transform(1, &dfX3, &dfY3) &&
+                            poCT->Transform(1, &dfX4, &dfY4) )
+                        {
+                            sAOI.MinX = MIN(MIN(dfX1, dfX2),MIN(dfX3,dfX4));
+                            sAOI.MinY = MIN(MIN(dfY1, dfY2),MIN(dfY3,dfY4));
+                            sAOI.MaxX = MAX(MAX(dfX1, dfX2),MAX(dfX3,dfX4));
+                            sAOI.MaxY = MAX(MAX(dfY1, dfY2),MAX(dfY3,dfY4));
+                            bHasAOI = TRUE;
+                        }
+                        delete poCT;
+                    }
+                    break;
+                }
+            }
+        }
+
+        // Otherwise default to BoundingBox of the TMS
+        if( !bHasAOI && oTMS.bBoundingBoxValid )
+        {
+            CPLDebug("WMTS", "Using TMS bounding box");
+            sAOI = oTMS.sBoundingBox;
+            bHasAOI = TRUE;
+        }
+
+        // Otherwise default to implied BoundingBox of the most precise TM
+        if( !bHasAOI )
+        {
+            const WMTSTileMatrix& oTM = oTMS.aoTM[oTMS.aoTM.size()-1];
+            CPLDebug("WMTS", "Using TM level %s bounding box", oTM.osIdentifier.c_str() );
+
+            sAOI.MinX = oTM.dfTLX;
+            sAOI.MaxY = oTM.dfTLY;
+            sAOI.MaxX = oTM.dfTLX + oTM.nMatrixWidth  * oTM.dfPixelSize * oTM.nTileWidth;
+            sAOI.MinY = oTM.dfTLY - oTM.nMatrixHeight * oTM.dfPixelSize * oTM.nTileHeight;
+            /*bHasAOI = TRUE;*/
+        }
+        else
+        {
+            // Clip with implied BoundingBox of the most precise TM
+            // Useful for http://tileserver.maptiler.com/wmts
+            const WMTSTileMatrix& oTM = oTMS.aoTM[oTMS.aoTM.size()-1];
+
+            // For https://data.linz.govt.nz/services;key=XXXXXXXX/wmts/1.0.0/set/69/WMTSCapabilities.xml
+            // only clip in Y since there's a warp over dateline
+            //sAOI.MinX = MAX(sAOI.MinX, oTM.dfTLX);
+            sAOI.MaxY = MIN(sAOI.MaxY, oTM.dfTLY);
+            //sAOI.MaxX = MIN(sAOI.MaxX, oTM.dfTLX + oTM.nMatrixWidth  * oTM.dfPixelSize * oTM.nTileWidth);
+            sAOI.MinY = MAX(sAOI.MinY, oTM.dfTLY - oTM.nMatrixHeight * oTM.dfPixelSize * oTM.nTileHeight);
+        }
+
+        // Clip with limits of most precise TM when available
+        {
+            const WMTSTileMatrix& oTM = oTMS.aoTM[oTMS.aoTM.size()-1];
+            if( aoMapTileMatrixLimits.find(oTM.osIdentifier) != aoMapTileMatrixLimits.end() )
+            {
+                const WMTSTileMatrixLimits& oTMLimits = aoMapTileMatrixLimits[oTM.osIdentifier];
+                double dfTileWidthUnits = oTM.dfPixelSize * oTM.nTileWidth;
+                double dfTileHeightUnits = oTM.dfPixelSize * oTM.nTileHeight;
+                sAOI.MinX = MAX(sAOI.MinX, oTM.dfTLX + oTMLimits.nMinTileCol * dfTileWidthUnits);
+                sAOI.MaxY = MIN(sAOI.MaxY, oTM.dfTLY - oTMLimits.nMinTileRow * dfTileHeightUnits);
+                sAOI.MaxX = MIN(sAOI.MaxX, oTM.dfTLX + (oTMLimits.nMaxTileCol + 1) * dfTileWidthUnits);
+                sAOI.MinY = MAX(sAOI.MinY, oTM.dfTLY - (oTMLimits.nMaxTileRow + 1) * dfTileHeightUnits);
+            }
+        }
+
+        // Establish raster dimension and extent
+        int nMaxZoomLevel = (int)oTMS.aoTM.size()-1;
+        while(nMaxZoomLevel >= 0)
+        {
+            const WMTSTileMatrix& oTM = oTMS.aoTM[nMaxZoomLevel];
+            double dfRasterXSize = (sAOI.MaxX - sAOI.MinX) / oTM.dfPixelSize;
+            double dfRasterYSize = (sAOI.MaxY - sAOI.MinY) / oTM.dfPixelSize;
+            if( dfRasterXSize < INT_MAX && dfRasterYSize < INT_MAX )
+            {
+                if( nMaxZoomLevel != (int)oTMS.aoTM.size()-1 )
+                {
+                    CPLDebug("WMTS", "Using zoom level %s instead of %s to avoid int overflow",
+                             oTMS.aoTM[nMaxZoomLevel].osIdentifier.c_str(),
+                             oTMS.aoTM[(int)oTMS.aoTM.size()-1].osIdentifier.c_str());
+                }
+
+                // Align AOI on pixel boundaries with respect to TopLeftCorner of
+                // this tile matrix
+                poDS->adfGT[0] = oTM.dfTLX + floor((sAOI.MinX - oTM.dfTLX) / oTM.dfPixelSize+1e-10) * oTM.dfPixelSize;
+                poDS->adfGT[1] = oTM.dfPixelSize;
+                poDS->adfGT[2] = 0.0;
+                poDS->adfGT[3] = oTM.dfTLY + ceil((sAOI.MaxY - oTM.dfTLY) / oTM.dfPixelSize-1e-10) * oTM.dfPixelSize;
+                poDS->adfGT[4] = 0.0;
+                poDS->adfGT[5] = -oTM.dfPixelSize;
+                poDS->nRasterXSize = int(0.5 + (sAOI.MaxX - poDS->adfGT[0]) / oTM.dfPixelSize);
+                poDS->nRasterYSize = int(0.5 + (poDS->adfGT[3] - sAOI.MinY) / oTM.dfPixelSize);
+                break;
+            }
+            nMaxZoomLevel --;
+        }
+        if( nMaxZoomLevel < 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "No zoom level in tile matrix set found");
+            CPLDestroyXMLNode(psXML);
+            delete poDS;
+            return NULL;
+        }
+        oTMS.aoTM.resize(1 + nMaxZoomLevel);
+        poDS->oTMS = oTMS;
+
+        if( osProjection.size() )
+        {
+            OGRSpatialReference oSRS;
+            if( oSRS.SetFromUserInput(osProjection) == OGRERR_NONE )
+            {
+                char* pszWKT = NULL;
+                oSRS.exportToWkt(&pszWKT);
+                poDS->osProjection = pszWKT;
+                CPLFree(pszWKT);
+            }
+        }
+        if( poDS->osProjection.size() == 0 )
+        {
+            // Strip AXIS
+            OGR_SRSNode *poGEOGCS = oTMS.oSRS.GetAttrNode( "GEOGCS" );
+            if( poGEOGCS != NULL )
+                poGEOGCS->StripNodes( "AXIS" );
+
+            OGR_SRSNode *poPROJCS = oTMS.oSRS.GetAttrNode( "PROJCS" );
+            if (poPROJCS != NULL && oTMS.oSRS.EPSGTreatsAsNorthingEasting())
+                poPROJCS->StripNodes( "AXIS" );
+
+            char* pszWKT = NULL;
+            oTMS.oSRS.exportToWkt(&pszWKT);
+            poDS->osProjection = pszWKT;
+            CPLFree(pszWKT);
+        }
+
+        if( osURLTileTemplate.size() == 0 )
+        {
+            osURLTileTemplate = GetOperationKVPURL(psXML, "GetTile");
+            if( osURLTileTemplate.size() == 0 )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "No RESTful nor KVP GetTile operation found");
+                CPLDestroyXMLNode(psXML);
+                delete poDS;
+                return NULL;
+            }
+            osURLTileTemplate = CPLURLAddKVP(osURLTileTemplate, "service", "WMTS");
+            osURLTileTemplate = CPLURLAddKVP(osURLTileTemplate, "request", "GetTile");
+            osURLTileTemplate = CPLURLAddKVP(osURLTileTemplate, "version", "1.0.0");
+            osURLTileTemplate = CPLURLAddKVP(osURLTileTemplate, "layer", osSelectLayer);
+            osURLTileTemplate = CPLURLAddKVP(osURLTileTemplate, "style", osSelectStyle);
+            osURLTileTemplate = CPLURLAddKVP(osURLTileTemplate, "format", osSelectTileFormat);
+            osURLTileTemplate = CPLURLAddKVP(osURLTileTemplate, "TileMatrixSet", osSelectTMS);
+            osURLTileTemplate += "&TileMatrix={TileMatrix}";
+            osURLTileTemplate += "&TileRow=${y}";
+            osURLTileTemplate += "&TileCol=${x}";
+
+            std::map<CPLString,CPLString>::iterator oIter = aoMapDimensions.begin();
+            for(; oIter != aoMapDimensions.end(); ++oIter )
+            {
+                osURLTileTemplate = CPLURLAddKVP(osURLTileTemplate,
+                                                 oIter->first,
+                                                 oIter->second);
+            }
+            //CPLDebug("WMTS", "osURLTileTemplate = %s", osURLTileTemplate.c_str());
+        }
+        else
+        {
+            osURLTileTemplate = Replace(osURLTileTemplate, "{Style}", osSelectStyle);
+            osURLTileTemplate = Replace(osURLTileTemplate, "{TileMatrixSet}", osSelectTMS);
+            osURLTileTemplate = Replace(osURLTileTemplate, "{TileCol}", "${x}");
+            osURLTileTemplate = Replace(osURLTileTemplate, "{TileRow}", "${y}");
+
+            std::map<CPLString,CPLString>::iterator oIter = aoMapDimensions.begin();
+            for(; oIter != aoMapDimensions.end(); ++oIter )
+            {
+                osURLTileTemplate = Replace(osURLTileTemplate,
+                                            CPLSPrintf("{%s}", oIter->first.c_str()),
+                                            oIter->second);
+            }
+        }
+
+        if( osURLFeatureInfoTemplate.size() == 0 && osSelectInfoFormat.size() != 0 )
+        {
+            osURLFeatureInfoTemplate = GetOperationKVPURL(psXML, "GetFeatureInfo");
+            if( osURLFeatureInfoTemplate.size() != 0 )
+            {
+                osURLFeatureInfoTemplate = CPLURLAddKVP(osURLFeatureInfoTemplate, "service", "WMTS");
+                osURLFeatureInfoTemplate = CPLURLAddKVP(osURLFeatureInfoTemplate, "request", "GetFeatureInfo");
+                osURLFeatureInfoTemplate = CPLURLAddKVP(osURLFeatureInfoTemplate, "version", "1.0.0");
+                osURLFeatureInfoTemplate = CPLURLAddKVP(osURLFeatureInfoTemplate, "layer", osSelectLayer);
+                osURLFeatureInfoTemplate = CPLURLAddKVP(osURLFeatureInfoTemplate, "style", osSelectStyle);
+                //osURLFeatureInfoTemplate = CPLURLAddKVP(osURLFeatureInfoTemplate, "format", osSelectTileFormat);
+                osURLFeatureInfoTemplate = CPLURLAddKVP(osURLFeatureInfoTemplate, "InfoFormat", osSelectInfoFormat);
+                osURLFeatureInfoTemplate += "&TileMatrixSet={TileMatrixSet}";
+                osURLFeatureInfoTemplate += "&TileMatrix={TileMatrix}";
+                osURLFeatureInfoTemplate += "&TileRow={TileRow}";
+                osURLFeatureInfoTemplate += "&TileCol={TileCol}";
+                osURLFeatureInfoTemplate += "&J={J}";
+                osURLFeatureInfoTemplate += "&I={I}";
+
+                std::map<CPLString,CPLString>::iterator oIter = aoMapDimensions.begin();
+                for(; oIter != aoMapDimensions.end(); ++oIter )
+                {
+                    osURLFeatureInfoTemplate = CPLURLAddKVP(osURLFeatureInfoTemplate,
+                                                            oIter->first,
+                                                            oIter->second);
+                }
+                //CPLDebug("WMTS", "osURLFeatureInfoTemplate = %s", osURLFeatureInfoTemplate.c_str());
+            }
+        }
+        else
+        {
+             osURLFeatureInfoTemplate = Replace(osURLFeatureInfoTemplate, "{Style}", osSelectStyle);
+
+            std::map<CPLString,CPLString>::iterator oIter = aoMapDimensions.begin();
+            for(; oIter != aoMapDimensions.end(); ++oIter )
+            {
+                osURLFeatureInfoTemplate = Replace(osURLFeatureInfoTemplate,
+                                            CPLSPrintf("{%s}", oIter->first.c_str()),
+                                            oIter->second);
+            }
+        }
+        poDS->osURLFeatureInfoTemplate = osURLFeatureInfoTemplate;
+
+        // Build all TMS datasets, wrapped in VRT datasets
+        for(int i=nMaxZoomLevel;i>=0;i--)
+        {
+            const WMTSTileMatrix& oTM = oTMS.aoTM[i];
+            int nRasterXSize = int(0.5 + poDS->nRasterXSize / oTM.dfPixelSize * poDS->adfGT[1]);
+            int nRasterYSize = int(0.5 + poDS->nRasterYSize / oTM.dfPixelSize * poDS->adfGT[1]);
+            if( nRasterXSize < 128 || nRasterYSize < 128 )
+            {
+                break;
+            }
+            CPLString osURL(Replace(osURLTileTemplate, "{TileMatrix}", oTM.osIdentifier));
+
+            double dfTileWidthUnits = oTM.dfPixelSize * oTM.nTileWidth;
+            double dfTileHeightUnits = oTM.dfPixelSize * oTM.nTileHeight;
+
+            // Compute the shift in terms of tiles between AOI and TM origin
+            int nTileX = (int)(floor(poDS->adfGT[0] - oTM.dfTLX + 1e-10) / dfTileWidthUnits);
+            int nTileY = (int)(floor(oTM.dfTLY - poDS->adfGT[3] + 1e-10) / dfTileHeightUnits);
+
+            // Compute extent of this zoom level slightly larger than the AOI and
+            // aligned on tile boundaries at this TM
+            double dfULX = oTM.dfTLX + nTileX * dfTileWidthUnits;
+            double dfULY = oTM.dfTLY - nTileY * dfTileHeightUnits;
+            double dfLRX = poDS->adfGT[0] + poDS->nRasterXSize * poDS->adfGT[1];
+            double dfLRY = poDS->adfGT[3] + poDS->nRasterYSize * poDS->adfGT[5];
+            dfLRX = dfULX + ceil((dfLRX - dfULX) / dfTileWidthUnits - 1e-10) * dfTileWidthUnits;
+            dfLRY = dfULY + floor((dfLRY - dfULY) / dfTileHeightUnits + 1e-10) * dfTileHeightUnits;
+
+            int nSizeX = int(0.5+(dfLRX - dfULX) / oTM.dfPixelSize);
+            int nSizeY = int(0.5+(dfULY - dfLRY) / oTM.dfPixelSize);
+
+            double dfDateLineX = oTM.dfTLX + oTM.nMatrixWidth * dfTileWidthUnits;
+            int nSizeX1 = int(0.5+(dfDateLineX - dfULX) / oTM.dfPixelSize);
+            int nSizeX2 = int(0.5+(dfLRX - dfDateLineX) / oTM.dfPixelSize);
+            if( dfDateLineX > dfLRX )
+            {
+                CPLDebug("WMTS", "ExtendBeyondDateLine ignored in that case");
+                bExtendBeyondDateLine = FALSE;
+            }
+
+#define WMS_TMS_TEMPLATE \
+    "<GDAL_WMS>" \
+    "<Service name=\"TMS\">" \
+    "    <ServerUrl>%s</ServerUrl>" \
+    "</Service>" \
+    "<DataWindow>" \
+    "    <UpperLeftX>%.16g</UpperLeftX>" \
+    "    <UpperLeftY>%.16g</UpperLeftY>" \
+    "    <LowerRightX>%.16g</LowerRightX>" \
+    "    <LowerRightY>%.16g</LowerRightY>" \
+    "    <TileLevel>0</TileLevel>" \
+    "    <TileX>%d</TileX>" \
+    "    <TileY>%d</TileY>" \
+    "    <SizeX>%d</SizeX>" \
+    "    <SizeY>%d</SizeY>" \
+    "    <YOrigin>top</YOrigin>" \
+    "</DataWindow>" \
+    "<BlockSizeX>%d</BlockSizeX>" \
+    "<BlockSizeY>%d</BlockSizeY>" \
+    "<BandsCount>%d</BandsCount>" \
+    "%s" \
+"</GDAL_WMS>"
+
+            CPLString osStr(CPLSPrintf( WMS_TMS_TEMPLATE,
+                WMTSEscapeXML(osURL).c_str(),
+                dfULX, dfULY, (bExtendBeyondDateLine) ? dfDateLineX : dfLRX, dfLRY,
+                nTileX, nTileY, (bExtendBeyondDateLine) ? nSizeX1 : nSizeX, nSizeY,
+                oTM.nTileWidth, oTM.nTileHeight, nBands,
+                osOtherXML.c_str()));
+            GDALDataset* poWMSDS = (GDALDataset*)GDALOpenEx(
+                osStr, GDAL_OF_RASTER | GDAL_OF_SHARED | GDAL_OF_VERBOSE_ERROR, NULL, NULL, NULL);
+            if( poWMSDS == NULL )
+            {
+                CPLDestroyXMLNode(psXML);
+                delete poDS;
+                return NULL;
+            }
+
+            VRTDatasetH hVRTDS = VRTCreate( nRasterXSize, nRasterYSize );
+            for(int iBand=1;iBand<=nBands;iBand++)
+            {
+                VRTAddBand( hVRTDS, GDT_Byte, NULL );
+            }
+
+            int nSrcXOff, nSrcYOff, nDstXOff, nDstYOff;
+
+            nSrcXOff = 0;
+            nDstXOff = (int)(0.5 + (dfULX - poDS->adfGT[0]) / oTM.dfPixelSize);
+
+            nSrcYOff = 0;
+            nDstYOff = (int)(0.5 + (poDS->adfGT[3] - dfULY) / oTM.dfPixelSize);
+
+            if( bExtendBeyondDateLine )
+            {
+                int nSrcXOff2, nDstXOff2;
+
+                nSrcXOff2 = 0;
+                nDstXOff2 = (int)(0.5 + (dfDateLineX - poDS->adfGT[0]) / oTM.dfPixelSize);
+
+                osStr = CPLSPrintf( WMS_TMS_TEMPLATE,
+                    WMTSEscapeXML(osURL).c_str(),
+                    -dfDateLineX, dfULY, dfLRX - 2 * dfDateLineX, dfLRY,
+                    0, nTileY, nSizeX2, nSizeY,
+                    oTM.nTileWidth, oTM.nTileHeight, nBands,
+                    osOtherXML.c_str());
+
+                GDALDataset* poWMSDS2 = (GDALDataset*)GDALOpenEx(
+                    osStr, GDAL_OF_RASTER | GDAL_OF_SHARED, NULL, NULL, NULL);
+                CPLAssert(poWMSDS2);
+
+                for(int iBand=1;iBand<=nBands;iBand++)
+                {
+                    VRTSourcedRasterBandH hVRTBand =
+                        (VRTSourcedRasterBandH) GDALGetRasterBand(hVRTDS, iBand);
+                    VRTAddSimpleSource( hVRTBand, GDALGetRasterBand(poWMSDS, iBand),
+                                        nSrcXOff, nSrcYOff, nSizeX1, nSizeY,
+                                        nDstXOff, nDstYOff, nSizeX1, nSizeY,
+                                        "NEAR", VRT_NODATA_UNSET);
+                    VRTAddSimpleSource( hVRTBand, GDALGetRasterBand(poWMSDS2, iBand),
+                                        nSrcXOff2, nSrcYOff, nSizeX2, nSizeY,
+                                        nDstXOff2, nDstYOff, nSizeX2, nSizeY,
+                                        "NEAR", VRT_NODATA_UNSET);
+                }
+
+                poWMSDS2->Dereference();
+            }
+            else
+            {
+                for(int iBand=1;iBand<=nBands;iBand++)
+                {
+                    VRTSourcedRasterBandH hVRTBand =
+                        (VRTSourcedRasterBandH) GDALGetRasterBand(hVRTDS, iBand);
+                    VRTAddSimpleSource( hVRTBand, GDALGetRasterBand(poWMSDS, iBand),
+                                        nSrcXOff, nSrcYOff, nSizeX, nSizeY,
+                                        nDstXOff, nDstYOff, nSizeX, nSizeY,
+                                        "NEAR", VRT_NODATA_UNSET);
+                }
+            }
+
+            poWMSDS->Dereference();
+
+            poDS->apoDatasets.push_back((GDALDataset*)hVRTDS);
+        }
+
+        if( poDS->apoDatasets.size() == 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "No zoom level found");
+            CPLDestroyXMLNode(psXML);
+            delete poDS;
+            return NULL;
+        }
+
+        poDS->SetMetadataItem("INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE");
+        for(int i=0;i<nBands;i++)
+            poDS->SetBand(i+1, new WMTSBand(poDS,i+1));
+
+        poDS->osXML = "<GDAL_WMTS>\n";
+        poDS->osXML += "  <GetCapabilitiesUrl>" +
+                     WMTSEscapeXML(osGetCapabilitiesURL) +
+                     "</GetCapabilitiesUrl>\n";
+        if( osSelectLayer.size() )
+            poDS->osXML += "  <Layer>" + WMTSEscapeXML(osSelectLayer) + "</Layer>\n";
+        if( osSelectStyle.size() )
+            poDS->osXML += "  <Style>" + WMTSEscapeXML(osSelectStyle) + "</Style>\n";
+        if( osSelectTMS.size() )
+            poDS->osXML += "  <TileMatrixSet>" + WMTSEscapeXML(osSelectTMS) + "</TileMatrixSet>\n";
+        if( nCountTileFormat > 1 && osSelectTileFormat.size() )
+            poDS->osXML += "  <Format>" + WMTSEscapeXML(osSelectTileFormat) + "</Format>\n";
+        if( nCountInfoFormat > 1 && osSelectInfoFormat.size() )
+            poDS->osXML += "  <InfoFormat>" + WMTSEscapeXML(osSelectInfoFormat) + "</InfoFormat>\n";
+        poDS->osXML += "  <DataWindow>\n";
+        poDS->osXML += CPLSPrintf("    <UpperLeftX>%.16g</UpperLeftX>\n",
+                             poDS->adfGT[0]);
+        poDS->osXML += CPLSPrintf("    <UpperLeftY>%.16g</UpperLeftY>\n",
+                             poDS->adfGT[3]);
+        poDS->osXML += CPLSPrintf("    <LowerRightX>%.16g</LowerRightX>\n",
+                             poDS->adfGT[0] +  poDS->adfGT[1] *  poDS->nRasterXSize);
+        poDS->osXML += CPLSPrintf("    <LowerRightY>%.16g</LowerRightY>\n",
+                             poDS->adfGT[3] +  poDS->adfGT[5] *  poDS->nRasterYSize);
+        poDS->osXML += "  </DataWindow>\n";
+        if( bExtendBeyondDateLine )
+            poDS->osXML += "  <ExtendBeyondDateLine>true</ExtendBeyondDateLine>\n";
+        poDS->osXML += CPLSPrintf("  <BandsCount>%d</BandsCount>\n", nBands);
+        poDS->osXML += "  <Cache />\n";
+        poDS->osXML += "  <UnsafeSSL>true</UnsafeSSL>\n";
+        poDS->osXML += "  <ZeroBlockHttpCodes>204,404</ZeroBlockHttpCodes>\n";
+        poDS->osXML += "  <ZeroBlockOnServerException>true</ZeroBlockOnServerException>\n";
+        poDS->osXML += "</GDAL_WMTS>\n";
+    }
+
+    CPLDestroyXMLNode(psXML);
+
+    poDS->SetPamFlags(0);
+    return poDS;
+}
+/************************************************************************/
+/*                             CreateCopy()                             */
+/************************************************************************/
+
+GDALDataset *WMTSDataset::CreateCopy( const char * pszFilename,
+                                         GDALDataset *poSrcDS,
+                                         CPL_UNUSED int bStrict,
+                                         CPL_UNUSED char ** papszOptions,
+                                         CPL_UNUSED GDALProgressFunc pfnProgress,
+                                         CPL_UNUSED void * pProgressData )
+{
+    if( poSrcDS->GetDriver() == NULL ||
+        poSrcDS->GetDriver() != GDALGetDriverByName("WMTS") )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Source dataset must be a WMTS dataset");
+        return NULL;
+    }
+
+    const char* pszXML = poSrcDS->GetMetadataItem("XML", "WMTS");
+    if (pszXML == NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot get XML definition of source WMTS dataset");
+        return NULL;
+    }
+
+    VSILFILE* fp = VSIFOpenL(pszFilename, "wb");
+    if (fp == NULL)
+        return NULL;
+
+    VSIFWriteL(pszXML, 1, strlen(pszXML), fp);
+    VSIFCloseL(fp);
+
+    GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly);
+    return Open(&oOpenInfo);
+}
+
+/************************************************************************/
+/*                       GDALRegister_WMTS()                            */
+/************************************************************************/
+
+void GDALRegister_WMTS()
+
+{
+    if( !GDAL_CHECK_VERSION( "WMTS driver" ) )
+        return;
+
+    if( GDALGetDriverByName( "WMTS" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "WMTS" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "OGC Web Mab Tile Service" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_wmts.html" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, "WMTS:" );
+
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+"<OpenOptionList>"
+"  <Option name='URL' type='string' description='URL that points to GetCapabilities response' required='YES'/>"
+"  <Option name='LAYER' type='string' description='Layer identifier'/>"
+"  <Option name='TILEMATRIXSET' alias='TMS' type='string' description='Tile matrix set identifier'/>"
+"  <Option name='STYLE' type='string' description='Style identifier'/>"
+"  <Option name='EXTENDBEYONDDATELINE' type='boolean' description='Whether to enable extend-beyond-dateline behaviour' default='NO'/>"
+"</OpenOptionList>");
+
+    poDriver->pfnOpen = WMTSDataset::Open;
+    poDriver->pfnIdentify = WMTSDataset::Identify;
+    poDriver->pfnCreateCopy = WMTSDataset::CreateCopy;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/frmts/xpm/xpmdataset.cpp b/frmts/xpm/xpmdataset.cpp
index d972905..62f5416 100644
--- a/frmts/xpm/xpmdataset.cpp
+++ b/frmts/xpm/xpmdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: xpmdataset.cpp 31998 2015-12-04 20:03:08Z rouault $
+ * $Id: xpmdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  XPM Driver
  * Purpose:  Implement GDAL XPM Support
@@ -31,17 +31,15 @@
 #include "gdal_pam.h"
 #include "cpl_string.h"
 #include "memdataset.h"
-#include "gdal_frmts.h"						      
+#include "gdal_frmts.h"
 
-
-CPL_CVSID("$Id: xpmdataset.cpp 31998 2015-12-04 20:03:08Z rouault $");
+CPL_CVSID("$Id: xpmdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 static unsigned char *ParseXPM( const char *pszInput,
                                 unsigned int nFileSize,
-                                int *pnXSize, int *pnYSize, 
+                                int *pnXSize, int *pnYSize,
                                 GDALColorTable **ppoRetTable );
 
-
 /************************************************************************/
 /* ==================================================================== */
 /*				XPMDataset				*/
@@ -51,22 +49,14 @@ static unsigned char *ParseXPM( const char *pszInput,
 class XPMDataset : public GDALPamDataset
 {
   public:
-                 XPMDataset();
+                 XPMDataset() {};
                  ~XPMDataset();
 
     static GDALDataset *Open( GDALOpenInfo * );
+    static int          Identify( GDALOpenInfo * );
 };
 
 /************************************************************************/
-/*                            XPMDataset()                            */
-/************************************************************************/
-
-XPMDataset::XPMDataset()
-
-{
-}
-
-/************************************************************************/
 /*                            ~XPMDataset()                             */
 /************************************************************************/
 
@@ -77,10 +67,10 @@ XPMDataset::~XPMDataset()
 }
 
 /************************************************************************/
-/*                                Open()                                */
+/*                            Identify()                                */
 /************************************************************************/
 
-GDALDataset *XPMDataset::Open( GDALOpenInfo * poOpenInfo )
+int XPMDataset::Identify( GDALOpenInfo * poOpenInfo )
 
 {
 /* -------------------------------------------------------------------- */
@@ -89,14 +79,26 @@ GDALDataset *XPMDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      containing the letters XPM, and to have "static" in the         */
 /*      header.                                                         */
 /* -------------------------------------------------------------------- */
-    if( poOpenInfo->nHeaderBytes < 32 
-        || strstr((const char *) poOpenInfo->pabyHeader,"XPM") == NULL 
-        || strstr((const char *) poOpenInfo->pabyHeader,"static") == NULL )
+    return poOpenInfo->nHeaderBytes >= 32 &&
+           strstr(reinterpret_cast<const char *>( poOpenInfo->pabyHeader ),
+                  "XPM") != NULL &&
+           strstr(reinterpret_cast<const char *>( poOpenInfo->pabyHeader ),
+                  "static") != NULL;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *XPMDataset::Open( GDALOpenInfo * poOpenInfo )
+
+{
+    if( !Identify(poOpenInfo) )
         return NULL;
 
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The XPM driver does not support update access to existing"
                   " files." );
         return NULL;
@@ -105,51 +107,50 @@ GDALDataset *XPMDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Read the whole file into a memory strings.                      */
 /* -------------------------------------------------------------------- */
-    unsigned int nFileSize;
-    char *pszFileContents;
     VSILFILE *fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
     if( fp == NULL )
         return NULL;
 
-    VSIFSeekL( fp, 0, SEEK_END );
-    nFileSize = (unsigned int) VSIFTellL( fp );
-    
-    pszFileContents = (char *) VSIMalloc(nFileSize+1);
-    if( pszFileContents == NULL )
+    if( VSIFSeekL( fp, 0, SEEK_END ) != 0 )
+    {
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
+        return NULL;
+    }
+    unsigned int nFileSize = static_cast<unsigned int>( VSIFTellL( fp ) );
+
+    char *pszFileContents = reinterpret_cast<char *>( VSI_MALLOC_VERBOSE(nFileSize+1) );
+    if( pszFileContents == NULL  )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory, 
-                  "Insufficient memory for loading XPM file %s into memory.", 
-                  poOpenInfo->pszFilename );
-        VSIFCloseL(fp);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
         return NULL;
     }
     pszFileContents[nFileSize] = '\0';
-    
-    VSIFSeekL( fp, 0, SEEK_SET );
 
-    if( VSIFReadL( pszFileContents, 1, nFileSize, fp ) != nFileSize)
+    if( VSIFSeekL( fp, 0, SEEK_SET ) != 0 ||
+        VSIFReadL( pszFileContents, 1, nFileSize, fp ) != nFileSize)
     {
         CPLFree( pszFileContents );
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   "Failed to read all %d bytes from file %s.",
                   nFileSize, poOpenInfo->pszFilename );
-        VSIFCloseL(fp);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
         return NULL;
     }
-    
-    VSIFCloseL(fp);
+
+    CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
     fp = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Convert into a binary image.                                    */
 /* -------------------------------------------------------------------- */
-    GByte *pabyImage;
-    int   nXSize, nYSize;
+    CPLErrorReset();
+
+    int nXSize;
+    int nYSize;
     GDALColorTable *poCT = NULL;
 
-    CPLErrorReset();
+    GByte *pabyImage = ParseXPM( pszFileContents, nFileSize, &nXSize, &nYSize, &poCT );
 
-    pabyImage = ParseXPM( pszFileContents, nFileSize, &nXSize, &nYSize, &poCT );
     CPLFree( pszFileContents );
 
     if( pabyImage == NULL )
@@ -160,9 +161,7 @@ GDALDataset *XPMDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    XPMDataset 	*poDS;
-
-    poDS = new XPMDataset();
+    XPMDataset 	*poDS = new XPMDataset();
 
 /* -------------------------------------------------------------------- */
 /*      Capture some information from the file that is of interest.     */
@@ -173,10 +172,8 @@ GDALDataset *XPMDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    MEMRasterBand *poBand;
-
-    poBand = new MEMRasterBand( poDS, 1, pabyImage, GDT_Byte, 1, nXSize, 
-                                TRUE );
+    MEMRasterBand *poBand = new MEMRasterBand( poDS, 1, pabyImage, GDT_Byte, 1,
+                                               nXSize, TRUE );
     poBand->SetColorTable( poCT );
     poDS->SetBand( 1, poBand );
 
@@ -202,35 +199,31 @@ GDALDataset *XPMDataset::Open( GDALOpenInfo * poOpenInfo )
 
 static GDALDataset *
 XPMCreateCopy( const char * pszFilename,
-               CPL_UNUSED GDALDataset *poSrcDS,
+               GDALDataset *poSrcDS,
                int bStrict,
-               CPL_UNUSED char ** papszOptions,
-               CPL_UNUSED GDALProgressFunc pfnProgress,
-               CPL_UNUSED void * pProgressData )
+               char ** /* papszOptions */,
+               GDALProgressFunc /* pfnProgress */,
+               void * /* pProgressData */)
 {
-    int  nBands = poSrcDS->GetRasterCount();
-    int  nXSize = poSrcDS->GetRasterXSize();
-    int  nYSize = poSrcDS->GetRasterYSize();
-    GDALColorTable *poCT;
-
 /* -------------------------------------------------------------------- */
 /*      Some some rudimentary checks                                    */
 /* -------------------------------------------------------------------- */
+    const int nBands = poSrcDS->GetRasterCount();
     if( nBands != 1 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "XPM driver only supports one band images.\n" );
 
         return NULL;
     }
 
-    if( poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte 
+    if( poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte
         && bStrict )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "XPM driver doesn't support data type %s. "
-                  "Only eight bit bands supported.\n", 
-                  GDALGetDataTypeName( 
+                  "Only eight bit bands supported.\n",
+                  GDALGetDataTypeName(
                       poSrcDS->GetRasterBand(1)->GetRasterDataType()) );
 
         return NULL;
@@ -240,16 +233,16 @@ XPMCreateCopy( const char * pszFilename,
 /*      If there is no colortable on the source image, create a         */
 /*      greyscale one with 64 levels of grey.                           */
 /* -------------------------------------------------------------------- */
-    GDALRasterBand	*poBand = poSrcDS->GetRasterBand(1);
-    int                 i;
-    GDALColorTable      oGreyTable;
+    GDALRasterBand *poBand = poSrcDS->GetRasterBand(1);
+
+    GDALColorTable oGreyTable;
+    GDALColorTable *poCT = poBand->GetColorTable();
 
-    poCT = poBand->GetColorTable();
     if( poCT == NULL )
     {
         poCT = &oGreyTable;
 
-        for( i = 0; i < 256; i++ )
+        for( int i = 0; i < 256; i++ )
         {
             GDALColorEntry sColor;
 
@@ -266,15 +259,17 @@ XPMCreateCopy( const char * pszFilename,
 /*      Build list of active colors, and the mapping from pixels to     */
 /*      our active colormap.                                            */
 /* -------------------------------------------------------------------- */
-    const char *pszColorCodes = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-+=[]|:;,.<>?/";
+    const char *pszColorCodes
+        = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@"
+        "#$%^&*()-+=[]|:;,.<>?/";
 
     int  anPixelMapping[256];
     GDALColorEntry asPixelColor[256];
-    int  nActiveColors = MIN(poCT->GetColorEntryCount(),256);
+    int nActiveColors = MIN(poCT->GetColorEntryCount(),256);
 
-    // Setup initial colortable and pixel value mapping. 
+    // Setup initial colortable and pixel value mapping.
     memset( anPixelMapping+0, 0, sizeof(int) * 256 );
-    for( i = 0; i < nActiveColors; i++ )
+    for( int i = 0; i < nActiveColors; i++ )
     {
         poCT->GetColorEntryAsRGB( i, asPixelColor + i );
         anPixelMapping[i] = i;
@@ -283,24 +278,24 @@ XPMCreateCopy( const char * pszFilename,
 /* ==================================================================== */
 /*      Iterate merging colors until we are under our limit (about 85). */
 /* ==================================================================== */
-    while( nActiveColors > (int) strlen(pszColorCodes) )
+    while( nActiveColors > static_cast<int>( strlen(pszColorCodes) ) )
     {
         int nClosestDistance = 768;
-        int iClose1 = -1, iClose2 = -1;
-        int iColor1, iColor2;
+        int iClose1 = -1;
+        int iClose2 = -1;
 
-        // Find the closest pair of colors. 
-        for( iColor1 = 0; iColor1 < nActiveColors; iColor1++ )
+        // Find the closest pair of colors.
+        for( int iColor1 = 0; iColor1 < nActiveColors; iColor1++ )
         {
-            for( iColor2 = iColor1+1; iColor2 < nActiveColors; iColor2++ )
+            for( int iColor2 = iColor1+1; iColor2 < nActiveColors; iColor2++ )
             {
-                int	nDistance;
+                int nDistance;
 
-                if( asPixelColor[iColor1].c4 < 128 
+                if( asPixelColor[iColor1].c4 < 128
                     && asPixelColor[iColor2].c4 < 128 )
                     nDistance = 0;
                 else
-                    nDistance = 
+                    nDistance =
                         ABS(asPixelColor[iColor1].c1-asPixelColor[iColor2].c1)
                       + ABS(asPixelColor[iColor1].c2-asPixelColor[iColor2].c2)
                       + ABS(asPixelColor[iColor1].c3-asPixelColor[iColor2].c3);
@@ -322,8 +317,8 @@ XPMCreateCopy( const char * pszFilename,
             break;
 
         // Merge two selected colors - shift icolor2 into icolor1 and
-        // move the last active color into icolor2's slot. 
-        for( i = 0; i < 256; i++ )
+        // move the last active color into icolor2's slot.
+        for( int i = 0; i < 256; i++ )
         {
             if( anPixelMapping[i] == iClose2 )
                 anPixelMapping[i] = iClose1;
@@ -334,17 +329,15 @@ XPMCreateCopy( const char * pszFilename,
         asPixelColor[iClose2] = asPixelColor[nActiveColors-1];
         nActiveColors--;
     }
-        
+
 /* ==================================================================== */
 /*      Write the output image.                                         */
 /* ==================================================================== */
-    VSILFILE	*fpPBM;
-
-    fpPBM = VSIFOpenL( pszFilename, "wb+" );
+    VSILFILE *fpPBM = VSIFOpenL( pszFilename, "wb+" );
     if( fpPBM == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Unable to create file `%s'.", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Unable to create file `%s'.",
                   pszFilename );
 
         return NULL;
@@ -353,62 +346,76 @@ XPMCreateCopy( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Write the header lines.                                         */
 /* -------------------------------------------------------------------- */
-    VSIFPrintfL( fpPBM, "/* XPM */\n" );
-    VSIFPrintfL( fpPBM, "static char *%s[] = {\n", 
-             CPLGetBasename( pszFilename ) );
-    VSIFPrintfL( fpPBM, "/* width height num_colors chars_per_pixel */\n" );
-    VSIFPrintfL( fpPBM, "\"  %3d   %3d     %3d             1\",\n",
-             nXSize, nYSize, nActiveColors );
-    VSIFPrintfL( fpPBM, "/* colors */\n" );
+    bool bOK = VSIFPrintfL( fpPBM, "/* XPM */\n" ) >= 0;
+    bOK &= VSIFPrintfL( fpPBM, "static char *%s[] = {\n",
+             CPLGetBasename( pszFilename ) ) >= 0;
+    bOK &= VSIFPrintfL( fpPBM, "/* width height num_colors chars_per_pixel */\n" ) >= 0;
+
+    const int nXSize = poSrcDS->GetRasterXSize();
+    const int nYSize = poSrcDS->GetRasterYSize();
+
+    bOK &= VSIFPrintfL( fpPBM, "\"  %3d   %3d     %3d             1\",\n",
+             nXSize, nYSize, nActiveColors ) >= 0;
+
+    bOK &= VSIFPrintfL( fpPBM, "/* colors */\n" ) >= 0;
 
 /* -------------------------------------------------------------------- */
 /*      Write the color table.                                          */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < nActiveColors; i++ )
+    for( int i = 0; bOK && i < nActiveColors; i++ )
     {
         if( asPixelColor[i].c4 < 128 )
-            VSIFPrintfL( fpPBM, "\"%c c None\",\n", pszColorCodes[i] );
+            bOK &= VSIFPrintfL( fpPBM, "\"%c c None\",\n", pszColorCodes[i] ) >= 0;
         else
-            VSIFPrintfL( fpPBM, 
+            bOK &= VSIFPrintfL( fpPBM,
                      "\"%c c #%02x%02x%02x\",\n",
                      pszColorCodes[i],
-                     asPixelColor[i].c1, 
-                     asPixelColor[i].c2, 
-                     asPixelColor[i].c3 );
+                     asPixelColor[i].c1,
+                     asPixelColor[i].c2,
+                     asPixelColor[i].c3 ) >= 0;
     }
 
 /* -------------------------------------------------------------------- */
 /*	Dump image.							*/
 /* -------------------------------------------------------------------- */
-    int iLine;
-    GByte 	*pabyScanline;
+    GByte *pabyScanline = reinterpret_cast<GByte *>( CPLMalloc( nXSize ) );
 
-    pabyScanline = (GByte *) CPLMalloc( nXSize );
-    for( iLine = 0; iLine < nYSize; iLine++ )
+    for( int iLine = 0; bOK && iLine < nYSize; iLine++ )
     {
-        poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, 
-                          (void *) pabyScanline, nXSize, 1, GDT_Byte, 0, 0, NULL );
-        
-        VSIFPutcL( '"', fpPBM );
+        if( poBand->RasterIO(
+               GF_Read, 0, iLine, nXSize, 1,
+               reinterpret_cast<void *>( pabyScanline), nXSize, 1, GDT_Byte,
+               0, 0, NULL ) != CE_None )
+        {
+            CPLFree( pabyScanline );
+            CPL_IGNORE_RET_VAL(VSIFCloseL( fpPBM ));
+            return NULL;
+        }
+
+        bOK &= VSIFPutcL( '"', fpPBM ) >= 0;
         for( int iPixel = 0; iPixel < nXSize; iPixel++ )
-            VSIFPutcL( pszColorCodes[anPixelMapping[pabyScanline[iPixel]]], 
-                   fpPBM);
-        VSIFPrintfL( fpPBM, "\",\n" );
+            bOK &= VSIFPutcL( pszColorCodes[anPixelMapping[pabyScanline[iPixel]]],
+                   fpPBM) >= 0;
+        bOK &= VSIFPrintfL( fpPBM, "\",\n" ) >= 0;
     }
-    
+
     CPLFree( pabyScanline );
 
 /* -------------------------------------------------------------------- */
 /*      cleanup                                                         */
 /* -------------------------------------------------------------------- */
-    VSIFPrintfL( fpPBM, "};\n" );
-    VSIFCloseL( fpPBM );
+    bOK &= VSIFPrintfL( fpPBM, "};\n" ) >= 0;
+    if( VSIFCloseL( fpPBM ) != 0 )
+        bOK = false;
+
+    if( !bOK )
+        return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Re-open dataset, and copy any auxiliary pam information.         */
 /* -------------------------------------------------------------------- */
-    GDALPamDataset *poDS = (GDALPamDataset *)
-        GDALOpen( pszFilename, GA_ReadOnly );
+    GDALPamDataset *poDS = reinterpret_cast<GDALPamDataset *>(
+        GDALOpen( pszFilename, GA_ReadOnly ) );
 
     if( poDS )
         poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
@@ -423,29 +430,25 @@ XPMCreateCopy( const char * pszFilename,
 void GDALRegister_XPM()
 
 {
-    GDALDriver	*poDriver;
+    if( GDALGetDriverByName( "XPM" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "XPM" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "XPM" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "X11 PixMap Format" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#XPM" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "xpm" );
-        poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/x-xpixmap" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
-                                   "Byte" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = XPMDataset::Open;
-        poDriver->pfnCreateCopy = XPMCreateCopy;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "XPM" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "X11 PixMap Format" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#XPM" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "xpm" );
+    poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/x-xpixmap" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = XPMDataset::Open;
+    poDriver->pfnIdentify = XPMDataset::Identify;
+    poDriver->pfnCreateCopy = XPMCreateCopy;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
 
 /************************************************************************/
@@ -455,7 +458,7 @@ void GDALRegister_XPM()
 static unsigned char *
 ParseXPM( const char *pszInput,
           unsigned int nFileSize,
-          int *pnXSize, int *pnYSize, 
+          int *pnXSize, int *pnYSize,
           GDALColorTable **ppoRetTable )
 
 {
@@ -463,12 +466,10 @@ ParseXPM( const char *pszInput,
 /*      Parse input into an array of strings from within the first C    */
 /*      initializer (list os comma separated strings in braces).        */
 /* ==================================================================== */
-    char **papszXPMList = NULL;
     const char *pszNext = pszInput;
-    int  i;
 
     // Skip till after open brace.
-    while( *pszNext != '\0' && *pszNext != '{' ) 
+    while( *pszNext != '\0' && *pszNext != '{' )
         pszNext++;
 
     if( *pszNext == '\0' )
@@ -477,22 +478,23 @@ ParseXPM( const char *pszInput,
     pszNext++;
 
     // Read lines till close brace.
-    
+
+    char **papszXPMList = NULL;
+    int  i = 0;
+
     while( *pszNext != '\0' && *pszNext != '}' )
     {
-        // skip whole comment. 
-        if( EQUALN(pszNext,"/*",2) )
+        // skip whole comment.
+        if( STARTS_WITH_CI(pszNext, "/*") )
         {
             pszNext += 2;
-            while( *pszNext != '\0' && !EQUALN(pszNext,"*/",2) )
+            while( *pszNext != '\0' && !STARTS_WITH_CI(pszNext, "*/") )
                 pszNext++;
         }
 
         // reading string constants
         else if( *pszNext == '"' )
         {
-            char   *pszLine;
-
             pszNext++;
             i = 0;
 
@@ -505,7 +507,7 @@ ParseXPM( const char *pszInput,
                 return NULL;
             }
 
-            pszLine = (char *) CPLMalloc(i+1);
+            char *pszLine = reinterpret_cast<char *>( CPLMalloc(i+1) );
             strncpy( pszLine, pszNext, i );
             pszLine[i] = '\0';
 
@@ -519,18 +521,18 @@ ParseXPM( const char *pszInput,
             pszNext++;
     }
 
-    if( CSLCount(papszXPMList) < 3 || *pszNext != '}' )
+    if( papszXPMList == NULL || CSLCount(papszXPMList) < 3 || *pszNext != '}' )
     {
         CSLDestroy( papszXPMList );
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Get the image information.                                      */
 /* -------------------------------------------------------------------- */
     int nColorCount, nCharsPerPixel;
 
-    if( sscanf( papszXPMList[0], "%d %d %d %d", 
+    if( sscanf( papszXPMList[0], "%d %d %d %d",
                 pnXSize, pnYSize, &nColorCount, &nCharsPerPixel ) != 4 ||
         *pnXSize <= 0 || *pnYSize <= 0 || nColorCount <= 0 || nColorCount > 256 ||
         static_cast<GUIntBig>(*pnXSize) * static_cast<GUIntBig>(*pnYSize) > nFileSize )
@@ -553,32 +555,29 @@ ParseXPM( const char *pszInput,
 /* -------------------------------------------------------------------- */
 /*      Parse out colors.                                               */
 /* -------------------------------------------------------------------- */
-    int iColor;
     int anCharLookup[256];
     GDALColorTable oCTable;
 
-    for( i = 0; i < 256; i++ ) 
+    for( i = 0; i < 256; i++ )
         anCharLookup[i] = -1;
 
-    for( iColor = 0; iColor < nColorCount; iColor++ )
+    for( int iColor = 0; iColor < nColorCount; iColor++ )
     {
         if( papszXPMList[iColor+1] == NULL )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Missing color definition for %d in XPM header.", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Missing color definition for %d in XPM header.",
                       iColor+1 );
             CSLDestroy( papszXPMList );
             return NULL;
         }
 
         char **papszTokens = CSLTokenizeString( papszXPMList[iColor+1]+1 );
-        GDALColorEntry sColor;
-        int            nRed, nGreen, nBlue;
 
         if( CSLCount(papszTokens) != 2 || !EQUAL(papszTokens[0],"c") )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Ill formed color definition (%s) in XPM header.", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Ill formed color definition (%s) in XPM header.",
                       papszXPMList[iColor+1] );
             CSLDestroy( papszXPMList );
             CSLDestroy( papszTokens );
@@ -586,7 +585,10 @@ ParseXPM( const char *pszInput,
         }
 
         anCharLookup[*(reinterpret_cast<GByte*>(papszXPMList[iColor+1]))] = iColor;
-        
+
+        GDALColorEntry sColor;
+        int nRed, nGreen, nBlue;
+
         if( EQUAL(papszTokens[1],"None") )
         {
             sColor.c1 = 0;
@@ -594,11 +596,11 @@ ParseXPM( const char *pszInput,
             sColor.c3 = 0;
             sColor.c4 = 0;
         }
-        else if( sscanf( papszTokens[1], "#%02x%02x%02x", 
+        else if( sscanf( papszTokens[1], "#%02x%02x%02x",
                          &nRed, &nGreen, &nBlue ) != 3 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Ill formed color definition (%s) in XPM header.", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Ill formed color definition (%s) in XPM header.",
                       papszXPMList[iColor+1] );
             CSLDestroy( papszXPMList );
             CSLDestroy( papszTokens );
@@ -606,9 +608,9 @@ ParseXPM( const char *pszInput,
         }
         else
         {
-            sColor.c1 = (short) nRed;
-            sColor.c2 = (short) nGreen;
-            sColor.c3 = (short) nBlue;
+            sColor.c1 = static_cast<short>( nRed );
+            sColor.c2 = static_cast<short>( nGreen );
+            sColor.c3 = static_cast<short>( nBlue );
             sColor.c4 = 255;
         }
 
@@ -620,20 +622,14 @@ ParseXPM( const char *pszInput,
 /* -------------------------------------------------------------------- */
 /*      Prepare image buffer.                                           */
 /* -------------------------------------------------------------------- */
-    GByte *pabyImage;
-
-    pabyImage = (GByte *) VSIMalloc2(*pnXSize, *pnYSize);
+    GByte *pabyImage
+        = reinterpret_cast<GByte *>( VSI_CALLOC_VERBOSE(*pnXSize, *pnYSize) );
     if( pabyImage == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory, 
-                  "Insufficient memory for %dx%d XPM image buffer.", 
-                  *pnXSize, *pnYSize );
         CSLDestroy( papszXPMList );
         return NULL;
     }
 
-    memset( pabyImage, 0, *pnXSize * *pnYSize );
-
 /* -------------------------------------------------------------------- */
 /*      Parse image.                                                    */
 /* -------------------------------------------------------------------- */
@@ -646,7 +642,7 @@ ParseXPM( const char *pszInput,
         {
             CPLFree( pabyImage );
             CSLDestroy( papszXPMList );
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Insufficient imagery lines in XPM image." );
             return NULL;
         }
@@ -658,7 +654,8 @@ ParseXPM( const char *pszInput,
             const int nPixelValue
                 = anCharLookup[pabyInLine[iPixel]];
             if( nPixelValue != -1 )
-                pabyImage[iLine * *pnXSize + iPixel] = (GByte) nPixelValue;
+                pabyImage[iLine * *pnXSize + iPixel]
+                    = static_cast<GByte>( nPixelValue );
         }
     }
 
diff --git a/frmts/xyz/frmt_xyz.html b/frmts/xyz/frmt_xyz.html
index e335183..2040ec2 100644
--- a/frmts/xyz/frmt_xyz.html
+++ b/frmts/xyz/frmt_xyz.html
@@ -9,7 +9,7 @@
 
 (Available for GDAL >= 1.8.0)
 <p>
-GDAL supports reading and writting ASCII <b>gridded</b> XYZ raster datasets (ie.
+GDAL supports reading and writing ASCII <b>gridded</b> XYZ raster datasets (i.e.
 ungridded XYZ, LIDAR XYZ etc. must be opened by other means.
 See the documentation of the <a href="gdal_grid.html">gdal_grid</a> utility).
 <p>
@@ -27,7 +27,7 @@ If no header is present or one of the column could not be identified in the head
 (in that order) are assumed to be the first 3 columns of each line.
 <p>
 The opening of a big dataset can be slow as the driver must scan the whole file to determine
-the dataset size and spatial resolution. The driver will autodetect the data type among 
+the dataset size and spatial resolution. The driver will autodetect the data type among
 Byte, Int16, Int32 or Float32.
 <p>
 
diff --git a/frmts/xyz/xyzdataset.cpp b/frmts/xyz/xyzdataset.cpp
index 896e6be..6acbffc 100644
--- a/frmts/xyz/xyzdataset.cpp
+++ b/frmts/xyz/xyzdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: xyzdataset.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: xyzdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  XYZ driver
  * Purpose:  GDALDataset driver for XYZ dataset.
@@ -27,17 +27,15 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_vsi_virtual.h"
 #include "cpl_string.h"
+#include "cpl_vsi_virtual.h"
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
-#include <vector>
-#include <algorithm>
 
-CPL_CVSID("$Id: xyzdataset.cpp 28053 2014-12-04 09:31:07Z rouault $");
+#include <algorithm>
+#include <vector>
 
-CPL_C_START
-void    GDALRegister_XYZ(void);
-CPL_C_END
+CPL_CVSID("$Id: xyzdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -50,7 +48,7 @@ class XYZRasterBand;
 class XYZDataset : public GDALPamDataset
 {
     friend class XYZRasterBand;
-    
+
     VSILFILE   *fp;
     int         bHasHeaderLine;
     int         nCommentLineCount;
@@ -59,8 +57,8 @@ class XYZDataset : public GDALPamDataset
     int         nYIndex;
     int         nZIndex;
     int         nMinTokens;
-    int         nLineNum;     /* any line */
-    int         nDataLineNum; /* line with values (header line and empty lines ignored) */
+    GIntBig     nLineNum;     /* any line */
+    GIntBig     nDataLineNum; /* line with values (header line and empty lines ignored) */
     double      adfGeoTransform[6];
     int         bSameNumberOfValuesPerLine;
     double      dfMinZ;
@@ -71,13 +69,13 @@ class XYZDataset : public GDALPamDataset
   public:
                  XYZDataset();
     virtual     ~XYZDataset();
-    
+
     virtual CPLErr GetGeoTransform( double * );
-    
+
     static GDALDataset *Open( GDALOpenInfo * );
     static int          Identify( GDALOpenInfo * );
-    static GDALDataset *CreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
-                                    int bStrict, char ** papszOptions, 
+    static GDALDataset *CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
+                                    int bStrict, char ** papszOptions,
                                     GDALProgressFunc pfnProgress, void * pProgressData );
 };
 
@@ -108,18 +106,16 @@ class XYZRasterBand : public GDALPamRasterBand
 /*                           XYZRasterBand()                            */
 /************************************************************************/
 
-XYZRasterBand::XYZRasterBand( XYZDataset *poDS, int nBand, GDALDataType eDT )
-
+XYZRasterBand::XYZRasterBand( XYZDataset *poDSIn, int nBandIn, GDALDataType eDT ) :
+    nLastYOff(-1)
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
     eDataType = eDT;
 
-    nBlockXSize = poDS->GetRasterXSize();
+    nBlockXSize = poDSIn->GetRasterXSize();
     nBlockYSize = 1;
-
-    nLastYOff = -1;
 }
 
 /************************************************************************/
@@ -130,7 +126,7 @@ CPLErr XYZRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                                   int nBlockYOff,
                                   void * pImage )
 {
-    XYZDataset *poGDS = (XYZDataset *) poDS;
+    XYZDataset *poGDS = reinterpret_cast<XYZDataset *>( poDS );
 
     if (poGDS->fp == NULL)
         return CE_Failure;
@@ -146,7 +142,8 @@ CPLErr XYZRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                       nRasterXSize);
     }
 
-    int nLineInFile = nBlockYOff * nBlockXSize; // only valid if bSameNumberOfValuesPerLine
+    // Only valid if bSameNumberOfValuesPerLine.
+    const GIntBig nLineInFile = static_cast<GIntBig>(nBlockYOff) * nBlockXSize;
     if ( (poGDS->bSameNumberOfValuesPerLine && poGDS->nDataLineNum > nLineInFile) ||
          (!poGDS->bSameNumberOfValuesPerLine && (nLastYOff == -1 || nBlockYOff == 0)) )
     {
@@ -162,7 +159,7 @@ CPLErr XYZRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 
         if (poGDS->bHasHeaderLine)
         {
-            const char* pszLine = CPLReadLine2L(poGDS->fp, 100, 0);
+            const char* pszLine = CPLReadLine2L(poGDS->fp, 100, NULL);
             if (pszLine == NULL)
                 return CE_Failure;
             poGDS->nLineNum ++;
@@ -171,11 +168,10 @@ CPLErr XYZRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 
     if( !poGDS->bSameNumberOfValuesPerLine && nBlockYOff != nLastYOff + 1 )
     {
-        int iY;
         if( nBlockYOff < nLastYOff )
         {
             nLastYOff = -1;
-            for(iY = 0; iY < nBlockYOff; iY++)
+            for( int iY = 0; iY < nBlockYOff; iY++ )
             {
                 if( IReadBlock(0, iY, NULL) != CE_None )
                     return CE_Failure;
@@ -183,7 +179,7 @@ CPLErr XYZRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
         }
         else
         {
-            for(iY = nLastYOff + 1; iY < nBlockYOff; iY++)
+            for( int iY = nLastYOff + 1; iY < nBlockYOff; iY++ )
             {
                 if( IReadBlock(0, iY, NULL) != CE_None )
                     return CE_Failure;
@@ -194,7 +190,7 @@ CPLErr XYZRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     {
         while(poGDS->nDataLineNum < nLineInFile)
         {
-            const char* pszLine = CPLReadLine2L(poGDS->fp, 100, 0);
+            const char* pszLine = CPLReadLine2L(poGDS->fp, 100, NULL);
             if (pszLine == NULL)
                 return CE_Failure;
             poGDS->nLineNum ++;
@@ -202,23 +198,23 @@ CPLErr XYZRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
             const char* pszPtr = pszLine;
             char ch;
             int nCol = 0;
-            int bLastWasSep = TRUE;
+            bool bLastWasSep = true;
             while((ch = *pszPtr) != '\0')
             {
                 if (ch == ' ')
                 {
                     if (!bLastWasSep)
                         nCol ++;
-                    bLastWasSep = TRUE;
+                    bLastWasSep = true;
                 }
                 else if ((ch == ',' && poGDS->chDecimalSep != ',') || ch == '\t' || ch == ';')
                 {
                     nCol ++;
-                    bLastWasSep = TRUE;
+                    bLastWasSep = true;
                 }
                 else
                 {
-                    bLastWasSep = FALSE;
+                    bLastWasSep = false;
                 }
                 pszPtr ++;
             }
@@ -231,21 +227,25 @@ CPLErr XYZRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
         }
     }
 
-    double dfExpectedY = poGDS->adfGeoTransform[3] + (0.5 + nBlockYOff) * poGDS->adfGeoTransform[5];
+    const double dfExpectedY
+        = poGDS->adfGeoTransform[3] +
+        (0.5 + nBlockYOff) * poGDS->adfGeoTransform[5];
+
     int idx = -1;
-    while(TRUE)
+    while(true)
     {
         int nCol;
-        int bLastWasSep;
+        bool bLastWasSep;
         do
         {
-            vsi_l_offset nOffsetBefore = VSIFTellL(poGDS->fp);
-            const char* pszLine = CPLReadLine2L(poGDS->fp, 100, 0);
+            const vsi_l_offset nOffsetBefore = VSIFTellL(poGDS->fp);
+            const char* pszLine = CPLReadLine2L(poGDS->fp, 100, NULL);
             if (pszLine == NULL)
             {
                 if( poGDS->bSameNumberOfValuesPerLine )
                 {
-                    CPLError(CE_Failure, CPLE_AppDefined, "Cannot read line %d", poGDS->nLineNum + 1);
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Cannot read line " CPL_FRMT_GIB, poGDS->nLineNum + 1);
                     return CE_Failure;
                 }
                 else
@@ -259,21 +259,22 @@ CPLErr XYZRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
             const char* pszPtr = pszLine;
             char ch;
             nCol = 0;
-            bLastWasSep = TRUE;
+            bLastWasSep = true;
             double dfX = 0.0, dfY = 0.0, dfZ = 0.0;
-            int bUsefulColsFound = 0;
+            int nUsefulColsFound = 0;
             while((ch = *pszPtr) != '\0')
             {
                 if (ch == ' ')
                 {
                     if (!bLastWasSep)
                         nCol ++;
-                    bLastWasSep = TRUE;
+                    bLastWasSep = true;
                 }
-                else if ((ch == ',' && poGDS->chDecimalSep != ',') || ch == '\t' || ch == ';')
+                else if ( ( ch == ',' && poGDS->chDecimalSep != ',' )
+                          || ch == '\t' || ch == ';' )
                 {
                     nCol ++;
-                    bLastWasSep = TRUE;
+                    bLastWasSep = true;
                 }
                 else
                 {
@@ -281,29 +282,29 @@ CPLErr XYZRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                     {
                         if (nCol == poGDS->nXIndex)
                         {
-                            bUsefulColsFound ++;
+                            nUsefulColsFound ++;
                             if( !poGDS->bSameNumberOfValuesPerLine )
                                 dfX = CPLAtofDelim(pszPtr, poGDS->chDecimalSep);
                         }
                         else if (nCol == poGDS->nYIndex)
                         {
-                            bUsefulColsFound ++;
+                            nUsefulColsFound ++;
                             if( !poGDS->bSameNumberOfValuesPerLine )
                                 dfY = CPLAtofDelim(pszPtr, poGDS->chDecimalSep);
                         }
                         else if( nCol == poGDS->nZIndex)
                         {
-                            bUsefulColsFound ++;
+                            nUsefulColsFound ++;
                             dfZ = CPLAtofDelim(pszPtr, poGDS->chDecimalSep);
                         }
                     }
-                    bLastWasSep = FALSE;
+                    bLastWasSep = false;
                 }
                 pszPtr ++;
             }
             nCol ++;
 
-            if( bUsefulColsFound == 3 )
+            if( nUsefulColsFound == 3 )
             {
                 if( poGDS->bSameNumberOfValuesPerLine )
                 {
@@ -315,8 +316,11 @@ CPLErr XYZRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                     {
                         if( idx < 0 )
                         {
-                            CPLError(CE_Failure, CPLE_AppDefined, "At line %d, found %f instead of %f for nBlockYOff = %d",
-                                    poGDS->nLineNum, dfY, dfExpectedY, nBlockYOff);
+                            CPLError( CE_Failure, CPLE_AppDefined,
+                                      "At line " CPL_FRMT_GIB", found %f instead of %f "
+                                      "for nBlockYOff = %d",
+                                      poGDS->nLineNum, dfY, dfExpectedY,
+                                      nBlockYOff);
                             return CE_Failure;
                         }
                         VSIFSeekL(poGDS->fp, nOffsetBefore, SEEK_SET);
@@ -325,7 +329,10 @@ CPLErr XYZRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                         return CE_None;
                     }
 
-                    idx = (int)((dfX - 0.5 * poGDS->adfGeoTransform[1] - poGDS->adfGeoTransform[0]) / poGDS->adfGeoTransform[1] + 0.5);
+                    idx = static_cast<int>(
+                        ( dfX - 0.5 * poGDS->adfGeoTransform[1]
+                          - poGDS->adfGeoTransform[0] )
+                        / poGDS->adfGeoTransform[1] + 0.5 );
                 }
                 CPLAssert(idx >= 0 && idx < nRasterXSize);
 
@@ -333,19 +340,23 @@ CPLErr XYZRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                 {
                     if (eDataType == GDT_Float32)
                     {
-                        ((float*)pImage)[idx] = (float)dfZ;
+                        reinterpret_cast<float *>( pImage )[idx]
+                            = static_cast<float>(dfZ);
                     }
                     else if (eDataType == GDT_Int32)
                     {
-                        ((GInt32*)pImage)[idx] = (GInt32)dfZ;
+                        reinterpret_cast<GInt32 *>( pImage )[idx]
+                            = static_cast<GInt32>( dfZ );
                     }
                     else if (eDataType == GDT_Int16)
                     {
-                        ((GInt16*)pImage)[idx] = (GInt16)dfZ;
+                        reinterpret_cast<GInt16 *>( pImage )[idx]
+                            = static_cast<GInt16>( dfZ );
                     }
                     else
                     {
-                        ((GByte*)pImage)[idx] = (GByte)dfZ;
+                        reinterpret_cast<GByte *>( pImage )[idx]
+                            = static_cast<GByte>( dfZ );
                     }
                 }
             }
@@ -362,7 +373,13 @@ CPLErr XYZRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     }
 
     if( poGDS->bSameNumberOfValuesPerLine ) {
-        CPLAssert(poGDS->nDataLineNum == (nBlockYOff + 1) * nBlockXSize);
+        if( poGDS->nDataLineNum != static_cast<GIntBig>(nBlockYOff + 1) * nBlockXSize )
+        {
+            CPLError(CE_Failure, CPLE_AssertionFailed,
+                     "The file has not the same number of values per "
+                     "line as initialy thought. It must be somehow corrupted");
+            return CE_Failure;
+        }
     }
 
     nLastYOff = nBlockYOff;
@@ -376,8 +393,9 @@ CPLErr XYZRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 
 double XYZRasterBand::GetMinimum(int *pbSuccess)
 {
-    XYZDataset *poGDS = (XYZDataset *) poDS;
-    if( pbSuccess ) *pbSuccess = TRUE;
+    XYZDataset *poGDS = reinterpret_cast<XYZDataset *>( poDS );
+    if( pbSuccess )
+        *pbSuccess = TRUE;
     return poGDS->dfMinZ;
 }
 
@@ -387,8 +405,9 @@ double XYZRasterBand::GetMinimum(int *pbSuccess)
 
 double XYZRasterBand::GetMaximum(int *pbSuccess)
 {
-    XYZDataset *poGDS = (XYZDataset *) poDS;
-    if( pbSuccess ) *pbSuccess = TRUE;
+    XYZDataset *poGDS = reinterpret_cast<XYZDataset *>( poDS );
+    if( pbSuccess )
+        *pbSuccess = TRUE;
     return poGDS->dfMaxZ;
 }
 
@@ -398,19 +417,20 @@ double XYZRasterBand::GetMaximum(int *pbSuccess)
 
 double XYZRasterBand::GetNoDataValue(int *pbSuccess)
 {
-    XYZDataset *poGDS = (XYZDataset *) poDS;
-    if( !poGDS->bSameNumberOfValuesPerLine && 
+    XYZDataset *poGDS = reinterpret_cast<XYZDataset *>( poDS );
+    if( !poGDS->bSameNumberOfValuesPerLine &&
         poGDS->dfMinZ > -32768 && eDataType != GDT_Byte )
     {
         if( pbSuccess ) *pbSuccess = TRUE;
         return (poGDS->dfMinZ > 0) ? 0 : -32768;
     }
-    else if ( !poGDS->bSameNumberOfValuesPerLine && 
+    else if ( !poGDS->bSameNumberOfValuesPerLine &&
               poGDS->dfMinZ > 0 && eDataType == GDT_Byte )
     {
         if( pbSuccess ) *pbSuccess = TRUE;
         return 0;
     }
+
     return GDALPamRasterBand::GetNoDataValue(pbSuccess);
 }
 
@@ -418,27 +438,27 @@ double XYZRasterBand::GetNoDataValue(int *pbSuccess)
 /*                            ~XYZDataset()                            */
 /************************************************************************/
 
-XYZDataset::XYZDataset()
+XYZDataset::XYZDataset() :
+    fp(NULL),
+    bHasHeaderLine(FALSE),
+    nCommentLineCount(0),
+    chDecimalSep('.'),
+    nXIndex(-1),
+    nYIndex(-1),
+    nZIndex(-1),
+    nMinTokens(0),
+    nLineNum(0),
+    nDataLineNum(((GIntBig)0x7FFFFFFF) << 32 | 0xFFFFFFFF),
+    bSameNumberOfValuesPerLine(TRUE),
+    dfMinZ(0),
+    dfMaxZ(0)
 {
-    fp = NULL;
-    nDataLineNum = INT_MAX;
-    nLineNum = 0;
-    nCommentLineCount = 0;
-    chDecimalSep = '.';
-    bHasHeaderLine = FALSE;
-    nXIndex = -1;
-    nYIndex = -1;
-    nZIndex = -1;
-    nMinTokens = 0;
     adfGeoTransform[0] = 0;
     adfGeoTransform[1] = 1;
     adfGeoTransform[2] = 0;
     adfGeoTransform[3] = 0;
     adfGeoTransform[4] = 0;
     adfGeoTransform[5] = 1;
-    bSameNumberOfValuesPerLine = TRUE;
-    dfMinZ = 0;
-    dfMaxZ = 0;
 }
 
 /************************************************************************/
@@ -473,8 +493,6 @@ int XYZDataset::IdentifyEx( GDALOpenInfo * poOpenInfo,
                             int& nCommentLineCount)
 
 {
-    int         i;
-
     bHasHeaderLine = FALSE;
     nCommentLineCount = 0;
 
@@ -485,7 +503,7 @@ int XYZDataset::IdentifyEx( GDALOpenInfo * poOpenInfo,
     /*  if the /vsigzip/ has not been explicitly passed */
     if (strlen(poOpenInfo->pszFilename) > 6 &&
         EQUAL(poOpenInfo->pszFilename + strlen(poOpenInfo->pszFilename) - 6, "xyz.gz") &&
-        !EQUALN(poOpenInfo->pszFilename, "/vsigzip/", 9))
+        !STARTS_WITH_CI(poOpenInfo->pszFilename, "/vsigzip/"))
     {
         osFilename = "/vsigzip/";
         osFilename += poOpenInfo->pszFilename;
@@ -503,19 +521,20 @@ int XYZDataset::IdentifyEx( GDALOpenInfo * poOpenInfo,
 /* -------------------------------------------------------------------- */
 /*      Chech that it looks roughly as a XYZ dataset                    */
 /* -------------------------------------------------------------------- */
-    const char* pszData = (const char*)poOpenInfo->pabyHeader;
+    const char* pszData
+        = reinterpret_cast<const char *>( poOpenInfo->pabyHeader );
 
     /* Skip comments line at the beginning such as in */
     /* http://pubs.usgs.gov/of/2003/ofr-03-230/DATA/NSLCU.XYZ */
-    i=0;
+    int i = 0;
     if (pszData[i] == '/')
     {
         nCommentLineCount ++;
 
         i++;
-        for(;i<poOpenInfo->nHeaderBytes;i++)
+        for( ; i < poOpenInfo->nHeaderBytes; i++)
         {
-            char ch = pszData[i];
+            const char ch = pszData[i];
             if (ch == 13 || ch == 10)
             {
                 if (ch == 13 && pszData[i+1] == 10)
@@ -531,9 +550,9 @@ int XYZDataset::IdentifyEx( GDALOpenInfo * poOpenInfo,
         }
     }
 
-    for(;i<poOpenInfo->nHeaderBytes;i++)
+    for( ; i < poOpenInfo->nHeaderBytes; i++ )
     {
-        char ch = pszData[i];
+        const char ch = pszData[i];
         if (ch == 13 || ch == 10)
         {
             break;
@@ -552,8 +571,8 @@ int XYZDataset::IdentifyEx( GDALOpenInfo * poOpenInfo,
             return FALSE;
         }
     }
-    int bHasFoundNewLine = FALSE;
-    int bPrevWasSep = TRUE;
+    bool bHasFoundNewLine = false;
+    bool bPrevWasSep = true;
     int nCols = 0;
     int nMaxCols = 0;
     for(;i<poOpenInfo->nHeaderBytes;i++)
@@ -561,14 +580,14 @@ int XYZDataset::IdentifyEx( GDALOpenInfo * poOpenInfo,
         char ch = pszData[i];
         if (ch == 13 || ch == 10)
         {
-            bHasFoundNewLine = TRUE;
+            bHasFoundNewLine = true;
             if (!bPrevWasSep)
             {
                 nCols ++;
                 if (nCols > nMaxCols)
                     nMaxCols = nCols;
             }
-            bPrevWasSep = TRUE;
+            bPrevWasSep = true;
             nCols = 0;
         }
         else if (ch == ' ' || ch == ',' || ch == '\t' || ch == ';')
@@ -579,12 +598,12 @@ int XYZDataset::IdentifyEx( GDALOpenInfo * poOpenInfo,
                 if (nCols > nMaxCols)
                     nMaxCols = nCols;
             }
-            bPrevWasSep = TRUE;
+            bPrevWasSep = true;
         }
         else if ((ch >= '0' && ch <= '9') || ch == '.' || ch == '+' ||
                  ch == '-' || ch == 'e' || ch == 'E')
         {
-            bPrevWasSep = FALSE;
+            bPrevWasSep = false;
         }
         else
         {
@@ -604,7 +623,6 @@ int XYZDataset::IdentifyEx( GDALOpenInfo * poOpenInfo,
 GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    int         i;
     int         bHasHeaderLine;
     int         nCommentLineCount = 0;
 
@@ -617,7 +635,7 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
     /*  if the /vsigzip/ has not been explicitly passed */
     if (strlen(poOpenInfo->pszFilename) > 6 &&
         EQUAL(poOpenInfo->pszFilename + strlen(poOpenInfo->pszFilename) - 6, "xyz.gz") &&
-        !EQUALN(poOpenInfo->pszFilename, "/vsigzip/", 9))
+        !STARTS_WITH_CI(poOpenInfo->pszFilename, "/vsigzip/"))
     {
         osFilename = "/vsigzip/";
         osFilename += poOpenInfo->pszFilename;
@@ -632,14 +650,15 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
 
     /* For better performance of CPLReadLine2L() we create a buffered reader */
     /* (except for /vsigzip/ since it has one internally) */
-    if (!EQUALN(poOpenInfo->pszFilename, "/vsigzip/", 9))
-        fp = (VSILFILE*) VSICreateBufferedReaderHandle((VSIVirtualHandle*)fp);
-    
-    const char* pszLine;
+    if (!STARTS_WITH_CI(poOpenInfo->pszFilename, "/vsigzip/"))
+        fp = reinterpret_cast<VSILFILE *>(
+            VSICreateBufferedReaderHandle(
+                reinterpret_cast<VSIVirtualHandle *>( fp ) ) );
+
     int nXIndex = -1, nYIndex = -1, nZIndex = -1;
     int nMinTokens = 0;
 
-    for(i=0;i<nCommentLineCount;i++)
+    for( int i = 0; i < nCommentLineCount; i++ )
         CPLReadLine2L(fp, 100, NULL);
 
 /* -------------------------------------------------------------------- */
@@ -647,7 +666,7 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if (bHasHeaderLine)
     {
-        pszLine = CPLReadLine2L(fp, 100, NULL);
+        const char* pszLine = CPLReadLine2L(fp, 100, NULL);
         if (pszLine == NULL)
         {
             VSIFCloseL(fp);
@@ -665,19 +684,18 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
             VSIFCloseL(fp);
             return NULL;
         }
-        int i;
-        for(i=0;i<nTokens;i++)
+        for( int i = 0; i < nTokens; i++ )
         {
             if (EQUAL(papszTokens[i], "x") ||
-                EQUALN(papszTokens[i], "lon", 3) ||
-                EQUALN(papszTokens[i], "east", 4))
+                STARTS_WITH_CI(papszTokens[i], "lon") ||
+                STARTS_WITH_CI(papszTokens[i], "east"))
                 nXIndex = i;
             else if (EQUAL(papszTokens[i], "y") ||
-                     EQUALN(papszTokens[i], "lat", 3) ||
-                     EQUALN(papszTokens[i], "north", 5))
+                     STARTS_WITH_CI(papszTokens[i], "lat") ||
+                     STARTS_WITH_CI(papszTokens[i], "north"))
                 nYIndex = i;
             else if (EQUAL(papszTokens[i], "z") ||
-                     EQUALN(papszTokens[i], "alt", 3) ||
+                     STARTS_WITH_CI(papszTokens[i], "alt") ||
                      EQUAL(papszTokens[i], "height"))
                 nZIndex = i;
         }
@@ -700,22 +718,24 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
         nZIndex = 2;
         nMinTokens = 3;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Parse data lines                                                */
 /* -------------------------------------------------------------------- */
 
-    int nLineNum = 0;
-    int nDataLineNum = 0;
+    GIntBig nLineNum = 0;
+    GIntBig nDataLineNum = 0;
     double dfX = 0, dfY = 0, dfZ = 0;
     double dfMinX = 0, dfMinY = 0, dfMaxX = 0, dfMaxY = 0;
     double dfMinZ = 0, dfMaxZ = 0;
     double dfLastX = 0, dfLastY = 0;
     std::vector<double> adfStepX, adfStepY;
     GDALDataType eDT = GDT_Byte;
-    int bSameNumberOfValuesPerLine = TRUE;
+    bool bSameNumberOfValuesPerLine = true;
     char chDecimalSep = '\0';
     int bStepYSign = 0;
+
+    const char* pszLine;
     while((pszLine = CPLReadLine2L(fp, 100, NULL)) != NULL)
     {
         nLineNum ++;
@@ -723,7 +743,7 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
         const char* pszPtr = pszLine;
         char ch;
         int nCol = 0;
-        int bLastWasSep = TRUE;
+        bool bLastWasSep = true;
         if( chDecimalSep == '\0' )
         {
             int nCountComma = 0;
@@ -738,21 +758,21 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
                 else if( ch == ',' )
                 {
                     nCountComma ++;
-                    bLastWasSep = FALSE;
+                    bLastWasSep = false;
                 }
                 else if( ch == ' ' )
                 {
                     if (!bLastWasSep)
                         nCountFieldSep ++;
-                    bLastWasSep = TRUE;
+                    bLastWasSep = true;
                 }
                 else if( ch == '\t' || ch == ';' )
                 {
                     nCountFieldSep ++;
-                    bLastWasSep = TRUE;
+                    bLastWasSep = true;
                 }
                 else
-                    bLastWasSep = FALSE;
+                    bLastWasSep = false;
                 pszPtr ++;
             }
             if( chDecimalSep == '\0' )
@@ -765,7 +785,7 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
                     chDecimalSep = ',';
             }
             pszPtr = pszLine;
-            bLastWasSep = TRUE;
+            bLastWasSep = true;
         }
 
         char chLocalDecimalSep = chDecimalSep ? chDecimalSep : '.';
@@ -775,12 +795,12 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
             {
                 if (!bLastWasSep)
                     nCol ++;
-                bLastWasSep = TRUE;
+                bLastWasSep = true;
             }
             else if ((ch == ',' && chLocalDecimalSep != ',') || ch == '\t' || ch == ';')
             {
                 nCol ++;
-                bLastWasSep = TRUE;
+                bLastWasSep = true;
             }
             else
             {
@@ -799,21 +819,29 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
                             dfMinZ = dfZ;
                         else if( dfZ > dfMaxZ )
                             dfMaxZ = dfZ;
-                        int nZ = (int)dfZ;
-                        if ((double)nZ != dfZ)
+                        if( dfZ < INT_MIN || dfZ > INT_MAX )
                         {
                             eDT = GDT_Float32;
                         }
-                        else if ((eDT == GDT_Byte || eDT == GDT_Int16) && (nZ < 0 || nZ > 255))
+                        else
                         {
-                            if (nZ < -32768 || nZ > 32767)
-                                eDT = GDT_Int32;
-                            else
-                                eDT = GDT_Int16;
+                            int nZ = static_cast<int>( dfZ );
+                            if( static_cast<double>( nZ ) != dfZ )
+                            {
+                                eDT = GDT_Float32;
+                            }
+                            else if ((eDT == GDT_Byte || eDT == GDT_Int16)
+                                     && (nZ < 0 || nZ > 255))
+                            {
+                                if (nZ < -32768 || nZ > 32767)
+                                    eDT = GDT_Int32;
+                                else
+                                    eDT = GDT_Int16;
+                            }
                         }
                     }
                 }
-                bLastWasSep = FALSE;
+                bLastWasSep = false;
             }
             pszPtr ++;
         }
@@ -827,7 +855,7 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
         if (nCol < nMinTokens)
         {
             CPLError(CE_Failure, CPLE_AppDefined,
-                     "At line %d, found %d tokens. Expected %d at least",
+                     "At line " CPL_FRMT_GIB ", found %d tokens. Expected %d at least",
                       nLineNum, nCol, nMinTokens);
             VSIFCloseL(fp);
             return NULL;
@@ -847,14 +875,15 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
                 if( dfStepX <= 0 )
                 {
                     CPLError(CE_Failure, CPLE_AppDefined,
-                         "Ungridded dataset: At line %d, X spacing was %f. Expected >0 value",
+                         "Ungridded dataset: At line " CPL_FRMT_GIB ", X spacing was %f. Expected >0 value",
                          nLineNum, dfStepX);
                     VSIFCloseL(fp);
                     return NULL;
                 }
                 if( std::find(adfStepX.begin(), adfStepX.end(), dfStepX) == adfStepX.end() )
                 {
-                    int bAddNewValue = TRUE;
+                    bool bAddNewValue = true;
+                    // TODO: Danger!  Erase called on the iterator.
                     std::vector<double>::iterator oIter = adfStepX.begin();
                     while( oIter != adfStepX.end() )
                     {
@@ -864,7 +893,7 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
                         }
                         else if( dfStepX > *oIter && fmod( dfStepX, *oIter ) < 1e-8 )
                         {
-                            bAddNewValue = FALSE;
+                            bAddNewValue = false;
                             break;
                         }
                         else
@@ -893,7 +922,7 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
                 else if( bStepYSign != bNewStepYSign )
                 {
                     CPLError(CE_Failure, CPLE_AppDefined,
-                         "Ungridded dataset: At line %d, change of Y direction",
+                         "Ungridded dataset: At line " CPL_FRMT_GIB ", change of Y direction",
                          nLineNum);
                     VSIFCloseL(fp);
                     return NULL;
@@ -904,7 +933,7 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
                 else if( adfStepY[0] != dfStepY )
                 {
                     CPLError(CE_Failure, CPLE_AppDefined,
-                        "Ungridded dataset: At line %d, too many stepY values", nLineNum);
+                        "Ungridded dataset: At line " CPL_FRMT_GIB ", too many stepY values", nLineNum);
                     VSIFCloseL(fp);
                     return NULL;
                 }
@@ -934,22 +963,32 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    double dfStepX = adfStepX[0];
-    double dfStepY = adfStepY[0] * bStepYSign;
-    int nXSize = 1 + int((dfMaxX - dfMinX) / dfStepX + 0.5);
-    int nYSize = 1 + int((dfMaxY - dfMinY) / fabs(dfStepY) + 0.5);
+    const double dfStepX = adfStepX[0];
+    const double dfStepY = adfStepY[0] * bStepYSign;
+    const double dfXSize = 1 + ((dfMaxX - dfMinX) / dfStepX + 0.5);
+    const double dfYSize = 1 + ((dfMaxY - dfMinY) / fabs(dfStepY) + 0.5);
+    if( dfXSize <= 0 || dfXSize > INT_MAX || dfYSize <= 0 || dfYSize > INT_MAX )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Invalid dimensions");
+        VSIFCloseL(fp);
+        return NULL;
+    }
+    const int nXSize = static_cast<int>(dfXSize);
+    const int nYSize = static_cast<int>(dfYSize);
 
-    //CPLDebug("XYZ", "minx=%f maxx=%f stepx=%f", dfMinX, dfMaxX, dfStepX);
-    //CPLDebug("XYZ", "miny=%f maxy=%f stepy=%f", dfMinY, dfMaxY, dfStepY);
+#ifdef DEBUG_VERBOSE
+    CPLDebug("XYZ", "minx=%f maxx=%f stepx=%f", dfMinX, dfMaxX, dfStepX);
+    CPLDebug("XYZ", "miny=%f maxy=%f stepy=%f", dfMinY, dfMaxY, dfStepY);
+#endif
 
-    if (nDataLineNum != nXSize * nYSize)
+    if (nDataLineNum != static_cast<GIntBig>(nXSize) * nYSize)
     {
-        bSameNumberOfValuesPerLine = FALSE;
+        bSameNumberOfValuesPerLine = false;
     }
-    
+
     if (poOpenInfo->eAccess == GA_Update)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The XYZ driver does not support update access to existing"
                   " datasets.\n" );
         VSIFCloseL(fp);
@@ -959,9 +998,7 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    XYZDataset         *poDS;
-
-    poDS = new XYZDataset();
+    XYZDataset *poDS = new XYZDataset();
     poDS->fp = fp;
     poDS->bHasHeaderLine = bHasHeaderLine;
     poDS->nCommentLineCount = nCommentLineCount;
@@ -980,7 +1017,10 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->bSameNumberOfValuesPerLine = bSameNumberOfValuesPerLine;
     poDS->dfMinZ = dfMinZ;
     poDS->dfMaxZ = dfMaxZ;
-    //CPLDebug("XYZ", "bSameNumberOfValuesPerLine = %d", bSameNumberOfValuesPerLine);
+#ifdef DEBUG_VERBOSE
+    CPLDebug( "XYZ", "bSameNumberOfValuesPerLine = %d",
+              bSameNumberOfValuesPerLine );
+#endif
 
     if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
     {
@@ -992,7 +1032,7 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
     poDS->nBands = 1;
-    for( i = 0; i < poDS->nBands; i++ )
+    for( int i = 0; i < poDS->nBands; i++ )
         poDS->SetBand( i+1, new XYZRasterBand( poDS, i+1, eDT ) );
 
 /* -------------------------------------------------------------------- */
@@ -1013,8 +1053,8 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
 /************************************************************************/
 
 GDALDataset* XYZDataset::CreateCopy( const char * pszFilename,
-                                     GDALDataset *poSrcDS, 
-                                     int bStrict, char ** papszOptions, 
+                                     GDALDataset *poSrcDS,
+                                     int bStrict, char ** papszOptions,
                                      GDALProgressFunc pfnProgress,
                                      void * pProgressData )
 {
@@ -1024,14 +1064,14 @@ GDALDataset* XYZDataset::CreateCopy( const char * pszFilename,
     int nBands = poSrcDS->GetRasterCount();
     if (nBands == 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "XYZ driver does not support source dataset with zero band.\n");
         return NULL;
     }
 
     if (nBands != 1)
     {
-        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, 
+        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
                   "XYZ driver only uses the first band of the dataset.\n");
         if (bStrict)
             return NULL;
@@ -1050,12 +1090,12 @@ GDALDataset* XYZDataset::CreateCopy( const char * pszFilename,
     poSrcDS->GetGeoTransform(adfGeoTransform);
     if (adfGeoTransform[2] != 0 || adfGeoTransform[4] != 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "XYZ driver does not support CreateCopy() from skewed or rotated dataset.\n");
         return NULL;
     }
 
-    GDALDataType eSrcDT = poSrcDS->GetRasterBand(1)->GetRasterDataType();
+    const GDALDataType eSrcDT = poSrcDS->GetRasterBand(1)->GetRasterDataType();
     GDALDataType eReqDT;
     if (eSrcDT == GDT_Byte || eSrcDT == GDT_Int16 ||
         eSrcDT == GDT_UInt16 || eSrcDT == GDT_Int32)
@@ -1070,7 +1110,7 @@ GDALDataset* XYZDataset::CreateCopy( const char * pszFilename,
     VSILFILE* fp = VSIFOpenL(pszFilename, "wb");
     if (fp == NULL)
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Cannot create %s", pszFilename );
         return NULL;
     }
@@ -1090,10 +1130,15 @@ GDALDataset* XYZDataset::CreateCopy( const char * pszFilename,
         pszColSep = ";";
     else if (EQUAL(pszColSep, "\\t") || EQUAL(pszColSep, "TAB"))
         pszColSep = "\t";
+#ifdef DEBUG_VERBOSE
+    else
+        CPLDebug("XYZ", "Using raw column separator: '%s' ",
+                 pszColSep);
+#endif
 
     const char* pszAddHeaderLine =
             CSLFetchNameValue(papszOptions, "ADD_HEADER_LINE");
-    if (pszAddHeaderLine != NULL && CSLTestBoolean(pszAddHeaderLine))
+    if (pszAddHeaderLine != NULL && CPLTestBool(pszAddHeaderLine))
     {
         VSIFPrintfL(fp, "X%sY%sZ\n", pszColSep, pszColSep);
     }
@@ -1101,10 +1146,10 @@ GDALDataset* XYZDataset::CreateCopy( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Copy imagery                                                    */
 /* -------------------------------------------------------------------- */
-    void* pLineBuffer = (void*) CPLMalloc(nXSize * sizeof(int));
-    int i, j;
+    void* pLineBuffer
+        = reinterpret_cast<void *>( CPLMalloc( nXSize * sizeof(int) ) );
     CPLErr eErr = CE_None;
-    for(j=0;j<nYSize && eErr == CE_None;j++)
+    for( int j=0; j < nYSize && eErr == CE_None; j++ )
     {
         eErr = poSrcDS->GetRasterBand(1)->RasterIO(
                                             GF_Read, 0, j, nXSize, 1,
@@ -1112,30 +1157,38 @@ GDALDataset* XYZDataset::CreateCopy( const char * pszFilename,
                                             eReqDT, 0, 0, NULL);
         if (eErr != CE_None)
             break;
-        double dfY = adfGeoTransform[3] + (j + 0.5) * adfGeoTransform[5];
+        const double dfY = adfGeoTransform[3] + (j + 0.5) * adfGeoTransform[5];
         CPLString osBuf;
-        for(i=0;i<nXSize;i++)
+        for( int i = 0; i < nXSize; i++ )
         {
+            const double dfX
+                = adfGeoTransform[0] + (i + 0.5) * adfGeoTransform[1];
             char szBuf[256];
-            double dfX = adfGeoTransform[0] + (i + 0.5) * adfGeoTransform[1];
             if (eReqDT == GDT_Int32)
-                CPLsprintf(szBuf, "%.18g%c%.18g%c%d\n", dfX, pszColSep[0], dfY, pszColSep[0], ((int*)pLineBuffer)[i]);
+                CPLsnprintf(szBuf, sizeof(szBuf), "%.18g%c%.18g%c%d\n",
+                            dfX, pszColSep[0], dfY, pszColSep[0],
+                            reinterpret_cast<int *>( pLineBuffer )[i] );
             else
-                CPLsprintf(szBuf, "%.18g%c%.18g%c%.18g\n", dfX, pszColSep[0], dfY, pszColSep[0], ((float*)pLineBuffer)[i]);
+                CPLsnprintf(szBuf, sizeof(szBuf), "%.18g%c%.18g%c%.18g\n",
+                            dfX, pszColSep[0], dfY, pszColSep[0],
+                            reinterpret_cast<float *>( pLineBuffer )[i]);
             osBuf += szBuf;
             if( (i & 1023) == 0 || i == nXSize - 1 )
             {
-                if ( VSIFWriteL( osBuf, (int)osBuf.size(), 1, fp ) != 1 )
+                if ( VSIFWriteL( osBuf,
+                                 static_cast<int>( osBuf.size() ), 1, fp )
+                     != 1 )
                 {
                     eErr = CE_Failure;
-                    CPLError( CE_Failure, CPLE_AppDefined, 
+                    CPLError( CE_Failure, CPLE_AppDefined,
                               "Write failed, disk full?\n" );
                     break;
                 }
                 osBuf = "";
             }
         }
-        if (!pfnProgress( (j+1) * 1.0 / nYSize, NULL, pProgressData))
+        if ( pfnProgress
+             && !pfnProgress( (j+1) * 1.0 / nYSize, NULL, pProgressData ) )
         {
             eErr = CE_Failure;
             break;
@@ -1143,7 +1196,7 @@ GDALDataset* XYZDataset::CreateCopy( const char * pszFilename,
     }
     CPLFree(pLineBuffer);
     VSIFCloseL(fp);
-    
+
     if (eErr != CE_None)
         return NULL;
 
@@ -1156,7 +1209,7 @@ GDALDataset* XYZDataset::CreateCopy( const char * pszFilename,
     poXYZ_DS->nRasterYSize = nYSize;
     poXYZ_DS->nBands = 1;
     poXYZ_DS->SetBand( 1, new XYZRasterBand( poXYZ_DS, 1, eReqDT ) );
-    /* If outputing to stdout, we can't reopen it --> silence warning */
+    /* If writing to stdout, we can't reopen it --> silence warning */
     CPLPushErrorHandler(CPLQuietErrorHandler);
     poXYZ_DS->fp = VSIFOpenL( pszFilename, "rb" );
     CPLPopErrorHandler();
@@ -1192,31 +1245,27 @@ CPLErr XYZDataset::GetGeoTransform( double * padfTransform )
 void GDALRegister_XYZ()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "XYZ" ) != NULL )
+      return;
 
-    if( GDALGetDriverByName( "XYZ" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "XYZ" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "ASCII Gridded XYZ" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_xyz.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "xyz" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "XYZ" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "ASCII Gridded XYZ" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_xyz.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "xyz" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "   <Option name='COLUMN_SEPARATOR' type='string' default=' ' description='Separator between fields.'/>"
 "   <Option name='ADD_HEADER_LINE' type='boolean' default='false' description='Add an header line with column names.'/>"
 "</CreationOptionList>");
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = XYZDataset::Open;
-        poDriver->pfnIdentify = XYZDataset::Identify;
-        poDriver->pfnCreateCopy = XYZDataset::CreateCopy;
+    poDriver->pfnOpen = XYZDataset::Open;
+    poDriver->pfnIdentify = XYZDataset::Identify;
+    poDriver->pfnCreateCopy = XYZDataset::CreateCopy;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/zlib/GNUmakefile b/frmts/zlib/GNUmakefile
index 954db57..d66b3c5 100644
--- a/frmts/zlib/GNUmakefile
+++ b/frmts/zlib/GNUmakefile
@@ -1,4 +1,4 @@
-# $Id: GNUmakefile 15888 2008-12-03 08:22:31Z dron $
+# $Id: GNUmakefile 32078 2015-12-08 09:09:45Z rouault $
 #
 # Makefile to build zlib using GNU Make and GCC.
 #
@@ -18,6 +18,8 @@ OBJ = \
 	uncompr.o \
 	zutil.o
 
+CPPFLAGS	:=	$(CPPFLAGS) -DDONT_DEPRECATE_SPRINTF
+
 default:	$(OBJ:.o=.$(OBJ_EXT))
 
 clean:
diff --git a/frmts/zlib/README b/frmts/zlib/README
index 3b8b372..1ae6df7 100644
--- a/frmts/zlib/README
+++ b/frmts/zlib/README
@@ -1,4 +1,4 @@
-$Id: README 10656 2007-01-19 01:31:01Z mloskot $
+$Id: README 31826 2015-11-29 15:39:57Z goatbar $
 
 zlib 1.2.3 is a general purpose data compression library.
 All the code is thread safe. The data format used by the zlib library
@@ -67,7 +67,7 @@ is available in Python 1.5 and later versions, see
 http://www.python.org/doc/lib/module-zlib.html
 
 A zlib binding for TCL written by Andreas Kupries <a.kupries at westend.com>
-is availlable at http://www.westend.com/~kupries/doc/trf/man/man.html
+is available at http://www.westend.com/~kupries/doc/trf/man/man.html
 
 An experimental package to read and write files in .zip format,
 written on top of zlib by Gilles Vollant <info at winimage.com>, is
@@ -95,7 +95,7 @@ Notes for some targets:
 - zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1   
   it works when compiled with cc.
 
-- on Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1
+- on Digital Unix 4.0D (formerly OSF/1) on AlphaServer, the cc option -std1
   is necessary to get gzprintf working correctly. This is done by configure.
 
 - zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works
diff --git a/frmts/zlib/adler32.c b/frmts/zlib/adler32.c
index ffccbe4..6975836 100644
--- a/frmts/zlib/adler32.c
+++ b/frmts/zlib/adler32.c
@@ -3,7 +3,7 @@
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
-/* @(#) $Id: adler32.c 10656 2007-01-19 01:31:01Z mloskot $ */
+/* @(#) $Id: adler32.c 31978 2015-12-03 16:02:10Z goatbar $ */
 
 #define ZLIB_INTERNAL
 #include "zlib.h"
@@ -106,7 +106,7 @@ uLong ZEXPORT adler32(adler, buf, len)
     }
 
     /* do remaining bytes (less than NMAX, still just one modulo) */
-    if (len) {                  /* avoid modulos if none remaining */
+    if (len) {                  /* avoid modulo if none remaining */
         while (len >= 16) {
             len -= 16;
             DO16(buf);
diff --git a/frmts/zlib/gzio.c b/frmts/zlib/gzio.c
index 37afda4..eba1ff9 100644
--- a/frmts/zlib/gzio.c
+++ b/frmts/zlib/gzio.c
@@ -5,7 +5,7 @@
  * Compile this file with -DNO_GZCOMPRESS to avoid the compression code.
  */
 
-/* @(#) $Id: gzio.c 10656 2007-01-19 01:31:01Z mloskot $ */
+/* @(#) $Id: gzio.c 32092 2015-12-08 14:54:56Z goatbar $ */
 
 #include <stdio.h>
 
@@ -256,7 +256,7 @@ int ZEXPORT gzsetparams (file, level, strategy)
 /* ===========================================================================
      Read a byte from a gz_stream; update next_in and avail_in. Return EOF
    for end of file.
-   IN assertion: the stream s has been sucessfully opened for reading.
+   IN assertion: the stream s has been successfully opened for reading.
 */
 local int get_byte(s)
     gz_stream *s;
@@ -281,7 +281,7 @@ local int get_byte(s)
     mode to transparent if the gzip magic header is not present; set s->err
     to Z_DATA_ERROR if the magic header is present but the rest of the header
     is incorrect.
-    IN assertion: the stream s has already been created sucessfully;
+    IN assertion: the stream s has already been created successfully;
        s->stream.avail_in is zero for the first time, but may be non-zero
        for concatenated .gz files.
 */
diff --git a/frmts/zlib/zconf.h b/frmts/zlib/zconf.h
index 7164db0..59af028 100644
--- a/frmts/zlib/zconf.h
+++ b/frmts/zlib/zconf.h
@@ -3,7 +3,7 @@
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
-/* @(#) $Id: zconf.h 10656 2007-01-19 01:31:01Z mloskot $ */
+/* @(#) $Id: zconf.h 30901 2015-10-08 04:18:30Z goatbar $ */
 
 #ifndef ZCONF_H
 #define ZCONF_H
@@ -68,7 +68,7 @@
 #if defined(_WINDOWS) && !defined(WINDOWS)
 #  define WINDOWS
 #endif
-#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+#if defined(_WIN32) || defined(__WIN32__)
 #  ifndef WIN32
 #    define WIN32
 #  endif
diff --git a/frmts/zlib/zlib.h b/frmts/zlib/zlib.h
index 6c5f03e..93c8579 100644
--- a/frmts/zlib/zlib.h
+++ b/frmts/zlib/zlib.h
@@ -270,7 +270,7 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
   output buffer because there might be more output pending.
 
     Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
-  decide how much data to accumualte before producing output, in order to
+  decide how much data to accumulate before producing output, in order to
   maximize compression.
 
     If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
@@ -1286,8 +1286,8 @@ ZEXTERN uLong ZEXPORT crc32   OF((uLong crc, const Bytef *buf, uInt len));
 /*
      Update a running CRC-32 with the bytes buf[0..len-1] and return the
    updated CRC-32. If buf is NULL, this function returns the required initial
-   value for the for the crc. Pre- and post-conditioning (one's complement) is
-   performed within this function so it shouldn't be done by the application.
+   value for the for the CRC. Pre- and post-conditioning (one's complement) is
+   performed within this function so it should not be done by the application.
    Usage example:
 
      uLong crc = crc32(0L, Z_NULL, 0);
diff --git a/frmts/zlib/zutil.c b/frmts/zlib/zutil.c
index 72f6364..b611f1a 100644
--- a/frmts/zlib/zutil.c
+++ b/frmts/zlib/zutil.c
@@ -3,7 +3,7 @@
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
-/* @(#) $Id: zutil.c 10656 2007-01-19 01:31:01Z mloskot $ */
+/* @(#) $Id: zutil.c 30901 2015-10-08 04:18:30Z goatbar $ */
 
 #include "zutil.h"
 
@@ -136,14 +136,6 @@ const char * ZEXPORT zError(err)
     return ERR_MSG(err);
 }
 
-#if defined(_WIN32_WCE)
-    /* The Microsoft C Run-Time Library for Windows CE doesn't have
-     * errno.  We define it as a global variable to simplify porting.
-     * Its value is always 0 and should not be used.
-     */
-    int errno = 0;
-#endif
-
 #ifndef HAVE_MEMCPY
 
 void zmemcpy(dest, source, len)
diff --git a/frmts/zlib/zutil.h b/frmts/zlib/zutil.h
index eacad9e..2f1af16 100644
--- a/frmts/zlib/zutil.h
+++ b/frmts/zlib/zutil.h
@@ -8,7 +8,7 @@
    subject to change. Applications should only use zlib.h.
  */
 
-/* @(#) $Id: zutil.h 13360 2007-12-18 03:47:06Z mloskot $ */
+/* @(#) $Id: zutil.h 30901 2015-10-08 04:18:30Z goatbar $ */
 
 #ifndef ZUTIL_H
 #define ZUTIL_H
@@ -17,26 +17,14 @@
 #include "zlib.h"
 
 #ifdef STDC
-#  ifndef _WIN32_WCE
-#    include <stddef.h>
-#  endif
+#  include <stddef.h>
 #  include <string.h>
 #  include <stdlib.h>
 #endif
 #ifdef NO_ERRNO_H
-#   ifdef _WIN32_WCE
-      /* The Microsoft C Run-Time Library for Windows CE doesn't have
-       * errno.  We define it as a global variable to simplify porting.
-       * Its value is always 0 and should not be used.  We rename it to
-       * avoid conflict with other libraries that use the same workaround.
-       */
-#     define errno z_errno
-#   endif
     extern int errno;
 #else
-#  ifndef _WIN32_WCE
-#    include <errno.h>
-#  endif
+#  include <errno.h>
 #endif
 
 #ifndef local
@@ -152,15 +140,7 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
 #endif
 
 #if (defined(_MSC_VER) && (_MSC_VER > 600))
-#  if defined(_WIN32_WCE)
-#    define fdopen(fd,mode) NULL /* No fdopen() */
-#    ifndef _PTRDIFF_T_DEFINED
-       typedef int ptrdiff_t;
-#      define _PTRDIFF_T_DEFINED
-#    endif
-#  else
-#    define fdopen(fd,type)  _fdopen(fd,type)
-#  endif
+#  define fdopen(fd,type)  _fdopen(fd,type)
 #endif
 
         /* common defaults */
diff --git a/frmts/zmap/zmapdataset.cpp b/frmts/zmap/zmapdataset.cpp
index 7f6cf45..c6d3a3a 100644
--- a/frmts/zmap/zmapdataset.cpp
+++ b/frmts/zmap/zmapdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: zmapdataset.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: zmapdataset.cpp 32984 2016-01-14 19:08:12Z goatbar $
  *
  * Project:  ZMap driver
  * Purpose:  GDALDataset driver for ZMap dataset.
@@ -27,15 +27,14 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_vsi_virtual.h"
 #include "cpl_string.h"
+#include "cpl_vsi_virtual.h"
+#include "gdal_frmts.h"
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: zmapdataset.cpp 28053 2014-12-04 09:31:07Z rouault $");
+#include <cmath>
 
-CPL_C_START
-void    GDALRegister_ZMap(void);
-CPL_C_END
+CPL_CVSID("$Id: zmapdataset.cpp 32984 2016-01-14 19:08:12Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -82,11 +81,9 @@ class ZMapRasterBand : public GDALPamRasterBand
     friend class ZMapDataset;
 
   public:
-
-                ZMapRasterBand( ZMapDataset * );
+    explicit ZMapRasterBand( ZMapDataset * );
 
     virtual CPLErr IReadBlock( int, int, void * );
-
     virtual double GetNoDataValue( int *pbSuccess = NULL );
 };
 
@@ -95,16 +92,16 @@ class ZMapRasterBand : public GDALPamRasterBand
 /*                           ZMapRasterBand()                           */
 /************************************************************************/
 
-ZMapRasterBand::ZMapRasterBand( ZMapDataset *poDS )
+ZMapRasterBand::ZMapRasterBand( ZMapDataset *poDSIn )
 
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
+    poDS = poDSIn;
+    nBand = 1;
 
     eDataType = GDT_Float64;
 
     nBlockXSize = 1;
-    nBlockYSize = poDS->GetRasterYSize();
+    nBlockYSize = poDSIn->GetRasterYSize();
 }
 
 /************************************************************************/
@@ -115,8 +112,7 @@ CPLErr ZMapRasterBand::IReadBlock( int nBlockXOff,
                                    CPL_UNUSED int nBlockYOff,
                                    void * pImage )
 {
-    int i;
-    ZMapDataset *poGDS = (ZMapDataset *) poDS;
+    ZMapDataset *poGDS = reinterpret_cast<ZMapDataset *>( poDS );
 
     if (poGDS->fp == NULL)
         return CE_Failure;
@@ -129,36 +125,37 @@ CPLErr ZMapRasterBand::IReadBlock( int nBlockXOff,
 
     if (nBlockXOff > poGDS->nColNum + 1)
     {
-        for(i=poGDS->nColNum + 1;i<nBlockXOff;i++)
+        for( int i = poGDS->nColNum + 1; i < nBlockXOff; i++ )
         {
             if (IReadBlock(i,0,pImage) != CE_None)
                 return CE_Failure;
         }
     }
 
-    char* pszLine;
-    i = 0;
-    double dfExp = pow(10.0, poGDS->nDecimalCount);
+    int i = 0;
+    const double dfExp = std::pow(10.0, poGDS->nDecimalCount);
     while(i<nRasterYSize)
     {
-        pszLine = (char*)CPLReadLineL(poGDS->fp);
+        char* pszLine = const_cast<char *>( CPLReadLineL(poGDS->fp) );
         if (pszLine == NULL)
             return CE_Failure;
         int nExpected = nRasterYSize - i;
         if (nExpected > poGDS->nValuesPerLine)
             nExpected = poGDS->nValuesPerLine;
-        if ((int)strlen(pszLine) != nExpected * poGDS->nFieldSize)
+        if( static_cast<int>( strlen(pszLine) )
+            != nExpected * poGDS->nFieldSize )
             return CE_Failure;
 
-        for(int j=0;j<nExpected;j++)
+        for( int j = 0; j < nExpected; j++ )
         {
             char* pszValue = pszLine + j * poGDS->nFieldSize;
-            char chSaved = pszValue[poGDS->nFieldSize];
+            const char chSaved = pszValue[poGDS->nFieldSize];
             pszValue[poGDS->nFieldSize] = 0;
             if (strchr(pszValue, '.') != NULL)
-                ((double*)pImage)[i+j] = CPLAtofM(pszValue);
+                reinterpret_cast<double *>( pImage )[i+j] = CPLAtofM(pszValue);
             else
-                ((double*)pImage)[i+j] = atoi(pszValue) * dfExp;
+                reinterpret_cast<double *>( pImage )[i+j]
+                    = atoi(pszValue) * dfExp;
             pszValue[poGDS->nFieldSize] = chSaved;
         }
 
@@ -176,7 +173,7 @@ CPLErr ZMapRasterBand::IReadBlock( int nBlockXOff,
 
 double ZMapRasterBand::GetNoDataValue( int *pbSuccess )
 {
-    ZMapDataset *poGDS = (ZMapDataset *) poDS;
+    ZMapDataset *poGDS = reinterpret_cast<ZMapDataset *>( poDS );
 
     if (pbSuccess)
         *pbSuccess = TRUE;
@@ -188,15 +185,15 @@ double ZMapRasterBand::GetNoDataValue( int *pbSuccess )
 /*                            ~ZMapDataset()                            */
 /************************************************************************/
 
-ZMapDataset::ZMapDataset()
+ZMapDataset::ZMapDataset() :
+    fp(NULL),
+    nValuesPerLine(0),
+    nFieldSize(0),
+    nDecimalCount(0),
+    nColNum(-1),
+    dfNoDataValue(0.0),
+    nDataStartOff(0)
 {
-    fp = NULL;
-    nDataStartOff = 0;
-    nColNum = -1;
-    nValuesPerLine = 0;
-    nFieldSize = 0;
-    nDecimalCount = 0;
-    dfNoDataValue = 0.0;
     adfGeoTransform[0] = 0;
     adfGeoTransform[1] = 1;
     adfGeoTransform[2] = 0;
@@ -223,18 +220,17 @@ ZMapDataset::~ZMapDataset()
 
 int ZMapDataset::Identify( GDALOpenInfo * poOpenInfo )
 {
-    int         i;
-
     if (poOpenInfo->nHeaderBytes == 0)
         return FALSE;
 
 /* -------------------------------------------------------------------- */
 /*      Chech that it looks roughly as a ZMap dataset                   */
 /* -------------------------------------------------------------------- */
-    const char* pszData = (const char*)poOpenInfo->pabyHeader;
+    const char* pszData
+        = reinterpret_cast<const char *>( poOpenInfo->pabyHeader );
 
     /* Skip comments line at the beginning */
-    i=0;
+    int i = 0;
     if (pszData[i] == '!')
     {
         i++;
@@ -267,7 +263,7 @@ int ZMapDataset::Identify( GDALOpenInfo * poOpenInfo )
     while (*pszToken == ' ')
         pszToken ++;
 
-    if (strncmp(pszToken, "GRID", 4) != 0)
+    if (!STARTS_WITH(pszToken, "GRID"))
     {
         CSLDestroy(papszTokens);
         return FALSE;
@@ -320,7 +316,7 @@ GDALDataset *ZMapDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    int nValuesPerLine = atoi(papszTokens[2]);
+    const int nValuesPerLine = atoi(papszTokens[2]);
     if (nValuesPerLine <= 0)
     {
         CSLDestroy(papszTokens);
@@ -346,10 +342,10 @@ GDALDataset *ZMapDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    int nFieldSize = atoi(papszTokens[0]);
-    double dfNoDataValue = CPLAtofM(papszTokens[1]);
-    int nDecimalCount = atoi(papszTokens[3]);
-    int nColumnNumber = atoi(papszTokens[4]);
+    const int nFieldSize = atoi(papszTokens[0]);
+    const double dfNoDataValue = CPLAtofM(papszTokens[1]);
+    const int nDecimalCount = atoi(papszTokens[3]);
+    const int nColumnNumber = atoi(papszTokens[4]);
 
     CSLDestroy(papszTokens);
     papszTokens = NULL;
@@ -379,12 +375,12 @@ GDALDataset *ZMapDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    int nRows = atoi(papszTokens[0]);
-    int nCols = atoi(papszTokens[1]);
-    double dfMinX = CPLAtofM(papszTokens[2]);
-    double dfMaxX = CPLAtofM(papszTokens[3]);
-    double dfMinY = CPLAtofM(papszTokens[4]);
-    double dfMaxY = CPLAtofM(papszTokens[5]);
+    const int nRows = atoi(papszTokens[0]);
+    const int nCols = atoi(papszTokens[1]);
+    const double dfMinX = CPLAtofM(papszTokens[2]);
+    const double dfMaxX = CPLAtofM(papszTokens[3]);
+    const double dfMinY = CPLAtofM(papszTokens[4]);
+    const double dfMaxY = CPLAtofM(papszTokens[5]);
 
     CSLDestroy(papszTokens);
     papszTokens = NULL;
@@ -395,7 +391,7 @@ GDALDataset *ZMapDataset::Open( GDALOpenInfo * poOpenInfo )
         VSIFCloseL(fp);
         return NULL;
     }
-    
+
     /* Ignore fourth header line */
     pszLine = CPLReadLine2L(fp, 100, NULL);
     if (pszLine == NULL)
@@ -415,9 +411,7 @@ GDALDataset *ZMapDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    ZMapDataset         *poDS;
-
-    poDS = new ZMapDataset();
+    ZMapDataset *poDS = new ZMapDataset();
     poDS->fp = fp;
     poDS->nDataStartOff = VSIFTellL(fp);
     poDS->nValuesPerLine = nValuesPerLine;
@@ -427,10 +421,10 @@ GDALDataset *ZMapDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->nRasterYSize = nRows;
     poDS->dfNoDataValue = dfNoDataValue;
 
-    if (CSLTestBoolean(CPLGetConfigOption("ZMAP_PIXEL_IS_POINT", "FALSE")))
+    if (CPLTestBool(CPLGetConfigOption("ZMAP_PIXEL_IS_POINT", "FALSE")))
     {
-        double dfStepX = (dfMaxX - dfMinX) / (nCols - 1);
-        double dfStepY = (dfMaxY - dfMinY) / (nRows - 1);
+        const double dfStepX = (dfMaxX - dfMinX) / (nCols - 1);
+        const double dfStepY = (dfMaxY - dfMinY) / (nRows - 1);
 
         poDS->adfGeoTransform[0] = dfMinX - dfStepX / 2;
         poDS->adfGeoTransform[1] = dfStepX;
@@ -439,8 +433,8 @@ GDALDataset *ZMapDataset::Open( GDALOpenInfo * poOpenInfo )
     }
     else
     {
-        double dfStepX = (dfMaxX - dfMinX) / nCols ;
-        double dfStepY = (dfMaxY - dfMinY) / nRows;
+        const double dfStepX = (dfMaxX - dfMinX) / nCols ;
+        const double dfStepY = (dfMaxY - dfMinY) / nRows;
 
         poDS->adfGeoTransform[0] = dfMinX;
         poDS->adfGeoTransform[1] = dfStepX;
@@ -474,10 +468,9 @@ GDALDataset *ZMapDataset::Open( GDALOpenInfo * poOpenInfo )
 
 static void WriteRightJustified(VSILFILE* fp, const char *pszValue, int nWidth)
 {
-    int nLen = strlen(pszValue);
+    int nLen = (int)strlen(pszValue);
     CPLAssert(nLen <= nWidth);
-    int i;
-    for(i=0;i<nWidth -nLen;i++)
+    for( int i=0; i < nWidth - nLen; i++ )
         VSIFWriteL(" ", 1, 1, fp);
     VSIFWriteL(pszValue, 1, nLen, fp);
 }
@@ -493,23 +486,23 @@ static void WriteRightJustified(VSILFILE* fp, double dfValue, int nWidth,
 {
     char szFormat[32];
     if (nDecimals >= 0)
-        sprintf(szFormat, "%%.%df", nDecimals);
+        snprintf(szFormat, sizeof(szFormat), "%%.%df", nDecimals);
     else
-        sprintf(szFormat, "%%g");
-    char* pszValue = (char*)CPLSPrintf(szFormat, dfValue);
+        snprintf(szFormat, sizeof(szFormat), "%%g");
+    char* pszValue = const_cast<char *>( CPLSPrintf(szFormat, dfValue) );
     char* pszE = strchr(pszValue, 'e');
     if (pszE)
         *pszE = 'E';
 
-    if ((int)strlen(pszValue) > nWidth)
+    if( static_cast<int>( strlen(pszValue) ) > nWidth)
     {
-        sprintf(szFormat, "%%.%dg", nDecimals);
-        pszValue = (char*)CPLSPrintf(szFormat, dfValue);
+        snprintf(szFormat, sizeof(szFormat), "%%.%dg", nDecimals);
+        pszValue = const_cast<char *>( CPLSPrintf(szFormat, dfValue) );
         pszE = strchr(pszValue, 'e');
         if (pszE)
             *pszE = 'E';
     }
-    
+
     CPLString osValue(pszValue);
     WriteRightJustified(fp, osValue.c_str(), nWidth);
 }
@@ -551,19 +544,20 @@ GDALDataset* ZMapDataset::CreateCopy( const char * pszFilename,
 /*      Get source dataset info                                         */
 /* -------------------------------------------------------------------- */
 
-    int nXSize = poSrcDS->GetRasterXSize();
-    int nYSize = poSrcDS->GetRasterYSize();
+    const int nXSize = poSrcDS->GetRasterXSize();
+    const int nYSize = poSrcDS->GetRasterYSize();
     if (nXSize == 1 || nYSize == 1)
     {
         return NULL;
     }
-    
+
     double adfGeoTransform[6];
     poSrcDS->GetGeoTransform(adfGeoTransform);
     if (adfGeoTransform[2] != 0 || adfGeoTransform[4] != 0)
     {
         CPLError( CE_Failure, CPLE_NotSupported,
-                  "ZMap driver does not support CreateCopy() from skewed or rotated dataset.\n");
+                  "ZMap driver does not support CreateCopy() from skewed or "
+                  "rotated dataset.\n");
         return NULL;
     }
 
@@ -579,9 +573,9 @@ GDALDataset* ZMapDataset::CreateCopy( const char * pszFilename,
         return NULL;
     }
 
-    int nFieldSize = 20;
-    int nValuesPerLine = 4;
-    int nDecimalCount = 7;
+    const int nFieldSize = 20;
+    const int nValuesPerLine = 4;
+    const int nDecimalCount = 7;
 
     int bHasNoDataValue = FALSE;
     double dfNoDataValue =
@@ -610,7 +604,7 @@ GDALDataset* ZMapDataset::CreateCopy( const char * pszFilename,
     WriteRightJustified(fp, nXSize, 10);
     VSIFPrintfL(fp, ",");
 
-    if (CSLTestBoolean(CPLGetConfigOption("ZMAP_PIXEL_IS_POINT", "FALSE")))
+    if (CPLTestBool(CPLGetConfigOption("ZMAP_PIXEL_IS_POINT", "FALSE")))
     {
         WriteRightJustified(fp, adfGeoTransform[0] + adfGeoTransform[1] / 2, 14, 7);
         VSIFPrintfL(fp, ",");
@@ -641,10 +635,11 @@ GDALDataset* ZMapDataset::CreateCopy( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Copy imagery                                                    */
 /* -------------------------------------------------------------------- */
-    double* padfLineBuffer = (double*) CPLMalloc(nYSize * sizeof(double));
-    int i, j;
+    double* padfLineBuffer = reinterpret_cast<double *>(
+        CPLMalloc(nYSize * sizeof(double) ) );
+
     CPLErr eErr = CE_None;
-    for(i=0;i<nXSize && eErr == CE_None;i++)
+    for( int i=0; i < nXSize && eErr == CE_None; i++ )
     {
         eErr = poSrcDS->GetRasterBand(1)->RasterIO(
                                             GF_Read, i, 0, 1, nYSize,
@@ -652,22 +647,24 @@ GDALDataset* ZMapDataset::CreateCopy( const char * pszFilename,
                                             GDT_Float64, 0, 0, NULL);
         if (eErr != CE_None)
             break;
-        int bEOLPrinted = FALSE;
-        for(j=0;j<nYSize;j++)
+        bool bEOLPrinted = false;
+        int j = 0;
+        for( ; j < nYSize; j++ )
         {
             WriteRightJustified(fp, padfLineBuffer[j], nFieldSize, nDecimalCount);
             if (((j + 1) % nValuesPerLine) == 0)
             {
-                bEOLPrinted = TRUE;
+                bEOLPrinted = true;
                 VSIFPrintfL(fp, "\n");
             }
             else
-                bEOLPrinted = FALSE;
+                bEOLPrinted = false;
         }
         if (!bEOLPrinted)
             VSIFPrintfL(fp, "\n");
 
-        if (!pfnProgress( (j+1) * 1.0 / nYSize, NULL, pProgressData))
+        if (pfnProgress != NULL &&
+            !pfnProgress( (j+1) * 1.0 / nYSize, NULL, pProgressData))
         {
             eErr = CE_Failure;
             break;
@@ -679,7 +676,8 @@ GDALDataset* ZMapDataset::CreateCopy( const char * pszFilename,
     if (eErr != CE_None)
         return NULL;
 
-    return (GDALDataset*) GDALOpen(pszFilename, GA_ReadOnly);
+    return reinterpret_cast<GDALDataset*>(
+        GDALOpen(pszFilename, GA_ReadOnly) );
 }
 
 /************************************************************************/
@@ -701,26 +699,21 @@ CPLErr ZMapDataset::GetGeoTransform( double * padfTransform )
 void GDALRegister_ZMap()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "ZMap" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "ZMap" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-
-        poDriver->SetDescription( "ZMap" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "ZMap Plus Grid" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "frmt_various.html#ZMap" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "dat" );
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetDescription( "ZMap" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "ZMap Plus Grid" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#ZMap" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "dat" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = ZMapDataset::Open;
-        poDriver->pfnIdentify = ZMapDataset::Identify;
-        poDriver->pfnCreateCopy = ZMapDataset::CreateCopy;
+    poDriver->pfnOpen = ZMapDataset::Open;
+    poDriver->pfnIdentify = ZMapDataset::Identify;
+    poDriver->pfnCreateCopy = ZMapDataset::CreateCopy;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/gcore/GNUmakefile b/gcore/GNUmakefile
index 9c0c4bc..75647cc 100644
--- a/gcore/GNUmakefile
+++ b/gcore/GNUmakefile
@@ -8,11 +8,12 @@ OBJ	=	gdalopeninfo.o gdaldrivermanager.o gdaldriver.o gdaldataset.o \
 		gdaljp2metadata.o gdaljp2box.o gdalmultidomainmetadata.o \
 		gdal_rat.o gdalgmlcoverage.o gdalpamproxydb.o \
                 gdalallvalidmaskband.o gdalnodatamaskband.o \
- 		gdalproxydataset.o gdalproxypool.o gdaldefaultasync.o \
+		gdalproxydataset.o gdalproxypool.o gdaldefaultasync.o \
 		gdalnodatavaluesmaskband.o gdaldllmain.o gdalexif.o gdalclientserver.o \
 		gdalgeorefpamdataset.o gdaljp2abstractdataset.o gdalvirtualmem.o \
 		gdaloverviewdataset.o gdalrescaledalphaband.o gdaljp2structure.o \
-		gdal_mdreader.o gdaljp2metadatagenerator.o
+		gdal_mdreader.o gdaljp2metadatagenerator.o gdalabstractbandblockcache.o \
+		gdalarraybandblockcache.o gdalhashsetbandblockcache.o
 
 # Enable the following if you want to use MITAB's code to convert
 # .tab coordinate systems into well known text.  But beware that linking
@@ -25,7 +26,7 @@ XTRA_OPT 	:=	$(XTRA_OPT) -DRENAME_INTERNAL_LIBTIFF_SYMBOLS
 endif
 endif
 
-CPPFLAGS	:=	 -I../frmts/gtiff -I../frmts/mem -I../frmts/vrt -I../ogr -I../ogr/ogrsf_frmts/generic $(JSON_INCLUDE) -I../ogr/ogrsf_frmts/geojson $(CPPFLAGS) $(PAM_SETTING) $(XTRA_OPT)
+CPPFLAGS	:=	 -I../frmts/gtiff -I../frmts/mem -I../frmts/vrt -I../ogr -I../ogr/ogrsf_frmts/generic -I../gnm/ -I../gnm/gnm_frmts/ $(JSON_INCLUDE) -I../ogr/ogrsf_frmts/geojson $(CPPFLAGS) $(PAM_SETTING) $(XTRA_OPT)
 
 ifeq ($(HAVE_SQLITE),yes)
 CXXFLAGS :=	$(CXXFLAGS) -DSQLITE_ENABLED
@@ -48,13 +49,8 @@ docs:
 gdal_misc.$(OBJ_EXT):	gdal_misc.cpp gdal_version.h
 
 gdaldrivermanager.$(OBJ_EXT):	gdaldrivermanager.cpp ../GDALmake.opt
-	$(CXX) -c $(GDAL_INCLUDE) $(CXXFLAGS) -DINST_DATA=\"$(INST_DATA)\" \
+	$(CXX) -c $(GDAL_INCLUDE) $(CPPFLAGS) $(CXXFLAGS) -DINST_DATA=\"$(INST_DATA)\" \
 		$< -o $@
 
 install:
 	for f in *.h ; do $(INSTALL_DATA) $$f $(DESTDIR)$(INST_INCLUDE) ; done
-
-# Small test tool using gdaljp2box.cpp to read jpeg2000 boxes.  Not normally
-# built or installed.
-jp2dump:	jp2dump.o
-	$(CXX) $(CXXFLAGS) jp2dump.o $(CONFIG_LIBS) -o jp2dump
diff --git a/gcore/gdal.h b/gcore/gdal.h
index d361ae5..e355f73 100644
--- a/gcore/gdal.h
+++ b/gcore/gdal.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal.h 29330 2015-06-14 12:11:11Z rouault $
+ * $Id: gdal.h 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  GDAL Core C/Public declarations.
@@ -70,17 +70,20 @@ typedef enum {
     GDT_TypeCount = 12          /* maximum type # + 1 */
 } GDALDataType;
 
-int CPL_DLL CPL_STDCALL GDALGetDataTypeSize( GDALDataType );
+int CPL_DLL CPL_STDCALL GDALGetDataTypeSize( GDALDataType );  // Deprecated.
+int CPL_DLL CPL_STDCALL GDALGetDataTypeSizeBits( GDALDataType eDataType );
+int CPL_DLL CPL_STDCALL GDALGetDataTypeSizeBytes( GDALDataType );
 int CPL_DLL CPL_STDCALL GDALDataTypeIsComplex( GDALDataType );
 const char CPL_DLL * CPL_STDCALL GDALGetDataTypeName( GDALDataType );
 GDALDataType CPL_DLL CPL_STDCALL GDALGetDataTypeByName( const char * );
 GDALDataType CPL_DLL CPL_STDCALL GDALDataTypeUnion( GDALDataType, GDALDataType );
+double CPL_DLL GDALAdjustValueToDataType( GDALDataType eDT, double dfValue, int* pbClamped, int* pbRounded );
 
 /**
 * status of the asynchronous stream
 */
-typedef enum 
-{	
+typedef enum
+{
 	GARIO_PENDING = 0,
 	GARIO_UPDATE = 1,
 	GARIO_ERROR = 2,
@@ -103,7 +106,7 @@ typedef enum {
     /*! Write data */  GF_Write = 1
 } GDALRWFlag;
 
-/* NOTE: values are selected to be consistent with GDALResampleAlg of alg/gdalwarper.h */ 
+/* NOTE: values are selected to be consistent with GDALResampleAlg of alg/gdalwarper.h */
 /** RasterIO() resampling method.
   * @since GDAL 2.0
   */
@@ -128,15 +131,15 @@ typedef enum
   */
 typedef struct
 {
-    /*! Version of structure (to allow future extensions of the structure) */ 
+    /*! Version of structure (to allow future extensions of the structure) */
     int                    nVersion;
 
-    /*! Resampling algorithm */ 
+    /*! Resampling algorithm */
     GDALRIOResampleAlg     eResampleAlg;
 
-    /*! Progress callback */ 
+    /*! Progress callback */
     GDALProgressFunc       pfnProgress;
-    /*! Progress callback user data */ 
+    /*! Progress callback user data */
     void                  *pProgressData;
 
     /*! Indicate if dfXOff, dfYOff, dfXSize and dfYSize are set.
@@ -193,7 +196,7 @@ const char CPL_DLL *GDALGetColorInterpretationName( GDALColorInterp );
 GDALColorInterp CPL_DLL GDALGetColorInterpretationByName( const char *pszName );
 
 /*! Types of color interpretations for a GDALColorTable. */
-typedef enum 
+typedef enum
 {
   /*! Grayscale (in GDALColorEntry.c1) */                      GPI_Gray=0,
   /*! Red, Green, Blue and Alpha in (in c1, c2, c3 and c4) */  GPI_RGB=1,
@@ -205,7 +208,7 @@ const char CPL_DLL *GDALGetPaletteInterpretationName( GDALPaletteInterp );
 
 /* "well known" metadata items. */
 
-#define GDALMD_AREA_OR_POINT   "AREA_OR_POINT" 
+#define GDALMD_AREA_OR_POINT   "AREA_OR_POINT"
 #  define GDALMD_AOP_AREA      "Area"
 #  define GDALMD_AOP_POINT     "Point"
 
@@ -214,7 +217,7 @@ const char CPL_DLL *GDALGetPaletteInterpretationName( GDALPaletteInterp );
 /*                                                                      */
 /*      error codes 100 to 299 reserved for GDAL.                       */
 /* -------------------------------------------------------------------- */
-#define CPLE_WrongFormat        200
+#define CPLE_WrongFormat        (CPLErrorNum)200
 
 /* -------------------------------------------------------------------- */
 /*      Define handle types related to various internal classes.        */
@@ -260,7 +263,7 @@ typedef GIntBig GSpacing;
 /** Extension handled by the driver. */
 #define GDAL_DMD_EXTENSION "DMD_EXTENSION"
 
-/** Connection prefix to provide as the file name of the the open function.
+/** Connection prefix to provide as the file name of the open function.
  * Typically set for non-file based drivers. Generally used with open options.
  * @since GDAL 2.0
  */
@@ -277,7 +280,7 @@ typedef GIntBig GSpacing;
 /** XML snippet with open options.
  * @since GDAL 2.0
  */
-#define GDAL_DMD_OPENOPTIONLIST "DMD_OPENOPTIONLIST" 
+#define GDAL_DMD_OPENOPTIONLIST "DMD_OPENOPTIONLIST"
 
 /** List of (space separated) raster data types support by the Create()/CreateCopy() API. */
 #define GDAL_DMD_CREATIONDATATYPES "DMD_CREATIONDATATYPES"
@@ -288,7 +291,7 @@ typedef GIntBig GSpacing;
 #define GDAL_DMD_CREATIONFIELDDATATYPES "DMD_CREATIONFIELDDATATYPES"
 
 /** Capability set by a driver that exposes Subdatasets. */
-#define GDAL_DMD_SUBDATASETS "DMD_SUBDATASETS" 
+#define GDAL_DMD_SUBDATASETS "DMD_SUBDATASETS"
 
 /** Capability set by a driver that implements the Open() API. */
 #define GDAL_DCAP_OPEN       "DCAP_OPEN"
@@ -312,20 +315,25 @@ typedef GIntBig GSpacing;
  */
 #define GDAL_DCAP_VECTOR     "DCAP_VECTOR"
 
-/** Capability set by a driver that can create fields with NOT NULL constraint. 
+/** Capability set by a driver having vector capability.
+ * @since GDAL 2.1
+ */
+#define GDAL_DCAP_GNM         "DCAP_GNM"
+
+/** Capability set by a driver that can create fields with NOT NULL constraint.
  * @since GDAL 2.0
  */
-#define GDAL_DCAP_NOTNULL_FIELDS "DCAP_NOTNULL_FIELDS" 
+#define GDAL_DCAP_NOTNULL_FIELDS "DCAP_NOTNULL_FIELDS"
 
-/** Capability set by a driver that can create fields with DEFAULT values. 
+/** Capability set by a driver that can create fields with DEFAULT values.
  * @since GDAL 2.0
  */
-#define GDAL_DCAP_DEFAULT_FIELDS "DCAP_DEFAULT_FIELDS" 
+#define GDAL_DCAP_DEFAULT_FIELDS "DCAP_DEFAULT_FIELDS"
 
 /** Capability set by a driver that can create geometry fields with NOT NULL constraint.
  * @since GDAL 2.0
  */
-#define GDAL_DCAP_NOTNULL_GEOMFIELDS "DCAP_NOTNULL_GEOMFIELDS" 
+#define GDAL_DCAP_NOTNULL_GEOMFIELDS "DCAP_NOTNULL_GEOMFIELDS"
 
 void CPL_DLL CPL_STDCALL GDALAllRegister( void );
 
@@ -375,6 +383,14 @@ GDALDatasetH CPL_DLL CPL_STDCALL GDALOpenShared( const char *, GDALAccess ) CPL_
  * @since GDAL 2.0
  */
 #define     GDAL_OF_VECTOR          0x04
+
+
+/** Allow gnm drivers to be used.
+ * Used by GDALOpenEx().
+ * @since GDAL 2.1
+ */
+#define     GDAL_OF_GNM             0x08
+
 /* Some space for GDAL 3.0 new types ;-) */
 /*#define     GDAL_OF_OTHER_KIND1   0x08 */
 /*#define     GDAL_OF_OTHER_KIND2   0x10 */
@@ -402,6 +418,40 @@ GDALDatasetH CPL_DLL CPL_STDCALL GDALOpenShared( const char *, GDALAccess ) CPL_
  */
 #define     GDAL_OF_INTERNAL        0x80
 
+/** Let GDAL decide if a array-based or hashset-based storage strategy for
+ * cached blocks must be used.
+ *
+ * GDAL_OF_DEFAULT_BLOCK_ACCESS, GDAL_OF_ARRAY_BLOCK_ACCESS and
+ * GDAL_OF_HASHSET_BLOCK_ACCESS are mutually exclusive.
+ *
+ * Used by GDALOpenEx().
+ * @since GDAL 2.1
+ */
+#define     GDAL_OF_DEFAULT_BLOCK_ACCESS  0
+
+/** Use a array-based storage strategy for cached blocks.
+ *
+ * GDAL_OF_DEFAULT_BLOCK_ACCESS, GDAL_OF_ARRAY_BLOCK_ACCESS and
+ * GDAL_OF_HASHSET_BLOCK_ACCESS are mutually exclusive.
+ *
+ * Used by GDALOpenEx().
+ * @since GDAL 2.1
+ */
+#define     GDAL_OF_ARRAY_BLOCK_ACCESS    0x100
+
+/** Use a hashset-based storage strategy for cached blocks.
+ *
+ * GDAL_OF_DEFAULT_BLOCK_ACCESS, GDAL_OF_ARRAY_BLOCK_ACCESS and
+ * GDAL_OF_HASHSET_BLOCK_ACCESS are mutually exclusive.
+ *
+ * Used by GDALOpenEx().
+ * @since GDAL 2.1
+ */
+#define     GDAL_OF_HASHSET_BLOCK_ACCESS  0x200
+
+#define     GDAL_OF_RESERVED_1            0x300
+#define     GDAL_OF_BLOCK_ACCESS_MASK     0x300
+
 GDALDatasetH CPL_DLL CPL_STDCALL GDALOpenEx( const char* pszFilename,
                                              unsigned int nOpenFlags,
                                              const char* const* papszAllowedDrivers,
@@ -419,10 +469,10 @@ void        CPL_DLL CPL_STDCALL GDALDeregisterDriver( GDALDriverH );
 void        CPL_DLL CPL_STDCALL GDALDestroyDriverManager( void );
 void        CPL_DLL             GDALDestroy( void );
 CPLErr      CPL_DLL CPL_STDCALL GDALDeleteDataset( GDALDriverH, const char * );
-CPLErr      CPL_DLL CPL_STDCALL GDALRenameDataset( GDALDriverH, 
+CPLErr      CPL_DLL CPL_STDCALL GDALRenameDataset( GDALDriverH,
                                                    const char * pszNewName,
                                                    const char * pszOldName );
-CPLErr      CPL_DLL CPL_STDCALL GDALCopyDatasetFiles( GDALDriverH, 
+CPLErr      CPL_DLL CPL_STDCALL GDALCopyDatasetFiles( GDALDriverH,
                                                       const char * pszNewName,
                                                       const char * pszOldName);
 int         CPL_DLL CPL_STDCALL GDALValidateCreationOptions( GDALDriverH,
@@ -442,7 +492,7 @@ const char CPL_DLL * CPL_STDCALL GDALGetDriverCreationOptionList( GDALDriverH );
 typedef struct
 {
     /** Unique identifier, often numeric */
-    char        *pszId; 
+    char        *pszId;
 
     /** Informational message or "" */
     char        *pszInfo;
@@ -467,12 +517,12 @@ void CPL_DLL CPL_STDCALL GDALDeinitGCPs( int, GDAL_GCP * );
 GDAL_GCP CPL_DLL * CPL_STDCALL GDALDuplicateGCPs( int, const GDAL_GCP * );
 
 int CPL_DLL CPL_STDCALL
-GDALGCPsToGeoTransform( int nGCPCount, const GDAL_GCP *pasGCPs, 
-                        double *padfGeoTransform, int bApproxOK )  CPL_WARN_UNUSED_RESULT; 
+GDALGCPsToGeoTransform( int nGCPCount, const GDAL_GCP *pasGCPs,
+                        double *padfGeoTransform, int bApproxOK )  CPL_WARN_UNUSED_RESULT;
 int CPL_DLL CPL_STDCALL
-GDALInvGeoTransform( double *padfGeoTransformIn, 
+GDALInvGeoTransform( double *padfGeoTransformIn,
                      double *padfInvGeoTransformOut ) CPL_WARN_UNUSED_RESULT;
-void CPL_DLL CPL_STDCALL GDALApplyGeoTransform( double *, double, double, 
+void CPL_DLL CPL_STDCALL GDALApplyGeoTransform( double *, double, double,
                                                 double *, double * );
 void CPL_DLL GDALComposeGeoTransforms(const double *padfGeoTransform1,
                                       const double *padfGeoTransform2,
@@ -486,7 +536,7 @@ char CPL_DLL  ** CPL_STDCALL GDALGetMetadataDomainList( GDALMajorObjectH hObject
 char CPL_DLL  ** CPL_STDCALL GDALGetMetadata( GDALMajorObjectH, const char * );
 CPLErr CPL_DLL CPL_STDCALL GDALSetMetadata( GDALMajorObjectH, char **,
                                             const char * );
-const char CPL_DLL * CPL_STDCALL 
+const char CPL_DLL * CPL_STDCALL
 GDALGetMetadataItem( GDALMajorObjectH, const char *, const char * );
 CPLErr CPL_DLL CPL_STDCALL
 GDALSetMetadataItem( GDALMajorObjectH, const char *, const char *,
@@ -498,7 +548,7 @@ void CPL_DLL CPL_STDCALL GDALSetDescription( GDALMajorObjectH, const char * );
 /*      GDALDataset class ... normally this represents one file.        */
 /* ==================================================================== */
 
-#define GDAL_DS_LAYER_CREATIONOPTIONLIST "DS_LAYER_CREATIONOPTIONLIST" 
+#define GDAL_DS_LAYER_CREATIONOPTIONLIST "DS_LAYER_CREATIONOPTIONLIST"
 
 GDALDriverH CPL_DLL CPL_STDCALL GDALGetDatasetDriver( GDALDatasetH );
 char CPL_DLL ** CPL_STDCALL GDALGetFileList( GDALDatasetH );
@@ -508,36 +558,36 @@ int CPL_DLL CPL_STDCALL     GDALGetRasterYSize( GDALDatasetH );
 int CPL_DLL CPL_STDCALL     GDALGetRasterCount( GDALDatasetH );
 GDALRasterBandH CPL_DLL CPL_STDCALL GDALGetRasterBand( GDALDatasetH, int );
 
-CPLErr CPL_DLL  CPL_STDCALL GDALAddBand( GDALDatasetH hDS, GDALDataType eType, 
+CPLErr CPL_DLL  CPL_STDCALL GDALAddBand( GDALDatasetH hDS, GDALDataType eType,
                              char **papszOptions );
 
-GDALAsyncReaderH CPL_DLL CPL_STDCALL 
+GDALAsyncReaderH CPL_DLL CPL_STDCALL
 GDALBeginAsyncReader(GDALDatasetH hDS, int nXOff, int nYOff,
                      int nXSize, int nYSize,
                      void *pBuf, int nBufXSize, int nBufYSize,
                      GDALDataType eBufType, int nBandCount, int* panBandMap,
                      int nPixelSpace, int nLineSpace, int nBandSpace,
-                     char **papszOptions);
+                     char **papszOptions) CPL_WARN_UNUSED_RESULT;
 
-void  CPL_DLL CPL_STDCALL 
+void  CPL_DLL CPL_STDCALL
 GDALEndAsyncReader(GDALDatasetH hDS, GDALAsyncReaderH hAsynchReaderH);
 
-CPLErr CPL_DLL CPL_STDCALL GDALDatasetRasterIO( 
+CPLErr CPL_DLL CPL_STDCALL GDALDatasetRasterIO(
     GDALDatasetH hDS, GDALRWFlag eRWFlag,
     int nDSXOff, int nDSYOff, int nDSXSize, int nDSYSize,
     void * pBuffer, int nBXSize, int nBYSize, GDALDataType eBDataType,
-    int nBandCount, int *panBandCount, 
-    int nPixelSpace, int nLineSpace, int nBandSpace);
+    int nBandCount, int *panBandCount,
+    int nPixelSpace, int nLineSpace, int nBandSpace) CPL_WARN_UNUSED_RESULT;
 
-CPLErr CPL_DLL CPL_STDCALL GDALDatasetRasterIOEx( 
+CPLErr CPL_DLL CPL_STDCALL GDALDatasetRasterIOEx(
     GDALDatasetH hDS, GDALRWFlag eRWFlag,
     int nDSXOff, int nDSYOff, int nDSXSize, int nDSYSize,
     void * pBuffer, int nBXSize, int nBYSize, GDALDataType eBDataType,
-    int nBandCount, int *panBandCount, 
+    int nBandCount, int *panBandCount,
     GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace,
-    GDALRasterIOExtraArg* psExtraArg);
+    GDALRasterIOExtraArg* psExtraArg) CPL_WARN_UNUSED_RESULT;
 
-CPLErr CPL_DLL CPL_STDCALL GDALDatasetAdviseRead( GDALDatasetH hDS, 
+CPLErr CPL_DLL CPL_STDCALL GDALDatasetAdviseRead( GDALDatasetH hDS,
     int nDSXOff, int nDSYOff, int nDSXSize, int nDSYSize,
     int nBXSize, int nBYSize, GDALDataType eBDataType,
     int nBandCount, int *panBandCount, char **papszOptions );
@@ -559,33 +609,33 @@ int CPL_DLL CPL_STDCALL GDALDereferenceDataset( GDALDatasetH );
 
 CPLErr CPL_DLL CPL_STDCALL
 GDALBuildOverviews( GDALDatasetH, const char *, int, int *,
-                    int, int *, GDALProgressFunc, void * );
+                    int, int *, GDALProgressFunc, void * ) CPL_WARN_UNUSED_RESULT;
 void CPL_DLL CPL_STDCALL GDALGetOpenDatasets( GDALDatasetH **hDS, int *pnCount );
 int CPL_DLL CPL_STDCALL GDALGetAccess( GDALDatasetH hDS );
 void CPL_DLL CPL_STDCALL GDALFlushCache( GDALDatasetH hDS );
 
-CPLErr CPL_DLL CPL_STDCALL 
+CPLErr CPL_DLL CPL_STDCALL
               GDALCreateDatasetMaskBand( GDALDatasetH hDS, int nFlags );
 
 CPLErr CPL_DLL CPL_STDCALL GDALDatasetCopyWholeRaster(
-    GDALDatasetH hSrcDS, GDALDatasetH hDstDS, char **papszOptions, 
-    GDALProgressFunc pfnProgress, void *pProgressData );
+    GDALDatasetH hSrcDS, GDALDatasetH hDstDS, char **papszOptions,
+    GDALProgressFunc pfnProgress, void *pProgressData ) CPL_WARN_UNUSED_RESULT;
 
 CPLErr CPL_DLL CPL_STDCALL GDALRasterBandCopyWholeRaster(
     GDALRasterBandH hSrcBand, GDALRasterBandH hDstBand, char **papszOptions,
-    GDALProgressFunc pfnProgress, void *pProgressData );
+    GDALProgressFunc pfnProgress, void *pProgressData ) CPL_WARN_UNUSED_RESULT;
 
-CPLErr CPL_DLL 
-GDALRegenerateOverviews( GDALRasterBandH hSrcBand, 
+CPLErr CPL_DLL
+GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
                          int nOverviewCount, GDALRasterBandH *pahOverviewBands,
-                         const char *pszResampling, 
+                         const char *pszResampling,
                          GDALProgressFunc pfnProgress, void *pProgressData );
 
 int    CPL_DLL GDALDatasetGetLayerCount( GDALDatasetH );
 OGRLayerH CPL_DLL GDALDatasetGetLayer( GDALDatasetH, int );
 OGRLayerH CPL_DLL GDALDatasetGetLayerByName( GDALDatasetH, const char * );
 OGRErr    CPL_DLL GDALDatasetDeleteLayer( GDALDatasetH, int );
-OGRLayerH CPL_DLL GDALDatasetCreateLayer( GDALDatasetH, const char *, 
+OGRLayerH CPL_DLL GDALDatasetCreateLayer( GDALDatasetH, const char *,
                                       OGRSpatialReferenceH, OGRwkbGeometryType,
                                       char ** );
 OGRLayerH CPL_DLL GDALDatasetCopyLayer( GDALDatasetH, OGRLayerH, const char *,
@@ -641,26 +691,26 @@ typedef CPLErr
                         int nPixelSpace, int nLineSpace);
 
 GDALDataType CPL_DLL CPL_STDCALL GDALGetRasterDataType( GDALRasterBandH );
-void CPL_DLL CPL_STDCALL 
+void CPL_DLL CPL_STDCALL
 GDALGetBlockSize( GDALRasterBandH, int * pnXSize, int * pnYSize );
 
-CPLErr CPL_DLL CPL_STDCALL GDALRasterAdviseRead( GDALRasterBandH hRB, 
+CPLErr CPL_DLL CPL_STDCALL GDALRasterAdviseRead( GDALRasterBandH hRB,
     int nDSXOff, int nDSYOff, int nDSXSize, int nDSYSize,
     int nBXSize, int nBYSize, GDALDataType eBDataType, char **papszOptions );
 
-CPLErr CPL_DLL CPL_STDCALL 
+CPLErr CPL_DLL CPL_STDCALL
 GDALRasterIO( GDALRasterBandH hRBand, GDALRWFlag eRWFlag,
               int nDSXOff, int nDSYOff, int nDSXSize, int nDSYSize,
               void * pBuffer, int nBXSize, int nBYSize,GDALDataType eBDataType,
-              int nPixelSpace, int nLineSpace );
-CPLErr CPL_DLL CPL_STDCALL 
+              int nPixelSpace, int nLineSpace ) CPL_WARN_UNUSED_RESULT;
+CPLErr CPL_DLL CPL_STDCALL
 GDALRasterIOEx( GDALRasterBandH hRBand, GDALRWFlag eRWFlag,
               int nDSXOff, int nDSYOff, int nDSXSize, int nDSYSize,
               void * pBuffer, int nBXSize, int nBYSize,GDALDataType eBDataType,
               GSpacing nPixelSpace, GSpacing nLineSpace,
-              GDALRasterIOExtraArg* psExtraArg );
-CPLErr CPL_DLL CPL_STDCALL GDALReadBlock( GDALRasterBandH, int, int, void * );
-CPLErr CPL_DLL CPL_STDCALL GDALWriteBlock( GDALRasterBandH, int, int, void * );
+              GDALRasterIOExtraArg* psExtraArg ) CPL_WARN_UNUSED_RESULT;
+CPLErr CPL_DLL CPL_STDCALL GDALReadBlock( GDALRasterBandH, int, int, void * ) CPL_WARN_UNUSED_RESULT;
+CPLErr CPL_DLL CPL_STDCALL GDALWriteBlock( GDALRasterBandH, int, int, void * ) CPL_WARN_UNUSED_RESULT;
 int CPL_DLL CPL_STDCALL GDALGetRasterBandXSize( GDALRasterBandH );
 int CPL_DLL CPL_STDCALL GDALGetRasterBandYSize( GDALRasterBandH );
 GDALAccess CPL_DLL CPL_STDCALL GDALGetRasterAccess( GDALRasterBandH );
@@ -669,7 +719,7 @@ GDALDatasetH CPL_DLL CPL_STDCALL GDALGetBandDataset( GDALRasterBandH );
 
 GDALColorInterp CPL_DLL CPL_STDCALL
 GDALGetRasterColorInterpretation( GDALRasterBandH );
-CPLErr CPL_DLL CPL_STDCALL 
+CPLErr CPL_DLL CPL_STDCALL
 GDALSetRasterColorInterpretation( GDALRasterBandH, GDALColorInterp );
 GDALColorTableH CPL_DLL CPL_STDCALL GDALGetRasterColorTable( GDALRasterBandH );
 CPLErr CPL_DLL CPL_STDCALL GDALSetRasterColorTable( GDALRasterBandH, GDALColorTableH );
@@ -678,19 +728,20 @@ int CPL_DLL CPL_STDCALL GDALGetOverviewCount( GDALRasterBandH );
 GDALRasterBandH CPL_DLL CPL_STDCALL GDALGetOverview( GDALRasterBandH, int );
 double CPL_DLL CPL_STDCALL GDALGetRasterNoDataValue( GDALRasterBandH, int * );
 CPLErr CPL_DLL CPL_STDCALL GDALSetRasterNoDataValue( GDALRasterBandH, double );
+CPLErr CPL_DLL CPL_STDCALL GDALDeleteRasterNoDataValue( GDALRasterBandH );
 char CPL_DLL ** CPL_STDCALL GDALGetRasterCategoryNames( GDALRasterBandH );
 CPLErr CPL_DLL CPL_STDCALL GDALSetRasterCategoryNames( GDALRasterBandH, char ** );
 double CPL_DLL CPL_STDCALL GDALGetRasterMinimum( GDALRasterBandH, int *pbSuccess );
 double CPL_DLL CPL_STDCALL GDALGetRasterMaximum( GDALRasterBandH, int *pbSuccess );
-CPLErr CPL_DLL CPL_STDCALL GDALGetRasterStatistics( 
-    GDALRasterBandH, int bApproxOK, int bForce, 
+CPLErr CPL_DLL CPL_STDCALL GDALGetRasterStatistics(
+    GDALRasterBandH, int bApproxOK, int bForce,
     double *pdfMin, double *pdfMax, double *pdfMean, double *pdfStdDev );
-CPLErr CPL_DLL CPL_STDCALL GDALComputeRasterStatistics( 
-    GDALRasterBandH, int bApproxOK, 
+CPLErr CPL_DLL CPL_STDCALL GDALComputeRasterStatistics(
+    GDALRasterBandH, int bApproxOK,
     double *pdfMin, double *pdfMax, double *pdfMean, double *pdfStdDev,
     GDALProgressFunc pfnProgress, void *pProgressData );
-CPLErr CPL_DLL CPL_STDCALL GDALSetRasterStatistics( 
-    GDALRasterBandH hBand, 
+CPLErr CPL_DLL CPL_STDCALL GDALSetRasterStatistics(
+    GDALRasterBandH hBand,
     double dfMin, double dfMax, double dfMean, double dfStdDev );
 
 const char CPL_DLL * CPL_STDCALL GDALGetRasterUnitType( GDALRasterBandH );
@@ -699,7 +750,7 @@ double CPL_DLL CPL_STDCALL GDALGetRasterOffset( GDALRasterBandH, int *pbSuccess
 CPLErr CPL_DLL CPL_STDCALL GDALSetRasterOffset( GDALRasterBandH hBand, double dfNewOffset);
 double CPL_DLL CPL_STDCALL GDALGetRasterScale( GDALRasterBandH, int *pbSuccess );
 CPLErr CPL_DLL CPL_STDCALL GDALSetRasterScale( GDALRasterBandH hBand, double dfNewOffset );
-void CPL_DLL CPL_STDCALL 
+void CPL_DLL CPL_STDCALL
 GDALComputeRasterMinMax( GDALRasterBandH hBand, int bApproxOK,
                          double adfMinMax[2] );
 CPLErr CPL_DLL CPL_STDCALL GDALFlushRasterCache( GDALRasterBandH hBand );
@@ -742,26 +793,26 @@ GDALGetRasterSampleOverviewEx( GDALRasterBandH, GUIntBig );
 CPLErr CPL_DLL CPL_STDCALL GDALFillRaster( GDALRasterBandH hBand,
                           double dfRealValue, double dfImaginaryValue );
 CPLErr CPL_DLL CPL_STDCALL
-GDALComputeBandStats( GDALRasterBandH hBand, int nSampleStep, 
-                             double *pdfMean, double *pdfStdDev, 
+GDALComputeBandStats( GDALRasterBandH hBand, int nSampleStep,
+                             double *pdfMean, double *pdfStdDev,
                              GDALProgressFunc pfnProgress,
                              void *pProgressData );
-CPLErr CPL_DLL  GDALOverviewMagnitudeCorrection( GDALRasterBandH hBaseBand, 
-                                        int nOverviewCount, 
-                                        GDALRasterBandH *pahOverviews, 
-                                        GDALProgressFunc pfnProgress, 
+CPLErr CPL_DLL  GDALOverviewMagnitudeCorrection( GDALRasterBandH hBaseBand,
+                                        int nOverviewCount,
+                                        GDALRasterBandH *pahOverviews,
+                                        GDALProgressFunc pfnProgress,
                                         void *pProgressData );
 
-GDALRasterAttributeTableH CPL_DLL CPL_STDCALL GDALGetDefaultRAT( 
+GDALRasterAttributeTableH CPL_DLL CPL_STDCALL GDALGetDefaultRAT(
     GDALRasterBandH hBand );
-CPLErr CPL_DLL CPL_STDCALL GDALSetDefaultRAT( GDALRasterBandH, 
+CPLErr CPL_DLL CPL_STDCALL GDALSetDefaultRAT( GDALRasterBandH,
                                               GDALRasterAttributeTableH );
 CPLErr CPL_DLL CPL_STDCALL GDALAddDerivedBandPixelFunc( const char *pszName,
                                     GDALDerivedPixelFunc pfnPixelFunc );
 
 GDALRasterBandH CPL_DLL CPL_STDCALL GDALGetMaskBand( GDALRasterBandH hBand );
 int CPL_DLL CPL_STDCALL GDALGetMaskFlags( GDALRasterBandH hBand );
-CPLErr CPL_DLL CPL_STDCALL 
+CPLErr CPL_DLL CPL_STDCALL
                        GDALCreateMaskBand( GDALRasterBandH hBand, int nFlags );
 
 #define GMF_ALL_VALID     0x01
@@ -773,28 +824,31 @@ CPLErr CPL_DLL CPL_STDCALL
 /*     GDALAsyncReader                                                  */
 /* ==================================================================== */
 
-GDALAsyncStatusType CPL_DLL CPL_STDCALL 
+GDALAsyncStatusType CPL_DLL CPL_STDCALL
 GDALARGetNextUpdatedRegion(GDALAsyncReaderH hARIO, double dfTimeout,
-                         int* pnXBufOff, int* pnYBufOff, 
+                         int* pnXBufOff, int* pnYBufOff,
                          int* pnXBufSize, int* pnYBufSize );
 int CPL_DLL CPL_STDCALL GDALARLockBuffer(GDALAsyncReaderH hARIO,
                                         double dfTimeout);
-void CPL_DLL CPL_STDCALL GDALARUnlockBuffer(GDALAsyncReaderH hARIO); 
+void CPL_DLL CPL_STDCALL GDALARUnlockBuffer(GDALAsyncReaderH hARIO);
 
 /* -------------------------------------------------------------------- */
 /*      Helper functions.                                               */
 /* -------------------------------------------------------------------- */
-int CPL_DLL CPL_STDCALL GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, 
+int CPL_DLL CPL_STDCALL GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv,
                                          int nOptions );
 void CPL_DLL CPL_STDCALL GDALSwapWords( void *pData, int nWordSize, int nWordCount,
                             int nWordSkip );
-void CPL_DLL CPL_STDCALL 
-    GDALCopyWords( void * pSrcData, GDALDataType eSrcType, int nSrcPixelOffset,
+void CPL_DLL CPL_STDCALL GDALSwapWordsEx( void *pData, int nWordSize, size_t nWordCount,
+                                  int nWordSkip );
+
+void CPL_DLL CPL_STDCALL
+    GDALCopyWords( const void * pSrcData, GDALDataType eSrcType, int nSrcPixelOffset,
                    void * pDstData, GDALDataType eDstType, int nDstPixelOffset,
                    int nWordCount );
 
-void CPL_DLL 
-GDALCopyBits( const GByte *pabySrcData, int nSrcOffset, int nSrcStep, 
+void CPL_DLL
+GDALCopyBits( const GByte *pabySrcData, int nSrcOffset, int nSrcStep,
               GByte *pabyDstData, int nDstOffset, int nDstStep,
               int nBitCount, int nStepCount );
 
@@ -809,7 +863,7 @@ int CPL_DLL CPL_STDCALL GDALReadTabFile( const char *, double *, char **,
                                          int *, GDAL_GCP ** );
 int CPL_DLL CPL_STDCALL GDALLoadOziMapFile( const char *, double *, char **,
                                             int *, GDAL_GCP ** );
-int CPL_DLL CPL_STDCALL GDALReadOziMapFile( const char * ,  double *,
+int CPL_DLL CPL_STDCALL GDALReadOziMapFile( const char *,  double *,
                                             char **, int *, GDAL_GCP ** );
 
 const char CPL_DLL * CPL_STDCALL GDALDecToDMS( double, const char *, int );
@@ -836,7 +890,7 @@ int CPL_DLL CPL_STDCALL GDALCheckVersion( int nVersionMajor, int nVersionMinor,
 
 #endif
 
-typedef struct { 
+typedef struct {
     double      dfLINE_OFF;
     double      dfSAMP_OFF;
     double      dfLAT_OFF;
@@ -853,7 +907,7 @@ typedef struct {
     double      adfLINE_DEN_COEFF[20];
     double      adfSAMP_NUM_COEFF[20];
     double      adfSAMP_DEN_COEFF[20];
-    
+
     double	dfMIN_LONG;
     double      dfMIN_LAT;
     double      dfMAX_LONG;
@@ -871,19 +925,19 @@ int CPL_DLL CPL_STDCALL GDALExtractRPCInfo( char **, GDALRPCInfo * );
 typedef struct
 {
     /*! gray, red, cyan or hue */
-    short      c1;      
+    short      c1;
 
-    /*! green, magenta, or lightness */    
-    short      c2;      
+    /*! green, magenta, or lightness */
+    short      c2;
 
     /*! blue, yellow, or saturation */
-    short      c3;      
+    short      c3;
 
     /*! alpha or blackband */
-    short      c4;      
+    short      c4;
 } GDALColorEntry;
 
-GDALColorTableH CPL_DLL CPL_STDCALL GDALCreateColorTable( GDALPaletteInterp );
+GDALColorTableH CPL_DLL CPL_STDCALL GDALCreateColorTable( GDALPaletteInterp ) CPL_WARN_UNUSED_RESULT;
 void CPL_DLL CPL_STDCALL GDALDestroyColorTable( GDALColorTableH );
 GDALColorTableH CPL_DLL CPL_STDCALL GDALCloneColorTable( GDALColorTableH );
 GDALPaletteInterp CPL_DLL CPL_STDCALL GDALGetPaletteInterpretation( GDALColorTableH );
@@ -891,7 +945,7 @@ int CPL_DLL CPL_STDCALL GDALGetColorEntryCount( GDALColorTableH );
 const GDALColorEntry CPL_DLL * CPL_STDCALL GDALGetColorEntry( GDALColorTableH, int );
 int CPL_DLL CPL_STDCALL GDALGetColorEntryAsRGB( GDALColorTableH, int, GDALColorEntry *);
 void CPL_DLL CPL_STDCALL GDALSetColorEntry( GDALColorTableH, int, const GDALColorEntry * );
-void CPL_DLL CPL_STDCALL GDALCreateColorRamp( GDALColorTableH hTable, 
+void CPL_DLL CPL_STDCALL GDALCreateColorRamp( GDALColorTableH hTable,
             int nStartIndex, const GDALColorEntry *psStartColor,
             int nEndIndex, const GDALColorEntry *psEndColor );
 
@@ -901,14 +955,14 @@ void CPL_DLL CPL_STDCALL GDALCreateColorRamp( GDALColorTableH hTable,
 
 /** Field type of raster attribute table */
 typedef enum {
-    /*! Integer field */	   	   GFT_Integer , 
+    /*! Integer field */	   	   GFT_Integer,
     /*! Floating point (double) field */   GFT_Real,
     /*! String field */                    GFT_String
 } GDALRATFieldType;
 
 /** Field usage of raster attribute table */
 typedef enum {
-    /*! General purpose field. */          GFU_Generic = 0,  
+    /*! General purpose field. */          GFU_Generic = 0,
     /*! Histogram pixel count */           GFU_PixelCount = 1,
     /*! Class name */                      GFU_Name = 2,
     /*! Class range minimum */             GFU_Min = 3,
@@ -929,30 +983,30 @@ typedef enum {
     /*! Maximum GFU value */               GFU_MaxCount
 } GDALRATFieldUsage;
 
-GDALRasterAttributeTableH CPL_DLL CPL_STDCALL 
-                                           GDALCreateRasterAttributeTable(void);
+GDALRasterAttributeTableH CPL_DLL CPL_STDCALL
+                                           GDALCreateRasterAttributeTable(void) CPL_WARN_UNUSED_RESULT;
 void CPL_DLL CPL_STDCALL GDALDestroyRasterAttributeTable(
     GDALRasterAttributeTableH );
 
 int CPL_DLL CPL_STDCALL GDALRATGetColumnCount( GDALRasterAttributeTableH );
 
-const char CPL_DLL * CPL_STDCALL GDALRATGetNameOfCol( 
+const char CPL_DLL * CPL_STDCALL GDALRATGetNameOfCol(
     GDALRasterAttributeTableH, int );
-GDALRATFieldUsage CPL_DLL CPL_STDCALL GDALRATGetUsageOfCol( 
+GDALRATFieldUsage CPL_DLL CPL_STDCALL GDALRATGetUsageOfCol(
     GDALRasterAttributeTableH, int );
-GDALRATFieldType CPL_DLL CPL_STDCALL GDALRATGetTypeOfCol( 
+GDALRATFieldType CPL_DLL CPL_STDCALL GDALRATGetTypeOfCol(
     GDALRasterAttributeTableH, int );
 
-int CPL_DLL CPL_STDCALL GDALRATGetColOfUsage( GDALRasterAttributeTableH, 
+int CPL_DLL CPL_STDCALL GDALRATGetColOfUsage( GDALRasterAttributeTableH,
                                               GDALRATFieldUsage );
 int CPL_DLL CPL_STDCALL GDALRATGetRowCount( GDALRasterAttributeTableH );
 
-const char CPL_DLL * CPL_STDCALL GDALRATGetValueAsString( 
-    GDALRasterAttributeTableH, int ,int);
-int CPL_DLL CPL_STDCALL GDALRATGetValueAsInt( 
-    GDALRasterAttributeTableH, int ,int);
-double CPL_DLL CPL_STDCALL GDALRATGetValueAsDouble( 
-    GDALRasterAttributeTableH, int ,int);
+const char CPL_DLL * CPL_STDCALL GDALRATGetValueAsString(
+    GDALRasterAttributeTableH, int, int);
+int CPL_DLL CPL_STDCALL GDALRATGetValueAsInt(
+    GDALRasterAttributeTableH, int, int);
+double CPL_DLL CPL_STDCALL GDALRATGetValueAsDouble(
+    GDALRasterAttributeTableH, int, int);
 
 void CPL_DLL CPL_STDCALL GDALRATSetValueAsString( GDALRasterAttributeTableH, int, int,
                                                   const char * );
@@ -963,36 +1017,36 @@ void CPL_DLL CPL_STDCALL GDALRATSetValueAsDouble( GDALRasterAttributeTableH, int
 
 int CPL_DLL CPL_STDCALL GDALRATChangesAreWrittenToFile( GDALRasterAttributeTableH hRAT );
 
-CPLErr CPL_DLL CPL_STDCALL GDALRATValuesIOAsDouble( GDALRasterAttributeTableH hRAT, GDALRWFlag eRWFlag, 
+CPLErr CPL_DLL CPL_STDCALL GDALRATValuesIOAsDouble( GDALRasterAttributeTableH hRAT, GDALRWFlag eRWFlag,
                                         int iField, int iStartRow, int iLength, double *pdfData );
-CPLErr CPL_DLL CPL_STDCALL GDALRATValuesIOAsInteger( GDALRasterAttributeTableH hRAT, GDALRWFlag eRWFlag, 
+CPLErr CPL_DLL CPL_STDCALL GDALRATValuesIOAsInteger( GDALRasterAttributeTableH hRAT, GDALRWFlag eRWFlag,
                                         int iField, int iStartRow, int iLength, int *pnData);
-CPLErr CPL_DLL CPL_STDCALL GDALRATValuesIOAsString( GDALRasterAttributeTableH hRAT, GDALRWFlag eRWFlag, 
+CPLErr CPL_DLL CPL_STDCALL GDALRATValuesIOAsString( GDALRasterAttributeTableH hRAT, GDALRWFlag eRWFlag,
                                         int iField, int iStartRow, int iLength, char **papszStrList);
 
-void CPL_DLL CPL_STDCALL GDALRATSetRowCount( GDALRasterAttributeTableH, 
+void CPL_DLL CPL_STDCALL GDALRATSetRowCount( GDALRasterAttributeTableH,
                                              int );
-CPLErr CPL_DLL CPL_STDCALL GDALRATCreateColumn( GDALRasterAttributeTableH, 
-                                                const char *, 
-                                                GDALRATFieldType, 
+CPLErr CPL_DLL CPL_STDCALL GDALRATCreateColumn( GDALRasterAttributeTableH,
+                                                const char *,
+                                                GDALRATFieldType,
                                                 GDALRATFieldUsage );
-CPLErr CPL_DLL CPL_STDCALL GDALRATSetLinearBinning( GDALRasterAttributeTableH, 
+CPLErr CPL_DLL CPL_STDCALL GDALRATSetLinearBinning( GDALRasterAttributeTableH,
                                                     double, double );
-int CPL_DLL CPL_STDCALL GDALRATGetLinearBinning( GDALRasterAttributeTableH, 
+int CPL_DLL CPL_STDCALL GDALRATGetLinearBinning( GDALRasterAttributeTableH,
                                                  double *, double * );
 CPLErr CPL_DLL CPL_STDCALL GDALRATInitializeFromColorTable(
     GDALRasterAttributeTableH, GDALColorTableH );
 GDALColorTableH CPL_DLL CPL_STDCALL GDALRATTranslateToColorTable(
     GDALRasterAttributeTableH, int nEntryCount );
-void CPL_DLL CPL_STDCALL GDALRATDumpReadable( GDALRasterAttributeTableH, 
+void CPL_DLL CPL_STDCALL GDALRATDumpReadable( GDALRasterAttributeTableH,
                                               FILE * );
-GDALRasterAttributeTableH CPL_DLL CPL_STDCALL 
+GDALRasterAttributeTableH CPL_DLL CPL_STDCALL
     GDALRATClone( GDALRasterAttributeTableH );
 
-void CPL_DLL* CPL_STDCALL 
-    GDALRATSerializeJSON( GDALRasterAttributeTableH );
+void CPL_DLL* CPL_STDCALL
+    GDALRATSerializeJSON( GDALRasterAttributeTableH ) CPL_WARN_UNUSED_RESULT;
 
-int CPL_DLL CPL_STDCALL GDALRATGetRowOfValue( GDALRasterAttributeTableH , double );
+int CPL_DLL CPL_STDCALL GDALRATGetRowOfValue( GDALRasterAttributeTableH, double );
 
 
 /* ==================================================================== */
@@ -1025,7 +1079,7 @@ CPLVirtualMem CPL_DLL* GDALDatasetGetVirtualMem( GDALDatasetH hDS,
                                                  size_t nCacheSize,
                                                  size_t nPageSizeHint,
                                                  int bSingleThreadUsage,
-                                                 char **papszOptions );
+                                                 char **papszOptions ) CPL_WARN_UNUSED_RESULT;
 
 CPLVirtualMem CPL_DLL* GDALRasterBandGetVirtualMem( GDALRasterBandH hBand,
                                          GDALRWFlag eRWFlag,
@@ -1038,19 +1092,19 @@ CPLVirtualMem CPL_DLL* GDALRasterBandGetVirtualMem( GDALRasterBandH hBand,
                                          size_t nCacheSize,
                                          size_t nPageSizeHint,
                                          int bSingleThreadUsage,
-                                         char **papszOptions );
+                                         char **papszOptions ) CPL_WARN_UNUSED_RESULT;
 
 CPLVirtualMem CPL_DLL* GDALGetVirtualMemAuto( GDALRasterBandH hBand,
                                               GDALRWFlag eRWFlag,
                                               int *pnPixelSpace,
                                               GIntBig *pnLineSpace,
-                                              char **papszOptions );
+                                              char **papszOptions ) CPL_WARN_UNUSED_RESULT;
 
 typedef enum
 {
     /*! Tile Interleaved by Pixel: tile (0,0) with internal band interleaved by pixel organization, tile (1, 0), ...  */
     GTO_TIP,
-    /*! Band Interleaved by Tile : tile (0,0) of first band, tile (0,0) of second band, ... tile (1,0) of fisrt band, tile (1,0) of second band, ... */
+    /*! Band Interleaved by Tile : tile (0,0) of first band, tile (0,0) of second band, ... tile (1,0) of first band, tile (1,0) of second band, ... */
     GTO_BIT,
     /*! Band SeQuential : all the tiles of first band, all the tiles of following band... */
     GTO_BSQ
@@ -1066,7 +1120,7 @@ CPLVirtualMem CPL_DLL* GDALDatasetGetTiledVirtualMem( GDALDatasetH hDS,
                                                       GDALTileOrganization eTileOrganization,
                                                       size_t nCacheSize,
                                                       int bSingleThreadUsage,
-                                                      char **papszOptions );
+                                                      char **papszOptions ) CPL_WARN_UNUSED_RESULT;
 
 CPLVirtualMem CPL_DLL* GDALRasterBandGetTiledVirtualMem( GDALRasterBandH hBand,
                                                          GDALRWFlag eRWFlag,
@@ -1076,14 +1130,23 @@ CPLVirtualMem CPL_DLL* GDALRasterBandGetTiledVirtualMem( GDALRasterBandH hBand,
                                                          GDALDataType eBufType,
                                                          size_t nCacheSize,
                                                          int bSingleThreadUsage,
-                                                         char **papszOptions );
+                                                         char **papszOptions ) CPL_WARN_UNUSED_RESULT;
+
+/* ==================================================================== */
+/*      VRTPansharpenedDataset class.                                   */
+/* ==================================================================== */
+
+GDALDatasetH CPL_DLL GDALCreatePansharpenedVRT( const char* pszXML,
+                                            GDALRasterBandH hPanchroBand,
+                                            int nInputSpectralBands,
+                                            GDALRasterBandH* pahInputSpectralBands ) CPL_WARN_UNUSED_RESULT;
 
 /* =================================================================== */
 /*      Misc API                                                        */
 /* ==================================================================== */
 
 CPLXMLNode CPL_DLL* GDALGetJPEG2000Structure(const char* pszFilename,
-                                             char** papszOptions);
+                                             char** papszOptions) CPL_WARN_UNUSED_RESULT;
 
 CPL_C_END
 
diff --git a/gcore/gdal_frmts.h b/gcore/gdal_frmts.h
index 261f241..44d06f8 100644
--- a/gcore/gdal_frmts.h
+++ b/gcore/gdal_frmts.h
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: gdal_frmts.h 28859 2015-04-07 08:40:10Z rouault $
+ * $Id: gdal_frmts.h 33351 2016-02-03 15:52:38Z goatbar $
  *
  * Project:  GDAL
- * Purpose:  Prototypes for all format specific driver initializations.
+ * Purpose:  Prototypes for all format specific driver initialization.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -34,7 +34,6 @@
 #include "cpl_port.h"
 
 CPL_C_START
-void CPL_DLL GDALRegister_GDB(void);
 void CPL_DLL GDALRegister_GTiff(void);
 void CPL_DLL GDALRegister_GXF(void);
 void CPL_DLL GDALRegister_OGDI(void);
@@ -42,7 +41,7 @@ void CPL_DLL GDALRegister_HFA(void);
 void CPL_DLL GDALRegister_AAIGrid(void);
 void CPL_DLL GDALRegister_GRASSASCIIGrid(void);
 void CPL_DLL GDALRegister_AIGrid(void);
-void CPL_DLL GDALRegister_AIGrid2(void);
+// void CPL_DLL GDALRegister_AIGrid2(void);
 void CPL_DLL GDALRegister_CEOS(void);
 void CPL_DLL GDALRegister_SAR_CEOS(void);
 void CPL_DLL GDALRegister_SDTS(void);
@@ -143,7 +142,6 @@ void CPL_DLL GDALRegister_SRP(void);
 void CPL_DLL GDALRegister_COASP(void);
 void CPL_DLL GDALRegister_BLX(void);
 void CPL_DLL GDALRegister_LCP(void);
-void CPL_DLL GDALRegister_PGCHIP(void);
 void CPL_DLL GDALRegister_TMS(void);
 void CPL_DLL GDALRegister_EIR(void);
 void CPL_DLL GDALRegister_GEOR(void);
@@ -182,6 +180,12 @@ void CPL_DLL GDALRegister_KRO(void);
 void CPL_DLL GDALRegister_KEA(void);
 void CPL_DLL GDALRegister_ROIPAC(void);
 void CPL_DLL GDALRegister_PLMOSAIC(void);
+void CPL_DLL GDALRegister_CALS(void);
+void CPL_DLL GDALRegister_ISCE(void);
+void CPL_DLL GDALRegister_WMTS(void);
+void CPL_DLL GDALRegister_SAFE(void);
+void CPL_DLL GDALRegister_SENTINEL2(void);
+void CPL_DLL GDALRegister_mrf(void);
 CPL_C_END
 
 #endif /* ndef GDAL_FRMTS_H_INCLUDED */
diff --git a/gcore/gdal_mdreader.cpp b/gcore/gdal_mdreader.cpp
index afb853e..8a41ce4 100644
--- a/gcore/gdal_mdreader.cpp
+++ b/gcore/gdal_mdreader.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: gdal_mdreader.cpp 31770 2015-11-25 23:01:18Z rouault $
+ * $Id: gdal_mdreader.cpp 33739 2016-03-18 13:12:40Z goatbar $
  *
  * Project:  GDAL Core
- * Purpose:  Read metadata (mainly the remote sensing imagery) from files of 
+ * Purpose:  Read metadata (mainly the remote sensing imagery) from files of
  *           different providers like DigitalGlobe, GeoEye etc.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  * Author:   Dmitry Baryshnikov, polimax at mail.ru
@@ -30,31 +30,31 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
- 
-#include "gdal_mdreader.h"
+
 #include "cpl_string.h"
 #include "cplkeywordparser.h"
+#include "gdal_mdreader.h"
 
 //readers
+#include "mdreader/reader_alos.h"
 #include "mdreader/reader_digital_globe.h"
+#include "mdreader/reader_eros.h"
 #include "mdreader/reader_geo_eye.h"
+#include "mdreader/reader_kompsat.h"
+#include "mdreader/reader_landsat.h"
 #include "mdreader/reader_orb_view.h"
 #include "mdreader/reader_pleiades.h"
+#include "mdreader/reader_rapid_eye.h"
 #include "mdreader/reader_rdk1.h"
-#include "mdreader/reader_landsat.h"
 #include "mdreader/reader_spot.h"
-#include "mdreader/reader_rapid_eye.h"
-#include "mdreader/reader_alos.h"
-#include "mdreader/reader_eros.h"
-#include "mdreader/reader_kompsat.h"
 
-CPL_CVSID("$Id: gdal_mdreader.cpp 31770 2015-11-25 23:01:18Z rouault $");
+CPL_CVSID("$Id: gdal_mdreader.cpp 33739 2016-03-18 13:12:40Z goatbar $");
 
 /**
  * The RPC parameters names
  */
 
-static const char *apszRPCTXTSingleValItems[] =
+static const char * const apszRPCTXTSingleValItems[] =
 {
     RPC_LINE_OFF,
     RPC_SAMP_OFF,
@@ -69,7 +69,7 @@ static const char *apszRPCTXTSingleValItems[] =
     NULL
 };
 
-static const char *apszRPCTXT20ValItems[] =
+static const char * const apszRPCTXT20ValItems[] =
 {
     RPC_LINE_NUM_COEFF,
     RPC_LINE_DEN_COEFF,
@@ -80,11 +80,10 @@ static const char *apszRPCTXT20ValItems[] =
 
 /**
  * GDALMDReaderManager()
- */  
-GDALMDReaderManager::GDALMDReaderManager()
-{
-    m_pReader = NULL;
-}
+ */
+GDALMDReaderManager::GDALMDReaderManager() :
+    m_pReader(NULL)
+{}
 
 /**
  * ~GDALMDReaderManager()
@@ -177,16 +176,15 @@ GDALMDReaderBase* GDALMDReaderManager::GetReader(const char *pszPath,
 
 /**
  * GDALMDReaderBase()
- */ 
-GDALMDReaderBase::GDALMDReaderBase(CPL_UNUSED const char *pszPath,
-                                   CPL_UNUSED char **papszSiblingFiles)
-{
-    m_bIsMetadataLoad = false;    
-    m_papszIMDMD = NULL;
-    m_papszRPCMD = NULL;
-    m_papszIMAGERYMD = NULL;
-    m_papszDEFAULTMD = NULL;    
-} 
+ */
+GDALMDReaderBase::GDALMDReaderBase( const char * /* pszPath */,
+                                    char ** /* papszSiblingFiles */ ) :
+    m_papszIMDMD(NULL),
+    m_papszRPCMD(NULL),
+    m_papszIMAGERYMD(NULL),
+    m_papszDEFAULTMD(NULL),
+    m_bIsMetadataLoad(false)
+{}
 
 /**
  * ~GDALMDReaderBase()
@@ -197,7 +195,7 @@ GDALMDReaderBase::~GDALMDReaderBase()
     CSLDestroy(m_papszRPCMD);
     CSLDestroy(m_papszIMAGERYMD);
     CSLDestroy(m_papszDEFAULTMD);
-} 
+}
 
 /**
  * GetMetadataItem()
@@ -208,12 +206,12 @@ char ** GDALMDReaderBase::GetMetadataDomain(const char *pszDomain)
     if(EQUAL(pszDomain, MD_DOMAIN_DEFAULT))
         return m_papszDEFAULTMD;
     else if(EQUAL(pszDomain, MD_DOMAIN_IMD))
-        return m_papszIMDMD;    
+        return m_papszIMDMD;
     else if(EQUAL(pszDomain, MD_DOMAIN_RPC))
-        return m_papszRPCMD;   
+        return m_papszRPCMD;
     else if(EQUAL(pszDomain, MD_DOMAIN_IMAGERY))
-        return m_papszIMAGERYMD;             
-    return NULL;    
+        return m_papszIMAGERYMD;
+    return NULL;
 }
 
 /**
@@ -229,21 +227,21 @@ void GDALMDReaderBase::LoadMetadata()
 /**
  * GetAcqisitionTimeFromString()
  */
-const time_t GDALMDReaderBase::GetAcquisitionTimeFromString(
-        const char* pszDateTime)
+time_t GDALMDReaderBase::GetAcquisitionTimeFromString(
+    const char* pszDateTime)
 {
     if(NULL == pszDateTime)
         return 0;
 
-    int iYear;
-    int iMonth;
-    int iDay;
-    int iHours;
-    int iMin;
-    int iSec;
+    int iYear = 0;
+    int iMonth = 0;
+    int iDay = 0;
+    int iHours = 0;
+    int iMin = 0;
+    int iSec = 0;
 
-    int r = sscanf ( pszDateTime, "%d-%d-%dT%d:%d:%d.%*dZ",
-                     &iYear, &iMonth, &iDay, &iHours, &iMin, &iSec);
+    const int r = sscanf ( pszDateTime, "%d-%d-%dT%d:%d:%d.%*dZ",
+                           &iYear, &iMonth, &iDay, &iHours, &iMin, &iSec);
 
     if (r != 6)
         return 0;
@@ -274,14 +272,14 @@ bool GDALMDReaderBase::FillMetadata(GDALMultiDomainMetadata* poMDMD)
 {
     if(NULL == poMDMD)
         return false;
-        
+
     LoadMetadata();
 
     SETMETADATA(poMDMD, m_papszIMDMD, MD_DOMAIN_IMD );
     SETMETADATA(poMDMD, m_papszRPCMD, MD_DOMAIN_RPC );
     SETMETADATA(poMDMD, m_papszIMAGERYMD, MD_DOMAIN_IMAGERY );
     SETMETADATA(poMDMD, m_papszDEFAULTMD, MD_DOMAIN_DEFAULT );
-    
+
     return true;
 }
 
@@ -418,23 +416,24 @@ char** GDALMDReaderBase::ReadXMLToList(CPLXMLNode* psNode, char** papszList,
 /**
  * GDALCheckFileHeader()
  */
-const bool GDALCheckFileHeader(const CPLString& soFilePath,
-                               const char * pszTestString, int nBufferSize)
+bool GDALCheckFileHeader(const CPLString& soFilePath,
+                         const char * pszTestString, int nBufferSize)
 {
     VSILFILE* fpL = VSIFOpenL( soFilePath, "r" );
     if( fpL == NULL )
         return false;
     char *pBuffer = new char[nBufferSize + 1];
-    pBuffer[nBufferSize] = 0;
-    int nReadBytes = (int) VSIFReadL( pBuffer, 1, nBufferSize, fpL );
-    VSIFCloseL(fpL);
+    pBuffer[nBufferSize] = '\0';
+    const int nReadBytes = static_cast<int>(
+        VSIFReadL( pBuffer, 1, nBufferSize, fpL ) );
+    CPL_IGNORE_RET_VAL(VSIFCloseL(fpL));
     if(nReadBytes == 0)
     {
         delete [] pBuffer;
         return false;
     }
 
-    bool bResult = strstr(pBuffer, pszTestString) != NULL;
+    const bool bResult = strstr(pBuffer, pszTestString) != NULL;
     delete [] pBuffer;
 
     return bResult;
@@ -462,7 +461,7 @@ CPLString CPLStrip(const CPLString& sString, const char cChar)
 
     if(dCopyCount == 0)
         return CPLString();
-    
+
     return sString.substr(dCopyFrom, dCopyCount);
 }
 
@@ -481,7 +480,7 @@ CPLString CPLStripQuotes(const CPLString& sString)
 /*                          GDALLoadRPBFile()                           */
 /************************************************************************/
 
-static const char *apszRPBMap[] = {
+static const char * const apszRPBMap[] = {
     apszRPCTXTSingleValItems[0], "IMAGE.lineOffset",
     apszRPCTXTSingleValItems[1], "IMAGE.sampOffset",
     apszRPCTXTSingleValItems[2], "IMAGE.latOffset",
@@ -506,27 +505,25 @@ char **GDALLoadRPBFile( const CPLString& soFilePath )
 /* -------------------------------------------------------------------- */
 /*      Read file and parse.                                            */
 /* -------------------------------------------------------------------- */
-    CPLKeywordParser oParser;
-
     VSILFILE *fp = VSIFOpenL( soFilePath, "r" );
 
     if( fp == NULL )
         return NULL;
 
+    CPLKeywordParser oParser;
     if( !oParser.Ingest( fp ) )
     {
-        VSIFCloseL( fp );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
         return NULL;
     }
 
-    VSIFCloseL( fp );
+    CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
 
 /* -------------------------------------------------------------------- */
 /*      Extract RPC information, in a GDAL "standard" metadata format.  */
 /* -------------------------------------------------------------------- */
-    int i;
     char **papszMD = NULL;
-    for( i = 0; apszRPBMap[i] != NULL; i += 2 )
+    for( int i = 0; apszRPBMap[i] != NULL; i += 2 )
     {
         const char *pszRPBVal = oParser.GetKeyword( apszRPBMap[i+1] );
         CPLString osAdjVal;
@@ -545,9 +542,7 @@ char **GDALLoadRPBFile( const CPLString& soFilePath )
         else
         {
             // strip out commas and turn newlines into spaces.
-            int j;
-
-            for( j = 0; pszRPBVal[j] != '\0'; j++ )
+            for( int j = 0; pszRPBVal[j] != '\0'; j++ )
             {
                 switch( pszRPBVal[j] )
                 {
@@ -587,7 +582,10 @@ char ** GDALLoadRPCFile( const CPLString& soFilePath )
 /* -------------------------------------------------------------------- */
 /*      Read file and parse.                                            */
 /* -------------------------------------------------------------------- */
-    char **papszLines = CSLLoad2( soFilePath, 100, 100, NULL );
+    // 100 lines would be enough, but some .rpc files have CR CR LF end of
+    // lines, which result in a blank line to be recognized, so accept up
+    // to 200 lines (#6341)
+    char **papszLines = CSLLoad2( soFilePath, 200, 100, NULL );
     if(!papszLines)
         return NULL;
 
@@ -622,7 +620,8 @@ char ** GDALLoadRPCFile( const CPLString& soFilePath )
         {
             CPLString soRPBMapItem;
             soRPBMapItem.Printf("%s_%d", apszRPBMap[i], j);
-            const char *pszRPBVal = CSLFetchNameValue(papszLines, soRPBMapItem.c_str() );
+            const char *pszRPBVal =
+                CSLFetchNameValue(papszLines, soRPBMapItem.c_str() );
             if( pszRPBVal == NULL )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
@@ -676,9 +675,8 @@ CPLErr GDALWriteRPCTXTFile( const char *pszFilename, char **papszMD )
 /* -------------------------------------------------------------------- */
 /*      Write RPC values from our RPC metadata.                         */
 /* -------------------------------------------------------------------- */
-    int i;
-
-    for( i = 0; apszRPCTXTSingleValItems[i] != NULL; i ++ )
+    bool bOK = true;
+    for( int i = 0; apszRPCTXTSingleValItems[i] != NULL; i ++ )
     {
         const char *pszRPCVal = CSLFetchNameValue( papszMD, apszRPCTXTSingleValItems[i] );
         if( pszRPCVal == NULL )
@@ -686,16 +684,16 @@ CPLErr GDALWriteRPCTXTFile( const char *pszFilename, char **papszMD )
             CPLError( CE_Failure, CPLE_AppDefined,
                       "%s field missing in metadata, %s file not written.",
                       apszRPCTXTSingleValItems[i], osRPCFilename.c_str() );
-            VSIFCloseL( fp );
+            CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
             VSIUnlink( osRPCFilename );
             return CE_Failure;
         }
 
-        VSIFPrintfL( fp, "%s: %s\n", apszRPCTXTSingleValItems[i], pszRPCVal );
+        bOK &= VSIFPrintfL( fp, "%s: %s\n", apszRPCTXTSingleValItems[i], pszRPCVal ) > 0;
     }
 
 
-    for( i = 0; apszRPCTXT20ValItems[i] != NULL; i ++ )
+    for( int i = 0; apszRPCTXT20ValItems[i] != NULL; i ++ )
     {
         const char *pszRPCVal = CSLFetchNameValue( papszMD, apszRPCTXT20ValItems[i] );
         if( pszRPCVal == NULL )
@@ -703,7 +701,7 @@ CPLErr GDALWriteRPCTXTFile( const char *pszFilename, char **papszMD )
             CPLError( CE_Failure, CPLE_AppDefined,
                       "%s field missing in metadata, %s file not written.",
                       apszRPCTXTSingleValItems[i], osRPCFilename.c_str() );
-            VSIFCloseL( fp );
+            CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
             VSIUnlink( osRPCFilename );
             return CE_Failure;
         }
@@ -717,26 +715,25 @@ CPLErr GDALWriteRPCTXTFile( const char *pszFilename, char **papszMD )
                       "%s field is corrupt (not 20 values), %s file not written.\n%s = %s",
                       apszRPCTXT20ValItems[i], osRPCFilename.c_str(),
                       apszRPCTXT20ValItems[i], pszRPCVal );
-            VSIFCloseL( fp );
+            CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
             VSIUnlink( osRPCFilename );
             CSLDestroy( papszItems );
             return CE_Failure;
         }
 
-        int j;
-
-        for( j = 0; j < 20; j++ )
+        for( int j = 0; j < 20; j++ )
         {
-            VSIFPrintfL( fp, "%s_%d: %s\n", apszRPCTXT20ValItems[i], j+1,
-                         papszItems[j] );
+            bOK &= VSIFPrintfL( fp, "%s_%d: %s\n", apszRPCTXT20ValItems[i], j+1,
+                         papszItems[j] ) > 0;
         }
         CSLDestroy( papszItems );
     }
 
 
-    VSIFCloseL( fp );
+    if( VSIFCloseL( fp ) != 0 )
+        bOK = false;
 
-    return CE_None;
+    return bOK ? CE_None : CE_Failure;
 }
 
 /************************************************************************/
@@ -748,7 +745,6 @@ CPLErr GDALWriteRPBFile( const char *pszFilename, char **papszMD )
 {
     CPLString osRPBFilename = CPLResetExtension( pszFilename, "RPB" );
 
-
 /* -------------------------------------------------------------------- */
 /*      Read file and parse.                                            */
 /* -------------------------------------------------------------------- */
@@ -765,19 +761,17 @@ CPLErr GDALWriteRPBFile( const char *pszFilename, char **papszMD )
 /* -------------------------------------------------------------------- */
 /*      Write the prefix information.                                   */
 /* -------------------------------------------------------------------- */
-    VSIFPrintfL( fp, "%s", "satId = \"QB02\";\n" );
-    VSIFPrintfL( fp, "%s", "bandId = \"P\";\n" );
-    VSIFPrintfL( fp, "%s", "SpecId = \"RPC00B\";\n" );
-    VSIFPrintfL( fp, "%s", "BEGIN_GROUP = IMAGE\n" );
-    VSIFPrintfL( fp, "%s", "\terrBias = 0.0;\n" );
-    VSIFPrintfL( fp, "%s", "\terrRand = 0.0;\n" );
+    bool bOK = VSIFPrintfL( fp, "%s", "satId = \"QB02\";\n" ) > 0;
+    bOK &= VSIFPrintfL( fp, "%s", "bandId = \"P\";\n" ) > 0;
+    bOK &= VSIFPrintfL( fp, "%s", "SpecId = \"RPC00B\";\n" ) > 0;
+    bOK &= VSIFPrintfL( fp, "%s", "BEGIN_GROUP = IMAGE\n" ) > 0;
+    bOK &= VSIFPrintfL( fp, "%s", "\terrBias = 0.0;\n" ) > 0;
+    bOK &= VSIFPrintfL( fp, "%s", "\terrRand = 0.0;\n" ) > 0;
 
 /* -------------------------------------------------------------------- */
 /*      Write RPC values from our RPC metadata.                         */
 /* -------------------------------------------------------------------- */
-    int i;
-
-    for( i = 0; apszRPBMap[i] != NULL; i += 2 )
+    for( int i = 0; apszRPBMap[i] != NULL; i += 2 )
     {
         const char *pszRPBVal = CSLFetchNameValue( papszMD, apszRPBMap[i] );
         const char *pszRPBTag;
@@ -787,24 +781,24 @@ CPLErr GDALWriteRPBFile( const char *pszFilename, char **papszMD )
             CPLError( CE_Failure, CPLE_AppDefined,
                       "%s field missing in metadata, %s file not written.",
                       apszRPBMap[i], osRPBFilename.c_str() );
-            VSIFCloseL( fp );
+            CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
             VSIUnlink( osRPBFilename );
             return CE_Failure;
         }
 
         pszRPBTag = apszRPBMap[i+1];
-        if( EQUALN(pszRPBTag,"IMAGE.",6) )
+        if( STARTS_WITH_CI(pszRPBTag, "IMAGE.") )
             pszRPBTag += 6;
 
         if( strstr(apszRPBMap[i], "COEF" ) == NULL )
         {
-            VSIFPrintfL( fp, "\t%s = %s;\n", pszRPBTag, pszRPBVal );
+            bOK &= VSIFPrintfL( fp, "\t%s = %s;\n", pszRPBTag, pszRPBVal ) > 0;
         }
         else
         {
             // Reformat in brackets with commas over multiple lines.
 
-            VSIFPrintfL( fp, "\t%s = (\n", pszRPBTag );
+            bOK &= VSIFPrintfL( fp, "\t%s = (\n", pszRPBTag ) > 0;
 
             char **papszItems = CSLTokenizeStringComplex( pszRPBVal, " ,",
                                                           FALSE, FALSE );
@@ -812,23 +806,22 @@ CPLErr GDALWriteRPBFile( const char *pszFilename, char **papszMD )
             if( CSLCount(papszItems) != 20 )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
-                          "%s field is corrupt (not 20 values), %s file not written.\n%s = %s",
+                          "%s field is corrupt (not 20 values), %s file not "
+                          "written.\n%s = %s",
                           apszRPBMap[i], osRPBFilename.c_str(),
                           apszRPBMap[i], pszRPBVal );
-                VSIFCloseL( fp );
+                CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
                 VSIUnlink( osRPBFilename );
                 CSLDestroy( papszItems );
                 return CE_Failure;
             }
 
-            int j;
-
-            for( j = 0; j < 20; j++ )
+            for( int j = 0; j < 20; j++ )
             {
                 if( j < 19 )
-                    VSIFPrintfL( fp, "\t\t\t%s,\n", papszItems[j] );
+                    bOK &= VSIFPrintfL( fp, "\t\t\t%s,\n", papszItems[j] ) > 0;
                 else
-                    VSIFPrintfL( fp, "\t\t\t%s);\n", papszItems[j] );
+                    bOK &= VSIFPrintfL( fp, "\t\t\t%s);\n", papszItems[j] ) > 0;
             }
             CSLDestroy( papszItems );
         }
@@ -837,11 +830,12 @@ CPLErr GDALWriteRPBFile( const char *pszFilename, char **papszMD )
 /* -------------------------------------------------------------------- */
 /*      Write end part                                                  */
 /* -------------------------------------------------------------------- */
-    VSIFPrintfL( fp, "%s", "END_GROUP = IMAGE\n" );
-    VSIFPrintfL( fp, "END;\n" );
-    VSIFCloseL( fp );
+    bOK &= VSIFPrintfL( fp, "%s", "END_GROUP = IMAGE\n" ) > 0;
+    bOK &= VSIFPrintfL( fp, "END;\n" ) > 0;
+    if( VSIFCloseL( fp ) != 0 )
+        bOK = false;
 
-    return CE_None;
+    return bOK ? CE_None : CE_Failure;
 }
 
 /************************************************************************/
@@ -850,7 +844,7 @@ CPLErr GDALWriteRPBFile( const char *pszFilename, char **papszMD )
 /*      Translate AA version IMD file to R version.                     */
 /************************************************************************/
 
-static int GDAL_IMD_AA2R( char ***ppapszIMD )
+static bool GDAL_IMD_AA2R( char ***ppapszIMD )
 
 {
     char **papszIMD = *ppapszIMD;
@@ -861,14 +855,16 @@ static int GDAL_IMD_AA2R( char ***ppapszIMD )
     const char *pszValue = CSLFetchNameValue( papszIMD, "version" );
 
     if( pszValue == NULL )
-        return FALSE;
+        return false;
 
     if( EQUAL(pszValue,"\"R\"") )
-        return TRUE;
+        return true;
 
     if( !EQUAL(pszValue,"\"AA\"") )
     {
-        CPLDebug( "IMD", "The file is not the expected 'version = \"AA\"' format.\nProceeding, but file may be corrupted." );
+        CPLDebug( "IMD",
+                  "The file is not the expected 'version = \"AA\"' format.\n"
+                  "Proceeding, but file may be corrupted." );
     }
 
 /* -------------------------------------------------------------------- */
@@ -879,9 +875,7 @@ static int GDAL_IMD_AA2R( char ***ppapszIMD )
 /* -------------------------------------------------------------------- */
 /*      remove a bunch of fields.                                       */
 /* -------------------------------------------------------------------- */
-    int iKey;
-
-    static const char *apszToRemove[] = {
+    static const char * const apszToRemove[] = {
         "productCatalogId",
         "childCatalogId",
         "productType",
@@ -893,7 +887,7 @@ static int GDAL_IMD_AA2R( char ***ppapszIMD )
         "productGSD",
         NULL };
 
-    for( iKey = 0; apszToRemove[iKey] != NULL; iKey++ )
+    for( int iKey = 0; apszToRemove[iKey] != NULL; iKey++ )
     {
         int iTarget = CSLFindName( papszIMD, apszToRemove[iKey] );
         if( iTarget != -1 )
@@ -903,7 +897,7 @@ static int GDAL_IMD_AA2R( char ***ppapszIMD )
 /* -------------------------------------------------------------------- */
 /*      Replace various min/mean/max with just the mean.                */
 /* -------------------------------------------------------------------- */
-    static const char *keylist[] = {
+    static const char * const keylist[] = {
         "CollectedRowGSD",
         "CollectedColGSD",
         "SunAz",
@@ -915,13 +909,11 @@ static int GDAL_IMD_AA2R( char ***ppapszIMD )
         "OffNadirViewAngle",
         NULL };
 
-    for( iKey = 0; keylist[iKey] != NULL; iKey++ )
+    for( int iKey = 0; keylist[iKey] != NULL; iKey++ )
     {
         CPLString osTarget;
-        int       iTarget;
-
         osTarget.Printf( "IMAGE_1.min%s", keylist[iKey] );
-        iTarget = CSLFindName( papszIMD, osTarget );
+        int iTarget = CSLFindName( papszIMD, osTarget );
         if( iTarget != -1 )
             papszIMD = CSLRemoveStrings( papszIMD, iTarget, 1, NULL );
 
@@ -936,7 +928,6 @@ static int GDAL_IMD_AA2R( char ***ppapszIMD )
         {
             CPLString osValue = CSLFetchNameValue( papszIMD, osTarget );
             CPLString osLine;
-
             osTarget.Printf( "IMAGE_1.%c%s",
                              tolower(keylist[iKey][0]),
                              keylist[iKey]+1 );
@@ -949,7 +940,7 @@ static int GDAL_IMD_AA2R( char ***ppapszIMD )
     }
 
     *ppapszIMD = papszIMD;
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -973,11 +964,11 @@ char ** GDALLoadIMDFile( const CPLString& osFilePath )
 
     if( !oParser.Ingest( fp ) )
     {
-        VSIFCloseL( fp );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
         return NULL;
     }
 
-    VSIFCloseL( fp );
+    CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
 
 /* -------------------------------------------------------------------- */
 /*      Consider version changing.                                      */
@@ -1008,17 +999,16 @@ static void GDALWriteIMDMultiLine( VSILFILE *fp, const char *pszValue )
 {
     char **papszItems = CSLTokenizeStringComplex( pszValue, "(,) ",
                                                   FALSE, FALSE );
-    int nItemCount = CSLCount(papszItems);
-    int i;
+    const int nItemCount = CSLCount(papszItems);
 
-    VSIFPrintfL( fp, "(\n" );
+    CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "(\n" ));
 
-    for( i = 0; i < nItemCount; i++ )
+    for( int i = 0; i < nItemCount; i++ )
     {
         if( i == nItemCount-1 )
-            VSIFPrintfL( fp, "\t%s );\n", papszItems[i] );
+            CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "\t%s );\n", papszItems[i] ));
         else
-            VSIFPrintfL( fp, "\t%s,\n", papszItems[i] );
+            CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "\t%s,\n", papszItems[i] ));
     }
     CSLDestroy( papszItems );
 }
@@ -1050,14 +1040,15 @@ CPLErr GDALWriteIMDFile( const char *pszFilename, char **papszMD )
 /*      Loop through all values writing.                                */
 /* -------------------------------------------------------------------- */
 /* ==================================================================== */
-    int iKey;
     CPLString osCurSection;
+    bool bOK = true;
 
-    for( iKey = 0; papszMD[iKey] != NULL; iKey++ )
+    for( int iKey = 0; papszMD[iKey] != NULL; iKey++ )
     {
         char *pszRawKey = NULL;
         const char *pszValue = CPLParseNameValue( papszMD[iKey], &pszRawKey );
-        CPLString osKeySection, osKeyItem;
+        CPLString osKeySection;
+        CPLString osKeyItem;
         char *pszDot = strchr(pszRawKey,'.');
 
 /* -------------------------------------------------------------------- */
@@ -1079,10 +1070,10 @@ CPLErr GDALWriteIMDFile( const char *pszFilename, char **papszMD )
 /*      Close and/or start sections as needed.                          */
 /* -------------------------------------------------------------------- */
         if( osCurSection.size() && !EQUAL(osCurSection,osKeySection) )
-            VSIFPrintfL( fp, "END_GROUP = %s\n", osCurSection.c_str() );
+            bOK &= VSIFPrintfL( fp, "END_GROUP = %s\n", osCurSection.c_str() ) > 0;
 
         if( osKeySection.size() && !EQUAL(osCurSection,osKeySection) )
-            VSIFPrintfL( fp, "BEGIN_GROUP = %s\n", osKeySection.c_str() );
+            bOK &= VSIFPrintfL( fp, "BEGIN_GROUP = %s\n", osKeySection.c_str() ) > 0;
 
         osCurSection = osKeySection;
 
@@ -1090,12 +1081,12 @@ CPLErr GDALWriteIMDFile( const char *pszFilename, char **papszMD )
 /*      Print out simple item.                                          */
 /* -------------------------------------------------------------------- */
         if( osCurSection.size() )
-            VSIFPrintfL( fp, "\t%s = ", osKeyItem.c_str() );
+            bOK &= VSIFPrintfL( fp, "\t%s = ", osKeyItem.c_str() ) > 0;
         else
-            VSIFPrintfL( fp, "%s = ", osKeyItem.c_str() );
+            bOK &= VSIFPrintfL( fp, "%s = ", osKeyItem.c_str() ) > 0;
 
         if( pszValue[0] != '(' )
-            VSIFPrintfL( fp, "%s;\n", pszValue );
+            bOK &= VSIFPrintfL( fp, "%s;\n", pszValue ) > 0;
         else
             GDALWriteIMDMultiLine( fp, pszValue );
     }
@@ -1104,11 +1095,12 @@ CPLErr GDALWriteIMDFile( const char *pszFilename, char **papszMD )
 /*      Close off.                                                      */
 /* -------------------------------------------------------------------- */
     if( osCurSection.size() )
-        VSIFPrintfL( fp, "END_GROUP = %s\n", osCurSection.c_str() );
+        bOK &= VSIFPrintfL( fp, "END_GROUP = %s\n", osCurSection.c_str() ) > 0;
 
-    VSIFPrintfL( fp, "END;\n" );
+    bOK &= VSIFPrintfL( fp, "END;\n" ) > 0;
 
-    VSIFCloseL( fp );
+    if( VSIFCloseL( fp ) != 0 )
+        bOK = false;
 
-    return CE_None;
+    return bOK ? CE_None : CE_Failure;
 }
diff --git a/gcore/gdal_mdreader.h b/gcore/gdal_mdreader.h
index f060cae..2c69a56 100644
--- a/gcore/gdal_mdreader.h
+++ b/gcore/gdal_mdreader.h
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: gdal_mdreader.h 29190 2015-05-13 21:40:30Z bishop $
+ * $Id: gdal_mdreader.h 33694 2016-03-10 17:54:30Z goatbar $
  *
  * Project:  GDAL Core
- * Purpose:  Read metadata (mainly the remote sensing imagery) from files of 
+ * Purpose:  Read metadata (mainly the remote sensing imagery) from files of
  *           different providers like DigitalGlobe, GeoEye etc.
  * Author:   Dmitry Baryshnikov, polimax at mail.ru
  *
@@ -27,7 +27,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
- 
+
 #ifndef GDAL_MDREADER_H_INCLUDED
 #define GDAL_MDREADER_H_INCLUDED
 
@@ -99,22 +99,22 @@ public:
 
     /**
      * @brief Get specified metadata domain
-     * @param pszDomain The metadata domain to return  
-     * @return List of metadata items 
+     * @param pszDomain The metadata domain to return
+     * @return List of metadata items
      */
     virtual char ** GetMetadataDomain(const char *pszDomain);
     /**
-     * @brief Fill provided metatada store class
-     * @param poMDMD Metatada store class
+     * @brief Fill provided metadata store class
+     * @param poMDMD Metadata store class
      * @return true on success or false
      */
     virtual bool FillMetadata(GDALMultiDomainMetadata* poMDMD);
     /**
-      * @brief Determine whether the input parameter correspond to the particular 
+      * @brief Determine whether the input parameter correspond to the particular
       *        provider of remote sensing data completely
       * @return True if all needed sources files found
       */
-    virtual const bool HasRequiredFiles() const = 0;
+    virtual bool HasRequiredFiles() const = 0;
     /**
      * @brief Get metadata file names. The caller become owner of returned list
      *        and have to free it via CSLDestroy.
@@ -132,7 +132,7 @@ protected:
      * @param pszDateTime String to convert
      * @return value in time_t
      */
-    virtual const time_t GetAcquisitionTimeFromString(const char* pszDateTime);
+    virtual time_t GetAcquisitionTimeFromString(const char* pszDateTime);
     /**
      * @brief ReadXMLToList Transform xml to list of NULL terminated name=value
      *        strings
@@ -160,31 +160,31 @@ protected:
     char **m_papszRPCMD;
     char **m_papszIMAGERYMD;
     char **m_papszDEFAULTMD;
-    bool m_bIsMetadataLoad; 
+    bool m_bIsMetadataLoad;
 };
 
 /**
  * The metadata reader main class.
- * The main purpose of this class is to provide an correspondent reader 
- * for provided path. 
+ * The main purpose of this class is to provide an correspondent reader
+ * for provided path.
  */
 class CPL_DLL GDALMDReaderManager{
 public:
     GDALMDReaderManager();
     virtual ~GDALMDReaderManager();
-    
+
     /**
-     * @brief Try to detect metadata reader correspondent to the provided 
-     *        datasource path 
-     * @param pszPath a path to GDALDataset 
+     * @brief Try to detect metadata reader correspondent to the provided
+     *        datasource path
+     * @param pszPath a path to GDALDataset
      * @param papszSiblingFiles file list for metadata search purposes
      * @param nType a preferable reader type (may be the OR of MDReaders)
      * @return an appropriate reader or NULL if no such reader or error.
      * The pointer delete by the GDALMDReaderManager, so the user have not
      * delete it.
      */
-    virtual GDALMDReaderBase* GetReader(const char *pszPath, 
-                                        char **papszSiblingFiles, 
+    virtual GDALMDReaderBase* GetReader(const char *pszPath,
+                                        char **papszSiblingFiles,
                                         GUInt32 nType = MDR_ANY);
 protected:
     GDALMDReaderBase *m_pReader;
@@ -196,7 +196,7 @@ CPLString CPLStripQuotes(const CPLString& osString);
 char** GDALLoadRPBFile( const CPLString& osFilePath );
 char** GDALLoadRPCFile( const CPLString& osFilePath );
 char** GDALLoadIMDFile( const CPLString& osFilePath );
-const bool GDALCheckFileHeader(const CPLString& soFilePath,
+bool GDALCheckFileHeader(const CPLString& soFilePath,
                                const char * pszTestString,
                                int nBufferSize = 256);
 
diff --git a/gcore/gdal_misc.cpp b/gcore/gdal_misc.cpp
index b343723..65ffa74 100644
--- a/gcore/gdal_misc.cpp
+++ b/gcore/gdal_misc.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_misc.cpp 29326 2015-06-10 20:36:31Z rouault $
+ * $Id: gdal_misc.cpp 33839 2016-03-31 21:29:48Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Free standing functions for GDAL.
@@ -28,34 +28,20 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_priv.h"
 #include "cpl_string.h"
 #include "cpl_minixml.h"
 #include "cpl_multiproc.h"
-#include <ctype.h>
-#include <string>
-
-CPL_CVSID("$Id: gdal_misc.cpp 29326 2015-06-10 20:36:31Z rouault $");
-
-#include "ogr_spatialref.h"
 #include "gdal_mdreader.h"
+#include "gdal_priv.h"
+#include "ogr_spatialref.h"
 
-/************************************************************************/
-/*                           __pure_virtual()                           */
-/*                                                                      */
-/*      The following is a gross hack to remove the last remaining      */
-/*      dependency on the GNU C++ standard library.                     */
-/************************************************************************/
-
-#ifdef __GNUC__
-
-extern "C"
-void __pure_virtual()
+#include <cctype>
 
-{
-}
+#include <iostream>
+#include <limits>
+#include <string>
 
-#endif
+CPL_CVSID("$Id: gdal_misc.cpp 33839 2016-03-31 21:29:48Z rouault $");
 
 /************************************************************************/
 /*                         GDALDataTypeUnion()                          */
@@ -71,14 +57,14 @@ void __pure_virtual()
  * @return a data type able to express eType1 and eType2.
  */
 
-GDALDataType CPL_STDCALL 
+GDALDataType CPL_STDCALL
 GDALDataTypeUnion( GDALDataType eType1, GDALDataType eType2 )
 
 {
-    int         bFloating, bComplex, nBits, bSigned;
+    int         bFloating, nBits, bSigned;
+
+    int bComplex = GDALDataTypeIsComplex(eType1) | GDALDataTypeIsComplex(eType2);
 
-    bComplex = GDALDataTypeIsComplex(eType1) | GDALDataTypeIsComplex(eType2);
-    
     switch( eType1 )
     {
       case GDT_Byte:
@@ -86,27 +72,27 @@ GDALDataTypeUnion( GDALDataType eType1, GDALDataType eType2 )
         bSigned = FALSE;
         bFloating = FALSE;
         break;
-        
+
       case GDT_Int16:
       case GDT_CInt16:
         nBits = 16;
         bSigned = TRUE;
         bFloating = FALSE;
         break;
-        
+
       case GDT_UInt16:
         nBits = 16;
         bSigned = FALSE;
         bFloating = FALSE;
         break;
-        
+
       case GDT_Int32:
       case GDT_CInt32:
         nBits = 32;
         bSigned = TRUE;
         bFloating = FALSE;
         break;
-        
+
       case GDT_UInt32:
         nBits = 32;
         bSigned = FALSE;
@@ -136,23 +122,23 @@ GDALDataTypeUnion( GDALDataType eType1, GDALDataType eType2 )
     {
       case GDT_Byte:
         break;
-        
+
       case GDT_Int16:
       case GDT_CInt16:
         nBits = MAX(nBits,16);
         bSigned = TRUE;
         break;
-        
+
       case GDT_UInt16:
         nBits = MAX(nBits,16);
         break;
-        
+
       case GDT_Int32:
       case GDT_CInt32:
         nBits = MAX(nBits,32);
         bSigned = TRUE;
         break;
-        
+
       case GDT_UInt32:
         nBits = MAX(nBits,32);
         break;
@@ -202,43 +188,44 @@ GDALDataTypeUnion( GDALDataType eType1, GDALDataType eType2 )
 
 
 /************************************************************************/
-/*                        GDALGetDataTypeSize()                         */
+/*                        GDALGetDataTypeSizeBytes()                    */
 /************************************************************************/
 
 /**
- * \brief Get data type size in bits.
+ * \brief Get data type size in <b>bytes</b>.
  *
- * Returns the size of a a GDT_* type in bits, <b>not bytes</b>!
+ * Returns the size of a GDT_* type in bytes.  In contrast,
+ * GDALGetDataTypeBits() returns the size in <b>bits</b>.
  *
  * @param eDataType type, such as GDT_Byte.
- * @return the number of bits or zero if it is not recognised.
+ * @return the number of bytes or zero if it is not recognised.
  */
 
-int CPL_STDCALL GDALGetDataTypeSize( GDALDataType eDataType )
+int CPL_STDCALL GDALGetDataTypeSizeBytes( GDALDataType eDataType )
 
 {
     switch( eDataType )
     {
       case GDT_Byte:
-        return 8;
+        return 1;
 
       case GDT_UInt16:
       case GDT_Int16:
-        return 16;
+        return 2;
 
       case GDT_UInt32:
       case GDT_Int32:
       case GDT_Float32:
       case GDT_CInt16:
-        return 32;
+        return 4;
 
       case GDT_Float64:
       case GDT_CInt32:
       case GDT_CFloat32:
-        return 64;
+        return 8;
 
       case GDT_CFloat64:
-        return 128;
+        return 16;
 
       default:
         return 0;
@@ -246,15 +233,57 @@ int CPL_STDCALL GDALGetDataTypeSize( GDALDataType eDataType )
 }
 
 /************************************************************************/
+/*                        GDALGetDataTypeSizeBits()                     */
+/************************************************************************/
+
+/**
+ * \brief Get data type size in <b>bits</b>.
+ *
+ * Returns the size of a GDT_* type in bits, <b>not bytes</b>!  Use
+ * GDALGetDataTypeSizeBytes() for bytes.
+ *
+ * @param eDataType type, such as GDT_Byte.
+ * @return the number of bits or zero if it is not recognised.
+ */
+
+int CPL_STDCALL GDALGetDataTypeSizeBits( GDALDataType eDataType )
+
+{
+    return GDALGetDataTypeSizeBytes( eDataType ) * 8;
+}
+
+/************************************************************************/
+/*                        GDALGetDataTypeSize()                         */
+/************************************************************************/
+
+/**
+ * \brief Get data type size in bits.  <b>Deprecated</b>.
+ *
+ * Returns the size of a GDT_* type in bits, <b>not bytes</b>!
+ *
+ * Use GDALGetDataTypeSizeBytes() for bytes.
+ * Use GDALGetDataTypeSizeBits() for bits.
+ *
+ * @param eDataType type, such as GDT_Byte.
+ * @return the number of bits or zero if it is not recognised.
+ */
+
+int CPL_STDCALL GDALGetDataTypeSize( GDALDataType eDataType )
+
+{
+    return GDALGetDataTypeSizeBytes( eDataType ) * 8;
+}
+
+/************************************************************************/
 /*                       GDALDataTypeIsComplex()                        */
 /************************************************************************/
 
 /**
- * \brief Is data type complex? 
+ * \brief Is data type complex?
  *
- * @return TRUE if the passed type is complex (one of GDT_CInt16, GDT_CInt32, 
+ * @return TRUE if the passed type is complex (one of GDT_CInt16, GDT_CInt32,
  * GDT_CFloat32 or GDT_CFloat64), that is it consists of a real and imaginary
- * component. 
+ * component.
  */
 
 int CPL_STDCALL GDALDataTypeIsComplex( GDALDataType eDataType )
@@ -284,7 +313,7 @@ int CPL_STDCALL GDALDataTypeIsComplex( GDALDataType eDataType )
  * the enumerated item name with the GDT_ prefix removed.  So GDT_Byte returns
  * "Byte".  The returned strings are static strings and should not be modified
  * or freed by the application.  These strings are useful for reporting
- * datatypes in debug statements, errors and other user output. 
+ * datatypes in debug statements, errors and other user output.
  *
  * @param eDataType type to get name of.
  * @return string corresponding to existing data type
@@ -310,10 +339,10 @@ const char * CPL_STDCALL GDALGetDataTypeName( GDALDataType eDataType )
 
       case GDT_UInt32:
         return "UInt32";
-        
+
       case GDT_Int32:
         return "Int32";
-        
+
       case GDT_Float32:
         return "Float32";
 
@@ -348,7 +377,7 @@ const char * CPL_STDCALL GDALGetDataTypeName( GDALDataType eDataType )
  * function is opposite to the GDALGetDataTypeName().
  *
  * @param pszName string containing the symbolic name of the type.
- * 
+ *
  * @return GDAL data type.
  */
 
@@ -357,9 +386,7 @@ GDALDataType CPL_STDCALL GDALGetDataTypeByName( const char *pszName )
 {
     VALIDATE_POINTER1( pszName, "GDALGetDataTypeByName", GDT_Unknown );
 
-    int	iType;
-    
-    for( iType = 1; iType < GDT_TypeCount; iType++ )
+    for( int iType = 1; iType < GDT_TypeCount; iType++ )
     {
         if( GDALGetDataTypeName((GDALDataType)iType) != NULL
             && EQUAL(GDALGetDataTypeName((GDALDataType)iType), pszName) )
@@ -372,6 +399,92 @@ GDALDataType CPL_STDCALL GDALGetDataTypeByName( const char *pszName )
 }
 
 /************************************************************************/
+/*                      GDALAdjustValueToDataType()                     */
+/************************************************************************/
+
+template<class T> static inline void ClampAndRound(double& dfValue, int& bClamped, int &bRounded)
+{
+    if (dfValue < std::numeric_limits<T>::min())
+    {
+        bClamped = TRUE;
+        dfValue = static_cast<double>(std::numeric_limits<T>::min());
+    }
+    else if (dfValue > std::numeric_limits<T>::max())
+    {
+        bClamped = TRUE;
+        dfValue = static_cast<double>(std::numeric_limits<T>::max());
+    }
+    else if (dfValue != static_cast<double>(static_cast<T>(dfValue)))
+    {
+        bRounded = TRUE;
+        dfValue = static_cast<double>(static_cast<T>(floor(dfValue + 0.5)));
+    }
+}
+
+/**
+ * \brief Adjust a value to the output data type
+ *
+ * Adjustment consist in clamping to minimum/maxmimum values of the data type
+ * and rounding for integral types.
+ *
+ * @param eDT target data type.
+ * @param dfValue value to adjust.
+ * @param pbClamped pointer to a integer(boolean) to indicate if clamping has been made, or NULL
+ * @param pbRounded pointer to a integer(boolean) to indicate if rounding has been made, or NULL
+ *
+ * @return adjusted value
+ * @since GDAL 2.1
+ */
+
+double GDALAdjustValueToDataType( GDALDataType eDT, double dfValue, int* pbClamped, int* pbRounded )
+{
+    int bClamped = FALSE, bRounded = FALSE;
+    switch(eDT)
+    {
+        case GDT_Byte:
+            ClampAndRound<GByte>(dfValue, bClamped, bRounded);
+            break;
+        case GDT_Int16:
+            ClampAndRound<GInt16>(dfValue, bClamped, bRounded);
+            break;
+        case GDT_UInt16:
+            ClampAndRound<GUInt16>(dfValue, bClamped, bRounded);
+            break;
+        case GDT_Int32:
+            ClampAndRound<GInt32>(dfValue, bClamped, bRounded);
+            break;
+        case GDT_UInt32:
+            ClampAndRound<GUInt32>(dfValue, bClamped, bRounded);
+            break;
+        case GDT_Float32:
+        {
+            if ( dfValue < -std::numeric_limits<float>::max())
+            {
+                bClamped = TRUE;
+                dfValue = static_cast<double>(-std::numeric_limits<float>::max());
+            }
+            else if (dfValue > std::numeric_limits<float>::max())
+            {
+                bClamped = TRUE;
+                dfValue = static_cast<double>(std::numeric_limits<float>::max());
+            }
+            else
+            {
+                dfValue = static_cast<double>(static_cast<float>(dfValue));
+            }
+            break;
+        }
+        default:
+            break;
+    }
+    if( pbClamped )
+        *pbClamped = bClamped;
+    if( pbRounded )
+        *pbRounded = bRounded;
+    return dfValue;
+}
+
+/************************************************************************/
 /*                        GDALGetAsyncStatusTypeByName()                */
 /************************************************************************/
 /**
@@ -381,7 +494,7 @@ GDALDataType CPL_STDCALL GDALGetDataTypeByName( const char *pszName )
  * function is opposite to the GDALGetAsyncStatusTypeName().
  *
  * @param pszName string containing the symbolic name of the type.
- * 
+ *
  * @return GDAL AsyncStatus type.
  */
 GDALAsyncStatusType CPL_DLL CPL_STDCALL GDALGetAsyncStatusTypeByName( const char *pszName )
@@ -414,7 +527,7 @@ GDALAsyncStatusType CPL_DLL CPL_STDCALL GDALGetAsyncStatusTypeByName( const char
  * the enumerated item name with the GARIO_ prefix removed.  So GARIO_COMPLETE returns
  * "COMPLETE".  The returned strings are static strings and should not be modified
  * or freed by the application.  These strings are useful for reporting
- * datatypes in debug statements, errors and other user output. 
+ * datatypes in debug statements, errors and other user output.
  *
  * @param eAsyncStatusType type to get name of.
  * @return string corresponding to type.
@@ -467,13 +580,13 @@ const char *GDALGetPaletteInterpretationName( GDALPaletteInterp eInterp )
 
       case GPI_RGB:
         return "RGB";
-        
+
       case GPI_CMYK:
         return "CMYK";
 
       case GPI_HLS:
         return "HLS";
-        
+
       default:
         return "Unknown";
     }
@@ -543,16 +656,16 @@ const char *GDALGetColorInterpretationName( GDALColorInterp eInterp )
 
       case GCI_BlackBand:
         return "Black";
-        
+
       case GCI_YCbCr_YBand:
         return "YCbCr_Y";
-        
+
       case GCI_YCbCr_CbBand:
         return "YCbCr_Cb";
-        
+
       case GCI_YCbCr_CrBand:
         return "YCbCr_Cr";
-        
+
       default:
         return "Unknown";
     }
@@ -563,13 +676,14 @@ const char *GDALGetColorInterpretationName( GDALColorInterp eInterp )
 /************************************************************************/
 
 /**
- * \brief Get color interpreation by symbolic name.
+ * \brief Get color interpretation by symbolic name.
  *
- * Returns a color interpreation corresponding to the given symbolic name. This
+ * Returns a color interpretation corresponding to the given symbolic name. This
  * function is opposite to the GDALGetColorInterpretationName().
  *
- * @param pszName string containing the symbolic name of the color interpretation.
- * 
+ * @param pszName string containing the symbolic name of the color
+ * interpretation.
+ *
  * @return GDAL color interpretation.
  *
  * @since GDAL 1.7.0
@@ -580,9 +694,7 @@ GDALColorInterp GDALGetColorInterpretationByName( const char *pszName )
 {
     VALIDATE_POINTER1( pszName, "GDALGetColorInterpretationByName", GCI_Undefined );
 
-    int	iType;
-    
-    for( iType = 0; iType <= GCI_Max; iType++ )
+    for( int iType = 0; iType <= GCI_Max; iType++ )
     {
         if( EQUAL(GDALGetColorInterpretationName((GDALColorInterp)iType), pszName) )
         {
@@ -597,8 +709,8 @@ GDALColorInterp GDALGetColorInterpretationByName( const char *pszName )
 /*                     GDALGetRandomRasterSample()                      */
 /************************************************************************/
 
-int CPL_STDCALL 
-GDALGetRandomRasterSample( GDALRasterBandH hBand, int nSamples, 
+int CPL_STDCALL
+GDALGetRandomRasterSample( GDALRasterBandH hBand, int nSamples,
                            float *pafSampleBuf )
 
 {
@@ -617,12 +729,11 @@ GDALGetRandomRasterSample( GDALRasterBandH hBand, int nSamples,
     int         nBlocksPerRow, nBlocksPerColumn;
     int         nSampleRate;
     int         bGotNoDataValue;
-    double      dfNoDataValue;
     int         nActualSamples = 0;
     int         nBlockSampleRate;
     int         nBlockPixels, nBlockCount;
 
-    dfNoDataValue = poBand->GetNoDataValue( &bGotNoDataValue );
+    double dfNoDataValue = poBand->GetNoDataValue( &bGotNoDataValue );
 
     poBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
 
@@ -632,7 +743,7 @@ GDALGetRandomRasterSample( GDALRasterBandH hBand, int nSamples,
     nBlockPixels = nBlockXSize * nBlockYSize;
     nBlockCount = nBlocksPerRow * nBlocksPerColumn;
 
-    if( nBlocksPerRow == 0 || nBlocksPerColumn == 0 || nBlockPixels == 0 
+    if( nBlocksPerRow == 0 || nBlocksPerColumn == 0 || nBlockPixels == 0
         || nBlockCount == 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -647,17 +758,17 @@ GDALGetRandomRasterSample( GDALRasterBandH hBand, int nSamples,
     if( nSampleRate == nBlocksPerRow && nSampleRate > 1 )
         nSampleRate--;
 
-    while( nSampleRate > 1 
+    while( nSampleRate > 1
            && ((nBlockCount-1) / nSampleRate + 1) * nBlockPixels < nSamples )
         nSampleRate--;
 
     if ((nSamples / ((nBlockCount-1) / nSampleRate + 1)) == 0)
         nBlockSampleRate = 1;
     else
-        nBlockSampleRate = 
+        nBlockSampleRate =
             MAX(1,nBlockPixels / (nSamples / ((nBlockCount-1) / nSampleRate + 1)));
 
-    for( int iSampleBlock = 0; 
+    for( int iSampleBlock = 0;
          iSampleBlock < nBlockCount;
          iSampleBlock += nSampleRate )
     {
@@ -671,11 +782,7 @@ GDALGetRandomRasterSample( GDALRasterBandH hBand, int nSamples,
         poBlock = poBand->GetLockedBlockRef( iXBlock, iYBlock );
         if( poBlock == NULL )
             continue;
-        if( poBlock->GetDataRef() == NULL )
-        {
-            poBlock->DropLock();
-            continue;
-        }
+        void* pDataRef = poBlock->GetDataRef();
 
         if( (iXBlock + 1) * nBlockXSize > poBand->GetXSize() )
             iXValid = poBand->GetXSize() - iXBlock * nBlockXSize;
@@ -693,54 +800,54 @@ GDALGetRandomRasterSample( GDALRasterBandH hBand, int nSamples,
             {
                 int     iOffset;
 
-                iOffset = iX + iY * nBlockXSize; 
+                iOffset = iX + iY * nBlockXSize;
                 switch( poBlock->GetDataType() )
                 {
                   case GDT_Byte:
-                    dfValue = ((GByte *) poBlock->GetDataRef())[iOffset];
+                    dfValue = ((GByte *) pDataRef)[iOffset];
                     break;
                   case GDT_UInt16:
-                    dfValue = ((GUInt16 *) poBlock->GetDataRef())[iOffset];
+                    dfValue = ((GUInt16 *) pDataRef)[iOffset];
                     break;
                   case GDT_Int16:
-                    dfValue = ((GInt16 *) poBlock->GetDataRef())[iOffset];
+                    dfValue = ((GInt16 *) pDataRef)[iOffset];
                     break;
                   case GDT_UInt32:
-                    dfValue = ((GUInt32 *) poBlock->GetDataRef())[iOffset];
+                    dfValue = ((GUInt32 *) pDataRef)[iOffset];
                     break;
                   case GDT_Int32:
-                    dfValue = ((GInt32 *) poBlock->GetDataRef())[iOffset];
+                    dfValue = ((GInt32 *) pDataRef)[iOffset];
                     break;
                   case GDT_Float32:
-                    dfValue = ((float *) poBlock->GetDataRef())[iOffset];
+                    dfValue = ((float *) pDataRef)[iOffset];
                     break;
                   case GDT_Float64:
-                    dfValue = ((double *) poBlock->GetDataRef())[iOffset];
+                    dfValue = ((double *) pDataRef)[iOffset];
                     break;
                   case GDT_CInt16:
-                    dfReal = ((GInt16 *) poBlock->GetDataRef())[iOffset*2];
-                    dfImag = ((GInt16 *) poBlock->GetDataRef())[iOffset*2+1];
+                    dfReal = ((GInt16 *) pDataRef)[iOffset*2];
+                    dfImag = ((GInt16 *) pDataRef)[iOffset*2+1];
                     dfValue = sqrt(dfReal*dfReal + dfImag*dfImag);
                     break;
                   case GDT_CInt32:
-                    dfReal = ((GInt32 *) poBlock->GetDataRef())[iOffset*2];
-                    dfImag = ((GInt32 *) poBlock->GetDataRef())[iOffset*2+1];
+                    dfReal = ((GInt32 *) pDataRef)[iOffset*2];
+                    dfImag = ((GInt32 *) pDataRef)[iOffset*2+1];
                     dfValue = sqrt(dfReal*dfReal + dfImag*dfImag);
                     break;
                   case GDT_CFloat32:
-                    dfReal = ((float *) poBlock->GetDataRef())[iOffset*2];
-                    dfImag = ((float *) poBlock->GetDataRef())[iOffset*2+1];
+                    dfReal = ((float *) pDataRef)[iOffset*2];
+                    dfImag = ((float *) pDataRef)[iOffset*2+1];
                     dfValue = sqrt(dfReal*dfReal + dfImag*dfImag);
                     break;
                   case GDT_CFloat64:
-                    dfReal = ((double *) poBlock->GetDataRef())[iOffset*2];
-                    dfImag = ((double *) poBlock->GetDataRef())[iOffset*2+1];
+                    dfReal = ((double *) pDataRef)[iOffset*2];
+                    dfImag = ((double *) pDataRef)[iOffset*2+1];
                     dfValue = sqrt(dfReal*dfReal + dfImag*dfImag);
                     break;
                   default:
                     CPLAssert( FALSE );
                 }
-            
+
                 if( bGotNoDataValue && dfValue == dfNoDataValue )
                     continue;
 
@@ -802,13 +909,11 @@ void CPL_STDCALL GDALDeinitGCPs( int nCount, GDAL_GCP * psGCP )
 /*                         GDALDuplicateGCPs()                          */
 /************************************************************************/
 
-GDAL_GCP * CPL_STDCALL 
+GDAL_GCP * CPL_STDCALL
 GDALDuplicateGCPs( int nCount, const GDAL_GCP *pasGCPList )
 
 {
-    GDAL_GCP    *pasReturn;
-
-    pasReturn = (GDAL_GCP *) CPLMalloc(sizeof(GDAL_GCP) * nCount);
+    GDAL_GCP *pasReturn = (GDAL_GCP *) CPLMalloc(sizeof(GDAL_GCP) * nCount);
     GDALInitGCPs( nCount, pasReturn );
 
     for( int iGCP = 0; iGCP < nCount; iGCP++ )
@@ -837,36 +942,34 @@ GDALDuplicateGCPs( int nCount, const GDAL_GCP *pasGCPList )
  * Find file with alternate extension.
  *
  * Finds the file with the indicated extension, substituting it in place
- * of the extension of the base filename.  Generally used to search for 
+ * of the extension of the base filename.  Generally used to search for
  * associated files like world files .RPB files, etc.  If necessary, the
  * extension will be tried in both upper and lower case.  If a sibling file
- * list is available it will be used instead of doing VSIStatExL() calls to 
- * probe the file system.  
+ * list is available it will be used instead of doing VSIStatExL() calls to
+ * probe the file system.
  *
- * Note that the result is a dynamic CPLString so this method should not 
+ * Note that the result is a dynamic CPLString so this method should not
  * be used in a situation where there could be cross heap issues.  It is
  * generally imprudent for application built on GDAL to use this function
  * unless they are sure they will always use the same runtime heap as GDAL.
  *
  * @param pszBaseFilename the filename relative to which to search.
  * @param pszExt the target extension in either upper or lower case.
- * @param papszSiblingFiles the list of files in the same directory as 
- * pszBaseFilename or NULL if they are not known. 
- * @param nFlags special options controlling search.  None defined yet, just 
+ * @param papszSiblingFiles the list of files in the same directory as
+ * pszBaseFilename or NULL if they are not known.
+ * @param nFlags special options controlling search.  None defined yet, just
  * pass 0.
- * 
+ *
  * @return an empty string if the target is not found, otherwise the target
- * file with similar path style as the pszBaseFilename. 
+ * file with similar path style as the pszBaseFilename.
  */
 
-CPLString GDALFindAssociatedFile( const char *pszBaseFilename, 
+CPLString GDALFindAssociatedFile( const char *pszBaseFilename,
                                   const char *pszExt,
-                                  char **papszSiblingFiles, 
-                                  int nFlags )
+                                  char **papszSiblingFiles,
+                                  int /* nFlags */ )
 
 {
-    (void) nFlags;
-
     CPLString osTarget = CPLResetExtension( pszBaseFilename, pszExt );
 
     if( papszSiblingFiles == NULL )
@@ -890,7 +993,7 @@ CPLString GDALFindAssociatedFile( const char *pszBaseFilename,
     }
     else
     {
-        int iSibling = CSLFindString( papszSiblingFiles, 
+        int iSibling = CSLFindString( papszSiblingFiles,
                                       CPLGetFilename(osTarget) );
         if( iSibling < 0 )
             return "";
@@ -901,39 +1004,37 @@ CPLString GDALFindAssociatedFile( const char *pszBaseFilename,
 
     return osTarget;
 }
-                             
+
 /************************************************************************/
 /*                         GDALLoadOziMapFile()                         */
 /************************************************************************/
 
-#define MAX_GCP 30
- 
+
 int CPL_STDCALL GDALLoadOziMapFile( const char *pszFilename,
-                                    double *padfGeoTransform, char **ppszWKT, 
+                                    double *padfGeoTransform, char **ppszWKT,
                                     int *pnGCPCount, GDAL_GCP **ppasGCPs )
 
 
 {
-    char	**papszLines;
-    int		iLine, nLines=0;
     int	        nCoordinateCount = 0;
+    static const int MAX_GCP = 30;
     GDAL_GCP    asGCPs[MAX_GCP];
-    
+
     VALIDATE_POINTER1( pszFilename, "GDALLoadOziMapFile", FALSE );
     VALIDATE_POINTER1( padfGeoTransform, "GDALLoadOziMapFile", FALSE );
     VALIDATE_POINTER1( pnGCPCount, "GDALLoadOziMapFile", FALSE );
     VALIDATE_POINTER1( ppasGCPs, "GDALLoadOziMapFile", FALSE );
 
-    papszLines = CSLLoad2( pszFilename, 1000, 200, NULL );
+    char **papszLines = CSLLoad2( pszFilename, 1000, 200, NULL );
 
     if ( !papszLines )
         return FALSE;
 
-    nLines = CSLCount( papszLines );
+    int nLines = CSLCount( papszLines );
 
     // Check the OziExplorer Map file signature
     if ( nLines < 5
-         || !EQUALN(papszLines[0], "OziExplorer Map Data File Version ", 34) )
+         || !STARTS_WITH_CI(papszLines[0], "OziExplorer Map Data File Version ") )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
         "GDALLoadOziMapFile(): file \"%s\" is not in OziExplorer Map format.",
@@ -953,9 +1054,10 @@ int CPL_STDCALL GDALLoadOziMapFile( const char *pszFilename,
     /* is explained at http://tech.groups.yahoo.com/group/OziUsers-L/message/12484 */
     double dfMSF = 1;
 
+    int	iLine;
     for ( iLine = 5; iLine < nLines; iLine++ )
     {
-        if ( EQUALN(papszLines[iLine], "MSF,", 4) )
+        if ( STARTS_WITH_CI(papszLines[iLine], "MSF,") )
         {
             dfMSF = CPLAtof(papszLines[iLine] + 4);
             if (dfMSF <= 0.01) /* Suspicious values */
@@ -990,12 +1092,12 @@ int CPL_STDCALL GDALLoadOziMapFile( const char *pszFilename,
         }
 
         if ( CSLCount(papszTok) >= 17
-             && EQUALN(papszTok[0], "Point", 5)
+             && STARTS_WITH_CI(papszTok[0], "Point")
              && !EQUAL(papszTok[2], "")
              && !EQUAL(papszTok[3], "")
              && nCoordinateCount < MAX_GCP )
         {
-            int     bReadOk = FALSE;
+            bool bReadOk = false;
             double  dfLon = 0., dfLat = 0.;
 
             if ( !EQUAL(papszTok[6], "")
@@ -1024,7 +1126,7 @@ int CPL_STDCALL GDALLoadOziMapFile( const char *pszFilename,
                         poTransform = OGRCreateCoordinateTransformation( poLatLong, &oSRS );
                         if ( poTransform )
                         {
-                            bReadOk = poTransform->Transform( 1, &dfLon, &dfLat );
+                            bReadOk = CPL_TO_BOOL(poTransform->Transform( 1, &dfLon, &dfLat ));
                             delete poTransform;
                         }
                         delete poLatLong;
@@ -1037,7 +1139,7 @@ int CPL_STDCALL GDALLoadOziMapFile( const char *pszFilename,
                 // Set cartesian coordinates of the pixels.
                 dfLon = CPLAtofM(papszTok[14]);
                 dfLat = CPLAtofM(papszTok[15]);
-                bReadOk = TRUE;
+                bReadOk = true;
 
                 //if ( EQUAL(papszTok[16], "S") )
                 //    dfLat = -dfLat;
@@ -1065,7 +1167,7 @@ int CPL_STDCALL GDALLoadOziMapFile( const char *pszFilename,
 
     if ( nCoordinateCount == 0 )
     {
-        CPLDebug( "GDAL", "GDALLoadOziMapFile(\"%s\") did read no GCPs.", 
+        CPLDebug( "GDAL", "GDALLoadOziMapFile(\"%s\") did read no GCPs.",
                   pszFilename );
         return FALSE;
     }
@@ -1074,17 +1176,17 @@ int CPL_STDCALL GDALLoadOziMapFile( const char *pszFilename,
 /*      Try to convert the GCPs into a geotransform definition, if      */
 /*      possible.  Otherwise we will need to use them as GCPs.          */
 /* -------------------------------------------------------------------- */
-    if( !GDALGCPsToGeoTransform( nCoordinateCount, asGCPs, padfGeoTransform, 
-                                 CSLTestBoolean(CPLGetConfigOption("OZI_APPROX_GEOTRANSFORM", "NO")) ) )
+    if( !GDALGCPsToGeoTransform( nCoordinateCount, asGCPs, padfGeoTransform,
+                                 CPLTestBool(CPLGetConfigOption("OZI_APPROX_GEOTRANSFORM", "NO")) ) )
     {
         if ( pnGCPCount && ppasGCPs )
         {
-            CPLDebug( "GDAL", 
-                "GDALLoadOziMapFile(%s) found file, wasn't able to derive a\n"
+            CPLDebug( "GDAL",
+                "GDALLoadOziMapFile(%s) found file, was not able to derive a\n"
                 "first order geotransform.  Using points as GCPs.",
                 pszFilename );
 
-            *ppasGCPs = (GDAL_GCP *) 
+            *ppasGCPs = (GDAL_GCP *)
                 CPLCalloc( sizeof(GDAL_GCP),nCoordinateCount );
             memcpy( *ppasGCPs, asGCPs, sizeof(GDAL_GCP) * nCoordinateCount );
             *pnGCPCount = nCoordinateCount;
@@ -1094,12 +1196,10 @@ int CPL_STDCALL GDALLoadOziMapFile( const char *pszFilename,
     {
         GDALDeinitGCPs( nCoordinateCount, asGCPs );
     }
-     
+
     return TRUE;
 }
 
-#undef MAX_GCP
-
 /************************************************************************/
 /*                       GDALReadOziMapFile()                           */
 /************************************************************************/
@@ -1110,26 +1210,23 @@ int CPL_STDCALL GDALReadOziMapFile( const char * pszBaseFilename,
 
 
 {
-    const char	*pszOzi;
-    FILE	*fpOzi;
-
 /* -------------------------------------------------------------------- */
 /*      Try lower case, then upper case.                                */
 /* -------------------------------------------------------------------- */
-    pszOzi = CPLResetExtension( pszBaseFilename, "map" );
+    const char *pszOzi = CPLResetExtension( pszBaseFilename, "map" );
 
-    fpOzi = VSIFOpen( pszOzi, "rt" );
+    VSILFILE *fpOzi = VSIFOpenL( pszOzi, "rt" );
 
     if ( fpOzi == NULL && VSIIsCaseSensitiveFS(pszOzi) )
     {
         pszOzi = CPLResetExtension( pszBaseFilename, "MAP" );
-        fpOzi = VSIFOpen( pszOzi, "rt" );
+        fpOzi = VSIFOpenL( pszOzi, "rt" );
     }
-    
+
     if ( fpOzi == NULL )
         return FALSE;
 
-    VSIFClose( fpOzi );
+    CPL_IGNORE_RET_VAL(VSIFCloseL( fpOzi ));
 
 /* -------------------------------------------------------------------- */
 /*      We found the file, now load and parse it.                       */
@@ -1141,38 +1238,37 @@ int CPL_STDCALL GDALReadOziMapFile( const char * pszBaseFilename,
 /************************************************************************/
 /*                         GDALLoadTabFile()                            */
 /*                                                                      */
-/*      Helper function for translator implementators wanting           */
+/*      Helper function for translator implementer wanting              */
 /*      support for MapInfo .tab-files.                                 */
 /************************************************************************/
 
 #define MAX_GCP 256
- 
+
 int CPL_STDCALL GDALLoadTabFile( const char *pszFilename,
-                                 double *padfGeoTransform, char **ppszWKT, 
+                                 double *padfGeoTransform, char **ppszWKT,
                                  int *pnGCPCount, GDAL_GCP **ppasGCPs )
 
 
 {
-    char	**papszLines;
     char        **papszTok=NULL;
-    int	        bTypeRasterFound = FALSE;
-    int		bInsideTableDef = FALSE;
-    int		iLine, numLines=0;
+    bool        bTypeRasterFound = false;
+    bool        bInsideTableDef = false;
     int	        nCoordinateCount = 0;
     GDAL_GCP    asGCPs[MAX_GCP];
-    
-    papszLines = CSLLoad2( pszFilename, 1000, 200, NULL );
+
+    char **papszLines = CSLLoad2( pszFilename, 1000, 200, NULL );
 
     if ( !papszLines )
         return FALSE;
 
-    numLines = CSLCount(papszLines);
+    int numLines = CSLCount(papszLines);
 
     // Iterate all lines in the TAB-file
+    int iLine;
     for(iLine=0; iLine<numLines; iLine++)
     {
         CSLDestroy(papszTok);
-        papszTok = CSLTokenizeStringComplex(papszLines[iLine], " \t(),;", 
+        papszTok = CSLTokenizeStringComplex(papszLines[iLine], " \t(),;",
                                             TRUE, FALSE);
 
         if (CSLCount(papszTok) < 2)
@@ -1188,7 +1284,7 @@ int CPL_STDCALL GDALLoadTabFile( const char *pszFilename,
             // Only RASTER-type will be handled
             if (EQUAL(papszTok[1], "RASTER"))
             {
-                bTypeRasterFound = TRUE;
+                bTypeRasterFound = true;
             }
             else
             {
@@ -1199,11 +1295,11 @@ int CPL_STDCALL GDALLoadTabFile( const char *pszFilename,
         }
         else if (bTypeRasterFound && bInsideTableDef
                  && CSLCount(papszTok) > 4
-                 && EQUAL(papszTok[4], "Label") 
+                 && EQUAL(papszTok[4], "Label")
                  && nCoordinateCount < MAX_GCP )
         {
             GDALInitGCPs( 1, asGCPs + nCoordinateCount );
-            
+
             asGCPs[nCoordinateCount].dfGCPPixel = CPLAtofM(papszTok[2]);
             asGCPs[nCoordinateCount].dfGCPLine = CPLAtofM(papszTok[3]);
             asGCPs[nCoordinateCount].dfGCPX = CPLAtofM(papszTok[0]);
@@ -1216,17 +1312,17 @@ int CPL_STDCALL GDALLoadTabFile( const char *pszFilename,
 
             nCoordinateCount++;
         }
-        else if( bTypeRasterFound && bInsideTableDef 
-                 && EQUAL(papszTok[0],"CoordSys") 
+        else if( bTypeRasterFound && bInsideTableDef
+                 && EQUAL(papszTok[0],"CoordSys")
                  && ppszWKT != NULL )
         {
             OGRSpatialReference oSRS;
-            
+
             if( oSRS.importFromMICoordSys( papszLines[iLine] ) == OGRERR_NONE )
                 oSRS.exportToWkt( ppszWKT );
         }
-        else if( EQUAL(papszTok[0],"Units") 
-                 && CSLCount(papszTok) > 1 
+        else if( EQUAL(papszTok[0],"Units")
+                 && CSLCount(papszTok) > 1
                  && EQUAL(papszTok[1],"degree") )
         {
             /*
@@ -1234,7 +1330,7 @@ int CPL_STDCALL GDALLoadTabFile( const char *pszFilename,
             ** system we need to convert it to geographic.  See to01_02.TAB.
             */
             if( ppszWKT != NULL && *ppszWKT != NULL
-                && EQUALN(*ppszWKT,"PROJCS",6) )
+                && STARTS_WITH_CI(*ppszWKT, "PROJCS") )
             {
                 OGRSpatialReference oSRS, oSRSGeogCS;
                 char *pszSrcWKT = *ppszWKT;
@@ -1245,7 +1341,7 @@ int CPL_STDCALL GDALLoadTabFile( const char *pszFilename,
                 oSRSGeogCS.exportToWkt( ppszWKT );
             }
         }
-            
+
     }
 
     CSLDestroy(papszTok);
@@ -1253,7 +1349,7 @@ int CPL_STDCALL GDALLoadTabFile( const char *pszFilename,
 
     if( nCoordinateCount == 0 )
     {
-        CPLDebug( "GDAL", "GDALLoadTabFile(%s) did not get any GCPs.", 
+        CPLDebug( "GDAL", "GDALLoadTabFile(%s) did not get any GCPs.",
                   pszFilename );
         return FALSE;
     }
@@ -1262,17 +1358,17 @@ int CPL_STDCALL GDALLoadTabFile( const char *pszFilename,
 /*      Try to convert the GCPs into a geotransform definition, if      */
 /*      possible.  Otherwise we will need to use them as GCPs.          */
 /* -------------------------------------------------------------------- */
-    if( !GDALGCPsToGeoTransform( nCoordinateCount, asGCPs, padfGeoTransform, 
-                                 CSLTestBoolean(CPLGetConfigOption("TAB_APPROX_GEOTRANSFORM", "NO")) ) )
+    if( !GDALGCPsToGeoTransform( nCoordinateCount, asGCPs, padfGeoTransform,
+                                 CPLTestBool(CPLGetConfigOption("TAB_APPROX_GEOTRANSFORM", "NO")) ) )
     {
         if (pnGCPCount && ppasGCPs)
         {
-            CPLDebug( "GDAL", 
-                "GDALLoadTabFile(%s) found file, wasn't able to derive a\n"
+            CPLDebug( "GDAL",
+                "GDALLoadTabFile(%s) found file, was not able to derive a\n"
                 "first order geotransform.  Using points as GCPs.",
                 pszFilename );
 
-            *ppasGCPs = (GDAL_GCP *) 
+            *ppasGCPs = (GDAL_GCP *)
                 CPLCalloc( sizeof(GDAL_GCP),nCoordinateCount );
             memcpy( *ppasGCPs, asGCPs, sizeof(GDAL_GCP) * nCoordinateCount );
             *pnGCPCount = nCoordinateCount;
@@ -1282,7 +1378,7 @@ int CPL_STDCALL GDALLoadTabFile( const char *pszFilename,
     {
         GDALDeinitGCPs( nCoordinateCount, asGCPs );
     }
-     
+
     return TRUE;
 }
 
@@ -1291,12 +1387,12 @@ int CPL_STDCALL GDALLoadTabFile( const char *pszFilename,
 /************************************************************************/
 /*                         GDALReadTabFile()                            */
 /*                                                                      */
-/*      Helper function for translator implementators wanting           */
+/*      Helper function for translator implementer wanting              */
 /*      support for MapInfo .tab-files.                                 */
 /************************************************************************/
 
-int CPL_STDCALL GDALReadTabFile( const char * pszBaseFilename, 
-                                 double *padfGeoTransform, char **ppszWKT, 
+int CPL_STDCALL GDALReadTabFile( const char * pszBaseFilename,
+                                 double *padfGeoTransform, char **ppszWKT,
                                  int *pnGCPCount, GDAL_GCP **ppasGCPs )
 
 
@@ -1354,11 +1450,11 @@ int GDALReadTabFile2( const char * pszBaseFilename,
         pszTAB = CPLResetExtension( pszBaseFilename, "TAB" );
         fpTAB = VSIFOpenL( pszTAB, "rt" );
     }
-    
+
     if( fpTAB == NULL )
         return FALSE;
 
-    VSIFCloseL( fpTAB );
+    CPL_IGNORE_RET_VAL(VSIFCloseL( fpTAB ));
 
 /* -------------------------------------------------------------------- */
 /*      We found the file, now load and parse it.                       */
@@ -1378,13 +1474,13 @@ int GDALReadTabFile2( const char * pszBaseFilename,
 /************************************************************************/
 
 /**
- * \brief Read ESRI world file. 
+ * \brief Read ESRI world file.
  *
  * This function reads an ESRI style world file, and formats a geotransform
  * from its contents.
  *
  * The world file contains an affine transformation with the parameters
- * in a different order than in a geotransform array. 
+ * in a different order than in a geotransform array.
  *
  * <ul>
  * <li> geotransform[1] : width of pixel
@@ -1397,12 +1493,12 @@ int GDALReadTabFile2( const char * pszBaseFilename,
  *
  * @param pszFilename the world file name.
  * @param padfGeoTransform the six double array into which the
- * geotransformation should be placed. 
+ * geotransformation should be placed.
  *
  * @return TRUE on success or FALSE on failure.
  */
 
-int CPL_STDCALL 
+int CPL_STDCALL
 GDALLoadWorldFile( const char *pszFilename, double *padfGeoTransform )
 
 {
@@ -1429,8 +1525,8 @@ GDALLoadWorldFile( const char *pszFilename, double *padfGeoTransform )
         world[nLines] = CPLAtofM(line);
         ++nLines;
     }
-      
-    if( nLines == 6 
+
+    if( nLines == 6
         && (world[0] != 0.0 || world[2] != 0.0)
         && (world[3] != 0.0 || world[1] != 0.0) )
     {
@@ -1453,7 +1549,7 @@ GDALLoadWorldFile( const char *pszFilename, double *padfGeoTransform )
     }
     else
     {
-        CPLDebug( "GDAL", 
+        CPLDebug( "GDAL",
                   "GDALLoadWorldFile(%s) found file, but it was corrupt.",
                   pszFilename );
         CSLDestroy(papszLines);
@@ -1466,17 +1562,17 @@ GDALLoadWorldFile( const char *pszFilename, double *padfGeoTransform )
 /************************************************************************/
 
 /**
- * \brief Read ESRI world file. 
+ * \brief Read ESRI world file.
  *
  * This function reads an ESRI style world file, and formats a geotransform
  * from its contents.  It does the same as GDALLoadWorldFile() function, but
  * it will form the filename for the worldfile from the filename of the raster
  * file referred and the suggested extension.  If no extension is provided,
  * the code will internally try the unix style and windows style world file
- * extensions (eg. for .tif these would be .tfw and .tifw). 
+ * extensions (eg. for .tif these would be .tfw and .tifw).
  *
  * The world file contains an affine transformation with the parameters
- * in a different order than in a geotransform array. 
+ * in a different order than in a geotransform array.
  *
  * <ul>
  * <li> geotransform[1] : width of pixel
@@ -1488,15 +1584,15 @@ GDALLoadWorldFile( const char *pszFilename, double *padfGeoTransform )
  * </ul>
  *
  * @param pszBaseFilename the target raster file.
- * @param pszExtension the extension to use (ie. ".wld") or NULL to derive it
+ * @param pszExtension the extension to use (i.e. ".wld") or NULL to derive it
  * from the pszBaseFilename
- * @param padfGeoTransform the six double array into which the 
- * geotransformation should be placed. 
+ * @param padfGeoTransform the six double array into which the
+ * geotransformation should be placed.
  *
  * @return TRUE on success or FALSE on failure.
  */
 
-int CPL_STDCALL 
+int CPL_STDCALL
 GDALReadWorldFile( const char *pszBaseFilename, const char *pszExtension,
                    double *padfGeoTransform )
 
@@ -1539,7 +1635,7 @@ int GDALReadWorldFile2( const char *pszBaseFilename, const char *pszExtension,
         szDerivedExtension[1] = oBaseExt[oBaseExt.length()-1];
         szDerivedExtension[2] = 'w';
         szDerivedExtension[3] = '\0';
-        
+
         if( GDALReadWorldFile2( pszBaseFilename, szDerivedExtension,
                                 padfGeoTransform, papszSiblingFiles,
                                 ppszWorldFileNameOut ) )
@@ -1549,8 +1645,7 @@ int GDALReadWorldFile2( const char *pszBaseFilename, const char *pszExtension,
         if( oBaseExt.length() > sizeof(szDerivedExtension)-2 )
             return FALSE;
 
-        strcpy( szDerivedExtension, oBaseExt.c_str() );
-        strcat( szDerivedExtension, "w" );
+        snprintf( szDerivedExtension, sizeof(szDerivedExtension), "%sw", oBaseExt.c_str() );
         return GDALReadWorldFile2( pszBaseFilename, szDerivedExtension,
                                   padfGeoTransform, papszSiblingFiles,
                                   ppszWorldFileNameOut );
@@ -1575,7 +1670,6 @@ int GDALReadWorldFile2( const char *pszBaseFilename, const char *pszExtension,
     }
 
     VSIStatBufL sStatBuf;
-    int bGotTFW;
 
     pszTFW = CPLResetExtension( pszBaseFilename, szExtLower );
 
@@ -1602,14 +1696,14 @@ int GDALReadWorldFile2( const char *pszBaseFilename, const char *pszExtension,
 /*      Try lower case, then upper case.                                */
 /* -------------------------------------------------------------------- */
 
-    bGotTFW = VSIStatExL( pszTFW, &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0;
+    bool bGotTFW = VSIStatExL( pszTFW, &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0;
 
     if( !bGotTFW  && VSIIsCaseSensitiveFS(pszTFW) )
     {
         pszTFW = CPLResetExtension( pszBaseFilename, szExtUpper );
         bGotTFW = VSIStatExL( pszTFW, &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0;
     }
-    
+
     if( !bGotTFW )
         return FALSE;
 
@@ -1626,19 +1720,19 @@ int GDALReadWorldFile2( const char *pszBaseFilename, const char *pszExtension,
 }
 
 /************************************************************************/
-/*                         GDALWriteWorldFile()                          */
+/*                         GDALWriteWorldFile()                         */
 /*                                                                      */
-/*      Helper function for translator implementators wanting           */
+/*      Helper function for translator implementer wanting              */
 /*      support for ESRI world files.                                   */
 /************************************************************************/
 
 /**
- * \brief Write ESRI world file. 
+ * \brief Write ESRI world file.
  *
  * This function writes an ESRI style world file from the passed geotransform.
  *
  * The world file contains an affine transformation with the parameters
- * in a different order than in a geotransform array. 
+ * in a different order than in a geotransform array.
  *
  * <ul>
  * <li> geotransform[1] : width of pixel
@@ -1650,14 +1744,14 @@ int GDALReadWorldFile2( const char *pszBaseFilename, const char *pszExtension,
  * </ul>
  *
  * @param pszBaseFilename the target raster file.
- * @param pszExtension the extension to use (ie. ".wld"). Must not be NULL
- * @param padfGeoTransform the six double array from which the 
- * geotransformation should be read. 
+ * @param pszExtension the extension to use (i.e. ".wld"). Must not be NULL
+ * @param padfGeoTransform the six double array from which the
+ * geotransformation should be read.
  *
  * @return TRUE on success or FALSE on failure.
  */
 
-int CPL_STDCALL 
+int CPL_STDCALL
 GDALWriteWorldFile( const char * pszBaseFilename, const char *pszExtension,
                     double *padfGeoTransform )
 
@@ -1671,12 +1765,12 @@ GDALWriteWorldFile( const char * pszBaseFilename, const char *pszExtension,
 /* -------------------------------------------------------------------- */
     CPLString osTFWText;
 
-    osTFWText.Printf( "%.10f\n%.10f\n%.10f\n%.10f\n%.10f\n%.10f\n", 
+    osTFWText.Printf( "%.10f\n%.10f\n%.10f\n%.10f\n%.10f\n%.10f\n",
                       padfGeoTransform[1],
                       padfGeoTransform[4],
                       padfGeoTransform[2],
                       padfGeoTransform[5],
-                      padfGeoTransform[0] 
+                      padfGeoTransform[0]
                       + 0.5 * padfGeoTransform[1]
                       + 0.5 * padfGeoTransform[2],
                       padfGeoTransform[3]
@@ -1684,7 +1778,7 @@ GDALWriteWorldFile( const char * pszBaseFilename, const char *pszExtension,
                       + 0.5 * padfGeoTransform[5] );
 
 /* -------------------------------------------------------------------- */
-/*      Update extention, and write to disk.                            */
+/*      Update extension, and write to disk.                            */
 /* -------------------------------------------------------------------- */
     const char  *pszTFW;
     VSILFILE    *fpTFW;
@@ -1694,10 +1788,11 @@ GDALWriteWorldFile( const char * pszBaseFilename, const char *pszExtension,
     if( fpTFW == NULL )
         return FALSE;
 
-    VSIFWriteL( (void *) osTFWText.c_str(), 1, osTFWText.size(), fpTFW );
-    VSIFCloseL( fpTFW );
+    int bRet = ( VSIFWriteL( (void *) osTFWText.c_str(), osTFWText.size(), 1, fpTFW ) == 1 );
+    if( VSIFCloseL( fpTFW ) != 0 )
+        bRet = FALSE;
 
-    return TRUE;
+    return bRet;
 }
 
 /************************************************************************/
@@ -1709,17 +1804,17 @@ GDALWriteWorldFile( const char * pszBaseFilename, const char *pszExtension,
  *
  * Available pszRequest values:
  * <ul>
- * <li> "VERSION_NUM": Returns GDAL_VERSION_NUM formatted as a string.  ie. "1170"
+ * <li> "VERSION_NUM": Returns GDAL_VERSION_NUM formatted as a string.  i.e. "1170"
  *      Note: starting with GDAL 1.10, this string will be longer than 4 characters.
- * <li> "RELEASE_DATE": Returns GDAL_RELEASE_DATE formatted as a string.  
- * ie. "20020416".
+ * <li> "RELEASE_DATE": Returns GDAL_RELEASE_DATE formatted as a string.
+ * i.e. "20020416".
  * <li> "RELEASE_NAME": Returns the GDAL_RELEASE_NAME. ie. "1.1.7"
- * <li> "--version": Returns one line version message suitable for use in 
- * response to --version requests.  ie. "GDAL 1.1.7, released 2002/04/16"
+ * <li> "--version": Returns one line version message suitable for use in
+ * response to --version requests.  i.e. "GDAL 1.1.7, released 2002/04/16"
  * <li> "LICENSE": Returns the content of the LICENSE.TXT file from the GDAL_DATA directory.
  *      Before GDAL 1.7.0, the returned string was leaking memory but this is now resolved.
  *      So the result should not been freed by the caller.
- * <li> "BUILD_INFO": List of NAME=VALUE pairs separated by newlines with 
+ * <li> "BUILD_INFO": List of NAME=VALUE pairs separated by newlines with
  * information on build time options.
  * </ul>
  *
@@ -1734,7 +1829,7 @@ const char * CPL_STDCALL GDALVersionInfo( const char *pszRequest )
 /* -------------------------------------------------------------------- */
 /*      Try to capture as much build information as practical.          */
 /* -------------------------------------------------------------------- */
-    if( pszRequest != NULL && EQUAL(pszRequest,"BUILD_INFO") ) 
+    if( pszRequest != NULL && EQUAL(pszRequest,"BUILD_INFO") )
     {
         CPLString osBuildInfo;
 
@@ -1744,9 +1839,7 @@ const char * CPL_STDCALL GDALVersionInfo( const char *pszRequest )
 #ifdef PAM_ENABLED
         osBuildInfo += "PAM_ENABLED=YES\n";
 #endif
-#ifdef OGR_ENABLED
         osBuildInfo += "OGR_ENABLED=YES\n";
-#endif
 
         CPLFree(CPLGetTLS(CTLS_VERSIONINFO));
         CPLSetTLS(CTLS_VERSIONINFO, CPLStrdup(osBuildInfo), TRUE );
@@ -1774,15 +1867,18 @@ const char * CPL_STDCALL GDALVersionInfo( const char *pszRequest )
 
         if( fp != NULL )
         {
-            VSIFSeekL( fp, 0, SEEK_END );
-            nLength = (int) VSIFTellL( fp ) + 1;
-            VSIFSeekL( fp, SEEK_SET, 0 );
-
-            pszResultLicence = (char *) VSICalloc(1,nLength);
-            if (pszResultLicence)
-                VSIFReadL( pszResultLicence, 1, nLength-1, fp );
+            if( VSIFSeekL( fp, 0, SEEK_END ) == 0 )
+            {
+                nLength = (int) VSIFTellL( fp ) + 1;
+                if( VSIFSeekL( fp, SEEK_SET, 0 ) == 0 )
+                {
+                    pszResultLicence = (char *) VSICalloc(1,nLength);
+                    if (pszResultLicence)
+                        CPL_IGNORE_RET_VAL(VSIFReadL( pszResultLicence, 1, nLength-1, fp ));
+                }
+            }
 
-            VSIFCloseL( fp );
+            CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
         }
 
         if (!pszResultLicence)
@@ -1810,13 +1906,13 @@ const char * CPL_STDCALL GDALVersionInfo( const char *pszRequest )
         osVersionInfo.Printf( GDAL_RELEASE_NAME );
     else // --version
         osVersionInfo.Printf( "GDAL %s, released %d/%02d/%02d",
-                              GDAL_RELEASE_NAME, 
-                              GDAL_RELEASE_DATE / 10000, 
+                              GDAL_RELEASE_NAME,
+                              GDAL_RELEASE_DATE / 10000,
                               (GDAL_RELEASE_DATE % 10000) / 100,
                               GDAL_RELEASE_DATE % 100 );
 
     CPLFree(CPLGetTLS(CTLS_VERSIONINFO)); // clear old value.
-    CPLSetTLS(CTLS_VERSIONINFO, CPLStrdup(osVersionInfo), TRUE ); 
+    CPLSetTLS(CTLS_VERSIONINFO, CPLStrdup(osVersionInfo), TRUE );
     return (char *) CPLGetTLS(CTLS_VERSIONINFO);
 }
 
@@ -1826,16 +1922,18 @@ const char * CPL_STDCALL GDALVersionInfo( const char *pszRequest )
 
 /** Return TRUE if GDAL library version at runtime matches nVersionMajor.nVersionMinor.
 
-    The purpose of this method is to ensure that calling code will run with the GDAL
-    version it is compiled for. It is primarly intented for external plugins.
+    The purpose of this method is to ensure that calling code will run
+    with the GDAL version it is compiled for. It is primarily intended
+    for external plugins.
 
     @param nVersionMajor Major version to be tested against
     @param nVersionMinor Minor version to be tested against
     @param pszCallingComponentName If not NULL, in case of version mismatch, the method
-                                   will issue a failure mentionning the name of
+                                   will issue a failure mentioning the name of
                                    the calling component.
 
-    @return TRUE if GDAL library version at runtime matches nVersionMajor.nVersionMinor, FALSE otherwise.
+    @return TRUE if GDAL library version at runtime matches
+    nVersionMajor.nVersionMinor, FALSE otherwise.
   */
 int CPL_STDCALL GDALCheckVersion( int nVersionMajor, int nVersionMinor,
                                   const char* pszCallingComponentName)
@@ -1905,29 +2003,29 @@ double CPL_STDCALL GDALDecToPackedDMS( double dfDec )
 /************************************************************************/
 
 /**
- * \brief Generate Geotransform from GCPs. 
+ * \brief Generate Geotransform from GCPs.
  *
- * Given a set of GCPs perform first order fit as a geotransform. 
+ * Given a set of GCPs perform first order fit as a geotransform.
  *
- * Due to imprecision in the calculations the fit algorithm will often 
+ * Due to imprecision in the calculations the fit algorithm will often
  * return non-zero rotational coefficients even if given perfectly non-rotated
  * inputs.  A special case has been implemented for corner corner coordinates
  * given in TL, TR, BR, BL order.  So when using this to get a geotransform
- * from 4 corner coordinates, pass them in this order. 
- * 
+ * from 4 corner coordinates, pass them in this order.
+ *
  * @param nGCPCount the number of GCPs being passed in.
- * @param pasGCPs the list of GCP structures. 
- * @param padfGeoTransform the six double array in which the affine 
- * geotransformation will be returned. 
- * @param bApproxOK If FALSE the function will fail if the geotransform is not 
- * essentially an exact fit (within 0.25 pixel) for all GCPs. 
- * 
+ * @param pasGCPs the list of GCP structures.
+ * @param padfGeoTransform the six double array in which the affine
+ * geotransformation will be returned.
+ * @param bApproxOK If FALSE the function will fail if the geotransform is not
+ * essentially an exact fit (within 0.25 pixel) for all GCPs.
+ *
  * @return TRUE on success or FALSE if there aren't enough points to prepare a
- * geotransform, the pointers are ill-determined or if bApproxOK is FALSE 
+ * geotransform, the pointers are ill-determined or if bApproxOK is FALSE
  * and the fit is poor.
  */
 
-int CPL_STDCALL 
+int CPL_STDCALL
 GDALGCPsToGeoTransform( int nGCPCount, const GDAL_GCP *pasGCPs,
                         double *padfGeoTransform, int bApproxOK )
 
@@ -1942,7 +2040,7 @@ GDALGCPsToGeoTransform( int nGCPCount, const GDAL_GCP *pasGCPs,
 
     if( nGCPCount == 2 )
     {
-        if( pasGCPs[1].dfGCPPixel == pasGCPs[0].dfGCPPixel 
+        if( pasGCPs[1].dfGCPPixel == pasGCPs[0].dfGCPPixel
             || pasGCPs[1].dfGCPLine == pasGCPs[0].dfGCPLine )
             return FALSE;
 
@@ -1953,12 +2051,12 @@ GDALGCPsToGeoTransform( int nGCPCount, const GDAL_GCP *pasGCPs,
         padfGeoTransform[4] = 0.0;
         padfGeoTransform[5] = (pasGCPs[1].dfGCPY - pasGCPs[0].dfGCPY)
             / (pasGCPs[1].dfGCPLine - pasGCPs[0].dfGCPLine);
-        
-        padfGeoTransform[0] = pasGCPs[0].dfGCPX 
+
+        padfGeoTransform[0] = pasGCPs[0].dfGCPX
             - pasGCPs[0].dfGCPPixel * padfGeoTransform[1]
             - pasGCPs[0].dfGCPLine * padfGeoTransform[2];
-        
-        padfGeoTransform[3] = pasGCPs[0].dfGCPY 
+
+        padfGeoTransform[3] = pasGCPs[0].dfGCPY
             - pasGCPs[0].dfGCPPixel * padfGeoTransform[4]
             - pasGCPs[0].dfGCPLine * padfGeoTransform[5];
 
@@ -1969,15 +2067,15 @@ GDALGCPsToGeoTransform( int nGCPCount, const GDAL_GCP *pasGCPs,
 /*      Special case of 4 corner coordinates of a non-rotated           */
 /*      image.  The points must be in TL-TR-BR-BL order for now.        */
 /*      This case helps avoid some imprecision in the general           */
-/*      calcuations.                                                    */
+/*      calculations.                                                   */
 /* -------------------------------------------------------------------- */
-    if( nGCPCount == 4 
+    if( nGCPCount == 4
         && pasGCPs[0].dfGCPLine == pasGCPs[1].dfGCPLine
         && pasGCPs[2].dfGCPLine == pasGCPs[3].dfGCPLine
         && pasGCPs[0].dfGCPPixel == pasGCPs[3].dfGCPPixel
         && pasGCPs[1].dfGCPPixel == pasGCPs[2].dfGCPPixel
         && pasGCPs[0].dfGCPLine != pasGCPs[2].dfGCPLine
-        && pasGCPs[0].dfGCPPixel != pasGCPs[1].dfGCPPixel 
+        && pasGCPs[0].dfGCPPixel != pasGCPs[1].dfGCPPixel
         && pasGCPs[0].dfGCPY == pasGCPs[1].dfGCPY
         && pasGCPs[2].dfGCPY == pasGCPs[3].dfGCPY
         && pasGCPs[0].dfGCPX == pasGCPs[3].dfGCPX
@@ -1992,9 +2090,9 @@ GDALGCPsToGeoTransform( int nGCPCount, const GDAL_GCP *pasGCPs,
         padfGeoTransform[5] = (pasGCPs[2].dfGCPY - pasGCPs[1].dfGCPY)
             / (pasGCPs[2].dfGCPLine - pasGCPs[1].dfGCPLine);
 
-        padfGeoTransform[0] = 
+        padfGeoTransform[0] =
             pasGCPs[0].dfGCPX - pasGCPs[0].dfGCPPixel * padfGeoTransform[1];
-        padfGeoTransform[3] = 
+        padfGeoTransform[3] =
             pasGCPs[0].dfGCPY - pasGCPs[0].dfGCPLine * padfGeoTransform[5];
         return TRUE;
     }
@@ -2028,13 +2126,13 @@ GDALGCPsToGeoTransform( int nGCPCount, const GDAL_GCP *pasGCPs,
     if( ABS(max_pixel - min_pixel) < EPS
         || ABS(max_line - min_line) < EPS
         || ABS(max_geox - min_geox) < EPS
-        || ABS(max_geoy - min_geoy) < EPS) 
+        || ABS(max_geoy - min_geoy) < EPS)
     {
         return FALSE;  // degenerate in at least one dimension.
     }
 
     double pl_normalize[6], geo_normalize[6];
-    
+
     pl_normalize[0] = -min_pixel / (max_pixel - min_pixel);
     pl_normalize[1] = 1.0 / (max_pixel - min_pixel);
     pl_normalize[2] = 0.0;
@@ -2053,7 +2151,7 @@ GDALGCPsToGeoTransform( int nGCPCount, const GDAL_GCP *pasGCPs,
 /* In the general case, do a least squares error approximation by       */
 /* solving the equation Sum[(A - B*x + C*y - Lon)^2] = minimum		*/
 /* -------------------------------------------------------------------- */
-	
+
     double sum_x = 0.0, sum_y = 0.0, sum_xy = 0.0, sum_xx = 0.0, sum_yy = 0.0;
     double sum_Lon = 0.0, sum_Lonx = 0.0, sum_Lony = 0.0;
     double sum_Lat = 0.0, sum_Latx = 0.0, sum_Laty = 0.0;
@@ -2062,11 +2160,11 @@ GDALGCPsToGeoTransform( int nGCPCount, const GDAL_GCP *pasGCPs,
     for (i = 0; i < nGCPCount; ++i) {
         double pixel, line, geox, geoy;
 
-        GDALApplyGeoTransform(pl_normalize, 
+        GDALApplyGeoTransform(pl_normalize,
                               pasGCPs[i].dfGCPPixel,
                               pasGCPs[i].dfGCPLine,
                               &pixel, &line);
-        GDALApplyGeoTransform(geo_normalize, 
+        GDALApplyGeoTransform(geo_normalize,
                               pasGCPs[i].dfGCPX,
                               pasGCPs[i].dfGCPY,
                               &geox, &geoy);
@@ -2105,7 +2203,7 @@ GDALGCPsToGeoTransform( int nGCPCount, const GDAL_GCP *pasGCPs,
 
     gt_normalized[3] = (sum_Lat * (sum_xx * sum_yy - sum_xy * sum_xy)
                   + sum_Latx * (sum_y * sum_xy - sum_x *  sum_yy)
-                  + sum_Laty * (sum_x * sum_xy - sum_y * sum_xx)) 
+                  + sum_Laty * (sum_x * sum_xy - sum_y * sum_xx))
         / divisor;
 
 /* -------------------------------------------------------------------- */
@@ -2144,7 +2242,7 @@ GDALGCPsToGeoTransform( int nGCPCount, const GDAL_GCP *pasGCPs,
 
     GDALComposeGeoTransforms(pl_normalize, gt_normalized, gt1p2);
     GDALComposeGeoTransforms(gt1p2, inv_geo_normalize, padfGeoTransform);
-    
+
 /* -------------------------------------------------------------------- */
 /*      Now check if any of the input points fit this poorly.           */
 /* -------------------------------------------------------------------- */
@@ -2152,7 +2250,7 @@ GDALGCPsToGeoTransform( int nGCPCount, const GDAL_GCP *pasGCPs,
     {
         // FIXME? Not sure if it is the more accurate way of computing
         // pixel size
-        double dfPixelSize = 0.5 * (ABS(padfGeoTransform[1]) 
+        double dfPixelSize = 0.5 * (ABS(padfGeoTransform[1])
             + ABS(padfGeoTransform[2])
             + ABS(padfGeoTransform[4])
             + ABS(padfGeoTransform[5]));
@@ -2161,18 +2259,18 @@ GDALGCPsToGeoTransform( int nGCPCount, const GDAL_GCP *pasGCPs,
         {
             double      dfErrorX, dfErrorY;
 
-            dfErrorX = 
+            dfErrorX =
                 (pasGCPs[i].dfGCPPixel * padfGeoTransform[1]
                  + pasGCPs[i].dfGCPLine * padfGeoTransform[2]
-                 + padfGeoTransform[0]) 
+                 + padfGeoTransform[0])
                 - pasGCPs[i].dfGCPX;
-            dfErrorY = 
+            dfErrorY =
                 (pasGCPs[i].dfGCPPixel * padfGeoTransform[4]
                  + pasGCPs[i].dfGCPLine * padfGeoTransform[5]
-                 + padfGeoTransform[3]) 
+                 + padfGeoTransform[3])
                 - pasGCPs[i].dfGCPY;
 
-            if( ABS(dfErrorX) > 0.25 * dfPixelSize 
+            if( ABS(dfErrorX) > 0.25 * dfPixelSize
                 || ABS(dfErrorY) > 0.25 * dfPixelSize )
             {
                 CPLDebug("GDAL", "dfErrorX/dfPixelSize = %.2f, dfErrorY/dfPixelSize = %.2f",
@@ -2192,16 +2290,16 @@ GDALGCPsToGeoTransform( int nGCPCount, const GDAL_GCP *pasGCPs,
 /**
  * \brief Compose two geotransforms.
  *
- * The resulting geotransform is the equivelent to padfGT1 and then padfGT2
+ * The resulting geotransform is the equivalent to padfGT1 and then padfGT2
  * being applied to a point.
- * 
+ *
  * @param padfGT1 the first geotransform, six values.
  * @param padfGT2 the second geotransform, six values.
  * @param padfGTOut the output geotransform, six values, may safely be the same
  * array as padfGT1 or padfGT2.
  */
 
-void GDALComposeGeoTransforms(const double *padfGT1, const double *padfGT2, 
+void GDALComposeGeoTransforms(const double *padfGT1, const double *padfGT2,
                               double *padfGTOut)
 
 {
@@ -2209,34 +2307,34 @@ void GDALComposeGeoTransforms(const double *padfGT1, const double *padfGT2,
     // We need to think of the geotransform in a more normal form to do
     // the matrix multiple:
     //
-    //  __                     __ 
+    //  __                     __
     //  | gt[1]   gt[2]   gt[0] |
     //  | gt[4]   gt[5]   gt[3] |
     //  |  0.0     0.0     1.0  |
     //  --                     --
-    // 
-    // Then we can use normal matrix multiplication to produce the 
-    // composed transformation.  I don't actually reform the matrix 
+    //
+    // Then we can use normal matrix multiplication to produce the
+    // composed transformation.  I don't actually reform the matrix
     // explicitly which is why the following may seem kind of spagettish.
 
-    gtwrk[1] = 
+    gtwrk[1] =
         padfGT2[1] * padfGT1[1]
         + padfGT2[2] * padfGT1[4];
-    gtwrk[2] = 
+    gtwrk[2] =
         padfGT2[1] * padfGT1[2]
         + padfGT2[2] * padfGT1[5];
-    gtwrk[0] = 
+    gtwrk[0] =
         padfGT2[1] * padfGT1[0]
         + padfGT2[2] * padfGT1[3]
         + padfGT2[0] * 1.0;
 
-    gtwrk[4] = 
+    gtwrk[4] =
         padfGT2[4] * padfGT1[1]
         + padfGT2[5] * padfGT1[4];
-    gtwrk[5] = 
+    gtwrk[5] =
         padfGT2[4] * padfGT1[2]
         + padfGT2[5] * padfGT1[5];
-    gtwrk[3] = 
+    gtwrk[3] =
         padfGT2[4] * padfGT1[0]
         + padfGT2[5] * padfGT1[3]
         + padfGT2[3] * 1.0;
@@ -2250,30 +2348,30 @@ void GDALComposeGeoTransforms(const double *padfGT1, const double *padfGT2,
 /**
  * \brief General utility option processing.
  *
- * This function is intended to provide a variety of generic commandline 
+ * This function is intended to provide a variety of generic commandline
  * options for all GDAL commandline utilities.  It takes care of the following
  * commandline options:
- *  
- *  --version: report version of GDAL in use. 
+ *
+ *  --version: report version of GDAL in use.
  *  --build: report build info about GDAL in use.
  *  --license: report GDAL license info.
  *  --formats: report all format drivers configured.
- *  --format [format]: report details of one format driver. 
- *  --optfile filename: expand an option file into the argument list. 
- *  --config key value: set system configuration option. 
+ *  --format [format]: report details of one format driver.
+ *  --optfile filename: expand an option file into the argument list.
+ *  --config key value: set system configuration option.
  *  --debug [on/off/value]: set debug level.
  *  --mempreload dir: preload directory contents into /vsimem
  *  --pause: Pause for user input (allows time to attach debugger)
  *  --locale [locale]: Install a locale using setlocale() (debugging)
- *  --help-general: report detailed help on general options. 
+ *  --help-general: report detailed help on general options.
  *
- * The argument array is replaced "in place" and should be freed with 
+ * The argument array is replaced "in place" and should be freed with
  * CSLDestroy() when no longer needed.  The typical usage looks something
  * like the following.  Note that the formats should be registered so that
  * the --formats and --format options will work properly.
  *
  *  int main( int argc, char ** argv )
- *  { 
+ *  {
  *    GDALAllRegister();
  *
  *    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
@@ -2286,11 +2384,11 @@ void GDALComposeGeoTransforms(const double *padfGT1, const double *padfGT2,
  *                 to determine which drivers should be displayed by --formats.
  *                 If set to 0, GDAL_OF_RASTER is assumed.
  *
- * @return updated nArgc argument count.  Return of 0 requests terminate 
+ * @return updated nArgc argument count.  Return of 0 requests terminate
  * without error, return of -1 requests exit with error code.
  */
 
-int CPL_STDCALL 
+int CPL_STDCALL
 GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
 
 {
@@ -2345,7 +2443,7 @@ GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
         {
             if( iArg + 2 >= nArgc )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "--config option given without a key and value argument." );
                 CSLDestroy( papszReturn );
                 return -1;
@@ -2361,57 +2459,55 @@ GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
 /* -------------------------------------------------------------------- */
         else if( EQUAL(papszArgv[iArg],"--mempreload") )
         {
-            int i;
-
             if( iArg + 1 >= nArgc )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "--mempreload option given without directory path.");
                 CSLDestroy( papszReturn );
                 return -1;
             }
-            
-            char **papszFiles = CPLReadDir( papszArgv[iArg+1] );
+
+            char **papszFiles = VSIReadDir( papszArgv[iArg+1] );
             if( CSLCount(papszFiles) == 0 )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "--mempreload given invalid or empty directory.");
                 CSLDestroy( papszReturn );
                 return -1;
             }
-                
-            for( i = 0; papszFiles[i] != NULL; i++ )
+
+            for( int i = 0; papszFiles[i] != NULL; i++ )
             {
-                CPLString osOldPath, osNewPath;
-                VSIStatBufL sStatBuf;
-                
                 if( EQUAL(papszFiles[i],".") || EQUAL(papszFiles[i],"..") )
                     continue;
 
-                osOldPath = CPLFormFilename( papszArgv[iArg+1], 
+                CPLString osOldPath, osNewPath;
+                osOldPath = CPLFormFilename( papszArgv[iArg+1],
                                              papszFiles[i], NULL );
                 osNewPath.Printf( "/vsimem/%s", papszFiles[i] );
 
+                VSIStatBufL sStatBuf;
                 if( VSIStatL( osOldPath, &sStatBuf ) != 0
                     || VSI_ISDIR( sStatBuf.st_mode ) )
                 {
-                    CPLDebug( "VSI", "Skipping preload of %s.", 
+                    CPLDebug( "VSI", "Skipping preload of %s.",
                               osOldPath.c_str() );
                     continue;
                 }
 
-                CPLDebug( "VSI", "Preloading %s to %s.", 
+                CPLDebug( "VSI", "Preloading %s to %s.",
                           osOldPath.c_str(), osNewPath.c_str() );
 
                 if( CPLCopyFile( osNewPath, osOldPath ) != 0 )
                 {
                     CPLError( CE_Failure, CPLE_AppDefined,
-                              "Failed to copy %s to /vsimem", 
+                              "Failed to copy %s to /vsimem",
                               osOldPath.c_str() );
+                    CSLDestroy( papszReturn );
                     return -1;
                 }
             }
-            
+
             CSLDestroy( papszFiles );
             iArg += 1;
         }
@@ -2423,7 +2519,7 @@ GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
         {
             if( iArg + 1 >= nArgc )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "--debug option given without debug level." );
                 CSLDestroy( papszReturn );
                 return -1;
@@ -2441,44 +2537,39 @@ GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
 /* -------------------------------------------------------------------- */
         else if( EQUAL(papszArgv[iArg],"--optfile") )
         {
-            const char *pszLine;
-            FILE *fpOptFile;
-
             if( iArg + 1 >= nArgc )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "--optfile option given without filename." );
                 CSLDestroy( papszReturn );
                 return -1;
             }
 
-            fpOptFile = VSIFOpen( papszArgv[iArg+1], "rb" );
+            VSILFILE *fpOptFile = VSIFOpenL( papszArgv[iArg+1], "rb" );
 
             if( fpOptFile == NULL )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "Unable to open optfile '%s'.\n%s",
                           papszArgv[iArg+1], VSIStrerror( errno ) );
                 CSLDestroy( papszReturn );
                 return -1;
             }
-            
-            while( (pszLine = CPLReadLine( fpOptFile )) != NULL )
-            {
-                char **papszTokens;
-                int i;
 
+            const char *pszLine;
+            while( (pszLine = CPLReadLineL( fpOptFile )) != NULL )
+            {
                 if( pszLine[0] == '#' || strlen(pszLine) == 0 )
                     continue;
 
-                papszTokens = CSLTokenizeString( pszLine );
-                for( i = 0; papszTokens != NULL && papszTokens[i] != NULL; i++)
+                char **papszTokens = CSLTokenizeString( pszLine );
+                for( int i = 0; papszTokens != NULL && papszTokens[i] != NULL; i++)
                     papszReturn = CSLAddString( papszReturn, papszTokens[i] );
                 CSLDestroy( papszTokens );
             }
 
-            VSIFClose( fpOptFile );
-                
+            VSIFCloseL( fpOptFile );
+
             iArg += 1;
         }
 
@@ -2487,13 +2578,11 @@ GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
 /* -------------------------------------------------------------------- */
         else if( EQUAL(papszArgv[iArg], "--formats") )
         {
-            int iDr;
-            
             if( nOptions == 0 )
                 nOptions = GDAL_OF_RASTER;
 
             printf( "Supported Formats:\n" );
-            for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
+            for( int iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
             {
                 GDALDriverH hDriver = GDALGetDriver(iDr);
 
@@ -2506,6 +2595,9 @@ GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
                 if( nOptions == GDAL_OF_VECTOR &&
                     !CSLFetchBoolean( papszMD, GDAL_DCAP_VECTOR, FALSE ) )
                     continue;
+                if( nOptions == GDAL_OF_GNM &&
+                    !CSLFetchBoolean( papszMD, GDAL_DCAP_GNM, FALSE ) )
+                    continue;
 
                 if( CSLFetchBoolean( papszMD, GDAL_DCAP_OPEN, FALSE ) )
                     pszRFlag = "r";
@@ -2534,6 +2626,8 @@ GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
                     pszKind = "raster";
                 else if( CSLFetchBoolean( papszMD, GDAL_DCAP_VECTOR, FALSE ) )
                     pszKind = "vector";
+                else if( CSLFetchBoolean( papszMD, GDAL_DCAP_GNM, FALSE ) )
+                    pszKind = "geography network";
                 else
                     pszKind = "unknown kind";
 
@@ -2560,7 +2654,7 @@ GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
 
             if( iArg + 1 >= nArgc )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "--format option given without a format code." );
                 return -1;
             }
@@ -2568,10 +2662,12 @@ GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
             hDriver = GDALGetDriverByName( papszArgv[iArg+1] );
             if( hDriver == NULL )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                          "--format option given with format '%s', but that format not\n"
-                          "recognised.  Use the --formats option to get a list of available formats,\n"
-                          "and use the short code (ie. GTiff or HFA) as the format identifier.\n", 
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "--format option given with format '%s', but that "
+                          "format not\nrecognised.  Use the --formats option "
+                          "to get a list of available formats,\n"
+                          "and use the short code (i.e. GTiff or HFA) as the "
+                          "format identifier.\n",
                           papszArgv[iArg+1] );
                 return -1;
             }
@@ -2585,6 +2681,8 @@ GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
                 printf( "  Supports: Raster\n" );
             if( CSLFetchBoolean( papszMD, GDAL_DCAP_VECTOR, FALSE ) )
                 printf( "  Supports: Vector\n" );
+            if( CSLFetchBoolean( papszMD, GDAL_DCAP_GNM, FALSE ) )
+                printf( "  Supports: Geography Network\n" );
 
             const char* pszExt = CSLFetchNameValue( papszMD, GDAL_DMD_EXTENSIONS );
             if( pszExt != NULL )
@@ -2592,18 +2690,18 @@ GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
                         pszExt );
 
             if( CSLFetchNameValue( papszMD, GDAL_DMD_MIMETYPE ) )
-                printf( "  Mime Type: %s\n", 
+                printf( "  Mime Type: %s\n",
                         CSLFetchNameValue( papszMD, GDAL_DMD_MIMETYPE ) );
             if( CSLFetchNameValue( papszMD, GDAL_DMD_HELPTOPIC ) )
-                printf( "  Help Topic: %s\n", 
+                printf( "  Help Topic: %s\n",
                         CSLFetchNameValue( papszMD, GDAL_DMD_HELPTOPIC ) );
-            
+
             if( CSLFetchBoolean( papszMD, GDAL_DMD_SUBDATASETS, FALSE ) )
                 printf( "  Supports: Subdatasets\n" );
             if( CSLFetchBoolean( papszMD, GDAL_DCAP_OPEN, FALSE ) )
                 printf( "  Supports: Open() - Open existing dataset.\n" );
             if( CSLFetchBoolean( papszMD, GDAL_DCAP_CREATE, FALSE ) )
-                printf( "  Supports: Create() - Create writeable dataset.\n" );
+                printf( "  Supports: Create() - Create writable dataset.\n" );
             if( CSLFetchBoolean( papszMD, GDAL_DCAP_CREATECOPY, FALSE ) )
                 printf( "  Supports: CreateCopy() - Create dataset by copying another.\n" );
             if( CSLFetchBoolean( papszMD, GDAL_DCAP_VIRTUALIO, FALSE ) )
@@ -2622,48 +2720,48 @@ GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
                 printf( "  Supports: Creating geometry fields with NOT NULL constraint.\n" );
             if( CSLFetchNameValue( papszMD, GDAL_DMD_CREATIONOPTIONLIST ) )
             {
-                CPLXMLNode *psCOL = 
-                    CPLParseXMLString( 
-                        CSLFetchNameValue( papszMD, 
+                CPLXMLNode *psCOL =
+                    CPLParseXMLString(
+                        CSLFetchNameValue( papszMD,
                                            GDAL_DMD_CREATIONOPTIONLIST ) );
-                char *pszFormattedXML = 
+                char *pszFormattedXML =
                     CPLSerializeXMLTree( psCOL );
 
                 CPLDestroyXMLNode( psCOL );
-                
+
                 printf( "\n%s\n", pszFormattedXML );
                 CPLFree( pszFormattedXML );
             }
             if( CSLFetchNameValue( papszMD, GDAL_DS_LAYER_CREATIONOPTIONLIST ) )
             {
-                CPLXMLNode *psCOL = 
-                    CPLParseXMLString( 
-                        CSLFetchNameValue( papszMD, 
+                CPLXMLNode *psCOL =
+                    CPLParseXMLString(
+                        CSLFetchNameValue( papszMD,
                                            GDAL_DS_LAYER_CREATIONOPTIONLIST ) );
-                char *pszFormattedXML = 
+                char *pszFormattedXML =
                     CPLSerializeXMLTree( psCOL );
 
                 CPLDestroyXMLNode( psCOL );
-                
+
                 printf( "\n%s\n", pszFormattedXML );
                 CPLFree( pszFormattedXML );
             }
 
             if( CSLFetchNameValue( papszMD, GDAL_DMD_CONNECTION_PREFIX ) )
-                printf( "  Connection prefix: %s\n", 
+                printf( "  Connection prefix: %s\n",
                         CSLFetchNameValue( papszMD, GDAL_DMD_CONNECTION_PREFIX ) );
 
             if( CSLFetchNameValue( papszMD, GDAL_DMD_OPENOPTIONLIST ) )
             {
-                CPLXMLNode *psCOL = 
-                    CPLParseXMLString( 
-                        CSLFetchNameValue( papszMD, 
+                CPLXMLNode *psCOL =
+                    CPLParseXMLString(
+                        CSLFetchNameValue( papszMD,
                                            GDAL_DMD_OPENOPTIONLIST ) );
-                char *pszFormattedXML = 
+                char *pszFormattedXML =
                     CPLSerializeXMLTree( psCOL );
 
                 CPLDestroyXMLNode( psCOL );
-                
+
                 printf( "%s\n", pszFormattedXML );
                 CPLFree( pszFormattedXML );
             }
@@ -2684,7 +2782,8 @@ GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
             printf( "  --config key value: set system configuration option.\n" );
             printf( "  --debug [on/off/value]: set debug level.\n" );
             printf( "  --pause: wait for user input, time to attach debugger\n" );
-            printf( "  --locale [locale]: install locale for debugging (ie. en_US.UTF-8)\n" );
+            printf( "  --locale [locale]: install locale for debugging "
+                    "(i.e. en_US.UTF-8)\n" );
             printf( "  --help-general: report detailed help on general options.\n" );
             CSLDestroy( papszReturn );
             return 0;
@@ -2703,12 +2802,13 @@ GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
 /* -------------------------------------------------------------------- */
         else if( EQUAL(papszArgv[iArg],"--pause") )
         {
-            printf( "Hit <ENTER> to Continue.\n" );
-            CPLReadLine( stdin );
+            std::cout << "Hit <ENTER> to Continue." << std::endl;
+            std::cin.clear();
+            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
         }
 
 /* -------------------------------------------------------------------- */
-/*      carry through unrecognised options.                             */
+/*      Carry through unrecognized options.                             */
 /* -------------------------------------------------------------------- */
         else
         {
@@ -2726,44 +2826,43 @@ GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
 /*                          _FetchDblFromMD()                           */
 /************************************************************************/
 
-static int _FetchDblFromMD( char **papszMD, const char *pszKey, 
-                            double *padfTarget, int nCount, double dfDefault )
+static bool _FetchDblFromMD( char **papszMD, const char *pszKey,
+                             double *padfTarget, int nCount, double dfDefault )
 
 {
     char szFullKey[200];
 
-    sprintf( szFullKey, "%s", pszKey );
+    snprintf( szFullKey, sizeof(szFullKey), "%s", pszKey );
 
     const char *pszValue = CSLFetchNameValue( papszMD, szFullKey );
-    int i;
-    
-    for( i = 0; i < nCount; i++ )
+
+    for( int i = 0; i < nCount; i++ )
         padfTarget[i] = dfDefault;
 
     if( pszValue == NULL )
-        return FALSE;
+        return false;
 
     if( nCount == 1 )
     {
         *padfTarget = CPLAtofM( pszValue );
-        return TRUE;
+        return true;
     }
 
-    char **papszTokens = CSLTokenizeStringComplex( pszValue, " ,", 
+    char **papszTokens = CSLTokenizeStringComplex( pszValue, " ,",
                                                    FALSE, FALSE );
 
     if( CSLCount( papszTokens ) != nCount )
     {
         CSLDestroy( papszTokens );
-        return FALSE;
+        return false;
     }
 
-    for( i = 0; i < nCount; i++ )
+    for( int i = 0; i < nCount; i++ )
         padfTarget[i] = CPLAtofM(papszTokens[i]);
 
     CSLDestroy( papszTokens );
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -2785,7 +2884,7 @@ int CPL_STDCALL GDALExtractRPCInfo( char **papszMD, GDALRPCInfo *psRPC )
         || CSLFetchNameValue( papszMD, RPC_SAMP_NUM_COEFF ) == NULL
         || CSLFetchNameValue( papszMD, RPC_SAMP_DEN_COEFF ) == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                  "Some required RPC metadata missing in GDALExtractRPCInfo()");
         return FALSE;
     }
@@ -2809,7 +2908,7 @@ int CPL_STDCALL GDALExtractRPCInfo( char **papszMD, GDALRPCInfo *psRPC )
                      20, 0.0 );
     _FetchDblFromMD( papszMD, RPC_SAMP_DEN_COEFF, psRPC->adfSAMP_DEN_COEFF,
                      20, 0.0 );
-    
+
     _FetchDblFromMD( papszMD, "MIN_LONG", &(psRPC->dfMIN_LONG), 1, -180.0 );
     _FetchDblFromMD( papszMD, "MIN_LAT", &(psRPC->dfMIN_LAT), 1, -90.0 );
     _FetchDblFromMD( papszMD, "MAX_LONG", &(psRPC->dfMAX_LONG), 1, 180.0 );
@@ -2845,18 +2944,16 @@ GDALDataset *GDALFindAssociatedAuxFile( const char *pszBasename,
 /*      file.  Check that we are the dependent file of the aux          */
 /*      file, or if we aren't verify that the dependent file does       */
 /*      not exist, likely mean it is us but some sort of renaming       */
-/*      has occured.                                                    */
+/*      has occurred.                                                   */
 /* -------------------------------------------------------------------- */
     CPLString osJustFile = CPLGetFilename(pszBasename); // without dir
     CPLString osAuxFilename = CPLResetExtension(pszBasename, pszAuxSuffixLC);
     GDALDataset *poODS = NULL;
     GByte abyHeader[32];
-    VSILFILE *fp;
 
-    fp = VSIFOpenL( osAuxFilename, "rb" );
+    VSILFILE *fp = VSIFOpenL( osAuxFilename, "rb" );
 
-
-    if ( fp == NULL && VSIIsCaseSensitiveFS(osAuxFilename)) 
+    if ( fp == NULL && VSIIsCaseSensitiveFS(osAuxFilename))
     {
         // Can't found file with lower case suffix. Try the upper case one.
         osAuxFilename = CPLResetExtension(pszBasename, pszAuxSuffixUC);
@@ -2866,7 +2963,7 @@ GDALDataset *GDALFindAssociatedAuxFile( const char *pszBasename,
     if( fp != NULL )
     {
         if( VSIFReadL( abyHeader, 1, 32, fp ) == 32 &&
-            EQUALN((char *) abyHeader,"EHFA_HEADER_TAG",15) )
+            STARTS_WITH_CI((char *) abyHeader, "EHFA_HEADER_TAG") )
         {
             /* Avoid causing failure in opening of main file from SWIG bindings */
             /* when auxiliary file cannot be opened (#3269) */
@@ -2877,7 +2974,7 @@ GDALDataset *GDALFindAssociatedAuxFile( const char *pszBasename,
                 poODS = (GDALDataset *) GDALOpen( osAuxFilename, eAccess );
             CPLTurnFailureIntoWarning(FALSE);
         }
-        VSIFCloseL( fp );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
     }
 
 /* -------------------------------------------------------------------- */
@@ -2889,7 +2986,7 @@ GDALDataset *GDALFindAssociatedAuxFile( const char *pszBasename,
             = poODS->GetMetadataItem( "HFA_DEPENDENT_FILE", "HFA" );
         if( pszDep == NULL  )
         {
-            CPLDebug( "AUX", 
+            CPLDebug( "AUX",
                       "Found %s but it has no dependent file, ignoring.",
                       osAuxFilename.c_str() );
             GDALClose( poODS );
@@ -2902,7 +2999,7 @@ GDALDataset *GDALFindAssociatedAuxFile( const char *pszBasename,
             if( VSIStatExL( pszDep, &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 )
             {
                 CPLDebug( "AUX", "%s is for file %s, not %s, ignoring.",
-                          osAuxFilename.c_str(), 
+                          osAuxFilename.c_str(),
                           pszDep, osJustFile.c_str() );
                 GDALClose( poODS );
                 poODS = NULL;
@@ -2911,7 +3008,7 @@ GDALDataset *GDALFindAssociatedAuxFile( const char *pszBasename,
             {
                 CPLDebug( "AUX", "%s is for file %s, not %s, but since\n"
                           "%s does not exist, we will use .aux file as our own.",
-                          osAuxFilename.c_str(), 
+                          osAuxFilename.c_str(),
                           pszDep, osJustFile.c_str(),
                           pszDep );
             }
@@ -2928,12 +3025,12 @@ GDALDataset *GDALFindAssociatedAuxFile( const char *pszBasename,
         {
             CPLDebug( "AUX",
                       "Ignoring aux file %s as its raster configuration\n"
-                      "(%dP x %dL x %dB) does not match master file (%dP x %dL x %dB)", 
+                      "(%dP x %dL x %dB) does not match master file (%dP x %dL x %dB)",
                       osAuxFilename.c_str(),
-                      poODS->GetRasterXSize(), 
+                      poODS->GetRasterXSize(),
                       poODS->GetRasterYSize(),
                       poODS->GetRasterCount(),
-                      poDependentDS->GetRasterXSize(), 
+                      poDependentDS->GetRasterXSize(),
                       poDependentDS->GetRasterYSize(),
                       poDependentDS->GetRasterCount() );
 
@@ -2941,7 +3038,7 @@ GDALDataset *GDALFindAssociatedAuxFile( const char *pszBasename,
             poODS = NULL;
         }
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Try appending .aux to the end of the filename.                  */
 /* -------------------------------------------------------------------- */
@@ -2963,7 +3060,7 @@ GDALDataset *GDALFindAssociatedAuxFile( const char *pszBasename,
         if( fp != NULL )
         {
             if( VSIFReadL( abyHeader, 1, 32, fp ) == 32 &&
-                EQUALN((char *) abyHeader,"EHFA_HEADER_TAG",15) )
+                STARTS_WITH_CI((char *) abyHeader, "EHFA_HEADER_TAG") )
             {
                 /* Avoid causing failure in opening of main file from SWIG bindings */
                 /* when auxiliary file cannot be opened (#3269) */
@@ -2974,16 +3071,16 @@ GDALDataset *GDALFindAssociatedAuxFile( const char *pszBasename,
                     poODS = (GDALDataset *) GDALOpen( osAuxFilename, eAccess );
                 CPLTurnFailureIntoWarning(FALSE);
             }
-            VSIFCloseL( fp );
+            CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
         }
- 
+
         if( poODS != NULL )
         {
             const char *pszDep
                 = poODS->GetMetadataItem( "HFA_DEPENDENT_FILE", "HFA" );
             if( pszDep == NULL  )
             {
-                CPLDebug( "AUX", 
+                CPLDebug( "AUX",
                           "Found %s but it has no dependent file, ignoring.",
                           osAuxFilename.c_str() );
                 GDALClose( poODS );
@@ -2996,7 +3093,7 @@ GDALDataset *GDALFindAssociatedAuxFile( const char *pszBasename,
                 if( VSIStatExL( pszDep, &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 )
                 {
                     CPLDebug( "AUX", "%s is for file %s, not %s, ignoring.",
-                              osAuxFilename.c_str(), 
+                              osAuxFilename.c_str(),
                               pszDep, osJustFile.c_str() );
                     GDALClose( poODS );
                     poODS = NULL;
@@ -3005,7 +3102,7 @@ GDALDataset *GDALFindAssociatedAuxFile( const char *pszBasename,
                 {
                     CPLDebug( "AUX", "%s is for file %s, not %s, but since\n"
                               "%s does not exist, we will use .aux file as our own.",
-                              osAuxFilename.c_str(), 
+                              osAuxFilename.c_str(),
                               pszDep, osJustFile.c_str(),
                               pszDep );
                 }
@@ -3024,12 +3121,12 @@ GDALDataset *GDALFindAssociatedAuxFile( const char *pszBasename,
     {
         CPLDebug( "AUX",
                   "Ignoring aux file %s as its raster configuration\n"
-                  "(%dP x %dL x %dB) does not match master file (%dP x %dL x %dB)", 
+                  "(%dP x %dL x %dB) does not match master file (%dP x %dL x %dB)",
                   osAuxFilename.c_str(),
-                  poODS->GetRasterXSize(), 
+                  poODS->GetRasterXSize(),
                   poODS->GetRasterYSize(),
                   poODS->GetRasterCount(),
-                  poDependentDS->GetRasterXSize(), 
+                  poDependentDS->GetRasterXSize(),
                   poDependentDS->GetRasterYSize(),
                   poDependentDS->GetRasterCount() );
 
@@ -3041,41 +3138,6 @@ GDALDataset *GDALFindAssociatedAuxFile( const char *pszBasename,
 }
 
 /************************************************************************/
-/* -------------------------------------------------------------------- */
-/*      The following stubs are present to ensure that older GDAL       */
-/*      bridges don't fail with newer libraries.                        */
-/* -------------------------------------------------------------------- */
-/************************************************************************/
-
-CPL_C_START
-
-void * CPL_STDCALL GDALCreateProjDef( const char * )
-{
-    CPLDebug( "GDAL", "GDALCreateProjDef no longer supported." );
-    return NULL;
-}
-
-CPLErr CPL_STDCALL GDALReprojectToLongLat( void *, double *, double * )
-{
-    CPLDebug( "GDAL", "GDALReprojectToLatLong no longer supported." );
-    return CE_Failure;
-}
-
-CPLErr CPL_STDCALL GDALReprojectFromLongLat( void *, double *, double * )
-{
-    CPLDebug( "GDAL", "GDALReprojectFromLatLong no longer supported." );
-    return CE_Failure;
-}
-
-void CPL_STDCALL GDALDestroyProjDef( void * )
-
-{
-    CPLDebug( "GDAL", "GDALDestroyProjDef no longer supported." );
-}
-
-CPL_C_END
-
-/************************************************************************/
 /* Infrastructure to check that dataset characteristics are valid       */
 /************************************************************************/
 
@@ -3105,6 +3167,7 @@ int GDALCheckDatasetDimensions( int nXSize, int nYSize )
   *
   * If the configuration option GDAL_MAX_BAND_COUNT is defined,
   * the band count will be compared to the maximum number of band allowed.
+  * If not defined, the maximum number allowed is 65536.
   *
   * @param nBands the band count
   * @param bIsZeroAllowed TRUE if band count == 0 is allowed
@@ -3114,17 +3177,21 @@ int GDALCheckDatasetDimensions( int nXSize, int nYSize )
 
 int GDALCheckBandCount( int nBands, int bIsZeroAllowed )
 {
-    int nMaxBands = -1;
-    const char* pszMaxBandCount = CPLGetConfigOption("GDAL_MAX_BAND_COUNT", NULL);
-    if (pszMaxBandCount != NULL)
+    if (nBands < 0 || (!bIsZeroAllowed && nBands == 0) )
     {
-        nMaxBands = atoi(pszMaxBandCount);
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Invalid band count : %d", nBands);
+        return FALSE;
     }
-    if (nBands < 0 || (!bIsZeroAllowed && nBands == 0) ||
-        (nMaxBands >= 0 && nBands > nMaxBands) )
+    const char* pszMaxBandCount = CPLGetConfigOption("GDAL_MAX_BAND_COUNT", "65536");
+    /* coverity[tainted_data] */
+    int nMaxBands = atoi(pszMaxBandCount);
+    if ( nBands > nMaxBands )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
-                 "Invalid band count : %d", nBands);
+                 "Invalid band count : %d. Maximum allowed currently is %d. "
+                 "Define GDAL_MAX_BAND_COUNT to a higher level if it is a legitimate number.",
+                 nBands, nMaxBands);
         return FALSE;
     }
     return TRUE;
@@ -3144,15 +3211,15 @@ void GDALSerializeGCPListToXML( CPLXMLNode* psParentNode,
 {
     CPLString oFmt;
 
-    CPLXMLNode *psPamGCPList = CPLCreateXMLNode( psParentNode, CXT_Element, 
+    CPLXMLNode *psPamGCPList = CPLCreateXMLNode( psParentNode, CXT_Element,
                                                  "GCPList" );
 
     CPLXMLNode* psLastChild = NULL;
 
-    if( pszGCPProjection != NULL 
+    if( pszGCPProjection != NULL
         && strlen(pszGCPProjection) > 0 )
     {
-        CPLSetXMLValue( psPamGCPList, "#Projection", 
+        CPLSetXMLValue( psPamGCPList, "#Projection",
                         pszGCPProjection );
         psLastChild = psPamGCPList->psChild;
     }
@@ -3175,21 +3242,21 @@ void GDALSerializeGCPListToXML( CPLXMLNode* psParentNode,
         if( psGCP->pszInfo != NULL && strlen(psGCP->pszInfo) > 0 )
             CPLSetXMLValue( psXMLGCP, "Info", psGCP->pszInfo );
 
-        CPLSetXMLValue( psXMLGCP, "#Pixel", 
+        CPLSetXMLValue( psXMLGCP, "#Pixel",
                         oFmt.Printf( "%.4f", psGCP->dfGCPPixel ) );
 
-        CPLSetXMLValue( psXMLGCP, "#Line", 
+        CPLSetXMLValue( psXMLGCP, "#Line",
                         oFmt.Printf( "%.4f", psGCP->dfGCPLine ) );
 
-        CPLSetXMLValue( psXMLGCP, "#X", 
+        CPLSetXMLValue( psXMLGCP, "#X",
                         oFmt.Printf( "%.12E", psGCP->dfGCPX ) );
 
-        CPLSetXMLValue( psXMLGCP, "#Y", 
+        CPLSetXMLValue( psXMLGCP, "#Y",
                         oFmt.Printf( "%.12E", psGCP->dfGCPY ) );
 
         /* Note: GDAL 1.10.1 and older generated #GCPZ, but could not read it back */
         if( psGCP->dfGCPZ != 0.0 )
-            CPLSetXMLValue( psXMLGCP, "#Z", 
+            CPLSetXMLValue( psXMLGCP, "#Z",
                             oFmt.Printf( "%.12E", psGCP->dfGCPZ ) );
     }
 }
@@ -3210,7 +3277,7 @@ void GDALDeserializeGCPListFromXML( CPLXMLNode* psGCPList,
     {
         const char *pszRawProj = CPLGetXMLValue(psGCPList, "Projection", "");
 
-        if( strlen(pszRawProj) > 0 
+        if( strlen(pszRawProj) > 0
             && oSRS.SetFromUserInput( pszRawProj ) == OGRERR_NONE )
             oSRS.exportToWkt( ppszGCPProjection );
         else
@@ -3220,19 +3287,19 @@ void GDALDeserializeGCPListFromXML( CPLXMLNode* psGCPList,
     // Count GCPs.
     int  nGCPMax = 0;
 
-    for( psXMLGCP = psGCPList->psChild; psXMLGCP != NULL; 
+    for( psXMLGCP = psGCPList->psChild; psXMLGCP != NULL;
          psXMLGCP = psXMLGCP->psNext )
         nGCPMax++;
 
     *ppasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),nGCPMax);
     *pnGCPCount = 0;
 
-    for( psXMLGCP = psGCPList->psChild; psXMLGCP != NULL; 
+    for( psXMLGCP = psGCPList->psChild; psXMLGCP != NULL;
          psXMLGCP = psXMLGCP->psNext )
     {
         GDAL_GCP *psGCP = *ppasGCPList + *pnGCPCount;
 
-        if( !EQUAL(psXMLGCP->pszValue,"GCP") || 
+        if( !EQUAL(psXMLGCP->pszValue,"GCP") ||
             psXMLGCP->eType != CXT_Element )
             continue;
 
@@ -3333,7 +3400,7 @@ char** GDALDeserializeOpenOptionsFromXML( CPLXMLNode* psParentNode )
 GDALRIOResampleAlg GDALRasterIOGetResampleAlg(const char* pszResampling)
 {
     GDALRIOResampleAlg eResampleAlg = GRIORA_NearestNeighbour;
-    if( EQUALN(pszResampling, "NEAR", 4) )
+    if( STARTS_WITH_CI(pszResampling, "NEAR") )
         eResampleAlg = GRIORA_NearestNeighbour;
     else if( EQUAL(pszResampling, "BILINEAR") )
         eResampleAlg = GRIORA_Bilinear;
@@ -3356,6 +3423,36 @@ GDALRIOResampleAlg GDALRasterIOGetResampleAlg(const char* pszResampling)
 }
 
 /************************************************************************/
+/*                    GDALRasterIOGetResampleAlgStr()                   */
+/************************************************************************/
+
+const char* GDALRasterIOGetResampleAlg(GDALRIOResampleAlg eResampleAlg)
+{
+    switch(eResampleAlg)
+    {
+        case GRIORA_NearestNeighbour:
+            return "NearestNeighbour";
+        case GRIORA_Bilinear:
+            return "Bilinear";
+        case GRIORA_Cubic:
+            return "Cubic";
+        case GRIORA_CubicSpline:
+            return "CubicSpline";
+        case GRIORA_Lanczos:
+            return "Lanczos";
+        case GRIORA_Average:
+            return "Average";
+        case GRIORA_Mode:
+            return "Mode";
+        case GRIORA_Gauss:
+            return "Gauss";
+        default:
+            CPLAssert(FALSE);
+            return "Unknown";
+    }
+}
+
+/************************************************************************/
 /*                   GDALRasterIOExtraArgSetResampleAlg()               */
 /************************************************************************/
 
diff --git a/gcore/gdal_pam.h b/gcore/gdal_pam.h
index 1e3c1c0..83a14a0 100644
--- a/gcore/gdal_pam.h
+++ b/gcore/gdal_pam.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_pam.h 28899 2015-04-14 09:27:00Z rouault $
+ * $Id: gdal_pam.h 33694 2016-03-10 17:54:30Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Declaration for Peristable Auxiliary Metadata classes.
@@ -64,20 +64,20 @@ class GDALPamRasterBand;
                                  GCIF_COLORINTERP | GCIF_BAND_METADATA |   \
                                  GCIF_RAT | GCIF_MASK |                    \
                                  GCIF_ONLY_IF_MISSING | GCIF_PROCESS_BANDS|\
-                                 GCIF_BAND_DESCRIPTION) 
+                                 GCIF_BAND_DESCRIPTION)
 
 /* GDAL PAM Flags */
 /* ERO 2011/04/13 : GPF_AUXMODE seems to be unimplemented */
 #define GPF_DIRTY		0x01  // .pam file needs to be written on close
 #define GPF_TRIED_READ_FAILED   0x02  // no need to keep trying to read .pam.
-#define GPF_DISABLED            0x04  // do not try any PAM stuff. 
+#define GPF_DISABLED            0x04  // do not try any PAM stuff.
 #define GPF_AUXMODE             0x08  // store info in .aux (HFA) file.
 #define GPF_NOSAVE              0x10  // do not try to save pam info.
 
 /* ==================================================================== */
 /*      GDALDatasetPamInfo                                              */
 /*                                                                      */
-/*      We make these things a seperate structure of information        */
+/*      We make these things a separate structure of information        */
 /*      primarily so we can modify it without altering the size of      */
 /*      the GDALPamDataset.  It is an effort to reduce ABI churn for    */
 /*      driver plugins.                                                 */
@@ -122,7 +122,7 @@ class CPL_DLL GDALPamDataset : public GDALDataset
 
     virtual CPLXMLNode *SerializeToXML( const char *);
     virtual CPLErr      XMLInit( CPLXMLNode *, const char * );
-    
+
     virtual CPLErr TryLoadXML(char **papszSiblingFiles = NULL);
     virtual CPLErr TrySaveXML();
 
@@ -169,10 +169,10 @@ class CPL_DLL GDALPamDataset : public GDALDataset
 
     virtual CPLErr CloneInfo( GDALDataset *poSrcDS, int nCloneInfoFlags );
 
-    virtual CPLErr IBuildOverviews( const char *pszResampling, 
-                                    int nOverviews, int *panOverviewList, 
+    virtual CPLErr IBuildOverviews( const char *pszResampling,
+                                    int nOverviews, int *panOverviewList,
                                     int nListBands, int *panBandList,
-                                    GDALProgressFunc pfnProgress, 
+                                    GDALProgressFunc pfnProgress,
                                     void * pProgressData );
 
 
@@ -181,12 +181,15 @@ class CPL_DLL GDALPamDataset : public GDALDataset
     GDALDatasetPamInfo *GetPamInfo() { return psPam; }
     int    GetPamFlags() { return nPamFlags; }
     void   SetPamFlags(int nValue ) { nPamFlags = nValue; }
+
+  private:
+    CPL_DISALLOW_COPY_ASSIGN(GDALPamDataset);
 };
 
 /* ==================================================================== */
 /*      GDALRasterBandPamInfo                                           */
 /*                                                                      */
-/*      We make these things a seperate structure of information        */
+/*      We make these things a separate structure of information        */
 /*      primarily so we can modify it without altering the size of      */
 /*      the GDALPamDataset.  It is an effort to reduce ABI churn for    */
 /*      driver plugins.                                                 */
@@ -203,7 +206,7 @@ typedef struct {
 
     char           *pszUnitType;
     char           **papszCategoryNames;
-    
+
     double         dfOffset;
     double         dfScale;
 
@@ -232,7 +235,7 @@ class CPL_DLL GDALPamRasterBand : public GDALRasterBand
 
     virtual CPLXMLNode *SerializeToXML( const char *pszVRTPath );
     virtual CPLErr      XMLInit( CPLXMLNode *, const char * );
-    
+
     void   PamInitialize();
     void   PamClear();
 
@@ -240,21 +243,23 @@ class CPL_DLL GDALPamRasterBand : public GDALRasterBand
 
   public:
                 GDALPamRasterBand();
+                GDALPamRasterBand(int bForceCachedIO);
     virtual     ~GDALPamRasterBand();
 
     virtual void        SetDescription( const char * );
 
     virtual CPLErr SetNoDataValue( double );
     virtual double GetNoDataValue( int *pbSuccess = NULL );
+    virtual CPLErr DeleteNoDataValue();
 
-    virtual CPLErr SetColorTable( GDALColorTable * ); 
+    virtual CPLErr SetColorTable( GDALColorTable * );
     virtual GDALColorTable *GetColorTable();
 
     virtual CPLErr SetColorInterpretation( GDALColorInterp );
     virtual GDALColorInterp GetColorInterpretation();
 
     virtual const char *GetUnitType();
-    CPLErr SetUnitType( const char * ); 
+    CPLErr SetUnitType( const char * );
 
     virtual char **GetCategoryNames();
     virtual CPLErr SetCategoryNames( char ** );
@@ -286,21 +291,24 @@ class CPL_DLL GDALPamRasterBand : public GDALRasterBand
     virtual GDALRasterAttributeTable *GetDefaultRAT();
     virtual CPLErr SetDefaultRAT( const GDALRasterAttributeTable * );
 
-    // new in GDALPamRasterBand. 
+    // new in GDALPamRasterBand.
     virtual CPLErr CloneInfo( GDALRasterBand *poSrcBand, int nCloneInfoFlags );
 
     // "semi private" methods.
     GDALRasterBandPamInfo *GetPamInfo() { return psPam; }
+
+  private:
+    CPL_DISALLOW_COPY_ASSIGN(GDALPamRasterBand);
 };
 
 // These are mainly helper functions for internal use.
-int CPL_DLL PamParseHistogram( CPLXMLNode *psHistItem, 
-                               double *pdfMin, double *pdfMax, 
-                               int *pnBuckets, GUIntBig **ppanHistogram, 
+int CPL_DLL PamParseHistogram( CPLXMLNode *psHistItem,
+                               double *pdfMin, double *pdfMax,
+                               int *pnBuckets, GUIntBig **ppanHistogram,
                                int *pbIncludeOutOfRange, int *pbApproxOK );
 CPLXMLNode CPL_DLL *
 PamFindMatchingHistogram( CPLXMLNode *psSavedHistograms,
-                          double dfMin, double dfMax, int nBuckets, 
+                          double dfMin, double dfMax, int nBuckets,
                           int bIncludeOutOfRange, int bApproxOK );
 CPLXMLNode CPL_DLL *
 PamHistogramToXMLTree( double dfMin, double dfMax,
diff --git a/gcore/gdal_priv.h b/gcore/gdal_priv.h
index 4a5e83d..76ba9a6 100644
--- a/gcore/gdal_priv.h
+++ b/gcore/gdal_priv.h
@@ -1,9 +1,9 @@
 /******************************************************************************
- * $Id: gdal_priv.h 31109 2015-10-23 19:53:08Z rouault $
+ * $Id: gdal_priv.h 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Name:     gdal_priv.h
  * Project:  GDAL Core
- * Purpose:  GDAL Core C++/Private declarations. 
+ * Purpose:  GDAL Core C++/Private declarations.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -32,6 +32,12 @@
 #ifndef GDAL_PRIV_H_INCLUDED
 #define GDAL_PRIV_H_INCLUDED
 
+/**
+ * \file gdal_priv.h
+ *
+ * C++ GDAL entry points.
+ */
+
 /* -------------------------------------------------------------------- */
 /*      Predeclare various classes before pulling in gdal.h, the        */
 /*      public declarations.                                            */
@@ -58,6 +64,7 @@ class GDALAsyncReader;
 #include "cpl_string.h"
 #include "cpl_minixml.h"
 #include "cpl_multiproc.h"
+#include "cpl_atomic_ops.h"
 #include <vector>
 #include <map>
 #include "ogr_core.h"
@@ -98,6 +105,9 @@ public:
                                  const char * pszDomain = "" );
 
     void        Clear();
+
+  private:
+    CPL_DISALLOW_COPY_ASSIGN(GDALMultiDomainMetadata);
 };
 
 /* ******************************************************************** */
@@ -112,24 +122,24 @@ public:
 class CPL_DLL GDALMajorObject
 {
   protected:
-    int                 nFlags; // GMO_* flags. 
+    int                 nFlags; // GMO_* flags.
     CPLString           sDescription;
     GDALMultiDomainMetadata oMDMD;
-    
+
     char               **BuildMetadataDomainList(char** papszList, int bCheckNonEmpty, ...) CPL_NULL_TERMINATED;
-    
+
   public:
                         GDALMajorObject();
     virtual            ~GDALMajorObject();
 
     int                 GetMOFlags();
     void                SetMOFlags(int nFlagsIn);
-                        
+
     virtual const char *GetDescription() const;
     virtual void        SetDescription( const char * );
 
     virtual char      **GetMetadataDomainList();
-    
+
     virtual char      **GetMetadata( const char * pszDomain = "" );
     virtual CPLErr      SetMetadata( char ** papszMetadata,
                                      const char * pszDomain = "" );
@@ -149,7 +159,7 @@ class CPL_DLL GDALDefaultOverviews
 
     GDALDataset *poDS;
     GDALDataset *poODS;
-    
+
     CPLString   osOvrFilename;
 
     int         bOvrIsAux;
@@ -158,7 +168,7 @@ class CPL_DLL GDALDefaultOverviews
     int         bOwnMaskDS;
     GDALDataset *poMaskDS;
 
-    // for "overview datasets" we record base level info so we can 
+    // for "overview datasets" we record base level info so we can
     // find our way back to get overview masks.
     GDALDataset *poBaseDS;
 
@@ -173,10 +183,12 @@ class CPL_DLL GDALDefaultOverviews
                GDALDefaultOverviews();
                ~GDALDefaultOverviews();
 
-    void       Initialize( GDALDataset *poDSIn, const char *pszName = NULL, 
+    void       Initialize( GDALDataset *poDSIn, const char *pszName = NULL,
                            char **papszSiblingFiles = NULL,
                            int bNameIsOVR = FALSE );
 
+    void       TransferSiblingFiles(char** papszSiblingFiles);
+
     int        IsInitialized();
 
     int        CloseDependentDatasets();
@@ -187,14 +199,14 @@ class CPL_DLL GDALDefaultOverviews
     GDALRasterBand *GetOverview(int,int);
 
     CPLErr     BuildOverviews( const char * pszBasename,
-                               const char * pszResampling, 
+                               const char * pszResampling,
                                int nOverviews, int * panOverviewList,
                                int nBands, int * panBandList,
                                GDALProgressFunc pfnProgress,
                                void *pProgressData );
 
     CPLErr     BuildOverviewsSubDataset( const char * pszPhysicalFile,
-                                         const char * pszResampling, 
+                                         const char * pszResampling,
                                          int nOverviews, int * panOverviewList,
                                          int nBands, int * panBandList,
                                          GDALProgressFunc pfnProgress,
@@ -208,10 +220,13 @@ class CPL_DLL GDALDefaultOverviews
     GDALRasterBand *GetMaskBand( int nBand );
     int        GetMaskFlags( int nBand );
 
-    int        HaveMaskFile( char **papszSiblings = NULL, 
+    int        HaveMaskFile( char **papszSiblings = NULL,
                              const char *pszBasename = NULL );
 
     char**     GetSiblingFiles() { return papszInitSiblingFiles; }
+
+  private:
+    CPL_DISALLOW_COPY_ASSIGN(GDALDefaultOverviews);
 };
 
 /* ******************************************************************** */
@@ -222,7 +237,7 @@ class CPL_DLL GDALDefaultOverviews
 
 class CPL_DLL GDALOpenInfo
 {
-    int         bHasGotSiblingFiles;
+    bool        bHasGotSiblingFiles;
     char        **papszSiblingFiles;
     int         nHeaderBytesTried;
 
@@ -247,6 +262,11 @@ class CPL_DLL GDALOpenInfo
 
     int         TryToIngest(int nBytes);
     char      **GetSiblingFiles();
+    char      **StealSiblingFiles();
+    bool        AreSiblingFilesLoaded() const;
+
+  private:
+    CPL_DISALLOW_COPY_ASSIGN(GDALOpenInfo);
 };
 
 /* ******************************************************************** */
@@ -286,9 +306,11 @@ class CPL_DLL GDALDataset : public GDALMajorObject
     friend class GDALDefaultOverviews;
     friend class GDALProxyDataset;
     friend class GDALDriverManager;
-    
+
     void AddToDatasetOpenList();
 
+    void           Init(int bForceCachedIO);
+
   protected:
     GDALDriver  *poDriver;
     GDALAccess  eAccess;
@@ -299,22 +321,22 @@ class CPL_DLL GDALDataset : public GDALMajorObject
     int         nBands;
     GDALRasterBand **papoBands;
 
-    int         bForceCachedIO;
+    int         nOpenFlags;
 
     int         nRefCount;
-    int         bShared;
+    GByte       bForceCachedIO;
+    GByte       bShared;
     GByte       bIsInternal;
     GByte       bSuppressOnClose;
-    GByte       bReserved1;
-    GByte       bReserved2;
 
                 GDALDataset(void);
+                GDALDataset(int bForceCachedIO);
 
     void        RasterInitialize( int, int );
     void        SetBand( int, GDALRasterBand * );
 
     GDALDefaultOverviews oOvManager;
-    
+
     virtual CPLErr IBuildOverviews( const char *, int, int *,
                                     int, int *, GDALProgressFunc, void * );
 
@@ -327,35 +349,70 @@ class CPL_DLL GDALDataset : public GDALMajorObject
     virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
                               void *, int, int, GDALDataType,
                               int, int *, GSpacing, GSpacing, GSpacing,
-                              GDALRasterIOExtraArg* psExtraArg );
+                              GDALRasterIOExtraArg* psExtraArg ) CPL_WARN_UNUSED_RESULT;
 
     CPLErr BlockBasedRasterIO( GDALRWFlag, int, int, int, int,
                                void *, int, int, GDALDataType,
                                int, int *, GSpacing, GSpacing, GSpacing,
-                               GDALRasterIOExtraArg* psExtraArg );
+                               GDALRasterIOExtraArg* psExtraArg ) CPL_WARN_UNUSED_RESULT;
     void   BlockBasedFlushCache();
 
+    CPLErr BandBasedRasterIO( GDALRWFlag eRWFlag,
+                               int nXOff, int nYOff, int nXSize, int nYSize,
+                               void * pData, int nBufXSize, int nBufYSize,
+                               GDALDataType eBufType,
+                               int nBandCount, int *panBandMap,
+                               GSpacing nPixelSpace, GSpacing nLineSpace,
+                               GSpacing nBandSpace,
+                               GDALRasterIOExtraArg* psExtraArg ) CPL_WARN_UNUSED_RESULT;
+
+    CPLErr RasterIOResampled( GDALRWFlag eRWFlag,
+                               int nXOff, int nYOff, int nXSize, int nYSize,
+                               void * pData, int nBufXSize, int nBufYSize,
+                               GDALDataType eBufType,
+                               int nBandCount, int *panBandMap,
+                               GSpacing nPixelSpace, GSpacing nLineSpace,
+                               GSpacing nBandSpace,
+                               GDALRasterIOExtraArg* psExtraArg ) CPL_WARN_UNUSED_RESULT;
+
     CPLErr ValidateRasterIOOrAdviseReadParameters(
                                const char* pszCallingFunc,
                                int* pbStopProcessingOnCENone,
                                int nXOff, int nYOff, int nXSize, int nYSize,
-                               int nBufXSize, int nBufYSize, 
+                               int nBufXSize, int nBufYSize,
                                int nBandCount, int *panBandMap);
 
+    CPLErr TryOverviewRasterIO( GDALRWFlag eRWFlag,
+                                int nXOff, int nYOff, int nXSize, int nYSize,
+                                void * pData, int nBufXSize, int nBufYSize,
+                                GDALDataType eBufType,
+                                int nBandCount, int *panBandMap,
+                                GSpacing nPixelSpace, GSpacing nLineSpace,
+                                GSpacing nBandSpace,
+                                GDALRasterIOExtraArg* psExtraArg,
+                                int* pbTried);
+
     virtual int         CloseDependentDatasets();
-    
+
     int                 ValidateLayerCreationOptions( const char* const* papszLCO );
-    
+
     char            **papszOpenOptions;
 
     friend class GDALRasterBand;
-    
+
+    // The below methods related to read write mutex are fragile logic, and
+    // should not be used by out-of-tree code if possible.
     int                 EnterReadWrite(GDALRWFlag eRWFlag);
     void                LeaveReadWrite();
 
     void                TemporarilyDropReadWriteLock();
     void                ReacquireReadWriteLock();
-    
+
+    void                DisableReadWriteMutex();
+
+    int          AcquireMutex();
+    void         ReleaseMutex();
+
   public:
     virtual     ~GDALDataset();
 
@@ -372,15 +429,15 @@ class CPL_DLL GDALDataset : public GDALMajorObject
     virtual CPLErr GetGeoTransform( double * );
     virtual CPLErr SetGeoTransform( double * );
 
-    virtual CPLErr        AddBand( GDALDataType eType, 
+    virtual CPLErr        AddBand( GDALDataType eType,
                                    char **papszOptions=NULL );
 
     virtual void *GetInternalHandle( const char * );
     virtual GDALDriver *GetDriver(void);
     virtual char      **GetFileList(void);
-    
+
     virtual     const char* GetDriverName();
-    
+
     virtual int    GetGCPCount();
     virtual const char *GetGCPProjection();
     virtual const GDAL_GCP *GetGCPs();
@@ -388,14 +445,14 @@ class CPL_DLL GDALDataset : public GDALMajorObject
                             const char *pszGCPProjection );
 
     virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
-                               int nBufXSize, int nBufYSize, 
-                               GDALDataType eDT, 
+                               int nBufXSize, int nBufYSize,
+                               GDALDataType eDT,
                                int nBandCount, int *panBandList,
                                char **papszOptions );
 
     virtual CPLErr          CreateMaskBand( int nFlagsIn );
 
-    virtual GDALAsyncReader* 
+    virtual GDALAsyncReader*
         BeginAsyncReader(int nXOff, int nYOff, int nXSize, int nYSize,
                          void *pBuf, int nBufXSize, int nBufYSize,
                          GDALDataType eBufType,
@@ -411,17 +468,17 @@ class CPL_DLL GDALDataset : public GDALMajorObject
 #ifndef DOXYGEN_SKIP
                           OPTIONAL_OUTSIDE_GDAL(NULL)
 #endif
-                          );
+                          ) CPL_WARN_UNUSED_RESULT;
 
     int           Reference();
     int           Dereference();
-    GDALAccess    GetAccess() { return eAccess; }
+    GDALAccess    GetAccess() const { return eAccess; }
 
     int           GetShared();
     void          MarkAsShared();
-    
+
     void          MarkSuppressOnClose() { bSuppressOnClose = TRUE; }
-    
+
     char        **GetOpenOptions() { return papszOpenOptions; }
 
     static GDALDataset **GetOpenDatasets( int *pnDatasetCount );
@@ -429,7 +486,7 @@ class CPL_DLL GDALDataset : public GDALMajorObject
     CPLErr BuildOverviews( const char *, int, int *,
                            int, int *, GDALProgressFunc, void * );
 
-    void ReportError(CPLErr eErrClass, int err_no, const char *fmt, ...)  CPL_PRINT_FUNC_FORMAT (4, 5);
+    void ReportError(CPLErr eErrClass, CPLErrorNum err_no, const char *fmt, ...)  CPL_PRINT_FUNC_FORMAT (4, 5);
 
 private:
     void           *m_hPrivateData;
@@ -448,17 +505,17 @@ private:
 
     virtual int         TestCapability( const char * );
 
-    virtual OGRLayer   *CreateLayer( const char *pszName, 
+    virtual OGRLayer   *CreateLayer( const char *pszName,
                                      OGRSpatialReference *poSpatialRef = NULL,
                                      OGRwkbGeometryType eGType = wkbUnknown,
                                      char ** papszOptions = NULL );
-    virtual OGRLayer   *CopyLayer( OGRLayer *poSrcLayer, 
-                                   const char *pszNewName, 
+    virtual OGRLayer   *CopyLayer( OGRLayer *poSrcLayer,
+                                   const char *pszNewName,
                                    char **papszOptions = NULL );
 
     virtual OGRStyleTable *GetStyleTable();
     virtual void        SetStyleTableDirectly( OGRStyleTable *poStyleTable );
-                            
+
     virtual void        SetStyleTable(OGRStyleTable *poStyleTable);
 
     virtual OGRLayer *  ExecuteSQL( const char *pszStatement,
@@ -473,9 +530,9 @@ private:
     virtual OGRErr      StartTransaction(int bForce=FALSE);
     virtual OGRErr      CommitTransaction();
     virtual OGRErr      RollbackTransaction();
-    
+
     static int          IsGenericSQLDialect(const char* pszDialect);
-    
+
     // Semi-public methods. Only to be used by in-tree drivers.
     GDALSQLParseInfo*   BuildParseInfo(swq_select* psSelectInfo,
                                        swq_select_parse_options* poSelectParseOptions);
@@ -487,7 +544,7 @@ private:
 
   protected:
 
-    virtual OGRLayer   *ICreateLayer( const char *pszName, 
+    virtual OGRLayer   *ICreateLayer( const char *pszName,
                                      OGRSpatialReference *poSpatialRef = NULL,
                                      OGRwkbGeometryType eGType = wkbUnknown,
                                      char ** papszOptions = NULL );
@@ -501,6 +558,9 @@ private:
     OGRErr              ProcessSQLAlterTableRenameColumn( const char * );
 
     OGRStyleTable      *m_poStyleTable;
+
+  private:
+    CPL_DISALLOW_COPY_ASSIGN(GDALDataset);
 };
 
 /* ******************************************************************** */
@@ -508,56 +568,66 @@ private:
 /* ******************************************************************** */
 
 //! A single raster block in the block cache.
+// And the global block manager that manages a least-recently-used list of
+// blocks from various datasets/bands
 
 class CPL_DLL GDALRasterBlock
 {
+    friend class GDALAbstractBandBlockCache;
+
     GDALDataType        eType;
-    
+
     int                 bDirty;
-    int                 nLockCount;
+    volatile int        nLockCount;
 
     int                 nXOff;
     int                 nYOff;
-       
+
     int                 nXSize;
     int                 nYSize;
-    
+
     void                *pData;
 
     GDALRasterBand      *poBand;
-    
+
     GDALRasterBlock     *poNext;
     GDALRasterBlock     *poPrevious;
-    
+
     int                  bMustDetach;
-    
-    void        Touch_unlocked( void );
+
     void        Detach_unlocked( void );
+    void        Touch_unlocked( void );
+
+    void        RecycleFor( int nXOffIn, int nYOffIn );
 
   public:
                 GDALRasterBlock( GDALRasterBand *, int, int );
+                GDALRasterBlock( int nXOffIn, int nYOffIn ); /* only for lookup purpose */
     virtual     ~GDALRasterBlock();
 
     CPLErr      Internalize( void );
-    void        Touch( void );      
-    void        MarkDirty( void );  
+    void        Touch( void );
+    void        MarkDirty( void );
     void        MarkClean( void );
-    void        AddLock( void ) { nLockCount++; }
-    void        DropLock( void ) { nLockCount--; }
+    int         AddLock( void ) { return CPLAtomicInc(&nLockCount); }
+    int         DropLock( void ) { return CPLAtomicDec(&nLockCount); }
     void        Detach();
 
     CPLErr      Write();
 
-    GDALDataType GetDataType() { return eType; }
-    int         GetXOff() { return nXOff; }
-    int         GetYOff() { return nYOff; }
-    int         GetXSize() { return nXSize; }
-    int         GetYSize() { return nYSize; }
-    int         GetDirty() { return bDirty; }
-    int         GetLockCount() { return nLockCount; }
+    GDALDataType GetDataType() const { return eType; }
+    int         GetXOff() const { return nXOff; }
+    int         GetYOff() const { return nYOff; }
+    int         GetXSize() const { return nXSize; }
+    int         GetYSize() const { return nYSize; }
+    int         GetDirty() const { return bDirty; }
 
     void        *GetDataRef( void ) { return pData; }
-    int          GetBlockSize() { return nXSize * nYSize * (GDALGetDataTypeSize(eType) / 8); }
+    int          GetBlockSize() const {
+        return nXSize * nYSize * GDALGetDataTypeSizeBytes(eType); }
+
+    int          TakeLock();
+    int          DropLockForRemovalFromStorage();
 
     /// @brief Accessor to source GDALRasterBand object.
     /// @return source raster band of the raster block.
@@ -567,10 +637,17 @@ class CPL_DLL GDALRasterBlock
     static int  FlushCacheBlock(int bDirtyBlocksOnly = FALSE);
     static void Verify();
 
-    static int  SafeLockBlock( GDALRasterBlock ** );
-    
+#ifdef notdef
+    static void CheckNonOrphanedBlocks(GDALRasterBand* poBand);
+    void        DumpBlock();
+    static void DumpAll();
+#endif
+
     /* Should only be called by GDALDestroyDriverManager() */
     static void DestroyRBMutex();
+
+  private:
+    CPL_DISALLOW_COPY_ASSIGN(GDALRasterBlock);
 };
 
 /* ******************************************************************** */
@@ -603,6 +680,53 @@ public:
 };
 
 /* ******************************************************************** */
+/*                       GDALAbstractBandBlockCache                     */
+/* ******************************************************************** */
+
+//! This manages how a raster band store its cached block.
+// CPL_DLL is just technical here. This is really a private concept
+// only used by GDALRasterBand implementation.
+
+class CPL_DLL GDALAbstractBandBlockCache
+{
+        // List of blocks that can be freed or recycled, and its lock
+        CPLLock          *hSpinLock;
+        GDALRasterBlock  *psListBlocksToFree;
+
+        // Band keep alive counter, and its lock & condition
+        CPLCond          *hCond;
+        CPLMutex         *hCondMutex;
+        volatile int      nKeepAliveCounter;
+
+    protected:
+        GDALRasterBand   *poBand;
+
+        void              FreeDanglingBlocks();
+        void              UnreferenceBlockBase();
+        void              WaitKeepAliveCounter();
+
+    public:
+                     GDALAbstractBandBlockCache(GDALRasterBand* poBand);
+            virtual ~GDALAbstractBandBlockCache();
+
+            GDALRasterBlock* CreateBlock(int nXBlockOff, int nYBlockOff);
+            void             AddBlockToFreeList( GDALRasterBlock * );
+
+            virtual bool             Init() = 0;
+            virtual bool             IsInitOK() = 0;
+            virtual CPLErr           FlushCache() = 0;
+            virtual CPLErr           AdoptBlock( GDALRasterBlock* poBlock ) = 0;
+            virtual GDALRasterBlock *TryGetLockedBlockRef( int nXBlockOff,
+                                                           int nYBlockYOff ) = 0;
+            virtual CPLErr           UnreferenceBlock( GDALRasterBlock* poBlock ) = 0;
+            virtual CPLErr           FlushBlock( int nXBlockOff, int nYBlockOff,
+                                                 int bWriteDirtyBlock ) = 0;
+};
+
+GDALAbstractBandBlockCache* GDALArrayBandBlockCacheCreate(GDALRasterBand* poBand);
+GDALAbstractBandBlockCache* GDALHashSetBandBlockCacheCreate(GDALRasterBand* poBand);
+
+/* ******************************************************************** */
 /*                            GDALRasterBand                            */
 /* ******************************************************************** */
 
@@ -611,12 +735,17 @@ public:
 class CPL_DLL GDALRasterBand : public GDALMajorObject
 {
   private:
+    friend class GDALArrayBandBlockCache;
+    friend class GDALHashSetBandBlockCache;
+    friend class GDALRasterBlock;
+
     CPLErr eFlushBlockErr;
+    GDALAbstractBandBlockCache* poBandBlockCache;
 
     void           SetFlushBlockErr( CPLErr eErr );
+    CPLErr         UnreferenceBlock( GDALRasterBlock* poBlock );
 
-    friend class GDALRasterBlock;
-    CPLErr         UnreferenceBlock( int nXBlockOff, int nYBlockOff );
+    void           Init(int bForceCachedIO);
 
   protected:
     GDALDataset *poDS;
@@ -624,7 +753,7 @@ class CPL_DLL GDALRasterBand : public GDALMajorObject
 
     int         nRasterXSize;
     int         nRasterYSize;
-    
+
     GDALDataType eDataType;
     GDALAccess  eAccess;
 
@@ -634,11 +763,6 @@ class CPL_DLL GDALRasterBand : public GDALMajorObject
     int         nBlocksPerRow;
     int         nBlocksPerColumn;
 
-    int         bSubBlockingActive;
-    int         nSubBlocksPerRow;
-    int         nSubBlocksPerColumn;
-    GDALRasterBlock **papoBlocks;
-
     int         nBlockReads;
     int         bForceCachedIO;
 
@@ -654,7 +778,7 @@ class CPL_DLL GDALRasterBand : public GDALMajorObject
 
     CPLErr RasterIOResampled( GDALRWFlag, int, int, int, int,
                               void *, int, int, GDALDataType,
-                              GSpacing, GSpacing, GDALRasterIOExtraArg* psExtraArg );
+                              GSpacing, GSpacing, GDALRasterIOExtraArg* psExtraArg ) CPL_WARN_UNUSED_RESULT;
 
     int          EnterReadWrite(GDALRWFlag eRWFlag);
     void         LeaveReadWrite();
@@ -671,19 +795,29 @@ class CPL_DLL GDALRasterBand : public GDALMajorObject
 
     virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
                               void *, int, int, GDALDataType,
-                              GSpacing, GSpacing, GDALRasterIOExtraArg* psExtraArg );
+                              GSpacing, GSpacing, GDALRasterIOExtraArg* psExtraArg ) CPL_WARN_UNUSED_RESULT;
     CPLErr         OverviewRasterIO( GDALRWFlag, int, int, int, int,
                                      void *, int, int, GDALDataType,
-                                     GSpacing, GSpacing, GDALRasterIOExtraArg* psExtraArg );
+                                     GSpacing, GSpacing, GDALRasterIOExtraArg* psExtraArg ) CPL_WARN_UNUSED_RESULT;
+
+    CPLErr TryOverviewRasterIO( GDALRWFlag eRWFlag,
+                                int nXOff, int nYOff, int nXSize, int nYSize,
+                                void * pData, int nBufXSize, int nBufYSize,
+                                GDALDataType eBufType,
+                                GSpacing nPixelSpace, GSpacing nLineSpace,
+                                GDALRasterIOExtraArg* psExtraArg,
+                                int* pbTried );
 
     int            InitBlockInfo();
 
-    CPLErr         AdoptBlock( int, int, GDALRasterBlock * );
+    CPLErr         AdoptBlock( GDALRasterBlock * );
     GDALRasterBlock *TryGetLockedBlockRef( int nXBlockOff, int nYBlockYOff );
+    void           AddBlockToFreeList( GDALRasterBlock * );
 
   public:
                 GDALRasterBand();
-                
+                GDALRasterBand(int bForceCachedIO);
+
     virtual     ~GDALRasterBand();
 
     int         GetXSize();
@@ -694,21 +828,21 @@ class CPL_DLL GDALRasterBand : public GDALMajorObject
     GDALDataType GetRasterDataType( void );
     void        GetBlockSize( int *, int * );
     GDALAccess  GetAccess();
-    
+
     CPLErr      RasterIO( GDALRWFlag, int, int, int, int,
                           void *, int, int, GDALDataType,
                           GSpacing, GSpacing, GDALRasterIOExtraArg* psExtraArg
 #ifndef DOXYGEN_SKIP
                           OPTIONAL_OUTSIDE_GDAL(NULL)
 #endif
-                          );
-    CPLErr      ReadBlock( int, int, void * );
+                          ) CPL_WARN_UNUSED_RESULT;
+    CPLErr      ReadBlock( int, int, void * ) CPL_WARN_UNUSED_RESULT;
 
-    CPLErr      WriteBlock( int, int, void * );
+    CPLErr      WriteBlock( int, int, void * ) CPL_WARN_UNUSED_RESULT;
 
-    GDALRasterBlock *GetLockedBlockRef( int nXBlockOff, int nYBlockOff, 
-                                        int bJustInitialize = FALSE );
-    CPLErr      FlushBlock( int = -1, int = -1, int bWriteDirtyBlock = TRUE );
+    GDALRasterBlock *GetLockedBlockRef( int nXBlockOff, int nYBlockOff,
+                                        int bJustInitialize = FALSE ) CPL_WARN_UNUSED_RESULT;
+    CPLErr      FlushBlock( int, int, int bWriteDirtyBlock = TRUE );
 
     unsigned char*  GetIndexColorTranslationTo(/* const */ GDALRasterBand* poReferenceBand,
                                                unsigned char* pTranslationTable = NULL,
@@ -730,20 +864,21 @@ class CPL_DLL GDALRasterBand : public GDALMajorObject
 
     virtual CPLErr SetCategoryNames( char ** );
     virtual CPLErr SetNoDataValue( double );
-    virtual CPLErr SetColorTable( GDALColorTable * ); 
+    virtual CPLErr DeleteNoDataValue();
+    virtual CPLErr SetColorTable( GDALColorTable * );
     virtual CPLErr SetColorInterpretation( GDALColorInterp );
     virtual CPLErr SetOffset( double );
     virtual CPLErr SetScale( double );
     virtual CPLErr SetUnitType( const char * );
 
     virtual CPLErr GetStatistics( int bApproxOK, int bForce,
-                                  double *pdfMin, double *pdfMax, 
+                                  double *pdfMin, double *pdfMax,
                                   double *pdfMean, double *padfStdDev );
-    virtual CPLErr ComputeStatistics( int bApproxOK, 
-                                      double *pdfMin, double *pdfMax, 
+    virtual CPLErr ComputeStatistics( int bApproxOK,
+                                      double *pdfMin, double *pdfMax,
                                       double *pdfMean, double *pdfStdDev,
                                       GDALProgressFunc, void *pProgressData );
-    virtual CPLErr SetStatistics( double dfMin, double dfMax, 
+    virtual CPLErr SetStatistics( double dfMin, double dfMax,
                                   double dfMean, double dfStdDev );
     virtual CPLErr ComputeRasterMinMax( int, double* );
 
@@ -755,7 +890,7 @@ class CPL_DLL GDALRasterBand : public GDALMajorObject
                                    GDALProgressFunc, void * );
 
     virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
-                               int nBufXSize, int nBufYSize, 
+                               int nBufXSize, int nBufYSize,
                                GDALDataType eDT, char **papszOptions );
 
     virtual CPLErr  GetHistogram( double dfMin, double dfMax,
@@ -780,9 +915,12 @@ class CPL_DLL GDALRasterBand : public GDALMajorObject
     virtual CPLVirtualMem  *GetVirtualMemAuto( GDALRWFlag eRWFlag,
                                                int *pnPixelSpace,
                                                GIntBig *pnLineSpace,
-                                               char **papszOptions );
+                                               char **papszOptions ) CPL_WARN_UNUSED_RESULT;
 
-    void ReportError(CPLErr eErrClass, int err_no, const char *fmt, ...)  CPL_PRINT_FUNC_FORMAT (4, 5);
+    void ReportError(CPLErr eErrClass, CPLErrorNum err_no, const char *fmt, ...)  CPL_PRINT_FUNC_FORMAT (4, 5);
+
+private:
+    CPL_DISALLOW_COPY_ASSIGN(GDALRasterBand);
 };
 
 /* ******************************************************************** */
@@ -859,6 +997,25 @@ class GDALRescaledAlphaBand : public GDALRasterBand
 };
 
 /* ******************************************************************** */
+/*                          GDALIdentifyEnum                            */
+/* ******************************************************************** */
+
+/**
+ * Enumeration used by GDALDriver::pfnIdentify().
+ *
+ * @since GDAL 2.1
+ */
+typedef enum
+{
+    /** Identify could not determine if the file is recognized or not by the probed driver. */
+    GDAL_IDENTIFY_UNKNOWN = -1,
+    /** Identify determined the file is not recognized by the probed driver. */
+    GDAL_IDENTIFY_FALSE = 0,
+    /** Identify determined the file is recognized by the probed driver. */
+    GDAL_IDENTIFY_TRUE = 1
+} GDALIdentifyEnum;
+
+/* ******************************************************************** */
 /*                              GDALDriver                              */
 /* ******************************************************************** */
 
@@ -868,10 +1025,10 @@ class GDALRescaledAlphaBand : public GDALRasterBand
  *
  * An instance of this class is created for each supported format, and
  * manages information about the format.
- * 
- * This roughly corresponds to a file format, though some          
- * drivers may be gateways to many formats through a secondary     
- * multi-library.                                                  
+ *
+ * This roughly corresponds to a file format, though some
+ * drivers may be gateways to many formats through a secondary
+ * multi-library.
  */
 
 class CPL_DLL GDALDriver : public GDALMajorObject
@@ -897,9 +1054,9 @@ class CPL_DLL GDALDriver : public GDALMajorObject
     CPLErr              CopyFiles( const char * pszNewName,
                                    const char * pszOldName );
 
-    GDALDataset         *CreateCopy( const char *, GDALDataset *, 
+    GDALDataset         *CreateCopy( const char *, GDALDataset *,
                                      int, char **,
-                                     GDALProgressFunc pfnProgress, 
+                                     GDALProgressFunc pfnProgress,
                                      void * pProgressData ) CPL_WARN_UNUSED_RESULT;
 
 /* -------------------------------------------------------------------- */
@@ -916,19 +1073,22 @@ class CPL_DLL GDALDriver : public GDALMajorObject
 
     CPLErr              (*pfnDelete)( const char * pszName );
 
-    GDALDataset         *(*pfnCreateCopy)( const char *, GDALDataset *, 
+    GDALDataset         *(*pfnCreateCopy)( const char *, GDALDataset *,
                                            int, char **,
-                                           GDALProgressFunc pfnProgress, 
+                                           GDALProgressFunc pfnProgress,
                                            void * pProgressData );
 
     void                *pDriverData;
 
     void                (*pfnUnloadDriver)(GDALDriver *);
 
-    /* Return 1 if the passed file is certainly recognized by the driver */
-    /* Return 0 if the passed file is certainly NOT recognized by the driver */
-    /* Return -1 if the passed file may be or may not be recognized by the driver,
-       and that a potentially costly test must be done with pfnOpen */
+    /** Identify() if the file is recognized or not by the driver.
+
+       Return GDAL_IDENTIFY_TRUE (1) if the passed file is certainly recognized by the driver.
+       Return GDAL_IDENTIFY_FALSE (0) if the passed file is certainly NOT recognized by the driver.
+       Return GDAL_IDENTIFY_UNKNOWN (-1) if the passed file may be or may not be recognized by the driver,
+       and that a potentially costly test must be done with pfnOpen.
+    */
     int                 (*pfnIdentify)( GDALOpenInfo * );
 
     CPLErr              (*pfnRename)( const char * pszNewName,
@@ -947,12 +1107,12 @@ class CPL_DLL GDALDriver : public GDALMajorObject
 /* -------------------------------------------------------------------- */
 /*      Helper methods.                                                 */
 /* -------------------------------------------------------------------- */
-    GDALDataset         *DefaultCreateCopy( const char *, GDALDataset *, 
+    GDALDataset         *DefaultCreateCopy( const char *, GDALDataset *,
                                             int, char **,
-                                            GDALProgressFunc pfnProgress, 
+                                            GDALProgressFunc pfnProgress,
                                             void * pProgressData ) CPL_WARN_UNUSED_RESULT;
-    static CPLErr        DefaultCopyMasks( GDALDataset *poSrcDS, 
-                                           GDALDataset *poDstDS, 
+    static CPLErr        DefaultCopyMasks( GDALDataset *poSrcDS,
+                                           GDALDataset *poDstDS,
                                            int bStrict );
     static CPLErr       QuietDelete( const char * pszName );
 
@@ -960,6 +1120,8 @@ class CPL_DLL GDALDriver : public GDALMajorObject
                                        const char * pszOldName );
     CPLErr              DefaultCopyFiles( const char * pszNewName,
                                           const char * pszOldName );
+private:
+    CPL_DISALLOW_COPY_ASSIGN(GDALDriver);
 };
 
 /* ******************************************************************** */
@@ -978,17 +1140,17 @@ class CPL_DLL GDALDriverManager : public GDALMajorObject
     int         nDrivers;
     GDALDriver  **papoDrivers;
     std::map<CPLString, GDALDriver*> oMapNameToDrivers;
-    
+
     GDALDriver  *GetDriver_unlocked( int iDriver )
             { return (iDriver >= 0 && iDriver < nDrivers) ? papoDrivers[iDriver] : NULL; }
-    
+
     GDALDriver  *GetDriverByName_unlocked( const char * pszName )
             { return oMapNameToDrivers[CPLString(pszName).toupper()]; }
-    
+
  public:
                 GDALDriverManager();
                 ~GDALDriverManager();
-                
+
     int         GetDriverCount( void );
     GDALDriver  *GetDriver( int );
     GDALDriver  *GetDriverByName( const char * );
@@ -996,6 +1158,7 @@ class CPL_DLL GDALDriverManager : public GDALMajorObject
     int         RegisterDriver( GDALDriver * );
     void        DeregisterDriver( GDALDriver * );
 
+    // AutoLoadDrivers is a no-op if compiled with GDAL_NO_AUTOLOAD defined.
     void        AutoLoadDrivers();
     void        AutoSkipDrivers();
 };
@@ -1036,21 +1199,21 @@ class CPL_DLL GDALAsyncReader
     virtual ~GDALAsyncReader();
 
     GDALDataset* GetGDALDataset() {return poDS;}
-    int GetXOffset() {return nXOff;}
-    int GetYOffset() {return nYOff;}
-    int GetXSize() {return nXSize;}
-    int GetYSize() {return nYSize;}
+    int GetXOffset() const { return nXOff; }
+    int GetYOffset() const { return nYOff; }
+    int GetXSize() const { return nXSize; }
+    int GetYSize() const { return nYSize; }
     void * GetBuffer() {return pBuf;}
-    int GetBufferXSize() {return nBufXSize;}
-    int GetBufferYSize() {return nBufYSize;}
-    GDALDataType GetBufferType() {return eBufType;}
-    int GetBandCount() {return nBandCount;}
-    int* GetBandMap() {return panBandMap;}
-    int GetPixelSpace() {return nPixelSpace;}
-    int GetLineSpace() {return nLineSpace;}
-    int GetBandSpace() {return nBandSpace;}
-
-    virtual GDALAsyncStatusType 
+    int GetBufferXSize() const { return nBufXSize; }
+    int GetBufferYSize() const { return nBufYSize; }
+    GDALDataType GetBufferType() const { return eBufType; }
+    int GetBandCount() const { return nBandCount; }
+    int* GetBandMap() { return panBandMap; }
+    int GetPixelSpace() const { return nPixelSpace; }
+    int GetLineSpace() const { return nLineSpace; }
+    int GetBandSpace() const { return nBandSpace; }
+
+    virtual GDALAsyncStatusType
         GetNextUpdatedRegion(double dfTimeout,
                              int* pnBufXOff, int* pnBufYOff,
                              int* pnBufXSize, int* pnBufYSize) = 0;
@@ -1062,12 +1225,12 @@ class CPL_DLL GDALAsyncReader
 /*      An assortment of overview related stuff.                        */
 /* ==================================================================== */
 
-/* Not a public symbol for the moment */
-CPLErr 
+/* Only exported for drivers as plugin. Signature may change */
+CPLErr CPL_DLL
 GDALRegenerateOverviewsMultiBand(int nBands, GDALRasterBand** papoSrcBands,
                                  int nOverviews,
                                  GDALRasterBand*** papapoOverviewBands,
-                                 const char * pszResampling, 
+                                 const char * pszResampling,
                                  GDALProgressFunc pfnProgress, void * pProgressData );
 
 typedef CPLErr (*GDALResampleFunction)
@@ -1090,38 +1253,58 @@ typedef CPLErr (*GDALResampleFunction)
 
 GDALResampleFunction GDALGetResampleFunction(const char* pszResampling,
                                                  int* pnRadius);
+
+#ifdef GDAL_ENABLE_RESAMPLING_MULTIBAND
+typedef CPLErr (*GDALResampleFunctionMultiBands)
+                      ( double dfXRatioDstToSrc,
+                        double dfYRatioDstToSrc,
+                        double dfSrcXDelta,
+                        double dfSrcYDelta,
+                        GDALDataType eWrkDataType,
+                        void * pChunk, int nBands,
+                        GByte * pabyChunkNodataMask,
+                        int nChunkXOff, int nChunkXSize,
+                        int nChunkYOff, int nChunkYSize,
+                        int nDstXOff, int nDstXOff2,
+                        int nDstYOff, int nDstYOff2,
+                        GDALRasterBand ** papoDstBands,
+                        const char * pszResampling,
+                        int bHasNoData, float fNoDataValue,
+                        GDALColorTable* poColorTable,
+                        GDALDataType eSrcDataType);
+
+GDALResampleFunctionMultiBands GDALGetResampleFunctionMultiBands(const char* pszResampling,
+                                                       int* pnRadius);
+#endif
+
 GDALDataType GDALGetOvrWorkDataType(const char* pszResampling,
                                         GDALDataType eSrcDataType);
 
 CPL_C_START
 
-#ifndef WIN32CE
-
 CPLErr CPL_DLL
 HFAAuxBuildOverviews( const char *pszOvrFilename, GDALDataset *poParentDS,
                       GDALDataset **ppoDS,
                       int nBands, int *panBandList,
-                      int nNewOverviews, int *panNewOverviewList, 
-                      const char *pszResampling, 
-                      GDALProgressFunc pfnProgress, 
+                      int nNewOverviews, int *panNewOverviewList,
+                      const char *pszResampling,
+                      GDALProgressFunc pfnProgress,
                       void *pProgressData );
 
-#endif /* WIN32CE */
-
-CPLErr CPL_DLL 
+CPLErr CPL_DLL
 GTIFFBuildOverviews( const char * pszFilename,
-                     int nBands, GDALRasterBand **papoBandList, 
+                     int nBands, GDALRasterBand **papoBandList,
                      int nOverviews, int * panOverviewList,
-                     const char * pszResampling, 
+                     const char * pszResampling,
                      GDALProgressFunc pfnProgress, void * pProgressData );
 
 CPLErr CPL_DLL
 GDALDefaultBuildOverviews( GDALDataset *hSrcDS, const char * pszBasename,
-                           const char * pszResampling, 
+                           const char * pszResampling,
                            int nOverviews, int * panOverviewList,
                            int nBands, int * panBandList,
                            GDALProgressFunc pfnProgress, void * pProgressData);
-                           
+
 int CPL_DLL GDALBandGetBestOverviewLevel(GDALRasterBand* poBand,
                                          int &nXOff, int &nYOff,
                                          int &nXSize, int &nYSize,
@@ -1145,7 +1328,7 @@ GDALFindAssociatedAuxFile( const char *pszBasefile, GDALAccess eAccess,
 /*      Misc functions.                                                 */
 /* ==================================================================== */
 
-CPLErr CPL_DLL GDALParseGMLCoverage( CPLXMLNode *psTree, 
+CPLErr CPL_DLL GDALParseGMLCoverage( CPLXMLNode *psTree,
                                      int *pnXSize, int *pnYSize,
                                      double *padfGeoTransform,
                                      char **ppszProjection );
@@ -1203,6 +1386,7 @@ int GDALValidateOptions( const char* pszOptionList,
                          const char* pszErrorMessageContainerName);
 
 GDALRIOResampleAlg GDALRasterIOGetResampleAlg(const char* pszResampling);
+const char* GDALRasterIOGetResampleAlg(GDALRIOResampleAlg eResampleAlg);
 
 void GDALRasterIOExtraArgSetResampleAlg(GDALRasterIOExtraArg* psExtraArg,
                                         int nXSize, int nYSize,
diff --git a/gcore/gdal_priv_templates.hpp b/gcore/gdal_priv_templates.hpp
new file mode 100644
index 0000000..cf4e1a0
--- /dev/null
+++ b/gcore/gdal_priv_templates.hpp
@@ -0,0 +1,436 @@
+/******************************************************************************
+ * $Id: gdal_priv_templates.hpp 31950 2015-12-01 20:01:42Z rouault $
+ *
+ * Project:  GDAL Core
+ * Purpose:  Inline C++ templates
+ * Author:   Phil Vachon, <philippe at cowpig.ca>
+ *
+ ******************************************************************************
+ * Copyright (c) 2009, Phil Vachon, <philippe at cowpig.ca>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef GDAL_PRIV_TEMPLATES_HPP_INCLUDED
+#define GDAL_PRIV_TEMPLATES_HPP_INCLUDED
+
+#define SSE_USE_SAME_ROUNDING_AS_NON_SSE
+
+#include <limits>
+
+/************************************************************************/
+/*                        GDALGetDataLimits()                           */
+/************************************************************************/
+/**
+ * Compute the limits of values that can be placed in Tout in terms of
+ * Tin. Usually used for output clamping, when the output data type's
+ * limits are stable relative to the input type (i.e. no roundoff error).
+ *
+ * @param tMaxValue the returned maximum value
+ * @param tMinValue the returned minimum value
+ */
+
+template <class Tin, class Tout>
+inline void GDALGetDataLimits(Tin &tMaxValue, Tin &tMinValue)
+{
+    tMaxValue = std::numeric_limits<Tin>::max();
+    tMinValue = std::numeric_limits<Tin>::min();
+
+    // Compute the actual minimum value of Tout in terms of Tin.
+    if (std::numeric_limits<Tout>::is_signed && std::numeric_limits<Tout>::is_integer)
+    {
+        // the minimum value is less than zero
+        if (std::numeric_limits<Tout>::digits < std::numeric_limits<Tin>::digits ||
+                        !std::numeric_limits<Tin>::is_integer)
+        {
+            // Tout is smaller than Tin, so we need to clamp values in input
+            // to the range of Tout's min/max values
+            if (std::numeric_limits<Tin>::is_signed)
+            {
+                tMinValue = static_cast<Tin>(std::numeric_limits<Tout>::min());
+            }
+            tMaxValue = static_cast<Tin>(std::numeric_limits<Tout>::max());
+        }
+    }
+    else if (std::numeric_limits<Tout>::is_integer)
+    {
+        // the output is unsigned, so we just need to determine the max
+        /* coverity[same_on_both_sides] */
+        if (std::numeric_limits<Tout>::digits <= std::numeric_limits<Tin>::digits)
+        {
+            // Tout is smaller than Tin, so we need to clamp the input values
+            // to the range of Tout's max
+            tMaxValue = static_cast<Tin>(std::numeric_limits<Tout>::max());
+        }
+        tMinValue = 0;
+    }
+
+}
+
+/************************************************************************/
+/*                          GDALClampValue()                            */
+/************************************************************************/
+/**
+ * Clamp values of type T to a specified range
+ *
+ * @param tValue the value
+ * @param tMax the max value
+ * @param tMin the min value
+ */
+template <class T>
+inline T GDALClampValue(const T tValue, const T tMax, const T tMin)
+{
+    return tValue > tMax ? tMax :
+           tValue < tMin ? tMin : tValue;
+}
+
+/************************************************************************/
+/*                          GDALCopyWord()                              */
+/************************************************************************/
+/**
+ * Copy a single word, optionally rounding if appropriate (i.e. going
+ * from the float to the integer case). Note that this is the function
+ * you should specialize if you're adding a new data type.
+ *
+ * @param tValueIn value of type Tin; the input value to be converted
+ * @param tValueOut value of type Tout; the output value
+ */
+
+template <class Tin, class Tout>
+inline void GDALCopyWord(const Tin tValueIn, Tout &tValueOut)
+{
+    Tin tMaxVal, tMinVal;
+    GDALGetDataLimits<Tin, Tout>(tMaxVal, tMinVal);
+    tValueOut = static_cast<Tout>(GDALClampValue(tValueIn, tMaxVal, tMinVal));
+}
+
+template <class Tin>
+inline void GDALCopyWord(const Tin tValueIn, float &fValueOut)
+{
+    fValueOut = (float) tValueIn;
+}
+
+template <class Tin>
+inline void GDALCopyWord(const Tin tValueIn, double &dfValueOut)
+{
+    dfValueOut = tValueIn;
+}
+
+inline void GDALCopyWord(const double dfValueIn, double &dfValueOut)
+{
+    dfValueOut = dfValueIn;
+}
+
+inline void GDALCopyWord(const float fValueIn, float &fValueOut)
+{
+    fValueOut = fValueIn;
+}
+
+inline void GDALCopyWord(const float fValueIn, double &dfValueOut)
+{
+    dfValueOut = fValueIn;
+}
+
+inline void GDALCopyWord(const double dfValueIn, float &fValueOut)
+{
+    fValueOut = static_cast<float>(dfValueIn);
+}
+
+template <class Tout>
+inline void GDALCopyWord(const float fValueIn, Tout &tValueOut)
+{
+    float fMaxVal, fMinVal;
+    GDALGetDataLimits<float, Tout>(fMaxVal, fMinVal);
+    tValueOut = static_cast<Tout>(
+        GDALClampValue(fValueIn + 0.5f, fMaxVal, fMinVal));
+}
+
+// Just need SSE, but don't bother being too specific
+#if (defined(__x86_64) || defined(_M_X64)) && defined(this_is_disabled)
+
+#include <xmmintrin.h>
+
+template <class Tout>
+inline void GDALCopyWordSSE(const float fValueIn, Tout &tValueOut)
+{
+    float fMaxVal, fMinVal;
+    GDALGetDataLimits<float, Tout>(fMaxVal, fMinVal);
+    __m128 xmm = _mm_set_ss(fValueIn);
+    __m128 xmm_min = _mm_set_ss(fMinVal);
+    __m128 xmm_max = _mm_set_ss(fMaxVal);
+    xmm = _mm_min_ss(_mm_max_ss(xmm, xmm_min), xmm_max);
+#ifdef SSE_USE_SAME_ROUNDING_AS_NON_SSE
+    __m128 p0d5 = _mm_set_ss(0.5f);
+    if (std::numeric_limits<Tout>::is_signed)
+    {
+        __m128 mask = _mm_cmpge_ss(xmm, _mm_set_ss(0.f));
+        __m128 m0d5 = _mm_set_ss(-0.5f);
+        xmm = _mm_add_ss(xmm, _mm_or_ps(_mm_and_ps(mask, p0d5), _mm_andnot_ps(mask, m0d5)));
+    }
+    else
+    {
+        xmm = _mm_add_ss(xmm, p0d5);
+    }
+#endif
+
+#ifdef SSE_USE_SAME_ROUNDING_AS_NON_SSE
+    tValueOut = (Tout)_mm_cvttss_si32(xmm);
+#else
+    tValueOut = (Tout)_mm_cvtss_si32(xmm);
+#endif
+}
+
+inline void GDALCopyWord(const float fValueIn, GByte &tValueOut)
+{
+    GDALCopyWordSSE(fValueIn, tValueOut);
+}
+
+inline void GDALCopyWord(const float fValueIn, GInt16 &tValueOut)
+{
+    GDALCopyWordSSE(fValueIn, tValueOut);
+}
+
+inline void GDALCopyWord(const float fValueIn, GUInt16 &tValueOut)
+{
+    GDALCopyWordSSE(fValueIn, tValueOut);
+}
+
+#else
+
+inline void GDALCopyWord(const float fValueIn, short &nValueOut)
+{
+    float fMaxVal, fMinVal;
+    GDALGetDataLimits<float, short>(fMaxVal, fMinVal);
+    float fValue = fValueIn >= 0.0f ? fValueIn + 0.5f :
+        fValueIn - 0.5f;
+    nValueOut = static_cast<short>(
+        GDALClampValue(fValue, fMaxVal, fMinVal));
+}
+
+#endif //  defined(__x86_64) || defined(_M_X64)
+
+template <class Tout>
+inline void GDALCopyWord(const double dfValueIn, Tout &tValueOut)
+{
+    double dfMaxVal, dfMinVal;
+    GDALGetDataLimits<double, Tout>(dfMaxVal, dfMinVal);
+    tValueOut = static_cast<Tout>(
+        GDALClampValue(dfValueIn + 0.5, dfMaxVal, dfMinVal));
+}
+
+inline void GDALCopyWord(const double dfValueIn, int &nValueOut)
+{
+    double dfMaxVal, dfMinVal;
+    GDALGetDataLimits<double, int>(dfMaxVal, dfMinVal);
+    double dfValue = dfValueIn >= 0.0 ? dfValueIn + 0.5 :
+        dfValueIn - 0.5;
+    nValueOut = static_cast<int>(
+        GDALClampValue(dfValue, dfMaxVal, dfMinVal));
+}
+
+inline void GDALCopyWord(const double dfValueIn, short &nValueOut)
+{
+    double dfMaxVal, dfMinVal;
+    GDALGetDataLimits<double, short>(dfMaxVal, dfMinVal);
+    double dfValue = dfValueIn > 0.0 ? dfValueIn + 0.5 :
+        dfValueIn - 0.5;
+    nValueOut = static_cast<short>(
+        GDALClampValue(dfValue, dfMaxVal, dfMinVal));
+}
+
+// Roundoff occurs for Float32 -> int32 for max/min. Overload GDALCopyWord
+// specifically for this case.
+inline void GDALCopyWord(const float fValueIn, int &nValueOut)
+{
+    if (fValueIn >= static_cast<float>(std::numeric_limits<int>::max()))
+    {
+        nValueOut = std::numeric_limits<int>::max();
+    }
+    else if (fValueIn <= static_cast<float>(std::numeric_limits<int>::min()))
+    {
+        nValueOut = std::numeric_limits<int>::min();
+    }
+    else
+    {
+        nValueOut = static_cast<int>(fValueIn > 0.0f ? 
+            fValueIn + 0.5f : fValueIn - 0.5f);
+    }
+}
+
+// Roundoff occurs for Float32 -> uint32 for max. Overload GDALCopyWord
+// specifically for this case.
+inline void GDALCopyWord(const float fValueIn, unsigned int &nValueOut)
+{
+    if (fValueIn >= static_cast<float>(std::numeric_limits<unsigned int>::max()))
+    {
+        nValueOut = std::numeric_limits<unsigned int>::max();
+    }
+    else if (fValueIn <= static_cast<float>(std::numeric_limits<unsigned int>::min()))
+    {
+        nValueOut = std::numeric_limits<unsigned int>::min();
+    }
+    else
+    {
+        nValueOut = static_cast<unsigned int>(fValueIn + 0.5f);
+    }
+}
+
+#ifdef notdef
+/************************************************************************/
+/*                         GDALCopy2Words()                             */
+/************************************************************************/
+/**
+ * Copy 2 words, optionally rounding if appropriate (i.e. going
+ * from the float to the integer case).
+ *
+ * @param pValueIn pointer to 2 input values of type Tin.
+ * @param pValueOut pointer to 2 output values of type Tout.
+ */
+
+template <class Tin, class Tout>
+inline void GDALCopy2Words(const Tin* pValueIn, Tout* const &pValueOut)
+{
+    GDALCopyWord(pValueIn[0], pValueOut[0]);
+    GDALCopyWord(pValueIn[1], pValueOut[1]);
+}
+
+// Just need SSE, but don't bother being too specific
+#if defined(__x86_64) || defined(_M_X64)
+
+#include <xmmintrin.h>
+
+template <class Tout>
+inline void GDALCopy2WordsSSE(const float* pValueIn, Tout* const &pValueOut)
+{
+    float fMaxVal, fMinVal;
+    GDALGetDataLimits<float, Tout>(fMaxVal, fMinVal);
+    __m128 xmm = _mm_set_ps(0, 0, pValueIn[1], pValueIn[0]);
+    __m128 xmm_min = _mm_set_ps(0, 0, fMinVal, fMinVal);
+    __m128 xmm_max = _mm_set_ps(0, 0, fMaxVal, fMaxVal);
+    xmm = _mm_min_ps(_mm_max_ps(xmm, xmm_min), xmm_max);
+    pValueOut[0] = _mm_cvtss_si32(xmm);
+    pValueOut[1] = _mm_cvtss_si32(_mm_shuffle_ps(xmm, xmm, _MM_SHUFFLE(0, 0, 0, 1)));
+}
+
+inline void GDALCopy2Words(const float* pValueIn, GByte* const &pValueOut)
+{
+    GDALCopy2WordsSSE(pValueIn, pValueOut);
+}
+
+inline void GDALCopy2Words(const float* pValueIn, GInt16* const &pValueOut)
+{
+    GDALCopy2WordsSSE(pValueIn, pValueOut);
+}
+
+inline void GDALCopy2Words(const float* pValueIn, GUInt16* const &pValueOut)
+{
+    GDALCopy2WordsSSE(pValueIn, pValueOut);
+}
+#endif //  defined(__x86_64) || defined(_M_X64)
+
+#endif
+
+/************************************************************************/
+/*                         GDALCopy4Words()                             */
+/************************************************************************/
+/**
+ * Copy 4 words, optionally rounding if appropriate (i.e. going
+ * from the float to the integer case).
+ *
+ * @param pValueIn pointer to 4 input values of type Tin.
+ * @param pValueOut pointer to 4 output values of type Tout.
+ */
+
+template <class Tin, class Tout>
+inline void GDALCopy4Words(const Tin* pValueIn, Tout* const &pValueOut)
+{
+    GDALCopyWord(pValueIn[0], pValueOut[0]);
+    GDALCopyWord(pValueIn[1], pValueOut[1]);
+    GDALCopyWord(pValueIn[2], pValueOut[2]);
+    GDALCopyWord(pValueIn[3], pValueOut[3]);
+}
+
+// Needs SSE2 for _mm_cvtps_epi32 and store operations
+#if defined(__x86_64) || defined(_M_X64)
+
+#include <emmintrin.h>
+
+template <class Tout>
+inline void GDALCopy4WordsSSE(const float* pValueIn, Tout* const &pValueOut)
+{
+    float fMaxVal, fMinVal;
+    GDALGetDataLimits<float, Tout>(fMaxVal, fMinVal);
+    __m128 xmm = _mm_loadu_ps(pValueIn);
+
+    __m128 xmm_min = _mm_set1_ps(fMinVal);
+    __m128 xmm_max = _mm_set1_ps(fMaxVal);
+    xmm = _mm_min_ps(_mm_max_ps(xmm, xmm_min), xmm_max);
+
+#ifdef SSE_USE_SAME_ROUNDING_AS_NON_SSE
+    __m128 p0d5 = _mm_set1_ps(0.5f);
+     if (std::numeric_limits<Tout>::is_signed)
+     {
+        __m128 m0d5 = _mm_set1_ps(-0.5f);
+        //__m128 mask = _mm_cmpge_ps(xmm, _mm_set1_ps(0.f));
+        __m128 mask = _mm_cmpge_ps(xmm, p0d5);
+        xmm = _mm_add_ps(xmm, _mm_or_ps(_mm_and_ps(mask, p0d5), _mm_andnot_ps(mask, m0d5))); /* f >= 0.5f ? f + 0.5f : f - 0.5f */
+     }
+     else
+     {
+         xmm = _mm_add_ps(xmm, p0d5);
+     }
+#endif
+
+#ifdef SSE_USE_SAME_ROUNDING_AS_NON_SSE
+    __m128i xmm_i = _mm_cvttps_epi32 (xmm);
+#else
+    __m128i xmm_i = _mm_cvtps_epi32(xmm);
+#endif
+#if 0
+    int aTemp[4];
+    _mm_storeu_si128 ( (__m128i *)aTemp, xmm_i);
+    pValueOut[0] = (Tout)aTemp[0];
+    pValueOut[1] = (Tout)aTemp[1];
+    pValueOut[2] = (Tout)aTemp[2];
+    pValueOut[3] = (Tout)aTemp[3];
+#else
+    pValueOut[0] = (Tout)_mm_extract_epi16(xmm_i, 0);
+    pValueOut[1] = (Tout)_mm_extract_epi16(xmm_i, 2);
+    pValueOut[2] = (Tout)_mm_extract_epi16(xmm_i, 4);
+    pValueOut[3] = (Tout)_mm_extract_epi16(xmm_i, 6);
+#endif
+}
+
+inline void GDALCopy4Words(const float* pValueIn, GByte* const &pValueOut)
+{
+    GDALCopy4WordsSSE(pValueIn, pValueOut);
+}
+
+inline void GDALCopy4Words(const float* pValueIn, GInt16* const &pValueOut)
+{
+    GDALCopy4WordsSSE(pValueIn, pValueOut);
+}
+
+inline void GDALCopy4Words(const float* pValueIn, GUInt16* const &pValueOut)
+{
+    GDALCopy4WordsSSE(pValueIn, pValueOut);
+}
+#endif //  defined(__x86_64) || defined(_M_X64)
+
+#endif // GDAL_PRIV_TEMPLATES_HPP_INCLUDED
diff --git a/gcore/gdal_proxy.h b/gcore/gdal_proxy.h
index a007056..8a17c35 100644
--- a/gcore/gdal_proxy.h
+++ b/gcore/gdal_proxy.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_proxy.h 28899 2015-04-14 09:27:00Z rouault $
+ * $Id: gdal_proxy.h 33694 2016-03-10 17:54:30Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  GDAL Core C++/Private declarations
@@ -44,6 +44,8 @@
 class CPL_DLL GDALProxyDataset : public GDALDataset
 {
     protected:
+        GDALProxyDataset() {};
+
         virtual GDALDataset *RefUnderlyingDataset() = 0;
         virtual void UnrefUnderlyingDataset(GDALDataset* poUnderlyingDataset);
 
@@ -84,13 +86,15 @@ class CPL_DLL GDALProxyDataset : public GDALDataset
                                 const char *pszGCPProjection );
 
         virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
-                                int nBufXSize, int nBufYSize, 
-                                GDALDataType eDT, 
+                                int nBufXSize, int nBufYSize,
+                                GDALDataType eDT,
                                 int nBandCount, int *panBandList,
                                 char **papszOptions );
 
         virtual CPLErr          CreateMaskBand( int nFlags );
 
+  private:
+    CPL_DISALLOW_COPY_ASSIGN(GDALProxyDataset);
 };
 
 /* ******************************************************************** */
@@ -100,6 +104,8 @@ class CPL_DLL GDALProxyDataset : public GDALDataset
 class CPL_DLL GDALProxyRasterBand : public GDALRasterBand
 {
     protected:
+        GDALProxyRasterBand() {};
+
         virtual GDALRasterBand* RefUnderlyingRasterBand() = 0;
         virtual void UnrefUnderlyingRasterBand(GDALRasterBand* poUnderlyingRasterBand);
 
@@ -134,20 +140,21 @@ class CPL_DLL GDALProxyRasterBand : public GDALRasterBand
 
         virtual CPLErr SetCategoryNames( char ** );
         virtual CPLErr SetNoDataValue( double );
-        virtual CPLErr SetColorTable( GDALColorTable * ); 
+        virtual CPLErr DeleteNoDataValue();
+        virtual CPLErr SetColorTable( GDALColorTable * );
         virtual CPLErr SetColorInterpretation( GDALColorInterp );
         virtual CPLErr SetOffset( double );
         virtual CPLErr SetScale( double );
         virtual CPLErr SetUnitType( const char * );
 
         virtual CPLErr GetStatistics( int bApproxOK, int bForce,
-                                    double *pdfMin, double *pdfMax, 
+                                    double *pdfMin, double *pdfMax,
                                     double *pdfMean, double *padfStdDev );
-        virtual CPLErr ComputeStatistics( int bApproxOK, 
-                                        double *pdfMin, double *pdfMax, 
+        virtual CPLErr ComputeStatistics( int bApproxOK,
+                                        double *pdfMin, double *pdfMax,
                                         double *pdfMean, double *pdfStdDev,
                                         GDALProgressFunc, void *pProgressData );
-        virtual CPLErr SetStatistics( double dfMin, double dfMax, 
+        virtual CPLErr SetStatistics( double dfMin, double dfMax,
                                     double dfMean, double dfStdDev );
         virtual CPLErr ComputeRasterMinMax( int, double* );
 
@@ -159,7 +166,7 @@ class CPL_DLL GDALProxyRasterBand : public GDALRasterBand
                                     GDALProgressFunc, void * );
 
         virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
-                                int nBufXSize, int nBufYSize, 
+                                int nBufXSize, int nBufYSize,
                                 GDALDataType eDT, char **papszOptions );
 
         virtual CPLErr  GetHistogram( double dfMin, double dfMax,
@@ -185,6 +192,8 @@ class CPL_DLL GDALProxyRasterBand : public GDALRasterBand
                                                 int *pnPixelSpace,
                                                 GIntBig *pnLineSpace,
                                                 char **papszOptions );
+  private:
+    CPL_DISALLOW_COPY_ASSIGN(GDALProxyRasterBand);
 };
 
 
@@ -247,6 +256,8 @@ class CPL_DLL GDALProxyPoolDataset : public GDALProxyDataset
 
         virtual const char *GetGCPProjection();
         virtual const GDAL_GCP *GetGCPs();
+  private:
+    CPL_DISALLOW_COPY_ASSIGN(GDALProxyPoolDataset);
 };
 
 /* ******************************************************************** */
@@ -300,7 +311,8 @@ class CPL_DLL GDALProxyPoolRasterBand : public GDALProxyRasterBand
         virtual GDALRasterBand *GetOverview(int);
         virtual GDALRasterBand *GetRasterSampleOverview( GUIntBig nDesiredSamples); // TODO
         virtual GDALRasterBand *GetMaskBand();
-
+  private:
+    CPL_DISALLOW_COPY_ASSIGN(GDALProxyPoolRasterBand);
 };
 
 /* ******************************************************************** */
diff --git a/gcore/gdal_rat.cpp b/gcore/gdal_rat.cpp
index a5830d6..bfab72c 100644
--- a/gcore/gdal_rat.cpp
+++ b/gcore/gdal_rat.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_rat.cpp 29243 2015-05-24 15:53:26Z rouault $
+ * $Id: gdal_rat.cpp 33785 2016-03-25 16:34:55Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALRasterAttributeTable and related classes.
@@ -33,7 +33,7 @@
 #include "json.h"
 #include "ogrgeojsonwriter.h"
 
-CPL_CVSID("$Id: gdal_rat.cpp 29243 2015-05-24 15:53:26Z rouault $");
+CPL_CVSID("$Id: gdal_rat.cpp 33785 2016-03-25 16:34:55Z goatbar $");
 
 /**
  * \class GDALRasterAttributeTable
@@ -43,31 +43,31 @@ CPL_CVSID("$Id: gdal_rat.cpp 29243 2015-05-24 15:53:26Z rouault $");
  * in the table applies to a range of pixel values (or a single value in
  * some cases), and might have attributes such as the histogram count for
  * that range, the color pixels of that range should be drawn names of classes
- * or any other generic information. 
+ * or any other generic information.
  *
  * Raster attribute tables can be used to represent histograms, color tables,
- * and classification information.  
+ * and classification information.
  *
  * Each column in a raster attribute table has a name, a type (integer,
- * floating point or string), and a GDALRATFieldUsage.  The usage distinguishes 
- * columns with particular understood purposes (such as color, histogram 
- * count, name) and columns that have specific purposes not understood by 
- * the library (long label, suitability_for_growing_wheat, etc).  
+ * floating point or string), and a GDALRATFieldUsage.  The usage distinguishes
+ * columns with particular understood purposes (such as color, histogram
+ * count, name) and columns that have specific purposes not understood by
+ * the library (long label, suitability_for_growing_wheat, etc).
  *
  * In the general case each row has a column indicating the minimum pixel
  * values falling into that category, and a column indicating the maximum
  * pixel value.  These are indicated with usage values of GFU_Min, and
  * GFU_Max.  In other cases where each row is a discrete pixel value, one
- * column of usage GFU_MinMax can be used.  
- * 
- * In other cases all the categories are of equal size and regularly spaced 
+ * column of usage GFU_MinMax can be used.
+ *
+ * In other cases all the categories are of equal size and regularly spaced
  * and the categorization information can be determine just by knowing the
  * value at which the categories start, and the size of a category.  This
- * is called "Linear Binning" and the information is kept specially on 
+ * is called "Linear Binning" and the information is kept specially on
  * the raster attribute table as a whole.
  *
  * RATs are normally associated with GDALRasterBands and be be queried
- * using the GDALRasterBand::GetDefaultRAT() method.  
+ * using the GDALRasterBand::GetDefaultRAT() method.
  */
 
 /************************************************************************/
@@ -76,10 +76,7 @@ CPL_CVSID("$Id: gdal_rat.cpp 29243 2015-05-24 15:53:26Z rouault $");
 /*                      Virtual Destructor                              */
 /************************************************************************/
 
-GDALRasterAttributeTable::~GDALRasterAttributeTable()
-{
-
-}
+GDALRasterAttributeTable::~GDALRasterAttributeTable() {}
 
 /************************************************************************/
 /*                              ValuesIO()                              */
@@ -96,30 +93,31 @@ GDALRasterAttributeTable::~GDALRasterAttributeTable()
  * @param iField column of the Attribute Table
  * @param iStartRow start row to start reading/writing (zero based)
  * @param iLength number of rows to read or write
- * @param pdfData pointer to array of doubles to read/write. Should be at least iLength long.
+ * @param pdfData pointer to array of doubles to read/write. Should be at least
+ *   iLength long.
  *
- * @return CE_None or CE_Failure if iStartRow + iLength greater than number of rows in table.
+ * @return CE_None or CE_Failure if iStartRow + iLength greater than number of
+ *   rows in table.
  */
 
-CPLErr GDALRasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, double *pdfData)
+CPLErr GDALRasterAttributeTable::ValuesIO(
+    GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, double *pdfData)
 {
-    int iIndex;
-
-    if( (iStartRow + iLength) > GetRowCount() ) 
+    if( (iStartRow + iLength) > GetRowCount() )
     {
         return CE_Failure;
     }
 
     if( eRWFlag == GF_Read )
     {
-        for(iIndex = iStartRow; iIndex < (iStartRow + iLength); iIndex++ )
+        for( int iIndex = iStartRow; iIndex < (iStartRow + iLength); iIndex++ )
         {
             pdfData[iIndex] = GetValueAsDouble(iIndex, iField);
         }
     }
     else
     {
-        for(iIndex = iStartRow; iIndex < (iStartRow + iLength); iIndex++ )
+        for( int iIndex = iStartRow; iIndex < (iStartRow + iLength); iIndex++ )
         {
             SetValue(iIndex, iField, pdfData[iIndex]);
         }
@@ -134,15 +132,18 @@ CPLErr GDALRasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iS
 /**
  * \brief Read or Write a block of doubles to/from the Attribute Table.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::ValuesIO()
+ * This function is the same as the C++ method
+ * GDALRasterAttributeTable::ValuesIO()
  */
-CPLErr CPL_STDCALL GDALRATValuesIOAsDouble( GDALRasterAttributeTableH hRAT, GDALRWFlag eRWFlag, 
-                                        int iField, int iStartRow, int iLength, double *pdfData )
+CPLErr CPL_STDCALL GDALRATValuesIOAsDouble(
+    GDALRasterAttributeTableH hRAT, GDALRWFlag eRWFlag,
+    int iField, int iStartRow, int iLength, double *pdfData )
 
 {
     VALIDATE_POINTER1( hRAT, "GDALRATValuesIOAsDouble", CE_Failure );
 
-    return ((GDALRasterAttributeTable *) hRAT)->ValuesIO(eRWFlag, iField, iStartRow, iLength, pdfData);
+    return static_cast<GDALRasterAttributeTable *>(hRAT)->
+        ValuesIO(eRWFlag, iField, iStartRow, iLength, pdfData);
 }
 
 /**
@@ -154,30 +155,31 @@ CPLErr CPL_STDCALL GDALRATValuesIOAsDouble( GDALRasterAttributeTableH hRAT, GDAL
  * @param iField column of the Attribute Table
  * @param iStartRow start row to start reading/writing (zero based)
  * @param iLength number of rows to read or write
- * @param pnData pointer to array of ints to read/write. Should be at least iLength long.
+ * @param pnData pointer to array of ints to read/write. Should be at least
+ *     iLength long.
  *
- * @return CE_None or CE_Failure if iStartRow + iLength greater than number of rows in table.
+ * @return CE_None or CE_Failure if iStartRow + iLength greater than number of
+ *     rows in table.
  */
 
-CPLErr GDALRasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, int *pnData)
+CPLErr GDALRasterAttributeTable::ValuesIO(
+    GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, int *pnData )
 {
-    int iIndex;
-
-    if( (iStartRow + iLength) > GetRowCount() ) 
+    if( (iStartRow + iLength) > GetRowCount() )
     {
         return CE_Failure;
     }
 
     if( eRWFlag == GF_Read )
     {
-        for(iIndex = iStartRow; iIndex < (iStartRow + iLength); iIndex++ )
+        for( int iIndex = iStartRow; iIndex < (iStartRow + iLength); iIndex++ )
         {
             pnData[iIndex] = GetValueAsInt(iIndex, iField);
         }
     }
     else
     {
-        for(iIndex = iStartRow; iIndex < (iStartRow + iLength); iIndex++ )
+        for( int iIndex = iStartRow; iIndex < (iStartRow + iLength); iIndex++ )
         {
             SetValue(iIndex, iField, pnData[iIndex]);
         }
@@ -192,15 +194,18 @@ CPLErr GDALRasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iS
 /**
  * \brief Read or Write a block of ints to/from the Attribute Table.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::ValuesIO()
+ * This function is the same as the C++ method
+ * GDALRasterAttributeTable::ValuesIO()
  */
-CPLErr CPL_STDCALL GDALRATValuesIOAsInteger( GDALRasterAttributeTableH hRAT, GDALRWFlag eRWFlag, 
-                                        int iField, int iStartRow, int iLength, int *pnData)
+CPLErr CPL_STDCALL GDALRATValuesIOAsInteger(
+    GDALRasterAttributeTableH hRAT, GDALRWFlag eRWFlag,
+    int iField, int iStartRow, int iLength, int *pnData )
 
 {
     VALIDATE_POINTER1( hRAT, "GDALRATValuesIOAsInteger", CE_Failure );
 
-    return ((GDALRasterAttributeTable *) hRAT)->ValuesIO(eRWFlag, iField, iStartRow, iLength, pnData);
+    return static_cast<GDALRasterAttributeTable *>(hRAT)->
+        ValuesIO(eRWFlag, iField, iStartRow, iLength, pnData);
 }
 
 /**
@@ -214,30 +219,32 @@ CPLErr CPL_STDCALL GDALRATValuesIOAsInteger( GDALRasterAttributeTableH hRAT, GDA
  * @param iField column of the Attribute Table
  * @param iStartRow start row to start reading/writing (zero based)
  * @param iLength number of rows to read or write
- * @param papszStrList pointer to array of strings to read/write. Should be at least iLength long.
+ * @param papszStrList pointer to array of strings to read/write. Should be at
+ *   least iLength long.
  *
- * @return CE_None or CE_Failure if iStartRow + iLength greater than number of rows in table.
+ * @return CE_None or CE_Failure if iStartRow + iLength greater than number of
+ *   rows in table.
  */
 
-CPLErr GDALRasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, char **papszStrList)
+CPLErr GDALRasterAttributeTable::ValuesIO(
+    GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength,
+    char **papszStrList )
 {
-    int iIndex;
-
-    if( (iStartRow + iLength) > GetRowCount() ) 
+    if( (iStartRow + iLength) > GetRowCount() )
     {
         return CE_Failure;
     }
 
     if( eRWFlag == GF_Read )
     {
-        for(iIndex = iStartRow; iIndex < (iStartRow + iLength); iIndex++ )
+        for( int iIndex = iStartRow; iIndex < (iStartRow + iLength); iIndex++ )
         {
             papszStrList[iIndex] = VSIStrdup(GetValueAsString(iIndex, iField));
         }
     }
     else
     {
-        for(iIndex = iStartRow; iIndex < (iStartRow + iLength); iIndex++ )
+        for( int iIndex = iStartRow; iIndex < (iStartRow + iLength); iIndex++ )
         {
             SetValue(iIndex, iField, papszStrList[iIndex]);
         }
@@ -252,15 +259,18 @@ CPLErr GDALRasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iS
 /**
  * \brief Read or Write a block of strings to/from the Attribute Table.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::ValuesIO()
+ * This function is the same as the C++ method
+ * GDALRasterAttributeTable::ValuesIO()
  */
-CPLErr CPL_STDCALL GDALRATValuesIOAsString( GDALRasterAttributeTableH hRAT, GDALRWFlag eRWFlag, 
-                                        int iField, int iStartRow, int iLength, char **papszStrList)
+CPLErr CPL_STDCALL GDALRATValuesIOAsString(
+    GDALRasterAttributeTableH hRAT, GDALRWFlag eRWFlag,
+    int iField, int iStartRow, int iLength, char **papszStrList )
 
 {
     VALIDATE_POINTER1( hRAT, "GDALRATValuesIOAsString", CE_Failure );
 
-    return ((GDALRasterAttributeTable *) hRAT)->ValuesIO(eRWFlag, iField, iStartRow, iLength, papszStrList);
+    return static_cast<GDALRasterAttributeTable *>(hRAT)->
+        ValuesIO(eRWFlag, iField, iStartRow, iLength, papszStrList);
 }
 
 /************************************************************************/
@@ -271,17 +281,15 @@ CPLErr CPL_STDCALL GDALRATValuesIOAsString( GDALRasterAttributeTableH hRAT, GDAL
  * \brief Set row count.
  *
  * Resizes the table to include the indicated number of rows.  Newly created
- * rows will be initialized to their default values - "" for strings, 
- * and zero for numeric fields. 
+ * rows will be initialized to their default values - "" for strings,
+ * and zero for numeric fields.
  *
  * This method is the same as the C function GDALRATSetRowCount().
  *
  * @param nNewCount the new number of rows.
  */
 
-void GDALRasterAttributeTable::SetRowCount( CPL_UNUSED int nNewCount )
-{
-}
+void GDALRasterAttributeTable::SetRowCount( int /* nNewCount */ ) {}
 
 /************************************************************************/
 /*                         GDALRATSetRowCount()                         */
@@ -290,15 +298,16 @@ void GDALRasterAttributeTable::SetRowCount( CPL_UNUSED int nNewCount )
 /**
  * \brief Set row count.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::SetRowCount()
+ * This function is the same as the C++ method
+ * GDALRasterAttributeTable::SetRowCount()
  */
-void CPL_STDCALL 
+void CPL_STDCALL
 GDALRATSetRowCount( GDALRasterAttributeTableH hRAT, int nNewCount )
 
 {
     VALIDATE_POINTER0( hRAT, "GDALRATSetRowCount" );
 
-    ((GDALRasterAttributeTable *) hRAT)->SetRowCount( nNewCount );
+    static_cast<GDALRasterAttributeTable *>(hRAT)->SetRowCount( nNewCount );
 }
 
 /************************************************************************/
@@ -308,18 +317,18 @@ GDALRATSetRowCount( GDALRasterAttributeTableH hRAT, int nNewCount )
 /**
  * \brief Get row for pixel value.
  *
- * Given a raw pixel value, the raster attribute table is scanned to 
+ * Given a raw pixel value, the raster attribute table is scanned to
  * determine which row in the table applies to the pixel value.  The
- * row index is returned. 
+ * row index is returned.
  *
  * This method is the same as the C function GDALRATGetRowOfValue().
  *
- * @param dfValue the pixel value. 
+ * @param dfValue the pixel value.
  *
- * @return the row index or -1 if no row is appropriate. 
+ * @return the row index or -1 if no row is appropriate.
  */
 
-int GDALRasterAttributeTable::GetRowOfValue( CPL_UNUSED double dfValue ) const
+int GDALRasterAttributeTable::GetRowOfValue( double /* dfValue */ ) const
 {
     return -1;
 }
@@ -331,15 +340,17 @@ int GDALRasterAttributeTable::GetRowOfValue( CPL_UNUSED double dfValue ) const
 /**
  * \brief Get row for pixel value.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::GetRowOfValue()
+ * This function is the same as the C++ method
+ * GDALRasterAttributeTable::GetRowOfValue()
  */
-int CPL_STDCALL 
+int CPL_STDCALL
 GDALRATGetRowOfValue( GDALRasterAttributeTableH hRAT, double dfValue )
 
 {
     VALIDATE_POINTER1( hRAT, "GDALRATGetRowOfValue", 0 );
 
-    return ((GDALRasterAttributeTable *) hRAT)->GetRowOfValue( dfValue );
+    return static_cast<GDALRasterAttributeTable *>(hRAT)->
+        GetRowOfValue( dfValue );
 }
 
 /************************************************************************/
@@ -352,7 +363,7 @@ GDALRATGetRowOfValue( GDALRasterAttributeTableH hRAT, double dfValue )
 int GDALRasterAttributeTable::GetRowOfValue( int nValue ) const
 
 {
-    return GetRowOfValue( (double) nValue );
+    return GetRowOfValue( static_cast<double>(nValue) );
 }
 
 /************************************************************************/
@@ -364,9 +375,9 @@ int GDALRasterAttributeTable::GetRowOfValue( int nValue ) const
  *
  * If the table already has rows, all row values for the new column will
  * be initialized to the default value ("", or zero).  The new column is
- * always created as the last column, can will be column (field) 
+ * always created as the last column, can will be column (field)
  * "GetColumnCount()-1" after CreateColumn() has completed successfully.
- * 
+ *
  * This method is the same as the C function GDALRATCreateColumn().
  *
  * @param pszFieldName the name of the field to create.
@@ -376,9 +387,9 @@ int GDALRasterAttributeTable::GetRowOfValue( int nValue ) const
  * @return CE_None on success or CE_Failure if something goes wrong.
  */
 
-CPLErr GDALRasterAttributeTable::CreateColumn( CPL_UNUSED const char *pszFieldName,
-                                               CPL_UNUSED GDALRATFieldType eFieldType,
-                                               CPL_UNUSED GDALRATFieldUsage eFieldUsage )
+CPLErr GDALRasterAttributeTable::CreateColumn(
+    const char * /* pszFieldName */, GDALRATFieldType /* eFieldType */,
+    GDALRATFieldUsage /* eFieldUsage */ )
 {
     return CE_Failure;
 }
@@ -390,19 +401,19 @@ CPLErr GDALRasterAttributeTable::CreateColumn( CPL_UNUSED const char *pszFieldNa
 /**
  * \brief Create new column.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::CreateColumn()
+ * This function is the same as the C++ method
+ * GDALRasterAttributeTable::CreateColumn()
  */
-CPLErr CPL_STDCALL GDALRATCreateColumn( GDALRasterAttributeTableH hRAT, 
-                                        const char *pszFieldName, 
+CPLErr CPL_STDCALL GDALRATCreateColumn( GDALRasterAttributeTableH hRAT,
+                                        const char *pszFieldName,
                                         GDALRATFieldType eFieldType,
                                         GDALRATFieldUsage eFieldUsage )
 
 {
     VALIDATE_POINTER1( hRAT, "GDALRATCreateColumn", CE_Failure );
 
-    return ((GDALRasterAttributeTable *) hRAT)->CreateColumn( pszFieldName, 
-                                                              eFieldType,
-                                                              eFieldUsage );
+    return static_cast<GDALRasterAttributeTable *>(hRAT)->
+        CreateColumn( pszFieldName, eFieldType, eFieldUsage );
 }
 
 /************************************************************************/
@@ -419,13 +430,13 @@ CPLErr CPL_STDCALL GDALRATCreateColumn( GDALRasterAttributeTableH hRAT,
  * This method is the same as the C function GDALRATSetLinearBinning().
  *
  * @param dfRow0MinIn the lower bound (pixel value) of the first category.
- * @param dfBinSizeIn the width of each category (in pixel value units). 
+ * @param dfBinSizeIn the width of each category (in pixel value units).
  *
  * @return CE_None on success or CE_Failure on failure.
  */
 
-CPLErr GDALRasterAttributeTable::SetLinearBinning( CPL_UNUSED double dfRow0MinIn,
-                                                   CPL_UNUSED double dfBinSizeIn )
+CPLErr GDALRasterAttributeTable::SetLinearBinning( double /* dfRow0MinIn */,
+                                                   double /* dfBinSizeIn */ )
 {
     return CE_Failure;
 }
@@ -437,17 +448,18 @@ CPLErr GDALRasterAttributeTable::SetLinearBinning( CPL_UNUSED double dfRow0MinIn
 /**
  * \brief Set linear binning information.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::SetLinearBinning()
+ * This function is the same as the C++ method
+ * GDALRasterAttributeTable::SetLinearBinning()
  */
-CPLErr CPL_STDCALL 
-GDALRATSetLinearBinning( GDALRasterAttributeTableH hRAT, 
+CPLErr CPL_STDCALL
+GDALRATSetLinearBinning( GDALRasterAttributeTableH hRAT,
                          double dfRow0Min, double dfBinSize )
 
 {
     VALIDATE_POINTER1( hRAT, "GDALRATSetLinearBinning", CE_Failure );
 
-    return ((GDALRasterAttributeTable *) hRAT)->SetLinearBinning(
-        dfRow0Min, dfBinSize );
+    return static_cast<GDALRasterAttributeTable *>(hRAT)->
+        SetLinearBinning( dfRow0Min, dfBinSize );
 }
 
 /************************************************************************/
@@ -467,8 +479,8 @@ GDALRATSetLinearBinning( GDALRasterAttributeTableH hRAT,
  * @return TRUE if linear binning information exists or FALSE if there is none.
  */
 
-int GDALRasterAttributeTable::GetLinearBinning( CPL_UNUSED double *pdfRow0Min,
-                                                CPL_UNUSED double *pdfBinSize ) const
+int GDALRasterAttributeTable::GetLinearBinning(
+    double * /* pdfRow0Min */ , double * /* pdfBinSize */ ) const
 {
     return FALSE;
 }
@@ -480,17 +492,18 @@ int GDALRasterAttributeTable::GetLinearBinning( CPL_UNUSED double *pdfRow0Min,
 /**
  * \brief Get linear binning information.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::GetLinearBinning()
+ * This function is the same as the C++ method
+ * GDALRasterAttributeTable::GetLinearBinning()
  */
-int CPL_STDCALL 
-GDALRATGetLinearBinning( GDALRasterAttributeTableH hRAT, 
+int CPL_STDCALL
+GDALRATGetLinearBinning( GDALRasterAttributeTableH hRAT,
                          double *pdfRow0Min, double *pdfBinSize )
 
 {
     VALIDATE_POINTER1( hRAT, "GDALRATGetLinearBinning", 0 );
 
-    return ((GDALRasterAttributeTable *) hRAT)->GetLinearBinning(
-        pdfRow0Min, pdfBinSize );
+    return static_cast<GDALRasterAttributeTable *>(hRAT)->
+        GetLinearBinning( pdfRow0Min, pdfBinSize );
 }
 
 /************************************************************************/
@@ -500,68 +513,67 @@ GDALRATGetLinearBinning( GDALRasterAttributeTableH hRAT,
 CPLXMLNode *GDALRasterAttributeTable::Serialize() const
 
 {
-    CPLXMLNode *psTree = NULL;
-    CPLXMLNode *psRow = NULL;
-
-    if( ( GetColumnCount() == 0 ) && ( GetRowCount() == 0 ) ) 
- 	    return NULL;
+    if( ( GetColumnCount() == 0 ) && ( GetRowCount() == 0 ) )
+        return NULL;
 
-    psTree = CPLCreateXMLNode( NULL, CXT_Element, "GDALRasterAttributeTable" );
+    CPLXMLNode *psTree
+        = CPLCreateXMLNode( NULL, CXT_Element, "GDALRasterAttributeTable" );
 
 /* -------------------------------------------------------------------- */
 /*      Add attributes with regular binning info if appropriate.        */
 /* -------------------------------------------------------------------- */
-    char szValue[128];
-    double dfRow0Min, dfBinSize;
+    char szValue[128] = { '\0' };
+    double dfRow0Min = 0.0;
+    double dfBinSize = 0.0;
 
     if( GetLinearBinning(&dfRow0Min, &dfBinSize) )
     {
-        CPLsprintf( szValue, "%.16g", dfRow0Min );
-        CPLCreateXMLNode( 
-            CPLCreateXMLNode( psTree, CXT_Attribute, "Row0Min" ), 
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g", dfRow0Min );
+        CPLCreateXMLNode(
+            CPLCreateXMLNode( psTree, CXT_Attribute, "Row0Min" ),
             CXT_Text, szValue );
 
-        CPLsprintf( szValue, "%.16g", dfBinSize );
-        CPLCreateXMLNode( 
-            CPLCreateXMLNode( psTree, CXT_Attribute, "BinSize" ), 
+        CPLsnprintf( szValue, sizeof(szValue), "%.16g", dfBinSize );
+        CPLCreateXMLNode(
+            CPLCreateXMLNode( psTree, CXT_Attribute, "BinSize" ),
             CXT_Text, szValue );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Define each column.                                             */
 /* -------------------------------------------------------------------- */
-    int iCol;
-    int iColCount = GetColumnCount();
+    const int iColCount = GetColumnCount();
 
-    for( iCol = 0; iCol < iColCount; iCol++ )
+    for( int iCol = 0; iCol < iColCount; iCol++ )
     {
-        CPLXMLNode *psCol;
+        CPLXMLNode *psCol
+            = CPLCreateXMLNode( psTree, CXT_Element, "FieldDefn" );
 
-        psCol = CPLCreateXMLNode( psTree, CXT_Element, "FieldDefn" );
-        
-        sprintf( szValue, "%d", iCol );
-        CPLCreateXMLNode( 
-            CPLCreateXMLNode( psCol, CXT_Attribute, "index" ), 
+        snprintf( szValue, sizeof(szValue), "%d", iCol );
+        CPLCreateXMLNode(
+            CPLCreateXMLNode( psCol, CXT_Attribute, "index" ),
             CXT_Text, szValue );
 
-        CPLCreateXMLElementAndValue( psCol, "Name", 
+        CPLCreateXMLElementAndValue( psCol, "Name",
                                      GetNameOfCol(iCol) );
 
-        sprintf( szValue, "%d", (int) GetTypeOfCol(iCol) );
+        snprintf( szValue, sizeof(szValue),
+                  "%d", static_cast<int>(GetTypeOfCol(iCol)) );
         CPLCreateXMLElementAndValue( psCol, "Type", szValue );
 
-        sprintf( szValue, "%d", (int) GetUsageOfCol(iCol) );
+        snprintf( szValue, sizeof(szValue),
+                  "%d", static_cast<int>(GetUsageOfCol(iCol)) );
         CPLCreateXMLElementAndValue( psCol, "Usage", szValue );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Write out each row.                                             */
 /* -------------------------------------------------------------------- */
-    int iRow;
-    int iRowCount = GetRowCount();
+    const int iRowCount = GetRowCount();
     CPLXMLNode *psTail = NULL;
+    CPLXMLNode *psRow = NULL;
 
-    for( iRow = 0; iRow < iRowCount; iRow++ )
+    for( int iRow = 0; iRow < iRowCount; iRow++ )
     {
         psRow = CPLCreateXMLNode( NULL, CXT_Element, "Row" );
         if( psTail == NULL )
@@ -570,19 +582,21 @@ CPLXMLNode *GDALRasterAttributeTable::Serialize() const
             psTail->psNext = psRow;
         psTail = psRow;
 
-        sprintf( szValue, "%d", iRow );
-        CPLCreateXMLNode( 
-            CPLCreateXMLNode( psRow, CXT_Attribute, "index" ), 
+        snprintf( szValue, sizeof(szValue), "%d", iRow );
+        CPLCreateXMLNode(
+            CPLCreateXMLNode( psRow, CXT_Attribute, "index" ),
             CXT_Text, szValue );
 
-        for( iCol = 0; iCol < iColCount; iCol++ )
+        for( int iCol = 0; iCol < iColCount; iCol++ )
         {
             const char *pszValue = szValue;
 
             if( GetTypeOfCol(iCol) == GFT_Integer )
-                sprintf( szValue, "%d", GetValueAsInt(iRow, iCol) );
+                snprintf( szValue, sizeof(szValue),
+                          "%d", GetValueAsInt(iRow, iCol) );
             else if( GetTypeOfCol(iCol) == GFT_Real )
-                CPLsprintf( szValue, "%.16g", GetValueAsDouble(iRow, iCol) );
+                CPLsnprintf( szValue, sizeof(szValue),
+                             "%.16g", GetValueAsDouble(iRow, iCol) );
             else
                 pszValue = GetValueAsString(iRow, iCol);
 
@@ -602,7 +616,7 @@ void *GDALRasterAttributeTable::SerializeJSON() const
 {
     json_object *poRAT = json_object_new_object();
 
-    if( ( GetColumnCount() == 0 ) && ( GetRowCount() == 0 ) ) 
+    if( ( GetColumnCount() == 0 ) && ( GetRowCount() == 0 ) )
         return poRAT;
 
 
@@ -624,25 +638,26 @@ void *GDALRasterAttributeTable::SerializeJSON() const
 /* -------------------------------------------------------------------- */
 /*      Define each column.                                             */
 /* -------------------------------------------------------------------- */
-    int iCol;
-    int iColCount = GetColumnCount();
+    const int iColCount = GetColumnCount();
     json_object *poFieldDefnArray = json_object_new_array();
-    json_object *poFieldDefn, *poColumnIndex, *poName, *poType, *poUsage;
 
-    for( iCol = 0; iCol < iColCount; iCol++ )
+    for( int iCol = 0; iCol < iColCount; iCol++ )
     {
-        poFieldDefn = json_object_new_object();
+        json_object * const poFieldDefn = json_object_new_object();
 
-        poColumnIndex = json_object_new_int( iCol );
+        json_object * const poColumnIndex = json_object_new_int( iCol );
         json_object_object_add( poFieldDefn, "index", poColumnIndex );
 
-        poName = json_object_new_string( GetNameOfCol(iCol) );
+        json_object * const poName =
+            json_object_new_string( GetNameOfCol(iCol) );
         json_object_object_add( poFieldDefn, "name", poName );
 
-        poType = json_object_new_int( (int) GetTypeOfCol(iCol) );
+        json_object * const poType =
+            json_object_new_int( static_cast<int>( GetTypeOfCol(iCol) ) );
         json_object_object_add( poFieldDefn, "type", poType );
 
-        poUsage = json_object_new_int( (int) GetUsageOfCol(iCol) );
+        json_object * const poUsage =
+            json_object_new_int( static_cast<int>( GetUsageOfCol(iCol) ) );
         json_object_object_add( poFieldDefn, "usage", poUsage );
 
         json_object_array_add( poFieldDefnArray, poFieldDefn );
@@ -653,26 +668,26 @@ void *GDALRasterAttributeTable::SerializeJSON() const
 /* -------------------------------------------------------------------- */
 /*      Write out each row.                                             */
 /* -------------------------------------------------------------------- */
-    int iRow;
-    int iRowCount = GetRowCount();
+    const int iRowCount = GetRowCount();
     json_object *poRowArray = json_object_new_array();
-    json_object *poRow, *poRowIndex, *poFArray, *poF;
 
-    for( iRow = 0; iRow < iRowCount; iRow++ )
+    for( int iRow = 0; iRow < iRowCount; iRow++ )
     {
-        poRow = json_object_new_object();
+        json_object * const poRow = json_object_new_object();
 
-        poRowIndex = json_object_new_int(iRow);
+        json_object * const poRowIndex = json_object_new_int(iRow);
         json_object_object_add( poRow, "index", poRowIndex );
 
-        poFArray = json_object_new_array();
+        json_object * const poFArray = json_object_new_array();
 
-        for( iCol = 0; iCol < iColCount; iCol++ )
+        for( int iCol = 0; iCol < iColCount; iCol++ )
         {
+            json_object *poF = NULL;
             if( GetTypeOfCol(iCol) == GFT_Integer )
                 poF = json_object_new_int( GetValueAsInt(iRow, iCol) );
             else if( GetTypeOfCol(iCol) == GFT_Real )
-                poF = json_object_new_double_with_precision( GetValueAsDouble(iRow, iCol), 16 );
+                poF = json_object_new_double_with_precision(
+                    GetValueAsDouble(iRow, iCol), 16 );
             else
                 poF = json_object_new_string( GetValueAsString(iRow, iCol) );
 
@@ -690,52 +705,58 @@ void *GDALRasterAttributeTable::SerializeJSON() const
 /*                              XMLInit()                               */
 /************************************************************************/
 
-CPLErr GDALRasterAttributeTable::XMLInit( CPLXMLNode *psTree, 
+CPLErr GDALRasterAttributeTable::XMLInit( CPLXMLNode *psTree,
                                           const char * /*pszVRTPath*/ )
 
 {
     CPLAssert( GetRowCount() == 0 && GetColumnCount() == 0 );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Linear binning.                                                 */
 /* -------------------------------------------------------------------- */
-    if( CPLGetXMLValue( psTree, "Row0Min", NULL ) 
+    if( CPLGetXMLValue( psTree, "Row0Min", NULL )
         && CPLGetXMLValue( psTree, "BinSize", NULL ) )
     {
-        SetLinearBinning( CPLAtof(CPLGetXMLValue( psTree, "Row0Min","" )), 
+        SetLinearBinning( CPLAtof(CPLGetXMLValue( psTree, "Row0Min","" )),
                           CPLAtof(CPLGetXMLValue( psTree, "BinSize","" )) );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Column definitions                                              */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psChild;
 
-    for( psChild = psTree->psChild; psChild != NULL; psChild = psChild->psNext)
+    for( CPLXMLNode *psChild = psTree->psChild;
+         psChild != NULL;
+         psChild = psChild->psNext)
     {
-        if( psChild->eType == CXT_Element 
+        if( psChild->eType == CXT_Element
             && EQUAL(psChild->pszValue,"FieldDefn") )
         {
-            CreateColumn( 
-              CPLGetXMLValue( psChild, "Name", "" ), 
-              (GDALRATFieldType) atoi(CPLGetXMLValue( psChild, "Type", "1" )),
-              (GDALRATFieldUsage) atoi(CPLGetXMLValue( psChild, "Usage","0")));
+            CreateColumn(
+                CPLGetXMLValue( psChild, "Name", "" ),
+                static_cast<GDALRATFieldType>(
+                    atoi(CPLGetXMLValue( psChild, "Type", "1" )) ),
+                static_cast<GDALRATFieldUsage>(
+                    atoi(CPLGetXMLValue( psChild, "Usage","0"))) );
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Row data.                                                       */
 /* -------------------------------------------------------------------- */
-    for( psChild = psTree->psChild; psChild != NULL; psChild = psChild->psNext)
+    for( CPLXMLNode *psChild = psTree->psChild;
+         psChild != NULL;
+         psChild = psChild->psNext)
     {
-        if( psChild->eType == CXT_Element 
+        if( psChild->eType == CXT_Element
             && EQUAL(psChild->pszValue,"Row") )
         {
-            int iRow = atoi(CPLGetXMLValue(psChild,"index","0"));
+            const int iRow = atoi(CPLGetXMLValue(psChild,"index","0"));
             int iField = 0;
-            CPLXMLNode *psF;
 
-            for( psF = psChild->psChild; psF != NULL; psF = psF->psNext )
+            for( CPLXMLNode *psF = psChild->psChild;
+                 psF != NULL;
+                 psF = psF->psNext )
             {
                 if( psF->eType != CXT_Element || !EQUAL(psF->pszValue,"F") )
                     continue;
@@ -760,15 +781,15 @@ CPLErr GDALRasterAttributeTable::XMLInit( CPLXMLNode *psTree,
  * \brief Initialize from color table.
  *
  * This method will setup a whole raster attribute table based on the
- * contents of the passed color table.  The Value (GFU_MinMax), 
+ * contents of the passed color table.  The Value (GFU_MinMax),
  * Red (GFU_Red), Green (GFU_Green), Blue (GFU_Blue), and Alpha (GFU_Alpha)
- * fields are created, and a row is set for each entry in the color table. 
- * 
- * The raster attribute table must be empty before calling 
- * InitializeFromColorTable(). 
+ * fields are created, and a row is set for each entry in the color table.
+ *
+ * The raster attribute table must be empty before calling
+ * InitializeFromColorTable().
  *
  * The Value fields are set based on the implicit assumption with color
- * tables that entry 0 applies to pixel value 0, 1 to 1, etc. 
+ * tables that entry 0 applies to pixel value 0, 1 to 1, etc.
  *
  * This method is the same as the C function GDALRATInitializeFromColorTable().
  *
@@ -777,16 +798,15 @@ CPLErr GDALRasterAttributeTable::XMLInit( CPLXMLNode *psTree,
  * @return CE_None on success or CE_Failure if something goes wrong.
  */
 
-CPLErr GDALRasterAttributeTable::InitializeFromColorTable( 
+CPLErr GDALRasterAttributeTable::InitializeFromColorTable(
     const GDALColorTable *poTable )
 
 {
-    int iRow;
-
     if( GetRowCount() > 0 || GetColumnCount() > 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Raster Attribute Table not empty in InitializeFromColorTable()" );
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Raster Attribute Table not empty in "
+                  "InitializeFromColorTable()" );
         return CE_Failure;
     }
 
@@ -799,7 +819,7 @@ CPLErr GDALRasterAttributeTable::InitializeFromColorTable(
 
     SetRowCount( poTable->GetColorEntryCount() );
 
-    for( iRow = 0; iRow < poTable->GetColorEntryCount(); iRow++ )
+    for( int iRow = 0; iRow < poTable->GetColorEntryCount(); iRow++ )
     {
         GDALColorEntry sEntry;
 
@@ -822,18 +842,18 @@ CPLErr GDALRasterAttributeTable::InitializeFromColorTable(
 /**
  * \brief Initialize from color table.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::InitializeFromColorTable()
+ * This function is the same as the C++ method
+ * GDALRasterAttributeTable::InitializeFromColorTable()
  */
-CPLErr CPL_STDCALL 
+CPLErr CPL_STDCALL
 GDALRATInitializeFromColorTable( GDALRasterAttributeTableH hRAT,
                                  GDALColorTableH hCT )
-                                 
 
 {
     VALIDATE_POINTER1( hRAT, "GDALRATInitializeFromColorTable", CE_Failure );
 
-    return ((GDALRasterAttributeTable *) hRAT)->
-        InitializeFromColorTable( (GDALColorTable *) hCT );
+    return static_cast<GDALRasterAttributeTable *>(hRAT)->
+        InitializeFromColorTable( static_cast<GDALColorTable *>(hCT) );
 }
 
 /************************************************************************/
@@ -844,84 +864,76 @@ GDALRATInitializeFromColorTable( GDALRasterAttributeTableH hRAT,
  * \brief Translate to a color table.
  *
  * This method will attempt to create a corresponding GDALColorTable from
- * this raster attribute table. 
- * 
+ * this raster attribute table.
+ *
  * This method is the same as the C function GDALRATTranslateToColorTable().
  *
- * @param nEntryCount The number of entries to produce (0 to nEntryCount-1), or -1 to auto-determine the number of entries.
+ * @param nEntryCount The number of entries to produce (0 to nEntryCount-1),
+ * or -1 to auto-determine the number of entries.
  *
  * @return the generated color table or NULL on failure.
  */
 
-GDALColorTable *GDALRasterAttributeTable::TranslateToColorTable( 
+GDALColorTable *GDALRasterAttributeTable::TranslateToColorTable(
     int nEntryCount )
 
 {
 /* -------------------------------------------------------------------- */
 /*      Establish which fields are red, green, blue and alpha.          */
 /* -------------------------------------------------------------------- */
-    int iRed, iGreen, iBlue, iAlpha;
-
-    iRed = GetColOfUsage( GFU_Red );
-    iGreen = GetColOfUsage( GFU_Green );
-    iBlue = GetColOfUsage( GFU_Blue );
-    iAlpha = GetColOfUsage( GFU_Alpha );
+    const int iRed = GetColOfUsage( GFU_Red );
+    const int iGreen = GetColOfUsage( GFU_Green );
+    const int iBlue = GetColOfUsage( GFU_Blue );
 
     if( iRed == -1 || iGreen == -1 || iBlue == -1 )
         return NULL;
 
+    const int iAlpha = GetColOfUsage( GFU_Alpha );
+
 /* -------------------------------------------------------------------- */
 /*      If we aren't given an explicit number of values to scan for,    */
 /*      search for the maximum "max" value.                             */
 /* -------------------------------------------------------------------- */
     if( nEntryCount == -1 )
     {
-        int  iRow;
-        int  iMaxCol;
-
-        iMaxCol = GetColOfUsage( GFU_Max );
+        int iMaxCol = GetColOfUsage( GFU_Max );
         if( iMaxCol == -1 )
             iMaxCol = GetColOfUsage( GFU_MinMax );
 
         if( iMaxCol == -1 || GetRowCount() == 0 )
             return NULL;
-    
-        for( iRow = 0; iRow < GetRowCount(); iRow++ )
-            nEntryCount = MAX(nEntryCount,GetValueAsInt(iRow,iMaxCol)+1);
+
+        for( int iRow = 0; iRow < GetRowCount(); iRow++ )
+            nEntryCount = MAX(nEntryCount, GetValueAsInt(iRow, iMaxCol) + 1);
 
         if( nEntryCount < 0 )
             return NULL;
 
         // restrict our number of entries to something vaguely sensible
-        nEntryCount = MIN(65535,nEntryCount);
+        nEntryCount = MIN(65535, nEntryCount);
     }
 
 /* -------------------------------------------------------------------- */
 /*      Assign values to color table.                                   */
 /* -------------------------------------------------------------------- */
     GDALColorTable *poCT = new GDALColorTable();
-    int iEntry;
 
-    for( iEntry = 0; iEntry < nEntryCount; iEntry++ )
+    for( int iEntry = 0; iEntry < nEntryCount; iEntry++ )
     {
-        GDALColorEntry sColor;
-        int iRow = GetRowOfValue( iEntry );
+        GDALColorEntry sColor = { 0, 0, 0, 0 };
+        const int iRow = GetRowOfValue( iEntry );
 
-        if( iRow == -1 )
-        {
-            sColor.c1 = sColor.c2 = sColor.c3 = sColor.c4 = 0;
-        }
-        else
+        if( iRow != -1 )
         {
-            sColor.c1 = (short) GetValueAsInt( iRow, iRed );
-            sColor.c2 = (short) GetValueAsInt( iRow, iGreen );
-            sColor.c3 = (short) GetValueAsInt( iRow, iBlue );
+            sColor.c1 = static_cast<short>( GetValueAsInt( iRow, iRed ) );
+            sColor.c2 = static_cast<short>( GetValueAsInt( iRow, iGreen ) );
+            sColor.c3 = static_cast<short>( GetValueAsInt( iRow, iBlue ) );
             if( iAlpha == -1 )
                 sColor.c4 = 255;
             else
-                sColor.c4 = (short) GetValueAsInt( iRow, iAlpha );
+                sColor.c4 = static_cast<short>( GetValueAsInt( iRow, iAlpha ) );
         }
-        
+
         poCT->SetColorEntry( iEntry, &sColor );
     }
 
@@ -935,17 +947,17 @@ GDALColorTable *GDALRasterAttributeTable::TranslateToColorTable(
 /**
  * \brief Translate to a color table.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::TranslateToColorTable()
+ * This function is the same as the C++ method
+ * GDALRasterAttributeTable::TranslateToColorTable()
  */
-GDALColorTableH CPL_STDCALL 
+GDALColorTableH CPL_STDCALL
 GDALRATTranslateToColorTable( GDALRasterAttributeTableH hRAT,
                               int nEntryCount )
-                                 
 
 {
     VALIDATE_POINTER1( hRAT, "GDALRATTranslateToColorTable", NULL );
 
-    return ((GDALRasterAttributeTable *) hRAT)->
+    return static_cast<GDALRasterAttributeTable *>(hRAT)->
         TranslateToColorTable( nEntryCount );
 }
 
@@ -957,12 +969,12 @@ GDALRATTranslateToColorTable( GDALRasterAttributeTableH hRAT,
 /**
  * \brief Dump RAT in readable form.
  *
- * Currently the readable form is the XML encoding ... only barely 
- * readable. 
+ * Currently the readable form is the XML encoding ... only barely
+ * readable.
  *
  * This method is the same as the C function GDALRATDumpReadable().
  *
- * @param fp file to dump to or NULL for stdout. 
+ * @param fp file to dump to or NULL for stdout.
  */
 
 void GDALRasterAttributeTable::DumpReadable( FILE * fp )
@@ -988,20 +1000,21 @@ void GDALRasterAttributeTable::DumpReadable( FILE * fp )
 /**
  * \brief Dump RAT in readable form.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::DumpReadable()
+ * This function is the same as the C++ method
+ * GDALRasterAttributeTable::DumpReadable()
  */
-void CPL_STDCALL 
+void CPL_STDCALL
 GDALRATDumpReadable( GDALRasterAttributeTableH hRAT, FILE *fp )
 
 {
     VALIDATE_POINTER0( hRAT, "GDALRATDumpReadable" );
 
-    ((GDALRasterAttributeTable *) hRAT)->DumpReadable( fp );
+    static_cast<GDALRasterAttributeTable *>(hRAT)->DumpReadable( fp );
 }
 
 
 /* \class GDALDefaultRasterAttributeTable
- * 
+ *
  * An implementation of GDALRasterAttributeTable that keeps
  * all data in memory. This is the same as the implementation
  * of GDALRasterAttributeTable in GDAL <= 1.10.
@@ -1015,17 +1028,15 @@ GDALRATDumpReadable( GDALRasterAttributeTableH hRAT, FILE *fp )
 
 //! Construct empty table.
 
-GDALDefaultRasterAttributeTable::GDALDefaultRasterAttributeTable()
-
-{
-    bColumnsAnalysed = FALSE;
-    nMinCol = -1;
-    nMaxCol = -1;
-    bLinearBinning = FALSE;
-    dfRow0Min = -0.5;
-    dfBinSize = 1.0;
-    nRowCount = 0;
-}
+GDALDefaultRasterAttributeTable::GDALDefaultRasterAttributeTable() :
+    bLinearBinning(FALSE),
+    dfRow0Min(-0.5),
+    dfBinSize(1.0),
+    bColumnsAnalysed(FALSE),
+    nMinCol(-1),
+    nMaxCol(-1),
+    nRowCount(0)
+{}
 
 /************************************************************************/
 /*                   GDALCreateRasterAttributeTable()                   */
@@ -1034,12 +1045,13 @@ GDALDefaultRasterAttributeTable::GDALDefaultRasterAttributeTable()
 /**
  * \brief Construct empty table.
  *
- * This function is the same as the C++ method GDALDefaultRasterAttributeTable::GDALDefaultRasterAttributeTable()
+ * This function is the same as the C++ method
+ * GDALDefaultRasterAttributeTable::GDALDefaultRasterAttributeTable()
  */
 GDALRasterAttributeTableH CPL_STDCALL GDALCreateRasterAttributeTable()
 
 {
-    return (GDALRasterAttributeTableH) (new GDALDefaultRasterAttributeTable());
+    return new GDALDefaultRasterAttributeTable();
 }
 
 /************************************************************************/
@@ -1048,8 +1060,8 @@ GDALRasterAttributeTableH CPL_STDCALL GDALCreateRasterAttributeTable()
 
 //! Copy constructor.
 
-GDALDefaultRasterAttributeTable::GDALDefaultRasterAttributeTable( 
-    const GDALDefaultRasterAttributeTable &oOther )
+GDALDefaultRasterAttributeTable::GDALDefaultRasterAttributeTable(
+    const GDALDefaultRasterAttributeTable &oOther ) : GDALRasterAttributeTable()
 
 {
     // We have tried to be careful to allow wholesale assignment
@@ -1062,10 +1074,7 @@ GDALDefaultRasterAttributeTable::GDALDefaultRasterAttributeTable(
 /*      All magic done by magic by the container destructors.           */
 /************************************************************************/
 
-GDALDefaultRasterAttributeTable::~GDALDefaultRasterAttributeTable()
-
-{
-}
+GDALDefaultRasterAttributeTable::~GDALDefaultRasterAttributeTable() {}
 
 /************************************************************************/
 /*                  GDALDestroyRasterAttributeTable()                   */
@@ -1074,9 +1083,10 @@ GDALDefaultRasterAttributeTable::~GDALDefaultRasterAttributeTable()
 /**
  * \brief Destroys a RAT.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::~GDALRasterAttributeTable()
+ * This function is the same as the C++ method
+ * GDALRasterAttributeTable::~GDALRasterAttributeTable()
  */
-void CPL_STDCALL 
+void CPL_STDCALL
 GDALDestroyRasterAttributeTable( GDALRasterAttributeTableH hRAT )
 
 {
@@ -1112,7 +1122,7 @@ void GDALDefaultRasterAttributeTable::AnalyseColumns()
 int GDALDefaultRasterAttributeTable::GetColumnCount() const
 
 {
-    return aoFields.size();
+    return static_cast<int>(aoFields.size());
 }
 
 /************************************************************************/
@@ -1122,14 +1132,15 @@ int GDALDefaultRasterAttributeTable::GetColumnCount() const
 /**
  * \brief Fetch table column count.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::GetColumnCount()
+ * This function is the same as the C++ method
+ * GDALRasterAttributeTable::GetColumnCount()
  */
 int CPL_STDCALL GDALRATGetColumnCount( GDALRasterAttributeTableH hRAT )
 
 {
     VALIDATE_POINTER1( hRAT, "GDALRATGetColumnCount", 0 );
 
-    return ((GDALRasterAttributeTable *) hRAT)->GetColumnCount();
+    return static_cast<GDALRasterAttributeTable *>(hRAT)->GetColumnCount();
 }
 
 /************************************************************************/
@@ -1142,8 +1153,7 @@ const char *GDALDefaultRasterAttributeTable::GetNameOfCol( int iCol ) const
     if( iCol < 0 || iCol >= (int) aoFields.size() )
         return "";
 
-    else
-        return aoFields[iCol].sName;
+    return aoFields[iCol].sName;
 }
 
 /************************************************************************/
@@ -1153,7 +1163,8 @@ const char *GDALDefaultRasterAttributeTable::GetNameOfCol( int iCol ) const
 /**
  * \brief Fetch name of indicated column.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::GetNameOfCol()
+ * This function is the same as the C++ method
+ * GDALRasterAttributeTable::GetNameOfCol()
  */
 const char *CPL_STDCALL GDALRATGetNameOfCol( GDALRasterAttributeTableH hRAT,
                                              int iCol )
@@ -1161,21 +1172,21 @@ const char *CPL_STDCALL GDALRATGetNameOfCol( GDALRasterAttributeTableH hRAT,
 {
     VALIDATE_POINTER1( hRAT, "GDALRATGetNameOfCol", NULL );
 
-    return ((GDALRasterAttributeTable *) hRAT)->GetNameOfCol( iCol );
+    return static_cast<GDALRasterAttributeTable *>(hRAT)->GetNameOfCol( iCol );
 }
 
 /************************************************************************/
 /*                           GetUsageOfCol()                            */
 /************************************************************************/
 
-GDALRATFieldUsage GDALDefaultRasterAttributeTable::GetUsageOfCol( int iCol ) const
+GDALRATFieldUsage GDALDefaultRasterAttributeTable::GetUsageOfCol(
+    int iCol ) const
 
 {
     if( iCol < 0 || iCol >= (int) aoFields.size() )
         return GFU_Generic;
 
-    else
-        return aoFields[iCol].eUsage;
+    return aoFields[iCol].eUsage;
 }
 
 /************************************************************************/
@@ -1183,17 +1194,18 @@ GDALRATFieldUsage GDALDefaultRasterAttributeTable::GetUsageOfCol( int iCol ) con
 /************************************************************************/
 
 /**
- * \brief Fetch column usage value. 
+ * \brief Fetch column usage value.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::GetUsageOfColetNameOfCol()
+ * This function is the same as the C++ method
+ * GDALRasterAttributeTable::GetUsageOfColetNameOfCol()
  */
-GDALRATFieldUsage CPL_STDCALL 
+GDALRATFieldUsage CPL_STDCALL
 GDALRATGetUsageOfCol( GDALRasterAttributeTableH hRAT, int iCol )
 
 {
     VALIDATE_POINTER1( hRAT, "GDALRATGetUsageOfCol", GFU_Generic );
 
-    return ((GDALRasterAttributeTable *) hRAT)->GetUsageOfCol( iCol );
+    return static_cast<GDALRasterAttributeTable *>(hRAT)->GetUsageOfCol( iCol );
 }
 
 /************************************************************************/
@@ -1206,8 +1218,7 @@ GDALRATFieldType GDALDefaultRasterAttributeTable::GetTypeOfCol( int iCol ) const
     if( iCol < 0 || iCol >= (int) aoFields.size() )
         return GFT_Integer;
 
-    else
-        return aoFields[iCol].eType;
+    return aoFields[iCol].eType;
 }
 
 /************************************************************************/
@@ -1217,27 +1228,27 @@ GDALRATFieldType GDALDefaultRasterAttributeTable::GetTypeOfCol( int iCol ) const
 /**
  * \brief Fetch column type.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::GetTypeOfCol()
+ * This function is the same as the C++ method
+ * GDALRasterAttributeTable::GetTypeOfCol()
  */
-GDALRATFieldType CPL_STDCALL 
+GDALRATFieldType CPL_STDCALL
 GDALRATGetTypeOfCol( GDALRasterAttributeTableH hRAT, int iCol )
 
 {
     VALIDATE_POINTER1( hRAT, "GDALRATGetTypeOfCol", GFT_Integer );
 
-    return ((GDALRasterAttributeTable *) hRAT)->GetTypeOfCol( iCol );
+    return static_cast<GDALRasterAttributeTable *>(hRAT)->GetTypeOfCol( iCol );
 }
 
 /************************************************************************/
 /*                           GetColOfUsage()                            */
 /************************************************************************/
 
-int GDALDefaultRasterAttributeTable::GetColOfUsage( GDALRATFieldUsage eUsage ) const
+int GDALDefaultRasterAttributeTable::GetColOfUsage(
+    GDALRATFieldUsage eUsage ) const
 
 {
-    unsigned int i;
-
-    for( i = 0; i < aoFields.size(); i++ )
+    for( unsigned int i = 0; i < aoFields.size(); i++ )
     {
         if( aoFields[i].eUsage == eUsage )
             return i;
@@ -1253,16 +1264,17 @@ int GDALDefaultRasterAttributeTable::GetColOfUsage( GDALRATFieldUsage eUsage ) c
 /**
  * \brief Fetch column index for given usage.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::GetColOfUsage()
+ * This function is the same as the C++ method
+ * GDALRasterAttributeTable::GetColOfUsage()
  */
-int CPL_STDCALL 
-GDALRATGetColOfUsage( GDALRasterAttributeTableH hRAT, 
-                      GDALRATFieldUsage eUsage )
+int CPL_STDCALL
+GDALRATGetColOfUsage( GDALRasterAttributeTableH hRAT, GDALRATFieldUsage eUsage )
 
 {
     VALIDATE_POINTER1( hRAT, "GDALRATGetColOfUsage", 0 );
 
-    return ((GDALRasterAttributeTable *) hRAT)->GetColOfUsage( eUsage );
+    return static_cast<GDALRasterAttributeTable *>(hRAT)->
+        GetColOfUsage( eUsage );
 }
 
 /************************************************************************/
@@ -1272,7 +1284,7 @@ GDALRATGetColOfUsage( GDALRasterAttributeTableH hRAT,
 int GDALDefaultRasterAttributeTable::GetRowCount() const
 
 {
-    return (int) nRowCount;
+    return static_cast<int>( nRowCount );
 }
 
 /************************************************************************/
@@ -1281,15 +1293,16 @@ int GDALDefaultRasterAttributeTable::GetRowCount() const
 /**
  * \brief Fetch row count.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::GetRowCount()
+ * This function is the same as the C++ method
+ * GDALRasterAttributeTable::GetRowCount()
  */
-int CPL_STDCALL 
+int CPL_STDCALL
 GDALRATGetRowCount( GDALRasterAttributeTableH hRAT )
 
 {
     VALIDATE_POINTER1( hRAT, "GDALRATGetRowCount", 0 );
 
-    return ((GDALRasterAttributeTable *) hRAT)->GetRowCount();
+    return static_cast<GDALRasterAttributeTable *>(hRAT)->GetRowCount();
 }
 
 /************************************************************************/
@@ -1320,14 +1333,14 @@ GDALDefaultRasterAttributeTable::GetValueAsString( int iRow, int iField ) const
     {
       case GFT_Integer:
       {
-          ((GDALDefaultRasterAttributeTable *) this)->
+          const_cast<GDALDefaultRasterAttributeTable *>(this)->
               osWorkingResult.Printf( "%d", aoFields[iField].anValues[iRow] );
           return osWorkingResult;
       }
 
       case GFT_Real:
       {
-          ((GDALDefaultRasterAttributeTable *) this)->
+          const_cast<GDALDefaultRasterAttributeTable *>(this)->
              osWorkingResult.Printf( "%.16g", aoFields[iField].adfValues[iRow]);
           return osWorkingResult;
       }
@@ -1347,22 +1360,24 @@ GDALDefaultRasterAttributeTable::GetValueAsString( int iRow, int iField ) const
 /**
  * \brief Fetch field value as a string.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::GetValueAsString()
+ * This function is the same as the C++ method
+ * GDALRasterAttributeTable::GetValueAsString()
  */
-const char * CPL_STDCALL 
+const char * CPL_STDCALL
 GDALRATGetValueAsString( GDALRasterAttributeTableH hRAT, int iRow, int iField )
 
 {
     VALIDATE_POINTER1( hRAT, "GDALRATGetValueAsString", NULL );
 
-    return ((GDALRasterAttributeTable *) hRAT)->GetValueAsString(iRow, iField);
+    return static_cast<GDALRasterAttributeTable *>(hRAT)->
+        GetValueAsString(iRow, iField);
 }
 
 /************************************************************************/
 /*                           GetValueAsInt()                            */
 /************************************************************************/
 
-int 
+int
 GDALDefaultRasterAttributeTable::GetValueAsInt( int iRow, int iField ) const
 
 {
@@ -1388,7 +1403,7 @@ GDALDefaultRasterAttributeTable::GetValueAsInt( int iRow, int iField ) const
         return aoFields[iField].anValues[iRow];
 
       case GFT_Real:
-        return (int)  aoFields[iField].adfValues[iRow];
+        return static_cast<int>( aoFields[iField].adfValues[iRow] );
 
       case GFT_String:
         return atoi( aoFields[iField].aosValues[iRow].c_str() );
@@ -1404,15 +1419,17 @@ GDALDefaultRasterAttributeTable::GetValueAsInt( int iRow, int iField ) const
 /**
  * \brief Fetch field value as a integer.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::GetValueAsInt()
+ * This function is the same as the C++ method
+ * GDALRasterAttributeTable::GetValueAsInt()
  */
-int CPL_STDCALL 
+int CPL_STDCALL
 GDALRATGetValueAsInt( GDALRasterAttributeTableH hRAT, int iRow, int iField )
 
 {
     VALIDATE_POINTER1( hRAT, "GDALRATGetValueAsInt", 0 );
 
-    return ((GDALRasterAttributeTable *) hRAT)->GetValueAsInt( iRow, iField );
+    return static_cast<GDALRasterAttributeTable *>(hRAT)->
+        GetValueAsInt( iRow, iField );
 }
 
 /************************************************************************/
@@ -1461,15 +1478,17 @@ GDALDefaultRasterAttributeTable::GetValueAsDouble( int iRow, int iField ) const
 /**
  * \brief Fetch field value as a double.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::GetValueAsDouble()
+ * This function is the same as the C++ method
+ * GDALRasterAttributeTable::GetValueAsDouble()
  */
-double CPL_STDCALL 
+double CPL_STDCALL
 GDALRATGetValueAsDouble( GDALRasterAttributeTableH hRAT, int iRow, int iField )
 
 {
     VALIDATE_POINTER1( hRAT, "GDALRATGetValueAsDouble", 0 );
 
-    return ((GDALRasterAttributeTable *) hRAT)->GetValueAsDouble(iRow,iField);
+    return static_cast<GDALRasterAttributeTable *>(hRAT)->
+        GetValueAsDouble(iRow,iField);
 }
 
 /************************************************************************/
@@ -1482,8 +1501,7 @@ void GDALDefaultRasterAttributeTable::SetRowCount( int nNewCount )
     if( nNewCount == nRowCount )
         return;
 
-    unsigned int iField;
-    for( iField = 0; iField < aoFields.size(); iField++ )
+    for( unsigned int iField = 0; iField < aoFields.size(); iField++ )
     {
         switch( aoFields[iField].eType )
         {
@@ -1508,8 +1526,8 @@ void GDALDefaultRasterAttributeTable::SetRowCount( int nNewCount )
 /*                              SetValue()                              */
 /************************************************************************/
 
-void GDALDefaultRasterAttributeTable::SetValue( int iRow, int iField, 
-                                         const char *pszValue )
+void GDALDefaultRasterAttributeTable::SetValue( int iRow, int iField,
+                                                const char *pszValue )
 
 {
     if( iField < 0 || iField >= (int) aoFields.size() )
@@ -1521,8 +1539,8 @@ void GDALDefaultRasterAttributeTable::SetValue( int iRow, int iField,
     }
 
     if( iRow == nRowCount )
-        SetRowCount( nRowCount+1 );
-    
+        SetRowCount( nRowCount + 1 );
+
     if( iRow < 0 || iRow >= nRowCount )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -1536,11 +1554,11 @@ void GDALDefaultRasterAttributeTable::SetValue( int iRow, int iField,
       case GFT_Integer:
         aoFields[iField].anValues[iRow] = atoi(pszValue);
         break;
-        
+
       case GFT_Real:
         aoFields[iField].adfValues[iRow] = CPLAtof(pszValue);
         break;
-        
+
       case GFT_String:
         aoFields[iField].aosValues[iRow] = pszValue;
         break;
@@ -1554,27 +1572,29 @@ void GDALDefaultRasterAttributeTable::SetValue( int iRow, int iField,
 /**
  * \brief Set field value from string.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::SetValue()
+ * This function is the same as the C++ method
+ * GDALRasterAttributeTable::SetValue()
  */
-void CPL_STDCALL 
+void CPL_STDCALL
 GDALRATSetValueAsString( GDALRasterAttributeTableH hRAT, int iRow, int iField,
                          const char *pszValue )
 
 {
     VALIDATE_POINTER0( hRAT, "GDALRATSetValueAsString" );
 
-    ((GDALRasterAttributeTable *) hRAT)->SetValue( iRow, iField, pszValue );
+    static_cast<GDALRasterAttributeTable *>(hRAT)->
+        SetValue( iRow, iField, pszValue );
 }
 
 /************************************************************************/
 /*                              SetValue()                              */
 /************************************************************************/
 
-void GDALDefaultRasterAttributeTable::SetValue( int iRow, int iField, 
-                                         int nValue )
+void GDALDefaultRasterAttributeTable::SetValue( int iRow, int iField,
+                                                int nValue )
 
 {
-    if( iField < 0 || iField >= (int) aoFields.size() )
+    if( iField < 0 || iField >= static_cast<int>( aoFields.size() ) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "iField (%d) out of range.", iField );
@@ -1584,7 +1604,7 @@ void GDALDefaultRasterAttributeTable::SetValue( int iRow, int iField,
 
     if( iRow == nRowCount )
         SetRowCount( nRowCount+1 );
-    
+
     if( iRow < 0 || iRow >= nRowCount )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -1598,16 +1618,16 @@ void GDALDefaultRasterAttributeTable::SetValue( int iRow, int iField,
       case GFT_Integer:
         aoFields[iField].anValues[iRow] = nValue;
         break;
-        
+
       case GFT_Real:
         aoFields[iField].adfValues[iRow] = nValue;
         break;
-        
+
       case GFT_String:
       {
           char szValue[100];
 
-          sprintf( szValue, "%d", nValue );
+          snprintf( szValue, sizeof(szValue), "%d", nValue );
           aoFields[iField].aosValues[iRow] = szValue;
       }
       break;
@@ -1621,24 +1641,26 @@ void GDALDefaultRasterAttributeTable::SetValue( int iRow, int iField,
 /**
  * \brief Set field value from integer.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::SetValue()
+ * This function is the same as the C++ method
+ * GDALRasterAttributeTable::SetValue()
  */
-void CPL_STDCALL 
+void CPL_STDCALL
 GDALRATSetValueAsInt( GDALRasterAttributeTableH hRAT, int iRow, int iField,
                       int nValue )
 
 {
     VALIDATE_POINTER0( hRAT, "GDALRATSetValueAsInt" );
 
-    ((GDALRasterAttributeTable *) hRAT)->SetValue( iRow, iField, nValue);
+    static_cast<GDALRasterAttributeTable *>(hRAT)->
+        SetValue( iRow, iField, nValue);
 }
 
 /************************************************************************/
 /*                              SetValue()                              */
 /************************************************************************/
 
-void GDALDefaultRasterAttributeTable::SetValue( int iRow, int iField, 
-                                         double dfValue )
+void GDALDefaultRasterAttributeTable::SetValue( int iRow, int iField,
+                                                double dfValue )
 
 {
     if( iField < 0 || iField >= (int) aoFields.size() )
@@ -1651,7 +1673,7 @@ void GDALDefaultRasterAttributeTable::SetValue( int iRow, int iField,
 
     if( iRow == nRowCount )
         SetRowCount( nRowCount+1 );
-    
+
     if( iRow < 0 || iRow >= nRowCount )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -1665,16 +1687,16 @@ void GDALDefaultRasterAttributeTable::SetValue( int iRow, int iField,
       case GFT_Integer:
         aoFields[iField].anValues[iRow] = (int) dfValue;
         break;
-        
+
       case GFT_Real:
         aoFields[iField].adfValues[iRow] = dfValue;
         break;
-        
+
       case GFT_String:
       {
-          char szValue[100];
+          char szValue[100] = { '\0' };
 
-          CPLsprintf( szValue, "%.15g", dfValue );
+          CPLsnprintf( szValue, sizeof(szValue), "%.15g", dfValue );
           aoFields[iField].aosValues[iRow] = szValue;
       }
       break;
@@ -1688,16 +1710,18 @@ void GDALDefaultRasterAttributeTable::SetValue( int iRow, int iField,
 /**
  * \brief Set field value from double.
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::SetValue()
+ * This function is the same as the C++ method
+ * GDALRasterAttributeTable::SetValue()
  */
-void CPL_STDCALL 
+void CPL_STDCALL
 GDALRATSetValueAsDouble( GDALRasterAttributeTableH hRAT, int iRow, int iField,
                          double dfValue )
 
 {
     VALIDATE_POINTER0( hRAT, "GDALRATSetValueAsDouble" );
 
-    ((GDALRasterAttributeTable *) hRAT)->SetValue( iRow, iField, dfValue );
+    static_cast<GDALRasterAttributeTable *>(hRAT)->
+        SetValue( iRow, iField, dfValue );
 }
 
 /************************************************************************/
@@ -1706,7 +1730,7 @@ GDALRATSetValueAsDouble( GDALRasterAttributeTableH hRAT, int iRow, int iField,
 
 int GDALDefaultRasterAttributeTable::ChangesAreWrittenToFile()
 {
-    // GDALRasterBand.SetDefaultRAT needs to be called on instances of 
+    // GDALRasterBand.SetDefaultRAT needs to be called on instances of
     // GDALDefaultRasterAttributeTable since changes are just in-memory
     return FALSE;
 }
@@ -1716,16 +1740,19 @@ int GDALDefaultRasterAttributeTable::ChangesAreWrittenToFile()
 /************************************************************************/
 
 /**
- * \brief Determine whether changes made to this RAT are reflected directly in the dataset
+ * \brief Determine whether changes made to this RAT are reflected directly in
+ * the dataset
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::ChangesAreWrittenToFile()
+ * This function is the same as the C++ method
+ * GDALRasterAttributeTable::ChangesAreWrittenToFile()
  */
 int CPL_STDCALL
 GDALRATChangesAreWrittenToFile( GDALRasterAttributeTableH hRAT )
 {
     VALIDATE_POINTER1( hRAT, "GDALRATChangesAreWrittenToFile", FALSE );
 
-    return ((GDALRasterAttributeTable *) hRAT)->ChangesAreWrittenToFile();
+    return static_cast<GDALRasterAttributeTable *>(hRAT)->
+        ChangesAreWrittenToFile();
 }
 
 /************************************************************************/
@@ -1740,46 +1767,45 @@ int GDALDefaultRasterAttributeTable::GetRowOfValue( double dfValue ) const
 /* -------------------------------------------------------------------- */
     if( bLinearBinning )
     {
-        int iBin = (int) floor((dfValue - dfRow0Min) / dfBinSize);
+        const int iBin = static_cast<int>(
+            floor((dfValue - dfRow0Min) / dfBinSize) );
         if( iBin < 0 || iBin >= nRowCount )
             return -1;
-        else
-            return iBin;
+
+        return iBin;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Do we have any information?                                     */
 /* -------------------------------------------------------------------- */
-    const GDALRasterAttributeField *poMin, *poMax;
-
     if( !bColumnsAnalysed )
-        ((GDALDefaultRasterAttributeTable *) this)->AnalyseColumns();
+        const_cast<GDALDefaultRasterAttributeTable *>(this)->AnalyseColumns();
 
     if( nMinCol == -1 && nMaxCol == -1 )
         return -1;
 
+    const GDALRasterAttributeField *poMin = NULL;
     if( nMinCol != -1 )
         poMin = &(aoFields[nMinCol]);
     else
         poMin = NULL;
-    
+
+    const GDALRasterAttributeField *poMax = NULL;
     if( nMaxCol != -1 )
         poMax = &(aoFields[nMaxCol]);
     else
         poMax = NULL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Search through rows for match.                                  */
 /* -------------------------------------------------------------------- */
-    int   iRow;
-
-    for( iRow = 0; iRow < nRowCount; iRow++ )
+    for( int iRow = 0; iRow < nRowCount; iRow++ )
     {
         if( poMin != NULL )
         {
             if( poMin->eType == GFT_Integer )
             {
-                while( iRow < nRowCount && dfValue < poMin->anValues[iRow] ) 
+                while( iRow < nRowCount && dfValue < poMin->anValues[iRow] )
                     iRow++;
             }
             else if( poMin->eType == GFT_Real )
@@ -1794,10 +1820,10 @@ int GDALDefaultRasterAttributeTable::GetRowOfValue( double dfValue ) const
 
         if( poMax != NULL )
         {
-            if( (poMax->eType == GFT_Integer 
-                 && dfValue > poMax->anValues[iRow] ) 
-                || (poMax->eType == GFT_Real 
-                    && dfValue > poMax->adfValues[iRow] ) )
+            if( (poMax->eType == GFT_Integer
+                 && dfValue > poMax->anValues[iRow] ) ||
+                (poMax->eType == GFT_Real
+                 && dfValue > poMax->adfValues[iRow] ) )
                 continue;
         }
 
@@ -1817,15 +1843,15 @@ int GDALDefaultRasterAttributeTable::GetRowOfValue( double dfValue ) const
 int GDALDefaultRasterAttributeTable::GetRowOfValue( int nValue ) const
 
 {
-    return GetRowOfValue( (double) nValue );
+    return GetRowOfValue( static_cast<double>( nValue ) );
 }
 
 /************************************************************************/
 /*                          SetLinearBinning()                          */
 /************************************************************************/
 
-CPLErr GDALDefaultRasterAttributeTable::SetLinearBinning( double dfRow0MinIn, 
-                                                   double dfBinSizeIn )
+CPLErr GDALDefaultRasterAttributeTable::SetLinearBinning( double dfRow0MinIn,
+                                                          double dfBinSizeIn )
 
 {
     bLinearBinning = TRUE;
@@ -1839,8 +1865,8 @@ CPLErr GDALDefaultRasterAttributeTable::SetLinearBinning( double dfRow0MinIn,
 /*                          GetLinearBinning()                          */
 /************************************************************************/
 
-int GDALDefaultRasterAttributeTable::GetLinearBinning( double *pdfRow0Min,
-                                                double *pdfBinSize ) const
+int GDALDefaultRasterAttributeTable::GetLinearBinning(
+    double *pdfRow0Min, double *pdfBinSize ) const
 
 {
     if( !bLinearBinning )
@@ -1856,19 +1882,19 @@ int GDALDefaultRasterAttributeTable::GetLinearBinning( double *pdfRow0Min,
 /*                            CreateColumn()                            */
 /************************************************************************/
 
-CPLErr GDALDefaultRasterAttributeTable::CreateColumn( const char *pszFieldName, 
+CPLErr GDALDefaultRasterAttributeTable::CreateColumn( const char *pszFieldName,
                                                GDALRATFieldType eFieldType,
                                                GDALRATFieldUsage eFieldUsage )
 
 {
-    int iNewField = aoFields.size();
+    const size_t iNewField = aoFields.size();
 
     aoFields.resize( iNewField+1 );
 
     aoFields[iNewField].sName = pszFieldName;
 
-    // color columns should be int 0..255 
-    if( ( eFieldUsage == GFU_Red ) || ( eFieldUsage == GFU_Green ) || 
+    // color columns should be int 0..255
+    if( ( eFieldUsage == GFU_Red ) || ( eFieldUsage == GFU_Green ) ||
         ( eFieldUsage == GFU_Blue ) || ( eFieldUsage == GFU_Alpha ) )
     {
         eFieldType = GFT_Integer;
@@ -1905,13 +1931,13 @@ GDALDefaultRasterAttributeTable *GDALDefaultRasterAttributeTable::Clone() const
  *
  * This function is the same as the C++ method GDALRasterAttributeTable::Clone()
  */
-GDALRasterAttributeTableH CPL_STDCALL 
+GDALRasterAttributeTableH CPL_STDCALL
 GDALRATClone( GDALRasterAttributeTableH hRAT )
 
 {
     VALIDATE_POINTER1( hRAT, "GDALRATClone", NULL );
 
-    return ((GDALRasterAttributeTable *) hRAT)->Clone();
+    return static_cast<GDALRasterAttributeTable *>(hRAT)->Clone();
 }
 
 /************************************************************************/
@@ -1921,13 +1947,14 @@ GDALRATClone( GDALRasterAttributeTableH hRAT )
 /**
  * \brief Serialize Raster Attribute Table in Json format
  *
- * This function is the same as the C++ method GDALRasterAttributeTable::SerializeJSON()
+ * This function is the same as the C++ method
+ * GDALRasterAttributeTable::SerializeJSON()
  */
-void* CPL_STDCALL 
+void* CPL_STDCALL
 GDALRATSerializeJSON( GDALRasterAttributeTableH hRAT )
 
 {
     VALIDATE_POINTER1( hRAT, "GDALRATSerializeJSON", NULL );
 
-    return ((GDALRasterAttributeTable *) hRAT)->SerializeJSON();
+    return static_cast<GDALRasterAttributeTable *>(hRAT)->SerializeJSON();
 }
diff --git a/gcore/gdal_rat.h b/gcore/gdal_rat.h
index a70445d..4a7a4f3 100644
--- a/gcore/gdal_rat.h
+++ b/gcore/gdal_rat.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_rat.h 29243 2015-05-24 15:53:26Z rouault $
+ * $Id: gdal_rat.h 33773 2016-03-23 18:39:47Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  GDALRasterAttributeTable class declarations.
@@ -32,8 +32,8 @@
 
 #include "cpl_minixml.h"
 
-// Clone and Serialize are allowed to fail if GetRowCount()*GetColCount() greater
-// than this number
+// Clone and Serialize are allowed to fail if GetRowCount()*GetColCount()
+// greater than this number
 #define RAT_MAX_ELEM_FOR_CLONE  1000000
 
 /************************************************************************/
@@ -43,7 +43,7 @@
 //! Raster Attribute Table interface.
 class GDALDefaultRasterAttributeTable;
 
-class CPL_DLL GDALRasterAttributeTable 
+class CPL_DLL GDALRasterAttributeTable
 {
 public:
     virtual ~GDALRasterAttributeTable();
@@ -60,7 +60,7 @@ public:
      * @return new copy of the RAT as an in-memory implementation.
      */
     virtual GDALDefaultRasterAttributeTable *Clone() const = 0;
-    
+
     /**
      * \brief Fetch table column count.
      *
@@ -75,14 +75,14 @@ public:
      *
      * This method is the same as the C function GDALRATGetNameOfCol().
      *
-     * @param iCol the column index (zero based). 
+     * @param iCol the column index (zero based).
      *
      * @return the column name or an empty string for invalid column numbers.
      */
     virtual const char   *GetNameOfCol( int ) const = 0;
 
     /**
-     * \brief Fetch column usage value. 
+     * \brief Fetch column usage value.
      *
      * This method is the same as the C function GDALRATGetUsageOfCol().
      *
@@ -102,27 +102,27 @@ public:
      * @return column type or GFT_Integer if the column index is illegal.
      */
     virtual GDALRATFieldType GetTypeOfCol( int ) const = 0;
-    
+
     /**
      * \brief Fetch column index for given usage.
      *
-     * Returns the index of the first column of the requested usage type, or -1 
-     * if no match is found. 
+     * Returns the index of the first column of the requested usage type, or -1
+     * if no match is found.
      *
      * This method is the same as the C function GDALRATGetUsageOfCol().
      *
      * @param eUsage usage type to search for.
      *
-     * @return column index, or -1 on failure. 
+     * @return column index, or -1 on failure.
      */
     virtual int           GetColOfUsage( GDALRATFieldUsage ) const = 0;
 
     /**
      * \brief Fetch row count.
-     * 
+     *
      * This method is the same as the C function GDALRATGetRowCount().
      *
-     * @return the number of rows. 
+     * @return the number of rows.
      */
     virtual int           GetRowCount() const = 0;
 
@@ -135,13 +135,13 @@ public:
      *
      * The returned string is temporary and cannot be expected to be
      * available after the next GDAL call.
-     * 
+     *
      * This method is the same as the C function GDALRATGetValueAsString().
      *
      * @param iRow row to fetch (zero based).
      * @param iField column to fetch (zero based).
-     * 
-     * @return field value. 
+     *
+     * @return field value.
      */
     virtual const char   *GetValueAsString( int iRow, int iField ) const = 0;
 
@@ -156,7 +156,7 @@ public:
      *
      * @param iRow row to fetch (zero based).
      * @param iField column to fetch (zero based).
-     * 
+     *
      * @return field value
      */
     virtual int           GetValueAsInt( int iRow, int iField ) const = 0;
@@ -167,12 +167,12 @@ public:
      * The value of the requested column in the requested row is returned
      * as a double.   Non double fields will be converted to double with
      * the possibility of data loss.
-     * 
+     *
      * This method is the same as the C function GDALRATGetValueAsDouble().
      *
      * @param iRow row to fetch (zero based).
      * @param iField column to fetch (zero based).
-     * 
+     *
      * @return field value
      */
     virtual double        GetValueAsDouble( int iRow, int iField ) const = 0;
@@ -190,7 +190,8 @@ public:
      * @param iField column to fetch (zero based).
      * @param pszValue the value to assign.
      */
-    virtual void          SetValue( int iRow, int iField, const char *pszValue ) = 0;
+    virtual void          SetValue( int iRow, int iField,
+                                    const char *pszValue ) = 0;
 
     /**
      * \brief Set field value from integer.
@@ -223,33 +224,43 @@ public:
     virtual void          SetValue( int iRow, int iField, double dfValue) = 0;
 
     /**
-     * \brief Determine whether changes made to this RAT are reflected directly in the dataset
-     * 
-     * If this returns FALSE then GDALRasterBand.SetDefaultRAT() should be called. Otherwise
-     * this is unnecessary since changes to this object are reflected in the dataset.
+     * \brief Determine whether changes made to this RAT are reflected directly
+     * in the dataset
      *
-     * This method is the same as the C function GDALRATChangesAreWrittenToFile().
+     * If this returns FALSE then GDALRasterBand.SetDefaultRAT() should be
+     * called. Otherwise this is unnecessary since changes to this object are
+     * reflected in the dataset.
+     *
+     * This method is the same as the C function
+     * GDALRATChangesAreWrittenToFile().
      *
      */
     virtual int           ChangesAreWrittenToFile() = 0;
 
-    virtual CPLErr        ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, double *pdfData);
-    virtual CPLErr        ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, int *pnData);
-    virtual CPLErr        ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, char **papszStrList);
+    virtual CPLErr        ValuesIO( GDALRWFlag eRWFlag, int iField,
+                                    int iStartRow, int iLength,
+                                    double *pdfData);
+    virtual CPLErr        ValuesIO( GDALRWFlag eRWFlag, int iField,
+                                    int iStartRow, int iLength, int *pnData);
+    virtual CPLErr        ValuesIO( GDALRWFlag eRWFlag, int iField,
+                                    int iStartRow, int iLength,
+                                    char **papszStrList);
 
     virtual void          SetRowCount( int iCount );
     virtual int           GetRowOfValue( double dfValue ) const;
     virtual int           GetRowOfValue( int nValue ) const;
 
-    virtual CPLErr        CreateColumn( const char *pszFieldName, 
-                                GDALRATFieldType eFieldType, 
-                                GDALRATFieldUsage eFieldUsage );
-    virtual CPLErr        SetLinearBinning( double dfRow0Min, double dfBinSize );
-    virtual int           GetLinearBinning( double *pdfRow0Min, double *pdfBinSize ) const;
+    virtual CPLErr        CreateColumn( const char *pszFieldName,
+                                        GDALRATFieldType eFieldType,
+                                        GDALRATFieldUsage eFieldUsage );
+    virtual CPLErr        SetLinearBinning( double dfRow0Min,
+                                            double dfBinSize );
+    virtual int           GetLinearBinning( double *pdfRow0Min,
+                                            double *pdfBinSize ) const;
 
     /**
      * \brief Serialize
-     * 
+     *
      * May fail (return NULL) if the attribute table is too large to serialize
      * (GetRowCount() * GetColCount() > RAT_MAX_ELEM_FOR_CLONE)
      */
@@ -259,7 +270,7 @@ public:
 
     virtual CPLErr        InitializeFromColorTable( const GDALColorTable * );
     virtual GDALColorTable *TranslateToColorTable( int nEntryCount = -1 );
-    
+
     virtual void          DumpReadable( FILE * = NULL );
 };
 
@@ -271,7 +282,7 @@ public:
 
 class GDALRasterAttributeField
 {
-public:
+ public:
     CPLString         sName;
 
     GDALRATFieldType  eType;
@@ -291,15 +302,15 @@ public:
 
 class CPL_DLL GDALDefaultRasterAttributeTable : public GDALRasterAttributeTable
 {
-private:
+ private:
     std::vector<GDALRasterAttributeField> aoFields;
 
-    int bLinearBinning;
+    int bLinearBinning;  // TODO(schwehr): Can this be a bool?
     double dfRow0Min;
     double dfBinSize;
 
     void  AnalyseColumns();
-    int   bColumnsAnalysed;
+    int   bColumnsAnalysed;  // TODO(schwehr): Can this be a bool?
     int   nMinCol;
     int   nMaxCol;
 
@@ -307,19 +318,19 @@ private:
 
     CPLString osWorkingResult;
 
-public:
+ public:
     GDALDefaultRasterAttributeTable();
-    GDALDefaultRasterAttributeTable(const GDALDefaultRasterAttributeTable&);
+    GDALDefaultRasterAttributeTable( const GDALDefaultRasterAttributeTable& );
     ~GDALDefaultRasterAttributeTable();
 
     GDALDefaultRasterAttributeTable *Clone() const;
-    
+
     virtual int           GetColumnCount() const;
 
     virtual const char   *GetNameOfCol( int ) const;
     virtual GDALRATFieldUsage GetUsageOfCol( int ) const;
     virtual GDALRATFieldType GetTypeOfCol( int ) const;
-    
+
     virtual int           GetColOfUsage( GDALRATFieldUsage ) const;
 
     virtual int           GetRowCount() const;
@@ -328,7 +339,8 @@ public:
     virtual int           GetValueAsInt( int iRow, int iField ) const;
     virtual double        GetValueAsDouble( int iRow, int iField ) const;
 
-    virtual void          SetValue( int iRow, int iField, const char *pszValue );
+    virtual void          SetValue( int iRow, int iField,
+                                    const char *pszValue );
     virtual void          SetValue( int iRow, int iField, double dfValue);
     virtual void          SetValue( int iRow, int iField, int nValue );
 
@@ -338,12 +350,13 @@ public:
     virtual int           GetRowOfValue( double dfValue ) const;
     virtual int           GetRowOfValue( int nValue ) const;
 
-    virtual CPLErr        CreateColumn( const char *pszFieldName, 
-                                GDALRATFieldType eFieldType, 
-                                GDALRATFieldUsage eFieldUsage );
-    virtual CPLErr        SetLinearBinning( double dfRow0Min, double dfBinSize );
-    virtual int           GetLinearBinning( double *pdfRow0Min, double *pdfBinSize ) const;
-
+    virtual CPLErr        CreateColumn( const char *pszFieldName,
+                                        GDALRATFieldType eFieldType,
+                                        GDALRATFieldUsage eFieldUsage );
+    virtual CPLErr        SetLinearBinning( double dfRow0Min,
+                                            double dfBinSize );
+    virtual int           GetLinearBinning( double *pdfRow0Min,
+                                            double *pdfBinSize ) const;
 };
 
 #endif /* ndef GDAL_RAT_H_INCLUDED */
diff --git a/gcore/gdal_version.h b/gcore/gdal_version.h
index 39740b2..2995652 100644
--- a/gcore/gdal_version.h
+++ b/gcore/gdal_version.h
@@ -5,8 +5,8 @@
 
 #ifndef GDAL_VERSION_MAJOR
 #  define GDAL_VERSION_MAJOR    2
-#  define GDAL_VERSION_MINOR    0
-#  define GDAL_VERSION_REV      2
+#  define GDAL_VERSION_MINOR    1
+#  define GDAL_VERSION_REV      0
 #  define GDAL_VERSION_BUILD    0
 #endif
 
@@ -22,8 +22,8 @@
 #endif
 
 #ifndef GDAL_RELEASE_DATE
-#  define GDAL_RELEASE_DATE     20160126
+#  define GDAL_RELEASE_DATE     20160401
 #endif
 #ifndef GDAL_RELEASE_NAME
-#  define GDAL_RELEASE_NAME     "2.0.2"
+#  define GDAL_RELEASE_NAME     "2.1.0beta1"
 #endif
diff --git a/gcore/gdalabstractbandblockcache.cpp b/gcore/gdalabstractbandblockcache.cpp
new file mode 100644
index 0000000..79b23a0
--- /dev/null
+++ b/gcore/gdalabstractbandblockcache.cpp
@@ -0,0 +1,190 @@
+/******************************************************************************
+ * $Id: gdalabstractbandblockcache.cpp 31703 2015-11-21 22:11:38Z rouault $
+ *
+ * Project:  GDAL Core
+ * Purpose:  Store cached blocks
+ * Author:   Even Rouault, <even dot rouault at spatialys dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Even Rouault <even dot rouault at spatialys dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gdal_priv.h"
+#include "cpl_multiproc.h"
+#include <new>
+
+CPL_CVSID("$Id: gdalabstractbandblockcache.cpp 31703 2015-11-21 22:11:38Z rouault $");
+
+#ifdef DEBUG_VERBOSE_ABBC
+static int nAllBandsKeptAlivedBlocks = 0;
+#endif
+
+/************************************************************************/
+/*                       GDALArrayBandBlockCache()                      */
+/************************************************************************/
+
+GDALAbstractBandBlockCache::GDALAbstractBandBlockCache(GDALRasterBand* poBandIn) :
+    hSpinLock(CPLCreateLock(LOCK_SPIN)),
+    psListBlocksToFree(NULL),
+    hCond(CPLCreateCond()),
+    hCondMutex(CPLCreateMutex()),
+    nKeepAliveCounter(0)
+{
+    poBand = poBandIn;
+    if( hCondMutex )
+        CPLReleaseMutex(hCondMutex);
+}
+
+/************************************************************************/
+/*                      ~GDALAbstractBandBlockCache()                   */
+/************************************************************************/
+
+GDALAbstractBandBlockCache::~GDALAbstractBandBlockCache()
+{
+    CPLAssert(nKeepAliveCounter == 0);
+    FreeDanglingBlocks();
+    if( hSpinLock )
+        CPLDestroyLock(hSpinLock);
+    if( hCondMutex )
+        CPLDestroyMutex(hCondMutex);
+    if( hCond )
+        CPLDestroyCond(hCond);
+}
+
+/************************************************************************/
+/*                            UnreferenceBlockBase()                    */
+/*                                                                      */
+/*      This is called by GDALRasterBlock::Internalize() and            */
+/*      FlushCacheBlock() when they remove a block from the linked list */
+/*      but haven't yet flushed it to disk or recovered its pData member*/
+/*      We must be aware that they are blocks in that state, since the  */
+/*      band must be kept alive while AddBlockToFreeList() hasn't been  */
+/*      called (in case a block is being flushed while the final        */
+/*      FlushCache() of the main thread of the dataset is running).     */
+/************************************************************************/
+
+void GDALAbstractBandBlockCache::UnreferenceBlockBase()
+{
+    CPLAtomicInc(&nKeepAliveCounter);
+}
+
+/************************************************************************/
+/*                          AddBlockToFreeList()                        */
+/*                                                                      */
+/*      This is called by GDALRasterBlock::Internalize() and            */
+/*      FlushCacheBlock() after they have been finished with a block.   */
+/************************************************************************/
+
+void GDALAbstractBandBlockCache::AddBlockToFreeList( GDALRasterBlock *poBlock )
+{
+    CPLAssert(poBlock->poPrevious == NULL);
+    CPLAssert(poBlock->poNext == NULL);
+    {
+#ifdef DEBUG_VERBOSE_ABBC
+        CPLAtomicInc(&nAllBandsKeptAlivedBlocks);
+        fprintf(stderr, "AddBlockToFreeList(): nAllBandsKeptAlivedBlocks=%d\n", nAllBandsKeptAlivedBlocks);
+#endif
+        CPLLockHolderOptionalLockD(hSpinLock);
+        poBlock->poNext = psListBlocksToFree;
+        psListBlocksToFree = poBlock;
+    }
+
+    // If no more blocks in transient state, then warn WaitKeepAliveCounter()
+    if( CPLAtomicDec(&nKeepAliveCounter) == 0 )
+    {
+        CPLAcquireMutex(hCondMutex, 1000);
+        CPLCondSignal(hCond);
+        CPLReleaseMutex(hCondMutex);
+    }
+}
+
+/************************************************************************/
+/*                         WaitKeepAliveCounter()                       */
+/************************************************************************/
+
+void GDALAbstractBandBlockCache::WaitKeepAliveCounter()
+{
+#ifdef DEBUG_VERBOSE
+    CPLDebug("GDAL", "WaitKeepAliveCounter()");
+#endif
+
+    CPLAcquireMutex(hCondMutex, 1000);
+    while( nKeepAliveCounter != 0 )
+    {
+        CPLDebug( "GDAL", "Waiting for other thread to finish working with our "
+                  "blocks" );
+        CPLCondWait(hCond, hCondMutex);
+    }
+    CPLReleaseMutex(hCondMutex);
+}
+
+/************************************************************************/
+/*                           FreeDanglingBlocks()                       */
+/************************************************************************/
+
+void GDALAbstractBandBlockCache::FreeDanglingBlocks()
+{
+    GDALRasterBlock* poList;
+    {
+        CPLLockHolderOptionalLockD(hSpinLock);
+        poList = psListBlocksToFree;
+        psListBlocksToFree = NULL;
+    }
+    while( poList )
+    {
+#ifdef DEBUG_VERBOSE_ABBC
+        CPLAtomicDec(&nAllBandsKeptAlivedBlocks);
+        fprintf(stderr, "FreeDanglingBlocks(): nAllBandsKeptAlivedBlocks=%d\n", nAllBandsKeptAlivedBlocks);
+#endif
+        GDALRasterBlock* poNext = poList->poNext;
+        poList->poNext = NULL;
+        delete poList;
+        poList = poNext;
+    }
+}
+
+/************************************************************************/
+/*                            CreateBlock()                             */
+/************************************************************************/
+
+GDALRasterBlock* GDALAbstractBandBlockCache::CreateBlock(int nXBlockOff,
+                                                         int nYBlockOff)
+{
+    GDALRasterBlock* poBlock;
+    {
+        CPLLockHolderOptionalLockD(hSpinLock);
+        poBlock = psListBlocksToFree;
+        if( poBlock )
+        {
+#ifdef DEBUG_VERBOSE_ABBC
+            CPLAtomicDec(&nAllBandsKeptAlivedBlocks);
+            fprintf(stderr, "CreateBlock(): nAllBandsKeptAlivedBlocks=%d\n", nAllBandsKeptAlivedBlocks);
+#endif
+            psListBlocksToFree = poBlock->poNext;
+        }
+    }
+    if( poBlock )
+        poBlock->RecycleFor(nXBlockOff, nYBlockOff);
+    else
+        poBlock = new (std::nothrow) GDALRasterBlock(
+            poBand, nXBlockOff, nYBlockOff );
+    return poBlock;
+}
diff --git a/gcore/gdalallvalidmaskband.cpp b/gcore/gdalallvalidmaskband.cpp
index b5ab48f..b4f7f75 100644
--- a/gcore/gdalallvalidmaskband.cpp
+++ b/gcore/gdalallvalidmaskband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalallvalidmaskband.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: gdalallvalidmaskband.cpp 31440 2015-11-12 01:38:25Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALAllValidMaskBand, a class implementing all
@@ -30,14 +30,14 @@
 
 #include "gdal_priv.h"
 
-CPL_CVSID("$Id: gdalallvalidmaskband.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: gdalallvalidmaskband.cpp 31440 2015-11-12 01:38:25Z goatbar $");
 
 /************************************************************************/
 /*                        GDALAllValidMaskBand()                        */
 /************************************************************************/
 
-GDALAllValidMaskBand::GDALAllValidMaskBand( GDALRasterBand *poParent )
-
+GDALAllValidMaskBand::GDALAllValidMaskBand( GDALRasterBand *poParent ) :
+    GDALRasterBand(FALSE)
 {
     poDS = NULL;
     nBand = 0;
@@ -53,18 +53,15 @@ GDALAllValidMaskBand::GDALAllValidMaskBand( GDALRasterBand *poParent )
 /*                       ~GDALAllValidMaskBand()                        */
 /************************************************************************/
 
-GDALAllValidMaskBand::~GDALAllValidMaskBand()
-
-{
-}
+GDALAllValidMaskBand::~GDALAllValidMaskBand() {}
 
 /************************************************************************/
 /*                             IReadBlock()                             */
 /************************************************************************/
 
-CPLErr GDALAllValidMaskBand::IReadBlock( CPL_UNUSED int nXBlockOff,
-                                         CPL_UNUSED int nYBlockOff,
-                                         void * pImage )
+CPLErr GDALAllValidMaskBand::IReadBlock( int /* nXBlockOff */,
+                                         int /* nYBlockOff */,
+                                         void *pImage )
 {
     memset( pImage, 255, nBlockXSize * nBlockYSize );
 
diff --git a/gcore/gdalarraybandblockcache.cpp b/gcore/gdalarraybandblockcache.cpp
new file mode 100644
index 0000000..fc83611
--- /dev/null
+++ b/gcore/gdalarraybandblockcache.cpp
@@ -0,0 +1,481 @@
+/******************************************************************************
+ * $Id: gdalarraybandblockcache.cpp 33694 2016-03-10 17:54:30Z goatbar $
+ *
+ * Project:  GDAL Core
+ * Purpose:  Store cached blocks in a array or a two-level array
+ * Author:   Even Rouault, <even dot rouault at spatialys dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 1998, Frank Warmerdam
+ * Copyright (c) 2007-2015, Even Rouault <even dot rouault at spatialys dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gdal_priv.h"
+#include "cpl_multiproc.h"
+#include <new>
+
+static const int SUBBLOCK_SIZE = 64;
+#define TO_SUBBLOCK(x) ((x) >> 6)
+#define WITHIN_SUBBLOCK(x) ((x) & 0x3f)
+
+CPL_CVSID("$Id: gdalarraybandblockcache.cpp 33694 2016-03-10 17:54:30Z goatbar $");
+
+/* ******************************************************************** */
+/*                        GDALArrayBandBlockCache                       */
+/* ******************************************************************** */
+
+class GDALArrayBandBlockCache CPL_FINAL : public GDALAbstractBandBlockCache
+{
+    bool              bSubBlockingActive;
+    int               nSubBlocksPerRow;
+    int               nSubBlocksPerColumn;
+    union
+    {
+        GDALRasterBlock **papoBlocks;
+        GDALRasterBlock ***papapoBlocks;
+    } u;
+
+    public:
+            explicit GDALArrayBandBlockCache(GDALRasterBand* poBand);
+           ~GDALArrayBandBlockCache();
+
+           virtual bool             Init();
+           virtual bool             IsInitOK();
+           virtual CPLErr           FlushCache();
+           virtual CPLErr           AdoptBlock( GDALRasterBlock * );
+           virtual GDALRasterBlock *TryGetLockedBlockRef( int nXBlockOff, int nYBlockYOff );
+           virtual CPLErr           UnreferenceBlock( GDALRasterBlock* poBlock );
+           virtual CPLErr           FlushBlock( int nXBlockOff, int nYBlockOff, int bWriteDirtyBlock );
+};
+
+/************************************************************************/
+/*                     GDALArrayBandBlockCacheCreate()                 */
+/************************************************************************/
+
+GDALAbstractBandBlockCache* GDALArrayBandBlockCacheCreate(GDALRasterBand* poBand)
+{
+    return new (std::nothrow) GDALArrayBandBlockCache(poBand);
+}
+
+/************************************************************************/
+/*                       GDALArrayBandBlockCache()                      */
+/************************************************************************/
+
+GDALArrayBandBlockCache::GDALArrayBandBlockCache(GDALRasterBand* poBandIn) :
+    GDALAbstractBandBlockCache(poBandIn),
+    bSubBlockingActive(false),
+    nSubBlocksPerRow(0),
+    nSubBlocksPerColumn(0)
+{
+    u.papoBlocks = NULL;
+}
+
+/************************************************************************/
+/*                      ~GDALArrayBandBlockCache()                     */
+/************************************************************************/
+
+GDALArrayBandBlockCache::~GDALArrayBandBlockCache()
+{
+    FlushCache();
+
+    if( !bSubBlockingActive )
+        CPLFree( u.papoBlocks );
+    else
+        CPLFree( u.papapoBlocks );
+}
+
+/************************************************************************/
+/*                                  Init()                              */
+/************************************************************************/
+
+bool GDALArrayBandBlockCache::Init()
+{
+    if( poBand->nBlocksPerRow < SUBBLOCK_SIZE/2 )
+    {
+        bSubBlockingActive = false;
+
+        if (poBand->nBlocksPerRow < INT_MAX / poBand->nBlocksPerColumn)
+        {
+            u.papoBlocks = reinterpret_cast<GDALRasterBlock **>(
+                VSICalloc( sizeof(void*),
+                           poBand->nBlocksPerRow * poBand->nBlocksPerColumn ) );
+            if( u.papoBlocks == NULL )
+            {
+                poBand->ReportError( CE_Failure, CPLE_OutOfMemory,
+                                    "Out of memory in InitBlockInfo()." );
+                return false;
+            }
+        }
+        else
+        {
+            poBand->ReportError( CE_Failure, CPLE_NotSupported,
+                                 "Too many blocks : %d x %d",
+                                 poBand->nBlocksPerRow, poBand->nBlocksPerColumn );
+            return false;
+        }
+    }
+    else
+    {
+        bSubBlockingActive = true;
+
+        nSubBlocksPerRow = DIV_ROUND_UP(poBand->nBlocksPerRow, SUBBLOCK_SIZE);
+        nSubBlocksPerColumn = DIV_ROUND_UP(poBand->nBlocksPerColumn, SUBBLOCK_SIZE);
+
+        if (nSubBlocksPerRow < INT_MAX / nSubBlocksPerColumn)
+        {
+            u.papapoBlocks = reinterpret_cast<GDALRasterBlock ***>(
+                VSICalloc( sizeof(void*),
+                           nSubBlocksPerRow * nSubBlocksPerColumn ) );
+            if( u.papapoBlocks == NULL )
+            {
+                poBand->ReportError( CE_Failure, CPLE_OutOfMemory,
+                                    "Out of memory in InitBlockInfo()." );
+                return false;
+            }
+
+        }
+        else
+        {
+            poBand->ReportError( CE_Failure, CPLE_NotSupported,
+                                 "Too many subblocks : %d x %d",
+                                 nSubBlocksPerRow, nSubBlocksPerColumn );
+            return false;
+        }
+    }
+
+    return true;
+}
+
+/************************************************************************/
+/*                             IsInitOK()                               */
+/************************************************************************/
+
+bool GDALArrayBandBlockCache::IsInitOK()
+{
+    return (!bSubBlockingActive) ?
+        u.papoBlocks != NULL : u.papapoBlocks != NULL;
+}
+
+/************************************************************************/
+/*                            AdoptBlock()                              */
+/************************************************************************/
+
+CPLErr GDALArrayBandBlockCache::AdoptBlock( GDALRasterBlock * poBlock )
+
+{
+    const int nXBlockOff = poBlock->GetXOff();
+    const int nYBlockOff = poBlock->GetYOff();
+
+    FreeDanglingBlocks();
+
+/* -------------------------------------------------------------------- */
+/*      Simple case without subblocking.                                */
+/* -------------------------------------------------------------------- */
+
+    if( !bSubBlockingActive )
+    {
+        const int nBlockIndex = nXBlockOff + nYBlockOff * poBand->nBlocksPerRow;
+
+        CPLAssert( u.papoBlocks[nBlockIndex] == NULL );
+        u.papoBlocks[nBlockIndex] = poBlock;
+    }
+    else
+    {
+/* -------------------------------------------------------------------- */
+/*      Identify the subblock in which our target occurs, and create    */
+/*      it if necessary.                                                */
+/* -------------------------------------------------------------------- */
+        const int nSubBlock = TO_SUBBLOCK(nXBlockOff)
+            + TO_SUBBLOCK(nYBlockOff) * nSubBlocksPerRow;
+
+        if( u.papapoBlocks[nSubBlock] == NULL )
+        {
+            const int nSubGridSize =
+                sizeof(GDALRasterBlock*) * SUBBLOCK_SIZE * SUBBLOCK_SIZE;
+
+            u.papapoBlocks[nSubBlock] = reinterpret_cast<GDALRasterBlock **>(
+                VSICalloc(1, nSubGridSize) );
+            if( u.papapoBlocks[nSubBlock] == NULL )
+            {
+                poBand->ReportError( CE_Failure, CPLE_OutOfMemory,
+                        "Out of memory in AdoptBlock()." );
+                return CE_Failure;
+            }
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Check within subblock.                                          */
+/* -------------------------------------------------------------------- */
+        GDALRasterBlock **papoSubBlockGrid = u.papapoBlocks[nSubBlock];
+
+        const int nBlockInSubBlock = WITHIN_SUBBLOCK(nXBlockOff)
+            + WITHIN_SUBBLOCK(nYBlockOff) * SUBBLOCK_SIZE;
+
+        CPLAssert( papoSubBlockGrid[nBlockInSubBlock] == NULL );
+        papoSubBlockGrid[nBlockInSubBlock] = poBlock;
+    }
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                            FlushCache()                              */
+/************************************************************************/
+
+CPLErr GDALArrayBandBlockCache::FlushCache()
+{
+    FreeDanglingBlocks();
+
+    CPLErr eGlobalErr = poBand->eFlushBlockErr;
+
+/* -------------------------------------------------------------------- */
+/*      Flush all blocks in memory ... this case is without subblocking.*/
+/* -------------------------------------------------------------------- */
+    if( !bSubBlockingActive && u.papoBlocks != NULL )
+    {
+        const int nBlocksPerColumn = poBand->nBlocksPerColumn;
+        const int nBlocksPerRow = poBand->nBlocksPerRow;
+        for( int iY = 0; iY < nBlocksPerColumn; iY++ )
+        {
+            for( int iX = 0; iX < nBlocksPerRow; iX++ )
+            {
+                if( u.papoBlocks[iX + iY*nBlocksPerRow] != NULL )
+                {
+                    CPLErr eErr = FlushBlock( iX, iY, eGlobalErr == CE_None );
+
+                    if( eErr != CE_None )
+                        eGlobalErr = eErr;
+                }
+            }
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      With subblocking.  We can short circuit missing subblocks.      */
+/* -------------------------------------------------------------------- */
+    else if( u.papapoBlocks != NULL )
+    {
+        for( int iSBY = 0; iSBY < nSubBlocksPerColumn; iSBY++ )
+        {
+            for( int iSBX = 0; iSBX < nSubBlocksPerRow; iSBX++ )
+            {
+                const int nSubBlock = iSBX + iSBY * nSubBlocksPerRow;
+
+                GDALRasterBlock **papoSubBlockGrid =  u.papapoBlocks[nSubBlock];
+
+                if( papoSubBlockGrid == NULL )
+                    continue;
+
+                for( int iY = 0; iY < SUBBLOCK_SIZE; iY++ )
+                {
+                    for( int iX = 0; iX < SUBBLOCK_SIZE; iX++ )
+                    {
+                        if( papoSubBlockGrid[iX + iY * SUBBLOCK_SIZE] != NULL )
+                        {
+                            CPLErr eErr = FlushBlock( iX + iSBX * SUBBLOCK_SIZE,
+                                                      iY + iSBY * SUBBLOCK_SIZE,
+                                                      eGlobalErr == CE_None );
+                            if( eErr != CE_None )
+                                eGlobalErr = eErr;
+                        }
+                    }
+                }
+
+                // We might as well get rid of this grid chunk since we know
+                // it is now empty.
+                u.papapoBlocks[nSubBlock] = NULL;
+                CPLFree( papoSubBlockGrid );
+            }
+        }
+    }
+
+    WaitKeepAliveCounter();
+
+    return( eGlobalErr );
+}
+
+/************************************************************************/
+/*                        UnreferenceBlock()                            */
+/************************************************************************/
+
+CPLErr GDALArrayBandBlockCache::UnreferenceBlock( GDALRasterBlock* poBlock )
+{
+    const int nXBlockOff = poBlock->GetXOff();
+    const int nYBlockOff = poBlock->GetYOff();
+
+    UnreferenceBlockBase();
+
+/* -------------------------------------------------------------------- */
+/*      Simple case for single level caches.                            */
+/* -------------------------------------------------------------------- */
+    if( !bSubBlockingActive )
+    {
+        const int nBlockIndex = nXBlockOff + nYBlockOff * poBand->nBlocksPerRow;
+
+        u.papoBlocks[nBlockIndex] = NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Identify our subblock.                                          */
+/* -------------------------------------------------------------------- */
+    else
+    {
+        const int nSubBlock = TO_SUBBLOCK(nXBlockOff)
+            + TO_SUBBLOCK(nYBlockOff) * nSubBlocksPerRow;
+
+/* -------------------------------------------------------------------- */
+/*      Check within subblock.                                          */
+/* -------------------------------------------------------------------- */
+        GDALRasterBlock **papoSubBlockGrid = u.papapoBlocks[nSubBlock];
+        if( papoSubBlockGrid == NULL )
+            return CE_None;
+
+        const int nBlockInSubBlock = WITHIN_SUBBLOCK(nXBlockOff)
+            + WITHIN_SUBBLOCK(nYBlockOff) * SUBBLOCK_SIZE;
+
+        papoSubBlockGrid[nBlockInSubBlock] = NULL;
+    }
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                            FlushBlock()                              */
+/************************************************************************/
+
+CPLErr GDALArrayBandBlockCache::FlushBlock( int nXBlockOff, int nYBlockOff,
+                                             int bWriteDirtyBlock )
+
+{
+    GDALRasterBlock *poBlock = NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Simple case for single level caches.                            */
+/* -------------------------------------------------------------------- */
+    if( !bSubBlockingActive )
+    {
+        const int nBlockIndex = nXBlockOff + nYBlockOff * poBand->nBlocksPerRow;
+
+        poBlock = u.papoBlocks[nBlockIndex];
+        u.papoBlocks[nBlockIndex] = NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Identify our subblock.                                          */
+/* -------------------------------------------------------------------- */
+    else
+    {
+        const int nSubBlock = TO_SUBBLOCK(nXBlockOff)
+            + TO_SUBBLOCK(nYBlockOff) * nSubBlocksPerRow;
+
+/* -------------------------------------------------------------------- */
+/*      Check within subblock.                                          */
+/* -------------------------------------------------------------------- */
+        GDALRasterBlock **papoSubBlockGrid = u.papapoBlocks[nSubBlock];
+        if( papoSubBlockGrid == NULL )
+            return CE_None;
+
+        const int nBlockInSubBlock = WITHIN_SUBBLOCK(nXBlockOff)
+            + WITHIN_SUBBLOCK(nYBlockOff) * SUBBLOCK_SIZE;
+
+        poBlock = papoSubBlockGrid[nBlockInSubBlock];
+        papoSubBlockGrid[nBlockInSubBlock] = NULL;
+    }
+
+    if( poBlock == NULL )
+        return CE_None;
+
+    if( !poBlock->DropLockForRemovalFromStorage() )
+        return CE_None;
+
+/* -------------------------------------------------------------------- */
+/*      Is the target block dirty?  If so we need to write it.          */
+/* -------------------------------------------------------------------- */
+    poBlock->Detach();
+
+    CPLErr eErr = CE_None;
+    if( bWriteDirtyBlock && poBlock->GetDirty() )
+        eErr = poBlock->Write();
+
+/* -------------------------------------------------------------------- */
+/*      Deallocate the block;                                           */
+/* -------------------------------------------------------------------- */
+    delete poBlock;
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                        TryGetLockedBlockRef()                        */
+/************************************************************************/
+
+GDALRasterBlock *GDALArrayBandBlockCache::TryGetLockedBlockRef( int nXBlockOff,
+                                                                 int nYBlockOff )
+
+{
+    GDALRasterBlock *poBlock;
+
+/* -------------------------------------------------------------------- */
+/*      Simple case for single level caches.                            */
+/* -------------------------------------------------------------------- */
+    if( !bSubBlockingActive )
+    {
+        const int nBlockIndex = nXBlockOff + nYBlockOff * poBand->nBlocksPerRow;
+
+        while( true )
+        {
+            poBlock = u.papoBlocks[nBlockIndex];
+            if( poBlock == NULL )
+                return NULL;
+            if( poBlock->TakeLock() )
+                break;
+        }
+    }
+    else
+    {
+/* -------------------------------------------------------------------- */
+/*      Identify our subblock.                                          */
+/* -------------------------------------------------------------------- */
+        const int nSubBlock = TO_SUBBLOCK(nXBlockOff)
+            + TO_SUBBLOCK(nYBlockOff) * nSubBlocksPerRow;
+
+/* -------------------------------------------------------------------- */
+/*      Check within subblock.                                          */
+/* -------------------------------------------------------------------- */
+        GDALRasterBlock **papoSubBlockGrid = u.papapoBlocks[nSubBlock];
+        if( papoSubBlockGrid == NULL )
+            return NULL;
+
+        const int nBlockInSubBlock = WITHIN_SUBBLOCK(nXBlockOff)
+            + WITHIN_SUBBLOCK(nYBlockOff) * SUBBLOCK_SIZE;
+
+        while( true )
+        {
+            poBlock = papoSubBlockGrid[nBlockInSubBlock];
+            if( poBlock == NULL )
+                return NULL;
+            if( poBlock->TakeLock() )
+                break;
+        }
+    }
+
+    return poBlock;
+}
diff --git a/gcore/gdalclientserver.cpp b/gcore/gdalclientserver.cpp
index 1026b21..f46b1a5 100644
--- a/gcore/gdalclientserver.cpp
+++ b/gcore/gdalclientserver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalclientserver.cpp 28899 2015-04-14 09:27:00Z rouault $
+ * $Id: gdalclientserver.cpp 33810 2016-03-29 22:18:45Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  GDAL Client/server dataset mechanism.
@@ -40,6 +40,7 @@
   #ifndef HAVE_GETADDRINFO
     #define HAVE_GETADDRINFO 1
   #endif
+  #define CONNECT_LEN(x) static_cast<int>(x)
 #else
   #include <sys/types.h>
   #include <sys/socket.h>
@@ -54,6 +55,11 @@
   #define WSAGetLastError() errno
   #define WSACleanup()
   #define closesocket(s) close(s)
+  #define CONNECT_LEN(x) (x)
+#endif
+
+#ifdef BUFFER_READ
+#include <sys/ioctl.h>
 #endif
 
 #include "gdal_pam.h"
@@ -61,7 +67,7 @@
 #include "cpl_spawn.h"
 #include "cpl_multiproc.h"
 
-/*! 
+/*!
 \page gdal_api_proxy GDAL API Proxy
 
 \section gdal_api_proxy_intro Introduction
@@ -84,7 +90,7 @@ The option can also be set to a list of file extensions that must be the only on
 this mechanism (e.g. GDAL_API_PROXY=ecw,sid).
 
 When enabled, datasets can be handled with GDALOpen(), GDALCreate() or GDALCreateCopy() with
-their nominal filename (or connexion string).
+their nominal filename (or connection string).
 
 Alternatively, the API_PROXY mechanism can be used selectively on a datasource by prefixing its
 name with API_PROXY:, for example GDALOpen("API_PROXY:foo.tif", GA_ReadOnly).
@@ -100,6 +106,9 @@ It is also possible to connect to a gdalserver in TCP, possibly on a remote host
 gdalserver must be launched on a host with "gdalserver -tcpserver the_tcp_port". And the client
 must set GDAL_API_PROXY_SERVER="hostname:the_tcp_port", where hostname is a string or a IP address.
 
+On Unix, gdalserver can also be launched on a Unix socket, which "gdalserver -unixserver /a/filename".
+Clients should then set GDAL_API_PROXY_SERVER to "/a/filename".
+
 In case of many dataset opening or creation, to avoid the cost of repeated process forking,
 a pool of unused connections is established. Each time a dataset is closed, the associated connection
 is pushed in the pool (if there's an empty bucket). When a following dataset is to be opened, one of those
@@ -117,11 +126,24 @@ Additionnaly, for GDALCreate() or GDALCreateCopy(), the VRT driver is also exclu
 Currently, the client dataset returned is not protected by a mutex, so it is unsafe to use it concurrently
 from multiple threads. However, it is safe to use several client datasets from multiple threads.
 
+\section gdal_api_proxy_concurrent Concurrent use of a dataset
+
+Starting with GDAL 2.1 (Unix only), if the gdalserver executable is launched in
+TCP (or Unix socket) mode, and with the -nofork flag, clients that will open the
+same dataset name through the API Proxy will be associated with the same dataset
+object on the server, thus enabling, for example, safe "concurrent" write from
+several clients.
+
+But in that mode, only one thread is used in the server, hence
+reducing scalability and client isolation. Furthermore some operations, like
+"gdal_translate api_proxy:in.tif api_proxy:out.tif" are not possible, since they
+would deadlock the server.
+
 */
 
 /* REMINDER: upgrade this number when the on-wire protocol changes */
 /* Note: please at least keep the version exchange protocol unchanged ! */
-#define GDAL_CLIENT_SERVER_PROTOCOL_MAJOR 2
+#define GDAL_CLIENT_SERVER_PROTOCOL_MAJOR 3
 #define GDAL_CLIENT_SERVER_PROTOCOL_MINOR 0
 
 #include <map>
@@ -131,6 +153,9 @@ CPL_C_START
 int CPL_DLL GDALServerLoop(CPL_FILE_HANDLE fin, CPL_FILE_HANDLE fout);
 const char* GDALClientDatasetGetFilename(const char* pszFilename);
 int CPL_DLL GDALServerLoopSocket(CPL_SOCKET nSocket);
+void CPL_DLL* GDALServerLoopInstanceCreateFromSocket(CPL_SOCKET nSocket);
+int  CPL_DLL  GDALServerLoopInstanceRunIteration(void* pInstance);
+void CPL_DLL  GDALServerLoopInstanceDestroy(void* pInstance);
 CPL_C_END
 
 #define BUFFER_SIZE 1024
@@ -142,6 +167,10 @@ typedef struct
     int             bOK;
     GByte           abyBuffer[BUFFER_SIZE];
     int             nBufferSize;
+#ifdef BUFFER_READ
+    GByte           abyRecvBuffer[BUFFER_SIZE];
+    int             nRecvBufferSize;
+#endif
 } GDALPipe;
 
 typedef struct
@@ -239,12 +268,13 @@ typedef enum
     INSTR_Band_GetDefaultRAT,
     INSTR_Band_SetDefaultRAT,
     INSTR_Band_AdviseRead,
+    INSTR_Band_DeleteNoDataValue,
     INSTR_Band_End,
     INSTR_END
 } InstrEnum;
 
-#ifdef DEBUG
-static const char* apszInstr[] =
+#ifdef DEBUG_VERBOSE
+static const char* const apszInstr[] =
 {
     "INVALID",
     "GetGDALVersion",
@@ -324,6 +354,7 @@ static const char* apszInstr[] =
     "Band_GetDefaultRAT",
     "Band_SetDefaultRAT",
     "Band_AdviseRead",
+    "Band_DeleteNoDataValue",
     "Band_End",
     "END",
 };
@@ -331,7 +362,7 @@ static const char* apszInstr[] =
 
 static const GByte abyEndOfJunkMarker[] = { 0xDE, 0xAD, 0xBE, 0xEF };
 
-/* Recycling of connexions to child processes */
+/* Recycling of connections to child processes */
 #define MAX_RECYCLED        128
 #define DEFAULT_RECYCLED    4
 static int bRecycleChild = FALSE;
@@ -377,7 +408,8 @@ CPL_UNUSED
 #ifdef WIN32
     SetCurrentDirectory(pszCWD);
 #else
-    CPLAssert(chdir(pszCWD) == 0);
+    if(chdir(pszCWD) != 0)
+        fprintf(stderr, "chdir(%s) failed\n", pszCWD);
 #endif
 }
 
@@ -432,7 +464,7 @@ class GDALClientDataset: public GDALPamDataset
        virtual CPLErr IRasterIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
                                void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType, 
+                               GDALDataType eBufType,
                                int nBandCount, int *panBandMap,
                                GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace,
                                GDALRasterIOExtraArg* psExtraArg);
@@ -440,15 +472,16 @@ class GDALClientDataset: public GDALPamDataset
                             GDALClientDataset(GDALPipe* p);
                             ~GDALClientDataset();
 
-        int                 Init(const char* pszFilename, GDALAccess eAccess);
+        int                 Init(const char* pszFilename, GDALAccess eAccess,
+                                 char** papszOpenOptions);
 
-        void                AttachAsyncProgress(GDALServerAsyncProgress* async) { this->async = async; }
+        void                AttachAsyncProgress(GDALServerAsyncProgress* asyncIn) { async = asyncIn; }
         int                 ProcessAsyncProgress();
         int                 SupportsInstr(InstrEnum instr) const { return abyCaps[instr / 8] & (1 << (instr % 8)); }
 
         virtual void        FlushCache();
 
-        virtual CPLErr        AddBand( GDALDataType eType, 
+        virtual CPLErr        AddBand( GDALDataType eType,
                                    char **papszOptions=NULL );
 
         //virtual void        SetDescription( const char * );
@@ -477,8 +510,8 @@ class GDALClientDataset: public GDALPamDataset
         virtual char      **GetFileList(void);
 
         virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
-                                int nBufXSize, int nBufYSize, 
-                                GDALDataType eDT, 
+                                int nBufXSize, int nBufYSize,
+                                GDALDataType eDT,
                                 int nBandCount, int *panBandList,
                                 char **papszOptions );
 
@@ -486,8 +519,8 @@ class GDALClientDataset: public GDALPamDataset
 
         static GDALDataset *Open( GDALOpenInfo * );
         static int          Identify( GDALOpenInfo * );
-        static GDALDataset *CreateCopy( const char * pszFilename, 
-                                        GDALDataset * poSrcDS, int bStrict, char ** papszOptions, 
+        static GDALDataset *CreateCopy( const char * pszFilename,
+                                        GDALDataset * poSrcDS, int bStrict, char ** papszOptions,
                                         GDALProgressFunc pfnProgress, void * pProgressData );
         static GDALDataset* Create( const char * pszName,
                                     int nXSize, int nYSize, int nBands,
@@ -525,7 +558,7 @@ class GDALClientRasterBand : public GDALPamRasterBand
 
     GDALRasterBand    *CreateFakeMaskBand();
 
-    int                                              bEnableLineCaching;
+    bool                                             bEnableLineCaching;
     int                                              nSuccessiveLinesRead;
     GDALDataType                                     eLastBufType;
     int                                              nLastYOff;
@@ -558,7 +591,7 @@ class GDALClientRasterBand : public GDALPamRasterBand
                              GDALDataType eDataType, int nBlockXSize, int nBlockYSize,
                              GByte abyCaps[16]);
         ~GDALClientRasterBand();
-        
+
         int GetSrvBand() const { return iSrvBand; }
         int SupportsInstr(InstrEnum instr) const { return abyCaps[instr / 8] & (1 << (instr % 8)); }
 
@@ -588,7 +621,7 @@ class GDALClientRasterBand : public GDALPamRasterBand
         virtual double GetScale( int *pbSuccess = NULL );
 
         virtual GDALColorTable *GetColorTable();
-        virtual CPLErr SetColorTable( GDALColorTable * ); 
+        virtual CPLErr SetColorTable( GDALColorTable * );
 
         virtual const char *GetUnitType();
         virtual CPLErr SetUnitType( const char * );
@@ -597,24 +630,25 @@ class GDALClientRasterBand : public GDALPamRasterBand
 
         virtual CPLErr SetCategoryNames( char ** );
         virtual CPLErr SetNoDataValue( double );
+        virtual CPLErr DeleteNoDataValue();
         virtual CPLErr SetOffset( double );
         virtual CPLErr SetScale( double );
 
         virtual CPLErr GetStatistics( int bApproxOK, int bForce,
-                                    double *pdfMin, double *pdfMax, 
+                                    double *pdfMin, double *pdfMax,
                                     double *pdfMean, double *padfStdDev );
-        virtual CPLErr ComputeStatistics( int bApproxOK, 
-                                        double *pdfMin, double *pdfMax, 
+        virtual CPLErr ComputeStatistics( int bApproxOK,
+                                        double *pdfMin, double *pdfMax,
                                         double *pdfMean, double *pdfStdDev,
                                         GDALProgressFunc, void *pProgressData );
-        virtual CPLErr SetStatistics( double dfMin, double dfMax, 
+        virtual CPLErr SetStatistics( double dfMin, double dfMax,
                                       double dfMean, double dfStdDev );
         virtual CPLErr ComputeRasterMinMax( int, double* );
 
-        virtual CPLErr GetHistogram( double dfMin, double dfMax, 
-                                     int nBuckets, GUIntBig *panHistogram, 
+        virtual CPLErr GetHistogram( double dfMin, double dfMax,
+                                     int nBuckets, GUIntBig *panHistogram,
                                      int bIncludeOutOfRange, int bApproxOK,
-                                     GDALProgressFunc pfnProgress, 
+                                     GDALProgressFunc pfnProgress,
                                      void *pProgressData );
 
         virtual CPLErr GetDefaultHistogram( double *pdfMin, double *pdfMax,
@@ -639,7 +673,7 @@ class GDALClientRasterBand : public GDALPamRasterBand
         virtual CPLErr SetDefaultRAT( const GDALRasterAttributeTable * );
 
         virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
-                                int nBufXSize, int nBufYSize, 
+                                int nBufXSize, int nBufYSize,
                                 GDALDataType eDT, char **papszOptions );
         /*
         virtual GDALRasterBand *GetRasterSampleOverview( GUIntBig );
@@ -659,6 +693,9 @@ static GDALPipe* GDALPipeBuild(CPLSpawnedProcess* sp)
     p->fout = CPLSpawnAsyncGetOutputFileHandle(sp);
     p->nSocket = INVALID_SOCKET;
     p->nBufferSize = 0;
+#ifdef BUFFER_READ
+    p->nRecvBufferSize = 0;
+#endif
     return p;
 }
 
@@ -670,6 +707,9 @@ static GDALPipe* GDALPipeBuild(CPL_SOCKET nSocket)
     p->fout = CPL_FILE_INVALID_HANDLE;
     p->nSocket = nSocket;
     p->nBufferSize = 0;
+#ifdef BUFFER_READ
+    p->nRecvBufferSize = 0;
+#endif
     return p;
 }
 
@@ -681,6 +721,9 @@ static GDALPipe* GDALPipeBuild(CPL_FILE_HANDLE fin, CPL_FILE_HANDLE fout)
     p->fout = fout;
     p->nSocket = INVALID_SOCKET;
     p->nBufferSize = 0;
+#ifdef BUFFER_READ
+    p->nRecvBufferSize = 0;
+#endif
     return p;
 }
 
@@ -708,7 +751,7 @@ static int GDALPipeWrite_internal(GDALPipe* p, const void* data, int length)
         int nRemain = length;
         while( nRemain > 0 )
         {
-            int nRet = send(p->nSocket, pabyData, nRemain, 0);
+            int nRet = static_cast<int>(send(p->nSocket, pabyData, nRemain, 0));
             if( nRet < 0 )
             {
                 CPLError(CE_Failure, CPLE_AppDefined, "Write to socket failed");
@@ -754,6 +797,29 @@ static void GDALPipeFree(GDALPipe * p)
 }
 
 /************************************************************************/
+/*                     GDALPipeReadSocketInternal()                     */
+/************************************************************************/
+
+static int GDALPipeReadSocketInternal(GDALPipe* p, void* data, int length)
+{
+    char* pabyData = (char*) data;
+    int nRemain = length;
+    while( nRemain > 0 )
+    {
+        int nRet = static_cast<int>(recv(p->nSocket, pabyData, nRemain, 0));
+        if( nRet <= 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Read from socket failed");
+            p->bOK = FALSE;
+            return FALSE;
+        }
+        pabyData += nRet;
+        nRemain -= nRet;
+    }
+    return TRUE;
+}
+
+/************************************************************************/
 /*                            GDALPipeRead()                            */
 /************************************************************************/
 
@@ -763,7 +829,25 @@ static int GDALPipeRead(GDALPipe* p, void* data, int length)
         return FALSE;
     if(!GDALPipeFlushBuffer(p))
         return FALSE;
-    
+
+#ifdef BUFFER_READ
+begin:
+    if( length <= p->nRecvBufferSize )
+    {
+        memcpy(data, p->abyRecvBuffer, length);
+        memmove(p->abyRecvBuffer, p->abyRecvBuffer + length, p->nRecvBufferSize - length);
+        p->nRecvBufferSize -= length;
+        return TRUE;
+    }
+    if( p->nRecvBufferSize )
+    {
+        memcpy( data, p->abyRecvBuffer, p->nRecvBufferSize);
+        data = (char*) data + p->nRecvBufferSize;
+        length -= p->nRecvBufferSize;
+        p->nRecvBufferSize = 0;
+    }
+#endif
+
     if( p->fout != CPL_FILE_INVALID_HANDLE )
     {
         if( CPLPipeRead(p->fin, data, length) )
@@ -775,21 +859,21 @@ static int GDALPipeRead(GDALPipe* p, void* data, int length)
     }
     else
     {
-        char* pabyData = (char*) data;
-        int nRemain = length;
-        while( nRemain > 0 )
+#ifdef BUFFER_READ
+        int nAvailable = 0;
+        if( length < BUFFER_SIZE &&
+            ioctl(p->nSocket, FIONREAD, &nAvailable) == 0 &&
+            nAvailable > length )
         {
-            int nRet = recv(p->nSocket, pabyData, nRemain, 0);
-            if( nRet <= 0 )
-            {
-                CPLError(CE_Failure, CPLE_AppDefined, "Read from socket failed");
-                p->bOK = FALSE;
+            //CPLDebug("GDAL", "%d bytes available", nAvailable);
+            int ToRead = ( nAvailable > BUFFER_SIZE ) ? BUFFER_SIZE : nAvailable;
+            if( !GDALPipeReadSocketInternal(p, p->abyRecvBuffer, ToRead) )
                 return FALSE;
-            }
-            pabyData += nRet;
-            nRemain -= nRet;
+            p->nRecvBufferSize = ToRead;
+            goto begin;
         }
-        return TRUE;
+#endif
+        return GDALPipeReadSocketInternal(p, data, length);
     }
 
 }
@@ -867,7 +951,7 @@ static int GDALPipeRead_nolength(GDALPipe* p, int nLength, void* pabyData)
 
 static int GDALPipeRead(GDALPipe* p, int nExpectedLength, void* pabyData)
 {
-    int nLength;
+    int nLength = 0;
     return GDALPipeRead(p, &nLength) &&
            nLength == nExpectedLength &&
            GDALPipeRead_nolength(p, nLength, pabyData);
@@ -875,7 +959,7 @@ static int GDALPipeRead(GDALPipe* p, int nExpectedLength, void* pabyData)
 
 static int GDALPipeRead(GDALPipe* p, char** ppszStr)
 {
-    int nLength;
+    int nLength = 0;
     if( !GDALPipeRead(p, &nLength) || nLength < 0 )
     {
         *ppszStr = NULL;
@@ -902,7 +986,7 @@ static int GDALPipeRead(GDALPipe* p, char** ppszStr)
 
 static int GDALPipeRead(GDALPipe* p, char*** ppapszStr)
 {
-    int nStrCount;
+    int nStrCount = 0;
     if( !GDALPipeRead(p, &nStrCount) )
         return FALSE;
     if( nStrCount < 0 )
@@ -929,7 +1013,7 @@ static int GDALPipeRead(GDALPipe* p, char*** ppapszStr)
 
 static int GDALPipeRead(GDALPipe* p, int nItems, int** ppanInt)
 {
-    int nSize;
+    int nSize = 0;
     *ppanInt = NULL;
     if( !GDALPipeRead(p, &nSize) )
         return FALSE;
@@ -945,7 +1029,7 @@ static int GDALPipeRead(GDALPipe* p, int nItems, int** ppanInt)
 
 static int GDALPipeRead(GDALPipe* p, int nItems, GUIntBig** ppanInt)
 {
-    int nSize;
+    int nSize = 0;
     *ppanInt = NULL;
     if( !GDALPipeRead(p, &nSize) )
         return FALSE;
@@ -1028,7 +1112,7 @@ static int GDALPipeRead(GDALPipe* p, int* pnGCPCount, GDAL_GCP** ppasGCPs)
 {
     *pnGCPCount = 0;
     *ppasGCPs = NULL;
-    int nGCPCount;
+    int nGCPCount = 0;
     if( !GDALPipeRead(p, &nGCPCount) )
         return FALSE;
     GDAL_GCP* pasGCPs = (GDAL_GCP* )CPLCalloc(nGCPCount, sizeof(GDAL_GCP));
@@ -1055,7 +1139,7 @@ static int GDALPipeRead(GDALPipe* p, int* pnGCPCount, GDAL_GCP** ppasGCPs)
 static int GDALPipeRead(GDALPipe* p, GDALClientDataset* poDS,
                         GDALRasterBand** ppoBand, GByte abyCaps[16])
 {
-    int iSrvBand;
+    int iSrvBand = 0;
     *ppoBand = NULL;
     if( !GDALPipeRead(p, &iSrvBand) )
         return FALSE;
@@ -1099,7 +1183,6 @@ static int GDALSkipUntilEndOfJunkMarker(GDALPipe* p)
 {
     if(!p->bOK)
         return FALSE;
-    GByte c;
     size_t nIter = 0;
     int nStep = 0;
     CPLString osJunk;
@@ -1109,7 +1192,9 @@ static int GDALSkipUntilEndOfJunkMarker(GDALPipe* p)
         return FALSE;
     if( memcmp(abyEndOfJunkMarker, abyBuffer, sizeof(abyBuffer)) == 0 )
         return TRUE;
-    while(TRUE)
+
+    GByte c = 0;
+    while(true)
     {
         if( nIter < sizeof(abyBuffer) )
             c = abyBuffer[nIter ++];
@@ -1243,7 +1328,8 @@ static int GDALPipeWrite(GDALPipe* p, GDALColorTable* poColorTable)
 
 static int GDALPipeWrite(GDALPipe* p, const GDALRasterAttributeTable* poRAT)
 {
-    int bRet;
+    // TODO(schwehr): Refactor and simplify.
+    int bRet = FALSE;
     if( poRAT == NULL )
         bRet = GDALPipeWrite(p, (const char*)NULL);
     else
@@ -1266,7 +1352,7 @@ static int GDALPipeWrite(GDALPipe* p, int nGCPCount, const GDAL_GCP* pasGCPs)
 {
     if( !GDALPipeWrite(p, nGCPCount ) )
         return FALSE;
-    for(int i=0;i<nGCPCount;i++)
+    for( int i=0; i < nGCPCount; i++ )
     {
         if( !GDALPipeWrite(p, pasGCPs[i].pszId) ||
             !GDALPipeWrite(p, pasGCPs[i].pszInfo) ||
@@ -1321,19 +1407,19 @@ static int GDALEmitEndOfJunkMarker(GDALPipe* p)
 
 static void GDALConsumeErrors(GDALPipe* p)
 {
-    int nErrors;
+    int nErrors = 0;
     if( !GDALPipeRead(p, &nErrors) )
         return;
-    for(int i=0;i<nErrors;i++)
+    for( int i=0; i < nErrors; i++ )
     {
-        int       eErr;
-        int       nErrNo;
+        int       eErr = 0;
+        int       nErrNo = 0;
         char     *pszErrorMsg = NULL;
         if( !GDALPipeRead(p, &eErr) ||
             !GDALPipeRead(p, &nErrNo) ||
             !GDALPipeRead(p, &pszErrorMsg) )
             return;
-        CPLError((CPLErr)eErr, nErrNo, "%s", pszErrorMsg ? pszErrorMsg : "unknown");
+        CPLError((CPLErr)eErr, (CPLErrorNum)nErrNo, "%s", pszErrorMsg ? pszErrorMsg : "unknown");
         CPLFree(pszErrorMsg);
     }
 }
@@ -1344,7 +1430,7 @@ static void GDALConsumeErrors(GDALPipe* p)
 
 static int GDALEmitReset(GDALPipe* p)
 {
-    int bOK;
+    int bOK = FALSE;
     if( !GDALPipeWrite(p, INSTR_Reset) ||
         !GDALSkipUntilEndOfJunkMarker(p) ||
         !GDALPipeRead(p, &bOK) )
@@ -1359,7 +1445,7 @@ static int GDALEmitReset(GDALPipe* p)
 
 static int GDALEmitEXIT(GDALPipe* p, InstrEnum instr = INSTR_EXIT )
 {
-    int bOK;
+    int bOK = FALSE;
     if( !GDALPipeWrite(p, instr) ||
         !GDALSkipUntilEndOfJunkMarker(p) ||
         !GDALPipeRead(p, &bOK) )
@@ -1540,16 +1626,15 @@ static GDALServerSpawnedProcess* GDALServerSpawnAsync()
         CPLString osHost(pszSpawnServer);
         osHost.resize(pszColon - pszSpawnServer);
         CPL_SOCKET nConnSocket = INVALID_SOCKET;
-        int nRet;
 
 #ifdef WIN32
         WSADATA wsaData;
 
-        nRet = WSAStartup(MAKEWORD(2, 2), &wsaData);
-        if (nRet != NO_ERROR)
+        int nRet1 = WSAStartup(MAKEWORD(2, 2), &wsaData);
+        if (nRet1 != NO_ERROR)
         {
             CPLError(CE_Failure, CPLE_AppDefined,
-                     "WSAStartup() failed with error: %d\n", nRet);
+                     "WSAStartup() failed with error: %d\n", nRet1);
             return NULL;
         }
 #endif
@@ -1563,11 +1648,11 @@ static GDALServerSpawnedProcess* GDALServerSpawnAsync()
         sHints.ai_flags = 0;
         sHints.ai_protocol = IPPROTO_TCP;
 
-        nRet = getaddrinfo(osHost, pszColon + 1, &sHints, &psResults);
-        if (nRet)
+        int nRet2 = getaddrinfo(osHost, pszColon + 1, &sHints, &psResults);
+        if (nRet2)
         {
             CPLError(CE_Failure, CPLE_AppDefined,
-                     "getaddrinfo(): %s", gai_strerror(nRet));
+                     "getaddrinfo(): %s", gai_strerror(nRet2));
             WSACleanup();
             return NULL;
         }
@@ -1583,7 +1668,7 @@ static GDALServerSpawnedProcess* GDALServerSpawnAsync()
                 continue;
 
             if (connect(nConnSocket, psResultsIter->ai_addr,
-                        psResultsIter->ai_addrlen) != SOCKET_ERROR)
+                        CONNECT_LEN(psResultsIter->ai_addrlen)) != SOCKET_ERROR)
                 break;
 
             closesocket(nConnSocket);
@@ -1696,7 +1781,7 @@ static GDALServerSpawnedProcess* GDALServerSpawnAsync()
     if( strstr(pszSpawnServer, "gdalserver") == NULL )
         apszGDALServer[1] = NULL;
 #endif
-    int bCheckVersions = TRUE;
+    bool bCheckVersions = true;
 
     CPLSpawnedProcess* sp;
 #ifndef WIN32
@@ -1704,7 +1789,7 @@ static GDALServerSpawnedProcess* GDALServerSpawnAsync()
         EQUAL(pszSpawnServer, "FALSE")  || EQUAL(pszSpawnServer, "0") )
     {
         sp = CPLSpawnAsync(GDALServerLoopForked, NULL, TRUE, TRUE, FALSE, NULL);
-        bCheckVersions = FALSE;
+        bCheckVersions = false;
     }
     else
 #endif
@@ -1750,20 +1835,20 @@ static CPLErr CPLErrOnlyRet(GDALPipe* p)
 class GDALServerErrorDesc
 {
     public:
-        GDALServerErrorDesc() {}
+        GDALServerErrorDesc(CPLErr eErrIn = CE_None,
+                            CPLErrorNum nErrNoIn = CPLE_None,
+                            const CPLString& osMsgIn = "") :
+                eErr(eErrIn), nErrNo(nErrNoIn), osErrorMsg(osMsgIn) {}
 
         CPLErr    eErr;
-        int       nErrNo;
+        CPLErrorNum       nErrNo;
         CPLString osErrorMsg;
 };
 
-static void CPL_STDCALL RunErrorHandler(CPLErr eErr, int nErrNo,
+static void CPL_STDCALL RunErrorHandler(CPLErr eErr, CPLErrorNum nErrNo,
                                         const char* pszErrorMsg)
 {
-    GDALServerErrorDesc oDesc;
-    oDesc.eErr = eErr;
-    oDesc.nErrNo = nErrNo;
-    oDesc.osErrorMsg = pszErrorMsg;
+    GDALServerErrorDesc oDesc(eErr, nErrNo, pszErrorMsg);
     std::vector<GDALServerErrorDesc>* paoErrors =
         (std::vector<GDALServerErrorDesc>*) CPLGetErrorHandlerUserData();
     if( paoErrors )
@@ -1815,6 +1900,85 @@ static int CPL_STDCALL RunSyncProgress(double dfComplete,
 }
 
 /************************************************************************/
+/*                         GDALServerInstance                           */
+/************************************************************************/
+
+class GDALServerInstance
+{
+public:
+    GDALPipe* p;
+    GDALDataset* poDS;
+    std::vector<GDALRasterBand*> aBands;
+    void* pBuffer;
+    int nBufferSize;
+
+        GDALServerInstance(GDALPipe* p);
+       ~GDALServerInstance();
+};
+
+GDALServerInstance::GDALServerInstance(GDALPipe* pIn) :
+        p(pIn), poDS(NULL), pBuffer(NULL), nBufferSize(0)
+{
+}
+
+GDALServerInstance::~GDALServerInstance()
+{
+    CPLFree(pBuffer);
+
+    if( poDS != NULL )
+    {
+        GDALClose((GDALDatasetH)poDS);
+        poDS = NULL;
+    }
+
+}
+
+/************************************************************************/
+/*                GDALServerLoopInstanceCreateFromSocket()              */
+/************************************************************************/
+
+void * GDALServerLoopInstanceCreateFromSocket(CPL_SOCKET nSocket)
+{
+#ifndef WIN32
+    unsetenv("CPL_SHOW_MEM_STATS");
+#endif
+    CPLSetConfigOption("GDAL_API_PROXY", "NO");
+
+    GDALPipe* p = GDALPipeBuild(nSocket);
+
+    return new GDALServerInstance(p);
+}
+
+/************************************************************************/
+/*                 GDALServerLoopInstanceRunIteration()                 */
+/************************************************************************/
+
+static int GDALServerLoopInternal(GDALServerInstance* poSrvInstance,
+                                  GDALDataset* poSrcDS,
+                                  GDALProgressFunc pfnProgress, void* pProgressData,
+                                  int bIterateForever);
+
+int    GDALServerLoopInstanceRunIteration(void* pInstance)
+{
+    GDALServerInstance* poSrvInstance = (GDALServerInstance*)pInstance;
+    int nRet = GDALServerLoopInternal(poSrvInstance, NULL, NULL, NULL, FALSE);
+    if( !poSrvInstance->p->bOK )
+        nRet = FALSE;
+    return nRet;
+}
+
+/************************************************************************/
+/*                  GDALServerLoopInstanceDestroy()                     */
+/************************************************************************/
+
+void   GDALServerLoopInstanceDestroy(void* pInstance)
+{
+    GDALServerInstance* poSrvInstance = (GDALServerInstance*)pInstance;
+    GDALPipeFree(poSrvInstance->p);
+    delete poSrvInstance;
+}
+
+/************************************************************************/
 /*                         GDALServerLoop()                             */
 /************************************************************************/
 
@@ -1822,15 +1986,30 @@ static int GDALServerLoop(GDALPipe* p,
                           GDALDataset* poSrcDS,
                           GDALProgressFunc pfnProgress, void* pProgressData)
 {
-    GDALDataset* poDS = NULL;
-    std::vector<GDALRasterBand*> aBands;
-    std::vector<GDALServerErrorDesc> aoErrors;
+    GDALServerInstance* poSrcInstance = new GDALServerInstance(p);
+    int nRet = GDALServerLoopInternal(poSrcInstance, poSrcDS, pfnProgress, pProgressData, TRUE);
+    delete poSrcInstance;
+
+    return nRet;
+}
+
+/************************************************************************/
+/*                         GDALServerLoopInternal()                     */
+/************************************************************************/
+
+static int GDALServerLoopInternal(GDALServerInstance* poSrvInstance,
+                                  GDALDataset* poSrcDS,
+                                  GDALProgressFunc pfnProgress, void* pProgressData,
+                                  int bIterateForever)
+{
     int nRet = 1;
+    GDALDataset* poDS = poSrvInstance->poDS;
+    std::vector<GDALServerErrorDesc> aoErrors;
     GDALServerAsyncProgress asyncp;
     memset(&asyncp, 0, sizeof(asyncp));
     asyncp.bRet = TRUE;
-    void* pBuffer = NULL;
-    int nBufferSize = 0;
+    void* pBuffer = poSrvInstance->pBuffer;
+    int nBufferSize = poSrvInstance->nBufferSize;
 
     const char* pszOldVal = CPLGetConfigOption("GDAL_API_PROXY", NULL);
     char* pszOldValDup = (pszOldVal) ? CPLStrdup(pszOldVal) : NULL;
@@ -1839,17 +2018,29 @@ static int GDALServerLoop(GDALPipe* p,
     if( poSrcDS == NULL )
         CPLPushErrorHandlerEx(RunErrorHandler, &aoErrors);
 
+    GDALPipe* p = poSrvInstance->p;
+
     // fprintf(stderr, "[%d] started\n", (int)getpid());
-    while(TRUE)
+    int nIter = 0;
+    //fprintf(stderr, "Beginning of loop: poSrcDS = %p, poDS = %p\n", poSrcDS, poDS);
+    while(true)
     {
-        int instr;
+        nIter ++;
+        if( !bIterateForever && nIter != 1 )
+        {
+            break;
+        }
+
+        int instr = 0;
         if( !GDALPipeRead(p, &instr) )
         {
             // fprintf(stderr, "[%d] instr failed\n", (int)getpid());
             break;
         }
 
-        // fprintf(stderr, "[%d] %s\n", (int)getpid(), (instr >= 0 && instr < INSTR_END) ? apszInstr[instr] : "unknown");
+#ifdef DEBUG_VERBOSE
+        fprintf(stderr, "[%d] %s\n", (int)getpid(), (instr >= 0 && instr < INSTR_END) ? apszInstr[instr] : "unknown");
+#endif
 
         GDALRasterBand* poBand = NULL;
 
@@ -1859,7 +2050,8 @@ static int GDALServerLoop(GDALPipe* p,
             {
                 GDALClose((GDALDatasetH)poDS);
                 poDS = NULL;
-                aBands.resize(0);
+                //fprintf(stderr, "INSTR_EXIT: poDS = %p\n", poDS);
+                poSrvInstance->aBands.resize(0);
             }
             GDALEmitEndOfJunkMarker(p);
             GDALPipeWrite(p, TRUE);
@@ -1876,7 +2068,7 @@ static int GDALServerLoop(GDALPipe* p,
                  instr == 0x01000000 )
         {
             /* Do not change this protocol ! */
-            char bClientIsLSB;
+            char bClientIsLSB = '\0';  // TODO(schwehr): bool char?
             char* pszClientVersion = NULL;
             int nClientMajor, nClientMinor,
                 nClientProtocolMajor, nClientProtocolMinor,
@@ -1948,7 +2140,7 @@ static int GDALServerLoop(GDALPipe* p,
             if( !GDALPipeRead(p, &dfProgress) ||
                 !GDALPipeRead(p, &pszProgressMsg) )
                 break;
-            int nRet = pfnProgress(dfProgress, pszProgressMsg, pProgressData);
+            nRet = pfnProgress(dfProgress, pszProgressMsg, pProgressData);
             GDALEmitEndOfJunkMarker(p);
             GDALPipeWrite(p, nRet);
             CPLFree(pszProgressMsg);
@@ -1959,8 +2151,9 @@ static int GDALServerLoop(GDALPipe* p,
             {
                 GDALClose((GDALDatasetH)poDS);
                 poDS = NULL;
+                //fprintf(stderr, "INSTR_Reset: poDS = %p\n", poDS);
                 MyChdirRootDirectory();
-                aBands.resize(0);
+                poSrvInstance->aBands.resize(0);
             }
             GDALEmitEndOfJunkMarker(p);
             GDALPipeWrite(p, TRUE);
@@ -1970,24 +2163,55 @@ static int GDALServerLoop(GDALPipe* p,
             int nAccess;
             char* pszFilename = NULL;
             char* pszCWD = NULL;
+            char** papszOpenOptions = NULL;
             if( !GDALPipeRead(p, &nAccess) ||
                 !GDALPipeRead(p, &pszFilename) ||
-                !GDALPipeRead(p, &pszCWD) )
+                !GDALPipeRead(p, &pszCWD) ||
+                !GDALPipeRead(p, &papszOpenOptions) )
             {
                 CPLFree(pszFilename);
                 CPLFree(pszCWD);
+                CSLDestroy(papszOpenOptions);
                 break;
             }
+
+            // This should not happen for clients that respect the (implied) protocol...
+            if( poSrcDS == NULL && poDS != NULL && pszFilename != NULL )
+            {
+                CPLFree(pszFilename);
+                CPLFree(pszCWD);
+                CSLDestroy(papszOpenOptions);
+
+                GDALEmitEndOfJunkMarker(p);
+                GDALPipeWrite(p, FALSE);
+
+                GDALPipeWrite(p, 1); // 1 error
+                GDALPipeWrite(p, CE_Failure);
+                GDALPipeWrite(p, CPLE_NotSupported);
+                GDALPipeWrite(p, "Only one dataset can be opened through a client connection");
+                continue;
+            }
+
             if( pszCWD != NULL )
             {
-                MyChdir(pszCWD);
+                if( pszFilename )
+                {
+                    if( CPLIsFilenameRelative(pszFilename) )
+                        MyChdir(pszCWD);
+                }
                 CPLFree(pszCWD);
             }
             if( poSrcDS != NULL )
                 poDS = poSrcDS;
             else if( poDS == NULL && pszFilename != NULL )
-                poDS = (GDALDataset*) GDALOpen(pszFilename, (GDALAccess)nAccess);
+                poDS = (GDALDataset*) GDALOpenEx(pszFilename,
+                                                 ((nAccess == GA_Update) ? GDAL_OF_UPDATE : 0) | GDAL_OF_SHARED,
+                                                 NULL,
+                                                 papszOpenOptions,
+                                                 NULL);
+            //fprintf(stderr, "INSTR_Open: poDS = %p\n", poDS);
             CPLFree(pszFilename);
+            CSLDestroy(papszOpenOptions);
             GDALEmitEndOfJunkMarker(p);
             GDALPipeWrite(p, poDS != NULL);
             if( poDS != NULL )
@@ -2036,24 +2260,24 @@ static int GDALServerLoop(GDALPipe* p,
                 /* Check if all bands are identical */
                 for(i=0;i<nBands;i++)
                 {
-                    GDALRasterBand* poBand = poDS->GetRasterBand(i+1);
-                    if( strlen(poBand->GetDescription()) > 0 )
+                    GDALRasterBand* poOtherBand = poDS->GetRasterBand(i+1);
+                    if( strlen(poOtherBand->GetDescription()) > 0 )
                     {
                         bAllSame = FALSE;
                         break;
                     }
                     if( i == 0 )
                     {
-                        poFirstBand = poBand;
-                        poBand->GetBlockSize(&nFBBlockXSize, &nFBBlockYSize);
+                        poFirstBand = poOtherBand;
+                        poOtherBand->GetBlockSize(&nFBBlockXSize, &nFBBlockYSize);
                     }
                     else
                     {
                         int nBlockXSize, nBlockYSize;
-                        poBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
-                        if( poBand->GetXSize() != poFirstBand->GetXSize() ||
-                            poBand->GetYSize() != poFirstBand->GetYSize() ||
-                            poBand->GetRasterDataType() != poFirstBand->GetRasterDataType() ||
+                        poOtherBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
+                        if( poOtherBand->GetXSize() != poFirstBand->GetXSize() ||
+                            poOtherBand->GetYSize() != poFirstBand->GetYSize() ||
+                            poOtherBand->GetRasterDataType() != poFirstBand->GetRasterDataType() ||
                             nBlockXSize != nFBBlockXSize ||
                             nBlockYSize != nFBBlockYSize )
                         {
@@ -2067,11 +2291,11 @@ static int GDALServerLoop(GDALPipe* p,
                 GDALPipeWrite(p, bAllSame);
                 for(i=0;i<nBands;i++)
                 {
-                    GDALRasterBand* poBand = poDS->GetRasterBand(i+1);
+                    GDALRasterBand* poOtherBand = poDS->GetRasterBand(i+1);
                     if( i > 0 && bAllSame )
-                        aBands.push_back(poBand);
+                        poSrvInstance->aBands.push_back(poOtherBand);
                     else
-                        GDALPipeWrite(p, aBands, poBand);
+                        GDALPipeWrite(p, poSrvInstance->aBands, poOtherBand);
                 }
             }
         }
@@ -2090,7 +2314,11 @@ static int GDALServerLoop(GDALPipe* p,
 
             if( pszCWD != NULL )
             {
-                MyChdir(pszCWD);
+                if( pszFilename )
+                {
+                    if( CPLIsFilenameRelative(pszFilename) )
+                        MyChdir(pszCWD);
+                }
                 CPLFree(pszCWD);
             }
 
@@ -2123,7 +2351,11 @@ static int GDALServerLoop(GDALPipe* p,
 
             if( pszCWD != NULL )
             {
-                MyChdir(pszCWD);
+                if( pszFilename )
+                {
+                    if( CPLIsFilenameRelative(pszFilename) )
+                        MyChdir(pszCWD);
+                }
                 CPLFree(pszCWD);
             }
 
@@ -2141,6 +2373,7 @@ static int GDALServerLoop(GDALPipe* p,
                 poDS = poDriver->Create(pszFilename, nXSize, nYSize, nBands,
                                         (GDALDataType)nDataType,
                                         papszOptions);
+                //fprintf(stderr, "INSTR_Create: poDS = %p\n", poDS);
             }
             else
                 CPLError(CE_Failure, CPLE_AppDefined, "Cannot find driver %s",
@@ -2175,9 +2408,29 @@ static int GDALServerLoop(GDALPipe* p,
 
             CPLFree(pszSrcDescription);
 
+            if( !bIterateForever )
+            {
+                GDALPipeWrite(p, FALSE);
+
+                GDALPipeWrite(p, 1); // 1 error
+                GDALPipeWrite(p, CE_Failure);
+                GDALPipeWrite(p, CPLE_NotSupported);
+                GDALPipeWrite(p, "CreateCopy() not supported in -nofork mode (to avoid deadlocks)");
+
+                CPLFree(pszFilename);
+                CPLFree(pszCWD);
+                CSLDestroy(papszCreateOptions);
+
+                continue;
+            }
+
             if( pszCWD != NULL )
             {
-                MyChdir(pszCWD);
+                if( pszFilename )
+                {
+                    if( CPLIsFilenameRelative(pszFilename) )
+                        MyChdir(pszCWD);
+                }
                 CPLFree(pszCWD);
             }
 
@@ -2193,22 +2446,23 @@ static int GDALServerLoop(GDALPipe* p,
             GDALPipeWrite(p, poDriver != NULL);
             if( poDriver != NULL )
             {
-                GDALClientDataset* poSrcDS = new GDALClientDataset(p);
-                if( !poSrcDS->Init(NULL, GA_ReadOnly) )
+                GDALClientDataset* l_poSrcDS = new GDALClientDataset(p);
+                if( !l_poSrcDS->Init(NULL, GA_ReadOnly, NULL) )
                 {
-                    delete poSrcDS;
+                    delete l_poSrcDS;
                     CPLFree(pszFilename);
                     CSLDestroy(papszCreateOptions);
                     break;
                 }
-                poSrcDS->AttachAsyncProgress(&asyncp);
+                l_poSrcDS->AttachAsyncProgress(&asyncp);
 
-                poDS = poDriver->CreateCopy(pszFilename, poSrcDS,
+                poDS = poDriver->CreateCopy(pszFilename, l_poSrcDS,
                                             bStrict, papszCreateOptions,
                                             RunAsyncProgress, &asyncp);
+                //fprintf(stderr, "INSTR_CreateCopy: poDS = %p\n", poDS);
 
-                int bProgressRet = poSrcDS->ProcessAsyncProgress();
-                GDALClose((GDALDatasetH)poSrcDS);
+                int bProgressRet = l_poSrcDS->ProcessAsyncProgress();
+                GDALClose((GDALDatasetH)l_poSrcDS);
 
                 if( !bProgressRet && poDS != NULL )
                 {
@@ -2242,7 +2496,11 @@ static int GDALServerLoop(GDALPipe* p,
 
             if( pszCWD != NULL )
             {
-                MyChdir(pszCWD);
+                if( pszFilename )
+                {
+                    if( CPLIsFilenameRelative(pszFilename) )
+                        MyChdir(pszCWD);
+                }
                 CPLFree(pszCWD);
             }
 
@@ -2266,7 +2524,7 @@ static int GDALServerLoop(GDALPipe* p,
             if( eErr == CE_None )
             {
                 int nBandCount = poDS->GetRasterCount();
-                GDALPipeWrite(p, aBands, poDS->GetRasterBand(nBandCount));
+                GDALPipeWrite(p, poSrvInstance->aBands, poDS->GetRasterBand(nBandCount));
             }
             CSLDestroy(papszOptions);
         }
@@ -2350,7 +2608,11 @@ static int GDALServerLoop(GDALPipe* p,
                 break;
             char* pszGCPProjection = NULL;
             if( !GDALPipeRead(p, &pszGCPProjection) )
+            {
+                GDALDeinitGCPs(nGCPCount, pasGCPs);
+                CPLFree(pasGCPs);
                 break;
+            }
             CPLErr eErr = poDS->SetGCPs(nGCPCount, pasGCPs, pszGCPProjection);
             GDALDeinitGCPs(nGCPCount, pasGCPs);
             CPLFree(pasGCPs);
@@ -2579,11 +2841,12 @@ static int GDALServerLoop(GDALPipe* p,
                 break;
             }
             /* Note: only combinations of nPixelSpace, nLineSpace and
-               nBandSpace that lead to compate band-interleaved or pixel-
-               interleaved buffers are valid. Other combinations will lead to segfault */
+               nBandSpace that lead to compatible band-interleaved or pixel-
+               interleaved buffers are valid. Other combinations will lead
+               to segfaults. */
             eBufType = (GDALDataType)nBufType;
-            int nSize = nBufXSize * nBufYSize * nBandCount *
-                (GDALGetDataTypeSize(eBufType) / 8);
+            const int nSize = nBufXSize * nBufYSize * nBandCount *
+                GDALGetDataTypeSizeBytes(eBufType);
             if( nSize > nBufferSize )
             {
                 nBufferSize = nSize;
@@ -2631,23 +2894,28 @@ static int GDALServerLoop(GDALPipe* p,
                 break;
             }
             /* Note: only combinations of nPixelSpace, nLineSpace and
-               nBandSpace that lead to compate band-interleaved or pixel-
-               interleaved buffers are valid. Other combinations will lead to segfault */
+               nBandSpace that lead to compatible band-interleaved or pixel-
+               interleaved buffers are valid. Other combinations will lead
+               to segfaults. */
             eBufType = (GDALDataType)nBufType;
-            int nExpectedSize = nBufXSize * nBufYSize * nBandCount *
-                (GDALGetDataTypeSize(eBufType) / 8);
+            const int nExpectedSize = nBufXSize * nBufYSize * nBandCount *
+                GDALGetDataTypeSizeBytes(eBufType);
             int nSize;
-            if( !GDALPipeRead(p, &nSize) )
-                break;
-            if( nSize != nExpectedSize )
+            if( !GDALPipeRead(p, &nSize) || nSize != nExpectedSize )
+            {
+                CPLFree(panBandMap);
                 break;
+            }
             if( nSize > nBufferSize )
             {
                 nBufferSize = nSize;
                 pBuffer = CPLRealloc(pBuffer, nSize);
             }
             if( !GDALPipeRead_nolength(p, nSize, pBuffer) )
+            {
+                CPLFree(panBandMap);
                 break;
+            }
 
             CPLErr eErr = poDS->RasterIO(GF_Write,
                                          nXOff, nYOff, nXSize, nYSize,
@@ -2676,9 +2944,9 @@ static int GDALServerLoop(GDALPipe* p,
             int iBand;
             if( !GDALPipeRead(p, &iBand) )
                 break;
-            if( iBand < 0 || iBand >= (int)aBands.size() )
+            if( iBand < 0 || iBand >= (int)poSrvInstance->aBands.size() )
                 break;
-            poBand = aBands[iBand];
+            poBand = poSrvInstance->aBands[iBand];
         }
         else
             break;
@@ -2843,6 +3111,12 @@ static int GDALServerLoop(GDALPipe* p,
             GDALEmitEndOfJunkMarker(p);
             GDALPipeWrite(p, eErr);
         }
+        else if( instr == INSTR_Band_DeleteNoDataValue )
+        {
+            CPLErr eErr = poBand->DeleteNoDataValue();
+            GDALEmitEndOfJunkMarker(p);
+            GDALPipeWrite(p, eErr);
+        }
         else if( instr == INSTR_Band_SetOffset )
         {
             double dfVal;
@@ -2869,8 +3143,8 @@ static int GDALServerLoop(GDALPipe* p,
                 break;
             int nBlockXSize, nBlockYSize;
             poBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
-            int nSize = nBlockXSize * nBlockYSize *
-                (GDALGetDataTypeSize(poBand->GetRasterDataType()) / 8);
+            const int nSize = nBlockXSize * nBlockYSize *
+                GDALGetDataTypeSizeBytes(poBand->GetRasterDataType());
             if( nSize > nBufferSize )
             {
                 nBufferSize = nSize;
@@ -2890,8 +3164,8 @@ static int GDALServerLoop(GDALPipe* p,
                 break;
             int nBlockXSize, nBlockYSize;
             poBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
-            int nExpectedSize = nBlockXSize * nBlockYSize *
-                (GDALGetDataTypeSize(poBand->GetRasterDataType()) / 8);
+            const int nExpectedSize = nBlockXSize * nBlockYSize *
+                GDALGetDataTypeSizeBytes(poBand->GetRasterDataType());
             if( nExpectedSize != nSize )
                 break;
             if( nSize > nBufferSize )
@@ -2921,8 +3195,8 @@ static int GDALServerLoop(GDALPipe* p,
                 !GDALPipeRead(p, &nBufType) )
                 break;
             eBufType = (GDALDataType)nBufType;
-            int nSize = nBufXSize * nBufYSize *
-                (GDALGetDataTypeSize(eBufType) / 8);
+            const int nSize = nBufXSize * nBufYSize *
+                GDALGetDataTypeSizeBytes(eBufType);
             if( nSize > nBufferSize )
             {
                 nBufferSize = nSize;
@@ -2952,8 +3226,8 @@ static int GDALServerLoop(GDALPipe* p,
                 !GDALPipeRead(p, &nBufType) )
                 break;
             eBufType = (GDALDataType)nBufType;
-            int nExpectedSize = nBufXSize * nBufYSize *
-                (GDALGetDataTypeSize(eBufType) / 8);
+            const int nExpectedSize = nBufXSize * nBufYSize *
+                GDALGetDataTypeSizeBytes(eBufType);
             int nSize;
             if( !GDALPipeRead(p, &nSize) )
                 break;
@@ -3052,14 +3326,14 @@ static int GDALServerLoop(GDALPipe* p,
             GUIntBig* panHistogram = (GUIntBig*) VSIMalloc2(sizeof(GUIntBig), nBuckets);
             if( panHistogram == NULL )
                 break;
-            CPLErr eErr = poBand->GetHistogram(dfMin, dfMax, 
-                                     nBuckets, panHistogram, 
+            CPLErr eErr = poBand->GetHistogram(dfMin, dfMax,
+                                     nBuckets, panHistogram,
                                      bIncludeOutOfRange, bApproxOK, NULL, NULL);
             GDALEmitEndOfJunkMarker(p);
             GDALPipeWrite(p, eErr);
             if( eErr != CE_Failure )
             {
-                GDALPipeWrite(p, nBuckets * sizeof(GUIntBig), panHistogram);
+                GDALPipeWrite(p, nBuckets * (int)sizeof(GUIntBig), panHistogram);
             }
             CPLFree(panHistogram);
         }
@@ -3081,7 +3355,7 @@ static int GDALServerLoop(GDALPipe* p,
                 GDALPipeWrite(p, dfMin);
                 GDALPipeWrite(p, dfMax);
                 GDALPipeWrite(p, nBuckets);
-                GDALPipeWrite(p, nBuckets * sizeof(GUIntBig) , panHistogram);
+                GDALPipeWrite(p, nBuckets * (int)sizeof(GUIntBig) , panHistogram);
             }
             CPLFree(panHistogram);
         }
@@ -3123,13 +3397,13 @@ static int GDALServerLoop(GDALPipe* p,
                 break;
             GDALRasterBand* poOvrBand = poBand->GetOverview(iOvr);
             GDALEmitEndOfJunkMarker(p);
-            GDALPipeWrite(p, aBands, poOvrBand);
+            GDALPipeWrite(p, poSrvInstance->aBands, poOvrBand);
         }
         else if( instr == INSTR_Band_GetMaskBand )
         {
             GDALRasterBand* poMaskBand = poBand->GetMaskBand();
             GDALEmitEndOfJunkMarker(p);
-            GDALPipeWrite(p, aBands, poMaskBand);
+            GDALPipeWrite(p, poSrvInstance->aBands, poMaskBand);
         }
         else if( instr == INSTR_Band_GetMaskFlags )
         {
@@ -3261,6 +3535,9 @@ static int GDALServerLoop(GDALPipe* p,
             GDALPipeWrite(p, 0);
     }
 
+    if( !bIterateForever )
+        GDALPipeFlushBuffer(p);
+
     if( poSrcDS == NULL )
         CPLPopErrorHandler();
 
@@ -3268,11 +3545,14 @@ static int GDALServerLoop(GDALPipe* p,
     CPLFree(pszOldValDup);
 
     // fprintf(stderr, "[%d] finished = %d\n", (int)getpid(), nRet);
+    //fprintf(stderr, "End of loop: poSrcDS = %p, poDS = %p\n", poSrcDS, poDS);
 
-    if( poSrcDS == NULL && poDS != NULL )
-        GDALClose((GDALDatasetH)poDS);
-
-    CPLFree(pBuffer);
+    if( poSrcDS == NULL )
+        poSrvInstance->poDS = poDS;
+    else
+        poSrvInstance->aBands.resize(0);
+    poSrvInstance->pBuffer = pBuffer;
+    poSrvInstance->nBufferSize = nBufferSize;
 
     CPLFree(asyncp.pszProgressMsg);
     if( asyncp.hMutex )
@@ -3325,10 +3605,10 @@ int GDALServerLoopSocket(CPL_SOCKET nSocket)
 /*                        GDALClientDataset()                           */
 /************************************************************************/
 
-GDALClientDataset::GDALClientDataset(GDALServerSpawnedProcess* ssp)
+GDALClientDataset::GDALClientDataset(GDALServerSpawnedProcess* sspIn)
 {
-    this->ssp = ssp;
-    this->p = ssp->p;
+    ssp = sspIn;
+    p = ssp->p;
     bFreeDriver = FALSE;
     nGCPCount = 0;
     pasGCPs = NULL;
@@ -3340,10 +3620,10 @@ GDALClientDataset::GDALClientDataset(GDALServerSpawnedProcess* ssp)
 /*                        GDALClientDataset()                           */
 /************************************************************************/
 
-GDALClientDataset::GDALClientDataset(GDALPipe* p)
+GDALClientDataset::GDALClientDataset(GDALPipe* pIn)
 {
-    this->ssp = NULL;
-    this->p = p;
+    ssp = NULL;
+    p = pIn;
     bFreeDriver = FALSE;
     nGCPCount = 0;
     pasGCPs = NULL;
@@ -3405,15 +3685,15 @@ int GDALClientDataset::ProcessAsyncProgress()
     GDALConsumeErrors(p);
     return bRet;
 }
- 
+
 /************************************************************************/
 /*                          IBuildOverviews()                           */
 /************************************************************************/
 
-CPLErr GDALClientDataset::IBuildOverviews( const char *pszResampling, 
-                                           int nOverviews, int *panOverviewList, 
+CPLErr GDALClientDataset::IBuildOverviews( const char *pszResampling,
+                                           int nOverviews, int *panOverviewList,
                                            int nListBands, int *panBandList,
-                                           GDALProgressFunc pfnProgress, 
+                                           GDALProgressFunc pfnProgress,
                                            void * pProgressData )
 {
     if( !SupportsInstr(INSTR_IBuildOverviews) )
@@ -3439,9 +3719,9 @@ CPLErr GDALClientDataset::IBuildOverviews( const char *pszResampling,
     if( !GDALPipeWrite(p, INSTR_IBuildOverviews) ||
         !GDALPipeWrite(p, pszResampling) ||
         !GDALPipeWrite(p, nOverviews) ||
-        !GDALPipeWrite(p, nOverviews * sizeof(int), panOverviewList) ||
+        !GDALPipeWrite(p, nOverviews * (int)sizeof(int), panOverviewList) ||
         !GDALPipeWrite(p, nListBands) ||
-        !GDALPipeWrite(p, nListBands * sizeof(int), panBandList) )
+        !GDALPipeWrite(p, nListBands * (int)sizeof(int), panBandList) )
         return CE_Failure;
 
     if( GDALServerLoop(p, NULL, pfnProgress, pProgressData) != 0 )
@@ -3465,7 +3745,7 @@ CPLErr GDALClientDataset::IBuildOverviews( const char *pszResampling,
 CPLErr GDALClientDataset::IRasterIO( GDALRWFlag eRWFlag,
                                  int nXOff, int nYOff, int nXSize, int nYSize,
                                  void * pData, int nBufXSize, int nBufYSize,
-                                 GDALDataType eBufType, 
+                                 GDALDataType eBufType,
                                  int nBandCount, int *panBandMap,
                                  GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace,
                                  GDALRasterIOExtraArg* psExtraArg)
@@ -3474,7 +3754,7 @@ CPLErr GDALClientDataset::IRasterIO( GDALRWFlag eRWFlag,
         return GDALPamDataset::IRasterIO( eRWFlag,
                                           nXOff, nYOff, nXSize, nYSize,
                                           pData, nBufXSize, nBufYSize,
-                                          eBufType, 
+                                          eBufType,
                                           nBandCount, panBandMap,
                                           nPixelSpace, nLineSpace, nBandSpace,
                                           psExtraArg );
@@ -3484,17 +3764,17 @@ CPLErr GDALClientDataset::IRasterIO( GDALRWFlag eRWFlag,
 
     ProcessAsyncProgress();
 
-    int nDataTypeSize = GDALGetDataTypeSize(eBufType) / 8;
+    const int nDataTypeSize = GDALGetDataTypeSizeBytes(eBufType);
     int bDirectCopy;
     if( nPixelSpace == nDataTypeSize &&
-        nLineSpace == nBufXSize * nDataTypeSize &&
+        nLineSpace == static_cast<GSpacing>(nBufXSize) * nDataTypeSize &&
         (nBandSpace == nBufYSize * nLineSpace ||
             (nBandSpace == 0 && nBandCount == 1)) )
     {
         bDirectCopy = TRUE;
     }
     else if( nBandCount > 1 &&
-                nPixelSpace == nBandCount * nDataTypeSize &&
+                nPixelSpace == static_cast<GSpacing>(nBandCount) * nDataTypeSize &&
                 nLineSpace == nBufXSize * nPixelSpace &&
                 nBandSpace == nBandCount )
     {
@@ -3518,7 +3798,7 @@ CPLErr GDALClientDataset::IRasterIO( GDALRWFlag eRWFlag,
         !GDALPipeWrite(p, nBufYSize) ||
         !GDALPipeWrite(p, eBufType) ||
         !GDALPipeWrite(p, nBandCount) ||
-        !GDALPipeWrite(p, nBandCount * sizeof(int), panBandMap) )
+        !GDALPipeWrite(p, nBandCount * (int)sizeof(int), panBandMap) )
         return CE_Failure;
 
     if( bDirectCopy )
@@ -3573,7 +3853,7 @@ CPLErr GDALClientDataset::IRasterIO( GDALRWFlag eRWFlag,
                         GDALCopyWords( pBuf + (iBand * nBufYSize + j) * nBufXSize * nDataTypeSize,
                                        eBufType, nDataTypeSize,
                                        (GByte*)pData + iBand * nBandSpace + j * nLineSpace,
-                                       eBufType, nPixelSpace,
+                                       eBufType, static_cast<int>(nPixelSpace),
                                        nBufXSize);
                     }
                 }
@@ -3602,7 +3882,7 @@ CPLErr GDALClientDataset::IRasterIO( GDALRWFlag eRWFlag,
                 for(int j=0;j<nBufYSize;j++)
                 {
                     GDALCopyWords( (GByte*)pData + iBand * nBandSpace + j * nLineSpace,
-                                   eBufType, nPixelSpace,
+                                   eBufType, static_cast<int>(nPixelSpace),
                                    pBuf + (iBand * nBufYSize + j) * nBufXSize * nDataTypeSize,
                                    eBufType, nDataTypeSize,
                                    nBufXSize );
@@ -3726,11 +4006,11 @@ int GDALClientDataset::GetGCPCount()
     if( !GDALSkipUntilEndOfJunkMarker(p) )
         return 0;
 
-    int nGCPCount;
-    if( !GDALPipeRead(p, &nGCPCount) )
+    int l_nGCPCount;
+    if( !GDALPipeRead(p, &l_nGCPCount) )
         return 0;
     GDALConsumeErrors(p);
-    return nGCPCount;
+    return l_nGCPCount;
 }
 
 /************************************************************************/
@@ -3793,15 +4073,15 @@ const GDAL_GCP * GDALClientDataset::GetGCPs()
 /*                               SetGCPs()                              */
 /************************************************************************/
 
-CPLErr GDALClientDataset::SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
-                                   const char *pszGCPProjection ) 
+CPLErr GDALClientDataset::SetGCPs( int nGCPCountIn, const GDAL_GCP *pasGCPList,
+                                   const char *pszGCPProjection )
 {
     if( !SupportsInstr(INSTR_SetGCPs) )
-        return GDALPamDataset::SetGCPs(nGCPCount, pasGCPList, pszGCPProjection);
+        return GDALPamDataset::SetGCPs(nGCPCountIn, pasGCPList, pszGCPProjection);
 
     CLIENT_ENTER();
     if( !GDALPipeWrite(p, INSTR_SetGCPs) ||
-        !GDALPipeWrite(p, nGCPCount, pasGCPList) ||
+        !GDALPipeWrite(p, nGCPCountIn, pasGCPList) ||
         !GDALPipeWrite(p, pszGCPProjection) )
         return CE_Failure;
     return CPLErrOnlyRet(p);
@@ -3827,7 +4107,7 @@ char** GDALClientDataset::GetFileList()
         return NULL;
     GDALConsumeErrors(p);
 
-    /* If server is Windows and client is Unix, then replace backslahes */
+    /* If server is Windows and client is Unix, then replace backslashes */
     /* by slashes */
 #ifndef WIN32
     char** papszIter = papszFileList;
@@ -3996,7 +4276,7 @@ void GDALClientDataset::FlushCache()
 /*                              AddBand()                               */
 /************************************************************************/
 
-CPLErr GDALClientDataset::AddBand( GDALDataType eType, 
+CPLErr GDALClientDataset::AddBand( GDALDataType eType,
                                    char **papszOptions )
 {
     if( !SupportsInstr(INSTR_AddBand) )
@@ -4020,7 +4300,7 @@ CPLErr GDALClientDataset::AddBand( GDALDataType eType,
         SetBand(GetRasterCount() + 1, poBand);
     }
     GDALConsumeErrors(p);
-    return eRet;    
+    return eRet;
 }
 
 
@@ -4029,8 +4309,8 @@ CPLErr GDALClientDataset::AddBand( GDALDataType eType,
 /************************************************************************/
 
 CPLErr GDALClientDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
-                                  int nBufXSize, int nBufYSize, 
-                                  GDALDataType eDT, 
+                                  int nBufXSize, int nBufYSize,
+                                  GDALDataType eDT,
                                   int nBandCount, int *panBandList,
                                   char **papszOptions )
 {
@@ -4049,7 +4329,7 @@ CPLErr GDALClientDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSi
         !GDALPipeWrite(p, nBufYSize) ||
         !GDALPipeWrite(p, eDT) ||
         !GDALPipeWrite(p, nBandCount) ||
-        !GDALPipeWrite(p, panBandList ? nBandCount * sizeof(int) : 0, panBandList) ||
+        !GDALPipeWrite(p, panBandList ? nBandCount * (int)sizeof(int) : 0, panBandList) ||
         !GDALPipeWrite(p, papszOptions) )
         return CE_Failure;
     return CPLErrOnlyRet(p);
@@ -4059,16 +4339,16 @@ CPLErr GDALClientDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSi
 /*                           CreateMaskBand()                           */
 /************************************************************************/
 
-CPLErr GDALClientDataset::CreateMaskBand( int nFlags )
+CPLErr GDALClientDataset::CreateMaskBand( int nFlagsIn )
 {
     if( !SupportsInstr(INSTR_CreateMaskBand) )
-        return GDALPamDataset::CreateMaskBand(nFlags);
+        return GDALPamDataset::CreateMaskBand(nFlagsIn);
 
     CLIENT_ENTER();
     GDALPipeWriteConfigOption(p, "GDAL_TIFF_INTERNAL_MASK_TO_8BIT", bRecycleChild);
     GDALPipeWriteConfigOption(p, "GDAL_TIFF_INTERNAL_MASK", bRecycleChild);
     if( !GDALPipeWrite(p, INSTR_CreateMaskBand) ||
-        !GDALPipeWrite(p, nFlags) )
+        !GDALPipeWrite(p, nFlagsIn) )
         return CE_Failure;
     return CPLErrOnlyRet(p);
 }
@@ -4077,31 +4357,32 @@ CPLErr GDALClientDataset::CreateMaskBand( int nFlags )
 /*                       GDALClientRasterBand()                         */
 /************************************************************************/
 
-GDALClientRasterBand::GDALClientRasterBand(GDALPipe* p, int iSrvBand, 
-                                           GDALClientDataset* poDS,
-                                           int nBand, GDALAccess eAccess,
-                                           int nRasterXSize, int nRasterYSize,
-                                           GDALDataType eDataType,
-                                           int nBlockXSize, int nBlockYSize,
+GDALClientRasterBand::GDALClientRasterBand(GDALPipe* pIn, int iSrvBandIn,
+                                           GDALClientDataset* poDSIn,
+                                           int nBandIn, GDALAccess eAccessIn,
+                                           int nRasterXSizeIn, int nRasterYSizeIn,
+                                           GDALDataType eDataTypeIn,
+                                           int nBlockXSizeIn, int nBlockYSizeIn,
                                            GByte abyCapsIn[16])
 {
-    this->p = p;
-    this->iSrvBand = iSrvBand;
-    this->poDS = poDS;
-    this->nBand = nBand;
-    this->eAccess = eAccess;
-    this->nRasterXSize = nRasterXSize;
-    this->nRasterYSize = nRasterYSize;
-    this->eDataType = eDataType;
-    this->nBlockXSize = nBlockXSize;
-    this->nBlockYSize = nBlockYSize;
+    p = pIn;
+    iSrvBand = iSrvBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
+    eAccess = eAccessIn;
+    nRasterXSize = nRasterXSizeIn;
+    nRasterYSize = nRasterYSizeIn;
+    eDataType = eDataTypeIn;
+    nBlockXSize = nBlockXSizeIn;
+    nBlockYSize = nBlockYSizeIn;
     papszCategoryNames = NULL;
     poColorTable = NULL;
     pszUnitType = NULL;
     poMaskBand = NULL;
     poRAT = NULL;
     memcpy(abyCaps, abyCapsIn, sizeof(abyCaps));
-    bEnableLineCaching = CSLTestBoolean(CPLGetConfigOption("GDAL_API_PROXY_LINE_CACHING", "YES"));
+    bEnableLineCaching = CPLTestBool(CPLGetConfigOption(
+        "GDAL_API_PROXY_LINE_CACHING", "YES"));
     nSuccessiveLinesRead = 0;
     eLastBufType = GDT_Unknown;
     nLastYOff = -1;
@@ -4137,7 +4418,7 @@ GDALClientRasterBand::~GDALClientRasterBand()
     std::map<CPLString, char**>::iterator oIterMD = aoMapMetadata.begin();
     for( ; oIterMD != aoMapMetadata.end(); ++oIterMD )
         CSLDestroy(oIterMD->second);
-    
+
     for(int i=0; i < (int)apoOldMaskBands.size(); i++)
         delete apoOldMaskBands[i];
 }
@@ -4211,14 +4492,14 @@ char ** GDALClientRasterBand::GetCategoryNames()
 /*                          SetCategoryNames()                          */
 /************************************************************************/
 
-CPLErr GDALClientRasterBand::SetCategoryNames( char ** papszCategoryNames )
+CPLErr GDALClientRasterBand::SetCategoryNames( char ** papszCategoryNamesIn )
 {
     if( !SupportsInstr(INSTR_Band_SetCategoryNames) )
-        return GDALPamRasterBand::SetCategoryNames(papszCategoryNames);
+        return GDALPamRasterBand::SetCategoryNames(papszCategoryNamesIn);
 
     CLIENT_ENTER();
     if( !WriteInstr(INSTR_Band_SetCategoryNames) ||
-        !GDALPipeWrite(p, papszCategoryNames) )
+        !GDALPipeWrite(p, papszCategoryNamesIn) )
         return CE_Failure;
     return CPLErrOnlyRet(p);
 }
@@ -4394,7 +4675,7 @@ CPLErr GDALClientRasterBand::SetColorInterpretation(GDALColorInterp eInterp)
 /************************************************************************/
 
 CPLErr GDALClientRasterBand::GetStatistics( int bApproxOK, int bForce,
-                                            double *pdfMin, double *pdfMax, 
+                                            double *pdfMin, double *pdfMax,
                                             double *pdfMean, double *pdfStdDev )
 {
     if( !SupportsInstr(INSTR_Band_GetStatistics) )
@@ -4402,10 +4683,10 @@ CPLErr GDALClientRasterBand::GetStatistics( int bApproxOK, int bForce,
             bApproxOK, bForce, pdfMin, pdfMax, pdfMean, pdfStdDev);
 
     CLIENT_ENTER();
-    if( !bApproxOK && CSLTestBoolean(CPLGetConfigOption("GDAL_API_PROXY_FORCE_APPROX", "NO")) )
+    if( !bApproxOK && CPLTestBool(CPLGetConfigOption("GDAL_API_PROXY_FORCE_APPROX", "NO")) )
         bApproxOK = TRUE;
     CPLErr eDefaultRet = CE_Failure;
-    if( CSLTestBoolean(CPLGetConfigOption("QGIS_HACK", "NO")) )
+    if( CPLTestBool(CPLGetConfigOption("QGIS_HACK", "NO")) )
     {
         if( pdfMin ) *pdfMin = 0;
         if( pdfMax ) *pdfMax = 255;
@@ -4446,9 +4727,9 @@ CPLErr GDALClientRasterBand::GetStatistics( int bApproxOK, int bForce,
 /*                         ComputeStatistics()                          */
 /************************************************************************/
 
-CPLErr GDALClientRasterBand::ComputeStatistics( int bApproxOK, 
+CPLErr GDALClientRasterBand::ComputeStatistics( int bApproxOK,
                                                 double *pdfMin,
-                                                double *pdfMax, 
+                                                double *pdfMax,
                                                 double *pdfMean,
                                                 double *pdfStdDev,
                                                 GDALProgressFunc pfnProgress,
@@ -4459,7 +4740,7 @@ CPLErr GDALClientRasterBand::ComputeStatistics( int bApproxOK,
             bApproxOK, pdfMin, pdfMax, pdfMean, pdfStdDev, pfnProgress, pProgressData);
 
     CLIENT_ENTER();
-    if( !bApproxOK && CSLTestBoolean(CPLGetConfigOption("GDAL_API_PROXY_FORCE_APPROX", "NO")) )
+    if( !bApproxOK && CPLTestBool(CPLGetConfigOption("GDAL_API_PROXY_FORCE_APPROX", "NO")) )
         bApproxOK = TRUE;
     if( !WriteInstr(INSTR_Band_ComputeStatistics) ||
         !GDALPipeWrite(p, bApproxOK) )
@@ -4491,7 +4772,7 @@ CPLErr GDALClientRasterBand::ComputeStatistics( int bApproxOK,
 /*                           SetStatistics()                            */
 /************************************************************************/
 
-CPLErr GDALClientRasterBand::SetStatistics( double dfMin, double dfMax, 
+CPLErr GDALClientRasterBand::SetStatistics( double dfMin, double dfMax,
                                         double dfMean, double dfStdDev )
 {
     if( !SupportsInstr(INSTR_Band_SetStatistics) )
@@ -4518,7 +4799,7 @@ CPLErr GDALClientRasterBand::ComputeRasterMinMax( int bApproxOK,
         return GDALPamRasterBand::ComputeRasterMinMax(bApproxOK, padfMinMax);
 
     CLIENT_ENTER();
-    if( !bApproxOK && CSLTestBoolean(CPLGetConfigOption("GDAL_API_PROXY_FORCE_APPROX", "NO")) )
+    if( !bApproxOK && CPLTestBool(CPLGetConfigOption("GDAL_API_PROXY_FORCE_APPROX", "NO")) )
         bApproxOK = TRUE;
     if( !WriteInstr(INSTR_Band_ComputeRasterMinMax) ||
         !GDALPipeWrite(p, bApproxOK) )
@@ -4543,11 +4824,11 @@ CPLErr GDALClientRasterBand::ComputeRasterMinMax( int bApproxOK,
 /*                            GetHistogram()                            */
 /************************************************************************/
 
-CPLErr GDALClientRasterBand::GetHistogram( double dfMin, double dfMax, 
-                                           int nBuckets, GUIntBig *panHistogram, 
+CPLErr GDALClientRasterBand::GetHistogram( double dfMin, double dfMax,
+                                           int nBuckets, GUIntBig *panHistogram,
                                            int bIncludeOutOfRange,
                                            int bApproxOK,
-                                           GDALProgressFunc pfnProgress, 
+                                           GDALProgressFunc pfnProgress,
                                            void *pProgressData )
 {
     if( !SupportsInstr(INSTR_Band_GetHistogram) )
@@ -4555,10 +4836,10 @@ CPLErr GDALClientRasterBand::GetHistogram( double dfMin, double dfMax,
             dfMin, dfMax, nBuckets, panHistogram, bIncludeOutOfRange, bApproxOK, pfnProgress, pProgressData);
 
     CLIENT_ENTER();
-    if( !bApproxOK && CSLTestBoolean(CPLGetConfigOption("GDAL_API_PROXY_FORCE_APPROX", "NO")) )
+    if( !bApproxOK && CPLTestBool(CPLGetConfigOption("GDAL_API_PROXY_FORCE_APPROX", "NO")) )
         bApproxOK = TRUE;
     CPLErr eDefaultRet = CE_Failure;
-    if( CSLTestBoolean(CPLGetConfigOption("QGIS_HACK", "NO")) )
+    if( CPLTestBool(CPLGetConfigOption("QGIS_HACK", "NO")) )
     {
         memset(panHistogram, 0, sizeof(GUIntBig) * nBuckets);
         eDefaultRet = CE_None;
@@ -4669,7 +4950,7 @@ CPLErr GDALClientRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
         !GDALPipeWrite(p, dfMin) ||
         !GDALPipeWrite(p, dfMax) ||
         !GDALPipeWrite(p, nBuckets) ||
-        !GDALPipeWrite(p, nBuckets * sizeof(GUIntBig), panHistogram) )
+        !GDALPipeWrite(p, nBuckets * (int)sizeof(GUIntBig), panHistogram) )
         return CE_Failure;
     return CPLErrOnlyRet(p);
 }
@@ -4699,7 +4980,7 @@ CPLErr GDALClientRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void* pI
         return eRet;
     int nSize;
     if( !GDALPipeRead(p, &nSize) ||
-        nSize != nBlockXSize * nBlockYSize * (GDALGetDataTypeSize(eDataType) / 8) ||
+        nSize != nBlockXSize * nBlockYSize * GDALGetDataTypeSizeBytes(eDataType) ||
         !GDALPipeRead_nolength(p, nSize, pImage) )
         return CE_Failure;
 
@@ -4719,7 +5000,8 @@ CPLErr GDALClientRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff, void* p
     InvalidateCachedLines();
 
     CLIENT_ENTER();
-    int nSize = nBlockXSize * nBlockYSize * (GDALGetDataTypeSize(eDataType) / 8);
+    const int nSize =
+        nBlockXSize * nBlockYSize * GDALGetDataTypeSizeBytes(eDataType);
     if( !WriteInstr(INSTR_Band_IWriteBlock) ||
         !GDALPipeWrite(p, nBlockXOff) ||
         !GDALPipeWrite(p, nBlockYOff) ||
@@ -4758,12 +5040,12 @@ CPLErr GDALClientRasterBand::IRasterIO_read_internal(
     int nSize;
     if( !GDALPipeRead(p, &nSize) )
         return CE_Failure;
-    int nDataTypeSize = GDALGetDataTypeSize(eBufType) / 8;
+    const int nDataTypeSize = GDALGetDataTypeSizeBytes(eBufType);
     GIntBig nExpectedSize = (GIntBig)nBufXSize * nBufYSize * nDataTypeSize;
     if( nSize != nExpectedSize )
         return CE_Failure;
     if( nPixelSpace == nDataTypeSize &&
-        nLineSpace == nBufXSize * nDataTypeSize )
+        nLineSpace == static_cast<GSpacing>(nBufXSize) * nDataTypeSize )
     {
         if( !GDALPipeRead_nolength(p, nSize, pData) )
             return CE_Failure;
@@ -4783,7 +5065,7 @@ CPLErr GDALClientRasterBand::IRasterIO_read_internal(
             GDALCopyWords( pBuf + j * nBufXSize * nDataTypeSize,
                             eBufType, nDataTypeSize,
                             (GByte*)pData + j * nLineSpace,
-                            eBufType, nPixelSpace,
+                            eBufType, static_cast<int>(nPixelSpace),
                             nBufXSize );
         }
         VSIFree(pBuf);
@@ -4818,7 +5100,7 @@ CPLErr GDALClientRasterBand::IRasterIO( GDALRWFlag eRWFlag,
         return GDALPamRasterBand::IRasterIO( eRWFlag,
                                              nXOff, nYOff, nXSize, nYSize,
                                              pData, nBufXSize, nBufYSize,
-                                             eBufType, 
+                                             eBufType,
                                              nPixelSpace, nLineSpace, psExtraArg );
 
     CLIENT_ENTER();
@@ -4838,7 +5120,7 @@ CPLErr GDALClientRasterBand::IRasterIO( GDALRWFlag eRWFlag,
             nXOff == 0 && nXSize == nRasterXSize && nYSize == 1 &&
             nBufXSize == nXSize && nBufYSize == nYSize )
         {
-            int nBufTypeSize = GDALGetDataTypeSize(eBufType) / 8;
+            const int nBufTypeSize = GDALGetDataTypeSizeBytes(eBufType);
 
             /* Is the current line already cached ? */
             if( nCachedYStart >= 0 &&
@@ -4847,10 +5129,11 @@ CPLErr GDALClientRasterBand::IRasterIO( GDALRWFlag eRWFlag,
             {
                 nSuccessiveLinesRead ++;
 
-                int nCachedBufTypeSize = GDALGetDataTypeSize(eCachedBufType) / 8;
+                const int nCachedBufTypeSize =
+                    GDALGetDataTypeSizeBytes(eCachedBufType);
                 GDALCopyWords(pabyCachedLines + (nYOff - nCachedYStart) * nXSize * nCachedBufTypeSize,
                               eCachedBufType, nCachedBufTypeSize,
-                              pData, eBufType, nPixelSpace,
+                              pData, eBufType, static_cast<int>(nPixelSpace),
                               nXSize);
                 nLastYOff = nYOff;
                 eLastBufType = eBufType;
@@ -4878,16 +5161,18 @@ CPLErr GDALClientRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                         eRet = IRasterIO_read_internal( nXOff, nYOff, nXSize, nLinesToRead,
                                                         pabyCachedLines, nXSize, nLinesToRead,
                                                         eBufType,
-                                                        nBufTypeSize, nBufTypeSize * nXSize );
+                                                        nBufTypeSize,
+                                                        static_cast<GSpacing>(nBufTypeSize) * nXSize );
                         if( eRet == CE_None )
                         {
                             eCachedBufType = eBufType;
                             nCachedYStart = nYOff;
 
-                            int nCachedBufTypeSize = GDALGetDataTypeSize(eCachedBufType) / 8;
+                            const int nCachedBufTypeSize =
+                                  GDALGetDataTypeSizeBytes(eCachedBufType);
                             GDALCopyWords(pabyCachedLines + (nYOff - nCachedYStart) * nXSize * nCachedBufTypeSize,
                                         eCachedBufType, nCachedBufTypeSize,
-                                        pData, eBufType, nPixelSpace,
+                                        pData, eBufType, static_cast<int>(nPixelSpace),
                                         nXSize);
                             nLastYOff = nYOff;
                             eLastBufType = eBufType;
@@ -4927,13 +5212,13 @@ CPLErr GDALClientRasterBand::IRasterIO( GDALRWFlag eRWFlag,
             !GDALPipeWrite(p, eBufType) )
             return CE_Failure;
 
-        int nDataTypeSize = GDALGetDataTypeSize(eBufType) / 8;
+        const int nDataTypeSize = GDALGetDataTypeSizeBytes(eBufType);
         GIntBig nSizeBig = (GIntBig)nBufXSize * nBufYSize * nDataTypeSize;
         int nSize = (int)nSizeBig;
         if( nSizeBig != nSize )
             return CE_Failure;
         if( nPixelSpace == nDataTypeSize &&
-            nLineSpace == nBufXSize * nDataTypeSize )
+            nLineSpace == static_cast<GSpacing>(nBufXSize) * nDataTypeSize )
         {
             if( !GDALPipeWrite(p, nSize, pData) )
                 return CE_Failure;
@@ -4946,7 +5231,7 @@ CPLErr GDALClientRasterBand::IRasterIO( GDALRWFlag eRWFlag,
             for(int j=0;j<nBufYSize;j++)
             {
                 GDALCopyWords( (GByte*)pData + j * nLineSpace,
-                               eBufType, nPixelSpace,
+                               eBufType, static_cast<int>(nPixelSpace),
                                pBuf + j * nBufXSize * nDataTypeSize,
                                eBufType, nDataTypeSize,
                                nBufXSize );
@@ -5181,15 +5466,15 @@ CPLErr GDALClientRasterBand::SetUnitType( const char * pszUnit )
 /*                           SetColorTable()                            */
 /************************************************************************/
 
-CPLErr GDALClientRasterBand::SetColorTable(GDALColorTable* poColorTable)
+CPLErr GDALClientRasterBand::SetColorTable(GDALColorTable* poColorTableIn)
 {
     if( !SupportsInstr(INSTR_Band_SetColorTable) )
-        return GDALPamRasterBand::SetColorTable(poColorTable);
+        return GDALPamRasterBand::SetColorTable(poColorTableIn);
 
     CLIENT_ENTER();
     if( !WriteInstr(INSTR_Band_SetColorTable) )
         return CE_Failure;
-    if( !GDALPipeWrite(p, poColorTable) )
+    if( !GDALPipeWrite(p, poColorTableIn) )
         return CE_Failure;
     return CPLErrOnlyRet(p);
 }
@@ -5220,6 +5505,22 @@ CPLErr GDALClientRasterBand::SetNoDataValue( double dfVal )
 }
 
 /************************************************************************/
+/*                         DeleteNoDataValue()                          */
+/************************************************************************/
+
+CPLErr GDALClientRasterBand::DeleteNoDataValue()
+{
+    if( !SupportsInstr(INSTR_Band_DeleteNoDataValue) )
+        return GDALPamRasterBand::DeleteNoDataValue();
+
+
+    CLIENT_ENTER();
+    if( !WriteInstr(INSTR_Band_DeleteNoDataValue) )
+        return CE_Failure;
+    return CPLErrOnlyRet(p);
+}
+
+/************************************************************************/
 /*                             SetScale()                               */
 /************************************************************************/
 
@@ -5266,7 +5567,7 @@ GDALRasterBand *GDALClientRasterBand::GetOverview(int iOverview)
 
     if( !GDALSkipUntilEndOfJunkMarker(p) )
         return NULL;
-    
+
     GDALRasterBand* poBand = NULL;
     if( !GDALPipeRead(p, (GDALClientDataset*) NULL, &poBand, abyCaps) )
         return NULL;
@@ -5321,27 +5622,27 @@ int GDALClientRasterBand::GetMaskFlags()
         return 0;
     if( !GDALSkipUntilEndOfJunkMarker(p) )
         return 0;
-    int nFlags;
-    if( !GDALPipeRead(p, &nFlags) )
+    int l_nFlags;
+    if( !GDALPipeRead(p, &l_nFlags) )
         return 0;
     GDALConsumeErrors(p);
-    return nFlags;
+    return l_nFlags;
 }
 
 /************************************************************************/
 /*                           CreateMaskBand()                           */
 /************************************************************************/
 
-CPLErr GDALClientRasterBand::CreateMaskBand( int nFlags )
+CPLErr GDALClientRasterBand::CreateMaskBand( int nFlagsIn )
 {
     if( !SupportsInstr(INSTR_Band_CreateMaskBand) )
-        return GDALPamRasterBand::CreateMaskBand(nFlags);
+        return GDALPamRasterBand::CreateMaskBand(nFlagsIn);
 
     CLIENT_ENTER();
     GDALPipeWriteConfigOption(p, "GDAL_TIFF_INTERNAL_MASK_TO_8BIT", bRecycleChild);
     GDALPipeWriteConfigOption(p, "GDAL_TIFF_INTERNAL_MASK", bRecycleChild);
     if( !WriteInstr(INSTR_Band_CreateMaskBand) ||
-        !GDALPipeWrite(p, nFlags) )
+        !GDALPipeWrite(p, nFlagsIn) )
         return CE_Failure;
     CPLErr eErr = CPLErrOnlyRet(p);
     if( eErr == CE_None && poMaskBand != NULL )
@@ -5391,7 +5692,7 @@ CPLErr GDALClientRasterBand::BuildOverviews( const char * pszResampling,
     if( !WriteInstr(INSTR_Band_BuildOverviews) ||
         !GDALPipeWrite(p, pszResampling) ||
         !GDALPipeWrite(p, nOverviews) ||
-        !GDALPipeWrite(p, nOverviews * sizeof(int), panOverviewList) )
+        !GDALPipeWrite(p, nOverviews * (int)sizeof(int), panOverviewList) )
         return CE_Failure;
     return CPLErrOnlyRet(p);
 }
@@ -5414,7 +5715,7 @@ GDALRasterAttributeTable *GDALClientRasterBand::GetDefaultRAT()
     GDALRasterAttributeTable* poNewRAT = NULL;
     if( !GDALPipeRead(p, &poNewRAT) )
         return NULL;
-    
+
     if( poNewRAT != NULL && poRAT != NULL )
     {
         *poRAT = *poNewRAT;
@@ -5438,14 +5739,14 @@ GDALRasterAttributeTable *GDALClientRasterBand::GetDefaultRAT()
 /*                           SetDefaultRAT()                            */
 /************************************************************************/
 
-CPLErr GDALClientRasterBand::SetDefaultRAT( const GDALRasterAttributeTable * poRAT )
+CPLErr GDALClientRasterBand::SetDefaultRAT( const GDALRasterAttributeTable * poRATIn )
 {
     if( !SupportsInstr(INSTR_Band_SetDefaultRAT) )
-        return GDALPamRasterBand::SetDefaultRAT(poRAT);
+        return GDALPamRasterBand::SetDefaultRAT(poRATIn);
 
     CLIENT_ENTER();
     if( !WriteInstr(INSTR_Band_SetDefaultRAT) ||
-        !GDALPipeWrite(p, poRAT) )
+        !GDALPipeWrite(p, poRATIn) )
         return CE_Failure;
     return CPLErrOnlyRet(p);
 }
@@ -5455,7 +5756,7 @@ CPLErr GDALClientRasterBand::SetDefaultRAT( const GDALRasterAttributeTable * poR
 /************************************************************************/
 
 CPLErr GDALClientRasterBand::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
-                                     int nBufXSize, int nBufYSize, 
+                                     int nBufXSize, int nBufYSize,
                                      GDALDataType eDT, char **papszOptions )
 {
     if( !SupportsInstr(INSTR_Band_AdviseRead) )
@@ -5483,17 +5784,18 @@ CPLErr GDALClientRasterBand::AdviseRead( int nXOff, int nYOff, int nXSize, int n
 
 GDALClientDataset* GDALClientDataset::CreateAndConnect()
 {
-    GDALServerSpawnedProcess* ssp = GDALServerSpawnAsync();
-    if( ssp == NULL )
+    GDALServerSpawnedProcess* l_ssp = GDALServerSpawnAsync();
+    if( l_ssp == NULL )
         return NULL;
-    return new GDALClientDataset(ssp);
+    return new GDALClientDataset(l_ssp);
 }
 
 /************************************************************************/
 /*                                Init()                                */
 /************************************************************************/
 
-int GDALClientDataset::Init(const char* pszFilename, GDALAccess eAccess)
+int GDALClientDataset::Init(const char* pszFilename, GDALAccess eAccessIn,
+                            char** papszOpenOptionsIn)
 {
     // FIXME find a way of transmitting the relevant config options to the forked Open() ?
     GDALPipeWriteConfigOption(p, "GTIFF_POINT_GEO_IGNORE", bRecycleChild);
@@ -5514,9 +5816,10 @@ int GDALClientDataset::Init(const char* pszFilename, GDALAccess eAccess)
     char* pszCWD = CPLGetCurrentDir();
 
     if( !GDALPipeWrite(p, INSTR_Open) ||
-        !GDALPipeWrite(p, eAccess) ||
+        !GDALPipeWrite(p, eAccessIn) ||
         !GDALPipeWrite(p, pszFilename) ||
-        !GDALPipeWrite(p, pszCWD))
+        !GDALPipeWrite(p, pszCWD) ||
+        !GDALPipeWrite(p, papszOpenOptionsIn))
     {
         CPLFree(pszCWD);
         return FALSE;
@@ -5537,7 +5840,7 @@ int GDALClientDataset::Init(const char* pszFilename, GDALAccess eAccess)
     if( !GDALPipeRead(p, sizeof(abyCaps), abyCaps) )
         return FALSE;
 
-    this->eAccess = eAccess;
+    eAccess = eAccessIn;
 
     char* pszDescription = NULL;
     if( !GDALPipeRead(p, &pszDescription) )
@@ -5558,7 +5861,7 @@ int GDALClientDataset::Init(const char* pszFilename, GDALAccess eAccess)
         CPLFree(pszDriverName);
         pszDriverName = NULL;
 
-        while(TRUE)
+        while(true)
         {
             char* pszKey = NULL, *pszVal = NULL;
             if( !GDALPipeRead(p, &pszKey) )
@@ -5638,7 +5941,7 @@ static int IsSeparateExecutable()
 const char* GDALClientDatasetGetFilename(const char* pszFilename)
 {
     const char* pszSpawn;
-    if( EQUALN(pszFilename, "API_PROXY:", strlen("API_PROXY:")) )
+    if( STARTS_WITH_CI(pszFilename, "API_PROXY:") )
     {
         pszFilename += strlen("API_PROXY:");
         pszSpawn = "YES";
@@ -5657,12 +5960,12 @@ const char* GDALClientDatasetGetFilename(const char* pszFilename)
      /* /vsistdin/ and /vsistdout/ can work on Unix in the fork() only context (i.e. GDAL_API_PROXY_SERVER undefined) */
      /* since the forked process will inherit the same descriptors as the parent */
 
-    if( EQUALN(pszFilename, "MEM:::", 6) ||
+    if( STARTS_WITH_CI(pszFilename, "MEM:::") ||
         strstr(pszFilename, "/vsimem/") != NULL ||
         strstr(pszFilename, "/vsimem\\") != NULL ||
         (strstr(pszFilename, "/vsistdout/") != NULL && IsSeparateExecutable()) ||
         (strstr(pszFilename, "/vsistdin/") != NULL && IsSeparateExecutable()) ||
-        EQUALN(pszFilename,"NUMPY:::",8) )
+        STARTS_WITH_CI(pszFilename, "NUMPY:::") )
         return NULL;
 
     if( !(EQUAL(pszSpawn, "YES") || EQUAL(pszSpawn, "ON") ||
@@ -5723,7 +6026,8 @@ GDALDataset *GDALClientDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
 
     CPLErrorReset();
-    if( !poDS->Init(pszFilename, poOpenInfo->eAccess) )
+    if( !poDS->Init(pszFilename, poOpenInfo->eAccess,
+                    poOpenInfo->papszOpenOptions) )
     {
         if( CPLGetLastErrorType() == 0 )
         {
@@ -5752,19 +6056,19 @@ int GDALClientDataset::Identify( GDALOpenInfo * poOpenInfo )
 
     CLIENT_ENTER();
 
-    GDALServerSpawnedProcess* ssp = GDALServerSpawnAsync();
-    if( ssp == NULL )
+    GDALServerSpawnedProcess* l_ssp = GDALServerSpawnAsync();
+    if( l_ssp == NULL )
         return FALSE;
 
     char* pszCWD = CPLGetCurrentDir();
 
-    GDALPipe* p = ssp->p;
-    if( !GDALPipeWrite(p, INSTR_Identify) ||
-        !GDALPipeWrite(p, pszFilename) ||
-        !GDALPipeWrite(p, pszCWD) ||
-        !GDALSkipUntilEndOfJunkMarker(p) )
+    GDALPipe* l_p = l_ssp->p;
+    if( !GDALPipeWrite(l_p, INSTR_Identify) ||
+        !GDALPipeWrite(l_p, pszFilename) ||
+        !GDALPipeWrite(l_p, pszCWD) ||
+        !GDALSkipUntilEndOfJunkMarker(l_p) )
     {
-        GDALServerSpawnAsyncFinish(ssp);
+        GDALServerSpawnAsyncFinish(l_ssp);
         CPLFree(pszCWD);
         return FALSE;
     }
@@ -5772,13 +6076,13 @@ int GDALClientDataset::Identify( GDALOpenInfo * poOpenInfo )
     CPLFree(pszCWD);
 
     int bRet;
-    if( !GDALPipeRead(p, &bRet) )
+    if( !GDALPipeRead(l_p, &bRet) )
     {
-        GDALServerSpawnAsyncFinish(ssp);
+        GDALServerSpawnAsyncFinish(l_ssp);
         return FALSE;
     }
 
-    GDALServerSpawnAsyncFinish(ssp);
+    GDALServerSpawnAsyncFinish(l_ssp);
     return bRet;
 }
 
@@ -5809,7 +6113,7 @@ static int GDALClientDatasetQuietDelete(GDALPipe* p,
 
 int GDALClientDataset::mCreateCopy( const char* pszFilename,
                                     GDALDataset* poSrcDS,
-                                    int bStrict, char** papszOptions, 
+                                    int bStrict, char** papszOptions,
                                     GDALProgressFunc pfnProgress,
                                     void * pProgressData )
 {
@@ -5876,16 +6180,16 @@ int GDALClientDataset::mCreateCopy( const char* pszFilename,
 
     GDALConsumeErrors(p);
 
-    return Init(NULL, GA_Update);
+    return Init(NULL, GA_Update, NULL);
 }
 
 /************************************************************************/
 /*                          CreateCopy()                                */
 /************************************************************************/
 
-GDALDataset *GDALClientDataset::CreateCopy( const char * pszFilename, 
+GDALDataset *GDALClientDataset::CreateCopy( const char * pszFilename,
                                             GDALDataset * poSrcDS, int bStrict,
-                                            char ** papszOptions, 
+                                            char ** papszOptions,
                                             GDALProgressFunc pfnProgress,
                                             void * pProgressData )
 {
@@ -5908,7 +6212,7 @@ GDALDataset *GDALClientDataset::CreateCopy( const char * pszFilename,
 /************************************************************************/
 
 int GDALClientDataset::mCreate( const char * pszFilename,
-                            int nXSize, int nYSize, int nBands,
+                            int nXSize, int nYSize, int nBandsIn,
                             GDALDataType eType,
                             char ** papszOptions )
 {
@@ -5945,7 +6249,7 @@ int GDALClientDataset::mCreate( const char * pszFilename,
         !GDALPipeWrite(p, pszCWD) ||
         !GDALPipeWrite(p, nXSize) ||
         !GDALPipeWrite(p, nYSize) ||
-        !GDALPipeWrite(p, nBands) ||
+        !GDALPipeWrite(p, nBandsIn) ||
         !GDALPipeWrite(p, eType) ||
         !GDALPipeWrite(p, papszOptions) )
     {
@@ -5967,7 +6271,7 @@ int GDALClientDataset::mCreate( const char * pszFilename,
 
     GDALConsumeErrors(p);
 
-    return Init(NULL, GA_Update);
+    return Init(NULL, GA_Update, NULL);
 }
 
 /************************************************************************/
@@ -5975,14 +6279,14 @@ int GDALClientDataset::mCreate( const char * pszFilename,
 /************************************************************************/
 
 GDALDataset* GDALClientDataset::Create( const char * pszName,
-                                    int nXSize, int nYSize, int nBands,
+                                    int nXSize, int nYSize, int nBandsIn,
                                     GDALDataType eType,
                                     char ** papszOptions )
 {
     CLIENT_ENTER();
 
     GDALClientDataset* poDS = CreateAndConnect();
-    if( poDS != NULL && !poDS->mCreate(pszName, nXSize, nYSize, nBands,
+    if( poDS != NULL && !poDS->mCreate(pszName, nXSize, nYSize, nBandsIn,
                                        eType, papszOptions) )
     {
         delete poDS;
@@ -6005,18 +6309,18 @@ CPLErr GDALClientDataset::Delete( const char * pszFilename )
 
     CLIENT_ENTER();
 
-    GDALServerSpawnedProcess* ssp = GDALServerSpawnAsync();
-    if( ssp == NULL )
+    GDALServerSpawnedProcess* l_ssp = GDALServerSpawnAsync();
+    if( l_ssp == NULL )
         return CE_Failure;
 
-    GDALPipe* p = ssp->p;
-    if( !GDALClientDatasetQuietDelete(p, pszFilename) )
+    GDALPipe* l_p = l_ssp->p;
+    if( !GDALClientDatasetQuietDelete(l_p, pszFilename) )
     {
-        GDALServerSpawnAsyncFinish(ssp);
+        GDALServerSpawnAsyncFinish(l_ssp);
         return CE_Failure;
     }
 
-    GDALServerSpawnAsyncFinish(ssp);
+    GDALServerSpawnAsyncFinish(l_ssp);
     return CE_None;
 }
 
@@ -6052,11 +6356,11 @@ GDALDriver* GDALGetAPIPROXYDriver()
     CPLMutexHolderD(GDALGetphDMMutex());
     if( poAPIPROXYDriver == NULL )
     {
-#ifdef DEBUG
-        CPLAssert(INSTR_END + 1 == sizeof(apszInstr) / sizeof(apszInstr[0]));
+#ifdef DEBUG_VERBOSE
+        CPL_STATIC_ASSERT(INSTR_END + 1 == sizeof(apszInstr) / sizeof(apszInstr[0]));
 #endif
         /* If asserted, change GDAL_CLIENT_SERVER_PROTOCOL_MAJOR / GDAL_CLIENT_SERVER_PROTOCOL_MINOR */
-        CPLAssert(INSTR_END + 1 == 80);
+        CPL_STATIC_ASSERT(INSTR_END + 1 == 81);
 
         const char* pszConnPool = CPLGetConfigOption("GDAL_API_PROXY_CONN_POOL", "YES");
         if( atoi(pszConnPool) > 0 )
@@ -6064,7 +6368,7 @@ GDALDriver* GDALGetAPIPROXYDriver()
             bRecycleChild = TRUE;
             nMaxRecycled = MIN(atoi(pszConnPool), MAX_RECYCLED);
         }
-        else if( CSLTestBoolean(pszConnPool) )
+        else if( CPLTestBool(pszConnPool) )
         {
             bRecycleChild = TRUE;
             nMaxRecycled = DEFAULT_RECYCLED;
@@ -6075,7 +6379,7 @@ GDALDriver* GDALGetAPIPROXYDriver()
 
         poAPIPROXYDriver->SetDescription( "API_PROXY" );
         poAPIPROXYDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poAPIPROXYDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
+        poAPIPROXYDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
                                    "API_PROXY" );
 
         poAPIPROXYDriver->pfnOpen = GDALClientDataset::Open;
diff --git a/gcore/gdalcolortable.cpp b/gcore/gdalcolortable.cpp
index 2adaad8..a597edf 100644
--- a/gcore/gdalcolortable.cpp
+++ b/gcore/gdalcolortable.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalcolortable.cpp 28082 2014-12-05 18:06:30Z rouault $
+ * $Id: gdalcolortable.cpp 33694 2016-03-10 17:54:30Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Color table implementation.
@@ -30,7 +30,7 @@
 
 #include "gdal_priv.h"
 
-CPL_CVSID("$Id: gdalcolortable.cpp 28082 2014-12-05 18:06:30Z rouault $");
+CPL_CVSID("$Id: gdalcolortable.cpp 33694 2016-03-10 17:54:30Z goatbar $");
 
 /************************************************************************/
 /*                           GDALColorTable()                           */
@@ -42,14 +42,12 @@ CPL_CVSID("$Id: gdalcolortable.cpp 28082 2014-12-05 18:06:30Z rouault $");
  * This constructor is the same as the C GDALCreateColorTable() function.
  *
  * @param eInterpIn the interpretation to be applied to GDALColorEntry
- * values. 
+ * values.
  */
 
-GDALColorTable::GDALColorTable( GDALPaletteInterp eInterpIn )
-
-{
-    eInterp = eInterpIn;
-}
+GDALColorTable::GDALColorTable( GDALPaletteInterp eInterpIn ) :
+    eInterp(eInterpIn)
+{}
 
 /************************************************************************/
 /*                        GDALCreateColorTable()                        */
@@ -63,7 +61,7 @@ GDALColorTable::GDALColorTable( GDALPaletteInterp eInterpIn )
 GDALColorTableH CPL_STDCALL GDALCreateColorTable( GDALPaletteInterp eInterp )
 
 {
-    return (GDALColorTableH) (new GDALColorTable( eInterp ));
+    return reinterpret_cast<GDALColorTableH>( new GDALColorTable( eInterp ) );
 }
 
 
@@ -74,13 +72,10 @@ GDALColorTableH CPL_STDCALL GDALCreateColorTable( GDALPaletteInterp eInterp )
 /**
  * \brief Destructor.
  *
- * This descructor is the same as the C GDALDestroyColorTable() function.
+ * This destructor is the same as the C GDALDestroyColorTable() function.
  */
 
-GDALColorTable::~GDALColorTable()
-
-{
-}
+GDALColorTable::~GDALColorTable() {}
 
 /************************************************************************/
 /*                       GDALDestroyColorTable()                        */
@@ -94,7 +89,7 @@ GDALColorTable::~GDALColorTable()
 void CPL_STDCALL GDALDestroyColorTable( GDALColorTableH hTable )
 
 {
-    delete (GDALColorTable *) hTable;
+    delete reinterpret_cast<GDALColorTable *>( hTable );
 }
 
 /************************************************************************/
@@ -116,8 +111,8 @@ const GDALColorEntry *GDALColorTable::GetColorEntry( int i ) const
 {
     if( i < 0 || i >= static_cast<int>(aoEntries.size()) )
         return NULL;
-    else
-        return &aoEntries[i];
+
+    return &aoEntries[i];
 }
 
 /************************************************************************/
@@ -130,13 +125,13 @@ const GDALColorEntry *GDALColorTable::GetColorEntry( int i ) const
  *
  * This function is the same as the C++ method GDALColorTable::GetColorEntry()
  */
-const GDALColorEntry * CPL_STDCALL 
+const GDALColorEntry * CPL_STDCALL
 GDALGetColorEntry( GDALColorTableH hTable, int i )
 
 {
     VALIDATE_POINTER1( hTable, "GDALGetColorEntry", NULL );
 
-    return ((GDALColorTable *) hTable)->GetColorEntry( i );
+    return reinterpret_cast<GDALColorTable *>( hTable )->GetColorEntry( i );
 }
 
 
@@ -166,7 +161,7 @@ int GDALColorTable::GetColorEntryAsRGB( int i, GDALColorEntry *poEntry ) const
 {
     if( eInterp != GPI_RGB || i < 0 || i >= static_cast<int>(aoEntries.size()) )
         return FALSE;
-    
+
     *poEntry = aoEntries[i];
     return TRUE;
 }
@@ -180,14 +175,15 @@ int GDALColorTable::GetColorEntryAsRGB( int i, GDALColorEntry *poEntry ) const
  *
  * This function is the same as the C++ method GDALColorTable::GetColorEntryAsRGB()
  */
-int CPL_STDCALL GDALGetColorEntryAsRGB( GDALColorTableH hTable, int i, 
+int CPL_STDCALL GDALGetColorEntryAsRGB( GDALColorTableH hTable, int i,
                             GDALColorEntry *poEntry )
 
 {
     VALIDATE_POINTER1( hTable, "GDALGetColorEntryAsRGB", 0 );
     VALIDATE_POINTER1( poEntry, "GDALGetColorEntryAsRGB", 0 );
 
-    return ((GDALColorTable *) hTable)->GetColorEntryAsRGB( i, poEntry );
+    return reinterpret_cast<GDALColorTable *>( hTable )->
+        GetColorEntryAsRGB( i, poEntry );
 }
 
 /************************************************************************/
@@ -201,7 +197,7 @@ int CPL_STDCALL GDALGetColorEntryAsRGB( GDALColorTableH hTable, int i,
  * to it is maintained.  Also, the passed in entry must match the color
  * interpretation of the table to which it is being assigned.
  *
- * The table is grown as needed to hold the supplied offset.  
+ * The table is grown as needed to hold the supplied offset.
  *
  * This function is the same as the C function GDALSetColorEntry().
  *
@@ -214,7 +210,7 @@ void GDALColorTable::SetColorEntry( int i, const GDALColorEntry * poEntry )
 {
     if( i < 0 )
         return;
-    
+
     try
     {
         if( i >= static_cast<int>(aoEntries.size()) )
@@ -223,7 +219,7 @@ void GDALColorTable::SetColorEntry( int i, const GDALColorEntry * poEntry )
             oBlack.c1 = oBlack.c2 = oBlack.c3 = oBlack.c4 = 0;
             aoEntries.resize(i+1, oBlack);
         }
-    
+
         aoEntries[i] = *poEntry;
     }
     catch(std::exception &e)
@@ -241,14 +237,14 @@ void GDALColorTable::SetColorEntry( int i, const GDALColorEntry * poEntry )
  *
  * This function is the same as the C++ method GDALColorTable::SetColorEntry()
  */
-void CPL_STDCALL GDALSetColorEntry( GDALColorTableH hTable, int i, 
+void CPL_STDCALL GDALSetColorEntry( GDALColorTableH hTable, int i,
                         const GDALColorEntry * poEntry )
 
 {
     VALIDATE_POINTER0( hTable, "GDALSetColorEntry" );
     VALIDATE_POINTER0( poEntry, "GDALSetColorEntry" );
 
-    ((GDALColorTable *) hTable)->SetColorEntry( i, poEntry );
+    reinterpret_cast<GDALColorTable *>( hTable )->SetColorEntry( i, poEntry );
 }
 
 
@@ -282,7 +278,8 @@ GDALColorTableH CPL_STDCALL GDALCloneColorTable( GDALColorTableH hTable )
 {
     VALIDATE_POINTER1( hTable, "GDALCloneColorTable", NULL );
 
-    return (GDALColorTableH) ((GDALColorTable *) hTable)->Clone();
+    return reinterpret_cast<GDALColorTableH>(
+        reinterpret_cast<GDALColorTable *>( hTable )->Clone() );
 }
 
 /************************************************************************/
@@ -300,7 +297,7 @@ GDALColorTableH CPL_STDCALL GDALCloneColorTable( GDALColorTableH hTable )
 int GDALColorTable::GetColorEntryCount() const
 
 {
-    return aoEntries.size();
+    return static_cast<int>(aoEntries.size());
 }
 
 /************************************************************************/
@@ -310,14 +307,15 @@ int GDALColorTable::GetColorEntryCount() const
 /**
  * \brief Get number of color entries in table.
  *
- * This function is the same as the C++ method GDALColorTable::GetColorEntryCount()
+ * This function is the same as the C++ method
+ * GDALColorTable::GetColorEntryCount()
  */
 int CPL_STDCALL GDALGetColorEntryCount( GDALColorTableH hTable )
 
 {
     VALIDATE_POINTER1( hTable, "GDALGetColorEntryCount", 0 );
 
-    return ((GDALColorTable *) hTable)->GetColorEntryCount();
+    return reinterpret_cast<GDALColorTable *>( hTable )->GetColorEntryCount();
 }
 
 /************************************************************************/
@@ -327,7 +325,7 @@ int CPL_STDCALL GDALGetColorEntryCount( GDALColorTableH hTable )
 /**
  * \brief Fetch palette interpretation.
  *
- * The returned value is used to interprete the values in the GDALColorEntry.
+ * The returned value is used to interpret the values in the GDALColorEntry.
  *
  * This method is the same as the C function GDALGetPaletteInterpretation().
  *
@@ -347,15 +345,17 @@ GDALPaletteInterp GDALColorTable::GetPaletteInterpretation() const
 /**
  * \brief Fetch palette interpretation.
  *
- * This function is the same as the C++ method GDALColorTable::GetPaletteInterpretation()
+ * This function is the same as the C++ method
+ * GDALColorTable::GetPaletteInterpretation()
  */
-GDALPaletteInterp CPL_STDCALL 
+GDALPaletteInterp CPL_STDCALL
 GDALGetPaletteInterpretation( GDALColorTableH hTable )
 
 {
     VALIDATE_POINTER1( hTable, "GDALGetPaletteInterpretation", GPI_Gray );
 
-    return ((GDALColorTable *) hTable)->GetPaletteInterpretation();
+    return reinterpret_cast<GDALColorTable *>( hTable )->
+        GetPaletteInterpretation();
 }
 
 /**
@@ -396,7 +396,7 @@ int GDALColorTable::CreateColorRamp(
 
     /* calculate number of colors in-between */
 
-    int nColors = nEndIndex - nStartIndex;
+    const int nColors = nEndIndex - nStartIndex;
 
     /* set starting color */
 
@@ -413,25 +413,29 @@ int GDALColorTable::CreateColorRamp(
 
     /* calculate the slope of the linear transformation */
 
-    double dfSlope1, dfSlope2, dfSlope3, dfSlope4;
-
-    dfSlope1 = ( psEndColor->c1 - psStartColor->c1 ) / (double) nColors;
-    dfSlope2 = ( psEndColor->c2 - psStartColor->c2 ) / (double) nColors;
-    dfSlope3 = ( psEndColor->c3 - psStartColor->c3 ) / (double) nColors;
-    dfSlope4 = ( psEndColor->c4 - psStartColor->c4 ) / (double) nColors;
+    const double dfSlope1 = ( psEndColor->c1 - psStartColor->c1 )
+        / static_cast<double>( nColors );
+    const double dfSlope2 = ( psEndColor->c2 - psStartColor->c2 )
+        / static_cast<double>( nColors );
+    const double dfSlope3 = ( psEndColor->c3 - psStartColor->c3 )
+        / static_cast<double>( nColors );
+    const double dfSlope4 = ( psEndColor->c4 - psStartColor->c4 )
+        / static_cast<double>( nColors );
 
     /* loop through the new colors */
 
     GDALColorEntry sColor = *psStartColor;
 
-    int i;
-
-    for( i = 1; i < nColors; i++ )
+    for( int i = 1; i < nColors; i++ )
     {
-        sColor.c1 = (short) ( i * dfSlope1 + (double) psStartColor->c1 );
-        sColor.c2 = (short) ( i * dfSlope2 + (double) psStartColor->c2 );
-        sColor.c3 = (short) ( i * dfSlope3 + (double) psStartColor->c3 );
-        sColor.c4 = (short) ( i * dfSlope4 + (double) psStartColor->c4 );
+        sColor.c1 = static_cast<short>(
+            i * dfSlope1 + static_cast<double>( psStartColor->c1 ) );
+        sColor.c2 = static_cast<short>(
+            i * dfSlope2 + static_cast<double>( psStartColor->c2 ) );
+        sColor.c3 = static_cast<short>(
+            i * dfSlope3 + static_cast<double>( psStartColor->c3 ) );
+        sColor.c4 = static_cast<short>(
+            i * dfSlope4 + static_cast<double>( psStartColor->c4 ) );
 
         SetColorEntry( nStartIndex + i, &sColor );
     }
@@ -450,15 +454,16 @@ int GDALColorTable::CreateColorRamp(
  *
  * This function is the same as the C++ method GDALColorTable::CreateColorRamp()
  */
-void CPL_STDCALL 
-GDALCreateColorRamp( GDALColorTableH hTable, 
+void CPL_STDCALL
+GDALCreateColorRamp( GDALColorTableH hTable,
             int nStartIndex, const GDALColorEntry *psStartColor,
             int nEndIndex, const GDALColorEntry *psEndColor )
 {
     VALIDATE_POINTER0( hTable, "GDALCreateColorRamp" );
 
-    ((GDALColorTable *) hTable)->CreateColorRamp( nStartIndex, psStartColor, 
-                                                  nEndIndex, psEndColor );
+    reinterpret_cast<GDALColorTable *>( hTable )->
+        CreateColorRamp( nStartIndex, psStartColor,
+                         nEndIndex, psEndColor );
 }
 
 /************************************************************************/
@@ -477,5 +482,6 @@ int GDALColorTable::IsSame(const GDALColorTable* poOtherCT) const
 {
     return aoEntries.size() == poOtherCT->aoEntries.size() &&
            (aoEntries.size() == 0 ||
-            memcmp(&aoEntries[0], &poOtherCT->aoEntries[0], aoEntries.size() * sizeof(GDALColorEntry)) == 0);
+            memcmp(&aoEntries[0], &poOtherCT->aoEntries[0], aoEntries.size()
+                   * sizeof(GDALColorEntry)) == 0);
 }
diff --git a/gcore/gdaldataset.cpp b/gcore/gdaldataset.cpp
index d6ec1bc..cf1cf3d 100644
--- a/gcore/gdaldataset.cpp
+++ b/gcore/gdaldataset.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: gdaldataset.cpp 31109 2015-10-23 19:53:08Z rouault $
+ * $Id: gdaldataset.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  GDAL Core
- * Purpose:  Base class for raster file formats.  
+ * Purpose:  Base class for raster file formats.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -28,17 +28,18 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_priv.h"
 #include "cpl_string.h"
 #include "cpl_hash_set.h"
 #include "cpl_multiproc.h"
+#include "cpl_vsi_error.h"
+#include "gdal_priv.h"
+#include "ogr_attrind.h"
 #include "ogr_featurestyle.h"
-#include "swq.h"
 #include "ogr_gensql.h"
-#include "ogr_attrind.h"
 #include "ogr_p.h"
-#include "ogrunionlayer.h"
 #include "ograpispy.h"
+#include "ogrunionlayer.h"
+#include "swq.h"
 
 #ifdef SQLITE_ENABLED
 #include "../sqlite/ogrsqliteexecutesql.h"
@@ -46,7 +47,7 @@
 
 #include <map>
 
-CPL_CVSID("$Id: gdaldataset.cpp 31109 2015-10-23 19:53:08Z rouault $");
+CPL_CVSID("$Id: gdaldataset.cpp 33808 2016-03-29 21:15:28Z goatbar $");
 
 CPL_C_START
 GDALAsyncReader *
@@ -61,10 +62,18 @@ GDALGetDefaultAsyncReader( GDALDataset *poDS,
                              int nBandSpace, char **papszOptions);
 CPL_C_END
 
+typedef enum
+{
+    RW_MUTEX_STATE_UNKNOWN,
+    RW_MUTEX_STATE_ALLOWED,
+    RW_MUTEX_STATE_DISABLED
+} GDALAllowReadWriteMutexState;
+
 typedef struct
 {
     CPLMutex* hMutex;
     int       nMutexTakenCount;
+    GDALAllowReadWriteMutexState eStateReadWriteMutex;
 } GDALDatasetPrivate;
 
 typedef struct
@@ -80,7 +89,7 @@ typedef struct
 
 /* Set of datasets opened as shared datasets (with GDALOpenShared) */
 /* The values in the set are of type SharedDatasetCtxt */
-static CPLHashSet* phSharedDatasetSet = NULL; 
+static CPLHashSet* phSharedDatasetSet = NULL;
 
 /* Set of all datasets created in the constructor of GDALDataset */
 /* In the case of a shared dataset, memorize the PID of the thread */
@@ -164,7 +173,7 @@ GIntBig GDALGetResponsiblePIDForCurrentThread()
  * Data Model</a>.
  *
  * Use GDALOpen() or GDALOpenShared() to create a GDALDataset for a named file,
- * or GDALDriver::Create() or GDALDriver::CreateCopy() to create a new 
+ * or GDALDriver::Create() or GDALDriver::CreateCopy() to create a new
  * dataset.
  */
 
@@ -175,6 +184,18 @@ GIntBig GDALGetResponsiblePIDForCurrentThread()
 GDALDataset::GDALDataset()
 
 {
+    Init( CPLTestBool(
+        CPLGetConfigOption( "GDAL_FORCE_CACHING", "NO") ) );
+}
+
+GDALDataset::GDALDataset(int bForceCachedIOIn)
+
+{
+    Init(bForceCachedIOIn);
+}
+
+void GDALDataset::Init(int bForceCachedIOIn)
+{
     poDriver = NULL;
     eAccess = GA_ReadOnly;
     nRasterXSize = 512;
@@ -182,24 +203,23 @@ GDALDataset::GDALDataset()
     nBands = 0;
     papoBands = NULL;
     nRefCount = 1;
+    nOpenFlags = 0;
     bShared = FALSE;
     bIsInternal = TRUE;
     bSuppressOnClose = FALSE;
-    bReserved1 = FALSE;
-    bReserved2 = FALSE;
     papszOpenOptions = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Set forced caching flag.                                        */
 /* -------------------------------------------------------------------- */
-    bForceCachedIO =  CSLTestBoolean( 
-        CPLGetConfigOption( "GDAL_FORCE_CACHING", "NO") );
-    
+    bForceCachedIO = (GByte)bForceCachedIOIn;
+
     m_poStyleTable = NULL;
-    m_hPrivateData = CPLCalloc(1, sizeof(GDALDatasetPrivate));
+    m_hPrivateData = VSI_CALLOC_VERBOSE(1, sizeof(GDALDatasetPrivate));
+    GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
+    psPrivate->eStateReadWriteMutex = RW_MUTEX_STATE_UNKNOWN;
 }
 
-
 /************************************************************************/
 /*                            ~GDALDataset()                            */
 /************************************************************************/
@@ -222,19 +242,17 @@ GDALDataset::GDALDataset()
 GDALDataset::~GDALDataset()
 
 {
-    int         i;
-
-    // we don't want to report destruction of datasets that 
+    // we don't want to report destruction of datasets that
     // were never really open or meant as internal
     if( !bIsInternal && ( nBands != 0 || !EQUAL(GetDescription(),"") ) )
     {
         if( CPLGetPID() != GDALGetResponsiblePIDForCurrentThread() )
-            CPLDebug( "GDAL", 
+            CPLDebug( "GDAL",
                       "GDALClose(%s, this=%p) (pid=%d, responsiblePID=%d)", GetDescription(), this,
-                      (int)CPLGetPID(), 
+                      (int)CPLGetPID(),
                       (int)GDALGetResponsiblePIDForCurrentThread() );
         else
-            CPLDebug( "GDAL", 
+            CPLDebug( "GDAL",
                       "GDALClose(%s, this=%p)", GetDescription(), this );
     }
 
@@ -290,7 +308,7 @@ GDALDataset::~GDALDataset()
 /* -------------------------------------------------------------------- */
 /*      Destroy the raster bands if they exist.                         */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < nBands && papoBands != NULL; i++ )
+    for( int i = 0; i < nBands && papoBands != NULL; i++ )
     {
         if( papoBands[i] != NULL )
             delete papoBands[i];
@@ -305,7 +323,7 @@ GDALDataset::~GDALDataset()
     }
 
     GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
-    if( psPrivate->hMutex != NULL )
+    if( psPrivate != NULL && psPrivate->hMutex != NULL )
         CPLDestroyMutex( psPrivate->hMutex );
     CPLFree(psPrivate);
 
@@ -356,26 +374,24 @@ void GDALDataset::AddToDatasetOpenList()
 void GDALDataset::FlushCache()
 
 {
-    int         i;
-
     // This sometimes happens if a dataset is destroyed before completely
-    // built. 
+    // built.
 
     if( papoBands != NULL )
     {
-        for( i = 0; i < nBands; i++ )
+        for( int i = 0; i < nBands; i++ )
         {
             if( papoBands[i] != NULL )
                 papoBands[i]->FlushCache();
         }
     }
 
-    int nLayers = GetLayerCount();
+    const int nLayers = GetLayerCount();
     if( nLayers > 0 )
     {
         GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
-        CPLMutexHolderD( &(psPrivate->hMutex) );
-        for( i = 0; i < nLayers ; i++ )
+        CPLMutexHolderD( psPrivate ? &(psPrivate->hMutex) : NULL );
+        for( int i = 0; i < nLayers ; i++ )
         {
             OGRLayer *poLayer = GetLayer(i);
 
@@ -419,26 +435,24 @@ void CPL_STDCALL GDALFlushCache( GDALDatasetH hDS )
 void GDALDataset::BlockBasedFlushCache()
 
 {
-    GDALRasterBand *poBand1;
-    int  nBlockXSize, nBlockYSize, iBand;
-    
-    poBand1 = GetRasterBand( 1 );
+    GDALRasterBand *poBand1 = GetRasterBand( 1 );
     if( poBand1 == NULL )
     {
         GDALDataset::FlushCache();
         return;
     }
 
+    int  nBlockXSize, nBlockYSize;
     poBand1->GetBlockSize( &nBlockXSize, &nBlockYSize );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Verify that all bands match.                                    */
 /* -------------------------------------------------------------------- */
-    for( iBand = 1; iBand < nBands; iBand++ )
+    for( int iBand = 1; iBand < nBands; iBand++ )
     {
-        int nThisBlockXSize, nThisBlockYSize;
         GDALRasterBand *poBand = GetRasterBand( iBand+1 );
-        
+
+        int nThisBlockXSize, nThisBlockYSize;
         poBand->GetBlockSize( &nThisBlockXSize, &nThisBlockYSize );
         if( nThisBlockXSize != nBlockXSize && nThisBlockYSize != nBlockYSize )
         {
@@ -454,7 +468,7 @@ void GDALDataset::BlockBasedFlushCache()
     {
         for( int iX = 0; iX < poBand1->nBlocksPerRow; iX++ )
         {
-            for( iBand = 0; iBand < nBands; iBand++ )
+            for( int iBand = 0; iBand < nBands; iBand++ )
             {
                 GDALRasterBand *poBand = GetRasterBand( iBand+1 );
 
@@ -479,7 +493,7 @@ void GDALDataset::RasterInitialize( int nXSize, int nYSize )
 
 {
     CPLAssert( nXSize > 0 && nYSize > 0 );
-    
+
     nRasterXSize = nXSize;
     nRasterYSize = nYSize;
 }
@@ -492,19 +506,19 @@ void GDALDataset::RasterInitialize( int nXSize, int nYSize )
  * \brief Add a band to a dataset.
  *
  * This method will add a new band to the dataset if the underlying format
- * supports this action.  Most formats do not. 
+ * supports this action.  Most formats do not.
  *
  * Note that the new GDALRasterBand is not returned.  It may be fetched
- * after successful completion of the method by calling 
+ * after successful completion of the method by calling
  * GDALDataset::GetRasterBand(GDALDataset::GetRasterCount()) as the newest
  * band will always be the last band.
  *
- * @param eType the data type of the pixels in the new band. 
+ * @param eType the data type of the pixels in the new band.
  *
  * @param papszOptions a list of NAME=VALUE option strings.  The supported
  * options are format specific.  NULL may be passed by default.
  *
- * @return CE_None on success or CE_Failure on failure.  
+ * @return CE_None on success or CE_Failure on failure.
  */
 
 CPLErr GDALDataset::AddBand( GDALDataType eType, char ** papszOptions )
@@ -529,7 +543,7 @@ CPLErr GDALDataset::AddBand( GDALDataType eType, char ** papszOptions )
  * @see GDALDataset::AddBand().
  */
 
-CPLErr CPL_STDCALL GDALAddBand( GDALDatasetH hDataset, 
+CPLErr CPL_STDCALL GDALAddBand( GDALDatasetH hDataset,
                     GDALDataType eType, char **papszOptions )
 
 {
@@ -552,7 +566,6 @@ void GDALDataset::SetBand( int nNewBand, GDALRasterBand * poBand )
 /*      Do we need to grow the bands list?                              */
 /* -------------------------------------------------------------------- */
     if( nBands < nNewBand || papoBands == NULL ) {
-        int             i;
         GDALRasterBand** papoNewBands;
 
         if( papoBands == NULL )
@@ -570,7 +583,7 @@ void GDALDataset::SetBand( int nNewBand, GDALRasterBand * poBand )
         }
         papoBands = papoNewBands;
 
-        for( i = nBands; i < nNewBand; i++ )
+        for( int i = nBands; i < nNewBand; i++ )
             papoBands[i] = NULL;
 
         nBands = MAX(nBands,nNewBand);
@@ -775,16 +788,16 @@ int CPL_STDCALL GDALGetRasterCount( GDALDatasetH hDS )
  * Same as the C function GDALGetProjectionRef().
  *
  * The returned string defines the projection coordinate system of the
- * image in OpenGIS WKT format.  It should be suitable for use with the 
+ * image in OpenGIS WKT format.  It should be suitable for use with the
  * OGRSpatialReference class.
  *
  * When a projection definition is not available an empty (but not NULL)
  * string is returned.
  *
  * @return a pointer to an internal projection reference string.  It should
- * not be altered, freed or expected to last for long. 
+ * not be altered, freed or expected to last for long.
  *
- * @see http://www.gdal.org/ogr/osr_tutorial.html
+ * @see http://www.gdal.org/osr_tutorial.html
  */
 
 const char *GDALDataset::GetProjectionRef()
@@ -891,13 +904,13 @@ CPLErr GDALDataset::GetGeoTransform( double * padfTransform )
 
 {
     CPLAssert( padfTransform != NULL );
-        
+
     padfTransform[0] = 0.0;     /* X Origin (top left corner) */
     padfTransform[1] = 1.0;     /* X Pixel size */
     padfTransform[2] = 0.0;
 
     padfTransform[3] = 0.0;     /* Y Origin (top left corner) */
-    padfTransform[4] = 0.0;     
+    padfTransform[4] = 0.0;
     padfTransform[5] = 1.0;     /* Y Pixel Size */
 
     return( CE_Failure );
@@ -960,7 +973,7 @@ CPLErr GDALDataset::SetGeoTransform( CPL_UNUSED double * padfTransform )
  * @see GDALDataset::SetGeoTransform()
  */
 
-CPLErr CPL_STDCALL 
+CPLErr CPL_STDCALL
 GDALSetGeoTransform( GDALDatasetH hDS, double * padfTransform )
 
 {
@@ -976,12 +989,12 @@ GDALSetGeoTransform( GDALDatasetH hDS, double * padfTransform )
 /**
  * \brief Fetch a format specific internally meaningful handle.
  *
- * This method is the same as the C GDALGetInternalHandle() method. 
+ * This method is the same as the C GDALGetInternalHandle() method.
  *
  * @param pszHandleName the handle name desired.  The meaningful names
  * will be specific to the file format.
  *
- * @return the desired handle value, or NULL if not recognised/supported.
+ * @return the desired handle value, or NULL if not recognized/supported.
  */
 
 void *GDALDataset::GetInternalHandle( CPL_UNUSED const char * pszHandleName )
@@ -1000,7 +1013,7 @@ void *GDALDataset::GetInternalHandle( CPL_UNUSED const char * pszHandleName )
  * @see GDALDataset::GetInternalHandle()
  */
 
-void * CPL_STDCALL 
+void * CPL_STDCALL
 GDALGetInternalHandle( GDALDatasetH hDS, const char * pszRequest )
 
 {
@@ -1188,9 +1201,9 @@ void GDALDataset::MarkAsShared()
 /************************************************************************/
 
 /**
- * \brief Get number of GCPs. 
+ * \brief Get number of GCPs.
  *
- * This method is the same as the C function GDALGetGCPCount(). 
+ * This method is the same as the C function GDALGetGCPCount().
  *
  * @return number of GCPs for this dataset.  Zero if there are none.
  */
@@ -1206,7 +1219,7 @@ int GDALDataset::GetGCPCount()
 /************************************************************************/
 
 /**
- * \brief Get number of GCPs. 
+ * \brief Get number of GCPs.
  *
  * @see GDALDataset::GetGCPCount()
  */
@@ -1224,13 +1237,13 @@ int CPL_STDCALL GDALGetGCPCount( GDALDatasetH hDS )
 /************************************************************************/
 
 /**
- * \brief Get output projection for GCPs. 
+ * \brief Get output projection for GCPs.
  *
- * This method is the same as the C function GDALGetGCPProjection(). 
+ * This method is the same as the C function GDALGetGCPProjection().
  *
  * The projection string follows the normal rules from GetProjectionRef().
  *
- * @return internal projection string or "" if there are no GCPs. 
+ * @return internal projection string or "" if there are no GCPs.
  *  It should not be altered, freed or expected to last for long.
  */
 
@@ -1245,7 +1258,7 @@ const char *GDALDataset::GetGCPProjection()
 /************************************************************************/
 
 /**
- * \brief Get output projection for GCPs. 
+ * \brief Get output projection for GCPs.
  *
  * @see GDALDataset::GetGCPProjection()
  */
@@ -1265,11 +1278,11 @@ const char * CPL_STDCALL GDALGetGCPProjection( GDALDatasetH hDS )
 /**
  * \brief Fetch GCPs.
  *
- * This method is the same as the C function GDALGetGCPs(). 
+ * This method is the same as the C function GDALGetGCPs().
  *
- * @return pointer to internal GCP structure list.  It should not be modified, 
- * and may change on the next GDAL call. 
- */ 
+ * @return pointer to internal GCP structure list.  It should not be modified,
+ * and may change on the next GDAL call.
+ */
 
 const GDAL_GCP *GDALDataset::GetGCPs()
 
@@ -1303,29 +1316,29 @@ const GDAL_GCP * CPL_STDCALL GDALGetGCPs( GDALDatasetH hDS )
 /**
  * \brief Assign GCPs.
  *
- * This method is the same as the C function GDALSetGCPs(). 
+ * This method is the same as the C function GDALSetGCPs().
  *
  * This method assigns the passed set of GCPs to this dataset, as well as
  * setting their coordinate system.  Internally copies are made of the
  * coordinate system and list of points, so the caller remains responsible for
- * deallocating these arguments if appropriate. 
+ * deallocating these arguments if appropriate.
  *
- * Most formats do not support setting of GCPs, even formats that can 
- * handle GCPs.  These formats will return CE_Failure. 
+ * Most formats do not support setting of GCPs, even formats that can
+ * handle GCPs.  These formats will return CE_Failure.
  *
- * @param nGCPCount number of GCPs being assigned. 
+ * @param nGCPCount number of GCPs being assigned.
  *
  * @param pasGCPList array of GCP structures being assign (nGCPCount in array).
  *
- * @param pszGCPProjection the new OGC WKT coordinate system to assign for the 
+ * @param pszGCPProjection the new OGC WKT coordinate system to assign for the
  * GCP output coordinates.  This parameter should be "" if no output coordinate
  * system is known.
  *
  * @return CE_None on success, CE_Failure on failure (including if action is
- * not supported for this format). 
- */ 
+ * not supported for this format).
+ */
 
-CPLErr GDALDataset::SetGCPs( int nGCPCount, 
+CPLErr GDALDataset::SetGCPs( int nGCPCount,
                              const GDAL_GCP *pasGCPList,
                              const char * pszGCPProjection )
 
@@ -1351,14 +1364,14 @@ CPLErr GDALDataset::SetGCPs( int nGCPCount,
  * @see GDALDataset::SetGCPs()
  */
 
-CPLErr CPL_STDCALL GDALSetGCPs( GDALDatasetH hDS, int nGCPCount, 
-                    const GDAL_GCP *pasGCPList, 
+CPLErr CPL_STDCALL GDALSetGCPs( GDALDatasetH hDS, int nGCPCount,
+                    const GDAL_GCP *pasGCPList,
                     const char *pszGCPProjection )
 
 {
     VALIDATE_POINTER1( hDS, "GDALSetGCPs", CE_Failure );
 
-    return ((GDALDataset *) hDS)->SetGCPs( nGCPCount, pasGCPList, 
+    return ((GDALDataset *) hDS)->SetGCPs( nGCPCount, pasGCPList,
                                            pszGCPProjection );
 }
 
@@ -1369,19 +1382,19 @@ CPLErr CPL_STDCALL GDALSetGCPs( GDALDatasetH hDS, int nGCPCount,
 /**
  * \brief Build raster overview(s)
  *
- * If the operation is unsupported for the indicated dataset, then 
- * CE_Failure is returned, and CPLGetLastErrorNo() will return 
+ * If the operation is unsupported for the indicated dataset, then
+ * CE_Failure is returned, and CPLGetLastErrorNo() will return
  * CPLE_NotSupported.
  *
  * This method is the same as the C function GDALBuildOverviews().
  *
  * @param pszResampling one of "NEAREST", "GAUSS", "CUBIC", "AVERAGE", "MODE",
  * "AVERAGE_MAGPHASE" or "NONE" controlling the downsampling method applied.
- * @param nOverviews number of overviews to build. 
- * @param panOverviewList the list of overview decimation factors to build. 
+ * @param nOverviews number of overviews to build.
+ * @param panOverviewList the list of overview decimation factors to build.
  * @param nListBands number of bands to build overviews for in panBandList.  Build
- * for all bands if this is 0. 
- * @param panBandList list of band numbers. 
+ * for all bands if this is 0.
+ * @param panBandList list of band numbers.
  * @param pfnProgress a function to call to report progress, or NULL.
  * @param pProgressData application data to pass to the progress function.
  *
@@ -1391,20 +1404,20 @@ CPLErr CPL_STDCALL GDALSetGCPs( GDALDatasetH hDS, int nGCPCount,
  * call could be made:
  * <pre>
  *   int       anOverviewList[3] = { 2, 4, 8 };
- *   
- *   poDataset->BuildOverviews( "NEAREST", 3, anOverviewList, 0, NULL, 
+ *
+ *   poDataset->BuildOverviews( "NEAREST", 3, anOverviewList, 0, NULL,
  *                              GDALDummyProgress, NULL );
  * </pre>
  *
  * @see GDALRegenerateOverviews()
  */
 
-CPLErr GDALDataset::BuildOverviews( const char *pszResampling, 
-                                    int nOverviews, int *panOverviewList, 
+CPLErr GDALDataset::BuildOverviews( const char *pszResampling,
+                                    int nOverviews, int *panOverviewList,
                                     int nListBands, int *panBandList,
-                                    GDALProgressFunc pfnProgress, 
+                                    GDALProgressFunc pfnProgress,
                                     void * pProgressData )
-    
+
 {
     CPLErr   eErr;
     int      *panAllBandList = NULL;
@@ -1422,7 +1435,7 @@ CPLErr GDALDataset::BuildOverviews( const char *pszResampling,
     if( pfnProgress == NULL )
         pfnProgress = GDALDummyProgress;
 
-    eErr = IBuildOverviews( pszResampling, nOverviews, panOverviewList, 
+    eErr = IBuildOverviews( pszResampling, nOverviews, panOverviewList,
                             nListBands, panBandList, pfnProgress, pProgressData );
 
     if( panAllBandList != NULL )
@@ -1442,35 +1455,35 @@ CPLErr GDALDataset::BuildOverviews( const char *pszResampling,
  */
 
 CPLErr CPL_STDCALL GDALBuildOverviews( GDALDatasetH hDataset,
-                           const char *pszResampling, 
-                           int nOverviews, int *panOverviewList, 
+                           const char *pszResampling,
+                           int nOverviews, int *panOverviewList,
                            int nListBands, int *panBandList,
-                           GDALProgressFunc pfnProgress, 
+                           GDALProgressFunc pfnProgress,
                            void * pProgressData )
 
 {
     VALIDATE_POINTER1( hDataset, "GDALBuildOverviews", CE_Failure );
 
     return ((GDALDataset *) hDataset)->BuildOverviews(
-        pszResampling, nOverviews, panOverviewList, nListBands, panBandList, 
+        pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
         pfnProgress, pProgressData );
 }
-    
+
 /************************************************************************/
 /*                          IBuildOverviews()                           */
 /*                                                                      */
 /*      Default implementation.                                         */
 /************************************************************************/
 
-CPLErr GDALDataset::IBuildOverviews( const char *pszResampling, 
-                                     int nOverviews, int *panOverviewList, 
+CPLErr GDALDataset::IBuildOverviews( const char *pszResampling,
+                                     int nOverviews, int *panOverviewList,
                                      int nListBands, int *panBandList,
-                                     GDALProgressFunc pfnProgress, 
+                                     GDALProgressFunc pfnProgress,
                                      void * pProgressData )
-    
+
 {
     if( oOvManager.IsInitialized() )
-        return oOvManager.BuildOverviews( NULL, pszResampling, 
+        return oOvManager.BuildOverviews( NULL, pszResampling,
                                           nOverviews, panOverviewList,
                                           nListBands, panBandList,
                                           pfnProgress, pProgressData );
@@ -1478,7 +1491,7 @@ CPLErr GDALDataset::IBuildOverviews( const char *pszResampling,
     {
         ReportError( CE_Failure, CPLE_NotSupported,
                   "BuildOverviews() not supported for this dataset." );
-        
+
         return( CE_Failure );
     }
 }
@@ -1486,23 +1499,23 @@ CPLErr GDALDataset::IBuildOverviews( const char *pszResampling,
 /************************************************************************/
 /*                             IRasterIO()                              */
 /*                                                                      */
-/*      The default implementation of IRasterIO() is to pass the        */
-/*      request off to each band objects rasterio methods with          */
-/*      appropriate arguments.                                          */
+/*      The default implementation of IRasterIO() is, in the general    */
+/*      case to pass the request off to each band objects rasterio      */
+/*      methods with appropriate arguments. In some cases, it might     */
+/*      choose instead the BlockBasedRasterIO() implementation.         */
 /************************************************************************/
 
 CPLErr GDALDataset::IRasterIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
                                void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType, 
+                               GDALDataType eBufType,
                                int nBandCount, int *panBandMap,
                                GSpacing nPixelSpace, GSpacing nLineSpace,
                                GSpacing nBandSpace,
                                GDALRasterIOExtraArg* psExtraArg )
-    
+
 {
-    int iBandIndex; 
-    CPLErr eErr = CE_None;
+
     const char* pszInterleave = NULL;
 
     CPLAssert( NULL != pData );
@@ -1511,18 +1524,162 @@ CPLErr GDALDataset::IRasterIO( GDALRWFlag eRWFlag,
         (pszInterleave = GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE")) != NULL &&
         EQUAL(pszInterleave, "PIXEL"))
     {
-        return BlockBasedRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, 
+        return BlockBasedRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
                                    pData, nBufXSize, nBufYSize,
                                    eBufType, nBandCount, panBandMap,
                                    nPixelSpace, nLineSpace, nBandSpace,
                                    psExtraArg );
     }
 
+    if( eRWFlag == GF_Read &&
+        (psExtraArg->eResampleAlg == GRIORA_Cubic ||
+         psExtraArg->eResampleAlg == GRIORA_CubicSpline ||
+         psExtraArg->eResampleAlg == GRIORA_Bilinear ||
+         psExtraArg->eResampleAlg == GRIORA_Lanczos) &&
+        !(nXSize == nBufXSize && nYSize == nBufYSize) && nBandCount > 1 )
+    {
+        GDALDataType eFirstBandDT = GDT_Unknown;
+        int nFirstMaskFlags = 0;
+        GDALRasterBand* poFirstMaskBand = NULL;
+        int nOKBands = 0;
+        for(int i=0;i<nBandCount;i++)
+        {
+            GDALRasterBand* poBand = GetRasterBand(panBandMap[i]);
+            if( (nBufXSize < nXSize || nBufYSize < nYSize) &&
+                poBand->GetOverviewCount() )
+            {
+                // Could be improved to select the appropriate overview
+                break;
+            }
+            if( poBand->GetColorTable() != NULL )
+            {
+                break;
+            }
+            GDALDataType eDT = poBand->GetRasterDataType();
+            if( GDALDataTypeIsComplex( eDT ) )
+            {
+                break;
+            }
+            if( i == 0 )
+            {
+                eFirstBandDT = eDT;
+                nFirstMaskFlags = poBand->GetMaskFlags();
+                poFirstMaskBand = poBand->GetMaskBand();
+            }
+            else
+            {
+                if( eDT != eFirstBandDT )
+                {
+                    break;
+                }
+                int nMaskFlags = poBand->GetMaskFlags();
+                GDALRasterBand* poMaskBand = poBand->GetMaskBand();
+                if( nFirstMaskFlags == GMF_ALL_VALID && nMaskFlags == GMF_ALL_VALID )
+                {
+                    /* ok */
+                }
+                else if( poFirstMaskBand == poMaskBand )
+                {
+                    /* ok */
+                }
+                else
+                {
+                    break;
+                }
+            }
+
+            nOKBands ++;
+        }
+
+        GDALProgressFunc  pfnProgressGlobal = psExtraArg->pfnProgress;
+        void             *pProgressDataGlobal = psExtraArg->pProgressData;
+
+        CPLErr eErr = CE_None;
+        if( nOKBands > 0 )
+        {
+            if( nOKBands < nBandCount )
+            {
+                psExtraArg->pfnProgress = GDALScaledProgress;
+                psExtraArg->pProgressData =
+                    GDALCreateScaledProgress( 0.0, (double)nOKBands / nBandCount,
+                                            pfnProgressGlobal,
+                                            pProgressDataGlobal );
+                if( psExtraArg->pProgressData == NULL )
+                    psExtraArg->pfnProgress = NULL;
+            }
+
+            eErr = RasterIOResampled( eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                                   pData, nBufXSize, nBufYSize,
+                                   eBufType, nOKBands, panBandMap,
+                                   nPixelSpace, nLineSpace, nBandSpace,
+                                   psExtraArg );
+
+            if( nOKBands < nBandCount )
+            {
+                GDALDestroyScaledProgress( psExtraArg->pProgressData );
+            }
+        }
+        if( eErr == CE_None && nOKBands < nBandCount )
+        {
+            if( nOKBands > 0 )
+            {
+                psExtraArg->pfnProgress = GDALScaledProgress;
+                psExtraArg->pProgressData =
+                    GDALCreateScaledProgress( (double)nOKBands / nBandCount, 1.0,
+                                            pfnProgressGlobal,
+                                            pProgressDataGlobal );
+                if( psExtraArg->pProgressData == NULL )
+                    psExtraArg->pfnProgress = NULL;
+            }
+            eErr = BandBasedRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                                   (GByte*)pData + nBandSpace * nOKBands, nBufXSize, nBufYSize,
+                                   eBufType, nBandCount - nOKBands, panBandMap + nOKBands,
+                                   nPixelSpace, nLineSpace, nBandSpace,
+                                   psExtraArg );
+            if( nOKBands > 0 )
+            {
+                GDALDestroyScaledProgress( psExtraArg->pProgressData );
+            }
+        }
+
+        psExtraArg->pfnProgress = pfnProgressGlobal;
+        psExtraArg->pProgressData = pProgressDataGlobal;
+
+        return eErr;
+    }
+
+    return BandBasedRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                                   pData, nBufXSize, nBufYSize,
+                                   eBufType, nBandCount, panBandMap,
+                                   nPixelSpace, nLineSpace, nBandSpace,
+                                   psExtraArg );
+}
+
+/************************************************************************/
+/*                         BandBasedRasterIO()                          */
+/*                                                                      */
+/*      Pass the request off to each band objects rasterio methods with */
+/*      appropriate arguments.                                          */
+/************************************************************************/
+
+CPLErr GDALDataset::BandBasedRasterIO( GDALRWFlag eRWFlag,
+                               int nXOff, int nYOff, int nXSize, int nYSize,
+                               void * pData, int nBufXSize, int nBufYSize,
+                               GDALDataType eBufType,
+                               int nBandCount, int *panBandMap,
+                               GSpacing nPixelSpace, GSpacing nLineSpace,
+                               GSpacing nBandSpace,
+                               GDALRasterIOExtraArg* psExtraArg )
+
+{
+    int iBandIndex;
+    CPLErr eErr = CE_None;
+
     GDALProgressFunc  pfnProgressGlobal = psExtraArg->pfnProgress;
     void             *pProgressDataGlobal = psExtraArg->pProgressData;
 
-    for( iBandIndex = 0; 
-         iBandIndex < nBandCount && eErr == CE_None; 
+    for( iBandIndex = 0;
+         iBandIndex < nBandCount && eErr == CE_None;
          iBandIndex++ )
     {
         GDALRasterBand *poBand = GetRasterBand(panBandMap[iBandIndex]);
@@ -1539,7 +1696,7 @@ CPLErr GDALDataset::IRasterIO( GDALRWFlag eRWFlag,
         if( nBandCount > 1 )
         {
             psExtraArg->pfnProgress = GDALScaledProgress;
-            psExtraArg->pProgressData = 
+            psExtraArg->pProgressData =
                 GDALCreateScaledProgress( 1.0 * iBandIndex / nBandCount,
                                         1.0 * (iBandIndex + 1) / nBandCount,
                                         pfnProgressGlobal,
@@ -1548,7 +1705,7 @@ CPLErr GDALDataset::IRasterIO( GDALRWFlag eRWFlag,
                 psExtraArg->pfnProgress = NULL;
         }
 
-        eErr = poBand->IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, 
+        eErr = poBand->IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
                                   (void *) pabyBandData, nBufXSize, nBufYSize,
                                   eBufType, nPixelSpace, nLineSpace,
                                   psExtraArg );
@@ -1556,7 +1713,7 @@ CPLErr GDALDataset::IRasterIO( GDALRWFlag eRWFlag,
         if( nBandCount > 1 )
             GDALDestroyScaledProgress( psExtraArg->pProgressData );
     }
-    
+
     psExtraArg->pfnProgress = pfnProgressGlobal;
     psExtraArg->pProgressData = pProgressDataGlobal;
 
@@ -1571,7 +1728,7 @@ CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters(
                                const char* pszCallingFunc,
                                int* pbStopProcessingOnCENone,
                                int nXOff, int nYOff, int nXSize, int nYSize,
-                               int nBufXSize, int nBufYSize, 
+                               int nBufXSize, int nBufYSize,
                                int nBandCount, int *panBandMap)
 {
 
@@ -1581,12 +1738,12 @@ CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters(
 /* -------------------------------------------------------------------- */
     if( nXSize < 1 || nYSize < 1 || nBufXSize < 1 || nBufYSize < 1 )
     {
-        CPLDebug( "GDAL", 
+        CPLDebug( "GDAL",
                   "%s skipped for odd window or buffer size.\n"
                   "  Window = (%d,%d)x%dx%d\n"
                   "  Buffer = %dx%d\n",
                   pszCallingFunc,
-                  nXOff, nYOff, nXSize, nYSize, 
+                  nXOff, nYOff, nXSize, nYSize,
                   nBufXSize, nBufYSize );
 
         *pbStopProcessingOnCENone = TRUE;
@@ -1645,7 +1802,7 @@ CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters(
  * \brief Read/write a region of image data from multiple bands.
  *
  * This method allows reading a region of one or more GDALRasterBands from
- * this dataset into a buffer,  or writing data from a buffer into a region 
+ * this dataset into a buffer,  or writing data from a buffer into a region
  * of the GDALRasterBands.  It automatically takes care of data type
  * translation if the data type (eBufType) of the buffer is different than
  * that of the GDALRasterBand.
@@ -1654,7 +1811,7 @@ CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters(
  * region being accessed (nXSize x nYSize).
  *
  * The nPixelSpace, nLineSpace and nBandSpace parameters allow reading into or
- * writing from various organization of buffers. 
+ * writing from various organization of buffers.
  *
  * For highest performance full resolution data access, read and write
  * on "block boundaries" as returned by GetBlockSize(), or use the
@@ -1692,10 +1849,10 @@ CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters(
  * pixel values will automatically be translated to/from the GDALRasterBand
  * data type as needed.
  *
- * @param nBandCount the number of bands being read or written. 
+ * @param nBandCount the number of bands being read or written.
  *
  * @param panBandMap the list of nBandCount band numbers being read/written.
- * Note band numbers are 1 based. This may be NULL to select the first 
+ * Note band numbers are 1 based. This may be NULL to select the first
  * nBandCount bands.
  *
  * @param nPixelSpace The byte offset from the start of one pixel value in
@@ -1707,9 +1864,9 @@ CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters(
  * eBufType * nBufXSize is used.
  *
  * @param nBandSpace the byte offset from the start of one bands data to the
- * start of the next. If defaulted (0) the value will be 
+ * start of the next. If defaulted (0) the value will be
  * nLineSpace * nBufYSize implying band sequential organization
- * of the data buffer. 
+ * of the data buffer.
  *
  * @param psExtraArg (new in GDAL 2.0) pointer to a GDALRasterIOExtraArg structure with additional
  * arguments to specify resampling and progress callback, or NULL for default
@@ -1723,7 +1880,7 @@ CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters(
 CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
                               int nXOff, int nYOff, int nXSize, int nYSize,
                               void * pData, int nBufXSize, int nBufYSize,
-                              GDALDataType eBufType, 
+                              GDALDataType eBufType,
                               int nBandCount, int *panBandMap,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
                               GSpacing nBandSpace,
@@ -1731,9 +1888,9 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
 
 {
     int i = 0;
-    int bNeedToFreeBandMap = FALSE;
+    bool bNeedToFreeBandMap = false;
     CPLErr eErr = CE_None;
-    
+
     GDALRasterIOExtraArg sExtraArg;
     if( psExtraArg == NULL )
     {
@@ -1756,7 +1913,7 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
                   "The buffer into which the data should be read is null" );
         return CE_Failure;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Do some validation of parameters.                               */
 /* -------------------------------------------------------------------- */
@@ -1772,7 +1929,7 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
     int bStopProcessing = FALSE;
     eErr = ValidateRasterIOOrAdviseReadParameters( "RasterIO()", &bStopProcessing,
                                                     nXOff, nYOff, nXSize, nYSize,
-                                                    nBufXSize, nBufYSize, 
+                                                    nBufXSize, nBufYSize,
                                                     nBandCount, panBandMap);
     if( eErr != CE_None || bStopProcessing )
         return eErr;
@@ -1782,8 +1939,8 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
 /*      value assuming a packed buffer.                                 */
 /* -------------------------------------------------------------------- */
     if( nPixelSpace == 0 )
-        nPixelSpace = GDALGetDataTypeSize( eBufType ) / 8;
-    
+        nPixelSpace = GDALGetDataTypeSizeBytes( eBufType );
+
     if( nLineSpace == 0 )
     {
         nLineSpace = nPixelSpace * nBufXSize;
@@ -1794,21 +1951,27 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
         nBandSpace = nLineSpace * nBufYSize;
     }
 
+    int anBandMap[] = { 1, 2, 3, 4 };
     if( panBandMap == NULL )
     {
-        panBandMap = (int *) VSIMalloc2(sizeof(int), nBandCount);
-        if (panBandMap == NULL)
+        if( nBandCount > 4 )
         {
-            ReportError( CE_Failure, CPLE_OutOfMemory,
-                      "Out of memory while allocating band map array" );
-            return CE_Failure;
-        }
-        for( i = 0; i < nBandCount; i++ )
-            panBandMap[i] = i+1;
+            panBandMap = (int *) VSIMalloc2(sizeof(int), nBandCount);
+            if (panBandMap == NULL)
+            {
+                ReportError( CE_Failure, CPLE_OutOfMemory,
+                          "Out of memory while allocating band map array" );
+                return CE_Failure;
+            }
 
-        bNeedToFreeBandMap = TRUE;
-    }
+            for( i = 0; i < nBandCount; i++ )
+                panBandMap[i] = i+1;
 
+            bNeedToFreeBandMap = true;
+        }
+        else
+            panBandMap = anBandMap;
+    }
 
     int bCallLeaveReadWrite = EnterReadWrite(eRWFlag);
 
@@ -1818,7 +1981,7 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
 /* -------------------------------------------------------------------- */
     if( bForceCachedIO )
     {
-        eErr = 
+        eErr =
             BlockBasedRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
                                 pData, nBufXSize, nBufYSize, eBufType,
                                 nBandCount, panBandMap,
@@ -1831,7 +1994,7 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
 /* -------------------------------------------------------------------- */
     else if( eErr == CE_None )
     {
-        eErr = 
+        eErr =
             IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
                        pData, nBufXSize, nBufYSize, eBufType,
                        nBandCount, panBandMap,
@@ -1863,14 +2026,14 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
  * @see GDALDataset::RasterIO()
  */
 
-CPLErr CPL_STDCALL 							
+CPLErr CPL_STDCALL
 GDALDatasetRasterIO( GDALDatasetH hDS, GDALRWFlag eRWFlag,
                      int nXOff, int nYOff, int nXSize, int nYSize,
                      void * pData, int nBufXSize, int nBufYSize,
                      GDALDataType eBufType,
                      int nBandCount, int *panBandMap,
                      int nPixelSpace, int nLineSpace, int nBandSpace )
-    
+
 {
     VALIDATE_POINTER1( hDS, "GDALDatasetRasterIO", CE_Failure );
 
@@ -1878,7 +2041,7 @@ GDALDatasetRasterIO( GDALDatasetH hDS, GDALRWFlag eRWFlag,
 
     return( poDS->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
                             pData, nBufXSize, nBufYSize, eBufType,
-                            nBandCount, panBandMap, 
+                            nBandCount, panBandMap,
                             nPixelSpace, nLineSpace, nBandSpace, NULL ) );
 }
 
@@ -1902,7 +2065,7 @@ GDALDatasetRasterIOEx( GDALDatasetH hDS, GDALRWFlag eRWFlag,
                        GSpacing nPixelSpace, GSpacing nLineSpace,
                        GSpacing nBandSpace,
                        GDALRasterIOExtraArg* psExtraArg )
-    
+
 {
     VALIDATE_POINTER1( hDS, "GDALDatasetRasterIOEx", CE_Failure );
 
@@ -1910,7 +2073,7 @@ GDALDatasetRasterIOEx( GDALDatasetH hDS, GDALRWFlag eRWFlag,
 
     return( poDS->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
                             pData, nBufXSize, nBufYSize, eBufType,
-                            nBandCount, panBandMap, 
+                            nBandCount, panBandMap,
                             nPixelSpace, nLineSpace, nBandSpace, psExtraArg ) );
 }
 /************************************************************************/
@@ -1928,7 +2091,7 @@ GDALDatasetRasterIOEx( GDALDatasetH hDS, GDALRWFlag eRWFlag,
  * @param pnCount integer into which to place the count of dataset pointers
  * being returned.
  *
- * @return a pointer to an array of dataset handles. 
+ * @return a pointer to an array of dataset handles.
  */
 
 GDALDataset **GDALDataset::GetOpenDatasets( int *pnCount )
@@ -1939,7 +2102,7 @@ GDALDataset **GDALDataset::GetOpenDatasets( int *pnCount )
     if (poAllDatasetMap != NULL)
     {
         int i = 0;
-        *pnCount = poAllDatasetMap->size();
+        *pnCount = static_cast<int>(poAllDatasetMap->size());
         ppDatasets = (GDALDataset**) CPLRealloc(ppDatasets, (*pnCount) * sizeof(GDALDataset*));
         std::map<GDALDataset*, GIntBig>::iterator oIter = poAllDatasetMap->begin();
         for(; oIter != poAllDatasetMap->end(); ++oIter, i++ )
@@ -2011,13 +2174,13 @@ int CPL_STDCALL GDALGetAccess( GDALDatasetH hDS )
 /**
  * \brief Advise driver of upcoming read requests.
  *
- * Some GDAL drivers operate more efficiently if they know in advance what 
+ * Some GDAL drivers operate more efficiently if they know in advance what
  * set of upcoming read requests will be made.  The AdviseRead() method allows
- * an application to notify the driver of the region and bands of interest, 
- * and at what resolution the region will be read.  
+ * an application to notify the driver of the region and bands of interest,
+ * and at what resolution the region will be read.
  *
  * Many drivers just ignore the AdviseRead() call, but it can dramatically
- * accelerate access via some drivers.  
+ * accelerate access via some drivers.
  *
  * @param nXOff The pixel offset to the top left corner of the region
  * of the band to be accessed.  This would be zero to start from the left side.
@@ -2039,22 +2202,22 @@ int CPL_STDCALL GDALGetAccess( GDALDatasetH hDS )
  * pixel values will automatically be translated to/from the GDALRasterBand
  * data type as needed.
  *
- * @param nBandCount the number of bands being read or written. 
+ * @param nBandCount the number of bands being read or written.
  *
  * @param panBandMap the list of nBandCount band numbers being read/written.
- * Note band numbers are 1 based.   This may be NULL to select the first 
+ * Note band numbers are 1 based.   This may be NULL to select the first
  * nBandCount bands.
  *
- * @param papszOptions a list of name=value strings with special control 
+ * @param papszOptions a list of name=value strings with special control
  * options.  Normally this is NULL.
  *
  * @return CE_Failure if the request is invalid and CE_None if it works or
- * is ignored. 
+ * is ignored.
  */
 
 CPLErr GDALDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
-                                int nBufXSize, int nBufYSize, 
-                                GDALDataType eBufType, 
+                                int nBufXSize, int nBufYSize,
+                                GDALDataType eBufType,
                                 int nBandCount, int *panBandMap,
                                 char **papszOptions )
 
@@ -2067,14 +2230,13 @@ CPLErr GDALDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
     int bStopProcessing = FALSE;
     CPLErr eErr = ValidateRasterIOOrAdviseReadParameters( "AdviseRead()", &bStopProcessing,
                                                     nXOff, nYOff, nXSize, nYSize,
-                                                    nBufXSize, nBufYSize, 
+                                                    nBufXSize, nBufYSize,
                                                     nBandCount, panBandMap);
     if( eErr != CE_None || bStopProcessing )
         return eErr;
 
     for( iBand = 0; iBand < nBandCount; iBand++ )
     {
-        CPLErr eErr;
         GDALRasterBand *poBand;
 
         if( panBandMap == NULL )
@@ -2088,7 +2250,7 @@ CPLErr GDALDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
         if( eErr != CE_None )
             return eErr;
     }
-    
+
     return CE_None;
 }
 
@@ -2101,18 +2263,18 @@ CPLErr GDALDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
  *
  * @see GDALDataset::AdviseRead()
  */
-CPLErr CPL_STDCALL 
-GDALDatasetAdviseRead( GDALDatasetH hDS, 
+CPLErr CPL_STDCALL
+GDALDatasetAdviseRead( GDALDatasetH hDS,
                        int nXOff, int nYOff, int nXSize, int nYSize,
-                       int nBufXSize, int nBufYSize, GDALDataType eDT, 
+                       int nBufXSize, int nBufYSize, GDALDataType eDT,
                        int nBandCount, int *panBandMap,char **papszOptions )
-    
+
 {
     VALIDATE_POINTER1( hDS, "GDALDatasetAdviseRead", CE_Failure );
 
-    return ((GDALDataset *) hDS)->AdviseRead( nXOff, nYOff, nXSize, nYSize, 
-                                              nBufXSize, nBufYSize, eDT, 
-                                              nBandCount, panBandMap, 
+    return ((GDALDataset *) hDS)->AdviseRead( nXOff, nYOff, nXSize, nYSize,
+                                              nBufXSize, nBufYSize, eDT,
+                                              nBandCount, panBandMap,
                                               papszOptions );
 }
 
@@ -2128,14 +2290,14 @@ GDALDatasetAdviseRead( GDALDatasetH hDS,
  * system files associated with the dataset (for instance a virtual dataset).
  * The returned file list is owned by the caller and should be deallocated
  * with CSLDestroy().
- * 
- * The returned filenames will normally be relative or absolute paths 
+ *
+ * The returned filenames will normally be relative or absolute paths
  * depending on the path used to originally open the dataset.  The strings
  * will be UTF-8 encoded.
  *
  * This method is the same as the C GDALGetFileList() function.
  *
- * @return NULL or a NULL terminated array of file names. 
+ * @return NULL or a NULL terminated array of file names.
  */
 
 char **GDALDataset::GetFileList()
@@ -2266,12 +2428,12 @@ char ** CPL_STDCALL GDALGetFileList( GDALDatasetH hDS )
  * @see http://trac.osgeo.org/gdal/wiki/rfc15_nodatabitmask
  *
  */
-CPLErr GDALDataset::CreateMaskBand( int nFlags )
+CPLErr GDALDataset::CreateMaskBand( int nFlagsIn )
 
 {
     if( oOvManager.IsInitialized() )
     {
-        CPLErr eErr = oOvManager.CreateMaskBand( nFlags, -1 );
+        CPLErr eErr = oOvManager.CreateMaskBand( nFlagsIn, -1 );
         if (eErr != CE_None)
             return eErr;
 
@@ -2291,7 +2453,7 @@ CPLErr GDALDataset::CreateMaskBand( int nFlags )
 
     ReportError( CE_Failure, CPLE_NotSupported,
               "CreateMaskBand() not supported for this dataset." );
-    
+
     return( CE_Failure );
 }
 
@@ -2319,7 +2481,7 @@ CPLErr CPL_STDCALL GDALCreateDatasetMaskBand( GDALDatasetH hDS, int nFlags )
  * \brief Open a raster file as a GDALDataset.
  *
  * This function will try to open the passed file, or virtual dataset
- * name by invoking the Open method of each registered GDALDriver in turn. 
+ * name by invoking the Open method of each registered GDALDriver in turn.
  * The first successful open will result in a returned dataset.  If all
  * drivers fail then NULL is returned and an error is issued.
  *
@@ -2353,10 +2515,10 @@ CPLErr CPL_STDCALL GDALCreateDatasetMaskBand( GDALDatasetH hDS, int nFlags )
  * drivers support only read only access.
  *
  * @return A GDALDatasetH handle or NULL on failure.  For C++ applications
- * this handle can be cast to a GDALDataset *. 
+ * this handle can be cast to a GDALDataset *.
  */
 
-GDALDatasetH CPL_STDCALL 
+GDALDatasetH CPL_STDCALL
 GDALOpen( const char * pszFilename, GDALAccess eAccess )
 
 {
@@ -2376,7 +2538,7 @@ GDALOpen( const char * pszFilename, GDALAccess eAccess )
  * \brief Open a raster or vector file as a GDALDataset.
  *
  * This function will try to open the passed file, or virtual dataset
- * name by invoking the Open method of each registered GDALDriver in turn. 
+ * name by invoking the Open method of each registered GDALDriver in turn.
  * The first successful open will result in a returned dataset.  If all
  * drivers fail then NULL is returned and an error is issued.
  *
@@ -2403,7 +2565,7 @@ GDALOpen( const char * pszFilename, GDALAccess eAccess )
  * the papszSiblingFiles parameter.
  * This is the list of all files at the same level in the file system as the
  * target file, including the target file. The filenames must not include any
- * path components, are an essentially just the output of CPLReadDir() on the
+ * path components, are an essentially just the output of VSIReadDir() on the
  * parent directory. If the target object does not have filesystem semantics
  * then the file list should be NULL.
  *
@@ -2439,14 +2601,16 @@ GDALOpen( const char * pszFilename, GDALAccess eAccess )
  * Open options are validated by default, and a warning is emitted in case the
  * option is not recognized. In some scenarios, it might be not desirable (e.g.
  * when not knowing which driver will open the file), so the special open option
- * VALIDATE_OPEN_OPTIONS can be set to NO to avoid such warnings.
+ * VALIDATE_OPEN_OPTIONS can be set to NO to avoid such warnings. Alternatively,
+ * since GDAL 2.1, an option name can be preceded by the @ character to indicate
+ * that it may not cause a warning if the driver doesn't declare this option.
  *
  * @param papszSiblingFiles  NULL, or a NULL terminated list of strings that are
  * filenames that are auxiliary to the main filename. If NULL is passed, a probing
  * of the file system will be done.
  *
  * @return A GDALDatasetH handle or NULL on failure.  For C++ applications
- * this handle can be cast to a GDALDataset *. 
+ * this handle can be cast to a GDALDataset *.
  *
  * @since GDAL 2.0
  */
@@ -2470,7 +2634,7 @@ GDALDatasetH CPL_STDCALL GDALOpenEx( const char* pszFilename,
             CPLError(CE_Failure, CPLE_IllegalArg, "GDAL_OF_SHARED and GDAL_OF_INTERNAL are exclusive");
             return NULL;
         }
-        
+
         CPLMutexHolderD( &hDLMutex );
 
         if (phSharedDatasetSet != NULL)
@@ -2500,6 +2664,21 @@ GDALDatasetH CPL_STDCALL GDALOpenEx( const char* pszFilename,
     if( (nOpenFlags & GDAL_OF_KIND_MASK) == 0 )
         nOpenFlags |= GDAL_OF_KIND_MASK;
 
+    int         iDriver;
+    GDALDriverManager *poDM = GetGDALDriverManager();
+    //CPLLocaleC  oLocaleForcer;
+
+    CPLErrorReset();
+    VSIErrorReset();
+    CPLAssert( NULL != poDM );
+
+    /* Build GDALOpenInfo just now to avoid useless file stat'ing if a */
+    /* shared dataset was asked before */
+    GDALOpenInfo oOpenInfo(pszFilename,
+                           nOpenFlags,
+                           (char**) papszSiblingFiles);
+
+    // Prevent infinite recursion
     {
         int* pnRecCount = (int*)CPLGetTLS( CTLS_GDALDATASET_REC_PROTECT_MAP );
         if( pnRecCount == NULL )
@@ -2517,19 +2696,17 @@ GDALDatasetH CPL_STDCALL GDALOpenEx( const char* pszFilename,
         (*pnRecCount) ++;
     }
 
-    int         iDriver;
-    GDALDriverManager *poDM = GetGDALDriverManager();
-    //CPLLocaleC  oLocaleForcer;
-
-    CPLErrorReset();
-    CPLAssert( NULL != poDM );
+    // Remove leading @ if present
+    char** papszOpenOptionsCleaned = CSLDuplicate((char**)papszOpenOptions);
+    for(char** papszIter = papszOpenOptionsCleaned;
+                                        papszIter && *papszIter; ++papszIter)
+    {
+        char* pszOption = *papszIter;
+        if( pszOption[0] == '@' )
+            memmove( pszOption, pszOption+1, strlen(pszOption+1)+1 );
+    }
 
-    /* Build GDALOpenInfo just now to avoid useless file stat'ing if a */
-    /* shared dataset was asked before */
-    GDALOpenInfo oOpenInfo(pszFilename,
-                           nOpenFlags,
-                           (char**) papszSiblingFiles);
-    oOpenInfo.papszOpenOptions = (char**) papszOpenOptions;
+    oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
 
     for( iDriver = -1; iDriver < poDM->GetDriverCount(); iDriver++ )
     {
@@ -2558,20 +2735,26 @@ GDALDatasetH CPL_STDCALL GDALOpenEx( const char* pszFilename,
         /* Remove general OVERVIEW_LEVEL open options from list before */
         /* passing it to the driver, if it isn't a driver specific option already */
         char** papszTmpOpenOptions = NULL;
-        if( CSLFetchNameValue((char**)papszOpenOptions, "OVERVIEW_LEVEL") != NULL &&
+        char** papszTmpOpenOptionsToValidate = NULL;
+        char** papszOptionsToValidate = (char**) papszOpenOptions;
+        if( CSLFetchNameValue(papszOpenOptionsCleaned, "OVERVIEW_LEVEL") != NULL &&
             (poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST) == NULL ||
              CPLString(poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST)).ifind("OVERVIEW_LEVEL") == std::string::npos) )
         {
-            papszTmpOpenOptions = CSLDuplicate((char**)papszOpenOptions);
+            papszTmpOpenOptions = CSLDuplicate(papszOpenOptionsCleaned);
             papszTmpOpenOptions = CSLSetNameValue(papszTmpOpenOptions, "OVERVIEW_LEVEL", NULL);
             oOpenInfo.papszOpenOptions = papszTmpOpenOptions;
+
+            papszOptionsToValidate = CSLDuplicate(papszOptionsToValidate);
+            papszOptionsToValidate = CSLSetNameValue(papszOptionsToValidate, "OVERVIEW_LEVEL", NULL);
+            papszTmpOpenOptionsToValidate = papszOptionsToValidate;
         }
 
         int bIdentifyRes =
             ( poDriver->pfnIdentify && poDriver->pfnIdentify(&oOpenInfo) > 0 );
         if( bIdentifyRes )
         {
-            GDALValidateOpenOptions( poDriver, oOpenInfo.papszOpenOptions );
+            GDALValidateOpenOptions( poDriver, papszOptionsToValidate );
         }
 
         if ( poDriver->pfnOpen != NULL )
@@ -2580,7 +2763,7 @@ GDALDatasetH CPL_STDCALL GDALOpenEx( const char* pszFilename,
             // If we couldn't determine for sure with Identify() (it returned -1)
             // but that Open() managed to open the file, post validate options.
             if( poDS != NULL && poDriver->pfnIdentify && !bIdentifyRes )
-                GDALValidateOpenOptions( poDriver, oOpenInfo.papszOpenOptions );
+                GDALValidateOpenOptions( poDriver, papszOptionsToValidate );
         }
         else if( poDriver->pfnOpenWithDriverArg != NULL )
         {
@@ -2589,15 +2772,19 @@ GDALDatasetH CPL_STDCALL GDALOpenEx( const char* pszFilename,
         else
         {
             CSLDestroy(papszTmpOpenOptions);
-            oOpenInfo.papszOpenOptions = (char**) papszOpenOptions;
+            CSLDestroy(papszTmpOpenOptionsToValidate);
+            oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
             continue;
         }
 
         CSLDestroy(papszTmpOpenOptions);
-        oOpenInfo.papszOpenOptions = (char**) papszOpenOptions;
+        CSLDestroy(papszTmpOpenOptionsToValidate);
+        oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
 
         if( poDS != NULL )
         {
+            poDS->nOpenFlags = nOpenFlags;
+
             if( strlen(poDS->GetDescription()) == 0 )
                 poDS->SetDescription( pszFilename );
 
@@ -2605,7 +2792,10 @@ GDALDatasetH CPL_STDCALL GDALOpenEx( const char* pszFilename,
                 poDS->poDriver = poDriver;
 
             if( poDS->papszOpenOptions == NULL )
-                poDS->papszOpenOptions = CSLDuplicate((char**)papszOpenOptions);
+            {
+                poDS->papszOpenOptions = papszOpenOptionsCleaned;
+                papszOpenOptionsCleaned = NULL;
+            }
 
             if( !(nOpenFlags & GDAL_OF_INTERNAL) )
             {
@@ -2665,7 +2855,9 @@ GDALDatasetH CPL_STDCALL GDALOpenEx( const char* pszFilename,
                     poDS = poOvrDS;
                 }
             }
+            VSIErrorReset();
 
+            CSLDestroy(papszOpenOptionsCleaned);
             return (GDALDatasetH) poDS;
         }
 
@@ -2675,21 +2867,31 @@ GDALDatasetH CPL_STDCALL GDALOpenEx( const char* pszFilename,
             if( pnRecCount )
                 (*pnRecCount) --;
 
+            CSLDestroy(papszOpenOptionsCleaned);
             return NULL;
         }
     }
 
+    CSLDestroy(papszOpenOptionsCleaned);
+
     if( nOpenFlags & GDAL_OF_VERBOSE_ERROR )
     {
-        if( oOpenInfo.bStatOK )
-            CPLError( CE_Failure, CPLE_OpenFailed,
-                    "`%s' not recognised as a supported file format.\n",
-                    pszFilename );
-        else
-            CPLError( CE_Failure, CPLE_OpenFailed,
-                    "`%s' does not exist in the file system,\n"
-                    "and is not recognised as a supported dataset name.\n",
-                    pszFilename );
+        // Check to see if there was a filesystem error, and report it if so.
+        // If not, return a more generic error.
+        if(!VSIToCPLError(CE_Failure, CPLE_OpenFailed)) {
+            if( oOpenInfo.bStatOK )
+                CPLError( CE_Failure, CPLE_OpenFailed,
+                          "`%s' not recognized as a supported file format.\n",
+                          pszFilename );
+            else {
+                // If Stat failed and no VSI error was set,
+                // assume it is because the file did not exist on the filesystem.
+                CPLError( CE_Failure, CPLE_OpenFailed,
+                          "`%s' does not exist in the file system,\n"
+                          "and is not recognized as a supported dataset name.\n",
+                          pszFilename );
+            }
+        }
     }
 
     int* pnRecCount = (int*)CPLGetTLS( CTLS_GDALDATASET_REC_PROTECT_MAP );
@@ -2708,7 +2910,7 @@ GDALDatasetH CPL_STDCALL GDALOpenEx( const char* pszFilename,
  *
  * This function works the same as GDALOpen(), but allows the sharing of
  * GDALDataset handles for a dataset with other callers to GDALOpenShared().
- * 
+ *
  * In particular, GDALOpenShared() will first consult it's list of currently
  * open and shared GDALDataset's, and if the GetDescription() name for one
  * exactly matches the pszFilename passed to GDALOpenShared() it will be
@@ -2731,17 +2933,17 @@ GDALDatasetH CPL_STDCALL GDALOpenEx( const char* pszFilename,
  *
  * @param pszFilename the name of the file to access.  In the case of
  * exotic drivers this may not refer to a physical file, but instead contain
- * information for the driver on how to access a dataset.  It should be in 
+ * information for the driver on how to access a dataset.  It should be in
  * UTF-8 encoding.
  *
  * @param eAccess the desired access, either GA_Update or GA_ReadOnly.  Many
  * drivers support only read only access.
  *
  * @return A GDALDatasetH handle or NULL on failure.  For C++ applications
- * this handle can be cast to a GDALDataset *. 
+ * this handle can be cast to a GDALDataset *.
  */
- 
-GDALDatasetH CPL_STDCALL 
+
+GDALDatasetH CPL_STDCALL
 GDALOpenShared( const char *pszFilename, GDALAccess eAccess )
 {
     VALIDATE_POINTER1( pszFilename, "GDALOpenShared", NULL );
@@ -2758,14 +2960,14 @@ GDALOpenShared( const char *pszFilename, GDALAccess eAccess )
 /************************************************************************/
 
 /**
- * \brief Close GDAL dataset. 
+ * \brief Close GDAL dataset.
  *
  * For non-shared datasets (opened with GDALOpen()) the dataset is closed
- * using the C++ "delete" operator, recovering all dataset related resources.  
- * For shared datasets (opened with GDALOpenShared()) the dataset is 
+ * using the C++ "delete" operator, recovering all dataset related resources.
+ * For shared datasets (opened with GDALOpenShared()) the dataset is
  * dereferenced, and closed only if the referenced count has dropped below 1.
  *
- * @param hDS The dataset to close.  May be cast from a "GDALDataset *". 
+ * @param hDS The dataset to close.  May be cast from a "GDALDataset *".
  */
 
 void CPL_STDCALL GDALClose( GDALDatasetH hDS )
@@ -2813,15 +3015,15 @@ static int GDALDumpOpenSharedDatasetsForeach(void* elt, void* user_data)
         pszDriverName = poDS->GetDriver()->GetDescription();
 
     poDS->Reference();
-    VSIFPrintf( fp, "  %d %c %-6s %7d %dx%dx%d %s\n", 
-                poDS->Dereference(), 
+    CPL_IGNORE_RET_VAL(VSIFPrintf( fp, "  %d %c %-6s %7d %dx%dx%d %s\n",
+                poDS->Dereference(),
                 poDS->GetShared() ? 'S' : 'N',
-                pszDriverName, 
+                pszDriverName,
                 (int)psStruct->nPID,
                 poDS->GetRasterXSize(),
                 poDS->GetRasterYSize(),
                 poDS->GetRasterCount(),
-                poDS->GetDescription() );
+                poDS->GetDescription() ));
 
     return TRUE;
 }
@@ -2842,15 +3044,15 @@ static int GDALDumpOpenDatasetsForeach(GDALDataset* poDS, FILE *fp)
         pszDriverName = poDS->GetDriver()->GetDescription();
 
     poDS->Reference();
-    VSIFPrintf( fp, "  %d %c %-6s %7d %dx%dx%d %s\n", 
-                poDS->Dereference(), 
+    CPL_IGNORE_RET_VAL(VSIFPrintf( fp, "  %d %c %-6s %7d %dx%dx%d %s\n",
+                poDS->Dereference(),
                 poDS->GetShared() ? 'S' : 'N',
-                pszDriverName, 
+                pszDriverName,
                 -1,
                 poDS->GetRasterXSize(),
                 poDS->GetRasterYSize(),
                 poDS->GetRasterCount(),
-                poDS->GetDescription() );
+                poDS->GetDescription() ));
 
     return TRUE;
 }
@@ -2858,15 +3060,15 @@ static int GDALDumpOpenDatasetsForeach(GDALDataset* poDS, FILE *fp)
 /**
  * \brief List open datasets.
  *
- * Dumps a list of all open datasets (shared or not) to the indicated 
+ * Dumps a list of all open datasets (shared or not) to the indicated
  * text file (may be stdout or stderr).   This function is primarily intended
- * to assist in debugging "dataset leaks" and reference counting issues. 
- * The information reported includes the dataset name, referenced count, 
- * shared status, driver name, size, and band count. 
+ * to assist in debugging "dataset leaks" and reference counting issues.
+ * The information reported includes the dataset name, referenced count,
+ * shared status, driver name, size, and band count.
  */
 
 int CPL_STDCALL GDALDumpOpenDatasets( FILE *fp )
-   
+
 {
     VALIDATE_POINTER1( fp, "GDALDumpOpenDatasets", 0 );
 
@@ -2874,7 +3076,7 @@ int CPL_STDCALL GDALDumpOpenDatasets( FILE *fp )
 
     if (poAllDatasetMap != NULL)
     {
-        VSIFPrintf( fp, "Open GDAL Datasets:\n" );
+        CPL_IGNORE_RET_VAL(VSIFPrintf( fp, "Open GDAL Datasets:\n" ));
         std::map<GDALDataset*, GIntBig>::iterator oIter = poAllDatasetMap->begin();
         for(; oIter != poAllDatasetMap->end(); ++oIter )
         {
@@ -2903,21 +3105,21 @@ int CPL_STDCALL GDALDumpOpenDatasets( FILE *fp )
  * indicated window on the dataset into the indicated buffer.  The parameters
  * for windowing, buffer size, buffer type and buffer organization are similar
  * to those for GDALDataset::RasterIO(); however, this call only launches
- * the request and filling the buffer is accomplished via calls to 
+ * the request and filling the buffer is accomplished via calls to
  * GetNextUpdatedRegion() on the return GDALAsyncReader session object.
- * 
+ *
  * Once all processing for the created session is complete, or if no further
  * refinement of the request is required, the GDALAsyncReader object should
- * be destroyed with the GDALDataset::EndAsyncReader() method. 
- * 
- * Note that the data buffer (pData) will potentially continue to be 
+ * be destroyed with the GDALDataset::EndAsyncReader() method.
+ *
+ * Note that the data buffer (pData) will potentially continue to be
  * updated as long as the session lives, but it is not deallocated when
  * the session (GDALAsyncReader) is destroyed with EndAsyncReader().  It
- * should be deallocated by the application at that point. 
+ * should be deallocated by the application at that point.
  *
- * Additional information on asynchronous IO in GDAL may be found at: 
+ * Additional information on asynchronous IO in GDAL may be found at:
  *   http://trac.osgeo.org/gdal/wiki/rfc24_progressive_data_support
- * 
+ *
  * This method is the same as the C GDALBeginAsyncReader() function.
  *
  * @param nXOff The pixel offset to the top left corner of the region
@@ -2930,9 +3132,9 @@ int CPL_STDCALL GDALDumpOpenDatasets( FILE *fp )
  *
  * @param nYSize The height of the region of the band to be accessed in lines.
  *
- * @param pBuf The buffer into which the data should be read. This buffer must 
- * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.  
- * It is organized in left to right,top to bottom pixel order.  Spacing is 
+ * @param pBuf The buffer into which the data should be read. This buffer must
+ * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.
+ * It is organized in left to right,top to bottom pixel order.  Spacing is
  * controlled by the nPixelSpace, and nLineSpace parameters.
  *
  * @param nBufXSize the width of the buffer image into which the desired region
@@ -2945,10 +3147,10 @@ int CPL_STDCALL GDALDumpOpenDatasets( FILE *fp )
  * pixel values will automatically be translated to/from the GDALRasterBand
  * data type as needed.
  *
- * @param nBandCount the number of bands being read or written. 
+ * @param nBandCount the number of bands being read or written.
  *
  * @param panBandMap the list of nBandCount band numbers being read/written.
- * Note band numbers are 1 based.   This may be NULL to select the first 
+ * Note band numbers are 1 based.   This may be NULL to select the first
  * nBandCount bands.
  *
  * @param nPixelSpace The byte offset from the start of one pixel value in
@@ -2960,17 +3162,17 @@ int CPL_STDCALL GDALDumpOpenDatasets( FILE *fp )
  * eBufType * nBufXSize is used.
  *
  * @param nBandSpace the byte offset from the start of one bands data to the
- * start of the next.  If defaulted (zero) the value will be 
+ * start of the next.  If defaulted (zero) the value will be
  * nLineSpace * nBufYSize implying band sequential organization
- * of the data buffer. 
+ * of the data buffer.
  *
  * @param papszOptions Driver specific control options in a string list or NULL.
  * Consult driver documentation for options supported.
- * 
+ *
  * @return The GDALAsyncReader object representing the request.
  */
 
-GDALAsyncReader* 
+GDALAsyncReader*
 GDALDataset::BeginAsyncReader(int nXOff, int nYOff,
                               int nXSize, int nYSize,
                               void *pBuf,
@@ -2983,7 +3185,7 @@ GDALDataset::BeginAsyncReader(int nXOff, int nYOff,
     // See gdaldefaultasync.cpp
 
     return
-        GDALGetDefaultAsyncReader( this, 
+        GDALGetDefaultAsyncReader( this,
                                      nXOff, nYOff, nXSize, nYSize,
                                      pBuf, nBufXSize, nBufYSize, eBufType,
                                      nBandCount, panBandMap,
@@ -2995,7 +3197,7 @@ GDALDataset::BeginAsyncReader(int nXOff, int nYOff,
 /*                        GDALBeginAsyncReader()                      */
 /************************************************************************/
 
-GDALAsyncReaderH CPL_STDCALL 
+GDALAsyncReaderH CPL_STDCALL
 GDALBeginAsyncReader(GDALDatasetH hDS, int xOff, int yOff,
                        int xSize, int ySize,
                        void *pBuf,
@@ -3024,10 +3226,10 @@ GDALBeginAsyncReader(GDALDatasetH hDS, int xOff, int yOff,
 /**
  * End asynchronous request.
  *
- * This method destroys an asynchronous io request and recovers all 
+ * This method destroys an asynchronous io request and recovers all
  * resources associated with it.
- * 
- * This method is the same as the C function GDALEndAsyncReader(). 
+ *
+ * This method is the same as the C function GDALEndAsyncReader().
  *
  * @param poARIO pointer to a GDALAsyncReader
  */
@@ -3044,7 +3246,7 @@ void CPL_STDCALL GDALEndAsyncReader(GDALDatasetH hDS, GDALAsyncReaderH hAsyncRea
 {
     VALIDATE_POINTER0( hDS, "GDALDataset" );
     VALIDATE_POINTER0( hAsyncReaderH, "GDALAsyncReader" );
-    ((GDALDataset *) hDS) -> EndAsyncReader((GDALAsyncReader *)hAsyncReaderH);	
+    ((GDALDataset *) hDS) -> EndAsyncReader((GDALAsyncReader *)hAsyncReaderH);
 }
 
 /************************************************************************/
@@ -3067,10 +3269,10 @@ void CPL_STDCALL GDALEndAsyncReader(GDALDatasetH hDS, GDALAsyncReaderH hAsyncRea
  * The driver implementation may choose to destroy its raster bands,
  * so be careful not to call any method on the raster bands afterwards.
  *
- * Basically the only safe action you can do after calling CloseDependantDatasets()
+ * Basically the only safe action you can do after calling CloseDependentDatasets()
  * is to call the destructor.
  *
- * Note: the only legitimate caller of CloseDependantDatasets() is
+ * Note: the only legitimate caller of CloseDependentDatasets() is
  * GDALDriverManager::~GDALDriverManager()
  *
  * @return TRUE if at least one reference to another dataset has been dropped.
@@ -3100,7 +3302,7 @@ int GDALDataset::CloseDependentDatasets()
  * @since GDAL 1.9.0
  */
 
-void GDALDataset::ReportError(CPLErr eErrClass, int err_no, const char *fmt, ...)
+void GDALDataset::ReportError(CPLErr eErrClass, CPLErrorNum err_no, const char *fmt, ...)
 {
     va_list args;
 
@@ -3144,16 +3346,16 @@ const char* GDALDataset::GetDriverName()
 
  This function should only be used to deallocate OGRLayers resulting from
  an ExecuteSQL() call on the same GDALDataset.  Failure to deallocate a
- results set before destroying the GDALDataset may cause errors. 
+ results set before destroying the GDALDataset may cause errors.
 
  This function is the same as the C++ method GDALDataset::ReleaseResultSet()
 
  @since GDAL 2.0
 
  @param hDS the dataset handle.
- @param poResultsSet the result of a previous ExecuteSQL() call.
+ @param hLayer the result of a previous ExecuteSQL() call.
 
-*/ 
+*/
 void GDALDatasetReleaseResultSet( GDALDatasetH hDS, OGRLayerH hLayer )
 
 {
@@ -3184,18 +3386,17 @@ void GDALDatasetReleaseResultSet( GDALDatasetH hDS, OGRLayerH hLayer )
  </ul>
 
  The \#define macro forms of the capability names should be used in preference
- to the strings themselves to avoid mispelling.
+ to the strings themselves to avoid misspelling.
 
  This function is the same as the C++ method GDALDataset::TestCapability()
 
  @since GDAL 2.0
 
  @param hDS the dataset handle.
- @param pszCapability the capability to test.
+ @param pszCap the capability to test.
 
  @return TRUE if capability available otherwise FALSE.
-
-*/ 
+*/
 int GDALDatasetTestCapability( GDALDatasetH hDS, const char *pszCap )
 
 {
@@ -3213,7 +3414,7 @@ int GDALDatasetTestCapability( GDALDatasetH hDS, const char *pszCap )
  \brief Get the number of layers in this dataset.
 
  This function is the same as the C++ method GDALDataset::GetLayerCount()
- 
+
  @since GDAL 2.0
 
  @param hDS the dataset handle.
@@ -3235,11 +3436,11 @@ int GDALDatasetGetLayerCount( GDALDatasetH hDS )
 /**
  \brief Fetch a layer by index.
 
- The returned layer remains owned by the 
+ The returned layer remains owned by the
  GDALDataset and should not be deleted by the application.
 
  This function is the same as the C++ method GDALDataset::GetLayer()
- 
+
  @since GDAL 2.0
 
  @param hDS the dataset handle.
@@ -3263,15 +3464,15 @@ OGRLayerH GDALDatasetGetLayer( GDALDatasetH hDS, int iLayer )
 /**
  \brief Fetch a layer by name.
 
- The returned layer remains owned by the 
+ The returned layer remains owned by the
  GDALDataset and should not be deleted by the application.
 
  This function is the same as the C++ method GDALDataset::GetLayerByName()
- 
+
  @since GDAL 2.0
 
  @param hDS the dataset handle.
- @param pszLayerName the layer name of the layer to fetch.
+ @param pszName the layer name of the layer to fetch.
 
  @return the layer, or NULL if Layer is not found or an error occurs.
 */
@@ -3295,11 +3496,11 @@ OGRLayerH GDALDatasetGetLayerByName( GDALDatasetH hDS, const char *pszName )
  the ODsCDeleteLayer capability will test TRUE on the GDALDataset.
 
  This method is the same as the C++ method GDALDataset::DeleteLayer().
- 
+
  @since GDAL 2.0
 
  @param hDS the dataset handle.
- @param iLayer the index of the layer to delete. 
+ @param iLayer the index of the layer to delete.
 
  @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
  layers is not supported for this datasource.
@@ -3322,33 +3523,32 @@ OGRErr GDALDatasetDeleteLayer( GDALDatasetH hDS, int iLayer )
 
 The papszOptions argument
 can be used to control driver specific creation options.  These options are
-normally documented in the format specific documentation. 
+normally documented in the format specific documentation.
 
  In GDAL 2.0, drivers should extend the ICreateLayer() method and not CreateLayer().
  CreateLayer() adds validation of layer creation options, before delegating the
  actual work to ICreateLayer().
 
  This method is the same as the C function GDALDatasetCreateLayer() and the
- deprecated OGR_DS_CreateLayer(). 
- 
+ deprecated OGR_DS_CreateLayer().
+
  In GDAL 1.X, this method used to be in the OGRDataSource class.
 
- @param hDS the dataset handle
- @param pszName the name for the new layer.  This should ideally not 
+ @param pszName the name for the new layer.  This should ideally not
 match any existing layer on the datasource.
  @param poSpatialRef the coordinate system to use for the new layer, or NULL if
-no coordinate system is available. 
+no coordinate system is available.
  @param eGType the geometry type for the layer.  Use wkbUnknown if there
-are no constraints on the types geometry to be written. 
+are no constraints on the types geometry to be written.
  @param papszOptions a StringList of name=value options.  Options are driver
 specific.
 
- @return NULL is returned on failure, or a new OGRLayer handle on success. 
+ @return NULL is returned on failure, or a new OGRLayer handle on success.
 
 <b>Example:</b>
 
 \code
-#include "gdal.h" 
+#include "gdal.h"
 #include "cpl_string.h"
 
 ...
@@ -3369,7 +3569,7 @@ specific.
         if( poLayer == NULL )
         {
             ...
-        }        
+        }
 \endcode
 */
 
@@ -3409,28 +3609,28 @@ OGRLayer *GDALDataset::CreateLayer( const char * pszName,
 
 The papszOptions argument
 can be used to control driver specific creation options.  These options are
-normally documented in the format specific documentation. 
+normally documented in the format specific documentation.
 
  This method is the same as the C++ method GDALDataset::CreateLayer().
- 
+
  @since GDAL 2.0
 
  @param hDS the dataset handle
- @param pszName the name for the new layer.  This should ideally not 
+ @param pszName the name for the new layer.  This should ideally not
 match any existing layer on the datasource.
- @param poSpatialRef the coordinate system to use for the new layer, or NULL if
-no coordinate system is available. 
+ @param hSpatialRef the coordinate system to use for the new layer, or NULL if
+no coordinate system is available.
  @param eGType the geometry type for the layer.  Use wkbUnknown if there
-are no constraints on the types geometry to be written. 
+are no constraints on the types geometry to be written.
  @param papszOptions a StringList of name=value options.  Options are driver
 specific.
 
- @return NULL is returned on failure, or a new OGRLayer handle on success. 
+ @return NULL is returned on failure, or a new OGRLayer handle on success.
 
 <b>Example:</b>
 
 \code
-#include "gdal.h" 
+#include "gdal.h"
 #include "cpl_string.h"
 
 ...
@@ -3451,14 +3651,14 @@ specific.
         if( poLayer == NULL )
         {
             ...
-        }        
+        }
 \endcode
 */
 
-OGRLayerH GDALDatasetCreateLayer( GDALDatasetH hDS, 
+OGRLayerH GDALDatasetCreateLayer( GDALDatasetH hDS,
                               const char * pszName,
                               OGRSpatialReferenceH hSpatialRef,
-                              OGRwkbGeometryType eType,
+                              OGRwkbGeometryType eGType,
                               char ** papszOptions )
 
 {
@@ -3467,10 +3667,10 @@ OGRLayerH GDALDatasetCreateLayer( GDALDatasetH hDS,
     if (pszName == NULL)
     {
         CPLError ( CE_Failure, CPLE_ObjectNull, "Name was NULL in GDALDatasetCreateLayer");
-        return 0;
+        return NULL;
     }
-    return (OGRLayerH) ((GDALDataset *)hDS)->CreateLayer( 
-        pszName, (OGRSpatialReference *) hSpatialRef, eType, papszOptions );
+    return (OGRLayerH) ((GDALDataset *)hDS)->CreateLayer(
+        pszName, (OGRSpatialReference *) hSpatialRef, eGType, papszOptions );
 }
 
 
@@ -3489,10 +3689,10 @@ OGRLayerH GDALDatasetCreateLayer( GDALDatasetH hDS,
  The source layer may come from another dataset.
 
  This method is the same as the C++ method GDALDataset::CopyLayer()
- 
+
  @since GDAL 2.0
 
- @param hDS the dataset handle. 
+ @param hDS the dataset handle.
  @param hSrcLayer source layer.
  @param pszNewName the name of the layer to create.
  @param papszOptions a StringList of name=value options.  Options are driver
@@ -3500,7 +3700,7 @@ OGRLayerH GDALDatasetCreateLayer( GDALDatasetH hDS,
 
  @return an handle to the layer, or NULL if an error occurs.
 */
-OGRLayerH GDALDatasetCopyLayer( GDALDatasetH hDS, 
+OGRLayerH GDALDatasetCopyLayer( GDALDatasetH hDS,
                                 OGRLayerH hSrcLayer, const char *pszNewName,
                                 char **papszOptions )
 
@@ -3509,8 +3709,8 @@ OGRLayerH GDALDatasetCopyLayer( GDALDatasetH hDS,
     VALIDATE_POINTER1( hSrcLayer, "GDALDatasetCopyLayer", NULL );
     VALIDATE_POINTER1( pszNewName, "GDALDatasetCopyLayer", NULL );
 
-    return (OGRLayerH) 
-        ((GDALDataset *) hDS)->CopyLayer( (OGRLayer *) hSrcLayer, 
+    return (OGRLayerH)
+        ((GDALDataset *) hDS)->CopyLayer( (OGRLayer *) hSrcLayer,
                                             pszNewName, papszOptions );
 }
 
@@ -3519,28 +3719,28 @@ OGRLayerH GDALDatasetCopyLayer( GDALDatasetH hDS,
 /************************************************************************/
 
 /**
- \brief Execute an SQL statement against the data store. 
+ \brief Execute an SQL statement against the data store.
 
  The result of an SQL query is either NULL for statements that are in error,
  or that have no results set, or an OGRLayer pointer representing a results
  set from the query.  Note that this OGRLayer is in addition to the layers
- in the data store and must be destroyed with 
+ in the data store and must be destroyed with
  ReleaseResultSet() before the dataset is closed
- (destroyed).  
+ (destroyed).
 
  This method is the same as the C++ method GDALDataset::ExecuteSQL()
 
  For more information on the SQL dialect supported internally by OGR
- review the <a href="ogr_sql.html">OGR SQL</a> document.  Some drivers (ie.
+ review the <a href="ogr_sql.html">OGR SQL</a> document.  Some drivers (i.e.
  Oracle and PostGIS) pass the SQL directly through to the underlying RDBMS.
 
  Starting with OGR 1.10, the <a href="ogr_sql_sqlite.html">SQLITE dialect</a>
  can also be used.
- 
+
  @since GDAL 2.0
- 
+
  @param hDS the dataset handle.
- @param pszStatement the SQL statement to execute. 
+ @param pszStatement the SQL statement to execute.
  @param hSpatialFilter geometry which represents a spatial filter. Can be NULL.
  @param pszDialect allows control of the statement dialect. If set to NULL, the
 OGR SQL engine will be used, except for RDBMS drivers that will use their dedicated SQL engine,
@@ -3552,7 +3752,7 @@ can also be used.
 
 */
 
-OGRLayerH GDALDatasetExecuteSQL( GDALDatasetH hDS, 
+OGRLayerH GDALDatasetExecuteSQL( GDALDatasetH hDS,
                              const char *pszStatement,
                              OGRGeometryH hSpatialFilter,
                              const char *pszDialect )
@@ -3560,7 +3760,7 @@ OGRLayerH GDALDatasetExecuteSQL( GDALDatasetH hDS,
 {
     VALIDATE_POINTER1( hDS, "GDALDatasetExecuteSQL", NULL );
 
-    return (OGRLayerH) 
+    return (OGRLayerH)
         ((GDALDataset *)hDS)->ExecuteSQL( pszStatement,
                                             (OGRGeometry *) hSpatialFilter,
                                             pszDialect );
@@ -3572,11 +3772,11 @@ OGRLayerH GDALDatasetExecuteSQL( GDALDatasetH hDS,
 
 /**
  \brief Returns dataset style table.
- 
+
  This function is the same as the C++ method GDALDataset::GetStyleTable()
- 
+
  @since GDAL 2.0
- 
+
  @param hDS the dataset handle
  @return handle to a style table which should not be modified or freed by the
  caller.
@@ -3586,7 +3786,7 @@ OGRStyleTableH GDALDatasetGetStyleTable( GDALDatasetH hDS )
 
 {
     VALIDATE_POINTER1( hDS, "OGR_DS_GetStyleTable", NULL );
-    
+
     return (OGRStyleTableH) ((GDALDataset *) hDS)->GetStyleTable( );
 }
 
@@ -3596,14 +3796,14 @@ OGRStyleTableH GDALDatasetGetStyleTable( GDALDatasetH hDS )
 
 /**
  \brief Set dataset style table.
- 
+
  This function operate exactly as GDALDatasetSetStyleTable() except that it
  assumes ownership of the passed table.
- 
+
  This function is the same as the C++ method GDALDataset::SetStyleTableDirectly()
- 
+
  @since GDAL 2.0
- 
+
  @param hDS the dataset handle
  @param hStyleTable style table handle to set
 
@@ -3614,7 +3814,7 @@ void GDALDatasetSetStyleTableDirectly( GDALDatasetH hDS,
 
 {
     VALIDATE_POINTER0( hDS, "OGR_DS_SetStyleTableDirectly" );
-    
+
     ((GDALDataset *) hDS)->SetStyleTableDirectly( (OGRStyleTable *) hStyleTable);
 }
 
@@ -3624,14 +3824,14 @@ void GDALDatasetSetStyleTableDirectly( GDALDatasetH hDS,
 
 /**
  \brief Set dataset style table.
- 
+
  This function operate exactly as GDALDatasetSetStyleTableDirectly() except that it
  assumes ownership of the passed table.
- 
+
  This function is the same as the C++ method GDALDataset::SetStyleTable()
- 
+
  @since GDAL 2.0
- 
+
  @param hDS the dataset handle
  @param hStyleTable style table handle to set
 
@@ -3642,7 +3842,7 @@ void GDALDatasetSetStyleTable( GDALDatasetH hDS, OGRStyleTableH hStyleTable )
 {
     VALIDATE_POINTER0( hDS, "OGR_DS_SetStyleTable" );
     VALIDATE_POINTER0( hStyleTable, "OGR_DS_SetStyleTable" );
-    
+
     ((GDALDataset *) hDS)->SetStyleTable( (OGRStyleTable *) hStyleTable);
 }
 
@@ -3655,7 +3855,7 @@ int GDALDataset::ValidateLayerCreationOptions( const char* const* papszLCO )
     const char *pszOptionList = GetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST );
     if( pszOptionList == NULL && poDriver != NULL )
     {
-        pszOptionList = 
+        pszOptionList =
              poDriver->GetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST );
     }
     CPLString osDataset;
@@ -3670,15 +3870,13 @@ int GDALDataset::ValidateLayerCreationOptions( const char* const* papszLCO )
 /************************************************************************/
 
 /**
- \fn OGRErr OGRDataSource::Release();
-
 \brief Drop a reference to this dataset, and if the reference count drops to one close (destroy) the dataset.
 
 This method is the same as the C function OGRReleaseDataSource().
 
 @deprecated. In GDAL 2, use GDALClose() instead
 
- at return OGRERR_NONE on success or an error code. 
+ at return OGRERR_NONE on success or an error code.
 */
 
 OGRErr GDALDataset::Release()
@@ -3721,7 +3919,7 @@ This method is the same as the C function  OGR_DS_GetSummaryRefCount().
 In GDAL 1.X, this method used to be in the OGRDataSource class.
 
 @deprecated
- 
+
 @return the current summary reference count for the datasource and its layers.
 */
 
@@ -3729,7 +3927,7 @@ int GDALDataset::GetSummaryRefCount() const
 
 {
     GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
-    CPLMutexHolderD( &(psPrivate->hMutex) );
+    CPLMutexHolderD( psPrivate ? &(psPrivate->hMutex) : NULL );
     int nSummaryCount = nRefCount;
     int iLayer;
     GDALDataset *poUseThis = (GDALDataset *) this;
@@ -3751,19 +3949,19 @@ This method is reserved to implementation by drivers.
 
 The papszOptions argument
 can be used to control driver specific creation options.  These options are
-normally documented in the format specific documentation. 
+normally documented in the format specific documentation.
 
- @param pszName the name for the new layer.  This should ideally not 
+ @param pszName the name for the new layer.  This should ideally not
 match any existing layer on the datasource.
  @param poSpatialRef the coordinate system to use for the new layer, or NULL if
-no coordinate system is available. 
+no coordinate system is available.
  @param eGType the geometry type for the layer.  Use wkbUnknown if there
-are no constraints on the types geometry to be written. 
+are no constraints on the types geometry to be written.
  @param papszOptions a StringList of name=value options.  Options are driver
 specific.
 
- @return NULL is returned on failure, or a new OGRLayer handle on success. 
- 
+ @return NULL is returned on failure, or a new OGRLayer handle on success.
+
  @since GDAL 2.0
 */
 
@@ -3780,7 +3978,7 @@ OGRLayer *GDALDataset::ICreateLayer( const char * pszName,
 
     CPLError( CE_Failure, CPLE_NotSupported,
               "CreateLayer() not supported by this dataset." );
-              
+
     return NULL;
 }
 
@@ -3802,17 +4000,19 @@ OGRLayer *GDALDataset::ICreateLayer( const char * pszName,
  deprecated OGR_DS_CopyLayer().
 
  In GDAL 1.X, this method used to be in the OGRDataSource class.
- 
+
  @param poSrcLayer source layer.
  @param pszNewName the name of the layer to create.
  @param papszOptions a StringList of name=value options.  Options are driver
-                     specific.
+                     specific. There is a common option to set output layer
+                     spatial reference: DST_SRSWKT. The option should be in
+                     WKT format.
 
  @return an handle to the layer, or NULL if an error occurs.
 */
 
-OGRLayer *GDALDataset::CopyLayer( OGRLayer *poSrcLayer, 
-                                    const char *pszNewName, 
+OGRLayer *GDALDataset::CopyLayer( OGRLayer *poSrcLayer,
+                                    const char *pszNewName,
                                     char **papszOptions )
 
 {
@@ -3824,11 +4024,14 @@ OGRLayer *GDALDataset::CopyLayer( OGRLayer *poSrcLayer,
 /* -------------------------------------------------------------------- */
     if( !TestCapability( ODsCCreateLayer ) )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "This datasource does not support creation of layers." );
         return NULL;
     }
 
+    const char* pszSRSWKT = CSLFetchNameValue(papszOptions, "DST_SRSWKT");
+    OGRSpatialReference oDstSpaRef(pszSRSWKT);
+
     CPLErrorReset();
     if( poSrcDefn->GetGeomFieldCount() > 1 &&
         TestCapability(ODsCCreateGeomFieldAfterCreateLayer) )
@@ -3837,10 +4040,21 @@ OGRLayer *GDALDataset::CopyLayer( OGRLayer *poSrcLayer,
     }
     else
     {
+        if(NULL == pszSRSWKT)
+        {
         poDstLayer =ICreateLayer( pszNewName, poSrcLayer->GetSpatialRef(),
                                   poSrcDefn->GetGeomType(), papszOptions );
     }
-    
+        else
+        {
+            // remove DST_WKT from option list to prevent WARNINfrom driver
+            int nSRSPos = CSLFindName(papszOptions, "DST_SRSWKT");
+            papszOptions = CSLRemoveStrings(papszOptions, nSRSPos, 1, NULL);
+            poDstLayer = ICreateLayer( pszNewName, &oDstSpaRef,
+                                  poSrcDefn->GetGeomType(), papszOptions );
+        }
+    }
+
     if( poDstLayer == NULL )
         return NULL;
 
@@ -3863,7 +4077,7 @@ OGRLayer *GDALDataset::CopyLayer( OGRLayer *poSrcLayer,
     /* returns NULL until a field has been added */
     OGRFeatureDefn* poDstFDefn = poDstLayer->GetLayerDefn();
     if (poDstFDefn)
-        nDstFieldCount = poDstFDefn->GetFieldCount();    
+        nDstFieldCount = poDstFDefn->GetFieldCount();
     for( iField = 0; iField < nSrcFieldCount; iField++ )
     {
         OGRFieldDefn* poSrcFieldDefn = poSrcDefn->GetFieldDefn(iField);
@@ -3900,16 +4114,43 @@ OGRLayer *GDALDataset::CopyLayer( OGRLayer *poSrcLayer,
     }
 
 /* -------------------------------------------------------------------- */
+    OGRCoordinateTransformation *poCT = NULL;
+    OGRSpatialReference *sourceSRS = poSrcLayer->GetSpatialRef();
+    if (sourceSRS != NULL && pszSRSWKT != NULL &&
+            sourceSRS->IsSame(&oDstSpaRef) == FALSE)
+    {
+        poCT = (OGRCoordinateTransformation*)OGRCreateCoordinateTransformation(sourceSRS, &oDstSpaRef);
+        if(NULL == poCT)
+        {
+            CPLError( CE_Failure, CPLE_NotSupported,
+                      "This input/output spatial reference is not supported." );
+            CPLFree(panMap);
+            return NULL;
+        }
+    }
 /*      Create geometry fields.                                         */
 /* -------------------------------------------------------------------- */
-    if( poSrcDefn->GetGeomFieldCount() > 1 &&
+/*      Create geometry fields.                                         */
+/* -------------------------------------------------------------------- */
+    int nSrcGeomFieldCount = poSrcDefn->GetGeomFieldCount();
+    if( nSrcGeomFieldCount > 1 &&
         TestCapability(ODsCCreateGeomFieldAfterCreateLayer) )
     {
-        int nSrcGeomFieldCount = poSrcDefn->GetGeomFieldCount();
+
         for( iField = 0; iField < nSrcGeomFieldCount; iField++ )
         {
+            if(NULL == pszSRSWKT)
+        {
             poDstLayer->CreateGeomField( poSrcDefn->GetGeomFieldDefn(iField) );
         }
+            else
+            {
+                OGRGeomFieldDefn* pDstGeomFieldDefn =
+                        poSrcDefn->GetGeomFieldDefn(iField);
+                pDstGeomFieldDefn->SetSpatialRef(&oDstSpaRef);
+                poDstLayer->CreateGeomField(pDstGeomFieldDefn);
+            }
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -3929,12 +4170,12 @@ OGRLayer *GDALDataset::CopyLayer( OGRLayer *poSrcLayer,
 
     if( nGroupTransactions <= 0 )
     {
-      while( TRUE )
+      while( true )
       {
         OGRFeature      *poDstFeature = NULL;
 
         poFeature = poSrcLayer->GetNextFeature();
-        
+
         if( poFeature == NULL )
             break;
 
@@ -3948,9 +4189,34 @@ OGRLayer *GDALDataset::CopyLayer( OGRLayer *poSrcLayer,
                       poFeature->GetFID(), poSrcDefn->GetName() );
             OGRFeature::DestroyFeature( poFeature );
             CPLFree(panMap);
+            if(NULL != poCT)
+                OCTDestroyCoordinateTransformation((OGRCoordinateTransformationH)poCT);
             return poDstLayer;
         }
 
+        if(NULL != poCT)
+        {
+            for( iField = 0; iField < nSrcGeomFieldCount; iField++ )
+            {
+                OGRGeometry* pGeom = poDstFeature->GetGeomFieldRef(iField);
+                if(NULL != pGeom)
+                {
+                    OGRErr eErr = pGeom->transform(poCT);
+                    if(eErr != OGRERR_NONE)
+                    {
+                        CPLError( CE_Failure, CPLE_AppDefined,
+                                  "Unable to transform geometry " CPL_FRMT_GIB
+                                  " from layer %s.\n",
+                                  poFeature->GetFID(), poSrcDefn->GetName() );
+                        OGRFeature::DestroyFeature( poFeature );
+                        CPLFree(panMap);
+                        OCTDestroyCoordinateTransformation((OGRCoordinateTransformationH)poCT);
+                        return poDstLayer;
+                    }
+                }
+            }
+        }
+
         poDstFeature->SetFID( poFeature->GetFID() );
 
         OGRFeature::DestroyFeature( poFeature );
@@ -3960,6 +4226,8 @@ OGRLayer *GDALDataset::CopyLayer( OGRLayer *poSrcLayer,
         {
             OGRFeature::DestroyFeature( poDstFeature );
             CPLFree(panMap);
+            if(NULL != poCT)
+                OCTDestroyCoordinateTransformation((OGRCoordinateTransformationH)poCT);
             return poDstLayer;
         }
 
@@ -3968,11 +4236,14 @@ OGRLayer *GDALDataset::CopyLayer( OGRLayer *poSrcLayer,
     }
     else
     {
-      int i, bStopTransfer = FALSE, bStopTransaction = FALSE;
+      bool bStopTransfer = false;
+      bool bStopTransaction = false;
       int nFeatCount = 0; // Number of features in the temporary array
       int nFeaturesToAdd = 0;
       OGRFeature **papoDstFeature =
-          (OGRFeature **)CPLCalloc(sizeof(OGRFeature *), nGroupTransactions);
+          (OGRFeature **)VSI_CALLOC_VERBOSE(sizeof(OGRFeature *), nGroupTransactions);
+      if( papoDstFeature == NULL )
+          bStopTransfer = true;
       while( !bStopTransfer )
       {
 /* -------------------------------------------------------------------- */
@@ -3984,7 +4255,7 @@ OGRLayer *GDALDataset::CopyLayer( OGRLayer *poSrcLayer,
 
             if( poFeature == NULL )
             {
-                bStopTransfer = 1;
+                bStopTransfer = true;
                 break;
             }
 
@@ -3998,43 +4269,77 @@ OGRLayer *GDALDataset::CopyLayer( OGRLayer *poSrcLayer,
                           "Unable to translate feature " CPL_FRMT_GIB " from layer %s.\n",
                           poFeature->GetFID(), poSrcDefn->GetName() );
                 OGRFeature::DestroyFeature( poFeature );
-                bStopTransfer = TRUE;
+                poFeature = NULL;
+                bStopTransfer = true;
                 break;
             }
 
-            papoDstFeature[nFeatCount]->SetFID( poFeature->GetFID() );
+            if(NULL != poCT)
+            {
+                for( iField = 0; iField < nSrcGeomFieldCount; iField++ )
+                {
+                    OGRGeometry* pGeom = papoDstFeature[nFeatCount]->GetGeomFieldRef(iField);
+                    if(NULL != pGeom)
+                    {
+                        OGRErr eErr = pGeom->transform(poCT);
+                        if(eErr != OGRERR_NONE)
+                        {
+                            CPLError( CE_Failure, CPLE_AppDefined,
+                                      "Unable to transform geometry " CPL_FRMT_GIB
+                                      " from layer %s.\n",
+                                      poFeature->GetFID(), poSrcDefn->GetName() );
+                            OGRFeature::DestroyFeature( poFeature );
+                            bStopTransfer = true;
+                            poFeature = NULL;
+                            break;
+                        }
+                    }
+                }
+            }
 
-            OGRFeature::DestroyFeature( poFeature );
+            if (poFeature)
+            {
+                papoDstFeature[nFeatCount]->SetFID( poFeature->GetFID() );
+                OGRFeature::DestroyFeature( poFeature );
+                poFeature = NULL;
+            }
         }
         nFeaturesToAdd = nFeatCount;
 
         CPLErrorReset();
-        bStopTransaction = FALSE;
+        bStopTransaction = false;
         while( !bStopTransaction )
         {
-            bStopTransaction = TRUE;
-            poDstLayer->StartTransaction();
-            for( i = 0; i < nFeaturesToAdd; i++ )
+            bStopTransaction = true;
+            if( poDstLayer->StartTransaction() != OGRERR_NONE )
+                break;
+            for( int i = 0; i < nFeaturesToAdd; i++ )
             {
                 if( poDstLayer->CreateFeature( papoDstFeature[i] ) != OGRERR_NONE )
                 {
                     nFeaturesToAdd = i;
-                    bStopTransfer = TRUE;
-                    bStopTransaction = FALSE;
+                    bStopTransfer = true;
+                    bStopTransaction = false;
                 }
             }
             if( bStopTransaction )
-                poDstLayer->CommitTransaction();
+            {
+                if( poDstLayer->CommitTransaction() != OGRERR_NONE )
+                    break;
+            }
             else
                 poDstLayer->RollbackTransaction();
         }
 
-        for( i = 0; i < nFeatCount; i++ )
+        for( int i = 0; i < nFeatCount; i++ )
             OGRFeature::DestroyFeature( papoDstFeature[i] );
       }
       CPLFree(papoDstFeature);
     }
 
+    if(NULL != poCT)
+        OCTDestroyCoordinateTransformation((OGRCoordinateTransformationH)poCT);
+
     CPLFree(panMap);
 
     return poDstLayer;
@@ -4052,10 +4357,10 @@ OGRLayer *GDALDataset::CopyLayer( OGRLayer *poSrcLayer,
 
  This method is the same as the C function GDALDatasetDeleteLayer() and the
  deprecated OGR_DS_DeleteLayer().
- 
+
  In GDAL 1.X, this method used to be in the OGRDataSource class.
 
- @param iLayer the index of the layer to delete. 
+ @param iLayer the index of the layer to delete.
 
  @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
  layers is not supported for this datasource.
@@ -4067,7 +4372,7 @@ OGRErr GDALDataset::DeleteLayer( int iLayer )
     (void) iLayer;
     CPLError( CE_Failure, CPLE_NotSupported,
               "DeleteLayer() not supported by this dataset." );
-              
+
     return OGRERR_UNSUPPORTED_OPERATION;
 }
 
@@ -4078,15 +4383,15 @@ OGRErr GDALDataset::DeleteLayer( int iLayer )
 /**
  \brief Fetch a layer by name.
 
- The returned layer remains owned by the 
+ The returned layer remains owned by the
  GDALDataset and should not be deleted by the application.
 
  This method is the same as the C function GDALDatasetGetLayerByName() and the
  deprecated OGR_DS_GetLayerByName().
- 
+
  In GDAL 1.X, this method used to be in the OGRDataSource class.
 
- @param pszLayerName the layer name of the layer to fetch.
+ @param pszName the layer name of the layer to fetch.
 
  @return the layer, or NULL if Layer is not found or an error occurs.
 */
@@ -4095,7 +4400,7 @@ OGRLayer *GDALDataset::GetLayerByName( const char *pszName )
 
 {
     GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
-    CPLMutexHolderD( &(psPrivate->hMutex) );
+    CPLMutexHolderD( psPrivate ? &(psPrivate->hMutex) : NULL );
 
     if ( ! pszName )
         return NULL;
@@ -4140,14 +4445,14 @@ OGRErr GDALDataset::ProcessSQLCreateIndex( const char *pszSQLCommand )
 /* -------------------------------------------------------------------- */
 /*      Do some general syntax checking.                                */
 /* -------------------------------------------------------------------- */
-    if( CSLCount(papszTokens) != 6 
+    if( CSLCount(papszTokens) != 6
         || !EQUAL(papszTokens[0],"CREATE")
         || !EQUAL(papszTokens[1],"INDEX")
         || !EQUAL(papszTokens[2],"ON")
         || !EQUAL(papszTokens[4],"USING") )
     {
         CSLDestroy( papszTokens );
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Syntax error in CREATE INDEX command.\n"
                   "Was '%s'\n"
                   "Should be of form 'CREATE INDEX ON <table> USING <field>'",
@@ -4163,19 +4468,20 @@ OGRErr GDALDataset::ProcessSQLCreateIndex( const char *pszSQLCommand )
 
     {
         GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
-        CPLMutexHolderD( &(psPrivate->hMutex) );
+        CPLMutexHolderD( psPrivate ? &(psPrivate->hMutex) : NULL );
 
         for( i = 0; i < GetLayerCount(); i++ )
         {
             poLayer = GetLayer(i);
-            
-            if( EQUAL(poLayer->GetName(),papszTokens[3]) )
+
+            if( poLayer!= NULL && EQUAL(poLayer->GetName(),papszTokens[3]) )
                 break;
+            poLayer = NULL;
         }
-        
-        if( i >= GetLayerCount() )
+
+        if( poLayer == NULL )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "CREATE INDEX ON failed, no such layer as `%s'.",
                       papszTokens[3] );
             CSLDestroy( papszTokens );
@@ -4188,7 +4494,7 @@ OGRErr GDALDataset::ProcessSQLCreateIndex( const char *pszSQLCommand )
 /* -------------------------------------------------------------------- */
     if( poLayer->GetIndex() == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "CREATE INDEX ON not supported by this driver." );
         CSLDestroy( papszTokens );
         return OGRERR_FAILURE;
@@ -4208,7 +4514,7 @@ OGRErr GDALDataset::ProcessSQLCreateIndex( const char *pszSQLCommand )
 
     if( i >= poLayer->GetLayerDefn()->GetFieldCount() )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "`%s' failed, field not found.",
                   pszSQLCommand );
         return OGRERR_FAILURE;
@@ -4235,7 +4541,7 @@ OGRErr GDALDataset::ProcessSQLCreateIndex( const char *pszSQLCommand )
 /************************************************************************/
 /*                        ProcessSQLDropIndex()                         */
 /*                                                                      */
-/*      The correct syntax for droping one or more indexes in           */
+/*      The correct syntax for dropping one or more indexes in          */
 /*      the OGR SQL dialect is:                                         */
 /*                                                                      */
 /*          DROP INDEX ON <layername> [USING <columnname>]              */
@@ -4252,11 +4558,11 @@ OGRErr GDALDataset::ProcessSQLDropIndex( const char *pszSQLCommand )
     if( (CSLCount(papszTokens) != 4 && CSLCount(papszTokens) != 6)
         || !EQUAL(papszTokens[0],"DROP")
         || !EQUAL(papszTokens[1],"INDEX")
-        || !EQUAL(papszTokens[2],"ON") 
+        || !EQUAL(papszTokens[2],"ON")
         || (CSLCount(papszTokens) == 6 && !EQUAL(papszTokens[4],"USING")) )
     {
         CSLDestroy( papszTokens );
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Syntax error in DROP INDEX command.\n"
                   "Was '%s'\n"
                   "Should be of form 'DROP INDEX ON <table> [USING <field>]'",
@@ -4272,19 +4578,20 @@ OGRErr GDALDataset::ProcessSQLDropIndex( const char *pszSQLCommand )
 
     {
         GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
-        CPLMutexHolderD( &(psPrivate->hMutex) );
+        CPLMutexHolderD( psPrivate ? &(psPrivate->hMutex) : NULL );
 
         for( i = 0; i < GetLayerCount(); i++ )
         {
             poLayer = GetLayer(i);
-        
-            if( EQUAL(poLayer->GetName(),papszTokens[3]) )
+
+            if( poLayer!= NULL && EQUAL(poLayer->GetName(),papszTokens[3]) )
                 break;
+            poLayer = NULL;
         }
 
-        if( i >= GetLayerCount() )
+        if( poLayer == NULL )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "CREATE INDEX ON failed, no such layer as `%s'.",
                       papszTokens[3] );
             CSLDestroy( papszTokens );
@@ -4297,14 +4604,14 @@ OGRErr GDALDataset::ProcessSQLDropIndex( const char *pszSQLCommand )
 /* -------------------------------------------------------------------- */
     if( poLayer->GetIndex() == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Indexes not supported by this driver." );
         CSLDestroy( papszTokens );
         return OGRERR_FAILURE;
     }
 
 /* -------------------------------------------------------------------- */
-/*      If we weren't given a field name, drop all indexes.             */
+/*      If we were not given a field name, drop all indexes.            */
 /* -------------------------------------------------------------------- */
     OGRErr eErr;
 
@@ -4344,7 +4651,7 @@ OGRErr GDALDataset::ProcessSQLDropIndex( const char *pszSQLCommand )
 
     if( i >= poLayer->GetLayerDefn()->GetFieldCount() )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "`%s' failed, field not found.",
                   pszSQLCommand );
         return OGRERR_FAILURE;
@@ -4380,7 +4687,7 @@ OGRErr GDALDataset::ProcessSQLDropTable( const char *pszSQLCommand )
         || !EQUAL(papszTokens[1],"TABLE") )
     {
         CSLDestroy( papszTokens );
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Syntax error in DROP TABLE command.\n"
                   "Was '%s'\n"
                   "Should be of form 'DROP TABLE <table>'",
@@ -4397,14 +4704,15 @@ OGRErr GDALDataset::ProcessSQLDropTable( const char *pszSQLCommand )
     for( i = 0; i < GetLayerCount(); i++ )
     {
         poLayer = GetLayer(i);
-        
-        if( EQUAL(poLayer->GetName(),papszTokens[2]) )
+
+        if( poLayer!= NULL && EQUAL(poLayer->GetName(),papszTokens[2]) )
             break;
+        poLayer = NULL;
     }
-    
-    if( i >= GetLayerCount() )
+
+    if( poLayer == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "DROP TABLE failed, no such layer as `%s'.",
                   papszTokens[2] );
         CSLDestroy( papszTokens );
@@ -4575,7 +4883,7 @@ OGRErr GDALDataset::ProcessSQLAlterTableAddColumn( const char *pszSQLCommand )
 /************************************************************************/
 /*                    ProcessSQLAlterTableDropColumn()                  */
 /*                                                                      */
-/*      The correct syntax for droping a column in the OGR SQL          */
+/*      The correct syntax for dropping a column in the OGR SQL         */
 /*      dialect is:                                                     */
 /*                                                                      */
 /*          ALTER TABLE <layername> DROP [COLUMN] <columnname>          */
@@ -4861,19 +5169,19 @@ OGRErr GDALDataset::ProcessSQLAlterTableAlterColumn( const char *pszSQLCommand )
     oNewFieldDefn.SetWidth(nWidth);
     oNewFieldDefn.SetPrecision(nPrecision);
 
-    int nFlags = 0;
+    int l_nFlags = 0;
     if (poOldFieldDefn->GetType() != oNewFieldDefn.GetType())
-        nFlags |= ALTER_TYPE_FLAG;
+        l_nFlags |= ALTER_TYPE_FLAG;
     if (poOldFieldDefn->GetWidth() != oNewFieldDefn.GetWidth() ||
         poOldFieldDefn->GetPrecision() != oNewFieldDefn.GetPrecision())
-        nFlags |= ALTER_WIDTH_PRECISION_FLAG;
+        l_nFlags |= ALTER_WIDTH_PRECISION_FLAG;
 
     CSLDestroy( papszTokens );
 
-    if (nFlags == 0)
+    if (l_nFlags == 0)
         return OGRERR_NONE;
     else
-        return poLayer->AlterFieldDefn( nFieldIndex, &oNewFieldDefn, nFlags );
+        return poLayer->AlterFieldDefn( nFieldIndex, &oNewFieldDefn, l_nFlags );
 }
 
 /************************************************************************/
@@ -4881,28 +5189,28 @@ OGRErr GDALDataset::ProcessSQLAlterTableAlterColumn( const char *pszSQLCommand )
 /************************************************************************/
 
 /**
- \brief Execute an SQL statement against the data store. 
+ \brief Execute an SQL statement against the data store.
 
  The result of an SQL query is either NULL for statements that are in error,
  or that have no results set, or an OGRLayer pointer representing a results
  set from the query.  Note that this OGRLayer is in addition to the layers
- in the data store and must be destroyed with 
+ in the data store and must be destroyed with
  ReleaseResultSet() before the dataset is closed
- (destroyed).  
+ (destroyed).
 
  This method is the same as the C function GDALDatasetExecuteSQL() and the
  deprecated OGR_DS_ExecuteSQL().
 
  For more information on the SQL dialect supported internally by OGR
- review the <a href="ogr_sql.html">OGR SQL</a> document.  Some drivers (ie.
+ review the <a href="ogr_sql.html">OGR SQL</a> document.  Some drivers (i.e.
  Oracle and PostGIS) pass the SQL directly through to the underlying RDBMS.
 
  Starting with OGR 1.10, the <a href="ogr_sql_sqlite.html">SQLITE dialect</a>
  can also be used.
 
  In GDAL 1.X, this method used to be in the OGRDataSource class.
- 
- @param pszStatement the SQL statement to execute. 
+
+ @param pszStatement the SQL statement to execute.
  @param poSpatialFilter geometry which represents a spatial filter. Can be NULL.
  @param pszDialect allows control of the statement dialect. If set to NULL, the
 OGR SQL engine will be used, except for RDBMS drivers that will use their dedicated SQL engine,
@@ -4944,25 +5252,25 @@ OGRLayer * GDALDataset::ExecuteSQL( const char *pszStatement,
 /* -------------------------------------------------------------------- */
 /*      Handle CREATE INDEX statements specially.                       */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszStatement,"CREATE INDEX",12) )
+    if( STARTS_WITH_CI(pszStatement, "CREATE INDEX") )
     {
         ProcessSQLCreateIndex( pszStatement );
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Handle DROP INDEX statements specially.                         */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszStatement,"DROP INDEX",10) )
+    if( STARTS_WITH_CI(pszStatement, "DROP INDEX") )
     {
         ProcessSQLDropIndex( pszStatement );
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Handle DROP TABLE statements specially.                         */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszStatement,"DROP TABLE",10) )
+    if( STARTS_WITH_CI(pszStatement, "DROP TABLE") )
     {
         ProcessSQLDropTable( pszStatement );
         return NULL;
@@ -4971,7 +5279,7 @@ OGRLayer * GDALDataset::ExecuteSQL( const char *pszStatement,
 /* -------------------------------------------------------------------- */
 /*      Handle ALTER TABLE statements specially.                        */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszStatement,"ALTER TABLE",11) )
+    if( STARTS_WITH_CI(pszStatement, "ALTER TABLE") )
     {
         char **papszTokens = CSLTokenizeString( pszStatement );
         if( CSLCount(papszTokens) >= 4 &&
@@ -5011,7 +5319,7 @@ OGRLayer * GDALDataset::ExecuteSQL( const char *pszStatement,
             return NULL;
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Preparse the SQL statement.                                     */
 /* -------------------------------------------------------------------- */
@@ -5020,7 +5328,7 @@ OGRLayer * GDALDataset::ExecuteSQL( const char *pszStatement,
     if( poSelectParseOptions != NULL )
         poCustomFuncRegistrar = poSelectParseOptions->poCustomFuncRegistrar;
     if( psSelectInfo->preparse( pszStatement,
-                                poCustomFuncRegistrar != NULL ) != CPLE_None )
+                                poCustomFuncRegistrar != NULL ) != CE_None )
     {
         delete psSelectInfo;
         return NULL;
@@ -5054,7 +5362,7 @@ OGRLayer * GDALDataset::ExecuteSQL( const char *pszStatement,
                                                      poSelectParseOptions);
         if( poLayer == NULL )
         {
-            /* Each source layer owns an independant select info */
+            /* Each source layer owns an independent select info. */
             for(int i=0;i<nSrcLayers;i++)
                 delete papoSrcLayers[i];
             CPLFree(papoSrcLayers);
@@ -5158,7 +5466,7 @@ GDALSQLParseInfo* GDALDataset::BuildParseInfo(swq_select* psSelectInfo,
     GDALSQLParseInfo* psParseInfo = (GDALSQLParseInfo*)CPLCalloc(1, sizeof(GDALSQLParseInfo));
 
 /* -------------------------------------------------------------------- */
-/*      Validate that all the source tables are recognised, count       */
+/*      Validate that all the source tables are recognized, count       */
 /*      fields.                                                         */
 /* -------------------------------------------------------------------- */
     int  nFieldCount = 0, iTable, iField;
@@ -5171,12 +5479,12 @@ GDALSQLParseInfo* GDALDataset::BuildParseInfo(swq_select* psSelectInfo,
 
         if( psTableDef->data_source != NULL )
         {
-            poTableDS = (GDALDataset *) 
+            poTableDS = (GDALDataset *)
                 OGROpenShared( psTableDef->data_source, FALSE, NULL );
             if( poTableDS == NULL )
             {
                 if( strlen(CPLGetLastErrorMsg()) == 0 )
-                    CPLError( CE_Failure, CPLE_AppDefined, 
+                    CPLError( CE_Failure, CPLE_AppDefined,
                               "Unable to open secondary datasource\n"
                               "`%s' required by JOIN.",
                               psTableDef->data_source );
@@ -5196,7 +5504,7 @@ GDALSQLParseInfo* GDALDataset::BuildParseInfo(swq_select* psSelectInfo,
 
         if( poSrcLayer == NULL )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "SELECT from table %s failed, no such table/featureclass.",
                       psTableDef->table_name );
 
@@ -5209,7 +5517,7 @@ GDALSQLParseInfo* GDALDataset::BuildParseInfo(swq_select* psSelectInfo,
                             poSelectParseOptions->bAddSecondaryTablesGeometryFields) )
             nFieldCount += poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Build the field list for all indicated tables.                  */
 /* -------------------------------------------------------------------- */
@@ -5219,22 +5527,22 @@ GDALSQLParseInfo* GDALDataset::BuildParseInfo(swq_select* psSelectInfo,
 
     psParseInfo->sFieldList.count = 0;
     psParseInfo->sFieldList.names = (char **) CPLMalloc( sizeof(char *) * (nFieldCount+SPECIAL_FIELD_COUNT) );
-    psParseInfo->sFieldList.types = (swq_field_type *)  
+    psParseInfo->sFieldList.types = (swq_field_type *)
         CPLMalloc( sizeof(swq_field_type) * (nFieldCount+SPECIAL_FIELD_COUNT) );
-    psParseInfo->sFieldList.table_ids = (int *) 
+    psParseInfo->sFieldList.table_ids = (int *)
         CPLMalloc( sizeof(int) * (nFieldCount+SPECIAL_FIELD_COUNT) );
-    psParseInfo->sFieldList.ids = (int *) 
+    psParseInfo->sFieldList.ids = (int *)
         CPLMalloc( sizeof(int) * (nFieldCount+SPECIAL_FIELD_COUNT) );
-    
+
     for( iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
     {
         swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
         GDALDataset *poTableDS = this;
         OGRLayer *poSrcLayer;
-        
+
         if( psTableDef->data_source != NULL )
         {
-            poTableDS = (GDALDataset *) 
+            poTableDS = (GDALDataset *)
                 OGROpenShared( psTableDef->data_source, FALSE, NULL );
             CPLAssert( poTableDS != NULL );
             poTableDS->Dereference();
@@ -5242,7 +5550,7 @@ GDALSQLParseInfo* GDALDataset::BuildParseInfo(swq_select* psSelectInfo,
 
         poSrcLayer = poTableDS->GetLayerByName( psTableDef->table_name );
 
-        for( iField = 0; 
+        for( iField = 0;
              iField < poSrcLayer->GetLayerDefn()->GetFieldCount();
              iField++ )
         {
@@ -5285,7 +5593,7 @@ GDALSQLParseInfo* GDALDataset::BuildParseInfo(swq_select* psSelectInfo,
         {
             nFIDIndex = psParseInfo->sFieldList.count;
 
-            for( iField = 0; 
+            for( iField = 0;
                  iField < poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
                  iField++ )
             {
@@ -5323,7 +5631,7 @@ GDALSQLParseInfo* GDALDataset::BuildParseInfo(swq_select* psSelectInfo,
         psParseInfo->sFieldList.ids[psParseInfo->sFieldList.count] = nFIDIndex + iField;
         psParseInfo->sFieldList.count++;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Finish the parse operation.                                     */
 /* -------------------------------------------------------------------- */
@@ -5354,16 +5662,16 @@ GDALSQLParseInfo* GDALDataset::BuildParseInfo(swq_select* psSelectInfo,
 
  This method should only be used to deallocate OGRLayers resulting from
  an ExecuteSQL() call on the same GDALDataset.  Failure to deallocate a
- results set before destroying the GDALDataset may cause errors. 
+ results set before destroying the GDALDataset may cause errors.
 
  This method is the same as the C function GDALDatasetReleaseResultSet() and the
  deprecated OGR_DS_ReleaseResultSet().
- 
+
  In GDAL 1.X, this method used to be in the OGRDataSource class.
- 
+
  @param poResultsSet the result of a previous ExecuteSQL() call.
+*/
 
-*/ 
 void GDALDataset::ReleaseResultSet( OGRLayer * poResultsSet )
 
 {
@@ -5376,12 +5684,12 @@ void GDALDataset::ReleaseResultSet( OGRLayer * poResultsSet )
 
 /**
  \brief Returns dataset style table.
- 
+
  This method is the same as the C function GDALDatasetGetStyleTable() and the
  deprecated OGR_DS_GetStyleTable().
- 
+
  In GDAL 1.X, this method used to be in the OGRDataSource class.
- 
+
  @return pointer to a style table which should not be modified or freed by the
  caller.
 */
@@ -5397,15 +5705,15 @@ OGRStyleTable *GDALDataset::GetStyleTable()
 
 /**
  \brief Set dataset style table.
- 
+
  This method operate exactly as SetStyleTable() except that it
  assumes ownership of the passed table.
- 
+
  This method is the same as the C function GDALDatasetSetStyleTableDirectly() and
  the deprecated OGR_DS_SetStyleTableDirectly().
- 
+
  In GDAL 1.X, this method used to be in the OGRDataSource class.
- 
+
  @param poStyleTable pointer to style table to set
 
 */
@@ -5422,15 +5730,15 @@ void GDALDataset::SetStyleTableDirectly( OGRStyleTable *poStyleTable )
 
 /**
  \brief Set dataset style table.
- 
+
  This method operate exactly as SetStyleTableDirectly() except
  that it does not assume ownership of the passed table.
- 
+
  This method is the same as the C function GDALDatasetSetStyleTable() and the
  deprecated OGR_DS_SetStyleTable().
- 
+
  In GDAL 1.X, this method used to be in the OGRDataSource class.
- 
+
  @param poStyleTable pointer to style table to set
 
 */
@@ -5463,7 +5771,7 @@ int GDALDataset::IsGenericSQLDialect(const char* pszDialect)
 
  This method is the same as the C function GDALDatasetGetLayerCount(),
  and the deprecated OGR_DS_GetLayerCount().
- 
+
  In GDAL 1.X, this method used to be in the OGRDataSource class.
 
  @return layer count.
@@ -5481,7 +5789,7 @@ int GDALDataset::GetLayerCount()
 /**
  \brief Fetch a layer by index.
 
- The returned layer remains owned by the 
+ The returned layer remains owned by the
  GDALDataset and should not be deleted by the application.
 
  This method is the same as the C function GDALDatasetGetLayer() and the
@@ -5521,17 +5829,16 @@ OGRLayer* GDALDataset::GetLayer(CPL_UNUSED int iLayer)
  </ul>
 
  The \#define macro forms of the capability names should be used in preference
- to the strings themselves to avoid mispelling.
+ to the strings themselves to avoid misspelling.
 
  This method is the same as the C function GDALDatasetTestCapability() and the
  deprecated OGR_DS_TestCapability().
 
  In GDAL 1.X, this method used to be in the OGRDataSource class.
 
- @param pszCapability the capability to test.
+ @param pszCap the capability to test.
 
  @return TRUE if capability available otherwise FALSE.
-
 */
 
 int GDALDataset::TestCapability( CPL_UNUSED const char * pszCap )
@@ -5544,38 +5851,39 @@ int GDALDataset::TestCapability( CPL_UNUSED const char * pszCap )
 /************************************************************************/
 
 /**
- \brief For datasources which support transactions, StartTransaction creates a transaction.
+ \brief For datasources which support transactions, StartTransaction creates a
+`transaction.
 
- If starting the transaction fails, will return 
- OGRERR_FAILURE. Datasources which do not support transactions will 
+ If starting the transaction fails, will return
+ OGRERR_FAILURE. Datasources which do not support transactions will
  always return OGRERR_UNSUPPORTED_OPERATION.
 
  Nested transactions are not supported.
- 
+
  All changes done after the start of the transaction are definitely applied in the
- datasource if CommitTransaction() is called. They may be cancelled by calling
+ datasource if CommitTransaction() is called. They may be canceled by calling
  RollbackTransaction() instead.
- 
+
  At the time of writing, transactions only apply on vector layers.
- 
- Datasets that support transactions will advertize the ODsCTransactions capability.
- Use of transactions at dataset level is generally prefered to transactions at
+
+ Datasets that support transactions will advertise the ODsCTransactions capability.
+ Use of transactions at dataset level is generally preferred to transactions at
  layer level, whose scope is rarely limited to the layer from which it was started.
- 
+
  In case StartTransaction() fails, neither CommitTransaction() or RollbackTransaction()
  should be called.
- 
+
  If an error occurs after a successful StartTransaction(), the whole
- transaction may or may not be implicitely cancelled, depending on drivers. (e.g.
+ transaction may or may not be implicitly canceled, depending on drivers. (e.g.
  the PG driver will cancel it, SQLite/GPKG not). In any case, in the event of an
  error, an explicit call to RollbackTransaction() should be done to keep things balanced.
- 
+
  By default, when bForce is set to FALSE, only "efficient" transactions will be
  attempted. Some drivers may offer an emulation of transactions, but sometimes
  with significant overhead, in which case the user must explicitly allow for such
  an emulation by setting bForce to TRUE. Drivers that offer emulated transactions
- should advertize the ODsCEmulatedTransactions capability (and not ODsCTransactions).
- 
+ should advertise the ODsCEmulatedTransactions capability (and not ODsCTransactions).
+
  This function is the same as the C function GDALDatasetStartTransaction().
 
  @param bForce can be set to TRUE if an emulation, possibly slow, of a transaction
@@ -5594,29 +5902,30 @@ OGRErr GDALDataset::StartTransaction(CPL_UNUSED int bForce)
 /************************************************************************/
 
 /**
- \brief For datasources which support transactions, StartTransaction creates a transaction.
+ \brief For datasources which support transactions, StartTransaction creates a
+ transaction.
 
- If starting the transaction fails, will return 
- OGRERR_FAILURE. Datasources which do not support transactions will 
+ If starting the transaction fails, will return
+ OGRERR_FAILURE. Datasources which do not support transactions will
  always return OGRERR_UNSUPPORTED_OPERATION.
 
  Nested transactions are not supported.
- 
+
  All changes done after the start of the transaction are definitely applied in the
- datasource if CommitTransaction() is called. They may be cancelled by calling
+ datasource if CommitTransaction() is called. They may be canceled by calling
  RollbackTransaction() instead.
- 
+
  At the time of writing, transactions only apply on vector layers.
- 
- Datasets that support transactions will advertize the ODsCTransactions capability.
- Use of transactions at dataset level is generally prefered to transactions at
+
+ Datasets that support transactions will advertise the ODsCTransactions capability.
+ Use of transactions at dataset level is generally preferred to transactions at
  layer level, whose scope is rarely limited to the layer from which it was started.
- 
+
  In case StartTransaction() fails, neither CommitTransaction() or RollbackTransaction()
  should be called.
 
  If an error occurs after a successful StartTransaction(), the whole
- transaction may or may not be implicitely cancelled, depending on drivers. (e.g.
+ transaction may or may not be implicitly canceled, depending on drivers. (e.g.
  the PG driver will cancel it, SQLite/GPKG not). In any case, in the event of an
  error, an explicit call to RollbackTransaction() should be done to keep things balanced.
 
@@ -5624,7 +5933,7 @@ OGRErr GDALDataset::StartTransaction(CPL_UNUSED int bForce)
  attempted. Some drivers may offer an emulation of transactions, but sometimes
  with significant overhead, in which case the user must explicitly allow for such
  an emulation by setting bForce to TRUE. Drivers that offer emulated transactions
- should advertize the ODsCEmulatedTransactions capability (and not ODsCTransactions).
+ should advertise the ODsCEmulatedTransactions capability (and not ODsCTransactions).
 
  This function is the same as the C++ method GDALDataset::StartTransaction()
 
@@ -5654,10 +5963,10 @@ OGRErr GDALDatasetStartTransaction(GDALDatasetH hDS, int bForce)
 /**
  \brief For datasources which support transactions, CommitTransaction commits a transaction.
 
- If no transaction is active, or the commit fails, will return 
- OGRERR_FAILURE. Datasources which do not support transactions will 
- always return OGRERR_UNSUPPORTED_OPERATION. 
- 
+ If no transaction is active, or the commit fails, will return
+ OGRERR_FAILURE. Datasources which do not support transactions will
+ always return OGRERR_UNSUPPORTED_OPERATION.
+
  Depending on drivers, this may or may not abort layer sequential readings that
  are active.
 
@@ -5678,10 +5987,10 @@ OGRErr GDALDataset::CommitTransaction()
 /**
  \brief For datasources which support transactions, CommitTransaction commits a transaction.
 
- If no transaction is active, or the commit fails, will return 
- OGRERR_FAILURE. Datasources which do not support transactions will 
- always return OGRERR_UNSUPPORTED_OPERATION. 
- 
+ If no transaction is active, or the commit fails, will return
+ OGRERR_FAILURE. Datasources which do not support transactions will
+ always return OGRERR_UNSUPPORTED_OPERATION.
+
  Depending on drivers, this may or may not abort layer sequential readings that
  are active.
 
@@ -5707,10 +6016,11 @@ OGRErr GDALDatasetCommitTransaction(GDALDatasetH hDS)
 /************************************************************************/
 
 /**
- \brief For datasources which support transactions, RollbackTransaction will roll back a datasource to its state before the start of the current transaction. 
- If no transaction is active, or the rollback fails, will return  
+ \brief For datasources which support transactions, RollbackTransaction will
+ roll back a datasource to its state before the start of the current transaction.
+ If no transaction is active, or the rollback fails, will return
  OGRERR_FAILURE. Datasources which do not support transactions will
- always return OGRERR_UNSUPPORTED_OPERATION. 
+ always return OGRERR_UNSUPPORTED_OPERATION.
 
  This function is the same as the C function GDALDatasetRollbackTransaction().
 
@@ -5727,10 +6037,11 @@ OGRErr GDALDataset::RollbackTransaction()
 /************************************************************************/
 
 /**
- \brief For datasources which support transactions, RollbackTransaction will roll back a datasource to its state before the start of the current transaction. 
- If no transaction is active, or the rollback fails, will return  
+ \brief For datasources which support transactions, RollbackTransaction will
+ roll back a datasource to its state before the start of the current transaction.
+ If no transaction is active, or the rollback fails, will return
  OGRERR_FAILURE. Datasources which do not support transactions will
- always return OGRERR_UNSUPPORTED_OPERATION. 
+ always return OGRERR_UNSUPPORTED_OPERATION.
 
  This function is the same as the C++ method GDALDataset::RollbackTransaction().
 
@@ -5756,11 +6067,35 @@ OGRErr GDALDatasetRollbackTransaction(GDALDatasetH hDS)
 int GDALDataset::EnterReadWrite(GDALRWFlag eRWFlag)
 {
     GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
-    if( eAccess == GA_Update && (eRWFlag == GF_Write || psPrivate->hMutex != NULL) )
+    if( psPrivate != NULL && eAccess == GA_Update )
     {
-        CPLCreateOrAcquireMutex(&psPrivate->hMutex, 1000.0);
-        psPrivate->nMutexTakenCount ++; /* not sure if we can have recursive calls, so ...*/
-        return TRUE;
+        if( psPrivate->eStateReadWriteMutex == RW_MUTEX_STATE_UNKNOWN )
+        {
+            // In case dead-lock would occur, which is not impossible,
+            // this can be used to prevent it, but at the risk of other
+            // issues
+            if( CSLTestBoolean(CPLGetConfigOption( "GDAL_ENABLE_READ_WRITE_MUTEX", "YES") ) )
+            {
+                psPrivate->eStateReadWriteMutex = RW_MUTEX_STATE_ALLOWED;
+            }
+            else
+            {
+                psPrivate->eStateReadWriteMutex = RW_MUTEX_STATE_DISABLED;
+            }
+        }
+        if( psPrivate->eStateReadWriteMutex == RW_MUTEX_STATE_ALLOWED &&
+            (eRWFlag == GF_Write || psPrivate->hMutex != NULL) )
+        {
+            // There should be no race related to creating this mutex since
+            // it should be first created through IWriteBlock() / IRasterIO()
+            // and then GDALRasterBlock might call it from another thread
+            if( psPrivate->hMutex == NULL )
+                psPrivate->hMutex = CPLCreateMutex();
+            else
+                CPLAcquireMutex(psPrivate->hMutex, 1000.0);
+            psPrivate->nMutexTakenCount ++; /* not sure if we can have recursive calls, so ...*/
+            return TRUE;
+        }
     }
     return FALSE;
 }
@@ -5772,8 +6107,28 @@ int GDALDataset::EnterReadWrite(GDALRWFlag eRWFlag)
 void GDALDataset::LeaveReadWrite()
 {
     GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
-    psPrivate->nMutexTakenCount --;
-    CPLReleaseMutex(psPrivate->hMutex);
+    if( psPrivate )
+    {
+        psPrivate->nMutexTakenCount --;
+        CPLReleaseMutex(psPrivate->hMutex);
+    }
+}
+
+/************************************************************************/
+/*                       DisableReadWriteMutex()                        */
+/************************************************************************/
+
+/* The mutex logic is broken in multi-threaded situations, for example */
+/* with 2 WarpedVRT datasets being read at the same time. In that */
+/* particular case, the mutex is not needed, so allow the VRTWarpedDataset code */
+/* to disable it. */
+void GDALDataset::DisableReadWriteMutex()
+{
+    GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
+    if( psPrivate )
+    {
+        psPrivate->eStateReadWriteMutex = RW_MUTEX_STATE_DISABLED;
+    }
 }
 
 /************************************************************************/
@@ -5783,8 +6138,11 @@ void GDALDataset::LeaveReadWrite()
 void GDALDataset::TemporarilyDropReadWriteLock()
 {
     GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
-    for(int i=0;i<psPrivate->nMutexTakenCount;i++)
-        CPLReleaseMutex(psPrivate->hMutex);
+    if( psPrivate )
+    {
+        for(int i=0;i<psPrivate->nMutexTakenCount;i++)
+            CPLReleaseMutex(psPrivate->hMutex);
+    }
 }
 
 /************************************************************************/
@@ -5794,6 +6152,32 @@ void GDALDataset::TemporarilyDropReadWriteLock()
 void GDALDataset::ReacquireReadWriteLock()
 {
     GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
-    for(int i=0;i<psPrivate->nMutexTakenCount;i++)
-        CPLAcquireMutex(psPrivate->hMutex, 1000.0);
+    if( psPrivate )
+    {
+        for(int i=0;i<psPrivate->nMutexTakenCount;i++)
+            CPLAcquireMutex(psPrivate->hMutex, 1000.0);
+    }
+}
+
+/************************************************************************/
+/*                           AcquireMutex()                             */
+/************************************************************************/
+
+int GDALDataset::AcquireMutex()
+{
+    GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
+    if( psPrivate == NULL )
+        return 0;
+    return CPLCreateOrAcquireMutex(&(psPrivate->hMutex), 1000.0);
+}
+
+/************************************************************************/
+/*                          ReleaseMutex()                              */
+/************************************************************************/
+
+void GDALDataset::ReleaseMutex()
+{
+    GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
+    if( psPrivate )
+        CPLReleaseMutex(psPrivate->hMutex);
 }
diff --git a/gcore/gdaldefaultasync.cpp b/gcore/gdaldefaultasync.cpp
index eef271f..ee34157 100644
--- a/gcore/gdaldefaultasync.cpp
+++ b/gcore/gdaldefaultasync.cpp
@@ -2,7 +2,7 @@
  * $Id: gdaldataset.cpp 16796 2009-04-17 23:35:04Z normanb $
  *
  * Project:  GDAL Core
- * Purpose:  Implementation of GDALDefaultAsyncReader and the 
+ * Purpose:  Implementation of GDALDefaultAsyncReader and the
  *           GDALAsyncReader base class.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -53,7 +53,21 @@ CPL_C_END
 /*                          GDALAsyncReader()                           */
 /************************************************************************/
 
-GDALAsyncReader::GDALAsyncReader()
+GDALAsyncReader::GDALAsyncReader() :
+    poDS(NULL),
+    nXOff(0),
+    nYOff(0),
+    nXSize(0),
+    nYSize(0),
+    pBuf(NULL),
+    nBufXSize(0),
+    nBufYSize(0),
+    eBufType(GDT_Unknown),
+    nBandCount(0),
+    panBandMap(NULL),
+    nPixelSpace(0),
+    nLineSpace(0),
+    nBandSpace(0)
 {
 }
 
@@ -70,30 +84,30 @@ GDALAsyncReader::~GDALAsyncReader()
 
 /**
  * \fn GDALAsyncStatusType GDALAsyncReader::GetNextUpdatedRegion( double dfTimeout, int* pnBufXOff, int* pnBufYOff, int* pnBufXSize, int* pnBufXSize) = 0;
- * 
+ *
  * \brief Get async IO update
  *
  * Provide an opportunity for an asynchronous IO request to update the
  * image buffer and return an indication of the area of the buffer that
- * has been updated.  
+ * has been updated.
  *
- * The dfTimeout parameter can be used to wait for additional data to 
+ * The dfTimeout parameter can be used to wait for additional data to
  * become available.  The timeout does not limit the amount
  * of time this method may spend actually processing available data.
  *
  * The following return status are possible.
- * - GARIO_PENDING: No imagery was altered in the buffer, but there is still 
- * activity pending, and the application should continue to call 
+ * - GARIO_PENDING: No imagery was altered in the buffer, but there is still
+ * activity pending, and the application should continue to call
  * GetNextUpdatedRegion() as time permits.
- * - GARIO_UPDATE: Some of the imagery has been updated, but there is still 
+ * - GARIO_UPDATE: Some of the imagery has been updated, but there is still
  * activity pending.
- * - GARIO_ERROR: Something has gone wrong. The asynchronous request should 
+ * - GARIO_ERROR: Something has gone wrong. The asynchronous request should
  * be ended.
- * - GARIO_COMPLETE: An update has occured and there is no more pending work 
- * on this request. The request should be ended and the buffer used. 
+ * - GARIO_COMPLETE: An update has occurred and there is no more pending work
+ * on this request. The request should be ended and the buffer used.
  *
- * @param dfTimeout the number of seconds to wait for additional updates.  Use 
- * -1 to wait indefinately, or zero to not wait at all if there is no data
+ * @param dfTimeout the number of seconds to wait for additional updates.  Use
+ * -1 to wait indefinitely, or zero to not wait at all if there is no data
  * available.
  * @param pnBufXOff location to return the X offset of the area of the
  * request buffer that has been updated.
@@ -103,17 +117,17 @@ GDALAsyncReader::~GDALAsyncReader()
  * request buffer that has been updated.
  * @param pnBufYSize location to return the Y size of the area of the
  * request buffer that has been updated.
- * 
- * @return GARIO_ status, details described above. 
+ *
+ * @return GARIO_ status, details described above.
  */
 
 /************************************************************************/
 /*                     GDALARGetNextUpdatedRegion()                     */
 /************************************************************************/
 
-GDALAsyncStatusType CPL_STDCALL 
+GDALAsyncStatusType CPL_STDCALL
 GDALARGetNextUpdatedRegion(GDALAsyncReaderH hARIO, double timeout,
-                           int* pnxbufoff, int* pnybufoff, 
+                           int* pnxbufoff, int* pnybufoff,
                            int* pnxbufsize, int* pnybufsize)
 {
     VALIDATE_POINTER1(hARIO, "GDALARGetNextUpdatedRegion", GARIO_ERROR);
@@ -128,13 +142,13 @@ GDALARGetNextUpdatedRegion(GDALAsyncReaderH hARIO, double timeout,
 /**
  * \brief Lock image buffer.
  *
- * Locks the image buffer passed into GDALDataset::BeginAsyncReader(). 
+ * Locks the image buffer passed into GDALDataset::BeginAsyncReader().
  * This is useful to ensure the image buffer is not being modified while
  * it is being used by the application.  UnlockBuffer() should be used
  * to release this lock when it is no longer needed.
  *
  * @param dfTimeout the time in seconds to wait attempting to lock the buffer.
- * -1.0 to wait indefinately and 0 to not wait at all if it can't be
+ * -1.0 to wait indefinitely and 0 to not wait at all if it can't be
  * acquired immediately.  Default is -1.0 (infinite wait).
  *
  * @return TRUE if successful, or FALSE on an error.
@@ -238,42 +252,42 @@ GDALGetDefaultAsyncReader( GDALDataset* poDS,
 /************************************************************************/
 
 GDALDefaultAsyncReader::
-GDALDefaultAsyncReader( GDALDataset* poDS,
-                          int nXOff, int nYOff,
-                          int nXSize, int nYSize,
-                          void *pBuf,
-                          int nBufXSize, int nBufYSize,
-                          GDALDataType eBufType,
-                          int nBandCount, int* panBandMap,
-                          int nPixelSpace, int nLineSpace,
-                          int nBandSpace, char **papszOptions) 
+GDALDefaultAsyncReader( GDALDataset* poDSIn,
+                          int nXOffIn, int nYOffIn,
+                          int nXSizeIn, int nYSizeIn,
+                          void *pBufIn,
+                          int nBufXSizeIn, int nBufYSizeIn,
+                          GDALDataType eBufTypeIn,
+                          int nBandCountIn, int* panBandMapIn,
+                          int nPixelSpaceIn, int nLineSpaceIn,
+                          int nBandSpaceIn, char **papszOptionsIn)
 
 {
-    this->poDS = poDS;
-    this->nXOff = nXOff;
-    this->nYOff = nYOff;
-    this->nXSize = nXSize;
-    this->nYSize = nYSize;
-    this->pBuf = pBuf;
-    this->nBufXSize = nBufXSize;
-    this->nBufYSize = nBufYSize;
-    this->eBufType = eBufType;
-    this->nBandCount = nBandCount;
-    this->panBandMap = (int *) CPLMalloc(sizeof(int)*nBandCount);
-
-    if( panBandMap != NULL )
-        memcpy( this->panBandMap, panBandMap, sizeof(int)*nBandCount );
+    poDS = poDSIn;
+    nXOff = nXOffIn;
+    nYOff = nYOffIn;
+    nXSize = nXSizeIn;
+    nYSize = nYSizeIn;
+    pBuf = pBufIn;
+    nBufXSize = nBufXSizeIn;
+    nBufYSize = nBufYSizeIn;
+    eBufType = eBufTypeIn;
+    nBandCount = nBandCountIn;
+    panBandMap = (int *) CPLMalloc(sizeof(int)*nBandCountIn);
+
+    if( panBandMapIn != NULL )
+        memcpy( panBandMap, panBandMapIn, sizeof(int)*nBandCount );
     else
     {
         for( int i = 0; i < nBandCount; i++ )
-            this->panBandMap[i] = i+1;
+            panBandMap[i] = i+1;
     }
-    
-    this->nPixelSpace = nPixelSpace;
-    this->nLineSpace = nLineSpace;
-    this->nBandSpace = nBandSpace;
 
-    this->papszOptions = CSLDuplicate(papszOptions);
+    nPixelSpace = nPixelSpaceIn;
+    nLineSpace = nLineSpaceIn;
+    nBandSpace = nBandSpaceIn;
+
+    papszOptions = CSLDuplicate(papszOptionsIn);
 }
 
 /************************************************************************/
diff --git a/gcore/gdaldefaultoverviews.cpp b/gcore/gdaldefaultoverviews.cpp
index 8a32a17..3dd6fbb 100644
--- a/gcore/gdaldefaultoverviews.cpp
+++ b/gcore/gdaldefaultoverviews.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: gdaldefaultoverviews.cpp 28907 2015-04-14 15:14:32Z rouault $
+ * $Id: gdaldefaultoverviews.cpp 33694 2016-03-10 17:54:30Z goatbar $
  *
  * Project:  GDAL Core
- * Purpose:  Helper code to implement overview and mask support for many 
+ * Purpose:  Helper code to implement overview and mask support for many
  *           drivers with no inherent format support.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -32,7 +32,7 @@
 #include "gdal_priv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: gdaldefaultoverviews.cpp 28907 2015-04-14 15:14:32Z rouault $");
+CPL_CVSID("$Id: gdaldefaultoverviews.cpp 33694 2016-03-10 17:54:30Z goatbar $");
 
 /************************************************************************/
 /*                        GDALDefaultOverviews()                        */
@@ -77,10 +77,10 @@ GDALDefaultOverviews::~GDALDefaultOverviews()
 
 int GDALDefaultOverviews::CloseDependentDatasets()
 {
-    int bHasDroppedRef = FALSE;
+    bool bHasDroppedRef = false;
     if( poODS != NULL )
     {
-        bHasDroppedRef = TRUE;
+        bHasDroppedRef = true;
         poODS->FlushCache();
         GDALClose( poODS );
         poODS = NULL;
@@ -90,7 +90,7 @@ int GDALDefaultOverviews::CloseDependentDatasets()
     {
         if( bOwnMaskDS )
         {
-            bHasDroppedRef = TRUE;
+            bHasDroppedRef = true;
             poMaskDS->FlushCache();
             GDALClose( poMaskDS );
         }
@@ -124,7 +124,7 @@ void GDALDefaultOverviews::Initialize( GDALDataset *poDSIn,
 
 {
     poDS = poDSIn;
-    
+
 /* -------------------------------------------------------------------- */
 /*      If we were already initialized, destroy the old overview        */
 /*      file handle.                                                    */
@@ -156,6 +156,20 @@ void GDALDefaultOverviews::Initialize( GDALDataset *poDSIn,
 }
 
 /************************************************************************/
+/*                         TransferSiblingFiles()                       */
+/*                                                                      */
+/*      Contrary to Initialize(), this sets papszInitSiblingFiles but   */
+/*      without duplicating the passed list. Which must be              */
+/*      "de-allocatable" with CSLDestroy()                              */
+/************************************************************************/
+
+void GDALDefaultOverviews::TransferSiblingFiles(char** papszSiblingFiles)
+{
+    CSLDestroy( papszInitSiblingFiles );
+    papszInitSiblingFiles = papszSiblingFiles;
+}
+
+/************************************************************************/
 /*                            OverviewScan()                            */
 /*                                                                      */
 /*      This is called to scan for overview files when a first          */
@@ -193,15 +207,21 @@ void GDALDefaultOverviews::OverviewScan()
             osOvrFilename.Printf( "%s.ovr", pszInitName );
         }
 
-        bExists = CPLCheckForFile( (char *) osOvrFilename.c_str(), 
+        std::vector<char> achOvrFilename;
+        achOvrFilename.resize(osOvrFilename.size() + 1);
+        memcpy(&(achOvrFilename[0]), osOvrFilename.c_str(), osOvrFilename.size() + 1);
+        bExists = CPLCheckForFile( &achOvrFilename[0],
                                    papszInitSiblingFiles );
+        osOvrFilename = &achOvrFilename[0];
 
 #if !defined(WIN32)
         if( !bInitNameIsOVR && !bExists && !papszInitSiblingFiles )
         {
             osOvrFilename.Printf( "%s.OVR", pszInitName );
-            bExists = CPLCheckForFile( (char *) osOvrFilename.c_str(), 
+            memcpy(&(achOvrFilename[0]), osOvrFilename.c_str(), osOvrFilename.size() + 1);
+            bExists = CPLCheckForFile( &achOvrFilename[0],
                                        papszInitSiblingFiles );
+            osOvrFilename = &achOvrFilename[0];
             if( !bExists )
                 osOvrFilename.Printf( "%s.ovr", pszInitName );
         }
@@ -226,7 +246,7 @@ void GDALDefaultOverviews::OverviewScan()
 /* -------------------------------------------------------------------- */
     if( !poODS && !EQUAL(pszInitName,":::VIRTUAL:::") )
     {
-        int bTryFindAssociatedAuxFile = TRUE;
+        bool bTryFindAssociatedAuxFile = true;
         if( papszInitSiblingFiles )
         {
             CPLString osAuxFilename = CPLResetExtension( pszInitName, "aux");
@@ -239,7 +259,7 @@ void GDALDefaultOverviews::OverviewScan()
                 iSibling = CSLFindString( papszInitSiblingFiles,
                                         CPLGetFilename(osAuxFilename) );
                 if( iSibling < 0 )
-                    bTryFindAssociatedAuxFile = FALSE;
+                    bTryFindAssociatedAuxFile = false;
             }
         }
 
@@ -251,8 +271,8 @@ void GDALDefaultOverviews::OverviewScan()
 
         if( poODS )
         {
-            int bUseRRD = CSLTestBoolean(CPLGetConfigOption("USE_RRD","NO"));
-            
+            int bUseRRD = CPLTestBool(CPLGetConfigOption("USE_RRD","NO"));
+
             bOvrIsAux = TRUE;
             if( GetOverviewCount(1) == 0 && !bUseRRD )
             {
@@ -269,17 +289,17 @@ void GDALDefaultOverviews::OverviewScan()
 
 /* -------------------------------------------------------------------- */
 /*      If we still don't have an overview, check to see if we have     */
-/*      overview metadata referencing a remote (ie. proxy) or local     */
+/*      overview metadata referencing a remote (i.e. proxy) or local    */
 /*      subdataset overview dataset.                                    */
 /* -------------------------------------------------------------------- */
     if( poODS == NULL )
     {
-        const char *pszProxyOvrFilename = 
+        const char *pszProxyOvrFilename =
             poDS->GetMetadataItem( "OVERVIEW_FILE", "OVERVIEWS" );
 
         if( pszProxyOvrFilename != NULL )
         {
-            if( EQUALN(pszProxyOvrFilename,":::BASE:::",10) )
+            if( STARTS_WITH_CI(pszProxyOvrFilename, ":::BASE:::") )
             {
                 CPLString osPath = CPLGetPath(poDS->GetDescription());
 
@@ -303,16 +323,15 @@ void GDALDefaultOverviews::OverviewScan()
     if( poODS )
     {
         int nOverviewCount = GetOverviewCount(1);
-        int iOver;
 
-        for( iOver = 0; iOver < nOverviewCount; iOver++ )
+        for( int iOver = 0; iOver < nOverviewCount; iOver++ )
         {
             GDALRasterBand *poBand = GetOverview( 1, iOver );
             GDALDataset    *poOverDS = NULL;
 
             if( poBand != NULL )
                 poOverDS = poBand->GetDataset();
-            
+
             if( poOverDS != NULL )
             {
                 poOverDS->oOvManager.poBaseDS = poDS;
@@ -329,12 +348,11 @@ void GDALDefaultOverviews::OverviewScan()
 int GDALDefaultOverviews::GetOverviewCount( int nBand )
 
 {
-    GDALRasterBand * poBand;
 
     if( poODS == NULL || nBand < 1 || nBand > poODS->GetRasterCount() )
         return 0;
 
-    poBand = poODS->GetRasterBand( nBand );
+    GDALRasterBand * poBand = poODS->GetRasterBand( nBand );
     if( poBand == NULL )
         return 0;
     else
@@ -354,12 +372,10 @@ GDALRasterBand *
 GDALDefaultOverviews::GetOverview( int nBand, int iOverview )
 
 {
-    GDALRasterBand * poBand;
-
     if( poODS == NULL || nBand < 1 || nBand > poODS->GetRasterCount() )
         return NULL;
 
-    poBand = poODS->GetRasterBand( nBand );
+    GDALRasterBand * poBand = poODS->GetRasterBand( nBand );
     if( poBand == NULL )
         return NULL;
 
@@ -396,7 +412,7 @@ int GDALOvLevelAdjust( int nOvLevel, int nXSize )
 
 {
     int nOXSize = (nXSize + nOvLevel - 1) / nOvLevel;
-    
+
     return (int) (0.5 + nXSize / (double) nOXSize);
 }
 
@@ -410,13 +426,13 @@ int GDALOvLevelAdjust2( int nOvLevel, int nXSize, int nYSize )
     if( nXSize >= nYSize / 2 && !(nXSize < nYSize && nXSize < nOvLevel) )
     {
         int     nOXSize = (nXSize + nOvLevel - 1) / nOvLevel;
-    
+
         return (int) (0.5 + nXSize / (double) nOXSize);
     }
     else
     {
         int     nOYSize = (nYSize + nOvLevel - 1) / nOvLevel;
-    
+
         return (int) (0.5 + nYSize / (double) nOYSize);
     }
 }
@@ -433,12 +449,12 @@ int GDALComputeOvFactor( int nOvrXSize, int nRasterXSize,
     /* in an attempt to behave closer as previous behaviour */
     if( nRasterXSize >= nRasterYSize / 2 )
     {
-        return (int) 
+        return (int)
                 (0.5 + nRasterXSize / (double) nOvrXSize);
     }
     else
     {
-        return (int) 
+        return (int)
                 (0.5 + nRasterYSize / (double) nOvrYSize);
     }
 }
@@ -456,10 +472,8 @@ CPLErr GDALDefaultOverviews::CleanOverviews()
     if( poODS == NULL )
         return CE_None;
 
-    // Delete the overview file(s). 
-    GDALDriver *poOvrDriver;
-
-    poOvrDriver = poODS->GetDriver();
+    // Delete the overview file(s).
+    GDALDriver *poOvrDriver = poODS->GetDriver();
     GDALClose( poODS );
     poODS = NULL;
 
@@ -469,10 +483,10 @@ CPLErr GDALDefaultOverviews::CleanOverviews()
     else
         eErr = CE_None;
 
-    // Reset the saved overview filename. 
+    // Reset the saved overview filename.
     if( !EQUAL(poDS->GetDescription(),":::VIRTUAL:::") )
     {
-        int bUseRRD = CSLTestBoolean(CPLGetConfigOption("USE_RRD","NO"));
+        const bool bUseRRD = CPLTestBool(CPLGetConfigOption("USE_RRD","NO"));
 
         if( bUseRRD )
             osOvrFilename = CPLResetExtension( poDS->GetDescription(), "aux" );
@@ -484,15 +498,15 @@ CPLErr GDALDefaultOverviews::CleanOverviews()
 
     return eErr;
 }
-    
+
 /************************************************************************/
 /*                      BuildOverviewsSubDataset()                      */
 /************************************************************************/
 
 CPLErr
-GDALDefaultOverviews::BuildOverviewsSubDataset( 
+GDALDefaultOverviews::BuildOverviewsSubDataset(
     const char * pszPhysicalFile,
-    const char * pszResampling, 
+    const char * pszResampling,
     int nOverviews, int * panOverviewList,
     int nBands, int * panBandList,
     GDALProgressFunc pfnProgress, void * pProgressData)
@@ -519,8 +533,8 @@ GDALDefaultOverviews::BuildOverviewsSubDataset(
                 else
                     osAdjustedOvrFilename = osOvrFilename;
 
-                poDS->SetMetadataItem( "OVERVIEW_FILE", 
-                                       osAdjustedOvrFilename, 
+                poDS->SetMetadataItem( "OVERVIEW_FILE",
+                                       osAdjustedOvrFilename,
                                        "OVERVIEWS" );
                 break;
             }
@@ -539,15 +553,14 @@ GDALDefaultOverviews::BuildOverviewsSubDataset(
 /************************************************************************/
 
 CPLErr
-GDALDefaultOverviews::BuildOverviews( 
+GDALDefaultOverviews::BuildOverviews(
     const char * pszBasename,
-    const char * pszResampling, 
+    const char * pszResampling,
     int nOverviews, int * panOverviewList,
     int nBands, int * panBandList,
     GDALProgressFunc pfnProgress, void * pProgressData)
 
 {
-    GDALRasterBand **pahBands;
     CPLErr       eErr;
     int          i;
 
@@ -563,7 +576,7 @@ GDALDefaultOverviews::BuildOverviews(
 /* -------------------------------------------------------------------- */
     if( poODS == NULL )
     {
-        bOvrIsAux = CSLTestBoolean(CPLGetConfigOption( "USE_RRD", "NO" ));
+        bOvrIsAux = CPLTestBool(CPLGetConfigOption( "USE_RRD", "NO" ));
         if( bOvrIsAux )
         {
             VSIStatBufL sStatBuf;
@@ -594,7 +607,7 @@ GDALDefaultOverviews::BuildOverviews(
     {
         CPLError( CE_Failure, CPLE_NotSupported,
                   "Generation of overviews in external TIFF currently only"
-                  " supported when operating on all bands.\n" 
+                  " supported when operating on all bands.\n"
                   "Operation failed.\n" );
         return CE_Failure;
     }
@@ -619,30 +632,27 @@ GDALDefaultOverviews::BuildOverviews(
 /*      which are new.  We assume that band 1 of the file is            */
 /*      representative.                                                 */
 /* -------------------------------------------------------------------- */
-    int   nNewOverviews, *panNewOverviewList = NULL;
     GDALRasterBand *poBand = poDS->GetRasterBand( 1 );
 
-    nNewOverviews = 0;
-    panNewOverviewList = (int *) CPLCalloc(sizeof(int),nOverviews);
+    int nNewOverviews = 0;
+    int *panNewOverviewList = (int *) CPLCalloc(sizeof(int),nOverviews);
     for( i = 0; i < nOverviews && poBand != NULL; i++ )
     {
-        int   j;
-
-        for( j = 0; j < poBand->GetOverviewCount(); j++ )
+        for( int j = 0; j < poBand->GetOverviewCount(); j++ )
         {
             int    nOvFactor;
             GDALRasterBand * poOverview = poBand->GetOverview( j );
             if (poOverview == NULL)
                 continue;
- 
+
             nOvFactor = GDALComputeOvFactor(poOverview->GetXSize(),
                                              poBand->GetXSize(),
                                              poOverview->GetYSize(),
                                              poBand->GetYSize());
 
-            if( nOvFactor == panOverviewList[i] 
-                || nOvFactor == GDALOvLevelAdjust2( panOverviewList[i], 
-                                                   poBand->GetXSize(), 
+            if( nOvFactor == panOverviewList[i]
+                || nOvFactor == GDALOvLevelAdjust2( panOverviewList[i],
+                                                   poBand->GetXSize(),
                                                    poBand->GetYSize() ) )
                 panOverviewList[i] *= -1;
         }
@@ -654,7 +664,8 @@ GDALDefaultOverviews::BuildOverviews(
 /* -------------------------------------------------------------------- */
 /*      Build band list.                                                */
 /* -------------------------------------------------------------------- */
-    pahBands = (GDALRasterBand **) CPLCalloc(sizeof(GDALRasterBand *),nBands);
+    GDALRasterBand **pahBands
+        = (GDALRasterBand **) CPLCalloc(sizeof(GDALRasterBand *),nBands);
     for( i = 0; i < nBands; i++ )
         pahBands[i] = poDS->GetRasterBand( panBandList[i] );
 
@@ -665,8 +676,6 @@ GDALDefaultOverviews::BuildOverviews(
 /*      produce the imagery.                                            */
 /* -------------------------------------------------------------------- */
 
-#ifndef WIN32CE
-
     if( bOvrIsAux )
     {
         if( nNewOverviews == 0 )
@@ -679,13 +688,11 @@ GDALDefaultOverviews::BuildOverviews(
         else
             eErr = HFAAuxBuildOverviews( osOvrFilename, poDS, &poODS,
                                      nBands, panBandList,
-                                     nNewOverviews, panNewOverviewList, 
-                                     pszResampling, 
+                                     nNewOverviews, panNewOverviewList,
+                                     pszResampling,
                                      pfnProgress, pProgressData );
 
-        int j;
-        
-        for( j = 0; j < nOverviews; j++ )
+        for( int j = 0; j < nOverviews; j++ )
         {
             if( panOverviewList[j] > 0 )
                 panOverviewList[j] *= -1;
@@ -697,7 +704,6 @@ GDALDefaultOverviews::BuildOverviews(
 /*      operate on it.                                                  */
 /* -------------------------------------------------------------------- */
     else
-#endif /* WIN32CE */
     {
         if( poODS != NULL )
         {
@@ -705,22 +711,22 @@ GDALDefaultOverviews::BuildOverviews(
             poODS = NULL;
         }
 
-        eErr = GTIFFBuildOverviews( osOvrFilename, nBands, pahBands, 
-                                    nNewOverviews, panNewOverviewList, 
+        eErr = GTIFFBuildOverviews( osOvrFilename, nBands, pahBands,
+                                    nNewOverviews, panNewOverviewList,
                                     pszResampling, pfnProgress, pProgressData );
-        
-        // Probe for proxy overview filename. 
+
+        // Probe for proxy overview filename.
         if( eErr == CE_Failure )
         {
-            const char *pszProxyOvrFilename = 
+            const char *pszProxyOvrFilename =
                 poDS->GetMetadataItem("FILENAME","ProxyOverviewRequest");
 
             if( pszProxyOvrFilename != NULL )
             {
                 osOvrFilename = pszProxyOvrFilename;
-                eErr = GTIFFBuildOverviews( osOvrFilename, nBands, pahBands, 
-                                            nNewOverviews, panNewOverviewList, 
-                                            pszResampling, 
+                eErr = GTIFFBuildOverviews( osOvrFilename, nBands, pahBands,
+                                            nNewOverviews, panNewOverviewList,
+                                            pszResampling,
                                             pfnProgress, pProgressData );
             }
         }
@@ -738,7 +744,7 @@ GDALDefaultOverviews::BuildOverviews(
 /* -------------------------------------------------------------------- */
     GDALRasterBand **papoOverviewBands;
 
-    papoOverviewBands = (GDALRasterBand **) 
+    papoOverviewBands = (GDALRasterBand **)
         CPLCalloc(sizeof(void*),nOverviews);
 
     for( int iBand = 0; iBand < nBands && eErr == CE_None; iBand++ )
@@ -748,11 +754,8 @@ GDALDefaultOverviews::BuildOverviews(
         nNewOverviews = 0;
         for( i = 0; i < nOverviews && poBand != NULL; i++ )
         {
-            int   j;
-            
-            for( j = 0; j < poBand->GetOverviewCount(); j++ )
+            for( int j = 0; j < poBand->GetOverviewCount(); j++ )
             {
-                int    nOvFactor;
                 GDALRasterBand * poOverview = poBand->GetOverview( j );
                 if (poOverview == NULL)
                     continue;
@@ -763,12 +766,12 @@ GDALDefaultOverviews::BuildOverviews(
                 if (bHasNoData)
                   poOverview->SetNoDataValue(noDataValue);
 
-                nOvFactor = GDALComputeOvFactor(poOverview->GetXSize(),
+                int nOvFactor = GDALComputeOvFactor(poOverview->GetXSize(),
                                                  poBand->GetXSize(),
                                                  poOverview->GetYSize(),
                                                  poBand->GetYSize());
 
-                if( nOvFactor == - panOverviewList[i] 
+                if( nOvFactor == - panOverviewList[i]
                     || (panOverviewList[i] < 0 &&
                         nOvFactor == GDALOvLevelAdjust2( -panOverviewList[i],
                                                        poBand->GetXSize(),
@@ -782,10 +785,10 @@ GDALDefaultOverviews::BuildOverviews(
 
         if( nNewOverviews > 0 )
         {
-            eErr = GDALRegenerateOverviews( (GDALRasterBandH) poBand, 
-                                            nNewOverviews, 
+            eErr = GDALRegenerateOverviews( (GDALRasterBandH) poBand,
+                                            nNewOverviews,
                                             (GDALRasterBandH*)papoOverviewBands,
-                                            pszResampling, 
+                                            pszResampling,
                                             pfnProgress, pProgressData );
         }
     }
@@ -827,9 +830,9 @@ GDALDefaultOverviews::BuildOverviews(
             /* will become invalid after poMaskDS closing */
             for( int iBand = 1; iBand <= poDS->GetRasterCount(); iBand ++ )
             {
-                GDALRasterBand *poBand = poDS->GetRasterBand(iBand);
-                if( poBand != NULL )
-                    poBand->InvalidateMaskBand();
+                GDALRasterBand *poOtherBand = poDS->GetRasterBand(iBand);
+                if( poOtherBand != NULL )
+                    poOtherBand->InvalidateMaskBand();
             }
 
             GDALClose( poMaskDS );
@@ -853,11 +856,11 @@ GDALDefaultOverviews::BuildOverviews(
 
         for( iOver = 0; iOver < nOverviewCount; iOver++ )
         {
-            GDALRasterBand *poBand = GetOverview( 1, iOver );
+            GDALRasterBand *poOtherBand = GetOverview( 1, iOver );
             GDALDataset    *poOverDS = NULL;
 
-            if( poBand != NULL )
-                poOverDS = poBand->GetDataset();
+            if( poOtherBand != NULL )
+                poOverDS = poOtherBand->GetDataset();
 
             if (poOverDS != NULL)
             {
@@ -883,19 +886,15 @@ CPLErr GDALDefaultOverviews::CreateMaskBand( int nFlags, int nBand )
 /* -------------------------------------------------------------------- */
 /*      ensure existing file gets opened if there is one.               */
 /* -------------------------------------------------------------------- */
-    HaveMaskFile();
+    CPL_IGNORE_RET_VAL(HaveMaskFile());
 
 /* -------------------------------------------------------------------- */
 /*      Try creating the mask file.                                     */
 /* -------------------------------------------------------------------- */
     if( poMaskDS == NULL )
     {
-        CPLString osMskFilename;
         GDALDriver *poDr = (GDALDriver *) GDALGetDriverByName( "GTiff" );
-        char **papszOpt = NULL;
-        int  nBX, nBY;
-        int  nBands;
-        
+
         if( poDr == NULL )
             return CE_Failure;
 
@@ -903,15 +902,17 @@ CPLErr GDALDefaultOverviews::CreateMaskBand( int nFlags, int nBand )
         if( poTBand == NULL )
             return CE_Failure;
 
+        int nBands;
         if( nFlags & GMF_PER_DATASET )
             nBands = 1;
         else
             nBands = poDS->GetRasterCount();
 
-
+        char **papszOpt = NULL;
         papszOpt = CSLSetNameValue( papszOpt, "COMPRESS", "DEFLATE" );
         papszOpt = CSLSetNameValue( papszOpt, "INTERLEAVE", "BAND" );
 
+        int  nBX, nBY;
         poTBand->GetBlockSize( &nBX, &nBY );
 
         // try to create matching tile size if legal in TIFF.
@@ -924,8 +925,9 @@ CPLErr GDALDefaultOverviews::CreateMaskBand( int nFlags, int nBand )
                                         CPLString().Printf("%d",nBY) );
         }
 
+        CPLString osMskFilename;
         osMskFilename.Printf( "%s.msk", poDS->GetDescription() );
-        poMaskDS = poDr->Create( osMskFilename, 
+        poMaskDS = poDr->Create( osMskFilename,
                                  poDS->GetRasterXSize(),
                                  poDS->GetRasterYSize(),
                                  nBands, GDT_Byte, papszOpt );
@@ -936,7 +938,7 @@ CPLErr GDALDefaultOverviews::CreateMaskBand( int nFlags, int nBand )
 
         bOwnMaskDS = TRUE;
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Save the mask flags for this band.                              */
 /* -------------------------------------------------------------------- */
@@ -944,21 +946,19 @@ CPLErr GDALDefaultOverviews::CreateMaskBand( int nFlags, int nBand )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Attempt to create a mask band for band %d of %s,\n"
-                  "but the .msk file has a PER_DATASET mask.", 
+                  "but the .msk file has a PER_DATASET mask.",
                   nBand, poDS->GetDescription() );
         return CE_Failure;
     }
-    
-    int iBand; 
 
-    for( iBand = 0; iBand < poDS->GetRasterCount(); iBand++ )
+    for( int iBand = 0; iBand < poDS->GetRasterCount(); iBand++ )
     {
         // we write only the info for this band, unless we are
         // using PER_DATASET in which case we write for all.
-        if( nBand != iBand + 1 && !(nFlags | GMF_PER_DATASET) )
+        if( nBand != iBand + 1 && !(nFlags & GMF_PER_DATASET) )
             continue;
 
-        poMaskDS->SetMetadataItem( 
+        poMaskDS->SetMetadataItem(
             CPLString().Printf("INTERNAL_MASK_FLAGS_%d", iBand+1 ),
             CPLString().Printf("%d", nFlags ) );
     }
@@ -973,18 +973,18 @@ CPLErr GDALDefaultOverviews::CreateMaskBand( int nFlags, int nBand )
 GDALRasterBand *GDALDefaultOverviews::GetMaskBand( int nBand )
 
 {
-    int nFlags = GetMaskFlags( nBand );
+    const int nFlags = GetMaskFlags( nBand );
 
     if( nFlags == 0x8000 ) // secret code meaning we don't handle this band.
         return NULL;
-        
+
     if( nFlags & GMF_PER_DATASET )
         return poMaskDS->GetRasterBand(1);
 
     if( nBand > 0 )
         return poMaskDS->GetRasterBand( nBand );
-    else 
-        return NULL;
+
+    return NULL;
 }
 
 /************************************************************************/
@@ -1000,15 +1000,15 @@ int GDALDefaultOverviews::GetMaskFlags( int nBand )
 /* -------------------------------------------------------------------- */
     if( !HaveMaskFile() )
         return 0;
-    
-    const char *pszValue = 
-        poMaskDS->GetMetadataItem( 
+
+    const char *pszValue =
+        poMaskDS->GetMetadataItem(
             CPLString().Printf( "INTERNAL_MASK_FLAGS_%d", MAX(nBand,1)) );
 
     if( pszValue == NULL )
         return 0x8000;
-    else
-        return atoi(pszValue);
+
+    return atoi(pszValue);
 }
 
 /************************************************************************/
@@ -1037,22 +1037,23 @@ int GDALDefaultOverviews::HaveMaskFile( char ** papszSiblingFiles,
 /* -------------------------------------------------------------------- */
     if( poBaseDS != NULL && poBaseDS->oOvManager.HaveMaskFile() )
     {
-        int iOver, nOverviewCount = 0;
         GDALRasterBand *poBaseBand = poBaseDS->GetRasterBand(1);
         GDALRasterBand *poBaseMask = NULL;
 
         if( poBaseBand != NULL )
             poBaseMask = poBaseBand->GetMaskBand();
+
+        int nOverviewCount = 0;
         if( poBaseMask )
             nOverviewCount = poBaseMask->GetOverviewCount();
 
-        for( iOver = 0; iOver < nOverviewCount; iOver++ )
+        for( int iOver = 0; iOver < nOverviewCount; iOver++ )
         {
             GDALRasterBand *poOverBand = poBaseMask->GetOverview( iOver );
             if (poOverBand == NULL)
                 continue;
-            
-            if( poOverBand->GetXSize() == poDS->GetRasterXSize() 
+
+            if( poOverBand->GetXSize() == poDS->GetRasterXSize()
                 && poOverBand->GetYSize() == poDS->GetRasterYSize() )
             {
                 poMaskDS = poOverBand->GetDataset();
@@ -1062,7 +1063,7 @@ int GDALDefaultOverviews::HaveMaskFile( char ** papszSiblingFiles,
 
         bCheckedForMask = TRUE;
         bOwnMaskDS = FALSE;
-        
+
         CPLAssert( poMaskDS != poDS );
 
         return poMaskDS != NULL;
@@ -1084,7 +1085,7 @@ int GDALDefaultOverviews::HaveMaskFile( char ** papszSiblingFiles,
     if( pszBasename == NULL )
         pszBasename = poDS->GetDescription();
 
-    // Don't bother checking for masks of masks. 
+    // Don't bother checking for masks of masks.
     if( EQUAL(CPLGetExtension(pszBasename),"msk") )
         return FALSE;
 
@@ -1092,15 +1093,21 @@ int GDALDefaultOverviews::HaveMaskFile( char ** papszSiblingFiles,
         return FALSE;
     osMskFilename.Printf( "%s.msk", pszBasename );
 
-    int bExists = CPLCheckForFile( (char *) osMskFilename.c_str(), 
+    std::vector<char> achMskFilename;
+    achMskFilename.resize(osMskFilename.size() + 1);
+    memcpy(&(achMskFilename[0]), osMskFilename.c_str(), osMskFilename.size() + 1);
+    int bExists = CPLCheckForFile( &achMskFilename[0],
                                    papszSiblingFiles );
+    osMskFilename = &achMskFilename[0];
 
 #if !defined(WIN32)
     if( !bExists && !papszSiblingFiles )
     {
         osMskFilename.Printf( "%s.MSK", pszBasename );
-        bExists = CPLCheckForFile( (char *) osMskFilename.c_str(), 
+        memcpy(&(achMskFilename[0]), osMskFilename.c_str(), osMskFilename.size() + 1);
+        bExists = CPLCheckForFile( &achMskFilename[0],
                                    papszSiblingFiles );
+        osMskFilename = &achMskFilename[0];
     }
 #endif
 
@@ -1120,6 +1127,6 @@ int GDALDefaultOverviews::HaveMaskFile( char ** papszSiblingFiles,
         return FALSE;
 
     bOwnMaskDS = TRUE;
-    
+
     return TRUE;
 }
diff --git a/gcore/gdaldllmain.cpp b/gcore/gdaldllmain.cpp
index adc66e7..d3d3bf1 100644
--- a/gcore/gdaldllmain.cpp
+++ b/gcore/gdaldllmain.cpp
@@ -57,29 +57,27 @@ void CPLFinalizeTLS();
  * if GDAL is dynamically linked, since it is automatically called through
  * the unregistration mechanisms of dynamic library loading.
  *
- * Note: no GDAL/OGR code should be called after this call !
+ * Note: no GDAL/OGR code should be called after this call!
  *
  * @since GDAL 2.0
  */
 
-static int bGDALDestroyAlreadyCalled = FALSE;
+static bool bGDALDestroyAlreadyCalled = FALSE;
 void GDALDestroy(void)
 {
     if( bGDALDestroyAlreadyCalled )
         return;
-    bGDALDestroyAlreadyCalled = TRUE;
+    bGDALDestroyAlreadyCalled = true;
 
     CPLDebug("GDAL", "In GDALDestroy - unloading GDAL shared library.");
     bInGDALGlobalDestructor = TRUE;
     GDALDestroyDriverManager();
 
-#ifdef OGR_ENABLED
     OGRCleanupAll();
-#endif
     bInGDALGlobalDestructor = FALSE;
 
     /* See https://trac.osgeo.org/gdal/ticket/6139 */
-    /* Needed in case no driver manager has been instanciated */
+    /* Needed in case no driver manager has been instantiated. */
     CPLFreeConfig();
     CPLFinalizeTLS();
     CPLCleanupMasterMutex();
@@ -120,7 +118,7 @@ static void GDALDestructor(void)
 {
     if( bGDALDestroyAlreadyCalled )
         return;
-    if( !CSLTestBoolean(CPLGetConfigOption("GDAL_DESTROY", "YES")) )
+    if( !CPLTestBool(CPLGetConfigOption("GDAL_DESTROY", "YES")) )
         return;
     GDALDestroy();
 }
@@ -158,8 +156,7 @@ extern "C" int WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpRese
         GDALDestroy();
     }
 
-    return 1; // ignroed for all reasons but DLL_PROCESS_ATTACH
+    return 1; // ignored for all reasons but DLL_PROCESS_ATTACH
 }
 
 #endif // _MSC_VER
-
diff --git a/gcore/gdaldriver.cpp b/gcore/gdaldriver.cpp
index 5b60d51..eb8c654 100644
--- a/gcore/gdaldriver.cpp
+++ b/gcore/gdaldriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaldriver.cpp 29207 2015-05-18 17:23:45Z mloskot $
+ * $Id: gdaldriver.cpp 33711 2016-03-12 06:29:35Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALDriver class (and C wrappers)
@@ -31,7 +31,7 @@
 #include "gdal_priv.h"
 #include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: gdaldriver.cpp 29207 2015-05-18 17:23:45Z mloskot $");
+CPL_CVSID("$Id: gdaldriver.cpp 33711 2016-03-12 06:29:35Z goatbar $");
 
 CPL_C_START
 const char* GDALClientDatasetGetFilename(const char* pszFilename);
@@ -75,11 +75,11 @@ GDALDriver::~GDALDriver()
 
 /**
  * \brief Destroy a GDALDriver.
- * 
- * This is roughly equivelent to deleting the driver, but is guaranteed
+ *
+ * This is roughly equivalent to deleting the driver, but is guaranteed
  * to take place in the GDAL heap.  It is important this that function
  * not be called on a driver that is registered with the GDALDriverManager.
- * 
+ *
  * @param hDriver the driver to destroy.
  */
 
@@ -115,8 +115,8 @@ void CPL_STDCALL GDALDestroyDriver( GDALDriverH hDriver )
  * In GDAL 2, the arguments nXSize, nYSize and nBands can be passed to 0 when
  * creating a vector-only dataset for a compatible driver.
  *
- * Equivelent of the C function GDALCreate().
- * 
+ * Equivalent of the C function GDALCreate().
+ *
  * @param pszFilename the name of the dataset to create.  UTF-8 encoded.
  * @param nXSize width of created raster in pixels.
  * @param nYSize height of created raster in pixels.
@@ -190,7 +190,7 @@ GDALDataset * GDALDriver::Create( const char * pszFilename,
 
             if( poDstDS != NULL )
             {
-                if( poDstDS->GetDescription() == NULL 
+                if( poDstDS->GetDescription() == NULL
                     || strlen(poDstDS->GetDescription()) == 0 )
                     poDstDS->SetDescription( pszFilename );
 
@@ -214,7 +214,7 @@ GDALDataset * GDALDriver::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Validate creation options.                                      */
 /* -------------------------------------------------------------------- */
-    if (CSLTestBoolean(CPLGetConfigOption("GDAL_VALIDATE_CREATION_OPTIONS", "YES")))
+    if (CPLTestBool(CPLGetConfigOption("GDAL_VALIDATE_CREATION_OPTIONS", "YES")))
         GDALValidateCreationOptions( this, papszOptions );
 
 /* -------------------------------------------------------------------- */
@@ -223,10 +223,10 @@ GDALDataset * GDALDriver::Create( const char * pszFilename,
     GDALDataset *poDS;
 
     CPLDebug( "GDAL", "GDALDriver::Create(%s,%s,%d,%d,%d,%s,%p)",
-              GetDescription(), pszFilename, nXSize, nYSize, nBands, 
-              GDALGetDataTypeName( eType ), 
+              GetDescription(), pszFilename, nXSize, nYSize, nBands,
+              GDALGetDataTypeName( eType ),
               papszOptions );
-    
+
     if( pfnCreate != NULL )
     {
         poDS = pfnCreate( pszFilename, nXSize, nYSize, nBands, eType,
@@ -245,7 +245,7 @@ GDALDataset * GDALDriver::Create( const char * pszFilename,
         if( poDS->GetDescription() == NULL
             || strlen(poDS->GetDescription()) == 0 )
             poDS->SetDescription( pszFilename );
-        
+
         if( poDS->poDriver == NULL )
             poDS->poDriver = this;
 
@@ -265,7 +265,7 @@ GDALDataset * GDALDriver::Create( const char * pszFilename,
  * @see GDALDriver::Create()
  */
 
-GDALDatasetH CPL_DLL CPL_STDCALL 
+GDALDatasetH CPL_DLL CPL_STDCALL
 GDALCreate( GDALDriverH hDriver, const char * pszFilename,
             int nXSize, int nYSize, int nBands, GDALDataType eBandType,
             char ** papszOptions )
@@ -287,7 +287,7 @@ CPLErr GDALDriver::DefaultCopyMasks( GDALDataset *poSrcDS,
                                      int bStrict )
 
 {
-    CPLErr eErr = CE_None;	
+    CPLErr eErr = CE_None;
 
     int nBands = poSrcDS->GetRasterCount();
     if (nBands == 0)
@@ -298,8 +298,8 @@ CPLErr GDALDriver::DefaultCopyMasks( GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Try to copy mask if it seems appropriate.                       */
 /* -------------------------------------------------------------------- */
-    for( int iBand = 0; 
-         eErr == CE_None && iBand < nBands; 
+    for( int iBand = 0;
+         eErr == CE_None && iBand < nBands;
          iBand++ )
     {
         GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand+1 );
@@ -331,7 +331,7 @@ CPLErr GDALDriver::DefaultCopyMasks( GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
     int nMaskFlags = poSrcDS->GetRasterBand(1)->GetMaskFlags();
     if( eErr == CE_None
-        && !(nMaskFlags & (GMF_ALL_VALID|GMF_ALPHA|GMF_NODATA) ) 
+        && !(nMaskFlags & (GMF_ALL_VALID|GMF_ALPHA|GMF_NODATA) )
         && (nMaskFlags & GMF_PER_DATASET) )
     {
         eErr = poDstDS->CreateMaskBand( nMaskFlags );
@@ -354,8 +354,8 @@ CPLErr GDALDriver::DefaultCopyMasks( GDALDataset *poSrcDS,
 /*                         DefaultCreateCopy()                          */
 /************************************************************************/
 
-GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename, 
-                                            GDALDataset * poSrcDS, 
+GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
+                                            GDALDataset * poSrcDS,
                                             int bStrict, char ** papszOptions,
                                             GDALProgressFunc pfnProgress,
                                             void * pProgressData )
@@ -363,7 +363,7 @@ GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
 {
     if( pfnProgress == NULL )
         pfnProgress = GDALDummyProgress;
-    
+
     CPLErrorReset();
 
 /* -------------------------------------------------------------------- */
@@ -410,22 +410,22 @@ GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
     }
 
 /* -------------------------------------------------------------------- */
-/*      Propogate some specific structural metadata as options if it    */
+/*      Propagate some specific structural metadata as options if it    */
 /*      appears to be supported by the target driver and the caller     */
 /*      didn't provide values.                                          */
 /* -------------------------------------------------------------------- */
     char **papszCreateOptions = CSLDuplicate( papszOptions );
     int  iOptItem;
-    static const char *apszOptItems[] = {
+    static const char * const apszOptItems[] = {
         "NBITS", "IMAGE_STRUCTURE",
-        "PIXELTYPE", "IMAGE_STRUCTURE", 
+        "PIXELTYPE", "IMAGE_STRUCTURE",
         NULL };
 
     for( iOptItem = 0; nBands > 0 && apszOptItems[iOptItem] != NULL; iOptItem += 2 )
     {
         // does the source have this metadata item on the first band?
-        const char *pszValue = 
-            poSrcDS->GetRasterBand(1)->GetMetadataItem( 
+        const char *pszValue =
+            poSrcDS->GetRasterBand(1)->GetMetadataItem(
                 apszOptItems[iOptItem], apszOptItems[iOptItem+1] );
 
         if( pszValue == NULL )
@@ -437,17 +437,17 @@ GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
 
         // Does this appear to be a supported creation option on this driver?
         const char *pszOptionList =
-            GetMetadataItem( GDAL_DMD_CREATIONDATATYPES );
+            GetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST );
 
-        if( pszOptionList == NULL 
-            || strstr(pszOptionList,apszOptItems[iOptItem]) != NULL )
+        if( pszOptionList == NULL
+            || strstr(pszOptionList,apszOptItems[iOptItem]) == NULL )
             continue;
 
         papszCreateOptions = CSLSetNameValue( papszCreateOptions,
-                                              apszOptItems[iOptItem], 
+                                              apszOptItems[iOptItem],
                                               pszValue );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create destination dataset.                                     */
 /* -------------------------------------------------------------------- */
@@ -457,9 +457,9 @@ GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
 
     if( nBands > 0 )
         eType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
-    poDstDS = Create( pszFilename, nXSize, nYSize, 
+    poDstDS = Create( pszFilename, nXSize, nYSize,
                       nBands, eType, papszCreateOptions );
-                      
+
     CSLDestroy(papszCreateOptions);
 
     if( poDstDS == NULL )
@@ -469,7 +469,7 @@ GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
     {
         if( GetMetadataItem(GDAL_DCAP_RASTER) != NULL )
         {
-            /* Shouldn't happen for a well-behaved driver */
+            /* Should not happen for a well-behaved driver */
             CPLError(CE_Failure, CPLE_AppDefined,
                      "Output driver created only %d bands whereas %d were expected",
                      nDstBands, nBands);
@@ -488,8 +488,8 @@ GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
         CPLPushErrorHandler(CPLQuietErrorHandler);
 
     if( eErr == CE_None
-        && poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None 
-        && (adfGeoTransform[0] != 0.0 
+        && poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None
+        && (adfGeoTransform[0] != 0.0
             || adfGeoTransform[1] != 1.0
             || adfGeoTransform[2] != 0.0
             || adfGeoTransform[3] != 0.0
@@ -501,7 +501,7 @@ GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
             eErr = CE_None;
     }
 
-    if( eErr == CE_None 
+    if( eErr == CE_None
         && poSrcDS->GetProjectionRef() != NULL
         && strlen(poSrcDS->GetProjectionRef()) > 0 )
     {
@@ -516,7 +516,7 @@ GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
     if( poSrcDS->GetGCPCount() > 0 && eErr == CE_None )
     {
         eErr = poDstDS->SetGCPs( poSrcDS->GetGCPCount(),
-                                 poSrcDS->GetGCPs(), 
+                                 poSrcDS->GetGCPs(),
                                  poSrcDS->GetGCPProjection() );
         if( !bStrict )
             eErr = CE_None;
@@ -533,7 +533,7 @@ GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
 
 /* -------------------------------------------------------------------- */
 /*      Copy transportable special domain metadata (RPCs).  It would    */
-/*      be nice to copy geolocation, but is is pretty fragile.          */
+/*      be nice to copy geolocation, but it is pretty fragile.          */
 /* -------------------------------------------------------------------- */
     char **papszMD = poSrcDS->GetMetadata( "RPC" );
     if( papszMD )
@@ -542,8 +542,8 @@ GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Loop copying bands.                                             */
 /* -------------------------------------------------------------------- */
-    for( int iBand = 0; 
-         eErr == CE_None && iBand < nDstBands; 
+    for( int iBand = 0;
+         eErr == CE_None && iBand < nDstBands;
          iBand++ )
     {
         GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand+1 );
@@ -586,15 +586,15 @@ GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
         if( bSuccess )
             poDstBand->SetNoDataValue( dfValue );
 
-        if( poSrcBand->GetColorInterpretation() != GCI_Undefined 
+        if( poSrcBand->GetColorInterpretation() != GCI_Undefined
             && poSrcBand->GetColorInterpretation()
             != poDstBand->GetColorInterpretation() )
-            poDstBand->SetColorInterpretation( 
+            poDstBand->SetColorInterpretation(
                 poSrcBand->GetColorInterpretation() );
 
         char** papszCatNames;
         papszCatNames = poSrcBand->GetCategoryNames();
-        if (0 != papszCatNames)
+        if (NULL != papszCatNames)
             poDstBand->SetCategoryNames( papszCatNames );
 
         if( !bStrict )
@@ -602,7 +602,7 @@ GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
             CPLPopErrorHandler();
             CPLErrorReset();
         }
-        else 
+        else
             eErr = CPLGetLastErrorType();
     }
 
@@ -610,8 +610,8 @@ GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
 /*      Copy image data.                                                */
 /* -------------------------------------------------------------------- */
     if( eErr == CE_None && nDstBands > 0 )
-        eErr = GDALDatasetCopyWholeRaster( (GDALDatasetH) poSrcDS, 
-                                           (GDALDatasetH) poDstDS, 
+        eErr = GDALDatasetCopyWholeRaster( (GDALDatasetH) poSrcDS,
+                                           (GDALDatasetH) poDstDS,
                                            NULL, pfnProgress, pProgressData );
 
 /* -------------------------------------------------------------------- */
@@ -663,15 +663,15 @@ GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
  * \brief Create a copy of a dataset.
  *
  * This method will attempt to create a copy of a raster dataset with the
- * indicated filename, and in this drivers format.  Band number, size, 
+ * indicated filename, and in this drivers format.  Band number, size,
  * type, projection, geotransform and so forth are all to be copied from
- * the provided template dataset.  
+ * the provided template dataset.
  *
  * Note that many sequential write once formats (such as JPEG and PNG) don't
  * implement the Create() method but do implement this CreateCopy() method.
  * If the driver doesn't implement CreateCopy(), but does implement Create()
  * then the default CreateCopy() mechanism built on calling Create() will
- * be used.                                                             
+ * be used.
  *
  * It is intended that CreateCopy() will often be used with a source dataset
  * which is a virtual dataset allowing configuration of band types, and
@@ -691,11 +691,11 @@ GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
  * \ref gdal_api_proxy mechanism.
  *
  * @param pszFilename the name for the new dataset.  UTF-8 encoded.
- * @param poSrcDS the dataset being duplicated. 
- * @param bStrict TRUE if the copy must be strictly equivelent, or more
- * normally FALSE indicating that the copy may adapt as needed for the 
- * output format. 
- * @param papszOptions additional format dependent options controlling 
+ * @param poSrcDS the dataset being duplicated.
+ * @param bStrict TRUE if the copy must be strictly equivalent, or more
+ * normally FALSE indicating that the copy may adapt as needed for the
+ * output format.
+ * @param papszOptions additional format dependent options controlling
  * creation of the output file. The APPEND_SUBDATASET=YES option can be
  * specified to avoid prior destruction of existing dataset.
  * @param pfnProgress a function to be used to report progress of the copy.
@@ -704,8 +704,8 @@ GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
  * @return a pointer to the newly created dataset (may be read-only access).
  */
 
-GDALDataset *GDALDriver::CreateCopy( const char * pszFilename, 
-                                     GDALDataset * poSrcDS, 
+GDALDataset *GDALDriver::CreateCopy( const char * pszFilename,
+                                     GDALDataset * poSrcDS,
                                      int bStrict, char ** papszOptions,
                                      GDALProgressFunc pfnProgress,
                                      void * pProgressData )
@@ -733,7 +733,7 @@ GDALDataset *GDALDriver::CreateCopy( const char * pszFilename,
                 pfnProgress, pProgressData);
             if( poDstDS != NULL )
             {
-                if( poDstDS->GetDescription() == NULL 
+                if( poDstDS->GetDescription() == NULL
                     || strlen(poDstDS->GetDescription()) == 0 )
                     poDstDS->SetDescription( pszFilename );
 
@@ -752,13 +752,14 @@ GDALDataset *GDALDriver::CreateCopy( const char * pszFilename,
 /*      name.  But even if that seems to fail we will continue since    */
 /*      it might just be a corrupt file or something.                   */
 /* -------------------------------------------------------------------- */
-    int bAppendSubdataset = CSLFetchBoolean(papszOptions, "APPEND_SUBDATASET", FALSE);
+    const bool bAppendSubdataset
+        = CPL_TO_BOOL(CSLFetchBoolean(papszOptions, "APPEND_SUBDATASET", FALSE));
     if( !bAppendSubdataset &&
         CSLFetchBoolean(papszOptions, "QUIET_DELETE_ON_CREATE_COPY", TRUE) )
         QuietDelete( pszFilename );
 
     char** papszOptionsToDelete = NULL;
-    int iIdxQuietDeleteOnCreateCopy = 
+    int iIdxQuietDeleteOnCreateCopy =
         CSLPartialFindString(papszOptions, "QUIET_DELETE_ON_CREATE_COPY=");
     if( iIdxQuietDeleteOnCreateCopy >= 0 )
     {
@@ -774,10 +775,10 @@ GDALDataset *GDALDriver::CreateCopy( const char * pszFilename,
 /* -------------------------------------------------------------------- */
     int iIdxInternalDataset =
         CSLPartialFindString(papszOptions, "_INTERNAL_DATASET=");
-    int bInternalDataset = FALSE;
+    bool bInternalDataset = false;
     if( iIdxInternalDataset >= 0 )
     {
-        bInternalDataset = CSLFetchBoolean(papszOptions, "_INTERNAL_DATASET", FALSE);
+        bInternalDataset = CPL_TO_BOOL(CSLFetchBoolean(papszOptions, "_INTERNAL_DATASET", FALSE));
         if( papszOptionsToDelete == NULL )
             papszOptionsToDelete = CSLDuplicate(papszOptions);
         papszOptions = CSLRemoveStrings(papszOptionsToDelete, iIdxInternalDataset, 1, NULL);
@@ -787,7 +788,7 @@ GDALDataset *GDALDriver::CreateCopy( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Validate creation options.                                      */
 /* -------------------------------------------------------------------- */
-    if (CSLTestBoolean(CPLGetConfigOption("GDAL_VALIDATE_CREATION_OPTIONS", "YES")))
+    if (CPLTestBool(CPLGetConfigOption("GDAL_VALIDATE_CREATION_OPTIONS", "YES")))
         GDALValidateCreationOptions( this, papszOptions);
 
 /* -------------------------------------------------------------------- */
@@ -796,13 +797,13 @@ GDALDataset *GDALDriver::CreateCopy( const char * pszFilename,
 /*      Create() method.                                                */
 /* -------------------------------------------------------------------- */
     GDALDataset *poDstDS;
-    if( pfnCreateCopy != NULL && !CSLTestBoolean(CPLGetConfigOption("GDAL_DEFAULT_CREATE_COPY", "NO")) )
+    if( pfnCreateCopy != NULL && !CPLTestBool(CPLGetConfigOption("GDAL_DEFAULT_CREATE_COPY", "NO")) )
     {
         poDstDS = pfnCreateCopy( pszFilename, poSrcDS, bStrict, papszOptions,
                                  pfnProgress, pProgressData );
         if( poDstDS != NULL )
         {
-            if( poDstDS->GetDescription() == NULL 
+            if( poDstDS->GetDescription() == NULL
                 || strlen(poDstDS->GetDescription()) == 0 )
                 poDstDS->SetDescription( pszFilename );
 
@@ -815,10 +816,10 @@ GDALDataset *GDALDriver::CreateCopy( const char * pszFilename,
     }
     else
     {
-        poDstDS = DefaultCreateCopy( pszFilename, poSrcDS, bStrict, 
+        poDstDS = DefaultCreateCopy( pszFilename, poSrcDS, bStrict,
                                   papszOptions, pfnProgress, pProgressData );
     }
-        
+
     CSLDestroy(papszOptionsToDelete);
     return poDstDS;
 }
@@ -833,9 +834,9 @@ GDALDataset *GDALDriver::CreateCopy( const char * pszFilename,
  * @see GDALDriver::CreateCopy()
  */
 
-GDALDatasetH CPL_STDCALL GDALCreateCopy( GDALDriverH hDriver, 
-                             const char * pszFilename, 
-                             GDALDatasetH hSrcDS, 
+GDALDatasetH CPL_STDCALL GDALCreateCopy( GDALDriverH hDriver,
+                             const char * pszFilename,
+                             GDALDatasetH hSrcDS,
                              int bStrict, char ** papszOptions,
                              GDALProgressFunc pfnProgress,
                              void * pProgressData )
@@ -843,7 +844,7 @@ GDALDatasetH CPL_STDCALL GDALCreateCopy( GDALDriverH hDriver,
 {
     VALIDATE_POINTER1( hDriver, "GDALCreateCopy", NULL );
     VALIDATE_POINTER1( hSrcDS, "GDALCreateCopy", NULL );
-    
+
     return (GDALDatasetH) ((GDALDriver *) hDriver)->
         CreateCopy( pszFilename, (GDALDataset *) hSrcDS, bStrict, papszOptions,
                     pfnProgress, pProgressData );
@@ -928,7 +929,7 @@ CPLErr GDALDriver::QuietDelete( const char *pszName )
  * It is unwise to have open dataset handles on this dataset when it is
  * deleted.
  *
- * Equivelent of the C function GDALDeleteDataset().
+ * Equivalent of the C function GDALDeleteDataset().
  *
  * @param pszFilename name of dataset to delete.
  *
@@ -947,23 +948,23 @@ CPLErr GDALDriver::Delete( const char * pszFilename )
 /*      Collect file list.                                              */
 /* -------------------------------------------------------------------- */
     GDALDatasetH hDS = (GDALDataset *) GDALOpenEx(pszFilename,0,NULL,NULL,NULL);
-        
+
     if( hDS == NULL )
     {
         if( CPLGetLastErrorNo() == 0 )
-            CPLError( CE_Failure, CPLE_OpenFailed, 
+            CPLError( CE_Failure, CPLE_OpenFailed,
                       "Unable to open %s to obtain file list.", pszFilename );
 
         return CE_Failure;
     }
 
     char **papszFileList = GDALGetFileList( hDS );
-        
+
     GDALClose( hDS );
 
     if( CSLCount( papszFileList ) == 0 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "Unable to determine files associated with %s,\n"
                   "delete fails.", pszFilename );
 
@@ -1011,7 +1012,7 @@ CPLErr CPL_STDCALL GDALDeleteDataset( GDALDriverH hDriver, const char * pszFilen
 
     if( hDriver == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "No identifiable driver for %s.",
                   pszFilename );
         return CE_Failure;
@@ -1027,7 +1028,7 @@ CPLErr CPL_STDCALL GDALDeleteDataset( GDALDriverH hDriver, const char * pszFilen
 /*      there is no format specific implementation.                     */
 /************************************************************************/
 
-CPLErr GDALDriver::DefaultRename( const char * pszNewName, 
+CPLErr GDALDriver::DefaultRename( const char * pszNewName,
                                   const char *pszOldName )
 
 {
@@ -1035,23 +1036,23 @@ CPLErr GDALDriver::DefaultRename( const char * pszNewName,
 /*      Collect file list.                                              */
 /* -------------------------------------------------------------------- */
     GDALDatasetH hDS = (GDALDataset *) GDALOpen(pszOldName,GA_ReadOnly);
-        
+
     if( hDS == NULL )
     {
         if( CPLGetLastErrorNo() == 0 )
-            CPLError( CE_Failure, CPLE_OpenFailed, 
+            CPLError( CE_Failure, CPLE_OpenFailed,
                       "Unable to open %s to obtain file list.", pszOldName );
 
         return CE_Failure;
     }
 
     char **papszFileList = GDALGetFileList( hDS );
-        
+
     GDALClose( hDS );
 
     if( CSLCount( papszFileList ) == 0 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "Unable to determine files associated with %s,\n"
                   "rename fails.", pszOldName );
 
@@ -1064,7 +1065,7 @@ CPLErr GDALDriver::DefaultRename( const char * pszNewName,
 /* -------------------------------------------------------------------- */
     CPLErr eErr = CE_None;
     int i;
-    char **papszNewFileList = 
+    char **papszNewFileList =
         CPLCorrespondingPaths( pszOldName, pszNewName, papszFileList );
 
     if( papszNewFileList == NULL )
@@ -1075,7 +1076,7 @@ CPLErr GDALDriver::DefaultRename( const char * pszNewName,
         if( CPLMoveFile( papszNewFileList[i], papszFileList[i] ) != 0 )
         {
             eErr = CE_Failure;
-            // Try to put the ones we moved back. 
+            // Try to put the ones we moved back.
             for( --i; i >= 0; i-- )
                 CPLMoveFile( papszFileList[i], papszNewFileList[i] );
             break;
@@ -1096,12 +1097,12 @@ CPLErr GDALDriver::DefaultRename( const char * pszNewName,
  * \brief Rename a dataset.
  *
  * Rename a dataset. This may including moving the dataset to a new directory
- * or even a new filesystem.  
+ * or even a new filesystem.
  *
  * It is unwise to have open dataset handles on this dataset when it is
- * being renamed. 
+ * being renamed.
  *
- * Equivelent of the C function GDALRenameDataset().
+ * Equivalent of the C function GDALRenameDataset().
  *
  * @param pszNewName new name for the dataset.
  * @param pszOldName old name for the dataset.
@@ -1128,17 +1129,17 @@ CPLErr GDALDriver::Rename( const char * pszNewName, const char *pszOldName )
  * @see GDALDriver::Rename()
  */
 
-CPLErr CPL_STDCALL GDALRenameDataset( GDALDriverH hDriver, 
+CPLErr CPL_STDCALL GDALRenameDataset( GDALDriverH hDriver,
                                       const char * pszNewName,
                                       const char * pszOldName )
 
 {
     if( hDriver == NULL )
         hDriver = GDALIdentifyDriver( pszOldName, NULL );
-    
+
     if( hDriver == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "No identifiable driver for %s.",
                   pszOldName );
         return CE_Failure;
@@ -1154,7 +1155,7 @@ CPLErr CPL_STDCALL GDALRenameDataset( GDALDriverH hDriver,
 /*      there is no format specific implementation.                     */
 /************************************************************************/
 
-CPLErr GDALDriver::DefaultCopyFiles( const char * pszNewName, 
+CPLErr GDALDriver::DefaultCopyFiles( const char * pszNewName,
                                      const char *pszOldName )
 
 {
@@ -1162,23 +1163,23 @@ CPLErr GDALDriver::DefaultCopyFiles( const char * pszNewName,
 /*      Collect file list.                                              */
 /* -------------------------------------------------------------------- */
     GDALDatasetH hDS = (GDALDataset *) GDALOpen(pszOldName,GA_ReadOnly);
-        
+
     if( hDS == NULL )
     {
         if( CPLGetLastErrorNo() == 0 )
-            CPLError( CE_Failure, CPLE_OpenFailed, 
+            CPLError( CE_Failure, CPLE_OpenFailed,
                       "Unable to open %s to obtain file list.", pszOldName );
 
         return CE_Failure;
     }
 
     char **papszFileList = GDALGetFileList( hDS );
-        
+
     GDALClose( hDS );
 
     if( CSLCount( papszFileList ) == 0 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "Unable to determine files associated with %s,\n"
                   "rename fails.", pszOldName );
 
@@ -1191,7 +1192,7 @@ CPLErr GDALDriver::DefaultCopyFiles( const char * pszNewName,
 /* -------------------------------------------------------------------- */
     CPLErr eErr = CE_None;
     int i;
-    char **papszNewFileList = 
+    char **papszNewFileList =
         CPLCorrespondingPaths( pszOldName, pszNewName, papszFileList );
 
     if( papszNewFileList == NULL )
@@ -1202,7 +1203,7 @@ CPLErr GDALDriver::DefaultCopyFiles( const char * pszNewName,
         if( CPLCopyFile( papszNewFileList[i], papszFileList[i] ) != 0 )
         {
             eErr = CE_Failure;
-            // Try to put the ones we moved back. 
+            // Try to put the ones we moved back.
             for( --i; i >= 0; i-- )
                 VSIUnlink( papszNewFileList[i] );
             break;
@@ -1224,7 +1225,7 @@ CPLErr GDALDriver::DefaultCopyFiles( const char * pszNewName,
  *
  * Copy all the files associated with a dataset.
  *
- * Equivelent of the C function GDALCopyDatasetFiles().
+ * Equivalent of the C function GDALCopyDatasetFiles().
  *
  * @param pszNewName new name for the dataset.
  * @param pszOldName old name for the dataset.
@@ -1251,17 +1252,17 @@ CPLErr GDALDriver::CopyFiles( const char * pszNewName, const char *pszOldName )
  * @see GDALDriver::CopyFiles()
  */
 
-CPLErr CPL_STDCALL GDALCopyDatasetFiles( GDALDriverH hDriver, 
+CPLErr CPL_STDCALL GDALCopyDatasetFiles( GDALDriverH hDriver,
                                          const char * pszNewName,
                                          const char * pszOldName )
 
 {
     if( hDriver == NULL )
         hDriver = GDALIdentifyDriver( pszOldName, NULL );
-    
+
     if( hDriver == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "No identifiable driver for %s.",
                   pszOldName );
         return CE_Failure;
@@ -1314,7 +1315,7 @@ const char * CPL_STDCALL GDALGetDriverLongName( GDALDriverH hDriver )
 {
     VALIDATE_POINTER1( hDriver, "GDALGetDriverLongName", NULL );
 
-    const char *pszLongName = 
+    const char *pszLongName =
         ((GDALDriver *) hDriver)->GetMetadataItem( GDAL_DMD_LONGNAME );
 
     if( pszLongName == NULL )
@@ -1368,7 +1369,7 @@ const char * CPL_STDCALL GDALGetDriverCreationOptionList( GDALDriverH hDriver )
 {
     VALIDATE_POINTER1( hDriver, "GDALGetDriverCreationOptionList", NULL );
 
-    const char *pszOptionList = 
+    const char *pszOptionList =
         ((GDALDriver *) hDriver)->GetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST );
 
     if( pszOptionList == NULL )
@@ -1393,7 +1394,7 @@ const char * CPL_STDCALL GDALGetDriverCreationOptionList( GDALDriverH hDriver )
  * function will return TRUE. Otherwise it will check that the keys and values
  * in the list of creation options are compatible with the capabilities declared
  * by the GDAL_DMD_CREATIONOPTIONLIST metadata item. In case of incompatibility
- * a (non fatal) warning will be emited and FALSE will be returned.
+ * a (non fatal) warning will be emitted and FALSE will be returned.
  *
  * @param hDriver the handle of the driver with whom the lists of creation option
  *                must be validated
@@ -1407,7 +1408,7 @@ int CPL_STDCALL GDALValidateCreationOptions( GDALDriverH hDriver,
                                              char** papszCreationOptions)
 {
     VALIDATE_POINTER1( hDriver, "GDALValidateCreationOptions", FALSE );
-    const char *pszOptionList = 
+    const char *pszOptionList =
         ((GDALDriver *) hDriver)->GetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST );
     CPLString osDriver;
     osDriver.Printf("driver %s", ((GDALDriver *) hDriver)->GetDescription());
@@ -1434,7 +1435,7 @@ int GDALValidateOpenOptions( GDALDriverH hDriver,
                              const char* const* papszOpenOptions)
 {
     VALIDATE_POINTER1( hDriver, "GDALValidateOpenOptions", FALSE );
-    const char *pszOptionList = 
+    const char *pszOptionList =
         ((GDALDriver *) hDriver)->GetMetadataItem( GDAL_DMD_OPENOPTIONLIST );
     CPLString osDriver;
     osDriver.Printf("driver %s", ((GDALDriver *) hDriver)->GetDescription());
@@ -1458,7 +1459,7 @@ int GDALValidateOptions( const char* pszOptionList,
         return TRUE;
     if( pszOptionList == NULL )
         return TRUE;
-    
+
     CPLXMLNode* psNode = CPLParseXMLString(pszOptionList);
     if (psNode == NULL)
     {
@@ -1487,9 +1488,18 @@ int GDALValidateOptions( const char* pszOptionList,
         if( EQUAL(pszKey, "VALIDATE_OPEN_OPTIONS") )
         {
             papszOptionsToValidate ++;
+            CPLFree(pszKey);
             continue;
         }
 
+        // Must we be forgiving in case of missing option ?
+        bool bWarnIfMissingKey = true;
+        if( pszKey[0] == '@' )
+        {
+            bWarnIfMissingKey = false;
+            memmove(pszKey, pszKey + 1, strlen(pszKey+1)+1);
+        }
+
         CPLXMLNode* psChildNode = psNode->psChild;
         while(psChildNode)
         {
@@ -1529,8 +1539,9 @@ int GDALValidateOptions( const char* pszOptionList,
         }
         if (psChildNode == NULL)
         {
-            if( !EQUAL(pszErrorMessageOptionType, "open option") ||
-                CSLFetchBoolean((char**)papszOptionsToValidate, "VALIDATE_OPEN_OPTIONS", TRUE) )
+            if( bWarnIfMissingKey &&
+                (!EQUAL(pszErrorMessageOptionType, "open option") ||
+                 CSLFetchBoolean((char**)papszOptionsToValidate, "VALIDATE_OPEN_OPTIONS", TRUE)) )
             {
                 CPLError(CE_Warning, CPLE_NotSupported,
                         "%s does not support %s %s",
@@ -1667,6 +1678,7 @@ int GDALValidateOptions( const char* pszOptionList,
                         CPLError(CE_Warning, CPLE_NotSupported,
                              "'%s' is an unexpected value for %s %s that should be >= %s.",
                              pszValue, pszKey, pszErrorMessageOptionType, pszMin);
+                        CPLFree(pszKey);
                         break;
                     }
                     if( pszMax && dfVal > CPLAtof(pszMax) )
@@ -1674,6 +1686,7 @@ int GDALValidateOptions( const char* pszOptionList,
                         CPLError(CE_Warning, CPLE_NotSupported,
                              "'%s' is an unexpected value for %s %s that should be <= %s.",
                              pszValue, pszKey, pszErrorMessageOptionType, pszMax);
+                        CPLFree(pszKey);
                         break;
                     }
                 }
@@ -1691,7 +1704,7 @@ int GDALValidateOptions( const char* pszOptionList,
             }
             else if (EQUAL(pszType, "STRING-SELECT"))
             {
-                int bMatchFound = FALSE;
+                bool bMatchFound = false;
                 CPLXMLNode* psStringSelect = psChildNode->psChild;
                 while(psStringSelect)
                 {
@@ -1704,7 +1717,7 @@ int GDALValidateOptions( const char* pszOptionList,
                             if (psOptionNode->eType == CXT_Text &&
                                 EQUAL(psOptionNode->pszValue, pszValue))
                             {
-                                bMatchFound = TRUE;
+                                bMatchFound = true;
                                 break;
                             }
                             psOptionNode = psOptionNode->psNext;
@@ -1773,7 +1786,7 @@ int GDALValidateOptions( const char* pszOptionList,
  * \brief Identify the driver that can open a raster file.
  *
  * This function will try to identify the driver that can open the passed file
- * name by invoking the Identify method of each registered GDALDriver in turn. 
+ * name by invoking the Identify method of each registered GDALDriver in turn.
  * The first driver that successful identifies the file name will be returned.
  * If all drivers fail then NULL is returned.
  *
@@ -1781,7 +1794,7 @@ int GDALValidateOptions( const char* pszOptionList,
  * file system machinery, it is possible to give an optional list of files.
  * This is the list of all files at the same level in the file system as the
  * target file, including the target file. The filenames will not include any
- * path components, are an essentially just the output of CPLReadDir() on the
+ * path components, are an essentially just the output of VSIReadDir() on the
  * parent directory. If the target object does not have filesystem semantics
  * then the file list should be NULL.
  *
@@ -1794,12 +1807,12 @@ int GDALValidateOptions( const char* pszOptionList,
  * value may be NULL.
  *
  * @return A GDALDriverH handle or NULL on failure.  For C++ applications
- * this handle can be cast to a GDALDriver *. 
+ * this handle can be cast to a GDALDriver *.
  */
 
 
-GDALDriverH CPL_STDCALL 
-GDALIdentifyDriver( const char * pszFilename, 
+GDALDriverH CPL_STDCALL
+GDALIdentifyDriver( const char * pszFilename,
                     char **papszFileList )
 
 {
@@ -1884,8 +1897,8 @@ GDALIdentifyDriver( const char * pszFilename,
 /*                          SetMetadataItem()                           */
 /************************************************************************/
 
-CPLErr GDALDriver::SetMetadataItem( const char * pszName, 
-                                    const char * pszValue, 
+CPLErr GDALDriver::SetMetadataItem( const char * pszName,
+                                    const char * pszValue,
                                     const char * pszDomain )
 
 {
diff --git a/gcore/gdaldrivermanager.cpp b/gcore/gdaldrivermanager.cpp
index 9be7a27..b9ff7b3 100644
--- a/gcore/gdaldrivermanager.cpp
+++ b/gcore/gdaldrivermanager.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaldrivermanager.cpp 29330 2015-06-14 12:11:11Z rouault $
+ * $Id: gdaldrivermanager.cpp 33711 2016-03-12 06:29:35Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALDriverManager class.
@@ -28,13 +28,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_priv.h"
-#include "cpl_string.h"
-#include "cpl_multiproc.h"
-#include "ogr_srs_api.h"
 #include "cpl_multiproc.h"
-#include "gdal_pam.h"
+#include "cpl_string.h"
 #include "gdal_alg_priv.h"
+#include "gdal_pam.h"
+#include "gdal_priv.h"
+#include "ogr_srs_api.h"
 
 #ifdef _MSC_VER
 #  ifdef MSVC_USE_VLD
@@ -43,10 +42,7 @@
 #  endif
 #endif
 
-CPL_CVSID("$Id: gdaldrivermanager.cpp 29330 2015-06-14 12:11:11Z rouault $");
-
-static const char *pszUpdatableINST_DATA = 
-"__INST_DATA_TARGET:                                                                                                                                      ";
+CPL_CVSID("$Id: gdaldrivermanager.cpp 33711 2016-03-12 06:29:35Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -96,40 +92,30 @@ GDALDriverManager * GetGDALDriverManager()
 /*                         GDALDriverManager()                          */
 /************************************************************************/
 
-GDALDriverManager::GDALDriverManager()
-
+GDALDriverManager::GDALDriverManager() :
+    nDrivers(0),
+    papoDrivers(NULL)
 {
-    nDrivers = 0;
-    papoDrivers = NULL;
-
     CPLAssert( poDM == NULL );
 
 /* -------------------------------------------------------------------- */
 /*      We want to push a location to search for data files             */
 /*      supporting GDAL/OGR such as EPSG csv files, S-57 definition     */
-/*      files, and so forth.  The static pszUpdateableINST_DATA         */
-/*      string can be updated within the shared library or              */
-/*      executable during an install to point installed data            */
-/*      directory.  If it isn't burned in here then we use the          */
-/*      INST_DATA macro (setup at configure time) if                    */
-/*      available. Otherwise we don't push anything and we hope         */
-/*      other mechanisms such as environment variables will have        */
-/*      been employed.                                                  */
+/*      files, and so forth.  Use the INST_DATA macro (setup at         */
+/*      configure time) if available. Otherwise we don't push anything  */
+/*      and we hope other mechanisms such as environment variables will */
+/*      have been employed.                                             */
 /* -------------------------------------------------------------------- */
     if( CPLGetConfigOption( "GDAL_DATA", NULL ) != NULL )
     {
         // this one is picked up automatically by finder initialization.
     }
-    else if( pszUpdatableINST_DATA[19] != ' ' )
-    {
-        CPLPushFinderLocation( pszUpdatableINST_DATA + 19 );
-    }
+#ifdef INST_DATA
     else
     {
-#ifdef INST_DATA
         CPLPushFinderLocation( INST_DATA );
-#endif
     }
+#endif
 }
 
 /************************************************************************/
@@ -145,12 +131,6 @@ GDALDriverManager::~GDALDriverManager()
 /* -------------------------------------------------------------------- */
 /*      Cleanup any open datasets.                                      */
 /* -------------------------------------------------------------------- */
-    int i, nDSCount;
-    GDALDataset **papoDSList;
-
-    /* First begin by requesting each reamining dataset to drop any reference */
-    /* to other datasets */
-    int bHasDroppedRef;
 
     /* We have to prevent the destroying of the dataset pool during this first */
     /* phase, otherwise it cause crashes with a VRT B referencing a VRT A, and if */
@@ -165,18 +145,23 @@ GDALDriverManager::~GDALDriverManager()
     /* datasets, which defeat some "design" of the proxy pool */
     GDALDatasetPoolPreventDestroy();
 
+    /* First begin by requesting each remaining dataset to drop any reference */
+    /* to other datasets */
+    bool bHasDroppedRef = false;
+
     do
     {
-        papoDSList = GDALDataset::GetOpenDatasets(&nDSCount);
+        int nDSCount;
+        GDALDataset **papoDSList = GDALDataset::GetOpenDatasets(&nDSCount);
         /* If a dataset has dropped a reference, the list might have become */
         /* invalid, so go out of the loop and try again with the new valid */
         /* list */
-        bHasDroppedRef = FALSE;
-        for(i=0;i<nDSCount && !bHasDroppedRef;i++)
+        bHasDroppedRef = false;
+        for(int i=0;i<nDSCount && !bHasDroppedRef;i++)
         {
             //CPLDebug("GDAL", "Call CloseDependentDatasets() on %s",
             //      papoDSList[i]->GetDescription() );
-            bHasDroppedRef = papoDSList[i]->CloseDependentDatasets();
+            bHasDroppedRef = CPL_TO_BOOL(papoDSList[i]->CloseDependentDatasets());
         }
     } while(bHasDroppedRef);
 
@@ -185,8 +170,9 @@ GDALDriverManager::~GDALDriverManager()
     GDALDatasetPoolForceDestroy();
 
     /* Now close the stand-alone datasets */
-    papoDSList = GDALDataset::GetOpenDatasets(&nDSCount);
-    for(i=0;i<nDSCount;i++)
+    int nDSCount;
+    GDALDataset **papoDSList = GDALDataset::GetOpenDatasets(&nDSCount);
+    for(int i=0;i<nDSCount;i++)
     {
         CPLDebug( "GDAL", "force close of %s (%p) in GDALDriverManager cleanup.",
                   papoDSList[i]->GetDescription(), papoDSList[i] );
@@ -201,7 +187,7 @@ GDALDriverManager::~GDALDriverManager()
 /* -------------------------------------------------------------------- */
     while( GetDriverCount() > 0 )
     {
-        GDALDriver      *poDriver = GetDriver(0);
+        GDALDriver *poDriver = GetDriver(0);
 
         DeregisterDriver(poDriver);
         delete poDriver;
@@ -220,7 +206,7 @@ GDALDriverManager::~GDALDriverManager()
     PamCleanProxyDB();
 
 /* -------------------------------------------------------------------- */
-/*      Blow away all the finder hints paths.  We really shouldn't      */
+/*      Blow away all the finder hints paths.  We really should not     */
 /*      be doing all of them, but it is currently hard to keep track    */
 /*      of those that actually belong to us.                            */
 /* -------------------------------------------------------------------- */
@@ -257,11 +243,11 @@ GDALDriverManager::~GDALDriverManager()
 /* -------------------------------------------------------------------- */
 /*      Cleanup dataset list mutex                                      */
 /* -------------------------------------------------------------------- */
-    if ( *GDALGetphDLMutex() != NULL ) 
-    { 
-        CPLDestroyMutex( *GDALGetphDLMutex() ); 
-        *GDALGetphDLMutex() = NULL; 
-    } 
+    if ( *GDALGetphDLMutex() != NULL )
+    {
+        CPLDestroyMutex( *GDALGetphDLMutex() );
+        *GDALGetphDLMutex() = NULL;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Cleanup raster block mutex                                      */
@@ -284,8 +270,13 @@ GDALDriverManager::~GDALDriverManager()
     CPLCleanupSetlocaleMutex();
 
 /* -------------------------------------------------------------------- */
+/*      Cleanup QHull mutex                                             */
+/* -------------------------------------------------------------------- */
+    GDALTriangulationTerminate();
+
+/* -------------------------------------------------------------------- */
 /*      Cleanup the master CPL mutex, which governs the creation        */
-/*      of all other mutexes.                                           */ 
+/*      of all other mutexes.                                           */
 /* -------------------------------------------------------------------- */
     CPLCleanupMasterMutex();
 
@@ -402,9 +393,7 @@ int GDALDriverManager::RegisterDriver( GDALDriver * poDriver )
 /* -------------------------------------------------------------------- */
     if( GetDriverByName_unlocked( poDriver->GetDescription() ) != NULL )
     {
-        int             i;
-
-        for( i = 0; i < nDrivers; i++ )
+        for( int i = 0; i < nDrivers; i++ )
         {
             if( papoDrivers[i] == poDriver )
             {
@@ -414,12 +403,15 @@ int GDALDriverManager::RegisterDriver( GDALDriver * poDriver )
 
         CPLAssert( FALSE );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Otherwise grow the list to hold the new entry.                  */
 /* -------------------------------------------------------------------- */
-    papoDrivers = (GDALDriver **)
-        VSIRealloc(papoDrivers, sizeof(GDALDriver *) * (nDrivers+1));
+    GDALDriver** papoNewDrivers = (GDALDriver **)
+        VSI_REALLOC_VERBOSE(papoDrivers, sizeof(GDALDriver *) * (nDrivers+1));
+    if( papoNewDrivers == NULL )
+        return -1;
+    papoDrivers = papoNewDrivers;
 
     papoDrivers[nDrivers] = poDriver;
     nDrivers++;
@@ -430,25 +422,26 @@ int GDALDriverManager::RegisterDriver( GDALDriver * poDriver )
 
     if( poDriver->pfnCreate != NULL )
         poDriver->SetMetadataItem( GDAL_DCAP_CREATE, "YES" );
-    
+
     if( poDriver->pfnCreateCopy != NULL )
         poDriver->SetMetadataItem( GDAL_DCAP_CREATECOPY, "YES" );
 
-    /* Backward compability for GDAL raster out-of-tree drivers: */
+    /* Backward compatibility for GDAL raster out-of-tree drivers: */
     /* if a driver hasn't explicitly set a vector capability, assume it is */
     /* a raster driver (legacy OGR drivers will have DCAP_VECTOR set before */
     /* calling RegisterDriver() ) */
     if( poDriver->GetMetadataItem( GDAL_DCAP_RASTER ) == NULL &&
-        poDriver->GetMetadataItem( GDAL_DCAP_VECTOR ) == NULL )
+        poDriver->GetMetadataItem( GDAL_DCAP_VECTOR ) == NULL &&
+        poDriver->GetMetadataItem( GDAL_DCAP_GNM ) == NULL )
     {
         CPLDebug("GDAL", "Assuming DCAP_RASTER for driver %s. Please fix it.",
                  poDriver->GetDescription() );
         poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
     }
-    
+
     if( poDriver->GetMetadataItem( GDAL_DMD_OPENOPTIONLIST ) != NULL &&
         poDriver->pfnIdentify == NULL &&
-        !EQUALN(poDriver->GetDescription(), "Interlis", strlen("Interlis")) )
+        !STARTS_WITH_CI(poDriver->GetDescription(), "Interlis") )
     {
         CPLDebug("GDAL", "Driver %s that defines GDAL_DMD_OPENOPTIONLIST must also "
                  "implement Identify(), so that it can be used",
@@ -456,7 +449,7 @@ int GDALDriverManager::RegisterDriver( GDALDriver * poDriver )
     }
 
     oMapNameToDrivers[CPLString(poDriver->GetDescription()).toupper()] = poDriver;
-    
+
     int iResult = nDrivers - 1;
 
     return iResult;
@@ -498,10 +491,10 @@ int CPL_STDCALL GDALRegisterDriver( GDALDriverH hDriver )
 void GDALDriverManager::DeregisterDriver( GDALDriver * poDriver )
 
 {
-    int         i;
     CPLMutexHolderD( &hDMMutex );
 
-    for( i = 0; i < nDrivers; i++ )
+    int i = 0;
+    for( ; i < nDrivers; i++ )
     {
         if( papoDrivers[i] == poDriver )
             break;
@@ -511,12 +504,13 @@ void GDALDriverManager::DeregisterDriver( GDALDriver * poDriver )
         return;
 
     oMapNameToDrivers.erase(CPLString(poDriver->GetDescription()).toupper());
-    while( i < nDrivers-1 )
+    nDrivers--;
+    // Move all following drivers down by one to pack the list.
+    while( i < nDrivers )
     {
         papoDrivers[i] = papoDrivers[i+1];
         i++;
     }
-    nDrivers--;
 }
 
 /************************************************************************/
@@ -585,13 +579,13 @@ GDALDriverH CPL_STDCALL GDALGetDriverByName( const char * pszName )
 /**
  * \brief This method unload undesirable drivers.
  *
- * All drivers specified in the comma delimited list in the GDAL_SKIP 
- * environment variable) will be deregistered and destroyed.  This method 
- * should normally be called after registration of standard drivers to allow 
+ * All drivers specified in the comma delimited list in the GDAL_SKIP
+ * environment variable) will be deregistered and destroyed.  This method
+ * should normally be called after registration of standard drivers to allow
  * the user a way of unloading undesired drivers.  The GDALAllRegister()
  * function already invokes AutoSkipDrivers() at the end, so if that functions
  * is called, it should not be necessary to call this method from application
- * code. 
+ * code.
  *
  * Note: space separator is also accepted for backward compatibility, but some
  * vector formats have spaces in their names, so it is encouraged to use comma
@@ -623,8 +617,8 @@ void GDALDriverManager::AutoSkipDrivers()
             GDALDriver *poDriver = GetDriverByName( apapszList[j][i] );
 
             if( poDriver == NULL )
-                CPLError( CE_Warning, CPLE_AppDefined, 
-                        "Unable to find driver %s to unload from GDAL_SKIP environment variable.", 
+                CPLError( CE_Warning, CPLE_AppDefined,
+                        "Unable to find driver %s to unload from GDAL_SKIP environment variable.",
                         apapszList[j][i] );
             else
             {
@@ -667,8 +661,10 @@ void GDALDriverManager::AutoSkipDrivers()
 void GDALDriverManager::AutoLoadDrivers()
 
 {
-    char     **papszSearchPath = NULL;
-    const char *pszGDAL_DRIVER_PATH = 
+#ifdef GDAL_NO_AUTOLOAD
+    CPLDebug( "GDAL", "GDALDriverManager::AutoLoadDrivers() not compiled in." );
+#else
+    const char *pszGDAL_DRIVER_PATH =
         CPLGetConfigOption( "GDAL_DRIVER_PATH", NULL );
     if( pszGDAL_DRIVER_PATH == NULL )
         pszGDAL_DRIVER_PATH = CPLGetConfigOption( "OGR_DRIVER_PATH", NULL );
@@ -677,7 +673,7 @@ void GDALDriverManager::AutoLoadDrivers()
 /*      Allow applications to completely disable this search by         */
 /*      setting the driver path to the special string "disable".        */
 /* -------------------------------------------------------------------- */
-    if( pszGDAL_DRIVER_PATH != NULL && EQUAL(pszGDAL_DRIVER_PATH,"disable")) 
+    if( pszGDAL_DRIVER_PATH != NULL && EQUAL(pszGDAL_DRIVER_PATH,"disable"))
     {
         CPLDebug( "GDAL", "GDALDriverManager::AutoLoadDrivers() disabled." );
         return;
@@ -686,20 +682,22 @@ void GDALDriverManager::AutoLoadDrivers()
 /* -------------------------------------------------------------------- */
 /*      Where should we look for stuff?                                 */
 /* -------------------------------------------------------------------- */
+    char **papszSearchPath = NULL;
+
     if( pszGDAL_DRIVER_PATH != NULL )
     {
 #ifdef WIN32
-        papszSearchPath = 
+        papszSearchPath =
             CSLTokenizeStringComplex( pszGDAL_DRIVER_PATH, ";", TRUE, FALSE );
 #else
-        papszSearchPath = 
+        papszSearchPath =
             CSLTokenizeStringComplex( pszGDAL_DRIVER_PATH, ":", TRUE, FALSE );
 #endif
     }
     else
     {
 #ifdef GDAL_PREFIX
-        papszSearchPath = CSLAddString( papszSearchPath, 
+        papszSearchPath = CSLAddString( papszSearchPath,
     #ifdef MACOSX_FRAMEWORK
                                         GDAL_PREFIX "/PlugIns");
     #else
@@ -717,17 +715,17 @@ void GDALDriverManager::AutoLoadDrivers()
         }
         else
         {
-            papszSearchPath = CSLAddString( papszSearchPath, 
+            papszSearchPath = CSLAddString( papszSearchPath,
                                             "/usr/local/lib/gdalplugins" );
         }
 #endif
 
    #ifdef MACOSX_FRAMEWORK
    #define num2str(x) str(x)
-   #define str(x) #x 
-     papszSearchPath = CSLAddString( papszSearchPath, 
+   #define str(x) #x
+     papszSearchPath = CSLAddString( papszSearchPath,
                                      "/Library/Application Support/GDAL/"
-                                     num2str(GDAL_VERSION_MAJOR) "."  
+                                     num2str(GDAL_VERSION_MAJOR) "."
                                      num2str(GDAL_VERSION_MINOR) "/PlugIns" );
    #endif
 
@@ -745,51 +743,52 @@ void GDALDriverManager::AutoLoadDrivers()
 /* -------------------------------------------------------------------- */
     for( int iDir = 0; iDir < CSLCount(papszSearchPath); iDir++ )
     {
-        char **papszFiles = NULL;
-        VSIStatBufL sStatBuf;
         CPLString osABISpecificDir =
             CPLFormFilename( papszSearchPath[iDir], osABIVersion, NULL );
-        
+
+        VSIStatBufL sStatBuf;
         if( VSIStatL( osABISpecificDir, &sStatBuf ) != 0 )
             osABISpecificDir = papszSearchPath[iDir];
 
-        papszFiles = CPLReadDir( osABISpecificDir );
-        int nFileCount = CSLCount(papszFiles);
+        char **papszFiles = VSIReadDir( osABISpecificDir );
+        const int nFileCount = CSLCount(papszFiles);
 
         for( int iFile = 0; iFile < nFileCount; iFile++ )
         {
-            char   *pszFuncName;
-            const char *pszFilename;
             const char *pszExtension = CPLGetExtension( papszFiles[iFile] );
-            void   *pRegister;
 
-            if( !EQUAL(pszExtension,"dll") 
-                && !EQUAL(pszExtension,"so") 
+            if( !EQUAL(pszExtension,"dll")
+                && !EQUAL(pszExtension,"so")
                 && !EQUAL(pszExtension,"dylib") )
                 continue;
 
-            if( EQUALN(papszFiles[iFile],"gdal_",strlen("gdal_")) )
+            char *pszFuncName;
+            if( STARTS_WITH_CI(papszFiles[iFile], "gdal_") )
             {
                 pszFuncName = (char *) CPLCalloc(strlen(papszFiles[iFile])+20,1);
-                sprintf( pszFuncName, "GDALRegister_%s", 
-                     CPLGetBasename(papszFiles[iFile]) + strlen("gdal_") );
+                snprintf( pszFuncName,
+                          strlen(papszFiles[iFile])+20,
+                          "GDALRegister_%s",
+                        CPLGetBasename(papszFiles[iFile]) + strlen("gdal_") );
             }
-            else if ( EQUALN(papszFiles[iFile],"ogr_",strlen("ogr_")) )
+            else if ( STARTS_WITH_CI(papszFiles[iFile], "ogr_") )
             {
                 pszFuncName = (char *) CPLCalloc(strlen(papszFiles[iFile])+20,1);
-                sprintf( pszFuncName, "RegisterOGR%s", 
-                     CPLGetBasename(papszFiles[iFile]) + strlen("ogr_") );
+                snprintf( pszFuncName,
+                         strlen(papszFiles[iFile])+20,
+                         "RegisterOGR%s",
+                         CPLGetBasename(papszFiles[iFile]) + strlen("ogr_") );
             }
             else
                 continue;
 
-            pszFilename = 
-                CPLFormFilename( osABISpecificDir, 
-                                 papszFiles[iFile], NULL );
+            const char *pszFilename
+                = CPLFormFilename( osABISpecificDir,
+                                   papszFiles[iFile], NULL );
 
             CPLErrorReset();
             CPLPushErrorHandler(CPLQuietErrorHandler);
-            pRegister = CPLGetSymbol( pszFilename, pszFuncName );
+            void *pRegister = CPLGetSymbol( pszFilename, pszFuncName );
             CPLPopErrorHandler();
             if( pRegister == NULL )
             {
@@ -802,10 +801,10 @@ void GDALDriverManager::AutoLoadDrivers()
                               "%s", osLastErrorMsg.c_str() );
                 }
             }
-            
+
             if( pRegister != NULL )
             {
-                CPLDebug( "GDAL", "Auto register %s using %s.", 
+                CPLDebug( "GDAL", "Auto register %s using %s.",
                           pszFilename, pszFuncName );
 
                 ((void (*)()) pRegister)();
@@ -818,6 +817,9 @@ void GDALDriverManager::AutoLoadDrivers()
     }
 
     CSLDestroy( papszSearchPath );
+
+#endif  // GDAL_NO_AUTOLOAD
+
 }
 
 /************************************************************************/
@@ -827,20 +829,18 @@ void GDALDriverManager::AutoLoadDrivers()
 /**
  * \brief Destroy the driver manager.
  *
- * Incidently unloads all managed drivers.
+ * Incidentally unloads all managed drivers.
  *
  * NOTE: This function is not thread safe.  It should not be called while
- * other threads are actively using GDAL. 
+ * other threads are actively using GDAL.
  */
 
 void CPL_STDCALL GDALDestroyDriverManager( void )
 
 {
-    // THREADSAFETY: We would like to lock the mutex here, but it 
+    // THREADSAFETY: We would like to lock the mutex here, but it
     // needs to be reacquired within the destructor during driver
     // deregistration.
     if( poDM != NULL )
         delete poDM;
 }
-
-
diff --git a/gcore/gdalexif.cpp b/gcore/gdalexif.cpp
index f98573d..5e053eb 100644
--- a/gcore/gdalexif.cpp
+++ b/gcore/gdalexif.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalexif.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: gdalexif.cpp 33229 2016-01-29 19:45:40Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Implements a EXIF directory reader
@@ -31,24 +31,34 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include <vector>
+
 #include "cpl_conv.h"
 #include "cpl_port.h"
 #include "cpl_error.h"
 #include "cpl_string.h"
 #include "cpl_vsi.h"
 
+#include "gdal_priv.h"
 #include "gdalexif.h"
 
-CPL_CVSID("$Id: gdalexif.cpp 27942 2014-11-11 00:57:41Z rouault $");
+using std::vector;
+
+CPL_CVSID("$Id: gdalexif.cpp 33229 2016-01-29 19:45:40Z goatbar $");
+
+static const int MAXSTRINGLENGTH = 65535;
+static const int EXIFOFFSETTAG = 0x8769;
+static const int INTEROPERABILITYOFFSET = 0xA005;
+static const int GPSOFFSETTAG = 0x8825;
 
 /************************************************************************/
 /*                         EXIFPrintData()                              */
 /************************************************************************/
 static void EXIFPrintData(char* pszData, GUInt16 type,
-                   GUInt32 count, unsigned char* data)
+                   GUInt32 count, const unsigned char* data)
 {
   const char* sep = "";
-  char  pszTemp[128];
+  char  szTemp[128];
   char* pszDataEnd = pszData;
 
   pszData[0]='\0';
@@ -58,20 +68,20 @@ static void EXIFPrintData(char* pszData, GUInt16 type,
   case TIFF_UNDEFINED:
   case TIFF_BYTE:
     for(;count>0;count--) {
-      sprintf(pszTemp, "%s%#02x", sep, *data++), sep = " ";
-      if (strlen(pszTemp) + pszDataEnd - pszData >= MAXSTRINGLENGTH)
+      snprintf(szTemp, sizeof(szTemp), "%s%#02x", sep, *data++), sep = " ";
+      if (strlen(szTemp) + pszDataEnd - pszData >= MAXSTRINGLENGTH)
           break;
-      strcat(pszDataEnd,pszTemp);
+      strcat(pszDataEnd,szTemp);
       pszDataEnd += strlen(pszDataEnd);
     }
     break;
 
   case TIFF_SBYTE:
     for(;count>0;count--) {
-      sprintf(pszTemp, "%s%d", sep, *(char *)data++), sep = " ";
-      if (strlen(pszTemp) + pszDataEnd - pszData >= MAXSTRINGLENGTH)
+      snprintf(szTemp, sizeof(szTemp), "%s%d", sep, *(const char *)data++), sep = " ";
+      if (strlen(szTemp) + pszDataEnd - pszData >= MAXSTRINGLENGTH)
           break;
-      strcat(pszDataEnd,pszTemp);
+      strcat(pszDataEnd,szTemp);
       pszDataEnd += strlen(pszDataEnd);
     }
     break;
@@ -82,104 +92,104 @@ static void EXIFPrintData(char* pszData, GUInt16 type,
     break;
 
   case TIFF_SHORT: {
-    register GUInt16 *wp = (GUInt16*)data;
+    const GUInt16 *wp = (const GUInt16*)data;
     for(;count>0;count--) {
-      sprintf(pszTemp, "%s%u", sep, *wp++), sep = " ";
-      if (strlen(pszTemp) + pszDataEnd - pszData >= MAXSTRINGLENGTH)
+      snprintf(szTemp, sizeof(szTemp), "%s%u", sep, *wp++), sep = " ";
+      if (strlen(szTemp) + pszDataEnd - pszData >= MAXSTRINGLENGTH)
           break;
-      strcat(pszDataEnd,pszTemp);
+      strcat(pszDataEnd,szTemp);
       pszDataEnd += strlen(pszDataEnd);
     }
     break;
   }
   case TIFF_SSHORT: {
-    register GInt16 *wp = (GInt16*)data;
+    const GInt16 *wp = (const GInt16*)data;
     for(;count>0;count--) {
-      sprintf(pszTemp, "%s%d", sep, *wp++);
+      snprintf(szTemp, sizeof(szTemp), "%s%d", sep, *wp++);
       sep = " ";
-      if (strlen(pszTemp) + pszDataEnd - pszData >= MAXSTRINGLENGTH)
+      if (strlen(szTemp) + pszDataEnd - pszData >= MAXSTRINGLENGTH)
           break;
-      strcat(pszDataEnd,pszTemp);
+      strcat(pszDataEnd,szTemp);
       pszDataEnd += strlen(pszDataEnd);
     }
     break;
   }
   case TIFF_LONG: {
-    register GUInt32 *lp = (GUInt32*)data;
+    const GUInt32 *lp = (const GUInt32*)data;
     for(;count>0;count--) {
-      sprintf(pszTemp, "%s%lu", sep, (unsigned long) *lp++);
+      snprintf(szTemp, sizeof(szTemp), "%s%lu", sep, (unsigned long) *lp++);
       sep = " ";
-      if (strlen(pszTemp) + pszDataEnd - pszData >= MAXSTRINGLENGTH)
+      if (strlen(szTemp) + pszDataEnd - pszData >= MAXSTRINGLENGTH)
           break;
-      strcat(pszDataEnd,pszTemp);
+      strcat(pszDataEnd,szTemp);
       pszDataEnd += strlen(pszDataEnd);
     }
     break;
   }
   case TIFF_SLONG: {
-    register GInt32 *lp = (GInt32*)data;
+    const GInt32 *lp = (const GInt32*)data;
     for(;count>0;count--) {
-      sprintf(pszTemp, "%s%ld", sep, (long) *lp++), sep = " ";
-      if (strlen(pszTemp) + pszDataEnd - pszData >= MAXSTRINGLENGTH)
+      snprintf(szTemp, sizeof(szTemp), "%s%ld", sep, (long) *lp++), sep = " ";
+      if (strlen(szTemp) + pszDataEnd - pszData >= MAXSTRINGLENGTH)
           break;
-      strcat(pszDataEnd,pszTemp);
+      strcat(pszDataEnd,szTemp);
       pszDataEnd += strlen(pszDataEnd);
     }
     break;
   }
   case TIFF_RATIONAL: {
-    register GUInt32 *lp = (GUInt32*)data;
+    const GUInt32 *lp = (const GUInt32*)data;
       //      if(bSwabflag)
       //      TIFFSwabArrayOfLong((GUInt32*) data, 2*count);
     for(;count>0;count--) {
       if( (lp[0]==0) && (lp[1] == 0) ) {
-          sprintf(pszTemp,"%s(0)",sep);
+          snprintf(szTemp, sizeof(szTemp), "%s(0)",sep);
       }
       else{
-          CPLsprintf(pszTemp, "%s(%g)", sep,
+          CPLsnprintf(szTemp, sizeof(szTemp), "%s(%g)", sep,
               (double) lp[0]/ (double)lp[1]);
       }
       sep = " ";
       lp += 2;
-      if (strlen(pszTemp) + pszDataEnd - pszData >= MAXSTRINGLENGTH)
+      if (strlen(szTemp) + pszDataEnd - pszData >= MAXSTRINGLENGTH)
           break;
-      strcat(pszDataEnd,pszTemp);
+      strcat(pszDataEnd,szTemp);
       pszDataEnd += strlen(pszDataEnd);
     }
     break;
   }
   case TIFF_SRATIONAL: {
-    register GInt32 *lp = (GInt32*)data;
+    const GInt32 *lp = (const GInt32*)data;
     for(;count>0;count--) {
-      CPLsprintf(pszTemp, "%s(%g)", sep,
+      CPLsnprintf(szTemp, sizeof(szTemp), "%s(%g)", sep,
           (float) lp[0]/ (float) lp[1]);
       sep = " ";
       lp += 2;
-      if (strlen(pszTemp) + pszDataEnd - pszData >= MAXSTRINGLENGTH)
+      if (strlen(szTemp) + pszDataEnd - pszData >= MAXSTRINGLENGTH)
           break;
-      strcat(pszDataEnd,pszTemp);
+      strcat(pszDataEnd,szTemp);
       pszDataEnd += strlen(pszDataEnd);
     }
     break;
   }
   case TIFF_FLOAT: {
-    register float *fp = (float *)data;
+    const float *fp = (const float *)data;
     for(;count>0;count--) {
-      CPLsprintf(pszTemp, "%s%g", sep, *fp++), sep = " ";
-      if (strlen(pszTemp) + pszDataEnd - pszData >= MAXSTRINGLENGTH)
+      CPLsnprintf(szTemp, sizeof(szTemp), "%s%g", sep, *fp++), sep = " ";
+      if (strlen(szTemp) + pszDataEnd - pszData >= MAXSTRINGLENGTH)
           break;
-      strcat(pszDataEnd,pszTemp);
+      strcat(pszDataEnd,szTemp);
       pszDataEnd += strlen(pszDataEnd);
     }
     break;
   }
   case TIFF_DOUBLE: {
-    register double *dp = (double *)data;
+    const double *dp = (const double *)data;
     for(;count>0;count--) {
-      CPLsprintf(pszTemp, "%s%g", sep, *dp++), sep = " ";
-      if (strlen(pszTemp) + pszDataEnd - pszData >= MAXSTRINGLENGTH)
+      CPLsnprintf(szTemp, sizeof(szTemp), "%s%g", sep, *dp++), sep = " ";
+      if (strlen(szTemp) + pszDataEnd - pszData >= MAXSTRINGLENGTH)
           break;
-      strcat(pszDataEnd,pszTemp);
+      strcat(pszDataEnd,szTemp);
       pszDataEnd += strlen(pszDataEnd);
     }
     break;
@@ -195,7 +205,6 @@ static void EXIFPrintData(char* pszData, GUInt16 type,
   }
 }
 
-
 /************************************************************************/
 /*                        EXIFExtractMetadata()                         */
 /*                                                                      */
@@ -206,29 +215,19 @@ CPLErr EXIFExtractMetadata(char**& papszMetadata,
                            int bSwabflag, int nTIFFHEADER,
                            int& nExifOffset, int& nInterOffset, int& nGPSOffset)
 {
-    GUInt16        nEntryCount;
-    int space;
-    unsigned int           n,i;
-    char          pszTemp[MAXSTRINGLENGTH];
-    char          pszName[128];
-
-    VSILFILE* fp = (VSILFILE* )fpInL;
-
-    TIFFDirEntry *poTIFFDirEntry;
-    TIFFDirEntry *poTIFFDir;
-    const struct tagname *poExifTags ;
-    const struct intr_tag *poInterTags = intr_tags;
-    const struct gpsname *poGPSTags;
-
 /* -------------------------------------------------------------------- */
 /*      Read number of entry in directory                               */
 /* -------------------------------------------------------------------- */
-    if( VSIFSeekL(fp, nOffset+nTIFFHEADER, SEEK_SET) != 0
+    GUInt16 nEntryCount;
+    VSILFILE * const fp = static_cast<VSILFILE *>(fpInL);
+
+    if( nOffset > INT_MAX - nTIFFHEADER ||
+        VSIFSeekL(fp, nOffset+nTIFFHEADER, SEEK_SET) != 0
         || VSIFReadL(&nEntryCount,1,sizeof(GUInt16),fp) != sizeof(GUInt16) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Error reading EXIF Directory count at %d.",
-                  nOffset + nTIFFHEADER );
+                  "Error reading EXIF Directory count at " CPL_FRMT_GUIB,
+                  static_cast<vsi_l_offset>(nOffset) + nTIFFHEADER );
         return CE_Failure;
     }
 
@@ -248,24 +247,35 @@ CPLErr EXIFExtractMetadata(char**& papszMetadata,
         return CE_Warning;
     }
 
-    poTIFFDir = (TIFFDirEntry *)CPLMalloc(nEntryCount * sizeof(TIFFDirEntry));
+    GDALEXIFTIFFDirEntry *poTIFFDir = static_cast<GDALEXIFTIFFDirEntry *>(
+        CPLMalloc(nEntryCount * sizeof(GDALEXIFTIFFDirEntry)) );
 
 /* -------------------------------------------------------------------- */
 /*      Read all directory entries                                      */
 /* -------------------------------------------------------------------- */
-    n = VSIFReadL(poTIFFDir, 1,nEntryCount*sizeof(TIFFDirEntry),fp);
-    if (n != nEntryCount*sizeof(TIFFDirEntry))
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Could not read all directories");
-        CPLFree(poTIFFDir);
-        return CE_Failure;
+        const unsigned int n = static_cast<int>(VSIFReadL(
+            poTIFFDir, 1,nEntryCount*sizeof(GDALEXIFTIFFDirEntry),fp));
+        if (n != nEntryCount*sizeof(GDALEXIFTIFFDirEntry))
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Could not read all directories");
+            CPLFree(poTIFFDir);
+            return CE_Failure;
+        }
     }
 
 /* -------------------------------------------------------------------- */
 /*      Parse all entry information in this directory                   */
 /* -------------------------------------------------------------------- */
-    for(poTIFFDirEntry = poTIFFDir,i=nEntryCount; i > 0; i--,poTIFFDirEntry++) {
+    vector<char> oTempStorage(MAXSTRINGLENGTH+1, 0);
+    char * const szTemp = &oTempStorage[0];
+
+    char szName[128];
+
+    GDALEXIFTIFFDirEntry *poTIFFDirEntry = poTIFFDir;
+
+    for( unsigned int i = nEntryCount; i > 0; i--,poTIFFDirEntry++ ) {
         if (bSwabflag) {
             TIFFSwabShort(&poTIFFDirEntry->tdir_tag);
             TIFFSwabShort(&poTIFFDirEntry->tdir_type);
@@ -276,34 +286,42 @@ CPLErr EXIFExtractMetadata(char**& papszMetadata,
 /* -------------------------------------------------------------------- */
 /*      Find Tag name in table                                          */
 /* -------------------------------------------------------------------- */
-        pszName[0] = '\0';
-        pszTemp[0] = '\0';
+        szName[0] = '\0';
+        szTemp[0] = '\0';
 
-        for (poExifTags = tagnames; poExifTags->tag; poExifTags++)
+        for ( const struct tagname *poExifTags = tagnames;
+              poExifTags->tag;
+              poExifTags++)
+        {
             if(poExifTags->tag == poTIFFDirEntry->tdir_tag) {
                 CPLAssert( NULL != poExifTags && NULL != poExifTags->name );
 
-                strcpy(pszName, poExifTags->name);
+                CPLStrlcpy(szName, poExifTags->name, sizeof(szName));
                 break;
             }
-
+        }
 
         if( nOffset == nGPSOffset) {
-            for( poGPSTags = gpstags; poGPSTags->tag != 0xffff; poGPSTags++ )
+            for( const struct gpsname *poGPSTags = gpstags;
+                 poGPSTags->tag != 0xffff;
+                 poGPSTags++ )
+            {
                 if( poGPSTags->tag == poTIFFDirEntry->tdir_tag ) {
                     CPLAssert( NULL != poGPSTags && NULL != poGPSTags->name );
-                    strcpy(pszName, poGPSTags->name);
+                    CPLStrlcpy(szName, poGPSTags->name, sizeof(szName));
                     break;
                 }
+            }
         }
 /* -------------------------------------------------------------------- */
 /*      If the tag was not found, look into the interoperability table  */
 /* -------------------------------------------------------------------- */
         if( nOffset == nInterOffset ) {
-            for(poInterTags = intr_tags; poInterTags->tag; poInterTags++)
+            const struct intr_tag *poInterTags = intr_tags;
+            for( ; poInterTags->tag; poInterTags++)
                 if(poInterTags->tag == poTIFFDirEntry->tdir_tag) {
                     CPLAssert( NULL != poInterTags && NULL != poInterTags->name );
-                    strcpy(pszName, poInterTags->name);
+                    CPLStrlcpy(szName, poInterTags->name, sizeof(szName));
                     break;
                 }
         }
@@ -311,21 +329,25 @@ CPLErr EXIFExtractMetadata(char**& papszMetadata,
 /* -------------------------------------------------------------------- */
 /*      Save important directory tag offset                             */
 /* -------------------------------------------------------------------- */
-        if( poTIFFDirEntry->tdir_tag == EXIFOFFSETTAG )
-            nExifOffset=poTIFFDirEntry->tdir_offset;
-        if( poTIFFDirEntry->tdir_tag == INTEROPERABILITYOFFSET )
-            nInterOffset=poTIFFDirEntry->tdir_offset;
-        if( poTIFFDirEntry->tdir_tag == GPSOFFSETTAG ) {
-            nGPSOffset=poTIFFDirEntry->tdir_offset;
+
+        // Our current API uses int32 and not uint32
+        if( poTIFFDirEntry->tdir_offset < INT_MAX )
+        {
+            if( poTIFFDirEntry->tdir_tag == EXIFOFFSETTAG )
+                nExifOffset=poTIFFDirEntry->tdir_offset;
+            else if( poTIFFDirEntry->tdir_tag == INTEROPERABILITYOFFSET )
+                nInterOffset=poTIFFDirEntry->tdir_offset;
+            else if( poTIFFDirEntry->tdir_tag == GPSOFFSETTAG )
+                nGPSOffset=poTIFFDirEntry->tdir_offset;
         }
 
 /* -------------------------------------------------------------------- */
 /*      If we didn't recognise the tag just ignore it.  To see all      */
 /*      tags comment out the continue.                                  */
 /* -------------------------------------------------------------------- */
-        if( pszName[0] == '\0' )
+        if( szName[0] == '\0' )
         {
-            sprintf( pszName, "EXIF_%d", poTIFFDirEntry->tdir_tag );
+            snprintf( szName, sizeof(szName), "EXIF_%d", poTIFFDirEntry->tdir_tag );
             continue;
         }
 
@@ -333,7 +355,7 @@ CPLErr EXIFExtractMetadata(char**& papszMetadata,
 /*      For UserComment we need to ignore the language binding and      */
 /*      just return the actual contents.                                */
 /* -------------------------------------------------------------------- */
-        if( EQUAL(pszName,"EXIF_UserComment")  )
+        if( EQUAL(szName,"EXIF_UserComment")  )
         {
             poTIFFDirEntry->tdir_type = TIFF_ASCII;
 
@@ -347,20 +369,21 @@ CPLErr EXIFExtractMetadata(char**& papszMetadata,
 /* -------------------------------------------------------------------- */
 /*      Make some UNDEFINED or BYTE fields ASCII for readability.       */
 /* -------------------------------------------------------------------- */
-        if( EQUAL(pszName,"EXIF_ExifVersion")
-            || EQUAL(pszName,"EXIF_FlashPixVersion")
-            || EQUAL(pszName,"EXIF_MakerNote")
-            || EQUAL(pszName,"GPSProcessingMethod") )
+        if( EQUAL(szName,"EXIF_ExifVersion")
+            || EQUAL(szName,"EXIF_FlashPixVersion")
+            || EQUAL(szName,"EXIF_MakerNote")
+            || EQUAL(szName,"GPSProcessingMethod") )
             poTIFFDirEntry->tdir_type = TIFF_ASCII;
 
 /* -------------------------------------------------------------------- */
 /*      Print tags                                                      */
 /* -------------------------------------------------------------------- */
-        int nDataWidth = TIFFDataWidth((TIFFDataType) poTIFFDirEntry->tdir_type);
-        space = poTIFFDirEntry->tdir_count * nDataWidth;
+        const int nDataWidth =
+            TIFFDataWidth((GDALEXIFTIFFDataType) poTIFFDirEntry->tdir_type);
+        const int space = poTIFFDirEntry->tdir_count * nDataWidth;
 
         /* Previous multiplication could overflow, hence this additional check */
-        if (poTIFFDirEntry->tdir_count > MAXSTRINGLENGTH)
+        if( poTIFFDirEntry->tdir_count > static_cast<GUInt32>(MAXSTRINGLENGTH) )
         {
             CPLError( CE_Warning, CPLE_AppDefined,
                       "Too many bytes in tag: %u, ignoring tag.",
@@ -402,7 +425,8 @@ CPLErr EXIFExtractMetadata(char**& papszMetadata,
                 }
             }
 
-            EXIFPrintData(pszTemp,
+            /* coverity[overrun-buffer-arg] */
+            EXIFPrintData(szTemp,
                           poTIFFDirEntry->tdir_type,
                           poTIFFDirEntry->tdir_count, data);
         }
@@ -414,8 +438,8 @@ CPLErr EXIFExtractMetadata(char**& papszMetadata,
             unsigned char *data = (unsigned char *)VSIMalloc(space);
 
             if (data) {
-                VSIFSeekL(fp,poTIFFDirEntry->tdir_offset+nTIFFHEADER,SEEK_SET);
-                VSIFReadL(data, 1, space, fp);
+                CPL_IGNORE_RET_VAL(VSIFSeekL(fp,poTIFFDirEntry->tdir_offset+nTIFFHEADER,SEEK_SET));
+                CPL_IGNORE_RET_VAL(VSIFReadL(data, 1, space, fp));
 
                 if (bSwabflag) {
                     switch (poTIFFDirEntry->tdir_type) {
@@ -444,7 +468,7 @@ CPLErr EXIFExtractMetadata(char**& papszMetadata,
                     }
                 }
 
-                EXIFPrintData(pszTemp, poTIFFDirEntry->tdir_type,
+                EXIFPrintData(szTemp, poTIFFDirEntry->tdir_type,
                               poTIFFDirEntry->tdir_count, data);
                 CPLFree(data);
             }
@@ -456,7 +480,7 @@ CPLErr EXIFExtractMetadata(char**& papszMetadata,
                       (long) space );
         }
 
-        papszMetadata = CSLSetNameValue(papszMetadata, pszName, pszTemp);
+        papszMetadata = CSLSetNameValue(papszMetadata, szName, szTemp);
     }
     CPLFree(poTIFFDir);
 
diff --git a/gcore/gdalexif.h b/gcore/gdalexif.h
index 91f5740..6ab1560 100644
--- a/gcore/gdalexif.h
+++ b/gcore/gdalexif.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalexif.h 24549 2012-06-09 20:14:14Z rouault $
+ * $Id: gdalexif.h 33175 2016-01-27 00:37:49Z goatbar $
  *
  * Project:  JPEG JFIF Driver
  * Purpose:  Implement GDAL JPEG Support based on IJG libjpeg.
@@ -27,11 +27,6 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#define EXIFOFFSETTAG 0x8769
-#define INTEROPERABILITYOFFSET 0xA005
-#define GPSOFFSETTAG     0x8825
-#define MAXSTRINGLENGTH 65535
-
 #ifdef RENAME_INTERNAL_LIBTIFF_SYMBOLS
 #include "../frmts/gtiff/libtiff/gdal_libtiff_symbol_rename.h"
 #endif
@@ -47,10 +42,10 @@ static const struct gpsname {
     { 0x04, "EXIF_GPSLongitude" },
     { 0x05, "EXIF_GPSAltitudeRef" },
     { 0x06, "EXIF_GPSAltitude" },
-    { 0x07, "EXIF_GPSTimeStamp" }, 
-    { 0x08, "EXIF_GPSSatellites" }, 
-    { 0x09, "EXIF_GPSStatus" }, 
-    { 0x0a, "EXIF_GPSMeasureMode" }, 
+    { 0x07, "EXIF_GPSTimeStamp" },
+    { 0x08, "EXIF_GPSSatellites" },
+    { 0x09, "EXIF_GPSStatus" },
+    { 0x0a, "EXIF_GPSMeasureMode" },
     { 0x0b, "EXIF_GPSDOP" },
     { 0x0c, "EXIF_GPSSpeedRef"},
     { 0x0d, "EXIF_GPSSpeed"},
@@ -70,9 +65,9 @@ static const struct gpsname {
     { 0x1b, "EXIF_GPSProcessingMethod"},
     { 0x1c, "EXIF_GPSAreaInformation"},
     { 0x1d, "EXIF_GPSDateStamp"},
-    { 0x1e, "EXIF_GPSDifferential"},  
-    { 0xffff,       ""}
-}; 
+    { 0x1e, "EXIF_GPSDifferential"},
+    { 0xffff, ""}
+};
 
 static const struct tagname {
   GUInt16       tag;
@@ -209,7 +204,7 @@ typedef enum {
         TIFF_FLOAT      = 11,   /* !32-bit IEEE floating point */
         TIFF_DOUBLE     = 12,   /* !64-bit IEEE floating point */
         TIFF_IFD        = 13    /* %32-bit unsigned integer (offset) */
-} TIFFDataType;
+} GDALEXIFTIFFDataType;
 
 /*
  * TIFF Image File Directories are comprised of a table of field
@@ -227,10 +222,10 @@ typedef struct {
         GUInt16          tdir_type;      /* data type; see below */
         GUInt32          tdir_count;     /* number of items; length in spec */
         GUInt32          tdir_offset;    /* byte offset to field data */
-} TIFFDirEntry;
+} GDALEXIFTIFFDirEntry;
 
 CPL_C_START
-extern	int TIFFDataWidth(TIFFDataType);    /* table of tag datatype widths */
+extern	int TIFFDataWidth(GDALEXIFTIFFDataType);    /* table of tag datatype widths */
 extern	void TIFFSwabShort(GUInt16*);
 extern	void TIFFSwabLong(GUInt32*);
 extern	void TIFFSwabDouble(double*);
@@ -238,4 +233,3 @@ extern	void TIFFSwabArrayOfShort(GUInt16*, unsigned long);
 extern	void TIFFSwabArrayOfLong(GUInt32*, unsigned long);
 extern	void TIFFSwabArrayOfDouble(double*, unsigned long);
 CPL_C_END
-
diff --git a/gcore/gdalgeorefpamdataset.cpp b/gcore/gdalgeorefpamdataset.cpp
index 5d8c489..6de69a7 100644
--- a/gcore/gdalgeorefpamdataset.cpp
+++ b/gcore/gdalgeorefpamdataset.cpp
@@ -1,7 +1,7 @@
 /******************************************************************************
- * $Id: gdalgeorefpamdataset.cpp 26571 2013-10-30 10:59:11Z rouault $
+ * $Id: gdalgeorefpamdataset.cpp 33535 2016-02-23 17:41:09Z goatbar $
  *
- * Project:  GDAL 
+ * Project:  GDAL
  * Purpose:  GDALPamDataset with internal storage for georeferencing, with
  *           priority for PAM over internal georeferencing
  * Author:   Even Rouault <even dot rouault at mines-paris dot org>
@@ -34,12 +34,12 @@
 /*                       GDALGeorefPamDataset()                         */
 /************************************************************************/
 
-GDALGeorefPamDataset::GDALGeorefPamDataset()
+GDALGeorefPamDataset::GDALGeorefPamDataset() :
+    bGeoTransformValid(false),
+    pszProjection(NULL),
+    nGCPCount(0),
+    pasGCPList(NULL)
 {
-    pszProjection = NULL;
-    nGCPCount = 0;
-    pasGCPList = NULL;
-    bGeoTransformValid = FALSE;
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
@@ -74,11 +74,11 @@ GDALGeorefPamDataset::~GDALGeorefPamDataset()
 int GDALGeorefPamDataset::GetGCPCount()
 
 {
-    int nPamGCPCount = GDALPamDataset::GetGCPCount();
+    const int nPamGCPCount = GDALPamDataset::GetGCPCount();
     if( nGCPCount > 0 && nPamGCPCount == 0)
         return nGCPCount;
-    else
-        return nPamGCPCount;
+
+    return nPamGCPCount;
 }
 
 /************************************************************************/
@@ -94,8 +94,8 @@ const char *GDALGeorefPamDataset::GetGCPProjection()
     const char* pszPamPrj = GDALPamDataset::GetGCPProjection();
     if( pszProjection != NULL && strlen(pszPamPrj) == 0 )
         return pszProjection;
-    else
-        return pszPamPrj;
+
+    return pszPamPrj;
 }
 
 /************************************************************************/
@@ -108,11 +108,11 @@ const char *GDALGeorefPamDataset::GetGCPProjection()
 const GDAL_GCP *GDALGeorefPamDataset::GetGCPs()
 
 {
-    int nPamGCPCount = GDALPamDataset::GetGCPCount();
+    const int nPamGCPCount = GDALPamDataset::GetGCPCount();
     if( nGCPCount > 0 && nPamGCPCount == 0)
         return pasGCPList;
-    else
-        return GDALPamDataset::GetGCPs();
+
+    return GDALPamDataset::GetGCPs();
 }
 
 /************************************************************************/
@@ -122,7 +122,7 @@ const GDAL_GCP *GDALGeorefPamDataset::GetGCPs()
 /*      our file.                                                       */
 /************************************************************************/
 
-const char *GDALGeorefPamDataset::GetProjectionRef() 
+const char *GDALGeorefPamDataset::GetProjectionRef()
 
 {
     const char* pszPamPrj = GDALPamDataset::GetProjectionRef();
@@ -132,8 +132,8 @@ const char *GDALGeorefPamDataset::GetProjectionRef()
 
     if( pszProjection != NULL && strlen(pszPamPrj) == 0 )
         return pszProjection;
-    else
-        return pszPamPrj;
+
+    return pszPamPrj;
 }
 
 /************************************************************************/
@@ -153,6 +153,6 @@ CPLErr GDALGeorefPamDataset::GetGeoTransform( double * padfTransform )
         memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
         return( CE_None );
     }
-    else
-        return eErr;
+
+    return eErr;
 }
diff --git a/gcore/gdalgeorefpamdataset.h b/gcore/gdalgeorefpamdataset.h
index de1298e..326b2b3 100644
--- a/gcore/gdalgeorefpamdataset.h
+++ b/gcore/gdalgeorefpamdataset.h
@@ -1,7 +1,7 @@
 /******************************************************************************
- * $Id: gdalgeorefpamdataset.h 26571 2013-10-30 10:59:11Z rouault $
+ * $Id: gdalgeorefpamdataset.h 33794 2016-03-26 13:19:07Z goatbar $
  *
- * Project:  GDAL 
+ * Project:  GDAL
  * Purpose:  GDALPamDataset with internal storage for georeferencing, with
  *           priority for PAM over internal georeferencing
  * Author:   Even Rouault <even dot rouault at mines-paris dot org>
@@ -36,7 +36,7 @@
 class CPL_DLL GDALGeorefPamDataset : public GDALPamDataset
 {
   protected:
-    int         bGeoTransformValid;
+    bool        bGeoTransformValid;
     double      adfGeoTransform[6];
     char        *pszProjection;
     int         nGCPCount;
@@ -44,7 +44,7 @@ class CPL_DLL GDALGeorefPamDataset : public GDALPamDataset
 
   public:
         GDALGeorefPamDataset();
-        ~GDALGeorefPamDataset();
+        virtual ~GDALGeorefPamDataset();
 
     virtual CPLErr          GetGeoTransform( double * );
     virtual const char     *GetProjectionRef();
diff --git a/gcore/gdalgmlcoverage.cpp b/gcore/gdalgmlcoverage.cpp
index e861191..89bac9c 100644
--- a/gcore/gdalgmlcoverage.cpp
+++ b/gcore/gdalgmlcoverage.cpp
@@ -1,7 +1,7 @@
 /******************************************************************************
- * $Id: gdalgmlcoverage.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: gdalgmlcoverage.cpp 33526 2016-02-22 20:54:09Z goatbar $
  *
- * Project:  GDAL 
+ * Project:  GDAL
  * Purpose:  Generic support for GML Coverage descriptions.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -27,20 +27,20 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_priv.h"
 #include "cpl_string.h"
 #include "cpl_minixml.h"
-#include "ogr_spatialref.h"
-#include "ogr_geometry.h"
+#include "gdal_priv.h"
 #include "ogr_api.h"
+#include "ogr_geometry.h"
+#include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: gdalgmlcoverage.cpp 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: gdalgmlcoverage.cpp 33526 2016-02-22 20:54:09Z goatbar $");
 
 /************************************************************************/
 /*                        ParseGMLCoverageDesc()                        */
 /************************************************************************/
 
-CPLErr GDALParseGMLCoverage( CPLXMLNode *psXML, 
+CPLErr GDALParseGMLCoverage( CPLXMLNode *psXML,
                              int *pnXSize, int *pnYSize,
                              double *padfGeoTransform,
                              char **ppszProjection )
@@ -54,7 +54,8 @@ CPLErr GDALParseGMLCoverage( CPLXMLNode *psXML,
 /* -------------------------------------------------------------------- */
     CPLXMLNode *psRG = CPLSearchXMLNode( psXML, "=RectifiedGrid" );
     CPLXMLNode *psOriginPoint = NULL;
-    const char *pszOffset1=NULL, *pszOffset2=NULL;
+    const char *pszOffset1 = NULL;
+    const char *pszOffset2 = NULL;
 
     if( psRG != NULL )
     {
@@ -66,7 +67,7 @@ CPLErr GDALParseGMLCoverage( CPLXMLNode *psXML,
         if( psOffset1 != NULL )
         {
             pszOffset1 = CPLGetXMLValue( psOffset1, "", NULL );
-            pszOffset2 = CPLGetXMLValue( psOffset1->psNext, "=offsetVector", 
+            pszOffset2 = CPLGetXMLValue( psOffset1->psNext, "=offsetVector",
                                          NULL );
         }
     }
@@ -74,7 +75,7 @@ CPLErr GDALParseGMLCoverage( CPLXMLNode *psXML,
 /* -------------------------------------------------------------------- */
 /*      If we are missing any of the origin or 2 offsets then give up.  */
 /* -------------------------------------------------------------------- */
-    if( psRG == NULL || psOriginPoint == NULL 
+    if( psRG == NULL || psOriginPoint == NULL
         || pszOffset1 == NULL || pszOffset2 == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -92,10 +93,12 @@ CPLErr GDALParseGMLCoverage( CPLXMLNode *psXML,
 
     if( CSLCount(papszLow) < 2 || CSLCount(papszHigh) < 2 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to find or parse GridEnvelope.low/high." );
+        CSLDestroy( papszLow );
+        CSLDestroy( papszHigh );
         return CE_Failure;
-    }        
+    }
 
     if( pnXSize != NULL )
         *pnXSize = atoi(papszHigh[0]) - atoi(papszLow[0]) + 1;
@@ -113,20 +116,20 @@ CPLErr GDALParseGMLCoverage( CPLXMLNode *psXML,
 
     if( psOriginPoint != NULL )
     {
-        int bOldWrap = FALSE;
+        bool bOldWrap = false;
 
-        // old coverages (ie. WCS) just have <pos> under <origin> so we
-        // may need to temporarily force <origin> to <Point>
+        // Old coverages (i.e. WCS) just have <pos> under <origin>, so we
+        // may need to temporarily force <origin> to <Point>.
         if( psOriginPoint->eType == CXT_Element
-            && EQUAL(psOriginPoint->pszValue,"origin") )
+            && EQUAL(psOriginPoint->pszValue, "origin") )
         {
             strcpy( psOriginPoint->pszValue, "Point");
-            bOldWrap = TRUE;
+            bOldWrap = true;
         }
-        poOriginGeometry = (OGRPoint *) 
-            OGR_G_CreateFromGMLTree( psOriginPoint );
+        poOriginGeometry = reinterpret_cast<OGRPoint *>(
+            OGR_G_CreateFromGMLTree( psOriginPoint ) );
 
-        if( poOriginGeometry != NULL 
+        if( poOriginGeometry != NULL
             && wkbFlatten(poOriginGeometry->getGeometryType()) != wkbPoint )
         {
             delete poOriginGeometry;
@@ -145,11 +148,11 @@ CPLErr GDALParseGMLCoverage( CPLXMLNode *psXML,
 /* -------------------------------------------------------------------- */
     char **papszOffset1Tokens = NULL;
     char **papszOffset2Tokens = NULL;
-    int bSuccess = FALSE;
+    bool bSuccess = false;
 
-    papszOffset1Tokens = 
+    papszOffset1Tokens =
         CSLTokenizeStringComplex( pszOffset1, " ,", FALSE, FALSE );
-    papszOffset2Tokens = 
+    papszOffset2Tokens =
         CSLTokenizeStringComplex( pszOffset2, " ,", FALSE, FALSE );
 
     if( CSLCount(papszOffset1Tokens) >= 2
@@ -169,7 +172,7 @@ CPLErr GDALParseGMLCoverage( CPLXMLNode *psXML,
         padfGeoTransform[3] -= padfGeoTransform[4]*0.5;
         padfGeoTransform[3] -= padfGeoTransform[5]*0.5;
 
-        bSuccess = TRUE;
+        bSuccess = true;
         //bHaveGeoTransform = TRUE;
     }
 
@@ -180,19 +183,19 @@ CPLErr GDALParseGMLCoverage( CPLXMLNode *psXML,
         delete poOriginGeometry;
 
 /* -------------------------------------------------------------------- */
-/*      If we have gotten a geotransform, then try to interprete the    */
+/*      If we have gotten a geotransform, then try to interpret the     */
 /*      srsName.                                                        */
 /* -------------------------------------------------------------------- */
-    if( bSuccess && pszSRSName != NULL 
+    if( bSuccess && pszSRSName != NULL
         && (*ppszProjection == NULL || strlen(*ppszProjection) == 0) )
     {
-        if( EQUALN(pszSRSName,"epsg:",5) )
+        if( STARTS_WITH_CI(pszSRSName, "epsg:") )
         {
             OGRSpatialReference oSRS;
             if( oSRS.SetFromUserInput( pszSRSName ) == OGRERR_NONE )
                 oSRS.exportToWkt( ppszProjection );
         }
-        else if( EQUALN(pszSRSName,"urn:ogc:def:crs:",16) )
+        else if( STARTS_WITH_CI(pszSRSName, "urn:ogc:def:crs:") )
         {
             OGRSpatialReference oSRS;
             if( oSRS.importFromURN( pszSRSName ) == OGRERR_NONE )
@@ -203,10 +206,9 @@ CPLErr GDALParseGMLCoverage( CPLXMLNode *psXML,
     }
 
     if( *ppszProjection )
-        CPLDebug( "GDALJP2Metadata", 
-                  "Got projection from GML box: %s", 
+        CPLDebug( "GDALJP2Metadata",
+                  "Got projection from GML box: %s",
                   *ppszProjection );
 
     return CE_None;
 }
-
diff --git a/gcore/gdalhashsetbandblockcache.cpp b/gcore/gdalhashsetbandblockcache.cpp
new file mode 100644
index 0000000..4415719
--- /dev/null
+++ b/gcore/gdalhashsetbandblockcache.cpp
@@ -0,0 +1,302 @@
+/******************************************************************************
+ * $Id: gdalhashsetbandblockcache.cpp 33536 2016-02-23 17:48:22Z goatbar $
+ *
+ * Project:  GDAL Core
+ * Purpose:  Store cached blocks in a hash set
+ * Author:   Even Rouault, <even dot rouault at spatialys dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2010, Tamas Szekeres
+ * Copyright (c) 2015, Even Rouault <even dot rouault at spatialys dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_hash_set.h"
+#include "cpl_multiproc.h"
+#include "gdal_priv.h"
+#include <algorithm>
+
+CPL_CVSID("$Id: gdalhashsetbandblockcache.cpp 33536 2016-02-23 17:48:22Z goatbar $");
+
+/* ******************************************************************** */
+/*                        GDALHashSetBandBlockCache                     */
+/* ******************************************************************** */
+
+class GDALHashSetBandBlockCache CPL_FINAL : public GDALAbstractBandBlockCache
+{
+    CPLHashSet     *hSet;
+    CPLLock        *hLock;
+
+    public:
+            GDALHashSetBandBlockCache(GDALRasterBand* poBand);
+           ~GDALHashSetBandBlockCache();
+
+           virtual bool             Init();
+           virtual bool             IsInitOK();
+           virtual CPLErr           FlushCache();
+           virtual CPLErr           AdoptBlock( GDALRasterBlock * );
+           virtual GDALRasterBlock *TryGetLockedBlockRef( int nXBlockOff,
+                                                          int nYBlockYOff );
+           virtual CPLErr           UnreferenceBlock( GDALRasterBlock* poBlock );
+           virtual CPLErr           FlushBlock( int nXBlockOff, int nYBlockOff,
+                                                int bWriteDirtyBlock );
+};
+
+/************************************************************************/
+/*                     GDALHashSetBandBlockCacheCreate()                */
+/************************************************************************/
+
+GDALAbstractBandBlockCache* GDALHashSetBandBlockCacheCreate(GDALRasterBand* poBand)
+{
+    return new GDALHashSetBandBlockCache(poBand);
+}
+
+/************************************************************************/
+/*                      GDALRasterBlockHashFunc()                       */
+/************************************************************************/
+
+/* calculate hash value */
+static unsigned long GDALRasterBlockHashFunc( const void * const elt )
+{
+    const GDALRasterBlock * const poBlock =
+        static_cast<const GDALRasterBlock * const>(elt);
+#if SIZEOF_UNSIGNED_LONG == 8
+    return static_cast<unsigned long>(
+        poBlock->GetXOff() | (((unsigned long)poBlock->GetYOff()) << 32));
+#else
+    return static_cast<unsigned long>(
+        ((poBlock->GetXOff() & 0xFFFF) ^ (poBlock->GetYOff() >> 16)) |
+        (((poBlock->GetYOff() & 0xFFFF) ^ (poBlock->GetXOff() >> 16)) << 16));
+#endif
+}
+
+/************************************************************************/
+/*                      GDALRasterBlockEqualFunc()                      */
+/************************************************************************/
+
+/* test equality */
+static int GDALRasterBlockEqualFunc( const void * const elt1,
+                                     const void * const elt2 )
+{
+    const GDALRasterBlock * const poBlock1 =
+        static_cast<const GDALRasterBlock * const>(elt1);
+    const GDALRasterBlock * const poBlock2 =
+        static_cast<const GDALRasterBlock * const >(elt2);
+    return poBlock1->GetXOff() == poBlock2->GetXOff() &&
+           poBlock1->GetYOff() == poBlock2->GetYOff();
+}
+
+/************************************************************************/
+/*                       GDALHashSetBandBlockCache()                    */
+/************************************************************************/
+
+GDALHashSetBandBlockCache::GDALHashSetBandBlockCache(GDALRasterBand* poBandIn) :
+    GDALAbstractBandBlockCache(poBandIn),
+    hSet(CPLHashSetNew(GDALRasterBlockHashFunc, GDALRasterBlockEqualFunc, NULL)),
+    hLock(CPLCreateLock(LOCK_ADAPTIVE_MUTEX))
+{}
+
+/************************************************************************/
+/*                      ~GDALHashSetBandBlockCache()                    */
+/************************************************************************/
+
+GDALHashSetBandBlockCache::~GDALHashSetBandBlockCache()
+{
+    FlushCache();
+    CPLHashSetDestroy(hSet);
+    CPLDestroyLock(hLock);
+}
+
+/************************************************************************/
+/*                                  Init()                              */
+/************************************************************************/
+
+bool GDALHashSetBandBlockCache::Init()
+{
+    return true;
+}
+
+/************************************************************************/
+/*                             IsInitOK()                               */
+/************************************************************************/
+
+bool GDALHashSetBandBlockCache::IsInitOK()
+{
+    return true;
+}
+
+/************************************************************************/
+/*                            AdoptBlock()                              */
+/************************************************************************/
+
+CPLErr GDALHashSetBandBlockCache::AdoptBlock( GDALRasterBlock * poBlock )
+
+{
+    FreeDanglingBlocks();
+
+    CPLLockHolderOptionalLockD( hLock );
+    CPLHashSetInsert(hSet, poBlock);
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*              GDALHashSetBandBlockCacheFlushCacheIterFunc()           */
+/************************************************************************/
+
+static int GDALHashSetBandBlockCacheFlushCacheIterFunc(void* elt, void* user_data)
+{
+    std::vector<GDALRasterBlock*>* papoBlocks = (std::vector<GDALRasterBlock*>*)user_data;
+    GDALRasterBlock* poBlock = (GDALRasterBlock*) elt;
+    papoBlocks->push_back(poBlock);
+    return TRUE;
+}
+
+/************************************************************************/
+/*                  GDALHashSetBandBlockCacheSortBlocks()               */
+/************************************************************************/
+
+// TODO: Both args should be const.
+static bool GDALHashSetBandBlockCacheSortBlocks(GDALRasterBlock* poBlock1,
+                                                GDALRasterBlock* poBlock2)
+{
+    return poBlock1->GetYOff() < poBlock2->GetYOff() ||
+           ( poBlock1->GetYOff() == poBlock2->GetYOff() &&
+             poBlock1->GetXOff() < poBlock2->GetXOff() );
+}
+
+/************************************************************************/
+/*                            FlushCache()                              */
+/************************************************************************/
+
+CPLErr GDALHashSetBandBlockCache::FlushCache()
+{
+    FreeDanglingBlocks();
+
+    CPLErr eGlobalErr = poBand->eFlushBlockErr;
+
+    std::vector<GDALRasterBlock*> apoBlocks;
+    {
+        CPLLockHolderOptionalLockD( hLock );
+        CPLHashSetForeach(hSet,
+                          GDALHashSetBandBlockCacheFlushCacheIterFunc,
+                          &apoBlocks);
+
+        CPLHashSetClear(hSet);
+    }
+
+    // Sort blocks by increasing y and then x in order to please some tests
+    // like tiff_write_133
+    std::sort(apoBlocks.begin(), apoBlocks.end(), GDALHashSetBandBlockCacheSortBlocks);
+
+    for(size_t i=0;i<apoBlocks.size();i++)
+    {
+        GDALRasterBlock* poBlock = apoBlocks[i];
+
+        if( poBlock->DropLockForRemovalFromStorage() )
+        {
+            CPLErr    eErr = CE_None;
+
+            if( eGlobalErr == CE_None && poBlock->GetDirty() )
+                eErr = poBlock->Write();
+
+            delete poBlock;
+
+            if( eErr != CE_None )
+                eGlobalErr = eErr;
+        }
+    }
+
+    WaitKeepAliveCounter();
+
+    return( eGlobalErr );
+}
+
+/************************************************************************/
+/*                        UnreferenceBlock()                            */
+/************************************************************************/
+
+CPLErr GDALHashSetBandBlockCache::UnreferenceBlock( GDALRasterBlock* poBlock )
+{
+    UnreferenceBlockBase();
+
+    CPLLockHolderOptionalLockD( hLock );
+    CPLHashSetRemoveDeferRehash(hSet, poBlock);
+    return CE_None;
+}
+
+/************************************************************************/
+/*                            FlushBlock()                              */
+/************************************************************************/
+
+CPLErr GDALHashSetBandBlockCache::FlushBlock( int nXBlockOff, int nYBlockOff,
+                                              int bWriteDirtyBlock )
+
+{
+    GDALRasterBlock oBlockForLookup(nXBlockOff, nYBlockOff);
+    GDALRasterBlock* poBlock = NULL;
+    {
+        CPLLockHolderOptionalLockD( hLock );
+        poBlock = reinterpret_cast<GDALRasterBlock*>(
+            CPLHashSetLookup(hSet, &oBlockForLookup) );
+        if( poBlock == NULL )
+            return CE_None;
+        CPLHashSetRemove(hSet, poBlock);
+    }
+
+    if( !poBlock->DropLockForRemovalFromStorage() )
+        return CE_None;
+
+    CPLErr eErr = CE_None;
+
+    if( bWriteDirtyBlock && poBlock->GetDirty() )
+        eErr = poBlock->Write();
+
+    delete poBlock;
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                        TryGetLockedBlockRef()                        */
+/************************************************************************/
+
+GDALRasterBlock *GDALHashSetBandBlockCache::TryGetLockedBlockRef( int nXBlockOff,
+                                                                  int nYBlockOff )
+
+{
+    GDALRasterBlock oBlockForLookup(nXBlockOff, nYBlockOff);
+    GDALRasterBlock* poBlock = NULL;
+    while( true )
+    {
+        {
+            CPLLockHolderOptionalLockD( hLock );
+            poBlock = reinterpret_cast<GDALRasterBlock*>(
+                CPLHashSetLookup(hSet, &oBlockForLookup) );
+        }
+        if( poBlock == NULL )
+            return NULL;
+        if( poBlock->TakeLock()  )
+            break;
+    }
+
+    poBlock->Touch();
+    return poBlock;
+}
diff --git a/gcore/gdaljp2abstractdataset.cpp b/gcore/gdaljp2abstractdataset.cpp
index 8f8ba33..d50e6f4 100644
--- a/gcore/gdaljp2abstractdataset.cpp
+++ b/gcore/gdaljp2abstractdataset.cpp
@@ -1,7 +1,7 @@
 /******************************************************************************
- * $Id: gdaljp2abstractdataset.cpp 29131 2015-05-03 14:47:58Z rouault $
+ * $Id: gdaljp2abstractdataset.cpp 33694 2016-03-10 17:54:30Z goatbar $
  *
- * Project:  GDAL 
+ * Project:  GDAL
  * Purpose:  GDALGeorefPamDataset with helper to read georeferencing and other
  *           metadata from JP2Boxes
  * Author:   Even Rouault <even dot rouault at mines-paris dot org>
@@ -77,26 +77,26 @@ int GDALJP2AbstractDataset::CloseDependentDatasets()
 /************************************************************************/
 
 void GDALJP2AbstractDataset::LoadJP2Metadata(GDALOpenInfo* poOpenInfo,
-                                             const char* pszOverideFilenameIn)
+                                             const char* pszOverrideFilenameIn)
 {
-    const char* pszOverideFilename = pszOverideFilenameIn;
-    if( pszOverideFilename == NULL )
-        pszOverideFilename = poOpenInfo->pszFilename;
+    const char* pszOverrideFilename = pszOverrideFilenameIn;
+    if( pszOverrideFilename == NULL )
+        pszOverrideFilename = poOpenInfo->pszFilename;
 
 /* -------------------------------------------------------------------- */
 /*      Check for georeferencing information.                           */
 /* -------------------------------------------------------------------- */
     GDALJP2Metadata oJP2Geo;
 
-    if( (poOpenInfo->fpL != NULL && pszOverideFilenameIn == NULL &&
+    if( (poOpenInfo->fpL != NULL && pszOverrideFilenameIn == NULL &&
          oJP2Geo.ReadAndParse(poOpenInfo->fpL) ) ||
-        (!(poOpenInfo->fpL != NULL && pszOverideFilenameIn == NULL) &&
-         oJP2Geo.ReadAndParse( pszOverideFilename )) )
+        (!(poOpenInfo->fpL != NULL && pszOverrideFilenameIn == NULL) &&
+         oJP2Geo.ReadAndParse( pszOverrideFilename )) )
     {
         CPLFree(pszProjection);
         pszProjection = CPLStrdup(oJP2Geo.pszProjection);
-        bGeoTransformValid = oJP2Geo.bHaveGeoTransform;
-        memcpy( adfGeoTransform, oJP2Geo.adfGeoTransform, 
+        bGeoTransformValid = CPL_TO_BOOL( oJP2Geo.bHaveGeoTransform );
+        memcpy( adfGeoTransform, oJP2Geo.adfGeoTransform,
                 sizeof(double) * 6 );
         nGCPCount = oJP2Geo.nGCPCount;
         pasGCPList =
@@ -126,14 +126,14 @@ void GDALJP2AbstractDataset::LoadJP2Metadata(GDALOpenInfo* poOpenInfo,
 /* -------------------------------------------------------------------- */
     int iBox;
 
-    for( iBox = 0; 
+    for( iBox = 0;
             oJP2Geo.papszGMLMetadata
-                && oJP2Geo.papszGMLMetadata[iBox] != NULL; 
+                && oJP2Geo.papszGMLMetadata[iBox] != NULL;
             iBox++ )
     {
         char *pszName = NULL;
-        const char *pszXML = 
-            CPLParseNameValue( oJP2Geo.papszGMLMetadata[iBox], 
+        const char *pszXML =
+            CPLParseNameValue( oJP2Geo.papszGMLMetadata[iBox],
                                 &pszName );
         CPLString osDomain;
         char *apszMDList[2];
@@ -209,10 +209,10 @@ void GDALJP2AbstractDataset::LoadJP2Metadata(GDALOpenInfo* poOpenInfo,
     if( !bGeoTransformValid )
     {
         bGeoTransformValid |=
-            GDALReadWorldFile2( pszOverideFilename, NULL,
+            GDALReadWorldFile2( pszOverrideFilename, NULL,
                                 adfGeoTransform,
                                 poOpenInfo->GetSiblingFiles(), &pszWldFilename )
-            || GDALReadWorldFile2( pszOverideFilename, ".wld",
+            || GDALReadWorldFile2( pszOverrideFilename, ".wld",
                                    adfGeoTransform,
                                    poOpenInfo->GetSiblingFiles(), &pszWldFilename );
     }
@@ -304,8 +304,7 @@ void GDALJP2AbstractDataset::LoadVectorLayers(int bOpenRemoteResources)
             CPLXMLNode* psChild = psGCorGMLJP2FeaturesChildIter->psChild;
             if( psChild->eType == CXT_Attribute &&
                 strcmp(psChild->pszValue, "xlink:href") == 0 &&
-                strncmp(psChild->psChild->pszValue,
-                        "gmljp2://xml/", strlen("gmljp2://xml/")) == 0 )
+                STARTS_WITH(psChild->psChild->pszValue, "gmljp2://xml/") )
             {
                 const char* pszBoxName = psChild->psChild->pszValue + strlen("gmljp2://xml/");
                 char** papszBoxData = GetMetadata(CPLSPrintf("xml:%s", pszBoxName));
@@ -323,11 +322,13 @@ void GDALJP2AbstractDataset::LoadVectorLayers(int bOpenRemoteResources)
             }
             if( psChild->eType == CXT_Attribute &&
                 strcmp(psChild->pszValue, "xlink:href") == 0 &&
-                (strncmp(psChild->psChild->pszValue, "http://", strlen("http://")) == 0 ||
-                 strncmp(psChild->psChild->pszValue, "https://", strlen("https://")) == 0) )
+                (STARTS_WITH(psChild->psChild->pszValue, "http://") ||
+                 STARTS_WITH(psChild->psChild->pszValue, "https://")) )
             {
                 if( !bOpenRemoteResources )
-                    CPLDebug("GMLJP2", "Remote feature collection %s mentionned in GMLJP2 box",
+                    CPLDebug("GMLJP2",
+                             "Remote feature collection %s mentioned in "
+                             "GMLJP2 box",
                              psChild->psChild->pszValue);
                 else
                     osGMLTmpFile = "/vsicurl/" + CPLString(psChild->psChild->pszValue);
@@ -359,24 +360,24 @@ void GDALJP2AbstractDataset::LoadVectorLayers(int bOpenRemoteResources)
                 if( pszSchemaLocation )
                 {
                     char **papszTokens = CSLTokenizeString2(
-                            pszSchemaLocation, " \t\n", 
+                            pszSchemaLocation, " \t\n",
                             CSLT_HONOURSTRINGS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES);
 
                     if( (CSLCount(papszTokens) % 2) == 0 )
                     {
                         for(char** papszIter = papszTokens; *papszIter; papszIter += 2 )
                         {
-                            if( strncmp(papszIter[1], "gmljp2://xml/", strlen("gmljp2://xml/")) == 0 )
+                            if( STARTS_WITH(papszIter[1], "gmljp2://xml/") )
                             {
                                 const char* pszBoxName = papszIter[1] + strlen("gmljp2://xml/");
                                 char** papszBoxData = GetMetadata(CPLSPrintf("xml:%s", pszBoxName));
                                 if( papszBoxData != NULL )
                                 {
                                     osXSDTmpFile = CPLSPrintf("/vsimem/gmljp2/%p/my.xsd", this);
-                                    VSIFCloseL(VSIFileFromMemBuffer(osXSDTmpFile,
+                                    CPL_IGNORE_RET_VAL(VSIFCloseL(VSIFileFromMemBuffer(osXSDTmpFile,
                                                                     (GByte*)papszBoxData[0],
                                                                     strlen(papszBoxData[0]),
-                                                                    FALSE));
+                                                                    FALSE)));
                                 }
                                 else
                                 {
@@ -434,7 +435,7 @@ void GDALJP2AbstractDataset::LoadVectorLayers(int bOpenRemoteResources)
                 CPLDebug("GMLJP2", "No GML driver found to read feature collection");
             }
 
-            if( strncmp(osGMLTmpFile, "/vsicurl/", strlen("/vsicurl/")) != 0 )
+            if( !STARTS_WITH(osGMLTmpFile, "/vsicurl/") )
                 VSIUnlink(osGMLTmpFile);
             if( osXSDTmpFile.size() )
                 VSIUnlink(osXSDTmpFile);
diff --git a/gcore/gdaljp2abstractdataset.h b/gcore/gdaljp2abstractdataset.h
index e1593fc..aea9600 100644
--- a/gcore/gdaljp2abstractdataset.h
+++ b/gcore/gdaljp2abstractdataset.h
@@ -1,7 +1,7 @@
 /******************************************************************************
- * $Id: gdaljp2abstractdataset.h 29131 2015-05-03 14:47:58Z rouault $
+ * $Id: gdaljp2abstractdataset.h 33794 2016-03-26 13:19:07Z goatbar $
  *
- * Project:  GDAL 
+ * Project:  GDAL
  * Purpose:  GDALGeorefPamDataset with helper to read georeferencing and other
  *           metadata from JP2Boxes
  * Author:   Even Rouault <even dot rouault at mines-paris dot org>
@@ -45,10 +45,10 @@ class CPL_DLL GDALJP2AbstractDataset: public GDALGeorefPamDataset
 
   public:
         GDALJP2AbstractDataset();
-        ~GDALJP2AbstractDataset();
+        virtual ~GDALJP2AbstractDataset();
 
         void LoadJP2Metadata(GDALOpenInfo* poOpenInfo,
-                             const char* pszOverideFilename = NULL);
+                             const char* pszOverrideFilename = NULL);
         void            LoadVectorLayers(int bOpenRemoteResources = FALSE);
 
         virtual char      **GetFileList(void);
diff --git a/gcore/gdaljp2box.cpp b/gcore/gdaljp2box.cpp
index 47dd66a..3fb9d68 100644
--- a/gcore/gdaljp2box.cpp
+++ b/gcore/gdaljp2box.cpp
@@ -1,7 +1,7 @@
 /******************************************************************************
- * $Id: gdaljp2box.cpp 28691 2015-03-08 20:07:02Z rouault $
+ * $Id: gdaljp2box.cpp 33550 2016-02-25 12:47:15Z goatbar $
  *
- * Project:  GDAL 
+ * Project:  GDAL
  * Purpose:  GDALJP2Box Implementation - Low level JP2 box reader.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -28,25 +28,23 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdaljp2metadata.h"
 #include "cpl_string.h"
+#include "gdaljp2metadata.h"
 
-CPL_CVSID("$Id: gdaljp2box.cpp 28691 2015-03-08 20:07:02Z rouault $");
+CPL_CVSID("$Id: gdaljp2box.cpp 33550 2016-02-25 12:47:15Z goatbar $");
 
 /************************************************************************/
 /*                             GDALJP2Box()                             */
 /************************************************************************/
 
-GDALJP2Box::GDALJP2Box( VSILFILE *fpIn )
-
+GDALJP2Box::GDALJP2Box( VSILFILE *fpIn ) :
+    fpVSIL(fpIn),
+    nBoxOffset(-1),
+    nBoxLength(0),
+    nDataOffset(-1),
+    pabyData(NULL)
 {
-    fpVSIL = fpIn;
     szBoxType[0] = '\0';
-    nBoxOffset = -1;
-    nDataOffset = -1;
-    nBoxLength = 0;
-    
-    pabyData = NULL;
 }
 
 /************************************************************************/
@@ -56,6 +54,7 @@ GDALJP2Box::GDALJP2Box( VSILFILE *fpIn )
 GDALJP2Box::~GDALJP2Box()
 
 {
+    // TODO(schwher): Need to close fpVSIL?
     CPLFree( pabyData );
 }
 
@@ -63,7 +62,7 @@ GDALJP2Box::~GDALJP2Box()
 /*                             SetOffset()                              */
 /************************************************************************/
 
-int  GDALJP2Box::SetOffset( GIntBig nNewOffset )
+int GDALJP2Box::SetOffset( GIntBig nNewOffset )
 
 {
     szBoxType[0] = '\0';
@@ -136,8 +135,8 @@ int GDALJP2Box::ReadNextChild( GDALJP2Box *poSuperBox )
 int GDALJP2Box::ReadBox()
 
 {
-    GUInt32   nLBox;
-    GUInt32   nTBox;
+    GUInt32 nLBox = 0;
+    GUInt32 nTBox = 0;
 
     nBoxOffset = VSIFTellL( fpVSIL );
 
@@ -159,11 +158,10 @@ int GDALJP2Box::ReadBox()
     }
     else
     {
-        GByte abyXLBox[8];
+        GByte abyXLBox[8] = { 0 };
         if( VSIFReadL( abyXLBox, 8, 1, fpVSIL ) != 1 )
             return FALSE;
 
-        
         if( sizeof(nBoxLength) == 8 )
         {
             CPL_MSBPTR64( abyXLBox );
@@ -174,15 +172,21 @@ int GDALJP2Box::ReadBox()
             CPL_MSBPTR32( abyXLBox+4 );
             memcpy( &nBoxLength, abyXLBox+4, 4 );
         }
-
+        if( nBoxLength < 0 )
+        {
+            CPLDebug("GDALJP2", "Invalid length for box %s", szBoxType);
+            return FALSE;
+        }
         nDataOffset = nBoxOffset + 16;
     }
 
     if( nBoxLength == 0 )
     {
-        VSIFSeekL( fpVSIL, 0, SEEK_END );
+        if( VSIFSeekL( fpVSIL, 0, SEEK_END ) != 0 )
+            return FALSE;
         nBoxLength = VSIFTellL( fpVSIL ) - nBoxOffset;
-        VSIFSeekL( fpVSIL, nDataOffset, SEEK_SET );
+        if( VSIFSeekL( fpVSIL, nDataOffset, SEEK_SET ) != 0 )
+            return FALSE;
     }
 
     if( EQUAL(szBoxType,"uuid") )
@@ -211,8 +215,8 @@ int GDALJP2Box::IsSuperBox()
     if( EQUAL(GetType(),"asoc") || EQUAL(GetType(),"jp2h")
         || EQUAL(GetType(),"res ") )
         return TRUE;
-    else
-        return FALSE;
+
+    return FALSE;
 }
 
 /************************************************************************/
@@ -222,23 +226,35 @@ int GDALJP2Box::IsSuperBox()
 GByte *GDALJP2Box::ReadBoxData()
 
 {
-    if( GetDataLength() > 100 * 1024 * 1024 )
-        return FALSE;
+    GIntBig nDataLength = GetDataLength();
+    if( nDataLength > 100 * 1024 * 1024 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Too big box : " CPL_FRMT_GIB " bytes",
+                  nDataLength );
+        return NULL;
+    }
+
+    if( VSIFSeekL( fpVSIL, nDataOffset, SEEK_SET ) != 0 )
+        return NULL;
 
-    VSIFSeekL( fpVSIL, nDataOffset, SEEK_SET );
-    
-    char *pszData = (char *) CPLMalloc((int)GetDataLength() + 1);
+    char *pszData = static_cast<char *>(
+        VSI_MALLOC_VERBOSE( static_cast<int>(nDataLength) + 1) );
+    if( pszData == NULL )
+        return NULL;
 
-    if( (GIntBig) VSIFReadL( pszData, 1, (int)GetDataLength(), fpVSIL ) 
-        != GetDataLength() )
+    if( static_cast<GIntBig>( VSIFReadL(
+           pszData, 1, static_cast<int>(nDataLength), fpVSIL ) )
+        != nDataLength )
     {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot read box content");
         CPLFree( pszData );
         return NULL;
     }
 
-    pszData[GetDataLength()] = '\0';
+    pszData[nDataLength] = '\0';
 
-    return (GByte *) pszData;
+    return reinterpret_cast<GByte *>( pszData );
 }
 
 /************************************************************************/
@@ -260,12 +276,13 @@ int GDALJP2Box::DumpReadable( FILE *fpOut, int nIndentLevel )
     if( fpOut == NULL )
         fpOut = stdout;
 
-    int i;
-    for(i=0;i<nIndentLevel;i++)
+    for( int i=0; i < nIndentLevel; i++)
         fprintf( fpOut, "  " );
 
-    fprintf( fpOut, "  Type=%s, Offset=" CPL_FRMT_GIB "/" CPL_FRMT_GIB", Data Size=" CPL_FRMT_GIB,
-             szBoxType, nBoxOffset, nDataOffset, 
+    fprintf( fpOut,
+             "  Type=%s, Offset=" CPL_FRMT_GIB "/" CPL_FRMT_GIB
+             ", Data Size=" CPL_FRMT_GIB,
+             szBoxType, nBoxOffset, nDataOffset,
              GetDataLength() );
 
     if( IsSuperBox() )
@@ -274,8 +291,8 @@ int GDALJP2Box::DumpReadable( FILE *fpOut, int nIndentLevel )
     }
 
     fprintf( fpOut, "\n" );
-    
-    if( IsSuperBox() ) 
+
+    if( IsSuperBox() )
     {
         GDALJP2Box oSubBox( GetFILE() );
 
@@ -290,7 +307,7 @@ int GDALJP2Box::DumpReadable( FILE *fpOut, int nIndentLevel )
     if( EQUAL(GetType(),"uuid") )
     {
         char *pszHex = CPLBinaryToHex( 16, GetUUID() );
-        for(i=0;i<nIndentLevel;i++)
+        for( int i=0; i < nIndentLevel; i++ )
             fprintf( fpOut, "  " );
 
         fprintf( fpOut, "    UUID=%s", pszHex );
@@ -330,13 +347,13 @@ void GDALJP2Box::SetWritableData( int nLength, const GByte *pabyDataIn )
 
 {
     CPLFree( pabyData );
-    
+
     pabyData = (GByte *) CPLMalloc(nLength);
     memcpy( pabyData, pabyDataIn, nLength );
 
     nBoxOffset = -9; // virtual offsets for data length computation.
     nDataOffset = -1;
-    
+
     nBoxLength = 8 + nLength;
 }
 
@@ -354,7 +371,8 @@ void GDALJP2Box::AppendWritableData( int nLength, const void *pabyDataIn )
         nBoxLength = 8;
     }
 
-    pabyData = (GByte *) CPLRealloc(pabyData, GetDataLength() + nLength);
+    pabyData = static_cast<GByte *>(
+        CPLRealloc(pabyData, static_cast<size_t>(GetDataLength() + nLength)) );
     memcpy( pabyData + GetDataLength(), pabyDataIn, nLength );
 
     nBoxLength += nLength;
@@ -392,17 +410,15 @@ void GDALJP2Box::AppendUInt8( GByte nVal )
 /*                           CreateUUIDBox()                            */
 /************************************************************************/
 
-GDALJP2Box *GDALJP2Box::CreateUUIDBox( 
-    const GByte *pabyUUID, int nDataSize, const GByte *pabyData )
+GDALJP2Box *GDALJP2Box::CreateUUIDBox(
+    const GByte *pabyUUID, int nDataSize, const GByte *pabyDataIn )
 
 {
-    GDALJP2Box *poBox;
-
-    poBox = new GDALJP2Box();
+    GDALJP2Box *poBox = new GDALJP2Box();
     poBox->SetType( "uuid" );
 
     poBox->AppendWritableData( 16, pabyUUID );
-    poBox->AppendWritableData( nDataSize, pabyData );
+    poBox->AppendWritableData( nDataSize, pabyDataIn );
 
     return poBox;
 }
@@ -424,36 +440,35 @@ GDALJP2Box *GDALJP2Box::CreateAsocBox( int nCount, GDALJP2Box **papoBoxes )
 GDALJP2Box *GDALJP2Box::CreateSuperBox( const char* pszType,
                                         int nCount, GDALJP2Box **papoBoxes )
 {
-    int nDataSize=0, iBox;
-    GByte *pabyCompositeData, *pabyNext;
+    int nDataSize=0;
 
 /* -------------------------------------------------------------------- */
 /*      Compute size of data area of asoc box.                          */
 /* -------------------------------------------------------------------- */
-    for( iBox = 0; iBox < nCount; iBox++ )
-        nDataSize += 8 + (int) papoBoxes[iBox]->GetDataLength();
+    for( int iBox = 0; iBox < nCount; iBox++ )
+        nDataSize += 8 + static_cast<int>( papoBoxes[iBox]->GetDataLength() );
 
-    pabyNext = pabyCompositeData = (GByte *) CPLMalloc(nDataSize);
+    GByte *pabyNext = static_cast<GByte *>( CPLMalloc(nDataSize) );
+    GByte *pabyCompositeData = pabyNext;
 
 /* -------------------------------------------------------------------- */
 /*      Copy subboxes headers and data into buffer.                     */
 /* -------------------------------------------------------------------- */
-    for( iBox = 0; iBox < nCount; iBox++ )
+    for( int iBox = 0; iBox < nCount; iBox++ )
     {
-        GUInt32   nLBox;
-
-        nLBox = CPL_MSBWORD32(papoBoxes[iBox]->nBoxLength);
+        GUInt32   nLBox = CPL_MSBWORD32(
+            static_cast<GUInt32>(papoBoxes[iBox]->nBoxLength));
         memcpy( pabyNext, &nLBox, 4 );
         pabyNext += 4;
 
         memcpy( pabyNext, papoBoxes[iBox]->szBoxType, 4 );
         pabyNext += 4;
 
-        memcpy( pabyNext, papoBoxes[iBox]->pabyData, 
+        memcpy( pabyNext, papoBoxes[iBox]->pabyData,
                 (int) papoBoxes[iBox]->GetDataLength() );
         pabyNext += papoBoxes[iBox]->GetDataLength();
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create asoc box.                                                */
 /* -------------------------------------------------------------------- */
@@ -461,7 +476,7 @@ GDALJP2Box *GDALJP2Box::CreateSuperBox( const char* pszType,
 
     poAsoc->SetType( pszType );
     poAsoc->SetWritableData( nDataSize, pabyCompositeData );
-    
+
     CPLFree( pabyCompositeData );
 
     return poAsoc;
@@ -474,11 +489,10 @@ GDALJP2Box *GDALJP2Box::CreateSuperBox( const char* pszType,
 GDALJP2Box *GDALJP2Box::CreateLblBox( const char *pszLabel )
 
 {
-    GDALJP2Box *poBox;
-
-    poBox = new GDALJP2Box();
+    GDALJP2Box *poBox = new GDALJP2Box();
     poBox->SetType( "lbl " );
-    poBox->SetWritableData( strlen(pszLabel)+1, (const GByte *) pszLabel );
+    poBox->SetWritableData( static_cast<int>(strlen(pszLabel)+1),
+                            reinterpret_cast<const GByte *>( pszLabel ) );
 
     return poBox;
 }
@@ -491,17 +505,17 @@ GDALJP2Box *GDALJP2Box::CreateLabelledXMLAssoc( const char *pszLabel,
                                                 const char *pszXML )
 
 {
-    GDALJP2Box oLabel, oXML;
-    GDALJP2Box *aoList[2];
-
+    GDALJP2Box oLabel;
     oLabel.SetType( "lbl " );
-    oLabel.SetWritableData( strlen(pszLabel)+1, (const GByte *) pszLabel );
+    oLabel.SetWritableData( static_cast<int>(strlen(pszLabel)+1),
+                            reinterpret_cast<const GByte *>(pszLabel) );
 
+    GDALJP2Box oXML;
     oXML.SetType( "xml " );
-    oXML.SetWritableData( strlen(pszXML)+1, (const GByte *) pszXML );
+    oXML.SetWritableData( static_cast<int>(strlen(pszXML)+1),
+                          reinterpret_cast<const GByte *>(pszXML) );
+
+    GDALJP2Box *aoList[2] = { &oLabel, &oXML };
 
-    aoList[0] = &oLabel;
-    aoList[1] = &oXML;
-    
     return CreateAsocBox( 2, aoList );
 }
diff --git a/gcore/gdaljp2metadata.cpp b/gcore/gdaljp2metadata.cpp
index 9a82ded..adcff7a 100644
--- a/gcore/gdaljp2metadata.cpp
+++ b/gcore/gdaljp2metadata.cpp
@@ -1,7 +1,7 @@
 /******************************************************************************
- * $Id: gdaljp2metadata.cpp 29330 2015-06-14 12:11:11Z rouault $
+ * $Id: gdaljp2metadata.cpp 33579 2016-02-26 23:55:40Z goatbar $
  *
- * Project:  GDAL 
+ * Project:  GDAL
  * Purpose:  GDALJP2Metadata - Read GeoTIFF and/or GML georef info.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *           Even Rouault <even dot rouault at spatialys dot com>
@@ -30,29 +30,29 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdaljp2metadata.h"
 #include "cpl_string.h"
 #include "cpl_minixml.h"
-#include "ogr_spatialref.h"
-#include "ogr_geometry.h"
-#include "ogr_api.h"
 #include "gt_wkt_srs_for_gdal.h"
-#include "json.h"
+#include "gdaljp2metadata.h"
 #include "gdaljp2metadatagenerator.h"
+#include "json.h"
+#include "ogr_api.h"
+#include "ogr_geometry.h"
+#include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: gdaljp2metadata.cpp 29330 2015-06-14 12:11:11Z rouault $");
+CPL_CVSID("$Id: gdaljp2metadata.cpp 33579 2016-02-26 23:55:40Z goatbar $");
 
-static const unsigned char msi_uuid2[16] =
-{0xb1,0x4b,0xf8,0xbd,0x08,0x3d,0x4b,0x43,
- 0xa5,0xae,0x8c,0xd7,0xd5,0xa6,0xce,0x03}; 
+static const unsigned char msi_uuid2[16] = {
+    0xb1,0x4b,0xf8,0xbd,0x08,0x3d,0x4b,0x43,
+    0xa5,0xae,0x8c,0xd7,0xd5,0xa6,0xce,0x03 };
 
-static const unsigned char msig_uuid[16] = 
-{ 0x96,0xA9,0xF1,0xF1,0xDC,0x98,0x40,0x2D,
-  0xA7,0xAE,0xD6,0x8E,0x34,0x45,0x18,0x09 };
+static const unsigned char msig_uuid[16] = {
+    0x96,0xA9,0xF1,0xF1,0xDC,0x98,0x40,0x2D,
+    0xA7,0xAE,0xD6,0x8E,0x34,0x45,0x18,0x09 };
 
-static const unsigned char xmp_uuid[16] =
-{ 0xBE,0x7A,0xCF,0xCB,0x97,0xA9,0x42,0xE8,
-  0x9C,0x71,0x99,0x94,0x91,0xE3,0xAF,0xAC};
+static const unsigned char xmp_uuid[16] = {
+    0xBE,0x7A,0xCF,0xCB,0x97,0xA9,0x42,0xE8,
+    0x9C,0x71,0x99,0x94,0x91,0xE3,0xAF,0xAC };
 
 struct _GDALJP2GeoTIFFBox
 {
@@ -60,43 +60,35 @@ struct _GDALJP2GeoTIFFBox
     GByte  *pabyGeoTIFFData;
 };
 
-#define MAX_JP2GEOTIFF_BOXES 2
+static const int MAX_JP2GEOTIFF_BOXES = 2;
 
 /************************************************************************/
 /*                          GDALJP2Metadata()                           */
 /************************************************************************/
 
-GDALJP2Metadata::GDALJP2Metadata()
-
+GDALJP2Metadata::GDALJP2Metadata() :
+    nGeoTIFFBoxesCount(0),
+    pasGeoTIFFBoxes(NULL),
+    nMSIGSize(0),
+    pabyMSIGData(NULL),
+    papszGMLMetadata(NULL),
+    bHaveGeoTransform (FALSE),
+    bPixelIsPoint(FALSE),
+    pszProjection(NULL),
+    nGCPCount(0),
+    pasGCPList(NULL),
+    papszRPCMD(NULL),
+    papszMetadata(NULL),
+    pszXMPMetadata(NULL),
+    pszGDALMultiDomainMetadata(NULL),
+    pszXMLIPR(NULL)
 {
-    pszProjection = NULL;
-
-    nGCPCount = 0;
-    pasGCPList = NULL;
-
-    papszRPCMD = NULL;
-
-    papszGMLMetadata = NULL;
-    papszMetadata = NULL;
-
-    nGeoTIFFBoxesCount = 0;
-    pasGeoTIFFBoxes = NULL;
-
-    nMSIGSize = 0;
-    pabyMSIGData = NULL;
-
-    pszXMPMetadata = NULL;
-    pszGDALMultiDomainMetadata = NULL;
-    pszXMLIPR = NULL;
-
-    bHaveGeoTransform = FALSE;
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
-    bPixelIsPoint = FALSE;
 }
 
 /************************************************************************/
@@ -139,19 +131,19 @@ int GDALJP2Metadata::ReadAndParse( const char *pszFilename )
 
 {
     VSILFILE *fpLL;
-        
+
     fpLL = VSIFOpenL( pszFilename, "rb" );
-        
+
     if( fpLL == NULL )
     {
-        CPLDebug( "GDALJP2Metadata", "Could not even open %s.", 
+        CPLDebug( "GDALJP2Metadata", "Could not even open %s.",
                   pszFilename );
 
         return FALSE;
     }
 
     int bRet = ReadAndParse( fpLL );
-    VSIFCloseL( fpLL );
+    CPL_IGNORE_RET_VAL(VSIFCloseL( fpLL ));
 
 /* -------------------------------------------------------------------- */
 /*      If we still don't have a geotransform, look for a world         */
@@ -159,7 +151,7 @@ int GDALJP2Metadata::ReadAndParse( const char *pszFilename )
 /* -------------------------------------------------------------------- */
     if( !bHaveGeoTransform )
     {
-        bHaveGeoTransform = 
+        bHaveGeoTransform =
             GDALReadWorldFile( pszFilename, NULL, adfGeoTransform )
             || GDALReadWorldFile( pszFilename, ".wld", adfGeoTransform );
         bRet |= bHaveGeoTransform;
@@ -185,7 +177,7 @@ int GDALJP2Metadata::ReadAndParse( VSILFILE *fpLL )
 /*      or gcps.                                                        */
 /* -------------------------------------------------------------------- */
     return bHaveGeoTransform
-        || nGCPCount > 0 
+        || nGCPCount > 0
         || (pszProjection != NULL && strlen(pszProjection) > 0)
         || papszRPCMD != NULL;
 }
@@ -216,7 +208,7 @@ void GDALJP2Metadata::CollectGMLData( GDALJP2Box *poGMLData )
 
             if( !oSubChildBox.ReadFirstChild( &oChildBox ) )
                 break;
-            
+
             while( strlen(oSubChildBox.GetType()) > 0 )
             {
                 if( EQUAL(oSubChildBox.GetType(),"lbl ") )
@@ -224,13 +216,14 @@ void GDALJP2Metadata::CollectGMLData( GDALJP2Box *poGMLData )
                 else if( EQUAL(oSubChildBox.GetType(),"xml ") )
                 {
                     pszXML = (char *) oSubChildBox.ReadBoxData();
+                    GIntBig nXMLLength = oSubChildBox.GetDataLength();
 
                     // Some GML data contains \0 instead of \n !
                     // See http://trac.osgeo.org/gdal/ticket/5760
-                    if( pszXML )
+                    if( pszXML != NULL && nXMLLength < 100 * 1024 * 1024 )
                     {
-                        int nXMLLength = (int)oSubChildBox.GetDataLength();
-                        int i;
+                        GIntBig i;
+                        /* coverity[tainted_data] */
                         for(i=nXMLLength-1; i >= 0; i--)
                         {
                             if( pszXML[i] == '\0' )
@@ -238,6 +231,7 @@ void GDALJP2Metadata::CollectGMLData( GDALJP2Box *poGMLData )
                             else
                                 break;
                         }
+                        /* coverity[tainted_data] */
                         for(i=0;i<nXMLLength;i++)
                         {
                             if( pszXML[i] == '\0' )
@@ -251,7 +245,8 @@ void GDALJP2Metadata::CollectGMLData( GDALJP2Box *poGMLData )
                             if( psNode == NULL )
                             {
                                 CPLDebug("GMLJP2", "GMLJP2 data contains nul characters inside content. Replacing them by \\n");
-                                for(int i=0;i<nXMLLength;i++)
+                                /* coverity[tainted_data] */
+                                for(i=0;i<nXMLLength;i++)
                                 {
                                     if( pszXML[i] == '\0' )
                                         pszXML[i] = '\n';
@@ -266,10 +261,10 @@ void GDALJP2Metadata::CollectGMLData( GDALJP2Box *poGMLData )
                 if( !oSubChildBox.ReadNextChild( &oChildBox ) )
                     break;
             }
-            
+
             if( pszLabel != NULL && pszXML != NULL )
             {
-                papszGMLMetadata = CSLSetNameValue( papszGMLMetadata, 
+                papszGMLMetadata = CSLSetNameValue( papszGMLMetadata,
                                                     pszLabel, pszXML );
 
                 if( strcmp(pszLabel, "gml.root-instance") == 0 &&
@@ -290,7 +285,7 @@ void GDALJP2Metadata::CollectGMLData( GDALJP2Box *poGMLData )
             CPLFree( pszLabel );
             CPLFree( pszXML );
         }
-        
+
         if( !oChildBox.ReadNextChild( poGMLData ) )
             break;
     }
@@ -312,14 +307,14 @@ int GDALJP2Metadata::ReadBoxes( VSILFILE *fpVSIL )
     while( strlen(oBox.GetType()) > 0 )
     {
 #ifdef DEBUG
-        if (CSLTestBoolean(CPLGetConfigOption("DUMP_JP2_BOXES", "NO")))
+        if (CPLTestBool(CPLGetConfigOption("DUMP_JP2_BOXES", "NO")))
             oBox.DumpReadable(stderr);
 #endif
 
 /* -------------------------------------------------------------------- */
 /*      Collect geotiff box.                                            */
 /* -------------------------------------------------------------------- */
-        if( EQUAL(oBox.GetType(),"uuid") 
+        if( EQUAL(oBox.GetType(),"uuid")
             && memcmp( oBox.GetUUID(), msi_uuid2, 16 ) == 0 )
         {
             /* Erdas JPEG2000 files can in some conditions contain 2 GeoTIFF */
@@ -352,7 +347,7 @@ int GDALJP2Metadata::ReadBoxes( VSILFILE *fpVSIL )
 /* -------------------------------------------------------------------- */
 /*      Collect MSIG box.                                               */
 /* -------------------------------------------------------------------- */
-        if( EQUAL(oBox.GetType(),"uuid") 
+        if( EQUAL(oBox.GetType(),"uuid")
             && memcmp( oBox.GetUUID(), msig_uuid, 16 ) == 0 )
         {
             if( nMSIGSize == 0 )
@@ -398,7 +393,7 @@ int GDALJP2Metadata::ReadBoxes( VSILFILE *fpVSIL )
         {
             GDALJP2Box oSubBox( fpVSIL );
 
-            if( oSubBox.ReadFirstChild( &oBox ) && 
+            if( oSubBox.ReadFirstChild( &oBox ) &&
                 EQUAL(oSubBox.GetType(),"lbl ") )
             {
                 char *pszLabel = (char *) oSubBox.ReadBoxData();
@@ -418,8 +413,7 @@ int GDALJP2Metadata::ReadBoxes( VSILFILE *fpVSIL )
             CPLString osBoxName;
 
             char *pszXML = (char *) oBox.ReadBoxData();
-            if( strncmp(pszXML, "<GDALMultiDomainMetadata>",
-                        strlen("<GDALMultiDomainMetadata>")) == 0 )
+            if( pszXML != NULL && STARTS_WITH(pszXML, "<GDALMultiDomainMetadata>") )
             {
                 if( pszGDALMultiDomainMetadata == NULL )
                 {
@@ -431,11 +425,11 @@ int GDALJP2Metadata::ReadBoxes( VSILFILE *fpVSIL )
                     CPLDebug("GDALJP2", "Too many GDAL metadata boxes. Ignoring this one");
                 }
             }
-            else
+            else if( pszXML != NULL )
             {
                 osBoxName.Printf( "BOX_%d", iBox++ );
 
-                papszGMLMetadata = CSLSetNameValue( papszGMLMetadata, 
+                papszGMLMetadata = CSLSetNameValue( papszGMLMetadata,
                                                     osBoxName, pszXML );
             }
             CPLFree( pszXML );
@@ -457,8 +451,8 @@ int GDALJP2Metadata::ReadBoxes( VSILFILE *fpVSIL )
                     GDALJP2Box oResBox( fpVSIL );
 
                     oResBox.ReadFirstChild( &oSubBox );
-                    
-                    // we will use either the resd or resc box, which ever
+
+                    // We will use either the resd or resc box, which ever
                     // happens to be first.  Should we prefer resd?
                     unsigned char *pabyResData = NULL;
                     if( oResBox.GetDataLength() == 10 &&
@@ -466,35 +460,35 @@ int GDALJP2Metadata::ReadBoxes( VSILFILE *fpVSIL )
                     {
                         int nVertNum, nVertDen, nVertExp;
                         int nHorzNum, nHorzDen, nHorzExp;
-                        
+
                         nVertNum = pabyResData[0] * 256 + pabyResData[1];
                         nVertDen = pabyResData[2] * 256 + pabyResData[3];
                         nHorzNum = pabyResData[4] * 256 + pabyResData[5];
                         nHorzDen = pabyResData[6] * 256 + pabyResData[7];
                         nVertExp = pabyResData[8];
                         nHorzExp = pabyResData[9];
-                        
-                        // compute in pixels/cm 
-                        double dfVertRes = 
+
+                        // compute in pixels/cm
+                        double dfVertRes =
                             (nVertNum/(double)nVertDen) * pow(10.0,nVertExp)/100;
-                        double dfHorzRes = 
+                        double dfHorzRes =
                             (nHorzNum/(double)nHorzDen) * pow(10.0,nHorzExp)/100;
                         CPLString osFormatter;
 
-                        papszMetadata = CSLSetNameValue( 
-                            papszMetadata, 
+                        papszMetadata = CSLSetNameValue(
+                            papszMetadata,
                             "TIFFTAG_XRESOLUTION",
                             osFormatter.Printf("%g",dfHorzRes) );
-                        
-                        papszMetadata = CSLSetNameValue( 
-                            papszMetadata, 
+
+                        papszMetadata = CSLSetNameValue(
+                            papszMetadata,
                             "TIFFTAG_YRESOLUTION",
                             osFormatter.Printf("%g",dfVertRes) );
-                        papszMetadata = CSLSetNameValue( 
-                            papszMetadata, 
-                            "TIFFTAG_RESOLUTIONUNIT", 
+                        papszMetadata = CSLSetNameValue(
+                            papszMetadata,
+                            "TIFFTAG_RESOLUTIONUNIT",
                             "3 (pixels/cm)" );
-                        
+
                         CPLFree( pabyResData );
                     }
                 }
@@ -538,10 +532,10 @@ int GDALJP2Metadata::ReadBoxes( VSILFILE *fpVSIL )
 int GDALJP2Metadata::ParseJP2GeoTIFF()
 
 {
-    if(! CSLTestBoolean(CPLGetConfigOption("GDAL_USE_GEOJP2", "TRUE")) )
+    if(! CPLTestBool(CPLGetConfigOption("GDAL_USE_GEOJP2", "TRUE")) )
         return FALSE;
 
-    int abValidProjInfo[MAX_JP2GEOTIFF_BOXES] = { FALSE };
+    bool abValidProjInfo[MAX_JP2GEOTIFF_BOXES] = { false };
     char* apszProjection[MAX_JP2GEOTIFF_BOXES] = { NULL };
     double aadfGeoTransform[MAX_JP2GEOTIFF_BOXES][6];
     int anGCPCount[MAX_JP2GEOTIFF_BOXES] = { 0 };
@@ -568,8 +562,8 @@ int GDALJP2Metadata::ParseJP2GeoTIFF()
                                &anGCPCount[i], &apasGCPList[i],
                                &abPixelIsPoint[i], &apapszRPCMD[i] ) == CE_None )
         {
-            if( apszProjection[i] != NULL && strlen(apszProjection[i]) != 0 ) 
-                abValidProjInfo[i] = TRUE;
+            if( apszProjection[i] != NULL && strlen(apszProjection[i]) != 0 )
+                abValidProjInfo[i] = true;
         }
     }
 
@@ -584,7 +578,7 @@ int GDALJP2Metadata::ParseJP2GeoTIFF()
         else if( abValidProjInfo[i] && apszProjection[i] != NULL )
         {
             /* Anything else than a LOCAL_CS will probably be better */
-            if( EQUALN(apszProjection[iBestIndex], "LOCAL_CS", strlen("LOCAL_CS")) )
+            if( STARTS_WITH_CI(apszProjection[iBestIndex], "LOCAL_CS") )
                 iBestIndex = i;
         }
     }
@@ -593,10 +587,10 @@ int GDALJP2Metadata::ParseJP2GeoTIFF()
     {
         for(i=0; i < nMax; i++)
         {
-            if( aadfGeoTransform[i][0] != 0 
-                || aadfGeoTransform[i][1] != 1 
+            if( aadfGeoTransform[i][0] != 0
+                || aadfGeoTransform[i][1] != 1
                 || aadfGeoTransform[i][2] != 0
-                || aadfGeoTransform[i][3] != 0 
+                || aadfGeoTransform[i][3] != 0
                 || aadfGeoTransform[i][4] != 0
                 || aadfGeoTransform[i][5] != 1
                 || anGCPCount[i] > 0
@@ -616,17 +610,17 @@ int GDALJP2Metadata::ParseJP2GeoTIFF()
         bPixelIsPoint = abPixelIsPoint[iBestIndex];
         papszRPCMD = apapszRPCMD[iBestIndex];
 
-        if( adfGeoTransform[0] != 0 
-            || adfGeoTransform[1] != 1 
+        if( adfGeoTransform[0] != 0
+            || adfGeoTransform[1] != 1
             || adfGeoTransform[2] != 0
-            || adfGeoTransform[3] != 0 
+            || adfGeoTransform[3] != 0
             || adfGeoTransform[4] != 0
             || adfGeoTransform[5] != 1 )
             bHaveGeoTransform = TRUE;
 
         if( pszProjection )
-            CPLDebug( "GDALJP2Metadata", 
-                "Got projection from GeoJP2 (geotiff) box (%d): %s", 
+            CPLDebug( "GDALJP2Metadata",
+                "Got projection from GeoJP2 (geotiff) box (%d): %s",
                 iBestIndex, pszProjection );
     }
 
@@ -700,11 +694,11 @@ GetDictionaryItem( char **papszGMLMetadata, const char *pszURN )
     int i;
 
 
-    if( EQUALN(pszURN,"urn:jp2k:xml:", 13) )
+    if( STARTS_WITH_CI(pszURN, "urn:jp2k:xml:") )
         pszLabel = CPLStrdup( pszURN + 13 );
-    else if( EQUALN(pszURN,"urn:ogc:tc:gmljp2:xml:", 22) )
+    else if( STARTS_WITH_CI(pszURN, "urn:ogc:tc:gmljp2:xml:") )
         pszLabel = CPLStrdup( pszURN + 22 );
-    else if( EQUALN(pszURN,"gmljp2://xml/",13) )
+    else if( STARTS_WITH_CI(pszURN, "gmljp2://xml/") )
         pszLabel = CPLStrdup( pszURN + 13 );
     else
         pszLabel = CPLStrdup( pszURN );
@@ -727,7 +721,7 @@ GetDictionaryItem( char **papszGMLMetadata, const char *pszURN )
 /* -------------------------------------------------------------------- */
 /*      Can we find an XML box with the desired label?                  */
 /* -------------------------------------------------------------------- */
-    const char *pszDictionary = 
+    const char *pszDictionary =
         CSLFetchNameValue( papszGMLMetadata, pszLabel );
 
     if( pszDictionary == NULL )
@@ -750,7 +744,7 @@ GetDictionaryItem( char **papszGMLMetadata, const char *pszURN )
     CPLStripXMLNamespace( psDictTree, NULL, TRUE );
 
     CPLXMLNode *psDictRoot = CPLSearchXMLNode( psDictTree, "=Dictionary" );
-    
+
     if( psDictRoot == NULL )
     {
         CPLDestroyXMLNode( psDictTree );
@@ -762,8 +756,8 @@ GetDictionaryItem( char **papszGMLMetadata, const char *pszURN )
 /*      Search for matching id.                                         */
 /* -------------------------------------------------------------------- */
     CPLXMLNode *psEntry, *psHit = NULL;
-    for( psEntry = psDictRoot->psChild; 
-         psEntry != NULL && psHit == NULL; 
+    for( psEntry = psDictRoot->psChild;
+         psEntry != NULL && psHit == NULL;
          psEntry = psEntry->psNext )
     {
         const char *pszId;
@@ -773,7 +767,7 @@ GetDictionaryItem( char **papszGMLMetadata, const char *pszURN )
 
         if( !EQUAL(psEntry->pszValue,"dictionaryEntry") )
             continue;
-        
+
         if( psEntry->psChild == NULL )
             continue;
 
@@ -792,7 +786,7 @@ GetDictionaryItem( char **papszGMLMetadata, const char *pszURN )
     return psHit;
 }
 
-        
+
 /************************************************************************/
 /*                            GMLSRSLookup()                            */
 /*                                                                      */
@@ -843,17 +837,17 @@ int GDALJP2Metadata::GMLSRSLookup( const char *pszURN )
 /*                        ParseGMLCoverageDesc()                        */
 /************************************************************************/
 
-int GDALJP2Metadata::ParseGMLCoverageDesc() 
+int GDALJP2Metadata::ParseGMLCoverageDesc()
 
 {
-    if(! CSLTestBoolean(CPLGetConfigOption("GDAL_USE_GMLJP2", "TRUE")) )
+    if(! CPLTestBool(CPLGetConfigOption("GDAL_USE_GMLJP2", "TRUE")) )
         return FALSE;
 
 /* -------------------------------------------------------------------- */
 /*      Do we have an XML doc that is apparently a coverage             */
 /*      description?                                                    */
 /* -------------------------------------------------------------------- */
-    const char *pszCoverage = CSLFetchNameValue( papszGMLMetadata, 
+    const char *pszCoverage = CSLFetchNameValue( papszGMLMetadata,
                                                  "gml.root-instance" );
 
     if( pszCoverage == NULL )
@@ -883,12 +877,12 @@ int GDALJP2Metadata::ParseGMLCoverageDesc()
     {
         psOriginPoint = CPLGetXMLNode( psRG, "origin.Point" );
 
-        
+
         CPLXMLNode *psOffset1 = CPLGetXMLNode( psRG, "offsetVector" );
         if( psOffset1 != NULL )
         {
             pszOffset1 = CPLGetXMLValue( psOffset1, "", NULL );
-            pszOffset2 = CPLGetXMLValue( psOffset1->psNext, "=offsetVector", 
+            pszOffset2 = CPLGetXMLValue( psOffset1->psNext, "=offsetVector",
                                          NULL );
         }
     }
@@ -910,10 +904,10 @@ int GDALJP2Metadata::ParseGMLCoverageDesc()
 
     if( psOriginPoint != NULL )
     {
-        poOriginGeometry = (OGRPoint *) 
+        poOriginGeometry = (OGRPoint *)
             OGR_G_CreateFromGMLTree( psOriginPoint );
 
-        if( poOriginGeometry != NULL 
+        if( poOriginGeometry != NULL
             && wkbFlatten(poOriginGeometry->getGeometryType()) != wkbPoint )
         {
             delete poOriginGeometry;
@@ -929,11 +923,11 @@ int GDALJP2Metadata::ParseGMLCoverageDesc()
 /* -------------------------------------------------------------------- */
     char **papszOffset1Tokens = NULL;
     char **papszOffset2Tokens = NULL;
-    int bSuccess = FALSE;
+    bool bSuccess = false;
 
-    papszOffset1Tokens = 
+    papszOffset1Tokens =
         CSLTokenizeStringComplex( pszOffset1, " ,", FALSE, FALSE );
-    papszOffset2Tokens = 
+    papszOffset2Tokens =
         CSLTokenizeStringComplex( pszOffset2, " ,", FALSE, FALSE );
 
     if( CSLCount(papszOffset1Tokens) >= 2
@@ -953,7 +947,7 @@ int GDALJP2Metadata::ParseGMLCoverageDesc()
         adfGeoTransform[3] -= adfGeoTransform[4]*0.5;
         adfGeoTransform[3] -= adfGeoTransform[5]*0.5;
 
-        bSuccess = TRUE;
+        bSuccess = true;
         bHaveGeoTransform = TRUE;
     }
 
@@ -966,12 +960,12 @@ int GDALJP2Metadata::ParseGMLCoverageDesc()
 /* -------------------------------------------------------------------- */
 /*      If we still don't have an srsName, check for it on the          */
 /*      boundedBy Envelope.  Some products                              */
-/*      (ie. EuropeRasterTile23.jpx) use this as the only srsName       */
+/*      (i.e. EuropeRasterTile23.jpx) use this as the only srsName      */
 /*      delivery vehicle.                                               */
 /* -------------------------------------------------------------------- */
     if( pszSRSName == NULL )
     {
-        pszSRSName = 
+        pszSRSName =
             CPLGetXMLValue( psXML,
                             "=FeatureCollection.boundedBy.Envelope.srsName",
                             NULL );
@@ -986,28 +980,26 @@ int GDALJP2Metadata::ParseGMLCoverageDesc()
     }
 
 /* -------------------------------------------------------------------- */
-/*      If we have gotten a geotransform, then try to interprete the    */
+/*      If we have gotten a geotransform, then try to interpret the     */
 /*      srsName.                                                        */
 /* -------------------------------------------------------------------- */
-    int bNeedAxisFlip = FALSE;
+    bool bNeedAxisFlip = false;
 
     OGRSpatialReference oSRS;
-    if( bSuccess && pszSRSName != NULL 
+    if( bSuccess && pszSRSName != NULL
         && (pszProjection == NULL || strlen(pszProjection) == 0) )
     {
-        if( EQUALN(pszSRSName,"epsg:",5) )
+        if( STARTS_WITH_CI(pszSRSName, "epsg:") )
         {
             if( oSRS.SetFromUserInput( pszSRSName ) == OGRERR_NONE )
                 oSRS.exportToWkt( &pszProjection );
         }
-        else if( (EQUALN(pszSRSName,"urn:",4) 
+        else if( (STARTS_WITH_CI(pszSRSName, "urn:")
                  && strstr(pszSRSName,":def:") != NULL
                  && oSRS.importFromURN(pszSRSName) == OGRERR_NONE) ||
                  /* GMLJP2 v2.0 uses CRS URL instead of URN */
                  /* See e.g. http://schemas.opengis.net/gmljp2/2.0/examples/minimalInstance.xml */
-                 (EQUALN(pszSRSName,"http://www.opengis.net/def/crs/",
-                         strlen("http://www.opengis.net/def/crs/")) 
-                 && oSRS.importFromCRSURL(pszSRSName) == OGRERR_NONE) )
+                 (STARTS_WITH_CI(pszSRSName, "http://www.opengis.net/def/crs/")                  && oSRS.importFromCRSURL(pszSRSName) == OGRERR_NONE) )
         {
             oSRS.exportToWkt( &pszProjection );
 
@@ -1016,33 +1008,33 @@ int GDALJP2Metadata::ParseGMLCoverageDesc()
             {
                 CPLDebug( "GMLJP2", "Request axis flip for SRS=%s",
                           pszSRSName );
-                bNeedAxisFlip = TRUE;
+                bNeedAxisFlip = true;
             }
         }
         else if( !GMLSRSLookup( pszSRSName ) )
         {
-            CPLDebug( "GDALJP2Metadata", 
-                      "Unable to evaluate SRSName=%s", 
+            CPLDebug( "GDALJP2Metadata",
+                      "Unable to evaluate SRSName=%s",
                       pszSRSName );
         }
     }
 
     if( pszProjection )
-        CPLDebug( "GDALJP2Metadata", 
-                  "Got projection from GML box: %s", 
+        CPLDebug( "GDALJP2Metadata",
+                  "Got projection from GML box: %s",
                  pszProjection );
 
 /* -------------------------------------------------------------------- */
 /*      Do we need to flip the axes?                                    */
 /* -------------------------------------------------------------------- */
     if( bNeedAxisFlip
-        && CSLTestBoolean( CPLGetConfigOption( "GDAL_IGNORE_AXIS_ORIENTATION",
+        && CPLTestBool( CPLGetConfigOption( "GDAL_IGNORE_AXIS_ORIENTATION",
                                                "FALSE" ) ) )
     {
-        bNeedAxisFlip = FALSE;
+        bNeedAxisFlip = false;
         CPLDebug( "GMLJP2", "Suppressed axis flipping based on GDAL_IGNORE_AXIS_ORIENTATION." );
     }
-    
+
     if( pszSRSName && bNeedAxisFlip )
     {
         // Suppress explicit axis order in SRS definition
@@ -1054,34 +1046,35 @@ int GDALJP2Metadata::ParseGMLCoverageDesc()
         OGR_SRSNode *poPROJCS = oSRS.GetAttrNode( "PROJCS" );
         if (poPROJCS != NULL && oSRS.EPSGTreatsAsNorthingEasting())
             poPROJCS->StripNodes( "AXIS" );
-        
+
         CPLFree(pszProjection);
         oSRS.exportToWkt( &pszProjection );
 
     }
-    
+
     /* Some Pleiades files have explicit <gml:axisName>Easting</gml:axisName> */
     /* <gml:axisName>Northing</gml:axisName> to override default EPSG order */
     if( bNeedAxisFlip && psRG != NULL )
     {
         int nAxisCount = 0;
-        int bFirstAxisIsEastOrLong = FALSE, bSecondAxisIsNorthOrLat = FALSE;
+        bool bFirstAxisIsEastOrLong = false;
+        bool bSecondAxisIsNorthOrLat = false;
         for(CPLXMLNode* psIter = psRG->psChild; psIter != NULL; psIter = psIter->psNext )
         {
             if( psIter->eType == CXT_Element && strcmp(psIter->pszValue, "axisName") == 0 &&
                 psIter->psChild != NULL && psIter->psChild->eType == CXT_Text )
             {
-                if( nAxisCount == 0 && 
-                    (EQUALN(psIter->psChild->pszValue, "EAST", 4) ||
-                     EQUALN(psIter->psChild->pszValue, "LONG", 4) ) )
+                if( nAxisCount == 0 &&
+                    (STARTS_WITH_CI(psIter->psChild->pszValue, "EAST") ||
+                     STARTS_WITH_CI(psIter->psChild->pszValue, "LONG") ) )
                 {
-                    bFirstAxisIsEastOrLong = TRUE;
+                    bFirstAxisIsEastOrLong = true;
                 }
                 else if( nAxisCount == 1 &&
-                         (EQUALN(psIter->psChild->pszValue, "NORTH", 5) ||
-                          EQUALN(psIter->psChild->pszValue, "LAT", 3)) )
+                         (STARTS_WITH_CI(psIter->psChild->pszValue, "NORTH") ||
+                          STARTS_WITH_CI(psIter->psChild->pszValue, "LAT")) )
                 {
-                    bSecondAxisIsNorthOrLat = TRUE;
+                    bSecondAxisIsNorthOrLat = true;
                 }
                 nAxisCount ++;
             }
@@ -1089,7 +1082,7 @@ int GDALJP2Metadata::ParseGMLCoverageDesc()
         if( bFirstAxisIsEastOrLong && bSecondAxisIsNorthOrLat )
         {
             CPLDebug( "GMLJP2", "Disable axis flip because of explicit axisName disabling it" );
-            bNeedAxisFlip = FALSE;
+            bNeedAxisFlip = false;
         }
     }
 
@@ -1101,7 +1094,7 @@ int GDALJP2Metadata::ParseGMLCoverageDesc()
     {
         double dfTemp;
 
-        CPLDebug( "GMLJP2", 
+        CPLDebug( "GMLJP2",
                   "Flipping axis orientation in GMLJP2 coverage description." );
 
         dfTemp = adfGeoTransform[0];
@@ -1116,7 +1109,7 @@ int GDALJP2Metadata::ParseGMLCoverageDesc()
             strstr(pszCoverage, "GDAL_JP2K_ALT_OFFSETVECTOR_ORDER=TRUE") != NULL;
 
         if( bHasAltOffsetVectorOrderComment ||
-            CSLTestBoolean( CPLGetConfigOption( "GDAL_JP2K_ALT_OFFSETVECTOR_ORDER",
+            CPLTestBool( CPLGetConfigOption( "GDAL_JP2K_ALT_OFFSETVECTOR_ORDER",
                                                 "FALSE" ) ) )
         {
             swapWith1Index = 5;
@@ -1210,7 +1203,7 @@ GDALJP2Box *GDALJP2Metadata::CreateJP2GeoTIFF()
     int         nGTBufSize = 0;
     unsigned char *pabyGTBuf = NULL;
 
-    if( GTIFMemBufFromWktEx( pszProjection, adfGeoTransform, 
+    if( GTIFMemBufFromWktEx( pszProjection, adfGeoTransform,
                              nGCPCount, pasGCPList,
                              &nGTBufSize, &pabyGTBuf, bPixelIsPoint,
                              papszRPCMD ) != CE_None )
@@ -1225,7 +1218,7 @@ GDALJP2Box *GDALJP2Metadata::CreateJP2GeoTIFF()
     GDALJP2Box *poBox;
 
     poBox = GDALJP2Box::CreateUUIDBox( msi_uuid2, nGTBufSize, pabyGTBuf );
-    
+
     CPLFree( pabyGTBuf );
 
     return poBox;
@@ -1275,11 +1268,11 @@ int GDALJP2Metadata::GetGMLJP2GeoreferencingInfo( int& nEPSGCode,
     }
 
     // Save error state as importFromEPSGA() will call CPLReset()
-    int errNo = CPLGetLastErrorNo();
+    CPLErrorNum errNo = CPLGetLastErrorNo();
     CPLErr eErr = CPLGetLastErrorType();
     CPLString osLastErrorMsg = CPLGetLastErrorMsg();
 
-    // Determinte if we need to flix axis. Reimport from EPSG and make
+    // Determine if we need to flip axis. Reimport from EPSG and make
     // sure not to strip axis definitions to determine the axis order.
     if( nEPSGCode != 0 && oSRS.importFromEPSGA(nEPSGCode) == OGRERR_NONE )
     {
@@ -1302,12 +1295,12 @@ int GDALJP2Metadata::GetGMLJP2GeoreferencingInfo( int& nEPSGCode,
         + adfGeoTransform[5] * 0.5;
     adfXVector[0] = adfGeoTransform[1];
     adfXVector[1] = adfGeoTransform[2];
-        
+
     adfYVector[0] = adfGeoTransform[4];
     adfYVector[1] = adfGeoTransform[5];
-    
+
     if( bNeedAxisFlip
-        && CSLTestBoolean( CPLGetConfigOption( "GDAL_IGNORE_AXIS_ORIENTATION",
+        && CPLTestBool( CPLGetConfigOption( "GDAL_IGNORE_AXIS_ORIENTATION",
                                                "FALSE" ) ) )
     {
         bNeedAxisFlip = FALSE;
@@ -1318,14 +1311,14 @@ int GDALJP2Metadata::GetGMLJP2GeoreferencingInfo( int& nEPSGCode,
     if( bNeedAxisFlip )
     {
         double dfTemp;
-        
+
         CPLDebug( "GMLJP2", "Flipping GML coverage axis order." );
-        
+
         dfTemp = adfOrigin[0];
         adfOrigin[0] = adfOrigin[1];
         adfOrigin[1] = dfTemp;
 
-        if( CSLTestBoolean( CPLGetConfigOption( "GDAL_JP2K_ALT_OFFSETVECTOR_ORDER",
+        if( CPLTestBool( CPLGetConfigOption( "GDAL_JP2K_ALT_OFFSETVECTOR_ORDER",
                                                 "FALSE" ) ) )
         {
             CPLDebug( "GMLJP2", "Choosing alternate GML \"<offsetVector>\" order based on "
@@ -1371,14 +1364,15 @@ int GDALJP2Metadata::GetGMLJP2GeoreferencingInfo( int& nEPSGCode,
             oSRS.exportToWkt(&pszWKT);
             char* pszXMLEscapedWKT = CPLEscapeString(pszWKT, -1, CPLES_XML);
             CPLFree(pszWKT);
-            osDictBox.Printf(  
+            osDictBox.Printf(
 "<gml:Dictionary gml:id=\"CRSU1\" \n"
 "        xmlns:gml=\"http://www.opengis.net/gml\"\n"
 "        xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
 "        xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
-"        xsi:schemaLocation=\"http://www.opengis.net/gml http://schemas.opengis.net/gml/3.1.1/base/gml.xsd\">\n"
-"  <gml:description>Dictionnary for cursom SRS %s</gml:description>\n"
-"  <gml:name>Dictionnary for custom SRS</gml:name>\n"
+"        xsi:schemaLocation=\"http://www.opengis.net/gml "
+"http://schemas.opengis.net/gml/3.1.1/base/gml.xsd\">\n"
+"  <gml:description>Dictionary for custom SRS %s</gml:description>\n"
+"  <gml:name>Dictionary for custom SRS</gml:name>\n"
 "  <gml:dictionaryEntry>\n"
 "%s\n"
 "  </gml:dictionaryEntry>\n"
@@ -1411,32 +1405,32 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2( int nXSize, int nYSize )
 
         if( fp == NULL )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Unable to open GMLJP2OVERRIDE file." );
             return NULL;
         }
-        
-        VSIFSeekL( fp, 0, SEEK_END );
+
+        CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 0, SEEK_END ));
         int nLength = (int) VSIFTellL( fp );
         pszGML = (char *) CPLCalloc(1,nLength+1);
-        VSIFSeekL( fp, 0, SEEK_SET );
-        VSIFReadL( pszGML, 1, nLength, fp );
-        VSIFCloseL( fp );
+        CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 0, SEEK_SET ));
+        CPL_IGNORE_RET_VAL(VSIFReadL( pszGML, 1, nLength, fp ));
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
 
         GDALJP2Box *apoGMLBoxes[2];
 
         apoGMLBoxes[0] = GDALJP2Box::CreateLblBox( "gml.data" );
-        apoGMLBoxes[1] = 
-            GDALJP2Box::CreateLabelledXMLAssoc( "gml.root-instance", 
+        apoGMLBoxes[1] =
+            GDALJP2Box::CreateLabelledXMLAssoc( "gml.root-instance",
                                                 pszGML );
 
         GDALJP2Box *poGMLData = GDALJP2Box::CreateAsocBox( 2, apoGMLBoxes);
-        
+
         delete apoGMLBoxes[0];
         delete apoGMLBoxes[1];
 
         CPLFree( pszGML );
-        
+
         return poGMLData;
     }
 
@@ -1456,9 +1450,9 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2( int nXSize, int nYSize )
 
     char szSRSName[100];
     if( nEPSGCode != 0 )
-        sprintf( szSRSName, "urn:ogc:def:crs:EPSG::%d", nEPSGCode );
+        snprintf( szSRSName, sizeof(szSRSName), "urn:ogc:def:crs:EPSG::%d", nEPSGCode );
     else
-        strcpy( szSRSName, 
+        snprintf( szSRSName, sizeof(szSRSName), "%s",
                 "gmljp2://xml/CRSDictionary.gml#ogrcrs1" );
 
     // Compute bounding box
@@ -1479,7 +1473,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2( int nXSize, int nYSize )
         double dfTmp = dfLCX;
         dfLCX = dfLCY;
         dfLCY = dfTmp;
-        
+
         dfTmp = dfUCX;
         dfUCX = dfUCY;
         dfUCY = dfTmp;
@@ -1490,7 +1484,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2( int nXSize, int nYSize )
 /* -------------------------------------------------------------------- */
     CPLString osDoc;
 
-    osDoc.Printf( 
+    osDoc.Printf(
 "<gml:FeatureCollection\n"
 "   xmlns:gml=\"http://www.opengis.net/gml\"\n"
 "   xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
@@ -1540,7 +1534,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2( int nXSize, int nYSize )
              szSRSName, dfLCX, dfLCY, dfUCX, dfUCY,
              nXSize-1, nYSize-1, szSRSName, adfOrigin[0], adfOrigin[1],
              pszComment,
-             szSRSName, adfXVector[0], adfXVector[1], 
+             szSRSName, adfXVector[0], adfXVector[1],
              szSRSName, adfYVector[0], adfYVector[1] );
 
 /* -------------------------------------------------------------------- */
@@ -1554,17 +1548,17 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2( int nXSize, int nYSize )
 /* -------------------------------------------------------------------- */
 /*      Setup gml.root-instance.                                        */
 /* -------------------------------------------------------------------- */
-    apoGMLBoxes[nGMLBoxes++] = 
+    apoGMLBoxes[nGMLBoxes++] =
         GDALJP2Box::CreateLabelledXMLAssoc( "gml.root-instance", osDoc );
 
 /* -------------------------------------------------------------------- */
 /*      Add optional dictionary.                                        */
 /* -------------------------------------------------------------------- */
     if( osDictBox.size() > 0 )
-        apoGMLBoxes[nGMLBoxes++] = 
+        apoGMLBoxes[nGMLBoxes++] =
             GDALJP2Box::CreateLabelledXMLAssoc( "CRSDictionary.gml",
                                                 osDictBox );
-        
+
 /* -------------------------------------------------------------------- */
 /*      Bundle gml.data boxes into an association.                      */
 /* -------------------------------------------------------------------- */
@@ -1599,7 +1593,7 @@ static CPLXMLNode* GDALGMLJP2GetXMLRoot(CPLXMLNode* psNode)
 
 static void GDALGMLJP2PatchFeatureCollectionSubstitutionGroup(CPLXMLNode* psRoot)
 {
-    /* GML 3.2 SF profile recommands the feature collection type to derive */
+    /* GML 3.2 SF profile recommends the feature collection type to derive */
     /* from gml:AbstractGML to prevent it to be included in another feature */
     /* collection, but this is what we want to do. So patch that... */
 
@@ -1692,7 +1686,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
     CPLString osRootGMLId = "ID_GMLJP2_0";
     CPLString osGridCoverage;
     CPLString osGridCoverageFile;
-    int bCRSURL = TRUE;
+    bool bCRSURL = true;
     std::vector<GMLJP2V2MetadataDesc> aoMetadata;
     std::vector<GMLJP2V2AnnotationDesc> aoAnnotations;
     std::vector<GMLJP2V2GMLFileDesc> aoGMLFiles;
@@ -1750,7 +1744,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                     [ "The metadata file will be generated from a template and a source file.",
                       "The template is a valid GMLJP2 metadata XML tree with placeholders like",
                       "{{{XPATH(some_xpath_expression)}}}",
-                      "that are evalated from the source XML file. Typical use case",
+                      "that are evaluated from the source XML file. Typical use case",
                       "is to generate a gmljp2:eopMetadata from the XML metadata",
                       "provided by the image provider in their own particular format." ],
                 "dynamic_metadata" :
@@ -1794,7 +1788,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                                   "Ignored for a remote_resource"],
                 "namespace": "http://example.com",
 
-                "#schema_location_doc": ["Value of the substitued schemaLocation. ",
+                "#schema_location_doc": ["Value of the substituted schemaLocation. ",
                                          "Typically a schema box label (link)",
                                          "Ignored for a remote_resource"],
                 "schema_location": "gmljp2://xml/schema_0.xsd",
@@ -1878,10 +1872,10 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
 
             json_object* poCRSURL = json_object_object_get(poRootInstance, "crs_url");
             if( poCRSURL && json_object_get_type(poCRSURL) == json_type_boolean )
-                bCRSURL = json_object_get_boolean(poCRSURL);
+                bCRSURL = CPL_TO_BOOL(json_object_get_boolean(poCRSURL));
 
 
-            json_object* poMetadatas = json_object_object_get(poRootInstance, "metadata"); 
+            json_object* poMetadatas = json_object_object_get(poRootInstance, "metadata");
             if( poMetadatas && json_object_get_type(poMetadatas) == json_type_array )
             {
                 for(int i=0;i<json_object_array_length(poMetadatas);i++)
@@ -1903,7 +1897,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                         json_object* poFile = json_object_object_get(poMetadata, "file");
                         if( poFile && json_object_get_type(poFile) == json_type_string )
                             pszFile = json_object_get_string(poFile);
-                        
+
                         const char* pszContent = NULL;
                         json_object* poContent = json_object_object_get(poMetadata, "content");
                         if( poContent && json_object_get_type(poContent) == json_type_string )
@@ -1915,7 +1909,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                         if( poDynamicMetadata && json_object_get_type(poDynamicMetadata) == json_type_object )
                         {
 #ifdef HAVE_LIBXML2
-                            if( CSLTestBoolean(CPLGetConfigOption("GDAL_DEBUG_PROCESS_DYNAMIC_METADATA", "YES")) )
+                            if( CPLTestBool(CPLGetConfigOption("GDAL_DEBUG_PROCESS_DYNAMIC_METADATA", "YES")) )
                             {
                                 json_object* poTemplate = json_object_object_get(poDynamicMetadata, "template");
                                 if( poTemplate && json_object_get_type(poTemplate) == json_type_string )
@@ -1972,7 +1966,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                 }
             }
 
-            json_object* poAnnotations = json_object_object_get(poRootInstance, "annotations"); 
+            json_object* poAnnotations = json_object_object_get(poRootInstance, "annotations");
             if( poAnnotations && json_object_get_type(poAnnotations) == json_type_array )
             {
                 for(int i=0;i<json_object_array_length(poAnnotations);i++)
@@ -1987,7 +1981,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                 }
             }
 
-            json_object* poGMLFileList = json_object_object_get(poRootInstance, "gml_filelist"); 
+            json_object* poGMLFileList = json_object_object_get(poRootInstance, "gml_filelist");
             if( poGMLFileList && json_object_get_type(poGMLFileList) == json_type_array )
             {
                 for(int i=0;i<json_object_array_length(poGMLFileList);i++)
@@ -2051,7 +2045,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                 }
             }
 
-            json_object* poStyles = json_object_object_get(poRootInstance, "styles"); 
+            json_object* poStyles = json_object_object_get(poRootInstance, "styles");
             if( poStyles && json_object_get_type(poStyles) == json_type_array )
             {
                 for(int i=0;i<json_object_array_length(poStyles);i++)
@@ -2094,7 +2088,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                 }
             }
 
-            json_object* poExtensions = json_object_object_get(poRootInstance, "extensions"); 
+            json_object* poExtensions = json_object_object_get(poRootInstance, "extensions");
             if( poExtensions && json_object_get_type(poExtensions) == json_type_array )
             {
                 for(int i=0;i<json_object_array_length(poExtensions);i++)
@@ -2138,7 +2132,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
             }
         }
 
-        json_object* poBoxes = json_object_object_get(poObj, "boxes"); 
+        json_object* poBoxes = json_object_object_get(poObj, "boxes");
         if( poBoxes && json_object_get_type(poBoxes) == json_type_array )
         {
             for(int i=0;i<json_object_array_length(poBoxes);i++)
@@ -2178,12 +2172,10 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
         for(int i=0;i<(int)aoGMLFiles.size();i++)
         {
             if( aoGMLFiles[i].osSchemaLocation.size() &&
-                strncmp(aoGMLFiles[i].osSchemaLocation, "gmljp2://xml/",
-                        strlen("gmljp2://xml/")) == 0 )
-            {
+                STARTS_WITH(aoGMLFiles[i].osSchemaLocation, "gmljp2://xml/") )            {
                 const char* pszLookedLabel =
                     aoGMLFiles[i].osSchemaLocation.c_str() + strlen("gmljp2://xml/");
-                int bFound = FALSE;
+                bool bFound = false;
                 for(int j=0; !bFound && j<(int)aoBoxes.size();j++)
                     bFound = (strcmp(pszLookedLabel, aoBoxes[j].osLabel) == 0);
                 if( !bFound )
@@ -2226,7 +2218,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
         double adfOrigin[2];
         double adfXVector[2];
         double adfYVector[2];
-        const char* pszComment = "";   
+        const char* pszComment = "";
         int bNeedAxisFlip = FALSE;
         if( !GetGMLJP2GeoreferencingInfo( nEPSGCode, adfOrigin,
                                         adfXVector, adfYVector,
@@ -2239,12 +2231,14 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
         if( nEPSGCode != 0 )
         {
             if( bCRSURL )
-                sprintf( szSRSName, "http://www.opengis.net/def/crs/EPSG/0/%d", nEPSGCode );
+                snprintf( szSRSName, sizeof(szSRSName),
+                          "http://www.opengis.net/def/crs/EPSG/0/%d", nEPSGCode );
             else
-                sprintf( szSRSName, "urn:ogc:def:crs:EPSG::%d", nEPSGCode );
+                snprintf( szSRSName, sizeof(szSRSName),
+                          "urn:ogc:def:crs:EPSG::%d", nEPSGCode );
         }
         else
-            strcpy( szSRSName, 
+            snprintf( szSRSName, sizeof(szSRSName), "%s",
                     "gmljp2://xml/CRSDictionary.gml#ogrcrs1" );
 
         osGridCoverage.Printf(
@@ -2283,14 +2277,14 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
             szSRSName,
             nXSize-1, nYSize-1, szSRSName, adfOrigin[0], adfOrigin[1],
             pszComment,
-            szSRSName, adfXVector[0], adfXVector[1], 
+            szSRSName, adfXVector[0], adfXVector[1],
             szSRSName, adfYVector[0], adfYVector[1] );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Main node.                                                      */
 /* -------------------------------------------------------------------- */
-    osDoc.Printf( 
+    osDoc.Printf(
 //"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
 "<gmljp2:GMLJP2CoverageCollection gml:id=\"%s\"\n"
 "     xmlns:gml=\"http://www.opengis.net/gml/3.2\"\n"
@@ -2319,7 +2313,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
 /*      Process metadata, annotations and features collections.         */
 /* -------------------------------------------------------------------- */
     std::vector<CPLString> aosTmpFiles;
-    int bRootHasXLink = FALSE;
+    bool bRootHasXLink = false;
     if( aoMetadata.size() || aoAnnotations.size() || aoGMLFiles.size() ||
         aoStyles.size() || aoExtensions.size() )
     {
@@ -2372,7 +2366,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                 }
                 else if( aoMetadata[i].bParentCoverageCollection )
                 {
-                    /*  Insert the gmlcov:metadata link as the next sibbling of */
+                    /* Insert the gmlcov:metadata link as the next sibling of */
                     /* GMLJP2CoverageCollection.rangeType */
                     CPLXMLNode* psRangeType =
                         CPLGetXMLNode(psGMLJP2CoverageCollection, "gmlcov:rangeType");
@@ -2489,7 +2483,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
             }
 
             CPLXMLNode* psGMLFileRoot = psGMLFile ? GDALGMLJP2GetXMLRoot(psGMLFile) : NULL;
-            if( psGMLFileRoot || aoGMLFiles[i].osRemoteResource.size() ) 
+            if( psGMLFileRoot || aoGMLFiles[i].osRemoteResource.size() )
             {
                 CPLXMLNode *node_f;
                 if( aoGMLFiles[i].bParentCoverageCollection )
@@ -2522,7 +2516,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                 {
                     if( !bRootHasXLink )
                     {
-                        bRootHasXLink = TRUE;
+                        bRootHasXLink = true;
                         CPLSetXMLValue(psGMLJP2CoverageCollection, "#xmlns:xlink",
                                        "http://www.w3.org/1999/xlink");
                     }
@@ -2564,7 +2558,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                 CPLXMLNode* psGMLFileGMLId =
                     CPLGetXMLNode(psGMLFileRoot, "gml:id");
                 if( psGMLFileGMLId && psGMLFileGMLId->eType == CXT_Attribute )
-                    CPLSetXMLValue( psGMLFileGMLId, "", 
+                    CPLSetXMLValue( psGMLFileGMLId, "",
                                     CPLSPrintf("%s_%d_%s",
                                                 osRootGMLId.c_str(), i,
                                                 psGMLFileGMLId->psChild->pszValue) );
@@ -2577,7 +2571,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                 if( psSchemaLocation && psSchemaLocation->eType == CXT_Attribute )
                 {
                     char **papszTokens = CSLTokenizeString2(
-                        psSchemaLocation->psChild->pszValue, " \t\n", 
+                        psSchemaLocation->psChild->pszValue, " \t\n",
                         CSLT_HONOURSTRINGS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES);
                     CPLString osSchemaLocation;
 
@@ -2733,7 +2727,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                 continue;
 
             CPLXMLNode* psKMLFileRoot = GDALGMLJP2GetXMLRoot(psKMLFile);
-            if( psKMLFileRoot ) 
+            if( psKMLFileRoot )
             {
                 CPLXMLNode* psFeatureMemberOfGridCoverage =
                     CPLGetXMLNode(psGMLJP2CoverageCollection, "gmljp2:featureMember");
@@ -2767,7 +2761,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                 continue;
 
             CPLXMLNode* psStyleRoot = GDALGMLJP2GetXMLRoot(psStyle);
-            if( psStyleRoot ) 
+            if( psStyleRoot )
             {
                 CPLXMLNode *psGMLJP2Style;
                 if( aoStyles[i].bParentCoverageCollection )
@@ -2804,7 +2798,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                 continue;
 
             CPLXMLNode* psExtensionRoot = GDALGMLJP2GetXMLRoot(psExtension);
-            if( psExtensionRoot ) 
+            if( psExtensionRoot )
             {
                 CPLXMLNode *psGMLJP2Extension;
                 if( aoExtensions[i].bParentCoverageCollection )
@@ -2876,7 +2870,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
             if( psNode )
             {
                 CPLXMLNode* psRoot = GDALGMLJP2GetXMLRoot(psNode);
-                if( psRoot ) 
+                if( psRoot )
                 {
                     GDALGMLJP2PatchFeatureCollectionSubstitutionGroup(psRoot);
                     pabyContent = (GByte*) CPLSerializeXMLTree(psRoot);
@@ -2934,10 +2928,10 @@ CPLXMLNode* GDALJP2Metadata::CreateGDALMultiDomainMetadataXML(
         papszSrcMD = CSLSetNameValue(papszSrcMD, "VERSION", NULL);
     }
 
-    int bHasMD = FALSE;
+    bool bHasMD = false;
     if( papszSrcMD && *papszSrcMD )
     {
-        bHasMD = TRUE;
+        bHasMD = true;
         oLocalMDMD.SetMetadata(papszSrcMD);
     }
     CSLDestroy(papszSrcMD);
@@ -2945,13 +2939,13 @@ CPLXMLNode* GDALJP2Metadata::CreateGDALMultiDomainMetadataXML(
     if( !bMainMDDomainOnly )
     {
         char** papszMDList = poSrcDS->GetMetadataDomainList();
-        for( char** papszMDListIter = papszMDList; 
+        for( char** papszMDListIter = papszMDList;
             papszMDListIter && *papszMDListIter; ++papszMDListIter )
         {
             if( !EQUAL(*papszMDListIter, "") &&
                 !EQUAL(*papszMDListIter, "IMAGE_STRUCTURE") &&
                 !EQUAL(*papszMDListIter, "JPEG2000") &&
-                !EQUALN(*papszMDListIter, "xml:BOX_", strlen("xml:BOX_")) &&
+                !STARTS_WITH_CI(*papszMDListIter, "xml:BOX_") &&
                 !EQUAL(*papszMDListIter, "xml:gml.root-instance") &&
                 !EQUAL(*papszMDListIter, "xml:XMP") &&
                 !EQUAL(*papszMDListIter, "xml:IPR") )
@@ -2959,7 +2953,7 @@ CPLXMLNode* GDALJP2Metadata::CreateGDALMultiDomainMetadataXML(
                 papszSrcMD = poSrcDS->GetMetadata(*papszMDListIter);
                 if( papszSrcMD && *papszSrcMD )
                 {
-                    bHasMD = TRUE;
+                    bHasMD = true;
                     oLocalMDMD.SetMetadata(papszSrcMD, *papszMDListIter);
                 }
             }
@@ -2995,7 +2989,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGDALMultiDomainMetadataXMLBox(
 
     GDALJP2Box* poBox = new GDALJP2Box();
     poBox->SetType("xml ");
-    poBox->SetWritableData(strlen(pszXML) + 1, (const GByte*)pszXML);
+    poBox->SetWritableData(static_cast<int>(strlen(pszXML) + 1), (const GByte*)pszXML);
     CPLFree(pszXML);
 
     return poBox;
@@ -3011,19 +3005,19 @@ GDALJP2Box** GDALJP2Metadata::CreateXMLBoxes( GDALDataset* poSrcDS,
     GDALJP2Box** papoBoxes = NULL;
     *pnBoxes = 0;
     char** papszMDList = poSrcDS->GetMetadataDomainList();
-    for( char** papszMDListIter = papszMDList; 
+    for( char** papszMDListIter = papszMDList;
         papszMDListIter && *papszMDListIter; ++papszMDListIter )
     {
         /* Write metadata that look like originating from JP2 XML boxes */
         /* as a standalone JP2 XML box */
-        if( EQUALN(*papszMDListIter, "xml:BOX_", strlen("xml:BOX_")) )
+        if( STARTS_WITH_CI(*papszMDListIter, "xml:BOX_") )
         {
             char** papszSrcMD = poSrcDS->GetMetadata(*papszMDListIter);
             if( papszSrcMD && *papszSrcMD )
             {
                 GDALJP2Box* poBox = new GDALJP2Box();
                 poBox->SetType("xml ");
-                poBox->SetWritableData(strlen(*papszSrcMD) + 1,
+                poBox->SetWritableData(static_cast<int>(strlen(*papszSrcMD) + 1),
                                        (const GByte*)*papszSrcMD);
                 papoBoxes = (GDALJP2Box**)CPLRealloc(papoBoxes,
                                         sizeof(GDALJP2Box*) * (*pnBoxes + 1));
@@ -3046,7 +3040,7 @@ GDALJP2Box *GDALJP2Metadata::CreateXMPBox ( GDALDataset* poSrcDS )
     if( papszSrcMD && * papszSrcMD )
     {
         poBox = GDALJP2Box::CreateUUIDBox(xmp_uuid,
-                                          strlen(*papszSrcMD) + 1,
+                                          static_cast<int>(strlen(*papszSrcMD) + 1),
                                           (const GByte*)*papszSrcMD);
     }
     return poBox;
@@ -3064,7 +3058,7 @@ GDALJP2Box *GDALJP2Metadata::CreateIPRBox ( GDALDataset* poSrcDS )
     {
         poBox = new GDALJP2Box();
         poBox->SetType("jp2i");
-        poBox->SetWritableData(strlen(*papszSrcMD) + 1,
+        poBox->SetWritableData(static_cast<int>(strlen(*papszSrcMD) + 1),
                                         (const GByte*)*papszSrcMD);
     }
     return poBox;
diff --git a/gcore/gdaljp2metadata.h b/gcore/gdaljp2metadata.h
index 2a40e9d..8e80d90 100644
--- a/gcore/gdaljp2metadata.h
+++ b/gcore/gdaljp2metadata.h
@@ -1,7 +1,7 @@
 /******************************************************************************
- * $Id: gdaljp2metadata.h 29210 2015-05-19 19:04:28Z rouault $
+ * $Id: gdaljp2metadata.h 33694 2016-03-10 17:54:30Z goatbar $
  *
- * Project:  GDAL 
+ * Project:  GDAL
  * Purpose:  JP2 Box Reader (and GMLJP2 Interpreter)
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -32,10 +32,10 @@
 #define GDAL_JP2READER_H_INCLUDED
 
 #include "cpl_conv.h"
+#include "cpl_minixml.h"
 #include "cpl_vsi.h"
 #include "gdal.h"
 #include "gdal_priv.h"
-#include "cpl_minixml.h"
 
 /************************************************************************/
 /*                              GDALJP2Box                              */
@@ -77,7 +77,7 @@ public:
     GIntBig     GetDataLength();
 
     const char *GetType() { return szBoxType; }
-    
+
     GByte      *ReadBoxData();
 
     int         IsSuperBox();
@@ -104,7 +104,7 @@ public:
     static GDALJP2Box *CreateLblBox( const char *pszLabel );
     static GDALJP2Box *CreateLabelledXMLAssoc( const char *pszLabel,
                                                const char *pszXML );
-    static GDALJP2Box *CreateUUIDBox( const GByte *pabyUUID, 
+    static GDALJP2Box *CreateUUIDBox( const GByte *pabyUUID,
                                       int nDataSize, const GByte *pabyData );
 };
 
@@ -126,7 +126,7 @@ private:
 
     int    nMSIGSize;
     GByte  *pabyMSIGData;
-    
+
     int      GetGMLJP2GeoreferencingInfo( int& nEPSGCode,
                                           double adfOrigin[2],
                                           double adfXVector[2],
@@ -140,7 +140,7 @@ private:
 
 public:
     char  **papszGMLMetadata;
-    
+
     int     bHaveGeoTransform;
     double  adfGeoTransform[6];
     int     bPixelIsPoint;
@@ -149,7 +149,7 @@ public:
 
     int         nGCPCount;
     GDAL_GCP    *pasGCPList;
-    
+
     char **papszRPCMD;
 
     char  **papszMetadata; /* TIFFTAG_?RESOLUTION* for now from resd box */
@@ -170,12 +170,12 @@ public:
     int     ReadAndParse( VSILFILE * fpVSIL );
     int     ReadAndParse( const char *pszFilename );
 
-    // Write oriented. 
+    // Write oriented.
     void    SetProjection( const char *pszWKT );
     void    SetGeoTransform( double * );
     void    SetGCPs( int, const GDAL_GCP * );
     void    SetRPCMD( char** papszRPCMDIn );
-    
+
     GDALJP2Box *CreateJP2GeoTIFF();
     GDALJP2Box *CreateGMLJP2( int nXSize, int nYSize );
     GDALJP2Box *CreateGMLJP2V2( int nXSize, int nYSize,
diff --git a/gcore/gdaljp2metadatagenerator.cpp b/gcore/gdaljp2metadatagenerator.cpp
index 9048048..1f9f6f5 100644
--- a/gcore/gdaljp2metadatagenerator.cpp
+++ b/gcore/gdaljp2metadatagenerator.cpp
@@ -1,7 +1,7 @@
 /******************************************************************************
- * $Id: gdaljp2metadatagenerator.cpp 29073 2015-04-30 11:38:01Z rouault $
+ * $Id: gdaljp2metadatagenerator.cpp 33694 2016-03-10 17:54:30Z goatbar $
  *
- * Project:  GDAL 
+ * Project:  GDAL
  * Purpose:  GDALJP2Metadata: metadata generator
  * Author:   Even Rouault <even dot rouault at spatialys dot com>
  *
@@ -30,7 +30,7 @@
 #include <vector>
 #include "gdaljp2metadatagenerator.h"
 
-CPL_CVSID("$Id: gdaljp2metadatagenerator.cpp 29073 2015-04-30 11:38:01Z rouault $");
+CPL_CVSID("$Id: gdaljp2metadatagenerator.cpp 33694 2016-03-10 17:54:30Z goatbar $");
 
 //#define ENABLE_BRAIN_DAMAGE
 
@@ -45,7 +45,7 @@ CPL_CVSID("$Id: gdaljp2metadatagenerator.cpp 29073 2015-04-30 11:38:01Z rouault
 /*                            GDALGMLJP2Expr                            */
 /************************************************************************/
 
-typedef enum 
+typedef enum
 {
     GDALGMLJP2Expr_Unknown,
     GDALGMLJP2Expr_XPATH,
@@ -245,7 +245,7 @@ typedef struct
 GDALGMLJP2Expr* GDALGMLJP2Expr::Build(const char* pszOriStr,
                                       const char*& pszStr)
 {
-    if( EQUALN(pszStr, "{{{", strlen("{{{")) )
+    if( STARTS_WITH_CI(pszStr, "{{{") )
     {
         pszStr += strlen("{{{");
         SkipSpaces(pszStr);
@@ -253,7 +253,7 @@ GDALGMLJP2Expr* GDALGMLJP2Expr::Build(const char* pszOriStr,
         if( poExpr == NULL )
             return NULL;
         SkipSpaces(pszStr);
-        if( !EQUALN(pszStr, "}}}", strlen("}}}")) )
+        if( !STARTS_WITH_CI(pszStr, "}}}") )
         {
             ReportError(pszOriStr, pszStr);
             delete poExpr;
@@ -262,7 +262,7 @@ GDALGMLJP2Expr* GDALGMLJP2Expr::Build(const char* pszOriStr,
         pszStr += strlen("}}}");
         return poExpr;
     }
-    else if( EQUALN(pszStr, "XPATH", strlen("XPATH")) )
+    else if( STARTS_WITH_CI(pszStr, "XPATH") )
     {
         pszStr += strlen("XPATH");
         SkipSpaces(pszStr);
@@ -273,7 +273,7 @@ GDALGMLJP2Expr* GDALGMLJP2Expr::Build(const char* pszOriStr,
         }
         pszStr ++;
         SkipSpaces(pszStr);
-        CPLString osValue;
+        CPLString l_osValue;
         int nParenthesisIndent = 0;
         char chLiteralQuote = '\0';
         while( *pszStr )
@@ -282,19 +282,19 @@ GDALGMLJP2Expr* GDALGMLJP2Expr::Build(const char* pszOriStr,
             {
                 if( *pszStr == chLiteralQuote )
                     chLiteralQuote = '\0';
-                osValue += *pszStr;
+                l_osValue += *pszStr;
                 pszStr++;
             }
             else if( *pszStr == '\'' || *pszStr == '"' )
             {
                 chLiteralQuote = *pszStr;
-                osValue += *pszStr;
+                l_osValue += *pszStr;
                 pszStr++;
             }
             else if( *pszStr == '(' )
             {
                 nParenthesisIndent ++;
-                osValue += *pszStr;
+                l_osValue += *pszStr;
                 pszStr++;
             }
             else if( *pszStr == ')' )
@@ -305,16 +305,16 @@ GDALGMLJP2Expr* GDALGMLJP2Expr::Build(const char* pszOriStr,
                     pszStr++;
                     GDALGMLJP2Expr* poExpr = new GDALGMLJP2Expr();
                     poExpr->eType = GDALGMLJP2Expr_XPATH;
-                    poExpr->osValue = osValue;
-                    //CPLDebug("GMLJP2", "XPath expression '%s'", osValue.c_str());
+                    poExpr->osValue = l_osValue;
+                    //CPLDebug("GMLJP2", "XPath expression '%s'", l_osValue.c_str());
                     return poExpr;
                 }
-                osValue += *pszStr;
+                l_osValue += *pszStr;
                 pszStr++;
             }
             else
             {
-                osValue += *pszStr;
+                l_osValue += *pszStr;
                 pszStr++;
             }
         }
@@ -325,15 +325,15 @@ GDALGMLJP2Expr* GDALGMLJP2Expr::Build(const char* pszOriStr,
     else if( pszStr[0] == '\'' )
     {
         pszStr ++;
-        CPLString osValue;
+        CPLString l_osValue;
         while( *pszStr )
         {
             if( *pszStr == '\\' )
             {
                 if( pszStr[1] == '\\' )
-                    osValue += "\\";
+                    l_osValue += "\\";
                 else if( pszStr[1] == '\'' )
-                    osValue += "\'";
+                    l_osValue += "\'";
                 else
                 {
                     ReportError(pszOriStr, pszStr);
@@ -346,12 +346,12 @@ GDALGMLJP2Expr* GDALGMLJP2Expr::Build(const char* pszOriStr,
                 pszStr ++;
                 GDALGMLJP2Expr* poExpr = new GDALGMLJP2Expr();
                 poExpr->eType = GDALGMLJP2Expr_STRING_LITERAL;
-                poExpr->osValue = osValue;
+                poExpr->osValue = l_osValue;
                 return poExpr;
             }
             else
             {
-                osValue += *pszStr;
+                l_osValue += *pszStr;
                 pszStr ++;
             }
         }
@@ -640,7 +640,7 @@ GDALGMLJP2Expr GDALGMLJP2Expr::Evaluate(xmlXPathContextPtr pXPathCtx,
             oExpr.eType = GDALGMLJP2Expr_STRING_LITERAL;
             return oExpr;
         }
-        
+
         case GDALGMLJP2Expr_UUID:
         {
             CPLString osRet;
@@ -663,7 +663,7 @@ GDALGMLJP2Expr GDALGMLJP2Expr::Evaluate(xmlXPathContextPtr pXPathCtx,
                 osRet += GDALGMLJP2HexFormatter(rand() & 0xFF);
             return GDALGMLJP2Expr(osRet);
         }
-        
+
         case GDALGMLJP2Expr_STRING_LENGTH:
         {
             GDALGMLJP2Expr oExpr(CPLSPrintf("%d",
@@ -730,7 +730,7 @@ static CPLString GDALGMLJP2EvalExpr(const CPLString& osTemplate,
 {
     CPLString osXMLRes;
     size_t nPos = 0;
-    while( TRUE )
+    while( true )
     {
         // Get next expression
         size_t nStartPos = osTemplate.find("{{{", nPos);
@@ -743,7 +743,7 @@ static CPLString GDALGMLJP2EvalExpr(const CPLString& osTemplate,
 
         // Add portion of template before the expression
         osXMLRes += osTemplate.substr(nPos, nStartPos - nPos);
-        
+
         const char* pszExpr = osTemplate.c_str() + nStartPos;
         GDALGMLJP2Expr* poExpr = GDALGMLJP2Expr::Build(pszExpr, pszExpr);
         if( poExpr == NULL )
@@ -759,7 +759,7 @@ static CPLString GDALGMLJP2EvalExpr(const CPLString& osTemplate,
 /*                      GDALGMLJP2XPathErrorHandler()                   */
 /************************************************************************/
 
-static void GDALGMLJP2XPathErrorHandler(CPL_UNUSED void * userData, 
+static void GDALGMLJP2XPathErrorHandler(CPL_UNUSED void * userData,
                                         xmlErrorPtr error)
 {
     if( error->domain == XML_FROM_XPATH &&
@@ -772,7 +772,7 @@ static void GDALGMLJP2XPathErrorHandler(CPL_UNUSED void * userData,
     }
     else
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "An error occured in libxml2");
+        CPLError(CE_Failure, CPLE_AppDefined, "An error occurred in libxml2");
     }
 }
 
@@ -855,7 +855,10 @@ static void GDALGMLJP2XPathUUID(xmlXPathParserContextPtr ctxt, int nargs)
     osRet += GDALGMLJP2HexFormatter(rand() & 0xFF);
     osRet += "-";
     for( int i=0; i<6; i ++ )
+    {
+        /* coverity[dont_call] */
         osRet += GDALGMLJP2HexFormatter(rand() & 0xFF);
+    }
 
     valuePush(ctxt, xmlXPathNewString((const xmlChar*)osRet.c_str()));
 }
@@ -866,8 +869,15 @@ static void GDALGMLJP2XPathUUID(xmlXPathParserContextPtr ctxt, int nargs)
 /*                      GDALGMLJP2GenerateMetadata()                    */
 /************************************************************************/
 
-CPLXMLNode* GDALGMLJP2GenerateMetadata(const CPLString& osTemplateFile,
-                                       const CPLString& osSourceFile)
+CPLXMLNode* GDALGMLJP2GenerateMetadata(
+#ifdef HAVE_LIBXML2
+    const CPLString& osTemplateFile,
+    const CPLString& osSourceFile
+#else
+    const CPLString& /* osTemplateFile */,
+    const CPLString& /* osSourceFile */
+#endif
+)
 {
 #ifndef HAVE_LIBXML2
     return NULL;
@@ -877,12 +887,12 @@ CPLXMLNode* GDALGMLJP2GenerateMetadata(const CPLString& osTemplateFile,
         return NULL;
     CPLString osTemplate((const char*)pabyStr);
     CPLFree(pabyStr);
-    
+
     if( !VSIIngestFile( NULL, osSourceFile, &pabyStr, NULL, -1 ) )
         return NULL;
     CPLString osSource((const char*)pabyStr);
     CPLFree(pabyStr);
-    
+
     xmlDocPtr pDoc = xmlParseDoc((const xmlChar *)osSource.c_str());
     if( pDoc == NULL )
     {
@@ -894,7 +904,7 @@ CPLXMLNode* GDALGMLJP2GenerateMetadata(const CPLString& osTemplateFile,
     xmlXPathContextPtr pXPathCtx = xmlXPathNewContext(pDoc);
     if( pXPathCtx == NULL )
     {
-        xmlFreeDoc(pDoc); 
+        xmlFreeDoc(pDoc);
         return NULL;
     }
 
@@ -902,13 +912,13 @@ CPLXMLNode* GDALGMLJP2GenerateMetadata(const CPLString& osTemplateFile,
     xmlXPathRegisterFunc(pXPathCtx, (const xmlChar *)"uuid", GDALGMLJP2XPathUUID);
 
     pXPathCtx->error = GDALGMLJP2XPathErrorHandler;
-    
+
     GDALGMLJP2RegisterNamespaces(pXPathCtx, xmlDocGetRootElement(pDoc));
 
     CPLString osXMLRes = GDALGMLJP2EvalExpr(osTemplate, pXPathCtx, pDoc);
 
-    xmlXPathFreeContext(pXPathCtx); 
-    xmlFreeDoc(pDoc); 
+    xmlXPathFreeContext(pXPathCtx);
+    xmlFreeDoc(pDoc);
 
     return CPLParseXMLString(osXMLRes);
 #endif
diff --git a/gcore/gdaljp2metadatagenerator.h b/gcore/gdaljp2metadatagenerator.h
index 79b5df8..bf7faf0 100644
--- a/gcore/gdaljp2metadatagenerator.h
+++ b/gcore/gdaljp2metadatagenerator.h
@@ -1,7 +1,7 @@
 /******************************************************************************
- * $Id: gdaljp2metadatagenerator.h 29048 2015-04-29 14:48:33Z rouault $
+ * $Id: gdaljp2metadatagenerator.h 33694 2016-03-10 17:54:30Z goatbar $
  *
- * Project:  GDAL 
+ * Project:  GDAL
  * Purpose:  GDALJP2Metadata: metadata generator
  * Author:   Even Rouault <even dot rouault at spatialys dot com>
  *
diff --git a/gcore/gdaljp2structure.cpp b/gcore/gdaljp2structure.cpp
index 526027e..dac6edb 100644
--- a/gcore/gdaljp2structure.cpp
+++ b/gcore/gdaljp2structure.cpp
@@ -1,7 +1,7 @@
 /******************************************************************************
- * $Id: gdaljp2structure.cpp 28766 2015-03-24 23:32:21Z rouault $
+ * $Id: gdaljp2structure.cpp 33581 2016-02-27 07:27:13Z goatbar $
  *
- * Project:  GDAL 
+ * Project:  GDAL
  * Purpose:  GDALJP2Stucture - Dump structure of a JP2/J2K file
  * Author:   Even Rouault, <even dot rouault at spatialys dot com>
  *
@@ -122,8 +122,8 @@ static void DumpGeoTIFFBox(CPLXMLNode* psBox,
     if( pabyBoxData && poVRTDriver)
     {
         CPLString osTmpFilename(CPLSPrintf("/vsimem/tmp_%p.tif", oBox.GetFILE()));
-        VSIFCloseL(VSIFileFromMemBuffer(
-            osTmpFilename, pabyBoxData, nBoxDataLength, TRUE) );
+        CPL_IGNORE_RET_VAL(VSIFCloseL(VSIFileFromMemBuffer(
+            osTmpFilename, pabyBoxData, nBoxDataLength, TRUE) ));
         CPLPushErrorHandler(CPLQuietErrorHandler);
         GDALDataset* poDS = (GDALDataset*) GDALOpen(osTmpFilename, GA_ReadOnly);
         CPLPopErrorHandler();
@@ -136,7 +136,7 @@ static void DumpGeoTIFFBox(CPLXMLNode* psBox,
             CPLXMLNode* psXMLVRT = CPLParseXMLString((const char*)pabyXML);
             if( psXMLVRT )
             {
-                CPLXMLNode* psXMLContentNode = 
+                CPLXMLNode* psXMLContentNode =
                     CPLCreateXMLNode( psBox, CXT_Element, "DecodedGeoTIFF" );
                 psXMLContentNode->psChild = psXMLVRT;
                 CPLXMLNode* psPrev = NULL;
@@ -172,7 +172,7 @@ static void DumpFTYPBox(CPLXMLNode* psBox, GDALJP2Box& oBox)
     GByte* pabyBoxData = oBox.ReadBoxData();
     if( pabyBoxData )
     {
-        CPLXMLNode* psDecodedContent = 
+        CPLXMLNode* psDecodedContent =
             CPLCreateXMLNode( psBox, CXT_Element, "DecodedContent" );
         GIntBig nRemainingLength = nBoxDataLength;
         GByte* pabyIter = pabyBoxData;
@@ -221,7 +221,7 @@ static void DumpIHDRBox(CPLXMLNode* psBox, GDALJP2Box& oBox)
     GByte* pabyBoxData = oBox.ReadBoxData();
     if( pabyBoxData )
     {
-        CPLXMLNode* psDecodedContent = 
+        CPLXMLNode* psDecodedContent =
             CPLCreateXMLNode( psBox, CXT_Element, "DecodedContent" );
         GIntBig nRemainingLength = nBoxDataLength;
         GByte* pabyIter = pabyBoxData;
@@ -274,7 +274,7 @@ static void DumpIHDRBox(CPLXMLNode* psBox, GDALJP2Box& oBox)
         if( nRemainingLength >= 1 )
         {
             AddField(psDecodedContent, "IPR", *pabyIter);
-            pabyIter += 1;
+            /*pabyIter += 1;*/
             nRemainingLength -= 1;
         }
         if( nRemainingLength > 0 )
@@ -291,7 +291,7 @@ static void DumpBPCCBox(CPLXMLNode* psBox, GDALJP2Box& oBox)
     GByte* pabyBoxData = oBox.ReadBoxData();
     if( pabyBoxData )
     {
-        CPLXMLNode* psDecodedContent = 
+        CPLXMLNode* psDecodedContent =
             CPLCreateXMLNode( psBox, CXT_Element, "DecodedContent" );
         GIntBig nRemainingLength = nBoxDataLength;
         GByte* pabyIter = pabyBoxData;
@@ -316,7 +316,7 @@ static void DumpCOLRBox(CPLXMLNode* psBox, GDALJP2Box& oBox)
     GByte* pabyBoxData = oBox.ReadBoxData();
     if( pabyBoxData )
     {
-        CPLXMLNode* psDecodedContent = 
+        CPLXMLNode* psDecodedContent =
             CPLCreateXMLNode( psBox, CXT_Element, "DecodedContent" );
         GIntBig nRemainingLength = nBoxDataLength;
         GByte* pabyIter = pabyBoxData;
@@ -326,7 +326,7 @@ static void DumpCOLRBox(CPLXMLNode* psBox, GDALJP2Box& oBox)
             nMeth = *pabyIter;
             AddField(psDecodedContent, "METH", nMeth,
                         (nMeth == 0) ? "Enumerated Colourspace":
-                        (nMeth == 0) ? "Restricted ICC profile": NULL);
+                        (nMeth == 1) ? "Restricted ICC profile": NULL);
             pabyIter += 1;
             nRemainingLength -= 1;
         }
@@ -351,7 +351,7 @@ static void DumpCOLRBox(CPLXMLNode* psBox, GDALJP2Box& oBox)
                         (nVal == 16) ? "sRGB" :
                         (nVal == 17) ? "greyscale":
                         (nVal == 18) ? "sYCC" : NULL);
-            pabyIter += 4;
+            /*pabyIter += 4;*/
             nRemainingLength -= 4;
         }
         if( nRemainingLength > 0 )
@@ -368,7 +368,7 @@ static void DumpPCLRBox(CPLXMLNode* psBox, GDALJP2Box& oBox)
     GByte* pabyBoxData = oBox.ReadBoxData();
     if( pabyBoxData )
     {
-        CPLXMLNode* psDecodedContent = 
+        CPLXMLNode* psDecodedContent =
             CPLCreateXMLNode( psBox, CXT_Element, "DecodedContent" );
         GIntBig nRemainingLength = nBoxDataLength;
         GByte* pabyIter = pabyBoxData;
@@ -436,7 +436,7 @@ static void DumpCMAPBox(CPLXMLNode* psBox, GDALJP2Box& oBox)
     GByte* pabyBoxData = oBox.ReadBoxData();
     if( pabyBoxData )
     {
-        CPLXMLNode* psDecodedContent = 
+        CPLXMLNode* psDecodedContent =
             CPLCreateXMLNode( psBox, CXT_Element, "DecodedContent" );
         GIntBig nRemainingLength = nBoxDataLength;
         GByte* pabyIter = pabyBoxData;
@@ -482,7 +482,7 @@ static void DumpCDEFBox(CPLXMLNode* psBox, GDALJP2Box& oBox)
     GByte* pabyBoxData = oBox.ReadBoxData();
     if( pabyBoxData )
     {
-        CPLXMLNode* psDecodedContent = 
+        CPLXMLNode* psDecodedContent =
             CPLCreateXMLNode( psBox, CXT_Element, "DecodedContent" );
         GIntBig nRemainingLength = nBoxDataLength;
         GByte* pabyIter = pabyBoxData;
@@ -555,7 +555,7 @@ static void DumpRESxBox(CPLXMLNode* psBox, GDALJP2Box& oBox)
     char chC = oBox.GetType()[3];
     if( pabyBoxData )
     {
-        CPLXMLNode* psDecodedContent = 
+        CPLXMLNode* psDecodedContent =
             CPLCreateXMLNode( psBox, CXT_Element, "DecodedContent" );
         GIntBig nRemainingLength = nBoxDataLength;
         GByte* pabyIter = pabyBoxData;
@@ -611,7 +611,7 @@ static void DumpRESxBox(CPLXMLNode* psBox, GDALJP2Box& oBox)
         {
             AddField(psDecodedContent, CPLSPrintf("HR%cE", chC), *pabyIter);
             nExpH = *pabyIter;
-            pabyIter += 1;
+            /*pabyIter += 1;*/
             nRemainingLength -= 1;
         }
         if( nRemainingLength == 0 )
@@ -635,7 +635,7 @@ static void DumpRREQBox(CPLXMLNode* psBox, GDALJP2Box& oBox)
     GByte* pabyBoxData = oBox.ReadBoxData();
     if( pabyBoxData )
     {
-        CPLXMLNode* psDecodedContent = 
+        CPLXMLNode* psDecodedContent =
             CPLCreateXMLNode( psBox, CXT_Element, "DecodedContent" );
         GIntBig nRemainingLength = nBoxDataLength;
         GByte* pabyIter = pabyBoxData;
@@ -811,12 +811,16 @@ static CPLXMLNode* DumpJPK2CodeStream(CPLXMLNode* psBox,
                                       GIntBig nBoxDataOffset,
                                       GIntBig nBoxDataLength)
 {
-    VSIFSeekL(fp, nBoxDataOffset, SEEK_SET);
     GByte abyMarker[2];
     CPLXMLNode* psCSBox = CPLCreateXMLNode( psBox, CXT_Element, "JP2KCodeStream" );
+    if( VSIFSeekL(fp, nBoxDataOffset, SEEK_SET) != 0 )
+    {
+        AddError(psCSBox, "Cannot read codestream", 0);
+        return psCSBox;
+    }
     GByte* pabyMarkerData = (GByte*)CPLMalloc(65535+1);
     GIntBig nNextTileOffset = 0;
-    while( TRUE )
+    while( true )
     {
         GIntBig nOffset = (GIntBig)VSIFTellL(fp);
         if( nOffset == nBoxDataOffset + nBoxDataLength )
@@ -839,18 +843,18 @@ static CPLXMLNode* DumpJPK2CodeStream(CPLXMLNode* psBox,
         if( abyMarker[1] == 0x93 )
         {
             GIntBig nMarkerSize = 0;
-            int bBreak = FALSE;
+            bool bBreak = false;
             if( nNextTileOffset == 0 )
             {
                 nMarkerSize = (nBoxDataOffset + nBoxDataLength - 2) - nOffset - 2;
-                VSIFSeekL(fp, nBoxDataOffset + nBoxDataLength - 2, SEEK_SET);
-                if( VSIFReadL(abyMarker, 2, 1, fp) != 1 ||
+                if( VSIFSeekL(fp, nBoxDataOffset + nBoxDataLength - 2, SEEK_SET) != 0 ||
+                    VSIFReadL(abyMarker, 2, 1, fp) != 1 ||
                     abyMarker[0] != 0xFF || abyMarker[1] != 0xD9 )
                 {
                     /* autotest/gdrivers/data/rgb16_ecwsdk.jp2 does not end */
                     /* with a EOC... */
                     nMarkerSize += 2;
-                    bBreak = TRUE;
+                    bBreak = true;
                 }
             }
             else if( nNextTileOffset >= nOffset + 2 )
@@ -867,7 +871,8 @@ static CPLXMLNode* DumpJPK2CodeStream(CPLXMLNode* psBox,
             }
             else if( nNextTileOffset && nNextTileOffset >= nOffset + 2 )
             {
-                VSIFSeekL(fp, nNextTileOffset, SEEK_SET);
+                if( VSIFSeekL(fp, nNextTileOffset, SEEK_SET) != 0 )
+                    AddError(psCSBox, "Cannot seek to", nNextTileOffset);
                 nNextTileOffset = 0;
             }
             else
@@ -1001,7 +1006,7 @@ static CPLXMLNode* DumpJPK2CodeStream(CPLXMLNode* psBox,
             for(int i=0;i<CSiz;i++)
             {
                 READ_MARKER_FIELD_UINT8_COMMENT(CPLSPrintf("Ssiz%d", i),
-                                                GetInterpretationOfBPC(nLastVal));
+                        GetInterpretationOfBPC(static_cast<GByte>(nLastVal)));
                 READ_MARKER_FIELD_UINT8(CPLSPrintf("XRsiz%d", i));
                 READ_MARKER_FIELD_UINT8(CPLSPrintf("YRsiz%d", i));
             }
@@ -1012,13 +1017,13 @@ static CPLXMLNode* DumpJPK2CodeStream(CPLXMLNode* psBox,
         }
         else if( abyMarker[1] == 0x52 ) /* COD */
         {
-            int bHasPrecincts = TRUE;
+            bool bHasPrecincts = false;
             if( nRemainingMarkerSize >= 1 ) {
                 nLastVal = *pabyMarkerDataIter;
                 CPLString osInterp;
                 if( nLastVal & 0x1 )
                 {
-                    bHasPrecincts = TRUE;
+                    bHasPrecincts = true;
                     osInterp += "User defined precincts";
                 }
                 else
@@ -1039,7 +1044,7 @@ static CPLXMLNode* DumpJPK2CodeStream(CPLXMLNode* psBox,
             }
             else {
                 AddError(psMarker, CPLSPrintf("Cannot read field %s", "Scod"));
-                nLastVal = 0;
+                /*nLastVal = 0;*/
             }
             READ_MARKER_FIELD_UINT8_COMMENT("SGcod_Progress",
                                             (nLastVal == 0) ? "LRCP" :
@@ -1090,7 +1095,7 @@ static CPLXMLNode* DumpJPK2CodeStream(CPLXMLNode* psBox,
             }
             else {
                 AddError(psMarker, CPLSPrintf("Cannot read field %s", "SPcod_cbstyle"));
-                nLastVal = 0;
+                /*nLastVal = 0;*/
             }
             READ_MARKER_FIELD_UINT8_COMMENT("SPcod_transformation",
                                             (nLastVal == 0) ? "9-7 irreversible":
@@ -1120,7 +1125,6 @@ static CPLXMLNode* DumpJPK2CodeStream(CPLXMLNode* psBox,
         }
         else if( abyMarker[1] == 0x55 ) /* TLM */
         {
-            CPLXMLNode* psMarker = CreateMarker( psCSBox, "TLM", nOffset, nMarkerSize );
             READ_MARKER_FIELD_UINT8("Ztlm");
             int ST = 0, SP = 0;
             READ_MARKER_FIELD_UINT8_COMMENT("Stlm",
@@ -1185,7 +1189,11 @@ static CPLXMLNode* DumpJPK2CodeStream(CPLXMLNode* psBox,
             }
         }
 
-        VSIFSeekL(fp, nOffset + 2 + nMarkerSize, SEEK_SET);
+        if( VSIFSeekL(fp, nOffset + 2 + nMarkerSize, SEEK_SET) != 0 )
+        {
+            AddError(psCSBox, "Cannot seek to next marker", nOffset + 2 + nMarkerSize);
+            break;
+        }
     }
     CPLFree(pabyMarkerData);
     return psCSBox;
@@ -1201,7 +1209,7 @@ void GDALGetJPEG2000StructureInternal(CPLXMLNode* psParent,
                                       GDALJP2Box* poParentBox,
                                       char** papszOptions)
 {
-    static const char* szHex = "0123456789ABCDEF";
+    static const char* const szHex = "0123456789ABCDEF";
     GDALJP2Box oBox( fp );
     if( oBox.ReadFirstChild(poParentBox) )
     {
@@ -1290,13 +1298,13 @@ void GDALGetJPEG2000StructureInternal(CPLXMLNode* psParent,
                             }
                             if( psXMLContentBox )
                             {
-                                CPLXMLNode* psXMLContentNode = 
+                                CPLXMLNode* psXMLContentNode =
                                     CPLCreateXMLNode( psBox, CXT_Element, "XMLContent" );
                                 psXMLContentNode->psChild = psXMLContentBox;
                             }
                             else
                             {
-                                CPLCreateXMLNode( 
+                                CPLCreateXMLNode(
                                     CPLCreateXMLNode( psBox, CXT_Element, "TextContent" ),
                                         CXT_Text, (const char*)pabyBoxData);
                             }
@@ -1397,20 +1405,22 @@ CPLXMLNode* GDALGetJPEG2000Structure(const char* pszFilename,
          memcmp(abyHeader + 4, jp2_box_jp, sizeof(jp2_box_jp)) != 0) )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "%s is not a JPEG2000 file", pszFilename);
-        VSIFCloseL(fp);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
         return NULL;
     }
-    
+
     CPLXMLNode* psParent = NULL;
     if( memcmp(abyHeader, jpc_header, sizeof(jpc_header)) == 0 )
     {
         if( CSLFetchBoolean(papszOptions, "CODESTREAM", FALSE) ||
             CSLFetchBoolean(papszOptions, "ALL", FALSE) )
         {
-            VSIFSeekL(fp, 0, SEEK_END);
-            GIntBig nBoxDataLength = (GIntBig)VSIFTellL(fp);
-            psParent = DumpJPK2CodeStream(NULL, fp, 0, nBoxDataLength);
-            CPLAddXMLAttributeAndValue(psParent, "filename", pszFilename );
+            if( VSIFSeekL(fp, 0, SEEK_END) == 0 )
+            {
+                GIntBig nBoxDataLength = (GIntBig)VSIFTellL(fp);
+                psParent = DumpJPK2CodeStream(NULL, fp, 0, nBoxDataLength);
+                CPLAddXMLAttributeAndValue(psParent, "filename", pszFilename );
+            }
         }
     }
     else
@@ -1420,6 +1430,6 @@ CPLXMLNode* GDALGetJPEG2000Structure(const char* pszFilename,
         GDALGetJPEG2000StructureInternal(psParent, fp, NULL, papszOptions );
     }
 
-    VSIFCloseL(fp);
+    CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
     return psParent;
 }
diff --git a/gcore/gdalmajorobject.cpp b/gcore/gdalmajorobject.cpp
index a94e6d9..9ccba0c 100644
--- a/gcore/gdalmajorobject.cpp
+++ b/gcore/gdalmajorobject.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalmajorobject.cpp 27110 2014-03-28 21:29:20Z rouault $
+ * $Id: gdalmajorobject.cpp 33694 2016-03-10 17:54:30Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Base class for objects with metadata, etc.
@@ -31,7 +31,7 @@
 #include "gdal_priv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: gdalmajorobject.cpp 27110 2014-03-28 21:29:20Z rouault $");
+CPL_CVSID("$Id: gdalmajorobject.cpp 33694 2016-03-10 17:54:30Z goatbar $");
 
 /************************************************************************/
 /*                          GDALMajorObject()                           */
@@ -61,14 +61,14 @@ GDALMajorObject::~GDALMajorObject()
 /************************************************************************/
 
 /**
- * \brief Fetch object description. 
+ * \brief Fetch object description.
  *
  * The semantics of the returned description are specific to the derived
  * type.  For GDALDatasets it is the dataset name.  For GDALRasterBands
  * it is actually a description (if supported) or "".
  *
  * This method is the same as the C function GDALGetDescription().
- * 
+ *
  * @return non-null pointer to internal description string.
  */
 
@@ -83,10 +83,10 @@ const char *GDALMajorObject::GetDescription() const
 /************************************************************************/
 
 /**
- * \brief Fetch object description. 
+ * \brief Fetch object description.
  *
  * @see GDALMajorObject::GetDescription()
- */ 
+ */
 
 const char * CPL_STDCALL GDALGetDescription( GDALMajorObjectH hObject )
 
@@ -101,19 +101,19 @@ const char * CPL_STDCALL GDALGetDescription( GDALMajorObjectH hObject )
 /************************************************************************/
 
 /**
- * \brief Set object description. 
+ * \brief Set object description.
  *
  * The semantics of the description are specific to the derived
  * type.  For GDALDatasets it is the dataset name.  For GDALRasterBands
  * it is actually a description (if supported) or "".
  *
- * Normally application code should not set the "description" for 
- * GDALDatasets.  It is handled internally.  
+ * Normally application code should not set the "description" for
+ * GDALDatasets.  It is handled internally.
  *
  * This method is the same as the C function GDALSetDescription().
  */
 
-void GDALMajorObject::SetDescription( const char * pszNewDesc ) 
+void GDALMajorObject::SetDescription( const char * pszNewDesc )
 
 {
     sDescription = pszNewDesc;
@@ -124,10 +124,10 @@ void GDALMajorObject::SetDescription( const char * pszNewDesc )
 /************************************************************************/
 
 /**
- * \brief Set object description. 
+ * \brief Set object description.
  *
  * @see GDALMajorObject::SetDescription()
- */ 
+ */
 
 void CPL_STDCALL GDALSetDescription( GDALMajorObjectH hObject, const char *pszNewDesc )
 
@@ -147,7 +147,7 @@ void CPL_STDCALL GDALSetDescription( GDALMajorObjectH hObject, const char *pszNe
  * The returned string list is the list of (non-empty) metadata domains.
  *
  * This method does the same thing as the C function GDALGetMetadataDomainList().
- * 
+ *
  * @return NULL or a string list. Must be freed with CSLDestroy()
  *
  * @since GDAL 1.11
@@ -207,9 +207,9 @@ char **GDALMajorObject::BuildMetadataDomainList(char** papszList, int bCheckNonE
  * @see GDALMajorObject::GetMetadataDomainList()
  *
  * @since GDAL 1.11
- */ 
+ */
 
-char ** CPL_STDCALL 
+char ** CPL_STDCALL
 GDALGetMetadataDomainList( GDALMajorObjectH hObject)
 
 {
@@ -226,18 +226,18 @@ GDALGetMetadataDomainList( GDALMajorObjectH hObject)
  * \brief Fetch metadata.
  *
  * The returned string list is owned by the object, and may change at
- * any time.  It is formated as a "Name=value" list with the last pointer
- * value being NULL.  Use the the CPL StringList functions such as 
- * CSLFetchNameValue() to manipulate it. 
+ * any time.  It is formatted as a "Name=value" list with the last pointer
+ * value being NULL.  Use the CPL StringList functions such as
+ * CSLFetchNameValue() to manipulate it.
  *
- * Note that relatively few formats return any metadata at this time. 
+ * Note that relatively few formats return any metadata at this time.
  *
  * This method does the same thing as the C function GDALGetMetadata().
  *
  * @param pszDomain the domain of interest.  Use "" or NULL for the default
  * domain.
- * 
- * @return NULL or a string list. 
+ *
+ * @return NULL or a string list.
  */
 
 char **GDALMajorObject::GetMetadata( const char * pszDomain )
@@ -254,9 +254,9 @@ char **GDALMajorObject::GetMetadata( const char * pszDomain )
  * \brief Fetch metadata.
  *
  * @see GDALMajorObject::GetMetadata()
- */ 
+ */
 
-char ** CPL_STDCALL 
+char ** CPL_STDCALL
 GDALGetMetadata( GDALMajorObjectH hObject, const char * pszDomain )
 
 {
@@ -269,21 +269,21 @@ GDALGetMetadata( GDALMajorObjectH hObject, const char * pszDomain )
 /*                            SetMetadata()                             */
 /************************************************************************/
 
-/** 
- * \brief Set metadata. 
+/**
+ * \brief Set metadata.
  *
  * The C function GDALSetMetadata() does the same thing as this method.
  *
  * @param papszMetadataIn the metadata in name=value string list format to
- * apply.  
+ * apply.
  * @param pszDomain the domain of interest.  Use "" or NULL for the default
- * domain. 
+ * domain.
  * @return CE_None on success, CE_Failure on failure and CE_Warning if the
- * metadata has been accepted, but is likely not maintained persistently 
+ * metadata has been accepted, but is likely not maintained persistently
  * by the underlying object between sessions.
  */
 
-CPLErr GDALMajorObject::SetMetadata( char ** papszMetadataIn, 
+CPLErr GDALMajorObject::SetMetadata( char ** papszMetadataIn,
                                      const char * pszDomain )
 
 {
@@ -296,13 +296,13 @@ CPLErr GDALMajorObject::SetMetadata( char ** papszMetadataIn,
 /************************************************************************/
 
 /**
- * \brief Set metadata. 
+ * \brief Set metadata.
  *
  * @see GDALMajorObject::SetMetadata()
- */ 
+ */
 
-CPLErr CPL_STDCALL 
-GDALSetMetadata( GDALMajorObjectH hObject, char **papszMD, 
+CPLErr CPL_STDCALL
+GDALSetMetadata( GDALMajorObjectH hObject, char **papszMD,
                  const char *pszDomain )
 
 {
@@ -328,7 +328,7 @@ GDALSetMetadata( GDALMajorObjectH hObject, char **papszMD,
  * copy of the value string on success.
  */
 
-const char *GDALMajorObject::GetMetadataItem( const char * pszName, 
+const char *GDALMajorObject::GetMetadataItem( const char * pszName,
                                               const char * pszDomain )
 
 {
@@ -343,10 +343,10 @@ const char *GDALMajorObject::GetMetadataItem( const char * pszName,
  * \brief Fetch single metadata item.
  *
  * @see GDALMajorObject::GetMetadataItem()
- */ 
+ */
 
-const char * CPL_STDCALL GDALGetMetadataItem( GDALMajorObjectH hObject, 
-                                 const char *pszName, 
+const char * CPL_STDCALL GDALGetMetadataItem( GDALMajorObjectH hObject,
+                                 const char *pszName,
                                  const char *pszDomain )
 
 {
@@ -371,8 +371,8 @@ const char * CPL_STDCALL GDALGetMetadataItem( GDALMajorObjectH hObject,
  * @return CE_None on success, or an error code on failure.
  */
 
-CPLErr GDALMajorObject::SetMetadataItem( const char * pszName, 
-                                         const char * pszValue, 
+CPLErr GDALMajorObject::SetMetadataItem( const char * pszName,
+                                         const char * pszValue,
                                          const char * pszDomain )
 
 {
@@ -388,11 +388,11 @@ CPLErr GDALMajorObject::SetMetadataItem( const char * pszName,
  * \brief Set single metadata item.
  *
  * @see GDALMajorObject::SetMetadataItem()
- */ 
+ */
 
-CPLErr CPL_STDCALL 
-GDALSetMetadataItem( GDALMajorObjectH hObject, 
-                     const char *pszName, const char *pszValue, 
+CPLErr CPL_STDCALL
+GDALSetMetadataItem( GDALMajorObjectH hObject,
+                     const char *pszName, const char *pszValue,
                      const char *pszDomain )
 
 {
@@ -421,4 +421,3 @@ void GDALMajorObject::SetMOFlags( int nNewFlags )
 {
     nFlags = nNewFlags;
 }
-
diff --git a/gcore/gdalmultidomainmetadata.cpp b/gcore/gdalmultidomainmetadata.cpp
index e843304..57f8aba 100644
--- a/gcore/gdalmultidomainmetadata.cpp
+++ b/gcore/gdalmultidomainmetadata.cpp
@@ -1,9 +1,9 @@
 /******************************************************************************
- * $Id: gdalmultidomainmetadata.cpp 29038 2015-04-28 09:03:36Z rouault $
+ * $Id: gdalmultidomainmetadata.cpp 33694 2016-03-10 17:54:30Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALMultiDomainMetadata class.  This class
- *           manages metadata items for a variable list of domains. 
+ *           manages metadata items for a variable list of domains.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -33,7 +33,7 @@
 #include "cpl_string.h"
 #include <map>
 
-CPL_CVSID("$Id: gdalmultidomainmetadata.cpp 29038 2015-04-28 09:03:36Z rouault $");
+CPL_CVSID("$Id: gdalmultidomainmetadata.cpp 33694 2016-03-10 17:54:30Z goatbar $");
 
 /************************************************************************/
 /*                      GDALMultiDomainMetadata()                       */
@@ -100,7 +100,7 @@ char **GDALMultiDomainMetadata::GetMetadata( const char *pszDomain )
 /*                            SetMetadata()                             */
 /************************************************************************/
 
-CPLErr GDALMultiDomainMetadata::SetMetadata( char **papszMetadata, 
+CPLErr GDALMultiDomainMetadata::SetMetadata( char **papszMetadata,
                                              const char *pszDomain )
 
 {
@@ -116,7 +116,7 @@ CPLErr GDALMultiDomainMetadata::SetMetadata( char **papszMetadata,
         papszDomainList = CSLAddString( papszDomainList, pszDomain );
         nDomainCount = CSLCount( papszDomainList );
 
-        papoMetadataLists = (CPLStringList **) 
+        papoMetadataLists = (CPLStringList **)
             CPLRealloc( papoMetadataLists, sizeof(void*)*(nDomainCount+1) );
         papoMetadataLists[nDomainCount] = NULL;
         papoMetadataLists[nDomainCount-1] = new CPLStringList();
@@ -127,7 +127,7 @@ CPLErr GDALMultiDomainMetadata::SetMetadata( char **papszMetadata,
 
     // we want to mark name/value pair domains as being sorted for fast
     // access.
-    if( !EQUALN(pszDomain,"xml:",4) && !EQUAL(pszDomain, "SUBDATASETS") )
+    if( !STARTS_WITH_CI(pszDomain, "xml:") && !EQUAL(pszDomain, "SUBDATASETS") )
         papoMetadataLists[iDomain]->Sort();
 
     return CE_None;
@@ -137,7 +137,7 @@ CPLErr GDALMultiDomainMetadata::SetMetadata( char **papszMetadata,
 /*                          GetMetadataItem()                           */
 /************************************************************************/
 
-const char *GDALMultiDomainMetadata::GetMetadataItem( const char *pszName, 
+const char *GDALMultiDomainMetadata::GetMetadataItem( const char *pszName,
                                                       const char *pszDomain )
 
 {
@@ -197,7 +197,7 @@ int GDALMultiDomainMetadata::XMLInit( CPLXMLNode *psTree, CPL_UNUSED int bMerge
 /* ==================================================================== */
 /*      Process all <Metadata> elements, each for one domain.           */
 /* ==================================================================== */
-    for( psMetadata = psTree->psChild; 
+    for( psMetadata = psTree->psChild;
          psMetadata != NULL; psMetadata = psMetadata->psNext )
     {
         CPLXMLNode *psMDI;
@@ -210,14 +210,14 @@ int GDALMultiDomainMetadata::XMLInit( CPLXMLNode *psTree, CPL_UNUSED int bMerge
         pszDomain = CPLGetXMLValue( psMetadata, "domain", "" );
         pszFormat = CPLGetXMLValue( psMetadata, "format", "" );
 
-        // Make sure we have a CPLStringList for this domain, 
+        // Make sure we have a CPLStringList for this domain,
         // without wiping out an existing one.
-        if( GetMetadata( pszDomain ) == NULL )  
+        if( GetMetadata( pszDomain ) == NULL )
             SetMetadata( NULL, pszDomain );
 
         int iDomain = CSLFindString( papszDomainList, pszDomain );
         CPLAssert( iDomain != -1 );
-        
+
         CPLStringList *poMDList = papoMetadataLists[iDomain];
 
 /* -------------------------------------------------------------------- */
@@ -231,7 +231,7 @@ int GDALMultiDomainMetadata::XMLInit( CPLXMLNode *psTree, CPL_UNUSED int bMerge
             psSubDoc = psMetadata->psChild;
             while( psSubDoc != NULL && psSubDoc->eType == CXT_Attribute )
                 psSubDoc = psSubDoc->psNext;
-            
+
             char *pszDoc = CPLSerializeXMLTree( psSubDoc );
 
             poMDList->Clear();
@@ -275,8 +275,8 @@ CPLXMLNode *GDALMultiDomainMetadata::Serialize()
 {
     CPLXMLNode *psFirst = NULL;
 
-    for( int iDomain = 0; 
-         papszDomainList != NULL && papszDomainList[iDomain] != NULL; 
+    for( int iDomain = 0;
+         papszDomainList != NULL && papszDomainList[iDomain] != NULL;
          iDomain++)
     {
         char **papszMD = papoMetadataLists[iDomain]->List();
@@ -285,27 +285,27 @@ CPLXMLNode *GDALMultiDomainMetadata::Serialize()
             continue;
 
         CPLXMLNode *psMD;
-        int bFormatXML = FALSE;
-        
+        bool bFormatXML = false;
+
         psMD = CPLCreateXMLNode( NULL, CXT_Element, "Metadata" );
 
         if( strlen( papszDomainList[iDomain] ) > 0 )
-            CPLCreateXMLNode( 
-                CPLCreateXMLNode( psMD, CXT_Attribute, "domain" ), 
+            CPLCreateXMLNode(
+                CPLCreateXMLNode( psMD, CXT_Attribute, "domain" ),
                 CXT_Text, papszDomainList[iDomain] );
 
-        if( EQUALN(papszDomainList[iDomain],"xml:",4) 
+        if( STARTS_WITH_CI(papszDomainList[iDomain], "xml:")
             && CSLCount(papszMD) == 1 )
         {
             CPLXMLNode *psValueAsXML = CPLParseXMLString( papszMD[0] );
             if( psValueAsXML != NULL )
             {
-                bFormatXML = TRUE;
+                bFormatXML = true;
 
-                CPLCreateXMLNode( 
-                    CPLCreateXMLNode( psMD, CXT_Attribute, "format" ), 
+                CPLCreateXMLNode(
+                    CPLCreateXMLNode( psMD, CXT_Attribute, "format" ),
                     CXT_Text, "xml" );
-                
+
                 CPLAddXMLChild( psMD, psValueAsXML );
             }
         }
@@ -318,16 +318,16 @@ CPLXMLNode *GDALMultiDomainMetadata::Serialize()
             {
                 psLastChild = psMD->psChild;
                 while( psLastChild->psNext != NULL )
-                    psLastChild = psLastChild->psNext; 
+                    psLastChild = psLastChild->psNext;
             }
             for( int i = 0; papszMD != NULL && papszMD[i] != NULL; i++ )
             {
                 const char *pszRawValue;
                 char *pszKey = NULL;
                 CPLXMLNode *psMDI;
-                
+
                 pszRawValue = CPLParseNameValue( papszMD[i], &pszKey );
-                
+
                 psMDI = CPLCreateXMLNode( NULL, CXT_Element, "MDI" );
                 if( psLastChild == NULL )
                     psMD->psChild = psMDI;
@@ -337,11 +337,11 @@ CPLXMLNode *GDALMultiDomainMetadata::Serialize()
 
                 CPLSetXMLValue( psMDI, "#key", pszKey );
                 CPLCreateXMLNode( psMDI, CXT_Text, pszRawValue );
-                
+
                 CPLFree( pszKey );
             }
         }
-            
+
         if( psFirst == NULL )
             psFirst = psMD;
         else
diff --git a/gcore/gdalnodatamaskband.cpp b/gcore/gdalnodatamaskband.cpp
index 56b348b..e268c5a 100644
--- a/gcore/gdalnodatamaskband.cpp
+++ b/gcore/gdalnodatamaskband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalnodatamaskband.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: gdalnodatamaskband.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALNoDataMaskBand, a class implementing all
@@ -31,17 +31,18 @@
 
 #include "gdal_priv.h"
 
-CPL_CVSID("$Id: gdalnodatamaskband.cpp 28053 2014-12-04 09:31:07Z rouault $");
+CPL_CVSID("$Id: gdalnodatamaskband.cpp 33808 2016-03-29 21:15:28Z goatbar $");
 
 /************************************************************************/
 /*                        GDALNoDataMaskBand()                          */
 /************************************************************************/
 
-GDALNoDataMaskBand::GDALNoDataMaskBand( GDALRasterBand *poParent )
+GDALNoDataMaskBand::GDALNoDataMaskBand( GDALRasterBand *poParentIn )
 
 {
     poDS = NULL;
     nBand = 0;
+    poParent = poParentIn;
 
     nRasterXSize = poParent->GetXSize();
     nRasterYSize = poParent->GetYSize();
@@ -49,7 +50,6 @@ GDALNoDataMaskBand::GDALNoDataMaskBand( GDALRasterBand *poParent )
     eDataType = GDT_Byte;
     poParent->GetBlockSize( &nBlockXSize, &nBlockYSize );
 
-    this->poParent = poParent;
     dfNoDataValue = poParent->GetNoDataValue();
 }
 
@@ -71,11 +71,11 @@ CPLErr GDALNoDataMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
 
 {
     GDALDataType eWrkDT;
-  
+
 /* -------------------------------------------------------------------- */
 /*      Decide on a working type.                                       */
 /* -------------------------------------------------------------------- */
-    switch( poParent->GetRasterDataType() ) 
+    switch( poParent->GetRasterDataType() )
     {
       case GDT_Byte:
         eWrkDT = GDT_Byte;
@@ -97,12 +97,12 @@ CPLErr GDALNoDataMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
       case GDT_CFloat32:
         eWrkDT = GDT_Float32;
         break;
-    
+
       case GDT_Float64:
       case GDT_CFloat64:
         eWrkDT = GDT_Float64;
         break;
-    
+
       default:
         CPLAssert( FALSE );
         eWrkDT = GDT_Float64;
@@ -112,14 +112,13 @@ CPLErr GDALNoDataMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
 /* -------------------------------------------------------------------- */
 /*      Read the image data.                                            */
 /* -------------------------------------------------------------------- */
-    GByte *pabySrc;
     CPLErr eErr;
 
-    pabySrc = (GByte *) VSIMalloc3( GDALGetDataTypeSize(eWrkDT)/8, nBlockXSize, nBlockYSize );
+    GByte *pabySrc = static_cast<GByte *>(
+        VSI_MALLOC3_VERBOSE( GDALGetDataTypeSizeBytes(eWrkDT),
+                             nBlockXSize, nBlockYSize ) );
     if (pabySrc == NULL)
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory,
-                  "GDALNoDataMaskBand::IReadBlock: Out of memory for buffer." );
         return CE_Failure;
     }
 
@@ -135,14 +134,17 @@ CPLErr GDALNoDataMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
     {
         /* memset the whole buffer to avoid Valgrind warnings in case we can't */
         /* fetch a full block */
-        memset(pabySrc, 0, GDALGetDataTypeSize(eWrkDT)/8 * nBlockXSize * nBlockYSize );
+        memset( pabySrc, 0,
+                GDALGetDataTypeSizeBytes(eWrkDT) * nBlockXSize * nBlockYSize );
     }
 
     eErr = poParent->RasterIO( GF_Read,
-                               nXBlockOff * nBlockXSize, nYBlockOff * nBlockYSize,
+                               nXBlockOff * nBlockXSize,
+                               nYBlockOff * nBlockYSize,
                                nXSizeRequest, nYSizeRequest,
                                pabySrc, nXSizeRequest, nYSizeRequest,
-                               eWrkDT, 0, nBlockXSize * (GDALGetDataTypeSize(eWrkDT)/8),
+                               eWrkDT, 0,
+                               nBlockXSize * GDALGetDataTypeSizeBytes(eWrkDT),
                                NULL );
     if( eErr != CE_None )
     {
diff --git a/gcore/gdalnodatavaluesmaskband.cpp b/gcore/gdalnodatavaluesmaskband.cpp
index 42a07f1..ef1f67b 100644
--- a/gcore/gdalnodatavaluesmaskband.cpp
+++ b/gcore/gdalnodatavaluesmaskband.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: gdalnodatavaluesmaskband.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: gdalnodatavaluesmaskband.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  GDAL Core
- * Purpose:  Implementation of GDALNoDataValuesMaskBand, a class implementing 
+ * Purpose:  Implementation of GDALNoDataValuesMaskBand, a class implementing
  *           a default band mask based on the NODATA_VALUES metadata item.
  *           A pixel is considered nodata in all bands if and only if all bands
  *           match the corresponding value in the NODATA_VALUES tuple
@@ -32,28 +32,28 @@
 
 #include "gdal_priv.h"
 
-CPL_CVSID("$Id: gdalnodatavaluesmaskband.cpp 28053 2014-12-04 09:31:07Z rouault $");
+CPL_CVSID("$Id: gdalnodatavaluesmaskband.cpp 33808 2016-03-29 21:15:28Z goatbar $");
 
 /************************************************************************/
 /*                   GDALNoDataValuesMaskBand()                         */
 /************************************************************************/
 
-GDALNoDataValuesMaskBand::GDALNoDataValuesMaskBand( GDALDataset* poDS )
+GDALNoDataValuesMaskBand::GDALNoDataValuesMaskBand( GDALDataset* poDSIn )
 
 {
-    const char* pszNoDataValues = poDS->GetMetadataItem("NODATA_VALUES");
+    const char* pszNoDataValues = poDSIn->GetMetadataItem("NODATA_VALUES");
     char** papszNoDataValues = CSLTokenizeStringComplex(pszNoDataValues, " ", FALSE, FALSE);
 
     int i;
-    padfNodataValues = (double*)CPLMalloc(sizeof(double) * poDS->GetRasterCount());
-    for(i=0;i<poDS->GetRasterCount();i++)
+    padfNodataValues = (double*)CPLMalloc(sizeof(double) * poDSIn->GetRasterCount());
+    for(i=0;i<poDSIn->GetRasterCount();i++)
     {
         padfNodataValues[i] = CPLAtof(papszNoDataValues[i]);
     }
 
     CSLDestroy(papszNoDataValues);
 
-    this->poDS = poDS;
+    poDS = poDSIn;
     nBand = 0;
 
     nRasterXSize = poDS->GetRasterXSize();
@@ -83,11 +83,11 @@ CPLErr GDALNoDataValuesMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
 {
     int iBand;
     GDALDataType eWrkDT;
-  
+
 /* -------------------------------------------------------------------- */
 /*      Decide on a working type.                                       */
 /* -------------------------------------------------------------------- */
-    switch( poDS->GetRasterBand(1)->GetRasterDataType() ) 
+    switch( poDS->GetRasterBand(1)->GetRasterDataType() )
     {
       case GDT_Byte:
         eWrkDT = GDT_Byte;
@@ -109,12 +109,12 @@ CPLErr GDALNoDataValuesMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
       case GDT_CFloat32:
         eWrkDT = GDT_Float32;
         break;
-    
+
       case GDT_Float64:
       case GDT_CFloat64:
         eWrkDT = GDT_Float64;
         break;
-    
+
       default:
         CPLAssert( FALSE );
         eWrkDT = GDT_Float64;
@@ -124,15 +124,14 @@ CPLErr GDALNoDataValuesMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
 /* -------------------------------------------------------------------- */
 /*      Read the image data.                                            */
 /* -------------------------------------------------------------------- */
-    GByte *pabySrc;
     CPLErr eErr;
 
     int nBands = poDS->GetRasterCount();
-    pabySrc = (GByte *) VSIMalloc3( nBands * GDALGetDataTypeSize(eWrkDT)/8, nBlockXSize, nBlockYSize );
+    GByte *pabySrc = static_cast<GByte *>(
+        VSI_MALLOC3_VERBOSE( nBands * GDALGetDataTypeSizeBytes(eWrkDT),
+                             nBlockXSize, nBlockYSize ) );
     if (pabySrc == NULL)
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory,
-                  "GDALNoDataValuesMaskBand::IReadBlock: Out of memory for buffer." );
         return CE_Failure;
     }
 
@@ -147,20 +146,28 @@ CPLErr GDALNoDataValuesMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
     {
         /* memset the whole buffer to avoid Valgrind warnings in case we can't */
         /* fetch a full block */
-        memset(pabySrc, 0, nBands * GDALGetDataTypeSize(eWrkDT)/8 * nBlockXSize * nBlockYSize );
+        memset( pabySrc, 0,
+                nBands * GDALGetDataTypeSizeBytes(eWrkDT) *
+                nBlockXSize * nBlockYSize );
     }
 
     int nBlockOffsetPixels = nBlockXSize * nBlockYSize;
-    int nBandOffsetByte = (GDALGetDataTypeSize(eWrkDT)/8) * nBlockXSize * nBlockYSize;
+    const int nBandOffsetByte =
+        GDALGetDataTypeSizeBytes(eWrkDT) * nBlockXSize * nBlockYSize;
     for(iBand=0;iBand<nBands;iBand++)
     {
         eErr = poDS->GetRasterBand(iBand + 1)->RasterIO(
-                                   GF_Read,
-                                   nXBlockOff * nBlockXSize, nYBlockOff * nBlockYSize,
-                                   nXSizeRequest, nYSizeRequest,
-                                   pabySrc + iBand * nBandOffsetByte, nXSizeRequest, nYSizeRequest,
-                                   eWrkDT, 0, nBlockXSize * (GDALGetDataTypeSize(eWrkDT)/8),
-                                   NULL);
+            GF_Read,
+            nXBlockOff * nBlockXSize,
+            nYBlockOff * nBlockYSize,
+            nXSizeRequest,
+            nYSizeRequest,
+            pabySrc + iBand * nBandOffsetByte,
+            nXSizeRequest,
+            nYSizeRequest,
+            eWrkDT, 0,
+            nBlockXSize * GDALGetDataTypeSizeBytes(eWrkDT),
+            NULL );
         if( eErr != CE_None )
             return eErr;
     }
diff --git a/gcore/gdalopeninfo.cpp b/gcore/gdalopeninfo.cpp
index 6211947..9b50745 100644
--- a/gcore/gdalopeninfo.cpp
+++ b/gcore/gdalopeninfo.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalopeninfo.cpp 29107 2015-05-02 11:23:26Z rouault $
+ * $Id: gdalopeninfo.cpp 33758 2016-03-21 09:06:22Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALOpenInfo class.
@@ -28,14 +28,19 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_priv.h"
+#include "gdal_priv.h"  // Must be included first for mingw VSIStatBufL.
 #include "cpl_conv.h"
+#include "cpl_vsi.h"
 
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
 
-CPL_CVSID("$Id: gdalopeninfo.cpp 29107 2015-05-02 11:23:26Z rouault $");
+#include <vector>
+
+CPL_CVSID("$Id: gdalopeninfo.cpp 33758 2016-03-21 09:06:22Z rouault $");
+
+using std::vector;
 
 /************************************************************************/
 /* ==================================================================== */
@@ -48,9 +53,21 @@ CPL_CVSID("$Id: gdalopeninfo.cpp 29107 2015-05-02 11:23:26Z rouault $");
 /************************************************************************/
 
 GDALOpenInfo::GDALOpenInfo( const char * pszFilenameIn, int nOpenFlagsIn,
-                            char **papszSiblingsIn )
-
+                            char **papszSiblingsIn ) :
+    bHasGotSiblingFiles(false),
+    papszSiblingFiles(NULL),
+    nHeaderBytesTried(0),
+    pszFilename(CPLStrdup(pszFilenameIn)),
+    papszOpenOptions(NULL),
+    eAccess(nOpenFlagsIn & GDAL_OF_UPDATE ? GA_Update : GA_ReadOnly),
+    nOpenFlags(nOpenFlagsIn),
+    bStatOK(FALSE),
+    bIsDirectory(FALSE),
+    fpL(NULL),
+    nHeaderBytes(0),
+    pabyHeader(NULL)
 {
+
 /* -------------------------------------------------------------------- */
 /*      Ensure that C: is treated as C:\ so we can stat it on           */
 /*      Windows.  Similar to what is done in CPLStat().                 */
@@ -59,87 +76,91 @@ GDALOpenInfo::GDALOpenInfo( const char * pszFilenameIn, int nOpenFlagsIn,
     if( strlen(pszFilenameIn) == 2 && pszFilenameIn[1] == ':' )
     {
         char    szAltPath[10];
-        
+
         strcpy( szAltPath, pszFilenameIn );
         strcat( szAltPath, "\\" );
+        CPLFree( pszFilename );
         pszFilename = CPLStrdup( szAltPath );
     }
-    else
-#endif
-        pszFilename = CPLStrdup( pszFilenameIn );
+#endif  // WIN32
 
 /* -------------------------------------------------------------------- */
-/*      Initialize.                                                     */
+/*      Collect information about the file.                             */
 /* -------------------------------------------------------------------- */
 
-    nHeaderBytes = 0;
-    nHeaderBytesTried = 0;
-    pabyHeader = NULL;
-    bIsDirectory = FALSE;
-    bStatOK = FALSE;
-    nOpenFlags = nOpenFlagsIn;
-    eAccess = (nOpenFlags & GDAL_OF_UPDATE) ? GA_Update : GA_ReadOnly;
-    fpL = NULL;
-    papszOpenOptions = NULL;
-
 #ifdef HAVE_READLINK
-    int  bHasRetried = FALSE;
-#endif
+    bool bHasRetried = false;
 
-/* -------------------------------------------------------------------- */
-/*      Collect information about the file.                             */
-/* -------------------------------------------------------------------- */
-    VSIStatBufL  sStat;
+retry:  // TODO(schwehr): Stop using goto.
 
-#ifdef HAVE_READLINK
-retry:
-#endif
-    int bPotentialDirectory = FALSE;
+#endif  // HAVE_READLINK
+
+#ifdef __FreeBSD__
+    /* FreeBSD 8 oddity: fopen(a_directory, "rb") returns non NULL */
+    bool bPotentialDirectory = (eAccess == GA_ReadOnly);
+#else
+    bool bPotentialDirectory = false;
+#endif  // __FreeBDS__
 
     /* Check if the filename might be a directory of a special virtual file system */
-    if( strncmp(pszFilename, "/vsizip/", strlen("/vsizip/")) == 0 ||
-        strncmp(pszFilename, "/vsitar/", strlen("/vsitar/")) == 0 )
+    if( STARTS_WITH(pszFilename, "/vsizip/") ||
+        STARTS_WITH(pszFilename, "/vsitar/") )
     {
         const char* pszExt = CPLGetExtension(pszFilename);
-        if( EQUAL(pszExt, "zip") || EQUAL(pszExt, "tar") || EQUAL(pszExt, "gz") )
-            bPotentialDirectory = TRUE;
+        if( EQUAL(pszExt, "zip") || EQUAL(pszExt, "tar") || EQUAL(pszExt, "gz")
+#ifdef DEBUG
+            // For AFL, so that .cur_input is detected as the archive filename.
+            || EQUAL( CPLGetFilename(pszFilename), ".cur_input" )
+#endif  // DEBUG
+          )
+        {
+            bPotentialDirectory = true;
+        }
     }
-    else if( strncmp(pszFilename, "/vsicurl/", strlen("/vsicurl/")) == 0 )
+    else if( STARTS_WITH(pszFilename, "/vsicurl/") )
     {
-        bPotentialDirectory = TRUE;
+        bPotentialDirectory = true;
     }
 
     if( bPotentialDirectory )
     {
-        /* For those special files, opening them with VSIFOpenL() might result */
-        /* in content, even if they should be considered as directories, so */
-        /* use stat */
-        if( VSIStatExL( pszFilename, &sStat,
-                        VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG ) == 0 )
-        {
+        int nStatFlags = VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG;
+        if(nOpenFlagsIn & GDAL_OF_VERBOSE_ERROR)
+            nStatFlags |= VSI_STAT_SET_ERROR_FLAG;
+
+        // For those special files, opening them with VSIFOpenL() might result
+        // in content, even if they should be considered as directories, so
+        // use stat.
+        VSIStatBufL sStat;
+
+        if(VSIStatExL( pszFilename, &sStat, nStatFlags) == 0) {
             bStatOK = TRUE;
             if( VSI_ISDIR( sStat.st_mode ) )
                 bIsDirectory = TRUE;
         }
     }
 
-    if( !bIsDirectory )
-        fpL = VSIFOpenL( pszFilename, (eAccess == GA_Update) ? "r+b" : "rb" );
+    if( !bIsDirectory ) {
+        fpL = VSIFOpenExL( pszFilename, (eAccess == GA_Update) ? "r+b" : "rb", (nOpenFlagsIn & GDAL_OF_VERBOSE_ERROR) > 0);
+    }
     if( fpL != NULL )
     {
         bStatOK = TRUE;
-        pabyHeader = (GByte *) CPLCalloc(1025,1);
-        nHeaderBytesTried = 1024;
-        nHeaderBytes = (int) VSIFReadL( pabyHeader, 1, nHeaderBytesTried, fpL );
+        const int nBufSize = 1025;
+        pabyHeader = static_cast<GByte *>( CPLCalloc(nBufSize, 1) );
+        nHeaderBytesTried = nBufSize - 1;
+        nHeaderBytes = static_cast<int>(
+            VSIFReadL( pabyHeader, 1, nHeaderBytesTried, fpL ) );
         VSIRewindL( fpL );
 
         /* If we cannot read anything, check if it is not a directory instead */
+        VSIStatBufL sStat;
         if( nHeaderBytes == 0 &&
             VSIStatExL( pszFilename, &sStat,
                         VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG ) == 0 &&
             VSI_ISDIR( sStat.st_mode ) )
         {
-            VSIFCloseL(fpL);
+            CPL_IGNORE_RET_VAL(VSIFCloseL(fpL));
             fpL = NULL;
             CPLFree(pabyHeader);
             pabyHeader = NULL;
@@ -148,7 +169,8 @@ retry:
     }
     else if( !bStatOK )
     {
-        if( VSIStatExL( pszFilename, &sStat,
+        VSIStatBufL sStat;
+        if( !bPotentialDirectory && VSIStatExL( pszFilename, &sStat,
                         VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG ) == 0 )
         {
             bStatOK = TRUE;
@@ -156,24 +178,29 @@ retry:
                 bIsDirectory = TRUE;
         }
 #ifdef HAVE_READLINK
-        else if ( !bHasRetried && strncmp(pszFilename, "/vsi", strlen("/vsi")) != 0 )
+        else if ( !bHasRetried && !STARTS_WITH(pszFilename, "/vsi") )
         {
-            /* If someone creates a file with "ln -sf /vsicurl/http://download.osgeo.org/gdal/data/gtiff/utm.tif my_remote_utm.tif" */
-            /* we will be able to open it by passing my_remote_utm.tif */
-            /* This helps a lot for GDAL based readers that only provide file explorers to open datasets */
-            char szPointerFilename[2048];
-            int nBytes = readlink(pszFilename, szPointerFilename, sizeof(szPointerFilename));
+            // If someone creates a file with "ln -sf
+            // /vsicurl/http://download.osgeo.org/gdal/data/gtiff/utm.tif
+            // my_remote_utm.tif" we will be able to open it by passing
+            // my_remote_utm.tif.  This helps a lot for GDAL based readers that
+            // only provide file explorers to open datasets.
+            const int nBufSize = 2048;
+            vector<char> oFilename(nBufSize);
+            char *szPointerFilename = &oFilename[0];
+            int nBytes = static_cast<int>(
+                readlink( pszFilename, szPointerFilename, nBufSize ) );
             if (nBytes != -1)
             {
-                szPointerFilename[MIN(nBytes, (int)sizeof(szPointerFilename)-1)] = 0;
+                szPointerFilename[MIN(nBytes, nBufSize - 1)] = 0;
                 CPLFree(pszFilename);
                 pszFilename = CPLStrdup(szPointerFilename);
                 papszSiblingsIn = NULL;
-                bHasRetried = TRUE;
+                bHasRetried = true;
                 goto retry;
             }
         }
-#endif
+#endif  // HAVE_READLINK
     }
 
 /* -------------------------------------------------------------------- */
@@ -183,7 +210,7 @@ retry:
     if( papszSiblingsIn != NULL )
     {
         papszSiblingFiles = CSLDuplicate( papszSiblingsIn );
-        bHasGotSiblingFiles = TRUE;
+        bHasGotSiblingFiles = true;
     }
     else if( bStatOK && !bIsDirectory )
     {
@@ -191,26 +218,27 @@ retry:
             CPLGetConfigOption( "GDAL_DISABLE_READDIR_ON_OPEN", "NO" );
         if (EQUAL(pszOptionVal, "EMPTY_DIR"))
         {
-            papszSiblingFiles = CSLAddString( NULL, CPLGetFilename(pszFilename) );
-            bHasGotSiblingFiles = TRUE;
+            papszSiblingFiles =
+                CSLAddString( NULL, CPLGetFilename(pszFilename) );
+            bHasGotSiblingFiles = true;
         }
-        else if( CSLTestBoolean(pszOptionVal) )
+        else if( CPLTestBool(pszOptionVal) )
         {
             /* skip reading the directory */
             papszSiblingFiles = NULL;
-            bHasGotSiblingFiles = TRUE;
+            bHasGotSiblingFiles = true;
         }
         else
         {
             /* will be lazy loaded */
             papszSiblingFiles = NULL;
-            bHasGotSiblingFiles = FALSE;
+            bHasGotSiblingFiles = false;
         }
     }
     else
     {
         papszSiblingFiles = NULL;
-        bHasGotSiblingFiles = TRUE;
+        bHasGotSiblingFiles = true;
     }
 }
 
@@ -225,7 +253,7 @@ GDALOpenInfo::~GDALOpenInfo()
     CPLFree( pszFilename );
 
     if( fpL != NULL )
-        VSIFCloseL( fpL );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fpL ));
     CSLDestroy( papszSiblingFiles );
 }
 
@@ -237,15 +265,24 @@ char** GDALOpenInfo::GetSiblingFiles()
 {
     if( bHasGotSiblingFiles )
         return papszSiblingFiles;
-    bHasGotSiblingFiles = TRUE;
+    bHasGotSiblingFiles = true;
 
     CPLString osDir = CPLGetDirname( pszFilename );
-    papszSiblingFiles = VSIReadDir( osDir );
+    const int nMaxFiles =
+        atoi(CPLGetConfigOption("GDAL_READDIR_LIMIT_ON_OPEN", "1000"));
+    papszSiblingFiles = VSIReadDirEx( osDir, nMaxFiles );
+    if( nMaxFiles > 0 && CSLCount(papszSiblingFiles) > nMaxFiles )
+    {
+        CPLDebug("GDAL", "GDAL_READDIR_LIMIT_ON_OPEN reached on %s",
+                 osDir.c_str());
+        CSLDestroy(papszSiblingFiles);
+        papszSiblingFiles = NULL;
+    }
 
     /* Small optimization to avoid unnecessary stat'ing from PAux or ENVI */
     /* drivers. The MBTiles driver needs no companion file. */
     if( papszSiblingFiles == NULL &&
-        strncmp(pszFilename, "/vsicurl/", 9) == 0 &&
+        STARTS_WITH(pszFilename, "/vsicurl/") &&
         EQUAL(CPLGetExtension( pszFilename ),"mbtiles") )
     {
         papszSiblingFiles = CSLAddString( NULL, CPLGetFilename(pszFilename) );
@@ -254,6 +291,29 @@ char** GDALOpenInfo::GetSiblingFiles()
     return papszSiblingFiles;
 }
 
+/************************************************************************/
+/*                         StealSiblingFiles()                          */
+/*                                                                      */
+/*      Same as GetSiblingFiles() except that the list is stealed       */
+/*      (ie ownership transferred to the caller) and the associated     */
+/*      member variable is set to NULL.                                 */
+/************************************************************************/
+
+char** GDALOpenInfo::StealSiblingFiles()
+{
+    char** papszRet = GetSiblingFiles();
+    papszSiblingFiles = NULL;
+    return papszRet;
+}
+
+/************************************************************************/
+/*                        AreSiblingFilesLoaded()                       */
+/************************************************************************/
+
+bool GDALOpenInfo::AreSiblingFilesLoaded() const
+{
+    return bHasGotSiblingFiles;
+}
 
 /************************************************************************/
 /*                           TryToIngest()                              */
@@ -265,11 +325,11 @@ int GDALOpenInfo::TryToIngest(int nBytes)
         return FALSE;
     if( nHeaderBytes < nHeaderBytesTried )
         return TRUE;
-    pabyHeader = (GByte*) CPLRealloc(pabyHeader, nBytes + 1);
+    pabyHeader = static_cast<GByte *>( CPLRealloc(pabyHeader, nBytes + 1) );
     memset(pabyHeader, 0, nBytes + 1);
     VSIRewindL(fpL);
     nHeaderBytesTried = nBytes;
-    nHeaderBytes = (int) VSIFReadL(pabyHeader, 1, nBytes, fpL);
+    nHeaderBytes = static_cast<int>( VSIFReadL(pabyHeader, 1, nBytes, fpL) );
     VSIRewindL(fpL);
 
     return TRUE;
diff --git a/gcore/gdaloverviewdataset.cpp b/gcore/gdaloverviewdataset.cpp
index de93452..e081bfb 100644
--- a/gcore/gdaloverviewdataset.cpp
+++ b/gcore/gdaloverviewdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaloverviewdataset.cpp 29128 2015-05-03 13:21:49Z rouault $
+ * $Id: gdaloverviewdataset.cpp 33816 2016-03-30 13:18:07Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of a dataset overview warping class
@@ -27,17 +27,17 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_proxy.h"
 #include "gdal_mdreader.h"
+#include "gdal_proxy.h"
 
-CPL_CVSID("$Id: gdaloverviewdataset.cpp 29128 2015-05-03 13:21:49Z rouault $");
+CPL_CVSID("$Id: gdaloverviewdataset.cpp 33816 2016-03-30 13:18:07Z goatbar $");
 
-/** In GDAL, GDALRasterBand::GetOverview() returns a stand-alone band, that
-    may have no parent dataset. This can be inconvenient in certain contexts, where
-    cross-band processing must be done, or when API expect a fully fledge dataset.
-    Furthermore even if overview band has a container dataset, that one often
-    fails to declare its projection, geotransform, etc... which make it somehow
-    useless. GDALOverviewDataset remedies to those deficiencies.
+/** In GDAL, GDALRasterBand::GetOverview() returns a stand-alone band, that may
+    have no parent dataset. This can be inconvenient in certain contexts, where
+    cross-band processing must be done, or when API expect a fully fledged
+    dataset.  Furthermore even if overview band has a container dataset, that
+    one often fails to declare its projection, geotransform, etc... which make
+    it somehow useless. GDALOverviewDataset remedies to those deficiencies.
 */
 
 class GDALOverviewBand;
@@ -92,6 +92,9 @@ class GDALOverviewDataset : public GDALDataset
                                              const char * pszDomain = "" );
 
         virtual int        CloseDependentDatasets();
+
+  private:
+    CPL_DISALLOW_COPY_ASSIGN(GDALOverviewDataset);
 };
 
 /* ******************************************************************** */
@@ -114,6 +117,9 @@ class GDALOverviewBand : public GDALProxyRasterBand
 
         virtual int GetOverviewCount();
         virtual GDALRasterBand *GetOverview(int);
+
+  private:
+    CPL_DISALLOW_COPY_ASSIGN(GDALOverviewBand);
 };
 
 /************************************************************************/
@@ -124,11 +130,11 @@ GDALDataset* GDALCreateOverviewDataset(GDALDataset* poMainDS, int nOvrLevel,
                                        int bThisLevelOnly, int bOwnDS)
 {
     /* Sanity checks */
-    int nBands = poMainDS->GetRasterCount();
+    const int nBands = poMainDS->GetRasterCount();
     if( nBands == 0 )
         return NULL;
 
-    for(int i = 1; i<= nBands; i++ )
+    for( int i = 1; i<= nBands; i++ )
     {
         if( poMainDS->GetRasterBand(i)->GetOverview(nOvrLevel) == NULL )
         {
@@ -150,22 +156,30 @@ GDALDataset* GDALCreateOverviewDataset(GDALDataset* poMainDS, int nOvrLevel,
 /*                        GDALOverviewDataset()                         */
 /************************************************************************/
 
-GDALOverviewDataset::GDALOverviewDataset(GDALDataset* poMainDS,
-                                         int nOvrLevel,
-                                         int bThisLevelOnly,
-                                         int bOwnDS)
+GDALOverviewDataset::GDALOverviewDataset(GDALDataset* poMainDSIn,
+                                         int nOvrLevelIn,
+                                         int bThisLevelOnlyIn,
+                                         int bOwnDSIn) :
+    poMainDS(poMainDSIn),
+    bOwnDS(bOwnDSIn),
+    nOvrLevel(nOvrLevelIn),
+    bThisLevelOnly(bThisLevelOnlyIn),
+    nGCPCount(0),
+    pasGCPList(NULL),
+    papszMD_RPC(NULL),
+    papszMD_GEOLOCATION(NULL)
 {
-    this->poMainDS = poMainDS;
-    this->nOvrLevel = nOvrLevel;
-    this->bOwnDS = bOwnDS;
-    this->bThisLevelOnly = bThisLevelOnly;
     eAccess = poMainDS->GetAccess();
-    nRasterXSize = poMainDS->GetRasterBand(1)->GetOverview(nOvrLevel)->GetXSize();
-    nRasterYSize = poMainDS->GetRasterBand(1)->GetOverview(nOvrLevel)->GetYSize();
+    nRasterXSize =
+        poMainDS->GetRasterBand(1)->GetOverview(nOvrLevel)->GetXSize();
+    nRasterYSize =
+        poMainDS->GetRasterBand(1)->GetOverview(nOvrLevel)->GetYSize();
     poOvrDS = poMainDS->GetRasterBand(1)->GetOverview(nOvrLevel)->GetDataset();
     if( poOvrDS != NULL && poOvrDS == poMainDS )
     {
-        CPLDebug("GDAL", "Dataset of overview is the same as the main band. This is not expected");
+        CPLDebug( "GDAL",
+                  "Dataset of overview is the same as the main band. "
+                  "This is not expected");
         poOvrDS = NULL;
     }
     nBands = poMainDS->GetRasterCount();
@@ -173,10 +187,6 @@ GDALOverviewDataset::GDALOverviewDataset(GDALDataset* poMainDS,
     {
         SetBand(i+1, new GDALOverviewBand(this, i+1));
     }
-    nGCPCount = 0;
-    pasGCPList = NULL;
-    papszMD_RPC = NULL;
-    papszMD_GEOLOCATION = NULL;
 
     /* We create a fake driver that has the same name as the original */
     /* one, but we cannot use the real driver object, so that code */
@@ -234,7 +244,15 @@ int GDALOverviewDataset::CloseDependentDatasets()
     {
         for(int i=0;i<nBands;i++)
         {
-            ((GDALOverviewBand*)papoBands[i])->poUnderlyingBand = NULL;
+            GDALOverviewBand* const band =
+                dynamic_cast<GDALOverviewBand*>(papoBands[i]);
+            if( band == NULL )
+            {
+                CPLError( CE_Fatal, CPLE_AppDefined,
+                          "OverviewBand cast fail." );
+                return FALSE;
+            }
+            band->poUnderlyingBand = NULL;
         }
         GDALClose( poMainDS );
         poMainDS = NULL;
@@ -256,16 +274,13 @@ int GDALOverviewDataset::CloseDependentDatasets()
 CPLErr GDALOverviewDataset::IRasterIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
                                void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType, 
+                               GDALDataType eBufType,
                                int nBandCount, int *panBandMap,
                                GSpacing nPixelSpace, GSpacing nLineSpace,
                                GSpacing nBandSpace,
                                GDALRasterIOExtraArg* psExtraArg)
-    
-{
-    int iBandIndex; 
-    CPLErr eErr = CE_None;
 
+{
     /* In case the overview bands are really linked to a dataset, then issue */
     /* the request to that dataset */
     if( poOvrDS != NULL )
@@ -277,37 +292,41 @@ CPLErr GDALOverviewDataset::IRasterIO( GDALRWFlag eRWFlag,
     }
 
     GDALProgressFunc  pfnProgressGlobal = psExtraArg->pfnProgress;
-    void             *pProgressDataGlobal = psExtraArg->pProgressData;
+    void *pProgressDataGlobal = psExtraArg->pProgressData;
+    CPLErr eErr = CE_None;
 
-    for( iBandIndex = 0; 
-         iBandIndex < nBandCount && eErr == CE_None; 
+    for( int iBandIndex = 0;
+         iBandIndex < nBandCount && eErr == CE_None;
          iBandIndex++ )
     {
-        GDALOverviewBand *poBand = (GDALOverviewBand*) GetRasterBand(panBandMap[iBandIndex]);
-        GByte *pabyBandData;
-
+        GDALOverviewBand *poBand =
+            dynamic_cast<GDALOverviewBand *>(
+                GetRasterBand(panBandMap[iBandIndex]) );
         if (poBand == NULL)
         {
             eErr = CE_Failure;
             break;
         }
 
-        pabyBandData = ((GByte *) pData) + iBandIndex * nBandSpace;
+        GByte *pabyBandData =
+            static_cast<GByte *>(pData) + iBandIndex * nBandSpace;
 
         psExtraArg->pfnProgress = GDALScaledProgress;
-        psExtraArg->pProgressData = 
+        psExtraArg->pProgressData =
             GDALCreateScaledProgress( 1.0 * iBandIndex / nBandCount,
                                       1.0 * (iBandIndex + 1) / nBandCount,
                                       pfnProgressGlobal,
                                       pProgressDataGlobal );
 
-        eErr = poBand->IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, 
-                                  (void *) pabyBandData, nBufXSize, nBufYSize,
-                                  eBufType, nPixelSpace, nLineSpace, psExtraArg );
+        eErr = poBand->IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                                  pabyBandData,
+                                  nBufXSize, nBufYSize,
+                                  eBufType, nPixelSpace,
+                                  nLineSpace, psExtraArg );
 
         GDALDestroyScaledProgress( psExtraArg->pProgressData );
     }
-    
+
     psExtraArg->pfnProgress = pfnProgressGlobal;
     psExtraArg->pProgressData = pProgressDataGlobal;
 
@@ -331,30 +350,22 @@ const char *GDALOverviewDataset::GetProjectionRef()
 CPLErr GDALOverviewDataset::GetGeoTransform( double * padfTransform )
 
 {
-    double adfGeoTransform[6];
-    if( poMainDS->GetGeoTransform(adfGeoTransform) == CE_None )
-    {
-        if( adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0 )
-        {
-            adfGeoTransform[1] *= (double)poMainDS->GetRasterXSize() / nRasterXSize;
-            adfGeoTransform[5] *= (double)poMainDS->GetRasterYSize() / nRasterYSize;
-        }
-        else
-        {
-            /* If the x and y ratios are not equal, then we cannot really */
-            /* compute a geotransform */
-            double dfRatio = (double)poMainDS->GetRasterXSize() / nRasterXSize;
-            adfGeoTransform[1] *= dfRatio;
-            adfGeoTransform[2] *= dfRatio;
-            adfGeoTransform[4] *= dfRatio;
-            adfGeoTransform[5] *= dfRatio;
-        }
-        memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
-
-        return CE_None;
-    }
-    else
+    double adfGeoTransform[6] = { 0.0 };
+    if( poMainDS->GetGeoTransform(adfGeoTransform) != CE_None )
         return CE_Failure;
+
+    adfGeoTransform[1] *=
+        static_cast<double>(poMainDS->GetRasterXSize()) / nRasterXSize;
+    adfGeoTransform[2] *=
+        static_cast<double>(poMainDS->GetRasterYSize()) / nRasterYSize;
+    adfGeoTransform[4] *=
+        static_cast<double>(poMainDS->GetRasterXSize()) / nRasterXSize;
+    adfGeoTransform[5] *=
+        static_cast<double>(poMainDS->GetRasterYSize()) / nRasterYSize;
+
+    memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
+
+    return CE_None;
 }
 
 /************************************************************************/
@@ -386,7 +397,7 @@ const GDAL_GCP *GDALOverviewDataset::GetGCPs()
 {
     if( pasGCPList != NULL )
         return pasGCPList;
-    
+
     const GDAL_GCP* pasGCPsMain = poMainDS->GetGCPs();
     if( pasGCPsMain == NULL )
         return NULL;
@@ -395,8 +406,10 @@ const GDAL_GCP *GDALOverviewDataset::GetGCPs()
     pasGCPList = GDALDuplicateGCPs( nGCPCount, pasGCPsMain );
     for(int i = 0; i < nGCPCount; i++)
     {
-        pasGCPList[i].dfGCPPixel *= (double)nRasterXSize / poMainDS->GetRasterXSize();
-        pasGCPList[i].dfGCPLine *= (double)nRasterYSize / poMainDS->GetRasterYSize();
+        pasGCPList[i].dfGCPPixel *= static_cast<double>(nRasterXSize) /
+            poMainDS->GetRasterXSize();
+        pasGCPList[i].dfGCPLine *= static_cast<double>(nRasterYSize) /
+            poMainDS->GetRasterYSize();
     }
     return pasGCPList;
 }
@@ -408,8 +421,9 @@ const GDAL_GCP *GDALOverviewDataset::GetGCPs()
 void GDALOverviewDataset::Rescale(char**& papszMD, const char* pszItem,
                                   double dfRatio, double dfDefaultVal)
 {
-    double dfVal = CPLAtofM(CSLFetchNameValueDef(papszMD, pszItem,
-                                            CPLSPrintf("%.18g", dfDefaultVal)));
+    double dfVal =
+        CPLAtofM( CSLFetchNameValueDef(papszMD, pszItem,
+                                       CPLSPrintf("%.18g", dfDefaultVal)) );
     dfVal *= dfRatio;
     papszMD = CSLSetNameValue(papszMD, pszItem, CPLSPrintf("%.18g", dfVal));
 }
@@ -420,51 +434,60 @@ void GDALOverviewDataset::Rescale(char**& papszMD, const char* pszItem,
 
 char  **GDALOverviewDataset::GetMetadata( const char * pszDomain )
 {
-    char** papszMD;
     if (poOvrDS != NULL)
     {
-        papszMD = poOvrDS->GetMetadata(pszDomain);
+        char** papszMD = poOvrDS->GetMetadata(pszDomain);
         if( papszMD != NULL )
             return papszMD;
     }
 
-    papszMD = poMainDS->GetMetadata(pszDomain);
+    char** papszMD = poMainDS->GetMetadata(pszDomain);
 
     /* We may need to rescale some values from the RPC metadata domain */
-    if( pszDomain != NULL && EQUAL(pszDomain, MD_DOMAIN_RPC) && papszMD != NULL )
+    if( pszDomain != NULL && EQUAL(pszDomain, MD_DOMAIN_RPC) &&
+        papszMD != NULL )
     {
         if( papszMD_RPC )
             return papszMD_RPC;
         papszMD_RPC = CSLDuplicate(papszMD);
 
-        Rescale(papszMD_RPC, RPC_LINE_OFF,
-                (double)nRasterYSize / poMainDS->GetRasterYSize(), 0.0);
-        Rescale(papszMD_RPC, RPC_LINE_SCALE,
-                (double)nRasterYSize / poMainDS->GetRasterYSize(), 1.0);
-        Rescale(papszMD_RPC, RPC_SAMP_OFF,
-                (double)nRasterXSize / poMainDS->GetRasterXSize(), 0.0);
-        Rescale(papszMD_RPC, RPC_SAMP_SCALE,
-                (double)nRasterXSize / poMainDS->GetRasterXSize(), 1.0);
+        Rescale( papszMD_RPC, RPC_LINE_OFF,
+                 static_cast<double>(nRasterYSize) / poMainDS->GetRasterYSize(),
+                 0.0 );
+        Rescale( papszMD_RPC, RPC_LINE_SCALE,
+                 static_cast<double>(nRasterYSize) / poMainDS->GetRasterYSize(),
+                 1.0 );
+        Rescale( papszMD_RPC, RPC_SAMP_OFF,
+                 static_cast<double>(nRasterXSize) / poMainDS->GetRasterXSize(),
+                 0.0 );
+        Rescale( papszMD_RPC, RPC_SAMP_SCALE,
+                 static_cast<double>(nRasterXSize) / poMainDS->GetRasterXSize(),
+                 1.0 );
 
         papszMD = papszMD_RPC;
     }
 
-    /* We may need to rescale some values from the GEOLOCATION metadata domain */
-    if( pszDomain != NULL && EQUAL(pszDomain, "GEOLOCATION") && papszMD != NULL )
+    // We may need to rescale some values from the GEOLOCATION metadata domain.
+    if( pszDomain != NULL && EQUAL(pszDomain, "GEOLOCATION") &&
+        papszMD != NULL )
     {
         if( papszMD_GEOLOCATION )
             return papszMD_GEOLOCATION;
         papszMD_GEOLOCATION = CSLDuplicate(papszMD);
 
-        Rescale(papszMD_GEOLOCATION, "PIXEL_OFFSET",
-                (double)poMainDS->GetRasterXSize() / nRasterXSize, 0.0);
-        Rescale(papszMD_GEOLOCATION, "LINE_OFFSET",
-                (double)poMainDS->GetRasterYSize() / nRasterYSize, 0.0);
+        Rescale( papszMD_GEOLOCATION, "PIXEL_OFFSET",
+                 static_cast<double>(poMainDS->GetRasterXSize()) /
+                 nRasterXSize, 0.0 );
+        Rescale( papszMD_GEOLOCATION, "LINE_OFFSET",
+                 static_cast<double>(poMainDS->GetRasterYSize()) /
+                 nRasterYSize, 0.0 );
 
-        Rescale(papszMD_GEOLOCATION, "PIXEL_STEP",
-                (double)nRasterXSize / poMainDS->GetRasterXSize(), 1.0);
-        Rescale(papszMD_GEOLOCATION, "LINE_STEP",
-                (double)nRasterYSize / poMainDS->GetRasterYSize(), 1.0);
+        Rescale( papszMD_GEOLOCATION, "PIXEL_STEP",
+                 static_cast<double>(nRasterXSize) / poMainDS->GetRasterXSize(),
+                 1.0 );
+        Rescale( papszMD_GEOLOCATION, "LINE_STEP",
+                 static_cast<double>(nRasterYSize) / poMainDS->GetRasterYSize(),
+                 1.0 );
 
         papszMD = papszMD_GEOLOCATION;
     }
@@ -500,13 +523,13 @@ const char *GDALOverviewDataset::GetMetadataItem( const char * pszName,
 /*                          GDALOverviewBand()                          */
 /************************************************************************/
 
-GDALOverviewBand::GDALOverviewBand(GDALOverviewDataset* poDS, int nBand)
+GDALOverviewBand::GDALOverviewBand(GDALOverviewDataset* poDSIn, int nBandIn)
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
-    poUnderlyingBand = poDS->poMainDS->GetRasterBand(nBand)->GetOverview(poDS->nOvrLevel);
-    nRasterXSize = poDS->nRasterXSize;
-    nRasterYSize = poDS->nRasterYSize;
+    poDS = poDSIn;
+    nBand = nBandIn;
+    poUnderlyingBand = poDSIn->poMainDS->GetRasterBand(nBand)->GetOverview(poDSIn->nOvrLevel);
+    nRasterXSize = poDSIn->nRasterXSize;
+    nRasterYSize = poDSIn->nRasterYSize;
     eDataType = poUnderlyingBand->GetRasterDataType();
     poUnderlyingBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
 }
@@ -526,7 +549,7 @@ GDALOverviewBand::~GDALOverviewBand()
 
 CPLErr GDALOverviewBand::FlushCache()
 {
-    if( ((GDALOverviewDataset*)poDS)->poMainDS )
+    if( poUnderlyingBand )
         return poUnderlyingBand->FlushCache();
     return CE_None;
 }
@@ -537,10 +560,10 @@ CPLErr GDALOverviewBand::FlushCache()
 
 GDALRasterBand* GDALOverviewBand::RefUnderlyingRasterBand()
 {
-    if( ((GDALOverviewDataset*)poDS)->poMainDS )
+    if( poUnderlyingBand )
         return poUnderlyingBand;
-    else
-        return NULL;
+
+    return NULL;
 }
 
 /************************************************************************/
@@ -549,11 +572,18 @@ GDALRasterBand* GDALOverviewBand::RefUnderlyingRasterBand()
 
 int GDALOverviewBand::GetOverviewCount()
 {
-    GDALOverviewDataset* poOvrDS = (GDALOverviewDataset*)poDS;
+    GDALOverviewDataset * const poOvrDS =
+        dynamic_cast<GDALOverviewDataset *>(poDS);
+    if( poOvrDS == NULL )
+    {
+        CPLError( CE_Fatal, CPLE_AppDefined, "OverviewDataset cast fail." );
+        return 0;
+    }
     if( poOvrDS->bThisLevelOnly )
         return 0;
-    GDALDataset* poMainDS = poOvrDS->poMainDS;
-    return poMainDS->GetRasterBand(nBand)->GetOverviewCount() - poOvrDS->nOvrLevel - 1;
+    GDALDataset * const poMainDS = poOvrDS->poMainDS;
+    return poMainDS->GetRasterBand(nBand)->GetOverviewCount()
+        - poOvrDS->nOvrLevel - 1;
 }
 
 /************************************************************************/
@@ -564,7 +594,14 @@ GDALRasterBand *GDALOverviewBand::GetOverview(int iOvr)
 {
     if( iOvr < 0 || iOvr >= GetOverviewCount() )
         return NULL;
-    GDALOverviewDataset* poOvrDS = (GDALOverviewDataset*)poDS;
-    GDALDataset* poMainDS = poOvrDS->poMainDS;
-    return poMainDS->GetRasterBand(nBand)->GetOverview(iOvr + poOvrDS->nOvrLevel + 1);
+    GDALOverviewDataset * const poOvrDS =
+        dynamic_cast<GDALOverviewDataset *>(poDS);
+    if( poOvrDS == NULL )
+    {
+        CPLError( CE_Fatal, CPLE_AppDefined, "OverviewDataset cast fail." );
+        return NULL;
+    }
+    GDALDataset * const poMainDS = poOvrDS->poMainDS;
+    return poMainDS->GetRasterBand(nBand)->
+        GetOverview(iOvr + poOvrDS->nOvrLevel + 1);
 }
diff --git a/gcore/gdalpamdataset.cpp b/gcore/gdalpamdataset.cpp
index 4945070..46f05eb 100644
--- a/gcore/gdalpamdataset.cpp
+++ b/gcore/gdalpamdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalpamdataset.cpp 29038 2015-04-28 09:03:36Z rouault $
+ * $Id: gdalpamdataset.cpp 33760 2016-03-21 13:52:50Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALPamDataset, a dataset base class that
@@ -29,11 +29,11 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
 #include "cpl_string.h"
+#include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: gdalpamdataset.cpp 29038 2015-04-28 09:03:36Z rouault $");
+CPL_CVSID("$Id: gdalpamdataset.cpp 33760 2016-03-21 13:52:50Z goatbar $");
 
 /************************************************************************/
 /*                           GDALPamDataset()                           */
@@ -41,18 +41,18 @@ CPL_CVSID("$Id: gdalpamdataset.cpp 29038 2015-04-28 09:03:36Z rouault $");
 
 /**
  * \class GDALPamDataset "gdal_pam.h"
- * 
+ *
  * A subclass of GDALDataset which introduces the ability to save and
- * restore auxiliary information (coordinate system, gcps, metadata, 
+ * restore auxiliary information (coordinate system, gcps, metadata,
  * etc) not supported by a file format via an "auxiliary metadata" file
- * with the .aux.xml extension.  
- * 
+ * with the .aux.xml extension.
+ *
  * <h3>Enabling PAM</h3>
- * 
- * PAM support can be enabled (resp. disabled) in GDAL by setting the GDAL_PAM_ENABLED
- * configuration option (via CPLSetConfigOption(), or the environment) to 
- * the value of YES (resp. NO). Note: The default value is build dependant and defaults
- * to YES in Windows and Unix builds.
+ *
+ * PAM support can be enabled (resp. disabled) in GDAL by setting the
+ * GDAL_PAM_ENABLED configuration option (via CPLSetConfigOption(), or the
+ * environment) to the value of YES (resp. NO). Note: The default value is
+ * build dependent and defaults to YES in Windows and Unix builds.
  *
  * <h3>PAM Proxy Files</h3>
  *
@@ -64,8 +64,8 @@ CPL_CVSID("$Id: gdalpamdataset.cpp 29038 2015-04-28 09:03:36Z rouault $");
  *
  * To enable this, set the GDAL_PAM_PROXY_DIR configuration option to be
  * the name of the directory where the proxies should be kept. The configuration
- * option must be set *before* the first access to PAM, because its value is cached
- * for later access.
+ * option must be set *before* the first access to PAM, because its value is
+ * cached for later access.
  *
  * <h3>Adding PAM to Drivers</h3>
  *
@@ -74,9 +74,9 @@ CPL_CVSID("$Id: gdalpamdataset.cpp 29038 2015-04-28 09:03:36Z rouault $");
  * dataset class from GDALPamDataset instead of directly from GDALDataset.
  * The raster band classes should also be derived from GDALPamRasterBand.
  *
- * They should also call something like this near the end of the Open() 
+ * They should also call something like this near the end of the Open()
  * method:
- * 
+ *
  * \code
  *      poDS->SetDescription( poOpenInfo->pszFilename );
  *      poDS->TryLoadXML();
@@ -86,10 +86,10 @@ CPL_CVSID("$Id: gdalpamdataset.cpp 29038 2015-04-28 09:03:36Z rouault $");
  * filename set as the description before TryLoadXML() is called.  TryLoadXML()
  * will look for an .aux.xml file with the same basename as the dataset and
  * in the same directory.  If found the contents will be loaded and kept
- * track of in the GDALPamDataset and GDALPamRasterBand objects.  When a 
+ * track of in the GDALPamDataset and GDALPamRasterBand objects.  When a
  * call like GetProjectionRef() is not implemented by the format specific
  * class, it will fall through to the PAM implementation which will return
- * information if it was in the .aux.xml file. 
+ * information if it was in the .aux.xml file.
  *
  * Drivers should also try to call the GDALPamDataset/GDALPamRasterBand
  * methods as a fallback if their implementation does not find information.
@@ -104,32 +104,31 @@ CPL_CVSID("$Id: gdalpamdataset.cpp 29038 2015-04-28 09:03:36Z rouault $");
  *          return( pszProjection );
  * \endcode
  *
- * So if the geotiff header is missing, the .aux.xml file will be 
- * consulted. 
+ * So if the geotiff header is missing, the .aux.xml file will be
+ * consulted.
  *
  * Similarly, if SetProjection() were called with a coordinate system
  * not supported by GeoTIFF, the SetProjection() method should pass it on
  * to the GDALPamDataset::SetProjection() method after issuing a warning
- * that the information can't be represented within the file itself. 
- * 
+ * that the information can't be represented within the file itself.
+ *
  * Drivers for subdataset based formats will also need to declare the
- * name of the physical file they are related to, and the name of their 
- * subdataset before calling TryLoadXML(). 
+ * name of the physical file they are related to, and the name of their
+ * subdataset before calling TryLoadXML().
  *
  * \code
  *      poDS->SetDescription( poOpenInfo->pszFilename );
  *      poDS->SetPhysicalFilename( poDS->pszFilename );
  *      poDS->SetSubdatasetName( osSubdatasetName );
- * 
+ *
  *      poDS->TryLoadXML();
  * \endcode
  */
 
-GDALPamDataset::GDALPamDataset()
-
+GDALPamDataset::GDALPamDataset() :
+    nPamFlags(0),
+    psPam(NULL)
 {
-    nPamFlags = 0;
-    psPam = NULL;
     SetMOFlags( GetMOFlags() | GMO_PAM_CLASS );
 }
 
@@ -168,17 +167,13 @@ void GDALPamDataset::FlushCache()
 CPLXMLNode *GDALPamDataset::SerializeToXML( const char *pszUnused )
 
 {
-    CPLString oFmt;
-
     if( psPam == NULL )
         return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Setup root node and attributes.                                 */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psDSTree;
-
-    psDSTree = CPLCreateXMLNode( NULL, CXT_Element, "PAMDataset" );
+    CPLXMLNode *psDSTree = CPLCreateXMLNode( NULL, CXT_Element, "PAMDataset" );
 
 /* -------------------------------------------------------------------- */
 /*      SRS                                                             */
@@ -191,14 +186,15 @@ CPLXMLNode *GDALPamDataset::SerializeToXML( const char *pszUnused )
 /* -------------------------------------------------------------------- */
     if( psPam->bHaveGeoTransform )
     {
-        CPLSetXMLValue( psDSTree, "GeoTransform", 
-                        oFmt.Printf( "%24.16e,%24.16e,%24.16e,%24.16e,%24.16e,%24.16e",
-                                     psPam->adfGeoTransform[0],
-                                     psPam->adfGeoTransform[1],
-                                     psPam->adfGeoTransform[2],
-                                     psPam->adfGeoTransform[3],
-                                     psPam->adfGeoTransform[4],
-                                     psPam->adfGeoTransform[5] ) );
+        CPLString oFmt;
+        oFmt.Printf( "%24.16e,%24.16e,%24.16e,%24.16e,%24.16e,%24.16e",
+                     psPam->adfGeoTransform[0],
+                     psPam->adfGeoTransform[1],
+                     psPam->adfGeoTransform[2],
+                     psPam->adfGeoTransform[3],
+                     psPam->adfGeoTransform[4],
+                     psPam->adfGeoTransform[5] );
+        CPLSetXMLValue( psDSTree, "GeoTransform", oFmt );
     }
 
 /* -------------------------------------------------------------------- */
@@ -206,9 +202,7 @@ CPLXMLNode *GDALPamDataset::SerializeToXML( const char *pszUnused )
 /* -------------------------------------------------------------------- */
     if( psPam->bHasMetadata )
     {
-        CPLXMLNode *psMD;
-
-        psMD = oMDMD.Serialize();
+        CPLXMLNode *psMD = oMDMD.Serialize();
         if( psMD != NULL )
         {
             CPLAddXMLChild( psDSTree, psMD );
@@ -229,19 +223,16 @@ CPLXMLNode *GDALPamDataset::SerializeToXML( const char *pszUnused )
 /* -------------------------------------------------------------------- */
 /*      Process bands.                                                  */
 /* -------------------------------------------------------------------- */
-    int iBand;
-
-    for( iBand = 0; iBand < GetRasterCount(); iBand++ )
+    for( int iBand = 0; iBand < GetRasterCount(); iBand++ )
     {
-        CPLXMLNode *psBandTree;
-
-        GDALPamRasterBand *poBand = (GDALPamRasterBand *)
-            GetRasterBand(iBand+1);
+        GDALPamRasterBand * const poBand =
+            reinterpret_cast<GDALPamRasterBand *>(
+                GetRasterBand(iBand+1) );
 
         if( poBand == NULL || !(poBand->GetMOFlags() & GMO_PAM_CLASS) )
             continue;
 
-        psBandTree = poBand->SerializeToXML( pszUnused );
+        CPLXMLNode * const psBandTree = poBand->SerializeToXML( pszUnused );
 
         if( psBandTree != NULL )
             CPLAddXMLChild( psDSTree, psBandTree );
@@ -268,15 +259,15 @@ void GDALPamDataset::PamInitialize()
 
 {
 #ifdef PAM_ENABLED
-    static const char *pszPamDefault = "YES";
+    const char * const pszPamDefault = "YES";
 #else
-    static const char *pszPamDefault = "NO";
+    const char * const pszPamDefault = "NO";
 #endif
-    
+
     if( psPam || (nPamFlags & GPF_DISABLED) )
         return;
 
-    if( !CSLTestBoolean( CPLGetConfigOption( "GDAL_PAM_ENABLED", 
+    if( !CPLTestBool( CPLGetConfigOption( "GDAL_PAM_ENABLED",
                                              pszPamDefault ) ) )
     {
         nPamFlags |= GPF_DISABLED;
@@ -296,17 +287,14 @@ void GDALPamDataset::PamInitialize()
     psPam->pszGCPProjection = NULL;
     psPam->bHasMetadata = FALSE;
 
-    int iBand;
-    
-    for( iBand = 0; iBand < GetRasterCount(); iBand++ )
+    for( int iBand = 0; iBand < GetRasterCount(); iBand++ )
     {
-        GDALPamRasterBand *poBand = (GDALPamRasterBand *)
-            GetRasterBand(iBand+1);
-        
+        GDALRasterBand *poBand = GetRasterBand(iBand+1);
+
         if( poBand == NULL || !(poBand->GetMOFlags() & GMO_PAM_CLASS) )
             continue;
 
-        poBand->PamInitialize();
+        reinterpret_cast<GDALPamRasterBand *>(poBand)->PamInitialize();
     }
 }
 
@@ -345,11 +333,10 @@ CPLErr GDALPamDataset::XMLInit( CPLXMLNode *psTree, const char *pszUnused )
 /* -------------------------------------------------------------------- */
     if( strlen(CPLGetXMLValue(psTree, "SRS", "")) > 0 )
     {
-        OGRSpatialReference oSRS;
-
         CPLFree( psPam->pszProjection );
         psPam->pszProjection = NULL;
 
+        OGRSpatialReference oSRS;
         if( oSRS.SetFromUserInput( CPLGetXMLValue(psTree, "SRS", "") )
             == OGRERR_NONE )
             oSRS.exportToWkt( &(psPam->pszProjection) );
@@ -361,9 +348,9 @@ CPLErr GDALPamDataset::XMLInit( CPLXMLNode *psTree, const char *pszUnused )
     if( strlen(CPLGetXMLValue(psTree, "GeoTransform", "")) > 0 )
     {
         const char *pszGT = CPLGetXMLValue(psTree, "GeoTransform", "");
-        char	**papszTokens;
 
-        papszTokens = CSLTokenizeStringComplex( pszGT, ",", FALSE, FALSE );
+        char **papszTokens =
+            CSLTokenizeStringComplex( pszGT, ",", FALSE, FALSE );
         if( CSLCount(papszTokens) != 6 )
         {
             CPLError( CE_Warning, CPLE_AppDefined,
@@ -396,7 +383,7 @@ CPLErr GDALPamDataset::XMLInit( CPLXMLNode *psTree, const char *pszUnused )
             GDALDeinitGCPs( psPam->nGCPCount, psPam->pasGCPList );
             CPLFree( psPam->pasGCPList );
             psPam->nGCPCount = 0;
-            psPam->pasGCPList = 0;
+            psPam->pasGCPList = NULL;
         }
 
         GDALDeserializeGCPListFromXML( psGCPList,
@@ -447,22 +434,20 @@ CPLErr GDALPamDataset::XMLInit( CPLXMLNode *psTree, const char *pszUnused )
 /* -------------------------------------------------------------------- */
 /*      Process bands.                                                  */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psBandTree;
-
-    for( psBandTree = psTree->psChild; 
+    for( CPLXMLNode *psBandTree = psTree->psChild;
          psBandTree != NULL; psBandTree = psBandTree->psNext )
     {
         if( psBandTree->eType != CXT_Element
             || !EQUAL(psBandTree->pszValue,"PAMRasterBand") )
             continue;
 
-        int nBand = atoi(CPLGetXMLValue( psBandTree, "band", "0"));
+        const int nBand = atoi(CPLGetXMLValue( psBandTree, "band", "0"));
 
         if( nBand < 1 || nBand > GetRasterCount() )
             continue;
 
-        GDALPamRasterBand *poBand = (GDALPamRasterBand *)
-            GetRasterBand(nBand);
+        GDALPamRasterBand *poBand = reinterpret_cast<GDALPamRasterBand *>(
+            GetRasterBand(nBand) );
 
         if( poBand == NULL || !(poBand->GetMOFlags() & GMO_PAM_CLASS) )
             continue;
@@ -502,8 +487,8 @@ const char *GDALPamDataset::GetPhysicalFilename()
 
     if( psPam )
         return psPam->osPhysicalFilename;
-    else
-        return "";
+
+    return "";
 }
 
 /************************************************************************/
@@ -530,8 +515,8 @@ const char *GDALPamDataset::GetSubdatasetName()
 
     if( psPam )
         return psPam->osSubdatasetName;
-    else
-        return "";
+
+    return "";
 }
 
 /************************************************************************/
@@ -595,7 +580,7 @@ int GDALPamDataset::IsPamFilenameAPotentialSiblingFile()
     if( strlen(pszPhysicalFile) == 0 && GetDescription() != NULL )
         pszPhysicalFile = GetDescription();
 
-    int nLenPhysicalFile = strlen(pszPhysicalFile);
+    size_t nLenPhysicalFile = strlen(pszPhysicalFile);
     int bIsSiblingPamFile = strncmp(psPam->pszPamFilename, pszPhysicalFile,
                                     nLenPhysicalFile) == 0 &&
                             strcmp(psPam->pszPamFilename + nLenPhysicalFile,
@@ -611,8 +596,6 @@ int GDALPamDataset::IsPamFilenameAPotentialSiblingFile()
 CPLErr GDALPamDataset::TryLoadXML(char **papszSiblingFiles)
 
 {
-    CPLXMLNode *psTree = NULL;
-
     PamInitialize();
 
 /* -------------------------------------------------------------------- */
@@ -620,7 +603,7 @@ CPLErr GDALPamDataset::TryLoadXML(char **papszSiblingFiles)
 /*      from a call at the end of the Open() method, and some calls     */
 /*      may have already marked the PAM info as dirty (for instance     */
 /*      setting metadata), but really everything to this point is       */
-/*      reproducable, and so the PAM info shouldn't really be           */
+/*      reproducible, and so the PAM info should not really be          */
 /*      thought of as dirty.                                            */
 /* -------------------------------------------------------------------- */
     nPamFlags &= ~GPF_DIRTY;
@@ -631,17 +614,19 @@ CPLErr GDALPamDataset::TryLoadXML(char **papszSiblingFiles)
     if( !BuildPamFilename() )
         return CE_None;
 
-    VSIStatBufL sStatBuf;
-
 /* -------------------------------------------------------------------- */
 /*      In case the PAM filename is a .aux.xml file next to the         */
 /*      physical file and we have a siblings list, then we can skip     */
 /*      stat'ing the filesystem.                                        */
 /* -------------------------------------------------------------------- */
+    VSIStatBufL sStatBuf;
+    CPLXMLNode *psTree = NULL;
+
     if (papszSiblingFiles != NULL && IsPamFilenameAPotentialSiblingFile())
     {
-        int iSibling = CSLFindString( papszSiblingFiles,
-                                      CPLGetFilename(psPam->pszPamFilename) );
+        const int iSibling =
+            CSLFindString( papszSiblingFiles,
+                           CPLGetFilename(psPam->pszPamFilename) );
         if( iSibling >= 0 )
         {
             CPLErrorReset();
@@ -667,9 +652,9 @@ CPLErr GDALPamDataset::TryLoadXML(char **papszSiblingFiles)
 /* -------------------------------------------------------------------- */
     if( psTree && psPam->osSubdatasetName.size() )
     {
-        CPLXMLNode *psSubTree;
-        
-        for( psSubTree = psTree->psChild; 
+        CPLXMLNode *psSubTree = psTree->psChild;
+
+        for( ;
              psSubTree != NULL;
              psSubTree = psSubTree->psNext )
         {
@@ -684,7 +669,7 @@ CPLErr GDALPamDataset::TryLoadXML(char **papszSiblingFiles)
             psSubTree = CPLGetXMLNode( psSubTree, "PAMDataset" );
             break;
         }
-        
+
         if( psSubTree != NULL )
             psSubTree = CPLCloneXMLTree( psSubTree );
 
@@ -701,10 +686,9 @@ CPLErr GDALPamDataset::TryLoadXML(char **papszSiblingFiles)
 /* -------------------------------------------------------------------- */
 /*      Initialize ourselves from this XML tree.                        */
 /* -------------------------------------------------------------------- */
-    CPLErr eErr;
 
     CPLString osVRTPath(CPLGetPath(psPam->pszPamFilename));
-    eErr = XMLInit( psTree, osVRTPath );
+    const CPLErr eErr = XMLInit( psTree, osVRTPath );
 
     CPLDestroyXMLNode( psTree );
 
@@ -721,9 +705,6 @@ CPLErr GDALPamDataset::TryLoadXML(char **papszSiblingFiles)
 CPLErr GDALPamDataset::TrySaveXML()
 
 {
-    CPLXMLNode *psTree;
-    CPLErr eErr = CE_None;
-
     nPamFlags &= ~GPF_DIRTY;
 
     if( psPam == NULL || (nPamFlags & GPF_NOSAVE) )
@@ -738,7 +719,7 @@ CPLErr GDALPamDataset::TrySaveXML()
 /* -------------------------------------------------------------------- */
 /*      Build the XML representation of the auxiliary metadata.          */
 /* -------------------------------------------------------------------- */
-    psTree = SerializeToXML( NULL );
+    CPLXMLNode *psTree = SerializeToXML( NULL );
 
     if( psTree == NULL )
     {
@@ -766,7 +747,7 @@ CPLErr GDALPamDataset::TrySaveXML()
         if( psOldTree == NULL )
             psOldTree = CPLCreateXMLNode( NULL, CXT_Element, "PAMDataset" );
 
-        for( psSubTree = psOldTree->psChild; 
+        for( psSubTree = psOldTree->psChild;
              psSubTree != NULL;
              psSubTree = psSubTree->psNext )
         {
@@ -783,13 +764,13 @@ CPLErr GDALPamDataset::TrySaveXML()
 
         if( psSubTree == NULL )
         {
-            psSubTree = CPLCreateXMLNode( psOldTree, CXT_Element, 
+            psSubTree = CPLCreateXMLNode( psOldTree, CXT_Element,
                                           "Subdataset" );
-            CPLCreateXMLNode( 
+            CPLCreateXMLNode(
                 CPLCreateXMLNode( psSubTree, CXT_Attribute, "name" ),
                 CXT_Text, psPam->osSubdatasetName );
         }
-        
+
         CPLXMLNode *psOldPamDataset = CPLGetXMLNode( psSubTree, "PAMDataset");
         if( psOldPamDataset != NULL )
         {
@@ -804,27 +785,29 @@ CPLErr GDALPamDataset::TrySaveXML()
 /* -------------------------------------------------------------------- */
 /*      Try saving the auxiliary metadata.                               */
 /* -------------------------------------------------------------------- */
-    int bSaved;
-    
+
     CPLPushErrorHandler( CPLQuietErrorHandler );
-    bSaved = CPLSerializeXMLTreeToFile( psTree, psPam->pszPamFilename );
+    const int bSaved =
+        CPLSerializeXMLTreeToFile( psTree, psPam->pszPamFilename );
     CPLPopErrorHandler();
 
 /* -------------------------------------------------------------------- */
 /*      If it fails, check if we have a proxy directory for auxiliary    */
 /*      metadata to be stored in, and try to save there.                */
 /* -------------------------------------------------------------------- */
+    CPLErr eErr = CE_None;
+
     if( bSaved )
         eErr = CE_None;
     else
     {
-        const char *pszNewPam;
         const char *pszBasename = GetDescription();
 
-        if( psPam && psPam->osPhysicalFilename.length() > 0 )
+        if( psPam->osPhysicalFilename.length() > 0 )
             pszBasename = psPam->osPhysicalFilename;
-            
-        if( PamGetProxy(pszBasename) == NULL 
+
+        const char *pszNewPam = NULL;
+        if( PamGetProxy(pszBasename) == NULL
             && ((pszNewPam = PamAllocateProxy(pszBasename)) != NULL))
         {
             CPLErrorReset();
@@ -833,15 +816,15 @@ CPLErr GDALPamDataset::TrySaveXML()
             eErr = TrySaveXML();
         }
         /* No way we can save into a /vsicurl resource */
-        else if( strncmp(psPam->pszPamFilename, "/vsicurl", strlen("/vsicurl")) != 0 )
+        else if( !STARTS_WITH(psPam->pszPamFilename, "/vsicurl") )
         {
-            CPLError( CE_Warning, CPLE_AppDefined, 
+            CPLError( CE_Warning, CPLE_AppDefined,
                       "Unable to save auxiliary information in %s.",
                       psPam->pszPamFilename );
             eErr = CE_Warning;
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Cleanup                                                         */
 /* -------------------------------------------------------------------- */
@@ -857,8 +840,8 @@ CPLErr GDALPamDataset::TrySaveXML()
 CPLErr GDALPamDataset::CloneInfo( GDALDataset *poSrcDS, int nCloneFlags )
 
 {
-    int bOnlyIfMissing = nCloneFlags & GCIF_ONLY_IF_MISSING;
-    int nSavedMOFlags = GetMOFlags();
+    const int bOnlyIfMissing = nCloneFlags & GCIF_ONLY_IF_MISSING;
+    const int nSavedMOFlags = GetMOFlags();
 
     PamInitialize();
 
@@ -873,11 +856,11 @@ CPLErr GDALPamDataset::CloneInfo( GDALDataset *poSrcDS, int nCloneFlags )
 /* -------------------------------------------------------------------- */
     if( nCloneFlags & GCIF_GEOTRANSFORM )
     {
-        double adfGeoTransform[6];
+      double adfGeoTransform[6] = { 0.0 };
 
         if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None )
         {
-            double adfOldGT[6];
+            double adfOldGT[6] = { 0.0 };
 
             if( !bOnlyIfMissing || GetGeoTransform( adfOldGT ) != CE_None )
                 SetGeoTransform( adfGeoTransform );
@@ -893,7 +876,7 @@ CPLErr GDALPamDataset::CloneInfo( GDALDataset *poSrcDS, int nCloneFlags )
 
         if( pszWKT != NULL && strlen(pszWKT) > 0 )
         {
-            if( !bOnlyIfMissing 
+            if( !bOnlyIfMissing
                 || GetProjectionRef() == NULL
                 || strlen(GetProjectionRef()) == 0 )
                 SetProjection( pszWKT );
@@ -909,8 +892,8 @@ CPLErr GDALPamDataset::CloneInfo( GDALDataset *poSrcDS, int nCloneFlags )
         {
             if( !bOnlyIfMissing || GetGCPCount() == 0 )
             {
-                SetGCPs( poSrcDS->GetGCPCount(), 
-                         poSrcDS->GetGCPs(), 
+                SetGCPs( poSrcDS->GetGCPCount(),
+                         poSrcDS->GetGCPs(),
                          poSrcDS->GetGCPProjection() );
             }
         }
@@ -923,7 +906,7 @@ CPLErr GDALPamDataset::CloneInfo( GDALDataset *poSrcDS, int nCloneFlags )
     {
         if( poSrcDS->GetMetadata() != NULL )
         {
-            if( !bOnlyIfMissing 
+            if( !bOnlyIfMissing
                 || CSLCount(GetMetadata()) != CSLCount(poSrcDS->GetMetadata()) )
             {
                 SetMetadata( poSrcDS->GetMetadata() );
@@ -931,8 +914,8 @@ CPLErr GDALPamDataset::CloneInfo( GDALDataset *poSrcDS, int nCloneFlags )
         }
         if( poSrcDS->GetMetadata("RPC") != NULL )
         {
-            if( !bOnlyIfMissing 
-                || CSLCount(GetMetadata("RPC")) 
+            if( !bOnlyIfMissing
+                || CSLCount(GetMetadata("RPC"))
                    != CSLCount(poSrcDS->GetMetadata("RPC")) )
             {
                 SetMetadata( poSrcDS->GetMetadata("RPC"), "RPC" );
@@ -945,21 +928,22 @@ CPLErr GDALPamDataset::CloneInfo( GDALDataset *poSrcDS, int nCloneFlags )
 /* -------------------------------------------------------------------- */
     if( nCloneFlags & GCIF_PROCESS_BANDS )
     {
-        int iBand;
-
-        for( iBand = 0; iBand < GetRasterCount(); iBand++ )
+        for( int iBand = 0; iBand < GetRasterCount(); iBand++ )
         {
-            GDALPamRasterBand *poBand = (GDALPamRasterBand *)
-                GetRasterBand(iBand+1);
+            GDALPamRasterBand *poBand = reinterpret_cast<GDALPamRasterBand *>(
+                GetRasterBand(iBand+1) );
 
             if( poBand == NULL || !(poBand->GetMOFlags() & GMO_PAM_CLASS) )
                 continue;
 
             if( poSrcDS->GetRasterCount() >= iBand+1 )
-                poBand->CloneInfo( poSrcDS->GetRasterBand(iBand+1), 
+                poBand->CloneInfo( poSrcDS->GetRasterBand(iBand+1),
                                    nCloneFlags );
             else
-                CPLDebug( "GDALPamDataset", "Skipping CloneInfo for band not in source, this is a bit unusual!" );
+                CPLDebug(
+                    "GDALPamDataset",
+                    "Skipping CloneInfo for band not in source, "
+                    "this is a bit unusual!" );
         }
     }
 
@@ -991,27 +975,31 @@ CPLErr GDALPamDataset::CloneInfo( GDALDataset *poSrcDS, int nCloneFlags )
 char **GDALPamDataset::GetFileList()
 
 {
-    VSIStatBufL sStatBuf;
     char **papszFileList = GDALDataset::GetFileList();
 
     if( psPam && psPam->osPhysicalFilename.size() > 0
         && CSLFindString( papszFileList, psPam->osPhysicalFilename ) == -1 )
     {
-        papszFileList = CSLInsertString( papszFileList, 0, 
+        papszFileList = CSLInsertString( papszFileList, 0,
                                          psPam->osPhysicalFilename );
     }
 
     if( psPam && psPam->pszPamFilename )
     {
-        int bAddPamFile = (nPamFlags & GPF_DIRTY);
+        int bAddPamFile = nPamFlags & GPF_DIRTY;
         if (!bAddPamFile)
         {
+            VSIStatBufL sStatBuf;
             if (oOvManager.GetSiblingFiles() != NULL && IsPamFilenameAPotentialSiblingFile())
+            {
                 bAddPamFile = CSLFindString(oOvManager.GetSiblingFiles(),
                                   CPLGetFilename(psPam->pszPamFilename)) >= 0;
+            }
             else
+            {
                 bAddPamFile = VSIStatExL( psPam->pszPamFilename, &sStatBuf,
                                           VSI_STAT_EXISTS_FLAG ) == 0;
+            }
         }
         if (bAddPamFile)
         {
@@ -1031,12 +1019,12 @@ char **GDALPamDataset::GetFileList()
 /*                          IBuildOverviews()                           */
 /************************************************************************/
 
-CPLErr GDALPamDataset::IBuildOverviews( const char *pszResampling, 
-                                        int nOverviews, int *panOverviewList, 
+CPLErr GDALPamDataset::IBuildOverviews( const char *pszResampling,
+                                        int nOverviews, int *panOverviewList,
                                         int nListBands, int *panBandList,
-                                        GDALProgressFunc pfnProgress, 
+                                        GDALProgressFunc pfnProgress,
                                         void * pProgressData )
-    
+
 {
 /* -------------------------------------------------------------------- */
 /*      Initialize PAM.                                                 */
@@ -1054,16 +1042,18 @@ CPLErr GDALPamDataset::IBuildOverviews( const char *pszResampling,
 /*      new overview file.                                              */
 /* -------------------------------------------------------------------- */
     if( oOvManager.IsInitialized() && psPam->osPhysicalFilename.length() != 0 )
-        return oOvManager.BuildOverviewsSubDataset( 
-            psPam->osPhysicalFilename, pszResampling, 
+    {
+        return oOvManager.BuildOverviewsSubDataset(
+            psPam->osPhysicalFilename, pszResampling,
             nOverviews, panOverviewList,
             nListBands, panBandList,
             pfnProgress, pProgressData );
-    else 
-        return GDALDataset::IBuildOverviews( pszResampling, 
-                                             nOverviews, panOverviewList, 
-                                             nListBands, panBandList, 
-                                             pfnProgress, pProgressData );
+    }
+
+    return GDALDataset::IBuildOverviews( pszResampling,
+                                         nOverviews, panOverviewList,
+                                         nListBands, panBandList,
+                                         pfnProgress, pProgressData );
 }
 
 
@@ -1076,8 +1066,8 @@ const char *GDALPamDataset::GetProjectionRef()
 {
     if( psPam && psPam->pszProjection )
         return psPam->pszProjection;
-    else
-        return GDALDataset::GetProjectionRef();
+
+    return GDALDataset::GetProjectionRef();
 }
 
 /************************************************************************/
@@ -1091,14 +1081,12 @@ CPLErr GDALPamDataset::SetProjection( const char *pszProjectionIn )
 
     if( psPam == NULL )
         return GDALDataset::SetProjection( pszProjectionIn );
-    else
-    {
-        CPLFree( psPam->pszProjection );
-        psPam->pszProjection = CPLStrdup( pszProjectionIn );
-        MarkPamDirty();
 
-        return CE_None;
-    }
+    CPLFree( psPam->pszProjection );
+    psPam->pszProjection = CPLStrdup( pszProjectionIn );
+    MarkPamDirty();
+
+    return CE_None;
 }
 
 /************************************************************************/
@@ -1113,8 +1101,8 @@ CPLErr GDALPamDataset::GetGeoTransform( double * padfTransform )
         memcpy( padfTransform, psPam->adfGeoTransform, sizeof(double) * 6 );
         return CE_None;
     }
-    else
-        return GDALDataset::GetGeoTransform( padfTransform );
+
+    return GDALDataset::GetGeoTransform( padfTransform );
 }
 
 /************************************************************************/
@@ -1133,10 +1121,8 @@ CPLErr GDALPamDataset::SetGeoTransform( double * padfTransform )
         memcpy( psPam->adfGeoTransform, padfTransform, sizeof(double) * 6 );
         return( CE_None );
     }
-    else
-    {
-        return GDALDataset::SetGeoTransform( padfTransform );
-    }
+
+    return GDALDataset::SetGeoTransform( padfTransform );
 }
 
 /************************************************************************/
@@ -1148,8 +1134,8 @@ int GDALPamDataset::GetGCPCount()
 {
     if( psPam && psPam->nGCPCount > 0 )
         return psPam->nGCPCount;
-    else
-        return GDALDataset::GetGCPCount();
+
+    return GDALDataset::GetGCPCount();
 }
 
 /************************************************************************/
@@ -1161,8 +1147,8 @@ const char *GDALPamDataset::GetGCPProjection()
 {
     if( psPam && psPam->pszGCPProjection != NULL )
         return psPam->pszGCPProjection;
-    else
-        return GDALDataset::GetGCPProjection();
+
+    return GDALDataset::GetGCPProjection();
 }
 
 /************************************************************************/
@@ -1174,8 +1160,8 @@ const GDAL_GCP *GDALPamDataset::GetGCPs()
 {
     if( psPam && psPam->nGCPCount > 0 )
         return psPam->pasGCPList;
-    else
-        return GDALDataset::GetGCPs();
+
+    return GDALDataset::GetGCPs();
 }
 
 /************************************************************************/
@@ -1205,17 +1191,15 @@ CPLErr GDALPamDataset::SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
 
         return CE_None;
     }
-    else
-    {
-        return GDALDataset::SetGCPs( nGCPCount, pasGCPList, pszGCPProjection );
-    }
+
+    return GDALDataset::SetGCPs( nGCPCount, pasGCPList, pszGCPProjection );
 }
 
 /************************************************************************/
 /*                            SetMetadata()                             */
 /************************************************************************/
 
-CPLErr GDALPamDataset::SetMetadata( char **papszMetadata, 
+CPLErr GDALPamDataset::SetMetadata( char **papszMetadata,
                                     const char *pszDomain )
 
 {
@@ -1234,8 +1218,8 @@ CPLErr GDALPamDataset::SetMetadata( char **papszMetadata,
 /*                          SetMetadataItem()                           */
 /************************************************************************/
 
-CPLErr GDALPamDataset::SetMetadataItem( const char *pszName, 
-                                        const char *pszValue, 
+CPLErr GDALPamDataset::SetMetadataItem( const char *pszName,
+                                        const char *pszValue,
                                         const char *pszDomain )
 
 {
@@ -1254,7 +1238,7 @@ CPLErr GDALPamDataset::SetMetadataItem( const char *pszName,
 /*                          GetMetadataItem()                           */
 /************************************************************************/
 
-const char *GDALPamDataset::GetMetadataItem( const char *pszName, 
+const char *GDALPamDataset::GetMetadataItem( const char *pszName,
                                              const char *pszDomain )
 
 {
@@ -1268,13 +1252,13 @@ const char *GDALPamDataset::GetMetadataItem( const char *pszName,
     {
         CPLString osPrelimOvr = GetDescription();
         osPrelimOvr += ":::OVR";
-        
+
         const char *pszProxyOvrFilename = PamAllocateProxy( osPrelimOvr );
         if( pszProxyOvrFilename == NULL )
             return NULL;
-        
+
         SetMetadataItem( "OVERVIEW_FILE", pszProxyOvrFilename, "OVERVIEWS" );
-        
+
         return pszProxyOvrFilename;
     }
 
@@ -1286,17 +1270,17 @@ const char *GDALPamDataset::GetMetadataItem( const char *pszName,
 /*      relative to the physical file the subdataset comes              */
 /*      from. (#3287).                                                  */
 /* -------------------------------------------------------------------- */
-    else if( pszDomain != NULL 
-             && EQUAL(pszDomain,"OVERVIEWS") 
+    else if( pszDomain != NULL
+             && EQUAL(pszDomain,"OVERVIEWS")
              && EQUAL(pszName,"OVERVIEW_FILE") )
     {
-        const char *pszOverviewFile = 
+        const char *pszOverviewFile =
             GDALDataset::GetMetadataItem( pszName, pszDomain );
 
-        if( pszOverviewFile == NULL 
-            || !EQUALN(pszOverviewFile,":::BASE:::",10) )
+        if( pszOverviewFile == NULL
+            || !STARTS_WITH_CI(pszOverviewFile, ":::BASE:::") )
             return pszOverviewFile;
-        
+
         CPLString osPath;
 
         if( strlen(GetPhysicalFilename()) > 0 )
@@ -1310,9 +1294,8 @@ const char *GDALPamDataset::GetMetadataItem( const char *pszName,
 /* -------------------------------------------------------------------- */
 /*      Everything else is a pass through.                              */
 /* -------------------------------------------------------------------- */
-    else
-        return GDALDataset::GetMetadataItem( pszName, pszDomain );
 
+    return GDALDataset::GetMetadataItem( pszName, pszDomain );
 }
 
 /************************************************************************/
@@ -1323,7 +1306,7 @@ char **GDALPamDataset::GetMetadata( const char *pszDomain )
 
 {
 //    if( pszDomain == NULL || !EQUAL(pszDomain,"ProxyOverviewRequest") )
-        return GDALDataset::GetMetadata( pszDomain );
+    return GDALDataset::GetMetadata( pszDomain );
 }
 
 /************************************************************************/
@@ -1397,7 +1380,7 @@ CPLErr GDALPamDataset::TryLoadAux(char **papszSiblingFiles)
     if( poAuxDS->GetGCPCount() > 0 )
     {
         psPam->nGCPCount = poAuxDS->GetGCPCount();
-        psPam->pasGCPList = GDALDuplicateGCPs( psPam->nGCPCount, 
+        psPam->pasGCPList = GDALDuplicateGCPs( psPam->nGCPCount,
                                                poAuxDS->GetGCPs() );
     }
 
@@ -1408,7 +1391,7 @@ CPLErr GDALPamDataset::TryLoadAux(char **papszSiblingFiles)
     char **papszMD = poAuxDS->GetMetadata();
     if( CSLCount(papszMD) > 0 )
     {
-        char **papszMerged = 
+        char **papszMerged =
             CSLMerge( CSLDuplicate(GetMetadata()), papszMD );
         GDALPamDataset::SetMetadata( papszMerged );
         CSLDestroy( papszMerged );
@@ -1417,7 +1400,7 @@ CPLErr GDALPamDataset::TryLoadAux(char **papszSiblingFiles)
     papszMD = poAuxDS->GetMetadata("XFORMS");
     if( CSLCount(papszMD) > 0 )
     {
-        char **papszMerged = 
+        char **papszMerged =
             CSLMerge( CSLDuplicate(GetMetadata("XFORMS")), papszMD );
         GDALPamDataset::SetMetadata( papszMerged, "XFORMS" );
         CSLDestroy( papszMerged );
@@ -1426,20 +1409,18 @@ CPLErr GDALPamDataset::TryLoadAux(char **papszSiblingFiles)
 /* ==================================================================== */
 /*      Process bands.                                                  */
 /* ==================================================================== */
-    int iBand;
-
-    for( iBand = 0; iBand < poAuxDS->GetRasterCount(); iBand++ )
+    for( int iBand = 0; iBand < poAuxDS->GetRasterCount(); iBand++ )
     {
         if( iBand >= GetRasterCount() )
             break;
 
-        GDALRasterBand *poAuxBand = poAuxDS->GetRasterBand( iBand+1 );
-        GDALRasterBand *poBand = GetRasterBand( iBand+1 );
+        GDALRasterBand * const poAuxBand = poAuxDS->GetRasterBand( iBand+1 );
+        GDALRasterBand * const poBand = GetRasterBand( iBand+1 );
 
         papszMD = poAuxBand->GetMetadata();
         if( CSLCount(papszMD) > 0 )
         {
-            char **papszMerged = 
+            char **papszMerged =
                 CSLMerge( CSLDuplicate(poBand->GetMetadata()), papszMD );
             poBand->SetMetadata( papszMerged );
             CSLDestroy( papszMerged );
@@ -1451,37 +1432,38 @@ CPLErr GDALPamDataset::TryLoadAux(char **papszSiblingFiles)
         if( poAuxBand->GetCategoryNames() != NULL )
             poBand->SetCategoryNames( poAuxBand->GetCategoryNames() );
 
-        if( poAuxBand->GetColorTable() != NULL 
+        if( poAuxBand->GetColorTable() != NULL
             && poBand->GetColorTable() == NULL )
             poBand->SetColorTable( poAuxBand->GetColorTable() );
 
         // histograms?
-        double dfMin, dfMax;
-        int nBuckets;
+        double dfMin = 0.0;
+        double dfMax = 0.0;
+        int nBuckets = 0;
         GUIntBig *panHistogram=NULL;
 
-        if( poAuxBand->GetDefaultHistogram( &dfMin, &dfMax, 
+        if( poAuxBand->GetDefaultHistogram( &dfMin, &dfMax,
                                             &nBuckets, &panHistogram,
                                             FALSE, NULL, NULL ) == CE_None )
         {
-            poBand->SetDefaultHistogram( dfMin, dfMax, nBuckets, 
+            poBand->SetDefaultHistogram( dfMin, dfMax, nBuckets,
                                          panHistogram );
             CPLFree( panHistogram );
         }
 
-        // RAT 
+        // RAT
         if( poAuxBand->GetDefaultRAT() != NULL )
             poBand->SetDefaultRAT( poAuxBand->GetDefaultRAT() );
 
         // NoData
         int bSuccess = FALSE;
-        double dfNoDataValue = poAuxBand->GetNoDataValue( &bSuccess );
+        const double dfNoDataValue = poAuxBand->GetNoDataValue( &bSuccess );
         if( bSuccess )
             poBand->SetNoDataValue( dfNoDataValue );
     }
 
     GDALClose( poAuxDS );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Mark PAM info as clean.                                         */
 /* -------------------------------------------------------------------- */
diff --git a/gcore/gdalpamproxydb.cpp b/gcore/gdalpamproxydb.cpp
index 4491519..5e274f9 100644
--- a/gcore/gdalpamproxydb.cpp
+++ b/gcore/gdalpamproxydb.cpp
@@ -1,11 +1,11 @@
 /******************************************************************************
- * $Id: gdalpamproxydb.cpp 28459 2015-02-12 13:48:21Z rouault $
+ * $Id: gdalpamproxydb.cpp 33766 2016-03-21 19:51:16Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of the GDAL PAM Proxy database interface.
  *           The proxy db is used to associate .aux.xml files in a temp
  *           directory - used for files for which aux.xml files can't be
- *           created (ie. read-only file systems). 
+ *           created (i.e. read-only file systems).
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -30,12 +30,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
+#include "cpl_multiproc.h"
 #include "cpl_string.h"
+#include "gdal_pam.h"
 #include "ogr_spatialref.h"
-#include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: gdalpamproxydb.cpp 28459 2015-02-12 13:48:21Z rouault $");
+CPL_CVSID("$Id: gdalpamproxydb.cpp 33766 2016-03-21 19:51:16Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -51,16 +51,16 @@ class GDALPamProxyDB
     CPLString   osProxyDBDir;
 
     int         nUpdateCounter;
-    
+
     std::vector<CPLString> aosOriginalFiles;
     std::vector<CPLString> aosProxyFiles;
 
     void        CheckLoadDB();
     void        LoadDB();
     void        SaveDB();
-}; 
+};
 
-static int bProxyDBInitialized = FALSE;
+static bool bProxyDBInitialized = FALSE;
 static GDALPamProxyDB *poProxyDB = NULL;
 static CPLMutex *hProxyDBLock = NULL;
 
@@ -91,7 +91,7 @@ void GDALPamProxyDB::LoadDB()
 /*      Open the database relating original names to proxy .aux.xml     */
 /*      file names.                                                     */
 /* -------------------------------------------------------------------- */
-    CPLString osDBName = 
+    CPLString osDBName =
         CPLFormFilename( osProxyDBDir, "gdal_pam_proxy", "dat" );
     VSILFILE *fpDB = VSIFOpenL( osDBName, "r" );
 
@@ -102,33 +102,45 @@ void GDALPamProxyDB::LoadDB()
 /* -------------------------------------------------------------------- */
 /*      Read header, verify and extract update counter.                 */
 /* -------------------------------------------------------------------- */
-    GByte  abyHeader[100];
+    const size_t nHeaderSize = 100;
+    GByte abyHeader[nHeaderSize] = { '\0' };
 
-    if( VSIFReadL( abyHeader, 1, 100, fpDB ) != 100 
-        || strncmp( (const char *) abyHeader, "GDAL_PROXY", 10 ) != 0 )
+    if( VSIFReadL( abyHeader, 1, nHeaderSize, fpDB ) != nHeaderSize
+        || !STARTS_WITH(reinterpret_cast<char *>(abyHeader), "GDAL_PROXY") )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Problem reading %s header - short or corrupt?", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Problem reading %s header - short or corrupt?",
                   osDBName.c_str() );
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpDB));
         return;
     }
 
-    nUpdateCounter = atoi((const char *) abyHeader + 10);
+    nUpdateCounter = atoi(reinterpret_cast<char *>(abyHeader) + 10);
 
 /* -------------------------------------------------------------------- */
 /*      Read the file in one gulp.                                      */
 /* -------------------------------------------------------------------- */
-    int nBufLength;
-    char *pszDBData;
-
-    VSIFSeekL( fpDB, 0, SEEK_END );
-    nBufLength = (int) (VSIFTellL(fpDB) - 100);
-
-    pszDBData = (char *) CPLCalloc(1,nBufLength+1);
-    VSIFSeekL( fpDB, 100, SEEK_SET );
-    VSIFReadL( pszDBData, 1, nBufLength, fpDB );
+    if( VSIFSeekL( fpDB, 0, SEEK_END ) != 0 )
+    {
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpDB));
+        return;
+    }
+    const int nBufLength = static_cast<int>(VSIFTellL(fpDB) - nHeaderSize);
+    if( VSIFSeekL( fpDB, nHeaderSize, SEEK_SET ) != 0 )
+    {
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpDB));
+        return;
+    }
+    char *pszDBData = static_cast<char *>( CPLCalloc(1,nBufLength+1) );
+    if( VSIFReadL( pszDBData, 1, nBufLength, fpDB ) !=
+        static_cast<size_t>(nBufLength) )
+    {
+        CPLFree(pszDBData);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpDB));
+        return;
+    }
 
-    VSIFCloseL( fpDB );
+    CPL_IGNORE_RET_VAL(VSIFCloseL( fpDB ));
 
 /* -------------------------------------------------------------------- */
 /*      Parse the list of in/out names.                                 */
@@ -137,18 +149,17 @@ void GDALPamProxyDB::LoadDB()
 
     while( iNext < nBufLength )
     {
-        CPLString osOriginal, osProxy;
-
+        CPLString osOriginal;
         osOriginal.assign( pszDBData + iNext );
 
         for( ; iNext < nBufLength && pszDBData[iNext] != '\0'; iNext++ ) {}
-        
+
         if( iNext == nBufLength )
             break;
-        
+
         iNext++;
 
-        osProxy = osProxyDBDir;
+        CPLString osProxy = osProxyDBDir;
         osProxy += "/";
         osProxy += pszDBData + iNext;
 
@@ -157,7 +168,7 @@ void GDALPamProxyDB::LoadDB()
 
         aosOriginalFiles.push_back( osOriginal );
         aosProxyFiles.push_back( osProxy );
-    }        
+    }
 
     CPLFree( pszDBData );
 }
@@ -173,16 +184,17 @@ void GDALPamProxyDB::SaveDB()
 /*      Open the database relating original names to proxy .aux.xml     */
 /*      file names.                                                     */
 /* -------------------------------------------------------------------- */
-    CPLString osDBName = 
+    CPLString osDBName =
         CPLFormFilename( osProxyDBDir, "gdal_pam_proxy", "dat" );
-    
+
     void *hLock = CPLLockFile( osDBName, 1.0 );
 
     // proceed even if lock fails - we need CPLBreakLockFile()!
     if( hLock == NULL )
     {
         CPLError( CE_Warning, CPLE_AppDefined,
-                  "GDALPamProxyDB::SaveDB() - Failed to lock %s file, proceeding anyways.",
+                  "GDALPamProxyDB::SaveDB() - "
+                  "Failed to lock %s file, proceeding anyways.",
                   osDBName.c_str() );
     }
 
@@ -192,8 +204,8 @@ void GDALPamProxyDB::SaveDB()
         if( hLock )
             CPLUnlockFile( hLock );
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Failed to save %s Pam Proxy DB.\n%s", 
-                  osDBName.c_str(), 
+                  "Failed to save %s Pam Proxy DB.\n%s",
+                  osDBName.c_str(),
                   VSIStrerror( errno ) );
         return;
     }
@@ -201,44 +213,57 @@ void GDALPamProxyDB::SaveDB()
 /* -------------------------------------------------------------------- */
 /*      Write header.                                                   */
 /* -------------------------------------------------------------------- */
-    GByte  abyHeader[100];
+    const size_t nHeaderSize = 100;
+    GByte abyHeader[nHeaderSize] = { '\0' };
 
     memset( abyHeader, ' ', sizeof(abyHeader) );
-    strncpy( (char *) abyHeader, "GDAL_PROXY", 10 );
-    sprintf( (char *) abyHeader + 10, "%9d", nUpdateCounter );
+    memcpy( reinterpret_cast<char *>(abyHeader), "GDAL_PROXY", 10 );
+    snprintf( reinterpret_cast<char *>(abyHeader) + 10, sizeof(abyHeader) - 10,
+              "%9d", nUpdateCounter );
 
-    VSIFWriteL( abyHeader, 1, 100, fpDB );
+    if( VSIFWriteL( abyHeader, 1, nHeaderSize, fpDB ) != nHeaderSize )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Failed to write complete %s Pam Proxy DB.\n%s",
+                  osDBName.c_str(),
+                  VSIStrerror( errno ) );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fpDB ));
+        VSIUnlink( osDBName );
+        if( hLock )
+            CPLUnlockFile( hLock );
+        return;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Write names.                                                    */
 /* -------------------------------------------------------------------- */
-    unsigned int i;
-
-    for( i = 0; i < aosOriginalFiles.size(); i++ )
+    for( unsigned int i = 0; i < aosOriginalFiles.size(); i++ )
     {
-        size_t nBytesWritten;
-        const char *pszProxyFile;
+        size_t nCount = VSIFWriteL( aosOriginalFiles[i].c_str(),
+                    strlen(aosOriginalFiles[i].c_str())+1, 1, fpDB );
 
-        VSIFWriteL( aosOriginalFiles[i].c_str(), 1, 
-                    strlen(aosOriginalFiles[i].c_str())+1, fpDB );
+        const char *pszProxyFile = CPLGetFilename(aosProxyFiles[i]);
+        nCount += VSIFWriteL( pszProxyFile,
+                                    strlen(pszProxyFile)+1, 1, fpDB );
 
-        pszProxyFile = CPLGetFilename(aosProxyFiles[i]);
-        nBytesWritten = VSIFWriteL( pszProxyFile, 1, 
-                                    strlen(pszProxyFile)+1, fpDB );
-
-        if( nBytesWritten != strlen(pszProxyFile)+1 )
+        if( nCount != 2 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Failed to write complete %s Pam Proxy DB.\n%s",
-                      osDBName.c_str(), 
+                      osDBName.c_str(),
                       VSIStrerror( errno ) );
-            VSIFCloseL( fpDB );
+            CPL_IGNORE_RET_VAL(VSIFCloseL( fpDB ));
             VSIUnlink( osDBName );
+            if( hLock )
+                CPLUnlockFile( hLock );
             return;
         }
     }
 
-    VSIFCloseL( fpDB );
+    if( VSIFCloseL( fpDB ) != 0 )
+    {
+        CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+    }
 
     if( hLock )
         CPLUnlockFile( hLock );
@@ -260,7 +285,7 @@ static void InitProxyDB()
 
         if( !bProxyDBInitialized )
         {
-            const char *pszProxyDir = 
+            const char *pszProxyDir =
                 CPLGetConfigOption( "GDAL_PAM_PROXY_DIR", NULL );
 
             if( pszProxyDir )
@@ -270,7 +295,7 @@ static void InitProxyDB()
             }
         }
 
-        bProxyDBInitialized = TRUE;
+        bProxyDBInitialized = true;
     }
 }
 
@@ -283,9 +308,9 @@ void PamCleanProxyDB()
 {
     {
         CPLMutexHolderD( &hProxyDBLock );
-        
-        bProxyDBInitialized = FALSE;
-        
+
+        bProxyDBInitialized = false;
+
         delete poProxyDB;
         poProxyDB = NULL;
     }
@@ -307,11 +332,10 @@ const char *PamGetProxy( const char *pszOriginal )
         return NULL;
 
     CPLMutexHolderD( &hProxyDBLock );
-    unsigned int i;
 
     poProxyDB->CheckLoadDB();
-    
-    for( i = 0; i < poProxyDB->aosOriginalFiles.size(); i++ )
+
+    for( unsigned int i = 0; i < poProxyDB->aosOriginalFiles.size(); i++ )
     {
         if( strcmp( poProxyDB->aosOriginalFiles[i], pszOriginal ) == 0 )
             return poProxyDB->aosProxyFiles[i];
@@ -346,22 +370,21 @@ const char *PamAllocateProxy( const char *pszOriginal )
 /*      We also need to be careful about length.                        */
 /* -------------------------------------------------------------------- */
     CPLString osRevProxyFile;
-    int   i;
 
-    i = strlen(pszOriginal) - 1;
+    int i = static_cast<int>(strlen(pszOriginal)) - 1;
     while( i >= 0 && osRevProxyFile.size() < 220 )
     {
-        if( i > 6 && EQUALN(pszOriginal+i-5,":::OVR",6) )
+        if( i > 6 && STARTS_WITH_CI(pszOriginal+i-5, ":::OVR") )
             i -= 6;
 
         // make some effort to break long names at path delimiters.
-        if( (pszOriginal[i] == '/' || pszOriginal[i] == '\\') 
+        if( (pszOriginal[i] == '/' || pszOriginal[i] == '\\')
             && osRevProxyFile.size() > 200 )
             break;
 
-        if( (pszOriginal[i] >= 'A' && pszOriginal[i] <= 'Z') 
-            || (pszOriginal[i] >= 'a' && pszOriginal[i] <= 'z') 
-            || (pszOriginal[i] >= '0' && pszOriginal[i] <= '9') 
+        if( (pszOriginal[i] >= 'A' && pszOriginal[i] <= 'Z')
+            || (pszOriginal[i] >= 'a' && pszOriginal[i] <= 'z')
+            || (pszOriginal[i] >= '0' && pszOriginal[i] <= '9')
             || pszOriginal[i] == '.' )
             osRevProxyFile += pszOriginal[i];
         else
@@ -369,17 +392,15 @@ const char *PamAllocateProxy( const char *pszOriginal )
 
         i--;
     }
-    
-    CPLString osOriginal = pszOriginal;
-    CPLString osProxy;
-    CPLString osCounter;
 
-    osProxy = poProxyDB->osProxyDBDir + "/";
+    CPLString osOriginal = pszOriginal;
+    CPLString osProxy = poProxyDB->osProxyDBDir + "/";
 
+    CPLString osCounter;
     osCounter.Printf( "%06d_", poProxyDB->nUpdateCounter++ );
     osProxy += osCounter;
 
-    for( i = osRevProxyFile.size()-1; i >= 0; i-- )
+    for( i = static_cast<int>(osRevProxyFile.size())-1; i >= 0; i-- )
         osProxy += osRevProxyFile[i];
 
     if( osOriginal.find(":::OVR") != CPLString::npos )
diff --git a/gcore/gdalpamrasterband.cpp b/gcore/gdalpamrasterband.cpp
index 6976451..b93b721 100644
--- a/gcore/gdalpamrasterband.cpp
+++ b/gcore/gdalpamrasterband.cpp
@@ -1,10 +1,10 @@
 /******************************************************************************
- * $Id: gdalpamrasterband.cpp 32191 2015-12-16 16:14:07Z rouault $
+ * $Id: gdalpamrasterband.cpp 33694 2016-03-10 17:54:30Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALPamRasterBand, a raster band base class
  *           that knows how to persistently store auxiliary metadata in an
- *           external xml file. 
+ *           external xml file.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -34,7 +34,7 @@
 #include "gdal_rat.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: gdalpamrasterband.cpp 32191 2015-12-16 16:14:07Z rouault $");
+CPL_CVSID("$Id: gdalpamrasterband.cpp 33694 2016-03-10 17:54:30Z goatbar $");
 
 /************************************************************************/
 /*                         GDALPamRasterBand()                          */
@@ -48,6 +48,17 @@ GDALPamRasterBand::GDALPamRasterBand()
 }
 
 /************************************************************************/
+/*                         GDALPamRasterBand()                          */
+/************************************************************************/
+
+GDALPamRasterBand::GDALPamRasterBand(int bForceCachedIOIn) : GDALRasterBand(bForceCachedIOIn)
+
+{
+    psPam = NULL;
+    SetMOFlags( GetMOFlags() | GMO_PAM_CLASS );
+}
+
+/************************************************************************/
 /*                         ~GDALPamRasterBand()                         */
 /************************************************************************/
 
@@ -89,11 +100,11 @@ CPLXMLNode *GDALPamRasterBand::SerializeToXML( CPL_UNUSED const char *pszUnused
         if (CPLIsNan(psPam->dfNoDataValue))
             CPLSetXMLValue( psTree, "NoDataValue",  "nan" );
         else
-            CPLSetXMLValue( psTree, "NoDataValue", 
+            CPLSetXMLValue( psTree, "NoDataValue",
                             oFmt.Printf( "%.14E", psPam->dfNoDataValue ) );
 
         /* hex encode real floating point values */
-        if( psPam->dfNoDataValue != floor(psPam->dfNoDataValue) 
+        if( psPam->dfNoDataValue != floor(psPam->dfNoDataValue)
             || psPam->dfNoDataValue != CPLAtof(oFmt) )
         {
             double dfNoDataLittleEndian;
@@ -101,7 +112,7 @@ CPLXMLNode *GDALPamRasterBand::SerializeToXML( CPL_UNUSED const char *pszUnused
             dfNoDataLittleEndian = psPam->dfNoDataValue;
             CPL_LSBPTR64( &dfNoDataLittleEndian );
 
-            char *pszHexEncoding = 
+            char *pszHexEncoding =
                 CPLBinaryToHex( 8, (GByte *) &dfNoDataLittleEndian );
             CPLSetXMLValue( psTree, "NoDataValue.#le_hex_equiv",pszHexEncoding);
             CPLFree( pszHexEncoding );
@@ -112,15 +123,15 @@ CPLXMLNode *GDALPamRasterBand::SerializeToXML( CPL_UNUSED const char *pszUnused
         CPLSetXMLValue( psTree, "UnitType", psPam->pszUnitType );
 
     if( psPam->dfOffset != 0.0 )
-        CPLSetXMLValue( psTree, "Offset", 
+        CPLSetXMLValue( psTree, "Offset",
                         oFmt.Printf( "%.16g", psPam->dfOffset ) );
 
     if( psPam->dfScale != 1.0 )
-        CPLSetXMLValue( psTree, "Scale", 
+        CPLSetXMLValue( psTree, "Scale",
                         oFmt.Printf( "%.16g", psPam->dfScale ) );
 
     if( psPam->eColorInterp != GCI_Undefined )
-        CPLSetXMLValue( psTree, "ColorInterp", 
+        CPLSetXMLValue( psTree, "ColorInterp",
                         GDALGetColorInterpretationName( psPam->eColorInterp ));
 
 /* -------------------------------------------------------------------- */
@@ -128,7 +139,7 @@ CPLXMLNode *GDALPamRasterBand::SerializeToXML( CPL_UNUSED const char *pszUnused
 /* -------------------------------------------------------------------- */
     if( psPam->papszCategoryNames != NULL )
     {
-        CPLXMLNode *psCT_XML = CPLCreateXMLNode( psTree, CXT_Element, 
+        CPLXMLNode *psCT_XML = CPLCreateXMLNode( psTree, CXT_Element,
                                                  "CategoryNames" );
         CPLXMLNode* psLastChild = NULL;
 
@@ -149,11 +160,11 @@ CPLXMLNode *GDALPamRasterBand::SerializeToXML( CPL_UNUSED const char *pszUnused
 /* -------------------------------------------------------------------- */
     if( psPam->poColorTable != NULL )
     {
-        CPLXMLNode *psCT_XML = CPLCreateXMLNode( psTree, CXT_Element, 
+        CPLXMLNode *psCT_XML = CPLCreateXMLNode( psTree, CXT_Element,
                                                  "ColorTable" );
         CPLXMLNode* psLastChild = NULL;
 
-        for( int iEntry=0; iEntry < psPam->poColorTable->GetColorEntryCount(); 
+        for( int iEntry=0; iEntry < psPam->poColorTable->GetColorEntryCount();
              iEntry++ )
         {
             GDALColorEntry sEntry;
@@ -166,7 +177,7 @@ CPLXMLNode *GDALPamRasterBand::SerializeToXML( CPL_UNUSED const char *pszUnused
             psLastChild = psEntry_XML;
 
             psPam->poColorTable->GetColorEntryAsRGB( iEntry, &sEntry );
-            
+
             CPLSetXMLValue( psEntry_XML, "#c1", oFmt.Printf("%d",sEntry.c1) );
             CPLSetXMLValue( psEntry_XML, "#c2", oFmt.Printf("%d",sEntry.c2) );
             CPLSetXMLValue( psEntry_XML, "#c3", oFmt.Printf("%d",sEntry.c3) );
@@ -179,9 +190,9 @@ CPLXMLNode *GDALPamRasterBand::SerializeToXML( CPL_UNUSED const char *pszUnused
 /* -------------------------------------------------------------------- */
     if( psPam->bHaveMinMax )
     {
-        CPLSetXMLValue( psTree, "Minimum", 
+        CPLSetXMLValue( psTree, "Minimum",
                         oFmt.Printf( "%.16g", psPam->dfMin ) );
-        CPLSetXMLValue( psTree, "Maximum", 
+        CPLSetXMLValue( psTree, "Maximum",
                         oFmt.Printf( "%.16g", psPam->dfMax ) );
     }
 
@@ -190,9 +201,9 @@ CPLXMLNode *GDALPamRasterBand::SerializeToXML( CPL_UNUSED const char *pszUnused
 /* -------------------------------------------------------------------- */
     if( psPam->bHaveStats )
     {
-        CPLSetXMLValue( psTree, "Mean", 
+        CPLSetXMLValue( psTree, "Mean",
                         oFmt.Printf( "%.16g", psPam->dfMean ) );
-        CPLSetXMLValue( psTree, "StandardDeviation", 
+        CPLSetXMLValue( psTree, "StandardDeviation",
                         oFmt.Printf( "%.16g", psPam->dfStdDev ) );
     }
 
@@ -246,21 +257,24 @@ void GDALPamRasterBand::PamInitialize()
     if( psPam )
         return;
 
-    GDALPamDataset *poParentDS = (GDALPamDataset *) GetDataset();
-
-    if( poParentDS == NULL || !(poParentDS->GetMOFlags() & GMO_PAM_CLASS) )
+    GDALDataset* poNonPamParentDS = GetDataset();
+    if( poNonPamParentDS == NULL || !(poNonPamParentDS->GetMOFlags() & GMO_PAM_CLASS) )
         return;
 
+    GDALPamDataset *poParentDS = (GDALPamDataset *) poNonPamParentDS;
+
     poParentDS->PamInitialize();
     if( poParentDS->psPam == NULL )
         return;
 
-    // Often (always?) initializing our parent will have initialized us. 
+    // Often (always?) initializing our parent will have initialized us.
     if( psPam != NULL )
         return;
 
     psPam = (GDALRasterBandPamInfo *)
-        CPLCalloc(sizeof(GDALRasterBandPamInfo),1);
+        VSI_CALLOC_VERBOSE(sizeof(GDALRasterBandPamInfo),1);
+    if( psPam == NULL )
+        return;
 
     psPam->dfScale = 1.0;
     psPam->poParentDS = poParentDS;
@@ -280,7 +294,7 @@ void GDALPamRasterBand::PamClear()
         if( psPam->poColorTable )
             delete psPam->poColorTable;
         psPam->poColorTable = NULL;
-        
+
         CPLFree( psPam->pszUnitType );
         CSLDestroy( psPam->papszCategoryNames );
 
@@ -318,10 +332,10 @@ CPLErr GDALPamRasterBand::XMLInit( CPLXMLNode *psTree, CPL_UNUSED const char *ps
 /*      Collect various other items of metadata.                        */
 /* -------------------------------------------------------------------- */
     GDALMajorObject::SetDescription( CPLGetXMLValue( psTree, "Description", "" ) );
-    
+
     if( CPLGetXMLValue( psTree, "NoDataValue", NULL ) != NULL )
     {
-        const char *pszLEHex = 
+        const char *pszLEHex =
             CPLGetXMLValue( psTree, "NoDataValue.le_hex_equiv", NULL );
         if( pszLEHex != NULL )
         {
@@ -330,26 +344,26 @@ CPLErr GDALPamRasterBand::XMLInit( CPLXMLNode *psTree, CPL_UNUSED const char *ps
             if( nBytes == 8 )
             {
                 CPL_LSBPTR64( pabyBin );
-                
+
                 GDALPamRasterBand::SetNoDataValue( *((double *) pabyBin) );
             }
             else
             {
-                GDALPamRasterBand::SetNoDataValue( 
+                GDALPamRasterBand::SetNoDataValue(
                     CPLAtof(CPLGetXMLValue( psTree, "NoDataValue", "0" )) );
             }
             CPLFree( pabyBin );
         }
         else
         {
-            GDALPamRasterBand::SetNoDataValue( 
+            GDALPamRasterBand::SetNoDataValue(
                 CPLAtof(CPLGetXMLValue( psTree, "NoDataValue", "0" )) );
         }
     }
 
-    GDALPamRasterBand::SetOffset( 
+    GDALPamRasterBand::SetOffset(
         CPLAtof(CPLGetXMLValue( psTree, "Offset", "0.0" )) );
-    GDALPamRasterBand::SetScale( 
+    GDALPamRasterBand::SetScale(
         CPLAtof(CPLGetXMLValue( psTree, "Scale", "1.0" )) );
 
     GDALPamRasterBand::SetUnitType( CPLGetXMLValue( psTree, "UnitType", NULL));
@@ -373,15 +387,15 @@ CPLErr GDALPamRasterBand::XMLInit( CPLXMLNode *psTree, CPL_UNUSED const char *ps
              psEntry != NULL; psEntry = psEntry->psNext )
         {
             /* Don't skeep <Category> tag with empty content */
-            if( psEntry->eType != CXT_Element 
-                || !EQUAL(psEntry->pszValue,"Category") 
+            if( psEntry->eType != CXT_Element
+                || !EQUAL(psEntry->pszValue,"Category")
                 || (psEntry->psChild != NULL && psEntry->psChild->eType != CXT_Text) )
                 continue;
-            
-            oCategoryNames.AddString( 
+
+            oCategoryNames.AddString(
                                  (psEntry->psChild) ? psEntry->psChild->pszValue : "" );
         }
-        
+
         GDALPamRasterBand::SetCategoryNames( oCategoryNames.List() );
     }
 
@@ -406,14 +420,14 @@ CPLErr GDALPamRasterBand::XMLInit( CPLXMLNode *psTree, CPL_UNUSED const char *ps
 
             oTable.SetColorEntry( iEntry++, &sCEntry );
         }
-        
+
         GDALPamRasterBand::SetColorTable( &oTable );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Do we have a complete set of stats?                             */
 /* -------------------------------------------------------------------- */
-    if( CPLGetXMLNode( psTree, "Minimum" ) != NULL 
+    if( CPLGetXMLNode( psTree, "Minimum" ) != NULL
         && CPLGetXMLNode( psTree, "Maximum" ) != NULL )
     {
         psPam->bHaveMinMax = TRUE;
@@ -421,7 +435,7 @@ CPLErr GDALPamRasterBand::XMLInit( CPLXMLNode *psTree, CPL_UNUSED const char *ps
         psPam->dfMax = CPLAtof(CPLGetXMLValue(psTree, "Maximum","0"));
     }
 
-    if( CPLGetXMLNode( psTree, "Mean" ) != NULL 
+    if( CPLGetXMLNode( psTree, "Mean" ) != NULL
         && CPLGetXMLNode( psTree, "StandardDeviation" ) != NULL )
     {
         psPam->bHaveStats = TRUE;
@@ -469,7 +483,7 @@ CPLErr GDALPamRasterBand::XMLInit( CPLXMLNode *psTree, CPL_UNUSED const char *ps
 /*                             CloneInfo()                              */
 /************************************************************************/
 
-CPLErr GDALPamRasterBand::CloneInfo( GDALRasterBand *poSrcBand, 
+CPLErr GDALPamRasterBand::CloneInfo( GDALRasterBand *poSrcBand,
                                      int nCloneFlags )
 
 {
@@ -492,7 +506,7 @@ CPLErr GDALPamRasterBand::CloneInfo( GDALRasterBand *poSrcBand,
     {
         if( poSrcBand->GetMetadata() != NULL )
         {
-            if( !bOnlyIfMissing 
+            if( !bOnlyIfMissing
              || CSLCount(GetMetadata()) != CSLCount(poSrcBand->GetMetadata()) )
             {
                 SetMetadata( poSrcBand->GetMetadata() );
@@ -518,11 +532,11 @@ CPLErr GDALPamRasterBand::CloneInfo( GDALRasterBand *poSrcBand,
     if( nCloneFlags & GCIF_NODATA )
     {
         double dfNoData = poSrcBand->GetNoDataValue( &bSuccess );
-        
+
         if( bSuccess )
         {
-            if( !bOnlyIfMissing 
-                || GetNoDataValue( &bSuccess ) != dfNoData 
+            if( !bOnlyIfMissing
+                || GetNoDataValue( &bSuccess ) != dfNoData
                 || !bSuccess )
                 GDALPamRasterBand::SetNoDataValue( dfNoData );
         }
@@ -546,7 +560,7 @@ CPLErr GDALPamRasterBand::CloneInfo( GDALRasterBand *poSrcBand,
     if( nCloneFlags & GCIF_SCALEOFFSET )
     {
         double dfOffset = poSrcBand->GetOffset( &bSuccess );
-        
+
         if( bSuccess )
         {
             if( !bOnlyIfMissing || GetOffset() != dfOffset )
@@ -554,7 +568,7 @@ CPLErr GDALPamRasterBand::CloneInfo( GDALRasterBand *poSrcBand,
         }
 
         double dfScale = poSrcBand->GetScale( &bSuccess );
-        
+
         if( bSuccess )
         {
             if( !bOnlyIfMissing || GetScale() != dfScale )
@@ -569,7 +583,7 @@ CPLErr GDALPamRasterBand::CloneInfo( GDALRasterBand *poSrcBand,
     {
         if( strlen(poSrcBand->GetUnitType()) > 0 )
         {
-            if( !bOnlyIfMissing 
+            if( !bOnlyIfMissing
                 || !EQUAL(GetUnitType(),poSrcBand->GetUnitType()) )
             {
                 GDALPamRasterBand::SetUnitType( poSrcBand->GetUnitType() );
@@ -585,9 +599,9 @@ CPLErr GDALPamRasterBand::CloneInfo( GDALRasterBand *poSrcBand,
         if( poSrcBand->GetColorInterpretation() != GCI_Undefined )
         {
             if( !bOnlyIfMissing
-                || poSrcBand->GetColorInterpretation() 
+                || poSrcBand->GetColorInterpretation()
                 != GetColorInterpretation() )
-                GDALPamRasterBand::SetColorInterpretation( 
+                GDALPamRasterBand::SetColorInterpretation(
                     poSrcBand->GetColorInterpretation() );
         }
     }
@@ -601,7 +615,7 @@ CPLErr GDALPamRasterBand::CloneInfo( GDALRasterBand *poSrcBand,
         {
             if( !bOnlyIfMissing || GetColorTable() == NULL )
             {
-                GDALPamRasterBand::SetColorTable( 
+                GDALPamRasterBand::SetColorTable(
                     poSrcBand->GetColorTable() );
             }
         }
@@ -635,7 +649,7 @@ CPLErr GDALPamRasterBand::CloneInfo( GDALRasterBand *poSrcBand,
 /*                            SetMetadata()                             */
 /************************************************************************/
 
-CPLErr GDALPamRasterBand::SetMetadata( char **papszMetadata, 
+CPLErr GDALPamRasterBand::SetMetadata( char **papszMetadata,
                                     const char *pszDomain )
 
 {
@@ -651,8 +665,8 @@ CPLErr GDALPamRasterBand::SetMetadata( char **papszMetadata,
 /*                          SetMetadataItem()                           */
 /************************************************************************/
 
-CPLErr GDALPamRasterBand::SetMetadataItem( const char *pszName, 
-                                        const char *pszValue, 
+CPLErr GDALPamRasterBand::SetMetadataItem( const char *pszName,
+                                        const char *pszValue,
                                         const char *pszDomain )
 
 {
@@ -685,6 +699,26 @@ CPLErr GDALPamRasterBand::SetNoDataValue( double dfNewValue )
 }
 
 /************************************************************************/
+/*                          DeleteNoDataValue()                         */
+/************************************************************************/
+
+CPLErr GDALPamRasterBand::DeleteNoDataValue()
+
+{
+    PamInitialize();
+
+    if( psPam )
+    {
+        psPam->bNoDataValueSet = FALSE;
+        psPam->dfNoDataValue = 0.0;
+        psPam->poParentDS->MarkPamDirty();
+        return CE_None;
+    }
+    else
+        return GDALRasterBand::DeleteNoDataValue();
+}
+
+/************************************************************************/
 /*                           GetNoDataValue()                           */
 /************************************************************************/
 
@@ -713,7 +747,7 @@ double GDALPamRasterBand::GetOffset( int *pbSuccess )
     {
         if( pbSuccess != NULL )
             *pbSuccess = TRUE;
-        
+
         return psPam->dfOffset;
     }
     else
@@ -754,7 +788,7 @@ double GDALPamRasterBand::GetScale( int *pbSuccess )
     {
         if( pbSuccess != NULL )
             *pbSuccess = TRUE;
-        
+
         return psPam->dfScale;
     }
     else
@@ -856,14 +890,14 @@ CPLErr GDALPamRasterBand::SetCategoryNames( char ** papszNewNames )
 {
     PamInitialize();
 
-    if( psPam ) 
+    if( psPam )
     {
         CSLDestroy( psPam->papszCategoryNames );
         psPam->papszCategoryNames = CSLDuplicate( papszNewNames );
         psPam->poParentDS->MarkPamDirty();
         return CE_None;
     }
-    else 
+    else
         return GDALRasterBand::SetCategoryNames( papszNewNames );
 
 }
@@ -898,7 +932,7 @@ CPLErr GDALPamRasterBand::SetColorTable( GDALColorTable *poTableIn )
             delete psPam->poColorTable;
             psPam->poColorTable = NULL;
         }
-        
+
         if( poTableIn )
         {
             psPam->poColorTable = poTableIn->Clone();
@@ -926,7 +960,7 @@ CPLErr GDALPamRasterBand::SetColorInterpretation( GDALColorInterp eInterpIn )
     if( psPam )
     {
         psPam->poParentDS->MarkPamDirty();
-        
+
         psPam->eColorInterp = eInterpIn;
 
         return CE_None;
@@ -962,7 +996,7 @@ void GDALPamRasterBand::SetDescription( const char *pszDescription )
 
     if( psPam && strcmp(pszDescription,GetDescription()) != 0 )
         psPam->poParentDS->MarkPamDirty();
-    
+
     GDALRasterBand::SetDescription( pszDescription );
 }
 
@@ -990,9 +1024,9 @@ PamParseHistogram( CPLXMLNode *psHistItem,
     if( ppanHistogram == NULL )
         return TRUE;
 
-    // Fetch the histogram and use it. 
+    // Fetch the histogram and use it.
     int iBucket;
-    const char *pszHistCounts = CPLGetXMLValue( psHistItem, 
+    const char *pszHistCounts = CPLGetXMLValue( psHistItem,
                                                 "HistCounts", "" );
 
     /* Sanity check to test consistency of BucketCount and HistCounts */
@@ -1014,14 +1048,14 @@ PamParseHistogram( CPLXMLNode *psHistItem,
     for( iBucket = 0; iBucket < *pnBuckets; iBucket++ )
     {
         (*ppanHistogram)[iBucket] = CPLAtoGIntBig(pszHistCounts);
-        
+
         // skip to next number.
         while( *pszHistCounts != '\0' && *pszHistCounts != '|' )
             pszHistCounts++;
         if( *pszHistCounts == '|' )
             pszHistCounts++;
     }
-    
+
     return TRUE;
 }
 
@@ -1030,7 +1064,7 @@ PamParseHistogram( CPLXMLNode *psHistItem,
 /************************************************************************/
 CPLXMLNode *
 PamFindMatchingHistogram( CPLXMLNode *psSavedHistograms,
-                          double dfMin, double dfMax, int nBuckets, 
+                          double dfMin, double dfMax, int nBuckets,
                           int bIncludeOutOfRange, int bApproxOK )
 
 {
@@ -1050,11 +1084,11 @@ PamFindMatchingHistogram( CPLXMLNode *psSavedHistograms,
 
         if( !(ARE_REAL_EQUAL(dfHistMin, dfMin))
             || !(ARE_REAL_EQUAL(dfHistMax, dfMax))
-            || atoi(CPLGetXMLValue( psXMLHist, 
+            || atoi(CPLGetXMLValue( psXMLHist,
                                     "BucketCount","0")) != nBuckets
-            || !atoi(CPLGetXMLValue( psXMLHist, 
-                                     "IncludeOutOfRange","0")) != !bIncludeOutOfRange 
-            || (!bApproxOK && atoi(CPLGetXMLValue( psXMLHist, 
+            || !atoi(CPLGetXMLValue( psXMLHist,
+                                     "IncludeOutOfRange","0")) != !bIncludeOutOfRange
+            || (!bApproxOK && atoi(CPLGetXMLValue( psXMLHist,
                                                    "Approximate","0"))) )
 
             continue;
@@ -1076,7 +1110,8 @@ PamHistogramToXMLTree( double dfMin, double dfMax,
 
 {
     char *pszHistCounts;
-    int iBucket, iHistOffset;
+    int iBucket;
+    size_t iHistOffset;
     CPLXMLNode *psXMLHist;
     CPLString oFmt;
 
@@ -1090,27 +1125,29 @@ PamHistogramToXMLTree( double dfMin, double dfMax,
 
     psXMLHist = CPLCreateXMLNode( NULL, CXT_Element, "HistItem" );
 
-    CPLSetXMLValue( psXMLHist, "HistMin", 
+    CPLSetXMLValue( psXMLHist, "HistMin",
                     oFmt.Printf( "%.16g", dfMin ));
-    CPLSetXMLValue( psXMLHist, "HistMax", 
+    CPLSetXMLValue( psXMLHist, "HistMax",
                     oFmt.Printf( "%.16g", dfMax ));
-    CPLSetXMLValue( psXMLHist, "BucketCount", 
+    CPLSetXMLValue( psXMLHist, "BucketCount",
                     oFmt.Printf( "%d", nBuckets ));
-    CPLSetXMLValue( psXMLHist, "IncludeOutOfRange", 
+    CPLSetXMLValue( psXMLHist, "IncludeOutOfRange",
                     oFmt.Printf( "%d", bIncludeOutOfRange ));
-    CPLSetXMLValue( psXMLHist, "Approximate", 
+    CPLSetXMLValue( psXMLHist, "Approximate",
                     oFmt.Printf( "%d", bApprox ));
 
     iHistOffset = 0;
     pszHistCounts[0] = '\0';
     for( iBucket = 0; iBucket < nBuckets; iBucket++ )
     {
-        sprintf( pszHistCounts + iHistOffset, CPL_FRMT_GUIB, panHistogram[iBucket] );
+        snprintf( pszHistCounts + iHistOffset,
+                  nLen - iHistOffset,
+                  CPL_FRMT_GUIB, panHistogram[iBucket] );
         if( iBucket < nBuckets-1 )
             strcat( pszHistCounts + iHistOffset, "|" );
         iHistOffset += strlen(pszHistCounts+iHistOffset);
     }
-        
+
     CPLSetXMLValue( psXMLHist, "HistCounts", pszHistCounts );
     CPLFree( pszHistCounts );
 
@@ -1124,15 +1161,15 @@ PamHistogramToXMLTree( double dfMin, double dfMax,
 CPLErr GDALPamRasterBand::GetHistogram( double dfMin, double dfMax,
                                         int nBuckets, GUIntBig * panHistogram,
                                         int bIncludeOutOfRange, int bApproxOK,
-                                        GDALProgressFunc pfnProgress, 
+                                        GDALProgressFunc pfnProgress,
                                         void *pProgressData )
 
 {
     PamInitialize();
 
     if( psPam == NULL )
-        return GDALRasterBand::GetHistogram( dfMin, dfMax, 
-                                             nBuckets, panHistogram, 
+        return GDALRasterBand::GetHistogram( dfMin, dfMax,
+                                             nBuckets, panHistogram,
                                              bIncludeOutOfRange, bApproxOK,
                                              pfnProgress, pProgressData );
 
@@ -1141,14 +1178,14 @@ CPLErr GDALPamRasterBand::GetHistogram( double dfMin, double dfMax,
 /* -------------------------------------------------------------------- */
     CPLXMLNode *psHistItem;
 
-    psHistItem = PamFindMatchingHistogram( psPam->psSavedHistograms, 
-                                           dfMin, dfMax, nBuckets, 
+    psHistItem = PamFindMatchingHistogram( psPam->psSavedHistograms,
+                                           dfMin, dfMax, nBuckets,
                                            bIncludeOutOfRange, bApproxOK );
     if( psHistItem != NULL )
     {
         GUIntBig *panTempHist = NULL;
 
-        if( PamParseHistogram( psHistItem, &dfMin, &dfMax, &nBuckets, 
+        if( PamParseHistogram( psHistItem, &dfMin, &dfMax, &nBuckets,
                                &panTempHist,
                                &bIncludeOutOfRange, &bApproxOK ) )
         {
@@ -1164,8 +1201,8 @@ CPLErr GDALPamRasterBand::GetHistogram( double dfMin, double dfMax,
 /* -------------------------------------------------------------------- */
     CPLErr eErr;
 
-    eErr = GDALRasterBand::GetHistogram( dfMin, dfMax, 
-                                         nBuckets, panHistogram, 
+    eErr = GDALRasterBand::GetHistogram( dfMin, dfMax,
+                                         nBuckets, panHistogram,
                                          bIncludeOutOfRange, bApproxOK,
                                          pfnProgress, pProgressData );
 
@@ -1176,8 +1213,8 @@ CPLErr GDALPamRasterBand::GetHistogram( double dfMin, double dfMax,
     {
         CPLXMLNode *psXMLHist;
 
-        psXMLHist = PamHistogramToXMLTree( dfMin, dfMax, nBuckets, 
-                                           panHistogram, 
+        psXMLHist = PamHistogramToXMLTree( dfMin, dfMax, nBuckets,
+                                           panHistogram,
                                            bIncludeOutOfRange, bApproxOK );
         if( psXMLHist != NULL )
         {
@@ -1186,7 +1223,7 @@ CPLErr GDALPamRasterBand::GetHistogram( double dfMin, double dfMax,
             if( psPam->psSavedHistograms == NULL )
                 psPam->psSavedHistograms = CPLCreateXMLNode( NULL, CXT_Element,
                                                              "Histograms" );
-            
+
             CPLAddXMLChild( psPam->psSavedHistograms, psXMLHist );
         }
     }
@@ -1198,7 +1235,7 @@ CPLErr GDALPamRasterBand::GetHistogram( double dfMin, double dfMax,
 /*                        SetDefaultHistogram()                         */
 /************************************************************************/
 
-CPLErr GDALPamRasterBand::SetDefaultHistogram( double dfMin, double dfMax, 
+CPLErr GDALPamRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
                                                int nBuckets, GUIntBig *panHistogram)
 
 {
@@ -1207,13 +1244,13 @@ CPLErr GDALPamRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
     PamInitialize();
 
     if( psPam == NULL )
-        return GDALRasterBand::SetDefaultHistogram( dfMin, dfMax, 
+        return GDALRasterBand::SetDefaultHistogram( dfMin, dfMax,
                                                     nBuckets, panHistogram );
 
 /* -------------------------------------------------------------------- */
 /*      Do we have a matching histogram we should replace?              */
 /* -------------------------------------------------------------------- */
-    psNode = PamFindMatchingHistogram( psPam->psSavedHistograms, 
+    psNode = PamFindMatchingHistogram( psPam->psSavedHistograms,
                                        dfMin, dfMax, nBuckets,
                                        TRUE, TRUE );
     if( psNode != NULL )
@@ -1228,7 +1265,7 @@ CPLErr GDALPamRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
 /* -------------------------------------------------------------------- */
     CPLXMLNode *psHistItem;
 
-    psHistItem = PamHistogramToXMLTree( dfMin, dfMax, nBuckets, 
+    psHistItem = PamHistogramToXMLTree( dfMin, dfMax, nBuckets,
                                         panHistogram, TRUE, FALSE );
     if( psHistItem == NULL )
         return CE_Failure;
@@ -1242,10 +1279,10 @@ CPLErr GDALPamRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
     if( psPam->psSavedHistograms == NULL )
         psPam->psSavedHistograms = CPLCreateXMLNode( NULL, CXT_Element,
                                                      "Histograms" );
-            
+
     psHistItem->psNext = psPam->psSavedHistograms->psChild;
     psPam->psSavedHistograms->psChild = psHistItem;
-    
+
     return CE_None;
 }
 
@@ -1253,13 +1290,13 @@ CPLErr GDALPamRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
 /*                        GetDefaultHistogram()                         */
 /************************************************************************/
 
-CPLErr 
-GDALPamRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax, 
-                                        int *pnBuckets, GUIntBig **ppanHistogram, 
+CPLErr
+GDALPamRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
+                                        int *pnBuckets, GUIntBig **ppanHistogram,
                                         int bForce,
-                                        GDALProgressFunc pfnProgress, 
+                                        GDALProgressFunc pfnProgress,
                                         void *pProgressData )
-    
+
 {
     if( psPam && psPam->psSavedHistograms != NULL )
     {
@@ -1274,7 +1311,7 @@ GDALPamRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
                 || !EQUAL(psXMLHist->pszValue,"HistItem") )
                 continue;
 
-            if( PamParseHistogram( psXMLHist, pdfMin, pdfMax, pnBuckets, 
+            if( PamParseHistogram( psXMLHist, pdfMin, pdfMax, pnBuckets,
                                    ppanHistogram, &bIncludeOutOfRange,
                                    &bApprox ) )
                 return CE_None;
@@ -1283,8 +1320,8 @@ GDALPamRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
         }
     }
 
-    return GDALRasterBand::GetDefaultHistogram( pdfMin, pdfMax, pnBuckets, 
-                                                ppanHistogram, bForce, 
+    return GDALRasterBand::GetDefaultHistogram( pdfMin, pdfMax, pnBuckets,
+                                                ppanHistogram, bForce,
                                                 pfnProgress, pProgressData );
 }
 
diff --git a/gcore/gdalproxydataset.cpp b/gcore/gdalproxydataset.cpp
index bd6d67b..628da37 100644
--- a/gcore/gdalproxydataset.cpp
+++ b/gcore/gdalproxydataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalproxydataset.cpp 28899 2015-04-14 09:27:00Z rouault $
+ * $Id: gdalproxydataset.cpp 33694 2016-03-10 17:54:30Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  A dataset and raster band classes that act as proxy for underlying
@@ -30,7 +30,7 @@
 
 #include "gdal_proxy.h"
 
-CPL_CVSID("$Id: gdalproxydataset.cpp 28899 2015-04-14 09:27:00Z rouault $");
+CPL_CVSID("$Id: gdalproxydataset.cpp 33694 2016-03-10 17:54:30Z goatbar $");
 
 /* ******************************************************************** */
 /*                        GDALProxyDataset                              */
@@ -58,23 +58,23 @@ D_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, IRasterIO,
                         ( GDALRWFlag eRWFlag,
                         int nXOff, int nYOff, int nXSize, int nYSize,
                         void * pData, int nBufXSize, int nBufYSize,
-                        GDALDataType eBufType, 
+                        GDALDataType eBufType,
                         int nBandCount, int *panBandMap,
                         GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace,
                         GDALRasterIOExtraArg* psExtraArg),
-                        ( eRWFlag, nXOff, nYOff, nXSize, nYSize, 
+                        ( eRWFlag, nXOff, nYOff, nXSize, nYSize,
                         pData, nBufXSize, nBufYSize,
                         eBufType, nBandCount, panBandMap,
                         nPixelSpace, nLineSpace, nBandSpace, psExtraArg ))
 
 
 D_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, IBuildOverviews,
-                        ( const char *pszResampling, 
-                          int nOverviews, int *panOverviewList, 
+                        ( const char *pszResampling,
+                          int nOverviews, int *panOverviewList,
                           int nListBands, int *panBandList,
-                          GDALProgressFunc pfnProgress, 
+                          GDALProgressFunc pfnProgress,
                           void * pProgressData ),
-                        ( pszResampling, nOverviews, panOverviewList, 
+                        ( pszResampling, nOverviews, panOverviewList,
                           nListBands, panBandList, pfnProgress, pProgressData ))
 
 void  GDALProxyDataset::FlushCache()
@@ -116,12 +116,12 @@ D_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, SetGCPs,
                         (nGCPCount, pasGCPList, pszGCPProjection))
 D_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, AdviseRead,
                         ( int nXOff, int nYOff, int nXSize, int nYSize,
-                                int nBufXSize, int nBufYSize, 
-                                GDALDataType eDT, 
+                                int nBufXSize, int nBufYSize,
+                                GDALDataType eDT,
                                 int nBandCount, int *panBandList,
                                 char **papszOptions ),
                         (nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, eDT, nBandCount, panBandList, papszOptions))
-D_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, CreateMaskBand, ( int nFlags ), (nFlags))
+D_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, CreateMaskBand, ( int nFlagsIn ), (nFlagsIn))
 
 /************************************************************************/
 /*                    UnrefUnderlyingDataset()                        */
@@ -175,10 +175,10 @@ retType GDALProxyRasterBand::methodName argList \
 }
 
 RB_PROXY_METHOD_WITH_RET_WITH_INIT_BLOCK(CPLErr, CE_Failure, IReadBlock,
-                                ( int nXBlockOff, int nYBlockOff, void* pImage), 
+                                ( int nXBlockOff, int nYBlockOff, void* pImage),
                                 (nXBlockOff, nYBlockOff, pImage) )
 RB_PROXY_METHOD_WITH_RET_WITH_INIT_BLOCK(CPLErr, CE_Failure, IWriteBlock,
-                                ( int nXBlockOff, int nYBlockOff, void* pImage), 
+                                ( int nXBlockOff, int nYBlockOff, void* pImage),
                                 (nXBlockOff, nYBlockOff, pImage) )
 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, IRasterIO,
                         ( GDALRWFlag eRWFlag,
@@ -187,7 +187,7 @@ RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, IRasterIO,
                                 GDALDataType eBufType,
                                 GSpacing nPixelSpace,
                                 GSpacing nLineSpace,
-                                GDALRasterIOExtraArg* psExtraArg ), 
+                                GDALRasterIOExtraArg* psExtraArg ),
                         (eRWFlag, nXOff, nYOff, nXSize, nYSize,
                                 pData, nBufXSize, nBufYSize, eBufType,
                                 nPixelSpace, nLineSpace, psExtraArg ) )
@@ -220,6 +220,7 @@ RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, Fill,
 
 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, SetCategoryNames, ( char ** arg ), (arg))
 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, SetNoDataValue, ( double arg ), (arg))
+RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, DeleteNoDataValue, (), ())
 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, SetColorTable, ( GDALColorTable *arg ), (arg))
 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, SetColorInterpretation,
                                     ( GDALColorInterp arg ), (arg))
@@ -229,17 +230,17 @@ RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, SetUnitType, ( const char * arg ),
 
 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, GetStatistics,
                         ( int bApproxOK, int bForce,
-                        double *pdfMin, double *pdfMax, 
+                        double *pdfMin, double *pdfMax,
                         double *pdfMean, double *padfStdDev ),
                         (bApproxOK, bForce, pdfMin, pdfMax, pdfMean, padfStdDev))
 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, ComputeStatistics,
-                        ( int bApproxOK, 
-                        double *pdfMin, double *pdfMax, 
+                        ( int bApproxOK,
+                        double *pdfMin, double *pdfMax,
                         double *pdfMean, double *pdfStdDev,
                         GDALProgressFunc pfn, void *pProgressData ),
                         ( bApproxOK, pdfMin, pdfMax, pdfMean, pdfStdDev, pfn, pProgressData))
 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, SetStatistics,
-                        ( double dfMin, double dfMax, 
+                        ( double dfMin, double dfMax,
                         double dfMean, double dfStdDev ),
                         (dfMin, dfMax, dfMean, dfStdDev))
 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, ComputeRasterMinMax,
@@ -258,7 +259,7 @@ RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, BuildOverviews,
 
 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, AdviseRead,
                         ( int nXOff, int nYOff, int nXSize, int nYSize,
-                        int nBufXSize, int nBufYSize, 
+                        int nBufXSize, int nBufYSize,
                         GDALDataType eDT, char **papszOptions ),
                         (nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, eDT, papszOptions))
 
@@ -290,7 +291,7 @@ RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, SetDefaultRAT,
 
 RB_PROXY_METHOD_WITH_RET(GDALRasterBand*, NULL, GetMaskBand, (), ())
 RB_PROXY_METHOD_WITH_RET(int, 0, GetMaskFlags, (), ())
-RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, CreateMaskBand, ( int nFlags ), (nFlags))
+RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, CreateMaskBand, ( int nFlagsIn ), (nFlagsIn))
 
 RB_PROXY_METHOD_WITH_RET(CPLVirtualMem*, NULL, GetVirtualMemAuto,
                          ( GDALRWFlag eRWFlag, int *pnPixelSpace, GIntBig *pnLineSpace, char **papszOptions ),
diff --git a/gcore/gdalproxypool.cpp b/gcore/gdalproxypool.cpp
index 0a591dd..b4a9d73 100644
--- a/gcore/gdalproxypool.cpp
+++ b/gcore/gdalproxypool.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalproxypool.cpp 31754 2015-11-25 11:06:14Z rouault $
+ * $Id: gdalproxypool.cpp 32234 2015-12-18 12:40:59Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  A dataset and raster band classes that differ the opening of the
@@ -31,7 +31,7 @@
 #include "gdal_proxy.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: gdalproxypool.cpp 31754 2015-11-25 11:06:14Z rouault $");
+CPL_CVSID("$Id: gdalproxypool.cpp 32234 2015-12-18 12:40:59Z rouault $");
 
 /* We *must* share the same mutex as the gdaldataset.cpp file, as we are */
 /* doing GDALOpen() calls that can indirectly call GDALOpenShared() on */
@@ -117,9 +117,9 @@ class GDALDatasetPool
 /*                         GDALDatasetPool()                            */
 /************************************************************************/
 
-GDALDatasetPool::GDALDatasetPool(int maxSize)
+GDALDatasetPool::GDALDatasetPool(int maxSizeIn)
 {
-    this->maxSize = maxSize;
+    maxSize = maxSizeIn;
     currentSize = 0;
     firstEntry = NULL;
     lastEntry = NULL;
@@ -263,7 +263,7 @@ GDALProxyPoolCacheEntry* GDALDatasetPool::_RefDataset(const char* pszFileName,
         }
         CPLFree(lastEntryWithZeroRefCount->pszFileName);
 
-        /* Recycle this entry for the to-be-openeded dataset and */
+        /* Recycle this entry for the to-be-opened dataset and */
         /* moves it to the top of the list */
         if (lastEntryWithZeroRefCount->prev)
             lastEntryWithZeroRefCount->prev->next = lastEntryWithZeroRefCount->next;
@@ -320,7 +320,7 @@ GDALProxyPoolCacheEntry* GDALDatasetPool::_RefDataset(const char* pszFileName,
 /*                       _CloseDataset()                                */
 /************************************************************************/
 
-void GDALDatasetPool::_CloseDataset(const char* pszFileName, GDALAccess eAccess)
+void GDALDatasetPool::_CloseDataset(const char* pszFileName, CPL_UNUSED GDALAccess eAccess)
 {
     GDALProxyPoolCacheEntry* cur = firstEntry;
     GIntBig responsiblePID = GDALGetResponsiblePIDForCurrentThread();
@@ -342,7 +342,7 @@ void GDALDatasetPool::_CloseDataset(const char* pszFileName, GDALAccess eAccess)
             refCountOfDisableRefCount --;
 
             GDALSetResponsiblePIDForCurrentThread(responsiblePID);
-            
+
             cur->poDS = NULL;
             cur->pszFileName[0] = '\0';
             break;
@@ -361,10 +361,10 @@ void GDALDatasetPool::Ref()
     CPLMutexHolderD( GDALGetphDLMutex() );
     if (singleton == NULL)
     {
-        int maxSize = atoi(CPLGetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", "100"));
-        if (maxSize < 2 || maxSize > 1000)
-            maxSize = 100;
-        singleton = new GDALDatasetPool(maxSize);
+        int l_maxSize = atoi(CPLGetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", "100"));
+        if (l_maxSize < 2 || l_maxSize > 1000)
+            l_maxSize = 100;
+        singleton = new GDALDatasetPool(l_maxSize);
     }
     if (singleton->refCountOfDisableRefCount == 0)
       singleton->refCount++;
@@ -380,6 +380,8 @@ void GDALDatasetPool::PreventDestroy()
 }
 
 /* keep that in sync with gdaldrivermanager.cpp */
+extern void GDALDatasetPoolPreventDestroy();
+
 void GDALDatasetPoolPreventDestroy()
 {
     GDALDatasetPool::PreventDestroy();
@@ -423,6 +425,8 @@ void GDALDatasetPool::ForceDestroy()
 }
 
 /* keep that in sync with gdaldrivermanager.cpp */
+extern void GDALDatasetPoolForceDestroy();
+
 void GDALDatasetPoolForceDestroy()
 {
     GDALDatasetPool::ForceDestroy();
@@ -544,31 +548,31 @@ CPL_C_END
 /* object */
 
 GDALProxyPoolDataset::GDALProxyPoolDataset(const char* pszSourceDatasetDescription,
-                                   int nRasterXSize, int nRasterYSize,
-                                   GDALAccess eAccess, int bShared,
-                                   const char * pszProjectionRef,
+                                   int nRasterXSizeIn, int nRasterYSizeIn,
+                                   GDALAccess eAccessIn, int bSharedIn,
+                                   const char * pszProjectionRefIn,
                                    double * padfGeoTransform)
 {
     GDALDatasetPool::Ref();
 
     SetDescription(pszSourceDatasetDescription);
 
-    this->nRasterXSize = nRasterXSize;
-    this->nRasterYSize = nRasterYSize;
-    this->eAccess = eAccess;
+    nRasterXSize = nRasterXSizeIn;
+    nRasterYSize = nRasterYSizeIn;
+    eAccess = eAccessIn;
 
-    this->bShared = bShared;
+    bShared = static_cast<GByte>(bSharedIn);
 
-    this->responsiblePID = GDALGetResponsiblePIDForCurrentThread();
+    responsiblePID = GDALGetResponsiblePIDForCurrentThread();
 
-    if (pszProjectionRef)
+    if (pszProjectionRefIn)
     {
-        this->pszProjectionRef = NULL;
+        pszProjectionRef = NULL;
         bHasSrcProjection = FALSE;
     }
     else
     {
-        this->pszProjectionRef = CPLStrdup(pszProjectionRef);
+        pszProjectionRef = CPLStrdup(pszProjectionRefIn);
         bHasSrcProjection = TRUE;
     }
     if (padfGeoTransform)
@@ -631,10 +635,10 @@ GDALProxyPoolDataset::~GDALProxyPoolDataset()
 /*                        SetOpenOptions()                              */
 /************************************************************************/
 
-void GDALProxyPoolDataset::SetOpenOptions(char** papszOpenOptions)
+void GDALProxyPoolDataset::SetOpenOptions(char** papszOpenOptionsIn)
 {
-    CPLAssert(this->papszOpenOptions == NULL);
-    this->papszOpenOptions = CSLDuplicate(papszOpenOptions);
+    CPLAssert(papszOpenOptions == NULL);
+    papszOpenOptions = CSLDuplicate(papszOpenOptionsIn);
 }
 
 /************************************************************************/
@@ -695,10 +699,10 @@ void GDALProxyPoolDataset::UnrefUnderlyingDataset(CPL_UNUSED GDALDataset* poUnde
 /*                        SetProjection()                               */
 /************************************************************************/
 
-CPLErr GDALProxyPoolDataset::SetProjection(const char* pszProjectionRef)
+CPLErr GDALProxyPoolDataset::SetProjection(const char* pszProjectionRefIn)
 {
     bHasSrcProjection = FALSE;
-    return GDALProxyDataset::SetProjection(pszProjectionRef);
+    return GDALProxyDataset::SetProjection(pszProjectionRefIn);
 }
 
 /************************************************************************/
@@ -900,17 +904,17 @@ void GDALProxyPoolDatasetAddSrcBandDescription( GDALProxyPoolDatasetH hProxyPool
 /*                    GDALProxyPoolRasterBand()                         */
 /* ******************************************************************** */
 
-GDALProxyPoolRasterBand::GDALProxyPoolRasterBand(GDALProxyPoolDataset* poDS, int nBand,
-                                                 GDALDataType eDataType,
-                                                 int nBlockXSize, int nBlockYSize)
+GDALProxyPoolRasterBand::GDALProxyPoolRasterBand(GDALProxyPoolDataset* poDSIn, int nBandIn,
+                                                 GDALDataType eDataTypeIn,
+                                                 int nBlockXSizeIn, int nBlockYSizeIn)
 {
-    this->poDS         = poDS;
-    this->nBand        = nBand;
-    this->eDataType    = eDataType;
-    this->nRasterXSize = poDS->GetRasterXSize();
-    this->nRasterYSize = poDS->GetRasterYSize();
-    this->nBlockXSize  = nBlockXSize;
-    this->nBlockYSize  = nBlockYSize;
+    poDS         = poDSIn;
+    nBand        = nBandIn;
+    eDataType    = eDataTypeIn;
+    nRasterXSize = poDSIn->GetRasterXSize();
+    nRasterYSize = poDSIn->GetRasterYSize();
+    nBlockXSize  = nBlockXSizeIn;
+    nBlockYSize  = nBlockYSizeIn;
 
     Init();
 }
@@ -919,14 +923,14 @@ GDALProxyPoolRasterBand::GDALProxyPoolRasterBand(GDALProxyPoolDataset* poDS, int
 /*                    GDALProxyPoolRasterBand()                         */
 /* ******************************************************************** */
 
-GDALProxyPoolRasterBand::GDALProxyPoolRasterBand(GDALProxyPoolDataset* poDS,
+GDALProxyPoolRasterBand::GDALProxyPoolRasterBand(GDALProxyPoolDataset* poDSIn,
                                                  GDALRasterBand* poUnderlyingRasterBand)
 {
-    this->poDS         = poDS;
-    this->nBand        = poUnderlyingRasterBand->GetBand();
-    this->eDataType    = poUnderlyingRasterBand->GetRasterDataType();
-    this->nRasterXSize = poUnderlyingRasterBand->GetXSize();
-    this->nRasterYSize = poUnderlyingRasterBand->GetYSize();
+    poDS         = poDSIn;
+    nBand        = poUnderlyingRasterBand->GetBand();
+    eDataType    = poUnderlyingRasterBand->GetRasterDataType();
+    nRasterXSize = poUnderlyingRasterBand->GetXSize();
+    nRasterYSize = poUnderlyingRasterBand->GetYSize();
     poUnderlyingRasterBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
 
     Init();
@@ -979,14 +983,14 @@ GDALProxyPoolRasterBand::~GDALProxyPoolRasterBand()
 /*                 AddSrcMaskBandDescription()                          */
 /************************************************************************/
 
-void GDALProxyPoolRasterBand::AddSrcMaskBandDescription( GDALDataType eDataType,
-                                                         int nBlockXSize,
-                                                         int nBlockYSize)
+void GDALProxyPoolRasterBand::AddSrcMaskBandDescription( GDALDataType eDataTypeIn,
+                                                         int nBlockXSizeIn,
+                                                         int nBlockYSizeIn)
 {
     CPLAssert(poProxyMaskBand == NULL);
     poProxyMaskBand = new GDALProxyPoolMaskBand((GDALProxyPoolDataset*)poDS,
-                                                this, eDataType,
-                                                nBlockXSize, nBlockYSize);
+                                                this, eDataTypeIn,
+                                                nBlockXSizeIn, nBlockYSizeIn);
 }
 
 /************************************************************************/
@@ -1226,14 +1230,14 @@ GDALRasterBand *GDALProxyPoolRasterBand::GetMaskBand()
 /*             GDALProxyPoolOverviewRasterBand()                        */
 /* ******************************************************************** */
 
-GDALProxyPoolOverviewRasterBand::GDALProxyPoolOverviewRasterBand(GDALProxyPoolDataset* poDS,
+GDALProxyPoolOverviewRasterBand::GDALProxyPoolOverviewRasterBand(GDALProxyPoolDataset* poDSIn,
                                                                  GDALRasterBand* poUnderlyingOverviewBand,
-                                                                 GDALProxyPoolRasterBand* poMainBand,
-                                                                 int nOverviewBand) :
-        GDALProxyPoolRasterBand(poDS, poUnderlyingOverviewBand)
+                                                                 GDALProxyPoolRasterBand* poMainBandIn,
+                                                                 int nOverviewBandIn) :
+        GDALProxyPoolRasterBand(poDSIn, poUnderlyingOverviewBand)
 {
-    this->poMainBand = poMainBand;
-    this->nOverviewBand = nOverviewBand;
+    poMainBand = poMainBandIn;
+    nOverviewBand = nOverviewBandIn;
 
     poUnderlyingMainRasterBand = NULL;
     nRefCountUnderlyingMainRasterBand = 0;
@@ -1277,12 +1281,12 @@ void GDALProxyPoolOverviewRasterBand::UnrefUnderlyingRasterBand(CPL_UNUSED GDALR
 /*                     GDALProxyPoolMaskBand()                          */
 /* ******************************************************************** */
 
-GDALProxyPoolMaskBand::GDALProxyPoolMaskBand(GDALProxyPoolDataset* poDS,
+GDALProxyPoolMaskBand::GDALProxyPoolMaskBand(GDALProxyPoolDataset* poDSIn,
                                              GDALRasterBand* poUnderlyingMaskBand,
-                                             GDALProxyPoolRasterBand* poMainBand) :
-        GDALProxyPoolRasterBand(poDS, poUnderlyingMaskBand)
+                                             GDALProxyPoolRasterBand* poMainBandIn) :
+        GDALProxyPoolRasterBand(poDSIn, poUnderlyingMaskBand)
 {
-    this->poMainBand = poMainBand;
+    poMainBand = poMainBandIn;
 
     poUnderlyingMainRasterBand = NULL;
     nRefCountUnderlyingMainRasterBand = 0;
@@ -1292,13 +1296,13 @@ GDALProxyPoolMaskBand::GDALProxyPoolMaskBand(GDALProxyPoolDataset* poDS,
 /*                     GDALProxyPoolMaskBand()                          */
 /* ******************************************************************** */
 
-GDALProxyPoolMaskBand::GDALProxyPoolMaskBand(GDALProxyPoolDataset* poDS,
-                                             GDALProxyPoolRasterBand* poMainBand,
-                                             GDALDataType eDataType,
-                                             int nBlockXSize, int nBlockYSize) :
-        GDALProxyPoolRasterBand(poDS, 1, eDataType, nBlockXSize, nBlockYSize)
+GDALProxyPoolMaskBand::GDALProxyPoolMaskBand(GDALProxyPoolDataset* poDSIn,
+                                             GDALProxyPoolRasterBand* poMainBandIn,
+                                             GDALDataType eDataTypeIn,
+                                             int nBlockXSizeIn, int nBlockYSizeIn) :
+        GDALProxyPoolRasterBand(poDSIn, 1, eDataTypeIn, nBlockXSizeIn, nBlockYSizeIn)
 {
-    this->poMainBand = poMainBand;
+    poMainBand = poMainBandIn;
 
     poUnderlyingMainRasterBand = NULL;
     nRefCountUnderlyingMainRasterBand = 0;
diff --git a/gcore/gdalrasterband.cpp b/gcore/gdalrasterband.cpp
index 4fe0205..f13e8fa 100644
--- a/gcore/gdalrasterband.cpp
+++ b/gcore/gdalrasterband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalrasterband.cpp 31109 2015-10-23 19:53:08Z rouault $
+ * $Id: gdalrasterband.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Base class for format specific band class implementation.  This
@@ -33,11 +33,7 @@
 #include "gdal_rat.h"
 #include "cpl_string.h"
 
-#define SUBBLOCK_SIZE 64
-#define TO_SUBBLOCK(x) ((x) >> 6)
-#define WITHIN_SUBBLOCK(x) ((x) & 0x3f)
-
-CPL_CVSID("$Id: gdalrasterband.cpp 31109 2015-10-23 19:53:08Z rouault $");
+CPL_CVSID("$Id: gdalrasterband.cpp 33808 2016-03-29 21:15:28Z goatbar $");
 
 /************************************************************************/
 /*                           GDALRasterBand()                           */
@@ -48,6 +44,17 @@ CPL_CVSID("$Id: gdalrasterband.cpp 31109 2015-10-23 19:53:08Z rouault $");
 GDALRasterBand::GDALRasterBand()
 
 {
+    Init(CPLTestBool( CPLGetConfigOption( "GDAL_FORCE_CACHING", "NO") ) );
+}
+
+GDALRasterBand::GDALRasterBand(int bForceCachedIOIn)
+
+{
+    Init(bForceCachedIOIn);
+}
+
+void GDALRasterBand::Init(int bForceCachedIOIn)
+{
     poDS = NULL;
     nBand = 0;
     nRasterXSize = nRasterYSize = 0;
@@ -56,21 +63,18 @@ GDALRasterBand::GDALRasterBand()
     nBlockXSize = nBlockYSize = -1;
     eDataType = GDT_Byte;
 
-    nSubBlocksPerRow = nBlocksPerRow = 0;
-    nSubBlocksPerColumn = nBlocksPerColumn = 0;
-
-    bSubBlockingActive = FALSE;
-    papoBlocks = NULL;
+    nBlocksPerRow = 0;
+    nBlocksPerColumn = 0;
 
     poMask = NULL;
     bOwnMask = false;
     nMaskFlags = 0;
 
     nBlockReads = 0;
-    bForceCachedIO =  CSLTestBoolean( 
-        CPLGetConfigOption( "GDAL_FORCE_CACHING", "NO") );
+    bForceCachedIO = bForceCachedIOIn;
 
     eFlushBlockErr = CE_None;
+    poBandBlockCache = NULL;
 }
 
 /************************************************************************/
@@ -85,17 +89,18 @@ GDALRasterBand::~GDALRasterBand()
 {
     FlushCache();
 
-    CPLFree( papoBlocks );
+    delete poBandBlockCache;
 
-    if( nBlockReads > nBlocksPerRow * nBlocksPerColumn
+    if( static_cast<GIntBig>(nBlockReads) > static_cast<GIntBig>(nBlocksPerRow) * nBlocksPerColumn
         && nBand == 1 && poDS != NULL )
     {
         CPLDebug( "GDAL", "%d block reads on %d block band 1 of %s.",
-                  nBlockReads, nBlocksPerRow * nBlocksPerColumn, 
+                  nBlockReads, nBlocksPerRow * nBlocksPerColumn,
                   poDS->GetDescription() );
     }
 
     InvalidateMaskBand();
+    nBand = -nBand;
 }
 
 /************************************************************************/
@@ -116,7 +121,7 @@ GDALRasterBand::~GDALRasterBand()
  * The nPixelSpace and nLineSpace parameters allow reading into or
  * writing from unusually organized buffers. This is primarily used
  * for buffers containing more than one bands raster data in interleaved
- * format. 
+ * format.
  *
  * Some formats may efficiently implement decimation into a buffer by
  * reading from lower resolution overview images.
@@ -211,11 +216,11 @@ CPLErr GDALRasterBand::RasterIO( GDALRWFlag eRWFlag,
 /* -------------------------------------------------------------------- */
     if( nXSize < 1 || nYSize < 1 || nBufXSize < 1 || nBufYSize < 1 )
     {
-        CPLDebug( "GDAL", 
+        CPLDebug( "GDAL",
                   "RasterIO() skipped for odd window or buffer size.\n"
                   "  Window = (%d,%d)x%dx%d\n"
                   "  Buffer = %dx%d\n",
-                  nXOff, nYOff, nXSize, nYSize, 
+                  nXOff, nYOff, nXSize, nYSize,
                   nBufXSize, nBufYSize );
 
         return CE_None;
@@ -223,8 +228,8 @@ CPLErr GDALRasterBand::RasterIO( GDALRWFlag eRWFlag,
 
     if( eRWFlag == GF_Write && eFlushBlockErr != CE_None )
     {
-        ReportError(eFlushBlockErr, CPLE_AppDefined,
-                 "An error occured while writing a dirty block");
+        ReportError( eFlushBlockErr, CPLE_AppDefined,
+                     "An error occurred while writing a dirty block");
         CPLErr eErr = eFlushBlockErr;
         eFlushBlockErr = CE_None;
         return eErr;
@@ -235,13 +240,15 @@ CPLErr GDALRasterBand::RasterIO( GDALRWFlag eRWFlag,
 /*      value assuming a packed buffer.                                 */
 /* -------------------------------------------------------------------- */
     if( nPixelSpace == 0 )
-        nPixelSpace = GDALGetDataTypeSize( eBufType ) / 8;
-    
+    {
+        nPixelSpace = GDALGetDataTypeSizeBytes( eBufType );
+    }
+
     if( nLineSpace == 0 )
     {
         nLineSpace = nPixelSpace * nBufXSize;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Do some validation of parameters.                               */
 /* -------------------------------------------------------------------- */
@@ -266,10 +273,10 @@ CPLErr GDALRasterBand::RasterIO( GDALRWFlag eRWFlag,
 /* -------------------------------------------------------------------- */
 /*      Call the format specific function.                              */
 /* -------------------------------------------------------------------- */
-    CPLErr eErr;
 
-    int bCallLeaveReadWrite = EnterReadWrite(eRWFlag);
+    const bool bCallLeaveReadWrite = CPL_TO_BOOL(EnterReadWrite(eRWFlag));
 
+    CPLErr eErr;
     if( bForceCachedIO )
         eErr = GDALRasterBand::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
                                          pData, nBufXSize, nBufYSize, eBufType,
@@ -293,17 +300,17 @@ CPLErr GDALRasterBand::RasterIO( GDALRWFlag eRWFlag,
  *
  * Use GDALRasterIOEx() if 64 bit spacings or extra arguments (resampling
  * resolution, progress callback, etc. are needed)
- * 
+ *
  * @see GDALRasterBand::RasterIO()
  */
 
-CPLErr CPL_STDCALL 
+CPLErr CPL_STDCALL
 GDALRasterIO( GDALRasterBandH hBand, GDALRWFlag eRWFlag,
               int nXOff, int nYOff, int nXSize, int nYSize,
               void * pData, int nBufXSize, int nBufYSize,
               GDALDataType eBufType,
               int nPixelSpace, int nLineSpace )
-    
+
 {
     VALIDATE_POINTER1( hBand, "GDALRasterIO", CE_Failure );
 
@@ -325,14 +332,14 @@ GDALRasterIO( GDALRasterBandH hBand, GDALRWFlag eRWFlag,
  * @since GDAL 2.0
  */
 
-CPLErr CPL_STDCALL 
+CPLErr CPL_STDCALL
 GDALRasterIOEx( GDALRasterBandH hBand, GDALRWFlag eRWFlag,
               int nXOff, int nYOff, int nXSize, int nYSize,
               void * pData, int nBufXSize, int nBufYSize,
               GDALDataType eBufType,
               GSpacing nPixelSpace, GSpacing nLineSpace,
               GDALRasterIOExtraArg* psExtraArg )
-    
+
 {
     VALIDATE_POINTER1( hBand, "GDALRasterIOEx", CE_Failure );
 
@@ -359,10 +366,10 @@ GDALRasterIOEx( GDALRasterBandH hBand, GDALRWFlag eRWFlag,
  * block oriented data without an extra copy into an application buffer.
  *
  * @param nXBlockOff the horizontal block offset, with zero indicating
- * the left most block, 1 the next block and so forth. 
+ * the leftmost block, 1 the next block and so forth.
  *
  * @param nYBlockOff the vertical block offset, with zero indicating
- * the left most block, 1 the next block and so forth.
+ * the topmost block, 1 the next block and so forth.
  *
  * @param pImage the buffer into which the data will be read.  The buffer
  * must be large enough to hold GetBlockXSize()*GetBlockYSize() words
@@ -379,26 +386,24 @@ GDALRasterIOEx( GDALRasterBandH hBand, GDALRWFlag eRWFlag,
  CPLErr GetHistogram( GDALRasterBand *poBand, GUIntBig *panHistogram )
 
  {
-     int        nXBlocks, nYBlocks, nXBlockSize, nYBlockSize;
-     int        iXBlock, iYBlock;
-     GByte      *pabyData;
-
      memset( panHistogram, 0, sizeof(GUIntBig) * 256 );
 
      CPLAssert( poBand->GetRasterDataType() == GDT_Byte );
 
+     int nXBlockSize, nYBlockSize;
+
      poBand->GetBlockSize( &nXBlockSize, &nYBlockSize );
-     nXBlocks = (poBand->GetXSize() + nXBlockSize - 1) / nXBlockSize;
-     nYBlocks = (poBand->GetYSize() + nYBlockSize - 1) / nYBlockSize;
+     int nXBlocks = (poBand->GetXSize() + nXBlockSize - 1) / nXBlockSize;
+     int nYBlocks = (poBand->GetYSize() + nYBlockSize - 1) / nYBlockSize;
 
-     pabyData = (GByte *) CPLMalloc(nXBlockSize * nYBlockSize);
+     GByte *pabyData = (GByte *) CPLMalloc(nXBlockSize * nYBlockSize);
 
-     for( iYBlock = 0; iYBlock < nYBlocks; iYBlock++ )
+     for( int iYBlock = 0; iYBlock < nYBlocks; iYBlock++ )
      {
-         for( iXBlock = 0; iXBlock < nXBlocks; iXBlock++ )
+         for( int iXBlock = 0; iXBlock < nXBlocks; iXBlock++ )
          {
              int        nXValid, nYValid;
-             
+
              poBand->ReadBlock( iXBlock, iYBlock, pabyData );
 
              // Compute the portion of the block that is valid
@@ -424,7 +429,7 @@ GDALRasterIOEx( GDALRasterBandH hBand, GDALRWFlag eRWFlag,
          }
      }
  }
- 
+
 </pre>
  */
 
@@ -437,10 +442,10 @@ CPLErr GDALRasterBand::ReadBlock( int nXBlockOff, int nYBlockOff,
 /*      Validate arguments.                                             */
 /* -------------------------------------------------------------------- */
     CPLAssert( pImage != NULL );
-    
+
     if( !InitBlockInfo() )
         return CE_Failure;
-        
+
     if( nXBlockOff < 0 || nXBlockOff >= nBlocksPerRow )
     {
         ReportError( CE_Failure, CPLE_IllegalArg,
@@ -493,7 +498,7 @@ CPLErr CPL_STDCALL GDALReadBlock( GDALRasterBandH hBand, int nXOff, int nYOff,
 /************************************************************************/
 /*                            IWriteBlock()                             */
 /*                                                                      */
-/*      Default internal implementation ... to be overriden by          */
+/*      Default internal implementation ... to be overridden by          */
 /*      subclasses that support writing.                                */
 /************************************************************************/
 
@@ -503,7 +508,7 @@ CPLErr GDALRasterBand::IWriteBlock( int, int, void * )
     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
         ReportError( CE_Failure, CPLE_NotSupported,
                   "WriteBlock() not supported for this dataset." );
-    
+
     return( CE_Failure );
 }
 
@@ -523,7 +528,7 @@ CPLErr GDALRasterBand::IWriteBlock( int, int, void * )
  * See ReadBlock() for an example of block oriented data access.
  *
  * @param nXBlockOff the horizontal block offset, with zero indicating
- * the left most block, 1 the next block and so forth. 
+ * the left most block, 1 the next block and so forth.
  *
  * @param nYBlockOff the vertical block offset, with zero indicating
  * the left most block, 1 the next block and so forth.
@@ -578,8 +583,8 @@ CPLErr GDALRasterBand::WriteBlock( int nXBlockOff, int nYBlockOff,
 
     if( eFlushBlockErr != CE_None )
     {
-        ReportError(eFlushBlockErr, CPLE_AppDefined,
-                 "An error occured while writing a dirty block");
+        ReportError( eFlushBlockErr, CPLE_AppDefined,
+                     "An error occurred while writing a dirty block");
         CPLErr eErr = eFlushBlockErr;
         eFlushBlockErr = CE_None;
         return eErr;
@@ -589,7 +594,7 @@ CPLErr GDALRasterBand::WriteBlock( int nXBlockOff, int nYBlockOff,
 /*      Invoke underlying implementation method.                        */
 /* -------------------------------------------------------------------- */
 
-    int bCallLeaveReadWrite = EnterReadWrite(GF_Write);
+    const bool bCallLeaveReadWrite = CPL_TO_BOOL(EnterReadWrite(GF_Write));
     CPLErr eErr = IWriteBlock( nXBlockOff, nYBlockOff, pImage );
     if( bCallLeaveReadWrite ) LeaveReadWrite();
 
@@ -628,7 +633,7 @@ CPLErr CPL_STDCALL GDALWriteBlock( GDALRasterBandH hBand, int nXOff, int nYOff,
  *
  * @return the data type of pixels for this band.
  */
-  
+
 
 GDALDataType GDALRasterBand::GetRasterDataType()
 
@@ -712,7 +717,7 @@ void GDALRasterBand::GetBlockSize( int * pnXSize, int *pnYSize )
  * @see GDALRasterBand::GetBlockSize()
  */
 
-void CPL_STDCALL 
+void CPL_STDCALL
 GDALGetBlockSize( GDALRasterBandH hBand, int * pnXSize, int * pnYSize )
 
 {
@@ -729,8 +734,8 @@ GDALGetBlockSize( GDALRasterBandH hBand, int * pnXSize, int * pnYSize )
 int GDALRasterBand::InitBlockInfo()
 
 {
-    if( papoBlocks != NULL )
-        return TRUE;
+    if( poBandBlockCache != NULL )
+        return poBandBlockCache->IsInitOK();
 
     /* Do some validation of raster and block dimensions in case the driver */
     /* would have neglected to do it itself */
@@ -748,17 +753,21 @@ int GDALRasterBand::InitBlockInfo()
         return FALSE;
     }
 
+    const int nDataTypeSize = GDALGetDataTypeSizeBytes(eDataType);
+    if( nDataTypeSize == 0 )
+    {
+        ReportError( CE_Failure, CPLE_AppDefined, "Invalid data type" );
+        return FALSE;
+    }
+
     if (nBlockXSize >= 10000 || nBlockYSize >= 10000)
     {
         /* Check that the block size is not overflowing int capacity as it is */
-        /* (reasonnably) assumed in many places (GDALRasterBlock::Internalize(), */
+        /* (reasonably) assumed in many places (GDALRasterBlock::Internalize(), */
         /* GDALRasterBand::Fill(), many drivers...) */
         /* As 10000 * 10000 * 16 < INT_MAX, we don't need to do the multiplication in other cases */
-
-        int nSizeInBytes = nBlockXSize * nBlockYSize * (GDALGetDataTypeSize(eDataType) / 8);
-
-        GIntBig nBigSizeInBytes = (GIntBig)nBlockXSize * nBlockYSize * (GDALGetDataTypeSize(eDataType) / 8);
-        if ((GIntBig)nSizeInBytes != nBigSizeInBytes)
+        if( nBlockXSize > INT_MAX / nDataTypeSize ||
+            nBlockYSize > INT_MAX / (nDataTypeSize * nBlockXSize) )
         {
             ReportError( CE_Failure, CPLE_NotSupported, "Too big block : %d * %d",
                         nBlockXSize, nBlockYSize );
@@ -769,50 +778,35 @@ int GDALRasterBand::InitBlockInfo()
     nBlocksPerRow = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
     nBlocksPerColumn = DIV_ROUND_UP(nRasterYSize, nBlockYSize);
 
-    if( nBlocksPerRow < SUBBLOCK_SIZE/2 )
+    const char* pszBlockStrategy = CPLGetConfigOption("GDAL_BAND_BLOCK_CACHE", NULL);
+    bool bUseArray = true;
+    if( pszBlockStrategy == NULL )
     {
-        bSubBlockingActive = FALSE;
-
-        if (nBlocksPerRow < INT_MAX / nBlocksPerColumn)
+        if( poDS == NULL ||
+            (poDS->nOpenFlags & GDAL_OF_BLOCK_ACCESS_MASK) ==
+                                            GDAL_OF_DEFAULT_BLOCK_ACCESS )
         {
-            papoBlocks = (GDALRasterBlock **)
-                VSICalloc( sizeof(void*), nBlocksPerRow * nBlocksPerColumn );
+            bUseArray = ( static_cast<GIntBig>(nBlocksPerRow) * nBlocksPerColumn < 1024 * 1024  );
         }
-        else
+        else if( (poDS->nOpenFlags & GDAL_OF_BLOCK_ACCESS_MASK) ==
+                                            GDAL_OF_HASHSET_BLOCK_ACCESS )
         {
-            ReportError( CE_Failure, CPLE_NotSupported, "Too many blocks : %d x %d",
-                     nBlocksPerRow, nBlocksPerColumn );
-            return FALSE;
+            bUseArray = false;
         }
     }
+    else if( EQUAL(pszBlockStrategy, "HASHSET") )
+        bUseArray = false;
+    if( bUseArray )
+        poBandBlockCache = GDALArrayBandBlockCacheCreate(this);
     else
     {
-        bSubBlockingActive = TRUE;
-
-        nSubBlocksPerRow = DIV_ROUND_UP(nBlocksPerRow, SUBBLOCK_SIZE);
-        nSubBlocksPerColumn = DIV_ROUND_UP(nBlocksPerColumn, SUBBLOCK_SIZE);
-
-        if (nSubBlocksPerRow < INT_MAX / nSubBlocksPerColumn)
-        {
-            papoBlocks = (GDALRasterBlock **)
-                VSICalloc( sizeof(void*), nSubBlocksPerRow * nSubBlocksPerColumn );
-        }
-        else
-        {
-            ReportError( CE_Failure, CPLE_NotSupported, "Too many subblocks : %d x %d",
-                      nSubBlocksPerRow, nSubBlocksPerColumn );
-            return FALSE;
-        }
+        if( nBand == 1)
+            CPLDebug("GDAL", "Use hashset band block cache");
+        poBandBlockCache = GDALHashSetBandBlockCacheCreate(this);
     }
-
-    if( papoBlocks == NULL )
-    {
-        ReportError( CE_Failure, CPLE_OutOfMemory,
-                  "Out of memory in InitBlockInfo()." );
+    if( poBandBlockCache == NULL )
         return FALSE;
-    }
-
-    return TRUE;
+    return poBandBlockCache->Init();
 }
 
 /************************************************************************/
@@ -825,74 +819,16 @@ int GDALRasterBand::InitBlockInfo()
 /*      This method is protected.                                       */
 /************************************************************************/
 
-CPLErr GDALRasterBand::AdoptBlock( int nXBlockOff, int nYBlockOff,
-                                   GDALRasterBlock * poBlock )
+CPLErr GDALRasterBand::AdoptBlock( GDALRasterBlock * poBlock )
 
 {
-    int         nBlockIndex;
-    
     if( !InitBlockInfo() )
         return CE_Failure;
-    
-/* -------------------------------------------------------------------- */
-/*      Simple case without subblocking.                                */
-/* -------------------------------------------------------------------- */
-    if( !bSubBlockingActive )
-    {
-        nBlockIndex = nXBlockOff + nYBlockOff * nBlocksPerRow;
-
-        if( papoBlocks[nBlockIndex] == poBlock )
-            return( CE_None );
-
-        if( papoBlocks[nBlockIndex] != NULL )
-            FlushBlock( nXBlockOff, nYBlockOff );
 
-        papoBlocks[nBlockIndex] = poBlock;
+    CPLErr eErr = poBandBlockCache->AdoptBlock(poBlock);
+    if( eErr == CE_None )
         poBlock->Touch();
-
-        return( CE_None );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Identify the subblock in which our target occurs, and create    */
-/*      it if necessary.                                                */
-/* -------------------------------------------------------------------- */
-    int nSubBlock = TO_SUBBLOCK(nXBlockOff) 
-        + TO_SUBBLOCK(nYBlockOff) * nSubBlocksPerRow;
-
-    if( papoBlocks[nSubBlock] == NULL )
-    {
-        const int nSubGridSize = 
-            sizeof(GDALRasterBlock*) * SUBBLOCK_SIZE * SUBBLOCK_SIZE;
-
-        papoBlocks[nSubBlock] = (GDALRasterBlock *) VSICalloc(1, nSubGridSize);
-        if( papoBlocks[nSubBlock] == NULL )
-        {
-            ReportError( CE_Failure, CPLE_OutOfMemory,
-                      "Out of memory in AdoptBlock()." );
-            return CE_Failure;
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Check within subblock.                                          */
-/* -------------------------------------------------------------------- */
-    GDALRasterBlock **papoSubBlockGrid = 
-        (GDALRasterBlock **) papoBlocks[nSubBlock];
-
-    int nBlockInSubBlock = WITHIN_SUBBLOCK(nXBlockOff)
-        + WITHIN_SUBBLOCK(nYBlockOff) * SUBBLOCK_SIZE;
-
-    if( papoSubBlockGrid[nBlockInSubBlock] == poBlock )
-        return CE_None;
-
-    if( papoSubBlockGrid[nBlockInSubBlock] != NULL )
-        FlushBlock( nXBlockOff, nYBlockOff );
-
-    papoSubBlockGrid[nBlockInSubBlock] = poBlock;
-    poBlock->Touch();
-
-    return CE_None;
+    return eErr;
 }
 
 /************************************************************************/
@@ -917,79 +853,15 @@ CPLErr GDALRasterBand::FlushCache()
 
     if (eFlushBlockErr != CE_None)
     {
-        ReportError(eFlushBlockErr, CPLE_AppDefined,
-                 "An error occured while writing a dirty block");
+        ReportError( eFlushBlockErr, CPLE_AppDefined,
+                     "An error occurred while writing a dirty block");
         eFlushBlockErr = CE_None;
     }
 
-    if (papoBlocks == NULL)
-        return eGlobalErr;
-
-/* -------------------------------------------------------------------- */
-/*      Flush all blocks in memory ... this case is without subblocking.*/
-/* -------------------------------------------------------------------- */
-    if( !bSubBlockingActive )
-    {
-        for( int iY = 0; iY < nBlocksPerColumn; iY++ )
-        {
-            for( int iX = 0; iX < nBlocksPerRow; iX++ )
-            {
-                if( papoBlocks[iX + iY*nBlocksPerRow] != NULL )
-                {
-                    CPLErr    eErr;
-
-                    eErr = FlushBlock( iX, iY, eGlobalErr == CE_None );
-
-                    if( eErr != CE_None )
-                        eGlobalErr = eErr;
-                }
-            }
-        }
+    if (poBandBlockCache == NULL || !poBandBlockCache->IsInitOK())
         return eGlobalErr;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      With subblocking.  We can short circuit missing subblocks.      */
-/* -------------------------------------------------------------------- */
-    int iSBX, iSBY;
 
-    for( iSBY = 0; iSBY < nSubBlocksPerColumn; iSBY++ )
-    {
-        for( iSBX = 0; iSBX < nSubBlocksPerRow; iSBX++ )
-        {
-            int nSubBlock = iSBX + iSBY * nSubBlocksPerRow;
-        
-            GDALRasterBlock **papoSubBlockGrid = 
-                (GDALRasterBlock **) papoBlocks[nSubBlock];
-
-            if( papoSubBlockGrid == NULL )
-                continue;
-
-            for( int iY = 0; iY < SUBBLOCK_SIZE; iY++ )
-            {
-                for( int iX = 0; iX < SUBBLOCK_SIZE; iX++ )
-                {
-                    if( papoSubBlockGrid[iX + iY * SUBBLOCK_SIZE] != NULL )
-                    {
-                        CPLErr eErr;
-
-                        eErr = FlushBlock( iX + iSBX * SUBBLOCK_SIZE, 
-                                           iY + iSBY * SUBBLOCK_SIZE,
-                                           eGlobalErr == CE_None );
-                        if( eErr != CE_None )
-                            eGlobalErr = eErr;
-                    }
-                }
-            }
-
-            // We might as well get rid of this grid chunk since we know 
-            // it is now empty.
-            papoBlocks[nSubBlock] = NULL;
-            CPLFree( papoSubBlockGrid );
-        }
-    }
-
-    return( eGlobalErr );
+    return poBandBlockCache->FlushCache();
 }
 
 /************************************************************************/
@@ -1016,103 +888,73 @@ CPLErr CPL_STDCALL GDALFlushRasterCache( GDALRasterBandH hBand )
 /*                                                                      */
 /*      Unreference the block from our array of blocks                  */
 /*      This method should only be called by                            */
-/*      GDALRasterBlock::Internalize(), and under the block cache mutex */
+/*      GDALRasterBlock::Internalize() and FlushCacheBlock() (and under */
+/*      the block cache mutex)                                          */
 /************************************************************************/
 
-CPLErr GDALRasterBand::UnreferenceBlock( int nXBlockOff, int nYBlockOff )
+CPLErr GDALRasterBand::UnreferenceBlock( GDALRasterBlock* poBlock )
 {
-
-    if( !papoBlocks )
-        return CE_None;
-    
-/* -------------------------------------------------------------------- */
-/*      Validate the request                                            */
-/* -------------------------------------------------------------------- */
-    if( nXBlockOff < 0 || nXBlockOff >= nBlocksPerRow )
+#ifdef notdef
+    if( poBandBlockCache == NULL || !poBandBlockCache->IsInitOK() )
     {
-        ReportError( CE_Failure, CPLE_IllegalArg,
-                  "Illegal nBlockXOff value (%d) in "
-                        "GDALRasterBand::FlushBlock()\n",
-                  nXBlockOff );
-
-        return( CE_Failure );
-    }
-
-    if( nYBlockOff < 0 || nYBlockOff >= nBlocksPerColumn )
-    {
-        ReportError( CE_Failure, CPLE_IllegalArg,
-                  "Illegal nBlockYOff value (%d) in "
-                        "GDALRasterBand::FlushBlock()\n",
-                  nYBlockOff );
-
-        return( CE_Failure );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Simple case for single level caches.                            */
-/* -------------------------------------------------------------------- */
-    if( !bSubBlockingActive )
-    {
-        int nBlockIndex = nXBlockOff + nYBlockOff * nBlocksPerRow;
-
-        papoBlocks[nBlockIndex] = NULL;
+        if( poBandBlockCache == NULL )
+            printf("poBandBlockCache == NULL\n");
+        else
+            printf("!poBandBlockCache->IsInitOK()\n");
+        printf("caller = %s\n", pszCaller);
+        printf("GDALRasterBand: %p\n", this);
+        printf("GDALRasterBand: nBand=%d\n", nBand);
+        printf("nRasterXSize = %d\n", nRasterXSize);
+        printf("nRasterYSize = %d\n", nRasterYSize);
+        printf("nBlockXSize = %d\n", nBlockXSize);
+        printf("nBlockYSize = %d\n", nBlockYSize);
+        poBlock->DumpBlock();
+        if( GetDataset() != NULL )
+            printf("Dataset: %s\n", GetDataset()->GetDescription());
+        GDALRasterBlock::Verify();
+        abort();
     }
+#endif
+    CPLAssert(poBandBlockCache && poBandBlockCache->IsInitOK());
+    return poBandBlockCache->UnreferenceBlock( poBlock );
+}
 
-/* -------------------------------------------------------------------- */
-/*      Identify our subblock.                                          */
-/* -------------------------------------------------------------------- */
-    else
-    {
-        int nSubBlock = TO_SUBBLOCK(nXBlockOff) 
-            + TO_SUBBLOCK(nYBlockOff) * nSubBlocksPerRow;
-
-        if( papoBlocks[nSubBlock] == NULL )
-            return CE_None;
-
-/* -------------------------------------------------------------------- */
-/*      Check within subblock.                                          */
-/* -------------------------------------------------------------------- */
-        GDALRasterBlock **papoSubBlockGrid = 
-            (GDALRasterBlock **) papoBlocks[nSubBlock];
-
-        int nBlockInSubBlock = WITHIN_SUBBLOCK(nXBlockOff)
-            + WITHIN_SUBBLOCK(nYBlockOff) * SUBBLOCK_SIZE;
-
-        papoSubBlockGrid[nBlockInSubBlock] = NULL;
-    }
+/************************************************************************/
+/*                        AddBlockToFreeList()                          */
+/*                                                                      */
+/*      When GDALRasterBlock::Internalize() or FlushCacheBlock() are    */
+/*      finished with a block about to be free'd, they pass it to that  */
+/*      method.                                                         */
+/************************************************************************/
 
-    return CE_None;
+void GDALRasterBand::AddBlockToFreeList( GDALRasterBlock * poBlock )
+{
+    CPLAssert(poBandBlockCache && poBandBlockCache->IsInitOK());
+    return poBandBlockCache->AddBlockToFreeList( poBlock );
 }
 
 /************************************************************************/
 /*                             FlushBlock()                             */
 /*                                                                      */
-/*      Flush a block out of the block cache.  If it has been           */
-/*      modified write it to disk.  If no specific tile is              */
-/*      indicated, write the oldest tile.                               */
-/*                                                                      */
-/*      Protected method.                                               */
+/*      Flush a block out of the block cache.                           */
 /************************************************************************/
 
 CPLErr GDALRasterBand::FlushBlock( int nXBlockOff, int nYBlockOff,
                                    int bWriteDirtyBlock )
 
 {
-    int             nBlockIndex;
-    GDALRasterBlock *poBlock = NULL;
+    if( poBandBlockCache == NULL || !poBandBlockCache->IsInitOK() )
+        return( CE_Failure );
 
-    if( !papoBlocks )
-        return CE_None;
-    
 /* -------------------------------------------------------------------- */
 /*      Validate the request                                            */
 /* -------------------------------------------------------------------- */
     if( nXBlockOff < 0 || nXBlockOff >= nBlocksPerRow )
     {
         ReportError( CE_Failure, CPLE_IllegalArg,
-                  "Illegal nBlockXOff value (%d) in "
-                        "GDALRasterBand::FlushBlock()\n",
-                  nXBlockOff );
+                    "Illegal nBlockXOff value (%d) in "
+                    "GDALRasterBand::FlushBlock()\n",
+                    nXBlockOff );
 
         return( CE_Failure );
     }
@@ -1120,72 +962,14 @@ CPLErr GDALRasterBand::FlushBlock( int nXBlockOff, int nYBlockOff,
     if( nYBlockOff < 0 || nYBlockOff >= nBlocksPerColumn )
     {
         ReportError( CE_Failure, CPLE_IllegalArg,
-                  "Illegal nBlockYOff value (%d) in "
-                        "GDALRasterBand::FlushBlock()\n",
-                  nYBlockOff );
+                    "Illegal nBlockYOff value (%d) in "
+                    "GDALRasterBand::FlushBlock()\n",
+                    nYBlockOff );
 
         return( CE_Failure );
     }
 
-/* -------------------------------------------------------------------- */
-/*      Simple case for single level caches.                            */
-/* -------------------------------------------------------------------- */
-    if( !bSubBlockingActive )
-    {
-        nBlockIndex = nXBlockOff + nYBlockOff * nBlocksPerRow;
-
-        GDALRasterBlock::SafeLockBlock( papoBlocks + nBlockIndex );
-
-        poBlock = papoBlocks[nBlockIndex];
-        papoBlocks[nBlockIndex] = NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Identify our subblock.                                          */
-/* -------------------------------------------------------------------- */
-    else
-    {
-        int nSubBlock = TO_SUBBLOCK(nXBlockOff) 
-            + TO_SUBBLOCK(nYBlockOff) * nSubBlocksPerRow;
-        
-        if( papoBlocks[nSubBlock] == NULL )
-            return CE_None;
-        
-/* -------------------------------------------------------------------- */
-/*      Check within subblock.                                          */
-/* -------------------------------------------------------------------- */
-        GDALRasterBlock **papoSubBlockGrid = 
-            (GDALRasterBlock **) papoBlocks[nSubBlock];
-        
-        int nBlockInSubBlock = WITHIN_SUBBLOCK(nXBlockOff)
-            + WITHIN_SUBBLOCK(nYBlockOff) * SUBBLOCK_SIZE;
-
-        GDALRasterBlock::SafeLockBlock( papoSubBlockGrid + nBlockInSubBlock );
-
-        poBlock = papoSubBlockGrid[nBlockInSubBlock];
-        papoSubBlockGrid[nBlockInSubBlock] = NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Is the target block dirty?  If so we need to write it.          */
-/* -------------------------------------------------------------------- */
-    CPLErr eErr = CE_None;
-
-    if( poBlock == NULL )
-        return CE_None;
-
-    poBlock->Detach();
-
-    if( bWriteDirtyBlock && poBlock->GetDirty() )
-        eErr = poBlock->Write();
-
-/* -------------------------------------------------------------------- */
-/*      Deallocate the block;                                           */
-/* -------------------------------------------------------------------- */
-    poBlock->DropLock();
-    delete poBlock;
-
-    return eErr;
+    return poBandBlockCache->FlushBlock( nXBlockOff, nYBlockOff, bWriteDirtyBlock );
 }
 
 /************************************************************************/
@@ -1193,43 +977,41 @@ CPLErr GDALRasterBand::FlushBlock( int nXBlockOff, int nYBlockOff,
 /************************************************************************/
 
 /**
- * \brief Try fetching block ref. 
+ * \brief Try fetching block ref.
  *
  * This method will returned the requested block (locked) if it is already
- * in the block cache for the layer.  If not, NULL is returned.  
- * 
+ * in the block cache for the layer.  If not, NULL is returned.
+ *
  * If a non-NULL value is returned, then a lock for the block will have been
  * acquired on behalf of the caller.  It is absolutely imperative that the
  * caller release this lock (with GDALRasterBlock::DropLock()) or else
  * severe problems may result.
  *
  * @param nXBlockOff the horizontal block offset, with zero indicating
- * the left most block, 1 the next block and so forth. 
+ * the left most block, 1 the next block and so forth.
  *
  * @param nYBlockOff the vertical block offset, with zero indicating
  * the top most block, 1 the next block and so forth.
- * 
- * @return NULL if block not available, or locked block pointer. 
+ *
+ * @return NULL if block not available, or locked block pointer.
  */
 
-GDALRasterBlock *GDALRasterBand::TryGetLockedBlockRef( int nXBlockOff, 
+GDALRasterBlock *GDALRasterBand::TryGetLockedBlockRef( int nXBlockOff,
                                                        int nYBlockOff )
 
 {
-    int             nBlockIndex = 0;
-    
-    if( !InitBlockInfo() )
-        return( NULL );
-    
+    if( poBandBlockCache == NULL || !poBandBlockCache->IsInitOK() )
+        return NULL;
+
 /* -------------------------------------------------------------------- */
 /*      Validate the request                                            */
 /* -------------------------------------------------------------------- */
     if( nXBlockOff < 0 || nXBlockOff >= nBlocksPerRow )
     {
         ReportError( CE_Failure, CPLE_IllegalArg,
-                  "Illegal nBlockXOff value (%d) in "
-                        "GDALRasterBand::TryGetLockedBlockRef()\n",
-                  nXBlockOff );
+                    "Illegal nBlockXOff value (%d) in "
+                    "GDALRasterBand::TryGetLockedBlockRef()\n",
+                    nXBlockOff );
 
         return( NULL );
     }
@@ -1237,46 +1019,14 @@ GDALRasterBlock *GDALRasterBand::TryGetLockedBlockRef( int nXBlockOff,
     if( nYBlockOff < 0 || nYBlockOff >= nBlocksPerColumn )
     {
         ReportError( CE_Failure, CPLE_IllegalArg,
-                  "Illegal nBlockYOff value (%d) in "
-                        "GDALRasterBand::TryGetLockedBlockRef()\n",
-                  nYBlockOff );
+                    "Illegal nBlockYOff value (%d) in "
+                    "GDALRasterBand::TryGetLockedBlockRef()\n",
+                    nYBlockOff );
 
         return( NULL );
     }
 
-/* -------------------------------------------------------------------- */
-/*      Simple case for single level caches.                            */
-/* -------------------------------------------------------------------- */
-    if( !bSubBlockingActive )
-    {
-        nBlockIndex = nXBlockOff + nYBlockOff * nBlocksPerRow;
-        
-        GDALRasterBlock::SafeLockBlock( papoBlocks + nBlockIndex );
-
-        return papoBlocks[nBlockIndex];
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Identify our subblock.                                          */
-/* -------------------------------------------------------------------- */
-    int nSubBlock = TO_SUBBLOCK(nXBlockOff) 
-        + TO_SUBBLOCK(nYBlockOff) * nSubBlocksPerRow;
-
-    if( papoBlocks[nSubBlock] == NULL )
-        return NULL;
-
-/* -------------------------------------------------------------------- */
-/*      Check within subblock.                                          */
-/* -------------------------------------------------------------------- */
-    GDALRasterBlock **papoSubBlockGrid = 
-        (GDALRasterBlock **) papoBlocks[nSubBlock];
-
-    int nBlockInSubBlock = WITHIN_SUBBLOCK(nXBlockOff)
-        + WITHIN_SUBBLOCK(nYBlockOff) * SUBBLOCK_SIZE;
-
-    GDALRasterBlock::SafeLockBlock( papoSubBlockGrid + nBlockInSubBlock );
-
-    return papoSubBlockGrid[nBlockInSubBlock];
+    return poBandBlockCache->TryGetLockedBlockRef(nXBlockOff, nYBlockOff);
 }
 
 /************************************************************************/
@@ -1287,11 +1037,11 @@ GDALRasterBlock *GDALRasterBand::TryGetLockedBlockRef( int nXBlockOff,
  * \brief Fetch a pointer to an internally cached raster block.
  *
  * This method will returned the requested block (locked) if it is already
- * in the block cache for the layer.  If not, the block will be read from 
+ * in the block cache for the layer.  If not, the block will be read from
  * the driver, and placed in the layer block cached, then returned.  If an
  * error occurs reading the block from the driver, a NULL value will be
  * returned.
- * 
+ *
  * If a non-NULL value is returned, then a lock for the block will have been
  * acquired on behalf of the caller.  It is absolutely imperative that the
  * caller release this lock (with GDALRasterBlock::DropLock()) or else
@@ -1299,16 +1049,16 @@ GDALRasterBlock *GDALRasterBand::TryGetLockedBlockRef( int nXBlockOff,
  *
  * Note that calling GetLockedBlockRef() on a previously uncached band will
  * enable caching.
- * 
+ *
  * @param nXBlockOff the horizontal block offset, with zero indicating
- * the left most block, 1 the next block and so forth. 
+ * the left most block, 1 the next block and so forth.
  *
  * @param nYBlockOff the vertical block offset, with zero indicating
  * the top most block, 1 the next block and so forth.
- * 
+ *
  * @param bJustInitialize If TRUE the block will be allocated and initialized,
  * but not actually read from the source.  This is useful when it will just
- * be completely set and written back. 
+ * be completely set and written back.
  *
  * @return pointer to the block object, or NULL on failure.
  */
@@ -1318,12 +1068,10 @@ GDALRasterBlock * GDALRasterBand::GetLockedBlockRef( int nXBlockOff,
                                                      int bJustInitialize )
 
 {
-    GDALRasterBlock *poBlock = NULL;
-
 /* -------------------------------------------------------------------- */
 /*      Try and fetch from cache.                                       */
 /* -------------------------------------------------------------------- */
-    poBlock = TryGetLockedBlockRef( nXBlockOff, nYBlockOff );
+    GDALRasterBlock *poBlock = TryGetLockedBlockRef( nXBlockOff, nYBlockOff );
 
 /* -------------------------------------------------------------------- */
 /*      If we didn't find it in our memory cache, instantiate a         */
@@ -1358,7 +1106,9 @@ GDALRasterBlock * GDALRasterBand::GetLockedBlockRef( int nXBlockOff,
             return( NULL );
         }
 
-        poBlock = new GDALRasterBlock( this, nXBlockOff, nYBlockOff );
+        poBlock = poBandBlockCache->CreateBlock( nXBlockOff, nYBlockOff );
+        if( poBlock == NULL )
+            return NULL;
 
         poBlock->AddLock();
 
@@ -1383,7 +1133,7 @@ GDALRasterBlock * GDALRasterBand::GetLockedBlockRef( int nXBlockOff,
             return( NULL );
         }
 
-        if ( AdoptBlock( nXBlockOff, nYBlockOff, poBlock ) != CE_None )
+        if ( AdoptBlock( poBlock ) != CE_None )
         {
             poBlock->DropLock();
             delete poBlock;
@@ -1404,7 +1154,7 @@ GDALRasterBlock * GDALRasterBand::GetLockedBlockRef( int nXBlockOff,
         if( !bJustInitialize )
         {
             nBlockReads++;
-            if( nBlockReads == nBlocksPerRow * nBlocksPerColumn + 1 
+            if( static_cast<GIntBig>(nBlockReads) == static_cast<GIntBig>(nBlocksPerRow) * nBlocksPerColumn + 1
                 && nBand == 1 && poDS != NULL )
             {
                 CPLDebug( "GDAL", "Potential thrashing on band %d of %s.",
@@ -1420,7 +1170,7 @@ GDALRasterBlock * GDALRasterBand::GetLockedBlockRef( int nXBlockOff,
 /*                               Fill()                                 */
 /************************************************************************/
 
-/** 
+/**
  * \brief Fill this band with a constant value.
  *
  * GDAL makes no guarantees
@@ -1435,7 +1185,7 @@ GDALRasterBlock * GDALRasterBand::GetLockedBlockRef( int nXBlockOff,
  *
  * @param dfRealValue Real component of fill value
  * @param dfImaginaryValue Imaginary component of fill value, defaults to zero
- * 
+ *
  * @return CE_Failure if the write fails, otherwise CE_None
  */
 CPLErr GDALRasterBand::Fill(double dfRealValue, double dfImaginaryValue) {
@@ -1463,7 +1213,7 @@ CPLErr GDALRasterBand::Fill(double dfRealValue, double dfImaginaryValue) {
 
     // Allocate the source block
     int blockSize = nBlockXSize * nBlockYSize;
-    int elementSize = GDALGetDataTypeSize(eDataType) / 8;
+    int elementSize = GDALGetDataTypeSizeBytes(eDataType);
     int blockByteSize = blockSize * elementSize;
     unsigned char* srcBlock = (unsigned char*) VSIMalloc(blockByteSize);
     if (srcBlock == NULL) {
@@ -1472,13 +1222,13 @@ CPLErr GDALRasterBand::Fill(double dfRealValue, double dfImaginaryValue) {
 		 "allocating %d bytes.\n", blockByteSize);
         return CE_Failure;
     }
-    
+
     // Initialize the source block
     double complexSrc[2] = { dfRealValue, dfImaginaryValue };
     GDALCopyWords(complexSrc, GDT_CFloat64, 0,
                   srcBlock, eDataType, elementSize, blockSize);
 
-    int bCallLeaveReadWrite = EnterReadWrite(GF_Write);
+    const bool bCallLeaveReadWrite = CPL_TO_BOOL(EnterReadWrite(GF_Write));
 
     // Write block to block cache
     for (int j = 0; j < nBlocksPerColumn; ++j) {
@@ -1491,18 +1241,12 @@ CPLErr GDALRasterBand::Fill(double dfRealValue, double dfImaginaryValue) {
                 VSIFree(srcBlock);
 		return CE_Failure;
 	    }
-            if (destBlock->GetDataRef() == NULL)
-            {
-                destBlock->DropLock();
-                VSIFree(srcBlock);
-                return CE_Failure;
-            }
 	    memcpy(destBlock->GetDataRef(), srcBlock, blockByteSize);
 	    destBlock->MarkDirty();
             destBlock->DropLock();
 	}
     }
-    
+
     if( bCallLeaveReadWrite ) LeaveReadWrite();
 
     // Free up the source block
@@ -1516,16 +1260,16 @@ CPLErr GDALRasterBand::Fill(double dfRealValue, double dfImaginaryValue) {
 /*                         GDALFillRaster()                             */
 /************************************************************************/
 
-/** 
+/**
  * \brief Fill this band with a constant value.
  *
  * @see GDALRasterBand::Fill()
  */
-CPLErr CPL_STDCALL GDALFillRaster(GDALRasterBandH hBand, double dfRealValue, 
+CPLErr CPL_STDCALL GDALFillRaster(GDALRasterBandH hBand, double dfRealValue,
 		      double dfImaginaryValue)
 {
     VALIDATE_POINTER1( hBand, "GDALFillRaster", CE_Failure );
-    
+
     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
     return poBand->Fill(dfRealValue, dfImaginaryValue);
 }
@@ -1575,13 +1319,13 @@ GDALAccess CPL_STDCALL GDALGetRasterAccess( GDALRasterBandH hBand )
  * \brief Fetch the list of category names for this raster.
  *
  * The return list is a "StringList" in the sense of the CPL functions.
- * That is a NULL terminated array of strings.  Raster values without 
+ * That is a NULL terminated array of strings.  Raster values without
  * associated names will have an empty string in the returned list.  The
- * first entry in the list is for raster values of zero, and so on. 
+ * first entry in the list is for raster values of zero, and so on.
  *
  * The returned stringlist should not be altered or freed by the application.
  * It may change on the next GDAL call, so please copy it if it is needed
- * for any period of time. 
+ * for any period of time.
  *
  * This method is the same as the C function GDALGetRasterCategoryNames().
  *
@@ -1621,12 +1365,12 @@ char ** CPL_STDCALL GDALGetRasterCategoryNames( GDALRasterBandH hBand )
  * \brief Set the category names for this band.
  *
  * See the GetCategoryNames() method for more on the interpretation of
- * category names. 
+ * category names.
  *
  * This method is the same as the C function GDALSetRasterCategoryNames().
  *
  * @param papszNames the NULL terminated StringList of category names.  May
- * be NULL to just clear the existing list. 
+ * be NULL to just clear the existing list.
  *
  * @return CE_None on success of CE_Failure on failure.  If unsupported
  * by the driver CE_Failure is returned, but no error message is reported.
@@ -1651,7 +1395,7 @@ CPLErr GDALRasterBand::SetCategoryNames( CPL_UNUSED char ** papszNames )
  * @see GDALRasterBand::SetCategoryNames()
  */
 
-CPLErr CPL_STDCALL 
+CPLErr CPL_STDCALL
 GDALSetRasterCategoryNames( GDALRasterBandH hBand, char ** papszNames )
 
 {
@@ -1667,7 +1411,7 @@ GDALSetRasterCategoryNames( GDALRasterBandH hBand, char ** papszNames )
 
 /**
  * \brief Fetch the no data value for this band.
- * 
+ *
  * If there is no out of data value, an out of range value will generally
  * be returned.  The no data value for a band is generally a special marker
  * value used to mark pixels that are not valid data.  Such pixels should
@@ -1686,7 +1430,7 @@ double GDALRasterBand::GetNoDataValue( int *pbSuccess )
 {
     if( pbSuccess != NULL )
         *pbSuccess = FALSE;
-    
+
     return -1e10;
 }
 
@@ -1696,11 +1440,11 @@ double GDALRasterBand::GetNoDataValue( int *pbSuccess )
 
 /**
  * \brief Fetch the no data value for this band.
- * 
+ *
  * @see GDALRasterBand::GetNoDataValue()
  */
 
-double CPL_STDCALL 
+double CPL_STDCALL
 GDALGetRasterNoDataValue( GDALRasterBandH hBand, int *pbSuccess )
 
 {
@@ -1715,10 +1459,17 @@ GDALGetRasterNoDataValue( GDALRasterBandH hBand, int *pbSuccess )
 /************************************************************************/
 
 /**
- * \brief Set the no data value for this band. 
+ * \brief Set the no data value for this band.
+ *
+ * Depending on drivers, changing the no data value may or may not have an
+ * effect on the pixel values of a raster that has just been created. It is
+ * thus advised to explicitly called Fill() if the intent is to initialize
+ * the raster to the nodata value.
+ * In ay case, changing an existing no data value, when one already exists and
+ * the dataset exists or has been initialized, has no effect on the pixel whose
+ * value matched the previous nodata value.
  *
- * To clear the nodata value, just set it with an "out of range" value.
- * Complex band no data values must have an imagery component of zero.
+ * To clear the nodata value, use DeleteNoDataValue().
  *
  * This method is the same as the C function GDALSetRasterNoDataValue().
  *
@@ -1744,12 +1495,20 @@ CPLErr GDALRasterBand::SetNoDataValue( CPL_UNUSED double dfNoData )
 /************************************************************************/
 
 /**
- * \brief Set the no data value for this band. 
+ * \brief Set the no data value for this band.
+ *
+ * Depending on drivers, changing the no data value may or may not have an
+ * effect on the pixel values of a raster that has just been created. It is
+ * thus advised to explicitly called Fill() if the intent is to initialize
+ * the raster to the nodata value.
+ * In ay case, changing an existing no data value, when one already exists and
+ * the dataset exists or has been initialized, has no effect on the pixel whose
+ * value matched the previous nodata value.
  *
  * @see GDALRasterBand::SetNoDataValue()
  */
 
-CPLErr CPL_STDCALL 
+CPLErr CPL_STDCALL
 GDALSetRasterNoDataValue( GDALRasterBandH hBand, double dfValue )
 
 {
@@ -1760,14 +1519,64 @@ GDALSetRasterNoDataValue( GDALRasterBandH hBand, double dfValue )
 }
 
 /************************************************************************/
+/*                        DeleteNoDataValue()                           */
+/************************************************************************/
+
+/**
+ * \brief Remove the no data value for this band.
+ *
+ * This method is the same as the C function GDALDeleteRasterNoDataValue().
+ *
+ * @param dfNoData the value to set.
+ *
+ * @return CE_None on success, or CE_Failure on failure.  If unsupported
+ * by the driver, CE_Failure is returned by no error message will have
+ * been emitted.
+ *
+ * @since GDAL 2.1
+ */
+
+CPLErr GDALRasterBand::DeleteNoDataValue()
+
+{
+    if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
+        ReportError( CE_Failure, CPLE_NotSupported,
+                  "DeleteNoDataValue() not supported for this dataset." );
+
+    return CE_Failure;
+}
+
+/************************************************************************/
+/*                       GDALDeleteRasterNoDataValue()                  */
+/************************************************************************/
+
+/**
+ * \brief Remove the no data value for this band.
+ *
+ * @see GDALRasterBand::DeleteNoDataValue()
+ *
+ * @since GDAL 2.1
+ */
+
+CPLErr CPL_STDCALL
+GDALDeleteRasterNoDataValue( GDALRasterBandH hBand )
+
+{
+    VALIDATE_POINTER1( hBand, "GDALDeleteRasterNoDataValue", CE_Failure );
+
+    GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
+    return poBand->DeleteNoDataValue();
+}
+
+/************************************************************************/
 /*                             GetMaximum()                             */
 /************************************************************************/
 
 /**
  * \brief Fetch the maximum value for this band.
- * 
+ *
  * For file formats that don't know this intrinsically, the maximum supported
- * value for the data type will generally be returned.  
+ * value for the data type will generally be returned.
  *
  * This method is the same as the C function GDALGetRasterMaximum().
  *
@@ -1781,12 +1590,12 @@ double GDALRasterBand::GetMaximum( int *pbSuccess )
 
 {
     const char *pszValue = NULL;
-    
+
     if( (pszValue = GetMetadataItem("STATISTICS_MAXIMUM")) != NULL )
     {
         if( pbSuccess != NULL )
             *pbSuccess = TRUE;
-        
+
         return CPLAtofM(pszValue);
     }
 
@@ -1837,11 +1646,11 @@ double GDALRasterBand::GetMaximum( int *pbSuccess )
 
 /**
  * \brief Fetch the maximum value for this band.
- * 
+ *
  * @see GDALRasterBand::GetMaximum()
  */
 
-double CPL_STDCALL 
+double CPL_STDCALL
 GDALGetRasterMaximum( GDALRasterBandH hBand, int *pbSuccess )
 
 {
@@ -1857,9 +1666,9 @@ GDALGetRasterMaximum( GDALRasterBandH hBand, int *pbSuccess )
 
 /**
  * \brief Fetch the minimum value for this band.
- * 
+ *
  * For file formats that don't know this intrinsically, the minimum supported
- * value for the data type will generally be returned.  
+ * value for the data type will generally be returned.
  *
  * This method is the same as the C function GDALGetRasterMinimum().
  *
@@ -1873,12 +1682,12 @@ double GDALRasterBand::GetMinimum( int *pbSuccess )
 
 {
     const char *pszValue = NULL;
-    
+
     if( (pszValue = GetMetadataItem("STATISTICS_MINIMUM")) != NULL )
     {
         if( pbSuccess != NULL )
             *pbSuccess = TRUE;
-        
+
         return CPLAtofM(pszValue);
     }
 
@@ -1925,11 +1734,11 @@ double GDALRasterBand::GetMinimum( int *pbSuccess )
 
 /**
  * \brief Fetch the minimum value for this band.
- * 
+ *
  * @see GDALRasterBand::GetMinimum()
  */
 
-double CPL_STDCALL 
+double CPL_STDCALL
 GDALGetRasterMinimum( GDALRasterBandH hBand, int *pbSuccess )
 
 {
@@ -1947,9 +1756,9 @@ GDALGetRasterMinimum( GDALRasterBandH hBand, int *pbSuccess )
  * \brief How should this band be interpreted as color?
  *
  * GCI_Undefined is returned when the format doesn't know anything
- * about the color interpretation. 
+ * about the color interpretation.
  *
- * This method is the same as the C function 
+ * This method is the same as the C function
  * GDALGetRasterColorInterpretation().
  *
  * @return color interpretation value for band.
@@ -1971,7 +1780,7 @@ GDALColorInterp GDALRasterBand::GetColorInterpretation()
  * @see GDALRasterBand::GetColorInterpretation()
  */
 
-GDALColorInterp CPL_STDCALL 
+GDALColorInterp CPL_STDCALL
 GDALGetRasterColorInterpretation( GDALRasterBandH hBand )
 
 {
@@ -1991,7 +1800,7 @@ GDALGetRasterColorInterpretation( GDALRasterBandH hBand )
  * This method is the same as the C function GDALSetRasterColorInterpretation().
  *
  * @param eColorInterp the new color interpretation to apply to this band.
- * 
+ *
  * @return CE_None on success or CE_Failure if method is unsupported by format.
  */
 
@@ -2015,7 +1824,7 @@ CPLErr GDALRasterBand::SetColorInterpretation( GDALColorInterp eColorInterp)
  * @see GDALRasterBand::SetColorInterpretation()
  */
 
-CPLErr CPL_STDCALL 
+CPLErr CPL_STDCALL
 GDALSetRasterColorInterpretation( GDALRasterBandH hBand,
                                   GDALColorInterp eColorInterp )
 
@@ -2072,14 +1881,14 @@ GDALColorTableH CPL_STDCALL GDALGetRasterColorTable( GDALRasterBandH hBand )
 /************************************************************************/
 
 /**
- * \brief Set the raster color table. 
- * 
+ * \brief Set the raster color table.
+ *
  * The driver will make a copy of all desired data in the colortable.  It
  * remains owned by the caller after the call.
  *
  * This method is the same as the C function GDALSetRasterColorTable().
  *
- * @param poCT the color table to apply.  This may be NULL to clear the color 
+ * @param poCT the color table to apply.  This may be NULL to clear the color
  * table (where supported).
  *
  * @return CE_None on success, or CE_Failure on failure.  If the action is
@@ -2102,12 +1911,12 @@ CPLErr GDALRasterBand::SetColorTable( GDALColorTable * poCT )
 /************************************************************************/
 
 /**
- * \brief Set the raster color table. 
- * 
+ * \brief Set the raster color table.
+ *
  * @see GDALRasterBand::SetColorTable()
  */
 
-CPLErr CPL_STDCALL 
+CPLErr CPL_STDCALL
 GDALSetRasterColorTable( GDALRasterBandH hBand, GDALColorTableH hCT )
 
 {
@@ -2124,8 +1933,8 @@ GDALSetRasterColorTable( GDALRasterBandH hBand, GDALColorTableH hCT )
 /**
  * \brief Check for arbitrary overviews.
  *
- * This returns TRUE if the underlying datastore can compute arbitrary 
- * overviews efficiently, such as is the case with OGDI over a network. 
+ * This returns TRUE if the underlying datastore can compute arbitrary
+ * overviews efficiently, such as is the case with OGDI over a network.
  * Datastores with arbitrary overviews don't generally have any fixed
  * overviews, but the RasterIO() method can be used in downsampling mode
  * to get overview data efficiently.
@@ -2133,7 +1942,7 @@ GDALSetRasterColorTable( GDALRasterBandH hBand, GDALColorTableH hCT )
  * This method is the same as the C function GDALHasArbitraryOverviews(),
  *
  * @return TRUE if arbitrary overviews available (efficiently), otherwise
- * FALSE. 
+ * FALSE.
  */
 
 int GDALRasterBand::HasArbitraryOverviews()
@@ -2156,7 +1965,7 @@ int CPL_STDCALL GDALHasArbitraryOverviews( GDALRasterBandH hBand )
 
 {
     VALIDATE_POINTER1( hBand, "GDALHasArbitraryOverviews", 0 );
-    
+
     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
     return poBand->HasArbitraryOverviews();
 }
@@ -2210,9 +2019,9 @@ int CPL_STDCALL GDALGetOverviewCount( GDALRasterBandH hBand )
  * \brief Fetch overview raster band object.
  *
  * This method is the same as the C function GDALGetOverview().
- * 
+ *
  * @param i overview index between 0 and GetOverviewCount()-1.
- * 
+ *
  * @return overview GDALRasterBand.
  */
 
@@ -2253,36 +2062,35 @@ GDALRasterBandH CPL_STDCALL GDALGetOverview( GDALRasterBandH hBand, int i )
  *
  * Returns the most reduced overview of the given band that still satisfies
  * the desired number of samples.  This function can be used with zero
- * as the number of desired samples to fetch the most reduced overview. 
+ * as the number of desired samples to fetch the most reduced overview.
  * The same band as was passed in will be returned if it has not overviews,
  * or if none of the overviews have enough samples.
  *
  * This method is the same as the C functions GDALGetRasterSampleOverview()
  * and GDALGetRasterSampleOverviewEx().
  *
- * @param nDesiredSamples the returned band will have at least this many 
+ * @param nDesiredSamples the returned band will have at least this many
  * pixels.
  *
- * @return optimal overview or the band itself. 
+ * @return optimal overview or the band itself.
  */
 
 GDALRasterBand *GDALRasterBand::GetRasterSampleOverview( GUIntBig nDesiredSamples )
 
 {
-    double dfBestSamples = 0; 
     GDALRasterBand *poBestBand = this;
 
-    dfBestSamples = GetXSize() * (double)GetYSize();
+    double dfBestSamples = GetXSize() * (double)GetYSize();
 
     for( int iOverview = 0; iOverview < GetOverviewCount(); iOverview++ )
     {
         GDALRasterBand  *poOBand = GetOverview( iOverview );
-        double          dfOSamples = 0;
 
         if (poOBand == NULL)
             continue;
 
-        dfOSamples = poOBand->GetXSize() * (double)poOBand->GetYSize();
+        const double dfOSamples
+            = poOBand->GetXSize() * (double)poOBand->GetYSize();
 
         if( dfOSamples < dfBestSamples && dfOSamples > nDesiredSamples )
         {
@@ -2308,7 +2116,7 @@ GDALRasterBand *GDALRasterBand::GetRasterSampleOverview( GUIntBig nDesiredSample
  * @see GDALGetRasterSampleOverviewEx()
  */
 
-GDALRasterBandH CPL_STDCALL 
+GDALRasterBandH CPL_STDCALL
 GDALGetRasterSampleOverview( GDALRasterBandH hBand, int nDesiredSamples )
 
 {
@@ -2330,7 +2138,7 @@ GDALGetRasterSampleOverview( GDALRasterBandH hBand, int nDesiredSamples )
  * @since GDAL 2.0
  */
 
-GDALRasterBandH CPL_STDCALL 
+GDALRasterBandH CPL_STDCALL
 GDALGetRasterSampleOverviewEx( GDALRasterBandH hBand, GUIntBig nDesiredSamples )
 
 {
@@ -2348,8 +2156,8 @@ GDALGetRasterSampleOverviewEx( GDALRasterBandH hBand, GUIntBig nDesiredSamples )
 /**
  * \brief Build raster overview(s)
  *
- * If the operation is unsupported for the indicated dataset, then 
- * CE_Failure is returned, and CPLGetLastErrorNo() will return 
+ * If the operation is unsupported for the indicated dataset, then
+ * CE_Failure is returned, and CPLGetLastErrorNo() will return
  * CPLE_NotSupported.
  *
  * WARNING:  It is not possible to build overviews for a single band in
@@ -2357,34 +2165,28 @@ GDALGetRasterSampleOverviewEx( GDALRasterBandH hBand, GUIntBig nDesiredSamples )
  * formats that use the default overview building in TIFF format.  Instead
  * it is necessary to build overviews on the dataset as a whole using
  * GDALDataset::BuildOverviews().  That makes this method pretty useless
- * from a practical point of view. 
+ * from a practical point of view.
  *
  * @param pszResampling one of "NEAREST", "GAUSS", "CUBIC", "AVERAGE", "MODE",
  * "AVERAGE_MAGPHASE" or "NONE" controlling the downsampling method applied.
- * @param nOverviews number of overviews to build. 
- * @param panOverviewList the list of overview decimation factors to build. 
+ * @param nOverviews number of overviews to build.
+ * @param panOverviewList the list of overview decimation factors to build.
  * @param pfnProgress a function to call to report progress, or NULL.
  * @param pProgressData application data to pass to the progress function.
  *
- * @return CE_None on success or CE_Failure if the operation doesn't work. 
+ * @return CE_None on success or CE_Failure if the operation doesn't work.
  */
 
-CPLErr GDALRasterBand::BuildOverviews( const char * pszResampling, 
-                                       int nOverviews, 
-                                       int * panOverviewList, 
-                                       GDALProgressFunc pfnProgress, 
-                                       void * pProgressData )
+CPLErr GDALRasterBand::BuildOverviews( const char * /* pszResampling */,
+                                       int /* nOverviews */,
+                                       int * /* panOverviewList */,
+                                       GDALProgressFunc /* pfnProgress */,
+                                       void * /* pProgressData */)
 
 {
-    (void) pszResampling;
-    (void) nOverviews;
-    (void) panOverviewList;
-    (void) pfnProgress;
-    (void) pProgressData;
-
     ReportError( CE_Failure, CPLE_NotSupported,
               "BuildOverviews() not supported for this dataset." );
-    
+
     return( CE_Failure );
 }
 
@@ -2396,14 +2198,14 @@ CPLErr GDALRasterBand::BuildOverviews( const char * pszResampling,
  * \brief Fetch the raster value offset.
  *
  * This value (in combination with the GetScale() value) is used to
- * transform raw pixel values into the units returned by GetUnits().  
+ * transform raw pixel values into the units returned by GetUnits().
  * For example this might be used to store elevations in GUInt16 bands
- * with a precision of 0.1, and starting from -100. 
- * 
+ * with a precision of 0.1, and starting from -100.
+ *
  * Units value = (raw value * scale) + offset
- * 
+ *
  * For file formats that don't know this intrinsically a value of zero
- * is returned. 
+ * is returned.
  *
  * This method is the same as the C function GDALGetRasterOffset().
  *
@@ -2449,7 +2251,7 @@ double CPL_STDCALL GDALGetRasterOffset( GDALRasterBandH hBand, int *pbSuccess )
  * \brief Set scaling offset.
  *
  * Very few formats implement this method.   When not implemented it will
- * issue a CPLE_NotSupported error and return CE_Failure. 
+ * issue a CPLE_NotSupported error and return CE_Failure.
  *
  * This method is the same as the C function GDALSetRasterOffset().
  *
@@ -2477,7 +2279,7 @@ CPLErr GDALRasterBand::SetOffset( CPL_UNUSED double dfNewOffset )
  * @see GDALRasterBand::SetOffset()
  */
 
-CPLErr CPL_STDCALL 
+CPLErr CPL_STDCALL
 GDALSetRasterOffset( GDALRasterBandH hBand, double dfNewOffset )
 
 {
@@ -2495,14 +2297,14 @@ GDALSetRasterOffset( GDALRasterBandH hBand, double dfNewOffset )
  * \brief Fetch the raster value scale.
  *
  * This value (in combination with the GetOffset() value) is used to
- * transform raw pixel values into the units returned by GetUnits().  
+ * transform raw pixel values into the units returned by GetUnits().
  * For example this might be used to store elevations in GUInt16 bands
- * with a precision of 0.1, and starting from -100. 
- * 
+ * with a precision of 0.1, and starting from -100.
+ *
  * Units value = (raw value * scale) + offset
- * 
+ *
  * For file formats that don't know this intrinsically a value of one
- * is returned. 
+ * is returned.
  *
  * This method is the same as the C function GDALGetRasterScale().
  *
@@ -2548,10 +2350,10 @@ double CPL_STDCALL GDALGetRasterScale( GDALRasterBandH hBand, int *pbSuccess )
  * \brief Set scaling ratio.
  *
  * Very few formats implement this method.   When not implemented it will
- * issue a CPLE_NotSupported error and return CE_Failure. 
+ * issue a CPLE_NotSupported error and return CE_Failure.
  *
  * This method is the same as the C function GDALSetRasterScale().
- * 
+ *
  * @param dfNewScale the new scale.
  *
  * @return CE_None or success or CE_Failure on failure.
@@ -2577,7 +2379,7 @@ CPLErr GDALRasterBand::SetScale( CPL_UNUSED double dfNewScale )
  * @see GDALRasterBand::SetScale()
  */
 
-CPLErr CPL_STDCALL 
+CPLErr CPL_STDCALL
 GDALSetRasterScale( GDALRasterBandH hBand, double dfNewOffset )
 
 {
@@ -2595,11 +2397,11 @@ GDALSetRasterScale( GDALRasterBandH hBand, double dfNewOffset )
  * \brief Return raster unit type.
  *
  * Return a name for the units of this raster's values.  For instance, it
- * might be "m" for an elevation model in meters, or "ft" for feet.  If no 
- * units are available, a value of "" will be returned.  The returned string 
+ * might be "m" for an elevation model in meters, or "ft" for feet.  If no
+ * units are available, a value of "" will be returned.  The returned string
  * should not be modified, nor freed by the calling application.
  *
- * This method is the same as the C function GDALGetRasterUnitType(). 
+ * This method is the same as the C function GDALGetRasterUnitType().
  *
  * @return unit name string.
  */
@@ -2637,14 +2439,14 @@ const char * CPL_STDCALL GDALGetRasterUnitType( GDALRasterBandH hBand )
  * \brief Set unit type.
  *
  * Set the unit type for a raster band.  Values should be one of
- * "" (the default indicating it is unknown), "m" indicating meters, 
+ * "" (the default indicating it is unknown), "m" indicating meters,
  * or "ft" indicating feet, though other nonstandard values are allowed.
  *
- * This method is the same as the C function GDALSetRasterUnitType(). 
+ * This method is the same as the C function GDALSetRasterUnitType().
  *
  * @param pszNewValue the new unit type value.
  *
- * @return CE_None on success or CE_Failure if not succuessful, or
+ * @return CE_None on success or CE_Failure if not successful, or
  * unsupported.
  */
 
@@ -2683,9 +2485,9 @@ CPLErr CPL_STDCALL GDALSetRasterUnitType( GDALRasterBandH hBand, const char *psz
 /************************************************************************/
 
 /**
- * \brief Fetch XSize of raster. 
+ * \brief Fetch XSize of raster.
  *
- * This method is the same as the C function GDALGetRasterBandXSize(). 
+ * This method is the same as the C function GDALGetRasterBandXSize().
  *
  * @return the width in pixels of this band.
  */
@@ -2701,7 +2503,7 @@ int GDALRasterBand::GetXSize()
 /************************************************************************/
 
 /**
- * \brief Fetch XSize of raster. 
+ * \brief Fetch XSize of raster.
  *
  * @see GDALRasterBand::GetXSize()
  */
@@ -2720,9 +2522,9 @@ int CPL_STDCALL GDALGetRasterBandXSize( GDALRasterBandH hBand )
 /************************************************************************/
 
 /**
- * \brief Fetch YSize of raster. 
+ * \brief Fetch YSize of raster.
  *
- * This method is the same as the C function GDALGetRasterBandYSize(). 
+ * This method is the same as the C function GDALGetRasterBandYSize().
  *
  * @return the height in pixels of this band.
  */
@@ -2738,7 +2540,7 @@ int GDALRasterBand::GetYSize()
 /************************************************************************/
 
 /**
- * \brief Fetch YSize of raster. 
+ * \brief Fetch YSize of raster.
  *
  * @see GDALRasterBand::GetYSize()
  */
@@ -2802,7 +2604,7 @@ int CPL_STDCALL GDALGetBandNumber( GDALRasterBandH hBand )
  * \brief Fetch the owning dataset handle.
  *
  * Note that some GDALRasterBands are not considered to be a part of a dataset,
- * such as overviews or other "freestanding" bands. 
+ * such as overviews or other "freestanding" bands.
  *
  * This method is the same as the C function GDALGetBandDataset().
  *
@@ -2840,23 +2642,23 @@ GDALDatasetH CPL_STDCALL GDALGetBandDataset( GDALRasterBandH hBand )
 /************************************************************************/
 
 /**
- * \brief Compute raster histogram. 
+ * \brief Compute raster histogram.
  *
- * Note that the bucket size is (dfMax-dfMin) / nBuckets.  
+ * Note that the bucket size is (dfMax-dfMin) / nBuckets.
  *
- * For example to compute a simple 256 entry histogram of eight bit data, 
+ * For example to compute a simple 256 entry histogram of eight bit data,
  * the following would be suitable.  The unusual bounds are to ensure that
  * bucket boundaries don't fall right on integer values causing possible errors
- * due to rounding after scaling. 
+ * due to rounding after scaling.
 <pre>
     GUIntBig anHistogram[256];
 
-    poBand->GetHistogram( -0.5, 255.5, 256, anHistogram, FALSE, FALSE, 
+    poBand->GetHistogram( -0.5, 255.5, 256, anHistogram, FALSE, FALSE,
                           GDALDummyProgress, NULL );
 </pre>
  *
  * Note that setting bApproxOK will generally result in a subsampling of the
- * file, and will utilize overviews if available.  It should generally 
+ * file, and will utilize overviews if available.  It should generally
  * produce a representative histogram for the data that is suitable for use
  * in generating histogram based luts for instance.  Generally bApproxOK is
  * much faster than an exactly computed histogram.
@@ -2869,19 +2671,19 @@ GDALDatasetH CPL_STDCALL GDALGetBandDataset( GDALRasterBandH hBand )
  * @param nBuckets the number of buckets in panHistogram.
  * @param panHistogram array into which the histogram totals are placed.
  * @param bIncludeOutOfRange if TRUE values below the histogram range will
- * mapped into panHistogram[0], and values above will be mapped into 
+ * mapped into panHistogram[0], and values above will be mapped into
  * panHistogram[nBuckets-1] otherwise out of range values are discarded.
  * @param bApproxOK TRUE if an approximate, or incomplete histogram OK.
- * @param pfnProgress function to report progress to completion. 
- * @param pProgressData application data to pass to pfnProgress. 
+ * @param pfnProgress function to report progress to completion.
+ * @param pProgressData application data to pass to pfnProgress.
  *
- * @return CE_None on success, or CE_Failure if something goes wrong. 
+ * @return CE_None on success, or CE_Failure if something goes wrong.
  */
 
-CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax, 
-                                     int nBuckets, GUIntBig *panHistogram, 
+CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
+                                     int nBuckets, GUIntBig *panHistogram,
                                      int bIncludeOutOfRange, int bApproxOK,
-                                     GDALProgressFunc pfnProgress, 
+                                     GDALProgressFunc pfnProgress,
                                      void *pProgressData )
 
 {
@@ -2899,7 +2701,7 @@ CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
         // minimum number of samples like GDALRasterBand::ComputeStatistics()
         // does?
         GDALRasterBand *poBestOverview = GetRasterSampleOverview( 0 );
-        
+
         if( poBestOverview != this )
         {
             return poBestOverview->GetHistogram( dfMin, dfMax, nBuckets,
@@ -2930,10 +2732,10 @@ CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
     /* Not advertized. May be removed at any time. Just as a provision if the */
     /* old behaviour made sense somethimes... */
     bGotNoDataValue = bGotNoDataValue &&
-        !CSLTestBoolean(CPLGetConfigOption("GDAL_NODATA_IN_HISTOGRAM", "NO"));
+        !CPLTestBool(CPLGetConfigOption("GDAL_NODATA_IN_HISTOGRAM", "NO"));
 
     const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
-    int bSignedByte = (pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE"));
+    const bool bSignedByte = (pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE"));
 
     if ( bApproxOK && HasArbitraryOverviews() )
     {
@@ -2941,11 +2743,11 @@ CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
 /*      Figure out how much the image should be reduced to get an       */
 /*      approximate value.                                              */
 /* -------------------------------------------------------------------- */
-        void    *pData;
-        int     nXReduced, nYReduced;
         double  dfReduction = sqrt(
             (double)nRasterXSize * nRasterYSize / GDALSTAT_APPROX_NUMSAMPLES );
 
+        int     nXReduced, nYReduced;
+
         if ( dfReduction > 1.0 )
         {
             nXReduced = (int)( nRasterXSize / dfReduction );
@@ -2963,8 +2765,9 @@ CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
             nYReduced = nRasterYSize;
         }
 
-        pData =
-            CPLMalloc(GDALGetDataTypeSize(eDataType)/8 * nXReduced * nYReduced);
+        void *pData =
+            CPLMalloc(
+                GDALGetDataTypeSizeBytes(eDataType) * nXReduced * nYReduced );
 
         CPLErr eErr = IRasterIO( GF_Read, 0, 0, nRasterXSize, nRasterYSize, pData,
                    nXReduced, nYReduced, eDataType, 0, 0, &sExtraArg );
@@ -2973,14 +2776,13 @@ CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
             CPLFree(pData);
             return eErr;
         }
-        
+
         /* this isn't the fastest way to do this, but is easier for now */
         for( int iY = 0; iY < nYReduced; iY++ )
         {
             for( int iX = 0; iX < nXReduced; iX++ )
             {
                 int    iOffset = iX + iY * nXReduced;
-                int    nIndex;
                 double dfValue = 0.0;
 
                 switch( eDataType )
@@ -3058,8 +2860,8 @@ CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
                 if( bGotNoDataValue && ARE_REAL_EQUAL(dfValue, dfNoDataValue) )
                     continue;
 
-                nIndex = (int) floor((dfValue - dfMin) * dfScale);
-                
+                int nIndex = (int) floor((dfValue - dfMin) * dfScale);
+
                 if( nIndex < 0 )
                 {
                     if( bIncludeOutOfRange )
@@ -3082,54 +2884,52 @@ CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
 
     else    // No arbitrary overviews
     {
-        int         nSampleRate;
 
         if( !InitBlockInfo() )
             return CE_Failure;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Figure out the ratio of blocks we will read to get an           */
 /*      approximate value.                                              */
 /* -------------------------------------------------------------------- */
 
+        int nSampleRate;
         if ( bApproxOK )
         {
-            nSampleRate = 
+            nSampleRate =
                 (int) MAX(1,sqrt((double) nBlocksPerRow * nBlocksPerColumn));
+            // We want to avoid probing only the first column of blocks for
+            // a square shaped raster, because it is not unlikely that it may
+            // be padding only (#6378)
+            if( nSampleRate == nBlocksPerRow && nBlocksPerRow > 1 )
+              nSampleRate += 1;
         }
         else
             nSampleRate = 1;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read the blocks, and add to histogram.                          */
 /* -------------------------------------------------------------------- */
-        for( int iSampleBlock = 0; 
+        for( int iSampleBlock = 0;
              iSampleBlock < nBlocksPerRow * nBlocksPerColumn;
              iSampleBlock += nSampleRate )
         {
-            int  iXBlock, iYBlock, nXCheck, nYCheck;
-            GDALRasterBlock *poBlock;
-            void* pData;
+            int  nXCheck, nYCheck;
 
             if( !pfnProgress( iSampleBlock
                               / ((double)nBlocksPerRow * nBlocksPerColumn),
                               "Compute Histogram", pProgressData ) )
                 return CE_Failure;
 
-            iYBlock = iSampleBlock / nBlocksPerRow;
-            iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
-            
-            poBlock = GetLockedBlockRef( iXBlock, iYBlock );
+            int iYBlock = iSampleBlock / nBlocksPerRow;
+            int iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
+
+            GDALRasterBlock *poBlock = GetLockedBlockRef( iXBlock, iYBlock );
             if( poBlock == NULL )
                 return CE_Failure;
-            if( poBlock->GetDataRef() == NULL )
-            {
-                poBlock->DropLock();
-                return CE_Failure;
-            }
-            
-            pData = poBlock->GetDataRef();
-            
+
+            void *pData = poBlock->GetDataRef();
+
             if( (iXBlock+1) * nBlockXSize > GetXSize() )
                 nXCheck = GetXSize() - iXBlock * nBlockXSize;
             else
@@ -3148,7 +2948,7 @@ CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
             {
                 int    nPixels = nXCheck * nYCheck;
                 GByte  *pabyData = (GByte *) pData;
-                
+
                 for( int i = 0; i < nPixels; i++ )
                     if (! (bGotNoDataValue && (pabyData[i] == (GByte)dfNoDataValue)))
                     {
@@ -3244,7 +3044,7 @@ CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
                         CPLAssert( FALSE );
                         return CE_Failure;
                     }
-                    
+
                     if( bGotNoDataValue && ARE_REAL_EQUAL(dfValue, dfNoDataValue) )
                         continue;
 
@@ -3281,7 +3081,7 @@ CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
 /************************************************************************/
 
 /**
- * \brief Compute raster histogram. 
+ * \brief Compute raster histogram.
  *
  * Use GDALGetRasterHistogramEx() instead to get correct counts for values
  * exceeding 2 billion.
@@ -3290,20 +3090,20 @@ CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
  * @see GDALGetRasterHistogramEx()
  */
 
-CPLErr CPL_STDCALL 
-GDALGetRasterHistogram( GDALRasterBandH hBand, 
-                        double dfMin, double dfMax, 
-                        int nBuckets, int *panHistogram, 
+CPLErr CPL_STDCALL
+GDALGetRasterHistogram( GDALRasterBandH hBand,
+                        double dfMin, double dfMax,
+                        int nBuckets, int *panHistogram,
                         int bIncludeOutOfRange, int bApproxOK,
-                        GDALProgressFunc pfnProgress, 
+                        GDALProgressFunc pfnProgress,
                         void *pProgressData )
-    
+
 {
     VALIDATE_POINTER1( hBand, "GDALGetRasterHistogram", CE_Failure );
     VALIDATE_POINTER1( panHistogram, "GDALGetRasterHistogram", CE_Failure );
 
     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
-    
+
     GUIntBig* panHistogramTemp = (GUIntBig*)VSIMalloc2(sizeof(GUIntBig), nBuckets);
     if( panHistogramTemp == NULL )
     {
@@ -3312,7 +3112,7 @@ GDALGetRasterHistogram( GDALRasterBandH hBand,
         return CE_Failure;
     }
 
-    CPLErr eErr = poBand->GetHistogram( dfMin, dfMax, nBuckets, panHistogramTemp, 
+    CPLErr eErr = poBand->GetHistogram( dfMin, dfMax, nBuckets, panHistogramTemp,
                       bIncludeOutOfRange, bApproxOK,
                       pfnProgress, pProgressData );
 
@@ -3331,9 +3131,9 @@ GDALGetRasterHistogram( GDALRasterBandH hBand,
                 panHistogram[i] = (int)panHistogramTemp[i];
         }
     }
-    
+
     CPLFree(panHistogramTemp);
-    
+
     return eErr;
 }
 
@@ -3342,28 +3142,28 @@ GDALGetRasterHistogram( GDALRasterBandH hBand,
 /************************************************************************/
 
 /**
- * \brief Compute raster histogram. 
+ * \brief Compute raster histogram.
  *
  * @see GDALRasterBand::GetHistogram()
  *
  * @since GDAL 2.0
  */
 
-CPLErr CPL_STDCALL 
-GDALGetRasterHistogramEx( GDALRasterBandH hBand, 
-                        double dfMin, double dfMax, 
-                        int nBuckets, GUIntBig *panHistogram, 
+CPLErr CPL_STDCALL
+GDALGetRasterHistogramEx( GDALRasterBandH hBand,
+                        double dfMin, double dfMax,
+                        int nBuckets, GUIntBig *panHistogram,
                         int bIncludeOutOfRange, int bApproxOK,
-                        GDALProgressFunc pfnProgress, 
+                        GDALProgressFunc pfnProgress,
                         void *pProgressData )
-    
+
 {
     VALIDATE_POINTER1( hBand, "GDALGetRasterHistogramEx", CE_Failure );
     VALIDATE_POINTER1( panHistogram, "GDALGetRasterHistogramEx", CE_Failure );
 
     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
 
-    return poBand->GetHistogram( dfMin, dfMax, nBuckets, panHistogram, 
+    return poBand->GetHistogram( dfMin, dfMax, nBuckets, panHistogram,
                       bIncludeOutOfRange, bApproxOK,
                       pfnProgress, pProgressData );
 }
@@ -3373,10 +3173,10 @@ GDALGetRasterHistogramEx( GDALRasterBandH hBand,
 /************************************************************************/
 
 /**
- * \brief Fetch default raster histogram. 
+ * \brief Fetch default raster histogram.
  *
  * The default method in GDALRasterBand will compute a default histogram. This
- * method is overriden by derived classes (such as GDALPamRasterBand, VRTDataset, HFADataset...)
+ * method is overridden by derived classes (such as GDALPamRasterBand, VRTDataset, HFADataset...)
  * that may be able to fetch efficiently an already stored histogram.
  *
  * This method is the same as the C functions GDALGetDefaultHistogram() and
@@ -3387,18 +3187,18 @@ GDALGetRasterHistogramEx( GDALRasterBandH hBand,
  * @param pnBuckets pointer to int value that will contain the number of buckets in *ppanHistogram.
  * @param ppanHistogram pointer to array into which the histogram totals are placed. To be freed with VSIFree
  * @param bForce TRUE to force the computation. If FALSE and no default histogram is available, the method will return CE_Warning
- * @param pfnProgress function to report progress to completion. 
- * @param pProgressData application data to pass to pfnProgress. 
+ * @param pfnProgress function to report progress to completion.
+ * @param pProgressData application data to pass to pfnProgress.
  *
- * @return CE_None on success, CE_Failure if something goes wrong, or 
+ * @return CE_None on success, CE_Failure if something goes wrong, or
  * CE_Warning if no default histogram is available.
  */
 
-CPLErr 
-    GDALRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax, 
-                                         int *pnBuckets, GUIntBig **ppanHistogram, 
+CPLErr
+    GDALRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
+                                         int *pnBuckets, GUIntBig **ppanHistogram,
                                          int bForce,
-                                         GDALProgressFunc pfnProgress, 
+                                         GDALProgressFunc pfnProgress,
                                          void *pProgressData )
 
 {
@@ -3414,7 +3214,7 @@ CPLErr
         return CE_Warning;
 
     int nBuckets = 256;
-    
+
     const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
     int bSignedByte = (pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE"));
 
@@ -3446,7 +3246,7 @@ CPLErr
     }
 
     *pnBuckets = nBuckets;
-    return GetHistogram( *pdfMin, *pdfMax, *pnBuckets, *ppanHistogram, 
+    return GetHistogram( *pdfMin, *pdfMax, *pnBuckets, *ppanHistogram,
                          TRUE, FALSE, pfnProgress, pProgressData );
 }
 
@@ -3455,7 +3255,7 @@ CPLErr
 /************************************************************************/
 
 /**
-  * \brief Fetch default raster histogram. 
+  * \brief Fetch default raster histogram.
   *
   * Use GDALGetRasterHistogramEx() instead to get correct counts for values
   * exceeding 2 billion.
@@ -3464,11 +3264,11 @@ CPLErr
   * @see GDALGetRasterHistogramEx()
   */
 
-CPLErr CPL_STDCALL GDALGetDefaultHistogram( GDALRasterBandH hBand, 
-                                double *pdfMin, double *pdfMax, 
-                                int *pnBuckets, int **ppanHistogram, 
+CPLErr CPL_STDCALL GDALGetDefaultHistogram( GDALRasterBandH hBand,
+                                double *pdfMin, double *pdfMax,
+                                int *pnBuckets, int **ppanHistogram,
                                 int bForce,
-                                GDALProgressFunc pfnProgress, 
+                                GDALProgressFunc pfnProgress,
                                 void *pProgressData )
 
 {
@@ -3520,18 +3320,18 @@ CPLErr CPL_STDCALL GDALGetDefaultHistogram( GDALRasterBandH hBand,
 /************************************************************************/
 
 /**
-  * \brief Fetch default raster histogram. 
+  * \brief Fetch default raster histogram.
   *
   * @see GDALRasterBand::GetDefaultHistogram()
   *
   * @since GDAL 2.0
   */
 
-CPLErr CPL_STDCALL GDALGetDefaultHistogramEx( GDALRasterBandH hBand, 
-                                double *pdfMin, double *pdfMax, 
-                                int *pnBuckets, GUIntBig **ppanHistogram, 
+CPLErr CPL_STDCALL GDALGetDefaultHistogramEx( GDALRasterBandH hBand,
+                                double *pdfMin, double *pdfMax,
+                                int *pnBuckets, GUIntBig **ppanHistogram,
                                 int bForce,
-                                GDALProgressFunc pfnProgress, 
+                                GDALProgressFunc pfnProgress,
                                 void *pProgressData )
 
 {
@@ -3552,13 +3352,13 @@ CPLErr CPL_STDCALL GDALGetDefaultHistogramEx( GDALRasterBandH hBand,
 /**
  * \brief Advise driver of upcoming read requests.
  *
- * Some GDAL drivers operate more efficiently if they know in advance what 
+ * Some GDAL drivers operate more efficiently if they know in advance what
  * set of upcoming read requests will be made.  The AdviseRead() method allows
- * an application to notify the driver of the region of interest, 
- * and at what resolution the region will be read.  
+ * an application to notify the driver of the region of interest,
+ * and at what resolution the region will be read.
  *
  * Many drivers just ignore the AdviseRead() call, but it can dramatically
- * accelerate access via some drivers.  
+ * accelerate access via some drivers.
  *
  * @param nXOff The pixel offset to the top left corner of the region
  * of the band to be accessed.  This would be zero to start from the left side.
@@ -3580,11 +3380,11 @@ CPLErr CPL_STDCALL GDALGetDefaultHistogramEx( GDALRasterBandH hBand,
  * pixel values will automatically be translated to/from the GDALRasterBand
  * data type as needed.
  *
- * @param papszOptions a list of name=value strings with special control 
+ * @param papszOptions a list of name=value strings with special control
  * options.  Normally this is NULL.
  *
  * @return CE_Failure if the request is invalid and CE_None if it works or
- * is ignored. 
+ * is ignored.
  */
 
 CPLErr GDALRasterBand::AdviseRead(
@@ -3607,17 +3407,17 @@ CPLErr GDALRasterBand::AdviseRead(
  * @see GDALRasterBand::AdviseRead()
  */
 
-CPLErr CPL_STDCALL 
-GDALRasterAdviseRead( GDALRasterBandH hBand, 
+CPLErr CPL_STDCALL
+GDALRasterAdviseRead( GDALRasterBandH hBand,
                       int nXOff, int nYOff, int nXSize, int nYSize,
-                      int nBufXSize, int nBufYSize, 
+                      int nBufXSize, int nBufYSize,
                       GDALDataType eDT, char **papszOptions )
-    
+
 {
     VALIDATE_POINTER1( hBand, "GDALRasterAdviseRead", CE_Failure );
 
     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
-    return poBand->AdviseRead( nXOff, nYOff, nXSize, nYSize, 
+    return poBand->AdviseRead( nXOff, nYOff, nXSize, nYSize,
         nBufXSize, nBufYSize, eDT, papszOptions );
 }
 
@@ -3626,30 +3426,30 @@ GDALRasterAdviseRead( GDALRasterBandH hBand,
 /************************************************************************/
 
 /**
- * \brief Fetch image statistics. 
+ * \brief Fetch image statistics.
  *
  * Returns the minimum, maximum, mean and standard deviation of all
  * pixel values in this band.  If approximate statistics are sufficient,
  * the bApproxOK flag can be set to true in which case overviews, or a
- * subset of image tiles may be used in computing the statistics.  
+ * subset of image tiles may be used in computing the statistics.
  *
- * If bForce is FALSE results will only be returned if it can be done 
- * quickly (ie. without scanning the data).  If bForce is FALSE and 
+ * If bForce is FALSE results will only be returned if it can be done
+ * quickly (i.e. without scanning the data).  If bForce is FALSE and
  * results cannot be returned efficiently, the method will return CE_Warning
  * but no warning will have been issued.   This is a non-standard use of
- * the CE_Warning return value to indicate "nothing done". 
+ * the CE_Warning return value to indicate "nothing done".
  *
  * Note that file formats using PAM (Persistent Auxiliary Metadata) services
  * will generally cache statistics in the .pam file allowing fast fetch
- * after the first request. 
+ * after the first request.
  *
  * This method is the same as the C function GDALGetRasterStatistics().
  *
  * @param bApproxOK If TRUE statistics may be computed based on overviews
- * or a subset of all tiles. 
- * 
+ * or a subset of all tiles.
+ *
  * @param bForce If FALSE statistics will only be returned if it can
- * be done without rescanning the image. 
+ * be done without rescanning the image.
  *
  * @param pdfMin Location into which to load image minimum (may be NULL).
  *
@@ -3657,15 +3457,15 @@ GDALRasterAdviseRead( GDALRasterBandH hBand,
  *
  * @param pdfMean Location into which to load image mean (may be NULL).
  *
- * @param pdfStdDev Location into which to load image standard deviation 
+ * @param pdfStdDev Location into which to load image standard deviation
  * (may be NULL).
  *
- * @return CE_None on success, CE_Warning if no values returned, 
+ * @return CE_None on success, CE_Warning if no values returned,
  * CE_Failure if an error occurs.
  */
 
 CPLErr GDALRasterBand::GetStatistics( int bApproxOK, int bForce,
-                                      double *pdfMin, double *pdfMax, 
+                                      double *pdfMin, double *pdfMax,
                                       double *pdfMean, double *pdfStdDev )
 
 {
@@ -3710,14 +3510,14 @@ CPLErr GDALRasterBand::GetStatistics( int bApproxOK, int bForce,
             return CE_None;
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Either return without results, or force computation.            */
 /* -------------------------------------------------------------------- */
     if( !bForce )
         return CE_Warning;
     else
-        return ComputeStatistics( bApproxOK, 
+        return ComputeStatistics( bApproxOK,
                                   pdfMin, pdfMax, pdfMean, pdfStdDev,
                                   GDALDummyProgress, NULL );
 }
@@ -3727,20 +3527,20 @@ CPLErr GDALRasterBand::GetStatistics( int bApproxOK, int bForce,
 /************************************************************************/
 
 /**
- * \brief Fetch image statistics. 
+ * \brief Fetch image statistics.
  *
  * @see GDALRasterBand::GetStatistics()
  */
 
-CPLErr CPL_STDCALL GDALGetRasterStatistics( 
-        GDALRasterBandH hBand, int bApproxOK, int bForce, 
+CPLErr CPL_STDCALL GDALGetRasterStatistics(
+        GDALRasterBandH hBand, int bApproxOK, int bForce,
         double *pdfMin, double *pdfMax, double *pdfMean, double *pdfStdDev )
 
 {
     VALIDATE_POINTER1( hBand, "GDALGetRasterStatistics", CE_Failure );
 
     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
-    return poBand->GetStatistics( 
+    return poBand->GetStatistics(
         bApproxOK, bForce, pdfMin, pdfMax, pdfMean, pdfStdDev );
 }
 
@@ -3749,28 +3549,28 @@ CPLErr CPL_STDCALL GDALGetRasterStatistics(
 /************************************************************************/
 
 /**
- * \brief Compute image statistics. 
+ * \brief Compute image statistics.
  *
  * Returns the minimum, maximum, mean and standard deviation of all
  * pixel values in this band.  If approximate statistics are sufficient,
  * the bApproxOK flag can be set to true in which case overviews, or a
- * subset of image tiles may be used in computing the statistics.  
+ * subset of image tiles may be used in computing the statistics.
  *
- * Once computed, the statistics will generally be "set" back on the 
- * raster band using SetStatistics(). 
+ * Once computed, the statistics will generally be "set" back on the
+ * raster band using SetStatistics().
  *
  * This method is the same as the C function GDALComputeRasterStatistics().
  *
  * @param bApproxOK If TRUE statistics may be computed based on overviews
- * or a subset of all tiles. 
- * 
+ * or a subset of all tiles.
+ *
  * @param pdfMin Location into which to load image minimum (may be NULL).
  *
  * @param pdfMax Location into which to load image maximum (may be NULL).-
  *
  * @param pdfMean Location into which to load image mean (may be NULL).
  *
- * @param pdfStdDev Location into which to load image standard deviation 
+ * @param pdfStdDev Location into which to load image standard deviation
  * (may be NULL).
  *
  * @param pfnProgress a function to call to report progress, or NULL.
@@ -3781,11 +3581,11 @@ CPLErr CPL_STDCALL GDALGetRasterStatistics(
  * is terminated by the user.
  */
 
-CPLErr 
+CPLErr
 GDALRasterBand::ComputeStatistics( int bApproxOK,
-                                   double *pdfMin, double *pdfMax, 
+                                   double *pdfMin, double *pdfMax,
                                    double *pdfMean, double *pdfStdDev,
-                                   GDALProgressFunc pfnProgress, 
+                                   GDALProgressFunc pfnProgress,
                                    void *pProgressData )
 
 {
@@ -3797,13 +3597,12 @@ GDALRasterBand::ComputeStatistics( int bApproxOK,
 /* -------------------------------------------------------------------- */
     if( bApproxOK && GetOverviewCount() > 0 && !HasArbitraryOverviews() )
     {
-        GDALRasterBand *poBand;
-
-        poBand = GetRasterSampleOverview( GDALSTAT_APPROX_NUMSAMPLES );
+        GDALRasterBand *poBand
+            = GetRasterSampleOverview( GDALSTAT_APPROX_NUMSAMPLES );
 
         if( poBand != this )
-            return poBand->ComputeStatistics( FALSE,  
-                                              pdfMin, pdfMax, 
+            return poBand->ComputeStatistics( FALSE,
+                                              pdfMin, pdfMax,
                                               pdfMean, pdfStdDev,
                                               pfnProgress, pProgressData );
     }
@@ -3812,7 +3611,7 @@ GDALRasterBand::ComputeStatistics( int bApproxOK,
 /*      Read actual data and compute statistics.                        */
 /* -------------------------------------------------------------------- */
     double      dfMin = 0.0, dfMax = 0.0;
-    int         bGotNoDataValue, bFirstValue = TRUE;
+    bool bFirstValue = true;
     /* Using Welford algorithm ( http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance ) */
     /* to compute standard deviation in a more numerically robust way than */
     /* the difference of the sum of square values with the square of the sum */
@@ -3830,6 +3629,7 @@ GDALRasterBand::ComputeStatistics( int bApproxOK,
         return CE_Failure;
     }
 
+    int bGotNoDataValue;
     const double dfNoDataValue = GetNoDataValue( &bGotNoDataValue );
     bGotNoDataValue = bGotNoDataValue && !CPLIsNan(dfNoDataValue);
 
@@ -3865,7 +3665,8 @@ GDALRasterBand::ComputeStatistics( int bApproxOK,
         }
 
         pData =
-            CPLMalloc(GDALGetDataTypeSize(eDataType)/8 * nXReduced * nYReduced);
+            CPLMalloc(
+                GDALGetDataTypeSizeBytes(eDataType) * nXReduced * nYReduced );
 
         CPLErr eErr = IRasterIO( GF_Read, 0, 0, nRasterXSize, nRasterYSize, pData,
                    nXReduced, nYReduced, eDataType, 0, 0, &sExtraArg );
@@ -3934,14 +3735,14 @@ GDALRasterBand::ComputeStatistics( int bApproxOK,
                   default:
                     CPLAssert( FALSE );
                 }
-                
+
                 if( bGotNoDataValue && ARE_REAL_EQUAL(dfValue, dfNoDataValue) )
                     continue;
 
                 if( bFirstValue )
                 {
                     dfMin = dfMax = dfValue;
-                    bFirstValue = FALSE;
+                    bFirstValue = false;
                 }
                 else
                 {
@@ -3961,8 +3762,6 @@ GDALRasterBand::ComputeStatistics( int bApproxOK,
 
     else    // No arbitrary overviews
     {
-        int     nSampleRate;
-        
         if( !InitBlockInfo() )
             return CE_Failure;
 
@@ -3970,15 +3769,21 @@ GDALRasterBand::ComputeStatistics( int bApproxOK,
 /*      Figure out the ratio of blocks we will read to get an           */
 /*      approximate value.                                              */
 /* -------------------------------------------------------------------- */
+        int nSampleRate;
         if ( bApproxOK )
         {
-            nSampleRate = 
+            nSampleRate =
                 (int)MAX( 1, sqrt((double)nBlocksPerRow * nBlocksPerColumn) );
+            // We want to avoid probing only the first column of blocks for
+            // a square shaped raster, because it is not unlikely that it may
+            // be padding only (#6378)
+            if( nSampleRate == nBlocksPerRow && nBlocksPerRow > 1 )
+              nSampleRate += 1;
         }
         else
             nSampleRate = 1;
 
-        for( int iSampleBlock = 0; 
+        for( int iSampleBlock = 0;
              iSampleBlock < nBlocksPerRow * nBlocksPerColumn;
              iSampleBlock += nSampleRate )
         {
@@ -3988,18 +3793,13 @@ GDALRasterBand::ComputeStatistics( int bApproxOK,
 
             iYBlock = iSampleBlock / nBlocksPerRow;
             iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
-            
+
             poBlock = GetLockedBlockRef( iXBlock, iYBlock );
             if( poBlock == NULL )
                 continue;
-            if( poBlock->GetDataRef() == NULL )
-            {
-                poBlock->DropLock();
-                continue;
-            }
-            
+
             pData = poBlock->GetDataRef();
-            
+
             if( (iXBlock+1) * nBlockXSize > GetXSize() )
                 nXCheck = GetXSize() - iXBlock * nBlockXSize;
             else
@@ -4076,7 +3876,7 @@ GDALRasterBand::ComputeStatistics( int bApproxOK,
                     if( bFirstValue )
                     {
                         dfMin = dfMax = dfValue;
-                        bFirstValue = FALSE;
+                        bFirstValue = false;
                     }
                     else
                     {
@@ -4112,7 +3912,7 @@ GDALRasterBand::ComputeStatistics( int bApproxOK,
 /* -------------------------------------------------------------------- */
 /*      Save computed information.                                      */
 /* -------------------------------------------------------------------- */
-    double dfStdDev = sqrt(dfM2 / nSampleCount);
+    const double dfStdDev = (nSampleCount > 0) ? sqrt(dfM2 / nSampleCount) : 0.0;
 
     if( nSampleCount > 0 )
         SetStatistics( dfMin, dfMax, dfMean, dfStdDev );
@@ -4146,13 +3946,13 @@ GDALRasterBand::ComputeStatistics( int bApproxOK,
 /************************************************************************/
 
 /**
-  * \brief Compute image statistics. 
+  * \brief Compute image statistics.
   *
   * @see GDALRasterBand::ComputeStatistics()
   */
 
-CPLErr CPL_STDCALL GDALComputeRasterStatistics( 
-        GDALRasterBandH hBand, int bApproxOK, 
+CPLErr CPL_STDCALL GDALComputeRasterStatistics(
+        GDALRasterBandH hBand, int bApproxOK,
         double *pdfMin, double *pdfMax, double *pdfMean, double *pdfStdDev,
         GDALProgressFunc pfnProgress, void *pProgressData )
 
@@ -4161,7 +3961,7 @@ CPLErr CPL_STDCALL GDALComputeRasterStatistics(
 
     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
 
-    return poBand->ComputeStatistics( 
+    return poBand->ComputeStatistics(
         bApproxOK, pdfMin, pdfMax, pdfMean, pdfStdDev,
         pfnProgress, pProgressData );
 }
@@ -4174,42 +3974,42 @@ CPLErr CPL_STDCALL GDALComputeRasterStatistics(
  * \brief Set statistics on band.
  *
  * This method can be used to store min/max/mean/standard deviation
- * statistics on a raster band.  
+ * statistics on a raster band.
  *
- * The default implementation stores them as metadata, and will only work 
+ * The default implementation stores them as metadata, and will only work
  * on formats that can save arbitrary metadata.  This method cannot detect
  * whether metadata will be properly saved and so may return CE_None even
  * if the statistics will never be saved.
  *
  * This method is the same as the C function GDALSetRasterStatistics().
- * 
+ *
  * @param dfMin minimum pixel value.
- * 
+ *
  * @param dfMax maximum pixel value.
  *
- * @param dfMean mean (average) of all pixel values.		
+ * @param dfMean mean (average) of all pixel values.
  *
  * @param dfStdDev Standard deviation of all pixel values.
  *
- * @return CE_None on success or CE_Failure on failure. 
+ * @return CE_None on success or CE_Failure on failure.
  */
 
-CPLErr GDALRasterBand::SetStatistics( double dfMin, double dfMax, 
+CPLErr GDALRasterBand::SetStatistics( double dfMin, double dfMax,
                                       double dfMean, double dfStdDev )
 
 {
     char szValue[128] = { 0 };
 
-    CPLsprintf( szValue, "%.14g", dfMin );
+    CPLsnprintf( szValue, sizeof(szValue), "%.14g", dfMin );
     SetMetadataItem( "STATISTICS_MINIMUM", szValue );
 
-    CPLsprintf( szValue, "%.14g", dfMax );
+    CPLsnprintf( szValue, sizeof(szValue), "%.14g", dfMax );
     SetMetadataItem( "STATISTICS_MAXIMUM", szValue );
 
-    CPLsprintf( szValue, "%.14g", dfMean );
+    CPLsnprintf( szValue, sizeof(szValue), "%.14g", dfMean );
     SetMetadataItem( "STATISTICS_MEAN", szValue );
 
-    CPLsprintf( szValue, "%.14g", dfStdDev );
+    CPLsnprintf( szValue, sizeof(szValue), "%.14g", dfStdDev );
     SetMetadataItem( "STATISTICS_STDDEV", szValue );
 
     return CE_None;
@@ -4225,8 +4025,8 @@ CPLErr GDALRasterBand::SetStatistics( double dfMin, double dfMax,
  * @see GDALRasterBand::SetStatistics()
  */
 
-CPLErr CPL_STDCALL GDALSetRasterStatistics( 
-        GDALRasterBandH hBand,  
+CPLErr CPL_STDCALL GDALSetRasterStatistics(
+        GDALRasterBandH hBand,
         double dfMin, double dfMax, double dfMean, double dfStdDev )
 
 {
@@ -4242,7 +4042,7 @@ CPLErr CPL_STDCALL GDALSetRasterStatistics(
 
 /**
  * \brief Compute the min/max values for a band.
- * 
+ *
  * If approximate is OK, then the band's GetMinimum()/GetMaximum() will
  * be trusted.  If it doesn't work, a subsample of blocks will be read to
  * get an approximate min/max.  If the band has a nodata value it will
@@ -4252,7 +4052,7 @@ CPLErr CPL_STDCALL GDALSetRasterStatistics(
  * an exact range.
  *
  * This method is the same as the C function GDALComputeRasterMinMax().
- * 
+ *
  * @param bApproxOK TRUE if an approximate (faster) answer is OK, otherwise
  * FALSE.
  * @param adfMinMax the array in which the minimum (adfMinMax[0]) and the
@@ -4285,7 +4085,7 @@ CPLErr GDALRasterBand::ComputeRasterMinMax( int bApproxOK,
             return CE_None;
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      If we have overview bands, use them for min/max.                */
 /* -------------------------------------------------------------------- */
@@ -4301,7 +4101,8 @@ CPLErr GDALRasterBand::ComputeRasterMinMax( int bApproxOK,
 /* -------------------------------------------------------------------- */
 /*      Read actual data and compute minimum and maximum.               */
 /* -------------------------------------------------------------------- */
-    int     bGotNoDataValue, bFirstValue = TRUE;
+    int bGotNoDataValue;
+    bool bFirstValue = true;
 
     const double dfNoDataValue = GetNoDataValue( &bGotNoDataValue );
     bGotNoDataValue = bGotNoDataValue && !CPLIsNan(dfNoDataValue);
@@ -4341,7 +4142,8 @@ CPLErr GDALRasterBand::ComputeRasterMinMax( int bApproxOK,
         }
 
         pData =
-            CPLMalloc(GDALGetDataTypeSize(eDataType)/8 * nXReduced * nYReduced);
+            CPLMalloc(
+                GDALGetDataTypeSizeBytes(eDataType) * nXReduced * nYReduced );
 
         CPLErr eErr = IRasterIO( GF_Read, 0, 0, nRasterXSize, nRasterYSize, pData,
                    nXReduced, nYReduced, eDataType, 0, 0, &sExtraArg );
@@ -4350,7 +4152,7 @@ CPLErr GDALRasterBand::ComputeRasterMinMax( int bApproxOK,
             CPLFree(pData);
             return eErr;
         }
-        
+
         /* this isn't the fastest way to do this, but is easier for now */
         for( int iY = 0; iY < nYReduced; iY++ )
         {
@@ -4410,14 +4212,14 @@ CPLErr GDALRasterBand::ComputeRasterMinMax( int bApproxOK,
                   default:
                     CPLAssert( FALSE );
                 }
-                
+
                 if( bGotNoDataValue && ARE_REAL_EQUAL(dfValue, dfNoDataValue) )
                     continue;
 
                 if( bFirstValue )
                 {
                     dfMin = dfMax = dfValue;
-                    bFirstValue = FALSE;
+                    bFirstValue = false;
                 }
                 else
                 {
@@ -4432,8 +4234,6 @@ CPLErr GDALRasterBand::ComputeRasterMinMax( int bApproxOK,
 
     else    // No arbitrary overviews
     {
-        int     nSampleRate;
-
         if( !InitBlockInfo() )
             return CE_Failure;
 
@@ -4441,36 +4241,35 @@ CPLErr GDALRasterBand::ComputeRasterMinMax( int bApproxOK,
 /*      Figure out the ratio of blocks we will read to get an           */
 /*      approximate value.                                              */
 /* -------------------------------------------------------------------- */
+        int nSampleRate;
+
         if ( bApproxOK )
         {
-            nSampleRate = 
+            nSampleRate =
                 (int) MAX(1,sqrt((double) nBlocksPerRow * nBlocksPerColumn));
+            // We want to avoid probing only the first column of blocks for
+            // a square shaped raster, because it is not unlikely that it may
+            // be padding only (#6378)
+            if( nSampleRate == nBlocksPerRow && nBlocksPerRow > 1 )
+              nSampleRate += 1;
         }
         else
             nSampleRate = 1;
-        
-        for( int iSampleBlock = 0; 
+
+        for( int iSampleBlock = 0;
              iSampleBlock < nBlocksPerRow * nBlocksPerColumn;
              iSampleBlock += nSampleRate )
         {
-            int  iXBlock, iYBlock, nXCheck, nYCheck;
-            GDALRasterBlock *poBlock;
-            void* pData;
+            int iYBlock = iSampleBlock / nBlocksPerRow;
+            int iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
 
-            iYBlock = iSampleBlock / nBlocksPerRow;
-            iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
-            
-            poBlock = GetLockedBlockRef( iXBlock, iYBlock );
+            GDALRasterBlock *poBlock = GetLockedBlockRef( iXBlock, iYBlock );
             if( poBlock == NULL )
                 continue;
-            if( poBlock->GetDataRef() == NULL )
-            {
-                poBlock->DropLock();
-                continue;
-            }
-            
-            pData = poBlock->GetDataRef();
-            
+
+            void *pData = poBlock->GetDataRef();
+
+            int nXCheck, nYCheck;
             if( (iXBlock+1) * nBlockXSize > GetXSize() )
                 nXCheck = GetXSize() - iXBlock * nBlockXSize;
             else
@@ -4480,7 +4279,7 @@ CPLErr GDALRasterBand::ComputeRasterMinMax( int bApproxOK,
                 nYCheck = GetYSize() - iYBlock * nBlockYSize;
             else
                 nYCheck = nBlockYSize;
-                
+
             /* this isn't the fastest way to do this, but is easier for now */
             for( int iY = 0; iY < nYCheck; iY++ )
             {
@@ -4540,14 +4339,14 @@ CPLErr GDALRasterBand::ComputeRasterMinMax( int bApproxOK,
                       default:
                         CPLAssert( FALSE );
                     }
-                    
+
                     if( bGotNoDataValue && ARE_REAL_EQUAL(dfValue, dfNoDataValue) )
                         continue;
 
                     if( bFirstValue )
                     {
                         dfMin = dfMax = dfValue;
-                        bFirstValue = FALSE;
+                        bFirstValue = false;
                     }
                     else
                     {
@@ -4582,12 +4381,12 @@ CPLErr GDALRasterBand::ComputeRasterMinMax( int bApproxOK,
 
 /**
  * \brief Compute the min/max values for a band.
- * 
+ *
  * @see GDALRasterBand::ComputeRasterMinMax()
  */
 
-void CPL_STDCALL 
-GDALComputeRasterMinMax( GDALRasterBandH hBand, int bApproxOK, 
+void CPL_STDCALL
+GDALComputeRasterMinMax( GDALRasterBandH hBand, int bApproxOK,
                          double adfMinMax[2] )
 
 {
@@ -4635,15 +4434,15 @@ CPLErr GDALRasterBand::SetDefaultHistogram( CPL_UNUSED double dfMin,
  * @see GDALSetRasterHistogramEx()
  */
 
-CPLErr CPL_STDCALL GDALSetDefaultHistogram( GDALRasterBandH hBand, 
-                                            double dfMin, double dfMax, 
+CPLErr CPL_STDCALL GDALSetDefaultHistogram( GDALRasterBandH hBand,
+                                            double dfMin, double dfMax,
                                             int nBuckets, int *panHistogram )
 
 {
     VALIDATE_POINTER1( hBand, "GDALSetDefaultHistogram", CE_Failure );
 
     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
-    
+
     GUIntBig* panHistogramTemp = (GUIntBig*) VSIMalloc2(sizeof(GUIntBig), nBuckets);
     if( panHistogramTemp == NULL )
     {
@@ -4656,11 +4455,11 @@ CPLErr CPL_STDCALL GDALSetDefaultHistogram( GDALRasterBandH hBand,
     {
         panHistogramTemp[i] = (GUIntBig)panHistogram[i];
     }
-    
+
     CPLErr eErr = poBand->SetDefaultHistogram( dfMin, dfMax, nBuckets, panHistogramTemp );
-    
+
     CPLFree(panHistogramTemp);
-    
+
     return eErr;
 }
 
@@ -4676,8 +4475,8 @@ CPLErr CPL_STDCALL GDALSetDefaultHistogram( GDALRasterBandH hBand,
  * @since GDAL 2.0
  */
 
-CPLErr CPL_STDCALL GDALSetDefaultHistogramEx( GDALRasterBandH hBand, 
-                                            double dfMin, double dfMax, 
+CPLErr CPL_STDCALL GDALSetDefaultHistogramEx( GDALRasterBandH hBand,
+                                            double dfMin, double dfMax,
                                             int nBuckets, GUIntBig *panHistogram )
 
 {
@@ -4696,7 +4495,7 @@ CPLErr CPL_STDCALL GDALSetDefaultHistogramEx( GDALRasterBandH hBand,
  *
  * A RAT will be returned if there is a default one associated with the
  * band, otherwise NULL is returned.  The returned RAT is owned by the
- * band and should not be deleted by the application. 
+ * band and should not be deleted by the application.
  *
  * This method is the same as the C function GDALGetDefaultRAT().
  *
@@ -4774,7 +4573,7 @@ CPLErr CPL_STDCALL GDALSetDefaultRAT( GDALRasterBandH hBand,
 
     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
 
-    return poBand->SetDefaultRAT( 
+    return poBand->SetDefaultRAT(
         static_cast<GDALRasterAttributeTable *>(hRAT) );
 }
 
@@ -4825,8 +4624,6 @@ GDALRasterBand *GDALRasterBand::GetMaskBand()
 /* -------------------------------------------------------------------- */
 /*      Check for a mask in a .msk file.                                */
 /* -------------------------------------------------------------------- */
-    GDALDataset *poDS = GetDataset();
-
     if( poDS != NULL && poDS->oOvManager.HaveMaskFile() )
     {
         poMask = poDS->oOvManager.GetMaskBand( nBand );
@@ -4845,14 +4642,16 @@ GDALRasterBand *GDALRasterBand::GetMaskBand()
         const char* pszNoDataValues = poDS->GetMetadataItem("NODATA_VALUES");
         if (pszNoDataValues != NULL)
         {
-            char** papszNoDataValues = CSLTokenizeStringComplex(pszNoDataValues, " ", FALSE, FALSE);
+            char** papszNoDataValues
+                = CSLTokenizeStringComplex(pszNoDataValues, " ", FALSE, FALSE);
 
             /* Make sure we have as many values as bands */
-            if (CSLCount(papszNoDataValues) == poDS->GetRasterCount() && poDS->GetRasterCount() != 0)
+            if (CSLCount(papszNoDataValues) == poDS->GetRasterCount()
+                && poDS->GetRasterCount() != 0)
             {
-                /* Make sure that all bands have the same data type */
-                /* This is cleraly not a fundamental condition, just a condition to make implementation */
-                /* easier. */
+                // Make sure that all bands have the same data type
+                // This is clearly not a fundamental condition, just a
+                // condition to make implementation easier.
                 int i;
                 GDALDataType eDT = GDT_Unknown;
                 for(i=0;i<poDS->GetRasterCount();i++)
@@ -4867,7 +4666,15 @@ GDALRasterBand *GDALRasterBand::GetMaskBand()
                 if (i == poDS->GetRasterCount())
                 {
                     nMaskFlags = GMF_NODATA | GMF_PER_DATASET;
-                    poMask = new GDALNoDataValuesMaskBand ( poDS );
+                    try
+                    {
+                        poMask = new GDALNoDataValuesMaskBand ( poDS );
+                    }
+                    catch( const std::bad_alloc& )
+                    {
+                        CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
+                        poMask = NULL;
+                    }
                     bOwnMask = true;
                     CSLDestroy(papszNoDataValues);
                     return poMask;
@@ -4875,7 +4682,9 @@ GDALRasterBand *GDALRasterBand::GetMaskBand()
                 else
                 {
                     ReportError(CE_Warning, CPLE_AppDefined,
-                            "All bands should have the same type in order the NODATA_VALUES metadata item to be used as a mask.");
+                                "All bands should have the same type in "
+                                "order the NODATA_VALUES metadata item "
+                                "to be used as a mask.");
                 }
             }
             else
@@ -4895,11 +4704,19 @@ GDALRasterBand *GDALRasterBand::GetMaskBand()
     int bHaveNoData;
 
     GetNoDataValue( &bHaveNoData );
-    
+
     if( bHaveNoData )
     {
         nMaskFlags = GMF_NODATA;
-        poMask = new GDALNoDataMaskBand( this );
+        try
+        {
+            poMask = new GDALNoDataMaskBand( this );
+        }
+        catch( const std::bad_alloc& )
+        {
+            CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
+            poMask = NULL;
+        }
         bOwnMask = true;
         return poMask;
     }
@@ -4907,7 +4724,7 @@ GDALRasterBand *GDALRasterBand::GetMaskBand()
 /* -------------------------------------------------------------------- */
 /*      Check for alpha case.                                           */
 /* -------------------------------------------------------------------- */
-    if( poDS != NULL 
+    if( poDS != NULL
         && poDS->GetRasterCount() == 2
         && this == poDS->GetRasterBand(1)
         && poDS->GetRasterBand(2)->GetColorInterpretation() == GCI_AlphaBand
@@ -4918,7 +4735,7 @@ GDALRasterBand *GDALRasterBand::GetMaskBand()
         return poMask;
     }
 
-    if( poDS != NULL 
+    if( poDS != NULL
         && poDS->GetRasterCount() == 4
         && (this == poDS->GetRasterBand(1)
             || this == poDS->GetRasterBand(2)
@@ -4934,7 +4751,15 @@ GDALRasterBand *GDALRasterBand::GetMaskBand()
         else if( poDS->GetRasterBand(4)->GetRasterDataType() == GDT_UInt16 )
         {
             nMaskFlags = GMF_ALPHA | GMF_PER_DATASET;
-            poMask = new GDALRescaledAlphaBand( poDS->GetRasterBand(4) );
+            try
+            {
+                poMask = new GDALRescaledAlphaBand( poDS->GetRasterBand(4) );
+            }
+            catch( const std::bad_alloc& )
+            {
+                CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
+                poMask = NULL;
+            }
             bOwnMask = true;
             return poMask;
         }
@@ -4944,7 +4769,15 @@ GDALRasterBand *GDALRasterBand::GetMaskBand()
 /*      Fallback to all valid case.                                     */
 /* -------------------------------------------------------------------- */
     nMaskFlags = GMF_ALL_VALID;
-    poMask = new GDALAllValidMaskBand( this );
+    try
+    {
+        poMask = new GDALAllValidMaskBand( this );
+    }
+    catch( const std::bad_alloc& )
+    {
+        CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
+        poMask = NULL;
+    }
     bOwnMask = true;
 
     return poMask;
@@ -5089,12 +4922,12 @@ void GDALRasterBand::InvalidateMaskBand()
  *
  */
 
-CPLErr GDALRasterBand::CreateMaskBand( int nFlags )
+CPLErr GDALRasterBand::CreateMaskBand( int nFlagsIn )
 
 {
     if( poDS != NULL && poDS->oOvManager.IsInitialized() )
     {
-        CPLErr eErr = poDS->oOvManager.CreateMaskBand( nFlags, nBand );
+        CPLErr eErr = poDS->oOvManager.CreateMaskBand( nFlagsIn, nBand );
         if (eErr != CE_None)
             return eErr;
 
@@ -5105,7 +4938,7 @@ CPLErr GDALRasterBand::CreateMaskBand( int nFlags )
 
     ReportError( CE_Failure, CPLE_NotSupported,
               "CreateMaskBand() not supported for this band." );
-    
+
     return CE_Failure;
 }
 
@@ -5178,9 +5011,11 @@ unsigned char* GDALRasterBand::GetIndexColorTranslationTo(GDALRasterBand* poRefe
             int nEntries = srcColorTable->GetColorEntryCount();
             int nRefEntries = destColorTable->GetColorEntryCount();
             int bHasNoDataValueSrc;
-            int noDataValueSrc = (int)GetNoDataValue(&bHasNoDataValueSrc);
+            double dfNoDataValueSrc = GetNoDataValue(&bHasNoDataValueSrc);
+            int noDataValueSrc = (bHasNoDataValueSrc) ? (int)dfNoDataValueSrc : 0;
             int bHasNoDataValueRef;
-            int noDataValueRef = (int)poReferenceBand->GetNoDataValue(&bHasNoDataValueRef);
+            double dfNoDataValueRef = poReferenceBand->GetNoDataValue(&bHasNoDataValueRef);
+            int noDataValueRef = (bHasNoDataValueRef) ? (int)dfNoDataValueRef : 0;
             int samePalette;
             int i, j;
 
@@ -5270,9 +5105,9 @@ unsigned char* GDALRasterBand::GetIndexColorTranslationTo(GDALRasterBand* poRefe
 /************************************************************************/
 
 /**
- * \brief Store that an error occured while writing a dirty block.
+ * \brief Store that an error occurred while writing a dirty block.
  *
- * This function stores the fact that an error occured while writing a dirty
+ * This function stores the fact that an error occurred while writing a dirty
  * block from GDALRasterBlock::FlushCacheBlock(). Indeed when dirty blocks are
  * flushed when the block cache get full, it is not convenient/possible to
  * report that a dirty block could not be written correctly. This function
@@ -5306,7 +5141,7 @@ void GDALRasterBand::SetFlushBlockErr( CPLErr eErr )
  * @since GDAL 1.9.0
  */
 
-void GDALRasterBand::ReportError(CPLErr eErrClass, int err_no, const char *fmt, ...)
+void GDALRasterBand::ReportError(CPLErr eErrClass, CPLErrorNum err_no, const char *fmt, ...)
 {
     va_list args;
 
@@ -5396,7 +5231,7 @@ CPLVirtualMem  *GDALRasterBand::GetVirtualMemAuto( GDALRWFlag eRWFlag,
                                                    GIntBig *pnLineSpace,
                                                    char **papszOptions )
 {
-    int nPixelSpace = GDALGetDataTypeSize(eDataType) / 8;
+    const int nPixelSpace = GDALGetDataTypeSizeBytes(eDataType);
     GIntBig nLineSpace = (GIntBig)nRasterXSize * nPixelSpace;
     if( pnPixelSpace )
         *pnPixelSpace = nPixelSpace;
@@ -5406,7 +5241,7 @@ CPLVirtualMem  *GDALRasterBand::GetVirtualMemAuto( GDALRWFlag eRWFlag,
                                             "CACHE_SIZE", "40000000"));
     size_t nPageSizeHint = atoi(CSLFetchNameValueDef(papszOptions,
                                             "PAGE_SIZE_HINT", "0"));
-    int bSingleThreadUsage = CSLTestBoolean(CSLFetchNameValueDef(papszOptions,
+    int bSingleThreadUsage = CPLTestBool(CSLFetchNameValueDef(papszOptions,
                                             "SINGLE_THREAD", "FALSE"));
     return GDALRasterBandGetVirtualMem( (GDALRasterBandH) this,
                                         eRWFlag,
diff --git a/gcore/gdalrasterblock.cpp b/gcore/gdalrasterblock.cpp
index 33f1d86..ced14d7 100644
--- a/gcore/gdalrasterblock.cpp
+++ b/gcore/gdalrasterblock.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: gdalrasterblock.cpp 31657 2015-11-20 13:14:23Z rouault $
+ * $Id: gdalrasterblock.cpp 33694 2016-03-10 17:54:30Z goatbar $
  *
  * Project:  GDAL Core
- * Purpose:  Implementation of GDALRasterBlock class and related global 
+ * Purpose:  Implementation of GDALRasterBlock class and related global
  *           raster block cache management.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -32,10 +32,10 @@
 #include "gdal_priv.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: gdalrasterblock.cpp 31657 2015-11-20 13:14:23Z rouault $");
+CPL_CVSID("$Id: gdalrasterblock.cpp 33694 2016-03-10 17:54:30Z goatbar $");
 
-static int bCacheMaxInitialized = FALSE;
-static GIntBig nCacheMax = 40 * 1024*1024;
+static bool bCacheMaxInitialized = false;
+static GIntBig nCacheMax = 40 * 1024*1024; /* Will later be overridden by the default 5% if GDAL_CACHEMAX not defined */
 static volatile GIntBig nCacheUsed = 0;
 
 static GDALRasterBlock *poOldest = NULL;    /* tail */
@@ -50,6 +50,7 @@ static CPLMutex *hRBLock = NULL;
 
 static CPLLock* hRBLock = NULL;
 static int bDebugContention = FALSE;
+static bool bSleepsForBockCacheDebug = false;
 static CPLLockType GetLockType()
 {
     static int nLockType = -1;
@@ -69,7 +70,7 @@ static CPLLockType GetLockType()
                      pszLockType);
             nLockType = LOCK_ADAPTIVE_MUTEX;
         }
-        bDebugContention = CSLTestBoolean(CPLGetConfigOption("GDAL_RB_LOCK_DEBUG_CONTENTION", "NO"));
+        bDebugContention = CPLTestBool(CPLGetConfigOption("GDAL_RB_LOCK_DEBUG_CONTENTION", "NO"));
     }
     return (CPLLockType) nLockType;
 }
@@ -129,7 +130,15 @@ void CPL_STDCALL GDALSetCacheMax( int nNewSizeInBytes )
 void CPL_STDCALL GDALSetCacheMax64( GIntBig nNewSizeInBytes )
 
 {
-    bCacheMaxInitialized = TRUE;
+#if 0
+    if( nNewSizeInBytes == 12346789 )
+    {
+        GDALRasterBlock::DumpAll();
+        return;
+    }
+#endif
+
+    bCacheMaxInitialized = true;
     nCacheMax = nNewSizeInBytes;
 
 /* -------------------------------------------------------------------- */
@@ -158,12 +167,15 @@ void CPL_STDCALL GDALSetCacheMax64( GIntBig nNewSizeInBytes )
  * caching system for caching GDAL read/write imagery.
  *
  * The first type this function is called, it will read the GDAL_CACHEMAX
- * configuation option to initialize the maximum cache memory.
+ * configuration option to initialize the maximum cache memory.
+ * Starting with GDAL 2.1, the value can be expressed as x% of the usable
+ * physical RAM (which may potentially be used by other processes). Otherwise
+ * it is expected to be a value in MB.
  *
  * This function cannot return a value higher than 2 GB. Use
  * GDALGetCacheMax64() to get a non-truncated value.
  *
- * @return maximum in bytes. 
+ * @return maximum in bytes.
  */
 
 int CPL_STDCALL GDALGetCacheMax()
@@ -171,13 +183,13 @@ int CPL_STDCALL GDALGetCacheMax()
     GIntBig nRes = GDALGetCacheMax64();
     if (nRes > INT_MAX)
     {
-        static int bHasWarned = FALSE;
+        static bool bHasWarned = false;
         if (!bHasWarned)
         {
             CPLError(CE_Warning, CPLE_AppDefined,
                      "Cache max value doesn't fit on a 32 bit integer. "
                      "Call GDALGetCacheMax64() instead");
-            bHasWarned = TRUE;
+            bHasWarned = true;
         }
         nRes = INT_MAX;
     }
@@ -195,7 +207,10 @@ int CPL_STDCALL GDALGetCacheMax()
  * caching system for caching GDAL read/write imagery.
  *
  * The first type this function is called, it will read the GDAL_CACHEMAX
- * configuation option to initialize the maximum cache memory.
+ * configuration option to initialize the maximum cache memory.
+ * Starting with GDAL 2.1, the value can be expressed as x% of the usable
+ * physical RAM (which may potentially be used by other processes). Otherwise
+ * it is expected to be a value in MB.
  *
  * @return maximum in bytes.
  *
@@ -209,25 +224,52 @@ GIntBig CPL_STDCALL GDALGetCacheMax64()
         {
             INITIALIZE_LOCK;
         }
-        const char* pszCacheMax = CPLGetConfigOption("GDAL_CACHEMAX",NULL);
-        bCacheMaxInitialized = TRUE;
-        if( pszCacheMax != NULL )
+        bSleepsForBockCacheDebug = CPLTestBool(CPLGetConfigOption("GDAL_DEBUG_BLOCK_CACHE", "NO"));
+
+        const char* pszCacheMax = CPLGetConfigOption("GDAL_CACHEMAX","5%");
+
+        GIntBig nNewCacheMax;
+        if( strchr(pszCacheMax, '%') != NULL )
+        {
+            GIntBig nUsagePhysicalRAM = CPLGetUsablePhysicalRAM();
+            // For some reason, coverity pretends that this will overflow...
+            // "Multiply operation overflows on operands static_cast<double>(nUsagePhysicalRAM)
+            // and CPLAtof(pszCacheMax). Example values for operands: CPLAtof(pszCacheMax) = 2251799813685248,
+            // static_cast<double>(nUsagePhysicalRAM) = -9223372036854775808."
+            /* coverity[overflow] */
+            double dfCacheMax = static_cast<double>(nUsagePhysicalRAM) * CPLAtof(pszCacheMax) / 100.0;
+            if( dfCacheMax >= 0 && dfCacheMax < 1e15 )
+                nNewCacheMax = static_cast<GIntBig>(dfCacheMax);
+            else
+                nNewCacheMax = nCacheMax;
+        }
+        else
         {
-            GIntBig nNewCacheMax = (GIntBig)CPLScanUIntBig(pszCacheMax, strlen(pszCacheMax));
+            nNewCacheMax = CPLAtoGIntBig(pszCacheMax);
             if( nNewCacheMax < 100000 )
             {
                 if (nNewCacheMax < 0)
                 {
                     CPLError(CE_Failure, CPLE_NotSupported,
-                             "Invalid value for GDAL_CACHEMAX. Using default value.");
-                    return nCacheMax;
+                                "Invalid value for GDAL_CACHEMAX. Using default value.");
+                    GIntBig nUsagePhysicalRAM = CPLGetUsablePhysicalRAM();
+                    if( nUsagePhysicalRAM )
+                        nNewCacheMax = nUsagePhysicalRAM / 20;
+                    else
+                        nNewCacheMax = nCacheMax;
+                }
+                else
+                {
+                    nNewCacheMax *= 1024 * 1024;
                 }
-                nNewCacheMax *= 1024 * 1024;
             }
-            nCacheMax = nNewCacheMax;
         }
+        nCacheMax = nNewCacheMax;
+        CPLDebug("GDAL", "GDAL_CACHEMAX = " CPL_FRMT_GIB " MB",
+                 nCacheMax / (1024 * 1024));
+        bCacheMaxInitialized = true;
     }
-
+    /* coverity[overflow_sink] */
     return nCacheMax;
 }
 
@@ -238,7 +280,7 @@ GIntBig CPL_STDCALL GDALGetCacheMax64()
 /**
  * \brief Get cache memory used.
  *
- * @return the number of bytes of memory currently in use by the 
+ * @return the number of bytes of memory currently in use by the
  * GDALRasterBlock memory caching.
  */
 
@@ -246,13 +288,13 @@ int CPL_STDCALL GDALGetCacheUsed()
 {
     if (nCacheUsed > INT_MAX)
     {
-        static int bHasWarned = FALSE;
+        static bool bHasWarned = false;
         if (!bHasWarned)
         {
             CPLError(CE_Warning, CPLE_AppDefined,
                      "Cache used value doesn't fit on a 32 bit integer. "
                      "Call GDALGetCacheUsed64() instead");
-            bHasWarned = TRUE;
+            bHasWarned = true;
         }
         return INT_MAX;
     }
@@ -312,16 +354,16 @@ int CPL_STDCALL GDALFlushCacheBlock()
  * some blocks of raster data for zero or more GDALRasterBand objects
  * across zero or more GDALDataset objects in a global raster cache with
  * a least recently used (LRU) list and an upper cache limit (see
- * GDALSetCacheMax()) under which the cache size is normally kept. 
+ * GDALSetCacheMax()) under which the cache size is normally kept.
  *
  * Some blocks in the cache may be modified relative to the state on disk
  * (they are marked "Dirty") and must be flushed to disk before they can
  * be discarded.  Other (Clean) blocks may just be discarded if their memory
- * needs to be recovered. 
+ * needs to be recovered.
  *
  * In normal situations applications do not interact directly with the
  * GDALRasterBlock - instead it it utilized by the RasterIO() interfaces
- * to implement caching. 
+ * to implement caching.
  *
  * Some driver classes are implemented in a fashion that completely avoids
  * use of the GDAL raster cache (and GDALRasterBlock) though this is not very
@@ -331,7 +373,7 @@ int CPL_STDCALL GDALFlushCacheBlock()
 /************************************************************************/
 /*                          FlushCacheBlock()                           */
 /*                                                                      */
-/*      Note, if we have alot of blocks locked for a long time, this    */
+/*      Note, if we have a lot of blocks locked for a long time, this    */
 /*      method is going to get slow because it will have to traverse    */
 /*      the linked list a long ways looking for a flushing              */
 /*      candidate.   It might help to re-touch locked blocks to push    */
@@ -343,10 +385,10 @@ int CPL_STDCALL GDALFlushCacheBlock()
  *
  * This static method is normally used to recover memory when a request
  * for a new cache block would put cache memory use over the established
- * limit.   
+ * limit.
  *
  * C++ analog to the C function GDALFlushCacheBlock().
- * 
+ *
  * @param bDirtyBlocksOnly Only flushes dirty blocks.
  * @return TRUE if successful or FALSE if no flushable block is found.
  */
@@ -360,17 +402,28 @@ int GDALRasterBlock::FlushCacheBlock(int bDirtyBlocksOnly)
         INITIALIZE_LOCK;
         poTarget = poOldest;
 
-        while( poTarget != NULL && (poTarget->GetLockCount() > 0 ||
-               (bDirtyBlocksOnly && !poTarget->GetDirty())) )
+        while( poTarget != NULL )
+        {
+            if( !bDirtyBlocksOnly || poTarget->GetDirty() )
+            {
+                if( CPLAtomicCompareAndExchange(&(poTarget->nLockCount), 0, -1) )
+                    break;
+            }
             poTarget = poTarget->poPrevious;
-        
+        }
+
         if( poTarget == NULL )
             return FALSE;
+        if( bSleepsForBockCacheDebug )
+            CPLSleep(CPLAtof(CPLGetConfigOption("GDAL_RB_FLUSHBLOCK_SLEEP_AFTER_DROP_LOCK", "0")));
 
         poTarget->Detach_unlocked();
-        poTarget->GetBand()->UnreferenceBlock(poTarget->GetXOff(),poTarget->GetYOff());
+        poTarget->GetBand()->UnreferenceBlock(poTarget);
     }
 
+    if( bSleepsForBockCacheDebug )
+        CPLSleep(CPLAtof(CPLGetConfigOption("GDAL_RB_FLUSHBLOCK_SLEEP_AFTER_RB_LOCK", "0")));
+
     if( poTarget->GetDirty() )
     {
         CPLErr eErr = poTarget->Write();
@@ -380,7 +433,10 @@ int GDALRasterBlock::FlushCacheBlock(int bDirtyBlocksOnly)
             poTarget->GetBand()->SetFlushBlockErr(eErr);
         }
     }
-    delete poTarget;
+
+    VSIFree(poTarget->pData);
+    poTarget->pData = NULL;
+    poTarget->GetBand()->AddBlockToFreeList(poTarget);
 
     return TRUE;
 }
@@ -396,7 +452,7 @@ int GDALRasterBlock::FlushCacheBlock(int bDirtyBlocksOnly)
  * useful when doing multi-threaded code that can trigger the block cache.
  *
  * Due to the current design of the block cache, dirty blocks belonging to a same
- * dataset could be pushed simultanously to the IWriteBlock() method of that
+ * dataset could be pushed simultaneously to the IWriteBlock() method of that
  * dataset from different threads, causing races.
  *
  * Calling this method before that code can help workarounding that issue,
@@ -419,7 +475,7 @@ void GDALRasterBlock::FlushDirtyBlocks()
 /************************************************************************/
 
 /**
- * @brief GDALRasterBlock Constructor 
+ * @brief GDALRasterBlock Constructor
  *
  * Normally only called from GDALRasterBand::GetLockedBlockRef().
  *
@@ -427,20 +483,18 @@ void GDALRasterBlock::FlushDirtyBlocks()
  * being constructed.
  *
  * @param nXOffIn the horizontal block offset, with zero indicating
- * the left most block, 1 the next block and so forth. 
+ * the left most block, 1 the next block and so forth.
  *
  * @param nYOffIn the vertical block offset, with zero indicating
  * the top most block, 1 the next block and so forth.
  */
 
-GDALRasterBlock::GDALRasterBlock( GDALRasterBand *poBandIn, 
+GDALRasterBlock::GDALRasterBlock( GDALRasterBand *poBandIn,
                                   int nXOffIn, int nYOffIn )
 
 {
-    CPLAssert( NULL != poBandIn );
-
+    CPLAssert( poBandIn != NULL );
     poBand = poBandIn;
-
     poBand->GetBlockSize( &nXSize, &nYSize );
     eType = poBand->GetRasterDataType();
     pData = NULL;
@@ -455,11 +509,70 @@ GDALRasterBlock::GDALRasterBlock( GDALRasterBand *poBandIn,
 }
 
 /************************************************************************/
+/*                          GDALRasterBlock()                           */
+/************************************************************************/
+
+/**
+ * @brief GDALRasterBlock Constructor (for GDALHashSetBandBlockAccess purpose)
+ *
+ * Normally only called from GDALHashSetBandBlockAccess class. Such a block
+ * is completely non functional and only meant as being used to do a look-up
+ * in the hash set of GDALHashSetBandBlockAccess
+ *
+ * @param nXOffIn the horizontal block offset, with zero indicating
+ * the left most block, 1 the next block and so forth.
+ *
+ * @param nYOffIn the vertical block offset, with zero indicating
+ * the top most block, 1 the next block and so forth.
+ */
+
+GDALRasterBlock::GDALRasterBlock( int nXOffIn, int nYOffIn )
+
+{
+    poBand = NULL;
+    nXSize = nYSize = 0;
+    eType = GDT_Unknown;
+    pData = NULL;
+    bDirty = FALSE;
+    nLockCount = 0;
+
+    poNext = poPrevious = NULL;
+
+    nXOff = nXOffIn;
+    nYOff = nYOffIn;
+    bMustDetach = FALSE;
+}
+
+/************************************************************************/
+/*                                  RecycleFor()                        */
+/************************************************************************/
+
+/**
+ * Recycle an existing block (of the same band)
+ *
+ * Normally called from GDALAbstractBandBlockCache::CreateBlock().
+ */
+
+void GDALRasterBlock::RecycleFor( int nXOffIn, int nYOffIn )
+{
+    CPLAssert(pData == NULL);
+    pData = NULL;
+    bDirty = FALSE;
+    nLockCount = 0;
+
+    poNext = poPrevious = NULL;
+
+    nXOff = nXOffIn;
+    nYOff = nYOffIn;
+    bMustDetach = TRUE;
+}
+
+/************************************************************************/
 /*                          ~GDALRasterBlock()                          */
 /************************************************************************/
 
 /**
- * Block destructor. 
+ * Block destructor.
  *
  * Normally called from GDALRasterBand::FlushBlock().
  */
@@ -474,7 +587,7 @@ GDALRasterBlock::~GDALRasterBlock()
         VSIFree( pData );
     }
 
-    CPLAssert( nLockCount == 0 );
+    CPLAssert( nLockCount <= 0 );
 
 #ifdef ENABLE_DEBUG
     Verify();
@@ -538,9 +651,10 @@ void GDALRasterBlock::Detach_unlocked()
 
 /**
  * Confirms (via assertions) that the block cache linked list is in a
- * consistent state. 
+ * consistent state.
  */
 
+#ifdef ENABLE_DEBUG
 void GDALRasterBlock::Verify()
 
 {
@@ -553,9 +667,9 @@ void GDALRasterBlock::Verify()
     {
         CPLAssert( poNewest->poPrevious == NULL );
         CPLAssert( poOldest->poNext == NULL );
-        
+
         GDALRasterBlock* poLast = NULL;
-        for( GDALRasterBlock *poBlock = poNewest; 
+        for( GDALRasterBlock *poBlock = poNewest;
              poBlock != NULL;
              poBlock = poBlock->poNext )
         {
@@ -568,6 +682,36 @@ void GDALRasterBlock::Verify()
     }
 }
 
+#else
+void GDALRasterBlock::Verify() {}
+#endif
+
+#if 0
+void GDALRasterBlock::CheckNonOrphanedBlocks(GDALRasterBand* poBand)
+{
+    TAKE_LOCK;
+    for( GDALRasterBlock *poBlock = poNewest;
+                          poBlock != NULL;
+                          poBlock = poBlock->poNext )
+    {
+        if ( poBlock->GetBand() == poBand )
+        {
+            printf("Cache has still blocks of band %p\n", poBand);
+            printf("Band : %d\n", poBand->GetBand());
+            printf("nRasterXSize = %d\n", poBand->GetXSize());
+            printf("nRasterYSize = %d\n", poBand->GetYSize());
+            int nBlockXSize, nBlockYSize;
+            poBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
+            printf("nBlockXSize = %d\n", nBlockXSize);
+            printf("nBlockYSize = %d\n", nBlockYSize);
+            printf("Dataset : %p\n", poBand->GetDataset());
+            if( poBand->GetDataset() )
+                printf("Dataset : %s\n", poBand->GetDataset()->GetDescription());
+        }
+    }
+}
+#endif
+
 /************************************************************************/
 /*                               Write()                                */
 /************************************************************************/
@@ -575,9 +719,9 @@ void GDALRasterBlock::Verify()
 /**
  * Force writing of the current block, if dirty.
  *
- * The block is written using GDALRasterBand::IWriteBlock() on it's 
- * corresponding band object.  Even if the write fails the block will 
- * be marked clean. 
+ * The block is written using GDALRasterBand::IWriteBlock() on it's
+ * corresponding band object.  Even if the write fails the block will
+ * be marked clean.
  *
  * @return CE_None otherwise the error returned by IWriteBlock().
  */
@@ -611,8 +755,8 @@ CPLErr GDALRasterBlock::Write()
 /**
  * Push block to top of LRU (least-recently used) list.
  *
- * This method is normally called when a block is used to keep track 
- * that it has been recently used. 
+ * This method is normally called when a block is used to keep track
+ * that it has been recently used.
  */
 
 void GDALRasterBlock::Touch()
@@ -629,7 +773,7 @@ void GDALRasterBlock::Touch_unlocked()
     if( poNewest == this )
         return;
 
-    // In theory, we shouldn't try to touch a block that has been detached
+    // In theory, we should not try to touch a block that has been detached
     CPLAssert(bMustDetach);
     if( !bMustDetach )
     {
@@ -641,7 +785,7 @@ void GDALRasterBlock::Touch_unlocked()
 
     if( poOldest == this )
         poOldest = this->poPrevious;
-    
+
     if( poPrevious != NULL )
         poPrevious->poNext = poNext;
 
@@ -657,7 +801,7 @@ void GDALRasterBlock::Touch_unlocked()
         poNewest->poPrevious = this;
     }
     poNewest = this;
-    
+
     if( poOldest == NULL )
     {
         CPLAssert( poPrevious == NULL && poNext == NULL );
@@ -678,9 +822,9 @@ void GDALRasterBlock::Touch_unlocked()
  * This method allocates memory for the block, and attempts to flush other
  * blocks, if necessary, to bring the total cache size back within the limits.
  * The newly allocated block is touched and will be considered most recently
- * used in the LRU list. 
- * 
- * @return CE_None on success or CE_Failure if memory allocation fails. 
+ * used in the LRU list.
+ *
+ * @return CE_None on success or CE_Failure if memory allocation fails.
  */
 
 CPLErr GDALRasterBlock::Internalize()
@@ -701,11 +845,11 @@ CPLErr GDALRasterBlock::Internalize()
 /* -------------------------------------------------------------------- */
 /*      Flush old blocks if we are nearing our memory limit.            */
 /* -------------------------------------------------------------------- */
-    int bFirstIter = TRUE;
-    int bLoopAgain;
+    bool bFirstIter = true;
+    bool bLoopAgain = false;
     do
     {
-        bLoopAgain = FALSE;
+        bLoopAgain = false;
         GDALRasterBlock* apoBlocksToFree[64];
         int nBlocksToFree = 0;
         {
@@ -716,15 +860,22 @@ CPLErr GDALRasterBlock::Internalize()
             GDALRasterBlock *poTarget = poOldest;
             while( nCacheUsed > nCurCacheMax )
             {
-                while( poTarget != NULL && poTarget->GetLockCount() > 0 ) 
+                while( poTarget != NULL )
+                {
+                    if( CPLAtomicCompareAndExchange(&(poTarget->nLockCount), 0, -1) )
+                        break;
                     poTarget = poTarget->poPrevious;
+                }
 
                 if( poTarget != NULL )
                 {
+                    if( bSleepsForBockCacheDebug )
+                        CPLSleep(CPLAtof(CPLGetConfigOption("GDAL_RB_INTERNALIZE_SLEEP_AFTER_DROP_LOCK", "0")));
+
                     GDALRasterBlock* _poPrevious = poTarget->poPrevious;
 
                     poTarget->Detach_unlocked();
-                    poTarget->GetBand()->UnreferenceBlock(poTarget->GetXOff(),poTarget->GetYOff());
+                    poTarget->GetBand()->UnreferenceBlock(poTarget);
 
                     apoBlocksToFree[nBlocksToFree++] = poTarget;
                     if( poTarget->GetDirty() )
@@ -754,7 +905,7 @@ CPLErr GDALRasterBlock::Internalize()
                 Touch_unlocked();
         }
 
-        bFirstIter = FALSE;
+        bFirstIter = false;
 
         /* Now free blocks we have detached and removed from their band */
         for(int i=0;i<nBlocksToFree;i++)
@@ -777,22 +928,23 @@ CPLErr GDALRasterBlock::Internalize()
                 poBlock->GetBlockSize() == nSizeInBytes )
             {
                 pNewData = pDataBlock;
-                poBlock->pData = NULL;
             }
+            else
+            {
+                VSIFree(poBlock->pData);
+            }
+            poBlock->pData = NULL;
 
-            delete poBlock;
+            poBlock->GetBand()->AddBlockToFreeList(poBlock);
         }
     }
     while(bLoopAgain);
 
     if( pNewData == NULL )
     {
-        pNewData = VSIMalloc( nSizeInBytes );
+        pNewData = VSI_MALLOC_VERBOSE( nSizeInBytes );
         if( pNewData == NULL )
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory, 
-                    "GDALRasterBlock::Internalize : Out of memory allocating %d bytes.",
-                    nSizeInBytes);
             return( CE_Failure );
         }
     }
@@ -838,46 +990,115 @@ void GDALRasterBlock::MarkClean()
 }
 
 /************************************************************************/
-/*                           SafeLockBlock()                            */
+/*                          DestroyRBMutex()                           */
+/************************************************************************/
+
+void GDALRasterBlock::DestroyRBMutex()
+{
+    if( hRBLock != NULL )
+        DESTROY_LOCK;
+    hRBLock = NULL;
+}
+
+/************************************************************************/
+/*                              TakeLock()                              */
 /************************************************************************/
 
 /**
- * \brief Safely lock block.
+ * Take a lock
  *
- * This method locks a GDALRasterBlock (and touches it) in a thread-safe
- * manner.  The global block cache mutex is held while locking the block,
- * in order to avoid race conditions with other threads that might be
- * trying to expire the block at the same time.  The block pointer may be
- * safely NULL, in which case this method does nothing. 
+ * Should only be used by GDALArrayBandBlockCache::TryGetLockedBlockRef()
+ * and GDALHashSetBandBlockCache::TryGetLockedBlockRef()
  *
- * @param ppBlock Pointer to the block pointer to try and lock/touch.
+ * @return TRUE if the lock has been successfully acquired. If FALSE, this
+ *         should be reattempted after fetching again from the raster band
+ *         block storage.
  */
- 
-int GDALRasterBlock::SafeLockBlock( GDALRasterBlock ** ppBlock )
 
+int GDALRasterBlock::TakeLock()
 {
-    CPLAssert( NULL != ppBlock );
+    int nLockVal = AddLock();
+    CPLAssert(nLockVal >= 0);
+    if( bSleepsForBockCacheDebug )
+        CPLSleep(CPLAtof(CPLGetConfigOption("GDAL_RB_TRYGET_SLEEP_AFTER_TAKE_LOCK", "0")));
+    if( nLockVal == 0 )
+    {
+#ifdef DEBUG
+        CPLDebug("GDAL", "TakeLock(%p): Block(%d,%d,%p) is being evicted while trying to reacquire it",
+                 (void*)CPLGetPID(), nXOff, nYOff, poBand);
+#endif
+        // The block is being evicted by GDALRasterBlock::Internalize()
+        // or FlushCacheBlock(), so wait for this to be done before trying
+        // again
+        DropLock();
 
-    TAKE_LOCK;
+        // wait for the block having been unreferenced
+        TAKE_LOCK;
 
-    if( *ppBlock != NULL )
-    {
-        (*ppBlock)->AddLock();
-        (*ppBlock)->Touch_unlocked();
-        
-        return TRUE;
-    }
-    else
         return FALSE;
+    }
+    Touch();
+    return TRUE;
 }
 
 /************************************************************************/
-/*                          DestroyRBMutex()                           */
+/*                      DropLockForRemovalFromStorage()                 */
 /************************************************************************/
 
-void GDALRasterBlock::DestroyRBMutex()
+/**
+ * Drop a lock before removing the block from the band storage.
+ *
+ * Should only be used by GDALArrayBandBlockCache::FlushBlock()
+ * and GDALHashSetBandBlockCache::FlushBlock()
+ *
+ * @return TRUE if the lock has been successfully dropped.
+ */
+
+int GDALRasterBlock::DropLockForRemovalFromStorage()
 {
-    if( hRBLock != NULL )
-        DESTROY_LOCK;
-    hRBLock = NULL;
+    // Detect potential conflict with GDALRasterBlock::Internalize()
+    // or FlushCacheBlock()
+    if( CPLAtomicCompareAndExchange(&nLockCount, 0, -1) )
+        return TRUE;
+#ifdef DEBUG
+    CPLDebug("GDAL", "DropLockForRemovalFromStorage(%p): Block(%d,%d,%p) was "
+                "attempted to be flushed from band but it is flushed by global cache",
+                (void*)CPLGetPID(), nXOff, nYOff, poBand);
+#endif
+
+    // Wait for the block for having been unreferenced
+    TAKE_LOCK;
+
+    return FALSE;
 }
+
+#if 0
+void GDALRasterBlock::DumpAll()
+{
+    int iBlock = 0;
+    for( GDALRasterBlock *poBlock = poNewest;
+                            poBlock != NULL;
+                            poBlock = poBlock->poNext )
+    {
+        printf("Block %d\n", iBlock);
+        poBlock->DumpBlock();
+        printf("\n");
+        iBlock ++;
+    }
+}
+
+void GDALRasterBlock::DumpBlock()
+{
+        printf("  Lock count = %d\n", nLockCount);
+        printf("  bDirty = %d\n", bDirty);
+        printf("  nXOff = %d\n", nXOff);
+        printf("  nYOff = %d\n", nYOff);
+        printf("  nXSize = %d\n", nXSize);
+        printf("  nYSize = %d\n", nYSize);
+        printf("  eType = %d\n", eType);
+        printf("  Band %p\n", GetBand());
+        printf("  Band %d\n", GetBand()->GetBand());
+        if( GetBand()->GetDataset() )
+            printf("  Dataset = %s\n", GetBand()->GetDataset()->GetDescription());
+}
+#endif
diff --git a/gcore/gdalrescaledalphaband.cpp b/gcore/gdalrescaledalphaband.cpp
index c48fb34..92ef8de 100644
--- a/gcore/gdalrescaledalphaband.cpp
+++ b/gcore/gdalrescaledalphaband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalrescaledalphaband.cpp 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: gdalrescaledalphaband.cpp 31703 2015-11-21 22:11:38Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALRescaledAlphaBand, a class implementing
@@ -30,15 +30,16 @@
 
 #include "gdal_priv.h"
 
-CPL_CVSID("$Id: gdalrescaledalphaband.cpp 28053 2014-12-04 09:31:07Z rouault $");
+CPL_CVSID("$Id: gdalrescaledalphaband.cpp 31703 2015-11-21 22:11:38Z rouault $");
 
 /************************************************************************/
 /*                        GDALRescaledAlphaBand()                       */
 /************************************************************************/
 
-GDALRescaledAlphaBand::GDALRescaledAlphaBand( GDALRasterBand *poParent )
+GDALRescaledAlphaBand::GDALRescaledAlphaBand( GDALRasterBand *poParentIn )
 
 {
+    poParent = poParentIn;
     CPLAssert(poParent->GetRasterDataType() == GDT_UInt16);
 
     poDS = NULL;
@@ -50,8 +51,6 @@ GDALRescaledAlphaBand::GDALRescaledAlphaBand( GDALRasterBand *poParent )
     eDataType = GDT_Byte;
     poParent->GetBlockSize( &nBlockXSize, &nBlockYSize );
 
-    this->poParent = poParent;
-
     pTemp = NULL;
 }
 
@@ -109,11 +108,9 @@ CPLErr GDALRescaledAlphaBand::IRasterIO( GDALRWFlag eRWFlag,
     {
         if( pTemp == NULL )
         {
-            pTemp = VSIMalloc2( sizeof(GUInt16), nRasterXSize );
+            pTemp = VSI_MALLOC2_VERBOSE( sizeof(GUInt16), nRasterXSize );
             if (pTemp == NULL)
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory,
-                        "GDALRescaledAlphaBand::IReadBlock: Out of memory for buffer." );
                 return CE_Failure;
             }
         }
@@ -136,7 +133,7 @@ CPLErr GDALRescaledAlphaBand::IRasterIO( GDALRWFlag eRWFlag,
                 if( pSrc[i] > 0 && pSrc[i] < 257 )
                     pabyImage[i] = 1;
                 else
-                    pabyImage[i] = (pSrc[i] * 255) / 65535;
+                    pabyImage[i] = static_cast<GByte>((pSrc[i] * 255) / 65535);
             }
         }
         return CE_None;
diff --git a/gcore/gdalsse_priv.h b/gcore/gdalsse_priv.h
index e323e87..ffc10ef 100644
--- a/gcore/gdalsse_priv.h
+++ b/gcore/gdalsse_priv.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalsse_priv.h 28877 2015-04-08 23:11:36Z rouault $
+ * $Id: gdalsse_priv.h 32173 2015-12-14 00:04:53Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  SSE2 helper
@@ -30,6 +30,8 @@
 #ifndef GDALSSE_PRIV_H_INCLUDED
 #define GDALSSE_PRIV_H_INCLUDED
 
+#include "cpl_port.h"
+
 /* We restrict to 64bit processors because they are guaranteed to have SSE2 */
 /* Could possibly be used too on 32bit, but we would need to check at runtime */
 #if (defined(__x86_64) || defined(_M_X64)) && !defined(USE_SSE2_EMULATION)
@@ -43,7 +45,9 @@ class XMMReg2Double
   public:
     __m128d xmm;
 
+    /* coverity[uninit_member] */
     XMMReg2Double() {}
+
     XMMReg2Double(double  val)  { xmm = _mm_load_sd (&val); }
     XMMReg2Double(const XMMReg2Double& other) : xmm(other.xmm) {}
 
@@ -54,6 +58,13 @@ class XMMReg2Double
         return reg;
     }
 
+    static inline XMMReg2Double Load1ValHighAndLow(const double* ptr)
+    {
+        XMMReg2Double reg;
+        reg.nsLoad1ValHighAndLow(ptr);
+        return reg;
+    }
+
     static inline XMMReg2Double Load2Val(const double* ptr)
     {
         XMMReg2Double reg;
@@ -95,7 +106,54 @@ class XMMReg2Double
         reg.nsLoad2Val(ptr);
         return reg;
     }
-    
+
+    static inline XMMReg2Double Equals(const XMMReg2Double& expr1, const XMMReg2Double& expr2)
+    {
+        XMMReg2Double reg;
+        reg.xmm = _mm_cmpeq_pd(expr1.xmm, expr2.xmm);
+        return reg;
+    }
+
+    static inline XMMReg2Double NotEquals(const XMMReg2Double& expr1, const XMMReg2Double& expr2)
+    {
+        XMMReg2Double reg;
+        reg.xmm = _mm_cmpneq_pd(expr1.xmm, expr2.xmm);
+        return reg;
+    }
+
+    static inline XMMReg2Double Greater(const XMMReg2Double& expr1, const XMMReg2Double& expr2)
+    {
+        XMMReg2Double reg;
+        reg.xmm = _mm_cmpgt_pd(expr1.xmm, expr2.xmm);
+        return reg;
+    }
+
+    static inline XMMReg2Double And(const XMMReg2Double& expr1, const XMMReg2Double& expr2)
+    {
+        XMMReg2Double reg;
+        reg.xmm = _mm_and_pd(expr1.xmm, expr2.xmm);
+        return reg;
+    }
+
+    static inline XMMReg2Double Ternary(const XMMReg2Double& cond, const XMMReg2Double& true_expr, const XMMReg2Double& false_expr)
+    {
+        XMMReg2Double reg;
+        reg.xmm = _mm_or_pd(_mm_and_pd (cond.xmm, true_expr.xmm), _mm_andnot_pd(cond.xmm, false_expr.xmm));
+        return reg;
+    }
+
+    static inline XMMReg2Double Min(const XMMReg2Double& expr1, const XMMReg2Double& expr2)
+    {
+        XMMReg2Double reg;
+        reg.xmm = _mm_min_pd(expr1.xmm, expr2.xmm);
+        return reg;
+    }
+
+    inline void nsLoad1ValHighAndLow(const double* ptr)
+    {
+        xmm =  _mm_load1_pd(ptr);
+    }
+
     inline void nsLoad2Val(const double* ptr)
     {
         xmm = _mm_loadu_pd(ptr);
@@ -117,7 +175,13 @@ class XMMReg2Double
 
     inline void nsLoad2Val(const unsigned char* ptr)
     {
+#ifdef CPL_CPU_REQUIRES_ALIGNED_ACCESS
+        unsigned short s;
+        memcpy(&s, ptr, 2);
+        __m128i xmm_i = _mm_cvtsi32_si128(s);
+#else
         __m128i xmm_i = _mm_cvtsi32_si128(*(unsigned short*)(ptr));
+#endif
         xmm_i = _mm_unpacklo_epi8(xmm_i, _mm_setzero_si128());
         xmm_i = _mm_unpacklo_epi16(xmm_i, _mm_setzero_si128());
         xmm = _mm_cvtepi32_pd(xmm_i);
@@ -142,10 +206,16 @@ class XMMReg2Double
         xmm_i = _mm_srli_epi32(xmm_i, 16);       /* 0|0|0|0|b|b|a|a --> 0|0|0|0|0|b|0|a */
         xmm = _mm_cvtepi32_pd(xmm_i);
     }
-    
+
     static inline void Load4Val(const unsigned char* ptr, XMMReg2Double& low, XMMReg2Double& high)
     {
+#ifdef CPL_CPU_REQUIRES_ALIGNED_ACCESS
+        int i;
+        memcpy(&i, ptr, 4);
+        __m128i xmm_i = _mm_cvtsi32_si128(i);
+#else
         __m128i xmm_i = _mm_cvtsi32_si128(*(int*)(ptr));
+#endif
         xmm_i = _mm_unpacklo_epi8(xmm_i, _mm_setzero_si128());
         xmm_i = _mm_unpacklo_epi16(xmm_i, _mm_setzero_si128());
         low.xmm = _mm_cvtepi32_pd(xmm_i);
@@ -177,49 +247,56 @@ class XMMReg2Double
         low.xmm = _mm_cvtps_pd(temp1);
         high.xmm = _mm_cvtps_pd(temp2);
     }
-    
+
     inline void Zeroize()
     {
         xmm = _mm_setzero_pd();
     }
 
-    inline const XMMReg2Double& operator= (const XMMReg2Double& other)
+    inline XMMReg2Double& operator= (const XMMReg2Double& other)
     {
         xmm = other.xmm;
         return *this;
     }
 
-    inline const XMMReg2Double& operator+= (const XMMReg2Double& other)
+    inline XMMReg2Double& operator+= (const XMMReg2Double& other)
     {
         xmm = _mm_add_pd(xmm, other.xmm);
         return *this;
     }
 
-    inline XMMReg2Double operator+ (const XMMReg2Double& other)
+    inline XMMReg2Double& operator*= (const XMMReg2Double& other)
+    {
+        xmm = _mm_mul_pd(xmm, other.xmm);
+        return *this;
+    }
+
+    inline XMMReg2Double operator+ (const XMMReg2Double& other) const
     {
         XMMReg2Double ret;
         ret.xmm = _mm_add_pd(xmm, other.xmm);
         return ret;
     }
 
-    inline XMMReg2Double operator- (const XMMReg2Double& other)
+    inline XMMReg2Double operator- (const XMMReg2Double& other) const
     {
         XMMReg2Double ret;
         ret.xmm = _mm_sub_pd(xmm, other.xmm);
         return ret;
     }
 
-    inline XMMReg2Double operator* (const XMMReg2Double& other)
+    inline XMMReg2Double operator* (const XMMReg2Double& other) const
     {
         XMMReg2Double ret;
         ret.xmm = _mm_mul_pd(xmm, other.xmm);
         return ret;
     }
 
-    inline const XMMReg2Double& operator*= (const XMMReg2Double& other)
+    inline XMMReg2Double operator/ (const XMMReg2Double& other) const
     {
-        xmm = _mm_mul_pd(xmm, other.xmm);
-        return *this;
+        XMMReg2Double ret;
+        ret.xmm = _mm_div_pd(xmm, other.xmm);
+        return ret;
     }
 
     inline void AddLowAndHigh()
@@ -228,17 +305,24 @@ class XMMReg2Double
         xmm2 = _mm_shuffle_pd(xmm,xmm,_MM_SHUFFLE2(0,1)); /* transfer high word into low word of xmm2 */
         xmm = _mm_add_pd(xmm, xmm2);
     }
-    
-    inline void Store2Double(double* pval)
+
+    inline void Store2Double(double* pval) const
     {
         _mm_storeu_pd(pval, xmm);
     }
-    
-    inline void Store2DoubleAligned(double* pval)
+
+    inline void Store2DoubleAligned(double* pval) const
     {
         _mm_store_pd(pval, xmm);
     }
 
+    void Store2Val(unsigned short* ptr) const
+    {
+        __m128i tmp = _mm_cvtpd_epi32(xmm); /* Convert the 2 double values to 2 integers */
+        ptr[0] = (GUInt16)_mm_extract_epi16(tmp, 0);
+        ptr[1] = (GUInt16)_mm_extract_epi16(tmp, 2);
+    }
+
     inline operator double () const
     {
         double val;
@@ -267,7 +351,105 @@ class XMMReg2Double
         reg.Zeroize();
         return reg;
     }
-    
+
+    static inline XMMReg2Double Load1ValHighAndLow(const double* ptr)
+    {
+        XMMReg2Double reg;
+        reg.nsLoad1ValHighAndLow(ptr);
+        return reg;
+    }
+
+    static inline XMMReg2Double Equals(const XMMReg2Double& expr1, const XMMReg2Double& expr2)
+    {
+        XMMReg2Double reg;
+
+        if (expr1.low == expr2.low)
+            memset(&(reg.low), 0xFF, sizeof(double));
+        else
+            reg.low = 0;
+
+        if (expr1.high == expr2.high)
+            memset(&(reg.high), 0xFF, sizeof(double));
+        else
+            reg.high = 0;
+
+        return reg;
+    }
+
+    static inline XMMReg2Double NotEquals(const XMMReg2Double& expr1, const XMMReg2Double& expr2)
+    {
+        XMMReg2Double reg;
+
+        if (expr1.low != expr2.low)
+            memset(&(reg.low), 0xFF, sizeof(double));
+        else
+            reg.low = 0;
+
+        if (expr1.high != expr2.high)
+            memset(&(reg.high), 0xFF, sizeof(double));
+        else
+            reg.high = 0;
+
+        return reg;
+    }
+
+    static inline XMMReg2Double Greater(const XMMReg2Double& expr1, const XMMReg2Double& expr2)
+    {
+        XMMReg2Double reg;
+
+        if (expr1.low > expr2.low)
+            memset(&(reg.low), 0xFF, sizeof(double));
+        else
+            reg.low = 0;
+
+        if (expr1.high > expr2.high)
+            memset(&(reg.high), 0xFF, sizeof(double));
+        else
+            reg.high = 0;
+
+        return reg;
+    }
+
+    static inline XMMReg2Double And(const XMMReg2Double& expr1, const XMMReg2Double& expr2)
+    {
+        XMMReg2Double reg;
+        int low1[2], high1[2];
+        int low2[2], high2[2];
+        memcpy(low1, &expr1.low, sizeof(double));
+        memcpy(high1, &expr1.high, sizeof(double));
+        memcpy(low2, &expr2.low, sizeof(double));
+        memcpy(high2, &expr2.high, sizeof(double));
+        low1[0] &= low2[0];
+        low1[1] &= low2[1];
+        high1[0] &= high2[0];
+        high1[1] &= high2[1];
+        memcpy(&reg.low, low1, sizeof(double));
+        memcpy(&reg.high, high1, sizeof(double));
+        return reg;
+    }
+
+    static inline XMMReg2Double Ternary(const XMMReg2Double& cond, const XMMReg2Double& true_expr, const XMMReg2Double& false_expr)
+    {
+        XMMReg2Double reg;
+        if( cond.low )
+            reg.low = true_expr.low;
+        else
+            reg.low = false_expr.low;
+        if( cond.high )
+            reg.high = true_expr.high;
+        else
+            reg.high = false_expr.high;
+        return reg;
+    }
+
+    static inline XMMReg2Double Min(const XMMReg2Double& expr1, const XMMReg2Double& expr2)
+    {
+        XMMReg2Double reg;
+        reg.low = (expr1.low < expr2.low) ? expr1.low : expr2.high;
+        reg.high = (expr1.high < expr2.high) ? expr1.high : expr2.low;
+        return reg;
+    }
+
     static inline XMMReg2Double Load2Val(const double* ptr)
     {
         XMMReg2Double reg;
@@ -281,7 +463,7 @@ class XMMReg2Double
         reg.nsLoad2ValAligned(ptr);
         return reg;
     }
-    
+
     static inline XMMReg2Double Load2Val(const float* ptr)
     {
         XMMReg2Double reg;
@@ -303,6 +485,19 @@ class XMMReg2Double
         return reg;
     }
 
+    static inline XMMReg2Double Load2Val(const unsigned short* ptr)
+    {
+        XMMReg2Double reg;
+        reg.nsLoad2Val(ptr);
+        return reg;
+    }
+
+    inline void nsLoad1ValHighAndLow(const double* pval)
+    {
+        low = pval[0];
+        high = pval[0];
+    }
+
     inline void nsLoad2Val(const double* pval)
     {
         low = pval[0];
@@ -338,7 +533,7 @@ class XMMReg2Double
         low = ptr[0];
         high = ptr[1];
     }
-    
+
     static inline void Load4Val(const unsigned char* ptr, XMMReg2Double& low, XMMReg2Double& high)
     {
         low.low = ptr[0];
@@ -377,21 +572,28 @@ class XMMReg2Double
         high = 0.0;
     }
 
-    inline const XMMReg2Double& operator= (const XMMReg2Double& other)
+    inline XMMReg2Double& operator= (const XMMReg2Double& other)
     {
         low = other.low;
         high = other.high;
         return *this;
     }
 
-    inline const XMMReg2Double& operator+= (const XMMReg2Double& other)
+    inline XMMReg2Double& operator+= (const XMMReg2Double& other)
     {
         low += other.low;
         high += other.high;
         return *this;
     }
 
-    inline XMMReg2Double operator+ (const XMMReg2Double& other)
+    inline XMMReg2Double& operator*= (const XMMReg2Double& other)
+    {
+        low *= other.low;
+        high *= other.high;
+        return *this;
+    }
+
+    inline XMMReg2Double operator+ (const XMMReg2Double& other) const
     {
         XMMReg2Double ret;
         ret.low = low + other.low;
@@ -399,7 +601,7 @@ class XMMReg2Double
         return ret;
     }
 
-    inline XMMReg2Double operator- (const XMMReg2Double& other)
+    inline XMMReg2Double operator- (const XMMReg2Double& other) const
     {
         XMMReg2Double ret;
         ret.low = low - other.low;
@@ -407,7 +609,7 @@ class XMMReg2Double
         return ret;
     }
 
-    inline XMMReg2Double operator* (const XMMReg2Double& other)
+    inline XMMReg2Double operator* (const XMMReg2Double& other) const
     {
         XMMReg2Double ret;
         ret.low = low * other.low;
@@ -415,11 +617,12 @@ class XMMReg2Double
         return ret;
     }
 
-    inline const XMMReg2Double& operator*= (const XMMReg2Double& other)
+    inline XMMReg2Double operator/ (const XMMReg2Double& other) const
     {
-        low *= other.low;
-        high *= other.high;
-        return *this;
+        XMMReg2Double ret;
+        ret.low = low / other.low;
+        ret.high = high / other.high;
+        return ret;
     }
 
     inline void AddLowAndHigh()
@@ -429,18 +632,24 @@ class XMMReg2Double
         high = add;
     }
 
-    inline void Store2Double(double* pval)
+    inline void Store2Double(double* pval) const
     {
         pval[0] = low;
         pval[1] = high;
     }
-    
-    inline void Store2DoubleAligned(double* pval)
+
+    inline void Store2DoubleAligned(double* pval) const
     {
         pval[0] = low;
         pval[1] = high;
     }
 
+    void Store2Val(unsigned short* ptr) const
+    {
+        ptr[0] = (GUInt16)low;
+        ptr[1] = (GUInt16)high;
+    }
+
     inline operator double () const
     {
         return low;
@@ -464,7 +673,15 @@ class XMMReg4Double
         reg.high.Zeroize();
         return reg;
     }
-    
+
+    static inline XMMReg4Double Load1ValHighAndLow(const double* ptr)
+    {
+        XMMReg4Double reg;
+        reg.low.nsLoad1ValHighAndLow(ptr);
+        reg.high = reg.low;
+        return reg;
+    }
+
     static inline XMMReg4Double Load4Val(const unsigned char* ptr)
     {
         XMMReg4Double reg;
@@ -510,22 +727,77 @@ class XMMReg4Double
         XMMReg2Double::Load4Val(ptr, reg.low, reg.high);
         return reg;
     }
-    
-    inline const XMMReg4Double& operator= (const XMMReg4Double& other)
+
+    static inline XMMReg4Double Equals(const XMMReg4Double& expr1, const XMMReg4Double& expr2)
+    {
+        XMMReg4Double reg;
+        reg.low = XMMReg2Double::Equals(expr1.low, expr2.low);
+        reg.high = XMMReg2Double::Equals(expr1.high, expr2.high);
+        return reg;
+    }
+
+    static inline XMMReg4Double NotEquals(const XMMReg4Double& expr1, const XMMReg4Double& expr2)
+    {
+        XMMReg4Double reg;
+        reg.low = XMMReg2Double::NotEquals(expr1.low, expr2.low);
+        reg.high = XMMReg2Double::NotEquals(expr1.high, expr2.high);
+        return reg;
+    }
+
+    static inline XMMReg4Double Greater(const XMMReg4Double& expr1, const XMMReg4Double& expr2)
+    {
+        XMMReg4Double reg;
+        reg.low = XMMReg2Double::Greater(expr1.low, expr2.low);
+        reg.high = XMMReg2Double::Greater(expr1.high, expr2.high);
+        return reg;
+    }
+
+    static inline XMMReg4Double And(const XMMReg4Double& expr1, const XMMReg4Double& expr2)
+    {
+        XMMReg4Double reg;
+        reg.low = XMMReg2Double::And(expr1.low, expr2.low);
+        reg.high = XMMReg2Double::And(expr1.high, expr2.high);
+        return reg;
+    }
+
+    static inline XMMReg4Double Ternary(const XMMReg4Double& cond, const XMMReg4Double& true_expr, const XMMReg4Double& false_expr)
+    {
+        XMMReg4Double reg;
+        reg.low = XMMReg2Double::Ternary(cond.low, true_expr.low, false_expr.low);
+        reg.high = XMMReg2Double::Ternary(cond.high, true_expr.high, false_expr.high);
+        return reg;
+    }
+
+    static inline XMMReg4Double Min(const XMMReg4Double& expr1, const XMMReg4Double& expr2)
+    {
+        XMMReg4Double reg;
+        reg.low = XMMReg2Double::Min(expr1.low, expr2.low);
+        reg.high = XMMReg2Double::Min(expr1.high, expr2.high);
+        return reg;
+    }
+
+    inline XMMReg4Double& operator= (const XMMReg4Double& other)
     {
         low = other.low;
         high = other.high;
         return *this;
     }
 
-    inline const XMMReg4Double& operator+= (const XMMReg4Double& other)
+    inline XMMReg4Double& operator+= (const XMMReg4Double& other)
     {
         low += other.low;
         high += other.high;
         return *this;
     }
 
-    inline XMMReg4Double operator+ (const XMMReg4Double& other)
+    inline XMMReg4Double& operator*= (const XMMReg4Double& other)
+    {
+        low *= other.low;
+        high *= other.high;
+        return *this;
+    }
+
+    inline XMMReg4Double operator+ (const XMMReg4Double& other) const
     {
         XMMReg4Double ret;
         ret.low = low + other.low;
@@ -533,7 +805,7 @@ class XMMReg4Double
         return ret;
     }
 
-    inline XMMReg4Double operator- (const XMMReg4Double& other)
+    inline XMMReg4Double operator- (const XMMReg4Double& other) const
     {
         XMMReg4Double ret;
         ret.low = low - other.low;
@@ -541,7 +813,7 @@ class XMMReg4Double
         return ret;
     }
 
-    inline XMMReg4Double operator* (const XMMReg4Double& other)
+    inline XMMReg4Double operator* (const XMMReg4Double& other) const
     {
         XMMReg4Double ret;
         ret.low = low * other.low;
@@ -549,11 +821,12 @@ class XMMReg4Double
         return ret;
     }
 
-    inline const XMMReg4Double& operator*= (const XMMReg4Double& other)
+    inline XMMReg4Double operator/ (const XMMReg4Double& other) const
     {
-        low *= other.low;
-        high *= other.high;
-        return *this;
+        XMMReg4Double ret;
+        ret.low = low / other.low;
+        ret.high = high / other.high;
+        return ret;
     }
 
     inline void AddLowAndHigh()
@@ -566,6 +839,17 @@ class XMMReg4Double
     {
         return low;
     }
+
+    inline XMMReg2Double& GetHigh()
+    {
+        return high;
+    }
+
+    void Store4Val(unsigned short* ptr) const
+    {
+        low.Store2Val(ptr);
+        high.Store2Val(ptr+2);
+    }
 };
 
 #endif /* GDALSSE_PRIV_H_INCLUDED */
diff --git a/gcore/gdalvirtualmem.cpp b/gcore/gdalvirtualmem.cpp
index a827143..0776d34 100644
--- a/gcore/gdalvirtualmem.cpp
+++ b/gcore/gdalvirtualmem.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: gdalvirtualmem.cpp 27921 2014-11-05 12:58:23Z rouault $
+ * $Id: gdalvirtualmem.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Name:     gdalvirtualmem.cpp
  * Project:  GDAL
@@ -15,22 +15,23 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
 #include "gdal.h"
 #include "cpl_conv.h"
 #include "cpl_virtualmem.h"
+#include "gdal_priv.h"
 
 /* To be changed if we go to 64-bit RasterIO coordinates and spacing */
 typedef int coord_type;
@@ -106,21 +107,21 @@ public:
 /*                             GDALVirtualMem()                         */
 /************************************************************************/
 
-GDALVirtualMem::GDALVirtualMem( GDALDatasetH hDS,
-                                GDALRasterBandH hBand,
-                                coord_type nXOff, coord_type nYOff,
+GDALVirtualMem::GDALVirtualMem( GDALDatasetH hDSIn,
+                                GDALRasterBandH hBandIn,
+                                coord_type nXOffIn, coord_type nYOffIn,
                                 CPL_UNUSED coord_type nXSize,
                                 CPL_UNUSED coord_type nYSize,
-                                coord_type nBufXSize, coord_type nBufYSize,
-                                GDALDataType eBufType,
-                                int nBandCount, const int* panBandMapIn,
-                                int nPixelSpace,
-                                GIntBig nLineSpace,
-                                GIntBig nBandSpace ) :
-    hDS(hDS), hBand(hBand), nXOff(nXOff), nYOff(nYOff), /*nXSize(nXSize), nYSize(nYSize),*/
-    nBufXSize(nBufXSize), nBufYSize(nBufYSize), eBufType(eBufType),
-    nBandCount(nBandCount), nPixelSpace(nPixelSpace), nLineSpace(nLineSpace),
-    nBandSpace(nBandSpace)
+                                coord_type nBufXSizeIn, coord_type nBufYSizeIn,
+                                GDALDataType eBufTypeIn,
+                                int nBandCountIn, const int* panBandMapIn,
+                                int nPixelSpaceIn,
+                                GIntBig nLineSpaceIn,
+                                GIntBig nBandSpaceIn ) :
+    hDS(hDSIn), hBand(hBandIn), nXOff(nXOffIn), nYOff(nYOffIn), /*nXSize(nXSize), nYSize(nYSize),*/
+    nBufXSize(nBufXSizeIn), nBufYSize(nBufYSizeIn), eBufType(eBufTypeIn),
+    nBandCount(nBandCountIn), nPixelSpace(nPixelSpaceIn), nLineSpace(nLineSpaceIn),
+    nBandSpace(nBandSpaceIn)
 {
     if( hDS != NULL )
     {
@@ -142,7 +143,7 @@ GDALVirtualMem::GDALVirtualMem( GDALDatasetH hDS,
         nBandCount = 1;
     }
 
-    int nDataTypeSize = GDALGetDataTypeSize(eBufType) / 8;
+    const int nDataTypeSize = GDALGetDataTypeSizeBytes(eBufType);
     if( nPixelSpace == nDataTypeSize &&
         nLineSpace == (GIntBig)nBufXSize * nPixelSpace &&
         nBandSpace == nBufYSize * nLineSpace )
@@ -299,12 +300,12 @@ void GDALVirtualMem::DoIOPixelInterleaved( GDALRWFlag eRWFlag,
             bandEnd = nBandCount;
 
         // Finish reading/writing the remaining bands for that pixel
-        GDALDatasetRasterIO( hDS, eRWFlag,
+        CPL_IGNORE_RET_VAL(GDALDatasetRasterIO( hDS, eRWFlag,
                             nXOff + x, nYOff + y, 1, 1,
                             (char*)pPage + nOffsetShift,
                             1, 1, eBufType,
                             bandEnd - band, panBandMap + band,
-                            nPixelSpace, (spacing_type)nLineSpace, (spacing_type)nBandSpace );
+                            nPixelSpace, (spacing_type)nLineSpace, (spacing_type)nBandSpace ));
 
         if( bandEnd < nBandCount )
             return;
@@ -330,12 +331,12 @@ void GDALVirtualMem::DoIOPixelInterleaved( GDALRWFlag eRWFlag,
 
         if( x < xEnd )
         {
-            GDALDatasetRasterIO( hDS, eRWFlag,
+            CPL_IGNORE_RET_VAL(GDALDatasetRasterIO( hDS, eRWFlag,
                                 nXOff + x, nYOff + y, xEnd - x, 1,
                                 (char*) pPage + nOffsetShift,
                                 xEnd - x, 1, eBufType,
                                 nBandCount, panBandMap,
-                                nPixelSpace, (spacing_type)nLineSpace, (spacing_type)nBandSpace );
+                                nPixelSpace, (spacing_type)nLineSpace, (spacing_type)nBandSpace ));
         }
 
         // Are there partial bands to read/write for the last pixel ?
@@ -350,12 +351,12 @@ void GDALVirtualMem::DoIOPixelInterleaved( GDALRWFlag eRWFlag,
             if( bandEnd >= nBandCount )
                 bandEnd = nBandCount;
 
-            GDALDatasetRasterIO( hDS, eRWFlag,
+            CPL_IGNORE_RET_VAL(GDALDatasetRasterIO( hDS, eRWFlag,
                                 nXOff + x, nYOff + y, 1, 1,
                                 (char*) pPage + nOffsetShift,
                                 1, 1, eBufType,
                                 bandEnd, panBandMap,
-                                nPixelSpace, (spacing_type)nLineSpace, (spacing_type)nBandSpace );
+                                nPixelSpace, (spacing_type)nLineSpace, (spacing_type)nBandSpace ));
         }
 
         return;
@@ -364,12 +365,12 @@ void GDALVirtualMem::DoIOPixelInterleaved( GDALRWFlag eRWFlag,
     // Yes, enough place to read/write until end of line
     if( x > 0 || nBytes - nOffsetShift < (size_t)nLineSpace )
     {
-        GDALDatasetRasterIO( hDS, eRWFlag,
+        CPL_IGNORE_RET_VAL(GDALDatasetRasterIO( hDS, eRWFlag,
                     nXOff + x, nYOff + y, nBufXSize - x, 1,
                     (char*)pPage + nOffsetShift,
                     nBufXSize - x, 1, eBufType,
                     nBandCount, panBandMap,
-                    nPixelSpace, (spacing_type)nLineSpace, (spacing_type)nBandSpace );
+                    nPixelSpace, (spacing_type)nLineSpace, (spacing_type)nBandSpace ));
 
         // Go to beginning of next line
         x = nBufXSize - 1;
@@ -388,13 +389,13 @@ void GDALVirtualMem::DoIOPixelInterleaved( GDALRWFlag eRWFlag,
         nLineCount = nBufYSize - y;
     if( nLineCount > 0 )
     {
-        GDALDatasetRasterIO( hDS, eRWFlag,
+        CPL_IGNORE_RET_VAL(GDALDatasetRasterIO( hDS, eRWFlag,
                              nXOff + 0, nYOff + y, nBufXSize, nLineCount,
                              (GByte*) pPage + nOffsetShift,
                              nBufXSize, nLineCount, eBufType,
                              nBandCount, panBandMap,
-                             nPixelSpace, (spacing_type)nLineSpace, (spacing_type)nBandSpace );
-        
+                             nPixelSpace, (spacing_type)nLineSpace, (spacing_type)nBandSpace ));
+
         y += nLineCount;
         if( y == nBufYSize )
             return;
@@ -404,7 +405,7 @@ void GDALVirtualMem::DoIOPixelInterleaved( GDALRWFlag eRWFlag,
 
     if( nOffsetShift < nBytes )
     {
-        DoIOPixelInterleaved( eRWFlag, nOffsetRecompute, 
+        DoIOPixelInterleaved( eRWFlag, nOffsetRecompute,
                (char*) pPage + nOffsetShift, nBytes - nOffsetShift );
     }
 }
@@ -456,11 +457,11 @@ void GDALVirtualMem::DoIOBandSequential( GDALRWFlag eRWFlag,
         GetXYBand(nOffset + nBytes, xEnd, yEnd, bandEnd);
         CPLAssert(y == yEnd);
         CPLAssert(band == bandEnd);
-        GDALRasterIO( (hBand) ? hBand : GDALGetRasterBand(hDS, panBandMap[band]), eRWFlag,
+        CPL_IGNORE_RET_VAL(GDALRasterIO( (hBand) ? hBand : GDALGetRasterBand(hDS, panBandMap[band]), eRWFlag,
                       nXOff + x, nYOff + y, xEnd - x, 1,
                       (char*)pPage + nOffsetShift,
                       xEnd - x, 1, eBufType,
-                      nPixelSpace, (spacing_type)nLineSpace );
+                      nPixelSpace, (spacing_type)nLineSpace ));
 
         return;
     }
@@ -468,11 +469,11 @@ void GDALVirtualMem::DoIOBandSequential( GDALRWFlag eRWFlag,
     // Yes, enough place to read/write until end of line
     if( x > 0 || nBytes - nOffsetShift < (size_t)nLineSpace )
     {
-        GDALRasterIO( (hBand) ? hBand : GDALGetRasterBand(hDS, panBandMap[band]), eRWFlag,
+        CPL_IGNORE_RET_VAL(GDALRasterIO( (hBand) ? hBand : GDALGetRasterBand(hDS, panBandMap[band]), eRWFlag,
                     nXOff + x, nYOff + y, nBufXSize - x, 1,
                     (char*)pPage + nOffsetShift,
                     nBufXSize - x, 1, eBufType,
-                    nPixelSpace, (spacing_type)nLineSpace );
+                    nPixelSpace, (spacing_type)nLineSpace ));
 
         // Go to beginning of next line
         x = nBufXSize - 1;
@@ -490,11 +491,11 @@ void GDALVirtualMem::DoIOBandSequential( GDALRWFlag eRWFlag,
         nLineCount = nBufYSize - y;
     if( nLineCount > 0 )
     {
-        GDALRasterIO( (hBand) ? hBand : GDALGetRasterBand(hDS, panBandMap[band]), eRWFlag,
+        CPL_IGNORE_RET_VAL(GDALRasterIO( (hBand) ? hBand : GDALGetRasterBand(hDS, panBandMap[band]), eRWFlag,
                     nXOff + 0, nYOff + y, nBufXSize, nLineCount,
                     (GByte*) pPage + nOffsetShift,
                     nBufXSize, nLineCount, eBufType,
-                    nPixelSpace, (spacing_type)nLineSpace );
+                    nPixelSpace, (spacing_type)nLineSpace ));
 
         y += nLineCount;
         if( y == nBufYSize )
@@ -510,7 +511,7 @@ void GDALVirtualMem::DoIOBandSequential( GDALRWFlag eRWFlag,
 
     if( nOffsetShift < nBytes )
     {
-        DoIOBandSequential( eRWFlag, nOffsetRecompute, 
+        DoIOBandSequential( eRWFlag, nOffsetRecompute,
                (char*) pPage + nOffsetShift, nBytes - nOffsetShift );
     }
 }
@@ -519,14 +520,13 @@ void GDALVirtualMem::DoIOBandSequential( GDALRWFlag eRWFlag,
 /*                    FillCacheBandSequential()                        */
 /************************************************************************/
 
-void GDALVirtualMem::FillCacheBandSequential(CPLVirtualMem* ctxt, 
+void GDALVirtualMem::FillCacheBandSequential(CPLVirtualMem*,
                   size_t nOffset,
                   void* pPageToFill,
                   size_t nToFill,
                   void* pUserData)
 {
     const GDALVirtualMem* psParms = (const GDALVirtualMem* )pUserData;
-    (void)ctxt;
     psParms->DoIOBandSequential(GF_Read, nOffset, pPageToFill, nToFill);
 }
 
@@ -534,14 +534,13 @@ void GDALVirtualMem::FillCacheBandSequential(CPLVirtualMem* ctxt,
 /*                    SaveFromCacheBandSequential()                    */
 /************************************************************************/
 
-void GDALVirtualMem::SaveFromCacheBandSequential(CPLVirtualMem* ctxt, 
+void GDALVirtualMem::SaveFromCacheBandSequential(CPLVirtualMem*,
                   size_t nOffset,
                   const void* pPageToBeEvicted,
                   size_t nToEvicted,
                   void* pUserData)
 {
     const GDALVirtualMem* psParms = (const GDALVirtualMem* )pUserData;
-    (void)ctxt;
     psParms->DoIOBandSequential(GF_Write, nOffset, (void*)pPageToBeEvicted, nToEvicted);
 }
 
@@ -549,14 +548,13 @@ void GDALVirtualMem::SaveFromCacheBandSequential(CPLVirtualMem* ctxt,
 /*                     FillCachePixelInterleaved()                      */
 /************************************************************************/
 
-void GDALVirtualMem::FillCachePixelInterleaved(CPLVirtualMem* ctxt, 
+void GDALVirtualMem::FillCachePixelInterleaved(CPLVirtualMem*,
                   size_t nOffset,
                   void* pPageToFill,
                   size_t nToFill,
                   void* pUserData)
 {
     const GDALVirtualMem* psParms = (const GDALVirtualMem* )pUserData;
-    (void)ctxt;
     psParms->DoIOPixelInterleaved(GF_Read, nOffset, pPageToFill, nToFill);
 }
 
@@ -564,14 +562,13 @@ void GDALVirtualMem::FillCachePixelInterleaved(CPLVirtualMem* ctxt,
 /*                     SaveFromCachePixelInterleaved()                  */
 /************************************************************************/
 
-void GDALVirtualMem::SaveFromCachePixelInterleaved(CPLVirtualMem* ctxt, 
+void GDALVirtualMem::SaveFromCachePixelInterleaved(CPLVirtualMem*,
                   size_t nOffset,
                   const void* pPageToBeEvicted,
                   size_t nToEvicted,
                   void* pUserData)
 {
     const GDALVirtualMem* psParms = (const GDALVirtualMem* )pUserData;
-    (void)ctxt;
     psParms->DoIOPixelInterleaved(GF_Write, nOffset, (void*)pPageToBeEvicted, nToEvicted);
 }
 
@@ -589,13 +586,13 @@ void GDALVirtualMem::Destroy(void* pUserData)
 /*                      GDALCheckBandParameters()                       */
 /************************************************************************/
 
-static int GDALCheckBandParameters( GDALDatasetH hDS,
-                                    int nBandCount, int* panBandMap )
+static bool GDALCheckBandParameters( GDALDatasetH hDS,
+                                     int nBandCount, int* panBandMap )
 {
     if( nBandCount == 0 )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "nBandCount == 0");
-        return FALSE;
+        return false;
     }
 
     if( panBandMap != NULL )
@@ -606,7 +603,7 @@ static int GDALCheckBandParameters( GDALDatasetH hDS,
             {
                 CPLError(CE_Failure, CPLE_AppDefined, "panBandMap[%d]=%d",
                         i, panBandMap[i]);
-                return FALSE;
+                return false;
             }
         }
     }
@@ -614,9 +611,9 @@ static int GDALCheckBandParameters( GDALDatasetH hDS,
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                 "nBandCount > GDALGetRasterCount(hDS)");
-        return FALSE;
+        return false;
     }
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -637,12 +634,11 @@ static CPLVirtualMem* GDALGetVirtualMem( GDALDatasetH hDS,
                                          size_t nCacheSize,
                                          size_t nPageSizeHint,
                                          int bSingleThreadUsage,
-                                         char **papszOptions )
+                                         char ** /*papszOptions*/ )
 {
     CPLVirtualMem* view;
     GDALVirtualMem* psParams;
     GUIntBig nReqMem;
-    (void) papszOptions;
 
     if( nXSize != nBufXSize || nYSize != nBufYSize )
     {
@@ -650,7 +646,7 @@ static CPLVirtualMem* GDALGetVirtualMem( GDALDatasetH hDS,
                  "nXSize != nBufXSize || nYSize != nBufYSize");
         return NULL;
     }
-    
+
     int nRasterXSize = (hDS) ? GDALGetRasterXSize(hDS) : GDALGetRasterBandXSize(hBand);
     int nRasterYSize = (hDS) ? GDALGetRasterYSize(hDS) : GDALGetRasterBandYSize(hBand);
 
@@ -664,7 +660,7 @@ static CPLVirtualMem* GDALGetVirtualMem( GDALDatasetH hDS,
         return NULL;
     }
 
-    if( nPixelSpace < 0 || nLineSpace < 0 || nBandSpace < 0) 
+    if( nPixelSpace < 0 || nLineSpace < 0 || nBandSpace < 0)
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                 "nPixelSpace < 0 || nLineSpace < 0 || nBandSpace < 0");
@@ -674,7 +670,7 @@ static CPLVirtualMem* GDALGetVirtualMem( GDALDatasetH hDS,
     if( hDS != NULL && !GDALCheckBandParameters(hDS, nBandCount, panBandMap ) )
         return NULL;
 
-    int nDataTypeSize = GDALGetDataTypeSize(eBufType) / 8;
+    const int nDataTypeSize = GDALGetDataTypeSizeBytes(eBufType);
     if( nPixelSpace == 0 )
         nPixelSpace = nDataTypeSize;
     if( nLineSpace == 0 )
@@ -700,7 +696,7 @@ static CPLVirtualMem* GDALGetVirtualMem( GDALDatasetH hDS,
         nLineSpace < (GIntBig)nBufXSize * nPixelSpace ||
         (nBandCount > 1 &&
         (nBandSpace == nPixelSpace ||
-        (nBandSpace < nPixelSpace && 
+        (nBandSpace < nPixelSpace &&
          (nBandSpace < nDataTypeSize || nPixelSpace < nBandCount * nBandSpace)) ||
         (nBandSpace > nPixelSpace &&
          (nPixelSpace < nDataTypeSize || nBandSpace < nBufYSize * nLineSpace)))) )
@@ -806,13 +802,15 @@ static CPLVirtualMem* GDALGetVirtualMem( GDALDatasetH hDS,
  * buffer size (nBufXSize x nBufYSize).
  *
  * The nPixelSpace, nLineSpace and nBandSpace parameters allow reading into or
- * writing from various organization of buffers. Arbitrary values for the spacing
- * parameters are not supported. Those values must be multiple of the size of the
- * buffer data type, and must be either band sequential organization (typically
- * nPixelSpace = GDALGetDataTypeSize(eBufType) / 8, nLineSpace = nPixelSpace * nBufXSize,
+ * writing from various organization of buffers. Arbitrary values for the
+ * spacing parameters are not supported. Those values must be multiple of the
+ * size of thebuffer data type, and must be either band sequential
+ * organization (typically nPixelSpace = GDALGetDataTypeSizeBytes(eBufType),
+ * nLineSpace = nPixelSpace * nBufXSize,
  * nBandSpace = nLineSpace * nBufYSize), or pixel-interleaved organization
- * (typically nPixelSpace = nBandSpace * nBandCount, nLineSpace = nPixelSpace * nBufXSize,
- * nBandSpace = GDALGetDataTypeSize(eBufType) / 8)
+ * (typically nPixelSpace = nBandSpace * nBandCount,
+ * nLineSpace = nPixelSpace * nBufXSize,
+ * nBandSpace = GDALGetDataTypeSizeBytes(eBufType))
  *
  * @param hDS Dataset object
  *
@@ -839,10 +837,10 @@ static CPLVirtualMem* GDALGetVirtualMem( GDALDatasetH hDS,
  * pixel values will automatically be translated to/from the GDALRasterBand
  * data type as needed.
  *
- * @param nBandCount the number of bands being read or written. 
+ * @param nBandCount the number of bands being read or written.
  *
  * @param panBandMap the list of nBandCount band numbers being read/written.
- * Note band numbers are 1 based. This may be NULL to select the first 
+ * Note band numbers are 1 based. This may be NULL to select the first
  * nBandCount bands.
  *
  * @param nPixelSpace The byte offset from the start of one pixel value in
@@ -854,7 +852,7 @@ static CPLVirtualMem* GDALGetVirtualMem( GDALDatasetH hDS,
  * eBufType * nBufXSize is used.
  *
  * @param nBandSpace the byte offset from the start of one bands data to the
- * start of the next. If defaulted (0) the value will be 
+ * start of the next. If defaulted (0) the value will be
  * nLineSpace * nBufYSize implying band sequential organization
  * of the data buffer.
  *
@@ -1071,17 +1069,17 @@ public:
 /*                        GDALTiledVirtualMem()                         */
 /************************************************************************/
 
-GDALTiledVirtualMem::GDALTiledVirtualMem( GDALDatasetH hDS,
-                                          GDALRasterBandH hBand,
-                                  int nXOff, int nYOff,
-                                  int nXSize, int nYSize,
-                                  int nTileXSize, int nTileYSize,
-                                  GDALDataType eBufType,
-                                  int nBandCount, const int* panBandMapIn,
-                                  GDALTileOrganization eTileOrganization ):
-    hDS(hDS), hBand(hBand), nXOff(nXOff), nYOff(nYOff), nXSize(nXSize), nYSize(nYSize),
-    nTileXSize(nTileXSize), nTileYSize(nTileYSize), eBufType(eBufType),
-    nBandCount(nBandCount), eTileOrganization(eTileOrganization)
+GDALTiledVirtualMem::GDALTiledVirtualMem( GDALDatasetH hDSIn,
+                                          GDALRasterBandH hBandIn,
+                                  int nXOffIn, int nYOffIn,
+                                  int nXSizeIn, int nYSizeIn,
+                                  int nTileXSizeIn, int nTileYSizeIn,
+                                  GDALDataType eBufTypeIn,
+                                  int nBandCountIn, const int* panBandMapIn,
+                                  GDALTileOrganization eTileOrganizationIn ):
+    hDS(hDSIn), hBand(hBandIn), nXOff(nXOffIn), nYOff(nYOffIn), nXSize(nXSizeIn), nYSize(nYSizeIn),
+    nTileXSize(nTileXSizeIn), nTileYSize(nTileYSizeIn), eBufType(eBufTypeIn),
+    nBandCount(nBandCountIn), eTileOrganization(eTileOrganizationIn)
 {
     if( hDS != NULL )
     {
@@ -1120,7 +1118,7 @@ GDALTiledVirtualMem::~GDALTiledVirtualMem()
 void GDALTiledVirtualMem::DoIO( GDALRWFlag eRWFlag, size_t nOffset,
                                 void* pPage, size_t nBytes ) const
 {
-    int nDataTypeSize = GDALGetDataTypeSize(eBufType) / 8;
+    const int nDataTypeSize = GDALGetDataTypeSizeBytes(eBufType);
     int nTilesPerRow = (nXSize + nTileXSize - 1) / nTileXSize;
     int nTilesPerCol = (nYSize + nTileYSize - 1) / nTileYSize;
     size_t nPageSize = nTileXSize * nTileYSize * nDataTypeSize;
@@ -1150,7 +1148,7 @@ void GDALTiledVirtualMem::DoIO( GDALRWFlag eRWFlag, size_t nOffset,
     else
     {
         //offset = nPageSize * (band * nTilesPerRow * nTilesPerCol + nTile)
-        band = nOffset / (nPageSize * nTilesPerRow * nTilesPerCol);
+        band = static_cast<int>(nOffset / (nPageSize * nTilesPerRow * nTilesPerCol));
         nTile = nOffset / nPageSize - band * nTilesPerRow * nTilesPerCol;
         nPixelSpace = nDataTypeSize;
         nLineSpace = nPixelSpace * nTileXSize;
@@ -1166,25 +1164,27 @@ void GDALTiledVirtualMem::DoIO( GDALRWFlag eRWFlag, size_t nOffset,
         memset(pPage, 0, nBytes);
     if( hDS != NULL )
     {
-        GDALDatasetRasterIO( hDS, eRWFlag,
-                            nXOff + nXTile * nTileXSize, nYOff + nYTile * nTileYSize,
+        CPL_IGNORE_RET_VAL(GDALDatasetRasterIO( hDS, eRWFlag,
+                            static_cast<int>(nXOff + nXTile * nTileXSize),
+                            static_cast<int>(nYOff + nYTile * nTileYSize),
                             nReqXSize, nReqYSize,
                             pPage,
                             nReqXSize, nReqYSize,
                             eBufType,
                             ( eTileOrganization != GTO_BSQ ) ? nBandCount : 1,
                             ( eTileOrganization != GTO_BSQ ) ? panBandMap : &band,
-                            nPixelSpace, nLineSpace, nBandSpace );
+                            nPixelSpace, nLineSpace, nBandSpace ));
     }
     else
     {
-        GDALRasterIO(hBand, eRWFlag,
-                     nXOff + nXTile * nTileXSize, nYOff + nYTile * nTileYSize,
+        CPL_IGNORE_RET_VAL(GDALRasterIO(hBand, eRWFlag,
+                      static_cast<int>(nXOff + nXTile * nTileXSize),
+                      static_cast<int>(nYOff + nYTile * nTileYSize),
                      nReqXSize, nReqYSize,
                      pPage,
                      nReqXSize, nReqYSize,
                      eBufType,
-                     nPixelSpace, nLineSpace );
+                     nPixelSpace, nLineSpace ));
     }
 }
 
@@ -1192,12 +1192,11 @@ void GDALTiledVirtualMem::DoIO( GDALRWFlag eRWFlag, size_t nOffset,
 /*                           FillCache()                                */
 /************************************************************************/
 
-void GDALTiledVirtualMem::FillCache(CPLVirtualMem* ctxt,  size_t nOffset,
+void GDALTiledVirtualMem::FillCache(CPLVirtualMem*,  size_t nOffset,
                                          void* pPageToFill,
                                          size_t nToFill, void* pUserData)
 {
     const GDALTiledVirtualMem* psParms = (const GDALTiledVirtualMem* )pUserData;
-    (void)ctxt;
     psParms->DoIO(GF_Read, nOffset, pPageToFill, nToFill);
 }
 
@@ -1205,12 +1204,11 @@ void GDALTiledVirtualMem::FillCache(CPLVirtualMem* ctxt,  size_t nOffset,
 /*                          SaveFromCache()                             */
 /************************************************************************/
 
-void GDALTiledVirtualMem::SaveFromCache(CPLVirtualMem* ctxt,  size_t nOffset,
+void GDALTiledVirtualMem::SaveFromCache(CPLVirtualMem*,  size_t nOffset,
                                              const void* pPageToBeEvicted,
                                              size_t nToEvicted, void* pUserData)
 {
     const GDALTiledVirtualMem* psParms = (const GDALTiledVirtualMem* )pUserData;
-    (void)ctxt;
     psParms->DoIO(GF_Write, nOffset, (void*)pPageToBeEvicted, nToEvicted);
 }
 
@@ -1239,11 +1237,10 @@ static CPLVirtualMem* GDALGetTiledVirtualMem( GDALDatasetH hDS,
                                               GDALTileOrganization eTileOrganization,
                                               size_t nCacheSize,
                                               int bSingleThreadUsage,
-                                              char **papszOptions )
+                                              char ** /* papszOptions */ )
 {
     CPLVirtualMem* view;
     GDALTiledVirtualMem* psParams;
-    (void) papszOptions;
 
     size_t nPageSize = CPLGetPageSize();
     if( nPageSize == 0 )
@@ -1268,7 +1265,7 @@ static CPLVirtualMem* GDALGetTiledVirtualMem( GDALDatasetH hDS,
     if( hDS != NULL && !GDALCheckBandParameters(hDS, nBandCount, panBandMap ) )
         return NULL;
 
-    int nDataTypeSize = GDALGetDataTypeSize(eBufType) / 8;
+    const int nDataTypeSize = GDALGetDataTypeSizeBytes(eBufType);
     int nTilesPerRow = (nXSize + nTileXSize - 1) / nTileXSize;
     int nTilesPerCol = (nYSize + nTileYSize - 1) / nTileYSize;
     GUIntBig nReqMem = (GUIntBig)nTilesPerRow * nTilesPerCol *
@@ -1339,7 +1336,7 @@ static CPLVirtualMem* GDALGetTiledVirtualMem( GDALDatasetH hDS,
  * "dirty" page) when the cache size limit has been reached.
  *
  * Contrary to GDALDatasetGetVirtualMem(), pixels will be organized by tiles
- * instead of scanlines. Different ways of organizing pixel within/accross tiles
+ * instead of scanlines. Different ways of organizing pixel within/across tiles
  * can be selected with the eTileOrganization parameter.
  *
  * If nXSize is not a multiple of nTileXSize or nYSize is not a multiple of
@@ -1405,10 +1402,10 @@ static CPLVirtualMem* GDALGetTiledVirtualMem( GDALDatasetH hDS,
  * pixel values will automatically be translated to/from the GDALRasterBand
  * data type as needed.
  *
- * @param nBandCount the number of bands being read or written. 
+ * @param nBandCount the number of bands being read or written.
  *
  * @param panBandMap the list of nBandCount band numbers being read/written.
- * Note band numbers are 1 based. This may be NULL to select the first 
+ * Note band numbers are 1 based. This may be NULL to select the first
  * nBandCount bands.
  *
  * @param eTileOrganization tile organization.
diff --git a/gcore/jp2dump.cpp b/gcore/jp2dump.cpp
deleted file mode 100644
index d6cdff5..0000000
--- a/gcore/jp2dump.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/******************************************************************************
- * $Id$
- *
- * Project:  GDAL 
- * Purpose:  Small test utility for dumping jpeg2000 boxes.
- * Author:   Frank Warmerdam, warmerdam at pobox.com
- *
- ******************************************************************************
- * Copyright (c) 2013, Frank Warmerdam <warmerdam at pobox.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "gdaljp2metadata.h"
-
-int main( int argc, char ** argv )
-
-{
-    VSILFILE   *fp;
-
-    if( argc < 2 )
-    {
-        printf( "Usage: jp2dump <filename>\n" );
-        exit( 2 );
-    }
-
-    fp = VSIFOpenL( argv[1], "rb" );
-    if( fp == NULL )
-    {
-        perror( "open" );
-        exit( 1 );
-    }
-
-    GDALJP2Box oBox(fp);
-
-    oBox.ReadFirst();
-    do 
-    {
-        oBox.DumpReadable( stdout );
-    } while( oBox.ReadNext() );
-}
diff --git a/gcore/makefile.vc b/gcore/makefile.vc
index a70bb7b..0a58e24 100644
--- a/gcore/makefile.vc
+++ b/gcore/makefile.vc
@@ -12,7 +12,9 @@ OBJ	=	gdalopeninfo.obj gdaldrivermanager.obj gdaldriver.obj \
 		gdaldllmain.obj gdalexif.obj gdalclientserver.obj \
 		gdalgeorefpamdataset.obj  gdaljp2abstractdataset.obj \
 		gdalvirtualmem.obj gdaloverviewdataset.obj gdalrescaledalphaband.obj \
-		gdaljp2structure.obj gdal_mdreader.obj gdaljp2metadatagenerator.obj
+		gdaljp2structure.obj gdal_mdreader.obj gdaljp2metadatagenerator.obj \
+		gdalabstractbandblockcache.obj \
+		gdalarraybandblockcache.obj gdalhashsetbandblockcache.obj
 
 RES	=	Version.res
 
diff --git a/gcore/mdreader/reader_alos.cpp b/gcore/mdreader/reader_alos.cpp
index 6456f2b..7e5bfb9 100644
--- a/gcore/mdreader/reader_alos.cpp
+++ b/gcore/mdreader/reader_alos.cpp
@@ -157,7 +157,7 @@ GDALMDReaderALOS::~GDALMDReaderALOS()
 /**
  * HasRequiredFiles()
  */
-const bool GDALMDReaderALOS::HasRequiredFiles() const
+bool GDALMDReaderALOS::HasRequiredFiles() const
 {
     if (!m_osIMDSourceFilename.empty())
         return true;
@@ -284,7 +284,7 @@ void GDALMDReaderALOS::LoadMetadata()
     }
 }
 
-static const char *apszRPCTXT20ValItems[] =
+static const char * const apszRPCTXT20ValItems[] =
 {
     RPC_LINE_NUM_COEFF,
     RPC_LINE_DEN_COEFF,
@@ -373,7 +373,7 @@ char** GDALMDReaderALOS::LoadRPCTxtFile()
 /**
  * GetAcqisitionTimeFromString()
  */
-const time_t GDALMDReaderALOS::GetAcquisitionTimeFromString(
+time_t GDALMDReaderALOS::GetAcquisitionTimeFromString(
         const char* pszDateTime)
 {
     if(NULL == pszDateTime)
diff --git a/gcore/mdreader/reader_alos.h b/gcore/mdreader/reader_alos.h
index 4eefb51..ab0e020 100644
--- a/gcore/mdreader/reader_alos.h
+++ b/gcore/mdreader/reader_alos.h
@@ -53,12 +53,12 @@ class GDALMDReaderALOS: public GDALMDReaderBase
 public:
     GDALMDReaderALOS(const char *pszPath, char **papszSiblingFiles);
     virtual ~GDALMDReaderALOS();
-    virtual const bool HasRequiredFiles() const;
+    virtual bool HasRequiredFiles() const;
     virtual char** GetMetadataFiles() const;
 protected:
     virtual void LoadMetadata();
     char** LoadRPCTxtFile();
-    virtual const time_t GetAcquisitionTimeFromString(const char* pszDateTime);
+    virtual time_t GetAcquisitionTimeFromString(const char* pszDateTime);
 protected:
     CPLString m_osIMDSourceFilename;
     CPLString m_osHDRSourceFilename;
diff --git a/gcore/mdreader/reader_digital_globe.cpp b/gcore/mdreader/reader_digital_globe.cpp
index 4d3cfab..458882a 100644
--- a/gcore/mdreader/reader_digital_globe.cpp
+++ b/gcore/mdreader/reader_digital_globe.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: reader_digital_globe.cpp 29145 2015-05-04 10:00:40Z rouault $
+ * $Id: reader_digital_globe.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from DigitalGlobe imagery.
@@ -27,22 +27,22 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
- 
+
 #include "reader_digital_globe.h"
- 
-CPL_CVSID("$Id: reader_digital_globe.cpp 29145 2015-05-04 10:00:40Z rouault $");
+
+CPL_CVSID("$Id: reader_digital_globe.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /**
  * GDALMDReaderDigitalGlobe()
  */
-GDALMDReaderDigitalGlobe::GDALMDReaderDigitalGlobe(const char *pszPath, 
+GDALMDReaderDigitalGlobe::GDALMDReaderDigitalGlobe(const char *pszPath,
         char **papszSiblingFiles) : GDALMDReaderBase(pszPath, papszSiblingFiles)
 {
-    m_osIMDSourceFilename = GDALFindAssociatedFile( pszPath, "IMD", 
+    m_osIMDSourceFilename = GDALFindAssociatedFile( pszPath, "IMD",
+                                                         papszSiblingFiles, 0 );
+    m_osRPBSourceFilename = GDALFindAssociatedFile( pszPath, "RPB",
                                                          papszSiblingFiles, 0 );
-    m_osRPBSourceFilename = GDALFindAssociatedFile( pszPath, "RPB", 
-                                                         papszSiblingFiles, 0 );    
-    m_osXMLSourceFilename = GDALFindAssociatedFile( pszPath, "XML", 
+    m_osXMLSourceFilename = GDALFindAssociatedFile( pszPath, "XML",
                                                          papszSiblingFiles, 0 );
 
     if( m_osIMDSourceFilename.size() )
@@ -58,16 +58,13 @@ GDALMDReaderDigitalGlobe::GDALMDReaderDigitalGlobe(const char *pszPath,
 
 /**
  * ~GDALMDReaderDigitalGlobe()
- */ 
-GDALMDReaderDigitalGlobe::~GDALMDReaderDigitalGlobe()
-{
-    
-}
+ */
+GDALMDReaderDigitalGlobe::~GDALMDReaderDigitalGlobe() {}
 
 /**
  * HasRequiredFiles()
  */
-const bool GDALMDReaderDigitalGlobe::HasRequiredFiles() const
+bool GDALMDReaderDigitalGlobe::HasRequiredFiles() const
 {
     if (!m_osIMDSourceFilename.empty())
         return true;
@@ -89,7 +86,7 @@ void GDALMDReaderDigitalGlobe::LoadMetadata()
 {
     if(m_bIsMetadataLoad)
         return;
-        
+
     if (!m_osIMDSourceFilename.empty())
     {
         m_papszIMDMD = GDALLoadIMDFile( m_osIMDSourceFilename );
@@ -101,9 +98,9 @@ void GDALMDReaderDigitalGlobe::LoadMetadata()
     }
 
     if((NULL == m_papszIMDMD || NULL == m_papszRPCMD) && !m_osXMLSourceFilename.empty())
-    { 
+    {
         CPLXMLNode* psNode = CPLParseXMLFile(m_osXMLSourceFilename);
-       
+
         if(psNode != NULL)
         {
             CPLXMLNode* psisdNode = psNode->psNext;
@@ -121,18 +118,18 @@ void GDALMDReaderDigitalGlobe::LoadMetadata()
     }
 
     m_papszDEFAULTMD = CSLAddNameValue(m_papszDEFAULTMD, MD_NAME_MDTYPE, "DG");
-           
-    m_bIsMetadataLoad = true;      
-    
+
+    m_bIsMetadataLoad = true;
+
     if(NULL == m_papszIMDMD)
     {
         return;
-    }   
+    }
     //extract imagery metadata
     const char* pszSatId = CSLFetchNameValue(m_papszIMDMD, "IMAGE.SATID");
     if(NULL != pszSatId)
     {
-        m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, 
+        m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
                                            MD_NAME_SATELLITE,
                                            CPLStripQuotes(pszSatId));
     }
@@ -146,8 +143,8 @@ void GDALMDReaderDigitalGlobe::LoadMetadata()
                                                CPLStripQuotes(pszSatId));
         }
     }
-    
-    const char* pszCloudCover = CSLFetchNameValue(m_papszIMDMD, 
+
+    const char* pszCloudCover = CSLFetchNameValue(m_papszIMDMD,
                                                   "IMAGE.CLOUDCOVER");
     if(NULL != pszCloudCover)
     {
@@ -181,7 +178,7 @@ void GDALMDReaderDigitalGlobe::LoadMetadata()
             }
         }
     }
-    
+
     const char* pszDateTime = CSLFetchNameValue(m_papszIMDMD,
                                        "IMAGE.FIRSTLINETIME");
     if(NULL != pszDateTime)
@@ -216,13 +213,13 @@ void GDALMDReaderDigitalGlobe::LoadMetadata()
 char** GDALMDReaderDigitalGlobe::GetMetadataFiles() const
 {
     char **papszFileList = NULL;
-    if(!m_osIMDSourceFilename.empty()) 
+    if(!m_osIMDSourceFilename.empty())
         papszFileList = CSLAddString( papszFileList, m_osIMDSourceFilename );
-    if(!m_osRPBSourceFilename.empty()) 
+    if(!m_osRPBSourceFilename.empty())
         papszFileList = CSLAddString( papszFileList, m_osRPBSourceFilename );
-    if(!m_osXMLSourceFilename.empty()) 
+    if(!m_osXMLSourceFilename.empty())
         papszFileList = CSLAddString( papszFileList, m_osXMLSourceFilename );
-    
+
     return papszFileList;
 }
 
@@ -232,7 +229,7 @@ char** GDALMDReaderDigitalGlobe::GetMetadataFiles() const
 char** GDALMDReaderDigitalGlobe::LoadIMDXmlNode(CPLXMLNode* psNode)
 {
     if(NULL == psNode)
-        return NULL;    
+        return NULL;
     char** papszList = NULL;
     return ReadXMLToList(psNode->psChild, papszList);
 }
@@ -240,7 +237,7 @@ char** GDALMDReaderDigitalGlobe::LoadIMDXmlNode(CPLXMLNode* psNode)
 /**
  * GDALLoadRPBXmlNode()
  */
-static const char *apszRPBMap[] = {
+static const char * const apszRPBMap[] = {
     RPC_LINE_OFF,   "image.lineOffset",
     RPC_SAMP_OFF,   "image.sampOffset",
     RPC_LAT_OFF,    "image.latOffset",
@@ -266,7 +263,7 @@ char** GDALMDReaderDigitalGlobe::LoadRPBXmlNode(CPLXMLNode* psNode)
 
     if(NULL == papszList)
         return NULL;
-    
+
     char** papszRPB = NULL;
     for( int i = 0; apszRPBMap[i] != NULL; i += 2 )
     {
@@ -275,6 +272,6 @@ char** GDALMDReaderDigitalGlobe::LoadRPBXmlNode(CPLXMLNode* psNode)
     }
 
     CSLDestroy(papszList);
-      
+
     return papszRPB;
 }
diff --git a/gcore/mdreader/reader_digital_globe.h b/gcore/mdreader/reader_digital_globe.h
index 3cdd6b0..555d21c 100644
--- a/gcore/mdreader/reader_digital_globe.h
+++ b/gcore/mdreader/reader_digital_globe.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: reader_digital_globe.h 29190 2015-05-13 21:40:30Z bishop $
+ * $Id: reader_digital_globe.h 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from DigitalGlobe imagery.
@@ -27,7 +27,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
- 
+
 #ifndef READER_DIGITAL_GLOBE_H_INCLUDED
 #define READER_DIGITAL_GLOBE_H_INCLUDED
 
@@ -59,13 +59,13 @@ class GDALMDReaderDigitalGlobe: public GDALMDReaderBase
 public:
     GDALMDReaderDigitalGlobe(const char *pszPath, char **papszSiblingFiles);
     virtual ~GDALMDReaderDigitalGlobe();
-    virtual const bool HasRequiredFiles() const;
+    virtual bool HasRequiredFiles() const;
     virtual char** GetMetadataFiles() const;
 protected:
     virtual void LoadMetadata();
     char** LoadRPBXmlNode(CPLXMLNode* psNode);
     char** LoadIMDXmlNode(CPLXMLNode* psNode);
-protected:    
+protected:
     CPLString m_osXMLSourceFilename;
     CPLString m_osIMDSourceFilename;
     CPLString m_osRPBSourceFilename;
diff --git a/gcore/mdreader/reader_eros.cpp b/gcore/mdreader/reader_eros.cpp
index af7680a..2b22003 100644
--- a/gcore/mdreader/reader_eros.cpp
+++ b/gcore/mdreader/reader_eros.cpp
@@ -45,7 +45,7 @@ GDALMDReaderEROS::GDALMDReaderEROS(const char *pszPath,
         return;
     for(i = 0; i < osBaseName.size(); i++)
     {
-        if(EQUALN(osBaseName + i, ".", 1))
+        if(STARTS_WITH_CI(osBaseName + i, "."))
         {
             pszPassFileName = CPLFormFilename( osDirName, szMetadataName,
                                                "pass" );
@@ -118,7 +118,7 @@ GDALMDReaderEROS::~GDALMDReaderEROS()
 /**
  * HasRequiredFiles()
  */
-const bool GDALMDReaderEROS::HasRequiredFiles() const
+bool GDALMDReaderEROS::HasRequiredFiles() const
 {
     if (!m_osIMDSourceFilename.empty())
         return true;
@@ -252,7 +252,7 @@ char** GDALMDReaderEROS::LoadImdTxtFile()
 /**
  * GetAcqisitionTimeFromString()
  */
-const time_t GDALMDReaderEROS::GetAcquisitionTimeFromString(
+time_t GDALMDReaderEROS::GetAcquisitionTimeFromString(
         const char* pszDateTime)
 {
     if(NULL == pszDateTime)
@@ -265,7 +265,7 @@ const time_t GDALMDReaderEROS::GetAcquisitionTimeFromString(
     int iMin;
     int iSec;
 
-    // exampe: sweep_start_utc     2013-04-22,11:35:02.50724
+    // example: sweep_start_utc     2013-04-22,11:35:02.50724
 
     int r = sscanf ( pszDateTime, "%d-%d-%d,%d:%d:%d.%*d",
                      &iYear, &iMonth, &iDay, &iHours, &iMin, &iSec);
diff --git a/gcore/mdreader/reader_eros.h b/gcore/mdreader/reader_eros.h
index 3eeca11..1d0be26 100644
--- a/gcore/mdreader/reader_eros.h
+++ b/gcore/mdreader/reader_eros.h
@@ -49,12 +49,12 @@ class GDALMDReaderEROS: public GDALMDReaderBase
 public:
     GDALMDReaderEROS(const char *pszPath, char **papszSiblingFiles);
     virtual ~GDALMDReaderEROS();
-    virtual const bool HasRequiredFiles() const;
+    virtual bool HasRequiredFiles() const;
     virtual char** GetMetadataFiles() const;
 protected:
     virtual void LoadMetadata();
     char** LoadImdTxtFile();
-    virtual const time_t GetAcquisitionTimeFromString(const char* pszDateTime);
+    virtual time_t GetAcquisitionTimeFromString(const char* pszDateTime);
 protected:
     CPLString m_osIMDSourceFilename;
     CPLString m_osRPBSourceFilename;
diff --git a/gcore/mdreader/reader_geo_eye.cpp b/gcore/mdreader/reader_geo_eye.cpp
index 41132f6..5fd3e9b 100644
--- a/gcore/mdreader/reader_geo_eye.cpp
+++ b/gcore/mdreader/reader_geo_eye.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: reader_geo_eye.cpp 29245 2015-05-24 16:46:56Z rouault $
+ * $Id: reader_geo_eye.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from GeoEye imagery.
@@ -27,18 +27,18 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
- 
+
 #include "reader_geo_eye.h"
 
-CPL_CVSID("$Id: reader_geo_eye.cpp 29245 2015-05-24 16:46:56Z rouault $");
+CPL_CVSID("$Id: reader_geo_eye.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /**
  * GDALMDReaderGeoEye()
  */
-GDALMDReaderGeoEye::GDALMDReaderGeoEye(const char *pszPath, 
+GDALMDReaderGeoEye::GDALMDReaderGeoEye(const char *pszPath,
         char **papszSiblingFiles) : GDALMDReaderBase(pszPath, papszSiblingFiles)
 {
-    
+
     const char* pszBaseName = CPLGetBasename(pszPath);
     const char* pszDirName = CPLGetDirname(pszPath);
     size_t nBaseNameLen = strlen(pszBaseName);
@@ -46,19 +46,19 @@ GDALMDReaderGeoEye::GDALMDReaderGeoEye(const char *pszPath,
         return;
 
     // get _metadata.txt file
-    
+
     // split file name by _rgb_ or _pan_
     char szMetadataName[512] = {0};
     size_t i;
     for(i = 0; i < nBaseNameLen; i++)
     {
         szMetadataName[i] = pszBaseName[i];
-        if(EQUALN(pszBaseName + i, "_rgb_", 5) || EQUALN(pszBaseName + i, "_pan_", 5))
+        if(STARTS_WITH_CI(pszBaseName + i, "_rgb_") || STARTS_WITH_CI(pszBaseName + i, "_pan_"))
         {
             break;
         }
     }
-    
+
     // form metadata file name
     CPLStrlcpy(szMetadataName + i, "_metadata.txt", 14);
     const char* pszIMDSourceFilename = CPLFormFilename( pszDirName,
@@ -66,7 +66,7 @@ GDALMDReaderGeoEye::GDALMDReaderGeoEye(const char *pszPath,
     if (CPLCheckForFile((char*)pszIMDSourceFilename, papszSiblingFiles))
     {
         m_osIMDSourceFilename = pszIMDSourceFilename;
-    }                                                     
+    }
     else
     {
         CPLStrlcpy(szMetadataName + i, "_METADATA.TXT", 14);
@@ -78,7 +78,7 @@ GDALMDReaderGeoEye::GDALMDReaderGeoEye(const char *pszPath,
     }
 
     // get _rpc.txt file
-    
+
     const char* pszRPBSourceFilename = CPLFormFilename( pszDirName,
                                                         CPLSPrintf("%s_rpc",
                                                         pszBaseName),
@@ -107,7 +107,7 @@ GDALMDReaderGeoEye::GDALMDReaderGeoEye(const char *pszPath,
 
 /**
  * ~GDALMDReaderGeoEye()
- */ 
+ */
 GDALMDReaderGeoEye::~GDALMDReaderGeoEye()
 {
 }
@@ -115,7 +115,7 @@ GDALMDReaderGeoEye::~GDALMDReaderGeoEye()
 /**
  * HasRequiredFiles()
  */
-const bool GDALMDReaderGeoEye::HasRequiredFiles() const
+bool GDALMDReaderGeoEye::HasRequiredFiles() const
 {
     if (!m_osIMDSourceFilename.empty())
         return true;
@@ -146,7 +146,7 @@ char** GDALMDReaderGeoEye::GetMetadataFiles() const
 void GDALMDReaderGeoEye::LoadMetadata()
 {
     if(m_bIsMetadataLoad)
-        return;        
+        return;
 
     if (!m_osIMDSourceFilename.empty())
     {
@@ -159,14 +159,14 @@ void GDALMDReaderGeoEye::LoadMetadata()
     }
 
     m_papszDEFAULTMD = CSLAddNameValue(m_papszDEFAULTMD, MD_NAME_MDTYPE, "GE");
-           
-    m_bIsMetadataLoad = true;      
-    
+
+    m_bIsMetadataLoad = true;
+
     if(NULL == m_papszIMDMD)
     {
         return;
-    }   
-    
+    }
+
     //extract imagery metadata
     const char* pszSatId = CSLFetchNameValue(m_papszIMDMD,
                                              "Source Image Metadata.Sensor");
@@ -176,7 +176,7 @@ void GDALMDReaderGeoEye::LoadMetadata()
                                            MD_NAME_SATELLITE,
                                            CPLStripQuotes(pszSatId));
     }
-        
+
     const char* pszCloudCover = CSLFetchNameValue(m_papszIMDMD,
                                    "Source Image Metadata.Percent Cloud Cover");
     if(NULL != pszCloudCover)
@@ -184,30 +184,30 @@ void GDALMDReaderGeoEye::LoadMetadata()
         m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
                                            MD_NAME_CLOUDCOVER, pszCloudCover);
     }
-    
+
     const char* pszDateTime = CSLFetchNameValue(m_papszIMDMD,
                                  "Source Image Metadata.Acquisition Date/Time");
-                                         
+
     if(NULL != pszDateTime)
     {
         char buffer[80];
         time_t timeMid = GetAcquisitionTimeFromString(pszDateTime);
 
         strftime (buffer, 80, MD_DATETIMEFORMAT, localtime(&timeMid));
-        m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, 
+        m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
                                            MD_NAME_ACQDATETIME, buffer);
-    }  
+    }
 }
 
 /**
  * GetAcqisitionTimeFromString()
  */
-const time_t GDALMDReaderGeoEye::GetAcquisitionTimeFromString(
+time_t GDALMDReaderGeoEye::GetAcquisitionTimeFromString(
         const char* pszDateTime)
 {
     if(NULL == pszDateTime)
         return 0;
-        
+
     int iYear;
     int iMonth;
     int iDay;
@@ -215,14 +215,14 @@ const time_t GDALMDReaderGeoEye::GetAcquisitionTimeFromString(
     int iMin;
     int iSec = 0;
 
-// string exampe: Acquisition Date/Time: 2006-03-01 11:08 GMT
+    // string example: Acquisition Date/Time: 2006-03-01 11:08 GMT
 
     int r = sscanf ( pszDateTime, "%d-%d-%d %d:%d GMT", &iYear, &iMonth,
                      &iDay, &iHours, &iMin);
 
     if (r != 5)
         return 0;
-    
+
     struct tm tmDateTime;
     tmDateTime.tm_sec = iSec;
     tmDateTime.tm_min = iMin;
@@ -239,7 +239,7 @@ const time_t GDALMDReaderGeoEye::GetAcquisitionTimeFromString(
  * LoadWKTIMDFile()
  */
 char** GDALMDReaderGeoEye::LoadIMDWktFile() const
-{	
+{
     char** papszResultList = NULL;
     char** papszLines = CSLLoad( m_osIMDSourceFilename );
     bool bBeginSection = false;
@@ -257,13 +257,13 @@ char** GDALMDReaderGeoEye::LoadIMDWktFile() const
     {
         // skip section (=== or ---) lines
 
-        if(EQUALN( papszLines[i], "===",3))
+        if(STARTS_WITH_CI(papszLines[i], "==="))
         {
             bBeginSection = true;
             continue;
         }
 
-        if(EQUALN( papszLines[i], "---",3) || CPLStrnlen(papszLines[i], 512) == 0)
+        if(STARTS_WITH_CI(papszLines[i], "---") || CPLStrnlen(papszLines[i], 512) == 0)
             continue;
 
         // check the metadata level
diff --git a/gcore/mdreader/reader_geo_eye.h b/gcore/mdreader/reader_geo_eye.h
index 1d6f26c..7a0074f 100644
--- a/gcore/mdreader/reader_geo_eye.h
+++ b/gcore/mdreader/reader_geo_eye.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: reader_geo_eye.h 29190 2015-05-13 21:40:30Z bishop $
+ * $Id: reader_geo_eye.h 32174 2015-12-14 00:09:26Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from GeoEye imagery.
@@ -27,7 +27,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
- 
+
 #ifndef READER_GEO_EYE_H_INCLUDED
 #define READER_GEO_EYE_H_INCLUDED
 
@@ -52,11 +52,11 @@ class GDALMDReaderGeoEye: public GDALMDReaderBase
 public:
     GDALMDReaderGeoEye(const char *pszPath, char **papszSiblingFiles);
     virtual ~GDALMDReaderGeoEye();
-    virtual const bool HasRequiredFiles() const;
+    virtual bool HasRequiredFiles() const;
     virtual char** GetMetadataFiles() const;
 protected:
     virtual void LoadMetadata();
-    virtual const time_t GetAcquisitionTimeFromString(const char* pszDateTime);
+    virtual time_t GetAcquisitionTimeFromString(const char* pszDateTime);
     char **LoadRPCWktFile() const;
     char **LoadIMDWktFile() const;
 protected:
diff --git a/gcore/mdreader/reader_kompsat.cpp b/gcore/mdreader/reader_kompsat.cpp
index 0f8ae66..ab093c6 100644
--- a/gcore/mdreader/reader_kompsat.cpp
+++ b/gcore/mdreader/reader_kompsat.cpp
@@ -40,7 +40,7 @@ GDALMDReaderKompsat::GDALMDReaderKompsat(const char *pszPath,
                                                          papszSiblingFiles, 0 );
     m_osRPBSourceFilename = GDALFindAssociatedFile( pszPath, "RPC",
                                                          papszSiblingFiles, 0 );
-    
+
     if(m_osIMDSourceFilename.size())
         CPLDebug( "MDReaderDigitalGlobe", "IMD Filename: %s",
               m_osIMDSourceFilename.c_str() );
@@ -59,7 +59,7 @@ GDALMDReaderKompsat::~GDALMDReaderKompsat()
 /**
  * HasRequiredFiles()
  */
-const bool GDALMDReaderKompsat::HasRequiredFiles() const
+bool GDALMDReaderKompsat::HasRequiredFiles() const
 {
     if (!m_osIMDSourceFilename.empty() && !m_osRPBSourceFilename.empty())
         return true;
@@ -179,11 +179,11 @@ char** GDALMDReaderKompsat::ReadTxtToList()
         const char *pszLine = papszLines[i];
 
         //check if this is begin block
-        if(EQUALN(pszLine, "BEGIN_", 6))
+        if(STARTS_WITH_CI(pszLine, "BEGIN_"))
         {
             for(j = 6; j < CPLStrnlen(pszLine, 512); j++)
             {
-                if(EQUALN(pszLine + j, "_BLOCK", 6))
+                if(STARTS_WITH_CI(pszLine + j, "_BLOCK"))
                 {
                     szName[j - 6] = 0;
                     break;
@@ -197,7 +197,7 @@ char** GDALMDReaderKompsat::ReadTxtToList()
         }
 
         //check if this is end block
-        if(EQUALN(pszLine, "END_", 4))
+        if(STARTS_WITH_CI(pszLine, "END_"))
         {
             soGroupName.clear(); // we don't expect subblocks
             continue;
@@ -245,7 +245,7 @@ char** GDALMDReaderKompsat::ReadTxtToList()
 /**
  * GetAcqisitionTimeFromString()
  */
-const time_t GDALMDReaderKompsat::GetAcquisitionTimeFromString(
+time_t GDALMDReaderKompsat::GetAcquisitionTimeFromString(
         const char* pszDateTime)
 {
     if(NULL == pszDateTime)
diff --git a/gcore/mdreader/reader_kompsat.h b/gcore/mdreader/reader_kompsat.h
index d5306ae..52b35d1 100644
--- a/gcore/mdreader/reader_kompsat.h
+++ b/gcore/mdreader/reader_kompsat.h
@@ -50,12 +50,12 @@ class GDALMDReaderKompsat: public GDALMDReaderBase
 public:
     GDALMDReaderKompsat(const char *pszPath, char **papszSiblingFiles);
     virtual ~GDALMDReaderKompsat();
-    virtual const bool HasRequiredFiles() const;
+    virtual bool HasRequiredFiles() const;
     virtual char** GetMetadataFiles() const;
 protected:
     virtual void LoadMetadata();
     char** ReadTxtToList();
-    virtual const time_t GetAcquisitionTimeFromString(const char* pszDateTime);
+    virtual time_t GetAcquisitionTimeFromString(const char* pszDateTime);
 protected:
     CPLString m_osIMDSourceFilename;
     CPLString m_osRPBSourceFilename;
diff --git a/gcore/mdreader/reader_landsat.cpp b/gcore/mdreader/reader_landsat.cpp
index 56c8e7f..de6ace0 100644
--- a/gcore/mdreader/reader_landsat.cpp
+++ b/gcore/mdreader/reader_landsat.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: reader_landsat.cpp 29245 2015-05-24 16:46:56Z rouault $
+ * $Id: reader_landsat.cpp 31120 2015-10-24 19:55:09Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from Landsat imagery.
@@ -30,7 +30,7 @@
 
 #include "reader_landsat.h"
 
-CPL_CVSID("$Id: reader_landsat.cpp 29245 2015-05-24 16:46:56Z rouault $");
+CPL_CVSID("$Id: reader_landsat.cpp 31120 2015-10-24 19:55:09Z rouault $");
 
 /**
  * GDALMDReaderLandsat()
@@ -50,7 +50,7 @@ GDALMDReaderLandsat::GDALMDReaderLandsat(const char *pszPath,
     for(i = 0; i < nBaseNameLen; i++)
     {
         szMetadataName[i] = pszBaseName[i];
-        if(EQUALN(pszBaseName + i, "_B", 2) || EQUALN(pszBaseName + i, "_b", 2))
+        if(STARTS_WITH_CI(pszBaseName + i, "_B") || STARTS_WITH_CI(pszBaseName + i, "_b"))
         {
             break;
         }
@@ -90,7 +90,7 @@ GDALMDReaderLandsat::~GDALMDReaderLandsat()
 /**
  * HasRequiredFiles()
  */
-const bool GDALMDReaderLandsat::HasRequiredFiles() const
+bool GDALMDReaderLandsat::HasRequiredFiles() const
 {
     if (!m_osIMDSourceFilename.empty())
         return true;
diff --git a/gcore/mdreader/reader_landsat.h b/gcore/mdreader/reader_landsat.h
index e54ce43..340dda9 100644
--- a/gcore/mdreader/reader_landsat.h
+++ b/gcore/mdreader/reader_landsat.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: reader_landsat.h 29190 2015-05-13 21:40:30Z bishop $
+ * $Id: reader_landsat.h 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from Landsat imagery.
@@ -38,7 +38,7 @@
 
 TIFF filename:      xxxxxx_aaa.tif
 Metadata filename:  xxxxxx_MTL.txt
-RPC filename:           
+RPC filename:
 
 Common metadata (from metadata filename):
     SatelliteId:         SPACECRAFT_ID
@@ -54,7 +54,7 @@ class GDALMDReaderLandsat: public GDALMDReaderBase
 public:
     GDALMDReaderLandsat(const char *pszPath, char **papszSiblingFiles);
     virtual ~GDALMDReaderLandsat();
-    virtual const bool HasRequiredFiles() const;
+    virtual bool HasRequiredFiles() const;
     virtual char** GetMetadataFiles() const;
 protected:
     virtual void LoadMetadata();
diff --git a/gcore/mdreader/reader_orb_view.cpp b/gcore/mdreader/reader_orb_view.cpp
index c39ead2..2b18a40 100644
--- a/gcore/mdreader/reader_orb_view.cpp
+++ b/gcore/mdreader/reader_orb_view.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: reader_orb_view.cpp 29145 2015-05-04 10:00:40Z rouault $
+ * $Id: reader_orb_view.cpp 29915 2015-08-29 21:29:57Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from OrbView imagery.
@@ -30,7 +30,7 @@
 
 #include "reader_orb_view.h"
 
-CPL_CVSID("$Id: reader_orb_view.cpp 29145 2015-05-04 10:00:40Z rouault $");
+CPL_CVSID("$Id: reader_orb_view.cpp 29915 2015-08-29 21:29:57Z rouault $");
 
 /**
  * GDALMDReaderOrbView()
@@ -80,7 +80,7 @@ GDALMDReaderOrbView::~GDALMDReaderOrbView()
 /**
  * HasRequiredFiles()
  */
-const bool GDALMDReaderOrbView::HasRequiredFiles() const
+bool GDALMDReaderOrbView::HasRequiredFiles() const
 {
     if (!m_osIMDSourceFilename.empty() && !m_osRPBSourceFilename.empty())
         return true;
diff --git a/gcore/mdreader/reader_orb_view.h b/gcore/mdreader/reader_orb_view.h
index 22c727e..c5d9af4 100644
--- a/gcore/mdreader/reader_orb_view.h
+++ b/gcore/mdreader/reader_orb_view.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: reader_orb_view.h 29190 2015-05-13 21:40:30Z bishop $
+ * $Id: reader_orb_view.h 29915 2015-08-29 21:29:57Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from OrbView imagery.
@@ -50,7 +50,7 @@ class GDALMDReaderOrbView: public GDALMDReaderBase
 public:
     GDALMDReaderOrbView(const char *pszPath, char **papszSiblingFiles);
     virtual ~GDALMDReaderOrbView();
-    virtual const bool HasRequiredFiles() const;
+    virtual bool HasRequiredFiles() const;
     virtual char** GetMetadataFiles() const;
 protected:
     virtual void LoadMetadata();
diff --git a/gcore/mdreader/reader_pleiades.cpp b/gcore/mdreader/reader_pleiades.cpp
index ff9aae7..e7551c9 100644
--- a/gcore/mdreader/reader_pleiades.cpp
+++ b/gcore/mdreader/reader_pleiades.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: reader_pleiades.cpp 29417 2015-06-22 08:30:54Z rouault $
+ * $Id: reader_pleiades.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from Pleiades imagery.
@@ -30,7 +30,7 @@
 
 #include "reader_pleiades.h"
 
-CPL_CVSID("$Id: reader_pleiades.cpp 29417 2015-06-22 08:30:54Z rouault $");
+CPL_CVSID("$Id: reader_pleiades.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 /**
  * GDALMDReaderPleiades()
@@ -52,12 +52,12 @@ GDALMDReaderPleiades::GDALMDReaderPleiades(const char *pszPath,
 
     // find last underline
     char sBaseName[512];
-    int nLastUnderline = 0;
+    size_t nLastUnderline = 0;
     for(size_t i = 4; i < nBaseNameLen; i++)
     {
         sBaseName[i - 4] = pszBaseName[i];
         if(pszBaseName[i] == '_')
-            nLastUnderline = i - 4;
+            nLastUnderline = i - 4U;
     }
 
     sBaseName[nLastUnderline] = 0;
@@ -108,7 +108,7 @@ GDALMDReaderPleiades::~GDALMDReaderPleiades()
 /**
  * HasRequiredFiles()
  */
-const bool GDALMDReaderPleiades::HasRequiredFiles() const
+bool GDALMDReaderPleiades::HasRequiredFiles() const
 {
     if (!m_osIMDSourceFilename.empty())
         return true;
@@ -256,7 +256,7 @@ void GDALMDReaderPleiades::LoadMetadata()
  * LoadRPCXmlFile()
  */
 
-static const char *apszRPBMap[] = {
+static const char * const apszRPBMap[] = {
     RPC_LINE_OFF,   "RFM_Validity.LINE_OFF",
     RPC_SAMP_OFF,   "RFM_Validity.SAMP_OFF",
     RPC_LAT_OFF,    "RFM_Validity.LAT_OFF",
@@ -269,7 +269,7 @@ static const char *apszRPBMap[] = {
     RPC_HEIGHT_SCALE,   "RFM_Validity.HEIGHT_SCALE",
     NULL,             NULL };
 
-static const char *apszRPCTXT20ValItems[] =
+static const char * const apszRPCTXT20ValItems[] =
 {
     RPC_LINE_NUM_COEFF,
     RPC_LINE_DEN_COEFF,
@@ -297,7 +297,7 @@ char** GDALMDReaderPleiades::LoadRPCXmlFile()
     if( NULL == papszRawRPCList )
     {
         CPLDestroyXMLNode(pNode);
-        return NULL;        
+        return NULL;
     }
 
     // format list
@@ -321,7 +321,6 @@ char** GDALMDReaderPleiades::LoadRPCXmlFile()
                                     CSLFetchNameValue(papszRawRPCList,
                                                         apszRPBMap[i + 1]));
         }
-	
     }
 
     // merge coefficients
diff --git a/gcore/mdreader/reader_pleiades.h b/gcore/mdreader/reader_pleiades.h
index cdcba6b..d9b5dcf 100644
--- a/gcore/mdreader/reader_pleiades.h
+++ b/gcore/mdreader/reader_pleiades.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: reader_pleiades.h 29190 2015-05-13 21:40:30Z bishop $
+ * $Id: reader_pleiades.h 29915 2015-08-29 21:29:57Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from Pleiades imagery.
@@ -51,7 +51,7 @@ class GDALMDReaderPleiades: public GDALMDReaderBase
 public:
     GDALMDReaderPleiades(const char *pszPath, char **papszSiblingFiles);
     virtual ~GDALMDReaderPleiades();
-    virtual const bool HasRequiredFiles() const;
+    virtual bool HasRequiredFiles() const;
     virtual char** GetMetadataFiles() const;
 protected:
     virtual void LoadMetadata();
diff --git a/gcore/mdreader/reader_rapid_eye.cpp b/gcore/mdreader/reader_rapid_eye.cpp
index beefa37..71c6862 100644
--- a/gcore/mdreader/reader_rapid_eye.cpp
+++ b/gcore/mdreader/reader_rapid_eye.cpp
@@ -72,7 +72,7 @@ GDALMDReaderRapidEye::~GDALMDReaderRapidEye()
 /**
  * HasRequiredFiles()
  */
-const bool GDALMDReaderRapidEye::HasRequiredFiles() const
+bool GDALMDReaderRapidEye::HasRequiredFiles() const
 {
     // check re:EarthObservation
     if (!m_osXMLSourceFilename.empty() &&
diff --git a/gcore/mdreader/reader_rapid_eye.h b/gcore/mdreader/reader_rapid_eye.h
index bf94321..392b3d0 100644
--- a/gcore/mdreader/reader_rapid_eye.h
+++ b/gcore/mdreader/reader_rapid_eye.h
@@ -51,7 +51,7 @@ class GDALMDReaderRapidEye: public GDALMDReaderBase
 public:
     GDALMDReaderRapidEye(const char *pszPath, char **papszSiblingFiles);
     virtual ~GDALMDReaderRapidEye();
-    virtual const bool HasRequiredFiles() const;
+    virtual bool HasRequiredFiles() const;
     virtual char** GetMetadataFiles() const;
 protected:
     virtual void LoadMetadata();
diff --git a/gcore/mdreader/reader_rdk1.cpp b/gcore/mdreader/reader_rdk1.cpp
index 19d7975..c9ac76e 100644
--- a/gcore/mdreader/reader_rdk1.cpp
+++ b/gcore/mdreader/reader_rdk1.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: reader_rdk1.cpp 29145 2015-05-04 10:00:40Z rouault $
+ * $Id: reader_rdk1.cpp 31812 2015-11-28 22:37:37Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from Resurs-DK1 imagery.
@@ -30,7 +30,7 @@
 
 #include "reader_rdk1.h"
 
-CPL_CVSID("$Id: reader_rdk1.cpp 29145 2015-05-04 10:00:40Z rouault $");
+CPL_CVSID("$Id: reader_rdk1.cpp 31812 2015-11-28 22:37:37Z goatbar $");
 
 /**
  * GDALMDReaderResursDK1()
@@ -55,7 +55,7 @@ GDALMDReaderResursDK1::~GDALMDReaderResursDK1()
 /**
  * HasRequiredFiles()
  */
-const bool GDALMDReaderResursDK1::HasRequiredFiles() const
+bool GDALMDReaderResursDK1::HasRequiredFiles() const
 {
     // check <MSP_ROOT>
     if (!m_osXMLSourceFilename.empty() &&
@@ -144,7 +144,7 @@ void GDALMDReaderResursDK1::LoadMetadata()
 /**
  * GetAcqisitionTimeFromString()
  */
-const time_t GDALMDReaderResursDK1::GetAcquisitionTimeFromString(
+time_t GDALMDReaderResursDK1::GetAcquisitionTimeFromString(
         const char* pszDateTime)
 {
     if(NULL == pszDateTime)
@@ -157,7 +157,7 @@ const time_t GDALMDReaderResursDK1::GetAcquisitionTimeFromString(
     int iMin;
     int iSec;
 
-// string exampe: <Normal>
+// string example <Normal>
 //                  tSceneTime = 10:21:36.000000
 //                  dSceneDate = 16/9/2008
 //                </Normal>
diff --git a/gcore/mdreader/reader_rdk1.h b/gcore/mdreader/reader_rdk1.h
index 1859e0c..f1889c8 100644
--- a/gcore/mdreader/reader_rdk1.h
+++ b/gcore/mdreader/reader_rdk1.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: reader_rdk1.h 29190 2015-05-13 21:40:30Z bishop $
+ * $Id: reader_rdk1.h 29915 2015-08-29 21:29:57Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from Resurs-DK1 imagery.
@@ -50,11 +50,11 @@ class GDALMDReaderResursDK1: public GDALMDReaderBase
 public:
     GDALMDReaderResursDK1(const char *pszPath, char **papszSiblingFiles);
     virtual ~GDALMDReaderResursDK1();
-    virtual const bool HasRequiredFiles() const;
+    virtual bool HasRequiredFiles() const;
     virtual char** GetMetadataFiles() const;
 protected:
     virtual void LoadMetadata();
-    virtual const time_t GetAcquisitionTimeFromString(const char* pszDateTime);
+    virtual time_t GetAcquisitionTimeFromString(const char* pszDateTime);
     virtual char** AddXMLNameValueToList(char** papszList, const char *pszName,
                                          const char *pszValue);
 protected:
diff --git a/gcore/mdreader/reader_spot.cpp b/gcore/mdreader/reader_spot.cpp
index f56276a..493c35d 100644
--- a/gcore/mdreader/reader_spot.cpp
+++ b/gcore/mdreader/reader_spot.cpp
@@ -40,7 +40,7 @@ GDALMDReaderSpot::GDALMDReaderSpot(const char *pszPath,
     const char* pszDirName = CPLGetDirname(pszPath);
 
     if(m_osIMDSourceFilename.empty())
-    {        
+    {
         pszIMDSourceFilename = CPLFormFilename( pszDirName, "METADATA.DIM", NULL );
 
         if (CPLCheckForFile((char*)pszIMDSourceFilename, papszSiblingFiles))
diff --git a/gcore/overview.cpp b/gcore/overview.cpp
index 582ffa0..bfdc8eb 100644
--- a/gcore/overview.cpp
+++ b/gcore/overview.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: overview.cpp 29496 2015-07-07 22:29:46Z rouault $
+ * $Id: overview.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Helper code to implement overview support in different drivers.
@@ -28,10 +28,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include <limits>
+
 #include "gdal_priv.h"
 #include "gdalwarper.h"
 
-CPL_CVSID("$Id: overview.cpp 29496 2015-07-07 22:29:46Z rouault $");
+CPL_CVSID("$Id: overview.cpp 33808 2016-03-29 21:15:28Z goatbar $");
 
 /************************************************************************/
 /*                     GDALResampleChunk32R_Near()                      */
@@ -58,13 +60,13 @@ GDALResampleChunk32R_NearT( double dfXRatioDstToSrc,
 /*      Allocate scanline buffer.                                       */
 /* -------------------------------------------------------------------- */
 
-    T* pDstScanline = (T *) VSIMalloc(nDstXWidth * (GDALGetDataTypeSize(eWrkDataType) / 8));
-    int* panSrcXOff = (int*)VSIMalloc(nDstXWidth * sizeof(int));
+    T* pDstScanline = static_cast<T *>(
+        VSI_MALLOC_VERBOSE(
+            nDstXWidth * GDALGetDataTypeSizeBytes(eWrkDataType) ) );
+    int* panSrcXOff = (int*)VSI_MALLOC_VERBOSE(nDstXWidth * sizeof(int));
 
     if( pDstScanline == NULL || panSrcXOff == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory,
-                  "GDALResampleChunk32R: Out of memory for line buffer." );
         VSIFree(pDstScanline);
         VSIFree(panSrcXOff);
         return CE_Failure;
@@ -73,13 +75,9 @@ GDALResampleChunk32R_NearT( double dfXRatioDstToSrc,
 /* ==================================================================== */
 /*      Precompute inner loop constants.                                */
 /* ==================================================================== */
-    int iDstPixel;
-    for( iDstPixel = nDstXOff; iDstPixel < nDstXOff2; iDstPixel++ )
+    for( int iDstPixel = nDstXOff; iDstPixel < nDstXOff2; iDstPixel++ )
     {
-        int   nSrcXOff;
-
-        nSrcXOff =
-            (int) (0.5 + iDstPixel * dfXRatioDstToSrc);
+        int nSrcXOff = (int) (0.5 + iDstPixel * dfXRatioDstToSrc);
         if ( nSrcXOff < nChunkXOff )
             nSrcXOff = nChunkXOff;
 
@@ -103,7 +101,7 @@ GDALResampleChunk32R_NearT( double dfXRatioDstToSrc,
 /* -------------------------------------------------------------------- */
 /*      Loop over destination pixels                                    */
 /* -------------------------------------------------------------------- */
-        for( iDstPixel = 0; iDstPixel < nDstXWidth; iDstPixel++ )
+        for( int iDstPixel = 0; iDstPixel < nDstXWidth; iDstPixel++ )
         {
             pDstScanline[iDstPixel] = pSrcScanline[panSrcXOff[iDstPixel]];
         }
@@ -178,17 +176,18 @@ GDALResampleChunk32R_Near( double dfXRatioDstToSrc,
 /************************************************************************/
 
 static int GDALFindBestEntry(int nEntryCount, const GDALColorEntry* aEntries,
-                             int nR, int nG, int nB)
+                             int nR, int nG, int nB, int nNoDataIndex)
 {
-    int i;
-    int nMinDist = 0;
-    int iBestEntry = 0;
-    for(i=0;i<nEntryCount;i++)
+    int nMinDist = std::numeric_limits<int>::max();
+    int iBestEntry = (nNoDataIndex != 0 || nEntryCount == 1) ? 0 : 1;
+    for( int i=0; i < nEntryCount; i++ )
     {
+        if (i == nNoDataIndex || aEntries[i].c4 == 0)
+            continue;
         int nDist = (nR - aEntries[i].c1) *  (nR - aEntries[i].c1) +
             (nG - aEntries[i].c2) *  (nG - aEntries[i].c2) +
             (nB - aEntries[i].c3) *  (nB - aEntries[i].c3);
-        if (i == 0 || nDist < nMinDist)
+        if (nDist < nMinDist)
         {
             nMinDist = nDist;
             iBestEntry = i;
@@ -198,6 +197,25 @@ static int GDALFindBestEntry(int nEntryCount, const GDALColorEntry* aEntries,
 }
 
 /************************************************************************/
+/*                      ReadColorTableAsArray()                        */
+/************************************************************************/
+
+static bool ReadColorTableAsArray(const GDALColorTable* poColorTable,
+                                  int& nEntryCount,
+                                  GDALColorEntry*& aEntries)
+{
+    nEntryCount = poColorTable->GetColorEntryCount();
+    aEntries = (GDALColorEntry* )VSI_MALLOC2_VERBOSE(sizeof(GDALColorEntry), nEntryCount);
+    if( aEntries == NULL )
+        return false;
+    for(int i=0;i<nEntryCount;i++)
+    {
+        poColorTable->GetColorEntryAsRGB(i, &aEntries[i]);
+    }
+    return true;
+}
+
+/************************************************************************/
 /*                    GDALResampleChunk32R_Average()                    */
 /************************************************************************/
 
@@ -217,21 +235,19 @@ GDALResampleChunk32R_AverageT( double dfXRatioDstToSrc,
                                  int bHasNoData, float fNoDataValue,
                                  GDALColorTable* poColorTable)
 {
-    CPLErr eErr = CE_None;
-
-    int bBit2Grayscale = EQUALN(pszResampling,"AVERAGE_BIT2GRAYSCALE",13);
+    int bBit2Grayscale = STARTS_WITH_CI(pszResampling,"AVERAGE_BIT2G" /* AVERAGE_BIT2GRAYSCALE */);
     if (bBit2Grayscale)
         poColorTable = NULL;
 
-    int nOXSize, nOYSize;
-    T    *pDstScanline;
 
-    T      tNoDataValue = (T)fNoDataValue;
+    T tNoDataValue;
     if (!bHasNoData)
         tNoDataValue = 0;
+    else
+        tNoDataValue = (T)fNoDataValue;
 
-    nOXSize = poOverview->GetXSize();
-    nOYSize = poOverview->GetYSize();
+    int nOXSize = poOverview->GetXSize();
+    int nOYSize = poOverview->GetYSize();
 
     int nChunkRightXOff = nChunkXOff + nChunkXSize;
     int nChunkBottomYOff = nChunkYOff + nChunkYSize;
@@ -241,13 +257,13 @@ GDALResampleChunk32R_AverageT( double dfXRatioDstToSrc,
 /*      Allocate scanline buffer.                                       */
 /* -------------------------------------------------------------------- */
 
-    pDstScanline = (T *) VSIMalloc(nDstXWidth * (GDALGetDataTypeSize(eWrkDataType) / 8));
-    int* panSrcXOffShifted = (int*)VSIMalloc(2 * nDstXWidth * sizeof(int));
+    T *pDstScanline = static_cast<T *>(
+        VSI_MALLOC_VERBOSE(
+            nDstXWidth * GDALGetDataTypeSizeBytes(eWrkDataType) ) );
+    int* panSrcXOffShifted = (int*)VSI_MALLOC_VERBOSE(2 * nDstXWidth * sizeof(int));
 
     if( pDstScanline == NULL || panSrcXOffShifted == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory,
-                  "GDALResampleChunk32R: Out of memory for line buffer." );
         VSIFree(pDstScanline);
         VSIFree(panSrcXOffShifted);
         return CE_Failure;
@@ -255,22 +271,18 @@ GDALResampleChunk32R_AverageT( double dfXRatioDstToSrc,
 
     int nEntryCount = 0;
     GDALColorEntry* aEntries = NULL;
-    if (poColorTable)
+    if(poColorTable && !ReadColorTableAsArray(poColorTable,nEntryCount,aEntries))
     {
-        int i;
-        nEntryCount = poColorTable->GetColorEntryCount();
-        aEntries = (GDALColorEntry* )CPLMalloc(sizeof(GDALColorEntry) * nEntryCount);
-        for(i=0;i<nEntryCount;i++)
-        {
-            poColorTable->GetColorEntryAsRGB(i, &aEntries[i]);
-        }
+        VSIFree(pDstScanline);
+        VSIFree(panSrcXOffShifted);
+        return CE_Failure;
     }
 
 /* ==================================================================== */
 /*      Precompute inner loop constants.                                */
 /* ==================================================================== */
     int iDstPixel;
-    int bSrcXSpacingIsTwo = TRUE;
+    bool bSrcXSpacingIsTwo = true;
     for( iDstPixel = nDstXOff; iDstPixel < nDstXOff2; iDstPixel++ )
     {
         int   nSrcXOff, nSrcXOff2;
@@ -294,21 +306,20 @@ GDALResampleChunk32R_AverageT( double dfXRatioDstToSrc,
         panSrcXOffShifted[2 * (iDstPixel - nDstXOff)] = nSrcXOff - nChunkXOff;
         panSrcXOffShifted[2 * (iDstPixel - nDstXOff) + 1] = nSrcXOff2 - nChunkXOff;
         if (nSrcXOff2 - nSrcXOff != 2)
-            bSrcXSpacingIsTwo = FALSE;
+            bSrcXSpacingIsTwo = false;
     }
 
 /* ==================================================================== */
 /*      Loop over destination scanlines.                                */
 /* ==================================================================== */
+    CPLErr eErr = CE_None;
     for( int iDstLine = nDstYOff; iDstLine < nDstYOff2 && eErr == CE_None; iDstLine++ )
     {
-        int   nSrcYOff, nSrcYOff2 = 0;
-
-        nSrcYOff = (int) (0.5 + iDstLine * dfYRatioDstToSrc);
+        int nSrcYOff = (int) (0.5 + iDstLine * dfYRatioDstToSrc);
         if ( nSrcYOff < nChunkYOff )
             nSrcYOff = nChunkYOff;
 
-        nSrcYOff2 =
+        int nSrcYOff2 =
             (int) (0.5 + (iDstLine+1) * dfYRatioDstToSrc);
         if( nSrcYOff2 == nSrcYOff )
             nSrcYOff2 ++;
@@ -389,16 +400,16 @@ GDALResampleChunk32R_AverageT( double dfXRatioDstToSrc,
 
             for( iDstPixel = 0; iDstPixel < nDstXWidth; iDstPixel++ )
             {
-                int  nSrcXOff = panSrcXOffShifted[2 * iDstPixel],
-                     nSrcXOff2 = panSrcXOffShifted[2 * iDstPixel + 1];
+                const int nSrcXOff = panSrcXOffShifted[2 * iDstPixel];
+                const int nSrcXOff2 = panSrcXOffShifted[2 * iDstPixel + 1];
 
                 T val;
                 int    nTotalR = 0, nTotalG = 0, nTotalB = 0;
-                int    nCount = 0, iX, iY;
+                int    nCount = 0;
 
-                for( iY = nSrcYOff; iY < nSrcYOff2; iY++ )
+                for( int iY = nSrcYOff; iY < nSrcYOff2; iY++ )
                 {
-                    for( iX = nSrcXOff; iX < nSrcXOff2; iX++ )
+                    for( int iX = nSrcXOff; iX < nSrcXOff2; iX++ )
                     {
                         val = pChunk[iX + iY *nChunkXSize];
                         if (bHasNoData == FALSE || val != tNoDataValue)
@@ -423,7 +434,8 @@ GDALResampleChunk32R_AverageT( double dfXRatioDstToSrc,
                         nG = (nTotalG + nCount / 2) / nCount,
                         nB = (nTotalB + nCount / 2) / nCount;
                     pDstScanline[iDstPixel] = (T)GDALFindBestEntry(
-                        nEntryCount, aEntries, nR, nG, nB);
+                        nEntryCount, aEntries, nR, nG, nB,
+                        bHasNoData ? static_cast<int>(tNoDataValue) : -1);
                 }
             }
         }
@@ -447,7 +459,7 @@ GDALResampleChunk32R_Average( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
                         GDALDataType eWrkDataType,
                         void * pChunk,
                         GByte * pabyChunkNodataMask,
-                        int nChunkXOff, int nChunkXSize, 
+                        int nChunkXOff, int nChunkXSize,
                         int nChunkYOff, int nChunkYSize,
                         int nDstXOff, int nDstXOff2,
                         int nDstYOff, int nDstYOff2,
@@ -530,8 +542,6 @@ GDALResampleChunk32R_Gauss( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
 /* -------------------------------------------------------------------- */
 /*      Create the filter kernel and allocate scanline buffer.          */
 /* -------------------------------------------------------------------- */
-    int nOXSize, nOYSize;
-    float    *pafDstScanline;
     int nGaussMatrixDim = 3;
     const int *panGaussMatrix;
     static const int anGaussMatrix3x3[] ={
@@ -554,8 +564,8 @@ GDALResampleChunk32R_Gauss( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
         6,36,90,120,90,36,6,
         1,6,15,20,15,6,1};
 
-    nOXSize = poOverview->GetXSize();
-    nOYSize = poOverview->GetYSize();
+    int nOXSize = poOverview->GetXSize();
+    int nOYSize = poOverview->GetYSize();
     int nResYFactor = (int) (0.5 + dfYRatioDstToSrc);
 
     // matrix for gauss filter
@@ -575,25 +585,19 @@ GDALResampleChunk32R_Gauss( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
         nGaussMatrixDim=7;
     }
 
-    pafDstScanline = (float *) VSIMalloc((nDstXOff2 - nDstXOff) * sizeof(float));
+    float *pafDstScanline
+        = (float *) VSI_MALLOC_VERBOSE((nDstXOff2 - nDstXOff) * sizeof(float));
     if( pafDstScanline == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory,
-                  "GDALResampleChunk32R: Out of memory for line buffer." );
         return CE_Failure;
     }
 
     int nEntryCount = 0;
     GDALColorEntry* aEntries = NULL;
-    if (poColorTable)
+    if(poColorTable && !ReadColorTableAsArray(poColorTable,nEntryCount,aEntries))
     {
-        int i;
-        nEntryCount = poColorTable->GetColorEntryCount();
-        aEntries = (GDALColorEntry* )CPLMalloc(sizeof(GDALColorEntry) * nEntryCount);
-        for(i=0;i<nEntryCount;i++)
-        {
-            poColorTable->GetColorEntryAsRGB(i, &aEntries[i]);
-        }
+        VSIFree(pafDstScanline);
+        return CE_Failure;
     }
 
     int nChunkRightXOff = nChunkXOff + nChunkXSize;
@@ -604,12 +608,8 @@ GDALResampleChunk32R_Gauss( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
 /* ==================================================================== */
     for( int iDstLine = nDstYOff; iDstLine < nDstYOff2 && eErr == CE_None; iDstLine++ )
     {
-        float *pafSrcScanline;
-        GByte *pabySrcScanlineNodataMask;
-        int   nSrcYOff, nSrcYOff2 = 0, iDstPixel;
-
-        nSrcYOff = (int) (0.5 + iDstLine * dfYRatioDstToSrc);
-        nSrcYOff2 = (int) (0.5 + (iDstLine+1) * dfYRatioDstToSrc) + 1;
+        int nSrcYOff = (int) (0.5 + iDstLine * dfYRatioDstToSrc);
+        int nSrcYOff2 = (int) (0.5 + (iDstLine+1) * dfYRatioDstToSrc) + 1;
 
         if( nSrcYOff < nChunkYOff )
         {
@@ -627,11 +627,11 @@ GDALResampleChunk32R_Gauss( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
             nSrcYOff = 0;
         }
 
-
         if( nSrcYOff2 > nChunkBottomYOff || (dfYRatioDstToSrc > 1 && iDstLine == nOYSize-1) )
             nSrcYOff2 = nChunkBottomYOff;
 
-        pafSrcScanline = pafChunk + ((nSrcYOff-nChunkYOff) * nChunkXSize);
+        float *pafSrcScanline = pafChunk + ((nSrcYOff-nChunkYOff) * nChunkXSize);
+        GByte *pabySrcScanlineNodataMask;
         if (pabyChunkNodataMask != NULL)
             pabySrcScanlineNodataMask = pabyChunkNodataMask + ((nSrcYOff-nChunkYOff) * nChunkXSize);
         else
@@ -640,12 +640,11 @@ GDALResampleChunk32R_Gauss( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
 /* -------------------------------------------------------------------- */
 /*      Loop over destination pixels                                    */
 /* -------------------------------------------------------------------- */
+        int  iDstPixel;
         for( iDstPixel = nDstXOff; iDstPixel < nDstXOff2; iDstPixel++ )
         {
-            int   nSrcXOff, nSrcXOff2;
-
-            nSrcXOff = (int) (0.5 + iDstPixel * dfXRatioDstToSrc);
-            nSrcXOff2 = (int)(0.5 + (iDstPixel+1) * dfXRatioDstToSrc) + 1;
+            int nSrcXOff = (int) (0.5 + iDstPixel * dfXRatioDstToSrc);
+            int nSrcXOff2 = (int)(0.5 + (iDstPixel+1) * dfXRatioDstToSrc) + 1;
 
             int iSizeX = nSrcXOff2 - nSrcXOff;
             nSrcXOff = nSrcXOff + iSizeX/2 - nGaussMatrixDim/2;
@@ -663,15 +662,14 @@ GDALResampleChunk32R_Gauss( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
             if (poColorTable == NULL)
             {
                 double dfTotal = 0.0, val;
-                int  nCount = 0, iX, iY;
-                int  i = 0,j = 0;
+                int nCount = 0;
                 const int *panLineWeight = panGaussMatrix +
                     nYShiftGaussMatrix * nGaussMatrixDim + nXShiftGaussMatrix;
 
-                for( j=0, iY = nSrcYOff; iY < nSrcYOff2;
+                for( int j=0, iY = nSrcYOff; iY < nSrcYOff2;
                         iY++, j++, panLineWeight += nGaussMatrixDim )
                 {
-                    for( i=0, iX = nSrcXOff; iX < nSrcXOff2; iX++,++i )
+                    for( int i=0, iX = nSrcXOff; iX < nSrcXOff2; iX++,++i )
                     {
                         val = pafSrcScanline[iX-nChunkXOff+(iY-nSrcYOff)*nChunkXSize];
                         if (pabySrcScanlineNodataMask == NULL ||
@@ -700,15 +698,14 @@ GDALResampleChunk32R_Gauss( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
             {
                 double val;
                 int  nTotalR = 0, nTotalG = 0, nTotalB = 0;
-                int  nTotalWeight = 0, iX, iY;
-                int  i = 0,j = 0;
+                int  nTotalWeight = 0;
                 const int *panLineWeight = panGaussMatrix +
                     nYShiftGaussMatrix * nGaussMatrixDim + nXShiftGaussMatrix;
 
-                for( j=0, iY = nSrcYOff; iY < nSrcYOff2;
+                for( int j=0, iY = nSrcYOff; iY < nSrcYOff2;
                         iY++, j++, panLineWeight += nGaussMatrixDim )
                 {
-                    for( i=0, iX = nSrcXOff; iX < nSrcXOff2; iX++,++i )
+                    for( int i=0, iX = nSrcXOff; iX < nSrcXOff2; iX++,++i )
                     {
                         val = pafSrcScanline[iX-nChunkXOff+(iY-nSrcYOff)*nChunkXSize];
                         if (bHasNoData == FALSE || val != fNoDataValue)
@@ -741,7 +738,7 @@ GDALResampleChunk32R_Gauss( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
                             nB = (nTotalB + nTotalWeight / 2) / nTotalWeight;
                         pafDstScanline[iDstPixel - nDstXOff] =
                             (float) GDALFindBestEntry(
-                                    nEntryCount, aEntries, nR, nG, nB);
+                                    nEntryCount, aEntries, nR, nG, nB, bHasNoData ? (int)fNoDataValue : -1);
                     }
                 }
             }
@@ -781,8 +778,6 @@ GDALResampleChunk32R_Mode( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
                              GDALDataType eSrcDataType)
 
 {
-    CPLErr eErr = CE_None;
-
     float * pafChunk = (float*) pChunk;
 
 /* -------------------------------------------------------------------- */
@@ -794,25 +789,18 @@ GDALResampleChunk32R_Mode( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
     nOXSize = poOverview->GetXSize();
     nOYSize = poOverview->GetYSize();
 
-    pafDstScanline = (float *) VSIMalloc((nDstXOff2 - nDstXOff) * sizeof(float));
+    pafDstScanline = (float *) VSI_MALLOC_VERBOSE((nDstXOff2 - nDstXOff) * sizeof(float));
     if( pafDstScanline == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory,
-                  "GDALResampleChunk32R: Out of memory for line buffer." );
         return CE_Failure;
     }
 
     int nEntryCount = 0;
     GDALColorEntry* aEntries = NULL;
-    if (poColorTable)
+    if(poColorTable && !ReadColorTableAsArray(poColorTable,nEntryCount,aEntries))
     {
-        int i;
-        nEntryCount = poColorTable->GetColorEntryCount();
-        aEntries = (GDALColorEntry* )CPLMalloc(sizeof(GDALColorEntry) * nEntryCount);
-        for(i=0;i<nEntryCount;i++)
-        {
-            poColorTable->GetColorEntryAsRGB(i, &aEntries[i]);
-        }
+        VSIFree(pafDstScanline);
+        return CE_Failure;
     }
 
     int      nMaxNumPx = 0;
@@ -825,17 +813,16 @@ GDALResampleChunk32R_Mode( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
 /* ==================================================================== */
 /*      Loop over destination scanlines.                                */
 /* ==================================================================== */
+    CPLErr eErr = CE_None;
     for( int iDstLine = nDstYOff; iDstLine < nDstYOff2 && eErr == CE_None; iDstLine++ )
     {
-        float *pafSrcScanline;
-        GByte *pabySrcScanlineNodataMask;
-        int   nSrcYOff, nSrcYOff2 = 0, iDstPixel;
+        int iDstPixel;
 
-        nSrcYOff = (int) (0.5 + iDstLine * dfYRatioDstToSrc);
+        int nSrcYOff = (int) (0.5 + iDstLine * dfYRatioDstToSrc);
         if ( nSrcYOff < nChunkYOff )
             nSrcYOff = nChunkYOff;
 
-        nSrcYOff2 =
+        int nSrcYOff2 =
             (int) (0.5 + (iDstLine+1) * dfYRatioDstToSrc);
         if( nSrcYOff2 == nSrcYOff )
             nSrcYOff2 ++;
@@ -847,7 +834,8 @@ GDALResampleChunk32R_Mode( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
             nSrcYOff2 = nChunkBottomYOff;
         }
 
-        pafSrcScanline = pafChunk + ((nSrcYOff-nChunkYOff) * nChunkXSize);
+        float *pafSrcScanline = pafChunk + ((nSrcYOff-nChunkYOff) * nChunkXSize);
+        GByte *pabySrcScanlineNodataMask;
         if (pabyChunkNodataMask != NULL)
             pabySrcScanlineNodataMask = pabyChunkNodataMask + ((nSrcYOff-nChunkYOff) * nChunkXSize);
         else
@@ -858,13 +846,11 @@ GDALResampleChunk32R_Mode( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
 /* -------------------------------------------------------------------- */
         for( iDstPixel = nDstXOff; iDstPixel < nDstXOff2; iDstPixel++ )
         {
-            int   nSrcXOff, nSrcXOff2;
-
-            nSrcXOff =
+            int nSrcXOff =
                 (int) (0.5 + iDstPixel * dfXRatioDstToSrc);
             if ( nSrcXOff < nChunkXOff )
                 nSrcXOff = nChunkXOff;
-            nSrcXOff2 = (int)
+            int nSrcXOff2 = (int)
                 (0.5 + (iDstPixel+1) * dfXRatioDstToSrc);
             if( nSrcXOff2 == nSrcXOff )
                 nSrcXOff2 ++;
@@ -880,12 +866,12 @@ GDALResampleChunk32R_Mode( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
             {
                 /* I'm not sure how much sense it makes to run a majority
                     filter on floating point data, but here it is for the sake
-                    of compatability. It won't look right on RGB images by the
+                    of compatibility. It won't look right on RGB images by the
                     nature of the filter. */
                 int     nNumPx = (nSrcYOff2-nSrcYOff)*(nSrcXOff2-nSrcXOff);
                 int     iMaxInd = 0, iMaxVal = -1, iY, iX;
 
-                if (nNumPx > nMaxNumPx)
+                if (pafVals == NULL || nNumPx > nMaxNumPx)
                 {
                     pafVals = (float*) CPLRealloc(pafVals, nNumPx * sizeof(float));
                     panSums = (int*) CPLRealloc(panSums, nNumPx * sizeof(int));
@@ -936,14 +922,14 @@ GDALResampleChunk32R_Mode( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
             {
                 /* So we go here for a paletted or non-paletted byte band */
                 /* The input values are then between 0 and 255 */
-                int     anVals[256], nMaxVal = 0, iMaxInd = -1, iY, iX;
+                int     anVals[256], nMaxVal = 0, iMaxInd = -1;
 
                 memset(anVals, 0, 256*sizeof(int));
 
-                for( iY = nSrcYOff; iY < nSrcYOff2; ++iY )
+                for( int iY = nSrcYOff; iY < nSrcYOff2; ++iY )
                 {
                     int     iTotYOff = (iY-nSrcYOff)*nChunkXSize-nChunkXOff;
-                    for( iX = nSrcXOff; iX < nSrcXOff2; ++iX )
+                    for( int iX = nSrcXOff; iX < nSrcXOff2; ++iX )
                     {
                         float  val = pafSrcScanline[iX+iTotYOff];
                         if (bHasNoData == FALSE || val != fNoDataValue)
@@ -1389,17 +1375,17 @@ template<> inline void GDALResampleConvolutionHorizontalPixelCountLess8_3rows<GU
 /*                   GDALResampleChunk32R_Convolution()                 */
 /************************************************************************/
 
-template<class T> static CPLErr
+template<class T, int bMultipleBands> static CPLErr
 GDALResampleChunk32R_ConvolutionT( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
                                      double dfSrcXDelta,
                                      double dfSrcYDelta,
-                                     T * pChunk,
+                                     const T * pChunk, int nBands,
                                      GByte * pabyChunkNodataMask,
                                      int nChunkXOff, int nChunkXSize,
                                      int nChunkYOff, int nChunkYSize,
                                      int nDstXOff, int nDstXOff2,
                                      int nDstYOff, int nDstYOff2,
-                                     GDALRasterBand * poOverview,
+                                     GDALRasterBand ** papoDstBands,
                                      int bHasNoData,
                                      float fNoDataValue,
                                      FilterFuncType pfnFilterFunc,
@@ -1408,9 +1394,6 @@ GDALResampleChunk32R_ConvolutionT( double dfXRatioDstToSrc, double dfYRatioDstTo
                                      float fMaxVal )
 
 {
-
-    CPLErr eErr = CE_None;
-
     if (!bHasNoData)
         fNoDataValue = 0.0f;
 
@@ -1426,23 +1409,21 @@ GDALResampleChunk32R_ConvolutionT( double dfXRatioDstToSrc, double dfYRatioDstTo
     double dfYScaleWeight = ( dfYScale >= 1.0 ) ? 1.0 : dfYScale;
     double dfYScaledRadius = nKernelRadius / dfYScaleWeight;
 
-    float* pafDstScanline = (float *) VSIMalloc(nDstXSize * sizeof(float));
+    float* pafDstScanline = (float *) VSI_MALLOC_VERBOSE(nDstXSize * sizeof(float));
 
     /* Temporary array to store result of horizontal filter */
-    double* padfHorizontalFiltered = (double*) VSIMalloc(nChunkYSize * nDstXSize * sizeof(double));
+    double* padfHorizontalFiltered = (double*) VSI_MALLOC_VERBOSE(nChunkYSize * nDstXSize * sizeof(double) * nBands);
 
     /* To store convolution coefficients */
-    double* padfWeightsAlloc = (double*) CPLMalloc((int)(
+    double* padfWeightsAlloc = (double*) VSI_MALLOC_VERBOSE((int)(
         2 + 2 * MAX(dfXScaledRadius, dfYScaledRadius) + 0.5 + 1 /* for alignment*/) * sizeof(double));
 
     GByte* pabyChunkNodataMaskHorizontalFiltered = NULL;
     if( pabyChunkNodataMask )
-        pabyChunkNodataMaskHorizontalFiltered = (GByte*) VSIMalloc(nChunkYSize * nDstXSize);
+        pabyChunkNodataMaskHorizontalFiltered = (GByte*) VSI_MALLOC_VERBOSE(nChunkYSize * nDstXSize);
     if( pafDstScanline == NULL || padfHorizontalFiltered == NULL ||
         padfWeightsAlloc == NULL || (pabyChunkNodataMask != NULL && pabyChunkNodataMaskHorizontalFiltered == NULL) )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory,
-                  "GDALResampleChunk32R_ConvolutionT: Out of memory for work buffers." );
         VSIFree(pafDstScanline);
         VSIFree(padfHorizontalFiltered);
         VSIFree(padfWeightsAlloc);
@@ -1460,7 +1441,7 @@ GDALResampleChunk32R_ConvolutionT( double dfXRatioDstToSrc, double dfYRatioDstTo
 /* ==================================================================== */
     int nChunkRightXOff = nChunkXOff + nChunkXSize;
 #ifdef USE_SSE2
-    int bSrcPixelCountLess8 = dfXScaledRadius < 4;
+    bool bSrcPixelCountLess8 = dfXScaledRadius < 4;
 #endif
     for( int iDstPixel = nDstXOff; iDstPixel < nDstXOff2; iDstPixel++ )
     {
@@ -1506,6 +1487,7 @@ GDALResampleChunk32R_ConvolutionT( double dfXRatioDstToSrc, double dfYRatioDstTo
             dfWeightSum += dfWeight;
         }
 
+        int nHeight = nChunkYSize * nBands;
         if( pabyChunkNodataMask == NULL )
         {
             if( dfWeightSum != 0 )
@@ -1514,12 +1496,11 @@ GDALResampleChunk32R_ConvolutionT( double dfXRatioDstToSrc, double dfYRatioDstTo
                 for(int i=0;i<nSrcPixelCount;i++)
                     padfWeights[i] *= dfInvWeightSum;
             }
-
             int iSrcLineOff = 0;
 #ifdef USE_SSE2
             if( bSrcPixelCountLess8 )
             {
-                for( ; iSrcLineOff+2 < nChunkYSize; iSrcLineOff +=3 )
+                for( ; iSrcLineOff+2 < nHeight; iSrcLineOff +=3 )
                 {
                     int j=iSrcLineOff * nChunkXSize + (nSrcPixelStart - nChunkXOff);
                     double dfVal1, dfVal2, dfVal3;
@@ -1534,7 +1515,7 @@ GDALResampleChunk32R_ConvolutionT( double dfXRatioDstToSrc, double dfYRatioDstTo
             else
 #endif
             {
-                for( ; iSrcLineOff+2 < nChunkYSize; iSrcLineOff +=3 )
+                for( ; iSrcLineOff+2 < nHeight; iSrcLineOff +=3 )
                 {
                     int j=iSrcLineOff * nChunkXSize + (nSrcPixelStart - nChunkXOff);
                     double dfVal1, dfVal2, dfVal3;
@@ -1546,7 +1527,7 @@ GDALResampleChunk32R_ConvolutionT( double dfXRatioDstToSrc, double dfYRatioDstTo
                     padfHorizontalFiltered[(iSrcLineOff+2) * nDstXSize + iDstPixel - nDstXOff] = dfVal3;
                 }
             }
-            for( ; iSrcLineOff < nChunkYSize; iSrcLineOff ++ )
+            for( ; iSrcLineOff < nHeight; iSrcLineOff ++ )
             {
                 int j=iSrcLineOff * nChunkXSize + (nSrcPixelStart - nChunkXOff);
                 double dfVal =
@@ -1557,7 +1538,7 @@ GDALResampleChunk32R_ConvolutionT( double dfXRatioDstToSrc, double dfYRatioDstTo
         }
         else
         {
-            for( int iSrcLineOff = 0; iSrcLineOff < nChunkYSize; iSrcLineOff ++ )
+            for( int iSrcLineOff = 0; iSrcLineOff < nHeight; iSrcLineOff ++ )
             {
                 double dfVal;
                 int j=iSrcLineOff * nChunkXSize + (nSrcPixelStart - nChunkXOff);
@@ -1584,6 +1565,11 @@ GDALResampleChunk32R_ConvolutionT( double dfXRatioDstToSrc, double dfYRatioDstTo
 /* ==================================================================== */
     int nChunkBottomYOff = nChunkYOff + nChunkYSize;
 
+    CPLErr eErr = CE_None;
+
+  for(int iBand=0;iBand< ((bMultipleBands)?nBands:1);iBand++)
+  {
+    const double* padfHorizontalFilteredBand = padfHorizontalFiltered + iBand * nChunkYSize * nDstXSize;
     for( int iDstLine = nDstYOff; iDstLine < nDstYOff2; iDstLine++ )
     {
         double dfSrcLine = (iDstLine+0.5)*dfYRatioDstToSrc + dfSrcYDelta;
@@ -1633,21 +1619,24 @@ GDALResampleChunk32R_ConvolutionT( double dfXRatioDstToSrc, double dfYRatioDstTo
                 for(int i=0;i<nSrcLineCount;i++)
                     padfWeights[i] *= dfInvWeightSum;
             }
+        }
 
+        if( pabyChunkNodataMask == NULL )
+        {
             int iFilteredPixelOff = 0;
             int j=(nSrcLineStart - nChunkYOff) * nDstXSize;
             for( ; iFilteredPixelOff+1 < nDstXSize; iFilteredPixelOff += 2, j+=2 )
             {
                 double dfVal1, dfVal2;
                 GDALResampleConvolutionVertical_2cols(
-                    padfHorizontalFiltered + j, nDstXSize, padfWeights, nSrcLineCount, dfVal1, dfVal2);
+                    padfHorizontalFilteredBand + j, nDstXSize, padfWeights, nSrcLineCount, dfVal1, dfVal2);
                 pafDstScanline[iFilteredPixelOff] = (float)dfVal1;
                 pafDstScanline[iFilteredPixelOff+1] = (float)dfVal2;
             }
             if( iFilteredPixelOff < nDstXSize )
             {
                 double dfVal = GDALResampleConvolutionVertical(
-                    padfHorizontalFiltered + j, nDstXSize, padfWeights, nSrcLineCount);
+                    padfHorizontalFilteredBand + j, nDstXSize, padfWeights, nSrcLineCount);
                 pafDstScanline[iFilteredPixelOff] = (float)dfVal;
             }
         }
@@ -1661,7 +1650,7 @@ GDALResampleChunk32R_ConvolutionT( double dfXRatioDstToSrc, double dfYRatioDstTo
                     i<nSrcLineCount; i++, j+=nDstXSize)
                 {
                     double dfWeight = padfWeights[i] * pabyChunkNodataMaskHorizontalFiltered[j];
-                    dfVal += padfHorizontalFiltered[j] * dfWeight;
+                    dfVal += padfHorizontalFilteredBand[j] * dfWeight;
                     dfWeightSum += dfWeight;
                 }
                 if( dfWeightSum > 0.0 )
@@ -1684,10 +1673,11 @@ GDALResampleChunk32R_ConvolutionT( double dfXRatioDstToSrc, double dfYRatioDstTo
             }
         }
 
-        eErr = poOverview->RasterIO( GF_Write, nDstXOff, iDstLine, nDstXSize, 1,
+        eErr = papoDstBands[iBand]->RasterIO( GF_Write, nDstXOff, iDstLine, nDstXSize, 1,
                                      pafDstScanline, nDstXSize, 1, GDT_Float32,
                                      0, 0, NULL );
     }
+  }
 
     VSIFree( padfWeightsAlloc );
     VSIFree( padfHorizontalFiltered );
@@ -1748,42 +1738,48 @@ static CPLErr GDALResampleChunk32R_Convolution(
     }
 
     if (eWrkDataType == GDT_Byte)
-        return GDALResampleChunk32R_ConvolutionT(dfXRatioDstToSrc, dfYRatioDstToSrc,
+        return GDALResampleChunk32R_ConvolutionT<GByte, FALSE>
+                       (dfXRatioDstToSrc, dfYRatioDstToSrc,
                         dfSrcXDelta, dfSrcYDelta,
-                        (GByte *) pChunk, pabyChunkNodataMask,
-                        nChunkXOff, nChunkXSize, 
+                        (GByte *) pChunk, 1,
+                        pabyChunkNodataMask,
+                        nChunkXOff, nChunkXSize,
                         nChunkYOff, nChunkYSize,
                         nDstXOff, nDstXOff2,
                         nDstYOff, nDstYOff2,
-                        poOverview,
+                        &poOverview,
                         bHasNoData, fNoDataValue,
                         pfnFilterFunc,
                         pfnFilterFunc4Values,
                         nKernelRadius,
                         fMaxVal);
    else if (eWrkDataType == GDT_UInt16)
-        return GDALResampleChunk32R_ConvolutionT(dfXRatioDstToSrc, dfYRatioDstToSrc,
+        return GDALResampleChunk32R_ConvolutionT<GUInt16,FALSE>
+                       (dfXRatioDstToSrc, dfYRatioDstToSrc,
                         dfSrcXDelta, dfSrcYDelta,
-                        (GUInt16 *) pChunk, pabyChunkNodataMask,
-                        nChunkXOff, nChunkXSize, 
+                        (GUInt16 *) pChunk, 1,
+                        pabyChunkNodataMask,
+                        nChunkXOff, nChunkXSize,
                         nChunkYOff, nChunkYSize,
                         nDstXOff, nDstXOff2,
                         nDstYOff, nDstYOff2,
-                        poOverview,
+                        &poOverview,
                         bHasNoData, fNoDataValue,
                         pfnFilterFunc,
                         pfnFilterFunc4Values,
                         nKernelRadius,
                         fMaxVal);
     else if (eWrkDataType == GDT_Float32)
-        return GDALResampleChunk32R_ConvolutionT(dfXRatioDstToSrc, dfYRatioDstToSrc,
+        return GDALResampleChunk32R_ConvolutionT<float,FALSE>
+                       (dfXRatioDstToSrc, dfYRatioDstToSrc,
                         dfSrcXDelta, dfSrcYDelta,
-                        (float *) pChunk, pabyChunkNodataMask,
+                        (float *) pChunk, 1,
+                        pabyChunkNodataMask,
                         nChunkXOff, nChunkXSize,
                         nChunkYOff, nChunkYSize,
                         nDstXOff, nDstXOff2,
                         nDstYOff, nDstYOff2,
-                        poOverview,
+                        &poOverview,
                         bHasNoData, fNoDataValue,
                         pfnFilterFunc,
                         pfnFilterFunc4Values,
@@ -1799,27 +1795,24 @@ static CPLErr GDALResampleChunk32R_Convolution(
 /************************************************************************/
 
 static CPLErr
-GDALResampleChunkC32R( int nSrcWidth, int nSrcHeight, 
+GDALResampleChunkC32R( int nSrcWidth, int nSrcHeight,
                          float * pafChunk, int nChunkYOff, int nChunkYSize,
                          int nDstYOff, int nDstYOff2,
                          GDALRasterBand * poOverview,
                          const char * pszResampling )
-    
+
 {
-    int      nOXSize, nOYSize;
-    float    *pafDstScanline;
     CPLErr   eErr = CE_None;
 
-    nOXSize = poOverview->GetXSize();
-    nOYSize = poOverview->GetYSize();
+    int nOXSize = poOverview->GetXSize();
+    int nOYSize = poOverview->GetYSize();
     double dfXRatioDstToSrc = (double)nSrcWidth / nOXSize;
     double dfYRatioDstToSrc = (double)nSrcHeight / nOYSize;
 
-    pafDstScanline = (float *) VSIMalloc(nOXSize * sizeof(float) * 2);
+    float *pafDstScanline
+        = (float *) VSI_MALLOC_VERBOSE(nOXSize * sizeof(float) * 2);
     if( pafDstScanline == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory,
-                  "GDALResampleChunkC32R: Out of memory for line buffer." );
         return CE_Failure;
     }
 
@@ -1828,14 +1821,11 @@ GDALResampleChunkC32R( int nSrcWidth, int nSrcHeight,
 /* ==================================================================== */
     for( int iDstLine = nDstYOff; iDstLine < nDstYOff2 && eErr == CE_None; iDstLine++ )
     {
-        float *pafSrcScanline;
-        int   nSrcYOff, nSrcYOff2, iDstPixel;
-
-        nSrcYOff = (int) (0.5 + iDstLine * dfYRatioDstToSrc);
+        int nSrcYOff = (int) (0.5 + iDstLine * dfYRatioDstToSrc);
         if( nSrcYOff < nChunkYOff )
             nSrcYOff = nChunkYOff;
-        
-        nSrcYOff2 = (int) (0.5 + (iDstLine+1) * dfYRatioDstToSrc);
+
+        int nSrcYOff2 = (int) (0.5 + (iDstLine+1) * dfYRatioDstToSrc);
         if( nSrcYOff2 == nSrcYOff )
             nSrcYOff2 ++;
 
@@ -1848,17 +1838,17 @@ GDALResampleChunkC32R( int nSrcWidth, int nSrcHeight,
         if( nSrcYOff2 > nChunkYOff + nChunkYSize )
             nSrcYOff2 = nChunkYOff + nChunkYSize;
 
-        pafSrcScanline = pafChunk + ((nSrcYOff-nChunkYOff) * nSrcWidth) * 2;
+        float *pafSrcScanline
+            = pafChunk + ((nSrcYOff-nChunkYOff) * nSrcWidth) * 2;
 
 /* -------------------------------------------------------------------- */
 /*      Loop over destination pixels                                    */
 /* -------------------------------------------------------------------- */
+        int iDstPixel;
         for( iDstPixel = 0; iDstPixel < nOXSize; iDstPixel++ )
         {
-            int   nSrcXOff, nSrcXOff2;
-
-            nSrcXOff = (int) (0.5 + iDstPixel * dfXRatioDstToSrc);
-            nSrcXOff2 = (int) 
+            int nSrcXOff = (int) (0.5 + iDstPixel * dfXRatioDstToSrc);
+            int nSrcXOff2 = (int)
                 (0.5 + (iDstPixel+1) * dfXRatioDstToSrc);
             if( nSrcXOff2 == nSrcXOff )
                 nSrcXOff2 ++;
@@ -1869,7 +1859,7 @@ GDALResampleChunkC32R( int nSrcWidth, int nSrcHeight,
                 nSrcXOff2 = nSrcWidth;
             }
 
-            if( EQUALN(pszResampling,"NEAR",4) )
+            if( STARTS_WITH_CI(pszResampling, "NEAR") )
             {
                 pafDstScanline[iDstPixel*2] = pafSrcScanline[nSrcXOff*2];
                 pafDstScanline[iDstPixel*2+1] = pafSrcScanline[nSrcXOff*2+1];
@@ -1877,23 +1867,21 @@ GDALResampleChunkC32R( int nSrcWidth, int nSrcHeight,
             else if( EQUAL(pszResampling,"AVERAGE_MAGPHASE") )
             {
                 double dfTotalR = 0.0, dfTotalI = 0.0, dfTotalM = 0.0;
-                int    nCount = 0, iX, iY;
+                int    nCount = 0;
 
-                for( iY = nSrcYOff; iY < nSrcYOff2; iY++ )
+                for( int iY = nSrcYOff; iY < nSrcYOff2; iY++ )
                 {
-                    for( iX = nSrcXOff; iX < nSrcXOff2; iX++ )
+                    for( int iX = nSrcXOff; iX < nSrcXOff2; iX++ )
                     {
-                        double  dfR, dfI;
-
-                        dfR = pafSrcScanline[iX*2+(iY-nSrcYOff)*nSrcWidth*2];
-                        dfI = pafSrcScanline[iX*2+(iY-nSrcYOff)*nSrcWidth*2+1];
+                        double dfR = pafSrcScanline[iX*2+(iY-nSrcYOff)*nSrcWidth*2];
+                        double dfI = pafSrcScanline[iX*2+(iY-nSrcYOff)*nSrcWidth*2+1];
                         dfTotalR += dfR;
                         dfTotalI += dfI;
                         dfTotalM += sqrt( dfR*dfR + dfI*dfI );
                         nCount++;
                     }
                 }
-                
+
                 CPLAssert( nCount > 0 );
                 if( nCount == 0 )
                 {
@@ -1902,14 +1890,13 @@ GDALResampleChunkC32R( int nSrcWidth, int nSrcHeight,
                 }
                 else
                 {
-                    double      dfM, dfDesiredM, dfRatio=1.0;
-
                     pafDstScanline[iDstPixel*2  ] = (float) (dfTotalR/nCount);
                     pafDstScanline[iDstPixel*2+1] = (float) (dfTotalI/nCount);
-                    
-                    dfM = sqrt(pafDstScanline[iDstPixel*2  ]*pafDstScanline[iDstPixel*2  ]
+
+                    const double dfM = sqrt(pafDstScanline[iDstPixel*2  ]*pafDstScanline[iDstPixel*2  ]
                              + pafDstScanline[iDstPixel*2+1]*pafDstScanline[iDstPixel*2+1]);
-                    dfDesiredM = dfTotalM / nCount;
+                    const double dfDesiredM = dfTotalM / nCount;
+                    double dfRatio=1.0;
                     if( dfM != 0.0 )
                         dfRatio = dfDesiredM / dfM;
 
@@ -1917,21 +1904,21 @@ GDALResampleChunkC32R( int nSrcWidth, int nSrcHeight,
                     pafDstScanline[iDstPixel*2+1] *= (float) dfRatio;
                 }
             }
-            else if( EQUALN(pszResampling,"AVER",4) )
+            else if( STARTS_WITH_CI(pszResampling, "AVER") )
             {
                 double dfTotalR = 0.0, dfTotalI = 0.0;
-                int    nCount = 0, iX, iY;
+                int nCount = 0;
 
-                for( iY = nSrcYOff; iY < nSrcYOff2; iY++ )
+                for( int iY = nSrcYOff; iY < nSrcYOff2; iY++ )
                 {
-                    for( iX = nSrcXOff; iX < nSrcXOff2; iX++ )
+                    for( int iX = nSrcXOff; iX < nSrcXOff2; iX++ )
                     {
                         dfTotalR += pafSrcScanline[iX*2+(iY-nSrcYOff)*nSrcWidth*2];
                         dfTotalI += pafSrcScanline[iX*2+(iY-nSrcYOff)*nSrcWidth*2+1];
                         nCount++;
                     }
                 }
-                
+
                 CPLAssert( nCount > 0 );
                 if( nCount == 0 )
                 {
@@ -1946,8 +1933,8 @@ GDALResampleChunkC32R( int nSrcWidth, int nSrcHeight,
             }
         }
 
-        eErr = poOverview->RasterIO( GF_Write, 0, iDstLine, nOXSize, 1, 
-                                     pafDstScanline, nOXSize, 1, GDT_CFloat32, 
+        eErr = poOverview->RasterIO( GF_Write, 0, iDstLine, nOXSize, 1,
+                                     pafDstScanline, nOXSize, 1, GDT_CFloat32,
                                      0, 0, NULL );
     }
 
@@ -1964,9 +1951,9 @@ GDALResampleChunkC32R( int nSrcWidth, int nSrcHeight,
 /************************************************************************/
 
 static CPLErr
-GDALRegenerateCascadingOverviews( 
-    GDALRasterBand *poSrcBand, int nOverviews, GDALRasterBand **papoOvrBands, 
-    const char * pszResampling, 
+GDALRegenerateCascadingOverviews(
+    GDALRasterBand *poSrcBand, int nOverviews, GDALRasterBand **papoOvrBands,
+    const char * pszResampling,
     GDALProgressFunc pfnProgress, void * pProgressData )
 
 {
@@ -1974,21 +1961,16 @@ GDALRegenerateCascadingOverviews(
 /*      First, we must put the overviews in order from largest to       */
 /*      smallest.                                                       */
 /* -------------------------------------------------------------------- */
-    int   i, j;
-
-    for( i = 0; i < nOverviews-1; i++ )
+    for( int i = 0; i < nOverviews-1; i++ )
     {
-        for( j = 0; j < nOverviews - i - 1; j++ )
+        for( int j = 0; j < nOverviews - i - 1; j++ )
         {
-
-            if( papoOvrBands[j]->GetXSize() 
+            if( papoOvrBands[j]->GetXSize()
                 * (float) papoOvrBands[j]->GetYSize() <
                 papoOvrBands[j+1]->GetXSize()
                 * (float) papoOvrBands[j+1]->GetYSize() )
             {
-                GDALRasterBand * poTempBand;
-
-                poTempBand = papoOvrBands[j];
+                GDALRasterBand *poTempBand = papoOvrBands[j];
                 papoOvrBands[j] = papoOvrBands[j+1];
                 papoOvrBands[j+1] = poTempBand;
             }
@@ -2001,7 +1983,7 @@ GDALRegenerateCascadingOverviews(
 /* -------------------------------------------------------------------- */
     double       dfTotalPixels = 0.0;
 
-    for( i = 0; i < nOverviews; i++ )
+    for( int i = 0; i < nOverviews; i++ )
     {
         dfTotalPixels += papoOvrBands[i]->GetXSize()
             * (double) papoOvrBands[i]->GetYSize();
@@ -2012,30 +1994,30 @@ GDALRegenerateCascadingOverviews(
 /* -------------------------------------------------------------------- */
     double      dfPixelsProcessed = 0.0;
 
-    for( i = 0; i < nOverviews; i++ )
+    for( int i = 0; i < nOverviews; i++ )
     {
-        void    *pScaledProgressData;
-        double  dfPixels;
         GDALRasterBand *poBaseBand;
-        CPLErr  eErr;
 
         if( i == 0 )
             poBaseBand = poSrcBand;
         else
             poBaseBand = papoOvrBands[i-1];
 
-        dfPixels = papoOvrBands[i]->GetXSize() 
+        double  dfPixels
+            = papoOvrBands[i]->GetXSize()
             * (double) papoOvrBands[i]->GetYSize();
 
-        pScaledProgressData = GDALCreateScaledProgress( 
+        void *pScaledProgressData
+            = GDALCreateScaledProgress(
             dfPixelsProcessed / dfTotalPixels,
-            (dfPixelsProcessed + dfPixels) / dfTotalPixels, 
+            (dfPixelsProcessed + dfPixels) / dfTotalPixels,
             pfnProgress, pProgressData );
 
-        eErr = GDALRegenerateOverviews( (GDALRasterBandH) poBaseBand, 
-                                        1, (GDALRasterBandH *) papoOvrBands+i, 
-                                        pszResampling, 
-                                        GDALScaledProgress, 
+        CPLErr eErr
+            = GDALRegenerateOverviews( (GDALRasterBandH) poBaseBand,
+                                        1, (GDALRasterBandH *) papoOvrBands+i,
+                                        pszResampling,
+                                        GDALScaledProgress,
                                         pScaledProgressData );
         GDALDestroyScaledProgress( pScaledProgressData );
 
@@ -2045,7 +2027,7 @@ GDALRegenerateCascadingOverviews(
         dfPixelsProcessed += dfPixels;
 
         /* we only do the bit2grayscale promotion on the base band */
-        if( EQUALN(pszResampling,"AVERAGE_BIT2GRAYSCALE",13) )
+        if( STARTS_WITH_CI(pszResampling,"AVERAGE_BIT2G" /* AVERAGE_BIT2GRAYSCALE */) )
             pszResampling = "AVERAGE";
     }
 
@@ -2060,16 +2042,16 @@ GDALResampleFunction GDALGetResampleFunction(const char* pszResampling,
                                                  int* pnRadius)
 {
     if( pnRadius ) *pnRadius = 0;
-    if( EQUALN(pszResampling,"NEAR",4) )
+    if( STARTS_WITH_CI(pszResampling, "NEAR") )
         return GDALResampleChunk32R_Near;
-    else if( EQUALN(pszResampling,"AVER",4) )
+    else if( STARTS_WITH_CI(pszResampling, "AVER") )
         return GDALResampleChunk32R_Average;
-    else if( EQUALN(pszResampling,"GAUSS",5) )
+    else if( STARTS_WITH_CI(pszResampling, "GAUSS") )
     {
         if( pnRadius ) *pnRadius = 1;
         return GDALResampleChunk32R_Gauss;
     }
-    else if( EQUALN(pszResampling,"MODE",4) )
+    else if( STARTS_WITH_CI(pszResampling, "MODE") )
         return GDALResampleChunk32R_Mode;
     else if( EQUAL(pszResampling,"CUBIC") )
     {
@@ -2100,6 +2082,154 @@ GDALResampleFunction GDALGetResampleFunction(const char* pszResampling,
     }
 }
 
+#ifdef GDAL_ENABLE_RESAMPLING_MULTIBAND
+
+// For some reason, this does not perform better, and sometimes it performs
+// worse that when operating band after band. Probably due to cache misses
+
+/************************************************************************/
+/*             GDALResampleChunk32RMultiBands_Convolution()             */
+/************************************************************************/
+
+static CPLErr GDALResampleChunk32RMultiBands_Convolution(
+                        double dfXRatioDstToSrc, double dfYRatioDstToSrc,
+                        double dfSrcXDelta,
+                        double dfSrcYDelta,
+                        GDALDataType eWrkDataType,
+                        void * pChunk, int nBands,
+                        GByte * pabyChunkNodataMask,
+                        int nChunkXOff, int nChunkXSize,
+                        int nChunkYOff, int nChunkYSize,
+                        int nDstXOff, int nDstXOff2,
+                        int nDstYOff, int nDstYOff2,
+                        GDALRasterBand **papoDstBands,
+                        const char * pszResampling,
+                        int bHasNoData, float fNoDataValue,
+                        CPL_UNUSED GDALColorTable* poColorTable_unused,
+                        CPL_UNUSED GDALDataType eSrcDataType)
+{
+    GDALResampleAlg eResample;
+    if( EQUAL(pszResampling, "BILINEAR") )
+        eResample = GRA_Bilinear;
+    else if( EQUAL(pszResampling, "CUBIC") )
+        eResample = GRA_Cubic;
+    else if( EQUAL(pszResampling, "CUBICSPLINE") )
+        eResample = GRA_CubicSpline;
+    else if( EQUAL(pszResampling, "LANCZOS") )
+        eResample = GRA_Lanczos;
+    else
+    {
+        CPLAssert(0);
+        return CE_Failure;
+    }
+    int nKernelRadius = GWKGetFilterRadius(eResample);
+    FilterFuncType pfnFilterFunc = GWKGetFilterFunc(eResample);
+    FilterFunc4ValuesType pfnFilterFunc4Values = GWKGetFilterFunc4Values(eResample);
+
+    float fMaxVal = 0.f;
+    // Cubic, etc... can have overshoots, so make sure we clamp values to the
+    // maximum value if NBITS is set
+    const char* pszNBITS = papoDstBands[0]->GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
+    GDALDataType eBandDT = papoDstBands[0]->GetRasterDataType();
+    if( eResample != GRA_Bilinear && pszNBITS != NULL &&
+        (eBandDT == GDT_Byte || eBandDT == GDT_UInt16 || eBandDT == GDT_UInt32) )
+    {
+        int nBits = atoi(pszNBITS);
+        if( nBits == GDALGetDataTypeSize(eBandDT) )
+            nBits = 0;
+        if( nBits )
+            fMaxVal = (float)((1 << nBits) -1);
+    }
+
+    if (eWrkDataType == GDT_Byte)
+        return GDALResampleChunk32R_ConvolutionT<GByte, TRUE>
+                       (dfXRatioDstToSrc, dfYRatioDstToSrc,
+                        dfSrcXDelta, dfSrcYDelta,
+                        (GByte *) pChunk, nBands,
+                        pabyChunkNodataMask,
+                        nChunkXOff, nChunkXSize,
+                        nChunkYOff, nChunkYSize,
+                        nDstXOff, nDstXOff2,
+                        nDstYOff, nDstYOff2,
+                        papoDstBands,
+                        bHasNoData, fNoDataValue,
+                        pfnFilterFunc,
+                        pfnFilterFunc4Values,
+                        nKernelRadius,
+                        fMaxVal);
+   else if (eWrkDataType == GDT_UInt16)
+        return GDALResampleChunk32R_ConvolutionT<GUInt16,TRUE>
+                       (dfXRatioDstToSrc, dfYRatioDstToSrc,
+                        dfSrcXDelta, dfSrcYDelta,
+                        (GUInt16 *) pChunk, nBands,
+                        pabyChunkNodataMask,
+                        nChunkXOff, nChunkXSize,
+                        nChunkYOff, nChunkYSize,
+                        nDstXOff, nDstXOff2,
+                        nDstYOff, nDstYOff2,
+                        papoDstBands,
+                        bHasNoData, fNoDataValue,
+                        pfnFilterFunc,
+                        pfnFilterFunc4Values,
+                        nKernelRadius,
+                        fMaxVal);
+    else if (eWrkDataType == GDT_Float32)
+        return GDALResampleChunk32R_ConvolutionT<float,TRUE>
+                       (dfXRatioDstToSrc, dfYRatioDstToSrc,
+                        dfSrcXDelta, dfSrcYDelta,
+                        (float *) pChunk, nBands,
+                        pabyChunkNodataMask,
+                        nChunkXOff, nChunkXSize,
+                        nChunkYOff, nChunkYSize,
+                        nDstXOff, nDstXOff2,
+                        nDstYOff, nDstYOff2,
+                        papoDstBands,
+                        bHasNoData, fNoDataValue,
+                        pfnFilterFunc,
+                        pfnFilterFunc4Values,
+                        nKernelRadius,
+                        fMaxVal);
+
+    CPLAssert(0);
+    return CE_Failure;
+}
+
+/************************************************************************/
+/*                    GDALGetResampleFunctionMultiBands()               */
+/************************************************************************/
+
+GDALResampleFunctionMultiBands GDALGetResampleFunctionMultiBands(
+                                                 const char* pszResampling,
+                                                 int* pnRadius)
+{
+    if( pnRadius ) *pnRadius = 0;
+    if( EQUAL(pszResampling,"CUBIC") )
+    {
+        if( pnRadius ) *pnRadius = GWKGetFilterRadius(GRA_Cubic);
+        return GDALResampleChunk32RMultiBands_Convolution;
+    }
+    else if( EQUAL(pszResampling,"CUBICSPLINE") )
+    {
+        if( pnRadius ) *pnRadius = GWKGetFilterRadius(GRA_CubicSpline);
+        return GDALResampleChunk32RMultiBands_Convolution;
+    }
+    else if( EQUAL(pszResampling,"LANCZOS") )
+    {
+        if( pnRadius ) *pnRadius = GWKGetFilterRadius(GRA_Lanczos);
+        return GDALResampleChunk32RMultiBands_Convolution;
+    }
+    else if( EQUAL(pszResampling,"BILINEAR") )
+    {
+        if( pnRadius ) *pnRadius = GWKGetFilterRadius(GRA_Bilinear);
+        return GDALResampleChunk32RMultiBands_Convolution;
+    }
+    else
+    {
+        return NULL;
+    }
+}
+#endif
+
 /************************************************************************/
 /*                      GDALGetOvrWorkDataType()                        */
 /************************************************************************/
@@ -2107,16 +2237,16 @@ GDALResampleFunction GDALGetResampleFunction(const char* pszResampling,
 GDALDataType GDALGetOvrWorkDataType(const char* pszResampling,
                                         GDALDataType eSrcDataType)
 {
-    if( (EQUALN(pszResampling,"NEAR",4) ||
-         EQUALN(pszResampling,"AVER",4) ||
+    if( (STARTS_WITH_CI(pszResampling, "NEAR") ||
+         STARTS_WITH_CI(pszResampling, "AVER") ||
          EQUAL(pszResampling,"CUBIC") ||
          EQUAL(pszResampling,"CUBICSPLINE") ||
          EQUAL(pszResampling,"LANCZOS") ||
          EQUAL(pszResampling,"BILINEAR")) &&
         eSrcDataType == GDT_Byte)
         return GDT_Byte;
-    else if( (EQUALN(pszResampling,"NEAR",4) ||
-         EQUALN(pszResampling,"AVER",4) ||
+    else if( (STARTS_WITH_CI(pszResampling, "NEAR") ||
+         STARTS_WITH_CI(pszResampling, "AVER") ||
          EQUAL(pszResampling,"CUBIC") ||
          EQUAL(pszResampling,"CUBICSPLINE") ||
          EQUAL(pszResampling,"LANCZOS") ||
@@ -2140,38 +2270,32 @@ GDALDataType GDALGetOvrWorkDataType(const char* pszResampling,
  * can also be used to generate downsampled images in one file from another
  * outside the overview architecture.
  *
- * The output bands need to exist in advance. 
+ * The output bands need to exist in advance.
  *
- * The full set of resampling algorithms is documented in 
+ * The full set of resampling algorithms is documented in
  * GDALDataset::BuildOverviews().
  *
  * This function will honour properly NODATA_VALUES tuples (special dataset metadata) so
  * that only a given RGB triplet (in case of a RGB image) will be considered as the
- * nodata value and not each value of the triplet independantly per band.
+ * nodata value and not each value of the triplet independently per band.
  *
- * @param hSrcBand the source (base level) band. 
+ * @param hSrcBand the source (base level) band.
  * @param nOverviewCount the number of downsampled bands being generated.
  * @param pahOvrBands the list of downsampled bands to be generated.
- * @param pszResampling Resampling algorithm (eg. "AVERAGE"). 
+ * @param pszResampling Resampling algorithm (e.g. "AVERAGE").
  * @param pfnProgress progress report function.
  * @param pProgressData progress function callback data.
  * @return CE_None on success or CE_Failure on failure.
  */
-CPLErr 
+CPLErr
 GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
-                         int nOverviewCount, GDALRasterBandH *pahOvrBands, 
-                         const char * pszResampling, 
+                         int nOverviewCount, GDALRasterBandH *pahOvrBands,
+                         const char * pszResampling,
                          GDALProgressFunc pfnProgress, void * pProgressData )
 
 {
     GDALRasterBand *poSrcBand = (GDALRasterBand *) hSrcBand;
     GDALRasterBand **papoOvrBands = (GDALRasterBand **) pahOvrBands;
-    int    nFullResYChunk, nWidth, nHeight;
-    int    nFRXBlockSize, nFRYBlockSize;
-    GDALDataType eType;
-    int    bHasNoData;
-    float  fNoDataValue;
-    GDALColorTable* poColorTable = NULL;
 
     if( pfnProgress == NULL )
         pfnProgress = GDALDummyProgress;
@@ -2180,17 +2304,20 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
         return CE_None;
 
     int nKernelRadius;
-    GDALResampleFunction pfnResampleFn = GDALGetResampleFunction(pszResampling,
-                                                                       &nKernelRadius);
+    GDALResampleFunction pfnResampleFn
+        = GDALGetResampleFunction(pszResampling, &nKernelRadius);
+
     if (pfnResampleFn == NULL)
         return CE_Failure;
 
 /* -------------------------------------------------------------------- */
 /*      Check color tables...                                           */
 /* -------------------------------------------------------------------- */
-    if ((EQUALN(pszResampling,"AVER",4)
-         || EQUALN(pszResampling,"MODE",4)
-         || EQUALN(pszResampling,"GAUSS",5)) &&
+    GDALColorTable* poColorTable = NULL;
+
+    if ((STARTS_WITH_CI(pszResampling, "AVER")
+         || STARTS_WITH_CI(pszResampling, "MODE")
+         || STARTS_WITH_CI(pszResampling, "GAUSS")) &&
         poSrcBand->GetColorInterpretation() == GCI_PaletteIndex)
     {
         poColorTable = poSrcBand->GetColorTable();
@@ -2200,16 +2327,17 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
             {
                 CPLError(CE_Warning, CPLE_AppDefined,
                         "Computing overviews on palette index raster bands "
-                        "with a palette whose color interpreation is not RGB "
+                        "with a palette whose color interpretation is not RGB "
                         "will probably lead to unexpected results.");
                 poColorTable = NULL;
             }
         }
         else
         {
-            CPLError(CE_Warning, CPLE_AppDefined,
-                    "Computing overviews on palette index raster bands "
-                    "without a palette will probably lead to unexpected results.");
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Computing overviews on palette index raster bands "
+                      "without a palette will probably lead to unexpected "
+                      "results." );
         }
     }
     // Not ready yet
@@ -2226,13 +2354,13 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
 
 
     /* If we have a nodata mask and we are doing something more complicated */
-    /* than nearest neighbouring, we have to fetch to nodata mask */ 
+    /* than nearest neighbouring, we have to fetch to nodata mask */
 
     GDALRasterBand* poMaskBand = NULL;
     int nMaskFlags = 0;
-    int bUseNoDataMask = FALSE;
+    bool bUseNoDataMask = false;
 
-    if( !EQUALN(pszResampling,"NEAR",4) )
+    if( !STARTS_WITH_CI(pszResampling, "NEAR") )
     {
         /* Special case if we are the alpha band. We want it to be considered */
         /* as the mask band to avoid alpha=0 to be taken into account in average */
@@ -2259,70 +2387,70 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
 
     /* In case the mask made be computed from another band of the dataset, */
     /* we can't use cascaded generation, as the computation of the overviews */
-    /* of the band used for the mask band may not have yet occured (#3033) */
-    if( (EQUALN(pszResampling,"AVER",4) |
-         EQUALN(pszResampling,"GAUSS",5) ||
+    /* of the band used for the mask band may not have yet occurred (#3033) */
+    if( (STARTS_WITH_CI(pszResampling, "AVER") |
+         STARTS_WITH_CI(pszResampling, "GAUSS") ||
          EQUAL(pszResampling,"CUBIC") ||
          EQUAL(pszResampling,"CUBICSPLINE") ||
          EQUAL(pszResampling,"LANCZOS") ||
          EQUAL(pszResampling,"BILINEAR")) && nOverviewCount > 1
          && !(bUseNoDataMask && nMaskFlags != GMF_NODATA))
-        return GDALRegenerateCascadingOverviews( poSrcBand, 
+        return GDALRegenerateCascadingOverviews( poSrcBand,
                                                  nOverviewCount, papoOvrBands,
-                                                 pszResampling, 
+                                                 pszResampling,
                                                  pfnProgress,
                                                  pProgressData );
 
 /* -------------------------------------------------------------------- */
 /*      Setup one horizontal swath to read from the raw buffer.         */
 /* -------------------------------------------------------------------- */
-    void *pChunk;
-    GByte *pabyChunkNodataMask = NULL;
-
+    int nFRXBlockSize, nFRYBlockSize;
     poSrcBand->GetBlockSize( &nFRXBlockSize, &nFRYBlockSize );
-    
+
+    int nFullResYChunk;
     if( nFRYBlockSize < 16 || nFRYBlockSize > 256 )
         nFullResYChunk = 64;
     else
         nFullResYChunk = nFRYBlockSize;
 
+    GDALDataType eType;
     if( GDALDataTypeIsComplex( poSrcBand->GetRasterDataType() ) )
         eType = GDT_CFloat32;
     else
         eType = GDALGetOvrWorkDataType(pszResampling, poSrcBand->GetRasterDataType());
 
-    nWidth = poSrcBand->GetXSize();
-    nHeight = poSrcBand->GetYSize();
-    
+    const int nWidth = poSrcBand->GetXSize();
+    const int nHeight = poSrcBand->GetYSize();
+
     int nMaxOvrFactor = 1;
     for( int iOverview = 0; iOverview < nOverviewCount; iOverview ++ )
     {
-        int nDstWidth = papoOvrBands[iOverview]->GetXSize();
-        int nDstHeight = papoOvrBands[iOverview]->GetYSize();
+        const int nDstWidth = papoOvrBands[iOverview]->GetXSize();
+        const int nDstHeight = papoOvrBands[iOverview]->GetYSize();
         nMaxOvrFactor = MAX( nMaxOvrFactor, (int)((double)nWidth / nDstWidth + 0.5) );
         nMaxOvrFactor = MAX( nMaxOvrFactor, (int)((double)nHeight / nDstHeight + 0.5) );
     }
-    int nMaxChunkYSizeQueried = nFullResYChunk + 2 * nKernelRadius * nMaxOvrFactor;
+    const int nMaxChunkYSizeQueried = nFullResYChunk + 2 * nKernelRadius * nMaxOvrFactor;
 
-    pChunk = 
-        VSIMalloc3((GDALGetDataTypeSize(eType)/8), nMaxChunkYSizeQueried, nWidth );
+    GByte *pabyChunkNodataMask = NULL;
+    void *pChunk =
+        VSI_MALLOC3_VERBOSE(
+            GDALGetDataTypeSizeBytes(eType), nMaxChunkYSizeQueried, nWidth );
     if (bUseNoDataMask)
     {
-        pabyChunkNodataMask = (GByte *) 
-            (GByte*) VSIMalloc2( nMaxChunkYSizeQueried, nWidth );
+        pabyChunkNodataMask =
+            (GByte*) VSI_MALLOC2_VERBOSE( nMaxChunkYSizeQueried, nWidth );
     }
 
     if( pChunk == NULL || (bUseNoDataMask && pabyChunkNodataMask == NULL))
     {
         CPLFree(pChunk);
         CPLFree(pabyChunkNodataMask);
-        CPLError( CE_Failure, CPLE_OutOfMemory, 
-                  "Out of memory in GDALRegenerateOverviews()." );
-
         return CE_Failure;
     }
 
-    fNoDataValue = (float) poSrcBand->GetNoDataValue(&bHasNoData);
+    int bHasNoData;
+    const float fNoDataValue = (float) poSrcBand->GetNoDataValue(&bHasNoData);
 
 /* -------------------------------------------------------------------- */
 /*      Loop over image operating on chunks.                            */
@@ -2330,11 +2458,11 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
     int  nChunkYOff = 0;
     CPLErr eErr = CE_None;
 
-    for( nChunkYOff = 0; 
-         nChunkYOff < nHeight && eErr == CE_None; 
+    for( nChunkYOff = 0;
+         nChunkYOff < nHeight && eErr == CE_None;
          nChunkYOff += nFullResYChunk )
     {
-        if( !pfnProgress( nChunkYOff / (double) nHeight, 
+        if( !pfnProgress( nChunkYOff / (double) nHeight,
                           NULL, pProgressData ) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
@@ -2343,7 +2471,7 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
 
         if( nFullResYChunk + nChunkYOff > nHeight )
             nFullResYChunk = nHeight - nChunkYOff;
-        
+
         int nChunkYOffQueried = nChunkYOff - nKernelRadius * nMaxOvrFactor;
         int nChunkYSizeQueried = nFullResYChunk + 2 * nKernelRadius * nMaxOvrFactor;
         if( nChunkYOffQueried < 0 )
@@ -2356,23 +2484,21 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
 
         /* read chunk */
         if (eErr == CE_None)
-            eErr = poSrcBand->RasterIO( GF_Read, 0, nChunkYOffQueried, nWidth, nChunkYSizeQueried, 
+            eErr = poSrcBand->RasterIO( GF_Read, 0, nChunkYOffQueried, nWidth, nChunkYSizeQueried,
                                 pChunk, nWidth, nChunkYSizeQueried, eType,
                                 0, 0, NULL );
         if (eErr == CE_None && bUseNoDataMask)
-            eErr = poMaskBand->RasterIO( GF_Read, 0, nChunkYOffQueried, nWidth, nChunkYSizeQueried, 
+            eErr = poMaskBand->RasterIO( GF_Read, 0, nChunkYOffQueried, nWidth, nChunkYSizeQueried,
                                 pabyChunkNodataMask, nWidth, nChunkYSizeQueried, GDT_Byte,
                                 0, 0, NULL );
 
         /* special case to promote 1bit data to 8bit 0/255 values */
         if( EQUAL(pszResampling,"AVERAGE_BIT2GRAYSCALE") )
         {
-            int i;
-
             if (eType == GDT_Float32)
             {
                 float* pafChunk = (float*)pChunk;
-                for( i = nChunkYSizeQueried*nWidth - 1; i >= 0; i-- )
+                for( int i = nChunkYSizeQueried*nWidth - 1; i >= 0; i-- )
                 {
                     if( pafChunk[i] == 1.0 )
                         pafChunk[i] = 255.0;
@@ -2381,7 +2507,7 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
             else if (eType == GDT_Byte)
             {
                 GByte* pabyChunk = (GByte*)pChunk;
-                for( i = nChunkYSizeQueried*nWidth - 1; i >= 0; i-- )
+                for( int i = nChunkYSizeQueried*nWidth - 1; i >= 0; i-- )
                 {
                     if( pabyChunk[i] == 1 )
                         pabyChunk[i] = 255;
@@ -2390,7 +2516,7 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
             else if (eType == GDT_UInt16)
             {
                 GUInt16* pasChunk = (GUInt16*)pChunk;
-                for( i = nChunkYSizeQueried*nWidth - 1; i >= 0; i-- )
+                for( int i = nChunkYSizeQueried*nWidth - 1; i >= 0; i-- )
                 {
                     if( pasChunk[i] == 1 )
                         pasChunk[i] = 255;
@@ -2402,12 +2528,10 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
         }
         else if( EQUAL(pszResampling,"AVERAGE_BIT2GRAYSCALE_MINISWHITE") )
         {
-            int i;
-
             if (eType == GDT_Float32)
             {
                 float* pafChunk = (float*)pChunk;
-                for( i = nChunkYSizeQueried*nWidth - 1; i >= 0; i-- )
+                for( int i = nChunkYSizeQueried*nWidth - 1; i >= 0; i-- )
                 {
                     if( pafChunk[i] == 1.0 )
                         pafChunk[i] = 0.0;
@@ -2418,7 +2542,7 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
             else if (eType == GDT_Byte)
             {
                 GByte* pabyChunk = (GByte*)pChunk;
-                for( i = nChunkYSizeQueried*nWidth - 1; i >= 0; i-- )
+                for( int i = nChunkYSizeQueried*nWidth - 1; i >= 0; i-- )
                 {
                     if( pabyChunk[i] == 1 )
                         pabyChunk[i] = 0;
@@ -2429,7 +2553,7 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
             else if (eType == GDT_UInt16)
             {
                 GUInt16* pasChunk = (GUInt16*)pChunk;
-                for( i = nChunkYSizeQueried*nWidth - 1; i >= 0; i-- )
+                for( int i = nChunkYSizeQueried*nWidth - 1; i >= 0; i-- )
                 {
                     if( pasChunk[i] == 1 )
                         pasChunk[i] = 0;
@@ -2444,11 +2568,11 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
 
         for( int iOverview = 0; iOverview < nOverviewCount && eErr == CE_None; iOverview++ )
         {
-            int nDstWidth = papoOvrBands[iOverview]->GetXSize();
-            int nDstHeight = papoOvrBands[iOverview]->GetYSize();
+            const int nDstWidth = papoOvrBands[iOverview]->GetXSize();
+            const int nDstHeight = papoOvrBands[iOverview]->GetYSize();
 
-            double dfXRatioDstToSrc = (double)nWidth / nDstWidth;
-            double dfYRatioDstToSrc = (double)nHeight / nDstHeight;
+            const double dfXRatioDstToSrc = (double)nWidth / nDstWidth;
+            const double dfYRatioDstToSrc = (double)nHeight / nDstHeight;
 
 /* -------------------------------------------------------------------- */
 /*      Figure out the line to start writing to, and the first line     */
@@ -2478,7 +2602,7 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
                                               bHasNoData, fNoDataValue, poColorTable,
                                               poSrcBand->GetRasterDataType());
             else
-                eErr = GDALResampleChunkC32R(nWidth, nHeight, 
+                eErr = GDALResampleChunkC32R(nWidth, nHeight,
                                                (float*)pChunk,
                                                nChunkYOffQueried, nChunkYSizeQueried,
                                                nDstYOff, nDstYOff2,
@@ -2488,14 +2612,14 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
 
     VSIFree( pChunk );
     VSIFree( pabyChunkNodataMask );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Renormalized overview mean / stddev if needed.                  */
 /* -------------------------------------------------------------------- */
     if( eErr == CE_None && EQUAL(pszResampling,"AVERAGE_MP") )
     {
-        GDALOverviewMagnitudeCorrection( (GDALRasterBandH) poSrcBand, 
-                                         nOverviewCount, 
+        GDALOverviewMagnitudeCorrection( (GDALRasterBandH) poSrcBand,
+                                         nOverviewCount,
                                          (GDALRasterBandH *) papoOvrBands,
                                          GDALDummyProgress, NULL );
     }
@@ -2503,8 +2627,8 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
 /* -------------------------------------------------------------------- */
 /*      It can be important to flush out data to overviews.             */
 /* -------------------------------------------------------------------- */
-    for( int iOverview = 0; 
-         eErr == CE_None && iOverview < nOverviewCount; 
+    for( int iOverview = 0;
+         eErr == CE_None && iOverview < nOverviewCount;
          iOverview++ )
     {
         eErr = papoOvrBands[iOverview]->FlushCache();
@@ -2523,7 +2647,7 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
 /************************************************************************/
 
 /**
- * \brief Variant of GDALRegenerateOverviews, specialy dedicated for generating
+ * \brief Variant of GDALRegenerateOverviews, specially dedicated for generating
  * compressed pixel-interleaved overviews (JPEG-IN-TIFF for example)
  *
  * This function will generate one or more overview images from a base
@@ -2547,7 +2671,7 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
  *
  * This function will honour properly NODATA_VALUES tuples (special dataset metadata) so
  * that only a given RGB triplet (in case of a RGB image) will be considered as the
- * nodata value and not each value of the triplet independantly per band.
+ * nodata value and not each value of the triplet independently per band.
  *
  * @param nBands the number of bands, size of papoSrcBands and size of
  *               first dimension of papapoOverviewBands
@@ -2555,22 +2679,19 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
  * @param nOverviews the number of downsampled overview levels being generated.
  * @param papapoOverviewBands bidimension array of bands. First dimension is indexed
  *                            by nBands. Second dimension is indexed by nOverviews.
- * @param pszResampling Resampling algorithm ("NEAREST", "AVERAGE" or "GAUSS"). 
+ * @param pszResampling Resampling algorithm ("NEAREST", "AVERAGE" or "GAUSS").
  * @param pfnProgress progress report function.
  * @param pProgressData progress function callback data.
  * @return CE_None on success or CE_Failure on failure.
  */
 
-CPLErr 
+CPLErr
 GDALRegenerateOverviewsMultiBand(int nBands, GDALRasterBand** papoSrcBands,
                                  int nOverviews,
                                  GDALRasterBand*** papapoOverviewBands,
-                                 const char * pszResampling, 
+                                 const char * pszResampling,
                                  GDALProgressFunc pfnProgress, void * pProgressData )
 {
-    CPLErr eErr = CE_None;
-    int iOverview, iBand;
-
     if( pfnProgress == NULL )
         pfnProgress = GDALDummyProgress;
 
@@ -2578,7 +2699,7 @@ GDALRegenerateOverviewsMultiBand(int nBands, GDALRasterBand** papoSrcBands,
         return CE_None;
 
     /* Sanity checks */
-    if (!EQUALN(pszResampling, "NEAR", 4) &&
+    if (!STARTS_WITH_CI(pszResampling, "NEAR") &&
         !EQUAL(pszResampling, "AVERAGE") &&
         !EQUAL(pszResampling, "GAUSS") &&
         !EQUAL(pszResampling, "CUBIC") &&
@@ -2600,7 +2721,7 @@ GDALRegenerateOverviewsMultiBand(int nBands, GDALRasterBand** papoSrcBands,
     int nSrcWidth = papoSrcBands[0]->GetXSize();
     int nSrcHeight = papoSrcBands[0]->GetYSize();
     GDALDataType eDataType = papoSrcBands[0]->GetRasterDataType();
-    for(iBand=1;iBand<nBands;iBand++)
+    for(int iBand=1;iBand<nBands;iBand++)
     {
         if (papoSrcBands[iBand]->GetXSize() != nSrcWidth ||
             papoSrcBands[iBand]->GetYSize() != nSrcHeight)
@@ -2617,11 +2738,11 @@ GDALRegenerateOverviewsMultiBand(int nBands, GDALRasterBand** papoSrcBands,
         }
     }
 
-    for(iOverview=0;iOverview<nOverviews;iOverview++)
+    for(int iOverview=0;iOverview<nOverviews;iOverview++)
     {
         int nDstWidth = papapoOverviewBands[0][iOverview]->GetXSize();
         int nDstHeight = papapoOverviewBands[0][iOverview]->GetYSize();
-        for(iBand=1;iBand<nBands;iBand++)
+        for(int iBand=1;iBand<nBands;iBand++)
         {
             if (papapoOverviewBands[iBand][iOverview]->GetXSize() != nDstWidth ||
                 papapoOverviewBands[iBand][iOverview]->GetYSize() != nDstHeight)
@@ -2641,7 +2762,7 @@ GDALRegenerateOverviewsMultiBand(int nBands, GDALRasterBand** papoSrcBands,
 
     /* First pass to compute the total number of pixels to read */
     double dfTotalPixelCount = 0;
-    for(iOverview=0;iOverview<nOverviews;iOverview++)
+    for(int iOverview=0;iOverview<nOverviews;iOverview++)
     {
         nSrcWidth = papoSrcBands[0]->GetXSize();
         nSrcHeight = papoSrcBands[0]->GetYSize();
@@ -2664,14 +2785,20 @@ GDALRegenerateOverviewsMultiBand(int nBands, GDALRasterBand** papoSrcBands,
     GDALDataType eWrkDataType = GDALGetOvrWorkDataType(pszResampling, eDataType);
 
     /* If we have a nodata mask and we are doing something more complicated */
-    /* than nearest neighbouring, we have to fetch to nodata mask */ 
-    int bUseNoDataMask = (!EQUALN(pszResampling,"NEAR",4) &&
+    /* than nearest neighbouring, we have to fetch to nodata mask */
+    bool bUseNoDataMask = (!STARTS_WITH_CI(pszResampling, "NEAR") &&
                           (papoSrcBands[0]->GetMaskFlags() & GMF_ALL_VALID) == 0);
 
-    int* pabHasNoData = (int*)CPLMalloc(nBands * sizeof(int));
-    float* pafNoDataValue = (float*)CPLMalloc(nBands * sizeof(float));
+    int* pabHasNoData = (int*)VSI_MALLOC_VERBOSE(nBands * sizeof(int));
+    float* pafNoDataValue = (float*)VSI_MALLOC_VERBOSE(nBands * sizeof(float));
+    if( pabHasNoData == NULL || pafNoDataValue == NULL )
+    {
+        CPLFree(pabHasNoData);
+        CPLFree(pafNoDataValue);
+        return CE_Failure;
+    }
 
-    for(iBand=0;iBand<nBands;iBand++)
+    for(int iBand=0;iBand<nBands;iBand++)
     {
         pabHasNoData[iBand] = FALSE;
         pafNoDataValue[iBand] = (float) papoSrcBands[iBand]->GetNoDataValue(&pabHasNoData[iBand]);
@@ -2679,7 +2806,8 @@ GDALRegenerateOverviewsMultiBand(int nBands, GDALRasterBand** papoSrcBands,
 
     /* Second pass to do the real job ! */
     double dfCurPixelCount = 0;
-    for(iOverview=0;iOverview<nOverviews && eErr == CE_None;iOverview++)
+    CPLErr eErr = CE_None;
+    for(int iOverview=0;iOverview<nOverviews && eErr == CE_None;iOverview++)
     {
         int iSrcOverview = -1; /* -1 means the source bands */
 
@@ -2701,8 +2829,8 @@ GDALRegenerateOverviewsMultiBand(int nBands, GDALRasterBand** papoSrcBands,
         double dfXRatioDstToSrc = (double)nSrcWidth / nDstWidth;
         double dfYRatioDstToSrc = (double)nSrcHeight / nDstHeight;
 
-        /* Compute the maximum chunck size of the source such as it will match the size of */
-        /* a block of the overview */
+        // Compute the maximum chunk size of the source such as it will match
+        // the size of a block of the overview.
         int nFullResXChunk = 1 + (int)(nDstBlockXSize * dfXRatioDstToSrc);
         int nFullResYChunk = 1 + (int)(nDstBlockYSize * dfYRatioDstToSrc);
 
@@ -2712,11 +2840,20 @@ GDALRegenerateOverviewsMultiBand(int nBands, GDALRasterBand** papoSrcBands,
         int nFullResXChunkQueried = nFullResXChunk + 2 * nKernelRadius * nOvrFactor;
         int nFullResYChunkQueried = nFullResYChunk + 2 * nKernelRadius * nOvrFactor;
 
-        void** papaChunk = (void**) CPLMalloc(nBands * sizeof(void*));
+        void** papaChunk = (void**) VSI_MALLOC_VERBOSE(nBands * sizeof(void*));
+        if( papaChunk == NULL )
+        {
+            CPLFree(pabHasNoData);
+            CPLFree(pafNoDataValue);
+            return CE_Failure;
+        }
         GByte* pabyChunkNoDataMask = NULL;
-        for(iBand=0;iBand<nBands;iBand++)
+        for(int iBand=0;iBand<nBands;iBand++)
         {
-            papaChunk[iBand] = VSIMalloc3(nFullResXChunkQueried, nFullResYChunkQueried, GDALGetDataTypeSize(eWrkDataType) / 8);
+            papaChunk[iBand] = VSI_MALLOC3_VERBOSE(
+                nFullResXChunkQueried,
+                nFullResYChunkQueried,
+                GDALGetDataTypeSizeBytes(eWrkDataType) );
             if( papaChunk[iBand] == NULL )
             {
                 while ( --iBand >= 0)
@@ -2724,27 +2861,21 @@ GDALRegenerateOverviewsMultiBand(int nBands, GDALRasterBand** papoSrcBands,
                 CPLFree(papaChunk);
                 CPLFree(pabHasNoData);
                 CPLFree(pafNoDataValue);
-
-                CPLError( CE_Failure, CPLE_OutOfMemory,
-                        "GDALRegenerateOverviewsMultiBand: Out of memory." );
                 return CE_Failure;
             }
         }
         if (bUseNoDataMask)
         {
-            pabyChunkNoDataMask = (GByte*) VSIMalloc2(nFullResXChunkQueried, nFullResYChunkQueried);
+            pabyChunkNoDataMask = (GByte*) VSI_MALLOC2_VERBOSE(nFullResXChunkQueried, nFullResYChunkQueried);
             if( pabyChunkNoDataMask == NULL )
             {
-                for(iBand=0;iBand<nBands;iBand++)
+                for(int iBand=0;iBand<nBands;iBand++)
                 {
                     CPLFree(papaChunk[iBand]);
                 }
                 CPLFree(papaChunk);
                 CPLFree(pabHasNoData);
                 CPLFree(pafNoDataValue);
-
-                CPLError( CE_Failure, CPLE_OutOfMemory,
-                        "GDALRegenerateOverviewsMultiBand: Out of memory." );
                 return CE_Failure;
             }
         }
@@ -2777,7 +2908,7 @@ GDALRegenerateOverviewsMultiBand(int nBands, GDALRasterBand** papoSrcBands,
                 nChunkYSizeQueried = nSrcHeight - nChunkYOffQueried;
             CPLAssert(nChunkYSizeQueried <= nFullResYChunkQueried);
 
-            if( !pfnProgress( dfCurPixelCount / dfTotalPixelCount, 
+            if( !pfnProgress( dfCurPixelCount / dfTotalPixelCount,
                               NULL, pProgressData ) )
             {
                 CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
@@ -2816,7 +2947,7 @@ GDALRegenerateOverviewsMultiBand(int nBands, GDALRasterBand** papoSrcBands,
                          nDstXOff, nDstYOff, nDstXCount, nDstYCount);*/
 
                 /* Read the source buffers for all the bands */
-                for(iBand=0;iBand<nBands && eErr == CE_None;iBand++)
+                for(int iBand=0;iBand<nBands && eErr == CE_None;iBand++)
                 {
                     GDALRasterBand* poSrcBand;
                     if (iSrcOverview == -1)
@@ -2825,7 +2956,7 @@ GDALRegenerateOverviewsMultiBand(int nBands, GDALRasterBand** papoSrcBands,
                         poSrcBand = papapoOverviewBands[iBand][iSrcOverview];
                     eErr = poSrcBand->RasterIO( GF_Read,
                                                 nChunkXOffQueried, nChunkYOffQueried,
-                                                nChunkXSizeQueried, nChunkYSizeQueried, 
+                                                nChunkXSizeQueried, nChunkYSizeQueried,
                                                 papaChunk[iBand],
                                                 nChunkXSizeQueried, nChunkYSizeQueried,
                                                 eWrkDataType, 0, 0, NULL );
@@ -2840,14 +2971,14 @@ GDALRegenerateOverviewsMultiBand(int nBands, GDALRasterBand** papoSrcBands,
                         poSrcBand = papapoOverviewBands[0][iSrcOverview];
                     eErr = poSrcBand->GetMaskBand()->RasterIO( GF_Read,
                                                                nChunkXOffQueried, nChunkYOffQueried,
-                                                               nChunkXSizeQueried, nChunkYSizeQueried, 
+                                                               nChunkXSizeQueried, nChunkYSizeQueried,
                                                                pabyChunkNoDataMask,
                                                                nChunkXSizeQueried, nChunkYSizeQueried,
                                                                GDT_Byte, 0, 0, NULL );
                 }
 
                 /* Compute the resulting overview block */
-                for(iBand=0;iBand<nBands && eErr == CE_None;iBand++)
+                for(int iBand=0;iBand<nBands && eErr == CE_None;iBand++)
                 {
                     eErr = pfnResampleFn(   dfXRatioDstToSrc, dfYRatioDstToSrc,
                                             0.0, 0.0,
@@ -2871,7 +3002,7 @@ GDALRegenerateOverviewsMultiBand(int nBands, GDALRasterBand** papoSrcBands,
         }
 
         /* Flush the data to overviews */
-        for(iBand=0;iBand<nBands;iBand++)
+        for(int iBand=0;iBand<nBands;iBand++)
         {
             CPLFree(papaChunk[iBand]);
             papapoOverviewBands[iBand][iOverview]->FlushCache();
@@ -2895,60 +3026,58 @@ GDALRegenerateOverviewsMultiBand(int nBands, GDALRasterBand** papoSrcBands,
 /*                        GDALComputeBandStats()                        */
 /************************************************************************/
 
-CPLErr CPL_STDCALL 
+CPLErr CPL_STDCALL
 GDALComputeBandStats( GDALRasterBandH hSrcBand,
                       int nSampleStep,
-                      double *pdfMean, double *pdfStdDev, 
-                      GDALProgressFunc pfnProgress, 
+                      double *pdfMean, double *pdfStdDev,
+                      GDALProgressFunc pfnProgress,
                       void *pProgressData )
 
 {
     VALIDATE_POINTER1( hSrcBand, "GDALComputeBandStats", CE_Failure );
 
     GDALRasterBand *poSrcBand = (GDALRasterBand *) hSrcBand;
-    int         iLine, nWidth, nHeight;
-    GDALDataType eType = poSrcBand->GetRasterDataType();
-    GDALDataType eWrkType;
-    int         bComplex;
-    float       *pafData;
-    double      dfSum=0.0, dfSum2=0.0;
-    int         nSamples = 0;
 
     if( pfnProgress == NULL )
         pfnProgress = GDALDummyProgress;
 
-    nWidth = poSrcBand->GetXSize();
-    nHeight = poSrcBand->GetYSize();
+    const int nWidth = poSrcBand->GetXSize();
+    const int nHeight = poSrcBand->GetYSize();
 
     if( nSampleStep >= nHeight || nSampleStep < 1 )
         nSampleStep = 1;
 
-    bComplex = GDALDataTypeIsComplex(eType);
+    GDALDataType eWrkType;
+    float *pafData;
+    GDALDataType eType = poSrcBand->GetRasterDataType();
+    const bool bComplex = CPL_TO_BOOL(GDALDataTypeIsComplex(eType));
     if( bComplex )
     {
-        pafData = (float *) VSIMalloc(nWidth * 2 * sizeof(float));
+        pafData = (float *) VSI_MALLOC_VERBOSE(nWidth * 2 * sizeof(float));
         eWrkType = GDT_CFloat32;
     }
     else
     {
-        pafData = (float *) VSIMalloc(nWidth * sizeof(float));
+        pafData = (float *) VSI_MALLOC_VERBOSE(nWidth * sizeof(float));
         eWrkType = GDT_Float32;
     }
 
-    if( pafData == NULL )
+    if( nWidth == 0 || pafData == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory,
-                  "GDALComputeBandStats: Out of memory for buffer." );
+        VSIFree(pafData);
         return CE_Failure;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Loop over all sample lines.                                     */
 /* -------------------------------------------------------------------- */
-    for( iLine = 0; iLine < nHeight; iLine += nSampleStep )
-    {
-        int     iPixel;
+    double dfSum=0.0;
+    double dfSum2=0.0;
+    int iLine = 0;
+    int nSamples = 0;
 
+    do
+    {
         if( !pfnProgress( iLine / (double) nHeight,
                           NULL, pProgressData ) )
         {
@@ -2966,15 +3095,14 @@ GDALComputeBandStats( GDALRasterBandH hSrcBand,
             return eErr;
         }
 
-        for( iPixel = 0; iPixel < nWidth; iPixel++ )
+        for( int iPixel = 0; iPixel < nWidth; iPixel++ )
         {
             float       fValue;
 
             if( bComplex )
             {
                 // Compute the magnitude of the complex value.
-
-                fValue = (float) 
+                fValue = (float)
                     sqrt(pafData[iPixel*2  ] * pafData[iPixel*2  ]
                          + pafData[iPixel*2+1] * pafData[iPixel*2+1]);
             }
@@ -2988,7 +3116,9 @@ GDALComputeBandStats( GDALRasterBandH hSrcBand,
         }
 
         nSamples += nWidth;
-    }
+        iLine += nSampleStep;
+
+    } while( iLine < nHeight );
 
     if( !pfnProgress( 1.0, NULL, pProgressData ) )
     {
@@ -3005,7 +3135,7 @@ GDALComputeBandStats( GDALRasterBandH hSrcBand,
 
     if( pdfStdDev != NULL )
     {
-        double  dfMean = dfSum / nSamples;
+        const double dfMean = dfSum / nSamples;
 
         *pdfStdDev = sqrt((dfSum2 / nSamples) - (dfMean * dfMean));
     }
@@ -3023,45 +3153,42 @@ GDALComputeBandStats( GDALRasterBandH hSrcBand,
 /************************************************************************/
 
 CPLErr
-GDALOverviewMagnitudeCorrection( GDALRasterBandH hBaseBand, 
+GDALOverviewMagnitudeCorrection( GDALRasterBandH hBaseBand,
                                  int nOverviewCount,
                                  GDALRasterBandH *pahOverviews,
-                                 GDALProgressFunc pfnProgress, 
+                                 GDALProgressFunc pfnProgress,
                                  void *pProgressData )
 
 {
     VALIDATE_POINTER1( hBaseBand, "GDALOverviewMagnitudeCorrection", CE_Failure );
 
-    CPLErr      eErr;
-    double      dfOrigMean, dfOrigStdDev;
-
 /* -------------------------------------------------------------------- */
 /*      Compute mean/stddev for source raster.                          */
 /* -------------------------------------------------------------------- */
-    eErr = GDALComputeBandStats( hBaseBand, 2, &dfOrigMean, &dfOrigStdDev, 
-                                 pfnProgress, pProgressData );
+    double dfOrigMean, dfOrigStdDev;
+    CPLErr eErr
+        = GDALComputeBandStats( hBaseBand, 2, &dfOrigMean, &dfOrigStdDev,
+                                pfnProgress, pProgressData );
 
     if( eErr != CE_None )
         return eErr;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Loop on overview bands.                                         */
 /* -------------------------------------------------------------------- */
-    int         iOverview;
-
-    for( iOverview = 0; iOverview < nOverviewCount; iOverview++ )
+    for( int iOverview = 0; iOverview < nOverviewCount; iOverview++ )
     {
         GDALRasterBand *poOverview = (GDALRasterBand *)pahOverviews[iOverview];
         double  dfOverviewMean, dfOverviewStdDev;
-        double  dfGain;
 
-        eErr = GDALComputeBandStats( pahOverviews[iOverview], 1, 
-                                     &dfOverviewMean, &dfOverviewStdDev, 
+        eErr = GDALComputeBandStats( pahOverviews[iOverview], 1,
+                                     &dfOverviewMean, &dfOverviewStdDev,
                                      pfnProgress, pProgressData );
 
         if( eErr != CE_None )
             return eErr;
 
+        double dfGain;
         if( dfOrigStdDev < 0.0001 )
             dfGain = 1.0;
         else
@@ -3070,36 +3197,31 @@ GDALOverviewMagnitudeCorrection( GDALRasterBandH hBaseBand,
 /* -------------------------------------------------------------------- */
 /*      Apply gain and offset.                                          */
 /* -------------------------------------------------------------------- */
-        GDALDataType    eWrkType, eType = poOverview->GetRasterDataType();
-        int             iLine, nWidth, nHeight, bComplex;
-        float           *pafData;
-
-        nWidth = poOverview->GetXSize();
-        nHeight = poOverview->GetYSize();
+        const int nWidth = poOverview->GetXSize();
+        const int nHeight = poOverview->GetYSize();
 
-        bComplex = GDALDataTypeIsComplex(eType);
+        GDALDataType eWrkType;
+        float *pafData;
+        const GDALDataType eType = poOverview->GetRasterDataType();
+        const bool bComplex = CPL_TO_BOOL(GDALDataTypeIsComplex(eType));
         if( bComplex )
         {
-            pafData = (float *) VSIMalloc2(nWidth, 2 * sizeof(float));
+            pafData = (float *) VSI_MALLOC2_VERBOSE(nWidth, 2 * sizeof(float));
             eWrkType = GDT_CFloat32;
         }
         else
         {
-            pafData = (float *) VSIMalloc2(nWidth, sizeof(float));
+            pafData = (float *) VSI_MALLOC2_VERBOSE(nWidth, sizeof(float));
             eWrkType = GDT_Float32;
         }
 
         if( pafData == NULL )
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory,
-                      "GDALOverviewMagnitudeCorrection: Out of memory for buffer." );
             return CE_Failure;
         }
 
-        for( iLine = 0; iLine < nHeight; iLine++ )
+        for( int iLine = 0; iLine < nHeight; iLine++ )
         {
-            int iPixel;
-            
             if( !pfnProgress( iLine / (double) nHeight,
                               NULL, pProgressData ) )
             {
@@ -3108,11 +3230,15 @@ GDALOverviewMagnitudeCorrection( GDALRasterBandH hBaseBand,
                 return CE_Failure;
             }
 
-            poOverview->RasterIO( GF_Read, 0, iLine, nWidth, 1,
+            if( poOverview->RasterIO( GF_Read, 0, iLine, nWidth, 1,
                                   pafData, nWidth, 1, eWrkType,
-                                  0, 0, NULL );
-            
-            for( iPixel = 0; iPixel < nWidth; iPixel++ )
+                                  0, 0, NULL ) != CE_None )
+            {
+                CPLFree( pafData );
+                return CE_Failure;
+            }
+
+            for( int iPixel = 0; iPixel < nWidth; iPixel++ )
             {
                 if( bComplex )
                 {
@@ -3127,9 +3253,13 @@ GDALOverviewMagnitudeCorrection( GDALRasterBandH hBaseBand,
                 }
             }
 
-            poOverview->RasterIO( GF_Write, 0, iLine, nWidth, 1,
+            if( poOverview->RasterIO( GF_Write, 0, iLine, nWidth, 1,
                                   pafData, nWidth, 1, eWrkType,
-                                  0, 0, NULL );
+                                  0, 0, NULL ) != CE_None )
+            {
+                CPLFree( pafData );
+                return CE_Failure;
+            }
         }
 
         if( !pfnProgress( 1.0, NULL, pProgressData ) )
@@ -3138,7 +3268,7 @@ GDALOverviewMagnitudeCorrection( GDALRasterBandH hBaseBand,
             CPLFree( pafData );
             return CE_Failure;
         }
-        
+
         CPLFree( pafData );
     }
 
diff --git a/gcore/rasterio.cpp b/gcore/rasterio.cpp
index 6dc16f0..77e2ca5 100644
--- a/gcore/rasterio.cpp
+++ b/gcore/rasterio.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rasterio.cpp 29496 2015-07-07 22:29:46Z rouault $
+ * $Id: rasterio.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Contains default implementation of GDALRasterBand::IRasterIO()
@@ -35,24 +35,11 @@
 #include "memdataset.h"
 #include "gdalwarper.h"
 
-// Define a list of "C++" compilers that have broken template support or
-// broken scoping so we can fall back on the legacy implementation of
-// GDALCopyWords
-#define NOT_BROKEN_COMPILER \
-	(!(defined(_MSC_VER) && _MSC_VER <= 1200) && !defined(__BORLANDC__) && \
-	!defined(__SUNPRO_CC))
-
-#if NOT_BROKEN_COMPILER
 #include <stdexcept>
 #include <limits>
+#include "gdal_priv_templates.hpp"
 
-// For now, work around MSVC++ 6.0's broken template support. If this value
-// is not defined, the old GDALCopyWords implementation is used.
-#define USE_NEW_COPYWORDS 1
-#endif
-
-
-CPL_CVSID("$Id: rasterio.cpp 29496 2015-07-07 22:29:46Z rouault $");
+CPL_CVSID("$Id: rasterio.cpp 33808 2016-03-29 21:15:28Z goatbar $");
 
 /************************************************************************/
 /*                             IRasterIO()                              */
@@ -70,20 +57,25 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                                   GDALRasterIOExtraArg* psExtraArg )
 
 {
-    int         nBandDataSize = GDALGetDataTypeSize( eDataType ) / 8;
-    int         nBufDataSize = GDALGetDataTypeSize( eBufType ) / 8;
+    const int nBandDataSize = GDALGetDataTypeSizeBytes( eDataType );
+    const int nBufDataSize = GDALGetDataTypeSizeBytes( eBufType );
     GByte       *pabySrcBlock = NULL;
     GDALRasterBlock *poBlock = NULL;
     int         nLBlockX=-1, nLBlockY=-1, iBufYOff, iBufXOff, iSrcY;
-    
+
     if( eRWFlag == GF_Write && eFlushBlockErr != CE_None )
     {
-        CPLError(eFlushBlockErr, CPLE_AppDefined,
-                 "An error occured while writing a dirty block");
+        CPLError( eFlushBlockErr, CPLE_AppDefined,
+                  "An error occurred while writing a dirty block" );
         CPLErr eErr = eFlushBlockErr;
         eFlushBlockErr = CE_None;
         return eErr;
     }
+    if( nBlockXSize <= 0 || nBlockYSize <= 0 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Invalid block size" );
+        return CE_Failure;
+    }
 
 /* ==================================================================== */
 /*      A common case is the data requested with the destination        */
@@ -92,35 +84,32 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     if( nPixelSpace == nBufDataSize
         && nLineSpace == nPixelSpace * nXSize
         && nBlockXSize == GetXSize()
-        && nBufXSize == nXSize 
+        && nBufXSize == nXSize
         && nBufYSize == nYSize )
     {
-//        printf( "IRasterIO(%d,%d,%d,%d) rw=%d case 1\n", 
-//                nXOff, nYOff, nXSize, nYSize, 
-//                (int) eRWFlag );
         CPLErr eErr = CE_None;
 
         for( iBufYOff = 0; iBufYOff < nBufYSize; iBufYOff++ )
         {
             int         nSrcByteOffset;
-            
+
             iSrcY = iBufYOff + nYOff;
-            
+
             if( iSrcY < nLBlockY * nBlockYSize
                 || iSrcY >= (nLBlockY+1) * nBlockYSize )
             {
                 nLBlockY = iSrcY / nBlockYSize;
-                int bJustInitialize = 
+                int bJustInitialize =
                     eRWFlag == GF_Write
                     && nXOff == 0 && nXSize == nBlockXSize
                     && nYOff <= nLBlockY * nBlockYSize
                     && nYOff + nYSize >= (nLBlockY+1) * nBlockYSize;
 
                 /* Is this a partial tile at right and/or bottom edges of */
-                /* the raster, and that is going to be completely written ? */
-                /* If so, don't load it from storage, but zeroized it so that */
-                /* the content outsize of the validity area is initialized */
-                int bMemZeroBuffer = FALSE;
+                /* the raster, and that is going to be completely written? */
+                /* If so, do not load it from storage, but zero it so that */
+                /* the content outsize of the validity area is initialized. */
+                bool bMemZeroBuffer = false;
                 if( eRWFlag == GF_Write && !bJustInitialize &&
                     nXOff == 0 && nXSize == nBlockXSize &&
                     nYOff <= nLBlockY * nBlockYSize &&
@@ -128,7 +117,7 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                     (nLBlockY+1) * nBlockYSize > GetYSize() )
                 {
                     bJustInitialize = TRUE;
-                    bMemZeroBuffer = TRUE;
+                    bMemZeroBuffer = true;
                 }
 
                 if( poBlock )
@@ -138,22 +127,16 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                 if( poBlock == NULL )
                 {
                     CPLError( CE_Failure, CPLE_AppDefined,
-            "GetBlockRef failed at X block offset %d, "
-                        "Y block offset %d", 0, nLBlockY );
+                              "GetBlockRef failed at X block offset %d, "
+                              "Y block offset %d", 0, nLBlockY );
                     eErr = CE_Failure;
                     break;
                 }
 
                 if( eRWFlag == GF_Write )
                     poBlock->MarkDirty();
-                
+
                 pabySrcBlock = (GByte *) poBlock->GetDataRef();
-                if( pabySrcBlock == NULL )
-                {
-                    poBlock->DropLock();
-                    eErr = CE_Failure;
-                    break;
-                }
                 if( bMemZeroBuffer )
                 {
                     memset(pabySrcBlock, 0,
@@ -161,24 +144,32 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                 }
             }
 
+            // To make Coverity happy. Should not happen by design.
+            if( pabySrcBlock == NULL )
+            {
+                CPLAssert(FALSE);
+                eErr = CE_Failure;
+                break;
+            }
+
             nSrcByteOffset = ((iSrcY-nLBlockY*nBlockYSize)*nBlockXSize + nXOff)
                 * nBandDataSize;
-            
+
             if( eDataType == eBufType )
             {
                 if( eRWFlag == GF_Read )
                     memcpy( ((GByte *) pData) + (GPtrDiff_t)iBufYOff * nLineSpace,
-                            pabySrcBlock + nSrcByteOffset, 
+                            pabySrcBlock + nSrcByteOffset,
                             (size_t)nLineSpace );
                 else
-                    memcpy( pabySrcBlock + nSrcByteOffset, 
+                    memcpy( pabySrcBlock + nSrcByteOffset,
                             ((GByte *) pData) + (GPtrDiff_t)iBufYOff * nLineSpace,
                             (size_t)nLineSpace );
             }
             else
             {
                 /* type to type conversion */
-                
+
                 if( eRWFlag == GF_Read )
                     GDALCopyWords( pabySrcBlock + nSrcByteOffset,
                                    eDataType, nBandDataSize,
@@ -205,7 +196,7 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 
         return eErr;
     }
-    
+
 /* ==================================================================== */
 /*      Do we have overviews that would be appropriate to satisfy       */
 /*      this request?                                                   */
@@ -215,7 +206,7 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     {
         int         nOverview;
         GDALRasterIOExtraArg sExtraArg;
-    
+
         GDALCopyRasterIOExtraArg(&sExtraArg, psExtraArg);
 
         nOverview =
@@ -232,13 +223,12 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                                             nPixelSpace, nLineSpace, &sExtraArg );
         }
     }
-    
-    
+
     if( eRWFlag == GF_Read &&
         nBufXSize < nXSize / 100 && nBufYSize < nYSize / 100 &&
         nPixelSpace == nBufDataSize &&
         nLineSpace == nPixelSpace * nBufXSize &&
-        CSLTestBoolean(CPLGetConfigOption("GDAL_NO_COSTLY_OVERVIEW", "NO")) )
+        CPLTestBool(CPLGetConfigOption("GDAL_NO_COSTLY_OVERVIEW", "NO")) )
     {
         memset(pData, 0, (size_t)(nLineSpace * nBufYSize));
         return CE_None;
@@ -253,10 +243,10 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 
     if ( /* nPixelSpace == nBufDataSize
             && */ nXSize == nBufXSize
-         && nYSize == nBufYSize )    
+         && nYSize == nBufYSize )
     {
-//        printf( "IRasterIO(%d,%d,%d,%d) rw=%d case 2\n", 
-//                nXOff, nYOff, nXSize, nYSize, 
+//        printf( "IRasterIO(%d,%d,%d,%d) rw=%d case 2\n",
+//                nXOff, nYOff, nXSize, nYSize,
 //                (int) eRWFlag );
 
 /* -------------------------------------------------------------------- */
@@ -287,7 +277,7 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                 nXSpan = ( ( nXSpan < nXSpanEnd )?nXSpan:nXSpanEnd ) - iSrcX;
                 nXSpanSize = nXSpan * (int)nPixelSpace;
 
-                int bJustInitialize = 
+                int bJustInitialize =
                     eRWFlag == GF_Write
                     && nYOff <= nLBlockY * nBlockYSize
                     && nYOff + nYSize >= (nLBlockY+1) * nBlockYSize
@@ -295,10 +285,10 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                     && nXOff + nXSize >= (nLBlockX+1) * nBlockXSize;
 
                 /* Is this a partial tile at right and/or bottom edges of */
-                /* the raster, and that is going to be completely written ? */
-                /* If so, don't load it from storage, but zeroized it so that */
-                /* the content outsize of the validity area is initialized */
-                int bMemZeroBuffer = FALSE;
+                /* the raster, and that is going to be completely written? */
+                /* If so, do not load it from storage, but zero it so that */
+                /* the content outsize of the validity area is initialized. */
+                bool bMemZeroBuffer = false;
                 if( eRWFlag == GF_Write && !bJustInitialize &&
                     nXOff <= nLBlockX * nBlockXSize &&
                     nYOff <= nLBlockY * nBlockYSize &&
@@ -308,14 +298,8 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                      (nYOff + nYSize == GetYSize() && (nLBlockY+1) * nBlockYSize > GetYSize())) )
                 {
                     bJustInitialize = TRUE;
-                    bMemZeroBuffer = TRUE;
+                    bMemZeroBuffer = true;
                 }
-//                printf( "bJustInitialize = %d (%d,%d,%d,%d)\n", 
-//                        bJustInitialize,
-//                        nYOff, nYSize, 
-//                        nLBlockY, nBlockYSize );
-//                bJustInitialize = FALSE;
-                
 
 /* -------------------------------------------------------------------- */
 /*      Ensure we have the appropriate block loaded.                    */
@@ -324,20 +308,15 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                 if( !poBlock )
                 {
                     CPLError( CE_Failure, CPLE_AppDefined,
-            "GetBlockRef failed at X block offset %d, "
-                        "Y block offset %d", nLBlockX, nLBlockY );
+                              "GetBlockRef failed at X block offset %d, "
+                              "Y block offset %d", nLBlockX, nLBlockY );
                     return( CE_Failure );
                 }
 
                 if( eRWFlag == GF_Write )
                     poBlock->MarkDirty();
-                
+
                 pabySrcBlock = (GByte *) poBlock->GetDataRef();
-                if( pabySrcBlock == NULL )
-                {
-                    poBlock->DropLock();
-                    return CE_Failure;
-                }
                 if( bMemZeroBuffer )
                 {
                     memset(pabySrcBlock, 0,
@@ -352,20 +331,19 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                 int kmax = MIN(nBlockYSize - (iSrcY % nBlockYSize), nBufYSize - iBufYOff);
                 for(int k=0; k<kmax;k++)
                 {
-                    if( eDataType == eBufType 
+                    if( eDataType == eBufType
                         && nPixelSpace == nBufDataSize )
                     {
                         if( eRWFlag == GF_Read )
                             memcpy( ((GByte *) pData) + iBufOffset + (GPtrDiff_t)k * nLineSpace,
                                     pabySrcBlock + iSrcOffset, nXSpanSize );
                         else
-                            memcpy( pabySrcBlock + iSrcOffset, 
+                            memcpy( pabySrcBlock + iSrcOffset,
                                     ((GByte *) pData) + iBufOffset + (GPtrDiff_t)k * nLineSpace, nXSpanSize );
                     }
                     else
                     {
                         /* type to type conversion */
-                        
                         if( eRWFlag == GF_Read )
                             GDALCopyWords( pabySrcBlock + iSrcOffset,
                                         eDataType, nBandDataSize,
@@ -377,7 +355,7 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                                         pabySrcBlock + iSrcOffset,
                                         eDataType, nBandDataSize, nXSpan );
                     }
-                    
+
                     iSrcOffset += nBlockXSize * nBandDataSize;
                 }
 
@@ -435,9 +413,6 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     dfSrcYInc = dfYSize / (double) nBufYSize;
     CPLErr eErr = CE_None;
 
-//    printf( "IRasterIO(%d,%d,%d,%d) rw=%d case 3\n", 
-//            nXOff, nYOff, nXSize, nYSize, 
-//            (int) eRWFlag );
     if (eRWFlag == GF_Write)
     {
 /* -------------------------------------------------------------------- */
@@ -473,12 +448,12 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                     nLBlockX = iDstX / nBlockXSize;
                     nLBlockY = iDstY / nBlockYSize;
 
-                    int bJustInitialize = 
+                    int bJustInitialize =
                            nYOff <= nLBlockY * nBlockYSize
                         && nYOff + nYSize >= (nLBlockY+1) * nBlockYSize
                         && nXOff <= nLBlockX * nBlockXSize
                         && nXOff + nXSize >= (nLBlockX+1) * nBlockXSize;
-                    /*int bMemZeroBuffer = FALSE;
+                    /*bool bMemZeroBuffer = FALSE;
                     if( !bJustInitialize &&
                         nXOff <= nLBlockX * nBlockXSize &&
                         nYOff <= nLBlockY * nBlockYSize &&
@@ -493,7 +468,7 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                     if( poBlock != NULL )
                         poBlock->DropLock();
 
-                    poBlock = GetLockedBlockRef( nLBlockX, nLBlockY, 
+                    poBlock = GetLockedBlockRef( nLBlockX, nLBlockY,
                                                 bJustInitialize );
                     if( poBlock == NULL )
                     {
@@ -503,11 +478,6 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                     poBlock->MarkDirty();
 
                     pabyDstBlock = (GByte *) poBlock->GetDataRef();
-                    if( pabyDstBlock == NULL )
-                    {
-                        poBlock->DropLock();
-                        return CE_Failure;
-                    }
                     /*if( bMemZeroBuffer )
                     {
                         memset(pabyDstBlock, 0,
@@ -515,6 +485,14 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                     }*/
                 }
 
+                // To make Coverity happy. Should not happen by design.
+                if( pabyDstBlock == NULL )
+                {
+                    CPLAssert(FALSE);
+                    eErr = CE_Failure;
+                    break;
+                }
+
     /* -------------------------------------------------------------------- */
     /*      Copy over this pixel of data.                                   */
     /* -------------------------------------------------------------------- */
@@ -523,7 +501,7 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 
                 if( eDataType == eBufType )
                 {
-                    memcpy( pabyDstBlock + iDstOffset, 
+                    memcpy( pabyDstBlock + iDstOffset,
                             ((GByte *) pData) + iBufOffset, nBandDataSize );
                 }
                 else
@@ -580,7 +558,7 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 
         double      dfSrcX, dfSrcY;
         int         nLimitBlockY = 0;
-        int         bByteCopy = ( eDataType == eBufType && nBandDataSize == 1); 
+        int         bByteCopy = ( eDataType == eBufType && nBandDataSize == 1);
         int nStartBlockX = -nBlockXSize;
 
 /* -------------------------------------------------------------------- */
@@ -625,7 +603,7 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                     if( poBlock != NULL )
                         poBlock->DropLock();
 
-                    poBlock = GetLockedBlockRef( nLBlockX, nLBlockY, 
+                    poBlock = GetLockedBlockRef( nLBlockX, nLBlockY,
                                                  FALSE );
                     if( poBlock == NULL )
                     {
@@ -634,24 +612,27 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                     }
 
                     pabySrcBlock = (GByte *) poBlock->GetDataRef();
-                    if( pabySrcBlock == NULL )
-                    {
-                        eErr = CE_Failure;
-                        break;
-                    }
                 }
 
+                // To make Coverity happy.  Should not happen by design.
+                if( pabySrcBlock == NULL )
+                {
+                    CPLAssert(FALSE);
+                    eErr = CE_Failure;
+                    break;
+                }
     /* -------------------------------------------------------------------- */
     /*      Copy over this pixel of data.                                   */
     /* -------------------------------------------------------------------- */
-                iSrcOffset = ((GPtrDiff_t)nDiffX + iSrcOffsetCst)*nBandDataSize;
 
                 if( bByteCopy )
                 {
+                    iSrcOffset = (GPtrDiff_t)nDiffX + iSrcOffsetCst;
                     ((GByte *) pData)[iBufOffset] = pabySrcBlock[iSrcOffset];
                 }
                 else if( eDataType == eBufType )
                 {
+                    iSrcOffset = ((GPtrDiff_t)nDiffX + iSrcOffsetCst)*nBandDataSize;
                     memcpy( ((GByte *) pData) + iBufOffset,
                             pabySrcBlock + iSrcOffset, nBandDataSize );
                 }
@@ -659,6 +640,7 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                 {
                     /* type to type conversion ... ouch, this is expensive way
                     of handling single words */
+                    iSrcOffset = ((GPtrDiff_t)nDiffX + iSrcOffsetCst)*nBandDataSize;
                     GDALCopyWords( pabySrcBlock + iSrcOffset, eDataType, 0,
                                 ((GByte *) pData) + iBufOffset, eBufType, 0,
                                 1 );
@@ -788,18 +770,21 @@ CPLErr GDALRasterBand::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
     nRet = CPLPrintPointer(szBuffer, (GByte*)pData - nPixelSpace * nDestXOffVirtual
                             - nLineSpace * nDestYOffVirtual, sizeof(szBuffer));
     szBuffer[nRet] = 0;
-    char** papszOptions = CSLSetNameValue(NULL, "DATAPOINTER", szBuffer);
 
-    papszOptions = CSLSetNameValue(papszOptions, "PIXELOFFSET",
-                                CPLSPrintf(CPL_FRMT_GIB, (GIntBig)nPixelSpace));
+    char* apszOptions[4];
+    char szBuffer0[64], szBuffer1[64], szBuffer2[64];
+    snprintf(szBuffer0, sizeof(szBuffer0), "DATAPOINTER=%s", szBuffer);
+    snprintf(szBuffer1, sizeof(szBuffer1), "PIXELOFFSET=" CPL_FRMT_GIB, (GIntBig)nPixelSpace);
+    snprintf(szBuffer2, sizeof(szBuffer2), "LINEOFFSET=" CPL_FRMT_GIB, (GIntBig)nLineSpace);
+    apszOptions[0] = szBuffer0;
+    apszOptions[1] = szBuffer1;
+    apszOptions[2] = szBuffer2;
+    apszOptions[3] = NULL;
 
-    papszOptions = CSLSetNameValue(papszOptions, "LINEOFFSET",
-                                CPLSPrintf(CPL_FRMT_GIB, (GIntBig)nLineSpace));
+    poMEMDS->AddBand(eBufType, apszOptions);
 
-    poMEMDS->AddBand(eBufType, papszOptions);
-    CSLDestroy(papszOptions);
     GDALRasterBandH hMEMBand = (GDALRasterBandH)poMEMDS->GetRasterBand(1);
-    
+
     const char* pszNBITS = GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
     if( pszNBITS )
         ((GDALRasterBand*)hMEMBand)->SetMetadataItem("NBITS", pszNBITS, "IMAGE_STRUCTURE");
@@ -816,8 +801,8 @@ CPLErr GDALRasterBand::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
             VRTAddBand( hVRTDS, eDataType, NULL );
             hVRTBand = GDALGetRasterBand(hVRTDS, 1);
             VRTAddSimpleSource( (VRTSourcedRasterBandH)hVRTBand,
-                                (GDALRasterBandH)this, 
-                                0, 0, 
+                                (GDALRasterBandH)this,
+                                0, 0,
                                 nRasterXSize, nRasterYSize,
                                 0, 0,
                                 nRasterXSize, nRasterYSize,
@@ -830,8 +815,8 @@ CPLErr GDALRasterBand::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
                 VRTSourcedRasterBand* poVRTMaskBand =
                     (VRTSourcedRasterBand*)(((GDALRasterBand*)hVRTBand)->GetMaskBand());
                 poVRTMaskBand->
-                    AddMaskBandSource( this, 
-                                    0, 0, 
+                    AddMaskBandSource( this,
+                                    0, 0,
                                     nRasterXSize, nRasterYSize,
                                     0, 0,
                                     nRasterXSize, nRasterYSize);
@@ -839,7 +824,17 @@ CPLErr GDALRasterBand::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
         }
 
         GDALWarpOptions* psWarpOptions = GDALCreateWarpOptions();
-        psWarpOptions->eResampleAlg = (GDALResampleAlg)psExtraArg->eResampleAlg;
+        switch(psExtraArg->eResampleAlg)
+        {
+            case GRIORA_NearestNeighbour: psWarpOptions->eResampleAlg = GRA_NearestNeighbour; break;
+            case GRIORA_Bilinear:         psWarpOptions->eResampleAlg = GRA_Bilinear; break;
+            case GRIORA_Cubic:            psWarpOptions->eResampleAlg = GRA_Cubic; break;
+            case GRIORA_CubicSpline:      psWarpOptions->eResampleAlg = GRA_CubicSpline; break;
+            case GRIORA_Lanczos:          psWarpOptions->eResampleAlg = GRA_Lanczos; break;
+            case GRIORA_Average:          psWarpOptions->eResampleAlg = GRA_Average; break;
+            case GRIORA_Mode:             psWarpOptions->eResampleAlg = GRA_Mode; break;
+            default:                      CPLAssert(FALSE); psWarpOptions->eResampleAlg = GRA_NearestNeighbour; break;
+        }
         psWarpOptions->hSrcDS = (GDALDatasetH) (hVRTDS ? hVRTDS : GetDataset());
         psWarpOptions->hDstDS = (GDALDatasetH) poMEMDS;
         psWarpOptions->nBandCount = 1;
@@ -886,7 +881,7 @@ CPLErr GDALRasterBand::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
         GDALResampleFunction pfnResampleFunc =
                         GDALGetResampleFunction(pszResampling, &nKernelRadius);
         CPLAssert(pfnResampleFunc);
-        GDALDataType eWrkDataType = 
+        GDALDataType eWrkDataType =
             GDALGetOvrWorkDataType(pszResampling, eDataType);
         int bHasNoData = FALSE;
         float fNoDataValue = (float) GetNoDataValue(&bHasNoData);
@@ -896,7 +891,7 @@ CPLErr GDALRasterBand::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
         int nDstBlockXSize = nBufXSize;
         int nDstBlockYSize = nBufYSize;
         int nFullResXChunk, nFullResYChunk;
-        while(TRUE)
+        while( true )
         {
             nFullResXChunk = 3 + (int)(nDstBlockXSize * dfXRatioDstToSrc);
             nFullResYChunk = 3 + (int)(nDstBlockYSize * dfYRatioDstToSrc);
@@ -920,31 +915,29 @@ CPLErr GDALRasterBand::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
         int nFullResXSizeQueried = nFullResXChunk + 2 * nKernelRadius * nOvrFactor;
         int nFullResYSizeQueried = nFullResYChunk + 2 * nKernelRadius * nOvrFactor;
 
-        void * pChunk = 
-            VSIMalloc3((GDALGetDataTypeSize(eWrkDataType)/8),
-                        nFullResXSizeQueried, nFullResYSizeQueried );
+        void * pChunk =
+            VSI_MALLOC3_VERBOSE( GDALGetDataTypeSizeBytes(eWrkDataType),
+                                 nFullResXSizeQueried, nFullResYSizeQueried );
         GByte * pabyChunkNoDataMask = NULL;
 
         GDALRasterBand* poMaskBand = NULL;
-        int nMaskFlags = 0;
-        int bUseNoDataMask = FALSE;
+        int l_nMaskFlags = 0;
+        bool bUseNoDataMask = false;
 
         poMaskBand = GetMaskBand();
-        nMaskFlags = GetMaskFlags();
+        l_nMaskFlags = GetMaskFlags();
 
-        bUseNoDataMask = ((nMaskFlags & GMF_ALL_VALID) == 0);
+        bUseNoDataMask = ((l_nMaskFlags & GMF_ALL_VALID) == 0);
         if (bUseNoDataMask)
         {
-            pabyChunkNoDataMask = (GByte *) 
-                (GByte*) VSIMalloc2( nFullResXSizeQueried, nFullResYSizeQueried );
+            pabyChunkNoDataMask = (GByte *)
+                (GByte*) VSI_MALLOC2_VERBOSE( nFullResXSizeQueried, nFullResYSizeQueried );
         }
         if( pChunk == NULL || (bUseNoDataMask && pabyChunkNoDataMask == NULL) )
         {
             GDALClose(poMEMDS);
             CPLFree(pChunk);
             CPLFree(pabyChunkNoDataMask);
-            CPLError( CE_Failure, CPLE_OutOfMemory,
-                      "Out of memory in RasterIO()." );
             return CE_Failure;
         }
 
@@ -1011,12 +1004,12 @@ CPLErr GDALRasterBand::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
                 /* Read the source buffers */
                 eErr = RasterIO( GF_Read,
                                 nChunkXOffQueried, nChunkYOffQueried,
-                                nChunkXSizeQueried, nChunkYSizeQueried, 
+                                nChunkXSizeQueried, nChunkYSizeQueried,
                                 pChunk,
                                 nChunkXSizeQueried, nChunkYSizeQueried,
                                 eWrkDataType, 0, 0, NULL );
 
-                int bSkipResample = FALSE;
+                bool bSkipResample = false;
                 int bNoDataMaskFullyOpaque = FALSE;
                 if (eErr == CE_None && bUseNoDataMask)
                 {
@@ -1024,7 +1017,7 @@ CPLErr GDALRasterBand::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
                                                  nChunkXOffQueried,
                                                  nChunkYOffQueried,
                                                  nChunkXSizeQueried,
-                                                 nChunkYSizeQueried, 
+                                                 nChunkYSizeQueried,
                                                  pabyChunkNoDataMask,
                                                  nChunkXSizeQueried,
                                                  nChunkYSizeQueried,
@@ -1051,7 +1044,7 @@ CPLErr GDALRasterBand::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
                                             eBufType, (int)nPixelSpace,
                                             nDstXCount);
                             }
-                            bSkipResample = TRUE;
+                            bSkipResample = true;
                         }
                         else
                         {
@@ -1104,309 +1097,598 @@ CPLErr GDALRasterBand::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
 }
 
 /************************************************************************/
-/*                           GDALSwapWords()                            */
+/*                          RasterIOResampled()                         */
 /************************************************************************/
 
-/**
- * Byte swap words in-place.
- *
- * This function will byte swap a set of 2, 4 or 8 byte words "in place" in
- * a memory array.  No assumption is made that the words being swapped are
- * word aligned in memory.  Use the CPL_LSB and CPL_MSB macros from cpl_port.h
- * to determine if the current platform is big endian or little endian.  Use
- * The macros like CPL_SWAP32() to byte swap single values without the overhead
- * of a function call. 
- * 
- * @param pData pointer to start of data buffer.
- * @param nWordSize size of words being swapped in bytes. Normally 2, 4 or 8.
- * @param nWordCount the number of words to be swapped in this call. 
- * @param nWordSkip the byte offset from the start of one word to the start of
- * the next. For packed buffers this is the same as nWordSize. 
- */
-
-void CPL_STDCALL GDALSwapWords( void *pData, int nWordSize, int nWordCount,
-                                int nWordSkip )
+CPLErr GDALDataset::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
+                               int nXOff, int nYOff, int nXSize, int nYSize,
+                               void * pData, int nBufXSize, int nBufYSize,
+                               GDALDataType eBufType,
+                               int nBandCount, int *panBandMap,
+                               GSpacing nPixelSpace, GSpacing nLineSpace,
+                               GSpacing nBandSpace,
+                               GDALRasterIOExtraArg* psExtraArg )
 
 {
-    if (nWordCount > 0)
-        VALIDATE_POINTER0( pData , "GDALSwapWords" );
+    CPLErr eErr = CE_None;
 
-    int         i;
-    GByte       *pabyData = (GByte *) pData;
+#if 0
+    // Determine if we use warping resampling or overview resampling
+    int bUseWarp;
+    if( !GDALDataTypeIsComplex( eDataType ) )
+        bUseWarp = FALSE;
+    else
+        bUseWarp = TRUE;
+#endif
 
-    switch( nWordSize )
+    double dfXOff, dfYOff, dfXSize, dfYSize;
+    if( psExtraArg->bFloatingPointWindowValidity )
     {
-      case 1:
-        break;
-
-      case 2:
-        CPLAssert( nWordSkip >= 2 || nWordCount == 1 );
-        for( i = 0; i < nWordCount; i++ )
-        {
-            GByte       byTemp;
-
-            byTemp = pabyData[0];
-            pabyData[0] = pabyData[1];
-            pabyData[1] = byTemp;
-
-            pabyData += nWordSkip;
-        }
-        break;
-        
-      case 4:
-        CPLAssert( nWordSkip >= 4 || nWordCount == 1 );
-        for( i = 0; i < nWordCount; i++ )
-        {
-            GByte       byTemp;
-
-            byTemp = pabyData[0];
-            pabyData[0] = pabyData[3];
-            pabyData[3] = byTemp;
-
-            byTemp = pabyData[1];
-            pabyData[1] = pabyData[2];
-            pabyData[2] = byTemp;
-
-            pabyData += nWordSkip;
-        }
-        break;
-
-      case 8:
-        CPLAssert( nWordSkip >= 8 || nWordCount == 1 );
-        for( i = 0; i < nWordCount; i++ )
-        {
-            GByte       byTemp;
-
-            byTemp = pabyData[0];
-            pabyData[0] = pabyData[7];
-            pabyData[7] = byTemp;
-
-            byTemp = pabyData[1];
-            pabyData[1] = pabyData[6];
-            pabyData[6] = byTemp;
-
-            byTemp = pabyData[2];
-            pabyData[2] = pabyData[5];
-            pabyData[5] = byTemp;
-
-            byTemp = pabyData[3];
-            pabyData[3] = pabyData[4];
-            pabyData[4] = byTemp;
+        dfXOff = psExtraArg->dfXOff;
+        dfYOff = psExtraArg->dfYOff;
+        dfXSize = psExtraArg->dfXSize;
+        dfYSize = psExtraArg->dfYSize;
+        CPLAssert(dfXOff - nXOff < 1.0);
+        CPLAssert(dfYOff - nYOff < 1.0);
+        CPLAssert(nXSize - dfXSize < 1.0);
+        CPLAssert(nYSize - dfYSize < 1.0);
+    }
+    else
+    {
+        dfXOff = nXOff;
+        dfYOff = nYOff;
+        dfXSize = nXSize;
+        dfYSize = nYSize;
+    }
 
-            pabyData += nWordSkip;
-        }
-        break;
+    double dfXRatioDstToSrc = dfXSize / nBufXSize;
+    double dfYRatioDstToSrc = dfYSize / nBufYSize;
 
-      default:
-        CPLAssert( FALSE );
+    /* Determine the coordinates in the "virtual" output raster to see */
+    /* if there are not integers, in which case we will use them as a shift */
+    /* so that subwindow extracts give the exact same results as entire raster */
+    /* scaling */
+    double dfDestXOff = dfXOff / dfXRatioDstToSrc;
+    bool bHasXOffVirtual = false;
+    int nDestXOffVirtual = 0;
+    if( fabs(dfDestXOff - (int)(dfDestXOff + 0.5)) < 1e-8 )
+    {
+        bHasXOffVirtual = true;
+        dfXOff = nXOff;
+        nDestXOffVirtual = (int)(dfDestXOff + 0.5);
     }
-}
 
-#ifdef USE_NEW_COPYWORDS
-// Place the new GDALCopyWords helpers in an anonymous namespace
-namespace {
-/************************************************************************/
-/*                          GetDataLimits()                             */
-/************************************************************************/
-/**
- * Compute the limits of values that can be placed in Tout in terms of
- * Tin. Usually used for output clamping, when the output data type's
- * limits are stable relative to the input type (i.e. no roundoff error).
- *
- * @param tMaxValue the returned maximum value
- * @param tMinValue the returned minimum value
- */
+    double dfDestYOff = dfYOff / dfYRatioDstToSrc;
+    bool bHasYOffVirtual = false;
+    int nDestYOffVirtual = 0;
+    if( fabs(dfDestYOff - (int)(dfDestYOff + 0.5)) < 1e-8 )
+    {
+        bHasYOffVirtual = true;
+        dfYOff = nYOff;
+        nDestYOffVirtual = (int)(dfDestYOff + 0.5);
+    }
 
-template <class Tin, class Tout>
-inline void GetDataLimits(Tin &tMaxValue, Tin &tMinValue)
-{
-    tMaxValue = std::numeric_limits<Tin>::max();
-    tMinValue = std::numeric_limits<Tin>::min();
+    /* Create a MEM dataset that wraps the output buffer */
+    GDALDataset* poMEMDS = MEMDataset::Create("", nDestXOffVirtual + nBufXSize,
+                                              nDestYOffVirtual + nBufYSize, 0,
+                                              eBufType, NULL);
+    GDALRasterBand** papoDstBands = (GDALRasterBand**) CPLMalloc( nBandCount * sizeof(GDALRasterBand*));
+    for(int i=0;i<nBandCount;i++)
+    {
+        char szBuffer[64];
+        int nRet;
+
+        nRet = CPLPrintPointer(szBuffer, (GByte*)pData - nPixelSpace * nDestXOffVirtual
+                                - nLineSpace * nDestYOffVirtual + nBandSpace * i, sizeof(szBuffer));
+        szBuffer[nRet] = 0;
+
+        char* apszOptions[4];
+        char szBuffer0[64], szBuffer1[64], szBuffer2[64];
+        snprintf(szBuffer0, sizeof(szBuffer0), "DATAPOINTER=%s", szBuffer);
+        snprintf(szBuffer1, sizeof(szBuffer1), "PIXELOFFSET=" CPL_FRMT_GIB, (GIntBig)nPixelSpace);
+        snprintf(szBuffer2, sizeof(szBuffer2), "LINEOFFSET=" CPL_FRMT_GIB, (GIntBig)nLineSpace);
+        apszOptions[0] = szBuffer0;
+        apszOptions[1] = szBuffer1;
+        apszOptions[2] = szBuffer2;
+        apszOptions[3] = NULL;
+
+        poMEMDS->AddBand(eBufType, apszOptions);
+
+        GDALRasterBand* poSrcBand = GetRasterBand(panBandMap[i]);
+        papoDstBands[i] = poMEMDS->GetRasterBand(i+1);
+        const char* pszNBITS = poSrcBand->GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
+        if( pszNBITS )
+            poMEMDS->GetRasterBand(i+1)->SetMetadataItem("NBITS", pszNBITS, "IMAGE_STRUCTURE");
+    }
 
-    // Compute the actual minimum value of Tout in terms of Tin.
-    if (std::numeric_limits<Tout>::is_signed && std::numeric_limits<Tout>::is_integer)
+#if 0
+    /* Do the resampling */
+    if( bUseWarp )
     {
-        // the minimum value is less than zero
-        if (std::numeric_limits<Tout>::digits < std::numeric_limits<Tin>::digits ||
-			!std::numeric_limits<Tin>::is_integer)
+        VRTDatasetH hVRTDS = NULL;
+        GDALRasterBandH hVRTBand = NULL;
+        if( GetDataset() == NULL )
         {
-            // Tout is smaller than Tin, so we need to clamp values in input
-            // to the range of Tout's min/max values
-            if (std::numeric_limits<Tin>::is_signed)
+            /* Create VRT dataset that wraps the whole dataset */
+            hVRTDS = VRTCreate(nRasterXSize, nRasterYSize);
+            VRTAddBand( hVRTDS, eDataType, NULL );
+            hVRTBand = GDALGetRasterBand(hVRTDS, 1);
+            VRTAddSimpleSource( (VRTSourcedRasterBandH)hVRTBand,
+                                (GDALRasterBandH)this,
+                                0, 0,
+                                nRasterXSize, nRasterYSize,
+                                0, 0,
+                                nRasterXSize, nRasterYSize,
+                                NULL, VRT_NODATA_UNSET );
+
+            /* Add a mask band if needed */
+            if( GetMaskFlags() != GMF_ALL_VALID )
             {
-                tMinValue = static_cast<Tin>(std::numeric_limits<Tout>::min());
+                ((GDALDataset*)hVRTDS)->CreateMaskBand(0);
+                VRTSourcedRasterBand* poVRTMaskBand =
+                    (VRTSourcedRasterBand*)(((GDALRasterBand*)hVRTBand)->GetMaskBand());
+                poVRTMaskBand->
+                    AddMaskBandSource( this,
+                                    0, 0,
+                                    nRasterXSize, nRasterYSize,
+                                    0, 0,
+                                    nRasterXSize, nRasterYSize);
             }
-            tMaxValue = static_cast<Tin>(std::numeric_limits<Tout>::max());
-        }
-    }
-    else if (std::numeric_limits<Tout>::is_integer)
-    {
-        // the output is unsigned, so we just need to determine the max
-        if (std::numeric_limits<Tout>::digits <= std::numeric_limits<Tin>::digits)
-        {
-            // Tout is smaller than Tin, so we need to clamp the input values
-            // to the range of Tout's max
-            tMaxValue = static_cast<Tin>(std::numeric_limits<Tout>::max());
         }
-        tMinValue = 0;
-    }
 
-}
+        GDALWarpOptions* psWarpOptions = GDALCreateWarpOptions();
+        psWarpOptions->eResampleAlg = (GDALResampleAlg)psExtraArg->eResampleAlg;
+        psWarpOptions->hSrcDS = (GDALDatasetH) (hVRTDS ? hVRTDS : GetDataset());
+        psWarpOptions->hDstDS = (GDALDatasetH) poMEMDS;
+        psWarpOptions->nBandCount = 1;
+        int nSrcBandNumber = (hVRTDS ? 1 : nBand);
+        int nDstBandNumber = 1;
+        psWarpOptions->panSrcBands = &nSrcBandNumber;
+        psWarpOptions->panDstBands = &nDstBandNumber;
+        psWarpOptions->pfnProgress = psExtraArg->pfnProgress ?
+                    psExtraArg->pfnProgress : GDALDummyProgress;
+        psWarpOptions->pProgressArg = psExtraArg->pProgressData;
+        psWarpOptions->pfnTransformer = GDALRasterIOTransformer;
+        GDALRasterIOTransformerStruct sTransformer;
+        sTransformer.dfXOff = (bHasXOffVirtual) ? 0 : dfXOff;
+        sTransformer.dfYOff = (bHasYOffVirtual) ? 0 : dfYOff;
+        sTransformer.dfXRatioDstToSrc = dfXRatioDstToSrc;
+        sTransformer.dfYRatioDstToSrc = dfYRatioDstToSrc;
+        psWarpOptions->pTransformerArg = &sTransformer;
 
-/************************************************************************/
-/*                            ClampValue()                                */
-/************************************************************************/
-/**
- * Clamp values of type T to a specified range
- *
- * @param tValue the value
- * @param tMax the max value
- * @param tMin the min value
- */
-template <class T>
-inline T ClampValue(const T tValue, const T tMax, const T tMin)
-{
-    return tValue > tMax ? tMax :
-           tValue < tMin ? tMin : tValue;
+        GDALWarpOperationH hWarpOperation = GDALCreateWarpOperation(psWarpOptions);
+        eErr = GDALChunkAndWarpImage( hWarpOperation,
+                                      nDestXOffVirtual, nDestYOffVirtual,
+                                      nBufXSize, nBufYSize );
+        GDALDestroyWarpOperation( hWarpOperation );
+
+        psWarpOptions->panSrcBands = NULL;
+        psWarpOptions->panDstBands = NULL;
+        GDALDestroyWarpOptions( psWarpOptions );
+
+        if( hVRTDS )
+            GDALClose(hVRTDS);
+    }
+    else
+#endif
+    {
+        const char* pszResampling =
+            (psExtraArg->eResampleAlg == GRIORA_Bilinear) ? "BILINEAR" :
+            (psExtraArg->eResampleAlg == GRIORA_Cubic) ? "CUBIC" :
+            (psExtraArg->eResampleAlg == GRIORA_CubicSpline) ? "CUBICSPLINE" :
+            (psExtraArg->eResampleAlg == GRIORA_Lanczos) ? "LANCZOS" :
+            (psExtraArg->eResampleAlg == GRIORA_Average) ? "AVERAGE" :
+            (psExtraArg->eResampleAlg == GRIORA_Mode) ? "MODE" :
+            (psExtraArg->eResampleAlg == GRIORA_Gauss) ? "GAUSS" : "UNKNOWN";
+
+        GDALRasterBand* poFirstSrcBand = GetRasterBand(panBandMap[0]);
+        GDALDataType eDataType = poFirstSrcBand->GetRasterDataType();
+        int nBlockXSize, nBlockYSize;
+        poFirstSrcBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
+
+        int nKernelRadius;
+        GDALResampleFunction pfnResampleFunc =
+                        GDALGetResampleFunction(pszResampling, &nKernelRadius);
+        CPLAssert(pfnResampleFunc);
+#ifdef GDAL_ENABLE_RESAMPLING_MULTIBAND
+        GDALResampleFunctionMultiBands pfnResampleFuncMultiBands =
+                        GDALGetResampleFunctionMultiBands(pszResampling, &nKernelRadius);
+#endif
+        GDALDataType eWrkDataType =
+            GDALGetOvrWorkDataType(pszResampling, eDataType);
+
+        int nDstBlockXSize = nBufXSize;
+        int nDstBlockYSize = nBufYSize;
+        int nFullResXChunk, nFullResYChunk;
+        while( true )
+        {
+            nFullResXChunk = 3 + (int)(nDstBlockXSize * dfXRatioDstToSrc);
+            nFullResYChunk = 3 + (int)(nDstBlockYSize * dfYRatioDstToSrc);
+            if( (nDstBlockXSize == 1 && nDstBlockYSize == 1) ||
+                ((GIntBig)nFullResXChunk * nFullResYChunk <= 1024 * 1024) )
+                break;
+            /* When operating on the full width of a raster whose block width is */
+            /* the raster width, prefer doing chunks in height */
+            if( nFullResXChunk >= nXSize && nXSize == nBlockXSize && nDstBlockYSize > 1 )
+                nDstBlockYSize /= 2;
+            /* Otherwise cut the maximal dimension */
+            else if( nDstBlockXSize > 1 && nFullResXChunk > nFullResYChunk )
+                nDstBlockXSize /= 2;
+            else
+                nDstBlockYSize /= 2;
+        }
+
+        int nOvrFactor = MAX( (int)(0.5 + dfXRatioDstToSrc),
+                                (int)(0.5 + dfYRatioDstToSrc) );
+        if( nOvrFactor == 0 ) nOvrFactor = 1;
+        int nFullResXSizeQueried = nFullResXChunk + 2 * nKernelRadius * nOvrFactor;
+        int nFullResYSizeQueried = nFullResYChunk + 2 * nKernelRadius * nOvrFactor;
+
+        void * pChunk =
+            VSI_MALLOC3_VERBOSE(
+                GDALGetDataTypeSizeBytes(eWrkDataType) * nBandCount,
+                nFullResXSizeQueried, nFullResYSizeQueried );
+        GByte * pabyChunkNoDataMask = NULL;
+
+        GDALRasterBand* poMaskBand = NULL;
+        int nMaskFlags = 0;
+        bool bUseNoDataMask = false;
+
+        poMaskBand = poFirstSrcBand->GetMaskBand();
+        nMaskFlags = poFirstSrcBand->GetMaskFlags();
+
+        bUseNoDataMask = ((nMaskFlags & GMF_ALL_VALID) == 0);
+        if (bUseNoDataMask)
+        {
+            pabyChunkNoDataMask = (GByte *)
+                (GByte*) VSI_MALLOC2_VERBOSE( nFullResXSizeQueried, nFullResYSizeQueried );
+        }
+        if( pChunk == NULL || (bUseNoDataMask && pabyChunkNoDataMask == NULL) )
+        {
+            GDALClose(poMEMDS);
+            CPLFree(pChunk);
+            CPLFree(pabyChunkNoDataMask);
+            return CE_Failure;
+        }
+
+        int nTotalBlocks = ((nBufXSize + nDstBlockXSize - 1) / nDstBlockXSize) *
+                           ((nBufYSize + nDstBlockYSize - 1) / nDstBlockYSize);
+        int nBlocksDone = 0;
+
+        int nDstYOff;
+        for( nDstYOff = 0; nDstYOff < nBufYSize && eErr == CE_None;
+            nDstYOff += nDstBlockYSize )
+        {
+            int nDstYCount;
+            if  (nDstYOff + nDstBlockYSize <= nBufYSize)
+                nDstYCount = nDstBlockYSize;
+            else
+                nDstYCount = nBufYSize - nDstYOff;
+
+            int nChunkYOff = nYOff + (int) (nDstYOff * dfYRatioDstToSrc);
+            int nChunkYOff2 = nYOff + 1 + (int) ceil((nDstYOff + nDstYCount) * dfYRatioDstToSrc);
+            if( nChunkYOff2 > nRasterYSize )
+                nChunkYOff2 = nRasterYSize;
+            int nYCount = nChunkYOff2 - nChunkYOff;
+            CPLAssert(nYCount <= nFullResYChunk);
+
+            int nChunkYOffQueried = nChunkYOff - nKernelRadius * nOvrFactor;
+            int nChunkYSizeQueried = nYCount + 2 * nKernelRadius * nOvrFactor;
+            if( nChunkYOffQueried < 0 )
+            {
+                nChunkYSizeQueried += nChunkYOffQueried;
+                nChunkYOffQueried = 0;
+            }
+            if( nChunkYSizeQueried + nChunkYOffQueried > nRasterYSize )
+                nChunkYSizeQueried = nRasterYSize - nChunkYOffQueried;
+            CPLAssert(nChunkYSizeQueried <= nFullResYSizeQueried);
+
+            int nDstXOff;
+            for( nDstXOff = 0; nDstXOff < nBufXSize && eErr == CE_None;
+                nDstXOff += nDstBlockXSize )
+            {
+                int nDstXCount;
+                if  (nDstXOff + nDstBlockXSize <= nBufXSize)
+                    nDstXCount = nDstBlockXSize;
+                else
+                    nDstXCount = nBufXSize - nDstXOff;
+
+                int nChunkXOff = nXOff + (int) (nDstXOff * dfXRatioDstToSrc);
+                int nChunkXOff2 = nXOff + 1 + (int) ceil((nDstXOff + nDstXCount) * dfXRatioDstToSrc);
+                if( nChunkXOff2 > nRasterXSize )
+                    nChunkXOff2 = nRasterXSize;
+                int nXCount = nChunkXOff2 - nChunkXOff;
+                CPLAssert(nXCount <= nFullResXChunk);
+
+                int nChunkXOffQueried = nChunkXOff - nKernelRadius * nOvrFactor;
+                int nChunkXSizeQueried = nXCount + 2 * nKernelRadius * nOvrFactor;
+                if( nChunkXOffQueried < 0 )
+                {
+                    nChunkXSizeQueried += nChunkXOffQueried;
+                    nChunkXOffQueried = 0;
+                }
+                if( nChunkXSizeQueried + nChunkXOffQueried > nRasterXSize )
+                    nChunkXSizeQueried = nRasterXSize - nChunkXOffQueried;
+                CPLAssert(nChunkXSizeQueried <= nFullResXSizeQueried);
+
+                bool bSkipResample = false;
+                int bNoDataMaskFullyOpaque = FALSE;
+                if (eErr == CE_None && bUseNoDataMask)
+                {
+                    eErr = poMaskBand->RasterIO( GF_Read,
+                                                 nChunkXOffQueried,
+                                                 nChunkYOffQueried,
+                                                 nChunkXSizeQueried,
+                                                 nChunkYSizeQueried,
+                                                 pabyChunkNoDataMask,
+                                                 nChunkXSizeQueried,
+                                                 nChunkYSizeQueried,
+                                                 GDT_Byte, 0, 0, NULL );
+
+                    /* Optimizations if mask if fully opaque or transparent */
+                    int nPixels = nChunkXSizeQueried * nChunkYSizeQueried;
+                    GByte bVal = pabyChunkNoDataMask[0];
+                    int i = 1;
+                    for( ; i < nPixels; i++ )
+                    {
+                        if( pabyChunkNoDataMask[i] != bVal )
+                            break;
+                    }
+                    if( i == nPixels )
+                    {
+                        if( bVal == 0 )
+                        {
+                            float fNoDataValue = 0.f;
+                            for(int iBand=0;iBand<nBandCount;iBand++)
+                            {
+                                for(int j=0;j<nDstYCount;j++)
+                                {
+                                    GDALCopyWords(&fNoDataValue, GDT_Float32, 0,
+                                                (GByte*)pData + iBand * nBandSpace +
+                                                    nLineSpace * (j + nDstYOff) +
+                                                    nDstXOff * nPixelSpace,
+                                                eBufType, (int)nPixelSpace,
+                                                nDstXCount);
+                                }
+                            }
+                            bSkipResample = true;
+                        }
+                        else
+                        {
+                            bNoDataMaskFullyOpaque = TRUE;
+                        }
+                    }
+                }
+
+                if( !bSkipResample && eErr == CE_None )
+                {
+                    /* Read the source buffers */
+                    eErr = RasterIO( GF_Read,
+                                    nChunkXOffQueried, nChunkYOffQueried,
+                                    nChunkXSizeQueried, nChunkYSizeQueried,
+                                    pChunk,
+                                    nChunkXSizeQueried, nChunkYSizeQueried,
+                                    eWrkDataType,
+                                    nBandCount, panBandMap,
+                                    0, 0, 0, NULL );
+                }
+
+#ifdef GDAL_ENABLE_RESAMPLING_MULTIBAND
+                if( pfnResampleFuncMultiBands && !bSkipResample && eErr == CE_None )
+                {
+                    eErr = pfnResampleFuncMultiBands( dfXRatioDstToSrc,
+                                                      dfYRatioDstToSrc,
+                                                      dfXOff - nXOff, /* == 0 if bHasXOffVirtual */
+                                                      dfYOff - nYOff, /* == 0 if bHasYOffVirtual */
+                                                      eWrkDataType,
+                                                      (GByte*)pChunk,
+                                                      nBandCount,
+                                                      (bNoDataMaskFullyOpaque) ? NULL : pabyChunkNoDataMask,
+                                                      nChunkXOffQueried - ((bHasXOffVirtual) ? 0 : nXOff),
+                                                      nChunkXSizeQueried,
+                                                      nChunkYOffQueried - ((bHasYOffVirtual) ? 0 : nYOff),
+                                                      nChunkYSizeQueried,
+                                                      nDstXOff + nDestXOffVirtual,
+                                                      nDstXOff + nDestXOffVirtual + nDstXCount,
+                                                      nDstYOff + nDestYOffVirtual,
+                                                      nDstYOff + nDestYOffVirtual + nDstYCount,
+                                                      papoDstBands,
+                                                      pszResampling,
+                                                      FALSE /*bHasNoData*/,
+                                                      0.f /* fNoDataValue */,
+                                                      NULL /* color table*/,
+                                                      eDataType );
+                }
+                else
+#endif
+                {
+                    size_t nChunkBandOffset =
+                        static_cast<size_t>(nChunkXSizeQueried) *
+                        nChunkYSizeQueried *
+                        GDALGetDataTypeSizeBytes(eWrkDataType);
+                    for(int i=0; i<nBandCount && !bSkipResample && eErr == CE_None; i++ )
+                    {
+                        eErr = pfnResampleFunc( dfXRatioDstToSrc,
+                                                dfYRatioDstToSrc,
+                                                dfXOff - nXOff, /* == 0 if bHasXOffVirtual */
+                                                dfYOff - nYOff, /* == 0 if bHasYOffVirtual */
+                                                eWrkDataType,
+                                                (GByte*)pChunk + i * nChunkBandOffset,
+                                                (bNoDataMaskFullyOpaque) ? NULL : pabyChunkNoDataMask,
+                                                nChunkXOffQueried - ((bHasXOffVirtual) ? 0 : nXOff),
+                                                nChunkXSizeQueried,
+                                                nChunkYOffQueried - ((bHasYOffVirtual) ? 0 : nYOff),
+                                                nChunkYSizeQueried,
+                                                nDstXOff + nDestXOffVirtual,
+                                                nDstXOff + nDestXOffVirtual + nDstXCount,
+                                                nDstYOff + nDestYOffVirtual,
+                                                nDstYOff + nDestYOffVirtual + nDstYCount,
+                                                poMEMDS->GetRasterBand(i+1),
+                                                pszResampling,
+                                                FALSE /*bHasNoData*/,
+                                                0.f /* fNoDataValue */,
+                                                NULL /* color table*/,
+                                                eDataType );
+                    }
+                }
+
+                nBlocksDone ++;
+                if( eErr == CE_None && psExtraArg->pfnProgress != NULL &&
+                    !psExtraArg->pfnProgress(1.0 * nBlocksDone / nTotalBlocks, "",
+                                             psExtraArg->pProgressData) )
+                {
+                    eErr = CE_Failure;
+                }
+            }
+        }
+
+        CPLFree(pChunk);
+        CPLFree(pabyChunkNoDataMask);
+    }
+
+    CPLFree(papoDstBands);
+    GDALClose(poMEMDS);
+
+    return eErr;
 }
 
 /************************************************************************/
-/*                            CopyWord()                                */
+/*                           GDALSwapWords()                            */
 /************************************************************************/
+
 /**
- * Copy a single word, optionally rounding if appropriate (i.e. going
- * from the float to the integer case). Note that this is the function
- * you should specialize if you're adding a new data type.
+ * Byte swap words in-place.
+ *
+ * This function will byte swap a set of 2, 4 or 8 byte words "in place" in
+ * a memory array.  No assumption is made that the words being swapped are
+ * word aligned in memory.  Use the CPL_LSB and CPL_MSB macros from cpl_port.h
+ * to determine if the current platform is big endian or little endian.  Use
+ * The macros like CPL_SWAP32() to byte swap single values without the overhead
+ * of a function call.
  *
- * @param tValueIn value of type Tin; the input value to be converted
- * @param tValueOut value of type Tout; the output value
+ * @param pData pointer to start of data buffer.
+ * @param nWordSize size of words being swapped in bytes. Normally 2, 4 or 8.
+ * @param nWordCount the number of words to be swapped in this call.
+ * @param nWordSkip the byte offset from the start of one word to the start of
+ * the next. For packed buffers this is the same as nWordSize.
  */
 
-template <class Tin, class Tout>
-inline void CopyWord(const Tin tValueIn, Tout &tValueOut)
-{
-    Tin tMaxVal, tMinVal;
-    GetDataLimits<Tin, Tout>(tMaxVal, tMinVal);
-    tValueOut = static_cast<Tout>(ClampValue(tValueIn, tMaxVal, tMinVal));
-}
+void CPL_STDCALL GDALSwapWords( void *pData, int nWordSize, int nWordCount,
+                                int nWordSkip )
 
-template <class Tin>
-inline void CopyWord(const Tin tValueIn, float &fValueOut)
 {
-    fValueOut = (float) tValueIn;
-}
+    if (nWordCount > 0)
+        VALIDATE_POINTER0( pData , "GDALSwapWords" );
 
-template <class Tin>
-inline void CopyWord(const Tin tValueIn, double &dfValueOut)
-{
-    dfValueOut = tValueIn;
-}
+    int         i;
+    GByte       *pabyData = (GByte *) pData;
 
-inline void CopyWord(const double dfValueIn, double &dfValueOut)
-{
-    dfValueOut = dfValueIn;
-}
+    switch( nWordSize )
+    {
+      case 1:
+        break;
 
-inline void CopyWord(const float fValueIn, float &fValueOut)
-{
-    fValueOut = fValueIn;
-}
+      case 2:
+        CPLAssert( nWordSkip >= 2 || nWordCount == 1 );
+        for( i = 0; i < nWordCount; i++ )
+        {
+            GByte       byTemp;
 
-inline void CopyWord(const float fValueIn, double &dfValueOut)
-{
-    dfValueOut = fValueIn;
-}
+            byTemp = pabyData[0];
+            pabyData[0] = pabyData[1];
+            pabyData[1] = byTemp;
 
-inline void CopyWord(const double dfValueIn, float &fValueOut)
-{
-    fValueOut = static_cast<float>(dfValueIn);
-}
+            pabyData += nWordSkip;
+        }
+        break;
 
-template <class Tout>
-inline void CopyWord(const float fValueIn, Tout &tValueOut)
-{
-    float fMaxVal, fMinVal;
-    GetDataLimits<float, Tout>(fMaxVal, fMinVal);
-    tValueOut = static_cast<Tout>(
-        ClampValue(fValueIn + 0.5f, fMaxVal, fMinVal));
-}
+      case 4:
+        CPLAssert( nWordSkip >= 4 || nWordCount == 1 );
+        for( i = 0; i < nWordCount; i++ )
+        {
+            GByte       byTemp;
 
-template <class Tout>
-inline void CopyWord(const double dfValueIn, Tout &tValueOut)
-{
-    double dfMaxVal, dfMinVal;
-    GetDataLimits<double, Tout>(dfMaxVal, dfMinVal);
-    tValueOut = static_cast<Tout>(
-        ClampValue(dfValueIn + 0.5, dfMaxVal, dfMinVal));
-}
+            byTemp = pabyData[0];
+            pabyData[0] = pabyData[3];
+            pabyData[3] = byTemp;
 
-inline void CopyWord(const double dfValueIn, int &nValueOut)
-{
-    double dfMaxVal, dfMinVal;
-    GetDataLimits<double, int>(dfMaxVal, dfMinVal);
-    double dfValue = dfValueIn >= 0.0 ? dfValueIn + 0.5 :
-        dfValueIn - 0.5;
-    nValueOut = static_cast<int>(
-        ClampValue(dfValue, dfMaxVal, dfMinVal));
-}
+            byTemp = pabyData[1];
+            pabyData[1] = pabyData[2];
+            pabyData[2] = byTemp;
 
-inline void CopyWord(const float fValueIn, short &nValueOut)
-{
-    float fMaxVal, fMinVal;
-    GetDataLimits<float, short>(fMaxVal, fMinVal);
-    float fValue = fValueIn >= 0.0f ? fValueIn + 0.5f :
-        fValueIn - 0.5f;
-    nValueOut = static_cast<short>(
-        ClampValue(fValue, fMaxVal, fMinVal));
-}
+            pabyData += nWordSkip;
+        }
+        break;
 
-inline void CopyWord(const double dfValueIn, short &nValueOut)
-{
-    double dfMaxVal, dfMinVal;
-    GetDataLimits<double, short>(dfMaxVal, dfMinVal);
-    double dfValue = dfValueIn > 0.0 ? dfValueIn + 0.5 :
-        dfValueIn - 0.5;
-    nValueOut = static_cast<short>(
-        ClampValue(dfValue, dfMaxVal, dfMinVal));
-}
+      case 8:
+        CPLAssert( nWordSkip >= 8 || nWordCount == 1 );
+        for( i = 0; i < nWordCount; i++ )
+        {
+            GByte       byTemp;
 
-// Roundoff occurs for Float32 -> int32 for max/min. Overload CopyWord
-// specifically for this case.
-inline void CopyWord(const float fValueIn, int &nValueOut)
-{
-    if (fValueIn >= static_cast<float>(std::numeric_limits<int>::max()))
-    {
-        nValueOut = std::numeric_limits<int>::max();
-    }
-    else if (fValueIn <= static_cast<float>(std::numeric_limits<int>::min()))
-    {
-        nValueOut = std::numeric_limits<int>::min();
-    }
-    else
-    {
-        nValueOut = static_cast<int>(fValueIn > 0.0f ? 
-            fValueIn + 0.5f : fValueIn - 0.5f);
+            byTemp = pabyData[0];
+            pabyData[0] = pabyData[7];
+            pabyData[7] = byTemp;
+
+            byTemp = pabyData[1];
+            pabyData[1] = pabyData[6];
+            pabyData[6] = byTemp;
+
+            byTemp = pabyData[2];
+            pabyData[2] = pabyData[5];
+            pabyData[5] = byTemp;
+
+            byTemp = pabyData[3];
+            pabyData[3] = pabyData[4];
+            pabyData[4] = byTemp;
+
+            pabyData += nWordSkip;
+        }
+        break;
+
+      default:
+        CPLAssert( FALSE );
     }
 }
 
-// Roundoff occurs for Float32 -> uint32 for max. Overload CopyWord
-// specifically for this case.
-inline void CopyWord(const float fValueIn, unsigned int &nValueOut)
+/************************************************************************/
+/*                           GDALSwapWordsEx()                          */
+/************************************************************************/
+
+/**
+ * Byte swap words in-place.
+ *
+ * This function will byte swap a set of 2, 4 or 8 byte words "in place" in
+ * a memory array.  No assumption is made that the words being swapped are
+ * word aligned in memory.  Use the CPL_LSB and CPL_MSB macros from cpl_port.h
+ * to determine if the current platform is big endian or little endian.  Use
+ * The macros like CPL_SWAP32() to byte swap single values without the overhead
+ * of a function call.
+ *
+ * @param pData pointer to start of data buffer.
+ * @param nWordSize size of words being swapped in bytes. Normally 2, 4 or 8.
+ * @param nWordCount the number of words to be swapped in this call.
+ * @param nWordSkip the byte offset from the start of one word to the start of
+ * the next. For packed buffers this is the same as nWordSize.
+ * @since GDAL 2.1
+ */
+void CPL_STDCALL GDALSwapWordsEx( void *pData, int nWordSize, size_t nWordCount,
+                                  int nWordSkip )
 {
-    if (fValueIn >= static_cast<float>(std::numeric_limits<unsigned int>::max()))
-    {
-        nValueOut = std::numeric_limits<unsigned int>::max();
-    }
-    else if (fValueIn <= static_cast<float>(std::numeric_limits<unsigned int>::min()))
-    {
-        nValueOut = std::numeric_limits<unsigned int>::min();
-    }
-    else
-    {
-        nValueOut = static_cast<unsigned int>(fValueIn + 0.5f);
+    GByte* pabyData = reinterpret_cast<GByte*>(pData);
+    while( nWordCount )
+    {
+        /* Pick-up a multiple of 8 as max chunk size */
+        int nWordCountSmall = (nWordCount > (1 << 30)) ? (1 << 30) : static_cast<int>(nWordCount);
+        GDALSwapWords(pabyData, nWordSize, nWordCountSmall, nWordSkip);
+        pabyData += static_cast<size_t>(nWordSkip) * nWordCountSmall;
+        nWordCount -= nWordCountSmall;
     }
 }
 
+// Place the new GDALCopyWords helpers in an anonymous namespace
+namespace {
+
 /************************************************************************/
 /*                           GDALCopyWordsT()                           */
 /************************************************************************/
@@ -1426,10 +1708,10 @@ inline void CopyWord(const float fValueIn, unsigned int &nValueOut)
  * @param nWordCount the total number of pixel words to copy
  *
  * @code
- * // Assume an input buffer of type GUInt16 named pBufferIn 
+ * // Assume an input buffer of type GUInt16 named pBufferIn
  * GByte *pBufferOut = new GByte[numBytesOut];
  * GDALCopyWordsT<GUInt16, GByte>(pSrcData, 2, pDstData, 1, numBytesOut);
- * @code
+ * @endcode
  * @note
  * This is a private function, and should not be exposed outside of rasterio.cpp.
  * External users should call the GDALCopyWords driver function.
@@ -1437,32 +1719,90 @@ inline void CopyWord(const float fValueIn, unsigned int &nValueOut)
  */
 
 template <class Tin, class Tout>
-static void GDALCopyWordsT(const Tin* const pSrcData, int nSrcPixelStride,
-                           Tout* const pDstData, int nDstPixelStride,
+static void GDALCopyWordsT(const Tin* const CPL_RESTRICT pSrcData, int nSrcPixelStride,
+                           Tout* const CPL_RESTRICT pDstData, int nDstPixelStride,
                            int nWordCount)
 {
     std::ptrdiff_t nDstOffset = 0;
 
     const char* const pSrcDataPtr = reinterpret_cast<const char*>(pSrcData);
     char* const pDstDataPtr = reinterpret_cast<char*>(pDstData);
-    for (std::ptrdiff_t n = 0; n < nWordCount; n++)
+    for (std::ptrdiff_t n = 0; n < nWordCount; n++  )
+    {
+        const Tin tValue = *reinterpret_cast<const Tin*>(pSrcDataPtr + (n * nSrcPixelStride));
+        Tout* const pOutPixel = reinterpret_cast<Tout*>(pDstDataPtr + nDstOffset);
+
+        GDALCopyWord(tValue, *pOutPixel);
+
+        nDstOffset += nDstPixelStride;
+    }
+}
+
+
+template <class Tin, class Tout>
+static void GDALCopyWordsT_4atatime(const Tin* const CPL_RESTRICT pSrcData, int nSrcPixelStride,
+                           Tout* const CPL_RESTRICT pDstData, int nDstPixelStride,
+                           int nWordCount)
+{
+    std::ptrdiff_t nDstOffset = 0;
+
+    const char* const pSrcDataPtr = reinterpret_cast<const char*>(pSrcData);
+    char* const pDstDataPtr = reinterpret_cast<char*>(pDstData);
+    std::ptrdiff_t n = 0;
+    if( nSrcPixelStride == (int)sizeof(Tin) && nDstPixelStride == (int)sizeof(Tout) )
+    {
+        for (; n < nWordCount-3; n+=4)
+        {
+            const Tin* pInValues = reinterpret_cast<const Tin*>(pSrcDataPtr + (n * nSrcPixelStride));
+            Tout* const pOutPixels = reinterpret_cast<Tout*>(pDstDataPtr + nDstOffset);
+
+            GDALCopy4Words(pInValues, pOutPixels);
+
+            nDstOffset += 4 * nDstPixelStride;
+        }
+    }
+    for( ; n < nWordCount; n++  )
     {
         const Tin tValue = *reinterpret_cast<const Tin*>(pSrcDataPtr + (n * nSrcPixelStride));
         Tout* const pOutPixel = reinterpret_cast<Tout*>(pDstDataPtr + nDstOffset);
 
-        CopyWord(tValue, *pOutPixel);
+        GDALCopyWord(tValue, *pOutPixel);
 
         nDstOffset += nDstPixelStride;
     }
 }
 
+static void GDALCopyWordsT(const float* const CPL_RESTRICT pSrcData, int nSrcPixelStride,
+                           GByte* const CPL_RESTRICT pDstData, int nDstPixelStride,
+                           int nWordCount)
+{
+    GDALCopyWordsT_4atatime(pSrcData, nSrcPixelStride,
+                            pDstData, nDstPixelStride, nWordCount);
+}
+
+static void GDALCopyWordsT(const float* const CPL_RESTRICT pSrcData, int nSrcPixelStride,
+                           GInt16* const CPL_RESTRICT pDstData, int nDstPixelStride,
+                           int nWordCount)
+{
+    GDALCopyWordsT_4atatime(pSrcData, nSrcPixelStride,
+                            pDstData, nDstPixelStride, nWordCount);
+}
+
+static void GDALCopyWordsT(const float* const CPL_RESTRICT pSrcData, int nSrcPixelStride,
+                           GUInt16* const CPL_RESTRICT pDstData, int nDstPixelStride,
+                           int nWordCount)
+{
+    GDALCopyWordsT_4atatime(pSrcData, nSrcPixelStride,
+                            pDstData, nDstPixelStride, nWordCount);
+}
+
 /************************************************************************/
 /*                   GDALCopyWordsComplexT()                            */
 /************************************************************************/
 /**
  * Template function, used to copy data from pSrcData into buffer
  * pDstData, with stride nSrcPixelStride in the source data and
- * stride nDstPixelStride in the destination data. Deals with the 
+ * stride nDstPixelStride in the destination data. Deals with the
  * complex case, where input is complex and output is complex.
  *
  * @param pSrcData the source data buffer
@@ -1475,8 +1815,8 @@ static void GDALCopyWordsT(const Tin* const pSrcData, int nSrcPixelStride,
  *
  */
 template <class Tin, class Tout>
-inline void GDALCopyWordsComplexT(const Tin* const pSrcData, int nSrcPixelStride,
-                                  Tout* const pDstData, int nDstPixelStride,
+inline void GDALCopyWordsComplexT(const Tin* const CPL_RESTRICT pSrcData, int nSrcPixelStride,
+                                  Tout* const CPL_RESTRICT pDstData, int nDstPixelStride,
                                   int nWordCount)
 {
     std::ptrdiff_t nDstOffset = 0;
@@ -1486,15 +1826,15 @@ inline void GDALCopyWordsComplexT(const Tin* const pSrcData, int nSrcPixelStride
     // Determine the minimum and maximum value we can have based
     // on the constraints of Tin and Tout.
     Tin tMaxValue, tMinValue;
-    GetDataLimits<Tin, Tout>(tMaxValue, tMinValue);
+    GDALGetDataLimits<Tin, Tout>(tMaxValue, tMinValue);
 
     for (std::ptrdiff_t n = 0; n < nWordCount; n++)
     {
         const Tin* const pPixelIn = reinterpret_cast<const Tin*>(pSrcDataPtr + n * nSrcPixelStride);
         Tout* const pPixelOut = reinterpret_cast<Tout*>(pDstDataPtr + nDstOffset);
 
-        CopyWord(pPixelIn[0], pPixelOut[0]);
-        CopyWord(pPixelIn[1], pPixelOut[1]);
+        GDALCopyWord(pPixelIn[0], pPixelOut[0]);
+        GDALCopyWord(pPixelIn[1], pPixelOut[1]);
 
         nDstOffset += nDstPixelStride;
     }
@@ -1506,7 +1846,7 @@ inline void GDALCopyWordsComplexT(const Tin* const pSrcData, int nSrcPixelStride
 /**
  * Template function, used to copy data from pSrcData into buffer
  * pDstData, with stride nSrcPixelStride in the source data and
- * stride nDstPixelStride in the destination data. Deals with the 
+ * stride nDstPixelStride in the destination data. Deals with the
  * case where the value is real coming in, but complex going out.
  *
  * @param pSrcData the source data buffer
@@ -1519,8 +1859,8 @@ inline void GDALCopyWordsComplexT(const Tin* const pSrcData, int nSrcPixelStride
  *
  */
 template <class Tin, class Tout>
-inline void GDALCopyWordsComplexOutT(const Tin* const pSrcData, int nSrcPixelStride,
-                                     Tout* const pDstData, int nDstPixelStride,
+inline void GDALCopyWordsComplexOutT(const Tin* const CPL_RESTRICT pSrcData, int nSrcPixelStride,
+                                     Tout* const CPL_RESTRICT pDstData, int nDstPixelStride,
                                      int nWordCount)
 {
     std::ptrdiff_t nDstOffset = 0;
@@ -1532,9 +1872,9 @@ inline void GDALCopyWordsComplexOutT(const Tin* const pSrcData, int nSrcPixelStr
 
     for (std::ptrdiff_t n = 0; n < nWordCount; n++)
     {
-        const Tin tValue = *reinterpret_cast<const Tin* const>(pSrcDataPtr + n * nSrcPixelStride);
+        const Tin tValue = *reinterpret_cast<const Tin*>(pSrcDataPtr + n * nSrcPixelStride);
         Tout* const pPixelOut = reinterpret_cast<Tout*>(pDstDataPtr + nDstOffset);
-        CopyWord(tValue, *pPixelOut);
+        GDALCopyWord(tValue, *pPixelOut);
 
         pPixelOut[1] = tOutZero;
 
@@ -1559,8 +1899,8 @@ inline void GDALCopyWordsComplexOutT(const Tin* const pSrcData, int nSrcPixelStr
  * @param nWordCount number of pixel words to be copied
  */
 template <class T>
-inline void GDALCopyWordsFromT(const T* const pSrcData, int nSrcPixelStride, bool bInComplex,
-                               void *pDstData, GDALDataType eDstType, int nDstPixelStride,
+inline void GDALCopyWordsFromT(const T* const CPL_RESTRICT pSrcData, int nSrcPixelStride, bool bInComplex,
+                               void * CPL_RESTRICT pDstData, GDALDataType eDstType, int nDstPixelStride,
                                int nWordCount)
 {
     switch (eDstType)
@@ -1663,14 +2003,14 @@ inline void GDALCopyWordsFromT(const T* const pSrcData, int nSrcPixelStride, boo
 }
 
 } // end anonymous namespace
-#endif
 
 /************************************************************************/
 /*                          GDALReplicateWord()                         */
 /************************************************************************/
 
-void GDALReplicateWord(void *pSrcData, GDALDataType eSrcType,
-                       void *pDstData, GDALDataType eDstType, int nDstPixelStride,
+static
+void GDALReplicateWord(const void * CPL_RESTRICT pSrcData, GDALDataType eSrcType,
+                       void * CPL_RESTRICT pDstData, GDALDataType eDstType, int nDstPixelStride,
                        int nWordCount)
 {
 /* ----------------------------------------------------------------------- */
@@ -1680,8 +2020,8 @@ void GDALReplicateWord(void *pSrcData, GDALDataType eSrcType,
 /* ----------------------------------------------------------------------- */
     /* Let the general translation case do the necessary conversions */
     /* on the first destination element */
-    GDALCopyWords(pSrcData, eSrcType, 0,
-                  pDstData, eDstType, nDstPixelStride,
+    GDALCopyWords((void*)pSrcData, eSrcType, 0,
+                  pDstData, eDstType, 0,
                   1 );
 
     /* Now copy the first element to the nWordCount - 1 following destination */
@@ -1721,35 +2061,141 @@ void GDALReplicateWord(void *pSrcData, GDALDataType eSrcType,
             } \
             break; \
         }
-
-        CASE_DUPLICATE_SIMPLE(GDT_UInt16, GUInt16)
-        CASE_DUPLICATE_SIMPLE(GDT_Int16,  GInt16)
-        CASE_DUPLICATE_SIMPLE(GDT_UInt32, GUInt32)
-        CASE_DUPLICATE_SIMPLE(GDT_Int32,  GInt32)
-        CASE_DUPLICATE_SIMPLE(GDT_Float32,float)
-        CASE_DUPLICATE_SIMPLE(GDT_Float64,double)
-
-#define CASE_DUPLICATE_COMPLEX(enum_type, c_type) \
-        case enum_type:\
-        { \
-            c_type valSet1 = ((c_type*)pDstData)[0]; \
-            c_type valSet2 = ((c_type*)pDstData)[1]; \
-            while(nWordCount--) \
-            { \
-                ((c_type*)pabyDstWord)[0] = valSet1; \
-                ((c_type*)pabyDstWord)[1] = valSet2; \
-                pabyDstWord += nDstPixelStride; \
-            } \
-            break; \
+
+        CASE_DUPLICATE_SIMPLE(GDT_UInt16, GUInt16)
+        CASE_DUPLICATE_SIMPLE(GDT_Int16,  GInt16)
+        CASE_DUPLICATE_SIMPLE(GDT_UInt32, GUInt32)
+        CASE_DUPLICATE_SIMPLE(GDT_Int32,  GInt32)
+        CASE_DUPLICATE_SIMPLE(GDT_Float32,float)
+        CASE_DUPLICATE_SIMPLE(GDT_Float64,double)
+
+#define CASE_DUPLICATE_COMPLEX(enum_type, c_type) \
+        case enum_type:\
+        { \
+            c_type valSet1 = ((c_type*)pDstData)[0]; \
+            c_type valSet2 = ((c_type*)pDstData)[1]; \
+            while(nWordCount--) \
+            { \
+                ((c_type*)pabyDstWord)[0] = valSet1; \
+                ((c_type*)pabyDstWord)[1] = valSet2; \
+                pabyDstWord += nDstPixelStride; \
+            } \
+            break; \
+        }
+
+        CASE_DUPLICATE_COMPLEX(GDT_CInt16, GInt16)
+        CASE_DUPLICATE_COMPLEX(GDT_CInt32, GInt32)
+        CASE_DUPLICATE_COMPLEX(GDT_CFloat32, float)
+        CASE_DUPLICATE_COMPLEX(GDT_CFloat64, double)
+
+        default:
+            CPLAssert( FALSE );
+    }
+}
+
+/************************************************************************/
+/*                        GDALUnrolledByteCopy()                        */
+/************************************************************************/
+
+template<int srcStride, int dstStride>
+static inline void GDALUnrolledByteCopy(GByte* CPL_RESTRICT pabyDest,
+                                    const GByte* CPL_RESTRICT pabySrc,
+                                    int nIters)
+{
+    if (nIters >= 16)
+    {
+        for ( int i = nIters / 16; i != 0; i -- )
+        {
+            pabyDest[0*dstStride] = pabySrc[0*srcStride];
+            pabyDest[1*dstStride] = pabySrc[1*srcStride];
+            pabyDest[2*dstStride] = pabySrc[2*srcStride];
+            pabyDest[3*dstStride] = pabySrc[3*srcStride];
+            pabyDest[4*dstStride] = pabySrc[4*srcStride];
+            pabyDest[5*dstStride] = pabySrc[5*srcStride];
+            pabyDest[6*dstStride] = pabySrc[6*srcStride];
+            pabyDest[7*dstStride] = pabySrc[7*srcStride];
+            pabyDest[8*dstStride] = pabySrc[8*srcStride];
+            pabyDest[9*dstStride] = pabySrc[9*srcStride];
+            pabyDest[10*dstStride] = pabySrc[10*srcStride];
+            pabyDest[11*dstStride] = pabySrc[11*srcStride];
+            pabyDest[12*dstStride] = pabySrc[12*srcStride];
+            pabyDest[13*dstStride] = pabySrc[13*srcStride];
+            pabyDest[14*dstStride] = pabySrc[14*srcStride];
+            pabyDest[15*dstStride] = pabySrc[15*srcStride];
+            pabyDest += 16*dstStride;
+            pabySrc += 16*srcStride;
+        }
+        nIters = nIters % 16;
+    }
+    for( int i = 0; i < nIters; i++ )
+    {
+        pabyDest[i*dstStride] = *pabySrc;
+        pabySrc += srcStride;
+    }
+}
+
+/************************************************************************/
+/*                         GDALFastByteCopy()                           */
+/************************************************************************/
+
+static inline void GDALFastByteCopy(GByte* CPL_RESTRICT pabyDest,
+                                    int nDestStride,
+                                    const GByte* CPL_RESTRICT pabySrc,
+                                    int nSrcStride,
+                                    int nIters)
+{
+    if( nDestStride == 1 )
+    {
+        if( nSrcStride == 1 )
+        {
+            memcpy(pabyDest, pabySrc, nIters);
+        }
+        else if( nSrcStride == 3 )
+        {
+            GDALUnrolledByteCopy<3,1>(pabyDest, pabySrc, nIters);
+        }
+        else if( nSrcStride == 4 )
+        {
+            GDALUnrolledByteCopy<4,1>(pabyDest, pabySrc, nIters);
+        }
+        else
+        {
+            while( nIters-- > 0 )
+            {
+                *pabyDest = *pabySrc;
+                pabySrc += nSrcStride;
+                pabyDest ++;
+            }
+        }
+    }
+    else if( nSrcStride == 1 )
+    {
+        if( nDestStride == 3 )
+        {
+            GDALUnrolledByteCopy<1,3>(pabyDest, pabySrc, nIters);
+        }
+        else if( nDestStride == 4 )
+        {
+            GDALUnrolledByteCopy<1,4>(pabyDest, pabySrc, nIters);
+        }
+        else
+        {
+            while( nIters-- > 0 )
+            {
+                *pabyDest = *pabySrc;
+                pabySrc ++;
+                pabyDest += nDestStride;
+            }
+        }
+    }
+    else
+    {
+        while( nIters-- > 0 )
+        {
+            *pabyDest = *pabySrc;
+            pabySrc += nSrcStride;
+            pabyDest += nDestStride;
         }
-
-        CASE_DUPLICATE_COMPLEX(GDT_CInt16, GInt16)
-        CASE_DUPLICATE_COMPLEX(GDT_CInt32, GInt32)
-        CASE_DUPLICATE_COMPLEX(GDT_CFloat32, float)
-        CASE_DUPLICATE_COMPLEX(GDT_CFloat64, double)
-
-        default:
-            CPLAssert( FALSE );
     }
 }
 
@@ -1762,19 +2208,19 @@ void GDALReplicateWord(void *pSrcData, GDALDataType eSrcType,
  *
  * This function is used to copy pixel word values from one memory buffer
  * to another, with support for conversion between data types, and differing
- * step factors.  The data type conversion is done using the normal GDAL 
+ * step factors.  The data type conversion is done using the normal GDAL
  * rules.  Values assigned to a lower range integer type are clipped.  For
  * instance assigning GDT_Int16 values to a GDT_Byte buffer will cause values
- * less the 0 to be set to 0, and values larger than 255 to be set to 255. 
+ * less the 0 to be set to 0, and values larger than 255 to be set to 255.
  * Assignment from floating point to integer uses default C type casting
- * semantics.   Assignment from non-complex to complex will result in the 
- * imaginary part being set to zero on output.  Assigment from complex to 
+ * semantics.   Assignment from non-complex to complex will result in the
+ * imaginary part being set to zero on output.  Assignment from complex to
  * non-complex will result in the complex portion being lost and the real
- * component being preserved (<i>not magnitidue!</i>). 
+ * component being preserved (<i>not magnitidue!</i>).
  *
- * No assumptions are made about the source or destination words occuring
+ * No assumptions are made about the source or destination words occurring
  * on word boundaries.  It is assumed that all values are in native machine
- * byte order. 
+ * byte order.
  *
  * @param pSrcData Pointer to source data to be converted.
  * @param eSrcType the source data type (see GDALDataType enum)
@@ -1784,8 +2230,7 @@ void GDALReplicateWord(void *pSrcData, GDALDataType eSrcType,
  * @param nDstPixelStride Destination pixel stride (i.e. distance between 2 words), in bytes
  * @param nWordCount number of words to be copied
  *
- * 
- * @note 
+ * @note
  * When adding a new data type to GDAL, you must do the following to
  * support it properly within the GDALCopyWords function:
  * 1. Add the data type to the switch on eSrcType in GDALCopyWords.
@@ -1799,11 +2244,54 @@ void GDALReplicateWord(void *pSrcData, GDALDataType eSrcType,
  */
 
 void CPL_STDCALL
-GDALCopyWords( void * pSrcData, GDALDataType eSrcType, int nSrcPixelStride,
-               void * pDstData, GDALDataType eDstType, int nDstPixelStride,
+GDALCopyWords( const void * CPL_RESTRICT pSrcData, GDALDataType eSrcType, int nSrcPixelStride,
+               void * CPL_RESTRICT pDstData, GDALDataType eDstType, int nDstPixelStride,
                int nWordCount )
 
 {
+    // On platforms where alignment matters, be careful
+    const int nSrcDataTypeSize = GDALGetDataTypeSizeBytes(eSrcType);
+#ifdef CPL_CPU_REQUIRES_ALIGNED_ACCESS
+    const int nDstDataTypeSize = GDALGetDataTypeSizeBytes(eDstType);
+    if( !(eSrcType == eDstType && nSrcPixelStride == nDstPixelStride) &&
+        ( (((GPtrDiff_t)pSrcData) % nSrcDataTypeSize) != 0 ||
+          (((GPtrDiff_t)pDstData) % nDstDataTypeSize) != 0 ||
+          ( nSrcPixelStride % nSrcDataTypeSize) != 0 ||
+          ( nDstPixelStride % nDstDataTypeSize) != 0 ) )
+    {
+        if( eSrcType == eDstType )
+        {
+            for( int i = 0; i < nWordCount; i++ )
+            {
+                memcpy( (GByte*)pDstData + nDstPixelStride * i,
+                        (GByte*)pSrcData + nSrcPixelStride * i,
+                        nDstDataTypeSize );
+            }
+        }
+        else
+        {
+#define ALIGN_PTR(ptr, align) ((ptr) + ((align) - ((size_t)(ptr) % (align))) % (align))
+            GByte abySrcBuffer[32]; /* the largest we need is for CFloat64 (16 bytes), so 32 bytes to be sure to get correctly aligned pointer */
+            GByte abyDstBuffer[32];
+            GByte* pabySrcBuffer = ALIGN_PTR(abySrcBuffer, nSrcDataTypeSize);
+            GByte* pabyDstBuffer = ALIGN_PTR(abyDstBuffer, nDstDataTypeSize);
+            for( int i = 0; i < nWordCount; i++ )
+            {
+                memcpy(pabySrcBuffer, (GByte*)pSrcData + nSrcPixelStride * i, nSrcDataTypeSize);
+                GDALCopyWords( pabySrcBuffer,
+                            eSrcType,
+                            0,
+                            pabyDstBuffer,
+                            eDstType,
+                            0,
+                            1 );
+                memcpy( (GByte*)pDstData + nDstPixelStride * i, pabyDstBuffer, nDstDataTypeSize );
+            }
+        }
+        return;
+    }
+#endif
+
     // Deal with the case where we're replicating a single word into the
     // provided buffer
     if (nSrcPixelStride == 0 && nWordCount > 1)
@@ -1812,16 +2300,40 @@ GDALCopyWords( void * pSrcData, GDALDataType eSrcType, int nSrcPixelStride,
         return;
     }
 
-#ifdef USE_NEW_COPYWORDS
-
-    int nSrcDataTypeSize = GDALGetDataTypeSize(eSrcType) / 8;
-    // Let memcpy() handle the case where we're copying a packed buffer
-    // of pixels.
-    if (eSrcType == eDstType && nSrcPixelStride == nDstPixelStride &&
-        nSrcPixelStride == nSrcDataTypeSize)
+    if (eSrcType == eDstType)
     {
-        memcpy(pDstData, pSrcData, nWordCount * nSrcDataTypeSize);
-        return;
+        if( eSrcType == GDT_Byte )
+        {
+            GDALFastByteCopy((GByte*)pDstData, nDstPixelStride,
+                             (const GByte*)pSrcData, nSrcPixelStride, nWordCount);
+            return;
+        }
+
+        if( nWordCount == 1 )
+        {
+            if( eSrcType == GDT_Int16 || eSrcType == GDT_UInt16 )
+                memcpy(pDstData, pSrcData, 2);
+            else if( eSrcType == GDT_Int32 || eSrcType == GDT_UInt32 ||
+                     eSrcType == GDT_Float32 || eSrcType == GDT_CInt16 )
+                memcpy(pDstData, pSrcData, 4);
+            else if( eSrcType == GDT_Float64 || eSrcType == GDT_CInt32 ||
+                     eSrcType == GDT_CFloat32 )
+                memcpy(pDstData, pSrcData, 8 );
+            else /* if( eSrcType == GDT_CFloat64 ) */
+                memcpy(pDstData, pSrcData, 16);
+            return;
+        }
+
+        // Let memcpy() handle the case where we're copying a packed buffer
+        // of pixels.
+        if( nSrcPixelStride == nDstPixelStride )
+        {
+            if( nSrcPixelStride == nSrcDataTypeSize)
+            {
+                memcpy(pDstData, pSrcData, nWordCount * nSrcDataTypeSize);
+                return;
+            }
+        }
     }
 
     // Handle the more general case -- deals with conversion of data types
@@ -1829,57 +2341,57 @@ GDALCopyWords( void * pSrcData, GDALDataType eSrcType, int nSrcPixelStride,
     switch (eSrcType)
     {
     case GDT_Byte:
-        GDALCopyWordsFromT<unsigned char>(static_cast<unsigned char *>(pSrcData), nSrcPixelStride, false,
+        GDALCopyWordsFromT<unsigned char>(static_cast<const unsigned char *>(pSrcData), nSrcPixelStride, false,
                                  pDstData, eDstType, nDstPixelStride,
                                  nWordCount);
         break;
     case GDT_UInt16:
-        GDALCopyWordsFromT<unsigned short>(static_cast<unsigned short *>(pSrcData), nSrcPixelStride, false,
+        GDALCopyWordsFromT<unsigned short>(static_cast<const unsigned short *>(pSrcData), nSrcPixelStride, false,
                                            pDstData, eDstType, nDstPixelStride,
                                            nWordCount);
         break;
     case GDT_Int16:
-        GDALCopyWordsFromT<short>(static_cast<short *>(pSrcData), nSrcPixelStride, false,
+        GDALCopyWordsFromT<short>(static_cast<const short *>(pSrcData), nSrcPixelStride, false,
                                   pDstData, eDstType, nDstPixelStride,
                                   nWordCount);
         break;
     case GDT_UInt32:
-        GDALCopyWordsFromT<unsigned int>(static_cast<unsigned int *>(pSrcData), nSrcPixelStride, false,
+        GDALCopyWordsFromT<unsigned int>(static_cast<const unsigned int *>(pSrcData), nSrcPixelStride, false,
                                          pDstData, eDstType, nDstPixelStride,
                                          nWordCount);
         break;
     case GDT_Int32:
-        GDALCopyWordsFromT<int>(static_cast<int *>(pSrcData), nSrcPixelStride, false,
+        GDALCopyWordsFromT<int>(static_cast<const int *>(pSrcData), nSrcPixelStride, false,
                                 pDstData, eDstType, nDstPixelStride,
                                 nWordCount);
         break;
     case GDT_Float32:
-        GDALCopyWordsFromT<float>(static_cast<float *>(pSrcData), nSrcPixelStride, false,
+        GDALCopyWordsFromT<float>(static_cast<const float *>(pSrcData), nSrcPixelStride, false,
                                   pDstData, eDstType, nDstPixelStride,
                                   nWordCount);
         break;
     case GDT_Float64:
-        GDALCopyWordsFromT<double>(static_cast<double *>(pSrcData), nSrcPixelStride, false,
+        GDALCopyWordsFromT<double>(static_cast<const double *>(pSrcData), nSrcPixelStride, false,
                                    pDstData, eDstType, nDstPixelStride,
                                    nWordCount);
         break;
     case GDT_CInt16:
-        GDALCopyWordsFromT<short>(static_cast<short *>(pSrcData), nSrcPixelStride, true,
+        GDALCopyWordsFromT<short>(static_cast<const short *>(pSrcData), nSrcPixelStride, true,
                                  pDstData, eDstType, nDstPixelStride,
                                  nWordCount);
         break;
     case GDT_CInt32:
-        GDALCopyWordsFromT<int>(static_cast<int *>(pSrcData), nSrcPixelStride, true,
+        GDALCopyWordsFromT<int>(static_cast<const int *>(pSrcData), nSrcPixelStride, true,
                                  pDstData, eDstType, nDstPixelStride,
                                  nWordCount);
         break;
     case GDT_CFloat32:
-        GDALCopyWordsFromT<float>(static_cast<float *>(pSrcData), nSrcPixelStride, true,
+        GDALCopyWordsFromT<float>(static_cast<const float *>(pSrcData), nSrcPixelStride, true,
                                  pDstData, eDstType, nDstPixelStride,
                                  nWordCount);
         break;
     case GDT_CFloat64:
-        GDALCopyWordsFromT<double>(static_cast<double *>(pSrcData), nSrcPixelStride, true,
+        GDALCopyWordsFromT<double>(static_cast<const double *>(pSrcData), nSrcPixelStride, true,
                                  pDstData, eDstType, nDstPixelStride,
                                  nWordCount);
         break;
@@ -1887,732 +2399,6 @@ GDALCopyWords( void * pSrcData, GDALDataType eSrcType, int nSrcPixelStride,
     default:
         CPLAssert(FALSE);
     }
-
-#else // undefined USE_NEW_COPYWORDS
-/* -------------------------------------------------------------------- */
-/*      Special case when no data type translation is required.         */
-/* -------------------------------------------------------------------- */
-    if( eSrcType == eDstType )
-    {
-        int     nWordSize = GDALGetDataTypeSize(eSrcType)/8;
-        int     i;
-
-        // contiguous blocks.
-        if( nWordSize == nSrcPixelStride && nWordSize == nDstPixelStride )
-        {
-            memcpy( pDstData, pSrcData, nSrcPixelStride * nWordCount );
-            return;
-        }
-
-        GByte *pabySrc = (GByte *) pSrcData;
-        GByte *pabyDst = (GByte *) pDstData;
-
-        // Moving single bytes.
-        if( nWordSize == 1 )
-        {
-            if (nWordCount > 100)
-            {
-/* ==================================================================== */
-/*     Optimization for high number of words to transfer and some       */
-/*     typical source and destination pixel spacing : we unroll the     */
-/*     loop.                                                            */
-/* ==================================================================== */
-#define ASSIGN(_nSrcPixelStride, _nDstPixelStride, _k) \
-                 pabyDst[_nDstPixelStride * _k] = pabySrc[_nSrcPixelStride * _k]
-#define ASSIGN_LOOP(_nSrcPixelStride, _nDstPixelStride) \
-                for( i = nWordCount / 16 ; i != 0; i-- ) \
-                { \
-                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 0); \
-                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 1); \
-                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 2); \
-                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 3); \
-                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 4); \
-                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 5); \
-                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 6); \
-                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 7); \
-                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 8); \
-                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 9); \
-                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 10); \
-                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 11); \
-                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 12); \
-                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 13); \
-                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 14); \
-                    ASSIGN(_nSrcPixelStride, _nDstPixelStride, 15); \
-                    pabyDst += _nDstPixelStride * 16; \
-                    pabySrc += _nSrcPixelStride * 16; \
-                } \
-                nWordCount = nWordCount % 16;
-
-                if (nSrcPixelStride == 3 && nDstPixelStride == 1)
-                {
-                    ASSIGN_LOOP(3, 1)
-                }
-                else if (nSrcPixelStride == 1 && nDstPixelStride == 3)
-                {
-                    ASSIGN_LOOP(1, 3)
-                }
-                else if (nSrcPixelStride == 4 && nDstPixelStride == 1)
-                {
-                    ASSIGN_LOOP(4, 1)
-                }
-                else if (nSrcPixelStride == 1 && nDstPixelStride == 4)
-                {
-                    ASSIGN_LOOP(1, 4)
-                }
-                else if (nSrcPixelStride == 3 && nDstPixelStride == 4)
-                {
-                    ASSIGN_LOOP(3, 4)
-                }
-                else if (nSrcPixelStride == 4 && nDstPixelStride == 3)
-                {
-                    ASSIGN_LOOP(4, 3)
-                }
-            }
-
-            for( i = nWordCount; i != 0; i-- )
-            {
-                *pabyDst = *pabySrc;
-                pabyDst += nDstPixelStride;
-                pabySrc += nSrcPixelStride;
-            }
-        }
-        else if (nWordSize == 2)
-        {
-            for( i = nWordCount; i != 0; i-- )
-            {
-                *(short*)pabyDst = *(short*)pabySrc;
-                pabyDst += nDstPixelStride;
-                pabySrc += nSrcPixelStride;
-            }
-        }
-        else if (nWordSize == 4)
-        {
-            for( i = nWordCount; i != 0; i-- )
-            {
-                *(int*)pabyDst = *(int*)pabySrc;
-                pabyDst += nDstPixelStride;
-                pabySrc += nSrcPixelStride;
-            }
-        }
-        else if (nWordSize == 8)
-        {
-            for( i = nWordCount; i != 0; i-- )
-            {
-                ((int*)pabyDst)[0] = ((int*)pabySrc)[0];
-                ((int*)pabyDst)[1] = ((int*)pabySrc)[1];
-                pabyDst += nDstPixelStride;
-                pabySrc += nSrcPixelStride;
-            }
-        }
-        else if (nWordSize == 16)
-        {
-            for( i = nWordCount; i != 0; i-- )
-            {
-                ((int*)pabyDst)[0] = ((int*)pabySrc)[0];
-                ((int*)pabyDst)[1] = ((int*)pabySrc)[1];
-                ((int*)pabyDst)[2] = ((int*)pabySrc)[2];
-                ((int*)pabyDst)[3] = ((int*)pabySrc)[3];
-                pabyDst += nDstPixelStride;
-                pabySrc += nSrcPixelStride;
-            }
-        }
-        else
-        {
-            CPLAssert(FALSE);
-        }
-
-        return;
-    }
-    
-/* ==================================================================== */
-/*      General translation case                                        */
-/* ==================================================================== */
-    for( int iWord = 0; iWord < nWordCount; iWord++ )
-    {
-        void   *pSrcWord, *pDstWord;
-        double  dfPixelValue=0.0, dfPixelValueI=0.0;
-
-        pSrcWord = static_cast<GByte *>(pSrcData) + iWord * nSrcPixelStride;
-        pDstWord = static_cast<GByte *>(pDstData) + iWord * nDstPixelStride;
-
-/* -------------------------------------------------------------------- */
-/*      Fetch source value based on data type.                          */
-/* -------------------------------------------------------------------- */
-        switch( eSrcType )
-        {
-          case GDT_Byte:
-          {
-              GByte byVal = *static_cast<GByte *>(pSrcWord);
-              switch( eDstType )
-              {
-                case GDT_UInt16:
-                  *static_cast<GUInt16 *>(pDstWord) = byVal;
-                  continue;
-                case GDT_Int16:
-                  *static_cast<GInt16 *>(pDstWord) = byVal;
-                  continue;
-                case GDT_UInt32:
-                  *static_cast<GUInt32 *>(pDstWord) = byVal;
-                  continue;
-                case GDT_Int32:
-                  *static_cast<GInt32 *>(pDstWord) = byVal;
-                  continue;
-                case GDT_CInt16:
-                {
-                    GInt16 *panDstWord = static_cast<GInt16 *>(pDstWord);
-                    panDstWord[0] = byVal;
-                    panDstWord[1] = 0;
-                    continue;
-                }
-                case GDT_CInt32:
-                {
-                    GInt32 *panDstWord = static_cast<GInt32 *>(pDstWord);
-                    panDstWord[0] = byVal;
-                    panDstWord[1] = 0;
-                    continue;
-                }
-                default:
-                  break;
-              }
-              dfPixelValue = byVal;
-          }
-          break;
-
-          case GDT_UInt16:
-          {
-              GUInt16 nVal = *static_cast<GUInt16 *>(pSrcWord);
-              switch( eDstType )
-              {
-                case GDT_Byte:
-                {
-                    GByte byVal;
-                    if( nVal > 255 )
-                        byVal = 255;
-                    else
-                        byVal = static_cast<GByte>(nVal);
-                    *static_cast<GByte *>(pDstWord) = byVal;
-                    continue;
-                }
-                case GDT_Int16:
-                  if( nVal > 32767 )
-                      nVal = 32767;
-                  *static_cast<GInt16 *>(pDstWord) = nVal;
-                  continue;
-                case GDT_UInt32:
-                  *static_cast<GUInt32 *>(pDstWord) = nVal;
-                  continue;
-                case GDT_Int32:
-                  *static_cast<GInt32 *>(pDstWord) = nVal;
-                  continue;
-                case GDT_CInt16:
-                {
-                    GInt16 *panDstWord = static_cast<GInt16 *>(pDstWord);
-                    if( nVal > 32767 )
-                        nVal = 32767;
-                    panDstWord[0] = nVal;
-                    panDstWord[1] = 0;
-                    continue;
-                }
-                case GDT_CInt32:
-                {
-                    GInt32 *panDstWord = static_cast<GInt32 *>(pDstWord);
-                    panDstWord[0] = nVal;
-                    panDstWord[1] = 0;
-                    continue;
-                }
-                default:
-                  break;
-              }
-              dfPixelValue = nVal;
-          }
-          break;
-          
-          case GDT_Int16:
-          {
-              GInt16 nVal = *static_cast<GInt16 *>(pSrcWord);
-              switch( eDstType )
-              {
-                case GDT_Byte:
-                {
-                    GByte byVal;
-                    if( nVal > 255 )
-                        byVal = 255;
-                    else if (nVal < 0)
-                        byVal = 0;
-                    else
-                        byVal = static_cast<GByte>(nVal);
-                    *static_cast<GByte *>(pDstWord) = byVal;
-                    continue;
-                }
-                case GDT_UInt16:
-                  if( nVal < 0 )
-                      nVal = 0;
-                  *static_cast<GUInt16 *>(pDstWord) = nVal;
-                  continue;
-                case GDT_UInt32:
-                  if( nVal < 0 )
-                      nVal = 0;
-                  *static_cast<GUInt32 *>(pDstWord) = nVal;
-                  continue;
-                case GDT_Int32:
-                  *static_cast<GInt32 *>(pDstWord) = nVal;
-                  continue;
-                case GDT_CInt16:
-                {
-                    GInt16 *panDstWord = static_cast<GInt16 *>(pDstWord);
-                    panDstWord[0] = nVal;
-                    panDstWord[1] = 0;
-                    continue;
-                }
-                case GDT_CInt32:
-                {
-                    GInt32 *panDstWord = static_cast<GInt32 *>(pDstWord);
-                    panDstWord[0] = nVal;
-                    panDstWord[1] = 0;
-                    continue;
-                }
-                default:
-                  break;
-              }
-              dfPixelValue = nVal;
-          }
-          break;
-          
-          case GDT_Int32:
-          {
-              GInt32 nVal = *static_cast<GInt32 *>(pSrcWord);
-              switch( eDstType )
-              {
-                case GDT_Byte:
-                {
-                    GByte byVal;
-                    if( nVal > 255 )
-                        byVal = 255;
-                    else if (nVal < 0)
-                        byVal = 0;
-                    else
-                        byVal = nVal;
-                    *static_cast<GByte *>(pDstWord) = byVal;
-                    continue;
-                }
-                case GDT_UInt16:
-                  if( nVal > 65535 )
-                      nVal = 65535;
-                  else if( nVal < 0 )
-                      nVal = 0;
-                  *static_cast<GUInt16 *>(pDstWord) = nVal;
-                  continue;
-                case GDT_Int16:
-                  if( nVal > 32767 )
-                      nVal = 32767;
-                  else if( nVal < -32768)
-                      nVal = -32768;
-                  *static_cast<GInt16 *>(pDstWord) = nVal;
-                  continue;
-                case GDT_UInt32:
-                  if( nVal < 0 )
-                      nVal = 0;
-                  *static_cast<GUInt32 *>(pDstWord) = nVal;
-                  continue;
-                case GDT_CInt16:
-                {
-                    GInt16 *panDstWord = static_cast<GInt16 *>(pDstWord);
-                    if( nVal > 32767 )
-                        nVal = 32767;
-                    else if( nVal < -32768)
-                        nVal = -32768;
-                    panDstWord[0] = nVal;
-                    panDstWord[1] = 0;
-                    continue;
-                }
-                case GDT_CInt32:
-                {
-                    GInt32 *panDstWord = static_cast<GInt32 *>(pDstWord);
-                    panDstWord[0] = nVal;
-                    panDstWord[1] = 0;
-                    continue;
-                }
-                default:
-                  break;
-              }
-              dfPixelValue = nVal;
-          }
-          break;
-          
-          case GDT_UInt32:
-          {
-              GUInt32 nVal = *static_cast<GUInt32 *>(pSrcWord);
-              switch( eDstType )
-              {
-                case GDT_Byte:
-                {
-                    GByte byVal;
-                    if( nVal > 255 )
-                        byVal = 255;
-                    else
-                        byVal = nVal;
-                    *static_cast<GByte *>(pDstWord) = byVal;
-                    continue;
-                }
-                case GDT_UInt16:
-                  if( nVal > 65535 )
-                      nVal = 65535;
-                  *static_cast<GUInt16 *>(pDstWord) = nVal;
-                  continue;
-                case GDT_Int16:
-                  if( nVal > 32767 )
-                      nVal = 32767;
-                  *static_cast<GInt16 *>(pDstWord) = nVal;
-                  continue;
-                case GDT_Int32:
-                  if( nVal > 2147483647UL )
-                      nVal = 2147483647UL;
-                  *static_cast<GInt32 *>(pDstWord) = nVal;
-                  continue;
-                case GDT_CInt16:
-                {
-                    GInt16 *panDstWord = static_cast<GInt16 *>(pDstWord);
-                    if( nVal > 32767 )
-                        nVal = 32767;
-                    panDstWord[0] = nVal;
-                    panDstWord[1] = 0;
-                    continue;
-                }
-                case GDT_CInt32:
-                {
-                    GInt32 *panDstWord = static_cast<GInt32 *>(pDstWord);
-                    if( nVal > 2147483647UL )
-                        nVal = 2147483647UL;
-                    panDstWord[0] = nVal;
-                    panDstWord[1] = 0;
-                    continue;
-                }
-                default:
-                  break;
-              }
-              dfPixelValue = nVal;
-          }
-          break;
-          
-          case GDT_CInt16:
-          {
-              GInt16 *panSrcWord = static_cast<GInt16 *>(pSrcWord);
-              GInt16 nVal = panSrcWord[0];
-              switch( eDstType )
-              {
-                case GDT_Byte:
-                {
-                    GByte byVal;
-                    if( nVal > 255 )
-                        byVal = 255;
-                    else if (nVal < 0)
-                        byVal = 0;
-                    else
-                        byVal = static_cast<GByte>(nVal);
-                    *static_cast<GByte *>(pDstWord) = byVal;
-                    continue;
-                }
-                case GDT_Int16:
-                  *static_cast<GInt16 *>(pDstWord) = nVal;
-                  continue;
-                case GDT_UInt16:
-                  if( nVal < 0 )
-                      nVal = 0;
-                  *static_cast<GUInt16 *>(pDstWord) = nVal;
-                  continue;
-                case GDT_UInt32:
-                  if( nVal < 0 )
-                      nVal = 0;
-                  *static_cast<GUInt32 *>(pDstWord) = nVal;
-                  continue;
-                case GDT_Int32:
-                  *static_cast<GInt32 *>(pDstWord) = nVal;
-                  continue;
-                case GDT_CInt32:
-                {
-                    GInt32 *panDstWord = static_cast<GInt32 *>(pDstWord);
-                    panDstWord[0] = panSrcWord[0];
-                    panDstWord[1] = panSrcWord[1];
-                    continue;
-                }
-                default:
-                  break;
-              }
-              dfPixelValue = panSrcWord[0];
-              dfPixelValueI = panSrcWord[1];
-          }
-          break;
-          
-          case GDT_CInt32:
-          {
-              GInt32 *panSrcWord = static_cast<GInt32 *>(pSrcWord);
-              GInt32 nVal = panSrcWord[0];
-              switch( eDstType )
-              {
-                case GDT_Byte:
-                {
-                    GByte byVal;
-                    if( nVal > 255 )
-                        byVal = 255;
-                    else if (nVal < 0)
-                        byVal = 0;
-                    else
-                        byVal = nVal;
-                    *static_cast<GByte *>(pDstWord) = byVal;
-                    continue;
-                }
-                case GDT_Int16:
-                  if( nVal > 32767 )
-                      nVal = 32767;
-                  else if( nVal < -32768)
-                      nVal = -32768;
-                  *static_cast<GInt16 *>(pDstWord) = nVal;
-                  continue;
-                case GDT_UInt16:
-                  if( nVal > 65535 )
-                      nVal = 65535;
-                  else if( nVal < 0 )
-                      nVal = 0;
-                  *static_cast<GUInt16 *>(pDstWord) = nVal;
-                  continue;
-                case GDT_UInt32:
-                  if( nVal < 0 )
-                      nVal = 0;
-                  *static_cast<GUInt32 *>(pDstWord) = nVal;
-                  continue;
-                case GDT_Int32:
-                  *static_cast<GInt32 *>(pDstWord) = nVal;
-                  continue;
-                case GDT_CInt16:
-                {
-                    GInt16 *panDstWord = static_cast<GInt16 *>(pDstWord);
-                    if( nVal > 32767 )
-                        nVal = 32767;
-                    else if( nVal < -32768)
-                        nVal = -32768;
-                    panDstWord[0] = nVal;
-                    nVal = panSrcWord[1];
-                    if( nVal > 32767 )
-                        nVal = 32767;
-                    else if( nVal < -32768)
-                        nVal = -32768;
-                    panDstWord[1] = nVal;
-                    continue;
-                }
-                default:
-                  break;
-              }
-              dfPixelValue = panSrcWord[0];
-              dfPixelValueI = panSrcWord[1];
-          }
-          break;
-
-          case GDT_Float32:
-          {
-              float fVal = *static_cast<float *>(pSrcWord);
-              dfPixelValue = fVal;
-          }
-          break;
-          
-          case GDT_Float64:
-          {
-              dfPixelValue = *static_cast<double *>(pSrcWord);
-          }
-          break;
-
-          case GDT_CFloat32:
-          {
-              float *pafSrcWord = static_cast<float *>(pSrcWord);
-              dfPixelValue = pafSrcWord[0];
-              dfPixelValueI = pafSrcWord[1];
-          }
-          break;
-          
-          case GDT_CFloat64:
-          {
-              double *padfSrcWord = static_cast<double *>(pSrcWord);
-              dfPixelValue = padfSrcWord[0];
-              dfPixelValueI = padfSrcWord[1];
-          }
-          break;
-
-          default:
-            CPLAssert( FALSE );
-        }
-        
-/* -------------------------------------------------------------------- */
-/*      Set the destination pixel, doing range clipping as needed.      */
-/* -------------------------------------------------------------------- */
-        switch( eDstType )
-        {
-          case GDT_Byte:
-          {
-              GByte *pabyDstWord = static_cast<GByte *>(pDstWord);
-
-              dfPixelValue += (float) 0.5;
-
-              if( dfPixelValue < 0.0 )
-                  *pabyDstWord = 0;
-              else if( dfPixelValue > 255.0 )
-                  *pabyDstWord = 255;
-              else
-                  *pabyDstWord = (GByte) dfPixelValue;
-          }
-          break;
-
-          case GDT_UInt16:
-          {
-              GUInt16   nVal;
-              
-              dfPixelValue += 0.5;
-
-              if( dfPixelValue < 0.0 )
-                  nVal = 0;
-              else if( dfPixelValue > 65535.0 )
-                  nVal = 65535;
-              else
-                  nVal = (GUInt16) dfPixelValue;
-
-              *static_cast<GUInt16 *>(pDstWord) = nVal;
-          }
-          break;
-
-          case GDT_Int16:
-          {
-              GInt16    nVal;
-              
-              dfPixelValue += 0.5;
-
-              if( dfPixelValue < -32768 )
-                  nVal = -32768;
-              else if( dfPixelValue > 32767 )
-                  nVal = 32767;
-              else
-                  nVal = (GInt16) floor(dfPixelValue);
-
-              *static_cast<GInt16 *>(pDstWord) = nVal;
-          }
-          break;
-          
-          case GDT_UInt32:
-          {
-              GUInt32   nVal;
-              
-              dfPixelValue += 0.5;
-
-              if( dfPixelValue < 0 )
-                  nVal = 0;
-              else if( dfPixelValue > 4294967295U )
-                  nVal = 4294967295U;
-              else
-                  nVal = (GInt32) dfPixelValue;
-
-              *static_cast<GUInt32 *>(pDstWord) = nVal;
-          }
-          break;
-          
-          case GDT_Int32:
-          {
-              GInt32    nVal;
-              
-              dfPixelValue += 0.5;
-
-              if( dfPixelValue < -2147483648.0 )
-                  nVal = INT_MIN;
-              else if( dfPixelValue > 2147483647 )
-                  nVal = 2147483647;
-              else
-                  nVal = (GInt32) floor(dfPixelValue);
-
-              *static_cast<GInt32 *>(pDstWord) = nVal;
-          }
-          break;
-
-          case GDT_Float32:
-          {
-              *static_cast<float *>(pDstWord) = static_cast<float>(dfPixelValue);
-          }
-          break;
-
-          case GDT_Float64:
-            *static_cast<double *>(pDstWord) = dfPixelValue;
-            break;
-              
-          case GDT_CInt16:
-          {
-              GInt16    nVal;
-              GInt16 *panDstWord = static_cast<GInt16 *>(pDstWord);
-              
-              dfPixelValue += 0.5;
-              dfPixelValueI += 0.5;
-
-              if( dfPixelValue < -32768 )
-                  nVal = -32768;
-              else if( dfPixelValue > 32767 )
-                  nVal = 32767;
-              else
-                  nVal = (GInt16) floor(dfPixelValue);
-              panDstWord[0] = nVal;
-
-              if( dfPixelValueI < -32768 )
-                  nVal = -32768;
-              else if( dfPixelValueI > 32767 )
-                  nVal = 32767;
-              else
-                  nVal = (GInt16) floor(dfPixelValueI);
-              panDstWord[1] = nVal;
-          }
-          break;
-          
-          case GDT_CInt32:
-          {
-              GInt32    nVal;
-              GInt32 *panDstWord = static_cast<GInt32 *>(pDstWord);
-              
-              dfPixelValue += 0.5;
-              dfPixelValueI += 0.5;
-
-              if( dfPixelValue < -2147483648.0 )
-                  nVal = INT_MIN;
-              else if( dfPixelValue > 2147483647 )
-                  nVal = 2147483647;
-              else
-                  nVal = (GInt32) floor(dfPixelValue);
-
-              panDstWord[0] = nVal;
-
-              if( dfPixelValueI < -2147483648.0 )
-                  nVal = INT_MIN;
-              else if( dfPixelValueI > 2147483647 )
-                  nVal = 2147483647;
-              else
-                  nVal = (GInt32) floor(dfPixelValueI);
-
-              panDstWord[1] = nVal;
-          }
-          break;
-
-          case GDT_CFloat32:
-          {
-              float *pafDstWord = static_cast<float *>(pDstWord);
-              pafDstWord[0] = static_cast<float>(dfPixelValue);
-              pafDstWord[1] = static_cast<float>(dfPixelValueI);
-          }
-          break;
-
-          case GDT_CFloat64:
-          {
-              double *padfDstWord = static_cast<double *>(pDstWord);
-              padfDstWord[0] = dfPixelValue;
-              padfDstWord[1] = dfPixelValueI;
-          }
-          break;
-              
-          default:
-            CPLAssert( FALSE );
-        }
-    } /* next iWord */
-#endif // defined USE_NEW_COPYWORDS
 }
 
 /************************************************************************/
@@ -2623,34 +2409,34 @@ GDALCopyWords( void * pSrcData, GDALDataType eSrcType, int nSrcPixelStride,
  * Bitwise word copying.
  *
  * A function for moving sets of partial bytes around.  Loosely
- * speaking this is a bitswise analog to GDALCopyWords().
+ * speaking this is a bitwise analog to GDALCopyWords().
  *
- * It copies nStepCount "words" where each word is nBitCount bits long. 
+ * It copies nStepCount "words" where each word is nBitCount bits long.
  * The nSrcStep and nDstStep are the number of bits from the start of one
  * word to the next (same as nBitCount if they are packed).  The nSrcOffset
  * and nDstOffset are the offset into the source and destination buffers
- * to start at, also measured in bits. 
+ * to start at, also measured in bits.
  *
  * All bit offsets are assumed to start from the high order bit in a byte
- * (ie. most significant bit first).  Currently this function is not very
- * optimized, but it may be improved for some common cases in the future 
- * as needed. 
+ * (i.e. most significant bit first).  Currently this function is not very
+ * optimized, but it may be improved for some common cases in the future
+ * as needed.
  *
  * @param pabySrcData the source data buffer.
- * @param nSrcOffset the offset (in bits) in pabySrcData to the start of the 
+ * @param nSrcOffset the offset (in bits) in pabySrcData to the start of the
  * first word to copy.
- * @param nSrcStep the offset in bits from the start one source word to the 
- * start of the next. 
+ * @param nSrcStep the offset in bits from the start one source word to the
+ * start of the next.
  * @param pabyDstData the destination data buffer.
- * @param nDstOffset the offset (in bits) in pabyDstData to the start of the 
+ * @param nDstOffset the offset (in bits) in pabyDstData to the start of the
  * first word to copy over.
- * @param nDstStep the offset in bits from the start one word to the 
- * start of the next. 
+ * @param nDstStep the offset in bits from the start one word to the
+ * start of the next.
  * @param nBitCount the number of bits in a word to be copied.
  * @param nStepCount the number of words to copy.
  */
 
-void GDALCopyBits( const GByte *pabySrcData, int nSrcOffset, int nSrcStep, 
+void GDALCopyBits( const GByte *pabySrcData, int nSrcOffset, int nSrcStep,
                    GByte *pabyDstData, int nDstOffset, int nDstStep,
                    int nBitCount, int nStepCount )
 
@@ -2664,7 +2450,7 @@ void GDALCopyBits( const GByte *pabySrcData, int nSrcOffset, int nSrcStep,
     {
         for( iBit = 0; iBit < nBitCount; iBit++ )
         {
-            if( pabySrcData[nSrcOffset>>3] 
+            if( pabySrcData[nSrcOffset>>3]
                 & (0x80 >>(nSrcOffset & 7)) )
                 pabyDstData[nDstOffset>>3] |= (0x80 >> (nDstOffset & 7));
             else
@@ -2673,7 +2459,7 @@ void GDALCopyBits( const GByte *pabySrcData, int nSrcOffset, int nSrcStep,
 
             nSrcOffset++;
             nDstOffset++;
-        } 
+        }
 
         nSrcOffset += (nSrcStep - nBitCount);
         nDstOffset += (nDstStep - nBitCount);
@@ -2709,7 +2495,7 @@ int GDALBandGetBestOverviewLevel2(GDALRasterBand* poBand,
 /*      based on the least reduced axis, and represents the number      */
 /*      of source pixels to one destination pixel.                      */
 /* -------------------------------------------------------------------- */
-    if( (nXSize / (double) nBufXSize) < (nYSize / (double) nBufYSize ) 
+    if( (nXSize / (double) nBufXSize) < (nYSize / (double) nBufYSize )
         || nBufYSize == 1 )
         dfDesiredResolution = nXSize / (double) nBufXSize;
     else
@@ -2724,7 +2510,7 @@ int GDALBandGetBestOverviewLevel2(GDALRasterBand* poBand,
     GDALRasterBand* poBestOverview = NULL;
     double dfBestResolution = 0;
     int nBestOverviewLevel = -1;
-    
+
     for( int iOverview = 0; iOverview < nOverviewCount; iOverview++ )
     {
         GDALRasterBand  *poOverview = poBand->GetOverview( iOverview );
@@ -2736,23 +2522,23 @@ int GDALBandGetBestOverviewLevel2(GDALRasterBand* poBand,
         // What resolution is this?
         if( (poBand->GetXSize() / (double) poOverview->GetXSize())
             < (poBand->GetYSize() / (double) poOverview->GetYSize()) )
-            dfResolution = 
+            dfResolution =
                 poBand->GetXSize() / (double) poOverview->GetXSize();
         else
-            dfResolution = 
+            dfResolution =
                 poBand->GetYSize() / (double) poOverview->GetYSize();
 
         // Is it nearly the requested resolution and better (lower) than
         // the current best resolution?
-        if( dfResolution >= dfDesiredResolution * 1.2 
+        if( dfResolution >= dfDesiredResolution * 1.2
             || dfResolution <= dfBestResolution )
             continue;
 
         // Ignore AVERAGE_BIT2GRAYSCALE overviews for RasterIO purposes.
-        const char *pszResampling = 
+        const char *pszResampling =
             poOverview->GetMetadataItem( "RESAMPLING" );
 
-        if( pszResampling != NULL && EQUALN(pszResampling,"AVERAGE_BIT2",12))
+        if( pszResampling != NULL && STARTS_WITH_CI(pszResampling, "AVERAGE_BIT2"))
             continue;
 
         // OK, this is our new best overview.
@@ -2774,7 +2560,7 @@ int GDALBandGetBestOverviewLevel2(GDALRasterBand* poBand,
 /* -------------------------------------------------------------------- */
     int         nOXOff, nOYOff, nOXSize, nOYSize;
     double      dfXRes, dfYRes;
-    
+
     dfXRes = poBand->GetXSize() / (double) poBestOverview->GetXSize();
     dfYRes = poBand->GetYSize() / (double) poBestOverview->GetYSize();
 
@@ -2786,12 +2572,12 @@ int GDALBandGetBestOverviewLevel2(GDALRasterBand* poBand,
         nOXSize = poBestOverview->GetXSize() - nOXOff;
     if( nOYOff + nOYSize > poBestOverview->GetYSize() )
         nOYSize = poBestOverview->GetYSize() - nOYOff;
-        
+
     nXOff = nOXOff;
     nYOff = nOYOff;
     nXSize = nOXSize;
     nYSize = nOYSize;
-    
+
     if( psExtraArg && psExtraArg->bFloatingPointWindowValidity )
     {
         psExtraArg->dfXOff /= dfXRes;
@@ -2799,7 +2585,7 @@ int GDALBandGetBestOverviewLevel2(GDALRasterBand* poBand,
         psExtraArg->dfYOff /= dfYRes;
         psExtraArg->dfYSize /= dfYRes;
     }
-    
+
     return nBestOverviewLevel;
 }
 
@@ -2824,7 +2610,7 @@ CPLErr GDALRasterBand::OverviewRasterIO( GDALRWFlag eRWFlag,
 {
     int         nOverview;
     GDALRasterIOExtraArg sExtraArg;
-    
+
     GDALCopyRasterIOExtraArg(&sExtraArg, psExtraArg);
 
     nOverview =
@@ -2832,7 +2618,7 @@ CPLErr GDALRasterBand::OverviewRasterIO( GDALRWFlag eRWFlag,
                                       nBufXSize, nBufYSize, &sExtraArg);
     if (nOverview < 0)
         return CE_Failure;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Recast the call in terms of the new raster layer.               */
 /* -------------------------------------------------------------------- */
@@ -2846,6 +2632,87 @@ CPLErr GDALRasterBand::OverviewRasterIO( GDALRWFlag eRWFlag,
 }
 
 /************************************************************************/
+/*                      TryOverviewRasterIO()                           */
+/************************************************************************/
+
+CPLErr GDALRasterBand::TryOverviewRasterIO( GDALRWFlag eRWFlag,
+                                            int nXOff, int nYOff, int nXSize, int nYSize,
+                                            void * pData, int nBufXSize, int nBufYSize,
+                                            GDALDataType eBufType,
+                                            GSpacing nPixelSpace, GSpacing nLineSpace,
+                                            GDALRasterIOExtraArg* psExtraArg,
+                                            int* pbTried )
+{
+    int nXOffMod = nXOff, nYOffMod = nYOff, nXSizeMod = nXSize, nYSizeMod = nYSize;
+    GDALRasterIOExtraArg sExtraArg;
+
+    GDALCopyRasterIOExtraArg(&sExtraArg, psExtraArg);
+
+    int iOvrLevel = GDALBandGetBestOverviewLevel2(this,
+                                                    nXOffMod, nYOffMod,
+                                                    nXSizeMod, nYSizeMod,
+                                                    nBufXSize, nBufYSize,
+                                                    &sExtraArg);
+
+    if( iOvrLevel >= 0 )
+    {
+        GDALRasterBand* poOverviewBand = GetOverview(iOvrLevel);
+        if( poOverviewBand  )
+        {
+            *pbTried = TRUE;
+            return poOverviewBand->RasterIO(
+                eRWFlag, nXOffMod, nYOffMod, nXSizeMod, nYSizeMod,
+                pData, nBufXSize, nBufYSize, eBufType,
+                nPixelSpace, nLineSpace, &sExtraArg);
+        }
+    }
+
+    *pbTried = FALSE;
+    return CE_None;
+}
+
+/************************************************************************/
+/*                      TryOverviewRasterIO()                           */
+/************************************************************************/
+
+CPLErr GDALDataset::TryOverviewRasterIO( GDALRWFlag eRWFlag,
+                                         int nXOff, int nYOff, int nXSize, int nYSize,
+                                         void * pData, int nBufXSize, int nBufYSize,
+                                         GDALDataType eBufType,
+                                         int nBandCount, int *panBandMap,
+                                         GSpacing nPixelSpace, GSpacing nLineSpace,
+                                         GSpacing nBandSpace,
+                                         GDALRasterIOExtraArg* psExtraArg,
+                                         int* pbTried )
+{
+    int nXOffMod = nXOff, nYOffMod = nYOff, nXSizeMod = nXSize, nYSizeMod = nYSize;
+    GDALRasterIOExtraArg sExtraArg;
+
+    GDALCopyRasterIOExtraArg(&sExtraArg, psExtraArg);
+
+    int iOvrLevel = GDALBandGetBestOverviewLevel2(papoBands[0],
+                                                    nXOffMod, nYOffMod,
+                                                    nXSizeMod, nYSizeMod,
+                                                    nBufXSize, nBufYSize,
+                                                    &sExtraArg);
+
+    if( iOvrLevel >= 0 && papoBands[0]->GetOverview(iOvrLevel) != NULL &&
+        papoBands[0]->GetOverview(iOvrLevel)->GetDataset() != NULL )
+    {
+        *pbTried = TRUE;
+        return papoBands[0]->GetOverview(iOvrLevel)->GetDataset()->RasterIO(
+            eRWFlag, nXOffMod, nYOffMod, nXSizeMod, nYSizeMod,
+            pData, nBufXSize, nBufYSize, eBufType,
+            nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace, &sExtraArg);
+    }
+    else
+    {
+        *pbTried = FALSE;
+        return CE_None;
+    }
+}
+
+/************************************************************************/
 /*                        GetBestOverviewLevel()                        */
 /*                                                                      */
 /* Returns the best overview level to satisfy the query or -1 if none   */
@@ -2863,10 +2730,10 @@ int GDALDatasetGetBestOverviewLevel(GDALDataset* poDS,
     int iBand, iOverview;
     int nOverviewCount = 0;
     GDALRasterBand *poFirstBand = NULL;
-    
+
     if (nBandCount == 0)
         return -1;
-    
+
 /* -------------------------------------------------------------------- */
 /* Check that all bands have the same number of overviews and           */
 /* that they have all the same size and block dimensions                */
@@ -2881,7 +2748,7 @@ int GDALDatasetGetBestOverviewLevel(GDALDataset* poDS,
         }
         else if (nOverviewCount != poBand->GetOverviewCount())
         {
-            CPLDebug( "GDAL", 
+            CPLDebug( "GDAL",
                       "GDALDataset::GetBestOverviewLevel() ... "
                       "mismatched overview count, use std method." );
             return -1;
@@ -2900,7 +2767,7 @@ int GDALDatasetGetBestOverviewLevel(GDALDataset* poDS,
                 if ( poOvrFirstBand->GetXSize() != poOvrBand->GetXSize() ||
                      poOvrFirstBand->GetYSize() != poOvrBand->GetYSize() )
                 {
-                    CPLDebug( "GDAL", 
+                    CPLDebug( "GDAL",
                               "GDALDataset::GetBestOverviewLevel() ... "
                               "mismatched overview sizes, use std method." );
                     return -1;
@@ -2912,7 +2779,7 @@ int GDALDatasetGetBestOverviewLevel(GDALDataset* poDS,
                 if (nBlockXSizeFirst != nBlockXSizeCurrent ||
                     nBlockYSizeFirst != nBlockYSizeCurrent)
                 {
-                    CPLDebug( "GDAL", 
+                    CPLDebug( "GDAL",
                           "GDALDataset::GetBestOverviewLevel() ... "
                           "mismatched block sizes, use std method." );
                     return -1;
@@ -2920,7 +2787,7 @@ int GDALDatasetGetBestOverviewLevel(GDALDataset* poDS,
             }
         }
     }
- 
+
     return GDALBandGetBestOverviewLevel2(poFirstBand,
                                         nXOff, nYOff, nXSize, nYSize,
                                         nBufXSize, nBufYSize, NULL);
@@ -2934,7 +2801,7 @@ int GDALDatasetGetBestOverviewLevel(GDALDataset* poDS,
 /*      much like the GDALRasterBand::IRasterIO(), but it handles       */
 /*      all bands at once, so that a format driver that handles a       */
 /*      request for different bands of the same block efficiently       */
-/*      (ie. without re-reading interleaved data) will efficiently.     */
+/*      (i.e. without re-reading interleaved data) will efficiently.    */
 /*                                                                      */
 /*      This method is intended to be called by an overridden           */
 /*      IRasterIO() method in the driver specific GDALDataset           */
@@ -2953,7 +2820,7 @@ int GDALDatasetGetBestOverviewLevel(GDALDataset* poDS,
 /*      basis. Overviews will be used when possible.                    */
 /************************************************************************/
 
-CPLErr 
+CPLErr
 GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
                                  int nXOff, int nYOff, int nXSize, int nYSize,
                                  void * pData, int nBufXSize, int nBufYSize,
@@ -2962,7 +2829,7 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
                                  GSpacing nPixelSpace, GSpacing nLineSpace,
                                  GSpacing nBandSpace,
                                  GDALRasterIOExtraArg* psExtraArg )
-    
+
 {
     GByte      **papabySrcBlock = NULL;
     GDALRasterBlock *poBlock = NULL;
@@ -2991,33 +2858,33 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
         else
         {
             poBand->GetBlockSize( &nThisBlockXSize, &nThisBlockYSize );
-            if( nThisBlockXSize != nBlockXSize 
+            if( nThisBlockXSize != nBlockXSize
                 || nThisBlockYSize != nBlockYSize )
             {
-                CPLDebug( "GDAL", 
+                CPLDebug( "GDAL",
                           "GDALDataset::BlockBasedRasterIO() ... "
                           "mismatched block sizes, use std method." );
-                return GDALDataset::IRasterIO( eRWFlag, 
-                                               nXOff, nYOff, nXSize, nYSize, 
-                                               pData, nBufXSize, nBufYSize, 
-                                               eBufType, 
+                return BandBasedRasterIO( eRWFlag,
+                                               nXOff, nYOff, nXSize, nYSize,
+                                               pData, nBufXSize, nBufYSize,
+                                               eBufType,
                                                nBandCount, panBandMap,
-                                               nPixelSpace, nLineSpace, 
+                                               nPixelSpace, nLineSpace,
                                                nBandSpace, psExtraArg );
             }
 
-            if( eDataType != poBand->GetRasterDataType() 
+            if( eDataType != poBand->GetRasterDataType()
                 && (nXSize != nBufXSize || nYSize != nBufYSize) )
             {
-                CPLDebug( "GDAL", 
+                CPLDebug( "GDAL",
                           "GDALDataset::BlockBasedRasterIO() ... "
                           "mismatched band data types, use std method." );
-                return GDALDataset::IRasterIO( eRWFlag, 
-                                               nXOff, nYOff, nXSize, nYSize, 
-                                               pData, nBufXSize, nBufYSize, 
-                                               eBufType, 
+                return BandBasedRasterIO( eRWFlag,
+                                               nXOff, nYOff, nXSize, nYSize,
+                                               pData, nBufXSize, nBufYSize,
+                                               eBufType,
                                                nBandCount, panBandMap,
-                                               nPixelSpace, nLineSpace, 
+                                               nPixelSpace, nLineSpace,
                                                nBandSpace, psExtraArg );
             }
         }
@@ -3030,7 +2897,7 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
 /*      called before proceeding to the next.                           */
 /* ==================================================================== */
 
-    if( nXSize == nBufXSize && nYSize == nBufYSize )    
+    if( nXSize == nBufXSize && nYSize == nBufYSize )
     {
         GDALRasterIOExtraArg sDummyExtraArg;
         INIT_RASTERIO_EXTRA_ARG(sDummyExtraArg);
@@ -3039,7 +2906,6 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
 
         for( iBufYOff = 0; iBufYOff < nBufYSize; iBufYOff += nChunkYSize )
         {
-            nChunkYSize = nBlockYSize;
             nChunkYOff = iBufYOff + nYOff;
             nChunkYSize = nBlockYSize - (nChunkYOff % nBlockYSize);
             if( nChunkYSize == 0 )
@@ -3049,7 +2915,6 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
 
             for( iBufXOff = 0; iBufXOff < nBufXSize; iBufXOff += nChunkXSize )
             {
-                nChunkXSize = nBlockXSize;
                 nChunkXOff = iBufXOff + nXOff;
                 nChunkXSize = nBlockXSize - (nChunkXOff % nBlockXSize);
                 if( nChunkXSize == 0 )
@@ -3059,20 +2924,20 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
 
                 GByte *pabyChunkData;
 
-                pabyChunkData = ((GByte *) pData) 
-                    + iBufXOff * nPixelSpace 
+                pabyChunkData = ((GByte *) pData)
+                    + iBufXOff * nPixelSpace
                     + (GPtrDiff_t)iBufYOff * nLineSpace;
 
                 for( iBand = 0; iBand < nBandCount; iBand++ )
                 {
                     GDALRasterBand *poBand = GetRasterBand(panBandMap[iBand]);
-                    
-                    eErr = 
-                        poBand->GDALRasterBand::IRasterIO( 
-                            eRWFlag, nChunkXOff, nChunkYOff, 
-                            nChunkXSize, nChunkYSize, 
-                            pabyChunkData + (GPtrDiff_t)iBand * nBandSpace, 
-                            nChunkXSize, nChunkYSize, eBufType, 
+
+                    eErr =
+                        poBand->GDALRasterBand::IRasterIO(
+                            eRWFlag, nChunkXOff, nChunkYOff,
+                            nChunkXSize, nChunkYSize,
+                            pabyChunkData + (GPtrDiff_t)iBand * nBandSpace,
+                            nChunkXSize, nChunkYSize, eBufType,
                             nPixelSpace, nLineSpace, &sDummyExtraArg );
                     if( eErr != CE_None )
                         return eErr;
@@ -3088,17 +2953,17 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
 
         return CE_None;
     }
-    
+
     /* Below code is not compatible with that case. It would need a complete */
     /* separate code like done in GDALRasterBand::IRasterIO. */
     if (eRWFlag == GF_Write && (nBufXSize < nXSize || nBufYSize < nYSize))
     {
-        return GDALDataset::IRasterIO( eRWFlag, 
-                                       nXOff, nYOff, nXSize, nYSize, 
-                                       pData, nBufXSize, nBufYSize, 
-                                       eBufType, 
+        return BandBasedRasterIO( eRWFlag,
+                                       nXOff, nYOff, nXSize, nYSize,
+                                       pData, nBufXSize, nBufYSize,
+                                       eBufType,
                                        nBandCount, panBandMap,
-                                       nPixelSpace, nLineSpace, 
+                                       nPixelSpace, nLineSpace,
                                        nBandSpace, psExtraArg );
     }
 
@@ -3106,12 +2971,12 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
     if( psExtraArg->eResampleAlg != GRIORA_NearestNeighbour &&
         (nBufXSize != nXSize || nBufYSize != nYSize) )
     {
-        return GDALDataset::IRasterIO( eRWFlag, 
-                                       nXOff, nYOff, nXSize, nYSize, 
-                                       pData, nBufXSize, nBufYSize, 
-                                       eBufType, 
+        return BandBasedRasterIO( eRWFlag,
+                                       nXOff, nYOff, nXSize, nYSize,
+                                       pData, nBufXSize, nBufYSize,
+                                       eBufType,
                                        nBandCount, panBandMap,
-                                       nPixelSpace, nLineSpace, 
+                                       nPixelSpace, nLineSpace,
                                        nBandSpace, psExtraArg );
     }
 
@@ -3120,11 +2985,11 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
 /*      request.  This is the most general implementation.              */
 /* ==================================================================== */
 
-    int         nBandDataSize = GDALGetDataTypeSize( eDataType ) / 8;
+    const int nBandDataSize = GDALGetDataTypeSizeBytes( eDataType );
 
     papabySrcBlock = (GByte **) CPLCalloc(sizeof(GByte*),nBandCount);
     papoBlocks = (GDALRasterBlock **) CPLCalloc(sizeof(void*),nBandCount);
-    
+
 /* -------------------------------------------------------------------- */
 /*      Select an overview level if appropriate.                        */
 /* -------------------------------------------------------------------- */
@@ -3142,7 +3007,7 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
 /*      Compute stepping increment.                                     */
 /* -------------------------------------------------------------------- */
     double      dfSrcX, dfSrcY, dfSrcXInc, dfSrcYInc;
-    
+
     dfSrcXInc = nXSize / (double) nBufXSize;
     dfSrcYInc = nYSize / (double) nBufYSize;
 
@@ -3152,19 +3017,19 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
     for( iBufYOff = 0; iBufYOff < nBufYSize; iBufYOff++ )
     {
         GPtrDiff_t  iBufOffset;
-        int         iSrcOffset;
-        
+        GPtrDiff_t  iSrcOffset;
+
         dfSrcY = (iBufYOff+0.5) * dfSrcYInc + nYOff;
         iSrcY = (int) dfSrcY;
 
         iBufOffset = (GPtrDiff_t)iBufYOff * (GPtrDiff_t)nLineSpace;
-        
+
         for( iBufXOff = 0; iBufXOff < nBufXSize; iBufXOff++ )
         {
             int iSrcX;
 
             dfSrcX = (iBufXOff+0.5) * dfSrcXInc + nXOff;
-            
+
             iSrcX = (int) dfSrcX;
 
             // FIXME: this code likely doesn't work if the dirty block gets flushed
@@ -3183,13 +3048,13 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
                 nLBlockX = iSrcX / nBlockXSize;
                 nLBlockY = iSrcY / nBlockYSize;
 
-                int bJustInitialize = 
+                int bJustInitialize =
                     eRWFlag == GF_Write
                     && nYOff <= nLBlockY * nBlockYSize
                     && nYOff + nYSize >= (nLBlockY+1) * nBlockYSize
                     && nXOff <= nLBlockX * nBlockXSize
                     && nXOff + nXSize >= (nLBlockX+1) * nBlockXSize;
-                /*int bMemZeroBuffer = FALSE;
+                /*bool bMemZeroBuffer = FALSE;
                 if( eRWFlag == GF_Write && !bJustInitialize &&
                     nXOff <= nLBlockX * nBlockXSize &&
                     nYOff <= nLBlockY * nBlockYSize &&
@@ -3206,7 +3071,7 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
                     GDALRasterBand *poBand = GetRasterBand( panBandMap[iBand]);
                     if (nOverviewLevel >= 0)
                         poBand = poBand->GetOverview(nOverviewLevel);
-                    poBlock = poBand->GetLockedBlockRef( nLBlockX, nLBlockY, 
+                    poBlock = poBand->GetLockedBlockRef( nLBlockX, nLBlockY,
                                                          bJustInitialize );
                     if( poBlock == NULL )
                     {
@@ -3219,15 +3084,10 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
 
                     if( papoBlocks[iBand] != NULL )
                         papoBlocks[iBand]->DropLock();
-                
+
                     papoBlocks[iBand] = poBlock;
 
                     papabySrcBlock[iBand] = (GByte *) poBlock->GetDataRef();
-                    if( papabySrcBlock[iBand] == NULL )
-                    {
-                        eErr = CE_Failure; 
-                        goto CleanupAndReturn;
-                    }
                     /*if( bMemZeroBuffer )
                     {
                         memset(papabySrcBlock[iBand], 0,
@@ -3246,27 +3106,27 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
             {
                 GByte *pabySrcBlock = papabySrcBlock[iBand];
                 GPtrDiff_t iBandBufOffset = iBufOffset + (GPtrDiff_t)iBand * (GPtrDiff_t)nBandSpace;
-                
+
                 if( eDataType == eBufType )
                 {
                     if( eRWFlag == GF_Read )
                         memcpy( ((GByte *) pData) + iBandBufOffset,
                                 pabySrcBlock + iSrcOffset, nBandDataSize );
                 else
-                    memcpy( pabySrcBlock + iSrcOffset, 
+                    memcpy( pabySrcBlock + iSrcOffset,
                             ((GByte *)pData) + iBandBufOffset, nBandDataSize );
                 }
                 else
                 {
                     /* type to type conversion ... ouch, this is expensive way
                        of handling single words */
-                    
+
                     if( eRWFlag == GF_Read )
                         GDALCopyWords( pabySrcBlock + iSrcOffset, eDataType, 0,
-                                       ((GByte *) pData) + iBandBufOffset, 
+                                       ((GByte *) pData) + iBandBufOffset,
                                        eBufType, 0, 1 );
                     else
-                        GDALCopyWords( ((GByte *) pData) + iBandBufOffset, 
+                        GDALCopyWords( ((GByte *) pData) + iBandBufOffset,
                                        eBufType, 0,
                                        pabySrcBlock + iSrcOffset, eDataType, 0,
                                        1 );
@@ -3292,7 +3152,7 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
         CPLFree( papoBlocks );
     }
 
-    return( CE_None );
+    return( eErr );
 }
 
 /************************************************************************/
@@ -3318,7 +3178,7 @@ static void GDALCopyWholeRasterGetSwathSize(GDALRasterBand *poSrcPrototypeBand,
     int nMaxBlockXSize = MAX(nBlockXSize, nSrcBlockXSize);
     int nMaxBlockYSize = MAX(nBlockYSize, nSrcBlockYSize);
 
-    int nPixelSize = (GDALGetDataTypeSize(eDT) / 8);
+    int nPixelSize = GDALGetDataTypeSizeBytes(eDT);
     if( bInterleave)
         nPixelSize *= nBandCount;
 
@@ -3501,12 +3361,12 @@ static void GDALCopyWholeRasterGetSwathSize(GDALRasterBand *poSrcPrototypeBand,
 /**
  * \brief Copy all dataset raster data.
  *
- * This function copies the complete raster contents of one dataset to 
- * another similarly configured dataset.  The source and destination 
+ * This function copies the complete raster contents of one dataset to
+ * another similarly configured dataset.  The source and destination
  * dataset must have the same number of bands, and the same width
- * and height.  The bands do not have to have the same data type. 
+ * and height.  The bands do not have to have the same data type.
  *
- * This function is primarily intended to support implementation of 
+ * This function is primarily intended to support implementation of
  * driver specific CreateCopy() functions.  It implements efficient copying,
  * in particular "chunking" the copy in substantial blocks and, if appropriate,
  * performing the transfer in a pixel interleaved fashion.
@@ -3514,7 +3374,7 @@ static void GDALCopyWholeRasterGetSwathSize(GDALRasterBand *poSrcPrototypeBand,
  * Currently the only papszOptions value supported are : "INTERLEAVE=PIXEL"
  * to force pixel interleaved operation and "COMPRESSED=YES" to force alignment
  * on target dataset block sizes to achieve best compression.  More options may be supported in
- * the future.  
+ * the future.
  *
  * @param hSrcDS the source dataset
  * @param hDstDS the destination dataset
@@ -3522,11 +3382,11 @@ static void GDALCopyWholeRasterGetSwathSize(GDALRasterBand *poSrcPrototypeBand,
  * @param pfnProgress progress reporting function.
  * @param pProgressData callback data for progress function.
  *
- * @return CE_None on success, or CE_Failure on failure. 
+ * @return CE_None on success, or CE_Failure on failure.
  */
 
 CPLErr CPL_STDCALL GDALDatasetCopyWholeRaster(
-    GDALDatasetH hSrcDS, GDALDatasetH hDstDS, char **papszOptions, 
+    GDALDatasetH hSrcDS, GDALDatasetH hDstDS, char **papszOptions,
     GDALProgressFunc pfnProgress, void *pProgressData )
 
 {
@@ -3543,11 +3403,11 @@ CPLErr CPL_STDCALL GDALDatasetCopyWholeRaster(
 /* -------------------------------------------------------------------- */
 /*      Confirm the datasets match in size and band counts.             */
 /* -------------------------------------------------------------------- */
-    int nXSize = poDstDS->GetRasterXSize(), 
+    int nXSize = poDstDS->GetRasterXSize(),
         nYSize = poDstDS->GetRasterYSize(),
         nBandCount = poDstDS->GetRasterCount();
 
-    if( poSrcDS->GetRasterXSize() != nXSize 
+    if( poSrcDS->GetRasterXSize() != nXSize
         || poSrcDS->GetRasterYSize() != nYSize
         || poSrcDS->GetRasterCount() != nBandCount )
     {
@@ -3562,7 +3422,7 @@ CPLErr CPL_STDCALL GDALDatasetCopyWholeRaster(
 /* -------------------------------------------------------------------- */
     if( !pfnProgress( 0.0, NULL, pProgressData ) )
     {
-        CPLError( CE_Failure, CPLE_UserInterrupt, 
+        CPLError( CE_Failure, CPLE_UserInterrupt,
                   "User terminated CreateCopy()" );
         return CE_Failure;
     }
@@ -3584,19 +3444,19 @@ CPLErr CPL_STDCALL GDALDatasetCopyWholeRaster(
 /* -------------------------------------------------------------------- */
     int bInterleave = FALSE;
     const char *pszInterleave = NULL;
-    
+
     pszInterleave = poSrcDS->GetMetadataItem( "INTERLEAVE", "IMAGE_STRUCTURE");
-    if( pszInterleave != NULL 
+    if( pszInterleave != NULL
         && (EQUAL(pszInterleave,"PIXEL") || EQUAL(pszInterleave,"LINE")) )
         bInterleave = TRUE;
 
     pszInterleave = poDstDS->GetMetadataItem( "INTERLEAVE", "IMAGE_STRUCTURE");
-    if( pszInterleave != NULL 
+    if( pszInterleave != NULL
         && (EQUAL(pszInterleave,"PIXEL") || EQUAL(pszInterleave,"LINE")) )
         bInterleave = TRUE;
 
     pszInterleave = CSLFetchNameValue( papszOptions, "INTERLEAVE" );
-    if( pszInterleave != NULL 
+    if( pszInterleave != NULL
         && (EQUAL(pszInterleave,"PIXEL") || EQUAL(pszInterleave,"LINE")) )
         bInterleave = TRUE;
     else if( pszInterleave != NULL && EQUAL(pszInterleave,"BAND") )
@@ -3606,7 +3466,7 @@ CPLErr CPL_STDCALL GDALDatasetCopyWholeRaster(
     /* disk space (GTiff case for example), and to avoid data loss (JPEG compression for example) */
     int bDstIsCompressed = FALSE;
     const char* pszDstCompressed= CSLFetchNameValue( papszOptions, "COMPRESSED" );
-    if (pszDstCompressed != NULL && CSLTestBoolean(pszDstCompressed))
+    if (pszDstCompressed != NULL && CPLTestBool(pszDstCompressed))
         bDstIsCompressed = TRUE;
 
 /* -------------------------------------------------------------------- */
@@ -3620,22 +3480,18 @@ CPLErr CPL_STDCALL GDALDatasetCopyWholeRaster(
                                     bDstIsCompressed, bInterleave,
                                     &nSwathCols, &nSwathLines);
 
-    int nPixelSize = (GDALGetDataTypeSize(eDT) / 8);
+    int nPixelSize = GDALGetDataTypeSizeBytes(eDT);
     if( bInterleave)
         nPixelSize *= nBandCount;
 
-    void *pSwathBuf = VSIMalloc3(nSwathCols, nSwathLines, nPixelSize );
+    void *pSwathBuf = VSI_MALLOC3_VERBOSE(nSwathCols, nSwathLines, nPixelSize );
     if( pSwathBuf == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory,
-                "Failed to allocate %d*%d*%d byte swath buffer in\n"
-                "GDALDatasetCopyWholeRaster()",
-                nSwathCols, nSwathLines, nPixelSize );
         return CE_Failure;
     }
 
-    CPLDebug( "GDAL", 
-            "GDALDatasetCopyWholeRaster(): %d*%d swaths, bInterleave=%d", 
+    CPLDebug( "GDAL",
+            "GDALDatasetCopyWholeRaster(): %d*%d swaths, bInterleave=%d",
             nSwathCols, nSwathLines, bInterleave );
 
     if( nSwathCols == nXSize && poSrcDS->GetDriver() != NULL &&
@@ -3678,7 +3534,7 @@ CPLErr CPL_STDCALL GDALDatasetCopyWholeRaster(
                         nThisCols = nXSize - iX;
 
                     sExtraArg.pfnProgress = GDALScaledProgress;
-                    sExtraArg.pProgressData = 
+                    sExtraArg.pProgressData =
                         GDALCreateScaledProgress( nBlocksDone / (double)nTotalBlocks,
                                                 (nBlocksDone + 0.5) / (double)nTotalBlocks,
                                                 pfnProgress,
@@ -3686,27 +3542,27 @@ CPLErr CPL_STDCALL GDALDatasetCopyWholeRaster(
                     if( sExtraArg.pProgressData == NULL )
                         sExtraArg.pfnProgress = NULL;
 
-                    eErr = poSrcDS->RasterIO( GF_Read, 
+                    eErr = poSrcDS->RasterIO( GF_Read,
                                             iX, iY, nThisCols, nThisLines,
-                                            pSwathBuf, nThisCols, nThisLines, 
-                                            eDT, 1, &nBand, 
+                                            pSwathBuf, nThisCols, nThisLines,
+                                            eDT, 1, &nBand,
                                             0, 0, 0, &sExtraArg );
 
                     GDALDestroyScaledProgress( sExtraArg.pProgressData );
 
                     if( eErr == CE_None )
-                        eErr = poDstDS->RasterIO( GF_Write, 
+                        eErr = poDstDS->RasterIO( GF_Write,
                                                 iX, iY, nThisCols, nThisLines,
-                                                pSwathBuf, nThisCols, nThisLines, 
+                                                pSwathBuf, nThisCols, nThisLines,
                                                 eDT, 1, &nBand,
                                                 0, 0, 0, NULL );
                     nBlocksDone ++;
-                    if( eErr == CE_None 
+                    if( eErr == CE_None
                         && !pfnProgress( nBlocksDone / (double)nTotalBlocks,
                                         NULL, pProgressData ) )
                     {
                         eErr = CE_Failure;
-                        CPLError( CE_Failure, CPLE_UserInterrupt, 
+                        CPLError( CE_Failure, CPLE_UserInterrupt,
                                 "User terminated CreateCopy()" );
                     }
                 }
@@ -3743,7 +3599,7 @@ CPLErr CPL_STDCALL GDALDatasetCopyWholeRaster(
                     nThisCols = nXSize - iX;
 
                 sExtraArg.pfnProgress = GDALScaledProgress;
-                sExtraArg.pProgressData = 
+                sExtraArg.pProgressData =
                     GDALCreateScaledProgress( nBlocksDone / (double)nTotalBlocks,
                                             (nBlocksDone + 0.5) / (double)nTotalBlocks,
                                             pfnProgress,
@@ -3751,28 +3607,28 @@ CPLErr CPL_STDCALL GDALDatasetCopyWholeRaster(
                 if( sExtraArg.pProgressData == NULL )
                     sExtraArg.pfnProgress = NULL;
 
-                eErr = poSrcDS->RasterIO( GF_Read, 
+                eErr = poSrcDS->RasterIO( GF_Read,
                                         iX, iY, nThisCols, nThisLines,
-                                        pSwathBuf, nThisCols, nThisLines, 
-                                        eDT, nBandCount, NULL, 
+                                        pSwathBuf, nThisCols, nThisLines,
+                                        eDT, nBandCount, NULL,
                                         0, 0, 0, &sExtraArg );
 
                 GDALDestroyScaledProgress( sExtraArg.pProgressData );
 
                 if( eErr == CE_None )
-                    eErr = poDstDS->RasterIO( GF_Write, 
+                    eErr = poDstDS->RasterIO( GF_Write,
                                             iX, iY, nThisCols, nThisLines,
-                                            pSwathBuf, nThisCols, nThisLines, 
-                                            eDT, nBandCount, NULL, 
+                                            pSwathBuf, nThisCols, nThisLines,
+                                            eDT, nBandCount, NULL,
                                             0, 0, 0, NULL );
 
                 nBlocksDone ++;
-                if( eErr == CE_None 
+                if( eErr == CE_None
                     && !pfnProgress( nBlocksDone / (double)nTotalBlocks,
                                     NULL, pProgressData ) )
                 {
                     eErr = CE_Failure;
-                    CPLError( CE_Failure, CPLE_UserInterrupt, 
+                    CPLError( CE_Failure, CPLE_UserInterrupt,
                             "User terminated CreateCopy()" );
                 }
             }
@@ -3862,7 +3718,7 @@ CPLErr CPL_STDCALL GDALRasterBandCopyWholeRaster(
     /* disk space (GTiff case for example), and to avoid data loss (JPEG compression for example) */
     int bDstIsCompressed = FALSE;
     const char* pszDstCompressed= CSLFetchNameValue( papszOptions, "COMPRESSED" );
-    if (pszDstCompressed != NULL && CSLTestBoolean(pszDstCompressed))
+    if (pszDstCompressed != NULL && CPLTestBool(pszDstCompressed))
         bDstIsCompressed = TRUE;
 
 /* -------------------------------------------------------------------- */
@@ -3876,15 +3732,11 @@ CPLErr CPL_STDCALL GDALRasterBandCopyWholeRaster(
                                     bDstIsCompressed, FALSE,
                                     &nSwathCols, &nSwathLines);
 
-    int nPixelSize = (GDALGetDataTypeSize(eDT) / 8);
+    const int nPixelSize = GDALGetDataTypeSizeBytes(eDT);
 
-    void *pSwathBuf = VSIMalloc3(nSwathCols, nSwathLines, nPixelSize );
+    void *pSwathBuf = VSI_MALLOC3_VERBOSE(nSwathCols, nSwathLines, nPixelSize );
     if( pSwathBuf == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory,
-                "Failed to allocate %d*%d*%d byte swath buffer in\n"
-                "GDALRasterBandCopyWholeRaster()",
-                nSwathCols, nSwathLines, nPixelSize );
         return CE_Failure;
     }
 
diff --git a/gdal.pc.in b/gdal.pc.in
index 7f61932..a1aef6e 100644
--- a/gdal.pc.in
+++ b/gdal.pc.in
@@ -3,7 +3,7 @@ exec_prefix=${prefix}
 libdir=${exec_prefix}/lib
 includedir=${exec_prefix}/include
 datadir=${CONFIG_INST_DATA}
- 
+
 Name: libgdal
 Description: Geospatial Data Abstraction Library
 Version: ${CONFIG_VERSION}
diff --git a/gdalnightlysvn.sh b/gdalnightlysvn.sh
index 991bee7..6d0fa72 100644
--- a/gdalnightlysvn.sh
+++ b/gdalnightlysvn.sh
@@ -37,17 +37,17 @@ if test "${BRANCH}" = "stable"; then
   SVNBRANCH="branches/${VERSION_STABLE}"
 fi
 
-CWD=/osgeo/gdal
+CWD=/var/www/gdal
 DATE=`date +%Y%m%d`
 DATEVER=`date +%Y.%m.%d`
 NIGHTLYVER="svn-${BRANCH}-${DATEVER}"
-BUILDER="/osgeo/gdal/mkgdaldist.sh"
+BUILDER="/var/www/gdal/mkgdaldist.sh"
 GDALDIR="${CWD}/${GDAL}"
-DAILYDIR="/osgeo/gdal/gdal-web/daily"
+DAILYDIR="/var/www/gdal/gdal-web/daily"
 LOG="/dev/null"
 
 if test ${VERBOSE} = 1; then
-	LOG=/osgeo/gdal/nightly.log
+	LOG=/var/www/gdal/nightly.log
 	echo -n "Building GDAL Nightly: ${NIGHTLYVER}..."
 fi
 
diff --git a/gnm/GNUmakefile b/gnm/GNUmakefile
new file mode 100644
index 0000000..7da2400
--- /dev/null
+++ b/gnm/GNUmakefile
@@ -0,0 +1,31 @@
+
+include ../GDALmake.opt
+
+OBJ	=	gnmnetwork.o gnmgenericnetwork.o gnmlayer.o gnmrule.o gnmresultlayer.o \
+        gnmgraph.o
+
+default:	lib
+
+all:	lib
+
+clean:
+	rm -f html/*
+	(cd gnm_frmts; $(MAKE) clean)
+	$(RM) *.o
+
+very-clean: clean
+	rm -rf html rtf
+
+lib:	sublibs $(OBJ:.o=.$(OBJ_EXT))
+
+$(OBJ): gnm.h gnm_priv.h 
+
+obj:	$(OBJ)
+
+sublibs:
+	(cd gnm_frmts; $(MAKE))
+	
+install:	;
+
+install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
+	
diff --git a/gnm/gnm.h b/gnm/gnm.h
new file mode 100644
index 0000000..97c5032
--- /dev/null
+++ b/gnm/gnm.h
@@ -0,0 +1,699 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
+ * Purpose:  GNM general public declarations.
+ * Authors:  Mikhail Gusev (gusevmihs at gmail dot com)
+ *           Dmitry Baryshnikov, polimax at mail.ru
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Mikhail Gusev
+ * Copyright (c) 2014-2015, NextGIS <info at nextgis.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef GNM
+#define GNM
+
+#include "ogrsf_frmts.h"
+#include "gnmgraph.h"
+
+// Direction of an edge.
+typedef int GNMDirection; // We use int values in order to save them to the
+                          // network data.
+
+// Network's metadata parameters names.
+#define GNM_MD_NAME     "net_name"
+#define GNM_MD_DESCR    "net_description"
+#define GNM_MD_SRS      "net_srs"
+#define GNM_MD_VERSION  "net_version"
+#define GNM_MD_RULE     "net_rule"
+#define GNM_MD_FORMAT   "FORMAT"
+#define GNM_MD_FETCHEDGES   "fetch_edge"
+#define GNM_MD_FETCHVERTEX  "fetch_vertex"
+#define GNM_MD_NUM_PATHS    "num_paths"
+#define GNM_MD_EMITTER   "emitter"
+
+// TODO: Constants for capabilities.
+//#define GNMCanChangeConnections "CanChangeConnections"
+
+typedef enum
+{
+    /** Dijkstra shortest path */           GATDijkstraShortestPath = 1,
+    /** KShortest Paths        */           GATKShortestPath,
+    /** Recursive Breadth-first search */   GATConnectedComponents
+} GNMGraphAlgorithmType;
+
+/**
+ * General GNM class which represents a geography network of common format.
+ *
+ * @since GDAL 2.1
+ */
+
+class CPL_DLL GNMNetwork : public GDALDataset
+{
+public:
+    GNMNetwork();
+    virtual ~GNMNetwork();
+
+    // GDALDataset Interface
+    virtual const char *GetProjectionRef(void);
+    virtual char      **GetFileList(void);
+
+    // GNMNetwork Interface
+
+    /**
+     * @brief Create network system layers
+     *
+     * Creates the connectivity (the "network path" of data) over the dataset
+     * and returns the resulting network.
+     * NOTE: This method does not create any connections among features
+     * but creates the necessary set of fields, layers, etc.
+     * NOTE: After the successful creation the passed dataset must not be
+     * modified outside (but can be read as usual).
+     * NOTE: For the common network format the creation is forbidden if the
+     * passed dataset already has network system layers and OVERWRITE creation
+     * option is FALSE.
+     *
+     * @param pszFilename - A path there the network folder (schema, etc.) will
+     *                      be created. The folder (schema, etc.) name get
+     *                      options.
+     * @param papszOptions - create network options. The create options
+     *                       specific for gnm driver.
+     * @return CE_None on success
+     */
+    virtual CPLErr Create( const char* pszFilename, char** papszOptions ) = 0;
+
+    /**
+     * @brief Open a network
+     * @param poOpenInfo GDALOpenInfo pointer
+     * @return CE_None on success
+     */
+    virtual CPLErr Open( GDALOpenInfo* poOpenInfo ) = 0;
+
+    /**
+     * @brief Delete network. Delete all dependent layers
+     * @return CE_None on success
+     */
+    virtual CPLErr Delete() = 0;
+
+    /**
+     * @brief GetName - a network name. The value provided to create function
+     *        in GNM_MD_NAME key. While creation this value used to create the
+     *        folder or db schema name. But can be changed after creation.
+     * @return Network name string
+     */
+    virtual const char* GetName() const;
+
+    /**
+     * @brief GetVersion return the network version if applicable
+     * @return version value
+     */
+    virtual int GetVersion() const { return 0;}
+
+    /**
+     * @brief DisconnectAll method clears the network graph
+     * @return CE_None on success
+     */
+    virtual CPLErr DisconnectAll () = 0;
+
+    /**
+     * @brief GetFeatureByGlobalFID search all network layers for given feature
+     *        identificator.
+     * @param nGFID feature identificator.
+     * @return OGRFeature pointer or NULL. The pointer should be freed via
+     *         OGRFeature::DestroyFeature().
+     */
+    virtual OGRFeature *GetFeatureByGlobalFID (GNMGFID nGFID) = 0;
+
+    /**
+     * @brief Create path between start and end GFIDs.
+     * @param nStartGFID - start identificator
+     * @param nEndGFID - end identificator
+     * @param eAlgorithm - The algorithm to get path
+     * @param papszOptions - algorithm specific options
+     * @return In memory OGRLayer pointer with features constituting
+     *         the shortest path (or paths). The caller have to free
+     *         the pointer via @see ReleaseResultSet().
+     */
+    virtual OGRLayer *GetPath (GNMGFID nStartFID, GNMGFID nEndFID,
+                     GNMGraphAlgorithmType eAlgorithm, char** papszOptions) = 0;
+protected:
+    /**
+     * @brief Check if network already exist
+     * @param pszFilename - path to network (folder or database
+     * @param papszOptions - create options
+     * @return TRUE if exist and not overwrite or FALSE
+     */
+    virtual int CheckNetworkExist( const char* pszFilename,
+                                   char** papszOptions ) = 0;
+
+protected:
+    CPLString m_soName;
+    CPLString m_soSRS;
+};
+
+class GNMRule;
+class OGRGNMWrappedResultLayer;
+
+/**
+ * GNM class which represents a geography network of generic format.
+ *
+ * @since GDAL 2.1
+ */
+
+class CPL_DLL GNMGenericNetwork: public GNMNetwork
+{
+public:
+    GNMGenericNetwork();
+    virtual ~GNMGenericNetwork();
+
+    // GDALDataset Interface
+
+    virtual int         GetLayerCount();
+    virtual OGRLayer    *GetLayer(int);
+    virtual OGRErr      DeleteLayer(int);
+
+    virtual int         TestCapability( const char * );
+
+    virtual OGRLayer   *CopyLayer( OGRLayer *poSrcLayer,
+                                   const char *pszNewName,
+                                   char **papszOptions = NULL );
+
+    virtual int CloseDependentDatasets();
+    virtual void FlushCache(void);
+
+    // GNMNetwork Interface
+
+    virtual CPLErr Create( const char* pszFilename, char** papszOptions ) = 0;
+    virtual CPLErr Delete();
+
+    virtual int GetVersion() const;
+    /**
+     * @brief GetNewGlobalFID increase the global ID counter.
+     * @return New global feature ID.
+     */
+    virtual GNMGFID GetNewGlobalFID();
+
+    /**
+     * @brief Get the algorithm name
+     * @param eAlgorithm GNM algorithm type
+     * @param bShortName Indicator which name to return - short or long
+     * @return String with algorithm name
+     */
+    virtual CPLString GetAlgorithmName(GNMDirection eAlgorithm, bool bShortName);
+
+    /**
+     * @brief AddFeatureGlobalFID add the FID <-> Layer name link to fast access
+     *        features by global FID.
+     * @param nFID - global FID
+     * @param pszLayerName - layer name
+     * @return CE_None on success
+     */
+    virtual CPLErr AddFeatureGlobalFID(GNMGFID nFID, const char* pszLayerName);
+
+    /**
+     * @brief Connects two features via third feature (may be virtual, so the
+     *        identificator should be -1). The features may be at the same layer
+     *        or different layers.
+     * @param nSrcFID - source feature identificator
+     * @param nTgtFID - target feature identificator
+     * @param nConFID - connection feature identificator (-1 for virtual connection)
+     * @param dfCost - cost moving from source to target (default 1)
+     * @param dfInvCost - cost moving from target to source (default 1)
+     * @param eDir - direction, may be source to target, traget to source or both.
+     *               (default - both)
+     * @return CE_None on success
+     */
+    virtual CPLErr ConnectFeatures (GNMGFID nSrcFID,
+                                    GNMGFID nTgtFID,
+                                    GNMGFID nConFID = -1,
+                                    double dfCost = 1,
+                                    double dfInvCost = 1,
+                                    GNMDirection eDir = GNM_EDGE_DIR_BOTH);
+
+    /**
+     * @brief Remove features connection
+     * @param nSrcFID - source feature identificator
+     * @param nTgtFID - target feature identificator
+     * @param nConFID - connection feature identificator
+     * @return CE_None on success
+     */
+    virtual CPLErr DisconnectFeatures (GNMGFID nSrcFID,
+                                       GNMGFID nTgtFID,
+                                       GNMGFID nConFID);
+
+    /**
+     * @brief Find the corresponding identificator in graph (source, target,
+     *        connector) and remove such connections.
+     * @param nFID - identificator to find.
+     * @return CE_None on success
+     */
+    virtual CPLErr DisconnectFeaturesWithId(GNMGFID nFID);
+
+    /**
+     * @brief Change connection attributes. Search the connection by source
+     *        feature identificator, target feature identificator and connection
+     *        identificator.
+     * @param nSrcFID - source feature identificator
+     * @param nTgtFID - target feature identificator
+     * @param nConFID - connection feature identificator
+     * @param dfCost - new cost moving from source to target
+     * @param dfInvCost - new cost moving from target to source
+     * @param eDir - new direction
+     * @return CE_None on success
+     */
+    virtual CPLErr ReconnectFeatures (GNMGFID nSrcFID,
+                                      GNMGFID nTgtFID,
+                                      GNMGFID nConFID,
+                                      double dfCost = 1,
+                                      double dfInvCost = 1,
+                                      GNMDirection eDir = GNM_EDGE_DIR_BOTH);
+
+    virtual CPLErr DisconnectAll();
+
+    virtual OGRFeature *GetFeatureByGlobalFID(GNMGFID nFID);
+
+    /**
+     * @brief Create network rule
+     *
+     * Creates the rule in the network according to the special syntax. These
+     * rules are declarative and make an effect for the network when they exist.
+     * Each rule for layer can be created only if the corresponding layer
+     * existed and removed when the layer is being deleted.
+     *
+     * Rules syntax for the common network format in GNM contains the key words
+     * (words in capital letters or signs) and the modifiers which refers to the
+     * network objects. All the following combinations are available:
+     *
+     *  Notation:
+     *	layer1, layer2, layer3 - a layer names (the corresponding layers must be
+     *                           exist;
+     *	field1 - a field name (field must be exist);
+     *	constant1 - any double constant;
+     *	string1 - any string;
+     *
+     *	Rules describing which layer can be connected or not connected with each
+     *  other, and (optional) which layer must serve as a connector. By default
+     *  all connections are forbidden. But while network creation process the
+     *  rule to allow any connection added. During the connection process each
+     *  rule tested if this connection can be created.
+     *
+     *    "ALLOW CONNECTS ANY"
+     *    "DENY CONNECTS ANY"
+     *	  "DENY CONNECTS layer1 WITH layer2"
+     *	  "ALLOW CONNECTS layer1 WITH layer2 VIA layer3"
+     *
+     * @param pszRuleStr Rule string which will parsed. If the parsing was
+     *        successful, the rule will start having effect immediately.
+     * @return CE_None on success.
+     */
+    virtual CPLErr CreateRule (const char *pszRuleStr);
+
+    /**
+     * @brief Delete all rules from network
+     * @return CE_None on success.
+     */
+    virtual CPLErr DeleteAllRules();
+
+    /**
+     * @brief Delete the specified rule
+     * @param pszRuleStr - the rule to delete
+     * @return CE_None on success.
+     */
+    virtual CPLErr DeleteRule(const char *pszRuleStr);
+
+    /**
+     * @brief Get the rule list
+     * @return list of rule strings. The caller have to free the lis via CPLDestroy.
+     */
+    virtual char** GetRules() const;
+
+    /**
+     * @brief Attempts to build the network topology automatically
+     *
+     * The method simply gets point and line or multiline layers from the
+     * papszLayerList and searches for each line which connects two points: start
+     * and end, so it can be not so effective in performance when it is called
+     * on huge networks.
+     * Note, when passing your tolerance value: this value will depend of spatial
+     * reference system of the network, and especially of its 0,0 position
+     * because dfTolerance is just divided by 2 and added/subtracted to/from
+     * both sides of each line-feature end point forming thus the square area
+     * around it. The first point-feature occurred inside this area will be given
+     * as a start/end point for the current connection. So it is also desirable
+     * that at least two layers are passed in papszLayerList (one point and one
+     * line), and they are already connected "visually" ("geometrically").
+     *
+     * @param papszLayerList A list of layers to connect. The list should be
+     *                       freed via CSLDestroy.
+     * @param dfTolerance Snapping tolerance.
+     * @return CE_None on success
+     */
+    virtual CPLErr ConnectPointsByLines (char **papszLayerList,
+                                         double dfTolerance,
+                                         double dfCost,
+                                         double dfInvCost,
+                                         GNMDirection eDir);
+
+    /**
+     * @brief Change the block state of edge or vertex
+     * @param nFID Identificator
+     * @param bIsBlock Block or unblock
+     * @return CE_None on success
+     */
+    virtual CPLErr ChangeBlockState (GNMGFID nFID, bool bIsBlock);
+
+    /**
+     * @brief Change all vertices and edges block state.
+     *
+     * This is mainly use for unblock all vertices and edges.
+     *
+     * @param bIsBlock Block or unblock
+     * @return CE_None on success
+     */
+    virtual CPLErr ChangeAllBlockState (bool bIsBlock = false);
+
+    virtual OGRLayer *GetPath (GNMGFID nStartFID, GNMGFID nEndFID,
+                     GNMGraphAlgorithmType eAlgorithm, char** papszOptions);
+protected:
+    /**
+     * @brief Check or create layer OGR driver
+     * @param pszDefaultDriverName - default driver name
+     * @param papszOptions - create options
+     * @return CE_None if driver is exist or CE_Failure
+     */
+    virtual CPLErr CheckLayerDriver(const char* pszDefaultDriverName,
+                                 char** papszOptions);
+    /**
+     * @brief Check if provided OGR driver accepted as storage for network data
+     * @param pszDriverName The driver name
+     * @return true if supported, else false
+     */
+    virtual bool CheckStorageDriverSupport(const char* pszDriverName) = 0;
+protected:
+    virtual CPLErr CreateMetadataLayer( GDALDataset* const pDS, int nVersion,
+                                     size_t nFieldSize = 1024 );
+    virtual CPLErr StoreNetworkSrs();
+    virtual CPLErr LoadNetworkSrs();
+    virtual CPLErr CreateGraphLayer( GDALDataset* const pDS );
+    virtual CPLErr CreateFeaturesLayer( GDALDataset* const pDS );
+    virtual CPLErr LoadMetadataLayer( GDALDataset* const pDS );
+    virtual CPLErr LoadGraphLayer( GDALDataset* const pDS );
+    virtual CPLErr LoadGraph();
+    virtual CPLErr LoadFeaturesLayer( GDALDataset* const pDS );
+    virtual CPLErr DeleteMetadataLayer() = 0;
+    virtual CPLErr DeleteGraphLayer() = 0;
+    virtual CPLErr DeleteFeaturesLayer() = 0;
+    virtual CPLErr LoadNetworkLayer(const char* pszLayername) = 0;
+    virtual CPLErr DeleteNetworkLayers() = 0;
+    virtual void ConnectPointsByMultiline(GIntBig nFID,
+                                  const OGRMultiLineString *poMultiLineString,
+                                  const std::vector<OGRLayer *> &paPointLayers,
+                                  double dfTolerance, double dfCost,
+                                  double dfInvCost, GNMDirection eDir);
+    virtual void ConnectPointsByLine(GIntBig nFID,
+                                     const OGRLineString *poLineString,
+                                     const std::vector<OGRLayer *> &paPointLayers,
+                                     double dfTolerance, double dfCost,
+                                     double dfInvCost, GNMDirection eDir);
+    virtual GNMGFID FindNearestPoint(const OGRPoint* poPoint,
+                                     const std::vector<OGRLayer*>& paPointLayers,
+                                     double dfTolerance);
+    virtual OGRFeature* FindConnection(GNMGFID nSrcFID, GNMGFID nTgtFID,
+                                       GNMGFID nConFID);
+    virtual void SaveRules();
+    virtual GNMGFID GetNewVirtualFID();
+    virtual void FillResultLayer(OGRGNMWrappedResultLayer* poResLayer,
+                                 const GNMPATH &path, int nNoOfPath,
+                                 bool bReturnVertices, bool bReturnEdges);
+protected:
+    int m_nVersion;
+    GNMGFID m_nGID;
+    GNMGFID m_nVirtualConnectionGID;
+    OGRLayer* m_poMetadataLayer;
+    OGRLayer* m_poGraphLayer;
+    OGRLayer* m_poFeaturesLayer;
+
+    GDALDriver *m_poLayerDriver;
+
+    std::map<GNMGFID, CPLString> m_moFeatureFIDMap;
+    std::vector<OGRLayer*> m_apoLayers;
+    std::vector<GNMRule> m_asRules;
+    bool m_bIsRulesChanged;
+
+    GNMGraph m_oGraph;
+    bool m_bIsGraphLoaded;
+};
+
+/**
+ * GNM layer which represents a geography network layer of generic format.
+ * The class override some OGRLayer methods to fulfill the network requirements.
+ *
+ * @since GDAL 2.1
+ */
+
+class GNMGenericLayer : public OGRLayer
+{
+public:
+    GNMGenericLayer(OGRLayer* poLayer, GNMGenericNetwork* poNetwork);
+    virtual ~GNMGenericLayer();
+
+    // OGRLayer Interface
+
+    virtual OGRGeometry *GetSpatialFilter();
+    virtual void        SetSpatialFilter( OGRGeometry * );
+    virtual void        SetSpatialFilterRect( double dfMinX, double dfMinY,
+                                              double dfMaxX, double dfMaxY );
+
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * );
+    virtual void        SetSpatialFilterRect( int iGeomField,
+                                            double dfMinX, double dfMinY,
+                                            double dfMaxX, double dfMaxY );
+
+    virtual OGRErr      SetAttributeFilter( const char * );
+
+    virtual void        ResetReading();
+    virtual OGRFeature *GetNextFeature();
+    virtual OGRErr      SetNextByIndex( GIntBig nIndex );
+
+    virtual OGRErr      DeleteFeature( GIntBig nFID );
+
+    virtual const char *GetName();
+    virtual OGRwkbGeometryType GetGeomType();
+    virtual OGRFeatureDefn *GetLayerDefn();
+    virtual int         FindFieldIndex( const char *pszFieldName, int bExactMatch );
+
+    virtual OGRSpatialReference *GetSpatialRef();
+
+    virtual GIntBig     GetFeatureCount( int bForce = TRUE );
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent,
+                                  int bForce = TRUE);
+
+    virtual int         TestCapability( const char * );
+
+    virtual OGRErr      CreateField( OGRFieldDefn *poField,
+                                     int bApproxOK = TRUE );
+    virtual OGRErr      DeleteField( int iField );
+    virtual OGRErr      ReorderFields( int* panMap );
+    virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn,
+                                        int nFlagsIn );
+
+    virtual OGRErr      CreateGeomField( OGRGeomFieldDefn *poField,
+                                     int bApproxOK = TRUE );
+
+    virtual OGRErr      SyncToDisk();
+
+    virtual OGRStyleTable *GetStyleTable();
+    virtual void        SetStyleTableDirectly( OGRStyleTable *poStyleTable );
+
+    virtual void        SetStyleTable(OGRStyleTable *poStyleTable);
+
+    virtual OGRErr      StartTransaction();
+    virtual OGRErr      CommitTransaction();
+    virtual OGRErr      RollbackTransaction();
+
+    virtual const char *GetFIDColumn();
+    virtual const char *GetGeometryColumn();
+
+    virtual OGRErr      SetIgnoredFields( const char **papszFields );
+
+    OGRErr              Intersection( OGRLayer *pLayerMethod,
+                                      OGRLayer *pLayerResult,
+                                      char** papszOptions = NULL,
+                                      GDALProgressFunc pfnProgress = NULL,
+                                      void * pProgressArg = NULL );
+    OGRErr              Union( OGRLayer *pLayerMethod,
+                               OGRLayer *pLayerResult,
+                               char** papszOptions = NULL,
+                               GDALProgressFunc pfnProgress = NULL,
+                               void * pProgressArg = NULL );
+    OGRErr              SymDifference( OGRLayer *pLayerMethod,
+                                       OGRLayer *pLayerResult,
+                                       char** papszOptions,
+                                       GDALProgressFunc pfnProgress,
+                                       void * pProgressArg );
+    OGRErr              Identity( OGRLayer *pLayerMethod,
+                                  OGRLayer *pLayerResult,
+                                  char** papszOptions = NULL,
+                                  GDALProgressFunc pfnProgress = NULL,
+                                  void * pProgressArg = NULL );
+    OGRErr              Update( OGRLayer *pLayerMethod,
+                                OGRLayer *pLayerResult,
+                                char** papszOptions = NULL,
+                                GDALProgressFunc pfnProgress = NULL,
+                                void * pProgressArg = NULL );
+    OGRErr              Clip( OGRLayer *pLayerMethod,
+                              OGRLayer *pLayerResult,
+                              char** papszOptions = NULL,
+                              GDALProgressFunc pfnProgress = NULL,
+                              void * pProgressArg = NULL );
+    OGRErr              Erase( OGRLayer *pLayerMethod,
+                               OGRLayer *pLayerResult,
+                               char** papszOptions = NULL,
+                               GDALProgressFunc pfnProgress = NULL,
+                               void * pProgressArg = NULL );
+
+    GIntBig             GetFeaturesRead();
+
+    int                 AttributeFilterEvaluationNeedsGeometry();
+
+    /* consider these private */
+    OGRErr               InitializeIndexSupport( const char * );
+    OGRLayerAttrIndex   *GetIndex();
+
+protected:
+    virtual OGRErr      ISetFeature( OGRFeature *poFeature );
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
+
+protected:
+    CPLString m_soLayerName;
+    OGRLayer *m_poLayer;
+    GNMGenericNetwork* m_poNetwork;
+    std::map<GNMGFID, GIntBig> m_mnFIDMap;
+};
+
+typedef enum
+{
+    /** Rule for connect features */   GRTConnection = 0
+} GNMRuleType;
+
+/**
+ * @brief The simple class for rules
+ *
+ * By now we have only connect rules, so the one class is enough. Maybe in
+ * future the set of classes for different rule types will be needed.
+ *
+ * @since GDAL 2.1
+ */
+
+class CPL_DLL GNMRule
+{
+public:
+    GNMRule();
+    GNMRule(const std::string &oRule );
+    GNMRule(const char* pszRule);
+    GNMRule(const GNMRule &oRule);
+    virtual ~GNMRule();
+    /**
+     * @brief  This function indicate if rule string was parsed successfully
+     * @return true if rule is valid
+     */
+    virtual bool IsValid() const;
+    /**
+     * @brief Indicator of any layer state
+     * @return true if accept any layer
+     */
+    virtual bool IsAcceptAny() const;
+    /**
+     * @brief This is for future use to indicate the rule type/ Now return only
+     * GRTConnection type.
+     * @return the rule type
+     */
+    virtual GNMRuleType GetType() const;
+    /**
+     * @brief Check if connection can take place.
+     * @param soSrcLayerName - the layer name
+     * @param soTgtLayerName - the layer name
+     * @param soConnLayerName - the layer name
+     * @return true if can connect features from soSrcLayerName and soTgtLayerName
+     *         via soConnLayerName
+     */
+    virtual bool CanConnect(const CPLString &soSrcLayerName,
+                            const CPLString &soTgtLayerName,
+                            const CPLString &soConnLayerName = "");
+    virtual CPLString GetSourceLayerName() const;
+    virtual CPLString GetTargetLayerName() const;
+    virtual CPLString GetConnectorLayerName() const;
+    const char* c_str() const;
+    operator const char* (void) const;
+protected:
+    virtual bool ParseRuleString();
+protected:
+    CPLString m_soSrcLayerName;
+    CPLString m_soTgtLayerName;
+    CPLString m_soConnLayerName;
+    bool m_bAllow;
+    bool m_bValid;
+    bool m_bAny;
+    CPLString m_soRuleString;
+};
+
+/**
+ * @brief The OGRGNMWrappedResultLayer class for search paths queries results.
+ *
+ * @since GDAL 2.1
+ */
+
+class OGRGNMWrappedResultLayer : public OGRLayer
+{
+public:
+    OGRGNMWrappedResultLayer(GDALDataset* poDS, OGRLayer* poLayer);
+    ~OGRGNMWrappedResultLayer();
+
+    // OGRLayer
+    virtual void ResetReading();
+    virtual OGRFeature *GetNextFeature();
+    virtual OGRErr SetNextByIndex( GIntBig nIndex );
+    virtual OGRFeature *GetFeature( GIntBig nFID );
+    virtual OGRFeatureDefn *GetLayerDefn();
+    virtual GIntBig GetFeatureCount( int bForce = TRUE );
+    virtual int TestCapability( const char * pszCap );
+    virtual OGRErr CreateField( OGRFieldDefn *poField, int bApproxOK = TRUE );
+    virtual OGRErr      CreateGeomField( OGRGeomFieldDefn *poField,
+                                     int bApproxOK = TRUE );
+    virtual const char *GetFIDColumn();
+    virtual const char *GetGeometryColumn();
+    virtual OGRSpatialReference *GetSpatialRef();
+
+    // OGRGNMWrappedResultLayer
+    virtual OGRErr InsertFeature(OGRFeature* poFeature,
+                                const CPLString &soLayerName, int nPathNo,
+                                bool bIsEdge);
+protected:
+    virtual OGRErr      ISetFeature( OGRFeature *poFeature );
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
+protected:
+    GDALDataset *poDS;
+    OGRLayer    *poLayer;
+};
+
+#endif // GNM
diff --git a/gnm/gnm_api.h b/gnm/gnm_api.h
new file mode 100644
index 0000000..cc80fa4
--- /dev/null
+++ b/gnm/gnm_api.h
@@ -0,0 +1,100 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
+ * Purpose:  GNM C API.
+ * Authors:  Mikhail Gusev (gusevmihs at gmail dot com)
+ *           Dmitry Baryshnikov, polimax at mail.ru
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Mikhail Gusev
+ * Copyright (c) 2014-2015, NextGIS <info at nextgis.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef GNM_API
+#define GNM_API
+
+#include "gnm.h"
+
+CPL_C_START
+
+typedef void *GNMNetworkH;
+typedef void *GNMGenericNetworkH;
+
+const char CPL_DLL * CPL_STDCALL GNMGetName (GNMNetworkH hNet);
+
+int CPL_DLL CPL_STDCALL GNMGetVersion(GNMNetworkH hNet);
+
+CPLErr CPL_DLL CPL_STDCALL GNMDisconnectAll (GNMNetworkH hNet);
+
+OGRFeatureH CPL_DLL CPL_STDCALL GNMGetFeatureByGlobalFID (GNMNetworkH hNet, GNMGFID nGFID);
+
+OGRLayerH CPL_DLL CPL_STDCALL GNMGetPath (GNMNetworkH hNet, GNMGFID nStartFID,
+                              GNMGFID nEndFID, GNMGraphAlgorithmType eAlgorithm,
+                              char** papszOptions);
+
+
+
+CPLErr CPL_DLL CPL_STDCALL GNMConnectFeatures (GNMGenericNetworkH hNet,
+                                               GNMGFID nSrcFID, GNMGFID nTgtFID,
+                                               GNMGFID nConFID, double dfCost,
+                                               double dfInvCost,
+                                               GNMDirection eDir);
+
+CPLErr CPL_DLL CPL_STDCALL GNMDisconnectFeatures (GNMGenericNetworkH hNet,
+                                                  GNMGFID nSrcFID, GNMGFID nTgtFID,
+                                                  GNMGFID nConFID);
+
+CPLErr CPL_DLL CPL_STDCALL GNMDisconnectFeaturesWithId(GNMGenericNetworkH hNet,
+                                                       GNMGFID nFID);
+
+
+CPLErr CPL_DLL CPL_STDCALL GNMReconnectFeatures (GNMGenericNetworkH hNet,
+                                                 GNMGFID nSrcFID, GNMGFID nTgtFID,
+                                                 GNMGFID nConFID, double dfCost,
+                                                 double dfInvCost, GNMDirection eDir);
+
+CPLErr CPL_DLL CPL_STDCALL GNMCreateRule (GNMGenericNetworkH hNet,
+                                          const char *pszRuleStr);
+
+CPLErr CPL_DLL CPL_STDCALL GNMDeleteAllRules(GNMGenericNetworkH hNet);
+
+CPLErr CPL_DLL CPL_STDCALL GNMDeleteRule(GNMGenericNetworkH hNet,
+                                         const char *pszRuleStr);
+
+char CPL_DLL ** CPL_STDCALL GNMGetRules(GNMGenericNetworkH hNet);
+
+CPLErr CPL_DLL CPL_STDCALL GNMConnectPointsByLines (GNMGenericNetworkH hNet,
+                                                    char **papszLayerList,
+                                                    double dfTolerance,
+                                                    double dfCost,
+                                                    double dfInvCost,
+                                                    GNMDirection eDir);
+
+CPLErr CPL_DLL CPL_STDCALL GNMChangeBlockState (GNMGenericNetworkH hNet,
+                                                GNMGFID nFID, bool bIsBlock);
+
+CPLErr CPL_DLL CPL_STDCALL GNMChangeAllBlockState (GNMGenericNetworkH hNet,
+                                                   int bIsBlock);
+
+CPL_C_END
+
+#endif // GNM_API
diff --git a/gnm/gnm_arch.dox b/gnm/gnm_arch.dox
new file mode 100644
index 0000000..8e639f4
--- /dev/null
+++ b/gnm/gnm_arch.dox
@@ -0,0 +1,56 @@
+/*! \page gnm_arch GNM Architecture
+
+This document is intended to describe the purpose and the structure of Geographic Network Model classes. GNM is the part of GDAL and provides the methods of creating, managing and analysing geographical networks.<p>
+
+The key purpose of GNM classes:<p>
+<ul>
+<li> To provide an abstraction for different existed network formats, like GDAL (previously OGR) provides one for spatial vector formats;<p>
+<li> To provide a network functionality to those spatial formats which does not have it at all.<p>
+</ul>
+
+\section gnm_arch_general_concept General concept
+
+Any real-world network can be represented as a set of vector data, which can be itself represented in GDAL as a GDALDataset. In GNM this data consists of two parts. Network's topology (graph), network's metadata (name/description), set of special feature identifiers, etc. belong to the "network part", while the common for GDAL layers, features, geometries belong to the "spatial/attribute part". In order to work with the datasets of different formats the following classes were designed in [...]
+
+<b>Network</b>: GNMNetwork represents an abstract network. The network data and spatial/attribute data in a dataset of some format in fact can be not separable (just additional layers/fields/tags), while the concrete implementation of GNMNetwork "knows" which data from the whole dataset refers to "network part" and is able to operate it. GNMNetwork allows user the following:<p>
+
+<ul>
+<li> Setting/unsetting connections. These generic methods of building the network topology (automatically and manually) receive the identifiers of features being connected in a common way, while the concrete implementation knows where and how to store and build the topology;<p>
+<li> Reading connections. The generic methods return the connections in the common way;<p>
+<li> Adding/removing layers/features. When the feature or layer is being added to the network some actions can be initiated (weights change in a graph, cascade changes in connected features). Concrete GNMNetwork describes how it is done.<p>
+<li> Defining network's business logic or behaviour. It can be expressed in network rules or constraints/restrictions. Expected that each rule can be set from a string and each concrete GNMNetwork will transform it to the internal look.<p>
+</ul>
+
+<b>Format</b>: GNMNetwork inherits GDALDataset and looks like OGRDatasource with additional functionality. There are a set of GDAL drivers for networks. The generic network implementation in GDAL provides additional functionality like rules, virtual edges and vertices. Also, while editing the feature the network control the network rules and other specific, and can deny saving edits. The other network drivers (pgRouting, OSRM, GraphHopper, etc.) should provide the basic functionality via [...]
+
+\section gnm_arch_network_formats Network formats
+
+To add a <b>native</b> support of the existed network format (like PostGIS pgRouting, Oracle Spatial Networks, topology in GML, etc.) to GNM the developer should implement the corresponding GNMDriver-GNMNetwork interface. But there is also a capability to use the <b>generic</b> network format, which is already implemented in GNM as a special class. It can be extremely useful when there is a need to create and use a network in the format that initially does not have its "network part" (li [...]
+
+<b>GNMGenericNetwork</b>: GNMGenericNetwork is a concrete implementation of the GNMNetwork. GNMGenericNetwork intends to support the most GDALDataset drivers (depends on the corresponding driver capabilities). Technically the network format abstraction is achieved with the help of GDAL abstraction: datasets and layers approach. GNMGdalNetwork aggregates a GDALDataset instance where the "network part" is represented as a set of "system layers" (wkbNone geometry, specific attribute fields) [...]
+
+The way of describing real-world networks by GNMGenericNetwork intends to be a generic, because:<p>
+<ul>
+<li> The most general type of graph is used, which holds every useful information: directions of edges (directed/undirected), edge costs (weighted/unweighted). This graph is stored as an incidence list: source vertex feature id, target vertex feature id, edge feature id, direct cost, inverse cost, direction of edge;<p>
+<li> Any feature with any geometry can be the vertex or the edge in a graph. Also, it may be no feature “under” the connection's edge at all (actually the virtual edge is created for this case). All this means that user operates with the feature identifiers, while the GNMGenericNetwork guaranties the connections integrity among features; <p>
+<li> Any feature in the network will gain the unique identifier – Global Feature Identifier (GFID) which allows unify any amount of "class layers" under one network;<p>
+<li> GNMGenericNetwork uses its own way to determine the network's business logic. See GNMGenericNetwork::CreateRule() for more details.<p>
+</ul>
+
+See the GNMGenericNetwork class documentation for more details.<p>
+
+The network of common format has also the following important features:<p>
+<ul>
+<li> The single spatial reference system is used in the network, that means that each feature which appears in the network will be transformed to this SRS;<p>
+<li> The network always created void and there is a need to import or create features;<p>
+<li> It is not possible to remove the "network part" from the dataset – only delete the whole network with all data. The deletion is made layer by layer and deletes only system and class layers which registered in the network.<p>
+</ul>
+
+\section gnm_arch_analysis Network analysis
+
+The network analysis in GNM is implemented in GNMNetwork object.<p>
+
+
+<b>GNMGenericNetwork</b> holds the graph in memory in STL containers and provides basic algorithms which return the results in the array-form (e.g. std::vector full of path's edges and vertexes GFIDs). But the caller get a result as OGRlayer there features get from layers consist the network. Also some additional fields created (VERTEX/EDGE indicator field, GFID, layer name, etc.). The caller have to free the result OGRLayer via ReleaseResultSet<p>
+
+*/
diff --git a/gnm/gnm_frmts/GNUmakefile b/gnm/gnm_frmts/GNUmakefile
new file mode 100644
index 0000000..946a762
--- /dev/null
+++ b/gnm/gnm_frmts/GNUmakefile
@@ -0,0 +1,38 @@
+
+include ../../GDALmake.opt
+
+#config gnm drivers list
+
+#add formats
+GNMFILE_ENABLED=yes
+GNMDB_ENABLED=yes
+#
+
+ifeq ($(GNMFILE_ENABLED),yes)
+    CXXFLAGS	:=	$(CXXFLAGS) -DGNMFILE_ENABLED
+endif
+
+
+ifeq ($(GNMDB_ENABLED),yes)
+    CXXFLAGS	:=	$(CXXFLAGS) -DGNMDB_ENABLED
+endif
+
+
+SUBDIRS-$(GNMFILE_ENABLED)	+= file
+SUBDIRS-$(GNMDB_ENABLED)	+= db
+
+OBJ	=	o/gnmregisterall.o
+
+%-install-obj:
+	$(MAKE) -C $* install-obj
+
+default:	$(OBJ:.o=.$(OBJ_EXT))  $(foreach d,$(SUBDIRS-yes),$(d)-install-obj)
+
+o/gnmregisterall.$(OBJ_EXT):	gnmregisterall.cpp ../../GDALmake.opt
+	$(CXX) -c $(GDAL_INCLUDE) $(CXXFLAGS) $(FRMT_FLAGS) \
+	gnmregisterall.cpp -o o/gnmregisterall.$(OBJ_EXT)
+
+clean:	$(foreach d,$(SUBDIRS-yes),$(d)-clean)
+	$(RM) -f *.o o/*.o o/*.a
+	$(RM) o/*.lo
+
diff --git a/gnm/gnm_frmts/db/GNUmakefile b/gnm/gnm_frmts/db/GNUmakefile
new file mode 100644
index 0000000..26d0a17
--- /dev/null
+++ b/gnm/gnm_frmts/db/GNUmakefile
@@ -0,0 +1,18 @@
+
+
+include ../../../GDALmake.opt
+
+OBJ	=	gnmdbdriver.o gnmdbnetwork.o
+
+CPPFLAGS	:=	-I. -I../ -I../../ $(CPPFLAGS)
+
+default:	$(OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+	rm -f *.lo $(O_OBJ)
+
+install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+
+
diff --git a/gnm/gnm_frmts/db/gnmdb.h b/gnm/gnm_frmts/db/gnmdb.h
new file mode 100644
index 0000000..6bed277
--- /dev/null
+++ b/gnm/gnm_frmts/db/gnmdb.h
@@ -0,0 +1,61 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
+ * Purpose:  GNM db based generic driver.
+ * Authors:  Mikhail Gusev (gusevmihs at gmail dot com)
+ *           Dmitry Baryshnikov, polimax at mail.ru
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Mikhail Gusev
+ * Copyright (c) 2014-2015, NextGIS <info at nextgis.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gnm.h"
+
+class GNMDatabaseNetwork : public GNMGenericNetwork
+{
+public:
+    GNMDatabaseNetwork();
+    virtual ~GNMDatabaseNetwork();
+    virtual CPLErr Open( GDALOpenInfo* poOpenInfo );
+    virtual OGRErr      DeleteLayer(int);
+    virtual CPLErr Create( const char* pszFilename, char** papszOptions );
+protected:
+    virtual OGRLayer   *ICreateLayer( const char *pszName,
+                                   OGRSpatialReference *poSpatialRef = NULL,
+                                   OGRwkbGeometryType eGType = wkbUnknown,
+                                   char ** papszOptions = NULL );
+    virtual int CheckNetworkExist( const char* pszFilename, char** papszOptions );
+protected:
+    virtual CPLErr DeleteMetadataLayer();
+    virtual CPLErr DeleteGraphLayer();
+    virtual CPLErr DeleteFeaturesLayer();
+    virtual CPLErr DeleteNetworkLayers();
+    virtual CPLErr LoadNetworkLayer(const char* pszLayername);
+    virtual bool CheckStorageDriverSupport(const char* pszDriverName);
+protected:
+    CPLErr FormName(const char* pszFilename, char** papszOptions);
+    CPLErr DeleteLayerByName(const char* pszLayerName);
+protected:
+    GDALDataset* m_poDS;
+    CPLString m_soNetworkFullName;
+};
diff --git a/gnm/gnm_frmts/db/gnmdbdriver.cpp b/gnm/gnm_frmts/db/gnmdbdriver.cpp
new file mode 100644
index 0000000..adb2496
--- /dev/null
+++ b/gnm/gnm_frmts/db/gnmdbdriver.cpp
@@ -0,0 +1,136 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
+ * Purpose:  GNM generic driver.
+ * Authors:  Mikhail Gusev (gusevmihs at gmail dot com)
+ *           Dmitry Baryshnikov, polimax at mail.ru
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Mikhail Gusev
+ * Copyright (c) 2014-2015, NextGIS <info at nextgis.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gnm_frmts.h"
+#include "gnm_priv.h"
+#include "gnmdb.h"
+
+static int GNMDBDriverIdentify( GDALOpenInfo* poOpenInfo )
+
+{
+    if( !STARTS_WITH_CI(poOpenInfo->pszFilename, "PGB:") &&
+        !STARTS_WITH_CI(poOpenInfo->pszFilename, "PG:") )
+        return FALSE;
+    if( (poOpenInfo->nOpenFlags & GDAL_OF_GNM) == 0 )
+        return FALSE;
+
+    // TODO: do we need to open datasource end check tables/layer exist?
+
+    return TRUE;
+}
+
+static GDALDataset *GNMDBDriverOpen( GDALOpenInfo* poOpenInfo )
+
+{
+    if( !GNMDBDriverIdentify(poOpenInfo) )
+        return NULL;
+
+    GNMDatabaseNetwork* poFN = new GNMDatabaseNetwork();
+
+    if( poFN->Open( poOpenInfo ) != CE_None)
+    {
+        delete poFN;
+        poFN = NULL;
+    }
+
+    return poFN;
+}
+
+
+static GDALDataset *GNMDBDriverCreate( const char * pszName,
+                                        CPL_UNUSED int nBands,
+                                        CPL_UNUSED int nXSize,
+                                        CPL_UNUSED int nYSize,
+                                        CPL_UNUSED GDALDataType eDT,
+                                        char **papszOptions )
+{
+    CPLAssert( NULL != pszName );
+    CPLDebug( "GNM", "Attempt to create network at: %s", pszName );
+
+    GNMDatabaseNetwork *poFN = new GNMDatabaseNetwork();
+
+    if( poFN->Create( pszName, papszOptions ) != CE_None )
+    {
+        delete poFN;
+        poFN = NULL;
+    }
+
+    return poFN;
+}
+
+static CPLErr GNMDBDriverDelete( const char *pszDataSource )
+
+{
+    GDALOpenInfo oOpenInfo(pszDataSource, GA_Update);
+    GNMDatabaseNetwork* poFN = new GNMDatabaseNetwork();
+
+    if( poFN->Open( &oOpenInfo ) != CE_None)
+    {
+        delete poFN;
+        poFN = NULL;
+
+        return CE_Failure;
+    }
+
+    return poFN->Delete();
+}
+
+void RegisterGNMDatabase()
+{
+    if( GDALGetDriverByName( "GNMDatabase" ) == NULL )
+    {
+        GDALDriver  *poDriver = new GDALDriver();
+
+        poDriver->SetDescription( "GNMDatabase" );
+        poDriver->SetMetadataItem( GDAL_DCAP_GNM, "YES" );
+        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                                   "Geographic Network generic DB based "
+                                   "model" );
+
+        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, CPLSPrintf(
+"<CreationOptionList>"
+"  <Option name='%s' type='string' description='The network name. Also it will be a folder name, so the limits for folder name distribute on network name'/>"
+"  <Option name='%s' type='string' description='The network description. Any text describes the network'/>"
+"  <Option name='%s' type='string' description='The network Spatial reference. All network features will reproject to this spatial reference. May be a WKT text or EPSG code'/>"
+"  <Option name='FORMAT' type='string' description='The OGR format to store network data.'/>"
+"  <Option name='OVERWRITE' type='boolean' description='Overwrite exist network or not' default='NO'/>"
+"</CreationOptionList>", GNM_MD_NAME, GNM_MD_DESCR, GNM_MD_SRS) );
+
+        poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+                                   "<LayerCreationOptionList/>" );
+        poDriver->pfnOpen = GNMDBDriverOpen;
+        poDriver->pfnIdentify = GNMDBDriverIdentify;
+        poDriver->pfnCreate = GNMDBDriverCreate;
+        poDriver->pfnDelete = GNMDBDriverDelete;
+
+        GetGDALDriverManager()->RegisterDriver( poDriver );
+    }
+}
diff --git a/gnm/gnm_frmts/db/gnmdbnetwork.cpp b/gnm/gnm_frmts/db/gnmdbnetwork.cpp
new file mode 100644
index 0000000..a77f536
--- /dev/null
+++ b/gnm/gnm_frmts/db/gnmdbnetwork.cpp
@@ -0,0 +1,462 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
+ * Purpose:  GNM db based generic driver.
+ * Authors:  Mikhail Gusev (gusevmihs at gmail dot com)
+ *           Dmitry Baryshnikov, polimax at mail.ru
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Mikhail Gusev
+ * Copyright (c) 2014-2015, NextGIS <info at nextgis.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gnmdb.h"
+#include "gnm_priv.h"
+
+GNMDatabaseNetwork::GNMDatabaseNetwork() : GNMGenericNetwork()
+{
+    m_poDS = NULL;
+}
+
+GNMDatabaseNetwork::~GNMDatabaseNetwork()
+{
+    FlushCache();
+
+    GDALClose(m_poDS);
+}
+
+CPLErr GNMDatabaseNetwork::Open(GDALOpenInfo *poOpenInfo)
+{
+    FormName(poOpenInfo->pszFilename, poOpenInfo->papszOpenOptions);
+
+    if(CSLFindName(poOpenInfo->papszOpenOptions, "LIST_ALL_TABLES") == -1)
+        poOpenInfo->papszOpenOptions = CSLAddNameValue(
+                    poOpenInfo->papszOpenOptions, "LIST_ALL_TABLES", "YES");
+
+    m_poDS = (GDALDataset*) GDALOpenEx( m_soNetworkFullName, GDAL_OF_VECTOR |
+                     GDAL_OF_UPDATE, NULL, NULL, poOpenInfo->papszOpenOptions );
+
+    if( NULL == m_poDS )
+    {
+    CPLError( CE_Failure, CPLE_OpenFailed, "Open '%s' failed",
+              m_soNetworkFullName.c_str() );
+    return CE_Failure;
+    }
+
+    // There should be only one schema so no schema name can be in table name
+    if(LoadMetadataLayer(m_poDS) != CE_None)
+    {
+        return CE_Failure;
+    }
+
+    if(LoadGraphLayer(m_poDS) != CE_None)
+    {
+        return CE_Failure;
+    }
+
+    if(LoadFeaturesLayer(m_poDS) != CE_None)
+    {
+        return CE_Failure;
+    }
+
+    return CE_None;
+}
+
+CPLErr GNMDatabaseNetwork::Create( const char* pszFilename, char** papszOptions )
+{
+    FormName(pszFilename, papszOptions);
+
+    if(m_soName.empty() || m_soNetworkFullName.empty())
+    {
+        CPLError( CE_Failure, CPLE_IllegalArg,
+                  "The network name should be present" );
+        return CE_Failure;
+    }
+
+    if(NULL == m_poDS)
+    {
+        m_poDS = (GDALDataset*) GDALOpenEx( m_soNetworkFullName, GDAL_OF_VECTOR |
+                                       GDAL_OF_UPDATE, NULL, NULL, papszOptions );
+    }
+
+    if( NULL == m_poDS )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed, "Open '%s' failed",
+                  m_soNetworkFullName.c_str() );
+        return CE_Failure;
+    }
+
+    GDALDriver *l_poDriver = m_poDS->GetDriver();
+    if(NULL == l_poDriver)
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed, "Get dataset driver failed");
+        return CE_Failure;
+    }
+
+    if(!CheckStorageDriverSupport(l_poDriver->GetDescription()))
+    {
+        return CE_Failure;
+    }
+
+    // check required options
+
+    const char* pszNetworkDescription = CSLFetchNameValue(papszOptions,
+                                                         GNM_MD_DESCR);
+    if(NULL != pszNetworkDescription)
+        sDescription = pszNetworkDescription;
+
+    // check Spatial reference
+    const char* pszSRS = CSLFetchNameValue(papszOptions, GNM_MD_SRS);
+    if( NULL == pszSRS )
+    {
+        CPLError( CE_Failure, CPLE_IllegalArg,
+                  "The network spatial reference should be present" );
+        return CE_Failure;
+    }
+    else
+    {
+        OGRSpatialReference spatialRef;
+        if (spatialRef.SetFromUserInput(pszSRS) != OGRERR_NONE)
+        {
+            CPLError( CE_Failure, CPLE_IllegalArg,
+                      "The network spatial reference should be present" );
+            return CE_Failure;
+        }
+
+        char *wktSrs = NULL;
+        if (spatialRef.exportToWkt(&wktSrs) != OGRERR_NONE)
+        {
+            CPLError( CE_Failure, CPLE_IllegalArg,
+                      "The network spatial reference should be present" );
+            return CE_Failure;
+        }
+        m_soSRS = wktSrs;
+
+        CPLFree(wktSrs);
+    }
+
+    int nResult = CheckNetworkExist(pszFilename, papszOptions);
+
+    if(TRUE == nResult)
+    {
+        CPLError( CE_Failure, CPLE_IllegalArg, "The network already exist" );
+        return CE_Failure;
+    }
+
+    // Create the necessary system layers and fields
+
+    // Create meta layer
+
+    CPLErr eResult = CreateMetadataLayer(m_poDS, GNM_VERSION_NUM);
+
+    if(CE_None != eResult)
+    {
+        //an error message should come from function
+        return CE_Failure;    }
+
+    // Create graph layer
+
+    eResult = CreateGraphLayer(m_poDS);
+
+    if(CE_None != eResult)
+    {
+        DeleteMetadataLayer();
+        return CE_Failure;
+    }
+
+    // Create features layer
+
+    eResult = CreateFeaturesLayer(m_poDS);
+
+    if(CE_None != eResult)
+    {
+        DeleteMetadataLayer();
+        DeleteGraphLayer();
+        return CE_Failure;
+    }
+
+    return CE_None;
+}
+
+int GNMDatabaseNetwork::CheckNetworkExist(const char *pszFilename, char **papszOptions)
+{
+    // check if path exist
+    // if path exist check if network already present and OVERWRITE option
+    // else create the path
+
+    if(FormName(pszFilename, papszOptions) != CE_None)
+    {
+        return TRUE;
+    }
+
+    if(NULL == m_poDS)
+    {
+        m_poDS = (GDALDataset*) GDALOpenEx( m_soNetworkFullName, GDAL_OF_VECTOR |
+                                      GDAL_OF_UPDATE, NULL, NULL, papszOptions );
+    }
+
+    bool bOverwrite = CPL_TO_BOOL(CSLFetchBoolean(papszOptions, "OVERWRITE", FALSE));
+
+    std::vector<int> anDeleteLayers;
+    int i;
+    for(i = 0; i < m_poDS->GetLayerCount(); ++i)
+    {
+        OGRLayer* poLayer = m_poDS->GetLayer(i);
+        if(NULL == poLayer)
+            continue;
+
+        if(EQUAL(poLayer->GetName(), GNM_SYSLAYER_META) ||
+           EQUAL(poLayer->GetName(), GNM_SYSLAYER_GRAPH) ||
+           EQUAL(poLayer->GetName(), GNM_SYSLAYER_FEATURES) )
+        {
+            anDeleteLayers.push_back(i);
+        }
+    }
+
+    if(anDeleteLayers.empty())
+        return FALSE;
+
+    if(bOverwrite)
+    {
+        for(i = (int)anDeleteLayers.size(); i > 0; i--)
+        {
+            CPLDebug("GNM", "Delete layer: %d", i);
+            if(m_poDS->DeleteLayer(anDeleteLayers[i - 1]) != OGRERR_NONE)
+                return TRUE;
+        }
+        return FALSE;
+    }
+    else
+    {
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+CPLErr GNMDatabaseNetwork::DeleteMetadataLayer()
+{
+    return DeleteLayerByName(GNM_SYSLAYER_META);
+}
+
+CPLErr GNMDatabaseNetwork::DeleteGraphLayer()
+{
+    return DeleteLayerByName(GNM_SYSLAYER_GRAPH);
+}
+
+CPLErr GNMDatabaseNetwork::DeleteFeaturesLayer()
+{
+    return DeleteLayerByName(GNM_SYSLAYER_FEATURES);
+}
+
+CPLErr GNMDatabaseNetwork::DeleteLayerByName(const char* pszLayerName)
+{
+    if(NULL == m_poDS)
+        return CE_Failure;
+
+    for(int i = 0; i < m_poDS->GetLayerCount(); ++i)
+    {
+        OGRLayer* poLayer = m_poDS->GetLayer(i);
+        if(NULL == poLayer)
+            continue;
+
+        if(EQUAL(poLayer->GetName(), pszLayerName))
+            return m_poDS->DeleteLayer(i) == OGRERR_NONE ? CE_None : CE_Failure;
+    }
+
+    CPLError(CE_Failure, CPLE_IllegalArg, "The layer %s not exist",
+             pszLayerName );
+    return CE_Failure;
+}
+
+CPLErr GNMDatabaseNetwork::DeleteNetworkLayers()
+{
+    while(GetLayerCount() > 0)
+    {
+        OGRErr eErr = DeleteLayer(0);
+        if(eErr != OGRERR_NONE)
+            return CE_Failure;
+    }
+    return CE_None;
+}
+
+CPLErr GNMDatabaseNetwork::LoadNetworkLayer(const char *pszLayername)
+{
+    // check if not loaded
+    for(size_t i = 0; i < m_apoLayers.size(); ++i)
+    {
+        if(EQUAL(m_apoLayers[i]->GetName(), pszLayername))
+            return CE_None;
+    }
+
+    OGRLayer* poLayer = m_poDS->GetLayerByName(pszLayername);
+    if(NULL == poLayer)
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed, "Layer '%s' is not exist",
+                  pszLayername );
+        return CE_Failure;
+    }
+
+    CPLDebug("GNM", "Layer '%s' loaded", poLayer->GetName());
+
+    GNMGenericLayer* pGNMLayer = new GNMGenericLayer(poLayer, this);
+    m_apoLayers.push_back(pGNMLayer);
+
+    return CE_None;
+}
+
+bool GNMDatabaseNetwork::CheckStorageDriverSupport(const char *pszDriverName)
+{
+    if(EQUAL(pszDriverName, "PostgreSQL"))
+        return true;
+    //TODO: expand this list with supported OGR direvers
+    return false;
+}
+
+CPLErr GNMDatabaseNetwork::FormName(const char *pszFilename, char **papszOptions)
+{
+    if(m_soNetworkFullName.empty())
+        m_soNetworkFullName = pszFilename;
+
+    if(m_soName.empty())
+    {
+        const char* pszNetworkName = CSLFetchNameValue(papszOptions, GNM_MD_NAME);
+        if(NULL != pszNetworkName)
+        {
+            m_soName = pszNetworkName;
+        }
+
+        char *pszActiveSchemaStart;
+        pszActiveSchemaStart = (char *)strstr(pszFilename, "active_schema=");
+        if (pszActiveSchemaStart == NULL)
+            pszActiveSchemaStart = (char *)strstr(pszFilename, "ACTIVE_SCHEMA=");
+        if (pszActiveSchemaStart != NULL)
+        {
+            char           *pszActiveSchema;
+            const char     *pszEnd = NULL;
+
+            pszActiveSchema = CPLStrdup( pszActiveSchemaStart + strlen("active_schema=") );
+
+            pszEnd = strchr(pszActiveSchemaStart, ' ');
+            if( pszEnd == NULL )
+                pszEnd = pszFilename + strlen(pszFilename);
+
+            pszActiveSchema[pszEnd - pszActiveSchemaStart - strlen("active_schema=")] = '\0';
+
+            m_soName = pszActiveSchema;
+            CPLFree(pszActiveSchema);
+        }
+        else
+        {
+            if(!m_soName.empty())
+            {
+                //add active schema
+                m_soNetworkFullName += "ACTIVE_SCHEMA=" + m_soName;
+            }
+            else
+            {
+                m_soName = "public";
+            }
+        }
+
+        CPLDebug( "GNM", "Network name: %s", m_soName.c_str() );
+    }
+    return CE_None;
+}
+
+OGRErr GNMDatabaseNetwork::DeleteLayer(int nIndex)
+{
+    if(NULL == m_poDS)
+    {
+        CPLError(CE_Failure, CPLE_FileIO, "Network not opened." );
+        return OGRERR_FAILURE;
+    }
+
+    OGRLayer* poNetworkLayer = GetLayer(nIndex);
+
+    CPLDebug("GNM", "Delete network layer '%s'", poNetworkLayer->GetName());
+
+    int nDeleteIndex = -1;
+    for(int i = 0; i < m_poDS->GetLayerCount(); ++i)
+    {
+        OGRLayer* poLayer = m_poDS->GetLayer(i);
+        if(EQUAL(poNetworkLayer->GetName(), poLayer->GetName()))
+        {
+            nDeleteIndex = i;
+            break;
+        }
+    }
+
+    if(m_poDS->DeleteLayer(nDeleteIndex) != OGRERR_NONE)
+    {
+        return OGRERR_FAILURE;
+    }
+
+    return GNMGenericNetwork::DeleteLayer(nIndex);
+}
+
+OGRLayer *GNMDatabaseNetwork::ICreateLayer(const char *pszName,
+                                CPL_UNUSED OGRSpatialReference *poSpatialRef,
+                                OGRwkbGeometryType eGType, char **papszOptions)
+{
+    //check if layer with such name exist
+    for(int i = 0; i < GetLayerCount(); ++i)
+    {
+        OGRLayer* pLayer = GetLayer(i);
+        if(NULL == pLayer)
+            continue;
+        if(EQUAL(pLayer->GetName(), pszName))
+        {
+            CPLError( CE_Failure, CPLE_IllegalArg,
+                      "The network layer '%s' already exist.", pszName );
+            return NULL;
+        }
+    }
+
+    OGRSpatialReference oSpaRef(m_soSRS);
+
+    OGRLayer *poLayer = m_poDS->CreateLayer( pszName, &oSpaRef, eGType, papszOptions );
+    if( poLayer == NULL )
+    {
+        CPLError( CE_Failure, CPLE_FileIO, "Layer creation failed." );
+        return NULL;
+    }
+
+    OGRFieldDefn oField( GNM_SYSFIELD_GFID, GNMGFIDInt );
+    if( poLayer->CreateField( &oField ) != OGRERR_NONE )
+    {
+        CPLError( CE_Failure, CPLE_FileIO, "Creating global identificator field failed." );
+        return NULL;
+    }
+
+
+    OGRFieldDefn oFieldBlock(GNM_SYSFIELD_BLOCKED, OFTInteger);
+    if( poLayer->CreateField( &oFieldBlock ) != OGRERR_NONE )
+    {
+        CPLError( CE_Failure, CPLE_FileIO, "Creating is blocking field failed." );
+        return NULL;
+    }
+
+    GNMGenericLayer* pGNMLayer = new GNMGenericLayer(poLayer, this);
+    m_apoLayers.push_back(pGNMLayer);
+    return pGNMLayer;
+}
diff --git a/gnm/gnm_frmts/db/makefile.vc b/gnm/gnm_frmts/db/makefile.vc
new file mode 100755
index 0000000..984f852
--- /dev/null
+++ b/gnm/gnm_frmts/db/makefile.vc
@@ -0,0 +1,16 @@
+
+OBJ	=	gnmdbdriver.obj gnmdbnetwork.obj
+
+
+GDAL_ROOT	=	..\..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+EXTRAFLAGS =	-I.. -I..\..
+
+default:	$(OBJ)
+	xcopy /D  /Y *.obj ..\o
+
+clean:
+	-del *.obj *.pdb
+
diff --git a/gnm/gnm_frmts/file/GNUmakefile b/gnm/gnm_frmts/file/GNUmakefile
new file mode 100644
index 0000000..bce2372
--- /dev/null
+++ b/gnm/gnm_frmts/file/GNUmakefile
@@ -0,0 +1,18 @@
+
+
+include ../../../GDALmake.opt
+
+OBJ	=	gnmfiledriver.o gnmfilenetwork.o
+
+CPPFLAGS	:=	-I. -I../ -I../../ $(CPPFLAGS)
+
+default:	$(OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+	rm -f *.lo $(O_OBJ)
+
+install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+
+
diff --git a/gnm/gnm_frmts/file/gnmfile.h b/gnm/gnm_frmts/file/gnmfile.h
new file mode 100644
index 0000000..7493874
--- /dev/null
+++ b/gnm/gnm_frmts/file/gnmfile.h
@@ -0,0 +1,75 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
+ * Purpose:  GNM file based generic driver.
+ * Authors:  Mikhail Gusev (gusevmihs at gmail dot com)
+ *           Dmitry Baryshnikov, polimax at mail.ru
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Mikhail Gusev
+ * Copyright (c) 2014-2015, NextGIS <info at nextgis.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gnm.h"
+
+#define GNM_MD_DEFAULT_FILE_FORMAT  "ESRI Shapefile"
+
+class GNMFileNetwork : public GNMGenericNetwork
+{
+public:
+    GNMFileNetwork();
+    virtual ~GNMFileNetwork();
+    virtual CPLErr Open( GDALOpenInfo* poOpenInfo );
+    virtual CPLErr Delete();
+    virtual int CloseDependentDatasets();
+    virtual OGRErr      DeleteLayer(int);
+    virtual CPLErr Create( const char* pszFilename, char** papszOptions );
+protected:
+    virtual OGRLayer   *ICreateLayer( const char *pszName,
+                                   OGRSpatialReference *poSpatialRef = NULL,
+                                   OGRwkbGeometryType eGType = wkbUnknown,
+                                   char ** papszOptions = NULL );
+    virtual int CheckNetworkExist( const char* pszFilename, char** papszOptions );
+protected:
+    virtual CPLErr CreateMetadataLayerFromFile( const char* pszFilename, int nVersion,
+                                        char** papszOptions );
+    virtual CPLErr StoreNetworkSrs();
+    virtual CPLErr LoadNetworkSrs();
+    virtual CPLErr DeleteMetadataLayer();
+    virtual CPLErr CreateGraphLayerFromFile( const char* pszFilename,
+                                     char** papszOptions );
+    virtual CPLErr DeleteGraphLayer();
+    virtual CPLErr CreateFeaturesLayerFromFile( const char* pszFilename,
+                                        char** papszOptions );
+    virtual CPLErr DeleteFeaturesLayer();
+    virtual CPLErr DeleteNetworkLayers();
+    virtual CPLErr LoadNetworkLayer(const char* pszLayername);
+    virtual bool CheckStorageDriverSupport(const char* pszDriverName);
+protected:
+    CPLErr FormPath(const char* pszFilename, char** papszOptions);
+protected:
+    CPLString m_soNetworkFullName;
+    GDALDataset* m_pMetadataDS;
+    GDALDataset* m_pGraphDS;
+    GDALDataset* m_pFeaturesDS;
+    std::map<OGRLayer*, GDALDataset*> m_mpLayerDatasetMap;
+};
diff --git a/gnm/gnm_frmts/file/gnmfiledriver.cpp b/gnm/gnm_frmts/file/gnmfiledriver.cpp
new file mode 100644
index 0000000..7c21dd3
--- /dev/null
+++ b/gnm/gnm_frmts/file/gnmfiledriver.cpp
@@ -0,0 +1,157 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
+ * Purpose:  GNM generic driver.
+ * Authors:  Mikhail Gusev (gusevmihs at gmail dot com)
+ *           Dmitry Baryshnikov, polimax at mail.ru
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Mikhail Gusev
+ * Copyright (c) 2014-2015, NextGIS <info at nextgis.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gnm_frmts.h"
+#include "gnmfile.h"
+
+static int GNMFileDriverIdentify( GDALOpenInfo* poOpenInfo )
+
+{
+    if( !poOpenInfo->bIsDirectory )
+        return FALSE;
+    if( (poOpenInfo->nOpenFlags & GDAL_OF_GNM) == 0 )
+        return FALSE;
+
+    char **papszFiles = VSIReadDir( poOpenInfo->pszFilename );
+    if( CSLCount(papszFiles) == 0 )
+    {
+        return FALSE;
+    }
+
+    bool bHasMeta(false), bHasGraph(false), bHasFeatures(false);
+
+    // search for base GNM files
+    for( int i = 0; papszFiles[i] != NULL; i++ )
+    {
+        if( EQUAL(papszFiles[i],".") || EQUAL(papszFiles[i],"..") )
+            continue;
+
+        if( EQUAL(CPLGetBasename(papszFiles[i]), GNM_SYSLAYER_META) )
+            bHasMeta = true;
+        else if( EQUAL(CPLGetBasename(papszFiles[i]), GNM_SYSLAYER_GRAPH) )
+            bHasGraph = true;
+        else if( EQUAL(CPLGetBasename(papszFiles[i]), GNM_SYSLAYER_FEATURES) )
+            bHasFeatures = true;
+
+        if(bHasMeta && bHasGraph && bHasFeatures)
+            break;
+    }
+
+    CSLDestroy( papszFiles );
+
+    return bHasMeta && bHasGraph && bHasFeatures;
+}
+
+static GDALDataset *GNMFileDriverOpen( GDALOpenInfo* poOpenInfo )
+
+{
+    if( !GNMFileDriverIdentify(poOpenInfo) )
+        return NULL;
+
+    GNMFileNetwork* poFN = new GNMFileNetwork();
+
+    if( poFN->Open( poOpenInfo ) != CE_None)
+    {
+        delete poFN;
+        poFN = NULL;
+    }
+
+    return poFN;
+}
+
+
+static GDALDataset *GNMFileDriverCreate( const char * pszName,
+                                        CPL_UNUSED int nBands,
+                                        CPL_UNUSED int nXSize,
+                                        CPL_UNUSED int nYSize,
+                                        CPL_UNUSED GDALDataType eDT,
+                                        char **papszOptions )
+{
+    CPLAssert( NULL != pszName );
+    CPLDebug( "GNM", "Attempt to create network at: %s", pszName );
+
+    GNMFileNetwork *poFN = new GNMFileNetwork();
+
+    if( poFN->Create( pszName, papszOptions ) != CE_None )
+    {
+        delete poFN;
+        poFN = NULL;
+    }
+
+    return poFN;
+}
+
+static CPLErr GNMFileDriverDelete( const char *pszDataSource )
+
+{
+    GDALOpenInfo oOpenInfo(pszDataSource, GA_Update);
+    GNMFileNetwork oFN;
+
+    if( oFN.Open( &oOpenInfo ) != CE_None)
+    {
+        return CE_Failure;
+    }
+
+    return oFN.Delete();
+}
+
+void RegisterGNMFile()
+{
+    if( GDALGetDriverByName( "GNMFile" ) == NULL )
+    {
+        GDALDriver  *poDriver = new GDALDriver();
+
+        poDriver->SetDescription( "GNMFile" );
+        poDriver->SetMetadataItem( GDAL_DCAP_GNM, "YES" );
+        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                                   "Geographic Network generic file based "
+                                   "model" );
+
+        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, CPLSPrintf(
+"<CreationOptionList>"
+"  <Option name='%s' type='string' description='The network name. Also it will be a folder name, so the limits for folder name distribute on network name'/>"
+"  <Option name='%s' type='string' description='The network description. Any text describes the network'/>"
+"  <Option name='%s' type='string' description='The network Spatial reference. All network features will reproject to this spatial reference. May be a WKT text or EPSG code'/>"
+"  <Option name='FORMAT' type='string' description='The OGR format to store network data.' default='%s'/>"
+"  <Option name='OVERWRITE' type='boolean' description='Overwrite exist network or not' default='NO'/>"
+"</CreationOptionList>", GNM_MD_NAME, GNM_MD_DESCR, GNM_MD_SRS,
+                                       GNM_MD_DEFAULT_FILE_FORMAT) );
+
+        poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+                                   "<LayerCreationOptionList/>" );
+        poDriver->pfnOpen = GNMFileDriverOpen;
+        poDriver->pfnIdentify = GNMFileDriverIdentify;
+        poDriver->pfnCreate = GNMFileDriverCreate;
+        poDriver->pfnDelete = GNMFileDriverDelete;
+
+        GetGDALDriverManager()->RegisterDriver( poDriver );
+    }
+}
diff --git a/gnm/gnm_frmts/file/gnmfilenetwork.cpp b/gnm/gnm_frmts/file/gnmfilenetwork.cpp
new file mode 100644
index 0000000..2f8af30
--- /dev/null
+++ b/gnm/gnm_frmts/file/gnmfilenetwork.cpp
@@ -0,0 +1,659 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
+ * Purpose:  GNM file based generic driver.
+ * Authors:  Mikhail Gusev (gusevmihs at gmail dot com)
+ *           Dmitry Baryshnikov, polimax at mail.ru
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Mikhail Gusev
+ * Copyright (c) 2014-2015, NextGIS <info at nextgis.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gnmfile.h"
+#include "gnm_priv.h"
+
+GNMFileNetwork::GNMFileNetwork() : GNMGenericNetwork()
+{
+    m_pMetadataDS = NULL;
+    m_pGraphDS = NULL;
+    m_pFeaturesDS = NULL;
+}
+
+GNMFileNetwork::~GNMFileNetwork()
+{
+    FlushCache();
+
+    GDALClose(m_pGraphDS);
+    GDALClose(m_pFeaturesDS);
+    GDALClose(m_pMetadataDS);
+}
+
+CPLErr GNMFileNetwork::Open(GDALOpenInfo *poOpenInfo)
+{
+    m_soNetworkFullName = poOpenInfo->pszFilename;
+    char **papszFiles = VSIReadDir( m_soNetworkFullName );
+    if( CSLCount(papszFiles) == 0 )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed, "Open '%s' file failed",
+                  m_soNetworkFullName.c_str() );
+        return CE_Failure;
+    }
+
+    // search for metadata file
+    CPLString soMetadatafile;
+    for( int i = 0; papszFiles[i] != NULL; i++ )
+    {
+        if( EQUAL(papszFiles[i],".") || EQUAL(papszFiles[i],"..") )
+            continue;
+
+        if( EQUAL(CPLGetBasename(papszFiles[i]), GNM_SYSLAYER_META) )
+        {
+            soMetadatafile = CPLFormFilename(m_soNetworkFullName, papszFiles[i],
+                                             NULL);
+            break;
+        }
+    }
+
+    CSLDestroy( papszFiles );
+
+    m_pMetadataDS = (GDALDataset*) GDALOpenEx( soMetadatafile, GDAL_OF_VECTOR |
+                                               GDAL_OF_UPDATE, NULL, NULL, NULL );
+    if( NULL == m_pMetadataDS )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed, "Open '%s' file failed",
+                  m_soNetworkFullName.c_str() );
+        return CE_Failure;
+    }
+
+    if(LoadMetadataLayer(m_pMetadataDS) != CE_None)
+    {
+        return CE_Failure;
+    }
+
+    m_poLayerDriver = m_pMetadataDS->GetDriver();
+    const char* pszExt = CPLGetExtension(soMetadatafile);
+
+    CPLString soGraphfile = CPLFormFilename(m_soNetworkFullName,
+                                            GNM_SYSLAYER_GRAPH, pszExt);
+    m_pGraphDS = (GDALDataset*) GDALOpenEx( soGraphfile, GDAL_OF_VECTOR |
+                                            GDAL_OF_UPDATE, NULL, NULL, NULL );
+    if( NULL == m_pGraphDS )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed, "Open '%s' file failed",
+                  m_soNetworkFullName.c_str() );
+        return CE_Failure;
+    }
+
+    if(LoadGraphLayer(m_pGraphDS) != CE_None)
+    {
+        return CE_Failure;
+    }
+
+    CPLString soFeaturesfile = CPLFormFilename(m_soNetworkFullName,
+                                            GNM_SYSLAYER_FEATURES, pszExt);
+    m_pFeaturesDS = (GDALDataset*) GDALOpenEx( soFeaturesfile, GDAL_OF_VECTOR |
+                                               GDAL_OF_UPDATE, NULL, NULL, NULL );
+    if( NULL == m_pFeaturesDS )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed, "Open '%s' file failed",
+                  m_soNetworkFullName.c_str() );
+        return CE_Failure;
+    }
+
+    if(LoadFeaturesLayer(m_pFeaturesDS) != CE_None)
+    {
+        return CE_Failure;
+    }
+
+    return CE_None;
+}
+
+int GNMFileNetwork::CheckNetworkExist(const char *pszFilename, char **papszOptions)
+{
+    // check if path exist
+    // if path exist check if network already present and OVERWRITE option
+    // else create the path
+
+    bool bOverwrite = CPL_TO_BOOL(CSLFetchBoolean(papszOptions, "OVERWRITE", FALSE));
+
+    if(m_soName.empty())
+    {
+        const char* pszNetworkName = CSLFetchNameValue(papszOptions, GNM_MD_NAME);
+
+        if( NULL != pszNetworkName )
+        {
+            m_soName = pszNetworkName;
+        }
+    }
+
+    if(FormPath(pszFilename, papszOptions) != CE_None)
+    {
+        return TRUE;
+    }
+
+    if (CPLCheckForFile((char*)m_soNetworkFullName.c_str(), NULL))
+    {
+        char **papszFiles = VSIReadDir( m_soNetworkFullName );
+        if( CSLCount(papszFiles) == 0 )
+        {
+            return FALSE;
+        }
+
+        // search for base GNM files
+        for(int i = 0; papszFiles[i] != NULL; i++ )
+        {
+            if( EQUAL(papszFiles[i],".") || EQUAL(papszFiles[i],"..") )
+                continue;
+
+            if( EQUAL(CPLGetBasename(papszFiles[i]), GNM_SYSLAYER_META) ||
+                EQUAL(CPLGetBasename(papszFiles[i]), GNM_SYSLAYER_GRAPH) ||
+                EQUAL(CPLGetBasename(papszFiles[i]), GNM_SYSLAYER_FEATURES) ||
+                EQUAL(papszFiles[i], GNM_SRSFILENAME) )
+            {
+                if(bOverwrite)
+                {
+                    const char* pszDeleteFile = CPLFormFilename(
+                                m_soNetworkFullName, papszFiles[i], NULL);
+                    CPLDebug("GNM", "Delete file: %s", pszDeleteFile);
+                    if( VSIUnlink(pszDeleteFile) != 0 )
+                    {
+                        return TRUE;
+                    }
+                }
+                else
+                {
+                    return TRUE;
+                }
+            }
+        }
+        CSLDestroy( papszFiles );
+    }
+    else
+    {
+        if (VSIMkdir(m_soNetworkFullName, 0755) != 0)
+        {
+            return TRUE;
+        }
+    }
+
+    return FALSE;
+}
+
+CPLErr GNMFileNetwork::Delete()
+{
+    CPLErr eResult = GNMGenericNetwork::Delete();
+    if(eResult != CE_None)
+       return eResult;
+
+    // check if folder empty
+    char **papszFiles = VSIReadDir( m_soNetworkFullName );
+    bool bIsEmpty = true;
+    for(int i = 0; papszFiles[i] != NULL; ++i)
+    {
+        if( !(EQUAL(papszFiles[i], "..") || EQUAL(papszFiles[i], ".")) )
+        {
+            bIsEmpty = false;
+            break;
+        }
+    }
+
+    CSLDestroy( papszFiles );
+
+    if( !bIsEmpty )
+    {
+        return eResult;
+    }
+    return VSIRmdir(m_soNetworkFullName) == 0 ? CE_None : CE_Failure;
+}
+
+CPLErr GNMFileNetwork::CreateMetadataLayerFromFile( const char* pszFilename, int nVersion,
+                                         char** papszOptions )
+{
+    CPLErr eResult = CheckLayerDriver(GNM_MD_DEFAULT_FILE_FORMAT, papszOptions);
+    if(CE_None != eResult)
+        return eResult;
+
+    eResult = FormPath(pszFilename, papszOptions);
+    if(CE_None != eResult)
+        return eResult;
+
+    const char* pszExt = m_poLayerDriver->GetMetadataItem(GDAL_DMD_EXTENSION);
+    CPLString osDSFileName = CPLFormFilename(m_soNetworkFullName,
+                                                GNM_SYSLAYER_META, pszExt);
+
+    m_pMetadataDS = m_poLayerDriver->Create(osDSFileName, 0, 0, 0, GDT_Unknown,
+                                            NULL );
+    if( NULL == m_pMetadataDS )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Creation of '%s' file failed",
+                  osDSFileName.c_str() );
+        return CE_Failure;
+    }
+
+    return GNMGenericNetwork::CreateMetadataLayer(m_pMetadataDS, nVersion, 254);
+}
+
+CPLErr GNMFileNetwork::StoreNetworkSrs()
+{
+    const char* pszSrsFileName = CPLFormFilename(m_soNetworkFullName,
+                                                 GNM_SRSFILENAME, NULL);
+    VSILFILE *fpSrsPrj = VSIFOpenL(pszSrsFileName, "w");
+    if (fpSrsPrj != NULL)
+    {
+        if(VSIFWriteL(m_soSRS, (int)m_soSRS.size(), 1, fpSrsPrj) != 1)
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "Write SRS failed, disk full?" );
+            VSIFCloseL(fpSrsPrj);
+            return CE_Failure;
+        }
+        VSIFCloseL(fpSrsPrj);
+    }
+    return CE_None;
+}
+
+CPLErr GNMFileNetwork::LoadNetworkSrs()
+{
+    const char* pszSrsFileName = CPLFormFilename(m_soNetworkFullName,
+                                                 GNM_SRSFILENAME, NULL);
+    char** papszLines = CSLLoad(pszSrsFileName);
+    if ( NULL == papszLines )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Loading of '%s' layer failed",
+                  GNM_SYSLAYER_META );
+        return CE_Failure;
+    }
+
+    m_soSRS = papszLines[0];
+
+    CSLDestroy( papszLines );
+
+    return CE_None;
+}
+
+CPLErr GNMFileNetwork::DeleteMetadataLayer()
+{
+    if(NULL != m_pMetadataDS)
+    {
+        const char* pszSrsFileName = CPLFormFilename(m_soNetworkFullName,
+                                                     GNM_SRSFILENAME, NULL);
+        VSIUnlink(pszSrsFileName); // just try to delete as file may not be existed
+        return m_pMetadataDS->DeleteLayer(0) == OGRERR_NONE ? CE_None : CE_Failure;
+    }
+    return CE_Failure;
+}
+
+CPLErr GNMFileNetwork::CreateGraphLayerFromFile( const char* pszFilename, char** papszOptions )
+{
+    CPLErr eResult = CheckLayerDriver(GNM_MD_DEFAULT_FILE_FORMAT, papszOptions);
+    if(CE_None != eResult)
+        return eResult;
+
+    eResult = FormPath(pszFilename, papszOptions);
+    if(CE_None != eResult)
+        return eResult;
+
+    const char* pszExt = m_poLayerDriver->GetMetadataItem(GDAL_DMD_EXTENSION);
+    CPLString osDSFileName = CPLFormFilename(m_soNetworkFullName,
+                                                GNM_SYSLAYER_GRAPH, pszExt);
+
+    m_pGraphDS = m_poLayerDriver->Create(osDSFileName, 0, 0, 0, GDT_Unknown,
+                                            NULL );
+
+    if( m_pGraphDS == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Creation of '%s' file failed",
+                  osDSFileName.c_str() );
+        return CE_Failure;
+    }
+
+    return GNMGenericNetwork::CreateGraphLayer(m_pGraphDS);
+}
+
+CPLErr GNMFileNetwork::DeleteGraphLayer()
+{
+    if(NULL != m_pGraphDS)
+    {
+        return m_pGraphDS->DeleteLayer(0) == OGRERR_NONE ? CE_None : CE_Failure;
+    }
+    return CE_Failure;
+}
+
+CPLErr GNMFileNetwork::CreateFeaturesLayerFromFile( const char* pszFilename, char** papszOptions )
+{
+    CPLErr eResult = CheckLayerDriver(GNM_MD_DEFAULT_FILE_FORMAT, papszOptions);
+    if(CE_None != eResult)
+        return eResult;
+
+    eResult = FormPath(pszFilename, papszOptions);
+    if(CE_None != eResult)
+        return eResult;
+
+    const char* pszExt = m_poLayerDriver->GetMetadataItem(GDAL_DMD_EXTENSION);
+    CPLString osDSFileName = CPLFormFilename(m_soNetworkFullName,
+                                                GNM_SYSLAYER_FEATURES, pszExt);
+
+    m_pFeaturesDS = m_poLayerDriver->Create(osDSFileName, 0, 0, 0, GDT_Unknown,
+                                            NULL );
+
+    if( m_pFeaturesDS == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Creation of '%s' file failed",
+                  osDSFileName.c_str() );
+        return CE_Failure;
+    }
+
+    return GNMGenericNetwork::CreateFeaturesLayer(m_pFeaturesDS);
+}
+
+CPLErr GNMFileNetwork::DeleteFeaturesLayer()
+{
+    if(NULL != m_pFeaturesDS)
+    {
+        return m_pFeaturesDS->DeleteLayer(0) == OGRERR_NONE ? CE_None : CE_Failure;
+    }
+    return CE_Failure;
+}
+
+CPLErr GNMFileNetwork::DeleteNetworkLayers()
+{
+    while(GetLayerCount() > 0)
+    {
+        OGRErr eErr = DeleteLayer(0);
+        if(eErr != OGRERR_NONE)
+            return CE_Failure;
+    }
+    return CE_None;
+}
+
+CPLErr GNMFileNetwork::LoadNetworkLayer(const char *pszLayername)
+{
+    // check if not loaded
+    for(size_t i = 0; i < m_apoLayers.size(); ++i)
+    {
+        if(EQUAL(m_apoLayers[i]->GetName(), pszLayername))
+            return CE_None;
+    }
+
+    const char* pszExt = m_poLayerDriver->GetMetadataItem(GDAL_DMD_EXTENSION);
+
+    CPLString soFile = CPLFormFilename(m_soNetworkFullName, pszLayername, pszExt);
+    GDALDataset *poDS = (GDALDataset*) GDALOpenEx( soFile, GDAL_OF_VECTOR |
+                                            GDAL_OF_UPDATE, NULL, NULL, NULL );
+    if( NULL == poDS )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed, "Open '%s' file failed",
+                  soFile.c_str() );
+        return CE_Failure;
+    }
+
+    OGRLayer* poLayer = poDS->GetLayer(0);
+    if(NULL == poLayer)
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed, "Layer '%s' is not exist",
+                  pszLayername );
+        return CE_Failure;
+    }
+
+    CPLDebug("GNM", "Layer '%s' loaded", poLayer->GetName());
+
+    GNMGenericLayer* pGNMLayer = new GNMGenericLayer(poLayer, this);
+    m_apoLayers.push_back(pGNMLayer);
+    m_mpLayerDatasetMap[pGNMLayer] = poDS;
+
+    return CE_None;
+}
+
+bool GNMFileNetwork::CheckStorageDriverSupport(const char *pszDriverName)
+{
+    if(EQUAL(pszDriverName, GNM_MD_DEFAULT_FILE_FORMAT))
+        return true;
+    //TODO: expand this list with supported OGR direvers
+    return false;
+}
+
+CPLErr GNMFileNetwork::FormPath(const char *pszFilename, char **papszOptions)
+{
+    if(m_soNetworkFullName.empty())
+    {
+        const char* pszNetworkName = CSLFetchNameValue(papszOptions, GNM_MD_NAME);
+        if(NULL == pszNetworkName)
+        {
+            CPLError( CE_Failure, CPLE_IllegalArg,
+                      "The network name should be present" );
+            return CE_Failure;
+        }
+        m_soNetworkFullName = CPLFormFilename(pszFilename, pszNetworkName, NULL);
+
+        CPLDebug( "GNM", "Network name: %s", m_soNetworkFullName.c_str() );
+    }
+    return CE_None;
+}
+
+int GNMFileNetwork::CloseDependentDatasets()
+{
+    size_t nCount = m_mpLayerDatasetMap.size();
+    for(std::map<OGRLayer*, GDALDataset*>::iterator
+        it = m_mpLayerDatasetMap.begin();
+        it != m_mpLayerDatasetMap.end(); ++it)
+    {
+        GDALClose(it->second);
+    }
+
+    m_mpLayerDatasetMap.clear();
+
+    GNMGenericNetwork::CloseDependentDatasets();
+
+    return nCount > 0 ? TRUE : FALSE;
+}
+
+OGRErr GNMFileNetwork::DeleteLayer(int nIndex)
+{
+    OGRLayer* pLayer = GetLayer(nIndex);
+
+    GDALDataset* poDS = m_mpLayerDatasetMap[pLayer];
+    if(NULL == poDS)
+    {
+        return OGRERR_FAILURE;
+    }
+
+    CPLDebug("GNM", "Delete network layer '%s'", pLayer->GetName());
+
+    if(poDS->DeleteLayer(0) != OGRERR_NONE)
+    {
+        return OGRERR_FAILURE;
+    }
+
+    GDALClose(poDS);
+
+    // remove pointer from map
+    m_mpLayerDatasetMap.erase(pLayer);
+
+    return GNMGenericNetwork::DeleteLayer(nIndex);
+}
+
+OGRLayer *GNMFileNetwork::ICreateLayer(const char *pszName,
+                                CPL_UNUSED OGRSpatialReference *poSpatialRef,
+                                OGRwkbGeometryType eGType, char **papszOptions)
+{
+    if(NULL == m_poLayerDriver)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "The network storage format driver is not defined." );
+        return NULL;
+    }
+
+    //check if layer with such name exist
+    for(int i = 0; i < GetLayerCount(); ++i)
+    {
+        OGRLayer* pLayer = GetLayer(i);
+        if(NULL == pLayer)
+            continue;
+        if(EQUAL(pLayer->GetName(), pszName))
+        {
+            CPLError( CE_Failure, CPLE_IllegalArg,
+                      "The network layer '%s' already exist.", pszName );
+            return NULL;
+        }
+    }
+
+    //form path
+    const char* pszExt = m_poLayerDriver->GetMetadataItem(GDAL_DMD_EXTENSION);
+    CPLString soPath = CPLFormFilename(m_soNetworkFullName, pszName ,pszExt);
+
+    GDALDataset *poDS = m_poLayerDriver->Create( soPath, 0, 0, 0, GDT_Unknown,
+                                                 papszOptions );
+    if( poDS == NULL )
+    {
+        CPLError( CE_Failure, CPLE_FileIO, "Creation of output file failed." );
+        return NULL;
+    }
+
+    OGRSpatialReference oSpaRef(m_soSRS);
+
+    OGRLayer *poLayer = poDS->CreateLayer( pszName, &oSpaRef, eGType, papszOptions );
+    if( poLayer == NULL )
+    {
+        CPLError( CE_Failure, CPLE_FileIO, "Layer creation failed." );
+        GDALClose(poDS);
+        return NULL;
+    }
+
+    OGRFieldDefn oField( GNM_SYSFIELD_GFID, GNMGFIDInt );
+    if( poLayer->CreateField( &oField ) != OGRERR_NONE )
+    {
+        CPLError( CE_Failure, CPLE_FileIO, "Creating global identificator field failed." );
+        GDALClose(poDS);
+        return NULL;
+    }
+
+
+    OGRFieldDefn oFieldBlock(GNM_SYSFIELD_BLOCKED, OFTInteger);
+    if( poLayer->CreateField( &oFieldBlock ) != OGRERR_NONE )
+    {
+        CPLError( CE_Failure, CPLE_FileIO, "Creating is blocking field failed." );
+        GDALClose(poDS);
+        return NULL;
+    }
+
+    GNMGenericLayer* pGNMLayer = new GNMGenericLayer(poLayer, this);
+    m_apoLayers.push_back(pGNMLayer);
+    m_mpLayerDatasetMap[pGNMLayer] = poDS;
+    return pGNMLayer;
+}
+
+CPLErr GNMFileNetwork::Create( const char* pszFilename, char** papszOptions )
+{
+    // check required options
+
+    // check name
+    const char* pszNetworkName = CSLFetchNameValue(papszOptions, GNM_MD_NAME);
+
+    if( NULL == pszNetworkName )
+    {
+        CPLError( CE_Failure, CPLE_IllegalArg,
+                  "The network name should be present" );
+        return CE_Failure;
+    }
+    else
+    {
+        m_soName = pszNetworkName;
+    }
+
+    const char* pszNetworkDescription = CSLFetchNameValue(papszOptions,
+                                                         GNM_MD_DESCR);
+    if(NULL != pszNetworkDescription)
+        sDescription = pszNetworkDescription;
+
+    // check Spatial reference
+    const char* pszSRS = CSLFetchNameValue(papszOptions, GNM_MD_SRS);
+    if( NULL == pszSRS )
+    {
+        CPLError( CE_Failure, CPLE_IllegalArg,
+                  "The network spatial reference should be present" );
+        return CE_Failure;
+    }
+    else
+    {
+        OGRSpatialReference spatialRef;
+        if (spatialRef.SetFromUserInput(pszSRS) != OGRERR_NONE)
+        {
+            CPLError( CE_Failure, CPLE_IllegalArg,
+                      "The network spatial reference should be present" );
+            return CE_Failure;
+        }
+
+        char *wktSrs = NULL;
+        if (spatialRef.exportToWkt(&wktSrs) != OGRERR_NONE)
+        {
+            CPLError( CE_Failure, CPLE_IllegalArg,
+                      "The network spatial reference should be present" );
+            return CE_Failure;
+        }
+        m_soSRS = wktSrs;
+
+        CPLFree(wktSrs);
+    }
+
+    int nResult = CheckNetworkExist(pszFilename, papszOptions);
+
+    if(TRUE == nResult)
+    {
+        CPLError( CE_Failure, CPLE_IllegalArg, "The network already exist" );
+        return CE_Failure;
+    }
+
+    // Create the necessary system layers and fields
+
+    // Create meta layer
+
+    CPLErr eResult = CreateMetadataLayerFromFile(pszFilename, GNM_VERSION_NUM, papszOptions);
+
+    if(CE_None != eResult)
+    {
+        //an error message should come from function
+        return CE_Failure;
+    }
+
+    // Create graph layer
+
+    eResult = CreateGraphLayerFromFile(pszFilename, papszOptions);
+
+    if(CE_None != eResult)
+    {
+        DeleteMetadataLayer();
+        return CE_Failure;
+    }
+
+    // Create features layer
+
+    eResult = CreateFeaturesLayerFromFile(pszFilename, papszOptions);
+
+    if(CE_None != eResult)
+    {
+        DeleteMetadataLayer();
+        DeleteGraphLayer();
+        return CE_Failure;
+    }
+
+    return CE_None;
+}
diff --git a/gnm/gnm_frmts/file/makefile.vc b/gnm/gnm_frmts/file/makefile.vc
new file mode 100755
index 0000000..6a97773
--- /dev/null
+++ b/gnm/gnm_frmts/file/makefile.vc
@@ -0,0 +1,16 @@
+
+OBJ	=	gnmfiledriver.obj gnmfilenetwork.obj
+
+
+GDAL_ROOT	=	..\..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+EXTRAFLAGS =	-I.. -I..\..
+
+default:	$(OBJ)
+	xcopy /D  /Y *.obj ..\o
+
+clean:
+	-del *.obj *.pdb
+
diff --git a/gnm/gnm_frmts/gnm_frmts.h b/gnm/gnm_frmts/gnm_frmts.h
new file mode 100644
index 0000000..ec942ea
--- /dev/null
+++ b/gnm/gnm_frmts/gnm_frmts.h
@@ -0,0 +1,49 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
+ * Purpose:  Classes related to format registration, and file opening.
+ * Authors:  Mikhail Gusev (gusevmihs at gmail dot com)
+ *           Dmitry Baryshnikov, polimax at mail.ru
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Mikhail Gusev
+ * Copyright (c) 2015, NextGIS <info at nextgis.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef GNM_FRMTS
+#define GNM_FRMTS
+
+#include "gdal_priv.h"
+
+/* -------------------------------------------------------------------- */
+/*      Various available registration methods.                         */
+/* -------------------------------------------------------------------- */
+CPL_C_START
+void CPL_DLL GNMRegisterAll();
+void GNMRegisterAllInternal();
+
+void CPL_DLL RegisterGNMFile();
+void CPL_DLL RegisterGNMDatabase();
+CPL_C_END
+
+#endif // GNM_FRMTS
+
diff --git a/gnm/gnm_frmts/gnmregisterall.cpp b/gnm/gnm_frmts/gnmregisterall.cpp
new file mode 100644
index 0000000..2d830a8
--- /dev/null
+++ b/gnm/gnm_frmts/gnmregisterall.cpp
@@ -0,0 +1,55 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
+ * Purpose:  Function to register all known OGR drivers.
+ * Authors:  Mikhail Gusev (gusevmihs at gmail dot com)
+ *           Dmitry Baryshnikov, polimax at mail.ru
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Mikhail Gusev
+ * Copyright (c) 2014-2015, NextGIS <info at nextgis.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gnm_frmts.h"
+
+CPL_CVSID("$Id$");
+
+void GNMRegisterAllInternal()
+{
+    CPLDebug("GNM", "GNMRegisterAllInternal");
+#ifdef GNMFILE_ENABLED
+    CPLDebug("GNM", "RegisterGNMFile");
+    RegisterGNMFile();
+#endif
+
+#ifdef GNMDB_ENABLED
+    CPLDebug("GNM", "RegisterGNMdatabase");
+    RegisterGNMDatabase();
+#endif
+
+//TODO:
+// * pgRouting driver
+// * OSRM driver
+// * GraphHopper driver
+// * ArcGIS geometric networks
+
+} /* GNMRegisterAll */
diff --git a/gnm/gnm_frmts/makefile.vc b/gnm/gnm_frmts/makefile.vc
new file mode 100755
index 0000000..a27179e
--- /dev/null
+++ b/gnm/gnm_frmts/makefile.vc
@@ -0,0 +1,32 @@
+GDAL_ROOT	=	..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+DIRLIST		=	file db
+
+!IFDEF INCLUDE_GNM_FRMTS
+
+EXTRAFLAGS	=	$(EXTRAFLAGS) -DGNMFILE_ENABLED -DGNMDB_ENABLED
+
+default:	o\gnmregisterall.obj subdirs
+
+subdirs:
+	for %d in ( $(DIRLIST) ) do \
+		cd %d \
+		&& $(MAKE) /f makefile.vc \
+		&& cd .. \
+		|| exit 1
+        
+o\gnmregisterall.obj:	gnmregisterall.cpp $(GDAL_ROOT)\nmake.opt
+	$(CC) $(CFLAGS) $(EXTRAFLAGS) /c gnmregisterall.cpp
+	copy gnmregisterall.obj o        
+    
+!ENDIF
+  
+clean:
+	-del o\*.obj *.obj
+	-for %d in ( $(DIRLIST) ) do \
+		cd %d \
+		&& $(MAKE) /f makefile.vc clean \
+		&& cd .. \
+		|| exit 1
diff --git a/gnm/gnm_frmts/o/README.TXT b/gnm/gnm_frmts/o/README.TXT
new file mode 100644
index 0000000..2058412
--- /dev/null
+++ b/gnm/gnm_frmts/o/README.TXT
@@ -0,0 +1,7 @@
+gdal/frmts/o
+------------
+
+This directory is where object files are put from the various format
+drivers so they can be easily linked into GDAL.  This file is here to
+ensure that the "o" directory isn't lost when people do a cvs checkout
+with pruning. 
diff --git a/gnm/gnm_priv.h b/gnm/gnm_priv.h
new file mode 100644
index 0000000..9b81e23
--- /dev/null
+++ b/gnm/gnm_priv.h
@@ -0,0 +1,101 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
+ * Purpose:  GNM private and internal declarations.
+ * Authors:  Mikhail Gusev (gusevmihs at gmail dot com)
+ *           Dmitry Baryshnikov, polimax at mail.ru
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Mikhail Gusev
+ * Copyright (c) 2014-2015, NextGIS <info at nextgis.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef GNM_PRIV
+#define GNM_PRIV
+
+#include "gdal_priv.h"
+
+/* -------------------------------------------------------------------- */
+/*              Common constants for internal use                       */
+/* -------------------------------------------------------------------- */
+
+// General constants.
+#define GNM_VERSION     "1.0"
+#define GNM_VERSION_NUM 100 //major * 100 + minor
+
+// Obligatory system layers.
+#define GNM_SYSLAYER_META       "_gnm_meta"
+#define GNM_SYSLAYER_GRAPH      "_gnm_graph"
+#define GNM_SYSLAYER_FEATURES   "_gnm_features"
+
+// System field names.
+// FORMAT NOTE: Shapefile driver does not support field names more than 10
+//              characters.
+
+#define GNM_SYSFIELD_PARAMNAME  "key"
+#define GNM_SYSFIELD_PARAMVALUE "val"
+#define GNM_SYSFIELD_SOURCE     "source"
+#define GNM_SYSFIELD_TARGET     "target"
+#define GNM_SYSFIELD_CONNECTOR  "connector"
+#define GNM_SYSFIELD_COST       "cost"
+#define GNM_SYSFIELD_INVCOST    "inv_cost"
+#define GNM_SYSFIELD_DIRECTION  "direction"
+#define GNM_SYSFIELD_GFID       "gnm_fid"
+#define GNM_SYSFIELD_LAYERNAME  "ogrlayer"
+#define GNM_SYSFIELD_BLOCKED    "blocked"
+#define GNM_SYSFIELD_PATHNUM    "path_num"
+#define GNM_SYSFIELD_TYPE       "ftype"
+
+// Rule strings key-words.
+#define GNM_RULEKW_CONNECTS "CONNECTS"
+#define GNM_RULEKW_WITH "WITH"
+#define GNM_RULEKW_VIA "VIA"
+#define GNM_RULEKW_ALLOW "ALLOW"
+#define GNM_RULEKW_DENY "DENY"
+#define GNM_RULEKW_ANY "ANY"
+
+// Graph constants
+#define GNM_EDGE_DIR_BOTH       0   // bidirectional
+#define GNM_EDGE_DIR_SRCTOTGT   1   // from source to target
+#define GNM_EDGE_DIR_TGTTOSRC   2   // from target to source
+
+#define GNM_BLOCK_NONE 0x0000  // no blocking (vertex or edge)
+#define GNM_BLOCK_SRC  0x0001  // the source vertex is blocked
+#define GNM_BLOCK_TGT  0x0002  // the target vertext is blocked
+#define GNM_BLOCK_CONN 0x0004  // the connection edge is blocked
+#define GNM_BLOCK_ALL GNM_BLOCK_SRC | GNM_BLOCK_TGT | GNM_BLOCK_CONN
+
+
+// Other string constants.
+#define GNM_SRSFILENAME "_gnm_srs.prj"
+
+// Alias for some big data type to store identificators.
+#define GNMGFID GIntBig
+// Corespondent datatype for identificator
+// (i.e. int -> OFTInteger -> GetFieldAsInteger and
+//       GUIntBig -> OFTInteger64 -> GetFieldAsInteger64)
+#define GNMGFIDInt OFTInteger64
+#define GetFieldAsGNMGFID GetFieldAsInteger64
+#define GNMGFIDFormat CPL_FRMT_GIB
+
+#endif // GNM_PRIV
+
diff --git a/gnm/gnm_tut.dox b/gnm/gnm_tut.dox
new file mode 100644
index 0000000..766ed9c
--- /dev/null
+++ b/gnm/gnm_tut.dox
@@ -0,0 +1,337 @@
+/*! \page gnm_tut GNM Tutorial
+
+This document is intended to describe using the GNM C++ classes to work with networks. It is  advised to read the <a href="gnm_arch.html">GNM architecture</a> before to understand the purpose and structure of GNM classes.
+
+\section gnm_tut_manage Managing networks
+
+In the first example we will create a small water network on the base of the set of spatial data (two shapefiles: pipes and wells which are situated at the GDAL source tree: autotest\gnm\data). The use of the common network format - GNMGdalNetwork class - will allow us to select one of the GDAL-supported vector formats for our network - ESRI Shapefile. After the creation we will build a topology and add some additional data: pumps layer, in order to manually edit network topology.
+
+Initially we register GDAL drivers and create some options (string pairs), which will be passed as parameters during network creation. Here we create a network's name.
+
+\code
+#include "gnm.h"
+#include <vector>
+
+int main ()
+{
+    GDALAllRegister();
+
+    char **papszDSCO = NULL;
+    papszDSCO = CSLAddNameValue(papszDSCO, GNM_MD_NAME, "my_pipes_network");
+    papszDSCO = CSLAddNameValue(papszDSCO, GNM_MD_SRS, "EPSG:4326");
+    papszDSCO = CSLAddNameValue(papszDSCO, GNM_MD_DESCR, "My pipes network");
+    papszDSCO = CSLAddNameValue(papszDSCO, GNM_MD_FORMAT, "ESRI Shapefile");
+
+\endcode
+    
+Some options are obligatory. The following parameters must be specified during the network creation: the path/name; format of network storage; spatial reference system (EPSG, WKT, etc.). The according dataset with the "network part" will be created and the resulting network will be returned.
+
+\code
+    GDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName("GNMFile");
+    GNMGenericNetwork* poDS = (GNMGenericNetwork*) poDriver->Create( "..\\network_data", 0, 0, 0, GDT_Unknown,
+                                                       papszDSCO );    
+    CSLDestroy(papszDSCO);
+\endcode
+
+For now we have a void network consisted of only "system layers". We need to populate it with "class layers" full of features, so we open a certain foreign dataset and copy layers from it to our network. Note, that we use GDALDataset:: methods for working with "class layers", because GNMNetwork inherited from GDALDataset. 
+
+\code
+    GDALDataset *poSrcDS = (GDALDataset*) GDALOpenEx("..\\in_data",
+                                    GDAL_OF_VECTOR | GDAL_OF_READONLY, NULL, NULL, NULL );
+                                    
+    OGRLayer *poSrcLayer1 = poSrcDS->GetLayerByName("pipes");
+    OGRLayer *poSrcLayer2 = poSrcDS->GetLayerByName("wells");
+
+    poDS->CopyLayer(poSrcLayer1, "pipes");
+    poDS->CopyLayer(poSrcLayer2, "wells");
+
+    GDALClose(poSrcDS);
+\endcode
+
+After the successful copying we have the network full of features, but with no topology. The features were added and registered in the network but they are still not connected with each other. Now it is time to build the network topology. There are two ways of doing this in GNM: manually or automatically. In the most cases automatic building is more convenient, while manual is useful for small editings. Automatic building requires some parameters: we must specify which "class layers" wil [...]
+
+\code
+    printf("\nBuilding network topology ...\n");
+    char **papszLayers = NULL;
+    for(int i = 0; i < poDS->GetLayerCount(); ++i)
+    {
+        OGRLayer* poLayer = poDS->GetLayer(i);
+        papszLayers = CSLAddString(papszLayers, poLayer->GetName() );
+    }
+    
+    if(poGenericNetwork->ConnectPointsByLines(papszLayers, dfTolerance,
+                                        dfDirCost, dfInvCost, eDir) != CE_None )
+    {
+        printf("Building topology failed\n");
+    }
+    else
+    {
+        printf("Topology has been built successfully\n");
+    }
+
+\endcode
+
+At this point we have a ready network with topological and spatial data, which can be used now for different purposes (analysis, converting into different formats, etc). But sometimes it is necessary to modify some network's data. For example we need to add additional features and attach them to our built topology (modify topology). We create a new "class layer" in the network and add one feature to it.
+
+\code
+     
+    OGRLayer *poNewLayer = poDS->CreateLayer("pumps", , NULL, wkbPoint, NULL );
+    if( poNewLayer == NULL )
+    {
+        printf( "Layer creation failed.\n" );
+        exit( 1 );
+    }
+    
+    OGRFieldDefn fieldDefn ("pressure",OFTReal);
+    if( poNewLayer->CreateField( &fieldDefn ) != OGRERR_NONE )
+    {
+        printf( "Creating Name field failed.\n" );
+        exit( 1 );
+    }
+        
+    OGRFeature *poFeature = OGRFeature::CreateFeature(poNewLayer->GetLayerDefn());
+    OGRPoint pt;
+    pt.setX(37.291466);
+    pt.setY(55.828351);
+    poFeature->SetGeometry(&pt);
+    if( poNewLayer->CreateFeature( poFeature ) != OGRERR_NONE )
+    {
+        printf( "Failed to create feature.\n" );
+        exit( 1 );
+    }
+    
+    GNMGFID gfid = poFeature->GetFID();
+
+    OGRFeature::DestroyFeature( poFeature );   
+\endcode
+
+After the successful creation the feature will be registered in the network and we can connect it with others. There can be two possible ways to do this. In the first case we need a real feature which will be an edge in the connection, while in the second case we do not need such feature, and passing -1 into the ConnectFeatures() method means that the special system edge will be created for this connection and added to the graph automatically. In our case we had added only one point feat [...]
+
+\code
+    if (poDS->ConnectFeatures(gfid ,63, -1, 5.0, 5.0, GNMDirection_SrcToTgt) != GNMError_None)
+    {
+        printf("Can not connect features\n");
+    }
+\endcode
+
+After all we correctly close the network which frees the allocated resources.
+
+\code
+    GDALClose(poDS);
+\endcode
+
+All in one block:
+
+\code
+#include "gnm.h"
+#include "gnm_priv.h"
+
+int main ()
+{
+    GDALAllRegister();
+
+    char **papszDSCO = NULL;
+    papszDSCO = CSLAddNameValue(papszDSCO, GNM_MD_NAME, "my_pipes_network");
+    papszDSCO = CSLAddNameValue(papszDSCO, GNM_MD_SRS, "EPSG:4326");
+    papszDSCO = CSLAddNameValue(papszDSCO, GNM_MD_DESCR, "My pipes network");
+    papszDSCO = CSLAddNameValue(papszDSCO, GNM_MD_FORMAT, "ESRI Shapefile");
+    
+    
+    GDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName("GNMFile");
+    GNMGenericNetwork* poDS = (GNMGenericNetwork*) poDriver->Create( "..\\network_data", 0, 0, 0, GDT_Unknown,
+                                                       papszDSCO );    
+    CSLDestroy(papszDSCO);
+    if (poDS == NULL)
+    {
+        printf("Failed to create network\n");
+        exit(1);
+    }
+
+    GDALDataset *poSrcDS = (GDALDataset*) GDALOpenEx("..\\in_data",GDAL_OF_VECTOR | GDAL_OF_READONLY, NULL, NULL, NULL );
+    if(poSrcDS == NULL)
+    {
+        printf("Can not open source dataset at\n");
+        exit(1);
+    }
+
+    OGRLayer *poSrcLayer1 = poSrcDS->GetLayerByName("pipes");
+    OGRLayer *poSrcLayer2 = poSrcDS->GetLayerByName("wells");
+    if (poSrcLayer1 == NULL || poSrcLayer2 == NULL)
+    {
+        printf("Can not process layers of source dataset\n");
+        exit(1);
+    }
+
+    poDS->CopyLayer(poSrcLayer1, "pipes");
+    poDS->CopyLayer(poSrcLayer2, "wells");
+
+    GDALClose(poSrcDS);
+
+    printf("\nBuilding network topology ...\n");
+    char **papszLayers = NULL;
+    for(int i = 0; i < poDS->GetLayerCount(); ++i)
+    {
+        OGRLayer* poLayer = poDS->GetLayer(i);
+        papszLayers = CSLAddString(papszLayers, poLayer->GetName() );
+    }
+    
+    if(poGenericNetwork->ConnectPointsByLines(papszLayers, dfTolerance,
+                                        dfDirCost, dfInvCost, eDir) != CE_None )
+    {
+        printf("Building topology failed\n");
+        exit(1);
+    }
+    else
+    {
+        printf("Topology has been built successfully\n");
+    }
+
+    OGRLayer *poNewLayer = poDS->CreateLayer("pumps", , NULL, wkbPoint, NULL );
+    if( poNewLayer == NULL )
+    {
+        printf( "Layer creation failed.\n" );
+        exit( 1 );
+    }
+    
+    OGRFieldDefn fieldDefn ("pressure",OFTReal);
+    if( poNewLayer->CreateField( &fieldDefn ) != OGRERR_NONE )
+    {
+        printf( "Creating Name field failed.\n" );
+        exit( 1 );
+    }
+        
+    OGRFeature *poFeature = OGRFeature::CreateFeature(poNewLayer->GetLayerDefn());
+    OGRPoint pt;
+    pt.setX(37.291466);
+    pt.setY(55.828351);
+    poFeature->SetGeometry(&pt);
+    if( poNewLayer->CreateFeature( poFeature ) != OGRERR_NONE )
+    {
+        printf( "Failed to create feature.\n" );
+        exit( 1 );
+    }
+    
+    GNMGFID gfid = poFeature->GetFID();
+
+    OGRFeature::DestroyFeature( poFeature );    
+
+    if (poDS->ConnectFeatures(gfid ,63, -1, 5.0, 5.0, GNMDirection_SrcToTgt) != GNMError_None)
+    {
+        printf("Can not connect features\n");
+    }
+
+    GDALClose(poDS);
+}
+\endcode
+
+\section gnm_tut_analyse Analysing networks
+
+In the second example we will analyse the network which we have built in the first example. We will calculate the shortest path between two points via Dijkstra algorithm performing the feature blockings and saving the resulting path into the file.
+
+Initially we open our network, passing the path to its Shapefile dataset.
+
+\code
+#include "gnm.h"
+#include "gnm_priv.h"
+
+int main ()
+{
+    GDALAllRegister();
+
+    GNMGenericNetwork *poNet = (GNMGenericNetwork*) GDALOpenEx("..\\network_data",GDAL_OF_GNM | GDAL_OF_UPDATE, NULL, NULL, NULL );
+    if(poSrcDS == NULL)
+    {
+        printf("Can not open source dataset at\n");
+        exit(1);
+    }
+\endcode
+
+Before any calculations we open the dataset which will hold the layer with the resulting path. 
+
+\code
+    GDALDataset *poResDS;
+    poResDS = (GDALDataset*) GDALOpenEx("..\\out_data",
+                                        GDAL_OF_VECTOR | GDAL_OF_UPDATE,
+                                        NULL, NULL, NULL);
+    if (poResDS == NULL)
+    {
+        printf("Failed to open resulting dataset\n");
+        exit(1);
+    }
+\endcode
+
+Finally we use the Dijkstra shortest path method to calculations. This path will be found passing over the blocked feature and saved into internal memory OGRLayer, which we copy to the real dataset. Now it can be visualized by GIS.
+
+\code
+    OGRLayer *poResLayer = poNet->GetPath(64, 41, GATDijkstraShortestPath, NULL);
+    if (poResLayer == NULL)
+    {
+        printf("Failed to save or calculate path\n");
+    }
+    else if (poResDS->CopyLayer(poResLayer, "shp_tutorial.shp") == NULL)
+    {
+        printf("Failed to save path to the layer\n");
+    }
+    else
+    {
+        printf("Path saved successfully\n");
+    }
+
+    GDALClose(poResDS);
+    poNet->ReleaseResultSet(poRout);
+    GDALClose(poNet);
+}
+\endcode
+
+All in one block:
+
+\code
+#include "gnm.h"
+#include "gnmstdanalysis.h"
+
+int main ()
+{
+    GDALAllRegister();
+
+    GNMGenericNetwork *poNet = (GNMGenericNetwork*) GDALOpenEx("..\\network_data",
+                                                     GDAL_OF_GNM | GDAL_OF_UPDATE, 
+                                                     NULL, NULL, NULL );
+    if(poSrcDS == NULL)
+    {
+        printf("Can not open source dataset at\n");
+        exit(1);
+    }
+    
+    GDALDataset *poResDS;
+    poResDS = (GDALDataset*) GDALOpenEx("..\\out_data",
+                                        GDAL_OF_VECTOR | GDAL_OF_UPDATE,
+                                        NULL, NULL, NULL);
+    if (poResDS == NULL)
+    {
+        printf("Failed to open resulting dataset\n");
+        exit(1);
+    }
+
+    poNet->ChangeBlockState(36, true);
+
+    OGRLayer *poResLayer = poNet->GetPath(64, 41, GATDijkstraShortestPath, NULL);
+    if (poResLayer == NULL)
+    {
+        printf("Failed to save or calculate path\n");
+    }
+    else if (poResDS->CopyLayer(poResLayer, "shp_tutorial.shp") == NULL)
+    {
+        printf("Failed to save path to the layer\n");
+    }
+    else
+    {
+        printf("Path saved successfully\n");
+    }
+
+    GDALClose(poResDS);
+    poNet->ReleaseResultSet(poRout);
+    GDALClose(poNet);
+}
+\endcode
+
+*/
diff --git a/gnm/gnmgenericnetwork.cpp b/gnm/gnmgenericnetwork.cpp
new file mode 100644
index 0000000..8864f7e
--- /dev/null
+++ b/gnm/gnmgenericnetwork.cpp
@@ -0,0 +1,1526 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
+ * Purpose:  GNM network class.
+ * Authors:  Mikhail Gusev (gusevmihs at gmail dot com)
+ *           Dmitry Baryshnikov, polimax at mail.ru
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Mikhail Gusev
+ * Copyright (c) 2014-2015, NextGIS <info at nextgis.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gnm_api.h"
+#include "ogrsf_frmts.h"
+
+#include <set>
+
+GNMGenericNetwork::GNMGenericNetwork() :
+    GNMNetwork(),
+    m_nVersion(0),
+    m_nGID(0),
+    m_nVirtualConnectionGID(-1),
+    m_poMetadataLayer(NULL),
+    m_poGraphLayer(NULL),
+    m_poFeaturesLayer(NULL),
+    m_poLayerDriver(NULL),
+    m_bIsRulesChanged(false),
+    m_bIsGraphLoaded(false)
+{
+}
+
+GNMGenericNetwork::~GNMGenericNetwork()
+{
+    for(size_t i = 0; i < m_apoLayers.size(); i++)
+        delete m_apoLayers[i];
+}
+
+int GNMGenericNetwork::GetLayerCount()
+{
+    return (int)m_apoLayers.size();
+}
+
+OGRLayer *GNMGenericNetwork::GetLayer(int nIndex)
+{
+    if(nIndex < 0 || nIndex >= (int)m_apoLayers.size())
+        return NULL;
+    return m_apoLayers[nIndex];
+}
+
+OGRErr GNMGenericNetwork::DeleteLayer(int nIndex)
+{
+    if(nIndex < 0 || nIndex >= (int)m_apoLayers.size())
+        return OGRERR_FAILURE;
+
+    const char* pszLayerName = m_apoLayers[nIndex]->GetName();
+    OGRFeature *poFeature;
+
+    std::set<GNMGFID> anGFIDs;
+    std::set<GNMGFID>::iterator it;
+    // remove layer GFID's from Features layer
+
+    m_poFeaturesLayer->ResetReading();
+    while ((poFeature = m_poFeaturesLayer->GetNextFeature()) != NULL)
+    {
+        const char *pFeatureClass = poFeature->GetFieldAsString(
+                    GNM_SYSFIELD_LAYERNAME);
+
+        if(EQUAL(pFeatureClass, pszLayerName))
+        {
+            anGFIDs.insert(poFeature->GetFieldAsGNMGFID(GNM_SYSFIELD_GFID));
+            CPL_IGNORE_RET_VAL(m_poFeaturesLayer->DeleteFeature(poFeature->GetFID()));
+        }
+        OGRFeature::DestroyFeature(poFeature);
+    }
+
+    // remove GFID's from graph layer
+
+    m_poGraphLayer->ResetReading();
+    while ((poFeature = m_poGraphLayer->GetNextFeature()) != NULL)
+    {
+        GNMGFID nGFID = poFeature->GetFieldAsGNMGFID(GNM_SYSFIELD_SOURCE);
+        it = anGFIDs.find(nGFID);
+        if( it != anGFIDs.end())
+        {
+            CPL_IGNORE_RET_VAL(m_poGraphLayer->DeleteFeature(poFeature->GetFID()));
+            OGRFeature::DestroyFeature(poFeature);
+            continue;
+        }
+
+        nGFID = poFeature->GetFieldAsGNMGFID(GNM_SYSFIELD_TARGET);
+        it = anGFIDs.find(nGFID);
+        if( it != anGFIDs.end())
+        {
+            CPL_IGNORE_RET_VAL(m_poGraphLayer->DeleteFeature(poFeature->GetFID()));
+            OGRFeature::DestroyFeature(poFeature);
+            continue;
+        }
+
+        nGFID = poFeature->GetFieldAsGNMGFID(GNM_SYSFIELD_CONNECTOR);
+        it = anGFIDs.find(nGFID);
+        if( it != anGFIDs.end())
+        {
+            CPL_IGNORE_RET_VAL(m_poGraphLayer->DeleteFeature(poFeature->GetFID()));
+            OGRFeature::DestroyFeature(poFeature);
+            continue;
+        }
+
+        OGRFeature::DestroyFeature(poFeature);
+    }
+
+    // remove connected rules
+    for(size_t i = m_asRules.size(); i > 0; --i)
+    {
+        if(EQUAL(m_asRules[i - 1].GetSourceLayerName(), pszLayerName))
+        {
+            m_asRules.erase(m_asRules.begin() + i - 1);
+            m_bIsRulesChanged = true;
+        }
+        else if(EQUAL(m_asRules[i - 1].GetTargetLayerName(), pszLayerName))
+        {
+            m_asRules.erase(m_asRules.begin() + i - 1);
+            m_bIsRulesChanged = true;
+        }
+        else if(EQUAL(m_asRules[i - 1].GetConnectorLayerName(), pszLayerName))
+        {
+            m_asRules.erase(m_asRules.begin() + i - 1);
+            m_bIsRulesChanged = true;
+        }
+    }
+
+    delete m_apoLayers[nIndex];
+    // remove from array
+    m_apoLayers.erase (m_apoLayers.begin() + nIndex);
+    return OGRERR_NONE;
+}
+
+CPLErr GNMGenericNetwork::Delete()
+{
+    CPLErr eResult = DeleteNetworkLayers();
+    if(eResult != CE_None)
+        return eResult;
+    eResult = DeleteMetadataLayer();
+    if(eResult != CE_None)
+        return eResult;
+    eResult = DeleteGraphLayer();
+    if(eResult != CE_None)
+        return eResult;
+
+    return DeleteFeaturesLayer();
+}
+
+int GNMGenericNetwork::GetVersion() const
+{
+    return m_nVersion;
+}
+
+GIntBig GNMGenericNetwork::GetNewGlobalFID()
+{
+    return m_nGID++;
+}
+
+CPLString GNMGenericNetwork::GetAlgorithmName(GNMDirection eAlgorithm,
+                                              bool bShortName)
+{
+    switch(eAlgorithm)
+    {
+    case GATDijkstraShortestPath:
+        if(bShortName)
+            return CPLString("Dijkstra");
+        else
+            return CPLString("Dijkstra shortest path");
+    case GATKShortestPath:
+        if(bShortName)
+            return CPLString("Yens");
+        else
+            return CPLString("Yens shortest paths");
+    case GATConnectedComponents:
+        if(bShortName)
+            return CPLString("Connected");
+        else
+            return CPLString("Connected components");
+    }
+
+    return CPLString("Invalid");
+}
+
+CPLErr GNMGenericNetwork::AddFeatureGlobalFID(GNMGFID nFID,
+                                              const char *pszLayerName)
+{
+    OGRFeature *poFeature = OGRFeature::CreateFeature(
+                m_poFeaturesLayer->GetLayerDefn() );
+    poFeature->SetField( GNM_SYSFIELD_GFID, nFID );
+    poFeature->SetField( GNM_SYSFIELD_LAYERNAME, pszLayerName );
+
+    if( m_poFeaturesLayer->CreateFeature( poFeature ) != OGRERR_NONE )
+    {
+        OGRFeature::DestroyFeature( poFeature );
+        CPLError( CE_Failure, CPLE_AppDefined, "Failed to create feature." );
+        return CE_Failure;
+    }
+
+    OGRFeature::DestroyFeature( poFeature );
+
+    return CE_None;
+}
+
+CPLErr GNMGenericNetwork::ConnectFeatures(GNMGFID nSrcGFID, GNMGFID nTgtGFID,
+                                          GNMGFID nConGFID, double dfCost,
+                                          double dfInvCost, GNMDirection eDir)
+{
+    if(!m_bIsGraphLoaded && LoadGraph() != CE_None)
+    {
+        return CE_Failure;
+    }
+
+    OGRFeature *poFeature = FindConnection(nSrcGFID, nTgtGFID, nConGFID);
+    if(poFeature != NULL)
+    {
+        OGRFeature::DestroyFeature( poFeature );
+        CPLError( CE_Failure, CPLE_AppDefined, "The connection already created" );
+        return CE_Failure;
+    }
+
+    if(m_asRules.empty())
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "The connection forbidden" );
+        return CE_Failure;
+    }
+    else
+    {
+        CPLString soSrcLayerName = m_moFeatureFIDMap[nSrcGFID];
+        CPLString soTgtLayerName = m_moFeatureFIDMap[nTgtGFID];
+        CPLString soConnLayerName = m_moFeatureFIDMap[nConGFID];
+        for(size_t i = 0; i < m_asRules.size(); ++i)
+        {
+            if(!m_asRules[i].CanConnect(soSrcLayerName, soTgtLayerName,
+                                        soConnLayerName))
+            {
+                CPLError( CE_Failure, CPLE_AppDefined, "The connection forbidden" );
+                return CE_Failure;
+            }
+        }
+    }
+
+    // we support both vertices and edge to be virtual
+    if(nConGFID == -1)
+       nConGFID = GetNewVirtualFID();
+    if(nSrcGFID == -1)
+       nSrcGFID = GetNewVirtualFID();
+    if(nTgtGFID == -1)
+       nTgtGFID = GetNewVirtualFID();
+
+    poFeature = OGRFeature::CreateFeature( m_poGraphLayer->GetLayerDefn() );
+    poFeature->SetField( GNM_SYSFIELD_SOURCE, nSrcGFID );
+    poFeature->SetField( GNM_SYSFIELD_TARGET, nTgtGFID );
+    poFeature->SetField( GNM_SYSFIELD_CONNECTOR, nConGFID );
+    poFeature->SetField( GNM_SYSFIELD_COST, dfCost );
+    poFeature->SetField( GNM_SYSFIELD_INVCOST, dfInvCost );
+    poFeature->SetField( GNM_SYSFIELD_DIRECTION, eDir );
+    poFeature->SetField( GNM_SYSFIELD_BLOCKED, GNM_BLOCK_NONE );
+
+    if( m_poGraphLayer->CreateFeature( poFeature ) != OGRERR_NONE )
+    {
+        OGRFeature::DestroyFeature( poFeature );
+        CPLError( CE_Failure, CPLE_AppDefined, "Failed to create feature." );
+        return CE_Failure;
+    }
+
+    OGRFeature::DestroyFeature( poFeature );
+
+    // update graph
+
+    m_oGraph.AddEdge(nConGFID, nSrcGFID, nTgtGFID, eDir == GNM_EDGE_DIR_BOTH,
+                     dfCost, dfInvCost);
+
+    return CE_None;
+}
+
+CPLErr GNMGenericNetwork::DisconnectFeatures(GNMGFID nSrcGFID, GNMGFID nTgtGFID,
+                                             GNMGFID nConGFID)
+{
+    if(!m_bIsGraphLoaded && LoadGraph() != CE_None)
+    {
+        return CE_Failure;
+    }
+
+    OGRFeature *poFeature = FindConnection(nSrcGFID, nTgtGFID, nConGFID);
+    if (poFeature == NULL)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "The connection not exist" );
+        return CE_Failure;
+    }
+
+    if (m_poGraphLayer->DeleteFeature(poFeature->GetFID()) != OGRERR_NONE)
+    {
+        OGRFeature::DestroyFeature(poFeature);
+        return CE_Failure;
+    }
+
+    OGRFeature::DestroyFeature(poFeature);
+
+    // update graph
+
+    m_oGraph.DeleteEdge(nConGFID);
+
+    return CE_None;
+}
+
+CPLErr GNMGenericNetwork::DisconnectFeaturesWithId(GNMGFID nFID)
+{
+    if(!m_bIsGraphLoaded && LoadGraph() != CE_None)
+    {
+        return CE_Failure;
+    }
+
+    CPLString soFilter;
+    soFilter.Printf("%s = " GNMGFIDFormat " or %s = " GNMGFIDFormat " or %s = " GNMGFIDFormat,
+                    GNM_SYSFIELD_SOURCE, nFID,
+                    GNM_SYSFIELD_TARGET, nFID,
+                    GNM_SYSFIELD_CONNECTOR, nFID);
+
+    CPLDebug("GNM", "Set attribute filter: %s", soFilter.c_str());
+
+    m_poGraphLayer->SetAttributeFilter(soFilter);
+    m_poGraphLayer->ResetReading();
+    OGRFeature* poFeature;
+    while ((poFeature = m_poGraphLayer->GetNextFeature()) != NULL)
+    {
+        if(m_poGraphLayer->DeleteFeature(poFeature->GetFID()) != CE_None)
+        {
+            OGRFeature::DestroyFeature( poFeature );
+            CPLError( CE_Failure, CPLE_AppDefined,
+                                       "Failed to remove feature connection." );
+            return CE_Failure;
+        }
+        OGRFeature::DestroyFeature( poFeature );
+    }
+
+    m_poGraphLayer->SetAttributeFilter(NULL);
+
+    m_oGraph.DeleteEdge(nFID);
+    m_oGraph.DeleteVertex(nFID);
+
+    return CE_None;
+}
+
+CPLErr GNMGenericNetwork::ReconnectFeatures(GNMGFID nSrcGFID, GNMGFID nTgtGFID,
+                                            GNMGFID nConGFID, double dfCost,
+                                            double dfInvCost, GNMDirection eDir)
+{
+    if(!m_bIsGraphLoaded && LoadGraph() != CE_None)
+    {
+        return CE_Failure;
+    }
+
+    OGRFeature *poFeature = FindConnection(nSrcGFID, nTgtGFID, nConGFID);
+    if (poFeature == NULL)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "The connection not exist" );
+        return CE_Failure;
+    }
+
+    poFeature->SetField( GNM_SYSFIELD_COST, dfCost );
+    poFeature->SetField( GNM_SYSFIELD_INVCOST, dfInvCost );
+    poFeature->SetField( GNM_SYSFIELD_DIRECTION, eDir );
+
+    if( m_poGraphLayer->SetFeature( poFeature ) != OGRERR_NONE )
+    {
+        OGRFeature::DestroyFeature( poFeature );
+        CPLError( CE_Failure, CPLE_AppDefined, "Failed to update feature." );
+        return CE_Failure;
+    }
+
+    OGRFeature::DestroyFeature( poFeature );
+
+    // update graph
+
+    m_oGraph.ChangeEdge(nConGFID, dfCost, dfInvCost);
+
+    return CE_None;
+}
+
+CPLErr GNMGenericNetwork::DisconnectAll()
+{
+    if(!m_bIsGraphLoaded && LoadGraph() != CE_None)
+    {
+        return CE_Failure;
+    }
+    // delete everything from m_pGraphLayer
+
+    OGRFeature *poFeature;
+    m_poGraphLayer->ResetReading();
+    while ((poFeature = m_poGraphLayer->GetNextFeature()) != NULL)
+    {
+        CPL_IGNORE_RET_VAL(m_poGraphLayer->DeleteFeature(poFeature->GetFID()));
+        OGRFeature::DestroyFeature( poFeature );
+    }
+
+    m_oGraph.Clear();
+
+    return CE_None;
+}
+
+OGRFeature *GNMGenericNetwork::GetFeatureByGlobalFID(GNMGFID nFID)
+{
+    CPLString soLayerName = m_moFeatureFIDMap[nFID];
+    for(size_t i = 0; i < m_apoLayers.size(); ++i)
+    {
+        if(EQUAL(soLayerName, m_apoLayers[i]->GetName()))
+            return m_apoLayers[i]->GetFeature(nFID);
+    }
+    return NULL;
+}
+
+CPLErr GNMGenericNetwork::CreateRule(const char *pszRuleStr)
+{
+    CPLDebug("GNM", "Try to create rule '%s'", pszRuleStr);
+    GNMRule oRule(pszRuleStr);
+    if(!oRule.IsValid())
+    {
+        return CE_Failure;
+    }
+
+    if(!oRule.IsAcceptAny())
+    {
+        bool bSrcExist = false;
+        bool bTgtExist = false;
+        bool bConnExist = false;
+        // check layers exist
+        for(size_t i = 0; i < m_apoLayers.size(); ++i)
+        {
+            if(EQUAL(oRule.GetSourceLayerName(), m_apoLayers[i]->GetName()))
+            {
+                bSrcExist = true;
+            }
+            else if(EQUAL(oRule.GetTargetLayerName(), m_apoLayers[i]->GetName()))
+            {
+                bTgtExist = true;
+            }
+            else if(EQUAL(oRule.GetConnectorLayerName(), m_apoLayers[i]->GetName()))
+            {
+                bConnExist = true;
+            }
+        }
+
+        if(!bSrcExist || !bTgtExist)
+        {
+            CPLError( CE_Failure, CPLE_IllegalArg, "Layers '%s' or '%s' not exist",
+                      oRule.GetSourceLayerName().c_str(),
+                      oRule.GetTargetLayerName().c_str());
+            return CE_Failure;
+        }
+
+        if(!bConnExist && !oRule.GetConnectorLayerName().empty())
+        {
+            CPLError( CE_Failure, CPLE_IllegalArg, "Connector layer '%s' not exist",
+                      oRule.GetConnectorLayerName().c_str());
+            return CE_Failure;
+        }
+    }
+
+    m_asRules.push_back(oRule);
+    m_bIsRulesChanged = true;
+
+    return CE_None;
+}
+
+CPLErr GNMGenericNetwork::DeleteAllRules()
+{
+    CPLString soFilter;
+    soFilter.Printf("%s LIKE '%s%%'", GNM_SYSFIELD_PARAMNAME, GNM_MD_RULE);
+    m_poMetadataLayer->SetAttributeFilter(soFilter);
+
+    m_poMetadataLayer->ResetReading();
+    OGRFeature *poFeature;
+    std::vector<GIntBig> aFIDs;
+    while((poFeature = m_poMetadataLayer->GetNextFeature()) != NULL)
+    {
+        aFIDs.push_back(poFeature->GetFID());
+        OGRFeature::DestroyFeature(poFeature);
+    }
+
+    m_poMetadataLayer->SetAttributeFilter(NULL);
+    for(size_t i = 0; i < aFIDs.size(); ++i)
+    {
+        CPL_IGNORE_RET_VAL(m_poMetadataLayer->DeleteFeature(aFIDs[i]));
+    }
+
+    return CE_None;
+}
+
+CPLErr GNMGenericNetwork::DeleteRule(const char *pszRuleStr)
+{
+    for(size_t i = 0; i < m_asRules.size(); ++i)
+    {
+        if(EQUAL(pszRuleStr, m_asRules[i]))
+        {
+            m_asRules.erase(m_asRules.begin() + i);
+            m_bIsRulesChanged = true;
+            return CE_None;
+        }
+    }
+
+    return CE_Failure;
+}
+
+char **GNMGenericNetwork::GetRules() const
+{
+    char** papszRules = NULL;
+    for(size_t i = 0; i < m_asRules.size(); ++i)
+    {
+        papszRules = CSLAddString(papszRules, m_asRules[i]);
+    }
+    return papszRules;
+}
+
+CPLErr GNMGenericNetwork::ConnectPointsByLines(char **papszLayerList,
+                                               double dfTolerance, double dfCost,
+                                               double dfInvCost, GNMDirection eDir)
+{
+    if( CSLCount(papszLayerList) < 2 )
+    {
+        CPLError( CE_Failure, CPLE_IllegalArg, "Minimum 2 layers needed to connect" );
+        return CE_Failure;
+    }
+
+    std::vector<OGRLayer*> paLineLayers;
+    std::vector<OGRLayer*> paPointLayers;
+    int eType;
+    int iLayer;
+    OGRLayer* poLayer;
+
+    for(iLayer = 0; papszLayerList[iLayer] != NULL; ++iLayer)
+    {
+        poLayer = GetLayerByName(papszLayerList[iLayer]);
+        if(NULL == poLayer)
+            continue;
+
+        eType = wkbFlatten(poLayer->GetGeomType());
+        if(eType == wkbLineString || eType == wkbMultiLineString)
+        {
+            paLineLayers.push_back(poLayer);
+        }
+        else if(eType == wkbPoint)
+        {
+            paPointLayers.push_back(poLayer);
+        }
+    }
+
+    if (paLineLayers.empty() || paPointLayers.empty() )
+    {
+        CPLError( CE_Failure, CPLE_IllegalArg, "Need at least one line (or "
+                            "multiline) layer and one point layer to connect" );
+        return CE_Failure;
+    }
+
+    // now walk through all lines and find nearest points for line start and end
+    OGRFeature* poFeature;
+    for(size_t i = 0; i < paLineLayers.size(); ++i)
+    {
+        poLayer = paLineLayers[i];
+        eType = wkbFlatten(poLayer->GetGeomType());
+
+        poLayer->ResetReading();
+        while((poFeature = poLayer->GetNextFeature()) != NULL)
+        {
+            const OGRGeometry* poGeom = poFeature->GetGeometryRef();
+            if(NULL != poGeom)
+            {
+                if(eType == wkbLineString)
+                {
+                    const OGRLineString* poLineString =
+                                                  (const OGRLineString*) poGeom;
+                    ConnectPointsByLine(poFeature->GetFID(), poLineString,
+                                        paPointLayers, dfTolerance, dfCost,
+                                        dfInvCost, eDir);
+                }
+                else if( eType == wkbMultiLineString)
+                {
+                    const OGRMultiLineString* poMultiLineString =
+                                             (const OGRMultiLineString*) poGeom;
+                    ConnectPointsByMultiline(poFeature->GetFID(), poMultiLineString,
+                                             paPointLayers, dfTolerance, dfCost,
+                                             dfInvCost, eDir);
+                }
+            }
+            OGRFeature::DestroyFeature(poFeature);
+        }
+    }
+
+    return CE_None;
+}
+
+CPLErr GNMGenericNetwork::ChangeBlockState(GNMGFID nFID, bool bIsBlock)
+{
+    if(!m_bIsGraphLoaded && LoadGraph() != CE_None)
+    {
+        return CE_Failure;
+    }
+
+    // change block state in layer
+    OGRLayer* poLayer = GetLayerByName(m_moFeatureFIDMap[nFID]);
+    if(NULL == poLayer)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Failed to get layer '%s'.",
+                  m_moFeatureFIDMap[nFID].c_str() );
+        return CE_Failure;
+    }
+
+    OGRFeature* poFeature = poLayer->GetFeature(nFID);
+    if(NULL == poFeature)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Failed to get feature '"
+                  GNMGFIDFormat"'.", nFID );
+        return CE_Failure;
+    }
+
+    if(bIsBlock)
+    {
+        poFeature->SetField( GNM_SYSFIELD_BLOCKED, GNM_BLOCK_ALL );
+    }
+    else
+    {
+        poFeature->SetField( GNM_SYSFIELD_BLOCKED, GNM_BLOCK_NONE );
+    }
+
+    if( poLayer->SetFeature( poFeature ) != OGRERR_NONE )
+    {
+        OGRFeature::DestroyFeature( poFeature );
+        CPLError( CE_Failure, CPLE_AppDefined, "Failed to update feature." );
+        return CE_Failure;
+    }
+
+    OGRFeature::DestroyFeature( poFeature );
+
+    GNMGFID nSrcFID, nTgtFID, nConFID;
+
+    // change block state in graph layer
+    m_poGraphLayer->ResetReading();
+    while ((poFeature = m_poGraphLayer->GetNextFeature()) != NULL)
+    {
+        nSrcFID = poFeature->GetFieldAsGNMGFID(GNM_SYSFIELD_SOURCE);
+        nTgtFID = poFeature->GetFieldAsGNMGFID(GNM_SYSFIELD_TARGET);
+        nConFID = poFeature->GetFieldAsGNMGFID(GNM_SYSFIELD_CONNECTOR);
+        int nBlockState = poFeature->GetFieldAsInteger(GNM_SYSFIELD_BLOCKED);
+
+        if(bIsBlock)
+        {
+            if(nSrcFID == nFID)
+                nBlockState |= GNM_BLOCK_SRC;
+            else if(nTgtFID == nFID)
+                nBlockState |= GNM_BLOCK_TGT;
+            else if(nConFID == nFID)
+                nBlockState |= GNM_BLOCK_CONN;
+
+            poFeature->SetField( GNM_SYSFIELD_BLOCKED, nBlockState );
+        }
+        else
+        {
+            if(nSrcFID == nFID)
+                nBlockState &= ~GNM_BLOCK_SRC;
+            else if(nTgtFID == nFID)
+                nBlockState &= ~GNM_BLOCK_TGT;
+            else if(nConFID == nFID)
+                nBlockState &= ~GNM_BLOCK_CONN;
+
+            poFeature->SetField( GNM_SYSFIELD_BLOCKED, nBlockState );
+        }
+
+        if( m_poGraphLayer->SetFeature( poFeature ) != OGRERR_NONE )
+        {
+            OGRFeature::DestroyFeature( poFeature );
+            CPLError( CE_Failure, CPLE_AppDefined, "Failed to update feature." );
+            return CE_Failure;
+        }
+
+        OGRFeature::DestroyFeature( poFeature );
+    }
+
+    // change block state in graph
+    m_oGraph.ChangeBlockState(nFID, bIsBlock);
+
+    return CE_None;
+}
+
+CPLErr GNMGenericNetwork::ChangeAllBlockState(bool bIsBlock)
+{
+    if(!m_bIsGraphLoaded && LoadGraph() != CE_None)
+    {
+        return CE_Failure;
+    }
+
+    OGRFeature *poFeature;
+    m_poGraphLayer->ResetReading();
+    while ((poFeature = m_poGraphLayer->GetNextFeature()) != NULL)
+    {
+        if(bIsBlock)
+        {
+            poFeature->SetField( GNM_SYSFIELD_BLOCKED, GNM_BLOCK_ALL );
+        }
+        else
+        {
+            poFeature->SetField( GNM_SYSFIELD_BLOCKED, GNM_BLOCK_NONE );
+        }
+
+        if( m_poGraphLayer->SetFeature( poFeature ) != OGRERR_NONE )
+        {
+            OGRFeature::DestroyFeature( poFeature );
+            CPLError( CE_Failure, CPLE_AppDefined, "Failed to update feature." );
+            return CE_Failure;
+        }
+
+        OGRFeature::DestroyFeature( poFeature );
+    }
+
+    // change all network layers
+
+    for(size_t i = 0; i < m_apoLayers.size(); ++i)
+    {
+        OGRLayer* poLayer = m_apoLayers[i];
+        if(NULL == poLayer)
+            continue;
+        while ((poFeature = poLayer->GetNextFeature()) != NULL)
+        {
+            if(bIsBlock)
+            {
+                poFeature->SetField( GNM_SYSFIELD_BLOCKED, GNM_BLOCK_ALL );
+            }
+            else
+            {
+                poFeature->SetField( GNM_SYSFIELD_BLOCKED, GNM_BLOCK_NONE );
+            }
+
+            if( poLayer->SetFeature( poFeature ) != OGRERR_NONE )
+            {
+                OGRFeature::DestroyFeature( poFeature );
+                CPLError( CE_Failure, CPLE_AppDefined, "Failed to update feature." );
+                return CE_Failure;
+            }
+
+            OGRFeature::DestroyFeature( poFeature );
+        }
+    }
+
+    m_oGraph.ChangeAllBlockState(bIsBlock);
+
+    return CE_None;
+}
+
+OGRLayer *GNMGenericNetwork::GetPath(GNMGFID nStartFID, GNMGFID nEndFID,
+                          GNMGraphAlgorithmType eAlgorithm, char **papszOptions)
+{
+
+    if(!m_bIsGraphLoaded && LoadGraph() != CE_None)
+    {
+        return NULL;
+    }
+
+    GDALDriver* poMEMDrv =
+            OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName("Memory");
+    if (poMEMDrv == NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot load 'Memory' driver");
+        return NULL;
+    }
+
+    GDALDataset* poMEMDS =
+            poMEMDrv->Create("dummy_name", 0, 0, 0, GDT_Unknown, NULL);
+    OGRSpatialReference oDstSpaRef(GetProjectionRef());
+    OGRLayer* poMEMLayer = poMEMDS->CreateLayer(GetAlgorithmName(eAlgorithm,
+                               true), &oDstSpaRef, wkbGeometryCollection, NULL);
+
+    OGRGNMWrappedResultLayer* poResLayer =
+                              new OGRGNMWrappedResultLayer(poMEMDS, poMEMLayer);
+
+    bool bReturnEdges = CPL_TO_BOOL(CSLFetchBoolean(papszOptions, GNM_MD_FETCHEDGES, TRUE));
+    bool bReturnVertices = CPL_TO_BOOL(CSLFetchBoolean(papszOptions, GNM_MD_FETCHVERTEX, TRUE));
+
+    switch (eAlgorithm)
+    {
+    case GATDijkstraShortestPath:
+        {
+            GNMPATH path = m_oGraph.DijkstraShortestPath(nStartFID, nEndFID);
+
+            // fill features in result layer
+            FillResultLayer(poResLayer, path, 1, bReturnVertices, bReturnEdges);
+        }
+        break;
+    case GATKShortestPath:
+        {
+            int nK = atoi(CSLFetchNameValueDef(papszOptions, GNM_MD_NUM_PATHS,
+                                               "1"));
+
+            CPLDebug("GNM", "Search %d path(s)", nK);
+
+            std::vector<GNMPATH> paths = m_oGraph.KShortestPaths(nStartFID,
+                                                                 nEndFID, nK);
+
+            // fill features in result layer
+            for(size_t i = 0; i < paths.size(); ++i)
+            {
+                FillResultLayer(poResLayer, paths[i], static_cast<int>(i + 1), bReturnVertices,
+                                bReturnEdges);
+            }
+        }
+        break;
+    case GATConnectedComponents:
+        {
+            GNMVECTOR anEmitters;
+            if(NULL != papszOptions)
+            {
+                char** papszEmitter = CSLFetchNameValueMultiple(papszOptions, GNM_MD_EMITTER);
+                for(int i = 0; papszEmitter[i] != NULL; ++i)
+                {
+                    GNMGFID nEmitter = atol(papszEmitter[i]);
+                    anEmitters.push_back(nEmitter);
+                }
+                CSLDestroy(papszEmitter);
+            }
+
+            if(nStartFID != -1)
+            {
+                anEmitters.push_back(nStartFID);
+            }
+
+            if(nStartFID != -1)
+            {
+                anEmitters.push_back(nEndFID);
+            }
+
+            GNMPATH path = m_oGraph.ConnectedComponents(anEmitters);
+
+            // fill features in result layer
+            FillResultLayer(poResLayer, path, 1, bReturnVertices, bReturnEdges);
+        }
+        break;
+    }
+
+    return poResLayer;
+}
+
+void GNMGenericNetwork::ConnectPointsByMultiline(GIntBig nFID,
+                                    const OGRMultiLineString* poMultiLineString,
+                                    const std::vector<OGRLayer*>& paPointLayers,
+                                    double dfTolerance, double dfCost,
+                                    double dfInvCost, GNMDirection eDir)
+{
+    VALIDATE_POINTER0(poMultiLineString,
+                                 "GNMGenericNetwork::ConnectPointsByMultiline");
+    for(int i = 0; i < poMultiLineString->getNumGeometries(); ++i)
+    {
+        const OGRLineString* poLinestring =
+                (OGRLineString*)poMultiLineString->getGeometryRef(i);
+        ConnectPointsByLine(nFID, poLinestring, paPointLayers, dfTolerance,
+                            dfCost, dfInvCost, eDir);
+    }
+}
+
+void GNMGenericNetwork::ConnectPointsByLine(GIntBig nFID,
+                                    const OGRLineString* poLineString,
+                                    const std::vector<OGRLayer*>& paPointLayers,
+                                    double dfTolerance, double dfCost,
+                                    double dfInvCost, GNMDirection eDir)
+{
+    VALIDATE_POINTER0(poLineString, "GNMGenericNetwork::ConnectPointsByLine");
+    OGRPoint oStartPoint, oEndPoint;
+    poLineString->StartPoint(&oStartPoint);
+    poLineString->EndPoint(&oEndPoint);
+    double dfHalfTolerance = dfTolerance / 2;
+
+    GNMGFID nSrcFID = FindNearestPoint(&oStartPoint, paPointLayers, dfHalfTolerance);
+    GNMGFID nTgtFID = FindNearestPoint(&oEndPoint, paPointLayers, dfHalfTolerance);
+
+    if(nSrcFID == -1 || nTgtFID == -1)
+        return;
+
+    // connect nSrcFID with nTgtFID via nFID
+    ConnectFeatures(nSrcFID, nTgtFID, (GNMGFID)nFID, dfCost, dfInvCost, eDir);
+}
+
+GNMGFID GNMGenericNetwork::FindNearestPoint(const OGRPoint* poPoint,
+                                    const std::vector<OGRLayer*>& paPointLayers,
+                                    double dfTolerance)
+{
+    VALIDATE_POINTER1(poPoint, "GNMGenericNetwork::FindNearestPoint", -1);
+    double dfMinX = poPoint->getX() - dfTolerance;
+    double dfMinY = poPoint->getY() - dfTolerance;
+    double dfMaxX = poPoint->getX() + dfTolerance;
+    double dfMaxY = poPoint->getY() + dfTolerance;
+
+    OGRFeature *poFeature;
+
+    for(size_t i = 0; i < paPointLayers.size(); ++i)
+    {
+        OGRLayer *poLayer = paPointLayers[i];
+
+        poLayer->SetSpatialFilterRect(dfMinX, dfMinY,
+                                      dfMaxX, dfMaxY);
+        poLayer->ResetReading();
+        while((poFeature = poLayer->GetNextFeature()) != NULL)
+        {
+            GNMGFID nRetFID = poFeature->GetFieldAsGNMGFID(GNM_SYSFIELD_GFID);
+            OGRFeature::DestroyFeature(poFeature);
+            return nRetFID;
+        }
+    }
+
+    return -1;
+}
+
+OGRFeature *GNMGenericNetwork::FindConnection(GNMGFID nSrcFID, GNMGFID nTgtFID,
+                                              GNMGFID nConFID)
+{
+
+    CPLString soFilter;
+    soFilter.Printf("%s = " GNMGFIDFormat " and %s = " GNMGFIDFormat " and %s = " GNMGFIDFormat,
+                    GNM_SYSFIELD_SOURCE, nSrcFID,
+                    GNM_SYSFIELD_TARGET, nTgtFID,
+                    GNM_SYSFIELD_CONNECTOR, nConFID);
+
+    CPLDebug("GNM", "Set attribute filter: %s", soFilter.c_str());
+
+    m_poGraphLayer->SetAttributeFilter(soFilter);
+    m_poGraphLayer->ResetReading();
+    OGRFeature *f = m_poGraphLayer->GetNextFeature();
+    m_poGraphLayer->SetAttributeFilter(NULL);
+    return f;
+}
+
+void GNMGenericNetwork::SaveRules()
+{
+    if(!m_bIsRulesChanged)
+        return;
+
+    if(DeleteAllRules() != CE_None)
+        return;
+
+    OGRFeature *poFeature;
+    for(int i = 0; i < (int)m_asRules.size(); ++i)
+    {
+        poFeature = OGRFeature::CreateFeature(m_poMetadataLayer->GetLayerDefn());
+        poFeature->SetField(GNM_SYSFIELD_PARAMNAME, CPLSPrintf("%s%d",
+                                                            GNM_MD_RULE, i + 1));
+        poFeature->SetField(GNM_SYSFIELD_PARAMVALUE, m_asRules[i]);
+        if(m_poMetadataLayer->CreateFeature(poFeature) != OGRERR_NONE)
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "Write rule '%s' failed",
+                      m_asRules[i].c_str());
+            // TODO: do we need interrupt here?
+            //OGRFeature::DestroyFeature( poFeature );
+            // return CE_Failure;
+        }
+        OGRFeature::DestroyFeature(poFeature);
+    }
+}
+
+GNMGFID GNMGenericNetwork::GetNewVirtualFID()
+{
+    return --m_nVirtualConnectionGID;
+}
+
+void GNMGenericNetwork::FillResultLayer(OGRGNMWrappedResultLayer *poResLayer,
+                                        const GNMPATH &path, int nNoOfPath,
+                                        bool bReturnVertices, bool bReturnEdges)
+{
+    for(size_t i = 0; i < path.size(); ++i)
+    {
+        if(bReturnVertices)
+        {
+            GNMGFID nGFID = path[i].first;
+
+            // TODO: create feature for virtual vertex
+            // if(nGFID < -1) {...}
+
+            CPLString soLayerName = m_moFeatureFIDMap[nGFID];
+            OGRFeature* poFeature = GetFeatureByGlobalFID(nGFID);
+            if(NULL != poFeature)
+            {
+                poResLayer->InsertFeature(poFeature, soLayerName, nNoOfPath,
+                                          false);
+
+                OGRFeature::DestroyFeature(poFeature);
+            }
+        }
+
+        if(bReturnEdges)
+        {
+            GNMGFID nGFID = path[i].second;
+
+            // TODO: create feature for virtual edge
+            // if(nGFID < -1) {...}
+
+            CPLString soLayerName = m_moFeatureFIDMap[nGFID];
+            OGRFeature* poFeature = GetFeatureByGlobalFID(nGFID);
+            if(NULL != poFeature)
+            {
+                poResLayer->InsertFeature(poFeature, soLayerName, nNoOfPath,
+                                          true);
+                OGRFeature::DestroyFeature(poFeature);
+            }
+        }
+    }
+}
+
+CPLErr GNMGenericNetwork::CheckLayerDriver(const char* pszDefaultDriverName,
+                                        char **papszOptions)
+{
+    if(NULL == m_poLayerDriver)
+    {
+        const char* pszDriverName = CSLFetchNameValueDef(papszOptions,
+                                                         GNM_MD_FORMAT,
+                                                         pszDefaultDriverName);
+
+        if(!CheckStorageDriverSupport(pszDriverName))
+        {
+            CPLError( CE_Failure, CPLE_IllegalArg, "%s driver not supported as network storage",
+                      pszDriverName );
+            return CE_Failure;
+        }
+
+        m_poLayerDriver = GetGDALDriverManager()->GetDriverByName(pszDriverName );
+        if(NULL == m_poLayerDriver)
+        {
+            CPLError( CE_Failure, CPLE_IllegalArg, "%s driver not available",
+                      pszDriverName );
+            return CE_Failure;
+        }
+    }
+    return CE_None;
+}
+
+CPLErr GNMGenericNetwork::CreateMetadataLayer(GDALDataset * const pDS, int nVersion,
+                                           size_t nFieldSize)
+{
+    OGRLayer* pMetadataLayer = pDS->CreateLayer(GNM_SYSLAYER_META, NULL, wkbNone,
+                                                NULL);
+    if (NULL == pMetadataLayer)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Creation of '%s' layer failed",
+                  GNM_SYSLAYER_META );
+        return CE_Failure;
+    }
+
+    OGRFieldDefn oFieldKey(GNM_SYSFIELD_PARAMNAME, OFTString);
+    oFieldKey.SetWidth(static_cast<int>(nFieldSize));
+    OGRFieldDefn oFieldValue(GNM_SYSFIELD_PARAMVALUE, OFTString);
+    oFieldValue.SetWidth(static_cast<int>(nFieldSize));
+
+    if(pMetadataLayer->CreateField(&oFieldKey) != OGRERR_NONE ||
+       pMetadataLayer->CreateField(&oFieldValue) != OGRERR_NONE)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Creation of layer '%s' fields failed",
+                  GNM_SYSLAYER_META );
+        return CE_Failure;
+    }
+
+    OGRFeature *poFeature;
+
+    // write name
+    poFeature = OGRFeature::CreateFeature(pMetadataLayer->GetLayerDefn());
+    poFeature->SetField(GNM_SYSFIELD_PARAMNAME, GNM_MD_NAME);
+    poFeature->SetField(GNM_SYSFIELD_PARAMVALUE, m_soName);
+    if(pMetadataLayer->CreateFeature(poFeature) != OGRERR_NONE)
+    {
+        OGRFeature::DestroyFeature( poFeature );
+        CPLError( CE_Failure, CPLE_AppDefined, "Write GNM name failed");
+        return CE_Failure;
+    }
+    OGRFeature::DestroyFeature(poFeature);
+
+    // write version
+    poFeature = OGRFeature::CreateFeature(pMetadataLayer->GetLayerDefn());
+    poFeature->SetField(GNM_SYSFIELD_PARAMNAME, GNM_MD_VERSION);
+    poFeature->SetField(GNM_SYSFIELD_PARAMVALUE, CPLSPrintf("%d", nVersion));
+    if(pMetadataLayer->CreateFeature(poFeature) != OGRERR_NONE)
+    {
+        OGRFeature::DestroyFeature( poFeature );
+        CPLError( CE_Failure, CPLE_AppDefined, "Write GNM version failed");
+        return CE_Failure;
+    }
+    OGRFeature::DestroyFeature(poFeature);
+
+    // write description
+    if(!sDescription.empty())
+    {
+        poFeature = OGRFeature::CreateFeature(pMetadataLayer->GetLayerDefn());
+        poFeature->SetField(GNM_SYSFIELD_PARAMNAME, GNM_MD_DESCR);
+        poFeature->SetField(GNM_SYSFIELD_PARAMVALUE, sDescription);
+        if(pMetadataLayer->CreateFeature(poFeature) != OGRERR_NONE)
+        {
+            OGRFeature::DestroyFeature( poFeature );
+            CPLError( CE_Failure, CPLE_AppDefined, "Write GNM description failed");
+            return CE_Failure;
+        }
+        OGRFeature::DestroyFeature(poFeature);
+    }
+
+    // write srs if < 254 or create file
+    if(!m_soSRS.empty())
+    {
+        if(m_soSRS.size() >= nFieldSize)
+        {
+            if(StoreNetworkSrs() != CE_None)
+                return CE_Failure;
+        }
+        else
+        {
+            poFeature = OGRFeature::CreateFeature(pMetadataLayer->GetLayerDefn());
+            poFeature->SetField(GNM_SYSFIELD_PARAMNAME, GNM_MD_SRS);
+            poFeature->SetField(GNM_SYSFIELD_PARAMVALUE, m_soSRS);
+            if(pMetadataLayer->CreateFeature(poFeature) != OGRERR_NONE)
+            {
+                OGRFeature::DestroyFeature( poFeature );
+                CPLError( CE_Failure, CPLE_AppDefined, "Write GNM SRS failed");
+                return CE_Failure;
+            }
+            OGRFeature::DestroyFeature(poFeature);
+        }
+    }
+
+    m_poMetadataLayer = pMetadataLayer;
+
+    m_nVersion = nVersion;
+
+    // create default rule
+    return CreateRule("ALLOW CONNECTS ANY");
+}
+
+CPLErr GNMGenericNetwork::StoreNetworkSrs()
+{
+    return CE_Failure;
+}
+
+CPLErr GNMGenericNetwork::LoadNetworkSrs()
+{
+    return CE_Failure;
+}
+
+CPLErr GNMGenericNetwork::CreateGraphLayer(GDALDataset * const pDS)
+{
+    m_poGraphLayer = pDS->CreateLayer(GNM_SYSLAYER_GRAPH, NULL, wkbNone, NULL);
+    if (NULL == m_poGraphLayer)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Creation of '%s' layer failed",
+                  GNM_SYSLAYER_GRAPH );
+        return CE_Failure;
+    }
+
+    OGRFieldDefn oFieldSrc(GNM_SYSFIELD_SOURCE, GNMGFIDInt);
+    OGRFieldDefn oFieldDst(GNM_SYSFIELD_TARGET, GNMGFIDInt);
+    OGRFieldDefn oFieldConnector(GNM_SYSFIELD_CONNECTOR, GNMGFIDInt);
+    OGRFieldDefn oFieldCost(GNM_SYSFIELD_COST, OFTReal);
+    OGRFieldDefn oFieldInvCost(GNM_SYSFIELD_INVCOST, OFTReal);
+    OGRFieldDefn oFieldDir(GNM_SYSFIELD_DIRECTION, OFTInteger);
+    OGRFieldDefn oFieldBlock(GNM_SYSFIELD_BLOCKED, OFTInteger);
+
+    if(m_poGraphLayer->CreateField(&oFieldSrc) != OGRERR_NONE ||
+       m_poGraphLayer->CreateField(&oFieldDst) != OGRERR_NONE ||
+       m_poGraphLayer->CreateField(&oFieldConnector) != OGRERR_NONE ||
+       m_poGraphLayer->CreateField(&oFieldCost) != OGRERR_NONE ||
+       m_poGraphLayer->CreateField(&oFieldInvCost) != OGRERR_NONE ||
+       m_poGraphLayer->CreateField(&oFieldDir) != OGRERR_NONE ||
+       m_poGraphLayer->CreateField(&oFieldBlock) != OGRERR_NONE)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Creation of layer '%s' fields failed",
+                  GNM_SYSLAYER_GRAPH );
+        return CE_Failure;
+    }
+
+    return CE_None;
+}
+
+CPLErr GNMGenericNetwork::CreateFeaturesLayer(GDALDataset * const pDS)
+{
+    m_poFeaturesLayer = pDS->CreateLayer(GNM_SYSLAYER_FEATURES, NULL, wkbNone, NULL);
+    if (NULL == m_poFeaturesLayer)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Creation of '%s' layer failed",
+                  GNM_SYSLAYER_FEATURES );
+        return CE_Failure;
+    }
+
+    OGRFieldDefn oFieldGID(GNM_SYSFIELD_GFID, GNMGFIDInt);
+    OGRFieldDefn oFieldLayerName(GNM_SYSFIELD_LAYERNAME, OFTString);
+    oFieldLayerName.SetWidth(254);
+
+    if(m_poFeaturesLayer->CreateField(&oFieldGID) != OGRERR_NONE ||
+       m_poFeaturesLayer->CreateField(&oFieldLayerName) != OGRERR_NONE)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Creation of layer '%s' fields failed",
+                  GNM_SYSLAYER_FEATURES );
+        return CE_Failure;
+    }
+
+    return CE_None;
+}
+
+CPLErr GNMGenericNetwork::LoadMetadataLayer(GDALDataset * const pDS)
+{
+    // read version, description, SRS, classes, rules
+    m_poMetadataLayer = pDS->GetLayerByName(GNM_SYSLAYER_META);
+    if(NULL == m_poMetadataLayer)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Loading of '%s' layer failed",
+                  GNM_SYSLAYER_META );
+        return CE_Failure;
+    }
+
+    std::map<int, GNMRule> moRules;
+    int nRulePrefixLen = static_cast<int>(CPLStrnlen(GNM_MD_RULE, 255));
+    OGRFeature *poFeature;
+    m_poMetadataLayer->ResetReading();
+    while ((poFeature = m_poMetadataLayer->GetNextFeature()) != NULL)
+    {
+        const char *pKey = poFeature->GetFieldAsString(GNM_SYSFIELD_PARAMNAME);
+        const char *pValue = poFeature->GetFieldAsString(GNM_SYSFIELD_PARAMVALUE);
+
+        CPLDebug("GNM", "Load metadata. Key: %s, value %s", pKey, pValue);
+
+        if(EQUAL(pKey, GNM_MD_NAME))
+        {
+            m_soName = pValue;
+        }
+        else if(EQUAL(pKey, GNM_MD_DESCR))
+        {
+            sDescription = pValue;
+        }
+        else if(EQUAL(pKey, GNM_MD_SRS))
+        {
+            m_soSRS = pValue;
+        }
+        else if(EQUAL(pKey, GNM_MD_VERSION))
+        {
+            m_nVersion = atoi(pValue);
+        }
+        else if(EQUALN(pKey, GNM_MD_RULE, nRulePrefixLen))
+        {
+            moRules[atoi(pKey + nRulePrefixLen)] = pValue;
+        }
+
+        OGRFeature::DestroyFeature(poFeature);
+    }
+
+    for(std::map<int, GNMRule>::iterator it =  moRules.begin();
+        it != moRules.end(); ++it)
+    {
+        if(it->second.IsValid())
+            m_asRules.push_back(it->second);
+    }
+
+    if(m_soSRS.empty())
+    {
+        if(LoadNetworkSrs() != CE_None)
+            return CE_Failure;
+    }
+
+    return CE_None;
+}
+
+CPLErr GNMGenericNetwork::LoadGraphLayer(GDALDataset * const pDS)
+{
+    m_poGraphLayer = pDS->GetLayerByName(GNM_SYSLAYER_GRAPH);
+    if(NULL == m_poGraphLayer)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Loading of '%s' layer failed",
+                  GNM_SYSLAYER_GRAPH );
+        return CE_Failure;
+    }
+
+    return CE_None;
+}
+
+CPLErr GNMGenericNetwork::LoadGraph()
+{
+    if(m_bIsGraphLoaded)
+        return CE_None;
+
+    if(NULL == m_poGraphLayer)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Loading of graph data failed");
+        return CE_Failure;
+    }
+
+    OGRFeature *poFeature;
+    m_poGraphLayer->ResetReading();
+    GNMGFID nSrcFID, nTgtFID, nConFID;
+    double dfCost, dfInvCost;
+    while ((poFeature = m_poGraphLayer->GetNextFeature()) != NULL)
+    {
+        nSrcFID = poFeature->GetFieldAsGNMGFID(GNM_SYSFIELD_SOURCE);
+        nTgtFID = poFeature->GetFieldAsGNMGFID(GNM_SYSFIELD_TARGET);
+        nConFID = poFeature->GetFieldAsGNMGFID(GNM_SYSFIELD_CONNECTOR);
+        dfCost = poFeature->GetFieldAsDouble(GNM_SYSFIELD_COST);
+        dfInvCost = poFeature->GetFieldAsDouble(GNM_SYSFIELD_INVCOST);
+        GNMDirection eDir = poFeature->GetFieldAsInteger(GNM_SYSFIELD_DIRECTION);
+
+        int nBlockState = poFeature->GetFieldAsInteger(GNM_SYSFIELD_BLOCKED);
+
+        bool bIsBlock = GNM_BLOCK_NONE != nBlockState;
+
+        m_oGraph.AddEdge(nConFID, nSrcFID, nTgtFID, eDir == GNM_EDGE_DIR_BOTH,
+                         dfCost, dfInvCost);
+
+        if(bIsBlock)
+        {
+            if(nBlockState & GNM_BLOCK_SRC)
+                m_oGraph.ChangeBlockState(nSrcFID, bIsBlock);
+            if(nBlockState & GNM_BLOCK_TGT)
+                m_oGraph.ChangeBlockState(nTgtFID, bIsBlock);
+            if(nBlockState & GNM_BLOCK_CONN)
+                m_oGraph.ChangeBlockState(nConFID, bIsBlock);
+        }
+
+        if(nConFID < m_nVirtualConnectionGID)
+            m_nVirtualConnectionGID = nConFID;
+
+        OGRFeature::DestroyFeature(poFeature);
+    }
+
+    m_bIsGraphLoaded = true;
+    return CE_None;
+}
+
+CPLErr GNMGenericNetwork::LoadFeaturesLayer(GDALDataset * const pDS)
+{
+    m_poFeaturesLayer = pDS->GetLayerByName(GNM_SYSLAYER_FEATURES);
+    if(NULL == m_poFeaturesLayer)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Loading of '%s' layer failed",
+                  GNM_SYSLAYER_FEATURES );
+        return CE_Failure;
+    }
+
+    OGRFeature *poFeature;
+    m_poFeaturesLayer->ResetReading();
+    while ((poFeature = m_poFeaturesLayer->GetNextFeature()) != NULL)
+    {
+        GNMGFID nFID = poFeature->GetFieldAsGNMGFID(GNM_SYSFIELD_GFID);
+        const char *pFeatureClass = poFeature->GetFieldAsString(
+                    GNM_SYSFIELD_LAYERNAME);
+
+        if(nFID >= m_nGID)
+            m_nGID = nFID + 1;
+
+        m_moFeatureFIDMap[nFID] = pFeatureClass;
+
+        // Load network layer. No error handling as we want to load whole network
+        LoadNetworkLayer(pFeatureClass);
+
+        OGRFeature::DestroyFeature(poFeature);
+    }
+    return CE_None;
+}
+
+int GNMGenericNetwork::TestCapability( const char * pszCap )
+
+{
+    if( EQUAL(pszCap, ODsCCreateLayer) )
+        return TRUE;
+    else if( EQUAL(pszCap, ODsCDeleteLayer) )
+        return TRUE;
+    else
+        return FALSE;
+}
+
+OGRLayer *GNMGenericNetwork::CopyLayer(OGRLayer *poSrcLayer,
+                                       const char *pszNewName, char **papszOptions)
+{
+    if(CSLFindName(papszOptions, "DST_SRSWKT") == -1)
+    {
+        papszOptions = CSLAddNameValue(papszOptions, "DST_SRSWKT",
+                                       GetProjectionRef());
+    }
+    else
+    {
+        papszOptions = CSLSetNameValue(papszOptions, "DST_SRSWKT",
+                                       GetProjectionRef());
+    }
+    return GDALDataset::CopyLayer(poSrcLayer, pszNewName, papszOptions);
+}
+
+int GNMGenericNetwork::CloseDependentDatasets()
+{
+    size_t nCount = m_apoLayers.size();
+    for(size_t i = 0; i < nCount; ++i)
+    {
+        delete m_apoLayers[i];
+    }
+    m_apoLayers.clear();
+
+    GNMNetwork::CloseDependentDatasets();
+
+    return nCount > 0 ? TRUE : FALSE;
+}
+
+void GNMGenericNetwork::FlushCache()
+{
+    SaveRules();
+
+    GNMNetwork::FlushCache();
+}
+
+//--- C API --------------------------------------------------------------------
+
+CPLErr CPL_STDCALL GNMConnectFeatures (GNMGenericNetworkH hNet,
+                                GNMGFID nSrcFID, GNMGFID nTgtFID,
+                                GNMGFID nConFID, double dfCost,
+                                double dfInvCost,
+                                GNMDirection eDir)
+{
+    VALIDATE_POINTER1( hNet, "GNMConnectFeatures", CE_Failure );
+
+    return ((GNMGenericNetwork*)hNet)->ConnectFeatures(nSrcFID, nTgtFID,
+                                                          nConFID, dfCost,
+                                                          dfInvCost, eDir);
+}
+
+CPLErr CPL_STDCALL GNMDisconnectFeatures (GNMGenericNetworkH hNet, GNMGFID nSrcFID,
+                                          GNMGFID nTgtFID, GNMGFID nConFID)
+{
+    VALIDATE_POINTER1( hNet, "GNMDisconnectFeatures", CE_Failure );
+
+    return ((GNMGenericNetwork*)hNet)->DisconnectFeatures(nSrcFID, nTgtFID,
+                                                          nConFID);
+}
+
+CPLErr CPL_STDCALL GNMDisconnectFeaturesWithId(GNMGenericNetworkH hNet,
+                                               GNMGFID nFID)
+{
+    VALIDATE_POINTER1( hNet, "GNMDisconnectFeaturesWithId", CE_Failure );
+
+    return ((GNMGenericNetwork*)hNet)->DisconnectFeaturesWithId(nFID);
+
+}
+
+
+CPLErr CPL_STDCALL GNMReconnectFeatures (GNMGenericNetworkH hNet,
+                                         GNMGFID nSrcFID, GNMGFID nTgtFID,
+                                         GNMGFID nConFID, double dfCost,
+                                         double dfInvCost, GNMDirection eDir)
+{
+    VALIDATE_POINTER1( hNet, "GNMReconnectFeatures", CE_Failure );
+
+    return ((GNMGenericNetwork*)hNet)->ReconnectFeatures(nSrcFID, nTgtFID,
+                                        nConFID, dfCost, dfInvCost, eDir);
+
+}
+
+CPLErr CPL_STDCALL GNMCreateRule (GNMGenericNetworkH hNet, const char *pszRuleStr)
+{
+    VALIDATE_POINTER1( hNet, "GNMCreateRule", CE_Failure );
+
+    return ((GNMGenericNetwork*)hNet)->CreateRule(pszRuleStr);
+
+}
+
+CPLErr CPL_STDCALL GNMDeleteAllRules(GNMGenericNetworkH hNet)
+{
+    VALIDATE_POINTER1( hNet, "GNMDeleteAllRules", CE_Failure );
+
+    return ((GNMGenericNetwork*)hNet)->DeleteAllRules();
+}
+
+CPLErr CPL_STDCALL GNMDeleteRule(GNMGenericNetworkH hNet, const char *pszRuleStr)
+{
+    VALIDATE_POINTER1( hNet, "GNMDeleteRule", CE_Failure );
+
+    return ((GNMGenericNetwork*)hNet)->DeleteRule(pszRuleStr);
+}
+
+char** CPL_STDCALL GNMGetRules(GNMGenericNetworkH hNet)
+{
+    VALIDATE_POINTER1( hNet, "GNMDeleteRule", NULL );
+
+    return ((GNMGenericNetwork*)hNet)->GetRules();
+}
+
+CPLErr CPL_STDCALL GNMConnectPointsByLines (GNMGenericNetworkH hNet,
+                                            char **papszLayerList,
+                                            double dfTolerance,
+                                            double dfCost,
+                                            double dfInvCost,
+                                            GNMDirection eDir)
+{
+    VALIDATE_POINTER1( hNet, "GNMConnectPointsByLines", CE_Failure );
+
+    return ((GNMGenericNetwork*)hNet)->ConnectPointsByLines(papszLayerList,
+                                                            dfTolerance,
+                                                            dfCost,
+                                                            dfInvCost, eDir);
+}
+
+CPLErr CPL_STDCALL GNMChangeBlockState (GNMGenericNetworkH hNet,
+                                        GNMGFID nFID, bool bIsBlock)
+{
+    VALIDATE_POINTER1( hNet, "GNMChangeBlockState", CE_Failure );
+
+    return ((GNMGenericNetwork*)hNet)->ChangeBlockState(nFID, bIsBlock);
+}
+
+CPLErr CPL_STDCALL GNMChangeAllBlockState (GNMGenericNetworkH hNet,
+                                           int bIsBlock)
+{
+    VALIDATE_POINTER1( hNet, "GNMChangeAllBlockState", CE_Failure );
+
+    return ((GNMGenericNetwork*)hNet)->ChangeAllBlockState(bIsBlock == TRUE);
+}
diff --git a/gnm/gnmgraph.cpp b/gnm/gnmgraph.cpp
new file mode 100644
index 0000000..2b39ba8
--- /dev/null
+++ b/gnm/gnmgraph.cpp
@@ -0,0 +1,622 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
+ * Purpose:  GNM graph implementation.
+ * Authors:  Mikhail Gusev (gusevmihs at gmail dot com)
+ *           Dmitry Baryshnikov, polimax at mail.ru
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Mikhail Gusev
+ * Copyright (c) 2014-2015, NextGIS <info at nextgis.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gnmgraph.h"
+#include <algorithm>
+#include <limits>
+#include <set>
+
+GNMGraph::GNMGraph()
+{
+}
+
+GNMGraph::~GNMGraph()
+{
+
+}
+
+void GNMGraph::AddVertex(GNMGFID nFID)
+{
+    if(m_mstVertices.find(nFID) != m_mstVertices.end())
+        return;
+
+    GNMStdVertex stVertex;
+    stVertex.bIsBloked = false;
+    m_mstVertices[nFID] = stVertex;
+}
+
+void GNMGraph::DeleteVertex(GNMGFID nFID)
+{
+    m_mstVertices.erase(nFID);
+
+    // remove all edges with this vertex
+    std::vector<GNMGFID> aoIdsToErase;
+    for(std::map<GNMGFID,GNMStdEdge>::iterator it = m_mstEdges.begin();
+        it != m_mstEdges.end(); ++it)
+    {
+        if(it->second.nSrcVertexFID == nFID || it->second.nTgtVertexFID == nFID)
+            aoIdsToErase.push_back(it->first);
+    }
+    for(size_t i=0;i<aoIdsToErase.size();i++)
+        m_mstEdges.erase(aoIdsToErase[i]);
+}
+
+void GNMGraph::AddEdge(GNMGFID nConFID, GNMGFID nSrcFID, GNMGFID nTgtFID,
+                       bool bIsBidir, double dfCost, double dfInvCost)
+{
+    // We do not add edge if an edge with the same id already exist
+    // because each edge must have only one source and one target vertex.
+    std::map<GNMGFID,GNMStdEdge>::iterator it = m_mstEdges.find(nConFID);
+    if (it != m_mstEdges.end())
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "The edge already exist." );
+        return;
+    }
+
+    AddVertex(nSrcFID);
+    AddVertex(nTgtFID);
+
+    std::map<GNMGFID, GNMStdVertex>::iterator itSrs = m_mstVertices.find(nSrcFID);
+    std::map<GNMGFID, GNMStdVertex>::iterator itTgt = m_mstVertices.find(nTgtFID);
+
+    // Insert edge to the array of edges.
+    GNMStdEdge stEdge;
+    stEdge.nSrcVertexFID = nSrcFID;
+    stEdge.nTgtVertexFID = nTgtFID;
+    stEdge.bIsBidir = bIsBidir;
+    stEdge.dfDirCost = dfCost;
+    stEdge.dfInvCost = dfInvCost;
+    stEdge.bIsBloked = false;
+
+    m_mstEdges[nConFID] = stEdge;
+
+    if (bIsBidir)
+    {
+        itSrs->second.anOutEdgeFIDs.push_back(nConFID);
+        itTgt->second.anOutEdgeFIDs.push_back(nConFID);
+    }
+    else
+    {
+        itSrs->second.anOutEdgeFIDs.push_back(nConFID);
+    }
+}
+
+void GNMGraph::DeleteEdge(GNMGFID nConFID)
+{
+    m_mstEdges.erase(nConFID);
+
+    // remove edge from all vertices anOutEdgeFIDs
+    for(std::map<GNMGFID, GNMStdVertex>::iterator it = m_mstVertices.begin();
+        it != m_mstVertices.end(); ++it)
+    {
+        it->second.anOutEdgeFIDs.erase(
+                    std::remove( it->second.anOutEdgeFIDs.begin(),
+                                 it->second.anOutEdgeFIDs.end(), nConFID),
+                    it->second.anOutEdgeFIDs.end());
+    }
+}
+
+void GNMGraph::ChangeEdge(GNMGFID nFID, double dfCost, double dfInvCost)
+{
+    std::map<GNMGFID, GNMStdEdge>::iterator it = m_mstEdges.find(nFID);
+    if (it != m_mstEdges.end())
+    {
+        it->second.dfDirCost = dfCost;
+        it->second.dfInvCost = dfInvCost;
+    }
+}
+
+void GNMGraph::ChangeBlockState(GNMGFID nFID, bool bBlock)
+{
+    // check vertices
+    std::map<GNMGFID, GNMStdVertex>::iterator itv = m_mstVertices.find(nFID);
+    if(itv != m_mstVertices.end())
+    {
+        itv->second.bIsBloked = bBlock;
+        return;
+    }
+
+    // check edges
+    std::map<GNMGFID, GNMStdEdge>::iterator ite = m_mstEdges.find(nFID);
+    if (ite != m_mstEdges.end())
+    {
+        ite->second.bIsBloked = bBlock;
+    }
+}
+
+bool GNMGraph::CheckVertexBlocked(GNMGFID nFID) const
+{
+    std::map<GNMGFID, GNMStdVertex>::const_iterator it = m_mstVertices.find(nFID);
+    if (it != m_mstVertices.end())
+        return it->second.bIsBloked;
+    return false;
+}
+
+void GNMGraph::ChangeAllBlockState(bool bBlock)
+{
+    for(std::map<GNMGFID, GNMStdVertex>::iterator itv = m_mstVertices.begin();
+        itv != m_mstVertices.end(); ++itv)
+    {
+        itv->second.bIsBloked = bBlock;
+    }
+
+    for(std::map<GNMGFID, GNMStdEdge>::iterator ite = m_mstEdges.begin();
+        ite != m_mstEdges.end(); ++ite)
+    {
+        ite->second.bIsBloked = bBlock;
+    }
+}
+
+GNMPATH GNMGraph::DijkstraShortestPath( GNMGFID nStartFID, GNMGFID nEndFID,
+                                 const std::map<GNMGFID, GNMStdEdge> &mstEdges)
+{
+    std::map<GNMGFID, GNMGFID> mnShortestTree;
+    DijkstraShortestPathTree(nStartFID, mstEdges, mnShortestTree);
+
+    // We search for a path in the resulting tree, starting from end point to
+    // start point.
+
+    GNMPATH aoShortestPath;
+    GNMGFID nNextVertexId = nEndFID;
+    std::map<GNMGFID, GNMGFID>::iterator it;
+    EDGEVERTEXPAIR buf;
+
+    while (true)
+    {
+        it = mnShortestTree.find(nNextVertexId);
+
+        if (it == mnShortestTree.end())
+        {
+            // We haven't found the start vertex - there is no path between
+            // to given vertices in a shortest-path tree.
+            break;
+        }
+        else if (it->first == nStartFID)
+        {
+            // We've reached the start vertex and return an array.
+            aoShortestPath.push_back( std::make_pair(nNextVertexId, -1) );
+
+            // Revert array because the first vertex is now the last in path.
+            int size = static_cast<int>(aoShortestPath.size());
+            for (int i = 0; i < size / 2; ++i)
+            {
+                buf = aoShortestPath[i];
+                aoShortestPath[i] = aoShortestPath[size - i - 1];
+                aoShortestPath[size - i - 1] = buf;
+            }
+            return aoShortestPath;
+        }
+        else
+        {
+            // There is only one edge which leads to this vertex, because we
+            // analyse a tree. We add this edge with its target vertex into
+            // final array.
+            aoShortestPath.push_back(std::make_pair(nNextVertexId, it->second));
+
+            // An edge has only two vertexes, so we get the opposite one to the
+            // current vertex in order to continue search backwards.
+            nNextVertexId = GetOppositVertex(it->second, it->first);
+        }
+    }
+
+    // return empty array
+    GNMPATH oRet;
+    return oRet;
+}
+
+GNMPATH GNMGraph::DijkstraShortestPath( GNMGFID nStartFID, GNMGFID nEndFID)
+{
+    return DijkstraShortestPath(nStartFID, nEndFID, m_mstEdges);
+}
+
+std::vector<GNMPATH> GNMGraph::KShortestPaths(GNMGFID nStartFID, GNMGFID nEndFID,
+                                              size_t nK)
+{
+    // Resulting array with paths.
+    // A will be sorted by the path costs' descending.
+    std::vector<GNMPATH> A;
+
+    if (nK <= 0)
+        return A; // return empty array if K is incorrect.
+
+    // Temporary array for storing paths-candidates.
+    // B will be automatically sorted by the cost descending order. We
+    // need multimap because there can be physically different paths but
+    // with the same costs.
+    std::multimap<double, GNMPATH> B;
+
+    // Firstly get the very shortest path.
+    // Note, that it is important to obtain the path from DijkstraShortestPath()
+    // as vector, rather than the map, because we need the correct order of the
+    // path segments in the Yen's algorithm iterations.
+    GNMPATH aoFirstPath = DijkstraShortestPath(nStartFID, nEndFID);
+    if (aoFirstPath.empty())
+        return A; // return empty array if there is no path between points.
+
+    A.push_back(aoFirstPath);
+
+    size_t i, k, l;
+    GNMPATH::iterator itAk, tempIt, itR;
+    std::vector<GNMPATH>::iterator itA;
+    std::map<GNMGFID, double>::iterator itDel;
+    GNMPATH aoRootPath, aoRootPathOther, aoSpurPath;
+    GNMGFID nSpurNode, nVertexToDel, nEdgeToDel;
+    double dfSumCost;
+
+    std::map<GNMGFID, GNMStdEdge> mstEdges = m_mstEdges;
+
+    for (k = 0; k < nK - 1; ++k) // -1 because we have already found one
+    {
+        std::map<GNMGFID, double> mDeletedEdges; // for infinity costs assignement
+        itAk = A[k].begin();
+
+        for (i = 0; i < A[k].size() - 1; ++i) // avoid end node
+        {
+            // Get the current node.
+            nSpurNode = A[k][i].first;
+
+            // Get the root path from the 0 to the current node.
+
+            // Equivalent to A[k][i]
+            // because we will use std::vector::assign, which assigns [..)
+            // range, not [..]
+            ++itAk;
+
+            aoRootPath.assign(A[k].begin(), itAk);
+
+            // Remove old incidence edges of all other best paths.
+            // i.e. if the spur vertex can be reached in already found best
+            // paths we must remove the following edge after the end of root
+            // path from the graph in order not to take in account these already
+            // seen best paths.
+            // i.e. it ensures that the spur path will be different.
+            for (itA = A.begin(); itA != A.end(); ++itA)
+            {
+                // check if the number of node exceed the number of last node in
+                // the path array (i.e. if one of the A paths has less amount of
+                // segments than the current candidate path)
+                if (i >= itA->size())
+                    continue;
+
+                // + 1, because we will use std::vector::assign, which assigns
+                // [..) range, not [..]
+                aoRootPathOther.assign(itA->begin(), itA->begin() + i + 1);
+
+                // Get the edge which follows the spur node for current path
+                // and delete it.
+                //
+                // NOTE: we do not delete edges due to performance reasons,
+                // because the deletion of edge and all its GFIDs in vertex
+                // records is slower than the infinity cost assignment.
+
+                // also check if node number exceed the number of the last node
+                // in root array.
+                if ((aoRootPath == aoRootPathOther) &&
+                        (i < aoRootPathOther.size()))
+                {
+                    tempIt = itA->begin() + i + 1;
+                    mDeletedEdges.insert(std::make_pair(tempIt->second,
+                                           mstEdges[tempIt->second].dfDirCost));
+                    mstEdges[tempIt->second].dfDirCost
+                                      = std::numeric_limits<double>::infinity();
+                }
+            }
+
+            // Remove root path nodes from the graph. If we do not delete them
+            // the path will be found backwards and some parts of the path will
+            // duplicate the parts of old paths.
+            // Note: we "delete" all the incidence to the root nodes edges, so
+            // to restore them in a common way.
+
+            // end()-1, because we should not remove the spur node
+            for (itR = aoRootPath.begin(); itR != aoRootPath.end() - 1; ++itR)
+            {
+                nVertexToDel = itR->first;
+                for (l = 0; l < m_mstVertices[nVertexToDel].anOutEdgeFIDs.size();
+                     ++l)
+                {
+                    nEdgeToDel = m_mstVertices[nVertexToDel].anOutEdgeFIDs[l];
+                    mDeletedEdges.insert(std::make_pair(nEdgeToDel,
+                                               mstEdges[nEdgeToDel].dfDirCost));
+                    mstEdges[nEdgeToDel].dfDirCost
+                                      = std::numeric_limits<double>::infinity();
+                }
+            }
+
+            // Find the new best path in the modified graph.
+            aoSpurPath = DijkstraShortestPath(nSpurNode, nEndFID, mstEdges);
+
+            // Firstly, restore deleted edges in order to calculate the summary
+            // cost of the path correctly later, because the costs will be
+            // gathered from the initial graph.
+            // We must do it here, after each edge removing, because the later
+            // Dijkstra searches must consider these edges.
+            for (itDel = mDeletedEdges.begin(); itDel != mDeletedEdges.end();
+                 ++itDel)
+            {
+                mstEdges[itDel->first].dfDirCost = itDel->second;
+            }
+
+            mDeletedEdges.clear();
+
+            // If the part of a new best path has been found we form a full one
+            // and add it to the candidates array.
+            if (!aoSpurPath.empty())
+            {
+                // + 1 so not to consider the first node in the found path,
+                // which is already the last node in the root path
+                aoRootPath.insert( aoRootPath.end(), aoSpurPath.begin() + 1,
+                                   aoSpurPath.end());
+                // Calculate the summary cost of the path.
+                // TODO: get the summary cost from the Dejkstra method?
+                dfSumCost = 0.0;
+                for (itR = aoRootPath.begin(); itR != aoRootPath.end(); ++itR)
+                {
+                    // TODO: check: Note, that here the current cost can not be
+                    // infinity, because every time we assign infinity costs for
+                    // edges of old paths, we anyway have the alternative edges
+                    // with non-infinity costs.
+                    dfSumCost += mstEdges[itR->second].dfDirCost;
+                }
+
+                B.insert(std::make_pair(dfSumCost, aoRootPath));
+            }
+        }
+
+        if (B.empty())
+            break;
+
+        // The best path is the first, because the map is sorted accordingly.
+        // Note, that here we won't clear the path candidates array and select
+        // the best path from all of the rest paths, even from those which were
+        // found on previous iterations. That's why we need k iterations at all.
+        // Note, that if there were two paths with the same costs and it is the
+        // LAST iteration the first occurred path will be added, rather than
+        // random.
+        A.push_back(B.begin()->second);
+
+        // Sometimes B contains fully duplicate paths. Such duplicates have been
+        // formed during the search of alternative for almost the same paths
+        // which were already in A.
+        // We allowed to add them into B so here we must delete all duplicates.
+        while (!B.empty() && B.begin()->second == A.back())
+        {
+            B.erase(B.begin());
+        }
+    }
+
+    return A;
+}
+
+GNMPATH GNMGraph::ConnectedComponents(const GNMVECTOR &anEmittersIDs)
+{
+    GNMPATH anConnectedIDs;
+
+    if(anEmittersIDs.empty())
+    {
+        CPLError( CE_Failure, CPLE_IllegalArg, "Emitters list is empty." );
+        return anConnectedIDs;
+    }
+    std::set<GNMGFID> anMarkedVertIDs;
+
+    std::queue<GNMGFID> anStartQueue;
+    GNMVECTOR::const_iterator it;
+    for (it = anEmittersIDs.begin(); it != anEmittersIDs.end(); ++it)
+    {
+        anStartQueue.push(*it);
+    }
+
+    // Begin the iterations of the Breadth-first search.
+    TraceTargets(anStartQueue, anMarkedVertIDs, anConnectedIDs);
+
+    return anConnectedIDs;
+}
+
+void GNMGraph::Clear()
+{
+    m_mstVertices.clear();
+    m_mstEdges.clear();
+}
+
+void GNMGraph::DijkstraShortestPathTree(GNMGFID nFID,
+                                   const std::map<GNMGFID, GNMStdEdge> &mstEdges,
+                                         std::map<GNMGFID, GNMGFID> &mnPathTree)
+{
+    // Initialize all vertexes in graph with infinity mark.
+    double dfInfinity = std::numeric_limits<double>::infinity();
+
+    std::map<GNMGFID, double> mMarks;
+    std::map<GNMGFID, GNMStdVertex>::iterator itv;
+    for (itv = m_mstVertices.begin(); itv != m_mstVertices.end(); ++itv)
+    {
+        mMarks[itv->first] = dfInfinity;
+    }
+
+    mMarks[nFID] = 0.0;
+    mnPathTree[nFID] = -1;
+
+    // Initialize all vertexes as unseen (there are no seen vertexes).
+    std::set<GNMGFID> snSeen;
+
+    // We use multimap to maintain the ascending order of costs and because
+    // there can be different vertexes with the equal cost.
+    std::multimap<double,GNMGFID> to_see;
+    std::multimap<double,GNMGFID>::iterator it;
+    to_see.insert(std::pair<double,GNMGFID>(0.0, nFID));
+    LPGNMCONSTVECTOR panOutcomeEdgeId;
+
+    size_t i;
+    GNMGFID nCurrenVertId, nCurrentEdgeId, nTargetVertId;
+    double dfCurrentEdgeCost, dfCurrentVertMark, dfNewVertexMark;
+    std::map<GNMGFID, GNMStdEdge>::const_iterator ite;
+
+    // Continue iterations while there are some vertexes to see.
+    while (!to_see.empty())
+    {
+        // We must see vertexes with minimal costs at first.
+        // In multimap the first cost is the minimal.
+        it = to_see.begin();
+
+        nCurrenVertId = it->second;
+        dfCurrentVertMark = it->first;
+        snSeen.insert(it->second);
+        to_see.erase(it);
+
+        // For all neighbours for the current vertex.
+        panOutcomeEdgeId = GetOutEdges(nCurrenVertId);
+        if(NULL == panOutcomeEdgeId)
+            continue;
+
+        for (i = 0; i < panOutcomeEdgeId->size(); ++i)
+        {
+            nCurrentEdgeId = panOutcomeEdgeId->operator[](i);
+
+            ite = mstEdges.find(nCurrentEdgeId);
+            if(ite == mstEdges.end() || ite->second.bIsBloked)
+                continue;
+
+            // We go in any edge from source to target so we take only
+            // direct cost (even if an edge is bi-directed).
+            dfCurrentEdgeCost = ite->second.dfDirCost;
+
+            // While we see outcome edges of current vertex id we definitely
+            // know that target vertex id will be target for current edge id.
+            nTargetVertId = GetOppositVertex(nCurrentEdgeId, nCurrenVertId);
+
+            // Calculate a new mark assuming the full path cost (mark of the
+            // current vertex) to this vertex.
+            dfNewVertexMark = dfCurrentVertMark + dfCurrentEdgeCost;
+
+            // Update mark of the vertex if needed.
+            if (snSeen.find(nTargetVertId) == snSeen.end() &&
+                    dfNewVertexMark < mMarks[nTargetVertId] &&
+                    !CheckVertexBlocked(nTargetVertId))
+            {
+                mMarks[nTargetVertId] = dfNewVertexMark;
+                mnPathTree[nTargetVertId] = nCurrentEdgeId;
+
+                // The vertex with minimal cost will be inserted to the
+                // beginning.
+                to_see.insert(std::pair<double,GNMGFID>(dfNewVertexMark,
+                                                        nTargetVertId));
+            }
+        }
+    }
+}
+
+LPGNMCONSTVECTOR GNMGraph::GetOutEdges(GNMGFID nFID) const
+{
+    std::map<GNMGFID,GNMStdVertex>::const_iterator it = m_mstVertices.find(nFID);
+    if (it != m_mstVertices.end())
+        return &it->second.anOutEdgeFIDs;
+    return NULL;
+}
+
+GNMGFID GNMGraph::GetOppositVertex(GNMGFID nEdgeFID, GNMGFID nVertexFID) const
+{
+    std::map<GNMGFID, GNMStdEdge>::const_iterator it = m_mstEdges.find(nEdgeFID);
+    if (it != m_mstEdges.end())
+    {
+        if (nVertexFID == it->second.nSrcVertexFID)
+        {
+            return it->second.nTgtVertexFID;
+        }
+        else if (nVertexFID == it->second.nTgtVertexFID)
+        {
+            return it->second.nSrcVertexFID;
+        }
+    }
+    return -1;
+}
+
+void GNMGraph::TraceTargets(std::queue<GNMGFID> &vertexQueue,
+                            std::set<GNMGFID> &markedVertIds,
+                            GNMPATH &connectedIds)
+{
+    GNMCONSTVECTOR::const_iterator it;
+    std::queue<GNMGFID> neighbours_queue;
+
+    // See all given vertexes except thouse that have been already seen.
+    while (!vertexQueue.empty())
+    {
+        GNMGFID nCurVertID = vertexQueue.front();
+
+        // There may be duplicate unmarked vertexes in a current queue. Check it.
+        if (markedVertIds.find(nCurVertID) == markedVertIds.end())
+        {
+            markedVertIds.insert(nCurVertID);
+
+            // See all outcome edges, add them to connected and than see the target
+            // vertex of each edge. Add it to the queue, which will be recursively
+            // seen the same way on the next iteration.
+            LPGNMCONSTVECTOR panOutcomeEdgeIDs = GetOutEdges(nCurVertID);
+            if(NULL != panOutcomeEdgeIDs)
+            {
+                for (it = panOutcomeEdgeIDs->begin(); it != panOutcomeEdgeIDs->end(); ++it)
+                {
+                    GNMGFID nCurEdgeID = *it;
+
+                    // ISSUE: think about to return a sequence of vertexes and edges
+                    // (which is more universal), as now we are going to return only
+                    // sequence of edges.
+                    connectedIds.push_back( std::make_pair(nCurVertID, nCurEdgeID) );
+
+                    // Get the only target vertex of this edge. If edge is bidirected
+                    // get not that vertex that with nCurVertID.
+                    GNMGFID nTargetVertID;
+                    /*
+                    std::vector<GNMGFID> target_vert_ids = _getTgtVert(cur_edge_id);
+                    std::vector<GNMGFID>::iterator itt;
+                    for (itt = target_vert_ids.begin(); itt != target_vert_ids.end(); ++itt)
+                    {
+                        if ((*itt) != cur_vert_id)
+                        {
+                            target_vert_id = *itt;
+                            break;
+                        }
+                    }
+                    */
+                    nTargetVertID = GetOppositVertex(nCurEdgeID, nCurVertID);
+
+                    // Avoid marked or blocked vertexes.
+                    if ((markedVertIds.find(nTargetVertID) == markedVertIds.end())
+                    && (!CheckVertexBlocked(nTargetVertID)))
+                        neighbours_queue.push(nTargetVertID);
+                }
+            }
+        }
+
+        vertexQueue.pop();
+    }
+
+    if (!neighbours_queue.empty())
+        TraceTargets(neighbours_queue, markedVertIds, connectedIds);
+}
diff --git a/gnm/gnmgraph.h b/gnm/gnmgraph.h
new file mode 100644
index 0000000..1795db0
--- /dev/null
+++ b/gnm/gnmgraph.h
@@ -0,0 +1,229 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
+ * Purpose:  GNM graph implementation.
+ * Authors:  Mikhail Gusev (gusevmihs at gmail dot com)
+ *           Dmitry Baryshnikov, polimax at mail.ru
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Mikhail Gusev
+ * Copyright (c) 2014-2015, NextGIS <info at nextgis.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gnm_priv.h"
+#include <vector>
+#include <queue>
+#include <set>
+
+// Types declarations.
+
+typedef std::vector<GNMGFID> GNMVECTOR, *LPGNMVECTOR;
+typedef const std::vector<GNMGFID> GNMCONSTVECTOR;
+typedef const std::vector<GNMGFID>* LPGNMCONSTVECTOR;
+typedef std::pair<GNMGFID,GNMGFID> EDGEVERTEXPAIR;
+typedef std::vector< EDGEVERTEXPAIR > GNMPATH;
+
+struct GNMStdEdge
+{
+    GNMGFID nSrcVertexFID;
+    GNMGFID nTgtVertexFID;
+    bool bIsBidir;
+    double dfDirCost;
+    double dfInvCost;
+    bool bIsBloked;
+};
+
+struct GNMStdVertex
+{
+    GNMVECTOR anOutEdgeFIDs;
+    bool bIsBloked;
+};
+
+/**
+ * The simple graph class, which holds the appropriate for
+ * calculations graph in memory (based on STL containers) and provides
+ * several basic algorithms of this graph's analysis. See the methods of
+ * this class for details. The common thing for all analysis methods is that
+ * all of them return the results in the array of GFIDs form. Use the
+ * GNMGraph class to receive the results in OGRLayer form.
+ * NOTE: GNMGraph holds the whole graph in memory, so it can consume
+ * a lot of memory if operating huge networks.
+ *
+ * @since GDAL 2.1
+ */
+
+class CPL_DLL GNMGraph
+{
+public:
+    GNMGraph();
+    virtual ~GNMGraph();
+
+    // GNMGraph
+
+    /**
+     * @brief Add a vertex to the graph
+     *
+     * NOTE: if there are vertices with these ID's already - nothing will be
+     * added.
+     *
+     * @param nFID - vertex identificator
+     */
+    virtual void AddVertex(GNMGFID nFID);
+
+    /**
+     * @brief Delete vertex from the graph
+     * @param nFID Vertex identificator
+     */
+    virtual void DeleteVertex(GNMGFID nFID);
+
+    /**
+     * @brief Add an edge to the graph
+     * @param nConFID Edge identificator
+     * @param nSrcFID Source vertex identificator
+     * @param nTgtFID Target vertex identificator
+     * @param bIsBidir Is bidirectional
+     * @param dfCost Cost
+     * @param dfInvCost Inverse cost
+     */
+    virtual void AddEdge(GNMGFID nConFID, GNMGFID nSrcFID, GNMGFID nTgtFID,
+                         bool bIsBidir, double dfCost, double dfInvCost);
+
+    /**
+     * @brief Delete edge from graph
+     * @param nConFID Edge identificator
+     */
+    virtual void DeleteEdge(GNMGFID nConFID);
+
+    /**
+     * @brief Change edge properties
+     * @param nConFID Edge identificator
+     * @param dfCost Cost
+     * @param dfInvCost Inverse cost
+     */
+    virtual void ChangeEdge(GNMGFID nFID, double dfCost, double dfInvCost);
+
+    /**
+     * @brief Change the block state of edge or vertex
+     * @param nFID Identificator
+     * @param bIsBlock Block or unblock
+     */
+    virtual void ChangeBlockState (GNMGFID nFID, bool bBlock);
+
+    /**
+     * @brief Check if vertex is blocked
+     * @param nFID Vertex identificator
+     * @return true if blocked, false if not blocked.
+     */
+    virtual bool CheckVertexBlocked(GNMGFID nFID) const;
+
+    /**
+     * @brief Change all vertices and edges block state.
+     *
+     * This is mainly use for unblock all vertices and edges.
+     *
+     * @param bIsBlock Block or unblock
+     */
+    virtual void ChangeAllBlockState (bool bBlock = false);
+
+    /**
+     * @brief An implementation of Dijkstra shortest path algorithm.
+     *
+     * Returns the best path between nStartFID and nEndFID features. Method
+     * uses @see DijkstraShortestPathTree and after that searches in
+     * the resulting tree the path from end to start point.
+     *
+     * @param nStartFID Start identificator
+     * @param nEndFID End identificator
+     * @return an array of best path included identificator of vertices and
+     * edges
+     */
+    virtual GNMPATH DijkstraShortestPath(GNMGFID nStartFID, GNMGFID nEndFID);
+
+    /**
+     * @brief An implementation of KShortest paths algorithm.
+     *
+     * Calculates several best paths between two points. Method takes in account
+     * the blocking state of features, i.e. the blocked features are the barriers
+     * during the routing process.
+     *
+     * @param nStartFID Vertex identificator from which to start paths calculating.
+     * @param nEndFID Vertex identificator to which the path will be calculated.
+     * @param nK How much best paths try to find between start and end points.
+     * @return an array of best paths. Each path is an array of pairs, where the
+     * first in a pair is a vertex identificator and the second is an edge
+     * identificator leading to this vertex. The elements in a path array are
+     * sorted by the path segments order, i.e. the first is the pair (nStartFID,
+     * -1) and the last is (nEndFID, <some edge>).
+     * If there is no any path between start and end vertex the returned array
+     * of paths will be empty. Also the actual amount of paths in the returned
+     * array can be less or equal than the nK parameter.
+     */
+    virtual std::vector<GNMPATH> KShortestPaths(GNMGFID nStartFID,
+                                                GNMGFID nEndFID, size_t nK);
+
+    /**
+     * @brief Search connected components of the network
+     *
+     * Returns the resource distribution in the network. Method search starting
+     * from the features identificators from input array. Uses the recursive
+     * Breadth-first search algorithm to find the connected to the given vector
+     * of GFIDs components. Method takes in account the blocking state of
+     * features, i.e. the blocked features are the barriers during the routing
+     * process.
+     *
+     * @param anEmittersIDs - array of emitters identificators
+     * @return an array of connected identificators
+     */
+    virtual GNMPATH ConnectedComponents(const GNMVECTOR &anEmittersIDs);
+
+    virtual void Clear();
+protected:
+    /**
+     * @brief Method to create best path tree.
+     *
+     * Calculates and builds the best path tree with the Dijkstra
+     * algorithm starting from the nFID. Method takes in account the blocking
+     * state of features, i.e. the blocked features are the barriers during the
+     * routing process.
+     *
+     * @param nFID - Vertex identificator from which to start tree building.
+     * @param mnPathTree - means < vertex id, edge id >
+     * @return std::map where the first is vertex identificator and the second
+     * is the edge identificator, which is the best way to the current vertex.
+     * The identificator to the start vertex is -1. If the vertex is isolated
+     * the returned map will be empty.
+     */
+    virtual void DijkstraShortestPathTree(GNMGFID nFID,
+                                  const std::map<GNMGFID, GNMStdEdge> &mstEdges,
+                                        std::map<GNMGFID, GNMGFID> &mnPathTree);
+    virtual GNMPATH DijkstraShortestPath(GNMGFID nStartFID, GNMGFID nEndFID,
+                                 const std::map<GNMGFID, GNMStdEdge> &mstEdges);
+
+    virtual LPGNMCONSTVECTOR GetOutEdges(GNMGFID nFID) const;
+    virtual GNMGFID GetOppositVertex(GNMGFID nEdgeFID, GNMGFID nVertexFID) const;
+    virtual void TraceTargets(std::queue<GNMGFID> &vertexQueue,
+                                std::set<GNMGFID> &markedVertIds,
+                                GNMPATH &connectedIds);
+protected:
+    std::map<GNMGFID, GNMStdVertex> m_mstVertices;
+    std::map<GNMGFID, GNMStdEdge>   m_mstEdges;
+};
diff --git a/gnm/gnmlayer.cpp b/gnm/gnmlayer.cpp
new file mode 100644
index 0000000..9663242
--- /dev/null
+++ b/gnm/gnmlayer.cpp
@@ -0,0 +1,367 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
+ * Purpose:  GNM layer class.
+ * Authors:  Mikhail Gusev (gusevmihs at gmail dot com)
+ *           Dmitry Baryshnikov, polimax at mail.ru
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Mikhail Gusev
+ * Copyright (c) 2014-2015, NextGIS <info at nextgis.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+#include "gnm.h"
+#include "gnm_priv.h"
+
+/**
+ * GNMGenericLayer
+ */
+GNMGenericLayer::GNMGenericLayer(OGRLayer* poLayer,
+                                 GNMGenericNetwork* poNetwork) : OGRLayer()
+{
+    m_poLayer = poLayer;
+    m_poNetwork = poNetwork;
+    m_soLayerName = poLayer->GetName();
+}
+
+/**
+ * ~GNMGenericLayer
+ */
+GNMGenericLayer::~GNMGenericLayer()
+{
+
+}
+
+const char *GNMGenericLayer::GetFIDColumn()
+{
+    return GNM_SYSFIELD_GFID;
+}
+
+const char *GNMGenericLayer::GetGeometryColumn()
+{
+    return m_poLayer->GetGeometryColumn();
+}
+
+OGRErr GNMGenericLayer::SetIgnoredFields(const char **papszFields)
+{
+    return m_poLayer->SetIgnoredFields(papszFields);
+}
+
+OGRErr GNMGenericLayer::Intersection(OGRLayer *pLayerMethod,
+                                     OGRLayer *pLayerResult,
+                                     char **papszOptions,
+                                     GDALProgressFunc pfnProgress,
+                                     void *pProgressArg)
+{
+    return m_poLayer->Intersection(pLayerMethod, pLayerResult, papszOptions,
+                                   pfnProgress, pProgressArg);
+}
+
+OGRErr GNMGenericLayer::Union(OGRLayer *pLayerMethod, OGRLayer *pLayerResult,
+                              char **papszOptions, GDALProgressFunc pfnProgress,
+                              void *pProgressArg)
+{
+    return m_poLayer->Union(pLayerMethod, pLayerResult, papszOptions,
+                                   pfnProgress, pProgressArg);
+}
+
+OGRErr GNMGenericLayer::SymDifference(OGRLayer *pLayerMethod,
+                                      OGRLayer *pLayerResult, char **papszOptions,
+                                      GDALProgressFunc pfnProgress, void *pProgressArg)
+{
+    return m_poLayer->Union(pLayerMethod, pLayerResult, papszOptions,
+                                   pfnProgress, pProgressArg);
+}
+
+OGRErr GNMGenericLayer::Identity(OGRLayer *pLayerMethod,
+                                 OGRLayer *pLayerResult, char **papszOptions,
+                                 GDALProgressFunc pfnProgress, void *pProgressArg)
+{
+    return m_poLayer->Union(pLayerMethod, pLayerResult, papszOptions,
+                                   pfnProgress, pProgressArg);
+}
+
+OGRErr GNMGenericLayer::Update(OGRLayer *pLayerMethod, OGRLayer *pLayerResult,
+                               char **papszOptions, GDALProgressFunc pfnProgress,
+                               void *pProgressArg)
+{
+    return m_poLayer->Update(pLayerMethod, pLayerResult, papszOptions,
+                                   pfnProgress, pProgressArg);
+}
+
+OGRErr GNMGenericLayer::Clip(OGRLayer *pLayerMethod, OGRLayer *pLayerResult,
+                             char **papszOptions, GDALProgressFunc pfnProgress,
+                             void *pProgressArg)
+{
+    return m_poLayer->Clip(pLayerMethod, pLayerResult, papszOptions,
+                                   pfnProgress, pProgressArg);
+}
+
+OGRErr GNMGenericLayer::Erase(OGRLayer *pLayerMethod, OGRLayer *pLayerResult,
+                              char **papszOptions, GDALProgressFunc pfnProgress,
+                              void *pProgressArg)
+{
+    return m_poLayer->Erase(pLayerMethod, pLayerResult, papszOptions,
+                                   pfnProgress, pProgressArg);
+}
+
+GIntBig GNMGenericLayer::GetFeaturesRead()
+{
+    return m_poLayer->GetFeaturesRead();
+}
+
+int GNMGenericLayer::AttributeFilterEvaluationNeedsGeometry()
+{
+    return m_poLayer->AttributeFilterEvaluationNeedsGeometry();
+}
+
+OGRErr GNMGenericLayer::InitializeIndexSupport(const char *pszVal)
+{
+    return m_poLayer->InitializeIndexSupport(pszVal);
+}
+
+OGRLayerAttrIndex *GNMGenericLayer::GetIndex()
+{
+    return m_poLayer->GetIndex();
+}
+
+OGRErr GNMGenericLayer::ISetFeature(OGRFeature *poFeature)
+{
+    VALIDATE_POINTER1(poFeature, "GNMGenericLayer::ISetFeature", CE_Failure);
+    std::map<GNMGFID, GIntBig>::iterator it = m_mnFIDMap.find(poFeature->GetFID());
+    if (it == m_mnFIDMap.end())
+    {
+        CPLError( CE_Failure, CPLE_IllegalArg, "The FID " CPL_FRMT_GIB " is invalid",
+                  poFeature->GetFID() );
+        return OGRERR_NON_EXISTING_FEATURE;
+    }
+
+    // TODO: check connection rules if feature can be changed.
+
+    poFeature->SetFID(it->second);
+    return m_poLayer->SetFeature(poFeature);
+}
+
+OGRErr GNMGenericLayer::ICreateFeature(OGRFeature *poFeature)
+{
+    VALIDATE_POINTER1(poFeature, "GNMGenericLayer::ICreateFeature", CE_Failure);
+    GNMGFID nFID = m_poNetwork->GetNewGlobalFID();
+    poFeature->SetFID(nFID);
+    poFeature->SetField(GNM_SYSFIELD_GFID, nFID);
+    poFeature->SetField(GNM_SYSFIELD_BLOCKED, GNM_BLOCK_NONE);
+    if(m_poNetwork->AddFeatureGlobalFID(nFID, GetName()) != CE_None)
+        return OGRERR_FAILURE;
+    return m_poLayer->CreateFeature(poFeature);
+}
+
+OGRGeometry *GNMGenericLayer::GetSpatialFilter()
+{
+    return m_poLayer->GetSpatialFilter();
+}
+
+void GNMGenericLayer::SetSpatialFilter(OGRGeometry *poGeometry)
+{
+    m_poLayer->SetSpatialFilter(poGeometry);
+}
+
+void GNMGenericLayer::SetSpatialFilterRect(double dfMinX, double dfMinY,
+                                           double dfMaxX, double dfMaxY)
+{
+    m_poLayer->SetSpatialFilterRect(dfMinX, dfMinY, dfMaxX, dfMaxY);
+}
+
+void GNMGenericLayer::SetSpatialFilter(int iGeomField, OGRGeometry *poGeometry)
+{
+    m_poLayer->SetSpatialFilter(iGeomField ,poGeometry);
+}
+
+void GNMGenericLayer::SetSpatialFilterRect(int iGeomField,
+                                           double dfMinX, double dfMinY,
+                                           double dfMaxX, double dfMaxY)
+{
+    m_poLayer->SetSpatialFilterRect(iGeomField, dfMinX, dfMinY, dfMaxX, dfMaxY);
+}
+
+OGRErr GNMGenericLayer::SetAttributeFilter(const char *pszFilter)
+{
+    return m_poLayer->SetAttributeFilter(pszFilter);
+}
+
+void GNMGenericLayer::ResetReading()
+{
+    m_poLayer->ResetReading();
+}
+
+OGRFeature *GNMGenericLayer::GetNextFeature()
+{
+    OGRFeature* pFeature = m_poLayer->GetNextFeature();
+    if(NULL == pFeature)
+        return NULL;
+    GNMGFID nGFID = pFeature->GetFieldAsGNMGFID(GNM_SYSFIELD_GFID);
+    m_mnFIDMap[nGFID] = pFeature->GetFID();
+    pFeature->SetFID(nGFID);
+    return pFeature;
+}
+
+OGRErr GNMGenericLayer::SetNextByIndex(GIntBig nIndex)
+{
+    return m_poLayer->SetNextByIndex(nIndex);
+}
+
+OGRErr GNMGenericLayer::DeleteFeature(GIntBig nFID)
+{
+    OGRFeature *poFeature = GetFeature(nFID);
+    if(NULL == poFeature)
+        return CE_Failure;
+
+    nFID = poFeature->GetFID();
+    std::map<GNMGFID, GIntBig>::iterator it = m_mnFIDMap.find(nFID);
+    if (it == m_mnFIDMap.end())
+    {
+        CPLError( CE_Failure, CPLE_IllegalArg, "The FID " CPL_FRMT_GIB " is invalid",
+                  nFID );
+        return OGRERR_NON_EXISTING_FEATURE;
+    }
+
+    OGRFeature::DestroyFeature(poFeature);
+
+    //delete from graph
+    if(m_poNetwork->DisconnectFeaturesWithId((GNMGFID)nFID) !=
+            CE_None)
+        return CE_Failure;
+
+    return m_poLayer->DeleteFeature(it->second);
+}
+
+const char *GNMGenericLayer::GetName()
+{
+    return m_soLayerName;
+}
+
+OGRwkbGeometryType GNMGenericLayer::GetGeomType()
+{
+    return m_poLayer->GetGeomType();
+}
+
+int GNMGenericLayer::FindFieldIndex(const char *pszFieldName, int bExactMatch)
+{
+    return m_poLayer->FindFieldIndex(pszFieldName, bExactMatch);
+}
+
+OGRSpatialReference *GNMGenericLayer::GetSpatialRef()
+{
+    return m_poLayer->GetSpatialRef();
+}
+
+GIntBig GNMGenericLayer::GetFeatureCount(int bForce)
+{
+    return m_poLayer->GetFeatureCount(bForce);
+}
+
+OGRErr GNMGenericLayer::GetExtent(OGREnvelope *psExtent, int bForce)
+{
+    return m_poLayer->GetExtent(psExtent, bForce);
+}
+
+OGRErr GNMGenericLayer::GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+{
+    return m_poLayer->GetExtent(iGeomField, psExtent, bForce);
+}
+
+int GNMGenericLayer::TestCapability(const char *pszCapability)
+{
+    return m_poLayer->TestCapability(pszCapability);
+}
+
+OGRErr GNMGenericLayer::CreateField(OGRFieldDefn *poField, int bApproxOK)
+{
+    return m_poLayer->CreateField(poField, bApproxOK);
+}
+
+OGRErr GNMGenericLayer::DeleteField(int iField)
+{
+    if(iField == FindFieldIndex(GNM_SYSFIELD_GFID, TRUE))
+        return OGRERR_UNSUPPORTED_OPERATION;
+    if(iField == FindFieldIndex(GNM_SYSFIELD_BLOCKED, TRUE))
+        return OGRERR_UNSUPPORTED_OPERATION;
+    return m_poLayer->DeleteField(iField);
+}
+
+OGRErr GNMGenericLayer::ReorderFields(int *panMap)
+{
+    return m_poLayer->ReorderFields(panMap);
+}
+
+OGRErr GNMGenericLayer::AlterFieldDefn(int iField, OGRFieldDefn *poNewFieldDefn, int nFlagsIn)
+{
+    if(iField == FindFieldIndex(GNM_SYSFIELD_GFID, TRUE))
+        return OGRERR_UNSUPPORTED_OPERATION;
+    if(iField == FindFieldIndex(GNM_SYSFIELD_BLOCKED, TRUE))
+        return OGRERR_UNSUPPORTED_OPERATION;
+    return m_poLayer->AlterFieldDefn(iField, poNewFieldDefn, nFlagsIn);
+}
+
+OGRErr GNMGenericLayer::CreateGeomField(OGRGeomFieldDefn *poField, int bApproxOK)
+{
+    return m_poLayer->CreateGeomField(poField, bApproxOK);
+}
+
+OGRErr GNMGenericLayer::SyncToDisk()
+{
+    return m_poLayer->SyncToDisk();
+}
+
+OGRStyleTable *GNMGenericLayer::GetStyleTable()
+{
+    return m_poLayer->GetStyleTable();
+}
+
+void GNMGenericLayer::SetStyleTableDirectly(OGRStyleTable *poStyleTable)
+{
+    return m_poLayer->SetStyleTableDirectly(poStyleTable);
+}
+
+void GNMGenericLayer::SetStyleTable(OGRStyleTable *poStyleTable)
+{
+    return m_poLayer->SetStyleTable(poStyleTable);
+}
+
+OGRErr GNMGenericLayer::StartTransaction()
+{
+    return m_poLayer->StartTransaction();
+}
+
+OGRErr GNMGenericLayer::CommitTransaction()
+{
+    return m_poLayer->CommitTransaction();
+}
+
+OGRErr GNMGenericLayer::RollbackTransaction()
+{
+    return m_poLayer->RollbackTransaction();
+}
+
+OGRFeatureDefn *GNMGenericLayer::GetLayerDefn()
+{
+    //TODO: hide GNM_SYSFIELD_GFID filed
+    return m_poLayer->GetLayerDefn();
+}
+
diff --git a/gnm/gnmnetwork.cpp b/gnm/gnmnetwork.cpp
new file mode 100644
index 0000000..7b41e4c
--- /dev/null
+++ b/gnm/gnmnetwork.cpp
@@ -0,0 +1,99 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
+ * Purpose:  GNM network class.
+ * Authors:  Mikhail Gusev (gusevmihs at gmail dot com)
+ *           Dmitry Baryshnikov, polimax at mail.ru
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Mikhail Gusev
+ * Copyright (c) 2014-2015, NextGIS <info at nextgis.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gnm_api.h"
+#include "ogrsf_frmts.h"
+
+GNMNetwork::GNMNetwork() : GDALDataset()
+{
+
+}
+
+GNMNetwork::~GNMNetwork()
+{
+
+}
+
+const char *GNMNetwork::GetName() const
+{
+    return m_soName;
+}
+
+const char *GNMNetwork::GetProjectionRef()
+{
+    return m_soSRS;
+}
+
+char **GNMNetwork::GetFileList()
+{
+    return NULL;
+}
+
+//--- C API --------------------------------------------------------------------
+
+const char* CPL_STDCALL GNMGetName (GNMNetworkH hNet)
+{
+    VALIDATE_POINTER1( hNet, "GNMGetVersion", NULL );
+
+    return ((GNMNetwork*)hNet)->GetName();
+}
+
+int CPL_STDCALL GNMGetVersion(GNMNetworkH hNet)
+{
+    VALIDATE_POINTER1( hNet, "GNMGetVersion", 0 );
+
+    return ((GNMNetwork*)hNet)->GetVersion();
+}
+
+CPLErr CPL_STDCALL GNMDisconnectAll (GNMNetworkH hNet)
+{
+    VALIDATE_POINTER1( hNet, "GNMDisconnectAll", CE_Failure );
+
+    return ((GNMNetwork*)hNet)->DisconnectAll();
+
+}
+
+OGRFeatureH CPL_STDCALL GNMGetFeatureByGlobalFID (GNMNetworkH hNet, GNMGFID nGFID)
+{
+    VALIDATE_POINTER1( hNet, "GNMGetFeatureByGlobalFID", NULL );
+
+    return (OGRFeatureH) ((GNMNetwork*)hNet)->GetFeatureByGlobalFID(nGFID);
+}
+
+OGRLayerH CPL_STDCALL GNMGetPath (GNMNetworkH hNet, GNMGFID nStartFID,
+                              GNMGFID nEndFID, GNMGraphAlgorithmType eAlgorithm,
+                              char** papszOptions)
+{
+    VALIDATE_POINTER1( hNet, "GNMGetPath", NULL );
+
+    return (OGRLayerH) ((GNMNetwork*)hNet)->GetPath(nStartFID, nEndFID,
+                                                    eAlgorithm, papszOptions);
+}
diff --git a/gnm/gnmresultlayer.cpp b/gnm/gnmresultlayer.cpp
new file mode 100644
index 0000000..989b719
--- /dev/null
+++ b/gnm/gnmresultlayer.cpp
@@ -0,0 +1,213 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
+ * Purpose:  GNM result layer class.
+ * Authors:  Mikhail Gusev (gusevmihs at gmail dot com)
+ *           Dmitry Baryshnikov, polimax at mail.ru
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Mikhail Gusev
+ * Copyright (c) 2014-2015, NextGIS <info at nextgis.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+#include "gnm.h"
+#include "gnm_priv.h"
+
+OGRGNMWrappedResultLayer::OGRGNMWrappedResultLayer(GDALDataset* poDSIn,
+                                                   OGRLayer* poLayerIn)
+{
+    this->poDS = poDSIn;
+    this->poLayer = poLayerIn;
+
+    //create standard fields
+
+    OGRFieldDefn oFieldGID(GNM_SYSFIELD_GFID, GNMGFIDInt);
+    poLayer->CreateField(&oFieldGID);
+
+    OGRFieldDefn oFieldLayerName(GNM_SYSFIELD_LAYERNAME, OFTString);
+    oFieldLayerName.SetWidth(254);
+    poLayer->CreateField(&oFieldLayerName);
+
+    OGRFieldDefn oFieldNo(GNM_SYSFIELD_PATHNUM, OFTInteger);
+    poLayer->CreateField(&oFieldNo);
+
+    OGRFieldDefn oFieldType(GNM_SYSFIELD_TYPE, OFTString); //EDGE or VERTEX
+    poLayer->CreateField(&oFieldType);
+}
+
+OGRGNMWrappedResultLayer::~OGRGNMWrappedResultLayer()
+{
+    delete poDS;
+}
+
+void OGRGNMWrappedResultLayer::ResetReading()
+{
+    poLayer->ResetReading();
+}
+
+OGRFeature *OGRGNMWrappedResultLayer::GetNextFeature()
+{
+    return poLayer->GetNextFeature();
+}
+
+OGRErr OGRGNMWrappedResultLayer::SetNextByIndex( GIntBig nIndex )
+{
+    return poLayer->SetNextByIndex(nIndex);
+}
+
+OGRFeature *OGRGNMWrappedResultLayer::GetFeature( GIntBig nFID )
+{
+    return poLayer->GetFeature(nFID);
+}
+
+OGRFeatureDefn *OGRGNMWrappedResultLayer::GetLayerDefn()
+{
+    return poLayer->GetLayerDefn();
+}
+
+GIntBig OGRGNMWrappedResultLayer::GetFeatureCount( int bForce )
+{
+    return poLayer->GetFeatureCount(bForce);
+}
+
+int OGRGNMWrappedResultLayer::TestCapability( const char * pszCap )
+{
+    return poLayer->TestCapability(pszCap);
+}
+
+OGRErr OGRGNMWrappedResultLayer::CreateField(OGRFieldDefn *poField, int bApproxOK)
+{
+    return poLayer->CreateField(poField, bApproxOK);
+}
+
+OGRErr OGRGNMWrappedResultLayer::CreateGeomField(OGRGeomFieldDefn *poField,
+                                                 int bApproxOK)
+{
+    return poLayer->CreateGeomField(poField, bApproxOK);
+}
+
+const char *OGRGNMWrappedResultLayer::GetFIDColumn()
+{
+    return poLayer->GetFIDColumn();
+}
+
+const char *OGRGNMWrappedResultLayer::GetGeometryColumn()
+{
+    return poLayer->GetGeometryColumn();
+}
+
+OGRSpatialReference *OGRGNMWrappedResultLayer::GetSpatialRef()
+{
+    return poLayer->GetSpatialRef();
+}
+
+OGRErr OGRGNMWrappedResultLayer::InsertFeature(OGRFeature *poFeature,
+                                              const CPLString &soLayerName,
+                                              int nPathNo, bool bIsEdge)
+{
+    VALIDATE_POINTER1(poFeature, "Input feature is invalid", OGRERR_INVALID_HANDLE);
+    // add fields from input feature
+    OGRFeatureDefn *poSrcDefn = poFeature->GetDefnRef();
+    OGRFeatureDefn* poDstFDefn = GetLayerDefn();
+    if(NULL == poSrcDefn || NULL == poDstFDefn)
+        return OGRERR_INVALID_HANDLE;
+
+    int nSrcFieldCount = poSrcDefn->GetFieldCount();
+    int nDstFieldCount = poDstFDefn->GetFieldCount();
+    int iField, *panMap;
+
+    // Initialize the index-to-index map to -1's
+    panMap = (int *) CPLMalloc( sizeof(int) * nSrcFieldCount );
+    for( iField = 0; iField < nSrcFieldCount; iField++)
+        panMap[iField] = -1;
+
+    for(iField = 0; iField < nSrcFieldCount; iField++)
+    {
+        OGRFieldDefn* poSrcFieldDefn = poSrcDefn->GetFieldDefn(iField);
+        OGRFieldDefn oFieldDefn( poSrcFieldDefn );
+
+        /* The field may have been already created at layer creation */
+        int iDstField = poDstFDefn->GetFieldIndex(oFieldDefn.GetNameRef());
+        if (iDstField >= 0)
+        {
+            // TODO: by now skip fields with different types. In future shoul
+            // cast types
+            OGRFieldDefn *poDstField = poDstFDefn->GetFieldDefn(iDstField);
+            if(NULL != poDstField && oFieldDefn.GetType() == poDstField->GetType())
+                panMap[iField] = iDstField;
+        }
+        else if (CreateField( &oFieldDefn ) == OGRERR_NONE)
+        {
+            /* Sanity check : if it fails, the driver is buggy */
+            if (poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "The output driver has claimed to have added the %s field, but it did not!",
+                         oFieldDefn.GetNameRef() );
+            }
+            else
+            {
+                panMap[iField] = nDstFieldCount;
+                nDstFieldCount ++;
+            }
+        }
+    }
+
+    OGRFeature* poInsertFeature = OGRFeature::CreateFeature( GetLayerDefn() );
+    if( poInsertFeature->SetFrom( poFeature, panMap, TRUE ) != OGRERR_NONE )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Unable to translate feature " CPL_FRMT_GIB
+                  " from layer %s.\n",
+                  poFeature->GetFID(), soLayerName.c_str() );
+        OGRFeature::DestroyFeature( poInsertFeature );
+        CPLFree(panMap);
+        return OGRERR_FAILURE;
+    }
+
+    //poInsertFeature->SetField( GNM_SYSFIELD_GFID, (GNMGFID)poFeature->GetFID() );
+    poInsertFeature->SetField( GNM_SYSFIELD_LAYERNAME, soLayerName);
+    poInsertFeature->SetField( GNM_SYSFIELD_PATHNUM, nPathNo);
+    poInsertFeature->SetField( GNM_SYSFIELD_TYPE, bIsEdge ? "EDGE" : "VERTEX");
+
+    CPLErrorReset();
+    if( CreateFeature( poInsertFeature ) != OGRERR_NONE )
+    {
+        OGRFeature::DestroyFeature( poInsertFeature );
+        CPLFree(panMap);
+        return OGRERR_FAILURE;
+    }
+
+    OGRFeature::DestroyFeature( poInsertFeature );
+    CPLFree(panMap);
+    return OGRERR_NONE;
+}
+
+OGRErr OGRGNMWrappedResultLayer::ISetFeature(OGRFeature *poFeature)
+{
+    return poLayer->SetFeature(poFeature);
+}
+
+OGRErr OGRGNMWrappedResultLayer::ICreateFeature(OGRFeature *poFeature)
+{
+    return poLayer->CreateFeature(poFeature);
+}
+
diff --git a/gnm/gnmrule.cpp b/gnm/gnmrule.cpp
new file mode 100644
index 0000000..e033885
--- /dev/null
+++ b/gnm/gnmrule.cpp
@@ -0,0 +1,189 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
+ * Purpose:  GNM rule class.
+ * Authors:  Mikhail Gusev (gusevmihs at gmail dot com)
+ *           Dmitry Baryshnikov, polimax at mail.ru
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Mikhail Gusev
+ * Copyright (c) 2014-2015, NextGIS <info at nextgis.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+#include "gnm.h"
+#include "gnm_priv.h"
+
+
+GNMRule::GNMRule()
+{
+    m_bValid = false;
+    m_bAllow = false;
+    m_bAny = false;
+}
+
+GNMRule::GNMRule(const std::string &oRule)
+{
+    m_soRuleString = oRule;
+    m_bValid = ParseRuleString();
+}
+
+GNMRule::GNMRule(const char *pszRule)
+{
+    m_soRuleString = pszRule;
+    m_bValid = ParseRuleString();
+}
+
+GNMRule::GNMRule(const GNMRule &oRule)
+{
+    m_soSrcLayerName = oRule.m_soSrcLayerName;
+    m_soTgtLayerName = oRule.m_soTgtLayerName;
+    m_soConnLayerName = oRule.m_soConnLayerName;
+    m_bAllow = oRule.m_bAllow;
+    m_bValid = oRule.m_bValid;
+    m_bAny = oRule.m_bAny;
+    m_soRuleString = oRule.m_soRuleString;
+}
+
+GNMRule::~GNMRule()
+{
+
+}
+
+bool GNMRule::IsValid() const
+{
+    return m_bValid;
+}
+
+bool GNMRule::IsAcceptAny() const
+{
+    return m_bAny;
+}
+
+GNMRuleType GNMRule::GetType() const
+{
+    return GRTConnection;
+}
+
+bool GNMRule::CanConnect(const CPLString &soSrcLayerName,
+                         const CPLString &soTgtLayerName,
+                         const CPLString &soConnLayerName)
+{
+    if(IsAcceptAny())
+        return m_bAllow;
+
+    if(m_soSrcLayerName == soSrcLayerName &&
+       m_soTgtLayerName == soTgtLayerName)
+    {
+        if(soConnLayerName.empty())
+            return m_bAllow;
+        else
+            return m_bAllow && m_soConnLayerName == soConnLayerName;
+    }
+
+    return false;
+}
+
+CPLString GNMRule::GetSourceLayerName() const
+{
+    return m_soSrcLayerName;
+}
+
+CPLString GNMRule::GetTargetLayerName() const
+{
+    return m_soTgtLayerName;
+}
+
+CPLString GNMRule::GetConnectorLayerName() const
+{
+    return m_soConnLayerName;
+}
+
+const char *GNMRule::c_str() const
+{
+    return m_soRuleString.c_str();
+}
+
+GNMRule::operator const char *() const
+{
+    return c_str();
+}
+
+bool GNMRule::ParseRuleString()
+{
+    CPLStringList aTokens (CSLTokenizeString2(m_soRuleString.c_str(), " ", CSLT_STRIPLEADSPACES |
+                                            CSLT_STRIPENDSPACES));
+
+    // the minimum rule consist 3 tokens
+    int nTokenCount = aTokens.Count();
+    if(nTokenCount < 3)
+    {
+        CPLError( CE_Failure, CPLE_IllegalArg, "Need more than %d tokens. Failed to parse rule: %s",
+                  nTokenCount, m_soRuleString.c_str() );
+        return false;
+    }
+
+    if(EQUAL(aTokens[0], GNM_RULEKW_ALLOW))
+        m_bAllow = true;
+    else if(EQUAL(aTokens[0], GNM_RULEKW_DENY))
+        m_bAllow = false;
+    else
+    {
+        CPLError( CE_Failure, CPLE_IllegalArg, "First token is invalid. Failed to parse rule: %s",
+                  m_soRuleString.c_str() );
+        return false;
+    }
+
+    // now just test if the value == connects
+    // in future shoult set rule type
+
+    if(!EQUAL(aTokens[1], GNM_RULEKW_CONNECTS))
+    {
+        CPLError( CE_Failure, CPLE_IllegalArg, "Not a CONNECTS rule. Failed to parse rule: %s",
+                  m_soRuleString.c_str() );
+        return false;
+    }
+
+    if(EQUAL(aTokens[2], GNM_RULEKW_ANY))
+    {
+        m_bAny = true;
+        return true;
+    }
+    else
+    {
+        if(nTokenCount < 5)
+        {
+            CPLError( CE_Failure, CPLE_IllegalArg, "Not an ANY rule, but have only %d tokens. Failed to parse rule: %s",
+                      nTokenCount, m_soRuleString.c_str() );
+            return false;
+        }
+        m_soSrcLayerName = aTokens[2];
+        m_soTgtLayerName = aTokens[4];
+    }
+
+    if(nTokenCount < 7) // skip 5 and 6 parameters
+        return true;
+    else
+        m_soConnLayerName = aTokens[6];
+
+    return true;
+}
+
+
diff --git a/gnm/makefile.vc b/gnm/makefile.vc
new file mode 100755
index 0000000..c5de34e
--- /dev/null
+++ b/gnm/makefile.vc
@@ -0,0 +1,40 @@
+
+EXTRAFLAGS =	-DWIN32 -I. -Iogrsf_frmts -Iogrsf_frmts\mem -I..\frmts\gtiff\libgeotiff -I..\frmts\zlib \
+		$(PROJ_FLAGS) $(PROJ_INCLUDE) $(GEOS_CFLAGS)
+
+GDAL_ROOT = 	..
+
+!INCLUDE ..\nmake.opt
+
+GNM_FRMTS =	gnm_frmts\gnm_frmts.lib
+OBJ_GNM	=	gnmnetwork.obj gnmgenericnetwork.obj gnmlayer.obj gnmrule.obj \
+            gnmresultlayer.obj gnmgraph.obj
+
+default:	gnm.lib
+
+gnm_frmts\gnm_frmts.lib:
+
+sublibs:	frmts
+
+frmts:
+	cd gnm_frmts
+	$(MAKE) /f makefile.vc
+	cd ..
+
+all:	frmts default
+
+gnm.lib:	$(OBJ_GNM)
+	lib /nologo /out:gnm.lib $(OBJ_GNM)
+
+install:	default
+
+clean:
+	-del *.obj
+	-del *.lib
+	-del *.pdb
+	-del *.ilk
+
+allclean:	clean
+	cd gnm_frmts
+	$(MAKE) /f makefile.vc clean
+	cd ..
diff --git a/ltmain.sh b/ltmain.sh
index 3061e3c..2ccb8f6 100644
--- a/ltmain.sh
+++ b/ltmain.sh
@@ -193,7 +193,7 @@ func_basename ()
 #             to NONDIR_REPLACEMENT.
 #             value returned in "$func_dirname_result"
 #   basename: Compute filename of FILE.
-#             value retuned in "$func_basename_result"
+#             value returned in "$func_basename_result"
 # Implementation must be kept synchronized with func_dirname
 # and func_basename. For efficiency, we do not delegate to
 # those functions but instead duplicate the functionality here.
@@ -4388,7 +4388,7 @@ EOF
         {
           /* however, if there is an option in the LTWRAPPER_OPTION_PREFIX
              namespace, but it is not one of the ones we know about and
-             have already dealt with, above (inluding dump-script), then
+             have already dealt with, above (including dump-script), then
              report an error. Otherwise, targets might begin to believe
              they are allowed to use options in the LTWRAPPER_OPTION_PREFIX
              namespace. The first time any user complains about this, we'll
@@ -7640,7 +7640,7 @@ func_mode_link ()
 	versuffix_save=$versuffix
 	major_save=$major
 	# I'm not sure if I'm treating the release correctly.  I think
-	# release should show up in the -l (ie -lgmp5) so we don't want to
+	# release should show up in the -l (i.e. -lgmp5) so we don't want to
 	# add it in twice.  Is that correct?
 	release=""
 	versuffix=""
diff --git a/m4/acinclude.m4 b/m4/acinclude.m4
index 167875d..38fa1c6 100644
--- a/m4/acinclude.m4
+++ b/m4/acinclude.m4
@@ -1,5 +1,5 @@
 dnl ***************************************************************************
-dnl $Id: acinclude.m4 28182 2014-12-20 19:53:13Z goatbar $
+dnl $Id: acinclude.m4 31826 2015-11-29 15:39:57Z goatbar $
 dnl
 dnl Project:  GDAL
 dnl Purpose:  Configure extra local definitions.
@@ -62,12 +62,12 @@ void test_f()
 # AC_CHECK_FUNC_CUSTOM(FUNCTION, [INCLUDE], [CODE], 
 #                      [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
 # -----------------------------------------------------------------
-# This function is primariliy added to facilite testing that 
+# This function is primarily added to facilitate testing that 
 # function prototypes are properly found such that functions can
 # be compiled properly in C++.  In particular, we want to include
 # the real include file, not internal define prototypes. 
 #
-# eg.
+# e.g.
 # AC_LANG_PUSH(C++)
 # AC_CHECK_FUNC_CUSTOM(gmtime_r,[#include <time.h>],[time_t t; struct tm ltime; t = time(0); gmtime_r( &t, &ltime );])
 # AC_LANG_POP(C++)
diff --git a/m4/ax_cflags_warn_all.m4 b/m4/ax_cflags_warn_all.m4
index ae0e7ef..976ae9e 100644
--- a/m4/ax_cflags_warn_all.m4
+++ b/m4/ax_cflags_warn_all.m4
@@ -117,4 +117,4 @@ dnl   compilers will fail about it. That was needed since a lot of
 dnl   compilers will give false positives for some option-syntax
 dnl   like -Woption or -Xoption as they think of it is a pass-through
 dnl   to later compile stages or something. The "%" is used as a
-dnl   delimimiter. A non-option comment can be given after "%%" marks.
+dnl   delimiter. A non-option comment can be given after "%%" marks.
diff --git a/m4/ax_check_compile_flag.m4 b/m4/ax_check_compile_flag.m4
new file mode 100644
index 0000000..ca36397
--- /dev/null
+++ b/m4/ax_check_compile_flag.m4
@@ -0,0 +1,74 @@
+# ===========================================================================
+#   http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
+#
+# DESCRIPTION
+#
+#   Check whether the given FLAG works with the current language's compiler
+#   or gives an error.  (Warnings, however, are ignored)
+#
+#   ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
+#   success/failure.
+#
+#   If EXTRA-FLAGS is defined, it is added to the current language's default
+#   flags (e.g. CFLAGS) when the check is done.  The check is thus made with
+#   the flags: "CFLAGS EXTRA-FLAGS FLAG".  This can for example be used to
+#   force the compiler to issue an error when a bad flag is given.
+#
+#   INPUT gives an alternative input source to AC_COMPILE_IFELSE.
+#
+#   NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
+#   macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Guido U. Draheim <guidod at gmx.de>
+#   Copyright (c) 2011 Maarten Bosmans <mkbosmans at gmail.com>
+#
+#   This program is free software: you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation, either version 3 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+#serial 4
+
+AC_DEFUN([AX_CHECK_COMPILE_FLAG],
+[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
+AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
+AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
+  ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
+  _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
+  AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
+    [AS_VAR_SET(CACHEVAR,[yes])],
+    [AS_VAR_SET(CACHEVAR,[no])])
+  _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
+AS_VAR_IF(CACHEVAR,yes,
+  [m4_default([$2], :)],
+  [m4_default([$3], :)])
+AS_VAR_POPDEF([CACHEVAR])dnl
+])dnl AX_CHECK_COMPILE_FLAGS
diff --git a/m4/ax_lib_libkml.m4 b/m4/ax_lib_libkml.m4
index 0c92e75..f26a1dc 100644
--- a/m4/ax_lib_libkml.m4
+++ b/m4/ax_lib_libkml.m4
@@ -1,4 +1,4 @@
-dnl $Id: ax_lib_libkml.m4 30555 2015-09-19 11:47:36Z rouault $
+dnl $Id: ax_lib_libkml.m4 29715 2015-08-21 17:46:02Z rouault $
 dnl
 dnl @synopsis AX_LIB_LIBKML([MINIMUM-VERSION])
 dnl
@@ -39,7 +39,7 @@ dnl
 dnl @category InstalledPackages
 dnl @category Cxx
 dnl @author Mateusz Loskot <mateusz at loskot.net>
-dnl @version $Date: 2015-09-19 04:47:36 -0700 (Sat, 19 Sep 2015) $
+dnl @version $Date: 2015-08-21 10:46:02 -0700 (Fri, 21 Aug 2015) $
 dnl @license AllPermissive
 dnl          Copying and distribution of this file, with or without modification,
 dnl          are permitted in any medium without royalty provided the copyright notice and
diff --git a/m4/ax_lib_sqlite3.m4 b/m4/ax_lib_sqlite3.m4
index b5fb956..2c3e688 100644
--- a/m4/ax_lib_sqlite3.m4
+++ b/m4/ax_lib_sqlite3.m4
@@ -1,4 +1,4 @@
-dnl $Id: ax_lib_sqlite3.m4 18833 2010-02-14 19:27:53Z rouault $
+dnl $Id: ax_lib_sqlite3.m4 32092 2015-12-08 14:54:56Z goatbar $
 dnl
 dnl @synopsis AX_LIB_SQLITE3([MINIMUM-VERSION])
 dnl 
@@ -6,9 +6,9 @@ dnl Test for the SQLite 3 library of a particular version (or newer)
 dnl
 dnl This macro takes only one optional argument, required version
 dnl of SQLite 3 library. If required version is not passed,
-dnl 3.0.0 is used in the test of existance of SQLite 3.
+dnl 3.0.0 is used in the test of existence of SQLite 3.
 dnl
-dnl If no intallation prefix to the installed SQLite library is given
+dnl If no installation prefix to the installed SQLite library is given
 dnl the macro searches under /usr, /usr/local, and /opt.
 dnl
 dnl This macro calls:
@@ -24,10 +24,10 @@ dnl
 dnl @category InstalledPackages
 dnl @category Cxx
 dnl @author Mateusz Loskot <mateusz at loskot.net>
-dnl @version $Date: 2010-02-14 11:27:53 -0800 (Sun, 14 Feb 2010) $
+dnl @version $Date: 2015-12-08 06:54:56 -0800 (Tue, 08 Dec 2015) $
 dnl @license AllPermissive
 dnl
-dnl $Id: ax_lib_sqlite3.m4 18833 2010-02-14 19:27:53Z rouault $
+dnl $Id: ax_lib_sqlite3.m4 32092 2015-12-08 14:54:56Z goatbar $
 dnl
 AC_DEFUN([AX_LIB_SQLITE3],
 [
@@ -149,7 +149,7 @@ AC_DEFUN([AX_LIB_SQLITE3],
             [
             AC_MSG_RESULT([not found])
             HAVE_SQLITE3="no"
-            succees="no"
+            success="no"
             ]
         )
         AC_LANG_POP([C++])
diff --git a/m4/lib-link.m4 b/m4/lib-link.m4
index e3d26fc..9bdaffa 100644
--- a/m4/lib-link.m4
+++ b/m4/lib-link.m4
@@ -173,7 +173,7 @@ AC_DEFUN([AC_LIB_LINKFLAGS_BODY],
     fi
 ])
   dnl Search the library and its dependencies in $additional_libdir and
-  dnl $LDFLAGS. Using breadth-first-seach.
+  dnl $LDFLAGS. Using breadth-first-search.
   LIB[]NAME=
   LTLIB[]NAME=
   INC[]NAME=
diff --git a/m4/libtool.m4 b/m4/libtool.m4
index d812584..26205a9 100644
--- a/m4/libtool.m4
+++ b/m4/libtool.m4
@@ -639,7 +639,7 @@ configured by $[0], generated by m4_PACKAGE_STRING.
 
 Copyright (C) 2010 Free Software Foundation, Inc.
 This config.lt script is free software; the Free Software Foundation
-gives unlimited permision to copy, distribute and modify it."
+gives unlimited permission to copy, distribute and modify it."
 
 while test $[#] != 0
 do
@@ -763,7 +763,7 @@ _LT_EOF
 [cat <<_LT_EOF >> "$ofile"
 
 dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded
-dnl in a comment (ie after a #).
+dnl in a comment (i.e. after a #).
 # ### BEGIN LIBTOOL TAG CONFIG: $1
 _LT_LIBTOOL_TAG_VARS(_LT_TAG)
 # ### END LIBTOOL TAG CONFIG: $1
@@ -1562,10 +1562,10 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
   cygwin* | mingw* | cegcc*)
     # On Win9x/ME, this test blows up -- it succeeds, but takes
     # about 5 minutes as the teststring grows exponentially.
-    # Worse, since 9x/ME are not pre-emptively multitasking,
+    # Worse, since 9x/ME are not preemptively multitasking,
     # you end up with a "frozen" computer, even though with patience
     # the test eventually succeeds (with a max line length of 256k).
-    # Instead, let's just punt: use the minimum linelength reported by
+    # Instead, let's just punt: use the minimum line length reported by
     # all of the supported platforms: 8192 (on NT/2K/XP).
     lt_cv_sys_max_cmd_len=8192;
     ;;
@@ -1732,7 +1732,7 @@ else
 #  endif
 #endif
 
-/* When -fvisbility=hidden is used, assume the code has been annotated
+/* When -fvisibility=hidden is used, assume the code has been annotated
    correspondingly for the symbols needed.  */
 #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
 int fnord () __attribute__((visibility("default")));
@@ -4548,7 +4548,7 @@ dnl Note also adjust exclude_expsyms for C++ above.
 
   case $host_os in
   cygwin* | mingw* | pw32* | cegcc*)
-    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # FIXME: the MSVC++ port hasn't been tested in a long time
     # When not using gcc, we currently assume that we are using
     # Microsoft Visual C++.
     if test "$GCC" != yes; then
diff --git a/m4/pkg.m4 b/m4/pkg.m4
index 0048a3f..452488c 100644
--- a/m4/pkg.m4
+++ b/m4/pkg.m4
@@ -1,4 +1,4 @@
-# pkg.m4 - Macros to locate and utilise pkg-config.            -*- Autoconf -*-
+# pkg.m4 - Macros to locate and utilize pkg-config.            -*- Autoconf -*-
 # 
 # Copyright © 2004 Scott James Remnant <scott at netsplit.com>.
 #
diff --git a/makefile.vc b/makefile.vc
index d49359a..129ed93 100644
--- a/makefile.vc
+++ b/makefile.vc
@@ -15,13 +15,11 @@ VB6_TARGET = vb6_dir
 # for a raster-gdal build.
 
 #OGR_BASE_INCLUDE = /INCLUDE:_OCTNewCoordinateTransformation at 8 \
-#		/INCLUDE:_OGRFeatureStylePuller at 0 \
 #		/INCLUDE:_OSRValidate at 4 \
 #		/INCLUDE:_OPTGetProjectionMethods at 0 \
 #		/INCLUDE:_OGR_G_GetPointCount at 4
 
-OGR_BASE_INCLUDE = /INCLUDE:$(SYM_PREFIX)OGRFeatureStylePuller \
-		/INCLUDE:$(SYM_PREFIX)OSRValidate \
+OGR_BASE_INCLUDE = /INCLUDE:$(SYM_PREFIX)OSRValidate \
 		/INCLUDE:$(SYM_PREFIX)OPTGetProjectionMethods \
 		/INCLUDE:$(SYM_PREFIX)OGR_G_GetPointCount 
 
@@ -31,6 +29,10 @@ OGR_OBJ = ogr\ogrsf_frmts\ogrsf_frmts.lib ogr\ogr.lib
 OGR_INCLUDE = $(OGR_BASE_INCLUDE) \
 		/INCLUDE:$(SYM_PREFIX)OGRRegisterAll
 
+!IFDEF INCLUDE_GNM_FRMTS        
+CPPFLAGS = $(CPPFLAGS) -DGNM_ENABLED        
+!ENDIF
+
 !IF DEFINED(STDCALL) && !DEFINED(WIN64)
 
 !IF $(MSVC_VER) < 1500
@@ -50,18 +52,25 @@ BASE_INCLUDE =	/INCLUDE:$(SYM_PREFIX)GDALSimpleImageWarp \
 		/INCLUDE:$(SYM_PREFIX)OCTNewCoordinateTransformation
 !ENDIF
 
-LIBOBJ = port\*.obj gcore\*.obj alg\*.obj frmts\o\*.obj $(OGR_OBJ) $(VB6_OBJ)
+LIBOBJ = port\*.obj gcore\*.obj alg\*.obj frmts\o\*.obj $(OGR_OBJ) gnm\*.obj gnm\gnm_frmts\o\*.obj $(VB6_OBJ) \
+	 apps\commonutils.obj apps\gdalinfo_lib.obj apps\gdal_translate_lib.obj apps\gdalwarp_lib.obj apps\ogr2ogr_lib.obj \
+	 apps\gdaldem_lib.obj apps\nearblack_lib.obj apps\gdal_grid_lib.obj apps\gdal_rasterize_lib.obj apps\gdalbuildvrt_lib.obj
 	
 DISTDIR	=	gdal_$(VERSION)
 
-default:	port_dir ogr_dir core_dir frmts_dir $(VB6_TARGET) $(GDAL_DLL) \
+default:	port_dir ogr_dir gnm_dir core_dir frmts_dir appslib-target $(VB6_TARGET)$(GDAL_DLL) \
 		plugin_dir apps_dir 
 
 staticlib:
 	if exist gdal.lib del gdal.lib
 	lib /nologo /out:gdal.lib $(LIBOBJ)
 
-target-lib: port_dir ogr_dir core_dir frmts_dir dll
+appslib-target:
+	cd apps
+	$(MAKE) /f makefile.vc appslib
+	cd ..	
+
+target-lib: port_dir ogr_dir gnm_dir core_dir frmts_dir appslib-target dll 
 
 clean:	
 	cd port
@@ -79,6 +88,9 @@ clean:
 	cd ogr
 	$(MAKE) /f makefile.vc allclean
 	cd ..
+    cd gnm
+	$(MAKE) /f makefile.vc allclean
+	cd ..
 	cd apps
 	$(MAKE) /f makefile.vc clean
 	cd ..
@@ -146,6 +158,11 @@ ogr_dir:      port_dir
 	$(MAKE) /f makefile.vc ogr.lib frmts
 	cd ..
 
+gnm_dir:      ogr_dir
+    cd gnm
+    $(MAKE) /f makefile.vc gnm.lib frmts
+    cd ..
+
 lib_dist:	default
 	rm -rf $(DISTDIR)
 	mkdir $(DISTDIR)
@@ -188,6 +205,11 @@ install: $(GDAL_DLL) plugin_dir apps_dir
 !ENDIF
 	cd ..\..
 !ENDIF
+!IFDEF INCLUDE_GNM_FRMTS
+    cd gnm
+    $(MAKE) /f makefile.vc install
+    cd ..
+!ENDIF
 
 devinstall: install
 	-mkdir $(INCDIR)
@@ -202,5 +224,9 @@ devinstall: install
 !IFDEF INCLUDE_OGR_FRMTS
 	copy ogr\ogrsf_frmts\*.h $(INCDIR)
 !ENDIF
+!IFDEF INCLUDE_GNM_FRMTS
+	copy gnm\*.h $(INCDIR)
+!ENDIF
+	copy apps\gdal_utils.h $(INCDIR)
 	copy gdal_i.lib $(LIBDIR)
 
diff --git a/makegdal_gen.bat b/makegdal_gen.bat
index 2667358..97d7886 100644
--- a/makegdal_gen.bat
+++ b/makegdal_gen.bat
@@ -45,7 +45,7 @@ if "%1"=="" (
 )
 
 ::  *********************
-::  Get plataform 32 or 64
+::  Get platform 32 or 64
 ::  *********************
 
 set _plat_=%2
@@ -171,7 +171,7 @@ goto :end
     ::  stop folders
     ::  *********************
     
-    for %%d in (data debian dist_docs docs html m4 pymod swig vb6) do (
+    for %%d in (data debian docs html m4 pymod swig vb6) do (
         if "%_name_%"=="%%d" (
             goto :end
         )
diff --git a/man/man1/_home_rouault_dist_wrk_gdal_apps_.1 b/man/man1/_home_rouault_dist_wrk_gdal_apps_.1
index a65998c..20ac4ac 100644
--- a/man/man1/_home_rouault_dist_wrk_gdal_apps_.1
+++ b/man/man1/_home_rouault_dist_wrk_gdal_apps_.1
@@ -1,4 +1,4 @@
-.TH "apps Directory Reference" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "apps Directory Reference" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -19,13 +19,22 @@ apps Directory Reference \-
 .RI "file \fBgdal_contour\&.cpp\fP"
 .br
 .ti -1c
-.RI "file \fBgdal_grid\&.cpp\fP"
+.RI "file \fBgdal_grid_bin\&.cpp\fP"
 .br
 .ti -1c
-.RI "file \fBgdal_rasterize\&.cpp\fP"
+.RI "file \fBgdal_grid_lib\&.cpp\fP"
 .br
 .ti -1c
-.RI "file \fBgdal_translate\&.cpp\fP"
+.RI "file \fBgdal_rasterize_bin\&.cpp\fP"
+.br
+.ti -1c
+.RI "file \fBgdal_rasterize_lib\&.cpp\fP"
+.br
+.ti -1c
+.RI "file \fBgdal_translate_bin\&.cpp\fP"
+.br
+.ti -1c
+.RI "file \fBgdal_translate_lib\&.cpp\fP"
 .br
 .ti -1c
 .RI "file \fBgdaladdo\&.cpp\fP"
@@ -34,15 +43,27 @@ apps Directory Reference \-
 .RI "file \fBgdalasyncread\&.cpp\fP"
 .br
 .ti -1c
-.RI "file \fBgdalbuildvrt\&.cpp\fP"
+.RI "file \fBgdalbuildvrt_bin\&.cpp\fP"
 .br
 .ti -1c
-.RI "file \fBgdaldem\&.cpp\fP"
+.RI "file \fBgdalbuildvrt_lib\&.cpp\fP"
+.br
+.ti -1c
+.RI "file \fBgdaldem_bin\&.cpp\fP"
+.br
+.ti -1c
+.RI "file \fBgdaldem_lib\&.cpp\fP"
 .br
 .ti -1c
 .RI "file \fBgdalenhance\&.cpp\fP"
 .br
 .ti -1c
+.RI "file \fBgdalinfo_bin\&.cpp\fP"
+.br
+.ti -1c
+.RI "file \fBgdalinfo_lib\&.cpp\fP"
+.br
+.ti -1c
 .RI "file \fBgdallocationinfo\&.cpp\fP"
 .br
 .ti -1c
@@ -58,16 +79,31 @@ apps Directory Reference \-
 .RI "file \fBgdaltransform\&.cpp\fP"
 .br
 .ti -1c
-.RI "file \fBgdalwarp\&.cpp\fP"
+.RI "file \fBgdalwarp_bin\&.cpp\fP"
+.br
+.ti -1c
+.RI "file \fBgdalwarp_lib\&.cpp\fP"
+.br
+.ti -1c
+.RI "file \fBgnmanalyse\&.cpp\fP"
+.br
+.ti -1c
+.RI "file \fBgnmmanage\&.cpp\fP"
 .br
 .ti -1c
 .RI "file \fBmultireadtest\&.cpp\fP"
 .br
 .ti -1c
-.RI "file \fBnearblack\&.cpp\fP"
+.RI "file \fBnearblack_bin\&.cpp\fP"
+.br
+.ti -1c
+.RI "file \fBnearblack_lib\&.cpp\fP"
+.br
+.ti -1c
+.RI "file \fBogr2ogr_bin\&.cpp\fP"
 .br
 .ti -1c
-.RI "file \fBogr2ogr\&.cpp\fP"
+.RI "file \fBogr2ogr_lib\&.cpp\fP"
 .br
 .ti -1c
 .RI "file \fBogrdissolve\&.cpp\fP"
diff --git a/man/man1/gdal-config.1 b/man/man1/gdal-config.1
index 77db0a1..3a674ae 100644
--- a/man/man1/gdal-config.1
+++ b/man/man1/gdal-config.1
@@ -1,4 +1,4 @@
-.TH "gdal-config" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal-config" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal2tiles.1 b/man/man1/gdal2tiles.1
index e429065..b08a25a 100644
--- a/man/man1/gdal2tiles.1
+++ b/man/man1/gdal2tiles.1
@@ -1,4 +1,4 @@
-.TH "gdal2tiles" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal2tiles" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -9,14 +9,14 @@ generates directory with TMS tiles, KMLs and simple web viewers
 .PP
 .nf
 gdal2tiles.py [-p profile] [-r resampling] [-s srs] [-z zoom]
-              [-e] [-a nodata] [-v] [-h] [-k] [-n] [-u url]
+              [-e] [-a nodata] [-v] [-q] [-h] [-k] [-n] [-u url]
               [-w webviewer] [-t title] [-c copyright]
               [-g googlekey] [-b bingkey] input_file [output_dir]
 .fi
 .PP
 .SH "DESCRIPTION"
 .PP
-This utility generates a directory with small tiles and metadata, following the OSGeo Tile Map Service Specification\&. Simple web pages with viewers based on Google Maps and OpenLayers are generated as well - so anybody can comfortably explore your maps on-line and you do not need to install or configure any special software (like MapServer) and the map displays very fast in the web browser\&. You only need to upload the generated directory onto a web server\&.
+This utility generates a directory with small tiles and metadata, following the OSGeo Tile Map Service Specification\&. Simple web pages with viewers based on Google Maps, OpenLayers and Leaflet are generated as well - so anybody can comfortably explore your maps on-line and you do not need to install or configure any special software (like MapServer) and the map displays very fast in the web browser\&. You only need to upload the generated directory onto a web server\&.
 .PP
 GDAL2Tiles also creates the necessary metadata for Google Earth (KML SuperOverlay), in case the supplied map uses EPSG:4326 projection\&.
 .PP
@@ -36,6 +36,8 @@ Resume mode\&. Generate only missing files\&.
 NODATA transparency value to assign to the input data\&. 
 .IP "\fB\fB-v, --verbose\fP \fP" 1c
 Generate verbose output of tile generation\&. 
+.IP "\fB\fB-q, --quiet\fP \fP" 1c
+Disable messages and status to stdout (GDAL >= 2\&.1)\&. 
 .IP "\fB\fB-h, --help\fP \fP" 1c
 Show help message and exit\&. 
 .IP "\fB\fB--version\fP \fP" 1c
@@ -57,7 +59,7 @@ URL address where the generated tiles are going to be published\&.
 .PP
 Options for generated HTML viewers a la Google Maps 
 .IP "\fB\fB-w\fP \fIWEBVIEWER\fP, --webviewer=\fIWEBVIEWER\fP: \fP" 1c
-Web viewer to generate (all,google,openlayers,none) - default 'all'\&. 
+Web viewer to generate (all,google,openlayers,leaflet,none) - default 'all'\&. 
 .IP "\fB\fB-t\fP \fITITLE\fP, --title=\fITITLE\fP: \fP" 1c
 Title of the map\&. 
 .IP "\fB\fB-c\fP \fICOPYRIGHT\fP, --copyright=\fICOPYRIGHT\fP: \fP" 1c
diff --git a/man/man1/gdal_calc.1 b/man/man1/gdal_calc.1
index 8d8ca6d..66381bf 100644
--- a/man/man1/gdal_calc.1
+++ b/man/man1/gdal_calc.1
@@ -1,4 +1,4 @@
-.TH "gdal_calc" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_calc" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_contour.1 b/man/man1/gdal_contour.1
index 3cfe32c..a4c4ad1 100644
--- a/man/man1/gdal_contour.1
+++ b/man/man1/gdal_contour.1
@@ -1,4 +1,4 @@
-.TH "gdal_contour" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_contour" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -55,6 +55,9 @@ Name one or more 'fixed levels' to extract\&.
 .IP "\fB\fB-nln\fP \fIoutlayername\fP: \fP" 1c
 Provide a name for the output vector layer\&. Defaults to 'contour'\&. 
 .PP
+.SH "C API"
+.PP
+Functionality of this utility can be done from C with GDALContourGenerate()\&.
 .SH "EXAMPLE"
 .PP
 This would create 10meter contours from the DEM data in dem\&.tif and produce a shapefile in contour\&.shp/shx/dbf with the contour elevations in the 'elev' attribute\&.
diff --git a/man/man1/gdal_edit.1 b/man/man1/gdal_edit.1
index 115c65a..f7b1f10 100644
--- a/man/man1/gdal_edit.1
+++ b/man/man1/gdal_edit.1
@@ -1,4 +1,4 @@
-.TH "gdal_edit" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_edit" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -9,7 +9,7 @@ Edit in place various information of an existing GDAL dataset
 .PP
 .nf
 gdal_edit [--help-general] [-ro] [-a_srs srs_def] [-a_ullr ulx uly lrx lry]
-          [-tr xres yres] [-unsetgt] [-a_nodata value]
+          [-tr xres yres] [-unsetgt] [-a_nodata value] [-unsetnodata]
           [-unsetstats] [-stats] [-approx_stats]
           [-gcp pixel line easting northing [elevation]]*
           [-unsetmd] [-oo NAME=VALUE]* [-mo "META-TAG=VALUE"]*  datasetname
@@ -51,6 +51,9 @@ Remove the georeference information\&.
 .IP "\fB\fB-a_nodata\fP \fIvalue\fP:\fP" 1c
 Assign a specified nodata value to output bands\&.
 .PP
+.IP "\fB\fB-unsetnodata\fP:\fP" 1c
+(GDAL >= 2\&.1) Remove existing nodata values\&.
+.PP
 .IP "\fB\fB-gcp\fP \fIpixel line easting northing [elevation]\fP:\fP" 1c
 Add the indicated ground control point to the dataset\&. This option may be provided multiple times to provide a set of GCPs\&. 
 .PP
diff --git a/man/man1/gdal_fillnodata.1 b/man/man1/gdal_fillnodata.1
index 748814b..7268ade 100644
--- a/man/man1/gdal_fillnodata.1
+++ b/man/man1/gdal_fillnodata.1
@@ -1,4 +1,4 @@
-.TH "gdal_fillnodata" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_fillnodata" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_grid.1 b/man/man1/gdal_grid.1
index 912f554..fa92ce3 100644
--- a/man/man1/gdal_grid.1
+++ b/man/man1/gdal_grid.1
@@ -1,4 +1,4 @@
-.TH "gdal_grid" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_grid" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -118,6 +118,20 @@ Minimum number of data points to use\&. If less amount of points found the grid
 .IP "\fB\fInodata\fP: \fP" 1c
 NODATA marker to fill empty points (default 0\&.0)\&. 
 .PP
+.SS "invdistnn"
+(Since GDAL 2\&.1) Inverse distance to a power with nearest neighbor searching, ideal when max_points is used\&. It has following parameters:
+.PP
+.IP "\fB\fIpower\fP: \fP" 1c
+Weighting power (default 2\&.0)\&. 
+.IP "\fB\fIradius\fP: \fP" 1c
+The radius of the search circle, which should be non-zero\&. Default is 1\&.0\&. 
+.IP "\fB\fImax_points\fP: \fP" 1c
+Maximum number of data points to use\&. Do not search for more points than this number\&. Found points will be ranked from nearest to furthest distance when weighting\&. Default is 12\&. 
+.IP "\fB\fImin_points\fP: \fP" 1c
+Minimum number of data points to use\&. If less amount of points found the grid node is considered empty and will be filled with NODATA marker\&. Default is 0\&. 
+.IP "\fB\fInodata\fP: \fP" 1c
+NODATA marker to fill empty points (default 0\&.0)\&. 
+.PP
 .SS "average"
 Moving average algorithm\&. It has following parameters:
 .PP
@@ -146,6 +160,18 @@ Angle of search ellipse rotation in degrees (counter clockwise, default 0\&.0)\&
 .IP "\fB\fInodata\fP: \fP" 1c
 NODATA marker to fill empty points (default 0\&.0)\&. 
 .PP
+.SS "linear"
+(Since GDAL 2\&.1) Linear interpolation algorithm\&.
+.PP
+The Linear method performs linear interpolation by computing a Delaunay triangulation of the point cloud, finding in which triangle of the triangulation the point is, and by doing linear interpolation from its barycentric coordinates within the triangle\&. If the point is not in any triangle, depending on the radius, the algorithm will use the value of the nearest point or the nodata value\&.
+.PP
+It has following parameters:
+.PP
+.IP "\fB\fIradius\fP: \fP" 1c
+In case the point to be interpolated does not fit into a triangle of the Delaunay triangulation, use that maximum distance to search a nearest neighbour, or use nodata otherwise\&. If set to -1, the search distance is infinite\&. If set to 0, nodata value will be always used\&. Default is -1\&. 
+.IP "\fB\fInodata\fP: \fP" 1c
+NODATA marker to fill empty points (default 0\&.0)\&. 
+.PP
 .SH "DATA METRICS"
 .PP
 Besides the interpolation functionality \fBgdal_grid\fP can be used to compute some data metrics using the specified window and output grid geometry\&. These metrics are:
@@ -226,6 +252,9 @@ If your CSV file does not contain column headers then it can be handled in the f
 .PP
 .PP
 \fCComma Separated Value\fP description page contains details on CSV format supported by GDAL/OGR\&.
+.SH "C API"
+.PP
+Starting with GDAL 2\&.1, this utility is also callable from C with GDALGrid()\&.
 .SH "EXAMPLE"
 .PP
 The following would create raster TIFF file from VRT datasource described in \fBREADING COMMA SEPARATED VALUES\fP section using the inverse distance to a power method\&. Values to interpolate will be read from Z value of geometry record\&.
diff --git a/man/man1/gdal_merge.1 b/man/man1/gdal_merge.1
index 420da1f..4dcec14 100644
--- a/man/man1/gdal_merge.1
+++ b/man/man1/gdal_merge.1
@@ -1,4 +1,4 @@
-.TH "gdal_merge" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_merge" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -9,8 +9,9 @@ mosaics a set of images
 .PP
 .nf
 gdal_merge.py [-o out_filename] [-of out_format] [-co NAME=VALUE]*
-              [-ps pixelsize_x pixelsize_y] [-tap] [-separate] [-v] [-pct]
-              [-ul_lr ulx uly lrx lry] [-n nodata_value] [-init "value [value...]"]
+              [-ps pixelsize_x pixelsize_y] [-tap] [-separate] [-q] [-v] [-pct]
+              [-ul_lr ulx uly lrx lry] [-init "value [value...]"]
+              [-n nodata_value] [-a_nodata output_nodata_value]
               [-ot datatype] [-createonly] input_files
 .fi
 .PP
@@ -25,7 +26,7 @@ Output format, defaults to GeoTIFF (GTiff)\&.
 .IP "\fB\fB-co\fP \fINAME=VALUE\fP:\fP" 1c
 Creation option for output file\&. Multiple options can be specified\&.  
 .IP "\fB\fB-ot\fP \fIdatatype\fP:\fP" 1c
-Force the output image bands to have a specific type\&. Use type names (ie\&. Byte, Int16,\&.\&.\&.)  
+Force the output image bands to have a specific type\&. Use type names (i\&.e\&. Byte, Int16,\&.\&.\&.)  
 .IP "\fB\fB-ps\fP \fIpixelsize_x pixelsize_y\fP:\fP" 1c
 Pixel size to be used for the output file\&. If not specified the resolution of the first input file will be used\&.
 .PP
@@ -38,9 +39,9 @@ The extents of the output file\&. If not specified the aggregate extents of all
 .IP "\fB\fB-v\fP:\fP" 1c
 Generate verbose output of mosaicing operations as they are done\&. 
 .IP "\fB\fB-separate\fP:\fP" 1c
-Place each input file into a separate \fIstacked\fP band\&.  
+Place each input file into a separate band\&.  
 .IP "\fB\fB-pct\fP:\fP" 1c
-Grab a pseudocolor table from the first input image, and use it for the output\&. Merging pseudocolored images this way assumes that all input files use the same color table\&.  
+Grab a pseudo-color table from the first input image, and use it for the output\&. Merging pseudo-colored images this way assumes that all input files use the same color table\&.  
 .IP "\fB\fB-n\fP \fInodata_value\fP:\fP" 1c
 Ignore pixels from files being merged in with this pixel value\&.  
 .IP "\fB\fB-a_nodata\fP \fIoutput_nodata_value\fP:\fP" 1c
diff --git a/man/man1/gdal_pansharpen.1 b/man/man1/gdal_pansharpen.1
new file mode 100644
index 0000000..b3bf31e
--- /dev/null
+++ b/man/man1/gdal_pansharpen.1
@@ -0,0 +1,99 @@
+.TH "gdal_pansharpen" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
+.ad l
+.nh
+.SH NAME
+gdal_pansharpen \- gdal_pansharpen\&.py 
+Perform a pansharpen operation\&.
+.PP
+(Since GDAL 2\&.1)
+.SH "SYNOPSIS"
+.PP
+.PP
+.nf
+gdal_pansharpen [--help-general] pan_dataset {spectral_dataset[,band=num]}+ out_dataset
+                [-of format] [-b band]* [-w weight_val]*
+                [-r {nearest,bilinear,cubic,cubicspline,lanczos,average}]
+                [-threads {ALL_CPUS|number}] [-bitdepth val] [-nodata val]
+                [-spat_adjust {union,intersection,none,nonewithoutwarning}]
+                [-co NAME=VALUE]* [-q]
+.fi
+.PP
+.SH "DESCRIPTION"
+.PP
+The gdal_pansharpen\&.py script performs a pan-sharpening operation\&. It can create a 'classic' output dataset (such as GeoTIFF), or a VRT dataset describing the pan-sharpening operation\&.
+.PP
+More details can be found in the \fCVRT tutorial\fP\&.
+.PP
+.IP "\fB\fB-of\fP \fIformat\fP:\fP" 1c
+Select the output format\&. The default is GeoTIFF (GTiff)\&. 'VRT' can also be used\&. Use the short format name\&. 
+.IP "\fB\fB-b\fP \fIband\fP:\fP" 1c
+Select band \fIband\fP from the input spectral bands for output\&. Bands are numbered from 1 in the order spectral bands are specified\&. Multiple \fB-b\fP switches may be used\&. When no -b switch is used, all input spectral bands are set for output\&. 
+.IP "\fB\fB-w\fP \fIweight_val\fP:\fP" 1c
+Specify a weight for the computation of the pseudo panchromatic value\&. There must be as many -w switches as input spectral bands\&. 
+.IP "\fB\fB-r\fP \fI{nearest,bilinear,cubic (default),cubicspline,lanczos,average}\fP:\fP" 1c
+Select a resampling algorithm\&. 
+.IP "\fB\fB-threads\fP \fI{ALL_CPUS,number}\fP:\fP" 1c
+Specify number of threads to use to do the resampling and pan-sharpening itself\&. Can be an integer number or ALL_CPUS\&. 
+.IP "\fB\fB-bitdepth\fP \fIval\fP:\fP" 1c
+Specify the bit depth of the panchromatic and spectral bands (e\&.g\&. 12)\&. If not specified, the NBITS metadata item from the panchromatic band will be used if it exists\&. 
+.IP "\fB\fB-nodata\fP \fIval\fP:\fP" 1c
+Specify nodata value for bands\&. Used for the resampling and pan-sharpening computation itself\&. If not set, deduced from the input bands, provided they have a consistent setting\&. 
+.IP "\fB\fB-spat_adjust\fP \fI{union (default),intersection,none,nonewithoutwarning}\fP:\fP" 1c
+Select behaviour when bands have not the same extent\&. See \fISpatialExtentAdjustment\fP documentation in \fCVRT tutorial\fP 
+.IP "\fB\fB-co\fP \fI'NAME=VALUE'\fP:\fP" 1c
+Passes a creation option to the output format driver\&. Multiple \fB-co\fP options may be listed\&. See format specific documentation for legal creation options for each format\&. 
+.IP "\fB\fB-q\fP:\fP" 1c
+Suppress progress monitor and other non-error output\&. 
+.IP "\fB\fIpan_dataset\fP\fP" 1c
+Dataset with panchromatic band (first band will be used)\&. 
+.IP "\fB\fIspectral_dataset[,band=num]\fP\fP" 1c
+Dataset with one or several spectral bands\&. If the band option is not specified, all bands of the datasets are taken into account\&. Otherwise, only the specified (num)th band\&. The same dataset can be repeated several times\&. 
+.IP "\fB\fIout_dataset\fP\fP" 1c
+Output dataset 
+.PP
+.PP
+Bands should be in the same projection\&.
+.SH "EXAMPLE"
+.PP
+With spectral bands in a single dataset : 
+.PP
+.nf
+gdal_pansharpen.py panchro.tif multispectral.tif pansharpened_out.tif
+
+.fi
+.PP
+.PP
+With a few spectral bands from a single dataset, reordered : 
+.PP
+.nf
+gdal_pansharpen.py panchro.tif multispectral.tif,band=3 multispectral.tif,band=2 multispectral.tif,band=1 pansharpened_out.tif
+
+.fi
+.PP
+.PP
+With spectral bands in several datasets : 
+.PP
+.nf
+gdal_pansharpen.py panchro.tif band1.tif band2.tif band3.tif pansharpened_out.tif
+
+.fi
+.PP
+.PP
+Specify weights: 
+.PP
+.nf
+gdal_pansharpen.py -w 0.7 -w 0.2 -w 0.1 panchro.tif multispectral.tif pansharpened_out.tif
+
+.fi
+.PP
+.PP
+Specify RGB bands from a RGBNir multispectral dataset while computing the pseudo panchromatic intensity on the 4 RGBNir bands: 
+.PP
+.nf
+gdal_pansharpen.py -b 1 -b 2 -b 3 panchro.tif rgbnir.tif pansharpened_out.tif
+
+.fi
+.PP
+.SH "AUTHORS"
+.PP
+Even Rouault <even\&.rouault at spatialys\&.com> 
diff --git a/man/man1/gdal_polygonize.1 b/man/man1/gdal_polygonize.1
index 435a143..66aaec4 100644
--- a/man/man1/gdal_polygonize.1
+++ b/man/man1/gdal_polygonize.1
@@ -1,4 +1,4 @@
-.TH "gdal_polygonize" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_polygonize" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_proximity.1 b/man/man1/gdal_proximity.1
index 0816fae..55104c3 100644
--- a/man/man1/gdal_proximity.1
+++ b/man/man1/gdal_proximity.1
@@ -1,4 +1,4 @@
-.TH "gdal_proximity" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_proximity" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -39,7 +39,7 @@ Select the output format\&. The default is GeoTIFF (GTiff)\&. Use the short form
 passes a creation option to the output format driver\&. Multiple \fB-co\fP options may be listed\&. See format specific documentation for legal creation options for each format\&. 
 .PP
 .IP "\fB\fB-ot\fP \fIdatatype\fP:\fP" 1c
-Force the output image bands to have a specific type\&. Use type names (ie\&. Byte, Int16,\&.\&.\&.) 
+Force the output image bands to have a specific type\&. Use type names (i\&.e\&. Byte, Int16,\&.\&.\&.) 
 .PP
 .IP "\fB\fB-values\fP \fIn,n,n\fP:\fP" 1c
 A list of target pixel values in the source image to be considered target pixels\&. If not specified, all non-zero pixels will be considered target pixels\&. 
diff --git a/man/man1/gdal_rasterize.1 b/man/man1/gdal_rasterize.1
index 33b9d68..15e747c 100644
--- a/man/man1/gdal_rasterize.1
+++ b/man/man1/gdal_rasterize.1
@@ -1,4 +1,4 @@
-.TH "gdal_rasterize" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_rasterize" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -11,8 +11,8 @@ burns vector geometries into a raster
 Usage: gdal_rasterize [-b band]* [-i] [-at]
        [-burn value]* | [-a attribute_name] [-3d]
        [-l layername]* [-where expression] [-sql select_statement]
-       [-of format] [-a_srs srs_def] [-co "NAME=VALUE"]*
-       [-a_nodata value] [-init value]*
+       [-dialect dialect] [-of format] [-a_srs srs_def]
+       [-co "NAME=VALUE"]* [-a_nodata value] [-init value]*
        [-te xmin ymin xmax ymax] [-tr xres yres] [-tap] [-ts width height]
        [-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/
              CInt16/CInt32/CFloat32/CFloat64}] [-q]
@@ -23,7 +23,7 @@ Usage: gdal_rasterize [-b band]* [-i] [-at]
 .PP
 This program burns vector geometries (points, lines, and polygons) into the raster band(s) of a raster image\&. Vectors are read from OGR supported vector formats\&.
 .PP
-Note that the vector data must be in the same coordinate system as the raster data; on the fly reprojection is not provided\&.
+Note that on the fly reprojection of vector data to the coordinate system of the raster data is only supported since GDAL 2\&.1\&.0\&.
 .PP
 Since GDAL 1\&.8\&.0, the target GDAL file can be created by gdal_rasterize\&. Either the -tr or -ts option must be used in that case\&.
 .PP
@@ -43,7 +43,7 @@ A fixed value to burn into a band for all objects\&. A list of -burn options can
 Identifies an attribute field on the features to be used for a burn-in value\&. The value will be burned into all output bands\&.
 .PP
 .IP "\fB\fB-3d\fP: \fP" 1c
-Indicates that a burn value should be extracted from the 'Z' values of the feature\&. These values are adjusted by the burn value given by '-burn value' or '-a attribute_name' if provided\&. As of now, only points and lines are drawn in 3D\&.
+Indicates that a burn value should be extracted from the 'Z' values of the feature\&. These values are added to the burn value given by '-burn value' or '-a attribute_name' if provided\&. As of now, only points and lines are drawn in 3D\&.
 .PP
 .IP "\fB\fB-l\fP \fIlayername\fP: \fP" 1c
 Indicates the layer(s) from the datasource that will be used for input features\&. May be specified multiple times, but at least one layer name or a -sql option must be specified\&.
@@ -54,6 +54,9 @@ An optional SQL WHERE style query expression to be applied to select features to
 .IP "\fB\fB-sql\fP \fIselect_statement\fP: \fP" 1c
 An SQL statement to be evaluated against the datasource to produce a virtual layer of features to be burned in\&.
 .PP
+.IP "\fB\fB-dialect\fP \fIdialect\fP: \fP" 1c
+(GDAL >= 2\&.1\&.0) SQL dialect\&. In some cases can be used to use (unoptimized) OGR SQL instead of the native SQL of an RDBMS by passing OGRSQL\&. Starting with GDAL 1\&.10, the 'SQLITE' dialect can also be used with any datasource\&.
+.PP
 .IP "\fB\fB-of\fP \fIformat\fP:\fP" 1c
 (GDAL >= 1\&.8\&.0) Select the output format\&. The default is GeoTIFF (GTiff)\&. Use the short format name\&.
 .PP
@@ -94,6 +97,9 @@ Any OGR supported readable datasource\&.
 The GDAL supported output file\&. Must support update mode access\&. Before GDAL 1\&.8\&.0, gdal_rasterize could not create new output files\&.
 .PP
 .PP
+.SH "C API"
+.PP
+Starting with GDAL 2\&.1, this utility is also callable from C with GDALRasterize()\&.
 .SH "EXAMPLE"
 .PP
 The following would burn all polygons from mask\&.shp into the RGB TIFF file work\&.tif with the color red (RGB = 255,0,0)\&.
diff --git a/man/man1/gdal_retile.1 b/man/man1/gdal_retile.1
index 1fc1f39..3498b0f 100644
--- a/man/man1/gdal_retile.1
+++ b/man/man1/gdal_retile.1
@@ -1,4 +1,4 @@
-.TH "gdal_retile" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_retile" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -28,13 +28,13 @@ This utility will retile a set of input tile(s)\&. All the input tile(s) must be
 If your number of input tiles exhausts the command line buffer, use the general --optfile option
 .PP
 .IP "\fB\fB-targetDir\fP \fIdirectory\fP:\fP" 1c
-The directory where the tile result is created\&. Pyramids are stored in subdirectories numbered from 1\&. Created tile names have a numbering schema and contain the name of the source tiles(s)  
+The directory where the tile result is created\&. Pyramids are stored in sub-directories numbered from 1\&. Created tile names have a numbering schema and contain the name of the source tiles(s)  
 .IP "\fB\fB-of\fP \fIformat\fP:\fP" 1c
 Output format, defaults to GeoTIFF (GTiff)\&.  
 .IP "\fB\fB-co\fP \fINAME=VALUE\fP:\fP" 1c
 Creation option for output file\&. Multiple options can be specified\&.  
 .IP "\fB\fB-ot\fP \fIdatatype\fP:\fP" 1c
-Force the output image bands to have a specific type\&. Use type names (ie\&. Byte, Int16,\&.\&.\&.)  
+Force the output image bands to have a specific type\&. Use type names (i\&.e\&. Byte, Int16,\&.\&.\&.)  
 .IP "\fB\fB-ps\fP \fIpixelsize_x pixelsize_y\fP:\fP" 1c
 Pixel size to be used for the output file\&. If not specified, 256 x 256 is the default  
 .IP "\fB\fB-levels\fP \fInumberOfLevels\fP:\fP" 1c
@@ -46,7 +46,7 @@ No retiling, build only the pyramids
 .IP "\fB\fB-r\fP \fIalgorithm\fP:\fP" 1c
 Resampling algorithm, default is near  
 .IP "\fB\fB-s_srs\fP \fIsrs_def\fP:\fP" 1c
-Source spatial reference to use\&. The coordinate systems that can be passed are anything supported by the OGRSpatialReference\&.SetFro‐mUserInput() call, which includes EPSG PCS and GCSes (ie\&.EPSG:4296), PROJ\&.4 declarations (as above), or the name of a \&.prf file containing well known text\&. If no srs_def is given, the srs_def of the source tiles is used (if there is any)\&. The srs_def will be propagated to created tiles (if possible) and to the optional shape file(s)  
+Source spatial reference to use\&. The coordinate systems that can be passed are anything supported by the OGRSpatialReference\&.SetFromUserInput() call, which includes EPSG, PCS, and GCSes (i\&.e\&. EPSG:4296), PROJ\&.4 declarations (as above), or the name of a \&.prj file containing well known text\&. If no srs_def is given, the srs_def of the source tiles is used (if there is any)\&. The srs_def will be propagated to created tiles (if possible) and to the optional shape file(s)  
 .IP "\fB\fB-tileIndex\fP \fItileIndexName\fP:\fP" 1c
 The name of shape file containing the result tile(s) index  
 .IP "\fB\fB-tileIndexField\fP \fItileIndexFieldName\fP:\fP" 1c
@@ -54,9 +54,9 @@ The name of the attribute containing the tile name
 .IP "\fB\fB-csv\fP \fIcsvFileName\fP:\fP" 1c
 The name of the csv file containing the tile(s) georeferencing information\&. The file contains 5 columns: tilename,minx,maxx,miny,maxy  
 .IP "\fB\fB-csvDelim\fP \fIcolumn delimiter\fP:\fP" 1c
-The column delimter used in the csv file, default value is a semicolon ';'  
+The column delimiter used in the CSV file, default value is a semicolon ';'  
 .IP "\fB\fB-useDirForEachRow\fP:\fP" 1c
-Normally the tiles of the base image are stored as described in \fB-targetDir\fP\&. For large images, some file systems have performance problems if the number of files in a directory is to big, causing gdal_retile not to finish in reasonable time\&. Using this parameter creates a different output structure\&. The tiles of the base image are stored in a subdirectory called 0, the pyramids in subdirectories numbered 1,2,\&.\&.\&.\&. Within each of these directories another level of subdir [...]
+Normally the tiles of the base image are stored as described in \fB-targetDir\fP\&. For large images, some file systems have performance problems if the number of files in a directory is to big, causing gdal_retile not to finish in reasonable time\&. Using this parameter creates a different output structure\&. The tiles of the base image are stored in a sub-directory called 0, the pyramids in sub-directories numbered 1,2,\&.\&.\&.\&. Within each of these directories another level of sub- [...]
 .PP
 .PP
 NOTE: gdal_retile\&.py is a Python script, and will only work if GDAL was built with Python support\&.
diff --git a/man/man1/gdal_sieve.1 b/man/man1/gdal_sieve.1
index debec1d..8f7b625 100644
--- a/man/man1/gdal_sieve.1
+++ b/man/man1/gdal_sieve.1
@@ -1,4 +1,4 @@
-.TH "gdal_sieve" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_sieve" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_translate.1 b/man/man1/gdal_translate.1
index 28559c4..3370949 100644
--- a/man/man1/gdal_translate.1
+++ b/man/man1/gdal_translate.1
@@ -1,4 +1,4 @@
-.TH "gdal_translate" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_translate" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -11,7 +11,7 @@ converts raster data between different formats
 gdal_translate [--help-general]
        [-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/
              CInt16/CInt32/CFloat32/CFloat64}] [-strict]
-       [-of format] [-b band] [-mask band] [-expand {gray|rgb|rgba}]
+       [-of format] [-b band]* [-mask band] [-expand {gray|rgb|rgba}]
        [-outsize xsize[%]|0 ysize[%]|0] [-tr xres yres]
        [-r {nearest,bilinear,cubic,cubicspline,lanczos,average,mode}]
        [-unscale] [-scale[_bn] [src_min src_max [dst_min dst_max]]]* [-exponent[_bn] exp_val]*
@@ -50,7 +50,7 @@ Set the size of the output file\&. Outsize is in pixels and lines unless '%' is
 .IP "\fB\fB-scale\fP \fI[src_min src_max [dst_min dst_max]]\fP:\fP" 1c
 Rescale the input pixels values from the range \fIsrc_min\fP to \fIsrc_max\fP to the range \fIdst_min\fP to \fIdst_max\fP\&. If omitted the output range is 0 to 255\&. If omitted the input range is automatically computed from the source data\&. Before GDAL 1\&.11, it can be specified only once, and in that case, it applies to all bands of the output dataset\&. Starting with GDAL 1\&.11, -scale can be repeated several times (if specified only once, it also applies to all bands of the outp [...]
 .IP "\fB\fB-exponent\fP \fI exp_val\fP:\fP" 1c
-(From GDAL 1\&.11) To apply non-linear scaling with a power function\&. exp_val is the exponent of the power function (must be postive)\&. This option must be used with the -scale option\&. If specified only once, -exponent applies to all bands of the output image\&. It can be repeated several times so as to specify per band parameters\&. It is also possible to use the '-exponent_bn' syntax where bn is a band number (e\&.g\&. '-exponent_2' for the 2nd band of the output dataset) to speci [...]
+(From GDAL 1\&.11) To apply non-linear scaling with a power function\&. exp_val is the exponent of the power function (must be positive)\&. This option must be used with the -scale option\&. If specified only once, -exponent applies to all bands of the output image\&. It can be repeated several times so as to specify per band parameters\&. It is also possible to use the '-exponent_bn' syntax where bn is a band number (e\&.g\&. '-exponent_2' for the 2nd band of the output dataset) to spec [...]
 .IP "\fB\fB-unscale\fP:\fP" 1c
 Apply the scale/offset metadata for the bands to convert scaled values to unscaled values\&. It is also often necessary to reset the output datatype with the \fB-ot\fP switch\&. 
 .IP "\fB\fB-srcwin\fP \fIxoff yoff xsize ysize\fP:\fP" 1c
@@ -90,6 +90,9 @@ The source dataset name\&. It can be either file name, URL of data source or sub
 .IP "\fB\fIdst_dataset\fP:\fP" 1c
 The destination file name\&. 
 .PP
+.SH "C API"
+.PP
+Starting with GDAL 2\&.1, this utility is also callable from C with GDALTranslate()\&.
 .SH "EXAMPLE"
 .PP
 .PP
diff --git a/man/man1/gdal_utilities.1 b/man/man1/gdal_utilities.1
index 97161bd..a8c6af1 100644
--- a/man/man1/gdal_utilities.1
+++ b/man/man1/gdal_utilities.1
@@ -1,4 +1,4 @@
-.TH "gdal_utilities" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_utilities" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -61,6 +61,8 @@ The following utility programs are distributed with GDAL\&.
 .IP "\(bu" 2
 \fBgdal_calc\&.py\fP - Command line raster calculator with numpy syntax 
 .IP "\(bu" 2
+\fBgdal_pansharpen\&.py\fP - Perform a pansharpen operation\&. 
+.IP "\(bu" 2
 \fBgdal-config\fP - Get options required to build software using GDAL\&. 
 .IP "\(bu" 2
 \fBgdalmanage\fP - Identify, copy, rename and delete raster\&. 
@@ -69,7 +71,7 @@ The following utility programs are distributed with GDAL\&.
 .PP
 .SH "Creating New Files"
 .PP
-Access an existing file to read it is generally quite simple\&. Just indicate the name of the file or dataset on the commandline\&. However, creating a file is more complicated\&. It may be necessary to indicate the the format to create, various creation options affecting how it will be created and perhaps a coordinate system to be assigned\&. Many of these options are handled similarly by different GDAL utilities, and are introduced here\&. 
+Access an existing file to read it is generally quite simple\&. Just indicate the name of the file or dataset on the command line\&. However, creating a file is more complicated\&. It may be necessary to indicate the the format to create, various creation options affecting how it will be created and perhaps a coordinate system to be assigned\&. Many of these options are handled similarly by different GDAL utilities, and are introduced here\&. 
 .PP
 .IP "\fB\fB-of\fP \fIformat\fP\fP" 1c
 Select the format to create the new file as\&. The formats are assigned short names such as GTiff (for GeoTIFF) or HFA (for Erdas Imagine)\&. The list of all format codes can be listed with the \fB--formats\fP switch\&. Only formats list as '(rw)' (read-write) can be written\&.
@@ -79,11 +81,11 @@ Many utilities default to creating GeoTIFF files if a format is not specified\&.
 .IP "\fB\fB-co\fP \fINAME=VALUE\fP\fP" 1c
 Many formats have one or more optional creation options that can be used to control particulars about the file created\&. For instance, the GeoTIFF driver supports creation options to control compression, and whether the file should be tiled\&.
 .PP
-The creation options available vary by format driver, and some simple formats have no creation options at all\&. A list of options supported for a format can be listed with the '--format <format>' commandline option but the web page for the format is the definitive source of information on driver creation options\&.
+The creation options available vary by format driver, and some simple formats have no creation options at all\&. A list of options supported for a format can be listed with the '--format <format>' command line option but the web page for the format is the definitive source of information on driver creation options\&.
 .PP
 .PP
 .IP "\fB\fB-a_srs\fP \fISRS\fP\fP" 1c
-Several utilities, (gdal_translate and gdalwarp) include the ability to specify coordinate systems with commandline options like \fB-a_srs\fP (assign SRS to output), \fB-s_srs\fP (source SRS) and \fB-t_srs\fP (target SRS)\&.
+Several utilities, (gdal_translate and gdalwarp) include the ability to specify coordinate systems with command line options like \fB-a_srs\fP (assign SRS to output), \fB-s_srs\fP (source SRS) and \fB-t_srs\fP (target SRS)\&.
 .PP
 These utilities allow the coordinate system (SRS = spatial reference system) to be assigned in a variety of formats\&.
 .PP
@@ -103,7 +105,7 @@ These utilities allow the coordinate system (SRS = spatial reference system) to
 .PP
 
 .IP "\(bu" 2
-\fIOpenGIS Well Known Text\fP: The Open GIS Consortium has defined a textual format for describing coordinate systems as part of the Simple Features specifications\&. This format is the internal working format for coordinate systems used in GDAL\&. The name of a file containing a WKT coordinate system definition may be used a coordinate system argument, or the entire coordinate system itself may be used as a commandline option (though escaping all the quotes in WKT is quite challenging)\&. 
+\fIOpenGIS Well Known Text\fP: The Open GIS Consortium has defined a textual format for describing coordinate systems as part of the Simple Features specifications\&. This format is the internal working format for coordinate systems used in GDAL\&. The name of a file containing a WKT coordinate system definition may be used a coordinate system argument, or the entire coordinate system itself may be used as a command line option (though escaping all the quotes in WKT is quite challenging)\&. 
 .PP
 .PP
 
@@ -132,13 +134,13 @@ All GDAL command line utility programs support the following 'general' options\&
 Report the version of GDAL and exit\&.
 .PP
 .IP "\fB\fB--formats\fP\fP" 1c
-List all raster formats supported by this GDAL build (read-only and read-write) and exit\&. The format support is indicated as follows: 'ro' is read-only driver; 'rw' is read or write (ie\&. supports CreateCopy); 'rw+' is read, write and update (ie\&. supports Create)\&. A 'v' is appended for formats supporting virtual IO (/vsimem, /vsigzip, /vsizip, etc)\&. A 's' is appended for formats supporting subdatasets\&. Note: The valid formats for the output of gdalwarp are formats that support [...]
+List all raster formats supported by this GDAL build (read-only and read-write) and exit\&. The format support is indicated as follows: 'ro' is read-only driver; 'rw' is read or write (i\&.e\&. supports CreateCopy); 'rw+' is read, write and update (i\&.e\&. supports Create)\&. A 'v' is appended for formats supporting virtual IO (/vsimem, /vsigzip, /vsizip, etc)\&. A 's' is appended for formats supporting subdatasets\&. Note: The valid formats for the output of gdalwarp are formats that s [...]
 .PP
 .IP "\fB\fB--format\fP \fIformat\fP\fP" 1c
 List detailed information about a single format driver\&. The \fIformat\fP should be the short name reported in the \fB--formats\fP list, such as GTiff\&.
 .PP
 .IP "\fB\fB--optfile\fP \fIfile\fP\fP" 1c
-Read the named file and substitute the contents into the commandline options list\&. Lines beginning with # will be ignored\&. Multi-word arguments may be kept together with double quotes\&. 
+Read the named file and substitute the contents into the command line options list\&. Lines beginning with # will be ignored\&. Multi-word arguments may be kept together with double quotes\&. 
 .PP
 .IP "\fB\fB--config\fP \fIkey value\fP\fP" 1c
 Sets the named \fCconfiguration keyword\fP to the given value, as opposed to setting them as environment variables\&. Some common configuration keywords are GDAL_CACHEMAX (memory used internally for caching in megabytes) and GDAL_DATA (path of the GDAL 'data' directory)\&. Individual drivers may be influenced by other configuration options\&. 
@@ -147,7 +149,7 @@ Sets the named \fCconfiguration keyword\fP to the given value, as opposed to set
 Control what debugging messages are emitted\&. A value of \fION\fP will enable all debug messages\&. A value of \fIOFF\fP will disable all debug messages\&. Another value will select only debug messages containing that string in the debug prefix code\&. 
 .PP
 .IP "\fB\fB--help-general\fP\fP" 1c
-Gives a brief usage message for the generic GDAL commandline options and exit\&. 
+Gives a brief usage message for the generic GDAL command line options and exit\&. 
 .PP
 .PP
 .PP
diff --git a/man/man1/gdaladdo.1 b/man/man1/gdaladdo.1
index 5e66c8d..8833f75 100644
--- a/man/man1/gdaladdo.1
+++ b/man/man1/gdaladdo.1
@@ -1,4 +1,4 @@
-.TH "gdaladdo" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "gdaladdo" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -9,7 +9,7 @@ builds or rebuilds overview images
 .PP
 .nf
 gdaladdo [-r {nearest,average,gauss,cubic,cubicspline,lanczos,average_mp,average_magphase,mode}]
-         [-b band]
+         [-b band]*
          [-ro] [-clean] [-oo NAME=VALUE]* [--help-general] filename levels
 .fi
 .PP
@@ -41,12 +41,12 @@ Selecting a level value like \fI2\fP causes an overview level that is 1/2 the re
 .PP
 For internal GeoTIFF overviews (or external overviews in GeoTIFF format), note that -clean does not shrink the file\&. A later run of gdaladdo with overview levels will cause the file to be expanded, rather than reusing the space of the previously deleted overviews\&. If you just want to change the resampling method on a file that already has overviews computed, you don't need to clean the existing overviews\&.
 .PP
-Some format drivers do not support overviews at all\&. Many format drivers store overviews in a secondary file with the extension \&.ovr that is actually in TIFF format\&. By default, the GeoTIFF driver stores overviews internally to the file operated on (if it is writeable), unless the -ro flag is specified\&.
+Some format drivers do not support overviews at all\&. Many format drivers store overviews in a secondary file with the extension \&.ovr that is actually in TIFF format\&. By default, the GeoTIFF driver stores overviews internally to the file operated on (if it is writable), unless the -ro flag is specified\&.
 .PP
-Most drivers also support an alternate overview format using Erdas Imagine format\&. To trigger this use the USE_RRD=YES configuration option\&. This will place the overviews in an associated \&.aux file suitable for direct use with Imagine or ArcGIS as well as GDAL applications\&. (eg --config USE_RRD YES)
+Most drivers also support an alternate overview format using Erdas Imagine format\&. To trigger this use the USE_RRD=YES configuration option\&. This will place the overviews in an associated \&.aux file suitable for direct use with Imagine or ArcGIS as well as GDAL applications\&. (e\&.g\&. --config USE_RRD YES)
 .SH "External overviews in GeoTIFF format"
 .PP
-External overviews created in TIFF format may be compressed using the COMPRESS_OVERVIEW configuration option\&. All compression methods, supported by the GeoTIFF driver, are available here\&. (eg --config COMPRESS_OVERVIEW DEFLATE)\&. The photometric interpretation can be set with --config PHOTOMETRIC_OVERVIEW {RGB,YCBCR,\&.\&.\&.}, and the interleaving with --config INTERLEAVE_OVERVIEW {PIXEL|BAND}\&.
+External overviews created in TIFF format may be compressed using the COMPRESS_OVERVIEW configuration option\&. All compression methods, supported by the GeoTIFF driver, are available here\&. (e\&.g\&. --config COMPRESS_OVERVIEW DEFLATE)\&. The photometric interpretation can be set with --config PHOTOMETRIC_OVERVIEW {RGB,YCBCR,\&.\&.\&.}, and the interleaving with --config INTERLEAVE_OVERVIEW {PIXEL|BAND}\&.
 .PP
 For JPEG compressed external overviews, the JPEG quality can be set with '--config JPEG_QUALITY_OVERVIEW value' (GDAL 1\&.7\&.0 or later)\&.
 .PP
@@ -76,6 +76,9 @@ IF_SAFER will create BigTIFF if the resulting file \fImight\fP exceed 4GB\&.
 .br
 .PP
 See the documentation of the GeoTIFF driver for further explanations on all those options\&.
+.SH "C API"
+.PP
+Functionality of this utility can be done from C with GDALBuildOverviews()\&.
 .SH "EXAMPLE"
 .PP
 .PP
@@ -95,7 +98,7 @@ gdaladdo -ro --config COMPRESS_OVERVIEW DEFLATE erdas.img 2 4 8 16
 .fi
 .PP
 .PP
-Create an external JPEG-compressed GeoTIFF overview file from a 3-band RGB dataset (if the dataset is a writeable GeoTIFF, you also need to add the -ro option to force the generation of external overview):
+Create an external JPEG-compressed GeoTIFF overview file from a 3-band RGB dataset (if the dataset is a writable GeoTIFF, you also need to add the -ro option to force the generation of external overview):
 .PP
 .PP
 .nf
diff --git a/man/man1/gdalbuildvrt.1 b/man/man1/gdalbuildvrt.1
index a4ab009..a776574 100644
--- a/man/man1/gdalbuildvrt.1
+++ b/man/man1/gdalbuildvrt.1
@@ -1,4 +1,4 @@
-.TH "gdalbuildvrt" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "gdalbuildvrt" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -11,26 +11,26 @@ Builds a VRT from a list of datasets\&. (compiled by default since GDAL 1\&.6\&.
 gdalbuildvrt [-tileindex field_name]
              [-resolution {highest|lowest|average|user}]
              [-te xmin ymin xmax ymax] [-tr xres yres] [-tap]
-             [-separate] [-b band] [-sd subdataset]
+             [-separate] [-b band]* [-sd subdataset]
              [-allow_projection_difference] [-q]
              [-addalpha] [-hidenodata]
              [-srcnodata "value [value...]"] [-vrtnodata "value [value...]"] 
              [-a_srs srs_def]
              [-r {nearest,bilinear,cubic,cubicspline,lanczos,average,mode}]
-             [-input_file_list my_liste.txt] [-overwrite] output.vrt [gdalfile]*
+             [-input_file_list my_list.txt] [-overwrite] output.vrt [gdalfile]*
 .fi
 .PP
 .SH "DESCRIPTION"
 .PP
 This program builds a VRT (Virtual Dataset) that is a mosaic of the list of input GDAL datasets\&. The list of input GDAL datasets can be specified at the end of the command line, or put in a text file (one filename per line) for very long lists, or it can be a MapServer tileindex (see \fBgdaltindex\fP utility)\&. In the later case, all entries in the tile index will be added to the VRT\&.
 .PP
-With -separate, each files goes into a separate \fIstacked\fP band in the VRT band\&. Otherwise, the files are considered as tiles of a larger mosaic and the VRT file has as many bands as one of the input files\&.
+With -separate, each files goes into a separate band in the VRT band\&. Otherwise, the files are considered as tiles of a larger mosaic and the VRT file has as many bands as one of the input files\&.
 .PP
 If one GDAL dataset is made of several subdatasets and has 0 raster bands, all the subdatasets will be added to the VRT rather than the dataset itself\&.
 .PP
 gdalbuildvrt does some amount of checks to assure that all files that will be put in the resulting VRT have similar characteristics : number of bands, projection, color interpretation\&.\&.\&. If not, files that do not match the common characteristics will be skipped\&. (This is only true in the default mode, and not when using the -separate option)
 .PP
-If there is some amount of spatial overlapping between files, the order may depend on the order they are inserted in the VRT file, but this behaviour should not be relied on\&.
+If there is some amount of spatial overlapping between files, the order of files appearing in the list of source matter: files that are listed at the end are the ones from which the content will be fetched\&. Note that nodata will be taken into account to potentially fetch data from less prioritary datasets, but currently, alpha channel is not taken into account to do alpha compositing (so a source with alpha=0 appearing on top of another source will override is content)\&. This might be [...]
 .PP
 This utility is somehow equivalent to the gdal_vrtmerge\&.py utility and is build by default in GDAL 1\&.6\&.1\&.
 .PP
@@ -59,7 +59,7 @@ In case the resolution of all input files is not the same, the -resolution flag
 (starting with GDAL 1\&.7\&.0) Set nodata values for input bands (different values can be supplied for each band)\&. If more than one value is supplied all values should be quoted to keep them together as a single operating system argument\&. If the option is not specified, the intrinsic nodata settings on the source datasets will be used (if they exist)\&. The value set by this option is written in the NODATA element of each ComplexSource element\&. Use a value of \fCNone\fP to ignore i [...]
 .PP
 .IP "\fB\fB-b\fP \fIband\fP:\fP" 1c
-(GDAL >= 1\&.10\&.0) Select an input \fIband\fP to be processed\&. Bands are numbered from 1\&. If input bands not set all bands will be added to vrt
+(GDAL >= 1\&.10\&.0) Select an input \fIband\fP to be processed\&. Bands are numbered from 1\&. If input bands not set all bands will be added to vrt\&. Multiple \fB-b\fP switches may be used to select a set of input bands\&.
 .PP
 .IP "\fB\fB-sd\fP \fIsubdataset\fP\fP" 1c
 (GDAL >= 1\&.10\&.0) If the input dataset contains several subdatasets use a subdataset with the specified number (starting from 1)\&. This is an alternative of giving the full subdataset name as an input\&.
@@ -68,7 +68,7 @@ In case the resolution of all input files is not the same, the -resolution flag
 (starting with GDAL 1\&.7\&.0) Set nodata values at the VRT band level (different values can be supplied for each band)\&. If more than one value is supplied all values should be quoted to keep them together as a single operating system argument\&. If the option is not specified, intrinsic nodata settings on the first dataset will be used (if they exist)\&. The value set by this option is written in the NoDataValue element of each VRTRasterBand element\&. Use a value of \fCNone\fP to ign [...]
 .PP
 .IP "\fB\fB-separate\fP:\fP" 1c
-(starting with GDAL 1\&.7\&.0) Place each input file into a separate \fIstacked\fP band\&. In that case, only the first band of each dataset will be placed into a new band\&. Contrary to the default mode, it is not required that all bands have the same datatype\&. 
+(starting with GDAL 1\&.7\&.0) Place each input file into a separate band\&. In that case, only the first band of each dataset will be placed into a new band\&. Contrary to the default mode, it is not required that all bands have the same datatype\&. 
 .PP
 .IP "\fB\fB-allow_projection_difference\fP:\fP" 1c
 (starting with GDAL 1\&.7\&.0) When this option is specified, the utility will accept to make a VRT even if the input datasets have not the same projection\&. Note: this does not mean that they will be reprojected\&. Their projection will just be ignored\&. 
@@ -103,7 +103,7 @@ gdalbuildvrt doq_index.vrt doq/*.tif
 Make a virtual mosaic from files whose name is specified in a text file : 
 .PP
 .nf
-gdalbuildvrt -input_file_list my_liste.txt doq_index.vrt
+gdalbuildvrt -input_file_list my_list.txt doq_index.vrt
 
 .fi
 .PP
diff --git a/man/man1/gdalcompare.1 b/man/man1/gdalcompare.1
index 9f27416..ebb7048 100644
--- a/man/man1/gdalcompare.1
+++ b/man/man1/gdalcompare.1
@@ -1,4 +1,4 @@
-.TH "gdalcompare" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "gdalcompare" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdaldem.1 b/man/man1/gdaldem.1
index 1919678..1c4b2da 100644
--- a/man/man1/gdaldem.1
+++ b/man/man1/gdaldem.1
@@ -1,4 +1,4 @@
-.TH "gdaldem" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "gdaldem" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -87,7 +87,7 @@ Select the output format\&. The default is GeoTIFF (GTiff)\&. Use the short form
 .IP "\fB\fB-compute_edges\fP:\fP" 1c
 (GDAL >= 1\&.8\&.0) Do the computation at raster edges and near nodata values 
 .IP "\fB\fB-alg\fP \fIZevenbergenThorne\fP:\fP" 1c
-(GDAL >= 1\&.8\&.0) Use Zevenbergen & Thorne formula, instead of Horn's formula, to compute slope & aspect\&. The litterature suggests Zevenbergen & Thorne to be more suited to smooth landscapes, whereas Horn's formula to perform better on rougher terrain\&. 
+(GDAL >= 1\&.8\&.0) Use Zevenbergen & Thorne formula, instead of Horn's formula, to compute slope & aspect\&. The literature suggests Zevenbergen & Thorne to be more suited to smooth landscapes, whereas Horn's formula to perform better on rougher terrain\&. 
 .IP "\fB\fB-b\fP \fIband\fP:\fP" 1c
 Select an input \fIband\fP to be processed\&. Bands are numbered from 1\&. 
 .IP "\fB\fB-co\fP \fI'NAME=VALUE'\fP:\fP" 1c
@@ -196,6 +196,9 @@ This command outputs a single-band raster with values computed from the elevatio
 The value -9999 is used as the output nodata value\&.
 .PP
 There are no specific options\&.
+.SH "C API"
+.PP
+Starting with GDAL 2\&.1, this utility is also callable from C with GDALDEMProcessing()\&.
 .SH "AUTHORS"
 .PP
 Matthew Perry perrygeo at gmail.com, Even Rouault even.rouault at mines-paris.org, Howard Butler hobu.inc at gmail.com, Chris Yesson chris.yesson at ioz.ac.uk
diff --git a/man/man1/gdalinfo.1 b/man/man1/gdalinfo.1
index 1bd9aa9..4a67925 100644
--- a/man/man1/gdalinfo.1
+++ b/man/man1/gdalinfo.1
@@ -1,4 +1,4 @@
-.TH "gdalinfo" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "gdalinfo" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -89,6 +89,9 @@ Band unit type (i\&.e\&.\&. 'meters' or 'feet' for elevation bands)\&.
 .IP "\(bu" 2
 Band pseudo-color tables\&. 
 .PP
+.SH "C API"
+.PP
+Starting with GDAL 2\&.1, this utility is also callable from C with GDALInfo()\&.
 .SH "EXAMPLE"
 .PP
 .PP
diff --git a/man/man1/gdallocationinfo.1 b/man/man1/gdallocationinfo.1
index a04e97f..e570f62 100644
--- a/man/man1/gdallocationinfo.1
+++ b/man/man1/gdallocationinfo.1
@@ -1,4 +1,4 @@
-.TH "gdallocationinfo" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "gdallocationinfo" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -23,7 +23,7 @@ The gdallocationinfo utility provide a mechanism to query information about a pi
 The output report will be XML formatted for convenient post processing\&.
 .PP
 .IP "\fB\fB-lifonly\fP: \fP" 1c
-The only output is filenames production from the LocationInfo request against the database (ie\&. for identifying impacted file from VRT)\&.
+The only output is filenames production from the LocationInfo request against the database (i\&.e\&. for identifying impacted file from VRT)\&.
 .PP
 .IP "\fB\fB-valonly\fP: \fP" 1c
 The only output is the pixel values of the selected pixel on each of the selected bands\&.
@@ -70,7 +70,7 @@ The raster pixel value of that pixel for all or a subset of the bands\&.
 The unscaled pixel value if a Scale and/or Offset apply to the band\&. 
 .PP
 .PP
-The pixel selected is requested by x/y coordinate on the commandline, or read from stdin\&. More than one coordinate pair can be supplied when reading coordinatesis from stdin\&. By default pixel/line coordinates are expected\&. However with use of the -geoloc, -wgs84, or -l_srs switches it is possible to specify the location in other coordinate systems\&.
+The pixel selected is requested by x/y coordinate on the command line, or read from stdin\&. More than one coordinate pair can be supplied when reading coordinates from stdin\&. By default pixel/line coordinates are expected\&. However with use of the -geoloc, -wgs84, or -l_srs switches it is possible to specify the location in other coordinate systems\&.
 .PP
 The default report is in a human readable text format\&. It is possible to instead request xml output with the -xml switch\&.
 .PP
diff --git a/man/man1/gdalmanage.1 b/man/man1/gdalmanage.1
index 00d9138..cb7a88c 100644
--- a/man/man1/gdalmanage.1
+++ b/man/man1/gdalmanage.1
@@ -1,4 +1,4 @@
-.TH "gdalmanage" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "gdalmanage" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalmove.1 b/man/man1/gdalmove.1
index 3cf464c..57ec9c3 100644
--- a/man/man1/gdalmove.1
+++ b/man/man1/gdalmove.1
@@ -1,4 +1,4 @@
-.TH "gdalmove" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "gdalmove" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalsrsinfo.1 b/man/man1/gdalsrsinfo.1
index 973ed54..9218a37 100644
--- a/man/man1/gdalsrsinfo.1
+++ b/man/man1/gdalsrsinfo.1
@@ -1,4 +1,4 @@
-.TH "gdalsrsinfo" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "gdalsrsinfo" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdaltindex.1 b/man/man1/gdaltindex.1
index 3223621..434e9d4 100644
--- a/man/man1/gdaltindex.1
+++ b/man/man1/gdaltindex.1
@@ -1,4 +1,4 @@
-.TH "gdaltindex" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "gdaltindex" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -21,7 +21,7 @@ This program builds a shapefile with a record for each input raster file, an att
 .IP "\fB\fB-f\fP format:\fP" 1c
 (GDAL >= 1\&.11) 
 .PP
-The OGR format of the output tile index file\&. Default is Esri Shapefile\&.
+The OGR format of the output tile index file\&. Default is ESRI Shapefile\&.
 .PP
 .IP "\fB\fB-tileindex\fP field_name: \fP" 1c
 .PP
diff --git a/man/man1/gdaltransform.1 b/man/man1/gdaltransform.1
index c5182e3..5ebe50b 100644
--- a/man/man1/gdaltransform.1
+++ b/man/man1/gdaltransform.1
@@ -1,4 +1,4 @@
-.TH "gdaltransform" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "gdaltransform" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -20,9 +20,9 @@ gdaltransform [--help-general]
 The gdaltransform utility reprojects a list of coordinates into any supported projection,including GCP-based transformations\&.
 .PP
 .IP "\fB\fB-s_srs\fP \fIsrs def\fP:\fP" 1c
-source spatial reference set\&. The coordinate systems that can be passed are anything supported by the OGRSpatialReference\&.SetFromUserInput() call, which includes EPSG PCS and GCSes (ie\&. EPSG:4296), PROJ\&.4 declarations (as above), or the name of a \&.prf file containing well known text\&. 
+source spatial reference set\&. The coordinate systems that can be passed are anything supported by the OGRSpatialReference\&.SetFromUserInput() call, which includes EPSG PCS and GCSes (i\&.e\&. EPSG:4296), PROJ\&.4 declarations (as above), or the name of a \&.prj file containing well known text\&. 
 .IP "\fB\fB-t_srs\fP \fIsrs_def\fP:\fP" 1c
-target spatial reference set\&. The coordinate systems that can be passed are anything supported by the OGRSpatialReference\&.SetFromUserInput() call, which includes EPSG PCS and GCSes (ie\&. EPSG:4296), PROJ\&.4 declarations (as above), or the name of a \&.prf file containing well known text\&. 
+target spatial reference set\&. The coordinate systems that can be passed are anything supported by the OGRSpatialReference\&.SetFromUserInput() call, which includes EPSG PCS and GCSes (i\&.e\&. EPSG:4296), PROJ\&.4 declarations (as above), or the name of a \&.prj file containing well known text\&. 
 .IP "\fB\fB-to\fP \fINAME=VALUE\fP:\fP" 1c
 set a transformer option suitable to pass to GDALCreateGenImgProjTransformer2()\&.  
 .IP "\fB\fB-order\fP \fIn\fP:\fP" 1c
diff --git a/man/man1/gdalwarp.1 b/man/man1/gdalwarp.1
index d9aceae..7c31af5 100644
--- a/man/man1/gdalwarp.1
+++ b/man/man1/gdalwarp.1
@@ -1,4 +1,4 @@
-.TH "gdalwarp" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "gdalwarp" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -22,6 +22,7 @@ gdalwarp [--help-general] [--formats]
     [-csql statement] [-cblend dist_in_pixels] [-crop_to_cutline]
     [-of format] [-co "NAME=VALUE"]* [-overwrite]
     [-nomd] [-cvmd meta_conflict_value] [-setci] [-oo NAME=VALUE]*
+    [-doo NAME=VALUE]*
     srcfile* dstfile
 .fi
 .PP
@@ -30,9 +31,9 @@ gdalwarp [--help-general] [--formats]
 The gdalwarp utility is an image mosaicing, reprojection and warping utility\&. The program can reproject to any supported projection, and can also apply GCPs stored with the image if the image is 'raw' with control information\&.
 .PP
 .IP "\fB\fB-s_srs\fP \fIsrs def\fP:\fP" 1c
-source spatial reference set\&. The coordinate systems that can be passed are anything supported by the OGRSpatialReference\&.SetFromUserInput() call, which includes EPSG PCS and GCSes (ie\&. EPSG:4296), PROJ\&.4 declarations (as above), or the name of a \&.prf file containing well known text\&. 
+source spatial reference set\&. The coordinate systems that can be passed are anything supported by the OGRSpatialReference\&.SetFromUserInput() call, which includes EPSG PCS and GCSes (i\&.e\&. EPSG:4296), PROJ\&.4 declarations (as above), or the name of a \&.prj file containing well known text\&. 
 .IP "\fB\fB-t_srs\fP \fIsrs_def\fP:\fP" 1c
-target spatial reference set\&. The coordinate systems that can be passed are anything supported by the OGRSpatialReference\&.SetFromUserInput() call, which includes EPSG PCS and GCSes (ie\&. EPSG:4296), PROJ\&.4 declarations (as above), or the name of a \&.prf file containing well known text\&. 
+target spatial reference set\&. The coordinate systems that can be passed are anything supported by the OGRSpatialReference\&.SetFromUserInput() call, which includes EPSG PCS and GCSes (i\&.e\&. EPSG:4296), PROJ\&.4 declarations (as above), or the name of a \&.prj file containing well known text\&. 
 .IP "\fB\fB-to\fP \fINAME=VALUE\fP:\fP" 1c
 set a transformer option suitable to pass to GDALCreateGenImgProjTransformer2()\&.  
 .IP "\fB\fB-order\fP \fIn\fP:\fP" 1c
@@ -44,13 +45,13 @@ Force use of RPCs\&.
 .IP "\fB\fB-geoloc\fP:\fP" 1c
 Force use of Geolocation Arrays\&. 
 .IP "\fB\fB-et\fP \fIerr_threshold\fP:\fP" 1c
-error threshold for transformation approximation (in pixel units - defaults to 0\&.125)\&. 
+error threshold for transformation approximation (in pixel units - defaults to 0\&.125, unless, starting with GDAL 2\&.1, the RPC_DEM warping option is specified, in which case, an exact transformer, i\&.e\&. err_threshold=0, will be used)\&. 
 .IP "\fB\fB-refine_gcps\fP \fItolerance minimum_gcps\fP:\fP" 1c
 (GDAL >= 1\&.9\&.0) refines the GCPs by automatically eliminating outliers\&. Outliers will be eliminated until minimum_gcps are left or when no outliers can be detected\&. The tolerance is passed to adjust when a GCP will be eliminated\&. Not that GCP refinement only works with polynomial interpolation\&. The tolerance is in pixel units if no projection is available, otherwise it is in SRS units\&. If minimum_gcps is not provided, the minimum GCPs according to the polynomial model is used\&. 
 .IP "\fB\fB-te\fP \fIxmin ymin xmax ymax\fP:\fP" 1c
 set georeferenced extents of output file to be created (in target SRS by default, or in the SRS specified with -te_srs)  
 .IP "\fB\fB-te_srs\fP \fIsrs_def\fP:\fP" 1c
-(GDAL >= 2\&.0) Specifies the SRS in which to interpret the coordinates given with -te\&. The \fIsrs_def\fP may be any of the usual GDAL/OGR forms, complete WKT, PROJ\&.4, EPSG:n or a file containing the WKT\&. This must not be confused with -t_srs which is the target SRS of the output dataset\&. -te_srs is a conveniency e\&.g\&. when knowing the output coordinates in a geodetic long/lat SRS, but still wanting a result in a projected coordinate system\&.  
+(GDAL >= 2\&.0) Specifies the SRS in which to interpret the coordinates given with -te\&. The \fIsrs_def\fP may be any of the usual GDAL/OGR forms, complete WKT, PROJ\&.4, EPSG:n or a file containing the WKT\&. This must not be confused with -t_srs which is the target SRS of the output dataset\&. -te_srs is a convenience e\&.g\&. when knowing the output coordinates in a geodetic long/lat SRS, but still wanting a result in a projected coordinate system\&.  
 .IP "\fB\fB-tr\fP \fIxres yres\fP:\fP" 1c
 set output file resolution (in target georeferenced units) 
 .IP "\fB\fB-tap\fP:\fP" 1c
@@ -58,7 +59,7 @@ set output file resolution (in target georeferenced units)
 .IP "\fB\fB-ts\fP \fIwidth height\fP:\fP" 1c
 set output file size in pixels and lines\&. If width or height is set to 0, the other dimension will be guessed from the computed resolution\&. Note that -ts cannot be used with -tr 
 .IP "\fB\fB-ovr\fP \fIlevel|AUTO|AUTO-n|NONE>\fP:\fP" 1c
-(GDAL >= 2\&.0) To specify which overview level of source files must be used\&. The default choice, AUTO, will select the overview level whose resolution is the closest to the target resolution\&. Specify an integer value (0-based, i\&.e\&. 0=1st overview level) to select a particular level\&. Specify AUTO-n where n is an integer greater or equal to 1, to select an overview level below the AUTO one\&. Or specify NONE to force the base resolution to be used\&. 
+(GDAL >= 2\&.0) To specify which overview level of source files must be used\&. The default choice, AUTO, will select the overview level whose resolution is the closest to the target resolution\&. Specify an integer value (0-based, i\&.e\&. 0=1st overview level) to select a particular level\&. Specify AUTO-n where n is an integer greater or equal to 1, to select an overview level below the AUTO one\&. Or specify NONE to force the base resolution to be used (can be useful if overviews hav [...]
 .IP "\fB\fB-wo\fP \fI'NAME=VALUE'\fP:\fP" 1c
 Set a warp option\&. The GDALWarpOptions::papszWarpOptions docs show all options\&. Multiple \fB-wo\fP options may be listed\&. 
 .IP "\fB\fB-ot\fP \fItype\fP:\fP" 1c
@@ -130,7 +131,9 @@ Set a blend distance to use to blend over cutlines (in pixels)\&.
 .IP "\fB\fB-setci\fP:\fP" 1c
 (GDAL >= 1\&.10\&.0) Set the color interpretation of the bands of the target dataset from the source dataset\&. 
 .IP "\fB\fB-oo\fP \fINAME=VALUE\fP:\fP" 1c
-(starting with GDAL 2\&.0) Dataset open option (format specific)
+(starting with GDAL 2\&.0) Dataset open option (format specific) 
+.IP "\fB\fB-doo\fP \fINAME=VALUE\fP:\fP" 1c
+(starting with GDAL 2\&.1) Output dataset open option (format specific)
 .PP
 .IP "\fB\fIsrcfile\fP:\fP" 1c
 The source file name(s)\&.  
@@ -140,7 +143,7 @@ The destination file name\&.
 .PP
 Mosaicing into an existing output file is supported if the output file already exists\&. The spatial extent of the existing file will not be modified to accommodate new data, so you may have to remove it in that case, or use the -overwrite option\&.
 .PP
-Polygon cutlines may be used as a mask to restrict the area of the destination file that may be updated, including blending\&. If the OGR layer containing the cutline features has no explicit SRS, the cutline features must be in the SRS of the destination file\&. When outputing to a not yet existing target dataset, its extent will be the one of the original raster unless -te or -crop_to_cutline are specified\&.
+Polygon cutlines may be used as a mask to restrict the area of the destination file that may be updated, including blending\&. If the OGR layer containing the cutline features has no explicit SRS, the cutline features must be in the SRS of the destination file\&. When writing to a not yet existing target dataset, its extent will be the one of the original raster unless -te or -crop_to_cutline are specified\&.
 .SH "EXAMPLE"
 .PP
 For instance, an eight bit spot scene stored in GeoTIFF with control points mapping the corners to lat/long could be warped to a UTM projection with a command like this:
diff --git a/man/man1/gnm_utilities.1 b/man/man1/gnm_utilities.1
new file mode 100644
index 0000000..1e5c7d3
--- /dev/null
+++ b/man/man1/gnm_utilities.1
@@ -0,0 +1,14 @@
+.TH "gnm_utilities" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
+.ad l
+.nh
+.SH NAME
+gnm_utilities \- GNM Utility Programs 
+There are several Geographical Network Model (GNM) utilities:
+.PP
+.PD 0
+.IP "\(bu" 2
+\fBgnmmanage\fP - Manages networks 
+.IP "\(bu" 2
+\fBgnmanalyse\fP - Analyses networks 
+.PP
+
diff --git a/man/man1/gnmanalyse.1 b/man/man1/gnmanalyse.1
new file mode 100644
index 0000000..e7a1639
--- /dev/null
+++ b/man/man1/gnmanalyse.1
@@ -0,0 +1,54 @@
+.TH "gnmanalyse" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
+.ad l
+.nh
+.SH NAME
+gnmanalyse \- gnmanalyse 
+Analyses networks
+.SH "SYNOPSIS"
+.PP
+.PP
+.nf
+gnmanalyse [--help][-q][-quiet][--long-usage]
+           [dijkstra start_gfid end_gfid [[-alo NAME=VALUE] ...]]]
+           [kpaths start_gfid end_gfid k [[-alo NAME=VALUE] ...]]]
+           [resource [[-alo NAME=VALUE] ...]]]
+           [-ds ds_name][-f ds_format][-l layer_name]
+           [[-dsco NAME=VALUE] ...][-lco NAME=VALUE]
+           gnm_name
+.fi
+.PP
+.SH "DESCRIPTION"
+.PP
+The gnmanalyse program provides analysing capabilities of geographical networks in GDAL\&. The results of calculations are return in an OGRLayer format or as a console text output if such layer is undefined\&. All calculations are made considering the blocking state of features\&.
+.PP
+.IP "\fB\fBdijkstra\fP \fIstart_gfid\fP \fIend_gfid\fP:\fP" 1c
+Calculates the best path between two points using Dijkstra algorithm from start_gfid point to end_gfid point\&. 
+.PP
+.IP "\fB\fBkpaths\fP \fIstart_gfid\fP \fIend_gfid\fP:\fP" 1c
+Calculates K shortest paths between two points using Yen's algorithm (which internally uses Dijkstra algorithm for single path calculating) from start_gfid point to end_gfid point\&. 
+.PP
+.IP "\fB\fBresource\fP:\fP" 1c
+Calculates the 'resource distribution'\&. The connected components search is performed using breadth-first search and starting from that features which are marked by rules as 'EMITTERS'\&. 
+.PP
+.IP "\fB\fB-ds\fP \fIds_name\fP:\fP" 1c
+The name&path of the dataset to save the layer with resulting paths\&. Not need to be existed dataset\&. 
+.PP
+.IP "\fB\fB-f\fP \fIds_format\fP:\fP" 1c
+Define this to set the format of newly created dataset\&. 
+.PP
+.IP "\fB\fB-l\fP \fIlayer_name\fP:\fP" 1c
+The name of the resulting layer\&. If the layer exist already - it will be rewritten\&. 
+.PP
+.IP "\fB\fIgnm_name\fP:\fP" 1c
+The network to work with (path and name)\&. 
+.PP
+.IP "\fB\fB-dsco\fP \fINAME=VALUE\fP:\fP" 1c
+Dataset creation option (format specific) 
+.IP "\fB\fB-lco\fP\fI NAME=VALUE\fP:\fP" 1c
+Layer creation option (format specific) 
+.IP "\fB\fB-alo\fP\fI NAME=VALUE\fP:\fP" 1c
+Algorithm option (format specific) 
+.PP
+.SH "AUTHORS"
+.PP
+Mikhail Gusev gusevmihs at gmail.com Dmitry Baryshnikov polimax at mail.ru 
diff --git a/man/man1/gnmmanage.1 b/man/man1/gnmmanage.1
new file mode 100644
index 0000000..26a7e6f
--- /dev/null
+++ b/man/man1/gnmmanage.1
@@ -0,0 +1,85 @@
+.TH "gnmmanage" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
+.ad l
+.nh
+.SH NAME
+gnmmanage \- gnmmanage 
+Manages networks
+.SH "SYNOPSIS"
+.PP
+.PP
+.nf
+gnmmanage [--help][-q][-quiet][--long-usage]
+          [info]
+          [create [-f format_name] [-t_srs srs_name] [-dsco NAME=VALUE]... ]
+          [import src_dataset_name] [-l layer_name]
+          [connect gfid_src gfid_tgt gfid_con [-c cost] [-ic inv_cost] [-dir dir]]
+          [disconnect gfid_src gfid_tgt gfid_con]
+          [rule rule_str]
+          [autoconnect tolerance]
+          [delete]
+          [change [-bl gfid][-unbl gfid][-unblall]]
+          gnm_name [layer [layer ...]].fi
+.PP
+.SH "DESCRIPTION"
+.PP
+The gnmmanage program can perform various managing operations on geographical networks in GDAL\&. In addition to creating and deleting networks this includes capabilities of managing network's features, topology and rules\&.
+.PP
+.IP "\fB\fBinfo\fP:\fP" 1c
+Different information about network: system and class layers, network metadata, network spatial reference\&. 
+.PP
+.IP "\fB\fBcreate\fP:\fP" 1c
+Create network\&.  
+.IP "\fB\fB-f\fP \fIformat_name\fP:\fP" 1c
+Output file format name\&.  
+.IP "\fB\fB-t_srs\fP \fIsrs_name\fP:\fP" 1c
+Spatial reference input\&.  
+.IP "\fB\fB-dsco\fP \fINAME=VALUE\fP:\fP" 1c
+Network creation option set as pair name=value\&.  
+.PP
+.PP
+.IP "\fB\fBimport\fP \fIsrc_dataset_name\fP:\fP" 1c
+Import layer with dataset name to copy\&.  
+.IP "\fB\fB-l\fP \fIlayer_name\fP:\fP" 1c
+Layer name in dataset\&. If unset, 0 layer is copied\&.  
+.PP
+.PP
+.IP "\fB\fBconnect\fP \fIgfid_src\fP \fIgfid_tgt\fP \fIgfid_con\fP:\fP" 1c
+Make a topological connection, where the gfid_src and gfid_tgt are vertexes and gfid_con is edge (gfid_con can be -1, so the system edge will be inserted)\&.  
+.IP "\fB\fB-c\fP \fIcost\fP \fB-ic\fP \fIinv_cost\fP \fB-dir\fP \fIdir\fP:\fP" 1c
+Manually assign the following values: the cost (weight), inverse cost and direction of the edge (optional)\&.  
+.PP
+.PP
+.IP "\fB\fBdisconnect\fP \fIgfid_src\fP \fIgfid_tgt\fP \fIgfid_con\fP:\fP" 1c
+Removes the connection from the graph\&. 
+.PP
+.IP "\fB\fBrule\fP \fIrule_str\fP:\fP" 1c
+Creates a rule in the network by the given rule_str string\&. 
+.PP
+.IP "\fB\fBautoconnect\fP \fItolerance\fP:\fP" 1c
+Create topology automatically with the given double tolerance and layer names\&. In no layer name provided all layers of network will be used\&.
+.PP
+.IP "\fB\fBdelete\fP:\fP" 1c
+Delete network\&. 
+.PP
+.IP "\fB\fBchange\fP:\fP" 1c
+Change blocking state of network edges or vertices\&. 
+.PP
+.IP "\fB\fB-bl\fP \fIgfid\fP:\fP" 1c
+Block feature before the main operation\&. Blocking features are saved in the special layer\&. 
+.PP
+.IP "\fB\fB-unbl\fP \fIgfid\fP:\fP" 1c
+Unblock feature before the main operation\&. 
+.PP
+.IP "\fB\fB-unblall\fP:\fP" 1c
+Unblock all blocked features before the main operation\&. 
+.PP
+.IP "\fB\fIgnm_name\fP:\fP" 1c
+The network to work with (path and name)\&. 
+.PP
+.IP "\fB\fIlayer\fP:\fP" 1c
+The network layer name\&. 
+.PP
+.PP
+.SH "AUTHORS"
+.PP
+Mikhail Gusev gusevmihs at gmail.com Dmitry Baryshnikov polimax at mail.ru 
diff --git a/man/man1/nearblack.1 b/man/man1/nearblack.1
index f9fb9c4..15b46e6 100644
--- a/man/man1/nearblack.1
+++ b/man/man1/nearblack.1
@@ -1,4 +1,4 @@
-.TH "nearblack" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "nearblack" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -14,12 +14,12 @@ nearblack [-of format] [-white | [-color c1,c2,c3...cn]*] [-near dist] [-nb non_
 .PP
 .SH "DESCRIPTION"
 .PP
-This utility will scan an image and try to set all pixels that are nearly or exactly black, white or one or more custom colors around the collar to black or white\&. This is often used to 'fix up' lossy compressed airphotos so that color pixels can be treated as transparent when mosaicking\&.
+This utility will scan an image and try to set all pixels that are nearly or exactly black, white or one or more custom colors around the collar to black or white\&. This is often used to 'fix up' lossy compressed air photos so that color pixels can be treated as transparent when mosaicing\&.
 .PP
 .IP "\fB\fB-o\fP \fIoutfile\fP:\fP" 1c
 The name of the output file to be created\&. Newly created files are created with the HFA driver by default (Erdas Imagine - \&.img) 
 .IP "\fB\fB-of\fP \fIformat\fP:\fP" 1c
-(GDAL 1\&.8\&.0 or later) Select the output format\&. Use the short format name (GTiff for GeoTIFF for examle)\&. 
+(GDAL 1\&.8\&.0 or later) Select the output format\&. Use the short format name (GTiff for GeoTIFF for example)\&. 
 .IP "\fB\fB-co\fP \fI'NAME=VALUE'\fP:\fP" 1c
 (GDAL 1\&.8\&.0 or later) Passes a creation option to the output format driver\&. Multiple \fB-co\fP options may be listed\&. See format specific documentation for legal creation options for each format\&. Only valid when creating a new file 
 .IP "\fB\fB-white\fP:\fP" 1c
@@ -45,6 +45,9 @@ The algorithm processes the image one scanline at a time\&. A scan 'in' is done
 The processing is all done in 8bit (Bytes)\&.
 .PP
 If the output file is omitted, the processed results will be written back to the input file - which must support update\&.
+.SH "C API"
+.PP
+Starting with GDAL 2\&.1, this utility is also callable from C with GDALNearblack()\&.
 .SH "AUTHORS"
 .PP
 Frank Warmerdam warmerdam at pobox.com 
diff --git a/man/man1/ogr2ogr.1 b/man/man1/ogr2ogr.1
index 5f05c0d..acc74aa 100644
--- a/man/man1/ogr2ogr.1
+++ b/man/man1/ogr2ogr.1
@@ -1,4 +1,4 @@
-.TH "ogr2ogr" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "ogr2ogr" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -10,8 +10,8 @@ converts simple features data between file formats
 .PP
 .nf
 Usage: ogr2ogr [--help-general] [-skipfailures] [-append] [-update]
-               [-select field_list] [-where restricted_where] 
-               [-progress] [-sql <sql statement>] [-dialect dialect]
+               [-select field_list] [-where restricted_where|@filename] 
+               [-progress] [-sql <sql statement>|@filename] [-dialect dialect]
                [-preserve_fid] [-fid FID]
                [-spat xmin ymin xmax ymax] [-spat_srs srs_def] [-geomfield field]
                [-a_srs srs_def] [-t_srs srs_def] [-s_srs srs_def]
@@ -19,7 +19,7 @@ Usage: ogr2ogr [--help-general] [-skipfailures] [-append] [-update]
                dst_datasource_name src_datasource_name
                [-lco NAME=VALUE] [-nln name]
                [-nlt type|PROMOTE_TO_MULTI|CONVERT_TO_LINEAR]
-               [-dim 2|3|layer_dim] [layer [layer ...]]
+               [-dim XY|XYZ|XYM|XYZM|2|3|layer_dim] [layer [layer ...]]
 
 Advanced options :
                [-gt n]
@@ -40,7 +40,7 @@ Advanced options :
                [-splitlistfields] [-maxsubfields val]
                [-explodecollections] [-zfield field_name]
                [-gcp pixel line easting northing [elevation]]* [-order n | -tps]
-               [-nomd] [-mo \"META-TAG=VALUE\"]*.fi
+               [-nomd] [-mo \"META-TAG=VALUE\"]* [-noNativeData].fi
 .PP
 .SH "DESCRIPTION"
 .PP
@@ -69,11 +69,11 @@ Comma-delimited list of fields from input layer to copy to the new layer\&. A fi
 .IP "\fB\fB-progress\fP:\fP" 1c
 (starting with GDAL 1\&.7\&.0) Display progress on terminal\&. Only works if input layers have the 'fast feature count' capability\&. 
 .IP "\fB\fB-sql\fP \fIsql_statement\fP:\fP" 1c
-SQL statement to execute\&. The resulting table/layer will be saved to the output\&. 
+SQL statement to execute\&. The resulting table/layer will be saved to the output\&. Starting with GDAL 2\&.1, the  syntax can be used to indicate that the content is in the pointed filename\&. 
 .IP "\fB\fB-dialect\fP \fIdialect\fP:\fP" 1c
 SQL dialect\&. In some cases can be used to use (unoptimized) OGR SQL instead of the native SQL of an RDBMS by passing OGRSQL\&. Starting with GDAL 1\&.10, the 'SQLITE' dialect can also be used with any datasource\&. 
 .IP "\fB\fB-where\fP\fI restricted_where\fP:\fP" 1c
-Attribute query (like SQL WHERE) 
+Attribute query (like SQL WHERE)\&. Starting with GDAL 2\&.1, the  syntax can be used to indicate that the content is in the pointed filename\&. 
 .IP "\fB\fB-skipfailures\fP:\fP" 1c
 Continue after a failure, skipping the failed feature\&. 
 .IP "\fB\fB-spat\fP\fI xmin ymin xmax ymax\fP:\fP" 1c
@@ -89,9 +89,9 @@ Layer creation option (format specific)
 .IP "\fB\fB-nln\fP\fI name\fP:\fP" 1c
 Assign an alternate name to the new layer 
 .IP "\fB\fB-nlt\fP\fI type\fP:\fP" 1c
-Define the geometry type for the created layer\&. One of NONE, GEOMETRY, POINT, LINESTRING, POLYGON, GEOMETRYCOLLECTION, MULTIPOINT, MULTIPOLYGON or MULTILINESTRING\&. And CIRCULARSTRING, COMPOUNDCURVE, CURVEPOLYGON, MULTICURVE and MULTISURFACE for GDAL 2\&.0 non-linear geometry types\&. Add '25D' to the name to get 2\&.5D versions\&. Starting with GDAL 1\&.10, PROMOTE_TO_MULTI can be used to automatically promote layers that mix polygon or multipolygons to multipolygons, and layers that [...]
+Define the geometry type for the created layer\&. One of NONE, GEOMETRY, POINT, LINESTRING, POLYGON, GEOMETRYCOLLECTION, MULTIPOINT, MULTIPOLYGON or MULTILINESTRING\&. And CIRCULARSTRING, COMPOUNDCURVE, CURVEPOLYGON, MULTICURVE and MULTISURFACE for GDAL 2\&.0 non-linear geometry types\&. Add 'Z', 'M', or 'ZM' to the name to get coordinates with elevation, measure, or elevation and measure\&. Starting with GDAL 1\&.10, PROMOTE_TO_MULTI can be used to automatically promote layers that mix  [...]
 .IP "\fB\fB-dim\fP\fI val\fP:\fP" 1c
-(starting with GDAL 1\&.10) Force the coordinate dimension to val (valid values are 2 or 3)\&. This affects both the layer geometry type, and feature geometries\&. Starting with GDAL 1\&.11, the value can be set to 'layer_dim' to instruct feature geometries to be promoted to the coordinate dimension declared by the layer\&.  
+(starting with GDAL 1\&.10) Force the coordinate dimension to val (valid values are XY, XYZ, XYM, and XYZM - for backwards compatibility 2 is an alias for XY and 3 is an alias for XYZ)\&. This affects both the layer geometry type, and feature geometries\&. Starting with GDAL 1\&.11, the value can be set to 'layer_dim' to instruct feature geometries to be promoted to the coordinate dimension declared by the layer\&. Support for M was added in GDAL 2\&.1 
 .IP "\fB\fB-a_srs\fP\fI srs_def\fP:\fP" 1c
 Assign an output SRS 
 .IP "\fB\fB-t_srs\fP\fI srs_def\fP:\fP" 1c
@@ -104,7 +104,7 @@ Use the FID of the source features instead of letting the output driver to autom
 If provided, only the feature with this feature id will be reported\&. Operates exclusive of the spatial or attribute queries\&. Note: if you want to select several features based on their feature id, you can also use the fact the 'fid' is a special field recognized by OGR SQL\&. So, '-where 'fid in (1,3,5)'' would select features 1, 3 and 5\&. 
 .PP
 .PP
-Srs_def can be a full WKT definition (hard to escape properly), or a well known definition (ie\&. EPSG:4326) or a file with a WKT definition\&.
+Srs_def can be a full WKT definition (hard to escape properly), or a well known definition (i\&.e\&. EPSG:4326) or a file with a WKT definition\&.
 .PP
 Advanced options :
 .PP
@@ -135,7 +135,7 @@ Restrict desired geometries based on attribute query\&.
 .IP "\fB\fB-wrapdateline\fP:\fP" 1c
 (starting with GDAL 1\&.7\&.0) split geometries crossing the dateline meridian (long\&. = +/- 180deg) 
 .IP "\fB\fB-datelineoffset\fP:\fP" 1c
-(starting with GDAL 1\&.10) offset from dateline in degrees (default long\&. = +/- 10deg, geometries within 170deg to -170deg will be splited) 
+(starting with GDAL 1\&.10) offset from dateline in degrees (default long\&. = +/- 10deg, geometries within 170deg to -170deg will be split) 
 .IP "\fB\fB-simplify\fP\fI tolerance\fP:\fP" 1c
 (starting with GDAL 1\&.9\&.0) distance tolerance for simplification\&. Note: the algorithm used preserves topology per feature, in particular for polygon geometries, but not for a whole layer\&. 
 .IP "\fB\fB-segmentize\fP\fI max_dist\fP:\fP" 1c
@@ -175,7 +175,9 @@ To be combined with -splitlistfields to limit the number of subfields created fo
 .IP "\fB\fB-nomd\fP:\fP" 1c
 (starting with GDAL 2\&.0) To disable copying of metadata from source dataset and layers into target dataset and layers, when supported by output driver\&. 
 .IP "\fB\fB-mo\fP \fI'META-TAG=VALUE'\fP:\fP" 1c
-(starting with GDAL 2\&.0) Passes a metadata key and value to set on the output dataset, when supported by output driver\&.
+(starting with GDAL 2\&.0) Passes a metadata key and value to set on the output dataset, when supported by output driver\&. 
+.IP "\fB\fB-noNativeData\fP:\fP" 1c
+(starting with GDAL 2\&.1) To disable copying of native data, i\&.e\&. details of source format not captured by OGR abstraction, that are otherwise preserved by some drivers (like GeoJSON) when converting to same format\&.
 .PP
 .PP
 .SH "PERFORMANCE HINTS"
@@ -185,6 +187,9 @@ When writing into transactional DBMS (SQLite/PostgreSQL,MySQL, etc\&.\&.\&.), it
 For PostgreSQL, the PG_USE_COPY config option can be set to YES for significantly insertion performance boot\&. See the PG driver documentation page\&.
 .PP
 More generally, consult the documentation page of the input and output drivers for performance hints\&.
+.SH "C API"
+.PP
+Starting with GDAL 2\&.1, this utility is also callable from C with GDALVectorTranslate()\&.
 .SH "EXAMPLE"
 .PP
 Example appending to an existing layer (both flags need to be used):
diff --git a/man/man1/ogr_utilities.1 b/man/man1/ogr_utilities.1
index 9f26836..57033b3 100644
--- a/man/man1/ogr_utilities.1
+++ b/man/man1/ogr_utilities.1
@@ -1,4 +1,4 @@
-.TH "ogr_utilities" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "ogr_utilities" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -17,4 +17,30 @@ The following utilities are distributed as part of the OGR Simple Features toolk
 .IP "\(bu" 2
 \fBogrlineref\fP - Create linear reference and provide some calculations using it 
 .PP
+.SH "General Command Line Switches"
+.PP
+All GDAL OGR command line utility programs support the following 'general' options\&.
+.PP
+.IP "\fB\fB--version\fP\fP" 1c
+Report the version of GDAL and exit\&.
+.PP
+.IP "\fB\fB--formats\fP\fP" 1c
+List all vector formats supported by this GDAL build (read-only and read-write) and exit\&. The format support is indicated as follows: 'ro' is read-only driver; 'rw' is read or write (i\&.e\&. supports CreateCopy); 'rw+' is read, write and update (i\&.e\&. supports Create)\&. A 'v' is appended for formats supporting virtual IO (/vsimem, /vsigzip, /vsizip, etc)\&. A 's' is appended for formats supporting subdatasets\&. 
+.PP
+.IP "\fB\fB--format\fP \fIformat\fP\fP" 1c
+List detailed information about a single format driver\&. The \fIformat\fP should be the short name reported in the \fB--formats\fP list, such as GML\&.
+.PP
+.IP "\fB\fB--optfile\fP \fIfile\fP\fP" 1c
+Read the named file and substitute the contents into the command line options list\&. Lines beginning with # will be ignored\&. Multi-word arguments may be kept together with double quotes\&. 
+.PP
+.IP "\fB\fB--config\fP \fIkey value\fP\fP" 1c
+Sets the named \fCconfiguration keyword\fP to the given value, as opposed to setting them as environment variables\&. Some common configuration keywords are SHAPE_ENCODING (force shapefile driver to read DBF files with the given character encoding) and CPL_TEMPDIR (define the location of temporary files)\&. Individual drivers may be influenced by other configuration options\&. 
+.PP
+.IP "\fB\fB--debug\fP \fIvalue\fP\fP" 1c
+Control what debugging messages are emitted\&. A value of \fION\fP will enable all debug messages\&. A value of \fIOFF\fP will disable all debug messages\&. Another value will select only debug messages containing that string in the debug prefix code\&. 
+.PP
+.IP "\fB\fB--help-general\fP\fP" 1c
+Gives a brief usage message for the generic GDAL OGR command line options and exit\&. 
+.PP
+.PP
 
diff --git a/man/man1/ogrinfo.1 b/man/man1/ogrinfo.1
index 4de4bc9..45bb4f7 100644
--- a/man/man1/ogrinfo.1
+++ b/man/man1/ogrinfo.1
@@ -1,4 +1,4 @@
-.TH "ogrinfo" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "ogrinfo" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -9,10 +9,10 @@ lists information about an OGR supported data source
 .PP
 .PP
 .nf
-ogrinfo [--help-general] [-ro] [-q] [-where restricted_where]
+ogrinfo [--help-general] [-ro] [-q] [-where restricted_where|@filename]
         [-spat xmin ymin xmax ymax] [-geomfield field] [-fid fid]
-        [-sql statement] [-dialect dialect] [-al] [-so] [-fields={YES/NO}]
-        [-geom={YES/NO/SUMMARY}] [-formats] [[-oo NAME=VALUE] ...]
+        [-sql statement|@filename] [-dialect dialect] [-al] [-so] [-fields={YES/NO}]
+        [-geom={YES/NO/SUMMARY/WKT/ISO_WKT}] [-formats] [[-oo NAME=VALUE] ...]
         [-nomd] [-listmdd] [-mdd domain|`all`]*
         [-nocount] [-noextent]
         datasource_name [layer [layer ...]].fi
@@ -30,9 +30,9 @@ Summary Only: suppress listing of features, show only the summary information li
 .IP "\fB\fB-q\fP:\fP" 1c
 Quiet verbose reporting of various information, including coordinate system, layer schema, extents, and feature count\&.  
 .IP "\fB\fB-where\fP \fIrestricted_where\fP:\fP" 1c
-An attribute query in a restricted form of the queries used in the SQL WHERE statement\&. Only features matching the attribute query will be reported\&. 
+An attribute query in a restricted form of the queries used in the SQL WHERE statement\&. Only features matching the attribute query will be reported\&. Starting with GDAL 2\&.1, the  syntax can be used to indicate that the content is in the pointed filename\&. 
 .IP "\fB\fB-sql\fP \fIstatement\fP:\fP" 1c
-Execute the indicated SQL statement and return the result\&. 
+Execute the indicated SQL statement and return the result\&. Starting with GDAL 2\&.1, the  syntax can be used to indicate that the content is in the pointed filename\&. 
 .IP "\fB\fB-dialect\fP \fIdialect\fP:\fP" 1c
 SQL dialect\&. In some cases can be used to use (unoptimized) OGR SQL instead of the native SQL of an RDBMS by passing OGRSQL\&. Starting with GDAL 1\&.10, the 'SQLITE' dialect can also be used with any datasource\&. 
 .IP "\fB\fB-spat\fP \fIxmin ymin xmax ymax\fP:\fP" 1c
@@ -43,8 +43,8 @@ The area of interest\&. Only features within the rectangle will be reported\&.
 If provided, only the feature with this feature id will be reported\&. Operates exclusive of the spatial or attribute queries\&. Note: if you want to select several features based on their feature id, you can also use the fact the 'fid' is a special field recognized by OGR SQL\&. So, '-where 'fid in (1,3,5)'' would select features 1, 3 and 5\&. 
 .IP "\fB\fB-fields\fP={YES/NO}:\fP" 1c
 (starting with GDAL 1\&.6\&.0) If set to NO, the feature dump will not display field values\&. Default value is YES\&. 
-.IP "\fB\fB-geom\fP={YES/NO/SUMMARY}:\fP" 1c
-(starting with GDAL 1\&.6\&.0) If set to NO, the feature dump will not display the geometry\&. If set to SUMMARY, only a summary of the geometry will be displayed\&. If set to YES, the geometry will be reported in full OGC WKT format\&. Default value is YES\&. 
+.IP "\fB\fB-geom\fP={YES/NO/SUMMARY/WKT/ISO_WKT}:\fP" 1c
+(starting with GDAL 1\&.6\&.0) If set to NO, the feature dump will not display the geometry\&. If set to SUMMARY, only a summary of the geometry will be displayed\&. If set to YES or ISO_WKT, the geometry will be reported in full OGC WKT format\&. If set to WKT the geometry will be reported in legacy WKT\&. Default value is YES\&. (WKT and ISO_WKT are available starting with GDAL 2\&.1, which also changes the default to ISO_WKT) 
 .IP "\fB\fB-oo\fP \fINAME=VALUE\fP:\fP" 1c
 (starting with GDAL 2\&.0) Dataset open option (format specific) 
 .IP "\fB\fB-nomd\fP\fP" 1c
@@ -65,7 +65,7 @@ The data source to open\&. May be a filename, directory or other virtual name\&.
 One or more layer names may be reported\&. 
 .PP
 .PP
-If no layer names are passed then ogrinfo will report a list of available layers (and their layerwide geometry type)\&. If layer name(s) are given then their extents, coordinate system, feature count, geometry type, schema and all features matching query parameters will be reported to the terminal\&. If no query parameters are provided, all features are reported\&.
+If no layer names are passed then ogrinfo will report a list of available layers (and their layer wide geometry type)\&. If layer name(s) are given then their extents, coordinate system, feature count, geometry type, schema and all features matching query parameters will be reported to the terminal\&. If no query parameters are provided, all features are reported\&.
 .PP
 Geometries are reported in OGC WKT format\&.
 .SH "EXAMPLE"
diff --git a/man/man1/ogrlineref.1 b/man/man1/ogrlineref.1
index ebf0db0..de77bc5 100644
--- a/man/man1/ogrlineref.1
+++ b/man/man1/ogrlineref.1
@@ -1,4 +1,4 @@
-.TH "ogrlineref" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "ogrlineref" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -32,7 +32,7 @@ ogrlineref [--help-general] [-progress] [-quiet]
 .PP
 .SH "DESCRIPTION"
 .PP
-The ogrlineref program can be used to create a linear reference - a file containing a segments of special length (e\&.g\&. 1 km in reference units) and get coordinates, linear referenced distances or sublines (subpaths) from this file\&. The utility not required the M or Z values in geometry\&. The results can be stored in any OGR supported format\&. Also some information writed to the stdout\&.
+The ogrlineref program can be used to create a linear reference - a file containing a segments of special length (e\&.g\&. 1 km in reference units) and get coordinates, linear referenced distances or sublines (subpaths) from this file\&. The utility not required the M or Z values in geometry\&. The results can be stored in any OGR supported format\&. Also some information is written to the stdout\&.
 .PP
 .IP "\fB\fB--help-general\fP:\fP" 1c
 Show the usage\&. 
@@ -53,7 +53,7 @@ The path to input linestring datasource (e\&.g\&. the road)
 .IP "\fB\fB-ln\fP\fIlayer_name\fP:\fP" 1c
 The layer name in datasource 
 .IP "\fB\fB-lf\fP\fIfield_name\fP:\fP" 1c
-The field name of uniq values to separate the input lines (e\&.g\&. the set of roads) 
+The field name of unique values to separate the input lines (e\&.g\&. the set of roads) 
 .IP "\fB\fB-p\fP\fIsrc_repers_datasource_name\fP:\fP" 1c
 The path to linear references points (e\&.g\&. the road mile-stones) 
 .IP "\fB\fB-pn\fP\fIlayer_name\fP:\fP" 1c
@@ -61,7 +61,7 @@ The layer name in datasource
 .IP "\fB\fB-pm\fP\fIpos_field_name\fP:\fP" 1c
 The field name of distances along path (e\&.g\&. mile-stones values) 
 .IP "\fB\fB-pf\fP\fIfield_name\fP:\fP" 1c
-The field name of uniq values to map input reference points to lines 
+The field name of unique values to map input reference points to lines 
 .IP "\fB\fB-r\fP\fIsrc_parts_datasource_name\fP:\fP" 1c
 The path to linear reference file 
 .IP "\fB\fB-rn\fP\fIlayer_name\fP:\fP" 1c
@@ -71,11 +71,11 @@ The path to output linear reference file (linestring datasource)
 .IP "\fB\fB-on\fP\fIlayer_name\fP:\fP" 1c
 The layer name in datasource 
 .IP "\fB\fB-of\fP\fIfield_name\fP:\fP" 1c
-The field name for storing the uniq values of input lines 
+The field name for storing the unique values of input lines 
 .IP "\fB\fB-s\fP\fIstep\fP:\fP" 1c
 The part size in linear units 
 .IP "\fB\fB-get_pos\fP:\fP" 1c
-Return linear referenced postion for input X, Y 
+Return linear referenced position for input X, Y 
 .IP "\fB\fB-x\fP\fIlong\fP:\fP" 1c
 Input X coordinate 
 .IP "\fB\fB-y\fP\fIlat\fP:\fP" 1c
diff --git a/man/man1/ogrtindex.1 b/man/man1/ogrtindex.1
index bb10e0a..2eccf61 100644
--- a/man/man1/ogrtindex.1
+++ b/man/man1/ogrtindex.1
@@ -1,4 +1,4 @@
-.TH "ogrtindex" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "ogrtindex" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/pct2rgb.1 b/man/man1/pct2rgb.1
index c64e999..2fc727e 100644
--- a/man/man1/pct2rgb.1
+++ b/man/man1/pct2rgb.1
@@ -1,4 +1,4 @@
-.TH "pct2rgb" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "pct2rgb" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -14,7 +14,7 @@ pct2rgb.py [-of format] [-b band] [-rgba] source_file dest_file
 .PP
 .SH "DESCRIPTION"
 .PP
-This utility will convert a pseudocolor band on the input file into an output RGB file of the desired format\&.
+This utility will convert a pseudo-color band on the input file into an output RGB file of the desired format\&.
 .PP
 .IP "\fB\fB-of\fP \fIformat\fP:\fP" 1c
 Format to generated (defaults to GeoTIFF)\&. 
diff --git a/man/man1/rgb2pct.1 b/man/man1/rgb2pct.1
index 410c4a9..7e93ba3 100644
--- a/man/man1/rgb2pct.1
+++ b/man/man1/rgb2pct.1
@@ -1,4 +1,4 @@
-.TH "rgb2pct" 1 "Tue Jan 26 2016" "GDAL" \" -*- nroff -*-
+.TH "rgb2pct" 1 "Fri Apr 1 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -20,7 +20,7 @@ Select the number of colors in the generated color table\&. Defaults to 256\&. M
 .IP "\fB\fB-pct\fP \fIpalette_file\fP:\fP" 1c
 Extract the color table from \fIpalette_file\fP instead of computing it\&. Can be used to have a consistent color table for multiple files\&. The \fIpalette_file\fP must be a raster file in a GDAL supported format with a palette\&. 
 .IP "\fB\fB-of\fP \fIformat\fP:\fP" 1c
-Format to generated (defaults to GeoTIFF)\&. Same semantics as the \fB-of\fP flag for gdal_translate\&. Only output formats supporting pseudocolor tables should be used\&.  
+Format to generated (defaults to GeoTIFF)\&. Same semantics as the \fB-of\fP flag for gdal_translate\&. Only output formats supporting pseudo-color tables should be used\&.  
 .IP "\fB\fIsource_file\fP:\fP" 1c
 The input RGB file\&.  
 .IP "\fB\fIdest_file\fP:\fP" 1c
diff --git a/mkbindist.sh b/mkbindist.sh
index 171066a..17fa43f 100755
--- a/mkbindist.sh
+++ b/mkbindist.sh
@@ -52,10 +52,6 @@ fi
 mkdir $DIST_DIR/html
 cp html/* $DIST_DIR/html
 
-cp dist_docs/README_UNX_BIN.TXT $DIST_DIR
-cp dist_docs/install_unx.sh $DIST_DIR
-cc -o $DIST_DIR/bin/burnpath dist_docs/burnpath.c
-
 #
 # Clean anything we don't want for non-developer releases.
 #
diff --git a/mkgdaldist.sh b/mkgdaldist.sh
index 0b89004..ca94245 100755
--- a/mkgdaldist.sh
+++ b/mkgdaldist.sh
@@ -1,16 +1,26 @@
 #!/bin/sh
 #
-# $Id: mkgdaldist.sh 25966 2013-04-29 20:33:17Z nowakpl $
+# $Id: mkgdaldist.sh 33096 2016-01-22 18:00:06Z rouault $
 #
 # mkgdaldist.sh - prepares GDAL source distribution package
 #
+
+# Doxgen 1.7.1 has a bug related to man pages. See https://trac.osgeo.org/gdal/ticket/6048
+echo $(doxygen --version) | xargs python -c "import sys; v = sys.argv[1].split('.'); v=int(v[0])*10000+int(v[1])*100+int(v[2]); sys.exit(v < 10704)"
+rc=$?
+if test $rc != 0; then
+    echo "Wrong Doxygen version. 1.7.4 or later required"
+    exit $rc;
+fi
+
 if [ $# -lt 1 ] ; then
   echo "Usage: mkgdaldist.sh <version> [-date date] [-branch branch] [-rc n]"
   echo " <version> - version number used in name of generated archive."
   echo " -date     - date of package generation, current date used if not provided"
   echo " -branch   - path to SVN branch, trunk is used if not provided"
   echo " -rc       - gives a release candidate id to embed in filenames"
-  echo "Example: mkgdaldist.sh 1.1.4 -branch branches/1.8 -rc RC2"
+  echo "Example: mkgdaldist.sh 1.8.0 -branch branches/1.8 -rc RC2"
+  echo "or       mkgdaldist.sh 1.10.0beta2"
   exit
 fi
 
@@ -84,6 +94,7 @@ fi
 
 echo "* Cleaning .svn directories under $PWD..."
 find gdal -name .svn | xargs rm -rf
+rm -f gdal/.gitignore
 
 #
 # Generate man pages
@@ -128,8 +139,6 @@ cd ${CWD}
 # Make distribution packages
 #
 echo "* Making distribution packages..."
-rm -rf gdal/dist_docs
-
 rm -f gdal/VERSION
 echo $GDAL_VERSION > gdal/VERSION
 
diff --git a/mktestdist.sh b/mktestdist.sh
index 0041c60..f181900 100755
--- a/mktestdist.sh
+++ b/mktestdist.sh
@@ -12,7 +12,7 @@ GDAL_VERSION=$1
 if test "$GDAL_VERSION" != "`cat VERSION`" ; then
   echo
   echo "NOTE: local VERSION file (`cat VERSION`) does not match supplied version ($GDAL_VERSION)."
-  echo "      Consider updating local VERSION file, and commiting to CVS." 
+  echo "      Consider updating local VERSION file, and committing to CVS." 
   echo
 fi
 
diff --git a/nmake-wince.opt b/nmake-wince.opt
deleted file mode 100644
index b76235d..0000000
--- a/nmake-wince.opt
+++ /dev/null
@@ -1,145 +0,0 @@
-# $Id: nmake-wince.opt 10609 2007-01-15 17:41:47Z  $
-#
-# Building options for Windows CE target
-#
-# Created by Mateusz Loskot <mateusz at loskot.net>
-#
-
-#################################################
-# NOTE: Macros below are going to be changed
-# and waits for configure script.
-# Configure script will make it possible to 
-# specify target CPU and system platform, etc.
-#################################################
-# Target platform definitions
-CEVersion	= 420
-CESubsystem	= "windowsce,$(CEVersion)"
-CEConfigName	= "POCKET PC 2003"
-
-# Target CPU
-TARGET_CPU	= ARM
-TARGET_CPU_ARCH	= ARMV4
-
-CECrt		= C
-CECrtDebug	= C
-CECrtMT		= C
-CECrtMTDebug	= C
-CENoDefaultLib	= libc.lib \
-		  /nodefaultlib:libcd.lib \
-		  /nodefaultlib:libcmt.lib \
-		  /nodefaultlib:libcmtd.lib \
-		  /nodefaultlib:msvcrt.lib \
-		  /nodefaultlib:msvcrtd.lib
-CEx86Corelibc	= corelibc.lib
-
-# Commands
-MAKE = nmake /nologo
-CC = clarm
-
-#################################################
-# END OF TEMPORARY MACROS BLOCK 
-#################################################
-
-# Location to install .exe, .dll and python stuff
-# Edit as required. GDAL_HOME is used for convenience here,
-# but this particular relative organization is not mandatory.
-
-GDAL_HOME	= "build"
-BINDIR		= $(GDAL_HOME)\bin
-LIBDIR		= $(GDAL_HOME)\lib
-INCDIR		= $(GDAL_HOME)\include
-DATADIR		= $(GDAL_HOME)\data
-HTMLDIR		= $(GDAL_HOME)\html
-
-# Uncomment the first for an optimized build or the second for a debug build.
-#OPTFLAGS= /MD /GX /Ox /nologo
-OPTFLAGS = /W3 /GR /GX /Zi /Od /nologo /D "DEBUG"
-
-# If you don't want some entry points to have STDCALL conventions, 
-# comment out the following and add -DCPL_DISABLE_STDCALL in OPTFLAGS
-STDCALL = YES
-
-# Version number embedded in DLL name. 
-VERSION = 13
-
-# Uncomment the following to link OGR utilities against main GDAL DLL
-# instead of statically linking against OGR libraries.
-DLLBUILD = 1
-
-# OGR Drivers supported on Windows CE
-# Uncomment OGR drivers you want to include.
-# NOTE: Only few drivers are supported by Windows CE (shape, tab)
-# and some are going to be supported in future (csv, gml, sqlite).
-# Rest of drivers are not going to be supported.
-# 
-#AVCBIN_SUPPORTED = 1
-#CSV_SUPPORTED	= 1
-#DGN_SUPPORTED	= 1
-#GML_SUPPORTED	= 1
-#MEM_SUPPORTED	= 1
-#NTF_SUPPORTED	= 1
-#REC_SUPPORTED	= 1
-#S57_SUPPORTED	= 1
-#SDTS_SUPPORTED	= 1
-SHAPE_SUPPORTED = 1
-TAB_SUPPORTED	= 1
-#TIGER_SUPPORTED= 1
-#VRT_SUPPORTED	= 1
-
-# Paths
-STLPORT_USE	= 1
-STLPORT_DIR	= C:\STLport-5.0.0
-WCELIBCEX_DIR	= wince\wcelibcex
-
-########### END OF STUFF THAT NORMALLY NEEDS TO BE UPDATED ##################
-
-GDAL_OUTPUT = gdalce
-
-GDAL_DLL	= $(GDAL_ROOT)\$(GDAL_OUTPUT)$(VERSION).dll
-GDAL_I_LIB	= $(GDAL_ROOT)\$(GDAL_OUTPUT)_i.lib
-GDAL_LIB	= $(GDAL_ROOT)\$(GDAL_OUTPUT).lib
-
-CPL_LIB		= $(GDAL_ROOT)\port/cpl.lib
-WCELIBCEX_LIB	= $(GDAL_ROOT)\$(WCELIBCEX_DIR)\wcelibcex.lib
-
-INC =	/I "$(GDAL_ROOT)\port" \
-	/I "$(GDAL_ROOT)\ogr" \
-	/I "$(GDAL_ROOT)\$(WCELIBCEX_DIR)"
-		 
-OPTFLAGS = $(OPTFLAGS)  /Fd$(GDAL_ROOT)\$(GDAL_OUTPUT).pdb
-
-LINKER_FLAGS =	/nologo \
-		/entry:"_DllMainCRTStartup" \
-		/base:"0x00100000" \
-		/stack:0x10000,0x1000 \
-		/align:"4096" \
-		/incremental:no \
-		/nodefaultlib:"$(CENoDefaultLib)" \
-		/subsystem:$(CESubsystem) \
-		/MACHINE:ARM
-
-#LINKER_FLAGS = /debug
-
-CFLAGS = $(OPTFLAGS) \
-	 $(INC) \
-	 $(EXTRAFLAGS) \
-	 /D "_LIB" \
-	 /D "$(CESubsystem)" \
-	 /D "_WIN32_WCE=$(CEVersion)" \
-	 /D "UNDER_CE=$(CEVersion)" \
-	 /D "$(TARGET_CPU)" \
-	 /D "_$(TARGET_CPU)_" \
-	 /D "$(TARGET_CPU_ARCH)" \
-	 /D "UNICODE" /D "_UNICODE" 
-
-EXTERNAL_LIBS = commctrl.lib \
-		coredll.lib \
-		corelibc.lib \
-		ccrtrtti.lib
-
-.c.obj:	
-	$(CC) $(CFLAGS) /c $*.c
-
-.cpp.obj:	
-	$(CC) $(CFLAGS) /c $*.cpp
-
diff --git a/nmake.opt b/nmake.opt
index bc4c93a..418c759 100644
--- a/nmake.opt
+++ b/nmake.opt
@@ -1,4 +1,4 @@
-# $Id: nmake.opt 32023 2015-12-06 12:13:58Z rouault $
+# $Id: nmake.opt 33775 2016-03-23 20:25:05Z tamas $
 #
 # nmake.opt - main configuration file for NMAKE makefiles.
 #
@@ -37,9 +37,8 @@
 # 1600 = 10.0(2010)
 # 1500 = 9.0 (2008)
 # 1400 = 8.0 (2005) - specific compilation flags, different from older VC++
-# 1310 = 7.1 (2003)
-# 1300 = 7.0 (2002)
-# 1200 = 6.0
+# 1310 = 7.1 (2003) # is it still supported ?
+# 1300 = 7.0 (2002) # is it still supported ?
 #
 !IFNDEF MSVC_VER
 #assume msvc VS2008.
@@ -106,7 +105,7 @@ JAVA_INCLUDE=-I$(JAVA_HOME)\include -I$(JAVA_HOME)\include\win32
 
 # Compilation flags
 
-# Enable code analyzis on request
+# Enable code analysis on request
 # http://msdn.microsoft.com/en-us/library/ms173498.aspx
 !IFDEF ANALYZE
 CXX_ANALYZE_FLAGS=/analyze
@@ -128,15 +127,15 @@ CXX_PDB_FLAGS=
 !IFNDEF OPTFLAGS
 !IF $(MSVC_VER) >= 1400
 !IFNDEF DEBUG
-OPTFLAGS= $(CXX_ANALYZE_FLAGS) $(CXX_PDB_FLAGS) /nologo /MD /EHsc /Ox /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /DNDEBUG
+OPTFLAGS= $(CXX_ANALYZE_FLAGS) $(CXX_PDB_FLAGS) /nologo /MD /EHsc /Ox /FC /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /DNDEBUG
 !ELSE
-OPTFLAGS= $(CXX_ANALYZE_FLAGS) $(CXX_PDB_FLAGS) /nologo /MD /EHsc /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /DDEBUG
+OPTFLAGS= $(CXX_ANALYZE_FLAGS) $(CXX_PDB_FLAGS) /nologo /MD /EHsc /FC /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /DDEBUG
 !ENDIF
 !ELSE
 !IFNDEF DEBUG
-OPTFLAGS= $(CXX_PDB_FLAGS) /nologo /MD /EHsc /GR /Ox /DNDEBUG
+OPTFLAGS= $(CXX_PDB_FLAGS) /nologo /MD /EHsc /GR /Ox /FC /DNDEBUG
 !ELSE
-OPTFLAGS= $(CXX_PDB_FLAGS) /nologo /MD /EHsc /GR /DDEBUG
+OPTFLAGS= $(CXX_PDB_FLAGS) /nologo /MD /EHsc /GR /FC /DDEBUG
 !ENDIF
 !ENDIF  #MSVC_VER
 !ENDIF  # OPTFLAGS
@@ -145,7 +144,16 @@ OPTFLAGS= $(CXX_PDB_FLAGS) /nologo /MD /EHsc /GR /DDEBUG
 # Set flags controlling warnings level, and suppression of some warnings.
 # 
 !IFNDEF WARNFLAGS
-WARNFLAGS =	/W4 /wd4127 /wd4251 /wd4275 /wd4786 /wd4100 /wd4245 /wd4206 /wd4018 /wd4389
+# 4127: conditional expression is constant
+# 4251: 'identifier' : class 'type' needs to have dll-interface to be used by clients of class 'type2'
+# 4275: non – DLL-interface classkey 'identifier' used as base for DLL-interface classkey 'identifier'
+# 4786: ??????????
+# 4100: 'identifier' : unreferenced formal parameter
+# 4245: 'conversion' : conversion from 'type1' to 'type2', signed/unsigned mismatch
+# 4206: nonstandard extension used : translation unit is empty (only applies to C source code)
+# 4611: interaction between '_setjmp' and C++ object destruction is non-portable
+# 
+WARNFLAGS =	/W4 /wd4127 /wd4251 /wd4275 /wd4786 /wd4100 /wd4245 /wd4206 /wd4611
 !ENDIF
 
 # 
@@ -153,9 +161,18 @@ WARNFLAGS =	/W4 /wd4127 /wd4251 /wd4275 /wd4786 /wd4100 /wd4245 /wd4206 /wd4018
 # 
 !IFNDEF SSEFLAGS
 SSEFLAGS = /DHAVE_SSE_AT_COMPILE_TIME
+#SSE_ARCH_FLAGS = /arch:SSE
+!ENDIF
+
+# VS2010 SP1 or later in fact required for runtime detection of AVX instruction set
+!IFNDEF AVXFLAGS
+!IF $(MSVC_VER) >= 1600
+AVXFLAGS = /DHAVE_AVX_AT_COMPILE_TIME
+AVX_ARCH_FLAGS = /arch:AVX
+!ENDIF
 !ENDIF
 
-# The followin are extra disables that can be applied to external source
+# The following are extra disables that can be applied to external source
 # not under our control that we wish to use less stringent warnings with.
 !IFNDEF SOFTWARNFLAGS
 SOFTWARNFLAGS= /wd4244 /wd4702 /wd4701 /wd4013 /wd4706 /wd4057 /wd4210 /wd4305
@@ -179,7 +196,7 @@ STDCALL=YES
 # Version number embedded in DLL name. 
 # If GDAL version is X.Y.Z, VERSION = X * 100 + Y
 !IFNDEF VERSION
-VERSION =	200
+VERSION =	201
 !ENDIF
 
 # Comment the following out if you want PAM supported disabled
@@ -194,12 +211,13 @@ DLLBUILD=1
 # vector formats. 
 INCLUDE_OGR_FRMTS = YES
 
-# Location of Visual C++ directory (only required for following SETARGV stuff)
-#VCDIR   = 	"D:\Software\VStudio\VC98"
+# Enable all GNM formats?  Comment out to disable
+# gnm formats.
+#INCLUDE_GNM_FRMTS = YES
 
-# Enable the following if VCDIR set properly, and you want the utility
-# programs to be able to expand wildcards. 
-#SETARGV =	$(VCDIR)\lib\setargv.obj
+# To be enabled defined to point to setargv.obj from the Visual C++ directory,
+# when you want the utility programs to be able to expand wildcards. 
+#SETARGV =	"D:\Software\VStudio\VC98\lib\setargv.obj"
 
 # Uncomment to build with libiconv library to support extended character
 # recoding capabilities. GDAL's internal stub implementation supports
@@ -219,18 +237,24 @@ BSB_SUPPORTED = 1
 # Comment out the following to disable ODBC support.
 ODBC_SUPPORTED = 1
 
+# Uncomment out the following to enable SQL Native Client support for MSSQL Bulk Copy.
+#SQLNCLI_VERSION = 11
+#SQLNCLI_DIR = C:\Program Files (x86)\Microsoft SQL Server\$(SQLNCLI_VERSION)0\SDK
+#SQLNCLI_LIB = "$(SQLNCLI_DIR)\Lib\x86\sqlncli$(SQLNCLI_VERSION).lib"
+#SQLNCLI_INCLUDE = "-I$(SQLNCLI_DIR)\Include" -DSQLNCLI_VERSION=$(SQLNCLI_VERSION) -DMSSQL_BCP_SUPPORTED=1
+
 # Comment out the following to disable JPEG support.
 JPEG_SUPPORTED = 1
 
 # This will enable 12bit libjpeg - use only with internal jpeg builds.
 JPEG12_SUPPORTED = 1
 
-#if using an external jpeg library uncomment the follwing lines
+#if using an external jpeg library uncomment the following lines
 #JPEG_EXTERNAL_LIB = 1
 #JPEGDIR = c:/projects/jpeg-6b
 #JPEG_LIB = $(JPEGDIR)/libjpeg.lib
 
-#if using an external png library uncomment the follwing lines
+#if using an external png library uncomment the following lines
 #PNG_EXTERNAL_LIB = 1
 #PNGDIR = c:/projects/libpng-1.0.8
 #PNG_LIB = $(PNGDIR)/libpng.lib
@@ -342,7 +366,7 @@ JPEG12_SUPPORTED = 1
 # of JasPer from ftp://ftp.remotesensing.org/gdal/
 #JASPER_INCLUDE = $(JASPER_INCLUDE) -DHAVE_JASPER_UUID
 
-# Uncommment and adjust paths if you have Kakadu 6.0 or newer
+# Uncomment and adjust paths if you have Kakadu 6.0 or newer
 #KAKFLAGS=-DKDU_MAJOR_VERSION=6 -DKDU_MINOR_VERSION=0 -DKDU_PATCH_VERSION=0
 #KAKDIR = 	\warmerda\pkg\kakadu-6.2.1
 #KAKLIB =	$(KAKDIR)\lib_x86\kdu_v62R.lib
@@ -391,8 +415,6 @@ PCIDSK_SETTING=INTERNAL
 #PCIDSK_SETTING=EXTERNAL
 #PCIDSK_INCLUDE=-I\warmerda\pcidsk\src
 #PCIDSK_LIB=\warmerda\pcidsk\src\pcidsk.lib
-# Use the following alternative to use the old PCIDSK implementation
-#PCIDSK_SETTING=OLD
 
 # PostGIS Libraries
 #PG_INC_DIR = n:\pkg\libpq_win32\include
@@ -495,6 +517,9 @@ OCI_INCLUDE =	-I$(ORACLE_HOME)\oci\include
 #FGDB_INC = $(FGDB_SDK)\include 
 #FGDB_LIB = $(FGDB_SDK)\lib\FileGDBAPI.lib
 
+#uncomment to build AmigoCloud as a plugin instead
+#AMIGOCLOUD_PLUGIN = YES
+
 
 #uncomment to use ArcObjects
 #ARCOBJECTS_ENABLED = YES
@@ -511,9 +536,9 @@ OCI_INCLUDE =	-I$(ORACLE_HOME)\oci\include
 # The cURL library is used for WCS, WMS, GeoJSON, SRS call importFromUrl(), WFS, GFT, CouchDB, /vsicurl/ etc.
 #CURL_DIR=C:\curl-7.15.0
 #CURL_INC = -I$(CURL_DIR)/include
-# Uncoment following line to use libcurl as dynamic library
+# Uncomment following line to use libcurl as dynamic library
 #CURL_LIB = $(CURL_DIR)/libcurl_imp.lib wsock32.lib wldap32.lib winmm.lib
-# Uncoment following two lines to use libcurl as static library
+# Uncomment following two lines to use libcurl as static library
 #CURL_LIB = $(CURL_DIR)/libcurl.lib wsock32.lib wldap32.lib winmm.lib
 #CURL_CFLAGS = -DCURL_STATICLIB
 
@@ -557,6 +582,35 @@ OCI_INCLUDE =	-I$(ORACLE_HOME)\oci\include
 #PODOFO_ENABLED = YES
 #PODOFO_CFLAGS = -Ie:/podofo-svn/install/include -Ie:/podofo-svn/install/include/podofo
 #PODOFO_LIBS = e:/podofo-svn/install/lib/podofo.lib E:/release-1500-dev/release-1500/lib/freetype239.lib gdi32.lib
+
+# Uncomment for PDF support with PDFium
+#
+# Copyright (C) 2015 Klokan Technologies GmbH (http://www.klokantech.com/)
+# Author: Martin Mikita <martin.mikita at klokantech.com>, xmikit00 @ FIT VUT Brno
+#
+# Pdfium can be built from the win_gdal_build branch at https://github.com/rouault/pdfium that
+# has the following patch to ensure /MD (MultiThreadedDLL) linking consistent with GDAL one.
+# Build script from PDFium is available at https://github.com/rouault/pdfium/tree/build
+#
+#diff --git a/build/standalone.gypi b/build/standalone.gypi
+#index ecf849b..0e567e4 100644
+#--- a/build/standalone.gypi
+#+++ b/build/standalone.gypi
+#@@ -100,7 +100,8 @@
+#               ['component=="shared_library"', {
+#                 'RuntimeLibrary': '2',  #/MD
+#               }, {
+#-                'RuntimeLibrary': '0',  #/MT
+#+                #'RuntimeLibrary': '0',  #/MT
+#+                 'RuntimeLibrary': '2',  #/MD
+#               }],
+#             ],
+#
+#PDFIUM_ENABLED = YES
+#PDFIUM_CFLAGS = -Ie:/pdfium/ -Ie:/pdfium/public
+#PDFIUM_LIB_DIR = e:/pdfium/build/Release/lib
+#PDFIUM_LIBS = $(PDFIUM_LIB_DIR)/pdfium.lib $(PDFIUM_LIB_DIR)/bigint.lib $(PDFIUM_LIB_DIR)/fdrm.lib $(PDFIUM_LIB_DIR)/formfiller.lib $(PDFIUM_LIB_DIR)/fpdfapi.lib $(PDFIUM_LIB_DIR)/fpdfdoc.lib $(PDFIUM_LIB_DIR)/fpdftext.lib $(PDFIUM_LIB_DIR)/freetype.lib $(PDFIUM_LIB_DIR)/fxcodec.lib $(PDFIUM_LIB_DIR)/fxcrt.lib $(PDFIUM_LIB_DIR)/fxedit.lib $(PDFIUM_LIB_DIR)/fxge.lib $(PDFIUM_LIB_DIR)/pdfwindow.lib $(PDFIUM_LIB_DIR)/fx_agg.lib $(PDFIUM_LIB_DIR)/fx_lcms2.lib $(PDFIUM_LIB_DIR)/fx_libjpeg.li [...]
+
 # Build PDF driver as plugin
 #PDF_PLUGIN = NO
 
@@ -569,7 +623,7 @@ OCI_INCLUDE =	-I$(ORACLE_HOME)\oci\include
 #WEBP_CFLAGS = -IE:/libwebp-0.1-windows/dev/Include
 #WEBP_LIBS = e:/libwebp-0.1-windows/dev/lib/libwebp_a.lib
 
-# Uncomment for libxml2 support (for cpl_xml_validate.cpp routines, used optionaly by the GML driver)
+# Uncomment for libxml2 support (for cpl_xml_validate.cpp routines, used optionally by the GML driver)
 #LIBXML2_INC = -Iz:\home\even\release-1500-dev\release-1500\include
 #LIBXML2_LIB = z:\home\even\release-1500-dev\release-1500\lib\libxml2.lib
 
@@ -588,6 +642,51 @@ OCI_INCLUDE =	-I$(ORACLE_HOME)\oci\include
 #GTA_CFLAGS = -IC:/gdal_trunk/libgta-1.0.0-w32/include -IC:/gdal_trunk/libgta-1.0.0-w32/include/gta
 #GTA_LIBS = C:/gdal_trunk/libgta-1.0.0-w32/lib/libgta.dll.a
 
+# Uncomment for MongoDB support
+# This configuration is valid for a libmongoclient built as a DLL with: scons.bat --32 --dynamic-windows --sharedclient  --prefix=c:\users\even\dev\mongo-client-install --cpppath=c:\users\even\dev\boost_1_55_0_32bit --libpath=c:\users\even\dev\boost_1_55_0_32bit\lib32-msvc-10.0 install
+#MONGODB_PLUGIN = NO
+#MONGODB_INC = c:/users/even/dev/mongo-client-install/include
+# Boost library names must be edited to reflect the actual MSVC and Boost versions
+#BOOST_INC = c:/users/even/dev/boost_1_55_0_32bit
+#BOOST_LIB_PATH= c:\users\even\dev\boost_1_55_0_32bit\lib32-msvc-10.0
+#MONGODB_LIBS = c:/users/even/dev/mongo-client-install/lib/mongoclient.lib  $(BOOST_LIB_PATH)\libboost_thread-vc100-mt-1_55.lib   $(BOOST_LIB_PATH)\libboost_system-vc100-mt-1_55.lib  $(BOOST_LIB_PATH)\libboost_date_time-vc100-mt-1_55.lib   $(BOOST_LIB_PATH)\libboost_chrono-vc100-mt-1_55.lib
+
+# For a static build of mongoclient, only building the driver as a plugin succeeded
+# The libmongoclient_s.lib file had to be renamed without the _s prefix to enable successful linking
+# It was built with: c:\Python27\Scripts\scons.bat --32 --prefix=c:\users\even\dev\mongo-client-install --cpppath=c:\users\even\dev\boost_1_55_0_32bit --libpath=c:\users\even\dev\boost_1_55_0_32bit\lib32-msvc-10.0 install
+# MONGODB_PLUGIN = YES
+# MONGODB_INC = c:/users/even/dev/mongo-client-install/include
+# MONGODB_CFLAGS = -DSTATIC_LIBMONGOCLIENT
+# BOOST_INC = c:/users/even/dev/boost_1_55_0_32bit
+# BOOST_LIB_PATH= c:\users\even\dev\boost_1_55_0_32bit\lib32-msvc-10.0
+# MONGODB_LIBS = c:/users/even/dev/mongo-client-install/lib/libmongoclient.lib $(BOOST_LIB_PATH)\libboost_thread-vc100-mt-1_55.lib  $(BOOST_LIB_PATH)\libboost_thread-vc100-mt-s-1_55.lib $(BOOST_LIB_PATH)\libboost_system-vc100-mt-1_55.lib $(BOOST_LIB_PATH)\libboost_system-vc100-mt-s-1_55.lib $(BOOST_LIB_PATH)\libboost_date_time-vc100-mt-1_55.lib  $(BOOST_LIB_PATH)\libboost_date_time-vc100-mt-s-1_55.lib $(BOOST_LIB_PATH)\libboost_chrono-vc100-mt-1_55.lib $(BOOST_LIB_PATH)\libboost_chrono-v [...]
+
+# QHull configuration. By default use internal libqhull.
+# QHULL_SETTING can be set to INTERNAL, EXTERNAL or NO
+# For external qhull, use qhull 2012
+!IFNDEF QHULL_SETTING
+QHULL_SETTING = INTERNAL
+!ENDIF
+# To be defined if QHULL_SETTING=EXTERNAL
+# QHULL_INC = -I....
+
+# Cryptopp stuff.
+# Make sure cryptopp is compiled with /MD ( Properties | Configuration properties | C/C++ |  Code Generation | Runtime Library: Multi-threaded DLL (/MD))
+# The headers file must be in $(CRYPTOPP_INC)/cryptopp (the /cryptopp part must not be in the following variable then)
+# CRYPTOPP_INC = -Ic:/install-cryptopp-x64/include 
+#
+# Define USE_ONLY_CRYPTODLL_ALG is running against cryptopp.dll, but not if statically linking
+# USE_ONLY_CRYPTODLL_ALG=YES
+#
+# When linking against the DLL:
+# CRYPTOPP_LIB = c:/install-cryptopp-x64/lib/cryptopp.lib
+#
+# When linking against the static lib:
+# CRYPTOPP_LIB = c:/install-cryptopp-x64/lib/cryptlib.lib
+
+# Comment out to disable MRF support.
+MRF_SETTING=yes
+
 # Any extra libraries needed on this platform?
 ADD_LIBS	= 
 
@@ -606,7 +705,7 @@ ADD_LIBS	=
 GDAL_DLL =	gdal$(VERSION).dll
 
 INC	=	-I$(GDAL_ROOT)\port -I$(GDAL_ROOT)\ogr -I$(GDAL_ROOT)\gcore \
-		-I$(GDAL_ROOT)\alg -I$(GDAL_ROOT)\ogr\ogrsf_frmts
+		-I$(GDAL_ROOT)\alg -I$(GDAL_ROOT)\ogr\ogrsf_frmts  -I$(GDAL_ROOT)\gnm -I$(GDAL_ROOT)\gnm\gnm_frmts -I$(GDAL_ROOT)\apps
 
 !IFDEF MSVC_VLD_DIR
 MSVC_VLD_FLAGS=-DMSVC_USE_VLD=1 -I$(MSVC_VLD_DIR)\include
@@ -621,11 +720,15 @@ MSVC_VLD_LIB=/LIBPATH:$(MSVC_VLD_DIR)/lib/Win32
 OGR_FLAG = -DOGR_ENABLED
 !ENDIF
 
+!IFDEF INCLUDE_GNM_FRMTS
+GNM_FLAG = -DGNM_ENABLED
+!ENDIF
+
 #LINKER_FLAGS =	/NODEFAULTLIB:LIBC 
 LINKER_FLAGS = $(EXTRA_LINKER_FLAGS) $(MSVC_VLD_LIB) $(LDEBUG)
 
 
-CFLAGS	=	$(OPTFLAGS) $(WARNFLAGS) $(SSEFLAGS) $(INC) $(EXTRAFLAGS) $(OGR_FLAG) $(MSVC_VLD_FLAGS) -DGDAL_COMPILATION
+CFLAGS	=	$(OPTFLAGS) $(WARNFLAGS) $(USER_DEFS) $(SSEFLAGS) $(INC) $(AVXFLAGS) $(EXTRAFLAGS) $(OGR_FLAG) $(GNM_FLAG) $(MSVC_VLD_FLAGS) -DGDAL_COMPILATION
 CPPFLAGS = $(CFLAGS) 
 MAKE	=	nmake /nologo
 
@@ -633,7 +736,7 @@ MAKE	=	nmake /nologo
 CC	=	cl
 !ENDIF
 
-INSTALL	=	xcopy /y /r /d /f
+INSTALL	=	xcopy /y /r /d /f /I
 
 CPLLIB	=    $(GDAL_ROOT)/port/cpl.lib
 
@@ -692,6 +795,14 @@ PDF_LIB_LINK =
 !ENDIF
 !ENDIF
 
+!IFDEF PDFIUM_LIBS
+!IF "$(PDF_PLUGIN)" != "YES"
+PDF_LIB_LINK = $(PDFIUM_LIBS)
+!ELSE
+PDF_LIB_LINK =
+!ENDIF
+!ENDIF
+
 !IFDEF NETCDF_LIB
 !IF "$(NETCDF_PLUGIN)" != "YES"
 NETCDF_LIB_LINK = $(NETCDF_LIB)
@@ -732,6 +843,14 @@ FGDB_LIB_LINK =
 !ENDIF
 !ENDIF
 
+!IFDEF MONGODB_INC
+!IF "$(MONGODB_PLUGIN)" != "YES"
+MONGODB_LIB_LINK = $(MONGODB_LIBS)
+!ELSE
+MONGODB_LIB_LINK =
+!ENDIF
+!ENDIF
+
 !IFDEF XERCES_DIR
 NAS_ENABLED = YES
 !ENDIF
@@ -753,5 +872,5 @@ EXTERNAL_LIBS =	$(OGDILIB) $(XERCES_LIB) $(EXPAT_LIB) $(OCI_LIB) $(PG_LIB) \
 	$(ODBCLIB) $(JASPER_LIB) $(PNG_LIB) $(ADD_LIBS) $(OPENJPEG_LIB) \
 	$(MRSID_LIDAR_LIB) $(LIBKML_LIBS) $(SOSI_LIBS) $(PDF_LIB_LINK) $(LZMA_LIBS) \
 	$(LIBICONV_LIBRARY) $(WEBP_LIBS) $(FGDB_LIB_LINK) $(FREEXL_LIBS) $(GTA_LIBS) \
-	$(INGRES_LIB) $(LIBXML2_LIB) $(PCRE_LIB) ws2_32.lib
+	$(INGRES_LIB) $(LIBXML2_LIB) $(PCRE_LIB) $(MONGODB_LIB_LINK) $(CRYPTOPP_LIB) $(SQLNCLI_LIB) ws2_32.lib
 		
diff --git a/ogr/Doxyfile b/ogr/Doxyfile
index f47028b..8ab3954 100644
--- a/ogr/Doxyfile
+++ b/ogr/Doxyfile
@@ -418,7 +418,7 @@ WARN_IF_UNDOCUMENTED   = YES
 
 WARN_IF_DOC_ERROR      = YES
 
-# This WARN_NO_PARAMDOC option can be abled to get warnings for 
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for 
 # functions that are documented, but have no documentation for their parameters 
 # or return value. If set to NO (the default) doxygen will only warn about 
 # wrong or incomplete parameter documentation, but not about the absence of 
diff --git a/ogr/GNUmakefile b/ogr/GNUmakefile
index d4d4045..f09a398 100644
--- a/ogr/GNUmakefile
+++ b/ogr/GNUmakefile
@@ -11,9 +11,7 @@ ifeq ($(HAVE_GEOS),yes)
 CPPFLAGS 	:=	-DHAVE_GEOS=1 $(GEOS_CFLAGS) $(CPPFLAGS)
 endif
 
-ifeq ($(OGR_ENABLED),yes)
 CXXFLAGS 	:=	-DHAVE_MITAB $(CXXFLAGS)
-endif
 
 ifeq ($(HAVE_EXPAT),yes)
 CPPFLAGS 	:=	-DHAVE_EXPAT $(EXPAT_INCLUDE) $(CPPFLAGS)
@@ -45,19 +43,9 @@ $(OBJ): ogr_feature.h ogr_geometry.h swq.h
 
 obj:	$(OBJ)
 
-ifeq ($(OGR_ENABLED),yes)
-
 sublibs:
 	(cd ogrsf_frmts; $(MAKE))
 
-else
-
-sublibs:
-	(cd ogrsf_frmts/mitab; $(MAKE))
-	(cd ogrsf_frmts/generic; $(MAKE))
-
-endif
-
 docs:
 	echo "This target does not exist anymore. Use top-level"
 
@@ -77,7 +65,7 @@ install:
 	    do $(INSTALL_DATA) $$f $(DESTDIR)$(INST_INCLUDE) ; \
 	done
 
-# The sed substition below workarounds a bug with gcc 4.1 -O2 (checked on 64bit platforms)
+# The sed substitution below workarounds a bug with gcc 4.1 -O2 (checked on 64bit platforms)
 # that produces buggy compiled code.
 # Seen on gcc 4.1.2-27ubuntu1 (Ubuntu 10.04) (not the default compiler) and gcc-4.1.2-48.el5 (CentOS 5.5)
 # (default compiler...)
@@ -85,8 +73,17 @@ install:
 # that it helps gcc 4.1 generating correct code here...
 parser:
 	bison -p swq -d -oswq_parser.cpp swq_parser.y
-	sed "s/yytype_int16 yyssa\[YYINITDEPTH\];/yytype_int16 yyssa[YYINITDEPTH]; \/\* workaround bug with gcc 4.1 -O2 \*\/ memset(yyssa, 0, sizeof(yyssa));/" < swq_parser.cpp > swq_parser.cpp.tmp
+	sed "s/yytype_int16 yyssa\[YYINITDEPTH\];/yytype_int16 yyssa[YYINITDEPTH]; \/\* workaround bug with gcc 4.1 -O2 \*\/ memset(yyssa, 0, sizeof(yyssa));/" < swq_parser.cpp | sed "s/\*yyssp = yystate/\*yyssp = (yytype_int16)yystate/" > swq_parser.cpp.tmp
 	mv swq_parser.cpp.tmp swq_parser.cpp
 
+# The sed hack is to please MSVC
 osr_cs_wkt_parser:
 	bison --no-lines -p osr_cs_wkt_ -d -oosr_cs_wkt_parser.c osr_cs_wkt_grammar.y
+	sed "s/\*yyssp = yystate/\*yyssp = (yytype_int16)yystate/" < osr_cs_wkt_parser.c | sed "s/yyerrorlab:/#if 0\nyyerrorlab:/" | sed "s/yyerrlab1:/#endif\nyyerrlab1:/" | sed "s/for (yylen = 0; yystr\[yylen\]; yylen++)/for (yylen = 0; yystr != YY_NULL \&\& yystr\[yylen\]; yylen++)/"  > osr_cs_wkt_parser.c.tmp
+	mv osr_cs_wkt_parser.c.tmp osr_cs_wkt_parser.c
+
+osr_cs_wkt_parser.$(OBJ_EXT):   osr_cs_wkt_parser.c
+	$(CC) $(GDAL_INCLUDE) $(CFLAGS) $(CPPFLAGS) $(NO_LOGICAL_OP_FLAG) -c -o $@ $<
+
+swq_parser.$(OBJ_EXT):   swq_parser.cpp
+	$(CXX) $(GDAL_INCLUDE) $(CXXFLAGS) $(CPPFLAGS) $(NO_LOGICAL_OP_FLAG) -c -o $@ $<
diff --git a/ogr/generate_encoding_table.c b/ogr/generate_encoding_table.c
index 8c8b092..903870d 100644
--- a/ogr/generate_encoding_table.c
+++ b/ogr/generate_encoding_table.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: generate_encoding_table.c 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: generate_encoding_table.c 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OGR
  * Purpose:  Generate a mapping table from a 1-byte encoding to unicode,
@@ -128,8 +128,8 @@ int main(int argc, char* argv[])
 
     if ( sConv == (iconv_t)-1 )
     {
-        fprintf(stderr, 
-                  "Recode from %s to %s failed with the error: \"%s\".", 
+        fprintf(stderr,
+                  "Recode from %s to %s failed with the error: \"%s\".",
                   pszSrcEncoding, pszDstEncoding, strerror(errno) );
         return 1;
     }
diff --git a/ogr/gml2ogrgeometry.cpp b/ogr/gml2ogrgeometry.cpp
index 7ab4e00..11b0f06 100644
--- a/ogr/gml2ogrgeometry.cpp
+++ b/ogr/gml2ogrgeometry.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gml2ogrgeometry.cpp 28751 2015-03-20 15:21:49Z rouault $
+ * $Id: gml2ogrgeometry.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  GML Reader
  * Purpose:  Code to translate between GML and OGR geometry forms.
@@ -15,16 +15,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************
  *
@@ -33,7 +33,7 @@
  *   overflows and stack corruptions with any kind of input data.
  *
  * Security Audit 2003/03/28 warmerda:
- *   Completed security audit.  I believe that this module may be safely used 
+ *   Completed security audit.  I believe that this module may be safely used
  *   to parse, arbitrary GML potentially provided by a hostile source without
  *   compromising the system.
  *
@@ -48,11 +48,6 @@
 #include "ogr_p.h"
 #include "ogrsf_frmts/xplane/ogr_xplane_geo_utils.h"
 
-#ifndef PI
-#define PI  3.14159265358979323846
-#endif
-
-
 /************************************************************************/
 /*                        GMLGetCoordTokenPos()                         */
 /************************************************************************/
@@ -61,7 +56,7 @@ static const char* GMLGetCoordTokenPos(const char* pszStr,
                                        const char** ppszNextToken)
 {
     char ch;
-    while(TRUE)
+    while( true )
     {
         ch = *pszStr;
         if (ch == '\0')
@@ -116,7 +111,7 @@ static const char *BareGMLElement( const char *pszInput )
 /*      after any namespace qualifiers have been stripped off.          */
 /************************************************************************/
 
-static const CPLXMLNode *FindBareXMLChild( const CPLXMLNode *psParent, 
+static const CPLXMLNode *FindBareXMLChild( const CPLXMLNode *psParent,
                                            const char *pszBareName )
 
 {
@@ -153,7 +148,7 @@ static const char *GetElementText( const CPLXMLNode *psElement )
 
         psChild = psChild->psNext;
     }
-    
+
     return NULL;
 }
 
@@ -185,10 +180,10 @@ static const CPLXMLNode *GetChildElement( const CPLXMLNode *psElement )
 /*     Returns true for positive orientation.                           */
 /************************************************************************/
 
-int GetElementOrientation( const CPLXMLNode *psElement )
+static bool GetElementOrientation( const CPLXMLNode *psElement )
 {
     if( psElement == NULL )
-        return TRUE;
+        return true;
 
     const CPLXMLNode *psChild = psElement->psChild;
 
@@ -200,8 +195,8 @@ int GetElementOrientation( const CPLXMLNode *psElement )
 
         psChild = psChild->psNext;
     }
-    
-    return TRUE;
+
+    return true;
 }
 
 /************************************************************************/
@@ -210,30 +205,30 @@ int GetElementOrientation( const CPLXMLNode *psElement )
 /*      Add a point to the passed geometry.                             */
 /************************************************************************/
 
-static int AddPoint( OGRGeometry *poGeometry, 
-                     double dfX, double dfY, double dfZ, int nDimension )
+static bool AddPoint( OGRGeometry *poGeometry,
+                      double dfX, double dfY, double dfZ, int nDimension )
 
 {
-    OGRwkbGeometryType eType = wkbFlatten(poGeometry->getGeometryType());
+    const OGRwkbGeometryType eType = wkbFlatten(poGeometry->getGeometryType());
     if( eType == wkbPoint )
     {
         OGRPoint *poPoint = (OGRPoint *) poGeometry;
 
         if( !poPoint->IsEmpty() )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "More than one coordinate for <Point> element.");
-            return FALSE;
+            return false;
         }
-            
+
         poPoint->setX( dfX );
         poPoint->setY( dfY );
         if( nDimension == 3 )
             poPoint->setZ( dfZ );
 
-        return TRUE;
+        return true;
     }
-                
+
     else if( eType == wkbLineString ||
              eType == wkbCircularString )
     {
@@ -242,13 +237,13 @@ static int AddPoint( OGRGeometry *poGeometry,
         else
             ((OGRSimpleCurve *) poGeometry)->addPoint( dfX, dfY );
 
-        return TRUE;
+        return true;
     }
 
     else
     {
-        CPLAssert( FALSE );
-        return FALSE;                                                   
+        CPLAssert( false );
+        return false;
     }
 }
 
@@ -256,8 +251,8 @@ static int AddPoint( OGRGeometry *poGeometry,
 /*                        ParseGMLCoordinates()                         */
 /************************************************************************/
 
-static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeometry,
-                                int nSRSDimension )
+static bool ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeometry,
+                                 int nSRSDimension )
 
 {
     const CPLXMLNode *psCoordinates = FindBareXMLChild( psGeomNode, "coordinates" );
@@ -279,7 +274,7 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
             if( strlen(pszDecimal) != 1 || (pszDecimal[0] >= '0' && pszDecimal[0] <= '9') )
             {
                 CPLError( CE_Failure, CPLE_AppDefined, "Wrong value for decimal attribute");
-                return FALSE;
+                return false;
             }
             chDecimal = pszDecimal[0];
         }
@@ -291,7 +286,7 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
             if( strlen(pszCS) != 1 || (pszCS[0] >= '0' && pszCS[0] <= '9') )
             {
                 CPLError( CE_Failure, CPLE_AppDefined, "Wrong value for cs attribute");
-                return FALSE;
+                return false;
             }
             chCS = pszCS[0];
         }
@@ -302,7 +297,7 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
             if( strlen(pszTS) != 1 || (pszTS[0] >= '0' && pszTS[0] <= '9') )
             {
                 CPLError( CE_Failure, CPLE_AppDefined, "Wrong value for tes attribute");
-                return FALSE;
+                return false;
             }
             chTS = pszTS[0];
         }
@@ -310,7 +305,7 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
         if( pszCoordString == NULL )
         {
             poGeometry->empty();
-            return TRUE;
+            return true;
         }
 
         while( *pszCoordString != '\0' )
@@ -318,7 +313,7 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
             double dfX, dfY, dfZ = 0.0;
             int nDimension = 2;
 
-            // parse out 2 or 3 tuple. 
+            // parse out 2 or 3 tuple.
             if( chDecimal == '.' )
                 dfX = OGRFastAtof( pszCoordString );
             else
@@ -332,7 +327,7 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
                         "Corrupt <coordinates> value." );
-                return FALSE;
+                return false;
             }
             else if( chCS == ',' && pszCS == NULL && isspace((unsigned char)*pszCoordString) )
             {
@@ -350,7 +345,7 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
                 dfY = OGRFastAtof( pszCoordString );
             else
                 dfY = CPLAtofDelim( pszCoordString, chDecimal) ;
-            while( *pszCoordString != '\0' 
+            while( *pszCoordString != '\0'
                    && *pszCoordString != chCS
                    && *pszCoordString != chTS
                    && !isspace((unsigned char)*pszCoordString) )
@@ -364,7 +359,7 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
                 else
                     dfZ = CPLAtofDelim( pszCoordString, chDecimal) ;
                 nDimension = 3;
-                while( *pszCoordString != '\0' 
+                while( *pszCoordString != '\0'
                        && *pszCoordString != chCS
                        && *pszCoordString != chTS
                        && !isspace((unsigned char)*pszCoordString) )
@@ -380,7 +375,7 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
                 pszCoordString++;
 
             if( !AddPoint( poGeometry, dfX, dfY, dfZ, nDimension ) )
-                return FALSE;
+                return false;
 
             iCoord++;
         }
@@ -391,12 +386,12 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
 /* -------------------------------------------------------------------- */
 /*      Is this a "pos"?  GML 3 construct.                              */
 /*      Parse if it exist a series of pos elements (this would allow    */
-/*      the correct parsing of gml3.1.1 geomtries such as linestring    */
+/*      the correct parsing of gml3.1.1 geometries such as linestring    */
 /*      defined with pos elements.                                      */
 /* -------------------------------------------------------------------- */
     const CPLXMLNode *psPos;
-    
-    int bHasFoundPosElement = FALSE;
+
+    bool bHasFoundPosElement = false;
     for( psPos = psGeomNode->psChild;
          psPos != NULL;
          psPos = psPos->psNext )
@@ -426,9 +421,9 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
                                                  oPoint.getY(), oPoint.getZ(),
                                                  oPoint.getCoordinateDimension() );
                         if (bSuccess)
-                            bHasFoundPosElement = TRUE;
+                            bHasFoundPosElement = true;
                         else
-                            return FALSE;
+                            return false;
                     }
                 }
             }
@@ -452,12 +447,11 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
         if (pszPos == NULL)
         {
             poGeometry->empty();
-            return TRUE;
+            return true;
         }
 
         const char* pszCur = pszPos;
-        const char* pszX = (pszCur != NULL) ?
-                            GMLGetCoordTokenPos(pszCur, &pszCur) : NULL;
+        const char* pszX = GMLGetCoordTokenPos(pszCur, &pszCur);
         const char* pszY = (pszCur != NULL) ?
                             GMLGetCoordTokenPos(pszCur, &pszCur) : NULL;
         const char* pszZ = (pszCur != NULL) ?
@@ -467,8 +461,8 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Did not get 2+ values in <gml:pos>%s</gml:pos> tuple.",
-                      pszPos ? pszPos : "" );
-            return FALSE;
+                      pszPos );
+            return false;
         }
 
         double dfX = OGRFastAtof(pszX);
@@ -477,26 +471,25 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
         int bSuccess = AddPoint( poGeometry, dfX, dfY, dfZ, (pszZ != NULL) ? 3 : 2 );
 
         if (bSuccess)
-            bHasFoundPosElement = TRUE;
+            bHasFoundPosElement = true;
         else
-            return FALSE;
+            return false;
     }
 
     if (bHasFoundPosElement)
-        return TRUE;
+        return true;
 
 /* -------------------------------------------------------------------- */
 /*      Is this a "posList"?  GML 3 construct (SF profile).             */
 /* -------------------------------------------------------------------- */
     const CPLXMLNode *psPosList = FindBareXMLChild( psGeomNode, "posList" );
-    
+
     if( psPosList != NULL )
     {
-        int bSuccess = FALSE;
         int nDimension = 2;
 
         /* Try to detect the presence of an srsDimension attribute */
-        /* This attribute is only availabe for gml3.1.1 but not */
+        /* This attribute is only available for gml3.1.1 but not */
         /* available for gml3.1 SF*/
         const char* pszSRSDimension = CPLGetXMLValue( (CPLXMLNode*) psPosList, "srsDimension", NULL);
         /* If not found at the posList level, try on the enclosing element */
@@ -511,18 +504,19 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "srsDimension = %d not supported", nDimension);
-            return FALSE;
+            return false;
         }
 
         const char* pszPosList = GetElementText( psPosList );
         if (pszPosList == NULL)
         {
             poGeometry->empty();
-            return TRUE;
+            return true;
         }
 
+        bool bSuccess = false;
         const char* pszCur = pszPosList;
-        while (TRUE)
+        while (true)
         {
             const char* pszX = GMLGetCoordTokenPos(pszCur, &pszCur);
             if (pszX == NULL && bSuccess)
@@ -537,8 +531,8 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
                 CPLError( CE_Failure, CPLE_AppDefined,
                         "Did not get at least %d values or invalid number of \n"
                         "set of coordinates <gml:posList>%s</gml:posList>",
-                        nDimension, pszPosList ? pszPosList : "");
-                return FALSE;
+                        nDimension, pszPosList);
+                return false;
             }
 
             double dfX = OGRFastAtof(pszX);
@@ -546,49 +540,44 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
             double dfZ = (pszZ != NULL) ? OGRFastAtof(pszZ) : 0.0;
             bSuccess = AddPoint( poGeometry, dfX, dfY, dfZ, nDimension );
 
-            if (bSuccess == FALSE || pszCur == NULL)
+            if ( !bSuccess || pszCur == NULL)
                 break;
         }
 
         return bSuccess;
     }
-    
 
 /* -------------------------------------------------------------------- */
 /*      Handle form with a list of <coord> items each with an <X>,      */
 /*      and <Y> element.                                                */
 /* -------------------------------------------------------------------- */
-    const CPLXMLNode *psCoordNode;
-
-    for( psCoordNode = psGeomNode->psChild; 
+    for( const CPLXMLNode *psCoordNode = psGeomNode->psChild;
          psCoordNode != NULL;
          psCoordNode = psCoordNode->psNext )
     {
-        if( psCoordNode->eType != CXT_Element 
+        if( psCoordNode->eType != CXT_Element
             || !EQUAL(BareGMLElement(psCoordNode->pszValue),"coord") )
             continue;
 
-        const CPLXMLNode *psXNode, *psYNode, *psZNode;
-        double dfX, dfY, dfZ = 0.0;
-        int nDimension = 2;
-
-        psXNode = FindBareXMLChild( psCoordNode, "X" );
-        psYNode = FindBareXMLChild( psCoordNode, "Y" );
-        psZNode = FindBareXMLChild( psCoordNode, "Z" );
+        const CPLXMLNode *psXNode = FindBareXMLChild( psCoordNode, "X" );
+        const CPLXMLNode *psYNode = FindBareXMLChild( psCoordNode, "Y" );
+        const CPLXMLNode *psZNode = FindBareXMLChild( psCoordNode, "Z" );
 
-        if( psXNode == NULL || psYNode == NULL 
+        if( psXNode == NULL || psYNode == NULL
             || GetElementText(psXNode) == NULL
             || GetElementText(psYNode) == NULL
             || (psZNode != NULL && GetElementText(psZNode) == NULL) )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Corrupt <coord> element, missing <X> or <Y> element?" );
-            return FALSE;
+            return false;
         }
 
-        dfX = OGRFastAtof( GetElementText(psXNode) );
-        dfY = OGRFastAtof( GetElementText(psYNode) );
+        double dfX = OGRFastAtof( GetElementText(psXNode) );
+        double dfY = OGRFastAtof( GetElementText(psYNode) );
 
+        int nDimension = 2;
+        double dfZ = 0.0;
         if( psZNode != NULL && GetElementText(psZNode) != NULL )
         {
             dfZ = OGRFastAtof( GetElementText(psZNode) );
@@ -596,7 +585,7 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
         }
 
         if( !AddPoint( poGeometry, dfX, dfY, dfZ, nDimension ) )
-            return FALSE;
+            return false;
 
         iCoord++;
     }
@@ -610,7 +599,7 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
 /*                                                                      */
 /*      Identifies the "good" Polygon whithin the collection returned   */
 /*      by GEOSPolygonize()                                             */
-/*      short rationale: GEOSPolygonize() will possibily return a       */
+/*      short rationale: GEOSPolygonize() will possibly return a        */
 /*      collection of many Polygons; only one is the "good" one,        */
 /*      (including both exterior- and interior-rings)                   */
 /*      any other simply represents a single "hole", and should be      */
@@ -620,7 +609,7 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
 static OGRPolygon *GML2FaceExtRing( OGRGeometry *poGeom )
 {
     OGRPolygon *poPolygon = NULL;
-    int bError = FALSE;
+    bool bError = false;
     OGRGeometryCollection *poColl = (OGRGeometryCollection *)poGeom;
     int iCount = poColl->getNumGeometries();
     int iExterior = 0;
@@ -632,7 +621,7 @@ static OGRPolygon *GML2FaceExtRing( OGRGeometry *poGeom )
         OGRGeometry * poChild = (OGRGeometry*)poColl->getGeometryRef(ig);
         if( poChild == NULL)
         {
-            bError = TRUE;
+            bError = true;
             continue;
         }
         if( wkbFlatten( poChild->getGeometryType()) == wkbPolygon )
@@ -644,10 +633,10 @@ static OGRPolygon *GML2FaceExtRing( OGRGeometry *poGeom )
                 iInterior++;
         }
         else
-            bError = TRUE;
+            bError = true;
     }
 
-    if( bError == FALSE && iCount > 0 )
+    if( !bError && iCount > 0 )
     {
        if( iCount == 1 && iExterior == 0 && iInterior == 1)
         {
@@ -679,17 +668,17 @@ static OGRPolygon *GML2FaceExtRing( OGRGeometry *poGeom )
 /************************************************************************/
 
 static
-int GML2OGRGeometry_AddToCompositeCurve(OGRCompoundCurve* poCC,
+bool GML2OGRGeometry_AddToCompositeCurve(OGRCompoundCurve* poCC,
                                         OGRGeometry* poGeom,
-                                        int& bChildrenAreAllLineString)
+                                        bool& bChildrenAreAllLineString)
 {
     if( poGeom == NULL ||
         !OGR_GT_IsCurve(poGeom->getGeometryType()) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                 "CompositeCurve: Got %.500s geometry as Member instead of a curve.",
                 poGeom ? poGeom->getGeometryName() : "NULL" );
-        return FALSE;
+        return false;
     }
 
     /* Crazy but allowed by GML: composite in composite */
@@ -700,11 +689,11 @@ int GML2OGRGeometry_AddToCompositeCurve(OGRCompoundCurve* poCC,
         {
             OGRCurve* poCurve = poCCChild->stealCurve(0);
             if( wkbFlatten(poCurve->getGeometryType()) != wkbLineString )
-                bChildrenAreAllLineString = FALSE;
+                bChildrenAreAllLineString = false;
             if( poCC->addCurveDirectly( poCurve ) != OGRERR_NONE )
             {
                 delete poCurve;
-                return FALSE;
+                return false;
             }
         }
         delete poCCChild;
@@ -712,14 +701,14 @@ int GML2OGRGeometry_AddToCompositeCurve(OGRCompoundCurve* poCC,
     else
     {
         if( wkbFlatten(poGeom->getGeometryType()) != wkbLineString )
-            bChildrenAreAllLineString = FALSE;
+            bChildrenAreAllLineString = false;
 
         if( poCC->addCurveDirectly( (OGRCurve*)poGeom ) != OGRERR_NONE )
         {
-            return FALSE;
+            return false;
         }
     }
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -727,27 +716,27 @@ int GML2OGRGeometry_AddToCompositeCurve(OGRCompoundCurve* poCC,
 /************************************************************************/
 
 static
-int GML2OGRGeometry_AddToMultiSurface(OGRMultiSurface* poMS,
+bool GML2OGRGeometry_AddToMultiSurface(OGRMultiSurface* poMS,
                                       OGRGeometry*& poGeom,
                                       const char* pszMemberElement,
-                                      int& bChildrenAreAllPolygons)
+                                      bool& bChildrenAreAllPolygons)
 {
     if (poGeom == NULL)
     {
         CPLError( CE_Failure, CPLE_AppDefined, "Invalid %s",
                     pszMemberElement );
-        return FALSE;
+        return false;
     }
 
     OGRwkbGeometryType eType = wkbFlatten(poGeom->getGeometryType());
     if( eType == wkbPolygon || eType == wkbCurvePolygon )
     {
         if( eType != wkbPolygon )
-            bChildrenAreAllPolygons = FALSE;
+            bChildrenAreAllPolygons = false;
 
         if( poMS->addGeometryDirectly( poGeom ) != OGRERR_NONE )
         {
-            return FALSE;
+            return false;
         }
     }
     else if (eType == wkbMultiPolygon || eType == wkbMultiSurface)
@@ -757,11 +746,11 @@ int GML2OGRGeometry_AddToMultiSurface(OGRMultiSurface* poMS,
         for(i=0;i<poMS2->getNumGeometries();i++)
         {
             if( wkbFlatten(poMS2->getGeometryRef(i)->getGeometryType()) != wkbPolygon )
-                bChildrenAreAllPolygons = FALSE;
+                bChildrenAreAllPolygons = false;
 
             if( poMS->addGeometry(poMS2->getGeometryRef(i)) != OGRERR_NONE )
             {
-                return FALSE;
+                return false;
             }
         }
         delete poGeom;
@@ -772,9 +761,9 @@ int GML2OGRGeometry_AddToMultiSurface(OGRMultiSurface* poMS,
         CPLError( CE_Failure, CPLE_AppDefined,
                     "Got %.500s geometry as %s.",
                     poGeom->getGeometryName(), pszMemberElement );
-        return FALSE;
+        return false;
     }
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -787,25 +776,25 @@ int GML2OGRGeometry_AddToMultiSurface(OGRMultiSurface* poMS,
 
 static
 OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
-                                               int bGetSecondaryGeometryOption,
+                                               int nPseudoBoolGetSecondaryGeometryOption,
                                                int nRecLevel,
                                                int nSRSDimension,
                                                const char* pszSRSName,
-                                               int bIgnoreGSG = FALSE,
-                                               int bOrientation = TRUE,
-                                               int bFaceHoleNegative = FALSE );
+                                               bool bIgnoreGSG = false,
+                                               bool bOrientation = true,
+                                               bool bFaceHoleNegative = false );
 
 OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
-                                      int bGetSecondaryGeometryOption,
+                                      int nPseudoBoolGetSecondaryGeometryOption,
                                       int nRecLevel,
                                       int nSRSDimension,
-                                      int bIgnoreGSG,
-                                      int bOrientation,
-                                      int bFaceHoleNegative ) 
+                                      bool bIgnoreGSG,
+                                      bool bOrientation,
+                                      bool bFaceHoleNegative )
 
 {
     return GML2OGRGeometry_XMLNode_Internal(psNode,
-                                            bGetSecondaryGeometryOption,
+                                            nPseudoBoolGetSecondaryGeometryOption,
                                             nRecLevel, nSRSDimension,
                                             NULL,
                                             bIgnoreGSG, bOrientation,
@@ -814,15 +803,15 @@ OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
 
 static
 OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
-                                               int bGetSecondaryGeometryOption,
+                                               int nPseudoBoolGetSecondaryGeometryOption,
                                                int nRecLevel,
                                                int nSRSDimension,
                                                const char* pszSRSName,
-                                               int bIgnoreGSG,
-                                               int bOrientation,
-                                               int bFaceHoleNegative )
+                                               bool bIgnoreGSG,
+                                               bool bOrientation,
+                                               bool bFaceHoleNegative )
 {
-    const int bCastToLinearTypeIfPossible = TRUE;     /* hard-coded for now */
+    const bool bCastToLinearTypeIfPossible = true;     /* hard-coded for now */
 
     if( psNode != NULL && strcmp(psNode->pszValue, "?xml") == 0 )
         psNode = psNode->psNext;
@@ -834,14 +823,14 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
     const char* pszSRSDimension = CPLGetXMLValue( (CPLXMLNode*) psNode, "srsDimension", NULL);
     if( pszSRSDimension != NULL )
         nSRSDimension = atoi(pszSRSDimension);
-    
+
     if( pszSRSName == NULL )
         pszSRSName = CPLGetXMLValue( (CPLXMLNode*) psNode, "srsName", NULL);
 
     const char *pszBaseGeometry = BareGMLElement( psNode->pszValue );
-    if (bGetSecondaryGeometryOption < 0)
-        bGetSecondaryGeometryOption = CSLTestBoolean(CPLGetConfigOption("GML_GET_SECONDARY_GEOM", "NO"));
-    int bGetSecondaryGeometry = bIgnoreGSG ? FALSE : bGetSecondaryGeometryOption;
+    if (nPseudoBoolGetSecondaryGeometryOption < 0)
+        nPseudoBoolGetSecondaryGeometryOption = CPLTestBool(CPLGetConfigOption("GML_GET_SECONDARY_GEOM", "NO"));
+    bool bGetSecondaryGeometry = bIgnoreGSG ? false : CPL_TO_BOOL(nPseudoBoolGetSecondaryGeometryOption);
 
     /* Arbitrary value, but certainly large enough for reasonable usages ! */
     if( nRecLevel == 32 )
@@ -882,7 +871,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         // Translate outer ring and add to polygon.
         OGRGeometry* poGeom =
             GML2OGRGeometry_XMLNode_Internal( psChild,
-                                              bGetSecondaryGeometryOption,
+                                              nPseudoBoolGetSecondaryGeometryOption,
                                               nRecLevel + 1, nSRSDimension,
                                               pszSRSName );
         if( poGeom == NULL )
@@ -893,7 +882,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 
         if( !OGR_GT_IsCurve(poGeom->getGeometryType()) )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "%s: Got %.500s geometry as outerBoundaryIs.",
                       pszBaseGeometry, poGeom->getGeometryName() );
             delete poGeom;
@@ -907,16 +896,16 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         }
 
         OGRCurvePolygon *poCP;
-        int bIsPolygon;
+        bool bIsPolygon;
         if( EQUAL(poGeom->getGeometryName(), "LINEARRING") )
         {
             poCP = new OGRPolygon();
-            bIsPolygon = TRUE;
+            bIsPolygon = true;
         }
         else
         {
             poCP = new OGRCurvePolygon();
-            bIsPolygon = FALSE;
+            bIsPolygon = false;
         }
 
         if( poCP->addRingDirectly( (OGRCurve*)poGeom ) != OGRERR_NONE )
@@ -926,10 +915,10 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             return NULL;
         }
 
-        // Find all inner rings 
-        for( psChild = psNode->psChild; 
+        // Find all inner rings
+        for( psChild = psNode->psChild;
              psChild != NULL;
-             psChild = psChild->psNext ) 
+             psChild = psChild->psNext )
         {
             if( psChild->eType == CXT_Element
                 && (EQUAL(BareGMLElement(psChild->pszValue),"innerBoundaryIs") ||
@@ -939,7 +928,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                 if (psInteriorChild != NULL)
                     poGeom =
                         GML2OGRGeometry_XMLNode_Internal( psInteriorChild,
-                                                          bGetSecondaryGeometryOption,
+                                                          nPseudoBoolGetSecondaryGeometryOption,
                                                           nRecLevel + 1,
                                                           nSRSDimension,
                                                           pszSRSName );
@@ -954,7 +943,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 
                 if( !OGR_GT_IsCurve(poGeom->getGeometryType()) )
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined, 
+                    CPLError( CE_Failure, CPLE_AppDefined,
                             "%s: Got %.500s geometry as innerBoundaryIs.",
                             pszBaseGeometry, poGeom->getGeometryName() );
                     delete poCP;
@@ -982,7 +971,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                                 delete poGeom;
                                 return NULL;
                             }
-                            bIsPolygon = FALSE;
+                            bIsPolygon = false;
                         }
                     }
                 }
@@ -1009,7 +998,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
     if( EQUAL(pszBaseGeometry,"LinearRing") )
     {
         OGRLinearRing   *poLinearRing = new OGRLinearRing();
-        
+
         if( !ParseGMLCoordinates( psNode, poLinearRing, nSRSDimension ) )
         {
             delete poLinearRing;
@@ -1026,14 +1015,14 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
     {
         OGRCurve* poRing = NULL;
         OGRCompoundCurve   *poCC = NULL;
-        int bChildrenAreAllLineString = TRUE;
+        bool bChildrenAreAllLineString = true;
         const CPLXMLNode *psChild;
 
-        int bLastCurveWasApproximateArc = FALSE;
-        int bLastCurveWasApproximateArcInvertedAxisOrder = FALSE;
+        bool bLastCurveWasApproximateArc = false;
+        bool bLastCurveWasApproximateArcInvertedAxisOrder = false;
         double dfLastCurveApproximateArcRadius = 0;
 
-        for( psChild = psNode->psChild; 
+        for( psChild = psNode->psChild;
              psChild != NULL; psChild = psChild->psNext )
         {
             if( psChild->eType == CXT_Element
@@ -1044,7 +1033,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                 if (psCurveChild != NULL)
                     poGeom =
                         GML2OGRGeometry_XMLNode_Internal( psCurveChild,
-                                                          bGetSecondaryGeometryOption,
+                                                          nPseudoBoolGetSecondaryGeometryOption,
                                                           nRecLevel + 1,
                                                           nSRSDimension,
                                                           pszSRSName );
@@ -1068,7 +1057,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                     poGeom = OGRGeometryFactory::forceToLineString( poGeom, false );
                 }
 
-                if( poGeom == NULL 
+                if( poGeom == NULL
                     || !OGR_GT_IsCurve(poGeom->getGeometryType()) )
                 {
                     delete poGeom;
@@ -1078,11 +1067,11 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                 }
 
                 if( wkbFlatten(poGeom->getGeometryType()) != wkbLineString )
-                    bChildrenAreAllLineString = FALSE;
+                    bChildrenAreAllLineString = false;
 
                 /* Ad-hoc logic to handle nicely connecting ArcByCenterPoint */
                 /* with consecutive curves, as found in some AIXM files */
-                int bIsApproximateArc = FALSE;
+                bool bIsApproximateArc = false;
                 const CPLXMLNode* psChild2, *psChild3;
                 if( strcmp(psCurveChild->pszValue, "Curve") == 0 &&
                     (psChild2 = GetChildElement(psCurveChild)) != NULL &&
@@ -1095,8 +1084,8 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                     {
                         double dfRadius = CPLAtof(CPLGetXMLValue((CPLXMLNode*)psRadius, NULL, "0"));
                         const char* pszUnits = CPLGetXMLValue((CPLXMLNode*)psRadius, "uom", NULL);
-                        int bSRSUnitIsDeegree = FALSE;
-                        int bInvertedAxisOrder = FALSE;
+                        bool bSRSUnitIsDegree = false;
+                        bool bInvertedAxisOrder = false;
                         if( pszSRSName != NULL )
                         {
                             OGRSpatialReference oSRS;
@@ -1104,16 +1093,16 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                             {
                                 if( oSRS.IsGeographic() )
                                 {
-                                    bInvertedAxisOrder = oSRS.EPSGTreatsAsLatLong();
-                                    bSRSUnitIsDeegree = fabs(oSRS.GetAngularUnits(NULL) - CPLAtof(SRS_UA_DEGREE_CONV)) < 1e-8;
+                                    bInvertedAxisOrder = CPL_TO_BOOL(oSRS.EPSGTreatsAsLatLong());
+                                    bSRSUnitIsDegree = fabs(oSRS.GetAngularUnits(NULL) - CPLAtof(SRS_UA_DEGREE_CONV)) < 1e-8;
                                 }
                             }
                         }
-                        if( bSRSUnitIsDeegree && pszUnits != NULL &&
+                        if( bSRSUnitIsDegree && pszUnits != NULL &&
                             (EQUAL(pszUnits, "m") || EQUAL(pszUnits, "nm") ||
                              EQUAL(pszUnits, "mi") || EQUAL(pszUnits, "ft")) )
                         {
-                            bIsApproximateArc = TRUE;
+                            bIsApproximateArc = true;
                             if( EQUAL(pszUnits, "nm") )
                                 dfRadius *= CPLAtof(SRS_UL_INTL_NAUT_MILE_CONV);
                             else if( EQUAL(pszUnits, "mi") )
@@ -1217,7 +1206,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             }
             return poRing;
         }
-        
+
         if( poCC == NULL )
             return NULL;
 
@@ -1245,7 +1234,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         || EQUAL(pszBaseGeometry,"GeodesicString") )
     {
         OGRLineString   *poLine = new OGRLineString();
-        
+
         if( !ParseGMLCoordinates( psNode, poLine, nSRSDimension ) )
         {
             delete poLine;
@@ -1300,18 +1289,18 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         if (det < 0)
         {
             if (alpha1 > alpha0)
-                alpha1 -= 2 * PI;
+                alpha1 -= 2 * M_PI;
             if (alpha2 > alpha1)
-                alpha2 -= 2 * PI;
-            alpha3 = alpha0 - 2 * PI;
+                alpha2 -= 2 * M_PI;
+            alpha3 = alpha0 - 2 * M_PI;
         }
         else
         {
             if (alpha1 < alpha0)
-                alpha1 += 2 * PI;
+                alpha1 += 2 * M_PI;
             if (alpha2 < alpha1)
-                alpha2 += 2 * PI;
-            alpha3 = alpha0 + 2 * PI;
+                alpha2 += 2 * M_PI;
+            alpha3 = alpha0 + 2 * M_PI;
         }
 
         CPLAssert((alpha0 <= alpha1 && alpha1 <= alpha2 && alpha2 <= alpha3) ||
@@ -1320,29 +1309,29 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         int nSign = (det >= 0) ? 1 : -1;
 
         double alpha, dfRemainder;
-        double dfStep = CPLAtof(CPLGetConfigOption("OGR_ARC_STEPSIZE","4")) / 180 * PI;
+        double dfStep = CPLAtof(CPLGetConfigOption("OGR_ARC_STEPSIZE","4")) / 180 * M_PI;
 
         // make sure the segments are not too short
         double dfMinStepLength = CPLAtof( CPLGetConfigOption("OGR_ARC_MINLENGTH","0") );
         if ( dfMinStepLength > 0.0 && dfStep * R < dfMinStepLength )
         {
             CPLDebug( "GML", "Increasing arc step to %lf° (was %lf° with segment length %lf at radius %lf; min segment length is %lf)",
-                      dfMinStepLength * 180.0 / PI / R,
-                      dfStep * 180.0 / PI,
+                      dfMinStepLength * 180.0 / M_PI / R,
+                      dfStep * 180.0 / M_PI,
                       dfStep * R,
                       R,
                       dfMinStepLength );
             dfStep = dfMinStepLength / R;
         }
 
-        if (dfStep < 4. / 180 * PI)
+        if (dfStep < 4. / 180 * M_PI)
         {
             CPLDebug( "GML", "Increasing arc step to %lf° (was %lf° with length %lf at radius %lf).",
-                      4. / 180 * PI,
-                      dfStep * 180.0 / PI,
+                      4. / 180 * M_PI,
+                      dfStep * 180.0 / M_PI,
                       dfStep * R,
                       R );
-            dfStep = 4. / 180 * PI;
+            dfStep = 4. / 180 * M_PI;
         }
 
         poLine->setNumPoints(0);
@@ -1594,9 +1583,9 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         {
             return NULL;
         }
-        
-        int bSRSUnitIsDeegree = FALSE;
-        int bInvertedAxisOrder = FALSE;
+
+        bool bSRSUnitIsDegree = false;
+        bool bInvertedAxisOrder = false;
         if( pszSRSName != NULL )
         {
             OGRSpatialReference oSRS;
@@ -1604,16 +1593,16 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             {
                 if( oSRS.IsGeographic() )
                 {
-                    bInvertedAxisOrder = oSRS.EPSGTreatsAsLatLong();
-                    bSRSUnitIsDeegree = fabs(oSRS.GetAngularUnits(NULL) - CPLAtof(SRS_UA_DEGREE_CONV)) < 1e-8;
+                    bInvertedAxisOrder = CPL_TO_BOOL(oSRS.EPSGTreatsAsLatLong());
+                    bSRSUnitIsDegree = fabs(oSRS.GetAngularUnits(NULL) - CPLAtof(SRS_UA_DEGREE_CONV)) < 1e-8;
                 }
             }
         }
 
         double dfCenterX = p.getX();
         double dfCenterY = p.getY();
-        
-        if( bSRSUnitIsDeegree && pszUnits != NULL &&
+
+        if( bSRSUnitIsDegree && pszUnits != NULL &&
             (EQUAL(pszUnits, "m") || EQUAL(pszUnits, "nm") ||
              EQUAL(pszUnits, "mi") || EQUAL(pszUnits, "ft")) )
         {
@@ -1646,9 +1635,9 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                     p.setX( dfLong );
                     p.setY( dfLat );
                 }
-                poLS->addPoint(&p);             
+                poLS->addPoint(&p);
             }
-            
+
             double dfLong, dfLat;
             if( bInvertedAxisOrder )
             {
@@ -1706,9 +1695,9 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         {
             return NULL;
         }
-        
-        int bSRSUnitIsDeegree = FALSE;
-        int bInvertedAxisOrder = FALSE;
+
+        bool bSRSUnitIsDegree = false;
+        bool bInvertedAxisOrder = false;
         if( pszSRSName != NULL )
         {
             OGRSpatialReference oSRS;
@@ -1716,16 +1705,16 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             {
                 if( oSRS.IsGeographic() )
                 {
-                    bInvertedAxisOrder = oSRS.EPSGTreatsAsLatLong();
-                    bSRSUnitIsDeegree = fabs(oSRS.GetAngularUnits(NULL) - CPLAtof(SRS_UA_DEGREE_CONV)) < 1e-8;
+                    bInvertedAxisOrder = CPL_TO_BOOL(oSRS.EPSGTreatsAsLatLong());
+                    bSRSUnitIsDegree = fabs(oSRS.GetAngularUnits(NULL) - CPLAtof(SRS_UA_DEGREE_CONV)) < 1e-8;
                 }
             }
         }
 
         double dfCenterX = p.getX();
         double dfCenterY = p.getY();
-        
-        if( bSRSUnitIsDeegree && pszUnits != NULL &&
+
+        if( bSRSUnitIsDegree && pszUnits != NULL &&
             (EQUAL(pszUnits, "m") || EQUAL(pszUnits, "nm") ||
              EQUAL(pszUnits, "mi") || EQUAL(pszUnits, "ft")) )
         {
@@ -1757,10 +1746,10 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                     p.setX( dfLong );
                     p.setY( dfLat );
                 }
-                poLS->addPoint(&p);             
+                poLS->addPoint(&p);
             }
             poLS->getPoint(0, &p);
-            poLS->addPoint(&p);     
+            poLS->addPoint(&p);
             return poLS;
         }
 
@@ -1780,12 +1769,12 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 /* -------------------------------------------------------------------- */
 /*      PointType                                                       */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"PointType") 
+    if( EQUAL(pszBaseGeometry,"PointType")
         || EQUAL(pszBaseGeometry,"Point")
         || EQUAL(pszBaseGeometry,"ConnectionPoint") )
     {
         OGRPoint *poPoint = new OGRPoint();
-        
+
         if( !ParseGMLCoordinates( psNode, poPoint, nSRSDimension ) )
         {
             delete poPoint;
@@ -1812,15 +1801,15 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         OGRPolygon *poBoxPoly = new OGRPolygon();
 
         poBoxRing->setNumPoints( 5 );
-        poBoxRing->setPoint( 
+        poBoxRing->setPoint(
             0, oPoints.getX(0), oPoints.getY(0), oPoints.getZ(0) );
-        poBoxRing->setPoint( 
+        poBoxRing->setPoint(
             1, oPoints.getX(1), oPoints.getY(0), oPoints.getZ(0) );
-        poBoxRing->setPoint( 
+        poBoxRing->setPoint(
             2, oPoints.getX(1), oPoints.getY(1), oPoints.getZ(1) );
-        poBoxRing->setPoint( 
+        poBoxRing->setPoint(
             3, oPoints.getX(0), oPoints.getY(1), oPoints.getZ(0) );
-        poBoxRing->setPoint( 
+        poBoxRing->setPoint(
             4, oPoints.getX(0), oPoints.getY(0), oPoints.getZ(0) );
 
         poBoxPoly->addRingDirectly( poBoxRing );
@@ -1851,7 +1840,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             CSLDestroy(papszUpperCorner);
             return NULL;
         }
-        
+
         double dfLLX = CPLAtof(papszLowerCorner[0]);
         double dfLLY = CPLAtof(papszLowerCorner[1]);
         double dfURX = CPLAtof(papszUpperCorner[0]);
@@ -1889,13 +1878,13 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             poMS = new OGRMultiPolygon();
         else
             poMS = new OGRMultiSurface();
-        int bReconstructTopology = FALSE;
-        int bChildrenAreAllPolygons = TRUE;
+        bool bReconstructTopology = false;
+        bool bChildrenAreAllPolygons = true;
 
         // Iterate over children
-        for( psChild = psNode->psChild; 
+        for( psChild = psNode->psChild;
              psChild != NULL;
-             psChild = psChild->psNext ) 
+             psChild = psChild->psNext )
         {
             const char* pszMemberElement = BareGMLElement(psChild->pszValue);
             if( psChild->eType == CXT_Element
@@ -1908,26 +1897,27 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                 {
                     /* Cf #5421 where there are PolygonPatch with only inner rings */
                     const CPLXMLNode* psPolygonPatch = GetChildElement(GetChildElement(psSurfaceChild));
+                    const CPLXMLNode* psPolygonPatchChild;
                     if( psPolygonPatch != NULL &&
                         psPolygonPatch->eType == CXT_Element &&
                         EQUAL(BareGMLElement(psPolygonPatch->pszValue),"PolygonPatch") &&
-                        GetChildElement(psPolygonPatch) != NULL &&
-                        EQUAL(BareGMLElement(GetChildElement(psPolygonPatch)->pszValue),"interior") )
+                        (psPolygonPatchChild = GetChildElement(psPolygonPatch)) != NULL &&
+                        EQUAL(BareGMLElement(psPolygonPatchChild->pszValue),"interior") )
                     {
-                        // Find all inner rings 
-                        for( const CPLXMLNode* psChild2 = psPolygonPatch->psChild; 
+                        // Find all inner rings
+                        for( const CPLXMLNode* psChild2 = psPolygonPatch->psChild;
                             psChild2 != NULL;
-                            psChild2 = psChild2->psNext ) 
+                            psChild2 = psChild2->psNext )
                         {
                             if( psChild2->eType == CXT_Element
                                 && (EQUAL(BareGMLElement(psChild2->pszValue),"interior")))
                             {
                                 const CPLXMLNode* psInteriorChild = GetChildElement(psChild2);
-                                OGRLinearRing* poRing;
+                                OGRGeometry* poRing;
                                 if (psInteriorChild != NULL)
-                                    poRing = (OGRLinearRing *) 
+                                    poRing =
                                         GML2OGRGeometry_XMLNode_Internal(
-                                            psInteriorChild, bGetSecondaryGeometryOption,
+                                            psInteriorChild, nPseudoBoolGetSecondaryGeometryOption,
                                             nRecLevel + 1, nSRSDimension, pszSRSName );
                                 else
                                     poRing = NULL;
@@ -1939,7 +1929,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                                 }
                                 if( !EQUAL(poRing->getGeometryName(),"LINEARRING") )
                                 {
-                                    CPLError( CE_Failure, CPLE_AppDefined, 
+                                    CPLError( CE_Failure, CPLE_AppDefined,
                                             "%s: Got %.500s geometry as innerBoundaryIs instead of LINEARRING.",
                                             pszBaseGeometry, poRing->getGeometryName() );
                                     delete poRing;
@@ -1947,9 +1937,9 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                                     return NULL;
                                 }
 
-                                bReconstructTopology = TRUE;
+                                bReconstructTopology = true;
                                 OGRPolygon *poPolygon = new OGRPolygon();
-                                poPolygon->addRingDirectly( poRing );
+                                poPolygon->addRingDirectly( (OGRLinearRing*)poRing );
                                 poMS->addGeometryDirectly( poPolygon );
                             }
                         }
@@ -1958,7 +1948,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                     {
                         OGRGeometry* poGeom =
                             GML2OGRGeometry_XMLNode_Internal( psSurfaceChild,
-                                  bGetSecondaryGeometryOption,
+                                  nPseudoBoolGetSecondaryGeometryOption,
                                   nRecLevel + 1, nSRSDimension, pszSRSName );
                         if( !GML2OGRGeometry_AddToMultiSurface(poMS, poGeom,
                                                                pszMemberElement,
@@ -1987,7 +1977,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                             EQUAL(pszMemberElement,"CompositeSurface")) )
                     {
                         OGRGeometry* poGeom = GML2OGRGeometry_XMLNode_Internal(
-                            psChild2, bGetSecondaryGeometryOption,
+                            psChild2, nPseudoBoolGetSecondaryGeometryOption,
                             nRecLevel + 1, nSRSDimension, pszSRSName );
                         if( !GML2OGRGeometry_AddToMultiSurface(poMS, poGeom,
                                                                pszMemberElement,
@@ -2026,7 +2016,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         }
         else
         {
-            if( bCastToLinearTypeIfPossible && 
+            if( bCastToLinearTypeIfPossible &&
                 wkbFlatten(poMS->getGeometryType()) == wkbMultiSurface &&
                 bChildrenAreAllPolygons )
             {
@@ -2046,34 +2036,34 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         OGRMultiPoint *poMP = new OGRMultiPoint();
 
         // collect points.
-        for( psChild = psNode->psChild; 
+        for( psChild = psNode->psChild;
              psChild != NULL;
-             psChild = psChild->psNext ) 
+             psChild = psChild->psNext )
         {
             if( psChild->eType == CXT_Element
                 && EQUAL(BareGMLElement(psChild->pszValue),"pointMember") )
             {
                 const CPLXMLNode* psPointChild = GetChildElement(psChild);
-                OGRPoint *poPoint;
+                OGRGeometry *poPointMember;
 
                 if (psPointChild != NULL)
                 {
-                    poPoint = (OGRPoint *) 
+                    poPointMember =
                         GML2OGRGeometry_XMLNode_Internal( psPointChild,
-                              bGetSecondaryGeometryOption,
+                              nPseudoBoolGetSecondaryGeometryOption,
                               nRecLevel + 1, nSRSDimension, pszSRSName );
-                    if( poPoint == NULL 
-                        || wkbFlatten(poPoint->getGeometryType()) != wkbPoint )
+                    if( poPointMember == NULL
+                        || wkbFlatten(poPointMember->getGeometryType()) != wkbPoint )
                     {
-                        CPLError( CE_Failure, CPLE_AppDefined, 
+                        CPLError( CE_Failure, CPLE_AppDefined,
                                 "MultiPoint: Got %.500s geometry as pointMember instead of POINT",
-                                poPoint ? poPoint->getGeometryName() : "NULL" );
-                        delete poPoint;
+                                poPointMember ? poPointMember->getGeometryName() : "NULL" );
+                        delete poPointMember;
                         delete poMP;
                         return NULL;
                     }
 
-                    poMP->addGeometryDirectly( poPoint );
+                    poMP->addGeometryDirectly( poPointMember );
                 }
             }
             else if (psChild->eType == CXT_Element
@@ -2088,7 +2078,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                         && (EQUAL(BareGMLElement(psChild2->pszValue),"Point")) )
                     {
                         OGRGeometry* poGeom = GML2OGRGeometry_XMLNode_Internal(
-                            psChild2, bGetSecondaryGeometryOption,
+                            psChild2, nPseudoBoolGetSecondaryGeometryOption,
                             nRecLevel + 1, nSRSDimension, pszSRSName );
                         if (poGeom == NULL)
                         {
@@ -2128,9 +2118,9 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         OGRMultiLineString *poMLS = new OGRMultiLineString();
 
         // collect lines
-        for( psChild = psNode->psChild; 
+        for( psChild = psNode->psChild;
              psChild != NULL;
-             psChild = psChild->psNext ) 
+             psChild = psChild->psNext )
         {
             if( psChild->eType == CXT_Element
                 && EQUAL(BareGMLElement(psChild->pszValue),"lineStringMember") )
@@ -2140,14 +2130,14 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 
                 if (psLineStringChild != NULL)
                     poGeom = GML2OGRGeometry_XMLNode_Internal( psLineStringChild,
-                          bGetSecondaryGeometryOption,
+                          nPseudoBoolGetSecondaryGeometryOption,
                           nRecLevel + 1, nSRSDimension, pszSRSName );
                 else
                     poGeom = NULL;
-                if( poGeom == NULL 
+                if( poGeom == NULL
                     || wkbFlatten(poGeom->getGeometryType()) != wkbLineString )
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined, 
+                    CPLError( CE_Failure, CPLE_AppDefined,
                               "MultiLineString: Got %.500s geometry as Member instead of LINESTRING.",
                               poGeom ? poGeom->getGeometryName() : "NULL" );
                     delete poGeom;
@@ -2170,12 +2160,12 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
     {
         const CPLXMLNode *psChild;
         OGRMultiCurve *poMC = new OGRMultiCurve();
-        int bChildrenAreAllLineString = TRUE;
+        bool bChildrenAreAllLineString = true;
 
         // collect curveMembers
-        for( psChild = psNode->psChild; 
+        for( psChild = psNode->psChild;
              psChild != NULL;
-             psChild = psChild->psNext ) 
+             psChild = psChild->psNext )
         {
             if( psChild->eType == CXT_Element
                 && EQUAL(BareGMLElement(psChild->pszValue),"curveMember") )
@@ -2184,12 +2174,12 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                 if( psChild2 != NULL ) /* empty curveMember is valid */
                 {
                     OGRGeometry* poGeom = GML2OGRGeometry_XMLNode_Internal(
-                        psChild2, bGetSecondaryGeometryOption,
+                        psChild2, nPseudoBoolGetSecondaryGeometryOption,
                         nRecLevel + 1, nSRSDimension, pszSRSName );
                     if( poGeom == NULL ||
                         !OGR_GT_IsCurve(poGeom->getGeometryType()) )
                     {
-                        CPLError( CE_Failure, CPLE_AppDefined, 
+                        CPLError( CE_Failure, CPLE_AppDefined,
                                 "MultiCurve: Got %.500s geometry as Member instead of a curve.",
                                 poGeom ? poGeom->getGeometryName() : "NULL" );
                         if( poGeom != NULL ) delete poGeom;
@@ -2198,7 +2188,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                     }
 
                     if( wkbFlatten(poGeom->getGeometryType()) != wkbLineString )
-                        bChildrenAreAllLineString = FALSE;
+                        bChildrenAreAllLineString = false;
 
                     if( poMC->addGeometryDirectly( poGeom ) != OGRERR_NONE )
                     {
@@ -2217,12 +2207,12 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                     if( psChild2->eType == CXT_Element )
                     {
                         OGRGeometry* poGeom = GML2OGRGeometry_XMLNode_Internal(
-                            psChild2, bGetSecondaryGeometryOption,
+                            psChild2, nPseudoBoolGetSecondaryGeometryOption,
                             nRecLevel + 1, nSRSDimension, pszSRSName );
                         if (poGeom == NULL ||
                             !OGR_GT_IsCurve(poGeom->getGeometryType()) )
                         {
-                            CPLError( CE_Failure, CPLE_AppDefined, 
+                            CPLError( CE_Failure, CPLE_AppDefined,
                                     "MultiCurve: Got %.500s geometry as Member instead of a curve.",
                                     poGeom ? poGeom->getGeometryName() : "NULL" );
                             if( poGeom != NULL ) delete poGeom;
@@ -2231,7 +2221,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                         }
 
                         if( wkbFlatten(poGeom->getGeometryType()) != wkbLineString )
-                            bChildrenAreAllLineString = FALSE;
+                            bChildrenAreAllLineString = false;
 
                         if( poMC->addGeometryDirectly( poGeom ) != OGRERR_NONE )
                         {
@@ -2258,12 +2248,12 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
     {
         const CPLXMLNode *psChild;
         OGRCompoundCurve *poCC = new OGRCompoundCurve();
-        int bChildrenAreAllLineString = TRUE;
+        bool bChildrenAreAllLineString = true;
 
         // collect curveMembers
-        for( psChild = psNode->psChild; 
+        for( psChild = psNode->psChild;
              psChild != NULL;
-             psChild = psChild->psNext ) 
+             psChild = psChild->psNext )
         {
             if( psChild->eType == CXT_Element
                 && EQUAL(BareGMLElement(psChild->pszValue),"curveMember") )
@@ -2272,7 +2262,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                 if( psChild2 != NULL ) /* empty curveMember is valid */
                 {
                     OGRGeometry*poGeom = GML2OGRGeometry_XMLNode_Internal(
-                        psChild2, bGetSecondaryGeometryOption,
+                        psChild2, nPseudoBoolGetSecondaryGeometryOption,
                         nRecLevel + 1, nSRSDimension, pszSRSName );
                     if( !GML2OGRGeometry_AddToCompositeCurve(poCC, poGeom,
                                                                 bChildrenAreAllLineString) )
@@ -2294,7 +2284,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                     if( psChild2->eType == CXT_Element )
                     {
                         OGRGeometry* poGeom = GML2OGRGeometry_XMLNode_Internal(
-                            psChild2, bGetSecondaryGeometryOption,
+                            psChild2, nPseudoBoolGetSecondaryGeometryOption,
                             nRecLevel + 1, nSRSDimension, pszSRSName );
                         if( !GML2OGRGeometry_AddToCompositeCurve(poCC, poGeom,
                                                              bChildrenAreAllLineString) )
@@ -2315,7 +2305,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         else
             return poCC;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Curve                                                           */
 /* -------------------------------------------------------------------- */
@@ -2334,12 +2324,12 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         OGRGeometry *poGeom;
 
         poGeom = GML2OGRGeometry_XMLNode_Internal(
-            psChild, bGetSecondaryGeometryOption,
+            psChild, nPseudoBoolGetSecondaryGeometryOption,
             nRecLevel + 1, nSRSDimension, pszSRSName );
         if( poGeom == NULL ||
             !OGR_GT_IsCurve(poGeom->getGeometryType()) )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                 "Curve: Got %.500s geometry as Member instead of segments.",
                 poGeom ? poGeom->getGeometryName() : "NULL" );
             if( poGeom != NULL ) delete poGeom;
@@ -2357,11 +2347,11 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         const CPLXMLNode *psChild;
         OGRCurve* poCurve = NULL;
         OGRCompoundCurve *poCC = NULL;
-        int bChildrenAreAllLineString = TRUE;
+        bool bChildrenAreAllLineString = true;
 
-        for( psChild = psNode->psChild; 
+        for( psChild = psNode->psChild;
              psChild != NULL;
-             psChild = psChild->psNext ) 
+             psChild = psChild->psNext )
 
         {
             if( psChild->eType == CXT_Element
@@ -2373,7 +2363,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                 OGRGeometry *poGeom;
 
                 poGeom = GML2OGRGeometry_XMLNode_Internal(
-                    psChild, bGetSecondaryGeometryOption,
+                    psChild, nPseudoBoolGetSecondaryGeometryOption,
                     nRecLevel + 1, nSRSDimension, pszSRSName );
                 if( poGeom == NULL ||
                     !OGR_GT_IsCurve(poGeom->getGeometryType()) )
@@ -2388,7 +2378,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                 }
 
                 if( wkbFlatten(poGeom->getGeometryType()) != wkbLineString )
-                    bChildrenAreAllLineString = FALSE;
+                    bChildrenAreAllLineString = false;
 
                 if( poCC == NULL && poCurve == NULL )
                     poCurve = (OGRCurve*)poGeom;
@@ -2445,9 +2435,9 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         OGRGeometryCollection *poGC = new OGRGeometryCollection();
 
         // collect geoms
-        for( psChild = psNode->psChild; 
+        for( psChild = psNode->psChild;
              psChild != NULL;
-             psChild = psChild->psNext ) 
+             psChild = psChild->psNext )
         {
             if( psChild->eType == CXT_Element
                 && EQUAL(BareGMLElement(psChild->pszValue),"geometryMember") )
@@ -2458,11 +2448,11 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                 if (psGeometryChild != NULL)
                 {
                     poGeom = GML2OGRGeometry_XMLNode_Internal(
-                        psGeometryChild, bGetSecondaryGeometryOption,
+                        psGeometryChild, nPseudoBoolGetSecondaryGeometryOption,
                         nRecLevel + 1, nSRSDimension, pszSRSName );
                     if( poGeom == NULL )
                     {
-                        CPLError( CE_Failure, CPLE_AppDefined, 
+                        CPLError( CE_Failure, CPLE_AppDefined,
                                 "GeometryCollection: Failed to get geometry in geometryMember" );
                         delete poGeom;
                         delete poGC;
@@ -2489,20 +2479,20 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                          *psPoint,
                          *psCurveProperty,
                          *psCurve;
-        int               bEdgeOrientation = TRUE,
-                          bNodeOrientation = TRUE;
+        bool              bEdgeOrientation = true;
+        bool              bNodeOrientation = true;
         OGRGeometry      *poGeom;
         OGRLineString    *poLineString;
         OGRPoint         *poPositiveNode = NULL, *poNegativeNode = NULL;
         OGRMultiPoint    *poMP;
-    
+
         bEdgeOrientation = GetElementOrientation(psNode);
 
         //collect edge
         psEdge = FindBareXMLChild(psNode,"Edge");
         if( psEdge == NULL )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Failed to get Edge element in directedEdge" );
             return NULL;
         }
@@ -2528,12 +2518,12 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             if( psPoint == NULL ) goto nonode;
 
             poGeom = GML2OGRGeometry_XMLNode_Internal(
-                psPoint, bGetSecondaryGeometryOption,
-                nRecLevel + 1, nSRSDimension, pszSRSName, TRUE );
+                psPoint, nPseudoBoolGetSecondaryGeometryOption,
+                nRecLevel + 1, nSRSDimension, pszSRSName, true );
             if( poGeom == NULL
                 || wkbFlatten(poGeom->getGeometryType()) != wkbPoint )
             {
-/*                CPLError( CE_Failure, CPLE_AppDefined, 
+/*                CPLError( CE_Failure, CPLE_AppDefined,
                       "Got %.500s geometry as Member instead of POINT.",
                       poGeom ? poGeom->getGeometryName() : "NULL" );*/
                 if( poGeom != NULL) delete poGeom;
@@ -2569,12 +2559,12 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             if( psPoint == NULL ) goto nonode;
 
             poGeom = GML2OGRGeometry_XMLNode_Internal(
-                psPoint, bGetSecondaryGeometryOption,
-                nRecLevel + 1, nSRSDimension, pszSRSName, TRUE );
+                psPoint, nPseudoBoolGetSecondaryGeometryOption,
+                nRecLevel + 1, nSRSDimension, pszSRSName, true );
             if( poGeom == NULL
                 || wkbFlatten(poGeom->getGeometryType()) != wkbPoint )
             {
-/*                CPLError( CE_Failure, CPLE_AppDefined, 
+/*                CPLError( CE_Failure, CPLE_AppDefined,
                       "Got %.500s geometry as Member instead of POINT.",
                       poGeom ? poGeom->getGeometryName() : "NULL" );*/
                 if( poGeom != NULL) delete poGeom;
@@ -2589,7 +2579,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             poMP = new OGRMultiPoint();
             poMP->addGeometryDirectly( poNegativeNode );
             poMP->addGeometryDirectly( poPositiveNode );
-            
+
             return poMP;
 
             nonode:;
@@ -2599,7 +2589,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         psCurveProperty = FindBareXMLChild(psEdge,"curveProperty");
         if( psCurveProperty == NULL )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                         "directedEdge: Failed to get curveProperty in Edge" );
             return NULL;
         }
@@ -2609,24 +2599,24 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             psCurve = FindBareXMLChild(psCurveProperty,"Curve");
         if( psCurve == NULL )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "directedEdge: Failed to get LineString or Curve tag in curveProperty" );
             return NULL;
         }
 
-        poLineString = (OGRLineString *)GML2OGRGeometry_XMLNode_Internal(
-            psCurve, bGetSecondaryGeometryOption,
-            nRecLevel + 1, nSRSDimension, pszSRSName, TRUE );
-        if( poLineString == NULL 
-            || wkbFlatten(poLineString->getGeometryType()) != wkbLineString )
+        OGRGeometry* poLineStringBeforeCast = GML2OGRGeometry_XMLNode_Internal(
+            psCurve, nPseudoBoolGetSecondaryGeometryOption,
+            nRecLevel + 1, nSRSDimension, pszSRSName, true );
+        if( poLineStringBeforeCast == NULL
+            || wkbFlatten(poLineStringBeforeCast->getGeometryType()) != wkbLineString )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Got %.500s geometry as Member instead of LINESTRING.",
-                      poLineString ? poLineString->getGeometryName() : "NULL" );
-            if( poLineString != NULL )
-                delete poLineString;
+                      poLineStringBeforeCast ? poLineStringBeforeCast->getGeometryName() : "NULL" );
+            delete poLineStringBeforeCast;
             return NULL;
         }
+        poLineString = (OGRLineString *)poLineStringBeforeCast;
 
         if( bGetSecondaryGeometry )
         {
@@ -2688,9 +2678,9 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             poMLS = new OGRMultiLineString();
 
         // collect directedEdges
-        for( psChild = psNode->psChild; 
+        for( psChild = psNode->psChild;
              psChild != NULL;
-             psChild = psChild->psNext ) 
+             psChild = psChild->psNext )
         {
             if( psChild->eType == CXT_Element
                 && EQUAL(BareGMLElement(psChild->pszValue),"directedEdge"))
@@ -2698,11 +2688,11 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                 OGRGeometry *poGeom;
 
                 poGeom = GML2OGRGeometry_XMLNode_Internal(
-                    psChild, bGetSecondaryGeometryOption,
+                    psChild, nPseudoBoolGetSecondaryGeometryOption,
                     nRecLevel + 1, nSRSDimension, pszSRSName );
                 if( poGeom == NULL )
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined, 
+                    CPLError( CE_Failure, CPLE_AppDefined,
                               "Failed to get geometry in directedEdge" );
                     delete poGeom;
                     if( bGetSecondaryGeometry )
@@ -2735,7 +2725,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                 }
                 else
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined, 
+                    CPLError( CE_Failure, CPLE_AppDefined,
                               "Got %.500s geometry as Member instead of %s.",
                               poGeom ? poGeom->getGeometryName() : "NULL",
                               bGetSecondaryGeometry?"MULTIPOINT":"LINESTRING");
@@ -2761,7 +2751,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
     if( EQUAL(pszBaseGeometry,"TopoSurface") )
     {
         /****************************************************************/
-        /* applying the FaceHoleNegative = FALSE rules                  */
+        /* applying the FaceHoleNegative = false rules                  */
         /*                                                              */
         /* - each <TopoSurface> is expected to represent a MultiPolygon */
         /* - each <Face> is expected to represent a distinct Polygon,   */
@@ -2769,20 +2759,20 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         /*   orientation="+/-" plays no role at all to identify "holes" */
         /* - each <Edge> within a <Face> may indifferently represent    */
         /*   an element of the Exterior or Interior Boundary; relative  */
-        /*   order of <Egdes> is absolutely irrelevant.                 */
+        /*   order of <Edges> is absolutely irrelevant.                 */
         /****************************************************************/
         /* Contributor: Alessandro Furieri, a.furieri at lqt.it            */
         /* Developed for Faunalia (http://www.faunalia.it)              */
         /* with funding from Regione Toscana -                          */
         /* Settore SISTEMA INFORMATIVO TERRITORIALE ED AMBIENTALE       */
         /****************************************************************/
-        if(bFaceHoleNegative != TRUE)
+        if( !bFaceHoleNegative )
         {
             if( bGetSecondaryGeometry )
                 return NULL;
 
 #ifndef HAVE_GEOS
-            static int bWarningAlreadyEmitted = FALSE;
+            static bool bWarningAlreadyEmitted = false;
             if (!bWarningAlreadyEmitted)
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
@@ -2790,7 +2780,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                         "As a workaround, you can try defining the GML_FACE_HOLE_NEGATIVE configuration option\n"
                         "to YES, so that the 'old' interpretation algorithm is used. But be warned that\n"
                         "the result might be incorrect.\n");
-                bWarningAlreadyEmitted = TRUE;
+                bWarningAlreadyEmitted = true;
             }
             return NULL;
 #else
@@ -2798,16 +2788,16 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             OGRMultiPolygon *poTS = new OGRMultiPolygon();
 
             // collect directed faces
-            for( psChild = psNode->psChild; 
+            for( psChild = psNode->psChild;
                 psChild != NULL;
-            psChild = psChild->psNext ) 
+            psChild = psChild->psNext )
             {
               if( psChild->eType == CXT_Element
               && EQUAL(BareGMLElement(psChild->pszValue),"directedFace") )
               {
                 // collect next face (psChild->psChild)
                 psFaceChild = GetChildElement(psChild);
-	
+
                 while( psFaceChild != NULL &&
                        !(psFaceChild->eType == CXT_Element &&
                          EQUAL(BareGMLElement(psFaceChild->pszValue),"Face")) )
@@ -2829,16 +2819,16 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                     OGRGeometry *poEdgeGeom;
 
                     poEdgeGeom = GML2OGRGeometry_XMLNode_Internal( psDirectedEdgeChild,
-                                                          bGetSecondaryGeometryOption,
+                                                          nPseudoBoolGetSecondaryGeometryOption,
                                                           nRecLevel + 1,
                                                           nSRSDimension,
                                                           pszSRSName,
-                                                          TRUE );
+                                                          true );
 
                     if( poEdgeGeom == NULL ||
                         wkbFlatten(poEdgeGeom->getGeometryType()) != wkbLineString )
                     {
-                      CPLError( CE_Failure, CPLE_AppDefined, 
+                      CPLError( CE_Failure, CPLE_AppDefined,
                                 "Failed to get geometry in directedEdge" );
                       delete poEdgeGeom;
                       delete poCollectedGeom;
@@ -2857,7 +2847,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                 poFaceCollectionGeom = poCollectedGeom->Polygonize();
                 if( poFaceCollectionGeom == NULL )
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined, 
+                    CPLError( CE_Failure, CPLE_AppDefined,
                               "Failed to assemble Edges in Face" );
                     delete poCollectedGeom;
                     delete poTS;
@@ -2926,7 +2916,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         }
 
         /****************************************************************/
-        /* applying the FaceHoleNegative = TRUE rules                   */
+        /* applying the FaceHoleNegative = true rules                   */
         /*                                                              */
         /* - each <TopoSurface> is expected to represent a MultiPolygon */
         /* - any <Face> declaring orientation="+" is expected to        */
@@ -2934,20 +2924,20 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         /* - any <Face> declaring orientation="-" is expected to        */
         /*   represent an Interior Ring (hole) belonging to the latest  */
         /*   Exterior Ring.                                             */
-        /* - <Egdes> within the same <Face> are expected to be          */
+        /* - <Edges> within the same <Face> are expected to be          */
         /*   arranged in geometrically adjacent and consecutive         */
         /*   sequence.                                                  */
         /****************************************************************/
         if( bGetSecondaryGeometry )
             return NULL;
         const CPLXMLNode *psChild, *psFaceChild, *psDirectedEdgeChild;
-        int bFaceOrientation = TRUE;
+        bool bFaceOrientation = true;
         OGRPolygon *poTS = new OGRPolygon();
 
         // collect directed faces
-        for( psChild = psNode->psChild; 
+        for( psChild = psNode->psChild;
              psChild != NULL;
-             psChild = psChild->psNext ) 
+             psChild = psChild->psNext )
         {
           if( psChild->eType == CXT_Element
               && EQUAL(BareGMLElement(psChild->pszValue),"directedFace") )
@@ -2976,17 +2966,17 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                 OGRGeometry *poEdgeGeom;
 
                 poEdgeGeom = GML2OGRGeometry_XMLNode_Internal( psDirectedEdgeChild,
-                                                      bGetSecondaryGeometryOption,
+                                                      nPseudoBoolGetSecondaryGeometryOption,
                                                       nRecLevel + 1,
                                                       nSRSDimension,
                                                       pszSRSName,
-                                                      TRUE,
+                                                      true,
                                                       bFaceOrientation );
 
                 if( poEdgeGeom == NULL ||
                     wkbFlatten(poEdgeGeom->getGeometryType()) != wkbLineString )
                 {
-                  CPLError( CE_Failure, CPLE_AppDefined, 
+                  CPLError( CE_Failure, CPLE_AppDefined,
                             "Failed to get geometry in directedEdge" );
                   delete poEdgeGeom;
                   delete poFaceGeom;
@@ -3010,7 +3000,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                       && fabs(poLS->getY(poLS->getNumPoints()-1)
                               - poAddLS->getY(0)) < 1e-14
                       && fabs(poLS->getZ(poLS->getNumPoints()-1)
-                              - poAddLS->getZ(0)) < 1e-14) 
+                              - poAddLS->getZ(0)) < 1e-14)
                   {
                       // Skip the first point of the new linestring to avoid
                       // invalidate duplicate points
@@ -3035,7 +3025,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                     && fabs(poLS->getY(poLS->getNumPoints()-1)
                             - poAddLS->getY(0)) < 1e-14
                     && fabs(poLS->getZ(poLS->getNumPoints()-1)
-                            - poAddLS->getZ(0)) < 1e-14) 
+                            - poAddLS->getZ(0)) < 1e-14)
                 {
                     // Skip the first point of the new linestring to avoid
                     // invalidate duplicate points
@@ -3052,7 +3042,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 
 /*            if( poFaceGeom == NULL )
             {
-              CPLError( CE_Failure, CPLE_AppDefined, 
+              CPLError( CE_Failure, CPLE_AppDefined,
                         "Failed to get Face geometry in directedFace" );
               delete poFaceGeom;
               return NULL;
@@ -3064,7 +3054,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 
 /*        if( poTS == NULL )
         {
-          CPLError( CE_Failure, CPLE_AppDefined, 
+          CPLError( CE_Failure, CPLE_AppDefined,
                     "Failed to get TopoSurface geometry" );
           delete poTS;
           return NULL;
@@ -3105,7 +3095,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             {
                 OGRGeometry *poGeom =
                     GML2OGRGeometry_XMLNode_Internal(
-                        psChild, bGetSecondaryGeometryOption,
+                        psChild, nPseudoBoolGetSecondaryGeometryOption,
                         nRecLevel + 1, nSRSDimension, pszSRSName );
                 if( poGeom == NULL )
                 {
@@ -3178,9 +3168,9 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             if( psChild->eType == CXT_Element
                 && EQUAL(BareGMLElement(psChild->pszValue),"Triangle") )
             {
-                OGRPolygon *poPolygon = (OGRPolygon *)
+                OGRGeometry *poPolygon =
                     GML2OGRGeometry_XMLNode_Internal(
-                        psChild, bGetSecondaryGeometryOption,
+                        psChild, nPseudoBoolGetSecondaryGeometryOption,
                         nRecLevel + 1, nSRSDimension, pszSRSName );
                 if( poPolygon == NULL )
                     return NULL;
@@ -3224,7 +3214,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 
         // Get the geometry inside <exterior>
         poGeom = GML2OGRGeometry_XMLNode_Internal(
-            psChild, bGetSecondaryGeometryOption,
+            psChild, nPseudoBoolGetSecondaryGeometryOption,
             nRecLevel + 1, nSRSDimension, pszSRSName );
         if( poGeom == NULL )
         {
@@ -3236,12 +3226,12 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         psChild = FindBareXMLChild( psNode, "interior");
         if( psChild != NULL )
         {
-            static int bWarnedOnce = FALSE;
+            static bool bWarnedOnce = false;
             if (!bWarnedOnce)
             {
                 CPLError( CE_Warning, CPLE_AppDefined,
                           "<interior> elements of <Solid> are ignored");
-                bWarnedOnce = TRUE;
+                bWarnedOnce = true;
             }
         }
 
@@ -3267,7 +3257,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         }
 
         return GML2OGRGeometry_XMLNode_Internal(
-            psChild, bGetSecondaryGeometryOption,
+            psChild, nPseudoBoolGetSecondaryGeometryOption,
             nRecLevel + 1, nSRSDimension, pszSRSName );
     }
 
@@ -3319,8 +3309,8 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         return poMP;
     }
 
-    CPLError( CE_Failure, CPLE_AppDefined, 
-              "Unrecognised geometry type <%.500s>.", 
+    CPLError( CE_Failure, CPLE_AppDefined,
+              "Unrecognized geometry type <%.500s>.",
               pszBaseGeometry );
 
     return NULL;
@@ -3364,7 +3354,7 @@ OGRGeometryH OGR_G_CreateFromGMLTree( const CPLXMLNode *psTree )
  *
  * @param pszGML The GML fragment for the geometry.
  *
- * @return a geometry on succes, or NULL on error.
+ * @return a geometry on success, or NULL on error.
  */
 
 OGRGeometryH OGR_G_CreateFromGML( const char *pszGML )
@@ -3372,7 +3362,7 @@ OGRGeometryH OGR_G_CreateFromGML( const char *pszGML )
 {
     if( pszGML == NULL || strlen(pszGML) == 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "GML Geometry is empty in OGR_G_CreateFromGML()." );
         return NULL;
     }
@@ -3393,12 +3383,10 @@ OGRGeometryH OGR_G_CreateFromGML( const char *pszGML )
     OGRGeometry *poGeometry;
 
     /* Must be in synced in OGR_G_CreateFromGML(), OGRGMLLayer::OGRGMLLayer() and GMLReader::GMLReader() */
-    int bFaceHoleNegative = CSLTestBoolean(CPLGetConfigOption("GML_FACE_HOLE_NEGATIVE", "NO"));
-    poGeometry = GML2OGRGeometry_XMLNode( psGML, -1, 0, 0, FALSE, TRUE, bFaceHoleNegative );
+    bool bFaceHoleNegative = CPLTestBool(CPLGetConfigOption("GML_FACE_HOLE_NEGATIVE", "NO"));
+    poGeometry = GML2OGRGeometry_XMLNode( psGML, -1, 0, 0, false, true, bFaceHoleNegative );
 
     CPLDestroyXMLNode( psGML );
-    
+
     return (OGRGeometryH) poGeometry;
 }
-
-
diff --git a/ogr/index.dox b/ogr/index.dox
deleted file mode 100644
index 6705509..0000000
--- a/ogr/index.dox
+++ /dev/null
@@ -1,114 +0,0 @@
-/*! \mainpage OGR Simple Feature Library
-
-The OGR Simple Features Library is a C++ 
-<a href="http://www.opensource.org/">open source</a> library (and commandline 
-tools) providing read (and sometimes write) access to a variety of vector file 
-formats including ESRI Shapefiles, S-57, SDTS, PostGIS, Oracle Spatial, 
-and Mapinfo mid/mif and TAB formats.<p>
-
-OGR is a part of the <a href="http://www.gdal.org/">GDAL</a> library.<p>
-
-<h2>Resources</h2>
-
-<ul>
-
-<li> <a href="ogr_formats.html">OGR Supported Formats</a> : ESRI Shapefile, ESRI ArcSDE, MapInfo (tab and mid/mif), GML, KML, PostGIS, Oracle Spatial, ...
-
-<li> <a href="../ogr_utilities.html">OGR Utility Programs</a> : ogrinfo, ogr2ogr, ogrtindex
-
-<li> <a href="hierarchy.html">OGR Class Documentation</a>
-
-<li> <a href="ogr_apitut.html">OGR C++ API Read/Write Tutorial</a>
-
-<li> <a href="ogr_drivertut.html">OGR Driver Implementation Tutorial</a>
-
-<li> <a href="ogr__api_8h.html">ogr_api.h</a>: OGR C API
-
-<li> <a href="ogr__srs__api_8h.html">ogr_srs_api.h</a>: OSR C API
-
-<li> <a href="osr_tutorial.html">OGR Projections Tutorial</a>
-
-<li> <a href="ogr_arch.html">OGR Architecture</a>
-
-<li> <a href="ogr_sql.html">OGR SQL</a> dialect and <a href="ogr_sql_sqlite.html">SQLITE SQL</a> dialect
-
-<li> <a href="ogr_feature_style.html">OGR - Feature Style Specification</a>
-
-<!-- sfc_tutorial.dox lives now under spike/sfcom_oledb/client, so the html page
-is no longer generated
-<li> <a href="sfc_tutorial.html">SFC (OLE DB client side API) 
-Tutorial</a>
--->
-
-<li> <a href="http://home.gdal.org/projects/opengis/twohalfdsf.html">Adam's 2.5 D Simple Features Proposal (OGC 99-402r2)</a>
-
-<li> Adam's SRS WKT Clarification Proposal in <a href="http://home.gdal.org/projects/opengis/wkt_prop.html">html</a>
-or <a href="http://home.gdal.org/projects/opengis/wkt_prop.doc">doc</a> format.
-
-</ul>
-
-<h2>Download</h2>
-
-<h3>Ready to Use Executables</h3>
-
-The best way to get OGR <a href="ogr_utilities.html">utilities</a>
-in ready-to-use form is to download the latest 
-<a href="http://fwtools.maptools.org/">FWTools</a> kit
-for your platform.  While large, these include builds of the OGR utilities
-with lots of optional components built-in.  Once downloaded follow the 
-included instructions to setup your path and other environment variables
-correctly, and then you can use the various OGR utilities from the command 
-line.  The kits also include <a href="http://openev.sf.net/">OpenEV</a>, 
-a viewer that will display OGR supported vector files.<p>
-
-<h3>Source</h3>
-
-The source code for this effort is intended to be available as OpenSource
-using an X Consortium style license.  The OGR library is currently a 
-loosely coupled subcomponent of the 
-<a href="http://www.gdal.org/">GDAL</a> library, so you get all
-of GDAL for the "price" of OGR.  
-See the GDAL <a href="http://www.gdal.org/download.html">Download</a> and
-<a href="http://www.gdal.org/gdal_building.html">Building</a> pages for 
-details on getting the source and building it. <p>
-
-<h2>Bug Reporting</h2>
-
-GDAL/OGR bugs 
-<a href="http://trac.osgeo.org/gdal">can be reported</a>, and 
-<a href="http://trac.osgeo.org/gdal/report/1?sort=ticket&asc=0">can be 
-listed</a> using Trac.<p>
-
-<h2>Mailing Lists</h2>
-
-A gdal-announce mailing list <a href="http://lists.osgeo.org/mailman/listinfo/gdal-announce">subscription</a> is a low volume way of keeping track of major
-developments with the GDAL/OGR project.
-
-The <a href="mailto:gdal-dev at lists.osgeo.org">gdal-dev at lists.osgeo.org</a> 
-mailing list can be used for discussion of development and user issues related 
-to OGR and related technologies. Subscriptions can be done, and archives 
-reviewed <a href="http://lists.osgeo.org/mailman/listinfo/gdal-dev/">on
-the web</a>.<p>
-
-<h2>Alternative Bindings for the OGR API</h2>
-
-In addition to the C++ API primarily addressed in the online documentation,
-there is also a slightly less complete C API implemented on top of the C++
-API, and access available from Python.<p>
-
-The C API is primarily intended to provide a less fragile API since slight
-changes in the C++ API (such as const correctness changes) can cause changes
-in method and class signatures that prevent use of new DLLs with older clients.
-The C API is also generally easy to call from other languages which allow call
-out to DLLs functions, such as Visual Basic, or Delphi. The API can be
-explored in the <a href="ogr__api_8h.html">ogr_api.h</a> include file.  
-The gdal/ogr/ogr_capi_test.c is a small sample program demonstrating use
-of the C API.<p>
-
-The Python API isn't really well documented at this time, but parallels the
-C/C++ APIs.  The interface classes can be browsed in the pymod/ogr.py
-(simple features) and pymod/osr.py
-(coordinate systems) python modules.  The pymod/samples/assemblepoly.py
-sample script is one demonstration of using the python API.<p>
-
-*/
diff --git a/ogr/makefile.vc b/ogr/makefile.vc
index 746e588..dcfa4df 100644
--- a/ogr/makefile.vc
+++ b/ogr/makefile.vc
@@ -66,9 +66,3 @@ allclean:	clean
 	cd ogrsf_frmts
 	$(MAKE) /f makefile.vc clean
 	cd ..
-
-# special override to avoid some warnings with this generated code.
-
-swq_parser.obj:	swq_parser.cpp
-	$(CC) $(CFLAGS) $(SOFTWARNFLAGS) /c $*.cpp
-
diff --git a/ogr/ogr2gmlgeometry.cpp b/ogr/ogr2gmlgeometry.cpp
index b1304a9..77f7db3 100644
--- a/ogr/ogr2gmlgeometry.cpp
+++ b/ogr/ogr2gmlgeometry.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr2gmlgeometry.cpp 27959 2014-11-14 18:29:21Z rouault $
+ * $Id: ogr2gmlgeometry.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  GML Translator
  * Purpose:  Code to translate OGRGeometry to GML string representation.
@@ -15,16 +15,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************
  *
@@ -33,19 +33,19 @@
  *   overflows and stack corruptions if caller could be trusted.
  *
  * Security Audit 2003/03/28 warmerda:
- *   Completed security audit.  I believe that this module may be safely used 
+ *   Completed security audit.  I believe that this module may be safely used
  *   to generate GML from arbitrary but well formed OGRGeomety objects that
  *   come from a potentially hostile source, but through a trusted OGR importer
  *   without compromising the system.
  *
  */
 
+#include "cpl_error.h"
+#include "cpl_conv.h"
 #include "cpl_minixml.h"
-#include "ogr_geometry.h"
 #include "ogr_api.h"
+#include "ogr_geometry.h"
 #include "ogr_p.h"
-#include "cpl_error.h"
-#include "cpl_conv.h"
 
 #define SRSDIM_LOC_GEOMETRY (1 << 0)
 #define SRSDIM_LOC_POSLIST  (1 << 1)
@@ -54,8 +54,8 @@
 /*                        MakeGMLCoordinate()                           */
 /************************************************************************/
 
-static void MakeGMLCoordinate( char *pszTarget, 
-                               double x, double y, double z, int b3D )
+static void MakeGMLCoordinate( char *pszTarget,
+                               double x, double y, double z, bool b3D )
 
 {
     OGRMakeWktCoordinate( pszTarget, x, y, z, b3D ? 3 : 2 );
@@ -84,7 +84,7 @@ static void MakeGMLCoordinate( char *pszTarget,
             sprintf( pszTarget, "%d,%d,%d", (int) x, (int) y, (int) z );
         else if( fabs(x) < 370 && fabs(y) < 370 )
             CPLsprintf( pszTarget, "%.16g,%.16g,%.16g", x, y, z );
-        else if( fabs(x) > 100000000.0 || fabs(y) > 100000000.0 
+        else if( fabs(x) > 100000000.0 || fabs(y) > 100000000.0
                  || fabs(z) > 100000000.0 )
             CPLsprintf( pszTarget, "%.16g,%.16g,%.16g", x, y, z );
         else
@@ -97,7 +97,7 @@ static void MakeGMLCoordinate( char *pszTarget,
 /*                            _GrowBuffer()                             */
 /************************************************************************/
 
-static void _GrowBuffer( int nNeeded, char **ppszText, int *pnMaxLength )
+static void _GrowBuffer( size_t nNeeded, char **ppszText, size_t *pnMaxLength )
 
 {
     if( nNeeded+1 >= *pnMaxLength )
@@ -111,11 +111,11 @@ static void _GrowBuffer( int nNeeded, char **ppszText, int *pnMaxLength )
 /*                            AppendString()                            */
 /************************************************************************/
 
-static void AppendString( char **ppszText, int *pnLength, int *pnMaxLength,
+static void AppendString( char **ppszText, size_t *pnLength, size_t *pnMaxLength,
                           const char *pszTextToAppend )
 
 {
-    _GrowBuffer( *pnLength + strlen(pszTextToAppend) + 1, 
+    _GrowBuffer( *pnLength + strlen(pszTextToAppend) + 1,
                  ppszText, pnMaxLength );
 
     strcat( *ppszText + *pnLength, pszTextToAppend );
@@ -127,13 +127,13 @@ static void AppendString( char **ppszText, int *pnLength, int *pnMaxLength,
 /*                        AppendCoordinateList()                        */
 /************************************************************************/
 
-static void AppendCoordinateList( OGRLineString *poLine, 
-                                  char **ppszText, int *pnLength, 
-                                  int *pnMaxLength )
+static void AppendCoordinateList( OGRLineString *poLine,
+                                  char **ppszText, size_t *pnLength,
+                                  size_t *pnMaxLength )
 
 {
     char        szCoordinate[256];
-    int         b3D = wkbHasZ(poLine->getGeometryType());
+    bool        b3D = wkbHasZ(poLine->getGeometryType()) != FALSE;
 
     *pnLength += strlen(*ppszText + *pnLength);
     _GrowBuffer( *pnLength + 20, ppszText, pnMaxLength );
@@ -141,24 +141,23 @@ static void AppendCoordinateList( OGRLineString *poLine,
     strcat( *ppszText + *pnLength, "<gml:coordinates>" );
     *pnLength += strlen(*ppszText + *pnLength);
 
-    
     for( int iPoint = 0; iPoint < poLine->getNumPoints(); iPoint++ )
     {
-        MakeGMLCoordinate( szCoordinate, 
+        MakeGMLCoordinate( szCoordinate,
                            poLine->getX(iPoint),
                            poLine->getY(iPoint),
                            poLine->getZ(iPoint),
                            b3D );
-        _GrowBuffer( *pnLength + strlen(szCoordinate)+1, 
+        _GrowBuffer( *pnLength + strlen(szCoordinate)+1,
                      ppszText, pnMaxLength );
 
         if( iPoint != 0 )
             strcat( *ppszText + *pnLength, " " );
-            
+
         strcat( *ppszText + *pnLength, szCoordinate );
         *pnLength += strlen(*ppszText + *pnLength);
     }
-    
+
     _GrowBuffer( *pnLength + 20, ppszText, pnMaxLength );
     strcat( *ppszText + *pnLength, "</gml:coordinates>" );
     *pnLength += strlen(*ppszText + *pnLength);
@@ -168,10 +167,11 @@ static void AppendCoordinateList( OGRLineString *poLine,
 /*                       OGR2GMLGeometryAppend()                        */
 /************************************************************************/
 
-static int OGR2GMLGeometryAppend( OGRGeometry *poGeometry, 
-                                  char **ppszText, int *pnLength, 
-                                  int *pnMaxLength,
-                                  int bIsSubGeometry )
+static bool OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
+                                   char **ppszText, size_t *pnLength,
+                                   size_t *pnMaxLength,
+                                   bool bIsSubGeometry,
+                                   const char* pszNamespaceDecl )
 
 {
 
@@ -179,13 +179,25 @@ static int OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
 /*      Check for Spatial Reference System attached to given geometry   */
 /* -------------------------------------------------------------------- */
 
-    // Buffer for srsName attribute (srsName="...")
-    char szAttributes[30] = { 0 };
-    int nAttrsLength = 0;
+    // Buffer for xmlns:gml and srsName attributes (srsName="...")
+    char szAttributes[64] = { 0 };
+    size_t nAttrsLength = 0;
+
+    szAttributes[0] = 0;
 
     const OGRSpatialReference* poSRS = NULL;
     poSRS = poGeometry->getSpatialReference();
 
+    if( pszNamespaceDecl != NULL )
+    {
+        snprintf( szAttributes + nAttrsLength,
+                  sizeof(szAttributes) - nAttrsLength,
+                  " xmlns:gml=\"%s\"",
+                  pszNamespaceDecl );
+        nAttrsLength += strlen(szAttributes + nAttrsLength);
+        pszNamespaceDecl = NULL;
+    }
+
     if( NULL != poSRS && !bIsSubGeometry )
     {
         const char* pszAuthName = NULL;
@@ -205,10 +217,12 @@ static int OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
                 pszAuthCode = poSRS->GetAuthorityCode( pszTarget );
                 if( NULL != pszAuthCode && strlen(pszAuthCode) < 10 )
                 {
-                    sprintf( szAttributes, " srsName=\"%s:%s\"",
-                            pszAuthName, pszAuthCode );
+                    snprintf( szAttributes + nAttrsLength,
+                              sizeof(szAttributes) - nAttrsLength,
+                              " srsName=\"%s:%s\"",
+                              pszAuthName, pszAuthCode );
 
-                    nAttrsLength = strlen(szAttributes);
+                    nAttrsLength += strlen(szAttributes + nAttrsLength);
                 }
             }
         }
@@ -225,13 +239,13 @@ static int OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
         char    szCoordinate[256];
         OGRPoint *poPoint = (OGRPoint *) poGeometry;
 
-        MakeGMLCoordinate( szCoordinate, 
-                           poPoint->getX(), poPoint->getY(), 0.0, FALSE );
+        MakeGMLCoordinate( szCoordinate,
+                           poPoint->getX(), poPoint->getY(), 0.0, false );
 
         _GrowBuffer( *pnLength + strlen(szCoordinate) + 60 + nAttrsLength,
                      ppszText, pnMaxLength );
 
-        sprintf( *ppszText + *pnLength, 
+        snprintf( *ppszText + *pnLength, *pnMaxLength -  *pnLength,
                 "<gml:Point%s><gml:coordinates>%s</gml:coordinates></gml:Point>",
                  szAttributes, szCoordinate );
 
@@ -245,14 +259,14 @@ static int OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
         char    szCoordinate[256];
         OGRPoint *poPoint = (OGRPoint *) poGeometry;
 
-        MakeGMLCoordinate( szCoordinate, 
-                           poPoint->getX(), poPoint->getY(), poPoint->getZ(), 
-                           TRUE );
-                           
+        MakeGMLCoordinate( szCoordinate,
+                           poPoint->getX(), poPoint->getY(), poPoint->getZ(),
+                           true );
+
         _GrowBuffer( *pnLength + strlen(szCoordinate) + 70 + nAttrsLength,
                      ppszText, pnMaxLength );
 
-        sprintf( *ppszText + *pnLength, 
+        snprintf( *ppszText + *pnLength, *pnMaxLength -  *pnLength,
                 "<gml:Point%s><gml:coordinates>%s</gml:coordinates></gml:Point>",
                  szAttributes, szCoordinate );
 
@@ -264,23 +278,24 @@ static int OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
 /* -------------------------------------------------------------------- */
     else if( eFType == wkbLineString )
     {
-        int bRing = EQUAL(poGeometry->getGeometryName(),"LINEARRING");
+        bool bRing = EQUAL(poGeometry->getGeometryName(),"LINEARRING");
 
         // Buffer for tag name + srsName attribute if set
         const size_t nLineTagLength = 16;
         char* pszLineTagName = NULL;
-        pszLineTagName = (char *) CPLMalloc( nLineTagLength + nAttrsLength + 1 );
+        const size_t nLineTagNameBufLen = nLineTagLength + nAttrsLength + 1;
+        pszLineTagName = (char *) CPLMalloc( nLineTagNameBufLen );
 
         if( bRing )
         {
-            sprintf( pszLineTagName, "<gml:LinearRing%s>", szAttributes );
+            snprintf( pszLineTagName, nLineTagNameBufLen, "<gml:LinearRing%s>", szAttributes );
 
             AppendString( ppszText, pnLength, pnMaxLength,
                           pszLineTagName );
         }
         else
         {
-            sprintf( pszLineTagName, "<gml:LineString%s>", szAttributes );
+            snprintf( pszLineTagName, nLineTagNameBufLen, "<gml:LineString%s>", szAttributes );
 
             AppendString( ppszText, pnLength, pnMaxLength,
                           pszLineTagName );
@@ -289,9 +304,9 @@ static int OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
         // FREE TAG BUFFER
         CPLFree( pszLineTagName );
 
-        AppendCoordinateList( (OGRLineString *) poGeometry, 
+        AppendCoordinateList( (OGRLineString *) poGeometry,
                               ppszText, pnLength, pnMaxLength );
-        
+
         if( bRing )
             AppendString( ppszText, pnLength, pnMaxLength,
                           "</gml:LinearRing>" );
@@ -310,10 +325,11 @@ static int OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
         // Buffer for polygon tag name + srsName attribute if set
         const size_t nPolyTagLength = 13;
         char* pszPolyTagName = NULL;
-        pszPolyTagName = (char *) CPLMalloc( nPolyTagLength + nAttrsLength + 1 );
+        const size_t nPolyTagNameBufLen = nPolyTagLength + nAttrsLength + 1;
+        pszPolyTagName = (char *) CPLMalloc( nPolyTagNameBufLen );
 
         // Compose Polygon tag with or without srsName attribute
-        sprintf( pszPolyTagName, "<gml:Polygon%s>", szAttributes );
+        snprintf( pszPolyTagName, nPolyTagNameBufLen, "<gml:Polygon%s>", szAttributes );
 
         AppendString( ppszText, pnLength, pnMaxLength,
                       pszPolyTagName );
@@ -328,13 +344,13 @@ static int OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
             AppendString( ppszText, pnLength, pnMaxLength,
                           "<gml:outerBoundaryIs>" );
 
-            if( !OGR2GMLGeometryAppend( poPolygon->getExteriorRing(), 
+            if( !OGR2GMLGeometryAppend( poPolygon->getExteriorRing(),
                                         ppszText, pnLength, pnMaxLength,
-                                        TRUE ) )
+                                        true, NULL ) )
             {
-                return FALSE;
+                return false;
             }
-            
+
             AppendString( ppszText, pnLength, pnMaxLength,
                           "</gml:outerBoundaryIs>" );
         }
@@ -345,11 +361,11 @@ static int OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
 
             AppendString( ppszText, pnLength, pnMaxLength,
                           "<gml:innerBoundaryIs>" );
-            
-            if( !OGR2GMLGeometryAppend( poRing, ppszText, pnLength, 
-                                        pnMaxLength, TRUE ) )
-                return FALSE;
-            
+
+            if( !OGR2GMLGeometryAppend( poRing, ppszText, pnLength,
+                                        pnMaxLength, true, NULL ) )
+                return false;
+
             AppendString( ppszText, pnLength, pnMaxLength,
                           "</gml:innerBoundaryIs>" );
         }
@@ -361,7 +377,7 @@ static int OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
 /* -------------------------------------------------------------------- */
 /*      MultiPolygon, MultiLineString, MultiPoint, MultiGeometry        */
 /* -------------------------------------------------------------------- */
-    else if( eFType == wkbMultiPolygon 
+    else if( eFType == wkbMultiPolygon
              || eFType == wkbMultiLineString
              || eFType == wkbMultiPoint
              || eFType == wkbGeometryCollection )
@@ -376,32 +392,36 @@ static int OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
 
         if( eFType == wkbMultiPolygon )
         {
-            pszElemOpen = (char *) CPLMalloc( 13 + nAttrsLength + 1 );
-            sprintf( pszElemOpen, "MultiPolygon%s>", szAttributes );
+            const size_t nBufLen = 13 + nAttrsLength + 1;
+            pszElemOpen = (char *) CPLMalloc( nBufLen );
+            snprintf( pszElemOpen, nBufLen, "MultiPolygon%s>", szAttributes );
 
             pszElemClose = "MultiPolygon>";
             pszMemberElem = "polygonMember>";
         }
         else if( eFType == wkbMultiLineString )
         {
-            pszElemOpen = (char *) CPLMalloc( 16 + nAttrsLength + 1 );
-            sprintf( pszElemOpen, "MultiLineString%s>", szAttributes );
+            const size_t nBufLen = 16 + nAttrsLength + 1;
+            pszElemOpen = (char *) CPLMalloc( nBufLen );
+            snprintf( pszElemOpen, nBufLen, "MultiLineString%s>", szAttributes );
 
             pszElemClose = "MultiLineString>";
             pszMemberElem = "lineStringMember>";
         }
         else if( eFType == wkbMultiPoint )
         {
-            pszElemOpen = (char *) CPLMalloc( 11 + nAttrsLength + 1 );
-            sprintf( pszElemOpen, "MultiPoint%s>", szAttributes );
+            const size_t nBufLen = 11 + nAttrsLength + 1;
+            pszElemOpen = (char *) CPLMalloc( nBufLen );
+            snprintf( pszElemOpen, nBufLen, "MultiPoint%s>", szAttributes );
 
             pszElemClose = "MultiPoint>";
             pszMemberElem = "pointMember>";
         }
         else
         {
-            pszElemOpen = (char *) CPLMalloc( 19 + nAttrsLength + 1 );
-            sprintf( pszElemOpen, "MultiGeometry%s>", szAttributes );
+            const size_t nBufLen = 19 + nAttrsLength + 1;
+            pszElemOpen = (char *) CPLMalloc( nBufLen );
+            snprintf( pszElemOpen, nBufLen, "MultiGeometry%s>", szAttributes );
 
             pszElemClose = "MultiGeometry>";
             pszMemberElem = "geometryMember>";
@@ -416,14 +436,14 @@ static int OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
 
             AppendString( ppszText, pnLength, pnMaxLength, "<gml:" );
             AppendString( ppszText, pnLength, pnMaxLength, pszMemberElem );
-            
-            if( !OGR2GMLGeometryAppend( poMember, 
+
+            if( !OGR2GMLGeometryAppend( poMember,
                                         ppszText, pnLength, pnMaxLength,
-                                        TRUE ) )
+                                        true, NULL ) )
             {
-                return FALSE;
+                return false;
             }
-            
+
             AppendString( ppszText, pnLength, pnMaxLength, "</gml:" );
             AppendString( ppszText, pnLength, pnMaxLength, pszMemberElem );
         }
@@ -438,10 +458,10 @@ static int OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
     {
         CPLError(CE_Failure, CPLE_NotSupported, "Unsupported geometry type %s",
                  OGRGeometryTypeToName(eType));
-        return FALSE;
+        return false;
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -461,7 +481,7 @@ CPLXMLNode *OGR_G_ExportEnvelopeToGMLTree( OGRGeometryH hGeometry )
     memset( &sEnvelope, 0, sizeof(sEnvelope) );
     ((OGRGeometry *) hGeometry)->getEnvelope( &sEnvelope );
 
-    if( sEnvelope.MinX == 0 && sEnvelope.MaxX == 0 
+    if( sEnvelope.MinX == 0 && sEnvelope.MaxX == 0
         && sEnvelope.MaxX == 0 && sEnvelope.MaxY == 0 )
     {
         /* there is apparently a special way of representing a null box
@@ -476,9 +496,9 @@ CPLXMLNode *OGR_G_ExportEnvelopeToGMLTree( OGRGeometryH hGeometry )
 /*      Add minxy coordinate.                                           */
 /* -------------------------------------------------------------------- */
     psCoord = CPLCreateXMLNode( psBox, CXT_Element, "gml:coord" );
-    
-    MakeGMLCoordinate( szCoordinate, sEnvelope.MinX, sEnvelope.MinY, 0.0, 
-                       FALSE );
+
+    MakeGMLCoordinate( szCoordinate, sEnvelope.MinX, sEnvelope.MinY, 0.0,
+                       false );
     pszY = strstr(szCoordinate,",") + 1;
     pszY[-1] = '\0';
 
@@ -489,9 +509,9 @@ CPLXMLNode *OGR_G_ExportEnvelopeToGMLTree( OGRGeometryH hGeometry )
 /*      Add maxxy coordinate.                                           */
 /* -------------------------------------------------------------------- */
     psCoord = CPLCreateXMLNode( psBox, CXT_Element, "gml:coord" );
-    
-    MakeGMLCoordinate( szCoordinate, sEnvelope.MaxX, sEnvelope.MaxY, 0.0, 
-                       FALSE );
+
+    MakeGMLCoordinate( szCoordinate, sEnvelope.MaxX, sEnvelope.MaxY, 0.0,
+                       false );
     pszY = strstr(szCoordinate,",") + 1;
     pszY[-1] = '\0';
 
@@ -506,9 +526,9 @@ CPLXMLNode *OGR_G_ExportEnvelopeToGMLTree( OGRGeometryH hGeometry )
 /*                     AppendGML3CoordinateList()                       */
 /************************************************************************/
 
-static void AppendGML3CoordinateList( const OGRSimpleCurve *poLine, int bCoordSwap,
-                                      char **ppszText, int *pnLength,
-                                      int *pnMaxLength, int nSRSDimensionLocFlags )
+static void AppendGML3CoordinateList( const OGRSimpleCurve *poLine, bool bCoordSwap,
+                                      char **ppszText, size_t *pnLength,
+                                      size_t *pnMaxLength, int nSRSDimensionLocFlags )
 
 {
     char        szCoordinate[256];
@@ -557,16 +577,17 @@ static void AppendGML3CoordinateList( const OGRSimpleCurve *poLine, int bCoordSw
 /*                      OGR2GML3GeometryAppend()                        */
 /************************************************************************/
 
-static int OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
-                                   const OGRSpatialReference* poParentSRS,
-                                   char **ppszText, int *pnLength,
-                                   int *pnMaxLength,
-                                   int bIsSubGeometry,
-                                   int bLongSRS,
-                                   int bLineStringAsCurve,
-                                   const char* pszGMLId,
-                                   int nSRSDimensionLocFlags,
-                                   int bForceLineStringAsLinearRing )
+static bool OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
+                                    const OGRSpatialReference* poParentSRS,
+                                    char **ppszText, size_t *pnLength,
+                                    size_t *pnMaxLength,
+                                    bool bIsSubGeometry,
+                                    bool bLongSRS,
+                                    bool bLineStringAsCurve,
+                                    const char* pszGMLId,
+                                    int nSRSDimensionLocFlags,
+                                    bool bForceLineStringAsLinearRing,
+                                    const char* pszNamespaceDecl)
 
 {
 
@@ -574,9 +595,9 @@ static int OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
 /*      Check for Spatial Reference System attached to given geometry   */
 /* -------------------------------------------------------------------- */
 
-    // Buffer for srsName, srsDimension and gml:id attributes (srsName="..." gml:id="...")
+    // Buffer for srsName, xmlns:gml, srsDimension and gml:id attributes (srsName="..." gml:id="...")
     char szAttributes[256];
-    int nAttrsLength = 0;
+    size_t nAttrsLength = 0;
 
     szAttributes[0] = 0;
 
@@ -584,9 +605,19 @@ static int OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
     if (poParentSRS)
         poSRS = poParentSRS;
     else
-        poParentSRS = poSRS = poGeometry->getSpatialReference();
+        poSRS = poGeometry->getSpatialReference();
 
-    int bCoordSwap = FALSE;
+    bool bCoordSwap = false;
+
+    if( pszNamespaceDecl != NULL )
+    {
+        snprintf( szAttributes + nAttrsLength,
+                  sizeof(szAttributes) - nAttrsLength,
+                  " xmlns:gml=\"%s\"",
+                  pszNamespaceDecl );
+        pszNamespaceDecl = NULL;
+        nAttrsLength += strlen(szAttributes + nAttrsLength);
+    }
 
     if( NULL != poSRS )
     {
@@ -614,7 +645,7 @@ static int OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
                         if (oSRS.importFromEPSGA(atoi(pszAuthCode)) == OGRERR_NONE)
                         {
                             if (oSRS.EPSGTreatsAsLatLong() || oSRS.EPSGTreatsAsNorthingEasting())
-                                bCoordSwap = TRUE;
+                                bCoordSwap = true;
                         }
                     }
 
@@ -622,18 +653,20 @@ static int OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
                     {
                         if (bLongSRS)
                         {
-                            snprintf( szAttributes, sizeof(szAttributes),
+                            snprintf( szAttributes + nAttrsLength,
+                                      sizeof(szAttributes) - nAttrsLength,
                                       " srsName=\"urn:ogc:def:crs:%s::%s\"",
                                       pszAuthName, pszAuthCode );
                         }
                         else
                         {
-                            snprintf( szAttributes, sizeof(szAttributes),
+                            snprintf( szAttributes + nAttrsLength,
+                                      sizeof(szAttributes) - nAttrsLength,
                                       " srsName=\"%s:%s\"",
                                       pszAuthName, pszAuthCode );
                         }
 
-                        nAttrsLength = strlen(szAttributes);
+                        nAttrsLength += strlen(szAttributes + nAttrsLength);
                     }
                 }
             }
@@ -643,18 +676,21 @@ static int OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
     if( (nSRSDimensionLocFlags & SRSDIM_LOC_GEOMETRY) != 0 &&
         wkbHasZ(poGeometry->getGeometryType()) )
     {
-        strcat(szAttributes, " srsDimension=\"3\"");
-        nAttrsLength = strlen(szAttributes);
+        snprintf( szAttributes + nAttrsLength,
+                  sizeof(szAttributes) - nAttrsLength,
+                  " srsDimension=\"3\"" );
+        nAttrsLength += strlen(szAttributes + nAttrsLength);
 
         nSRSDimensionLocFlags &= ~SRSDIM_LOC_GEOMETRY;
     }
 
     if (pszGMLId != NULL && nAttrsLength + 9 + strlen(pszGMLId) + 1 < sizeof(szAttributes))
     {
-        strcat(szAttributes, " gml:id=\"");
-        strcat(szAttributes, pszGMLId);
-        strcat(szAttributes, "\"");
-        nAttrsLength = strlen(szAttributes);
+        snprintf( szAttributes + nAttrsLength,
+                  sizeof(szAttributes) - nAttrsLength,
+                  " gml:id=\"%s\"",
+                  pszGMLId );
+        nAttrsLength += strlen(szAttributes + nAttrsLength);
     }
 
     OGRwkbGeometryType eType = poGeometry->getGeometryType();
@@ -678,7 +714,7 @@ static int OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
         _GrowBuffer( *pnLength + strlen(szCoordinate) + 60 + nAttrsLength,
                      ppszText, pnMaxLength );
 
-        sprintf( *ppszText + *pnLength,
+        snprintf( *ppszText + *pnLength, *pnMaxLength -  *pnLength,
                 "<gml:Point%s><gml:pos>%s</gml:pos></gml:Point>",
                  szAttributes, szCoordinate );
 
@@ -702,7 +738,7 @@ static int OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
         _GrowBuffer( *pnLength + strlen(szCoordinate) + 70 + nAttrsLength,
                      ppszText, pnMaxLength );
 
-        sprintf( *ppszText + *pnLength,
+        snprintf( *ppszText + *pnLength, *pnMaxLength -  *pnLength,
                 "<gml:Point%s><gml:pos>%s</gml:pos></gml:Point>",
                  szAttributes, szCoordinate );
 
@@ -714,7 +750,7 @@ static int OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
 /* -------------------------------------------------------------------- */
     else if( eFType == wkbLineString )
     {
-        int bRing = EQUAL(poGeometry->getGeometryName(),"LINEARRING") ||
+        bool bRing = EQUAL(poGeometry->getGeometryName(),"LINEARRING") ||
                     bForceLineStringAsLinearRing;
         if (!bRing && bLineStringAsCurve)
         {
@@ -734,7 +770,8 @@ static int OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
             // Buffer for tag name + srsName attribute if set
             const size_t nLineTagLength = 16;
             char* pszLineTagName = NULL;
-            pszLineTagName = (char *) CPLMalloc( nLineTagLength + nAttrsLength + 1 );
+            const size_t nLineTagNameBufLen = nLineTagLength + nAttrsLength + 1;
+            pszLineTagName = (char *) CPLMalloc( nLineTagNameBufLen );
 
             if( bRing )
             {
@@ -744,7 +781,7 @@ static int OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
             }
             else
             {
-                sprintf( pszLineTagName, "<gml:LineString%s>", szAttributes );
+                snprintf( pszLineTagName, nLineTagNameBufLen, "<gml:LineString%s>", szAttributes );
 
                 AppendString( ppszText, pnLength, pnMaxLength,
                             pszLineTagName );
@@ -834,10 +871,10 @@ static int OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
             AppendString( ppszText, pnLength, pnMaxLength,
                           "<gml:curveMember>" );
             if( !OGR2GML3GeometryAppend( poCC->getCurve(i), poSRS, ppszText, pnLength,
-                                         pnMaxLength, TRUE, bLongSRS,
+                                         pnMaxLength, true, bLongSRS,
                                          bLineStringAsCurve,
-                                         NULL, nSRSDimensionLocFlags, FALSE) )
-                return FALSE;
+                                         NULL, nSRSDimensionLocFlags, false, NULL) )
+                return false;
             AppendString( ppszText, pnLength, pnMaxLength,
                           "</gml:curveMember>" );
         }
@@ -855,10 +892,11 @@ static int OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
         // Buffer for polygon tag name + srsName attribute if set
         const size_t nPolyTagLength = 13;
         char* pszPolyTagName = NULL;
-        pszPolyTagName = (char *) CPLMalloc( nPolyTagLength + nAttrsLength + 1 );
+        const size_t nPolyTagNameBufLen = nPolyTagLength + nAttrsLength + 1;
+        pszPolyTagName = (char *) CPLMalloc( nPolyTagNameBufLen );
 
         // Compose Polygon tag with or without srsName attribute
-        sprintf( pszPolyTagName, "<gml:Polygon%s>", szAttributes );
+        snprintf( pszPolyTagName, nPolyTagNameBufLen, "<gml:Polygon%s>", szAttributes );
 
         AppendString( ppszText, pnLength, pnMaxLength,
                       pszPolyTagName );
@@ -875,10 +913,10 @@ static int OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
 
             if( !OGR2GML3GeometryAppend( poCP->getExteriorRingCurve(), poSRS,
                                          ppszText, pnLength, pnMaxLength,
-                                         TRUE, bLongSRS, bLineStringAsCurve,
-                                         NULL, nSRSDimensionLocFlags, TRUE) )
+                                         true, bLongSRS, bLineStringAsCurve,
+                                         NULL, nSRSDimensionLocFlags, true, NULL) )
             {
-                return FALSE;
+                return false;
             }
 
             AppendString( ppszText, pnLength, pnMaxLength,
@@ -893,10 +931,10 @@ static int OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
                           "<gml:interior>" );
 
             if( !OGR2GML3GeometryAppend( poRing, poSRS, ppszText, pnLength,
-                                         pnMaxLength, TRUE, bLongSRS,
+                                         pnMaxLength, true, bLongSRS,
                                          bLineStringAsCurve,
-                                         NULL, nSRSDimensionLocFlags, TRUE) )
-                return FALSE;
+                                         NULL, nSRSDimensionLocFlags, true, NULL) )
+                return false;
 
             AppendString( ppszText, pnLength, pnMaxLength,
                           "</gml:interior>" );
@@ -926,32 +964,36 @@ static int OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
 
         if( eFType == wkbMultiPolygon || eFType == wkbMultiSurface )
         {
-            pszElemOpen = (char *) CPLMalloc( 13 + nAttrsLength + 1 );
-            sprintf( pszElemOpen, "MultiSurface%s>", szAttributes );
+            const size_t nBufLen = 13 + nAttrsLength + 1;
+            pszElemOpen = (char *) CPLMalloc( nBufLen );
+            snprintf( pszElemOpen, nBufLen, "MultiSurface%s>", szAttributes );
 
             pszElemClose = "MultiSurface>";
             pszMemberElem = "surfaceMember>";
         }
         else if( eFType == wkbMultiLineString || eFType == wkbMultiCurve )
         {
-            pszElemOpen = (char *) CPLMalloc( 16 + nAttrsLength + 1 );
-            sprintf( pszElemOpen, "MultiCurve%s>", szAttributes );
+            const size_t nBufLen = 16 + nAttrsLength + 1;
+            pszElemOpen = (char *) CPLMalloc( nBufLen );
+            snprintf( pszElemOpen, nBufLen, "MultiCurve%s>", szAttributes );
 
             pszElemClose = "MultiCurve>";
             pszMemberElem = "curveMember>";
         }
         else if( eFType == wkbMultiPoint )
         {
-            pszElemOpen = (char *) CPLMalloc( 11 + nAttrsLength + 1 );
-            sprintf( pszElemOpen, "MultiPoint%s>", szAttributes );
+            const size_t nBufLen = 11 + nAttrsLength + 1;
+            pszElemOpen = (char *) CPLMalloc( nBufLen );
+            snprintf( pszElemOpen, nBufLen, "MultiPoint%s>", szAttributes );
 
             pszElemClose = "MultiPoint>";
             pszMemberElem = "pointMember>";
         }
         else
         {
-            pszElemOpen = (char *) CPLMalloc( 19 + nAttrsLength + 1 );
-            sprintf( pszElemOpen, "MultiGeometry%s>", szAttributes );
+            const size_t nBufLen = 19 + nAttrsLength + 1;
+            pszElemOpen = (char *) CPLMalloc( nBufLen );
+            snprintf( pszElemOpen, nBufLen, "MultiGeometry%s>", szAttributes );
 
             pszElemClose = "MultiGeometry>";
             pszMemberElem = "geometryMember>";
@@ -973,11 +1015,11 @@ static int OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
 
             if( !OGR2GML3GeometryAppend( poMember, poSRS,
                                          ppszText, pnLength, pnMaxLength,
-                                         TRUE, bLongSRS, bLineStringAsCurve,
-                                         pszGMLIdSub, nSRSDimensionLocFlags, FALSE ) )
+                                         true, bLongSRS, bLineStringAsCurve,
+                                         pszGMLIdSub, nSRSDimensionLocFlags, false, NULL ) )
             {
                 CPLFree(pszGMLIdSub);
-                return FALSE;
+                return false;
             }
 
             CPLFree(pszGMLIdSub);
@@ -996,10 +1038,10 @@ static int OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
     {
         CPLError(CE_Failure, CPLE_NotSupported, "Unsupported geometry type %s",
                  OGRGeometryTypeToName(eType));
-        return FALSE;
+        return false;
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -1059,7 +1101,7 @@ char *OGR_G_ExportToGML( OGRGeometryH hGeometry )
  *
  * The supported options are :
  * <ul>
- * <li> FORMAT=GML3. Otherwise it will default to GML 2.1.2 output.
+ * <li> FORMAT=GML3 (GML2 or GML32 also accepted starting with GDAL 2.1). If not set, it will default to GML 2.1.2 output.
  * <li> GML3_LINESTRING_ELEMENT=curve. (Only valid for FORMAT=GML3) To use gml:Curve element for linestrings.
  *     Otherwise gml:LineString will be used .
  * <li> GML3_LONGSRS=YES/NO. (Only valid for FORMAT=GML3) Default to YES. If YES, SRS with EPSG authority will
@@ -1073,9 +1115,11 @@ char *OGR_G_ExportToGML( OGRGeometryH hGeometry )
  *      For 2.5D geometries, define the location where to attach the srsDimension attribute.
  *      There are diverging implementations. Some put in on the <gml:posList> element, other
  *      on the top geometry element.
+ * <li> NAMESPACE_DECL=YES/NO. If set to YES, xmlns:gml="http://www.opengis.net/gml" will be added to the
+ *      root node for GML < 3.2 or xmlns:gml="http://www.opengis.net/gml/3.2" for GML 3.2
  * </ul>
  *
- * Note that curve geometries like CIRCULARSTRING, COMPOUNDCURVE, CURVEPOLYGON, 
+ * Note that curve geometries like CIRCULARSTRING, COMPOUNDCURVE, CURVEPOLYGON,
  * MULTICURVE or MULTISURFACE are not supported in GML 2.
  *
  * This method is the same as the C++ method OGRGeometry::exportToGML().
@@ -1091,7 +1135,7 @@ char *OGR_G_ExportToGMLEx( OGRGeometryH hGeometry, char** papszOptions )
 
 {
     char        *pszText;
-    int         nLength = 0, nMaxLength = 1;
+    size_t       nLength = 0, nMaxLength = 1;
 
     if( hGeometry == NULL )
         return CPLStrdup( "" );
@@ -1100,12 +1144,15 @@ char *OGR_G_ExportToGMLEx( OGRGeometryH hGeometry, char** papszOptions )
     pszText[0] = '\0';
 
     const char* pszFormat = CSLFetchNameValue(papszOptions, "FORMAT");
-    if (pszFormat && EQUAL(pszFormat, "GML3"))
+    bool bNamespaceDecl = CPLTestBool(CSLFetchNameValueDef(papszOptions, "NAMESPACE_DECL", "NO")) != FALSE;
+    if (pszFormat && (EQUAL(pszFormat, "GML3") || EQUAL(pszFormat, "GML32")) )
     {
         const char* pszLineStringElement = CSLFetchNameValue(papszOptions, "GML3_LINESTRING_ELEMENT");
-        int bLineStringAsCurve = (pszLineStringElement && EQUAL(pszLineStringElement, "curve"));
-        int bLongSRS = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "GML3_LONGSRS", "YES"));
+        bool bLineStringAsCurve = (pszLineStringElement && EQUAL(pszLineStringElement, "curve"));
+        bool bLongSRS = CPLTestBool(CSLFetchNameValueDef(papszOptions, "GML3_LONGSRS", "YES")) != FALSE;
         const char* pszGMLId = CSLFetchNameValue(papszOptions, "GMLID");
+        if( pszGMLId == NULL && EQUAL(pszFormat, "GML32") )
+            CPLError(CE_Warning, CPLE_AppDefined, "FORMAT=GML32 specified but not GMLID set");
         const char* pszSRSDimensionLoc = CSLFetchNameValueDef(papszOptions,"SRSDIMENSION_LOC","POSLIST");
         char** papszSRSDimensionLoc = CSLTokenizeString2(pszSRSDimensionLoc, ",", 0);
         int nSRSDimensionLocFlags = 0;
@@ -1120,9 +1167,15 @@ char *OGR_G_ExportToGMLEx( OGRGeometryH hGeometry, char** papszOptions )
                          papszSRSDimensionLoc[i]);
         }
         CSLDestroy(papszSRSDimensionLoc);
+        const char* pszNamespaceDecl = NULL;
+        if( bNamespaceDecl && EQUAL(pszFormat, "GML32") )
+            pszNamespaceDecl = "http://www.opengis.net/gml/3.2";
+        else if( bNamespaceDecl )
+            pszNamespaceDecl = "http://www.opengis.net/gml";
         if( !OGR2GML3GeometryAppend( (OGRGeometry *) hGeometry, NULL, &pszText,
-                                    &nLength, &nMaxLength, FALSE, bLongSRS,
-                                     bLineStringAsCurve, pszGMLId, nSRSDimensionLocFlags, FALSE ))
+                                     &nLength, &nMaxLength, false, bLongSRS,
+                                     bLineStringAsCurve, pszGMLId, nSRSDimensionLocFlags, false,
+                                     pszNamespaceDecl ))
         {
             CPLFree( pszText );
             return NULL;
@@ -1131,8 +1184,12 @@ char *OGR_G_ExportToGMLEx( OGRGeometryH hGeometry, char** papszOptions )
             return pszText;
     }
 
+    const char* pszNamespaceDecl = NULL;
+    if( bNamespaceDecl )
+        pszNamespaceDecl = "http://www.opengis.net/gml";
     if( !OGR2GMLGeometryAppend( (OGRGeometry *) hGeometry, &pszText,
-                                &nLength, &nMaxLength, FALSE ))
+                                &nLength, &nMaxLength, false,
+                                pszNamespaceDecl ))
     {
         CPLFree( pszText );
         return NULL;
diff --git a/ogr/ogr_api.cpp b/ogr/ogr_api.cpp
index 2abe6cb..27e96a4 100644
--- a/ogr/ogr_api.cpp
+++ b/ogr/ogr_api.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: ogr_api.cpp 28039 2014-11-30 18:24:59Z rouault $
+ * $Id: ogr_api.cpp 33757 2016-03-20 20:22:33Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
- * Purpose:  C API Functions that don't correspond one-to-one with C++ 
+ * Purpose:  C API Functions that don't correspond one-to-one with C++
  *           methods, such as the "simplified" geometry access functions.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -33,7 +33,7 @@
 #include "ogr_api.h"
 #include "cpl_error.h"
 
-static int bNonLinearGeometriesEnabled = TRUE;
+static bool bNonLinearGeometriesEnabled = true;
 
 /************************************************************************/
 /*                        OGR_G_GetPointCount()                         */
@@ -74,8 +74,9 @@ int OGR_G_GetPointCount( OGRGeometryH hGeom )
  *
  * This method primary exists to preset the number of points in a linestring
  * geometry before setPoint() is used to assign them to avoid reallocating
- * the array larger with each call to addPoint(). 
+ * the array larger with each call to addPoint().
  *
+ * @param hGeom handle to the geometry.
  * @param nNewPointCount the new number of points for geometry.
  */
 
@@ -89,8 +90,8 @@ void OGR_G_SetPointCount( OGRGeometryH hGeom, int nNewPointCount )
       case wkbLineString:
       case wkbCircularString:
       {
-        OGRLineString *poLine = (OGRLineString *) hGeom;
-        poLine->setNumPoints( nNewPointCount );
+        OGRSimpleCurve* poSC = (OGRSimpleCurve *)hGeom;
+        poSC->setNumPoints( nNewPointCount );
         break;
       }
       default:
@@ -107,7 +108,7 @@ void OGR_G_SetPointCount( OGRGeometryH hGeom, int nNewPointCount )
  *
  * @param hGeom handle to the geometry from which to get the x coordinate.
  * @param i point to get the x coordinate.
- * @return the X coordinate of this point. 
+ * @return the X coordinate of this point.
  */
 
 double OGR_G_GetX( OGRGeometryH hGeom, int i )
@@ -131,13 +132,13 @@ double OGR_G_GetX( OGRGeometryH hGeom, int i )
       case wkbLineString:
       case wkbCircularString:
       {
-          OGRLineString* poLS = (OGRLineString *) hGeom;
-          if (i < 0 || i >= poLS->getNumPoints())
+          OGRSimpleCurve* poSC = (OGRSimpleCurve *)hGeom;
+          if (i < 0 || i >= poSC->getNumPoints())
           {
               CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
               return 0.0;
           }
-          return poLS->getX( i );
+          return poSC->getX( i );
       }
 
       default:
@@ -154,7 +155,7 @@ double OGR_G_GetX( OGRGeometryH hGeom, int i )
  *
  * @param hGeom handle to the geometry from which to get the y coordinate.
  * @param i point to get the Y coordinate.
- * @return the Y coordinate of this point. 
+ * @return the Y coordinate of this point.
  */
 
 double OGR_G_GetY( OGRGeometryH hGeom, int i )
@@ -178,13 +179,13 @@ double OGR_G_GetY( OGRGeometryH hGeom, int i )
       case wkbLineString:
       case wkbCircularString:
       {
-          OGRLineString* poLS = (OGRLineString *) hGeom;
-          if (i < 0 || i >= poLS->getNumPoints())
+          OGRSimpleCurve* poSC = (OGRSimpleCurve *)hGeom;
+          if (i < 0 || i >= poSC->getNumPoints())
           {
               CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
               return 0.0;
           }
-          return poLS->getY( i );
+          return poSC->getY( i );
       }
 
       default:
@@ -201,7 +202,7 @@ double OGR_G_GetY( OGRGeometryH hGeom, int i )
  *
  * @param hGeom handle to the geometry from which to get the Z coordinate.
  * @param i point to get the Z coordinate.
- * @return the Z coordinate of this point. 
+ * @return the Z coordinate of this point.
  */
 
 double OGR_G_GetZ( OGRGeometryH hGeom, int i )
@@ -225,13 +226,60 @@ double OGR_G_GetZ( OGRGeometryH hGeom, int i )
       case wkbLineString:
       case wkbCircularString:
       {
-          OGRLineString* poLS = (OGRLineString *) hGeom;
-          if (i < 0 || i >= poLS->getNumPoints())
+          OGRSimpleCurve* poSC = (OGRSimpleCurve *)hGeom;
+          if (i < 0 || i >= poSC->getNumPoints())
           {
               CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
               return 0.0;
           }
-          return poLS->getZ( i );
+          return poSC->getZ( i );
+      }
+
+      default:
+          CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
+          return 0.0;
+    }
+}
+
+/************************************************************************/
+/*                             OGR_G_GetM()                             */
+/************************************************************************/
+/**
+ * \brief Fetch the m coordinate of a point from a geometry.
+ *
+ * @param hGeom handle to the geometry from which to get the M coordinate.
+ * @param i point to get the M coordinate.
+ * @return the M coordinate of this point.
+ */
+
+double OGR_G_GetM( OGRGeometryH hGeom, int i )
+
+{
+    VALIDATE_POINTER1( hGeom, "OGR_G_GetM", 0 );
+
+    switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
+    {
+      case wkbPoint:
+      {
+          if( i == 0 )
+              return ((OGRPoint *) hGeom)->getM();
+          else
+          {
+              CPLError(CE_Failure, CPLE_NotSupported, "Only i == 0 is supported");
+              return 0.0;
+          }
+      }
+
+      case wkbLineString:
+      case wkbCircularString:
+      {
+          OGRSimpleCurve* poSC = (OGRSimpleCurve *)hGeom;
+          if (i < 0 || i >= poSC->getNumPoints())
+          {
+              CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
+              return 0.0;
+          }
+          return poSC->getM( i );
       }
 
       default:
@@ -248,7 +296,7 @@ double OGR_G_GetZ( OGRGeometryH hGeom, int i )
  * \brief Returns all points of line string.
  *
  * This method copies all points into user arrays. The user provides the
- * stride between 2 consecutives elements of the array.
+ * stride between 2 consecutive elements of the array.
  *
  * On some CPU architectures, care must be taken so that the arrays are properly aligned.
  *
@@ -286,9 +334,9 @@ int OGR_G_GetPoints( OGRGeometryH hGeom,
       case wkbLineString:
       case wkbCircularString:
       {
-          OGRLineString* poLS = (OGRLineString *) hGeom;
-          poLS->getPoints(pabyX, nXStride, pabyY, nYStride, pabyZ, nZStride);
-          return poLS->getNumPoints();
+          OGRSimpleCurve* poSC = (OGRSimpleCurve *)hGeom;
+          poSC->getPoints(pabyX, nXStride, pabyY, nYStride, pabyZ, nZStride);
+          return poSC->getNumPoints();
       }
       break;
 
@@ -299,6 +347,68 @@ int OGR_G_GetPoints( OGRGeometryH hGeom,
     }
 }
 
+/************************************************************************/
+/*                          OGR_G_GetPointsZM()                         */
+/************************************************************************/
+
+/**
+ * \brief Returns all points of line string.
+ *
+ * This method copies all points into user arrays. The user provides the
+ * stride between 2 consecutive elements of the array.
+ *
+ * On some CPU architectures, care must be taken so that the arrays are properly aligned.
+ *
+ * @param hGeom handle to the geometry from which to get the coordinates.
+ * @param pabyX a buffer of at least (sizeof(double) * nXStride * nPointCount) bytes, may be NULL.
+ * @param nXStride the number of bytes between 2 elements of pabyX.
+ * @param pabyY a buffer of at least (sizeof(double) * nYStride * nPointCount) bytes, may be NULL.
+ * @param nYStride the number of bytes between 2 elements of pabyY.
+ * @param pabyZ a buffer of at last size (sizeof(double) * nZStride * nPointCount) bytes, may be NULL.
+ * @param nZStride the number of bytes between 2 elements of pabyZ.
+ * @param pabyM a buffer of at last size (sizeof(double) * nMStride * nPointCount) bytes, may be NULL.
+ * @param nMStride the number of bytes between 2 elements of pabyM.
+ *
+ * @return the number of points
+ *
+ * @since OGR 1.9.0
+ */
+
+int OGR_G_GetPointsZM( OGRGeometryH hGeom,
+                       void* pabyX, int nXStride,
+                       void* pabyY, int nYStride,
+                       void* pabyZ, int nZStride,
+                       void* pabyM, int nMStride)
+{
+    VALIDATE_POINTER1( hGeom, "OGR_G_GetPointsZM", 0 );
+
+    switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
+    {
+      case wkbPoint:
+      {
+        if (pabyX) *((double*)pabyX) = ((OGRPoint *)hGeom)->getX();
+        if (pabyY) *((double*)pabyY) = ((OGRPoint *)hGeom)->getY();
+        if (pabyZ) *((double*)pabyZ) = ((OGRPoint *)hGeom)->getZ();
+        if (pabyM) *((double*)pabyM) = ((OGRPoint *)hGeom)->getM();
+        return 1;
+      }
+      break;
+
+      case wkbLineString:
+      case wkbCircularString:
+      {
+          OGRSimpleCurve* poSC = (OGRSimpleCurve *)hGeom;
+          poSC->getPoints(pabyX, nXStride, pabyY, nYStride, pabyZ, nZStride, pabyM, nMStride);
+          return poSC->getNumPoints();
+      }
+      break;
+
+      default:
+        CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
+        return 0;
+        break;
+    }
+}
 
 /************************************************************************/
 /*                           OGR_G_GetPoint()                           */
@@ -314,7 +424,7 @@ int OGR_G_GetPoints( OGRGeometryH hGeom,
  * @param pdfZ value of z coordinate.
  */
 
-void OGR_G_GetPoint( OGRGeometryH hGeom, int i, 
+void OGR_G_GetPoint( OGRGeometryH hGeom, int i,
                      double *pdfX, double *pdfY, double *pdfZ )
 
 {
@@ -341,8 +451,8 @@ void OGR_G_GetPoint( OGRGeometryH hGeom, int i,
       case wkbLineString:
       case wkbCircularString:
       {
-          OGRLineString* poLS = (OGRLineString *) hGeom;
-          if (i < 0 || i >= poLS->getNumPoints())
+          OGRSimpleCurve* poSC = (OGRSimpleCurve *)hGeom;
+          if (i < 0 || i >= poSC->getNumPoints())
           {
               CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
               *pdfX = *pdfY = 0;
@@ -351,10 +461,10 @@ void OGR_G_GetPoint( OGRGeometryH hGeom, int i,
           }
           else
           {
-            *pdfX = poLS->getX( i );
-            *pdfY = poLS->getY( i );
+            *pdfX = poSC->getX( i );
+            *pdfY = poSC->getY( i );
             if( pdfZ != NULL )
-                *pdfZ =  poLS->getZ( i );
+                *pdfZ =  poSC->getZ( i );
           }
       }
       break;
@@ -366,7 +476,79 @@ void OGR_G_GetPoint( OGRGeometryH hGeom, int i,
 }
 
 /************************************************************************/
-/*                           OGR_G_SetPoint()                           */
+/*                           OGR_G_GetPointZM()                         */
+/************************************************************************/
+
+/**
+ * \brief Fetch a point in line string or a point geometry.
+ *
+ * @param hGeom handle to the geometry from which to get the coordinates.
+ * @param i the vertex to fetch, from 0 to getNumPoints()-1, zero for a point.
+ * @param pdfX value of x coordinate.
+ * @param pdfY value of y coordinate.
+ * @param pdfZ value of z coordinate.
+ * @param pdfM value of m coordinate.
+ */
+
+void OGR_G_GetPointZM( OGRGeometryH hGeom, int i,
+                       double *pdfX, double *pdfY, double *pdfZ, double *pdfM )
+
+{
+    VALIDATE_POINTER0( hGeom, "OGR_G_GetPointZM" );
+
+    switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
+    {
+      case wkbPoint:
+      {
+          if( i == 0 )
+          {
+              *pdfX = ((OGRPoint *)hGeom)->getX();
+              *pdfY = ((OGRPoint *)hGeom)->getY();
+              if( pdfZ != NULL )
+                  *pdfZ = ((OGRPoint *)hGeom)->getZ();
+              if( pdfM != NULL )
+                  *pdfM = ((OGRPoint *)hGeom)->getM();
+          }
+          else
+          {
+              CPLError(CE_Failure, CPLE_NotSupported, "Only i == 0 is supported");
+          }
+      }
+      break;
+
+      case wkbLineString:
+      case wkbCircularString:
+      {
+          OGRSimpleCurve* poSC = (OGRSimpleCurve *)hGeom;
+          if (i < 0 || i >= poSC->getNumPoints())
+          {
+              CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
+              *pdfX = *pdfY = 0;
+              if( pdfZ != NULL )
+                  *pdfZ = 0;
+              if( pdfM != NULL )
+                  *pdfM = 0;
+          }
+          else
+          {
+            *pdfX = poSC->getX( i );
+            *pdfY = poSC->getY( i );
+            if( pdfZ != NULL )
+                *pdfZ =  poSC->getZ( i );
+            if( pdfM != NULL )
+                *pdfM =  poSC->getM( i );
+          }
+      }
+      break;
+
+      default:
+        CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
+        break;
+    }
+}
+
+/************************************************************************/
+/*                           OGR_G_SetPoints()                          */
 /************************************************************************/
 /**
  * \brief Assign all points in a point or a line string geometry.
@@ -376,11 +558,11 @@ void OGR_G_GetPoint( OGRGeometryH hGeom, int i,
  *
  * @param hGeom handle to the geometry to set the coordinates.
  * @param nPointsIn number of points being passed in padfX and padfY.
- * @param padfX list of X coordinates of points being assigned.
+ * @param pabyX list of X coordinates (double values) of points being assigned.
  * @param nXStride the number of bytes between 2 elements of pabyX.
- * @param padfY list of Y coordinates of points being assigned.
+ * @param pabyY list of Y coordinates (double values) of points being assigned.
  * @param nYStride the number of bytes between 2 elements of pabyY.
- * @param padfZ list of Z coordinates of points being assigned (defaults to NULL for 2D objects).
+ * @param pabyZ list of Z coordinates (double values) of points being assigned (defaults to NULL for 2D objects).
  * @param nZStride the number of bytes between 2 elements of pabyZ.
  */
 
@@ -392,38 +574,175 @@ void CPL_DLL OGR_G_SetPoints( OGRGeometryH hGeom, int nPointsIn,
 {
     VALIDATE_POINTER0( hGeom, "OGR_G_SetPoints" );
 
+    if( pabyX == NULL || pabyY == NULL )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, "pabyX == NULL || pabyY == NULL");
+        return;
+    }
+
     switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
     {
       case wkbPoint:
       {
-        ((OGRPoint *) hGeom)->setX( pabyX ? *( (double *)pabyX ) : 0.0 );
-        ((OGRPoint *) hGeom)->setY( pabyY ? *( (double *)pabyY ) : 0.0 );
-        ((OGRPoint *) hGeom)->setZ( pabyZ ? *( (double *)pabyZ ) : 0.0 );
+        ((OGRPoint *) hGeom)->setX( *( (double *)pabyX ) );
+        ((OGRPoint *) hGeom)->setY( *( (double *)pabyY ) );
+        if( pabyZ != NULL )
+            ((OGRPoint *) hGeom)->setZ(*( (double *)pabyZ ) );
         break;
       }
       case wkbLineString:
       case wkbCircularString:
       {
-        OGRLineString* poLine = (OGRLineString *) hGeom;
+        OGRSimpleCurve* poSC = (OGRSimpleCurve *)hGeom;
 
-        if( nXStride == 0 && nYStride == 0 && nZStride == 0 )
+        if( nXStride == (int)sizeof(double) &&
+            nYStride == (int)sizeof(double) &&
+            ((nZStride == 0 && pabyZ == NULL) ||
+             (nZStride == (int)sizeof(double) && pabyZ != NULL)) )
         {
-          poLine->setPoints( nPointsIn, (double *)pabyX, (double *)pabyY, (double *)pabyZ ); 
+          poSC->setPoints( nPointsIn, (double *)pabyX, (double *)pabyY, (double *)pabyZ );
         }
         else
         {
-          double x, y, z;		  
-          x = y = z = 0;
-          poLine->setNumPoints( nPointsIn );
+          poSC->setNumPoints( nPointsIn );
 
           for (int i = 0; i < nPointsIn; ++i)
           {
-            if( pabyX ) x = *(double*)((char*)pabyX + i * nXStride);
-            if( pabyY ) y = *(double*)((char*)pabyY + i * nYStride);
-            if( pabyZ ) z = *(double*)((char*)pabyZ + i * nZStride);
+            double x = *(double*)((char*)pabyX + i * nXStride);
+            double y = *(double*)((char*)pabyY + i * nYStride);
+            if( pabyZ )
+            {
+                double z = *(double*)((char*)pabyZ + i * nZStride);
+                poSC->setPoint( i, x, y, z );
+            }
+            else
+            {
+                poSC->setPoint( i, x, y );
+            }
+          }
+        }
+        break;
+      }
+      default:
+        CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
+        break;
+    }
+}
 
-            poLine->setPoint( i, x, y, z );
+/************************************************************************/
+/*                           OGR_G_SetPointsZM()                        */
+/************************************************************************/
+/**
+ * \brief Assign all points in a point or a line string geometry.
+ *
+ * This method clear any existing points assigned to this geometry,
+ * and assigns a whole new set.
+ *
+ * @param hGeom handle to the geometry to set the coordinates.
+ * @param nPointsIn number of points being passed in padfX and padfY.
+ * @param pabyX list of X coordinates (double values) of points being assigned.
+ * @param nXStride the number of bytes between 2 elements of pabyX.
+ * @param pabyY list of Y coordinates (double values) of points being assigned.
+ * @param nYStride the number of bytes between 2 elements of pabyY.
+ * @param pabyZ list of Z coordinates (double values) of points being assigned (if not NULL, upgrades the geometry to have Z coordinate).
+ * @param nZStride the number of bytes between 2 elements of pabyZ.
+ * @param pabyM list of M coordinates (double values) of points being assigned (if not NULL, upgrades the geometry to have M coordinate).
+ * @param nMStride the number of bytes between 2 elements of pabyM.
+ */
+
+void CPL_DLL OGR_G_SetPointsZM( OGRGeometryH hGeom, int nPointsIn,
+                                void* pabyX, int nXStride,
+                                void* pabyY, int nYStride,
+                                void* pabyZ, int nZStride,
+                                void* pabyM, int nMStride )
+
+{
+    VALIDATE_POINTER0( hGeom, "OGR_G_SetPointsZM" );
+
+    if( pabyX == NULL || pabyY == NULL )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, "pabyX == NULL || pabyY == NULL");
+        return;
+    }
+
+    switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
+    {
+      case wkbPoint:
+      {
+        ((OGRPoint *) hGeom)->setX( *( (double *)pabyX ) );
+        ((OGRPoint *) hGeom)->setY( *( (double *)pabyY ) );
+        if (pabyZ)
+            ((OGRPoint *) hGeom)->setZ( *(double *)pabyZ );
+        if (pabyM)
+            ((OGRPoint *) hGeom)->setM( *(double *)pabyM );
+        break;
+      }
+      case wkbLineString:
+      case wkbCircularString:
+      {
+        OGRSimpleCurve* poSC = (OGRSimpleCurve *)hGeom;
+
+        if(  nXStride == (int)sizeof(double) &&
+             nYStride == (int)sizeof(double) &&
+             ((nZStride == 0 && pabyZ == NULL) ||
+              (nZStride == (int)sizeof(double) && pabyZ != NULL)) &&
+             ((nMStride == 0 && pabyM == NULL) ||
+              (nMStride == (int)sizeof(double) && pabyM != NULL)) )
+        {
+            if (!pabyZ && !pabyM)
+                poSC->setPoints( nPointsIn, (double *)pabyX, (double *)pabyY );
+            else if (pabyZ && !pabyM)
+                poSC->setPoints( nPointsIn, (double *)pabyX, (double *)pabyY, (double *)pabyZ );
+            else if (!pabyZ && pabyM)
+                poSC->setPointsM( nPointsIn, (double *)pabyX, (double *)pabyY, (double *)pabyM );
+            else
+                poSC->setPoints( nPointsIn, (double *)pabyX, (double *)pabyY, (double *)pabyZ, (double *)pabyM );
+        }
+        else
+        {
+          poSC->setNumPoints( nPointsIn );
+
+          if (!pabyZ && !pabyM)
+          {
+              for (int i = 0; i < nPointsIn; ++i)
+              {
+                  double x = *(double*)((char*)pabyX + i * nXStride);
+                  double y = *(double*)((char*)pabyY + i * nYStride);
+                  poSC->setPoint( i, x, y );
+              }
+          }
+          else if (pabyZ && !pabyM)
+          {
+              for (int i = 0; i < nPointsIn; ++i)
+              {
+                  double x = *(double*)((char*)pabyX + i * nXStride);
+                  double y = *(double*)((char*)pabyY + i * nYStride);
+                  double z = *(double*)((char*)pabyZ + i * nZStride);
+                  poSC->setPoint( i, x, y, z );
+              }
+          }
+          else if (!pabyZ && pabyM)
+          {
+              for (int i = 0; i < nPointsIn; ++i)
+              {
+                  double x = *(double*)((char*)pabyX + i * nXStride);
+                  double y = *(double*)((char*)pabyY + i * nYStride);
+                  double m = *(double*)((char*)pabyM + i * nMStride);
+                  poSC->setPointM( i, x, y, m );
+              }
+          }
+          else
+          {
+              for (int i = 0; i < nPointsIn; ++i)
+              {
+                  double x = *(double*)((char*)pabyX + i * nXStride);
+                  double y = *(double*)((char*)pabyY + i * nYStride);
+                  double z = *(double*)((char*)pabyZ + i * nZStride);
+                  double m = *(double*)((char*)pabyM + i * nMStride);
+                  poSC->setPoint( i, x, y, z, m );
+              }
           }
+
         }
         break;
       }
@@ -451,7 +770,7 @@ void CPL_DLL OGR_G_SetPoints( OGRGeometryH hGeom, int nPointsIn,
  * @param dfZ input Z coordinate to assign (defaults to zero).
  */
 
-void OGR_G_SetPoint( OGRGeometryH hGeom, int i, 
+void OGR_G_SetPoint( OGRGeometryH hGeom, int i,
                      double dfX, double dfY, double dfZ )
 
 {
@@ -482,7 +801,7 @@ void OGR_G_SetPoint( OGRGeometryH hGeom, int i,
               CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
               return;
           }
-          ((OGRLineString *) hGeom)->setPoint( i, dfX, dfY, dfZ );
+          ((OGRSimpleCurve *) hGeom)->setPoint( i, dfX, dfY, dfZ );
           break;
       }
 
@@ -509,9 +828,9 @@ void OGR_G_SetPoint( OGRGeometryH hGeom, int i,
  * @param dfY input Y coordinate to assign.
  */
 
-void OGR_G_SetPoint_2D( OGRGeometryH hGeom, int i, 
+void OGR_G_SetPoint_2D( OGRGeometryH hGeom, int i,
                         double dfX, double dfY )
-    
+
 {
     VALIDATE_POINTER0( hGeom, "OGR_G_SetPoint_2D" );
 
@@ -539,7 +858,127 @@ void OGR_G_SetPoint_2D( OGRGeometryH hGeom, int i,
               CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
               return;
           }
-          ((OGRLineString *) hGeom)->setPoint( i, dfX, dfY );
+          ((OGRSimpleCurve *) hGeom)->setPoint( i, dfX, dfY );
+          break;
+      }
+
+      default:
+        CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
+        break;
+    }
+}
+
+/************************************************************************/
+/*                           OGR_G_SetPointM()                          */
+/************************************************************************/
+/**
+ * \brief Set the location of a vertex in a point or linestring geometry.
+ *
+ * If iPoint is larger than the number of existing
+ * points in the linestring, the point count will be increased to
+ * accommodate the request.
+ *
+ * @param hGeom handle to the geometry to add a vertex to.
+ * @param i the index of the vertex to assign (zero based) or
+ *  zero for a point.
+ * @param dfX input X coordinate to assign.
+ * @param dfY input Y coordinate to assign.
+ * @param dfM input M coordinate to assign.
+ */
+
+void OGR_G_SetPointM( OGRGeometryH hGeom, int i,
+                      double dfX, double dfY, double dfM )
+
+{
+    VALIDATE_POINTER0( hGeom, "OGR_G_SetPointM" );
+
+    switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
+    {
+      case wkbPoint:
+      {
+          if( i == 0 )
+          {
+              ((OGRPoint *) hGeom)->setX( dfX );
+              ((OGRPoint *) hGeom)->setY( dfY );
+              ((OGRPoint *) hGeom)->setM( dfM );
+          }
+          else
+          {
+              CPLError(CE_Failure, CPLE_NotSupported, "Only i == 0 is supported");
+          }
+      }
+      break;
+
+      case wkbLineString:
+      case wkbCircularString:
+      {
+          if (i < 0)
+          {
+              CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
+              return;
+          }
+          ((OGRSimpleCurve *) hGeom)->setPointM( i, dfX, dfY, dfM );
+          break;
+      }
+
+      default:
+        CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
+        break;
+    }
+}
+
+/************************************************************************/
+/*                           OGR_G_SetPointZM()                         */
+/************************************************************************/
+/**
+ * \brief Set the location of a vertex in a point or linestring geometry.
+ *
+ * If iPoint is larger than the number of existing
+ * points in the linestring, the point count will be increased to
+ * accommodate the request.
+ *
+ * @param hGeom handle to the geometry to add a vertex to.
+ * @param i the index of the vertex to assign (zero based) or
+ *  zero for a point.
+ * @param dfX input X coordinate to assign.
+ * @param dfY input Y coordinate to assign.
+ * @param dfZ input Z coordinate to assign.
+ * @param dfM input M coordinate to assign.
+ */
+
+void OGR_G_SetPointZM( OGRGeometryH hGeom, int i,
+                       double dfX, double dfY, double dfZ, double dfM )
+
+{
+    VALIDATE_POINTER0( hGeom, "OGR_G_SetPointZM" );
+
+    switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
+    {
+      case wkbPoint:
+      {
+          if( i == 0 )
+          {
+              ((OGRPoint *) hGeom)->setX( dfX );
+              ((OGRPoint *) hGeom)->setY( dfY );
+              ((OGRPoint *) hGeom)->setZ( dfZ );
+              ((OGRPoint *) hGeom)->setM( dfM );
+          }
+          else
+          {
+              CPLError(CE_Failure, CPLE_NotSupported, "Only i == 0 is supported");
+          }
+      }
+      break;
+
+      case wkbLineString:
+      case wkbCircularString:
+      {
+          if (i < 0)
+          {
+              CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
+              return;
+          }
+          ((OGRSimpleCurve *) hGeom)->setPoint( i, dfX, dfY, dfZ, dfM );
           break;
       }
 
@@ -564,7 +1003,7 @@ void OGR_G_SetPoint_2D( OGRGeometryH hGeom, int i,
  * @param dfZ z coordinate of point to add.
  */
 
-void OGR_G_AddPoint( OGRGeometryH hGeom, 
+void OGR_G_AddPoint( OGRGeometryH hGeom,
                      double dfX, double dfY, double dfZ )
 
 {
@@ -582,7 +1021,7 @@ void OGR_G_AddPoint( OGRGeometryH hGeom,
 
       case wkbLineString:
       case wkbCircularString:
-        ((OGRLineString *) hGeom)->addPoint( dfX, dfY, dfZ );
+        ((OGRSimpleCurve *) hGeom)->addPoint( dfX, dfY, dfZ );
         break;
 
       default:
@@ -592,7 +1031,7 @@ void OGR_G_AddPoint( OGRGeometryH hGeom,
 }
 
 /************************************************************************/
-/*                           OGR_G_AddPoint()                           */
+/*                           OGR_G_AddPoint_2D()                        */
 /************************************************************************/
 /**
  * \brief Add a point to a geometry (line string or point).
@@ -605,7 +1044,7 @@ void OGR_G_AddPoint( OGRGeometryH hGeom,
  * @param dfY y coordinate of point to add.
  */
 
-void OGR_G_AddPoint_2D( OGRGeometryH hGeom, 
+void OGR_G_AddPoint_2D( OGRGeometryH hGeom,
                         double dfX, double dfY )
 
 {
@@ -622,7 +1061,93 @@ void OGR_G_AddPoint_2D( OGRGeometryH hGeom,
 
       case wkbLineString:
       case wkbCircularString:
-        ((OGRLineString *) hGeom)->addPoint( dfX, dfY );
+        ((OGRSimpleCurve *) hGeom)->addPoint( dfX, dfY );
+        break;
+
+      default:
+        CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
+        break;
+    }
+}
+
+/************************************************************************/
+/*                           OGR_G_AddPointM()                          */
+/************************************************************************/
+/**
+ * \brief Add a point to a geometry (line string or point).
+ *
+ * The vertex count of the line string is increased by one, and assigned from
+ * the passed location value.
+ *
+ * @param hGeom handle to the geometry to add a point to.
+ * @param dfX x coordinate of point to add.
+ * @param dfY y coordinate of point to add.
+ * @param dfM m coordinate of point to add.
+ */
+
+void OGR_G_AddPointM( OGRGeometryH hGeom,
+                      double dfX, double dfY, double dfM )
+
+{
+    VALIDATE_POINTER0( hGeom, "OGR_G_AddPointM" );
+
+    switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
+    {
+      case wkbPoint:
+      {
+          ((OGRPoint *) hGeom)->setX( dfX );
+          ((OGRPoint *) hGeom)->setY( dfY );
+          ((OGRPoint *) hGeom)->setM( dfM );
+      }
+      break;
+
+      case wkbLineString:
+      case wkbCircularString:
+        ((OGRSimpleCurve *) hGeom)->addPointM( dfX, dfY, dfM );
+        break;
+
+      default:
+        CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
+        break;
+    }
+}
+
+/************************************************************************/
+/*                           OGR_G_AddPointZM()                         */
+/************************************************************************/
+/**
+ * \brief Add a point to a geometry (line string or point).
+ *
+ * The vertex count of the line string is increased by one, and assigned from
+ * the passed location value.
+ *
+ * @param hGeom handle to the geometry to add a point to.
+ * @param dfX x coordinate of point to add.
+ * @param dfY y coordinate of point to add.
+ * @param dfZ z coordinate of point to add.
+ * @param dfM m coordinate of point to add.
+ */
+
+void OGR_G_AddPointZM( OGRGeometryH hGeom,
+                       double dfX, double dfY, double dfZ, double dfM )
+
+{
+    VALIDATE_POINTER0( hGeom, "OGR_G_AddPointZM" );
+
+    switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
+    {
+      case wkbPoint:
+      {
+          ((OGRPoint *) hGeom)->setX( dfX );
+          ((OGRPoint *) hGeom)->setY( dfY );
+          ((OGRPoint *) hGeom)->setZ( dfZ );
+          ((OGRPoint *) hGeom)->setM( dfM );
+      }
+      break;
+
+      case wkbLineString:
+      case wkbCircularString:
+          ((OGRSimpleCurve *) hGeom)->addPoint( dfX, dfY, dfZ, dfM );
         break;
 
       default:
@@ -682,19 +1207,19 @@ int OGR_G_GetGeometryCount( OGRGeometryH hGeom )
  *
  * This function returns an handle to a geometry within the container.
  * The returned geometry remains owned by the container, and should not be
- * modified.  The handle is only valid untill the next change to the
+ * modified.  The handle is only valid until the next change to the
  * geometry container.  Use OGR_G_Clone() to make a copy.
  *
- * This function relates to the SFCOM 
+ * This function relates to the SFCOM
  * IGeometryCollection::get_Geometry() method.
  *
- * This function is the same as the CPP method 
+ * This function is the same as the CPP method
  * OGRGeometryCollection::getGeometryRef().
  *
  * For a polygon, OGR_G_GetGeometryRef(iSubGeom) returns the exterior ring
  * if iSubGeom == 0, and the interior rings for iSubGeom > 0.
  *
- * @param hGeom handle to the geometry container from which to get a 
+ * @param hGeom handle to the geometry container from which to get a
  * geometry from.
  * @param iSubGeom the index of the geometry to fetch, between 0 and
  *          getNumGeometries() - 1.
@@ -710,10 +1235,10 @@ OGRGeometryH OGR_G_GetGeometryRef( OGRGeometryH hGeom, int iSubGeom )
     if( OGR_GT_IsSubClassOf(eType, wkbCurvePolygon) )
     {
         if( iSubGeom == 0 )
-            return (OGRGeometryH) 
+            return (OGRGeometryH)
                 ((OGRCurvePolygon *)hGeom)->getExteriorRingCurve();
         else
-            return (OGRGeometryH) 
+            return (OGRGeometryH)
                 ((OGRCurvePolygon *)hGeom)->getInteriorRingCurve(iSubGeom-1);
     }
     else if( OGR_GT_IsSubClassOf(eType, wkbCompoundCurve) )
@@ -723,7 +1248,7 @@ OGRGeometryH OGR_G_GetGeometryRef( OGRGeometryH hGeom, int iSubGeom )
     else
     {
         CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
-        return 0;
+        return NULL;
     }
 }
 
@@ -740,7 +1265,7 @@ OGRGeometryH OGR_G_GetGeometryRef( OGRGeometryH hGeom, int iSubGeom )
  *
  * There is no SFCOM analog to this method.
  *
- * This function is the same as the CPP method 
+ * This function is the same as the CPP method
  * OGRGeometryCollection::addGeometry.
  *
  * For a polygon, hNewSubGeom must be a linearring. If the polygon is empty,
@@ -775,7 +1300,7 @@ OGRErr OGR_G_AddGeometry( OGRGeometryH hGeom, OGRGeometryH hNewSubGeom )
     }
     else if( OGR_GT_IsSubClassOf(eType, wkbGeometryCollection) )
     {
-        eErr = ((OGRGeometryCollection *)hGeom)->addGeometry( 
+        eErr = ((OGRGeometryCollection *)hGeom)->addGeometry(
                                                 (OGRGeometry *) hNewSubGeom );
     }
 
@@ -793,7 +1318,7 @@ OGRErr OGR_G_AddGeometry( OGRGeometryH hGeom, OGRGeometryH hNewSubGeom )
  * geometry is taken by the container rather than cloning as addGeometry()
  * does.
  *
- * This function is the same as the CPP method 
+ * This function is the same as the CPP method
  * OGRGeometryCollection::addGeometryDirectly.
  *
  * There is no SFCOM analog to this method.
@@ -809,7 +1334,7 @@ OGRErr OGR_G_AddGeometry( OGRGeometryH hGeom, OGRGeometryH hNewSubGeom )
  * the geometry type is illegal for the type of geometry container.
  */
 
-OGRErr OGR_G_AddGeometryDirectly( OGRGeometryH hGeom, 
+OGRErr OGR_G_AddGeometryDirectly( OGRGeometryH hGeom,
                                   OGRGeometryH hNewSubGeom )
 
 {
@@ -831,7 +1356,7 @@ OGRErr OGR_G_AddGeometryDirectly( OGRGeometryH hGeom,
     }
     else if( OGR_GT_IsSubClassOf(eType, wkbGeometryCollection) )
     {
-        eErr = ((OGRGeometryCollection *)hGeom)->addGeometryDirectly( 
+        eErr = ((OGRGeometryCollection *)hGeom)->addGeometryDirectly(
                                                 (OGRGeometry *) hNewSubGeom );
     }
 
@@ -853,7 +1378,7 @@ OGRErr OGR_G_AddGeometryDirectly( OGRGeometryH hGeom,
  *
  * There is no SFCOM analog to this method.
  *
- * This function is the same as the CPP method 
+ * This function is the same as the CPP method
  * OGRGeometryCollection::removeGeometry().
  *
  * @param hGeom the existing geometry to delete from.
@@ -862,7 +1387,7 @@ OGRErr OGR_G_AddGeometryDirectly( OGRGeometryH hGeom,
  *
  * @param bDelete if TRUE the geometry will be destroyed, otherwise it will
  * not.  The default is TRUE as the existing geometry is considered to own the
- * geometries in it. 
+ * geometries in it.
  *
  * @return OGRERR_NONE if successful, or OGRERR_FAILURE if the index is
  * out of range.
@@ -871,12 +1396,12 @@ OGRErr OGR_G_AddGeometryDirectly( OGRGeometryH hGeom,
 OGRErr OGR_G_RemoveGeometry( OGRGeometryH hGeom, int iGeom, int bDelete )
 
 {
-    VALIDATE_POINTER1( hGeom, "OGR_G_RemoveGeometry", 0 );
+    VALIDATE_POINTER1( hGeom, "OGR_G_RemoveGeometry", OGRERR_FAILURE );
 
     OGRwkbGeometryType eType = wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType());
     if( OGR_GT_IsSubClassOf(eType, wkbCurvePolygon) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                 "OGR_G_RemoveGeometry() not supported on polygons yet." );
         return OGRERR_UNSUPPORTED_OPERATION;
     }
@@ -898,12 +1423,12 @@ OGRErr OGR_G_RemoveGeometry( OGRGeometryH hGeom, int iGeom, int bDelete )
  * \brief Compute length of a geometry.
  *
  * Computes the length for OGRCurve or MultiCurve objects.
- * Undefined for all other geometry types (returns zero). 
+ * Undefined for all other geometry types (returns zero).
  *
  * This function utilizes the C++ get_Length() method.
  *
  * @param hGeom the geometry to operate on.
- * @return the lenght or 0.0 for unsupported geometry types.
+ * @return the length or 0.0 for unsupported geometry types.
  *
  * @since OGR 1.8.0
  */
@@ -943,12 +1468,12 @@ double OGR_G_Length( OGRGeometryH hGeom )
  * \brief Compute geometry area.
  *
  * Computes the area for an OGRLinearRing, OGRPolygon or OGRMultiPolygon.
- * Undefined for all other geometry types (returns zero). 
+ * Undefined for all other geometry types (returns zero).
  *
  * This function utilizes the C++ get_Area() methods such as
- * OGRPolygon::get_Area(). 
+ * OGRPolygon::get_Area().
  *
- * @param hGeom the geometry to operate on. 
+ * @param hGeom the geometry to operate on.
  * @return the area or 0.0 for unsupported geometry types.
  *
  * @since OGR 1.8.0
@@ -998,27 +1523,6 @@ double OGR_G_GetArea( OGRGeometryH hGeom )
     return OGR_G_Area( hGeom );
 }
 
-#ifndef OGR_ENABLED
-OGRGeometryH OGR_G_CreateGeometryFromJson( const char* )
-{
-    return NULL;
-}
-
-char* OGR_G_ExportToKML( OGRGeometryH, const char* pszAltitudeMode )
-{
-    return NULL;
-}
-
-char* OGR_G_ExportToJson( OGRGeometryH )
-{
-    return NULL;
-}
-char* OGR_G_ExportToJsonEx( OGRGeometryH, char** papszOptions )
-{
-    return NULL;
-}
-#endif
-
 /************************************************************************/
 /*                         OGR_G_HasCurveGeometry()                     */
 /************************************************************************/
@@ -1067,12 +1571,12 @@ int OGR_G_HasCurveGeometry( OGRGeometryH hGeom, int bLookForNonLinear )
  *
  * The reverse function is OGR_G_GetCurveGeometry().
  *
- * This method relates to the ISO SQL/MM Part 3 ICurve::CurveToLine() and 
+ * This method relates to the ISO SQL/MM Part 3 ICurve::CurveToLine() and
  * CurvePolygon::CurvePolyToPoly() methods.
  *
  * This function is the same as C++ method OGRGeometry::getLinearGeometry().
  *
- * @param hGeom the geometry to operate on. 
+ * @param hGeom the geometry to operate on.
  * @param dfMaxAngleStepSizeDegrees the largest step in degrees along the
  * arc, zero to use the default setting.
  * @param papszOptions options as a null-terminated list of strings or NULL.
@@ -1111,7 +1615,7 @@ OGRGeometryH CPL_DLL OGR_G_GetLinearGeometry( OGRGeometryH hGeom,
  *
  * This function is the same as C++ method OGRGeometry::getCurveGeometry().
  *
- * @param hGeom the geometry to operate on. 
+ * @param hGeom the geometry to operate on.
  * @param papszOptions options as a null-terminated list of strings.
  *                     Unused for now. Must be set to NULL.
  *
@@ -1192,7 +1696,7 @@ OGRGeometryH OGR_G_Value( OGRGeometryH hGeom, double dfDistance )
 
 void OGRSetNonLinearGeometriesEnabledFlag(int bFlag)
 {
-    bNonLinearGeometriesEnabled = bFlag;
+    bNonLinearGeometriesEnabled = (bFlag != FALSE);
 }
 
 /************************************************************************/
diff --git a/ogr/ogr_api.h b/ogr/ogr_api.h
index 5c9fca4..cd3704e 100644
--- a/ogr/ogr_api.h
+++ b/ogr/ogr_api.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_api.h 28900 2015-04-14 09:40:34Z rouault $
+ * $Id: ogr_api.h 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  C API for OGR Geometry, Feature, Layers, DataSource and drivers.
@@ -33,10 +33,10 @@
 
 /**
  * \file ogr_api.h
- * 
+ *
  * C API and defines for OGRFeature, OGRGeometry, and OGRDataSource
- * related classes. 
- * 
+ * related classes.
+ *
  * See also: ogr_geometry.h, ogr_feature.h, ogrsf_frmts.h, ogr_featurestyle.h
  */
 
@@ -55,14 +55,14 @@ typedef struct OGRGeometryHS *OGRGeometryH;
 typedef void *OGRGeometryH;
 #endif
 
-#ifndef _DEFINED_OGRSpatialReferenceH
-#define _DEFINED_OGRSpatialReferenceH
+#ifndef DEFINED_OGRSpatialReferenceH
+#define DEFINED_OGRSpatialReferenceH
 
 #ifdef DEBUG
 typedef struct OGRSpatialReferenceHS *OGRSpatialReferenceH;
 typedef struct OGRCoordinateTransformationHS *OGRCoordinateTransformationH;
 #else
-typedef void *OGRSpatialReferenceH;                               
+typedef void *OGRSpatialReferenceH;
 typedef void *OGRCoordinateTransformationH;
 #endif
 
@@ -72,34 +72,39 @@ struct _CPLXMLNode;
 
 /* From base OGRGeometry class */
 
-OGRErr CPL_DLL OGR_G_CreateFromWkb( unsigned char *, OGRSpatialReferenceH, 
+OGRErr CPL_DLL OGR_G_CreateFromWkb( unsigned char *, OGRSpatialReferenceH,
                                     OGRGeometryH *, int );
-OGRErr CPL_DLL OGR_G_CreateFromWkt( char **, OGRSpatialReferenceH, 
+OGRErr CPL_DLL OGR_G_CreateFromWkt( char **, OGRSpatialReferenceH,
                                     OGRGeometryH * );
-OGRErr CPL_DLL OGR_G_CreateFromFgf( unsigned char *, OGRSpatialReferenceH, 
+OGRErr CPL_DLL OGR_G_CreateFromFgf( unsigned char *, OGRSpatialReferenceH,
                                     OGRGeometryH *, int, int * );
 void   CPL_DLL OGR_G_DestroyGeometry( OGRGeometryH );
-OGRGeometryH CPL_DLL OGR_G_CreateGeometry( OGRwkbGeometryType );
-OGRGeometryH CPL_DLL 
-OGR_G_ApproximateArcAngles( 
+OGRGeometryH CPL_DLL OGR_G_CreateGeometry( OGRwkbGeometryType ) CPL_WARN_UNUSED_RESULT;
+OGRGeometryH CPL_DLL
+OGR_G_ApproximateArcAngles(
     double dfCenterX, double dfCenterY, double dfZ,
-    double dfPrimaryRadius, double dfSecondaryAxis, double dfRotation, 
+    double dfPrimaryRadius, double dfSecondaryAxis, double dfRotation,
     double dfStartAngle, double dfEndAngle,
-    double dfMaxAngleStepSizeDegrees );
+    double dfMaxAngleStepSizeDegrees ) CPL_WARN_UNUSED_RESULT;
 
-OGRGeometryH CPL_DLL OGR_G_ForceToPolygon( OGRGeometryH );
-OGRGeometryH CPL_DLL OGR_G_ForceToLineString( OGRGeometryH );
-OGRGeometryH CPL_DLL OGR_G_ForceToMultiPolygon( OGRGeometryH );
-OGRGeometryH CPL_DLL OGR_G_ForceToMultiPoint( OGRGeometryH );
-OGRGeometryH CPL_DLL OGR_G_ForceToMultiLineString( OGRGeometryH );
+OGRGeometryH CPL_DLL OGR_G_ForceToPolygon( OGRGeometryH ) CPL_WARN_UNUSED_RESULT;
+OGRGeometryH CPL_DLL OGR_G_ForceToLineString( OGRGeometryH ) CPL_WARN_UNUSED_RESULT;
+OGRGeometryH CPL_DLL OGR_G_ForceToMultiPolygon( OGRGeometryH ) CPL_WARN_UNUSED_RESULT;
+OGRGeometryH CPL_DLL OGR_G_ForceToMultiPoint( OGRGeometryH ) CPL_WARN_UNUSED_RESULT;
+OGRGeometryH CPL_DLL OGR_G_ForceToMultiLineString( OGRGeometryH ) CPL_WARN_UNUSED_RESULT;
 OGRGeometryH CPL_DLL OGR_G_ForceTo( OGRGeometryH hGeom,
                                     OGRwkbGeometryType eTargetType,
-                                    char** papszOptions );
+                                    char** papszOptions ) CPL_WARN_UNUSED_RESULT;
 
 int    CPL_DLL OGR_G_GetDimension( OGRGeometryH );
 int    CPL_DLL OGR_G_GetCoordinateDimension( OGRGeometryH );
+int    CPL_DLL OGR_G_CoordinateDimension( OGRGeometryH );
 void   CPL_DLL OGR_G_SetCoordinateDimension( OGRGeometryH, int );
-OGRGeometryH CPL_DLL OGR_G_Clone( OGRGeometryH );
+int    CPL_DLL OGR_G_Is3D( OGRGeometryH );
+int    CPL_DLL OGR_G_IsMeasured( OGRGeometryH );
+void   CPL_DLL OGR_G_Set3D( OGRGeometryH, int );
+void   CPL_DLL OGR_G_SetMeasured( OGRGeometryH, int );
+OGRGeometryH CPL_DLL OGR_G_Clone( OGRGeometryH ) CPL_WARN_UNUSED_RESULT;
 void   CPL_DLL OGR_G_GetEnvelope( OGRGeometryH, OGREnvelope * );
 void   CPL_DLL OGR_G_GetEnvelope3D( OGRGeometryH, OGREnvelope3D * );
 OGRErr CPL_DLL OGR_G_ImportFromWkb( OGRGeometryH, unsigned char *, int );
@@ -115,28 +120,29 @@ void   CPL_DLL OGR_G_DumpReadable( OGRGeometryH, FILE *, const char * );
 void   CPL_DLL OGR_G_FlattenTo2D( OGRGeometryH );
 void   CPL_DLL OGR_G_CloseRings( OGRGeometryH );
 
-OGRGeometryH CPL_DLL OGR_G_CreateFromGML( const char * );
-char   CPL_DLL *OGR_G_ExportToGML( OGRGeometryH );
-char   CPL_DLL *OGR_G_ExportToGMLEx( OGRGeometryH, char** papszOptions );
+OGRGeometryH CPL_DLL OGR_G_CreateFromGML( const char * ) CPL_WARN_UNUSED_RESULT;
+char   CPL_DLL *OGR_G_ExportToGML( OGRGeometryH ) CPL_WARN_UNUSED_RESULT;
+char   CPL_DLL *OGR_G_ExportToGMLEx( OGRGeometryH, char** papszOptions ) CPL_WARN_UNUSED_RESULT;
 
-OGRGeometryH CPL_DLL OGR_G_CreateFromGMLTree( const CPLXMLNode * );
-CPLXMLNode CPL_DLL *OGR_G_ExportToGMLTree( OGRGeometryH );
-CPLXMLNode CPL_DLL *OGR_G_ExportEnvelopeToGMLTree( OGRGeometryH );
+OGRGeometryH CPL_DLL OGR_G_CreateFromGMLTree( const CPLXMLNode * ) CPL_WARN_UNUSED_RESULT;
+CPLXMLNode CPL_DLL *OGR_G_ExportToGMLTree( OGRGeometryH ) CPL_WARN_UNUSED_RESULT;
+CPLXMLNode CPL_DLL *OGR_G_ExportEnvelopeToGMLTree( OGRGeometryH ) CPL_WARN_UNUSED_RESULT;
 
-char   CPL_DLL *OGR_G_ExportToKML( OGRGeometryH, const char* pszAltitudeMode );
+char   CPL_DLL *OGR_G_ExportToKML( OGRGeometryH, const char* pszAltitudeMode ) CPL_WARN_UNUSED_RESULT;
 
-char   CPL_DLL *OGR_G_ExportToJson( OGRGeometryH );
-char   CPL_DLL *OGR_G_ExportToJsonEx( OGRGeometryH, char** papszOptions );
-OGRGeometryH CPL_DLL OGR_G_CreateGeometryFromJson( const char* );
+char   CPL_DLL *OGR_G_ExportToJson( OGRGeometryH ) CPL_WARN_UNUSED_RESULT;
+char   CPL_DLL *OGR_G_ExportToJsonEx( OGRGeometryH, char** papszOptions ) CPL_WARN_UNUSED_RESULT;
+OGRGeometryH CPL_DLL OGR_G_CreateGeometryFromJson( const char* ) CPL_WARN_UNUSED_RESULT;
 
-void   CPL_DLL OGR_G_AssignSpatialReference( OGRGeometryH, 
+void   CPL_DLL OGR_G_AssignSpatialReference( OGRGeometryH,
                                              OGRSpatialReferenceH );
 OGRSpatialReferenceH CPL_DLL OGR_G_GetSpatialReference( OGRGeometryH );
 OGRErr CPL_DLL OGR_G_Transform( OGRGeometryH, OGRCoordinateTransformationH );
 OGRErr CPL_DLL OGR_G_TransformTo( OGRGeometryH, OGRSpatialReferenceH );
 
-OGRGeometryH CPL_DLL OGR_G_Simplify( OGRGeometryH hThis, double tolerance );
-OGRGeometryH CPL_DLL OGR_G_SimplifyPreserveTopology( OGRGeometryH hThis, double tolerance );
+OGRGeometryH CPL_DLL OGR_G_Simplify( OGRGeometryH hThis, double tolerance ) CPL_WARN_UNUSED_RESULT;
+OGRGeometryH CPL_DLL OGR_G_SimplifyPreserveTopology( OGRGeometryH hThis, double tolerance ) CPL_WARN_UNUSED_RESULT;
+OGRGeometryH CPL_DLL OGR_G_DelaunayTriangulation( OGRGeometryH hThis, double dfTolerance, int bOnlyEdges ) CPL_WARN_UNUSED_RESULT;
 
 void   CPL_DLL OGR_G_Segmentize(OGRGeometryH hGeom, double dfMaxLength );
 int    CPL_DLL OGR_G_Intersects( OGRGeometryH, OGRGeometryH );
@@ -149,24 +155,24 @@ int    CPL_DLL OGR_G_Within( OGRGeometryH, OGRGeometryH );
 int    CPL_DLL OGR_G_Contains( OGRGeometryH, OGRGeometryH );
 int    CPL_DLL OGR_G_Overlaps( OGRGeometryH, OGRGeometryH );
 
-OGRGeometryH CPL_DLL OGR_G_Boundary( OGRGeometryH );
-OGRGeometryH CPL_DLL OGR_G_ConvexHull( OGRGeometryH );
-OGRGeometryH CPL_DLL OGR_G_Buffer( OGRGeometryH, double, int );
-OGRGeometryH CPL_DLL OGR_G_Intersection( OGRGeometryH, OGRGeometryH );
-OGRGeometryH CPL_DLL OGR_G_Union( OGRGeometryH, OGRGeometryH );
-OGRGeometryH CPL_DLL OGR_G_UnionCascaded( OGRGeometryH );
-OGRGeometryH CPL_DLL OGR_G_PointOnSurface( OGRGeometryH );
+OGRGeometryH CPL_DLL OGR_G_Boundary( OGRGeometryH ) CPL_WARN_UNUSED_RESULT;
+OGRGeometryH CPL_DLL OGR_G_ConvexHull( OGRGeometryH ) CPL_WARN_UNUSED_RESULT;
+OGRGeometryH CPL_DLL OGR_G_Buffer( OGRGeometryH, double, int ) CPL_WARN_UNUSED_RESULT;
+OGRGeometryH CPL_DLL OGR_G_Intersection( OGRGeometryH, OGRGeometryH ) CPL_WARN_UNUSED_RESULT;
+OGRGeometryH CPL_DLL OGR_G_Union( OGRGeometryH, OGRGeometryH ) CPL_WARN_UNUSED_RESULT;
+OGRGeometryH CPL_DLL OGR_G_UnionCascaded( OGRGeometryH ) CPL_WARN_UNUSED_RESULT;
+OGRGeometryH CPL_DLL OGR_G_PointOnSurface( OGRGeometryH ) CPL_WARN_UNUSED_RESULT;
 /*OGRGeometryH CPL_DLL OGR_G_Polygonize( OGRGeometryH *, int);*/
 /*OGRGeometryH CPL_DLL OGR_G_Polygonizer_getCutEdges( OGRGeometryH *, int);*/
 /*OGRGeometryH CPL_DLL OGR_G_LineMerge( OGRGeometryH );*/
 
-OGRGeometryH CPL_DLL OGR_G_Difference( OGRGeometryH, OGRGeometryH );
-OGRGeometryH CPL_DLL OGR_G_SymDifference( OGRGeometryH, OGRGeometryH );
+OGRGeometryH CPL_DLL OGR_G_Difference( OGRGeometryH, OGRGeometryH ) CPL_WARN_UNUSED_RESULT;
+OGRGeometryH CPL_DLL OGR_G_SymDifference( OGRGeometryH, OGRGeometryH ) CPL_WARN_UNUSED_RESULT;
 double CPL_DLL OGR_G_Distance( OGRGeometryH, OGRGeometryH );
 double CPL_DLL OGR_G_Length( OGRGeometryH );
 double CPL_DLL OGR_G_Area( OGRGeometryH );
 int    CPL_DLL OGR_G_Centroid( OGRGeometryH, OGRGeometryH );
-OGRGeometryH CPL_DLL OGR_G_Value( OGRGeometryH, double dfDistance );
+OGRGeometryH CPL_DLL OGR_G_Value( OGRGeometryH, double dfDistance ) CPL_WARN_UNUSED_RESULT;
 
 void   CPL_DLL OGR_G_Empty( OGRGeometryH );
 int    CPL_DLL OGR_G_IsEmpty( OGRGeometryH );
@@ -174,8 +180,8 @@ int    CPL_DLL OGR_G_IsValid( OGRGeometryH );
 /*char    CPL_DLL *OGR_G_IsValidReason( OGRGeometryH );*/
 int    CPL_DLL OGR_G_IsSimple( OGRGeometryH );
 int    CPL_DLL OGR_G_IsRing( OGRGeometryH );
- 
-OGRGeometryH CPL_DLL OGR_G_Polygonize( OGRGeometryH );
+
+OGRGeometryH CPL_DLL OGR_G_Polygonize( OGRGeometryH ) CPL_WARN_UNUSED_RESULT;
 
 /* backward compatibility (non-standard methods) */
 int    CPL_DLL OGR_G_Intersect( OGRGeometryH, OGRGeometryH ) CPL_WARN_DEPRECATED("Non standard method. Use OGR_G_Intersects() instead");
@@ -190,22 +196,41 @@ int    CPL_DLL OGR_G_GetPoints( OGRGeometryH hGeom,
                                 void* pabyX, int nXStride,
                                 void* pabyY, int nYStride,
                                 void* pabyZ, int nZStride);
+int    CPL_DLL OGR_G_GetPointsZM( OGRGeometryH hGeom,
+                                  void* pabyX, int nXStride,
+                                  void* pabyY, int nYStride,
+                                  void* pabyZ, int nZStride,
+                                  void* pabyM, int nMStride);
 double CPL_DLL OGR_G_GetX( OGRGeometryH, int );
 double CPL_DLL OGR_G_GetY( OGRGeometryH, int );
 double CPL_DLL OGR_G_GetZ( OGRGeometryH, int );
-void   CPL_DLL OGR_G_GetPoint( OGRGeometryH, int iPoint, 
+double CPL_DLL OGR_G_GetM( OGRGeometryH, int );
+void   CPL_DLL OGR_G_GetPoint( OGRGeometryH, int iPoint,
                                double *, double *, double * );
+void   CPL_DLL OGR_G_GetPointZM( OGRGeometryH, int iPoint,
+                                 double *, double *, double *, double * );
 void   CPL_DLL OGR_G_SetPointCount( OGRGeometryH hGeom, int nNewPointCount );
-void   CPL_DLL OGR_G_SetPoint( OGRGeometryH, int iPoint, 
+void   CPL_DLL OGR_G_SetPoint( OGRGeometryH, int iPoint,
                                double, double, double );
-void   CPL_DLL OGR_G_SetPoint_2D( OGRGeometryH, int iPoint, 
+void   CPL_DLL OGR_G_SetPoint_2D( OGRGeometryH, int iPoint,
                                   double, double );
+void   CPL_DLL OGR_G_SetPointM( OGRGeometryH, int iPoint,
+                                double, double, double );
+void   CPL_DLL OGR_G_SetPointZM( OGRGeometryH, int iPoint,
+                                 double, double, double, double );
 void   CPL_DLL OGR_G_AddPoint( OGRGeometryH, double, double, double );
 void   CPL_DLL OGR_G_AddPoint_2D( OGRGeometryH, double, double );
+void   CPL_DLL OGR_G_AddPointM( OGRGeometryH, double, double, double );
+void   CPL_DLL OGR_G_AddPointZM( OGRGeometryH, double, double, double, double );
 void   CPL_DLL OGR_G_SetPoints( OGRGeometryH hGeom, int nPointsIn,
                                 void* pabyX, int nXStride,
                                 void* pabyY, int nYStride,
                                 void* pabyZ, int nZStride );
+void   CPL_DLL OGR_G_SetPointsZM( OGRGeometryH hGeom, int nPointsIn,
+                                  void* pabyX, int nXStride,
+                                  void* pabyY, int nYStride,
+                                  void* pabyZ, int nZStride,
+                                  void* pabyM, int nMStride );
 
 /* Methods for getting/setting rings and members collections */
 
@@ -218,17 +243,17 @@ OGRErr CPL_DLL OGR_G_RemoveGeometry( OGRGeometryH, int, int );
 int CPL_DLL OGR_G_HasCurveGeometry( OGRGeometryH, int bLookForNonLinear );
 OGRGeometryH CPL_DLL OGR_G_GetLinearGeometry( OGRGeometryH hGeom,
                                               double dfMaxAngleStepSizeDegrees,
-                                              char** papszOptions);
+                                              char** papszOptions) CPL_WARN_UNUSED_RESULT;
 OGRGeometryH CPL_DLL OGR_G_GetCurveGeometry( OGRGeometryH hGeom,
-                                             char** papszOptions );
+                                             char** papszOptions ) CPL_WARN_UNUSED_RESULT;
 
 OGRGeometryH CPL_DLL OGRBuildPolygonFromEdges( OGRGeometryH hLinesAsCollection,
-                                       int bBestEffort, 
-                                       int bAutoClose, 
+                                       int bBestEffort,
+                                       int bAutoClose,
                                        double dfTolerance,
-                                       OGRErr * peErr );
+                                       OGRErr * peErr ) CPL_WARN_UNUSED_RESULT;
 
-OGRErr CPL_DLL OGRSetGenerate_DB2_V72_BYTE_ORDER( 
+OGRErr CPL_DLL OGRSetGenerate_DB2_V72_BYTE_ORDER(
     int bGenerate_DB2_V72_BYTE_ORDER );
 
 int CPL_DLL OGRGetGenerate_DB2_V72_BYTE_ORDER(void);
@@ -270,7 +295,7 @@ int    CPL_DLL OGR_Fld_GetWidth( OGRFieldDefnH );
 void   CPL_DLL OGR_Fld_SetWidth( OGRFieldDefnH, int );
 int    CPL_DLL OGR_Fld_GetPrecision( OGRFieldDefnH );
 void   CPL_DLL OGR_Fld_SetPrecision( OGRFieldDefnH, int );
-void   CPL_DLL OGR_Fld_Set( OGRFieldDefnH, const char *, OGRFieldType, 
+void   CPL_DLL OGR_Fld_Set( OGRFieldDefnH, const char *, OGRFieldType,
                             int, int, OGRJustification );
 int    CPL_DLL OGR_Fld_IsIgnored( OGRFieldDefnH hDefn );
 void   CPL_DLL OGR_Fld_SetIgnored( OGRFieldDefnH hDefn, int );
@@ -349,8 +374,8 @@ OGRFeatureDefnH CPL_DLL OGR_F_GetDefnRef( OGRFeatureH );
 OGRErr CPL_DLL OGR_F_SetGeometryDirectly( OGRFeatureH, OGRGeometryH );
 OGRErr CPL_DLL OGR_F_SetGeometry( OGRFeatureH, OGRGeometryH );
 OGRGeometryH CPL_DLL OGR_F_GetGeometryRef( OGRFeatureH );
-OGRGeometryH CPL_DLL OGR_F_StealGeometry( OGRFeatureH );
-OGRFeatureH CPL_DLL OGR_F_Clone( OGRFeatureH );
+OGRGeometryH CPL_DLL OGR_F_StealGeometry( OGRFeatureH ) CPL_WARN_UNUSED_RESULT;
+OGRFeatureH CPL_DLL OGR_F_Clone( OGRFeatureH ) CPL_WARN_UNUSED_RESULT;
 int    CPL_DLL OGR_F_Equal( OGRFeatureH, OGRFeatureH );
 
 int    CPL_DLL OGR_F_GetFieldCount( OGRFeatureH );
@@ -387,9 +412,9 @@ void   CPL_DLL OGR_F_SetFieldDoubleList( OGRFeatureH, int, int, double * );
 void   CPL_DLL OGR_F_SetFieldStringList( OGRFeatureH, int, char ** );
 void   CPL_DLL OGR_F_SetFieldRaw( OGRFeatureH, int, OGRField * );
 void   CPL_DLL OGR_F_SetFieldBinary( OGRFeatureH, int, int, GByte * );
-void   CPL_DLL OGR_F_SetFieldDateTime( OGRFeatureH, int, 
+void   CPL_DLL OGR_F_SetFieldDateTime( OGRFeatureH, int,
                                        int, int, int, int, int, int, int );
-void   CPL_DLL OGR_F_SetFieldDateTimeEx( OGRFeatureH, int, 
+void   CPL_DLL OGR_F_SetFieldDateTimeEx( OGRFeatureH, int,
                                        int, int, int, int, int, float, int );
 
 int               CPL_DLL OGR_F_GetGeomFieldCount( OGRFeatureH hFeat );
@@ -419,6 +444,11 @@ OGRStyleTableH CPL_DLL OGR_F_GetStyleTable( OGRFeatureH );
 void   CPL_DLL OGR_F_SetStyleTableDirectly( OGRFeatureH, OGRStyleTableH );
 void   CPL_DLL OGR_F_SetStyleTable( OGRFeatureH, OGRStyleTableH );
 
+const char CPL_DLL *OGR_F_GetNativeData( OGRFeatureH );
+void CPL_DLL OGR_F_SetNativeData( OGRFeatureH, const char* );
+const char CPL_DLL *OGR_F_GetNativeMediaType( OGRFeatureH );
+void CPL_DLL OGR_F_SetNativeMediaType( OGRFeatureH, const char* );
+
 void   CPL_DLL OGR_F_FillUnsetWithDefault( OGRFeatureH hFeat,
                                            int bNotNullableOnly,
                                            char** papszOptions );
@@ -444,7 +474,7 @@ const char CPL_DLL* OGR_L_GetName( OGRLayerH );
 OGRwkbGeometryType CPL_DLL OGR_L_GetGeomType( OGRLayerH );
 OGRGeometryH CPL_DLL OGR_L_GetSpatialFilter( OGRLayerH );
 void   CPL_DLL OGR_L_SetSpatialFilter( OGRLayerH, OGRGeometryH );
-void   CPL_DLL OGR_L_SetSpatialFilterRect( OGRLayerH, 
+void   CPL_DLL OGR_L_SetSpatialFilterRect( OGRLayerH,
                                            double, double, double, double );
 void     CPL_DLL OGR_L_SetSpatialFilterEx( OGRLayerH, int iGeomField,
                                            OGRGeometryH hGeom );
@@ -453,12 +483,12 @@ void     CPL_DLL OGR_L_SetSpatialFilterRectEx( OGRLayerH, int iGeomField,
                                                double dfMaxX, double dfMaxY );
 OGRErr CPL_DLL OGR_L_SetAttributeFilter( OGRLayerH, const char * );
 void   CPL_DLL OGR_L_ResetReading( OGRLayerH );
-OGRFeatureH CPL_DLL OGR_L_GetNextFeature( OGRLayerH );
+OGRFeatureH CPL_DLL OGR_L_GetNextFeature( OGRLayerH ) CPL_WARN_UNUSED_RESULT;
 OGRErr CPL_DLL OGR_L_SetNextByIndex( OGRLayerH, GIntBig );
-OGRFeatureH CPL_DLL OGR_L_GetFeature( OGRLayerH, GIntBig );
-OGRErr CPL_DLL OGR_L_SetFeature( OGRLayerH, OGRFeatureH );
-OGRErr CPL_DLL OGR_L_CreateFeature( OGRLayerH, OGRFeatureH );
-OGRErr CPL_DLL OGR_L_DeleteFeature( OGRLayerH, GIntBig );
+OGRFeatureH CPL_DLL OGR_L_GetFeature( OGRLayerH, GIntBig )  CPL_WARN_UNUSED_RESULT;
+OGRErr CPL_DLL OGR_L_SetFeature( OGRLayerH, OGRFeatureH ) CPL_WARN_UNUSED_RESULT;
+OGRErr CPL_DLL OGR_L_CreateFeature( OGRLayerH, OGRFeatureH ) CPL_WARN_UNUSED_RESULT;
+OGRErr CPL_DLL OGR_L_DeleteFeature( OGRLayerH, GIntBig ) CPL_WARN_UNUSED_RESULT;
 OGRFeatureDefnH CPL_DLL OGR_L_GetLayerDefn( OGRLayerH );
 OGRSpatialReferenceH CPL_DLL OGR_L_GetSpatialRef( OGRLayerH );
 int    CPL_DLL OGR_L_FindFieldIndex( OGRLayerH, const char *, int bExactMatch );
@@ -474,8 +504,8 @@ OGRErr CPL_DLL OGR_L_DeleteField( OGRLayerH, int iField );
 OGRErr CPL_DLL OGR_L_ReorderFields( OGRLayerH, int* panMap );
 OGRErr CPL_DLL OGR_L_ReorderField( OGRLayerH, int iOldFieldPos, int iNewFieldPos );
 OGRErr CPL_DLL OGR_L_AlterFieldDefn( OGRLayerH, int iField, OGRFieldDefnH hNewFieldDefn, int nFlags );
-OGRErr CPL_DLL OGR_L_StartTransaction( OGRLayerH );
-OGRErr CPL_DLL OGR_L_CommitTransaction( OGRLayerH );
+OGRErr CPL_DLL OGR_L_StartTransaction( OGRLayerH )  CPL_WARN_UNUSED_RESULT;
+OGRErr CPL_DLL OGR_L_CommitTransaction( OGRLayerH )  CPL_WARN_UNUSED_RESULT;
 OGRErr CPL_DLL OGR_L_RollbackTransaction( OGRLayerH );
 int    CPL_DLL OGR_L_Reference( OGRLayerH );
 int    CPL_DLL OGR_L_Dereference( OGRLayerH );
@@ -505,7 +535,7 @@ OGRLayerH CPL_DLL OGR_DS_GetLayer( OGRDataSourceH, int );
 OGRLayerH CPL_DLL OGR_DS_GetLayerByName( OGRDataSourceH, const char * );
 OGRErr    CPL_DLL OGR_DS_DeleteLayer( OGRDataSourceH, int );
 OGRSFDriverH CPL_DLL OGR_DS_GetDriver( OGRDataSourceH );
-OGRLayerH CPL_DLL OGR_DS_CreateLayer( OGRDataSourceH, const char *, 
+OGRLayerH CPL_DLL OGR_DS_CreateLayer( OGRDataSourceH, const char *,
                                       OGRSpatialReferenceH, OGRwkbGeometryType,
                                       char ** );
 OGRLayerH CPL_DLL OGR_DS_CopyLayer( OGRDataSourceH, OGRLayerH, const char *,
@@ -530,7 +560,7 @@ OGRDataSourceH CPL_DLL OGR_Dr_Open( OGRSFDriverH, const char *, int ) CPL_WARN_U
 int CPL_DLL OGR_Dr_TestCapability( OGRSFDriverH, const char * );
 OGRDataSourceH CPL_DLL OGR_Dr_CreateDataSource( OGRSFDriverH, const char *,
                                                 char ** ) CPL_WARN_UNUSED_RESULT;
-OGRDataSourceH CPL_DLL OGR_Dr_CopyDataSource( OGRSFDriverH,  OGRDataSourceH, 
+OGRDataSourceH CPL_DLL OGR_Dr_CopyDataSource( OGRSFDriverH,  OGRDataSourceH,
                                               const char *, char ** ) CPL_WARN_UNUSED_RESULT;
 OGRErr CPL_DLL OGR_Dr_DeleteDataSource( OGRSFDriverH, const char * );
 
@@ -569,16 +599,16 @@ typedef void *OGRStyleToolH;
 OGRStyleMgrH CPL_DLL OGR_SM_Create(OGRStyleTableH hStyleTable) CPL_WARN_UNUSED_RESULT;
 void    CPL_DLL OGR_SM_Destroy(OGRStyleMgrH hSM);
 
-const char CPL_DLL *OGR_SM_InitFromFeature(OGRStyleMgrH hSM, 
+const char CPL_DLL *OGR_SM_InitFromFeature(OGRStyleMgrH hSM,
                                            OGRFeatureH hFeat);
-int     CPL_DLL OGR_SM_InitStyleString(OGRStyleMgrH hSM, 
+int     CPL_DLL OGR_SM_InitStyleString(OGRStyleMgrH hSM,
                                        const char *pszStyleString);
-int     CPL_DLL OGR_SM_GetPartCount(OGRStyleMgrH hSM, 
+int     CPL_DLL OGR_SM_GetPartCount(OGRStyleMgrH hSM,
                                     const char *pszStyleString);
-OGRStyleToolH CPL_DLL OGR_SM_GetPart(OGRStyleMgrH hSM, int nPartId, 
+OGRStyleToolH CPL_DLL OGR_SM_GetPart(OGRStyleMgrH hSM, int nPartId,
                                      const char *pszStyleString);
 int     CPL_DLL OGR_SM_AddPart(OGRStyleMgrH hSM, OGRStyleToolH hST);
-int     CPL_DLL OGR_SM_AddStyle(OGRStyleMgrH hSM, const char *pszStyleName, 
+int     CPL_DLL OGR_SM_AddStyle(OGRStyleMgrH hSM, const char *pszStyleName,
                                const char *pszStyleString);
 
 /* OGRStyleTool */
@@ -589,7 +619,7 @@ void    CPL_DLL OGR_ST_Destroy(OGRStyleToolH hST);
 OGRSTClassId CPL_DLL OGR_ST_GetType(OGRStyleToolH hST);
 
 OGRSTUnitId CPL_DLL OGR_ST_GetUnit(OGRStyleToolH hST);
-void    CPL_DLL OGR_ST_SetUnit(OGRStyleToolH hST, OGRSTUnitId eUnit, 
+void    CPL_DLL OGR_ST_SetUnit(OGRStyleToolH hST, OGRSTUnitId eUnit,
                                double dfGroundPaperScale);
 
 const char CPL_DLL *OGR_ST_GetParamStr(OGRStyleToolH hST, int eParam, int *bValueIsNull);
@@ -600,14 +630,14 @@ void    CPL_DLL OGR_ST_SetParamNum(OGRStyleToolH hST, int eParam, int nValue);
 void    CPL_DLL OGR_ST_SetParamDbl(OGRStyleToolH hST, int eParam, double dfValue);
 const char CPL_DLL *OGR_ST_GetStyleString(OGRStyleToolH hST);
 
-int CPL_DLL OGR_ST_GetRGBFromString(OGRStyleToolH hST, const char *pszColor, 
-                                    int *pnRed, int *pnGreen, int *pnBlue, 
+int CPL_DLL OGR_ST_GetRGBFromString(OGRStyleToolH hST, const char *pszColor,
+                                    int *pnRed, int *pnGreen, int *pnBlue,
                                     int *pnAlpha);
 
 /* OGRStyleTable */
 
 OGRStyleTableH  CPL_DLL OGR_STBL_Create( void ) CPL_WARN_UNUSED_RESULT;
-void    CPL_DLL OGR_STBL_Destroy( OGRStyleTableH hSTBL ); 
+void    CPL_DLL OGR_STBL_Destroy( OGRStyleTableH hSTBL );
 int     CPL_DLL OGR_STBL_AddStyle( OGRStyleTableH hStyleTable,
                                    const char *pszName,
                                    const char *pszStyleString);
diff --git a/ogr/ogr_apitut.dox b/ogr/ogr_apitut.dox
index 2e0d62d..ed14e21 100644
--- a/ogr/ogr_apitut.dox
+++ b/ogr/ogr_apitut.dox
@@ -305,7 +305,7 @@ The OGRLayer returned by GDALDataset::GetLayerByName() is also a reference
 to an internal layer owned by the GDALDataset so we don't need to delete
 it.  But we do need to delete the datasource in order to close the input file.
 Once again we do this with a custom delete method to avoid special win32 
-heap issus. 
+heap issues. 
 
 In C/C++ :
 \code
diff --git a/ogr/ogr_arch.dox b/ogr/ogr_arch.dox
index f552536..dc55b67 100644
--- a/ogr/ogr_arch.dox
+++ b/ogr/ogr_arch.dox
@@ -8,11 +8,11 @@ these same OGR classes could be used by an implementation of SFCORBA
 for instance or used directly by C++ programs wanting to use an OpenGIS
 simple features inspired API.<p>
 
-Because OGR is modelled on the OpenGIS simple features data model, it is
+Because OGR is modeled on the OpenGIS simple features data model, it is
 very helpful to review the SFCOM, or other simple features interface
 specifications which can be retrieved from the 
 <a href="http://www.opengeospatial.org">Open Geospatial Consortium</a> web site.  Data
-types, and method names are modelled on those from the interface 
+types, and method names are modeled on those from the interface 
 specifications.<p>
 
 \section ogr_arch_overview Class Overview
@@ -72,8 +72,8 @@ OGRMultiSurface classes.
 Additional intermediate abstract base classes contain functionality that
 could eventually be implemented by other geometry types.  These include
 OGRCurve (base class for OGRLineString) and OGRSurface (base class for 
-OGRPolygon).  Some intermediate interfaces modelled in the simple features
-abstract model and SFCOM are not modelled in OGR at this time.  In most 
+OGRPolygon).  Some intermediate interfaces modeled in the simple features
+abstract model and SFCOM are not modeled in OGR at this time.  In most 
 cases the methods are aggregated into other classes.<p>
 
 The OGRGeometryFactory is used to convert well known text, and well known
@@ -142,7 +142,7 @@ manner by the feature of that type (or feature class).<p>
 The feature id (FID) of a feature is intended to be a unique identifier for
 the feature within the layer it is a member of.  Freestanding features, or
 features not yet written to a layer may have a null (OGRNullFID) feature id. 
-The feature ids are modelled in OGR as a 64-bit integer (GDAL 2.0 or later);
+The feature ids are modeled in OGR as a 64-bit integer (GDAL 2.0 or later);
 however, this is not sufficiently expressive to model the natural feature ids in some
 formats.  For instance, the GML feature id is a string.<p>
 
@@ -240,7 +240,7 @@ A GDALDriver object is instantiated for each file format supported.
 The GDALDriver objects are registered with the GDALDriverManager, a
 singleton class that is normally used to open new datasets.<p>
 
-It is intended that a new GDALDriver object is instanciated and define function
+It is intended that a new GDALDriver object is instantiated and define function
 pointers for operations like Identify(), Open() for each
 file format to be supported (along with a file format specific 
 GDALDataset, and OGRLayer classes).<p>
diff --git a/ogr/ogr_capi_test.c b/ogr/ogr_capi_test.c
index ba01988..c21cf66 100644
--- a/ogr/ogr_capi_test.c
+++ b/ogr/ogr_capi_test.c
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: ogr_capi_test.c 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: ogr_capi_test.c 33714 2016-03-13 05:42:13Z goatbar $
  **********************************************************************
  * Copyright (c) 2003, Daniel Morissette
  *
@@ -107,8 +107,8 @@ int OGRCDump(const char *pszFname)
             OGRFieldDefnH fieldDefn;
 
             fieldDefn = OGR_FD_GetFieldDefn( layerDefn, j );
-            printf(" Field %d: %s (%s)\n", 
-                   j, OGR_Fld_GetNameRef(fieldDefn), 
+            printf(" Field %d: %s (%s)\n",
+                   j, OGR_Fld_GetNameRef(fieldDefn),
                    OGR_GetFieldTypeName(OGR_Fld_GetType(fieldDefn)) );
         }
         printf("\n");
@@ -222,7 +222,7 @@ int OGRCCreate(const char *pszFname)
     OGR_G_AddPoint(geometry, 12.34,  45.67, 0);
 
     OGR_F_SetGeometryDirectly(feature, geometry);
- 
+
     OGR_L_CreateFeature( layer, feature );
 
     /* Create a new polygon (square) */
@@ -241,7 +241,7 @@ int OGRCCreate(const char *pszFname)
     OGR_G_AddGeometryDirectly(geometry, ring);
 
     OGR_F_SetGeometryDirectly(feature, geometry);
- 
+
     OGR_L_CreateFeature( layer, feature );
 
     /* Close data source */
diff --git a/ogr/ogr_core.h b/ogr/ogr_core.h
index a1819df..7818137 100644
--- a/ogr/ogr_core.h
+++ b/ogr/ogr_core.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_core.h 28900 2015-04-14 09:40:34Z rouault $
+ * $Id: ogr_core.h 33680 2016-03-08 09:59:03Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Define some core portability services for cross-platform OGR code.
@@ -62,14 +62,13 @@ class CPL_DLL OGREnvelope
     double      MinY;
     double      MaxY;
 
-/* See http://trac.osgeo.org/gdal/ticket/5299 for details on this pragma */
-#if ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && !defined(_MSC_VER)) 
+#ifdef HAVE_GCC_DIAGNOSTIC_PUSH
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wfloat-equal"
 #endif
     int  IsInit() const { return MinX != 0 || MinY != 0 || MaxX != 0 || MaxY != 0; }
 
-#if ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && !defined(_MSC_VER))
+#ifdef HAVE_GCC_DIAGNOSTIC_PUSH
 #pragma GCC diagnostic pop
 #endif
 
@@ -103,7 +102,7 @@ class CPL_DLL OGREnvelope
             MinY = MaxY = dfY;
         }
     }
-    
+
     void Intersect( OGREnvelope const& sOther ) {
         if(Intersects(sOther))
         {
@@ -130,10 +129,10 @@ class CPL_DLL OGREnvelope
             MaxY = 0;
         }
     }
- 
+
     int Intersects(OGREnvelope const& other) const
     {
-        return MinX <= other.MaxX && MaxX >= other.MinX && 
+        return MinX <= other.MaxX && MaxX >= other.MinX &&
                MinY <= other.MaxY && MaxY >= other.MinY;
     }
 
@@ -175,7 +174,15 @@ class CPL_DLL OGREnvelope3D : public OGREnvelope
     double      MinZ;
     double      MaxZ;
 
+#ifdef HAVE_GCC_DIAGNOSTIC_PUSH
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
     int  IsInit() const { return MinX != 0 || MinY != 0 || MaxX != 0 || MaxY != 0 || MinZ != 0 || MaxZ != 0; }
+#ifdef HAVE_GCC_DIAGNOSTIC_PUSH
+#pragma GCC diagnostic pop
+#endif
+
     void Merge( OGREnvelope3D const& sOther ) {
         if( IsInit() )
         {
@@ -282,6 +289,21 @@ void CPL_DLL *OGRRealloc( void *, size_t );
 char CPL_DLL *OGRStrdup( const char * );
 void CPL_DLL OGRFree( void * );
 
+#ifdef STRICT_OGRERR_TYPE
+typedef enum
+{
+    OGRERR_NONE,
+    OGRERR_NOT_ENOUGH_DATA,
+    OGRERR_NOT_ENOUGH_MEMORY,
+    OGRERR_UNSUPPORTED_GEOMETRY_TYPE,
+    OGRERR_UNSUPPORTED_OPERATION,
+    OGRERR_CORRUPT_DATA,
+    OGRERR_FAILURE,
+    OGRERR_UNSUPPORTED_SRS,
+    OGRERR_INVALID_HANDLE,
+    OGRERR_NON_EXISTING_FEATURE
+} OGRErr;
+#else
 typedef int OGRErr;
 
 #define OGRERR_NONE                0
@@ -295,6 +317,8 @@ typedef int OGRErr;
 #define OGRERR_INVALID_HANDLE      8
 #define OGRERR_NON_EXISTING_FEATURE 9   /* added in GDAL 2.0 */
 
+#endif
+
 typedef int     OGRBoolean;
 
 /* -------------------------------------------------------------------- */
@@ -306,7 +330,7 @@ typedef int     OGRBoolean;
  * but are also returned from OGRGeometry::getGeometryType() to identify the
  * type of a geometry object.
  */
-typedef enum 
+typedef enum
 {
     wkbUnknown = 0,         /**< unknown type, non-standard */
 
@@ -330,6 +354,13 @@ typedef enum
                              *    ISO SQL/MM Part 3. GDAL >= 2.0 */
     wkbMultiCurve = 11,     /**< GeometryCollection of Curves, ISO SQL/MM Part 3. GDAL >= 2.0 */
     wkbMultiSurface = 12,   /**< GeometryCollection of Surfaces, ISO SQL/MM Part 3. GDAL >= 2.0 */
+    wkbCurve = 13,          /**< Curve (abstract type). ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbSurface = 14,        /**< Surface (abstract type). ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbPolyhedralSurface = 15,/**< a contiguous collection of polygons, which share common boundary segments,
+                               *   ISO SQL/MM Part 3. Reserved in GDAL >= 2.1 but not yet implemented */
+    wkbTIN = 16,              /**< a PolyhedralSurface consisting only of Triangle patches
+                               *    ISO SQL/MM Part 3. Reserved in GDAL >= 2.1 but not yet implemented */
+    wkbTriangle = 17,         /** < a Triangle. ISO SQL/MM Part 3. Reserved in GDAL >= 2.1 but not yet implemented */
 
     wkbNone = 100,          /**< non-standard, for pure attribute records */
     wkbLinearRing = 101,    /**< non-standard, just for createGeometry() */
@@ -339,6 +370,47 @@ typedef enum
     wkbCurvePolygonZ = 1010,    /**< wkbCurvePolygon with Z component. ISO SQL/MM Part 3. GDAL >= 2.0 */
     wkbMultiCurveZ = 1011,      /**< wkbMultiCurve with Z component. ISO SQL/MM Part 3. GDAL >= 2.0 */
     wkbMultiSurfaceZ = 1012,    /**< wkbMultiSurface with Z component. ISO SQL/MM Part 3. GDAL >= 2.0 */
+    wkbCurveZ = 1013,           /**< wkbCurve with Z component. ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbSurfaceZ = 1014,         /**< wkbSurface with Z component. ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbPolyhedralSurfaceZ = 1015,  /**< ISO SQL/MM Part 3. Reserved in GDAL >= 2.1 but not yet implemented */
+    wkbTINZ = 1016,                /**< ISO SQL/MM Part 3. Reserved in GDAL >= 2.1 but not yet implemented */
+    wkbTriangleZ = 1017,           /**< ISO SQL/MM Part 3. Reserved in GDAL >= 2.1 but not yet implemented */
+
+    wkbPointM = 2001,              /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbLineStringM = 2002,         /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbPolygonM = 2003,            /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbMultiPointM = 2004,         /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbMultiLineStringM = 2005,    /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbMultiPolygonM = 2006,       /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbGeometryCollectionM = 2007, /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbCircularStringM = 2008,     /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbCompoundCurveM = 2009,      /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbCurvePolygonM = 2010,       /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbMultiCurveM = 2011,         /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbMultiSurfaceM = 2012,       /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbCurveM = 2013,              /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbSurfaceM = 2014,            /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbPolyhedralSurfaceM = 2015,  /**< ISO SQL/MM Part 3. Reserved in GDAL >= 2.1 but not yet implemented */
+    wkbTINM = 2016,                /**< ISO SQL/MM Part 3. Reserved in GDAL >= 2.1 but not yet implemented */
+    wkbTriangleM = 2017,           /**< ISO SQL/MM Part 3. Reserved in GDAL >= 2.1 but not yet implemented */
+
+    wkbPointZM = 3001,              /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbLineStringZM = 3002,         /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbPolygonZM = 3003,            /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbMultiPointZM = 3004,         /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbMultiLineStringZM = 3005,    /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbMultiPolygonZM = 3006,       /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbGeometryCollectionZM = 3007, /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbCircularStringZM = 3008,     /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbCompoundCurveZM = 3009,      /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbCurvePolygonZM = 3010,       /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbMultiCurveZM = 3011,         /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbMultiSurfaceZM = 3012,       /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbCurveZM = 3013,              /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbSurfaceZM = 3014,            /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbPolyhedralSurfaceZM = 3015,  /**< ISO SQL/MM Part 3. Reserved in GDAL >= 2.1 but not yet implemented */
+    wkbTINZM = 3016,                /**< ISO SQL/MM Part 3. Reserved in GDAL >= 2.1 but not yet implemented */
+    wkbTriangleZM = 3017,           /**< ISO SQL/MM Part 3. Reserved in GDAL >= 2.1 but not yet implemented */
 
     wkbPoint25D = 0x80000001, /**< 2.5D extension as per 99-402 */
     wkbLineString25D = 0x80000002, /**< 2.5D extension as per 99-402 */
@@ -350,15 +422,11 @@ typedef enum
 
 } OGRwkbGeometryType;
 
-/* Outside of OGRwkbGeometryType since they are abstract types */
-#define wkbCurve            ((OGRwkbGeometryType)13)      /**< Curve (abstract type). SF-SQL 1.2 */
-#define wkbSurface          ((OGRwkbGeometryType)14)      /**< Surface (abstract type). SF-SQL 1.2 */
-
 /**
- * Output variants of WKB we support. 
+ * Output variants of WKB we support.
  *
  * 99-402 was a short-lived extension to SFSQL 1.1 that used a high-bit flag
- * to indicate the presence of Z coordiantes in a WKB geometry.
+ * to indicate the presence of Z coordinates in a WKB geometry.
  *
  * SQL/MM Part 3 and SFSQL 1.2 use offsets of 1000 (Z), 2000 (M) and 3000 (ZM)
  * to indicate the present of higher dimensional coordinates in a WKB geometry.
@@ -368,7 +436,7 @@ typedef enum
  * The codes are also found in §8.2.3 of <a href="http://portal.opengeospatial.org/files/?artifact_id=25355">
  * OGC 06-103r4 "OpenGIS® Implementation Standard for Geographic information - Simple feature access - Part 1: Common architecture", v1.2.1</a>
  */
-typedef enum 
+typedef enum
 {
     wkbVariantOldOgc, /**< Old-style 99-402 extended dimension (Z) WKB types */
     wkbVariantIso,  /**< SFSQL 1.2 and ISO SQL/MM Part 3 extended dimension (Z&M) WKB types */
@@ -387,13 +455,23 @@ typedef enum
 /** Return if the geometry type is a 3D geometry type
   * @since GDAL 2.0
   */
-#define wkbHasZ(x)     OGR_GT_HasZ(x)
+#define wkbHasZ(x)     (OGR_GT_HasZ(x) != 0)
 
 /** Return the 3D geometry type corresponding to the specified geometry type.
   * @since GDAL 2.0
   */
 #define wkbSetZ(x)     OGR_GT_SetZ(x)
 
+/** Return if the geometry type is a measured geometry type
+  * @since GDAL 2.1
+  */
+#define wkbHasM(x)     (OGR_GT_HasM(x) != 0)
+
+/** Return the measured geometry type corresponding to the specified geometry type.
+  * @since GDAL 2.1
+  */
+#define wkbSetM(x)     OGR_GT_SetM(x)
+
 #define ogrZMarker 0x21125711
 
 const char CPL_DLL * OGRGeometryTypeToName( OGRwkbGeometryType eType );
@@ -404,8 +482,10 @@ OGRwkbGeometryType CPL_DLL OGRMergeGeometryTypesEx( OGRwkbGeometryType eMain,
                                                     int bAllowPromotingToCurves );
 OGRwkbGeometryType CPL_DLL OGR_GT_Flatten( OGRwkbGeometryType eType );
 OGRwkbGeometryType CPL_DLL OGR_GT_SetZ( OGRwkbGeometryType eType );
+OGRwkbGeometryType CPL_DLL OGR_GT_SetM( OGRwkbGeometryType eType );
 OGRwkbGeometryType CPL_DLL OGR_GT_SetModifier( OGRwkbGeometryType eType, int bSetZ, int bSetM );
 int                CPL_DLL OGR_GT_HasZ( OGRwkbGeometryType eType );
+int                CPL_DLL OGR_GT_HasM( OGRwkbGeometryType eType );
 int                CPL_DLL OGR_GT_IsSubClassOf( OGRwkbGeometryType eType,
                                                 OGRwkbGeometryType eSuperType );
 int                CPL_DLL OGR_GT_IsCurve( OGRwkbGeometryType );
@@ -415,7 +495,7 @@ OGRwkbGeometryType CPL_DLL OGR_GT_GetCollection( OGRwkbGeometryType eType );
 OGRwkbGeometryType CPL_DLL OGR_GT_GetCurve( OGRwkbGeometryType eType );
 OGRwkbGeometryType CPL_DLL OGR_GT_GetLinear( OGRwkbGeometryType eType );
 
-typedef enum 
+typedef enum
 {
     wkbXDR = 0,         /* MSB/Sun/Motoroloa: Most Significant Byte First   */
     wkbNDR = 1          /* LSB/Intel/Vax: Least Significant Byte First      */
@@ -426,7 +506,7 @@ typedef enum
 #endif
 
 #ifdef HACK_FOR_IBM_DB2_V72
-#  define DB2_V72_FIX_BYTE_ORDER(x) ((((x) & 0x31) == (x)) ? (OGRwkbByteOrder) ((x) & 0x1) : (x))
+#  define DB2_V72_FIX_BYTE_ORDER(x) ((((x) & 0x31) == (x)) ? ((x) & 0x1) : (x))
 #  define DB2_V72_UNFIX_BYTE_ORDER(x) ((unsigned char) (OGRGeometry::bGenerate_DB2_V72_BYTE_ORDER ? ((x) | 0x30) : (x)))
 #else
 #  define DB2_V72_FIX_BYTE_ORDER(x) (x)
@@ -493,11 +573,19 @@ typedef enum
  */
 #define OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT       0x00000008
 
-/** Enable all validation tests.
+/** Allow geometry fields to have a different coordinate dimension that their
+ * geometry column type.
+ * This flag only makes sense if OGR_F_VAL_GEOM_TYPE is set too.
+ * Used by OGR_F_Validate().
+ * @since GDAL 2.1
+ */
+#define OGR_F_VAL_ALLOW_DIFFERENT_GEOM_DIM       0x00000010
+
+/** Enable all validation tests (except OGR_F_VAL_ALLOW_DIFFERENT_GEOM_DIM)
  * Used by OGR_F_Validate().
  * @since GDAL 2.0
  */
-#define OGR_F_VAL_ALL            0xFFFFFFFF
+#define OGR_F_VAL_ALL            (0x7FFFFFFF & ~OGR_F_VAL_ALLOW_DIFFERENT_GEOM_DIM)
 
 /************************************************************************/
 /*                  ogr_feature.h related definitions.                  */
@@ -509,7 +597,7 @@ typedef enum
  * field types can be known.
  */
 
-typedef enum 
+typedef enum
 {
   /** Simple 32bit integer */                   OFTInteger = 0,
   /** List of 32bit integers */                 OFTIntegerList = 1,
@@ -544,7 +632,7 @@ typedef enum
                                                         OFSTBoolean = 1,
     /** Signed 16-bit integer. Only valid for OFTInteger and OFTIntegerList. */
                                                         OFSTInt16 = 2,
-    /** Single precision (32 bit) floatint point. Only valid for OFTReal and OFTRealList. */
+    /** Single precision (32 bit) floating point. Only valid for OFTReal and OFTRealList. */
                                                         OFSTFloat32 = 3,
                                                         OFSTMaxSubType = 3
 } OGRFieldSubType;
@@ -553,7 +641,7 @@ typedef enum
  * Display justification for field values.
  */
 
-typedef enum 
+typedef enum
 {
     OJUndefined = 0,
     OJLeft = 1,
@@ -576,12 +664,12 @@ typedef union {
     GIntBig     Integer64;
     double      Real;
     char       *String;
-    
+
     struct {
         int     nCount;
         int     *paList;
     } IntegerList;
-    
+
     struct {
         int     nCount;
         GIntBig *paList;
@@ -591,7 +679,7 @@ typedef union {
         int     nCount;
         double  *paList;
     } RealList;
-    
+
     struct {
         int     nCount;
         char    **paList;
@@ -601,7 +689,7 @@ typedef union {
         int     nCount;
         GByte   *paData;
     } Binary;
-    
+
     struct {
         int     nMarker1;
         int     nMarker2;
@@ -613,7 +701,7 @@ typedef union {
         GByte   Day;
         GByte   Hour;
         GByte   Minute;
-        GByte   TZFlag; /* 0=unknown, 1=localtime(ambiguous), 
+        GByte   TZFlag; /* 0=unknown, 1=localtime(ambiguous),
                            100=GMT, 104=GMT+1, 80=GMT-5, etc */
         GByte   Reserved; /* must be set to 0 */
         float   Second; /* with millisecond accuracy. at the end of the structure, so as to keep it 12 bytes on 32 bit */
@@ -622,7 +710,7 @@ typedef union {
 
 #define OGR_GET_MS(floatingpoint_sec)   (int)(((floatingpoint_sec) - (int)(floatingpoint_sec)) * 1000 + 0.5)
 
-int CPL_DLL OGRParseDate( const char *pszInput, OGRField *psOutput, 
+int CPL_DLL OGRParseDate( const char *pszInput, OGRField *psOutput,
                           int nOptions );
 
 /* -------------------------------------------------------------------- */
@@ -645,6 +733,7 @@ int CPL_DLL OGRParseDate( const char *pszInput, OGRField *psOutput,
 #define OLCIgnoreFields        "IgnoreFields"
 #define OLCCreateGeomField     "CreateGeomField"
 #define OLCCurveGeometries     "CurveGeometries"
+#define OLCMeasuredGeometries  "MeasuredGeometries"
 
 #define ODsCCreateLayer        "CreateLayer"
 #define ODsCDeleteLayer        "DeleteLayer"
@@ -652,6 +741,7 @@ int CPL_DLL OGRParseDate( const char *pszInput, OGRField *psOutput,
 #define ODsCCurveGeometries    "CurveGeometries"
 #define ODsCTransactions       "Transactions"
 #define ODsCEmulatedTransactions "EmulatedTransactions"
+#define ODsCMeasuredGeometries "MeasuredGeometries"
 
 #define ODrCCreateDataSource   "CreateDataSource"
 #define ODrCDeleteDataSource   "DeleteDataSource"
@@ -700,9 +790,9 @@ typedef enum ogr_style_tool_units_id
  * List of parameters for use with OGRStylePen.
  */
 typedef enum ogr_style_tool_param_pen_id
-{  
-    OGRSTPenColor       = 0,                   
-    OGRSTPenWidth       = 1,                   
+{
+    OGRSTPenColor       = 0,
+    OGRSTPenWidth       = 1,
     OGRSTPenPattern     = 2,
     OGRSTPenId          = 3,
     OGRSTPenPerOffset   = 4,
@@ -710,24 +800,24 @@ typedef enum ogr_style_tool_param_pen_id
     OGRSTPenJoin        = 6,
     OGRSTPenPriority    = 7,
     OGRSTPenLast        = 8
-              
+
 } OGRSTPenParam;
 
 /**
  * List of parameters for use with OGRStyleBrush.
  */
 typedef enum ogr_style_tool_param_brush_id
-{  
-    OGRSTBrushFColor    = 0,                   
-    OGRSTBrushBColor    = 1,                   
+{
+    OGRSTBrushFColor    = 0,
+    OGRSTBrushBColor    = 1,
     OGRSTBrushId        = 2,
-    OGRSTBrushAngle     = 3,                   
+    OGRSTBrushAngle     = 3,
     OGRSTBrushSize      = 4,
     OGRSTBrushDx        = 5,
     OGRSTBrushDy        = 6,
     OGRSTBrushPriority  = 7,
     OGRSTBrushLast      = 8
-              
+
 } OGRSTBrushParam;
 
 
@@ -735,7 +825,7 @@ typedef enum ogr_style_tool_param_brush_id
  * List of parameters for use with OGRStyleSymbol.
  */
 typedef enum ogr_style_tool_param_symbol_id
-{  
+{
     OGRSTSymbolId       = 0,
     OGRSTSymbolAngle    = 1,
     OGRSTSymbolColor    = 2,
@@ -749,14 +839,14 @@ typedef enum ogr_style_tool_param_symbol_id
     OGRSTSymbolFontName = 10,
     OGRSTSymbolOColor   = 11,
     OGRSTSymbolLast     = 12
-              
+
 } OGRSTSymbolParam;
 
 /**
  * List of parameters for use with OGRStyleLabel.
  */
 typedef enum ogr_style_tool_param_label_id
-{  
+{
     OGRSTLabelFontName  = 0,
     OGRSTLabelSize      = 1,
     OGRSTLabelTextString = 2,
@@ -779,7 +869,7 @@ typedef enum ogr_style_tool_param_label_id
     OGRSTLabelHColor    = 19,
     OGRSTLabelOColor    = 20,
     OGRSTLabelLast      = 21
-              
+
 } OGRSTLabelParam;
 
 /* ------------------------------------------------------------------- */
@@ -798,12 +888,12 @@ const char CPL_DLL * CPL_STDCALL GDALVersionInfo( const char * );
 /** Return TRUE if GDAL library version at runtime matches nVersionMajor.nVersionMinor.
 
     The purpose of this method is to ensure that calling code will run with the GDAL
-    version it is compiled for. It is primarly intented for external plugins.
+    version it is compiled for. It is primarily indented for external plugins.
 
     @param nVersionMajor Major version to be tested against
     @param nVersionMinor Minor version to be tested against
     @param pszCallingComponentName If not NULL, in case of version mismatch, the method
-                                   will issue a failure mentionning the name of
+                                   will issue a failure mentioning the name of
                                    the calling component.
   */
 int CPL_DLL CPL_STDCALL GDALCheckVersion( int nVersionMajor, int nVersionMinor,
diff --git a/ogr/ogr_drivertut.dox b/ogr/ogr_drivertut.dox
index cbd1e35..a1d3bec 100644
--- a/ogr/ogr_drivertut.dox
+++ b/ogr/ogr_drivertut.dox
@@ -7,9 +7,10 @@
 
 \section odt_overall Overall Approach
 
-In general new formats are added to OGR by implementing format specific
-drivers with intanciating a GDALDriver and subclasses of GDALDatasetand OGRLayer.  The
-GDALDriver instance is registered with the GDALDriverManager at runtime.
+In general new formats are added to OGR by implementing format
+specific drivers with instantiating a GDALDriver and subclasses of
+GDALDataset and OGRLayer.  The GDALDriver instance is registered with
+the GDALDriverManager at runtime.
 
 Before following this tutorial to implement an OGR driver, please review 
 the <a href="ogr_arch.html">OGR Architecture</a> document carefully. 
@@ -100,7 +101,7 @@ static GDALDataset *OGRSPFDriverOpen( GDALOpenInfo* poOpenInfo )
         return NULL;
 
     OGRSPFDataSource   *poDS = new OGRSPFDataSource();
-    if( !poDS->Open( poOpenInfo->pszFilename, poOpenInfo->eAcces == GA_Update ) )
+    if( !poDS->Open( poOpenInfo->pszFilename, poOpenInfo->eAccess == GA_Update ) )
     {
         delete poDS;
         return NULL;
@@ -192,7 +193,7 @@ identified format as efficiently as possible, since many drivers may be
 invoked with files of the wrong format before the correct driver is 
 reached.  In this particular Open() we just test the file extension but this
 is generally a poor way of identifying a file format.  If available, checking
-"magic header values" or something similar is preferrable. 
+"magic header values" or something similar is preferable.
 
 In the case of the SPF format, update in place is not supported, 
 so we always fail if bUpdate is FALSE. 
diff --git a/ogr/ogr_expat.cpp b/ogr/ogr_expat.cpp
index 6e90d09..f4f5352 100644
--- a/ogr/ogr_expat.cpp
+++ b/ogr/ogr_expat.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_expat.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogr_expat.cpp 30134 2015-09-05 14:27:57Z rouault $
  *
  * Project:  OGR
  * Purpose:  Convenience function for parsing with Expat library
@@ -32,7 +32,7 @@
 #include "ogr_expat.h"
 #include "cpl_error.h"
 
-CPL_CVSID("$Id: ogr_expat.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogr_expat.cpp 30134 2015-09-05 14:27:57Z rouault $");
 
 #define OGR_EXPAT_MAX_ALLOWED_ALLOC 10000000
 
@@ -161,7 +161,10 @@ static int OGRExpatUnknownEncodingHandler (CPL_UNUSED void *unused_encodingHandl
     else if( EQUAL(name, "ISO-8859-15") )
         FillISO885915(info);
     else
+    {
+        CPLDebug("OGR", "Unhandled encoding %s", name);
         return XML_STATUS_ERROR;
+    }
 
     info->data    = NULL;
     info->convert = NULL;
diff --git a/ogr/ogr_feature.h b/ogr/ogr_feature.h
index f413ad9..454756c 100644
--- a/ogr/ogr_feature.h
+++ b/ogr/ogr_feature.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_feature.h 28968 2015-04-21 19:00:02Z rouault $
+ * $Id: ogr_feature.h 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Class for representing a whole feature, and layer schemas.
@@ -28,8 +28,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_FEATURE_H_INCLUDED
-#define _OGR_FEATURE_H_INCLUDED
+#ifndef OGR_FEATURE_H_INCLUDED
+#define OGR_FEATURE_H_INCLUDED
 
 #include "ogr_geometry.h"
 #include "ogr_featurestyle.h"
@@ -63,19 +63,19 @@ class CPL_DLL OGRFieldDefn
 {
   private:
     char                *pszName;
-    OGRFieldType        eType;                  
-    OGRJustification    eJustify;               
+    OGRFieldType        eType;
+    OGRJustification    eJustify;
     int                 nWidth;                 /* zero is variable */
     int                 nPrecision;
     char                *pszDefault;
-    
+
     int                 bIgnore;
     OGRFieldSubType     eSubType;
-    
+
     int                 bNullable;
 
     void                Initialize( const char *, OGRFieldType );
-    
+
   public:
                         OGRFieldDefn( const char *, OGRFieldType );
                         OGRFieldDefn( OGRFieldDefn * );
@@ -117,6 +117,9 @@ class CPL_DLL OGRFieldDefn
     void                SetNullable( int bNullableIn ) { bNullable = bNullableIn; }
 
     int                 IsSame( const OGRFieldDefn * ) const;
+
+  private:
+    CPL_DISALLOW_COPY_ASSIGN(OGRFieldDefn);
 };
 
 /************************************************************************/
@@ -171,6 +174,9 @@ public:
         void                SetNullable( int bNullableIn ) { bNullable = bNullableIn; }
 
         int                 IsSame( OGRGeomFieldDefn * );
+
+  private:
+    CPL_DISALLOW_COPY_ASSIGN(OGRGeomFieldDefn);
 };
 
 /************************************************************************/
@@ -194,14 +200,14 @@ public:
  * contain multiple geometry fields (OGRGeomFieldDefn class).
  *
  * It is reasonable for different translators to derive classes from
- * OGRFeatureDefn with additional translator specific information. 
+ * OGRFeatureDefn with additional translator specific information.
  */
 
 class CPL_DLL OGRFeatureDefn
 {
   protected:
     volatile int nRefCount;
-    
+
     int         nFieldCount;
     OGRFieldDefn **papoFieldDefn;
 
@@ -211,7 +217,7 @@ class CPL_DLL OGRFeatureDefn
     char        *pszFeatureClassName;
 
     int         bIgnoreStyle;
-    
+
   public:
                 OGRFeatureDefn( const char * pszName = NULL );
     virtual    ~OGRFeatureDefn();
@@ -252,6 +258,9 @@ class CPL_DLL OGRFeatureDefn
 
     static OGRFeatureDefn  *CreateFeatureDefn( const char *pszName = NULL );
     static void         DestroyFeatureDefn( OGRFeatureDefn * );
+
+  private:
+    CPL_DISALLOW_COPY_ASSIGN(OGRFeatureDefn);
 };
 
 /************************************************************************/
@@ -270,22 +279,26 @@ class CPL_DLL OGRFeature
     OGRFeatureDefn      *poDefn;
     OGRGeometry        **papoGeometries;
     OGRField            *pauFields;
+    char                *m_pszNativeData;
+    char                *m_pszNativeMediaType;
+
+    bool                SetFieldInternal( int i, OGRField * puValue );
 
-  protected: 
+  protected:
     char *              m_pszStyleString;
     OGRStyleTable       *m_poStyleTable;
     char *              m_pszTmpFieldValue;
-    
+
   public:
                         OGRFeature( OGRFeatureDefn * );
-    virtual            ~OGRFeature();                        
+    virtual            ~OGRFeature();
 
     OGRFeatureDefn     *GetDefnRef() { return poDefn; }
-    
+
     OGRErr              SetGeometryDirectly( OGRGeometry * );
     OGRErr              SetGeometry( OGRGeometry * );
     OGRGeometry        *GetGeometryRef();
-    OGRGeometry        *StealGeometry();
+    OGRGeometry        *StealGeometry() CPL_WARN_UNUSED_RESULT;
 
     int                 GetGeomFieldCount()
                                 { return poDefn->GetGeomFieldCount(); }
@@ -300,7 +313,7 @@ class CPL_DLL OGRFeature
     OGRErr              SetGeomFieldDirectly( int iField, OGRGeometry * );
     OGRErr              SetGeomField( int iField, OGRGeometry * );
 
-    OGRFeature         *Clone();
+    OGRFeature         *Clone() CPL_WARN_UNUSED_RESULT;
     virtual OGRBoolean  Equal( OGRFeature * poFeature );
 
     int                 GetFieldCount() { return poDefn->GetFieldCount(); }
@@ -310,9 +323,9 @@ class CPL_DLL OGRFeature
                                       { return poDefn->GetFieldIndex(pszName);}
 
     int                 IsFieldSet( int iField );
-    
+
     void                UnsetField( int iField );
-    
+
     OGRField           *GetRawFieldRef( int i ) { return pauFields + i; }
 
     int                 GetFieldAsInteger( int i );
@@ -324,13 +337,13 @@ class CPL_DLL OGRFeature
     const double       *GetFieldAsDoubleList( int i, int *pnCount );
     char              **GetFieldAsStringList( int i );
     GByte              *GetFieldAsBinary( int i, int *pnCount );
-    int                 GetFieldAsDateTime( int i, 
+    int                 GetFieldAsDateTime( int i,
                                      int *pnYear, int *pnMonth, int *pnDay,
-                                     int *pnHour, int *pnMinute, int *pnSecond, 
+                                     int *pnHour, int *pnMinute, int *pnSecond,
                                      int *pnTZFlag );
-    int                 GetFieldAsDateTime( int i, 
+    int                 GetFieldAsDateTime( int i,
                                      int *pnYear, int *pnMonth, int *pnDay,
-                                     int *pnHour, int *pnMinute, float *pfSecond, 
+                                     int *pnHour, int *pnMinute, float *pfSecond,
                                      int *pnTZFlag );
 
     int                 GetFieldAsInteger( const char *pszFName )
@@ -367,7 +380,7 @@ class CPL_DLL OGRFeature
     void                SetField( int i, OGRField * puValue );
     void                SetField( int i, int nCount, GByte * pabyBinary );
     void                SetField( int i, int nYear, int nMonth, int nDay,
-                                  int nHour=0, int nMinute=0, float fSecond=0.f, 
+                                  int nHour=0, int nMinute=0, float fSecond=0.f,
                                   int nTZFlag = 0 );
 
     void                SetField( const char *pszFName, int nValue )
@@ -391,12 +404,12 @@ class CPL_DLL OGRFeature
                            { SetField( GetFieldIndex(pszFName), papszValues); }
     void                SetField( const char *pszFName, OGRField * puValue )
                            { SetField( GetFieldIndex(pszFName), puValue ); }
-    void                SetField( const char *pszFName, 
+    void                SetField( const char *pszFName,
                                   int nYear, int nMonth, int nDay,
-                                  int nHour=0, int nMinute=0, float fSecond=0.f, 
+                                  int nHour=0, int nMinute=0, float fSecond=0.f,
                                   int nTZFlag = 0 )
-                           { SetField( GetFieldIndex(pszFName), 
-                                       nYear, nMonth, nDay, 
+                           { SetField( GetFieldIndex(pszFName),
+                                       nYear, nMonth, nDay,
                                        nHour, nMinute, fSecond, nTZFlag ); }
 
     GIntBig             GetFID() { return nFID; }
@@ -406,11 +419,11 @@ class CPL_DLL OGRFeature
 
     OGRErr              SetFrom( OGRFeature *, int = TRUE);
     OGRErr              SetFrom( OGRFeature *, int *, int = TRUE );
-    OGRErr              SetFieldsFrom( OGRFeature *, int *, int = TRUE ); 
+    OGRErr              SetFieldsFrom( OGRFeature *, int *, int = TRUE );
 
-    OGRErr              RemapFields( OGRFeatureDefn *poNewDefn, 
+    OGRErr              RemapFields( OGRFeatureDefn *poNewDefn,
                                      int *panRemapSource );
-    OGRErr              RemapGeomFields( OGRFeatureDefn *poNewDefn, 
+    OGRErr              RemapGeomFields( OGRFeatureDefn *poNewDefn,
                                      int *panRemapSource );
 
     int                 Validate( int nValidateFlags,
@@ -425,8 +438,16 @@ class CPL_DLL OGRFeature
     virtual void        SetStyleTable(OGRStyleTable *poStyleTable);
     virtual void        SetStyleTableDirectly(OGRStyleTable *poStyleTable);
 
+    const char         *GetNativeData() const { return m_pszNativeData; }
+    const char         *GetNativeMediaType() const { return m_pszNativeMediaType; }
+    void                SetNativeData( const char* pszNativeData );
+    void                SetNativeMediaType( const char* pszNativeMediaType );
+
     static OGRFeature  *CreateFeature( OGRFeatureDefn * );
     static void         DestroyFeature( OGRFeature * );
+
+  private:
+    CPL_DISALLOW_COPY_ASSIGN(OGRFeature);
 };
 
 /************************************************************************/
@@ -446,9 +467,9 @@ class CPL_DLL OGRFeatureQuery
     char          **FieldCollector( void *, char ** );
 
     GIntBig       *EvaluateAgainstIndices( swq_expr_node*, OGRLayer *, GIntBig& nFIDCount);
-    
+
     int         CanUseIndex( swq_expr_node*, OGRLayer * );
-    
+
   public:
                 OGRFeatureQuery();
                 ~OGRFeatureQuery();
@@ -458,7 +479,7 @@ class CPL_DLL OGRFeatureQuery
     int         Evaluate( OGRFeature * );
 
     GIntBig       *EvaluateAgainstIndices( OGRLayer *, OGRErr * );
-    
+
     int         CanUseIndex( OGRLayer * );
 
     char      **GetUsedFields();
@@ -466,4 +487,4 @@ class CPL_DLL OGRFeatureQuery
     void       *GetSWQExpr() { return pSWQExpr; }
 };
 
-#endif /* ndef _OGR_FEATURE_H_INCLUDED */
+#endif /* ndef OGR_FEATURE_H_INCLUDED */
diff --git a/ogr/ogr_feature_style.html b/ogr/ogr_feature_style.html
index 3f95cc3..c000031 100644
--- a/ogr/ogr_feature_style.html
+++ b/ogr/ogr_feature_style.html
@@ -206,7 +206,7 @@ The best way to get familiar with something is by example.
   A point symbol:
      "SYMBOL(c:#00FF00,id:"points.sym-45,ogr-sym-7")"
 
-  A text label, taking the text string from the "text_string" 
+  A text label, taking the text string from the "text_string"
   attribute field:
      "LABEL(f:"Times New Roman",s:12pt,t:{text_string})"</PRE>
 Here is what a style table that contains all the above styles could look
@@ -260,7 +260,7 @@ tool to define a portion of the complete graphical representation:
 
   <style_part> =   <tool_name>([<tool_param>[,<tool_param>[,...]]])
 
-  <tool_name> =    name of a drawing tool, for now: PEN | BRUSH | SYMBOL | LABEL 
+  <tool_name> =    name of a drawing tool, for now: PEN | BRUSH | SYMBOL | LABEL
 
   <tool_param> =   <param_name>:<param_value>
 
@@ -359,14 +359,14 @@ in)
 
   <TR>
     <TD ALIGN=CENTER>id</TD>
-    <TD><B>Comma-delimited list of Pen Names or Ids</B> - For systems that 
-identify pens with a name or an id.  The names in the comma-delimited list 
+    <TD><B>Comma-delimited list of Pen Names or Ids</B> - For systems that
+identify pens with a name or an id.  The names in the comma-delimited list
 of ids are scanned until one is recognized by the target system.
       <P>
 Pen Ids can be either system-specific ids (see further below) or be one
 of the pre-defined OGR pen ids for well known line patterns.  The id
-parameter should always include one of the OGR ids at the end of the 
-comma-delimited list of ids so that an application never has to rely on 
+parameter should always include one of the OGR ids at the end of the
+comma-delimited list of ids so that an application never has to rely on
 understanding system-specific ids.
       <P>
 Here is the current list of OGR pen ids (this could grow over time):<BR>
@@ -377,24 +377,24 @@ Here is the current list of OGR pen ids (this could grow over time):<BR>
         <LI>ogr-pen-3: short-dash
         <LI>ogr-pen-4: long-dash
         <LI>ogr-pen-5: dot
-line 
+line
         <LI>ogr-pen-6: dash-dot
-line 
+line
         <LI>ogr-pen-7: dash-dot-dot
 line
         <LI>ogr-pen-8: alternate-line (sets every other pixel)
 
       </UL>
       <P>
-System-specific ids are very 
-likely to be meaningful only to that specific system that created them.  
-The ids should start with the system's name, followed by a dash (-), 
-followed by whatever information is meaningful to that system (a number, 
+System-specific ids are very
+likely to be meaningful only to that specific system that created them.
+The ids should start with the system's name, followed by a dash (-),
+followed by whatever information is meaningful to that system (a number,
 a name, a filename, etc.).<BR>
 e.g. "mapinfo-5", or "mysoft-lines.sym-123", or "othersystems-funnyline"
       <P>
-System-specific ids are allowed in order to prevent loss of information when 
-dealing with data from systems that store line patterns in external files 
+System-specific ids are allowed in order to prevent loss of information when
+dealing with data from systems that store line patterns in external files
 or that have their own pre-defined set of line styles.  (To do a MapInfo MIF
 to TAB translation without any loss for instance.)
       <P>Examples: <BR>
@@ -489,40 +489,40 @@ list can eventually grow and that all parameters are optional:
 <TD ALIGN=CENTER>id</TD>
 
 <TD>
-      <P><B>Brush Name or Brush Id</B> - Comma-delimited list of brush names or ids.  The names in the comma-delimited list 
+      <P><B>Brush Name or Brush Id</B> - Comma-delimited list of brush names or ids.  The names in the comma-delimited list
 of ids are scanned until one is recognized by the target system.
 </P>
       <P>
 Brush  Ids can be either system-specific ids (see further below) or be one
 of the pre-defined OGR brush  ids for well known brush patterns.  The id
-parameter should always include one of the OGR ids at the end of the 
-comma-delimited list of ids so that an application never has to rely on 
+parameter should always include one of the OGR ids at the end of the
+comma-delimited list of ids so that an application never has to rely on
 understanding system-specific ids.
       <P>
 Here is the current list of OGR brush ids (this could grow over time):<BR>
       <UL>
         <LI>ogr-brush-0: solid  (the default when no id is provided)
         <LI>ogr-brush-1: null brush (transparent - no fill)
-        <LI>ogr-brush-2:  horizontal hatch /* ------ */	
-        <LI>ogr-brush-3: vertical hatch /* |||||| */          
-	      <LI>ogr-brush-4: fdiagonal hatch /* \\\\\\ */         
-        <LI>ogr-brush-5: bdiagonal hatch /* ////// */         	
-        <LI>ogr-brush-6: cross hatch /* ++++++ */             	
-        <LI>ogr-brush-7:  diagcross hatch /* xxxxxx */              
+        <LI>ogr-brush-2:  horizontal hatch /* ------ */
+        <LI>ogr-brush-3: vertical hatch /* |||||| */
+	      <LI>ogr-brush-4: fdiagonal hatch /* \\\\\\ */
+        <LI>ogr-brush-5: bdiagonal hatch /* ////// */
+        <LI>ogr-brush-6: cross hatch /* ++++++ */
+        <LI>ogr-brush-7:  diagcross hatch /* xxxxxx */
       </UL>
       <P>
-Like with Pen Ids, system-specific brush ids are very 
-likely to be meaningful only to that specific system that created them.  
-The ids should start with the system's name, followed by a dash (-), 
-followed by whatever information is meaningful to that system (a number, 
+Like with Pen Ids, system-specific brush ids are very
+likely to be meaningful only to that specific system that created them.
+The ids should start with the system's name, followed by a dash (-),
+followed by whatever information is meaningful to that system (a number,
 a name, a filename, etc.).
       <P>The following conventions will be used for common system-specific brush ids:</P>
       <UL>
         <LI>"bmp-filename.bmp" for Windows BMP patterns
         <LI>??? any others, e.g. vector symbols, WMF, ???
-        
+
       </UL>
-    
+
       </TD>
 </TR>
 
@@ -590,19 +590,19 @@ list can eventually grow and that all parameters are optional:
 <TD ALIGN=CENTER>id</TD>
 
     <TD>
-      <P><B>Symbol Name or Id</B> - Comma-delimited list of symbol names or ids.  The names in the comma-delimited list 
+      <P><B>Symbol Name or Id</B> - Comma-delimited list of symbol names or ids.  The names in the comma-delimited list
 of ids are scanned until one is recognized by the target system.
 </P>
       <P>
 Symbol  Ids can be either system-specific ids (see further below) or be one
 of the pre-defined OGR symbol  ids for well known symbols.  The id
-parameter should always include one of the OGR ids at the end of the 
-comma-delimited list of ids so that an application never has to rely on 
+parameter should always include one of the OGR ids at the end of the
+comma-delimited list of ids so that an application never has to rely on
 understanding system-specific ids.
       <P>
 Here is the current list of OGR symbol ids (this could grow over time):<BR>
       <UL>
-        <LI>ogr-sym-0: cross (+)        
+        <LI>ogr-sym-0: cross (+)
         <LI>ogr-sym-1: diagcross (X)
         <LI>ogr-sym-2: circle (not filled)
         <LI>ogr-sym-3: circle (filled)
@@ -613,19 +613,19 @@ Here is the current list of OGR symbol ids (this could grow over time):<BR>
         <LI>ogr-sym-8: star (not filled)
         <LI>ogr-sym-9: star (filled)
         <LI>ogr-sym-10: vertical bar (can be rotated using angle attribute to produce diag bar)
-        <LI>??? should any other common be included ???             
+        <LI>??? should any other common be included ???
       </UL>
       <P>
-Like with Pen Ids, system-specific symbol ids are very 
-likely to be meaningful only to that specific system that created them.  
-The ids should start with the system's name, followed by a dash (-), 
-followed by whatever information is meaningful to that system (a number, 
+Like with Pen Ids, system-specific symbol ids are very
+likely to be meaningful only to that specific system that created them.
+The ids should start with the system's name, followed by a dash (-),
+followed by whatever information is meaningful to that system (a number,
 a name, a filename, etc.).
       <P>The following conventions will be used for common system-specific symbol ids:</P>
       <UL>
         <LI>"bmp-filename.bmp" for Windows BMP symbols
         <LI>??? any others, e.g. vector symbols, WMF, ???
-        
+
       </UL>
       </TD>
 </TR>
@@ -729,7 +729,7 @@ this list can eventually grow and all parameters are optional:
 
   <TR>
     <TD ALIGN=CENTER>f</TD>
-    <TD><B>Font Name</B> - 
+    <TD><B>Font Name</B> -
 <BR>
       Comma-delimited list of fonts names.  works like the HTML FONT tag: the list of font names is scanned until a supported font name is encountered.
 <BR>
@@ -789,7 +789,7 @@ it is escaped with a antislash (\) character before it.
 
   <TR>
     <TD ALIGN=CENTER>w</TD>
-    <TD><B>Stretch</B> - The stretch factor changes the width of all 
+    <TD><B>Stretch</B> - The stretch factor changes the width of all
 	    characters in the font by factor percent. For example, setting
 	    factor to 150 results in all characters in the font being 1.5
 	    times (i.e. 150%) wider. The default stretch factor is 100.</TD>
@@ -864,7 +864,7 @@ line along which it is placed.  If the offset is negative then the label will be
   </TR>
   <TR>
     <TD ALIGN=CENTER>bo</TD>
-    <TD><B>Bold</B> - 
+    <TD><B>Bold</B> -
 <BR>
       If specified, then text will be bold.</TD>
   </TR>
@@ -876,7 +876,7 @@ line along which it is placed.  If the offset is negative then the label will be
     <TD ALIGN=CENTER>un</TD>
     <TD><B>Underline</B> -</TD>
   </TR>
-  
+
 
   <TR>
     <TD ALIGN=CENTER>l</TD>
@@ -971,9 +971,9 @@ The OGRStyle class knows how to parse a style string,</LI>
     } OGRSTUnitId;
 
     typedef enum ogr_style_tool_param_pen_id
-    {  
-      OGRSTPenColor = 0,                   
-      OGRSTPenWidth,                   
+    {
+      OGRSTPenColor = 0,
+      OGRSTPenWidth,
       OGRSTPenPattern,
       OGRSTPenId,
       OGRSTPenPerOffset,
@@ -981,27 +981,27 @@ The OGRStyle class knows how to parse a style string,</LI>
       OGRSTPenJoin,
       OGRSTPenPriority,
       OGRSTPenLast
-              
+
     } OGRSTPenParam;
 
     typedef enum ogr_style_tool_param_brush_id
-    {  
-      OGRSTBrushFColor = 0,                   
-      OGRSTBrushBColor,                   
+    {
+      OGRSTBrushFColor = 0,
+      OGRSTBrushBColor,
       OGRSTBrushId,
-      OGRSTBrushAngle,                   
+      OGRSTBrushAngle,
       OGRSTBrushSize,
       OGRSTBrushDx,
       OGRSTBrushDy,
       OGRSTBrushPriority,
       OGRSTBrushLast
-              
+
     } OGRSTBrushParam;
 
 
 
     typedef enum ogr_style_tool_param_symbol_id
-    {  
+    {
       OGRSTSymbolId = 0,
       OGRSTSymbolAngle,
       OGRSTSymbolColor,
@@ -1013,11 +1013,11 @@ The OGRStyle class knows how to parse a style string,</LI>
       OGRSTSymbolOffset,
       OGRSTSymbolPriority,
       OGRSTSymbolLast
-              
+
     } OGRSTSymbolParam;
 
     typedef enum ogr_style_tool_param_label_id
-    {  
+    {
       OGRSTLabelFontName = 0,
       OGRSTLabelSize,
       OGRSTLabelTextString,
@@ -1034,54 +1034,54 @@ The OGRStyle class knows how to parse a style string,</LI>
       OGRSTLabelUnderline,
       OGRSTLabelPriority,
       OGRSTLabelLast
-              
+
     } OGRSTLabelParam;
 
-    //Every time a pszStyleString given in parameter is NULL, 
+    //Every time a pszStyleString given in parameter is NULL,
       the StyleString defined in the Mgr will be use.
 
 class OGRStyleMgr
 {
     OGRStyleMgr(OGRStyleTable *poDataSetStyleTable =NULL);
- 
+
     GBool SetFeatureStyleString(OGRFeature *,const char *pszStyleString=NULL,
 				GBool bNoMatching = FALSE);
-    /*it will set in the given feature the pszStyleString with 
-	    the style or will set the style name found in 
+    /*it will set in the given feature the pszStyleString with
+	    the style or will set the style name found in
             dataset StyleTable (if bNoMatching == FALSE)*/
-	      
+
     const char *InitFromFeature(OGRFeature *);
     GBool InitStyleString(const char *pszStyleString = NULL);
-    
+
     const char *GetStyleName(const char *pszStyleString= NULL);
     const char *GetStyleByName(const char *pszStyleName);
-    
+
     GBool AddStyle(const char *pszStyleName, const char *pszStyleString=NULL);
-    
+
     const char *GetStyleString(OGRFeature * = NULL);
- 
+
     GBool AddPart(OGRStyleTool *);
     GBool AddPart(const char *);
 
     int GetPartCount(const char *pszStyleString = NULL);
     OGRStyleTool *GetPart(int hPartId, const char *pszStyleString = NULL);
-        
+
     OGRStyleTable *GetDataSetStyleTable(){return m_poDataSetStyleTable;}
-    
+
     OGRStyleTool *CreateStyleToolFromStyleString(const char *pszStyleString);
 
-}; 
+};
 
 class OGRStyleTool
 {
     OGRStyleTool(OGRSTClassId eClassId);
-    GBool GetRGBFromString(const char *pszColor, int &nRed, int &nGreen, 
+    GBool GetRGBFromString(const char *pszColor, int &nRed, int &nGreen,
 			   int &nBlue);
-    int   GetSpecificId(const char *pszId, const char *pszWanted); 
+    int   GetSpecificId(const char *pszId, const char *pszWanted);
     OGRSTClassId GetType();
     void SetUnit(OGRSTUnitId,double dfScale = 1.0); //the dfScale will be
          //used if we are working with Ground Unit ( ground = paper * scale);
-    OGRSTUnitId GetUnit(){return m_eUnit;}   
+    OGRSTUnitId GetUnit(){return m_eUnit;}
     void SetStyleString(const char *pszStyleString);
 };
 
@@ -1090,7 +1090,7 @@ class OGRStylePen : public OGRStyleTool
    /**********************************************************************/
     /* Explicit fct for all parameters defined in the Drawing tools  Pen */
     /**********************************************************************/
-     
+
     const char *Color(GBool &bDefault)
     void SetColor(const char *pszColor)
     double Width(GBool &bDefault)
@@ -1113,11 +1113,11 @@ class OGRStylePen : public OGRStyleTool
     inline const char *GetParamStr(OGRSTPenParam eParam, GBool &bValueIsNull)
     inline int GetParamNum(OGRSTPenParam eParam,GBool &bValueIsNull)
     inline double GetParamDbl(OGRSTPenParam eParam,GBool &bValueIsNull)
-    inline void SetParamStr(OGRSTPenParam eParam, 
+    inline void SetParamStr(OGRSTPenParam eParam,
 	                        const char *pszParamString)
     inline void SetParamNum(OGRSTPenParam eParam, int nParam)
     inline void SetParamDbl(OGRSTPenParam eParam, double dfParam)
-   
+
 };
 
 
@@ -1142,16 +1142,16 @@ class OGRStyleBrush : public OGRStyleTool
     void SetSpacingY(double dfY)
     int  Priority(GBool &bDefault)
     void SetPriority(int nPriority)
-    
+
     /*****************************************************************/
-    
+
 };
 class OGRStyleSymbol : public OGRStyleTool
 {
     /*****************************************************************/
     /* Explicit fct for all parameters defined in the Drawing tools */
     /*****************************************************************/
-    
+
     const char *Id(GBool &bDefault)
     void  SetId(const char *pszId)
     double Angle(GBool &bDefault)
@@ -1172,9 +1172,9 @@ class OGRStyleSymbol : public OGRStyleTool
     void SetPerp(double dfPerp)
     int  Priority(GBool &bDefault)
     void SetPriority(int nPriority)
-    
+
     /*****************************************************************/
-    
+
 };
 
 class OGRStyleLabel : public OGRStyleTool
@@ -1183,7 +1183,7 @@ class OGRStyleLabel : public OGRStyleTool
     /*****************************************************************/
     /* Explicit fct for all parameters defined in the Drawing tools */
     /*****************************************************************/
-    
+
     const char *FontName(GBool &bDefault)
     void  SetFontName(const char *pszFontName)
     double Size(GBool &bDefault)
@@ -1215,18 +1215,18 @@ class OGRStyleLabel : public OGRStyleTool
     int  Priority(GBool &bDefault)
     void SetPriority(int nPriority)
     /*****************************************************************/
-    
+
 };
 
 class OGRStyleTable
 {
-    
+
     OGRStyleTable();
 
     GBool AddStyle(const char *pszName,const char *pszStyleString);
     GBool RemoveStyle(const char *pszName);
     GBool ModifyStyle(const char *pszName, const char *pszStyleString);
-    
+
     GBool SaveStyleTable(const char *pszFilename);
     GBool LoadStyleTable(const char *pszFilename);
     const char *Find(const char *pszStyleString);
@@ -1252,7 +1252,7 @@ Usage examples:
    }
 
    oStyleTable->SaveStyleTable("ttt.tbl");
-   
+
 
    // Create a New style in the style table
 
@@ -1262,7 +1262,7 @@ Usage examples:
    poStyleMgr->AddStyle("@Name");
    poStyleMgr->SetFeatureStyleString(poFeature,"@Name",TRUE);
    oStyleTable->SaveStyleTable("ttt.tbl");
-   
+
 
    // Create a New style in the style table
 
@@ -1272,7 +1272,7 @@ Usage examples:
    poStylePen->SetUnit(OGRSTUPixel);
    poStylePen->SetWidth(10.0);
    poStyleMgr->AddPart(poStylePen);
-   
+
    delete poStylePen;
 
 
@@ -1281,7 +1281,7 @@ Usage examples:
    OGRStyleTool  *poStyleTool;
 
    poStyleMgr->GetStyleString(poFeature);
-   
+
    for (i=0;i<poStyleMgr->GetPartCount();i++)
    {
       poStyleTool = GetPart(i);
@@ -1291,7 +1291,7 @@ Usage examples:
             poStylePen = (OGRStylePen *)poStyleTool;
             pszColor = poStylePen->Color(bDefault);
             if (bDefault == FALSE)
-              poStylePen->GetRGBFromString(pszColor, nRed, nGree, 
+              poStylePen->GetRGBFromString(pszColor, nRed, nGreen,
 	                                   nBlue, nTrans);
             else
               // Color not defined;
@@ -1300,8 +1300,8 @@ Usage examples:
             if (bDefault == FALSE)
               // Use dfWidth
             else
-              // dfWidth not defined                
-     
+              // dfWidth not defined
+
            :
            :
        }
@@ -1313,4 +1313,4 @@ Usage examples:
 </P>
 <P>
 <HR WIDTH=50%>
-</BODY></HTML>    
+</BODY></HTML>
diff --git a/ogr/ogr_featurestyle.h b/ogr/ogr_featurestyle.h
index 8bdb04c..b3ef911 100644
--- a/ogr/ogr_featurestyle.h
+++ b/ogr/ogr_featurestyle.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_featurestyle.h 19442 2010-04-18 00:02:37Z mloskot $
+ * $Id: ogr_featurestyle.h 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Define of Feature Representation
@@ -73,8 +73,9 @@ typedef struct ogr_style_value
 } OGRStyleValue;
 
 
-//Everytime a pszStyleString gived in parameter is NULL, 
-//    the StyleString defined in the Mgr will be use.
+// Every time a pszStyleString given in parameter is NULL,
+// the StyleString defined in the Mgr will be use.
+
 /**
  * This class represents a style table
  */
@@ -92,7 +93,7 @@ class CPL_DLL OGRStyleTable
     GBool AddStyle(const char *pszName,const char *pszStyleString);
     GBool RemoveStyle(const char *pszName);
     GBool ModifyStyle(const char *pszName, const char *pszStyleString);
-    
+
     GBool SaveStyleTable(const char *pszFilename);
     GBool LoadStyleTable(const char *pszFilename);
     const char *Find(const char *pszStyleString);
@@ -124,31 +125,31 @@ class CPL_DLL OGRStyleMgr
 
     GBool SetFeatureStyleString(OGRFeature *,const char *pszStyleString=NULL,
                                 GBool bNoMatching = FALSE);
-    /*it will set in the gived feature the pszStyleString with 
-            the style or will set the style name found in 
-            dataset StyleTable (if bNoMatching == FALSE)*/
-              
+    /* It will set in the given feature the pszStyleString with
+            the style or will set the style name found in
+            dataset StyleTable (if bNoMatching == FALSE). */
+
     const char *InitFromFeature(OGRFeature *);
     GBool InitStyleString(const char *pszStyleString = NULL);
-    
+
     const char *GetStyleName(const char *pszStyleString= NULL);
     const char *GetStyleByName(const char *pszStyleName);
-    
+
     GBool AddStyle(const char *pszStyleName, const char *pszStyleString=NULL);
-    
+
     const char *GetStyleString(OGRFeature * = NULL);
- 
+
     GBool AddPart(OGRStyleTool *);
     GBool AddPart(const char *);
 
     int GetPartCount(const char *pszStyleString = NULL);
     OGRStyleTool *GetPart(int hPartId, const char *pszStyleString = NULL);
-    
-    /*It could have a reference counting processus for the OGRStyleTable, if
-      needed */
-      
+
+    /* It could have a reference counting process us for the OGRStyleTable, if
+      needed. */
+
     OGRStyleTable *GetDataSetStyleTable(){return m_poDataSetStyleTable;}
-    
+
     OGRStyleTool *CreateStyleToolFromStyleString(const char *pszStyleString);
 
 };
@@ -174,12 +175,12 @@ class CPL_DLL OGRStyleTool
                 int nCount);
 
   public:
-    
+
     OGRStyleTool(){}
     OGRStyleTool(OGRSTClassId eClassId);
     virtual ~OGRStyleTool();
 
-    GBool GetRGBFromString(const char *pszColor, int &nRed, int &nGreen, 
+    GBool GetRGBFromString(const char *pszColor, int &nRed, int &nGreen,
                            int &nBlue, int &nTransparence);
     int   GetSpecificId(const char *pszId, const char *pszWanted);
 
@@ -188,20 +189,20 @@ class CPL_DLL OGRStyleTool
 
     GBool IsStyleParsed() {return m_bParsed;}
     void  StyleParsed() {m_bParsed = TRUE;}
-    
+
     OGRSTClassId GetType();
 
     void SetInternalInputUnitFromParam(char *pszString);
-    
+
     void SetUnit(OGRSTUnitId,double dfScale = 1.0); //the dfScale will be
          //used if we are working with Ground Unit ( ground = paper * scale);
 
     OGRSTUnitId GetUnit(){return m_eUnit;}
-    
-    /* It's existe two way to set the parameters in the Style, with generic
-methodes (using a defined enumeration) or with the reel method specific
-for Each style tools.*/
-    
+
+    // There are two way to set the parameters in the Style, with generic
+    // methods (using a defined enumeration) or with the reel method specific
+    // for Each style tools.
+
     virtual const char *GetStyleString() = 0;
     void SetStyleString(const char *pszStyleString);
     const char *GetStyleString(const OGRStyleParamId *pasStyleParam ,
@@ -218,11 +219,11 @@ for Each style tools.*/
     double GetParamDbl(const OGRStyleParamId &sStyleParam ,
                        OGRStyleValue &sStyleValue,
                        GBool &bValueIsNull);
-    
+
     void SetParamStr(const OGRStyleParamId &sStyleParam ,
                      OGRStyleValue &sStyleValue,
                      const char *pszParamString);
-    
+
     void SetParamNum(const OGRStyleParamId &sStyleParam ,
                      OGRStyleValue &sStyleValue,
                      int nParam);
@@ -250,12 +251,12 @@ class CPL_DLL OGRStylePen : public OGRStyleTool
   public:
 
     OGRStylePen();
-    virtual ~OGRStylePen(); 
+    virtual ~OGRStylePen();
 
     /**********************************************************************/
     /* Explicit fct for all parameters defined in the Drawing tools  Pen  */
     /**********************************************************************/
-     
+
     const char *Color(GBool &bDefault){return GetParamStr(OGRSTPenColor,bDefault);}
     void SetColor(const char *pszColor){SetParamStr(OGRSTPenColor,pszColor);}
     double Width(GBool &bDefault){return GetParamDbl(OGRSTPenWidth,bDefault);}
@@ -272,9 +273,9 @@ class CPL_DLL OGRStylePen : public OGRStyleTool
     void SetJoin(const char *pszJoin){SetParamStr(OGRSTPenJoin,pszJoin);}
     int  Priority(GBool &bDefault){return GetParamNum(OGRSTPenPriority,bDefault);}
     void SetPriority(int nPriority){SetParamNum(OGRSTPenPriority,nPriority);}
-    
+
     /*****************************************************************/
-    
+
     const char *GetParamStr(OGRSTPenParam eParam, GBool &bValueIsNull);
     int GetParamNum(OGRSTPenParam eParam,GBool &bValueIsNull);
     double GetParamDbl(OGRSTPenParam eParam,GBool &bValueIsNull);
@@ -318,10 +319,9 @@ class CPL_DLL OGRStyleBrush : public OGRStyleTool
     void SetSpacingY(double dfY){SetParamDbl(OGRSTBrushDy,dfY  );}
     int  Priority(GBool &bDefault){ return GetParamNum(OGRSTBrushPriority,bDefault);}
     void SetPriority(int nPriority){ SetParamNum(OGRSTBrushPriority,nPriority);}
-    
 
     /*****************************************************************/
-    
+
      const char *GetParamStr(OGRSTBrushParam eParam, GBool &bValueIsNull);
      int GetParamNum(OGRSTBrushParam eParam,GBool &bValueIsNull);
      double GetParamDbl(OGRSTBrushParam eParam,GBool &bValueIsNull);
@@ -350,7 +350,7 @@ class CPL_DLL OGRStyleSymbol : public OGRStyleTool
     /*****************************************************************/
     /* Explicit fct for all parameters defined in the Drawing tools  */
     /*****************************************************************/
-    
+
     const char *Id(GBool &bDefault){return GetParamStr(OGRSTSymbolId,bDefault);}
     void  SetId(const char *pszId){ SetParamStr(OGRSTSymbolId,pszId);}
     double Angle(GBool &bDefault){ return GetParamDbl(OGRSTSymbolAngle,bDefault);}
@@ -368,7 +368,7 @@ class CPL_DLL OGRStyleSymbol : public OGRStyleTool
     double Offset(GBool &bDefault){return GetParamDbl(OGRSTSymbolOffset,bDefault);}
     void SetOffset(double dfOffset){SetParamDbl(OGRSTSymbolOffset,dfOffset  );}
     double Perp(GBool &bDefault){return GetParamDbl(OGRSTSymbolPerp,bDefault);}
-    void SetPerp(double dfPerp){SetParamDbl(OGRSTSymbolPerp,dfPerp  );}  
+    void SetPerp(double dfPerp){SetParamDbl(OGRSTSymbolPerp,dfPerp  );}
     int  Priority(GBool &bDefault){return GetParamNum(OGRSTSymbolPriority,bDefault);}
     void SetPriority(int nPriority){SetParamNum(OGRSTSymbolPriority,nPriority);}
     const char *FontName(GBool &bDefault)
@@ -379,7 +379,7 @@ class CPL_DLL OGRStyleSymbol : public OGRStyleTool
     void SetOColor(const char *pszColor){SetParamStr(OGRSTSymbolOColor,pszColor);}
 
     /*****************************************************************/
-    
+
      const char *GetParamStr(OGRSTSymbolParam eParam, GBool &bValueIsNull);
      int GetParamNum(OGRSTSymbolParam eParam,GBool &bValueIsNull);
      double GetParamDbl(OGRSTSymbolParam eParam,GBool &bValueIsNull);
@@ -408,7 +408,7 @@ class CPL_DLL OGRStyleLabel : public OGRStyleTool
     /*****************************************************************/
     /* Explicit fct for all parameters defined in the Drawing tools  */
     /*****************************************************************/
-    
+
     const char *FontName(GBool &bDefault){return GetParamStr(OGRSTLabelFontName,bDefault);}
     void  SetFontName(const char *pszFontName){SetParamStr(OGRSTLabelFontName,pszFontName);}
     double Size(GBool &bDefault){return GetParamDbl(OGRSTLabelSize,bDefault);}
@@ -430,7 +430,7 @@ class CPL_DLL OGRStyleLabel : public OGRStyleTool
     double SpacingY(GBool &bDefault){return GetParamDbl(OGRSTLabelDy,bDefault);}
     void SetSpacingY(double dfY){SetParamDbl(OGRSTLabelDy,dfY);}
     double Perp(GBool &bDefault){return GetParamDbl(OGRSTLabelPerp,bDefault);}
-    void SetPerp(double dfPerp){SetParamDbl(OGRSTLabelPerp,dfPerp);}  
+    void SetPerp(double dfPerp){SetParamDbl(OGRSTLabelPerp,dfPerp);}
     GBool Bold(GBool &bDefault){return GetParamNum(OGRSTLabelBold,bDefault);}
     void SetBold(GBool bBold){SetParamNum(OGRSTLabelBold,bBold);}
     GBool Italic(GBool &bDefault){return GetParamNum(OGRSTLabelItalic,bDefault);}
@@ -451,9 +451,9 @@ class CPL_DLL OGRStyleLabel : public OGRStyleTool
     void SetShadowColor(const char *pszShadowColor){SetParamStr(OGRSTLabelHColor,pszShadowColor);}
     const char *OutlineColor(GBool &bDefault){return GetParamStr(OGRSTLabelOColor,bDefault);}
     void SetOutlineColor(const char *pszOutlineColor){SetParamStr(OGRSTLabelOColor,pszOutlineColor);}
-    
+
     /*****************************************************************/
-    
+
      const char *GetParamStr(OGRSTLabelParam eParam, GBool &bValueIsNull);
      int GetParamNum(OGRSTLabelParam eParam,GBool &bValueIsNull);
      double GetParamDbl(OGRSTLabelParam eParam,GBool &bValueIsNull);
diff --git a/ogr/ogr_fromepsg.cpp b/ogr/ogr_fromepsg.cpp
index dbfc360..c4a8f44 100644
--- a/ogr/ogr_fromepsg.cpp
+++ b/ogr/ogr_fromepsg.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_fromepsg.cpp 29504 2015-07-08 19:18:55Z rouault $
+ * $Id: ogr_fromepsg.cpp 33605 2016-02-29 21:29:59Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Generate an OGRSpatialReference object based on an EPSG
@@ -29,20 +29,20 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_spatialref.h"
-#include "ogr_p.h"
 #include "cpl_csv.h"
+#include "ogr_p.h"
+#include "ogr_spatialref.h"
+
 #include <vector>
 
-CPL_CVSID("$Id: ogr_fromepsg.cpp 29504 2015-07-08 19:18:55Z rouault $");
+CPL_CVSID("$Id: ogr_fromepsg.cpp 33605 2016-02-29 21:29:59Z goatbar $");
 
-#ifndef PI
-#  define PI 3.14159265358979323846
-#endif
+extern void OGRsnPrintDouble( char * pszStrBuf, size_t size, double dfValue );
 
-void OGRPrintDouble( char * pszStrBuf, double dfValue );
+int EPSGGetWGS84Transform( int nGeogCS, std::vector<CPLString>& asTransform );
+void OGREPSGDatumNameMassage( char ** ppszDatum );
 
-static const char *papszDatumEquiv[] =
+static const char * const apszDatumEquiv[] =
 {
     "Militar_Geographische_Institut",
     "Militar_Geographische_Institute",
@@ -67,8 +67,7 @@ static const char *papszDatumEquiv[] =
 void OGREPSGDatumNameMassage( char ** ppszDatum )
 
 {
-    int         i, j;
-    char        *pszDatum = *ppszDatum;
+    char *pszDatum = *ppszDatum;
 
     if (pszDatum[0] == '\0')
         return;
@@ -76,7 +75,7 @@ void OGREPSGDatumNameMassage( char ** ppszDatum )
 /* -------------------------------------------------------------------- */
 /*      Translate non-alphanumeric values to underscores.               */
 /* -------------------------------------------------------------------- */
-    for( i = 0; pszDatum[i] != '\0'; i++ )
+    for( int i = 0; pszDatum[i] != '\0'; i++ )
     {
         if( pszDatum[i] != '+'
             && !(pszDatum[i] >= 'A' && pszDatum[i] <= 'Z')
@@ -90,7 +89,8 @@ void OGREPSGDatumNameMassage( char ** ppszDatum )
 /* -------------------------------------------------------------------- */
 /*      Remove repeated and trailing underscores.                       */
 /* -------------------------------------------------------------------- */
-    for( i = 1, j = 0; pszDatum[i] != '\0'; i++ )
+    int j = 0; // Used after for loop.
+    for( int i = 1; pszDatum[i] != '\0'; i++ )
     {
         if( pszDatum[j] == '_' && pszDatum[i] == '_' )
             continue;
@@ -101,17 +101,17 @@ void OGREPSGDatumNameMassage( char ** ppszDatum )
         pszDatum[j] = '\0';
     else
         pszDatum[j+1] = '\0';
-    
+
 /* -------------------------------------------------------------------- */
 /*      Search for datum equivelences.  Specific massaged names get     */
 /*      mapped to OpenGIS specified names.                              */
 /* -------------------------------------------------------------------- */
-    for( i = 0; papszDatumEquiv[i] != NULL; i += 2 )
+    for( int i = 0; apszDatumEquiv[i] != NULL; i += 2 )
     {
-        if( EQUAL(*ppszDatum,papszDatumEquiv[i]) )
+        if( EQUAL(*ppszDatum, apszDatumEquiv[i]) )
         {
             CPLFree( *ppszDatum );
-            *ppszDatum = CPLStrdup( papszDatumEquiv[i+1] );
+            *ppszDatum = CPLStrdup( apszDatumEquiv[i+1] );
             break;
         }
     }
@@ -127,26 +127,23 @@ static double
 EPSGAngleStringToDD( const char * pszAngle, int nUOMAngle )
 
 {
-    double      dfAngle;
-    
+    double dfAngle = 0.0;
+
     if( nUOMAngle == 9110 )             /* DDD.MMSSsss */
     {
-        char    *pszDecimal;
-        
         dfAngle = ABS(atoi(pszAngle));
-        pszDecimal = (char *) strchr(pszAngle,'.');
+        const char *pszDecimal = strchr(pszAngle,'.');
         if( pszDecimal != NULL && strlen(pszDecimal) > 1 )
         {
-            char        szMinutes[3];
-            char        szSeconds[64];
+            char szMinutes[3] = { '\0', '\0', '\0' };
+            char szSeconds[64] = { '\0' };
 
             szMinutes[0] = pszDecimal[1];
             if( pszDecimal[2] >= '0' && pszDecimal[2] <= '9' )
                 szMinutes[1] = pszDecimal[2];
             else
                 szMinutes[1] = '0';
-            
-            szMinutes[2] = '\0';
+
             dfAngle += atoi(szMinutes) / 60.0;
 
             if( strlen(pszDecimal) > 3 )
@@ -177,7 +174,7 @@ EPSGAngleStringToDD( const char * pszAngle, int nUOMAngle )
     }
     else if( nUOMAngle == 9101 )                        /* radians */
     {
-        dfAngle = 180 * (CPLAtof(pszAngle ) / PI);
+        dfAngle = 180 * (CPLAtof(pszAngle ) / M_PI);
     }
     else if( nUOMAngle == 9103 )                        /* arc-minute */
     {
@@ -187,30 +184,25 @@ EPSGAngleStringToDD( const char * pszAngle, int nUOMAngle )
     {
         dfAngle = CPLAtof(pszAngle) / 3600;
     }
-    else /* decimal degrees ... some cases missing but seeminly never used */
+    else /* decimal degrees ... some cases missing but seemingly never used */
     {
         CPLAssert( nUOMAngle == 9102 || nUOMAngle == 0 );
-        
+
         dfAngle = CPLAtof(pszAngle );
     }
 
-    return( dfAngle );
+    return dfAngle;
 }
 
 /************************************************************************/
 /*                        EPSGGetUOMAngleInfo()                         */
 /************************************************************************/
 
-int EPSGGetUOMAngleInfo( int nUOMAngleCode,
-                         char **ppszUOMName,
-                         double * pdfInDegrees )
+static bool EPSGGetUOMAngleInfo( int nUOMAngleCode,
+                                 char **ppszUOMName,
+                                 double * pdfInDegrees )
 
 {
-    const char  *pszUOMName = NULL;
-    double      dfInDegrees = 1.0;
-    const char *pszFilename;
-    char        szSearchKey[24];
-
     /* We do a special override of some of the DMS formats name */
     /* This will also solve accuracy problems when computing */
     /* the dfInDegree value from the CSV values (#3643) */
@@ -222,15 +214,17 @@ int EPSGGetUOMAngleInfo( int nUOMAngleCode,
             *ppszUOMName = CPLStrdup("degree");
         if( pdfInDegrees != NULL )
             *pdfInDegrees = 1.0;
-        return TRUE;
+        return true;
     }
 
-    pszFilename = CSVFilename( "unit_of_measure.csv" );
+    const char *pszFilename = CSVFilename( "unit_of_measure.csv" );
+
+    char szSearchKey[24] = { '\0' };
+    snprintf( szSearchKey, sizeof(szSearchKey), "%d", nUOMAngleCode );
 
-    sprintf( szSearchKey, "%d", nUOMAngleCode );
-    pszUOMName = CSVGetField( pszFilename,
-                              "UOM_CODE", szSearchKey, CC_Integer,
-                              "UNIT_OF_MEAS_NAME" );
+    const char *pszUOMName = CSVGetField( pszFilename,
+                                          "UOM_CODE", szSearchKey, CC_Integer,
+                                          "UNIT_OF_MEAS_NAME" );
 
 /* -------------------------------------------------------------------- */
 /*      If the file is found, read from there.  Note that FactorC is    */
@@ -238,22 +232,22 @@ int EPSGGetUOMAngleInfo( int nUOMAngleCode,
 /*      case we really want to return the default InDegrees value       */
 /*      (1.0) from above.                                               */
 /* -------------------------------------------------------------------- */
-    if( pszUOMName != NULL )
+    double dfInDegrees = 1.0;
+
+    if( !EQUAL( pszUOMName, "" ) )
     {
-        double dfFactorB, dfFactorC;
-        
-        dfFactorB = 
+        const double dfFactorB =
             CPLAtof(CSVGetField( pszFilename,
-                              "UOM_CODE", szSearchKey, CC_Integer,
-                              "FACTOR_B" ));
-        
-        dfFactorC = 
+                                 "UOM_CODE", szSearchKey, CC_Integer,
+                                 "FACTOR_B" ));
+
+        const double dfFactorC =
             CPLAtof(CSVGetField( pszFilename,
-                              "UOM_CODE", szSearchKey, CC_Integer,
-                              "FACTOR_C" ));
+                                 "UOM_CODE", szSearchKey, CC_Integer,
+                                 "FACTOR_C" ));
 
         if( dfFactorC != 0.0 )
-            dfInDegrees = (dfFactorB / dfFactorC) * (180.0 / PI);
+            dfInDegrees = (dfFactorB / dfFactorC) * (180.0 / M_PI);
 
         // For some reason, (FactorB) is not very precise in EPSG, use
         // a more exact form for grads.
@@ -270,16 +264,7 @@ int EPSGGetUOMAngleInfo( int nUOMAngleCode,
         {
           case 9101:
             pszUOMName = "radian";
-            dfInDegrees = 180.0 / PI;
-            break;
-
-          case 9102:
-          case 9107:
-          case 9108:
-          case 9110:
-          case 9122:
-            pszUOMName = "degree";
-            dfInDegrees = 1.0;
+            dfInDegrees = 180.0 / M_PI;
             break;
 
           case 9103:
@@ -291,7 +276,7 @@ int EPSGGetUOMAngleInfo( int nUOMAngleCode,
             pszUOMName = "arc-second";
             dfInDegrees = 1 / 3600.0;
             break;
-        
+
           case 9105:
             pszUOMName = "grad";
             dfInDegrees = 180.0 / 200.0;
@@ -301,14 +286,14 @@ int EPSGGetUOMAngleInfo( int nUOMAngleCode,
             pszUOMName = "gon";
             dfInDegrees = 180.0 / 200.0;
             break;
-        
+
           case 9109:
             pszUOMName = "microradian";
-            dfInDegrees = 180.0 / (3.14159265358979 * 1000000.0);
+            dfInDegrees = 180.0 / (M_PI * 1000000.0);
             break;
 
           default:
-            return FALSE;
+            return false;
         }
     }
 
@@ -316,17 +301,12 @@ int EPSGGetUOMAngleInfo( int nUOMAngleCode,
 /*      Return to caller.                                               */
 /* -------------------------------------------------------------------- */
     if( ppszUOMName != NULL )
-    {
-        if( pszUOMName != NULL )
-            *ppszUOMName = CPLStrdup( pszUOMName );
-        else
-            *ppszUOMName = NULL;
-    }
+        *ppszUOMName = CPLStrdup( pszUOMName );
 
     if( pdfInDegrees != NULL )
         *pdfInDegrees = dfInDegrees;
 
-    return( TRUE );
+    return true;
 }
 
 /************************************************************************/
@@ -336,18 +316,12 @@ int EPSGGetUOMAngleInfo( int nUOMAngleCode,
 /*      lookup length aliases in the UOM_LE_ALIAS table.                */
 /************************************************************************/
 
-static int 
+static bool
 EPSGGetUOMLengthInfo( int nUOMLengthCode,
                       char **ppszUOMName,
                       double * pdfInMeters )
 
 {
-    char        **papszUnitsRecord;
-    char        szSearchKey[24];
-    int         iNameField;
-
-#define UOM_FILENAME CSVFilename( "unit_of_measure.csv" )
-
 /* -------------------------------------------------------------------- */
 /*      We short cut meter to save work in the most common case.        */
 /* -------------------------------------------------------------------- */
@@ -358,39 +332,41 @@ EPSGGetUOMLengthInfo( int nUOMLengthCode,
         if( pdfInMeters != NULL )
             *pdfInMeters = 1.0;
 
-        return TRUE;
+        return true;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Search the units database for this unit.  If we don't find      */
 /*      it return failure.                                              */
 /* -------------------------------------------------------------------- */
-    sprintf( szSearchKey, "%d", nUOMLengthCode );
-    papszUnitsRecord =
-        CSVScanFileByName( UOM_FILENAME, "UOM_CODE", szSearchKey, CC_Integer );
+    const char *uom_filename = CSVFilename( "unit_of_measure.csv" );
+
+    char szSearchKey[24] = { '\0' };
+    snprintf( szSearchKey, sizeof(szSearchKey), "%d", nUOMLengthCode );
+    char **papszUnitsRecord =
+        CSVScanFileByName( uom_filename, "UOM_CODE", szSearchKey, CC_Integer );
 
     if( papszUnitsRecord == NULL )
-        return FALSE;
+        return false;
 
 /* -------------------------------------------------------------------- */
 /*      Get the name, if requested.                                     */
 /* -------------------------------------------------------------------- */
     if( ppszUOMName != NULL )
     {
-        iNameField = CSVGetFileFieldId( UOM_FILENAME, "UNIT_OF_MEAS_NAME" );
+        const int iNameField =
+            CSVGetFileFieldId( uom_filename, "UNIT_OF_MEAS_NAME" );
         *ppszUOMName = CPLStrdup( CSLGetField(papszUnitsRecord, iNameField) );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Get the A and B factor fields, and create the multiplicative    */
 /*      factor.                                                         */
 /* -------------------------------------------------------------------- */
     if( pdfInMeters != NULL )
     {
-        int     iBFactorField, iCFactorField;
-        
-        iBFactorField = CSVGetFileFieldId( UOM_FILENAME, "FACTOR_B" );
-        iCFactorField = CSVGetFileFieldId( UOM_FILENAME, "FACTOR_C" );
+        const int iBFactorField = CSVGetFileFieldId( uom_filename, "FACTOR_B" );
+        const int iCFactorField = CSVGetFileFieldId( uom_filename, "FACTOR_C" );
 
         if( CPLAtof(CSLGetField(papszUnitsRecord, iCFactorField)) > 0.0 )
             *pdfInMeters = CPLAtof(CSLGetField(papszUnitsRecord,iBFactorField))
@@ -398,8 +374,8 @@ EPSGGetUOMLengthInfo( int nUOMLengthCode,
         else
             *pdfInMeters = 0.0;
     }
-    
-    return( TRUE );
+
+    return true;
 }
 
 /************************************************************************/
@@ -439,25 +415,20 @@ static void EPSGNegateString(CPLString& osValue)
 int EPSGGetWGS84Transform( int nGeogCS, std::vector<CPLString>& asTransform )
 
 {
-    int         nMethodCode, iDXField, iField;
-    char        szCode[32];
-    const char *pszFilename;
-    char **papszLine;
-
 /* -------------------------------------------------------------------- */
 /*      Fetch the line from the GCS table.                              */
 /* -------------------------------------------------------------------- */
-    pszFilename = CSVFilename("gcs.override.csv");
-    sprintf( szCode, "%d", nGeogCS );
-    papszLine = CSVScanFileByName( pszFilename,
-                                   "COORD_REF_SYS_CODE", 
-                                   szCode, CC_Integer );
+    const char *pszFilename = CSVFilename("gcs.override.csv");
+    char szCode[32] = { '\0' };
+    snprintf( szCode, sizeof(szCode), "%d", nGeogCS );
+    char **papszLine = CSVScanFileByName(
+        pszFilename, "COORD_REF_SYS_CODE", szCode, CC_Integer );
     if( papszLine == NULL )
     {
         pszFilename = CSVFilename("gcs.csv");
-        sprintf( szCode, "%d", nGeogCS );
+        snprintf( szCode, sizeof(szCode), "%d", nGeogCS );
         papszLine = CSVScanFileByName( pszFilename,
-                                       "COORD_REF_SYS_CODE", 
+                                       "COORD_REF_SYS_CODE",
                                        szCode, CC_Integer );
     }
 
@@ -467,7 +438,7 @@ int EPSGGetWGS84Transform( int nGeogCS, std::vector<CPLString>& asTransform )
 /* -------------------------------------------------------------------- */
 /*      Verify that the method code is one of our accepted ones.        */
 /* -------------------------------------------------------------------- */
-    nMethodCode = 
+    const int nMethodCode =
         atoi(CSLGetField( papszLine,
                           CSVGetFileFieldId(pszFilename,
                                             "COORD_OP_METHOD_CODE")));
@@ -477,12 +448,12 @@ int EPSGGetWGS84Transform( int nGeogCS, std::vector<CPLString>& asTransform )
 /* -------------------------------------------------------------------- */
 /*      Fetch the transformation parameters.                            */
 /* -------------------------------------------------------------------- */
-    iDXField = CSVGetFileFieldId(pszFilename, "DX");
+    const int iDXField = CSVGetFileFieldId(pszFilename, "DX");
     if (iDXField < 0 || CSLCount(papszLine) < iDXField + 7)
         return FALSE;
 
     asTransform.resize(0);
-    for( iField = 0; iField < 7; iField++ )
+    for(int  iField = 0; iField < 7; iField++ )
     {
         const char* pszValue = papszLine[iDXField+iField];
         if( pszValue[0] )
@@ -502,7 +473,7 @@ int EPSGGetWGS84Transform( int nGeogCS, std::vector<CPLString>& asTransform )
         EPSGNegateString(asTransform[4]);
         EPSGNegateString(asTransform[5]);
     }
-        
+
     return TRUE;
 }
 
@@ -513,15 +484,10 @@ int EPSGGetWGS84Transform( int nGeogCS, std::vector<CPLString>& asTransform )
 /*      in degrees.                                                     */
 /************************************************************************/
 
-static int 
+static bool
 EPSGGetPMInfo( int nPMCode, char ** ppszName, double *pdfOffset )
 
 {
-    char        szSearchKey[24];
-    int         nUOMAngle;
-
-#define PM_FILENAME CSVFilename("prime_meridian.csv")
-
 /* -------------------------------------------------------------------- */
 /*      Use a special short cut for Greenwich, since it is so common.   */
 /* -------------------------------------------------------------------- */
@@ -533,20 +499,22 @@ EPSGGetPMInfo( int nPMCode, char ** ppszName, double *pdfOffset )
             *pdfOffset = 0.0;
         if( ppszName != NULL )
             *ppszName = CPLStrdup( "Greenwich" );
-        return TRUE;
+        return true;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Search the database for the corresponding datum code.           */
 /* -------------------------------------------------------------------- */
-    sprintf( szSearchKey, "%d", nPMCode );
+    char szSearchKey[24] = { '\0' };
+    snprintf( szSearchKey, sizeof(szSearchKey), "%d", nPMCode );
 
-    nUOMAngle =
+    const char *PM_FILENAME = CSVFilename("prime_meridian.csv");
+    const int nUOMAngle =
         atoi(CSVGetField( PM_FILENAME,
                           "PRIME_MERIDIAN_CODE", szSearchKey, CC_Integer,
                           "UOM_CODE" ) );
     if( nUOMAngle < 1 )
-        return FALSE;
+        return false;
 
 /* -------------------------------------------------------------------- */
 /*      Get the PM offset.                                              */
@@ -560,18 +528,18 @@ EPSGGetPMInfo( int nPMCode, char ** ppszName, double *pdfOffset )
                              "GREENWICH_LONGITUDE" ),
                 nUOMAngle );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Get the name, if requested.                                     */
 /* -------------------------------------------------------------------- */
     if( ppszName != NULL )
         *ppszName =
             CPLStrdup(
-                CSVGetField( PM_FILENAME, 
+                CSVGetField( PM_FILENAME,
                              "PRIME_MERIDIAN_CODE", szSearchKey, CC_Integer,
                              "PRIME_MERIDIAN_NAME" ));
-    
-    return( TRUE );
+
+    return true;
 }
 
 /************************************************************************/
@@ -581,53 +549,49 @@ EPSGGetPMInfo( int nPMCode, char ** ppszName, double *pdfOffset )
 /*      GCS.                                                            */
 /************************************************************************/
 
-static int
+static bool
 EPSGGetGCSInfo( int nGCSCode, char ** ppszName,
                 int * pnDatum, char **ppszDatumName,
                 int * pnPM, int *pnEllipsoid, int *pnUOMAngle,
                 int * pnCoordSysCode )
 
 {
-    char        szSearchKey[24];
-    int         nDatum, nPM, nUOMAngle, nEllipsoid;
-    const char  *pszFilename;
-
-
 /* -------------------------------------------------------------------- */
 /*      Search the database for the corresponding datum code.           */
 /* -------------------------------------------------------------------- */
-    pszFilename = CSVFilename("gcs.override.csv");
-    sprintf( szSearchKey, "%d", nGCSCode );
+    const char  *pszFilename = CSVFilename("gcs.override.csv");
+    char szSearchKey[24] = { '\0' };
+    snprintf( szSearchKey, sizeof(szSearchKey), "%d", nGCSCode );
 
-    nDatum = atoi(CSVGetField( pszFilename, "COORD_REF_SYS_CODE", 
-                               szSearchKey, CC_Integer,
-                               "DATUM_CODE" ) );
+    int nDatum = atoi(CSVGetField( pszFilename, "COORD_REF_SYS_CODE",
+                                         szSearchKey, CC_Integer,
+                                         "DATUM_CODE" ) );
 
     if( nDatum < 1 )
     {
         pszFilename = CSVFilename("gcs.csv");
-        sprintf( szSearchKey, "%d", nGCSCode );
-        
-        nDatum = atoi(CSVGetField( pszFilename, "COORD_REF_SYS_CODE", 
+        snprintf( szSearchKey, sizeof(szSearchKey), "%d", nGCSCode );
+
+        nDatum = atoi(CSVGetField( pszFilename, "COORD_REF_SYS_CODE",
                                    szSearchKey, CC_Integer,
                                    "DATUM_CODE" ) );
     }
 
     if( nDatum < 1 )
-        return FALSE;
+        return false;
 
     if( pnDatum != NULL )
         *pnDatum = nDatum;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Get the PM.                                                     */
 /* -------------------------------------------------------------------- */
-    nPM = atoi(CSVGetField( pszFilename, "COORD_REF_SYS_CODE", 
-                            szSearchKey, CC_Integer,
-                            "PRIME_MERIDIAN_CODE" ) );
+    const int nPM = atoi(CSVGetField( pszFilename, "COORD_REF_SYS_CODE",
+                                      szSearchKey, CC_Integer,
+                                      "PRIME_MERIDIAN_CODE" ) );
 
     if( nPM < 1 )
-        return FALSE;
+        return false;
 
     if( pnPM != NULL )
         *pnPM = nPM;
@@ -635,12 +599,12 @@ EPSGGetGCSInfo( int nGCSCode, char ** ppszName,
 /* -------------------------------------------------------------------- */
 /*      Get the Ellipsoid.                                              */
 /* -------------------------------------------------------------------- */
-    nEllipsoid = atoi(CSVGetField( pszFilename, "COORD_REF_SYS_CODE", 
-                                   szSearchKey, CC_Integer,
-                                   "ELLIPSOID_CODE" ) );
+    const int nEllipsoid = atoi(CSVGetField( pszFilename, "COORD_REF_SYS_CODE",
+                                             szSearchKey, CC_Integer,
+                                             "ELLIPSOID_CODE" ) );
 
     if( nEllipsoid < 1 )
-        return FALSE;
+        return false;
 
     if( pnEllipsoid != NULL )
         *pnEllipsoid = nEllipsoid;
@@ -648,12 +612,12 @@ EPSGGetGCSInfo( int nGCSCode, char ** ppszName,
 /* -------------------------------------------------------------------- */
 /*      Get the angular units.                                          */
 /* -------------------------------------------------------------------- */
-    nUOMAngle = atoi(CSVGetField( pszFilename, "COORD_REF_SYS_CODE", 
-                                  szSearchKey, CC_Integer,
-                                  "UOM_CODE" ) );
+    const int nUOMAngle = atoi(CSVGetField( pszFilename, "COORD_REF_SYS_CODE",
+                                            szSearchKey, CC_Integer,
+                                            "UOM_CODE" ) );
 
     if( nUOMAngle < 1 )
-        return FALSE;
+        return false;
 
     if( pnUOMAngle != NULL )
         *pnUOMAngle = nUOMAngle;
@@ -663,32 +627,30 @@ EPSGGetGCSInfo( int nGCSCode, char ** ppszName,
 /* -------------------------------------------------------------------- */
     if( ppszName != NULL )
         *ppszName =
-            CPLStrdup(CSVGetField( pszFilename, "COORD_REF_SYS_CODE", 
+            CPLStrdup(CSVGetField( pszFilename, "COORD_REF_SYS_CODE",
                                    szSearchKey, CC_Integer,
                                    "COORD_REF_SYS_NAME" ));
-    
+
 /* -------------------------------------------------------------------- */
 /*      Get the datum name, if requested.                               */
 /* -------------------------------------------------------------------- */
     if( ppszDatumName != NULL )
         *ppszDatumName =
-            CPLStrdup(CSVGetField( pszFilename, "COORD_REF_SYS_CODE", 
+            CPLStrdup(CSVGetField( pszFilename, "COORD_REF_SYS_CODE",
                                    szSearchKey, CC_Integer,
                                    "DATUM_NAME" ));
-    
+
 /* -------------------------------------------------------------------- */
 /*      Get the CoordSysCode                                            */
 /* -------------------------------------------------------------------- */
-    int nCSC;
+    const int nCSC = atoi(CSVGetField( pszFilename, "COORD_REF_SYS_CODE",
+                                       szSearchKey, CC_Integer,
+                                       "COORD_SYS_CODE" ) );
 
-    nCSC = atoi(CSVGetField( pszFilename, "COORD_REF_SYS_CODE", 
-                             szSearchKey, CC_Integer,
-                             "COORD_SYS_CODE" ) );
-    
     if( pnCoordSysCode != NULL )
         *pnCoordSysCode = nCSC;
 
-    return( TRUE );
+    return TRUE;
 }
 
 /************************************************************************/
@@ -716,22 +678,19 @@ EPSGGetGCSInfo( int nGCSCode, char ** ppszName,
  * @return OGRERR_NONE on success or an error code in case of failure.
  **/
 
-OGRErr 
+OGRErr
 OSRGetEllipsoidInfo( int nCode, char ** ppszName,
                      double * pdfSemiMajor, double * pdfInvFlattening )
 
 {
-    char        szSearchKey[24];
-    double      dfSemiMajor, dfToMeters = 1.0;
-    int         nUOMLength;
-    
 /* -------------------------------------------------------------------- */
 /*      Get the semi major axis.                                        */
 /* -------------------------------------------------------------------- */
+    char szSearchKey[24] = { '\0' };
     snprintf( szSearchKey, sizeof(szSearchKey), "%d", nCode );
     szSearchKey[sizeof(szSearchKey) - 1] = '\n';
 
-    dfSemiMajor =
+    double dfSemiMajor =
         CPLAtof(CSVGetField( CSVFilename("ellipsoid.csv" ),
                              "ELLIPSOID_CODE", szSearchKey, CC_Integer,
                              "SEMI_MAJOR_AXIS" ) );
@@ -741,32 +700,35 @@ OSRGetEllipsoidInfo( int nCode, char ** ppszName,
 /* -------------------------------------------------------------------- */
 /*      Get the translation factor into meters.                         */
 /* -------------------------------------------------------------------- */
-    nUOMLength = atoi(CSVGetField( CSVFilename("ellipsoid.csv" ),
-                                   "ELLIPSOID_CODE", szSearchKey, CC_Integer,
-                                   "UOM_CODE" ));
-    EPSGGetUOMLengthInfo( nUOMLength, NULL, &dfToMeters );
+    const int nUOMLength = atoi(CSVGetField( CSVFilename("ellipsoid.csv" ),
+                                             "ELLIPSOID_CODE", szSearchKey,
+                                             CC_Integer,
+                                             "UOM_CODE" ));
+    double dfToMeters = 1.0;
+    if ( !EPSGGetUOMLengthInfo( nUOMLength, NULL, &dfToMeters ) )
+    {
+        dfToMeters = 1.0;
+    }
 
     dfSemiMajor *= dfToMeters;
-    
+
     if( pdfSemiMajor != NULL )
         *pdfSemiMajor = dfSemiMajor;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Get the semi-minor if requested.  If the Semi-minor axis        */
 /*      isn't available, compute it based on the inverse flattening.    */
 /* -------------------------------------------------------------------- */
     if( pdfInvFlattening != NULL )
     {
-        *pdfInvFlattening = 
+        *pdfInvFlattening =
             CPLAtof(CSVGetField( CSVFilename("ellipsoid.csv" ),
                                  "ELLIPSOID_CODE", szSearchKey, CC_Integer,
                                  "INV_FLATTENING" ));
 
         if( *pdfInvFlattening == 0.0 )
         {
-            double dfSemiMinor;
-
-            dfSemiMinor =
+            const double dfSemiMinor =
                 CPLAtof(CSVGetField( CSVFilename("ellipsoid.csv" ),
                                   "ELLIPSOID_CODE", szSearchKey, CC_Integer,
                                   "SEMI_MINOR_AXIS" )) * dfToMeters;
@@ -774,7 +736,8 @@ OSRGetEllipsoidInfo( int nCode, char ** ppszName,
             if( dfSemiMajor == 0.0 )
                 *pdfInvFlattening = 0.0;
             else
-                *pdfInvFlattening = OSRCalcInvFlattening(dfSemiMajor, dfSemiMinor);
+                *pdfInvFlattening =
+                    OSRCalcInvFlattening(dfSemiMajor, dfSemiMinor);
         }
     }
 
@@ -790,33 +753,35 @@ OSRGetEllipsoidInfo( int nCode, char ** ppszName,
     return OGRERR_NONE;
 }
 
-#define CoLatConeAxis        1036 /* see #4223 */
-#define NatOriginLat         8801
-#define NatOriginLong        8802
-#define NatOriginScaleFactor 8805
-#define FalseEasting         8806
-#define FalseNorthing        8807
-#define ProjCenterLat        8811
-#define ProjCenterLong       8812
-#define Azimuth              8813
-#define AngleRectifiedToSkewedGrid 8814
-#define InitialLineScaleFactor 8815
-#define ProjCenterEasting    8816
-#define ProjCenterNorthing   8817
-#define PseudoStdParallelLat 8818
-#define PseudoStdParallelScaleFactor 8819
-#define FalseOriginLat       8821
-#define FalseOriginLong      8822
-#define StdParallel1Lat      8823
-#define StdParallel2Lat      8824
-#define FalseOriginEasting   8826
-#define FalseOriginNorthing  8827
-#define SphericalOriginLat   8828
-#define SphericalOriginLong  8829
-#define InitialLongitude     8830
-#define ZoneWidth            8831
-#define PolarLatStdParallel  8832
-#define PolarLongOrigin      8833
+static const int CoLatConeAxis =        1036; /* see #4223 */
+static const int NatOriginLat =         8801;
+static const int NatOriginLong =        8802;
+static const int NatOriginScaleFactor = 8805;
+static const int FalseEasting =         8806;
+static const int FalseNorthing =        8807;
+static const int ProjCenterLat =        8811;
+static const int ProjCenterLong =       8812;
+static const int Azimuth =              8813;
+static const int AngleRectifiedToSkewedGrid = 8814;
+static const int InitialLineScaleFactor = 8815;
+static const int ProjCenterEasting =    8816;
+static const int ProjCenterNorthing =   8817;
+static const int PseudoStdParallelLat = 8818;
+static const int PseudoStdParallelScaleFactor = 8819;
+static const int FalseOriginLat =       8821;
+static const int FalseOriginLong =      8822;
+static const int StdParallel1Lat =      8823;
+static const int StdParallel2Lat =      8824;
+static const int FalseOriginEasting =   8826;
+static const int FalseOriginNorthing =  8827;
+static const int SphericalOriginLat =   8828;
+static const int SphericalOriginLong =  8829;
+#if 0
+static const int InitialLongitude =     8830;
+static const int ZoneWidth =            8831;
+#endif
+static const int PolarLatStdParallel =  8832;
+static const int PolarLongOrigin =      8833;
 
 /************************************************************************/
 /*                         EPSGGetProjTRFInfo()                         */
@@ -827,69 +792,75 @@ OSRGetEllipsoidInfo( int nCode, char ** ppszName,
 /*      normalized into degrees and meters.                             */
 /************************************************************************/
 
-static int
+static bool
 EPSGGetProjTRFInfo( int nPCS, int * pnProjMethod,
                     int *panParmIds, double * padfProjParms )
 
 {
-    int         nProjMethod, i;
-    double      adfProjParms[7];
-    char        szTRFCode[16];
-    CPLString   osFilename;
-
 /* -------------------------------------------------------------------- */
 /*      Get the proj method.  If this fails to return a meaningful      */
 /*      number, then the whole function fails.                          */
 /* -------------------------------------------------------------------- */
-    osFilename = CSVFilename( "pcs.override.csv" );
-    sprintf( szTRFCode, "%d", nPCS );
-    nProjMethod =
+    CPLString osFilename = CSVFilename( "pcs.override.csv" );
+    char szTRFCode[16] = { '\0' };
+    snprintf( szTRFCode, sizeof(szTRFCode), "%d", nPCS );
+
+    int nProjMethod =
         atoi( CSVGetField( osFilename,
                            "COORD_REF_SYS_CODE", szTRFCode, CC_Integer,
                            "COORD_OP_METHOD_CODE" ) );
     if( nProjMethod == 0 )
     {
         osFilename = CSVFilename( "pcs.csv" );
-        sprintf( szTRFCode, "%d", nPCS );
+        snprintf( szTRFCode, sizeof(szTRFCode), "%d", nPCS );
         nProjMethod =
             atoi( CSVGetField( osFilename,
                                "COORD_REF_SYS_CODE", szTRFCode, CC_Integer,
                                "COORD_OP_METHOD_CODE" ) );
+        if( nProjMethod == 0 )
+            return false;
     }
 
-    if( nProjMethod == 0 )
-        return FALSE;
-
 /* -------------------------------------------------------------------- */
 /*      Get the parameters for this projection.                         */
 /* -------------------------------------------------------------------- */
+    double adfProjParms[7] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
 
-    for( i = 0; i < 7; i++ )
+    for( int i = 0; i < 7; i++ )
     {
-        char    szParamUOMID[32], szParamValueID[32], szParamCodeID[32];
-        char    *pszValue;
-        int     nUOM;
-        
-        sprintf( szParamCodeID, "PARAMETER_CODE_%d", i+1 );
-        sprintf( szParamUOMID, "PARAMETER_UOM_%d", i+1 );
-        sprintf( szParamValueID, "PARAMETER_VALUE_%d", i+1 );
+        if( panParmIds == NULL )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "panParmIds cannot be NULL." );
+            return false;
+        }
+
+        char szParamUOMID[32] = { '\0' };
+        char szParamValueID[32] = { '\0' };
+        char szParamCodeID[32] = { '\0' };
+
+        snprintf( szParamCodeID, sizeof(szParamCodeID),
+                  "PARAMETER_CODE_%d", i+1 );
+        snprintf( szParamUOMID, sizeof(szParamUOMID), "PARAMETER_UOM_%d", i+1 );
+        snprintf( szParamValueID, sizeof(szParamValueID),
+                  "PARAMETER_VALUE_%d", i+1 );
 
-        if( panParmIds != NULL )
-            panParmIds[i] = 
-                atoi(CSVGetField( osFilename, "COORD_REF_SYS_CODE", szTRFCode,
-                                  CC_Integer, szParamCodeID ));
+        panParmIds[i] =
+            atoi(CSVGetField( osFilename, "COORD_REF_SYS_CODE", szTRFCode,
+                              CC_Integer, szParamCodeID ));
 
-        nUOM = atoi(CSVGetField( osFilename, "COORD_REF_SYS_CODE", szTRFCode,
-                                 CC_Integer, szParamUOMID ));
-        pszValue = CPLStrdup(
+        int nUOM = atoi(CSVGetField( osFilename, "COORD_REF_SYS_CODE",
+                                     szTRFCode,
+                                     CC_Integer, szParamUOMID ));
+        char *pszValue = CPLStrdup(
             CSVGetField( osFilename, "COORD_REF_SYS_CODE", szTRFCode,
                          CC_Integer, szParamValueID ));
 
         // there is a bug in the EPSG 6.2.2 database for PCS 2935 and 2936
         // such that they have foot units for the scale factor.  Avoid this.
-        if( (panParmIds[i] == NatOriginScaleFactor 
+        if( (panParmIds[i] == NatOriginScaleFactor
              || panParmIds[i] == InitialLineScaleFactor
-             || panParmIds[i] == PseudoStdParallelScaleFactor) 
+             || panParmIds[i] == PseudoStdParallelScaleFactor)
             && nUOM < 9200 )
             nUOM = 9201;
 
@@ -897,7 +868,7 @@ EPSGGetProjTRFInfo( int nPCS, int * pnProjMethod,
             adfProjParms[i] = EPSGAngleStringToDD( pszValue, nUOM );
         else if( nUOM > 9000 && nUOM < 9100 )
         {
-            double dfInMeters;
+            double dfInMeters = 0.0;
 
             if( !EPSGGetUOMLengthInfo( nUOM, NULL, &dfInMeters ) )
                 dfInMeters = 1.0;
@@ -910,7 +881,7 @@ EPSGGetProjTRFInfo( int nPCS, int * pnProjMethod,
         else /* really we should consider looking up other scaling factors */
         {
             if( nUOM != 9201 )
-                CPLDebug( "OGR", 
+                CPLDebug( "OGR",
                           "Non-unity scale factor units! (UOM=%d, PCS=%d)",
                           nUOM, nPCS );
             adfProjParms[i] = CPLAtof(pszValue);
@@ -927,11 +898,11 @@ EPSGGetProjTRFInfo( int nPCS, int * pnProjMethod,
 
     if( padfProjParms != NULL )
     {
-        for( i = 0; i < 7; i++ )
+        for( int i = 0; i < 7; i++ )
             padfProjParms[i] = adfProjParms[i];
     }
 
-    return TRUE;
+    return true;
 }
 
 
@@ -939,48 +910,46 @@ EPSGGetProjTRFInfo( int nPCS, int * pnProjMethod,
 /*                           EPSGGetPCSInfo()                           */
 /************************************************************************/
 
-static int 
+static bool
 EPSGGetPCSInfo( int nPCSCode, char **ppszEPSGName,
                 int *pnUOMLengthCode, int *pnUOMAngleCode,
                 int *pnGeogCS, int *pnTRFCode, int *pnCoordSysCode )
 
 {
-    char        **papszRecord;
-    char        szSearchKey[24];
-    const char  *pszFilename;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Search the units database for this unit.  If we don't find      */
 /*      it return failure.                                              */
 /* -------------------------------------------------------------------- */
-    pszFilename = CSVFilename( "pcs.override.csv" );
-    sprintf( szSearchKey, "%d", nPCSCode );
-    papszRecord = CSVScanFileByName( pszFilename, "COORD_REF_SYS_CODE",
-                                     szSearchKey, CC_Integer );
+    const char *pszFilename = CSVFilename( "pcs.override.csv" );
+    char szSearchKey[24] = { '\0' };
+    snprintf( szSearchKey, sizeof(szSearchKey), "%d", nPCSCode );
+    char  **papszRecord = CSVScanFileByName( pszFilename, "COORD_REF_SYS_CODE",
+                                             szSearchKey, CC_Integer );
 
     if( papszRecord == NULL )
     {
         pszFilename = CSVFilename( "pcs.csv" );
-        sprintf( szSearchKey, "%d", nPCSCode );
+        snprintf( szSearchKey, sizeof(szSearchKey), "%d", nPCSCode );
         papszRecord = CSVScanFileByName( pszFilename, "COORD_REF_SYS_CODE",
                                          szSearchKey, CC_Integer );
-        
+
     }
 
     if( papszRecord == NULL )
-        return FALSE;
+        return false;
 
 /* -------------------------------------------------------------------- */
 /*      Get the name, if requested.                                     */
 /* -------------------------------------------------------------------- */
     if( ppszEPSGName != NULL )
     {
-        CPLString osPCSName = 
+        CPLString osPCSName =
             CSLGetField( papszRecord,
                          CSVGetFileFieldId(pszFilename,
                                            "COORD_REF_SYS_NAME"));
-            
-        const char *pszDeprecated = 
+
+        const char *pszDeprecated =
             CSLGetField( papszRecord,
                          CSVGetFileFieldId(pszFilename,
                                            "DEPRECATED") );
@@ -996,9 +965,7 @@ EPSGGetPCSInfo( int nPCSCode, char **ppszEPSGName,
 /* -------------------------------------------------------------------- */
     if( pnUOMLengthCode != NULL )
     {
-        const char      *pszValue;
-
-        pszValue =
+        const char *pszValue =
             CSLGetField( papszRecord,
                          CSVGetFileFieldId(pszFilename,"UOM_CODE"));
         if( atoi(pszValue) > 0 )
@@ -1012,12 +979,10 @@ EPSGGetPCSInfo( int nPCSCode, char **ppszEPSGName,
 /* -------------------------------------------------------------------- */
     if( pnUOMAngleCode != NULL )
     {
-        const char      *pszValue;
-        
-        pszValue =
+        const char *pszValue =
             CSLGetField( papszRecord,
                          CSVGetFileFieldId(pszFilename,"UOM_ANGLE_CODE") );
-        
+
         if( atoi(pszValue) > 0 )
             *pnUOMAngleCode = atoi(pszValue);
         else
@@ -1029,9 +994,7 @@ EPSGGetPCSInfo( int nPCSCode, char **ppszEPSGName,
 /* -------------------------------------------------------------------- */
     if( pnGeogCS != NULL )
     {
-        const char      *pszValue;
-
-        pszValue =
+        const char *pszValue =
             CSLGetField( papszRecord,
                          CSVGetFileFieldId(pszFilename,"SOURCE_GEOGCRS_CODE"));
         if( atoi(pszValue) > 0 )
@@ -1045,13 +1008,10 @@ EPSGGetPCSInfo( int nPCSCode, char **ppszEPSGName,
 /* -------------------------------------------------------------------- */
     if( pnTRFCode != NULL )
     {
-        const char      *pszValue;
-
-        pszValue =
+        const char *pszValue =
             CSLGetField( papszRecord,
                          CSVGetFileFieldId(pszFilename,"COORD_OP_CODE"));
-                         
-        
+
         if( atoi(pszValue) > 0 )
             *pnTRFCode = atoi(pszValue);
         else
@@ -1061,23 +1021,21 @@ EPSGGetPCSInfo( int nPCSCode, char **ppszEPSGName,
 /* -------------------------------------------------------------------- */
 /*      Get the CoordSysCode                                            */
 /* -------------------------------------------------------------------- */
-    int nCSC;
+    const int nCSC = atoi(CSVGetField( pszFilename, "COORD_REF_SYS_CODE",
+                                       szSearchKey, CC_Integer,
+                                       "COORD_SYS_CODE" ) );
 
-    nCSC = atoi(CSVGetField( pszFilename, "COORD_REF_SYS_CODE", 
-                             szSearchKey, CC_Integer,
-                             "COORD_SYS_CODE" ) );
-    
     if( pnCoordSysCode != NULL )
         *pnCoordSysCode = nCSC;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                          SetEPSGAxisInfo()                           */
 /************************************************************************/
 
-static OGRErr SetEPSGAxisInfo( OGRSpatialReference *poSRS, 
+static OGRErr SetEPSGAxisInfo( OGRSpatialReference *poSRS,
                                const char *pszTargetKey,
                                int nCoordSysCode )
 
@@ -1089,39 +1047,37 @@ static OGRErr SetEPSGAxisInfo( OGRSpatialReference *poSRS,
     // Conventional and common Easting/Northing values.
     if( nCoordSysCode >= 4400 && nCoordSysCode <= 4410 )
     {
-        return 
-            poSRS->SetAxes( pszTargetKey, 
-                            "Easting", OAO_East, 
+        return
+            poSRS->SetAxes( pszTargetKey,
+                            "Easting", OAO_East,
                             "Northing", OAO_North );
     }
 
     // Conventional and common Easting/Northing values.
     if( nCoordSysCode >= 6400 && nCoordSysCode <= 6423 )
     {
-        return 
-            poSRS->SetAxes( pszTargetKey, 
-                            "Latitude", OAO_North, 
+        return
+            poSRS->SetAxes( pszTargetKey,
+                            "Latitude", OAO_North,
                             "Longitude", OAO_East );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Get the definition from the coordinate_axis.csv file.           */
 /* -------------------------------------------------------------------- */
-    char        **papszRecord;
-    char        **papszAxis1=NULL, **papszAxis2=NULL;
-    char        szSearchKey[24];
-    const char *pszFilename;
-
-    pszFilename = CSVFilename( "coordinate_axis.csv" );
-    sprintf( szSearchKey, "%d", nCoordSysCode );
-    papszRecord = CSVScanFileByName( pszFilename, "COORD_SYS_CODE",
-                                     szSearchKey, CC_Integer );
+    char szSearchKey[24] = { '\0' };
+    const char *pszFilename = CSVFilename( "coordinate_axis.csv" );
+    snprintf( szSearchKey, sizeof(szSearchKey), "%d", nCoordSysCode );
+    char **papszRecord = CSVScanFileByName( pszFilename, "COORD_SYS_CODE",
+                                            szSearchKey, CC_Integer );
 
+    char **papszAxis1 = NULL;
+    char **papszAxis2 = NULL;
     if( papszRecord != NULL )
     {
         papszAxis1 = CSLDuplicate( papszRecord );
         papszRecord = CSVGetNextLine( pszFilename );
-        if( CSLCount(papszRecord) > 0 
+        if( CSLCount(papszRecord) > 0
             && EQUAL(papszRecord[0],papszAxis1[0]) )
             papszAxis2 = CSLDuplicate( papszRecord );
     }
@@ -1130,7 +1086,8 @@ static OGRErr SetEPSGAxisInfo( OGRSpatialReference *poSRS,
     {
         CSLDestroy( papszAxis1 );
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Failed to find entries for COORD_SYS_CODE %d in coordinate_axis.csv", 
+                  "Failed to find entries for COORD_SYS_CODE %d "
+                  "in coordinate_axis.csv",
                   nCoordSysCode );
         return OGRERR_FAILURE;
     }
@@ -1139,16 +1096,13 @@ static OGRErr SetEPSGAxisInfo( OGRSpatialReference *poSRS,
 /*      Confirm the records are complete, and work out which columns    */
 /*      are which.                                                      */
 /* -------------------------------------------------------------------- */
-    int   iAxisOrientationField, iAxisAbbrevField, iAxisOrderField;
-    int   iAxisNameCodeField;
-
-    iAxisOrientationField = 
+    const int iAxisOrientationField =
         CSVGetFileFieldId( pszFilename, "coord_axis_orientation" );
-    iAxisAbbrevField = 
+    const int iAxisAbbrevField =
         CSVGetFileFieldId( pszFilename, "coord_axis_abbreviation" );
-    iAxisOrderField = 
+    const int iAxisOrderField =
         CSVGetFileFieldId( pszFilename, "coord_axis_order" );
-    iAxisNameCodeField = 
+    const int iAxisNameCodeField =
         CSVGetFileFieldId( pszFilename, "coord_axis_name_code" );
 
     /* Check that all fields are available and that the axis_order field */
@@ -1168,13 +1122,14 @@ static OGRErr SetEPSGAxisInfo( OGRSpatialReference *poSRS,
         return OGRERR_FAILURE;
     }
 
-    if( CSLCount(papszAxis1) < iAxisOrderField+1 
+    if( CSLCount(papszAxis1) < iAxisOrderField+1
         || CSLCount(papszAxis2) < iAxisOrderField+1 )
     {
         CSLDestroy( papszAxis1 );
         CSLDestroy( papszAxis2 );
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Axis records appear incomplete for COORD_SYS_CODE %d in coordinate_axis.csv", 
+                  "Axis records appear incomplete for COORD_SYS_CODE %d "
+                  "in coordinate_axis.csv",
                   nCoordSysCode );
         return OGRERR_FAILURE;
     }
@@ -1192,11 +1147,11 @@ static OGRErr SetEPSGAxisInfo( OGRSpatialReference *poSRS,
 /* -------------------------------------------------------------------- */
 /*      Work out axis enumeration values.                               */
 /* -------------------------------------------------------------------- */
-    OGRAxisOrientation eOAxis1 = OAO_Other, eOAxis2 = OAO_Other;
-    int iAO;
-    static int anCodes[7] = { -1, 9907, 9909, 9906, 9908, -1, -1 };
+    OGRAxisOrientation eOAxis1 = OAO_Other;
+    OGRAxisOrientation eOAxis2 = OAO_Other;
+    static const int anCodes[7] = { -1, 9907, 9909, 9906, 9908, -1, -1 };
 
-    for( iAO = 0; iAO < 7; iAO++ )
+    for( int iAO = 0; iAO < 7; iAO++ )
     {
         if( EQUAL(papszAxis1[iAxisOrientationField],
                   OSRAxisEnumToName((OGRAxisOrientation) iAO)) )
@@ -1205,10 +1160,10 @@ static OGRErr SetEPSGAxisInfo( OGRSpatialReference *poSRS,
                   OSRAxisEnumToName((OGRAxisOrientation) iAO)) )
             eOAxis2 = (OGRAxisOrientation) iAO;
 
-        if( eOAxis1 == OAO_Other 
+        if( eOAxis1 == OAO_Other
             && anCodes[iAO] == atoi(papszAxis1[iAxisNameCodeField]) )
             eOAxis1 = (OGRAxisOrientation) iAO;
-        if( eOAxis2 == OAO_Other 
+        if( eOAxis2 == OAO_Other
             && anCodes[iAO] == atoi(papszAxis2[iAxisNameCodeField]) )
             eOAxis2 = (OGRAxisOrientation) iAO;
     }
@@ -1217,11 +1172,11 @@ static OGRErr SetEPSGAxisInfo( OGRSpatialReference *poSRS,
 /*      Work out the axis name.  We try to expand the abbreviation      */
 /*      to a longer name.                                               */
 /* -------------------------------------------------------------------- */
-    const char *apszAxisName[2];
-    apszAxisName[0] = papszAxis1[iAxisAbbrevField];
-    apszAxisName[1] = papszAxis2[iAxisAbbrevField];
+    const char *apszAxisName[2] = {
+        papszAxis1[iAxisAbbrevField],
+        papszAxis2[iAxisAbbrevField] };
 
-    for( iAO = 0; iAO < 2; iAO++ )
+    for( int iAO = 0; iAO < 2; iAO++ )
     {
         if( EQUAL(apszAxisName[iAO],"N") )
             apszAxisName[iAO] = "Northing";
@@ -1236,14 +1191,13 @@ static OGRErr SetEPSGAxisInfo( OGRSpatialReference *poSRS,
 /* -------------------------------------------------------------------- */
 /*      Set the axes.                                                   */
 /* -------------------------------------------------------------------- */
-    OGRErr eResult;
-    eResult = poSRS->SetAxes( pszTargetKey, 
-                              apszAxisName[0], eOAxis1,
-                              apszAxisName[1], eOAxis2 );
+    const OGRErr eResult = poSRS->SetAxes( pszTargetKey,
+                                           apszAxisName[0], eOAxis1,
+                                           apszAxisName[1], eOAxis2 );
 
     CSLDestroy( papszAxis1 );
     CSLDestroy( papszAxis2 );
-    
+
     return eResult;
 }
 
@@ -1257,17 +1211,22 @@ static OGRErr SetEPSGAxisInfo( OGRSpatialReference *poSRS,
 static OGRErr SetEPSGGeogCS( OGRSpatialReference * poSRS, int nGeogCS )
 
 {
-    int  nDatumCode, nPMCode, nUOMAngle, nEllipsoidCode, nCSC;
-    char *pszGeogCSName = NULL, *pszDatumName = NULL, *pszEllipsoidName = NULL;
-    char *pszPMName = NULL, *pszAngleName = NULL;
-    double dfPMOffset, dfSemiMajor, dfInvFlattening;
-    double dfAngleInDegrees, dfAngleInRadians;
+    int nDatumCode = 0;
+    int nPMCode = 0;
+    int nUOMAngle = 0;
+    int nEllipsoidCode = 0;
+    int nCSC = 0;
+    char *pszGeogCSName = NULL;
+    char *pszDatumName = NULL;
+    char *pszAngleName = NULL;
 
     if( !EPSGGetGCSInfo( nGeogCS, &pszGeogCSName,
-                         &nDatumCode, &pszDatumName, 
+                         &nDatumCode, &pszDatumName,
                          &nPMCode, &nEllipsoidCode, &nUOMAngle, &nCSC ) )
         return OGRERR_UNSUPPORTED_SRS;
 
+    char *pszPMName = NULL;
+    double dfPMOffset = 0.0;
     if( !EPSGGetPMInfo( nPMCode, &pszPMName, &dfPMOffset ) )
     {
         CPLFree( pszDatumName );
@@ -1277,7 +1236,10 @@ static OGRErr SetEPSGGeogCS( OGRSpatialReference * poSRS, int nGeogCS )
 
     OGREPSGDatumNameMassage( &pszDatumName );
 
-    if( OSRGetEllipsoidInfo( nEllipsoidCode, &pszEllipsoidName, 
+    char *pszEllipsoidName = NULL;
+    double dfSemiMajor = 0.0;
+    double dfInvFlattening = 0.0;
+    if( OSRGetEllipsoidInfo( nEllipsoidCode, &pszEllipsoidName,
                              &dfSemiMajor, &dfInvFlattening ) != OGRERR_NONE )
     {
         CPLFree( pszDatumName );
@@ -1286,6 +1248,8 @@ static OGRErr SetEPSGGeogCS( OGRSpatialReference * poSRS, int nGeogCS )
         return OGRERR_UNSUPPORTED_SRS;
     }
 
+    double dfAngleInDegrees = 0.0;
+    double dfAngleInRadians = 0.0;
     if( !EPSGGetUOMAngleInfo( nUOMAngle, &pszAngleName, &dfAngleInDegrees ) )
     {
         pszAngleName = CPLStrdup("degree");
@@ -1298,7 +1262,7 @@ static OGRErr SetEPSGGeogCS( OGRSpatialReference * poSRS, int nGeogCS )
     else
         dfAngleInRadians = CPLAtof(SRS_UA_DEGREE_CONV) * dfAngleInDegrees;
 
-    poSRS->SetGeogCS( pszGeogCSName, pszDatumName, 
+    poSRS->SetGeogCS( pszGeogCSName, pszDatumName,
                       pszEllipsoidName, dfSemiMajor, dfInvFlattening,
                       pszPMName, dfPMOffset,
                       pszAngleName, dfAngleInRadians );
@@ -1306,13 +1270,12 @@ static OGRErr SetEPSGGeogCS( OGRSpatialReference * poSRS, int nGeogCS )
     std::vector<CPLString> asBursaTransform;
     if( EPSGGetWGS84Transform( nGeogCS, asBursaTransform ) )
     {
-        OGR_SRSNode     *poWGS84;
-
-        poWGS84 = new OGR_SRSNode( "TOWGS84" );
+        OGR_SRSNode *poWGS84 = new OGR_SRSNode( "TOWGS84" );
 
         for( int iCoeff = 0; iCoeff < 7; iCoeff++ )
         {
-            poWGS84->AddChild( new OGR_SRSNode( asBursaTransform[iCoeff].c_str() ) );
+            poWGS84->AddChild( new OGR_SRSNode(
+                asBursaTransform[iCoeff].c_str() ) );
         }
 
         poSRS->GetAttrNode( "DATUM" )->AddChild( poWGS84 );
@@ -1354,14 +1317,12 @@ static OGRErr SetEPSGGeogCS( OGRSpatialReference * poSRS, int nGeogCS )
 static double OGR_FetchParm( double *padfProjParms,
                              int *panParmIds,
                              int nTargetId,
-                             CPL_UNUSED double dfFromGreenwich )
+                             double /* dfFromGreenwich */)
 {
-    int i;
-    double dfResult;
-
 /* -------------------------------------------------------------------- */
 /*      Set default in meters/degrees.                                  */
 /* -------------------------------------------------------------------- */
+    double dfResult = 0.0;
     switch( nTargetId )
     {
       case NatOriginScaleFactor:
@@ -1381,7 +1342,7 @@ static double OGR_FetchParm( double *padfProjParms,
 /* -------------------------------------------------------------------- */
 /*      Try to find actual value in parameter list.                     */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < 7; i++ )
+    for( int i = 0; i < 7; i++ )
     {
         if( panParmIds[i] == nTargetId )
         {
@@ -1397,7 +1358,7 @@ static double OGR_FetchParm( double *padfProjParms,
 /*      SetNormProjParm() method expects longitudes relative to         */
 /*      greenwich, so there is nothing for us to do.                    */
 /* -------------------------------------------------------------------- */
-#ifdef notdef
+#if 0
     switch( nTargetId )
     {
       case NatOriginLong:
@@ -1430,14 +1391,15 @@ static double OGR_FetchParm( double *padfProjParms,
 static OGRErr SetEPSGProjCS( OGRSpatialReference * poSRS, int nPCSCode )
 
 {
-    int         nGCSCode, nUOMAngleCode, nUOMLength, nTRFCode, nProjMethod=0;
-    int         anParmIds[7], nCSC = 0;
-    char        *pszPCSName = NULL, *pszUOMLengthName = NULL;
-    double      adfProjParms[7], dfInMeters, dfFromGreenwich;
-    OGRErr      nErr;
-    OGR_SRSNode *poNode;
-
-    if( !EPSGGetPCSInfo( nPCSCode, &pszPCSName, &nUOMLength, &nUOMAngleCode,
+    int nGCSCode = 0;
+    int nUOMAngleCode = 0;
+    int nUOMLength = 0;
+    int nTRFCode = 0;
+    int nCSC = 0;
+    char *pszPCSName = NULL;
+
+    if( !EPSGGetPCSInfo( nPCSCode, &pszPCSName,
+                         &nUOMLength, &nUOMAngleCode,
                          &nGCSCode, &nTRFCode, &nCSC ) )
     {
         CPLFree(pszPCSName);
@@ -1445,22 +1407,25 @@ static OGRErr SetEPSGProjCS( OGRSpatialReference * poSRS, int nPCSCode )
     }
 
     poSRS->SetNode( "PROJCS", pszPCSName );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Set GEOGCS.                                                     */
 /* -------------------------------------------------------------------- */
-    nErr = SetEPSGGeogCS( poSRS, nGCSCode );
+    const OGRErr nErr = SetEPSGGeogCS( poSRS, nGCSCode );
     if( nErr != OGRERR_NONE )
     {
         CPLFree(pszPCSName);
         return nErr;
     }
 
-    dfFromGreenwich = poSRS->GetPrimeMeridian();
+    const double dfFromGreenwich = poSRS->GetPrimeMeridian();
 
 /* -------------------------------------------------------------------- */
 /*      Set linear units.                                               */
 /* -------------------------------------------------------------------- */
+    char *pszUOMLengthName = NULL;
+    double dfInMeters = 0.0;
+
     if( !EPSGGetUOMLengthInfo( nUOMLength, &pszUOMLengthName, &dfInMeters ) )
     {
         CPLFree(pszPCSName);
@@ -1476,6 +1441,10 @@ static OGRErr SetEPSGProjCS( OGRSpatialReference * poSRS, int nPCSCode )
 /* -------------------------------------------------------------------- */
 /*      Set projection and parameters.                                  */
 /* -------------------------------------------------------------------- */
+    int nProjMethod = 0;
+    int anParmIds[7] = { 0 };
+    double adfProjParms[7] = { 0.0 };
+
     if( !EPSGGetProjTRFInfo( nPCSCode, &nProjMethod, anParmIds, adfProjParms ))
         return OGRERR_UNSUPPORTED_SRS;
 
@@ -1484,21 +1453,21 @@ static OGRErr SetEPSGProjCS( OGRSpatialReference * poSRS, int nPCSCode )
       case 9801:
       case 9817: /* really LCC near conformal */
         poSRS->SetLCC1SP( OGR_FP( NatOriginLat ), OGR_FP( NatOriginLong ),
-                          OGR_FP( NatOriginScaleFactor ), 
+                          OGR_FP( NatOriginScaleFactor ),
                           OGR_FP( FalseEasting ), OGR_FP( FalseNorthing ) );
         break;
 
       case 9802:
         poSRS->SetLCC( OGR_FP( StdParallel1Lat ), OGR_FP( StdParallel2Lat ),
                        OGR_FP( FalseOriginLat ), OGR_FP( FalseOriginLong ),
-                       OGR_FP( FalseOriginEasting ), 
+                       OGR_FP( FalseOriginEasting ),
                        OGR_FP( FalseOriginNorthing ));
         break;
 
       case 9803:
         poSRS->SetLCCB( OGR_FP( StdParallel1Lat ), OGR_FP( StdParallel2Lat ),
                         OGR_FP( FalseOriginLat ), OGR_FP( FalseOriginLong ),
-                        OGR_FP( FalseOriginEasting ), 
+                        OGR_FP( FalseOriginEasting ),
                         OGR_FP( FalseOriginNorthing ));
         break;
 
@@ -1513,13 +1482,17 @@ static OGRErr SetEPSGProjCS( OGRSpatialReference * poSRS, int nPCSCode )
       case 9841: /* Mercator 1SP (Spherical) */
       case 1024: /* Google Mercator */
         poSRS->SetMercator( OGR_FP( NatOriginLat ), OGR_FP( NatOriginLong ),
-                            OGR_FP( NatOriginScaleFactor ), 
+                            OGR_FP( NatOriginScaleFactor ),
                             OGR_FP( FalseEasting ), OGR_FP( FalseNorthing ) );
 
-        if( nProjMethod == 1024 || nProjMethod == 9841 ) // override hack for google mercator.
+        // override hack for google mercator.
+        if( nProjMethod == 1024 || nProjMethod == 9841 )
         {
-            poSRS->SetExtension( "PROJCS", "PROJ4", 
-                                 "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext  +no_defs" );
+            poSRS->SetExtension(
+                "PROJCS", "PROJ4",
+                "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 "
+                "+x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null "
+                "+wktext +no_defs" );
         }
         break;
 
@@ -1530,25 +1503,25 @@ static OGRErr SetEPSGProjCS( OGRSpatialReference * poSRS, int nPCSCode )
 
       case 9807:
         poSRS->SetTM( OGR_FP( NatOriginLat ), OGR_FP( NatOriginLong ),
-                      OGR_FP( NatOriginScaleFactor ), 
+                      OGR_FP( NatOriginScaleFactor ),
                       OGR_FP( FalseEasting ), OGR_FP( FalseNorthing ) );
         break;
-        
+
       case 9808:
         poSRS->SetTMSO( OGR_FP( NatOriginLat ), OGR_FP( NatOriginLong ),
-                        OGR_FP( NatOriginScaleFactor ), 
+                        OGR_FP( NatOriginScaleFactor ),
                         OGR_FP( FalseEasting ), OGR_FP( FalseNorthing ) );
         break;
-        
+
       case 9809:
         poSRS->SetOS( OGR_FP( NatOriginLat ), OGR_FP( NatOriginLong ),
-                      OGR_FP( NatOriginScaleFactor ), 
+                      OGR_FP( NatOriginScaleFactor ),
                       OGR_FP( FalseEasting ), OGR_FP( FalseNorthing ) );
         break;
 
       case 9810:
         poSRS->SetPS( OGR_FP( NatOriginLat ), OGR_FP( NatOriginLong ),
-                      OGR_FP( NatOriginScaleFactor ), 
+                      OGR_FP( NatOriginScaleFactor ),
                       OGR_FP( FalseEasting ), OGR_FP( FalseNorthing ) );
         break;
 
@@ -1559,20 +1532,21 @@ static OGRErr SetEPSGProjCS( OGRSpatialReference * poSRS, int nPCSCode )
 
       case 9812:
       case 9813:
+      {
         poSRS->SetHOM( OGR_FP( ProjCenterLat ), OGR_FP( ProjCenterLong ),
-                       OGR_FP( Azimuth ), 
+                       OGR_FP( Azimuth ),
                        OGR_FP( AngleRectifiedToSkewedGrid ),
                        OGR_FP( InitialLineScaleFactor ),
                        OGR_FP( FalseEasting ), OGR_FP( FalseNorthing ) );
 
-        poNode = poSRS->GetAttrNode( "PROJECTION" )->GetChild( 0 );
+        OGR_SRSNode *poNode = poSRS->GetAttrNode( "PROJECTION" )->GetChild( 0 );
         if( nProjMethod == 9813 )
             poNode->SetValue( SRS_PT_LABORDE_OBLIQUE_MERCATOR );
         break;
-
+      }
       case 9814:
         /* NOTE: This is no longer used!  Swiss Oblique Mercator gets
-        ** implemented using 9815 instead.  
+        ** implemented using 9815 instead.
         */
         poSRS->SetSOC( OGR_FP( ProjCenterLat ), OGR_FP( ProjCenterLong ),
                        OGR_FP( FalseEasting ), OGR_FP( FalseNorthing ) );
@@ -1580,16 +1554,16 @@ static OGRErr SetEPSGProjCS( OGRSpatialReference * poSRS, int nPCSCode )
 
       case 9815:
         poSRS->SetHOMAC( OGR_FP( ProjCenterLat ), OGR_FP( ProjCenterLong ),
-                         OGR_FP( Azimuth ), 
+                         OGR_FP( Azimuth ),
                          OGR_FP( AngleRectifiedToSkewedGrid ),
                          OGR_FP( InitialLineScaleFactor ),
-                         OGR_FP( ProjCenterEasting ), 
+                         OGR_FP( ProjCenterEasting ),
                          OGR_FP( ProjCenterNorthing ) );
         break;
 
       case 9816:
         poSRS->SetTMG( OGR_FP( FalseOriginLat ), OGR_FP( FalseOriginLong ),
-                       OGR_FP( FalseOriginEasting ), 
+                       OGR_FP( FalseOriginEasting ),
                        OGR_FP( FalseOriginNorthing ) );
         break;
 
@@ -1607,14 +1581,14 @@ static OGRErr SetEPSGProjCS( OGRSpatialReference * poSRS, int nPCSCode )
               dfCenterLong = OGR_FP( PolarLongOrigin );
 
           double dfAzimuth = OGR_FP( CoLatConeAxis ); // See ticket #4223
-          if( dfAzimuth == 0.0 ) 
+          if( dfAzimuth == 0.0 )
               dfAzimuth = OGR_FP( Azimuth );
 
           poSRS->SetKrovak( OGR_FP( ProjCenterLat ), dfCenterLong,
-                            dfAzimuth, 
+                            dfAzimuth,
                             OGR_FP( PseudoStdParallelLat ),
                             OGR_FP( PseudoStdParallelScaleFactor ),
-                            OGR_FP( ProjCenterEasting ), 
+                            OGR_FP( ProjCenterEasting ),
                             OGR_FP( ProjCenterNorthing ) );
       }
       break;
@@ -1625,7 +1599,7 @@ static OGRErr SetEPSGProjCS( OGRSpatialReference * poSRS, int nPCSCode )
                         OGR_FP( FalseEasting ), OGR_FP( FalseNorthing ) );
         break;
 
-      case 9821: /* DEPREACTED : this is the spherical form, and really needs different
+      case 9821: /* DEPRECATED : this is the spherical form, and really needs different
                     equations which give different results but PROJ.4 doesn't
                     seem to support the spherical form. */
         poSRS->SetLAEA( OGR_FP( SphericalOriginLat ),
@@ -1634,8 +1608,8 @@ static OGRErr SetEPSGProjCS( OGRSpatialReference * poSRS, int nPCSCode )
         break;
 
       case 9822: /* Albers (Conic) Equal Area */
-        poSRS->SetACEA( OGR_FP( StdParallel1Lat ), 
-                        OGR_FP( StdParallel2Lat ), 
+        poSRS->SetACEA( OGR_FP( StdParallel1Lat ),
+                        OGR_FP( StdParallel2Lat ),
                         OGR_FP( FalseOriginLat ),
                         OGR_FP( FalseOriginLong ),
                         OGR_FP( FalseOriginEasting ),
@@ -1647,7 +1621,7 @@ static OGRErr SetEPSGProjCS( OGRSpatialReference * poSRS, int nPCSCode )
       case 1028:
       case 1029:
         poSRS->SetEquirectangular( OGR_FP( NatOriginLat ),
-                                   OGR_FP( NatOriginLong ), 
+                                   OGR_FP( NatOriginLong ),
                                    0.0, 0.0 );
         break;
 
@@ -1658,7 +1632,8 @@ static OGRErr SetEPSGProjCS( OGRSpatialReference * poSRS, int nPCSCode )
         break;
 
       case 9834: /* Lambert Cylindrical Equal Area (Spherical) bug #2659 */
-        poSRS->SetCEA( OGR_FP( StdParallel1Lat ), OGR_FP( NatOriginLong ), 
+      case 9835: /* Lambert Cylindrical Equal Area (Ellipsoidal) */
+        poSRS->SetCEA( OGR_FP( StdParallel1Lat ), OGR_FP( NatOriginLong ),
                        OGR_FP( FalseEasting ), OGR_FP( FalseNorthing ) );
         break;
 
@@ -1695,13 +1670,10 @@ static OGRErr SetEPSGVertCS( OGRSpatialReference * poSRS, int nVertCSCode )
 /* -------------------------------------------------------------------- */
 /*      Fetch record from the vertcs.csv or override file.              */
 /* -------------------------------------------------------------------- */
-    char        **papszRecord;
-    char        szSearchKey[24];
-    const char  *pszFilename;
-    
-    pszFilename = CSVFilename( "vertcs.override.csv" );
-    sprintf( szSearchKey, "%d", nVertCSCode );
-    papszRecord = CSVScanFileByName( pszFilename, "COORD_REF_SYS_CODE",
+    const char  *pszFilename = CSVFilename( "vertcs.override.csv" );
+    char szSearchKey[24] = { 0 };
+    snprintf( szSearchKey, sizeof(szSearchKey), "%d", nVertCSCode );
+    char **papszRecord = CSVScanFileByName( pszFilename, "COORD_REF_SYS_CODE",
                                      szSearchKey, CC_Integer );
 
     if( papszRecord == NULL )
@@ -1709,17 +1681,15 @@ static OGRErr SetEPSGVertCS( OGRSpatialReference * poSRS, int nVertCSCode )
         pszFilename = CSVFilename( "vertcs.csv" );
         papszRecord = CSVScanFileByName( pszFilename, "COORD_REF_SYS_CODE",
                                          szSearchKey, CC_Integer );
-        
     }
 
     if( papszRecord == NULL )
         return OGRERR_UNSUPPORTED_SRS;
 
-
 /* -------------------------------------------------------------------- */
 /*      Setup the basic VERT_CS.                                        */
 /* -------------------------------------------------------------------- */
-    poSRS->SetVertCS( 
+    poSRS->SetVertCS(
         CSLGetField( papszRecord,
                      CSVGetFileFieldId(pszFilename,
                                        "COORD_REF_SYS_NAME")),
@@ -1730,13 +1700,13 @@ static OGRErr SetEPSGVertCS( OGRSpatialReference * poSRS, int nVertCSCode )
 /* -------------------------------------------------------------------- */
 /*      Should we add a geoidgrids extension node?                      */
 /* -------------------------------------------------------------------- */
-    const char *pszMethod = 
-        CSLGetField( papszRecord, 
+    const char *pszMethod =
+        CSLGetField( papszRecord,
                      CSVGetFileFieldId(pszFilename,"COORD_OP_METHOD_CODE_1"));
     if( pszMethod && EQUAL(pszMethod,"9665") )
     {
-        const char *pszParm11 = 
-            CSLGetField( papszRecord, 
+        const char *pszParm11 =
+            CSLGetField( papszRecord,
                          CSVGetFileFieldId(pszFilename,"PARM_1_1"));
 
         poSRS->SetExtension( "VERT_CS|VERT_DATUM", "PROJ4_GRIDS", pszParm11 );
@@ -1753,12 +1723,13 @@ static OGRErr SetEPSGVertCS( OGRSpatialReference * poSRS, int nVertCSCode )
 /* -------------------------------------------------------------------- */
 /*      Set linear units.                                               */
 /* -------------------------------------------------------------------- */
-    char *pszUOMLengthName = NULL;
-    double dfInMeters;
     int nUOM_CODE = atoi(CSLGetField( papszRecord,
                                       CSVGetFileFieldId(pszFilename,
                                                         "UOM_CODE")));
 
+    char *pszUOMLengthName = NULL;
+    double dfInMeters = 0.0;
+
     if( !EPSGGetUOMLengthInfo( nUOM_CODE, &pszUOMLengthName, &dfInMeters ) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -1790,24 +1761,18 @@ static OGRErr SetEPSGCompdCS( OGRSpatialReference * poSRS, int nCCSCode )
 /* -------------------------------------------------------------------- */
 /*      Fetch record from the compdcs.csv or override file.             */
 /* -------------------------------------------------------------------- */
-    char        **papszRecord = NULL;
-    char        szSearchKey[24];
-    const char  *pszFilename;
-    
-    sprintf( szSearchKey, "%d", nCCSCode );
+    char szSearchKey[24] = { 0 };
+    snprintf( szSearchKey, sizeof(szSearchKey), "%d", nCCSCode );
 
-// So far no override file needed.    
+// So far no override file needed.
 //    pszFilename = CSVFilename( "compdcs.override.csv" );
 //    papszRecord = CSVScanFileByName( pszFilename, "COORD_REF_SYS_CODE",
 //                                     szSearchKey, CC_Integer );
 
     //if( papszRecord == NULL )
-    {
-        pszFilename = CSVFilename( "compdcs.csv" );
-        papszRecord = CSVScanFileByName( pszFilename, "COORD_REF_SYS_CODE",
-                                         szSearchKey, CC_Integer );
-        
-    }
+    const char  *pszFilename = CSVFilename( "compdcs.csv" );
+    char **papszRecord = CSVScanFileByName( pszFilename, "COORD_REF_SYS_CODE",
+                                            szSearchKey, CC_Integer );
 
     if( papszRecord == NULL )
         return OGRERR_UNSUPPORTED_SRS;
@@ -1826,19 +1791,17 @@ static OGRErr SetEPSGCompdCS( OGRSpatialReference * poSRS, int nCCSCode )
 /* -------------------------------------------------------------------- */
 /*      Set the COMPD_CS node with a name.                              */
 /* -------------------------------------------------------------------- */
-    poSRS->SetNode( "COMPD_CS", 
+    poSRS->SetNode( "COMPD_CS",
                     CSLGetField( papszRecord,
                                  CSVGetFileFieldId(pszFilename,
                                                    "COORD_REF_SYS_NAME")) );
 
 /* -------------------------------------------------------------------- */
-/*      Lookup the the projected coordinate system.  Can the            */
+/*      Lookup the projected coordinate system.  Can the            */
 /*      horizontal CRS be a GCS?                                        */
 /* -------------------------------------------------------------------- */
     OGRSpatialReference oPCS;
-    OGRErr eErr;
-
-    eErr = SetEPSGProjCS( &oPCS, nPCSCode );
+    OGRErr eErr = SetEPSGProjCS( &oPCS, nPCSCode );
     if( eErr != OGRERR_NONE )
     {
         // perhaps it is a GCS?
@@ -1850,7 +1813,7 @@ static OGRErr SetEPSGCompdCS( OGRSpatialReference * poSRS, int nCCSCode )
         return eErr;
     }
 
-    poSRS->GetRoot()->AddChild( 
+    poSRS->GetRoot()->AddChild(
         oPCS.GetRoot()->Clone() );
 
 /* -------------------------------------------------------------------- */
@@ -1861,7 +1824,7 @@ static OGRErr SetEPSGCompdCS( OGRSpatialReference * poSRS, int nCCSCode )
     if( eErr != OGRERR_NONE )
         return eErr;
 
-    poSRS->GetRoot()->AddChild( 
+    poSRS->GetRoot()->AddChild(
         oVertCS.GetRoot()->Clone() );
 
 /* -------------------------------------------------------------------- */
@@ -1882,24 +1845,18 @@ static OGRErr SetEPSGGeocCS( OGRSpatialReference * poSRS, int nGCSCode )
 /* -------------------------------------------------------------------- */
 /*      Fetch record from the geoccs.csv or override file.              */
 /* -------------------------------------------------------------------- */
-    char        **papszRecord = NULL;
-    char        szSearchKey[24];
-    const char  *pszFilename;
-    
-    sprintf( szSearchKey, "%d", nGCSCode );
+    char szSearchKey[24] = { 0 };
+    snprintf( szSearchKey, sizeof(szSearchKey), "%d", nGCSCode );
 
-// So far no override file needed.    
+// So far no override file needed.
 //    pszFilename = CSVFilename( "compdcs.override.csv" );
 //    papszRecord = CSVScanFileByName( pszFilename, "COORD_REF_SYS_CODE",
 //                                     szSearchKey, CC_Integer );
 
     //if( papszRecord == NULL )
-    {
-        pszFilename = CSVFilename( "geoccs.csv" );
-        papszRecord = CSVScanFileByName( pszFilename, "COORD_REF_SYS_CODE",
-                                         szSearchKey, CC_Integer );
-        
-    }
+    const char *pszFilename = CSVFilename( "geoccs.csv" );
+    char **papszRecord = CSVScanFileByName( pszFilename, "COORD_REF_SYS_CODE",
+                                            szSearchKey, CC_Integer );
 
     if( papszRecord == NULL )
         return OGRERR_UNSUPPORTED_SRS;
@@ -1915,27 +1872,23 @@ static OGRErr SetEPSGGeocCS( OGRSpatialReference * poSRS, int nGCSCode )
 /* -------------------------------------------------------------------- */
 /*      Get datum related information.                                  */
 /* -------------------------------------------------------------------- */
-    int nDatumCode, nEllipsoidCode, nPMCode;
-    char *pszDatumName;
-    
-    nDatumCode = atoi(CSLGetField( papszRecord,
-                                   CSVGetFileFieldId(pszFilename,
-                                                     "DATUM_CODE")));
-    
-    pszDatumName = 
+    const int nDatumCode = atoi(CSLGetField( papszRecord,
+                                             CSVGetFileFieldId(pszFilename,
+                                                               "DATUM_CODE")));
+
+    char *pszDatumName =
         CPLStrdup( CSLGetField( papszRecord,
                                 CSVGetFileFieldId(pszFilename,"DATUM_NAME") ) );
     OGREPSGDatumNameMassage( &pszDatumName );
 
 
-    nEllipsoidCode = atoi(CSLGetField( papszRecord,
-                                   CSVGetFileFieldId(pszFilename,
-                                                     "ELLIPSOID_CODE")));
-    
-    nPMCode = atoi(CSLGetField( papszRecord,
-                                CSVGetFileFieldId(pszFilename,
-                                                  "PRIME_MERIDIAN_CODE")));
-    
+    const int nEllipsoidCode = atoi(CSLGetField(
+        papszRecord, CSVGetFileFieldId(pszFilename, "ELLIPSOID_CODE")));
+
+    const int nPMCode = atoi(CSLGetField(
+        papszRecord, CSVGetFileFieldId(pszFilename,
+                                       "PRIME_MERIDIAN_CODE")));
+
 /* -------------------------------------------------------------------- */
 /*      Get prime meridian information.                                 */
 /* -------------------------------------------------------------------- */
@@ -1952,9 +1905,9 @@ static OGRErr SetEPSGGeocCS( OGRSpatialReference * poSRS, int nGCSCode )
 /*      Get the ellipsoid information.                                  */
 /* -------------------------------------------------------------------- */
     char *pszEllipsoidName = NULL;
-    double dfSemiMajor, dfInvFlattening; 
+    double dfSemiMajor, dfInvFlattening;
 
-    if( OSRGetEllipsoidInfo( nEllipsoidCode, &pszEllipsoidName, 
+    if( OSRGetEllipsoidInfo( nEllipsoidCode, &pszEllipsoidName,
                              &dfSemiMajor, &dfInvFlattening ) != OGRERR_NONE )
     {
         CPLFree( pszDatumName );
@@ -1965,15 +1918,14 @@ static OGRErr SetEPSGGeocCS( OGRSpatialReference * poSRS, int nGCSCode )
 /* -------------------------------------------------------------------- */
 /*      Setup the spheroid.                                             */
 /* -------------------------------------------------------------------- */
-    char                szValue[128];
-
     OGR_SRSNode *poSpheroid = new OGR_SRSNode( "SPHEROID" );
     poSpheroid->AddChild( new OGR_SRSNode( pszEllipsoidName ) );
 
-    OGRPrintDouble( szValue, dfSemiMajor );
+    char szValue[128] = { 0 };
+    OGRsnPrintDouble( szValue, sizeof(szValue), dfSemiMajor );
     poSpheroid->AddChild( new OGR_SRSNode(szValue) );
 
-    OGRPrintDouble( szValue, dfInvFlattening );
+    OGRsnPrintDouble( szValue, sizeof(szValue), dfInvFlattening );
     poSpheroid->AddChild( new OGR_SRSNode(szValue) );
 
     CPLFree( pszEllipsoidName );
@@ -1995,8 +1947,8 @@ static OGRErr SetEPSGGeocCS( OGRSpatialReference * poSRS, int nGCSCode )
     if( dfPMOffset == 0.0 )
         strcpy( szValue, "0" );
     else
-        OGRPrintDouble( szValue, dfPMOffset );
-    
+        OGRsnPrintDouble( szValue, sizeof(szValue), dfPMOffset );
+
     OGR_SRSNode *poPM = new OGR_SRSNode( "PRIMEM" );
     poPM->AddChild( new OGR_SRSNode( pszPMName ) );
     poPM->AddChild( new OGR_SRSNode( szValue ) );
@@ -2008,17 +1960,16 @@ static OGRErr SetEPSGGeocCS( OGRSpatialReference * poSRS, int nGCSCode )
 /* -------------------------------------------------------------------- */
 /*      Should we try to lookup a datum transform?                      */
 /* -------------------------------------------------------------------- */
-#ifdef notdef
+#if 0
     if( EPSGGetWGS84Transform( nGeogCS, adfBursaTransform ) )
     {
-        OGR_SRSNode     *poWGS84;
-        char            szValue[100];
+        char szValue[100] = { 0 };
 
-        poWGS84 = new OGR_SRSNode( "TOWGS84" );
+        OGR_SRSNode *poWGS84 = new OGR_SRSNode( "TOWGS84" );
 
         for( int iCoeff = 0; iCoeff < 7; iCoeff++ )
         {
-            CPLsprintf( szValue, "%g", adfBursaTransform[iCoeff] );
+            CPLsnprintf( szValue, sizeof(szValue), "%g", adfBursaTransform[iCoeff] );
             poWGS84->AddChild( new OGR_SRSNode( szValue ) );
         }
 
@@ -2029,12 +1980,12 @@ static OGRErr SetEPSGGeocCS( OGRSpatialReference * poSRS, int nGCSCode )
 /* -------------------------------------------------------------------- */
 /*      Set linear units.                                               */
 /* -------------------------------------------------------------------- */
-    char *pszUOMLengthName = NULL;
-    double dfInMeters = 1.0;
     int nUOMLength = atoi(CSLGetField( papszRecord,
                                        CSVGetFileFieldId(pszFilename,
                                                          "UOM_CODE")));
-    
+
+    double dfInMeters = 1.0;
+    char *pszUOMLengthName = NULL;
     if( !EPSGGetUOMLengthInfo( nUOMLength, &pszUOMLengthName, &dfInMeters ) )
     {
         return OGRERR_UNSUPPORTED_SRS;
@@ -2054,14 +2005,14 @@ static OGRErr SetEPSGGeocCS( OGRSpatialReference * poSRS, int nGCSCode )
     poAxis->AddChild( new OGR_SRSNode( OSRAxisEnumToName(OAO_Other) ) );
 
     poSRS->GetRoot()->AddChild( poAxis );
-    
+
     poAxis = new OGR_SRSNode( "AXIS" );
 
     poAxis->AddChild( new OGR_SRSNode( "Geocentric Y" ) );
     poAxis->AddChild( new OGR_SRSNode( OSRAxisEnumToName(OAO_Other) ) );
 
     poSRS->GetRoot()->AddChild( poAxis );
-    
+
     poAxis = new OGR_SRSNode( "AXIS" );
 
     poAxis->AddChild( new OGR_SRSNode( "Geocentric Z" ) );
@@ -2093,21 +2044,21 @@ static OGRErr SetEPSGGeocCS( OGRSpatialReference * poSRS, int nGCSCode )
  *
  * This method will initialize the spatial reference based on the
  * passed in EPSG GCS or PCS code.  The coordinate system definitions
- * are normally read from the EPSG derived support files such as 
- * pcs.csv, gcs.csv, pcs.override.csv, gcs.override.csv and falling 
- * back to search for a PROJ.4 epsg init file or a definition in epsg.wkt. 
+ * are normally read from the EPSG derived support files such as
+ * pcs.csv, gcs.csv, pcs.override.csv, gcs.override.csv and falling
+ * back to search for a PROJ.4 epsg init file or a definition in epsg.wkt.
  *
  * These support files are normally searched for in /usr/local/share/gdal
  * or in the directory identified by the GDAL_DATA configuration option.
  * See CPLFindFile() for details.
- * 
+ *
  * This method is relatively expensive, and generally involves quite a bit
  * of text file scanning.  Reasonable efforts should be made to avoid calling
- * it many times for the same coordinate system. 
- * 
- * This method is similar to importFromEPSGA() except that EPSG preferred 
+ * it many times for the same coordinate system.
+ *
+ * This method is similar to importFromEPSGA() except that EPSG preferred
  * axis ordering will *not* be applied for geographic coordinate systems.
- * EPSG normally defines geographic coordinate systems to use lat/long 
+ * EPSG normally defines geographic coordinate systems to use lat/long
  * contrary to typical GIS use). Since OGR 1.10.0, EPSG preferred
  * axis ordering will also *not* be applied for projected coordinate systems
  * that use northing/easting order.
@@ -2115,7 +2066,7 @@ static OGRErr SetEPSGGeocCS( OGRSpatialReference * poSRS, int nGCSCode )
  * This method is the same as the C function OSRImportFromEPSG().
  *
  * @param nCode a GCS or PCS code from the horizontal coordinate system table.
- * 
+ *
  * @return OGRERR_NONE on success, or an error code on failure.
  */
 
@@ -2153,9 +2104,10 @@ OGRErr OGRSpatialReference::importFromEPSG( int nCode )
 OGRErr CPL_STDCALL OSRImportFromEPSG( OGRSpatialReferenceH hSRS, int nCode )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRImportFromEPSG", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRImportFromEPSG", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->importFromEPSG( nCode );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
+        importFromEPSG( nCode );
 }
 
 /************************************************************************/
@@ -2166,9 +2118,9 @@ OGRErr CPL_STDCALL OSRImportFromEPSG( OGRSpatialReferenceH hSRS, int nCode )
  * \brief Initialize SRS based on EPSG GCS or PCS code.
  *
  * This method will initialize the spatial reference based on the
- * passed in EPSG GCS or PCS code.  
- * 
- * This method is similar to importFromEPSG() except that EPSG preferred 
+ * passed in EPSG GCS or PCS code.
+ *
+ * This method is similar to importFromEPSG() except that EPSG preferred
  * axis ordering *will* be applied for geographic and projected coordinate systems.
  * EPSG normally defines geographic coordinate systems to use lat/long, and
  * also there are also a few projected coordinate systems that use northing/easting
@@ -2178,15 +2130,13 @@ OGRErr CPL_STDCALL OSRImportFromEPSG( OGRSpatialReferenceH hSRS, int nCode )
  * This method is the same as the C function OSRImportFromEPSGA().
  *
  * @param nCode a GCS or PCS code from the horizontal coordinate system table.
- * 
+ *
  * @return OGRERR_NONE on success, or an error code on failure.
  */
 
 OGRErr OGRSpatialReference::importFromEPSGA( int nCode )
 
 {
-    OGRErr  eErr;
-
     bNormInfoSet = FALSE;
 
 /* -------------------------------------------------------------------- */
@@ -2202,13 +2152,13 @@ OGRErr OGRSpatialReference::importFromEPSGA( int nCode )
 /*      Verify that we can find the required filename(s).               */
 /* -------------------------------------------------------------------- */
     if( CSVScanFileByName( CSVFilename( "gcs.csv" ),
-                           "COORD_REF_SYS_CODE", 
+                           "COORD_REF_SYS_CODE",
                            "4269", CC_Integer ) == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "Unable to open EPSG support file %s.\n"
                   "Try setting the GDAL_DATA environment variable to point to the\n"
-                  "directory containing EPSG csv files.", 
+                  "directory containing EPSG csv files.",
                   CSVFilename( "gcs.csv" ) );
         return OGRERR_FAILURE;
     }
@@ -2216,7 +2166,7 @@ OGRErr OGRSpatialReference::importFromEPSGA( int nCode )
 /* -------------------------------------------------------------------- */
 /*      Try this as various sorts of objects till one works.            */
 /* -------------------------------------------------------------------- */
-    eErr = SetEPSGGeogCS( this, nCode );
+    OGRErr eErr = SetEPSGGeogCS( this, nCode );
     if( eErr == OGRERR_UNSUPPORTED_SRS )
         eErr = SetEPSGProjCS( this, nCode );
     if( eErr == OGRERR_UNSUPPORTED_SRS )
@@ -2232,8 +2182,8 @@ OGRErr OGRSpatialReference::importFromEPSGA( int nCode )
 /* -------------------------------------------------------------------- */
     if( eErr == OGRERR_UNSUPPORTED_SRS )
     {
-        char szCode[32];
-        sprintf( szCode, "%d", nCode );
+        char szCode[32] = { 0 };
+        snprintf( szCode, sizeof(szCode), "%d", nCode );
         eErr = importFromDict( "epsg.wkt", szCode );
     }
 
@@ -2243,16 +2193,14 @@ OGRErr OGRSpatialReference::importFromEPSGA( int nCode )
 /* -------------------------------------------------------------------- */
     if( eErr == OGRERR_UNSUPPORTED_SRS )
     {
-        char szWrkDefn[100];
-        char *pszNormalized;
+        char szWrkDefn[100] = { 0 };
+        snprintf( szWrkDefn, sizeof(szWrkDefn), "+init=epsg:%d", nCode );
 
-        sprintf( szWrkDefn, "+init=epsg:%d", nCode );
-        
-        pszNormalized = OCTProj4Normalize( szWrkDefn );
+        char *pszNormalized = OCTProj4Normalize( szWrkDefn );
 
         if( strstr(pszNormalized,"proj=") != NULL )
             eErr = importFromProj4( pszNormalized );
-        
+
         CPLFree( pszNormalized );
     }
 
@@ -2260,7 +2208,7 @@ OGRErr OGRSpatialReference::importFromEPSGA( int nCode )
 /*      Push in authority information if we were successful, and it     */
 /*      is not already present.                                         */
 /* -------------------------------------------------------------------- */
-    const char *pszAuthName;
+    const char *pszAuthName = NULL;
 
     if( IsProjected() )
         pszAuthName = GetAuthorityName( "PROJCS" );
@@ -2282,7 +2230,8 @@ OGRErr OGRSpatialReference::importFromEPSGA( int nCode )
     if( eErr == OGRERR_UNSUPPORTED_SRS )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
-                  "EPSG PCS/GCS code %d not found in EPSG support files.  Is this a valid\nEPSG coordinate system?", 
+                  "EPSG PCS/GCS code %d not found in EPSG support files.  "
+                  "Is this a valid\nEPSG coordinate system?",
                   nCode );
     }
 
@@ -2292,7 +2241,7 @@ OGRErr OGRSpatialReference::importFromEPSGA( int nCode )
 /*      ordering.                                                       */
 /* -------------------------------------------------------------------- */
     if( eErr == OGRERR_NONE )
-    {    
+    {
         eErr = FixupOrdering();
     }
 
@@ -2312,9 +2261,10 @@ OGRErr OGRSpatialReference::importFromEPSGA( int nCode )
 OGRErr CPL_STDCALL OSRImportFromEPSGA( OGRSpatialReferenceH hSRS, int nCode )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRImportFromEPSGA", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRImportFromEPSGA", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->importFromEPSGA( nCode );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
+        importFromEPSGA( nCode );
 }
 
 /************************************************************************/
@@ -2332,19 +2282,19 @@ OGRErr CPL_STDCALL OSRImportFromEPSGA( OGRSpatialReferenceH hSRS, int nCode )
  * This method is the same as the C function OSRSetStatePlaneWithUnits().
  *
  * @param nZone State plane zone number, in the USGS numbering scheme (as
- * dinstinct from the Arc/Info and Erdas numbering scheme. 
+ * distinct from the Arc/Info and Erdas numbering scheme.
  *
  * @param bNAD83 TRUE if the NAD83 zone definition should be used or FALSE
- * if the NAD27 zone definition should be used.  
+ * if the NAD27 zone definition should be used.
  *
- * @param pszOverrideUnitName Linear unit name to apply overriding the 
+ * @param pszOverrideUnitName Linear unit name to apply overriding the
  * legal definition for this zone.
  *
  * @param dfOverrideUnit Linear unit conversion factor to apply overriding
- * the legal definition for this zone. 
- * 
+ * the legal definition for this zone.
+ *
  * @return OGRERR_NONE on success, or OGRERR_FAILURE on failure, mostly likely
- * due to the EPSG tables not being accessable. 
+ * due to the EPSG tables not being accessible.
  */
 
 OGRErr OGRSpatialReference::SetStatePlane( int nZone, int bNAD83,
@@ -2352,13 +2302,11 @@ OGRErr OGRSpatialReference::SetStatePlane( int nZone, int bNAD83,
                                            double dfOverrideUnit )
 
 {
-    int         nAdjustedId;
-    int         nPCSCode;
-    char        szID[32];
 
 /* -------------------------------------------------------------------- */
 /*      Get the index id from stateplane.csv.                           */
 /* -------------------------------------------------------------------- */
+    int nAdjustedId = 0;
     if( bNAD83 )
         nAdjustedId = nZone;
     else
@@ -2369,20 +2317,20 @@ OGRErr OGRSpatialReference::SetStatePlane( int nZone, int bNAD83,
 /*      PCS corresponding to each Proj_ code since the proj code        */
 /*      already effectively indicates NAD27 or NAD83.                   */
 /* -------------------------------------------------------------------- */
-    sprintf( szID, "%d", nAdjustedId );
-    nPCSCode =
+    char szID[32] = { 0 };
+    snprintf( szID, sizeof(szID), "%d", nAdjustedId );
+    const int nPCSCode =
         atoi( CSVGetField( CSVFilename( "stateplane.csv" ),
                            "ID", szID, CC_Integer,
                            "EPSG_PCS_CODE" ) );
     if( nPCSCode < 1 )
     {
-        char    szName[128];
-        static int bFailureReported = FALSE;
+        static bool bFailureReported = false;
 
         if( !bFailureReported )
         {
-            bFailureReported = TRUE;
-            CPLError( CE_Warning, CPLE_OpenFailed, 
+            bFailureReported = true;
+            CPLError( CE_Warning, CPLE_OpenFailed,
                       "Unable to find state plane zone in stateplane.csv,\n"
                       "likely because the GDAL data files cannot be found.  Using\n"
                       "incomplete definition of state plane zone.\n" );
@@ -2391,13 +2339,15 @@ OGRErr OGRSpatialReference::SetStatePlane( int nZone, int bNAD83,
         Clear();
         if( bNAD83 )
         {
-            sprintf( szName, "State Plane Zone %d / NAD83", nZone );
+            char szName[128] = { 0 };
+            snprintf( szName, sizeof(szName), "State Plane Zone %d / NAD83", nZone );
             SetLocalCS( szName );
             SetLinearUnits( SRS_UL_METER, 1.0 );
         }
         else
         {
-            sprintf( szName, "State Plane Zone %d / NAD27", nZone );
+            char szName[128] = { 0 };
+            snprintf( szName, sizeof(szName), "State Plane Zone %d / NAD27", nZone );
             SetLocalCS( szName );
             SetLinearUnits( SRS_UL_US_FOOT, CPLAtof(SRS_UL_US_FOOT_CONV) );
         }
@@ -2419,19 +2369,18 @@ OGRErr OGRSpatialReference::SetStatePlane( int nZone, int bNAD83,
 /*      We will need to adjust the linear projection parameter to       */
 /*      match the provided units, and clear the authority code.         */
 /* -------------------------------------------------------------------- */
-    if( dfOverrideUnit != 0.0 
+    if( dfOverrideUnit != 0.0
         && fabs(dfOverrideUnit - GetLinearUnits()) > 0.0000000001 )
     {
-        double dfFalseEasting = GetNormProjParm( SRS_PP_FALSE_EASTING );
-        double dfFalseNorthing= GetNormProjParm( SRS_PP_FALSE_NORTHING);
-        OGR_SRSNode *poPROJCS;
+        const double dfFalseEasting = GetNormProjParm( SRS_PP_FALSE_EASTING );
+        const double dfFalseNorthing = GetNormProjParm( SRS_PP_FALSE_NORTHING);
 
         SetLinearUnits( pszOverrideUnitName, dfOverrideUnit );
-        
+
         SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
         SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
 
-        poPROJCS = GetAttrNode( "PROJCS" );
+        OGR_SRSNode * const poPROJCS = GetAttrNode( "PROJCS" );
         if( poPROJCS != NULL && poPROJCS->FindChild( "AUTHORITY" ) != -1 )
         {
             poPROJCS->DestroyChild( poPROJCS->FindChild( "AUTHORITY" ) );
@@ -2449,14 +2398,15 @@ OGRErr OGRSpatialReference::SetStatePlane( int nZone, int bNAD83,
  * \brief Set State Plane projection definition.
  *
  * This function is the same as OGRSpatialReference::SetStatePlane().
- */ 
- 
+ */
+
 OGRErr OSRSetStatePlane( OGRSpatialReferenceH hSRS, int nZone, int bNAD83 )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetStatePlane", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetStatePlane", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetStatePlane( nZone, bNAD83 );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
+        SetStatePlane( nZone, bNAD83 );
 }
 
 /************************************************************************/
@@ -2467,19 +2417,20 @@ OGRErr OSRSetStatePlane( OGRSpatialReferenceH hSRS, int nZone, int bNAD83 )
  * \brief Set State Plane projection definition.
  *
  * This function is the same as OGRSpatialReference::SetStatePlane().
- */ 
- 
-OGRErr OSRSetStatePlaneWithUnits( OGRSpatialReferenceH hSRS, 
+ */
+
+OGRErr OSRSetStatePlaneWithUnits( OGRSpatialReferenceH hSRS,
                                   int nZone, int bNAD83,
                                   const char *pszOverrideUnitName,
                                   double dfOverrideUnit )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetStatePlaneWithUnits", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetStatePlaneWithUnits", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetStatePlane( nZone, bNAD83,
-                                                          pszOverrideUnitName,
-                                                          dfOverrideUnit );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
+        SetStatePlane( nZone, bNAD83,
+                       pszOverrideUnitName,
+                       dfOverrideUnit );
 }
 
 /************************************************************************/
@@ -2516,21 +2467,19 @@ int OGRSpatialReference::GetEPSGGeogCS()
 /* -------------------------------------------------------------------- */
 /*      Is this a "well known" geographic coordinate system?            */
 /* -------------------------------------------------------------------- */
-    int bWGS, bNAD;
-
-    bWGS = strstr(pszGEOGCS,"WGS") != NULL
+    const int bWGS = strstr(pszGEOGCS,"WGS") != NULL
         || strstr(pszDatum, "WGS")
         || strstr(pszGEOGCS,"World Geodetic System")
         || strstr(pszGEOGCS,"World_Geodetic_System")
         || strstr(pszDatum, "World Geodetic System")
-        || strstr(pszDatum, "World_Geodetic_System"); 
+        || strstr(pszDatum, "World_Geodetic_System");
 
-    bNAD = strstr(pszGEOGCS,"NAD") != NULL
+    const int bNAD = strstr(pszGEOGCS,"NAD") != NULL
         || strstr(pszDatum, "NAD")
         || strstr(pszGEOGCS,"North American")
         || strstr(pszGEOGCS,"North_American")
         || strstr(pszDatum, "North American")
-        || strstr(pszDatum, "North_American"); 
+        || strstr(pszDatum, "North_American");
 
     if( bWGS && (strstr(pszGEOGCS,"84") || strstr(pszDatum,"84")) )
         return 4326;
@@ -2550,12 +2499,12 @@ int OGRSpatialReference::GetEPSGGeogCS()
 /* -------------------------------------------------------------------- */
     pszAuthName = GetAuthorityName( "GEOGCS|DATUM" );
 
-    if( pszAuthName != NULL 
-        && EQUAL(pszAuthName,"epsg") 
+    if( pszAuthName != NULL
+        && EQUAL(pszAuthName,"epsg")
         && GetPrimeMeridian() == 0.0 )
     {
-        int nDatum = atoi(GetAuthorityCode("GEOGCS|DATUM"));
-        
+        const int nDatum = atoi(GetAuthorityCode("GEOGCS|DATUM"));
+
         if( nDatum >= 6000 && nDatum <= 6999 )
             return nDatum - 2000;
     }
@@ -2571,17 +2520,17 @@ int OGRSpatialReference::GetEPSGGeogCS()
  * \brief Set EPSG authority info if possible.
  *
  * This method inspects a WKT definition, and adds EPSG authority nodes
- * where an aspect of the coordinate system can be easily and safely 
- * corresponded with an EPSG identifier.  In practice, this method will 
+ * where an aspect of the coordinate system can be easily and safely
+ * corresponded with an EPSG identifier.  In practice, this method will
  * evolve over time.  In theory it can add authority nodes for any object
- * (ie. spheroid, datum, GEOGCS, units, and PROJCS) that could have an 
- * authority node.  Mostly this is useful to inserting appropriate 
- * PROJCS codes for common formulations (like UTM n WGS84). 
+ * (i.e. spheroid, datum, GEOGCS, units, and PROJCS) that could have an
+ * authority node.  Mostly this is useful to inserting appropriate
+ * PROJCS codes for common formulations (like UTM n WGS84).
  *
- * If it success the OGRSpatialReference is updated in place, and the 
- * method return OGRERR_NONE.  If the method fails to identify the 
- * general coordinate system OGRERR_UNSUPPORTED_SRS is returned but no 
- * error message is posted via CPLError(). 
+ * If it success the OGRSpatialReference is updated in place, and the
+ * method return OGRERR_NONE.  If the method fails to identify the
+ * general coordinate system OGRERR_UNSUPPORTED_SRS is returned but no
+ * error message is posted via CPLError().
  *
  * This method is the same as the C function OSRAutoIdentifyEPSG().
  *
@@ -2595,10 +2544,10 @@ OGRErr OGRSpatialReference::AutoIdentifyEPSG()
 /*      Do we have a GEOGCS node, but no authority?  If so, try         */
 /*      guessing it.                                                    */
 /* -------------------------------------------------------------------- */
-    if( (IsProjected() || IsGeographic()) 
+    if( (IsProjected() || IsGeographic())
         && GetAuthorityCode( "GEOGCS" ) == NULL )
     {
-        int nGCS = GetEPSGGeogCS();
+        const int nGCS = GetEPSGGeogCS();
         if( nGCS != -1 )
             SetAuthority( "GEOGCS", "EPSG", nGCS );
     }
@@ -2606,8 +2555,9 @@ OGRErr OGRSpatialReference::AutoIdentifyEPSG()
 /* -------------------------------------------------------------------- */
 /*      Is this a UTM coordinate system with a common GEOGCS?           */
 /* -------------------------------------------------------------------- */
-    int nZone, bNorth;
-    if( (nZone = GetUTMZone( &bNorth )) != 0 
+    int nZone = 0;
+    int bNorth = FALSE;
+    if( (nZone = GetUTMZone( &bNorth )) != 0
         && GetAuthorityCode( "PROJCS") == NULL )
     {
         const char *pszAuthName, *pszAuthCode;
@@ -2621,12 +2571,12 @@ OGRErr OGRSpatialReference::AutoIdentifyEPSG()
         }
         else if( EQUAL(pszAuthName,"EPSG") && atoi(pszAuthCode) == 4326 )
         { // WGS84
-            if( bNorth ) 
+            if( bNorth )
                 SetAuthority( "PROJCS", "EPSG", 32600 + nZone );
             else
                 SetAuthority( "PROJCS", "EPSG", 32700 + nZone );
         }
-        else if( EQUAL(pszAuthName,"EPSG") && atoi(pszAuthCode) == 4267 
+        else if( EQUAL(pszAuthName,"EPSG") && atoi(pszAuthCode) == 4267
                  && nZone >= 3 && nZone <= 22 && bNorth )
             SetAuthority( "PROJCS", "EPSG", 26700 + nZone ); // NAD27
         else if( EQUAL(pszAuthName,"EPSG") && atoi(pszAuthCode) == 4269
@@ -2634,7 +2584,7 @@ OGRErr OGRSpatialReference::AutoIdentifyEPSG()
             SetAuthority( "PROJCS", "EPSG", 26900 + nZone ); // NAD83
         else if( EQUAL(pszAuthName,"EPSG") && atoi(pszAuthCode) == 4322 )
         { // WGS72
-            if( bNorth ) 
+            if( bNorth )
                 SetAuthority( "PROJCS", "EPSG", 32200 + nZone );
             else
                 SetAuthority( "PROJCS", "EPSG", 32300 + nZone );
@@ -2646,10 +2596,11 @@ OGRErr OGRSpatialReference::AutoIdentifyEPSG()
 /* -------------------------------------------------------------------- */
     if( IsProjected() && GetAuthorityCode("PROJCS") != NULL )
         return OGRERR_NONE;
-    else if( IsGeographic() && GetAuthorityCode("GEOGCS") != NULL )
+
+    if( IsGeographic() && GetAuthorityCode("GEOGCS") != NULL )
         return OGRERR_NONE;
-    else
-        return OGRERR_UNSUPPORTED_SRS;
+
+    return OGRERR_UNSUPPORTED_SRS;
 }
 
 /************************************************************************/
@@ -2660,14 +2611,14 @@ OGRErr OGRSpatialReference::AutoIdentifyEPSG()
  * \brief Set EPSG authority info if possible.
  *
  * This function is the same as OGRSpatialReference::AutoIdentifyEPSG().
- */ 
- 
+ */
+
 OGRErr OSRAutoIdentifyEPSG( OGRSpatialReferenceH hSRS )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRAutoIdentifyEPSG", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRAutoIdentifyEPSG", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->AutoIdentifyEPSG();
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->AutoIdentifyEPSG();
 }
 
 /************************************************************************/
@@ -2681,15 +2632,15 @@ OGRErr OSRAutoIdentifyEPSG( OGRSpatialReferenceH hSRS )
  * Currently this returns TRUE for all geographic coordinate systems
  * with an EPSG code set, and AXIS values set defining it as lat, long.
  * Note that coordinate systems with an EPSG code and no axis settings
- * will be assumed to not be lat/long.  
+ * will be assumed to not be lat/long.
  *
  * FALSE will be returned for all coordinate systems that are not geographic,
- * or that do not have an EPSG code set. 
+ * or that do not have an EPSG code set.
  *
  * This method is the same as the C function OSREPSGTreatsAsLatLong().
  *
- * @return TRUE or FALSE. 
- */ 
+ * @return TRUE or FALSE.
+ */
 
 int OGRSpatialReference::EPSGTreatsAsLatLong()
 
@@ -2702,12 +2653,12 @@ int OGRSpatialReference::EPSGTreatsAsLatLong()
     if( pszAuth == NULL || !EQUAL(pszAuth,"EPSG") )
         return FALSE;
 
-    OGR_SRSNode *poFirstAxis = GetAttrNode( "GEOGCS|AXIS" );
+    OGR_SRSNode * const poFirstAxis = GetAttrNode( "GEOGCS|AXIS" );
 
     if( poFirstAxis == NULL )
         return FALSE;
 
-    if( poFirstAxis->GetChildCount() >= 2 
+    if( poFirstAxis->GetChildCount() >= 2
         && EQUAL(poFirstAxis->GetChild(1)->GetValue(),"NORTH") )
         return TRUE;
 
@@ -2723,14 +2674,14 @@ int OGRSpatialReference::EPSGTreatsAsLatLong()
  * system should be treated as having lat/long coordinate ordering.
  *
  * This function is the same as OGRSpatialReference::OSREPSGTreatsAsLatLong().
- */ 
- 
+ */
+
 int OSREPSGTreatsAsLatLong( OGRSpatialReferenceH hSRS )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSREPSGTreatsAsLatLong", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSREPSGTreatsAsLatLong", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->EPSGTreatsAsLatLong();
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->EPSGTreatsAsLatLong();
 }
 
 /************************************************************************/
@@ -2765,7 +2716,7 @@ int OGRSpatialReference::EPSGTreatsAsNorthingEasting()
     if( pszAuth == NULL || !EQUAL(pszAuth,"EPSG") )
         return FALSE;
 
-    OGR_SRSNode *poFirstAxis = GetAttrNode( "PROJCS|AXIS" );
+    OGR_SRSNode * const poFirstAxis = GetAttrNode( "PROJCS|AXIS" );
 
     if( poFirstAxis == NULL )
         return FALSE;
@@ -2785,7 +2736,8 @@ int OGRSpatialReference::EPSGTreatsAsNorthingEasting()
  * \brief This function returns TRUE if EPSG feels this geographic coordinate
  * system should be treated as having northing/easting coordinate ordering.
  *
- * This function is the same as OGRSpatialReference::EPSGTreatsAsNorthingEasting().
+ * This function is the same as
+ * OGRSpatialReference::EPSGTreatsAsNorthingEasting().
  *
  * @since OGR 1.10.0
  */
@@ -2793,7 +2745,8 @@ int OGRSpatialReference::EPSGTreatsAsNorthingEasting()
 int OSREPSGTreatsAsNorthingEasting( OGRSpatialReferenceH hSRS )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSREPSGTreatsAsNorthingEasting", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSREPSGTreatsAsNorthingEasting", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->EPSGTreatsAsNorthingEasting();
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
+        EPSGTreatsAsNorthingEasting();
 }
diff --git a/ogr/ogr_geocoding.cpp b/ogr/ogr_geocoding.cpp
index b29e76d..736e7d9 100644
--- a/ogr/ogr_geocoding.cpp
+++ b/ogr/ogr_geocoding.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_geocoding.cpp 28459 2015-02-12 13:48:21Z rouault $
+ * $Id: ogr_geocoding.cpp 33757 2016-03-20 20:22:33Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Client of geocoding service.
@@ -40,7 +40,7 @@
 
 /* Recent mingw define struct timezone */
 #if !(defined(__GNUC__) && defined(_TIMEZONE_DEFINED))
-struct timezone 
+struct timezone
 {
   int  tz_minuteswest; /* minutes W of Greenwich */
   int  tz_dsttime;     /* type of DST correction */
@@ -50,7 +50,7 @@ struct timezone
 #define MICROSEC_IN_SEC   1000000
 
 static
-int OGR_gettimeofday(struct timeval *tv, struct timezone *tzIgnored)
+int OGR_gettimeofday(struct timeval *tv, CPL_UNUSED struct timezone *tzIgnored)
 {
     FILETIME ft;
     GetSystemTimeAsFileTime(&ft);
@@ -77,7 +77,7 @@ int OGR_gettimeofday(struct timeval *tv, struct timezone *tzIgnored)
 #include "ogr_mem.h"
 #include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: ogr_geocoding.cpp 28459 2015-02-12 13:48:21Z rouault $");
+CPL_CVSID("$Id: ogr_geocoding.cpp 33757 2016-03-20 20:22:33Z goatbar $");
 
 struct _OGRGeocodingSessionHS
 {
@@ -119,7 +119,6 @@ static double dfLastQueryTimeStampMapQuestNominatim = 0.0;
 #define FIELD_URL                "url"
 #define FIELD_BLOB               "blob"
 
-#ifdef OGR_ENABLED
 
 /************************************************************************/
 /*                       OGRGeocodeGetParameter()                       */
@@ -141,13 +140,13 @@ const char* OGRGeocodeGetParameter(char** papszOptions, const char* pszKey,
 /*                      OGRGeocodeHasStringValidFormat()                */
 /************************************************************************/
 
-/* Checks that pszQueryTemplate has one and only one occurence of %s in it. */
+/* Checks that pszQueryTemplate has one and only one occurrence of %s in it. */
 static
 int OGRGeocodeHasStringValidFormat(const char* pszQueryTemplate)
 {
     const char* pszIter = pszQueryTemplate;
     int bValidFormat = TRUE;
-    int bFoundPctS = FALSE;
+    bool bFoundPctS = false;
     while( *pszIter != '\0' )
     {
         if( *pszIter == '%' )
@@ -163,7 +162,7 @@ int OGRGeocodeHasStringValidFormat(const char* pszQueryTemplate)
                     bValidFormat = FALSE;
                     break;
                 }
-                bFoundPctS = TRUE;
+                bFoundPctS = true;
             }
             else
             {
@@ -178,7 +177,6 @@ int OGRGeocodeHasStringValidFormat(const char* pszQueryTemplate)
     return bValidFormat;
 }
 
-#endif /* #ifdef OGR_ENABLED */
 
 /************************************************************************/
 /*                       OGRGeocodeCreateSession()                      */
@@ -212,11 +210,11 @@ int OGRGeocodeHasStringValidFormat(const char* pszQueryTemplate)
  * <li> "DELAY": minimum delay, in second, between 2 consecutive queries.
  *       Defaults to 1.0.
  * <li> "QUERY_TEMPLATE": URL template for GET requests. Must contain one
- *       and only one occurence of %%s in it. If not specified, for
+ *       and only one occurrence of %%s in it. If not specified, for
  *       SERVICE=OSM_NOMINATIM, MAPQUEST_NOMINATIM, YAHOO, GEONAMES or BING,
  *       the URL template is hard-coded.
  * <li> "REVERSE_QUERY_TEMPLATE": URL template for GET requests for reverse
- *       geocoding. Must contain one and only one occurence of {lon} and {lat} in it.
+ *       geocoding. Must contain one and only one occurrence of {lon} and {lat} in it.
  *       If not specified, for SERVICE=OSM_NOMINATIM, MAPQUEST_NOMINATIM, YAHOO,
  *       GEONAMES or BING, the URL template is hard-coded.
  * </ul>
@@ -235,7 +233,6 @@ int OGRGeocodeHasStringValidFormat(const char* pszQueryTemplate)
 
 OGRGeocodingSessionH OGRGeocodeCreateSession(char** papszOptions)
 {
-#ifdef OGR_ENABLED
     OGRGeocodingSessionH hSession =
         (OGRGeocodingSessionH)CPLCalloc(1, sizeof(_OGRGeocodingSessionHS));
 
@@ -243,7 +240,7 @@ OGRGeocodingSessionH OGRGeocodeCreateSession(char** papszOptions)
                                                           "CACHE_FILE",
                                                           DEFAULT_CACHE_SQLITE);
     CPLString osExt = CPLGetExtension(pszCacheFilename);
-    if( !(EQUALN(pszCacheFilename, "PG:", 3) ||
+    if( !(STARTS_WITH_CI(pszCacheFilename, "PG:") ||
         EQUAL(osExt, "csv") || EQUAL(osExt, "sqlite")) )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -253,9 +250,9 @@ OGRGeocodingSessionH OGRGeocodeCreateSession(char** papszOptions)
     }
     hSession->pszCacheFilename = CPLStrdup(pszCacheFilename);
 
-    hSession->bReadCache = CSLTestBoolean(
+    hSession->bReadCache = CPLTestBool(
         OGRGeocodeGetParameter(papszOptions, "READ_CACHE", "TRUE"));
-    hSession->bWriteCache = CSLTestBoolean(
+    hSession->bWriteCache = CPLTestBool(
         OGRGeocodeGetParameter(papszOptions, "WRITE_CACHE", "TRUE"));
 
     const char* pszGeocodingService = OGRGeocodeGetParameter(papszOptions,
@@ -357,10 +354,6 @@ OGRGeocodingSessionH OGRGeocodeCreateSession(char** papszOptions)
         (pszReverseQueryTemplate) ? CPLStrdup(pszReverseQueryTemplate) : NULL;
 
     return hSession;
-#else
-    CPLError(CE_Failure, CPLE_NotSupported, "Requires OGR support");
-    return NULL;
-#endif
 }
 
 /************************************************************************/
@@ -376,7 +369,6 @@ OGRGeocodingSessionH OGRGeocodeCreateSession(char** papszOptions)
  */
 void OGRGeocodeDestroySession(OGRGeocodingSessionH hSession)
 {
-#ifdef OGR_ENABLED
     if( hSession == NULL )
         return;
     CPLFree(hSession->pszCacheFilename);
@@ -391,10 +383,8 @@ void OGRGeocodeDestroySession(OGRGeocodingSessionH hSession)
     if( hSession->poDS )
         OGRReleaseDataSource((OGRDataSourceH) hSession->poDS);
     CPLFree(hSession);
-#endif
 }
 
-#ifdef OGR_ENABLED
 
 /************************************************************************/
 /*                        OGRGeocodeGetCacheLayer()                     */
@@ -412,8 +402,9 @@ static OGRLayer* OGRGeocodeGetCacheLayer(OGRGeocodingSessionH hSession,
         if( OGRGetDriverCount() == 0 )
             OGRRegisterAll();
 
-        char* pszOldVal = CPLGetConfigOption("OGR_SQLITE_SYNCHRONOUS", NULL) ?
-            CPLStrdup(CPLGetConfigOption("OGR_SQLITE_SYNCHRONOUS", NULL)) : NULL;
+        bool bHadValue = (CPLGetConfigOption("OGR_SQLITE_SYNCHRONOUS", NULL) != NULL);
+        std::string oOldVal(CPLGetConfigOption("OGR_SQLITE_SYNCHRONOUS", ""));
+
         CPLSetThreadLocalConfigOption("OGR_SQLITE_SYNCHRONOUS", "OFF");
 
         poDS = (OGRDataSource*) OGROpen(hSession->pszCacheFilename, TRUE, NULL);
@@ -432,7 +423,7 @@ static OGRLayer* OGRGeocodeGetCacheLayer(OGRGeocodingSessionH hSession,
         }
 
         if( bCreateIfNecessary && poDS == NULL &&
-            !EQUALN(hSession->pszCacheFilename, "PG:", 3) )
+            !STARTS_WITH_CI(hSession->pszCacheFilename, "PG:") )
         {
             OGRSFDriverH hDriver = OGRGetDriverByName(osExt);
             if( hDriver == NULL &&
@@ -474,7 +465,7 @@ static OGRLayer* OGRGeocodeGetCacheLayer(OGRGeocodingSessionH hSession,
             }
         }
 
-        CPLSetThreadLocalConfigOption("OGR_SQLITE_SYNCHRONOUS", pszOldVal);
+        CPLSetThreadLocalConfigOption("OGR_SQLITE_SYNCHRONOUS", bHadValue ? oOldVal.c_str() : NULL);
 
         if( poDS == NULL )
             return NULL;
@@ -505,7 +496,7 @@ static OGRLayer* OGRGeocodeGetCacheLayer(OGRGeocodingSessionH hSession,
             OGRFieldDefn oFieldDefnBlob(FIELD_BLOB, OFTString);
             poLayer->CreateField(&oFieldDefnBlob);
             if( EQUAL(osExt, "SQLITE") ||
-                EQUALN(hSession->pszCacheFilename, "PG:", 3) )
+                STARTS_WITH_CI(hSession->pszCacheFilename, "PG:") )
             {
                 const char* pszSQL =
                     CPLSPrintf( "CREATE INDEX idx_%s_%s ON %s(%s)",
@@ -564,7 +555,7 @@ static char* OGRGeocodeGetFromCache(OGRGeocodingSessionH hSession,
 /*                        OGRGeocodePutIntoCache()                      */
 /************************************************************************/
 
-static int OGRGeocodePutIntoCache(OGRGeocodingSessionH hSession,
+static bool OGRGeocodePutIntoCache(OGRGeocodingSessionH hSession,
                                   const char* pszURL,
                                   const char* pszContent)
 {
@@ -573,12 +564,12 @@ static int OGRGeocodePutIntoCache(OGRGeocodingSessionH hSession,
     int nIdxBlob = -1;
     OGRLayer* poLayer = OGRGeocodeGetCacheLayer(hSession, TRUE, &nIdxBlob);
     if( poLayer == NULL )
-        return FALSE;
+        return false;
 
     OGRFeature* poFeature = new OGRFeature(poLayer->GetLayerDefn());
     poFeature->SetField(FIELD_URL, pszURL);
     poFeature->SetField(FIELD_BLOB, pszContent);
-    int bRet = poLayer->CreateFeature(poFeature) == OGRERR_NONE;
+    bool bRet = poLayer->CreateFeature(poFeature) == OGRERR_NONE;
     delete poFeature;
 
     return bRet;
@@ -596,7 +587,7 @@ static OGRLayerH OGRGeocodeMakeRawLayer(const char* pszContent)
     poLayer->CreateField(&oFieldDefnRaw);
     OGRFeature* poFeature = new OGRFeature(poFDefn);
     poFeature->SetField("raw", pszContent);
-    poLayer->CreateFeature(poFeature);
+    CPL_IGNORE_RET_VAL(poLayer->CreateFeature(poFeature));
     delete poFeature;
     return (OGRLayerH) poLayer;
 }
@@ -663,7 +654,7 @@ static OGRLayerH OGRGeocodeBuildLayerNominatim(CPLXMLNode* psSearchResults,
             (strcmp(psPlace->pszValue, "place") == 0 || /* Nominatim */
              strcmp(psPlace->pszValue, "geoname") == 0 /* Geonames */) )
         {
-            int bFoundLat = FALSE, bFoundLon = FALSE;
+            bool bFoundLat = false, bFoundLon = false;
             double dfLat = 0.0, dfLon = 0.0;
 
             /* Iteration to fill the feature */
@@ -685,13 +676,13 @@ static OGRLayerH OGRGeocodeBuildLayerNominatim(CPLXMLNode* psSearchResults,
                         poFeature->SetField(nIdx, pszVal);
                         if( strcmp(pszName, "lat") == 0 )
                         {
-                            bFoundLat = TRUE;
+                            bFoundLat = true;
                             dfLat = CPLAtofM(pszVal);
                         }
                         else if( strcmp(pszName, "lon") == 0 ||  /* Nominatim */
                                  strcmp(pszName, "lng") == 0 /* Geonames */ )
                         {
-                            bFoundLon = TRUE;
+                            bFoundLon = true;
                             dfLon = CPLAtofM(pszVal);
                         }
                     }
@@ -727,7 +718,7 @@ static OGRLayerH OGRGeocodeBuildLayerNominatim(CPLXMLNode* psSearchResults,
             if( poFeature->GetGeometryRef() == NULL && bFoundLon && bFoundLat )
                 poFeature->SetGeometryDirectly(new OGRPoint(dfLon, dfLat));
 
-            poLayer->CreateFeature(poFeature);
+            CPL_IGNORE_RET_VAL(poLayer->CreateFeature(poFeature));
             delete poFeature;
         }
         psPlace = psPlace->psNext;
@@ -753,7 +744,7 @@ static OGRLayerH OGRGeocodeReverseBuildLayerNominatim(CPLXMLNode* psReverseGeoco
     OGRMemLayer* poLayer = new OGRMemLayer( "result", NULL, wkbNone );
     OGRFeatureDefn* poFDefn = poLayer->GetLayerDefn();
 
-    int bFoundLat = FALSE, bFoundLon = FALSE;
+    bool bFoundLat = false, bFoundLon = false;
     double dfLat = 0.0, dfLon = 0.0;
 
     /* First iteration to add fields */
@@ -770,7 +761,7 @@ static OGRLayerH OGRGeocodeReverseBuildLayerNominatim(CPLXMLNode* psReverseGeoco
             {
                 if( pszVal != NULL )
                 {
-                    bFoundLat = TRUE;
+                    bFoundLat = true;
                     dfLat = CPLAtofM(pszVal);
                 }
                 oFieldDefn.SetType(OFTReal);
@@ -779,7 +770,7 @@ static OGRLayerH OGRGeocodeReverseBuildLayerNominatim(CPLXMLNode* psReverseGeoco
             {
                 if( pszVal != NULL )
                 {
-                    bFoundLon = TRUE;
+                    bFoundLon = true;
                     dfLon = CPLAtofM(pszVal);
                 }
                 oFieldDefn.SetType(OFTReal);
@@ -789,8 +780,10 @@ static OGRLayerH OGRGeocodeReverseBuildLayerNominatim(CPLXMLNode* psReverseGeoco
         psChild = psChild->psNext;
     }
 
-    OGRFieldDefn oFieldDefn("display_name", OFTString);
-    poLayer->CreateField(&oFieldDefn);
+    {
+        OGRFieldDefn oFieldDefn("display_name", OFTString);
+        poLayer->CreateField(&oFieldDefn);
+    }
 
     psChild = psAddressParts->psChild;
     while( psChild != NULL )
@@ -837,7 +830,7 @@ static OGRLayerH OGRGeocodeReverseBuildLayerNominatim(CPLXMLNode* psReverseGeoco
     {
         int nIdx;
         const char* pszName = psChild->pszValue;
-        const char* pszVal = CPLGetXMLValue(psChild, NULL, NULL);
+        pszVal = CPLGetXMLValue(psChild, NULL, NULL);
         if( (psChild->eType == CXT_Element || psChild->eType == CXT_Attribute) &&
             (nIdx = poFDefn->GetFieldIndex(pszName)) >= 0 )
         {
@@ -857,7 +850,7 @@ static OGRLayerH OGRGeocodeReverseBuildLayerNominatim(CPLXMLNode* psReverseGeoco
     if( poFeature->GetGeometryRef() == NULL && bFoundLon && bFoundLat )
         poFeature->SetGeometryDirectly(new OGRPoint(dfLon, dfLat));
 
-    poLayer->CreateFeature(poFeature);
+    CPL_IGNORE_RET_VAL(poLayer->CreateFeature(poFeature));
     delete poFeature;
 
     return (OGRLayerH) poLayer;
@@ -921,7 +914,7 @@ static OGRLayerH OGRGeocodeBuildLayerYahoo(CPLXMLNode* psResultSet,
         if( psPlace->eType == CXT_Element &&
             strcmp(psPlace->pszValue, "Result") == 0 )
         {
-            int bFoundLat = FALSE, bFoundLon = FALSE;
+            bool bFoundLat = false, bFoundLon = false;
             double dfLat = 0.0, dfLon = 0.0;
 
             /* Second iteration to fill the feature */
@@ -943,12 +936,12 @@ static OGRLayerH OGRGeocodeBuildLayerYahoo(CPLXMLNode* psResultSet,
                         poFeature->SetField(nIdx, pszVal);
                         if( strcmp(pszName, "latitude") == 0 )
                         {
-                            bFoundLat = TRUE;
+                            bFoundLat = true;
                             dfLat = CPLAtofM(pszVal);
                         }
                         else if( strcmp(pszName, "longitude") == 0 )
                         {
-                            bFoundLon = TRUE;
+                            bFoundLon = true;
                             dfLon = CPLAtofM(pszVal);
                         }
                     }
@@ -986,7 +979,7 @@ static OGRLayerH OGRGeocodeBuildLayerYahoo(CPLXMLNode* psResultSet,
             if( bFoundLon && bFoundLat )
                 poFeature->SetGeometryDirectly(new OGRPoint(dfLon, dfLat));
 
-            poLayer->CreateFeature(poFeature);
+            CPL_IGNORE_RET_VAL(poLayer->CreateFeature(poFeature));
             delete poFeature;
         }
         psPlace = psPlace->psNext;
@@ -1075,7 +1068,7 @@ static OGRLayerH OGRGeocodeBuildLayerBing (CPLXMLNode* psResponse,
         if( psPlace->eType == CXT_Element &&
             strcmp(psPlace->pszValue, "Location") == 0 )
         {
-            int bFoundLat = FALSE, bFoundLon = FALSE;
+            bool bFoundLat = false, bFoundLon = false;
             double dfLat = 0.0, dfLon = 0.0;
 
             OGRFeature* poFeature = new OGRFeature(poFDefn);
@@ -1113,12 +1106,12 @@ static OGRLayerH OGRGeocodeBuildLayerBing (CPLXMLNode* psResponse,
                                 poFeature->SetField(nIdx, pszVal);
                                 if( strcmp(pszName, "Latitude") == 0 )
                                 {
-                                    bFoundLat = TRUE;
+                                    bFoundLat = true;
                                     dfLat = CPLAtofM(pszVal);
                                 }
                                 else if( strcmp(pszName, "Longitude") == 0 )
                                 {
-                                    bFoundLon = TRUE;
+                                    bFoundLon = true;
                                     dfLon = CPLAtofM(pszVal);
                                 }
                             }
@@ -1144,7 +1137,7 @@ static OGRLayerH OGRGeocodeBuildLayerBing (CPLXMLNode* psResponse,
             if( bFoundLon && bFoundLat )
                 poFeature->SetGeometryDirectly(new OGRPoint(dfLon, dfLat));
 
-            poLayer->CreateFeature(poFeature);
+            CPL_IGNORE_RET_VAL(poLayer->CreateFeature(poFeature));
             delete poFeature;
         }
         psPlace = psPlace->psNext;
@@ -1250,7 +1243,7 @@ static OGRLayerH OGRGeocodeCommon(OGRGeocodingSessionH hSession,
     }
 
     int bAddRawFeature =
-        CSLTestBoolean(OGRGeocodeGetParameter(papszOptions, "RAW_FEATURE", "NO"));
+        CPLTestBool(OGRGeocodeGetParameter(papszOptions, "RAW_FEATURE", "NO"));
 
     OGRLayerH hLayer = NULL;
 
@@ -1315,7 +1308,10 @@ static OGRLayerH OGRGeocodeCommon(OGRGeocodingSessionH hSession,
             if( pszResult != NULL )
             {
                 if( hSession->bWriteCache )
+                {
+                    /* coverity[tainted_data] */
                     OGRGeocodePutIntoCache(hSession, osURL, pszResult);
+                }
                 hLayer = OGRGeocodeBuildLayer(pszResult, bAddRawFeature);
             }
             CPLHTTPDestroyResult(psResult);
@@ -1330,7 +1326,6 @@ static OGRLayerH OGRGeocodeCommon(OGRGeocodingSessionH hSession,
     return hLayer;
 }
 
-#endif /* #ifdef OGR_ENABLED */
 
 /************************************************************************/
 /*                              OGRGeocode()                            */
@@ -1386,7 +1381,6 @@ OGRLayerH OGRGeocode(OGRGeocodingSessionH hSession,
                      char** papszStructuredQuery,
                      char** papszOptions)
 {
-#ifdef OGR_ENABLED
     VALIDATE_POINTER1( hSession, "OGRGeocode", NULL );
     if( (pszQuery == NULL && papszStructuredQuery == NULL) ||
         (pszQuery != NULL && papszStructuredQuery != NULL) )
@@ -1436,13 +1430,10 @@ OGRLayerH OGRGeocode(OGRGeocodingSessionH hSession,
         }
     }
 
+    /* coverity[tainted_data] */
     return OGRGeocodeCommon(hSession, osURL, papszOptions);
-#else
-    return NULL;
-#endif
 }
 
-#ifdef OGR_ENABLED
 
 /************************************************************************/
 /*                      OGRGeocodeReverseSubstitute()                   */
@@ -1472,7 +1463,6 @@ static CPLString OGRGeocodeReverseSubstitute(CPLString osURL,
     return osURL;
 }
 
-#endif /* #ifdef OGR_ENABLED */
 
 /************************************************************************/
 /*                         OGRGeocodeReverse()                          */
@@ -1521,7 +1511,6 @@ OGRLayerH OGRGeocodeReverse(OGRGeocodingSessionH hSession,
                             double dfLon, double dfLat,
                             char** papszOptions)
 {
-#ifdef OGR_ENABLED
     VALIDATE_POINTER1( hSession, "OGRGeocodeReverse", NULL );
 
     if( hSession->pszReverseQueryTemplate == NULL )
@@ -1543,10 +1532,8 @@ OGRLayerH OGRGeocodeReverse(OGRGeocodingSessionH hSession,
         }
     }
 
+    /* coverity[tainted_data] */
     return OGRGeocodeCommon(hSession, osURL, papszOptions);
-#else
-    return NULL;
-#endif
 }
 
 /************************************************************************/
@@ -1563,7 +1550,5 @@ OGRLayerH OGRGeocodeReverse(OGRGeocodingSessionH hSession,
  */
 void OGRGeocodeFreeResult(OGRLayerH hLayer)
 {
-#ifdef OGR_ENABLED
     delete (OGRLayer*) hLayer;
-#endif
 }
diff --git a/ogr/ogr_geocoding.h b/ogr/ogr_geocoding.h
index 2e5125a..6ed9d50 100644
--- a/ogr/ogr_geocoding.h
+++ b/ogr/ogr_geocoding.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_geocoding.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: ogr_geocoding.h 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Client of geocoding service.
@@ -27,15 +27,15 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_GEOCODING_H_INCLUDED
-#define _OGR_GEOCODING_H_INCLUDED
+#ifndef OGR_GEOCODING_H_INCLUDED
+#define OGR_GEOCODING_H_INCLUDED
 
 #include "cpl_port.h"
 #include "ogr_api.h"
 
 /**
  * \file ogr_geocoding.h
- * 
+ *
  * C API for geocoding client.
  */
 
@@ -60,4 +60,4 @@ void CPL_DLL OGRGeocodeFreeResult(OGRLayerH hLayer);
 
 CPL_C_END
 
-#endif // _OGR_GEOCODING_H_INCLUDED
+#endif // OGR_GEOCODING_H_INCLUDED
diff --git a/ogr/ogr_geometry.h b/ogr/ogr_geometry.h
index cfbcfc1..0024396 100644
--- a/ogr/ogr_geometry.h
+++ b/ogr/ogr_geometry.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_geometry.h 28123 2014-12-10 19:27:55Z rouault $
+ * $Id: ogr_geometry.h 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Classes for manipulating simple features that is not specific
@@ -29,8 +29,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_GEOMETRY_H_INCLUDED
-#define _OGR_GEOMETRY_H_INCLUDED
+#ifndef OGR_GEOMETRY_H_INCLUDED
+#define OGR_GEOMETRY_H_INCLUDED
 
 #include "ogr_core.h"
 #include "ogr_spatialref.h"
@@ -52,7 +52,7 @@ class OGRRawPoint
                   x = y = 0.0;
           }
 
-          OGRRawPoint(double x, double y) : x(x), y(y) {}
+          OGRRawPoint(double xIn, double yIn) : x(xIn), y(yIn) {}
     double      x;
     double      y;
 };
@@ -100,7 +100,7 @@ typedef OGRCurvePolygon* (*OGRSurfaceCasterToCurvePolygon)(OGRSurface*);
  * CURVEPOLYGON (OGRCurvePolygon), MULTICURVE (OGRMultiCurve) and MULTISURFACE (OGRMultiSurface).
  *
  */
- 
+
 class CPL_DLL OGRGeometry
 {
   private:
@@ -109,10 +109,11 @@ class CPL_DLL OGRGeometry
   protected:
     friend class OGRCurveCollection;
 
-    int                   nCoordDimension;
+    unsigned int          flags;
 
     OGRErr                importPreambuleFromWkt( char ** ppszInput,
-                                                  int* pbHasZ, int* pbHasM );
+                                                  int* pbHasZ, int* pbHasM,
+                                                  bool* pbIsEmpty );
     OGRErr                importCurveCollectionFromWkt( char ** ppszInput,
                                                   int bAllowEmptyComponent,
                                                   int bAllowLineString,
@@ -122,7 +123,6 @@ class CPL_DLL OGRGeometry
     OGRErr                importPreambuleFromWkb( unsigned char * pabyData,
                                                   int nSize,
                                                   OGRwkbByteOrder& eByteOrder,
-                                                  OGRBoolean& b3D,
                                                   OGRwkbVariant eWkbVariant );
     OGRErr                importPreambuleOfCollectionFromWkb(
                                                         unsigned char * pabyData,
@@ -132,19 +132,39 @@ class CPL_DLL OGRGeometry
                                                         int nMinSubGeomSize,
                                                         int& nGeomCount,
                                                         OGRwkbVariant eWkbVariant );
+    OGRErr                PointOnSurfaceInternal( OGRPoint * poPoint ) const;
+
   public:
+
+/************************************************************************/
+/*                   Bit flags for OGRGeometry                          */
+/*          The OGR_G_NOT_EMPTY_POINT is used *only* for points.        */
+/*          Do not use these outside of the core.                       */
+/*          Use Is3D, IsMeasured, set3D, and setMeasured instead        */
+/************************************************************************/
+
+    static const unsigned int OGR_G_NOT_EMPTY_POINT = 0x1;
+    static const unsigned int OGR_G_3D = 0x2;
+    static const unsigned int OGR_G_MEASURED = 0x4;
+
                 OGRGeometry();
+                OGRGeometry( const OGRGeometry& other );
     virtual     ~OGRGeometry();
-                        
+
+    OGRGeometry& operator=( const OGRGeometry& other );
+
     // standard IGeometry
     virtual int getDimension() const = 0;
     virtual int getCoordinateDimension() const;
-    virtual OGRBoolean  IsEmpty() const = 0; 
+    int CoordinateDimension() const;
+    virtual OGRBoolean  IsEmpty() const;
     virtual OGRBoolean  IsValid() const;
     virtual OGRBoolean  IsSimple() const;
+    OGRBoolean  Is3D() const { return flags & OGR_G_3D; }
+    OGRBoolean  IsMeasured() const { return flags & OGR_G_MEASURED; }
     virtual OGRBoolean  IsRing() const;
     virtual void        empty() = 0;
-    virtual OGRGeometry *clone() const = 0;
+    virtual OGRGeometry *clone() const CPL_WARN_UNUSED_RESULT = 0;
     virtual void getEnvelope( OGREnvelope * psEnvelope ) const = 0;
     virtual void getEnvelope( OGREnvelope3D * psEnvelope ) const = 0;
 
@@ -154,7 +174,7 @@ class CPL_DLL OGRGeometry
     virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *, OGRwkbVariant=wkbVariantOldOgc ) const = 0;
     virtual OGRErr importFromWkt( char ** ppszInput ) = 0;
     virtual OGRErr exportToWkt( char ** ppszDstText, OGRwkbVariant=wkbVariantOldOgc ) const = 0;
-    
+
     // non-standard
     virtual OGRwkbGeometryType getGeometryType() const = 0;
     OGRwkbGeometryType    getIsoGeometryType() const;
@@ -162,27 +182,29 @@ class CPL_DLL OGRGeometry
     virtual void   dumpReadable( FILE *, const char * = NULL, char** papszOptions = NULL ) const;
     virtual void   flattenTo2D() = 0;
     virtual char * exportToGML( const char* const * papszOptions = NULL ) const;
-	virtual char * exportToKML() const;
+    virtual char * exportToKML() const;
     virtual char * exportToJson() const;
 
     static GEOSContextHandle_t createGEOSContext();
     static void freeGEOSContext(GEOSContextHandle_t hGEOSCtxt);
-    virtual GEOSGeom exportToGEOS(GEOSContextHandle_t hGEOSCtxt) const;
+    virtual GEOSGeom exportToGEOS(GEOSContextHandle_t hGEOSCtxt) const CPL_WARN_UNUSED_RESULT;
     virtual OGRBoolean hasCurveGeometry(int bLookForNonLinear = FALSE) const;
-    virtual OGRGeometry* getCurveGeometry(const char* const* papszOptions = NULL) const;
+    virtual OGRGeometry* getCurveGeometry(const char* const* papszOptions = NULL) const CPL_WARN_UNUSED_RESULT;
     virtual OGRGeometry* getLinearGeometry(double dfMaxAngleStepSizeDegrees = 0,
-                                             const char* const* papszOptions = NULL) const;
+                                             const char* const* papszOptions = NULL) const CPL_WARN_UNUSED_RESULT;
 
     virtual void closeRings();
 
-    virtual void setCoordinateDimension( int nDimension ); 
+    virtual void setCoordinateDimension( int nDimension );
+    virtual void set3D( OGRBoolean bIs3D );
+    virtual void setMeasured( OGRBoolean bIsMeasured );
 
     void    assignSpatialReference( OGRSpatialReference * poSR );
     OGRSpatialReference *getSpatialReference( void ) const { return poSRS; }
 
     virtual OGRErr  transform( OGRCoordinateTransformation *poCT ) = 0;
     OGRErr  transformTo( OGRSpatialReference *poSR );
-    
+
     virtual void segmentize(double dfMaxLength);
 
     // ISpatialRelation
@@ -195,33 +217,36 @@ class CPL_DLL OGRGeometry
     virtual OGRBoolean  Contains( const OGRGeometry * ) const;
     virtual OGRBoolean  Overlaps( const OGRGeometry * ) const;
 //    virtual OGRBoolean  Relate( const OGRGeometry *, const char * ) const;
-
-    virtual OGRGeometry *Boundary() const;
-    virtual double  Distance( const OGRGeometry * ) const;
-    virtual OGRGeometry *ConvexHull() const;
-    virtual OGRGeometry *Buffer( double dfDist, int nQuadSegs = 30 ) const;
-    virtual OGRGeometry *Intersection( const OGRGeometry *) const;
-    virtual OGRGeometry *Union( const OGRGeometry * ) const;
-    virtual OGRGeometry *UnionCascaded() const;
-    virtual OGRGeometry *Difference( const OGRGeometry * ) const;
-    virtual OGRGeometry *SymDifference( const OGRGeometry * ) const;
+//    virtual OGRGeometry *LocateAlong( double mValue ) const;
+//    virtual OGRGeometry *LocateBetween( double mStart, double mEnd ) const;
+
+    virtual OGRGeometry *Boundary() const CPL_WARN_UNUSED_RESULT;
+    virtual double  Distance( const OGRGeometry * ) const ;
+    virtual OGRGeometry *ConvexHull() const CPL_WARN_UNUSED_RESULT;
+    virtual OGRGeometry *Buffer( double dfDist, int nQuadSegs = 30 ) const CPL_WARN_UNUSED_RESULT;
+    virtual OGRGeometry *Intersection( const OGRGeometry *) const CPL_WARN_UNUSED_RESULT;
+    virtual OGRGeometry *Union( const OGRGeometry * ) const CPL_WARN_UNUSED_RESULT;
+    virtual OGRGeometry *UnionCascaded() const CPL_WARN_UNUSED_RESULT;
+    virtual OGRGeometry *Difference( const OGRGeometry * ) const CPL_WARN_UNUSED_RESULT;
+    virtual OGRGeometry *SymDifference( const OGRGeometry * ) const CPL_WARN_UNUSED_RESULT;
     virtual OGRErr       Centroid( OGRPoint * poPoint ) const;
-    virtual OGRGeometry *Simplify(double dTolerance) const;
-    OGRGeometry *SimplifyPreserveTopology(double dTolerance) const;
+    virtual OGRGeometry *Simplify(double dTolerance) const CPL_WARN_UNUSED_RESULT;
+    OGRGeometry *SimplifyPreserveTopology(double dTolerance) const CPL_WARN_UNUSED_RESULT;
+    virtual OGRGeometry *DelaunayTriangulation(double dfTolerance, int bOnlyEdges) const CPL_WARN_UNUSED_RESULT;
 
-    virtual OGRGeometry *Polygonize() const;
+    virtual OGRGeometry *Polygonize() const CPL_WARN_UNUSED_RESULT;
 
-    // backward compatibility to non-standard method names. 
+    // backward compatibility to non-standard method names.
     OGRBoolean  Intersect( OGRGeometry * ) const CPL_WARN_DEPRECATED("Non standard method. Use Intersects() instead");
     OGRBoolean  Equal( OGRGeometry * ) const CPL_WARN_DEPRECATED("Non standard method. Use Equals() instead");
-    virtual OGRGeometry *SymmetricDifference( const OGRGeometry * ) const CPL_WARN_DEPRECATED("Non standard method. Use SymDifference() instead");
-    virtual OGRGeometry *getBoundary() const CPL_WARN_DEPRECATED("Non standard method. Use Boundary() instead");
-    
+    OGRGeometry *SymmetricDifference( const OGRGeometry * ) const CPL_WARN_DEPRECATED("Non standard method. Use SymDifference() instead");
+    OGRGeometry *getBoundary() const CPL_WARN_DEPRECATED("Non standard method. Use Boundary() instead");
+
     // Special HACK for DB2 7.2 support
     static int bGenerate_DB2_V72_BYTE_ORDER;
 
     virtual void        swapXY();
-    
+
     static OGRGeometry* CastToIdentity(OGRGeometry* poGeom) { return poGeom; }
     static OGRGeometry* CastToError(OGRGeometry* poGeom);
 };
@@ -241,45 +266,51 @@ class CPL_DLL OGRPoint : public OGRGeometry
     double      x;
     double      y;
     double      z;
+    double      m;
 
   public:
                 OGRPoint();
                 OGRPoint( double x, double y );
                 OGRPoint( double x, double y, double z );
+                OGRPoint( double x, double y, double z, double m );
+                OGRPoint( const OGRPoint& other );
     virtual     ~OGRPoint();
 
+    OGRPoint& operator=( const OGRPoint& other );
+
     // IWks Interface
     virtual int WkbSize() const;
     virtual OGRErr importFromWkb( unsigned char *, int=-1, OGRwkbVariant=wkbVariantOldOgc );
     virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *, OGRwkbVariant=wkbVariantOldOgc ) const;
     virtual OGRErr importFromWkt( char ** );
     virtual OGRErr exportToWkt( char ** ppszDstText, OGRwkbVariant=wkbVariantOldOgc ) const;
-    
+
     // IGeometry
     virtual int getDimension() const;
-    virtual int getCoordinateDimension() const;
     virtual OGRGeometry *clone() const;
     virtual void empty();
     virtual void getEnvelope( OGREnvelope * psEnvelope ) const;
     virtual void getEnvelope( OGREnvelope3D * psEnvelope ) const;
-    virtual OGRBoolean  IsEmpty() const;
+    virtual OGRBoolean  IsEmpty() const { return !(flags & OGR_G_NOT_EMPTY_POINT); }
 
     // IPoint
-    double      getX() const { return x; } 
+    double      getX() const { return x; }
     double      getY() const { return y; }
     double      getZ() const { return z; }
+    double      getM() const { return m; }
 
     // Non standard
-    virtual void setCoordinateDimension( int nDimension ); 
-    void        setX( double xIn ) { x = xIn; if (nCoordDimension <= 0) nCoordDimension = 2; }
-    void        setY( double yIn ) { y = yIn; if (nCoordDimension <= 0) nCoordDimension = 2; }
-    void        setZ( double zIn ) { z = zIn; nCoordDimension=3; }
+    virtual void setCoordinateDimension( int nDimension );
+    void        setX( double xIn ) { x = xIn; flags |= OGR_G_NOT_EMPTY_POINT; }
+    void        setY( double yIn ) { y = yIn; flags |= OGR_G_NOT_EMPTY_POINT; }
+    void        setZ( double zIn ) { z = zIn; flags |= (OGR_G_NOT_EMPTY_POINT | OGR_G_3D); }
+    void        setM( double mIn ) { m = mIn; flags |= (OGR_G_NOT_EMPTY_POINT | OGR_G_MEASURED); }
 
     // ISpatialRelation
     virtual OGRBoolean  Equals( OGRGeometry * ) const;
     virtual OGRBoolean  Intersects( const OGRGeometry * ) const;
     virtual OGRBoolean  Within( const OGRGeometry * ) const;
-    
+
     // Non standard from OGRGeometry
     virtual const char *getGeometryName() const;
     virtual OGRwkbGeometryType getGeometryType() const;
@@ -321,6 +352,7 @@ class CPL_DLL OGRCurve : public OGRGeometry
 {
   protected:
             OGRCurve();
+            OGRCurve( const OGRCurve& other );
 
     virtual OGRCurveCasterToLineString GetCasterToLineString() const = 0;
     virtual OGRCurveCasterToLinearRing GetCasterToLinearRing() const = 0;
@@ -333,6 +365,8 @@ class CPL_DLL OGRCurve : public OGRGeometry
   public:
     virtual ~OGRCurve();
 
+    OGRCurve& operator=( const OGRCurve& other );
+
     // ICurve methods
     virtual double get_Length() const = 0;
     virtual void StartPoint(OGRPoint *) const = 0;
@@ -375,9 +409,12 @@ class CPL_DLL OGRSimpleCurve: public OGRCurve
     int         nPointCount;
     OGRRawPoint *paoPoints;
     double      *padfZ;
+    double      *padfM;
 
     void        Make3D();
     void        Make2D();
+    void        RemoveM();
+    void        AddM();
 
     OGRErr      importFromWKTListOnly( char ** ppszInput, int bHasZ, int bHasM,
                                        OGRRawPoint*& paoPointsIn, int& nMaxPoints,
@@ -386,10 +423,13 @@ class CPL_DLL OGRSimpleCurve: public OGRCurve
     virtual double get_LinearArea() const;
 
                 OGRSimpleCurve();
+                OGRSimpleCurve( const OGRSimpleCurve& other );
 
   public:
     virtual     ~OGRSimpleCurve();
 
+    OGRSimpleCurve& operator=( const OGRSimpleCurve& other );
+
     // IWks Interface
     virtual int WkbSize() const;
     virtual OGRErr importFromWkb( unsigned char *, int = -1, OGRwkbVariant=wkbVariantOldOgc );
@@ -418,30 +458,49 @@ class CPL_DLL OGRSimpleCurve: public OGRCurve
     double      getX( int i ) const { return paoPoints[i].x; }
     double      getY( int i ) const { return paoPoints[i].y; }
     double      getZ( int i ) const;
+    double      getM( int i ) const;
 
     // ISpatialRelation
     virtual OGRBoolean  Equals( OGRGeometry * ) const;
-    
+
     // non standard.
-    virtual void setCoordinateDimension( int nDimension ); 
+    virtual void setCoordinateDimension( int nDimension );
+    virtual void set3D( OGRBoolean bIs3D );
+    virtual void setMeasured( OGRBoolean bIsMeasured );
     void        setNumPoints( int nNewPointCount, int bZeroizeNewContent = TRUE );
     void        setPoint( int, OGRPoint * );
     void        setPoint( int, double, double );
     void        setZ( int, double );
+    void        setM( int, double );
     void        setPoint( int, double, double, double );
+    void        setPointM( int, double, double, double );
+    void        setPoint( int, double, double, double, double );
     void        setPoints( int, OGRRawPoint *, double * = NULL );
+    void        setPointsM( int, OGRRawPoint *, double * );
+    void        setPoints( int, OGRRawPoint *, double *, double * );
     void        setPoints( int, double * padfX, double * padfY,
                            double *padfZIn = NULL );
+    void        setPointsM( int, double * padfX, double * padfY,
+                            double *padfMIn = NULL );
+    void        setPoints( int, double * padfX, double * padfY,
+                           double *padfZIn, double *padfMIn );
     void        addPoint( OGRPoint * );
     void        addPoint( double, double );
     void        addPoint( double, double, double );
+    void        addPointM( double, double, double );
+    void        addPoint( double, double, double, double );
 
     void        getPoints( OGRRawPoint *, double * = NULL ) const;
+    void        getPoints( OGRRawPoint *, double *, double * ) const;
     void        getPoints( void* pabyX, int nXStride,
                            void* pabyY, int nYStride,
                            void* pabyZ = NULL, int nZStride = 0 ) const;
+    void        getPoints( void* pabyX, int nXStride,
+                           void* pabyY, int nYStride,
+                           void* pabyZ, int nZStride,
+                           void* pabyM, int nMStride ) const;
 
-    void        addSubLineString( const OGRLineString *, 
+    void        addSubLineString( const OGRLineString *,
                                   int nStartVertex = 0, int nEndVertex = -1 );
     void        reversePoints( void );
     virtual OGRPointIterator* getPointIterator() const;
@@ -481,8 +540,11 @@ class CPL_DLL OGRLineString : public OGRSimpleCurve
 
   public:
                 OGRLineString();
+                OGRLineString(const OGRLineString& other);
     virtual    ~OGRLineString();
 
+    OGRLineString& operator=(const OGRLineString& other);
+
     virtual OGRLineString* CurveToLine(double dfMaxAngleStepSizeDegrees = 0,
                                        const char* const* papszOptions = NULL) const;
     virtual OGRGeometry* getCurveGeometry(const char* const* papszOptions = NULL) const;
@@ -500,19 +562,19 @@ class CPL_DLL OGRLineString : public OGRSimpleCurve
 /**
  * Concrete representation of a closed ring.
  *
- * This class is functionally equivelent to an OGRLineString, but has a
+ * This class is functionally equivalent to an OGRLineString, but has a
  * separate identity to maintain alignment with the OpenGIS simple feature
- * data model.  It exists to serve as a component of an OGRPolygon.  
+ * data model.  It exists to serve as a component of an OGRPolygon.
  *
  * The OGRLinearRing has no corresponding free standing well known binary
  * representation, so importFromWkb() and exportToWkb() will not actually
  * work.  There is a non-standard GDAL WKT representation though.
  *
- * Because OGRLinearRing is not a "proper" free standing simple features 
+ * Because OGRLinearRing is not a "proper" free standing simple features
  * object, it cannot be directly used on a feature via SetGeometry(), and
- * cannot genearally be used with GEOS for operations like Intersects(). 
+ * cannot generally be used with GEOS for operations like Intersects().
  * Instead the polygon should be used, or the OGRLinearRing should be
- * converted to an OGRLineString for such operations. 
+ * converted to an OGRLineString for such operations.
  *
  * Note: this class exists in SFSQL 1.2, but not in ISO SQL/MM Part 3.
  */
@@ -520,15 +582,15 @@ class CPL_DLL OGRLineString : public OGRSimpleCurve
 class CPL_DLL OGRLinearRing : public OGRLineString
 {
   protected:
-    friend class OGRPolygon; 
-    
+    friend class OGRPolygon;
+
     // These are not IWks compatible ... just a convenience for OGRPolygon.
-    virtual int _WkbSize( int b3D ) const;
-    virtual OGRErr _importFromWkb( OGRwkbByteOrder, int b3D,
+    virtual int _WkbSize( int _flags ) const;
+    virtual OGRErr _importFromWkb( OGRwkbByteOrder, int _flags,
                                    unsigned char *, int=-1 );
-    virtual OGRErr _exportToWkb( OGRwkbByteOrder, int b3D, 
+    virtual OGRErr _exportToWkb( OGRwkbByteOrder, int _flags,
                                  unsigned char * ) const;
-    
+
     static OGRLineString* CastToLineString(OGRLinearRing* poLR);
 
     virtual OGRCurveCasterToLineString GetCasterToLineString() const;
@@ -536,9 +598,12 @@ class CPL_DLL OGRLinearRing : public OGRLineString
 
   public:
                         OGRLinearRing();
+                        OGRLinearRing(const OGRLinearRing& other);
                         OGRLinearRing( OGRLinearRing * );
     virtual            ~OGRLinearRing();
 
+    OGRLinearRing& operator=(const OGRLinearRing& other);
+
     // Non standard.
     virtual const char *getGeometryName() const;
     virtual OGRGeometry *clone() const;
@@ -547,10 +612,10 @@ class CPL_DLL OGRLinearRing : public OGRLineString
     virtual void closeRings();
     OGRBoolean isPointInRing(const OGRPoint* pt, int bTestEnvelope = TRUE) const;
     OGRBoolean isPointOnRingBoundary(const OGRPoint* pt, int bTestEnvelope = TRUE) const;
-    
-    // IWks Interface - Note this isnt really a first class object
+
+    // IWks Interface - Note this isn't really a first class object
     // for the purposes of WKB form.  These methods always fail since this
-    // object cant be serialized on its own. 
+    // object can't be serialized on its own.
     virtual int WkbSize() const;
     virtual OGRErr importFromWkb( unsigned char *, int=-1, OGRwkbVariant=wkbVariantOldOgc );
     virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *, OGRwkbVariant=wkbVariantOldOgc ) const;
@@ -587,8 +652,11 @@ class CPL_DLL OGRCircularString : public OGRSimpleCurve
 
   public:
                 OGRCircularString();
+                OGRCircularString(const OGRCircularString& other);
     virtual    ~OGRCircularString();
 
+    OGRCircularString& operator=(const OGRCircularString& other);
+
     // IWks Interface
     virtual OGRErr importFromWkb( unsigned char *, int = -1, OGRwkbVariant=wkbVariantOldOgc );
     virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *, OGRwkbVariant=wkbVariantOldOgc ) const;
@@ -642,8 +710,11 @@ class CPL_DLL OGRCurveCollection
 
   public:
                 OGRCurveCollection();
+                OGRCurveCollection(const OGRCurveCollection& other);
                ~OGRCurveCollection();
 
+    OGRCurveCollection& operator=(const OGRCurveCollection& other);
+
     void            empty(OGRGeometry* poGeom);
     OGRBoolean      IsEmpty() const;
     void            getEnvelope( OGREnvelope * psEnvelope ) const;
@@ -671,6 +742,8 @@ class CPL_DLL OGRCurveCollection
                                  unsigned char *, OGRwkbVariant eWkbVariant ) const;
     OGRBoolean      Equals(OGRCurveCollection *poOCC) const;
     void            setCoordinateDimension( OGRGeometry* poGeom, int nNewDimension );
+    void            set3D( OGRGeometry* poGeom, OGRBoolean bIs3D );
+    void            setMeasured( OGRGeometry* poGeom, OGRBoolean bIsMeasured );
     int             getNumCurves() const;
     OGRCurve       *getCurve( int );
     const OGRCurve *getCurve( int ) const;
@@ -720,8 +793,11 @@ class CPL_DLL OGRCompoundCurve : public OGRCurve
 
   public:
                 OGRCompoundCurve();
+                OGRCompoundCurve(const OGRCompoundCurve& other);
     virtual     ~OGRCompoundCurve();
 
+    OGRCompoundCurve& operator=(const OGRCompoundCurve& other);
+
     // IWks Interface
     virtual int WkbSize() const;
     virtual OGRErr importFromWkb( unsigned char *, int = -1, OGRwkbVariant=wkbVariantOldOgc );
@@ -743,7 +819,7 @@ class CPL_DLL OGRCompoundCurve : public OGRCurve
     virtual void Value( double, OGRPoint * ) const;
     virtual OGRLineString* CurveToLine(double dfMaxAngleStepSizeDegrees = 0,
                                        const char* const* papszOptions = NULL) const;
-    
+
     virtual int getNumPoints() const;
     virtual double get_AreaOfCurveSegments() const;
     virtual double get_Area() const;
@@ -755,10 +831,12 @@ class CPL_DLL OGRCompoundCurve : public OGRCurve
     int             getNumCurves() const;
     OGRCurve       *getCurve( int );
     const OGRCurve *getCurve( int ) const;
-    
+
     // non standard.
-    virtual void setCoordinateDimension( int nDimension ); 
-        
+    virtual void setCoordinateDimension( int nDimension );
+    virtual void set3D( OGRBoolean bIs3D );
+    virtual void setMeasured( OGRBoolean bIsMeasured );
+
     OGRErr         addCurve( OGRCurve*, double dfToleranceEps = 1e-14  );
     OGRErr         addCurveDirectly( OGRCurve*, double dfToleranceEps = 1e-14 );
     OGRCurve      *stealCurve( int );
@@ -838,8 +916,11 @@ class CPL_DLL OGRCurvePolygon : public OGRSurface
 
   public:
                 OGRCurvePolygon();
+                OGRCurvePolygon(const OGRCurvePolygon&);
     virtual    ~OGRCurvePolygon();
 
+    OGRCurvePolygon& operator=(const OGRCurvePolygon& other);
+
     // Non standard (OGRGeometry).
     virtual const char *getGeometryName() const;
     virtual OGRwkbGeometryType getGeometryType() const;
@@ -855,8 +936,8 @@ class CPL_DLL OGRCurvePolygon : public OGRSurface
 
     // ISurface Interface
     virtual double      get_Area() const;
-    virtual int         PointOnSurface( OGRPoint * poPoint ) const;
-    
+    virtual OGRErr      PointOnSurface( OGRPoint * poPoint ) const;
+
     // IWks Interface
     virtual int WkbSize() const;
     virtual OGRErr importFromWkb( unsigned char *, int = -1, OGRwkbVariant=wkbVariantOldOgc );
@@ -868,7 +949,7 @@ class CPL_DLL OGRCurvePolygon : public OGRSurface
     virtual int getDimension() const;
     virtual void getEnvelope( OGREnvelope * psEnvelope ) const;
     virtual void getEnvelope( OGREnvelope3D * psEnvelope ) const;
-    
+
     // ICurvePolygon
     virtual OGRPolygon* CurvePolyToPoly(double dfMaxAngleStepSizeDegrees = 0,
                                         const char* const* papszOptions = NULL) const;
@@ -879,7 +960,9 @@ class CPL_DLL OGRCurvePolygon : public OGRSurface
     virtual OGRBoolean  Contains( const OGRGeometry * ) const;
 
     // Non standard
-    virtual void setCoordinateDimension( int nDimension ); 
+    virtual void setCoordinateDimension( int nDimension );
+    virtual void set3D( OGRBoolean bIs3D );
+    virtual void setMeasured( OGRBoolean bIsMeasured );
 
     OGRErr        addRing( OGRCurve * );
     OGRErr        addRingDirectly( OGRCurve * );
@@ -925,8 +1008,11 @@ class CPL_DLL OGRPolygon : public OGRCurvePolygon
 
   public:
                 OGRPolygon();
+                OGRPolygon(const OGRPolygon& other);
     virtual    ~OGRPolygon();
 
+    OGRPolygon& operator=(const OGRPolygon& other);
+
     // Non standard (OGRGeometry).
     virtual const char *getGeometryName() const;
     virtual OGRwkbGeometryType getGeometryType() const;
@@ -936,15 +1022,15 @@ class CPL_DLL OGRPolygon : public OGRCurvePolygon
                                              const char* const* papszOptions = NULL) const;
 
     // ISurface Interface
-    virtual int         PointOnSurface( OGRPoint * poPoint ) const;
-    
+    virtual OGRErr        PointOnSurface( OGRPoint * poPoint ) const;
+
     // IWks Interface
     virtual int WkbSize() const;
     virtual OGRErr importFromWkb( unsigned char *, int = -1, OGRwkbVariant=wkbVariantOldOgc );
     virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *, OGRwkbVariant=wkbVariantOldOgc ) const;
     virtual OGRErr importFromWkt( char ** );
     virtual OGRErr exportToWkt( char ** ppszDstText, OGRwkbVariant=wkbVariantOldOgc ) const;
-    
+
     // ICurvePolygon
     virtual OGRPolygon* CurvePolyToPoly(double dfMaxAngleStepSizeDegrees = 0,
                                         const char* const* papszOptions = NULL) const;
@@ -987,14 +1073,17 @@ class CPL_DLL OGRGeometryCollection : public OGRGeometry
                                                      OGRwkbVariant eWkbVariant,
                                                      const char* pszSkipPrefix ) const;
     virtual OGRBoolean         isCompatibleSubType( OGRwkbGeometryType ) const;
-    
+
     static OGRGeometryCollection* TransferMembersAndDestroy(OGRGeometryCollection* poSrc,
                                                   OGRGeometryCollection* poDst);
 
   public:
                 OGRGeometryCollection();
+                OGRGeometryCollection(const OGRGeometryCollection& other);
     virtual     ~OGRGeometryCollection();
 
+    OGRGeometryCollection& operator=(const OGRGeometryCollection& other);
+
     // Non standard (OGRGeometry).
     virtual const char *getGeometryName() const;
     virtual OGRwkbGeometryType getGeometryType() const;
@@ -1030,9 +1119,11 @@ class CPL_DLL OGRGeometryCollection : public OGRGeometry
 
     // ISpatialRelation
     virtual OGRBoolean  Equals( OGRGeometry * ) const;
-    
+
     // Non standard
-    virtual void setCoordinateDimension( int nDimension ); 
+    virtual void setCoordinateDimension( int nDimension );
+    virtual void set3D( OGRBoolean bIs3D );
+    virtual void setMeasured( OGRBoolean bIsMeasured );
     virtual OGRErr addGeometry( const OGRGeometry * );
     virtual OGRErr addGeometryDirectly( OGRGeometry * );
     virtual OGRErr removeGeometry( int iIndex, int bDelete = TRUE );
@@ -1059,14 +1150,17 @@ class CPL_DLL OGRMultiSurface : public OGRGeometryCollection
 
   public:
             OGRMultiSurface();
+            OGRMultiSurface(const OGRMultiSurface& other);
     virtual ~OGRMultiSurface();
 
+    OGRMultiSurface& operator=(const OGRMultiSurface& other);
+
     // Non standard (OGRGeometry).
     virtual const char *getGeometryName() const;
     virtual OGRwkbGeometryType getGeometryType() const;
     virtual OGRErr importFromWkt( char ** );
     virtual OGRErr exportToWkt( char **, OGRwkbVariant=wkbVariantOldOgc ) const;
-    
+
     // IMultiSurface methods
     virtual OGRErr      PointOnSurface( OGRPoint * poPoint ) const;
 
@@ -1094,19 +1188,22 @@ class CPL_DLL OGRMultiPolygon : public OGRMultiSurface
 
   public:
             OGRMultiPolygon();
+            OGRMultiPolygon(const OGRMultiPolygon& other);
     virtual ~OGRMultiPolygon();
 
+    OGRMultiPolygon& operator=(const OGRMultiPolygon& other);
+
     // Non standard (OGRGeometry).
     virtual const char *getGeometryName() const;
     virtual OGRwkbGeometryType getGeometryType() const;
     virtual OGRErr exportToWkt( char **, OGRwkbVariant=wkbVariantOldOgc ) const;
-    
+
     // IMultiSurface methods
     virtual OGRErr      PointOnSurface( OGRPoint * poPoint ) const;
 
     // Non standard
     virtual OGRBoolean hasCurveGeometry(int bLookForNonLinear = FALSE) const;
-    
+
     static OGRMultiSurface* CastToMultiSurface(OGRMultiPolygon* poMP);
 };
 
@@ -1128,8 +1225,11 @@ class CPL_DLL OGRMultiPoint : public OGRGeometryCollection
 
   public:
             OGRMultiPoint();
+            OGRMultiPoint(const OGRMultiPoint& other);
     virtual ~OGRMultiPoint();
 
+    OGRMultiPoint& operator=(const OGRMultiPoint& other);
+
     // Non standard (OGRGeometry).
     virtual const char *getGeometryName() const;
     virtual OGRwkbGeometryType getGeometryType() const;
@@ -1161,8 +1261,11 @@ class CPL_DLL OGRMultiCurve : public OGRGeometryCollection
 
   public:
             OGRMultiCurve();
+            OGRMultiCurve(const OGRMultiCurve& other);
     virtual ~OGRMultiCurve();
 
+    OGRMultiCurve& operator=(const OGRMultiCurve& other);
+
     // Non standard (OGRGeometry).
     virtual const char *getGeometryName() const;
     virtual OGRwkbGeometryType getGeometryType() const;
@@ -1171,7 +1274,7 @@ class CPL_DLL OGRMultiCurve : public OGRGeometryCollection
 
     // IGeometry methods
     virtual int getDimension() const;
-    
+
     // Non standard
     virtual OGRBoolean hasCurveGeometry(int bLookForNonLinear = FALSE) const;
 
@@ -1193,13 +1296,16 @@ class CPL_DLL OGRMultiLineString : public OGRMultiCurve
 
   public:
             OGRMultiLineString();
+            OGRMultiLineString(const OGRMultiLineString& other);
     virtual ~OGRMultiLineString();
 
+    OGRMultiLineString& operator=(const OGRMultiLineString& other);
+
     // Non standard (OGRGeometry).
     virtual const char *getGeometryName() const;
     virtual OGRwkbGeometryType getGeometryType() const;
     virtual OGRErr exportToWkt( char **, OGRwkbVariant=wkbVariantOldOgc ) const;
-    
+
     // Non standard
     virtual OGRBoolean hasCurveGeometry(int bLookForNonLinear = FALSE) const;
 
@@ -1241,7 +1347,7 @@ class CPL_DLL OGRGeometryFactory
     static OGRGeometry * forceToMultiPolygon( OGRGeometry * );
     static OGRGeometry * forceToMultiPoint( OGRGeometry * );
     static OGRGeometry * forceToMultiLineString( OGRGeometry * );
-    
+
     static OGRGeometry * forceTo( OGRGeometry* poGeom,
                                   OGRwkbGeometryType eTargetType,
                                   const char*const* papszOptions = NULL );
@@ -1256,10 +1362,10 @@ class CPL_DLL OGRGeometryFactory
                                               OGRCoordinateTransformation *poCT,
                                               char** papszOptions );
 
-    static OGRGeometry* 
+    static OGRGeometry*
         approximateArcAngles( double dfX, double dfY, double dfZ,
-                              double dfPrimaryRadius, double dfSecondaryAxis, 
-                              double dfRotation, 
+                              double dfPrimaryRadius, double dfSecondaryAxis,
+                              double dfRotation,
                               double dfStartAngle, double dfEndAngle,
                               double dfMaxAngleStepSizeDegrees );
 
@@ -1288,5 +1394,7 @@ OGRPreparedGeometry* OGRCreatePreparedGeometry( const OGRGeometry* poGeom );
 void OGRDestroyPreparedGeometry( OGRPreparedGeometry* poPreparedGeom );
 int OGRPreparedGeometryIntersects( const OGRPreparedGeometry* poPreparedGeom,
                                    const OGRGeometry* poOtherGeom );
+int OGRPreparedGeometryContains( const OGRPreparedGeometry* poPreparedGeom,
+                                 const OGRGeometry* poOtherGeom );
 
-#endif /* ndef _OGR_GEOMETRY_H_INCLUDED */
+#endif /* ndef OGR_GEOMETRY_H_INCLUDED */
diff --git a/ogr/ogr_geos.h b/ogr/ogr_geos.h
index f9d24cf..19e75e4 100644
--- a/ogr/ogr_geos.h
+++ b/ogr/ogr_geos.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_geos.h 27483 2014-06-30 20:49:41Z rouault $
+ * $Id: ogr_geos.h 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Definitions related to support for use of GEOS in OGR.
@@ -32,7 +32,7 @@
 #ifndef OGR_GEOS_H_INCLUDED
 #define OGR_GEOS_H_INCLUDED
 
-#ifdef HAVE_GEOS 
+#ifdef HAVE_GEOS
 // To avoid accidental use of non reentrant GEOS API.
 // (check only effective in GEOS >= 3.5)
 #  define GEOS_USE_ONLY_R_API
@@ -40,7 +40,7 @@
 #  include <geos_c.h>
 #else
 
-namespace geos { 
+namespace geos {
     class Geometry;
 };
 
diff --git a/ogr/ogr_opt.cpp b/ogr/ogr_opt.cpp
index e7c70c9..38acf73 100644
--- a/ogr/ogr_opt.cpp
+++ b/ogr/ogr_opt.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_opt.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: ogr_opt.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features
  * Purpose:  Functions for getting list of projection types, and their parms.
@@ -31,9 +31,9 @@
 #include "ogr_srs_api.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogr_opt.cpp 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: ogr_opt.cpp 33631 2016-03-04 06:28:09Z goatbar $");
 
-static const char *papszParameterDefinitions[] = {
+static const char * const papszParameterDefinitions[] = {
     SRS_PP_CENTRAL_MERIDIAN,    "Central Meridian",     "Long",  "0.0",
     SRS_PP_SCALE_FACTOR,        "Scale Factor",         "Ratio", "1.0",
     SRS_PP_STANDARD_PARALLEL_1, "Standard Parallel 1",  "Lat",   "0.0",
@@ -51,163 +51,167 @@ static const char *papszParameterDefinitions[] = {
     SRS_PP_LATITUDE_OF_POINT_2, "Latitude of Point 2",  "Lat",   "0.0",
     SRS_PP_LONGITUDE_OF_POINT_3,"Longitude of Point 3", "Long",  "0.0",
     SRS_PP_LATITUDE_OF_POINT_3, "Latitude of Point 3",  "Lat",   "0.0",
-    SRS_PP_RECTIFIED_GRID_ANGLE,"Rectified Grid Angle", "Angle", "0.0", 
-    SRS_PP_SATELLITE_HEIGHT,    "Satellite Height",     "m",   "35785831.0", 
+    SRS_PP_RECTIFIED_GRID_ANGLE,"Rectified Grid Angle", "Angle", "0.0",
+    SRS_PP_SATELLITE_HEIGHT,    "Satellite Height",     "m",   "35785831.0",
+    SRS_PP_PEG_POINT_LATITUDE,  "Peg Point Latitude",   "Lat",   "0.0",
+    SRS_PP_PEG_POINT_LONGITUDE, "Peg Point Longitude",  "Long",  "0.0",
+    SRS_PP_PEG_POINT_HEADING,   "Peg Point Heading",    "Angle", "0.0",
+    SRS_PP_PEG_POINT_HEIGHT,    "Peg Point Height",     "m",     "0.0",
     NULL
 };
 
-static const char *papszProjectionDefinitions[] = {
+static const char * const papszProjectionDefinitions[] = {
 
-    "*", 
+    "*",
     SRS_PT_TRANSVERSE_MERCATOR,
     "Transverse Mercator",
     SRS_PP_LATITUDE_OF_ORIGIN,
-    SRS_PP_CENTRAL_MERIDIAN, 
-    SRS_PP_SCALE_FACTOR, 
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_SCALE_FACTOR,
     SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
-    "*", 
+    "*",
     SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED,
     "Transverse Mercator (South Oriented)",
-    SRS_PP_LATITUDE_OF_ORIGIN, 
+    SRS_PP_LATITUDE_OF_ORIGIN,
     SRS_PP_CENTRAL_MERIDIAN,
-    SRS_PP_SCALE_FACTOR, 
+    SRS_PP_SCALE_FACTOR,
     SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_TUNISIA_MINING_GRID,
     "Tunisia Mining Grid",
-    SRS_PP_LATITUDE_OF_ORIGIN, 
-    SRS_PP_CENTRAL_MERIDIAN, 
-    SRS_PP_FALSE_EASTING, 
-    SRS_PP_FALSE_NORTHING, 
+    SRS_PP_LATITUDE_OF_ORIGIN,
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_FALSE_EASTING,
+    SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_ALBERS_CONIC_EQUAL_AREA,
     "Albers Conic Equal Area",
     SRS_PP_STANDARD_PARALLEL_1,
     SRS_PP_STANDARD_PARALLEL_2,
-    SRS_PP_LATITUDE_OF_CENTER, 
+    SRS_PP_LATITUDE_OF_CENTER,
     SRS_PP_LONGITUDE_OF_CENTER,
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
-    "*", 
+    "*",
     SRS_PT_AZIMUTHAL_EQUIDISTANT,
     "Azimuthal Equidistant",
-    SRS_PP_LATITUDE_OF_CENTER, 
+    SRS_PP_LATITUDE_OF_CENTER,
     SRS_PP_LONGITUDE_OF_CENTER,
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_CYLINDRICAL_EQUAL_AREA,
     "Cylindrical Equal Area",
-    SRS_PP_STANDARD_PARALLEL_1, 
-    SRS_PP_CENTRAL_MERIDIAN, 
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_STANDARD_PARALLEL_1,
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
-    "*", 
-    SRS_PT_CASSINI_SOLDNER, 
-    "Cassini/Soldner", 
-    SRS_PP_LATITUDE_OF_ORIGIN, 
-    SRS_PP_CENTRAL_MERIDIAN, 
-    SRS_PP_FALSE_EASTING, 
+    "*",
+    SRS_PT_CASSINI_SOLDNER,
+    "Cassini/Soldner",
+    SRS_PP_LATITUDE_OF_ORIGIN,
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_EQUIDISTANT_CONIC,
-    "Equidistant Conic", 
+    "Equidistant Conic",
     SRS_PP_STANDARD_PARALLEL_1,
     SRS_PP_STANDARD_PARALLEL_2,
-    SRS_PP_LATITUDE_OF_CENTER, 
+    SRS_PP_LATITUDE_OF_CENTER,
     SRS_PP_LONGITUDE_OF_CENTER,
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_BONNE,
     "Bonne",
     SRS_PP_STANDARD_PARALLEL_1,
-    SRS_PP_CENTRAL_MERIDIAN, 
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_ECKERT_I,
     "Eckert I",
-    SRS_PP_CENTRAL_MERIDIAN, 
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
-    
+
     "*",
     SRS_PT_ECKERT_II,
     "Eckert II",
-    SRS_PP_CENTRAL_MERIDIAN, 
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
-    
+
     "*",
     SRS_PT_ECKERT_III,
     "Eckert III",
-    SRS_PP_CENTRAL_MERIDIAN, 
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
-    
+
     "*",
     SRS_PT_ECKERT_IV,
     "Eckert IV",
-    SRS_PP_CENTRAL_MERIDIAN, 
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
-    
+
     "*",
     SRS_PT_ECKERT_V,
     "Eckert V",
-    SRS_PP_CENTRAL_MERIDIAN, 
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
-    
+
     "*",
     SRS_PT_ECKERT_VI,
     "Eckert VI",
-    SRS_PP_CENTRAL_MERIDIAN, 
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_EQUIRECTANGULAR,
     "Equirectangular",
-    SRS_PP_LATITUDE_OF_ORIGIN, 
-    SRS_PP_CENTRAL_MERIDIAN, 
-    SRS_PP_STANDARD_PARALLEL_1, 
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_LATITUDE_OF_ORIGIN,
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_STANDARD_PARALLEL_1,
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_GAUSSSCHREIBERTMERCATOR,
     "Gauss-Schreiber Transverse Mercator",
-    SRS_PP_LATITUDE_OF_ORIGIN, 
-    SRS_PP_CENTRAL_MERIDIAN, 
-    SRS_PP_SCALE_FACTOR, 
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_LATITUDE_OF_ORIGIN,
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_SCALE_FACTOR,
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_GALL_STEREOGRAPHIC,
     "Gall Stereographic",
-    SRS_PP_CENTRAL_MERIDIAN, 
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_GOODE_HOMOLOSINE,
     "Goode Homolosine",
-    SRS_PP_CENTRAL_MERIDIAN, 
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
@@ -217,28 +221,28 @@ static const char *papszProjectionDefinitions[] = {
     "*",
     SRS_PT_GEOSTATIONARY_SATELLITE,
     "Geostationary Satellite",
-    SRS_PP_CENTRAL_MERIDIAN, 
+    SRS_PP_CENTRAL_MERIDIAN,
     SRS_PP_SATELLITE_HEIGHT,
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_GNOMONIC,
     "Gnomonic",
     SRS_PP_LATITUDE_OF_ORIGIN,
-    SRS_PP_CENTRAL_MERIDIAN, 
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_HOTINE_OBLIQUE_MERCATOR,
     "Hotine Oblique Mercator",
-    SRS_PP_LATITUDE_OF_CENTER, 
+    SRS_PP_LATITUDE_OF_CENTER,
     SRS_PP_LONGITUDE_OF_CENTER,
-    SRS_PP_AZIMUTH, 
+    SRS_PP_AZIMUTH,
     SRS_PP_RECTIFIED_GRID_ANGLE,
-    SRS_PP_SCALE_FACTOR, 
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_SCALE_FACTOR,
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
@@ -249,61 +253,61 @@ static const char *papszProjectionDefinitions[] = {
     SRS_PP_LONGITUDE_OF_POINT_1,
     SRS_PP_LATITUDE_OF_POINT_2,
     SRS_PP_LONGITUDE_OF_POINT_2,
-    SRS_PP_SCALE_FACTOR, 
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_SCALE_FACTOR,
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA,
     "Lambert Azimuthal Equal Area",
-    SRS_PP_LATITUDE_OF_CENTER, 
+    SRS_PP_LATITUDE_OF_CENTER,
     SRS_PP_LONGITUDE_OF_CENTER,
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP,
     "Lambert Conformal Conic (2SP)",
-    SRS_PP_STANDARD_PARALLEL_1, 
-    SRS_PP_STANDARD_PARALLEL_2, 
-    SRS_PP_LATITUDE_OF_ORIGIN, 
-    SRS_PP_CENTRAL_MERIDIAN, 
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_STANDARD_PARALLEL_1,
+    SRS_PP_STANDARD_PARALLEL_2,
+    SRS_PP_LATITUDE_OF_ORIGIN,
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP,
     "Lambert Conformal Conic (1SP)",
     SRS_PP_LATITUDE_OF_ORIGIN,
-    SRS_PP_CENTRAL_MERIDIAN, 
-    SRS_PP_SCALE_FACTOR, 
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_SCALE_FACTOR,
     SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM,
     "Lambert Conformal Conic (2SP - Belgium)",
-    SRS_PP_STANDARD_PARALLEL_1, 
-    SRS_PP_STANDARD_PARALLEL_2, 
-    SRS_PP_LATITUDE_OF_ORIGIN, 
-    SRS_PP_CENTRAL_MERIDIAN, 
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_STANDARD_PARALLEL_1,
+    SRS_PP_STANDARD_PARALLEL_2,
+    SRS_PP_LATITUDE_OF_ORIGIN,
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_MILLER_CYLINDRICAL,
     "Miller Cylindrical",
-    SRS_PP_LATITUDE_OF_CENTER, 
+    SRS_PP_LATITUDE_OF_CENTER,
     SRS_PP_LONGITUDE_OF_CENTER,
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_MERCATOR_1SP,
     "Mercator (1SP)",
     SRS_PP_LATITUDE_OF_ORIGIN,
-    SRS_PP_CENTRAL_MERIDIAN, 
-    SRS_PP_SCALE_FACTOR, 
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_SCALE_FACTOR,
     SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
@@ -312,56 +316,56 @@ static const char *papszProjectionDefinitions[] = {
     "Mercator (2SP)",
     SRS_PP_STANDARD_PARALLEL_1,
     SRS_PP_LATITUDE_OF_ORIGIN,
-    SRS_PP_CENTRAL_MERIDIAN, 
+    SRS_PP_CENTRAL_MERIDIAN,
     SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_MOLLWEIDE,
     "Mollweide",
-    SRS_PP_CENTRAL_MERIDIAN, 
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_NEW_ZEALAND_MAP_GRID,
     "New Zealand Map Grid",
-    SRS_PP_LATITUDE_OF_ORIGIN, 
-    SRS_PP_CENTRAL_MERIDIAN, 
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_LATITUDE_OF_ORIGIN,
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_OBLIQUE_STEREOGRAPHIC,
     "Oblique Stereographic",
-    SRS_PP_LATITUDE_OF_ORIGIN, 
-    SRS_PP_CENTRAL_MERIDIAN, 
-    SRS_PP_SCALE_FACTOR, 
+    SRS_PP_LATITUDE_OF_ORIGIN,
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_SCALE_FACTOR,
     SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_ORTHOGRAPHIC,
     "Orthographic",
-    SRS_PP_LATITUDE_OF_ORIGIN, 
-    SRS_PP_CENTRAL_MERIDIAN, 
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_LATITUDE_OF_ORIGIN,
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_POLYCONIC,
     "Polyconic",
-    SRS_PP_LATITUDE_OF_ORIGIN, 
-    SRS_PP_CENTRAL_MERIDIAN, 
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_LATITUDE_OF_ORIGIN,
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
-    
+
     "*",
     SRS_PT_POLAR_STEREOGRAPHIC,
     "Polar Stereographic",
     SRS_PP_LATITUDE_OF_ORIGIN,
-    SRS_PP_CENTRAL_MERIDIAN, 
-    SRS_PP_SCALE_FACTOR, 
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_SCALE_FACTOR,
     SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
@@ -369,51 +373,51 @@ static const char *papszProjectionDefinitions[] = {
     SRS_PT_ROBINSON,
     "Robinson",
     SRS_PP_LONGITUDE_OF_CENTER,
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_SINUSOIDAL,
     "Sinusoidal",
     SRS_PP_LONGITUDE_OF_CENTER,
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*"
     SRS_PT_STEREOGRAPHIC,
     "Stereographic",
     SRS_PP_LATITUDE_OF_ORIGIN,
-    SRS_PP_CENTRAL_MERIDIAN, 
-    SRS_PP_SCALE_FACTOR, 
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_SCALE_FACTOR,
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*"
     SRS_PT_TWO_POINT_EQUIDISTANT,
     "Two Point Equidistant",
     SRS_PP_LATITUDE_OF_1ST_POINT,
-    SRS_PP_LONGITUDE_OF_1ST_POINT, 
+    SRS_PP_LONGITUDE_OF_1ST_POINT,
     SRS_PP_LATITUDE_OF_2ND_POINT,
     SRS_PP_LONGITUDE_OF_2ND_POINT,
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_VANDERGRINTEN,
     "Van Der Grinten",
     SRS_PP_CENTRAL_MERIDIAN,
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*"
     SRS_PT_KROVAK,
     "Krovak",
     SRS_PP_LATITUDE_OF_CENTER,
-    SRS_PP_LONGITUDE_OF_CENTER, 
+    SRS_PP_LONGITUDE_OF_CENTER,
     SRS_PP_AZIMUTH,
     SRS_PP_PSEUDO_STD_PARALLEL_1,
     SRS_PP_SCALE_FACTOR,
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
@@ -421,51 +425,51 @@ static const char *papszProjectionDefinitions[] = {
     "International Map of the World Polyconic",
     SRS_PP_LATITUDE_OF_1ST_POINT,
     SRS_PP_LATITUDE_OF_2ND_POINT,
-    SRS_PP_CENTRAL_MERIDIAN, 
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_WAGNER_I,
     "Wagner I (Kavraisky VI)",
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_WAGNER_II,
     "Wagner II",
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_WAGNER_III,
     "Wagner III",
     SRS_PP_LATITUDE_OF_ORIGIN,
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_WAGNER_IV,
     "Wagner IV",
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_WAGNER_V,
     "Wagner V",
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_WAGNER_VI,
     "Wagner VI",
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
     SRS_PT_WAGNER_VII,
     "Wagner VII",
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
 
     "*",
@@ -474,6 +478,14 @@ static const char *papszProjectionDefinitions[] = {
     SRS_PP_LATITUDE_OF_ORIGIN,
     SRS_PP_CENTRAL_MERIDIAN,
 
+    "*",
+    SRS_PT_SCH,
+    "Spherical Crosstrack Height",
+    SRS_PP_PEG_POINT_LATITUDE,
+    SRS_PP_PEG_POINT_LONGITUDE,
+    SRS_PP_PEG_POINT_HEADING,
+    SRS_PP_PEG_POINT_HEIGHT,
+
     NULL
 };
 
@@ -484,7 +496,7 @@ static const char *papszProjectionDefinitions[] = {
 /*                      OPTGetProjectionMethods()                       */
 /************************************************************************/
 
-/** 
+/**
  * Fetch list of possible projection methods.
  *
  * @return Returns NULL terminated list of projection methods.  This should
@@ -511,10 +523,10 @@ char **OPTGetProjectionMethods()
 /************************************************************************/
 
 /**
- * Fetch the parameters for a given projection method. 
+ * Fetch the parameters for a given projection method.
  *
  * @param pszProjectionMethod internal name of projection methods to fetch
- * the parameters for, such as "Transverse_Mercator" 
+ * the parameters for, such as "Transverse_Mercator"
  * (SRS_PT_TRANSVERSE_MERCATOR).
  *
  * @param ppszUserName pointer in which to return a user visible name for
@@ -522,11 +534,11 @@ char **OPTGetProjectionMethods()
  * freed by the caller.  Legal to pass in NULL if user name not required.
  *
  * @return returns a NULL terminated list of internal parameter names that
- * should be freed by the caller when no longer needed.  Returns NULL if 
+ * should be freed by the caller when no longer needed.  Returns NULL if
  * projection method is unknown.
  */
 
-char **OPTGetParameterList( const char *pszProjectionMethod, 
+char **OPTGetParameterList( const char *pszProjectionMethod,
                             char ** ppszUserName )
 
 {
@@ -535,7 +547,7 @@ char **OPTGetParameterList( const char *pszProjectionMethod,
 
     for( i = 1; papszProjectionDefinitions[i] != NULL; i++ )
     {
-        if( papszProjectionDefinitions[i-1][0] == '*' 
+        if( papszProjectionDefinitions[i-1][0] == '*'
             && EQUAL(papszProjectionDefinitions[i],pszProjectionMethod) )
         {
             i++;
@@ -544,10 +556,10 @@ char **OPTGetParameterList( const char *pszProjectionMethod,
                 *ppszUserName = (char *)papszProjectionDefinitions[i];
 
             i++;
-            while( papszProjectionDefinitions[i] != NULL 
+            while( papszProjectionDefinitions[i] != NULL
                    && papszProjectionDefinitions[i][0] != '*' )
             {
-                papszList = CSLAddString( papszList, 
+                papszList = CSLAddString( papszList,
                                           papszProjectionDefinitions[i] );
                 i++;
             }
@@ -556,7 +568,7 @@ char **OPTGetParameterList( const char *pszProjectionMethod,
             return papszList;
         }
     }
-    
+
     return NULL;
 }
 
@@ -565,22 +577,22 @@ char **OPTGetParameterList( const char *pszProjectionMethod,
 /************************************************************************/
 
 /**
- * Fetch information about a single parameter of a projection method. 
+ * Fetch information about a single parameter of a projection method.
  *
  * @param pszProjectionMethod name of projection method for which the parameter
  * applies.  Not currently used, but in the future this could affect defaults.
  * This is the internal projection method name, such as "Tranverse_Mercator".
  *
  * @param pszParameterName name of the parameter to fetch information about.
- * This is the internal name such as "central_meridian" 
- * (SRS_PP_CENTRAL_MERIDIAN). 
- * 
+ * This is the internal name such as "central_meridian"
+ * (SRS_PP_CENTRAL_MERIDIAN).
+ *
  * @param ppszUserName location at which to return the user visible name for
- * the parameter.  This pointer may be NULL to skip the user name.  The 
+ * the parameter.  This pointer may be NULL to skip the user name.  The
  * returned name should not be modified or freed.
  *
  * @param ppszType location at which to return the parameter type for
- * the parameter.  This pointer may be NULL to skip.  The  returned type 
+ * the parameter.  This pointer may be NULL to skip.  The  returned type
  * should not be modified or freed.  The type values are described above.
  *
  * @param pdfDefaultValue location at which to put the default value for
@@ -617,4 +629,3 @@ int OPTGetParameterInfo( const char * pszProjectionMethod,
 
     return FALSE;
 }
-
diff --git a/ogr/ogr_p.h b/ogr/ogr_p.h
index 69a4daf..359df8b 100644
--- a/ogr/ogr_p.h
+++ b/ogr/ogr_p.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_p.h 28900 2015-04-14 09:40:34Z rouault $
+ * $Id: ogr_p.h 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Some private helper functions and stuff for OGR implementation.
@@ -42,11 +42,12 @@
 
 #include "ogr_core.h"
 #include "ogr_geometry.h"
+#include "ogr_feature.h"
 
 /* A default name for the default geometry column, instead of '' */
 #define OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME     "_ogr_geometry_"
 
-#ifdef CPL_MSB 
+#ifdef CPL_MSB
 #  define OGR_SWAP(x)   (x == wkbNDR)
 #else
 #  define OGR_SWAP(x)   (x == wkbXDR)
@@ -66,22 +67,32 @@
 /*      helper function for parsing well known text format vector objects.*/
 /* -------------------------------------------------------------------- */
 
-#ifdef _OGR_GEOMETRY_H_INCLUDED
+#ifdef OGR_GEOMETRY_H_INCLUDED
 #define OGR_WKT_TOKEN_MAX       64
 
 const char CPL_DLL * OGRWktReadToken( const char * pszInput, char * pszToken );
 
 const char CPL_DLL * OGRWktReadPoints( const char * pszInput,
-                                       OGRRawPoint **ppaoPoints, 
+                                       OGRRawPoint **ppaoPoints,
                                        double **ppadfZ,
                                        int * pnMaxPoints,
                                        int * pnReadPoints );
 
+const char CPL_DLL * OGRWktReadPointsM( const char * pszInput,
+                                        OGRRawPoint **ppaoPoints,
+                                        double **ppadfZ,
+                                        double **ppadfM,
+                                        int * flags, /* geometry flags, are we expecting Z, M, or both; may change due to input */
+                                        int * pnMaxPoints,
+                                        int * pnReadPoints );
+
 void CPL_DLL OGRMakeWktCoordinate( char *, double, double, double, int );
+void CPL_DLL OGRMakeWktCoordinateM( char *, double, double, double, double, OGRBoolean, OGRBoolean );
 
 #endif
 
-void OGRFormatDouble( char *pszBuffer, int nBufferLen, double dfVal, char chDecimalSep, int nPrecision = 15 );
+void OGRFormatDouble( char *pszBuffer, int nBufferLen, double dfVal,
+                      char chDecimalSep, int nPrecision = 15, char chConversionSpecifier = 'f' );
 
 /* -------------------------------------------------------------------- */
 /*      Date-time parsing and processing functions                      */
@@ -114,9 +125,9 @@ int CPL_DLL OGRGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOpti
 #define SPF_OGR_GEOM_AREA 4
 #define SPECIAL_FIELD_COUNT 5
 
-extern const char* SpecialFieldNames[SPECIAL_FIELD_COUNT];
+extern const char* const SpecialFieldNames[SPECIAL_FIELD_COUNT];
 
-#ifdef _SWQ_H_INCLUDED_
+#ifdef SWQ_H_INCLUDED_
 extern const swq_field_type SpecialFieldTypes[SPECIAL_FIELD_COUNT];
 #endif
 
@@ -134,12 +145,12 @@ OGRErr CPL_DLL OGRCheckPermutation(int* panPermutation, int nSize);
 /* GML related */
 
 OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
-                                      int bGetSecondaryGeometryOption,
+                                      int nPseudoBoolGetSecondaryGeometryOption,
                                       int nRecLevel = 0,
                                       int nSRSDimension = 0,
-                                      int bIgnoreGSG = FALSE,
-                                      int bOrientation = TRUE,
-                                      int bFaceHoleNegative = FALSE);
+                                      bool bIgnoreGSG = false,
+                                      bool bOrientation = true,
+                                      bool bFaceHoleNegative = false);
 
 /************************************************************************/
 /*                        PostGIS EWKB encoding                         */
@@ -150,7 +161,7 @@ OGRGeometry CPL_DLL *OGRGeometryFromEWKB( GByte *pabyWKB, int nLength, int* pnSR
 OGRGeometry CPL_DLL *OGRGeometryFromHexEWKB( const char *pszBytea, int* pnSRID,
                                              int bIsPostGIS1_EWKB );
 char CPL_DLL * OGRGeometryToHexEWKB( OGRGeometry * poGeometry, int nSRSId,
-                                     int bIsPostGIS1_EWKB );
+                                     int nPostGISMajor, int nPostGISMinor );
 
 /************************************************************************/
 /*                        WKB Type Handling encoding                    */
@@ -158,6 +169,14 @@ char CPL_DLL * OGRGeometryToHexEWKB( OGRGeometry * poGeometry, int nSRSId,
 
 OGRErr OGRReadWKBGeometryType( unsigned char * pabyData,
                                OGRwkbVariant wkbVariant,
-                               OGRwkbGeometryType *eGeometryType, OGRBoolean *b3D );
+                               OGRwkbGeometryType *eGeometryType );
+
+/************************************************************************/
+/*                            Other                                     */
+/************************************************************************/
+
+void CPL_DLL OGRUpdateFieldType( OGRFieldDefn* poFDefn,
+                                 OGRFieldType eNewType,
+                                 OGRFieldSubType eNewSubType );
 
 #endif /* ndef OGR_P_H_INCLUDED */
diff --git a/ogr/ogr_spatialref.h b/ogr/ogr_spatialref.h
index d3ec944..f12ff22 100644
--- a/ogr/ogr_spatialref.h
+++ b/ogr/ogr_spatialref.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_spatialref.h 28972 2015-04-22 10:39:11Z rouault $
+ * $Id: ogr_spatialref.h 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Classes for manipulating spatial reference systems in a
@@ -29,8 +29,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_SPATIALREF_H_INCLUDED
-#define _OGR_SPATIALREF_H_INCLUDED
+#ifndef OGR_SPATIALREF_H_INCLUDED
+#define OGR_SPATIALREF_H_INCLUDED
 
 #include "ogr_srs_api.h"
 
@@ -53,7 +53,7 @@
  *
  * Normally application code just interacts with the OGRSpatialReference
  * object, which uses the OGR_SRSNode to implement it's data structure;
- * however, this class is user accessable for detailed access to components
+ * however, this class is user accessible for detailed access to components
  * of an SRS definition.
  */
 
@@ -68,13 +68,13 @@ class CPL_DLL OGR_SRSNode
 
     int         NeedsQuoting() const;
     OGRErr      importFromWkt( char **, int nRecLevel, int* pnNodes );
-    
+
   public:
                 OGR_SRSNode(const char * = NULL);
                 ~OGR_SRSNode();
 
     int         IsLeafNode() const { return nChildren == 0; }
-    
+
     int         GetChildCount() const { return nChildren; }
     OGR_SRSNode *GetChild( int );
     const OGR_SRSNode *GetChild( int ) const;
@@ -100,10 +100,10 @@ class CPL_DLL OGR_SRSNode
     OGRErr      importFromWkt( char ** );
     OGRErr      exportToWkt( char ** ) const;
     OGRErr      exportToPrettyWkt( char **, int = 1) const;
-    
-    OGRErr      applyRemapper( const char *pszNode, 
-                               char **papszSrcValues, 
-                               char **papszDstValues, 
+
+    OGRErr      applyRemapper( const char *pszNode,
+                               char **papszSrcValues,
+                               char **papszDstValues,
                                int nStepSize = 1,
                                int bChildOfHit = FALSE );
 };
@@ -113,7 +113,7 @@ class CPL_DLL OGR_SRSNode
 /************************************************************************/
 
 /**
- * This class respresents a OpenGIS Spatial Reference System, and contains
+ * This class represents an OpenGIS Spatial Reference System, and contains
  * methods for converting between this object organization and well known
  * text (WKT) format.  This object is reference counted as one instance of
  * the object is normally shared between many OGRGeometry objects.
@@ -152,11 +152,11 @@ class CPL_DLL OGRSpatialReference
   public:
                 OGRSpatialReference(const OGRSpatialReference&);
                 OGRSpatialReference(const char * = NULL);
-                
+
     virtual    ~OGRSpatialReference();
-    
+
     static void DestroySpatialReference(OGRSpatialReference* poSRS);
-                
+
     OGRSpatialReference &operator=(const OGRSpatialReference&);
 
     int         Reference();
@@ -178,7 +178,7 @@ class CPL_DLL OGRSpatialReference
                                   double * ) const;
     OGRErr      exportToERM( char *pszProj, char *pszDatum, char *pszUnits );
     OGRErr      exportToMICoordSys( char ** ) const;
-    
+
     OGRErr      importFromWkt( char ** );
     OGRErr      importFromProj4( const char * );
     OGRErr      importFromEPSG( int );
@@ -190,7 +190,7 @@ class CPL_DLL OGRSpatialReference
 #define USGS_ANGLE_PACKEDDMS      TRUE /* 1 */
 #define USGS_ANGLE_RADIANS        2
     OGRErr      importFromUSGS( long iProjSys, long iZone,
-                                double *padfPrjParams, long iDatum, 
+                                double *padfPrjParams, long iDatum,
                                 int nUSGSAngleFormat = USGS_ANGLE_PACKEDDMS );
     OGRErr      importFromPanorama( long, long, long, double* );
     OGRErr      importFromOzi( const char * const* papszLines );
@@ -203,7 +203,7 @@ class CPL_DLL OGRSpatialReference
                                const char *pszUnits );
     OGRErr      importFromUrl( const char * );
     OGRErr      importFromMICoordSys( const char * );
-    
+
     OGRErr      morphToESRI();
     OGRErr      morphFromESRI();
 
@@ -215,19 +215,19 @@ class CPL_DLL OGRSpatialReference
 
     int         EPSGTreatsAsLatLong();
     int         EPSGTreatsAsNorthingEasting();
-    const char *GetAxis( const char *pszTargetKey, int iAxis, 
+    const char *GetAxis( const char *pszTargetKey, int iAxis,
                          OGRAxisOrientation *peOrientation ) const;
-    OGRErr      SetAxes( const char *pszTargetKey, 
-                         const char *pszXAxisName, 
+    OGRErr      SetAxes( const char *pszTargetKey,
+                         const char *pszXAxisName,
                          OGRAxisOrientation eXAxisOrientation,
-                         const char *pszYAxisName, 
+                         const char *pszYAxisName,
                          OGRAxisOrientation eYAxisOrientation );
 
-    // Machinary for accessing parse nodes
+    // Machinery for accessing parse nodes
     OGR_SRSNode *GetRoot() { return poRoot; }
     const OGR_SRSNode *GetRoot() const { return poRoot; }
     void        SetRoot( OGR_SRSNode * );
-    
+
     OGR_SRSNode *GetAttrNode(const char *);
     const OGR_SRSNode *GetAttrNode(const char *) const;
     const char  *GetAttrValue(const char *, int = 0) const;
@@ -235,7 +235,7 @@ class CPL_DLL OGRSpatialReference
     OGRErr      SetNode( const char *, const char * );
     OGRErr      SetNode( const char *, double );
 
-    OGRErr      SetLinearUnitsAndUpdateParameters( const char *pszName, 
+    OGRErr      SetLinearUnitsAndUpdateParameters( const char *pszName,
                                                    double dfInMeters );
     OGRErr      SetLinearUnits( const char *pszName, double dfInMeters );
     OGRErr      SetTargetLinearUnits( const char *pszTargetKey,
@@ -275,9 +275,9 @@ class CPL_DLL OGRSpatialReference
     OGRErr      SetWellKnownGeogCS( const char * );
     OGRErr      CopyGeogCSFrom( const OGRSpatialReference * poSrcSRS );
     OGRErr      SetVertCS( const char *pszVertCSName,
-                           const char *pszVertDatumName, 
+                           const char *pszVertDatumName,
                            int nVertDatumClass = 2005 );
-    OGRErr      SetCompoundCS( const char *pszName, 
+    OGRErr      SetCompoundCS( const char *pszName,
                                const OGRSpatialReference *poHorizSRS,
                                const OGRSpatialReference *poVertSRS );
 
@@ -287,13 +287,13 @@ class CPL_DLL OGRSpatialReference
                             double = 0.0, double = 0.0, double = 0.0,
                             double = 0.0 );
     OGRErr      GetTOWGS84( double *padfCoef, int nCoeff = 7 ) const;
-    
+
     double      GetSemiMajor( OGRErr * = NULL ) const;
     double      GetSemiMinor( OGRErr * = NULL ) const;
     double      GetInvFlattening( OGRErr * = NULL ) const;
 
-    OGRErr      SetAuthority( const char * pszTargetKey, 
-                              const char * pszAuthority, 
+    OGRErr      SetAuthority( const char * pszTargetKey,
+                              const char * pszAuthority,
                               int nCode );
 
     OGRErr      AutoIdentifyEPSG();
@@ -302,13 +302,13 @@ class CPL_DLL OGRSpatialReference
     const char *GetAuthorityCode( const char * pszTargetKey ) const;
     const char *GetAuthorityName( const char * pszTargetKey ) const;
 
-    const char *GetExtension( const char *pszTargetKey, 
+    const char *GetExtension( const char *pszTargetKey,
                               const char *pszName,
                               const char *pszDefault = NULL ) const;
-    OGRErr      SetExtension( const char *pszTargetKey, 
-                              const char *pszName, 
+    OGRErr      SetExtension( const char *pszTargetKey,
+                              const char *pszName,
                               const char *pszValue );
-    
+
     int         FindProjParm( const char *pszParameter,
                               const OGR_SRSNode *poPROJCS=NULL ) const;
     OGRErr      SetProjParm( const char *, double );
@@ -325,7 +325,7 @@ class CPL_DLL OGRSpatialReference
     OGRErr      SetACEA( double dfStdP1, double dfStdP2,
                          double dfCenterLat, double dfCenterLong,
                          double dfFalseEasting, double dfFalseNorthing );
-    
+
     /** Azimuthal Equidistant */
     OGRErr      SetAE( double dfCenterLat, double dfCenterLong,
                        double dfFalseEasting, double dfFalseNorthing );
@@ -333,7 +333,7 @@ class CPL_DLL OGRSpatialReference
     /** Bonne */
     OGRErr      SetBonne( double dfStdP1, double dfCentralMeridian,
                           double dfFalseEasting, double dfFalseNorthing );
-    
+
     /** Cylindrical Equal Area */
     OGRErr      SetCEA( double dfStdP1, double dfCentralMeridian,
                         double dfFalseEasting, double dfFalseNorthing );
@@ -366,11 +366,11 @@ class CPL_DLL OGRSpatialReference
                                      double dfFalseEasting, double dfFalseNorthing );
 
     /** Geostationary Satellite */
-    OGRErr      SetGEOS( double dfCentralMeridian, double dfSatelliteHeight, 
+    OGRErr      SetGEOS( double dfCentralMeridian, double dfSatelliteHeight,
                          double dfFalseEasting, double dfFalseNorthing );
 
     /** Goode Homolosine */
-    OGRErr      SetGH( double dfCentralMeridian, 
+    OGRErr      SetGH( double dfCentralMeridian,
                        double dfFalseEasting, double dfFalseNorthing );
 
     /** Interrupted Goode Homolosine */
@@ -379,7 +379,7 @@ class CPL_DLL OGRSpatialReference
     /** Gall Stereograpic */
     OGRErr      SetGS( double dfCentralMeridian,
                        double dfFalseEasting, double dfFalseNorthing );
- 
+
     /** Gauss Schreiber Transverse Mercator */
     OGRErr      SetGaussSchreiberTMercator(double dfCenterLat, double dfCenterLong,
                                            double dfScale,
@@ -421,7 +421,7 @@ class CPL_DLL OGRSpatialReference
     /** Krovak Oblique Conic Conformal */
     OGRErr      SetKrovak( double dfCenterLat, double dfCenterLong,
                            double dfAzimuth, double dfPseudoStdParallelLat,
-                           double dfScale, 
+                           double dfScale,
                            double dfFalseEasting, double dfFalseNorthing );
 
     /** Lambert Azimuthal Equal-Area */
@@ -442,14 +442,14 @@ class CPL_DLL OGRSpatialReference
     OGRErr      SetLCCB( double dfStdP1, double dfStdP2,
                          double dfCenterLat, double dfCenterLong,
                          double dfFalseEasting, double dfFalseNorthing );
-    
+
     /** Miller Cylindrical */
     OGRErr      SetMC( double dfCenterLat, double dfCenterLong,
                        double dfFalseEasting, double dfFalseNorthing );
 
     /** Mercator */
     OGRErr      SetMercator( double dfCenterLat, double dfCenterLong,
-                             double dfScale, 
+                             double dfScale,
                              double dfFalseEasting, double dfFalseNorthing );
 
     OGRErr      SetMercator2SP( double dfStdP1,
@@ -468,7 +468,7 @@ class CPL_DLL OGRSpatialReference
     OGRErr      SetOS( double dfOriginLat, double dfCMeridian,
                        double dfScale,
                        double dfFalseEasting,double dfFalseNorthing);
-    
+
     /** Orthographic */
     OGRErr      SetOrthographic( double dfCenterLat, double dfCenterLong,
                                  double dfFalseEasting,double dfFalseNorthing);
@@ -481,15 +481,15 @@ class CPL_DLL OGRSpatialReference
     OGRErr      SetPS( double dfCenterLat, double dfCenterLong,
                        double dfScale,
                        double dfFalseEasting, double dfFalseNorthing);
-    
+
     /** Robinson */
-    OGRErr      SetRobinson( double dfCenterLong, 
+    OGRErr      SetRobinson( double dfCenterLong,
                              double dfFalseEasting, double dfFalseNorthing );
-    
+
     /** Sinusoidal */
-    OGRErr      SetSinusoidal( double dfCenterLong, 
+    OGRErr      SetSinusoidal( double dfCenterLong,
                                double dfFalseEasting, double dfFalseNorthing );
-    
+
     /** Stereographic */
     OGRErr      SetStereographic( double dfCenterLat, double dfCenterLong,
                                   double dfScale,
@@ -498,20 +498,20 @@ class CPL_DLL OGRSpatialReference
     /** Swiss Oblique Cylindrical */
     OGRErr      SetSOC( double dfLatitudeOfOrigin, double dfCentralMeridian,
                         double dfFalseEasting, double dfFalseNorthing );
-    
+
     /** Transverse Mercator */
     OGRErr      SetTM( double dfCenterLat, double dfCenterLong,
                        double dfScale,
                        double dfFalseEasting, double dfFalseNorthing );
 
     /** Transverse Mercator variants. */
-    OGRErr      SetTMVariant( const char *pszVariantName, 
+    OGRErr      SetTMVariant( const char *pszVariantName,
                               double dfCenterLat, double dfCenterLong,
                               double dfScale,
                               double dfFalseEasting, double dfFalseNorthing );
 
     /** Tunesia Mining Grid  */
-    OGRErr      SetTMG( double dfCenterLat, double dfCenterLong, 
+    OGRErr      SetTMG( double dfCenterLat, double dfCenterLong,
                         double dfFalseEasting, double dfFalseNorthing );
 
     /** Transverse Mercator (South Oriented) */
@@ -520,10 +520,10 @@ class CPL_DLL OGRSpatialReference
                          double dfFalseEasting, double dfFalseNorthing );
 
     /** Two Point Equidistant */
-    OGRErr      SetTPED( double dfLat1, double dfLong1, 
-                         double dfLat2, double dfLong2, 
+    OGRErr      SetTPED( double dfLat1, double dfLong1,
+                         double dfLat2, double dfLong2,
                          double dfFalseEasting, double dfFalseNorthing );
-    
+
     /** VanDerGrinten */
     OGRErr      SetVDG( double dfCenterLong,
                         double dfFalseEasting, double dfFalseNorthing );
@@ -539,17 +539,20 @@ class CPL_DLL OGRSpatialReference
     /** Quadrilateralized Spherical Cube */
     OGRErr      SetQSC(double dfCenterLat, double dfCenterLong);
 
+    /** Spherical, Cross-track, Height */
+    OGRErr      SetSCH( double dfPegLat, double dfPegLong,
+                        double dfPegHeading, double dfPegHgt);
     /** State Plane */
     OGRErr      SetStatePlane( int nZone, int bNAD83 = TRUE,
                                const char *pszOverrideUnitName = NULL,
                                double dfOverrideUnit = 0.0 );
 
-    OGRErr      ImportFromESRIStatePlaneWKT( 
-        int nCode, const char* pszDatumName, const char* pszUnitsName, 
-        int nPCSCode, const char* pszCSName = 0 );
-    OGRErr      ImportFromESRIWisconsinWKT( 
-        const char* pszPrjName, double dfCentralMeridian, double dfLatOfOrigin, 
-        const char* pszUnitsName, const char* pszCSName = 0 );
+    OGRErr      ImportFromESRIStatePlaneWKT(
+        int nCode, const char* pszDatumName, const char* pszUnitsName,
+        int nPCSCode, const char* pszCSName = NULL );
+    OGRErr      ImportFromESRIWisconsinWKT(
+        const char* pszPrjName, double dfCentralMeridian, double dfLatOfOrigin,
+        const char* pszUnitsName, const char* pszCSName = NULL );
 
     static OGRSpatialReference* GetWGS84SRS();
 };
@@ -569,12 +572,12 @@ class CPL_DLL OGRSpatialReference
  *
  * Also, see OGRCreateCoordinateTransformation() for creating transformations.
  */
- 
+
 class CPL_DLL OGRCoordinateTransformation
 {
 public:
     virtual ~OGRCoordinateTransformation() {}
-    
+
     static void DestroyCT(OGRCoordinateTransformation* poCT);
 
     // From CT_CoordinateTransformation
@@ -592,8 +595,8 @@ public:
      *
      * This method is the same as the C function OCTTransform().
      *
-     * The method TransformEx() allows extended success information to 
-     * be captured indicating which points failed to transform. 
+     * The method TransformEx() allows extended success information to
+     * be captured indicating which points failed to transform.
      *
      * @param nCount number of points to transform.
      * @param x array of nCount X vertices, modified in place.
@@ -602,7 +605,7 @@ public:
      * @return TRUE on success, or FALSE if some or all points fail to
      * transform.
      */
-    virtual int Transform( int nCount, 
+    virtual int Transform( int nCount,
                            double *x, double *y, double *z = NULL ) = 0;
 
     /**
@@ -614,20 +617,20 @@ public:
      * @param x array of nCount X vertices, modified in place.
      * @param y array of nCount Y vertices, modified in place.
      * @param z array of nCount Z vertices, modified in place.
-     * @param pabSuccess array of per-point flags set to TRUE if that point 
+     * @param pabSuccess array of per-point flags set to TRUE if that point
      * transforms, or FALSE if it does not.
      *
-     * @return TRUE if some or all points transform successfully, or FALSE if 
+     * @return TRUE if some or all points transform successfully, or FALSE if
      * if none transform.
      */
-    virtual int TransformEx( int nCount, 
+    virtual int TransformEx( int nCount,
                              double *x, double *y, double *z = NULL,
                              int *pabSuccess = NULL ) = 0;
 
 };
 
 OGRCoordinateTransformation CPL_DLL *
-OGRCreateCoordinateTransformation( OGRSpatialReference *poSource, 
+OGRCreateCoordinateTransformation( OGRSpatialReference *poSource,
                                    OGRSpatialReference *poTarget );
 
-#endif /* ndef _OGR_SPATIALREF_H_INCLUDED */
+#endif /* ndef OGR_SPATIALREF_H_INCLUDED */
diff --git a/ogr/ogr_sql.dox b/ogr/ogr_sql.dox
index 3b640bc..6840078 100644
--- a/ogr/ogr_sql.dox
+++ b/ogr/ogr_sql.dox
@@ -77,7 +77,7 @@ keyword may be used against any type of field.  Currently the distinctness
 test against a string value is case insensitive in OGR SQL.  The result of
 a SELECT with a DISTINCT keyword is a layer with one column (named the same
 as the field operated on), and one feature per distinct value.  Geometries
-are discarded.  The distinct values are assembled in memory, so alot of 
+are discarded.  The distinct values are assembled in memory, so a lot of 
 memory may be used for datasets with a large number of distinct values.
 
 \code
@@ -89,7 +89,7 @@ When a summarization operator is applied to any field, then all fields must
 have summarization operators applied.   The summarization operators are
 COUNT (a count of instances), AVG (numerical average), SUM (numerical sum), 
 MIN (lexical or numerical minimum), and MAX (lexical or numerical maximum). 
-This example produces a variety of sumarization information on parcel
+This example produces a variety of summarization information on parcel
 property values:
 
 \code
@@ -232,7 +232,7 @@ WHERE a_field = 'a_value'
 
 Identifiers (column names and tables names) can be used unquoted if they don't
 contain special characters or are not a SQL reserved keyword. Otherwise they must
-be surroundered with double-quote characters. e.g. WHERE "from" = 5
+be surrounded with double-quote characters. e.g. WHERE "from" = 5.
 
 \subsection ogr_sql_where WHERE
 
@@ -258,7 +258,7 @@ The available logical operators are
 <b>ILIKE</b>,
 <b>BETWEEN</b> and
 <b>IN</b>. 
-Most of the operators are self explanitory, but is is worth nothing that <b>
+Most of the operators are self explanatory, but it is worth noting that <b>
 !=</b> is the same as <b><></b>, the string equality is
 case insensitive, but the <b><</b>, <b>></b>, <b><=</b> and <b>>=</b> operators <i>are</i> case sensitive.  Both the LIKE and ILIKE operators are case insensitive.
 
@@ -433,7 +433,7 @@ Before GDAL 2.0, the expression after ON should necessarily be of the form
 "{primary_table}.{field_name} = {secondary_table}.{field_name}", and in that
 order.
 Starting with GDAL 2.0, it is possible to use a more complex boolean expression,
-involving multiple comparison operators, but with the restrictions mentionned
+involving multiple comparison operators, but with the restrictions mentioned
 in the below "JOIN limitations" section. In particular, in case of multiple joins (3 tables
 or more) the fields compared in a JOIN must belong to the primary table (the one
 after FROM) and the table of the active JOIN.
diff --git a/ogr/ogr_sql_sqlite.dox b/ogr/ogr_sql_sqlite.dox
index 7ba0292..4bf6e26 100644
--- a/ogr/ogr_sql_sqlite.dox
+++ b/ogr/ogr_sql_sqlite.dox
@@ -129,7 +129,7 @@ OGRFeature(SELECT):2
 
 The <b>ogr_datasource_load_layers(datasource_name[, update_mode[, prefix]])</b>
 function can be used to automatically load all the layers of a datasource as
-<a href="http://gdal.org/ogr/drv_sqlite.html">VirtualOGR tables</a>.<p>
+<a href="http://gdal.org/drv_sqlite.html">VirtualOGR tables</a>.<p>
 
 \code
 sqlite> SELECT load_extension('libgdal.so');
diff --git a/ogr/ogr_srs_api.h b/ogr/ogr_srs_api.h
index 4d66a47..ca961ec 100644
--- a/ogr/ogr_srs_api.h
+++ b/ogr/ogr_srs_api.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_srs_api.h 31181 2015-10-28 15:02:25Z rouault $
+ * $Id: ogr_srs_api.h 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  C API and constant declarations for OGR Spatial References.
@@ -28,8 +28,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_SRS_API_H_INCLUDED
-#define _OGR_SRS_API_H_INCLUDED
+#ifndef OGR_SRS_API_H_INCLUDED
+#define OGR_SRS_API_H_INCLUDED
 
 #ifndef SWIG
 #include "ogr_core.h"
@@ -38,9 +38,9 @@ CPL_C_START
 
 /**
  * \file ogr_srs_api.h
- * 
+ *
  * C spatial reference system services and defines.
- * 
+ *
  * See also: ogr_spatialref.h
  */
 
@@ -56,7 +56,7 @@ typedef enum {
     OAO_Up=5,
     OAO_Down=6
 } OGRAxisOrientation;
-    
+
 const char CPL_DLL *OSRAxisEnumToName( OGRAxisOrientation eOrientation );
 
 /* -------------------------------------------------------------------- */
@@ -80,7 +80,7 @@ typedef enum {
     ODT_VD_Max=2999,
     ODT_LD_Min=10000,
     ODT_LD_Max=32767
-} OGRDatumType; 
+} OGRDatumType;
 
 #endif // ndef SWIG
 
@@ -88,7 +88,7 @@ typedef enum {
 /*      Some standard WKT geographic coordinate systems.                */
 /* ==================================================================== */
 
-#define SRS_WKT_WGS84 "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9108\"]],AUTHORITY[\"EPSG\",\"4326\"]]"
+#define SRS_WKT_WGS84 "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]]"
 
 /* ==================================================================== */
 /*      Some "standard" strings.                                        */
@@ -186,13 +186,14 @@ typedef enum {
 #define SRS_PT_WAGNER_VI        "Wagner_VI"
 #define SRS_PT_WAGNER_VII       "Wagner_VII"
 #define SRS_PT_QSC              "Quadrilateralized_Spherical_Cube"
-#define SRS_PT_AITOFF           "Aitoff" 
-#define SRS_PT_WINKEL_I         "Winkel_I" 
-#define SRS_PT_WINKEL_II        "Winkel_II" 
-#define SRS_PT_WINKEL_TRIPEL    "Winkel_Tripel" 
-#define SRS_PT_CRASTER_PARABOLIC    "Craster_Parabolic" 
+#define SRS_PT_AITOFF           "Aitoff"
+#define SRS_PT_WINKEL_I         "Winkel_I"
+#define SRS_PT_WINKEL_II        "Winkel_II"
+#define SRS_PT_WINKEL_TRIPEL    "Winkel_Tripel"
+#define SRS_PT_CRASTER_PARABOLIC    "Craster_Parabolic"
 #define SRS_PT_LOXIMUTHAL        "Loximuthal"
 #define SRS_PT_QUARTIC_AUTHALIC  "Quartic_Authalic"
+#define SRS_PT_SCH              "Spherical_Cross_Track_Height"
 
 #define SRS_PP_CENTRAL_MERIDIAN         "central_meridian"
 #define SRS_PP_SCALE_FACTOR             "scale_factor"
@@ -223,6 +224,10 @@ typedef enum {
 #define SRS_PP_LONGITUDE_OF_1ST_POINT   "Longitude_Of_1st_Point"
 #define SRS_PP_LATITUDE_OF_2ND_POINT    "Latitude_Of_2nd_Point"
 #define SRS_PP_LONGITUDE_OF_2ND_POINT   "Longitude_Of_2nd_Point"
+#define SRS_PP_PEG_POINT_LATITUDE       "peg_point_latitude"
+#define SRS_PP_PEG_POINT_LONGITUDE      "peg_point_longitude"
+#define SRS_PP_PEG_POINT_HEADING        "peg_point_heading"
+#define SRS_PP_PEG_POINT_HEIGHT         "peg_point_height"
 
 #define SRS_UL_METER            "Meter"
 #define SRS_UL_FOOT             "Foot (International)" /* or just "FOOT"? */
@@ -237,7 +242,7 @@ typedef enum {
 #define SRS_UL_CHAIN_CONV                   "20.116684023368047"
 #define SRS_UL_ROD              "Rod"           /* based on US Foot */
 #define SRS_UL_ROD_CONV                     "5.02921005842012"
-#define SRS_UL_LINK_Clarke      "Link_Clarke"          
+#define SRS_UL_LINK_Clarke      "Link_Clarke"
 #define SRS_UL_LINK_Clarke_CONV              "0.2011661949"
 
 #define SRS_UL_KILOMETER        "Kilometer"
@@ -290,21 +295,21 @@ typedef enum {
 #define SRS_DN_WGS72            "WGS_1972"
 #define SRS_DN_WGS84            "WGS_1984"
 
-#define SRS_WGS84_SEMIMAJOR     6378137.0                                
+#define SRS_WGS84_SEMIMAJOR     6378137.0
 #define SRS_WGS84_INVFLATTENING 298.257223563
 
 #ifndef SWIG
 /* -------------------------------------------------------------------- */
 /*      C Wrappers for C++ objects and methods.                         */
 /* -------------------------------------------------------------------- */
-#ifndef _DEFINED_OGRSpatialReferenceH
-#define _DEFINED_OGRSpatialReferenceH
+#ifndef DEFINED_OGRSpatialReferenceH
+#define DEFINED_OGRSpatialReferenceH
 
 #ifdef DEBUG
 typedef struct OGRSpatialReferenceHS *OGRSpatialReferenceH;
 typedef struct OGRCoordinateTransformationHS *OGRCoordinateTransformationH;
 #else
-typedef void *OGRSpatialReferenceH;                               
+typedef void *OGRSpatialReferenceH;
 typedef void *OGRCoordinateTransformationH;
 #endif
 
@@ -336,7 +341,7 @@ OGRErr CPL_DLL OSRImportFromPCI( OGRSpatialReferenceH hSRS, const char *,
 OGRErr CPL_DLL OSRImportFromUSGS( OGRSpatialReferenceH,
                                   long, long, double *, long);
 OGRErr CPL_DLL OSRImportFromXML( OGRSpatialReferenceH, const char * );
-OGRErr CPL_DLL OSRImportFromDict( OGRSpatialReferenceH, const char *, 
+OGRErr CPL_DLL OSRImportFromDict( OGRSpatialReferenceH, const char *,
                                   const char * );
 OGRErr CPL_DLL OSRImportFromPanorama( OGRSpatialReferenceH, long, long, long,
                                       double * );
@@ -372,7 +377,7 @@ OGRErr CPL_DLL OSRSetAngularUnits( OGRSpatialReferenceH, const char *, double );
 double CPL_DLL OSRGetAngularUnits( OGRSpatialReferenceH, char ** );
 OGRErr CPL_DLL OSRSetLinearUnits( OGRSpatialReferenceH, const char *, double );
 OGRErr CPL_DLL OSRSetTargetLinearUnits( OGRSpatialReferenceH, const char *, const char *, double );
-OGRErr CPL_DLL OSRSetLinearUnitsAndUpdateParameters( 
+OGRErr CPL_DLL OSRSetLinearUnitsAndUpdateParameters(
     OGRSpatialReferenceH, const char *, double );
 double CPL_DLL OSRGetLinearUnits( OGRSpatialReferenceH, char ** );
 double CPL_DLL OSRGetTargetLinearUnits( OGRSpatialReferenceH, const char *, char ** );
@@ -394,15 +399,14 @@ OGRErr CPL_DLL OSRSetProjCS( OGRSpatialReferenceH hSRS, const char * pszName );
 OGRErr CPL_DLL OSRSetGeocCS( OGRSpatialReferenceH hSRS, const char * pszName );
 OGRErr CPL_DLL OSRSetWellKnownGeogCS( OGRSpatialReferenceH hSRS,
                                       const char * pszName );
-OGRErr CPL_DLL CPL_STDCALL OSRSetFromUserInput( OGRSpatialReferenceH hSRS, 
+OGRErr CPL_DLL CPL_STDCALL OSRSetFromUserInput( OGRSpatialReferenceH hSRS,
                                     const char * );
-OGRErr CPL_DLL OSRCopyGeogCSFrom( OGRSpatialReferenceH hSRS, 
-                                  OGRSpatialReferenceH hSrcSRS );
-OGRErr CPL_DLL OSRSetTOWGS84( OGRSpatialReferenceH hSRS, 
-                              double, double, double, 
+OGRErr CPL_DLL OSRCopyGeogCSFrom( OGRSpatialReferenceH hSRS,
+                                  const OGRSpatialReferenceH hSrcSRS );
+OGRErr CPL_DLL OSRSetTOWGS84( OGRSpatialReferenceH hSRS,
+                              double, double, double,
                               double, double, double, double );
 OGRErr CPL_DLL OSRGetTOWGS84( OGRSpatialReferenceH hSRS, double *, int );
-                        
 
 OGRErr CPL_DLL OSRSetCompoundCS( OGRSpatialReferenceH hSRS,
                                  const char *pszName,
@@ -438,20 +442,20 @@ const char CPL_DLL *OSRGetAuthorityName( OGRSpatialReferenceH hSRS,
 OGRErr CPL_DLL OSRSetProjection( OGRSpatialReferenceH, const char * );
 OGRErr CPL_DLL OSRSetProjParm( OGRSpatialReferenceH, const char *, double );
 double CPL_DLL OSRGetProjParm( OGRSpatialReferenceH hSRS,
-                        const char * pszParmName, 
+                        const char * pszParmName,
                         double dfDefault /* = 0.0 */,
                         OGRErr * /* = NULL */ );
 OGRErr CPL_DLL OSRSetNormProjParm( OGRSpatialReferenceH, const char *, double);
 double CPL_DLL OSRGetNormProjParm( OGRSpatialReferenceH hSRS,
-                                   const char * pszParmName, 
+                                   const char * pszParmName,
                                    double dfDefault /* = 0.0 */,
                                    OGRErr * /* = NULL */ );
 
 OGRErr CPL_DLL OSRSetUTM( OGRSpatialReferenceH hSRS, int nZone, int bNorth );
 int    CPL_DLL OSRGetUTMZone( OGRSpatialReferenceH hSRS, int *pbNorth );
-OGRErr CPL_DLL OSRSetStatePlane( OGRSpatialReferenceH hSRS, 
+OGRErr CPL_DLL OSRSetStatePlane( OGRSpatialReferenceH hSRS,
                                  int nZone, int bNAD83 );
-OGRErr CPL_DLL OSRSetStatePlaneWithUnits( OGRSpatialReferenceH hSRS, 
+OGRErr CPL_DLL OSRSetStatePlaneWithUnits( OGRSpatialReferenceH hSRS,
                                           int nZone, int bNAD83,
                                           const char *pszOverrideUnitName,
                                           double dfOverrideUnit );
@@ -460,25 +464,25 @@ OGRErr CPL_DLL OSRAutoIdentifyEPSG( OGRSpatialReferenceH hSRS );
 int    CPL_DLL OSREPSGTreatsAsLatLong( OGRSpatialReferenceH hSRS );
 int    CPL_DLL OSREPSGTreatsAsNorthingEasting( OGRSpatialReferenceH hSRS );
 const char CPL_DLL *OSRGetAxis( OGRSpatialReferenceH hSRS,
-                                const char *pszTargetKey, int iAxis, 
+                                const char *pszTargetKey, int iAxis,
                                 OGRAxisOrientation *peOrientation );
-OGRErr CPL_DLL OSRSetAxes( OGRSpatialReferenceH hSRS, 
+OGRErr CPL_DLL OSRSetAxes( OGRSpatialReferenceH hSRS,
                            const char *pszTargetKey,
                            const char *pszXAxisName,
                            OGRAxisOrientation eXAxisOrientation,
-                           const char *pszYAxisName, 
+                           const char *pszYAxisName,
                            OGRAxisOrientation eYAxisOrientation );
 /** Albers Conic Equal Area */
 OGRErr CPL_DLL OSRSetACEA( OGRSpatialReferenceH hSRS, double dfStdP1, double dfStdP2,
                          double dfCenterLat, double dfCenterLong,
                          double dfFalseEasting, double dfFalseNorthing );
-    
+
 /** Azimuthal Equidistant */
 OGRErr CPL_DLL  OSRSetAE( OGRSpatialReferenceH hSRS, double dfCenterLat, double dfCenterLong,
                        double dfFalseEasting, double dfFalseNorthing );
 
 /** Bonne */
-OGRErr CPL_DLL OSRSetBonne(OGRSpatialReferenceH hSRS, 
+OGRErr CPL_DLL OSRSetBonne(OGRSpatialReferenceH hSRS,
                            double dfStandardParallel, double dfCentralMeridian,
                            double dfFalseEasting, double dfFalseNorthing );
 
@@ -523,20 +527,20 @@ OGRErr CPL_DLL OSRSetEquirectangular2( OGRSpatialReferenceH hSRS,
 /** Gall Stereograpic */
 OGRErr CPL_DLL OSRSetGS( OGRSpatialReferenceH hSRS, double dfCentralMeridian,
                        double dfFalseEasting, double dfFalseNorthing );
-    
+
 /** Goode Homolosine */
 OGRErr CPL_DLL OSRSetGH( OGRSpatialReferenceH hSRS, double dfCentralMeridian,
                          double dfFalseEasting, double dfFalseNorthing );
 
 /** Interrupted Goode Homolosine */
 OGRErr CPL_DLL OSRSetIGH( OGRSpatialReferenceH hSRS );
-    
+
 /** GEOS - Geostationary Satellite View */
-OGRErr CPL_DLL OSRSetGEOS( OGRSpatialReferenceH hSRS, 
+OGRErr CPL_DLL OSRSetGEOS( OGRSpatialReferenceH hSRS,
                            double dfCentralMeridian, double dfSatelliteHeight,
                            double dfFalseEasting, double dfFalseNorthing );
 
-/** Gauss Schreiber Transverse Mercator */    
+/** Gauss Schreiber Transverse Mercator */
 OGRErr CPL_DLL OSRSetGaussSchreiberTMercator( OGRSpatialReferenceH hSRS,
                                   double dfCenterLat, double dfCenterLong,
                                   double dfScale,
@@ -561,9 +565,9 @@ OGRErr CPL_DLL OSRSetHOM( OGRSpatialReferenceH hSRS,
                           double dfScale,
                           double dfFalseEasting, double dfFalseNorthing );
 
-OGRErr CPL_DLL OSRSetHOMAC( OGRSpatialReferenceH hSRS, 
+OGRErr CPL_DLL OSRSetHOMAC( OGRSpatialReferenceH hSRS,
                     double dfCenterLat, double dfCenterLong,
-                    double dfAzimuth, double dfRectToSkew, 
+                    double dfAzimuth, double dfRectToSkew,
                     double dfScale,
                     double dfFalseEasting,
                     double dfFalseNorthing );
@@ -586,7 +590,7 @@ OGRErr CPL_DLL OSRSetIWMPolyconic( OGRSpatialReferenceH hSRS,
 OGRErr CPL_DLL OSRSetKrovak( OGRSpatialReferenceH hSRS,
                              double dfCenterLat, double dfCenterLong,
                              double dfAzimuth, double dfPseudoStdParallelLat,
-                             double dfScale, 
+                             double dfScale,
                              double dfFalseEasting, double dfFalseNorthing );
 
 /** Lambert Azimuthal Equal-Area */
@@ -611,7 +615,7 @@ OGRErr CPL_DLL OSRSetLCCB( OGRSpatialReferenceH hSRS,
                            double dfStdP1, double dfStdP2,
                            double dfCenterLat, double dfCenterLong,
                            double dfFalseEasting, double dfFalseNorthing );
-    
+
 /** Miller Cylindrical */
 OGRErr CPL_DLL OSRSetMC( OGRSpatialReferenceH hSRS,
                          double dfCenterLat, double dfCenterLong,
@@ -620,9 +624,9 @@ OGRErr CPL_DLL OSRSetMC( OGRSpatialReferenceH hSRS,
 /** Mercator */
 OGRErr CPL_DLL OSRSetMercator( OGRSpatialReferenceH hSRS,
                                double dfCenterLat, double dfCenterLong,
-                               double dfScale, 
+                               double dfScale,
                                double dfFalseEasting, double dfFalseNorthing );
-OGRErr CPL_DLL OSRSetMercator2SP( OGRSpatialReferenceH hSRS, 
+OGRErr CPL_DLL OSRSetMercator2SP( OGRSpatialReferenceH hSRS,
                           double dfStdP1,
                           double dfCenterLat, double dfCenterLong,
                           double dfFalseEasting, double dfFalseNorthing );
@@ -643,7 +647,7 @@ OGRErr CPL_DLL OSRSetOS( OGRSpatialReferenceH hSRS,
                          double dfOriginLat, double dfCMeridian,
                          double dfScale,
                          double dfFalseEasting,double dfFalseNorthing);
-    
+
 /** Orthographic */
 OGRErr CPL_DLL OSRSetOrthographic( OGRSpatialReferenceH hSRS,
                                    double dfCenterLat, double dfCenterLong,
@@ -660,30 +664,30 @@ OGRErr CPL_DLL OSRSetPS( OGRSpatialReferenceH hSRS,
                          double dfCenterLat, double dfCenterLong,
                          double dfScale,
                          double dfFalseEasting, double dfFalseNorthing);
-    
+
 /** Robinson */
 OGRErr CPL_DLL OSRSetRobinson( OGRSpatialReferenceH hSRS,
-                               double dfCenterLong, 
+                               double dfCenterLong,
                                double dfFalseEasting, double dfFalseNorthing );
-    
+
 /** Sinusoidal */
 OGRErr CPL_DLL OSRSetSinusoidal( OGRSpatialReferenceH hSRS,
-                                 double dfCenterLong, 
+                                 double dfCenterLong,
                                  double dfFalseEasting,
                                  double dfFalseNorthing );
-    
+
 /** Stereographic */
 OGRErr CPL_DLL OSRSetStereographic( OGRSpatialReferenceH hSRS,
                                     double dfCenterLat, double dfCenterLong,
                                     double dfScale,
                                     double dfFalseEasting,
                                     double dfFalseNorthing);
-    
+
 /** Swiss Oblique Cylindrical */
 OGRErr CPL_DLL OSRSetSOC( OGRSpatialReferenceH hSRS,
                           double dfLatitudeOfOrigin, double dfCentralMeridian,
                           double dfFalseEasting, double dfFalseNorthing );
-    
+
 /** Transverse Mercator
  *
  * Special processing available for Transverse Mercator with GDAL >= 1.10 and PROJ >= 4.8 :
@@ -696,7 +700,7 @@ OGRErr CPL_DLL OSRSetTM( OGRSpatialReferenceH hSRS,
                          double dfFalseEasting, double dfFalseNorthing );
 
 /** Transverse Mercator variant */
-OGRErr CPL_DLL OSRSetTMVariant( 
+OGRErr CPL_DLL OSRSetTMVariant(
     OGRSpatialReferenceH hSRS, const char *pszVariantName,
     double dfCenterLat, double dfCenterLong,
     double dfScale,
@@ -704,7 +708,7 @@ OGRErr CPL_DLL OSRSetTMVariant(
 
 /** Tunesia Mining Grid  */
 OGRErr CPL_DLL OSRSetTMG( OGRSpatialReferenceH hSRS,
-                          double dfCenterLat, double dfCenterLong, 
+                          double dfCenterLat, double dfCenterLong,
                          double dfFalseEasting, double dfFalseNorthing );
 
 /** Transverse Mercator (South Oriented) */
@@ -733,6 +737,12 @@ OGRErr CPL_DLL OSRSetWagner( OGRSpatialReferenceH hSRS, int nVariation,
 OGRErr CPL_DLL OSRSetQSC( OGRSpatialReferenceH hSRS,
                               double dfCenterLat, double dfCenterLong );
 
+/** Spherical, Cross-track, Height */
+OGRErr CPL_DLL OSRSetSCH( OGRSpatialReferenceH hSRS,
+                              double dfPegLat, double dfPegLong,
+                              double dfPegHeading, double dfPegHgt);
+
+
 double CPL_DLL OSRCalcInvFlattening( double dfSemiMajor, double dfSemiMinor );
 double CPL_DLL OSRCalcSemiMinorFromInvFlattening( double dfSemiMajor, double dfInvFlattening );
 
@@ -744,7 +754,7 @@ void CPL_DLL OSRCleanup( void );
 OGRCoordinateTransformationH CPL_DLL CPL_STDCALL
 OCTNewCoordinateTransformation( OGRSpatialReferenceH hSourceSRS,
                                 OGRSpatialReferenceH hTargetSRS );
-void CPL_DLL CPL_STDCALL 
+void CPL_DLL CPL_STDCALL
       OCTDestroyCoordinateTransformation( OGRCoordinateTransformationH );
 
 int CPL_DLL CPL_STDCALL
@@ -778,4 +788,4 @@ CPL_C_END
 
 #endif /* ndef SWIG */
 
-#endif /* ndef _OGR_SRS_API_H_INCLUDED */
+#endif /* ndef OGR_SRS_API_H_INCLUDED */
diff --git a/ogr/ogr_srs_dict.cpp b/ogr/ogr_srs_dict.cpp
index f928ad4..f0969c1 100644
--- a/ogr/ogr_srs_dict.cpp
+++ b/ogr/ogr_srs_dict.cpp
@@ -1,9 +1,9 @@
 /******************************************************************************
- * $Id: ogr_srs_dict.cpp 11881 2007-08-13 18:03:48Z mloskot $
+ * $Id: ogr_srs_dict.cpp 33632 2016-03-04 06:51:02Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
- * Purpose:  Implement importFromDict() method to read a WKT SRS from a 
- *           coordinate system dictionary in a simple text format. 
+ * Purpose:  Implement importFromDict() method to read a WKT SRS from a
+ *           coordinate system dictionary in a simple text format.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -28,11 +28,11 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_spatialref.h"
 #include "cpl_conv.h"
+#include "cpl_vsi.h"
+#include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: ogr_srs_dict.cpp 11881 2007-08-13 18:03:48Z mloskot $");
-
+CPL_CVSID("$Id: ogr_srs_dict.cpp 33632 2016-03-04 06:51:02Z goatbar $");
 
 /************************************************************************/
 /*                           importFromDict()                           */
@@ -41,18 +41,18 @@ CPL_CVSID("$Id: ogr_srs_dict.cpp 11881 2007-08-13 18:03:48Z mloskot $");
 /**
  * Read SRS from WKT dictionary.
  *
- * This method will attempt to find the indicated coordinate system identity 
+ * This method will attempt to find the indicated coordinate system identity
  * in the indicated dictionary file.  If found, the WKT representation is
- * imported and used to initialize this OGRSpatialReference.  
+ * imported and used to initialize this OGRSpatialReference.
  *
  * More complete information on the format of the dictionary files can
  * be found in the epsg.wkt file in the GDAL data tree.  The dictionary
  * files are searched for in the "GDAL" domain using CPLFindFile().  Normally
- * this results in searching /usr/local/share/gdal or somewhere similar. 
+ * this results in searching /usr/local/share/gdal or somewhere similar.
  *
  * This method is the same as the C function OSRImportFromDict().
  *
- * @param pszDictFile the name of the dictionary file to load.  
+ * @param pszDictFile the name of the dictionary file to load.
  *
  * @param pszCode the code to lookup in the dictionary.
  *
@@ -60,50 +60,48 @@ CPL_CVSID("$Id: ogr_srs_dict.cpp 11881 2007-08-13 18:03:48Z mloskot $");
  * found, and OGRERR_SRS_FAILURE if something more dramatic goes wrong.
  */
 
-OGRErr OGRSpatialReference::importFromDict( const char *pszDictFile, 
+OGRErr OGRSpatialReference::importFromDict( const char *pszDictFile,
                                             const char *pszCode )
 
 {
-    const char *pszFilename;
-    FILE *fp;
-    OGRErr eErr = OGRERR_UNSUPPORTED_SRS;
-
 /* -------------------------------------------------------------------- */
 /*      Find and open file.                                             */
 /* -------------------------------------------------------------------- */
-    pszFilename = CPLFindFile( "gdal", pszDictFile );
+    const char *pszFilename = CPLFindFile( "gdal", pszDictFile );
     if( pszFilename == NULL )
         return OGRERR_UNSUPPORTED_SRS;
 
-    fp = VSIFOpen( pszFilename, "rb" );
+    VSILFILE *fp = VSIFOpenL( pszFilename, "rb" );
     if( fp == NULL )
         return OGRERR_UNSUPPORTED_SRS;
 
 /* -------------------------------------------------------------------- */
 /*      Process lines.                                                  */
 /* -------------------------------------------------------------------- */
-    const char *pszLine;
+    OGRErr eErr = OGRERR_UNSUPPORTED_SRS;
+    const char *pszLine = NULL;
 
-    while( (pszLine = CPLReadLine(fp)) != NULL )
+    while( (pszLine = CPLReadLineL(fp)) != NULL )
 
     {
         if( pszLine[0] == '#' )
-            /* do nothing */;
+            continue;
 
-        else if( EQUALN(pszLine,"include ",8) )
+        if( STARTS_WITH_CI(pszLine, "include ") )
         {
             eErr = importFromDict( pszLine + 8, pszCode );
             if( eErr != OGRERR_UNSUPPORTED_SRS )
                 break;
+            continue;
         }
 
-        else if( strstr(pszLine,",") == NULL )
-            /* do nothing */;
+        if( strstr(pszLine,",") == NULL )
+            continue;
 
-        else if( EQUALN(pszLine,pszCode,strlen(pszCode))
-                 && pszLine[strlen(pszCode)] == ',' )
+        if( EQUALN(pszLine,pszCode,strlen(pszCode))
+            && pszLine[strlen(pszCode)] == ',' )
         {
-            char *pszWKT = (char *) pszLine + strlen(pszCode)+1;
+            char *pszWKT = const_cast<char *>(pszLine) + strlen(pszCode)+1;
 
             eErr = importFromWkt( &pszWKT );
             break;
@@ -113,8 +111,8 @@ OGRErr OGRSpatialReference::importFromDict( const char *pszDictFile,
 /* -------------------------------------------------------------------- */
 /*      Cleanup                                                         */
 /* -------------------------------------------------------------------- */
-    VSIFClose( fp );
-    
+    VSIFCloseL( fp );
+
     return eErr;
 }
 
@@ -122,13 +120,13 @@ OGRErr OGRSpatialReference::importFromDict( const char *pszDictFile,
 /*                         OSRImportFromDict()                          */
 /************************************************************************/
 
-OGRErr OSRImportFromDict( OGRSpatialReferenceH hSRS, 
-                          const char *pszDictFile, 
+OGRErr OSRImportFromDict( OGRSpatialReferenceH hSRS,
+                          const char *pszDictFile,
                           const char *pszCode )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRImportFromDict", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRImportFromDict", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->importFromDict( pszDictFile,
-                                                           pszCode );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
+        importFromDict( pszDictFile, pszCode );
 }
diff --git a/ogr/ogr_srs_erm.cpp b/ogr/ogr_srs_erm.cpp
index 62a6e8e..435a67f 100644
--- a/ogr/ogr_srs_erm.cpp
+++ b/ogr/ogr_srs_erm.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_srs_erm.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: ogr_srs_erm.cpp 33553 2016-02-25 14:05:00Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implement ERMapper projection conversions.
@@ -31,7 +31,7 @@
 #include "ogr_spatialref.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogr_srs_erm.cpp 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: ogr_srs_erm.cpp 33553 2016-02-25 14:05:00Z goatbar $");
 
 /************************************************************************/
 /*                         OSRImportFromERM()                           */
@@ -47,7 +47,7 @@ OGRErr OSRImportFromERM( OGRSpatialReferenceH hSRS, const char *pszProj,
                          const char *pszDatum, const char *pszUnits )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRImportFromERM", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRImportFromERM", OGRERR_FAILURE );
 
     return ((OGRSpatialReference *) hSRS)->importFromERM( pszProj,
                                                           pszDatum,
@@ -62,9 +62,9 @@ OGRErr OSRImportFromERM( OGRSpatialReferenceH hSRS, const char *pszProj,
  * Create OGR WKT from ERMapper projection definitions.
  *
  * Generates an OGRSpatialReference definition from an ERMapper datum
- * and projection name.  Based on the ecw_cs.wkt dictionary file from 
- * gdal/data. 
- * 
+ * and projection name.  Based on the ecw_cs.wkt dictionary file from
+ * gdal/data.
+ *
  * @param pszProj the projection name, such as "NUTM11" or "GEOGRAPHIC".
  * @param pszDatum the datum name, such as "NAD83".
  * @param pszUnits the linear units "FEET" or "METERS".
@@ -72,7 +72,7 @@ OGRErr OSRImportFromERM( OGRSpatialReferenceH hSRS, const char *pszProj,
  * @return OGRERR_NONE on success or OGRERR_UNSUPPORTED_SRS if not found.
  */
 
-OGRErr OGRSpatialReference::importFromERM( const char *pszProj, 
+OGRErr OGRSpatialReference::importFromERM( const char *pszProj,
                                            const char *pszDatum,
                                            const char *pszUnits )
 
@@ -89,11 +89,11 @@ OGRErr OGRSpatialReference::importFromERM( const char *pszProj,
 /*      Do we have an EPSG coordinate system?                           */
 /* -------------------------------------------------------------------- */
 
-    if( EQUALN(pszProj,"EPSG:",5) )
+    if( STARTS_WITH_CI(pszProj, "EPSG:") )
         return importFromEPSG( atoi(pszProj+5) );
 
 
-    if( EQUALN(pszDatum,"EPSG:",5) )
+    if( STARTS_WITH_CI(pszDatum, "EPSG:") )
         return importFromEPSG( atoi(pszDatum+5) );
 
 /* -------------------------------------------------------------------- */
@@ -137,7 +137,7 @@ OGRErr OGRSpatialReference::importFromERM( const char *pszProj,
 /************************************************************************/
 /*                          OSRExportToERM()                            */
 /************************************************************************/
-/** 
+/**
  * \brief Convert coordinate system to ERMapper format.
  *
  * This function is the same as OGRSpatialReference::exportToERM().
@@ -146,7 +146,7 @@ OGRErr OSRExportToERM( OGRSpatialReferenceH hSRS,
                        char *pszProj, char *pszDatum, char *pszUnits )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRExportToERM", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRExportToERM", OGRERR_FAILURE );
 
     return ((OGRSpatialReference *) hSRS)->exportToERM( pszProj, pszDatum,
                                                         pszUnits );
@@ -160,14 +160,14 @@ OGRErr OSRExportToERM( OGRSpatialReferenceH hSRS,
  * Convert coordinate system to ERMapper format.
  *
  * @param pszProj 32 character buffer to receive projection name.
- * @param pszDatum 32 character buffer to recieve datum name.
+ * @param pszDatum 32 character buffer to receive datum name.
  * @param pszUnits 32 character buffer to receive units name.
  *
  * @return OGRERR_NONE on success, OGRERR_SRS_UNSUPPORTED if not translation is
  * found, or OGRERR_FAILURE on other failures.
  */
 
-OGRErr OGRSpatialReference::exportToERM( char *pszProj, char *pszDatum, 
+OGRErr OGRSpatialReference::exportToERM( char *pszProj, char *pszDatum,
                                          char *pszUnits )
 
 {
@@ -176,7 +176,7 @@ OGRErr OGRSpatialReference::exportToERM( char *pszProj, char *pszDatum,
     strcpy( pszUnits, "METERS" );
 
     if( !IsProjected() && !IsGeographic() )
-        return TRUE;
+        return OGRERR_UNSUPPORTED_SRS;
 
 /* -------------------------------------------------------------------- */
 /*      Try to find the EPSG code.                                      */
@@ -208,7 +208,7 @@ OGRErr OGRSpatialReference::exportToERM( char *pszProj, char *pszDatum,
     OGRSpatialReference oSRSWork;
     const char *pszWKTDatum = GetAttrValue( "DATUM" );
 
-    if( pszWKTDatum != NULL 
+    if( pszWKTDatum != NULL
         && oSRSWork.importFromDict( "ecw_cs.wkt", pszWKTDatum ) == OGRERR_NONE)
     {
         strncpy( pszDatum, pszWKTDatum, 32 );
@@ -227,10 +227,10 @@ OGRErr OGRSpatialReference::exportToERM( char *pszProj, char *pszDatum,
 
         else if( nEPSGGCSCode == 4322 )
             strcpy( pszDatum, "WGS72DOD" );
-        
+
         else if( nEPSGGCSCode == 4267 )
             strcpy( pszDatum, "NAD27" );
-        
+
         else if( nEPSGGCSCode == 4269 )
             strcpy( pszDatum, "NAD83" );
 
@@ -290,14 +290,14 @@ OGRErr OGRSpatialReference::exportToERM( char *pszProj, char *pszDatum,
     {
         if( EQUAL(pszDatum,"GDA94") && !bNorth && nZone >= 48 && nZone <= 58)
         {
-            sprintf( pszProj, "MGA%02d", nZone );
+            snprintf( pszProj, 32, "MGA%02d", nZone );
         }
         else
         {
             if( bNorth )
-                sprintf( pszProj, "NUTM%02d", nZone );
+                snprintf( pszProj, 32, "NUTM%02d", nZone );
             else
-                sprintf( pszProj, "SUTM%02d", nZone );
+                snprintf( pszProj, 32, "SUTM%02d", nZone );
         }
     }
 
@@ -308,8 +308,8 @@ OGRErr OGRSpatialReference::exportToERM( char *pszProj, char *pszDatum,
     {
         const char *pszPROJCS = GetAttrValue( "PROJCS" );
 
-        if( pszPROJCS != NULL 
-            && oSRSWork.importFromDict( "ecw_cs.wkt", pszPROJCS ) == OGRERR_NONE 
+        if( pszPROJCS != NULL
+            && oSRSWork.importFromDict( "ecw_cs.wkt", pszPROJCS ) == OGRERR_NONE
             && oSRSWork.IsProjected() )
         {
             strncpy( pszProj, pszPROJCS, 32 );
@@ -323,8 +323,8 @@ OGRErr OGRSpatialReference::exportToERM( char *pszProj, char *pszDatum,
 /* -------------------------------------------------------------------- */
     if( (EQUAL(pszDatum,"RAW") || EQUAL(pszProj,"RAW")) && nEPSGCode != 0 )
     {
-        sprintf( pszProj, "EPSG:%d", nEPSGCode );
-        sprintf( pszDatum, "EPSG:%d", nEPSGCode );
+        snprintf( pszProj, 32, "EPSG:%d", nEPSGCode );
+        snprintf( pszDatum, 32, "EPSG:%d", nEPSGCode );
     }
 
 /* -------------------------------------------------------------------- */
@@ -336,7 +336,7 @@ OGRErr OGRSpatialReference::exportToERM( char *pszProj, char *pszDatum,
         strcpy( pszUnits, "FEET" );
     else
         strcpy( pszUnits, "METERS" );
-       
+
     if( EQUAL(pszProj,"RAW") )
         return OGRERR_UNSUPPORTED_SRS;
     else
diff --git a/ogr/ogr_srs_esri.cpp b/ogr/ogr_srs_esri.cpp
index 0e8953a..189702f 100644
--- a/ogr/ogr_srs_esri.cpp
+++ b/ogr/ogr_srs_esri.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_srs_esri.cpp 30733 2015-09-28 19:41:53Z rouault $
+ * $Id: ogr_srs_esri.cpp 33534 2016-02-23 16:57:43Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGRSpatialReference translation to/from ESRI .prj definitions.
@@ -29,105 +29,112 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_spatialref.h"
-#include "ogr_p.h"
 #include "cpl_csv.h"
 #include "cpl_multiproc.h"
+#include "cpl_vsi.h"
+#include "ogr_p.h"
+#include "ogr_spatialref.h"
 
 #include "ogr_srs_esri_names.h"
 
-CPL_CVSID("$Id: ogr_srs_esri.cpp 30733 2015-09-28 19:41:53Z rouault $");
+CPL_CVSID("$Id: ogr_srs_esri.cpp 33534 2016-02-23 16:57:43Z goatbar $");
 
 void  SetNewName( OGRSpatialReference* pOgr, const char* keyName, const char* newName );
-int   RemapImgWGSProjcsName(OGRSpatialReference* pOgr, const char* pszProjCSName, 
+int   RemapImgWGSProjcsName(OGRSpatialReference* pOgr, const char* pszProjCSName,
                             const char* pszProgCSName);
-int   RemapImgUTMNames(OGRSpatialReference* pOgr, const char* pszProjCSName, 
+int   RemapImgUTMNames(OGRSpatialReference* pOgr, const char* pszProjCSName,
                        const char* pszProgCSName, char **mappingTable);
-int   RemapNameBasedOnKeyName(OGRSpatialReference* pOgr, const char* pszName, 
+int   RemapNameBasedOnKeyName(OGRSpatialReference* pOgr, const char* pszName,
                              const char* pszkeyName, char **mappingTable);
-int   RemapNamesBasedOnTwo(OGRSpatialReference* pOgr, const char* name1, const char* name2, 
-                             char **mappingTable, long nTableStepSize, 
+int   RemapNamesBasedOnTwo(OGRSpatialReference* pOgr, const char* name1, const char* name2,
+                             char **mappingTable, int nTableStepSize,
                              char** pszkeyNames, long nKeys);
-int   RemapPValuesBasedOnProjCSAndPName(OGRSpatialReference* pOgr, 
+int   RemapPValuesBasedOnProjCSAndPName(OGRSpatialReference* pOgr,
                              const char* pszProgCSName, char **mappingTable);
-int   RemapPNamesBasedOnProjCSAndPName(OGRSpatialReference* pOgr, 
+int   RemapPNamesBasedOnProjCSAndPName(OGRSpatialReference* pOgr,
                              const char* pszProgCSName, char **mappingTable);
-int   DeleteParamBasedOnPrjName( OGRSpatialReference* pOgr, 
+int   DeleteParamBasedOnPrjName( OGRSpatialReference* pOgr,
                              const char* pszProjectionName, char **mappingTable);
-int   AddParamBasedOnPrjName( OGRSpatialReference* pOgr, 
+int   AddParamBasedOnPrjName( OGRSpatialReference* pOgr,
                              const char* pszProjectionName, char **mappingTable);
 int   RemapGeogCSName(OGRSpatialReference* pOgr, const char *pszGeogCSName);
 
+extern void OGREPSGDatumNameMassage( char ** ppszDatum );
+
+CPL_C_START
+void CleanupESRIDatumMappingTable(void);
+CPL_C_END
+
 static int   FindCodeFromDict( const char* pszDictFile, const char* CSName, char* code );
 
-static const char *apszProjMapping[] = {
+static const char * const apszProjMapping[] = {
     "Albers", SRS_PT_ALBERS_CONIC_EQUAL_AREA,
     "Cassini", SRS_PT_CASSINI_SOLDNER,
     "Equidistant_Cylindrical", SRS_PT_EQUIRECTANGULAR,
     "Plate_Carree", SRS_PT_EQUIRECTANGULAR,
-    "Hotine_Oblique_Mercator_Azimuth_Natural_Origin", 
+    "Hotine_Oblique_Mercator_Azimuth_Natural_Origin",
                                         SRS_PT_HOTINE_OBLIQUE_MERCATOR,
     "Lambert_Conformal_Conic", SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP,
     "Lambert_Conformal_Conic", SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP,
     "Van_der_Grinten_I", SRS_PT_VANDERGRINTEN,
     SRS_PT_TRANSVERSE_MERCATOR, SRS_PT_TRANSVERSE_MERCATOR,
     "Gauss_Kruger", SRS_PT_TRANSVERSE_MERCATOR,
-    NULL, NULL }; 
- 
-static const char *apszAlbersMapping[] = {
-    SRS_PP_CENTRAL_MERIDIAN, SRS_PP_LONGITUDE_OF_CENTER, 
+    NULL, NULL };
+
+static const char * const apszAlbersMapping[] = {
+    SRS_PP_CENTRAL_MERIDIAN, SRS_PP_LONGITUDE_OF_CENTER,
     SRS_PP_LATITUDE_OF_ORIGIN, SRS_PP_LATITUDE_OF_CENTER,
     "Central_Parallel", SRS_PP_LATITUDE_OF_CENTER,
     NULL, NULL };
 
-static const char *apszECMapping[] = {
-    SRS_PP_CENTRAL_MERIDIAN, SRS_PP_LONGITUDE_OF_CENTER, 
-    SRS_PP_LATITUDE_OF_ORIGIN, SRS_PP_LATITUDE_OF_CENTER, 
+static const char * const apszECMapping[] = {
+    SRS_PP_CENTRAL_MERIDIAN, SRS_PP_LONGITUDE_OF_CENTER,
+    SRS_PP_LATITUDE_OF_ORIGIN, SRS_PP_LATITUDE_OF_CENTER,
     NULL, NULL };
 
-static const char *apszPolarStereographicMapping[] = {
+static const char * const apszPolarStereographicMapping[] = {
     SRS_PP_STANDARD_PARALLEL_1, SRS_PP_LATITUDE_OF_ORIGIN,
     NULL, NULL };
 
-static const char *apszOrthographicMapping[] = {
+static const char * const apszOrthographicMapping[] = {
     "Longitude_Of_Center", SRS_PP_CENTRAL_MERIDIAN,
     "Latitude_Of_Center", SRS_PP_LATITUDE_OF_ORIGIN,
     NULL, NULL };
 
-static const char *apszLambertConformalConicMapping[] = {
+static const char * const apszLambertConformalConicMapping[] = {
     "Central_Parallel", SRS_PP_LATITUDE_OF_ORIGIN,
     NULL, NULL };
 
 static char **papszDatumMapping = NULL;
 static CPLMutex* hDatumMappingMutex = NULL;
- 
-static const char *apszDefaultDatumMapping[] = {
+
+static const char * const apszDefaultDatumMapping[] = {
     "6267", "North_American_1927", SRS_DN_NAD27,
     "6269", "North_American_1983", SRS_DN_NAD83,
-    NULL, NULL, NULL }; 
+    NULL, NULL, NULL };
 
-static const char *apszSpheroidMapping[] = {
+static const char * const apszSpheroidMapping[] = {
     "WGS_84", "WGS_1984",
     "WGS_72", "WGS_1972",
     "GRS_1967_Modified", "GRS_1967_Truncated",
     "Krassowsky_1940", "Krasovsky_1940",
     "Everest_1830_1937_Adjustment", "Everest_Adjustment_1937",
-    NULL, NULL }; 
- 
-static const char *apszUnitMapping[] = {
+    NULL, NULL };
+
+static const char * const apszUnitMapping[] = {
     "Meter", "meter",
     "Meter", "metre",
     "Foot", "foot",
     "Foot", "feet",
-    "Foot", "international_feet", 
+    "Foot", "international_feet",
     "Foot_US", SRS_UL_US_FOOT,
     "Foot_Clarke", "clarke_feet",
     "Degree", "degree",
     "Degree", "degrees",
     "Degree", SRS_UA_DEGREE,
     "Radian", SRS_UA_RADIAN,
-    NULL, NULL }; 
- 
+    NULL, NULL };
+
 /* -------------------------------------------------------------------- */
 /*      Table relating USGS and ESRI state plane zones.                 */
 /* -------------------------------------------------------------------- */
@@ -271,7 +278,7 @@ static const int anUsgsEsriZones[] =
  5200, 6076,
  5201, 6051,
  5202, 6051,
- 5300,    0, 
+ 5300,    0,
  5400,    0
 };
 
@@ -288,13 +295,11 @@ static const int anUsgsEsriZones[] =
 #define DM_GET_ESRI_NAME(map, i)          map[(i)*DM_ELT_SIZE + DM_IDX_ESRI_NAME]
 #define DM_GET_EPSG_NAME(map, i)          map[(i)*DM_ELT_SIZE + DM_IDX_EPSG_NAME]
 
-char *DMGetEPSGCode(int i) { return DM_GET_EPSG_CODE(papszDatumMapping, i); }
-char *DMGetESRIName(int i) { return DM_GET_ESRI_NAME(papszDatumMapping, i); }
-char *DMGetEPSGName(int i) { return DM_GET_EPSG_NAME(papszDatumMapping, i); }
+static char *DMGetEPSGCode(int i) { return DM_GET_EPSG_CODE(papszDatumMapping, i); }
+static char *DMGetESRIName(int i) { return DM_GET_ESRI_NAME(papszDatumMapping, i); }
+/* static char *DMGetEPSGName(int i) { return DM_GET_EPSG_NAME(papszDatumMapping, i); } */
 
 
-void OGREPSGDatumNameMassage( char ** ppszDatum );
-
 /************************************************************************/
 /*                           ESRIToUSGSZone()                           */
 /*                                                                      */
@@ -305,10 +310,9 @@ void OGREPSGDatumNameMassage( char ** ppszDatum );
 static int ESRIToUSGSZone( int nESRIZone )
 
 {
-    int         nPairs = sizeof(anUsgsEsriZones) / (2*sizeof(int));
-    int         i;
-    
-    for( i = 0; i < nPairs; i++ )
+    const int nPairs = sizeof(anUsgsEsriZones) / (2*sizeof(int));
+
+    for( int i = 0; i < nPairs; i++ )
     {
         if( anUsgsEsriZones[i*2+1] == nESRIZone )
             return anUsgsEsriZones[i*2];
@@ -327,16 +331,15 @@ static int ESRIToUSGSZone( int nESRIZone )
 static void MorphNameToESRI( char ** ppszName )
 
 {
-    int         i, j;
     char        *pszName = *ppszName;
-    
+
     if (pszName[0] == '\0')
         return;
 
 /* -------------------------------------------------------------------- */
 /*      Translate non-alphanumeric values to underscores.               */
 /* -------------------------------------------------------------------- */
-    for( i = 0; pszName[i] != '\0'; i++ )
+    for( int i = 0; pszName[i] != '\0'; i++ )
     {
         if( pszName[i] != '+'
             && !(pszName[i] >= 'A' && pszName[i] <= 'Z')
@@ -350,7 +353,8 @@ static void MorphNameToESRI( char ** ppszName )
 /* -------------------------------------------------------------------- */
 /*      Remove repeated and trailing underscores.                       */
 /* -------------------------------------------------------------------- */
-    for( i = 1, j = 0; pszName[i] != '\0'; i++ )
+    int j = 0;  // Used after the for loop.
+    for( int i = 1; pszName[i] != '\0'; i++ )
     {
         if( pszName[j] == '_' && pszName[i] == '_' )
             continue;
@@ -367,14 +371,14 @@ static void MorphNameToESRI( char ** ppszName )
 /*                     CleanESRIDatumMappingTable()                     */
 /************************************************************************/
 
-CPL_C_START 
+CPL_C_START
 void CleanupESRIDatumMappingTable()
 
 {
     if( papszDatumMapping == NULL )
         return;
 
-    if( papszDatumMapping != (char **) apszDefaultDatumMapping )
+    if( papszDatumMapping != apszDefaultDatumMapping )
     {
         CSLDestroy( papszDatumMapping );
         papszDatumMapping = NULL;
@@ -403,62 +407,65 @@ static void InitDatumMappingTable()
 /*      Try to open the datum.csv file.                                 */
 /* -------------------------------------------------------------------- */
     const char  *pszFilename = CSVFilename("gdal_datum.csv");
-    FILE * fp = VSIFOpen( pszFilename, "rb" );
+    VSILFILE *fp = VSIFOpenL( pszFilename, "rb" );
 
 /* -------------------------------------------------------------------- */
 /*      Use simple default set if we can't find the file.               */
 /* -------------------------------------------------------------------- */
     if( fp == NULL )
     {
-        papszDatumMapping = (char **)apszDefaultDatumMapping;
+        papszDatumMapping = const_cast<char **>(apszDefaultDatumMapping);
         return;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Figure out what fields we are interested in.                    */
 /* -------------------------------------------------------------------- */
-    char **papszFieldNames = CSVReadParseLine( fp );
-    int  nDatumCodeField = CSLFindString( papszFieldNames, "DATUM_CODE" );
-    int  nEPSGNameField = CSLFindString( papszFieldNames, "DATUM_NAME" );
-    int  nESRINameField = CSLFindString( papszFieldNames, "ESRI_DATUM_NAME" );
+    char **papszFieldNames = CSVReadParseLineL( fp );
+    const int nDatumCodeField = CSLFindString( papszFieldNames, "DATUM_CODE" );
+    const int nEPSGNameField = CSLFindString( papszFieldNames, "DATUM_NAME" );
+    const int nESRINameField =
+        CSLFindString( papszFieldNames, "ESRI_DATUM_NAME" );
 
     CSLDestroy( papszFieldNames );
 
     if( nDatumCodeField == -1 || nEPSGNameField == -1 || nESRINameField == -1 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Failed to find required field in gdal_datum.csv in InitDatumMappingTable(), using default table setup." );
-        
-        papszDatumMapping = (char **)apszDefaultDatumMapping;
-        VSIFClose( fp );
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Failed to find required field in gdal_datum.csv in "
+                  "InitDatumMappingTable(), using default table setup." );
+
+        papszDatumMapping = const_cast<char **>(apszDefaultDatumMapping);
+        VSIFCloseL( fp );
         return;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read each line, adding a detail line for each.                  */
 /* -------------------------------------------------------------------- */
     int nMappingCount = 0;
     const int nMaxDatumMappings = 1000;
-    char **papszFields;
-    papszDatumMapping = (char **)CPLCalloc(sizeof(char*),nMaxDatumMappings*3);
+    char **papszFields = NULL;
+    papszDatumMapping = static_cast<char **>(
+        CPLCalloc(sizeof(char*),nMaxDatumMappings*3) );
 
-    for( papszFields = CSVReadParseLine( fp );
+    for( papszFields = CSVReadParseLineL( fp );
          papszFields != NULL;
-         papszFields = CSVReadParseLine( fp ) )
+         papszFields = CSVReadParseLineL( fp ) )
     {
-        int nFieldCount = CSLCount(papszFields);
+        const int nFieldCount = CSLCount(papszFields);
 
         CPLAssert( nMappingCount+1 < nMaxDatumMappings );
 
-        if( MAX(nEPSGNameField,MAX(nDatumCodeField,nESRINameField)) 
-            < nFieldCount 
+        if( MAX(nEPSGNameField,MAX(nDatumCodeField,nESRINameField))
+            < nFieldCount
             && nMaxDatumMappings > nMappingCount+1 )
         {
-            papszDatumMapping[nMappingCount*3+0] = 
+            papszDatumMapping[nMappingCount*3+0] =
                 CPLStrdup( papszFields[nDatumCodeField] );
-            papszDatumMapping[nMappingCount*3+1] = 
+            papszDatumMapping[nMappingCount*3+1] =
                 CPLStrdup( papszFields[nESRINameField] );
-            papszDatumMapping[nMappingCount*3+2] = 
+            papszDatumMapping[nMappingCount*3+2] =
                 CPLStrdup( papszFields[nEPSGNameField] );
             OGREPSGDatumNameMassage( &(papszDatumMapping[nMappingCount*3+2]) );
 
@@ -467,7 +474,7 @@ static void InitDatumMappingTable()
         CSLDestroy( papszFields );
     }
 
-    VSIFClose( fp );
+    VSIFCloseL( fp );
 
     papszDatumMapping[nMappingCount*3+0] = NULL;
     papszDatumMapping[nMappingCount*3+1] = NULL;
@@ -487,9 +494,10 @@ static void InitDatumMappingTable()
 OGRErr OSRImportFromESRI( OGRSpatialReferenceH hSRS, char **papszPrj )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRImportFromESRI", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRImportFromESRI", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->importFromESRI( papszPrj );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
+        importFromESRI( papszPrj );
 }
 
 /************************************************************************/
@@ -500,49 +508,45 @@ OGRErr OSRImportFromESRI( OGRSpatialReferenceH hSRS, char **papszPrj )
 /*      helper function for importFromESRI().                           */
 /************************************************************************/
 
-static double OSR_GDV( char **papszNV, const char * pszField, 
+static double OSR_GDV( char **papszNV, const char * pszField,
                        double dfDefaultValue )
 
 {
-    int         iLine;
-
     if( papszNV == NULL || papszNV[0] == NULL )
         return dfDefaultValue;
 
-    if( EQUALN(pszField,"PARAM_",6) )
+    if( STARTS_WITH_CI(pszField, "PARAM_") )
     {
-        int     nOffset;
-
-        for( iLine = 0; 
-             papszNV[iLine] != NULL && !EQUALN(papszNV[iLine],"Paramet",7);
+        int iLine = 0;  // iLine is used after the for loop.
+        for( ;
+             papszNV[iLine] != NULL &&
+                 !STARTS_WITH_CI(papszNV[iLine], "Paramet");
              iLine++ ) {}
 
-        for( nOffset=atoi(pszField+6); 
-             papszNV[iLine] != NULL && nOffset > 0; 
-             iLine++ ) 
+        for( int nOffset=atoi(pszField+6);
+             papszNV[iLine] != NULL && nOffset > 0;
+             iLine++ )
         {
             if( strlen(papszNV[iLine]) > 0 )
                 nOffset--;
         }
-        
-        while( papszNV[iLine] != NULL && strlen(papszNV[iLine]) == 0 ) 
+
+        while( papszNV[iLine] != NULL && strlen(papszNV[iLine]) == 0 )
             iLine++;
 
         if( papszNV[iLine] != NULL )
         {
-            char        **papszTokens, *pszLine = papszNV[iLine];
-            double      dfValue;
-            
-            int         i;
-            
+            char * const pszLine = papszNV[iLine];
+
             // Trim comments.
-            for( i=0; pszLine[i] != '\0'; i++ )
+            for( int i=0; pszLine[i] != '\0'; i++ )
             {
                 if( pszLine[i] == '/' && pszLine[i+1] == '*' )
                     pszLine[i] = '\0';
             }
 
-            papszTokens = CSLTokenizeString(papszNV[iLine]);
+            double dfValue = 0.0;
+            char **papszTokens = CSLTokenizeString(papszNV[iLine]);
             if( CSLCount(papszTokens) == 3 )
             {
                 /* http://agdcftp1.wr.usgs.gov/pub/projects/lcc/akcan_lcc/akcan.tar.gz contains */
@@ -567,58 +571,52 @@ static double OSR_GDV( char **papszNV, const char * pszField,
 
             return dfValue;
         }
-        else
-            return dfDefaultValue;
-    }
-    else
-    {
-        for( iLine = 0; 
-             papszNV[iLine] != NULL && 
-                 !EQUALN(papszNV[iLine],pszField,strlen(pszField));
-             iLine++ ) {}
 
-        if( papszNV[iLine] == NULL )
-            return dfDefaultValue;
-        else
-            return CPLAtof( papszNV[iLine] + strlen(pszField) );
+        return dfDefaultValue;
     }
+
+    int iLine = 0;  // iLine used after for loop.
+    for( ;
+         papszNV[iLine] != NULL &&
+             !EQUALN(papszNV[iLine],pszField,strlen(pszField));
+         iLine++ ) {}
+
+    if( papszNV[iLine] == NULL )
+        return dfDefaultValue;
+
+    return CPLAtof( papszNV[iLine] + strlen(pszField) );
 }
 
 /************************************************************************/
 /*                              OSR_GDS()                               */
 /************************************************************************/
 
-static CPLString OSR_GDS( char **papszNV, const char * pszField, 
+static CPLString OSR_GDS( char **papszNV, const char * pszField,
                           const char *pszDefaultValue )
 
 {
-    int         iLine;
-
     if( papszNV == NULL || papszNV[0] == NULL )
         return pszDefaultValue;
 
-    for( iLine = 0; 
-         papszNV[iLine] != NULL && 
+    int iLine = 0;  // iLine used after for loop.
+    for( ;
+         papszNV[iLine] != NULL &&
              !EQUALN(papszNV[iLine],pszField,strlen(pszField));
          iLine++ ) {}
 
     if( papszNV[iLine] == NULL )
         return pszDefaultValue;
+
+    char **papszTokens = CSLTokenizeString(papszNV[iLine]);
+
+    CPLString osResult;
+    if( CSLCount(papszTokens) > 1 )
+        osResult = papszTokens[1];
     else
-    {
-        CPLString osResult;
-        char    **papszTokens;
-        
-        papszTokens = CSLTokenizeString(papszNV[iLine]);
+        osResult = pszDefaultValue;
 
-        if( CSLCount(papszTokens) > 1 )
-            osResult = papszTokens[1];
-        else
-            osResult = pszDefaultValue;
-        
-        CSLDestroy( papszTokens );
-        return osResult;
-    }
+    CSLDestroy( papszTokens );
+    return osResult;
 }
 
 /************************************************************************/
@@ -634,22 +632,22 @@ static CPLString OSR_GDS( char **papszNV, const char * pszField,
  * as the newer pseudo-OGC WKT .prj files.  Note that new style .prj files
  * are in OGC WKT format, but require some manipulation to correct datum
  * names, and units on some projection parameters.  This is addressed within
- * importFromESRI() by an automatical call to morphFromESRI(). 
+ * importFromESRI() by an automatic call to morphFromESRI().
  *
- * Currently only GEOGRAPHIC, UTM, STATEPLANE, GREATBRITIAN_GRID, ALBERS, 
+ * Currently only GEOGRAPHIC, UTM, STATEPLANE, GREATBRITIAN_GRID, ALBERS,
  * EQUIDISTANT_CONIC, TRANSVERSE (mercator), POLAR, MERCATOR and POLYCONIC
  * projections are supported from old style files.
  *
- * At this time there is no equivelent exportToESRI() method.  Writing old
+ * At this time there is no equivalent exportToESRI() method.  Writing old
  * style .prj files is not supported by OGRSpatialReference. However the
  * morphToESRI() and exportToWkt() methods can be used to generate output
- * suitable to write to new style (Arc 8) .prj files. 
+ * suitable to write to new style (Arc 8) .prj files.
  *
- * This function is the equilvelent of the C function OSRImportFromESRI().
+ * This function is the equivalent of the C function OSRImportFromESRI().
  *
  * @param papszPrj NULL terminated list of strings containing the definition.
  *
- * @return OGRERR_NONE on success or an error code in case of failure. 
+ * @return OGRERR_NONE on success or an error code in case of failure.
  */
 
 OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
@@ -659,28 +657,24 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
         return OGRERR_CORRUPT_DATA;
 
 /* -------------------------------------------------------------------- */
-/*      ArcGIS and related products now use a varient of Well Known     */
-/*      Text.  Try to recognise this and ingest it.  WKT is usually     */
+/*      ArcGIS and related products now use a variant of Well Known     */
+/*      Text.  Try to recognize this and ingest it.  WKT is usually     */
 /*      all on one line, but we will accept multi-line formats and      */
 /*      concatenate.                                                    */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(papszPrj[0],"GEOGCS",6)
-        || EQUALN(papszPrj[0],"PROJCS",6)
-        || EQUALN(papszPrj[0],"LOCAL_CS",8) )
+    if( STARTS_WITH_CI(papszPrj[0], "GEOGCS")
+        || STARTS_WITH_CI(papszPrj[0], "PROJCS")
+        || STARTS_WITH_CI(papszPrj[0], "LOCAL_CS") )
     {
-        char    *pszWKT, *pszWKT2;
-        OGRErr  eErr;
-        int     i;
-
-        pszWKT = CPLStrdup(papszPrj[0]);
-        for( i = 1; papszPrj[i] != NULL; i++ )
+        char *pszWKT = CPLStrdup(papszPrj[0]);
+        for( int i = 1; papszPrj[i] != NULL; i++ )
         {
-            pszWKT = (char *) 
-                CPLRealloc(pszWKT,strlen(pszWKT)+strlen(papszPrj[i])+1);
+            pszWKT = static_cast<char *>(
+                CPLRealloc(pszWKT,strlen(pszWKT)+strlen(papszPrj[i])+1) );
             strcat( pszWKT, papszPrj[i] );
         }
-        pszWKT2 = pszWKT;
-        eErr = importFromWkt( &pszWKT2 );
+        char *pszWKT2 = pszWKT;
+        OGRErr eErr = importFromWkt( &pszWKT2 );
         CPLFree( pszWKT );
 
         if( eErr == OGRERR_NONE )
@@ -701,37 +695,36 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
 
     else if( EQUAL(osProj,"GEOGRAPHIC") )
     {
+        // Nothing to do.
     }
-    
+
     else if( EQUAL(osProj,"utm") )
     {
-        if( (int) OSR_GDV( papszPrj, "zone", 0.0 ) != 0 )
+        if( static_cast<int>( OSR_GDV( papszPrj, "zone", 0.0 ) ) != 0 )
         {
-            double      dfYShift = OSR_GDV( papszPrj, "Yshift", 0.0 );
+            const double dfYShift = OSR_GDV( papszPrj, "Yshift", 0.0 );
 
-            SetUTM( (int) OSR_GDV( papszPrj, "zone", 0.0 ),
+            SetUTM( static_cast<int>( OSR_GDV( papszPrj, "zone", 0.0 ) ),
                     dfYShift == 0.0 );
         }
         else
         {
-            double      dfCentralMeridian, dfRefLat;
-            int         nZone;
-
-            dfCentralMeridian = OSR_GDV( papszPrj, "PARAM_1", 0.0 );
-            dfRefLat = OSR_GDV( papszPrj, "PARAM_2", 0.0 );
+            const double dfCentralMeridian = OSR_GDV( papszPrj, "PARAM_1", 0.0 );
+            const double dfRefLat = OSR_GDV( papszPrj, "PARAM_2", 0.0 );
 
-            nZone = (int) ((dfCentralMeridian+183) / 6.0 + 0.0000001);
+            const int nZone = static_cast<int>(
+                (dfCentralMeridian+183) / 6.0 + 0.0000001 );
             SetUTM( nZone, dfRefLat >= 0.0 );
         }
     }
 
     else if( EQUAL(osProj,"STATEPLANE") )
     {
-        int nZone = (int) OSR_GDV( papszPrj, "zone", 0.0 );
+        int nZone = static_cast<int>( OSR_GDV( papszPrj, "zone", 0.0 ) );
         if( nZone != 0 )
             nZone = ESRIToUSGSZone( nZone );
         else
-            nZone = (int) OSR_GDV( papszPrj, "fipszone", 0.0 );
+            nZone = static_cast<int>( OSR_GDV( papszPrj, "fipszone", 0.0 ) );
 
         if( nZone != 0 )
         {
@@ -742,10 +735,10 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
         }
     }
 
-    else if( EQUAL(osProj,"GREATBRITIAN_GRID") 
+    else if( EQUAL(osProj,"GREATBRITIAN_GRID")
              || EQUAL(osProj,"GREATBRITAIN_GRID") )
     {
-        const char *pszWkt = 
+        const char *pszWkt =
             "PROJCS[\"OSGB 1936 / British National Grid\",GEOGCS[\"OSGB 1936\",DATUM[\"OSGB_1936\",SPHEROID[\"Airy 1830\",6377563.396,299.3249646]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",49],PARAMETER[\"central_meridian\",-2],PARAMETER[\"scale_factor\",0.999601272],PARAMETER[\"false_easting\",400000],PARAMETER[\"false_northing\",-100000],UNIT[\"metre\",1]]";
 
         importFromWkt( (char **) &pszWkt );
@@ -753,11 +746,11 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
 
     else if( EQUAL(osProj,"ALBERS") )
     {
-        SetACEA( OSR_GDV( papszPrj, "PARAM_1", 0.0 ), 
-                 OSR_GDV( papszPrj, "PARAM_2", 0.0 ), 
-                 OSR_GDV( papszPrj, "PARAM_4", 0.0 ), 
-                 OSR_GDV( papszPrj, "PARAM_3", 0.0 ), 
-                 OSR_GDV( papszPrj, "PARAM_5", 0.0 ), 
+        SetACEA( OSR_GDV( papszPrj, "PARAM_1", 0.0 ),
+                 OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
+                 OSR_GDV( papszPrj, "PARAM_4", 0.0 ),
+                 OSR_GDV( papszPrj, "PARAM_3", 0.0 ),
+                 OSR_GDV( papszPrj, "PARAM_5", 0.0 ),
                  OSR_GDV( papszPrj, "PARAM_6", 0.0 ) );
     }
 
@@ -781,52 +774,53 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
 
     else if( EQUAL(osProj,"EQUIDISTANT_CONIC") )
     {
-        int     nStdPCount = (int) OSR_GDV( papszPrj, "PARAM_1", 0.0 );
+        const int nStdPCount = static_cast<int>(
+            OSR_GDV( papszPrj, "PARAM_1", 0.0 ) );
 
         if( nStdPCount == 1 )
         {
-            SetEC( OSR_GDV( papszPrj, "PARAM_2", 0.0 ), 
-                   OSR_GDV( papszPrj, "PARAM_2", 0.0 ), 
-                   OSR_GDV( papszPrj, "PARAM_4", 0.0 ), 
-                   OSR_GDV( papszPrj, "PARAM_3", 0.0 ), 
-                   OSR_GDV( papszPrj, "PARAM_5", 0.0 ), 
+            SetEC( OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
+                   OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
+                   OSR_GDV( papszPrj, "PARAM_4", 0.0 ),
+                   OSR_GDV( papszPrj, "PARAM_3", 0.0 ),
+                   OSR_GDV( papszPrj, "PARAM_5", 0.0 ),
                    OSR_GDV( papszPrj, "PARAM_6", 0.0 ) );
         }
         else
         {
-            SetEC( OSR_GDV( papszPrj, "PARAM_2", 0.0 ), 
-                   OSR_GDV( papszPrj, "PARAM_3", 0.0 ), 
-                   OSR_GDV( papszPrj, "PARAM_5", 0.0 ), 
-                   OSR_GDV( papszPrj, "PARAM_4", 0.0 ), 
-                   OSR_GDV( papszPrj, "PARAM_5", 0.0 ), 
+            SetEC( OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
+                   OSR_GDV( papszPrj, "PARAM_3", 0.0 ),
+                   OSR_GDV( papszPrj, "PARAM_5", 0.0 ),
+                   OSR_GDV( papszPrj, "PARAM_4", 0.0 ),
+                   OSR_GDV( papszPrj, "PARAM_5", 0.0 ),
                    OSR_GDV( papszPrj, "PARAM_7", 0.0 ) );
         }
     }
 
     else if( EQUAL(osProj,"TRANSVERSE") )
     {
-        SetTM( OSR_GDV( papszPrj, "PARAM_3", 0.0 ), 
-               OSR_GDV( papszPrj, "PARAM_2", 0.0 ), 
-               OSR_GDV( papszPrj, "PARAM_1", 0.0 ), 
-               OSR_GDV( papszPrj, "PARAM_4", 0.0 ), 
+        SetTM( OSR_GDV( papszPrj, "PARAM_3", 0.0 ),
+               OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
+               OSR_GDV( papszPrj, "PARAM_1", 0.0 ),
+               OSR_GDV( papszPrj, "PARAM_4", 0.0 ),
                OSR_GDV( papszPrj, "PARAM_5", 0.0 ) );
     }
 
     else if( EQUAL(osProj,"POLAR") )
     {
-        SetPS( OSR_GDV( papszPrj, "PARAM_2", 0.0 ), 
-               OSR_GDV( papszPrj, "PARAM_1", 0.0 ), 
+        SetPS( OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
+               OSR_GDV( papszPrj, "PARAM_1", 0.0 ),
                1.0,
-               OSR_GDV( papszPrj, "PARAM_3", 0.0 ), 
+               OSR_GDV( papszPrj, "PARAM_3", 0.0 ),
                OSR_GDV( papszPrj, "PARAM_4", 0.0 ) );
     }
 
     else if( EQUAL(osProj,"MERCATOR") )
     {
-        SetMercator( OSR_GDV( papszPrj, "PARAM_1", 0.0 ), 
-                     OSR_GDV( papszPrj, "PARAM_0", 0.0 ), 
-                     1.0, 
-                     OSR_GDV( papszPrj, "PARAM_2", 0.0 ), 
+        SetMercator( OSR_GDV( papszPrj, "PARAM_1", 0.0 ),
+                     OSR_GDV( papszPrj, "PARAM_0", 0.0 ),
+                     1.0,
+                     OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
                      OSR_GDV( papszPrj, "PARAM_3", 0.0 ) );
     }
 
@@ -834,7 +828,6 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
     {
        // This is EPSG:3875 Pseudo Mercator. We might as well import it from
        // the EPSG spec.
-       CPLString osAuxiliarySphereType;
        importFromEPSG(3857);
     }
 
@@ -857,9 +850,7 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
 /* -------------------------------------------------------------------- */
     if( !IsLocal() && GetAttrNode( "GEOGCS" ) == NULL )
     {
-        CPLString osDatum;
-
-        osDatum = OSR_GDS( papszPrj, "Datum", "");
+        CPLString osDatum = OSR_GDS( papszPrj, "Datum", "");
 
         if( EQUAL(osDatum,"NAD27") || EQUAL(osDatum,"NAD83")
             || EQUAL(osDatum,"WGS84") || EQUAL(osDatum,"WGS72") )
@@ -877,11 +868,9 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
         }
         else
         {
-            CPLString osSpheroid;
+            CPLString osSpheroid = OSR_GDS( papszPrj, "Spheroid", "");
 
-            osSpheroid = OSR_GDS( papszPrj, "Spheroid", "");
-            
-            if( EQUAL(osSpheroid,"INT1909") 
+            if( EQUAL(osSpheroid,"INT1909")
                 || EQUAL(osSpheroid,"INTERNATIONAL1909") )
             {
                 OGRSpatialReference oGCS;
@@ -906,7 +895,7 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
                 oGCS.importFromEPSG( 4019 );
                 CopyGeogCSFrom( &oGCS );
             }
-            else if( EQUAL(osSpheroid,"KRASOVSKY") 
+            else if( EQUAL(osSpheroid,"KRASOVSKY")
                      || EQUAL(osSpheroid,"KRASSOVSKY")
                      || EQUAL(osSpheroid,"KRASSOWSKY") )
             {
@@ -922,8 +911,32 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
             }
             else
             {
-                // If we don't know, default to WGS84 so there is something there.
-                SetWellKnownGeogCS( "WGS84" );
+                bool bFoundParameters = false;
+                for( int iLine = 0; papszPrj[iLine] != NULL; iLine++ )
+                {
+                    if( STARTS_WITH_CI(papszPrj[iLine],"Parameters") )
+                    {
+                        char** papszTokens = CSLTokenizeString(papszPrj[iLine] + strlen("Parameters"));
+                        if( CSLCount(papszTokens) == 2 )
+                        {
+                            OGRSpatialReference oGCS;
+                            const double dfSemiMajor = CPLAtof( papszTokens[0] );
+                            const double dfSemiMinor = CPLAtof( papszTokens[1] );
+                            const double dfInvFlattening = OSRCalcInvFlattening( dfSemiMajor, dfSemiMinor );
+                            oGCS.SetGeogCS( "unknown", "unknown", "unknown",
+                                            dfSemiMajor, dfInvFlattening );
+                            CopyGeogCSFrom( &oGCS );
+                            bFoundParameters = true;
+                        }
+                        CSLDestroy(papszTokens);
+                        break;
+                    }
+                }
+                if( !bFoundParameters )
+                {
+                    // If unknown, default to WGS84 so there is something there.
+                    SetWellKnownGeogCS( "WGS84" );
+                }
             }
         }
     }
@@ -933,16 +946,16 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
 /* -------------------------------------------------------------------- */
     if( IsLocal() || IsProjected() )
     {
-        CPLString osValue;
         double dfOldUnits = GetLinearUnits();
+        CPLString osValue = OSR_GDS( papszPrj, "Units", "" );
 
-        osValue = OSR_GDS( papszPrj, "Units", "" );
         if( EQUAL(osValue, "" ) )
             SetLinearUnitsAndUpdateParameters( SRS_UL_METER, 1.0 );
         else if( EQUAL(osValue,"FEET") )
-            SetLinearUnitsAndUpdateParameters( SRS_UL_US_FOOT, CPLAtof(SRS_UL_US_FOOT_CONV) );
+            SetLinearUnitsAndUpdateParameters( SRS_UL_US_FOOT,
+                                               CPLAtof(SRS_UL_US_FOOT_CONV) );
         else if( CPLAtof(osValue) != 0.0 )
-            SetLinearUnitsAndUpdateParameters( "user-defined", 
+            SetLinearUnitsAndUpdateParameters( "user-defined",
                                                1.0 / CPLAtof(osValue) );
         else
             SetLinearUnitsAndUpdateParameters( osValue, 1.0 );
@@ -951,7 +964,7 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
         // nodes on the PROJCS.  This especially applies to state plane
         // per bug 1697
         double dfNewUnits = GetLinearUnits();
-        if( dfOldUnits != 0.0 
+        if( dfOldUnits != 0.0
             && (dfNewUnits / dfOldUnits < 0.9999999
                 || dfNewUnits / dfOldUnits > 1.0000001) )
         {
@@ -959,7 +972,7 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
                 GetRoot()->DestroyChild(GetRoot()->FindChild( "AUTHORITY" ));
         }
     }
-    
+
     return OGRERR_NONE;
 }
 
@@ -971,8 +984,8 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
  *
  * The value nodes of this coordinate system are modified in various manners
  * more closely map onto the ESRI concept of WKT format.  This includes
- * renaming a variety of projections and arguments, and stripping out 
- * nodes note recognised by ESRI (like AUTHORITY and AXIS). 
+ * renaming a variety of projections and arguments, and stripping out
+ * nodes note recognised by ESRI (like AUTHORITY and AXIS).
  *
  * This does the same as the C function OSRMorphToESRI().
  *
@@ -982,21 +995,39 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
 OGRErr OGRSpatialReference::morphToESRI()
 
 {
-    OGRErr      eErr;
+/* -------------------------------------------------------------------- */
+/*      Special case for EPSG:3857. Hard to deal with in the general    */
+/*      case as GDAL (at the time of writing) uses regular Mercator_1SP */
+/*      to model it.                                                    */
+/* -------------------------------------------------------------------- */
+    const char* pszAuthName = GetAuthorityName(NULL);
+    const char* pszAuthCode = GetAuthorityCode(NULL);
+    if( (pszAuthName != NULL && EQUAL(pszAuthName,"EPSG") && pszAuthCode != NULL &&
+         atoi(pszAuthCode) == 3857) ||
+        (GetAttrValue("PROJCS") != NULL && EQUAL(GetAttrValue("PROJCS"), "WGS 84 / Pseudo-Mercator")) )
+    {
+        Clear();
+        const char* pszESRI_PE_WebMercator = "PROJCS[\"WGS_1984_Web_Mercator_Auxiliary_Sphere\",GEOGCS[\"GCS_WGS_1984\",DATUM[\"D_WGS_1984\",SPHEROID[\"WGS_1984\",6378137.0,298.257223563]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Mercator_Auxiliary_Sphere\"],PARAMETER[\"False_Easting\",0.0],PARAMETER[\"False_Northing\",0.0],PARAMETER[\"Central_Meridian\",0.0],PARAMETER[\"Standard_Parallel_1\",0.0],PARAMETER[\"Auxiliary_Sphere_Type\",0.0],UNIT[\"Meter\",1.0]]";
+        return importFromWkt( (char**) &pszESRI_PE_WebMercator );
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Fixup ordering, missing linear units, etc.                      */
 /* -------------------------------------------------------------------- */
-    eErr = Fixup();
-    if( eErr != OGRERR_NONE )
-        return eErr;
+    {
+        const OGRErr eErr = Fixup();
+        if( eErr != OGRERR_NONE )
+            return eErr;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Strip all CT parameters (AXIS, AUTHORITY, TOWGS84, etc).        */
 /* -------------------------------------------------------------------- */
-    eErr = StripCTParms();
-    if( eErr != OGRERR_NONE )
-        return eErr;
+    {
+        const OGRErr eErr = StripCTParms();
+        if( eErr != OGRERR_NONE )
+            return eErr;
+    }
 
     if( GetRoot() == NULL )
         return OGRERR_NONE;
@@ -1006,19 +1037,19 @@ OGRErr OGRSpatialReference::morphToESRI()
 /*      out the case with an angle to rectified grid.  Bug 423          */
 /* -------------------------------------------------------------------- */
     const char *pszProjection = GetAttrValue("PROJECTION");
-    
+
     if( pszProjection != NULL
-        && EQUAL(pszProjection,SRS_PT_HOTINE_OBLIQUE_MERCATOR) 
-        && fabs(GetProjParm(SRS_PP_AZIMUTH, 0.0 )-90) < 0.0001 
+        && EQUAL(pszProjection,SRS_PT_HOTINE_OBLIQUE_MERCATOR)
+        && fabs(GetProjParm(SRS_PP_AZIMUTH, 0.0 )-90) < 0.0001
         && fabs(GetProjParm(SRS_PP_RECTIFIED_GRID_ANGLE, 0.0 )-90) < 0.0001 )
     {
-        SetNode( "PROJCS|PROJECTION", 
+        SetNode( "PROJCS|PROJECTION",
                  "Hotine_Oblique_Mercator_Azimuth_Center" );
 
         /* ideally we should strip out of the rectified_grid_angle */
         // strip off rectified_grid_angle -- I hope it is 90!
         OGR_SRSNode *poPROJCS = GetAttrNode( "PROJCS" );
-        int iRGAChild = FindProjParm( "rectified_grid_angle", poPROJCS );
+        const int iRGAChild = FindProjParm( "rectified_grid_angle", poPROJCS );
         if( iRGAChild != -1 )
             poPROJCS->DestroyChild( iRGAChild);
 
@@ -1035,13 +1066,13 @@ OGRErr OGRSpatialReference::morphToESRI()
     {
         if( GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) < 0.0 )
         {
-            SetNode( "PROJCS|PROJECTION", 
+            SetNode( "PROJCS|PROJECTION",
                      "Stereographic_South_Pole" );
             pszProjection = GetAttrValue("PROJECTION");
         }
         else
         {
-            SetNode( "PROJCS|PROJECTION", 
+            SetNode( "PROJCS|PROJECTION",
                      "Stereographic_North_Pole" );
             pszProjection = GetAttrValue("PROJECTION");
         }
@@ -1059,9 +1090,12 @@ OGRErr OGRSpatialReference::morphToESRI()
 /* -------------------------------------------------------------------- */
 /*      Translate PROJECTION keywords that are misnamed.                */
 /* -------------------------------------------------------------------- */
-    GetRoot()->applyRemapper( "PROJECTION", 
-                              (char **)apszProjMapping+1,
-                              (char **)apszProjMapping, 2 );
+    // TODO(schwehr): How is applyRemapper safe with
+    //   static const char * const apszProjMapping[]?
+    GetRoot()->applyRemapper( "PROJECTION",
+                              const_cast<char **>(apszProjMapping+1),
+                              const_cast<char **>(apszProjMapping),
+                              2 );
     pszProjection = GetAttrValue("PROJECTION");
 
 /* -------------------------------------------------------------------- */
@@ -1069,7 +1103,7 @@ OGRErr OGRSpatialReference::morphToESRI()
 /* -------------------------------------------------------------------- */
     InitDatumMappingTable();
 
-    GetRoot()->applyRemapper( "DATUM", 
+    GetRoot()->applyRemapper( "DATUM",
                               papszDatumMapping+2, papszDatumMapping+1, 3 );
 
     const char *pszProjCSName      = NULL;
@@ -1085,36 +1119,36 @@ OGRErr OGRSpatialReference::morphToESRI()
     if( poGeogCS != NULL )
     {
         const char *pszGeogCSName = poGeogCS->GetChild(0)->GetValue();
-        const char *pszAuthName = GetAuthorityName("GEOGCS");
+        pszAuthName = GetAuthorityName("GEOGCS");
         const char *pszUTMPrefix = NULL;
         int nGCSCode = -1;
-        
+
         if( pszAuthName != NULL && EQUAL(pszAuthName,"EPSG") )
             nGCSCode = atoi(GetAuthorityCode("GEOGCS"));
 
-        if( nGCSCode == 4326 
-            || EQUAL(pszGeogCSName,"WGS84") 
+        if( nGCSCode == 4326
+            || EQUAL(pszGeogCSName,"WGS84")
             || EQUAL(pszGeogCSName,"WGS 84") )
         {
             poGeogCS->GetChild(0)->SetValue( "GCS_WGS_1984" );
             pszUTMPrefix = "WGS_1984";
         }
-        else if( nGCSCode == 4322 
-            || EQUAL(pszGeogCSName,"WGS72") 
+        else if( nGCSCode == 4322
+            || EQUAL(pszGeogCSName,"WGS72")
             || EQUAL(pszGeogCSName,"WGS 72") )
         {
             poGeogCS->GetChild(0)->SetValue( "GCS_WGS_1972" );
             pszUTMPrefix = "WGS_1972";
         }
         else if( nGCSCode == 4267
-                 || EQUAL(pszGeogCSName,"NAD27") 
+                 || EQUAL(pszGeogCSName,"NAD27")
                  || EQUAL(pszGeogCSName,"NAD 27") )
         {
             poGeogCS->GetChild(0)->SetValue( "GCS_North_American_1927" );
             pszUTMPrefix = "NAD_1927";
         }
         else if( nGCSCode == 4269
-                 || EQUAL(pszGeogCSName,"NAD83") 
+                 || EQUAL(pszGeogCSName,"NAD83")
                  || EQUAL(pszGeogCSName,"NAD 83") )
         {
             poGeogCS->GetChild(0)->SetValue( "GCS_North_American_1983" );
@@ -1138,27 +1172,27 @@ OGRErr OGRSpatialReference::morphToESRI()
 /* -------------------------------------------------------------------- */
 /*      Force Unnamed to Unknown for most common locations.             */
 /* -------------------------------------------------------------------- */
-        static const char *apszUnknownMapping[] = { 
+        static const char * const apszUnknownMapping[] = {
             "Unknown", "Unnamed",
-            NULL, NULL 
+            NULL, NULL
         };
 
-        GetRoot()->applyRemapper( "PROJCS", 
+        GetRoot()->applyRemapper( "PROJCS",
                                   (char **)apszUnknownMapping+1,
                                   (char **)apszUnknownMapping+0, 2 );
-        GetRoot()->applyRemapper( "GEOGCS", 
+        GetRoot()->applyRemapper( "GEOGCS",
                                   (char **)apszUnknownMapping+1,
                                   (char **)apszUnknownMapping+0, 2 );
-        GetRoot()->applyRemapper( "DATUM", 
+        GetRoot()->applyRemapper( "DATUM",
                                   (char **)apszUnknownMapping+1,
                                   (char **)apszUnknownMapping+0, 2 );
-        GetRoot()->applyRemapper( "SPHEROID", 
+        GetRoot()->applyRemapper( "SPHEROID",
                                   (char **)apszUnknownMapping+1,
                                   (char **)apszUnknownMapping+0, 2 );
-        GetRoot()->applyRemapper( "PRIMEM", 
+        GetRoot()->applyRemapper( "PRIMEM",
                                   (char **)apszUnknownMapping+1,
                                   (char **)apszUnknownMapping+0, 2 );
-    
+
 /* -------------------------------------------------------------------- */
 /*      If the PROJCS name is unset, use the PROJECTION name in         */
 /*      place of unknown, or unnamed.  At the request of Peng Gao.      */
@@ -1196,25 +1230,25 @@ OGRErr OGRSpatialReference::morphToESRI()
         int nZone  = 0;
 
         /* get zone from name first */
-        if( pszProjCSName && EQUALN(pszProjCSName, "UTM Zone ", 9) )
+        if( pszProjCSName && STARTS_WITH_CI(pszProjCSName, "UTM Zone ") )
         {
             nZone = atoi(pszProjCSName+9);
             if( strstr(pszProjCSName, "North") )
-                bNorth = 1;
+                bNorth = TRUE;
         }
 
         /* if can not get from the name, from the parameters */
-        if( nZone <= 0 ) 
+        if( nZone <= 0 )
             nZone = GetUTMZone( &bNorth );
 
         if( nZone > 0 && pszUTMPrefix )
         {
             char szUTMName[128];
             if( bNorth )
-                sprintf( szUTMName, "%s_UTM_Zone_%dN", pszUTMPrefix, nZone );
+                snprintf( szUTMName, sizeof(szUTMName), "%s_UTM_Zone_%dN", pszUTMPrefix, nZone );
             else
-                sprintf( szUTMName, "%s_UTM_Zone_%dS", pszUTMPrefix, nZone );
-              
+                snprintf( szUTMName, sizeof(szUTMName), "%s_UTM_Zone_%dS", pszUTMPrefix, nZone );
+
             if( poProjCSNodeChild )
                 poProjCSNodeChild->SetValue( szUTMName );
         }
@@ -1224,17 +1258,18 @@ OGRErr OGRSpatialReference::morphToESRI()
 /*      Translate UNIT keywords that are misnamed, or even the wrong    */
 /*      case.                                                           */
 /* -------------------------------------------------------------------- */
-    GetRoot()->applyRemapper( "UNIT", 
-                              (char **)apszUnitMapping+1,
-                              (char **)apszUnitMapping, 2 );
+    GetRoot()->applyRemapper( "UNIT",
+                              const_cast<char **>(apszUnitMapping+1),
+                              const_cast<char **>(apszUnitMapping),
+                              2 );
 
 /* -------------------------------------------------------------------- */
 /*      reset constants for decimal degrees to the exact string ESRI    */
 /*      expects when encountered to ensure a matchup.                   */
 /* -------------------------------------------------------------------- */
     OGR_SRSNode *poUnit = GetAttrNode( "GEOGCS|UNIT" );
-    
-    if( poUnit != NULL && poUnit->GetChildCount() >= 2 
+
+    if( poUnit != NULL && poUnit->GetChildCount() >= 2
         && ABS(GetAngularUnits()-0.0174532925199433) < 0.00000000001 )
     {
         poUnit->GetChild(0)->SetValue("Degree");
@@ -1245,8 +1280,8 @@ OGRErr OGRSpatialReference::morphToESRI()
 /*      Make sure we reproduce US Feet exactly too.                     */
 /* -------------------------------------------------------------------- */
     poUnit = GetAttrNode( "PROJCS|UNIT" );
-    
-    if( poUnit != NULL && poUnit->GetChildCount() >= 2 
+
+    if( poUnit != NULL && poUnit->GetChildCount() >= 2
         && ABS(GetLinearUnits()- 0.30480060960121924) < 0.000000000000001)
     {
         poUnit->GetChild(0)->SetValue("Foot_US");
@@ -1256,55 +1291,60 @@ OGRErr OGRSpatialReference::morphToESRI()
 /* -------------------------------------------------------------------- */
 /*      Remap parameters used for Albers.                               */
 /* -------------------------------------------------------------------- */
+    // Do not remove the previous pszProjection assignment, for easy
+    // maintainability.
+    CPL_IGNORE_RET_VAL(pszProjection);
     pszProjection = GetAttrValue("PROJECTION");
     poProjCS = GetAttrNode( "PROJCS" );
-    
+
     if( pszProjection != NULL && EQUAL(pszProjection,"Albers") )
-        GetRoot()->applyRemapper( 
-            "PARAMETER", (char **)apszAlbersMapping + 1,
-            (char **)apszAlbersMapping + 0, 2 );
+        GetRoot()->applyRemapper(
+            "PARAMETER", const_cast<char **>(apszAlbersMapping + 1),
+            const_cast<char **>(apszAlbersMapping + 0), 2 );
 
-    if( pszProjection != NULL 
+    if( pszProjection != NULL
         && (EQUAL(pszProjection,SRS_PT_EQUIDISTANT_CONIC) ||
             EQUAL(pszProjection,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) ||
             EQUAL(pszProjection,SRS_PT_AZIMUTHAL_EQUIDISTANT) ||
             EQUAL(pszProjection,SRS_PT_SINUSOIDAL) ||
             EQUAL(pszProjection,SRS_PT_ROBINSON) ) )
-        GetRoot()->applyRemapper( 
-            "PARAMETER", (char **)apszECMapping + 1,
-            (char **)apszECMapping + 0, 2 );
-
-    if( pszProjection != NULL 
-        && EQUALN(pszProjection,"Stereographic_",14)
-        && EQUALN(pszProjection+strlen(pszProjection)-5,"_Pole",5) )
-        GetRoot()->applyRemapper( 
-            "PARAMETER", 
-            (char **)apszPolarStereographicMapping + 1, 
-            (char **)apszPolarStereographicMapping + 0, 2 );
+        GetRoot()->applyRemapper(
+            "PARAMETER", const_cast<char **>(apszECMapping + 1),
+            const_cast<char **>(apszECMapping + 0), 2 );
+
+    if( pszProjection != NULL
+        && STARTS_WITH_CI(pszProjection, "Stereographic_")
+        && STARTS_WITH_CI(pszProjection+strlen(pszProjection)-5, "_Pole") )
+        GetRoot()->applyRemapper(
+            "PARAMETER",
+            const_cast<char **>(apszPolarStereographicMapping + 1),
+            const_cast<char **>(apszPolarStereographicMapping + 0), 2 );
 
     if( pszProjection != NULL && EQUAL(pszProjection,"Plate_Carree") )
         if(FindProjParm( SRS_PP_STANDARD_PARALLEL_1, poProjCS ) < 0)
-            GetRoot()->applyRemapper( 
-                "PARAMETER", 
-                (char **)apszPolarStereographicMapping + 1, 
-                (char **)apszPolarStereographicMapping + 0, 2 );
+            GetRoot()->applyRemapper(
+                "PARAMETER",
+                const_cast<char **>(apszPolarStereographicMapping + 1),
+                const_cast<char **>(apszPolarStereographicMapping + 0), 2 );
 
 /* -------------------------------------------------------------------- */
 /*      ESRI's Equidistant_Cylindrical does not support the             */
 /*      latitude_of_origin keyword.                                     */
 /* -------------------------------------------------------------------- */
-    if( pszProjection != NULL 
+    if( pszProjection != NULL
         && EQUAL(pszProjection,"Equidistant_Cylindrical") )
     {
         if( GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0) != 0.0 )
         {
-            CPLDebug( "OGR_ESRI", "Equirectangular with non-zero latitude of origin - not supported." );
+            CPLDebug( "OGR_ESRI",
+                      "Equirectangular with non-zero latitude of origin - "
+                      "not supported." );
         }
         else
         {
             OGR_SRSNode *poPROJCS = GetAttrNode("PROJCS");
             if( poPROJCS )
-                poPROJCS->DestroyChild( 
+                poPROJCS->DestroyChild(
                     FindProjParm( SRS_PP_LATITUDE_OF_ORIGIN ) );
         }
     }
@@ -1313,28 +1353,28 @@ OGRErr OGRSpatialReference::morphToESRI()
     if( pszProjection != NULL && EQUAL(pszProjection,SRS_PT_MERCATOR_2SP) )
     {
         SetNode( "PROJCS|PROJECTION", "Mercator" );
-        pszProjection = GetAttrValue("PROJECTION");
     }
-    
+
     /* See #4861 */
-    if( pszProjection != NULL && EQUAL(pszProjection,SRS_PT_MERCATOR_1SP) )
+    else if( pszProjection != NULL && EQUAL(pszProjection,SRS_PT_MERCATOR_1SP) )
     {
         SetNode( "PROJCS|PROJECTION", "Mercator" );
-        pszProjection = GetAttrValue("PROJECTION");
-        
-        double dfK0 = GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0);
-        
-        double dfInvFlattening = GetInvFlattening();;
+
+        const double dfK0 = GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0);
+
+        const double dfInvFlattening = GetInvFlattening();;
         double e2 = 0.0;
         if( dfInvFlattening != 0.0 )
         {
             double f = 1 / dfInvFlattening;
             e2 = 2 *f - f*f;
         }
-        double dfStdP1Lat = acos( sqrt( (1 - e2) / (1 / (dfK0 * dfK0)) - e2) ) / M_PI * 180.0;
+        const double dfStdP1Lat =
+            acos( sqrt( (1 - e2) / (1 / (dfK0 * dfK0)) - e2) ) / M_PI * 180.0;
         if( poProjCS )
         {
-            int iScaleFactorChild = FindProjParm( SRS_PP_SCALE_FACTOR, poProjCS );
+            const int iScaleFactorChild =
+                FindProjParm( SRS_PP_SCALE_FACTOR, poProjCS );
             if( iScaleFactorChild != -1 )
                 poProjCS->DestroyChild( iScaleFactorChild);
             SetProjParm(SRS_PP_STANDARD_PARALLEL_1, dfStdP1Lat);
@@ -1345,15 +1385,15 @@ OGRErr OGRSpatialReference::morphToESRI()
 /* -------------------------------------------------------------------- */
 /*      Convert SPHEROID name to use underscores instead of spaces.     */
 /* -------------------------------------------------------------------- */
-    OGR_SRSNode *poSpheroid;
     OGR_SRSNode *poSpheroidChild = NULL;
-    poSpheroid = GetAttrNode( "SPHEROID" );
+    OGR_SRSNode *poSpheroid = GetAttrNode( "SPHEROID" );
     if( poSpheroid != NULL )
         poSpheroidChild = poSpheroid->GetChild(0);
 
     if( poSpheroidChild != NULL )
     {
-//        char *pszNewValue = CPLStrdup(RemapSpheroidName(poSpheroidChild->GetValue()));
+        // char *pszNewValue =
+        //     CPLStrdup(RemapSpheroidName(poSpheroidChild->GetValue()));
         char *pszNewValue = CPLStrdup(poSpheroidChild->GetValue());
 
         MorphNameToESRI( &pszNewValue );
@@ -1361,9 +1401,10 @@ OGRErr OGRSpatialReference::morphToESRI()
         poSpheroidChild->SetValue( pszNewValue );
         CPLFree( pszNewValue );
 
-        GetRoot()->applyRemapper( "SPHEROID", 
-                                  (char **) apszSpheroidMapping+0,
-                                  (char **) apszSpheroidMapping+1, 2 );
+        GetRoot()->applyRemapper( "SPHEROID",
+                                  const_cast<char **>(apszSpheroidMapping+0),
+                                  const_cast<char **>(apszSpheroidMapping+1),
+                                  2 );
     }
 
     if( poSpheroid != NULL )
@@ -1371,34 +1412,32 @@ OGRErr OGRSpatialReference::morphToESRI()
 
     if( poSpheroidChild != NULL )
     {
-      const char * dfValue = poSpheroidChild->GetValue();
+      const char * pszValue = poSpheroidChild->GetValue();
       for( int i = 0; apszInvFlatteningMapping[i] != NULL; i += 2 )
       {
-        if( EQUALN(apszInvFlatteningMapping[i], dfValue, strlen(apszInvFlatteningMapping[i]) ))
+        if( EQUALN(apszInvFlatteningMapping[i], pszValue,
+                   strlen(apszInvFlatteningMapping[i]) ))
         {
           poSpheroidChild->SetValue( apszInvFlatteningMapping[i+1] );
           break;
         }
       }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Try to insert a D_ in front of the datum name.                  */
 /* -------------------------------------------------------------------- */
-    OGR_SRSNode *poDatum;
-
-    poDatum = GetAttrNode( "DATUM" );
+    OGR_SRSNode *poDatum = GetAttrNode( "DATUM" );
     if( poDatum != NULL )
         poDatum = poDatum->GetChild(0);
 
     if( poDatum != NULL )
     {
         const char* pszDatumName = poDatum->GetValue();
-        if( !EQUALN(pszDatumName, "D_",2) )
+        if( !STARTS_WITH_CI(pszDatumName, "D_") )
         {
-            char *pszNewValue;
-
-            pszNewValue = (char *) CPLMalloc(strlen(poDatum->GetValue())+3);
+            char *pszNewValue = static_cast<char *>(
+                CPLMalloc(strlen(poDatum->GetValue())+3) );
             strcpy( pszNewValue, "D_" );
             strcat( pszNewValue, poDatum->GetValue() );
             poDatum->SetValue( pszNewValue );
@@ -1414,21 +1453,22 @@ OGRErr OGRSpatialReference::morphToESRI()
 
     if( pszProjCSName )
     {
-      pszGcsName = GetAttrValue( "GEOGCS" ); 
-      if(pszGcsName && !EQUALN( pszGcsName, "GCS_", 4 ) )
+      pszGcsName = GetAttrValue( "GEOGCS" );
+      if(pszGcsName && !STARTS_WITH_CI(pszGcsName, "GCS_") )
       {
-        char* newGcsName = (char *) CPLMalloc(strlen(pszGcsName) + 5);
+        char* newGcsName = static_cast<char *>(
+            CPLMalloc(strlen(pszGcsName) + 5) );
         strcpy( newGcsName, "GCS_" );
         strcat(newGcsName, pszGcsName);
         SetNewName( this, "GEOGCS", newGcsName );
         CPLFree( newGcsName );
-        pszGcsName = GetAttrValue("GEOGCS" );
-      }    
+        pszGcsName = GetAttrValue( "GEOGCS" );
+      }
       RemapGeogCSName(this, pszGcsName);
 
-      // Specific processing and remapping 
+      // Specific processing and remapping
       pszProjection = GetAttrValue("PROJECTION");
-      if(pszProjection) 
+      if(pszProjection)
       {
         if(EQUAL(pszProjection,"Lambert_Conformal_Conic"))
         {
@@ -1443,7 +1483,8 @@ OGRErr OGRSpatialReference::morphToESRI()
               {
                 OGR_SRSNode *poNewParm = new OGR_SRSNode( "PARAMETER" );
                 poNewParm->AddChild( new OGR_SRSNode( "standard_parallel_1" ) );
-                poNewParm->AddChild( new OGR_SRSNode( poParameter->GetChild(1)->GetValue() ) );
+                poNewParm->AddChild( new OGR_SRSNode(
+                    poParameter->GetChild(1)->GetValue() ) );
                 poProjCS->AddChild( poNewParm );
               }
             }
@@ -1455,7 +1496,7 @@ OGRErr OGRSpatialReference::morphToESRI()
           int iChild = FindProjParm( SRS_PP_STANDARD_PARALLEL_1, poProjCS );
           if(iChild < 0)
             iChild = FindProjParm( SRS_PP_PSEUDO_STD_PARALLEL_1, poProjCS );
-            
+
           if(iChild >= 0)
           {
             const OGR_SRSNode *poParameter = poProjCS->GetChild(iChild);
@@ -1488,9 +1529,9 @@ OGRErr OGRSpatialReference::morphToESRI()
 OGRErr OSRMorphToESRI( OGRSpatialReferenceH hSRS )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRMorphToESRI", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRMorphToESRI", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->morphToESRI();
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->morphToESRI();
 }
 
 /************************************************************************/
@@ -1510,10 +1551,10 @@ OGRErr OSRMorphToESRI( OGRSpatialReferenceH hSRS )
  * translation of EPSG to WKT for the CT specification.
  *
  * Starting with GDAL 1.9.0, missing parameters in TOWGS84, DATUM or GEOGCS
- * nodes can be added to the WKT, comparing existing WKT parameters to GDAL's 
+ * nodes can be added to the WKT, comparing existing WKT parameters to GDAL's
  * databases.  Note that this optional procedure is very conservative and should
- * not introduce false information into the WKT defintion (altough caution
- * should be advised when activating it). Needs the Configuration Option 
+ * not introduce false information into the WKT definition (although caution
+ * should be advised when activating it). Needs the Configuration Option
  * GDAL_FIX_ESRI_WKT be set to one of the following values (TOWGS84 is
  * recommended for proper datum shift calculations):
  *
@@ -1527,7 +1568,7 @@ OGRErr OSRMorphToESRI( OGRSpatialReferenceH hSRS )
  * <tr><td>  </td><td><b>GEOGCS</b></td><td>  </td><td>
  * Adds EPSG AUTHORITY nodes and sets GEOGCS, DATUM and SPHEROID
  * names to OGR spec. Effectively replaces GEOGCS node with the result of
- * importFromEPSG(n), using EPSG code n corresponding to the existing GEOGCS. 
+ * importFromEPSG(n), using EPSG code n corresponding to the existing GEOGCS.
  * Does not impact PROJCS values.</td></tr>
  * </table>
  *
@@ -1539,10 +1580,6 @@ OGRErr OSRMorphToESRI( OGRSpatialReferenceH hSRS )
 OGRErr OGRSpatialReference::morphFromESRI()
 
 {
-    OGRErr      eErr = OGRERR_NONE;
-    OGR_SRSNode *poDatum;
-    char        *pszDatumOrig = NULL;
-
     if( GetRoot() == NULL )
         return OGRERR_NONE;
 
@@ -1551,19 +1588,20 @@ OGRErr OGRSpatialReference::morphFromESRI()
 /* -------------------------------------------------------------------- */
 /*      Save original datum name for later                              */
 /* -------------------------------------------------------------------- */
-    poDatum = GetAttrNode( "DATUM" );
-    if( poDatum != NULL ) 
+    OGR_SRSNode *poDatum = GetAttrNode( "DATUM" );
+    char *pszDatumOrig = NULL;
+    if( poDatum != NULL )
     {
         poDatum = poDatum->GetChild(0);
         pszDatumOrig = CPLStrdup( poDatum->GetValue() );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Translate DATUM keywords that are oddly named.                  */
 /* -------------------------------------------------------------------- */
-    GetRoot()->applyRemapper( "DATUM", 
-                              (char **)papszDatumMapping+1,
-                              (char **)papszDatumMapping+2, 3 );
+    GetRoot()->applyRemapper( "DATUM",
+                              const_cast<char **>(papszDatumMapping+1),
+                              const_cast<char **>(papszDatumMapping+2), 3 );
 
 /* -------------------------------------------------------------------- */
 /*      Try to remove any D_ in front of the datum name.                */
@@ -1574,7 +1612,7 @@ OGRErr OGRSpatialReference::morphFromESRI()
 
     if( poDatum != NULL )
     {
-        if( EQUALN(poDatum->GetValue(),"D_",2) )
+        if( STARTS_WITH_CI(poDatum->GetValue(), "D_") )
         {
             char *pszNewValue = CPLStrdup( poDatum->GetValue() + 2 );
             poDatum->SetValue( pszNewValue );
@@ -1585,9 +1623,9 @@ OGRErr OGRSpatialReference::morphFromESRI()
 /* -------------------------------------------------------------------- */
 /*      Translate some SPHEROID keywords that are oddly named.          */
 /* -------------------------------------------------------------------- */
-    GetRoot()->applyRemapper( "SPHEROID", 
-                              (char **)apszSpheroidMapping+1,
-                              (char **)apszSpheroidMapping+0, 2 );
+    GetRoot()->applyRemapper( "SPHEROID",
+                              const_cast<char **>(apszSpheroidMapping+1),
+                              const_cast<char **>(apszSpheroidMapping+0), 2 );
 
 /* -------------------------------------------------------------------- */
 /*      Split Lambert_Conformal_Conic into 1SP or 2SP form.             */
@@ -1599,16 +1637,16 @@ OGRErr OGRSpatialReference::morphFromESRI()
 /*      poor test.                                                      */
 /* -------------------------------------------------------------------- */
     const char *pszProjection = GetAttrValue("PROJECTION");
-    
+
     if( pszProjection != NULL
         && EQUAL(pszProjection,"Lambert_Conformal_Conic") )
     {
-        if( GetProjParm( SRS_PP_STANDARD_PARALLEL_1, 1000.0 ) != 1000.0 
+        if( GetProjParm( SRS_PP_STANDARD_PARALLEL_1, 1000.0 ) != 1000.0
             && GetProjParm( SRS_PP_STANDARD_PARALLEL_2, 1000.0 ) != 1000.0 )
-            SetNode( "PROJCS|PROJECTION", 
+            SetNode( "PROJCS|PROJECTION",
                      SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP );
         else
-            SetNode( "PROJCS|PROJECTION", 
+            SetNode( "PROJCS|PROJECTION",
                      SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP );
 
         pszProjection = GetAttrValue("PROJECTION");
@@ -1629,7 +1667,7 @@ OGRErr OGRSpatialReference::morphFromESRI()
     if( pszProjection != NULL
         && EQUAL(pszProjection,"Hotine_Oblique_Mercator_Azimuth_Center") )
     {
-        SetProjParm( SRS_PP_RECTIFIED_GRID_ANGLE , 
+        SetProjParm( SRS_PP_RECTIFIED_GRID_ANGLE ,
                      GetProjParm( SRS_PP_AZIMUTH, 0.0 ) );
         FixupOrdering();
     }
@@ -1638,39 +1676,39 @@ OGRErr OGRSpatialReference::morphFromESRI()
 /*      Remap Albers, Mercator and Polar Stereographic parameters.      */
 /* -------------------------------------------------------------------- */
     if( pszProjection != NULL && EQUAL(pszProjection,"Albers") )
-        GetRoot()->applyRemapper( 
+        GetRoot()->applyRemapper(
             "PARAMETER", (char **)apszAlbersMapping + 0,
             (char **)apszAlbersMapping + 1, 2 );
 
-    if( pszProjection != NULL 
+    if( pszProjection != NULL
         && (EQUAL(pszProjection,SRS_PT_EQUIDISTANT_CONIC) ||
             EQUAL(pszProjection,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) ||
             EQUAL(pszProjection,SRS_PT_AZIMUTHAL_EQUIDISTANT) ||
             EQUAL(pszProjection,SRS_PT_SINUSOIDAL) ||
             EQUAL(pszProjection,SRS_PT_ROBINSON) ) )
-        GetRoot()->applyRemapper( 
-            "PARAMETER", (char **)apszECMapping + 0,
-            (char **)apszECMapping + 1, 2 );
+        GetRoot()->applyRemapper(
+            "PARAMETER", const_cast<char **>(apszECMapping + 0),
+            const_cast<char **>(apszECMapping + 1), 2 );
 
     if( pszProjection != NULL && EQUAL(pszProjection,"Orthographic") )
-        GetRoot()->applyRemapper( 
-            "PARAMETER", (char **)apszOrthographicMapping + 0,
-            (char **)apszOrthographicMapping + 1, 2 );
+        GetRoot()->applyRemapper(
+            "PARAMETER", const_cast<char **>(apszOrthographicMapping + 0),
+            const_cast<char **>(apszOrthographicMapping + 1), 2 );
 
-    if( pszProjection != NULL 
-        && EQUALN(pszProjection,"Stereographic_",14) 
-        && EQUALN(pszProjection+strlen(pszProjection)-5,"_Pole",5) )
-        GetRoot()->applyRemapper( 
-            "PARAMETER", 
-            (char **)apszPolarStereographicMapping + 0, 
-            (char **)apszPolarStereographicMapping + 1, 2 );
+    if( pszProjection != NULL
+        && STARTS_WITH_CI(pszProjection, "Stereographic_")
+        && STARTS_WITH_CI(pszProjection+strlen(pszProjection)-5, "_Pole") )
+        GetRoot()->applyRemapper(
+            "PARAMETER",
+            const_cast<char **>(apszPolarStereographicMapping + 0),
+            const_cast<char **>(apszPolarStereographicMapping + 1), 2 );
 
 /* -------------------------------------------------------------------- */
 /*      Remap south and north polar stereographic to one value.         */
 /* -------------------------------------------------------------------- */
     if( pszProjection != NULL
-        && EQUALN(pszProjection,"Stereographic_",14)
-        && EQUALN(pszProjection+strlen(pszProjection)-5,"_Pole",5) )
+        && STARTS_WITH_CI(pszProjection, "Stereographic_")
+        && STARTS_WITH_CI(pszProjection+strlen(pszProjection)-5, "_Pole") )
     {
         SetNode( "PROJCS|PROJECTION", SRS_PT_POLAR_STEREOGRAPHIC );
         pszProjection = GetAttrValue("PROJECTION");
@@ -1692,10 +1730,10 @@ OGRErr OGRSpatialReference::morphFromESRI()
 /* -------------------------------------------------------------------- */
 #ifdef notdef
     if( pszProjection != NULL && EQUAL(pszProjection,"Equidistant_Cylindrical") )
-        GetRoot()->applyRemapper( 
-            "PARAMETER", 
-            (char **)apszPolarStereographicMapping + 0, 
-            (char **)apszPolarStereographicMapping + 1, 2 );
+        GetRoot()->applyRemapper(
+            "PARAMETER",
+            const_cast<char **>(apszPolarStereographicMapping + 0),
+            const_cast<char **>(apszPolarStereographicMapping + 1), 2 );
 #endif
 
 /* -------------------------------------------------------------------- */
@@ -1723,12 +1761,15 @@ OGRErr OGRSpatialReference::morphFromESRI()
         ( EQUAL( pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP ) ||
           EQUAL( pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP ) ) )
     {
-        GetRoot()->applyRemapper( 
-            "PARAMETER", (char **)apszLambertConformalConicMapping + 0,
-            (char **)apszLambertConformalConicMapping + 1, 2 );
+        GetRoot()->applyRemapper(
+            "PARAMETER",
+            const_cast<char **>(apszLambertConformalConicMapping + 0),
+            const_cast<char **>(apszLambertConformalConicMapping + 1),
+            2 );
 
-        /* LCC 1SP has duplicated parameters Standard_Parallel_1 and Latitude_Of_Origin */
-        /* http://trac.osgeo.org/gdal/ticket/2072 */
+        // LCC 1SP has duplicated parameters Standard_Parallel_1 and
+        // Latitude_Of_Origin.
+        // http://trac.osgeo.org/gdal/ticket/2072
         if( EQUAL( pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP ) )
         {
             OGR_SRSNode *poPROJCS = GetAttrNode( "PROJCS" );
@@ -1744,31 +1785,32 @@ OGRErr OGRSpatialReference::morphFromESRI()
                 }
             }
         }
-
     }
 
 /* -------------------------------------------------------------------- */
 /*      Translate PROJECTION keywords that are misnamed.                */
 /* -------------------------------------------------------------------- */
-    GetRoot()->applyRemapper( "PROJECTION", 
-                              (char **)apszProjMapping,
-                              (char **)apszProjMapping+1, 2 );
-    
+    GetRoot()->applyRemapper( "PROJECTION",
+                              const_cast<char **>(apszProjMapping),
+                              const_cast<char **>(apszProjMapping+1),
+                              2 );
+
 /* -------------------------------------------------------------------- */
 /*      Translate DATUM keywords that are misnamed.                     */
 /* -------------------------------------------------------------------- */
     InitDatumMappingTable();
 
-    GetRoot()->applyRemapper( "DATUM", 
-                              (char **)papszDatumMapping+1,
-                              (char **)papszDatumMapping+2, 3 );
+    GetRoot()->applyRemapper( "DATUM",
+                              const_cast<char **>(papszDatumMapping+1),
+                              const_cast<char **>(papszDatumMapping+2),
+                              3 );
 
 /* -------------------------------------------------------------------- */
 /*      Special case for Peru96 related SRS that should use the         */
 /*      Peru96 DATUM, but in ESRI world, both Peru96 and SIRGAS-Chile   */
 /*      are translated as D_SIRGAS-Chile.                               */
 /* -------------------------------------------------------------------- */
-    int bPeru96Datum = FALSE;
+    bool bPeru96Datum = false;
     if( poDatum != NULL && EQUAL(poDatum->GetValue(), "SIRGAS_Chile") )
     {
         const char* pszSRSName = GetAttrValue("PROJCS");
@@ -1776,7 +1818,7 @@ OGRErr OGRSpatialReference::morphFromESRI()
             pszSRSName = GetAttrValue("GEOGCS");
         if( strstr(pszSRSName, "Peru96") )
         {
-            bPeru96Datum = TRUE;
+            bPeru96Datum = true;
             poDatum->SetValue( "Peru96" );
         }
     }
@@ -1786,15 +1828,16 @@ OGRErr OGRSpatialReference::morphFromESRI()
 /* -------------------------------------------------------------------- */
     /* TODO test more ESRI WKT; also add PROJCS */
 
-    /* Check GDAL_FIX_ESRI_WKT config option (default=NO); if YES, set to DATUM */
+    // Check GDAL_FIX_ESRI_WKT config option (default=NO); if YES, set to DATUM
     const char *pszFixWktConfig=CPLGetConfigOption( "GDAL_FIX_ESRI_WKT", "NO" );
     if ( EQUAL(pszFixWktConfig,"YES") )
         pszFixWktConfig = "DATUM";
 
-    if( !EQUAL(pszFixWktConfig, "NO") && poDatum != NULL )
-    { 
-        CPLDebug( "OGR_ESRI", 
-                  "morphFromESRI() looking for missing TOWGS84, datum=%s, config=%s",
+    if( !EQUAL(pszFixWktConfig, "NO") && poDatum != NULL && pszDatumOrig != NULL )
+    {
+        CPLDebug( "OGR_ESRI",
+                  "morphFromESRI() looking for missing TOWGS84, datum=%s, "
+                  "config=%s",
                   pszDatumOrig, pszFixWktConfig );
 
         /* Special case for WGS84 and other common GCS? */
@@ -1806,10 +1849,10 @@ OGRErr OGRSpatialReference::morphFromESRI()
             {
                 const char *pszFilename = NULL;
                 char **papszRecord = NULL;
-                
+
                 /* look for GEOGCS corresponding to this datum */
                 pszFilename = CSVFilename("gcs.csv");
-                papszRecord = CSVScanFileByName( pszFilename, "DATUM_CODE",  
+                papszRecord = CSVScanFileByName( pszFilename, "DATUM_CODE",
                                                  DMGetEPSGCode(i), CC_Integer );
                 if ( papszRecord != NULL )
                 {
@@ -1823,117 +1866,128 @@ OGRErr OGRSpatialReference::morphFromESRI()
                                                      CSVGetFileFieldId(pszFilename,"COORD_REF_SYS_CODE")) );
                     // int bDeprecated = atoi( CSLGetField( papszRecord,
                     //                                      CSVGetFileFieldId(pszFilename,"DEPRECATED")) );
-                    
-                    CPLDebug( "OGR_ESRI", "morphFromESRI() got GEOGCS node #%d", nGeogCS );
+
+                    CPLDebug( "OGR_ESRI", "morphFromESRI() got GEOGCS node #%d",
+                              nGeogCS );
 
                     // if ( nGeogCS >= 1 && bDeprecated == 0 )
                     if ( nGeogCS >= 1 )
                     {
                         OGRSpatialReference oSRSTemp;
                         if ( oSRSTemp.importFromEPSG( nGeogCS ) == OGRERR_NONE )
-                        {                        
-                            /* make clone of GEOGCS and strip CT parms for testing */
-                            OGRSpatialReference *poSRSTemp2 = NULL;
-                            int bIsSame = FALSE;
+                        {
+                            // Clone of GEOGCS and strip CT parms for testing.
                             char *pszOtherValue = NULL;
                             double dfThisValue, dfOtherValue;
                             OGR_SRSNode *poNode = NULL;
 
-                            poSRSTemp2 = oSRSTemp.CloneGeogCS();
+                            OGRSpatialReference *poSRSTemp2 =
+                                oSRSTemp.CloneGeogCS();
                             poSRSTemp2->StripCTParms();
-                            bIsSame = this->IsSameGeogCS( poSRSTemp2 );
+                            bool bIsSame =
+                                CPL_TO_BOOL(IsSameGeogCS( poSRSTemp2 ));
                             exportToWkt ( &pszOtherValue );
-                            CPLDebug( "OGR_ESRI", 
-                                      "morphFromESRI() got SRS %s, matching: %d", 
-                                      pszOtherValue, bIsSame );
+                            CPLDebug( "OGR_ESRI",
+                                      "morphFromESRI() got SRS %s, matching: %d",
+                                      pszOtherValue, static_cast<int>(bIsSame) );
                             CPLFree( pszOtherValue );
                             delete poSRSTemp2;
 
-                            /* clone GEOGCS from original if they match and if allowed */
+                            // Clone GEOGCS from original if they match and if
+                            // allowed.
                             if ( EQUAL(pszFixWktConfig,"GEOGCS")
                                  && bIsSame )
                             {
                                 this->CopyGeogCSFrom( &oSRSTemp );
-                                CPLDebug( "OGR_ESRI", 
-                                          "morphFromESRI() cloned GEOGCS from EPSG:%d",
+                                CPLDebug( "OGR_ESRI",
+                                          "morphFromESRI() cloned GEOGCS "
+                                          "from EPSG:%d",
                                           nGeogCS );
                                 /* exit loop */
                                 break;
-                            }   
-                            /* else try to copy only DATUM or TOWGS84 
-                               we got here either because of config option or 
+                            }
+                            /* else try to copy only DATUM or TOWGS84
+                               we got here either because of config option or
                                GEOGCS are not strictly equal */
-                            else if ( EQUAL(pszFixWktConfig,"GEOGCS") || 
+                            else if ( EQUAL(pszFixWktConfig,"GEOGCS") ||
                                       EQUAL(pszFixWktConfig,"DATUM") ||
                                       EQUAL(pszFixWktConfig,"TOWGS84") )
                             {
-                                /* test for matching SPHEROID, because there can be 2 datums with same ESRI name 
+                                /* test for matching SPHEROID, because there can be 2 datums with same ESRI name
                                    but different spheroids (e.g. EPSG:4618 and EPSG:4291) - see bug #4345 */
                                 /* instead of testing for matching SPHEROID name (which can be error-prone), test
                                    for matching parameters (semi-major and inverse flattening ) - see bug #4673 */
-                                bIsSame = TRUE;
+                                bIsSame = true;
                                 dfThisValue = this->GetSemiMajor();
                                 dfOtherValue = oSRSTemp.GetSemiMajor();
                                 if ( ABS( dfThisValue - dfOtherValue ) > 0.01 )
-                                    bIsSame = FALSE;
-                                CPLDebug( "OGR_ESRI", 
-                                          "morphFromESRI() SemiMajor: this = %.15g other = %.15g", 
+                                    bIsSame = false;
+                                CPLDebug( "OGR_ESRI",
+                                          "morphFromESRI() SemiMajor: "
+                                          "this = %.15g other = %.15g",
                                           dfThisValue, dfOtherValue );
                                 dfThisValue = this->GetInvFlattening();
                                 dfOtherValue = oSRSTemp.GetInvFlattening();
                                 if ( ABS( dfThisValue - dfOtherValue ) > 0.0001 )
-                                    bIsSame = FALSE;
-                                CPLDebug( "OGR_ESRI", 
-                                          "morphFromESRI() InvFlattening: this = %g other = %g", 
+                                    bIsSame = false;
+                                CPLDebug( "OGR_ESRI",
+                                          "morphFromESRI() InvFlattening: "
+                                          "this = %g other = %g",
                                           dfThisValue, dfOtherValue );
 
                                 if ( bIsSame )
                                 {
-                                    /* test for matching PRIMEM, because there can be 2 datums with same ESRI name 
+                                    /* test for matching PRIMEM, because there can be 2 datums with same ESRI name
                                        but different prime meridian (e.g. EPSG:4218 and EPSG:4802)  - see bug #4378 */
                                     /* instead of testing for matching PRIMEM name (which can be error-prone), test
                                        for matching value - see bug #4673 */
                                     dfThisValue = this->GetPrimeMeridian();
                                     dfOtherValue = oSRSTemp.GetPrimeMeridian();
-                                    CPLDebug( "OGR_ESRI", 
-                                              "morphFromESRI() PRIMEM: this = %.15g other = %.15g", 
+                                    CPLDebug( "OGR_ESRI",
+                                              "morphFromESRI() PRIMEM: "
+                                              "this = %.15g other = %.15g",
                                               dfThisValue, dfOtherValue );
-                                    if ( ABS( dfThisValue - dfOtherValue ) > 0.0001 )
-                                        bIsSame = FALSE;
+                                    if ( ABS( dfThisValue - dfOtherValue )
+                                         > 0.0001 )
+                                        bIsSame = false;
                                 }
-                
-                                /* found a matching spheroid */ 
+
+                                /* found a matching spheroid */
                                 if ( bIsSame )
                                 {
                                     /* clone DATUM */
-                                    if ( EQUAL(pszFixWktConfig,"GEOGCS") || 
+                                    if ( EQUAL(pszFixWktConfig,"GEOGCS") ||
                                          EQUAL(pszFixWktConfig,"DATUM")  )
                                     {
-                                        OGR_SRSNode *poGeogCS = this->GetAttrNode( "GEOGCS" ); 
-                                        const OGR_SRSNode *poDatumOther = oSRSTemp.GetAttrNode( "DATUM" );  
-                                        if ( poGeogCS && poDatumOther ) 
+                                        OGR_SRSNode *poGeogCS = this->GetAttrNode( "GEOGCS" );
+                                        const OGR_SRSNode *poDatumOther =
+                                            oSRSTemp.GetAttrNode( "DATUM" );
+                                        if ( poGeogCS && poDatumOther )
                                         {
                                             /* make sure we preserve the position of the DATUM node */
-                                            int nPos = poGeogCS->FindChild( "DATUM" );
+                                            const int nPos =
+                                                poGeogCS->FindChild( "DATUM" );
                                             if ( nPos >= 0 )
                                             {
                                                 poGeogCS->DestroyChild( nPos );
-                                                poGeogCS->InsertChild( poDatumOther->Clone(), nPos );
-                                                CPLDebug( "OGR_ESRI", 
+                                                poGeogCS->InsertChild(
+                                                    poDatumOther->Clone(),
+                                                    nPos );
+                                                CPLDebug( "OGR_ESRI",
                                                           "morphFromESRI() cloned DATUM from EPSG:%d",
                                                           nGeogCS );
                                             }
                                         }
-                                    } 
+                                    }
                                     /* just copy TOWGS84 */
                                     else if ( EQUAL(pszFixWktConfig,"TOWGS84") )
-                                    { 
+                                    {
                                         poNode=oSRSTemp.GetAttrNode( "DATUM|TOWGS84" );
-                                        if ( poNode ) 
+                                        if ( poNode )
                                         {
                                             poNode=poNode->Clone();
                                             GetAttrNode( "DATUM" )->AddChild( poNode );
-                                            CPLDebug( "OGR_ESRI", 
+                                            CPLDebug( "OGR_ESRI",
                                                       "morphFromESRI() found missing TOWGS84 from EPSG:%d",
                                                       nGeogCS );
                                         }
@@ -1945,13 +1999,14 @@ OGRErr OGRSpatialReference::morphFromESRI()
                         }
                     }
                 }
-            }         
+            }
         }
     }
 
     CPLFree( pszDatumOrig );
 
-    return eErr;
+    // TODO: Somehow track issues.
+    return OGRERR_NONE;
 }
 
 /************************************************************************/
@@ -1966,9 +2021,9 @@ OGRErr OGRSpatialReference::morphFromESRI()
 OGRErr OSRMorphFromESRI( OGRSpatialReferenceH hSRS )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRMorphFromESRI", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRMorphFromESRI", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->morphFromESRI();
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->morphFromESRI();
 }
 
 /************************************************************************/
@@ -1976,7 +2031,8 @@ OGRErr OSRMorphFromESRI( OGRSpatialReferenceH hSRS )
 /*                                                                      */
 /*      Set an esri name                                                */
 /************************************************************************/
-void SetNewName( OGRSpatialReference* pOgr, const char* keyName, const char* newName )
+void SetNewName( OGRSpatialReference* pOgr, const char* keyName,
+                 const char* newName )
 {
     OGR_SRSNode *poNode = pOgr->GetAttrNode( keyName );
     OGR_SRSNode *poNodeChild = NULL;
@@ -1991,12 +2047,14 @@ void SetNewName( OGRSpatialReference* pOgr, const char* keyName, const char* new
 /*                                                                      */
 /*      Convert Img projcs names to ESRI style                          */
 /************************************************************************/
-int RemapImgWGSProjcsName( OGRSpatialReference* pOgr, const char* pszProjCSName, const char* pszProgCSName )
+int RemapImgWGSProjcsName( OGRSpatialReference* pOgr, const char* pszProjCSName,
+                           const char* pszProgCSName )
 {
     if(EQUAL(pszProgCSName, "WGS_1972") || EQUAL(pszProgCSName, "WGS_1984") )
     {
-        char* newName = (char *) CPLMalloc(strlen(pszProjCSName) + 10);
-        sprintf( newName, "%s_", pszProgCSName );
+        char* newName = static_cast<char *>(
+            CPLMalloc(strlen(pszProjCSName) + 10) );
+        snprintf( newName, strlen(pszProjCSName) + 10, "%s_", pszProgCSName );
         strcat(newName, pszProjCSName);
         SetNewName( pOgr, "PROJCS", newName );
         CPLFree( newName );
@@ -2011,16 +2069,16 @@ int RemapImgWGSProjcsName( OGRSpatialReference* pOgr, const char* pszProjCSName,
 /*      Convert Img UTM names to ESRI style                             */
 /************************************************************************/
 
-int RemapImgUTMNames( OGRSpatialReference* pOgr, const char* pszProjCSName, const char* pszProgCSName, 
+int RemapImgUTMNames( OGRSpatialReference* pOgr, const char* pszProjCSName,
+                      const char* pszProgCSName,
                       char **mappingTable )
 {
-    long i;
-    long iIndex = -1;
-    for( i = 0; mappingTable[i] != NULL; i += 5 )
+    int iIndex = -1;
+    for( int i = 0; mappingTable[i] != NULL; i += 5 )
     {
         if( EQUAL(pszProjCSName, mappingTable[i]) )
         {
-            long j = i;
+            int j = i;
             while(mappingTable[j] != NULL && EQUAL(mappingTable[i], mappingTable[j]))
             {
                 if( EQUAL(pszProgCSName, mappingTable[j+1]) )
@@ -2066,12 +2124,12 @@ int RemapImgUTMNames( OGRSpatialReference* pOgr, const char* pszProjCSName, cons
 /*      Convert a name to ESRI style name                               */
 /************************************************************************/
 
-int RemapNameBasedOnKeyName( OGRSpatialReference* pOgr, const char* pszName, const char* pszkeyName, 
+int RemapNameBasedOnKeyName( OGRSpatialReference* pOgr, const char* pszName,
+                             const char* pszkeyName,
                              char **mappingTable )
 {
-    long i;
-    long iIndex = -1;
-    for( i = 0; mappingTable[i] != NULL; i += 2 )
+    int iIndex = -1;
+    for( int i = 0; mappingTable[i] != NULL; i += 2 )
     {
         if( EQUAL(pszName, mappingTable[i]) )
         {
@@ -2079,7 +2137,7 @@ int RemapNameBasedOnKeyName( OGRSpatialReference* pOgr, const char* pszName, con
             break;
         }
     }
-    if(iIndex >= 0) 
+    if(iIndex >= 0)
     {
         OGR_SRSNode *poNode = pOgr->GetAttrNode( pszkeyName );
         OGR_SRSNode *poNodeChild = NULL;
@@ -2097,19 +2155,19 @@ int RemapNameBasedOnKeyName( OGRSpatialReference* pOgr, const char* pszName, con
 /*      Convert a name to ESRI style name                               */
 /************************************************************************/
 
-int RemapNamesBasedOnTwo( OGRSpatialReference* pOgr, const char* name1, const char* name2, 
-                          char **mappingTable, long nTableStepSize, 
+int RemapNamesBasedOnTwo( OGRSpatialReference* pOgr, const char* name1,
+                          const char* name2,
+                          char **mappingTable, int nTableStepSize,
                           char** pszkeyNames, long nKeys )
 {
-    long i, n, n1;
-    long iIndex = -1;
-    for( i = 0; mappingTable[i] != NULL; i += nTableStepSize )
+    int iIndex = -1;
+    for( int i = 0; mappingTable[i] != NULL; i += nTableStepSize )
     {
-        n = strlen(name1);
-        n1 = strlen(mappingTable[i]); 
+        const size_t n = strlen(name1);
+        const size_t n1 = strlen(mappingTable[i]);
         if( EQUALN(name1, mappingTable[i], n1<=n? n1 : n) )
         {
-            long j = i;
+            int j = i;
             while(mappingTable[j] != NULL && EQUAL(mappingTable[i], mappingTable[j]))
             {
                 if( EQUALN(name2, mappingTable[j+1], strlen(mappingTable[j+1])) )
@@ -2125,7 +2183,7 @@ int RemapNamesBasedOnTwo( OGRSpatialReference* pOgr, const char* name1, const ch
     }
     if(iIndex >= 0)
     {
-        for( i = 0; i < nKeys; i ++ )
+        for( int i = 0; i < nKeys; i ++ )
         {
             OGR_SRSNode *poNode = pOgr->GetAttrNode( pszkeyNames[i] );
             OGR_SRSNode *poNodeChild = NULL;
@@ -2145,25 +2203,26 @@ int RemapNamesBasedOnTwo( OGRSpatialReference* pOgr, const char* name1, const ch
 /*      Convert a parameters to ESRI style name                         */
 /************************************************************************/
 
-int RemapPValuesBasedOnProjCSAndPName( OGRSpatialReference* pOgr, const char* pszProgCSName, 
+int RemapPValuesBasedOnProjCSAndPName( OGRSpatialReference* pOgr,
+                                       const char* pszProgCSName,
                                        char **mappingTable )
 {
-    long ret = 0;
+    int ret = 0;
     OGR_SRSNode *poPROJCS = pOgr->GetAttrNode( "PROJCS" );
     for( int i = 0; mappingTable[i] != NULL; i += 4 )
     {
-        while( mappingTable[i] != NULL && EQUALN(pszProgCSName, mappingTable[i], strlen(mappingTable[i])) )
+        while( mappingTable[i] != NULL &&
+               EQUALN(pszProgCSName, mappingTable[i], strlen(mappingTable[i])) )
         {
-            OGR_SRSNode *poParm;
             const char* pszParamName = mappingTable[i+1];
             const char* pszParamValue = mappingTable[i+2];
             for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
             {
-                poParm = poPROJCS->GetChild( iChild );
+                OGR_SRSNode *poParm = poPROJCS->GetChild( iChild );
 
-                if( EQUAL(poParm->GetValue(),"PARAMETER") 
-                    && poParm->GetChildCount() == 2 
-                    && EQUAL(poParm->GetChild(0)->GetValue(),pszParamName) 
+                if( EQUAL(poParm->GetValue(),"PARAMETER")
+                    && poParm->GetChildCount() == 2
+                    && EQUAL(poParm->GetChild(0)->GetValue(),pszParamName)
                     && EQUALN(poParm->GetChild(1)->GetValue(),pszParamValue, strlen(pszParamValue) ) )
                 {
                     poParm->GetChild(1)->SetValue( mappingTable[i+3] );
@@ -2185,23 +2244,24 @@ int RemapPValuesBasedOnProjCSAndPName( OGRSpatialReference* pOgr, const char* ps
 /*      Convert a parameters to ESRI style name                         */
 /************************************************************************/
 
-int RemapPNamesBasedOnProjCSAndPName( OGRSpatialReference* pOgr, const char* pszProgCSName, 
-                                                                     char **mappingTable )
+int RemapPNamesBasedOnProjCSAndPName( OGRSpatialReference* pOgr,
+                                      const char* pszProgCSName,
+                                      char **mappingTable )
 {
-  long ret = 0;
+  int ret = 0;
   OGR_SRSNode *poPROJCS = pOgr->GetAttrNode( "PROJCS" );
   for( int i = 0; mappingTable[i] != NULL; i += 3 )
   {
-    while( mappingTable[i] != NULL && EQUALN(pszProgCSName, mappingTable[i], strlen(mappingTable[i])) )
+    while( mappingTable[i] != NULL &&
+           EQUALN(pszProgCSName, mappingTable[i], strlen(mappingTable[i])) )
     {
-      OGR_SRSNode *poParm;
       const char* pszParamName = mappingTable[i+1];
       for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
       {
-          poParm = poPROJCS->GetChild( iChild );
+          OGR_SRSNode *poParm = poPROJCS->GetChild( iChild );
 
-          if( EQUAL(poParm->GetValue(),"PARAMETER") 
-              && poParm->GetChildCount() == 2 
+          if( EQUAL(poParm->GetValue(),"PARAMETER")
+              && poParm->GetChildCount() == 2
               && EQUAL(poParm->GetChild(0)->GetValue(),pszParamName) )
           {
               poParm->GetChild(0)->SetValue( mappingTable[i+2] );
@@ -2222,24 +2282,24 @@ int RemapPNamesBasedOnProjCSAndPName( OGRSpatialReference* pOgr, const char* psz
 /*                                                                      */
 /*      Delete non-ESRI parameters                                      */
 /************************************************************************/
-int DeleteParamBasedOnPrjName( OGRSpatialReference* pOgr, const char* pszProjectionName, 
+int DeleteParamBasedOnPrjName( OGRSpatialReference* pOgr,
+                               const char* pszProjectionName,
                                char **mappingTable )
 {
-    long iIndex = -1, ret = -1;
+    int ret = -1;
     for( int i = 0; mappingTable[i] != NULL; i += 2 )
     {
         if( EQUALN(pszProjectionName, mappingTable[i], strlen(mappingTable[i])) )
         {
             OGR_SRSNode *poPROJCS = pOgr->GetAttrNode( "PROJCS" );
-            OGR_SRSNode *poParm;
             const char* pszParamName = mappingTable[i+1];
-            iIndex = -1;
+            int iIndex = -1;
             for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
             {
-                poParm = poPROJCS->GetChild( iChild );
+                OGR_SRSNode *poParm = poPROJCS->GetChild( iChild );
 
-                if( EQUAL(poParm->GetValue(),"PARAMETER") 
-                    && poParm->GetChildCount() == 2 
+                if( EQUAL(poParm->GetValue(),"PARAMETER")
+                    && poParm->GetChildCount() == 2
                     && EQUAL(poParm->GetChild(0)->GetValue(),pszParamName) )
                 {
                     iIndex = iChild;
@@ -2260,29 +2320,28 @@ int DeleteParamBasedOnPrjName( OGRSpatialReference* pOgr, const char* pszProject
 /*                                                                      */
 /*      Add ESRI style parameters                                       */
 /************************************************************************/
-int AddParamBasedOnPrjName( OGRSpatialReference* pOgr, const char* pszProjectionName, 
+int AddParamBasedOnPrjName( OGRSpatialReference* pOgr, const char* pszProjectionName,
                             char **mappingTable )
 {
-    long ret = -1;
+    int ret = -1;
     OGR_SRSNode *poPROJCS = pOgr->GetAttrNode( "PROJCS" );
     for( int i = 0; mappingTable[i] != NULL; i += 3 )
     {
         if( EQUALN(pszProjectionName, mappingTable[i], strlen(mappingTable[i])) )
         {
-            OGR_SRSNode *poParm;
-            int exist = 0;
+            bool exist = false;
             for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
             {
-                poParm = poPROJCS->GetChild( iChild );
+                OGR_SRSNode *poParm = poPROJCS->GetChild( iChild );
 
-                if( EQUAL(poParm->GetValue(),"PARAMETER") 
-                    && poParm->GetChildCount() == 2 
+                if( EQUAL(poParm->GetValue(),"PARAMETER")
+                    && poParm->GetChildCount() == 2
                     && EQUAL(poParm->GetChild(0)->GetValue(),mappingTable[i+1]) )
-                    exist = 1;
+                    exist = true;
             }
-            if(!exist)
+            if( !exist )
             {
-                poParm = new OGR_SRSNode( "PARAMETER" );
+                OGR_SRSNode *poParm = new OGR_SRSNode( "PARAMETER" );
                 poParm->AddChild( new OGR_SRSNode( mappingTable[i+1] ) );
                 poParm->AddChild( new OGR_SRSNode( mappingTable[i+2] ) );
                 poPROJCS->AddChild( poParm );
@@ -2300,25 +2359,38 @@ int AddParamBasedOnPrjName( OGRSpatialReference* pOgr, const char* pszProjection
 /************************************************************************/
 int RemapGeogCSName( OGRSpatialReference* pOgr, const char *pszGeogCSName )
 {
-    static const char *keyNamesG[] = {
+    static const char * const keyNamesG[] = {
         "GEOGCS"};
     int ret = -1;
 
     const char* pszUnitName = pOgr->GetAttrValue( "GEOGCS|UNIT");
     if(pszUnitName)
-        ret = RemapNamesBasedOnTwo( pOgr, pszGeogCSName+4, pszUnitName, (char**)apszGcsNameMappingBasedOnUnit, 3, (char**)keyNamesG, 1);
+        // TODO(schwehr): Figure out a safer way to rename.
+        //   The casting away const here looks dangerous.
+        ret = RemapNamesBasedOnTwo(
+            pOgr, pszGeogCSName+4, pszUnitName,
+            const_cast<char**>(apszGcsNameMappingBasedOnUnit),
+            3, const_cast<char**>(keyNamesG), 1);
     if(ret < 0)
     {
         const char* pszPrimeName = pOgr->GetAttrValue("PRIMEM");
         if(pszPrimeName)
-            ret = RemapNamesBasedOnTwo( pOgr, pszGeogCSName+4, pszPrimeName, (char**)apszGcsNameMappingBasedPrime, 3, (char**)keyNamesG, 1);
+            ret = RemapNamesBasedOnTwo(
+                pOgr, pszGeogCSName+4, pszPrimeName,
+                const_cast<char**>(apszGcsNameMappingBasedPrime),
+                3, const_cast<char**>(keyNamesG), 1);
         if(ret < 0)
-            ret = RemapNameBasedOnKeyName( pOgr, pszGeogCSName+4, "GEOGCS", (char**)apszGcsNameMapping);
+            ret = RemapNameBasedOnKeyName(
+                pOgr, pszGeogCSName+4, "GEOGCS",
+                const_cast<char**>(apszGcsNameMapping) );
     }
     if(ret < 0)
     {
         const char* pszProjCS = pOgr->GetAttrValue( "PROJCS" );
-        ret = RemapNamesBasedOnTwo( pOgr, pszProjCS, pszGeogCSName, (char**)apszGcsNameMappingBasedOnProjCS, 3, (char**)keyNamesG, 1);
+        ret = RemapNamesBasedOnTwo(
+            pOgr, pszProjCS, pszGeogCSName,
+            const_cast<char**>(apszGcsNameMappingBasedOnProjCS),
+            3, const_cast<char**>(keyNamesG), 1);
     }
     return ret;
 }
@@ -2329,40 +2401,44 @@ int RemapGeogCSName( OGRSpatialReference* pOgr, const char *pszGeogCSName )
 /*      Search a ESRI State Plane WKT and import it.                    */
 /************************************************************************/
 
-OGRErr OGRSpatialReference::ImportFromESRIStatePlaneWKT(  int code, const char* datumName, const char* unitsName, int pcsCode, const char* csName )
+OGRErr OGRSpatialReference::ImportFromESRIStatePlaneWKT(
+    int code, const char* datumName, const char* unitsName,
+    int pcsCode, const char* csName )
 {
-    int i;
-    long searchCode = -1;
-
     /* if the CS name is known */
     if (code == 0 && !datumName && !unitsName && pcsCode == 32767 && csName)
     {
         char codeS[10];
-        if (FindCodeFromDict( "esri_StatePlane_extra.wkt", csName, codeS ) != OGRERR_NONE)
+        if (FindCodeFromDict( "esri_StatePlane_extra.wkt", csName, codeS )
+            != OGRERR_NONE)
             return OGRERR_FAILURE;
         return importFromDict( "esri_StatePlane_extra.wkt", codeS);
     }
 
+    int searchCode = -1;
+    if( unitsName == NULL )
+        unitsName = "";
+
     /* Find state plane prj str by pcs code only */
     if( code == 0 && !datumName && pcsCode != 32767 )
     {
-
         int unitCode = 1;
         if( EQUAL(unitsName, "international_feet") )
             unitCode = 3;
         else if( strstr(unitsName, "feet") || strstr(unitsName, "foot") )
             unitCode = 2;
-        for(i=0; statePlanePcsCodeToZoneCode[i] != 0; i+=2)
+
+        for(int i=0; statePlanePcsCodeToZoneCode[i] != 0; i+=2)
         {
             if( pcsCode == statePlanePcsCodeToZoneCode[i] )
             {
                 searchCode = statePlanePcsCodeToZoneCode[i+1];
                 int unitIndex =  searchCode % 10;
-                if( (unitCode == 1 && !(unitIndex == 0 || unitIndex == 1)) 
+                if( (unitCode == 1 && !(unitIndex == 0 || unitIndex == 1))
                     || (unitCode == 2 && !(unitIndex == 2 || unitIndex == 3 || unitIndex == 4 ))
                     || (unitCode == 3 && !(unitIndex == 5 || unitIndex == 6 )) )
                 {
-                    searchCode -= unitIndex; 
+                    searchCode -= unitIndex;
                     switch (unitIndex)
                     {
                       case 0:
@@ -2384,8 +2460,9 @@ OGRErr OGRSpatialReference::ImportFromESRIStatePlaneWKT(  int code, const char*
                             searchCode += 6;
                         break;
                       case 4:
-                        if(unitCode == 2)
-                            searchCode += 4;
+                        // FIXME? The following cond is not possible
+                        /*if(unitCode == 2)
+                            searchCode += 4;*/
                         break;
                     }
                 }
@@ -2395,17 +2472,26 @@ OGRErr OGRSpatialReference::ImportFromESRIStatePlaneWKT(  int code, const char*
     }
     else /* Find state plane prj str by all inputs. */
     {
-        /* Need to have a specail EPSG-ESRI zone code mapping first. */
-        for(i=0; statePlaneZoneMapping[i] != 0; i+=3)
+        if( code < 0 || code > INT_MAX / 10 )
+            return OGRERR_FAILURE;
+
+        /* Need to have a special EPSG-ESRI zone code mapping first. */
+        for(int i=0; statePlaneZoneMapping[i] != 0; i+=3)
         {
-            if( code == statePlaneZoneMapping[i] 
-                && (statePlaneZoneMapping[i+1] == -1 || pcsCode == statePlaneZoneMapping[i+1]))
+            if( code == statePlaneZoneMapping[i]
+                && (statePlaneZoneMapping[i+1] == -1 ||
+                    pcsCode == statePlaneZoneMapping[i+1]))
             {
                 code = statePlaneZoneMapping[i+2];
                 break;
             }
         }
-        searchCode = (long)code * 10;
+        searchCode = code * 10;
+        if (!datumName)
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "datumName is NULL.");
+            return OGRERR_FAILURE;
+        }
         if(EQUAL(datumName, "HARN"))
         {
             if( EQUAL(unitsName, "international_feet") )
@@ -2432,7 +2518,7 @@ OGRErr OGRSpatialReference::ImportFromESRIStatePlaneWKT(  int code, const char*
     if(searchCode > 0)
     {
         char codeS[10];
-        sprintf(codeS, "%d", (int)searchCode);
+        snprintf(codeS, sizeof(codeS), "%d", (int)searchCode);
         return importFromDict( "esri_StatePlane_extra.wkt", codeS);
     }
     return OGRERR_FAILURE;
@@ -2444,7 +2530,9 @@ OGRErr OGRSpatialReference::ImportFromESRIStatePlaneWKT(  int code, const char*
 /*      Search a ESRI State Plane WKT and import it.                    */
 /************************************************************************/
 
-OGRErr OGRSpatialReference::ImportFromESRIWisconsinWKT( const char* prjName, double centralMeridian, double latOfOrigin, const char* unitsName, const char* csName )
+OGRErr OGRSpatialReference::ImportFromESRIWisconsinWKT(
+    const char* prjName, double centralMeridian, double latOfOrigin,
+    const char* unitsName, const char* csName )
 {
     /* if the CS name is known */
     if (!prjName && !unitsName && csName)
@@ -2454,28 +2542,29 @@ OGRErr OGRSpatialReference::ImportFromESRIWisconsinWKT( const char* prjName, dou
             return OGRERR_FAILURE;
         return importFromDict( "esri_Wisconsin_extra.wkt", codeS);
     }
-    double* tableWISCRS;
-    if(EQUALN(prjName, "Lambert_Conformal_Conic", 22))
+    const double* tableWISCRS = NULL;
+    if(prjName != NULL && STARTS_WITH_CI(prjName, "Lambert_Conformal_Conic"))
         tableWISCRS = apszWISCRS_LCC_meter;
-    else if(EQUAL(prjName, SRS_PT_TRANSVERSE_MERCATOR))
+    else if(prjName != NULL && EQUAL(prjName, SRS_PT_TRANSVERSE_MERCATOR))
         tableWISCRS = apszWISCRS_TM_meter;
     else
         return OGRERR_FAILURE;
     int k = -1;
     for(int i=0; tableWISCRS[i] != 0; i+=3)
     {
-        if( fabs(centralMeridian - tableWISCRS[i]) <= 0.0000000001 && fabs(latOfOrigin - tableWISCRS[i+1]) <= 0.0000000001) 
+        if( fabs(centralMeridian - tableWISCRS[i]) <= 0.0000000001 &&
+            fabs(latOfOrigin - tableWISCRS[i+1]) <= 0.0000000001 )
         {
-            k = (long)tableWISCRS[i+2];
+            k = static_cast<int>(tableWISCRS[i+2]); // double to int ?
             break;
         }
     }
     if(k > 0)
     {
-        if(!EQUAL(unitsName, "meters"))
+        if(unitsName != NULL && !EQUAL(unitsName, "meters"))
             k += 100;
-        char codeS[10];
-        sprintf(codeS, "%d", k);
+        char codeS[10] = { '\0' };
+        snprintf(codeS, sizeof(codeS), "%d", k);
         return importFromDict( "esri_Wisconsin_extra.wkt", codeS);
     }
     return OGRERR_FAILURE;
@@ -2488,28 +2577,24 @@ OGRErr OGRSpatialReference::ImportFromESRIWisconsinWKT( const char* prjName, dou
 /************************************************************************/
 static int FindCodeFromDict( const char* pszDictFile, const char* CSName, char* code )
 {
-    const char *pszFilename;
-    FILE *fp;
-    OGRErr eErr = OGRERR_UNSUPPORTED_SRS;
-
 /* -------------------------------------------------------------------- */
 /*      Find and open file.                                             */
 /* -------------------------------------------------------------------- */
-    pszFilename = CPLFindFile( "gdal", pszDictFile );
+    const char *pszFilename = CPLFindFile( "gdal", pszDictFile );
     if( pszFilename == NULL )
         return OGRERR_UNSUPPORTED_SRS;
 
-    fp = VSIFOpen( pszFilename, "rb" );
+    VSILFILE *fp = VSIFOpenL( pszFilename, "rb" );
     if( fp == NULL )
         return OGRERR_UNSUPPORTED_SRS;
 
 /* -------------------------------------------------------------------- */
 /*      Process lines.                                                  */
 /* -------------------------------------------------------------------- */
-    const char *pszLine;
-
-    while( (pszLine = CPLReadLine(fp)) != NULL )
+    OGRErr eErr = OGRERR_UNSUPPORTED_SRS;
+    const char *pszLine = NULL;
 
+    while( (pszLine = CPLReadLineL(fp)) != NULL )
     {
         if( pszLine[0] == '#' )
             /* do nothing */;
@@ -2521,7 +2606,7 @@ static int FindCodeFromDict( const char* pszDictFile, const char* CSName, char*
           {
             strncpy( code, pszLine, pComma - pszLine);
             code[pComma - pszLine] = '\0';
-            eErr = OGRERR_NONE;  
+            eErr = OGRERR_NONE;
           }
           break;
         }
@@ -2530,7 +2615,7 @@ static int FindCodeFromDict( const char* pszDictFile, const char* CSName, char*
 /* -------------------------------------------------------------------- */
 /*      Cleanup                                                         */
 /* -------------------------------------------------------------------- */
-    VSIFClose( fp );
-    
+    VSIFCloseL( fp );
+
     return eErr;
 }
diff --git a/ogr/ogr_srs_esri_names.h b/ogr/ogr_srs_esri_names.h
index 964aeab..2a7181b 100644
--- a/ogr/ogr_srs_esri_names.h
+++ b/ogr/ogr_srs_esri_names.h
@@ -1,4 +1,4 @@
-static const char *apszGcsNameMapping[] = {
+static const char * const apszGcsNameMapping[] = {
 "North_American_Datum_1983", "GCS_North_American_1983",
 "North_American_Datum_1927", "GCS_North_American_1927",
 "NAD27_CONUS", "GCS_North_American_1927",
@@ -23,7 +23,7 @@ static const char *apszGcsNameMapping[] = {
 "Stockholm_1938", "GCS_RT38",
 "Latvia_1992", "GCS_LKS_1992",
 "Azores_Oriental_Islands_1995", "GCS_Azores_Oriental_1995",
-"Azores_Central_Islands_1948", "GCS_Azores_Central_1948", 
+"Azores_Central_Islands_1948", "GCS_Azores_Central_1948",
 "Azores_Central_Islands_1995", "GCS_Azores_Central_1995",
 "ATF", "GCS_ATF_Paris",
 //"ITRF_2000", "GCS_MONREF_1997",
@@ -62,7 +62,7 @@ static const char *apszGcsNameMapping[] = {
 "Carthage_Tunisia", "GCS_Carthage",
 "Deir_ez_Zor_2", "GCS_Deir_ez_Zor",
 "Old_Egyptian_1907", "GCS_Egypt_1907",
-"PSAD56", "GCS_Provisional_S_American_1956", 
+"PSAD56", "GCS_Provisional_S_American_1956",
 "Indian 1975", "GCS_Indian_1975",
 "Indian_1960_1", "GCS_Indian_1960",
 "Kalianpur_1937_1", "GCS_Kalianpur_1937",
@@ -105,7 +105,7 @@ static const char *apszGcsNameMapping[] = {
 "ETRS89", "GCS_ETRS_1989",
 NULL, NULL};
 
-static const char *apszGcsNameMappingBasedOnProjCS[] = {
+static const char * const apszGcsNameMappingBasedOnProjCS[] = {
 "EUREF_FIN_TM35FIN", "GCS_ETRS_1989", "GCS_EUREF_FIN",
 "Nord_Maroc_Degree", "GCS_Merchich", "GCS_Merchich_Degree",
 "Sahara_Degree", "GCS_Merchich", "GCS_Merchich_Degree",
@@ -122,7 +122,7 @@ NULL, NULL, NULL};
 
 
 
-static const char *apszGcsNameMappingBasedOnUnit[] = {
+static const char * const apszGcsNameMappingBasedOnUnit[] = {
 "Voirol_Unifie_1960", "Degree", "GCS_Voirol_Unifie_1960_Degree",
 "Voirol_1960", "Degree", "GCS_Voirol_Unifie_1960_Degree",
 "Voirol 1960", "Degree", "GCS_Voirol_Unifie_1960_Degree",
@@ -131,7 +131,7 @@ static const char *apszGcsNameMappingBasedOnUnit[] = {
 "NTF", "Grad", "GCS_NTF_Paris",
 NULL, NULL, NULL};
 
-static const char *apszGcsNameMappingBasedPrime[] = {
+static const char * const apszGcsNameMappingBasedPrime[] = {
 "Bern_1898", "Bern", "GCS_Bern_1898_Bern",
 "Madrid_1870", "Madrid", "GCS_Madrid_1870_Madrid",
 "MGI", "Ferro", "GCS_MGI_Ferro",
@@ -142,18 +142,18 @@ static const char *apszGcsNameMappingBasedPrime[] = {
 "Stockholm_1938", "Stockholm", "GCS_RT38_Stockholm",
 NULL, NULL, NULL};
 
-static const char *apszInvFlatteningMapping[] = {
-"293.464999999", "293.465", 
+static const char * const apszInvFlatteningMapping[] = {
+"293.464999999", "293.465",
 "293.465000003", "293.465",
 "293.465073361", "293.465",
 "293.466020000", "293.46602",
 "293.466021293", "293.46602",
 "293.4663077168286", "293.466307656",
 "293.4664236085404", "293.466307656",
-"294.2606763690", "294.260676369", 
-"294.9786981999", "294.9786982", 
+"294.2606763690", "294.260676369",
+"294.9786981999", "294.9786982",
 "294.978698213", "294.9786982",
-"295.9999999999", "296.0", 
+"295.9999999999", "296.0",
 "297.0000000000", "297.0",
 "297.0000000284", "297.0",
 "297.0000535480", "297.0",
@@ -181,19 +181,19 @@ static const char *apszInvFlatteningMapping[] = {
 "299.32496405862", "299.3249646",
 "299.32497531503", "299.3249646",
 "300.80158474106", "300.8017",
-"300.80169943849", "300.8017", 
+"300.80169943849", "300.8017",
 "300.80169999999", "300.8017",
 "300.80170000000", "300.8017",
 "300.80170009712", "300.8017",
 NULL, NULL};
 
-static const char *apszParamValueMapping[] = {
+static const char * const apszParamValueMapping[] = {
 "Cassini", "false_easting", "283799.9999", "283800.0",
 "Cassini", "false_easting", "132033.9199", "132033.92",
 "Cassini", "false_northing", "214499.9999", "214500.0",
-"Cassini", "false_northing", "62565.9599", "62565.95", 
-"Transverse_Mercator", "false_easting", "499999.1331", "500000.0",  
-"Transverse_Mercator", "false_easting", "299999.4798609", "300000.0", 
+"Cassini", "false_northing", "62565.9599", "62565.95",
+"Transverse_Mercator", "false_easting", "499999.1331", "500000.0",
+"Transverse_Mercator", "false_easting", "299999.4798609", "300000.0",
 "Transverse_Mercator", "false_northing", "399999.30648", "400000.0",
 "Transverse_Mercator", "false_northing", "499999.1331", "500000.0",
 "Transverse_Mercator", "central_meridian","51.21666666666668", "51.21666666666667",
@@ -205,7 +205,7 @@ static const char *apszParamValueMapping[] = {
 "Hotine_Oblique_Mercator_Azimuth_Center", "latitude_of_center",	"46.95240555555557", "46.95240555555556",
 NULL, NULL, NULL, NULL};
 
-static const char *apszParamNameMapping[] = {
+static const char * const apszParamNameMapping[] = {
 "Lambert_Azimuthal_Equal_Area", "longitude_of_center", "Central_Meridian",
 "Lambert_Azimuthal_Equal_Area", "Latitude_Of_Center", "Latitude_Of_Origin",
 "Miller_Cylindrical", "longitude_of_center", "Central_Meridian",
@@ -217,154 +217,154 @@ static const char *apszParamNameMapping[] = {
 "Hotine_Oblique_Mercator_Two_Point_Natural_Origin", "latitude_of_point_1", "Latitude_Of_1st_Point",
 "Hotine_Oblique_Mercator_Two_Point_Natural_Origin", "longitude_of_point_1", "Longitude_Of_1st_Point",
 "Hotine_Oblique_Mercator_Two_Point_Natural_Origin", "latitude_of_point_2", "Latitude_Of_2nd_Point",
-"Hotine_Oblique_Mercator_Two_Point_Natural_Origin", "longitude_of_point_2", "Longitude_Of_2nd_Point", 
+"Hotine_Oblique_Mercator_Two_Point_Natural_Origin", "longitude_of_point_2", "Longitude_Of_2nd_Point",
 NULL, NULL, NULL};
 
-static const char *apszDeleteParametersBasedOnProjection[] = {
+static const char * const apszDeleteParametersBasedOnProjection[] = {
 "Stereographic_South_Pole", "scale_factor",
 "Stereographic_North_Pole", "scale_factor",
 "Mercator", "scale_factor",
 "Miller_Cylindrical", "latitude_of_center",
-"Equidistant_Cylindrical", "pseudo_standard_parallel_1", 
-"Equidistant_Cylindrical", "latitude_of_origin", 
+"Equidistant_Cylindrical", "pseudo_standard_parallel_1",
+"Equidistant_Cylindrical", "latitude_of_origin",
 "Plate_Carree", "latitude_of_origin",
 "Plate_Carree", "pseudo_standard_parallel_1",
 "Plate_Carree", "standard_parallel_1",
-"Hotine_Oblique_Mercator_Azimuth_Center", "rectified_grid_angle", 
-"Hotine_Oblique_Mercator_Azimuth_Natural_Origin", "rectified_grid_angle", 
+"Hotine_Oblique_Mercator_Azimuth_Center", "rectified_grid_angle",
+"Hotine_Oblique_Mercator_Azimuth_Natural_Origin", "rectified_grid_angle",
 NULL, NULL};
 
-static const char *apszAddParametersBasedOnProjection[] = {
-"Cassini", "scale_factor", "1.0", 
-"Mercator", "standard_parallel_1", "0.0", 
+static const char * const apszAddParametersBasedOnProjection[] = {
+"Cassini", "scale_factor", "1.0",
+"Mercator", "standard_parallel_1", "0.0",
 NULL, NULL, NULL};
 
-static int statePlaneZoneMapping[] = {
+static const int statePlaneZoneMapping[] = {
 /* old zone code, prj code, new zone code */
  3126, -1,    101,
  3151, -1,    102,
  3176, -1,    202,
- 3201, -1,    203, 
- 3226, -1,    301, 
- 3251, -1,    302, 
- 3326, -1,    403, 
- 3351, -1,    404, 
+ 3201, -1,    203,
+ 3226, -1,    301,
+ 3251, -1,    302,
+ 3326, -1,    403,
+ 3351, -1,    404,
  3376, 26945, 405,
- 3426, -1,    407, 
- 3451, -1,    501, 
- 3476, -1,    502, 
- 3526, -1,    600, 
- 3551, -1,    700, 
- 3576, -1,    903, 
- 3626, -1,    902, 
- 3651, -1,    1001, 
- 3676, -1,    1002, 
- 3726, -1,    1102, 
- 3751, -1,    1103, 
- 3776, -1,    1201, 
- 3801, -1,    1202, 
- 3826, -1,    1301, 
- 3851, -1,    1302, 
- 3876, -1,    1401, 
- 3926, -1,    1501, 
- 3951, -1,    1502, 
- 3976, -1,    1601, 
- 4026, -1,    1701, 
- 6426, -1,    1703, 
- 4076, -1,    1801, 
- 4101, -1,    1802, 
+ 3426, -1,    407,
+ 3451, -1,    501,
+ 3476, -1,    502,
+ 3526, -1,    600,
+ 3551, -1,    700,
+ 3576, -1,    903,
+ 3626, -1,    902,
+ 3651, -1,    1001,
+ 3676, -1,    1002,
+ 3726, -1,    1102,
+ 3751, -1,    1103,
+ 3776, -1,    1201,
+ 3801, -1,    1202,
+ 3826, -1,    1301,
+ 3851, -1,    1302,
+ 3876, -1,    1401,
+ 3926, -1,    1501,
+ 3951, -1,    1502,
+ 3976, -1,    1601,
+ 4026, -1,    1701,
+ 6426, -1,    1703,
+ 4076, -1,    1801,
+ 4101, -1,    1802,
  4126, -1,    1900,
- 4151, -1,    2001, 
- 4176, -1,    2002, 
- 4226, -1,    2102, 
- 4251, -1,    2103, 
- 6351, -1,    2111, 
- 6376, -1,    2112, 
- 6401, -1,    2113, 
- 4276, -1,    2201, 
- 4326, -1,    2203, 
- 4351, -1,    2301, 
- 4376, -1,    2302, 
+ 4151, -1,    2001,
+ 4176, -1,    2002,
+ 4226, -1,    2102,
+ 4251, -1,    2103,
+ 6351, -1,    2111,
+ 6376, -1,    2112,
+ 6401, -1,    2113,
+ 4276, -1,    2201,
+ 4326, -1,    2203,
+ 4351, -1,    2301,
+ 4376, -1,    2302,
  4400, 32045, 3400,
- 4401, -1,    2401, 
- 4426, -1,    2402, 
- 4451, -1,    2403, 
+ 4401, -1,    2401,
+ 4426, -1,    2402,
+ 4451, -1,    2403,
  4476, 32100, 2500,
  4476, -1,    2501,
  4701, 32111,	2900,
  4801, 2260,  3101,
  4801, 32115, 3101,
- 4526, -1,    2503, 
- 4551, -1,    2601, 
- 4576, -1,    2602, 
- 4626, -1,    2702, 
- 4651, -1,    2703, 
- 4676, -1,    2800, 
- 4726, -1,    3001, 
- 4751, -1,    3002, 
- 4776, -1,    3003, 
- 4826, -1,    3102, 
- 4851, -1,    3103, 
- 4876, -1,    3104, 
- 4926, -1,    3301, 
- 4951, -1,    3302, 
- 4976, -1,    3401, 
- 5026, -1,    3501, 
- 5051, -1,    3502, 
- 5076, -1,    3601, 
- 5126, -1,    3701, 
- 5151, -1,    3702, 
- 5176, -1,    3800, 
- 5226, -1,    3902, 
- 5251, -1,    4001, 
- 5276, -1,    4002, 
- 5301, -1,    4100, 
- 5326, -1,    4201, 
- 5351, -1,    4202, 
- 5376, -1,    4203, 
- 5401, -1,    4204, 
- 5426, -1,    4205, 
- 5451, -1,    4301, 
- 5476, -1,    4302, 
- 5501, -1,    4303, 
- 5526, -1,    4400, 
- 5551, -1,    4501, 
- 5576, -1,    4502, 
- 5601, -1,    4601, 
- 5626, -1,    4602, 
- 5651, -1,    4701, 
- 5676, -1,    4702, 
- 5701, -1,    4801, 
- 5726, -1,    4802, 
- 5751, -1,    4803, 
- 5776, -1,    4901, 
- 5801, -1,    4902, 
- 5826, -1,    4903, 
- 5851, -1,    4904, 
- 6101, -1,    5001, 
- 6126, -1,    5002, 
- 6151, -1,    5003, 
- 6176, -1,    5004, 
- 6201, -1,    5005, 
- 6226, -1,    5006, 
- 6251, -1,    5007, 
- 6276, -1,    5008, 
- 6301, -1,    5009, 
- 6326, -1,    5010, 
- 5876, -1,    5101, 
- 5901, -1,    5102, 
- 5926, -1,    5103, 
- 5951, -1,    5104, 
- 5976, -1,    5105, 
- 6001, -1,    5201, 
- 6026, -1,    5200, 
- 6076, -1,    5200, 
- 6051, -1,    5202, 
- 0,    0,     0 
- }; 
+ 4526, -1,    2503,
+ 4551, -1,    2601,
+ 4576, -1,    2602,
+ 4626, -1,    2702,
+ 4651, -1,    2703,
+ 4676, -1,    2800,
+ 4726, -1,    3001,
+ 4751, -1,    3002,
+ 4776, -1,    3003,
+ 4826, -1,    3102,
+ 4851, -1,    3103,
+ 4876, -1,    3104,
+ 4926, -1,    3301,
+ 4951, -1,    3302,
+ 4976, -1,    3401,
+ 5026, -1,    3501,
+ 5051, -1,    3502,
+ 5076, -1,    3601,
+ 5126, -1,    3701,
+ 5151, -1,    3702,
+ 5176, -1,    3800,
+ 5226, -1,    3902,
+ 5251, -1,    4001,
+ 5276, -1,    4002,
+ 5301, -1,    4100,
+ 5326, -1,    4201,
+ 5351, -1,    4202,
+ 5376, -1,    4203,
+ 5401, -1,    4204,
+ 5426, -1,    4205,
+ 5451, -1,    4301,
+ 5476, -1,    4302,
+ 5501, -1,    4303,
+ 5526, -1,    4400,
+ 5551, -1,    4501,
+ 5576, -1,    4502,
+ 5601, -1,    4601,
+ 5626, -1,    4602,
+ 5651, -1,    4701,
+ 5676, -1,    4702,
+ 5701, -1,    4801,
+ 5726, -1,    4802,
+ 5751, -1,    4803,
+ 5776, -1,    4901,
+ 5801, -1,    4902,
+ 5826, -1,    4903,
+ 5851, -1,    4904,
+ 6101, -1,    5001,
+ 6126, -1,    5002,
+ 6151, -1,    5003,
+ 6176, -1,    5004,
+ 6201, -1,    5005,
+ 6226, -1,    5006,
+ 6251, -1,    5007,
+ 6276, -1,    5008,
+ 6301, -1,    5009,
+ 6326, -1,    5010,
+ 5876, -1,    5101,
+ 5901, -1,    5102,
+ 5926, -1,    5103,
+ 5951, -1,    5104,
+ 5976, -1,    5105,
+ 6001, -1,    5201,
+ 6026, -1,    5200,
+ 6076, -1,    5200,
+ 6051, -1,    5202,
+ 0,    0,     0
+ };
 
 /* This is not a complete mapping. Need to add more. */
-static int statePlanePcsCodeToZoneCode[] = {
+static const int statePlanePcsCodeToZoneCode[] = {
 /* pcs code, state plane prj str index*/
 2222, 2016,
 2223, 2026,
@@ -503,215 +503,215 @@ static int statePlanePcsCodeToZoneCode[] = {
 2991, 102991,
 2992, 102992,
 2993, 102993,
-2994, 102994, 
-// following are NAD 1983 SPCS Zone  
-26929, 1011,      
-26930, 1021,      
-26931, 50011,          
-26932, 50021,          
-26933, 50031,          
-26934, 50041,          
-26935, 50051,          
-26936, 50061,          
-26937, 50071,          
-26938, 50081,          
-26939, 50091,          
-26940, 50101,         
-26948, 2011,      
-26949, 2021,   
-26950, 2031,      
-26951, 3011,    
-26952, 3021,    
-26941, 4011,      
-26942, 4021,     
-26943, 4031,    
-26944, 4041,     
-26945, 4051,      
-26946, 4061,     
-26953, 5011,    
-26954, 5021,  
-26955, 5031,    
-26956, 6001,       
-26957, 7001,          
-26958, 9011,      
-26959, 9021,      
-26960, 9031,     
-26966, 10011,      
-26967, 10021,      
-26961, 51011,     
-26962, 51021,     
-26963, 51031,     
-26964, 51041,     
-26965, 51051,     
-26968, 11011,        
-26969, 11021,     
-26970, 11031,        
-26971, 12011,     
-26972, 12021,     
-26973, 13011,      
-26974, 13021,      
-26975, 14011,        
-26976, 14021,        
-26977, 15011,      
-26978, 15021,      
-26979, 16011,    
-26980, 16021,    
-26981, 17011,   
-26982, 17021,   
-26983, 18011,        
-26984, 18021,        
-26985, 19001,          
-26986, 20011,    
-26987, 20021,      
-26988, 21111,    
-26989, 21121,  
-26990, 21131,    
-26991, 22011,   
-26992, 22021, 
-26993, 22031,   
-26994, 23011,  
-26995, 23021,  
-26996, 24011,     
-26997, 24021,  
-26998, 24031,     
-32100, 25001,           
-32104, 26001,          
-32107, 27011,       
-32108, 27021,    
-32109, 27031,       
-32110, 28001,     
-32111, 29001,        
-32112, 30011,   
-32113, 30021,  
-32114, 30031,   
-32115, 31011,     
-32116, 31021,  
-32117, 31031,     
-32118, 31041,    
-32119, 32001, 
-32120, 33011,    
-32121, 33021,    
-32122, 34011,        
-32123, 34021,        
-32124, 35011,    
-32125, 35021,    
-32126, 36011,      
-32127, 36021,      
-32128, 37011,    
-32129, 37021,    
-32130, 38001,      
-32133, 39001,    
-32134, 40011,    
-32135, 40021,    
-32136, 41001,         
-32137, 42011,       
-32138, 42021, 
-32139, 42031,     
-32140, 42041, 
-32141, 42051,       
-32142, 43011,        
-32143, 43021,      
-32144, 43031,        
-32145, 44001,           
-32146, 45011,    
-32147, 45021,    
-32148, 46011,  
-32149, 46021,  
-32150, 47011,   
-32151, 47021,   
-32152, 48011,   
-32153, 48021, 
-32154, 48031,   
-32155, 49011,    
-32156, 49021,     
-32157, 49031,    
-32158, 49041,   
-32161, 52000,    
-65161, 54001,  
+2994, 102994,
+// following are NAD 1983 SPCS Zone
+26929, 1011,
+26930, 1021,
+26931, 50011,
+26932, 50021,
+26933, 50031,
+26934, 50041,
+26935, 50051,
+26936, 50061,
+26937, 50071,
+26938, 50081,
+26939, 50091,
+26940, 50101,
+26948, 2011,
+26949, 2021,
+26950, 2031,
+26951, 3011,
+26952, 3021,
+26941, 4011,
+26942, 4021,
+26943, 4031,
+26944, 4041,
+26945, 4051,
+26946, 4061,
+26953, 5011,
+26954, 5021,
+26955, 5031,
+26956, 6001,
+26957, 7001,
+26958, 9011,
+26959, 9021,
+26960, 9031,
+26966, 10011,
+26967, 10021,
+26961, 51011,
+26962, 51021,
+26963, 51031,
+26964, 51041,
+26965, 51051,
+26968, 11011,
+26969, 11021,
+26970, 11031,
+26971, 12011,
+26972, 12021,
+26973, 13011,
+26974, 13021,
+26975, 14011,
+26976, 14021,
+26977, 15011,
+26978, 15021,
+26979, 16011,
+26980, 16021,
+26981, 17011,
+26982, 17021,
+26983, 18011,
+26984, 18021,
+26985, 19001,
+26986, 20011,
+26987, 20021,
+26988, 21111,
+26989, 21121,
+26990, 21131,
+26991, 22011,
+26992, 22021,
+26993, 22031,
+26994, 23011,
+26995, 23021,
+26996, 24011,
+26997, 24021,
+26998, 24031,
+32100, 25001,
+32104, 26001,
+32107, 27011,
+32108, 27021,
+32109, 27031,
+32110, 28001,
+32111, 29001,
+32112, 30011,
+32113, 30021,
+32114, 30031,
+32115, 31011,
+32116, 31021,
+32117, 31031,
+32118, 31041,
+32119, 32001,
+32120, 33011,
+32121, 33021,
+32122, 34011,
+32123, 34021,
+32124, 35011,
+32125, 35021,
+32126, 36011,
+32127, 36021,
+32128, 37011,
+32129, 37021,
+32130, 38001,
+32133, 39001,
+32134, 40011,
+32135, 40021,
+32136, 41001,
+32137, 42011,
+32138, 42021,
+32139, 42031,
+32140, 42041,
+32141, 42051,
+32142, 43011,
+32143, 43021,
+32144, 43031,
+32145, 44001,
+32146, 45011,
+32147, 45021,
+32148, 46011,
+32149, 46021,
+32150, 47011,
+32151, 47021,
+32152, 48011,
+32153, 48021,
+32154, 48031,
+32155, 49011,
+32156, 49021,
+32157, 49031,
+32158, 49041,
+32161, 52000,
+65161, 54001,
 0,     0
 };
 
 /* ==================================================================== */
 /*      WISCRS Table                                                    */
 /* ==================================================================== */
-static double apszWISCRS_LCC_meter[] = {
+static const double apszWISCRS_LCC_meter[] = {
 // Central_Meridian, Latitude_Of_Origin, SR code
-   -91.1527777777, 46.6696483772, 103303.0, 
-   -92.4577777777, 45.8987148658, 103306.0, 
-   -91.2944444444, 44.9778568986, 103308.0, 
-   -89.3944444444, 43.4625466458, 103310.0, 
-   -90.9388888888, 43.2000556050, 103311.0, 
-   -89.4222222222, 43.0695160375, 103312.0, 
-   -91.2888888888, 45.8722811263, 103317.0, 
-   -89.8388888888, 42.6375622769, 103322.0, 
-   -89.2416666666, 43.8070001177, 103323.0, 
-   -89.8388888888, 42.6375622769, 103332.0, 
-   -89.0333333333, 45.1542371052, 103333.0, 
-   -89.7700000000, 44.9009044236, 103336.0, 
-   -89.2416666666, 43.8070001177, 103338.0, 
-   -90.6416666666, 44.0000739286, 103341.0, 
-   -89.5444444444, 45.7042237702, 103343.0, 
-   -92.2277777777, 44.6361488719, 103346.0, 
-   -92.2277777777, 44.6361488719, 103347.0, 
-   -89.5000000000, 44.4168239752, 103349.0, 
-   -90.4305555555, 43.3223129275, 103352.0, 
-   -91.1166666666, 45.9000991313, 103356.0, 
-   -90.4833333333, 45.1778220858, 103360.0, 
-   -90.7833333333, 43.5750329397, 103362.0, 
-   -89.4888888888, 46.0778440905, 103363.0, 
-   -88.5416666667, 42.6694620969, 103364.0, 
-   -91.7833333333, 45.9612198333, 103365.0, 
-   -89.2416666666, 44.1139440458, 103369.0, 
-   -90.0000000000, 44.3625954694, 103371.0, 
+   -91.1527777777, 46.6696483772, 103303.0,
+   -92.4577777777, 45.8987148658, 103306.0,
+   -91.2944444444, 44.9778568986, 103308.0,
+   -89.3944444444, 43.4625466458, 103310.0,
+   -90.9388888888, 43.2000556050, 103311.0,
+   -89.4222222222, 43.0695160375, 103312.0,
+   -91.2888888888, 45.8722811263, 103317.0,
+   -89.8388888888, 42.6375622769, 103322.0,
+   -89.2416666666, 43.8070001177, 103323.0,
+   -89.8388888888, 42.6375622769, 103332.0,
+   -89.0333333333, 45.1542371052, 103333.0,
+   -89.7700000000, 44.9009044236, 103336.0,
+   -89.2416666666, 43.8070001177, 103338.0,
+   -90.6416666666, 44.0000739286, 103341.0,
+   -89.5444444444, 45.7042237702, 103343.0,
+   -92.2277777777, 44.6361488719, 103346.0,
+   -92.2277777777, 44.6361488719, 103347.0,
+   -89.5000000000, 44.4168239752, 103349.0,
+   -90.4305555555, 43.3223129275, 103352.0,
+   -91.1166666666, 45.9000991313, 103356.0,
+   -90.4833333333, 45.1778220858, 103360.0,
+   -90.7833333333, 43.5750329397, 103362.0,
+   -89.4888888888, 46.0778440905, 103363.0,
+   -88.5416666667, 42.6694620969, 103364.0,
+   -91.7833333333, 45.9612198333, 103365.0,
+   -89.2416666666, 44.1139440458, 103369.0,
+   -90.0000000000, 44.3625954694, 103371.0,
    0.0, 0,0, 0,0
 };
 
-static double apszWISCRS_TM_meter[] = {
-// Central_Meridian, Latitude_Of_Origin, SR code 
-   -90.0000000000, 43.3666666666, 103300.0, 
-   -90.6222222222, 45.7061111111, 103301.0, 
-   -91.8500000000, 45.1333333333, 103302.0, 
-   -88.0000000000, 43.0000000000, 103304.0, 
-   -91.7972222222, 43.4813888888, 103305.0, 
-   -88.5000000000, 42.7194444444, 103307.0, 
-   -90.7083333333, 43.6000000000, 103309.0, 
-   -88.7750000000, 41.4722222222, 103313.0, 
-   -87.2722222222, 44.4000000000, 103314.0, 
-   -91.9166666666, 45.8833333333, 103315.0, 
-   -91.8944444444, 44.4083333333, 103316.0, 
-   -88.1416666666, 45.4388888888, 103318.0, 
-   -88.5000000000, 42.7194444444, 103319.0, 
-   -88.6333333333, 44.0055555556, 103320.0, 
-   -90.8000000000, 41.4111111111, 103321.0, 
-   -90.1611111111, 42.5388888888, 103324.0, 
-   -90.2555555555, 45.4333333333, 103325.0, 
-   -90.8442965194, 44.2533351277, 103326.0, 
-   -88.7750000000, 41.4722222222, 103327.0, 
-   -90.0000000000, 43.3666666666, 103328.0, 
-   -87.8944444444, 42.2166666666, 103329.0, 
-   -87.5500000000, 43.2666666666, 103330.0, 
-   -91.3166666666, 43.4511111111, 103331.0, 
-   -89.7333333333, 44.8444444444, 103334.0, 
-   -87.5500000000, 43.2666666666, 103335.0, 
-   -87.7111111111, 44.6916666666, 103337.0, 
-   -88.4166666666, 44.7166666666, 103339.0, 
-   -87.8944444444, 42.2166666666, 103340.0, 
-   -87.9083333333, 44.3972222222, 103342.0, 
-   -88.5000000000, 42.7194444444, 103344.0, 
-   -87.8944444444, 42.2166666666, 103345.0, 
-   -92.6333333333, 44.6611111111, 103348.0, 
-   -90.4888888889, 44.5555555556, 103350.0, 
-   -87.8944444444, 42.2166666666, 103351.0, 
-   -89.0722222222, 41.9444444444, 103353.0, 
-   -91.0666666666, 43.9194444444, 103354.0, 
-   -89.9000000000, 42.8194444444, 103355.0, 
-   -88.6055555556, 44.0361111111, 103357.0, 
-   -87.5500000000, 43.2666666666, 103358.0, 
-   -92.6333333333, 44.0361111111, 103359.0, 
-   -91.3666666666, 43.1611111111, 103361.0, 
-   -88.0638888888, 42.9180555555, 103366.0, 
-   -88.2250000000, 42.5694444444, 103367.0, 
-   -88.8166666666, 43.4202777777, 103368.0, 
-   -88.5000000000, 42.7194444444, 103370.0, 
+static const double apszWISCRS_TM_meter[] = {
+// Central_Meridian, Latitude_Of_Origin, SR code
+   -90.0000000000, 43.3666666666, 103300.0,
+   -90.6222222222, 45.7061111111, 103301.0,
+   -91.8500000000, 45.1333333333, 103302.0,
+   -88.0000000000, 43.0000000000, 103304.0,
+   -91.7972222222, 43.4813888888, 103305.0,
+   -88.5000000000, 42.7194444444, 103307.0,
+   -90.7083333333, 43.6000000000, 103309.0,
+   -88.7750000000, 41.4722222222, 103313.0,
+   -87.2722222222, 44.4000000000, 103314.0,
+   -91.9166666666, 45.8833333333, 103315.0,
+   -91.8944444444, 44.4083333333, 103316.0,
+   -88.1416666666, 45.4388888888, 103318.0,
+   -88.5000000000, 42.7194444444, 103319.0,
+   -88.6333333333, 44.0055555556, 103320.0,
+   -90.8000000000, 41.4111111111, 103321.0,
+   -90.1611111111, 42.5388888888, 103324.0,
+   -90.2555555555, 45.4333333333, 103325.0,
+   -90.8442965194, 44.2533351277, 103326.0,
+   -88.7750000000, 41.4722222222, 103327.0,
+   -90.0000000000, 43.3666666666, 103328.0,
+   -87.8944444444, 42.2166666666, 103329.0,
+   -87.5500000000, 43.2666666666, 103330.0,
+   -91.3166666666, 43.4511111111, 103331.0,
+   -89.7333333333, 44.8444444444, 103334.0,
+   -87.5500000000, 43.2666666666, 103335.0,
+   -87.7111111111, 44.6916666666, 103337.0,
+   -88.4166666666, 44.7166666666, 103339.0,
+   -87.8944444444, 42.2166666666, 103340.0,
+   -87.9083333333, 44.3972222222, 103342.0,
+   -88.5000000000, 42.7194444444, 103344.0,
+   -87.8944444444, 42.2166666666, 103345.0,
+   -92.6333333333, 44.6611111111, 103348.0,
+   -90.4888888889, 44.5555555556, 103350.0,
+   -87.8944444444, 42.2166666666, 103351.0,
+   -89.0722222222, 41.9444444444, 103353.0,
+   -91.0666666666, 43.9194444444, 103354.0,
+   -89.9000000000, 42.8194444444, 103355.0,
+   -88.6055555556, 44.0361111111, 103357.0,
+   -87.5500000000, 43.2666666666, 103358.0,
+   -92.6333333333, 44.0361111111, 103359.0,
+   -91.3666666666, 43.1611111111, 103361.0,
+   -88.0638888888, 42.9180555555, 103366.0,
+   -88.2250000000, 42.5694444444, 103367.0,
+   -88.8166666666, 43.4202777777, 103368.0,
+   -88.5000000000, 42.7194444444, 103370.0,
    0.0, 0,0, 0,0
 };
diff --git a/ogr/ogr_srs_ozi.cpp b/ogr/ogr_srs_ozi.cpp
index 73e5a39..9e2840f 100644
--- a/ogr/ogr_srs_ozi.cpp
+++ b/ogr/ogr_srs_ozi.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_srs_ozi.cpp 28972 2015-04-22 10:39:11Z rouault $
+ * $Id: ogr_srs_ozi.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGRSpatialReference translation from OziExplorer
@@ -33,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_csv.h"
 
-CPL_CVSID("$Id: ogr_srs_ozi.cpp 28972 2015-04-22 10:39:11Z rouault $");
+CPL_CVSID("$Id: ogr_srs_ozi.cpp 33631 2016-03-04 06:28:09Z goatbar $");
 
 /************************************************************************/
 /*                          OSRImportFromOzi()                          */
@@ -51,8 +51,8 @@ CPL_CVSID("$Id: ogr_srs_ozi.cpp 28972 2015-04-22 10:39:11Z rouault $");
  * @param hSRS spatial reference object.
  * @param papszLines Map file lines. This is an array of strings containing
  * the whole OziExplorer .MAP file. The array is terminated by a NULL pointer.
- * 
- * @return OGRERR_NONE on success or an error code in case of failure. 
+ *
+ * @return OGRERR_NONE on success or an error code in case of failure.
  *
  * @since OGR 2.0
  */
@@ -61,7 +61,7 @@ OGRErr OSRImportFromOzi( OGRSpatialReferenceH hSRS,
                          const char * const* papszLines )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRImportFromOzi", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRImportFromOzi", OGRERR_FAILURE );
 
     return ((OGRSpatialReference *) hSRS)->importFromOzi( papszLines );
 }
@@ -78,8 +78,8 @@ OGRErr OSRImportFromOzi( OGRSpatialReferenceH hSRS,
  *
  * @param papszLines Map file lines. This is an array of strings containing
  * the whole OziExplorer .MAP file. The array is terminated by a NULL pointer.
- * 
- * @return OGRERR_NONE on success or an error code in case of failure. 
+ *
+ * @return OGRERR_NONE on success or an error code in case of failure.
  *
  * @since OGR 1.10
  */
@@ -99,11 +99,11 @@ OGRErr OGRSpatialReference::importFromOzi( const char * const* papszLines )
 
     for ( iLine = 5; iLine < nLines; iLine++ )
     {
-        if ( EQUALN(papszLines[iLine], "Map Projection", 14) )
+        if ( STARTS_WITH_CI(papszLines[iLine], "Map Projection") )
         {
             pszProj = papszLines[iLine];
         }
-        else if ( EQUALN(papszLines[iLine], "Projection Setup", 16) )
+        else if ( STARTS_WITH_CI(papszLines[iLine], "Projection Setup") )
         {
             pszProjParms = papszLines[iLine];
         }
@@ -116,20 +116,20 @@ OGRErr OGRSpatialReference::importFromOzi( const char * const* papszLines )
 /*      Operate on the basis of the projection name.                    */
 /* -------------------------------------------------------------------- */
     char    **papszProj = CSLTokenizeStringComplex( pszProj, ",", TRUE, TRUE );
-    char    **papszProjParms = CSLTokenizeStringComplex( pszProjParms, ",", 
+    char    **papszProjParms = CSLTokenizeStringComplex( pszProjParms, ",",
                                                          TRUE, TRUE );
     char    **papszDatum = NULL;
-                                                         
+
     if (CSLCount(papszProj) < 2)
     {
         goto not_enough_data;
     }
 
-    if ( EQUALN(papszProj[1], "Latitude/Longitude", 18) )
+    if ( STARTS_WITH_CI(papszProj[1], "Latitude/Longitude") )
     {
     }
 
-    else if ( EQUALN(papszProj[1], "Mercator", 8) )
+    else if ( STARTS_WITH_CI(papszProj[1], "Mercator") )
     {
         if (CSLCount(papszProjParms) < 6) goto not_enough_data;
         double dfScale = CPLAtof(papszProjParms[3]);
@@ -139,7 +139,7 @@ OGRErr OGRSpatialReference::importFromOzi( const char * const* papszLines )
                      CPLAtof(papszProjParms[4]), CPLAtof(papszProjParms[5]) );
     }
 
-    else if ( EQUALN(papszProj[1], "Transverse Mercator", 19) )
+    else if ( STARTS_WITH_CI(papszProj[1], "Transverse Mercator") )
     {
         if (CSLCount(papszProjParms) < 6) goto not_enough_data;
         SetTM( CPLAtof(papszProjParms[1]), CPLAtof(papszProjParms[2]),
@@ -147,7 +147,7 @@ OGRErr OGRSpatialReference::importFromOzi( const char * const* papszLines )
                CPLAtof(papszProjParms[4]), CPLAtof(papszProjParms[5]) );
     }
 
-    else if ( EQUALN(papszProj[1], "Lambert Conformal Conic", 23) )
+    else if ( STARTS_WITH_CI(papszProj[1], "Lambert Conformal Conic") )
     {
         if (CSLCount(papszProjParms) < 8) goto not_enough_data;
         SetLCC( CPLAtof(papszProjParms[6]), CPLAtof(papszProjParms[7]),
@@ -155,14 +155,14 @@ OGRErr OGRSpatialReference::importFromOzi( const char * const* papszLines )
                 CPLAtof(papszProjParms[4]), CPLAtof(papszProjParms[5]) );
     }
 
-    else if ( EQUALN(papszProj[1], "Sinusoidal", 10) )
+    else if ( STARTS_WITH_CI(papszProj[1], "Sinusoidal") )
     {
         if (CSLCount(papszProjParms) < 6) goto not_enough_data;
         SetSinusoidal( CPLAtof(papszProjParms[2]),
                        CPLAtof(papszProjParms[4]), CPLAtof(papszProjParms[5]) );
     }
 
-    else if ( EQUALN(papszProj[1], "Albers Equal Area", 17) )
+    else if ( STARTS_WITH_CI(papszProj[1], "Albers Equal Area") )
     {
         if (CSLCount(papszProjParms) < 8) goto not_enough_data;
         SetACEA( CPLAtof(papszProjParms[6]), CPLAtof(papszProjParms[7]),
@@ -170,12 +170,12 @@ OGRErr OGRSpatialReference::importFromOzi( const char * const* papszLines )
                  CPLAtof(papszProjParms[4]), CPLAtof(papszProjParms[5]) );
     }
 
-    else if ( EQUALN(papszProj[1], "(UTM) Universal Transverse Mercator", 35) && nLines > 5 )
+    else if ( STARTS_WITH_CI(papszProj[1], "(UTM) Universal Transverse Mercator") && nLines > 5 )
     {
         /* Look for the UTM zone in the calibration point data */
         for ( iLine = 5; iLine < nLines; iLine++ )
         {
-            if ( EQUALN(papszLines[iLine], "Point", 5) )
+            if ( STARTS_WITH_CI(papszLines[iLine], "Point") )
             {
                 char    **papszTok = NULL;
                 papszTok = CSLTokenizeString2( papszLines[iLine], ",",
@@ -192,21 +192,21 @@ OGRErr OGRSpatialReference::importFromOzi( const char * const* papszLines )
                     CSLDestroy(papszTok);
                     continue;
                 }
-                SetUTM( CPLAtofM(papszTok[13]), EQUAL(papszTok[16], "N") );
+                SetUTM( atoi(papszTok[13]), EQUAL(papszTok[16], "N") );
                 CSLDestroy(papszTok);
                 break;
             }
         }
         if ( iLine == nLines )    /* Try to guess the UTM zone */
         {
-            float fMinLongitude = INT_MAX;
-            float fMaxLongitude = INT_MIN;
-            float fMinLatitude = INT_MAX;
-            float fMaxLatitude = INT_MIN;
-            int bFoundMMPLL = FALSE;
+            float fMinLongitude = 1000.0f;
+            float fMaxLongitude = -1000.0f;;
+            float fMinLatitude = 1000.0f;
+            float fMaxLatitude = -1000.0f;
+            bool bFoundMMPLL = false;
             for ( iLine = 5; iLine < nLines; iLine++ )
             {
-                if ( EQUALN(papszLines[iLine], "MMPLL", 5) )
+                if ( STARTS_WITH_CI(papszLines[iLine], "MMPLL") )
                 {
                     char    **papszTok = NULL;
                     papszTok = CSLTokenizeString2( papszLines[iLine], ",",
@@ -218,11 +218,11 @@ OGRErr OGRSpatialReference::importFromOzi( const char * const* papszLines )
                         CSLDestroy(papszTok);
                         continue;
                     }
-                    float fLongitude = CPLAtofM(papszTok[2]);
-                    float fLatitude = CPLAtofM(papszTok[3]);
+                    float fLongitude = static_cast<float>(CPLAtofM(papszTok[2]));
+                    float fLatitude = static_cast<float>(CPLAtofM(papszTok[3]));
                     CSLDestroy(papszTok);
 
-                    bFoundMMPLL = TRUE;
+                    bFoundMMPLL = true;
 
                     if ( fMinLongitude > fLongitude )
                         fMinLongitude = fLongitude;
@@ -239,10 +239,10 @@ OGRErr OGRSpatialReference::importFromOzi( const char * const* papszLines )
             if ( bFoundMMPLL && fMaxLatitude <= 90 )
             {
                 int nUtmZone;
-                if ( fMedianLatitude >= 56 && fMedianLatitude <= 64 && 
+                if ( fMedianLatitude >= 56 && fMedianLatitude <= 64 &&
                      fMedianLongitude >= 3 && fMedianLongitude <= 12 )
                     nUtmZone = 32;                                             /* Norway exception */
-                else if ( fMedianLatitude >= 72 && fMedianLatitude <= 84 && 
+                else if ( fMedianLatitude >= 72 && fMedianLatitude <= 84 &&
                          fMedianLongitude >= 0 && fMedianLongitude <= 42 )
                     nUtmZone = (int) ((fMedianLongitude + 3 ) / 12) * 2 + 31;  /* Svalbard exception */
                 else
@@ -254,22 +254,22 @@ OGRErr OGRSpatialReference::importFromOzi( const char * const* papszLines )
         }
     }
 
-    else if ( EQUALN(papszProj[1], "(I) France Zone I", 17) )
+    else if ( STARTS_WITH_CI(papszProj[1], "(I) France Zone I") )
     {
         SetLCC1SP( 49.5, 2.337229167, 0.99987734, 600000, 1200000 );
     }
 
-    else if ( EQUALN(papszProj[1], "(II) France Zone II", 19) )
+    else if ( STARTS_WITH_CI(papszProj[1], "(II) France Zone II") )
     {
         SetLCC1SP( 46.8, 2.337229167, 0.99987742, 600000, 2200000 );
     }
 
-    else if ( EQUALN(papszProj[1], "(III) France Zone III", 21) )
+    else if ( STARTS_WITH_CI(papszProj[1], "(III) France Zone III") )
     {
         SetLCC1SP( 44.1, 2.337229167, 0.99987750, 600000, 3200000 );
     }
 
-    else if ( EQUALN(papszProj[1], "(IV) France Zone IV", 19) )
+    else if ( STARTS_WITH_CI(papszProj[1], "(IV) France Zone IV") )
     {
         SetLCC1SP( 42.165, 2.337229167, 0.99994471, 234.358, 4185861.369 );
     }
@@ -280,83 +280,83 @@ OGRErr OGRSpatialReference::importFromOzi( const char * const* papszLines )
  */
 
 /*
-    else if ( EQUALN(papszProj[1], "(BNG) British National Grid", 27) )
+    else if ( STARTS_WITH_CI(papszProj[1], "(BNG) British National Grid") )
     {
     }
 
-    else if ( EQUALN(papszProj[1], "(IG) Irish Grid", 15) )
+    else if ( STARTS_WITH_CI(papszProj[1], "(IG) Irish Grid") )
     {
     }
 
-    else if ( EQUALN(papszProj[1], "(NZG) New Zealand Grid", 22) )
+    else if ( STARTS_WITH_CI(papszProj[1], "(NZG) New Zealand Grid") )
     {
     }
 
-    else if ( EQUALN(papszProj[1], "(NZTM2) New Zealand TM 2000", 27) )
+    else if ( STARTS_WITH_CI(papszProj[1], "(NZTM2) New Zealand TM 2000") )
     {
     }
 
-    else if ( EQUALN(papszProj[1], "(SG) Swedish Grid", 27) )
+    else if ( STARTS_WITH_CI(papszProj[1], "(SG) Swedish Grid") )
     {
     }
 
-    else if ( EQUALN(papszProj[1], "(SUI) Swiss Grid", 26) )
+    else if ( STARTS_WITH_CI(papszProj[1], "(SUI) Swiss Grid") )
     {
     }
 
-    else if ( EQUALN(papszProj[1], "(A)Lambert Azimuthual Equal Area", 32) )
+    else if ( STARTS_WITH_CI(papszProj[1], "(A)Lambert Azimuthual Equal Area") )
     {
     }
 
-    else if ( EQUALN(papszProj[1], "(EQC) Equidistant Conic", 23) )
+    else if ( STARTS_WITH_CI(papszProj[1], "(EQC) Equidistant Conic") )
     {
     }
 
-    else if ( EQUALN(papszProj[1], "Polyconic (American)", 20) )
+    else if ( STARTS_WITH_CI(papszProj[1], "Polyconic (American)") )
     {
     }
 
-    else if ( EQUALN(papszProj[1], "Van Der Grinten", 15) )
+    else if ( STARTS_WITH_CI(papszProj[1], "Van Der Grinten") )
     {
     }
 
-    else if ( EQUALN(papszProj[1], "Vertical Near-Sided Perspective", 31) )
+    else if ( STARTS_WITH_CI(papszProj[1], "Vertical Near-Sided Perspective") )
     {
     }
 
-    else if ( EQUALN(papszProj[1], "(WIV) Wagner IV", 15) )
+    else if ( STARTS_WITH_CI(papszProj[1], "(WIV) Wagner IV") )
     {
     }
 
-    else if ( EQUALN(papszProj[1], "Bonne", 5) )
+    else if ( STARTS_WITH_CI(papszProj[1], "Bonne") )
     {
     }
 
-    else if ( EQUALN(papszProj[1], "(MT0) Montana State Plane Zone 2500", 35) )
+    else if ( STARTS_WITH_CI(papszProj[1], "(MT0) Montana State Plane Zone 2500") )
     {
     }
 
-    else if ( EQUALN(papszProj[1], "ITA1) Italy Grid Zone 1", 23) )
+    else if ( STARTS_WITH_CI(papszProj[1], "ITA1) Italy Grid Zone 1") )
     {
     }
 
-    else if ( EQUALN(papszProj[1], "ITA2) Italy Grid Zone 2", 23) )
+    else if ( STARTS_WITH_CI(papszProj[1], "ITA2) Italy Grid Zone 2") )
     {
     }
 
-    else if ( EQUALN(papszProj[1], "(VICMAP-TM) Victoria Aust.(pseudo AMG)", 38) )
+    else if ( STARTS_WITH_CI(papszProj[1], "(VICMAP-TM) Victoria Aust.(pseudo AMG)") )
     {
     }
 
-    else if ( EQUALN(papszProj[1], "VICGRID) Victoria Australia", 27) )
+    else if ( STARTS_WITH_CI(papszProj[1], "VICGRID) Victoria Australia") )
     {
     }
 
-    else if ( EQUALN(papszProj[1], "(VG94) VICGRID94 Victoria Australia", 35) )
+    else if ( STARTS_WITH_CI(papszProj[1], "(VG94) VICGRID94 Victoria Australia") )
     {
     }
 
-    else if ( EQUALN(papszProj[1], "Gnomonic", 8) )
+    else if ( STARTS_WITH_CI(papszProj[1], "Gnomonic") )
     {
     }
 */
@@ -377,7 +377,7 @@ OGRErr OGRSpatialReference::importFromOzi( const char * const* papszLines )
                                                | CSLT_STRIPENDSPACES );
     if ( papszDatum == NULL)
         goto not_enough_data;
-        
+
     if ( !IsLocal() )
     {
 
@@ -506,4 +506,3 @@ other_error:
 
     return OGRERR_FAILURE;
 }
-
diff --git a/ogr/ogr_srs_panorama.cpp b/ogr/ogr_srs_panorama.cpp
index 5acef79..0c2ef90 100644
--- a/ogr/ogr_srs_panorama.cpp
+++ b/ogr/ogr_srs_panorama.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_srs_panorama.cpp 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: ogr_srs_panorama.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGRSpatialReference translation to/from "Panorama" GIS
@@ -34,14 +34,14 @@
 #include "cpl_conv.h"
 #include "cpl_csv.h"
 
-CPL_CVSID("$Id: ogr_srs_panorama.cpp 27044 2014-03-16 23:41:27Z rouault $");
+CPL_CVSID("$Id: ogr_srs_panorama.cpp 33631 2016-03-04 06:28:09Z goatbar $");
 
 #define TO_DEGREES 57.2957795130823208766
 #define TO_RADIANS 0.017453292519943295769
 
 // XXX: this macro computes zone number from the central meridian parameter.
 // Note, that "Panorama" parameters are set in radians.
-// In degrees it means formulae:
+// In degrees it means formula:
 //
 //              zone = (central_meridian + 3) / 6
 //
@@ -78,7 +78,7 @@ CPL_CVSID("$Id: ogr_srs_panorama.cpp 27044 2014-03-16 23:41:27Z rouault $");
 #define PAN_DATUM_WGS84     2L  // WGS84
 
 /************************************************************************/
-/*  "Panorama" ellipsod codes.                                          */
+/*  "Panorama" ellipsoid codes.                                         */
 /************************************************************************/
 
 #define PAN_ELLIPSOID_NONE          -1L
@@ -96,7 +96,7 @@ CPL_CVSID("$Id: ogr_srs_panorama.cpp 27044 2014-03-16 23:41:27Z rouault $");
 /*  Correspondence between "Panorama" and EPSG datum codes.             */
 /************************************************************************/
 
-static const long aoDatums[] =
+static const int aoDatums[] =
 {
     0,
     4284,   // Pulkovo, 1942
@@ -116,7 +116,7 @@ static const long aoDatums[] =
 /*  Correspondence between "Panorama" and EPSG ellipsoid codes.         */
 /************************************************************************/
 
-static const long aoEllips[] =
+static const int aoEllips[] =
 {
     0,
     7024,   // Krassovsky, 1940
@@ -141,7 +141,7 @@ static const long aoEllips[] =
     7003   // Australian National, 1965
 };
 
-#define NUMBER_OF_ELLIPSOIDS    (sizeof(aoEllips)/sizeof(aoEllips[0]))
+#define NUMBER_OF_ELLIPSOIDS    static_cast<int>(sizeof(aoEllips)/sizeof(aoEllips[0]))
 
 /************************************************************************/
 /*                        OSRImportFromPanorama()                       */
@@ -152,7 +152,7 @@ OGRErr OSRImportFromPanorama( OGRSpatialReferenceH hSRS,
                               double *padfPrjParams )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRImportFromPanorama", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRImportFromPanorama", OGRERR_FAILURE );
 
     return ((OGRSpatialReference *) hSRS)->importFromPanorama( iProjSys,
                                                                iDatum,iEllips,
@@ -204,7 +204,7 @@ OGRErr OSRImportFromPanorama( OGRSpatialReferenceH hSRS,
  * </pre>
  *
  * @param iEllips Input spheroid.
- * 
+ *
  *      <h4>Supported Spheroids</h4>
  * <pre>
  *       1: Krassovsky, 1940
@@ -235,7 +235,7 @@ OGRErr OSRImportFromPanorama( OGRSpatialReferenceH hSRS,
  * zero. If NULL supplied instead of array pointer default values will be used
  * (i.e., zeroes).
  *
- * @return OGRERR_NONE on success or an error code in case of failure. 
+ * @return OGRERR_NONE on success or an error code in case of failure.
  */
 
 OGRErr OGRSpatialReference::importFromPanorama( long iProjSys, long iDatum,
@@ -248,7 +248,7 @@ OGRErr OGRSpatialReference::importFromPanorama( long iProjSys, long iDatum,
 /* -------------------------------------------------------------------- */
 /*      Use safe defaults if projection parameters are not supplied.    */
 /* -------------------------------------------------------------------- */
-    int     bProjAllocated = FALSE;
+    int bProjAllocated = false;
 
     if( padfPrjParams == NULL )
     {
@@ -259,7 +259,7 @@ OGRErr OGRSpatialReference::importFromPanorama( long iProjSys, long iDatum,
             return OGRERR_NOT_ENOUGH_MEMORY;
         for ( i = 0; i < 7; i++ )
             padfPrjParams[i] = 0.0;
-        bProjAllocated = TRUE;
+        bProjAllocated = true;
     }
 
 /* -------------------------------------------------------------------- */
@@ -272,15 +272,15 @@ OGRErr OGRSpatialReference::importFromPanorama( long iProjSys, long iDatum,
 
         case PAN_PROJ_UTM:
             {
-                long nZone;
+                int nZone;
 
                 if ( padfPrjParams[7] == 0.0 )
-                    nZone = (long)TO_ZONE(padfPrjParams[3]);
+                    nZone = (int) TO_ZONE(padfPrjParams[3]);
                 else
-                    nZone = (long) padfPrjParams[7];
+                    nZone = (int) padfPrjParams[7];
 
                 // XXX: no way to determine south hemisphere. Always assume
-                // nothern hemisphere.
+                // northern hemisphere.
                 SetUTM( nZone, TRUE );
             }
             break;
@@ -332,18 +332,18 @@ OGRErr OGRSpatialReference::importFromPanorama( long iProjSys, long iDatum,
                 // parameter, because usually it is not contained in the
                 // "Panorama" projection definition.
                 // FIXME: what to do with negative values?
-                long    nZone;
+                int    nZone;
                 double  dfCenterLong;
 
                 if ( padfPrjParams[7] == 0.0 )
                 {
-                    nZone = (long)TO_ZONE(padfPrjParams[3]);
+                    nZone = (int)TO_ZONE(padfPrjParams[3]);
                     dfCenterLong = TO_DEGREES * padfPrjParams[3];
                 }
                 else
                 {
-                    nZone = (long) padfPrjParams[7];
-                    dfCenterLong = 6 * nZone - 3;
+                    nZone = (int) padfPrjParams[7];
+                    dfCenterLong = 6 * (double)nZone - 3;
                 }
 
                 padfPrjParams[5] = nZone * 1000000.0 + 500000.0;
@@ -432,7 +432,7 @@ OGRErr OGRSpatialReference::importFromPanorama( long iProjSys, long iDatum,
         }
 
         else if ( iEllips > 0
-                  && iEllips < (long)NUMBER_OF_ELLIPSOIDS
+                  && iEllips < NUMBER_OF_ELLIPSOIDS
                   && aoEllips[iEllips] )
         {
             char    *pszName = NULL;
@@ -496,11 +496,11 @@ OGRErr OSRExportToPanorama( OGRSpatialReferenceH hSRS,
                             long *piZone, double *padfPrjParams )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRExportToPanorama", CE_Failure );
-    VALIDATE_POINTER1( piProjSys, "OSRExportToPanorama", CE_Failure );
-    VALIDATE_POINTER1( piDatum, "OSRExportToPanorama", CE_Failure );
-    VALIDATE_POINTER1( piEllips, "OSRExportToPanorama", CE_Failure );
-    VALIDATE_POINTER1( padfPrjParams, "OSRExportToPanorama", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRExportToPanorama", OGRERR_FAILURE );
+    VALIDATE_POINTER1( piProjSys, "OSRExportToPanorama", OGRERR_FAILURE );
+    VALIDATE_POINTER1( piDatum, "OSRExportToPanorama", OGRERR_FAILURE );
+    VALIDATE_POINTER1( piEllips, "OSRExportToPanorama", OGRERR_FAILURE );
+    VALIDATE_POINTER1( padfPrjParams, "OSRExportToPanorama", OGRERR_FAILURE );
 
     return ((OGRSpatialReference *) hSRS)->exportToPanorama( piProjSys,
                                                              piDatum, piEllips,
@@ -525,15 +525,15 @@ OGRErr OSRExportToPanorama( OGRSpatialReferenceH hSRS,
  *
  * @param piEllips Pointer to variable, where the spheroid code will be
  * returned.
- * 
+ *
  * @param piZone Pointer to variable, where the zone for UTM projection
  * system will be returned.
  *
  * @param padfPrjParams an existing 7 double buffer into which the
  * projection parameters will be placed. See importFromPanorama()
  * for the list of parameters.
- * 
- * @return OGRERR_NONE on success or an error code on failure. 
+ *
+ * @return OGRERR_NONE on success or an error code on failure.
  */
 
 OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
@@ -576,7 +576,7 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
         *piProjSys = PAN_PROJ_MERCAT;
         padfPrjParams[3] =
             TO_RADIANS * GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
-        padfPrjParams[0] = 
+        padfPrjParams[0] =
             TO_RADIANS * GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
         padfPrjParams[4] = GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 );
         padfPrjParams[5] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
@@ -588,7 +588,7 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
         *piProjSys = PAN_PROJ_PS;
         padfPrjParams[3] =
             TO_RADIANS * GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
-        padfPrjParams[2] = 
+        padfPrjParams[2] =
             TO_RADIANS * GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
         padfPrjParams[4] = GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 );
         padfPrjParams[5] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
@@ -600,7 +600,7 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
         *piProjSys = PAN_PROJ_POLYC;
         padfPrjParams[3] =
             TO_RADIANS * GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
-        padfPrjParams[2] = 
+        padfPrjParams[2] =
             TO_RADIANS * GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
         padfPrjParams[5] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         padfPrjParams[6] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
@@ -611,11 +611,11 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
         *piProjSys = PAN_PROJ_EC;
         padfPrjParams[0] =
             TO_RADIANS * GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 );
-        padfPrjParams[1] = 
+        padfPrjParams[1] =
             TO_RADIANS * GetNormProjParm( SRS_PP_STANDARD_PARALLEL_2, 0.0 );
         padfPrjParams[3] =
             TO_RADIANS * GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
-        padfPrjParams[2] = 
+        padfPrjParams[2] =
             TO_RADIANS * GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
         padfPrjParams[5] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         padfPrjParams[6] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
@@ -626,11 +626,11 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
         *piProjSys = PAN_PROJ_LCC;
         padfPrjParams[0] =
             TO_RADIANS * GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 );
-        padfPrjParams[1] = 
+        padfPrjParams[1] =
             TO_RADIANS * GetNormProjParm( SRS_PP_STANDARD_PARALLEL_2, 0.0 );
         padfPrjParams[3] =
             TO_RADIANS * GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
-        padfPrjParams[2] = 
+        padfPrjParams[2] =
             TO_RADIANS * GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
         padfPrjParams[5] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         padfPrjParams[6] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
@@ -647,13 +647,13 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
             *piProjSys = PAN_PROJ_UTM;
             if( !bNorth )
                 *piZone = - *piZone;
-        }            
+        }
         else
         {
             *piProjSys = PAN_PROJ_TM;
             padfPrjParams[3] =
                 TO_RADIANS * GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
-            padfPrjParams[2] = 
+            padfPrjParams[2] =
                 TO_RADIANS * GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
             padfPrjParams[4] =
                 GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 );
@@ -676,7 +676,7 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
         *piProjSys = PAN_PROJ_STEREO;
         padfPrjParams[3] =
             TO_RADIANS * GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
-        padfPrjParams[2] = 
+        padfPrjParams[2] =
             TO_RADIANS * GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
         padfPrjParams[4] = GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 );
         padfPrjParams[5] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
@@ -688,7 +688,7 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
         *piProjSys = PAN_PROJ_AE;
         padfPrjParams[3] =
             TO_RADIANS * GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 );
-        padfPrjParams[0] = 
+        padfPrjParams[0] =
             TO_RADIANS * GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 );
         padfPrjParams[5] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         padfPrjParams[6] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
@@ -699,7 +699,7 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
         *piProjSys = PAN_PROJ_GNOMON;
         padfPrjParams[3] =
             TO_RADIANS * GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
-        padfPrjParams[2] = 
+        padfPrjParams[2] =
             TO_RADIANS * GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
         padfPrjParams[5] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         padfPrjParams[6] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
@@ -719,7 +719,7 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
         *piProjSys = PAN_PROJ_LAEA;
         padfPrjParams[3] =
             TO_RADIANS * GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
-        padfPrjParams[0] = 
+        padfPrjParams[0] =
             TO_RADIANS * GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
         padfPrjParams[5] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         padfPrjParams[6] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
@@ -730,7 +730,7 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
         *piProjSys = PAN_PROJ_EQC;
         padfPrjParams[3] =
             TO_RADIANS * GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
-        padfPrjParams[0] = 
+        padfPrjParams[0] =
             TO_RADIANS * GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
         padfPrjParams[5] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         padfPrjParams[6] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
@@ -741,7 +741,7 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
         *piProjSys = PAN_PROJ_CEA;
         padfPrjParams[3] =
             TO_RADIANS * GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
-        padfPrjParams[2] = 
+        padfPrjParams[2] =
             TO_RADIANS * GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 );
         padfPrjParams[5] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         padfPrjParams[6] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
@@ -752,9 +752,9 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
         *piProjSys = PAN_PROJ_IMWP;
         padfPrjParams[3] =
             TO_RADIANS * GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
-        padfPrjParams[0] = 
+        padfPrjParams[0] =
             TO_RADIANS * GetNormProjParm( SRS_PP_LATITUDE_OF_1ST_POINT, 0.0 );
-        padfPrjParams[1] = 
+        padfPrjParams[1] =
             TO_RADIANS * GetNormProjParm( SRS_PP_LATITUDE_OF_2ND_POINT, 0.0 );
         padfPrjParams[5] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         padfPrjParams[6] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
@@ -768,7 +768,7 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
                   "Geographic system will be used.", pszProjection );
         *piProjSys = PAN_PROJ_NONE;
     }
- 
+
 /* -------------------------------------------------------------------- */
 /*      Translate the datum.                                            */
 /* -------------------------------------------------------------------- */
@@ -795,14 +795,13 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
     {
         double      dfSemiMajor = GetSemiMajor();
         double      dfInvFlattening = GetInvFlattening();
-        size_t      i;
 
 #ifdef DEBUG
         CPLDebug( "OSR_Panorama",
                   "Datum \"%s\" unsupported by \"Panorama\" GIS. "
                   "Trying to translate an ellipsoid definition.", pszDatum );
 #endif
-       
+
         for ( i = 0; i < NUMBER_OF_ELLIPSOIDS; i++ )
         {
             if ( aoEllips[i] )
@@ -835,4 +834,3 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
 
     return OGRERR_NONE;
 }
-
diff --git a/ogr/ogr_srs_pci.cpp b/ogr/ogr_srs_pci.cpp
index 69dcd49..3af8cfa 100644
--- a/ogr/ogr_srs_pci.cpp
+++ b/ogr/ogr_srs_pci.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_srs_pci.cpp 28565 2015-02-27 10:26:21Z rouault $
+ * $Id: ogr_srs_pci.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGRSpatialReference translation to/from PCI georeferencing
@@ -34,9 +34,9 @@
 #include "cpl_conv.h"
 #include "cpl_csv.h"
 
-CPL_CVSID("$Id: ogr_srs_pci.cpp 28565 2015-02-27 10:26:21Z rouault $");
+CPL_CVSID("$Id: ogr_srs_pci.cpp 33631 2016-03-04 06:28:09Z goatbar $");
 
-typedef struct 
+typedef struct
 {
     const char  *pszPCIDatum;
     int         nEPSGCode;
@@ -102,7 +102,7 @@ static const PCIDatums asEllips[] =
     { "E006", 7042 },     // Everest, 1830
     { "E008", 7019 },     // GRS, 1980 (NAD1983)
     { "E009", 7001 },     // Airy, 1830
-    { "E010", 7018 },     // Modified Everest 
+    { "E010", 7018 },     // Modified Everest
     { "E011", 7002 },     // Modified Airy
     { "E012", 7030 },     // WGS, 1984 (GPS)
     { "E014", 7003 },     // Australian National, 1965
@@ -134,7 +134,7 @@ OGRErr OSRImportFromPCI( OGRSpatialReferenceH hSRS, const char *pszProj,
                          const char *pszUnits, double *padfPrjParams )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRImportFromPCI", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRImportFromPCI", OGRERR_FAILURE );
 
     return ((OGRSpatialReference *) hSRS)->importFromPCI( pszProj,
                                                           pszUnits,
@@ -182,10 +182,10 @@ OGRErr OSRImportFromPCI( OGRSpatialReferenceH hSRS, const char *pszProj,
  * [16] Landsat path number
  *
  * Particular projection uses different parameters, unused ones may be set to
- * zero. If NULL suppliet instead of array pointer default values will be
+ * zero. If NULL is supplied instead of an array pointer, default values will be
  * used (i.e., zeroes).
  *
- * @return OGRERR_NONE on success or an error code in case of failure. 
+ * @return OGRERR_NONE on success or an error code in case of failure.
  */
 
 OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
@@ -203,7 +203,7 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
 /* -------------------------------------------------------------------- */
 /*      Use safe defaults if projection parameters are not supplied.    */
 /* -------------------------------------------------------------------- */
-    int     bProjAllocated = FALSE;
+    bool bProjAllocated = false;
 
     if( padfPrjParams == NULL )
     {
@@ -214,7 +214,7 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
             return OGRERR_NOT_ENOUGH_MEMORY;
         for ( i = 0; i < 17; i++ )
             padfPrjParams[i] = 0.0;
-        bProjAllocated = TRUE;
+        bProjAllocated = true;
     }
 
 /* -------------------------------------------------------------------- */
@@ -234,7 +234,7 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
             int nCode = atoi(pszEM+1);
 
             if( nCode >= -99 && nCode <= 999 )
-                sprintf( szEarthModel, "%c%03d", toupper(*pszEM), nCode );
+                snprintf( szEarthModel, sizeof(szEarthModel), "%c%03d", toupper(*pszEM), nCode );
 
             break;
         }
@@ -242,7 +242,7 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
         pszEM--;
     }
 
-    if( EQUAL(pszEM,"E000") 
+    if( EQUAL(pszEM,"E000")
         || EQUAL(pszEM,"D-01")
         || EQUAL(pszEM,"D-03")
         || EQUAL(pszEM,"D-07")
@@ -251,63 +251,63 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
         || EQUAL(pszEM,"D-13")
         || EQUAL(pszEM,"D-17") )
         bIsNAD27 = TRUE;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Operate on the basis of the projection name.                    */
 /* -------------------------------------------------------------------- */
-    if( EQUALN( pszProj, "LONG/LAT", 8 ) )
+    if( STARTS_WITH_CI(pszProj, "LONG/LAT") )
     {
     }
-    
-    else if( EQUALN( pszProj, "METER", 5 ) 
-             || EQUALN( pszProj, "METRE", 5 ) )
+
+    else if( STARTS_WITH_CI(pszProj, "METER")
+             || STARTS_WITH_CI(pszProj, "METRE") )
     {
         SetLocalCS( "METER" );
         SetLinearUnits( "METER", 1.0 );
     }
 
-    else if( EQUALN( pszProj, "FEET", 4 ) 
-             || EQUALN( pszProj, "FOOT", 4 ) )
+    else if( STARTS_WITH_CI(pszProj, "FEET")
+             || STARTS_WITH_CI(pszProj, "FOOT") )
     {
         SetLocalCS( "FEET" );
         SetLinearUnits( "FEET", CPLAtof(SRS_UL_FOOT_CONV) );
     }
 
-    else if( EQUALN( pszProj, "ACEA", 4 ) )
+    else if( STARTS_WITH_CI(pszProj, "ACEA") )
     {
         SetACEA( padfPrjParams[4], padfPrjParams[5],
                  padfPrjParams[3], padfPrjParams[2],
                  padfPrjParams[6], padfPrjParams[7] );
     }
 
-    else if( EQUALN( pszProj, "AE", 2 ) )
+    else if( STARTS_WITH_CI(pszProj, "AE") )
     {
         SetAE( padfPrjParams[3], padfPrjParams[2],
                padfPrjParams[6], padfPrjParams[7] );
     }
 
-    else if( EQUALN( pszProj, "CASS ", 5 ) )
+    else if( STARTS_WITH_CI(pszProj, "CASS ") )
     {
         SetCS( padfPrjParams[3], padfPrjParams[2],
                padfPrjParams[6], padfPrjParams[7] );
     }
 
-    else if( EQUALN( pszProj, "EC", 2 ) )
+    else if( STARTS_WITH_CI(pszProj, "EC") )
     {
         SetEC( padfPrjParams[4], padfPrjParams[5],
                padfPrjParams[3], padfPrjParams[2],
                padfPrjParams[6], padfPrjParams[7] );
     }
 
-    else if( EQUALN( pszProj, "ER", 2 ) )
+    else if( STARTS_WITH_CI(pszProj, "ER") )
     {
-        // PCI and GCTP don't support natural origin lat. 
+        // PCI and GCTP don't support natural origin lat.
         SetEquirectangular2( 0.0, padfPrjParams[2],
-                             padfPrjParams[3], 
+                             padfPrjParams[3],
                              padfPrjParams[6], padfPrjParams[7] );
     }
 
-    else if( EQUALN( pszProj, "GNO", 3 ) )
+    else if( STARTS_WITH_CI(pszProj, "GNO") )
     {
         SetGnomonic( padfPrjParams[3], padfPrjParams[2],
                      padfPrjParams[6], padfPrjParams[7] );
@@ -317,46 +317,46 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
 
     // FIXME: GOOD -- our Goode's is not the interrupted version from pci
 
-    else if( EQUALN( pszProj, "LAEA", 4 ) )
+    else if( STARTS_WITH_CI(pszProj, "LAEA") )
     {
         SetLAEA( padfPrjParams[3], padfPrjParams[2],
                  padfPrjParams[6], padfPrjParams[7] );
     }
 
-    else if( EQUALN( pszProj, "LCC ", 4 ) )
+    else if( STARTS_WITH_CI(pszProj, "LCC ") )
     {
         SetLCC( padfPrjParams[4], padfPrjParams[5],
                 padfPrjParams[3], padfPrjParams[2],
                 padfPrjParams[6], padfPrjParams[7] );
     }
 
-    else if( EQUALN( pszProj, "LCC_1SP ", 7 ) )
+    else if( STARTS_WITH_CI(pszProj, "LCC_1SP ") )
     {
         SetLCC1SP( padfPrjParams[3], padfPrjParams[2],
                    padfPrjParams[8],
                    padfPrjParams[6], padfPrjParams[7] );
     }
 
-    else if( EQUALN( pszProj, "MC", 2 ) )
+    else if( STARTS_WITH_CI(pszProj, "MC") )
     {
         SetMC( padfPrjParams[3], padfPrjParams[2],
                padfPrjParams[6], padfPrjParams[7] );
     }
 
-    else if( EQUALN( pszProj, "MER", 3 ) )
+    else if( STARTS_WITH_CI(pszProj, "MER") )
     {
         SetMercator( padfPrjParams[3], padfPrjParams[2],
                      (padfPrjParams[8] != 0.0) ? padfPrjParams[8] : 1.0,
                      padfPrjParams[6], padfPrjParams[7] );
     }
 
-    else if( EQUALN( pszProj, "OG", 2 ) )
+    else if( STARTS_WITH_CI(pszProj, "OG") )
     {
         SetOrthographic( padfPrjParams[3], padfPrjParams[2],
                          padfPrjParams[6], padfPrjParams[7] );
     }
 
-    else if( EQUALN( pszProj, "OM ", 3 ) )
+    else if( STARTS_WITH_CI(pszProj, "OM ") )
     {
         if( padfPrjParams[10] == 0.0
             && padfPrjParams[11] == 0.0
@@ -364,14 +364,14 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
             && padfPrjParams[13] == 0.0 )
         {
             SetHOM( padfPrjParams[3], padfPrjParams[2],
-                    padfPrjParams[14], 
+                    padfPrjParams[14],
                     padfPrjParams[14], // use azimuth for grid angle
                     padfPrjParams[8],
                     padfPrjParams[6], padfPrjParams[7] );
         }
         else
         {
-            SetHOM2PNO( padfPrjParams[3], 
+            SetHOM2PNO( padfPrjParams[3],
                         padfPrjParams[11], padfPrjParams[10],
                         padfPrjParams[13], padfPrjParams[12],
                         padfPrjParams[8],
@@ -379,40 +379,40 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
         }
     }
 
-    else if( EQUALN( pszProj, "PC", 2 ) )
+    else if( STARTS_WITH_CI(pszProj, "PC") )
     {
         SetPolyconic( padfPrjParams[3], padfPrjParams[2],
                       padfPrjParams[6], padfPrjParams[7] );
     }
 
-    else if( EQUALN( pszProj, "PS", 2 ) )
+    else if( STARTS_WITH_CI(pszProj, "PS") )
     {
         SetPS( padfPrjParams[3], padfPrjParams[2],
                (padfPrjParams[8] != 0.0) ? padfPrjParams[8] : 1.0,
                padfPrjParams[6], padfPrjParams[7] );
     }
 
-    else if( EQUALN( pszProj, "ROB", 3 ) )
+    else if( STARTS_WITH_CI(pszProj, "ROB") )
     {
         SetRobinson( padfPrjParams[2],
                      padfPrjParams[6], padfPrjParams[7] );
     }
 
-    else if( EQUALN( pszProj, "SGDO", 4 ) )
+    else if( STARTS_WITH_CI(pszProj, "SGDO") )
     {
         SetOS( padfPrjParams[3], padfPrjParams[2],
                (padfPrjParams[8] != 0.0) ? padfPrjParams[8] : 1.0,
                padfPrjParams[6], padfPrjParams[7] );
     }
 
-    else if( EQUALN( pszProj, "SG", 2 ) )
+    else if( STARTS_WITH_CI(pszProj, "SG") )
     {
         SetStereographic( padfPrjParams[3], padfPrjParams[2],
                           (padfPrjParams[8] != 0.0) ? padfPrjParams[8] : 1.0,
                           padfPrjParams[6], padfPrjParams[7] );
     }
 
-    else if( EQUALN( pszProj, "SIN", 3 ) )
+    else if( STARTS_WITH_CI(pszProj, "SIN") )
     {
         SetSinusoidal( padfPrjParams[2],
                        padfPrjParams[6], padfPrjParams[7] );
@@ -420,50 +420,50 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
 
     // FIXME: SOM --- Space Oblique Mercator skipped
 
-    else if( EQUALN( pszProj, "SPCS", 4 ) )
+    else if( STARTS_WITH_CI(pszProj, "SPCS") )
     {
         int     iZone;
 
-        iZone = CPLScanLong( (char *)pszProj + 5, 4 );
+        iZone = (int)CPLScanLong( (char *)pszProj + 5, 4 );
 
         SetStatePlane( iZone, !bIsNAD27 );
         SetLinearUnitsAndUpdateParameters( SRS_UL_METER, 1.0 );
     }
 
-    else if( EQUALN( pszProj, "SPIF", 4 ) )
+    else if( STARTS_WITH_CI(pszProj, "SPIF") )
     {
         int     iZone;
 
-        iZone = CPLScanLong( (char *)pszProj + 5, 4 );
+        iZone = (int)CPLScanLong( (char *)pszProj + 5, 4 );
 
         SetStatePlane( iZone, !bIsNAD27 );
         SetLinearUnitsAndUpdateParameters( SRS_UL_FOOT,
                                            CPLAtof(SRS_UL_FOOT_CONV) );
     }
 
-    else if( EQUALN( pszProj, "SPAF", 4 ) )
+    else if( STARTS_WITH_CI(pszProj, "SPAF") )
     {
         int     iZone;
 
-        iZone = CPLScanLong( (char *)pszProj + 5, 4 );
+        iZone = (int)CPLScanLong( (char *)pszProj + 5, 4 );
 
         SetStatePlane( iZone, !bIsNAD27 );
         SetLinearUnitsAndUpdateParameters( SRS_UL_US_FOOT,
                                            CPLAtof(SRS_UL_US_FOOT_CONV) );
     }
 
-    else if( EQUALN( pszProj, "TM", 2 ) )
+    else if( STARTS_WITH_CI(pszProj, "TM") )
     {
         SetTM( padfPrjParams[3], padfPrjParams[2],
                (padfPrjParams[8] != 0.0) ? padfPrjParams[8] : 1.0,
                padfPrjParams[6], padfPrjParams[7] );
     }
 
-    else if( EQUALN( pszProj, "UTM", 3 ) )
+    else if( STARTS_WITH_CI(pszProj, "UTM") )
     {
         int     iZone, bNorth = TRUE;
 
-        iZone = CPLScanLong( (char *)pszProj + 4, 5 );;
+        iZone = (int)CPLScanLong( (char *)pszProj + 4, 5 );;
         if ( iZone < 0 )
         {
             iZone = -iZone;
@@ -497,11 +497,11 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
                 // an MGRS zone code so we ignore it.
             }
         }
-        
+
         SetUTM( iZone, bNorth );
     }
 
-    else if( EQUALN( pszProj, "VDG", 3 ) )
+    else if( STARTS_WITH_CI(pszProj, "VDG") )
     {
         SetVDG( padfPrjParams[2],
                 padfPrjParams[6], padfPrjParams[7] );
@@ -520,11 +520,11 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
 /* -------------------------------------------------------------------- */
 /*      We have an earthmodel string, look it up in the datum list.     */
 /* -------------------------------------------------------------------- */
-    if( strlen(szEarthModel) > 0 
+    if( strlen(szEarthModel) > 0
         && (poRoot == NULL || IsProjected() || IsGeographic()) )
     {
         const PCIDatums   *pasDatum = asDatums;
-        
+
         // Search for matching datum
         while ( pasDatum->pszPCIDatum )
         {
@@ -537,9 +537,9 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
             }
             pasDatum++;
         }
-        
+
 /* -------------------------------------------------------------------- */
-/*      If we did not find a datum definition in our incode epsg        */
+/*      If we did not find a datum definition in our in-code EPSG        */
 /*      lookup table, then try fetching from the pci_datum.txt          */
 /*      file.                                                           */
 /* -------------------------------------------------------------------- */
@@ -552,14 +552,14 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
 
             if( pszDatumCSV )
                 fp = VSIFOpen( pszDatumCSV, "r" );
-            
+
             if( fp != NULL )
             {
                 char **papszLineItems = NULL;
 
                 while( (papszLineItems = CSVReadParseLine( fp )) != NULL )
                 {
-                    if( CSLCount(papszLineItems) > 3 
+                    if( CSLCount(papszLineItems) > 3
                         && EQUALN(papszLineItems[0],szEarthModel,4) )
                     {
                         papszDatumDefn = papszLineItems;
@@ -572,7 +572,7 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
                 VSIFClose( fp );
             }
         }
-        
+
 /* -------------------------------------------------------------------- */
 /*      If not, look in the ellipsoid/EPSG matching list.               */
 /* -------------------------------------------------------------------- */
@@ -582,7 +582,7 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
             double  dfSemiMajor = 0.0;
             double  dfInvFlattening = 0.0;
             int     nEPSGCode = 0;
-                    
+
             pasDatum = asEllips;
 
             while ( pasDatum->pszPCIDatum )
@@ -590,8 +590,8 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
                 if( EQUALN( szEarthModel, pasDatum->pszPCIDatum, 4 ) )
                 {
                     nEPSGCode = pasDatum->nEPSGCode;
-                    OSRGetEllipsoidInfo( pasDatum->nEPSGCode, &pszName,
-                                         &dfSemiMajor, &dfInvFlattening );
+                    CPL_IGNORE_RET_VAL(OSRGetEllipsoidInfo( pasDatum->nEPSGCode, &pszName,
+                                         &dfSemiMajor, &dfInvFlattening ));
                     break;
 
                 }
@@ -606,17 +606,17 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
             {
                 const char *pszCSV = CSVFilename( "pci_ellips.txt" );
                 FILE *fp = NULL;
-                
+
                 if( pszCSV )
                     fp = VSIFOpen( pszCSV, "r" );
-                
+
                 if( fp != NULL )
                 {
                     char **papszLineItems = NULL;
-                    
+
                     while( (papszLineItems = CSVReadParseLine( fp )) != NULL )
                     {
-                        if( CSLCount(papszLineItems) > 3 
+                        if( CSLCount(papszLineItems) > 3
                             && EQUALN(papszLineItems[0],szEarthModel,4) )
                         {
                             dfSemiMajor = CPLAtof( papszLineItems[2] );
@@ -627,7 +627,7 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
                         CSLDestroy( papszLineItems );
                     }
                     CSLDestroy( papszLineItems );
-                    
+
                     VSIFClose( fp );
                 }
             }
@@ -635,7 +635,7 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
 /* -------------------------------------------------------------------- */
 /*      Custom spheroid?                                                */
 /* -------------------------------------------------------------------- */
-            if( dfSemiMajor == 0.0 && EQUALN(szEarthModel,"E999",4) 
+            if( dfSemiMajor == 0.0 && STARTS_WITH_CI(szEarthModel, "E999")
                 && padfPrjParams[0] != 0.0 )
             {
                 dfSemiMajor = padfPrjParams[0];
@@ -677,13 +677,14 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
                 SetAuthority( "SPHEROID", "EPSG", nEPSGCode );
 
             // Do we have 7 datum shift parameters?
-            if( CSLCount(papszDatumDefn) >= 15 
+            if( papszDatumDefn != NULL &&
+                CSLCount(papszDatumDefn) >= 15
                 && CPLAtof(papszDatumDefn[14]) != 0.0 )
             {
                 double dfScale = CPLAtof(papszDatumDefn[14]);
 
                 // we want scale in parts per million off 1.0
-                // but pci uses a mix of forms. 
+                // but pci uses a mix of forms.
                 if( dfScale >= 0.999 && dfScale <= 1.001 )
                     dfScale = (dfScale-1.0) * 1000000.0;
 
@@ -697,9 +698,10 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
             }
 
             // Do we have 7 datum shift parameters?
-            else if( CSLCount(papszDatumDefn) == 11 
-                     && (CPLAtof(papszDatumDefn[3]) != 0.0 
-                         || CPLAtof(papszDatumDefn[4]) != 0.0 
+            else if( papszDatumDefn != NULL &&
+                     CSLCount(papszDatumDefn) == 11
+                     && (CPLAtof(papszDatumDefn[3]) != 0.0
+                         || CPLAtof(papszDatumDefn[4]) != 0.0
                          || CPLAtof(papszDatumDefn[5]) != 0.0 ) )
             {
                 SetTOWGS84( CPLAtof(papszDatumDefn[3]),
@@ -735,7 +737,7 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
 /************************************************************************/
 /*                          OSRExportToPCI()                            */
 /************************************************************************/
-/** 
+/**
  * \brief Export coordinate system in PCI projection definition.
  *
  * This function is the same as OGRSpatialReference::exportToPCI().
@@ -745,7 +747,7 @@ OGRErr OSRExportToPCI( OGRSpatialReferenceH hSRS,
                        double **ppadfPrjParams )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRExportToPCI", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRExportToPCI", OGRERR_FAILURE );
 
     *ppszProj = NULL;
     *ppszUnits = NULL;
@@ -768,21 +770,21 @@ OGRErr OSRExportToPCI( OGRSpatialReferenceH hSRS,
  * with CPLFree() when no longer needed.
  *
  * LOCAL_CS coordinate systems are not translatable.  An empty string
- * will be returned along with OGRERR_NONE.  
+ * will be returned along with OGRERR_NONE.
  *
- * This method is the equivelent of the C function OSRExportToPCI().
+ * This method is the equivalent of the C function OSRExportToPCI().
  *
  * @param ppszProj pointer to which dynamically allocated PCI projection
  * definition will be assigned.
- * 
- * @param ppszUnits pointer to which dynamically allocated units definition 
+ *
+ * @param ppszUnits pointer to which dynamically allocated units definition
  * will be assigned.
  *
  * @param ppadfPrjParams pointer to which dynamically allocated array of
  * 17 projection parameters will be assigned. See importFromPCI() for the list
  * of parameters.
- * 
- * @return OGRERR_NONE on success or an error code on failure. 
+ *
+ * @return OGRERR_NONE on success or an error code on failure.
  */
 
 OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
@@ -1066,7 +1068,7 @@ OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
                 CPLPrintInt32( szProj + 5, nZone, 4 );
             else
                 CPLPrintInt32( szProj + 5, -nZone, 4 );
-        }            
+        }
         else
         {
             CPLPrintStringFill( szProj, "TM", 16 );
@@ -1096,7 +1098,7 @@ OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
                   "PIXEL value will be used.", pszProjection );
         CPLPrintStringFill( szProj, "PIXEL", 16 );
     }
-    
+
 /* ==================================================================== */
 /*      Translate the earth model.                                      */
 /* ==================================================================== */
@@ -1127,12 +1129,11 @@ OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
     if( szEarthModel[0] == '\0' )
     {
         const char *pszAuthority = GetAuthorityName("GEOGCS");
-        
+
         if( pszAuthority && EQUAL(pszAuthority,"EPSG") )
         {
             int nGCS_EPSG = atoi(GetAuthorityCode("GEOGCS"));
-            int i;
-            
+
             for( i = 0; asDatums[i].nEPSGCode != 0; i++ )
             {
                 if( asDatums[i].nEPSGCode == nGCS_EPSG )
@@ -1181,18 +1182,19 @@ OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
 
             if( pszCSV )
                 fp = VSIFOpen( pszCSV, "r" );
-        
+
             if( fp != NULL )
             {
                 char **papszLineItems = NULL;
-                
+
                 while( (papszLineItems = CSVReadParseLine( fp )) != NULL )
                 {
-                    if( CSLCount(papszLineItems) >= 4 
+                    if( CSLCount(papszLineItems) >= 4
                         && CPLIsEqual(dfSemiMajor,CPLAtof(papszLineItems[2]))
                         && CPLIsEqual(dfSemiMinor,CPLAtof(papszLineItems[3])) )
                     {
                         strncpy( szEarthModel, papszLineItems[0], 5 );
+                        szEarthModel[4] = '\0';
                         break;
                     }
 
@@ -1201,12 +1203,12 @@ OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
 
                 CSLDestroy( papszLineItems );
                 VSIFClose( fp );
-            }            
+            }
         }
 
         // custom ellipsoid parameters
         if( szEarthModel[0] == '\0' )
-        {                                   
+        {
             CPLPrintStringFill( szEarthModel, "E999", 4 );
             (*ppadfPrjParams)[0] = dfSemiMajor;
             (*ppadfPrjParams)[1] = OSRCalcSemiMinorFromInvFlattening(dfSemiMajor, dfInvFlattening);
@@ -1217,7 +1219,7 @@ OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
 /*      If we have a non-parameteric ellipsoid, scan the                */
 /*      pci_datum.txt for a match.                                      */
 /* -------------------------------------------------------------------- */
-    if( szEarthModel[0] == 'E' 
+    if( szEarthModel[0] == 'E'
         && !EQUAL(szEarthModel,"E999")
         && pszDatum != NULL )
     {
@@ -1227,24 +1229,25 @@ OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
         int    bHaveTOWGS84;
 
         bHaveTOWGS84 = (GetTOWGS84( adfTOWGS84, 7 ) == OGRERR_NONE);
-        
+
         if( pszDatumCSV )
             fp = VSIFOpen( pszDatumCSV, "r" );
-        
+
         if( fp != NULL )
         {
             char **papszLineItems = NULL;
-            
+
             while( (papszLineItems = CSVReadParseLine( fp )) != NULL )
             {
                 // Compare based on datum name.  This is mostly for
                 // PCI round-tripping.  We won't usually get exact matches
                 // from other sources.
-                if( CSLCount(papszLineItems) > 3 
+                if( CSLCount(papszLineItems) > 3
                     && EQUAL(papszLineItems[1],pszDatum)
                     && EQUAL(papszLineItems[2],szEarthModel) )
                 {
                     strncpy( szEarthModel, papszLineItems[0], 5 );
+                    szEarthModel[4] = '\0';
                     break;
                 }
 
@@ -1253,13 +1256,13 @@ OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
                 if( CSLCount(papszLineItems) < 11 )
                     bTOWGS84Match = FALSE;
 
-                if( bTOWGS84Match 
+                if( bTOWGS84Match
                     && (!CPLIsEqual(adfTOWGS84[0],CPLAtof(papszLineItems[3]))
                         || !CPLIsEqual(adfTOWGS84[1],CPLAtof(papszLineItems[4]))
                         || !CPLIsEqual(adfTOWGS84[2],CPLAtof(papszLineItems[5]))))
                     bTOWGS84Match = FALSE;
 
-                if( bTOWGS84Match && CSLCount(papszLineItems) >= 15 
+                if( bTOWGS84Match && CSLCount(papszLineItems) >= 15
                     && (!CPLIsEqual(adfTOWGS84[3],CPLAtof(papszLineItems[11]))
                         || !CPLIsEqual(adfTOWGS84[4],CPLAtof(papszLineItems[12]))
                         || !CPLIsEqual(adfTOWGS84[5],CPLAtof(papszLineItems[13]))))
@@ -1287,12 +1290,13 @@ OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
                 if( bTOWGS84Match )
                 {
                     strncpy( szEarthModel, papszLineItems[0], 5 );
+                    szEarthModel[4] = '\0';
                     break;
                 }
 
                 CSLDestroy( papszLineItems );
             }
-        
+
             CSLDestroy( papszLineItems );
             VSIFClose( fp );
         }
@@ -1306,8 +1310,8 @@ OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
 /*      Translate the linear units.                                     */
 /* -------------------------------------------------------------------- */
     const char  *pszUnits;
-        
-    if( EQUALN( szProj, "LONG/LAT", 8 ) )
+
+    if( STARTS_WITH_CI(szProj, "LONG/LAT") )
         pszUnits = "DEGREE";
     else
         pszUnits = "METRE";
diff --git a/ogr/ogr_srs_proj4.cpp b/ogr/ogr_srs_proj4.cpp
index 1a6db83..74941f4 100644
--- a/ogr/ogr_srs_proj4.cpp
+++ b/ogr/ogr_srs_proj4.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: ogr_srs_proj4.cpp 29114 2015-05-02 20:19:13Z rouault $
+ * $Id: ogr_srs_proj4.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGRSpatialReference interface to PROJ.4.
  * Author:   Frank Warmerdam <warmerdam at pobox.com>
  *
  ******************************************************************************
- * Copyright (c) 1999,  Les Technologies SoftMap Inc. 
+ * Copyright (c) 1999,  Les Technologies SoftMap Inc.
  * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
  * Copyright (c) 2014, Kyle Shannon <kyle at pobox dot com>
  *
@@ -36,13 +36,13 @@
 
 extern int EPSGGetWGS84Transform( int nGeogCS, std::vector<CPLString>& asTransform );
 
-CPL_CVSID("$Id: ogr_srs_proj4.cpp 29114 2015-05-02 20:19:13Z rouault $");
+CPL_CVSID("$Id: ogr_srs_proj4.cpp 33631 2016-03-04 06:28:09Z goatbar $");
 
 /* -------------------------------------------------------------------- */
-/*      The following list comes from osrs/proj/src/pj_ellps.c          */
-/*      ... please update from time to time.                            */
+/*      The following list comes from osrs/proj/src/pj_ellps.c.         */
+/*      Please update from time to time.                                */
 /* -------------------------------------------------------------------- */
-static const char *ogr_pj_ellps[] = {
+static const char * const ogr_pj_ellps[] = {
 "MERIT",        "a=6378137.0", "rf=298.257", "MERIT 1983",
 "SGS85",        "a=6378136.0", "rf=298.257",  "Soviet Geodetic System 85",
 "GRS80",        "a=6378137.0", "rf=298.257222101", "GRS 1980(IUGG, 1980)",
@@ -85,7 +85,7 @@ static const char *ogr_pj_ellps[] = {
 "WGS72",        "a=6378135.0", "rf=298.26", "WGS 72",
 "WGS84",    "a=6378137.0",  "rf=298.257223563", "WGS 84",
 "sphere",   "a=6370997.0",  "b=6370997.0", "Normal Sphere (r=6370997)",
-0, 0, 0, 0,
+NULL, NULL, NULL, NULL,
 };
 
 typedef struct
@@ -136,8 +136,7 @@ static const OGRProj4PM ogr_pj_pms [] = {
 static const char* OGRGetProj4Datum(const char* pszDatum,
                                     int nEPSGDatum)
 {
-    unsigned int i;
-    for(i=0;i<sizeof(ogr_pj_datums)/sizeof(ogr_pj_datums[0]);i++)
+    for(size_t i=0;i<sizeof(ogr_pj_datums)/sizeof(ogr_pj_datums[0]);i++)
     {
         if (nEPSGDatum == ogr_pj_datums[i].nGCS ||
             EQUAL(pszDatum, ogr_pj_datums[i].pszOGR))
@@ -150,8 +149,7 @@ static const char* OGRGetProj4Datum(const char* pszDatum,
 
 static const OGRProj4PM* OGRGetProj4PMFromProj4Name(const char* pszProj4PMName)
 {
-    unsigned int i;
-    for(i=0;i<sizeof(ogr_pj_pms)/sizeof(ogr_pj_pms[0]);i++)
+    for(size_t i=0;i<sizeof(ogr_pj_pms)/sizeof(ogr_pj_pms[0]);i++)
     {
         if (EQUAL(pszProj4PMName, ogr_pj_pms[i].pszProj4PMName))
         {
@@ -163,8 +161,7 @@ static const OGRProj4PM* OGRGetProj4PMFromProj4Name(const char* pszProj4PMName)
 
 static const OGRProj4PM* OGRGetProj4PMFromCode(int nPMCode)
 {
-    unsigned int i;
-    for(i=0;i<sizeof(ogr_pj_pms)/sizeof(ogr_pj_pms[0]);i++)
+    for(size_t i=0;i<sizeof(ogr_pj_pms)/sizeof(ogr_pj_pms[0]);i++)
     {
         if (nPMCode == ogr_pj_pms[i].nPMCode)
         {
@@ -187,6 +184,95 @@ static const OGRProj4PM* OGRGetProj4PMFromVal(double dfVal)
     return NULL;
 }
 
+typedef struct
+{
+    const char* pszWKTName;
+    const char* pszValueInMeter;
+    const char* pszProjName;
+} LinearUnitsStruct;
+
+static const LinearUnitsStruct asLinearUnits [] =
+{
+{ SRS_UL_METER, "1.0", "m" },
+{ SRS_UL_METER, "1.0", "meter" }, // alias of former
+{ SRS_UL_METER, "1.0", "metre" }, // alias of former
+{ "metre", "1.0", "m" }, // alias of former
+{ "kilometre", SRS_UL_KILOMETER_CONV, "km" }, // Leave as 'kilometre' instead of SRS_UL_KILOMETER due to historical usage
+{ SRS_UL_KILOMETER, SRS_UL_KILOMETER_CONV, "km" }, // alias of former
+{ SRS_UL_DECIMETER, SRS_UL_DECIMETER_CONV, "dm" },
+{ SRS_UL_CENTIMETER, SRS_UL_CENTIMETER_CONV, "cm" },
+{ SRS_UL_MILLIMETER, SRS_UL_MILLIMETER_CONV, "mm" },
+
+{ SRS_UL_FOOT, SRS_UL_FOOT_CONV, "ft" }, // Leave as 'Foot (International)' or SRS_UL_FOOT instead of SRS_UL_INTL_FOOT due to historical usage
+{ SRS_UL_INTL_FOOT, SRS_UL_INTL_FOOT_CONV, "ft" }, // alias of former
+{ SRS_UL_US_FOOT, SRS_UL_US_FOOT_CONV, "us-ft" },
+{ SRS_UL_INDIAN_FOOT, SRS_UL_INDIAN_FOOT_CONV, "ind-ft" },
+
+{ SRS_UL_INTL_NAUT_MILE, SRS_UL_INTL_NAUT_MILE_CONV, "kmi" },
+{ SRS_UL_NAUTICAL_MILE, SRS_UL_NAUTICAL_MILE_CONV, "kmi" }, // alias of former
+
+{ SRS_UL_INTL_STAT_MILE, SRS_UL_INTL_STAT_MILE_CONV, "mi" },
+{ "Mile", SRS_UL_INTL_STAT_MILE_CONV, "mi" }, // alias of former
+{ "IMILE", SRS_UL_INTL_STAT_MILE_CONV, "mi" }, // alias of former
+{ SRS_UL_US_STAT_MILE, SRS_UL_US_STAT_MILE_CONV, "us-mi"},
+
+{ SRS_UL_INTL_LINK, SRS_UL_INTL_LINK_CONV, "link" },
+{ SRS_UL_LINK, SRS_UL_LINK_CONV, "link" }, // alias of former
+
+{ SRS_UL_INTL_YARD, SRS_UL_INTL_YARD_CONV, "yd" },
+{ "IYARD", SRS_UL_INTL_YARD_CONV, "yd" }, // alias of former
+{ SRS_UL_US_YARD, SRS_UL_US_YARD_CONV, "us-yd" },
+{ SRS_UL_INDIAN_YARD, SRS_UL_INDIAN_YARD_CONV, "ind-yd" },
+
+{ SRS_UL_INTL_INCH, SRS_UL_INTL_INCH_CONV, "in" },
+{ SRS_UL_US_INCH, SRS_UL_US_INCH_CONV, "us-in" },
+
+{ SRS_UL_INTL_FATHOM, SRS_UL_INTL_FATHOM_CONV, "fath" },
+
+{ SRS_UL_INTL_CHAIN, SRS_UL_INTL_CHAIN_CONV, "ch" },
+{ SRS_UL_US_CHAIN, SRS_UL_US_CHAIN_CONV, "us-ch" },
+{ SRS_UL_INDIAN_CHAIN, SRS_UL_INDIAN_CHAIN_CONV, "ind-ch" },
+
+// { SRS_UL_ROD, SRS_UL_ROD_CONV, "????" }
+};
+
+/************************************************************************/
+/*                        GetLinearFromLinearConvOrName()               */
+/************************************************************************/
+
+static const LinearUnitsStruct *GetLinearFromLinearConvOrName(
+                                                  double dfLinearConv,
+                                                  const char *pszLinearUnits )
+
+{
+    for( size_t i=0; i < sizeof(asLinearUnits) / sizeof(asLinearUnits[0]); i++ )
+    {
+        if( (pszLinearUnits != NULL && EQUAL(pszLinearUnits, asLinearUnits[i].pszWKTName)) ||
+            fabs(dfLinearConv - CPLAtof(asLinearUnits[i].pszValueInMeter)) < 0.00000001 )
+        {
+            return &(asLinearUnits[i]);
+        }
+    }
+    return NULL;
+}
+
+/************************************************************************/
+/*                        GetLinearFromProjName()                       */
+/************************************************************************/
+
+static const LinearUnitsStruct* GetLinearFromProjName( const char* pszProjName )
+
+{
+    for( size_t i=0; i < sizeof(asLinearUnits) / sizeof(asLinearUnits[0]); i++ )
+    {
+        if( EQUAL(pszProjName, asLinearUnits[i].pszProjName) )
+        {
+            return &(asLinearUnits[i]);
+        }
+    }
+    return NULL;
+}
+
 /************************************************************************/
 /*                          OSRProj4Tokenize()                          */
 /*                                                                      */
@@ -195,20 +281,17 @@ static const OGRProj4PM* OGRGetProj4PMFromVal(double dfVal)
 /*      strings with a + sign in the exponents of parameter values.     */
 /************************************************************************/
 
-char **OSRProj4Tokenize( const char *pszFull )
+static char **OSRProj4Tokenize( const char *pszFull )
 
 {
-    char *pszStart = NULL;
-    char *pszFullWrk;
-    char **papszTokens = NULL;
-    int  i;
-
     if( pszFull == NULL )
         return NULL;
 
-    pszFullWrk = CPLStrdup( pszFull );
+    char *pszFullWrk = CPLStrdup( pszFull );
+    char *pszStart = NULL;
+    char **papszTokens = NULL;
 
-    for( i=0; pszFullWrk[i] != '\0'; i++ )
+    for( int i=0; pszFullWrk[i] != '\0'; i++ )
     {
         switch( pszFullWrk[i] )
         {
@@ -253,7 +336,7 @@ char **OSRProj4Tokenize( const char *pszFull )
 /************************************************************************/
 /*                         OSRImportFromProj4()                         */
 /************************************************************************/
-/** 
+/**
  * \brief Import PROJ.4 coordinate string.
  *
  * This function is the same as OGRSpatialReference::importFromProj4().
@@ -261,7 +344,7 @@ char **OSRProj4Tokenize( const char *pszFull )
 OGRErr OSRImportFromProj4( OGRSpatialReferenceH hSRS, const char *pszProj4 )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRImportFromProj4", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRImportFromProj4", OGRERR_FAILURE );
 
     return ((OGRSpatialReference *) hSRS)->importFromProj4( pszProj4 );
 }
@@ -274,13 +357,11 @@ OGRErr OSRImportFromProj4( OGRSpatialReferenceH hSRS, const char *pszProj4 )
 /*      helper function for importFromProj4().                          */
 /************************************************************************/
 
-static double OSR_GDV( char **papszNV, const char * pszField, 
+static double OSR_GDV( char **papszNV, const char * pszField,
                        double dfDefaultValue )
 
 {
-    const char * pszValue;
-
-    pszValue = CSLFetchNameValue( papszNV, pszField );
+    const char *pszValue = CSLFetchNameValue( papszNV, pszField );
 
     // special hack to use k_0 if available.
     if( pszValue == NULL && EQUAL(pszField,"k") )
@@ -301,19 +382,19 @@ static double OSR_GDV( char **papszNV, const char * pszField,
  *
  * The OGRSpatialReference is initialized from the passed PROJ.4 style
  * coordinate system string.  In addition to many +proj formulations which
- * have OGC equivelents, it is also possible to import "+init=epsg:n" style
+ * have OGC equivalents, it is also possible to import "+init=epsg:n" style
  * definitions.  These are passed to importFromEPSG().  Other init strings
- * (such as the state plane zones) are not currently supported.   
+ * (such as the state plane zones) are not currently supported.
  *
  * Example:
- *   pszProj4 = "+proj=utm +zone=11 +datum=WGS84" 
+ *   pszProj4 = "+proj=utm +zone=11 +datum=WGS84"
  *
- * Some parameters, such as grids, recognised by PROJ.4 may not be well
+ * Some parameters, such as grids, recognized by PROJ.4 may not be well
  * understood and translated into the OGRSpatialReference model. It is possible
- * to add the +wktext parameter which is a special keyword that OGR recognises
+ * to add the +wktext parameter which is a special keyword that OGR recognized
  * as meaning "embed the entire PROJ.4 string in the WKT and use it literally
  * when converting back to PROJ.4 format".
- * 
+ *
  * For example:
  * "+proj=nzmg +lat_0=-41 +lon_0=173 +x_0=2510000 +y_0=6023150 +ellps=intl
  *  +units=m +nadgrids=nzgd2kgrid0005.gsb +wktext"
@@ -332,7 +413,7 @@ static double OSR_GDV( char **papszNV, const char * pszField,
  *    PARAMETER["false_easting",2510000],
  *    PARAMETER["false_northing",6023150],
  *    UNIT["Meter",1],
- *    EXTENSION["PROJ4","+proj=nzmg +lat_0=-41 +lon_0=173 +x_0=2510000 
+ *    EXTENSION["PROJ4","+proj=nzmg +lat_0=-41 +lon_0=173 +x_0=2510000
  *               +y_0=6023150 +ellps=intl  +units=m +nadgrids=nzgd2kgrid0005.gsb +wktext"]]
  * \endcode
  *
@@ -370,7 +451,7 @@ static double OSR_GDV( char **papszNV, const char * pszField,
  *
  * This method is the equivalent of the C function OSRImportFromProj4().
  *
- * @param pszProj4 the PROJ.4 style string. 
+ * @param pszProj4 the PROJ.4 style string.
  *
  * @return OGRERR_NONE on success or OGRERR_CORRUPT_DATA on failure.
  */
@@ -378,12 +459,6 @@ static double OSR_GDV( char **papszNV, const char * pszField,
 OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
 
 {
-    char **papszNV = NULL;
-    char **papszTokens;
-    int  i;
-    char *pszCleanCopy;
-    int   bAddProj4Extension = FALSE;
-
 /* -------------------------------------------------------------------- */
 /*      Clear any existing definition.                                  */
 /* -------------------------------------------------------------------- */
@@ -393,11 +468,11 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
 /*      Strip any newlines or other "funny" stuff that might occur      */
 /*      if this string just came from reading a file.                   */
 /* -------------------------------------------------------------------- */
-    pszCleanCopy = CPLStrdup( pszProj4 );
-    for( i = 0; pszCleanCopy[i] != '\0'; i++ )
+    char *pszCleanCopy = CPLStrdup( pszProj4 );
+    for( int i = 0; pszCleanCopy[i] != '\0'; i++ )
     {
-        if( pszCleanCopy[i] == 10 
-            || pszCleanCopy[i] == 13 
+        if( pszCleanCopy[i] == 10
+            || pszCleanCopy[i] == 13
             || pszCleanCopy[i] == 9 )
             pszCleanCopy[i] = ' ';
     }
@@ -406,19 +481,17 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
 /*      Try to normalize the definition.  This should expand +init=     */
 /*      clauses and so forth.                                           */
 /* -------------------------------------------------------------------- */
-    char *pszNormalized;
-
-    pszNormalized = OCTProj4Normalize( pszCleanCopy );
+    char *pszNormalized = OCTProj4Normalize( pszCleanCopy );
 
     /* Workaround proj.4 bug (#239) by manually re-adding no_off/no_uoff */
-    if( strstr(pszCleanCopy, "+no_off") != NULL && 
+    if( strstr(pszCleanCopy, "+no_off") != NULL &&
         strstr(pszNormalized, "+no_off") == NULL )
     {
         char* pszTmp = CPLStrdup(CPLSPrintf("%s +no_off", pszNormalized));
         CPLFree(pszNormalized);
         pszNormalized = pszTmp;
     }
-    else if( strstr(pszCleanCopy, "+no_uoff") != NULL && 
+    else if( strstr(pszCleanCopy, "+no_uoff") != NULL &&
         strstr(pszNormalized, "+no_uoff") == NULL )
     {
         char* pszTmp = CPLStrdup(CPLSPrintf("%s +no_uoff", pszNormalized));
@@ -427,18 +500,17 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
     }
 
     CPLFree( pszCleanCopy );
-    
+
 /* -------------------------------------------------------------------- */
 /*      If we have an EPSG based init string, and no existing +proj     */
 /*      portion then try to normalize into into a PROJ.4 string.        */
 /* -------------------------------------------------------------------- */
-    if( strstr(pszNormalized,"init=epsg:") != NULL 
+    if( strstr(pszNormalized,"init=epsg:") != NULL
         && strstr(pszNormalized,"proj=") == NULL )
     {
-        OGRErr eErr;
         const char *pszNumber = strstr(pszNormalized,"init=epsg:") + 10;
 
-        eErr = importFromEPSG( atoi(pszNumber) );
+        OGRErr eErr = importFromEPSG( atoi(pszNumber) );
         if( eErr == OGRERR_NONE )
         {
             CPLFree( pszNormalized );
@@ -450,10 +522,11 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
 /*      Parse the PROJ.4 string into a cpl_string.h style name/value    */
 /*      list.                                                           */
 /* -------------------------------------------------------------------- */
-    papszTokens = OSRProj4Tokenize( pszNormalized );
+    char **papszTokens = OSRProj4Tokenize( pszNormalized );
     CPLFree( pszNormalized );
-    
-    for( i = 0; papszTokens != NULL && papszTokens[i] != NULL; i++ )
+    char **papszNV = NULL;
+
+    for( int i = 0; papszTokens != NULL && papszTokens[i] != NULL; i++ )
     {
         char *pszEqual = strstr(papszTokens[i],"=");
 
@@ -472,7 +545,7 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
 /*      Extract the prime meridian, if there is one set.                */
 /* -------------------------------------------------------------------- */
     const char *pszPM = CSLFetchNameValue( papszNV, "pm" );
-    double dfFromGreenwich = 0.0;
+    double l_dfFromGreenwich = 0.0;
     /* int    nPMCode = -1; */
 
     if( pszPM != NULL )
@@ -480,13 +553,13 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
         const OGRProj4PM* psProj4PM = OGRGetProj4PMFromProj4Name(pszPM);
         if (psProj4PM)
         {
-            dfFromGreenwich = CPLDMSToDec(psProj4PM->pszFromGreenwich);
+            l_dfFromGreenwich = CPLDMSToDec(psProj4PM->pszFromGreenwich);
             pszPM = psProj4PM->pszWKTPMName;
             /* nPMCode = psProj4PM->nPMCode; */
         }
         else
         {
-            dfFromGreenwich = CPLDMSToDec( pszPM );
+            l_dfFromGreenwich = CPLDMSToDec( pszPM );
             pszPM = "unnamed";
         }
     }
@@ -497,6 +570,7 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
 /*      Operate on the basis of the projection name.                    */
 /* -------------------------------------------------------------------- */
     const char *pszProj = CSLFetchNameValue(papszNV,"proj");
+    bool bAddProj4Extension = false;
 
     if( pszProj == NULL )
     {
@@ -508,41 +582,41 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
     else if( EQUAL(pszProj,"longlat") || EQUAL(pszProj,"latlong") )
     {
     }
-    
+
     else if( EQUAL(pszProj,"geocent") )
     {
         SetGeocCS( "Geocentric" );
     }
-    
+
     else if( EQUAL(pszProj,"bonne") )
     {
-        SetBonne( OSR_GDV( papszNV, "lat_1", 0.0 ), 
-                  OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                  OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetBonne( OSR_GDV( papszNV, "lat_1", 0.0 ),
+                  OSR_GDV( papszNV, "lon_0", 0.0 ),
+                  OSR_GDV( papszNV, "x_0", 0.0 ),
                   OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(pszProj,"cass") )
     {
-        SetCS( OSR_GDV( papszNV, "lat_0", 0.0 ), 
-               OSR_GDV( papszNV, "lon_0", 0.0 ), 
-               OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetCS( OSR_GDV( papszNV, "lat_0", 0.0 ),
+               OSR_GDV( papszNV, "lon_0", 0.0 ),
+               OSR_GDV( papszNV, "x_0", 0.0 ),
                OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(pszProj,"nzmg") )
     {
-        SetNZMG( OSR_GDV( papszNV, "lat_0", -41.0 ), 
-                 OSR_GDV( papszNV, "lon_0", 173.0 ), 
-                 OSR_GDV( papszNV, "x_0", 2510000.0 ), 
+        SetNZMG( OSR_GDV( papszNV, "lat_0", -41.0 ),
+                 OSR_GDV( papszNV, "lon_0", 173.0 ),
+                 OSR_GDV( papszNV, "x_0", 2510000.0 ),
                  OSR_GDV( papszNV, "y_0", 6023150.0 ) );
     }
 
     else if( EQUAL(pszProj,"cea") )
     {
-        SetCEA( OSR_GDV( papszNV, "lat_ts", 0.0 ), 
-                OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetCEA( OSR_GDV( papszNV, "lat_ts", 0.0 ),
+                OSR_GDV( papszNV, "lon_0", 0.0 ),
+                OSR_GDV( papszNV, "x_0", 0.0 ),
                 OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
@@ -551,31 +625,31 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
         const char *pszAxis = CSLFetchNameValue( papszNV, "axis" );
 
         if( pszAxis == NULL || !EQUAL(pszAxis,"wsu") )
-            SetTM( OSR_GDV( papszNV, "lat_0", 0.0 ), 
-                   OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                   OSR_GDV( papszNV, "k", 1.0 ), 
-                   OSR_GDV( papszNV, "x_0", 0.0 ), 
+            SetTM( OSR_GDV( papszNV, "lat_0", 0.0 ),
+                   OSR_GDV( papszNV, "lon_0", 0.0 ),
+                   OSR_GDV( papszNV, "k", 1.0 ),
+                   OSR_GDV( papszNV, "x_0", 0.0 ),
                    OSR_GDV( papszNV, "y_0", 0.0 ) );
         else
-            SetTMSO( OSR_GDV( papszNV, "lat_0", 0.0 ), 
-                     OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                     OSR_GDV( papszNV, "k", 1.0 ), 
-                     OSR_GDV( papszNV, "x_0", 0.0 ), 
+            SetTMSO( OSR_GDV( papszNV, "lat_0", 0.0 ),
+                     OSR_GDV( papszNV, "lon_0", 0.0 ),
+                     OSR_GDV( papszNV, "k", 1.0 ),
+                     OSR_GDV( papszNV, "x_0", 0.0 ),
                      OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     /* For etmerc, we translate it into standard TM for the WKT */
     /* point of view, but make sure that the original proj.4 */
     /* definition is preserved for accurate reprojection */
-    else if( EQUAL(pszProj,"etmerc") && 
+    else if( EQUAL(pszProj,"etmerc") &&
              CSLFetchNameValue( papszNV, "axis" ) == NULL )
     {
-        bAddProj4Extension = TRUE;
+        bAddProj4Extension = true;
 
-        SetTM( OSR_GDV( papszNV, "lat_0", 0.0 ), 
-                OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                OSR_GDV( papszNV, "k", 1.0 ), 
-                OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetTM( OSR_GDV( papszNV, "lat_0", 0.0 ),
+                OSR_GDV( papszNV, "lon_0", 0.0 ),
+                OSR_GDV( papszNV, "k", 1.0 ),
+                OSR_GDV( papszNV, "x_0", 0.0 ),
                 OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
@@ -588,57 +662,57 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
     else if( EQUAL(pszProj,"merc") /* 2SP form */
              && OSR_GDV(papszNV, "lat_ts", 1000.0) < 999.0 )
     {
-        SetMercator2SP( OSR_GDV( papszNV, "lat_ts", 0.0 ), 
+        SetMercator2SP( OSR_GDV( papszNV, "lat_ts", 0.0 ),
                         0.0,
-                        OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                        OSR_GDV( papszNV, "x_0", 0.0 ), 
+                        OSR_GDV( papszNV, "lon_0", 0.0 ),
+                        OSR_GDV( papszNV, "x_0", 0.0 ),
                         OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(pszProj,"merc") ) /* 1SP form */
     {
         SetMercator( 0.0,
-                     OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                     OSR_GDV( papszNV, "k", 1.0 ), 
-                     OSR_GDV( papszNV, "x_0", 0.0 ), 
+                     OSR_GDV( papszNV, "lon_0", 0.0 ),
+                     OSR_GDV( papszNV, "k", 1.0 ),
+                     OSR_GDV( papszNV, "x_0", 0.0 ),
                      OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
-    else if( EQUAL(pszProj,"stere") 
+    else if( EQUAL(pszProj,"stere")
              && ABS(OSR_GDV( papszNV, "lat_0", 0.0 ) - 90) < 0.001 )
     {
-        SetPS( OSR_GDV( papszNV, "lat_ts", 90.0 ), 
-               OSR_GDV( papszNV, "lon_0", 0.0 ), 
-               OSR_GDV( papszNV, "k", 1.0 ), 
-               OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetPS( OSR_GDV( papszNV, "lat_ts", 90.0 ),
+               OSR_GDV( papszNV, "lon_0", 0.0 ),
+               OSR_GDV( papszNV, "k", 1.0 ),
+               OSR_GDV( papszNV, "x_0", 0.0 ),
                OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
-    else if( EQUAL(pszProj,"stere") 
+    else if( EQUAL(pszProj,"stere")
              && ABS(OSR_GDV( papszNV, "lat_0", 0.0 ) + 90) < 0.001 )
     {
-        SetPS( OSR_GDV( papszNV, "lat_ts", -90.0 ), 
-               OSR_GDV( papszNV, "lon_0", 0.0 ), 
-               OSR_GDV( papszNV, "k", 1.0 ), 
-               OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetPS( OSR_GDV( papszNV, "lat_ts", -90.0 ),
+               OSR_GDV( papszNV, "lon_0", 0.0 ),
+               OSR_GDV( papszNV, "k", 1.0 ),
+               OSR_GDV( papszNV, "x_0", 0.0 ),
                OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(pszProj,"sterea") )
     {
-        SetOS( OSR_GDV( papszNV, "lat_0", 0.0 ), 
-               OSR_GDV( papszNV, "lon_0", 0.0 ), 
-               OSR_GDV( papszNV, "k", 1.0 ), 
-               OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetOS( OSR_GDV( papszNV, "lat_0", 0.0 ),
+               OSR_GDV( papszNV, "lon_0", 0.0 ),
+               OSR_GDV( papszNV, "k", 1.0 ),
+               OSR_GDV( papszNV, "x_0", 0.0 ),
                OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(pszProj,"stere") )
     {
-        SetStereographic( OSR_GDV( papszNV, "lat_0", 0.0 ), 
-                          OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                          OSR_GDV( papszNV, "k", 1.0 ),  
-                          OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetStereographic( OSR_GDV( papszNV, "lat_0", 0.0 ),
+                          OSR_GDV( papszNV, "lon_0", 0.0 ),
+                          OSR_GDV( papszNV, "k", 1.0 ),
+                          OSR_GDV( papszNV, "x_0", 0.0 ),
                           OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
@@ -668,58 +742,58 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
 
     else if( EQUAL(pszProj,"gnom") )
     {
-        SetGnomonic( OSR_GDV( papszNV, "lat_0", 0.0 ), 
-                     OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                     OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetGnomonic( OSR_GDV( papszNV, "lat_0", 0.0 ),
+                     OSR_GDV( papszNV, "lon_0", 0.0 ),
+                     OSR_GDV( papszNV, "x_0", 0.0 ),
                      OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(pszProj,"ortho") )
     {
-        SetOrthographic( OSR_GDV( papszNV, "lat_0", 0.0 ), 
-                         OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                         OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetOrthographic( OSR_GDV( papszNV, "lat_0", 0.0 ),
+                         OSR_GDV( papszNV, "lon_0", 0.0 ),
+                         OSR_GDV( papszNV, "x_0", 0.0 ),
                          OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(pszProj,"laea") )
     {
-        SetLAEA( OSR_GDV( papszNV, "lat_0", 0.0 ), 
-                 OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                 OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetLAEA( OSR_GDV( papszNV, "lat_0", 0.0 ),
+                 OSR_GDV( papszNV, "lon_0", 0.0 ),
+                 OSR_GDV( papszNV, "x_0", 0.0 ),
                  OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(pszProj,"aeqd") )
     {
-        SetAE( OSR_GDV( papszNV, "lat_0", 0.0 ), 
-               OSR_GDV( papszNV, "lon_0", 0.0 ), 
-               OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetAE( OSR_GDV( papszNV, "lat_0", 0.0 ),
+               OSR_GDV( papszNV, "lon_0", 0.0 ),
+               OSR_GDV( papszNV, "x_0", 0.0 ),
                OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(pszProj,"eqdc") )
     {
-        SetEC( OSR_GDV( papszNV, "lat_1", 0.0 ), 
-               OSR_GDV( papszNV, "lat_2", 0.0 ), 
-               OSR_GDV( papszNV, "lat_0", 0.0 ), 
-               OSR_GDV( papszNV, "lon_0", 0.0 ), 
-               OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetEC( OSR_GDV( papszNV, "lat_1", 0.0 ),
+               OSR_GDV( papszNV, "lat_2", 0.0 ),
+               OSR_GDV( papszNV, "lat_0", 0.0 ),
+               OSR_GDV( papszNV, "lon_0", 0.0 ),
+               OSR_GDV( papszNV, "x_0", 0.0 ),
                OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(pszProj,"mill") )
     {
-        SetMC( OSR_GDV( papszNV, "lat_0", 0.0 ), 
-               OSR_GDV( papszNV, "lon_0", 0.0 ), 
-               OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetMC( OSR_GDV( papszNV, "lat_0", 0.0 ),
+               OSR_GDV( papszNV, "lon_0", 0.0 ),
+               OSR_GDV( papszNV, "x_0", 0.0 ),
                OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(pszProj,"moll") )
     {
-        SetMollweide( OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                      OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetMollweide( OSR_GDV( papszNV, "lon_0", 0.0 ),
+                      OSR_GDV( papszNV, "x_0", 0.0 ),
                       OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
@@ -727,61 +801,61 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
              EQUAL(pszProj,"eck4") || EQUAL(pszProj,"eck5") || EQUAL(pszProj,"eck6"))
     {
         SetEckert(   pszProj[3] - '0',
-                     OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                     OSR_GDV( papszNV, "x_0", 0.0 ), 
+                     OSR_GDV( papszNV, "lon_0", 0.0 ),
+                     OSR_GDV( papszNV, "x_0", 0.0 ),
                      OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(pszProj,"poly") )
     {
-        SetPolyconic( OSR_GDV( papszNV, "lat_0", 0.0 ), 
-                      OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                      OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetPolyconic( OSR_GDV( papszNV, "lat_0", 0.0 ),
+                      OSR_GDV( papszNV, "lon_0", 0.0 ),
+                      OSR_GDV( papszNV, "x_0", 0.0 ),
                       OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(pszProj,"aea") )
     {
-        SetACEA( OSR_GDV( papszNV, "lat_1", 0.0 ), 
-                 OSR_GDV( papszNV, "lat_2", 0.0 ), 
-                 OSR_GDV( papszNV, "lat_0", 0.0 ), 
-                 OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                 OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetACEA( OSR_GDV( papszNV, "lat_1", 0.0 ),
+                 OSR_GDV( papszNV, "lat_2", 0.0 ),
+                 OSR_GDV( papszNV, "lat_0", 0.0 ),
+                 OSR_GDV( papszNV, "lon_0", 0.0 ),
+                 OSR_GDV( papszNV, "x_0", 0.0 ),
                  OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(pszProj,"robin") )
     {
-        SetRobinson( OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                     OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetRobinson( OSR_GDV( papszNV, "lon_0", 0.0 ),
+                     OSR_GDV( papszNV, "x_0", 0.0 ),
                      OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(pszProj,"vandg") )
     {
-        SetVDG( OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetVDG( OSR_GDV( papszNV, "lon_0", 0.0 ),
+                OSR_GDV( papszNV, "x_0", 0.0 ),
                 OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(pszProj,"sinu") )
     {
-        SetSinusoidal( OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                       OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetSinusoidal( OSR_GDV( papszNV, "lon_0", 0.0 ),
+                       OSR_GDV( papszNV, "x_0", 0.0 ),
                        OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(pszProj,"gall") )
     {
-        SetGS( OSR_GDV( papszNV, "lon_0", 0.0 ), 
-               OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetGS( OSR_GDV( papszNV, "lon_0", 0.0 ),
+               OSR_GDV( papszNV, "x_0", 0.0 ),
                OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(pszProj,"goode") )
     {
-        SetGH( OSR_GDV( papszNV, "lon_0", 0.0 ), 
-               OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetGH( OSR_GDV( papszNV, "lon_0", 0.0 ),
+               OSR_GDV( papszNV, "x_0", 0.0 ),
                OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
@@ -792,33 +866,36 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
 
     else if( EQUAL(pszProj,"geos") )
     {
-        SetGEOS( OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                 OSR_GDV( papszNV, "h", 35785831.0 ), 
-                 OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetGEOS( OSR_GDV( papszNV, "lon_0", 0.0 ),
+                 OSR_GDV( papszNV, "h", 35785831.0 ),
+                 OSR_GDV( papszNV, "x_0", 0.0 ),
                  OSR_GDV( papszNV, "y_0", 0.0 ) );
+
+        if( EQUAL(CSLFetchNameValueDef( papszNV, "sweep", "y" ), "x") )
+            bAddProj4Extension = true;
     }
 
-    else if( EQUAL(pszProj,"lcc") ) 
+    else if( EQUAL(pszProj,"lcc") )
     {
-        if( OSR_GDV(papszNV, "lat_0", 0.0 ) 
+        if( OSR_GDV(papszNV, "lat_0", 0.0 )
             == OSR_GDV(papszNV, "lat_1", 0.0 ) &&
             CSLFetchNameValue( papszNV, "lat_2" ) == NULL )
         {
             /* 1SP form */
-            SetLCC1SP( OSR_GDV( papszNV, "lat_0", 0.0 ), 
-                       OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                       OSR_GDV( papszNV, "k_0", 1.0 ), 
-                       OSR_GDV( papszNV, "x_0", 0.0 ), 
+            SetLCC1SP( OSR_GDV( papszNV, "lat_0", 0.0 ),
+                       OSR_GDV( papszNV, "lon_0", 0.0 ),
+                       OSR_GDV( papszNV, "k_0", 1.0 ),
+                       OSR_GDV( papszNV, "x_0", 0.0 ),
                        OSR_GDV( papszNV, "y_0", 0.0 ) );
         }
         else
         {
             /* 2SP form */
-            SetLCC( OSR_GDV( papszNV, "lat_1", 0.0 ), 
-                    OSR_GDV( papszNV, "lat_2", 0.0 ), 
-                    OSR_GDV( papszNV, "lat_0", 0.0 ), 
-                    OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                    OSR_GDV( papszNV, "x_0", 0.0 ), 
+            SetLCC( OSR_GDV( papszNV, "lat_1", 0.0 ),
+                    OSR_GDV( papszNV, "lat_2", 0.0 ),
+                    OSR_GDV( papszNV, "lat_0", 0.0 ),
+                    OSR_GDV( papszNV, "lon_0", 0.0 ),
+                    OSR_GDV( papszNV, "x_0", 0.0 ),
                     OSR_GDV( papszNV, "y_0", 0.0 ) );
         }
     }
@@ -829,73 +906,73 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
             || CSLFetchNameValue(papszNV,"no_off") != NULL )
         {
             /* From PJ_omerc, when alpha is defined but not gamma */
-            /* the default gama value is alpha */
+            /* the default gamma value is alpha */
             /*  if (alp || gam) {
                     if (alp) {
                         gamma0 = asin(sin(alpha_c) / D);
                     if (!gam)
                         gamma = alpha_c; */
-            SetHOM( OSR_GDV( papszNV, "lat_0", 0.0 ), 
-                    OSR_GDV( papszNV, "lonc", 0.0 ), 
-                    OSR_GDV( papszNV, "alpha", 0.0 ), 
-                    OSR_GDV( papszNV, "gamma", OSR_GDV( papszNV, "alpha", 0.0 ) ), 
-                    OSR_GDV( papszNV, "k", 1.0 ), 
-                    OSR_GDV( papszNV, "x_0", 0.0 ), 
+            SetHOM( OSR_GDV( papszNV, "lat_0", 0.0 ),
+                    OSR_GDV( papszNV, "lonc", 0.0 ),
+                    OSR_GDV( papszNV, "alpha", 0.0 ),
+                    OSR_GDV( papszNV, "gamma", OSR_GDV( papszNV, "alpha", 0.0 ) ),
+                    OSR_GDV( papszNV, "k", 1.0 ),
+                    OSR_GDV( papszNV, "x_0", 0.0 ),
                     OSR_GDV( papszNV, "y_0", 0.0 ) );
         }
         else
         {
-            SetHOMAC( OSR_GDV( papszNV, "lat_0", 0.0 ), 
-                   OSR_GDV( papszNV, "lonc", 0.0 ), 
-                   OSR_GDV( papszNV, "alpha", 0.0 ), 
-                   OSR_GDV( papszNV, "gamma", OSR_GDV( papszNV, "alpha", 0.0 ) ), 
-                   OSR_GDV( papszNV, "k", 1.0 ), 
-                   OSR_GDV( papszNV, "x_0", 0.0 ), 
+            SetHOMAC( OSR_GDV( papszNV, "lat_0", 0.0 ),
+                   OSR_GDV( papszNV, "lonc", 0.0 ),
+                   OSR_GDV( papszNV, "alpha", 0.0 ),
+                   OSR_GDV( papszNV, "gamma", OSR_GDV( papszNV, "alpha", 0.0 ) ),
+                   OSR_GDV( papszNV, "k", 1.0 ),
+                   OSR_GDV( papszNV, "x_0", 0.0 ),
                    OSR_GDV( papszNV, "y_0", 0.0 ) );
         }
     }
 
     else if( EQUAL(pszProj,"somerc") )
     {
-        SetHOMAC( OSR_GDV( papszNV, "lat_0", 0.0 ), 
-                  OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                  90.0,  90.0, 
-                  OSR_GDV( papszNV, "k", 1.0 ), 
-                  OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetHOMAC( OSR_GDV( papszNV, "lat_0", 0.0 ),
+                  OSR_GDV( papszNV, "lon_0", 0.0 ),
+                  90.0,  90.0,
+                  OSR_GDV( papszNV, "k", 1.0 ),
+                  OSR_GDV( papszNV, "x_0", 0.0 ),
                   OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(pszProj,"krovak") )
     {
-        SetKrovak( OSR_GDV( papszNV, "lat_0", 0.0 ), 
-                   OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                   OSR_GDV( papszNV, "alpha", 0.0 ), 
+        SetKrovak( OSR_GDV( papszNV, "lat_0", 0.0 ),
+                   OSR_GDV( papszNV, "lon_0", 0.0 ),
+                   OSR_GDV( papszNV, "alpha", 0.0 ),
                    0.0, // pseudo_standard_parallel_1
-                   OSR_GDV( papszNV, "k", 1.0 ), 
-                   OSR_GDV( papszNV, "x_0", 0.0 ), 
+                   OSR_GDV( papszNV, "k", 1.0 ),
+                   OSR_GDV( papszNV, "x_0", 0.0 ),
                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(pszProj, "iwm_p") )
     {
-        SetIWMPolyconic( OSR_GDV( papszNV, "lat_1", 0.0 ), 
+        SetIWMPolyconic( OSR_GDV( papszNV, "lat_1", 0.0 ),
                          OSR_GDV( papszNV, "lat_2", 0.0 ),
-                         OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                         OSR_GDV( papszNV, "x_0", 0.0 ), 
+                         OSR_GDV( papszNV, "lon_0", 0.0 ),
+                         OSR_GDV( papszNV, "x_0", 0.0 ),
                          OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(pszProj, "wag1") )
     {
         SetWagner( 1, 0.0,
-                   OSR_GDV( papszNV, "x_0", 0.0 ), 
+                   OSR_GDV( papszNV, "x_0", 0.0 ),
                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(pszProj, "wag2") )
     {
         SetWagner( 2, 0.0,
-                   OSR_GDV( papszNV, "x_0", 0.0 ), 
+                   OSR_GDV( papszNV, "x_0", 0.0 ),
                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
@@ -903,35 +980,35 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
     {
         SetWagner( 3,
                    OSR_GDV( papszNV, "lat_ts", 0.0 ),
-                   OSR_GDV( papszNV, "x_0", 0.0 ), 
+                   OSR_GDV( papszNV, "x_0", 0.0 ),
                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(pszProj, "wag4") )
     {
         SetWagner( 4, 0.0,
-                   OSR_GDV( papszNV, "x_0", 0.0 ), 
+                   OSR_GDV( papszNV, "x_0", 0.0 ),
                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(pszProj, "wag5") )
     {
         SetWagner( 5, 0.0,
-                   OSR_GDV( papszNV, "x_0", 0.0 ), 
+                   OSR_GDV( papszNV, "x_0", 0.0 ),
                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(pszProj, "wag6") )
     {
         SetWagner( 6, 0.0,
-                   OSR_GDV( papszNV, "x_0", 0.0 ), 
+                   OSR_GDV( papszNV, "x_0", 0.0 ),
                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( EQUAL(pszProj, "wag7") )
     {
         SetWagner( 7, 0.0,
-                   OSR_GDV( papszNV, "x_0", 0.0 ), 
+                   OSR_GDV( papszNV, "x_0", 0.0 ),
                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
@@ -940,21 +1017,28 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
         SetQSC( OSR_GDV( papszNV, "lat_0", 0.0 ),
                 OSR_GDV( papszNV, "lon_0", 0.0 ) );
     }
+    else if( EQUAL(pszProj,"sch") )
+    {
+        SetSCH( OSR_GDV( papszNV, "plat_0", 0.0 ),
+                OSR_GDV( papszNV, "plon_0", 0.0 ),
+                OSR_GDV( papszNV, "phdg_0", 0.0 ),
+                OSR_GDV( papszNV, "h_0", 0.0) );
+    }
 
     else if( EQUAL(pszProj,"tpeqd") )
     {
-        SetTPED( OSR_GDV( papszNV, "lat_1", 0.0 ), 
-                 OSR_GDV( papszNV, "lon_1", 0.0 ), 
-                 OSR_GDV( papszNV, "lat_2", 0.0 ), 
-                 OSR_GDV( papszNV, "lon_2", 0.0 ), 
-                 OSR_GDV( papszNV, "x_0", 0.0 ), 
+        SetTPED( OSR_GDV( papszNV, "lat_1", 0.0 ),
+                 OSR_GDV( papszNV, "lon_1", 0.0 ),
+                 OSR_GDV( papszNV, "lat_2", 0.0 ),
+                 OSR_GDV( papszNV, "lon_2", 0.0 ),
+                 OSR_GDV( papszNV, "x_0", 0.0 ),
                  OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
     else if( strstr(pszProj4,"wktext") != NULL )
     {
-        // Fake out a projected coordinate system for otherwise 
-        // unrecognised projections for which we are already planning
+        // Fake out a projected coordinate system for otherwise
+        // unrecognized projections for which we are already planning
         // to embed the actual PROJ.4 string via extension node.
         SetProjection( "custom_proj4" );
     }
@@ -969,32 +1053,30 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
 /* -------------------------------------------------------------------- */
 /*      Try to translate the datum.                                     */
 /* -------------------------------------------------------------------- */
-    const char *pszValue;
-    int  bFullyDefined = FALSE;
+    bool bFullyDefined = false;
 
-    pszValue = CSLFetchNameValue(papszNV, "datum");
+    const char *pszValue = CSLFetchNameValue(papszNV, "datum");
     if( pszValue == NULL )
     {
         /* do nothing */
     }
     else if( (EQUAL(pszValue,"NAD27") || EQUAL(pszValue,"NAD83")
               || EQUAL(pszValue,"WGS84") || EQUAL(pszValue,"WGS72"))
-             && dfFromGreenwich == 0.0 )
+             && l_dfFromGreenwich == 0.0 )
     {
         SetWellKnownGeogCS( pszValue );
-        bFullyDefined = TRUE;
+        bFullyDefined = true;
     }
     else
     {
-        unsigned int i;
-        for(i=0;i<sizeof(ogr_pj_datums)/sizeof(ogr_pj_datums[0]);i++)
+        for(size_t i=0;i<sizeof(ogr_pj_datums)/sizeof(ogr_pj_datums[0]);i++)
         {
             if ( EQUAL(pszValue, ogr_pj_datums[i].pszPJ) )
             {
                 OGRSpatialReference oGCS;
                 oGCS.importFromEPSG( ogr_pj_datums[i].nEPSG );
                 CopyGeogCSFrom( &oGCS );
-                bFullyDefined = TRUE;
+                bFullyDefined = true;
                 break;
             }
         }
@@ -1010,28 +1092,28 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
     pszValue = CSLFetchNameValue(papszNV, "ellps");
     if( pszValue != NULL && !bFullyDefined )
     {
-        for( i = 0; ogr_pj_ellps[i] != NULL; i += 4 )
+        for( int i = 0; ogr_pj_ellps[i] != NULL; i += 4 )
         {
             if( !EQUAL(ogr_pj_ellps[i],pszValue) )
                 continue;
 
-            CPLAssert( EQUALN(ogr_pj_ellps[i+1],"a=",2) );
-            
+            CPLAssert( STARTS_WITH_CI(ogr_pj_ellps[i+1], "a=") );
+
             dfSemiMajor = CPLAtof(ogr_pj_ellps[i+1]+2);
-            if( EQUALN(ogr_pj_ellps[i+2],"rf=",3) )
+            if( STARTS_WITH_CI(ogr_pj_ellps[i+2], "rf=") )
                 dfInvFlattening = CPLAtof(ogr_pj_ellps[i+2]+3);
             else
             {
-                CPLAssert( EQUALN(ogr_pj_ellps[i+2],"b=",2) );
+                CPLAssert( STARTS_WITH_CI(ogr_pj_ellps[i+2], "b=") );
                 dfSemiMinor = CPLAtof(ogr_pj_ellps[i+2]+2);
                 dfInvFlattening = OSRCalcInvFlattening(dfSemiMajor, dfSemiMinor);
             }
-            
-            SetGeogCS( ogr_pj_ellps[i+3], "unknown", ogr_pj_ellps[i], 
+
+            SetGeogCS( ogr_pj_ellps[i+3], "unknown", ogr_pj_ellps[i],
                        dfSemiMajor, dfInvFlattening,
-                       pszPM, dfFromGreenwich );
+                       pszPM, l_dfFromGreenwich );
 
-            bFullyDefined = TRUE;
+            bFullyDefined = true;
             break;
         }
     }
@@ -1049,9 +1131,9 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
             }
             else
             {
-                CPLDebug( "OGR_PROJ4", "Can't find ellipse definition, default to WGS84:\n%s", 
+                CPLDebug( "OGR_PROJ4", "Can't find ellipse definition, default to WGS84:\n%s",
                           pszProj4 );
-                
+
                 dfSemiMajor = SRS_WGS84_SEMIMAJOR;
                 dfSemiMinor = -1.0;
                 dfInvFlattening = SRS_WGS84_INVFLATTENING;
@@ -1070,10 +1152,10 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
                     dfInvFlattening = 1.0 / dfFlattening;
             }
         }
-        
+
         if( dfSemiMinor == -1.0 && dfInvFlattening == -1.0 )
         {
-            CPLDebug( "OGR_PROJ4", "Can't find ellipse definition in:\n%s", 
+            CPLDebug( "OGR_PROJ4", "Can't find ellipse definition in:\n%s",
                       pszProj4 );
             CSLDestroy( papszNV );
             return OGRERR_UNSUPPORTED_SRS;
@@ -1083,40 +1165,45 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
         {
             dfInvFlattening = OSRCalcInvFlattening(dfSemiMajor, dfSemiMinor);
         }
-        
+
         SetGeogCS( "unnamed ellipse", "unknown", "unnamed",
                    dfSemiMajor, dfInvFlattening,
-                   pszPM, dfFromGreenwich );
-        
-        bFullyDefined = TRUE;
+                   pszPM, l_dfFromGreenwich );
+
+        /*bFullyDefined = true;*/
     }
 
 /* -------------------------------------------------------------------- */
 /*      Handle TOWGS84 conversion.                                      */
 /* -------------------------------------------------------------------- */
     pszValue = CSLFetchNameValue(papszNV, "towgs84");
-    if(pszValue!=NULL)
-    {
-        char **papszToWGS84 = CSLTokenizeStringComplex( pszValue, ",", 
+    // Make sure that we do not include a useless TOWGS84 node if the datum
+    // is WGS84.  Depending on the proj.4 version +datum=WGS84 might be
+    // expanded with a +towgs84=0,0,0 or not
+    if(pszValue!=NULL &&
+        !( EQUAL(CSLFetchNameValueDef(papszNV, "datum", ""), "WGS84")
+           && EQUAL(pszValue, "0,0,0")) )
+    {
+        char **papszToWGS84 = CSLTokenizeStringComplex( pszValue, ",",
                                                         FALSE, TRUE );
 
         if( CSLCount(papszToWGS84) >= 7 )
-            SetTOWGS84( CPLAtof(papszToWGS84[0]), 
-                        CPLAtof(papszToWGS84[1]), 
-                        CPLAtof(papszToWGS84[2]), 
-                        CPLAtof(papszToWGS84[3]), 
-                        CPLAtof(papszToWGS84[4]), 
-                        CPLAtof(papszToWGS84[5]), 
+            SetTOWGS84( CPLAtof(papszToWGS84[0]),
+                        CPLAtof(papszToWGS84[1]),
+                        CPLAtof(papszToWGS84[2]),
+                        CPLAtof(papszToWGS84[3]),
+                        CPLAtof(papszToWGS84[4]),
+                        CPLAtof(papszToWGS84[5]),
                         CPLAtof(papszToWGS84[6]) );
         else if( CSLCount(papszToWGS84) >= 3 )
-            SetTOWGS84( CPLAtof(papszToWGS84[0]), 
-                        CPLAtof(papszToWGS84[1]), 
+            SetTOWGS84( CPLAtof(papszToWGS84[0]),
+                        CPLAtof(papszToWGS84[1]),
                         CPLAtof(papszToWGS84[2]) );
         else
-            CPLError( CE_Warning, CPLE_AppDefined, 
-                      "Seemingly corrupt +towgs84 option (%s), ignoring.", 
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Seemingly corrupt +towgs84 option (%s), ignoring.",
                       pszValue );
-                        
+
         CSLDestroy(papszToWGS84);
     }
 
@@ -1139,14 +1226,13 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
 
         if( pszValue != NULL && CPLAtofM(pszValue) > 0.0 )
         {
-            double dfValue = CPLAtofM(pszValue);
-
-            if( fabs(dfValue - CPLAtof(SRS_UL_US_FOOT_CONV)) < 0.00000001 )
-                SetLinearUnits( SRS_UL_US_FOOT, CPLAtof(SRS_UL_US_FOOT_CONV) );
-            else if( fabs(dfValue - CPLAtof(SRS_UL_FOOT_CONV)) < 0.00000001 )
-                SetLinearUnits( SRS_UL_FOOT, CPLAtof(SRS_UL_FOOT_CONV) );
-            else if( dfValue == 1.0 )
-                SetLinearUnits( SRS_UL_METER, 1.0 );
+            const double dfValue = CPLAtofM(pszValue);
+            const LinearUnitsStruct* psLinearUnits = GetLinearFromLinearConvOrName( dfValue, pszValue );
+            if( psLinearUnits != NULL )
+            {
+                SetLinearUnits( psLinearUnits->pszWKTName,
+                                CPLAtof(psLinearUnits->pszValueInMeter) );
+            }
             else
                 SetLinearUnits( "unknown", CPLAtofM(pszValue) );
         }
@@ -1155,76 +1241,12 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
         */
         else if( (pszValue = CSLFetchNameValue(papszNV, "units")) != NULL )
         {
-            if( EQUAL(pszValue,"meter" ) || EQUAL(pszValue,"m") || EQUAL(pszValue,"metre") )
-                SetLinearUnits( SRS_UL_METER, 1.0 );
-            /*
-            ** Leave as 'kilometre' instead of SRS_UL_KILOMETER due to
-            ** historical usage
-            */
-            else if( EQUAL( pszValue,"km") )
-                SetLinearUnits( "kilometre",
-                                CPLAtof( SRS_UL_KILOMETER_CONV ) );
-            else if( EQUAL( pszValue,"us-ft" ) )
-                SetLinearUnits( SRS_UL_US_FOOT,
-                                CPLAtof( SRS_UL_US_FOOT_CONV ) );
-            /*
-            ** Leave as 'Foot (International)' or SRS_UL_FOOT instead of
-            ** SRS_UL_INTL_FOOT due to historical usage
-            */
-            else if( EQUAL( pszValue,"ft" ) )
-                SetLinearUnits( SRS_UL_FOOT,
-                                CPLAtof( SRS_UL_FOOT_CONV) );
-            else if( EQUAL( pszValue,"yd" ) )
-                SetLinearUnits( SRS_UL_INTL_YARD,
-                                CPLAtof( SRS_UL_INTL_YARD_CONV ) );
-            else if( EQUAL( pszValue,"us-yd" ) )
-                SetLinearUnits( SRS_UL_US_YARD,
-                                CPLAtof( SRS_UL_US_YARD_CONV ) );
-            else if( EQUAL( pszValue,"dm" ) )
-                SetLinearUnits( SRS_UL_DECIMETER, 
-                                CPLAtof( SRS_UL_DECIMETER_CONV ) );
-            else if( EQUAL( pszValue,"cm" ) )
-                SetLinearUnits( SRS_UL_CENTIMETER,
-                                CPLAtof( SRS_UL_CENTIMETER_CONV ) );
-            else if( EQUAL( pszValue,"mm" ) )
-                SetLinearUnits( SRS_UL_MILLIMETER,
-                                CPLAtof( SRS_UL_MILLIMETER_CONV ) );
-            else if( EQUAL( pszValue,"kmi" ) )
-                SetLinearUnits( SRS_UL_INTL_NAUT_MILE,
-                                CPLAtof( SRS_UL_INTL_NAUT_MILE_CONV ) );
-            else if( EQUAL( pszValue,"in" ) )
-                SetLinearUnits( SRS_UL_INTL_INCH,
-                                CPLAtof( SRS_UL_INTL_INCH_CONV ) );
-            else if( EQUAL( pszValue,"mi" ) )
-                SetLinearUnits( SRS_UL_INTL_STAT_MILE,
-                                CPLAtof( SRS_UL_INTL_STAT_MILE_CONV ) );
-            else if( EQUAL( pszValue,"fath" ) )
-                SetLinearUnits( SRS_UL_INTL_FATHOM,
-                                CPLAtof( SRS_UL_INTL_FATHOM_CONV ) );
-            else if( EQUAL( pszValue,"ch" ) )
-                SetLinearUnits( SRS_UL_INTL_CHAIN,
-                                CPLAtof( SRS_UL_INTL_CHAIN_CONV ) );
-            else if( EQUAL( pszValue,"link" ) )
-                SetLinearUnits( SRS_UL_INTL_LINK,
-                                CPLAtof( SRS_UL_INTL_LINK_CONV ) );
-            else if( EQUAL( pszValue,"us-in" ) )
-                SetLinearUnits( SRS_UL_US_INCH,
-                                CPLAtof( SRS_UL_US_INCH_CONV ) );
-            else if( EQUAL( pszValue, "us-ch" ) )
-                SetLinearUnits( SRS_UL_US_CHAIN,
-                                CPLAtof( SRS_UL_US_CHAIN_CONV ) );
-            else if( EQUAL( pszValue, "us-mi" ) )
-                SetLinearUnits( SRS_UL_US_STAT_MILE,
-                                CPLAtof( SRS_UL_US_STAT_MILE_CONV ) );
-            else if( EQUAL( pszValue, "ind-yd" ) )
-                SetLinearUnits( SRS_UL_INDIAN_YARD,
-                                CPLAtof( SRS_UL_INDIAN_YARD_CONV ) );
-            else if( EQUAL( pszValue, "ind-ft" ) )
-                SetLinearUnits( SRS_UL_INDIAN_FOOT,
-                                CPLAtof( SRS_UL_INDIAN_FOOT_CONV ) );
-            else if( EQUAL( pszValue, "ind-ch" ) )
-                SetLinearUnits( SRS_UL_INDIAN_CHAIN,
-                                CPLAtof( SRS_UL_INDIAN_CHAIN_CONV ) );
+            const LinearUnitsStruct* psLinearUnits = GetLinearFromProjName( pszValue );
+            if( psLinearUnits != NULL )
+            {
+                SetLinearUnits( psLinearUnits->pszWKTName,
+                                CPLAtof(psLinearUnits->pszValueInMeter) );
+            }
             else // This case is untranslatable.  Should add all proj.4 unts
                 SetLinearUnits( pszValue, 1.0 );
         }
@@ -1237,12 +1259,11 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
     if( GetLinearUnits() != 1.0 && IsProjected() )
     {
         OGR_SRSNode *poPROJCS = GetAttrNode( "PROJCS" );
-        int  i;
 
-        for( i = 0; i < poPROJCS->GetChildCount(); i++ )
+        for( int i = 0; i < poPROJCS->GetChildCount(); i++ )
         {
             OGR_SRSNode *poParm = poPROJCS->GetChild(i);
-            if( !EQUAL(poParm->GetValue(),"PARAMETER") 
+            if( !EQUAL(poParm->GetValue(),"PARAMETER")
                 || poParm->GetChildCount() != 2 )
                 continue;
 
@@ -1250,7 +1271,7 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
 
             if( IsLinearParameter(pszParmName) )
                 SetNormProjParm(pszParmName,GetProjParm(pszParmName));
-        }        
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -1261,13 +1282,13 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
     if( pszValue != NULL )
     {
         OGR_SRSNode *poHorizSRS = GetRoot()->Clone();
-        
+
         Clear();
-        
+
         CPLString osName = poHorizSRS->GetChild(0)->GetValue();
         osName += " + ";
         osName += "Unnamed Vertical Datum";
-        
+
         SetNode( "COMPD_CS", osName );
         GetRoot()->AddChild( poHorizSRS );
 
@@ -1279,7 +1300,7 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
         osTarget += "|VERT_CS|VERT_DATUM";
 
         SetNode( osTarget, "Unnamed" );
-        
+
         poVERT_CS->GetChild(1)->AddChild( new OGR_SRSNode( "2005" ) );
         SetExtension( osTarget, "PROJ4_GRIDS", pszValue );
     }
@@ -1296,22 +1317,12 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
 
         if( pszValue != NULL && CPLAtofM(pszValue) > 0.0 )
         {
-            double dfValue = CPLAtofM(pszValue);
-
-            if( fabs(dfValue - CPLAtof(SRS_UL_US_FOOT_CONV)) < 0.00000001 )
+            const double dfValue = CPLAtofM(pszValue);
+            const LinearUnitsStruct* psLinearUnits = GetLinearFromLinearConvOrName( dfValue, pszValue );
+            if( psLinearUnits != NULL )
             {
-                pszUnitName = SRS_UL_US_FOOT;
-                pszUnitConv = SRS_UL_US_FOOT_CONV;
-            }
-            else if( fabs(dfValue - CPLAtof(SRS_UL_FOOT_CONV)) < 0.00000001 )
-            {
-                pszUnitName = SRS_UL_FOOT;
-                pszUnitConv = SRS_UL_FOOT_CONV;
-            }
-            else if( dfValue == 1.0 )
-            {
-                pszUnitName = SRS_UL_METER;
-                pszUnitConv = "1.0";
+                pszUnitName = psLinearUnits->pszWKTName,
+                pszUnitConv = psLinearUnits->pszValueInMeter;
             }
             else
             {
@@ -1321,38 +1332,22 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
         }
         else if( (pszValue = CSLFetchNameValue(papszNV, "vunits")) != NULL )
         {
-            if( EQUAL(pszValue,"meter" ) || EQUAL(pszValue,"m") || EQUAL(pszValue,"metre") )
-            {
-                pszUnitName = SRS_UL_METER;
-                pszUnitConv = "1.0";
-            }
-            else if( EQUAL(pszValue,"us-ft" ) )
-            {
-                pszUnitName = SRS_UL_US_FOOT;
-                pszUnitConv = SRS_UL_US_FOOT_CONV;
-            }
-            else if( EQUAL(pszValue,"ft" ) )
+            const LinearUnitsStruct* psLinearUnits = GetLinearFromProjName( pszValue );
+            if( psLinearUnits != NULL )
             {
-                pszUnitName = SRS_UL_FOOT;
-                pszUnitConv = SRS_UL_FOOT_CONV;
+                pszUnitName = psLinearUnits->pszWKTName,
+                pszUnitConv = psLinearUnits->pszValueInMeter;
             }
-            else if( EQUAL(pszValue,"yd" ) )
-            {
-                pszUnitName = "Yard";
-                pszUnitConv = "0.9144";
-            }
-            else if( EQUAL(pszValue,"us-yd" ) )
+            else
             {
-                pszUnitName = "US Yard";
-                pszUnitConv = "0.914401828803658";
+                pszUnitName = "unknown";
+                pszUnitConv = pszValue;
             }
         }
 
         if( pszUnitName != NULL )
         {
-            OGR_SRSNode *poUnits; 
-
-            poUnits = new OGR_SRSNode( "UNIT" );
+            OGR_SRSNode *poUnits = new OGR_SRSNode( "UNIT" );
             poUnits->AddChild( new OGR_SRSNode( pszUnitName ) );
             poUnits->AddChild( new OGR_SRSNode( pszUnitConv ) );
 
@@ -1400,66 +1395,18 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
 }
 
 /************************************************************************/
-/*                           LinearToProj4()                            */
-/************************************************************************/
-
-static const char *LinearToProj4( double dfLinearConv, 
-                                  const char *pszLinearUnits )
-
-{
-    if( dfLinearConv == 1.0 )
-        return "m";
-
-    else if( dfLinearConv == 1000.0 )
-        return "km";
-    
-    else if( dfLinearConv == 0.0254 )
-        return "in";
-    
-    else if( EQUAL(pszLinearUnits,SRS_UL_FOOT) 
-             || fabs(dfLinearConv - CPLAtof(SRS_UL_FOOT_CONV)) < 0.000000001 )
-        return "ft";
-    
-    else if( EQUAL(pszLinearUnits,"IYARD") || dfLinearConv == 0.9144 )
-        return "yd";
-
-    else if( dfLinearConv == 0.914401828803658 )
-        return "us-yd";
-    
-    else if( dfLinearConv == 0.001 )
-        return "mm";
-    
-    else if( dfLinearConv == 0.01 )
-        return "cm";
-
-    else if( EQUAL(pszLinearUnits,SRS_UL_US_FOOT) 
-             || fabs(dfLinearConv - CPLAtof(SRS_UL_US_FOOT_CONV)) < 0.00000001 )
-        return "us-ft";
-
-    else if( EQUAL(pszLinearUnits,SRS_UL_NAUTICAL_MILE) )
-        return "kmi";
-
-    else if( EQUAL(pszLinearUnits,"Mile") 
-             || EQUAL(pszLinearUnits,"IMILE") )
-        return "mi";
-    else
-        return NULL;
-}
-
-
-/************************************************************************/
 /*                          OSRExportToProj4()                          */
 /************************************************************************/
-/** 
+/**
  * \brief Export coordinate system in PROJ.4 format.
  *
  * This function is the same as OGRSpatialReference::exportToProj4().
  */
-OGRErr CPL_STDCALL OSRExportToProj4( OGRSpatialReferenceH hSRS, 
+OGRErr CPL_STDCALL OSRExportToProj4( OGRSpatialReferenceH hSRS,
                                      char ** ppszReturn )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRExportToProj4", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRExportToProj4", OGRERR_FAILURE );
 
     *ppszReturn = NULL;
 
@@ -1485,7 +1432,7 @@ OGRErr CPL_STDCALL OSRExportToProj4( OGRSpatialReferenceH hSRS,
  * deallocated by the caller with CPLFree() when no longer needed.
  *
  * LOCAL_CS coordinate systems are not translatable.  An empty string
- * will be returned along with OGRERR_NONE.  
+ * will be returned along with OGRERR_NONE.
  *
  * Special processing for Transverse Mercator with GDAL >= 1.10 and PROJ >= 4.8 :
  * if the OSR_USE_ETMERC configuration option is set to YES, the PROJ.4
@@ -1494,22 +1441,17 @@ OGRErr CPL_STDCALL OSRExportToProj4( OGRSpatialReferenceH hSRS,
  * expense of computational speed) when reprojection occurs near the edges
  * of the validity area for the projection.
  *
- * This method is the equivelent of the C function OSRExportToProj4().
+ * This method is the equivalent of the C function OSRExportToProj4().
  *
- * @param ppszProj4 pointer to which dynamically allocated PROJ.4 definition 
- * will be assigned. 
+ * @param ppszProj4 pointer to which dynamically allocated PROJ.4 definition
+ * will be assigned.
  *
- * @return OGRERR_NONE on success or an error code on failure. 
+ * @return OGRERR_NONE on success or an error code on failure.
  */
 
 OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
 {
-    char        szProj4[512];
-    const char *pszProjection = GetAttrValue("PROJECTION");
-
-    szProj4[0] = '\0';
-
     if( GetRoot() == NULL )
     {
         *ppszProj4 = CPLStrdup("");
@@ -1521,7 +1463,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 /* -------------------------------------------------------------------- */
 /*      Do we have a PROJ.4 override definition?                        */
 /* -------------------------------------------------------------------- */
-    const char *pszPredefProj4 = GetExtension( GetRoot()->GetValue(), 
+    const char *pszPredefProj4 = GetExtension( GetRoot()->GetValue(),
                                                "PROJ4", NULL );
     if( pszPredefProj4 != NULL )
     {
@@ -1533,25 +1475,30 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 /*      Get the prime meridian info.                                    */
 /* -------------------------------------------------------------------- */
     const OGR_SRSNode *poPRIMEM = GetAttrNode( "PRIMEM" );
-    double dfFromGreenwich = 0.0;
+    double l_dfFromGreenwich = 0.0;
 
-    if( poPRIMEM != NULL && poPRIMEM->GetChildCount() >= 2 
+    if( poPRIMEM != NULL && poPRIMEM->GetChildCount() >= 2
         && CPLAtof(poPRIMEM->GetChild(1)->GetValue()) != 0.0 )
     {
-        dfFromGreenwich = CPLAtof(poPRIMEM->GetChild(1)->GetValue());
+        l_dfFromGreenwich = CPLAtof(poPRIMEM->GetChild(1)->GetValue());
     }
 
 /* ==================================================================== */
 /*      Handle the projection definition.                               */
 /* ==================================================================== */
 
+    const char *pszProjection = GetAttrValue("PROJECTION");
+
+    char szProj4[512];
+    szProj4[0] = '\0';
+
     if( pszProjection == NULL && IsGeographic() )
     {
-        CPLsprintf( szProj4+strlen(szProj4), "+proj=longlat " );
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4), "+proj=longlat " );
     }
     else if( IsGeocentric() )
     {
-        CPLsprintf( szProj4+strlen(szProj4), "+proj=geocent " );
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4), "+proj=geocent " );
     }
 
     else if( pszProjection == NULL && !IsGeographic() )
@@ -1562,7 +1509,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
     }
     else if( EQUAL(pszProjection,SRS_PT_CYLINDRICAL_EQUAL_AREA) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=cea +lon_0=%.16g +lat_ts=%.16g +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
                  GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
@@ -1572,7 +1519,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_BONNE) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=bonne +lon_0=%.16g +lat_1=%.16g +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
                  GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
@@ -1582,7 +1529,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_CASSINI_SOLDNER) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=cass +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
@@ -1592,7 +1539,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_NEW_ZEALAND_MAP_GRID) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=nzmg +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
@@ -1608,11 +1555,11 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
              EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_25) )
     {
         int bNorth;
-        int nZone = GetUTMZone( &bNorth );
+        const int nZone = GetUTMZone( &bNorth );
 
-        if( CSLTestBoolean(CPLGetConfigOption("OSR_USE_ETMERC", "FALSE")) )
+        if( CPLTestBool(CPLGetConfigOption("OSR_USE_ETMERC", "FALSE")) )
         {
-            CPLsprintf( szProj4+strlen(szProj4),
+            CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                      "+proj=etmerc +lat_0=%.16g +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g ",
                      GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
                      GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
@@ -1623,14 +1570,14 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
         else if( nZone != 0 )
         {
             if( bNorth )
-                CPLsprintf( szProj4+strlen(szProj4), "+proj=utm +zone=%d ", 
+                CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4), "+proj=utm +zone=%d ",
                          nZone );
             else
-                CPLsprintf( szProj4+strlen(szProj4),"+proj=utm +zone=%d +south ", 
+                CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),"+proj=utm +zone=%d +south ",
                          nZone );
-        }            
+        }
         else
-            CPLsprintf( szProj4+strlen(szProj4),
+            CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                      "+proj=tmerc +lat_0=%.16g +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g ",
                      GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
                      GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
@@ -1641,7 +1588,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=tmerc +lat_0=%.16g +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g +axis=wsu ",
                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
@@ -1653,14 +1600,14 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
     else if( EQUAL(pszProjection,SRS_PT_MERCATOR_1SP) )
     {
         if( GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0) == 0.0 )
-            CPLsprintf( szProj4+strlen(szProj4),
+            CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                      "+proj=merc +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g ",
                      GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
                      GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
                      GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
                      GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
         else if( GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0) == 1.0 )
-            CPLsprintf( szProj4+strlen(szProj4),
+            CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                      "+proj=merc +lon_0=%.16g +lat_ts=%.16g +x_0=%.16g +y_0=%.16g ",
                      GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
                      GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
@@ -1677,7 +1624,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_MERCATOR_2SP) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=merc +lon_0=%.16g +lat_ts=%.16g +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
                  GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
@@ -1690,7 +1637,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
        // This is EPSG:3875 Pseudo Mercator. No point in trying to parse the
        // rest of the parameters, since we know pretty much everything at this
        // stage.
-       CPLsprintf( szProj4+strlen(szProj4),
+       CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
 		"+proj=merc +a=%.16g +b=%.16g +lat_ts=%.16g"
 		" +lon_0=%.16g +x_0=%.16g +y_0=%.16g +k=%.16g +units=m"
 		" +nadgrids=@null +wktext  +no_defs",
@@ -1701,13 +1648,13 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 		GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
 		GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0) );
        *ppszProj4 = CPLStrdup( szProj4 );
-       
+
        return OGRERR_NONE;
     }
 
     else if( EQUAL(pszProjection,SRS_PT_OBLIQUE_STEREOGRAPHIC) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=sterea +lat_0=%.16g +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g ",
 //         "+proj=stere +lat_0=%.16g +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
@@ -1719,7 +1666,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_STEREOGRAPHIC) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=stere +lat_0=%.16g +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
@@ -1731,7 +1678,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
     else if( EQUAL(pszProjection,SRS_PT_POLAR_STEREOGRAPHIC) )
     {
         if( GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0) >= 0.0 )
-            CPLsprintf( szProj4+strlen(szProj4),
+            CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                      "+proj=stere +lat_0=90 +lat_ts=%.16g +lon_0=%.16g "
                      "+k=%.16g +x_0=%.16g +y_0=%.16g ",
                      GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,90.0),
@@ -1740,7 +1687,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
                      GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
                      GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
         else
-            CPLsprintf( szProj4+strlen(szProj4),
+            CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                      "+proj=stere +lat_0=-90 +lat_ts=%.16g +lon_0=%.16g "
                      "+k=%.16g +x_0=%.16g +y_0=%.16g ",
                      GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,-90.0),
@@ -1752,7 +1699,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_EQUIRECTANGULAR) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=eqc +lat_ts=%.16g +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
@@ -1763,7 +1710,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_GAUSSSCHREIBERTMERCATOR) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=gstmerc +lat_0=%.16g +lon_0=%.16g"
                  " +k_0=%.16g +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,-21.116666667),
@@ -1775,7 +1722,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_GNOMONIC) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=gnom +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
@@ -1785,7 +1732,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_ORTHOGRAPHIC) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=ortho +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
@@ -1795,7 +1742,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=laea +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
@@ -1805,7 +1752,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_AZIMUTHAL_EQUIDISTANT) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=aeqd +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
@@ -1815,7 +1762,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_EQUIDISTANT_CONIC) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=eqdc +lat_0=%.16g +lon_0=%.16g +lat_1=%.16g +lat_2=%.16g"
                  " +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0),
@@ -1828,7 +1775,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_MILLER_CYLINDRICAL) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=mill +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g +R_A ",
                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
@@ -1838,7 +1785,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_MOLLWEIDE) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=moll +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
@@ -1847,7 +1794,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_ECKERT_I) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=eck1 +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
@@ -1856,7 +1803,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_ECKERT_II) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=eck2 +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
@@ -1865,34 +1812,34 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_ECKERT_III) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=eck3 +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
     }
-    
+
     else if( EQUAL(pszProjection,SRS_PT_ECKERT_IV) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=eck4 +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
     }
-    
+
     else if( EQUAL(pszProjection,SRS_PT_ECKERT_V) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=eck5 +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
     }
-    
+
     else if( EQUAL(pszProjection,SRS_PT_ECKERT_VI) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=eck6 +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
@@ -1901,7 +1848,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_POLYCONIC) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=poly +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
@@ -1911,7 +1858,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=aea +lat_1=%.16g +lat_2=%.16g +lat_0=%.16g +lon_0=%.16g"
                  " +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
@@ -1924,7 +1871,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_ROBINSON) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=robin +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
@@ -1933,7 +1880,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_VANDERGRINTEN) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=vandg +lon_0=%.16g +x_0=%.16g +y_0=%.16g +R_A ",
                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
@@ -1942,7 +1889,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_SINUSOIDAL) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=sinu +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0),
                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
@@ -1951,7 +1898,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_GALL_STEREOGRAPHIC) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=gall +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
@@ -1960,7 +1907,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_GOODE_HOMOLOSINE) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=goode +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
@@ -1969,12 +1916,12 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_IGH) )
     {
-        CPLsprintf( szProj4+strlen(szProj4), "+proj=igh " );
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4), "+proj=igh " );
     }
 
     else if( EQUAL(pszProjection,SRS_PT_GEOSTATIONARY_SATELLITE) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=geos +lon_0=%.16g +h=%.16g +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
                  GetNormProjParm(SRS_PP_SATELLITE_HEIGHT,35785831.0),
@@ -1985,7 +1932,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
     else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP)
              || EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=lcc +lat_1=%.16g +lat_2=%.16g +lat_0=%.16g +lon_0=%.16g"
                  " +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
@@ -1995,10 +1942,10 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
     }
-    
+
     else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=lcc +lat_1=%.16g +lat_0=%.16g +lon_0=%.16g"
                  " +k_0=%.16g +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
@@ -2012,10 +1959,10 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
     else if( EQUAL(pszProjection,SRS_PT_HOTINE_OBLIQUE_MERCATOR) )
     {
         /* special case for swiss oblique mercator : see bug 423 */
-        if( fabs(GetNormProjParm(SRS_PP_AZIMUTH,0.0) - 90.0) < 0.0001 
+        if( fabs(GetNormProjParm(SRS_PP_AZIMUTH,0.0) - 90.0) < 0.0001
             && fabs(GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE,0.0)-90.0) < 0.0001 )
         {
-            CPLsprintf( szProj4+strlen(szProj4),
+            CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                      "+proj=somerc +lat_0=%.16g +lon_0=%.16g"
                      " +k_0=%.16g +x_0=%.16g +y_0=%.16g ",
                      GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
@@ -2026,7 +1973,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
         }
         else
         {
-            CPLsprintf( szProj4+strlen(szProj4),
+            CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                      "+proj=omerc +lat_0=%.16g +lonc=%.16g +alpha=%.16g"
                      " +k=%.16g +x_0=%.16g +y_0=%.16g +no_uoff ",
                      GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
@@ -2040,7 +1987,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
             // Note that gamma is only supported by PROJ 4.8.0 and later.
             if( GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE,1000.0) != 1000.0 )
             {
-                CPLsprintf( szProj4+strlen(szProj4), "+gamma=%.16g ",
+                CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4), "+gamma=%.16g ",
                          GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE,1000.0));
             }
         }
@@ -2049,10 +1996,10 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
     else if( EQUAL(pszProjection,SRS_PT_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER))
     {
         /* special case for swiss oblique mercator : see bug 423 */
-        if( fabs(GetNormProjParm(SRS_PP_AZIMUTH,0.0) - 90.0) < 0.0001 
+        if( fabs(GetNormProjParm(SRS_PP_AZIMUTH,0.0) - 90.0) < 0.0001
             && fabs(GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE,0.0)-90.0) < 0.0001 )
         {
-            CPLsprintf( szProj4+strlen(szProj4),
+            CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                      "+proj=somerc +lat_0=%.16g +lon_0=%.16g"
                      " +k_0=%.16g +x_0=%.16g +y_0=%.16g ",
                      GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
@@ -2063,7 +2010,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
         }
         else
         {
-            CPLsprintf( szProj4+strlen(szProj4),
+            CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                      "+proj=omerc +lat_0=%.16g +lonc=%.16g +alpha=%.16g"
                      " +k=%.16g +x_0=%.16g +y_0=%.16g ",
                      GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
@@ -2077,7 +2024,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
             // Note that gamma is only supported by PROJ 4.8.0 and later.
             if( GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE,1000.0) != 1000.0 )
             {
-                CPLsprintf( szProj4+strlen(szProj4), "+gamma=%.16g ",
+                CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4), "+gamma=%.16g ",
                          GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE,1000.0));
             }
         }
@@ -2088,7 +2035,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
     {
         // Not really clear which of Point_1/1st_Point convention is the
         // "normalized" one, so accept both
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=omerc +lat_0=%.16g"
                  " +lon_1=%.16g +lat_1=%.16g +lon_2=%.16g +lat_2=%.16g"
                  " +k=%.16g +x_0=%.16g +y_0=%.16g ",
@@ -2104,7 +2051,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_KROVAK) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=krovak +lat_0=%.16g +lon_0=%.16g +alpha=%.16g"
                  " +k=%.16g +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0),
@@ -2117,7 +2064,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_TWO_POINT_EQUIDISTANT) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=tpeqd +lat_1=%.16g +lon_1=%.16g "
                  "+lat_2=%.16g +lon_2=%.16g "
                  "+x_0=%.16g +y_0=%.16g ",
@@ -2131,7 +2078,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection, SRS_PT_IMW_POLYCONIC) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=iwm_p +lat_1=%.16g +lat_2=%.16g +lon_0=%.16g "
                  "+x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_LATITUDE_OF_1ST_POINT, 0.0),
@@ -2143,7 +2090,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection, SRS_PT_WAGNER_I) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=wag1 +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
                  GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
@@ -2151,7 +2098,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection, SRS_PT_WAGNER_II) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=wag2 +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
                  GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
@@ -2159,7 +2106,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection, SRS_PT_WAGNER_III) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=wag3 +lat_ts=%.16g +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
                  GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
@@ -2168,7 +2115,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection, SRS_PT_WAGNER_IV) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=wag4 +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
                  GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
@@ -2176,7 +2123,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection, SRS_PT_WAGNER_V) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=wag5 +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
                  GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
@@ -2184,7 +2131,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection, SRS_PT_WAGNER_VI) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=wag6 +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
                  GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
@@ -2192,7 +2139,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection, SRS_PT_WAGNER_VII) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=wag7 +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
                  GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
@@ -2200,16 +2147,26 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_QSC) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=qsc +lat_0=%.16g +lon_0=%.16g ",
                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0) );
     }
 
+    else if ( EQUAL(pszProjection, SRS_PT_SCH) )
+    {
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
+                "+proj=sch +plat_0=%.16g +plon_0=%.16g +phdg_0=%.16g +h_0=%.16g ",
+                GetNormProjParm(SRS_PP_PEG_POINT_LATITUDE, 0.0),
+                GetNormProjParm(SRS_PP_PEG_POINT_LONGITUDE, 0.0),
+                GetNormProjParm(SRS_PP_PEG_POINT_HEADING, 0.0),
+                GetNormProjParm(SRS_PP_PEG_POINT_HEIGHT, 0.0) );
+    }
+
     /* Note: This never really gets used currently.  See bug 423 */
     else if( EQUAL(pszProjection,SRS_PT_SWISS_OBLIQUE_CYLINDRICAL) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=somerc +lat_0=%.16g +lon_0=%.16g"
                  " +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
@@ -2220,7 +2177,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
     else if( EQUAL(pszProjection,SRS_PT_AITOFF) )
     {
         //+lat_ts=0.0
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=aitoff +lat_0=%.16g +lon_0=%.16g"
                  " +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
@@ -2228,10 +2185,10 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
     }
- 
+
     else if( EQUAL(pszProjection,SRS_PT_WINKEL_I) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=wink1 +lat_0=%.16g +lon_0=%.16g lat_ts=%.16g"
                  " +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
@@ -2243,7 +2200,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_WINKEL_II) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=wink2 +lat_0=%.16g +lon_0=%.16g +lat_1=%.16g"
                  " +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
@@ -2255,7 +2212,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_WINKEL_TRIPEL) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=wintri +lat_0=%.16g +lon_0=%.16g +lat_1=%.16g"
                  " +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
@@ -2267,7 +2224,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_CRASTER_PARABOLIC) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=crast +lat_0=%.16g +lon_0=%.16g"
                  " +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
@@ -2278,7 +2235,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_LOXIMUTHAL) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=loxim +lon_0=%.16g +lat_1=%.16g"
                  " +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
@@ -2289,7 +2246,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     else if( EQUAL(pszProjection,SRS_PT_QUARTIC_AUTHALIC) )
     {
-        CPLsprintf( szProj4+strlen(szProj4),
+        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
                  "+proj=qua_aut +lat_0=%.16g +lon_0=%.16g"
                  " +x_0=%.16g +y_0=%.16g ",
                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
@@ -2301,7 +2258,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
     else
     {
         CPLError( CE_Failure, CPLE_NotSupported,
-                  "No translation for %s to PROJ.4 format is known.", 
+                  "No translation for %s to PROJ.4 format is known.",
                   pszProjection );
         *ppszProj4 = CPLStrdup("");
         return OGRERR_UNSUPPORTED_SRS;
@@ -2311,8 +2268,8 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 /*      Handle earth model.  For now we just always emit the user       */
 /*      defined ellipsoid parameters.                                   */
 /* -------------------------------------------------------------------- */
-    double      dfSemiMajor = GetSemiMajor();
-    double      dfInvFlattening = GetInvFlattening();
+    const double      dfSemiMajor = GetSemiMajor();
+    const double      dfInvFlattening = GetInvFlattening();
     const char  *pszPROJ4Ellipse = NULL;
     const char  *pszDatum = GetAttrValue("DATUM");
 
@@ -2389,17 +2346,17 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
     else if( ABS(dfSemiMajor-6378165.0) < 0.01
              && ABS(dfInvFlattening-298.3) < 0.0001 )
     {
-        pszPROJ4Ellipse = "WGS60";      
+        pszPROJ4Ellipse = "WGS60";
     }
     else if( ABS(dfSemiMajor-6378145.0) < 0.01
              && ABS(dfInvFlattening-298.25) < 0.0001 )
     {
-        pszPROJ4Ellipse = "WGS66";      
+        pszPROJ4Ellipse = "WGS66";
     }
     else if( ABS(dfSemiMajor-6378135.0) < 0.01
              && ABS(dfInvFlattening-298.26) < 0.0001 )
     {
-        pszPROJ4Ellipse = "WGS72";      
+        pszPROJ4Ellipse = "WGS72";
     }
     else if( ABS(dfSemiMajor-6378137.0) < 0.01
              && ABS(dfInvFlattening-298.257223563) < 0.000001 )
@@ -2420,10 +2377,10 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
     char szEllipseDef[128];
 
     if( pszPROJ4Ellipse == NULL )
-        CPLsprintf( szEllipseDef, "+a=%.16g +b=%.16g ",
+      CPLsnprintf( szEllipseDef, sizeof(szEllipseDef), "+a=%.16g +b=%.16g ",
                  GetSemiMajor(), GetSemiMinor() );
     else
-        CPLsprintf( szEllipseDef, "+ellps=%s ",
+        CPLsnprintf( szEllipseDef, sizeof(szEllipseDef), "+ellps=%s ",
                  pszPROJ4Ellipse );
 
 /* -------------------------------------------------------------------- */
@@ -2431,19 +2388,16 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 /* -------------------------------------------------------------------- */
     const char *pszPROJ4Datum = NULL;
     const OGR_SRSNode *poTOWGS84 = GetAttrNode( "TOWGS84" );
-    char  szTOWGS84[256];
     int nEPSGDatum = -1;
-    const char *pszAuthority;
     int nEPSGGeogCS = -1;
-    const char *pszGeogCSAuthority;
     const char *pszProj4Grids = GetExtension( "DATUM", "PROJ4_GRIDS" );
 
-    pszAuthority = GetAuthorityName( "DATUM" );
+    const char *pszAuthority = GetAuthorityName( "DATUM" );
 
     if( pszAuthority != NULL && EQUAL(pszAuthority,"EPSG") )
         nEPSGDatum = atoi(GetAuthorityCode( "DATUM" ));
 
-    pszGeogCSAuthority = GetAuthorityName( "GEOGCS" );
+    const char *pszGeogCSAuthority = GetAuthorityName( "GEOGCS" );
 
     if( pszGeogCSAuthority != NULL && EQUAL(pszGeogCSAuthority,"EPSG") )
         nEPSGGeogCS = atoi(GetAuthorityCode( "GEOGCS" ));
@@ -2475,14 +2429,14 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
         pszPROJ4Datum = NULL;
     }
 
-    if( pszPROJ4Datum == NULL 
-        || CSLTestBoolean(CPLGetConfigOption("OVERRIDE_PROJ_DATUM_WITH_TOWGS84", "YES")) )
+    if( pszPROJ4Datum == NULL
+        || CPLTestBool(CPLGetConfigOption("OVERRIDE_PROJ_DATUM_WITH_TOWGS84", "YES")) )
     {
         if( poTOWGS84 != NULL )
         {
             int iChild;
             if( poTOWGS84->GetChildCount() >= 3
-                && (poTOWGS84->GetChildCount() < 7 
+                && (poTOWGS84->GetChildCount() < 7
                     || (EQUAL(poTOWGS84->GetChild(3)->GetValue(),"")
                         && EQUAL(poTOWGS84->GetChild(4)->GetValue(),"")
                         && EQUAL(poTOWGS84->GetChild(5)->GetValue(),"")
@@ -2513,7 +2467,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
                 pszPROJ4Datum = NULL;
             }
         }
-        
+
         // If we don't know the datum, trying looking up TOWGS84 parameters
         // based on the EPSG GCS code.
         else if( nEPSGGeogCS != -1 && pszPROJ4Datum == NULL )
@@ -2521,14 +2475,16 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
             std::vector<CPLString> asBursaTransform;
             if( EPSGGetWGS84Transform( nEPSGGeogCS, asBursaTransform ) )
             {
-                CPLsprintf( szTOWGS84, "+towgs84=%s,%s,%s,%s,%s,%s,%s",
-                         asBursaTransform[0].c_str(),
-                         asBursaTransform[1].c_str(),
-                         asBursaTransform[2].c_str(),
-                         asBursaTransform[3].c_str(),
-                         asBursaTransform[4].c_str(),
-                         asBursaTransform[5].c_str(),
-                         asBursaTransform[6].c_str() );
+                char szTOWGS84[256];
+                CPLsnprintf( szTOWGS84, sizeof(szTOWGS84),
+                             "+towgs84=%s,%s,%s,%s,%s,%s,%s",
+                             asBursaTransform[0].c_str(),
+                             asBursaTransform[1].c_str(),
+                             asBursaTransform[2].c_str(),
+                             asBursaTransform[3].c_str(),
+                             asBursaTransform[4].c_str(),
+                             asBursaTransform[5].c_str(),
+                             asBursaTransform[6].c_str() );
                 SAFE_PROJ4_STRCAT( szEllipseDef );
                 szEllipseDef[0] = '\0';
 
@@ -2538,7 +2494,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
             }
         }
     }
-    
+
     if( pszPROJ4Datum != NULL )
     {
         SAFE_PROJ4_STRCAT( "+datum=" );
@@ -2546,7 +2502,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
         SAFE_PROJ4_STRCAT( " " );
     }
     else // The ellipsedef may already have been appended and will now
-        // be empty, otherwise append now.
+         // be empty, otherwise append now.
     {
         SAFE_PROJ4_STRCAT( szEllipseDef );
         szEllipseDef[0] = '\0';
@@ -2555,11 +2511,10 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 /* -------------------------------------------------------------------- */
 /*      Is there prime meridian info to apply?                          */
 /* -------------------------------------------------------------------- */
-    if( poPRIMEM != NULL && poPRIMEM->GetChildCount() >= 2 
+    if( poPRIMEM != NULL && poPRIMEM->GetChildCount() >= 2
         && CPLAtof(poPRIMEM->GetChild(1)->GetValue()) != 0.0 )
     {
-        const char *pszAuthority = GetAuthorityName( "PRIMEM" );
-        char szPMValue[128];
+        pszAuthority = GetAuthorityName( "PRIMEM" );
         int  nCode = -1;
 
         if( pszAuthority != NULL && EQUAL(pszAuthority,"EPSG") )
@@ -2569,41 +2524,45 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
         if (nCode > 0)
             psProj4PM = OGRGetProj4PMFromCode(nCode);
         if (psProj4PM == NULL)
-            psProj4PM = OGRGetProj4PMFromVal(dfFromGreenwich);
+            psProj4PM = OGRGetProj4PMFromVal(l_dfFromGreenwich);
 
+        char szPMValue[128];
         if (psProj4PM != NULL)
         {
             strcpy( szPMValue, psProj4PM->pszProj4PMName );
         }
         else
         {
-            CPLsprintf( szPMValue, "%.16g", dfFromGreenwich );
+            CPLsnprintf( szPMValue, sizeof(szPMValue), "%.16g", l_dfFromGreenwich );
         }
 
         SAFE_PROJ4_STRCAT( "+pm=" );
         SAFE_PROJ4_STRCAT( szPMValue );
         SAFE_PROJ4_STRCAT( " " );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Handle linear units.                                            */
 /* -------------------------------------------------------------------- */
     const char  *pszPROJ4Units=NULL;
     char        *pszLinearUnits = NULL;
-    double      dfLinearConv;
+    double      dfLinearConv = GetLinearUnits( &pszLinearUnits );
 
-    dfLinearConv = GetLinearUnits( &pszLinearUnits );
-        
     if( strstr(szProj4,"longlat") != NULL )
         pszPROJ4Units = NULL;
-    else 
+    else
     {
-        pszPROJ4Units = LinearToProj4( dfLinearConv, pszLinearUnits );
+        const LinearUnitsStruct* psLinearUnits = GetLinearFromLinearConvOrName(
+                                                dfLinearConv, pszLinearUnits );
+        if( psLinearUnits != NULL )
+            pszPROJ4Units = psLinearUnits->pszProjName;
+        else
+            pszPROJ4Units = NULL;
 
         if( pszPROJ4Units == NULL )
         {
             char szLinearConv[128];
-            CPLsprintf( szLinearConv, "%.16g", dfLinearConv );
+            CPLsnprintf( szLinearConv, sizeof(szLinearConv), "%.16g", dfLinearConv );
             SAFE_PROJ4_STRCAT( "+to_meter=" );
             SAFE_PROJ4_STRCAT( szLinearConv );
             SAFE_PROJ4_STRCAT( " " );
@@ -2621,13 +2580,13 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 /*      If we have vertical datum grids, attach them to the proj.4 string.*/
 /* -------------------------------------------------------------------- */
     const char *pszProj4Geoids = GetExtension( "VERT_DATUM", "PROJ4_GRIDS" );
-    
+
     if( pszProj4Geoids != NULL )
     {
         SAFE_PROJ4_STRCAT( "+geoidgrids=" );
         SAFE_PROJ4_STRCAT( pszProj4Geoids );
         SAFE_PROJ4_STRCAT(  " " );
-    }    
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Handle vertical units, but only if we have them.                */
@@ -2643,14 +2602,19 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
         pszPROJ4Units = NULL;
 
         dfLinearConv = CPLAtof( poVUNITS->GetChild(1)->GetValue() );
-        
-        pszPROJ4Units = LinearToProj4( dfLinearConv,
-                                       poVUNITS->GetChild(0)->GetValue() );
-            
+
+        const LinearUnitsStruct* psLinearUnits = GetLinearFromLinearConvOrName(
+                                                dfLinearConv,
+                                                poVUNITS->GetChild(0)->GetValue() );
+        if( psLinearUnits != NULL )
+            pszPROJ4Units = psLinearUnits->pszProjName;
+        else
+            pszPROJ4Units = NULL;
+
         if( pszPROJ4Units == NULL )
         {
             char szLinearConv[128];
-            CPLsprintf( szLinearConv, "%.16g", dfLinearConv );
+            CPLsnprintf( szLinearConv, sizeof(szLinearConv), "%.16g", dfLinearConv );
             SAFE_PROJ4_STRCAT( "+vto_meter=" );
             SAFE_PROJ4_STRCAT( szLinearConv );
             SAFE_PROJ4_STRCAT( " " );
@@ -2668,7 +2632,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 /*      proj_def.dat are implicitly used with our definitions.          */
 /* -------------------------------------------------------------------- */
     SAFE_PROJ4_STRCAT( "+no_defs " );
-    
+
     *ppszProj4 = CPLStrdup( szProj4 );
 
     return OGRERR_NONE;
diff --git a/ogr/ogr_srs_usgs.cpp b/ogr/ogr_srs_usgs.cpp
index 20fc4de..d8e6881 100644
--- a/ogr/ogr_srs_usgs.cpp
+++ b/ogr/ogr_srs_usgs.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_srs_usgs.cpp 28565 2015-02-27 10:26:21Z rouault $
+ * $Id: ogr_srs_usgs.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGRSpatialReference translation to/from USGS georeferencing
@@ -34,7 +34,7 @@
 #include "cpl_conv.h"
 #include "cpl_csv.h"
 
-CPL_CVSID("$Id: ogr_srs_usgs.cpp 28565 2015-02-27 10:26:21Z rouault $");
+CPL_CVSID("$Id: ogr_srs_usgs.cpp 33631 2016-03-04 06:28:09Z goatbar $");
 
 /************************************************************************/
 /*  GCTP projection codes.                                              */
@@ -60,11 +60,11 @@ CPL_CVSID("$Id: ogr_srs_usgs.cpp 28565 2015-02-27 10:26:21Z rouault $");
 #define EQRECT  17L     // Equirectangular
 #define MILLER  18L     // Miller Cylindrical
 #define VGRINT  19L     // Van der Grinten
-#define HOM     20L     // (Hotine) Oblique Mercator 
+#define HOM     20L     // (Hotine) Oblique Mercator
 #define ROBIN   21L     // Robinson
 #define SOM     22L     // Space Oblique Mercator (SOM)
 #define ALASKA  23L     // Alaska Conformal
-#define GOODE   24L     // Interrupted Goode Homolosine 
+#define GOODE   24L     // Interrupted Goode Homolosine
 #define MOLL    25L     // Mollweide
 #define IMOLL   26L     // Interrupted Mollweide
 #define HAMMER  27L     // Hammer
@@ -73,11 +73,11 @@ CPL_CVSID("$Id: ogr_srs_usgs.cpp 28565 2015-02-27 10:26:21Z rouault $");
 #define OBEQA   30L     // Oblated Equal Area
 #define ISINUS1 31L     // Integerized Sinusoidal Grid (the same as 99)
 #define CEA     97L     // Cylindrical Equal Area (Grid corners set
-                        // in meters for EASE grid) 
+                        // in meters for EASE grid)
 #define BCEA    98L     // Cylindrical Equal Area (Grid corners set
-                        // in DMS degs for EASE grid) 
+                        // in DMS degs for EASE grid)
 #define ISINUS  99L     // Integerized Sinusoidal Grid
-                        // (added by Raj Gejjagaraguppe ARC for MODIS) 
+                        // (added by Raj Gejjagaraguppe ARC for MODIS)
 
 /************************************************************************/
 /*  GCTP ellipsoid codes.                                               */
@@ -108,7 +108,7 @@ CPL_CVSID("$Id: ogr_srs_usgs.cpp 28565 2015-02-27 10:26:21Z rouault $");
 /*  Correspondence between GCTP and EPSG ellipsoid codes.               */
 /************************************************************************/
 
-static const long aoEllips[] =
+static const int aoEllips[] =
 {
     7008,   // Clarke, 1866 (NAD1927)
     7034,   // Clarke, 1880
@@ -158,7 +158,7 @@ OGRErr OSRImportFromUSGS( OGRSpatialReferenceH hSRS, long iProjsys,
                           long iZone, double *padfPrjParams, long iDatum )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRImportFromUSGS", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRImportFromUSGS", OGRERR_FAILURE );
 
     return ((OGRSpatialReference *) hSRS)->importFromUSGS( iProjsys, iZone,
                                                            padfPrjParams,
@@ -204,13 +204,13 @@ static double OGRSpatialReferenceUSGSUnpackRadian(double dfVal)
  *        <h4>Projection Transformation Package Projection Parameters</h4>
  * <pre>
  * ----------------------------------------------------------------------------
- *                         |                    Array Element                  
+ *                         |                    Array Element
  *  Code & Projection Id   |---------------------------------------------------
  *                         |   0  |   1  |  2   |  3   |   4   |    5    |6 | 7
  * ----------------------------------------------------------------------------
- *  0 Geographic           |      |      |      |      |       |         |  |  
- *  1 U T M                |Lon/Z |Lat/Z |      |      |       |         |  |  
- *  2 State Plane          |      |      |      |      |       |         |  |  
+ *  0 Geographic           |      |      |      |      |       |         |  |
+ *  1 U T M                |Lon/Z |Lat/Z |      |      |       |         |  |
+ *  2 State Plane          |      |      |      |      |       |         |  |
  *  3 Albers Equal Area    |SMajor|SMinor|STDPR1|STDPR2|CentMer|OriginLat|FE|FN
  *  4 Lambert Conformal C  |SMajor|SMinor|STDPR1|STDPR2|CentMer|OriginLat|FE|FN
  *  5 Mercator             |SMajor|SMinor|      |      |CentMer|TrueScale|FE|FN
@@ -235,19 +235,19 @@ static double OGRSpatialReferenceUSGSUnpackRadian(double dfVal)
  * 22 Space Oblique Merc A |SMajor|SMinor|      |IncAng|AscLong|         |FE|FN
  *    Space Oblique Merc B |SMajor|SMinor|Satnum|Path  |       |         |FE|FN
  * 23 Alaska Conformal     |SMajor|SMinor|      |      |       |         |FE|FN
- * 24 Interrupted Goode    |Sphere|      |      |      |       |         |  |  
+ * 24 Interrupted Goode    |Sphere|      |      |      |       |         |  |
  * 25 Mollweide            |Sphere|      |      |      |CentMer|         |FE|FN
- * 26 Interrupt Mollweide  |Sphere|      |      |      |       |         |  |  
+ * 26 Interrupt Mollweide  |Sphere|      |      |      |       |         |  |
  * 27 Hammer               |Sphere|      |      |      |CentMer|         |FE|FN
  * 28 Wagner IV            |Sphere|      |      |      |CentMer|         |FE|FN
  * 29 Wagner VII           |Sphere|      |      |      |CentMer|         |FE|FN
  * 30 Oblated Equal Area   |Sphere|      |Shapem|Shapen|CentLon|CenterLat|FE|FN
  * ----------------------------------------------------------------------------
- * 
+ *
  *       ----------------------------------------------------
  *                               |      Array Element       |
  *         Code & Projection Id  |---------------------------
- *                               |  8  |  9 |  10 | 11 | 12 |  
+ *                               |  8  |  9 |  10 | 11 | 12 |
  *       ----------------------------------------------------
  *        0 Geographic           |     |    |     |    |    |
  *        1 U T M                |     |    |     |    |    |
@@ -257,12 +257,12 @@ static double OGRSpatialReferenceUSGSUnpackRadian(double dfVal)
  *        5 Mercator             |     |    |     |    |    |
  *        6 Polar Stereographic  |     |    |     |    |    |
  *        7 Polyconic            |     |    |     |    |    |
- *        8 Equid. Conic A       |zero |    |     |    |    |   
+ *        8 Equid. Conic A       |zero |    |     |    |    |
  *          Equid. Conic B       |one  |    |     |    |    |
  *        9 Transverse Mercator  |     |    |     |    |    |
  *       10 Stereographic        |     |    |     |    |    |
- *       11 Lambert Azimuthal    |     |    |     |    |    |    
- *       12 Azimuthal            |     |    |     |    |    |    
+ *       11 Lambert Azimuthal    |     |    |     |    |    |
+ *       12 Azimuthal            |     |    |     |    |    |
  *       13 Gnomonic             |     |    |     |    |    |
  *       14 Orthographic         |     |    |     |    |    |
  *       15 Gen. Vert. Near Per  |     |    |     |    |    |
@@ -270,10 +270,10 @@ static double OGRSpatialReferenceUSGSUnpackRadian(double dfVal)
  *       17 Equirectangular      |     |    |     |    |    |
  *       18 Miller Cylindrical   |     |    |     |    |    |
  *       19 Van der Grinten      |     |    |     |    |    |
- *       20 Hotin Oblique Merc A |Long1|Lat1|Long2|Lat2|zero|   
+ *       20 Hotin Oblique Merc A |Long1|Lat1|Long2|Lat2|zero|
  *          Hotin Oblique Merc B |     |    |     |    |one |
  *       21 Robinson             |     |    |     |    |    |
- *       22 Space Oblique Merc A |PSRev|LRat|PFlag|    |zero|    
+ *       22 Space Oblique Merc A |PSRev|LRat|PFlag|    |zero|
  *          Space Oblique Merc B |     |    |     |    |one |
  *       23 Alaska Conformal     |     |    |     |    |    |
  *       24 Interrupted Goode    |     |    |     |    |    |
@@ -405,12 +405,12 @@ static double OGRSpatialReferenceUSGSUnpackRadian(double dfVal)
  *
  * @param nUSGSAngleFormat one of USGS_ANGLE_DECIMALDEGREES, USGS_ANGLE_PACKEDDMS, or USGS_ANGLE_RADIANS (default is USGS_ANGLE_PACKEDDMS).
  *
- * @return OGRERR_NONE on success or an error code in case of failure. 
+ * @return OGRERR_NONE on success or an error code in case of failure.
  */
 
 OGRErr OGRSpatialReference::importFromUSGS( long iProjSys, long iZone,
                                             double *padfPrjParams,
-                                            long iDatum, 
+                                            long iDatum,
                                             int nUSGSAngleFormat  )
 
 {
@@ -456,7 +456,7 @@ OGRErr OGRSpatialReference::importFromUSGS( long iProjSys, long iZone,
                     iZone = -iZone;
                     bNorth = FALSE;
                 }
-                SetUTM( iZone, bNorth );
+                SetUTM( (int)iZone, bNorth );
             }
             break;
 
@@ -470,8 +470,8 @@ OGRErr OGRSpatialReference::importFromUSGS( long iProjSys, long iZone,
                     CPLError( CE_Warning, CPLE_AppDefined,
                               "Wrong datum for State Plane projection %d. "
                               "Should be 0 or 8.", (int) iDatum );
-                
-                SetStatePlane( iZone, bNAD83 );
+
+                SetStatePlane( (int)iZone, bNAD83 );
             }
             break;
 
@@ -646,7 +646,7 @@ OGRErr OGRSpatialReference::importFromUSGS( long iProjSys, long iZone,
         // FIXME: OBEQA --- Oblated Equal Area skipped
 
         // FIXME: ISINUS1 --- Integerized Sinusoidal Grid (the same as 99) skipped
-        
+
         // FIXME: CEA --- Cylindrical Equal Area skipped (Grid corners set in meters for EASE grid)
 
         // FIXME: BCEA --- Cylindrical Equal Area skipped (Grid corners set in DMS degs for EASE grid)
@@ -657,7 +657,7 @@ OGRErr OGRSpatialReference::importFromUSGS( long iProjSys, long iZone,
             CPLDebug( "OSR_USGS", "Unsupported projection: %ld", iProjSys );
             SetLocalCS( CPLString().Printf("GCTP projection number %ld", iProjSys) );
             break;
-            
+
     }
 
 /* -------------------------------------------------------------------- */
@@ -698,7 +698,7 @@ OGRErr OGRSpatialReference::importFromUSGS( long iProjSys, long iZone,
                     SetGeogCS( CPLString().Printf(
                                     "Unknown datum based upon the %s ellipsoid",
                                     pszName ),
-                               CPLString().Printf( 
+                               CPLString().Printf(
                                     "Not specified (based on %s spheroid)",
                                     pszName ),
                                pszName, dfSemiMajor, dfInvFlattening,
@@ -741,7 +741,7 @@ OGRErr OGRSpatialReference::importFromUSGS( long iProjSys, long iZone,
             {
                 CPLError( CE_Warning, CPLE_AppDefined,
                           "Failed to lookup datum code %d, likely due to missing GDAL gcs.csv\n"
-                          " file.  Falling back to use WGS84.", 
+                          " file.  Falling back to use WGS84.",
                           (int) iDatum );
                 SetWellKnownGeogCS("WGS84" );
             }
@@ -773,7 +773,7 @@ OGRErr OGRSpatialReference::importFromUSGS( long iProjSys, long iZone,
 /************************************************************************/
 /*                          OSRExportToUSGS()                           */
 /************************************************************************/
-/** 
+/**
  * \brief Export coordinate system in USGS GCTP projection definition.
  *
  * This function is the same as OGRSpatialReference::exportToUSGS().
@@ -784,7 +784,7 @@ OGRErr OSRExportToUSGS( OGRSpatialReferenceH hSRS,
                         double **ppadfPrjParams, long *piDatum )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRExportToUSGS", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRExportToUSGS", OGRERR_FAILURE );
 
     *ppadfPrjParams = NULL;
 
@@ -807,15 +807,15 @@ OGRErr OSRExportToUSGS( OGRSpatialReferenceH hSRS,
  *
  * @param piZone Pointer to variable, where the zone for UTM and State Plane
  * projection systems will be returned.
- * 
+ *
  * @param ppadfPrjParams Pointer to which dynamically allocated array of
  * 15 projection parameters will be assigned. See importFromUSGS() for
  * the list of parameters. Caller responsible to free this array.
  *
  * @param piDatum Pointer to variable, where the datum code will
  * be returned.
- * 
- * @return OGRERR_NONE on success or an error code on failure. 
+ *
+ * @return OGRERR_NONE on success or an error code on failure.
  */
 
 OGRErr OGRSpatialReference::exportToUSGS( long *piProjSys, long *piZone,
@@ -941,7 +941,7 @@ OGRErr OGRSpatialReference::exportToUSGS( long *piProjSys, long *piZone,
             *piProjSys = UTM;
             if( !bNorth )
                 *piZone = - *piZone;
-        }            
+        }
         else
         {
             *piProjSys = TM;
@@ -1127,7 +1127,7 @@ OGRErr OGRSpatialReference::exportToUSGS( long *piProjSys, long *piZone,
                   "Geographic system will be used.", pszProjection );
         *piProjSys = GEO;
     }
- 
+
 /* -------------------------------------------------------------------- */
 /*      Translate the datum.                                            */
 /* -------------------------------------------------------------------- */
@@ -1155,7 +1155,7 @@ OGRErr OGRSpatialReference::exportToUSGS( long *piProjSys, long *piZone,
                       "Datum \"%s\" unsupported by USGS GCTP. "
                       "Try to translate ellipsoid definition.", pszDatum );
 #endif
-            
+
             for ( i = 0; i < NUMBER_OF_ELLIPSOIDS; i++ )
             {
                 double  dfSM;
@@ -1198,4 +1198,3 @@ OGRErr OGRSpatialReference::exportToUSGS( long *piProjSys, long *piZone,
 
     return OGRERR_NONE;
 }
-
diff --git a/ogr/ogr_srs_validate.cpp b/ogr/ogr_srs_validate.cpp
index 17dbada..ac7180a 100644
--- a/ogr/ogr_srs_validate.cpp
+++ b/ogr/ogr_srs_validate.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_srs_validate.cpp 27975 2014-11-17 12:37:48Z rouault $
+ * $Id: ogr_srs_validate.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of the OGRSpatialReference::Validate() method and
@@ -33,12 +33,12 @@
 #include "ogr_p.h"
 #include "osr_cs_wkt.h"
 
-CPL_CVSID("$Id: ogr_srs_validate.cpp 27975 2014-11-17 12:37:48Z rouault $");
+CPL_CVSID("$Id: ogr_srs_validate.cpp 33631 2016-03-04 06:28:09Z goatbar $");
 
-/* why would fipszone and zone be paramers when they relate to a composite
+/* why would fipszone and zone be parameters when they relate to a composite
    projection which renders done into a non-zoned projection? */
 
-static const char *papszParameters[] =
+static const char * const papszParameters[] =
 {
     SRS_PP_CENTRAL_MERIDIAN,
     SRS_PP_SCALE_FACTOR,
@@ -69,6 +69,10 @@ static const char *papszParameters[] =
     SRS_PP_LONGITUDE_OF_1ST_POINT,
     SRS_PP_LATITUDE_OF_2ND_POINT,
     SRS_PP_LONGITUDE_OF_2ND_POINT,
+    SRS_PP_PEG_POINT_LATITUDE, /* for SCH */
+    SRS_PP_PEG_POINT_LONGITUDE, /* for SCH */
+    SRS_PP_PEG_POINT_HEADING, /* for SCH */
+    SRS_PP_PEG_POINT_HEIGHT, /* for SCH */
     NULL
 };
 
@@ -77,7 +81,7 @@ static const char *papszParameters[] =
 // underscores instead of spaces.  Should we use the EPSG names were available?
 // Plate-Caree has an accent in the spec!
 
-static const char *papszProjectionSupported[] =
+static const char * const papszProjectionSupported[] =
 {
     SRS_PT_CASSINI_SOLDNER,
     SRS_PT_BONNE,
@@ -128,15 +132,16 @@ static const char *papszProjectionSupported[] =
     SRS_PT_WAGNER_VI,
     SRS_PT_WAGNER_VII,
     SRS_PT_QSC,
+    SRS_PT_SCH,
     SRS_PT_GAUSSSCHREIBERTMERCATOR,
     SRS_PT_KROVAK,
     SRS_PT_CYLINDRICAL_EQUAL_AREA,
-    SRS_PT_GOODE_HOMOLOSINE, 
+    SRS_PT_GOODE_HOMOLOSINE,
     SRS_PT_IGH,
     NULL
 };
 
-static const char *papszProjectionUnsupported[] =
+static const char * const papszProjectionUnsupported[] =
 {
     SRS_PT_NEW_ZEALAND_MAP_GRID,
     SRS_PT_TUNISIA_MINING_GRID,
@@ -146,7 +151,7 @@ static const char *papszProjectionUnsupported[] =
 /*
 ** List of supported projections with the PARAMETERS[] acceptable for each.
 */
-static const char *papszProjWithParms[] = {
+static const char * const papszProjWithParms[] = {
 
     SRS_PT_TRANSVERSE_MERCATOR,
     SRS_PP_LATITUDE_OF_ORIGIN,
@@ -466,44 +471,44 @@ static const char *papszProjWithParms[] = {
     SRS_PT_IMW_POLYCONIC,
     SRS_PP_LATITUDE_OF_1ST_POINT,
     SRS_PP_LATITUDE_OF_2ND_POINT,
-    SRS_PP_CENTRAL_MERIDIAN, 
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
     NULL,
 
     SRS_PT_WAGNER_I,
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
     NULL,
 
     SRS_PT_WAGNER_II,
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
     NULL,
 
     SRS_PT_WAGNER_III,
     SRS_PP_LATITUDE_OF_ORIGIN,
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
     NULL,
 
     SRS_PT_WAGNER_IV,
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
     NULL,
 
     SRS_PT_WAGNER_V,
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
     NULL,
 
     SRS_PT_WAGNER_VI,
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
     NULL,
 
     SRS_PT_WAGNER_VII,
-    SRS_PP_FALSE_EASTING, 
+    SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
     NULL,
 
@@ -512,6 +517,13 @@ static const char *papszProjWithParms[] = {
     SRS_PP_CENTRAL_MERIDIAN,
     NULL,
 
+    SRS_PT_SCH,
+    SRS_PP_PEG_POINT_LATITUDE,
+    SRS_PP_PEG_POINT_LONGITUDE,
+    SRS_PP_PEG_POINT_HEADING,
+    SRS_PP_PEG_POINT_HEIGHT,
+    NULL,
+
     SRS_PT_GAUSSSCHREIBERTMERCATOR,
     SRS_PP_LATITUDE_OF_ORIGIN,
     SRS_PP_CENTRAL_MERIDIAN,
@@ -532,7 +544,7 @@ static const char *papszProjWithParms[] = {
     NULL
 };
 
-static const char *papszAliasGroupList[] = {
+static const char * const papszAliasGroupList[] = {
     SRS_PP_LATITUDE_OF_ORIGIN,
     SRS_PP_LATITUDE_OF_CENTER,
     NULL,
@@ -553,7 +565,7 @@ static const char *papszAliasGroupList[] = {
  *
  * This method attempts to verify that the spatial reference system is
  * well formed, and consists of known tokens.  The validation is not
- * comprehensive. 
+ * comprehensive.
  *
  * This method is the same as the C function OSRValidate().
  *
@@ -581,7 +593,7 @@ OGRErr OGRSpatialReference::Validate()
     /* using the CT spec grammar */
     static int bUseCTGrammar = -1;
     if( bUseCTGrammar < 0 )
-        bUseCTGrammar = CSLTestBoolean(CPLGetConfigOption("OSR_USE_CT_GRAMMAR", "TRUE"));
+        bUseCTGrammar = CPLTestBool(CPLGetConfigOption("OSR_USE_CT_GRAMMAR", "TRUE"));
 
     if( eErr == OGRERR_NONE && bUseCTGrammar )
     {
@@ -618,7 +630,7 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
         && !EQUAL(poRoot->GetValue(),"COMPD_CS"))
     {
         CPLDebug( "OGRSpatialReference::Validate",
-                  "Unrecognised root node `%s'\n",
+                  "Unrecognized root node `%s'\n",
                   poRoot->GetValue() );
         return OGRERR_CORRUPT_DATA;
     }
@@ -654,7 +666,7 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
             }
             else if( EQUAL(poNode->GetValue(),"EXTENSION") )
             {
-                // We do not try to control the sub-organization of 
+                // We do not try to control the sub-organization of
                 // EXTENSION nodes.
             }
             else
@@ -677,8 +689,8 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
     {
         OGR_SRSNode     *poNode;
         int             i;
-        int             bGotVertDatum = FALSE;
-        int             bGotUnit = FALSE;
+        bool            bGotVertDatum = false;
+        bool            bGotUnit = false;
         int             nCountAxis = 0;
 
         for( i = 1; i < poRoot->GetChildCount(); i++ )
@@ -690,14 +702,14 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
                 OGRErr eErr = ValidateVertDatum(poNode);
                 if (eErr != OGRERR_NONE)
                     return eErr;
-                bGotVertDatum = TRUE;
+                bGotVertDatum = true;
             }
             else if( EQUAL(poNode->GetValue(),"UNIT") )
             {
                 OGRErr eErr = ValidateUnit(poNode);
                 if (eErr != OGRERR_NONE)
                     return eErr;
-                bGotUnit = TRUE;
+                bGotUnit = true;
             }
             else if( EQUAL(poNode->GetValue(),"AXIS") )
             {
@@ -755,9 +767,9 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
     {
         OGR_SRSNode     *poNode;
         int             i;
-        int             bGotDatum = FALSE;
-        int             bGotPrimeM = FALSE;
-        int             bGotUnit = FALSE;
+        bool            bGotDatum = false;
+        bool            bGotPrimeM = false;
+        bool            bGotUnit = false;
         int             nCountAxis = 0;
 
         for( i = 1; i < poRoot->GetChildCount(); i++ )
@@ -766,20 +778,20 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
 
             if( EQUAL(poNode->GetValue(),"DATUM") )
             {
-                bGotDatum = TRUE;
+                bGotDatum = true;
             }
             else if( EQUAL(poNode->GetValue(),"PRIMEM") )
             {
-                bGotPrimeM = TRUE;
+                bGotPrimeM = true;
 
-                if( poNode->GetChildCount() < 2 
+                if( poNode->GetChildCount() < 2
                     || poNode->GetChildCount() > 3 )
                 {
                     CPLDebug( "OGRSpatialReference::Validate",
                               "PRIMEM has wrong number of children (%d),"
                               "not 2 or 3 as expected.\n",
                               poNode->GetChildCount() );
-                    
+
                     return OGRERR_CORRUPT_DATA;
                 }
             }
@@ -788,7 +800,7 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
                 OGRErr eErr = ValidateUnit(poNode);
                 if (eErr != OGRERR_NONE)
                     return eErr;
-                bGotUnit = TRUE;
+                bGotUnit = true;
             }
             else if( EQUAL(poNode->GetValue(),"AXIS") )
             {
@@ -876,16 +888,16 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
                               "PARAMETER has wrong number of children (%d),"
                               "not 2 as expected.\n",
                               poNode->GetChildCount() );
-                    
+
                     return OGRERR_CORRUPT_DATA;
                 }
                 else if( CSLFindString( (char **)papszParameters,
                                         poNode->GetChild(0)->GetValue()) == -1)
                 {
                     CPLDebug( "OGRSpatialReference::Validate",
-                              "Unrecognised PARAMETER `%s'.\n",
+                              "Unrecognized PARAMETER `%s'.\n",
                               poNode->GetChild(0)->GetValue() );
-                    
+
                     return OGRERR_UNSUPPORTED_SRS;
                 }
             }
@@ -897,7 +909,7 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
                               "PROJECTION has wrong number of children (%d),"
                               "not 1 or 2 as expected.\n",
                               poNode->GetChildCount() );
-                    
+
                     return OGRERR_CORRUPT_DATA;
                 }
                 else if( CSLFindString( (char **)papszProjectionSupported,
@@ -906,18 +918,18 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
                                         poNode->GetChild(0)->GetValue()) == -1)
                 {
                     CPLDebug( "OGRSpatialReference::Validate",
-                              "Unrecognised PROJECTION `%s'.\n",
+                              "Unrecognized PROJECTION `%s'.\n",
                               poNode->GetChild(0)->GetValue() );
-                    
+
                     return OGRERR_UNSUPPORTED_SRS;
                 }
                 else if( CSLFindString( (char **)papszProjectionSupported,
                                         poNode->GetChild(0)->GetValue()) == -1)
                 {
                     CPLDebug( "OGRSpatialReference::Validate",
-                              "Unsupported, but recognised PROJECTION `%s'.\n",
+                              "Unsupported, but recognized PROJECTION `%s'.\n",
                               poNode->GetChild(0)->GetValue() );
-                    
+
                     return OGRERR_UNSUPPORTED_SRS;
                 }
 
@@ -954,7 +966,7 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
             }
             else if( EQUAL(poNode->GetValue(),"EXTENSION") )
             {
-                // We do not try to control the sub-organization of 
+                // We do not try to control the sub-organization of
                 // EXTENSION nodes.
             }
             else
@@ -962,12 +974,12 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
                 CPLDebug( "OGRSpatialReference::Validate",
                           "Unexpected child for PROJCS `%s'.\n",
                           poNode->GetValue() );
-                
+
                 return OGRERR_CORRUPT_DATA;
             }
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Validate GEOGCS if found.                                       */
 /* -------------------------------------------------------------------- */
@@ -988,14 +1000,14 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
             }
             else if( EQUAL(poNode->GetValue(),"PRIMEM") )
             {
-                if( poNode->GetChildCount() < 2 
+                if( poNode->GetChildCount() < 2
                     || poNode->GetChildCount() > 3 )
                 {
                     CPLDebug( "OGRSpatialReference::Validate",
                               "PRIMEM has wrong number of children (%d),"
                               "not 2 or 3 as expected.\n",
                               poNode->GetChildCount() );
-                    
+
                     return OGRERR_CORRUPT_DATA;
                 }
             }
@@ -1013,7 +1025,7 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
             }
             else if( EQUAL(poNode->GetValue(),"EXTENSION") )
             {
-                // We do not try to control the sub-organization of 
+                // We do not try to control the sub-organization of
                 // EXTENSION nodes.
             }
             else if( EQUAL(poNode->GetValue(),"AUTHORITY") )
@@ -1027,7 +1039,7 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
                 CPLDebug( "OGRSpatialReference::Validate",
                           "Unexpected child for GEOGCS `%s'.\n",
                           poNode->GetValue() );
-                
+
                 return OGRERR_CORRUPT_DATA;
             }
         }
@@ -1036,7 +1048,7 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
         {
             CPLDebug( "OGRSpatialReference::Validate",
                       "No DATUM child in GEOGCS.\n" );
-            
+
             return OGRERR_CORRUPT_DATA;
         }
     }
@@ -1049,14 +1061,14 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
     if( poDATUM != NULL )
     {
         OGR_SRSNode     *poSPHEROID;
-        int             bGotSpheroid = FALSE;
+        bool            bGotSpheroid = false;
         int             i;
 
         if( poDATUM->GetChildCount() == 0 )
         {
             CPLDebug( "OGRSpatialReference::Validate",
                       "DATUM has no children." );
-            
+
             return OGRERR_CORRUPT_DATA;
         }
 
@@ -1068,16 +1080,16 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
             if( EQUAL(poNode->GetValue(),"SPHEROID") )
             {
                 poSPHEROID = poDATUM->GetChild(1);
-                bGotSpheroid = TRUE;
+                bGotSpheroid = true;
 
-                if( poSPHEROID->GetChildCount() != 3 
+                if( poSPHEROID->GetChildCount() != 3
                     && poSPHEROID->GetChildCount() != 4 )
                 {
                     CPLDebug( "OGRSpatialReference::Validate",
                               "SPHEROID has wrong number of children (%d),"
                               "not 3 or 4 as expected.\n",
                               poSPHEROID->GetChildCount() );
-                    
+
                     return OGRERR_CORRUPT_DATA;
                 }
                 else if( CPLAtof(poSPHEROID->GetChild(1)->GetValue()) == 0.0 )
@@ -1096,7 +1108,7 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
             }
             else if( EQUAL(poNode->GetValue(),"TOWGS84") )
             {
-                if( poNode->GetChildCount() != 3 
+                if( poNode->GetChildCount() != 3
                     && poNode->GetChildCount() != 7)
                 {
                     CPLDebug( "OGRSpatialReference::Validate",
@@ -1107,7 +1119,7 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
             }
             else if( EQUAL(poNode->GetValue(),"EXTENSION") )
             {
-                // We do not try to control the sub-organization of 
+                // We do not try to control the sub-organization of
                 // EXTENSION nodes.
             }
             else
@@ -1115,7 +1127,7 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
                 CPLDebug( "OGRSpatialReference::Validate",
                           "Unexpected child for DATUM `%s'.\n",
                           poNode->GetValue() );
-                
+
                 return OGRERR_CORRUPT_DATA;
             }
         }
@@ -1124,10 +1136,10 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
         {
             CPLDebug( "OGRSpatialReference::Validate",
                       "No SPHEROID child in DATUM.\n" );
-            
+
             return OGRERR_CORRUPT_DATA;
         }
-    }        
+    }
 
 /* -------------------------------------------------------------------- */
 /*      If this is projected, try to validate the detailed set of       */
@@ -1145,7 +1157,7 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
 /************************************************************************/
 /*                            OSRValidate()                             */
 /************************************************************************/
-/** 
+/**
  * \brief Validate SRS tokens.
  *
  * This function is the same as the C++ method OGRSpatialReference::Validate().
@@ -1153,7 +1165,7 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
 OGRErr OSRValidate( OGRSpatialReferenceH hSRS )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRValidate", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRValidate", OGRERR_FAILURE );
 
     return ((OGRSpatialReference *) hSRS)->Validate();
 }
@@ -1171,7 +1183,7 @@ OGRErr OSRValidate( OGRSpatialReferenceH hSRS )
  *
  * @return TRUE if both strings are aliases according to the AliasGroupList, FALSE otherwise
  */
-int OGRSpatialReference::IsAliasFor( const char *pszParm1, 
+int OGRSpatialReference::IsAliasFor( const char *pszParm1,
                                      const char *pszParm2 )
 
 {
@@ -1227,7 +1239,7 @@ OGRErr OGRSpatialReference::ValidateProjection(OGR_SRSNode *poRoot)
 
     if( poPROJCS->GetNode( "PROJECTION" ) == NULL )
     {
-        CPLDebug( "OGRSpatialReference::Validate", 
+        CPLDebug( "OGRSpatialReference::Validate",
                   "PROJCS does not have PROJECTION subnode." );
         return OGRERR_CORRUPT_DATA;
     }
@@ -1237,10 +1249,10 @@ OGRErr OGRSpatialReference::ValidateProjection(OGR_SRSNode *poRoot)
 /* -------------------------------------------------------------------- */
     const char *pszProjection;
     int        iOffset;
-    
+
     pszProjection = poPROJCS->GetNode("PROJECTION")->GetChild(0)->GetValue();
 
-    for( iOffset = 0; 
+    for( iOffset = 0;
          papszProjWithParms[iOffset] != NULL
              && !EQUAL(papszProjWithParms[iOffset],pszProjection); )
     {
@@ -1288,14 +1300,14 @@ OGRErr OGRSpatialReference::ValidateProjection(OGR_SRSNode *poRoot)
 
             if( papszProjWithParms[i] == NULL )
             {
-                CPLDebug( "OGRSpatialReference::Validate", 
+                CPLDebug( "OGRSpatialReference::Validate",
                           "PARAMETER %s for PROJECTION %s is not permitted.",
                           pszParmName, pszProjection );
                 return OGRERR_CORRUPT_DATA;
             }
             else
             {
-                CPLDebug( "OGRSpatialReference::Validate", 
+                CPLDebug( "OGRSpatialReference::Validate",
                           "PARAMETER %s for PROJECTION %s is an alias for %s.",
                           pszParmName, pszProjection,
                           papszProjWithParms[i] );
@@ -1455,4 +1467,3 @@ OGRErr OGRSpatialReference::ValidateUnit(OGR_SRSNode *poRoot)
 
     return OGRERR_NONE;
 }
-
diff --git a/ogr/ogr_srs_xml.cpp b/ogr/ogr_srs_xml.cpp
index 77bb663..2765f8b 100644
--- a/ogr/ogr_srs_xml.cpp
+++ b/ogr/ogr_srs_xml.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_srs_xml.cpp 28767 2015-03-25 10:48:08Z rouault $
+ * $Id: ogr_srs_xml.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGRSpatialReference interface to OGC XML (014r4).
@@ -41,15 +41,13 @@
 /*      original string.                                                */
 /************************************************************************/
 
-static int parseURN( char *pszURN, 
-                     const char **ppszObjectType, 
-                     const char **ppszAuthority, 
-                     const char **ppszCode,
-                     const char **ppszVersion = NULL )
+static bool parseURN( char *pszURN,
+                      const char **ppszObjectType,
+                      const char **ppszAuthority,
+                      const char **ppszCode,
+                      const char **ppszVersion = NULL )
 
 {
-    int  i;
-
     if( ppszObjectType != NULL )
         *ppszObjectType = "";
     if( ppszAuthority != NULL )
@@ -62,8 +60,8 @@ static int parseURN( char *pszURN,
 /* -------------------------------------------------------------------- */
 /*      Verify prefix.                                                  */
 /* -------------------------------------------------------------------- */
-    if( !EQUALN(pszURN,"urn:ogc:def:",12) )
-        return FALSE;
+    if( !STARTS_WITH_CI(pszURN, "urn:ogc:def:") )
+        return false;
 
 /* -------------------------------------------------------------------- */
 /*      Extract object type                                             */
@@ -71,12 +69,12 @@ static int parseURN( char *pszURN,
     if( ppszObjectType != NULL )
         *ppszObjectType = (const char *) pszURN + 12;
 
-    i = 12;
+    int  i = 12;
     while( pszURN[i] != ':' && pszURN[i] != '\0' )
         i++;
 
     if( pszURN[i] == '\0' )
-        return FALSE;
+        return false;
 
     pszURN[i] = '\0';
     i++;
@@ -91,7 +89,7 @@ static int parseURN( char *pszURN,
         i++;
 
     if( pszURN[i] == '\0' )
-        return FALSE;
+        return false;
 
     pszURN[i] = '\0';
     i++;
@@ -106,7 +104,7 @@ static int parseURN( char *pszURN,
         i++;
 
     if( pszURN[i] == '\0' )
-        return FALSE;
+        return false;
 
     pszURN[i] = '\0';
     i++;
@@ -116,34 +114,33 @@ static int parseURN( char *pszURN,
 /* -------------------------------------------------------------------- */
     if( ppszCode != NULL )
         *ppszCode = (char *) pszURN + i;
-    
-    return TRUE;
+
+    return true;
 }
 
 /************************************************************************/
 /*                               addURN()                               */
 /************************************************************************/
 
-static void addURN( CPLXMLNode *psTarget, 
-                    const char *pszAuthority, 
-                    const char *pszObjectType, 
+static void addURN( CPLXMLNode *psTarget,
+                    const char *pszAuthority,
+                    const char *pszObjectType,
                     int nCode,
                     const char *pszVersion = "" )
 
 {
-    char szURN[200];
-
     if( pszVersion == NULL )
         pszVersion = "";
 
+    char szURN[200];
     CPLAssert( strlen(pszAuthority)+strlen(pszObjectType) < sizeof(szURN)-30 );
 
-    sprintf( szURN, "urn:ogc:def:%s:%s:%s:", 
+    snprintf( szURN, sizeof(szURN), "urn:ogc:def:%s:%s:%s:",
              pszObjectType, pszAuthority, pszVersion );
-    
+
     if( nCode != 0 )
-        sprintf( szURN + strlen(szURN), "%d", nCode );
-    
+        snprintf( szURN + strlen(szURN), sizeof(szURN) - strlen(szURN), "%d", nCode );
+
     CPLCreateXMLNode(
         CPLCreateXMLNode( psTarget, CXT_Attribute, "xlink:href" ),
         CXT_Text, szURN );
@@ -157,17 +154,16 @@ static void addURN( CPLXMLNode *psTarget,
 /************************************************************************/
 
 static CPLXMLNode *
-AddValueIDWithURN( CPLXMLNode *psTarget, 
+AddValueIDWithURN( CPLXMLNode *psTarget,
                    const char *pszElement,
-                   const char *pszAuthority, 
-                   const char *pszObjectType, 
+                   const char *pszAuthority,
+                   const char *pszObjectType,
                    int nCode,
                    const char *pszVersion = "" )
-    
-{
-    CPLXMLNode *psElement;
 
-    psElement = CPLCreateXMLNode( psTarget, CXT_Element, pszElement );
+{
+    CPLXMLNode *psElement
+        = CPLCreateXMLNode( psTarget, CXT_Element, pszElement );
     addURN( psElement, pszAuthority, pszObjectType, nCode, pszVersion );
 
     return psElement;
@@ -181,37 +177,36 @@ AddValueIDWithURN( CPLXMLNode *psTarget,
 /*        <name codeSpace="urn">code</name>                             */
 /*      </srsId>                                                        */
 /************************************************************************/
-static CPLXMLNode *addAuthorityIDBlock( CPLXMLNode *psTarget, 
+static CPLXMLNode *addAuthorityIDBlock( CPLXMLNode *psTarget,
                                      const char *pszElement,
-                                     const char *pszAuthority, 
-                                     const char *pszObjectType, 
+                                     const char *pszAuthority,
+                                     const char *pszObjectType,
                                      int nCode,
                                      const char *pszVersion = "" )
 
 {
-    char szURN[200];
-
 /* -------------------------------------------------------------------- */
 /*      Prepare partial URN without the actual code.                    */
 /* -------------------------------------------------------------------- */
     if( pszVersion == NULL )
         pszVersion = "";
 
+    char szURN[200];
     CPLAssert( strlen(pszAuthority)+strlen(pszObjectType) < sizeof(szURN)-30 );
 
-    sprintf( szURN, "urn:ogc:def:%s:%s:%s:", 
+    snprintf( szURN, sizeof(szURN), "urn:ogc:def:%s:%s:%s:",
              pszObjectType, pszAuthority, pszVersion );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Prepare the base name, eg. <srsID>.                             */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psElement = 
+    CPLXMLNode *psElement =
         CPLCreateXMLNode( psTarget, CXT_Element, pszElement );
 
 /* -------------------------------------------------------------------- */
 /*      Prepare the name element.                                       */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode * psName = 
+    CPLXMLNode * psName =
         CPLCreateXMLNode( psElement, CXT_Element, "gml:name" );
 
 /* -------------------------------------------------------------------- */
@@ -225,7 +220,7 @@ static CPLXMLNode *addAuthorityIDBlock( CPLXMLNode *psTarget,
 /*      Attach code value to name node.                                 */
 /* -------------------------------------------------------------------- */
     char szCode[32];
-    sprintf( szCode, "%d", nCode );
+    snprintf( szCode, sizeof(szCode), "%d", nCode );
 
     CPLCreateXMLNode( psName, CXT_Text, szCode );
 
@@ -245,7 +240,7 @@ static void addGMLId( CPLXMLNode *psParent )
     static int nNextGMLId = 1;
     char   szIdText[40];
 
-    sprintf( szIdText, "ogrcrs%d", nNextGMLId++ );
+    snprintf( szIdText, sizeof(szIdText), "ogrcrs%d", nNextGMLId++ );
 
     /* psId =  */
     CPLCreateXMLNode(
@@ -272,7 +267,7 @@ static CPLXMLNode *exportAuthorityToXML( const OGR_SRSNode *poAuthParent,
     if( poAuthParent->FindChild( "AUTHORITY" ) == -1 )
         return NULL;
 
-    poAuthority = poAuthParent->GetChild( 
+    poAuthority = poAuthParent->GetChild(
         poAuthParent->FindChild( "AUTHORITY" ));
 
 /* -------------------------------------------------------------------- */
@@ -285,26 +280,24 @@ static CPLXMLNode *exportAuthorityToXML( const OGR_SRSNode *poAuthParent,
     pszEdition = NULL;
 
     if( bUseSubName )
-        return addAuthorityIDBlock( psXMLParent, pszTagName, pszCodeSpace, 
+        return addAuthorityIDBlock( psXMLParent, pszTagName, pszCodeSpace,
                                  pszObjectType, atoi(pszCode), pszEdition );
-    else
-        return AddValueIDWithURN( psXMLParent, pszTagName, pszCodeSpace, 
-                                  pszObjectType, atoi(pszCode), pszEdition );
-                              
+
+    return AddValueIDWithURN( psXMLParent, pszTagName, pszCodeSpace,
+                              pszObjectType, atoi(pszCode), pszEdition );
 }
 
 /************************************************************************/
 /*                             addProjArg()                             */
 /************************************************************************/
 
-static void addProjArg( const OGRSpatialReference *poSRS, CPLXMLNode *psBase, 
+static void addProjArg( const OGRSpatialReference *poSRS, CPLXMLNode *psBase,
                         const char *pszMeasureType, double dfDefault,
                         int nParameterID, const char *pszWKTName )
 
 {
-    CPLXMLNode *psNode, *psValue;
-
-    psNode = CPLCreateXMLNode( psBase, CXT_Element, "gml:usesValue" );
+    CPLXMLNode *psNode
+        = CPLCreateXMLNode( psBase, CXT_Element, "gml:usesValue" );
 
 /* -------------------------------------------------------------------- */
 /*      Handle the UOM.                                                 */
@@ -316,25 +309,26 @@ static void addProjArg( const OGRSpatialReference *poSRS, CPLXMLNode *psBase,
     else
         pszUOMValue = "urn:ogc:def:uom:EPSG::9001";
 
-    psValue = CPLCreateXMLNode( psNode, CXT_Element, "gml:value" );
+    CPLXMLNode *psValue
+        = CPLCreateXMLNode( psNode, CXT_Element, "gml:value" );
 
-    CPLCreateXMLNode( 
+    CPLCreateXMLNode(
         CPLCreateXMLNode( psValue, CXT_Attribute, "uom" ),
         CXT_Text, pszUOMValue );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Add the parameter value itself.                                 */
 /* -------------------------------------------------------------------- */
     double dfParmValue
         = poSRS->GetNormProjParm( pszWKTName, dfDefault, NULL );
-        
-    CPLCreateXMLNode( psValue, CXT_Text, 
+
+    CPLCreateXMLNode( psValue, CXT_Text,
                       CPLString().Printf( "%.16g", dfParmValue ) );
 
 /* -------------------------------------------------------------------- */
 /*      Add the valueOfParameter.                                       */
 /* -------------------------------------------------------------------- */
-    AddValueIDWithURN( psNode, "gml:valueOfParameter", "EPSG", "parameter", 
+    AddValueIDWithURN( psNode, "gml:valueOfParameter", "EPSG", "parameter",
                        nParameterID );
 }
 
@@ -344,22 +338,25 @@ static void addProjArg( const OGRSpatialReference *poSRS, CPLXMLNode *psBase,
 /*      Added the <usesAxis> element and down.                          */
 /************************************************************************/
 
-static CPLXMLNode *addAxis( CPLXMLNode *psXMLParent, 
+static CPLXMLNode *addAxis( CPLXMLNode *psXMLParent,
                             const char *pszAxis, // "Lat", "Long", "E" or "N"
                             const OGR_SRSNode * /* poUnitsSrc */ )
 
 {
-    CPLXMLNode *psAxisXML;
-
-    psAxisXML = 
-        CPLCreateXMLNode( 
+    CPLXMLNode *psAxisXML =
+        CPLCreateXMLNode(
             CPLCreateXMLNode( psXMLParent, CXT_Element, "gml:usesAxis" ),
             CXT_Element, "gml:CoordinateSystemAxis" );
+    if (!psAxisXML)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "addAxis failed." );
+        return NULL;
+    }
     addGMLId( psAxisXML );
 
     if( EQUAL(pszAxis,"Lat") )
     {
-        CPLCreateXMLNode( 
+        CPLCreateXMLNode(
             CPLCreateXMLNode( psAxisXML, CXT_Attribute, "gml:uom" ),
             CXT_Text, "urn:ogc:def:uom:EPSG::9102" );
 
@@ -371,7 +368,7 @@ static CPLXMLNode *addAxis( CPLXMLNode *psXMLParent,
     }
     else if( EQUAL(pszAxis,"Long") )
     {
-        CPLCreateXMLNode( 
+        CPLCreateXMLNode(
             CPLCreateXMLNode( psAxisXML, CXT_Attribute, "gml:uom" ),
             CXT_Text, "urn:ogc:def:uom:EPSG::9102" );
 
@@ -383,7 +380,7 @@ static CPLXMLNode *addAxis( CPLXMLNode *psXMLParent,
     }
     else if( EQUAL(pszAxis,"E") )
     {
-        CPLCreateXMLNode( 
+        CPLCreateXMLNode(
             CPLCreateXMLNode( psAxisXML, CXT_Attribute, "gml:uom" ),
             CXT_Text, "urn:ogc:def:uom:EPSG::9001" );
 
@@ -394,7 +391,7 @@ static CPLXMLNode *addAxis( CPLXMLNode *psXMLParent,
     }
     else if( EQUAL(pszAxis,"N") )
     {
-        CPLCreateXMLNode( 
+        CPLCreateXMLNode(
             CPLCreateXMLNode( psAxisXML, CXT_Attribute, "gml:uom" ),
             CXT_Text, "urn:ogc:def:uom:EPSG::9001" );
 
@@ -418,22 +415,22 @@ static CPLXMLNode *addAxis( CPLXMLNode *psXMLParent,
 static CPLXMLNode *exportGeogCSToXML( const OGRSpatialReference *poSRS )
 
 {
-    CPLXMLNode  *psGCS_XML;
     const OGR_SRSNode *poGeogCS = poSRS->GetAttrNode( "GEOGCS" );
 
     if( poGeogCS == NULL )
         return NULL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Establish initial infrastructure.                               */
 /* -------------------------------------------------------------------- */
-    psGCS_XML = CPLCreateXMLNode( NULL, CXT_Element, "gml:GeographicCRS" );
+    CPLXMLNode  *psGCS_XML
+        = CPLCreateXMLNode( NULL, CXT_Element, "gml:GeographicCRS" );
     addGMLId( psGCS_XML );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Attach symbolic name (srsName).                                 */
 /* -------------------------------------------------------------------- */
-    CPLCreateXMLElementAndValue( psGCS_XML, "gml:srsName", 
+    CPLCreateXMLElementAndValue( psGCS_XML, "gml:srsName",
                                  poGeogCS->GetChild(0)->GetValue() );
 
 /* -------------------------------------------------------------------- */
@@ -447,9 +444,8 @@ static CPLXMLNode *exportGeogCSToXML( const OGRSpatialReference *poSRS )
 /*      ellipsoidalCS.  Basically this defines the axes and their       */
 /*      units.                                                          */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psECS;
-
-    psECS = CPLCreateXMLNode( 
+    CPLXMLNode *psECS
+        = CPLCreateXMLNode(
         CPLCreateXMLNode( psGCS_XML, CXT_Element, "gml:usesEllipsoidalCS" ),
         CXT_Element, "gml:EllipsoidalCS" );
 
@@ -466,7 +462,6 @@ static CPLXMLNode *exportGeogCSToXML( const OGRSpatialReference *poSRS )
 /*      Start with the datum.                                           */
 /* -------------------------------------------------------------------- */
     const OGR_SRSNode    *poDatum = poGeogCS->GetNode( "DATUM" );
-    CPLXMLNode     *psDatumXML;
 
     if( poDatum == NULL )
     {
@@ -474,16 +469,17 @@ static CPLXMLNode *exportGeogCSToXML( const OGRSpatialReference *poSRS )
         return NULL;
     }
 
-    psDatumXML = CPLCreateXMLNode( 
+    CPLXMLNode *psDatumXML
+        = CPLCreateXMLNode(
         CPLCreateXMLNode( psGCS_XML, CXT_Element, "gml:usesGeodeticDatum" ),
         CXT_Element, "gml:GeodeticDatum" );
-    
+
     addGMLId( psDatumXML );
 
 /* -------------------------------------------------------------------- */
 /*      Set the datumName.                                              */
 /* -------------------------------------------------------------------- */
-    CPLCreateXMLElementAndValue( psDatumXML, "gml:datumName", 
+    CPLCreateXMLElementAndValue( psDatumXML, "gml:datumName",
                                  poDatum->GetChild(0)->GetValue() );
 
 /* -------------------------------------------------------------------- */
@@ -495,11 +491,11 @@ static CPLXMLNode *exportGeogCSToXML( const OGRSpatialReference *poSRS )
 /*      Setup prime meridian information.                               */
 /* -------------------------------------------------------------------- */
     const OGR_SRSNode *poPMNode = poGeogCS->GetNode( "PRIMEM" );
-    CPLXMLNode *psPM;
     char *pszPMName = (char* ) "Greenwich";
     double dfPMOffset = poSRS->GetPrimeMeridian( &pszPMName );
 
-    psPM = CPLCreateXMLNode( 
+    CPLXMLNode *psPM
+        = CPLCreateXMLNode(
         CPLCreateXMLNode( psDatumXML, CXT_Element, "gml:usesPrimeMeridian" ),
         CXT_Element, "gml:PrimeMeridian" );
 
@@ -510,19 +506,17 @@ static CPLXMLNode *exportGeogCSToXML( const OGRSpatialReference *poSRS )
     if( poPMNode )
         exportAuthorityToXML( poPMNode, "gml:meridianID", psPM, "meridian" );
 
-    CPLXMLNode *psAngle;
-
-    psAngle = 
-        CPLCreateXMLNode( 
+    CPLXMLNode *psAngle
+        = CPLCreateXMLNode(
             CPLCreateXMLNode( psPM, CXT_Element, "gml:greenwichLongitude" ),
             CXT_Element, "gml:angle" );
-    
+
     CPLCreateXMLNode( CPLCreateXMLNode( psAngle, CXT_Attribute, "uom" ),
                       CXT_Text, "urn:ogc:def:uom:EPSG::9102" );
 
-    CPLCreateXMLNode( psAngle, CXT_Text, 
+    CPLCreateXMLNode( psAngle, CXT_Text,
                       CPLString().Printf( "%.16g", dfPMOffset ) );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Translate the ellipsoid.                                        */
 /* -------------------------------------------------------------------- */
@@ -530,42 +524,39 @@ static CPLXMLNode *exportGeogCSToXML( const OGRSpatialReference *poSRS )
 
     if( poEllipsoid != NULL )
     {
-        CPLXMLNode *psEllipseXML;
-
-        psEllipseXML = 
-            CPLCreateXMLNode( 
+        CPLXMLNode *psEllipseXML
+            = CPLCreateXMLNode(
                 CPLCreateXMLNode(psDatumXML,CXT_Element,"gml:usesEllipsoid" ),
                 CXT_Element, "gml:Ellipsoid" );
 
         addGMLId( psEllipseXML );
 
-        CPLCreateXMLElementAndValue( psEllipseXML, "gml:ellipsoidName", 
+        CPLCreateXMLElementAndValue( psEllipseXML, "gml:ellipsoidName",
                                      poEllipsoid->GetChild(0)->GetValue() );
 
         exportAuthorityToXML( poEllipsoid, "gml:ellipsoidID", psEllipseXML,
                               "ellipsoid");
-        
-        CPLXMLNode *psParmXML;
 
-        psParmXML = CPLCreateXMLNode( psEllipseXML, CXT_Element, 
+        CPLXMLNode *psParmXML
+            = CPLCreateXMLNode( psEllipseXML, CXT_Element,
                                       "gml:semiMajorAxis" );
 
         CPLCreateXMLNode( CPLCreateXMLNode(psParmXML,CXT_Attribute,"uom"),
                           CXT_Text, "urn:ogc:def:uom:EPSG::9001" );
 
-        CPLCreateXMLNode( psParmXML, CXT_Text, 
+        CPLCreateXMLNode( psParmXML, CXT_Text,
                           poEllipsoid->GetChild(1)->GetValue() );
 
-        psParmXML = 
-            CPLCreateXMLNode( 
-                CPLCreateXMLNode( psEllipseXML, CXT_Element, 
+        psParmXML =
+            CPLCreateXMLNode(
+                CPLCreateXMLNode( psEllipseXML, CXT_Element,
                                   "gml:secondDefiningParameter" ),
                 CXT_Element, "gml:inverseFlattening" );
-        
+
         CPLCreateXMLNode( CPLCreateXMLNode(psParmXML,CXT_Attribute,"uom"),
                           CXT_Text, "urn:ogc:def:uom:EPSG::9201" );
 
-        CPLCreateXMLNode( psParmXML, CXT_Text, 
+        CPLCreateXMLNode( psParmXML, CXT_Text,
                           poEllipsoid->GetChild(2)->GetValue() );
     }
 
@@ -583,19 +574,18 @@ static CPLXMLNode *exportProjCSToXML( const OGRSpatialReference *poSRS )
 
     if( poProjCS == NULL )
         return NULL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Establish initial infrastructure.                               */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode   *psCRS_XML;
-
-    psCRS_XML = CPLCreateXMLNode( NULL, CXT_Element, "gml:ProjectedCRS" );
+    CPLXMLNode   *psCRS_XML
+        = CPLCreateXMLNode( NULL, CXT_Element, "gml:ProjectedCRS" );
     addGMLId( psCRS_XML );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Attach symbolic name (a name in a nameset).                     */
 /* -------------------------------------------------------------------- */
-    CPLCreateXMLElementAndValue( psCRS_XML, "gml:srsName", 
+    CPLCreateXMLElementAndValue( psCRS_XML, "gml:srsName",
                                  poProjCS->GetChild(0)->GetValue() );
 
 /* -------------------------------------------------------------------- */
@@ -614,29 +604,27 @@ static CPLXMLNode *exportProjCSToXML( const OGRSpatialReference *poSRS )
 /* -------------------------------------------------------------------- */
 /*      Our projected coordinate system is "defined by Conversion".     */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psDefinedBy;
-
-    psDefinedBy = CPLCreateXMLNode( psCRS_XML, CXT_Element, 
+    CPLXMLNode *psDefinedBy
+        = CPLCreateXMLNode( psCRS_XML, CXT_Element,
                                     "gml:definedByConversion" );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Projections are handled as ParameterizedTransformations.        */
 /* -------------------------------------------------------------------- */
     const char *pszProjection = poSRS->GetAttrValue("PROJECTION");
-    CPLXMLNode *psConv;
-
-    psConv = CPLCreateXMLNode( psDefinedBy, CXT_Element, "gml:Conversion");
+    CPLXMLNode *psConv
+        = CPLCreateXMLNode( psDefinedBy, CXT_Element, "gml:Conversion");
     addGMLId( psConv );
 
     CPLCreateXMLNode(CPLCreateXMLNode(psConv, CXT_Element, "gml:coordinateOperationName"),
                      CXT_Text, pszProjection);
-    
+
 /* -------------------------------------------------------------------- */
 /*      Transverse Mercator                                             */
 /* -------------------------------------------------------------------- */
     if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR) )
     {
-        AddValueIDWithURN( psConv, "gml:usesMethod", "EPSG", "method", 
+        AddValueIDWithURN( psConv, "gml:usesMethod", "EPSG", "method",
                            9807 );
 
         addProjArg( poSRS, psConv, "Angular", 0.0,
@@ -656,7 +644,7 @@ static CPLXMLNode *exportProjCSToXML( const OGRSpatialReference *poSRS )
 /* -------------------------------------------------------------------- */
     else if( EQUAL(pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP) )
     {
-        AddValueIDWithURN( psConv, "gml:usesMethod", "EPSG", "method", 
+        AddValueIDWithURN( psConv, "gml:usesMethod", "EPSG", "method",
                            9801 );
 
         addProjArg( poSRS, psConv, "Angular", 0.0,
@@ -670,7 +658,6 @@ static CPLXMLNode *exportProjCSToXML( const OGRSpatialReference *poSRS )
         addProjArg( poSRS, psConv, "Linear", 0.0,
                     8807, SRS_PP_FALSE_NORTHING );
     }
-    
     else
     {
         CPLError(CE_Warning, CPLE_NotSupported,
@@ -680,10 +667,8 @@ static CPLXMLNode *exportProjCSToXML( const OGRSpatialReference *poSRS )
 /* -------------------------------------------------------------------- */
 /*      Define the cartesian coordinate system.                         */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode  *psCCS;
-
-    psCCS = 
-        CPLCreateXMLNode( 
+    CPLXMLNode  *psCCS
+        = CPLCreateXMLNode(
             CPLCreateXMLNode( psCRS_XML, CXT_Element, "gml:usesCartesianCS" ),
             CXT_Element, "gml:CartesianCS" );
 
@@ -709,12 +694,12 @@ static CPLXMLNode *exportProjCSToXML( const OGRSpatialReference *poSRS )
  * deallocated by the caller with CPLFree() when no longer needed.
  *
  * LOCAL_CS coordinate systems are not translatable.  An empty string
- * will be returned along with OGRERR_NONE.  
+ * will be returned along with OGRERR_NONE.
  *
- * This method is the equivelent of the C function OSRExportToXML().
+ * This method is the equivalent of the C function OSRExportToXML().
  *
- * @param ppszRawXML pointer to which dynamically allocated XML definition 
- * will be assigned. 
+ * @param ppszRawXML pointer to which dynamically allocated XML definition
+ * will be assigned.
  * @param pszDialect currently ignored. The dialect used is GML based.
  *
  * @return OGRERR_NONE on success or an error code on failure.
@@ -745,19 +730,19 @@ OGRErr OGRSpatialReference::exportToXML( char **ppszRawXML,
 /************************************************************************/
 /*                           OSRExportToXML()                           */
 /************************************************************************/
-/** 
+/**
  * \brief Export coordinate system in XML format.
  *
  * This function is the same as OGRSpatialReference::exportToXML().
  */
 
-OGRErr OSRExportToXML( OGRSpatialReferenceH hSRS, char **ppszRawXML, 
+OGRErr OSRExportToXML( OGRSpatialReferenceH hSRS, char **ppszRawXML,
                        const char *pszDialect )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRExportToXML", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRExportToXML", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->exportToXML( ppszRawXML, 
+    return ((OGRSpatialReference *) hSRS)->exportToXML( ppszRawXML,
                                                         pszDialect );
 }
 
@@ -774,9 +759,9 @@ static void importXMLUnits( CPLXMLNode *psSrcXML, const char *pszClass,
     OGR_SRSNode *poNode = poSRS->GetAttrNode( pszTarget );
     OGR_SRSNode *poUnits;
 
-    CPLAssert( EQUAL(pszClass,"AngularUnit") 
+    CPLAssert( EQUAL(pszClass,"AngularUnit")
                || EQUAL(pszClass,"LinearUnit") );
-        
+
     psSrcXML = CPLGetXMLNode( psSrcXML, pszClass );
     if( psSrcXML == NULL )
         goto DefaultTarget;
@@ -786,18 +771,18 @@ static void importXMLUnits( CPLXMLNode *psSrcXML, const char *pszClass,
         pszUnitsPer = CPLGetXMLValue( psSrcXML, "radiansPerUnit", NULL );
     else
         pszUnitsPer = CPLGetXMLValue( psSrcXML, "metresPerUnit", NULL );
-    
+
     if( pszUnitsPer == NULL )
     {
-        CPLDebug( "OGR_SRS_XML", 
-                  "Missing PerUnit value for %s.", 
+        CPLDebug( "OGR_SRS_XML",
+                  "Missing PerUnit value for %s.",
                   pszClass );
         goto DefaultTarget;
     }
-    
+
     if( poNode == NULL )
     {
-        CPLDebug( "OGR_SRS_XML", "Can't find %s in importXMLUnits.", 
+        CPLDebug( "OGR_SRS_XML", "Can't find %s in importXMLUnits.",
                   pszTarget );
         goto DefaultTarget;
     }
@@ -813,7 +798,7 @@ static void importXMLUnits( CPLXMLNode *psSrcXML, const char *pszClass,
         poUnits = new OGR_SRSNode( "UNIT" );
         poUnits->AddChild( new OGR_SRSNode( pszUnitName ) );
         poUnits->AddChild( new OGR_SRSNode( pszUnitsPer ) );
-        
+
         poNode->AddChild( poUnits );
     }
     return;
@@ -839,8 +824,8 @@ static void importXMLUnits( CPLXMLNode *psSrcXML, const char *pszClass,
 /*                         importXMLAuthority()                         */
 /************************************************************************/
 
-static void importXMLAuthority( CPLXMLNode *psSrcXML, 
-                                OGRSpatialReference *poSRS, 
+static void importXMLAuthority( CPLXMLNode *psSrcXML,
+                                OGRSpatialReference *poSRS,
                                 const char *pszSourceKey,
                                 const char *pszTargetKey )
 
@@ -848,14 +833,13 @@ static void importXMLAuthority( CPLXMLNode *psSrcXML,
     CPLXMLNode *psIDNode = CPLGetXMLNode( psSrcXML, pszSourceKey );
     CPLXMLNode *psNameNode = CPLGetXMLNode( psIDNode, "name" );
     CPLXMLNode *psCodeSpace = CPLGetXMLNode( psNameNode, "codeSpace" );
-    const char *pszAuthority, *pszCode;
-    char *pszURN;
-    int nCode = 0;
 
     if( psIDNode == NULL || psNameNode == NULL || psCodeSpace == NULL )
         return;
 
-    pszURN = CPLStrdup(CPLGetXMLValue( psCodeSpace, "", "" ));
+    char *pszURN = CPLStrdup(CPLGetXMLValue( psCodeSpace, "", "" ));
+
+    const char *pszAuthority, *pszCode;
     if( !parseURN( pszURN, NULL, &pszAuthority, &pszCode ) )
     {
         CPLFree( pszURN );
@@ -865,6 +849,7 @@ static void importXMLAuthority( CPLXMLNode *psSrcXML,
     if( strlen(pszCode) == 0 )
         pszCode = (char *) CPLGetXMLValue( psNameNode, "", "" );
 
+    int nCode = 0;
     if( pszCode != NULL )
         nCode = atoi(pszCode);
 
@@ -881,10 +866,10 @@ static void importXMLAuthority( CPLXMLNode *psSrcXML,
 /*        urn:ogc:def:parameter:EPSG:6.3:9707                           */
 /************************************************************************/
 
-static int ParseOGCDefURN( const char *pszURN, 
+static bool ParseOGCDefURN( const char *pszURN,
                            CPLString *poObjectType,
                            CPLString *poAuthority,
-                           CPLString *poVersion, 
+                           CPLString *poVersion,
                            CPLString *poValue )
 
 {
@@ -900,16 +885,16 @@ static int ParseOGCDefURN( const char *pszURN,
     if( poValue != NULL )
         *poValue = "";
 
-    if( pszURN == NULL || !EQUALN(pszURN,"urn:ogc:def:",12) )
-        return FALSE;
+    if( pszURN == NULL || !STARTS_WITH_CI(pszURN, "urn:ogc:def:") )
+        return false;
 
-    char **papszTokens = CSLTokenizeStringComplex( pszURN + 12, ":", 
+    char **papszTokens = CSLTokenizeStringComplex( pszURN + 12, ":",
                                                    FALSE, TRUE );
 
     if( CSLCount(papszTokens) != 4 )
     {
         CSLDestroy( papszTokens );
-        return FALSE;
+        return false;
     }
 
     if( poObjectType != NULL )
@@ -925,7 +910,7 @@ static int ParseOGCDefURN( const char *pszURN,
         *poValue = papszTokens[3];
 
     CSLDestroy( papszTokens );
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -936,26 +921,24 @@ static int ParseOGCDefURN( const char *pszURN,
 /*      something of the form <elem xlink:href="urn:...:">n</a>.        */
 /************************************************************************/
 
-static int getEPSGObjectCodeValue( CPLXMLNode *psNode, 
+static int getEPSGObjectCodeValue( CPLXMLNode *psNode,
                                    const char *pszEPSGObjectType, /*"method" */
                                    int nDefault )
 
 {
     if( psNode == NULL )
         return nDefault;
-    
-    CPLString osObjectType, osAuthority, osValue;
-    const char* pszHrefVal;
-    
-    pszHrefVal = CPLGetXMLValue( psNode, "xlink:href", NULL );
+
+    const char* pszHrefVal = CPLGetXMLValue( psNode, "xlink:href", NULL );
     if (pszHrefVal == NULL)
         pszHrefVal = CPLGetXMLValue( psNode, "href", NULL );
-    
+
+    CPLString osObjectType, osAuthority, osValue;
     if( !ParseOGCDefURN( pszHrefVal,
                          &osObjectType, &osAuthority, NULL, &osValue ) )
         return nDefault;
 
-    if( !EQUAL(osAuthority,"EPSG") 
+    if( !EQUAL(osAuthority,"EPSG")
         || !EQUAL(osObjectType, pszEPSGObjectType) )
         return nDefault;
 
@@ -965,30 +948,30 @@ static int getEPSGObjectCodeValue( CPLXMLNode *psNode,
     const char *pszValue = CPLGetXMLValue( psNode, "", NULL);
     if( pszValue != NULL )
         return atoi(pszValue);
-    else
-        return nDefault;
+
+    return nDefault;
 }
 
 /************************************************************************/
 /*                         getProjectionParm()                          */
 /************************************************************************/
 
-static double getProjectionParm( CPLXMLNode *psRootNode, 
-                                 int nParameterCode, 
-                                 const char * /*pszMeasureType */, 
+static double getProjectionParm( CPLXMLNode *psRootNode,
+                                 int nParameterCode,
+                                 const char * /*pszMeasureType */,
                                  double dfDefault )
 
 {
     CPLXMLNode *psUsesParameter;
 
-    for( psUsesParameter = psRootNode->psChild; 
+    for( psUsesParameter = psRootNode->psChild;
          psUsesParameter != NULL;
          psUsesParameter = psUsesParameter->psNext )
     {
         if( psUsesParameter->eType != CXT_Element )
             continue;
 
-        if( !EQUAL(psUsesParameter->pszValue,"usesParameterValue") 
+        if( !EQUAL(psUsesParameter->pszValue,"usesParameterValue")
             && !EQUAL(psUsesParameter->pszValue,"usesValue") )
             continue;
 
@@ -996,7 +979,7 @@ static double getProjectionParm( CPLXMLNode *psRootNode,
                                                   "valueOfParameter"),
                                     "parameter", 0 ) == nParameterCode )
         {
-            const char *pszValue = CPLGetXMLValue( psUsesParameter, "value", 
+            const char *pszValue = CPLGetXMLValue( psUsesParameter, "value",
                                                    NULL );
 
             if( pszValue != NULL )
@@ -1017,7 +1000,7 @@ static double getProjectionParm( CPLXMLNode *psRootNode,
 /************************************************************************/
 
 static double getNormalizedValue( CPLXMLNode *psNode, const char *pszPath,
-                                  const char * /*pszMeasure*/, 
+                                  const char * /*pszMeasure*/,
                                   double dfDefault )
 
 {
@@ -1028,17 +1011,17 @@ static double getNormalizedValue( CPLXMLNode *psNode, const char *pszPath,
         psTargetNode = psNode;
     else
         psTargetNode = CPLGetXMLNode( psNode, pszPath );
-    
+
     if( psTargetNode == NULL )
         return dfDefault;
 
-    for( psValueNode = psTargetNode->psChild; 
+    for( psValueNode = psTargetNode->psChild;
          psValueNode != NULL && psValueNode->eType != CXT_Text;
          psValueNode = psValueNode->psNext ) {}
 
     if( psValueNode == NULL )
         return dfDefault;
-    
+
     // Add normalization later.
 
     return CPLAtof(psValueNode->pszValue);
@@ -1048,7 +1031,7 @@ static double getNormalizedValue( CPLXMLNode *psNode, const char *pszPath,
 /*                        importGeogCSFromXML()                         */
 /************************************************************************/
 
-static OGRErr importGeogCSFromXML( OGRSpatialReference *poSRS, 
+static OGRErr importGeogCSFromXML( OGRSpatialReference *poSRS,
                                    CPLXMLNode *psCRS )
 
 {
@@ -1058,7 +1041,7 @@ static OGRErr importGeogCSFromXML( OGRSpatialReference *poSRS,
 /* -------------------------------------------------------------------- */
 /*      Set the GEOGCS name from the srsName.                           */
 /* -------------------------------------------------------------------- */
-    pszGeogName = 
+    pszGeogName =
         CPLGetXMLValue( psCRS, "srsName", "Unnamed GeogCS" );
 
 /* -------------------------------------------------------------------- */
@@ -1080,7 +1063,7 @@ static OGRErr importGeogCSFromXML( OGRSpatialReference *poSRS,
             && oIdSRS.GetAuthorityName( "LOCAL_CS" ) != NULL
             && EQUAL(oIdSRS.GetAuthorityName("LOCAL_CS"),"EPSG") )
         {
-            return poSRS->importFromEPSG( 
+            return poSRS->importFromEPSG(
                 atoi(oIdSRS.GetAuthorityCode("LOCAL_CS")) );
         }
     }
@@ -1088,7 +1071,7 @@ static OGRErr importGeogCSFromXML( OGRSpatialReference *poSRS,
 /* -------------------------------------------------------------------- */
 /*      Get datum name.                                                 */
 /* -------------------------------------------------------------------- */
-    pszDatumName = 
+    pszDatumName =
         CPLGetXMLValue( psDatum, "datumName", "Unnamed Datum" );
 
 /* -------------------------------------------------------------------- */
@@ -1097,19 +1080,19 @@ static OGRErr importGeogCSFromXML( OGRSpatialReference *poSRS,
     CPLXMLNode *psE;
 
     psE = CPLGetXMLNode( psDatum, "usesEllipsoid.Ellipsoid" );
-    pszEllipsoidName = 
+    pszEllipsoidName =
         CPLGetXMLValue( psE, "ellipsoidName", "Unnamed Ellipsoid" );
 
-    dfSemiMajor = getNormalizedValue( psE, "semiMajorAxis", "Linear", 
+    dfSemiMajor = getNormalizedValue( psE, "semiMajorAxis", "Linear",
                                       SRS_WGS84_SEMIMAJOR );
 
-    dfInvFlattening = 
-        getNormalizedValue( psE, "secondDefiningParameter.inverseFlattening", 
+    dfInvFlattening =
+        getNormalizedValue( psE, "secondDefiningParameter.inverseFlattening",
                             "Unitless", 0.0 );
 
     if( dfInvFlattening == 0.0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Ellipsoid inverseFlattening corrupt or missing." );
         return OGRERR_CORRUPT_DATA;
     }
@@ -1127,9 +1110,9 @@ static OGRErr importGeogCSFromXML( OGRSpatialReference *poSRS,
     }
     else
     {
-        pszPMName = CPLGetXMLValue( psPM, "meridianName", 
+        pszPMName = CPLGetXMLValue( psPM, "meridianName",
                                     "Unnamed Prime Meridian");
-        dfPMOffset = 
+        dfPMOffset =
             getNormalizedValue( psPM, "greenwichLongitude.angle",
                                 "Angular", 0.0 );
     }
@@ -1137,8 +1120,8 @@ static OGRErr importGeogCSFromXML( OGRSpatialReference *poSRS,
 /* -------------------------------------------------------------------- */
 /*      Set the geographic definition.                                  */
 /* -------------------------------------------------------------------- */
-    poSRS->SetGeogCS( pszGeogName, pszDatumName, 
-                      pszEllipsoidName, dfSemiMajor, dfInvFlattening, 
+    poSRS->SetGeogCS( pszGeogName, pszDatumName,
+                      pszEllipsoidName, dfSemiMajor, dfInvFlattening,
                       pszPMName, dfPMOffset );
 
 /* -------------------------------------------------------------------- */
@@ -1148,7 +1131,7 @@ static OGRErr importGeogCSFromXML( OGRSpatialReference *poSRS,
 #ifdef notdef
     CPLXMLNode *psAxis;
 
-    psAxis = CPLGetXMLNode( psGeo2DCRS, 
+    psAxis = CPLGetXMLNode( psGeo2DCRS,
                             "EllipsoidalCoordinateSystem.CoordinateAxis" );
     importXMLUnits( psAxis, "AngularUnit", poSRS, "GEOGCS" );
 #endif
@@ -1158,14 +1141,14 @@ static OGRErr importGeogCSFromXML( OGRSpatialReference *poSRS,
 /* -------------------------------------------------------------------- */
     importXMLAuthority( psCRS, poSRS, "srsID", "GEOGCS" );
     importXMLAuthority( psDatum, poSRS, "datumID", "GEOGCS|DATUM" );
-    importXMLAuthority( psE, poSRS, "ellipsoidID", 
+    importXMLAuthority( psE, poSRS, "ellipsoidID",
                         "GEOGCS|DATUM|SPHEROID" );
-    importXMLAuthority( psDatum, poSRS, 
+    importXMLAuthority( psDatum, poSRS,
                         "usesPrimeMeridian.PrimeMeridian.meridianID",
                         "GEOGCS|PRIMEM" );
 
     poSRS->Fixup();
-    
+
     return OGRERR_NONE;
 }
 
@@ -1173,7 +1156,7 @@ static OGRErr importGeogCSFromXML( OGRSpatialReference *poSRS,
 /*                        importProjCSFromXML()                         */
 /************************************************************************/
 
-static OGRErr importProjCSFromXML( OGRSpatialReference *poSRS, 
+static OGRErr importProjCSFromXML( OGRSpatialReference *poSRS,
                                    CPLXMLNode *psCRS )
 
 {
@@ -1204,7 +1187,7 @@ static OGRErr importProjCSFromXML( OGRSpatialReference *poSRS,
 /* -------------------------------------------------------------------- */
 /*      Try to set the GEOGCS info.                                     */
 /* -------------------------------------------------------------------- */
-    
+
     psSubXML = CPLGetXMLNode( psCRS, "baseCRS.GeographicCRS" );
     if( psSubXML != NULL )
     {
@@ -1233,16 +1216,16 @@ static OGRErr importProjCSFromXML( OGRSpatialReference *poSRS,
 /* -------------------------------------------------------------------- */
     int nMethod = getEPSGObjectCodeValue( CPLGetXMLNode( psConv, "usesMethod"),
                                           "method", 0 );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Transverse Mercator.                                            */
 /* -------------------------------------------------------------------- */
-    if( nMethod == 9807 ) 
+    if( nMethod == 9807 )
     {
-        poSRS->SetTM( 
-            getProjectionParm( psConv, 8801, "Angular", 0.0 ), 
-            getProjectionParm( psConv, 8802, "Angular", 0.0 ), 
-            getProjectionParm( psConv, 8805, "Unitless", 1.0 ), 
+        poSRS->SetTM(
+            getProjectionParm( psConv, 8801, "Angular", 0.0 ),
+            getProjectionParm( psConv, 8802, "Angular", 0.0 ),
+            getProjectionParm( psConv, 8805, "Unitless", 1.0 ),
             getProjectionParm( psConv, 8806, "Linear", 0.0 ),
             getProjectionParm( psConv, 8807, "Linear", 0.0 ) );
     }
@@ -1253,7 +1236,7 @@ static OGRErr importProjCSFromXML( OGRSpatialReference *poSRS,
     else
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Conversion method %d not recognised.", 
+                  "Conversion method %d not recognised.",
                   nMethod );
         return OGRERR_CORRUPT_DATA;
     }
@@ -1273,7 +1256,7 @@ static OGRErr importProjCSFromXML( OGRSpatialReference *poSRS,
 /*                           importFromXML()                            */
 /************************************************************************/
 
-/** 
+/**
  * \brief Import coordinate system from XML format (GML only currently).
  *
  * This method is the same as the C function OSRImportFromXML()
@@ -1287,12 +1270,12 @@ OGRErr OGRSpatialReference::importFromXML( const char *pszXML )
     OGRErr  eErr = OGRERR_UNSUPPORTED_SRS;
 
     this->Clear();
-        
+
 /* -------------------------------------------------------------------- */
 /*      Parse the XML.                                                  */
 /* -------------------------------------------------------------------- */
     psTree = CPLParseXMLString( pszXML );
-    
+
     if( psTree == NULL )
         return OGRERR_CORRUPT_DATA;
 
@@ -1303,16 +1286,14 @@ OGRErr OGRSpatialReference::importFromXML( const char *pszXML )
 /*      root elements as there is sometimes prefix stuff like           */
 /*      <?xml>.                                                         */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psNode = psTree;
-
-    for( psNode = psTree; psNode != NULL; psNode = psNode->psNext )
+    for( CPLXMLNode* psNode = psTree; psNode != NULL; psNode = psNode->psNext )
     {
         if( EQUAL(psNode->pszValue,"GeographicCRS") )
         {
             eErr = importGeogCSFromXML( this, psNode );
             break;
         }
-        
+
         else if( EQUAL(psNode->pszValue,"ProjectedCRS") )
         {
             eErr = importProjCSFromXML( this, psNode );
@@ -1329,7 +1310,7 @@ OGRErr OGRSpatialReference::importFromXML( const char *pszXML )
 /*                          OSRImportFromXML()                          */
 /************************************************************************/
 
-/** 
+/**
  * \brief Import coordinate system from XML format (GML only currently).
  *
  * This function is the same as OGRSpatialReference::importFromXML().
@@ -1337,8 +1318,8 @@ OGRErr OGRSpatialReference::importFromXML( const char *pszXML )
 OGRErr OSRImportFromXML( OGRSpatialReferenceH hSRS, const char *pszXML )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRImportFromXML", CE_Failure );
-    VALIDATE_POINTER1( pszXML, "OSRImportFromXML", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRImportFromXML", OGRERR_FAILURE );
+    VALIDATE_POINTER1( pszXML, "OSRImportFromXML", OGRERR_FAILURE );
 
     return ((OGRSpatialReference *) hSRS)->importFromXML( pszXML );
 }
diff --git a/ogr/ogr_srsnode.cpp b/ogr/ogr_srsnode.cpp
index efde2f0..be870eb 100644
--- a/ogr/ogr_srsnode.cpp
+++ b/ogr/ogr_srsnode.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_srsnode.cpp 27975 2014-11-17 12:37:48Z rouault $
+ * $Id: ogr_srsnode.cpp 33674 2016-03-07 20:58:21Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGR_SRSNode class.
@@ -28,10 +28,10 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_spatialref.h"
 #include "ogr_p.h"
+#include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: ogr_srsnode.cpp 27975 2014-11-17 12:37:48Z rouault $");
+CPL_CVSID("$Id: ogr_srsnode.cpp 33674 2016-03-07 20:58:21Z goatbar $");
 
 /************************************************************************/
 /*                            OGR_SRSNode()                             */
@@ -45,16 +45,12 @@ CPL_CVSID("$Id: ogr_srsnode.cpp 27975 2014-11-17 12:37:48Z rouault $");
  * with a value of "".  Newly created OGR_SRSNodes have no children.
  */
 
-OGR_SRSNode::OGR_SRSNode( const char * pszValueIn )
-
-{
-    pszValue = CPLStrdup( pszValueIn );
-
-    nChildren = 0;
-    papoChildNodes = NULL;
-
-    poParent = NULL;
-}
+OGR_SRSNode::OGR_SRSNode( const char * pszValueIn ) :
+    pszValue(CPLStrdup(pszValueIn)),
+    papoChildNodes(NULL),
+    poParent(NULL),
+    nChildren(0)
+{}
 
 /************************************************************************/
 /*                            ~OGR_SRSNode()                            */
@@ -95,7 +91,7 @@ void OGR_SRSNode::ClearChildren()
  *
  * Get number of children nodes.
  *
- * @return 0 for leaf nodes, or the number of children nodes. 
+ * @return 0 for leaf nodes, or the number of children nodes.
  */
 
 /************************************************************************/
@@ -109,7 +105,7 @@ void OGR_SRSNode::ClearChildren()
  * GetChildCount() - 1.
  *
  * @return a pointer to the child OGR_SRSNode, or NULL if there is no such
- * child. 
+ * child.
  */
 
 OGR_SRSNode *OGR_SRSNode::GetChild( int iChild )
@@ -117,8 +113,8 @@ OGR_SRSNode *OGR_SRSNode::GetChild( int iChild )
 {
     if( iChild < 0 || iChild >= nChildren )
         return NULL;
-    else
-        return papoChildNodes[iChild];
+
+    return papoChildNodes[iChild];
 }
 
 const OGR_SRSNode *OGR_SRSNode::GetChild( int iChild ) const
@@ -126,8 +122,8 @@ const OGR_SRSNode *OGR_SRSNode::GetChild( int iChild ) const
 {
     if( iChild < 0 || iChild >= nChildren )
         return NULL;
-    else
-        return papoChildNodes[iChild];
+
+    return papoChildNodes[iChild];
 }
 
 /************************************************************************/
@@ -144,7 +140,7 @@ const OGR_SRSNode *OGR_SRSNode::GetChild( int iChild ) const
  *
  * If a node appears more than once in the tree (such as UNIT for instance),
  * the first encountered will be returned.  Use GetNode() on a subtree to be
- * more specific. 
+ * more specific.
  *
  * @param pszName the name of the node to search for.
  *
@@ -154,11 +150,6 @@ const OGR_SRSNode *OGR_SRSNode::GetChild( int iChild ) const
 OGR_SRSNode *OGR_SRSNode::GetNode( const char * pszName )
 
 {
-    int  i;
-
-    if( this == NULL )
-        return NULL;
-    
     if( nChildren > 0 && EQUAL(pszName,pszValue) )
         return this;
 
@@ -166,9 +157,9 @@ OGR_SRSNode *OGR_SRSNode::GetNode( const char * pszName )
 /*      First we check the immediate children so we will get an         */
 /*      immediate child in preference to a subchild.                    */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < nChildren; i++ )
+    for( int i = 0; i < nChildren; i++ )
     {
-        if( EQUAL(papoChildNodes[i]->pszValue,pszName) 
+        if( EQUAL(papoChildNodes[i]->pszValue,pszName)
             && papoChildNodes[i]->nChildren > 0 )
             return papoChildNodes[i];
     }
@@ -176,11 +167,9 @@ OGR_SRSNode *OGR_SRSNode::GetNode( const char * pszName )
 /* -------------------------------------------------------------------- */
 /*      Then get each child to check their children.                    */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < nChildren; i++ )
+    for( int i = 0; i < nChildren; i++ )
     {
-        OGR_SRSNode *poNode;
-
-        poNode = papoChildNodes[i]->GetNode( pszName );
+        OGR_SRSNode *poNode = papoChildNodes[i]->GetNode( pszName );
         if( poNode != NULL )
             return poNode;
     }
@@ -191,7 +180,7 @@ OGR_SRSNode *OGR_SRSNode::GetNode( const char * pszName )
 const OGR_SRSNode *OGR_SRSNode::GetNode( const char * pszName ) const
 
 {
-    return ((OGR_SRSNode *) this)->GetNode( pszName );
+    return const_cast<OGR_SRSNode *>(this)->GetNode( pszName );
 }
 
 /************************************************************************/
@@ -220,15 +209,15 @@ void OGR_SRSNode::AddChild( OGR_SRSNode * poNew )
 
 /**
  * Insert the passed node as a child of target node, at the indicated
- * position. 
+ * position.
  *
  * Note that ownership of the passed node is assumed by the node on which
  * the method is invoked ... use the Clone() method if the original is to
  * be preserved.  All existing children at location iChild and beyond are
- * push down one space to make space for the new child. 
+ * push down one space to make space for the new child.
  *
  * @param poNew the node to add as a child.
- * @param iChild position to insert, use 0 to insert at the beginning. 
+ * @param iChild position to insert, use 0 to insert at the beginning.
  */
 
 void OGR_SRSNode::InsertChild( OGR_SRSNode * poNew, int iChild )
@@ -238,12 +227,12 @@ void OGR_SRSNode::InsertChild( OGR_SRSNode * poNew, int iChild )
         iChild = nChildren;
 
     nChildren++;
-    papoChildNodes = (OGR_SRSNode **)
-        CPLRealloc( papoChildNodes, sizeof(void*) * nChildren );
+    papoChildNodes = static_cast<OGR_SRSNode **>(
+        CPLRealloc( papoChildNodes, sizeof(void*) * nChildren ) );
 
     memmove( papoChildNodes + iChild + 1, papoChildNodes + iChild,
              sizeof(void*) * (nChildren - iChild - 1) );
-    
+
     papoChildNodes[iChild] = poNew;
     poNew->poParent = this;
 }
@@ -287,17 +276,17 @@ void OGR_SRSNode::DestroyChild( int iChild )
  * Note that the node value must match pszValue with the exception of
  * case.  The comparison is case insensitive.
  *
- * @param pszValue the node value being searched for.
+ * @param pszValueIn the node value being searched for.
  *
- * @return the child index, or -1 on failure. 
+ * @return the child index, or -1 on failure.
  */
 
-int OGR_SRSNode::FindChild( const char * pszValue ) const
+int OGR_SRSNode::FindChild( const char * pszValueIn ) const
 
 {
     for( int i = 0; i < nChildren; i++ )
     {
-        if( EQUAL(papoChildNodes[i]->pszValue,pszValue) )
+        if( EQUAL(papoChildNodes[i]->pszValue, pszValueIn) )
             return i;
     }
 
@@ -342,15 +331,13 @@ void OGR_SRSNode::SetValue( const char * pszNewValue )
 /**
  * Make a duplicate of this node, and it's children.
  *
- * @return a new node tree, which becomes the responsiblity of the caller.
+ * @return a new node tree, which becomes the responsibility of the caller.
  */
 
 OGR_SRSNode *OGR_SRSNode::Clone() const
 
 {
-    OGR_SRSNode *poNew;
-
-    poNew = new OGR_SRSNode( pszValue );
+    OGR_SRSNode *poNew = new OGR_SRSNode( pszValue );
 
     for( int i = 0; i < nChildren; i++ )
     {
@@ -375,22 +362,22 @@ int OGR_SRSNode::NeedsQuoting() const
 
     // As per bugzilla bug 201, the OGC spec says the authority code
     // needs to be quoted even though it appears well behaved.
-    if( poParent != NULL && EQUAL(poParent->GetValue(),"AUTHORITY") )
+    if( poParent != NULL && EQUAL(poParent->GetValue(), "AUTHORITY") )
         return TRUE;
-    
+
     // As per bugzilla bug 294, the OGC spec says the direction
     // values for the AXIS keywords should *not* be quoted.
-    if( poParent != NULL && EQUAL(poParent->GetValue(),"AXIS") 
+    if( poParent != NULL && EQUAL(poParent->GetValue(), "AXIS")
         && this != poParent->GetChild(0) )
         return FALSE;
 
     // Strings starting with e or E are not valid numeric values, so they
-    // need quoting, like in AXIS["E",EAST] 
+    // need quoting, like in AXIS["E",EAST]
     if( (pszValue[0] == 'e' || pszValue[0] == 'E') )
         return TRUE;
 
     // Non-numeric tokens are generally quoted while clean numeric values
-    // are generally not. 
+    // are generally not.
     for( int i = 0; pszValue[i] != '\0'; i++ )
     {
         if( (pszValue[i] < '0' || pszValue[i] > '9')
@@ -416,23 +403,21 @@ int OGR_SRSNode::NeedsQuoting() const
  * @param ppszResult the resulting string is returned in this pointer.
  *
  * @return currently OGRERR_NONE is always returned, but the future it
- * is possible error conditions will develop. 
+ * is possible error conditions will develop.
  */
- 
+
 
 OGRErr OGR_SRSNode::exportToWkt( char ** ppszResult ) const
 
 {
-    char        **papszChildrenWkt = NULL;
-    int         nLength = strlen(pszValue)+4;
-    int         i;
-
 /* -------------------------------------------------------------------- */
 /*      Build a list of the WKT format for the children.                */
 /* -------------------------------------------------------------------- */
-    papszChildrenWkt = (char **) CPLCalloc(sizeof(char*),(nChildren+1));
-    
-    for( i = 0; i < nChildren; i++ )
+    char **papszChildrenWkt = static_cast<char **>(
+        CPLCalloc(sizeof(char*),(nChildren+1)) );
+    size_t nLength = strlen(pszValue)+4;
+
+    for( int i = 0; i < nChildren; i++ )
     {
         papoChildNodes[i]->exportToWkt( papszChildrenWkt + i );
         nLength += strlen(papszChildrenWkt[i]) + 1;
@@ -441,9 +426,9 @@ OGRErr OGR_SRSNode::exportToWkt( char ** ppszResult ) const
 /* -------------------------------------------------------------------- */
 /*      Allocate the result string.                                     */
 /* -------------------------------------------------------------------- */
-    *ppszResult = (char *) CPLMalloc(nLength);
+    *ppszResult = static_cast<char *>( CPLMalloc(nLength) );
     *ppszResult[0] = '\0';
-    
+
 /* -------------------------------------------------------------------- */
 /*      Capture this nodes value.  We put it in double quotes if        */
 /*      this is a leaf node, otherwise we assume it is a well formed    */
@@ -463,8 +448,8 @@ OGRErr OGR_SRSNode::exportToWkt( char ** ppszResult ) const
 /* -------------------------------------------------------------------- */
     if( nChildren > 0 )
         strcat( *ppszResult, "[" );
-    
-    for( i = 0; i < nChildren; i++ )
+
+    for( int i = 0; i < nChildren; i++ )
     {
         strcat( *ppszResult, papszChildrenWkt[i] );
         if( i == nChildren-1 )
@@ -485,16 +470,14 @@ OGRErr OGR_SRSNode::exportToWkt( char ** ppszResult ) const
 OGRErr OGR_SRSNode::exportToPrettyWkt( char ** ppszResult, int nDepth ) const
 
 {
-    char        **papszChildrenWkt = NULL;
-    int         nLength = strlen(pszValue)+4;
-    int         i;
-
 /* -------------------------------------------------------------------- */
 /*      Build a list of the WKT format for the children.                */
 /* -------------------------------------------------------------------- */
-    papszChildrenWkt = (char **) CPLCalloc(sizeof(char*),(nChildren+1));
-    
-    for( i = 0; i < nChildren; i++ )
+    char **papszChildrenWkt = static_cast<char **>(
+        CPLCalloc(sizeof(char*),(nChildren+1)) );
+    size_t nLength = strlen(pszValue)+4;
+
+    for( int i = 0; i < nChildren; i++ )
     {
         papoChildNodes[i]->exportToPrettyWkt( papszChildrenWkt + i,
                                               nDepth + 1);
@@ -504,9 +487,9 @@ OGRErr OGR_SRSNode::exportToPrettyWkt( char ** ppszResult, int nDepth ) const
 /* -------------------------------------------------------------------- */
 /*      Allocate the result string.                                     */
 /* -------------------------------------------------------------------- */
-    *ppszResult = (char *) CPLMalloc(nLength);
+    *ppszResult = static_cast<char *>( CPLMalloc(nLength) );
     *ppszResult[0] = '\0';
-    
+
 /* -------------------------------------------------------------------- */
 /*      Capture this nodes value.  We put it in double quotes if        */
 /*      this is a leaf node, otherwise we assume it is a well formed    */
@@ -526,15 +509,13 @@ OGRErr OGR_SRSNode::exportToPrettyWkt( char ** ppszResult, int nDepth ) const
 /* -------------------------------------------------------------------- */
     if( nChildren > 0 )
         strcat( *ppszResult, "[" );
-    
-    for( i = 0; i < nChildren; i++ )
+
+    for( int i = 0; i < nChildren; i++ )
     {
         if( papoChildNodes[i]->GetChildCount() > 0 )
         {
-            int  j;
-
             strcat( *ppszResult, "\n" );
-            for( j = 0; j < 4*nDepth; j++ )
+            for( int j = 0; j < 4*nDepth; j++ )
                 strcat( *ppszResult, " " );
         }
         strcat( *ppszResult, papszChildrenWkt[i] );
@@ -546,7 +527,7 @@ OGRErr OGR_SRSNode::exportToPrettyWkt( char ** ppszResult, int nDepth ) const
     {
         if( (*ppszResult)[strlen(*ppszResult)-1] == ',' )
             (*ppszResult)[strlen(*ppszResult)-1] = '\0';
-        
+
         strcat( *ppszResult, "]" );
     }
 
@@ -586,7 +567,7 @@ OGRErr OGR_SRSNode::importFromWkt( char ** ppszInput, int nRecLevel, int* pnNode
 
 {
     const char  *pszInput = *ppszInput;
-    int         bInQuotedString = FALSE;
+    bool bInQuotedString = false;
 
     /* Sanity checks */
     if( nRecLevel == 10 )
@@ -597,19 +578,21 @@ OGRErr OGR_SRSNode::importFromWkt( char ** ppszInput, int nRecLevel, int* pnNode
     {
         return OGRERR_CORRUPT_DATA;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Clear any existing children of this node.                       */
 /* -------------------------------------------------------------------- */
     ClearChildren();
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read the ``value'' for this node.                               */
 /* -------------------------------------------------------------------- */
     char        szToken[512];
-    int         nTokenLen = 0;
-    
-    while( *pszInput != '\0' && nTokenLen < (int) sizeof(szToken)-1 )
+    szToken[0] = '\0';
+    size_t nTokenLen = 0;
+
+    while( *pszInput != '\0' &&
+           nTokenLen + 1 < sizeof(szToken) )
     {
         if( *pszInput == '"' )
         {
@@ -621,12 +604,12 @@ OGRErr OGR_SRSNode::importFromWkt( char ** ppszInput, int nRecLevel, int* pnNode
         {
             break;
         }
-        else if( !bInQuotedString 
-                 && (*pszInput == ' ' || *pszInput == '\t' 
+        else if( !bInQuotedString
+                 && (*pszInput == ' ' || *pszInput == '\t'
                      || *pszInput == 10 || *pszInput == 13) )
         {
             /* just skip over whitespace */
-        } 
+        }
         else
         {
             szToken[nTokenLen++] = *pszInput;
@@ -648,15 +631,16 @@ OGRErr OGR_SRSNode::importFromWkt( char ** ppszInput, int nRecLevel, int* pnNode
     {
         do
         {
-            OGR_SRSNode *poNewChild;
-            OGRErr      eErr;
 
             pszInput++; // Skip bracket or comma.
 
-            poNewChild = new OGR_SRSNode();
+            OGR_SRSNode *poNewChild = new OGR_SRSNode();
 
             (*pnNodes) ++;
-            eErr = poNewChild->importFromWkt( (char **) &pszInput, nRecLevel + 1, pnNodes );
+            const OGRErr eErr =
+                poNewChild->importFromWkt(
+                    const_cast<char **>( &pszInput ),
+                    nRecLevel + 1, pnNodes );
             if( eErr != OGRERR_NONE )
             {
                 delete poNewChild;
@@ -664,9 +648,9 @@ OGRErr OGR_SRSNode::importFromWkt( char ** ppszInput, int nRecLevel, int* pnNode
             }
 
             AddChild( poNewChild );
-            
+
             // swallow whitespace
-            while( isspace(*pszInput) ) 
+            while( isspace(*pszInput) )
                 pszInput++;
 
         } while( *pszInput == ',' );
@@ -697,8 +681,6 @@ OGRErr OGR_SRSNode::importFromWkt( char ** ppszInput, int nRecLevel, int* pnNode
 void OGR_SRSNode::MakeValueSafe()
 
 {
-    int         i, j;
-
 /* -------------------------------------------------------------------- */
 /*      First process subnodes.                                         */
 /* -------------------------------------------------------------------- */
@@ -712,11 +694,11 @@ void OGR_SRSNode::MakeValueSafe()
 /* -------------------------------------------------------------------- */
     if( (pszValue[0] >= '0' && pszValue[0] <= '9') || pszValue[0] != '.' )
         return;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Translate non-alphanumeric values to underscores.               */
 /* -------------------------------------------------------------------- */
-    for( i = 0; pszValue[i] != '\0'; i++ )
+    for( int i = 0; pszValue[i] != '\0'; i++ )
     {
         if( !(pszValue[i] >= 'A' && pszValue[i] <= 'Z')
             && !(pszValue[i] >= 'a' && pszValue[i] <= 'z')
@@ -729,14 +711,15 @@ void OGR_SRSNode::MakeValueSafe()
 /* -------------------------------------------------------------------- */
 /*      Remove repeated and trailing underscores.                       */
 /* -------------------------------------------------------------------- */
-    for( i = 1, j = 0; pszValue[i] != '\0'; i++ )
+    int j = 0;
+    for( int i = 1; pszValue[i] != '\0'; i++ )
     {
         if( pszValue[j] == '_' && pszValue[i] == '_' )
             continue;
 
         pszValue[++j] = pszValue[i];
     }
-    
+
     if( pszValue[j] == '_' )
         pszValue[j] = '\0';
     else
@@ -756,8 +739,8 @@ void OGR_SRSNode::MakeValueSafe()
  * parent node matches that value.  Even if a replacement occurs, searching
  * continues.
  *
- * @param pszNode Restrict remapping to children of this type of node 
- *                (eg. "PROJECTION")
+ * @param pszNode Restrict remapping to children of this type of node
+ *                (e.g. "PROJECTION")
  * @param papszSrcValues a NULL terminated array of source string.  If the
  * node value matches one of these (case insensitive) then replacement occurs.
  * @param papszDstValues an array of destination strings.  On a match, the
@@ -768,27 +751,25 @@ void OGR_SRSNode::MakeValueSafe()
  * @param bChildOfHit Only TRUE if we the current node is the child of a match,
  * and so needs to be set.  Application code would normally pass FALSE for this
  * argument.
- * 
+ *
  * @return returns OGRERR_NONE unless something bad happens.  There is no
- * indication returned about whether any replacement occured.  
+ * indication returned about whether any replacement occurred.
  */
 
-OGRErr OGR_SRSNode::applyRemapper( const char *pszNode, 
-                                   char **papszSrcValues, 
-                                   char **papszDstValues, 
+OGRErr OGR_SRSNode::applyRemapper( const char *pszNode,
+                                   char **papszSrcValues,
+                                   char **papszDstValues,
                                    int nStepSize, int bChildOfHit )
 
 {
-    int i;
-
 /* -------------------------------------------------------------------- */
 /*      Scan for value, and replace if our parent was a "hit".          */
 /* -------------------------------------------------------------------- */
     if( bChildOfHit || pszNode == NULL )
     {
-        for( i = 0; papszSrcValues[i] != NULL; i += nStepSize )
+        for( int i = 0; papszSrcValues[i] != NULL; i += nStepSize )
         {
-            if( EQUAL(papszSrcValues[i],pszValue) && 
+            if( EQUAL(papszSrcValues[i],pszValue) &&
                 ! EQUAL(papszDstValues[i],"") )
             {
                 SetValue( papszDstValues[i] );
@@ -798,7 +779,7 @@ OGRErr OGR_SRSNode::applyRemapper( const char *pszNode,
     }
 
 /* -------------------------------------------------------------------- */
-/*      Are the the target node?                                        */
+/*      Is this the target node?                                        */
 /* -------------------------------------------------------------------- */
     if( pszNode != NULL )
         bChildOfHit = EQUAL(pszValue,pszNode);
@@ -806,15 +787,15 @@ OGRErr OGR_SRSNode::applyRemapper( const char *pszNode,
 /* -------------------------------------------------------------------- */
 /*      Recurse                                                         */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < GetChildCount(); i++ )
+    for( int i = 0; i < GetChildCount(); i++ )
     {
-        GetChild(i)->applyRemapper( pszNode, papszSrcValues, 
+        GetChild(i)->applyRemapper( pszNode, papszSrcValues,
                                     papszDstValues, nStepSize, bChildOfHit );
     }
 
     return OGRERR_NONE;
 }
-                                   
+
 /************************************************************************/
 /*                             StripNodes()                             */
 /************************************************************************/
@@ -822,7 +803,7 @@ OGRErr OGR_SRSNode::applyRemapper( const char *pszNode,
 /**
  * Strip child nodes matching name.
  *
- * Removes any decendent nodes of this node that match the given name. 
+ * Removes any descendant nodes of this node that match the given name.
  * Of course children of removed nodes are also discarded.
  *
  * @param pszName the name for nodes that should be removed.
@@ -849,24 +830,25 @@ void OGR_SRSNode::StripNodes( const char * pszName )
 /************************************************************************/
 
 /* EXTENSION ... being a OSR extension... is arbitrary placed before the AUTHORITY */
-static const char * const apszPROJCSRule[] = 
-{ "PROJCS", "GEOGCS", "PROJECTION", "PARAMETER", "UNIT", "AXIS", "EXTENSION", "AUTHORITY", 
-  NULL };
+static const char * const apszPROJCSRule[] =
+{ "PROJCS", "GEOGCS", "PROJECTION", "PARAMETER", "UNIT", "AXIS", "EXTENSION",
+  "AUTHORITY", NULL };
 
-static const char * const apszDATUMRule[] = 
+static const char * const apszDATUMRule[] =
 { "DATUM", "SPHEROID", "TOWGS84", "EXTENSION", "AUTHORITY", NULL };
 
-static const char * const apszGEOGCSRule[] = 
+static const char * const apszGEOGCSRule[] =
 { "GEOGCS", "DATUM", "PRIMEM", "UNIT", "AXIS", "EXTENSION", "AUTHORITY", NULL };
 
-static const char * const apszGEOCCSRule[] = 
+static const char * const apszGEOCCSRule[] =
 { "GEOCCS", "DATUM", "PRIMEM", "UNIT", "AXIS", "AUTHORITY", NULL };
 
-static const char * const apszVERTCSRule[] = 
+static const char * const apszVERTCSRule[] =
 { "VERT_CS", "VERT_DATUM", "UNIT", "AXIS", "EXTENSION", "AUTHORITY", NULL };
 
-static const char * const *apszOrderingRules[] = {
-    apszPROJCSRule, apszGEOGCSRule, apszDATUMRule, apszGEOCCSRule, apszVERTCSRule, NULL };
+static const char * const * const apszOrderingRules[] = {
+    apszPROJCSRule, apszGEOGCSRule, apszDATUMRule, apszGEOCCSRule,
+    apszVERTCSRule, NULL };
 
 /**
  * Correct parameter ordering to match CT Specification.
@@ -879,19 +861,17 @@ static const char * const *apszOrderingRules[] = {
  * This method will reorder the children of the node it is invoked on and
  * then recurse to all children to fix up their children.
  *
- * @return OGRERR_NONE on success or an error code if something goes 
- * wrong.  
+ * @return OGRERR_NONE on success or an error code if something goes
+ * wrong.
  */
 
 OGRErr OGR_SRSNode::FixupOrdering()
 
 {
-    int    i;
-
 /* -------------------------------------------------------------------- */
 /*      Recurse ordering children.                                      */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < GetChildCount(); i++ )
+    for( int i = 0; i < GetChildCount(); i++ )
         GetChild(i)->FixupOrdering();
 
     if( GetChildCount() < 3 )
@@ -902,7 +882,7 @@ OGRErr OGR_SRSNode::FixupOrdering()
 /* -------------------------------------------------------------------- */
     const char * const * papszRule = NULL;
 
-    for( i = 0; apszOrderingRules[i] != NULL; i++ )
+    for( int i = 0; apszOrderingRules[i] != NULL; i++ )
     {
         if( EQUAL(apszOrderingRules[i][0],pszValue) )
         {
@@ -919,15 +899,16 @@ OGRErr OGR_SRSNode::FixupOrdering()
 /*      (panChildPr) with the priority code for each child (derived     */
 /*      from the rule) and we then bubble sort based on this.           */
 /* -------------------------------------------------------------------- */
-    int  *panChildKey = (int *) CPLCalloc(sizeof(int),GetChildCount());
+    int  *panChildKey = static_cast<int *>(
+        CPLCalloc(sizeof(int), GetChildCount()));
 
-    for( i = 1; i < GetChildCount(); i++ )
+    for( int i = 1; i < GetChildCount(); i++ )
     {
-        panChildKey[i] = CSLFindString( (char**) papszRule, 
+        panChildKey[i] = CSLFindString( (char**) papszRule,
                                         GetChild(i)->GetValue() );
         if( panChildKey[i] == -1 )
         {
-            CPLDebug( "OGRSpatialReference", 
+            CPLDebug( "OGRSpatialReference",
                       "Found unexpected key %s when trying to order SRS nodes.",
                       GetChild(i)->GetValue() );
         }
@@ -937,12 +918,12 @@ OGRErr OGR_SRSNode::FixupOrdering()
 /*      Sort - Note we don't try to do anything with the first child    */
 /*      which we assume is a name string.                               */
 /* -------------------------------------------------------------------- */
-    int j, bChange = TRUE;
+    bool bChange = true;
 
-    for( i = 1; bChange && i < GetChildCount()-1; i++ )
+    for( int i = 1; bChange && i < GetChildCount()-1; i++ )
     {
-        bChange = FALSE;
-        for( j = 1; j < GetChildCount()-i; j++ )
+        bChange = false;
+        for( int j = 1; j < GetChildCount()-i; j++ )
         {
             if( panChildKey[j] == -1 || panChildKey[j+1] == -1 )
                 continue;
@@ -950,16 +931,14 @@ OGRErr OGR_SRSNode::FixupOrdering()
             if( panChildKey[j] > panChildKey[j+1] )
             {
                 OGR_SRSNode *poTemp = papoChildNodes[j];
-                int          nKeyTemp = panChildKey[j];
-
                 papoChildNodes[j] = papoChildNodes[j+1];
                 papoChildNodes[j+1] = poTemp;
 
-                nKeyTemp = panChildKey[j];
+                int nKeyTemp = panChildKey[j];
                 panChildKey[j] = panChildKey[j+1];
                 panChildKey[j+1] = nKeyTemp;
 
-                bChange = TRUE;
+                bChange = true;
             }
         }
     }
@@ -968,5 +947,3 @@ OGRErr OGR_SRSNode::FixupOrdering()
 
     return OGRERR_NONE;
 }
-
-
diff --git a/ogr/ograpispy.cpp b/ogr/ograpispy.cpp
index b0f3969..5d7be0c 100644
--- a/ogr/ograpispy.cpp
+++ b/ogr/ograpispy.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ograpispy.cpp 28808 2015-03-28 15:01:36Z rouault $
+ * $Id: ograpispy.cpp 33680 2016-03-08 09:59:03Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGR C API "Spy"
@@ -55,7 +55,7 @@ class LayerDescription
         int iLayer;
 
         LayerDescription(): iLayer(-1) {}
-        LayerDescription(int iLayer): iLayer(iLayer) {}
+        LayerDescription(int iLayerIn): iLayer(iLayerIn) {}
 };
 
 class DatasetDescription
@@ -65,7 +65,7 @@ class DatasetDescription
         std::map<OGRLayerH, LayerDescription> oMapLayer;
 
         DatasetDescription() : iDS(-1) {}
-        DatasetDescription(int iDS) : iDS(iDS) {}
+        DatasetDescription(int iDSIn) : iDS(iDSIn) {}
         ~DatasetDescription();
 };
 
@@ -78,7 +78,7 @@ class FeatureDefnDescription
         std::map<OGRGeomFieldDefnH, int> oMapGeomFieldDefn;
 
         FeatureDefnDescription(): hFDefn(NULL), iUniqueNumber(-1) {}
-        FeatureDefnDescription(OGRFeatureDefnH hFDefn, int iUniqueNumber): hFDefn(hFDefn), iUniqueNumber(iUniqueNumber) {}
+        FeatureDefnDescription(OGRFeatureDefnH hFDefnIn, int iUniqueNumberIn): hFDefn(hFDefnIn), iUniqueNumber(iUniqueNumberIn) {}
         void Free();
 };
 
@@ -86,7 +86,7 @@ static std::map<OGRDataSourceH, DatasetDescription> oMapDS;
 static std::map<OGRLayerH, CPLString> oGlobalMapLayer;
 static OGRLayerH hLayerGetNextFeature = NULL;
 static OGRLayerH hLayerGetLayerDefn = NULL;
-static int bDeferGetFieldCount = FALSE;
+static bool bDeferGetFieldCount = false;
 static int nGetNextFeatureCalls = 0;
 static std::set<CPLString> aoSetCreatedDS;
 static std::map<OGRFeatureDefnH, FeatureDefnDescription> oMapFDefn;
@@ -133,7 +133,7 @@ static void OGRAPISpyFileClose()
     }
 }
 
-static int OGRAPISpyEnabled()
+static bool OGRAPISpyEnabled()
 {
     const char* pszSpyFile = CPLGetConfigOption("OGR_API_SPY_FILE", NULL);
     bOGRAPISpyEnabled = (pszSpyFile != NULL);
@@ -141,10 +141,10 @@ static int OGRAPISpyEnabled()
     {
         osSpyFile.resize(0);
         aoSetCreatedDS.clear();
-        return FALSE;
+        return false;
     }
     if( osSpyFile.size() )
-        return TRUE;
+        return true;
 
     osSpyFile = pszSpyFile;
 
@@ -172,7 +172,7 @@ static int OGRAPISpyEnabled()
     fprintf(fpSpyFile, "shutil.copy\n"); // same here
     fprintf(fpSpyFile, "\n");
 
-    return TRUE;
+    return true;
 }
 
 static CPLString OGRAPISpyGetOptions(char** papszOptions)
@@ -290,6 +290,8 @@ static CPLString OGRAPISpyGetGeomType(OGRwkbGeometryType eType)
         casePrefixOgrDot(wkbCurvePolygon)
         casePrefixOgrDot(wkbMultiCurve)
         casePrefixOgrDot(wkbMultiSurface)
+        casePrefixOgrDot(wkbCurve)
+        casePrefixOgrDot(wkbSurface)
         casePrefixOgrDot(wkbNone)
         casePrefixOgrDot(wkbLinearRing)
         casePrefixOgrDot(wkbCircularStringZ)
@@ -297,6 +299,8 @@ static CPLString OGRAPISpyGetGeomType(OGRwkbGeometryType eType)
         casePrefixOgrDot(wkbCurvePolygonZ)
         casePrefixOgrDot(wkbMultiCurveZ)
         casePrefixOgrDot(wkbMultiSurfaceZ)
+        casePrefixOgrDot(wkbCurveZ)
+        casePrefixOgrDot(wkbSurfaceZ)
         casePrefixOgrDot(wkbPoint25D)
         casePrefixOgrDot(wkbLineString25D)
         casePrefixOgrDot(wkbPolygon25D)
@@ -304,6 +308,47 @@ static CPLString OGRAPISpyGetGeomType(OGRwkbGeometryType eType)
         casePrefixOgrDot(wkbMultiLineString25D)
         casePrefixOgrDot(wkbMultiPolygon25D)
         casePrefixOgrDot(wkbGeometryCollection25D)
+        casePrefixOgrDot(wkbPolyhedralSurface)
+        casePrefixOgrDot(wkbTIN)
+        casePrefixOgrDot(wkbTriangle)
+        casePrefixOgrDot(wkbPolyhedralSurfaceZ)
+        casePrefixOgrDot(wkbTINZ)
+        casePrefixOgrDot(wkbTriangleZ)
+        casePrefixOgrDot(wkbPointM)
+        casePrefixOgrDot(wkbLineStringM)
+        casePrefixOgrDot(wkbPolygonM)
+        casePrefixOgrDot(wkbMultiPointM)
+        casePrefixOgrDot(wkbMultiLineStringM)
+        casePrefixOgrDot(wkbMultiPolygonM)
+        casePrefixOgrDot(wkbGeometryCollectionM)
+        casePrefixOgrDot(wkbCircularStringM)
+        casePrefixOgrDot(wkbCompoundCurveM)
+        casePrefixOgrDot(wkbCurvePolygonM)
+        casePrefixOgrDot(wkbMultiCurveM)
+        casePrefixOgrDot(wkbMultiSurfaceM)
+        casePrefixOgrDot(wkbCurveM)
+        casePrefixOgrDot(wkbSurfaceM)
+        casePrefixOgrDot(wkbPolyhedralSurfaceM)
+        casePrefixOgrDot(wkbTINM)
+        casePrefixOgrDot(wkbTriangleM)
+        casePrefixOgrDot(wkbPointZM)
+        casePrefixOgrDot(wkbLineStringZM)
+        casePrefixOgrDot(wkbPolygonZM)
+        casePrefixOgrDot(wkbMultiPointZM)
+        casePrefixOgrDot(wkbMultiLineStringZM)
+        casePrefixOgrDot(wkbMultiPolygonZM)
+        casePrefixOgrDot(wkbGeometryCollectionZM)
+        casePrefixOgrDot(wkbCircularStringZM)
+        casePrefixOgrDot(wkbCompoundCurveZM)
+        casePrefixOgrDot(wkbCurvePolygonZM)
+        casePrefixOgrDot(wkbMultiCurveZM)
+        casePrefixOgrDot(wkbMultiSurfaceZM)
+        casePrefixOgrDot(wkbCurveZM)
+        casePrefixOgrDot(wkbSurfaceZM)
+        casePrefixOgrDot(wkbPolyhedralSurfaceZM)
+        casePrefixOgrDot(wkbTriangleZM)
+        casePrefixOgrDot(wkbTINZM)
+
     }
     return "error";
 }
@@ -359,7 +404,7 @@ static void OGRAPISpyFlushDefered()
         {
             fprintf(fpSpyFile, "%s.GetFieldCount()\n",
                     OGRAPISpyGetFeatureDefnVar(hDefn).c_str());
-            bDeferGetFieldCount = FALSE;
+            bDeferGetFieldCount = false;
         }
 
         hLayerGetLayerDefn = NULL;
@@ -403,7 +448,7 @@ int OGRAPISpyOpenTakeSnapshot(const char* pszName, int bUpdate)
                 CPLString osBaseDir;
                 CPLString osSrcDir;
                 CPLString osWorkingDir;
-                while(TRUE)
+                while( true )
                 {
                     osBaseDir = CPLFormFilename(osSnapshotPath,
                                         CPLSPrintf("snapshot_%d", i), NULL );
@@ -478,7 +523,7 @@ void OGRAPISpyPreClose(OGRDataSourceH hDS)
     OGRAPISpyFileClose();
 }
 
-void OGRAPISpyPostClose(CPL_UNUSED OGRDataSourceH hDS)
+void OGRAPISpyPostClose()
 {
     if( !GDALIsInGlobalDestructor() )
     {
@@ -564,7 +609,7 @@ void OGRAPISpy_DS_GetLayerByName( OGRDataSourceH hDS, const char* pszLayerName,
     OGRAPISpyFileClose();
 }
 
-void OGRAPISpy_DS_ExecuteSQL( OGRDataSourceH hDS, 
+void OGRAPISpy_DS_ExecuteSQL( OGRDataSourceH hDS,
                               const char *pszStatement,
                               OGRGeometryH hSpatialFilter,
                               const char *pszDialect,
@@ -596,7 +641,7 @@ void OGRAPISpy_DS_ReleaseResultSet( OGRDataSourceH hDS, OGRLayerH hLayer)
     OGRAPISpyFileClose();
 }
 
-void OGRAPISpy_DS_CreateLayer( OGRDataSourceH hDS, 
+void OGRAPISpy_DS_CreateLayer( OGRDataSourceH hDS,
                                const char * pszName,
                                OGRSpatialReferenceH hSpatialRef,
                                OGRwkbGeometryType eType,
@@ -741,13 +786,13 @@ static void OGRAPISpyDumpFeature( OGRFeatureH hFeat )
         if( poGeom != NULL )
         {
             fprintf(fpSpyFile, "f.SetGeomField(%d, %s)\n", i, OGRAPISpyGetGeom(
-                (OGRGeometryH)poGeom ).c_str() ); 
+                (OGRGeometryH)poGeom ).c_str() );
         }
     }
     const char* pszStyleString = poFeature->GetStyleString();
     if( pszStyleString != NULL )
         fprintf(fpSpyFile, "f.SetStyleString(%s)\n",
-                OGRAPISpyGetString(pszStyleString).c_str() ); 
+                OGRAPISpyGetString(pszStyleString).c_str() );
 }
 
 void OGRAPISpy_L_SetFeature( OGRLayerH hLayer, OGRFeatureH hFeat )
@@ -786,7 +831,7 @@ static void OGRAPISpyDumpFieldDefn( OGRFieldDefn* poFieldDefn )
                 OGRAPISpyGetString(poFieldDefn->GetDefault()).c_str());
 }
 
-void OGRAPISpy_L_CreateField( OGRLayerH hLayer, OGRFieldDefnH hField, 
+void OGRAPISpy_L_CreateField( OGRLayerH hLayer, OGRFieldDefnH hField,
                               int bApproxOK )
 {
     OGRAPISpyFlushDefered();
@@ -840,7 +885,7 @@ void OGRAPISpy_L_AlterFieldDefn( OGRLayerH hLayer, int iField,
     OGRAPISpyFileClose();
 }
 
-void OGRAPISpy_L_CreateGeomField( OGRLayerH hLayer, OGRGeomFieldDefnH hField, 
+void OGRAPISpy_L_CreateGeomField( OGRLayerH hLayer, OGRGeomFieldDefnH hField,
                                   int bApproxOK )
 {
     OGRAPISpyFlushDefered();
@@ -928,7 +973,7 @@ void OGRAPISpy_L_SetSpatialFilterEx( OGRLayerH hLayer, int iGeomField,
 }
 
 void OGRAPISpy_L_SetSpatialFilterRect( OGRLayerH hLayer,
-                                       double dfMinX, double dfMinY, 
+                                       double dfMinX, double dfMinY,
                                        double dfMaxX, double dfMaxY)
 {
     OGRAPISpyFlushDefered();
@@ -939,7 +984,7 @@ void OGRAPISpy_L_SetSpatialFilterRect( OGRLayerH hLayer,
 }
 
 void OGRAPISpy_L_SetSpatialFilterRectEx( OGRLayerH hLayer, int iGeomField,
-                                         double dfMinX, double dfMinY, 
+                                         double dfMinX, double dfMinY,
                                          double dfMaxX, double dfMaxY)
 {
 
@@ -983,7 +1028,7 @@ void OGRAPISpy_FD_GetFieldCount(OGRFeatureDefnH hDefn)
     if( hLayerGetLayerDefn != NULL &&
         (OGRFeatureDefnH)(((OGRLayer*)hLayerGetLayerDefn)->GetLayerDefn()) == hDefn )
     {
-        bDeferGetFieldCount = TRUE;
+        bDeferGetFieldCount = true;
     }
     else
     {
diff --git a/ogr/ograpispy.h b/ogr/ograpispy.h
index 1b7174d..d2d21e7 100644
--- a/ogr/ograpispy.h
+++ b/ogr/ograpispy.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ograpispy.h 28807 2015-03-28 14:46:31Z rouault $
+ * $Id: ograpispy.h 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGR C API "Spy"
@@ -27,14 +27,14 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGRAPISPY_H_INCLUDED
-#define _OGRAPISPY_H_INCLUDED
+#ifndef OGRAPISPY_H_INCLUDED
+#define OGRAPISPY_H_INCLUDED
 
 #include "gdal.h"
 
 /**
  * \file ograpispy.h
- * 
+ *
  * OGR C API spy.
  *
  * If GDAL is compiled with OGRAPISPY_ENABLED defined (which is the case for a
@@ -76,7 +76,7 @@ int OGRAPISpyOpenTakeSnapshot(const char* pszName, int bUpdate);
 void OGRAPISpyOpen(const char* pszName, int bUpdate, int iSnapshot,
                    GDALDatasetH* phDS);
 void OGRAPISpyPreClose(OGRDataSourceH hDS);
-void OGRAPISpyPostClose(OGRDataSourceH hDS);
+void OGRAPISpyPostClose();
 void OGRAPISpyCreateDataSource(OGRSFDriverH hDriver, const char* pszName,
                                char** papszOptions, OGRDataSourceH hDS);
 void OGRAPISpyDeleteDataSource(OGRSFDriverH hDriver, const char* pszName);
@@ -85,14 +85,14 @@ void OGRAPISpy_DS_GetLayerCount( OGRDataSourceH hDS );
 void OGRAPISpy_DS_GetLayer( OGRDataSourceH hDS, int iLayer, OGRLayerH hLayer );
 void OGRAPISpy_DS_GetLayerByName( OGRDataSourceH hDS, const char* pszLayerName,
                                   OGRLayerH hLayer );
-void OGRAPISpy_DS_ExecuteSQL( OGRDataSourceH hDS, 
+void OGRAPISpy_DS_ExecuteSQL( OGRDataSourceH hDS,
                               const char *pszStatement,
                               OGRGeometryH hSpatialFilter,
                               const char *pszDialect,
                               OGRLayerH hLayer);
 void OGRAPISpy_DS_ReleaseResultSet( OGRDataSourceH hDS, OGRLayerH hLayer);
 
-void OGRAPISpy_DS_CreateLayer( OGRDataSourceH hDS, 
+void OGRAPISpy_DS_CreateLayer( OGRDataSourceH hDS,
                                const char * pszName,
                                OGRSpatialReferenceH hSpatialRef,
                                OGRwkbGeometryType eType,
@@ -113,7 +113,7 @@ void OGRAPISpy_L_SetNextByIndex( OGRLayerH hLayer, GIntBig nIndex );
 void OGRAPISpy_L_GetNextFeature( OGRLayerH hLayer );
 void OGRAPISpy_L_SetFeature( OGRLayerH hLayer, OGRFeatureH hFeat );
 void OGRAPISpy_L_CreateFeature( OGRLayerH hLayer, OGRFeatureH hFeat );
-void OGRAPISpy_L_CreateField( OGRLayerH hLayer, OGRFieldDefnH hField, 
+void OGRAPISpy_L_CreateField( OGRLayerH hLayer, OGRFieldDefnH hField,
                               int bApproxOK );
 void OGRAPISpy_L_DeleteField( OGRLayerH hLayer, int iField );
 void OGRAPISpy_L_ReorderFields( OGRLayerH hLayer, int* panMap );
@@ -122,7 +122,7 @@ void OGRAPISpy_L_ReorderField( OGRLayerH hLayer, int iOldFieldPos,
 void OGRAPISpy_L_AlterFieldDefn( OGRLayerH hLayer, int iField,
                                  OGRFieldDefnH hNewFieldDefn,
                                  int nFlags );
-void OGRAPISpy_L_CreateGeomField( OGRLayerH hLayer, OGRGeomFieldDefnH hField, 
+void OGRAPISpy_L_CreateGeomField( OGRLayerH hLayer, OGRGeomFieldDefnH hField,
                                   int bApproxOK );
 void OGRAPISpy_L_StartTransaction( OGRLayerH hLayer );
 void OGRAPISpy_L_CommitTransaction( OGRLayerH hLayer );
@@ -137,10 +137,10 @@ void OGRAPISpy_L_SetSpatialFilter( OGRLayerH hLayer, OGRGeometryH hGeom );
 void OGRAPISpy_L_SetSpatialFilterEx( OGRLayerH hLayer, int iGeomField,
                                      OGRGeometryH hGeom );
 void OGRAPISpy_L_SetSpatialFilterRect( OGRLayerH hLayer,
-                                       double dfMinX, double dfMinY, 
+                                       double dfMinX, double dfMinY,
                                        double dfMaxX, double dfMaxY);
 void OGRAPISpy_L_SetSpatialFilterRectEx( OGRLayerH hLayer, int iGeomField,
-                                         double dfMinX, double dfMinY, 
+                                         double dfMinX, double dfMinY,
                                          double dfMaxX, double dfMaxY);
 void OGRAPISpy_L_ResetReading( OGRLayerH hLayer );
 void OGRAPISpy_L_SyncToDisk( OGRLayerH hLayer );
@@ -170,4 +170,4 @@ CPL_C_END
 
 #endif /* OGRAPISPY_ENABLED */
 
-#endif /*  _OGRAPISPY_H_INCLUDED */
+#endif /*  OGRAPISPY_H_INCLUDED */
diff --git a/ogr/ograssemblepolygon.cpp b/ogr/ograssemblepolygon.cpp
index f748249..2b91b15 100644
--- a/ogr/ograssemblepolygon.cpp
+++ b/ogr/ograssemblepolygon.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ograssemblepolygon.cpp 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: ograssemblepolygon.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  S-57 Reader
  * Purpose:  Implements polygon assembly from a bunch of arcs.
@@ -33,7 +33,7 @@
 #include "ogr_api.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ograssemblepolygon.cpp 27044 2014-03-16 23:41:27Z rouault $");
+CPL_CVSID("$Id: ograssemblepolygon.cpp 33631 2016-03-04 06:28:09Z goatbar $");
 
 /************************************************************************/
 /*                            CheckPoints()                             */
@@ -42,35 +42,33 @@ CPL_CVSID("$Id: ograssemblepolygon.cpp 27044 2014-03-16 23:41:27Z rouault $");
 /*      distance.  Update the current best distance if they are.        */
 /************************************************************************/
 
-static int CheckPoints( OGRLineString *poLine1, int iPoint1,
+static bool CheckPoints( OGRLineString *poLine1, int iPoint1,
                         OGRLineString *poLine2, int iPoint2,
                         double *pdfDistance )
 
 {
-    double      dfDeltaX, dfDeltaY, dfDistance;
-
     if( pdfDistance == NULL || *pdfDistance == 0 )
         return poLine1->getX(iPoint1) == poLine2->getX(iPoint2)
             && poLine1->getY(iPoint1) == poLine2->getY(iPoint2);
 
-    dfDeltaX = poLine1->getX(iPoint1) - poLine2->getX(iPoint2);
-    dfDeltaY = poLine1->getY(iPoint1) - poLine2->getY(iPoint2);
+    double dfDeltaX = poLine1->getX(iPoint1) - poLine2->getX(iPoint2);
+    double dfDeltaY = poLine1->getY(iPoint1) - poLine2->getY(iPoint2);
 
     dfDeltaX = ABS(dfDeltaX);
     dfDeltaY = ABS(dfDeltaY);
-    
+
     if( dfDeltaX > *pdfDistance || dfDeltaY > *pdfDistance )
-        return FALSE;
-    
-    dfDistance = sqrt(dfDeltaX*dfDeltaX + dfDeltaY*dfDeltaY);
+        return false;
+
+    double dfDistance = sqrt(dfDeltaX*dfDeltaX + dfDeltaY*dfDeltaY);
 
     if( dfDistance < *pdfDistance )
     {
         *pdfDistance = dfDistance;
-        return TRUE;
+        return true;
     }
     else
-        return FALSE;
+        return false;
 }
 
 /************************************************************************/
@@ -103,8 +101,8 @@ static void AddEdgeToRing( OGRLinearRing * poRing, OGRLineString * poLine,
 /* -------------------------------------------------------------------- */
 /*      Should we skip a repeating vertex?                              */
 /* -------------------------------------------------------------------- */
-    if( poRing->getNumPoints() > 0 
-        && CheckPoints( poRing, poRing->getNumPoints()-1, 
+    if( poRing->getNumPoints() > 0
+        && CheckPoints( poRing, poRing->getNumPoints()-1,
                         poLine, iStart, NULL ) )
     {
         iStart += iStep;
@@ -132,9 +130,9 @@ static void AddEdgeToRing( OGRLinearRing * poRing, OGRLineString * poLine,
  */
 
 OGRGeometryH OGRBuildPolygonFromEdges( OGRGeometryH hLines,
-                                       int bBestEffort, 
+                                       int bBestEffort,
                                        int bAutoClose,
-                                       double dfTolerance, 
+                                       double dfTolerance,
                                        OGRErr * peErr )
 
 {
@@ -144,7 +142,7 @@ OGRGeometryH OGRBuildPolygonFromEdges( OGRGeometryH hLines,
             *peErr = OGRERR_NONE;
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Check for the case of a geometrycollection that can be          */
 /*      promoted to MultiLineString.                                    */
@@ -178,7 +176,7 @@ OGRGeometryH OGRBuildPolygonFromEdges( OGRGeometryH hLines,
         return NULL;
     }
 
-    int         bSuccess = TRUE;
+    bool bSuccess = true;
     OGRGeometryCollection *poLines = (OGRGeometryCollection *) hLines;
     std::vector<OGRLinearRing*> aoRings;
 
@@ -200,7 +198,7 @@ OGRGeometryH OGRBuildPolygonFromEdges( OGRGeometryH hLines,
     {
         int             iEdge;
         OGRLineString   *poLine;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Find the first unconsumed edge.                                 */
 /* -------------------------------------------------------------------- */
@@ -220,30 +218,31 @@ OGRGeometryH OGRBuildPolygonFromEdges( OGRGeometryH hLines,
 /*      Start a new ring, copying in the current line directly          */
 /* -------------------------------------------------------------------- */
         OGRLinearRing   *poRing = new OGRLinearRing();
-        
+
         AddEdgeToRing( poRing, poLine, FALSE );
 
 /* ==================================================================== */
 /*      Loop adding edges to this ring until we make a whole pass       */
 /*      within finding anything to add.                                 */
 /* ==================================================================== */
-        int             bWorkDone = TRUE;
+        bool            bWorkDone = true;
         double          dfBestDist = dfTolerance;
 
         while( !CheckPoints(poRing,0,poRing,poRing->getNumPoints()-1,NULL)
                && nRemainingEdges > 0
                && bWorkDone )
         {
-            int         iBestEdge = -1, bReverse = FALSE;
+            int         iBestEdge = -1;
+            int         bReverse = FALSE;
 
-            bWorkDone = FALSE;
+            bWorkDone = false;
             dfBestDist = dfTolerance;
 
             // We consider linking the end to the beginning.  If this is
             // closer than any other option we will just close the loop.
 
             //CheckPoints(poRing,0,poRing,poRing->getNumPoints()-1,&dfBestDist);
-            
+
             // Find unused edge with end point closest to our loose end.
             for( iEdge = 0; iEdge < nEdges; iEdge++ )
             {
@@ -275,14 +274,14 @@ OGRGeometryH OGRBuildPolygonFromEdges( OGRGeometryH hLines,
             // We found one within tolerance - add it.
             if( iBestEdge != -1 )
             {
-                poLine = (OGRLineString *) 
+                poLine = (OGRLineString *)
                     poLines->getGeometryRef(iBestEdge);
-                
+
                 AddEdgeToRing( poRing, poLine, bReverse );
-                    
+
                 panEdgeConsumed[iBestEdge] = TRUE;
                 nRemainingEdges--;
-                bWorkDone = TRUE;
+                bWorkDone = true;
             }
         }
 
@@ -294,15 +293,15 @@ OGRGeometryH OGRBuildPolygonFromEdges( OGRGeometryH hLines,
         if( !CheckPoints(poRing,0,poRing,poRing->getNumPoints()-1,
                          &dfBestDist) )
         {
-            CPLDebug( "OGR", 
+            CPLDebug( "OGR",
                       "Failed to close ring %d.\n"
                       "End Points are: (%.8f,%.7f) and (%.7f,%.7f)\n",
                       (int)aoRings.size(),
-                      poRing->getX(0), poRing->getY(0), 
-                      poRing->getX(poRing->getNumPoints()-1), 
+                      poRing->getX(0), poRing->getY(0),
+                      poRing->getX(poRing->getNumPoints()-1),
                       poRing->getY(poRing->getNumPoints()-1) );
 
-            bSuccess = FALSE;
+            bSuccess = false;
         }
 
 /* -------------------------------------------------------------------- */
@@ -311,8 +310,8 @@ OGRGeometryH OGRBuildPolygonFromEdges( OGRGeometryH hLines,
         if( bAutoClose
             && !CheckPoints(poRing,0,poRing,poRing->getNumPoints()-1,NULL) )
         {
-            poRing->addPoint( poRing->getX(0), 
-                              poRing->getY(0), 
+            poRing->addPoint( poRing->getX(0),
+                              poRing->getY(0),
                               poRing->getZ(0));
         }
 
@@ -361,9 +360,6 @@ OGRGeometryH OGRBuildPolygonFromEdges( OGRGeometryH hLines,
         else
             *peErr = OGRERR_FAILURE;
     }
-    
+
     return (OGRGeometryH) poPolygon;
 }
-
-
-
diff --git a/ogr/ogrcircularstring.cpp b/ogr/ogrcircularstring.cpp
index 5221d57..5276986 100644
--- a/ogr/ogrcircularstring.cpp
+++ b/ogr/ogrcircularstring.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrcircularstring.cpp 28005 2014-11-26 10:04:43Z rouault $
+ * $Id: ogrcircularstring.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRCircularString geometry class.
@@ -48,6 +48,24 @@ OGRCircularString::OGRCircularString()
 }
 
 /************************************************************************/
+/*              OGRCircularString( const OGRCircularString& )           */
+/************************************************************************/
+
+/**
+ * \brief Copy constructor.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the constructor
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRCircularString::OGRCircularString( const OGRCircularString& other ) :
+    OGRSimpleCurve( other )
+{
+}
+
+/************************************************************************/
 /*                        ~OGRCircularString()                          */
 /************************************************************************/
 
@@ -57,13 +75,39 @@ OGRCircularString::~OGRCircularString()
 }
 
 /************************************************************************/
+/*                  operator=( const OGRCircularString& )               */
+/************************************************************************/
+
+/**
+ * \brief Assignment operator.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the operator
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRCircularString& OGRCircularString::operator=( const OGRCircularString& other )
+{
+    if( this != &other)
+    {
+        OGRSimpleCurve::operator=( other );
+    }
+    return *this;
+}
+
+/************************************************************************/
 /*                          getGeometryType()                           */
 /************************************************************************/
 
 OGRwkbGeometryType OGRCircularString::getGeometryType() const
 
 {
-    if( getCoordinateDimension() == 3 )
+    if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
+        return wkbCircularStringZM;
+    else if( flags & OGR_G_MEASURED  )
+        return wkbCircularStringM;
+    else if( flags & OGR_G_3D )
         return wkbCircularStringZ;
     else
         return wkbCircularString;
@@ -165,7 +209,7 @@ OGRErr OGRCircularString::exportToWkt( char ** ppszDstText,
 /************************************************************************/
 /*                             get_Length()                             */
 /*                                                                      */
-/*      For now we return a simple euclidian 2D distance.               */
+/*      For now we return a simple euclidean 2D distance.               */
 /************************************************************************/
 
 double OGRCircularString::get_Length() const
@@ -425,7 +469,7 @@ void OGRCircularString::Value( double dfDistance, OGRPoint * poPoint ) const
         StartPoint( poPoint );
         return;
     }
-    
+
     for(i=0;i<nPointCount-2;i+=2)
     {
         double x0 = paoPoints[i].x, y0 = paoPoints[i].y,
@@ -443,13 +487,13 @@ void OGRCircularString::Value( double dfDistance, OGRPoint * poPoint ) const
             double dfSegLength = fabs(alpha2 - alpha0) * R;
             if (dfSegLength > 0)
             {
-                if( (dfLength <= dfDistance) && ((dfLength + dfSegLength) >= 
+                if( (dfLength <= dfDistance) && ((dfLength + dfSegLength) >=
                                                 dfDistance) )
                 {
                     double      dfRatio;
 
                     dfRatio = (dfDistance - dfLength) / dfSegLength;
-                    
+
                     double alpha = alpha0 * (1 - dfRatio) + alpha2 * dfRatio;
                     double x = cx + R * cos(alpha), y = cy + R * sin(alpha);
 
@@ -459,7 +503,7 @@ void OGRCircularString::Value( double dfDistance, OGRPoint * poPoint ) const
                     if( getCoordinateDimension() == 3 )
                         poPoint->setZ( padfZ[i] * (1 - dfRatio)
                                     + padfZ[i+2] * dfRatio );
-                    
+
                     return;
                 }
 
@@ -472,7 +516,7 @@ void OGRCircularString::Value( double dfDistance, OGRPoint * poPoint ) const
             double dfSegLength = sqrt((x2-x0)*(x2-x0)+(y2-y0)*(y2-y0));
             if (dfSegLength > 0)
             {
-                if( (dfLength <= dfDistance) && ((dfLength + dfSegLength) >= 
+                if( (dfLength <= dfDistance) && ((dfLength + dfSegLength) >=
                                                 dfDistance) )
                 {
                     double      dfRatio;
@@ -487,7 +531,7 @@ void OGRCircularString::Value( double dfDistance, OGRPoint * poPoint ) const
                     if( getCoordinateDimension() == 3 )
                         poPoint->setZ( padfZ[i] * (1 - dfRatio)
                                     + padfZ[i+2] * dfRatio );
-                    
+
                     return;
                 }
 
diff --git a/ogr/ogrcompoundcurve.cpp b/ogr/ogrcompoundcurve.cpp
index dad2a82..a1eb484 100644
--- a/ogr/ogrcompoundcurve.cpp
+++ b/ogr/ogrcompoundcurve.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrcompoundcurve.cpp 27960 2014-11-14 18:31:32Z rouault $
+ * $Id: ogrcompoundcurve.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRCompoundCurve geometry class.
@@ -47,6 +47,25 @@ OGRCompoundCurve::OGRCompoundCurve()
 }
 
 /************************************************************************/
+/*             OGRCompoundCurve( const OGRCompoundCurve& )              */
+/************************************************************************/
+
+/**
+ * \brief Copy constructor.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the constructor
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRCompoundCurve::OGRCompoundCurve( const OGRCompoundCurve& other ) :
+    OGRCurve(other),
+    oCC(other.oCC)
+{
+}
+
+/************************************************************************/
 /*                         ~OGRCompoundCurve()                          */
 /************************************************************************/
 
@@ -56,13 +75,41 @@ OGRCompoundCurve::~OGRCompoundCurve()
 }
 
 /************************************************************************/
+/*                 operator=( const OGRCompoundCurve&)                  */
+/************************************************************************/
+
+/**
+ * \brief Assignment operator.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the operator
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRCompoundCurve& OGRCompoundCurve::operator=( const OGRCompoundCurve& other )
+{
+    if( this != &other)
+    {
+        OGRCurve::operator=( other );
+
+        oCC = other.oCC;
+    }
+    return *this;
+}
+
+/************************************************************************/
 /*                          getGeometryType()                           */
 /************************************************************************/
 
 OGRwkbGeometryType OGRCompoundCurve::getGeometryType() const
 
 {
-    if( getCoordinateDimension() == 3 )
+    if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
+        return wkbCompoundCurveZM;
+    else if( flags & OGR_G_MEASURED  )
+        return wkbCompoundCurveM;
+    else if( flags & OGR_G_3D )
         return wkbCompoundCurveZ;
     else
         return wkbCompoundCurve;
@@ -107,9 +154,10 @@ OGRErr OGRCompoundCurve::importFromWkb( unsigned char * pabyData,
 {
     OGRwkbByteOrder eByteOrder;
     int nDataOffset = 0;
+    /* coverity[tainted_data] */
     OGRErr eErr = oCC.importPreambuleFromWkb(this, pabyData, nSize, nDataOffset,
                                              eByteOrder, 9, eWkbVariant);
-    if( eErr >= 0 )
+    if( eErr != OGRERR_NONE )
         return eErr;
 
     return oCC.importBodyFromWkb(this, pabyData, nSize, nDataOffset,
@@ -172,6 +220,7 @@ OGRGeometry *OGRCompoundCurve::clone() const
 
     poNewCC = new OGRCompoundCurve;
     poNewCC->assignSpatialReference( getSpatialReference() );
+    poNewCC->flags = flags;
 
     for( int i = 0; i < oCC.nCurveCount; i++ )
     {
@@ -220,7 +269,7 @@ OGRBoolean OGRCompoundCurve::IsEmpty() const
 /************************************************************************/
 /*                             get_Length()                             */
 /*                                                                      */
-/*      For now we return a simple euclidian 2D distance.               */
+/*      For now we return a simple euclidean 2D distance.               */
 /************************************************************************/
 
 double OGRCompoundCurve::get_Length() const
@@ -270,7 +319,7 @@ void OGRCompoundCurve::Value( double dfDistance, OGRPoint *poPoint ) const
         double dfSegLength = oCC.papoCurves[iGeom]->get_Length();
         if (dfSegLength > 0)
         {
-            if( (dfLength <= dfDistance) && ((dfLength + dfSegLength) >= 
+            if( (dfLength <= dfDistance) && ((dfLength + dfSegLength) >=
                                              dfDistance) )
             {
                 oCC.papoCurves[iGeom]->Value(dfDistance - dfLength, poPoint);
@@ -281,7 +330,7 @@ void OGRCompoundCurve::Value( double dfDistance, OGRPoint *poPoint ) const
             dfLength += dfSegLength;
         }
     }
-    
+
     EndPoint( poPoint );
 }
 
@@ -325,14 +374,13 @@ OGRLineString* OGRCompoundCurve::CurveToLine(double dfMaxAngleStepSizeDegrees,
 
 OGRBoolean  OGRCompoundCurve::Equals( OGRGeometry *poOther ) const
 {
-    OGRCompoundCurve *poOCC = (OGRCompoundCurve *) poOther;
-
-    if( poOCC == this )
+    if( poOther == this )
         return TRUE;
-    
+
     if( poOther->getGeometryType() != getGeometryType() )
         return FALSE;
-    
+
+    OGRCompoundCurve *poOCC = (OGRCompoundCurve *) poOther;
     return oCC.Equals(&(poOCC->oCC));
 }
 
@@ -345,6 +393,16 @@ void OGRCompoundCurve::setCoordinateDimension( int nNewDimension )
     oCC.setCoordinateDimension( this, nNewDimension );
 }
 
+void OGRCompoundCurve::set3D( OGRBoolean bIs3D )
+{
+    oCC.set3D(this, bIs3D);
+}
+
+void OGRCompoundCurve::setMeasured( OGRBoolean bIsMeasured )
+{
+    oCC.setMeasured(this, bIsMeasured);
+}
+
 /************************************************************************/
 /*                          getNumCurves()                              */
 /************************************************************************/
@@ -384,9 +442,9 @@ int          OGRCompoundCurve::getNumCurves() const
  * @return pointer to curve.  May be NULL.
  */
 
-OGRCurve    *OGRCompoundCurve::getCurve( int i )
+OGRCurve    *OGRCompoundCurve::getCurve( int iRing )
 {
-    return oCC.getCurve(i);
+    return oCC.getCurve(iRing);
 }
 
 /************************************************************************/
@@ -409,9 +467,9 @@ OGRCurve    *OGRCompoundCurve::getCurve( int i )
  * @return pointer to curve.  May be NULL.
  */
 
-const OGRCurve *OGRCompoundCurve::getCurve( int i ) const
+const OGRCurve *OGRCompoundCurve::getCurve( int iRing ) const
 {
-    return oCC.getCurve(i);
+    return oCC.getCurve(iRing);
 }
 
 /************************************************************************/
@@ -616,8 +674,8 @@ class OGRCompoundCurvePointIterator: public OGRPointIterator
         OGRPointIterator       *poCurveIter;
 
     public:
-        OGRCompoundCurvePointIterator(const OGRCompoundCurve* poCC) :
-                            poCC(poCC), iCurCurve(0), poCurveIter(NULL) {}
+        OGRCompoundCurvePointIterator(const OGRCompoundCurve* poCCIn) :
+                            poCC(poCCIn), iCurCurve(0), poCurveIter(NULL) {}
        ~OGRCompoundCurvePointIterator() { delete poCurveIter; }
 
         virtual OGRBoolean getNextPoint(OGRPoint* p);
@@ -695,7 +753,7 @@ OGRLineString* OGRCompoundCurve::CastToLineString(OGRCompoundCurve* poCC)
  *
  * The passed in geometry is consumed and a new one returned (or NULL in case
  * of failure)
- * 
+ *
  * @param poCC the input geometry - ownership is passed to the method.
  * @return new geometry.
  */
diff --git a/ogr/ogrct.cpp b/ogr/ogrct.cpp
index 905aaca..aa5e1c9 100644
--- a/ogr/ogrct.cpp
+++ b/ogr/ogrct.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrct.cpp 28459 2015-02-12 13:48:21Z rouault $
+ * $Id: ogrct.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRSCoordinateTransformation class.
@@ -39,7 +39,7 @@
 #include "proj_api.h"
 #endif
 
-CPL_CVSID("$Id: ogrct.cpp 28459 2015-02-12 13:48:21Z rouault $");
+CPL_CVSID("$Id: ogrct.cpp 33631 2016-03-04 06:28:09Z goatbar $");
 
 /* ==================================================================== */
 /*      PROJ.4 interface stuff.                                         */
@@ -65,7 +65,7 @@ static CPLMutex *hPROJMutex = NULL;
 static projPJ       (*pfn_pj_init_plus)(const char *) = NULL;
 static projPJ       (*pfn_pj_init)(int, char**) = NULL;
 static void     (*pfn_pj_free)(projPJ) = NULL;
-static int      (*pfn_pj_transform)(projPJ, projPJ, long, int, 
+static int      (*pfn_pj_transform)(projPJ, projPJ, long, int,
                                     double *, double *, double * ) = NULL;
 static int         *(*pfn_pj_get_errno_ref)(void) = NULL;
 static char        *(*pfn_pj_strerrno)(int) = NULL;
@@ -77,7 +77,14 @@ static int (*pfn_pj_ctx_get_errno)( projCtx ) = NULL;
 static projCtx (*pfn_pj_ctx_alloc)(void) = NULL;
 static void    (*pfn_pj_ctx_free)( projCtx ) = NULL;
 
-#if (defined(WIN32) || defined(WIN32CE)) && !defined(__MINGW32__)
+// Locale-safe proj starts with 4.10
+#if defined(PJ_LOCALE_SAFE)
+static bool      bProjLocaleSafe = PJ_LOCALE_SAFE;
+#else
+static bool      bProjLocaleSafe = false;
+#endif
+
+#if defined(WIN32) && !defined(__MINGW32__)
 #  define LIBNAME      "proj.dll"
 #elif defined(__MINGW32__)
 // XXX: If PROJ.4 library was properly built using libtool in Cygwin or MinGW
@@ -85,7 +92,7 @@ static void    (*pfn_pj_ctx_free)( projCtx ) = NULL;
 // (it is CURRENT-AGE number). If DLL came somewhere else (e.g. from MSVC
 // build) it can be named either way, so use PROJSO environment variable to
 // specify the right library name. By default assume that in Cygwin/MinGW all
-// components were buit in the same way.
+// components were built in the same way.
 #  define LIBNAME      "libproj-0.dll"
 #elif defined(__CYGWIN__)
 #  define LIBNAME      "cygproj-0.dll"
@@ -120,7 +127,6 @@ class OGRProj4CT : public OGRCoordinateTransformation
     double      dfSourceToRadians;
     int         bSourceWrap;
     double      dfSourceWrapLong;
-    
 
     OGRSpatialReference *poSRSTarget;
     void        *psPJTarget;
@@ -130,15 +136,17 @@ class OGRProj4CT : public OGRCoordinateTransformation
     double      dfTargetWrapLong;
 
     int         bIdentityTransform;
+    //int         bWGS84ToWebMercator;
+    int         bWebMercatorToWGS84;
 
     int         nErrorCount;
-    
+
     int         bCheckWithInvertProj;
     double      dfThreshold;
-    
+
     projCtx     pjctx;
 
-    int         InitializeNoLock( OGRSpatialReference *poSource, 
+    int         InitializeNoLock( OGRSpatialReference *poSource,
                                   OGRSpatialReference *poTarget );
 
     int         nMaxCount;
@@ -153,17 +161,16 @@ public:
                 OGRProj4CT();
     virtual     ~OGRProj4CT();
 
-    int         Initialize( OGRSpatialReference *poSource, 
+    int         Initialize( OGRSpatialReference *poSource,
                             OGRSpatialReference *poTarget );
 
     virtual OGRSpatialReference *GetSourceCS();
     virtual OGRSpatialReference *GetTargetCS();
-    virtual int Transform( int nCount, 
+    virtual int Transform( int nCount,
                            double *x, double *y, double *z = NULL );
-    virtual int TransformEx( int nCount, 
+    virtual int TransformEx( int nCount,
                              double *x, double *y, double *z = NULL,
                              int *panSuccess = NULL );
-
 };
 
 /************************************************************************/
@@ -173,10 +180,8 @@ public:
 static const char* GetProjLibraryName()
 {
     const char *pszLibName = LIBNAME;
-#if !defined(WIN32CE)
     if( CPLGetConfigOption("PROJSO",NULL) != NULL )
         pszLibName = CPLGetConfigOption("PROJSO",NULL);
-#endif
     return pszLibName;
 }
 
@@ -184,16 +189,16 @@ static const char* GetProjLibraryName()
 /*                          LoadProjLibrary()                           */
 /************************************************************************/
 
-static int LoadProjLibrary_unlocked()
+static bool LoadProjLibrary_unlocked()
 
 {
-    static int  bTriedToLoad = FALSE;
+    static bool bTriedToLoad = false;
     const char *pszLibName;
-    
+
     if( bTriedToLoad )
         return( pfn_pj_transform != NULL );
 
-    bTriedToLoad = TRUE;
+    bTriedToLoad = true;
 
     pszLibName = GetProjLibraryName();
 
@@ -217,16 +222,17 @@ static int LoadProjLibrary_unlocked()
 #else
     CPLPushErrorHandler( CPLQuietErrorHandler );
 
+    /* coverity[tainted_string] */
     pfn_pj_init = (projPJ (*)(int, char**)) CPLGetSymbol( pszLibName,
                                                        "pj_init" );
     CPLPopErrorHandler();
-    
+
     if( pfn_pj_init == NULL )
-       return( FALSE );
+       return false;
 
-    pfn_pj_init_plus = (projPJ (*)(const char *)) 
+    pfn_pj_init_plus = (projPJ (*)(const char *))
         CPLGetSymbol( pszLibName, "pj_init_plus" );
-    pfn_pj_free = (void (*)(projPJ)) 
+    pfn_pj_free = (void (*)(projPJ))
         CPLGetSymbol( pszLibName, "pj_free" );
     pfn_pj_transform = (int (*)(projPJ,projPJ,long,int,double*,
                                 double*,double*))
@@ -252,6 +258,8 @@ static int LoadProjLibrary_unlocked()
     pfn_pj_ctx_get_errno = (int (*)( projCtx ))
         CPLGetSymbol( pszLibName, "pj_ctx_get_errno" );
 
+    bProjLocaleSafe = CPLGetSymbol(pszLibName, "pj_atof") != NULL;
+
     CPLPopErrorHandler();
     CPLErrorReset();
 #endif
@@ -272,20 +280,23 @@ static int LoadProjLibrary_unlocked()
         pfn_pj_ctx_get_errno = NULL;
     }
 
+    if( bProjLocaleSafe )
+        CPLDebug("OGRCT", "Using locale-safe proj version");
+
     if( pfn_pj_transform == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Attempt to load %s, but couldn't find pj_transform.\n"
-                  "Please upgrade to PROJ 4.1.2 or later.", 
+                  "Please upgrade to PROJ 4.1.2 or later.",
                   pszLibName );
 
-        return FALSE;
+        return false;
     }
 
-    return( TRUE );
+    return true;
 }
 
-static int LoadProjLibrary()
+static bool LoadProjLibrary()
 
 {
     CPLMutexHolderD( &hPROJMutex );
@@ -301,19 +312,11 @@ static int LoadProjLibrary()
 /*      forth as possible.                                              */
 /************************************************************************/
 
-char *OCTProj4Normalize( const char *pszProj4Src )
-
+static char *OCTProj4NormalizeInternal( const char *pszProj4Src )
 {
     char        *pszNewProj4Def, *pszCopy;
     projPJ      psPJSource = NULL;
 
-    CPLMutexHolderD( &hPROJMutex );
-
-    if( !LoadProjLibrary_unlocked() || pfn_pj_dalloc == NULL || pfn_pj_get_def == NULL )
-        return CPLStrdup( pszProj4Src );
-
-    CPLLocaleC  oLocaleEnforcer;
-
     psPJSource = pfn_pj_init_plus( pszProj4Src );
 
     if( psPJSource == NULL )
@@ -332,18 +335,36 @@ char *OCTProj4Normalize( const char *pszProj4Src )
     return pszCopy;
 }
 
+char *OCTProj4Normalize( const char *pszProj4Src )
+
+{
+    CPLMutexHolderD( &hPROJMutex );
+
+    if( !LoadProjLibrary_unlocked() || pfn_pj_dalloc == NULL || pfn_pj_get_def == NULL )
+        return CPLStrdup( pszProj4Src );
+
+    if( bProjLocaleSafe )
+        return OCTProj4NormalizeInternal(pszProj4Src);
+    else
+    {
+        CPLLocaleC  oLocaleEnforcer;
+        return OCTProj4NormalizeInternal(pszProj4Src);
+    }
+
+}
+
 /************************************************************************/
 /*                 OCTDestroyCoordinateTransformation()                 */
 /************************************************************************/
 
 /**
- * \brief OGRCoordinateTransformation destructor. 
+ * \brief OGRCoordinateTransformation destructor.
  *
  * This function is the same as OGRCoordinateTransformation::DestroyCT()
  *
  * @param hCT the object to delete
  */
- 
+
 void CPL_STDCALL
 OCTDestroyCoordinateTransformation( OGRCoordinateTransformationH hCT )
 
@@ -356,7 +377,7 @@ OCTDestroyCoordinateTransformation( OGRCoordinateTransformationH hCT )
 /************************************************************************/
 
 /**
- * \brief OGRCoordinateTransformation destructor. 
+ * \brief OGRCoordinateTransformation destructor.
  *
  * This function is the same as OGRCoordinateTransformation::~OGRCoordinateTransformation()
  * and OCTDestroyCoordinateTransformation()
@@ -364,13 +385,13 @@ OCTDestroyCoordinateTransformation( OGRCoordinateTransformationH hCT )
  * This static method will destroy a OGRCoordinateTransformation.  It is
  * equivalent to calling delete on the object, but it ensures that the
  * deallocation is properly executed within the OGR libraries heap on
- * platforms where this can matter (win32).  
+ * platforms where this can matter (win32).
  *
  * @param poCT the object to delete
  *
  * @since GDAL 1.7.0
  */
- 
+
 void OGRCoordinateTransformation::DestroyCT(OGRCoordinateTransformation* poCT)
 {
     delete poCT;
@@ -385,21 +406,21 @@ void OGRCoordinateTransformation::DestroyCT(OGRCoordinateTransformation* poCT)
  *
  * This is the same as the C function OCTNewCoordinateTransformation().
  *
- * Input spatial reference system objects are assigned 
+ * Input spatial reference system objects are assigned
  * by copy (calling clone() method) and no ownership transfer occurs.
  *
  * The delete operator, or OCTDestroyCoordinateTransformation() should
- * be used to destroy transformation objects. 
+ * be used to destroy transformation objects.
  *
  * The PROJ.4 library must be available at run-time.
  *
- * @param poSource source spatial reference system. 
- * @param poTarget target spatial reference system. 
+ * @param poSource source spatial reference system.
+ * @param poTarget target spatial reference system.
  * @return NULL on failure or a ready to use transformation object.
  */
 
-OGRCoordinateTransformation*  
-OGRCreateCoordinateTransformation( OGRSpatialReference *poSource, 
+OGRCoordinateTransformation*
+OGRCreateCoordinateTransformation( OGRSpatialReference *poSource,
                                    OGRSpatialReference *poTarget )
 
 {
@@ -407,7 +428,7 @@ OGRCreateCoordinateTransformation( OGRSpatialReference *poSource,
 
     if( pfn_pj_init == NULL && !LoadProjLibrary() )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "Unable to load PROJ.4 library (%s), creation of\n"
                   "OGRCoordinateTransformation failed.",
                   GetProjLibraryName() );
@@ -415,7 +436,7 @@ OGRCreateCoordinateTransformation( OGRSpatialReference *poSource,
     }
 
     poCT = new OGRProj4CT();
-    
+
     if( !poCT->Initialize( poSource, poTarget ) )
     {
         delete poCT;
@@ -436,26 +457,26 @@ OGRCreateCoordinateTransformation( OGRSpatialReference *poSource,
  *
  * This is the same as the C++ function OGRCreateCoordinateTransformation().
  *
- * Input spatial reference system objects are assigned 
+ * Input spatial reference system objects are assigned
  * by copy (calling clone() method) and no ownership transfer occurs.
  *
  * OCTDestroyCoordinateTransformation() should
- * be used to destroy transformation objects. 
+ * be used to destroy transformation objects.
  *
  * The PROJ.4 library must be available at run-time.
  *
- * @param hSourceSRS source spatial reference system. 
- * @param hTargetSRS target spatial reference system. 
+ * @param hSourceSRS source spatial reference system.
+ * @param hTargetSRS target spatial reference system.
  * @return NULL on failure or a ready to use transformation object.
  */
- 
-OGRCoordinateTransformationH CPL_STDCALL 
+
+OGRCoordinateTransformationH CPL_STDCALL
 OCTNewCoordinateTransformation(
     OGRSpatialReferenceH hSourceSRS, OGRSpatialReferenceH hTargetSRS )
 
 {
-    return (OGRCoordinateTransformationH) 
-        OGRCreateCoordinateTransformation( 
+    return (OGRCoordinateTransformationH)
+        OGRCreateCoordinateTransformation(
             (OGRSpatialReference *) hSourceSRS,
             (OGRSpatialReference *) hTargetSRS );
 }
@@ -464,32 +485,18 @@ OCTNewCoordinateTransformation(
 /*                             OGRProj4CT()                             */
 /************************************************************************/
 
-OGRProj4CT::OGRProj4CT()
-
+OGRProj4CT::OGRProj4CT() :
+    poSRSSource(NULL), psPJSource(NULL), bSourceLatLong(FALSE),
+    dfSourceToRadians(0.0), bSourceWrap(FALSE), dfSourceWrapLong(0.0),
+    poSRSTarget(NULL), psPJTarget(NULL), bTargetLatLong(FALSE),
+    dfTargetFromRadians(0.0), bTargetWrap(FALSE), dfTargetWrapLong(0.0),
+    bIdentityTransform(FALSE), bWebMercatorToWGS84(FALSE), nErrorCount(0),
+    bCheckWithInvertProj(FALSE), dfThreshold(0.0), pjctx(NULL), nMaxCount(0),
+    padfOriX(NULL), padfOriY(NULL), padfOriZ(NULL), padfTargetX(NULL),
+    padfTargetY(NULL), padfTargetZ(NULL)
 {
-    poSRSSource = NULL;
-    poSRSTarget = NULL;
-    psPJSource = NULL;
-    psPJTarget = NULL;
-    
-    bIdentityTransform = FALSE;
-    nErrorCount = 0;
-    
-    bCheckWithInvertProj = FALSE;
-    dfThreshold = 0;
-
-    nMaxCount = 0;
-    padfOriX = NULL;
-    padfOriY = NULL;
-    padfOriZ = NULL;
-    padfTargetX = NULL;
-    padfTargetY = NULL;
-    padfTargetZ = NULL;
-
     if (pfn_pj_ctx_alloc != NULL)
         pjctx = pfn_pj_ctx_alloc();
-    else
-        pjctx = NULL;
 }
 
 /************************************************************************/
@@ -544,10 +551,15 @@ OGRProj4CT::~OGRProj4CT()
 /*                             Initialize()                             */
 /************************************************************************/
 
-int OGRProj4CT::Initialize( OGRSpatialReference * poSourceIn, 
+int OGRProj4CT::Initialize( OGRSpatialReference * poSourceIn,
                             OGRSpatialReference * poTargetIn )
 
 {
+    if( bProjLocaleSafe )
+    {
+        return InitializeNoLock(poSourceIn, poTargetIn);
+    }
+
     CPLLocaleC  oLocaleEnforcer;
     if (pjctx != NULL)
     {
@@ -562,7 +574,7 @@ int OGRProj4CT::Initialize( OGRSpatialReference * poSourceIn,
 /*                         InitializeNoLock()                           */
 /************************************************************************/
 
-int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn, 
+int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn,
                                   OGRSpatialReference * poTargetIn )
 
 {
@@ -617,7 +629,7 @@ int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn,
     if( CPLGetConfigOption( "CENTER_LONG", NULL ) != NULL )
     {
         bSourceWrap = bTargetWrap = TRUE;
-        dfSourceWrapLong = dfTargetWrapLong = 
+        dfSourceWrapLong = dfTargetWrapLong =
             CPLAtof(CPLGetConfigOption( "CENTER_LONG", "" ));
         CPLDebug( "OGRCT", "Wrap at %g.", dfSourceWrapLong );
     }
@@ -637,9 +649,9 @@ int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn,
         bTargetWrap = TRUE;
         CPLDebug( "OGRCT", "Wrap target at %g.", dfTargetWrapLong );
     }
-    
+
     bCheckWithInvertProj = CSLTestBoolean(CPLGetConfigOption( "CHECK_WITH_INVERT_PROJ", "NO" ));
-    
+
     /* The threshold is rather experimental... Works well with the cases of ticket #2305 */
     if (bSourceLatLong)
         dfThreshold = CPLAtof(CPLGetConfigOption( "THRESHOLD", ".1" ));
@@ -648,12 +660,9 @@ int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn,
         /* a tolerance of 10000 */
         dfThreshold = CPLAtof(CPLGetConfigOption( "THRESHOLD", "10000" ));
 
-/* -------------------------------------------------------------------- */
-/*      Establish PROJ.4 handle for source if projection.               */
-/* -------------------------------------------------------------------- */
-    // OGRThreadSafety: The following variable is not a thread safety issue 
-    // since the only issue is incrementing while accessing which at worse 
-    // means debug output could be one "increment" late. 
+    // OGRThreadSafety: The following variable is not a thread safety issue
+    // since the only issue is incrementing while accessing which at worse
+    // means debug output could be one "increment" late.
     static int   nDebugReportCount = 0;
 
     char        *pszSrcProj4Defn = NULL;
@@ -667,95 +676,179 @@ int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn,
     if( strlen(pszSrcProj4Defn) == 0 )
     {
         CPLFree( pszSrcProj4Defn );
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "No PROJ.4 translation for source SRS, coordinate\n"
                   "transformation initialization has failed." );
         return FALSE;
     }
 
-    if (pjctx)
-        psPJSource = pfn_pj_init_plus_ctx( pjctx, pszSrcProj4Defn );
-    else
-        psPJSource = pfn_pj_init_plus( pszSrcProj4Defn );
-    
-    if( psPJSource == NULL )
+    char        *pszDstProj4Defn = NULL;
+
+    if( poSRSTarget->exportToProj4( &pszDstProj4Defn ) != OGRERR_NONE )
+    {
+        CPLFree( pszSrcProj4Defn );
+        CPLFree( pszDstProj4Defn );
+        return FALSE;
+    }
+
+    if( strlen(pszDstProj4Defn) == 0 )
     {
-        if( pjctx != NULL)
+        CPLFree( pszSrcProj4Defn );
+        CPLFree( pszDstProj4Defn );
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "No PROJ.4 translation for destination SRS, coordinate\n"
+                  "transformation initialization has failed." );
+        return FALSE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Optimization to avoid useless nadgrids evaluation.              */
+/*      For example when converting between WGS84 and WebMercator       */
+/* -------------------------------------------------------------------- */
+    if( pszSrcProj4Defn[strlen(pszSrcProj4Defn)-1] == ' ' )
+        pszSrcProj4Defn[strlen(pszSrcProj4Defn)-1] = 0;
+    if( pszDstProj4Defn[strlen(pszDstProj4Defn)-1] == ' ' )
+        pszDstProj4Defn[strlen(pszDstProj4Defn)-1] = 0;
+    char* pszNeedle = strstr(pszSrcProj4Defn, "  ");
+    if( pszNeedle )
+        memmove(pszNeedle, pszNeedle + 1, strlen(pszNeedle + 1)+1);
+    pszNeedle = strstr(pszDstProj4Defn, "  ");
+    if( pszNeedle )
+        memmove(pszNeedle, pszNeedle + 1, strlen(pszNeedle + 1)+1);
+
+    if( (strstr(pszSrcProj4Defn, "+datum=WGS84") != NULL ||
+         strstr(pszSrcProj4Defn, "+ellps=WGS84 +towgs84=0,0,0,0,0,0,0 ") != NULL) &&
+        strstr(pszDstProj4Defn, "+nadgrids=@null ") != NULL &&
+        strstr(pszDstProj4Defn, "+towgs84") == NULL )
+    {
+        char* pszDst = strstr(pszSrcProj4Defn, "+towgs84=0,0,0,0,0,0,0 ");
+        char* pszSrc;
+        if( pszDst != NULL )
         {
-            int pj_errno = pfn_pj_ctx_get_errno(pjctx);
+            pszSrc = pszDst + strlen("+towgs84=0,0,0,0,0,0,0 ");
+            memmove(pszDst, pszSrc, strlen(pszSrc)+1);
+        }
+        else
+            memcpy(strstr(pszSrcProj4Defn, "+datum=WGS84"), "+ellps", 6);
 
-            /* pfn_pj_strerrno not yet thread-safe in PROJ 4.8.0 */
-            CPLMutexHolderD(&hPROJMutex);
-            CPLError( CE_Failure, CPLE_NotSupported, 
-                      "Failed to initialize PROJ.4 with `%s'.\n%s", 
-                      pszSrcProj4Defn, pfn_pj_strerrno(pj_errno) );
+        pszDst = strstr(pszDstProj4Defn, "+nadgrids=@null ");
+        pszSrc = pszDst + strlen("+nadgrids=@null ");
+        memmove(pszDst, pszSrc, strlen(pszSrc)+1);
+
+        pszDst = strstr(pszDstProj4Defn, "+wktext ");
+        if( pszDst )
+        {
+            pszSrc = pszDst + strlen("+wktext ");
+            memmove(pszDst, pszSrc, strlen(pszSrc)+1);
         }
-        else if( pfn_pj_get_errno_ref != NULL
-            && pfn_pj_strerrno != NULL )
+
+        //bWGS84ToWebMercator =
+        //    strcmp(pszSrcProj4Defn, "+proj=longlat +ellps=WGS84 +no_defs") == 0 &&
+        //    strcmp(pszDstProj4Defn, "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +no_defs") == 0;
+    }
+    else
+    if( (strstr(pszDstProj4Defn, "+datum=WGS84") != NULL ||
+         strstr(pszDstProj4Defn, "+ellps=WGS84 +towgs84=0,0,0,0,0,0,0 ") != NULL) &&
+        strstr(pszSrcProj4Defn, "+nadgrids=@null ") != NULL &&
+        strstr(pszSrcProj4Defn, "+towgs84") == NULL )
+    {
+        char* pszDst = strstr(pszDstProj4Defn, "+towgs84=0,0,0,0,0,0,0 ");
+        char* pszSrc;
+        if( pszDst != NULL)
         {
-            int *p_pj_errno = pfn_pj_get_errno_ref();
+            pszSrc = pszDst + strlen("+towgs84=0,0,0,0,0,0,0 ");
+            memmove(pszDst, pszSrc, strlen(pszSrc)+1);
+        }
+        else
+            memcpy(strstr(pszDstProj4Defn, "+datum=WGS84"), "+ellps", 6);
+
+        pszDst = strstr(pszSrcProj4Defn, "+nadgrids=@null ");
+        pszSrc = pszDst + strlen("+nadgrids=@null ");
+        memmove(pszDst, pszSrc, strlen(pszSrc)+1);
 
-            CPLError( CE_Failure, CPLE_NotSupported, 
-                      "Failed to initialize PROJ.4 with `%s'.\n%s", 
-                      pszSrcProj4Defn, pfn_pj_strerrno(*p_pj_errno) );
+        pszDst = strstr(pszSrcProj4Defn, "+wktext ");
+        if( pszDst )
+        {
+            pszSrc = pszDst + strlen("+wktext ");
+            memmove(pszDst, pszSrc, strlen(pszSrc)+1);
         }
+        bWebMercatorToWGS84 =
+            strcmp(pszDstProj4Defn, "+proj=longlat +ellps=WGS84 +no_defs") == 0 &&
+            strcmp(pszSrcProj4Defn, "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +no_defs") == 0;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Establish PROJ.4 handle for source if projection.               */
+/* -------------------------------------------------------------------- */
+    if( !bWebMercatorToWGS84 )
+    {
+        if (pjctx)
+            psPJSource = pfn_pj_init_plus_ctx( pjctx, pszSrcProj4Defn );
         else
+            psPJSource = pfn_pj_init_plus( pszSrcProj4Defn );
+
+        if( psPJSource == NULL )
         {
-            CPLError( CE_Failure, CPLE_NotSupported, 
-                      "Failed to initialize PROJ.4 with `%s'.\n", 
-                      pszSrcProj4Defn );
+            if( pjctx != NULL)
+            {
+                int pj_errno = pfn_pj_ctx_get_errno(pjctx);
+
+                /* pfn_pj_strerrno not yet thread-safe in PROJ 4.8.0 */
+                CPLMutexHolderD(&hPROJMutex);
+                CPLError( CE_Failure, CPLE_NotSupported,
+                        "Failed to initialize PROJ.4 with `%s'.\n%s",
+                        pszSrcProj4Defn, pfn_pj_strerrno(pj_errno) );
+            }
+            else if( pfn_pj_get_errno_ref != NULL
+                && pfn_pj_strerrno != NULL )
+            {
+                int *p_pj_errno = pfn_pj_get_errno_ref();
+
+                CPLError( CE_Failure, CPLE_NotSupported,
+                        "Failed to initialize PROJ.4 with `%s'.\n%s",
+                        pszSrcProj4Defn, pfn_pj_strerrno(*p_pj_errno) );
+            }
+            else
+            {
+                CPLError( CE_Failure, CPLE_NotSupported,
+                        "Failed to initialize PROJ.4 with `%s'.\n",
+                        pszSrcProj4Defn );
+            }
         }
     }
-    
+
     if( nDebugReportCount < 10 )
         CPLDebug( "OGRCT", "Source: %s", pszSrcProj4Defn );
 
-    if( psPJSource == NULL )
+    if( !bWebMercatorToWGS84 && psPJSource == NULL )
     {
         CPLFree( pszSrcProj4Defn );
+        CPLFree( pszDstProj4Defn );
         return FALSE;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Establish PROJ.4 handle for target if projection.               */
 /* -------------------------------------------------------------------- */
-
-    char        *pszDstProj4Defn = NULL;
-
-    if( poSRSTarget->exportToProj4( &pszDstProj4Defn ) != OGRERR_NONE )
+    if( !bWebMercatorToWGS84 )
     {
-        CPLFree( pszSrcProj4Defn );
-        CPLFree( pszDstProj4Defn );
-        return FALSE;
-    }
+        if (pjctx)
+            psPJTarget = pfn_pj_init_plus_ctx( pjctx, pszDstProj4Defn );
+        else
+            psPJTarget = pfn_pj_init_plus( pszDstProj4Defn );
 
-    if( strlen(pszDstProj4Defn) == 0 )
-    {
-        CPLFree( pszSrcProj4Defn );
-        CPLFree( pszDstProj4Defn );
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "No PROJ.4 translation for destination SRS, coordinate\n"
-                  "transformation initialization has failed." );
-        return FALSE;
+        if( psPJTarget == NULL )
+            CPLError( CE_Failure, CPLE_NotSupported,
+                    "Failed to initialize PROJ.4 with `%s'.",
+                    pszDstProj4Defn );
     }
-
-    if (pjctx)
-        psPJTarget = pfn_pj_init_plus_ctx( pjctx, pszDstProj4Defn );
-    else
-        psPJTarget = pfn_pj_init_plus( pszDstProj4Defn );
-    
-    if( psPJTarget == NULL )
-        CPLError( CE_Failure, CPLE_NotSupported, 
-                  "Failed to initialize PROJ.4 with `%s'.", 
-                  pszDstProj4Defn );
-    
     if( nDebugReportCount < 10 )
     {
         CPLDebug( "OGRCT", "Target: %s", pszDstProj4Defn );
         nDebugReportCount++;
     }
 
-    if( psPJTarget == NULL )
+    if( !bWebMercatorToWGS84 && psPJTarget == NULL )
     {
         CPLFree( pszSrcProj4Defn );
         CPLFree( pszDstProj4Defn );
@@ -765,15 +858,17 @@ int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn,
     /* Determine if we really have a transformation to do */
     bIdentityTransform = (strcmp(pszSrcProj4Defn, pszDstProj4Defn) == 0);
 
+#if 0
     /* In case of identity transform, under the following conditions, */
-    /* we can also avoid transforming from deegrees <--> radians. */
+    /* we can also avoid transforming from degrees <--> radians. */
     if( bIdentityTransform && bSourceLatLong && !bSourceWrap &&
         bTargetLatLong && !bTargetWrap &&
-        abs(dfSourceToRadians * dfTargetFromRadians - 1.0) < 1e-10 )
+        fabs(dfSourceToRadians * dfTargetFromRadians - 1.0) < 1e-10 )
     {
         /*bSourceLatLong = FALSE;
         bTargetLatLong = FALSE;*/
     }
+#endif
 
     CPLFree( pszSrcProj4Defn );
     CPLFree( pszDstProj4Defn );
@@ -881,18 +976,79 @@ int OGRProj4CT::TransformEx( int nCount, double *x, double *y, double *z,
             }
         }
     }
-    
+
+/* -------------------------------------------------------------------- */
+/*      Optimized transform from WebMercator to WGS84                   */
+/* -------------------------------------------------------------------- */
+    bool bTransformDone = false;
+    if( bWebMercatorToWGS84 )
+    {
+#define REVERSE_SPHERE_RADIUS  (1. / 6378137.)
+
+        double y0 = y[0];
+        for( i = 0; i < nCount; i++ )
+        {
+            if( x[i] != HUGE_VAL )
+            {
+                x[i] = x[i] * REVERSE_SPHERE_RADIUS;
+                if( x[i] > M_PI )
+                {
+                    if( x[i] < M_PI+1e-14 )
+                        x[i] = M_PI;
+                    else if (bCheckWithInvertProj)
+                    {
+                        x[i] = y[i] = HUGE_VAL;
+                        y0 = HUGE_VAL;
+                        continue;
+                    }
+                    else
+                    {
+                        do {
+                            x[i] -= 2 * M_PI;
+                        } while ( x[i] > M_PI );
+                    }
+                }
+                else if( x[i] < -M_PI )
+                {
+                    if( x[i] > -M_PI-1e-14 )
+                        x[i] = -M_PI;
+                    else if (bCheckWithInvertProj)
+                    {
+                        x[i] = y[i] = HUGE_VAL;
+                        y0 = HUGE_VAL;
+                        continue;
+                    }
+                    else
+                    {
+                        do {
+                            x[i] += 2 * M_PI;
+                        } while( x[i] < -M_PI );
+                    }
+                }
+                 // Optimization for the case where we are provided a whole line of same northing
+                if( i > 0 && y[i] == y0 )
+                    y[i] = y[0];
+                else
+                    y[i] = M_PI / 2 - 2. * atan(exp(-y[i] * REVERSE_SPHERE_RADIUS));
+            }
+        }
+
+        bTransformDone = true;
+    }
+    else if( bIdentityTransform )
+        bTransformDone = true;
+
 /* -------------------------------------------------------------------- */
-/*      Do the transformation using PROJ.4.                             */
+/*      Do the transformation (or not...) using PROJ.4.                 */
 /* -------------------------------------------------------------------- */
-    if( !bIdentityTransform && pjctx == NULL )
+    if( !bTransformDone && pjctx == NULL )
     {
         /* The mutex has already been created */
         CPLAssert(hPROJMutex != NULL);
         CPLAcquireMutex(hPROJMutex, 1000.0);
     }
 
-    if( bIdentityTransform )
+    if( bTransformDone )
         err = 0;
     else if (bCheckWithInvertProj)
     {
@@ -924,7 +1080,7 @@ int OGRProj4CT::TransformEx( int nCount, double *x, double *y, double *z,
             {
                 memcpy(padfTargetZ, z, sizeof(double)*nCount);
             }
-            
+
             err = pfn_pj_transform( psPJTarget, psPJSource , nCount, 1,
                                     padfTargetX, padfTargetY, (z) ? padfTargetZ : NULL);
             if (err == 0)
@@ -967,10 +1123,10 @@ int OGRProj4CT::TransformEx( int nCount, double *x, double *y, double *z,
             const char *pszError = NULL;
             if( pfn_pj_strerrno != NULL )
                 pszError = pfn_pj_strerrno( err );
-            
+
             if( pszError == NULL )
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                          "Reprojection failed, err = %d", 
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Reprojection failed, err = %d",
                           err );
             else
                 CPLError( CE_Failure, CPLE_AppDefined, "%s", pszError );
@@ -981,8 +1137,8 @@ int OGRProj4CT::TransformEx( int nCount, double *x, double *y, double *z,
         }
         else if( nErrorCount == 20 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Reprojection failed, err = %d, further errors will be suppressed on the transform object.", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Reprojection failed, err = %d, further errors will be suppressed on the transform object.",
                       err );
         }
 
@@ -991,7 +1147,7 @@ int OGRProj4CT::TransformEx( int nCount, double *x, double *y, double *z,
         return FALSE;
     }
 
-    if( !bIdentityTransform && pjctx == NULL )
+    if( !bTransformDone && pjctx == NULL )
         CPLReleaseMutex(hPROJMutex);
 
 /* -------------------------------------------------------------------- */
@@ -1054,4 +1210,3 @@ int CPL_STDCALL OCTTransformEx( OGRCoordinateTransformationH hTransform,
     return ((OGRCoordinateTransformation*) hTransform)->
         TransformEx( nCount, x, y, z, pabSuccess );
 }
-
diff --git a/ogr/ogrcurve.cpp b/ogr/ogrcurve.cpp
index ff7238a..f77cf6c 100644
--- a/ogr/ogrcurve.cpp
+++ b/ogr/ogrcurve.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: ogrcurve.cpp 28004 2014-11-26 09:58:44Z rouault $
+ * $Id: ogrcurve.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
- * Purpose:  The OGRCurve geometry class. 
+ * Purpose:  The OGRCurve geometry class.
  * Author:   Frank Warmerdam, warmerda at home.com
  *
  ******************************************************************************
@@ -30,7 +30,7 @@
 #include "ogr_geometry.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrcurve.cpp 28004 2014-11-26 09:58:44Z rouault $");
+CPL_CVSID("$Id: ogrcurve.cpp 33631 2016-03-04 06:28:09Z goatbar $");
 
 /************************************************************************/
 /*                                OGRCurve()                            */
@@ -49,6 +49,28 @@ OGRCurve::~OGRCurve()
 }
 
 /************************************************************************/
+/*                       OGRCurve( const OGRCurve& )                    */
+/************************************************************************/
+
+OGRCurve::OGRCurve( const OGRCurve& other ) :
+    OGRGeometry( other )
+{
+}
+
+/************************************************************************/
+/*                       operator=( const OGRCurve& )                   */
+/************************************************************************/
+
+OGRCurve& OGRCurve::operator=( const OGRCurve& other )
+{
+    if( this != &other)
+    {
+        OGRGeometry::operator=( other );
+    }
+    return *this;
+}
+
+/************************************************************************/
 /*                            getDimension()                            */
 /************************************************************************/
 
@@ -147,7 +169,7 @@ int OGRCurve::get_IsClosed() const
  *
  * If the dfMaxAngleStepSizeDegrees is zero, then a default value will be
  * used.  This is currently 4 degrees unless the user has overridden the
- * value with the OGR_ARC_STEPSIZE configuration variable. 
+ * value with the OGR_ARC_STEPSIZE configuration variable.
  *
  * This method relates to the ISO SQL/MM Part 3 ICurve::CurveToLine() method.
  *
@@ -269,7 +291,7 @@ OGRBoolean OGRCurve::IsConvex() const
  *
  * The passed in geometry is consumed and a new one returned (or NULL in case
  * of failure)
- * 
+ *
  * @param poCurve the input geometry - ownership is passed to the method.
  * @return new geometry
  *
@@ -300,7 +322,7 @@ OGRCompoundCurve* OGRCurve::CastToCompoundCurve(OGRCurve* poCurve)
  *
  * The passed in geometry is consumed and a new one returned (or NULL in case
  * of failure)
- * 
+ *
  * @param poCurve the input geometry - ownership is passed to the method.
  * @return new geometry.
  *
@@ -322,7 +344,7 @@ OGRLineString* OGRCurve::CastToLineString(OGRCurve* poCurve)
  *
  * The passed in geometry is consumed and a new one returned (or NULL in case
  * of failure)
- * 
+ *
  * @param poCurve the input geometry - ownership is passed to the method.
  * @return new geometry.
  *
@@ -343,7 +365,7 @@ OGRLinearRing* OGRCurve::CastToLinearRing(OGRCurve* poCurve)
  * \brief Returns if a point is contained in a (closed) curve.
  *
  * Final users should use OGRGeometry::Contains() instead.
- * 
+ *
  * @param p the point to test
  * @return TRUE if it is inside the curve, FALSE otherwise or -1 if unknown.
  *
diff --git a/ogr/ogrcurvecollection.cpp b/ogr/ogrcurvecollection.cpp
index 519423b..023b5c9 100644
--- a/ogr/ogrcurvecollection.cpp
+++ b/ogr/ogrcurvecollection.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrcurvecollection.cpp 29330 2015-06-14 12:11:11Z rouault $
+ * $Id: ogrcurvecollection.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRCurveCollection class.
@@ -45,6 +45,38 @@ OGRCurveCollection::OGRCurveCollection()
 }
 
 /************************************************************************/
+/*             OGRCurveCollection( const OGRCurveCollection& )          */
+/************************************************************************/
+
+/**
+ * \brief Copy constructor.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the constructor
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRCurveCollection::OGRCurveCollection( const OGRCurveCollection& other ) :
+    nCurveCount( 0 ),
+    papoCurves( NULL )
+{
+    if( other.nCurveCount > 0 )
+    {
+        nCurveCount = other.nCurveCount;
+        papoCurves = (OGRCurve **) VSI_CALLOC_VERBOSE(sizeof(void*), nCurveCount);
+
+        if( papoCurves )
+        {
+            for( int i = 0; i < nCurveCount; i++ )
+            {
+                papoCurves[i] = (OGRCurve*)other.papoCurves[i]->clone();
+            }
+        }
+    }
+}
+
+/************************************************************************/
 /*                         ~OGRCurveCollection()                        */
 /************************************************************************/
 
@@ -55,6 +87,42 @@ OGRCurveCollection::~OGRCurveCollection()
 }
 
 /************************************************************************/
+/*                 operator=( const OGRCurveCollection& )               */
+/************************************************************************/
+
+/**
+ * \brief Assignment operator.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the operator
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRCurveCollection& OGRCurveCollection::operator=( const OGRCurveCollection& other )
+{
+    if( this != &other)
+    {
+        empty(NULL);
+
+        if( other.nCurveCount > 0 )
+        {
+            nCurveCount = other.nCurveCount;
+            papoCurves = (OGRCurve **) VSI_MALLOC2_VERBOSE(sizeof(void*), nCurveCount);
+
+            if( papoCurves )
+            {
+                for( int i = 0; i < nCurveCount; i++ )
+                {
+                    papoCurves[i] = (OGRCurve*)other.papoCurves[i]->clone();
+                }
+            }
+        }
+    }
+    return *this;
+}
+
+/************************************************************************/
 /*                              WkbSize()                               */
 /************************************************************************/
 
@@ -78,15 +146,29 @@ OGRErr OGRCurveCollection::addCurveDirectly( OGRGeometry* poGeom,
                                              OGRCurve* poCurve,
                                              int bNeedRealloc )
 {
-    if( poCurve->getCoordinateDimension() == 3 && poGeom->getCoordinateDimension() != 3 )
-        poGeom->setCoordinateDimension(3);
-    else if( poCurve->getCoordinateDimension() != 3 && poGeom->getCoordinateDimension() == 3 )
-        poCurve->setCoordinateDimension(3);
+    if( poGeom->Is3D() && !poCurve->Is3D() )
+
+        poCurve->set3D(TRUE);
+
+    if( poGeom->IsMeasured() && !poCurve->IsMeasured() )
+
+        poCurve->setMeasured(TRUE);
+
+    if( !poGeom->Is3D() && poCurve->Is3D() )
+
+        poGeom->set3D(TRUE);
+
+    if( !poGeom->IsMeasured() && poCurve->IsMeasured() )
+
+        poGeom->setMeasured(TRUE);
 
     if( bNeedRealloc )
     {
-        papoCurves = (OGRCurve **) OGRRealloc( papoCurves,
+        OGRCurve** papoNewCurves = (OGRCurve **) VSI_REALLOC_VERBOSE( papoCurves,
                                              sizeof(OGRCurve*) * (nCurveCount+1) );
+        if( papoNewCurves == NULL )
+            return OGRERR_FAILURE;
+        papoCurves = papoNewCurves;
     }
 
     papoCurves[nCurveCount] = poCurve;
@@ -116,17 +198,18 @@ OGRErr OGRCurveCollection::importPreambuleFromWkb( OGRGeometry* poGeom,
                                                         nMinSubGeomSize,
                                                         nCurveCount,
                                                         eWkbVariant );
-    if( eErr >= 0 )
+    if( eErr != OGRERR_NONE )
         return eErr;
 
-    papoCurves = (OGRCurve **) VSIMalloc2(sizeof(void*), nCurveCount);
+    /* coverity[tainted_data] */
+    papoCurves = (OGRCurve **) VSI_CALLOC_VERBOSE(sizeof(void*), nCurveCount);
     if (nCurveCount != 0 && papoCurves == NULL)
     {
         nCurveCount = 0;
         return OGRERR_NOT_ENOUGH_MEMORY;
     }
 
-    return -1;
+    return OGRERR_NONE;
 }
 
 /************************************************************************/
@@ -158,8 +241,7 @@ OGRErr OGRCurveCollection::importBodyFromWkb( OGRGeometry* poGeom,
             return OGRERR_NOT_ENOUGH_DATA;
 
         OGRwkbGeometryType eSubGeomType;
-        OGRBoolean bIs3D;
-        if ( OGRReadWKBGeometryType( pabySubData, eWkbVariant, &eSubGeomType, &bIs3D ) != OGRERR_NONE )
+        if ( OGRReadWKBGeometryType( pabySubData, eWkbVariant, &eSubGeomType ) != OGRERR_NONE )
             return OGRERR_FAILURE;
 
         if( (eSubGeomType != wkbCompoundCurve && OGR_GT_IsCurve(eSubGeomType)) ||
@@ -203,13 +285,18 @@ OGRErr OGRCurveCollection::exportToWkt( const OGRGeometry* poGeom,
 
 {
     char        **papszGeoms;
-    int         iGeom, nCumulativeLength = 0;
+    int         iGeom;
+    size_t      nCumulativeLength = 0;
     OGRErr      eErr;
 
     if( nCurveCount == 0 )
     {
         CPLString osEmpty;
-        if( poGeom->getCoordinateDimension()  == 3 )
+        if( poGeom->Is3D() && poGeom->IsMeasured() )
+            osEmpty.Printf("%s ZM EMPTY",poGeom->getGeometryName());
+        else if( poGeom->IsMeasured() )
+            osEmpty.Printf("%s M EMPTY",poGeom->getGeometryName());
+        else if( poGeom->Is3D() )
             osEmpty.Printf("%s Z EMPTY",poGeom->getGeometryName());
         else
             osEmpty.Printf("%s EMPTY",poGeom->getGeometryName());
@@ -230,11 +317,11 @@ OGRErr OGRCurveCollection::exportToWkt( const OGRGeometry* poGeom,
 
         nCumulativeLength += strlen(papszGeoms[iGeom]);
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Allocate the right amount of space for the aggregated string    */
 /* -------------------------------------------------------------------- */
-    *ppszDstText = (char *) VSIMalloc(nCumulativeLength + nCurveCount +
+    *ppszDstText = (char *) VSI_MALLOC_VERBOSE(nCumulativeLength + nCurveCount +
                                     strlen(poGeom->getGeometryName()) + 10);
 
     if( *ppszDstText == NULL )
@@ -247,7 +334,11 @@ OGRErr OGRCurveCollection::exportToWkt( const OGRGeometry* poGeom,
 /*      Build up the string, freeing temporary strings as we go.        */
 /* -------------------------------------------------------------------- */
     strcpy( *ppszDstText, poGeom->getGeometryName() );
-    if( poGeom->getCoordinateDimension() == 3 )
+    if( poGeom->Is3D() && poGeom->IsMeasured() )
+        strcat( *ppszDstText, " ZM" );
+    else if( poGeom->IsMeasured() )
+        strcat( *ppszDstText, " M" );
+    else if( poGeom->Is3D() )
         strcat( *ppszDstText, " Z" );
     strcat( *ppszDstText, " (" );
     nCumulativeLength = strlen(*ppszDstText);
@@ -258,16 +349,20 @@ OGRErr OGRCurveCollection::exportToWkt( const OGRGeometry* poGeom,
             (*ppszDstText)[nCumulativeLength++] = ',';
 
         /* We must strip the explicit "LINESTRING " prefix */
-        int nSkip = 0;
+        size_t nSkip = 0;
         if( !papoCurves[iGeom]->IsEmpty() &&
-            EQUALN(papszGeoms[iGeom], "LINESTRING ", strlen("LINESTRING ")) )
+            STARTS_WITH_CI(papszGeoms[iGeom], "LINESTRING ") )
         {
             nSkip = strlen("LINESTRING ");
-            if( EQUALN(papszGeoms[iGeom] + nSkip, "Z ", 2) )
+            if( STARTS_WITH_CI(papszGeoms[iGeom] + nSkip, "ZM ") )
+                nSkip += 3;
+            else if( STARTS_WITH_CI(papszGeoms[iGeom] + nSkip, "M ") )
+                nSkip += 2;
+            else if( STARTS_WITH_CI(papszGeoms[iGeom] + nSkip, "Z ") )
                 nSkip += 2;
         }
 
-        int nGeomLength = strlen(papszGeoms[iGeom] + nSkip);
+        size_t nGeomLength = strlen(papszGeoms[iGeom] + nSkip);
         memcpy( *ppszDstText + nCumulativeLength, papszGeoms[iGeom] + nSkip, nGeomLength );
         nCumulativeLength += nGeomLength;
         VSIFree( papszGeoms[iGeom] );
@@ -297,7 +392,7 @@ OGRErr OGRCurveCollection::exportToWkb( const OGRGeometry* poGeom,
                                         OGRwkbVariant eWkbVariant ) const
 {
     int         nOffset;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Set the byte order.                                             */
 /* -------------------------------------------------------------------- */
@@ -324,7 +419,7 @@ OGRErr OGRCurveCollection::exportToWkb( const OGRGeometry* poGeom,
         nGType = CPL_MSBWORD32( nGType );
 
     memcpy( pabyData + 1, &nGType, 4 );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Copy in the raw data.                                           */
 /* -------------------------------------------------------------------- */
@@ -339,9 +434,9 @@ OGRErr OGRCurveCollection::exportToWkb( const OGRGeometry* poGeom,
     {
         memcpy( pabyData+5, &nCurveCount, 4 );
     }
-    
+
     nOffset = 9;
-    
+
 /* ==================================================================== */
 /*      Serialize each of the Geoms.                                    */
 /* ==================================================================== */
@@ -351,7 +446,7 @@ OGRErr OGRCurveCollection::exportToWkb( const OGRGeometry* poGeom,
 
         nOffset += papoCurves[iGeom]->WkbSize();
     }
-    
+
     return OGRERR_NONE;
 }
 
@@ -397,7 +492,7 @@ void OGRCurveCollection::getEnvelope( OGREnvelope * psEnvelope ) const
 void OGRCurveCollection::getEnvelope( OGREnvelope3D * psEnvelope ) const
 {
     OGREnvelope3D       oGeomEnv;
-    int                 bExtentSet = FALSE;
+    bool                bExtentSet = false;
 
     for( int iGeom = 0; iGeom < nCurveCount; iGeom++ )
     {
@@ -406,7 +501,7 @@ void OGRCurveCollection::getEnvelope( OGREnvelope3D * psEnvelope ) const
             if (!bExtentSet)
             {
                 papoCurves[iGeom]->getEnvelope( psEnvelope );
-                bExtentSet = TRUE;
+                bExtentSet = true;
             }
             else
             {
@@ -440,7 +535,7 @@ OGRBoolean  OGRCurveCollection::Equals( OGRCurveCollection *poOCC ) const
 {
     if( getNumCurves() != poOCC->getNumCurves() )
         return FALSE;
-    
+
     // we should eventually test the SRS.
 
     for( int iGeom = 0; iGeom < nCurveCount; iGeom++ )
@@ -467,6 +562,26 @@ void OGRCurveCollection::setCoordinateDimension( OGRGeometry* poGeom,
     poGeom->OGRGeometry::setCoordinateDimension( nNewDimension );
 }
 
+void OGRCurveCollection::set3D( OGRGeometry* poGeom, OGRBoolean bIs3D )
+{
+    for( int iGeom = 0; iGeom < nCurveCount; iGeom++ )
+    {
+        papoCurves[iGeom]->set3D( bIs3D );
+    }
+
+    poGeom->OGRGeometry::set3D( bIs3D );
+}
+
+void OGRCurveCollection::setMeasured( OGRGeometry* poGeom, OGRBoolean bIsMeasured )
+{
+    for( int iGeom = 0; iGeom < nCurveCount; iGeom++ )
+    {
+        papoCurves[iGeom]->setMeasured( bIsMeasured );
+    }
+
+    poGeom->OGRGeometry::setMeasured( bIsMeasured );
+}
+
 /************************************************************************/
 /*                          getNumCurves()                              */
 /************************************************************************/
@@ -534,7 +649,7 @@ OGRErr  OGRCurveCollection::transform( OGRGeometry* poGeom,
         {
             if( iGeom != 0 )
             {
-                CPLDebug("OGR", 
+                CPLDebug("OGR",
                          "OGRCurveCollection::transform() failed for a geometry other\n"
                          "than the first, meaning some geometries are transformed\n"
                          "and some are not!\n" );
diff --git a/ogr/ogrcurvepolygon.cpp b/ogr/ogrcurvepolygon.cpp
index 5edd963..276c349 100644
--- a/ogr/ogrcurvepolygon.cpp
+++ b/ogr/ogrcurvepolygon.cpp
@@ -48,6 +48,25 @@ OGRCurvePolygon::OGRCurvePolygon()
 }
 
 /************************************************************************/
+/*               OGRCurvePolygon( const OGRCurvePolygon& )              */
+/************************************************************************/
+
+/**
+ * \brief Copy constructor.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the constructor
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRCurvePolygon::OGRCurvePolygon( const OGRCurvePolygon& other ) :
+    OGRSurface(other),
+    oCC(other.oCC)
+{
+}
+
+/************************************************************************/
 /*                           ~OGRCurvePolygon()                         */
 /************************************************************************/
 
@@ -57,6 +76,30 @@ OGRCurvePolygon::~OGRCurvePolygon()
 }
 
 /************************************************************************/
+/*                 operator=( const OGRCurvePolygon&)                  */
+/************************************************************************/
+
+/**
+ * \brief Assignment operator.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the operator
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRCurvePolygon& OGRCurvePolygon::operator=( const OGRCurvePolygon& other )
+{
+    if( this != &other)
+    {
+        OGRSurface::operator=( other );
+
+        oCC = other.oCC;
+    }
+    return *this;
+}
+
+/************************************************************************/
 /*                               clone()                                */
 /************************************************************************/
 
@@ -67,11 +110,18 @@ OGRGeometry *OGRCurvePolygon::clone() const
 
     poNewPolygon = (OGRCurvePolygon*)
             OGRGeometryFactory::createGeometry(getGeometryType());
+    if( poNewPolygon == NULL )
+        return NULL;
     poNewPolygon->assignSpatialReference( getSpatialReference() );
+    poNewPolygon->flags = flags;
 
     for( int i = 0; i < oCC.nCurveCount; i++ )
     {
-        poNewPolygon->addRing( oCC.papoCurves[i] );
+        if( poNewPolygon->addRing( oCC.papoCurves[i] ) != OGRERR_NONE )
+        {
+            delete poNewPolygon;
+            return NULL;
+        }
     }
 
     return poNewPolygon;
@@ -94,7 +144,11 @@ void OGRCurvePolygon::empty()
 OGRwkbGeometryType OGRCurvePolygon::getGeometryType() const
 
 {
-    if( nCoordDimension == 3 )
+    if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
+        return wkbCurvePolygonZM;
+    else if( flags & OGR_G_MEASURED  )
+        return wkbCurvePolygonM;
+    else if( flags & OGR_G_3D )
         return wkbCurvePolygonZ;
     else
         return wkbCurvePolygon;
@@ -258,6 +312,8 @@ OGRErr OGRCurvePolygon::addRing( OGRCurve * poNewRing )
 
 {
     OGRCurve* poNewRingCloned = (OGRCurve* )poNewRing->clone();
+    if( poNewRingCloned == NULL )
+        return OGRERR_FAILURE;
     OGRErr eErr = addRingDirectly(poNewRingCloned);
     if( eErr != OGRERR_NONE )
         delete poNewRingCloned;
@@ -363,9 +419,10 @@ OGRErr OGRCurvePolygon::importFromWkb( unsigned char * pabyData,
 {
     OGRwkbByteOrder eByteOrder;
     int nDataOffset = 0;
+    /* coverity[tainted_data] */
     OGRErr eErr = oCC.importPreambuleFromWkb(this, pabyData, nSize, nDataOffset,
                                              eByteOrder, 9, eWkbVariant);
-    if( eErr >= 0 )
+    if( eErr != OGRERR_NONE )
         return eErr;
 
     return oCC.importBodyFromWkb(this, pabyData, nSize, nDataOffset,
@@ -489,13 +546,10 @@ OGRGeometry* OGRCurvePolygon::getLinearGeometry(double dfMaxAngleStepSizeDegrees
 /*                           PointOnSurface()                           */
 /************************************************************************/
 
-int OGRCurvePolygon::PointOnSurface( OGRPoint *poPoint ) const
+OGRErr OGRCurvePolygon::PointOnSurface( OGRPoint *poPoint ) const
 
 {
-    OGRPolygon* poPoly = CurvePolyToPoly();
-    int ret = poPoly->PointOnSurface(poPoint);
-    delete poPoly;
-    return ret;
+    return PointOnSurfaceInternal(poPoint);
 }
 
 /************************************************************************/
@@ -511,7 +565,7 @@ void OGRCurvePolygon::getEnvelope( OGREnvelope * psEnvelope ) const
 /************************************************************************/
 /*                            getEnvelope()                             */
 /************************************************************************/
- 
+
 void OGRCurvePolygon::getEnvelope( OGREnvelope3D * psEnvelope ) const
 
 {
@@ -525,17 +579,16 @@ void OGRCurvePolygon::getEnvelope( OGREnvelope3D * psEnvelope ) const
 OGRBoolean OGRCurvePolygon::Equals( OGRGeometry * poOther ) const
 
 {
-    OGRCurvePolygon *poOPoly = (OGRCurvePolygon *) poOther;
-
-    if( poOPoly == this )
+    if( poOther == this )
         return TRUE;
-    
+
     if( poOther->getGeometryType() != getGeometryType() )
         return FALSE;
 
     if ( IsEmpty() && poOther->IsEmpty() )
         return TRUE;
-    
+
+    OGRCurvePolygon *poOPoly = (OGRCurvePolygon *) poOther;
     return oCC.Equals( &(poOPoly->oCC) );
 }
 
@@ -583,6 +636,15 @@ void OGRCurvePolygon::setCoordinateDimension( int nNewDimension )
     oCC.setCoordinateDimension(this, nNewDimension);
 }
 
+void OGRCurvePolygon::set3D( OGRBoolean bIs3D )
+{
+    oCC.set3D( this, bIs3D );
+}
+
+void OGRCurvePolygon::setMeasured( OGRBoolean bIsMeasured )
+{
+    oCC.setMeasured( this, bIsMeasured );
+}
 
 /************************************************************************/
 /*                               IsEmpty()                              */
@@ -670,11 +732,11 @@ OGRBoolean OGRCurvePolygon::Intersects( const OGRGeometry *poOtherGeom ) const
  * instances of OGRLineString. This can be verified if hasCurveGeometry(TRUE)
  * returns FALSE. It is not intended to approximate curve polygons. For that
  * use getLinearGeometry().
- * 
+ *
  * The passed in geometry is consumed and a new one returned (or NULL in case
- * of failure). 
- * 
- * @param poMS the input geometry - ownership is passed to the method.
+ * of failure).
+ *
+ * @param poCP the input geometry - ownership is passed to the method.
  * @return new geometry.
  */
 
diff --git a/ogr/ogrfeature.cpp b/ogr/ogrfeature.cpp
index 523b9c8..40beeaa 100644
--- a/ogr/ogrfeature.cpp
+++ b/ogr/ogrfeature.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: ogrfeature.cpp 33000 2016-01-15 15:01:06Z rouault $
- * 
+ * $Id: ogrfeature.cpp 33631 2016-03-04 06:28:09Z goatbar $
+ *
  * Project:  OpenGIS Simple Features Reference Implementation
- * Purpose:  The OGRFeature class implementation. 
+ * Purpose:  The OGRFeature class implementation.
  * Author:   Frank Warmerdam, warmerda at home.com
  *
  ******************************************************************************
@@ -34,8 +34,9 @@
 #include "cpl_time.h"
 #include <vector>
 #include <errno.h>
+#include <new>
 
-CPL_CVSID("$Id: ogrfeature.cpp 33000 2016-01-15 15:01:06Z rouault $");
+CPL_CVSID("$Id: ogrfeature.cpp 33631 2016-03-04 06:28:09Z goatbar $");
 
 /************************************************************************/
 /*                             OGRFeature()                             */
@@ -47,7 +48,7 @@ CPL_CVSID("$Id: ogrfeature.cpp 33000 2016-01-15 15:01:06Z rouault $");
  * Note that the OGRFeature will increment the reference count of it's
  * defining OGRFeatureDefn.  Destruction of the OGRFeatureDefn before
  * destruction of all OGRFeatures that depend on it is likely to result in
- * a crash. 
+ * a crash.
  *
  * This method is the same as the C function OGR_F_Create().
  *
@@ -55,28 +56,31 @@ CPL_CVSID("$Id: ogrfeature.cpp 33000 2016-01-15 15:01:06Z rouault $");
  * adhere.
  */
 
-OGRFeature::OGRFeature( OGRFeatureDefn * poDefnIn )
-
+OGRFeature::OGRFeature( OGRFeatureDefn * poDefnIn ) :
+            nFID(OGRNullFID),
+            poDefn(poDefnIn),
+            m_pszNativeData(NULL),
+            m_pszNativeMediaType(NULL),
+            m_pszStyleString(NULL),
+            m_poStyleTable(NULL),
+            m_pszTmpFieldValue(NULL)
 {
-    m_pszStyleString = NULL;
-    m_poStyleTable = NULL;
-    m_pszTmpFieldValue = NULL;
     poDefnIn->Reference();
-    poDefn = poDefnIn;
-
-    nFID = OGRNullFID;
 
     // Allocate array of fields and initialize them to the unset special value
-    pauFields = (OGRField *) CPLMalloc( poDefn->GetFieldCount() *
+    pauFields = (OGRField *) VSI_MALLOC_VERBOSE( poDefn->GetFieldCount() *
                                         sizeof(OGRField) );
 
-    papoGeometries = (OGRGeometry **) CPLCalloc( poDefn->GetGeomFieldCount(),
+    papoGeometries = (OGRGeometry **) VSI_CALLOC_VERBOSE( poDefn->GetGeomFieldCount(),
                                         sizeof(OGRGeometry*) );
 
-    for( int i = 0; i < poDefn->GetFieldCount(); i++ )
+    if( pauFields != NULL )
     {
-        pauFields[i].Set.nMarker1 = OGRUnsetMarker;
-        pauFields[i].Set.nMarker2 = OGRUnsetMarker;
+        for( int i = 0; i < poDefn->GetFieldCount(); i++ )
+        {
+            pauFields[i].Set.nMarker1 = OGRUnsetMarker;
+            pauFields[i].Set.nMarker2 = OGRUnsetMarker;
+        }
     }
 }
 
@@ -89,23 +93,22 @@ OGRFeature::OGRFeature( OGRFeatureDefn * poDefnIn )
  * Note that the OGRFeature will increment the reference count of it's
  * defining OGRFeatureDefn.  Destruction of the OGRFeatureDefn before
  * destruction of all OGRFeatures that depend on it is likely to result in
- * a crash. 
+ * a crash.
  *
  * This function is the same as the C++ method OGRFeature::OGRFeature().
- * 
- * @param hDefn handle to the feature class (layer) definition to 
+ *
+ * @param hDefn handle to the feature class (layer) definition to
  * which the feature will adhere.
- * 
- * @return an handle to the new feature object with null fields and 
- * no geometry.
+ *
+ * @return an handle to the new feature object with null fields and
+ * no geometry, or, starting with GDAL 2.1, NULL in case out of memory situation.
  */
 
 OGRFeatureH OGR_F_Create( OGRFeatureDefnH hDefn )
 
 {
     VALIDATE_POINTER1( hDefn, "OGR_F_Create", NULL );
-
-    return (OGRFeatureH) new OGRFeature( (OGRFeatureDefn *) hDefn );
+    return (OGRFeatureH) OGRFeature::CreateFeature( (OGRFeatureDefn*) hDefn );
 }
 
 /************************************************************************/
@@ -117,14 +120,14 @@ OGRFeature::~OGRFeature()
 {
     int i;
 
-    int nFieldcount = poDefn->GetFieldCount();
+    int nFieldcount = ( pauFields != NULL ) ? poDefn->GetFieldCount() : 0;
     for( i = 0; i < nFieldcount; i++ )
     {
         OGRFieldDefn    *poFDefn = poDefn->GetFieldDefn(i);
-        
+
         if( !IsFieldSet(i) )
             continue;
-    
+
         switch( poFDefn->GetType() )
         {
           case OFTString:
@@ -152,19 +155,21 @@ OGRFeature::~OGRFeature()
             break;
         }
     }
-    
-    int nGeomFieldCount = poDefn->GetGeomFieldCount();
+
+    int nGeomFieldCount = (papoGeometries != NULL) ? poDefn->GetGeomFieldCount() : 0;
     for( i = 0; i < nGeomFieldCount; i++ )
     {
         delete papoGeometries[i];
     }
-    
+
     poDefn->Release();
 
     CPLFree( pauFields );
     CPLFree( papoGeometries );
     CPLFree(m_pszStyleString);
     CPLFree(m_pszTmpFieldValue);
+    CPLFree( m_pszNativeData );
+    CPLFree( m_pszNativeMediaType );
 }
 
 /************************************************************************/
@@ -174,13 +179,13 @@ OGRFeature::~OGRFeature()
  * \brief Destroy feature
  *
  * The feature is deleted, but within the context of the GDAL/OGR heap.
- * This is necessary when higher level applications use GDAL/OGR from a 
+ * This is necessary when higher level applications use GDAL/OGR from a
  * DLL and they want to delete a feature created within the DLL.  If the
  * delete is done in the calling application the memory will be freed onto
- * the application heap which is inappropriate. 
+ * the application heap which is inappropriate.
  *
  * This function is the same as the C++ method OGRFeature::DestroyFeature().
- * 
+ *
  * @param hFeat handle to the feature to destroy.
  */
 
@@ -197,22 +202,32 @@ void OGR_F_Destroy( OGRFeatureH hFeat )
 /**
  * \brief Feature factory.
  *
- * This is essentially a feature factory, useful for               
- * applications creating features but wanting to ensure they       
- * are created out of the OGR/GDAL heap.                           
- * 
+ * This is essentially a feature factory, useful for
+ * applications creating features but wanting to ensure they
+ * are created out of the OGR/GDAL heap.
+ *
  * This method is the same as the C function OGR_F_Create().
  *
  * @param poDefn Feature definition defining schema.
- * 
- * @return new feature object with null fields and no geometry.  May be
- * deleted with delete. 
+ *
+ * @return new feature object with null fields and no geometry, or, starting with
+ * GDAL 2.1, NULL in case of out of memory situation.  May be
+ * deleted with DestroyFeature().
  */
 
 OGRFeature *OGRFeature::CreateFeature( OGRFeatureDefn *poDefn )
 
 {
-    return new OGRFeature( poDefn );
+    OGRFeature* poFeature = new (std::nothrow) OGRFeature( poDefn );
+    if( poFeature == NULL )
+        return NULL;
+    if( (poFeature->pauFields == NULL && poDefn->GetFieldCount() != 0) ||
+        (poFeature->papoGeometries == NULL && poDefn->GetGeomFieldCount() != 0) )
+    {
+        delete poFeature;
+        return NULL;
+    }
+    return poFeature;
 }
 
 /************************************************************************/
@@ -223,13 +238,13 @@ OGRFeature *OGRFeature::CreateFeature( OGRFeatureDefn *poDefn )
  * \brief Destroy feature
  *
  * The feature is deleted, but within the context of the GDAL/OGR heap.
- * This is necessary when higher level applications use GDAL/OGR from a 
+ * This is necessary when higher level applications use GDAL/OGR from a
  * DLL and they want to delete a feature created within the DLL.  If the
  * delete is done in the calling application the memory will be freed onto
- * the application heap which is inappropriate. 
+ * the application heap which is inappropriate.
  *
  * This method is the same as the C function OGR_F_Destroy().
- * 
+ *
  * @param poFeature the feature to delete.
  */
 
@@ -295,8 +310,8 @@ OGRFeatureDefnH OGR_F_GetDefnRef( OGRFeatureH hFeat )
  *
  * @return OGRERR_NONE if successful, or OGR_UNSUPPORTED_GEOMETRY_TYPE if
  * the geometry type is illegal for the OGRFeatureDefn (checking not yet
- * implemented). 
- */ 
+ * implemented).
+ */
 
 OGRErr OGRFeature::SetGeometryDirectly( OGRGeometry * poGeomIn )
 
@@ -321,7 +336,7 @@ OGRErr OGRFeature::SetGeometryDirectly( OGRGeometry * poGeomIn )
  * SetGeometry(), except that this function assumes ownership of the
  * passed geometry (even in case of failure of that function).
  *
- * This function is the same as the C++ method 
+ * This function is the same as the C++ method
  * OGRFeature::SetGeometryDirectly.
  *
  * @param hFeat handle to the feature on which to apply the geometry.
@@ -329,13 +344,13 @@ OGRErr OGRFeature::SetGeometryDirectly( OGRGeometry * poGeomIn )
  *
  * @return OGRERR_NONE if successful, or OGR_UNSUPPORTED_GEOMETRY_TYPE if
  * the geometry type is illegal for the OGRFeatureDefn (checking not yet
- * implemented). 
- */ 
+ * implemented).
+ */
 
 OGRErr OGR_F_SetGeometryDirectly( OGRFeatureH hFeat, OGRGeometryH hGeom )
 
 {
-    VALIDATE_POINTER1( hFeat, "OGR_F_SetGeometryDirectly", CE_Failure );
+    VALIDATE_POINTER1( hFeat, "OGR_F_SetGeometryDirectly", OGRERR_FAILURE );
 
     return ((OGRFeature *) hFeat)->SetGeometryDirectly((OGRGeometry *) hGeom);
 }
@@ -349,7 +364,7 @@ OGRErr OGR_F_SetGeometryDirectly( OGRFeatureH hFeat, OGRGeometryH hGeom )
  *
  * This method updates the features geometry, and operate exactly as
  * SetGeometryDirectly(), except that this method does not assume ownership
- * of the passed geometry, but instead makes a copy of it. 
+ * of the passed geometry, but instead makes a copy of it.
  *
  * This method is the same as the C function OGR_F_SetGeometry().
  *
@@ -359,8 +374,8 @@ OGRErr OGR_F_SetGeometryDirectly( OGRFeatureH hFeat, OGRGeometryH hGeom )
  *
  * @return OGRERR_NONE if successful, or OGR_UNSUPPORTED_GEOMETRY_TYPE if
  * the geometry type is illegal for the OGRFeatureDefn (checking not yet
- * implemented). 
- */ 
+ * implemented).
+ */
 
 OGRErr OGRFeature::SetGeometry( OGRGeometry * poGeomIn )
 
@@ -380,7 +395,7 @@ OGRErr OGRFeature::SetGeometry( OGRGeometry * poGeomIn )
  *
  * This function updates the features geometry, and operate exactly as
  * SetGeometryDirectly(), except that this function does not assume ownership
- * of the passed geometry, but instead makes a copy of it. 
+ * of the passed geometry, but instead makes a copy of it.
  *
  * This function is the same as the C++ OGRFeature::SetGeometry().
  *
@@ -389,13 +404,13 @@ OGRErr OGRFeature::SetGeometry( OGRGeometry * poGeomIn )
  *
  * @return OGRERR_NONE if successful, or OGR_UNSUPPORTED_GEOMETRY_TYPE if
  * the geometry type is illegal for the OGRFeatureDefn (checking not yet
- * implemented). 
- */ 
+ * implemented).
+ */
 
 OGRErr OGR_F_SetGeometry( OGRFeatureH hFeat, OGRGeometryH hGeom )
 
 {
-    VALIDATE_POINTER1( hFeat, "OGR_F_SetGeometry", CE_Failure );
+    VALIDATE_POINTER1( hFeat, "OGR_F_SetGeometry", OGRERR_FAILURE );
 
     return ((OGRFeature *) hFeat)->SetGeometry((OGRGeometry *) hGeom);
 }
@@ -409,7 +424,7 @@ OGRErr OGR_F_SetGeometry( OGRFeatureH hFeat, OGRGeometryH hGeom )
  *
  * Fetch the geometry from this feature, and clear the reference to the
  * geometry on the feature.  This is a mechanism for the application to
- * take over ownship of the geometry from the feature without copying. 
+ * take over ownership of the geometry from the feature without copying.
  * Sort of an inverse to SetGeometryDirectly().
  *
  * After this call the OGRFeature will have a NULL geometry.
@@ -452,7 +467,7 @@ OGRGeometry *OGRFeature::StealGeometry(int iGeomField)
  *
  * Fetch the geometry from this feature, and clear the reference to the
  * geometry on the feature.  This is a mechanism for the application to
- * take over ownship of the geometry from the feature without copying. 
+ * take over ownership of the geometry from the feature without copying.
  * Sort of an inverse to OGR_FSetGeometryDirectly().
  *
  * After this call the OGRFeature will have a NULL geometry.
@@ -478,7 +493,7 @@ OGRGeometryH OGR_F_StealGeometry( OGRFeatureH hFeat )
  * \brief Fetch pointer to feature geometry.
  *
  * This method is the same as the C function OGR_F_GetGeometryRef().
- * 
+ *
  * Starting with GDAL 1.11, this is equivalent to calling
  * OGRFeature::GetGeomFieldRef(0).
  *
@@ -513,7 +528,7 @@ OGRGeometryH OGR_F_GetGeometryRef( OGRFeatureH hFeat )
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_GetGeometryRef", NULL );
 
-    OGRFeature* poFeature = (OGRFeature *) hFeat; 
+    OGRFeature* poFeature = (OGRFeature *) hFeat;
     OGRGeometry* poGeom = poFeature->GetGeometryRef();
 
     if( !OGRGetNonLinearGeometriesEnabledFlag() && poGeom != NULL &&
@@ -522,6 +537,7 @@ OGRGeometryH OGR_F_GetGeometryRef( OGRFeatureH hFeat )
         OGRwkbGeometryType eTargetType = OGR_GT_GetLinear(poGeom->getGeometryType());
         poGeom = OGRGeometryFactory::forceTo(poFeature->StealGeometry(), eTargetType);
         poFeature->SetGeomFieldDirectly(0, poGeom);
+        poGeom = poFeature->GetGeometryRef();
     }
 
     return (OGRGeometryH)poGeom;
@@ -599,7 +615,7 @@ OGRGeometryH OGR_F_GetGeomFieldRef( OGRFeatureH hFeat, int iField )
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_GetGeomFieldRef", NULL );
 
-    OGRFeature* poFeature = (OGRFeature *) hFeat; 
+    OGRFeature* poFeature = (OGRFeature *) hFeat;
     OGRGeometry* poGeom = poFeature->GetGeomFieldRef(iField);
 
     if( !OGRGetNonLinearGeometriesEnabledFlag() && poGeom != NULL &&
@@ -608,6 +624,7 @@ OGRGeometryH OGR_F_GetGeomFieldRef( OGRFeatureH hFeat, int iField )
         OGRwkbGeometryType eTargetType = OGR_GT_GetLinear(poGeom->getGeometryType());
         poGeom = OGRGeometryFactory::forceTo(poFeature->StealGeometry(iField), eTargetType);
         poFeature->SetGeomFieldDirectly(iField, poGeom);
+        poGeom = poFeature->GetGeomFieldRef(iField);
     }
 
     return (OGRGeometryH)poGeom;
@@ -632,11 +649,11 @@ OGRGeometryH OGR_F_GetGeomFieldRef( OGRFeatureH hFeat, int iField )
  * without assigning new one.
  *
  * @return OGRERR_NONE if successful, or OGRERR_FAILURE if the index is invalid,
- * or OGR_UNSUPPORTED_GEOMETRY_TYPE if the geometry type is illegal for the
+ * or OGRERR_UNSUPPORTED_GEOMETRY_TYPE if the geometry type is illegal for the
  * OGRFeatureDefn (checking not yet implemented).
  *
  * @since GDAL 1.11
- */ 
+ */
 
 OGRErr OGRFeature::SetGeomFieldDirectly( int iField, OGRGeometry * poGeomIn )
 
@@ -647,14 +664,46 @@ OGRErr OGRFeature::SetGeomFieldDirectly( int iField, OGRGeometry * poGeomIn )
         return OGRERR_FAILURE;
     }
 
+    /*
+    // (Verify the type) and set/unset flags.
+    OGRwkbGeometryType eMyGeomType = poDefn->GetGeomFieldDefn(iField)->GetType();
+
+    if( eMyGeomType != wkbUnknown )
+    {
+        OGRwkbGeometryType eGeomInType = poGeomIn->getGeometryType();
+
+          This leads to segfaults in tests probably because issues with simple vs multi geometries
+          if( wkbFlatten(eGeomInType) != wkbFlatten(eMyGeomType) )
+          {
+          delete poGeomIn;
+          return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
+          }
+
+        if( wkbHasZ(eMyGeomType) && !wkbHasZ(eGeomInType) )
+        {
+            poGeomIn->set3D(TRUE);
+        }
+        else if( !wkbHasZ(eMyGeomType) && wkbHasZ(eGeomInType) )
+        {
+            poGeomIn->set3D(FALSE);
+        }
+        if( wkbHasM(eMyGeomType) && !wkbHasM(eGeomInType) )
+        {
+            poGeomIn->setMeasured(TRUE);
+        }
+        else if( !wkbHasM(eMyGeomType) && wkbHasM(eGeomInType) )
+        {
+            poGeomIn->setMeasured(FALSE);
+        }
+    }
+    */
+
     if( papoGeometries[iField] != poGeomIn )
     {
         delete papoGeometries[iField];
         papoGeometries[iField] = poGeomIn;
     }
 
-    // I should be verifying that the geometry matches the defn's type.
-    
     return OGRERR_NONE;
 }
 
@@ -669,7 +718,7 @@ OGRErr OGRFeature::SetGeomFieldDirectly( int iField, OGRGeometry * poGeomIn )
  * SetGeomField(), except that this function assumes ownership of the
  * passed geometry (even in case of failure of that function).
  *
- * This function is the same as the C++ method 
+ * This function is the same as the C++ method
  * OGRFeature::SetGeomFieldDirectly.
  *
  * @param hFeat handle to the feature on which to apply the geometry.
@@ -681,13 +730,13 @@ OGRErr OGRFeature::SetGeomFieldDirectly( int iField, OGRGeometry * poGeomIn )
  * OGRFeatureDefn (checking not yet implemented).
  *
  * @since GDAL 1.11
- */ 
+ */
 
 OGRErr OGR_F_SetGeomFieldDirectly( OGRFeatureH hFeat, int iField,
                                    OGRGeometryH hGeom )
 
 {
-    VALIDATE_POINTER1( hFeat, "OGR_F_SetGeomFieldDirectly", CE_Failure );
+    VALIDATE_POINTER1( hFeat, "OGR_F_SetGeomFieldDirectly", OGRERR_FAILURE );
 
     return ((OGRFeature *) hFeat)->SetGeomFieldDirectly(iField,
                                                         (OGRGeometry *) hGeom);
@@ -702,7 +751,7 @@ OGRErr OGR_F_SetGeomFieldDirectly( OGRFeatureH hFeat, int iField,
  *
  * This method updates the features geometry, and operate exactly as
  * SetGeomFieldDirectly(), except that this method does not assume ownership
- * of the passed geometry, but instead makes a copy of it. 
+ * of the passed geometry, but instead makes a copy of it.
  *
  * This method is the same as the C function OGR_F_SetGeomField().
  *
@@ -716,7 +765,7 @@ OGRErr OGR_F_SetGeomFieldDirectly( OGRFeatureH hFeat, int iField,
  * OGRFeatureDefn (checking not yet implemented).
  *
  * @since GDAL 1.11
- */ 
+ */
 
 OGRErr OGRFeature::SetGeomField( int iField, OGRGeometry * poGeomIn )
 
@@ -735,7 +784,7 @@ OGRErr OGRFeature::SetGeomField( int iField, OGRGeometry * poGeomIn )
     }
 
     // I should be verifying that the geometry matches the defn's type.
-    
+
     return OGRERR_NONE;
 }
 
@@ -748,7 +797,7 @@ OGRErr OGRFeature::SetGeomField( int iField, OGRGeometry * poGeomIn )
  *
  * This function updates the features geometry, and operate exactly as
  * SetGeometryDirectly(), except that this function does not assume ownership
- * of the passed geometry, but instead makes a copy of it. 
+ * of the passed geometry, but instead makes a copy of it.
  *
  * This function is the same as the C++ OGRFeature::SetGeomField().
  *
@@ -758,13 +807,13 @@ OGRErr OGRFeature::SetGeomField( int iField, OGRGeometry * poGeomIn )
  *
  * @return OGRERR_NONE if successful, or OGR_UNSUPPORTED_GEOMETRY_TYPE if
  * the geometry type is illegal for the OGRFeatureDefn (checking not yet
- * implemented). 
- */ 
+ * implemented).
+ */
 
 OGRErr OGR_F_SetGeomField( OGRFeatureH hFeat, int iField, OGRGeometryH hGeom )
 
 {
-    VALIDATE_POINTER1( hFeat, "OGR_F_SetGeomField", CE_Failure );
+    VALIDATE_POINTER1( hFeat, "OGR_F_SetGeomField", OGRERR_FAILURE );
 
     return ((OGRFeature *) hFeat)->SetGeomField(iField, (OGRGeometry *) hGeom);
 }
@@ -781,29 +830,71 @@ OGRErr OGR_F_SetGeomField( OGRFeatureH hFeat, int iField, OGRGeometryH hGeom )
  *
  * This method is the same as the C function OGR_F_Clone().
  *
- * @return new feature, exactly matching this feature.
+ * @return new feature, exactly matching this feature. Or, starting with GDAL 2.1,
+ *         NULL in case of out of memory situation.
  */
 
 OGRFeature *OGRFeature::Clone()
 
 {
     int i;
-    OGRFeature  *poNew = new OGRFeature( poDefn );
+    OGRFeature  *poNew = CreateFeature( poDefn );
+    if( poNew == NULL )
+        return NULL;
 
     for( i = 0; i < poDefn->GetFieldCount(); i++ )
     {
-        poNew->SetField( i, pauFields + i );
+        if( !poNew->SetFieldInternal( i, pauFields + i ) )
+        {
+            delete poNew;
+            return NULL;
+        }
     }
     for( i = 0; i < poDefn->GetGeomFieldCount(); i++ )
     {
-        poNew->SetGeomField( i, papoGeometries[i] );
+        if( papoGeometries[i] != NULL )
+        {
+            poNew->papoGeometries[i] = papoGeometries[i]->clone();
+            if( poNew->papoGeometries[i] == NULL )
+            {
+                delete poNew;
+                return NULL;
+            }
+        }
     }
 
-    if( GetStyleString() != NULL )
-        poNew->SetStyleString(GetStyleString());
+    if( m_pszStyleString != NULL )
+    {
+        poNew->m_pszStyleString = VSI_STRDUP_VERBOSE(m_pszStyleString);
+        if( poNew->m_pszStyleString == NULL )
+        {
+            delete poNew;
+            return NULL;
+        }
+    }
 
     poNew->SetFID( GetFID() );
 
+    if( m_pszNativeData != NULL )
+    {
+        poNew->m_pszNativeData = VSI_STRDUP_VERBOSE(m_pszNativeData);
+        if( poNew->m_pszNativeData == NULL )
+        {
+            delete poNew;
+            return NULL;
+        }
+    }
+
+    if( m_pszNativeMediaType != NULL )
+    {
+        poNew->m_pszNativeMediaType = VSI_STRDUP_VERBOSE(m_pszNativeMediaType);
+        if( poNew->m_pszNativeMediaType == NULL )
+        {
+            delete poNew;
+            return NULL;
+        }
+    }
+
     return poNew;
 }
 
@@ -923,14 +1014,14 @@ OGRFieldDefnH OGR_F_GetFieldDefnRef( OGRFeatureH hFeat, int i )
 
 /**
  * \fn int OGRFeature::GetFieldIndex( const char * pszName );
- * 
+ *
  * \brief Fetch the field index given field name.
  *
- * This is a cover for the OGRFeatureDefn::GetFieldIndex() method. 
+ * This is a cover for the OGRFeatureDefn::GetFieldIndex() method.
  *
  * This method is the same as the C function OGR_F_GetFieldIndex().
  *
- * @param pszName the name of the field to search for. 
+ * @param pszName the name of the field to search for.
  *
  * @return the field index, or -1 if no matching field is found.
  */
@@ -942,12 +1033,12 @@ OGRFieldDefnH OGR_F_GetFieldDefnRef( OGRFeatureH hFeat, int i )
 /**
  * \brief Fetch the field index given field name.
  *
- * This is a cover for the OGRFeatureDefn::GetFieldIndex() method. 
+ * This is a cover for the OGRFeatureDefn::GetFieldIndex() method.
  *
  * This function is the same as the C++ method OGRFeature::GetFieldIndex().
  *
  * @param hFeat handle to the feature on which the field is found.
- * @param pszName the name of the field to search for. 
+ * @param pszName the name of the field to search for.
  *
  * @return the field index, or -1 if no matching field is found.
  */
@@ -1055,14 +1146,14 @@ OGRGeomFieldDefnH OGR_F_GetGeomFieldDefnRef( OGRFeatureH hFeat, int i )
 
 /**
  * \fn int OGRFeature::GetGeomFieldIndex( const char * pszName );
- * 
+ *
  * \brief Fetch the geometry field index given geometry field name.
  *
- * This is a cover for the OGRFeatureDefn::GetGeomFieldIndex() method. 
+ * This is a cover for the OGRFeatureDefn::GetGeomFieldIndex() method.
  *
  * This method is the same as the C function OGR_F_GetGeomFieldIndex().
  *
- * @param pszName the name of the geometry field to search for. 
+ * @param pszName the name of the geometry field to search for.
  *
  * @return the geometry field index, or -1 if no matching geometry field is found.
  *
@@ -1076,12 +1167,12 @@ OGRGeomFieldDefnH OGR_F_GetGeomFieldDefnRef( OGRFeatureH hFeat, int i )
 /**
  * \brief Fetch the geometry field index given geometry field name.
  *
- * This is a cover for the OGRFeatureDefn::GetGeomFieldIndex() method. 
+ * This is a cover for the OGRFeatureDefn::GetGeomFieldIndex() method.
  *
  * This function is the same as the C++ method OGRFeature::GetGeomFieldIndex().
  *
  * @param hFeat handle to the feature on which the geometry field is found.
- * @param pszName the name of the geometry field to search for. 
+ * @param pszName the name of the geometry field to search for.
  *
  * @return the geometry field index, or -1 if no matching geometry field is found.
  *
@@ -1143,7 +1234,7 @@ int OGRFeature::IsFieldSet( int iField )
         }
     }
     else
-    { 
+    {
         return pauFields[iField].Set.nMarker1 != OGRUnsetMarker
             || pauFields[iField].Set.nMarker2 != OGRUnsetMarker;
     }
@@ -1168,9 +1259,9 @@ int OGR_F_IsFieldSet( OGRFeatureH hFeat, int iField )
 
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_IsFieldSet", 0 );
-    
+
     OGRFeature* poFeature = (OGRFeature* )hFeat;
-    
+
     if (iField < 0 || iField >= poFeature->GetFieldCount())
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Invalid index : %d", iField);
@@ -1199,7 +1290,7 @@ void OGRFeature::UnsetField( int iField )
 
     if( poFDefn == NULL || !IsFieldSet(iField) )
         return;
-    
+
     switch( poFDefn->GetType() )
     {
       case OFTRealList:
@@ -1256,14 +1347,14 @@ void OGR_F_UnsetField( OGRFeatureH hFeat, int iField )
 /**
  * \fn OGRField *OGRFeature::GetRawFieldRef( int iField );
  *
- * \brief Fetch a pointer to the internal field value given the index.  
+ * \brief Fetch a pointer to the internal field value given the index.
  *
  * This method is the same as the C function OGR_F_GetRawFieldRef().
  *
  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
  *
  * @return the returned pointer is to an internal data structure, and should
- * not be freed, or modified. 
+ * not be freed, or modified.
  */
 
 /************************************************************************/
@@ -1271,7 +1362,7 @@ void OGR_F_UnsetField( OGRFeatureH hFeat, int iField )
 /************************************************************************/
 
 /**
- * \brief Fetch an handle to the internal field value given the index.  
+ * \brief Fetch an handle to the internal field value given the index.
  *
  * This function is the same as the C++ method OGRFeature::GetRawFieldRef().
  *
@@ -1279,7 +1370,7 @@ void OGR_F_UnsetField( OGRFeatureH hFeat, int iField )
  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
  *
  * @return the returned handle is to an internal data structure, and should
- * not be freed, or modified. 
+ * not be freed, or modified.
  */
 
 OGRField *OGR_F_GetRawFieldRef( OGRFeatureH hFeat, int iField )
@@ -1320,12 +1411,14 @@ int OGRFeature::GetFieldAsInteger( int iField )
         {
         case SPF_FID:
         {
-            int nVal = (nFID > INT_MAX) ? INT_MAX : (nFID < INT_MIN) ? INT_MIN : (int) nFID;
+            int nVal = (nFID > INT_MAX) ? INT_MAX :
+                (nFID < INT_MIN) ? INT_MIN : (int) nFID;
+
             if( (GIntBig)nVal != nFID )
             {
-                CPLError(CE_Warning, CPLE_AppDefined,
-                 "Integer overflow occured when trying to return 64bit integer. "
-                 "Use GetFieldAsInteger64() instead");
+                CPLError( CE_Warning, CPLE_AppDefined,
+                          "Integer overflow occurred when trying to return "
+                          "64bit integer. Use GetFieldAsInteger64() instead" );
             }
             return nVal;
         }
@@ -1339,27 +1432,29 @@ int OGRFeature::GetFieldAsInteger( int iField )
             return 0;
         }
     }
-    
+
     OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
-    
+
     if( poFDefn == NULL )
         return 0;
-    
+
     if( !IsFieldSet(iField) )
         return 0;
-    
+
     OGRFieldType eType = poFDefn->GetType();
     if( eType == OFTInteger )
         return pauFields[iField].Integer;
     else if( eType == OFTInteger64 )
     {
         GIntBig nVal64 = pauFields[iField].Integer64;
-        int nVal = (nVal64 > INT_MAX) ? INT_MAX : (nVal64 < INT_MIN) ? INT_MIN : (int) nVal64;
+        int nVal = (nVal64 > INT_MAX) ? INT_MAX :
+            (nVal64 < INT_MIN) ? INT_MIN : (int) nVal64;
+
         if( (GIntBig)nVal != nVal64 )
         {
-            CPLError(CE_Warning, CPLE_AppDefined,
-                 "Integer overflow occured when trying to return 64bit integer. "
-                 "Use GetFieldAsInteger64() instead");
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Integer overflow occurred when trying to return 64bit "
+                      "integer. Use GetFieldAsInteger64() instead");
         }
         return nVal;
     }
@@ -1434,7 +1529,7 @@ GIntBig OGRFeature::GetFieldAsInteger64( int iField )
         {
         case SPF_FID:
             return nFID;
-        
+
         case SPF_OGR_GEOM_AREA:
             if( GetGeomFieldCount() == 0 || papoGeometries[0] == NULL )
                 return 0;
@@ -1444,15 +1539,15 @@ GIntBig OGRFeature::GetFieldAsInteger64( int iField )
             return 0;
         }
     }
-    
+
     OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
-    
+
     if( poFDefn == NULL )
         return 0;
-    
+
     if( !IsFieldSet(iField) )
         return 0;
-    
+
     OGRFieldType eType = poFDefn->GetType();
     if( eType == OFTInteger )
         return (GIntBig) pauFields[iField].Integer;
@@ -1541,15 +1636,15 @@ double OGRFeature::GetFieldAsDouble( int iField )
             return 0.0;
         }
     }
-    
+
     OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
-    
+
     if( poFDefn == NULL )
         return 0.0;
 
     if( !IsFieldSet(iField) )
         return 0.0;
-    
+
     OGRFieldType eType = poFDefn->GetType();
     if( eType == OFTReal )
         return pauFields[iField].Real;
@@ -1596,6 +1691,60 @@ double OGR_F_GetFieldAsDouble( OGRFeatureH hFeat, int iField )
 }
 
 /************************************************************************/
+/*                      OGRFeatureFormatDateTimeBuffer()                */
+/************************************************************************/
+
+#define TEMP_BUFFER_SIZE 80
+static void OGRFeatureFormatDateTimeBuffer(char szTempBuffer[TEMP_BUFFER_SIZE],
+                                           int nYear, int nMonth, int nDay,
+                                           int nHour, int nMinute, float fSecond,
+                                           int nTZFlag )
+{
+    int ms = OGR_GET_MS(fSecond);
+    if( ms != 0 )
+        snprintf( szTempBuffer, TEMP_BUFFER_SIZE,
+                "%04d/%02d/%02d %02d:%02d:%06.3f",
+                nYear,
+                nMonth,
+                nDay,
+                nHour,
+                nMinute,
+                fSecond );
+    else /* default format */
+        snprintf( szTempBuffer, TEMP_BUFFER_SIZE,
+                "%04d/%02d/%02d %02d:%02d:%02d",
+                nYear,
+                nMonth,
+                nDay,
+                nHour,
+                nMinute,
+                (int)fSecond );
+
+
+    if( nTZFlag > 1 )
+    {
+        int nOffset = (nTZFlag - 100) * 15;
+        int nHours = (int) (nOffset / 60);  // round towards zero
+        int nMinutes = ABS(nOffset - nHours * 60);
+
+        if( nOffset < 0 )
+        {
+            strcat( szTempBuffer, "-" );
+            nHours = ABS(nHours);
+        }
+        else
+            strcat( szTempBuffer, "+" );
+
+        if( nMinutes == 0 )
+            snprintf( szTempBuffer+strlen(szTempBuffer),
+                    TEMP_BUFFER_SIZE-strlen(szTempBuffer), "%02d", nHours );
+        else
+            snprintf( szTempBuffer+strlen(szTempBuffer),
+                    TEMP_BUFFER_SIZE-strlen(szTempBuffer), "%02d%02d", nHours, nMinutes );
+    }
+}
+
+/************************************************************************/
 /*                          GetFieldAsString()                          */
 /************************************************************************/
 
@@ -1611,17 +1760,16 @@ double OGR_F_GetFieldAsDouble( OGRFeatureH hFeat, int iField )
  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
  *
  * @return the field value.  This string is internal, and should not be
- * modified, or freed.  Its lifetime may be very brief. 
+ * modified, or freed.  Its lifetime may be very brief.
  */
 
 const char *OGRFeature::GetFieldAsString( int iField )
 
 {
-#define TEMP_BUFFER_SIZE 80
     char         szTempBuffer[TEMP_BUFFER_SIZE];
 
     CPLFree(m_pszTmpFieldValue);
-    m_pszTmpFieldValue = NULL;            
+    m_pszTmpFieldValue = NULL;
 
     int iSpecialField = iField - poDefn->GetFieldCount();
     if (iSpecialField >= 0)
@@ -1631,7 +1779,10 @@ const char *OGRFeature::GetFieldAsString( int iField )
         {
           case SPF_FID:
             snprintf( szTempBuffer, TEMP_BUFFER_SIZE, CPL_FRMT_GIB, GetFID() );
-            return m_pszTmpFieldValue = CPLStrdup( szTempBuffer );
+            m_pszTmpFieldValue = VSI_STRDUP_VERBOSE( szTempBuffer );
+            if( m_pszTmpFieldValue == NULL )
+                return "";
+            return m_pszTmpFieldValue;
 
           case SPF_OGR_GEOMETRY:
             if( GetGeomFieldCount() > 0 && papoGeometries[0] != NULL )
@@ -1660,23 +1811,26 @@ const char *OGRFeature::GetFieldAsString( int iField )
             if( GetGeomFieldCount() == 0 || papoGeometries[0] == NULL )
                 return "";
 
-            CPLsnprintf( szTempBuffer, TEMP_BUFFER_SIZE, "%.16g", 
+            CPLsnprintf( szTempBuffer, TEMP_BUFFER_SIZE, "%.16g",
                       OGR_G_Area((OGRGeometryH)papoGeometries[0]) );
-            return m_pszTmpFieldValue = CPLStrdup( szTempBuffer );
+            m_pszTmpFieldValue = VSI_STRDUP_VERBOSE( szTempBuffer );
+            if( m_pszTmpFieldValue == NULL )
+                return "";
+            return m_pszTmpFieldValue;
 
           default:
             return "";
         }
     }
-    
+
     OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
-    
+
     if( poFDefn == NULL )
         return "";
-    
+
     if( !IsFieldSet(iField) )
         return "";
-    
+
     OGRFieldType eType = poFDefn->GetType();
     if( eType == OFTString )
     {
@@ -1689,13 +1843,19 @@ const char *OGRFeature::GetFieldAsString( int iField )
     {
         snprintf( szTempBuffer, TEMP_BUFFER_SIZE,
                   "%d", pauFields[iField].Integer );
-        return m_pszTmpFieldValue = CPLStrdup( szTempBuffer );
+        m_pszTmpFieldValue = VSI_STRDUP_VERBOSE( szTempBuffer );
+        if( m_pszTmpFieldValue == NULL )
+            return "";
+        return m_pszTmpFieldValue;
     }
     else if( eType == OFTInteger64 )
     {
         snprintf( szTempBuffer, TEMP_BUFFER_SIZE,
                   CPL_FRMT_GIB, pauFields[iField].Integer64 );
-        return m_pszTmpFieldValue = CPLStrdup( szTempBuffer );
+        m_pszTmpFieldValue = VSI_STRDUP_VERBOSE( szTempBuffer );
+        if( m_pszTmpFieldValue == NULL )
+            return "";
+        return m_pszTmpFieldValue;
     }
     else if( eType == OFTReal )
     {
@@ -1708,58 +1868,30 @@ const char *OGRFeature::GetFieldAsString( int iField )
         }
         else
             strcpy( szFormat, "%.15g" );
-        
+
         CPLsnprintf( szTempBuffer, TEMP_BUFFER_SIZE,
                   szFormat, pauFields[iField].Real );
-        
-        return m_pszTmpFieldValue = CPLStrdup( szTempBuffer );
+
+        m_pszTmpFieldValue = VSI_STRDUP_VERBOSE( szTempBuffer );
+        if( m_pszTmpFieldValue == NULL )
+            return "";
+        return m_pszTmpFieldValue;
     }
     else if( eType == OFTDateTime )
     {
-        int ms = OGR_GET_MS(pauFields[iField].Date.Second);
-        if( ms != 0 )
-            snprintf( szTempBuffer, TEMP_BUFFER_SIZE,
-                    "%04d/%02d/%02d %02d:%02d:%06.3f", 
-                    pauFields[iField].Date.Year,
-                    pauFields[iField].Date.Month,
-                    pauFields[iField].Date.Day,
-                    pauFields[iField].Date.Hour,
-                    pauFields[iField].Date.Minute,
-                    pauFields[iField].Date.Second );
-        else /* default format */
-            snprintf( szTempBuffer, TEMP_BUFFER_SIZE,
-                    "%04d/%02d/%02d %02d:%02d:%02d", 
-                    pauFields[iField].Date.Year,
-                    pauFields[iField].Date.Month,
-                    pauFields[iField].Date.Day,
-                    pauFields[iField].Date.Hour,
-                    pauFields[iField].Date.Minute,
-                    (int)pauFields[iField].Date.Second );
-
-
-        if( pauFields[iField].Date.TZFlag > 1 )
-        {
-            int nOffset = (pauFields[iField].Date.TZFlag - 100) * 15;
-            int nHours = (int) (nOffset / 60);  // round towards zero
-            int nMinutes = ABS(nOffset - nHours * 60);
-
-            if( nOffset < 0 )
-            {
-                strcat( szTempBuffer, "-" );
-                nHours = ABS(nHours);
-            }
-            else
-                strcat( szTempBuffer, "+" );
-
-            if( nMinutes == 0 )
-                snprintf( szTempBuffer+strlen(szTempBuffer), 
-                          TEMP_BUFFER_SIZE-strlen(szTempBuffer), "%02d", nHours );
-            else
-                snprintf( szTempBuffer+strlen(szTempBuffer), 
-                          TEMP_BUFFER_SIZE-strlen(szTempBuffer), "%02d%02d", nHours, nMinutes );
-        }
-
-        return m_pszTmpFieldValue = CPLStrdup( szTempBuffer );
+        OGRFeatureFormatDateTimeBuffer(szTempBuffer,
+                                       pauFields[iField].Date.Year,
+                                       pauFields[iField].Date.Month,
+                                       pauFields[iField].Date.Day,
+                                       pauFields[iField].Date.Hour,
+                                       pauFields[iField].Date.Minute,
+                                       pauFields[iField].Date.Second,
+                                       pauFields[iField].Date.TZFlag );
+
+        m_pszTmpFieldValue = VSI_STRDUP_VERBOSE( szTempBuffer );
+        if( m_pszTmpFieldValue == NULL )
+            return "";
+        return m_pszTmpFieldValue;
     }
     else if( eType == OFTDate )
     {
@@ -1768,23 +1900,29 @@ const char *OGRFeature::GetFieldAsString( int iField )
                   pauFields[iField].Date.Month,
                   pauFields[iField].Date.Day );
 
-        return m_pszTmpFieldValue = CPLStrdup( szTempBuffer );
+        m_pszTmpFieldValue = VSI_STRDUP_VERBOSE( szTempBuffer );
+        if( m_pszTmpFieldValue == NULL )
+            return "";
+        return m_pszTmpFieldValue;
     }
     else if( eType == OFTTime )
     {
         int ms = OGR_GET_MS(pauFields[iField].Date.Second);
         if( ms != 0 )
-            snprintf( szTempBuffer, TEMP_BUFFER_SIZE, "%02d:%02d:%06.3f", 
+            snprintf( szTempBuffer, TEMP_BUFFER_SIZE, "%02d:%02d:%06.3f",
                   pauFields[iField].Date.Hour,
                   pauFields[iField].Date.Minute,
                   pauFields[iField].Date.Second );
         else
-            snprintf( szTempBuffer, TEMP_BUFFER_SIZE, "%02d:%02d:%02d", 
+            snprintf( szTempBuffer, TEMP_BUFFER_SIZE, "%02d:%02d:%02d",
                   pauFields[iField].Date.Hour,
                   pauFields[iField].Date.Minute,
                   (int)pauFields[iField].Date.Second );
-        
-        return m_pszTmpFieldValue = CPLStrdup( szTempBuffer );
+
+        m_pszTmpFieldValue = VSI_STRDUP_VERBOSE( szTempBuffer );
+        if( m_pszTmpFieldValue == NULL )
+            return "";
+        return m_pszTmpFieldValue;
     }
     else if( eType == OFTIntegerList )
     {
@@ -1801,10 +1939,10 @@ const char *OGRFeature::GetFieldAsString( int iField )
             {
                 break;
             }
-            
+
             if( i > 0 )
                 strcat( szTempBuffer, "," );
-            
+
             strcat( szTempBuffer, szItem );
         }
 
@@ -1812,8 +1950,11 @@ const char *OGRFeature::GetFieldAsString( int iField )
             strcat( szTempBuffer, ",...)" );
         else
             strcat( szTempBuffer, ")" );
-        
-        return m_pszTmpFieldValue = CPLStrdup( szTempBuffer );
+
+        m_pszTmpFieldValue = VSI_STRDUP_VERBOSE( szTempBuffer );
+        if( m_pszTmpFieldValue == NULL )
+            return "";
+        return m_pszTmpFieldValue;
     }
     else if( eType == OFTInteger64List )
     {
@@ -1830,10 +1971,10 @@ const char *OGRFeature::GetFieldAsString( int iField )
             {
                 break;
             }
-            
+
             if( i > 0 )
                 strcat( szTempBuffer, "," );
-            
+
             strcat( szTempBuffer, szItem );
         }
 
@@ -1841,8 +1982,11 @@ const char *OGRFeature::GetFieldAsString( int iField )
             strcat( szTempBuffer, ",...)" );
         else
             strcat( szTempBuffer, ")" );
-        
-        return m_pszTmpFieldValue = CPLStrdup( szTempBuffer );
+
+        m_pszTmpFieldValue = VSI_STRDUP_VERBOSE( szTempBuffer );
+        if( m_pszTmpFieldValue == NULL )
+            return "";
+        return m_pszTmpFieldValue;
     }
     else if( eType == OFTRealList )
     {
@@ -1857,7 +2001,7 @@ const char *OGRFeature::GetFieldAsString( int iField )
         }
         else
             strcpy( szFormat, "%.16g" );
-        
+
         snprintf( szTempBuffer, TEMP_BUFFER_SIZE, "(%d:", nCount );
         for( i = 0; i < nCount; i++ )
         {
@@ -1868,10 +2012,10 @@ const char *OGRFeature::GetFieldAsString( int iField )
             {
                 break;
             }
-            
+
             if( i > 0 )
                 strcat( szTempBuffer, "," );
-            
+
             strcat( szTempBuffer, szItem );
         }
 
@@ -1879,8 +2023,11 @@ const char *OGRFeature::GetFieldAsString( int iField )
             strcat( szTempBuffer, ",...)" );
         else
             strcat( szTempBuffer, ")" );
-        
-        return m_pszTmpFieldValue = CPLStrdup( szTempBuffer );
+
+        m_pszTmpFieldValue = VSI_STRDUP_VERBOSE( szTempBuffer );
+        if( m_pszTmpFieldValue == NULL )
+            return "";
+        return m_pszTmpFieldValue;
     }
     else if( eType == OFTStringList )
     {
@@ -1890,7 +2037,7 @@ const char *OGRFeature::GetFieldAsString( int iField )
         for( i = 0; i < nCount; i++ )
         {
             const char  *pszItem = pauFields[iField].StringList.paList[i];
-            
+
             if( strlen(szTempBuffer) + strlen(pszItem)  + 6
                 >= sizeof(szTempBuffer) )
             {
@@ -1899,7 +2046,7 @@ const char *OGRFeature::GetFieldAsString( int iField )
 
             if( i > 0 )
                 strcat( szTempBuffer, "," );
-            
+
             strcat( szTempBuffer, pszItem );
         }
 
@@ -1907,14 +2054,17 @@ const char *OGRFeature::GetFieldAsString( int iField )
             strcat( szTempBuffer, ",...)" );
         else
             strcat( szTempBuffer, ")" );
-        
-        return m_pszTmpFieldValue = CPLStrdup( szTempBuffer );
+
+        m_pszTmpFieldValue = VSI_STRDUP_VERBOSE( szTempBuffer );
+        if( m_pszTmpFieldValue == NULL )
+            return "";
+        return m_pszTmpFieldValue;
     }
     else if( eType == OFTBinary )
     {
         int     nCount = pauFields[iField].Binary.nCount;
         char    *pszHex;
-        
+
         if( nCount > (int) sizeof(szTempBuffer) / 2 - 4 )
             nCount = sizeof(szTempBuffer) / 2 - 4;
 
@@ -1927,11 +2077,13 @@ const char *OGRFeature::GetFieldAsString( int iField )
 
         CPLFree( pszHex );
 
-        return m_pszTmpFieldValue = CPLStrdup( szTempBuffer );
+        m_pszTmpFieldValue = VSI_STRDUP_VERBOSE( szTempBuffer );
+        if( m_pszTmpFieldValue == NULL )
+            return "";
+        return m_pszTmpFieldValue;
     }
     else
         return "";
-#undef TEMP_BUFFER_SIZE
 }
 
 /************************************************************************/
@@ -1951,7 +2103,7 @@ const char *OGRFeature::GetFieldAsString( int iField )
  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
  *
  * @return the field value.  This string is internal, and should not be
- * modified, or freed.  Its lifetime may be very brief. 
+ * modified, or freed.  Its lifetime may be very brief.
  */
 
 const char *OGR_F_GetFieldAsString( OGRFeatureH hFeat, int iField )
@@ -1998,7 +2150,7 @@ const int *OGRFeature::GetFieldAsIntegerList( int iField, int *pnCount )
     {
         if( pnCount != NULL )
             *pnCount = 0;
-        
+
         return NULL;
     }
 }
@@ -2012,7 +2164,7 @@ const int *OGRFeature::GetFieldAsIntegerList( int iField, int *pnCount )
  *
  * Currently this function only works for OFTIntegerList fields.
  *
- * This function is the same as the C++ method 
+ * This function is the same as the C++ method
  * OGRFeature::GetFieldAsIntegerList().
  *
  * @param hFeat handle to the feature that owned the field.
@@ -2024,7 +2176,7 @@ const int *OGRFeature::GetFieldAsIntegerList( int iField, int *pnCount )
  * on return the returned pointer may be NULL or non-NULL.
  */
 
-const int *OGR_F_GetFieldAsIntegerList( OGRFeatureH hFeat, int iField, 
+const int *OGR_F_GetFieldAsIntegerList( OGRFeatureH hFeat, int iField,
                                   int *pnCount )
 
 {
@@ -2070,7 +2222,7 @@ const GIntBig *OGRFeature::GetFieldAsInteger64List( int iField, int *pnCount )
     {
         if( pnCount != NULL )
             *pnCount = 0;
-        
+
         return NULL;
     }
 }
@@ -2084,7 +2236,7 @@ const GIntBig *OGRFeature::GetFieldAsInteger64List( int iField, int *pnCount )
  *
  * Currently this function only works for OFTInteger64List fields.
  *
- * This function is the same as the C++ method 
+ * This function is the same as the C++ method
  * OGRFeature::GetFieldAsInteger64List().
  *
  * @param hFeat handle to the feature that owned the field.
@@ -2097,7 +2249,7 @@ const GIntBig *OGRFeature::GetFieldAsInteger64List( int iField, int *pnCount )
  * @since GDAL 2.0
  */
 
-const GIntBig *OGR_F_GetFieldAsInteger64List( OGRFeatureH hFeat, int iField, 
+const GIntBig *OGR_F_GetFieldAsInteger64List( OGRFeatureH hFeat, int iField,
                                   int *pnCount )
 
 {
@@ -2142,7 +2294,7 @@ const double *OGRFeature::GetFieldAsDoubleList( int iField, int *pnCount )
     {
         if( pnCount != NULL )
             *pnCount = 0;
-        
+
         return NULL;
     }
 }
@@ -2156,7 +2308,7 @@ const double *OGRFeature::GetFieldAsDoubleList( int iField, int *pnCount )
  *
  * Currently this function only works for OFTRealList fields.
  *
- * This function is the same as the C++ method 
+ * This function is the same as the C++ method
  * OGRFeature::GetFieldAsDoubleList().
  *
  * @param hFeat handle to the feature that owned the field.
@@ -2168,7 +2320,7 @@ const double *OGRFeature::GetFieldAsDoubleList( int iField, int *pnCount )
  * on return the returned pointer may be NULL or non-NULL.
  */
 
-const double *OGR_F_GetFieldAsDoubleList( OGRFeatureH hFeat, int iField, 
+const double *OGR_F_GetFieldAsDoubleList( OGRFeatureH hFeat, int iField,
                                           int *pnCount )
 
 {
@@ -2204,10 +2356,10 @@ char **OGRFeature::GetFieldAsStringList( int iField )
 
     if( poFDefn == NULL )
         return NULL;
-    
+
     if( !IsFieldSet(iField) )
         return NULL;
-    
+
     if( poFDefn->GetType() == OFTStringList )
     {
         return pauFields[iField].StringList.paList;
@@ -2230,7 +2382,7 @@ char **OGRFeature::GetFieldAsStringList( int iField )
  * The returned list is terminated by a NULL pointer. The number of
  * elements can also be calculated using CSLCount().
  *
- * This function is the same as the C++ method 
+ * This function is the same as the C++ method
  * OGRFeature::GetFieldAsStringList().
  *
  * @param hFeat handle to the feature that owned the field.
@@ -2275,10 +2427,10 @@ GByte *OGRFeature::GetFieldAsBinary( int iField, int *pnBytes )
 
     if( poFDefn == NULL )
         return NULL;
-    
+
     if( !IsFieldSet(iField) )
         return NULL;
-    
+
     if( poFDefn->GetType() == OFTBinary )
     {
         *pnBytes = pauFields[iField].Binary.nCount;
@@ -2304,7 +2456,7 @@ GByte *OGRFeature::GetFieldAsBinary( int iField, int *pnBytes )
  *
  * This method only works for OFTBinary and OFTString fields.
  *
- * This function is the same as the C++ method 
+ * This function is the same as the C++ method
  * OGRFeature::GetFieldAsBinary().
  *
  * @param hFeat handle to the feature that owned the field.
@@ -2357,10 +2509,10 @@ int OGRFeature::GetFieldAsDateTime( int iField,
 
     if( poFDefn == NULL )
         return FALSE;
-    
+
     if( !IsFieldSet(iField) )
         return FALSE;
-    
+
     if( poFDefn->GetType() == OFTDate
         || poFDefn->GetType() == OFTTime
         || poFDefn->GetType() == OFTDateTime )
@@ -2395,10 +2547,10 @@ int OGRFeature::GetFieldAsDateTime( int iField,
                                     int *pnTZFlag )
 {
     float fSecond;
-    int nRet = GetFieldAsDateTime( iField, pnYear, pnMonth, pnDay, pnHour, pnMinute,
+    int bRet = GetFieldAsDateTime( iField, pnYear, pnMonth, pnDay, pnHour, pnMinute,
                                    &fSecond, pnTZFlag);
-    if( pnSecond ) *pnSecond = (int)fSecond;
-    return nRet;
+    if( bRet && pnSecond ) *pnSecond = (int)fSecond;
+    return bRet;
 }
 
 /************************************************************************/
@@ -2410,7 +2562,7 @@ int OGRFeature::GetFieldAsDateTime( int iField,
  *
  * Currently this method only works for OFTDate, OFTTime and OFTDateTime fields.
  *
- * This function is the same as the C++ method 
+ * This function is the same as the C++ method
  * OGRFeature::GetFieldAsDateTime().
  *
  * @param hFeat handle to the feature that owned the field.
@@ -2432,17 +2584,17 @@ int OGR_F_GetFieldAsDateTime( OGRFeatureH hFeat, int iField,
                               int *pnYear, int *pnMonth, int *pnDay,
                               int *pnHour, int *pnMinute, int *pnSecond,
                               int *pnTZFlag )
-    
+
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_GetFieldAsDateTime", 0 );
 
     float fSecond;
-    int nRet =((OGRFeature *)hFeat)->GetFieldAsDateTime( iField,
+    int bRet =((OGRFeature *)hFeat)->GetFieldAsDateTime( iField,
                                                       pnYear, pnMonth, pnDay,
                                                       pnHour, pnMinute,&fSecond,
                                                       pnTZFlag );
-    if( pnSecond ) *pnSecond = (int)fSecond;
-    return nRet;
+    if( bRet && pnSecond ) *pnSecond = (int)fSecond;
+    return bRet;
 }
 
 /************************************************************************/
@@ -2454,7 +2606,7 @@ int OGR_F_GetFieldAsDateTime( OGRFeatureH hFeat, int iField,
  *
  * Currently this method only works for OFTDate, OFTTime and OFTDateTime fields.
  *
- * This function is the same as the C++ method 
+ * This function is the same as the C++ method
  * OGRFeature::GetFieldAsDateTime().
  *
  * @param hFeat handle to the feature that owned the field.
@@ -2475,7 +2627,7 @@ int OGR_F_GetFieldAsDateTimeEx( OGRFeatureH hFeat, int iField,
                                 int *pnYear, int *pnMonth, int *pnDay,
                                 int *pnHour, int *pnMinute, float *pfSecond,
                                 int *pnTZFlag )
-    
+
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_GetFieldAsDateTimeEx", 0 );
 
@@ -2523,7 +2675,7 @@ static int OGRFeatureGetIntegerValue(OGRFieldDefn *poFDefn, int nValue)
 /************************************************************************/
 
 /**
- * \brief Set field to integer value. 
+ * \brief Set field to integer value.
  *
  * OFTInteger, OFTInteger64 and OFTReal fields will be set directly.  OFTString fields
  * will be assigned a string representation of the value, but not necessarily
@@ -2576,12 +2728,27 @@ void OGRFeature::SetField( int iField, int nValue )
     {
         char    szTempBuffer[64];
 
-        sprintf( szTempBuffer, "%d", nValue );
+        snprintf( szTempBuffer, sizeof(szTempBuffer), "%d", nValue );
 
         if( IsFieldSet( iField) )
             CPLFree( pauFields[iField].String );
 
-        pauFields[iField].String = CPLStrdup( szTempBuffer );
+        pauFields[iField].String = VSI_STRDUP_VERBOSE( szTempBuffer );
+        if( pauFields[iField].String == NULL )
+        {
+            pauFields[iField].Set.nMarker1 = OGRUnsetMarker;
+            pauFields[iField].Set.nMarker2 = OGRUnsetMarker;
+        }
+    }
+    else if( eType == OFTStringList )
+    {
+        char    szTempBuffer[64];
+
+        snprintf( szTempBuffer, sizeof(szTempBuffer), "%d", nValue );
+        char   *apszValues[2];
+        apszValues[0] = szTempBuffer;
+        apszValues[1] = NULL;
+        SetField( iField, apszValues);
     }
     else
     {
@@ -2594,7 +2761,7 @@ void OGRFeature::SetField( int iField, int nValue )
 /************************************************************************/
 
 /**
- * \brief Set field to integer value. 
+ * \brief Set field to integer value.
  *
  * OFTInteger, OFTInteger64 and OFTReal fields will be set directly.  OFTString fields
  * will be assigned a string representation of the value, but not necessarily
@@ -2621,7 +2788,7 @@ void OGR_F_SetFieldInteger( OGRFeatureH hFeat, int iField, int nValue )
 /************************************************************************/
 
 /**
- * \brief Set field to 64 bit integer value. 
+ * \brief Set field to 64 bit integer value.
  *
  * OFTInteger, OFTInteger64 and OFTReal fields will be set directly.  OFTString fields
  * will be assigned a string representation of the value, but not necessarily
@@ -2646,11 +2813,14 @@ void OGRFeature::SetField( int iField, GIntBig nValue )
     OGRFieldType eType = poFDefn->GetType();
     if( eType == OFTInteger )
     {
-        int nVal32 = (nValue < INT_MIN ) ? INT_MIN : (nValue > INT_MAX) ? INT_MAX : (int)nValue;
+        int nVal32 = (nValue < INT_MIN ) ? INT_MIN :
+            (nValue > INT_MAX) ? INT_MAX : (int)nValue;
+
         if( (GIntBig)nVal32 != nValue )
         {
-            CPLError(CE_Warning, CPLE_AppDefined,
-                 "Integer overflow occured when trying to set 32bit field.");
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Integer overflow occurred when trying to set "
+                      "32bit field." );
         }
         SetField(iField, nVal32);
     }
@@ -2664,11 +2834,14 @@ void OGRFeature::SetField( int iField, GIntBig nValue )
     }
     else if( eType == OFTIntegerList )
     {
-        int nVal32 = (nValue < INT_MIN ) ? INT_MIN : (nValue > INT_MAX) ? INT_MAX : (int)nValue;
+        int nVal32 = (nValue < INT_MIN ) ? INT_MIN :
+            (nValue > INT_MAX) ? INT_MAX : (int)nValue;
+
         if( (GIntBig)nVal32 != nValue )
         {
-            CPLError(CE_Warning, CPLE_AppDefined,
-                 "Integer overflow occured when trying to set 32bit field.");
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Integer overflow occurred when trying to set "
+                      "32bit field." );
         }
         SetField( iField, 1, &nVal32 );
     }
@@ -2685,12 +2858,27 @@ void OGRFeature::SetField( int iField, GIntBig nValue )
     {
         char    szTempBuffer[64];
 
-        sprintf( szTempBuffer, CPL_FRMT_GIB, nValue );
+        snprintf( szTempBuffer, sizeof(szTempBuffer), CPL_FRMT_GIB, nValue );
 
         if( IsFieldSet( iField) )
             CPLFree( pauFields[iField].String );
 
-        pauFields[iField].String = CPLStrdup( szTempBuffer );
+        pauFields[iField].String = VSI_STRDUP_VERBOSE( szTempBuffer );
+        if( pauFields[iField].String == NULL )
+        {
+            pauFields[iField].Set.nMarker1 = OGRUnsetMarker;
+            pauFields[iField].Set.nMarker2 = OGRUnsetMarker;
+        }
+    }
+    else if( eType == OFTStringList )
+    {
+        char    szTempBuffer[64];
+
+        snprintf( szTempBuffer, sizeof(szTempBuffer), CPL_FRMT_GIB, nValue );
+        char   *apszValues[2];
+        apszValues[0] = szTempBuffer;
+        apszValues[1] = NULL;
+        SetField( iField, apszValues);
     }
     else
     {
@@ -2703,7 +2891,7 @@ void OGRFeature::SetField( int iField, GIntBig nValue )
 /************************************************************************/
 
 /**
- * \brief Set field to 64 bit integer value. 
+ * \brief Set field to 64 bit integer value.
  *
  * OFTInteger, OFTInteger64 and OFTReal fields will be set directly.  OFTString fields
  * will be assigned a string representation of the value, but not necessarily
@@ -2731,7 +2919,7 @@ void OGR_F_SetFieldInteger64( OGRFeatureH hFeat, int iField, GIntBig nValue )
 /************************************************************************/
 
 /**
- * \brief Set field to double value. 
+ * \brief Set field to double value.
  *
  * OFTInteger, OFTInteger64 and OFTReal fields will be set directly.  OFTString fields
  * will be assigned a string representation of the value, but not necessarily
@@ -2747,11 +2935,11 @@ void OGR_F_SetFieldInteger64( OGRFeatureH hFeat, int iField, GIntBig nValue )
 void OGRFeature::SetField( int iField, double dfValue )
 
 {
-    OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
+    OGRFieldDefn *poFDefn = poDefn->GetFieldDefn( iField );
 
     if( poFDefn == NULL )
         return;
-    
+
     OGRFieldType eType = poFDefn->GetType();
     if( eType == OFTReal )
     {
@@ -2790,12 +2978,25 @@ void OGRFeature::SetField( int iField, double dfValue )
     {
         char    szTempBuffer[128];
 
-        CPLsprintf( szTempBuffer, "%.16g", dfValue );
+        CPLsnprintf( szTempBuffer, sizeof(szTempBuffer), "%.16g", dfValue );
 
         if( IsFieldSet( iField) )
             CPLFree( pauFields[iField].String );
 
-        pauFields[iField].String = CPLStrdup( szTempBuffer );
+        pauFields[iField].String = VSI_STRDUP_VERBOSE( szTempBuffer );
+        if( pauFields[iField].String == NULL )
+        {
+            pauFields[iField].Set.nMarker1 = OGRUnsetMarker;
+            pauFields[iField].Set.nMarker2 = OGRUnsetMarker;
+        }
+    }
+    else if( eType == OFTStringList )
+    {
+        char    szTempBuffer[64];
+
+        CPLsnprintf( szTempBuffer, sizeof(szTempBuffer), "%.16g", dfValue );
+        char   *apszValues[2] = {szTempBuffer, NULL};
+        SetField( iField, apszValues);
     }
     else
     {
@@ -2808,7 +3009,7 @@ void OGRFeature::SetField( int iField, double dfValue )
 /************************************************************************/
 
 /**
- * \brief Set field to double value. 
+ * \brief Set field to double value.
  *
  * OFTInteger, OFTInteger64 and OFTReal fields will be set directly.  OFTString fields
  * will be assigned a string representation of the value, but not necessarily
@@ -2835,7 +3036,7 @@ void OGR_F_SetFieldDouble( OGRFeatureH hFeat, int iField, double dfValue )
 /************************************************************************/
 
 /**
- * \brief Set field to string value. 
+ * \brief Set field to string value.
  *
  * OFTInteger fields will be set based on an atoi() conversion of the string.
  * OFTInteger64 fields will be set based on an CPLAtoGIntBig() conversion of the string.
@@ -2860,20 +3061,25 @@ void OGRFeature::SetField( int iField, const char * pszValue )
 
     if( poFDefn == NULL )
         return;
-    
+
     OGRFieldType eType = poFDefn->GetType();
     if( eType == OFTString )
     {
         if( IsFieldSet(iField) )
             CPLFree( pauFields[iField].String );
-            
-        pauFields[iField].String = CPLStrdup( pszValue );
+
+        pauFields[iField].String = VSI_STRDUP_VERBOSE( pszValue ? pszValue : "" );
+        if( pauFields[iField].String == NULL )
+        {
+            pauFields[iField].Set.nMarker1 = OGRUnsetMarker;
+            pauFields[iField].Set.nMarker2 = OGRUnsetMarker;
+        }
     }
     else if( eType == OFTInteger )
     {
         errno = 0; /* As allowed by C standard, some systems like MSVC doesn't reset errno */
         long nVal = strtol(pszValue, &pszLast, 10);
-        nVal = OGRFeatureGetIntegerValue(poFDefn, nVal);
+        nVal = OGRFeatureGetIntegerValue(poFDefn, (int)nVal);
         pauFields[iField].Integer = (nVal > INT_MAX) ? INT_MAX : (nVal < INT_MIN) ? INT_MIN : (int) nVal;
         if( bWarn && (errno == ERANGE || nVal != (long)pauFields[iField].Integer || !pszLast || *pszLast ) )
             CPLError(CE_Warning, CPLE_AppDefined,
@@ -2893,7 +3099,7 @@ void OGRFeature::SetField( int iField, const char * pszValue )
                       "Value '%s' of field %s.%s parsed incompletely to real %.16g.",
                       pszValue, poDefn->GetName(), poFDefn->GetNameRef(), pauFields[iField].Real );
     }
-    else if( eType == OFTDate 
+    else if( eType == OFTDate
              || eType == OFTTime
              || eType == OFTDateTime )
     {
@@ -2902,19 +3108,19 @@ void OGRFeature::SetField( int iField, const char * pszValue )
         if( OGRParseDate( pszValue, &sWrkField, 0 ) )
             memcpy( pauFields+iField, &sWrkField, sizeof(sWrkField));
     }
-    else if( eType == OFTIntegerList 
-             || eType == OFTInteger64List 
+    else if( eType == OFTIntegerList
+             || eType == OFTInteger64List
              || eType == OFTRealList )
     {
         char **papszValueList = NULL;
 
         if( pszValue[0] == '(' && strchr(pszValue,':') != NULL )
         {
-            papszValueList = CSLTokenizeString2( 
+            papszValueList = CSLTokenizeString2(
                 pszValue, ",:()", 0 );
         }
 
-        if( CSLCount(papszValueList) == 0
+        if( papszValueList == NULL || *papszValueList == NULL
             || atoi(papszValueList[0]) != CSLCount(papszValueList)-1 )
         {
             /* do nothing - the count does not match entries */
@@ -2972,9 +3178,10 @@ void OGRFeature::SetField( int iField, const char * pszValue )
     {
         if( pszValue && *pszValue )
         {
-            if( pszValue[0] == '(' && strchr(pszValue,':') != NULL )
+            if( pszValue[0] == '(' && strchr(pszValue,':') != NULL &&
+                pszValue[strlen(pszValue)-1] == ')' )
             {
-                char** papszValueList = CSLTokenizeString2( 
+                char** papszValueList = CSLTokenizeString2(
                                                         pszValue, ",:()", 0 );
                 int i, nCount = atoi(papszValueList[0]);
                 std::vector<char*> aosValues;
@@ -2989,7 +3196,7 @@ void OGRFeature::SetField( int iField, const char * pszValue )
             }
             else
             {
-                const char *papszValues[2] = { pszValue, 0 };
+                const char *papszValues[2] = { pszValue, NULL };
                 SetField( iField, (char **) papszValues );
             }
         }
@@ -3005,7 +3212,7 @@ void OGRFeature::SetField( int iField, const char * pszValue )
 /************************************************************************/
 
 /**
- * \brief Set field to string value. 
+ * \brief Set field to string value.
  *
  * OFTInteger fields will be set based on an atoi() conversion of the string.
  * OFTInteger64 fields will be set based on an CPLAtoGIntBig() conversion of the string.
@@ -3032,7 +3239,7 @@ void OGR_F_SetFieldString( OGRFeatureH hFeat, int iField, const char *pszValue)
 /************************************************************************/
 
 /**
- * \brief Set field to list of integers value. 
+ * \brief Set field to list of integers value.
  *
  * This method currently on has an effect of OFTIntegerList, OFTInteger64List
  * and OFTRealList fields.
@@ -3051,8 +3258,9 @@ void OGRFeature::SetField( int iField, int nCount, int *panValues )
 
     if( poFDefn == NULL )
         return;
-    
-    if( poFDefn->GetType() == OFTIntegerList )
+
+    OGRFieldType eType = poFDefn->GetType();
+    if( eType == OFTIntegerList )
     {
         OGRField        uField;
         int            *panValuesMod = NULL;
@@ -3066,7 +3274,9 @@ void OGRFeature::SetField( int iField, int nCount, int *panValues )
                 {
                     if( panValuesMod == NULL )
                     {
-                        panValuesMod = (int*)CPLMalloc(nCount * sizeof(int));
+                        panValuesMod = (int*)VSI_MALLOC_VERBOSE(nCount * sizeof(int));
+                        if( panValuesMod == NULL )
+                            return;
                         memcpy(panValuesMod, panValues, nCount * sizeof(int));
                     }
                     panValuesMod[i] = nVal;
@@ -3081,7 +3291,7 @@ void OGRFeature::SetField( int iField, int nCount, int *panValues )
         SetField( iField, &uField );
         CPLFree(panValuesMod);
     }
-    else if( poFDefn->GetType() == OFTInteger64List )
+    else if( eType == OFTInteger64List )
     {
         std::vector<GIntBig> anValues;
 
@@ -3090,7 +3300,7 @@ void OGRFeature::SetField( int iField, int nCount, int *panValues )
 
         SetField( iField, nCount, &anValues[0] );
     }
-    else if( poFDefn->GetType() == OFTRealList )
+    else if( eType == OFTRealList )
     {
         std::vector<double> adfValues;
 
@@ -3099,13 +3309,24 @@ void OGRFeature::SetField( int iField, int nCount, int *panValues )
 
         SetField( iField, nCount, &adfValues[0] );
     }
-    else if( (poFDefn->GetType() == OFTInteger ||
-              poFDefn->GetType() == OFTInteger64 || 
-              poFDefn->GetType() == OFTReal)
+    else if( (eType == OFTInteger ||
+              eType == OFTInteger64 ||
+              eType == OFTReal)
              && nCount == 1 )
     {
         SetField( iField, panValues[0] );
     }
+    else if( eType == OFTStringList )
+    {
+        char** papszValues = (char**)VSI_MALLOC_VERBOSE((nCount+1) * sizeof(char*));
+        if( papszValues == NULL )
+            return;
+        for( int i=0; i < nCount; i++ )
+            papszValues[i] = VSI_STRDUP_VERBOSE(CPLSPrintf("%d", panValues[i]));
+        papszValues[nCount] = NULL;
+        SetField( iField, papszValues);
+        CSLDestroy(papszValues);
+    }
 }
 
 /************************************************************************/
@@ -3113,7 +3334,7 @@ void OGRFeature::SetField( int iField, int nCount, int *panValues )
 /************************************************************************/
 
 /**
- * \brief Set field to list of integers value. 
+ * \brief Set field to list of integers value.
  *
  * This function currently on has an effect of OFTIntegerList, OFTInteger64List
  * and OFTRealList fields.
@@ -3126,7 +3347,7 @@ void OGRFeature::SetField( int iField, int nCount, int *panValues )
  * @param panValues the values to assign.
  */
 
-void OGR_F_SetFieldIntegerList( OGRFeatureH hFeat, int iField, 
+void OGR_F_SetFieldIntegerList( OGRFeatureH hFeat, int iField,
                                 int nCount, int *panValues )
 
 {
@@ -3140,7 +3361,7 @@ void OGR_F_SetFieldIntegerList( OGRFeatureH hFeat, int iField,
 /************************************************************************/
 
 /**
- * \brief Set field to list of 64 bit integers value. 
+ * \brief Set field to list of 64 bit integers value.
  *
  * This method currently on has an effect of OFTIntegerList, OFTInteger64List
  * and OFTRealList fields.
@@ -3160,26 +3381,30 @@ void OGRFeature::SetField( int iField, int nCount, const GIntBig *panValues )
 
     if( poFDefn == NULL )
         return;
-    
-    if( poFDefn->GetType() == OFTIntegerList )
+
+    OGRFieldType eType = poFDefn->GetType();
+    if( eType == OFTIntegerList )
     {
         std::vector<int> anValues;
 
         for( int i=0; i < nCount; i++ )
         {
             GIntBig nValue = panValues[i];
-            int nVal32 = (nValue < INT_MIN ) ? INT_MIN : (nValue > INT_MAX) ? INT_MAX : (int)nValue;
+            int nVal32 = (nValue < INT_MIN ) ? INT_MIN :
+                (nValue > INT_MAX) ? INT_MAX : (int)nValue;
+
             if( (GIntBig)nVal32 != nValue )
             {
-                CPLError(CE_Warning, CPLE_AppDefined,
-                     "Integer overflow occured when trying to set 32bit field.");
+                CPLError( CE_Warning, CPLE_AppDefined,
+                          "Integer overflow occurred when trying to set "
+                          "32bit field." );
             }
             anValues.push_back( nVal32 );
         }
 
         SetField( iField, nCount, &anValues[0] );
     }
-    else if( poFDefn->GetType() == OFTInteger64List )
+    else if( eType == OFTInteger64List )
     {
         OGRField uField;
         uField.Integer64List.nCount = nCount;
@@ -3188,7 +3413,7 @@ void OGRFeature::SetField( int iField, int nCount, const GIntBig *panValues )
 
         SetField( iField, &uField );
     }
-    else if( poFDefn->GetType() == OFTRealList )
+    else if( eType == OFTRealList )
     {
         std::vector<double> adfValues;
 
@@ -3197,13 +3422,24 @@ void OGRFeature::SetField( int iField, int nCount, const GIntBig *panValues )
 
         SetField( iField, nCount, &adfValues[0] );
     }
-    else if( (poFDefn->GetType() == OFTInteger ||
-              poFDefn->GetType() == OFTInteger64 ||
-              poFDefn->GetType() == OFTReal)
+    else if( (eType == OFTInteger ||
+              eType == OFTInteger64 ||
+              eType == OFTReal)
              && nCount == 1 )
     {
         SetField( iField, panValues[0] );
     }
+    else if( eType == OFTStringList )
+    {
+        char** papszValues = (char**)VSI_MALLOC_VERBOSE((nCount+1) * sizeof(char*));
+        if( papszValues == NULL )
+            return;
+        for( int i=0; i < nCount; i++ )
+            papszValues[i] = VSI_STRDUP_VERBOSE(CPLSPrintf(CPL_FRMT_GIB, panValues[i]));
+        papszValues[nCount] = NULL;
+        SetField( iField, papszValues);
+        CSLDestroy(papszValues);
+    }
 }
 
 /************************************************************************/
@@ -3211,7 +3447,7 @@ void OGRFeature::SetField( int iField, int nCount, const GIntBig *panValues )
 /************************************************************************/
 
 /**
- * \brief Set field to list of 64 bit integers value. 
+ * \brief Set field to list of 64 bit integers value.
  *
  * This function currently on has an effect of OFTIntegerList, OFTInteger64List
  * and OFTRealList fields.
@@ -3225,7 +3461,7 @@ void OGRFeature::SetField( int iField, int nCount, const GIntBig *panValues )
  * @since GDAL 2.0
  */
 
-void OGR_F_SetFieldInteger64List( OGRFeatureH hFeat, int iField, 
+void OGR_F_SetFieldInteger64List( OGRFeatureH hFeat, int iField,
                                 int nCount, const GIntBig *panValues )
 
 {
@@ -3239,7 +3475,7 @@ void OGR_F_SetFieldInteger64List( OGRFeatureH hFeat, int iField,
 /************************************************************************/
 
 /**
- * \brief Set field to list of doubles value. 
+ * \brief Set field to list of doubles value.
  *
  * This method currently on has an effect of OFTIntegerList, OFTInteger64List,
  * OFTRealList fields.
@@ -3258,18 +3494,19 @@ void OGRFeature::SetField( int iField, int nCount, double * padfValues )
 
     if( poFDefn == NULL )
         return;
-    
-    if( poFDefn->GetType() == OFTRealList )
+
+    OGRFieldType eType = poFDefn->GetType();
+    if( eType == OFTRealList )
     {
         OGRField        uField;
-        
+
         uField.RealList.nCount = nCount;
         uField.Set.nMarker2 = 0;
         uField.RealList.paList = padfValues;
-        
+
         SetField( iField, &uField );
     }
-    else if( poFDefn->GetType() == OFTIntegerList )
+    else if( eType == OFTIntegerList )
     {
         std::vector<int> anValues;
 
@@ -3278,7 +3515,7 @@ void OGRFeature::SetField( int iField, int nCount, double * padfValues )
 
         SetField( iField, nCount, &anValues[0] );
     }
-    else if( poFDefn->GetType() == OFTInteger64List )
+    else if( eType == OFTInteger64List )
     {
         std::vector<GIntBig> anValues;
 
@@ -3287,13 +3524,24 @@ void OGRFeature::SetField( int iField, int nCount, double * padfValues )
 
         SetField( iField, nCount, &anValues[0] );
     }
-    else if( (poFDefn->GetType() == OFTInteger ||
-              poFDefn->GetType() == OFTInteger64 || 
-              poFDefn->GetType() == OFTReal)
+    else if( (eType == OFTInteger ||
+              eType == OFTInteger64 ||
+              eType == OFTReal)
              && nCount == 1 )
     {
         SetField( iField, padfValues[0] );
     }
+    else if( eType == OFTStringList )
+    {
+        char** papszValues = (char**)VSI_MALLOC_VERBOSE((nCount+1) * sizeof(char*));
+        if( papszValues == NULL )
+            return;
+        for( int i=0; i < nCount; i++ )
+            papszValues[i] = VSI_STRDUP_VERBOSE(CPLSPrintf("%.16g", padfValues[i]));
+        papszValues[nCount] = NULL;
+        SetField( iField, papszValues);
+        CSLDestroy(papszValues);
+    }
 }
 
 /************************************************************************/
@@ -3301,7 +3549,7 @@ void OGRFeature::SetField( int iField, int nCount, double * padfValues )
 /************************************************************************/
 
 /**
- * \brief Set field to list of doubles value. 
+ * \brief Set field to list of doubles value.
  *
  * This function currently on has an effect of OFTIntegerList, OFTInteger64List,
  * OFTRealList fields.
@@ -3314,7 +3562,7 @@ void OGRFeature::SetField( int iField, int nCount, double * padfValues )
  * @param padfValues the values to assign.
  */
 
-void OGR_F_SetFieldDoubleList( OGRFeatureH hFeat, int iField, 
+void OGR_F_SetFieldDoubleList( OGRFeatureH hFeat, int iField,
                                int nCount, double *padfValues )
 
 {
@@ -3328,7 +3576,7 @@ void OGR_F_SetFieldDoubleList( OGRFeatureH hFeat, int iField,
 /************************************************************************/
 
 /**
- * \brief Set field to list of strings value. 
+ * \brief Set field to list of strings value.
  *
  * This method currently on has an effect of OFTStringList fields.
  *
@@ -3345,17 +3593,69 @@ void OGRFeature::SetField( int iField, char ** papszValues )
 
     if( poFDefn == NULL )
         return;
-    
-    if( poFDefn->GetType() == OFTStringList )
+
+    OGRFieldType eType = poFDefn->GetType();
+    if( eType == OFTStringList )
     {
         OGRField        uField;
-        
+
         uField.StringList.nCount = CSLCount(papszValues);
         uField.Set.nMarker2 = 0;
         uField.StringList.paList = papszValues;
 
         SetField( iField, &uField );
     }
+    else if( eType == OFTIntegerList )
+    {
+        int nValues = CSLCount(papszValues);
+        int* panValues = (int*)VSI_MALLOC_VERBOSE(nValues * sizeof(int));
+        if( panValues == NULL )
+            return;
+        for(int i=0;i<nValues;i++)
+        {
+            errno = 0; /* As allowed by C standard, some systems like MSVC doesn't reset errno */
+            int nVal = atoi(papszValues[i]);
+            if( errno == ERANGE )
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "32 bit integer overflow when converting %s",
+                         papszValues[i]);
+                if( papszValues[i][0] == '-' )
+                    nVal = INT_MIN;
+                else
+                    nVal = INT_MAX;
+            }
+            panValues[i] = nVal;
+        }
+        SetField( iField, nValues, panValues );
+        CPLFree(panValues);
+    }
+    else if( eType == OFTInteger64List )
+    {
+        int nValues = CSLCount(papszValues);
+        GIntBig* panValues = (GIntBig*)VSI_MALLOC_VERBOSE(nValues * sizeof(GIntBig));
+        if( panValues == NULL )
+            return;
+        for(int i=0;i<nValues;i++)
+        {
+            panValues[i] = CPLAtoGIntBigEx(papszValues[i], TRUE, NULL);
+        }
+        SetField( iField, nValues, panValues );
+        CPLFree(panValues);
+    }
+    else if( eType == OFTRealList )
+    {
+        int nValues = CSLCount(papszValues);
+        double* padfValues = (double*)VSI_MALLOC_VERBOSE(nValues * sizeof(double));
+        if( padfValues == NULL )
+            return;
+        for(int i=0;i<nValues;i++)
+        {
+            padfValues[i] = CPLAtof(papszValues[i]);
+        }
+        SetField( iField, nValues, padfValues );
+        CPLFree(padfValues);
+    }
 }
 
 /************************************************************************/
@@ -3363,7 +3663,7 @@ void OGRFeature::SetField( int iField, char ** papszValues )
 /************************************************************************/
 
 /**
- * \brief Set field to list of strings value. 
+ * \brief Set field to list of strings value.
  *
  * This function currently on has an effect of OFTStringList fields.
  *
@@ -3374,7 +3674,7 @@ void OGRFeature::SetField( int iField, char ** papszValues )
  * @param papszValues the values to assign.
  */
 
-void OGR_F_SetFieldStringList( OGRFeatureH hFeat, int iField, 
+void OGR_F_SetFieldStringList( OGRFeatureH hFeat, int iField,
                                char ** papszValues )
 
 {
@@ -3396,7 +3696,7 @@ void OGR_F_SetFieldStringList( OGRFeatureH hFeat, int iField,
  *
  * @param iField the field to set, from 0 to GetFieldCount()-1.
  * @param nBytes bytes of data being set.
- * @param pabyData the raw data being applied. 
+ * @param pabyData the raw data being applied.
  */
 
 void OGRFeature::SetField( int iField, int nBytes, GByte *pabyData )
@@ -3406,8 +3706,9 @@ void OGRFeature::SetField( int iField, int nBytes, GByte *pabyData )
 
     if( poFDefn == NULL )
         return;
-    
-    if( poFDefn->GetType() == OFTBinary )
+
+    OGRFieldType eType = poFDefn->GetType();
+    if( eType == OFTBinary )
     {
         OGRField        uField;
 
@@ -3417,9 +3718,11 @@ void OGRFeature::SetField( int iField, int nBytes, GByte *pabyData )
 
         SetField( iField, &uField );
     }
-    else if( poFDefn->GetType() == OFTString )
+    else if( eType == OFTString || eType == OFTStringList )
     {
-        char* pszStr = (char*)CPLMalloc(nBytes + 1);
+        char* pszStr = (char*)VSI_MALLOC_VERBOSE(nBytes + 1);
+        if( pszStr == NULL )
+            return;
         memcpy(pszStr, pabyData, nBytes);
         pszStr[nBytes] = 0;
         SetField( iField, pszStr );
@@ -3444,7 +3747,7 @@ void OGRFeature::SetField( int iField, int nBytes, GByte *pabyData )
  * @param pabyData the data to apply.
  */
 
-void OGR_F_SetFieldBinary( OGRFeatureH hFeat, int iField, 
+void OGR_F_SetFieldBinary( OGRFeatureH hFeat, int iField,
                            int nBytes, GByte *pabyData )
 
 {
@@ -3476,7 +3779,7 @@ void OGR_F_SetFieldBinary( OGRFeatureH hFeat, int iField,
  */
 
 void OGRFeature::SetField( int iField, int nYear, int nMonth, int nDay,
-                           int nHour, int nMinute, float fSecond, 
+                           int nHour, int nMinute, float fSecond,
                            int nTZFlag )
 
 {
@@ -3484,10 +3787,11 @@ void OGRFeature::SetField( int iField, int nYear, int nMonth, int nDay,
 
     if( poFDefn == NULL )
         return;
-    
-    if( poFDefn->GetType() == OFTDate 
-        || poFDefn->GetType() == OFTTime 
-        || poFDefn->GetType() == OFTDateTime )
+
+    OGRFieldType eType = poFDefn->GetType();
+    if( eType == OFTDate
+        || eType == OFTTime
+        || eType == OFTDateTime )
     {
         if( (GInt16)nYear != nYear )
         {
@@ -3504,6 +3808,19 @@ void OGRFeature::SetField( int iField, int nYear, int nMonth, int nDay,
         pauFields[iField].Date.Second = fSecond;
         pauFields[iField].Date.TZFlag = (GByte)nTZFlag;
     }
+    else if( eType == OFTString || eType == OFTStringList )
+    {
+        char szTempBuffer[TEMP_BUFFER_SIZE];
+        OGRFeatureFormatDateTimeBuffer(szTempBuffer,
+                                       nYear,
+                                       nMonth,
+                                       nDay,
+                                       nHour,
+                                       nMinute,
+                                       fSecond,
+                                       nTZFlag);
+        SetField( iField, szTempBuffer );
+    }
 }
 
 /************************************************************************/
@@ -3529,9 +3846,9 @@ void OGRFeature::SetField( int iField, int nYear, int nMonth, int nDay,
  * @see Use OGR_F_SetFieldDateTimeEx() for second with millisecond accuracy.
  */
 
-void OGR_F_SetFieldDateTime( OGRFeatureH hFeat, int iField, 
+void OGR_F_SetFieldDateTime( OGRFeatureH hFeat, int iField,
                              int nYear, int nMonth, int nDay,
-                             int nHour, int nMinute, int nSecond, 
+                             int nHour, int nMinute, int nSecond,
                              int nTZFlag )
 
 
@@ -3539,7 +3856,7 @@ void OGR_F_SetFieldDateTime( OGRFeatureH hFeat, int iField,
     VALIDATE_POINTER0( hFeat, "OGR_F_SetFieldDateTime" );
 
     ((OGRFeature *)hFeat)->SetField( iField, nYear, nMonth, nDay,
-                                     nHour, nMinute, nSecond, nTZFlag );
+                                     nHour, nMinute, static_cast<float>(nSecond), nTZFlag );
 }
 
 /************************************************************************/
@@ -3565,9 +3882,9 @@ void OGR_F_SetFieldDateTime( OGRFeatureH hFeat, int iField,
  * @since GDAL 2.0
  */
 
-void OGR_F_SetFieldDateTimeEx( OGRFeatureH hFeat, int iField, 
+void OGR_F_SetFieldDateTimeEx( OGRFeatureH hFeat, int iField,
                              int nYear, int nMonth, int nDay,
-                             int nHour, int nMinute, float fSecond, 
+                             int nHour, int nMinute, float fSecond,
                              int nTZFlag )
 
 
@@ -3588,7 +3905,7 @@ void OGR_F_SetFieldDateTimeEx( OGRFeatureH hFeat, int iField,
  * The passed value OGRField must be of exactly the same type as the
  * target field, or an application crash may occur.  The passed value
  * is copied, and will not be affected.  It remains the responsibility of
- * the caller. 
+ * the caller.
  *
  * This method is the same as the C function OGR_F_SetFieldRaw().
  *
@@ -3599,11 +3916,16 @@ void OGR_F_SetFieldDateTimeEx( OGRFeatureH hFeat, int iField,
 void OGRFeature::SetField( int iField, OGRField * puValue )
 
 {
-    OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
+    SetFieldInternal( iField, puValue );
+}
 
+bool OGRFeature::SetFieldInternal( int iField, OGRField * puValue )
+
+{
+    OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
     if( poFDefn == NULL )
-        return;
-    
+        return false;
+
     if( poFDefn->GetType() == OFTInteger )
     {
         pauFields[iField] = *puValue;
@@ -3624,14 +3946,22 @@ void OGRFeature::SetField( int iField, OGRField * puValue )
     {
         if( IsFieldSet( iField ) )
             CPLFree( pauFields[iField].String );
-        
+
         if( puValue->String == NULL )
             pauFields[iField].String = NULL;
         else if( puValue->Set.nMarker1 == OGRUnsetMarker
                  && puValue->Set.nMarker2 == OGRUnsetMarker )
             pauFields[iField] = *puValue;
         else
-            pauFields[iField].String = CPLStrdup( puValue->String );
+        {
+            pauFields[iField].String = VSI_STRDUP_VERBOSE( puValue->String );
+            if( pauFields[iField].String == NULL )
+            {
+                pauFields[iField].Set.nMarker1 = OGRUnsetMarker;
+                pauFields[iField].Set.nMarker2 = OGRUnsetMarker;
+                return false;
+            }
+        }
     }
     else if( poFDefn->GetType() == OFTDate
              || poFDefn->GetType() == OFTTime
@@ -3642,10 +3972,10 @@ void OGRFeature::SetField( int iField, OGRField * puValue )
     else if( poFDefn->GetType() == OFTIntegerList )
     {
         int     nCount = puValue->IntegerList.nCount;
-        
+
         if( IsFieldSet( iField ) )
             CPLFree( pauFields[iField].IntegerList.paList );
-        
+
         if( puValue->Set.nMarker1 == OGRUnsetMarker
             && puValue->Set.nMarker2 == OGRUnsetMarker )
         {
@@ -3654,7 +3984,13 @@ void OGRFeature::SetField( int iField, OGRField * puValue )
         else
         {
             pauFields[iField].IntegerList.paList =
-                (int *) CPLMalloc(sizeof(int) * nCount);
+                (int *) VSI_MALLOC_VERBOSE(sizeof(int) * nCount);
+            if( pauFields[iField].IntegerList.paList == NULL )
+            {
+                pauFields[iField].Set.nMarker1 = OGRUnsetMarker;
+                pauFields[iField].Set.nMarker2 = OGRUnsetMarker;
+                return false;
+            }
             memcpy( pauFields[iField].IntegerList.paList,
                     puValue->IntegerList.paList,
                     sizeof(int) * nCount );
@@ -3664,10 +4000,10 @@ void OGRFeature::SetField( int iField, OGRField * puValue )
     else if( poFDefn->GetType() == OFTInteger64List )
     {
         int     nCount = puValue->Integer64List.nCount;
-        
+
         if( IsFieldSet( iField ) )
             CPLFree( pauFields[iField].Integer64List.paList );
-        
+
         if( puValue->Set.nMarker1 == OGRUnsetMarker
             && puValue->Set.nMarker2 == OGRUnsetMarker )
         {
@@ -3676,7 +4012,13 @@ void OGRFeature::SetField( int iField, OGRField * puValue )
         else
         {
             pauFields[iField].Integer64List.paList =
-                (GIntBig *) CPLMalloc(sizeof(GIntBig) * nCount);
+                (GIntBig *) VSI_MALLOC_VERBOSE(sizeof(GIntBig) * nCount);
+            if( pauFields[iField].Integer64List.paList == NULL )
+            {
+                pauFields[iField].Set.nMarker1 = OGRUnsetMarker;
+                pauFields[iField].Set.nMarker2 = OGRUnsetMarker;
+                return false;
+            }
             memcpy( pauFields[iField].Integer64List.paList,
                     puValue->Integer64List.paList,
                     sizeof(GIntBig) * nCount );
@@ -3698,7 +4040,13 @@ void OGRFeature::SetField( int iField, OGRField * puValue )
         else
         {
             pauFields[iField].RealList.paList =
-                (double *) CPLMalloc(sizeof(double) * nCount);
+                (double *) VSI_MALLOC_VERBOSE(sizeof(double) * nCount);
+            if( pauFields[iField].RealList.paList == NULL )
+            {
+                pauFields[iField].Set.nMarker1 = OGRUnsetMarker;
+                pauFields[iField].Set.nMarker2 = OGRUnsetMarker;
+                return false;
+            }
             memcpy( pauFields[iField].RealList.paList,
                     puValue->RealList.paList,
                     sizeof(double) * nCount );
@@ -3709,7 +4057,7 @@ void OGRFeature::SetField( int iField, OGRField * puValue )
     {
         if( IsFieldSet( iField ) )
             CSLDestroy( pauFields[iField].StringList.paList );
-        
+
         if( puValue->Set.nMarker1 == OGRUnsetMarker
             && puValue->Set.nMarker2 == OGRUnsetMarker )
         {
@@ -3717,9 +4065,21 @@ void OGRFeature::SetField( int iField, OGRField * puValue )
         }
         else
         {
-            pauFields[iField].StringList.paList =
-                CSLDuplicate( puValue->StringList.paList );
-            
+            char** papszNewList = NULL;
+            char** papszIter = puValue->StringList.paList;
+            for(; papszIter != NULL && *papszIter != NULL; ++papszIter )
+            {
+                char** papszNewList2 = CSLAddStringMayFail(papszNewList, *papszIter);
+                if( papszNewList2 == NULL )
+                {
+                    CSLDestroy(papszNewList);
+                    pauFields[iField].Set.nMarker1 = OGRUnsetMarker;
+                    pauFields[iField].Set.nMarker2 = OGRUnsetMarker;
+                    return false;
+                }
+                papszNewList = papszNewList2;
+            }
+            pauFields[iField].StringList.paList = papszNewList;
             pauFields[iField].StringList.nCount = puValue->StringList.nCount;
             CPLAssert( CSLCount(puValue->StringList.paList)
                        == puValue->StringList.nCount );
@@ -3729,7 +4089,7 @@ void OGRFeature::SetField( int iField, OGRField * puValue )
     {
         if( IsFieldSet( iField ) )
             CPLFree( pauFields[iField].Binary.paData );
-        
+
         if( puValue->Set.nMarker1 == OGRUnsetMarker
             && puValue->Set.nMarker2 == OGRUnsetMarker )
         {
@@ -3737,18 +4097,25 @@ void OGRFeature::SetField( int iField, OGRField * puValue )
         }
         else
         {
-            pauFields[iField].Binary.nCount = puValue->Binary.nCount;
             pauFields[iField].Binary.paData =
-                (GByte *) CPLMalloc(puValue->Binary.nCount);
+                (GByte *) VSI_MALLOC_VERBOSE(puValue->Binary.nCount);
+            if( pauFields[iField].Binary.paData == NULL )
+            {
+                pauFields[iField].Set.nMarker1 = OGRUnsetMarker;
+                pauFields[iField].Set.nMarker2 = OGRUnsetMarker;
+                return false;
+            }
             memcpy( pauFields[iField].Binary.paData,
                     puValue->Binary.paData,
                     puValue->Binary.nCount );
+            pauFields[iField].Binary.nCount = puValue->Binary.nCount;
         }
     }
     else
     {
         /* do nothing for other field types */
     }
+    return true;
 }
 
 /************************************************************************/
@@ -3761,7 +4128,7 @@ void OGRFeature::SetField( int iField, OGRField * puValue )
  * The passed value OGRField must be of exactly the same type as the
  * target field, or an application crash may occur.  The passed value
  * is copied, and will not be affected.  It remains the responsibility of
- * the caller. 
+ * the caller.
  *
  * This function is the same as the C++ method OGRFeature::SetField().
  *
@@ -3800,7 +4167,7 @@ void OGR_F_SetFieldRaw( OGRFeatureH hFeat, int iField, OGRField *psValue )
  * This method is the same as the C function OGR_F_DumpReadable().
  *
  * @param fpOut the stream to write to, such as stdout.  If NULL stdout will
- * be used. 
+ * be used.
  * @param papszOptions NULL terminated list of options (may be NULL)
  */
 
@@ -3951,16 +4318,16 @@ GIntBig OGR_F_GetFID( OGRFeatureH hFeat )
  *
  * This method is the same as the C function OGR_F_SetFID().
  *
- * @param nFID the new feature identifier value to assign.
+ * @param nFIDIn the new feature identifier value to assign.
  *
- * @return On success OGRERR_NONE, or on failure some other value. 
+ * @return On success OGRERR_NONE, or on failure some other value.
  */
 
-OGRErr OGRFeature::SetFID( GIntBig nFID )
+OGRErr OGRFeature::SetFID( GIntBig nFIDIn )
 
 {
-    this->nFID = nFID;
-    
+    nFID = nFIDIn;
+
     return OGRERR_NONE;
 }
 
@@ -3981,13 +4348,13 @@ OGRErr OGRFeature::SetFID( GIntBig nFID )
  * @param hFeat handle to the feature to set the feature id to.
  * @param nFID the new feature identifier value to assign.
  *
- * @return On success OGRERR_NONE, or on failure some other value. 
+ * @return On success OGRERR_NONE, or on failure some other value.
  */
 
 OGRErr OGR_F_SetFID( OGRFeatureH hFeat, GIntBig nFID )
 
 {
-    VALIDATE_POINTER1( hFeat, "OGR_F_SetFID", CE_Failure );
+    VALIDATE_POINTER1( hFeat, "OGR_F_SetFID", OGRERR_FAILURE );
 
     return ((OGRFeature *) hFeat)->SetFID(nFID);
 }
@@ -4018,7 +4385,7 @@ OGRBoolean OGRFeature::Equal( OGRFeature * poFeature )
 
     if( GetFID() != poFeature->GetFID() )
         return FALSE;
-    
+
     if( GetDefnRef() != poFeature->GetDefnRef() )
         return FALSE;
 
@@ -4039,7 +4406,7 @@ OGRBoolean OGRFeature::Equal( OGRFeature * poFeature )
                        poFeature->GetFieldAsInteger(i) )
                     return FALSE;
                 break;
-                
+
             case OFTInteger64:
                 if( GetFieldAsInteger64(i) !=
                        poFeature->GetFieldAsInteger64(i) )
@@ -4053,7 +4420,7 @@ OGRBoolean OGRFeature::Equal( OGRFeature * poFeature )
                 break;
 
             case OFTString:
-                if ( strcmp(GetFieldAsString(i), 
+                if ( strcmp(GetFieldAsString(i),
                             poFeature->GetFieldAsString(i)) != 0 )
                     return FALSE;
                 break;
@@ -4091,7 +4458,7 @@ OGRBoolean OGRFeature::Equal( OGRFeature * poFeature )
                 }
                 break;
             }
-            
+
             case OFTRealList:
             {
                 int nCount1, nCount2;
@@ -4163,7 +4530,7 @@ OGRBoolean OGRFeature::Equal( OGRFeature * poFeature )
             }
 
             default:
-                if( strcmp(GetFieldAsString(i), 
+                if( strcmp(GetFieldAsString(i),
                            poFeature->GetFieldAsString(i)) != 0 )
                     return FALSE;
                 break;
@@ -4182,7 +4549,7 @@ OGRBoolean OGRFeature::Equal( OGRFeature * poFeature )
         if( poThisGeom != NULL && poOtherGeom == NULL )
             return FALSE;
 
-        if( poThisGeom != NULL && poOtherGeom != NULL 
+        if( poThisGeom != NULL && poOtherGeom != NULL
             && (!poThisGeom->Equals( poOtherGeom ) ) )
             return FALSE;
     }
@@ -4253,7 +4620,9 @@ OGRErr OGRFeature::SetFrom( OGRFeature * poSrcFeature, int bForgiving )
     int         iField, *panMap;
     OGRErr      eErr;
 
-    panMap = (int *) VSIMalloc( sizeof(int) * poSrcFeature->GetFieldCount() );
+    panMap = (int *) VSI_MALLOC_VERBOSE( sizeof(int) * poSrcFeature->GetFieldCount() );
+    if( panMap == NULL )
+        return OGRERR_FAILURE;
     for( iField = 0; iField < poSrcFeature->GetFieldCount(); iField++ )
     {
         panMap[iField] = GetFieldIndex(
@@ -4272,9 +4641,9 @@ OGRErr OGRFeature::SetFrom( OGRFeature * poSrcFeature, int bForgiving )
     }
 
     eErr = SetFrom( poSrcFeature, panMap, bForgiving );
-    
+
     VSIFree(panMap);
-    
+
     return eErr;
 }
 
@@ -4288,7 +4657,7 @@ OGRErr OGRFeature::SetFrom( OGRFeature * poSrcFeature, int bForgiving )
  * Overwrite the contents of this feature from the geometry and attributes
  * of another.  The hOtherFeature does not need to have the same
  * OGRFeatureDefn.  Field values are copied by corresponding field names.
- * Field types do not have to exactly match.  OGR_F_SetField*() function 
+ * Field types do not have to exactly match.  OGR_F_SetField*() function
  * conversion rules will be applied as needed.
  *
  * This function is the same as the C++ method OGRFeature::SetFrom().
@@ -4304,14 +4673,14 @@ OGRErr OGRFeature::SetFrom( OGRFeature * poSrcFeature, int bForgiving )
  * not transferred, otherwise an error code.
  */
 
-OGRErr OGR_F_SetFrom( OGRFeatureH hFeat, OGRFeatureH hOtherFeat, 
+OGRErr OGR_F_SetFrom( OGRFeatureH hFeat, OGRFeatureH hOtherFeat,
                       int bForgiving )
 
 {
-    VALIDATE_POINTER1( hFeat, "OGR_F_SetFrom", CE_Failure );
-    VALIDATE_POINTER1( hOtherFeat, "OGR_F_SetFrom", CE_Failure );
+    VALIDATE_POINTER1( hFeat, "OGR_F_SetFrom", OGRERR_FAILURE );
+    VALIDATE_POINTER1( hOtherFeat, "OGR_F_SetFrom", OGRERR_FAILURE );
 
-    return ((OGRFeature *) hFeat)->SetFrom( (OGRFeature *) hOtherFeat, 
+    return ((OGRFeature *) hFeat)->SetFrom( (OGRFeature *) hOtherFeat,
                                            bForgiving );
 }
 
@@ -4339,7 +4708,7 @@ OGRErr OGR_F_SetFrom( OGRFeatureH hFeat, OGRFeatureH hOtherFeat,
  * stored at the corresponding index of the source feature's fields. A value of
  * -1 should be used to ignore the source's field. The array should not be NULL
  * and be as long as the number of fields in the source feature.
- * 
+ *
  * @param bForgiving TRUE if the operation should continue despite lacking
  * output fields matching some of the source fields.
  *
@@ -4395,6 +4764,12 @@ OGRErr OGRFeature::SetFrom( OGRFeature * poSrcFeature, int *panMap ,
     SetStyleString( poSrcFeature->GetStyleString() );
 
 /* -------------------------------------------------------------------- */
+/*      Copy native data.                                               */
+/* -------------------------------------------------------------------- */
+    SetNativeData( poSrcFeature->GetNativeData() );
+    SetNativeMediaType( poSrcFeature->GetNativeMediaType() );
+
+/* -------------------------------------------------------------------- */
 /*      Set the fields by name.                                         */
 /* -------------------------------------------------------------------- */
 
@@ -4415,7 +4790,7 @@ OGRErr OGRFeature::SetFrom( OGRFeature * poSrcFeature, int *panMap ,
  * Overwrite the contents of this feature from the geometry and attributes
  * of another.  The hOtherFeature does not need to have the same
  * OGRFeatureDefn.  Field values are copied according to the provided indices
- * map. Field types do not have to exactly match.  OGR_F_SetField*() function 
+ * map. Field types do not have to exactly match.  OGR_F_SetField*() function
  * conversion rules will be applied as needed. This is more efficient than
  * OGR_F_SetFrom() in that this doesn't lookup the fields by their names.
  * Particularly useful when the field names don't match.
@@ -4430,7 +4805,7 @@ OGRErr OGRFeature::SetFrom( OGRFeature * poSrcFeature, int *panMap ,
  * stored at the corresponding index of the source feature's fields. A value of
  * -1 should be used to ignore the source's field. The array should not be NULL
  * and be as long as the number of fields in the source feature.
- * 
+ *
  * @param bForgiving TRUE if the operation should continue despite lacking
  * output fields matching some of the source fields.
  *
@@ -4438,15 +4813,15 @@ OGRErr OGRFeature::SetFrom( OGRFeature * poSrcFeature, int *panMap ,
  * not transferred, otherwise an error code.
  */
 
-OGRErr OGR_F_SetFromWithMap( OGRFeatureH hFeat, OGRFeatureH hOtherFeat, 
+OGRErr OGR_F_SetFromWithMap( OGRFeatureH hFeat, OGRFeatureH hOtherFeat,
                       int bForgiving, int *panMap )
 
 {
-    VALIDATE_POINTER1( hFeat, "OGR_F_SetFrom", CE_Failure );
-    VALIDATE_POINTER1( hOtherFeat, "OGR_F_SetFrom", CE_Failure );
-    VALIDATE_POINTER1( panMap, "OGR_F_SetFrom", CE_Failure);
+    VALIDATE_POINTER1( hFeat, "OGR_F_SetFrom", OGRERR_FAILURE );
+    VALIDATE_POINTER1( hOtherFeat, "OGR_F_SetFrom", OGRERR_FAILURE );
+    VALIDATE_POINTER1( panMap, "OGR_F_SetFrom", OGRERR_FAILURE);
 
-    return ((OGRFeature *) hFeat)->SetFrom( (OGRFeature *) hOtherFeat, 
+    return ((OGRFeature *) hFeat)->SetFrom( (OGRFeature *) hOtherFeat,
                                            panMap, bForgiving );
 }
 
@@ -4473,7 +4848,7 @@ OGRErr OGR_F_SetFromWithMap( OGRFeatureH hFeat, OGRFeatureH hOtherFeat,
  * stored at the corresponding index of the source feature's fields. A value of
  * -1 should be used to ignore the source's field. The array should not be NULL
  * and be as long as the number of fields in the source feature.
- * 
+ *
  * @param bForgiving TRUE if the operation should continue despite lacking
  * output fields matching some of the source fields.
  *
@@ -4512,7 +4887,7 @@ OGRErr OGRFeature::SetFieldsFrom( OGRFeature * poSrcFeature, int *panMap ,
           case OFTInteger64:
             SetField( iDstField, poSrcFeature->GetFieldAsInteger64( iField ) );
             break;
-            
+
           case OFTReal:
             SetField( iDstField, poSrcFeature->GetFieldAsDouble( iField ) );
             break;
@@ -4569,33 +4944,40 @@ OGRErr OGRFeature::SetFieldsFrom( OGRFeature * poSrcFeature, int *panMap ,
           case OFTDate:
           case OFTDateTime:
           case OFTTime:
-            if (GetFieldDefnRef(iDstField)->GetType() == OFTDate ||
-                GetFieldDefnRef(iDstField)->GetType() == OFTTime ||
-                GetFieldDefnRef(iDstField)->GetType() == OFTDateTime)
+          {
+            OGRFieldType eDstFieldType = GetFieldDefnRef(iDstField)->GetType();
+            if (eDstFieldType == OFTDate ||
+                eDstFieldType == OFTTime ||
+                eDstFieldType == OFTDateTime )
             {
                 SetField( iDstField, poSrcFeature->GetRawFieldRef( iField ) );
             }
-            else if (GetFieldDefnRef(iDstField)->GetType() == OFTString)
+            else if( eDstFieldType == OFTString ||
+                     eDstFieldType == OFTStringList )
             {
                 SetField( iDstField, poSrcFeature->GetFieldAsString( iField ) );
             }
             else if( !bForgiving )
                 return OGRERR_FAILURE;
             break;
+          }
 
           default:
-            if( poSrcFeature->GetFieldDefnRef(iField)->GetType()
-                == GetFieldDefnRef(iDstField)->GetType() )
+          {
+            OGRFieldType eDstFieldType = GetFieldDefnRef(iDstField)->GetType();
+            if( poSrcFeature->GetFieldDefnRef(iField)->GetType() == eDstFieldType )
             {
                 SetField( iDstField, poSrcFeature->GetRawFieldRef(iField) );
             }
-            else if (GetFieldDefnRef(iDstField)->GetType() == OFTString)
+            else if (eDstFieldType == OFTString ||
+                     eDstFieldType == OFTStringList )
             {
                 SetField( iDstField, poSrcFeature->GetFieldAsString( iField ) );
             }
             else if( !bForgiving )
                 return OGRERR_FAILURE;
             break;
+          }
         }
     }
 
@@ -4613,9 +4995,9 @@ OGRErr OGRFeature::SetFieldsFrom( OGRFeature * poSrcFeature, int *panMap ,
  * this string, and ogr_featurestyle.h for services available to parse it.
  *
  * This method is the same as the C function OGR_F_GetStyleString().
- * 
- * @return a reference to a representation in string format, or NULL if 
- * there isn't one. 
+ *
+ * @return a reference to a representation in string format, or NULL if
+ * there isn't one.
  */
 
 const char *OGRFeature::GetStyleString()
@@ -4643,10 +5025,10 @@ const char *OGRFeature::GetStyleString()
  * this string, and ogr_featurestyle.h for services available to parse it.
  *
  * This function is the same as the C++ method OGRFeature::GetStyleString().
- * 
+ *
  * @param hFeat handle to the feature to get the style from.
- * @return a reference to a representation in string format, or NULL if 
- * there isn't one. 
+ * @return a reference to a representation in string format, or NULL if
+ * there isn't one.
  */
 
 const char *OGR_F_GetStyleString( OGRFeatureH hFeat )
@@ -4678,9 +5060,9 @@ void OGRFeature::SetStyleString(const char *pszString)
         CPLFree(m_pszStyleString);
         m_pszStyleString = NULL;
     }
-    
+
     if( pszString )
-        m_pszStyleString = CPLStrdup(pszString);
+        m_pszStyleString = VSI_STRDUP_VERBOSE(pszString);
 }
 
 /************************************************************************/
@@ -4782,7 +5164,7 @@ void OGRFeature::SetStyleTableDirectly(OGRStyleTable *poStyleTable)
 /*      feature defn to another with minimum work.                      */
 /************************************************************************/
 
-OGRErr OGRFeature::RemapFields( OGRFeatureDefn *poNewDefn, 
+OGRErr OGRFeature::RemapFields( OGRFeatureDefn *poNewDefn,
                                 int *panRemapSource )
 
 {
@@ -4792,7 +5174,7 @@ OGRErr OGRFeature::RemapFields( OGRFeatureDefn *poNewDefn,
     if( poNewDefn == NULL )
         poNewDefn = poDefn;
 
-    pauNewFields = (OGRField *) CPLCalloc( poNewDefn->GetFieldCount(), 
+    pauNewFields = (OGRField *) CPLCalloc( poNewDefn->GetFieldCount(),
                                            sizeof(OGRField) );
 
     for( iDstField = 0; iDstField < poDefn->GetFieldCount(); iDstField++ )
@@ -4804,16 +5186,16 @@ OGRErr OGRFeature::RemapFields( OGRFeatureDefn *poNewDefn,
         }
         else
         {
-            memcpy( pauNewFields + iDstField, 
+            memcpy( pauNewFields + iDstField,
                     pauFields + panRemapSource[iDstField],
                     sizeof(OGRField) );
         }
     }
 
-    /* 
+    /*
     ** We really should be freeing memory for old columns that
     ** are no longer present.  We don't for now because it is a bit messy
-    ** and would take too long to test.  
+    ** and would take too long to test.
     */
 
 /* -------------------------------------------------------------------- */
@@ -4834,7 +5216,7 @@ OGRErr OGRFeature::RemapFields( OGRFeatureDefn *poNewDefn,
 /*      feature defn to another with minimum work.                      */
 /************************************************************************/
 
-OGRErr OGRFeature::RemapGeomFields( OGRFeatureDefn *poNewDefn, 
+OGRErr OGRFeature::RemapGeomFields( OGRFeatureDefn *poNewDefn,
                                     int *panRemapSource )
 
 {
@@ -4844,7 +5226,7 @@ OGRErr OGRFeature::RemapGeomFields( OGRFeatureDefn *poNewDefn,
     if( poNewDefn == NULL )
         poNewDefn = poDefn;
 
-    papoNewGeomFields = (OGRGeometry **) CPLCalloc( poNewDefn->GetGeomFieldCount(), 
+    papoNewGeomFields = (OGRGeometry **) CPLCalloc( poNewDefn->GetGeomFieldCount(),
                                            sizeof(OGRGeometry*) );
 
     for( iDstField = 0; iDstField < poDefn->GetGeomFieldCount(); iDstField++ )
@@ -4860,10 +5242,10 @@ OGRErr OGRFeature::RemapGeomFields( OGRFeatureDefn *poNewDefn,
         }
     }
 
-    /* 
+    /*
     ** We really should be freeing memory for old columns that
     ** are no longer present.  We don't for now because it is a bit messy
-    ** and would take too long to test.  
+    ** and would take too long to test.
     */
 
 /* -------------------------------------------------------------------- */
@@ -4885,7 +5267,7 @@ OGRStyleTableH OGR_F_GetStyleTable( OGRFeatureH hFeat )
 
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_GetStyleTable", NULL );
-    
+
     return (OGRStyleTableH) ((OGRFeature *) hFeat)->GetStyleTable( );
 }
 
@@ -4898,7 +5280,7 @@ void OGR_F_SetStyleTableDirectly( OGRFeatureH hFeat,
 
 {
     VALIDATE_POINTER0( hFeat, "OGR_F_SetStyleTableDirectly" );
-    
+
     ((OGRFeature *) hFeat)->SetStyleTableDirectly( (OGRStyleTable *) hStyleTable);
 }
 
@@ -4912,7 +5294,7 @@ void OGR_F_SetStyleTable( OGRFeatureH hFeat,
 {
     VALIDATE_POINTER0( hFeat, "OGR_F_SetStyleTable" );
     VALIDATE_POINTER0( hStyleTable, "OGR_F_SetStyleTable" );
-    
+
     ((OGRFeature *) hFeat)->SetStyleTable( (OGRStyleTable *) hStyleTable);
 }
 
@@ -4947,7 +5329,7 @@ void OGRFeature::FillUnsetWithDefault(int bNotNullableOnly,
         {
             if( eType == OFTDate || eType == OFTTime || eType == OFTDateTime )
             {
-                if( EQUALN(pszDefault, "CURRENT", strlen("CURRENT")) )
+                if( STARTS_WITH_CI(pszDefault, "CURRENT") )
                 {
                     time_t t = time(NULL);
                     struct tm brokendown;
@@ -4957,7 +5339,7 @@ void OGRFeature::FillUnsetWithDefault(int bNotNullableOnly,
                                 brokendown.tm_mday,
                                 brokendown.tm_hour,
                                 brokendown.tm_min,
-                                brokendown.tm_sec,
+                                static_cast<float>(brokendown.tm_sec),
                                 100 );
                 }
                 else
@@ -5032,7 +5414,8 @@ void OGR_F_FillUnsetWithDefault( OGRFeatureH hFeat,
  * This method is the same as the C function OGR_F_Validate().
  *
  * @param nValidateFlags OGR_F_VAL_ALL or combination of OGR_F_VAL_NULL,
- *                       OGR_F_VAL_GEOM_TYPE, OGR_F_VAL_WIDTH and OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT
+ *                       OGR_F_VAL_GEOM_TYPE, OGR_F_VAL_WIDTH and OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT,
+ *                       OGR_F_VAL_ALLOW_DIFFERENT_GEOM_DIM
  *                       with '|' operator
  * @param bEmitError TRUE if a CPLError() must be emitted when a check fails
  * @return TRUE if all enabled validation tests pass.
@@ -5068,8 +5451,14 @@ int OGRFeature::Validate( int nValidateFlags, int bEmitError )
             {
                 OGRwkbGeometryType eType = poDefn->GetGeomFieldDefn(i)->GetType();
                 OGRwkbGeometryType eFType = poGeom->getGeometryType();
-                if( (eType == wkbSetZ(wkbUnknown) && !wkbHasZ(eFType)) ||
-                    (eType != wkbSetZ(wkbUnknown) && eFType != eType) )
+                if( (nValidateFlags & OGR_F_VAL_ALLOW_DIFFERENT_GEOM_DIM) &&
+                    (wkbFlatten(eFType) == wkbFlatten(eType) ||
+                     wkbFlatten(eType) == wkbUnknown) )
+                {
+                    /* ok */
+                }
+                else if( (eType == wkbSetZ(wkbUnknown) && !wkbHasZ(eFType)) ||
+                         (eType != wkbSetZ(wkbUnknown) && eFType != eType) )
                 {
                     bRet = FALSE;
                     if( bEmitError )
@@ -5156,3 +5545,234 @@ int OGR_F_Validate( OGRFeatureH hFeat, int nValidateFlags, int bEmitError )
 
     return ((OGRFeature *) hFeat)->Validate( nValidateFlags, bEmitError );
 }
+
+/************************************************************************/
+/*                          GetNativeData()                             */
+/************************************************************************/
+
+/**
+ * \fn const char* OGRFeature::GetNativeData() const;
+ *
+ * \brief Returns the native data for the feature.
+ *
+ * The native data is the representation in a "natural" form that comes from
+ * the driver that created this feature, or that is aimed at an output driver.
+ * The native data may be in different format, which is indicated by
+ * GetNativeMediaType().
+ *
+ * Note that most drivers do not support storing the native data in the feature
+ * object, and if they do, generally the NATIVE_DATA open option must be passed
+ * at dataset opening.
+ *
+ * The "native data" does not imply it is something more performant or powerful than
+ * what can be obtained with the rest of the API, but it may be useful in
+ * round-tripping scenarios where some characteristics of the underlying format
+ * are not captured otherwise by the OGR abstraction.
+ *
+ * This function is the same as the C function
+ * OGR_F_GetNativeData().
+ *
+ * @return a string with the native data, or NULL if there is none.
+ * @since GDAL 2.1
+ *
+ * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
+ */
+
+/************************************************************************/
+/*                      ,  OGR_F_GetNativeData()                        */
+/************************************************************************/
+
+/**
+ * \brief Returns the native data for the feature.
+ *
+ * The native data is the representation in a "natural" form that comes from
+ * the driver that created this feature, or that is aimed at an output driver.
+ * The native data may be in different format, which is indicated by
+ * OGR_F_GetNativeMediaType().
+ *
+ * Note that most drivers do not support storing the native data in the feature
+ * object, and if they do, generally the NATIVE_DATA open option must be passed
+ * at dataset opening.
+ *
+ * The "native data" does not imply it is something more performant or powerful than
+ * what can be obtained with the rest of the API, but it may be useful in
+ * round-tripping scenarios where some characteristics of the underlying format
+ * are not captured otherwise by the OGR abstraction.
+ *
+ * This function is the same as the C++ method
+ * OGRFeature::GetNativeData().
+ *
+ * @param hFeat handle to the feature.
+ * @return a string with the native data, or NULL if there is none.
+ * @since GDAL 2.1
+ *
+ * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
+ */
+
+const char *OGR_F_GetNativeData( OGRFeatureH hFeat )
+
+{
+    VALIDATE_POINTER1( hFeat, "OGR_F_GetNativeData", NULL );
+
+    return ((const OGRFeature *) hFeat)->GetNativeData();
+}
+
+/************************************************************************/
+/*                        GetNativeMediaType()                          */
+/************************************************************************/
+
+/**
+ * \fn const char* OGRFeature::GetNativeMediaType() const;
+ *
+ * \brief Returns the native media type for the feature.
+ *
+ * The native media type is the identifier for the format of the native data.
+ * It follows the IANA RFC 2045 (see https://en.wikipedia.org/wiki/Media_type),
+ * e.g. "application/vnd.geo+json" for JSon.
+ *
+ * This function is the same as the C function
+ * OGR_F_GetNativeMediaType().
+ *
+ * @return a string with the native media type, or NULL if there is none.
+ * @since GDAL 2.1
+ *
+ * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
+ */
+
+/************************************************************************/
+/*                       OGR_F_GetNativeMediaType()                     */
+/************************************************************************/
+
+/**
+ * \brief Returns the native media type for the feature.
+ *
+ * The native media type is the identifier for the format of the native data.
+ * It follows the IANA RFC 2045 (see https://en.wikipedia.org/wiki/Media_type),
+ * e.g. "application/vnd.geo+json" for JSon.
+ *
+ * This function is the same as the C function
+ * OGR_F_GetNativeMediaType().
+ *
+ * @param hFeat handle to the feature.
+ * @return a string with the native media type, or NULL if there is none.
+ * @since GDAL 2.1
+ *
+ * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
+ */
+
+const char *OGR_F_GetNativeMediaType( OGRFeatureH hFeat )
+{
+    VALIDATE_POINTER1( hFeat, "OGR_F_GetNativeMediaType", NULL );
+
+    return ((const OGRFeature *) hFeat)->GetNativeMediaType();
+}
+
+/************************************************************************/
+/*                      ,    SetNativeData()                            */
+/************************************************************************/
+
+/**
+ * \brief Sets the native data for the feature.
+ *
+ * The native data is the representation in a "natural" form that comes from
+ * the driver that created this feature, or that is aimed at an output driver.
+ * The native data may be in different format, which is indicated by
+ * GetNativeMediaType().
+ *
+ * This function is the same as the C function
+ * OGR_F_SetNativeData().
+ *
+ * @param pszNativeData a string with the native data, or NULL if there is none.
+ * @since GDAL 2.1
+ *
+ * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
+ */
+
+void OGRFeature::SetNativeData( const char* pszNativeData )
+{
+    CPLFree( m_pszNativeData );
+    m_pszNativeData = ( pszNativeData ) ? VSI_STRDUP_VERBOSE( pszNativeData ) : NULL;
+}
+
+/************************************************************************/
+/*                      ,   OGR_F_SetNativeData()                       */
+/************************************************************************/
+
+/**
+ * \brief Sets the native data for the feature.
+ *
+ * The native data is the representation in a "natural" form that comes from
+ * the driver that created this feature, or that is aimed at an output driver.
+ * The native data may be in different format, which is indicated by
+ * OGR_F_GetNativeMediaType().
+ *
+ * This function is the same as the C++ method
+ * OGRFeature::SetNativeData().
+ *
+ * @param hFeat handle to the feature.
+ * @param pszNativeData a string with the native data, or NULL if there is none.
+ * @since GDAL 2.1
+ *
+ * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
+ */
+
+void OGR_F_SetNativeData( OGRFeatureH hFeat, const char* pszNativeData )
+{
+    VALIDATE_POINTER0( hFeat, "OGR_F_SetNativeData" );
+
+    ((OGRFeature *) hFeat)->SetNativeData(pszNativeData);
+}
+
+/************************************************************************/
+/*                      ,  SetNativeMediaType()                         */
+/************************************************************************/
+
+/**
+ * \brief Sets the native media type for the feature.
+ *
+ * The native media type is the identifier for the format of the native data.
+ * It follows the IANA RFC 2045 (see https://en.wikipedia.org/wiki/Media_type),
+ * e.g. "application/vnd.geo+json" for JSon.
+ *
+ * This function is the same as the C function
+ * OGR_F_SetNativeMediaType().
+ *
+ * @param pszNativeMediaType a string with the native media type, or NULL if there is none.
+ * @since GDAL 2.1
+ *
+ * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
+ */
+
+void OGRFeature::SetNativeMediaType( const char* pszNativeMediaType )
+{
+    CPLFree( m_pszNativeMediaType );
+    m_pszNativeMediaType = ( pszNativeMediaType ) ? VSI_STRDUP_VERBOSE( pszNativeMediaType ) : NULL;
+}
+
+/************************************************************************/
+/*                        , OGR_F_SetNativeMediaType()                  */
+/************************************************************************/
+
+/**
+ * \brief Sets the native media type for the feature.
+ *
+ * The native media type is the identifier for the format of the native data.
+ * It follows the IANA RFC 2045 (see https://en.wikipedia.org/wiki/Media_type),
+ * e.g. "application/vnd.geo+json" for JSon.
+ *
+ * This function is the same as the C++ method
+ * OGRFeature::SetNativeMediaType().
+ *
+ * @param hFeat handle to the feature.
+ * @param pszNativeMediaType a string with the native media type, or NULL if there is none.
+ * @since GDAL 2.1
+ *
+ * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
+ */
+
+void OGR_F_SetNativeMediaType( OGRFeatureH hFeat, const char* pszNativeMediaType )
+{
+    VALIDATE_POINTER0( hFeat, "OGR_F_SetNativeMediaType" );
+
+    ((OGRFeature *) hFeat)->SetNativeMediaType(pszNativeMediaType);
+}
diff --git a/ogr/ogrfeaturedefn.cpp b/ogr/ogrfeaturedefn.cpp
index d690d4b..cfc05d5 100644
--- a/ogr/ogrfeaturedefn.cpp
+++ b/ogr/ogrfeaturedefn.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrfeaturedefn.cpp 28807 2015-03-28 14:46:31Z rouault $
+ * $Id: ogrfeaturedefn.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRFeatureDefn class implementation.
@@ -33,7 +33,7 @@
 #include "ogr_p.h"
 #include "ograpispy.h"
 
-CPL_CVSID("$Id: ogrfeaturedefn.cpp 28807 2015-03-28 14:46:31Z rouault $");
+CPL_CVSID("$Id: ogrfeaturedefn.cpp 33631 2016-03-04 06:28:09Z goatbar $");
 
 /************************************************************************/
 /*                           OGRFeatureDefn()                           */
@@ -49,20 +49,21 @@ CPL_CVSID("$Id: ogrfeaturedefn.cpp 28807 2015-03-28 14:46:31Z rouault $");
  * This method is the same as the C function OGR_FD_Create().
  *
  * @param pszName the name to be assigned to this layer/class.  It does not
- * need to be unique. 
+ * need to be unique.
  */
 
-OGRFeatureDefn::OGRFeatureDefn( const char * pszName )
-
+OGRFeatureDefn::OGRFeatureDefn( const char * pszName ) :
+    nRefCount(0),
+    nFieldCount(0),
+    papoFieldDefn(NULL),
+    nGeomFieldCount(1),
+    papoGeomFieldDefn(NULL),
+    pszFeatureClassName(NULL),
+    bIgnoreStyle(FALSE)
 {
     pszFeatureClassName = CPLStrdup( pszName );
-    nRefCount = 0;
-    nFieldCount = 0;
-    papoFieldDefn = NULL;
-    nGeomFieldCount = 1;
     papoGeomFieldDefn = (OGRGeomFieldDefn**) CPLMalloc(sizeof(OGRGeomFieldDefn*));
     papoGeomFieldDefn[0] = new OGRGeomFieldDefn("", wkbUnknown);
-    bIgnoreStyle = FALSE;
 }
 
 /************************************************************************/
@@ -74,11 +75,11 @@ OGRFeatureDefn::OGRFeatureDefn( const char * pszName )
  * The OGRFeatureDefn maintains a reference count, but this starts at
  * zero, and should normally be incremented by the owner.
  *
- * This function is the same as the C++ method 
+ * This function is the same as the C++ method
  * OGRFeatureDefn::OGRFeatureDefn().
  *
  * @param pszName the name to be assigned to this layer/class.  It does not
- * need to be unique. 
+ * need to be unique.
  * @return handle to the newly created feature definition.
  */
 
@@ -102,7 +103,7 @@ OGRFeatureDefn::~OGRFeatureDefn()
                   "OGRFeatureDefn %s with a ref count of %d deleted!\n",
                   pszFeatureClassName, nRefCount );
     }
-    
+
     CPLFree( pszFeatureClassName );
 
     for( int i = 0; i < nFieldCount; i++ )
@@ -124,9 +125,9 @@ OGRFeatureDefn::~OGRFeatureDefn()
 /*                           OGR_FD_Destroy()                           */
 /************************************************************************/
 /**
- * \brief Destroy a feature definition object and release all memory associated with it. 
+ * \brief Destroy a feature definition object and release all memory associated with it.
  *
- * This function is the same as the C++ method 
+ * This function is the same as the C++ method
  * OGRFeatureDefn::~OGRFeatureDefn().
  *
  * @param hDefn handle to the feature definition to be destroyed.
@@ -184,9 +185,9 @@ void OGR_FD_Release( OGRFeatureDefnH hDefn )
  *
  * \brief Create a copy of this feature definition.
  *
- * Creates a deep copy of the feature definition. 
- * 
- * @return the copy. 
+ * Creates a deep copy of the feature definition.
+ *
+ * @return the copy.
  */
 
 OGRFeatureDefn *OGRFeatureDefn::Clone()
@@ -201,7 +202,7 @@ OGRFeatureDefn *OGRFeatureDefn::Clone()
     for( i = 0; i < nFieldCount; i++ )
         poCopy->AddFieldDefn( GetFieldDefn( i ) );
 
-    /* There is a default geometry field created at OGRFeatureDefn instanciation */
+    // There is a default geometry field created at OGRFeatureDefn instantiation
     poCopy->DeleteGeomFieldDefn(0);
     GetGeomFieldCount();
     for( i = 0; i < nGeomFieldCount; i++ )
@@ -327,7 +328,7 @@ OGRFieldDefn *OGRFeatureDefn::GetFieldDefn( int iField )
 /**
  * \brief Fetch field definition of the passed feature definition.
  *
- * This function is the same as the C++ method 
+ * This function is the same as the C++ method
  * OGRFeatureDefn::GetFieldDefn().
  *
  * Starting with GDAL 1.7.0, this method will also issue an error if the index
@@ -364,7 +365,7 @@ OGRFieldDefnH OGR_FD_GetFieldDefn( OGRFeatureDefnH hDefn, int iField )
  * function directly, but use OGRLayer::CreateField() instead.
  *
  * This method should only be called while there are no OGRFeature
- * objects in existance based on this OGRFeatureDefn.  The OGRFieldDefn
+ * objects in existence based on this OGRFeatureDefn.  The OGRFieldDefn
  * passed in is copied, and remains the responsibility of the caller.
  *
  * This method is the same as the C function OGR_FD_AddFieldDefn().
@@ -394,7 +395,7 @@ void OGRFeatureDefn::AddFieldDefn( OGRFieldDefn * poNewDefn )
  * function directly, but use OGR_L_CreateField() instead.
  *
  * This function  should only be called while there are no OGRFeature
- * objects in existance based on this OGRFeatureDefn.  The OGRFieldDefn
+ * objects in existence based on this OGRFeatureDefn.  The OGRFieldDefn
  * passed in is copied, and remains the responsibility of the caller.
  *
  * This function is the same as the C++ method OGRFeatureDefn::AddFieldDefn().
@@ -417,15 +418,15 @@ void OGR_FD_AddFieldDefn( OGRFeatureDefnH hDefn, OGRFieldDefnH hNewField )
 /**
  * \brief Delete an existing field definition.
  *
- * To delete an existing field definition from a layer definition, do not use this
- * function directly, but use OGRLayer::DeleteField() instead.
+ * To delete an existing field definition from a layer definition, do not use
+ * this function directly, but use OGRLayer::DeleteField() instead.
  *
  * This method should only be called while there are no OGRFeature
- * objects in existance based on this OGRFeatureDefn.
+ * objects in existence based on this OGRFeatureDefn.
  *
  * This method is the same as the C function OGR_FD_DeleteFieldDefn().
  *
- * @param iField the index of the field defintion.
+ * @param iField the index of the field definition.
  * @return OGRERR_NONE in case of success.
  * @since OGR 1.9.0
  */
@@ -462,12 +463,12 @@ OGRErr OGRFeatureDefn::DeleteFieldDefn( int iField )
  * function directly, but use OGR_L_DeleteField() instead.
  *
  * This method should only be called while there are no OGRFeature
- * objects in existance based on this OGRFeatureDefn.
+ * objects in existence based on this OGRFeatureDefn.
  *
  * This method is the same as the C++ method OGRFeatureDefn::DeleteFieldDefn().
  *
  * @param hDefn handle to the feature definition.
- * @param iField the index of the field defintion.
+ * @param iField the index of the field definition.
  * @return OGRERR_NONE in case of success.
  * @since OGR 1.9.0
  */
@@ -489,7 +490,7 @@ OGRErr OGR_FD_DeleteFieldDefn( OGRFeatureDefnH hDefn, int iField )
  * function directly, but use OGR_L_ReorderFields() instead.
  *
  * This method should only be called while there are no OGRFeature
- * objects in existance based on this OGRFeatureDefn.
+ * objects in existence based on this OGRFeatureDefn.
  *
  * This method is the same as the C function OGR_FD_ReorderFieldDefns().
  *
@@ -536,9 +537,10 @@ OGRErr OGRFeatureDefn::ReorderFieldDefns( int* panMap )
  * function directly, but use OGR_L_ReorderFields() instead.
  *
  * This method should only be called while there are no OGRFeature
- * objects in existance based on this OGRFeatureDefn.
+ * objects in existence based on this OGRFeatureDefn.
  *
- * This method is the same as the C++ method OGRFeatureDefn::ReorderFieldDefns().
+ * This method is the same as the C++ method
+ * OGRFeatureDefn::ReorderFieldDefns().
  *
  * @param hDefn handle to the feature definition.
  * @param panMap an array of GetFieldCount() elements which
@@ -546,10 +548,10 @@ OGRErr OGRFeatureDefn::ReorderFieldDefns( int* panMap )
  * for each field definition at position i after reordering,
  * its position before reordering was panMap[i].
  * @return OGRERR_NONE in case of success.
- * @since OGR 1.9.0
+ * @since OGR 2.1.0
  */
 
-OGRErr OGR_FD_ReorderFieldDefn( OGRFeatureDefnH hDefn, int* panMap )
+OGRErr OGR_FD_ReorderFieldDefns( OGRFeatureDefnH hDefn, int* panMap )
 
 {
     return ((OGRFeatureDefn *) hDefn)->ReorderFieldDefns( panMap );
@@ -637,7 +639,7 @@ OGRGeomFieldDefn *OGRFeatureDefn::GetGeomFieldDefn( int iGeomField )
 /**
  * \brief Fetch geometry field definition of the passed feature definition.
  *
- * This function is the same as the C++ method 
+ * This function is the same as the C++ method
  * OGRFeatureDefn::GetGeomFieldDefn().
  *
  * @param hDefn handle to the feature definition to get the field definition
@@ -673,13 +675,13 @@ OGRGeomFieldDefnH OGR_FD_GetGeomFieldDefn( OGRFeatureDefnH hDefn, int iGeomField
  *
  * To add a new geometry field definition to a layer definition, do not use this
  * function directly, but use OGRLayer::CreateGeomField() instead.
- * 
+ *
  * This method does an internal copy of the passed geometry field definition,
  * unless bCopy is set to FALSE (in which case it takes ownership of the
  * field definition.
  *
  * This method should only be called while there are no OGRFeature
- * objects in existance based on this OGRFeatureDefn.  The OGRGeomFieldDefn
+ * objects in existence based on this OGRFeatureDefn.  The OGRGeomFieldDefn
  * passed in is copied, and remains the responsibility of the caller.
  *
  * This method is the same as the C function OGR_FD_AddGeomFieldDefn().
@@ -713,19 +715,21 @@ void OGRFeatureDefn::AddGeomFieldDefn( OGRGeomFieldDefn * poNewDefn,
  * function directly, but use OGR_L_CreateGeomField() instead.
  *
  * This function  should only be called while there are no OGRFeature
- * objects in existance based on this OGRFeatureDefn.  The OGRGeomFieldDefn
+ * objects in existence based on this OGRFeatureDefn.  The OGRGeomFieldDefn
  * passed in is copied, and remains the responsibility of the caller.
  *
- * This function is the same as the C++ method OGRFeatureDefn::AddGeomFieldDefn().
+ * This function is the same as the C++ method
+ * OGRFeatureDefn::AddGeomFieldDefn().
  *
- * @param hDefn handle to the feature definition to add the geometry field definition
- * to.
+ * @param hDefn handle to the feature definition to add the geometry field
+ * definition to.
  * @param hNewGeomField handle to the new field definition.
  *
  * @since GDAL 1.11
  */
 
-void OGR_FD_AddGeomFieldDefn( OGRFeatureDefnH hDefn, OGRGeomFieldDefnH hNewGeomField )
+void OGR_FD_AddGeomFieldDefn( OGRFeatureDefnH hDefn,
+                              OGRGeomFieldDefnH hNewGeomField )
 
 {
     ((OGRFeatureDefn *) hDefn)->AddGeomFieldDefn( (OGRGeomFieldDefn *) hNewGeomField );
@@ -738,15 +742,15 @@ void OGR_FD_AddGeomFieldDefn( OGRFeatureDefnH hDefn, OGRGeomFieldDefnH hNewGeomF
 /**
  * \brief Delete an existing geometry field definition.
  *
- * To delete an existing field definition from a layer definition, do not use this
- * function directly, but use OGRLayer::DeleteGeomField() instead.
+ * To delete an existing field definition from a layer definition, do not use
+ * this function directly, but use OGRLayer::DeleteGeomField() instead.
  *
  * This method should only be called while there are no OGRFeature
- * objects in existance based on this OGRFeatureDefn.
+ * objects in existence based on this OGRFeatureDefn.
  *
  * This method is the same as the C function OGR_FD_DeleteGeomFieldDefn().
  *
- * @param iGeomField the index of the geometry field defintion.
+ * @param iGeomField the index of the geometry field definition.
  * @return OGRERR_NONE in case of success.
  *
  * @since GDAL 1.11
@@ -780,16 +784,18 @@ OGRErr OGRFeatureDefn::DeleteGeomFieldDefn( int iGeomField )
 /**
  * \brief Delete an existing geometry field definition.
  *
- * To delete an existing geometry field definition from a layer definition, do not use this
- * function directly, but use OGR_L_DeleteGeomField() instead (*not implemented yet*)
+ * To delete an existing geometry field definition from a layer definition, do
+ * not use this function directly, but use OGR_L_DeleteGeomField() instead
+ * (*not implemented yet*).
  *
  * This method should only be called while there are no OGRFeature
- * objects in existance based on this OGRFeatureDefn.
+ * objects in existence based on this OGRFeatureDefn.
  *
- * This method is the same as the C++ method OGRFeatureDefn::DeleteGeomFieldDefn().
+ * This method is the same as the C++ method
+ * OGRFeatureDefn::DeleteGeomFieldDefn().
  *
  * @param hDefn handle to the feature definition.
- * @param iGeomField the index of the geometry field defintion.
+ * @param iGeomField the index of the geometry field definition.
  * @return OGRERR_NONE in case of success.
  *
  * @since GDAL 1.11
@@ -818,7 +824,7 @@ OGRErr OGR_FD_DeleteGeomFieldDefn( OGRFeatureDefnH hDefn, int iGeomField )
  *
  * @return the geometry field index, or -1 if no match found.
  */
- 
+
 
 int OGRFeatureDefn::GetGeomFieldIndex( const char * pszGeomFieldName )
 
@@ -826,7 +832,8 @@ int OGRFeatureDefn::GetGeomFieldIndex( const char * pszGeomFieldName )
     GetGeomFieldCount();
     for( int i = 0; i < nGeomFieldCount; i++ )
     {
-        if( EQUAL(pszGeomFieldName, GetGeomFieldDefn(i)->GetNameRef() ) )
+        OGRGeomFieldDefn* poGFldDefn = GetGeomFieldDefn(i);
+        if( poGFldDefn != NULL && EQUAL(pszGeomFieldName, poGFldDefn->GetNameRef() ) )
             return i;
     }
 
@@ -844,7 +851,7 @@ int OGRFeatureDefn::GetGeomFieldIndex( const char * pszGeomFieldName )
  *
  * This function is the same as the C++ method OGRFeatureDefn::GetGeomFieldIndex.
  *
- * @param hDefn handle to the feature definition to get field index from. 
+ * @param hDefn handle to the feature definition to get field index from.
  * @param pszGeomFieldName the geometry field name to search for.
  *
  * @return the geometry field index, or -1 if no match found.
@@ -877,7 +884,7 @@ int OGR_FD_GetGeomFieldIndex( OGRFeatureDefnH hDefn,
  * wkbNone indicates no geometry is available for the layer at all.
  * Many drivers do not properly mark the geometry
  * type as 25D even if some or all geometries are in fact 25D.  A few (broken)
- * drivers return wkbPolygon for layers that also include wkbMultiPolygon.  
+ * drivers return wkbPolygon for layers that also include wkbMultiPolygon.
  *
  * Starting with GDAL 1.11, this method returns GetGeomFieldDefn(0)->GetType().
  *
@@ -889,7 +896,10 @@ OGRwkbGeometryType OGRFeatureDefn::GetGeomType()
 {
     if( GetGeomFieldCount() == 0 )
         return wkbNone;
-    OGRwkbGeometryType eType = GetGeomFieldDefn(0)->GetType();
+    OGRGeomFieldDefn* poGFldDefn = GetGeomFieldDefn(0);
+    if( poGFldDefn == NULL )
+        return wkbNone;
+    OGRwkbGeometryType eType = poGFldDefn->GetType();
     if( eType == (wkbUnknown | wkb25DBitInternalUse) && CSLTestBoolean(CPLGetConfigOption("QGIS_HACK", "NO")) )
         eType = wkbUnknown;
     return eType;
@@ -935,7 +945,7 @@ OGRwkbGeometryType OGR_FD_GetGeomType( OGRFeatureDefnH hDefn )
  * All geometry objects using this type must be of the defined type or
  * a derived type.  The default upon creation is wkbUnknown which allows for
  * any geometry type.  The geometry type should generally not be changed
- * after any OGRFeatures have been created against this definition. 
+ * after any OGRFeatures have been created against this definition.
  *
  * This method is the same as the C function OGR_FD_SetGeomType().
  *
@@ -971,7 +981,7 @@ void OGRFeatureDefn::SetGeomType( OGRwkbGeometryType eNewType )
  * All geometry objects using this type must be of the defined type or
  * a derived type.  The default upon creation is wkbUnknown which allows for
  * any geometry type.  The geometry type should generally not be changed
- * after any OGRFeatures have been created against this definition. 
+ * after any OGRFeatures have been created against this definition.
  *
  * This function is the same as the C++ method OGRFeatureDefn::SetGeomType().
  *
@@ -994,11 +1004,11 @@ void OGR_FD_SetGeomType( OGRFeatureDefnH hDefn, OGRwkbGeometryType eType )
 
 /**
  * \fn int OGRFeatureDefn::Reference();
- * 
+ *
  * \brief Increments the reference count by one.
  *
  * The reference count is used keep track of the number of OGRFeature
- * objects referencing this definition. 
+ * objects referencing this definition.
  *
  * This method is the same as the C function OGR_FD_Reference().
  *
@@ -1012,7 +1022,7 @@ void OGR_FD_SetGeomType( OGRFeatureDefnH hDefn, OGRwkbGeometryType eType )
  * \brief Increments the reference count by one.
  *
  * The reference count is used keep track of the number of OGRFeature
- * objects referencing this definition. 
+ * objects referencing this definition.
  *
  * This function is the same as the C++ method OGRFeatureDefn::Reference().
  *
@@ -1051,7 +1061,7 @@ int OGR_FD_Reference( OGRFeatureDefnH hDefn )
  * This function is the same as the C++ method OGRFeatureDefn::Dereference().
  *
  * @param hDefn handle to the feature definition on witch OGRFeature are
- * based on. 
+ * based on.
  * @return the updated reference count.
  */
 
@@ -1082,11 +1092,11 @@ int OGR_FD_Dereference( OGRFeatureDefnH hDefn )
 /**
  * \brief Fetch current reference count.
  *
- * This function is the same as the C++ method 
+ * This function is the same as the C++ method
  * OGRFeatureDefn::GetReferenceCount().
  *
  * @param hDefn handle to the feature definition on witch OGRFeature are
- * based on. 
+ * based on.
  * @return the current reference count.
  */
 
@@ -1112,7 +1122,7 @@ int OGR_FD_GetReferenceCount( OGRFeatureDefnH hDefn )
  *
  * @return the field index, or -1 if no match found.
  */
- 
+
 
 int OGRFeatureDefn::GetFieldIndex( const char * pszFieldName )
 
@@ -1120,7 +1130,8 @@ int OGRFeatureDefn::GetFieldIndex( const char * pszFieldName )
     GetFieldCount();
     for( int i = 0; i < nFieldCount; i++ )
     {
-        if( EQUAL(pszFieldName, GetFieldDefn(i)->GetNameRef() ) )
+        OGRFieldDefn* poFDefn = GetFieldDefn(i);
+        if( poFDefn != NULL && EQUAL(pszFieldName, poFDefn->GetNameRef() ) )
             return i;
     }
 
@@ -1138,7 +1149,7 @@ int OGRFeatureDefn::GetFieldIndex( const char * pszFieldName )
  *
  * This function is the same as the C++ method OGRFeatureDefn::GetFieldIndex.
  *
- * @param hDefn handle to the feature definition to get field index from. 
+ * @param hDefn handle to the feature definition to get field index from.
  * @param pszFieldName the field name to search for.
  *
  * @return the field index, or -1 if no match found.
@@ -1175,7 +1186,10 @@ int OGRFeatureDefn::IsGeometryIgnored()
 {
     if( GetGeomFieldCount() == 0 )
         return FALSE;
-    return GetGeomFieldDefn(0)->IsIgnored();
+    OGRGeomFieldDefn* poGFldDefn = GetGeomFieldDefn(0);
+    if( poGFldDefn == NULL )
+        return FALSE;
+    return poGFldDefn->IsIgnored();
 }
 
 /************************************************************************/
@@ -1185,13 +1199,13 @@ int OGRFeatureDefn::IsGeometryIgnored()
 /**
  * \brief Determine whether the geometry can be omitted when fetching features
  *
- * This function is the same as the C++ method 
+ * This function is the same as the C++ method
  * OGRFeatureDefn::IsGeometryIgnored().
  *
  * Starting with GDAL 1.11, this method returns GetGeomFieldDefn(0)->IsIgnored().
  *
  * @param hDefn handle to the feature definition on witch OGRFeature are
- * based on. 
+ * based on.
  * @return ignore state
  */
 
@@ -1219,7 +1233,11 @@ int OGR_FD_IsGeometryIgnored( OGRFeatureDefnH hDefn )
 void OGRFeatureDefn::SetGeometryIgnored( int bIgnore )
 {
     if( GetGeomFieldCount() > 0 )
-        GetGeomFieldDefn(0)->SetIgnored(bIgnore);
+    {
+        OGRGeomFieldDefn* poGFldDefn = GetGeomFieldDefn(0);
+        if( poGFldDefn != NULL )
+            poGFldDefn->SetIgnored(bIgnore);
+    }
 }
 
 /************************************************************************/
@@ -1229,13 +1247,13 @@ void OGRFeatureDefn::SetGeometryIgnored( int bIgnore )
 /**
  * \brief Set whether the geometry can be omitted when fetching features
  *
- * This function is the same as the C++ method 
+ * This function is the same as the C++ method
  * OGRFeatureDefn::SetGeometryIgnored().
  *
  * Starting with GDAL 1.11, this method calls GetGeomFieldDefn(0)->SetIgnored().
  *
  * @param hDefn handle to the feature definition on witch OGRFeature are
- * based on. 
+ * based on.
  * @param bIgnore ignore state
  */
 
@@ -1265,11 +1283,11 @@ void OGR_FD_SetGeometryIgnored( OGRFeatureDefnH hDefn, int bIgnore )
 /**
  * \brief Determine whether the style can be omitted when fetching features
  *
- * This function is the same as the C++ method 
+ * This function is the same as the C++ method
  * OGRFeatureDefn::IsStyleIgnored().
  *
  * @param hDefn handle to the feature definition on which OGRFeature are
- * based on. 
+ * based on.
  * @return ignore state
  */
 
@@ -1299,11 +1317,11 @@ int OGR_FD_IsStyleIgnored( OGRFeatureDefnH hDefn )
 /**
  * \brief Set whether the style can be omitted when fetching features
  *
- * This function is the same as the C++ method 
+ * This function is the same as the C++ method
  * OGRFeatureDefn::SetStyleIgnored().
  *
  * @param hDefn handle to the feature definition on witch OGRFeature are
- * based on. 
+ * based on.
  * @param bIgnore ignore state
  */
 
@@ -1382,7 +1400,7 @@ int OGRFeatureDefn::IsSame( OGRFeatureDefn * poOtherFeatureDefn )
  * \brief Test if the feature definition is identical to the other one.
  *
  * @param hFDefn handle to the feature definition on witch OGRFeature are
- * based on. 
+ * based on.
  * @param hOtherFDefn handle to the other feature definition to compare to.
  * @return TRUE if the feature definition is identical to the other one.
  *
diff --git a/ogr/ogrfeaturequery.cpp b/ogr/ogrfeaturequery.cpp
index f77b3cb..d90fe85 100644
--- a/ogr/ogrfeaturequery.cpp
+++ b/ogr/ogrfeaturequery.cpp
@@ -1,9 +1,9 @@
 /******************************************************************************
- * $Id: ogrfeaturequery.cpp 28968 2015-04-21 19:00:02Z rouault $
- * 
+ * $Id: ogrfeaturequery.cpp 33631 2016-03-04 06:28:09Z goatbar $
+ *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of simple SQL WHERE style attributes queries
- *           for OGRFeatures.  
+ *           for OGRFeatures.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -35,15 +35,15 @@
 #include "ogr_p.h"
 #include "ogr_attrind.h"
 
-CPL_CVSID("$Id: ogrfeaturequery.cpp 28968 2015-04-21 19:00:02Z rouault $");
+CPL_CVSID("$Id: ogrfeaturequery.cpp 33631 2016-03-04 06:28:09Z goatbar $");
 
 /************************************************************************/
 /*     Support for special attributes (feature query and selection)     */
 /************************************************************************/
 
-const char* SpecialFieldNames[SPECIAL_FIELD_COUNT] 
+const char* const SpecialFieldNames[SPECIAL_FIELD_COUNT]
 = {"FID", "OGR_GEOMETRY", "OGR_STYLE", "OGR_GEOM_WKT", "OGR_GEOM_AREA"};
-const swq_field_type SpecialFieldTypes[SPECIAL_FIELD_COUNT] 
+const swq_field_type SpecialFieldTypes[SPECIAL_FIELD_COUNT]
 = {SWQ_INTEGER, SWQ_STRING, SWQ_STRING, SWQ_STRING, SWQ_FLOAT};
 
 /************************************************************************/
@@ -71,7 +71,7 @@ OGRFeatureQuery::~OGRFeatureQuery()
 /*                                Parse                                 */
 /************************************************************************/
 
-OGRErr OGRFeatureQuery::Compile( OGRFeatureDefn *poDefn, 
+OGRErr OGRFeatureQuery::Compile( OGRFeatureDefn *poDefn,
                                  const char * pszExpression,
                                  int bCheck,
                                  swq_custom_func_registrar* poCustomFuncRegistrar )
@@ -95,9 +95,9 @@ OGRErr OGRFeatureQuery::Compile( OGRFeatureDefn *poDefn,
     int         nFieldCount = poDefn->GetFieldCount() + SPECIAL_FIELD_COUNT +
                               poDefn->GetGeomFieldCount();
 
-    papszFieldNames = (char **) 
+    papszFieldNames = (char **)
         CPLMalloc(sizeof(char *) * nFieldCount );
-    paeFieldTypes = (swq_field_type *) 
+    paeFieldTypes = (swq_field_type *)
         CPLMalloc(sizeof(swq_field_type) * nFieldCount );
 
     for( iField = 0; iField < poDefn->GetFieldCount(); iField++ )
@@ -173,7 +173,7 @@ OGRErr OGRFeatureQuery::Compile( OGRFeatureDefn *poDefn,
 
     poTargetDefn = poDefn;
     eCPLErr = swq_expr_compile( pszExpression, nFieldCount,
-                                papszFieldNames, paeFieldTypes, 
+                                papszFieldNames, paeFieldTypes,
                                 bCheck,
                                 poCustomFuncRegistrar,
                                 (swq_expr_node **) &pSWQExpr );
@@ -211,22 +211,22 @@ static swq_expr_node *OGRFeatureFetcher( swq_expr_node *op, void *pFeatureIn )
     {
       case SWQ_INTEGER:
       case SWQ_BOOLEAN:
-        poRetNode = new swq_expr_node( 
+        poRetNode = new swq_expr_node(
             poFeature->GetFieldAsInteger(op->field_index) );
         break;
 
       case SWQ_INTEGER64:
-        poRetNode = new swq_expr_node( 
+        poRetNode = new swq_expr_node(
             poFeature->GetFieldAsInteger64(op->field_index) );
         break;
 
       case SWQ_FLOAT:
-        poRetNode = new swq_expr_node( 
+        poRetNode = new swq_expr_node(
             poFeature->GetFieldAsDouble(op->field_index) );
         break;
 
       default:
-        poRetNode = new swq_expr_node( 
+        poRetNode = new swq_expr_node(
             poFeature->GetFieldAsString(op->field_index) );
         break;
     }
@@ -274,9 +274,9 @@ int OGRFeatureQuery::CanUseIndex( OGRLayer *poLayer )
     swq_expr_node *psExpr = (swq_expr_node *) pSWQExpr;
 
 /* -------------------------------------------------------------------- */
-/*      Do we have an index on the targetted layer?                     */
+/*      Do we have an index on the targeted layer?                      */
 /* -------------------------------------------------------------------- */
-    if ( poLayer->GetIndex() == FALSE )
+    if ( poLayer->GetIndex() == NULL )
         return FALSE;
 
     return CanUseIndex( psExpr, poLayer );
@@ -307,7 +307,7 @@ int OGRFeatureQuery::CanUseIndex( swq_expr_node *psExpr,
 
     swq_expr_node *poColumn = psExpr->papoSubExpr[0];
     swq_expr_node *poValue = psExpr->papoSubExpr[1];
-    
+
     if( poColumn->eNodeType != SNT_COLUMN
         || poValue->eNodeType != SNT_CONSTANT )
         return FALSE;
@@ -348,7 +348,7 @@ static int CompareGIntBig(const void *pa, const void *pb)
         return 0;
 }
 
-GIntBig *OGRFeatureQuery::EvaluateAgainstIndices( OGRLayer *poLayer, 
+GIntBig *OGRFeatureQuery::EvaluateAgainstIndices( OGRLayer *poLayer,
                                                OGRErr *peErr )
 
 {
@@ -358,7 +358,7 @@ GIntBig *OGRFeatureQuery::EvaluateAgainstIndices( OGRLayer *poLayer,
         *peErr = OGRERR_NONE;
 
 /* -------------------------------------------------------------------- */
-/*      Do we have an index on the targetted layer?                     */
+/*      Do we have an index on the targeted layer?                      */
 /* -------------------------------------------------------------------- */
     if ( poLayer->GetIndex() == NULL )
         return NULL;
@@ -534,7 +534,7 @@ GIntBig *OGRFeatureQuery::EvaluateAgainstIndices( swq_expr_node *psExpr,
 
     swq_expr_node *poColumn = psExpr->papoSubExpr[0];
     swq_expr_node *poValue = psExpr->papoSubExpr[1];
-    
+
     if( poColumn->eNodeType != SNT_COLUMN
         || poValue->eNodeType != SNT_CONSTANT )
         return NULL;
@@ -615,18 +615,18 @@ GIntBig *OGRFeatureQuery::EvaluateAgainstIndices( swq_expr_node *psExpr,
         else
             sValue.Integer = (int) poValue->int_value;
         break;
-      
+
       case OFTInteger64:
         if (poValue->field_type == SWQ_FLOAT)
             sValue.Integer64 = (GIntBig) poValue->float_value;
         else
             sValue.Integer64 = poValue->int_value;
         break;
-        
+
       case OFTReal:
         sValue.Real = poValue->float_value;
         break;
-        
+
       case OFTString:
         sValue.String = poValue->string_value;
         break;
@@ -655,7 +655,7 @@ GIntBig *OGRFeatureQuery::EvaluateAgainstIndices( swq_expr_node *psExpr,
 /*      GetUsedFields().                                                */
 /************************************************************************/
 
-char **OGRFeatureQuery::FieldCollector( void *pBareOp, 
+char **OGRFeatureQuery::FieldCollector( void *pBareOp,
                                         char **papszList )
 
 {
@@ -683,14 +683,14 @@ char **OGRFeatureQuery::FieldCollector( void *pBareOp,
             pszFieldName = SpecialFieldNames[op->field_index - poTargetDefn->GetFieldCount()];
         else if( op->field_index >= 0
                  && op->field_index < poTargetDefn->GetFieldCount() )
-            pszFieldName = 
+            pszFieldName =
                 poTargetDefn->GetFieldDefn(op->field_index)->GetNameRef();
         else
         {
             CSLDestroy( papszList );
             return NULL;
         }
-        
+
         if( CSLFindString( papszList, pszFieldName ) == -1 )
             papszList = CSLAddString( papszList, pszFieldName );
     }
@@ -719,11 +719,11 @@ char **OGRFeatureQuery::FieldCollector( void *pBareOp,
  * All attribute fields are used in the expression of this feature
  * query are returned as a StringList of field names.  This function would
  * primarily be used within drivers to recognise special case conditions
- * depending only on attribute fields that can be very efficiently 
- * fetched. 
+ * depending only on attribute fields that can be very efficiently
+ * fetched.
  *
  * NOTE: If any fields in the expression are from tables other than the
- * primary table then NULL is returned indicating an error.  In succesful
+ * primary table then NULL is returned indicating an error.  In successful
  * use, no non-empty expression should return an empty list.
  *
  * @return list of field names.  Free list with CSLDestroy() when no longer
@@ -736,9 +736,5 @@ char **OGRFeatureQuery::GetUsedFields( )
     if( pSWQExpr == NULL )
         return NULL;
 
-    
     return FieldCollector( pSWQExpr, NULL );
 }
-
-
-
diff --git a/ogr/ogrfeaturestyle.cpp b/ogr/ogrfeaturestyle.cpp
index 22fc55e..30e07bc 100644
--- a/ogr/ogrfeaturestyle.cpp
+++ b/ogr/ogrfeaturestyle.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrfeaturestyle.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: ogrfeaturestyle.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Feature Representation string API
@@ -34,11 +34,7 @@
 #include "ogr_featurestyle.h"
 #include "ogr_api.h"
 
-CPL_CVSID("$Id: ogrfeaturestyle.cpp 27942 2014-11-11 00:57:41Z rouault $");
-
-CPL_C_START
-void OGRFeatureStylePuller() {}
-CPL_C_END
+CPL_CVSID("$Id: ogrfeaturestyle.cpp 33631 2016-03-04 06:28:09Z goatbar $");
 
 /****************************************************************************/
 /*                Class Parameter (used in the String)                      */
@@ -69,7 +65,7 @@ static const OGRStyleParamId asStyleBrush[] =
     {OGRSTBrushPriority,"l",FALSE,OGRSTypeInteger}
 };
 
-static const OGRStyleParamId asStyleSymbol[] = 
+static const OGRStyleParamId asStyleSymbol[] =
 {
     {OGRSTSymbolId,"id",FALSE,OGRSTypeString},
     {OGRSTSymbolAngle,"a",FALSE,OGRSTypeDouble},
@@ -122,8 +118,8 @@ static const OGRStyleParamId asStyleLabel[] =
  * \brief Constructor.
  *
  * This method is the same as the C function OGR_SM_Create()
- * 
- * @param poDataSetStyleTable (currently unused, reserved for future use), pointer 
+ *
+ * @param poDataSetStyleTable (currently unused, reserved for future use), pointer
  * to OGRStyleTable. Pass NULL for now.
  */
 OGRStyleMgr::OGRStyleMgr(OGRStyleTable *poDataSetStyleTable)
@@ -139,10 +135,10 @@ OGRStyleMgr::OGRStyleMgr(OGRStyleTable *poDataSetStyleTable)
  * \brief OGRStyleMgr factory.
  *
  * This function is the same as the C++ method OGRStyleMgr::OGRStyleMgr().
- * 
+ *
  * @param hStyleTable pointer to OGRStyleTable or NULL if not working with
  *  a style table.
- * 
+ *
  * @return an handle to the new style manager object.
  */
 
@@ -190,9 +186,9 @@ void OGR_SM_Destroy( OGRStyleMgrH hSM )
 /*      GBool OGRStyleMgr::SetFeatureStyleString(OGRFeature *poFeature,     */
 /*                                       char *pszStyleString,              */
 /*                                       GBool bNoMatching)                 */
-/*      Set the gived representation to the feature,                        */
+/*      Set the given representation to the feature,                        */
 /*      if bNoMatching == TRUE, don't try to find it in the styletable      */
-/*      otherwize, we will use the name defined in the styletable           */
+/*      otherwise, we will use the name defined in the styletable.          */
 /****************************************************************************/
 
 /**
@@ -200,20 +196,20 @@ void OGR_SM_Destroy( OGRStyleMgrH hSM )
  *
  * @param poFeature       the feature object to store the style in
  * @param pszStyleString  the style to store
- * @param bNoMatching     TRUE to lookup the style in the style table and 
+ * @param bNoMatching     TRUE to lookup the style in the style table and
  *  add the name to the feature
  *
  * @return TRUE on success, FALSE on error.
  */
- 
-GBool OGRStyleMgr::SetFeatureStyleString(OGRFeature *poFeature, 
+
+GBool OGRStyleMgr::SetFeatureStyleString(OGRFeature *poFeature,
                                          const char *pszStyleString,
                                          GBool bNoMatching)
 {
     const char *pszName;
-    if (poFeature == FALSE)
+    if (poFeature == NULL)
       return FALSE;
-    
+
     if (pszStyleString == NULL)
       poFeature->SetStyleString("");
     else if (bNoMatching == TRUE)
@@ -239,7 +235,7 @@ GBool OGRStyleMgr::SetFeatureStyleString(OGRFeature *poFeature,
  * @param poFeature feature object from which to read the style.
  *
  * @return a reference to the style string read from the feature, or NULL
- * in case of error.. 
+ * in case of error..
  */
 
 const char *OGRStyleMgr::InitFromFeature(OGRFeature *poFeature)
@@ -263,7 +259,7 @@ const char *OGRStyleMgr::InitFromFeature(OGRFeature *poFeature)
 /**
  * \brief Initialize style manager from the style string of a feature.
  *
- * This function is the same as the C++ method 
+ * This function is the same as the C++ method
  * OGRStyleMgr::InitFromFeature().
  *
  * @param hSM handle to the style manager.
@@ -271,9 +267,9 @@ const char *OGRStyleMgr::InitFromFeature(OGRFeature *poFeature)
  *
  * @return a reference to the style string read from the feature, or NULL
  * in case of error.
- */ 
+ */
 
-const char *OGR_SM_InitFromFeature(OGRStyleMgrH hSM, 
+const char *OGR_SM_InitFromFeature(OGRStyleMgrH hSM,
                                            OGRFeatureH hFeat)
 
 {
@@ -295,7 +291,7 @@ const char *OGR_SM_InitFromFeature(OGRStyleMgrH hSM,
  *
  * @param pszStyleString the style string to use (can be NULL).
  *
- * @return TRUE on success, FALSE on errors. 
+ * @return TRUE on success, FALSE on errors.
  */
 GBool OGRStyleMgr::InitStyleString(const char *pszStyleString)
 {
@@ -309,11 +305,9 @@ GBool OGRStyleMgr::InitStyleString(const char *pszStyleString)
 
     if (m_pszStyleString == NULL && pszStyleString)
       m_pszStyleString = CPLStrdup(pszStyleString);
-   
 
-    
     return TRUE;
-}    
+}
 
 /************************************************************************/
 /*                     OGR_SM_InitStyleString()                         */
@@ -327,8 +321,8 @@ GBool OGRStyleMgr::InitStyleString(const char *pszStyleString)
  * @param hSM handle to the style manager.
  * @param pszStyleString the style string to use (can be NULL).
  *
- * @return TRUE on success, FALSE on errors. 
- */ 
+ * @return TRUE on success, FALSE on errors.
+ */
 
 int OGR_SM_InitStyleString(OGRStyleMgrH hSM, const char *pszStyleString)
 
@@ -356,8 +350,8 @@ int OGR_SM_InitStyleString(OGRStyleMgrH hSM, const char *pszStyleString)
 const char *OGRStyleMgr::GetStyleName(const char *pszStyleString)
 {
 
-    // SECURITY:  the unit and the value for all parameter should be the same,
-    // a text comparaison is executed .
+    // SECURITY: The unit and the value for all parameter should be the same,
+    // a text comparison is executed.
 
     const char *pszStyle;
 
@@ -387,14 +381,14 @@ const char *OGRStyleMgr::GetStyleName(const char *pszStyleString)
  * @return the style string matching the name or NULL if not found or error.
  */
 const char *OGRStyleMgr::GetStyleByName(const char *pszStyleName)
-{    
+{
     if (m_poDataSetStyleTable)
     {
         return  m_poDataSetStyleTable->Find(pszStyleName);
     }
     return NULL;
 }
-    
+
 /****************************************************************************/
 /*            GBool OGRStyleMgr::AddStyle(char *pszStyleName,               */
 /*                                   char *pszStyleString)                  */
@@ -407,13 +401,13 @@ const char *OGRStyleMgr::GetStyleByName(const char *pszStyleName)
  * This method is the same as the C function OGR_SM_AddStyle().
  *
  * @param pszStyleName the name of the style to add.
- * @param pszStyleString the style string to use, or NULL to use the style 
+ * @param pszStyleString the style string to use, or NULL to use the style
  *                       stored in the manager.
  *
- * @return TRUE on success, FALSE on errors. 
+ * @return TRUE on success, FALSE on errors.
  */
 
-GBool OGRStyleMgr::AddStyle(const char *pszStyleName, 
+GBool OGRStyleMgr::AddStyle(const char *pszStyleName,
                             const char *pszStyleString)
 {
     const char *pszStyle;
@@ -442,18 +436,18 @@ GBool OGRStyleMgr::AddStyle(const char *pszStyleName,
  *
  * @param hSM handle to the style manager.
  * @param pszStyleName the name of the style to add.
- * @param pszStyleString the style string to use, or NULL to use the style 
+ * @param pszStyleString the style string to use, or NULL to use the style
  *                       stored in the manager.
  *
- * @return TRUE on success, FALSE on errors. 
- */ 
+ * @return TRUE on success, FALSE on errors.
+ */
 
-int OGR_SM_AddStyle(OGRStyleMgrH hSM, const char *pszStyleName, 
+int OGR_SM_AddStyle(OGRStyleMgrH hSM, const char *pszStyleName,
                     const char *pszStyleString)
 {
     VALIDATE_POINTER1( hSM, "OGR_SM_AddStyle", FALSE );
     VALIDATE_POINTER1( pszStyleName, "OGR_SM_AddStyle", FALSE );
-    
+
     return ((OGRStyleMgr *) hSM)->AddStyle( pszStyleName, pszStyleString);
 }
 
@@ -494,12 +488,12 @@ const char *OGRStyleMgr::GetStyleString(OGRFeature *poFeature)
  *
  * @param pszPart the style string defining the part to add.
  *
- * @return TRUE on success, FALSE on errors. 
+ * @return TRUE on success, FALSE on errors.
  */
 
 GBool OGRStyleMgr::AddPart(const char *pszPart)
 {
-    char *pszTmp; 
+    char *pszTmp;
     if (pszPart)
     {
         if (m_pszStyleString)
@@ -533,8 +527,8 @@ GBool OGRStyleMgr::AddPart(const char *pszPart)
  *
  * @param poStyleTool the style tool defining the part to add.
  *
- * @return TRUE on success, FALSE on errors. 
- */ 
+ * @return TRUE on success, FALSE on errors.
+ */
 
 GBool OGRStyleMgr::AddPart(OGRStyleTool *poStyleTool)
 {
@@ -560,7 +554,7 @@ GBool OGRStyleMgr::AddPart(OGRStyleTool *poStyleTool)
 
     return FALSE;
 }
-    
+
 /************************************************************************/
 /*                     OGR_SM_AddPart()                                 */
 /************************************************************************/
@@ -573,8 +567,8 @@ GBool OGRStyleMgr::AddPart(OGRStyleTool *poStyleTool)
  * @param hSM handle to the style manager.
  * @param hST the style tool defining the part to add.
  *
- * @return TRUE on success, FALSE on errors. 
- */ 
+ * @return TRUE on success, FALSE on errors.
+ */
 
 int OGR_SM_AddPart(OGRStyleMgrH hSM, OGRStyleToolH hST)
 
@@ -601,8 +595,8 @@ int OGR_SM_AddPart(OGRStyleMgrH hSM, OGRStyleToolH hST)
  * @param pszStyleString (optional) the style string on which to operate.
  * If NULL then the current style string stored in the style manager is used.
  *
- * @return the number of parts (style tools) in the style. 
- */ 
+ * @return the number of parts (style tools) in the style.
+ */
 
 int OGRStyleMgr::GetPartCount(const char *pszStyleString)
 {
@@ -643,8 +637,8 @@ int OGRStyleMgr::GetPartCount(const char *pszStyleString)
  * @param pszStyleString (optional) the style string on which to operate.
  * If NULL then the current style string stored in the style manager is used.
  *
- * @return the number of parts (style tools) in the style. 
- */ 
+ * @return the number of parts (style tools) in the style.
+ */
 
 int OGR_SM_GetPartCount(OGRStyleMgrH hSM, const char *pszStyleString)
 
@@ -667,16 +661,17 @@ int OGR_SM_GetPartCount(OGRStyleMgrH hSM, const char *pszStyleString)
  *
  * This method is the same as the C function OGR_SM_GetPart().
  *
- * This method instanciates a new object that should be freed with OGR_ST_Destroy().
+ * This method instantiates a new object that should be freed with
+ * OGR_ST_Destroy().
  *
  * @param nPartId the part number (0-based index).
  * @param pszStyleString (optional) the style string on which to operate.
  * If NULL then the current style string stored in the style manager is used.
  *
  * @return OGRStyleTool of the requested part (style tools) or NULL on error.
- */ 
+ */
 
-OGRStyleTool *OGRStyleMgr::GetPart(int nPartId, 
+OGRStyleTool *OGRStyleMgr::GetPart(int nPartId,
                                    const char *pszStyleString)
 {
     char **papszStyleString;
@@ -685,7 +680,7 @@ OGRStyleTool *OGRStyleMgr::GetPart(int nPartId,
     OGRStyleTool    *poStyleTool = NULL;
 
     if (pszStyleString)
-      pszStyle = pszStyleString; 
+      pszStyle = pszStyleString;
     else
       pszStyle = m_pszStyleString;
 
@@ -698,7 +693,7 @@ OGRStyleTool *OGRStyleMgr::GetPart(int nPartId,
                                           | CSLT_PRESERVEESCAPES );
 
     pszString = CSLGetField( papszStyleString, nPartId );
-    
+
     if ( strlen(pszString) > 0 )
     {
         poStyleTool = CreateStyleToolFromStyleString(pszString);
@@ -709,7 +704,7 @@ OGRStyleTool *OGRStyleMgr::GetPart(int nPartId,
     CSLDestroy( papszStyleString );
 
     return poStyleTool;
-} 
+}
 
 /************************************************************************/
 /*                     OGR_SM_GetPart()                                 */
@@ -720,7 +715,8 @@ OGRStyleTool *OGRStyleMgr::GetPart(int nPartId,
  *
  * This function is the same as the C++ method OGRStyleMgr::GetPart().
  *
- * This function instanciates a new object that should be freed with OGR_ST_Destroy().
+ * This function instantiates a new object that should be freed with
+ * OGR_ST_Destroy().
  *
  * @param hSM handle to the style manager.
  * @param nPartId the part number (0-based index).
@@ -728,9 +724,9 @@ OGRStyleTool *OGRStyleMgr::GetPart(int nPartId,
  * If NULL then the current style string stored in the style manager is used.
  *
  * @return OGRStyleToolH of the requested part (style tools) or NULL on error.
- */ 
+ */
 
-OGRStyleToolH OGR_SM_GetPart(OGRStyleMgrH hSM, int nPartId, 
+OGRStyleToolH OGR_SM_GetPart(OGRStyleMgrH hSM, int nPartId,
                              const char *pszStyleString)
 
 {
@@ -743,8 +739,8 @@ OGRStyleToolH OGR_SM_GetPart(OGRStyleMgrH hSM, int nPartId,
 /****************************************************************************/
 /* OGRStyleTool *CreateStyleToolFromStyleString(const char *pszStyleString) */
 /*                                                                          */
-/* create a Style tool from the gived StyleString, it should contain only a */
-/* part of a StyleString                                                    */
+/* create a Style tool from the given StyleString, it should contain only a */
+/* part of a StyleString.                                                    */
 /****************************************************************************/
 OGRStyleTool *OGRStyleMgr::CreateStyleToolFromStyleString(const char *
                                                           pszStyleString)
@@ -754,7 +750,7 @@ OGRStyleTool *OGRStyleMgr::CreateStyleToolFromStyleString(const char *
                                            | CSLT_PRESERVEQUOTES
                                            | CSLT_PRESERVEESCAPES );
     OGRStyleTool   *poStyleTool;
-        
+
     if (CSLCount(papszToken) <2)
         poStyleTool = NULL;
     else if (EQUAL(papszToken[0],"PEN"))
@@ -765,7 +761,7 @@ OGRStyleTool *OGRStyleMgr::CreateStyleToolFromStyleString(const char *
         poStyleTool = new OGRStyleSymbol();
     else if (EQUAL(papszToken[0],"LABEL"))
         poStyleTool = new OGRStyleLabel();
-    else 
+    else
         poStyleTool = NULL;
 
     CSLDestroy( papszToken );
@@ -796,8 +792,8 @@ OGRStyleTable::OGRStyleTable()
  * \brief OGRStyleTable factory.
  *
  * This function is the same as the C++ method OGRStyleTable::OGRStyleTable().
- * 
- * 
+ *
+ *
  * @return an handle to the new style table object.
  */
 
@@ -812,10 +808,10 @@ OGRStyleTableH OGR_STBL_Create( void )
 /*                                                                          */
 /****************************************************************************/
 
-/** 
- * \brief Clear a style table. 
- * 
- */  
+/**
+ * \brief Clear a style table.
+ *
+ */
 
 void OGRStyleTable::Clear()
 {
@@ -852,7 +848,7 @@ void OGR_STBL_Destroy( OGRStyleTableH hSTBL )
 /****************************************************************************/
 /*    const char *OGRStyleTable::GetStyleName(const char *pszStyleString)   */
 /*                                                                          */
-/*    return the Name of a gived stylestring otherwise NULL                 */
+/*    return the Name of a given stylestring otherwise NULL.                */
 /****************************************************************************/
 
 /**
@@ -875,18 +871,18 @@ const char *OGRStyleTable::GetStyleName(const char *pszStyleString)
         if (pszStyleStringBegin && EQUAL(&pszStyleStringBegin[1],
                                          pszStyleString))
         {
-            int nColon;
+            size_t nColon;
 
             osLastRequestedStyleName = m_papszStyleTable[i];
             nColon = osLastRequestedStyleName.find( ':' );
-            if( nColon != -1 )
-                osLastRequestedStyleName = 
+            if( nColon != std::string::npos )
+                osLastRequestedStyleName =
                     osLastRequestedStyleName.substr(0,nColon);
 
             return osLastRequestedStyleName;
         }
     }
-        
+
     return NULL;
 }
 
@@ -912,7 +908,7 @@ const char *OGRStyleTable::GetStyleName(const char *pszStyleString)
 GBool OGRStyleTable::AddStyle(const char *pszName, const char *pszStyleString)
 {
     int nPos;
-    
+
     if (pszName && pszStyleString)
     {
         if ((nPos = IsExist(pszName)) != -1)
@@ -946,15 +942,15 @@ int OGR_STBL_AddStyle( OGRStyleTableH hStyleTable,
                        const char *pszName, const char *pszStyleString)
 {
     VALIDATE_POINTER1( hStyleTable, "OGR_STBL_AddStyle", FALSE );
-    
+
     return ((OGRStyleTable *) hStyleTable)->AddStyle( pszName, pszStyleString );
 }
 
 /****************************************************************************/
 /*            GBool OGRStyleTable::RemoveStyle(char *pszName)               */
 /*                                                                          */
-/*    Remove the gived style in the table based on the name, return TRUE    */
-/*    on success otherwise FALSE                                            */
+/*    Remove the given style in the table based on the name, return TRUE    */
+/*    on success otherwise FALSE.                                           */
 /****************************************************************************/
 
 /**
@@ -980,8 +976,8 @@ GBool OGRStyleTable::RemoveStyle(const char *pszName)
 /*            GBool OGRStyleTable::ModifyStyle(char *pszName,               */
 /*                                             char *pszStyleString)        */
 /*                                                                          */
-/*    Modify the gived style, if the style doesn't exist, it will be added  */
-/*    return TRUE on success otherwise return FALSE                         */
+/*    Modify the given style, if the style doesn't exist, it will be added  */
+/*    return TRUE on success otherwise return FALSE.                        */
 /****************************************************************************/
 
 /**
@@ -994,7 +990,7 @@ GBool OGRStyleTable::RemoveStyle(const char *pszName)
  * @return TRUE on success, FALSE on error
  */
 
-GBool OGRStyleTable::ModifyStyle(const char *pszName, 
+GBool OGRStyleTable::ModifyStyle(const char *pszName,
                                  const char * pszStyleString)
 {
     if (pszName == NULL || pszStyleString == NULL)
@@ -1003,13 +999,13 @@ GBool OGRStyleTable::ModifyStyle(const char *pszName,
     RemoveStyle(pszName);
     return AddStyle(pszName, pszStyleString);
 
-}    
+}
 
 /****************************************************************************/
 /*            GBool OGRStyleTable::SaveStyleTable(char *)                   */
 /*                                                                          */
-/*    Save the StyleTable in the gived file, return TRUE on success         */
-/*    otherwise return FALSE                                                */
+/*    Save the StyleTable in the given file, return TRUE on success         */
+/*    otherwise return FALSE.                                               */
 /****************************************************************************/
 
 /**
@@ -1051,7 +1047,7 @@ int OGR_STBL_SaveStyleTable( OGRStyleTableH hStyleTable,
 {
     VALIDATE_POINTER1( hStyleTable, "OGR_STBL_SaveStyleTable", FALSE );
     VALIDATE_POINTER1( pszFilename, "OGR_STBL_SaveStyleTable", FALSE );
-    
+
     return ((OGRStyleTable *) hStyleTable)->SaveStyleTable( pszFilename );
 }
 
@@ -1076,9 +1072,9 @@ GBool OGRStyleTable::LoadStyleTable(const char *pszFilename)
       return FALSE;
 
     CSLDestroy(m_papszStyleTable);
-        
+
     m_papszStyleTable = CSLLoad(pszFilename);
-   
+
     if (m_papszStyleTable == NULL)
       return FALSE;
     else
@@ -1105,15 +1101,15 @@ int OGR_STBL_LoadStyleTable( OGRStyleTableH hStyleTable,
 {
     VALIDATE_POINTER1( hStyleTable, "OGR_STBL_LoadStyleTable", FALSE );
     VALIDATE_POINTER1( pszFilename, "OGR_STBL_LoadStyleTable", FALSE );
-    
+
     return ((OGRStyleTable *) hStyleTable)->LoadStyleTable( pszFilename );
 }
 
 /****************************************************************************/
 /*             const char *OGRStyleTable::Find(const char *pszName)         */
 /*                                                                          */
-/*             return the StyleString based on the gived name,              */
-/*             otherwise return NULL                                        */
+/*             return the StyleString based on the given name,              */
+/*             otherwise return NULL.                                       */
 /****************************************************************************/
 
 /**
@@ -1134,14 +1130,14 @@ const char *OGRStyleTable::Find(const char *pszName)
     {
 
         pszOutput = CSLGetField(m_papszStyleTable,nPos);
-         
+
         pszDash = strstr(pszOutput,":");
-        
+
         if (pszDash)
           return &pszDash[1];
     }
     return NULL;
-}   
+}
 
 /************************************************************************/
 /*                     OGR_STBL_Find()                                  */
@@ -1160,9 +1156,9 @@ const char *OGRStyleTable::Find(const char *pszName)
 
 const char *OGR_STBL_Find( OGRStyleTableH hStyleTable, const char *pszName )
 {
-    VALIDATE_POINTER1( hStyleTable, "OGR_STBL_Find", FALSE );
-    VALIDATE_POINTER1( pszName, "OGR_STBL_Find", FALSE );
-    
+    VALIDATE_POINTER1( hStyleTable, "OGR_STBL_Find", NULL );
+    VALIDATE_POINTER1( pszName, "OGR_STBL_Find", NULL );
+
     return ((OGRStyleTable *) hStyleTable)->Find( pszName );
 }
 
@@ -1180,9 +1176,9 @@ const char *OGR_STBL_Find( OGRStyleTableH hStyleTable, const char *pszName )
 
 void OGRStyleTable::Print(FILE *fpOut)
 {
-    
-    VSIFPrintf(fpOut,"#OFS-Version: 1.0\n");
-    VSIFPrintf(fpOut,"#StyleField: style\n");
+
+    CPL_IGNORE_RET_VAL(VSIFPrintf(fpOut,"#OFS-Version: 1.0\n"));
+    CPL_IGNORE_RET_VAL(VSIFPrintf(fpOut,"#StyleField: style\n"));
     if (m_papszStyleTable)
     {
         CSLPrint(m_papszStyleTable,fpOut);
@@ -1220,12 +1216,11 @@ int OGRStyleTable::IsExist(const char *pszName)
         if (strstr(m_papszStyleTable[i],pszNewString) != NULL)
         {
             return i;
-            
         }
     }
 
     return -1;
-}    
+}
 
 /************************************************************************/
 /*                               Clone()                                */
@@ -1298,12 +1293,12 @@ const char *OGRStyleTable::GetNextStyle()
 
         pszDash = strstr(pszOutput,":");
 
-        int nColon;
+        size_t nColon;
 
         osLastRequestedStyleName = pszOutput;
         nColon = osLastRequestedStyleName.find( ':' );
-        if( nColon != -1 )
-            osLastRequestedStyleName = 
+        if( nColon != std::string::npos )
+            osLastRequestedStyleName =
                 osLastRequestedStyleName.substr(0,nColon);
 
         if (pszDash)
@@ -1329,7 +1324,7 @@ const char *OGRStyleTable::GetNextStyle()
 const char *OGR_STBL_GetNextStyle( OGRStyleTableH hStyleTable)
 {
     VALIDATE_POINTER1( hStyleTable, "OGR_STBL_GetNextStyle", NULL );
-    
+
     return ((OGRStyleTable *) hStyleTable)->GetNextStyle();
 }
 
@@ -1360,7 +1355,7 @@ const char *OGRStyleTable::GetLastStyleName()
 const char *OGR_STBL_GetLastStyleName( OGRStyleTableH hStyleTable)
 {
     VALIDATE_POINTER1( hStyleTable, "OGR_STBL_GetLastStyleName", NULL );
-    
+
     return ((OGRStyleTable *) hStyleTable)->GetLastStyleName();
 }
 
@@ -1371,8 +1366,8 @@ const char *OGR_STBL_GetLastStyleName( OGRStyleTableH hStyleTable)
 /****************************************************************************/
 OGRStyleTool::OGRStyleTool(OGRSTClassId eClassId)
 {
-    m_eClassId = eClassId; 
-    m_dfScale = 1.0; 
+    m_eClassId = eClassId;
+    m_dfScale = 1.0;
     m_eUnit = OGRSTUMM;
     m_pszStyleString = NULL;
     m_bModified = FALSE;
@@ -1386,11 +1381,11 @@ OGRStyleTool::OGRStyleTool(OGRSTClassId eClassId)
  * \brief OGRStyleTool factory.
  *
  * This function is a constructor for OGRStyleTool derived classes.
- * 
+ *
  * @param eClassId subclass of style tool to create. One of OGRSTCPen (1),
  * OGRSTCBrush (2), OGRSTCSymbol (3) or OGRSTCLabel (4).
- * 
- * @return an handle to the new style tool object or NULL if the creation 
+ *
+ * @return an handle to the new style tool object or NULL if the creation
  * failed.
  */
 
@@ -1433,7 +1428,7 @@ OGRStyleTool::~OGRStyleTool()
 void OGR_ST_Destroy( OGRStyleToolH hST )
 
 {
-    delete (OGRStyleTool *) hST; 
+    delete (OGRStyleTool *) hST;
 }
 
 
@@ -1460,12 +1455,10 @@ const char *OGRStyleTool::GetStyleString(const OGRStyleParamId *pasStyleParam,
         int i;
         GBool bFound;
         const char *pszClass;
-        // FIXME: we should use CPLString instead of static buffer:
-        char szCurrent[8192];
-        szCurrent[0] = '\0';
-    
+        CPLString osCurrent;
+
         CPLFree(m_pszStyleString);
-        
+
         switch (GetType())
         {
           case OGRSTCPen:
@@ -1484,7 +1477,7 @@ const char *OGRStyleTool::GetStyleString(const OGRStyleParamId *pasStyleParam,
             pszClass = "UNKNOWN(";
         }
 
-        strcat(szCurrent,pszClass);
+        osCurrent = pszClass;
 
         bFound = FALSE;
         for (i=0;i< nSize;i++)
@@ -1493,76 +1486,76 @@ const char *OGRStyleTool::GetStyleString(const OGRStyleParamId *pasStyleParam,
               continue;
 
             if (bFound)
-              strcat(szCurrent,",");
+              osCurrent += ",";
             bFound = TRUE;
-            
-            strcat(szCurrent,pasStyleParam[i].pszToken);
+
+            osCurrent += pasStyleParam[i].pszToken;
             switch (pasStyleParam[i].eType)
             {
               case OGRSTypeString:
-                strcat(szCurrent,":");
-                strcat(szCurrent,pasStyleValue[i].pszValue);
+                osCurrent += ":";
+                osCurrent += pasStyleValue[i].pszValue;
                 break;
               case OGRSTypeDouble:
-                strcat(szCurrent,CPLString().Printf(":%f",pasStyleValue[i].dfValue));
+                osCurrent += CPLString().Printf(":%f",pasStyleValue[i].dfValue);
                 break;
               case OGRSTypeInteger:
-                strcat(szCurrent,CPLString().Printf(":%d",pasStyleValue[i].nValue));
+                osCurrent += CPLString().Printf(":%d",pasStyleValue[i].nValue);
                 break;
               default:
                 break;
-            }       
+            }
             if (pasStyleParam[i].bGeoref)
               switch (pasStyleValue[i].eUnit)
               {
                 case OGRSTUGround:
-                  strcat(szCurrent,"g");
+                  osCurrent += "g";
                   break;
                 case OGRSTUPixel:
-                  strcat(szCurrent,"px");
+                  osCurrent += "px";
                   break;
                 case OGRSTUPoints:
-                  strcat(szCurrent,"pt");
+                  osCurrent += "pt";
                   break;
                 case OGRSTUCM:
-                  strcat(szCurrent,"cm");
+                  osCurrent += "cm";
                   break;
                 case OGRSTUInches:
-                  strcat(szCurrent,"in");
+                  osCurrent += "in";
                   break;
                 case OGRSTUMM:
-                  //strcat(szCurrent,"mm");
+                  //osCurrent += "mm";
                 default:
                   break;    //imp
               }
         }
-        strcat(szCurrent,")");
+        osCurrent += ")";
 
-        m_pszStyleString = CPLStrdup(szCurrent);
+        m_pszStyleString = CPLStrdup(osCurrent);
 
         m_bModified = FALSE;
     }
-    
+
     return m_pszStyleString;
-}   
+}
 
 /************************************************************************/
 /*                          GetRGBFromString()                          */
 /************************************************************************/
 
-GBool OGRStyleTool::GetRGBFromString(const char *pszColor, int &nRed, 
-                                     int &nGreen ,int & nBlue, 
+GBool OGRStyleTool::GetRGBFromString(const char *pszColor, int &nRed,
+                                     int &nGreen ,int & nBlue,
                                      int &nTransparance)
 {
    int nCount=0;
-   
+
    nTransparance = 255;
 
    // FIXME: should we really use sscanf here?
    if (pszColor)
-       nCount  = sscanf(pszColor,"#%2x%2x%2x%2x",&nRed,&nGreen,&nBlue, 
+       nCount  = sscanf(pszColor,"#%2x%2x%2x%2x",&nRed,&nGreen,&nBlue,
                         &nTransparance);
-   
+
    if (nCount >=3)
      return TRUE;
    else
@@ -1588,16 +1581,16 @@ int OGRStyleTool::GetSpecificId(const char *pszId, const char *pszWanted)
 
     if (pszId == NULL)
       return -1;
-    
+
     if ((pszFound = strstr(pszId, pszRealWanted)) != NULL)
     {
         // We found the string, it could be no value after it, use default one
         nValue = 0;
-        
+
         if (pszFound[strlen(pszRealWanted)] == '-' )
           nValue =atoi(&pszFound[strlen(pszRealWanted)+1]);
     }
-    
+
     return nValue;
 
 }
@@ -1618,8 +1611,8 @@ OGRSTClassId OGRStyleTool::GetType()
  *
  * @param hST handle to the style tool.
  *
- * @return the style tool type, one of OGRSTCPen (1), OGRSTCBrush (2), 
- * OGRSTCSymbol (3) or OGRSTCLabel (4). Returns OGRSTCNone (0) if the 
+ * @return the style tool type, one of OGRSTCPen (1), OGRSTCBrush (2),
+ * OGRSTCSymbol (3) or OGRSTCLabel (4). Returns OGRSTCNone (0) if the
  * OGRStyleToolH is invalid.
  */
 
@@ -1667,7 +1660,7 @@ void OGRStyleTool::SetUnit(OGRSTUnitId eUnit,double dfScale)
  *
  * This function is the same as OGRStyleTool::SetUnit()
  *
- * @param hST handle to the style tool. 
+ * @param hST handle to the style tool.
  * @param eUnit the new unit.
  * @param dfGroundPaperScale ground to paper scale factor.
  *
@@ -1693,7 +1686,7 @@ GBool OGRStyleTool::Parse(const OGRStyleParamId *pasStyle,
 
 
     OGRSTUnitId  eLastUnit;
-    
+
     if (IsStyleParsed() == TRUE)
       return TRUE;
 
@@ -1701,7 +1694,7 @@ GBool OGRStyleTool::Parse(const OGRStyleParamId *pasStyle,
 
     if (m_pszStyleString == NULL)
       return FALSE;
-    
+
     // Tokenize the String to get the Type and the content
     // Example: Type(elem1:val2,elem2:val2)
     papszToken  = CSLTokenizeString2(m_pszStyleString,"()",
@@ -1712,24 +1705,24 @@ GBool OGRStyleTool::Parse(const OGRStyleParamId *pasStyle,
     if (CSLCount(papszToken) > 2 || CSLCount(papszToken) == 0)
     {
         CSLDestroy( papszToken );
-        CPLError(CE_Failure, CPLE_AppDefined, 
+        CPLError(CE_Failure, CPLE_AppDefined,
                  "Error in the format of the StyleTool %s\n",m_pszStyleString);
         return FALSE;
     }
-    
+
     // Tokenize the content of the StyleString to get paired components in it.
     papszToken2 = CSLTokenizeString2( papszToken[1], ",",
                                       CSLT_HONOURSTRINGS
                                       | CSLT_PRESERVEQUOTES
                                       | CSLT_PRESERVEESCAPES );
-    
+
     // Valid that we have the right StyleString for this feature type.
     switch (GetType())
     {
       case OGRSTCPen:
         if (!EQUAL(papszToken[0],"PEN"))
         {
-            CPLError(CE_Failure, CPLE_AppDefined, 
+            CPLError(CE_Failure, CPLE_AppDefined,
                      "Error in the Type of StyleTool %s should be a PEN Type\n",
                      papszToken[0]);
             CSLDestroy( papszToken );
@@ -1740,7 +1733,7 @@ GBool OGRStyleTool::Parse(const OGRStyleParamId *pasStyle,
       case OGRSTCBrush:
         if (!EQUAL(papszToken[0],"BRUSH"))
         {
-            CPLError(CE_Failure, CPLE_AppDefined, 
+            CPLError(CE_Failure, CPLE_AppDefined,
                      "Error in the Type of StyleTool %s should be a BRUSH Type\n",
                      papszToken[0]);
             CSLDestroy( papszToken );
@@ -1751,7 +1744,7 @@ GBool OGRStyleTool::Parse(const OGRStyleParamId *pasStyle,
       case OGRSTCSymbol:
         if (!EQUAL(papszToken[0],"SYMBOL"))
         {
-            CPLError(CE_Failure, CPLE_AppDefined, 
+            CPLError(CE_Failure, CPLE_AppDefined,
                      "Error in the Type of StyleTool %s should be a SYMBOL Type\n",
                      papszToken[0]);
             CSLDestroy( papszToken );
@@ -1762,7 +1755,7 @@ GBool OGRStyleTool::Parse(const OGRStyleParamId *pasStyle,
       case OGRSTCLabel:
         if (!EQUAL(papszToken[0],"LABEL"))
         {
-            CPLError(CE_Failure, CPLE_AppDefined, 
+            CPLError(CE_Failure, CPLE_AppDefined,
                      "Error in the Type of StyleTool %s should be a LABEL Type\n",
                      papszToken[0]);
             CSLDestroy( papszToken );
@@ -1771,35 +1764,35 @@ GBool OGRStyleTool::Parse(const OGRStyleParamId *pasStyle,
         }
         break;
       default:
-        CPLError(CE_Failure, CPLE_AppDefined, 
+        CPLError(CE_Failure, CPLE_AppDefined,
                  "Error in the Type of StyleTool, Type undetermined\n");
         CSLDestroy( papszToken );
         CSLDestroy( papszToken2 );
         return FALSE;
         break;
     }
-    
+
     ////////////////////////////////////////////////////////////////////////
-    // Here we will loop on each element in the StyleString. If it's 
-    // a valid element, we will add it in the StyleTool with 
+    // Here we will loop on each element in the StyleString. If it's
+    // a valid element, we will add it in the StyleTool with
     // SetParamStr().
     //
-    // It's important to note that the SetInternalUnit...() is use to update 
-    // the unit of the StyleTool param (m_eUnit). 
+    // It's important to note that the SetInternalUnit...() is use to update
+    // the unit of the StyleTool param (m_eUnit).
     // See OGRStyleTool::SetParamStr().
-    // There's a StyleTool unit (m_eUnit), which is the output unit, and each 
+    // There's a StyleTool unit (m_eUnit), which is the output unit, and each
     // parameter of the style have its own unit value (the input unit). Here we
     // set m_eUnit to the input unit and in SetParamStr(), we will use this
-    // value to set the input unit. Then after the loop we will reset m_eUnit 
+    // value to set the input unit. Then after the loop we will reset m_eUnit
     // to it's original value. (Yes it's a side effect / black magic)
     //
     // The pasStyle variable is a global variable passed in argument to the
-    // function. See at the top of this file the four OGRStyleParamId 
-    // variable. They are used to register the valid parameter of each 
+    // function. See at the top of this file the four OGRStyleParamId
+    // variable. They are used to register the valid parameter of each
     // StyleTool.
     ////////////////////////////////////////////////////////////////////////
 
-    // Save Scale and output Units because the parsing code will alter 
+    // Save Scale and output Units because the parsing code will alter
     // the values
     eLastUnit = m_eUnit;
     double  dSavedScale = m_dfScale;
@@ -1808,10 +1801,10 @@ GBool OGRStyleTool::Parse(const OGRStyleParamId *pasStyle,
     for ( i = 0; i < nElements; i++ )
     {
         char    **papszStylePair =
-            CSLTokenizeString2( papszToken2[i], ":", 
-                                CSLT_HONOURSTRINGS 
+            CSLTokenizeString2( papszToken2[i], ":",
+                                CSLT_HONOURSTRINGS
                                 | CSLT_STRIPLEADSPACES
-                                | CSLT_STRIPENDSPACES 
+                                | CSLT_STRIPENDSPACES
                                 | CSLT_ALLOWEMPTYTOKENS );
 
         int     j, nTokens = CSLCount(papszStylePair);
@@ -1826,12 +1819,12 @@ GBool OGRStyleTool::Parse(const OGRStyleParamId *pasStyle,
             CSLDestroy(papszStylePair);
             continue;
         }
-        
+
         for ( j = 0; j < nCount; j++ )
         {
             if ( EQUAL(pasStyle[j].pszToken, papszStylePair[0]) )
             {
-                if (nTokens == 2 && pasStyle[j].bGeoref == TRUE)
+                if (papszStylePair[1] != NULL && pasStyle[j].bGeoref == TRUE)
                     SetInternalInputUnitFromParam(papszStylePair[1]);
 
                 // Set either the actual value of style parameter or "1"
@@ -1839,7 +1832,7 @@ GBool OGRStyleTool::Parse(const OGRStyleParamId *pasStyle,
                 // "1" means that boolean parameter is present in the style
                 // string.
                 OGRStyleTool::SetParamStr( pasStyle[j], pasValue[j],
-                                    (nTokens == 2) ? papszStylePair[1] : "1" );
+                                    (papszStylePair[1] != NULL) ? papszStylePair[1] : "1" );
 
                 break;
             }
@@ -1910,7 +1903,7 @@ void OGRStyleTool::SetInternalInputUnitFromParam(char *pszString)
         pszUnit[0]= '\0';
         return;
     }
-    
+
     SetUnit(OGRSTUMM);
 }
 
@@ -2000,13 +1993,13 @@ const char *OGRStyleTool::GetParamStr(const OGRStyleParamId &sStyleParam ,
     }
 
     bValueIsNull = !sStyleValue.bValid;
-    
+
     if (bValueIsNull == TRUE)
       return NULL;
 
     switch (sStyleParam.eType)
     {
-      
+
         // if sStyleParam.bGeoref == TRUE , need to convert to output value;
       case OGRSTypeString:
         return sStyleValue.pszValue;
@@ -2016,7 +2009,7 @@ const char *OGRStyleTool::GetParamStr(const OGRStyleParamId &sStyleParam ,
                                                  sStyleValue.eUnit));
         else
           return CPLSPrintf("%f",sStyleValue.dfValue);
-                            
+
       case OGRSTypeInteger:
         if (sStyleParam.bGeoref)
           return CPLSPrintf("%d",ComputeWithUnit(sStyleValue.nValue,
@@ -2061,13 +2054,12 @@ double OGRStyleTool::GetParamDbl(const OGRStyleParamId &sStyleParam ,
     }
 
     bValueIsNull = !sStyleValue.bValid;
-    
+
     if (bValueIsNull == TRUE)
       return 0;
 
     switch (sStyleParam.eType)
     {
-      
         // if sStyleParam.bGeoref == TRUE , need to convert to output value;
       case OGRSTypeString:
         if (sStyleParam.bGeoref)
@@ -2085,7 +2077,7 @@ double OGRStyleTool::GetParamDbl(const OGRStyleParamId &sStyleParam ,
         if (sStyleParam.bGeoref)
           return (double)ComputeWithUnit(sStyleValue.nValue,
                                          sStyleValue.eUnit);
-        else    
+        else
           return (double)sStyleValue.nValue;
       case OGRSTypeBoolean:
         return (double)sStyleValue.nValue;
@@ -2111,7 +2103,6 @@ void OGRStyleTool::SetParamStr(const OGRStyleParamId &sStyleParam ,
     sStyleValue.eUnit = GetUnit();
     switch (sStyleParam.eType)
     {
-      
         // if sStyleParam.bGeoref == TRUE , need to convert to output value;
       case OGRSTypeString:
         sStyleValue.pszValue = CPLStrdup(pszParamString);
@@ -2145,7 +2136,7 @@ void OGRStyleTool::SetParamNum(const OGRStyleParamId &sStyleParam ,
     sStyleValue.eUnit = GetUnit();
     switch (sStyleParam.eType)
     {
-        
+
         // if sStyleParam.bGeoref == TRUE , need to convert to output value;
       case OGRSTypeString:
         sStyleValue.pszValue = CPLStrdup(CPLString().Printf("%d",nParam));
@@ -2172,14 +2163,13 @@ void OGRStyleTool::SetParamNum(const OGRStyleParamId &sStyleParam ,
 void OGRStyleTool::SetParamDbl(const OGRStyleParamId &sStyleParam ,
                                OGRStyleValue &sStyleValue,
                                double dfParam)
-{ 
+{
     Parse();
     StyleModified();
     sStyleValue.bValid = TRUE;
     sStyleValue.eUnit = GetUnit();
     switch (sStyleParam.eType)
     {
-        
         // if sStyleParam.bGeoref == TRUE , need to convert to output value;
       case OGRSTypeString:
         sStyleValue.pszValue = CPLStrdup(CPLString().Printf("%f",dfParam));
@@ -2204,10 +2194,10 @@ void OGRStyleTool::SetParamDbl(const OGRStyleParamId &sStyleParam ,
  * \brief Get Style Tool parameter value as string
  *
  * Maps to the OGRStyleTool subclasses' GetParamStr() methods.
- * 
+ *
  * @param hST handle to the style tool.
  * @param eParam the parameter id from the enumeration corresponding to the
- * type of this style tool (one of the OGRSTPenParam, OGRSTBrushParam, 
+ * type of this style tool (one of the OGRSTPenParam, OGRSTBrushParam,
  * OGRSTSymbolParam or OGRSTLabelParam enumerations)
  * @param bValueIsNull pointer to an integer that will be set to TRUE or FALSE
  * to indicate whether the parameter value is NULL.
@@ -2226,11 +2216,11 @@ const char *OGR_ST_GetParamStr( OGRStyleToolH hST, int eParam, int *bValueIsNull
     switch( ((OGRStyleTool *) hST)->GetType() )
     {
       case OGRSTCPen:
-        pszVal = ((OGRStylePen *) hST)->GetParamStr((OGRSTPenParam)eParam, 
+        pszVal = ((OGRStylePen *) hST)->GetParamStr((OGRSTPenParam)eParam,
                                                     bIsNull);
         break;
       case OGRSTCBrush:
-        pszVal = ((OGRStyleBrush *) hST)->GetParamStr((OGRSTBrushParam)eParam, 
+        pszVal = ((OGRStyleBrush *) hST)->GetParamStr((OGRSTBrushParam)eParam,
                                                       bIsNull);
         break;
       case OGRSTCSymbol:
@@ -2238,7 +2228,7 @@ const char *OGR_ST_GetParamStr( OGRStyleToolH hST, int eParam, int *bValueIsNull
                                                        bIsNull);
         break;
       case OGRSTCLabel:
-        pszVal = ((OGRStyleLabel *) hST)->GetParamStr((OGRSTLabelParam)eParam, 
+        pszVal = ((OGRStyleLabel *) hST)->GetParamStr((OGRSTLabelParam)eParam,
                                                       bIsNull);
         break;
       default:
@@ -2256,10 +2246,10 @@ const char *OGR_ST_GetParamStr( OGRStyleToolH hST, int eParam, int *bValueIsNull
  * \brief Get Style Tool parameter value as an integer
  *
  * Maps to the OGRStyleTool subclasses' GetParamNum() methods.
- * 
+ *
  * @param hST handle to the style tool.
  * @param eParam the parameter id from the enumeration corresponding to the
- * type of this style tool (one of the OGRSTPenParam, OGRSTBrushParam, 
+ * type of this style tool (one of the OGRSTPenParam, OGRSTBrushParam,
  * OGRSTSymbolParam or OGRSTLabelParam enumerations)
  * @param bValueIsNull pointer to an integer that will be set to TRUE or FALSE
  * to indicate whether the parameter value is NULL.
@@ -2278,11 +2268,11 @@ int OGR_ST_GetParamNum( OGRStyleToolH hST, int eParam, int *bValueIsNull )
     switch( ((OGRStyleTool *) hST)->GetType() )
     {
       case OGRSTCPen:
-        nVal = ((OGRStylePen *) hST)->GetParamNum((OGRSTPenParam)eParam, 
+        nVal = ((OGRStylePen *) hST)->GetParamNum((OGRSTPenParam)eParam,
                                                     bIsNull);
         break;
       case OGRSTCBrush:
-        nVal = ((OGRStyleBrush *) hST)->GetParamNum((OGRSTBrushParam)eParam, 
+        nVal = ((OGRStyleBrush *) hST)->GetParamNum((OGRSTBrushParam)eParam,
                                                       bIsNull);
         break;
       case OGRSTCSymbol:
@@ -2290,7 +2280,7 @@ int OGR_ST_GetParamNum( OGRStyleToolH hST, int eParam, int *bValueIsNull )
                                                        bIsNull);
         break;
       case OGRSTCLabel:
-        nVal = ((OGRStyleLabel *) hST)->GetParamNum((OGRSTLabelParam)eParam, 
+        nVal = ((OGRStyleLabel *) hST)->GetParamNum((OGRSTLabelParam)eParam,
                                                       bIsNull);
         break;
       default:
@@ -2308,10 +2298,10 @@ int OGR_ST_GetParamNum( OGRStyleToolH hST, int eParam, int *bValueIsNull )
  * \brief Get Style Tool parameter value as a double
  *
  * Maps to the OGRStyleTool subclasses' GetParamDbl() methods.
- * 
+ *
  * @param hST handle to the style tool.
  * @param eParam the parameter id from the enumeration corresponding to the
- * type of this style tool (one of the OGRSTPenParam, OGRSTBrushParam, 
+ * type of this style tool (one of the OGRSTPenParam, OGRSTBrushParam,
  * OGRSTSymbolParam or OGRSTLabelParam enumerations)
  * @param bValueIsNull pointer to an integer that will be set to TRUE or FALSE
  * to indicate whether the parameter value is NULL.
@@ -2330,11 +2320,11 @@ double OGR_ST_GetParamDbl( OGRStyleToolH hST, int eParam, int *bValueIsNull )
     switch( ((OGRStyleTool *) hST)->GetType() )
     {
       case OGRSTCPen:
-        dfVal = ((OGRStylePen *) hST)->GetParamDbl((OGRSTPenParam)eParam, 
+        dfVal = ((OGRStylePen *) hST)->GetParamDbl((OGRSTPenParam)eParam,
                                                   bIsNull);
         break;
       case OGRSTCBrush:
-        dfVal = ((OGRStyleBrush *) hST)->GetParamDbl((OGRSTBrushParam)eParam, 
+        dfVal = ((OGRStyleBrush *) hST)->GetParamDbl((OGRSTBrushParam)eParam,
                                                     bIsNull);
         break;
       case OGRSTCSymbol:
@@ -2342,7 +2332,7 @@ double OGR_ST_GetParamDbl( OGRStyleToolH hST, int eParam, int *bValueIsNull )
                                                      bIsNull);
         break;
       case OGRSTCLabel:
-        dfVal = ((OGRStyleLabel *) hST)->GetParamDbl((OGRSTLabelParam)eParam, 
+        dfVal = ((OGRStyleLabel *) hST)->GetParamDbl((OGRSTLabelParam)eParam,
                                                     bIsNull);
         break;
       default:
@@ -2361,10 +2351,10 @@ double OGR_ST_GetParamDbl( OGRStyleToolH hST, int eParam, int *bValueIsNull )
  * \brief Set Style Tool parameter value from a string
  *
  * Maps to the OGRStyleTool subclasses' SetParamStr() methods.
- * 
+ *
  * @param hST handle to the style tool.
  * @param eParam the parameter id from the enumeration corresponding to the
- * type of this style tool (one of the OGRSTPenParam, OGRSTBrushParam, 
+ * type of this style tool (one of the OGRSTPenParam, OGRSTBrushParam,
  * OGRSTSymbolParam or OGRSTLabelParam enumerations)
  * @param pszValue the new parameter value
  *
@@ -2378,11 +2368,11 @@ void OGR_ST_SetParamStr( OGRStyleToolH hST, int eParam, const char *pszValue )
     switch( ((OGRStyleTool *) hST)->GetType() )
     {
       case OGRSTCPen:
-        ((OGRStylePen *) hST)->SetParamStr((OGRSTPenParam)eParam, 
+        ((OGRStylePen *) hST)->SetParamStr((OGRSTPenParam)eParam,
                                            pszValue);
         break;
       case OGRSTCBrush:
-        ((OGRStyleBrush *) hST)->SetParamStr((OGRSTBrushParam)eParam, 
+        ((OGRStyleBrush *) hST)->SetParamStr((OGRSTBrushParam)eParam,
                                              pszValue);
         break;
       case OGRSTCSymbol:
@@ -2390,7 +2380,7 @@ void OGR_ST_SetParamStr( OGRStyleToolH hST, int eParam, const char *pszValue )
                                               pszValue);
         break;
       case OGRSTCLabel:
-        ((OGRStyleLabel *) hST)->SetParamStr((OGRSTLabelParam)eParam, 
+        ((OGRStyleLabel *) hST)->SetParamStr((OGRSTLabelParam)eParam,
                                              pszValue);
         break;
       default:
@@ -2406,10 +2396,10 @@ void OGR_ST_SetParamStr( OGRStyleToolH hST, int eParam, const char *pszValue )
  * \brief Set Style Tool parameter value from an integer
  *
  * Maps to the OGRStyleTool subclasses' SetParamNum() methods.
- * 
+ *
  * @param hST handle to the style tool.
  * @param eParam the parameter id from the enumeration corresponding to the
- * type of this style tool (one of the OGRSTPenParam, OGRSTBrushParam, 
+ * type of this style tool (one of the OGRSTPenParam, OGRSTBrushParam,
  * OGRSTSymbolParam or OGRSTLabelParam enumerations)
  * @param nValue the new parameter value
  *
@@ -2422,11 +2412,11 @@ void OGR_ST_SetParamNum( OGRStyleToolH hST, int eParam, int nValue )
     switch( ((OGRStyleTool *) hST)->GetType() )
     {
       case OGRSTCPen:
-        ((OGRStylePen *) hST)->SetParamNum((OGRSTPenParam)eParam, 
+        ((OGRStylePen *) hST)->SetParamNum((OGRSTPenParam)eParam,
                                            nValue);
         break;
       case OGRSTCBrush:
-        ((OGRStyleBrush *) hST)->SetParamNum((OGRSTBrushParam)eParam, 
+        ((OGRStyleBrush *) hST)->SetParamNum((OGRSTBrushParam)eParam,
                                              nValue);
         break;
       case OGRSTCSymbol:
@@ -2434,7 +2424,7 @@ void OGR_ST_SetParamNum( OGRStyleToolH hST, int eParam, int nValue )
                                               nValue);
         break;
       case OGRSTCLabel:
-        ((OGRStyleLabel *) hST)->SetParamNum((OGRSTLabelParam)eParam, 
+        ((OGRStyleLabel *) hST)->SetParamNum((OGRSTLabelParam)eParam,
                                              nValue);
         break;
       default:
@@ -2449,10 +2439,10 @@ void OGR_ST_SetParamNum( OGRStyleToolH hST, int eParam, int nValue )
  * \brief Set Style Tool parameter value from a double
  *
  * Maps to the OGRStyleTool subclasses' SetParamDbl() methods.
- * 
+ *
  * @param hST handle to the style tool.
  * @param eParam the parameter id from the enumeration corresponding to the
- * type of this style tool (one of the OGRSTPenParam, OGRSTBrushParam, 
+ * type of this style tool (one of the OGRSTPenParam, OGRSTBrushParam,
  * OGRSTSymbolParam or OGRSTLabelParam enumerations)
  * @param dfValue the new parameter value
  *
@@ -2465,11 +2455,11 @@ void OGR_ST_SetParamDbl( OGRStyleToolH hST, int eParam, double dfValue )
     switch( ((OGRStyleTool *) hST)->GetType() )
     {
       case OGRSTCPen:
-        ((OGRStylePen *) hST)->SetParamDbl((OGRSTPenParam)eParam, 
+        ((OGRStylePen *) hST)->SetParamDbl((OGRSTPenParam)eParam,
                                            dfValue);
         break;
       case OGRSTCBrush:
-        ((OGRStyleBrush *) hST)->SetParamDbl((OGRSTBrushParam)eParam, 
+        ((OGRStyleBrush *) hST)->SetParamDbl((OGRSTBrushParam)eParam,
                                              dfValue);
         break;
       case OGRSTCSymbol:
@@ -2477,7 +2467,7 @@ void OGR_ST_SetParamDbl( OGRStyleToolH hST, int eParam, double dfValue )
                                               dfValue);
         break;
       case OGRSTCLabel:
-        ((OGRStyleLabel *) hST)->SetParamDbl((OGRSTLabelParam)eParam, 
+        ((OGRStyleLabel *) hST)->SetParamDbl((OGRSTLabelParam)eParam,
                                              dfValue);
         break;
       default:
@@ -2493,7 +2483,7 @@ void OGR_ST_SetParamDbl( OGRStyleToolH hST, int eParam, double dfValue )
  * \brief Get the style string for this Style Tool
  *
  * Maps to the OGRStyleTool subclasses' GetStyleString() methods.
- * 
+ *
  * @param hST handle to the style tool.
  *
  * @return the style string for this style tool or "" if the hST is invalid.
@@ -2533,7 +2523,7 @@ const char *OGR_ST_GetStyleString( OGRStyleToolH hST )
  * \brief Return the r,g,b,a components of a color encoded in \#RRGGBB[AA] format
  *
  * Maps to OGRStyleTool::GetRGBFromString().
- * 
+ *
  * @param hST handle to the style tool.
  * @param pszColor the color to parse
  * @param pnRed pointer to an int in which the red value will be returned
@@ -2542,11 +2532,11 @@ const char *OGR_ST_GetStyleString( OGRStyleToolH hST )
  * @param pnAlpha pointer to an int in which the (optional) alpha value will
  * be returned
  *
- * @return TRUE if the color could be succesfully parsed, or FALSE in case of
+ * @return TRUE if the color could be successfully parsed, or FALSE in case of
  * errors.
  */
 
-int OGR_ST_GetRGBFromString( OGRStyleToolH hST, const char *pszColor, 
+int OGR_ST_GetRGBFromString( OGRStyleToolH hST, const char *pszColor,
                              int *pnRed, int *pnGreen, int *pnBlue,
                              int *pnAlpha )
 {
@@ -2574,7 +2564,7 @@ int OGR_ST_GetRGBFromString( OGRStyleToolH hST, const char *pszColor,
 /****************************************************************************/
 OGRStylePen::OGRStylePen() : OGRStyleTool(OGRSTCPen)
 {
-    m_pasStyleValue = (OGRStyleValue *)CPLCalloc(OGRSTPenLast, 
+    m_pasStyleValue = (OGRStyleValue *)CPLCalloc(OGRSTPenLast,
                                                  sizeof(OGRStyleValue));
 }
 
@@ -2604,7 +2594,7 @@ OGRStylePen::~OGRStylePen()
 /************************************************************************/
 GBool OGRStylePen::Parse()
 
-{ 
+{
     return OGRStyleTool::Parse(asStylePen,m_pasStyleValue,(int)OGRSTPenLast);
 }
 
@@ -2612,7 +2602,7 @@ GBool OGRStylePen::Parse()
 /*                            GetParamStr()                             */
 /************************************************************************/
 const char *OGRStylePen::GetParamStr(OGRSTPenParam eParam, GBool &bValueIsNull)
-{   
+{
     return OGRStyleTool::GetParamStr(asStylePen[eParam],
                                      m_pasStyleValue[eParam],
                                      bValueIsNull);
@@ -2622,7 +2612,7 @@ const char *OGRStylePen::GetParamStr(OGRSTPenParam eParam, GBool &bValueIsNull)
 /*                            GetParamNum()                             */
 /************************************************************************/
 int OGRStylePen::GetParamNum(OGRSTPenParam eParam,GBool &bValueIsNull)
-{  
+{
     return OGRStyleTool::GetParamNum(asStylePen[eParam],
                                      m_pasStyleValue[eParam],bValueIsNull);
 }
@@ -2631,7 +2621,7 @@ int OGRStylePen::GetParamNum(OGRSTPenParam eParam,GBool &bValueIsNull)
 /*                            GetParamDbl()                             */
 /************************************************************************/
 double OGRStylePen::GetParamDbl(OGRSTPenParam eParam,GBool &bValueIsNull)
-{  
+{
     return OGRStyleTool::GetParamDbl(asStylePen[eParam],
                                      m_pasStyleValue[eParam],bValueIsNull);
 }
@@ -2641,7 +2631,7 @@ double OGRStylePen::GetParamDbl(OGRSTPenParam eParam,GBool &bValueIsNull)
 /************************************************************************/
 
 void OGRStylePen::SetParamStr(OGRSTPenParam eParam, const char *pszParamString)
-{   
+{
     OGRStyleTool::SetParamStr(asStylePen[eParam],m_pasStyleValue[eParam],
                               pszParamString);
 }
@@ -2650,16 +2640,16 @@ void OGRStylePen::SetParamStr(OGRSTPenParam eParam, const char *pszParamString)
 /*                            SetParamNum()                             */
 /************************************************************************/
 void OGRStylePen::SetParamNum(OGRSTPenParam eParam, int nParam)
-{  
+{
     OGRStyleTool::SetParamNum(asStylePen[eParam],
                               m_pasStyleValue[eParam],nParam);
 }
-    
+
 /************************************************************************/
 /*                            SetParamDbl()                             */
 /************************************************************************/
 void OGRStylePen::SetParamDbl(OGRSTPenParam eParam, double dfParam)
-{   
+{
     OGRStyleTool::SetParamDbl(asStylePen[eParam],
                               m_pasStyleValue[eParam],dfParam);
 }
@@ -2668,7 +2658,7 @@ void OGRStylePen::SetParamDbl(OGRSTPenParam eParam, double dfParam)
 /*                           GetStyleString()                           */
 /************************************************************************/
 const char *OGRStylePen::GetStyleString()
-{   
+{
     return OGRStyleTool::GetStyleString(asStylePen,m_pasStyleValue,
                                         (int)OGRSTPenLast);
 }
@@ -2679,7 +2669,7 @@ const char *OGRStylePen::GetStyleString()
 /****************************************************************************/
 OGRStyleBrush::OGRStyleBrush() : OGRStyleTool(OGRSTCBrush)
 {
-    m_pasStyleValue = (OGRStyleValue *)CPLCalloc(OGRSTBrushLast, 
+    m_pasStyleValue = (OGRStyleValue *)CPLCalloc(OGRSTBrushLast,
                                                  sizeof(OGRStyleValue));
 }
 
@@ -2687,7 +2677,7 @@ OGRStyleBrush::OGRStyleBrush() : OGRStyleTool(OGRSTCBrush)
 /*                      OGRStyleBrush::~OGRStyleBrush()                     */
 /*                                                                          */
 /****************************************************************************/
-OGRStyleBrush::~OGRStyleBrush() 
+OGRStyleBrush::~OGRStyleBrush()
 {
     for (int i = 0; i < OGRSTBrushLast; i++)
     {
@@ -2705,7 +2695,7 @@ OGRStyleBrush::~OGRStyleBrush()
 /*                               Parse()                                */
 /************************************************************************/
 GBool OGRStyleBrush::Parse()
-{ 
+{
     return OGRStyleTool::Parse(asStyleBrush,m_pasStyleValue,
                                (int)OGRSTBrushLast);
 }
@@ -2714,7 +2704,7 @@ GBool OGRStyleBrush::Parse()
 /*                            GetParamStr()                             */
 /************************************************************************/
 const char *OGRStyleBrush::GetParamStr(OGRSTBrushParam eParam, GBool &bValueIsNull)
-{  
+{
     return OGRStyleTool::GetParamStr(asStyleBrush[eParam],
                                      m_pasStyleValue[eParam],
                                      bValueIsNull);
@@ -2724,7 +2714,7 @@ const char *OGRStyleBrush::GetParamStr(OGRSTBrushParam eParam, GBool &bValueIsNu
 /*                            GetParamNum()                             */
 /************************************************************************/
 int OGRStyleBrush::GetParamNum(OGRSTBrushParam eParam,GBool &bValueIsNull)
-{  
+{
     return OGRStyleTool::GetParamNum(asStyleBrush[eParam],
                                      m_pasStyleValue[eParam],bValueIsNull);
 }
@@ -2733,7 +2723,7 @@ int OGRStyleBrush::GetParamNum(OGRSTBrushParam eParam,GBool &bValueIsNull)
 /*                            GetParamDbl()                             */
 /************************************************************************/
 double OGRStyleBrush::GetParamDbl(OGRSTBrushParam eParam,GBool &bValueIsNull)
-{  
+{
     return OGRStyleTool::GetParamDbl(asStyleBrush[eParam],
                                      m_pasStyleValue[eParam],bValueIsNull);
 }
@@ -2742,7 +2732,7 @@ double OGRStyleBrush::GetParamDbl(OGRSTBrushParam eParam,GBool &bValueIsNull)
 /*                            SetParamStr()                             */
 /************************************************************************/
 void OGRStyleBrush::SetParamStr(OGRSTBrushParam eParam, const char *pszParamString)
-{   
+{
     OGRStyleTool::SetParamStr(asStyleBrush[eParam],m_pasStyleValue[eParam],
                               pszParamString);
 }
@@ -2751,16 +2741,16 @@ void OGRStyleBrush::SetParamStr(OGRSTBrushParam eParam, const char *pszParamStri
 /*                            SetParamNum()                             */
 /************************************************************************/
 void OGRStyleBrush::SetParamNum(OGRSTBrushParam eParam, int nParam)
-{  
+{
     OGRStyleTool::SetParamNum(asStyleBrush[eParam],
                               m_pasStyleValue[eParam],nParam);
 }
-    
+
 /************************************************************************/
 /*                            SetParamDbl()                             */
 /************************************************************************/
 void OGRStyleBrush::SetParamDbl(OGRSTBrushParam eParam, double dfParam)
-{   
+{
     OGRStyleTool::SetParamDbl(asStyleBrush[eParam],
                               m_pasStyleValue[eParam],dfParam);
 }
@@ -2769,7 +2759,7 @@ void OGRStyleBrush::SetParamDbl(OGRSTBrushParam eParam, double dfParam)
 /*                           GetStyleString()                           */
 /************************************************************************/
 const char *OGRStyleBrush::GetStyleString()
-{   
+{
     return OGRStyleTool::GetStyleString(asStyleBrush,m_pasStyleValue,
                                         (int)OGRSTBrushLast);
 }
@@ -2779,7 +2769,7 @@ const char *OGRStyleBrush::GetStyleString()
 /****************************************************************************/
 OGRStyleSymbol::OGRStyleSymbol() : OGRStyleTool(OGRSTCSymbol)
 {
-    m_pasStyleValue = (OGRStyleValue *)CPLCalloc(OGRSTSymbolLast, 
+    m_pasStyleValue = (OGRStyleValue *)CPLCalloc(OGRSTSymbolLast,
                                                  sizeof(OGRStyleValue));
 }
 
@@ -2805,7 +2795,7 @@ OGRStyleSymbol::~OGRStyleSymbol()
 /*                               Parse()                                */
 /************************************************************************/
 GBool OGRStyleSymbol::Parse()
-{ 
+{
     return OGRStyleTool::Parse(asStyleSymbol,m_pasStyleValue,
                                (int)OGRSTSymbolLast);
 }
@@ -2860,7 +2850,7 @@ void OGRStyleSymbol::SetParamDbl(OGRSTSymbolParam eParam, double dfParam)
 /*                           GetStyleString()                           */
 /************************************************************************/
 const char *OGRStyleSymbol::GetStyleString()
-{   
+{
     return OGRStyleTool::GetStyleString(asStyleSymbol,m_pasStyleValue,
                                         (int)OGRSTSymbolLast);
 }
@@ -2872,7 +2862,7 @@ const char *OGRStyleSymbol::GetStyleString()
 /****************************************************************************/
 OGRStyleLabel::OGRStyleLabel() : OGRStyleTool(OGRSTCLabel)
 {
-    m_pasStyleValue = (OGRStyleValue *)CPLCalloc(OGRSTLabelLast, 
+    m_pasStyleValue = (OGRStyleValue *)CPLCalloc(OGRSTLabelLast,
                                                  sizeof(OGRStyleValue));
 }
 
@@ -2953,4 +2943,3 @@ const char *OGRStyleLabel::GetStyleString()
 {   return OGRStyleTool::GetStyleString(asStyleLabel,m_pasStyleValue,
                                         (int)OGRSTLabelLast);
 }
-
diff --git a/ogr/ogrfielddefn.cpp b/ogr/ogrfielddefn.cpp
index 20e615a..3c78aac 100644
--- a/ogr/ogrfielddefn.cpp
+++ b/ogr/ogrfielddefn.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrfielddefn.cpp 28806 2015-03-28 14:37:47Z rouault $
+ * $Id: ogrfielddefn.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRFieldDefn class implementation.
@@ -33,7 +33,7 @@
 #include "ogr_p.h"
 #include "ograpispy.h"
 
-CPL_CVSID("$Id: ogrfielddefn.cpp 28806 2015-03-28 14:37:47Z rouault $");
+CPL_CVSID("$Id: ogrfielddefn.cpp 33631 2016-03-04 06:28:09Z goatbar $");
 
 /************************************************************************/
 /*                            OGRFieldDefn()                            */
@@ -208,7 +208,7 @@ void OGR_Fld_SetName( OGRFieldDefnH hDefn, const char *pszName )
  *
  * @param hDefn handle to the field definition.
  * @return the name of the field definition.
- * 
+ *
  */
 
 const char *OGR_Fld_GetNameRef( OGRFieldDefnH hDefn )
@@ -272,7 +272,7 @@ OGRFieldType OGR_Fld_GetType( OGRFieldDefnH hDefn )
  *
  * This method is the same as the C function OGR_Fld_SetType().
  *
- * @param eType the new field type.
+ * @param eTypeIn the new field type.
  */
 
 void OGRFieldDefn::SetType( OGRFieldType eTypeIn )
@@ -358,7 +358,7 @@ OGRFieldSubType OGR_Fld_GetSubType( OGRFieldDefnH hDefn )
  *
  * This method is the same as the C function OGR_Fld_SetSubType().
  *
- * @param eSubType the new field subtype.
+ * @param eSubTypeIn the new field subtype.
  * @since GDAL 2.0
  */
 void OGRFieldDefn::SetSubType( OGRFieldSubType eSubTypeIn )
@@ -410,7 +410,7 @@ void OGR_Fld_SetSubType( OGRFieldDefnH hDefn, OGRFieldSubType eSubType )
  * low-level layers to do the job. So retrieving the feature from the layer is
  * recommended.
  *
- * The accepted values are NULL, a numeric value, a litteral value enclosed
+ * The accepted values are NULL, a numeric value, a literal value enclosed
  * between single quote characters (and inner single quote characters escaped by
  * repetition of the single quote character),
  * CURRENT_TIMESTAMP, CURRENT_TIME, CURRENT_DATE or
@@ -423,7 +423,7 @@ void OGR_Fld_SetSubType( OGRFieldDefnH hDefn, OGRFieldSubType eSubType )
  *
  * This function is the same as the C function OGR_Fld_SetDefault().
  *
- * @param pszDefault new default field value or NULL pointer.
+ * @param pszDefaultIn new default field value or NULL pointer.
  *
  * @since GDAL 2.0
  */
@@ -480,7 +480,7 @@ void OGRFieldDefn::SetDefault( const char* pszDefaultIn )
  * low-level layers to do the job. So retrieving the feature from the layer is
  * recommended.
  *
- * The accepted values are NULL, a numeric value, a litteral value enclosed
+ * The accepted values are NULL, a numeric value, a literal value enclosed
  * between single quote characters (and inner single quote characters escaped by
  * repetition of the single quote character),
  * CURRENT_TIMESTAMP, CURRENT_TIME, CURRENT_DATE or
@@ -549,11 +549,13 @@ const char *OGR_Fld_GetDefault( OGRFieldDefnH hDefn )
 /**
  * \brief Returns whether the default value is driver specific.
  *
- * Driver specific default values are those that are *not* NULL, a numeric value,
- * a litteral value enclosed between single quote characters, CURRENT_TIMESTAMP,
- * CURRENT_TIME, CURRENT_DATE or datetime literal value.
+ * Driver specific default values are those that are *not* NULL, a
+ * numeric value, a literal value enclosed between single quote
+ * characters, CURRENT_TIMESTAMP, CURRENT_TIME, CURRENT_DATE or
+ * datetime literal value.
  *
- * This method is the same as the C function OGR_Fld_IsDefaultDriverSpecific().
+ * This method is the same as the C function
+ * OGR_Fld_IsDefaultDriverSpecific().
  *
  * @return TRUE if the default value is driver specific.
  * @since GDAL 2.0
@@ -588,11 +590,13 @@ int OGRFieldDefn::IsDefaultDriverSpecific() const
 /**
  * \brief Returns whether the default value is driver specific.
  *
- * Driver specific default values are those that are *not* NULL, a numeric value,
- * a litteral value enclosed between single quote characters, CURRENT_TIMESTAMP,
- * CURRENT_TIME, CURRENT_DATE or datetime literal value.
+ * Driver specific default values are those that are *not* NULL, a
+ * numeric value, a literal value enclosed between single quote
+ * characters, CURRENT_TIMESTAMP, CURRENT_TIME, CURRENT_DATE or
+ * datetime literal value.
  *
- * This function is the same as the C++ method OGRFieldDefn::IsDefaultDriverSpecific().
+ * This function is the same as the C++ method
+ * OGRFieldDefn::IsDefaultDriverSpecific().
  *
  * @param hDefn handle to the field definition
  * @return TRUE if the default value is driver specific.
@@ -671,7 +675,7 @@ const char * OGRFieldDefn::GetFieldTypeName( OGRFieldType eType )
 /**
  * \brief Fetch human readable name for a field type.
  *
- * This function is the same as the CPP method 
+ * This function is the same as the CPP method
  * OGRFieldDefn::GetFieldTypeName().
  *
  * @param eType the field type to get name for.
@@ -729,7 +733,7 @@ const char * OGRFieldDefn::GetFieldSubTypeName( OGRFieldSubType eSubType )
 /**
  * \brief Fetch human readable name for a field subtype.
  *
- * This function is the same as the CPP method 
+ * This function is the same as the CPP method
  * OGRFieldDefn::GetFieldSubTypeName().
  *
  * @param eSubType the field subtype to get name for.
@@ -851,7 +855,7 @@ void OGR_Fld_SetJustify( OGRFieldDefnH hDefn, OGRJustification eJustify )
  *
  * This method is the same as the C function OGR_Fld_GetWidth().
  *
- * @return the width, zero means no specified width. 
+ * @return the width, zero means no specified width.
  */
 
 /************************************************************************/
@@ -863,7 +867,7 @@ void OGR_Fld_SetJustify( OGRFieldDefnH hDefn, OGRJustification eJustify )
  * This function is the same as the CPP method OGRFieldDefn::GetWidth().
  *
  * @param hDefn handle to the field definition to get width from.
- * @return the width, zero means no specified width. 
+ * @return the width, zero means no specified width.
  */
 
 int OGR_Fld_GetWidth( OGRFieldDefnH hDefn )
@@ -948,12 +952,12 @@ int OGR_Fld_GetPrecision( OGRFieldDefnH hDefn )
  * \fn void OGRFieldDefn::SetPrecision( int nPrecision );
  *
  * \brief Set the formatting precision for this field in characters.
- * 
- * This should normally be zero for fields of types other than OFTReal. 
+ *
+ * This should normally be zero for fields of types other than OFTReal.
  *
  * This method is the same as the C function OGR_Fld_SetPrecision().
  *
- * @param nPrecision the new precision. 
+ * @param nPrecision the new precision.
  */
 
 /************************************************************************/
@@ -961,13 +965,13 @@ int OGR_Fld_GetPrecision( OGRFieldDefnH hDefn )
 /************************************************************************/
 /**
  * \brief Set the formatting precision for this field in characters.
- * 
- * This should normally be zero for fields of types other than OFTReal. 
+ *
+ * This should normally be zero for fields of types other than OFTReal.
  *
  * This function is the same as the CPP method OGRFieldDefn::SetPrecision().
  *
  * @param hDefn handle to the field definition to set precision to.
- * @param nPrecision the new precision. 
+ * @param nPrecision the new precision.
  */
 
 void OGR_Fld_SetPrecision( OGRFieldDefnH hDefn, int nPrecision )
@@ -986,7 +990,7 @@ void OGR_Fld_SetPrecision( OGRFieldDefnH hDefn, int nPrecision )
  * This method is the same as the C function OGR_Fld_Set().
  *
  * @param pszNameIn the new name to assign.
- * @param eTypeIn the new type (one of the OFT values like OFTInteger). 
+ * @param eTypeIn the new type (one of the OFT values like OFTInteger).
  * @param nWidthIn the preferred formatting width.  Defaults to zero indicating
  * undefined.
  * @param nPrecisionIn number of decimals places for formatting, defaults to
@@ -1017,7 +1021,7 @@ void OGRFieldDefn::Set( const char *pszNameIn,
  *
  * @param hDefn handle to the field definition to set to.
  * @param pszNameIn the new name to assign.
- * @param eTypeIn the new type (one of the OFT values like OFTInteger). 
+ * @param eTypeIn the new type (one of the OFT values like OFTInteger).
  * @param nWidthIn the preferred formatting width.  Defaults to zero indicating
  * undefined.
  * @param nPrecisionIn number of decimals places for formatting, defaults to
@@ -1026,13 +1030,13 @@ void OGRFieldDefn::Set( const char *pszNameIn,
  * to OJUndefined.
  */
 
-void OGR_Fld_Set( OGRFieldDefnH hDefn, const char *pszNameIn, 
+void OGR_Fld_Set( OGRFieldDefnH hDefn, const char *pszNameIn,
                         OGRFieldType eTypeIn,
                         int nWidthIn, int nPrecisionIn,
                         OGRJustification eJustifyIn )
 
 {
-    ((OGRFieldDefn *) hDefn)->Set( pszNameIn, eTypeIn, nWidthIn, 
+    ((OGRFieldDefn *) hDefn)->Set( pszNameIn, eTypeIn, nWidthIn,
                                    nPrecisionIn, eJustifyIn );
 }
 
@@ -1214,3 +1218,158 @@ void OGR_Fld_SetNullable( OGRFieldDefnH hDefn, int bNullableIn )
 {
     ((OGRFieldDefn *) hDefn)->SetNullable( bNullableIn );
 }
+
+
+/************************************************************************/
+/*                        OGRUpdateFieldType()                          */
+/************************************************************************/
+
+/**
+ * \brief Update the type of a field definition by "merging" its existing type with a new type.
+ *
+ * The update is done such as broadening the type. For example a OFTInteger
+ * updated with OFTInteger64 will be promoted to OFTInteger64.
+ *
+ * @param poFDefn the field definition whose type must be updated.
+ * @param eNewType the new field type to merge into the existing type.
+ * @param eNewSubType the new field subtype to merge into the existing subtype.
+ * @since GDAL 2.1
+ */
+
+void OGRUpdateFieldType( OGRFieldDefn* poFDefn,
+                         OGRFieldType eNewType,
+                         OGRFieldSubType eNewSubType )
+{
+    OGRFieldType eType = poFDefn->GetType();
+    if( eType == OFTInteger )
+    {
+        if( eNewType == OFTInteger &&
+            poFDefn->GetSubType() == OFSTBoolean && eNewSubType != OFSTBoolean )
+        {
+            poFDefn->SetSubType(OFSTNone);
+        }
+        else if( eNewType == OFTInteger64 || eNewType == OFTReal )
+        {
+            poFDefn->SetSubType(OFSTNone);
+            poFDefn->SetType(eNewType);
+        }
+        else if( eNewType == OFTIntegerList || eNewType == OFTInteger64List ||
+                 eNewType == OFTRealList || eNewType == OFTStringList )
+        {
+            if( eNewType != OFTIntegerList || eNewSubType != OFSTBoolean )
+                poFDefn->SetSubType(OFSTNone);
+            poFDefn->SetType(eNewType);
+        }
+        else if( eNewType != OFTInteger )
+        {
+            poFDefn->SetSubType(OFSTNone);
+            poFDefn->SetType(OFTString);
+        }
+    }
+    else if( eType == OFTInteger64 )
+    {
+        if( eNewType == OFTReal )
+        {
+            poFDefn->SetSubType(OFSTNone);
+            poFDefn->SetType(eNewType);
+        }
+        else if( eNewType == OFTIntegerList )
+        {
+            poFDefn->SetSubType(OFSTNone);
+            poFDefn->SetType(OFTInteger64List);
+        }
+        else if( eNewType == OFTInteger64List ||
+                 eNewType == OFTRealList || eNewType == OFTStringList )
+        {
+            if( eNewType != OFTIntegerList )
+                poFDefn->SetSubType(OFSTNone);
+            poFDefn->SetType(eNewType);
+        }
+        else if( eNewType != OFTInteger && eNewType != OFTInteger64 )
+        {
+            poFDefn->SetSubType(OFSTNone);
+            poFDefn->SetType(OFTString);
+        }
+    }
+    else if( eType == OFTReal )
+    {
+        if( eNewType == OFTIntegerList || eNewType == OFTInteger64List ||
+            eNewType == OFTRealList )
+        {
+            poFDefn->SetType(OFTRealList);
+        }
+        else if( eNewType == OFTStringList )
+        {
+            poFDefn->SetType(OFTStringList);
+        }
+        else if( eNewType != OFTInteger && eNewType != OFTInteger64 &&
+                 eNewType != OFTReal )
+        {
+            poFDefn->SetSubType(OFSTNone);
+            poFDefn->SetType(OFTString);
+        }
+    }
+    else if( eType == OFTIntegerList )
+    {
+        if( eNewType == OFTIntegerList &&
+            poFDefn->GetSubType() == OFSTBoolean && eNewSubType != OFSTBoolean )
+        {
+            poFDefn->SetSubType(OFSTNone);
+        }
+        else if( eNewType == OFTInteger64 || eNewType == OFTInteger64List )
+        {
+            poFDefn->SetSubType(OFSTNone);
+            poFDefn->SetType(OFTInteger64List);
+        }
+        else if( eNewType == OFTReal || eNewType == OFTRealList )
+        {
+            poFDefn->SetSubType(OFSTNone);
+            poFDefn->SetType(OFTRealList);
+        }
+        else if( eNewType != OFTInteger && eNewType != OFTIntegerList )
+        {
+            poFDefn->SetSubType(OFSTNone);
+            poFDefn->SetType(OFTStringList);
+        }
+    }
+    else if( eType == OFTInteger64List )
+    {
+        if( eNewType == OFTReal || eNewType == OFTRealList )
+            poFDefn->SetType(OFTRealList);
+        else if( eNewType != OFTInteger && eNewType != OFTInteger64 &&
+                 eNewType != OFTIntegerList && eNewType != OFTInteger64List )
+        {
+            poFDefn->SetSubType(OFSTNone);
+            poFDefn->SetType(OFTStringList);
+        }
+    }
+    else if( eType == OFTRealList )
+    {
+        if( eNewType != OFTInteger && eNewType != OFTInteger64 &&
+            eNewType != OFTReal &&
+            eNewType != OFTIntegerList && eNewType != OFTInteger64List &&
+            eNewType != OFTRealList )
+        {
+            poFDefn->SetSubType(OFSTNone);
+            poFDefn->SetType(OFTStringList);
+        }
+    }
+    else if( eType == OFTDateTime )
+    {
+        if( eNewType != OFTDateTime && eNewType != OFTDate )
+        {
+            poFDefn->SetType(OFTString);
+        }
+    }
+    else if( eType == OFTDate || eType == OFTTime )
+    {
+        if( eNewType == OFTDateTime )
+            poFDefn->SetType(OFTDateTime);
+        else if( eNewType != eType )
+            poFDefn->SetType(OFTString);
+    }
+    else if( eType == OFTString && eNewType == OFTStringList )
+    {
+        poFDefn->SetType(OFTStringList);
+    }
+}
diff --git a/ogr/ogrgeomediageometry.cpp b/ogr/ogrgeomediageometry.cpp
index 6b6c962..94fc4eb 100644
--- a/ogr/ogrgeomediageometry.cpp
+++ b/ogr/ogrgeomediageometry.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeomediageometry.cpp 27959 2014-11-14 18:29:21Z rouault $
+ * $Id: ogrgeomediageometry.cpp 30352 2015-09-14 01:12:29Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements decoder of geomedia geometry blobs
@@ -30,7 +30,7 @@
 #include "ogrgeomediageometry.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrgeomediageometry.cpp 27959 2014-11-14 18:29:21Z rouault $");
+CPL_CVSID("$Id: ogrgeomediageometry.cpp 30352 2015-09-14 01:12:29Z goatbar $");
 
 #define GEOMEDIA_POINT          0xC0
 #define GEOMEDIA_ORIENTED_POINT 0xC8
@@ -97,8 +97,7 @@ OGRErr OGRCreateFromGeomedia( GByte *pabyGeom,
 
         OGRLineString* poLS = new OGRLineString();
         poLS->setNumPoints(nPoints);
-        int i;
-        for(i=0;i<nPoints;i++)
+        for(int i=0;i<nPoints;i++)
         {
             double dfX, dfY, dfZ;
             memcpy(&dfX, pabyGeom, 8);
@@ -134,8 +133,7 @@ OGRErr OGRCreateFromGeomedia( GByte *pabyGeom,
 
         OGRLinearRing* poRing = new OGRLinearRing();
         poRing->setNumPoints(nPoints);
-        int i;
-        for(i=0;i<nPoints;i++)
+        for(int i=0;i<nPoints;i++)
         {
             double dfX, dfY, dfZ;
             memcpy(&dfX, pabyGeom, 8);
@@ -217,10 +215,10 @@ OGRErr OGRCreateFromGeomedia( GByte *pabyGeom,
         }
         else if ( interiorGeomType == wkbMultiPolygon )
         {
-            int numGeom = ((OGRMultiPolygon*)poInteriorGeom)->getNumGeometries();
+            const int numGeom = ((OGRMultiPolygon*)poInteriorGeom)->getNumGeometries();
             for ( int i = 0; i < numGeom; ++i )
             {
-                OGRPolygon* poInteriorPolygon = 
+                OGRPolygon* poInteriorPolygon =
                     (OGRPolygon*)((OGRMultiPolygon*)poInteriorGeom)->getGeometryRef(i);
                 ((OGRPolygon*)poExteriorGeom)->addRing( poInteriorPolygon->getExteriorRing() );
             }
@@ -244,7 +242,6 @@ OGRErr OGRCreateFromGeomedia( GByte *pabyGeom,
         if (nBytes < 4)
             return OGRERR_FAILURE;
 
-        int i;
         int nParts;
         memcpy(&nParts, pabyGeom, 4);
         CPL_LSBPTR32(&nParts);
@@ -261,10 +258,10 @@ OGRErr OGRCreateFromGeomedia( GByte *pabyGeom,
             GByte* pabyGeomBackup = pabyGeom;
             int nBytesBackup = nBytes;
 
-            int bAllPolyline = TRUE;
-            int bAllPolygon = TRUE;
+            bool bAllPolyline = true;
+            bool bAllPolygon = true;
 
-            for(i=0;i<nParts;i++)
+            for(int i=0;i<nParts;i++)
             {
                 if (nBytes < 4)
                     return OGRERR_FAILURE;
@@ -293,9 +290,9 @@ OGRErr OGRCreateFromGeomedia( GByte *pabyGeom,
 
                 int nSubGeomType = pabyGeom[0];
                 if ( nSubGeomType != GEOMEDIA_POLYLINE )
-                    bAllPolyline = FALSE;
+                    bAllPolyline = false;
                 if ( nSubGeomType != GEOMEDIA_POLYGON )
-                    bAllPolygon = FALSE;
+                    bAllPolygon = false;
 
                 pabyGeom += nSubBytes;
                 nBytes -= nSubBytes;
@@ -314,10 +311,13 @@ OGRErr OGRCreateFromGeomedia( GByte *pabyGeom,
                                         (nGeomType == GEOMEDIA_MULTIPOLYGON) ? new OGRMultiPolygon() :
                                                               new OGRGeometryCollection();
 
-        for(i=0;i<nParts;i++)
+        for(int i=0;i<nParts;i++)
         {
             if (nBytes < 4)
+            {
+                delete poColl;
                 return OGRERR_FAILURE;
+            }
             int nSubBytes;
             memcpy(&nSubBytes, pabyGeom, 4);
             CPL_LSBPTR32(&nSubBytes);
diff --git a/ogr/ogrgeomediageometry.h b/ogr/ogrgeomediageometry.h
index efc906d..6de124f 100644
--- a/ogr/ogrgeomediageometry.h
+++ b/ogr/ogrgeomediageometry.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeomediageometry.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: ogrgeomediageometry.h 31777 2015-11-26 14:14:41Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements decoder of geomedia geometry blobs
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_GEOMEDIAGEOMETRY_H_INCLUDED
-#define _OGR_GEOMEDIAGEOMETRY_H_INCLUDED
+#ifndef OGR_GEOMEDIAGEOMETRY_H_INCLUDED
+#define OGR_GEOMEDIAGEOMETRY_H_INCLUDED
 
 #include "ogr_geometry.h"
 #include "ogr_spatialref.h"
diff --git a/ogr/ogrgeometry.cpp b/ogr/ogrgeometry.cpp
index fb350bc..f8b1e89 100644
--- a/ogr/ogrgeometry.cpp
+++ b/ogr/ogrgeometry.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeometry.cpp 28548 2015-02-24 17:30:15Z rouault $
+ * $Id: ogrgeometry.cpp 33757 2016-03-20 20:22:33Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements a few base methods on OGRGeometry.
@@ -35,7 +35,13 @@
 #include "cpl_multiproc.h"
 #include <assert.h>
 
-CPL_CVSID("$Id: ogrgeometry.cpp 28548 2015-02-24 17:30:15Z rouault $");
+#ifndef HAVE_GEOS
+#define UNUSED_IF_NO_GEOS CPL_UNUSED
+#else
+#define UNUSED_IF_NO_GEOS
+#endif
+
+CPL_CVSID("$Id: ogrgeometry.cpp 33757 2016-03-20 20:22:33Z goatbar $");
 
 int OGRGeometry::bGenerate_DB2_V72_BYTE_ORDER = FALSE;
 
@@ -67,7 +73,28 @@ OGRGeometry::OGRGeometry()
 
 {
     poSRS = NULL;
-    nCoordDimension = 2;
+    flags = 0;
+}
+
+/************************************************************************/
+/*                   OGRGeometry( const OGRGeometry& )                  */
+/************************************************************************/
+
+/**
+ * \brief Copy constructor.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the constructor
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRGeometry::OGRGeometry( const OGRGeometry& other ) :
+    poSRS(other.poSRS),
+    flags(other.flags)
+{
+    if( poSRS != NULL )
+        poSRS->Reference();
 }
 
 /************************************************************************/
@@ -82,6 +109,39 @@ OGRGeometry::~OGRGeometry()
 }
 
 /************************************************************************/
+/*                    operator=( const OGRGeometry&)                    */
+/************************************************************************/
+
+/**
+ * \brief Assignment operator.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the operator
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRGeometry& OGRGeometry::operator=( const OGRGeometry& other )
+{
+    if( this != &other)
+    {
+        assignSpatialReference( other.getSpatialReference() );
+        flags = other.flags;
+    }
+    return *this;
+}
+
+/************************************************************************/
+/*                               IsEmpty()                              */
+/************************************************************************/
+
+OGRBoolean OGRGeometry::IsEmpty() const
+{
+    fprintf(stderr, "Missing IsEmpty method for a class.\n");
+    exit(1);
+}
+
+/************************************************************************/
 /*                            dumpReadable()                            */
 /************************************************************************/
 
@@ -106,7 +166,7 @@ void OGRGeometry::dumpReadable( FILE * fp, const char * pszPrefix, char** papszO
 
 {
     char        *pszWkt = NULL;
-    
+
     if( pszPrefix == NULL )
         pszPrefix = "";
 
@@ -128,19 +188,41 @@ void OGRGeometry::dumpReadable( FILE * fp, const char * pszPrefix, char** papszO
             case wkbNone:
             case wkbPoint:
             case wkbPoint25D:
+            case wkbPointM:
+            case wkbPointZM:
+            case wkbPolyhedralSurface: /* not yet implemented */
+            case wkbTIN: /* not yet implemented */
+            case wkbPolyhedralSurfaceZ: /* not yet implemented */
+            case wkbTINZ: /* not yet implemented */
+            case wkbPolyhedralSurfaceM: /* not yet implemented */
+            case wkbTINM: /* not yet implemented */
+            case wkbPolyhedralSurfaceZM: /* not yet implemented */
+            case wkbTINZM: /* not yet implemented */
+            case wkbTriangle: /* not yet implemented */
+            case wkbTriangleZ: /* not yet implemented */
+            case wkbTriangleM: /* not yet implemented */
+            case wkbTriangleZM: /* not yet implemented */
                 fprintf( fp, "\n");
                 break;
             case wkbLineString:
             case wkbLineString25D:
+            case wkbLineStringM:
+            case wkbLineStringZM:
             case wkbCircularString:
             case wkbCircularStringZ:
+            case wkbCircularStringM:
+            case wkbCircularStringZM:
                 poLine = (OGRLineString*)this;
                 fprintf( fp, "%d points\n", poLine->getNumPoints() );
                 break;
             case wkbPolygon:
             case wkbPolygon25D:
+            case wkbPolygonM:
+            case wkbPolygonZM:
             case wkbCurvePolygon:
             case wkbCurvePolygonZ:
+            case wkbCurvePolygonM:
+            case wkbCurvePolygonZM:
             {
                 int ir;
                 int nRings;
@@ -182,6 +264,8 @@ void OGRGeometry::dumpReadable( FILE * fp, const char * pszPrefix, char** papszO
             }
             case wkbCompoundCurve:
             case wkbCompoundCurveZ:
+            case wkbCompoundCurveM:
+            case wkbCompoundCurveZM:
             {
                 OGRCompoundCurve* poCC = (OGRCompoundCurve* )this;
                 if( poCC->getNumCurves() == 0 )
@@ -212,6 +296,18 @@ void OGRGeometry::dumpReadable( FILE * fp, const char * pszPrefix, char** papszO
             case wkbMultiCurveZ:
             case wkbMultiSurfaceZ:
             case wkbGeometryCollection25D:
+            case wkbMultiPointM:
+            case wkbMultiLineStringM:
+            case wkbMultiPolygonM:
+            case wkbMultiCurveM:
+            case wkbMultiSurfaceM:
+            case wkbGeometryCollectionM:
+            case wkbMultiPointZM:
+            case wkbMultiLineStringZM:
+            case wkbMultiPolygonZM:
+            case wkbMultiCurveZM:
+            case wkbMultiSurfaceZM:
+            case wkbGeometryCollectionZM:
             {
                 int ig;
                 poColl = (OGRGeometryCollection*)this;
@@ -225,11 +321,18 @@ void OGRGeometry::dumpReadable( FILE * fp, const char * pszPrefix, char** papszO
                 break;
             }
             case wkbLinearRing:
+            case wkbCurve:
+            case wkbSurface:
+            case wkbCurveZ:
+            case wkbSurfaceZ:
+            case wkbCurveM:
+            case wkbSurfaceM:
+            case wkbCurveZM:
+            case wkbSurfaceZM:
                 break;
         }
     }
-    else if (pszDisplayGeometry == NULL || CSLTestBoolean(pszDisplayGeometry) ||
-             EQUAL(pszDisplayGeometry, "WKT"))
+    else if (pszDisplayGeometry != NULL && EQUAL(pszDisplayGeometry, "WKT"))
     {
         if( exportToWkt( &pszWkt ) == OGRERR_NONE )
         {
@@ -237,6 +340,15 @@ void OGRGeometry::dumpReadable( FILE * fp, const char * pszPrefix, char** papszO
             CPLFree( pszWkt );
         }
     }
+    else if (pszDisplayGeometry == NULL || CSLTestBoolean(pszDisplayGeometry) ||
+             EQUAL(pszDisplayGeometry, "ISO_WKT"))
+    {
+        if( exportToWkt( &pszWkt, wkbVariantIso ) == OGRERR_NONE )
+        {
+            fprintf( fp, "%s%s\n", pszPrefix, pszWkt );
+            CPLFree( pszWkt );
+        }
+    }
 }
 
 /************************************************************************/
@@ -273,7 +385,7 @@ void OGR_G_DumpReadable( OGRGeometryH hGeom, FILE *fp, const char *pszPrefix )
  * is replaced, but under no circumstances does this result in the object
  * being reprojected.  It is just changing the interpretation of the existing
  * geometry.  Note that assigning a spatial reference increments the
- * reference count on the OGRSpatialReference, but does not copy it. 
+ * reference count on the OGRSpatialReference, but does not copy it.
  *
  * This is similar to the SFCOM IGeometry::put_SpatialReference() method.
  *
@@ -303,19 +415,19 @@ void OGRGeometry::assignSpatialReference( OGRSpatialReference * poSR )
  * is replaced, but under no circumstances does this result in the object
  * being reprojected.  It is just changing the interpretation of the existing
  * geometry.  Note that assigning a spatial reference increments the
- * reference count on the OGRSpatialReference, but does not copy it. 
+ * reference count on the OGRSpatialReference, but does not copy it.
  *
  * This is similar to the SFCOM IGeometry::put_SpatialReference() method.
  *
- * This function is the same as the CPP method 
+ * This function is the same as the CPP method
  * OGRGeometry::assignSpatialReference.
  *
- * @param hGeom handle on the geometry to apply the new spatial reference 
+ * @param hGeom handle on the geometry to apply the new spatial reference
  * system.
  * @param hSRS handle on the  new spatial reference system to apply.
  */
 
-void OGR_G_AssignSpatialReference( OGRGeometryH hGeom, 
+void OGR_G_AssignSpatialReference( OGRGeometryH hGeom,
                                    OGRSpatialReferenceH hSRS )
 
 {
@@ -333,16 +445,16 @@ void OGR_G_AssignSpatialReference( OGRGeometryH hGeom,
  * \brief Do these features intersect?
  *
  * Determines whether two geometries intersect.  If GEOS is enabled, then
- * this is done in rigerous fashion otherwise TRUE is returned if the
- * envelopes (bounding boxes) of the two features overlap. 
+ * this is done in rigorous fashion otherwise TRUE is returned if the
+ * envelopes (bounding boxes) of the two geometries overlap.
  *
  * The poOtherGeom argument may be safely NULL, but in this case the method
  * will always return TRUE.   That is, a NULL geometry is treated as being
- * everywhere. 
+ * everywhere.
  *
  * This method is the same as the C function OGR_G_Intersects().
  *
- * @param poOtherGeom the other geometry to test against.  
+ * @param poOtherGeom the other geometry to test against.
  *
  * @return TRUE if the geometries intersect, otherwise FALSE.
  */
@@ -352,7 +464,7 @@ OGRBoolean OGRGeometry::Intersects( const OGRGeometry *poOtherGeom ) const
 {
     OGREnvelope         oEnv1, oEnv2;
 
-    if( this == NULL || poOtherGeom == NULL )
+    if( poOtherGeom == NULL )
         return TRUE;
 
     this->getEnvelope( &oEnv1 );
@@ -365,11 +477,9 @@ OGRBoolean OGRGeometry::Intersects( const OGRGeometry *poOtherGeom ) const
         return FALSE;
 
 #ifndef HAVE_GEOS
-
-    // Without GEOS we assume that envelope overlap is equivelent to
+    // Without GEOS we assume that envelope overlap is equivalent to
     // actual intersection.
     return TRUE;
-
 #else
 
     GEOSGeom hThisGeosGeom = NULL;
@@ -378,7 +488,7 @@ OGRBoolean OGRGeometry::Intersects( const OGRGeometry *poOtherGeom ) const
     GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
     hThisGeosGeom = exportToGEOS(hGEOSCtxt);
     hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
-    
+
     OGRBoolean bResult = FALSE;
     if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
     {
@@ -396,7 +506,7 @@ OGRBoolean OGRGeometry::Intersects( const OGRGeometry *poOtherGeom ) const
 #endif /* HAVE_GEOS */
 }
 
-// Old API compatibility function.                                 
+// Old API compatibility function.
 
 OGRBoolean OGRGeometry::Intersect( OGRGeometry *poOtherGeom ) const
 
@@ -410,9 +520,9 @@ OGRBoolean OGRGeometry::Intersect( OGRGeometry *poOtherGeom ) const
 /**
  * \brief Do these features intersect?
  *
- * Currently this is not implemented in a rigerous fashion, and generally
- * just tests whether the envelopes of the two features intersect.  Eventually
- * this will be made rigerous.
+ * Determines whether two geometries intersect.  If GEOS is enabled, then
+ * this is done in rigorous fashion otherwise TRUE is returned if the
+ * envelopes (bounding boxes) of the two geometries overlap.
  *
  * This function is the same as the CPP method OGRGeometry::Intersects.
  *
@@ -450,7 +560,7 @@ int OGR_G_Intersect( OGRGeometryH hGeom, OGRGeometryH hOtherGeom )
  * This method will transform the coordinates of a geometry from
  * their current spatial reference system to a new target spatial
  * reference system.  Normally this means reprojecting the vectors,
- * but it could include datum shifts, and changes of units. 
+ * but it could include datum shifts, and changes of units.
  *
  * This method will only work if the geometry already has an assigned
  * spatial reference system, and if it is transformable to the target
@@ -464,7 +574,7 @@ int OGR_G_Intersect( OGRGeometryH hGeom, OGRGeometryH hOtherGeom )
  * transforming a single geometry.
  *
  * This method is the same as the C function OGR_G_TransformTo().
- * 
+ *
  * @param poSR spatial reference system to transform to.
  *
  * @return OGRERR_NONE on success, or an error code.
@@ -503,7 +613,7 @@ OGRErr OGRGeometry::transformTo( OGRSpatialReference *poSR )
  * This function will transform the coordinates of a geometry from
  * their current spatial reference system to a new target spatial
  * reference system.  Normally this means reprojecting the vectors,
- * but it could include datum shifts, and changes of units. 
+ * but it could include datum shifts, and changes of units.
  *
  * This function will only work if the geometry already has an assigned
  * spatial reference system, and if it is transformable to the target
@@ -517,7 +627,7 @@ OGRErr OGRGeometry::transformTo( OGRSpatialReference *poSR )
  * transforming a single geometry.
  *
  * This function is the same as the CPP method OGRGeometry::transformTo.
- * 
+ *
  * @param hGeom handle on the geometry to apply the transform to.
  * @param hSRS handle on the spatial reference system to apply.
  *
@@ -540,8 +650,8 @@ OGRErr OGR_G_TransformTo( OGRGeometryH hGeom, OGRSpatialReferenceH hSRS )
  * This method will transform the coordinates of a geometry from
  * their current spatial reference system to a new target spatial
  * reference system.  Normally this means reprojecting the vectors,
- * but it could include datum shifts, and changes of units. 
- * 
+ * but it could include datum shifts, and changes of units.
+ *
  * Note that this method does not require that the geometry already
  * have a spatial reference system.  It will be assumed that they can
  * be treated as having the source spatial reference system of the
@@ -565,8 +675,8 @@ OGRErr OGR_G_TransformTo( OGRGeometryH hGeom, OGRSpatialReferenceH hSRS )
  * This function will transform the coordinates of a geometry from
  * their current spatial reference system to a new target spatial
  * reference system.  Normally this means reprojecting the vectors,
- * but it could include datum shifts, and changes of units. 
- * 
+ * but it could include datum shifts, and changes of units.
+ *
  * Note that this function does not require that the geometry already
  * have a spatial reference system.  It will be assumed that they can
  * be treated as having the source spatial reference system of the
@@ -582,7 +692,7 @@ OGRErr OGR_G_TransformTo( OGRGeometryH hGeom, OGRSpatialReferenceH hSRS )
  * @return OGRERR_NONE on success or an error code.
  */
 
-OGRErr OGR_G_Transform( OGRGeometryH hGeom, 
+OGRErr OGR_G_Transform( OGRGeometryH hGeom,
                         OGRCoordinateTransformationH hTransform )
 
 {
@@ -617,8 +727,10 @@ OGRwkbGeometryType OGRGeometry::getIsoGeometryType() const
 {
     OGRwkbGeometryType nGType = wkbFlatten(getGeometryType());
 
-    if ( getCoordinateDimension() == 3 )
+    if ( flags & OGR_G_3D )
         nGType = (OGRwkbGeometryType)(nGType + 1000);
+    if ( flags & OGR_G_MEASURED )
+        nGType = (OGRwkbGeometryType)(nGType + 2000);
 
     return nGType;
 }
@@ -705,18 +817,41 @@ int OGR_G_GetDimension( OGRGeometryH hGeom )
 /**
  * \brief Get the dimension of the coordinates in this object.
  *
- * This method corresponds to the SFCOM IGeometry::GetDimension() method.
- *
  * This method is the same as the C function OGR_G_GetCoordinateDimension().
  *
- * @return in practice this will return 2 or 3. It can also return 0 in the
- * case of an empty point.
+ * @deprecated use CoordinateDimension().
+ *
+ * @return this will return 2 or 3.
  */
 
 int OGRGeometry::getCoordinateDimension() const
 
 {
-    return nCoordDimension;
+    return (flags & OGR_G_3D) ? 3 : 2;
+}
+
+/************************************************************************/
+/*                        CoordinateDimension()                         */
+/************************************************************************/
+/**
+ * \brief Get the dimension of the coordinates in this object.
+ *
+ * This method is the same as the C function OGR_G_CoordinateDimension().
+ *
+ * @return this will return 2 for XY, 3 for XYZ and XYM, and 4 for XYZM data.
+ *
+ * @since GDAL 2.1
+ */
+
+int OGRGeometry::CoordinateDimension() const
+
+{
+    if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
+        return 4;
+    else if( (flags & OGR_G_3D) || (flags & OGR_G_MEASURED) )
+        return 3;
+    else
+        return 2;
 }
 
 /************************************************************************/
@@ -726,16 +861,15 @@ int OGRGeometry::getCoordinateDimension() const
  *
  * \brief Get the dimension of the coordinates in this geometry.
  *
- * This function corresponds to the SFCOM IGeometry::GetDimension() method.
- *
- * This function is the same as the CPP method 
+ * This function is the same as the CPP method
  * OGRGeometry::getCoordinateDimension().
  *
- * @param hGeom handle on the geometry to get the dimension of the 
+ * @param hGeom handle on the geometry to get the dimension of the
  * coordinates from.
  *
- * @return in practice this will return 2 or 3. It can also return 0 in the
- * case of an empty point.
+ * @deprecated use OGR_G_CoordinateDimension(), OGR_G_Is3D(), or OGR_G_IsMeasured().
+ *
+ * @return this will return 2 or 3.
  */
 
 int OGR_G_GetCoordinateDimension( OGRGeometryH hGeom )
@@ -747,16 +881,87 @@ int OGR_G_GetCoordinateDimension( OGRGeometryH hGeom )
 }
 
 /************************************************************************/
+/*                    OGR_G_CoordinateDimension()                       */
+/************************************************************************/
+/**
+ *
+ * \brief Get the dimension of the coordinates in this geometry.
+ *
+ * This function is the same as the CPP method
+ * OGRGeometry::CoordinateDimension().
+ *
+ * @param hGeom handle on the geometry to get the dimension of the
+ * coordinates from.
+ *
+ * @return this will return 2 for XY, 3 for XYZ and XYM, and 4 for XYZM data.
+ *
+ * @since GDAL 2.1
+ */
+
+int OGR_G_CoordinateDimension( OGRGeometryH hGeom )
+
+{
+    VALIDATE_POINTER1( hGeom, "OGR_G_CoordinateDimension", 0 );
+
+    return ((OGRGeometry *) hGeom)->CoordinateDimension();
+}
+
+/**
+ *
+ * \brief See whether this geometry has Z coordinates.
+ *
+ * This function is the same as the CPP method
+ * OGRGeometry::Is3D().
+ *
+ * @param hGeom handle on the geometry to check whether it has Z coordinates.
+ *
+ * @return TRUE if the geometry has Z coordinates.
+ * @since GDAL 2.1
+ */
+
+int OGR_G_Is3D( OGRGeometryH hGeom )
+
+{
+    VALIDATE_POINTER1( hGeom, "OGR_G_Is3D", 0 );
+
+    return ((OGRGeometry *) hGeom)->Is3D();
+}
+
+/**
+ *
+ * \brief See whether this geometry is measured.
+ *
+ * This function is the same as the CPP method
+ * OGRGeometry::IsMeasured().
+ *
+ * @param hGeom handle on the geometry to check whether it is measured.
+ *
+ * @return TRUE if the geometry has M coordinates.
+ * @since GDAL 2.1
+ */
+
+int OGR_G_IsMeasured( OGRGeometryH hGeom )
+
+{
+    VALIDATE_POINTER1( hGeom, "OGR_G_IsMeasured", 0 );
+
+    return ((OGRGeometry *) hGeom)->IsMeasured();
+}
+
+/************************************************************************/
 /*                       setCoordinateDimension()                       */
 /************************************************************************/
 
 /**
- * \brief Set the coordinate dimension. 
+ * \brief Set the coordinate dimension.
  *
  * This method sets the explicit coordinate dimension.  Setting the coordinate
  * dimension of a geometry to 2 should zero out any existing Z values.  Setting
- * the dimension of a geometry collection will not necessarily affect the
- * children geometries. 
+ * the dimension of a geometry collection, a compound curve, a polygon, etc.
+ * will affect the children geometries.
+ * This will also remove the M dimension if present before this call.
+ *
+ * @deprecated use set3D() or setMeasured().
  *
  * @param nNewDimension New coordinate dimension value, either 2 or 3.
  */
@@ -764,7 +969,55 @@ int OGR_G_GetCoordinateDimension( OGRGeometryH hGeom )
 void OGRGeometry::setCoordinateDimension( int nNewDimension )
 
 {
-    nCoordDimension = nNewDimension;
+    if( nNewDimension == 2 )
+        flags &= ~OGR_G_3D;
+    else
+        flags |= OGR_G_3D;
+    setMeasured( FALSE );
+}
+
+/**
+ * \brief Add or remove the Z coordinate dimension.
+ *
+ * This method adds or removes the explicit Z coordinate dimension.
+ * Removing the Z coordinate dimension of a geometry will remove any
+ * existing Z values.  Adding the Z dimension to a geometry
+ * collection, a compound curve, a polygon, etc.  will affect the
+ * children geometries.
+ *
+ * @param bIs3D Should the geometry have a Z dimension, either TRUE or FALSE.
+ * @since GDAL 2.1
+ */
+
+void OGRGeometry::set3D( OGRBoolean bIs3D )
+
+{
+    if (bIs3D)
+        flags |= OGR_G_3D;
+    else
+        flags &= ~OGR_G_3D;
+}
+
+/**
+ * \brief Add or remove the M coordinate dimension.
+ *
+ * This method adds or removes the explicit M coordinate dimension.
+ * Removing the M coordinate dimension of a geometry will remove any
+ * existing M values.  Adding the M dimension to a geometry
+ * collection, a compound curve, a polygon, etc.  will affect the
+ * children geometries.
+ *
+ * @param bIsMeasured Should the geometry have a M dimension, either TRUE or FALSE.
+ * @since GDAL 2.1
+ */
+
+void OGRGeometry::setMeasured( OGRBoolean bIsMeasured )
+
+{
+    if (bIsMeasured)
+        flags |= OGR_G_MEASURED;
+    else
+        flags &= ~OGR_G_MEASURED;
 }
 
 /************************************************************************/
@@ -775,9 +1028,12 @@ void OGRGeometry::setCoordinateDimension( int nNewDimension )
  * \brief Set the coordinate dimension.
  *
  * This method sets the explicit coordinate dimension.  Setting the coordinate
- * dimension of a geometry to 2 should zero out any existing Z values.  Setting
- * the dimension of a geometry collection will not necessarily affect the
- * children geometries.
+ * dimension of a geometry to 2 should zero out any existing Z values. Setting
+ * the dimension of a geometry collection, a compound curve, a polygon, etc.
+ * will affect the children geometries.
+ * This will also remove the M dimension if present before this call.
+ *
+ * @deprecated use OGR_G_Set3D() or OGR_G_SetMeasured().
  *
  * @param hGeom handle on the geometry to set the dimension of the
  * coordinates.
@@ -792,6 +1048,60 @@ void OGR_G_SetCoordinateDimension( OGRGeometryH hGeom, int nNewDimension)
     ((OGRGeometry *) hGeom)->setCoordinateDimension( nNewDimension );
 }
 
+/************************************************************************/
+/*                    OGR_G_Set3D()                                     */
+/************************************************************************/
+
+/**
+ * \brief Add or remove the Z coordinate dimension.
+ *
+ * This method adds or removes the explicit Z coordinate dimension.
+ * Removing the Z coordinate dimension of a geometry will remove any
+ * existing Z values.  Adding the Z dimension to a geometry
+ * collection, a compound curve, a polygon, etc.  will affect the
+ * children geometries.
+ *
+ * @param hGeom handle on the geometry to set or unset the Z dimension.
+ * @param bIs3D Should the geometry have a Z dimension, either TRUE or FALSE.
+ * @since GDAL 2.1
+ */
+
+void OGR_G_Set3D( OGRGeometryH hGeom, int bIs3D)
+
+{
+    VALIDATE_POINTER0( hGeom, "OGR_G_Set3D" );
+
+    ((OGRGeometry *) hGeom)->set3D( bIs3D );
+}
+
+/************************************************************************/
+/*                    OGR_G_SetMeasured()                               */
+/************************************************************************/
+
+/**
+ * \brief Set the coordinate dimension.
+ *
+ * \brief Add or remove the M coordinate dimension.
+ *
+ * This method adds or removes the explicit M coordinate dimension.
+ * Removing the M coordinate dimension of a geometry will remove any
+ * existing M values.  Adding the M dimension to a geometry
+ * collection, a compound curve, a polygon, etc.  will affect the
+ * children geometries.
+ *
+ * @param hGeom handle on the geometry to set or unset the M dimension.
+ * @param bIsMeasured Should the geometry have a M dimension, either TRUE or FALSE.
+ * @since GDAL 2.1
+ */
+
+void OGR_G_SetMeasured( OGRGeometryH hGeom, int bIsMeasured)
+
+{
+    VALIDATE_POINTER0( hGeom, "OGR_G_SetMeasured" );
+
+    ((OGRGeometry *) hGeom)->setMeasured( bIsMeasured );
+}
+
 /**
  * \fn int OGRGeometry::Equals( OGRGeometry *poOtherGeom ) const;
  *
@@ -829,16 +1139,11 @@ int OGR_G_Equals( OGRGeometryH hGeom, OGRGeometryH hOther )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_Equals", FALSE );
 
-    if (hGeom == NULL) {
-        CPLError ( CE_Failure, CPLE_ObjectNull, "hGeom was NULL in OGR_G_Equals");
-        return 0;
-    }
-
     if (hOther == NULL) {
         CPLError ( CE_Failure, CPLE_ObjectNull, "hOther was NULL in OGR_G_Equals");
         return 0;
     }
-    
+
     return ((OGRGeometry *) hGeom)->Equals( (OGRGeometry *) hOther );
 }
 
@@ -973,8 +1278,8 @@ void OGR_G_GetEnvelope3D( OGRGeometryH hGeom, OGREnvelope3D *psEnvelope )
  * The object must have already been instantiated as the correct derived
  * type of geometry object to match the binaries type.  This method is used
  * by the OGRGeometryFactory class, but not normally called by application
- * code.  
- * 
+ * code.
+ *
  * This method relates to the SFCOM IWks::ImportFromWKB() method.
  *
  * This method is the same as the C function OGR_G_ImportFromWkb().
@@ -1010,7 +1315,7 @@ void OGR_G_GetEnvelope3D( OGRGeometryH hGeom, OGREnvelope3D *psEnvelope )
  * OGRERR_CORRUPT_DATA may be returned.
  */
 
-OGRErr OGR_G_ImportFromWkb( OGRGeometryH hGeom, 
+OGRErr OGR_G_ImportFromWkb( OGRGeometryH hGeom,
                             unsigned char *pabyData, int nSize )
 
 {
@@ -1036,10 +1341,10 @@ OGRErr OGR_G_ImportFromWkb( OGRGeometryH hGeom,
  * @param pabyData a buffer into which the binary representation is
  *                      written.  This buffer must be at least
  *                      OGRGeometry::WkbSize() byte in size.
- * @param eWkbVariant What standard to use when exporting geometries with 
- *                      three dimensions (or more). The default wkbVariantOldOgc is 
- *                      the historical OGR variant. wkbVariantIso is the 
- *                      variant defined in ISO SQL/MM and adopted by OGC 
+ * @param eWkbVariant What standard to use when exporting geometries with
+ *                      three dimensions (or more). The default wkbVariantOldOgc is
+ *                      the historical OGR variant. wkbVariantIso is the
+ *                      variant defined in ISO SQL/MM and adopted by OGC
  *                      for SFSQL 1.2.
  *
  * @return Currently OGRERR_NONE is always returned.
@@ -1061,7 +1366,7 @@ OGRErr OGR_G_ImportFromWkb( OGRGeometryH hGeom,
  * This function is the same as the CPP method OGRGeometry::exportToWkb(OGRwkbByteOrder, unsigned char *, OGRwkbVariant)
  * with eWkbVariant = wkbVariantOldOgc.
  *
- * @param hGeom handle on the geometry to convert to a well know binary 
+ * @param hGeom handle on the geometry to convert to a well know binary
  * data from.
  * @param eOrder One of wkbXDR or wkbNDR indicating MSB or LSB byte order
  *               respectively.
@@ -1093,7 +1398,7 @@ OGRErr OGR_G_ExportToWkb( OGRGeometryH hGeom, OGRwkbByteOrder eOrder,
  * This function is the same as the CPP method  OGRGeometry::exportToWkb(OGRwkbByteOrder, unsigned char *, OGRwkbVariant)
  * with eWkbVariant = wkbVariantIso.
  *
- * @param hGeom handle on the geometry to convert to a well know binary 
+ * @param hGeom handle on the geometry to convert to a well know binary
  * data from.
  * @param eOrder One of wkbXDR or wkbNDR indicating MSB or LSB byte order
  *               respectively.
@@ -1123,8 +1428,8 @@ OGRErr OGR_G_ExportToIsoWkb( OGRGeometryH hGeom, OGRwkbByteOrder eOrder,
  * The object must have already been instantiated as the correct derived
  * type of geometry object to match the text type.  This method is used
  * by the OGRGeometryFactory class, but not normally called by application
- * code.  
- * 
+ * code.
+ *
  * This method relates to the SFCOM IWks::ImportFromWKT() method.
  *
  * This method is the same as the C function OGR_G_ImportFromWkt().
@@ -1145,7 +1450,7 @@ OGRErr OGR_G_ExportToIsoWkb( OGRGeometryH hGeom, OGRwkbByteOrder eOrder,
  *
  * The object must have already been instantiated as the correct derived
  * type of geometry object to match the text type.
- * 
+ *
  * This function relates to the SFCOM IWks::ImportFromWKT() method.
  *
  * This function is the same as the CPP method OGRGeometry::importFromWkt().
@@ -1174,7 +1479,8 @@ OGRErr OGR_G_ImportFromWkt( OGRGeometryH hGeom, char ** ppszSrcText )
 
 /* Returns -1 if processing must continue */
 OGRErr OGRGeometry::importPreambuleFromWkt( char ** ppszInput,
-                                            int* pbHasZ, int* pbHasM )
+                                            int* pbHasZ, int* pbHasM,
+                                            bool* pbIsEmpty )
 {
     char        szToken[OGR_WKT_TOKEN_MAX];
     const char  *pszInput = *ppszInput;
@@ -1183,12 +1489,27 @@ OGRErr OGRGeometry::importPreambuleFromWkt( char ** ppszInput,
 /*      Clear existing Geoms.                                           */
 /* -------------------------------------------------------------------- */
     empty();
+    *pbIsEmpty = false;
+
+    int bHasZ = FALSE, bHasM = FALSE;
+    bool bIsoWKT = true;
 
 /* -------------------------------------------------------------------- */
 /*      Read and verify the type keyword, and ensure it matches the     */
 /*      actual type of this container.                                  */
 /* -------------------------------------------------------------------- */
     pszInput = OGRWktReadToken( pszInput, szToken );
+    if( szToken[0] != '\0' )
+    {
+        // Postgis EWKT : POINTM instead of POINT M
+        const size_t nTokenLen = strlen(szToken);
+        if( szToken[nTokenLen-1] == 'M' )
+        {
+            szToken[nTokenLen-1] = '\0';
+            bHasM = TRUE;
+            bIsoWKT = false;
+        }
+    }
 
     if( !EQUAL(szToken,getGeometryName()) )
         return OGRERR_CORRUPT_DATA;
@@ -1197,12 +1518,17 @@ OGRErr OGRGeometry::importPreambuleFromWkt( char ** ppszInput,
 /*      Check for EMPTY ...                                             */
 /* -------------------------------------------------------------------- */
     const char *pszPreScan;
-    int bHasZ = FALSE, bHasM = FALSE;
 
     pszPreScan = OGRWktReadToken( pszInput, szToken );
-    if( EQUAL(szToken,"EMPTY") )
+    if( !bIsoWKT )
+    {
+        /* go on */
+    }
+    else if( EQUAL(szToken,"EMPTY") )
     {
         *ppszInput = (char *) pszPreScan;
+        *pbIsEmpty = true;
+        *pbHasM = bHasM;
         empty();
         return OGRERR_NONE;
     }
@@ -1226,7 +1552,7 @@ OGRErr OGRGeometry::importPreambuleFromWkt( char ** ppszInput,
     *pbHasZ = bHasZ;
     *pbHasM = bHasM;
 
-    if (bHasZ || bHasM)
+    if ( bIsoWKT && (bHasZ || bHasM) )
     {
         pszInput = pszPreScan;
         pszPreScan = OGRWktReadToken( pszInput, szToken );
@@ -1235,10 +1561,10 @@ OGRErr OGRGeometry::importPreambuleFromWkt( char ** ppszInput,
             *ppszInput = (char *) pszPreScan;
             empty();
             if( bHasZ )
-                setCoordinateDimension(3);
-
-            /* FIXME?: In theory we should store the M presence */
-            /* if we want to allow round-trip with ExportToWKT v1.2 */
+                set3D(TRUE);
+            if( bHasM )
+                setMeasured(TRUE);
+            *pbIsEmpty = true;
             return OGRERR_NONE;
         }
     }
@@ -1264,14 +1590,15 @@ OGRErr OGRGeometry::importPreambuleFromWkt( char ** ppszInput,
             {
                 *ppszInput = (char *) pszPreScan;
                 empty();
+                *pbIsEmpty = true;
                 return OGRERR_NONE;
             }
         }
     }
-    
+
     *ppszInput = (char*) pszInput;
 
-    return -1;
+    return OGRERR_NONE;
 }
 
 
@@ -1399,7 +1726,7 @@ OGRwkbGeometryType OGR_G_GetGeometryType( OGRGeometryH hGeom )
  *
  * \brief Fetch WKT name for geometry type.
  *
- * There is no SFCOM analog to this method.  
+ * There is no SFCOM analog to this method.
  *
  * This method is the same as the C function OGR_G_GetGeometryName().
  *
@@ -1414,7 +1741,7 @@ OGRwkbGeometryType OGR_G_GetGeometryType( OGRGeometryH hGeom )
 /**
  * \brief Fetch WKT name for geometry type.
  *
- * There is no SFCOM analog to this function.  
+ * There is no SFCOM analog to this function.
  *
  * This function is the same as the CPP method OGRGeometry::getGeometryName().
  *
@@ -1438,7 +1765,7 @@ const char *OGR_G_GetGeometryName( OGRGeometryH hGeom )
  * This method relates to the SFCOM IGeometry::clone() method.
  *
  * This method is the same as the C function OGR_G_Clone().
- * 
+ *
  * @return a new object instance with the same geometry, and spatial
  * reference system as the original.
  */
@@ -1452,7 +1779,7 @@ const char *OGR_G_GetGeometryName( OGRGeometryH hGeom )
  * This function relates to the SFCOM IGeometry::clone() method.
  *
  * This function is the same as the CPP method OGRGeometry::clone().
- * 
+ *
  * @param hGeom handle on the geometry to clone from.
  * @return an handle on the  copy of the geometry with the spatial
  * reference system as the original.
@@ -1487,7 +1814,7 @@ OGRGeometryH OGR_G_Clone( OGRGeometryH hGeom )
  *
  * This function relates to the SFCOM IGeometry::get_SpatialReference() method.
  *
- * This function is the same as the CPP method 
+ * This function is the same as the CPP method
  * OGRGeometry::getSpatialReference().
  *
  * @param hGeom handle on the geometry to get spatial reference from.
@@ -1499,7 +1826,7 @@ OGRSpatialReferenceH OGR_G_GetSpatialReference( OGRGeometryH hGeom )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_GetSpatialReference", NULL );
 
-    return (OGRSpatialReferenceH) 
+    return (OGRSpatialReferenceH)
         ((OGRGeometry *) hGeom)->getSpatialReference();
 }
 
@@ -1563,7 +1890,7 @@ void OGR_G_Empty( OGRGeometryH hGeom )
  *
  * @param hGeom The Geometry to test.
  *
- * @return TRUE if the geometry has no points, otherwise FALSE.  
+ * @return TRUE if the geometry has no points, otherwise FALSE.
  */
 
 int OGR_G_IsEmpty( OGRGeometryH hGeom )
@@ -1585,11 +1912,11 @@ int OGR_G_IsEmpty( OGRGeometryH hGeom )
  *
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this method will always return 
- * FALSE. 
+ * If OGR is built without the GEOS library, this method will always return
+ * FALSE.
  *
  *
- * @return TRUE if the geometry has no points, otherwise FALSE.  
+ * @return TRUE if the geometry has no points, otherwise FALSE.
  */
 
 OGRBoolean
@@ -1604,7 +1931,7 @@ OGRGeometry::IsValid(  ) const
 
     OGRBoolean bResult = FALSE;
     GEOSGeom hThisGeosGeom = NULL;
-    
+
     GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
     hThisGeosGeom = exportToGEOS(hGEOSCtxt);
 
@@ -1631,12 +1958,12 @@ OGRGeometry::IsValid(  ) const
  *
  * This function is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this function will always return 
- * FALSE. 
+ * If OGR is built without the GEOS library, this function will always return
+ * FALSE.
  *
  * @param hGeom The Geometry to test.
  *
- * @return TRUE if the geometry has no points, otherwise FALSE.  
+ * @return TRUE if the geometry has no points, otherwise FALSE.
  */
 
 int OGR_G_IsValid( OGRGeometryH hGeom )
@@ -1658,11 +1985,11 @@ int OGR_G_IsValid( OGRGeometryH hGeom )
  *
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this method will always return 
- * FALSE. 
+ * If OGR is built without the GEOS library, this method will always return
+ * FALSE.
  *
  *
- * @return TRUE if the geometry has no points, otherwise FALSE.  
+ * @return TRUE if the geometry has no points, otherwise FALSE.
  */
 
 OGRBoolean
@@ -1677,7 +2004,7 @@ OGRGeometry::IsSimple(  ) const
 
     OGRBoolean bResult = FALSE;
     GEOSGeom hThisGeosGeom = NULL;
-    
+
     GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
     hThisGeosGeom = exportToGEOS(hGEOSCtxt);
 
@@ -1696,7 +2023,7 @@ OGRGeometry::IsSimple(  ) const
 
 /**
  * \brief Returns TRUE if the geometry is simple.
- * 
+ *
  * Returns TRUE if the geometry has no anomalous geometric points, such
  * as self intersection or self tangency. The description of each
  * instantiable geometric class will include the specific conditions that
@@ -1704,7 +2031,7 @@ OGRGeometry::IsSimple(  ) const
  *
  * This function is the same as the c++ method OGRGeometry::IsSimple() method.
  *
- * If OGR is built without the GEOS library, this function will always return 
+ * If OGR is built without the GEOS library, this function will always return
  * FALSE.
  *
  * @param hGeom The Geometry to test.
@@ -1731,11 +2058,11 @@ int OGR_G_IsSimple( OGRGeometryH hGeom )
  *
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this method will always return 
- * FALSE. 
+ * If OGR is built without the GEOS library, this method will always return
+ * FALSE.
  *
  *
- * @return TRUE if the geometry has no points, otherwise FALSE.  
+ * @return TRUE if the geometry has no points, otherwise FALSE.
  */
 
 OGRBoolean
@@ -1750,7 +2077,7 @@ OGRGeometry::IsRing(  ) const
 
     OGRBoolean bResult = FALSE;
     GEOSGeom hThisGeosGeom = NULL;
-    
+
     GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
     hThisGeosGeom = exportToGEOS(hGEOSCtxt);
 
@@ -1777,12 +2104,12 @@ OGRGeometry::IsRing(  ) const
  *
  * This function is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this function will always return 
- * FALSE. 
+ * If OGR is built without the GEOS library, this function will always return
+ * FALSE.
  *
  * @param hGeom The Geometry to test.
  *
- * @return TRUE if the geometry has no points, otherwise FALSE.  
+ * @return TRUE if the geometry has no points, otherwise FALSE.
  */
 
 int OGR_G_IsRing( OGRGeometryH hGeom )
@@ -1799,50 +2126,61 @@ int OGR_G_IsRing( OGRGeometryH hGeom )
 /*      OGR constants.                                                  */
 /************************************************************************/
 
-#define EQUALN_CST(var, cst) EQUALN(var, cst, strlen(cst))
-
 OGRwkbGeometryType OGRFromOGCGeomType( const char *pszGeomType )
 {
     OGRwkbGeometryType eType;
-    int bConvertTo3D = FALSE;
+    bool bConvertTo3D = false;
+    bool bIsMeasured = false;
     if( *pszGeomType != '\0' )
     {
         char ch = pszGeomType[strlen(pszGeomType)-1];
+        if( ch == 'm' || ch == 'M' )
+        {
+            bIsMeasured = true;
+            if( strlen(pszGeomType) > 1 )
+                ch = pszGeomType[strlen(pszGeomType)-2];
+        }
         if( ch == 'z' || ch == 'Z' )
         {
-            bConvertTo3D = TRUE;
+            bConvertTo3D = true;
         }
     }
-    if ( EQUALN_CST(pszGeomType, "POINT") )
+    if ( STARTS_WITH_CI(pszGeomType, "POINT") )
         eType = wkbPoint;
-    else if ( EQUALN_CST(pszGeomType, "LINESTRING") )
+    else if ( STARTS_WITH_CI(pszGeomType, "LINESTRING") )
         eType = wkbLineString;
-    else if ( EQUALN_CST(pszGeomType, "POLYGON") )
+    else if ( STARTS_WITH_CI(pszGeomType, "POLYGON") )
         eType = wkbPolygon;
-    else if ( EQUALN_CST(pszGeomType, "MULTIPOINT") )
+    else if ( STARTS_WITH_CI(pszGeomType, "MULTIPOINT") )
         eType = wkbMultiPoint;
-    else if ( EQUALN_CST(pszGeomType, "MULTILINESTRING") )
+    else if ( STARTS_WITH_CI(pszGeomType, "MULTILINESTRING") )
         eType = wkbMultiLineString;
-    else if ( EQUALN_CST(pszGeomType, "MULTIPOLYGON") )
+    else if ( STARTS_WITH_CI(pszGeomType, "MULTIPOLYGON") )
         eType = wkbMultiPolygon;
-    else if ( EQUALN_CST(pszGeomType, "GEOMETRYCOLLECTION") )
+    else if ( STARTS_WITH_CI(pszGeomType, "GEOMETRYCOLLECTION") )
         eType = wkbGeometryCollection;
-    else if ( EQUALN_CST(pszGeomType, "CIRCULARSTRING") )
+    else if ( STARTS_WITH_CI(pszGeomType, "CIRCULARSTRING") )
         eType = wkbCircularString;
-    else if ( EQUALN_CST(pszGeomType, "COMPOUNDCURVE") )
+    else if ( STARTS_WITH_CI(pszGeomType, "COMPOUNDCURVE") )
         eType = wkbCompoundCurve;
-    else if ( EQUALN_CST(pszGeomType, "CURVEPOLYGON") )
+    else if ( STARTS_WITH_CI(pszGeomType, "CURVEPOLYGON") )
         eType = wkbCurvePolygon;
-    else if ( EQUALN_CST(pszGeomType, "MULTICURVE") )
+    else if ( STARTS_WITH_CI(pszGeomType, "MULTICURVE") )
         eType = wkbMultiCurve;
-    else if ( EQUALN_CST(pszGeomType, "MULTISURFACE") )
+    else if ( STARTS_WITH_CI(pszGeomType, "MULTISURFACE") )
         eType = wkbMultiSurface;
+    else if ( STARTS_WITH_CI(pszGeomType, "CURVE") )
+        eType = wkbCurve;
+    else if ( STARTS_WITH_CI(pszGeomType, "SURFACE") )
+        eType = wkbSurface;
     else
         eType = wkbUnknown;
 
     if( bConvertTo3D )
         eType = wkbSetZ(eType);
-    
+    if( bIsMeasured )
+        eType = wkbSetM(eType);
+
     return eType;
 }
 
@@ -1882,6 +2220,10 @@ const char * OGRToOGCGeomType( OGRwkbGeometryType eGeomType )
             return "MULTICURVE";
         case wkbMultiSurface:
             return "MULTISURFACE";
+        case wkbCurve:
+            return "CURVE";
+        case wkbSurface:
+            return "SURFACE";
         default:
             return "";
     }
@@ -1905,101 +2247,168 @@ const char * OGRToOGCGeomType( OGRwkbGeometryType eGeomType )
 const char *OGRGeometryTypeToName( OGRwkbGeometryType eType )
 
 {
-    bool b2D = wkbFlatten(eType) == eType;
+    bool b3D = wkbHasZ(eType);
+    bool bMeasured = wkbHasM(eType);
 
     switch( wkbFlatten(eType) )
     {
-      case wkbUnknown:
-        if( b2D )
-            return "Unknown (any)";
-        else
-            return "3D Unknown (any)";
+        case wkbUnknown:
+            if (b3D && bMeasured)
+                return "3D Measured Unknown (any)";
+            else if (b3D)
+                return "3D Unknown (any)";
+            else if (bMeasured)
+                return "Measured Unknown (any)";
+            else
+                return "Unknown (any)";
 
-      case wkbPoint:
-        if( b2D )
-            return "Point";
-        else
-            return "3D Point";
+        case wkbPoint:
+            if (b3D && bMeasured)
+                return "3D Measured Point";
+            else if (b3D)
+                return "3D Point";
+            else if (bMeasured)
+                return "Measured Point";
+            else
+                return "Point";
 
-      case wkbLineString:
-        if( b2D )
-            return "Line String";
-        else
-            return "3D Line String";
+        case wkbLineString:
+            if (b3D && bMeasured)
+                return "3D Measured Line String";
+            else if (b3D)
+                return "3D Line String";
+            else if (bMeasured)
+                return "Measured Line String";
+            else
+                return "Line String";
 
-      case wkbPolygon:
-        if( b2D )
-            return "Polygon";
-        else
-            return "3D Polygon";
+        case wkbPolygon:
+            if (b3D && bMeasured)
+                return "3D Measured Polygon";
+            else if (b3D)
+                return "3D Polygon";
+            else if (bMeasured)
+                return "Measured Polygon";
+            else
+                return "Polygon";
 
-      case wkbMultiPoint:
-        if( b2D )
-            return "Multi Point";
-        else
-            return "3D Multi Point";
+        case wkbMultiPoint:
+            if (b3D && bMeasured)
+                return "3D Measured Multi Point";
+            else if (b3D)
+                return "3D Multi Point";
+            else if (bMeasured)
+                return "Measured Multi Point";
+            else
+                return "Multi Point";
 
-      case wkbMultiLineString:
-        if( b2D )
-            return "Multi Line String";
-        else
-            return "3D Multi Line String";
+        case wkbMultiLineString:
+            if (b3D && bMeasured)
+                return "3D Measured Multi Line String";
+            else if (b3D)
+                return "3D Multi Line String";
+            else if (bMeasured)
+                return "Measured Multi Line String";
+            else
+                return "Multi Line String";
 
-      case wkbMultiPolygon:
-        if( b2D )
-            return "Multi Polygon";
-        else
-            return "3D Multi Polygon";
+        case wkbMultiPolygon:
+          if (b3D && bMeasured)
+                return "3D Measured Multi Polygon";
+            else if (b3D)
+                return "3D Multi Polygon";
+            else if (bMeasured)
+                return "Measured Multi Polygon";
+            else
+                return "Multi Polygon";
 
-      case wkbGeometryCollection:
-        if( b2D )
-            return "Geometry Collection";
-        else
-            return "3D Geometry Collection";
+        case wkbGeometryCollection:
+            if (b3D && bMeasured)
+                return "3D Measured Geometry Collection";
+            else if (b3D)
+                return "3D Geometry Collection";
+            else if (bMeasured)
+                return "Measured Geometry Collection";
+            else
+                return "Geometry Collection";
 
-      case wkbCircularString:
-        if( b2D )
-            return "Circular String";
-        else
-            return "3D Circular String";
+        case wkbCircularString:
+            if (b3D && bMeasured)
+                return "3D Measured Circular String";
+            else if (b3D)
+                return "3D Circular String";
+            else if (bMeasured)
+                return "Measured Circular String";
+            else
+                return "Circular String";
 
-      case wkbCompoundCurve:
-        if( b2D )
-            return "Compound Curve";
-        else
-            return "3D Compound Curve";
+        case wkbCompoundCurve:
+            if (b3D && bMeasured)
+                return "3D Measured Compound Curve";
+            else if (b3D)
+                return "3D Compound Curve";
+            else if (bMeasured)
+                return "Measured Compound Curve";
+            else
+                return "Compound Curve";
 
-      case wkbCurvePolygon:
-        if( b2D )
-            return "Curve Polygon";
-        else
-            return "3D Curve Polygon";
+        case wkbCurvePolygon:
+            if (b3D && bMeasured)
+                return "3D Measured Curve Polygon";
+            else if (b3D)
+                return "3D Curve Polygon";
+            else if (bMeasured)
+                return "Measured Curve Polygon";
+            else
+                return "Curve Polygon";
 
-      case wkbMultiCurve:
-        if( b2D )
-            return "Multi Curve";
-        else
-            return "3D Multi Curve";
+        case wkbMultiCurve:
+            if (b3D && bMeasured)
+                return "3D Measured Multi Curve";
+            else if (b3D)
+                return "3D Multi Curve";
+            else if (bMeasured)
+                return "Measured Multi Curve";
+            else
+                return "Multi Curve";
 
-      case wkbMultiSurface:
-        if( b2D )
-            return "Multi Surface";
-        else
-            return "3D Multi Surface";
-
-      case wkbNone:
-        return "None";
-
-      default:
-      {
-          // OGRThreadSafety: This static is judged to be a very low risk 
-          // for thread safety because it is only used in case of error, 
-          // and the worst that can happen is reporting the wrong code
-          // in the generated message.
-          static char szWorkName[33];
-          sprintf( szWorkName, "Unrecognised: %d", (int) eType );
-          return szWorkName;
-      }
+        case wkbMultiSurface:
+            if (b3D && bMeasured)
+                return "3D Measured Multi Surface";
+            else if (b3D)
+                return "3D Multi Surface";
+            else if (bMeasured)
+                return "Measured Multi Surface";
+            else
+                return "Multi Surface";
+
+        case wkbCurve:
+            if (b3D && bMeasured)
+                return "3D Measured Curve";
+            else if (b3D)
+                return "3D Curve";
+            else if (bMeasured)
+                return "Measured Curve";
+            else
+                return "Curve";
+
+        case wkbSurface:
+            if (b3D && bMeasured)
+                return "3D Measured Surface";
+            else if (b3D)
+                return "3D Surface";
+            else if (bMeasured)
+                return "Measured Surface";
+            else
+                return "Surface";
+
+        case wkbNone:
+            return "None";
+
+        default:
+        {
+            return CPLSPrintf( "Unrecognized: %d", (int) eType );
+        }
     }
 }
 
@@ -2019,15 +2428,15 @@ const char *OGRGeometryTypeToName( OGRwkbGeometryType eType )
  * geometry types with nothing in common but the base geometry
  * type.  wkbNone should be used to indicate that no geometries
  * have been encountered yet, and means the first geometry
- * encounted will establish the preliminary type.
- * 
+ * encountered will establish the preliminary type.
+ *
  * @param eMain the first input geometry type.
  * @param eExtra the second input geometry type.
  *
  * @return the merged geometry type.
  */
 
-OGRwkbGeometryType 
+OGRwkbGeometryType
 OGRMergeGeometryTypes( OGRwkbGeometryType eMain,
                        OGRwkbGeometryType eExtra )
 
@@ -2047,13 +2456,13 @@ OGRMergeGeometryTypes( OGRwkbGeometryType eMain,
  * geometry types with nothing in common but the base geometry
  * type.  wkbNone should be used to indicate that no geometries
  * have been encountered yet, and means the first geometry
- * encounted will establish the preliminary type.
+ * encountered will establish the preliminary type.
  *
  * If bAllowPromotingToCurves is set to TRUE, mixing Polygon and CurvePolygon
  * will return CurvePolygon. Mixing LineString, CircularString, CompoundCurve
  * will return CompoundCurve. Mixing MultiPolygon and MultiSurface will return
  * MultiSurface. Mixing MultiCurve and MultiLineString will return MultiCurve.
- * 
+ *
  * @param eMain the first input geometry type.
  * @param eExtra the second input geometry type.
  * @param bAllowPromotingToCurves determine if promotion to curve type must be done.
@@ -2063,20 +2472,20 @@ OGRMergeGeometryTypes( OGRwkbGeometryType eMain,
  * @since GDAL 2.0
  */
 
-OGRwkbGeometryType 
+OGRwkbGeometryType
 OGRMergeGeometryTypesEx( OGRwkbGeometryType eMain,
                          OGRwkbGeometryType eExtra,
                          int bAllowPromotingToCurves )
 
 {
-    int bHasZ;
     OGRwkbGeometryType eFMain = wkbFlatten(eMain);
     OGRwkbGeometryType eFExtra = wkbFlatten(eExtra);
 
-    bHasZ = ( eFMain != eMain || eFExtra != eExtra );
+    const bool bHasZ = ( wkbHasZ(eMain) || wkbHasZ(eExtra) );
+    const bool bHasM = ( wkbHasM(eMain) || wkbHasM(eExtra) );
 
     if( eFMain == wkbUnknown || eFExtra == wkbUnknown )
-        return OGR_GT_SetModifier(wkbUnknown, bHasZ, FALSE);
+        return OGR_GT_SetModifier(wkbUnknown, bHasZ, bHasM);
 
     if( eFMain == wkbNone )
         return eExtra;
@@ -2086,30 +2495,40 @@ OGRMergeGeometryTypesEx( OGRwkbGeometryType eMain,
 
     if( eFMain == eFExtra )
     {
-        return OGR_GT_SetModifier(eFMain, bHasZ, FALSE);
+        return OGR_GT_SetModifier(eFMain, bHasZ, bHasM);
     }
 
     if( bAllowPromotingToCurves )
     {
         if( OGR_GT_IsCurve(eFMain) && OGR_GT_IsCurve(eFExtra) )
-            return OGR_GT_SetModifier(wkbCompoundCurve, bHasZ, FALSE);
+            return OGR_GT_SetModifier(wkbCompoundCurve, bHasZ, bHasM);
 
         if( OGR_GT_IsSubClassOf(eFMain, eFExtra) )
-            return OGR_GT_SetModifier(eFExtra, bHasZ, FALSE);
+            return OGR_GT_SetModifier(eFExtra, bHasZ, bHasM);
 
         if( OGR_GT_IsSubClassOf(eFExtra, eFMain) )
-            return OGR_GT_SetModifier(eFMain, bHasZ, FALSE);
+            return OGR_GT_SetModifier(eFMain, bHasZ, bHasM);
     }
 
     // Both are geometry collections.
     if( OGR_GT_IsSubClassOf(eFMain, wkbGeometryCollection) &&
         OGR_GT_IsSubClassOf(eFExtra, wkbGeometryCollection) )
     {
-        return OGR_GT_SetModifier(wkbGeometryCollection, bHasZ, FALSE);
+        return OGR_GT_SetModifier(wkbGeometryCollection, bHasZ, bHasM);
+    }
+
+    // One is subclass of the other one
+    if( OGR_GT_IsSubClassOf(eFMain, eFExtra) )
+    {
+        return OGR_GT_SetModifier(eFExtra, bHasZ, bHasM);
+    }
+    else if( OGR_GT_IsSubClassOf(eFExtra, eFMain) )
+    {
+        return OGR_GT_SetModifier(eFMain, bHasZ, bHasM);
     }
 
     // Nothing apparently in common.
-    return OGR_GT_SetModifier(wkbUnknown, bHasZ, FALSE);
+    return OGR_GT_SetModifier(wkbUnknown, bHasZ, bHasM);
 }
 
 /**
@@ -2195,19 +2614,7 @@ char *OGRGeometry::exportToGML( const char* const * papszOptions ) const
 
 char *OGRGeometry::exportToKML() const
 {
-#ifndef _WIN32_WCE
-#ifdef OGR_ENABLED
     return OGR_G_ExportToKML( (OGRGeometryH) this, NULL );
-#else
-    CPLError( CE_Failure, CPLE_AppDefined,
-              "OGRGeometry::exportToKML() not supported in builds without OGR drivers." );
-    return NULL;
-#endif
-#else
-    CPLError( CE_Failure, CPLE_AppDefined,
-              "OGRGeometry::exportToKML() not supported in the WinCE build." );
-    return NULL;
-#endif
 }
 
 /************************************************************************/
@@ -2228,20 +2635,8 @@ char *OGRGeometry::exportToKML() const
 
 char *OGRGeometry::exportToJson() const
 {
-#ifndef _WIN32_WCE
-#ifdef OGR_ENABLED
     OGRGeometry* poGeometry = const_cast<OGRGeometry*>(this);
     return OGR_G_ExportToJson( (OGRGeometryH) (poGeometry) );
-#else
-    CPLError( CE_Failure, CPLE_AppDefined,
-              "OGRGeometry::exportToJson() not supported in builds without OGR drivers." );
-    return NULL;
-#endif
-#else
-    CPLError( CE_Failure, CPLE_AppDefined,
-              "OGRGeometry::exportToJson() not supported in the WinCE build." );
-    return NULL;
-#endif
 }
 
 /************************************************************************/
@@ -2286,7 +2681,7 @@ int OGRGetGenerate_DB2_V72_BYTE_ORDER()
 GEOSContextHandle_t OGRGeometry::createGEOSContext()
 {
 #ifndef HAVE_GEOS
-    CPLError( CE_Failure, CPLE_NotSupported, 
+    CPLError( CE_Failure, CPLE_NotSupported,
               "GEOS support not enabled." );
     return NULL;
 #else
@@ -2298,7 +2693,7 @@ GEOSContextHandle_t OGRGeometry::createGEOSContext()
 /*                          freeGEOSContext()                           */
 /************************************************************************/
 
-void OGRGeometry::freeGEOSContext(GEOSContextHandle_t hGEOSCtxt)
+void OGRGeometry::freeGEOSContext(UNUSED_IF_NO_GEOS GEOSContextHandle_t hGEOSCtxt)
 {
 #ifdef HAVE_GEOS
     if( hGEOSCtxt != NULL )
@@ -2312,12 +2707,12 @@ void OGRGeometry::freeGEOSContext(GEOSContextHandle_t hGEOSCtxt)
 /*                            exportToGEOS()                            */
 /************************************************************************/
 
-GEOSGeom OGRGeometry::exportToGEOS(GEOSContextHandle_t hGEOSCtxt) const
+GEOSGeom OGRGeometry::exportToGEOS(UNUSED_IF_NO_GEOS GEOSContextHandle_t hGEOSCtxt) const
 
 {
 #ifndef HAVE_GEOS
 
-    CPLError( CE_Failure, CPLE_NotSupported, 
+    CPLError( CE_Failure, CPLE_NotSupported,
               "GEOS support not enabled." );
     return NULL;
 
@@ -2338,7 +2733,22 @@ GEOSGeom OGRGeometry::exportToGEOS(GEOSContextHandle_t hGEOSCtxt) const
     size_t nDataSize;
     unsigned char *pabyData = NULL;
 
-    const OGRGeometry* poLinearGeom = (hasCurveGeometry()) ? getLinearGeometry() : this;
+    OGRGeometry* poLinearGeom = NULL;
+    if( hasCurveGeometry() )
+    {
+        poLinearGeom = getLinearGeometry();
+        if( poLinearGeom->IsMeasured() )
+            poLinearGeom->setMeasured(FALSE);
+    }
+    else
+    {
+        poLinearGeom = const_cast<OGRGeometry*>(this);
+        if( IsMeasured() )
+        {
+            poLinearGeom = clone();
+            poLinearGeom->setMeasured(FALSE);
+        }
+    }
     nDataSize = poLinearGeom->WkbSize();
     pabyData = (unsigned char *) CPLMalloc(nDataSize);
     if( poLinearGeom->exportToWkb( wkbNDR, pabyData ) == OGRERR_NONE )
@@ -2465,8 +2875,8 @@ OGRGeometry* OGRGeometry::getCurveGeometry(CPL_UNUSED const char* const* papszOp
  *
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this method will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this method will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @param poOtherGeom the other geometry to compare against.
  *
@@ -2484,7 +2894,7 @@ double OGRGeometry::Distance( const OGRGeometry *poOtherGeom ) const
 
 #ifndef HAVE_GEOS
 
-    CPLError( CE_Failure, CPLE_NotSupported, 
+    CPLError( CE_Failure, CPLE_NotSupported,
               "GEOS support not enabled." );
     return -1.0;
 
@@ -2497,7 +2907,7 @@ double OGRGeometry::Distance( const OGRGeometry *poOtherGeom ) const
     GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
     hOther = poOtherGeom->exportToGEOS(hGEOSCtxt);
     hThis = exportToGEOS(hGEOSCtxt);
-   
+
     int bIsErr = 0;
     double dfDistance = 0.0;
 
@@ -2510,7 +2920,7 @@ double OGRGeometry::Distance( const OGRGeometry *poOtherGeom ) const
     GEOSGeom_destroy_r( hGEOSCtxt, hOther );
     freeGEOSContext( hGEOSCtxt );
 
-    if ( bIsErr > 0 ) 
+    if ( bIsErr > 0 )
     {
         return dfDistance;
     }
@@ -2534,8 +2944,8 @@ double OGRGeometry::Distance( const OGRGeometry *poOtherGeom ) const
  *
  * This function is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this function will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this function will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @param hFirst the first geometry to compare against.
  * @param hOther the other geometry to compare against.
@@ -2556,6 +2966,7 @@ double OGR_G_Distance( OGRGeometryH hFirst, OGRGeometryH hOther )
 /*                       OGRGeometryRebuildCurves()                     */
 /************************************************************************/
 
+#ifdef HAVE_GEOS
 static OGRGeometry* OGRGeometryRebuildCurves(const OGRGeometry* poGeom,
                                              const OGRGeometry* poOtherGeom,
                                              OGRGeometry* poOGRProduct)
@@ -2571,6 +2982,7 @@ static OGRGeometry* OGRGeometryRebuildCurves(const OGRGeometry* poGeom,
     }
     return poOGRProduct;
 }
+#endif
 
 /************************************************************************/
 /*                             ConvexHull()                             */
@@ -2580,14 +2992,14 @@ static OGRGeometry* OGRGeometryRebuildCurves(const OGRGeometry* poGeom,
  * \brief Compute convex hull.
  *
  * A new geometry object is created and returned containing the convex
- * hull of the geometry on which the method is invoked.  
+ * hull of the geometry on which the method is invoked.
  *
  * This method is the same as the C function OGR_G_ConvexHull().
  *
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this method will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this method will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @return a newly allocated geometry now owned by the caller, or NULL on failure.
  */
@@ -2597,7 +3009,7 @@ OGRGeometry *OGRGeometry::ConvexHull() const
 {
 #ifndef HAVE_GEOS
 
-    CPLError( CE_Failure, CPLE_NotSupported, 
+    CPLError( CE_Failure, CPLE_NotSupported,
               "GEOS support not enabled." );
     return NULL;
 
@@ -2637,14 +3049,14 @@ OGRGeometry *OGRGeometry::ConvexHull() const
  * \brief Compute convex hull.
  *
  * A new geometry object is created and returned containing the convex
- * hull of the geometry on which the method is invoked.  
+ * hull of the geometry on which the method is invoked.
  *
  * This function is the same as the C++ method OGRGeometry::ConvexHull().
  *
  * This function is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this function will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this function will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @param hTarget The Geometry to calculate the convex hull of.
  *
@@ -2668,14 +3080,14 @@ OGRGeometryH OGR_G_ConvexHull( OGRGeometryH hTarget )
  * \brief Compute boundary.
  *
  * A new geometry object is created and returned containing the boundary
- * of the geometry on which the method is invoked.  
+ * of the geometry on which the method is invoked.
  *
  * This method is the same as the C function OGR_G_Boundary().
  *
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this method will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this method will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @return a newly allocated geometry now owned by the caller, or NULL on failure.
  *
@@ -2687,12 +3099,12 @@ OGRGeometry *OGRGeometry::Boundary() const
 {
 #ifndef HAVE_GEOS
 
-    CPLError( CE_Failure, CPLE_NotSupported, 
+    CPLError( CE_Failure, CPLE_NotSupported,
               "GEOS support not enabled." );
     return NULL;
 
 #else
-    
+
     GEOSGeom hGeosGeom = NULL;
     GEOSGeom hGeosProduct = NULL;
     OGRGeometry *poOGRProduct = NULL;
@@ -2741,14 +3153,14 @@ OGRGeometry *OGRGeometry::getBoundary() const
  * \brief Compute boundary.
  *
  * A new geometry object is created and returned containing the boundary
- * of the geometry on which the method is invoked.  
+ * of the geometry on which the method is invoked.
  *
  * This function is the same as the C++ method OGR_G_Boundary().
  *
  * This function is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this function will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this function will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @param hTarget The Geometry to calculate the boundary of.
  *
@@ -2789,37 +3201,38 @@ OGRGeometryH OGR_G_GetBoundary( OGRGeometryH hTarget )
  *
  * Builds a new geometry containing the buffer region around the geometry
  * on which it is invoked.  The buffer is a polygon containing the region within
- * the buffer distance of the original geometry.  
+ * the buffer distance of the original geometry.
  *
  * Some buffer sections are properly described as curves, but are converted to
- * approximate polygons.  The nQuadSegs parameter can be used to control how many
- * segements should be used to define a 90 degree curve - a quadrant of a circle. 
- * A value of 30 is a reasonable default.  Large values result in large numbers
- * of vertices in the resulting buffer geometry while small numbers reduce the 
- * accuracy of the result. 
+ * approximate polygons.  The nQuadSegs parameter can be used to control how
+ * many segments should be used to define a 90 degree curve - a quadrant of a
+ * circle.  A value of 30 is a reasonable default.  Large values result in
+ * large numbers of vertices in the resulting buffer geometry while small
+ * numbers reduce the accuracy of the result.
  *
  * This method is the same as the C function OGR_G_Buffer().
  *
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this method will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this method will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @param dfDist the buffer distance to be applied. Should be expressed into
  *               the same unit as the coordinates of the geometry.
  *
  * @param nQuadSegs the number of segments used to approximate a 90 degree (quadrant) of
- * curvature. 
+ * curvature.
  *
- * @return the newly created geometry, or NULL if an error occurs. 
+ * @return the newly created geometry, or NULL if an error occurs.
  */
 
-OGRGeometry *OGRGeometry::Buffer( double dfDist, int nQuadSegs ) const
+OGRGeometry *OGRGeometry::Buffer( UNUSED_IF_NO_GEOS double dfDist,
+                                  UNUSED_IF_NO_GEOS int nQuadSegs ) const
 
 {
 #ifndef HAVE_GEOS
 
-    CPLError( CE_Failure, CPLE_NotSupported, 
+    CPLError( CE_Failure, CPLE_NotSupported,
               "GEOS support not enabled." );
     return NULL;
 
@@ -2861,30 +3274,30 @@ OGRGeometry *OGRGeometry::Buffer( double dfDist, int nQuadSegs ) const
  *
  * Builds a new geometry containing the buffer region around the geometry
  * on which it is invoked.  The buffer is a polygon containing the region within
- * the buffer distance of the original geometry.  
+ * the buffer distance of the original geometry.
  *
  * Some buffer sections are properly described as curves, but are converted to
- * approximate polygons.  The nQuadSegs parameter can be used to control how many
- * segements should be used to define a 90 degree curve - a quadrant of a circle. 
- * A value of 30 is a reasonable default.  Large values result in large numbers
- * of vertices in the resulting buffer geometry while small numbers reduce the 
- * accuracy of the result. 
+ * approximate polygons.  The nQuadSegs parameter can be used to control how
+ * many segments should be used to define a 90 degree curve - a quadrant of a
+ * circle.  A value of 30 is a reasonable default.  Large values result in
+ * large numbers of vertices in the resulting buffer geometry while small
+ * numbers reduce the accuracy of the result.
  *
  * This function is the same as the C++ method OGRGeometry::Buffer().
  *
  * This function is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this function will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this function will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @param hTarget the geometry.
  * @param dfDist the buffer distance to be applied. Should be expressed into
  *               the same unit as the coordinates of the geometry.
  *
  * @param nQuadSegs the number of segments used to approximate a 90 degree
- * (quadrant) of curvature. 
+ * (quadrant) of curvature.
  *
- * @return the newly created geometry, or NULL if an error occurs. 
+ * @return the newly created geometry, or NULL if an error occurs.
  */
 
 OGRGeometryH OGR_G_Buffer( OGRGeometryH hTarget, double dfDist, int nQuadSegs )
@@ -2904,14 +3317,14 @@ OGRGeometryH OGR_G_Buffer( OGRGeometryH hTarget, double dfDist, int nQuadSegs )
  *
  * Generates a new geometry which is the region of intersection of the
  * two geometries operated on.  The Intersects() method can be used to test if
- * two geometries intersect. 
+ * two geometries intersect.
  *
  * This method is the same as the C function OGR_G_Intersection().
  *
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this method will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this method will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @param poOtherGeom the other geometry intersected with "this" geometry.
  *
@@ -2919,12 +3332,12 @@ OGRGeometryH OGR_G_Buffer( OGRGeometryH hTarget, double dfDist, int nQuadSegs )
  * no intersection or an error occurs.
  */
 
-OGRGeometry *OGRGeometry::Intersection( const OGRGeometry *poOtherGeom ) const
+OGRGeometry *OGRGeometry::Intersection( UNUSED_IF_NO_GEOS const OGRGeometry *poOtherGeom ) const
 
 {
 #ifndef HAVE_GEOS
 
-    CPLError( CE_Failure, CPLE_NotSupported, 
+    CPLError( CE_Failure, CPLE_NotSupported,
               "GEOS support not enabled." );
     return NULL;
 
@@ -2973,14 +3386,14 @@ OGRGeometry *OGRGeometry::Intersection( const OGRGeometry *poOtherGeom ) const
  *
  * Generates a new geometry which is the region of intersection of the
  * two geometries operated on.  The OGR_G_Intersects() function can be used to
- * test if two geometries intersect. 
+ * test if two geometries intersect.
  *
  * This function is the same as the C++ method OGRGeometry::Intersection().
  *
  * This function is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this function will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this function will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @param hThis the geometry.
  * @param hOther the other geometry.
@@ -2994,7 +3407,7 @@ OGRGeometryH OGR_G_Intersection( OGRGeometryH hThis, OGRGeometryH hOther )
 {
     VALIDATE_POINTER1( hThis, "OGR_G_Intersection", NULL );
 
-    return (OGRGeometryH) 
+    return (OGRGeometryH)
         ((OGRGeometry *) hThis)->Intersection( (OGRGeometry *) hOther );
 }
 
@@ -3006,26 +3419,26 @@ OGRGeometryH OGR_G_Intersection( OGRGeometryH hThis, OGRGeometryH hOther )
  * \brief Compute union.
  *
  * Generates a new geometry which is the region of union of the
- * two geometries operated on.  
+ * two geometries operated on.
  *
  * This method is the same as the C function OGR_G_Union().
  *
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this method will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this method will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @param poOtherGeom the other geometry unioned with "this" geometry.
  *
  * @return a new geometry representing the union or NULL if an error occurs.
  */
 
-OGRGeometry *OGRGeometry::Union( const OGRGeometry *poOtherGeom ) const
+OGRGeometry *OGRGeometry::Union( UNUSED_IF_NO_GEOS const OGRGeometry *poOtherGeom ) const
 
 {
 #ifndef HAVE_GEOS
 
-    CPLError( CE_Failure, CPLE_NotSupported, 
+    CPLError( CE_Failure, CPLE_NotSupported,
               "GEOS support not enabled." );
     return NULL;
 
@@ -3073,14 +3486,14 @@ OGRGeometry *OGRGeometry::Union( const OGRGeometry *poOtherGeom ) const
  * \brief Compute union.
  *
  * Generates a new geometry which is the region of union of the
- * two geometries operated on.  
+ * two geometries operated on.
  *
  * This function is the same as the C++ method OGRGeometry::Union().
  *
  * This function is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this function will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this function will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @param hThis the geometry.
  * @param hOther the other geometry.
@@ -3093,7 +3506,7 @@ OGRGeometryH OGR_G_Union( OGRGeometryH hThis, OGRGeometryH hOther )
 {
     VALIDATE_POINTER1( hThis, "OGR_G_Union", NULL );
 
-    return (OGRGeometryH) 
+    return (OGRGeometryH)
         ((OGRGeometry *) hThis)->Union( (OGRGeometry *) hOther );
 }
 
@@ -3108,8 +3521,8 @@ OGRGeometryH OGR_G_Union( OGRGeometryH hThis, OGRGeometryH hOther )
  *
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this method will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this method will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @return a new geometry representing the union or NULL if an error occurs.
  *
@@ -3121,7 +3534,7 @@ OGRGeometry *OGRGeometry::UnionCascaded() const
 {
 #ifndef HAVE_GEOS
 
-    CPLError( CE_Failure, CPLE_NotSupported, 
+    CPLError( CE_Failure, CPLE_NotSupported,
               "GEOS support not enabled." );
     return NULL;
 #else
@@ -3163,8 +3576,8 @@ OGRGeometry *OGRGeometry::UnionCascaded() const
  *
  * This function is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this function will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this function will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @param hThis the geometry.
  *
@@ -3176,7 +3589,7 @@ OGRGeometryH OGR_G_UnionCascaded( OGRGeometryH hThis )
 {
     VALIDATE_POINTER1( hThis, "OGR_G_UnionCascaded", NULL );
 
-    return (OGRGeometryH) 
+    return (OGRGeometryH)
         ((OGRGeometry *) hThis)->UnionCascaded();
 }
 
@@ -3188,32 +3601,32 @@ OGRGeometryH OGR_G_UnionCascaded( OGRGeometryH hThis )
  * \brief Compute difference.
  *
  * Generates a new geometry which is the region of this geometry with the
- * region of the second geometry removed. 
+ * region of the second geometry removed.
  *
  * This method is the same as the C function OGR_G_Difference().
  *
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this method will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this method will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @param poOtherGeom the other geometry removed from "this" geometry.
  *
- * @return a new geometry representing the difference or NULL if the 
+ * @return a new geometry representing the difference or NULL if the
  * difference is empty or an error occurs.
  */
 
-OGRGeometry *OGRGeometry::Difference( const OGRGeometry *poOtherGeom ) const
+OGRGeometry *OGRGeometry::Difference( UNUSED_IF_NO_GEOS const OGRGeometry *poOtherGeom ) const
 
 {
 #ifndef HAVE_GEOS
 
-    CPLError( CE_Failure, CPLE_NotSupported, 
+    CPLError( CE_Failure, CPLE_NotSupported,
               "GEOS support not enabled." );
     return NULL;
 
 #else
-    
+
     GEOSGeom hThisGeosGeom = NULL;
     GEOSGeom hOtherGeosGeom = NULL;
     GEOSGeom hGeosProduct = NULL;
@@ -3256,19 +3669,19 @@ OGRGeometry *OGRGeometry::Difference( const OGRGeometry *poOtherGeom ) const
  * \brief Compute difference.
  *
  * Generates a new geometry which is the region of this geometry with the
- * region of the other geometry removed. 
+ * region of the other geometry removed.
  *
  * This function is the same as the C++ method OGRGeometry::Difference().
  *
  * This function is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this function will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this function will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @param hThis the geometry.
  * @param hOther the other geometry.
  *
- * @return a new geometry representing the difference or NULL if the 
+ * @return a new geometry representing the difference or NULL if the
  * difference is empty or an error occurs.
  */
 
@@ -3277,7 +3690,7 @@ OGRGeometryH OGR_G_Difference( OGRGeometryH hThis, OGRGeometryH hOther )
 {
     VALIDATE_POINTER1( hThis, "OGR_G_Difference", NULL );
 
-    return (OGRGeometryH) 
+    return (OGRGeometryH)
         ((OGRGeometry *) hThis)->Difference( (OGRGeometry *) hOther );
 }
 
@@ -3295,24 +3708,24 @@ OGRGeometryH OGR_G_Difference( OGRGeometryH hThis, OGRGeometryH hOther )
  *
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this method will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this method will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @param poOtherGeom the other geometry.
  *
- * @return a new geometry representing the symmetric difference or NULL if the 
+ * @return a new geometry representing the symmetric difference or NULL if the
  * difference is empty or an error occurs.
  *
  * @since OGR 1.8.0
  */
 
 OGRGeometry *
-OGRGeometry::SymDifference( const OGRGeometry *poOtherGeom ) const
+OGRGeometry::SymDifference( UNUSED_IF_NO_GEOS const OGRGeometry *poOtherGeom ) const
 
 {
 #ifndef HAVE_GEOS
 
-    CPLError( CE_Failure, CPLE_NotSupported, 
+    CPLError( CE_Failure, CPLE_NotSupported,
               "GEOS support not enabled." );
     return NULL;
 
@@ -3381,13 +3794,13 @@ OGRGeometry::SymmetricDifference( const OGRGeometry *poOtherGeom ) const
  *
  * This function is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this function will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this function will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @param hThis the geometry.
  * @param hOther the other geometry.
  *
- * @return a new geometry representing the symmetric difference or NULL if the 
+ * @return a new geometry representing the symmetric difference or NULL if the
  * difference is empty or an error occurs.
  *
  * @since OGR 1.8.0
@@ -3398,7 +3811,7 @@ OGRGeometryH OGR_G_SymDifference( OGRGeometryH hThis, OGRGeometryH hOther )
 {
     VALIDATE_POINTER1( hThis, "OGR_G_SymDifference", NULL );
 
-    return (OGRGeometryH) 
+    return (OGRGeometryH)
         ((OGRGeometry *) hThis)->SymDifference( (OGRGeometry *) hOther );
 }
 
@@ -3414,7 +3827,7 @@ OGRGeometryH OGR_G_SymmetricDifference( OGRGeometryH hThis, OGRGeometryH hOther
 {
     VALIDATE_POINTER1( hThis, "OGR_G_SymmetricDifference", NULL );
 
-    return (OGRGeometryH) 
+    return (OGRGeometryH)
         ((OGRGeometry *) hThis)->SymDifference( (OGRGeometry *) hOther );
 }
 
@@ -3425,27 +3838,27 @@ OGRGeometryH OGR_G_SymmetricDifference( OGRGeometryH hThis, OGRGeometryH hOther
 /**
  * \brief Test for disjointness.
  *
- * Tests if this geometry and the other passed into the method are disjoint. 
+ * Tests if this geometry and the other passed into the method are disjoint.
  *
  * This method is the same as the C function OGR_G_Disjoint().
  *
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this method will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this method will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @param poOtherGeom the geometry to compare to this geometry.
  *
- * @return TRUE if they are disjoint, otherwise FALSE.  
+ * @return TRUE if they are disjoint, otherwise FALSE.
  */
 
 OGRBoolean
-OGRGeometry::Disjoint( const OGRGeometry *poOtherGeom ) const
+OGRGeometry::Disjoint( UNUSED_IF_NO_GEOS const OGRGeometry *poOtherGeom ) const
 
 {
 #ifndef HAVE_GEOS
 
-    CPLError( CE_Failure, CPLE_NotSupported, 
+    CPLError( CE_Failure, CPLE_NotSupported,
               "GEOS support not enabled." );
     return FALSE;
 
@@ -3478,19 +3891,19 @@ OGRGeometry::Disjoint( const OGRGeometry *poOtherGeom ) const
 /**
  * \brief Test for disjointness.
  *
- * Tests if this geometry and the other geometry are disjoint. 
+ * Tests if this geometry and the other geometry are disjoint.
  *
  * This function is the same as the C++ method OGRGeometry::Disjoint().
  *
  * This function is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this function will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this function will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @param hThis the geometry to compare.
  * @param hOther the other geometry to compare.
  *
- * @return TRUE if they are disjoint, otherwise FALSE.  
+ * @return TRUE if they are disjoint, otherwise FALSE.
  */
 int OGR_G_Disjoint( OGRGeometryH hThis, OGRGeometryH hOther )
 
@@ -3513,21 +3926,21 @@ int OGR_G_Disjoint( OGRGeometryH hThis, OGRGeometryH hOther )
  *
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this method will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this method will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @param poOtherGeom the geometry to compare to this geometry.
  *
- * @return TRUE if they are touching, otherwise FALSE.  
+ * @return TRUE if they are touching, otherwise FALSE.
  */
 
 OGRBoolean
-OGRGeometry::Touches( const OGRGeometry *poOtherGeom ) const
+OGRGeometry::Touches( UNUSED_IF_NO_GEOS const OGRGeometry *poOtherGeom ) const
 
 {
 #ifndef HAVE_GEOS
 
-    CPLError( CE_Failure, CPLE_NotSupported, 
+    CPLError( CE_Failure, CPLE_NotSupported,
               "GEOS support not enabled." );
     return FALSE;
 
@@ -3566,13 +3979,13 @@ OGRGeometry::Touches( const OGRGeometry *poOtherGeom ) const
  *
  * This function is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this function will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this function will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @param hThis the geometry to compare.
  * @param hOther the other geometry to compare.
  *
- * @return TRUE if they are touching, otherwise FALSE.  
+ * @return TRUE if they are touching, otherwise FALSE.
  */
 
 int OGR_G_Touches( OGRGeometryH hThis, OGRGeometryH hOther )
@@ -3596,21 +4009,21 @@ int OGR_G_Touches( OGRGeometryH hThis, OGRGeometryH hOther )
  *
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this method will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this method will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @param poOtherGeom the geometry to compare to this geometry.
  *
- * @return TRUE if they are crossing, otherwise FALSE.  
+ * @return TRUE if they are crossing, otherwise FALSE.
  */
 
 OGRBoolean
-OGRGeometry::Crosses( const OGRGeometry *poOtherGeom ) const
+OGRGeometry::Crosses( UNUSED_IF_NO_GEOS const OGRGeometry *poOtherGeom ) const
 
 {
 #ifndef HAVE_GEOS
 
-    CPLError( CE_Failure, CPLE_NotSupported, 
+    CPLError( CE_Failure, CPLE_NotSupported,
               "GEOS support not enabled." );
     return FALSE;
 
@@ -3649,13 +4062,13 @@ OGRGeometry::Crosses( const OGRGeometry *poOtherGeom ) const
  *
  * This function is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this function will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this function will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @param hThis the geometry to compare.
  * @param hOther the other geometry to compare.
  *
- * @return TRUE if they are crossing, otherwise FALSE.  
+ * @return TRUE if they are crossing, otherwise FALSE.
  */
 
 int OGR_G_Crosses( OGRGeometryH hThis, OGRGeometryH hOther )
@@ -3679,21 +4092,21 @@ int OGR_G_Crosses( OGRGeometryH hThis, OGRGeometryH hOther )
  *
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this method will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this method will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @param poOtherGeom the geometry to compare to this geometry.
  *
- * @return TRUE if poOtherGeom is within this geometry, otherwise FALSE.  
+ * @return TRUE if poOtherGeom is within this geometry, otherwise FALSE.
  */
 
 OGRBoolean
-OGRGeometry::Within( const OGRGeometry *poOtherGeom ) const
+OGRGeometry::Within( UNUSED_IF_NO_GEOS const OGRGeometry *poOtherGeom ) const
 
 {
 #ifndef HAVE_GEOS
 
-    CPLError( CE_Failure, CPLE_NotSupported, 
+    CPLError( CE_Failure, CPLE_NotSupported,
               "GEOS support not enabled." );
     return FALSE;
 
@@ -3732,13 +4145,13 @@ OGRGeometry::Within( const OGRGeometry *poOtherGeom ) const
  *
  * This function is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this function will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this function will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @param hThis the geometry to compare.
  * @param hOther the other geometry to compare.
  *
- * @return TRUE if hThis is within hOther, otherwise FALSE.  
+ * @return TRUE if hThis is within hOther, otherwise FALSE.
  */
 int OGR_G_Within( OGRGeometryH hThis, OGRGeometryH hOther )
 
@@ -3761,21 +4174,21 @@ int OGR_G_Within( OGRGeometryH hThis, OGRGeometryH hOther )
  *
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this method will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this method will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @param poOtherGeom the geometry to compare to this geometry.
  *
- * @return TRUE if poOtherGeom contains this geometry, otherwise FALSE.  
+ * @return TRUE if poOtherGeom contains this geometry, otherwise FALSE.
  */
 
 OGRBoolean
-OGRGeometry::Contains( const OGRGeometry *poOtherGeom ) const
+OGRGeometry::Contains( UNUSED_IF_NO_GEOS const OGRGeometry *poOtherGeom ) const
 
 {
 #ifndef HAVE_GEOS
 
-    CPLError( CE_Failure, CPLE_NotSupported, 
+    CPLError( CE_Failure, CPLE_NotSupported,
               "GEOS support not enabled." );
     return FALSE;
 
@@ -3814,13 +4227,13 @@ OGRGeometry::Contains( const OGRGeometry *poOtherGeom ) const
  *
  * This function is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this function will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this function will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @param hThis the geometry to compare.
  * @param hOther the other geometry to compare.
  *
- * @return TRUE if hThis contains hOther geometry, otherwise FALSE.  
+ * @return TRUE if hThis contains hOther geometry, otherwise FALSE.
  */
 int OGR_G_Contains( OGRGeometryH hThis, OGRGeometryH hOther )
 
@@ -3838,27 +4251,27 @@ int OGR_G_Contains( OGRGeometryH hThis, OGRGeometryH hOther )
  * \brief Test for overlap.
  *
  * Tests if this geometry and the other passed into the method overlap, that is
- * their intersection has a non-zero area. 
+ * their intersection has a non-zero area.
  *
  * This method is the same as the C function OGR_G_Overlaps().
  *
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this method will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this method will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @param poOtherGeom the geometry to compare to this geometry.
  *
- * @return TRUE if they are overlapping, otherwise FALSE.  
+ * @return TRUE if they are overlapping, otherwise FALSE.
  */
 
 OGRBoolean
-OGRGeometry::Overlaps( const OGRGeometry *poOtherGeom ) const
+OGRGeometry::Overlaps( UNUSED_IF_NO_GEOS const OGRGeometry *poOtherGeom ) const
 
 {
 #ifndef HAVE_GEOS
 
-    CPLError( CE_Failure, CPLE_NotSupported, 
+    CPLError( CE_Failure, CPLE_NotSupported,
               "GEOS support not enabled." );
     return FALSE;
 
@@ -3891,19 +4304,19 @@ OGRGeometry::Overlaps( const OGRGeometry *poOtherGeom ) const
  * \brief Test for overlap.
  *
  * Tests if this geometry and the other geometry overlap, that is their
- * intersection has a non-zero area. 
+ * intersection has a non-zero area.
  *
  * This function is the same as the C++ method OGRGeometry::Overlaps().
  *
  * This function is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this function will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this function will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @param hThis the geometry to compare.
  * @param hOther the other geometry to compare.
  *
- * @return TRUE if they are overlapping, otherwise FALSE.  
+ * @return TRUE if they are overlapping, otherwise FALSE.
  */
 
 int OGR_G_Overlaps( OGRGeometryH hThis, OGRGeometryH hOther )
@@ -3921,9 +4334,9 @@ int OGR_G_Overlaps( OGRGeometryH hThis, OGRGeometryH hOther )
 /**
  * \brief Force rings to be closed.
  *
- * If this geometry, or any contained geometries has polygon rings that 
+ * If this geometry, or any contained geometries has polygon rings that
  * are not closed, they will be closed by adding the starting point at
- * the end. 
+ * the end.
  */
 
 void OGRGeometry::closeRings()
@@ -3961,7 +4374,7 @@ void OGR_G_CloseRings( OGRGeometryH hGeom )
  * \brief Compute the geometry centroid.
  *
  * The centroid location is applied to the passed in OGRPoint object.
- * The centroid is not necessarily within the geometry.  
+ * The centroid is not necessarily within the geometry.
  *
  * This method relates to the SFCOM ISurface::get_Centroid() method
  * however the current implementation based on GEOS can operate on other
@@ -3974,15 +4387,15 @@ void OGR_G_CloseRings( OGRGeometryH hGeom )
  *
  * This function is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this function will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this function will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @return OGRERR_NONE on success or OGRERR_FAILURE on error.
  *
  * @since OGR 1.8.0 as a OGRGeometry method (previously was restricted to OGRPolygon)
  */
 
-int OGRGeometry::Centroid( OGRPoint *poPoint ) const
+OGRErr OGRGeometry::Centroid( OGRPoint *poPoint ) const
 
 {
     if( poPoint == NULL )
@@ -3990,7 +4403,7 @@ int OGRGeometry::Centroid( OGRPoint *poPoint ) const
 
 #ifndef HAVE_GEOS
     // notdef ... not implemented yet.
-    CPLError( CE_Failure, CPLE_NotSupported, 
+    CPLError( CE_Failure, CPLE_NotSupported,
               "GEOS support not enabled." );
     return OGRERR_FAILURE;
 
@@ -3998,7 +4411,7 @@ int OGRGeometry::Centroid( OGRPoint *poPoint ) const
 
     GEOSGeom hThisGeosGeom = NULL;
     GEOSGeom hOtherGeosGeom = NULL;
-    
+
     GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
     hThisGeosGeom = exportToGEOS(hGEOSCtxt);
 
@@ -4066,7 +4479,7 @@ int OGRGeometry::Centroid( OGRPoint *poPoint ) const
  * \brief Compute the geometry centroid.
  *
  * The centroid location is applied to the passed in OGRPoint object.
- * The centroid is not necessarily within the geometry.  
+ * The centroid is not necessarily within the geometry.
  *
  * This method relates to the SFCOM ISurface::get_Centroid() method
  * however the current implementation based on GEOS can operate on other
@@ -4079,8 +4492,8 @@ int OGRGeometry::Centroid( OGRPoint *poPoint ) const
  *
  * This function is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this function will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this function will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @return OGRERR_NONE on success or OGRERR_FAILURE on error.
  */
@@ -4092,13 +4505,13 @@ int OGR_G_Centroid( OGRGeometryH hGeom, OGRGeometryH hCentroidPoint )
 
     OGRGeometry *poGeom = ((OGRGeometry *) hGeom);
     OGRPoint *poCentroid = ((OGRPoint *) hCentroidPoint);
-    
+
     if( poCentroid == NULL )
         return OGRERR_FAILURE;
 
     if( wkbFlatten(poCentroid->getGeometryType()) != wkbPoint )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Passed wrong geometry type as centroid argument." );
         return OGRERR_FAILURE;
     }
@@ -4120,12 +4533,12 @@ int OGR_G_Centroid( OGRGeometryH hGeom, OGRGeometryH hCentroidPoint )
  *
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this method will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this method will always fail,
+ * issuing a CPLE_NotSupported error.
  *
- * @param hGeom the geometry to operate on. 
+ * @param hGeom the geometry to operate on.
  * @return a point guaranteed to lie on the surface or NULL if an error
- *         occured.
+ *         occurred.
  *
  * @since OGR 1.10
  */
@@ -4136,7 +4549,7 @@ OGRGeometryH OGR_G_PointOnSurface( OGRGeometryH hGeom )
     VALIDATE_POINTER1( hGeom, "OGR_G_PointOnSurface", NULL );
 
 #ifndef HAVE_GEOS
-    CPLError( CE_Failure, CPLE_NotSupported, 
+    CPLError( CE_Failure, CPLE_NotSupported,
               "GEOS support not enabled." );
     return NULL;
 #else
@@ -4146,7 +4559,7 @@ OGRGeometryH OGR_G_PointOnSurface( OGRGeometryH hGeom )
 
     GEOSContextHandle_t hGEOSCtxt = OGRGeometry::createGEOSContext();
     hThisGeosGeom = poThis->exportToGEOS(hGEOSCtxt);
- 
+
     if( hThisGeosGeom != NULL )
     {
         hOtherGeosGeom = GEOSPointOnSurface_r( hGEOSCtxt, hThisGeosGeom );
@@ -4158,9 +4571,9 @@ OGRGeometryH OGR_G_PointOnSurface( OGRGeometryH hGeom )
             return NULL;
         }
 
-        OGRGeometry *poInsidePointGeom = (OGRGeometry *) 
+        OGRGeometry *poInsidePointGeom = (OGRGeometry *)
             OGRGeometryFactory::createFromGEOS(hGEOSCtxt,  hOtherGeosGeom );
- 
+
         GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
 
         if (poInsidePointGeom == NULL)
@@ -4190,6 +4603,31 @@ OGRGeometryH OGR_G_PointOnSurface( OGRGeometryH hGeom )
 }
 
 /************************************************************************/
+/*                          PointOnSurfaceInternal()                    */
+/************************************************************************/
+
+OGRErr OGRGeometry::PointOnSurfaceInternal( OGRPoint * poPoint ) const
+{
+    if( poPoint == NULL || poPoint->IsEmpty() )
+        return OGRERR_FAILURE;
+
+    OGRGeometryH hInsidePoint = OGR_G_PointOnSurface( (OGRGeometryH) this );
+    if( hInsidePoint == NULL )
+        return OGRERR_FAILURE;
+
+    OGRPoint *poInsidePoint = (OGRPoint *) hInsidePoint;
+    if( poInsidePoint->IsEmpty() )
+        poPoint->empty();
+    else
+    {
+        poPoint->setX( poInsidePoint->getX() );
+        poPoint->setY( poInsidePoint->getY() );
+    }
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
 /*                              Simplify()                              */
 /************************************************************************/
 
@@ -4200,8 +4638,8 @@ OGRGeometryH OGR_G_PointOnSurface( OGRGeometryH hGeom )
  *
  * This function is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this function will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this function will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @param dTolerance the distance tolerance for the simplification.
  *
@@ -4210,12 +4648,12 @@ OGRGeometryH OGR_G_PointOnSurface( OGRGeometryH hGeom )
  * @since OGR 1.8.0
  */
 
-OGRGeometry *OGRGeometry::Simplify(double dTolerance) const
+OGRGeometry *OGRGeometry::Simplify(UNUSED_IF_NO_GEOS double dTolerance) const
 
 {
 #ifndef HAVE_GEOS
 
-    CPLError( CE_Failure, CPLE_NotSupported, 
+    CPLError( CE_Failure, CPLE_NotSupported,
               "GEOS support not enabled." );
     return NULL;
 
@@ -4226,7 +4664,7 @@ OGRGeometry *OGRGeometry::Simplify(double dTolerance) const
 
     GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
     hThisGeosGeom = exportToGEOS(hGEOSCtxt);
-    if( hThisGeosGeom != NULL ) 
+    if( hThisGeosGeom != NULL )
     {
         hGeosProduct = GEOSSimplify_r( hGEOSCtxt, hThisGeosGeom, dTolerance );
         GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
@@ -4257,8 +4695,8 @@ OGRGeometry *OGRGeometry::Simplify(double dTolerance) const
  *
  * This function is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this function will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this function will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @param hThis the geometry.
  * @param dTolerance the distance tolerance for the simplification.
@@ -4296,7 +4734,7 @@ OGRGeometryH OGR_G_Simplify( OGRGeometryH hThis, double dTolerance )
  * @since OGR 1.9.0
  */
 
-OGRGeometry *OGRGeometry::SimplifyPreserveTopology(double dTolerance) const
+OGRGeometry *OGRGeometry::SimplifyPreserveTopology(UNUSED_IF_NO_GEOS double dTolerance) const
 
 {
 #ifndef HAVE_GEOS
@@ -4362,6 +4800,98 @@ OGRGeometryH OGR_G_SimplifyPreserveTopology( OGRGeometryH hThis, double dToleran
 }
 
 /************************************************************************/
+/*                         DelaunayTriangulation()                      */
+/************************************************************************/
+
+/**
+ * \brief Return a Delaunay triangulation of the vertices of the geometry.
+ *
+ * This function is the same as the C function OGR_G_DelaunayTriangulation().
+ *
+ * This function is built on the GEOS library, v3.4 or above.
+ * If OGR is built without the GEOS library, this function will always fail,
+ * issuing a CPLE_NotSupported error.
+ *
+ * @param dfTolerance optional snapping tolerance to use for improved robustness
+ * @param bOnlyEdges if TRUE, will return a MULTILINESTRING, otherwise it will
+ *                   return a GEOMETRYCOLLECTION containing triangular POLYGONs.
+ *
+ * @return the geometry resulting from the Delaunay triangulation or NULL if an error occurs.
+ *
+ * @since OGR 2.1
+ */
+
+#ifndef HAVE_GEOS
+OGRGeometry *OGRGeometry::DelaunayTriangulation(double /*dfTolerance*/, int /*bOnlyEdges*/) const
+{
+    CPLError( CE_Failure, CPLE_NotSupported,
+              "GEOS support not enabled." );
+    return NULL;
+}
+#elif GEOS_VERSION_MAJOR < 3 || (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR < 4)
+OGRGeometry *OGRGeometry::DelaunayTriangulation(double /*dfTolerance*/, int /*bOnlyEdges*/) const
+{
+    CPLError( CE_Failure, CPLE_NotSupported,
+              "GEOS 3.4 or later needed for DelaunayTriangulation." );
+    return NULL;
+}
+#else
+OGRGeometry *OGRGeometry::DelaunayTriangulation(double dfTolerance, int bOnlyEdges) const
+{
+    GEOSGeom hThisGeosGeom = NULL;
+    GEOSGeom hGeosProduct = NULL;
+    OGRGeometry *poOGRProduct = NULL;
+
+    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+    hThisGeosGeom = exportToGEOS(hGEOSCtxt);
+    if( hThisGeosGeom != NULL )
+    {
+        hGeosProduct = GEOSDelaunayTriangulation_r( hGEOSCtxt, hThisGeosGeom, dfTolerance, bOnlyEdges );
+        GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
+        if( hGeosProduct != NULL )
+        {
+            poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt,  hGeosProduct );
+            if( poOGRProduct != NULL && getSpatialReference() != NULL )
+                poOGRProduct->assignSpatialReference(getSpatialReference());
+            GEOSGeom_destroy_r( hGEOSCtxt, hGeosProduct );
+        }
+    }
+    freeGEOSContext( hGEOSCtxt );
+    return poOGRProduct;
+}
+#endif
+
+/************************************************************************/
+/*                     OGR_G_DelaunayTriangulation()                    */
+/************************************************************************/
+
+/**
+ * \brief Return a Delaunay triangulation of the vertices of the geometry.
+ *
+ * This function is the same as the C++ method OGRGeometry::DelaunayTriangulation().
+ *
+ * This function is built on the GEOS library, v3.4 or above.
+ * If OGR is built without the GEOS library, this function will always fail,
+ * issuing a CPLE_NotSupported error.
+ *
+ * @param hThis the geometry.
+ * @param dfTolerance optional snapping tolerance to use for improved robustness
+ * @param bOnlyEdges if TRUE, will return a MULTILINESTRING, otherwise it will
+ *                   return a GEOMETRYCOLLECTION containing triangular POLYGONs.
+ *
+ * @return the geometry resulting from the Delaunay triangulation or NULL if an error occurs.
+ *
+ * @since OGR 2.1
+ */
+
+OGRGeometryH OGR_G_DelaunayTriangulation( OGRGeometryH hThis, double dfTolerance, int bOnlyEdges )
+
+{
+    VALIDATE_POINTER1( hThis, "OGR_G_DelaunayTriangulation", NULL );
+    return (OGRGeometryH) ((OGRGeometry *) hThis)->DelaunayTriangulation( dfTolerance, bOnlyEdges );
+}
+
+/************************************************************************/
 /*                             Polygonize()                             */
 /************************************************************************/
 /* Contributor: Alessandro Furieri, a.furieri at lqt.it                    */
@@ -4376,14 +4906,14 @@ OGRGeometryH OGR_G_SimplifyPreserveTopology( OGRGeometryH hThis, double dToleran
  * A new geometry object is created and returned containing a collection
  * of reassembled Polygons: NULL will be returned if the input collection
  * doesn't corresponds to a MultiLinestring, or when reassembling Edges
- * into Polygons is impossible due to topogical inconsistencies.
+ * into Polygons is impossible due to topological inconsistencies.
  *
  * This method is the same as the C function OGR_G_Polygonize().
  *
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this method will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this method will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @return a newly allocated geometry now owned by the caller, or NULL on failure.
  *
@@ -4395,7 +4925,7 @@ OGRGeometry *OGRGeometry::Polygonize() const
 {
 #ifndef HAVE_GEOS
 
-    CPLError( CE_Failure, CPLE_NotSupported, 
+    CPLError( CE_Failure, CPLE_NotSupported,
               "GEOS support not enabled." );
     return NULL;
 
@@ -4413,7 +4943,7 @@ OGRGeometry *OGRGeometry::Polygonize() const
     GEOSGeom *hGeosGeomList = NULL;
     GEOSGeom hGeosPolygs = NULL;
     OGRGeometry *poPolygsOGRGeom = NULL;
-    int bError = FALSE;
+    bool bError = false;
 
     GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
 
@@ -4424,17 +4954,17 @@ OGRGeometry *OGRGeometry::Polygonize() const
         OGRGeometry * poChild = (OGRGeometry*)poColl->getGeometryRef(ig);
         if( poChild == NULL ||
             wkbFlatten(poChild->getGeometryType()) != wkbLineString )
-            bError = TRUE;
+            bError = true;
         else
         {
             hGeosGeom = poChild->exportToGEOS(hGEOSCtxt);
             if( hGeosGeom == NULL)
-                bError = TRUE;
+                bError = true;
         }
         *(hGeosGeomList + ig) = hGeosGeom;
     }
 
-    if( bError == FALSE )
+    if( !bError )
     {
         hGeosPolygs = GEOSPolygonize_r( hGEOSCtxt, hGeosGeomList, iCount );
 
@@ -4470,14 +5000,14 @@ OGRGeometry *OGRGeometry::Polygonize() const
  * A new geometry object is created and returned containing a collection
  * of reassembled Polygons: NULL will be returned if the input collection
  * doesn't corresponds to a MultiLinestring, or when reassembling Edges
- * into Polygons is impossible due to topogical inconsistencies.  
+ * into Polygons is impossible due to topological inconsistencies.
  *
  * This function is the same as the C++ method OGRGeometry::Polygonize().
  *
  * This function is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this function will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this function will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @param hTarget The Geometry to be polygonized.
  *
@@ -4545,7 +5075,7 @@ int OGRHasPreparedGeometrySupport()
 /*                         OGRCreatePreparedGeometry()                  */
 /************************************************************************/
 
-OGRPreparedGeometry* OGRCreatePreparedGeometry( const OGRGeometry* poGeom )
+OGRPreparedGeometry* OGRCreatePreparedGeometry( UNUSED_IF_NO_GEOS const OGRGeometry* poGeom )
 {
 #ifdef HAVE_GEOS_PREPARED_GEOMETRY
     GEOSContextHandle_t hGEOSCtxt = OGRGeometry::createGEOSContext();
@@ -4578,7 +5108,7 @@ OGRPreparedGeometry* OGRCreatePreparedGeometry( const OGRGeometry* poGeom )
 /*                        OGRDestroyPreparedGeometry()                  */
 /************************************************************************/
 
-void OGRDestroyPreparedGeometry( OGRPreparedGeometry* poPreparedGeom )
+void OGRDestroyPreparedGeometry( UNUSED_IF_NO_GEOS OGRPreparedGeometry* poPreparedGeom )
 {
 #ifdef HAVE_GEOS_PREPARED_GEOMETRY
     if( poPreparedGeom != NULL )
@@ -4595,8 +5125,8 @@ void OGRDestroyPreparedGeometry( OGRPreparedGeometry* poPreparedGeom )
 /*                      OGRPreparedGeometryIntersects()                 */
 /************************************************************************/
 
-int OGRPreparedGeometryIntersects( const OGRPreparedGeometry* poPreparedGeom,
-                                   const OGRGeometry* poOtherGeom )
+int OGRPreparedGeometryIntersects( UNUSED_IF_NO_GEOS const OGRPreparedGeometry* poPreparedGeom,
+                                   UNUSED_IF_NO_GEOS const OGRGeometry* poOtherGeom )
 {
 #ifdef HAVE_GEOS_PREPARED_GEOMETRY
     if( poPreparedGeom == NULL || poOtherGeom == NULL )
@@ -4617,6 +5147,28 @@ int OGRPreparedGeometryIntersects( const OGRPreparedGeometry* poPreparedGeom,
 #endif
 }
 
+int OGRPreparedGeometryContains( UNUSED_IF_NO_GEOS const OGRPreparedGeometry* poPreparedGeom,
+                                 UNUSED_IF_NO_GEOS const OGRGeometry* poOtherGeom )
+{
+#ifdef HAVE_GEOS_PREPARED_GEOMETRY
+    if( poPreparedGeom == NULL || poOtherGeom == NULL )
+        return FALSE;
+
+    GEOSGeom hGEOSOtherGeom = poOtherGeom->exportToGEOS(poPreparedGeom->hGEOSCtxt);
+    if( hGEOSOtherGeom == NULL )
+        return FALSE;
+
+    int bRet = GEOSPreparedContains_r(poPreparedGeom->hGEOSCtxt,
+                                      poPreparedGeom->poPreparedGEOSGeom,
+                                      hGEOSOtherGeom);
+    GEOSGeom_destroy_r( poPreparedGeom->hGEOSCtxt, hGEOSOtherGeom );
+
+    return bRet;
+#else
+    return FALSE;
+#endif
+}
+
 /************************************************************************/
 /*                       OGRGeometryFromEWKB()                          */
 /************************************************************************/
@@ -4632,8 +5184,7 @@ OGRGeometry *OGRGeometryFromEWKB( GByte *pabyWKB, int nLength, int* pnSRID,
 
 {
     OGRGeometry *poGeometry = NULL;
-    unsigned int ewkbFlags = 0;
-    
+
     if (nLength < 5)
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -4642,23 +5193,9 @@ OGRGeometry *OGRGeometryFromEWKB( GByte *pabyWKB, int nLength, int* pnSRID,
     }
 
 /* -------------------------------------------------------------------- */
-/*      Detect XYZM variant of PostGIS EWKB                             */
-/*                                                                      */
-/*      OGR does not support parsing M coordinate,                      */
-/*      so we return NULL geometry.                                     */
+/*      Detect byte order                                               */
 /* -------------------------------------------------------------------- */
-    memcpy(&ewkbFlags, pabyWKB+1, 4);
     OGRwkbByteOrder eByteOrder = (pabyWKB[0] == 0 ? wkbXDR : wkbNDR);
-    if( OGR_SWAP( eByteOrder ) )
-        ewkbFlags= CPL_SWAP32(ewkbFlags);
-
-    if (ewkbFlags & WKBMOFFSET)
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-            "Reading EWKB with 4-dimensional coordinates (XYZM) is not supported" );
-
-        return NULL;
-    }
 
 /* -------------------------------------------------------------------- */
 /*      PostGIS EWKB format includes an  SRID, but this won't be        */
@@ -4686,8 +5223,8 @@ OGRGeometry *OGRGeometryFromEWKB( GByte *pabyWKB, int nLength, int* pnSRID,
 /* -------------------------------------------------------------------- */
 /*      Try to ingest the geometry.                                     */
 /* -------------------------------------------------------------------- */
-    OGRGeometryFactory::createFromWkb( pabyWKB, NULL, &poGeometry, nLength, 
-                                       (bIsPostGIS1_EWKB) ? wkbVariantPostGIS1 : wkbVariantOldOgc );
+    (void) OGRGeometryFactory::createFromWkb( pabyWKB, NULL, &poGeometry, nLength,
+                                              (bIsPostGIS1_EWKB) ? wkbVariantPostGIS1 : wkbVariantOldOgc );
 
     return poGeometry;
 }
@@ -4721,7 +5258,7 @@ OGRGeometry *OGRGeometryFromHexEWKB( const char *pszBytea, int* pnSRID,
 /************************************************************************/
 
 char* OGRGeometryToHexEWKB( OGRGeometry * poGeometry, int nSRSId,
-                            int bIsPostGIS1_EWKB  )
+                            int nPostGISMajor, int nPostGISMinor )
 {
     GByte       *pabyWKB;
     char        *pszTextBuf;
@@ -4731,8 +5268,18 @@ char* OGRGeometryToHexEWKB( OGRGeometry * poGeometry, int nSRSId,
     int nWkbSize = poGeometry->WkbSize();
     pabyWKB = (GByte *) CPLMalloc(nWkbSize);
 
-    if( poGeometry->exportToWkb( wkbNDR, pabyWKB,
-            bIsPostGIS1_EWKB ? wkbVariantPostGIS1 : wkbVariantOldOgc ) != OGRERR_NONE )
+    if( (nPostGISMajor > 2 || (nPostGISMajor == 2 && nPostGISMinor >= 2)) &&
+        wkbFlatten(poGeometry->getGeometryType()) == wkbPoint &&
+        poGeometry->IsEmpty() )
+    {
+        if( poGeometry->exportToWkb( wkbNDR, pabyWKB, wkbVariantIso ) != OGRERR_NONE )
+        {
+            CPLFree( pabyWKB );
+            return CPLStrdup("");
+        }
+    }
+    else if( poGeometry->exportToWkb( wkbNDR, pabyWKB,
+            (nPostGISMajor < 2) ? wkbVariantPostGIS1 : wkbVariantOldOgc ) != OGRERR_NONE )
     {
         CPLFree( pabyWKB );
         return CPLStrdup("");
@@ -4746,7 +5293,7 @@ char* OGRGeometryToHexEWKB( OGRGeometry * poGeometry, int nSRSId,
     pszTextBuf = (char *) CPLMalloc(pszSize);
     pszTextBufCurrent = pszTextBuf;
 
-    /* Convert the 1st byte, which is the endianess flag, to hex. */
+    /* Convert the 1st byte, which is the endianness flag, to hex. */
     pszHex = CPLBinaryToHex( 1, pabyWKB );
     strcpy(pszTextBufCurrent, pszHex );
     CPLFree ( pszHex );
@@ -4759,7 +5306,7 @@ char* OGRGeometryToHexEWKB( OGRGeometry * poGeometry, int nSRSId,
     /* Now add the SRID flag if an SRID is provided */
     if (nSRSId > 0)
     {
-        /* Change the flag to wkbNDR (little) endianess */
+        /* Change the flag to wkbNDR (little) endianness */
         GUInt32 nGSrsFlag = CPL_LSBWORD32( WKBSRIDFLAG );
         /* Apply the flag */
         geomType = geomType | nGSrsFlag;
@@ -4774,7 +5321,7 @@ char* OGRGeometryToHexEWKB( OGRGeometry * poGeometry, int nSRSId,
     /* Now include SRID if provided */
     if (nSRSId > 0)
     {
-        /* Force the srsid to wkbNDR (little) endianess */
+        /* Force the srsid to wkbNDR (little) endianness */
         GUInt32 nGSRSId = CPL_LSBWORD32( nSRSId );
         pszHex = CPLBinaryToHex( sizeof(nGSRSId),(GByte*) &nGSRSId );
         strcpy(pszTextBufCurrent, pszHex );
@@ -4799,10 +5346,10 @@ char* OGRGeometryToHexEWKB( OGRGeometry * poGeometry, int nSRSId,
  * \brief Add intermediate vertices to a geometry.
  *
  * This method modifies the geometry to add intermediate vertices if necessary
- * so that the maximum length between 2 consecutives vertices is lower than
+ * so that the maximum length between 2 consecutive vertices is lower than
  * dfMaxLength.
  *
- * @param dfMaxLength maximum length between 2 consecutives vertices.
+ * @param dfMaxLength maximum length between 2 consecutive vertices.
  */
 
 
@@ -4813,7 +5360,6 @@ char* OGRGeometryToHexEWKB( OGRGeometry * poGeometry, int nSRSId,
 OGRErr OGRGeometry::importPreambuleFromWkb( unsigned char * pabyData,
                                             int nSize,
                                             OGRwkbByteOrder& eByteOrder,
-                                            OGRBoolean& b3D,
                                             OGRwkbVariant eWkbVariant )
 {
     if( nSize < 9 && nSize != -1 )
@@ -4822,20 +5368,25 @@ OGRErr OGRGeometry::importPreambuleFromWkb( unsigned char * pabyData,
 /* -------------------------------------------------------------------- */
 /*      Get the byte order byte.                                        */
 /* -------------------------------------------------------------------- */
-    eByteOrder = DB2_V72_FIX_BYTE_ORDER((OGRwkbByteOrder) *pabyData);
-    if (!( eByteOrder == wkbXDR || eByteOrder == wkbNDR ))
+    int nByteOrder = DB2_V72_FIX_BYTE_ORDER(*pabyData);
+    if (!( nByteOrder == wkbXDR || nByteOrder == wkbNDR ))
         return OGRERR_CORRUPT_DATA;
+    eByteOrder = (OGRwkbByteOrder) nByteOrder;
 
 /* -------------------------------------------------------------------- */
 /*      Get the geometry feature type.                                  */
 /* -------------------------------------------------------------------- */
     OGRwkbGeometryType eGeometryType;
-    OGRErr err = OGRReadWKBGeometryType( pabyData, eWkbVariant, &eGeometryType, &b3D );
+    OGRErr err = OGRReadWKBGeometryType( pabyData, eWkbVariant, &eGeometryType );
+    if( wkbHasZ(eGeometryType) )
+        flags |= OGR_G_3D;
+    if( wkbHasM(eGeometryType) )
+        flags |= OGR_G_MEASURED;
 
-    if( err != OGRERR_NONE || eGeometryType != wkbFlatten(getGeometryType()) )
+    if( err != OGRERR_NONE || eGeometryType != getGeometryType() )
         return OGRERR_CORRUPT_DATA;
 
-    return -1;
+    return OGRERR_NONE;
 }
 
 /************************************************************************/
@@ -4854,25 +5405,28 @@ OGRErr OGRGeometry::importPreambuleOfCollectionFromWkb( unsigned char * pabyData
                                                         OGRwkbVariant eWkbVariant )
 {
     nGeomCount = 0;
-    OGRBoolean b3D = FALSE;
 
-    OGRErr eErr = importPreambuleFromWkb( pabyData, nSize, eByteOrder, b3D, eWkbVariant );
-    if( eErr >= 0 )
+    OGRErr eErr = importPreambuleFromWkb( pabyData, nSize, eByteOrder, eWkbVariant );
+    if( eErr != OGRERR_NONE )
         return eErr;
 
 /* -------------------------------------------------------------------- */
 /*      Clear existing Geoms.                                           */
 /* -------------------------------------------------------------------- */
-    empty();
+    int _flags = flags; // flags set in importPreambuleFromWkb
+    empty(); // may reset flags etc.
 
-    if( b3D )
-        setCoordinateDimension(3);
+    // restore
+    if( _flags & OGR_G_3D )
+        set3D(TRUE);
+    if( _flags & OGR_G_MEASURED )
+        setMeasured(TRUE);
 
 /* -------------------------------------------------------------------- */
 /*      Get the sub-geometry count.                                     */
 /* -------------------------------------------------------------------- */
     memcpy( &nGeomCount, pabyData + 5, 4 );
-    
+
     if( OGR_SWAP( eByteOrder ) )
         nGeomCount = CPL_SWAP32(nGeomCount);
 
@@ -4895,7 +5449,7 @@ OGRErr OGRGeometry::importPreambuleOfCollectionFromWkb( unsigned char * pabyData
     if( nSize != -1 )
         nSize -= nDataOffset;
 
-    return -1;
+    return OGRERR_NONE;
 }
 
 /************************************************************************/
@@ -4914,12 +5468,15 @@ OGRErr OGRGeometry::importCurveCollectionFromWkt( char ** ppszInput,
 
 {
     int bHasZ = FALSE, bHasM = FALSE;
-    OGRErr      eErr = importPreambuleFromWkt(ppszInput, &bHasZ, &bHasM);
-    if( eErr >= 0 )
+    bool bIsEmpty = false;
+    OGRErr      eErr = importPreambuleFromWkt(ppszInput, &bHasZ, &bHasM, &bIsEmpty);
+    flags = 0;
+    if( eErr != OGRERR_NONE )
         return eErr;
-
-    if( bHasZ )
-        setCoordinateDimension(3);
+    if( bHasZ ) flags |= OGR_G_3D;
+    if( bHasM ) flags |= OGR_G_MEASURED;
+    if( bIsEmpty )
+        return OGRERR_NONE;
 
     char        szToken[OGR_WKT_TOKEN_MAX];
     const char  *pszInput = *ppszInput;
@@ -4981,6 +5538,10 @@ OGRErr OGRGeometry::importCurveCollectionFromWkt( char ** ppszInput,
             eErr = OGRERR_CORRUPT_DATA;
         }
 
+        /* if this has M it is an error if poGeom does not have M */
+        if( poCurve && !Is3D() && IsMeasured() && !poCurve->IsMeasured() )
+            eErr = OGRERR_CORRUPT_DATA;
+
         if( eErr == OGRERR_NONE )
             eErr = pfnAddCurveDirectly( this, poCurve );
         if( eErr != OGRERR_NONE )
@@ -4990,7 +5551,7 @@ OGRErr OGRGeometry::importCurveCollectionFromWkt( char ** ppszInput,
         }
 
 /* -------------------------------------------------------------------- */
-/*      Read the delimeter following the surface.                       */
+/*      Read the delimiter following the surface.                       */
 /* -------------------------------------------------------------------- */
         pszInput = OGRWktReadToken( pszInput, szToken );
 
@@ -5008,7 +5569,7 @@ OGRErr OGRGeometry::importCurveCollectionFromWkt( char ** ppszInput,
 
     if( szToken[0] != ')' )
         return OGRERR_CORRUPT_DATA;
-    
+
     *ppszInput = (char *) pszInput;
     return OGRERR_NONE;
 }
@@ -5033,7 +5594,7 @@ OGRErr OGRGeometry::importCurveCollectionFromWkt( char ** ppszInput,
 OGRwkbGeometryType OGR_GT_Flatten( OGRwkbGeometryType eType )
 {
     eType = (OGRwkbGeometryType) (eType & (~wkb25DBitInternalUse));
-    if( eType >= 1001 && eType < 2000 ) /* ISO Z */
+    if( eType >= 1000 && eType < 2000 ) /* ISO Z */
         return (OGRwkbGeometryType) (eType - 1000);
     if( eType >= 2000 && eType < 3000 ) /* ISO M */
         return (OGRwkbGeometryType) (eType - 2000);
@@ -5059,7 +5620,31 @@ int OGR_GT_HasZ( OGRwkbGeometryType eType )
 {
     if( eType & wkb25DBitInternalUse )
         return TRUE;
-    if( eType >= 1001 && eType < 2000 )
+    if( eType >= 1000 && eType < 2000 ) /* we accept 1000 for wkbUnknownZ */
+        return TRUE;
+    if( eType >= 3000 && eType < 4000 ) /* we accept 3000 for wkbUnknownZM */
+        return TRUE;
+    return FALSE;
+}
+
+/************************************************************************/
+/*                          OGR_GT_HasM()                               */
+/************************************************************************/
+/**
+ * \brief Return if the geometry type is a measured type.
+ *
+ * @param eType Input geometry type
+ *
+ * @return TRUE if the geometry type is a measured type.
+ *
+ * @since GDAL 2.1
+ */
+
+int OGR_GT_HasM( OGRwkbGeometryType eType )
+{
+    if( eType >= 2000 && eType < 3000 ) /* we accept 2000 for wkbUnknownM */
+        return TRUE;
+    if( eType >= 3000 && eType < 4000 ) /* we accept 3000 for wkbUnknownZM */
         return TRUE;
     return FALSE;
 }
@@ -5081,21 +5666,46 @@ OGRwkbGeometryType OGR_GT_SetZ( OGRwkbGeometryType eType )
 {
     if( OGR_GT_HasZ(eType) || eType == wkbNone )
         return eType;
-    if( eType >= wkbUnknown && eType <= wkbGeometryCollection )
+    if( eType <= wkbGeometryCollection )
         return (OGRwkbGeometryType)(eType | wkb25DBitInternalUse);
     else
         return (OGRwkbGeometryType)(eType + 1000);
 }
 
 /************************************************************************/
+/*                           OGR_GT_SetM()                              */
+/************************************************************************/
+/**
+ * \brief Returns the measured geometry type corresponding to the passed geometry type.
+ *
+ * @param eType Input geometry type
+ *
+ * @return measured geometry type corresponding to the passed geometry type.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRwkbGeometryType OGR_GT_SetM( OGRwkbGeometryType eType )
+{
+    if( OGR_GT_HasM(eType) || eType == wkbNone )
+        return eType;
+    if( eType & wkb25DBitInternalUse)
+    {
+        eType = (OGRwkbGeometryType)(eType & ~wkb25DBitInternalUse);
+        eType = (OGRwkbGeometryType)(eType + 1000);
+    }
+    return (OGRwkbGeometryType)(eType + 2000);
+}
+
+/************************************************************************/
 /*                        OGR_GT_SetModifier()                          */
 /************************************************************************/
 /**
- * \brief Returns a 2D or 3D geometry type depending on parameter.
+ * \brief Returns a XY, XYZ, XYM or XYZM geometry type depending on parameter.
  *
  * @param eType Input geometry type
  * @param bHasZ TRUE if the output geometry type must be 3D.
- * @param bHasM Must be set to FALSE currently.
+ * @param bHasM TRUE if the output geometry type must be measured.
  *
  * @return Output geometry type.
  *
@@ -5103,10 +5713,14 @@ OGRwkbGeometryType OGR_GT_SetZ( OGRwkbGeometryType eType )
  */
 
 OGRwkbGeometryType OGR_GT_SetModifier( OGRwkbGeometryType eType, int bHasZ,
-                                       CPL_UNUSED int bHasM )
-{
-    if( bHasZ )
-        return OGR_GT_SetZ(eType);
+                                       int bHasM )
+{
+    if( bHasZ && bHasM )
+        return OGR_GT_SetM(OGR_GT_SetZ(eType));
+    else if( bHasM )
+        return OGR_GT_SetM(wkbFlatten(eType));
+    else if( bHasZ )
+        return OGR_GT_SetZ(wkbFlatten(eType));
     else
         return wkbFlatten(eType);
 }
@@ -5170,7 +5784,8 @@ int OGR_GT_IsSubClassOf( OGRwkbGeometryType eType,
  * wkbCurvePolygon->wkbMultiSurface.
  * In other cases, wkbUnknown is returned
  *
- * Passed Z flag is preserved.
+ * Passed Z, M, ZM flag is preserved.
+ *
  *
  * @param eType Input geometry type
  *
@@ -5181,6 +5796,8 @@ int OGR_GT_IsSubClassOf( OGRwkbGeometryType eType,
 
 OGRwkbGeometryType OGR_GT_GetCollection( OGRwkbGeometryType eType )
 {
+    const bool bHasZ = wkbHasZ(eType);
+    const bool bHasM = wkbHasM(eType);
     if( eType == wkbNone )
         return wkbNone;
     OGRwkbGeometryType eFGType = wkbFlatten(eType);
@@ -5198,12 +5815,14 @@ OGRwkbGeometryType OGR_GT_GetCollection( OGRwkbGeometryType eType )
 
     else if( OGR_GT_IsSurface(eFGType) )
         eType = wkbMultiSurface;
-    
+
     else
         return wkbUnknown;
 
-    if( wkbHasZ(eType) )
+    if( bHasZ )
         eType = wkbSetZ(eType);
+    if( bHasM )
+        eType = wkbSetM(eType);
 
     return eType;
 }
@@ -5219,7 +5838,7 @@ OGRwkbGeometryType OGR_GT_GetCollection( OGRwkbGeometryType eType )
  * and wkbMultiLineString->wkbMultiCurve.
  * In other cases, the passed geometry is returned.
  *
- * Passed Z flag is preserved.
+ * Passed Z, M, ZM flag is preserved.
  *
  * @param eType Input geometry type
  *
@@ -5230,6 +5849,8 @@ OGRwkbGeometryType OGR_GT_GetCollection( OGRwkbGeometryType eType )
 
 OGRwkbGeometryType OGR_GT_GetCurve( OGRwkbGeometryType eType )
 {
+    const bool bHasZ = wkbHasZ(eType);
+    const bool bHasM = wkbHasM(eType);
     OGRwkbGeometryType eFGType = wkbFlatten(eType);
 
     if( eFGType == wkbLineString )
@@ -5244,8 +5865,10 @@ OGRwkbGeometryType OGR_GT_GetCurve( OGRwkbGeometryType eType )
     else if( eFGType == wkbMultiPolygon )
         eType = wkbMultiSurface;
 
-    if( wkbHasZ(eType) )
+    if( bHasZ )
         eType = wkbSetZ(eType);
+    if( bHasM )
+        eType = wkbSetM(eType);
 
     return eType;
 }
@@ -5261,7 +5884,7 @@ OGRwkbGeometryType OGR_GT_GetCurve( OGRwkbGeometryType eType )
  * wkbMultiSurface->wkbMultiPolygon and wkbMultiCurve->wkbMultiLineString.
  * In other cases, the passed geometry is returned.
  *
- * Passed Z flag is preserved.
+ * Passed Z, M, ZM flag is preserved.
  *
  * @param eType Input geometry type
  *
@@ -5272,6 +5895,8 @@ OGRwkbGeometryType OGR_GT_GetCurve( OGRwkbGeometryType eType )
 
 OGRwkbGeometryType OGR_GT_GetLinear( OGRwkbGeometryType eType )
 {
+    const bool bHasZ = wkbHasZ(eType);
+    const bool bHasM = wkbHasM(eType);
     OGRwkbGeometryType eFGType = wkbFlatten(eType);
 
     if( OGR_GT_IsCurve(eFGType) )
@@ -5286,8 +5911,10 @@ OGRwkbGeometryType OGR_GT_GetLinear( OGRwkbGeometryType eType )
     else if( eFGType == wkbMultiSurface )
         eType = wkbMultiPolygon;
 
-    if( wkbHasZ(eType) )
+    if( bHasZ )
         eType = wkbSetZ(eType);
+    if( bHasM )
+        eType = wkbSetM(eType);
 
     return eType;
 }
@@ -5300,7 +5927,7 @@ OGRwkbGeometryType OGR_GT_GetLinear( OGRwkbGeometryType eType )
  * \brief Return if a geometry type is an instance of Curve
  *
  * Such geometry type are wkbLineString, wkbCircularString, wkbCompoundCurve
- * and their 3D variant.
+ * and their Z/M/ZM variant.
  *
  * @param eGeomType the geometry type
  * @return TRUE if the geometry type is an instance of Curve
@@ -5321,7 +5948,7 @@ int OGR_GT_IsCurve( OGRwkbGeometryType eGeomType )
  * \brief Return if a geometry type is an instance of Surface
  *
  * Such geometry type are wkbCurvePolygon and wkbPolygon
- * and their 3D variant.
+ * and their Z/M/ZM variant.
  *
  * @param eGeomType the geometry type
  * @return TRUE if the geometry type is an instance of Surface
diff --git a/ogr/ogrgeometrycollection.cpp b/ogr/ogrgeometrycollection.cpp
index 0ef02ae..420d37b 100644
--- a/ogr/ogrgeometrycollection.cpp
+++ b/ogr/ogrgeometrycollection.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeometrycollection.cpp 33153 2016-01-25 12:45:47Z rouault $
+ * $Id: ogrgeometrycollection.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRGeometryCollection class.
@@ -32,7 +32,7 @@
 #include "ogr_p.h"
 #include "ogr_api.h"
 
-CPL_CVSID("$Id: ogrgeometrycollection.cpp 33153 2016-01-25 12:45:47Z rouault $");
+CPL_CVSID("$Id: ogrgeometrycollection.cpp 33631 2016-03-04 06:28:09Z goatbar $");
 
 /************************************************************************/
 /*                       OGRGeometryCollection()                        */
@@ -50,6 +50,30 @@ OGRGeometryCollection::OGRGeometryCollection()
 }
 
 /************************************************************************/
+/*         OGRGeometryCollection( const OGRGeometryCollection& )        */
+/************************************************************************/
+
+/**
+ * \brief Copy constructor.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the constructor
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRGeometryCollection::OGRGeometryCollection( const OGRGeometryCollection& other ) :
+    OGRGeometry( other ),
+    nGeomCount( 0 ),
+    papoGeoms( NULL )
+{
+    for( int i = 0; i < other.nGeomCount; i++ )
+    {
+        addGeometry( other.papoGeoms[i] );
+    }
+}
+
+/************************************************************************/
 /*                       ~OGRGeometryCollection()                       */
 /************************************************************************/
 
@@ -60,6 +84,35 @@ OGRGeometryCollection::~OGRGeometryCollection()
 }
 
 /************************************************************************/
+/*               operator=( const OGRGeometryCollection&)               */
+/************************************************************************/
+
+/**
+ * \brief Assignment operator.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the operator
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRGeometryCollection& OGRGeometryCollection::operator=( const OGRGeometryCollection& other )
+{
+    if( this != &other)
+    {
+        empty();
+
+        OGRGeometry::operator=( other );
+
+        for( int i = 0; i < other.nGeomCount; i++ )
+        {
+            addGeometry( other.papoGeoms[i] );
+        }
+    }
+    return *this;
+}
+
+/************************************************************************/
 /*                               empty()                                */
 /************************************************************************/
 
@@ -77,7 +130,6 @@ void OGRGeometryCollection::empty()
 
     nGeomCount = 0;
     papoGeoms = NULL;
-    nCoordDimension = 2;
 }
 
 /************************************************************************/
@@ -91,11 +143,18 @@ OGRGeometry *OGRGeometryCollection::clone() const
 
     poNewGC = (OGRGeometryCollection*)
             OGRGeometryFactory::createGeometry(getGeometryType());
+    if( poNewGC == NULL )
+        return NULL;
     poNewGC->assignSpatialReference( getSpatialReference() );
+    poNewGC->flags = flags;
 
     for( int i = 0; i < nGeomCount; i++ )
     {
-        poNewGC->addGeometry( papoGeoms[i] );
+        if( poNewGC->addGeometry( papoGeoms[i] ) != OGRERR_NONE )
+        {
+            delete poNewGC;
+            return NULL;
+        }
     }
 
     return poNewGC;
@@ -108,7 +167,11 @@ OGRGeometry *OGRGeometryCollection::clone() const
 OGRwkbGeometryType OGRGeometryCollection::getGeometryType() const
 
 {
-    if( getCoordinateDimension() == 3 )
+    if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
+        return wkbGeometryCollectionZM;
+    else if( flags & OGR_G_MEASURED )
+        return wkbGeometryCollectionM;
+    else if( flags & OGR_G_3D )
         return wkbGeometryCollection25D;
     else
         return wkbGeometryCollection;
@@ -147,7 +210,8 @@ void OGRGeometryCollection::flattenTo2D()
     for( int i = 0; i < nGeomCount; i++ )
         papoGeoms[i]->flattenTo2D();
 
-    nCoordDimension = 2;
+    flags &= ~OGR_G_3D;
+    flags &= ~OGR_G_MEASURED;
 }
 
 /************************************************************************/
@@ -188,7 +252,7 @@ int OGRGeometryCollection::getNumGeometries() const
  *
  * This method returns a pointer to an geometry within the container.  The
  * returned geometry remains owned by the container, and should not be
- * modified.  The pointer is only valid untill the next change to the
+ * modified.  The pointer is only valid until the next change to the
  * geometry container.  Use IGeometry::clone() to make a copy.
  *
  * This method relates to the SFCOM IGeometryCollection::get_Geometry() method.
@@ -198,7 +262,7 @@ int OGRGeometryCollection::getNumGeometries() const
  * @return pointer to requested geometry.
  */
 
-OGRGeometry * OGRGeometryCollection::getGeometryRef( int i ) 
+OGRGeometry * OGRGeometryCollection::getGeometryRef( int i )
 
 {
     if( i < 0 || i >= nGeomCount )
@@ -247,6 +311,8 @@ OGRErr OGRGeometryCollection::addGeometry( const OGRGeometry * poNewGeom )
     OGRGeometry *poClone = poNewGeom->clone();
     OGRErr      eErr;
 
+    if( poClone == NULL )
+        return OGRERR_FAILURE;
     eErr = addGeometryDirectly( poClone );
     if( eErr != OGRERR_NONE )
         delete poClone;
@@ -286,13 +352,27 @@ OGRErr OGRGeometryCollection::addGeometryDirectly( OGRGeometry * poNewGeom )
     if( !isCompatibleSubType(poNewGeom->getGeometryType()) )
         return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
 
-    if( poNewGeom->getCoordinateDimension() == 3 && getCoordinateDimension() != 3 )
-        setCoordinateDimension(3);
-    else if( poNewGeom->getCoordinateDimension() != 3 && getCoordinateDimension() == 3 )
-        poNewGeom->setCoordinateDimension(3);
+    if( poNewGeom->Is3D() && !Is3D() )
+
+        set3D(TRUE);
+
+    if( poNewGeom->IsMeasured() && !IsMeasured() )
+
+        setMeasured(TRUE);
 
-    papoGeoms = (OGRGeometry **) OGRRealloc( papoGeoms,
+    if( !poNewGeom->Is3D() && Is3D() )
+
+        poNewGeom->set3D(TRUE);
+
+    if( !poNewGeom->IsMeasured() && IsMeasured() )
+
+        poNewGeom->setMeasured(TRUE);
+
+    OGRGeometry** papoNewGeoms = (OGRGeometry **) VSI_REALLOC_VERBOSE( papoGeoms,
                                              sizeof(void*) * (nGeomCount+1) );
+    if( papoNewGeoms == NULL )
+        return OGRERR_FAILURE;
+    papoGeoms = papoNewGeoms;
 
     papoGeoms[nGeomCount] = poNewGeom;
 
@@ -320,7 +400,7 @@ OGRErr OGRGeometryCollection::addGeometryDirectly( OGRGeometry * poNewGeom )
  *
  * @param bDelete if TRUE the geometry will be deallocated, otherwise it will
  * not.  The default is TRUE as the container is considered to own the
- * geometries in it. 
+ * geometries in it.
  *
  * @return OGRERR_NONE if successful, or OGRERR_FAILURE if the index is
  * out of range.
@@ -343,7 +423,7 @@ OGRErr OGRGeometryCollection::removeGeometry( int iGeom, int bDelete )
     if( bDelete )
         delete papoGeoms[iGeom];
 
-    memmove( papoGeoms + iGeom, papoGeoms + iGeom + 1, 
+    memmove( papoGeoms + iGeom, papoGeoms + iGeom + 1,
              sizeof(void*) * (nGeomCount-iGeom-1) );
 
     nGeomCount--;
@@ -380,19 +460,18 @@ OGRErr OGRGeometryCollection::importFromWkbInternal( unsigned char * pabyData,
                                                      OGRwkbVariant eWkbVariant )
 
 {
-    OGRwkbByteOrder     eByteOrder;
-    int                 nDataOffset;
-
-    /* Arbitrary value, but certainly large enough for reasonable usages ! */
+    /* Arbitrary value, but certainly large enough for reasonable use cases. */
     if( nRecLevel == 32 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                    "Too many recursiong level (%d) while parsing WKB geometry.",
-                    nRecLevel );
+                  "Too many recursion levels (%d) while parsing WKB geometry.",
+                  nRecLevel );
         return OGRERR_CORRUPT_DATA;
     }
 
     nGeomCount = 0;
+    OGRwkbByteOrder eByteOrder = wkbXDR;
+    int nDataOffset = 0;
     OGRErr eErr = importPreambuleOfCollectionFromWkb( pabyData,
                                                       nSize,
                                                       nDataOffset,
@@ -400,10 +479,12 @@ OGRErr OGRGeometryCollection::importFromWkbInternal( unsigned char * pabyData,
                                                       9,
                                                       nGeomCount,
                                                       eWkbVariant );
-    if( eErr >= 0 )
+
+    if( eErr != OGRERR_NONE )
         return eErr;
 
-    papoGeoms = (OGRGeometry **) VSIMalloc2(sizeof(void*), nGeomCount);
+    /* coverity[tainted_data] */
+    papoGeoms = (OGRGeometry **) VSI_CALLOC_VERBOSE(sizeof(void*), nGeomCount);
     if (nGeomCount != 0 && papoGeoms == NULL)
     {
         nGeomCount = 0;
@@ -415,17 +496,13 @@ OGRErr OGRGeometryCollection::importFromWkbInternal( unsigned char * pabyData,
 /* -------------------------------------------------------------------- */
     for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
     {
-        OGRErr  eErr;
-        OGRGeometry* poSubGeom = NULL;
-
         /* Parses sub-geometry */
         unsigned char* pabySubData = pabyData + nDataOffset;
         if( nSize < 9 && nSize != -1 )
             return OGRERR_NOT_ENOUGH_DATA;
 
         OGRwkbGeometryType eSubGeomType;
-        OGRBoolean bIs3D;
-        eErr = OGRReadWKBGeometryType( pabySubData, eWkbVariant, &eSubGeomType, &bIs3D );
+        eErr = OGRReadWKBGeometryType( pabySubData, eWkbVariant, &eSubGeomType );
         if( eErr != OGRERR_NONE )
             return eErr;
 
@@ -437,10 +514,14 @@ OGRErr OGRGeometryCollection::importFromWkbInternal( unsigned char * pabyData,
             return OGRERR_CORRUPT_DATA;
         }
 
+        OGRGeometry* poSubGeom = NULL;
         if( OGR_GT_IsSubClassOf(eSubGeomType, wkbGeometryCollection) )
         {
             poSubGeom = OGRGeometryFactory::createGeometry( eSubGeomType );
-            eErr = ((OGRGeometryCollection*)poSubGeom)->
+            if( poSubGeom == NULL )
+                eErr = OGRERR_FAILURE;
+            else
+                eErr = ((OGRGeometryCollection*)poSubGeom)->
                         importFromWkbInternal( pabySubData, nSize, nRecLevel + 1, eWkbVariant );
         }
         else
@@ -459,8 +540,10 @@ OGRErr OGRGeometryCollection::importFromWkbInternal( unsigned char * pabyData,
 
         papoGeoms[iGeom] = poSubGeom;
 
-        if (papoGeoms[iGeom]->getCoordinateDimension() == 3)
-            nCoordDimension = 3;
+        if (papoGeoms[iGeom]->Is3D())
+            flags |= OGR_G_3D;
+        if (papoGeoms[iGeom]->IsMeasured())
+            flags |= OGR_G_MEASURED;
 
         int nSubGeomWkbSize = papoGeoms[iGeom]->WkbSize();
         if( nSize != -1 )
@@ -498,8 +581,6 @@ OGRErr  OGRGeometryCollection::exportToWkb( OGRwkbByteOrder eByteOrder,
                                             OGRwkbVariant eWkbVariant ) const
 
 {
-    int         nOffset;
-    
     if( eWkbVariant == wkbVariantOldOgc &&
         (wkbFlatten(getGeometryType()) == wkbMultiCurve ||
          wkbFlatten(getGeometryType()) == wkbMultiSurface) ) /* does not make sense for new geometries, so patch it */
@@ -517,7 +598,7 @@ OGRErr  OGRGeometryCollection::exportToWkb( OGRwkbByteOrder eByteOrder,
 /*      preserved.                                                      */
 /* -------------------------------------------------------------------- */
     GUInt32 nGType = getGeometryType();
-    
+
     if ( eWkbVariant == wkbVariantIso )
         nGType = getIsoGeometryType();
     else if( eWkbVariant == wkbVariantPostGIS1 )
@@ -531,31 +612,29 @@ OGRErr  OGRGeometryCollection::exportToWkb( OGRwkbByteOrder eByteOrder,
         if( bIs3D )
             nGType = (OGRwkbGeometryType)(nGType | wkb25DBitInternalUse); /* yes we explicitly set wkb25DBit */
     }
-    
+
     if( eByteOrder == wkbNDR )
         nGType = CPL_LSBWORD32( nGType );
     else
         nGType = CPL_MSBWORD32( nGType );
 
     memcpy( pabyData + 1, &nGType, 4 );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Copy in the raw data.                                           */
 /* -------------------------------------------------------------------- */
     if( OGR_SWAP( eByteOrder ) )
     {
-        int     nCount;
-
-        nCount = CPL_SWAP32( nGeomCount );
+        int nCount = CPL_SWAP32( nGeomCount );
         memcpy( pabyData+5, &nCount, 4 );
     }
     else
     {
         memcpy( pabyData+5, &nGeomCount, 4 );
     }
-    
-    nOffset = 9;
-    
+
+    int nOffset = 9;
+
 /* ==================================================================== */
 /*      Serialize each of the Geoms.                                    */
 /* ==================================================================== */
@@ -575,7 +654,7 @@ OGRErr  OGRGeometryCollection::exportToWkb( OGRwkbByteOrder eByteOrder,
 
         nOffset += papoGeoms[iGeom]->WkbSize();
     }
-    
+
     return OGRERR_NONE;
 }
 
@@ -590,15 +669,20 @@ OGRErr OGRGeometryCollection::importFromWktInternal( char ** ppszInput, int nRec
     if( nRecLevel == 32 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                    "Too many recursiong level (%d) while parsing WKT geometry.",
-                    nRecLevel );
+                  "Too many recursion levels (%d) while parsing WKT geometry.",
+                  nRecLevel );
         return OGRERR_CORRUPT_DATA;
     }
 
     int bHasZ = FALSE, bHasM = FALSE;
-    OGRErr      eErr = importPreambuleFromWkt(ppszInput, &bHasZ, &bHasM);
-    if( eErr >= 0 )
+    bool bIsEmpty = false;
+    OGRErr      eErr = importPreambuleFromWkt(ppszInput, &bHasZ, &bHasM, &bIsEmpty);
+    if( eErr != OGRERR_NONE )
         return eErr;
+    if( bHasZ ) flags |= OGR_G_3D;
+    if( bHasM ) flags |= OGR_G_MEASURED;
+    if( bIsEmpty )
+        return OGRERR_NONE;
 
     char        szToken[OGR_WKT_TOKEN_MAX];
     const char  *pszInput = *ppszInput;
@@ -612,7 +696,6 @@ OGRErr OGRGeometryCollection::importFromWktInternal( char ** ppszInput, int nRec
     do
     {
         OGRGeometry *poGeom = NULL;
-        OGRErr      eErr;
 
     /* -------------------------------------------------------------------- */
     /*      Get the first token, which should be the geometry type.         */
@@ -633,7 +716,13 @@ OGRErr OGRGeometryCollection::importFromWktInternal( char ** ppszInput, int nRec
                                                        NULL, &poGeom );
 
         if( eErr == OGRERR_NONE )
-            eErr = addGeometryDirectly( poGeom );
+        {
+            /* if this has M but not Z it is an error if poGeom does not have M */
+            if( !Is3D() && IsMeasured() && !poGeom->IsMeasured() )
+                eErr = OGRERR_CORRUPT_DATA;
+            else
+                eErr = addGeometryDirectly( poGeom );
+        }
         if( eErr != OGRERR_NONE )
         {
             delete poGeom;
@@ -641,11 +730,11 @@ OGRErr OGRGeometryCollection::importFromWktInternal( char ** ppszInput, int nRec
         }
 
 /* -------------------------------------------------------------------- */
-/*      Read the delimeter following the ring.                          */
+/*      Read the delimiter following the ring.                          */
 /* -------------------------------------------------------------------- */
-        
+
         pszInput = OGRWktReadToken( pszInput, szToken );
-        
+
     } while( szToken[0] == ',' );
 
 /* -------------------------------------------------------------------- */
@@ -653,9 +742,9 @@ OGRErr OGRGeometryCollection::importFromWktInternal( char ** ppszInput, int nRec
 /* -------------------------------------------------------------------- */
     if( szToken[0] != ')' )
         return OGRERR_CORRUPT_DATA;
-    
+
     *ppszInput = (char *) pszInput;
-    
+
     return OGRERR_NONE;
 }
 
@@ -673,7 +762,7 @@ OGRErr OGRGeometryCollection::importFromWkt( char ** ppszInput )
 /*                            exportToWkt()                             */
 /*                                                                      */
 /*      Translate this structure into it's well known text format       */
-/*      equivelent.  This could be made alot more CPU efficient!        */
+/*      equivalent.  This could be made a lot more CPU efficient!        */
 /************************************************************************/
 
 OGRErr OGRGeometryCollection::exportToWkt( char ** ppszDstText,
@@ -688,9 +777,10 @@ OGRErr OGRGeometryCollection::exportToWktInternal( char ** ppszDstText,
 
 {
     char        **papszGeoms;
-    int         iGeom, nCumulativeLength = 0;
+    int         iGeom;
+    size_t      nCumulativeLength = 0;
     OGRErr      eErr;
-    int bMustWriteComma = FALSE;
+    bool bMustWriteComma = false;
 
 /* -------------------------------------------------------------------- */
 /*      Build a list of strings containing the stuff for each Geom.     */
@@ -703,25 +793,35 @@ OGRErr OGRGeometryCollection::exportToWktInternal( char ** ppszDstText,
         if( eErr != OGRERR_NONE )
             goto error;
 
-        int nSkip = 0;
+        size_t nSkip = 0;
         if( pszSkipPrefix != NULL &&
             EQUALN(papszGeoms[iGeom], pszSkipPrefix, strlen(pszSkipPrefix)) &&
             papszGeoms[iGeom][strlen(pszSkipPrefix)] == ' ' )
         {
             nSkip = strlen(pszSkipPrefix) + 1;
-            if( EQUALN(papszGeoms[iGeom] + nSkip, "Z ", 2) )
+            if( STARTS_WITH_CI(papszGeoms[iGeom] + nSkip, "ZM ") )
+                nSkip += 3;
+            else if( STARTS_WITH_CI(papszGeoms[iGeom] + nSkip, "M ") )
+                nSkip += 2;
+            if( STARTS_WITH_CI(papszGeoms[iGeom] + nSkip, "Z ") )
                 nSkip += 2;
 
             /* skip empty subgeoms */
             if( papszGeoms[iGeom][nSkip] != '(' )
             {
                 CPLDebug( "OGR", "OGRGeometryCollection::exportToWkt() - skipping %s.",
-                         papszGeoms[iGeom] );
+                          papszGeoms[iGeom] );
                 CPLFree( papszGeoms[iGeom] );
                 papszGeoms[iGeom] = NULL;
                 continue;
             }
         }
+        else if( eWkbVariant != wkbVariantIso )
+        {
+            char *substr;
+            if( (substr = strstr(papszGeoms[iGeom], " Z")) != NULL )
+                memmove(substr, substr+strlen(" Z"), 1+strlen(substr+strlen(" Z")));
+        }
 
         nCumulativeLength += strlen(papszGeoms[iGeom] + nSkip);
     }
@@ -733,8 +833,17 @@ OGRErr OGRGeometryCollection::exportToWktInternal( char ** ppszDstText,
     {
         CPLFree( papszGeoms );
         CPLString osEmpty;
-        if( getCoordinateDimension() == 3 && eWkbVariant == wkbVariantIso )
-            osEmpty.Printf("%s Z EMPTY",getGeometryName());
+        if( eWkbVariant == wkbVariantIso )
+        {
+            if( Is3D() && IsMeasured() )
+                osEmpty.Printf("%s ZM EMPTY",getGeometryName());
+            else if( IsMeasured() )
+                osEmpty.Printf("%s M EMPTY",getGeometryName());
+            else if( Is3D() )
+                osEmpty.Printf("%s Z EMPTY",getGeometryName());
+            else
+                osEmpty.Printf("%s EMPTY",getGeometryName());
+        }
         else
             osEmpty.Printf("%s EMPTY",getGeometryName());
         *ppszDstText = CPLStrdup(osEmpty);
@@ -744,7 +853,7 @@ OGRErr OGRGeometryCollection::exportToWktInternal( char ** ppszDstText,
 /* -------------------------------------------------------------------- */
 /*      Allocate the right amount of space for the aggregated string    */
 /* -------------------------------------------------------------------- */
-    *ppszDstText = (char *) VSIMalloc(nCumulativeLength + nGeomCount + 25);
+    *ppszDstText = (char *) VSI_MALLOC_VERBOSE(nCumulativeLength + nGeomCount + 26);
 
     if( *ppszDstText == NULL )
     {
@@ -756,8 +865,15 @@ OGRErr OGRGeometryCollection::exportToWktInternal( char ** ppszDstText,
 /*      Build up the string, freeing temporary strings as we go.        */
 /* -------------------------------------------------------------------- */
     strcpy( *ppszDstText, getGeometryName() );
-    if( getCoordinateDimension() == 3 && eWkbVariant == wkbVariantIso )
-        strcat( *ppszDstText, " Z" );
+    if( eWkbVariant == wkbVariantIso )
+    {
+        if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
+            strcat( *ppszDstText, " ZM" );
+        else if( flags & OGR_G_3D )
+            strcat( *ppszDstText, " Z" );
+        else if( flags & OGR_G_MEASURED )
+            strcat( *ppszDstText, " M" );
+    }
     strcat( *ppszDstText, " (" );
     nCumulativeLength = strlen(*ppszDstText);
 
@@ -768,19 +884,23 @@ OGRErr OGRGeometryCollection::exportToWktInternal( char ** ppszDstText,
 
         if( bMustWriteComma )
             (*ppszDstText)[nCumulativeLength++] = ',';
-        bMustWriteComma = TRUE;
+        bMustWriteComma = true;
 
-        int nSkip = 0;
+        size_t nSkip = 0;
         if( pszSkipPrefix != NULL &&
             EQUALN(papszGeoms[iGeom], pszSkipPrefix, strlen(pszSkipPrefix)) &&
             papszGeoms[iGeom][strlen(pszSkipPrefix)] == ' ' )
         {
             nSkip = strlen(pszSkipPrefix) + 1;
-            if( EQUALN(papszGeoms[iGeom] + nSkip, "Z ", 2) )
+            if( STARTS_WITH_CI(papszGeoms[iGeom] + nSkip, "ZM ") )
+                nSkip += 3;
+            else if( STARTS_WITH_CI(papszGeoms[iGeom] + nSkip, "M ") )
+                nSkip += 2;
+            else if( STARTS_WITH_CI(papszGeoms[iGeom] + nSkip, "Z ") )
                 nSkip += 2;
         }
 
-        int nGeomLength = strlen(papszGeoms[iGeom] + nSkip);
+        size_t nGeomLength = strlen(papszGeoms[iGeom] + nSkip);
         memcpy( *ppszDstText + nCumulativeLength, papszGeoms[iGeom] + nSkip, nGeomLength );
         nCumulativeLength += nGeomLength;
         VSIFree( papszGeoms[iGeom] );
@@ -823,7 +943,7 @@ void OGRGeometryCollection::getEnvelope( OGREnvelope3D * psEnvelope ) const
 
 {
     OGREnvelope3D       oGeomEnv;
-    int                 bExtentSet = FALSE;
+    bool                bExtentSet = false;
 
     for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
     {
@@ -832,7 +952,7 @@ void OGRGeometryCollection::getEnvelope( OGREnvelope3D * psEnvelope ) const
             if (!bExtentSet)
             {
                 papoGeoms[iGeom]->getEnvelope( psEnvelope );
-                bExtentSet = TRUE;
+                bExtentSet = true;
             }
             else
             {
@@ -856,20 +976,19 @@ void OGRGeometryCollection::getEnvelope( OGREnvelope3D * psEnvelope ) const
 OGRBoolean OGRGeometryCollection::Equals( OGRGeometry * poOther ) const
 
 {
-    OGRGeometryCollection *poOGC = (OGRGeometryCollection *) poOther;
-
-    if( poOGC == this )
+    if( poOther == this )
         return TRUE;
-    
+
     if( poOther->getGeometryType() != getGeometryType() )
         return FALSE;
 
     if ( IsEmpty() && poOther->IsEmpty() )
         return TRUE;
 
+    OGRGeometryCollection *poOGC = (OGRGeometryCollection *) poOther;
     if( getNumGeometries() != poOGC->getNumGeometries() )
         return FALSE;
-    
+
     // we should eventually test the SRS.
 
     for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
@@ -900,7 +1019,7 @@ OGRErr OGRGeometryCollection::transform( OGRCoordinateTransformation *poCT )
         {
             if( iGeom != 0 )
             {
-                CPLDebug("OGR", 
+                CPLDebug("OGR",
                          "OGRGeometryCollection::transform() failed for a geometry other\n"
                          "than the first, meaning some geometries are transformed\n"
                          "and some are not!\n" );
@@ -947,6 +1066,26 @@ void OGRGeometryCollection::setCoordinateDimension( int nNewDimension )
     OGRGeometry::setCoordinateDimension( nNewDimension );
 }
 
+void OGRGeometryCollection::set3D( OGRBoolean bIs3D )
+{
+    for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
+    {
+        papoGeoms[iGeom]->set3D( bIs3D );
+    }
+
+    OGRGeometry::set3D( bIs3D );
+}
+
+void OGRGeometryCollection::setMeasured( OGRBoolean bIsMeasured )
+{
+    for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
+    {
+        papoGeoms[iGeom]->setMeasured( bIsMeasured );
+    }
+
+    OGRGeometry::setMeasured( bIsMeasured );
+}
+
 
 /************************************************************************/
 /*                              get_Length()                            */
@@ -1091,6 +1230,8 @@ OGRGeometry* OGRGeometryCollection::getLinearGeometry(double dfMaxAngleStepSizeD
 {
     OGRGeometryCollection* poGC = (OGRGeometryCollection*)
         OGRGeometryFactory::createGeometry(OGR_GT_GetLinear(getGeometryType()));
+    if( poGC == NULL )
+        return NULL;
     poGC->assignSpatialReference( getSpatialReference() );
     for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
     {
@@ -1109,13 +1250,15 @@ OGRGeometry* OGRGeometryCollection::getCurveGeometry(const char* const* papszOpt
 {
     OGRGeometryCollection* poGC = (OGRGeometryCollection*)
         OGRGeometryFactory::createGeometry(OGR_GT_GetCurve(getGeometryType()));
+    if( poGC == NULL )
+        return NULL;
     poGC->assignSpatialReference( getSpatialReference() );
-    int bHasCurveGeometry = FALSE;
+    bool bHasCurveGeometry = false;
     for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
     {
         OGRGeometry* poSubGeom = papoGeoms[iGeom]->getCurveGeometry(papszOptions);
         if( poSubGeom->hasCurveGeometry() )
-            bHasCurveGeometry = TRUE;
+            bHasCurveGeometry = true;
         poGC->addGeometryDirectly( poSubGeom );
     }
     if( !bHasCurveGeometry )
@@ -1135,7 +1278,8 @@ OGRGeometryCollection* OGRGeometryCollection::TransferMembersAndDestroy(
                                             OGRGeometryCollection* poDst)
 {
     poDst->assignSpatialReference(poSrc->getSpatialReference());
-    poDst->setCoordinateDimension(poSrc->getCoordinateDimension());
+    poDst->set3D(poSrc->Is3D());
+    poDst->setMeasured(poSrc->IsMeasured());
     poDst->nGeomCount = poSrc->nGeomCount;
     poDst->papoGeoms = poSrc->papoGeoms;
     poSrc->nGeomCount = 0;
diff --git a/ogr/ogrgeometryfactory.cpp b/ogr/ogrgeometryfactory.cpp
index 0cb3691..caeb4b0 100644
--- a/ogr/ogrgeometryfactory.cpp
+++ b/ogr/ogrgeometryfactory.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeometryfactory.cpp 29330 2015-06-14 12:11:11Z rouault $
+ * $Id: ogrgeometryfactory.cpp 33652 2016-03-05 23:39:47Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Factory for converting geometry to and from well known binary
@@ -33,8 +33,15 @@
 #include "ogr_api.h"
 #include "ogr_p.h"
 #include "ogr_geos.h"
+#include <new>
 
-CPL_CVSID("$Id: ogrgeometryfactory.cpp 29330 2015-06-14 12:11:11Z rouault $");
+#ifndef HAVE_GEOS
+#define UNUSED_IF_NO_GEOS CPL_UNUSED
+#else
+#define UNUSED_IF_NO_GEOS
+#endif
+
+CPL_CVSID("$Id: ogrgeometryfactory.cpp 33652 2016-03-05 23:39:47Z rouault $");
 
 /************************************************************************/
 /*                           createFromWkb()                            */
@@ -51,7 +58,7 @@ CPL_CVSID("$Id: ogrgeometryfactory.cpp 29330 2015-06-14 12:11:11Z rouault $");
  * establish the number of bytes it required in WKB format.
  *
  * Also note that this is a static method, and that there
- * is no need to instantiate an OGRGeometryFactory object.  
+ * is no need to instantiate an OGRGeometryFactory object.
  *
  * The C function OGR_G_CreateFromWkb() is the same as this method.
  *
@@ -64,6 +71,7 @@ CPL_CVSID("$Id: ogrgeometryfactory.cpp 29330 2015-06-14 12:11:11Z rouault $");
  *                  OGRGeometryFactory::destroyGeometry() after use.
  * @param nBytes the number of bytes available in pabyData, or -1 if it isn't
  *               known.
+ * @param eWkbVariant WKB variant.
  *
  * @return OGRERR_NONE if all goes well, otherwise any of
  * OGRERR_NOT_ENOUGH_DATA, OGRERR_UNSUPPORTED_GEOMETRY_TYPE, or
@@ -78,7 +86,7 @@ OGRErr OGRGeometryFactory::createFromWkb(unsigned char *pabyData,
 
 {
     OGRwkbGeometryType eGeometryType;
-    OGRwkbByteOrder eByteOrder;
+    int             nByteOrder;
     OGRErr      eErr;
     OGRGeometry *poGeom;
 
@@ -91,14 +99,12 @@ OGRErr OGRGeometryFactory::createFromWkb(unsigned char *pabyData,
 /*      Get the byte order byte.  The extra tests are to work around    */
 /*      bug sin the WKB of DB2 v7.2 as identified by Safe Software.     */
 /* -------------------------------------------------------------------- */
-    eByteOrder = DB2_V72_FIX_BYTE_ORDER((OGRwkbByteOrder) *pabyData);
-
-
-    if( eByteOrder != wkbXDR && eByteOrder != wkbNDR )
+    nByteOrder = DB2_V72_FIX_BYTE_ORDER(*pabyData);
+    if( nByteOrder != wkbXDR && nByteOrder != wkbNDR )
     {
-        CPLDebug( "OGR", 
+        CPLDebug( "OGR",
                   "OGRGeometryFactory::createFromWkb() - got corrupt data.\n"
-                  "%02X%02X%02X%02X%02X%02X%02X%02X%02X\n", 
+                  "%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
                   pabyData[0],
                   pabyData[1],
                   pabyData[2],
@@ -117,8 +123,7 @@ OGRErr OGRGeometryFactory::createFromWkb(unsigned char *pabyData,
 /*      one byte.                                                       */
 /* -------------------------------------------------------------------- */
 
-    OGRBoolean bIs3D;
-    OGRErr err = OGRReadWKBGeometryType( pabyData, eWkbVariant, &eGeometryType, &bIs3D );
+    OGRErr err = OGRReadWKBGeometryType( pabyData, eWkbVariant, &eGeometryType );
 
     if( err != OGRERR_NONE )
         return err;
@@ -129,7 +134,7 @@ OGRErr OGRGeometryFactory::createFromWkb(unsigned char *pabyData,
 /*      initialize from the input stream.                               */
 /* -------------------------------------------------------------------- */
     poGeom = createGeometry( eGeometryType );
-    
+
     if( poGeom == NULL )
         return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
 
@@ -143,12 +148,12 @@ OGRErr OGRGeometryFactory::createFromWkb(unsigned char *pabyData,
 /* -------------------------------------------------------------------- */
     if( eErr == OGRERR_NONE )
     {
-        if ( poGeom->hasCurveGeometry() && 
-             CSLTestBoolean(CPLGetConfigOption("OGR_STROKE_CURVE", "FALSE")) ) 
+        if ( poGeom->hasCurveGeometry() &&
+             CSLTestBoolean(CPLGetConfigOption("OGR_STROKE_CURVE", "FALSE")) )
         {
             OGRGeometry* poNewGeom = poGeom->getLinearGeometry();
-            delete poGeom; 
-            poGeom = poNewGeom; 
+            delete poGeom;
+            poGeom = poNewGeom;
         }
         poGeom->assignSpatialReference( poSR );
         *ppoReturn = poGeom;
@@ -180,7 +185,7 @@ OGRErr OGRGeometryFactory::createFromWkb(unsigned char *pabyData,
  * @param pabyData pointer to the input BLOB data.
  * @param hSRS handle to the spatial reference to be assigned to the
  *             created geometry object.  This may be NULL.
- * @param phGeometry the newly created geometry object will 
+ * @param phGeometry the newly created geometry object will
  * be assigned to the indicated handle on return.  This will be NULL in case
  * of failure. If not NULL, *phGeometry should be freed with
  * OGR_G_DestroyGeometry() after use.
@@ -192,13 +197,13 @@ OGRErr OGRGeometryFactory::createFromWkb(unsigned char *pabyData,
  * OGRERR_CORRUPT_DATA may be returned.
  */
 
-OGRErr CPL_DLL OGR_G_CreateFromWkb( unsigned char *pabyData, 
+OGRErr CPL_DLL OGR_G_CreateFromWkb( unsigned char *pabyData,
                                     OGRSpatialReferenceH hSRS,
-                                    OGRGeometryH *phGeometry, 
+                                    OGRGeometryH *phGeometry,
                                     int nBytes )
 
 {
-    return OGRGeometryFactory::createFromWkb( pabyData, 
+    return OGRGeometryFactory::createFromWkb( pabyData,
                                               (OGRSpatialReference *) hSRS,
                                               (OGRGeometry **) phGeometry,
                                               nBytes );
@@ -227,8 +232,8 @@ OGRErr CPL_DLL OGR_G_CreateFromWkb( unsigned char *pabyData,
  *
  *  <pre>
  *    const char* wkt= "POINT(0 0)";
- *  
- *    // cast because OGR_G_CreateFromWkt will move the pointer 
+ *
+ *    // cast because OGR_G_CreateFromWkt will move the pointer
  *    char* pszWkt = (char*) wkt;
  *    OGRSpatialReferenceH ref = OSRNewSpatialReference(NULL);
  *    OGRGeometryH new_geom;
@@ -263,62 +268,62 @@ OGRErr OGRGeometryFactory::createFromWkt(char **ppszData,
 /* -------------------------------------------------------------------- */
 /*      Instantiate a geometry of the appropriate type.                 */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(szToken,"POINT") )
+    if( STARTS_WITH_CI(szToken,"POINT") )
     {
         poGeom = new OGRPoint();
     }
 
-    else if( EQUAL(szToken,"LINESTRING") )
+    else if( STARTS_WITH_CI(szToken,"LINESTRING") )
     {
         poGeom = new OGRLineString();
     }
 
-    else if( EQUAL(szToken,"POLYGON") )
+    else if( STARTS_WITH_CI(szToken,"POLYGON") )
     {
         poGeom = new OGRPolygon();
     }
-    
-    else if( EQUAL(szToken,"GEOMETRYCOLLECTION") )
+
+    else if( STARTS_WITH_CI(szToken,"GEOMETRYCOLLECTION") )
     {
         poGeom = new OGRGeometryCollection();
     }
-    
-    else if( EQUAL(szToken,"MULTIPOLYGON") )
+
+    else if( STARTS_WITH_CI(szToken,"MULTIPOLYGON") )
     {
         poGeom = new OGRMultiPolygon();
     }
 
-    else if( EQUAL(szToken,"MULTIPOINT") )
+    else if( STARTS_WITH_CI(szToken,"MULTIPOINT") )
     {
         poGeom = new OGRMultiPoint();
     }
 
-    else if( EQUAL(szToken,"MULTILINESTRING") )
+    else if( STARTS_WITH_CI(szToken,"MULTILINESTRING") )
     {
         poGeom = new OGRMultiLineString();
     }
 
-    else if( EQUAL(szToken,"CIRCULARSTRING") )
+    else if( STARTS_WITH_CI(szToken,"CIRCULARSTRING") )
     {
         poGeom = new OGRCircularString();
     }
 
-    else if( EQUAL(szToken,"COMPOUNDCURVE") )
+    else if( STARTS_WITH_CI(szToken,"COMPOUNDCURVE") )
     {
         poGeom = new OGRCompoundCurve();
     }
 
-    else if( EQUAL(szToken,"CURVEPOLYGON") )
+    else if( STARTS_WITH_CI(szToken,"CURVEPOLYGON") )
     {
         poGeom = new OGRCurvePolygon();
     }
 
-    else if( EQUAL(szToken,"MULTICURVE") )
+    else if( STARTS_WITH_CI(szToken,"MULTICURVE") )
     {
         poGeom = new OGRMultiCurve();
     }
 
-    else if( EQUAL(szToken,"MULTISURFACE") )
+    else if( STARTS_WITH_CI(szToken,"MULTISURFACE") )
     {
         poGeom = new OGRMultiSurface();
     }
@@ -332,18 +337,18 @@ OGRErr OGRGeometryFactory::createFromWkt(char **ppszData,
 /*      Do the import.                                                  */
 /* -------------------------------------------------------------------- */
     eErr = poGeom->importFromWkt( &pszInput );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Assign spatial reference system.                                */
 /* -------------------------------------------------------------------- */
     if( eErr == OGRERR_NONE )
     {
-        if ( poGeom->hasCurveGeometry() && 
-             CSLTestBoolean(CPLGetConfigOption("OGR_STROKE_CURVE", "FALSE")) ) 
+        if ( poGeom->hasCurveGeometry() &&
+             CSLTestBoolean(CPLGetConfigOption("OGR_STROKE_CURVE", "FALSE")) )
         {
             OGRGeometry* poNewGeom = poGeom->getLinearGeometry();
-            delete poGeom; 
-            poGeom = poNewGeom; 
+            delete poGeom;
+            poGeom = poNewGeom;
         }
         poGeom->assignSpatialReference( poSR );
         *ppoReturn = poGeom;
@@ -353,7 +358,7 @@ OGRErr OGRGeometryFactory::createFromWkt(char **ppszData,
     {
         delete poGeom;
     }
-    
+
     return eErr;
 }
 
@@ -381,7 +386,7 @@ OGRErr OGRGeometryFactory::createFromWkt(char **ppszData,
  * OGRERR_CORRUPT_DATA may be returned.
  */
 
-OGRErr CPL_DLL OGR_G_CreateFromWkt( char **ppszData, 
+OGRErr CPL_DLL OGR_G_CreateFromWkt( char **ppszData,
                                     OGRSpatialReferenceH hSRS,
                                     OGRGeometryH *phGeometry )
 
@@ -395,12 +400,12 @@ OGRErr CPL_DLL OGR_G_CreateFromWkt( char **ppszData,
 /*                           createGeometry()                           */
 /************************************************************************/
 
-/** 
+/**
  * \brief Create an empty geometry of desired type.
  *
  * This is equivalent to allocating the desired geometry with new, but
- * the allocation is guaranteed to take place in the context of the 
- * GDAL/OGR heap. 
+ * the allocation is guaranteed to take place in the context of the
+ * GDAL/OGR heap.
  *
  * This method is the same as the C function OGR_G_CreateGeometry().
  *
@@ -417,43 +422,43 @@ OGRGeometryFactory::createGeometry( OGRwkbGeometryType eGeometryType )
     switch( wkbFlatten(eGeometryType) )
     {
       case wkbPoint:
-          return new OGRPoint();
+          return new (std::nothrow) OGRPoint();
 
       case wkbLineString:
-          return new OGRLineString();
+          return new (std::nothrow) OGRLineString();
 
       case wkbPolygon:
-          return new OGRPolygon();
+          return new (std::nothrow) OGRPolygon();
 
       case wkbGeometryCollection:
-          return new OGRGeometryCollection();
+          return new (std::nothrow) OGRGeometryCollection();
 
       case wkbMultiPolygon:
-          return new OGRMultiPolygon();
+          return new (std::nothrow) OGRMultiPolygon();
 
       case wkbMultiPoint:
-          return new OGRMultiPoint();
+          return new (std::nothrow) OGRMultiPoint();
 
       case wkbMultiLineString:
-          return new OGRMultiLineString();
+          return new (std::nothrow) OGRMultiLineString();
 
       case wkbLinearRing:
-          return new OGRLinearRing();
+          return new (std::nothrow) OGRLinearRing();
 
       case wkbCircularString:
-          return new OGRCircularString();
+          return new (std::nothrow) OGRCircularString();
 
       case wkbCompoundCurve:
-          return new OGRCompoundCurve();
+          return new (std::nothrow) OGRCompoundCurve();
 
       case wkbCurvePolygon:
-          return new OGRCurvePolygon();
+          return new (std::nothrow) OGRCurvePolygon();
 
       case wkbMultiCurve:
-          return new OGRMultiCurve();
+          return new (std::nothrow) OGRMultiCurve();
 
       case wkbMultiSurface:
-          return new OGRMultiSurface();
+          return new (std::nothrow) OGRMultiSurface();
 
       default:
           return NULL;
@@ -463,14 +468,14 @@ OGRGeometryFactory::createGeometry( OGRwkbGeometryType eGeometryType )
 /************************************************************************/
 /*                        OGR_G_CreateGeometry()                        */
 /************************************************************************/
-/** 
+/**
  * \brief Create an empty geometry of desired type.
  *
  * This is equivalent to allocating the desired geometry with new, but
- * the allocation is guaranteed to take place in the context of the 
- * GDAL/OGR heap. 
+ * the allocation is guaranteed to take place in the context of the
+ * GDAL/OGR heap.
  *
- * This function is the same as the CPP method 
+ * This function is the same as the CPP method
  * OGRGeometryFactory::createGeometry.
  *
  * @param eGeometryType the type code of the geometry to be created.
@@ -493,7 +498,7 @@ OGRGeometryH OGR_G_CreateGeometry( OGRwkbGeometryType eGeometryType )
 /**
  * \brief Destroy geometry object.
  *
- * Equivalent to invoking delete on a geometry, but it guaranteed to take 
+ * Equivalent to invoking delete on a geometry, but it guaranteed to take
  * place within the context of the GDAL/OGR heap.
  *
  * This method is the same as the C function OGR_G_DestroyGeometry().
@@ -514,10 +519,10 @@ void OGRGeometryFactory::destroyGeometry( OGRGeometry *poGeom )
 /**
  * \brief Destroy geometry object.
  *
- * Equivalent to invoking delete on a geometry, but it guaranteed to take 
+ * Equivalent to invoking delete on a geometry, but it guaranteed to take
  * place within the context of the GDAL/OGR heap.
  *
- * This function is the same as the CPP method 
+ * This function is the same as the CPP method
  * OGRGeometryFactory::destroyGeometry.
  *
  * @param hGeom handle to the geometry to delete.
@@ -539,8 +544,8 @@ void OGR_G_DestroyGeometry( OGRGeometryH hGeom )
  * Tries to force the provided geometry to be a polygon. This effects a change
  * on multipolygons.
  * Starting with GDAL 2.0, curve polygons or closed curves will be changed to polygons.
- * The passed in geometry is consumed and a new one returned (or potentially the same one). 
- * 
+ * The passed in geometry is consumed and a new one returned (or potentially the same one).
+ *
  * @param poGeom the input geometry - ownership is passed to the method.
  * @return new geometry.
  */
@@ -603,13 +608,13 @@ OGRGeometry *OGRGeometryFactory::forceToPolygon( OGRGeometry *poGeom )
 
     for( iGeom = 0; iGeom < poGC->getNumGeometries(); iGeom++ )
     {
-        if( wkbFlatten(poGC->getGeometryRef(iGeom)->getGeometryType()) 
+        if( wkbFlatten(poGC->getGeometryRef(iGeom)->getGeometryType())
             != wkbPolygon )
             continue;
 
         OGRPolygon *poOldPoly = (OGRPolygon *) poGC->getGeometryRef(iGeom);
         int   iRing;
-        
+
         if( poOldPoly->getExteriorRing() == NULL )
             continue;
 
@@ -618,7 +623,7 @@ OGRGeometry *OGRGeometryFactory::forceToPolygon( OGRGeometry *poGeom )
         for( iRing = 0; iRing < poOldPoly->getNumInteriorRings(); iRing++ )
             poPolygon->addRingDirectly( poOldPoly->stealInteriorRing( iRing ) );
     }
-    
+
     delete poGC;
 
     return poPolygon;
@@ -631,7 +636,7 @@ OGRGeometry *OGRGeometryFactory::forceToPolygon( OGRGeometry *poGeom )
 /**
  * \brief Convert to polygon.
  *
- * This function is the same as the C++ method 
+ * This function is the same as the C++ method
  * OGRGeometryFactory::forceToPolygon().
  *
  * @param hGeom handle to the geometry to convert (ownership surrendered).
@@ -643,7 +648,7 @@ OGRGeometry *OGRGeometryFactory::forceToPolygon( OGRGeometry *poGeom )
 OGRGeometryH OGR_G_ForceToPolygon( OGRGeometryH hGeom )
 
 {
-    return (OGRGeometryH) 
+    return (OGRGeometryH)
         OGRGeometryFactory::forceToPolygon( (OGRGeometry *) hGeom );
 }
 
@@ -656,8 +661,8 @@ OGRGeometryH OGR_G_ForceToPolygon( OGRGeometryH hGeom )
  *
  * Tries to force the provided geometry to be a multipolygon.  Currently
  * this just effects a change on polygons.  The passed in geometry is
- * consumed and a new one returned (or potentially the same one). 
- * 
+ * consumed and a new one returned (or potentially the same one).
+ *
  * @return new geometry.
  */
 
@@ -695,7 +700,7 @@ OGRGeometry *OGRGeometryFactory::forceToMultiPolygon( OGRGeometry *poGeom )
         eGeomType == wkbMultiSurface )
     {
         int iGeom;
-        int bAllPoly = TRUE;
+        bool bAllPoly = true;
         OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeom;
         if( poGeom->hasCurveGeometry() )
         {
@@ -708,12 +713,12 @@ OGRGeometry *OGRGeometryFactory::forceToMultiPolygon( OGRGeometry *poGeom )
         {
             OGRwkbGeometryType eSubGeomType = wkbFlatten(poGC->getGeometryRef(iGeom)->getGeometryType());
             if( eSubGeomType != wkbPolygon )
-                bAllPoly = FALSE;
+                bAllPoly = false;
         }
 
         if( !bAllPoly )
             return poGeom;
-        
+
         OGRMultiPolygon *poMP = new OGRMultiPolygon();
         poMP->assignSpatialReference(poGeom->getSpatialReference());
 
@@ -740,7 +745,7 @@ OGRGeometry *OGRGeometryFactory::forceToMultiPolygon( OGRGeometry *poGeom )
 
 /* -------------------------------------------------------------------- */
 /*      Eventually we should try to split the polygon into component    */
-/*      island polygons.  But thats alot of work and can be put off.    */
+/*      island polygons.  But that is a lot of work and can be put off. */
 /* -------------------------------------------------------------------- */
     if( eGeomType != wkbPolygon )
         return poGeom;
@@ -759,7 +764,7 @@ OGRGeometry *OGRGeometryFactory::forceToMultiPolygon( OGRGeometry *poGeom )
 /**
  * \brief Convert to multipolygon.
  *
- * This function is the same as the C++ method 
+ * This function is the same as the C++ method
  * OGRGeometryFactory::forceToMultiPolygon().
  *
  * @param hGeom handle to the geometry to convert (ownership surrendered).
@@ -771,7 +776,7 @@ OGRGeometry *OGRGeometryFactory::forceToMultiPolygon( OGRGeometry *poGeom )
 OGRGeometryH OGR_G_ForceToMultiPolygon( OGRGeometryH hGeom )
 
 {
-    return (OGRGeometryH) 
+    return (OGRGeometryH)
         OGRGeometryFactory::forceToMultiPolygon( (OGRGeometry *) hGeom );
 }
 
@@ -785,8 +790,8 @@ OGRGeometryH OGR_G_ForceToMultiPolygon( OGRGeometryH hGeom )
  * Tries to force the provided geometry to be a multipoint.  Currently
  * this just effects a change on points or collection of points.
  * The passed in geometry is
- * consumed and a new one returned (or potentially the same one). 
- * 
+ * consumed and a new one returned (or potentially the same one).
+ *
  * @return new geometry.
  */
 
@@ -813,19 +818,19 @@ OGRGeometry *OGRGeometryFactory::forceToMultiPoint( OGRGeometry *poGeom )
     if( eGeomType == wkbGeometryCollection )
     {
         int iGeom;
-        int bAllPoint = TRUE;
+        bool bAllPoint = true;
         OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeom;
 
         for( iGeom = 0; iGeom < poGC->getNumGeometries(); iGeom++ )
         {
             if( wkbFlatten(poGC->getGeometryRef(iGeom)->getGeometryType())
                 != wkbPoint )
-                bAllPoint = FALSE;
+                bAllPoint = false;
         }
 
         if( !bAllPoint )
             return poGeom;
-        
+
         OGRMultiPoint *poMP = new OGRMultiPoint();
         poMP->assignSpatialReference(poGeom->getSpatialReference());
 
@@ -857,7 +862,7 @@ OGRGeometry *OGRGeometryFactory::forceToMultiPoint( OGRGeometry *poGeom )
 /**
  * \brief Convert to multipoint.
  *
- * This function is the same as the C++ method 
+ * This function is the same as the C++ method
  * OGRGeometryFactory::forceToMultiPoint().
  *
  * @param hGeom handle to the geometry to convert (ownership surrendered).
@@ -869,7 +874,7 @@ OGRGeometry *OGRGeometryFactory::forceToMultiPoint( OGRGeometry *poGeom )
 OGRGeometryH OGR_G_ForceToMultiPoint( OGRGeometryH hGeom )
 
 {
-    return (OGRGeometryH) 
+    return (OGRGeometryH)
         OGRGeometryFactory::forceToMultiPoint( (OGRGeometry *) hGeom );
 }
 
@@ -885,14 +890,14 @@ OGRGeometryH OGR_G_ForceToMultiPoint( OGRGeometryH hGeom )
  * - linestrings are placed in a multilinestring.
  * - circularstrings and compoundcurves will be approximated and placed in a
  * multilinestring.
- * - geometry collections will be converted to multilinestring if they only 
+ * - geometry collections will be converted to multilinestring if they only
  * contain linestrings.
  * - polygons will be changed to a collection of linestrings (one per ring).
  * - curvepolygons will be approximated and changed to a collection of linestrings (one per ring).
  *
  * The passed in geometry is
- * consumed and a new one returned (or potentially the same one). 
- * 
+ * consumed and a new one returned (or potentially the same one).
+ *
  * @return new geometry.
  */
 
@@ -919,7 +924,7 @@ OGRGeometry *OGRGeometryFactory::forceToMultiLineString( OGRGeometry *poGeom )
     if( eGeomType == wkbGeometryCollection )
     {
         int iGeom;
-        int bAllLines = TRUE;
+        bool bAllLines = true;
         OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeom;
         if( poGeom->hasCurveGeometry() )
         {
@@ -931,12 +936,12 @@ OGRGeometry *OGRGeometryFactory::forceToMultiLineString( OGRGeometry *poGeom )
         for( iGeom = 0; iGeom < poGC->getNumGeometries(); iGeom++ )
         {
             if( poGC->getGeometryRef(iGeom)->getGeometryType() != wkbLineString )
-                bAllLines = FALSE;
+                bAllLines = false;
         }
 
         if( !bAllLines )
             return poGeom;
-        
+
         OGRMultiLineString *poMP = new OGRMultiLineString();
         poMP->assignSpatialReference(poGeom->getSpatialReference());
 
@@ -1034,7 +1039,7 @@ OGRGeometry *OGRGeometryFactory::forceToMultiLineString( OGRGeometry *poGeom )
             for( iRing = 0; iRing < poPoly->getNumInteriorRings()+1; iRing++ )
             {
                 OGRLineString *poNewLS, *poLR;
-                
+
                 if( iRing == 0 )
                 {
                     poLR = poPoly->getExteriorRing();
@@ -1043,10 +1048,10 @@ OGRGeometry *OGRGeometryFactory::forceToMultiLineString( OGRGeometry *poGeom )
                 }
                 else
                     poLR = poPoly->getInteriorRing(iRing-1);
-    
+
                 if (poLR == NULL || poLR->getNumPoints() == 0)
                     continue;
-                
+
                 poNewLS = new OGRLineString();
                 poNewLS->addSubLineString( poLR );
                 poMP->addGeometryDirectly( poNewLS );
@@ -1101,7 +1106,7 @@ OGRGeometry *OGRGeometryFactory::forceToMultiLineString( OGRGeometry *poGeom )
 /**
  * \brief Convert to multilinestring.
  *
- * This function is the same as the C++ method 
+ * This function is the same as the C++ method
  * OGRGeometryFactory::forceToMultiLineString().
  *
  * @param hGeom handle to the geometry to convert (ownership surrendered).
@@ -1113,7 +1118,7 @@ OGRGeometry *OGRGeometryFactory::forceToMultiLineString( OGRGeometry *poGeom )
 OGRGeometryH OGR_G_ForceToMultiLineString( OGRGeometryH hGeom )
 
 {
-    return (OGRGeometryH) 
+    return (OGRGeometryH)
         OGRGeometryFactory::forceToMultiLineString( (OGRGeometry *) hGeom );
 }
 
@@ -1173,13 +1178,13 @@ typedef enum
 /**
  * \brief Organize polygons based on geometries.
  *
- * Analyse a set of rings (passed as simple polygons), and based on a 
- * geometric analysis convert them into a polygon with inner rings, 
+ * Analyse a set of rings (passed as simple polygons), and based on a
+ * geometric analysis convert them into a polygon with inner rings,
  * (or a MultiPolygon if dealing with more than one polygon) that follow the
  * OGC Simple Feature specification.
  *
  * All the input geometries must be OGRPolygons with only a valid exterior
- * ring (at least 4 points) and no interior rings. 
+ * ring (at least 4 points) and no interior rings.
  *
  * The passed in geometries become the responsibility of the method, but the
  * papoPolygons "pointer array" remains owned by the caller.
@@ -1187,7 +1192,7 @@ typedef enum
  * For faster computation, a polygon is considered to be inside
  * another one if a single point of its external ring is included into the other one.
  * (unless 'OGR_DEBUG_ORGANIZE_POLYGONS' configuration option is set to TRUE.
- * In that case, a slower algorithm that tests exact topological relationships 
+ * In that case, a slower algorithm that tests exact topological relationships
  * is used if GEOS is available.)
  *
  * In cases where a big number of polygons is passed to this function, the default processing
@@ -1212,8 +1217,8 @@ typedef enum
  * @param papoPolygons array of geometry pointers - should all be OGRPolygons.
  * Ownership of the geometries is passed, but not of the array itself.
  * @param nPolygonCount number of items in papoPolygons
- * @param pbIsValidGeometry value will be set TRUE if result is valid or 
- * FALSE otherwise. 
+ * @param pbIsValidGeometry value will be set TRUE if result is valid or
+ * FALSE otherwise.
  * @param papszOptions a list of strings for passing options
  *
  * @return a single resulting geometry (either OGRPolygon or OGRMultiPolygon).
@@ -1268,10 +1273,10 @@ OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
 /* -------------------------------------------------------------------- */
     sPolyExtended* asPolyEx = new sPolyExtended[nPolygonCount];
 
-    int go_on = TRUE;
-    int bMixedUpGeometries = FALSE;
-    int bNonPolygon = FALSE;
-    int bFoundCCW = FALSE;
+    bool go_on = true;
+    bool bMixedUpGeometries = false;
+    bool bNonPolygon = false;
+    bool bFoundCCW = false;
 
     const char* pszMethodValue = CSLFetchNameValue( (char**)papszOptions, "METHOD" );
     const char* pszMethodValueOption = CPLGetConfigOption("OGR_ORGANIZE_POLYGONS", NULL);
@@ -1283,7 +1288,7 @@ OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
         if (EQUAL(pszMethodValue, "SKIP"))
         {
             method = METHOD_SKIP;
-            bMixedUpGeometries = TRUE;
+            bMixedUpGeometries = true;
         }
         else if (EQUAL(pszMethodValue, "ONLY_CCW"))
         {
@@ -1330,15 +1335,15 @@ OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
         {
             if( !bMixedUpGeometries )
             {
-                CPLError( 
-                    CE_Warning, CPLE_AppDefined, 
+                CPLError(
+                    CE_Warning, CPLE_AppDefined,
                     "organizePolygons() received an unexpected geometry.\n"
                     "Either a polygon with interior rings, or a polygon with less than 4 points,\n"
                     "or a non-Polygon geometry.  Return arguments as a collection." );
-                bMixedUpGeometries = TRUE;
+                bMixedUpGeometries = true;
             }
             if( wkbFlatten(papoPolygons[i]->getGeometryType()) != wkbPolygon )
-                bNonPolygon = TRUE;
+                bNonPolygon = true;
         }
     }
 
@@ -1420,7 +1425,7 @@ OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
         {
             if (bFoundCCW)
             {
-                CPLError( CE_Warning, CPLE_AppDefined, 
+                CPLError( CE_Warning, CPLE_AppDefined,
                      "organizePolygons() received a polygon with more than %d parts. "
                      "The processing may be really slow.\n"
                      "You can skip the processing by setting METHOD=SKIP, "
@@ -1430,7 +1435,7 @@ OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
             }
             else
             {
-                CPLError( CE_Warning, CPLE_AppDefined, 
+                CPLError( CE_Warning, CPLE_AppDefined,
                         "organizePolygons() received a polygon with more than %d parts. "
                         "The processing may be really slow.\n"
                         "You can skip the processing by setting METHOD=SKIP.",
@@ -1441,32 +1446,34 @@ OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
     }
 
 
-    /* This a several steps algorithm :
+    /* This a nulti-step algorithm :
        1) Sort polygons by descending areas
        2) For each polygon of rank i, find its smallest enclosing polygon
           among the polygons of rank [i-1 ... 0]. If there are no such polygon,
-          this is a toplevel polygon. Otherwise, depending on if the enclosing
-          polygon is toplevel or not, we can decide if we are toplevel or not
-       3) Re-sort the polygons to retrieve their inital order (nicer for some applications)
-       4) For each non toplevel polygon (= inner ring), add it to its outer ring
-       5) Add the toplevel polygons to the multipolygon
+          this is a top-level polygon. Otherwise, depending on if the enclosing
+          polygon is top-level or not, we can decide if we are top-level or not
+       3) Re-sort the polygons to retrieve their initial order (nicer for
+          some applications)
+       4) For each non top-level polygon (= inner ring), add it to its
+          outer ring
+       5) Add the top-level polygons to the multipolygon
 
        Complexity : O(nPolygonCount^2)
     */
 
     /* Compute how each polygon relate to the other ones
-       To save a bit of computation we always begin the computation by a test 
-       on the enveloppe. We also take into account the areas to avoid some 
-       useless tests.  (A contains B implies envelop(A) contains envelop(B) 
-       and area(A) > area(B)) In practise, we can hope that few full geometry 
+       To save a bit of computation we always begin the computation by a test
+       on the envelope. We also take into account the areas to avoid some
+       useless tests.  (A contains B implies envelop(A) contains envelop(B)
+       and area(A) > area(B)) In practice, we can hope that few full geometry
        intersection of inclusion test is done:
-       * if the polygons are well separated geographically (a set of islands 
-       for example), no full geometry intersection or inclusion test is done. 
+       * if the polygons are well separated geographically (a set of islands
+       for example), no full geometry intersection or inclusion test is done.
        (the envelopes don't intersect each other)
 
-       * if the polygons are 'lake inside an island inside a lake inside an 
-       area' and that each polygon is much smaller than its enclosing one, 
-       their bounding boxes are stricly contained into each oter, and thus, 
+       * if the polygons are 'lake inside an island inside a lake inside an
+       area' and that each polygon is much smaller than its enclosing one,
+       their bounding boxes are strictly contained into each other, and thus,
        no full geometry intersection or inclusion test is done
     */
 
@@ -1500,7 +1507,7 @@ OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
 
         for(j=i-1; go_on && j>=0;j--)
         {
-            int b_i_inside_j = FALSE;
+            bool b_i_inside_j = false;
 
             if (method == METHOD_ONLY_CCW && asPolyEx[j].bIsCW == FALSE)
             {
@@ -1518,7 +1525,7 @@ OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
                         /* We are testing if a CCW ring is in the biggest CW ring */
                         /* It *must* be inside as this is the last candidate, otherwise */
                         /* the winding order rules is broken */
-                        b_i_inside_j = TRUE;
+                        b_i_inside_j = true;
                     }
                     else if (asPolyEx[j].poExteriorRing->isPointOnRingBoundary(&asPolyEx[i].poAPoint, FALSE))
                     {
@@ -1530,15 +1537,15 @@ OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
                             asPolyEx[i].poExteriorRing->getPoint(k, &point);
                             if (asPolyEx[j].poExteriorRing->isPointOnRingBoundary(&point, FALSE))
                             {
-                                /* If it is on the boundary of j, iterate again */ 
+                                /* If it is on the boundary of j, iterate again */
                             }
                             else if (asPolyEx[j].poExteriorRing->isPointInRing(&point, FALSE))
                             {
                                 /* If then point is strictly included in j, then i is considered inside j */
-                                b_i_inside_j = TRUE;
+                                b_i_inside_j = true;
                                 break;
                             }
-                            else 
+                            else
                             {
                                 /* If it is outside, then i cannot be inside j */
                                 break;
@@ -1558,15 +1565,15 @@ OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
                                 pointMiddle.setY((point1.getY() + point2.getY()) / 2);
                                 if (asPolyEx[j].poExteriorRing->isPointOnRingBoundary(&pointMiddle, FALSE))
                                 {
-                                    /* If it is on the boundary of j, iterate again */ 
+                                    /* If it is on the boundary of j, iterate again */
                                 }
                                 else if (asPolyEx[j].poExteriorRing->isPointInRing(&pointMiddle, FALSE))
                                 {
                                     /* If then point is strictly included in j, then i is considered inside j */
-                                    b_i_inside_j = TRUE;
+                                    b_i_inside_j = true;
                                     break;
                                 }
-                                else 
+                                else
                                 {
                                     /* If it is outside, then i cannot be inside j */
                                     break;
@@ -1577,12 +1584,12 @@ OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
                     /* Note that isPointInRing only test strict inclusion in the ring */
                     else if (asPolyEx[j].poExteriorRing->isPointInRing(&asPolyEx[i].poAPoint, FALSE))
                     {
-                        b_i_inside_j = TRUE;
+                        b_i_inside_j = true;
                     }
                 }
                 else if (asPolyEx[j].poPolygon->Contains(asPolyEx[i].poPolygon))
                 {
-                    b_i_inside_j = TRUE;
+                    b_i_inside_j = true;
                 }
             }
 
@@ -1605,8 +1612,8 @@ OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
                 }
                 break;
             }
-            /* We use Overlaps instead of Intersects to be more 
-               tolerant about touching polygons */ 
+            /* We use Overlaps instead of Intersects to be more
+               tolerant about touching polygons */
             else if ( bUseFastVersion || !asPolyEx[i].sEnvelope.Intersects(asPolyEx[j].sEnvelope)
                      || !asPolyEx[i].poPolygon->Overlaps(asPolyEx[j].poPolygon) )
             {
@@ -1618,16 +1625,16 @@ OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
                    contained inside the other one. This is a really broken
                    case. We just make a multipolygon with the whole set of
                    polygons */
-                go_on = FALSE;
+                go_on = false;
 #ifdef DEBUG
                 char* wkt1;
                 char* wkt2;
                 asPolyEx[i].poPolygon->exportToWkt(&wkt1);
                 asPolyEx[j].poPolygon->exportToWkt(&wkt2);
-                CPLDebug( "OGR", 
+                CPLDebug( "OGR",
                           "Bad intersection for polygons %d and %d\n"
                           "geom %d: %s\n"
-                          "geom %d: %s", 
+                          "geom %d: %s",
                           i, j, i, wkt1, j, wkt2 );
                 CPLFree(wkt1);
                 CPLFree(wkt2);
@@ -1725,7 +1732,7 @@ OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
  * This method translates a fragment of GML containing only the geometry
  * portion into a corresponding OGRGeometry.  There are many limitations
  * on the forms of GML geometries supported by this parser, but they are
- * too numerous to list here. 
+ * too numerous to list here.
  *
  * The following GML2 elements are parsed : Point, LineString, Polygon,
  * MultiPoint, MultiLineString, MultiPolygon, MultiGeometry.
@@ -1742,7 +1749,7 @@ OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
  *
  * @param pszData The GML fragment for the geometry.
  *
- * @return a geometry on succes, or NULL on error.  
+ * @return a geometry on success, or NULL on error.
  */
 
 OGRGeometry *OGRGeometryFactory::createFromGML( const char *pszData )
@@ -1751,7 +1758,7 @@ OGRGeometry *OGRGeometryFactory::createFromGML( const char *pszData )
     OGRGeometryH hGeom;
 
     hGeom = OGR_G_CreateFromGML( pszData );
-    
+
     return (OGRGeometry *) hGeom;
 }
 
@@ -1760,12 +1767,13 @@ OGRGeometry *OGRGeometryFactory::createFromGML( const char *pszData )
 /************************************************************************/
 
 OGRGeometry *
-OGRGeometryFactory::createFromGEOS( GEOSContextHandle_t hGEOSCtxt, GEOSGeom geosGeom )
+OGRGeometryFactory::createFromGEOS( UNUSED_IF_NO_GEOS GEOSContextHandle_t hGEOSCtxt,
+                                    UNUSED_IF_NO_GEOS GEOSGeom geosGeom )
 
 {
-#ifndef HAVE_GEOS 
+#ifndef HAVE_GEOS
 
-    CPLError( CE_Failure, CPLE_NotSupported, 
+    CPLError( CE_Failure, CPLE_NotSupported,
               "GEOS support not enabled." );
     return NULL;
 
@@ -1795,7 +1803,7 @@ OGRGeometryFactory::createFromGEOS( GEOSContextHandle_t hGEOSCtxt, GEOSGeom geos
         return NULL;
     }
 
-    if( OGRGeometryFactory::createFromWkb( (unsigned char *) pabyBuf, 
+    if( OGRGeometryFactory::createFromWkb( (unsigned char *) pabyBuf,
                                            NULL, &poGeometry, (int) nSize )
         != OGRERR_NONE )
     {
@@ -1833,7 +1841,7 @@ OGRGeometryFactory::createFromGEOS( GEOSContextHandle_t hGEOSCtxt, GEOSGeom geos
 int OGRGeometryFactory::haveGEOS()
 
 {
-#ifndef HAVE_GEOS 
+#ifndef HAVE_GEOS
     return FALSE;
 #else
     return TRUE;
@@ -1848,7 +1856,7 @@ int OGRGeometryFactory::haveGEOS()
  * \brief Create a geometry object of the appropriate type from it's FGF (FDO Geometry Format) binary representation.
  *
  * Also note that this is a static method, and that there
- * is no need to instantiate an OGRGeometryFactory object.  
+ * is no need to instantiate an OGRGeometryFactory object.
  *
  * The C function OGR_G_CreateFromFgf() is the same as this method.
  *
@@ -1857,9 +1865,9 @@ int OGRGeometryFactory::haveGEOS()
  *             created geometry object.  This may be NULL.
  * @param ppoReturn the newly created geometry object will be assigned to the
  *                  indicated pointer on return.  This will be NULL in case
- *                  of failure.
+ *                  of failure, but NULL might be a valid return for a NULL shape.
  * @param nBytes the number of bytes available in pabyData.
- * @param pnBytesConsumed if not NULL, it will be set to the number of bytes 
+ * @param pnBytesConsumed if not NULL, it will be set to the number of bytes
  * consumed (at most nBytes).
  *
  * @return OGRERR_NONE if all goes well, otherwise any of
@@ -1890,20 +1898,12 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
                                                   int *pnBytesConsumed,
                                                   int nRecLevel )
 {
-    OGRErr       eErr = OGRERR_NONE;
-    OGRGeometry *poGeom = NULL;
-    GInt32       nGType, nGDim;
-    int          nTupleSize = 0;
-    int          iOrdinal = 0;
-    
-    (void) iOrdinal;
-
     /* Arbitrary value, but certainly large enough for reasonable usages ! */
     if( nRecLevel == 32 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                    "Too many recursiong level (%d) while parsing FGF geometry.",
-                    nRecLevel );
+                  "Too many recursion levels (%d) while parsing FGF geometry.",
+                  nRecLevel );
         return OGRERR_CORRUPT_DATA;
     }
 
@@ -1915,6 +1915,7 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
 /* -------------------------------------------------------------------- */
 /*      Decode the geometry type.                                       */
 /* -------------------------------------------------------------------- */
+    GInt32 nGType;
     memcpy( &nGType, pabyData + 0, 4 );
     CPL_LSBPTR32( &nGType );
 
@@ -1922,20 +1923,24 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
         return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
 
 /* -------------------------------------------------------------------- */
-/*      Decode the dimentionality if appropriate.                       */
+/*      Decode the dimensionality if appropriate.                       */
 /* -------------------------------------------------------------------- */
+    OGRGeometry *poGeom = NULL;
+    int          nTupleSize = 0;
+    GInt32       nGDim = 0;
+
+    // TODO: Why is this a switch?
     switch( nGType )
     {
       case 1: // Point
       case 2: // LineString
       case 3: // Polygon
-        
         if( nBytes < 8 )
             return OGRERR_NOT_ENOUGH_DATA;
 
         memcpy( &nGDim, pabyData + 4, 4 );
         CPL_LSBPTR32( &nGDim );
-        
+
         if( nGDim < 0 || nGDim > 3 )
             return OGRERR_CORRUPT_DATA;
 
@@ -1954,7 +1959,7 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
 /* -------------------------------------------------------------------- */
 /*      None                                                            */
 /* -------------------------------------------------------------------- */
-    if( nGType == 0 ) 
+    if( nGType == 0 )
     {
         if( pnBytesConsumed )
             *pnBytesConsumed = 4;
@@ -1965,14 +1970,13 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
 /* -------------------------------------------------------------------- */
     else if( nGType == 1 )
     {
-        double  adfTuple[4];
-
         if( nBytes < nTupleSize * 8 + 8 )
             return OGRERR_NOT_ENOUGH_DATA;
 
+        double  adfTuple[4];
         memcpy( adfTuple, pabyData + 8, nTupleSize*8 );
 #ifdef CPL_MSB
-        for( iOrdinal = 0; iOrdinal < nTupleSize; iOrdinal++ )
+        for( int iOrdinal = 0; iOrdinal < nTupleSize; iOrdinal++ )
             CPL_SWAP64PTR( adfTuple + iOrdinal );
 #endif
         if( nTupleSize > 2 )
@@ -1989,14 +1993,10 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
 /* -------------------------------------------------------------------- */
     else if( nGType == 2 )
     {
-        double adfTuple[4];
-        GInt32 nPointCount;
-        int    iPoint;
-        OGRLineString *poLS;
-
         if( nBytes < 12 )
             return OGRERR_NOT_ENOUGH_DATA;
 
+        GInt32 nPointCount;
         memcpy( &nPointCount, pabyData + 8, 4 );
         CPL_LSBPTR32( &nPointCount );
 
@@ -2006,15 +2006,17 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
         if( nBytes - 12 < nTupleSize * 8 * nPointCount )
             return OGRERR_NOT_ENOUGH_DATA;
 
-        poGeom = poLS = new OGRLineString();
+        OGRLineString *poLS = new OGRLineString();
+        poGeom = poLS;
         poLS->setNumPoints( nPointCount );
 
-        for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+        for( int iPoint = 0; iPoint < nPointCount; iPoint++ )
         {
-            memcpy( adfTuple, pabyData + 12 + 8*nTupleSize*iPoint, 
+            double adfTuple[4];
+            memcpy( adfTuple, pabyData + 12 + 8*nTupleSize*iPoint,
                     nTupleSize*8 );
 #ifdef CPL_MSB
-            for( iOrdinal = 0; iOrdinal < nTupleSize; iOrdinal++ )
+            for( int iOrdinal = 0; iOrdinal < nTupleSize; iOrdinal++ )
                 CPL_SWAP64PTR( adfTuple + iOrdinal );
 #endif
             if( nTupleSize > 2 )
@@ -2032,17 +2034,10 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
 /* -------------------------------------------------------------------- */
     else if( nGType == 3 )
     {
-        double adfTuple[4];
-        GInt32 nPointCount;
-        GInt32 nRingCount;
-        int    iPoint, iRing;
-        OGRLinearRing *poLR;
-        OGRPolygon *poPoly;
-        int    nNextByte;
-
         if( nBytes < 12 )
             return OGRERR_NOT_ENOUGH_DATA;
 
+        GInt32 nRingCount;
         memcpy( &nRingCount, pabyData + 8, 4 );
         CPL_LSBPTR32( &nRingCount );
 
@@ -2053,11 +2048,12 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
         if (nBytes - 12 < nRingCount * 4)
             return OGRERR_NOT_ENOUGH_DATA;
 
-        nNextByte = 12;
-        
-        poGeom = poPoly = new OGRPolygon();
+        int nNextByte = 12;
+
+        OGRPolygon * poPoly = new OGRPolygon();
+        poGeom = poPoly;
 
-        for( iRing = 0; iRing < nRingCount; iRing++ )
+        for( int iRing = 0; iRing < nRingCount; iRing++ )
         {
             if( nBytes - nNextByte < 4 )
             {
@@ -2065,6 +2061,7 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
                 return OGRERR_NOT_ENOUGH_DATA;
             }
 
+            GInt32 nPointCount;
             memcpy( &nPointCount, pabyData + nNextByte, 4 );
             CPL_LSBPTR32( &nPointCount );
 
@@ -2082,16 +2079,17 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
                 return OGRERR_NOT_ENOUGH_DATA;
             }
 
-            poLR = new OGRLinearRing();
+            OGRLinearRing *poLR = new OGRLinearRing();
             poLR->setNumPoints( nPointCount );
-            
-            for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+
+            for( int iPoint = 0; iPoint < nPointCount; iPoint++ )
             {
+                double adfTuple[4];
                 memcpy( adfTuple, pabyData + nNextByte, nTupleSize*8 );
                 nNextByte += nTupleSize * 8;
 
 #ifdef CPL_MSB
-                for( iOrdinal = 0; iOrdinal < nTupleSize; iOrdinal++ )
+                for( int iOrdinal = 0; iOrdinal < nTupleSize; iOrdinal++ )
                     CPL_SWAP64PTR( adfTuple + iOrdinal );
 #endif
                 if( nTupleSize > 2 )
@@ -2115,13 +2113,10 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
              || nGType == 6      // MultiPolygon
              || nGType == 7 )    // MultiGeometry
     {
-        OGRGeometryCollection *poGC = NULL;
-        GInt32 nGeomCount;
-        int iGeom, nBytesUsed;
-
         if( nBytes < 8 )
             return OGRERR_NOT_ENOUGH_DATA;
 
+        GInt32 nGeomCount;
         memcpy( &nGeomCount, pabyData + 4, 4 );
         CPL_LSBPTR32( &nGeomCount );
 
@@ -2132,8 +2127,7 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
         if (nBytes - 8 < 4 * nGeomCount)
             return OGRERR_NOT_ENOUGH_DATA;
 
-        nBytesUsed = 8;
-
+        OGRGeometryCollection *poGC = NULL;
         if( nGType == 4 )
             poGC = new OGRMultiPoint();
         else if( nGType == 5 )
@@ -2142,14 +2136,16 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
             poGC = new OGRMultiPolygon();
         else if( nGType == 7 )
             poGC = new OGRGeometryCollection();
-        
-        for( iGeom = 0; iGeom < nGeomCount; iGeom++ )
+
+        int nBytesUsed = 8;
+
+        for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
         {
             int nThisGeomSize;
             OGRGeometry *poThisGeom = NULL;
-         
-            eErr = createFromFgfInternal( pabyData + nBytesUsed, poSR, &poThisGeom,
-                                  nBytes - nBytesUsed, &nThisGeomSize, nRecLevel + 1);
+
+            OGRErr eErr = createFromFgfInternal( pabyData + nBytesUsed, poSR, &poThisGeom,
+                                                 nBytes - nBytesUsed, &nThisGeomSize, nRecLevel + 1);
             if( eErr != OGRERR_NONE )
             {
                 delete poGC;
@@ -2157,12 +2153,15 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
             }
 
             nBytesUsed += nThisGeomSize;
-            eErr = poGC->addGeometryDirectly( poThisGeom );
-            if( eErr != OGRERR_NONE )
+            if( poThisGeom != NULL )
             {
-                delete poGC;
-                delete poThisGeom;
-                return eErr;
+                eErr = poGC->addGeometryDirectly( poThisGeom );
+                if( eErr != OGRERR_NONE )
+                {
+                    delete poGC;
+                    delete poThisGeom;
+                    return eErr;
+                }
             }
         }
 
@@ -2184,31 +2183,24 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
 /* -------------------------------------------------------------------- */
 /*      Assign spatial reference system.                                */
 /* -------------------------------------------------------------------- */
-    if( eErr == OGRERR_NONE )
-    {
-        if( poGeom != NULL && poSR )
-            poGeom->assignSpatialReference( poSR );
-        *ppoReturn = poGeom;
-    }
-    else
-    {
-        delete poGeom;
-    }
+    if( poGeom != NULL && poSR )
+        poGeom->assignSpatialReference( poSR );
+    *ppoReturn = poGeom;
 
-    return eErr;
+    return OGRERR_NONE;
 }
 
 /************************************************************************/
 /*                        OGR_G_CreateFromFgf()                         */
 /************************************************************************/
 
-OGRErr CPL_DLL OGR_G_CreateFromFgf( unsigned char *pabyData, 
+OGRErr CPL_DLL OGR_G_CreateFromFgf( unsigned char *pabyData,
                                     OGRSpatialReferenceH hSRS,
-                                    OGRGeometryH *phGeometry, 
+                                    OGRGeometryH *phGeometry,
                                     int nBytes, int *pnBytesConsumed )
 
 {
-    return OGRGeometryFactory::createFromFgf( pabyData, 
+    return OGRGeometryFactory::createFromFgf( pabyData,
                                               (OGRSpatialReference *) hSRS,
                                               (OGRGeometry **) phGeometry,
                                               nBytes, pnBytesConsumed );
@@ -2333,7 +2325,7 @@ static void FixPolygonCoordinatesAtDateLine(OGRPolygon* poPoly, double dfDateLin
     {
         OGRLineString* poLS = (iPart == 0) ? poPoly->getExteriorRing() :
                                              poPoly->getInteriorRing(iPart-1);
-        int bGoEast = FALSE;
+        bool bGoEast = false;
         int bIs3D = poLS->getCoordinateDimension() == 3;
         for(i=1;i<poLS->getNumPoints();i++)
         {
@@ -2345,7 +2337,7 @@ static void FixPolygonCoordinatesAtDateLine(OGRPolygon* poPoly, double dfDateLin
                 if ((dfPrevX > dfLeftBorderX && dfX < dfRightBorderX) || (dfX < 0 && bGoEast))
                 {
                     dfX += 360;
-                    bGoEast = TRUE;
+                    bGoEast = true;
                     if( bIs3D )
                         poLS->setPoint(i, dfX, poLS->getY(i), poLS->getZ(i));
                     else
@@ -2365,11 +2357,11 @@ static void FixPolygonCoordinatesAtDateLine(OGRPolygon* poPoly, double dfDateLin
                                 poLS->setPoint(j, dfX + 360, poLS->getY(j));
                         }
                     }
-                    bGoEast = FALSE;
+                    bGoEast = false;
                 }
                 else
                 {
-                    bGoEast = FALSE;
+                    bGoEast = false;
                 }
             }
         }
@@ -2395,7 +2387,7 @@ static void Sub360ToLon( OGRGeometry* poGeom )
             {
                 Sub360ToLon((OGRGeometry*)OGR_G_GetGeometryRef((OGRGeometryH)poGeom, iGeom));
             }
-            
+
             break;
         }
 
@@ -2418,7 +2410,7 @@ static void Sub360ToLon( OGRGeometry* poGeom )
             }
             break;
         }
-            
+
         default:
             break;
     }
@@ -2437,7 +2429,7 @@ static void AddSimpleGeomToMulti(OGRGeometryCollection* poMulti,
         case wkbLineString:
             poMulti->addGeometry(poGeom);
             break;
-            
+
         case wkbMultiLineString:
         case wkbMultiPolygon:
         case wkbGeometryCollection:
@@ -2451,7 +2443,7 @@ static void AddSimpleGeomToMulti(OGRGeometryCollection* poMulti,
             }
             break;
         }
-            
+
         default:
             break;
     }
@@ -2471,26 +2463,26 @@ static void CutGeometryOnDateLineAndAddToMulti(OGRGeometryCollection* poMulti,
         case wkbPolygon:
         case wkbLineString:
         {
-            int bWrapDateline = FALSE;
-            int bSplitLineStringAtDateline = FALSE;
+            bool bWrapDateline = false;
+            bool bSplitLineStringAtDateline = false;
             OGREnvelope oEnvelope;
-            
+
             poGeom->getEnvelope(&oEnvelope);
-            
+
             /* Naive heuristics... Place to improvement... */
             OGRGeometry* poDupGeom = NULL;
-            
+
             double dfLeftBorderX = 180 - dfDateLineOffset;
             double dfRightBorderX = -180 + dfDateLineOffset;
             double dfDiffSpace = 360 - dfDateLineOffset;
-            
+
             if (oEnvelope.MinX > dfLeftBorderX && oEnvelope.MaxX > 180)
             {
 #ifndef HAVE_GEOS
-                CPLError( CE_Failure, CPLE_NotSupported, 
+                CPLError( CE_Failure, CPLE_NotSupported,
                         "GEOS support not enabled." );
 #else
-                bWrapDateline = TRUE;
+                bWrapDateline = true;
 #endif
             }
             else
@@ -2504,7 +2496,7 @@ static void CutGeometryOnDateLineAndAddToMulti(OGRGeometryCollection* poMulti,
                 {
                     int i;
                     double dfMaxSmallDiffLong = 0;
-                    int bHasBigDiff = FALSE;
+                    bool bHasBigDiff = false;
                     /* Detect big gaps in longitude */
                     for(i=1;i<poLS->getNumPoints();i++)
                     {
@@ -2513,21 +2505,21 @@ static void CutGeometryOnDateLineAndAddToMulti(OGRGeometryCollection* poMulti,
                         double dfDiffLong = fabs(dfX - dfPrevX);
                         if (dfDiffLong > dfDiffSpace &&
                             ((dfX > dfLeftBorderX && dfPrevX < dfRightBorderX) || (dfPrevX > dfLeftBorderX && dfX < dfRightBorderX)))
-                            bHasBigDiff = TRUE;
+                            bHasBigDiff = true;
                         else if (dfDiffLong > dfMaxSmallDiffLong)
                             dfMaxSmallDiffLong = dfDiffLong;
                     }
                     if (bHasBigDiff && dfMaxSmallDiffLong < dfDateLineOffset)
                     {
                         if (eGeomType == wkbLineString)
-                            bSplitLineStringAtDateline = TRUE;
+                            bSplitLineStringAtDateline = true;
                         else
                         {
 #ifndef HAVE_GEOS
-                            CPLError( CE_Failure, CPLE_NotSupported, 
+                            CPLError( CE_Failure, CPLE_NotSupported,
                                     "GEOS support not enabled." );
 #else
-                            bWrapDateline = TRUE;
+                            bWrapDateline = true;
                             poDupGeom = poGeom->clone();
                             FixPolygonCoordinatesAtDateLine((OGRPolygon*)poDupGeom, dfDateLineOffset);
 #endif
@@ -2553,7 +2545,7 @@ static void CutGeometryOnDateLineAndAddToMulti(OGRGeometryCollection* poMulti,
                 OGRGeometry* poGeom2 = poWorkGeom->Intersection(poRectangle2);
                 delete poRectangle1;
                 delete poRectangle2;
-                
+
                 if (poGeom1 != NULL && poGeom2 != NULL)
                 {
                     AddSimpleGeomToMulti(poMulti, poGeom1);
@@ -2564,7 +2556,7 @@ static void CutGeometryOnDateLineAndAddToMulti(OGRGeometryCollection* poMulti,
                 {
                     AddSimpleGeomToMulti(poMulti, poGeom);
                 }
-                
+
                 delete poGeom1;
                 delete poGeom2;
                 delete poDupGeom;
@@ -2572,10 +2564,10 @@ static void CutGeometryOnDateLineAndAddToMulti(OGRGeometryCollection* poMulti,
             else
             {
                 poMulti->addGeometry(poGeom);
-            }   
+            }
             break;
         }
-            
+
         case wkbMultiLineString:
         case wkbMultiPolygon:
         case wkbGeometryCollection:
@@ -2589,7 +2581,7 @@ static void CutGeometryOnDateLineAndAddToMulti(OGRGeometryCollection* poMulti,
             }
             break;
         }
-            
+
         default:
             break;
     }
@@ -2613,7 +2605,7 @@ OGRGeometry* OGRGeometryFactory::transformWithOptions( const OGRGeometry* poSrcG
             return NULL;
         }
     }
-    
+
     if (CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "WRAPDATELINE", "NO")))
     {
         OGRwkbGeometryType eType = wkbFlatten(poSrcGeom->getGeometryType());
@@ -2624,20 +2616,20 @@ OGRGeometry* OGRGeometryFactory::transformWithOptions( const OGRGeometry* poSrcG
             eNewType = wkbMultiLineString;
         else
             eNewType = wkbGeometryCollection;
-        
+
         OGRGeometryCollection* poMulti =
             (OGRGeometryCollection* )createGeometry(eNewType);
-            
+
         double dfDateLineOffset = CPLAtofM(CSLFetchNameValueDef(papszOptions, "DATELINEOFFSET", "10"));
         if(dfDateLineOffset <= 0 || dfDateLineOffset >= 360)
             dfDateLineOffset = 10;
 
         CutGeometryOnDateLineAndAddToMulti(poMulti, poDstGeom, dfDateLineOffset);
-        
+
         if (poMulti->getNumGeometries() == 0)
         {
             delete poMulti;
-        }            
+        }
         else if (poMulti->getNumGeometries() == 1)
         {
             delete poDstGeom;
@@ -2675,7 +2667,7 @@ static double OGRGF_GetDefaultStepSize()
  *
  * If the dfMaxAngleStepSizeDegrees is zero, then a default value will be
  * used.  This is currently 4 degrees unless the user has overridden the
- * value with the OGR_ARC_STEPSIZE configuration variable. 
+ * value with the OGR_ARC_STEPSIZE configuration variable.
  *
  * @see CPLSetConfigOption()
  *
@@ -2683,21 +2675,21 @@ static double OGRGF_GetDefaultStepSize()
  * @param dfCenterY center Y
  * @param dfZ center Z
  * @param dfPrimaryRadius X radius of ellipse.
- * @param dfSecondaryRadius Y radius of ellipse. 
+ * @param dfSecondaryRadius Y radius of ellipse.
  * @param dfRotation rotation of the ellipse clockwise.
- * @param dfStartAngle angle to first point on arc (clockwise of X-positive) 
- * @param dfEndAngle angle to last point on arc (clockwise of X-positive) 
+ * @param dfStartAngle angle to first point on arc (clockwise of X-positive)
+ * @param dfEndAngle angle to last point on arc (clockwise of X-positive)
  * @param dfMaxAngleStepSizeDegrees the largest step in degrees along the
  * arc, zero to use the default setting.
- * 
+ *
  * @return OGRLineString geometry representing an approximation of the arc.
  *
  * @since OGR 1.8.0
  */
 
-OGRGeometry* OGRGeometryFactory::approximateArcAngles( 
+OGRGeometry* OGRGeometryFactory::approximateArcAngles(
     double dfCenterX, double dfCenterY, double dfZ,
-    double dfPrimaryRadius, double dfSecondaryRadius, double dfRotation, 
+    double dfPrimaryRadius, double dfSecondaryRadius, double dfRotation,
     double dfStartAngle, double dfEndAngle,
     double dfMaxAngleStepSizeDegrees )
 
@@ -2713,12 +2705,12 @@ OGRGeometry* OGRGeometryFactory::approximateArcAngles(
         dfMaxAngleStepSizeDegrees = OGRGF_GetDefaultStepSize();
     }
 
-    // switch direction 
+    // switch direction
     dfStartAngle *= -1;
     dfEndAngle *= -1;
 
     // Figure out the number of slices to make this into.
-    nVertexCount = (int) 
+    nVertexCount = (int)
         ceil(fabs(dfEndAngle - dfStartAngle)/dfMaxAngleStepSizeDegrees) + 1;
     nVertexCount = MAX(2,nVertexCount);
     dfSlice = (dfEndAngle-dfStartAngle)/(nVertexCount-1);
@@ -2734,15 +2726,15 @@ OGRGeometry* OGRGeometryFactory::approximateArcAngles(
 
         dfAngleOnEllipse = (dfStartAngle + iPoint * dfSlice) * M_PI / 180.0;
 
-        // Compute position on the unrotated ellipse. 
+        // Compute position on the unrotated ellipse.
         dfEllipseX = cos(dfAngleOnEllipse) * dfPrimaryRadius;
         dfEllipseY = sin(dfAngleOnEllipse) * dfSecondaryRadius;
-        
+
         // Rotate this position around the center of the ellipse.
-        dfArcX = dfCenterX 
-            + dfEllipseX * cos(dfRotationRadians) 
+        dfArcX = dfCenterX
+            + dfEllipseX * cos(dfRotationRadians)
             + dfEllipseY * sin(dfRotationRadians);
-        dfArcY = dfCenterY 
+        dfArcY = dfCenterY
             - dfEllipseX * sin(dfRotationRadians)
             + dfEllipseY * cos(dfRotationRadians);
 
@@ -2784,8 +2776,8 @@ OGRGeometry* OGRGeometryFactory::approximateArcAngles(
  * @since OGR 1.8.0
  */
 
-OGRGeometryH CPL_DLL 
-OGR_G_ApproximateArcAngles( 
+OGRGeometryH CPL_DLL
+OGR_G_ApproximateArcAngles(
     double dfCenterX, double dfCenterY, double dfZ,
     double dfPrimaryRadius, double dfSecondaryRadius, double dfRotation,
     double dfStartAngle, double dfEndAngle,
@@ -2793,7 +2785,7 @@ OGR_G_ApproximateArcAngles(
 
 {
     return (OGRGeometryH) OGRGeometryFactory::approximateArcAngles(
-        dfCenterX, dfCenterY, dfZ, 
+        dfCenterX, dfCenterY, dfZ,
         dfPrimaryRadius, dfSecondaryRadius, dfRotation,
         dfStartAngle, dfEndAngle, dfMaxAngleStepSizeDegrees );
 }
@@ -2880,7 +2872,7 @@ OGRGeometry *OGRGeometryFactory::forceToLineString( OGRGeometry *poGeom, bool bO
     {
         OGRGeometryCollection *poNewGC = (OGRGeometryCollection *) poGC->getLinearGeometry();
         delete poGC;
-        poGeom = poGC = poNewGC;
+        poGC = poNewGC;
     }
 
     if( poGC->getNumGeometries() == 0 )
@@ -2958,11 +2950,11 @@ OGRGeometry *OGRGeometryFactory::forceToLineString( OGRGeometry *poGeom, bool bO
 
     if ( poGC->getNumGeometries() == 1 )
     {
-        OGRLineString *poLineString = (OGRLineString *) poGC->getGeometryRef(0);
+        OGRGeometry *poSingleGeom = poGC->getGeometryRef(0);
         poGC->removeGeometry( 0, FALSE );
         delete poGC;
 
-        return poLineString;
+        return poSingleGeom;
     }
 
     return poGC;
@@ -3045,16 +3037,16 @@ OGRGeometry * OGRGeometryFactory::forceTo( OGRGeometry* poGeom,
     if( !OGR_GT_IsSubClassOf(eType, wkbGeometryCollection) &&
          OGR_GT_IsSubClassOf(OGR_GT_GetCollection(eType), eTargetType) )
     {
-        OGRGeometryCollection* poRet = (OGRGeometryCollection*)createGeometry(eTargetType);
-        if( poRet )
+        OGRGeometry* poRet = createGeometry(eTargetType);
+        if( poRet == NULL)
         {
-            poRet->assignSpatialReference(poGeom->getSpatialReference());
-            if( eType == wkbLineString )
-                poGeom = OGRCurve::CastToLineString( (OGRCurve*)poGeom );
-            poRet->addGeometryDirectly(poGeom);
-        }
-        else
             delete poGeom;
+            return NULL;
+        }
+        poRet->assignSpatialReference(poGeom->getSpatialReference());
+        if( eType == wkbLineString )
+            poGeom = OGRCurve::CastToLineString( (OGRCurve*)poGeom );
+        ((OGRGeometryCollection*)poRet)->addGeometryDirectly(poGeom);
         return poRet;
     }
 
@@ -3358,7 +3350,7 @@ static void OGRGeometryFactoryStrokeArc(OGRLineString* poLine,
 #else
     /* Constant angle between all points, so as to not depend on winding order */
     int nSteps = (int)(fabs((alpha1 - alpha0) / dfStep)+0.5);
-    if( bStealthConstraints ) 
+    if( bStealthConstraints )
     {
         /* We need at least 6 intermediate vertex, and if more additional */
         /* multiples of 2 */
@@ -3440,8 +3432,8 @@ static GUInt16 OGRGF_GetHiddenValue(double dfX, double dfY)
 
 /* We need to define a full ordering between starting point and ending point */
 /* whatever it is */
-static int OGRGF_NeedSwithArcOrder(double x0, double y0,
-                                   double x2, double y2)
+static bool OGRGF_NeedSwithArcOrder(double x0, double y0,
+                                    double x2, double y2)
 {
     return ( x0 < x2 || (x0 == x2 && y0 < y2) );
 }
@@ -3506,7 +3498,7 @@ OGRLineString* OGRGeometryFactory::curveToLineString(
     double R, cx, cy, alpha0, alpha1, alpha2;
 
     /* So as to make sure the same curve followed in both direction results */
-    /* in perfectly(=binary identical) symetrical points */
+    /* in perfectly(=binary identical) symmetrical points. */
     if( OGRGF_NeedSwithArcOrder(x0,y0,x2,y2) )
     {
         OGRLineString* poLS = curveToLineString(x2,y2,z2,x1,y1,z1,x0,y0,z0,
@@ -3517,11 +3509,11 @@ OGRLineString* OGRGeometryFactory::curveToLineString(
     }
 
     OGRLineString* poLine = new OGRLineString();
-    int bIsArc = TRUE;
+    bool bIsArc = true;
     if( !GetCurveParmeters(x0, y0, x1, y1, x2, y2,
-                           R, cx, cy, alpha0, alpha1, alpha2)) 
+                           R, cx, cy, alpha0, alpha1, alpha2))
     {
-        bIsArc = FALSE;
+        bIsArc = false;
         cx = cy = R = alpha0 = alpha1 = alpha2 = 0.0;
     }
 
@@ -3548,7 +3540,7 @@ OGRLineString* OGRGeometryFactory::curveToLineString(
     else
         poLine->addPoint(x0, y0);
 
-    int bAddIntermediatePoint = FALSE;
+    bool bAddIntermediatePoint = false;
     int bStealth = TRUE;
     for(const char* const* papszIter = papszOptions; papszIter && *papszIter; papszIter++)
     {
@@ -3558,12 +3550,12 @@ OGRLineString* OGRGeometryFactory::curveToLineString(
         {
             if( EQUAL(pszValue, "YES") || EQUAL(pszValue, "TRUE") || EQUAL(pszValue, "ON") )
             {
-                bAddIntermediatePoint = TRUE;
+                bAddIntermediatePoint = true;
                 bStealth = FALSE;
             }
             else if( EQUAL(pszValue, "NO") || EQUAL(pszValue, "FALSE") || EQUAL(pszValue, "OFF") )
             {
-                bAddIntermediatePoint = FALSE;
+                bAddIntermediatePoint = false;
                 bStealth = FALSE;
             }
             else if( EQUAL(pszValue, "STEALTH") )
@@ -3609,7 +3601,7 @@ OGRLineString* OGRGeometryFactory::curveToLineString(
             /* bits of the x,y of the first 2 computed points (so 32 bits), */
             /* then put 0xFF, and on the last couple points put again the */
             /* angle but in reverse order, so that overall the low-significant bits */
-            /* of all the points are symetrical w.r.t the mid-point */
+            /* of all the points are symmetrical w.r.t the mid-point */
             double dfRatio = (alpha1 - alpha0) / (alpha2 - alpha0);
             GUInt32 nAlphaRatio = (GUInt32)(0.5 + HIDDEN_ALPHA_SCALE * dfRatio);
             GUInt16 nAlphaRatioLow = nAlphaRatio & HIDDEN_ALPHA_HALF_MASK;
@@ -3711,8 +3703,8 @@ static int OGRGF_DetectArc(const OGRLineString* poLS, int i,
     GUInt32 nAlphaRatioRef =
             OGRGF_GetHiddenValue(p1.getX(), p1.getY()) |
         (OGRGF_GetHiddenValue(p2.getX(), p2.getY()) << HIDDEN_ALPHA_HALF_WIDTH);
-    int bFoundFFFFFFFFPattern = FALSE;
-    int bFoundReversedAlphaRatioRef = FALSE;
+    bool bFoundFFFFFFFFPattern = false;
+    bool bFoundReversedAlphaRatioRef = false;
     int bValidAlphaRatio = (nAlphaRatioRef > 0 && nAlphaRatioRef < 0xFFFFFFFF);
     int nCountValidAlphaRatio = 1;
 
@@ -3831,7 +3823,7 @@ static int OGRGF_DetectArc(const OGRLineString* poLS, int i,
 #endif
             if( !bFoundFFFFFFFFPattern && nAlphaRatioReversed == 0xFFFFFFFF )
             {
-                bFoundFFFFFFFFPattern = TRUE;
+                bFoundFFFFFFFFPattern = true;
                 nCountValidAlphaRatio ++;
             }
             else if( bFoundFFFFFFFFPattern && !bFoundReversedAlphaRatioRef &&
@@ -3842,7 +3834,7 @@ static int OGRGF_DetectArc(const OGRLineString* poLS, int i,
             else if( bFoundFFFFFFFFPattern && !bFoundReversedAlphaRatioRef &&
                         nAlphaRatioReversed == nAlphaRatioRef )
             {
-                bFoundReversedAlphaRatioRef = TRUE;
+                bFoundReversedAlphaRatioRef = true;
                 nCountValidAlphaRatio ++;
             }
             else
@@ -3866,8 +3858,9 @@ static int OGRGF_DetectArc(const OGRLineString* poLS, int i,
                             dfLastValidAlpha -= dfMaxDeltaAlpha;
                             j --;
 #ifdef VERBOSE_DEBUG_CURVEFROMLINESTRING
-                            printf("--> corrected as fabs(dfLastValidAlpha - alpha0_1)=%f, j=%d\n",
-                                fabs(dfLastValidAlpha - alpha0_1), j);
+                            printf( "--> corrected as fabs(dfLastValidAlpha - "
+                                    "alpha0_1)=%f, j=%d\n",
+                                    fabs(dfLastValidAlpha - alpha0_1), j);
 #endif
                         }
                     }
@@ -3878,8 +3871,9 @@ static int OGRGF_DetectArc(const OGRLineString* poLS, int i,
                             dfLastValidAlpha += dfMaxDeltaAlpha;
                             j --;
 #ifdef VERBOSE_DEBUG_CURVEFROMLINESTRING
-                            printf("--> corrected as fabs(dfLastValidAlpha - alpha0_1)=%f, j=%d\n",
-                                fabs(dfLastValidAlpha - alpha0_1), j);
+                            printf( "--> corrected as fabs(dfLastValidAlpha - "
+                                    "alpha0_1)=%f, j=%d\n",
+                                    fabs(dfLastValidAlpha - alpha0_1), j);
 #endif
                         }
                     }
@@ -3888,7 +3882,8 @@ static int OGRGF_DetectArc(const OGRLineString* poLS, int i,
                 }
 
 #ifdef VERBOSE_DEBUG_CURVEFROMLINESTRING
-                printf("j=%d, nAlphaRatioReversed = %u --> unconsistent values accross arc. Don't use it\n",
+                printf( "j=%d, nAlphaRatioReversed = %u --> inconsistent "
+                        "values across arc. Don't use it\n",
                         j, nAlphaRatioReversed);
 #endif
                 bValidAlphaRatio = FALSE;
@@ -3943,7 +3938,7 @@ static int OGRGF_DetectArc(const OGRLineString* poLS, int i,
     if( poLSNew != NULL )
     {
         double dfScale2 = MAX(1, fabs(p0.getX()));
-        dfScale2 = MAX(dfScale, fabs(p0.getY()));
+        dfScale2 = MAX(dfScale2, fabs(p0.getY()));
         /* Not strictly necessary, but helps having 'clean' lines without duplicated points */
         if( fabs(poLSNew->getX(poLSNew->getNumPoints()-1) - p0.getX()) / dfScale2 > 1e-8 ||
             fabs(poLSNew->getY(poLSNew->getNumPoints()-1) - p0.getY()) / dfScale2 > 1e-8 )
diff --git a/ogr/ogrlinearring.cpp b/ogr/ogrlinearring.cpp
index bf9ebdb..05ffebd 100644
--- a/ogr/ogrlinearring.cpp
+++ b/ogr/ogrlinearring.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrlinearring.cpp 27959 2014-11-14 18:29:21Z rouault $
+ * $Id: ogrlinearring.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRLinearRing geometry class.
@@ -31,7 +31,7 @@
 #include "ogr_geometry.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrlinearring.cpp 27959 2014-11-14 18:29:21Z rouault $");
+CPL_CVSID("$Id: ogrlinearring.cpp 33631 2016-03-04 06:28:09Z goatbar $");
 
 /************************************************************************/
 /*                           OGRLinearRing()                            */
@@ -43,6 +43,24 @@ OGRLinearRing::OGRLinearRing()
 }
 
 /************************************************************************/
+/*                  OGRLinearRing( const OGRLinearRing& )               */
+/************************************************************************/
+
+/**
+ * \brief Copy constructor.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the constructor
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRLinearRing::OGRLinearRing( const OGRLinearRing& other ) :
+    OGRLineString( other )
+{
+}
+
+/************************************************************************/
 /*                          ~OGRLinearRing()                            */
 /************************************************************************/
 
@@ -77,10 +95,32 @@ OGRLinearRing::OGRLinearRing( OGRLinearRing * poSrcRing )
 }
 
 /************************************************************************/
+/*                    operator=( const OGRLinearRing& )                 */
+/************************************************************************/
+
+/**
+ * \brief Assignment operator.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the operator
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRLinearRing& OGRLinearRing::operator=( const OGRLinearRing& other )
+{
+    if( this != &other)
+    {
+        OGRLineString::operator=( other );
+    }
+    return *this;
+}
+
+/************************************************************************/
 /*                          getGeometryName()                           */
 /************************************************************************/
 
-const char * OGRLinearRing::getGeometryName() const 
+const char * OGRLinearRing::getGeometryName() const
 
 {
     return "LINEARRING";
@@ -106,7 +146,7 @@ int OGRLinearRing::WkbSize() const
 
 OGRErr OGRLinearRing::importFromWkb( CPL_UNUSED unsigned char *pabyData,
                                      CPL_UNUSED  int nSize,
-                                     CPL_UNUSED OGRwkbVariant eWkbVariant ) 
+                                     CPL_UNUSED OGRwkbVariant eWkbVariant )
 
 {
     return OGRERR_UNSUPPORTED_OPERATION;
@@ -118,7 +158,7 @@ OGRErr OGRLinearRing::importFromWkb( CPL_UNUSED unsigned char *pabyData,
 /*      Disable method for this class.                                  */
 /************************************************************************/
 
-OGRErr OGRLinearRing::exportToWkb( CPL_UNUSED OGRwkbByteOrder eByteOrder, 
+OGRErr OGRLinearRing::exportToWkb( CPL_UNUSED OGRwkbByteOrder eByteOrder,
                                    CPL_UNUSED unsigned char * pabyData,
                                    CPL_UNUSED OGRwkbVariant eWkbVariant ) const
 
@@ -133,9 +173,9 @@ OGRErr OGRLinearRing::exportToWkb( CPL_UNUSED OGRwkbByteOrder eByteOrder,
 /*      method!                                                         */
 /************************************************************************/
 
-OGRErr OGRLinearRing::_importFromWkb( OGRwkbByteOrder eByteOrder, int b3D, 
+OGRErr OGRLinearRing::_importFromWkb( OGRwkbByteOrder eByteOrder, int _flags,
                                       unsigned char * pabyData,
-                                      int nBytesAvailable ) 
+                                      int nBytesAvailable )
 
 {
     if( nBytesAvailable < 4 && nBytesAvailable != -1 )
@@ -145,21 +185,27 @@ OGRErr OGRLinearRing::_importFromWkb( OGRwkbByteOrder eByteOrder, int b3D,
 /*      Get the vertex count.                                           */
 /* -------------------------------------------------------------------- */
     int         nNewNumPoints;
-    
+
     memcpy( &nNewNumPoints, pabyData, 4 );
-    
+
     if( OGR_SWAP( eByteOrder ) )
         nNewNumPoints = CPL_SWAP32(nNewNumPoints);
 
     /* Check if the wkb stream buffer is big enough to store
      * fetched number of points.
-     * 16 or 24 - size of point structure
+     * 16, 24, or 32 - size of point structure
      */
-    int nPointSize = (b3D ? 24 : 16);
+    int nPointSize;
+    if( (_flags & OGR_G_3D) && (_flags & OGR_G_MEASURED) )
+        nPointSize = 32;
+    else if( (_flags & OGR_G_3D) || (_flags & OGR_G_MEASURED) )
+        nPointSize = 24;
+    else
+        nPointSize = 16;
     if (nNewNumPoints < 0 || nNewNumPoints > INT_MAX / nPointSize)
         return OGRERR_CORRUPT_DATA;
     int nBufferMinSize = nPointSize * nNewNumPoints;
-   
+
     if( nBytesAvailable != -1 && nBufferMinSize > nBytesAvailable - 4 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -170,21 +216,39 @@ OGRErr OGRLinearRing::_importFromWkb( OGRwkbByteOrder eByteOrder, int b3D,
     /* (Re)Allocation of paoPoints buffer. */
     setNumPoints( nNewNumPoints, FALSE );
 
-    if( b3D )
+    if( _flags & OGR_G_3D )
         Make3D();
     else
         Make2D();
-    
+
+    if( _flags & OGR_G_MEASURED )
+        AddM();
+    else
+        RemoveM();
+
 /* -------------------------------------------------------------------- */
 /*      Get the vertices                                                */
 /* -------------------------------------------------------------------- */
-    int i = 0;
-
-    if( !b3D )
+    if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
     {
-        memcpy( paoPoints, pabyData + 4, 16 * nPointCount );
+        for( int i = 0; i < nPointCount; i++ )
+        {
+            memcpy( &(paoPoints[i].x), pabyData + 4 + 32 * i, 8 );
+            memcpy( &(paoPoints[i].y), pabyData + 4 + 32 * i + 8, 8 );
+            memcpy( padfZ + i, pabyData + 4 + 32 * i + 16, 8 );
+            memcpy( padfM + i, pabyData + 4 + 32 * i + 24, 8 );
+        }
     }
-    else
+    else if( flags & OGR_G_MEASURED )
+    {
+        for( int i = 0; i < nPointCount; i++ )
+        {
+            memcpy( &(paoPoints[i].x), pabyData + 4 + 24 * i, 8 );
+            memcpy( &(paoPoints[i].y), pabyData + 4 + 24 * i + 8, 8 );
+            memcpy( padfM + i, pabyData + 4 + 24 * i + 16, 8 );
+        }
+    }
+    else if( flags & OGR_G_3D )
     {
         for( int i = 0; i < nPointCount; i++ )
         {
@@ -193,18 +257,26 @@ OGRErr OGRLinearRing::_importFromWkb( OGRwkbByteOrder eByteOrder, int b3D,
             memcpy( padfZ + i, pabyData + 4 + 24 * i + 16, 8 );
         }
     }
-    
+    else
+    {
+        memcpy( paoPoints, pabyData + 4, 16 * nPointCount );
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Byte swap if needed.                                            */
 /* -------------------------------------------------------------------- */
     if( OGR_SWAP( eByteOrder ) )
     {
-        for( i = 0; i < nPointCount; i++ )
+        for( int i = 0; i < nPointCount; i++ )
         {
             CPL_SWAPDOUBLE( &(paoPoints[i].x) );
             CPL_SWAPDOUBLE( &(paoPoints[i].y) );
 
-            if( b3D )
+            if( flags & OGR_G_3D )
+            {
+                CPL_SWAPDOUBLE( padfZ + i );
+            }
+            if( flags & OGR_G_MEASURED )
             {
                 CPL_SWAPDOUBLE( padfZ + i );
             }
@@ -221,7 +293,7 @@ OGRErr OGRLinearRing::_importFromWkb( OGRwkbByteOrder eByteOrder, int b3D,
 /*      exportToWkb() METHOD!                                           */
 /************************************************************************/
 
-OGRErr  OGRLinearRing::_exportToWkb( OGRwkbByteOrder eByteOrder, int b3D,
+OGRErr  OGRLinearRing::_exportToWkb( OGRwkbByteOrder eByteOrder, int _flags,
                                      unsigned char * pabyData ) const
 
 {
@@ -235,7 +307,37 @@ OGRErr  OGRLinearRing::_exportToWkb( OGRwkbByteOrder eByteOrder, int b3D,
 /* -------------------------------------------------------------------- */
 /*      Copy in the raw data.                                           */
 /* -------------------------------------------------------------------- */
-    if( b3D )
+    if( (_flags & OGR_G_3D) && (_flags & OGR_G_MEASURED) )
+    {
+        nWords = 4 * nPointCount;
+        for( i = 0; i < nPointCount; i++ )
+        {
+            memcpy( pabyData+4+i*32, &(paoPoints[i].x), 8 );
+            memcpy( pabyData+4+i*32+8, &(paoPoints[i].y), 8 );
+            if( padfZ == NULL )
+                memset( pabyData+4+i*32+16, 0, 8 );
+            else
+                memcpy( pabyData+4+i*32+16, padfZ + i, 8 );
+            if( padfM == NULL )
+                memset( pabyData+4+i*32+24, 0, 8 );
+            else
+                memcpy( pabyData+4+i*32+24, padfM + i, 8 );
+        }
+    }
+    else if( _flags & OGR_G_MEASURED )
+    {
+        nWords = 3 * nPointCount;
+        for( i = 0; i < nPointCount; i++ )
+        {
+            memcpy( pabyData+4+i*24, &(paoPoints[i].x), 8 );
+            memcpy( pabyData+4+i*24+8, &(paoPoints[i].y), 8 );
+            if( padfM == NULL )
+                memset( pabyData+4+i*24+16, 0, 8 );
+            else
+                memcpy( pabyData+4+i*24+16, padfM + i, 8 );
+        }
+    }
+    else if( _flags & OGR_G_3D )
     {
         nWords = 3 * nPointCount;
         for( i = 0; i < nPointCount; i++ )
@@ -250,7 +352,7 @@ OGRErr  OGRLinearRing::_exportToWkb( OGRwkbByteOrder eByteOrder, int b3D,
     }
     else
     {
-        nWords = 2 * nPointCount; 
+        nWords = 2 * nPointCount;
         memcpy( pabyData+4, paoPoints, 16 * nPointCount );
     }
 
@@ -269,7 +371,7 @@ OGRErr  OGRLinearRing::_exportToWkb( OGRwkbByteOrder eByteOrder, int b3D,
             CPL_SWAPDOUBLE( pabyData + 4 + 8 * i );
         }
     }
-    
+
     return OGRERR_NONE;
 }
 
@@ -279,10 +381,12 @@ OGRErr  OGRLinearRing::_exportToWkb( OGRwkbByteOrder eByteOrder, int b3D,
 /*      Helper method for OGRPolygon.  NOT THE NORMAL WkbSize() METHOD! */
 /************************************************************************/
 
-int OGRLinearRing::_WkbSize( int b3D ) const
+int OGRLinearRing::_WkbSize( int _flags ) const
 
 {
-    if( b3D )
+    if( (_flags & OGR_G_3D) && (_flags & OGR_G_MEASURED) )
+        return 4 + 32 * nPointCount;
+    else if( (_flags & OGR_G_3D) || (_flags & OGR_G_MEASURED) )
         return 4 + 24 * nPointCount;
     else
         return 4 + 16 * nPointCount;
@@ -303,7 +407,8 @@ OGRGeometry *OGRLinearRing::clone() const
     poNewLinearRing = new OGRLinearRing();
     poNewLinearRing->assignSpatialReference( getSpatialReference() );
 
-    poNewLinearRing->setPoints( nPointCount, paoPoints, padfZ );
+    poNewLinearRing->setPoints( nPointCount, paoPoints, padfZ, padfM );
+    poNewLinearRing->flags = flags;
 
     return poNewLinearRing;
 }
@@ -315,7 +420,7 @@ OGRGeometry *OGRLinearRing::clone() const
 
 static const double EPSILON = 1E-5;
 
-static inline bool epsilonEqual(double a, double b, double eps) 
+static inline bool epsilonEqual(double a, double b, double eps)
 {
     return (::fabs(a - b) < eps);
 }
@@ -335,7 +440,7 @@ int OGRLinearRing::isClockwise() const
 {
     int    i, v, next;
     double  dx0, dy0, dx1, dy1, crossproduct;
-    int    bUseFallback = FALSE;
+    bool bUseFallback = false;
 
     if( nPointCount < 2 )
         return TRUE;
@@ -350,14 +455,14 @@ int OGRLinearRing::isClockwise() const
                paoPoints[i].x > paoPoints[v].x ) )
         {
             v = i;
-            bUseFallback = FALSE;
+            bUseFallback = false;
         }
         else if ( paoPoints[i].y == paoPoints[v].y &&
                   paoPoints[i].x == paoPoints[v].x )
         {
             /* Two vertex with same coordinates are the lowest rightmost */
             /* vertex! We cannot use that point as the pivot (#5342) */
-            bUseFallback = TRUE;
+            bUseFallback = true;
         }
     }
 
@@ -373,13 +478,12 @@ int OGRLinearRing::isClockwise() const
     {
         /* Don't try to be too clever by retrying with a next point */
         /* This can lead to false results as in the case of #3356 */
-        bUseFallback = TRUE;
+        bUseFallback = true;
     }
 
     dx0 = paoPoints[next].x - paoPoints[v].x;
     dy0 = paoPoints[next].y - paoPoints[v].y;
-    
-    
+
     /* following */
     next = v + 1;
     if ( next >= nPointCount - 1 )
@@ -392,7 +496,7 @@ int OGRLinearRing::isClockwise() const
     {
         /* Don't try to be too clever by retrying with a next point */
         /* This can lead to false results as in the case of #3356 */
-        bUseFallback = TRUE;
+        bUseFallback = true;
     }
 
     dx1 = paoPoints[next].x - paoPoints[v].x;
@@ -407,12 +511,12 @@ int OGRLinearRing::isClockwise() const
         else if ( crossproduct < 0 )  /* CW */
             return TRUE;
     }
-    
+
     /* ok, this is a degenerate case : the extent of the polygon is less than EPSILON */
     /* or 2 nearly identical points were found */
     /* Try with Green Formula as a fallback, but this is not a guarantee */
     /* as we'll probably be affected by numerical instabilities */
-    
+
     double dfSum = paoPoints[0].x * (paoPoints[1].y - paoPoints[nPointCount-1].y);
 
     for (i=1; i<nPointCount-1; i++) {
@@ -424,25 +528,25 @@ int OGRLinearRing::isClockwise() const
     return dfSum < 0;
 }
 
-/************************************************************************/ 
-/*                             reverseWindingOrder()                    */ 
-/************************************************************************/ 
+/************************************************************************/
+/*                             reverseWindingOrder()                    */
+/************************************************************************/
 
-void OGRLinearRing::reverseWindingOrder() 
+void OGRLinearRing::reverseWindingOrder()
 
-{ 
-    int pos = 0; 
-    OGRPoint pointA, pointB; 
+{
+    int pos = 0;
+    OGRPoint pointA, pointB;
 
-    for( int i = 0; i < nPointCount / 2; i++ ) 
-    { 
-        getPoint( i, &pointA ); 
+    for( int i = 0; i < nPointCount / 2; i++ )
+    {
+        getPoint( i, &pointA );
         pos = nPointCount - i - 1;
         getPoint( pos, &pointB );
         setPoint( i, &pointB );
         setPoint( pos, &pointA );
     }
-} 
+}
 
 /************************************************************************/
 /*                             closeRing()                              */
@@ -454,7 +558,7 @@ void OGRLinearRing::closeRings()
     if( nPointCount < 2 )
         return;
 
-    if( getX(0) != getX(nPointCount-1) 
+    if( getX(0) != getX(nPointCount-1)
         || getY(0) != getY(nPointCount-1)
         || getZ(0) != getZ(nPointCount-1) )
     {
@@ -504,7 +608,7 @@ OGRBoolean OGRLinearRing::isPointInRing(const OGRPoint* poPoint, int bTestEnvelo
     double prev_diff_x = getX(0) - dfTestX;
     double prev_diff_y = getY(0) - dfTestY;
 
-    for ( int iPoint = 1; iPoint < iNumPoints; iPoint++ ) 
+    for ( int iPoint = 1; iPoint < iNumPoints; iPoint++ )
     {
         const double x1 = getX(iPoint) - dfTestX;
         const double y1 = getY(iPoint) - dfTestY;
@@ -568,7 +672,7 @@ OGRBoolean OGRLinearRing::isPointOnRingBoundary(const OGRPoint* poPoint, int bTe
     double prev_diff_x = getX(0) - dfTestX;
     double prev_diff_y = getY(0) - dfTestY;
 
-    for ( int iPoint = 1; iPoint < iNumPoints; iPoint++ ) 
+    for ( int iPoint = 1; iPoint < iNumPoints; iPoint++ )
     {
         const double x1 = getX(iPoint) - dfTestX;
         const double y1 = getY(iPoint) - dfTestY;
@@ -576,10 +680,11 @@ OGRBoolean OGRLinearRing::isPointOnRingBoundary(const OGRPoint* poPoint, int bTe
         const double x2 = prev_diff_x;
         const double y2 = prev_diff_y;
 
-        /* If the point is on the segment, return immediatly */
+        /* If the point is on the segment, return immediately. */
         /* FIXME? If the test point is not exactly identical to one of */
         /* the vertices of the ring, but somewhere on a segment, there's */
-        /* little chance that we get 0. So that should be tested against some epsilon */
+        /* little chance that we get 0. So that should be tested against some */
+        /* epsilon. */
 
         if ( x1 * y2 - x2 * y1 == 0 )
         {
@@ -605,7 +710,7 @@ OGRBoolean OGRLinearRing::isPointOnRingBoundary(const OGRPoint* poPoint, int bTe
  * \brief Cast to line string.
  *
  * The passed in geometry is consumed and a new one returned .
- * 
+ *
  * @param poLR the input geometry - ownership is passed to the method.
  * @return new geometry.
  */
diff --git a/ogr/ogrlinestring.cpp b/ogr/ogrlinestring.cpp
index 1718db2..c8cd107 100644
--- a/ogr/ogrlinestring.cpp
+++ b/ogr/ogrlinestring.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrlinestring.cpp 29330 2015-06-14 12:11:11Z rouault $
+ * $Id: ogrlinestring.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRSimpleCurve and OGRLineString geometry classes.
@@ -33,18 +33,37 @@
 #include <assert.h>
 #include "ogr_geos.h"
 
-CPL_CVSID("$Id: ogrlinestring.cpp 29330 2015-06-14 12:11:11Z rouault $");
+CPL_CVSID("$Id: ogrlinestring.cpp 33631 2016-03-04 06:28:09Z goatbar $");
 
 /************************************************************************/
 /*                           OGRSimpleCurve()                           */
 /************************************************************************/
 
-OGRSimpleCurve::OGRSimpleCurve()
+OGRSimpleCurve::OGRSimpleCurve() :
+    nPointCount(0), paoPoints(NULL), padfZ(NULL), padfM(NULL)
+{ }
 
+/************************************************************************/
+/*                OGRSimpleCurve( const OGRSimpleCurve& )               */
+/************************************************************************/
+
+/**
+ * \brief Copy constructor.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the constructor
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRSimpleCurve::OGRSimpleCurve( const OGRSimpleCurve& other ) :
+    OGRCurve( other ),
+    nPointCount( 0 ),
+    paoPoints( NULL ),
+    padfZ( NULL ),
+    padfM( NULL )
 {
-    nPointCount = 0;
-    paoPoints = NULL;
-    padfZ = NULL;
+    setPoints( other.nPointCount, other.paoPoints, other.padfZ, other.padfM );
 }
 
 /************************************************************************/
@@ -58,6 +77,32 @@ OGRSimpleCurve::~OGRSimpleCurve()
         OGRFree( paoPoints );
     if( padfZ != NULL )
         OGRFree( padfZ );
+    if( padfM != NULL )
+        OGRFree( padfM );
+}
+
+/************************************************************************/
+/*                       operator=( const OGRPoint& )                   */
+/************************************************************************/
+
+/**
+ * \brief Assignment operator.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the operator
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRSimpleCurve& OGRSimpleCurve::operator=( const OGRSimpleCurve& other )
+{
+    if( this != &other)
+    {
+        OGRCurve::operator=( other );
+
+        setPoints( other.nPointCount, other.paoPoints, other.padfZ, other.padfM );
+    }
+    return *this;
 }
 
 /************************************************************************/
@@ -68,6 +113,7 @@ void OGRSimpleCurve::flattenTo2D()
 
 {
     Make2D();
+    setMeasured(FALSE);
 }
 
 /************************************************************************/
@@ -77,16 +123,23 @@ void OGRSimpleCurve::flattenTo2D()
 OGRGeometry *OGRSimpleCurve::clone() const
 
 {
-    OGRLineString       *poNewLineString;
+    OGRSimpleCurve       *poCurve;
 
-    poNewLineString = (OGRLineString*)
+    poCurve = (OGRSimpleCurve*)
             OGRGeometryFactory::createGeometry(getGeometryType());
+    if( poCurve == NULL )
+        return NULL;
 
-    poNewLineString->assignSpatialReference( getSpatialReference() );
-    poNewLineString->setPoints( nPointCount, paoPoints, padfZ );
-    poNewLineString->setCoordinateDimension( getCoordinateDimension() );
-    
-    return poNewLineString;
+    poCurve->assignSpatialReference( getSpatialReference() );
+    poCurve->setPoints( nPointCount, paoPoints, padfZ, padfM );
+    if( poCurve->getNumPoints() != nPointCount )
+    {
+        delete poCurve;
+        return NULL;
+    }
+    poCurve->flags = flags;
+
+    return poCurve;
 }
 
 /************************************************************************/
@@ -106,11 +159,29 @@ void OGRSimpleCurve::empty()
 void OGRSimpleCurve::setCoordinateDimension( int nNewDimension )
 
 {
-    nCoordDimension = nNewDimension;
     if( nNewDimension == 2 )
         Make2D();
     else if( nNewDimension == 3 )
         Make3D();
+    setMeasured(FALSE);
+}
+
+void OGRSimpleCurve::set3D( OGRBoolean bIs3D )
+
+{
+    if (bIs3D)
+        Make3D();
+    else
+        Make2D();
+}
+
+void OGRSimpleCurve::setMeasured( OGRBoolean bIsMeasured )
+
+{
+    if (bIsMeasured)
+        AddM();
+    else
+        RemoveM();
 }
 
 /************************************************************************/
@@ -123,7 +194,7 @@ void OGRSimpleCurve::setCoordinateDimension( int nNewDimension )
 int OGRSimpleCurve::WkbSize() const
 
 {
-    return 5 + 4 + 8 * nPointCount * getCoordinateDimension();
+    return 5 + 4 + 8 * nPointCount * CoordinateDimension();
 }
 
 /************************************************************************/
@@ -138,7 +209,7 @@ void OGRSimpleCurve::Make2D()
         OGRFree( padfZ );
         padfZ = NULL;
     }
-    nCoordDimension = 2;
+    flags &= ~OGR_G_3D;
 }
 
 /************************************************************************/
@@ -151,11 +222,57 @@ void OGRSimpleCurve::Make3D()
     if( padfZ == NULL )
     {
         if( nPointCount == 0 )
-            padfZ = (double *) OGRCalloc(sizeof(double),1);
+            padfZ = (double *) VSI_CALLOC_VERBOSE(sizeof(double),1);
+        else
+            padfZ = (double *) VSI_CALLOC_VERBOSE(sizeof(double),nPointCount);
+        if( padfZ == NULL )
+        {
+            flags &= ~OGR_G_3D;
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "OGRSimpleCurve::Make3D() failed");
+            return;
+        }
+    }
+    flags |= OGR_G_3D;
+}
+
+/************************************************************************/
+/*                               RemoveM()                              */
+/************************************************************************/
+
+void OGRSimpleCurve::RemoveM()
+
+{
+    if( padfM != NULL )
+    {
+        OGRFree( padfM );
+        padfM = NULL;
+    }
+    flags &= ~OGR_G_MEASURED;
+}
+
+/************************************************************************/
+/*                               AddM()                                 */
+/************************************************************************/
+
+void OGRSimpleCurve::AddM()
+
+{
+    if( padfM == NULL )
+    {
+        if( nPointCount == 0 )
+            padfM = (double *) VSI_CALLOC_VERBOSE(sizeof(double),1);
         else
-            padfZ = (double *) OGRCalloc(sizeof(double),nPointCount);
+            padfM = (double *) VSI_CALLOC_VERBOSE(sizeof(double),nPointCount);
+        if( padfM == NULL )
+        {
+            flags &= ~OGR_G_MEASURED;
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "OGRSimpleCurve::AddM() failed");
+            return;
+        }
     }
-    nCoordDimension = 3;
+    flags |= OGR_G_MEASURED;
 }
 
 /************************************************************************/
@@ -181,8 +298,10 @@ void    OGRSimpleCurve::getPoint( int i, OGRPoint * poPoint ) const
     poPoint->setX( paoPoints[i].x );
     poPoint->setY( paoPoints[i].y );
 
-    if( getCoordinateDimension() == 3 && padfZ != NULL )
+    if( (flags & OGR_G_3D) && padfZ != NULL )
         poPoint->setZ( padfZ[i] );
+    if( (flags & OGR_G_MEASURED) && padfM != NULL )
+        poPoint->setM( padfM[i] );
 }
 
 /**
@@ -190,7 +309,7 @@ void    OGRSimpleCurve::getPoint( int i, OGRPoint * poPoint ) const
  *
  * \brief Fetch vertex count.
  *
- * Returns the number of vertices in the line string.  
+ * Returns the number of vertices in the line string.
  *
  * @return vertex count.
  */
@@ -203,7 +322,7 @@ void    OGRSimpleCurve::getPoint( int i, OGRPoint * poPoint ) const
  * Returns the X value at the indicated vertex.   If iVertex is out of range a
  * crash may occur, no internal range checking is performed.
  *
- * @param iVertex the vertex to return, between 0 and getNumPoints()-1. 
+ * @param iVertex the vertex to return, between 0 and getNumPoints()-1.
  *
  * @return X value.
  */
@@ -216,7 +335,7 @@ void    OGRSimpleCurve::getPoint( int i, OGRPoint * poPoint ) const
  * Returns the Y value at the indicated vertex.   If iVertex is out of range a
  * crash may occur, no internal range checking is performed.
  *
- * @param iVertex the vertex to return, between 0 and getNumPoints()-1. 
+ * @param iVertex the vertex to return, between 0 and getNumPoints()-1.
  *
  * @return X value.
  */
@@ -232,7 +351,7 @@ void    OGRSimpleCurve::getPoint( int i, OGRPoint * poPoint ) const
  * value is available, 0.0 is returned.  If iVertex is out of range a
  * crash may occur, no internal range checking is performed.
  *
- * @param iVertex the vertex to return, between 0 and getNumPoints()-1. 
+ * @param iVertex the vertex to return, between 0 and getNumPoints()-1.
  *
  * @return Z value.
  */
@@ -240,14 +359,40 @@ void    OGRSimpleCurve::getPoint( int i, OGRPoint * poPoint ) const
 double OGRSimpleCurve::getZ( int iVertex ) const
 
 {
-    if( padfZ != NULL && iVertex >= 0 && iVertex < nPointCount 
-        && nCoordDimension >= 3 )
+    if( padfZ != NULL && iVertex >= 0 && iVertex < nPointCount
+        && (flags & OGR_G_3D) )
         return( padfZ[iVertex] );
     else
         return 0.0;
 }
 
 /************************************************************************/
+/*                                getM()                                */
+/************************************************************************/
+
+/**
+ * \brief Get measure at vertex.
+ *
+ * Returns the M (measure) value at the indicated vertex.  If no M
+ * value is available, 0.0 is returned.  If iVertex is out of range a
+ * crash may occur, no internal range checking is performed.
+ *
+ * @param iVertex the vertex to return, between 0 and getNumPoints()-1.
+ *
+ * @return M value.
+ */
+
+double OGRSimpleCurve::getM( int iVertex ) const
+
+{
+    if( padfM != NULL && iVertex >= 0 && iVertex < nPointCount
+        && (flags & OGR_G_MEASURED) )
+        return( padfM[iVertex] );
+    else
+        return 0.0;
+}
+
+/************************************************************************/
 /*                            setNumPoints()                            */
 /************************************************************************/
 
@@ -256,24 +401,31 @@ double OGRSimpleCurve::getZ( int iVertex ) const
  *
  * This method primary exists to preset the number of points in a linestring
  * geometry before setPoint() is used to assign them to avoid reallocating
- * the array larger with each call to addPoint(). 
+ * the array larger with each call to addPoint().
  *
  * This method has no SFCOM analog.
  *
  * @param nNewPointCount the new number of points for geometry.
+ * @param bZeroizeNewContent whether to set to zero the new elements of arrays
+ *                           that are extended.
  */
 
 void OGRSimpleCurve::setNumPoints( int nNewPointCount, int bZeroizeNewContent )
 
 {
+    CPLAssert( nNewPointCount >= 0 );
+
     if( nNewPointCount == 0 )
     {
         OGRFree( paoPoints );
         paoPoints = NULL;
-        
+
         OGRFree( padfZ );
         padfZ = NULL;
-        
+
+        OGRFree( padfM );
+        padfM = NULL;
+
         nPointCount = 0;
         return;
     }
@@ -281,27 +433,23 @@ void OGRSimpleCurve::setNumPoints( int nNewPointCount, int bZeroizeNewContent )
     if( nNewPointCount > nPointCount )
     {
         OGRRawPoint* paoNewPoints = (OGRRawPoint *)
-            VSIRealloc(paoPoints, sizeof(OGRRawPoint) * nNewPointCount);
+            VSI_REALLOC_VERBOSE(paoPoints, sizeof(OGRRawPoint) * nNewPointCount);
         if (paoNewPoints == NULL)
         {
-            CPLError(CE_Failure, CPLE_OutOfMemory,
-                     "Could not allocate array for %d points", nNewPointCount);
             return;
         }
         paoPoints = paoNewPoints;
-        
+
         if( bZeroizeNewContent )
             memset( paoPoints + nPointCount,
                 0, sizeof(OGRRawPoint) * (nNewPointCount - nPointCount) );
-        
-        if( getCoordinateDimension() == 3 )
+
+        if( flags & OGR_G_3D )
         {
             double* padfNewZ = (double *)
-                VSIRealloc( padfZ, sizeof(double)*nNewPointCount );
+                VSI_REALLOC_VERBOSE( padfZ, sizeof(double)*nNewPointCount );
             if (padfNewZ == NULL)
             {
-                CPLError(CE_Failure, CPLE_OutOfMemory,
-                     "Could not allocate array for %d points", nNewPointCount);
                 return;
             }
             padfZ = padfNewZ;
@@ -309,6 +457,20 @@ void OGRSimpleCurve::setNumPoints( int nNewPointCount, int bZeroizeNewContent )
                 memset( padfZ + nPointCount, 0,
                     sizeof(double) * (nNewPointCount - nPointCount) );
         }
+
+        if( flags & OGR_G_MEASURED )
+        {
+            double* padfNewM = (double *)
+                VSI_REALLOC_VERBOSE( padfM, sizeof(double)*nNewPointCount );
+            if (padfNewM == NULL)
+            {
+                return;
+            }
+            padfM = padfNewM;
+            if( bZeroizeNewContent )
+                memset( padfM + nPointCount, 0,
+                    sizeof(double) * (nNewPointCount - nPointCount) );
+        }
     }
 
     nPointCount = nNewPointCount;
@@ -326,7 +488,7 @@ void OGRSimpleCurve::setNumPoints( int nNewPointCount, int bZeroizeNewContent )
  * accommodate the request.
  *
  * There is no SFCOM analog to this method.
- * 
+ *
  * @param iPoint the index of the vertex to assign (zero based).
  * @param poPoint the value to assign to the vertex.
  */
@@ -334,10 +496,14 @@ void OGRSimpleCurve::setNumPoints( int nNewPointCount, int bZeroizeNewContent )
 void OGRSimpleCurve::setPoint( int iPoint, OGRPoint * poPoint )
 
 {
-    if (poPoint->getCoordinateDimension() < 3)
-        setPoint( iPoint, poPoint->getX(), poPoint->getY() );
-    else
+    if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
+        setPoint( iPoint, poPoint->getX(), poPoint->getY(), poPoint->getM() );
+    else if( flags & OGR_G_MEASURED )
+        setPointM( iPoint, poPoint->getX(), poPoint->getY(), poPoint->getM() );
+    else if( flags & OGR_G_3D )
         setPoint( iPoint, poPoint->getX(), poPoint->getY(), poPoint->getZ() );
+    else
+        setPoint( iPoint, poPoint->getX(), poPoint->getY() );
 }
 
 /************************************************************************/
@@ -350,7 +516,7 @@ void OGRSimpleCurve::setPoint( int iPoint, OGRPoint * poPoint )
  * If iPoint is larger than the number of necessary the number of existing
  * points in the line string, the point count will be increased to
  * accommodate the request.
- * 
+ *
  * There is no SFCOM analog to this method.
  *
  * @param iPoint the index of the vertex to assign (zero based).
@@ -362,7 +528,7 @@ void OGRSimpleCurve::setPoint( int iPoint, OGRPoint * poPoint )
 void OGRSimpleCurve::setPoint( int iPoint, double xIn, double yIn, double zIn )
 
 {
-    if( getCoordinateDimension() == 2 )
+    if( !(flags & OGR_G_3D) )
         Make3D();
 
     if( iPoint >= nPointCount )
@@ -371,18 +537,75 @@ void OGRSimpleCurve::setPoint( int iPoint, double xIn, double yIn, double zIn )
         if (nPointCount < iPoint + 1)
             return;
     }
+#ifdef DEBUG
+    if( paoPoints == NULL )
+        return;
+#endif
 
     paoPoints[iPoint].x = xIn;
     paoPoints[iPoint].y = yIn;
 
-    if( zIn != 0.0 )
+    if( padfZ != NULL )
     {
+        padfZ[iPoint] = zIn;
+    }
+}
+
+void OGRSimpleCurve::setPointM( int iPoint, double xIn, double yIn, double mIn )
+
+{
+    if( !(flags & OGR_G_MEASURED) )
+        AddM();
+
+    if( iPoint >= nPointCount )
+    {
+        setNumPoints( iPoint+1 );
+        if (nPointCount < iPoint + 1)
+            return;
+    }
+#ifdef DEBUG
+    if( paoPoints == NULL )
+        return;
+#endif
+
+    paoPoints[iPoint].x = xIn;
+    paoPoints[iPoint].y = yIn;
+
+    if( padfM != NULL )
+    {
+        padfM[iPoint] = mIn;
+    }
+}
+
+void OGRSimpleCurve::setPoint( int iPoint, double xIn, double yIn, double zIn, double mIn )
+
+{
+    if( !(flags & OGR_G_3D) )
         Make3D();
+    if( !(flags & OGR_G_MEASURED) )
+        AddM();
+
+    if( iPoint >= nPointCount )
+    {
+        setNumPoints( iPoint+1 );
+        if (nPointCount < iPoint + 1)
+            return;
+    }
+#ifdef DEBUG
+    if( paoPoints == NULL )
+        return;
+#endif
+
+    paoPoints[iPoint].x = xIn;
+    paoPoints[iPoint].y = yIn;
+
+    if( padfZ != NULL )
+    {
         padfZ[iPoint] = zIn;
     }
-    else if( getCoordinateDimension() == 3 )
+    if( padfM != NULL )
     {
-        padfZ[iPoint] = 0.0;
+        padfM[iPoint] = mIn;
     }
 }
 
@@ -416,11 +639,31 @@ void OGRSimpleCurve::setZ( int iPoint, double zIn )
             return;
     }
 
-    if( padfZ )
+    if( padfZ != NULL )
         padfZ[iPoint] = zIn;
 }
 
 /************************************************************************/
+/*                                setM()                                */
+/************************************************************************/
+
+void OGRSimpleCurve::setM( int iPoint, double mIn )
+{
+    if( !(flags & OGR_G_MEASURED) )
+        AddM();
+
+    if( iPoint >= nPointCount )
+    {
+        setNumPoints( iPoint+1 );
+        if (nPointCount < iPoint + 1)
+            return;
+    }
+
+    if( padfM != NULL )
+        padfM[iPoint] = mIn;
+}
+
+/************************************************************************/
 /*                              addPoint()                              */
 /************************************************************************/
 
@@ -461,6 +704,12 @@ void OGRSimpleCurve::addPoint( OGRPoint * poPoint )
  * @param z the Z coordinate to assign to the new point (defaults to zero).
  */
 
+void OGRSimpleCurve::addPoint( double x, double y, double z, double m )
+
+{
+    setPoint( nPointCount, x, y, z, m );
+}
+
 void OGRSimpleCurve::addPoint( double x, double y, double z )
 
 {
@@ -473,6 +722,136 @@ void OGRSimpleCurve::addPoint( double x, double y )
     setPoint( nPointCount, x, y );
 }
 
+/**
+ * \brief Add a point to a line string.
+ *
+ * The vertex count of the line string is increased by one, and assigned from
+ * the passed location value.
+ *
+ * There is no SFCOM analog to this method.
+ *
+ * @param x the X coordinate to assign to the new point.
+ * @param y the Y coordinate to assign to the new point.
+ * @param m the M coordinate to assign to the new point.
+ */
+
+void OGRSimpleCurve::addPointM( double x, double y, double m )
+
+{
+    setPointM( nPointCount, x, y, m );
+}
+
+/************************************************************************/
+/*                             setPointsM()                             */
+/************************************************************************/
+
+/**
+ * \brief Assign all points in a line string.
+ *
+ * This method clears any existing points assigned to this line string,
+ * and assigns a whole new set.  It is the most efficient way of assigning
+ * the value of a line string.
+ *
+ * There is no SFCOM analog to this method.
+ *
+ * @param nPointsIn number of points being passed in paoPointsIn
+ * @param paoPointsIn list of points being assigned.
+ * @param padfM the M values that go with the points.
+ */
+
+void OGRSimpleCurve::setPointsM( int nPointsIn, OGRRawPoint * paoPointsIn,
+                                 double * padfMIn )
+
+{
+    setNumPoints( nPointsIn, FALSE );
+    if (nPointCount < nPointsIn
+#ifdef DEBUG
+        || paoPoints == NULL
+#endif
+        )
+        return;
+
+    if( nPointsIn )
+        memcpy( paoPoints, paoPointsIn, sizeof(OGRRawPoint) * nPointsIn);
+
+/* -------------------------------------------------------------------- */
+/*      Check measures.                                                 */
+/* -------------------------------------------------------------------- */
+    if( padfMIn == NULL && (flags & OGR_G_MEASURED) )
+    {
+        RemoveM();
+    }
+    else if( padfMIn )
+    {
+        AddM();
+        if( padfM && nPointsIn )
+            memcpy( padfM, padfMIn, sizeof(double) * nPointsIn );
+    }
+}
+
+/************************************************************************/
+/*                             setPoints()                              */
+/************************************************************************/
+
+/**
+ * \brief Assign all points in a line string.
+ *
+ * This method clears any existing points assigned to this line string,
+ * and assigns a whole new set.  It is the most efficient way of assigning
+ * the value of a line string.
+ *
+ * There is no SFCOM analog to this method.
+ *
+ * @param nPointsIn number of points being passed in paoPointsIn
+ * @param paoPointsIn list of points being assigned.
+ * @param padfZ the Z values that go with the points.
+ * @param padfM the M values that go with the points.
+ */
+
+void OGRSimpleCurve::setPoints( int nPointsIn, OGRRawPoint * paoPointsIn,
+                                double * padfZIn, double * padfMIn )
+
+{
+    setNumPoints( nPointsIn, FALSE );
+    if (nPointCount < nPointsIn
+#ifdef DEBUG
+        || paoPoints == NULL
+#endif
+        )
+        return;
+
+    if( nPointsIn )
+        memcpy( paoPoints, paoPointsIn, sizeof(OGRRawPoint) * nPointsIn);
+
+/* -------------------------------------------------------------------- */
+/*      Check 2D/3D.                                                    */
+/* -------------------------------------------------------------------- */
+    if( padfZIn == NULL && getCoordinateDimension() > 2 )
+    {
+        Make2D();
+    }
+    else if( padfZIn )
+    {
+        Make3D();
+        if( padfZ && nPointsIn )
+            memcpy( padfZ, padfZIn, sizeof(double) * nPointsIn );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Check measures.                                                 */
+/* -------------------------------------------------------------------- */
+    if( padfMIn == NULL && (flags & OGR_G_MEASURED) )
+    {
+        RemoveM();
+    }
+    else if( padfMIn )
+    {
+        AddM();
+        if( padfM && nPointsIn )
+            memcpy( padfM, padfMIn, sizeof(double) * nPointsIn );
+    }
+}
+
 /************************************************************************/
 /*                             setPoints()                              */
 /************************************************************************/
@@ -492,26 +871,32 @@ void OGRSimpleCurve::addPoint( double x, double y )
  */
 
 void OGRSimpleCurve::setPoints( int nPointsIn, OGRRawPoint * paoPointsIn,
-                               double * padfZ )
+                               double * padfZIn )
 
 {
     setNumPoints( nPointsIn, FALSE );
-    if (nPointCount < nPointsIn)
+    if (nPointCount < nPointsIn
+#ifdef DEBUG
+        || paoPoints == NULL
+#endif
+        )
         return;
 
-    memcpy( paoPoints, paoPointsIn, sizeof(OGRRawPoint) * nPointsIn);
+    if( nPointsIn )
+        memcpy( paoPoints, paoPointsIn, sizeof(OGRRawPoint) * nPointsIn);
 
 /* -------------------------------------------------------------------- */
 /*      Check 2D/3D.                                                    */
 /* -------------------------------------------------------------------- */
-    if( padfZ == NULL && getCoordinateDimension() > 2 )
+    if( padfZIn == NULL && getCoordinateDimension() > 2 )
     {
         Make2D();
     }
-    else if( padfZ )
+    else if( padfZIn )
     {
         Make3D();
-        memcpy( this->padfZ, padfZ, sizeof(double) * nPointsIn );
+        if( padfZ && nPointsIn )
+            memcpy( padfZ, padfZIn, sizeof(double) * nPointsIn );
     }
 }
 
@@ -535,19 +920,128 @@ void OGRSimpleCurve::setPoints( int nPointsIn, OGRRawPoint * paoPointsIn,
  */
 
 void OGRSimpleCurve::setPoints( int nPointsIn, double * padfX, double * padfY,
-                               double * padfZ )
+                                double * padfZIn )
 
 {
-    int         i;
+/* -------------------------------------------------------------------- */
+/*      Check 2D/3D.                                                    */
+/* -------------------------------------------------------------------- */
+    if( padfZIn == NULL )
+        Make2D();
+    else
+        Make3D();
+
+/* -------------------------------------------------------------------- */
+/*      Assign values.                                                  */
+/* -------------------------------------------------------------------- */
+    setNumPoints( nPointsIn, FALSE );
+    if (nPointCount < nPointsIn)
+        return;
+
+    for( int i = 0; i < nPointsIn; i++ )
+    {
+        paoPoints[i].x = padfX[i];
+        paoPoints[i].y = padfY[i];
+    }
+
+    if( padfZ == NULL || !padfZIn || !nPointsIn )
+    {
+        return;
+    }
+
+    memcpy( padfZ, padfZIn, sizeof(double) * nPointsIn );
+}
+
+/************************************************************************/
+/*                             setPointsM()                             */
+/************************************************************************/
 
+/**
+ * \brief Assign all points in a line string.
+ *
+ * This method clear any existing points assigned to this line string,
+ * and assigns a whole new set.
+ *
+ * There is no SFCOM analog to this method.
+ *
+ * @param nPointsIn number of points being passed in padfX and padfY.
+ * @param padfX list of X coordinates of points being assigned.
+ * @param padfY list of Y coordinates of points being assigned.
+ * @param padfM list of M coordinates of points being assigned.
+ */
+
+void OGRSimpleCurve::setPointsM( int nPointsIn, double * padfX, double * padfY,
+                                 double * padfMIn )
+
+{
 /* -------------------------------------------------------------------- */
 /*      Check 2D/3D.                                                    */
 /* -------------------------------------------------------------------- */
-    if( padfZ == NULL )
+    if( padfMIn == NULL )
+        RemoveM();
+    else
+        AddM();
+
+/* -------------------------------------------------------------------- */
+/*      Assign values.                                                  */
+/* -------------------------------------------------------------------- */
+    setNumPoints( nPointsIn, FALSE );
+    if (nPointCount < nPointsIn)
+        return;
+
+    for( int i = 0; i < nPointsIn; i++ )
+    {
+        paoPoints[i].x = padfX[i];
+        paoPoints[i].y = padfY[i];
+    }
+
+    if( padfMIn == NULL || !padfM || !nPointsIn )
+    {
+        return;
+    }
+
+    memcpy( padfM, padfMIn, sizeof(double) * nPointsIn );
+}
+
+/************************************************************************/
+/*                             setPoints()                              */
+/************************************************************************/
+
+/**
+ * \brief Assign all points in a line string.
+ *
+ * This method clear any existing points assigned to this line string,
+ * and assigns a whole new set.
+ *
+ * There is no SFCOM analog to this method.
+ *
+ * @param nPointsIn number of points being passed in padfX and padfY.
+ * @param padfX list of X coordinates of points being assigned.
+ * @param padfY list of Y coordinates of points being assigned.
+ * @param padfZ list of Z coordinates of points being assigned.
+ * @param padfM list of M coordinates of points being assigned.
+ */
+
+void OGRSimpleCurve::setPoints( int nPointsIn, double * padfX, double * padfY,
+                                double * padfZIn, double * padfMIn )
+
+{
+/* -------------------------------------------------------------------- */
+/*      Check 2D/3D.                                                    */
+/* -------------------------------------------------------------------- */
+    if( padfZIn == NULL )
         Make2D();
     else
         Make3D();
-    
+
+/* -------------------------------------------------------------------- */
+/*      Check measures.                                                 */
+/* -------------------------------------------------------------------- */
+    if( padfMIn == NULL )
+        RemoveM();
+    else
+        AddM();
+
 /* -------------------------------------------------------------------- */
 /*      Assign values.                                                  */
 /* -------------------------------------------------------------------- */
@@ -555,14 +1049,16 @@ void OGRSimpleCurve::setPoints( int nPointsIn, double * padfX, double * padfY,
     if (nPointCount < nPointsIn)
         return;
 
-    for( i = 0; i < nPointsIn; i++ )
+    for( int i = 0; i < nPointsIn; i++ )
     {
         paoPoints[i].x = padfX[i];
         paoPoints[i].y = padfY[i];
     }
 
-    if( this->padfZ != NULL )
-        memcpy( this->padfZ, padfZ, sizeof(double) * nPointsIn );
+    if( padfZ != NULL && padfZIn && nPointsIn )
+        memcpy( padfZ, padfZIn, sizeof(double) * nPointsIn );
+    if( padfM != NULL && padfMIn && nPointsIn )
+        memcpy( padfM, padfMIn, sizeof(double) * nPointsIn );
 }
 
 /************************************************************************/
@@ -579,25 +1075,25 @@ void OGRSimpleCurve::setPoints( int nPointsIn, double * padfX, double * padfY,
  * There is no SFCOM analog to this method.
  *
  * @param paoPointsOut a buffer into which the points is written.
- * @param padfZ the Z values that go with the points (optional, may be NULL).
+ * @param padfZOut the Z values that go with the points (optional, may be NULL).
  */
 
-void OGRSimpleCurve::getPoints( OGRRawPoint * paoPointsOut, double * padfZ ) const
+void OGRSimpleCurve::getPoints( OGRRawPoint * paoPointsOut, double * padfZOut ) const
 {
-    if ( ! paoPointsOut )
+    if ( ! paoPointsOut || nPointCount == 0 )
         return;
-        
+
     memcpy( paoPointsOut, paoPoints, sizeof(OGRRawPoint) * nPointCount );
 
 /* -------------------------------------------------------------------- */
 /*      Check 2D/3D.                                                    */
 /* -------------------------------------------------------------------- */
-    if( padfZ )
+    if( padfZOut )
     {
-        if ( this->padfZ )
-            memcpy( padfZ, this->padfZ, sizeof(double) * nPointCount );
+        if ( padfZ )
+            memcpy( padfZOut, padfZ, sizeof(double) * nPointCount );
         else
-            memset( padfZ, 0, sizeof(double) * nPointCount );
+            memset( padfZOut, 0, sizeof(double) * nPointCount );
     }
 }
 
@@ -610,7 +1106,7 @@ void OGRSimpleCurve::getPoints( OGRRawPoint * paoPointsOut, double * padfZ ) con
  * \brief Returns all points of line string.
  *
  * This method copies all points into user arrays. The user provides the
- * stride between 2 consecutives elements of the array.
+ * stride between 2 consecutive elements of the array.
  *
  * On some CPU architectures, care must be taken so that the arrays are properly aligned.
  *
@@ -660,15 +1156,51 @@ void OGRSimpleCurve::getPoints( void* pabyX, int nXStride,
     }
 }
 
+void OGRSimpleCurve::getPoints( void* pabyX, int nXStride,
+                                void* pabyY, int nYStride,
+                                void* pabyZ, int nZStride,
+                                void* pabyM, int nMStride)  const
+{
+    int i;
+    if (pabyX != NULL && nXStride == 0)
+        return;
+    if (pabyY != NULL && nYStride == 0)
+        return;
+    if (pabyZ != NULL && nZStride == 0)
+        return;
+    if (pabyM != NULL && nMStride == 0)
+        return;
+    for(i=0;i<nPointCount;i++)
+    {
+        if (pabyX) *(double*)((char*)pabyX + i * nXStride) = paoPoints[i].x;
+        if (pabyY) *(double*)((char*)pabyY + i * nYStride) = paoPoints[i].y;
+    }
+
+    if (pabyZ)
+    {
+        for(i=0;i<nPointCount;i++)
+        {
+            *(double*)((char*)pabyZ + i * nZStride) = (padfZ) ? padfZ[i] : 0.0;
+        }
+    }
+    if (pabyM)
+    {
+        for(i=0;i<nPointCount;i++)
+        {
+            *(double*)((char*)pabyM + i * nZStride) = (padfM) ? padfM[i] : 0.0;
+        }
+    }
+}
+
 /************************************************************************/
 /*                           reversePoints()                            */
 /************************************************************************/
 
 /**
- * \brief Reverse point order. 
+ * \brief Reverse point order.
  *
- * This method updates the points in this line string in place 
- * reversing the point ordering (first for last, etc).  
+ * This method updates the points in this line string in place
+ * reversing the point ordering (first for last, etc).
  */
 
 void OGRSimpleCurve::reversePoints()
@@ -702,16 +1234,16 @@ void OGRSimpleCurve::reversePoints()
  *
  * Adds the request range of vertices to the end of this line string
  * in an efficient manner.  If the nStartVertex is larger than the
- * nEndVertex then the vertices will be reversed as they are copied. 
+ * nEndVertex then the vertices will be reversed as they are copied.
  *
- * @param poOtherLine the other OGRLineString. 
+ * @param poOtherLine the other OGRLineString.
  * @param nStartVertex the first vertex to copy, defaults to 0 to start
- * with the first vertex in the other linestring. 
- * @param nEndVertex the last vertex to copy, defaults to -1 indicating 
- * the last vertex of the other line string. 
+ * with the first vertex in the other linestring.
+ * @param nEndVertex the last vertex to copy, defaults to -1 indicating
+ * the last vertex of the other line string.
  */
 
-void OGRSimpleCurve::addSubLineString( const OGRLineString *poOtherLine, 
+void OGRSimpleCurve::addSubLineString( const OGRLineString *poOtherLine,
                                       int nStartVertex, int nEndVertex )
 
 {
@@ -725,8 +1257,8 @@ void OGRSimpleCurve::addSubLineString( const OGRLineString *poOtherLine,
     if( nEndVertex == -1 )
         nEndVertex = nOtherLineNumPoints - 1;
 
-    if( nStartVertex < 0 || nEndVertex < 0 
-        || nStartVertex >= nOtherLineNumPoints 
+    if( nStartVertex < 0 || nEndVertex < 0
+        || nStartVertex >= nOtherLineNumPoints
         || nEndVertex >= nOtherLineNumPoints )
     {
         CPLAssert( FALSE );
@@ -740,7 +1272,11 @@ void OGRSimpleCurve::addSubLineString( const OGRLineString *poOtherLine,
     int nPointsToAdd = ABS(nEndVertex-nStartVertex) + 1;
 
     setNumPoints( nPointsToAdd + nOldPoints, FALSE );
-    if (nPointCount < nPointsToAdd + nOldPoints)
+    if (nPointCount < nPointsToAdd + nOldPoints
+#ifdef DEBUG
+        || paoPoints == NULL
+#endif
+        )
         return;
 
 /* -------------------------------------------------------------------- */
@@ -748,17 +1284,20 @@ void OGRSimpleCurve::addSubLineString( const OGRLineString *poOtherLine,
 /* -------------------------------------------------------------------- */
     if( nEndVertex >= nStartVertex )
     {
-        memcpy( paoPoints + nOldPoints, 
-                poOtherLine->paoPoints + nStartVertex, 
+        memcpy( paoPoints + nOldPoints,
+                poOtherLine->paoPoints + nStartVertex,
                 sizeof(OGRRawPoint) * nPointsToAdd );
         if( poOtherLine->padfZ != NULL )
         {
             Make3D();
-            memcpy( padfZ + nOldPoints, poOtherLine->padfZ + nStartVertex,
-                    sizeof(double) * nPointsToAdd );
+            if( padfZ != NULL )
+            {
+                memcpy( padfZ + nOldPoints, poOtherLine->padfZ + nStartVertex,
+                        sizeof(double) * nPointsToAdd );
+            }
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Copy the x/y points - reverse copies done double by double.     */
 /* -------------------------------------------------------------------- */
@@ -768,19 +1307,21 @@ void OGRSimpleCurve::addSubLineString( const OGRLineString *poOtherLine,
 
         for( i = 0; i < nPointsToAdd; i++ )
         {
-            paoPoints[i+nOldPoints].x = 
+            paoPoints[i+nOldPoints].x =
                 poOtherLine->paoPoints[nStartVertex-i].x;
-            paoPoints[i+nOldPoints].y = 
+            paoPoints[i+nOldPoints].y =
                 poOtherLine->paoPoints[nStartVertex-i].y;
         }
 
         if( poOtherLine->padfZ != NULL )
         {
             Make3D();
-
-            for( i = 0; i < nPointsToAdd; i++ )
+            if( padfZ != NULL )
             {
-                padfZ[i+nOldPoints] = poOtherLine->padfZ[nStartVertex-i];
+                for( i = 0; i < nPointsToAdd; i++ )
+                {
+                    padfZ[i+nOldPoints] = poOtherLine->padfZ[nStartVertex-i];
+                }
             }
         }
     }
@@ -809,14 +1350,14 @@ OGRErr OGRSimpleCurve::importFromWkb( unsigned char * pabyData,
                                                       16,
                                                       nNewNumPoints,
                                                       eWkbVariant );
-    if( eErr >= 0 )
+    if( eErr != OGRERR_NONE )
         return eErr;
 
     /* Check if the wkb stream buffer is big enough to store
      * fetched number of points.
-     * 16 or 24 - size of point structure
      */
-    int nPointSize = (getCoordinateDimension() == 3 ? 24 : 16);
+    int dim = CoordinateDimension();
+    int nPointSize = dim*sizeof(double);
     if (nNewNumPoints < 0 || nNewNumPoints > INT_MAX / nPointSize)
         return OGRERR_CORRUPT_DATA;
     int nBufferMinSize = nPointSize * nNewNumPoints;
@@ -836,8 +1377,25 @@ OGRErr OGRSimpleCurve::importFromWkb( unsigned char * pabyData,
 /*      Get the vertex.                                                 */
 /* -------------------------------------------------------------------- */
     int i = 0;
-    
-    if( getCoordinateDimension() == 3 )
+
+    if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
+    {
+        for( i = 0; i < nPointCount; i++ )
+        {
+            memcpy( paoPoints + i, pabyData + 9 + i*32, 16 );
+            memcpy( padfZ + i, pabyData + 9 + 16 + i*32, 8 );
+            memcpy( padfM + i, pabyData + 9 + 24 + i*32, 8 );
+        }
+    }
+    else if( flags & OGR_G_MEASURED )
+    {
+        for( i = 0; i < nPointCount; i++ )
+        {
+            memcpy( paoPoints + i, pabyData + 9 + i*24, 16 );
+            memcpy( padfM + i, pabyData + 9 + 16 + i*24, 8 );
+        }
+    }
+    else if( flags & OGR_G_3D )
     {
         for( i = 0; i < nPointCount; i++ )
         {
@@ -845,11 +1403,11 @@ OGRErr OGRSimpleCurve::importFromWkb( unsigned char * pabyData,
             memcpy( padfZ + i, pabyData + 9 + 16 + i*24, 8 );
         }
     }
-    else
+    else if( nPointCount )
     {
         memcpy( paoPoints, pabyData + 9, 16 * nPointCount );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Byte swap if needed.                                            */
 /* -------------------------------------------------------------------- */
@@ -861,15 +1419,23 @@ OGRErr OGRSimpleCurve::importFromWkb( unsigned char * pabyData,
             CPL_SWAPDOUBLE( &(paoPoints[i].y) );
         }
 
-        if( getCoordinateDimension() == 3 )
+        if( flags & OGR_G_3D )
         {
             for( i = 0; i < nPointCount; i++ )
             {
                 CPL_SWAPDOUBLE( padfZ + i );
             }
         }
+
+        if( flags & OGR_G_MEASURED )
+        {
+            for( i = 0; i < nPointCount; i++ )
+            {
+                CPL_SWAPDOUBLE( padfM + i );
+            }
+        }
     }
-    
+
     return OGRERR_NONE;
 }
 
@@ -894,10 +1460,16 @@ OGRErr  OGRSimpleCurve::exportToWkb( OGRwkbByteOrder eByteOrder,
 /* -------------------------------------------------------------------- */
     GUInt32 nGType = getGeometryType();
 
-    if ( eWkbVariant == wkbVariantIso )
+    if( eWkbVariant == wkbVariantPostGIS1 )
+    {
+        nGType = wkbFlatten(nGType);
+        if( Is3D() )
+            nGType = (OGRwkbGeometryType)(nGType | wkb25DBitInternalUse); /* yes we explicitly set wkb25DBit */
+        if( IsMeasured() )
+            nGType = (OGRwkbGeometryType)(nGType | 0x40000000);
+    }
+    else if ( eWkbVariant == wkbVariantIso )
         nGType = getIsoGeometryType();
-    else if( eWkbVariant == wkbVariantPostGIS1 && wkbHasZ((OGRwkbGeometryType)nGType) )
-        nGType = (OGRwkbGeometryType)(wkbFlatten(nGType) | wkb25DBitInternalUse); /* yes we explicitly set wkb25DBit */
 
     if( eByteOrder == wkbNDR )
         nGType = CPL_LSBWORD32( nGType );
@@ -905,7 +1477,7 @@ OGRErr  OGRSimpleCurve::exportToWkb( OGRwkbByteOrder eByteOrder,
         nGType = CPL_MSBWORD32( nGType );
 
     memcpy( pabyData + 1, &nGType, 4 );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Copy in the data count.                                         */
 /* -------------------------------------------------------------------- */
@@ -915,8 +1487,25 @@ OGRErr  OGRSimpleCurve::exportToWkb( OGRwkbByteOrder eByteOrder,
 /*      Copy in the raw data.                                           */
 /* -------------------------------------------------------------------- */
     int         i;
-    
-    if( getCoordinateDimension() == 3 )
+
+    if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
+    {
+        for( i = 0; i < nPointCount; i++ )
+        {
+            memcpy( pabyData + 9 + 32*i, paoPoints+i, 16 );
+            memcpy( pabyData + 9 + 16 + 32*i, padfZ+i, 8 );
+            memcpy( pabyData + 9 + 24 + 32*i, padfM+i, 8 );
+        }
+    }
+    else if( flags & OGR_G_MEASURED )
+    {
+        for( i = 0; i < nPointCount; i++ )
+        {
+            memcpy( pabyData + 9 + 24*i, paoPoints+i, 16 );
+            memcpy( pabyData + 9 + 16 + 24*i, padfM+i, 8 );
+        }
+    }
+    else if( flags & OGR_G_3D )
     {
         for( i = 0; i < nPointCount; i++ )
         {
@@ -924,7 +1513,7 @@ OGRErr  OGRSimpleCurve::exportToWkb( OGRwkbByteOrder eByteOrder,
             memcpy( pabyData + 9 + 16 + 24*i, padfZ+i, 8 );
         }
     }
-    else
+    else if( nPointCount )
         memcpy( pabyData+9, paoPoints, 16 * nPointCount );
 
 /* -------------------------------------------------------------------- */
@@ -937,12 +1526,12 @@ OGRErr  OGRSimpleCurve::exportToWkb( OGRwkbByteOrder eByteOrder,
         nCount = CPL_SWAP32( nPointCount );
         memcpy( pabyData+5, &nCount, 4 );
 
-        for( i = getCoordinateDimension() * nPointCount - 1; i >= 0; i-- )
+        for( i = CoordinateDimension() * nPointCount - 1; i >= 0; i-- )
         {
             CPL_SWAP64PTR( pabyData + 9 + 8 * i );
         }
     }
-    
+
     return OGRERR_NONE;
 }
 
@@ -957,40 +1546,46 @@ OGRErr OGRSimpleCurve::importFromWkt( char ** ppszInput )
 
 {
     int bHasZ = FALSE, bHasM = FALSE;
-    OGRErr      eErr = importPreambuleFromWkt(ppszInput, &bHasZ, &bHasM);
-    if( eErr >= 0 )
+    bool bIsEmpty = false;
+    OGRErr      eErr = importPreambuleFromWkt(ppszInput, &bHasZ, &bHasM, &bIsEmpty);
+    flags = 0;
+    if( eErr != OGRERR_NONE )
         return eErr;
+    if( bHasZ ) flags |= OGR_G_3D;
+    if( bHasM ) flags |= OGR_G_MEASURED;
+    if( bIsEmpty )
+    {
+        // we should be at the end
+        if( !((*ppszInput[0] == '\000') || (*ppszInput[0] == ',')) )
+            return OGRERR_CORRUPT_DATA;
+        return OGRERR_NONE;
+    }
 
     const char  *pszInput = *ppszInput;
 
 /* -------------------------------------------------------------------- */
 /*      Read the point list.                                            */
 /* -------------------------------------------------------------------- */
+    int flagsFromInput = flags;
     nPointCount = 0;
 
     int nMaxPoints = 0;
-    pszInput = OGRWktReadPoints( pszInput, &paoPoints, &padfZ, &nMaxPoints,
-                                &nPointCount );
+    pszInput = OGRWktReadPointsM( pszInput, &paoPoints, &padfZ, &padfM, &flagsFromInput,
+                                  &nMaxPoints, &nPointCount );
     if( pszInput == NULL )
         return OGRERR_CORRUPT_DATA;
 
-    *ppszInput = (char *) pszInput;
-
-    if( padfZ == NULL )
-        nCoordDimension = 2;
-    else
+    if( (flagsFromInput & OGR_G_3D) && !(flags & OGR_G_3D) )
     {
-        /* Ignore Z array when we have a LINESTRING M */
-        if (bHasM && !bHasZ)
-        {
-            nCoordDimension = 2;
-            CPLFree(padfZ);
-            padfZ = NULL;
-        }
-        else
-            nCoordDimension = 3;
+        set3D(TRUE);
+    }
+    if( (flagsFromInput & OGR_G_MEASURED) && !(flags & OGR_G_MEASURED) )
+    {
+        setMeasured(TRUE);
     }
 
+    *ppszInput = (char *) pszInput;
+
     return OGRERR_NONE;
 }
 
@@ -1010,22 +1605,47 @@ OGRErr OGRSimpleCurve::importFromWKTListOnly( char ** ppszInput, int bHasZ, int
 /* -------------------------------------------------------------------- */
 /*      Read the point list.                                            */
 /* -------------------------------------------------------------------- */
+    int flagsFromInput = flags;
     int nPointCountRead = 0;
+    double *padfMIn = NULL;
+    if( flagsFromInput == 0 ) /* flags was not set, this is not called by us */
+    {
+        if( bHasM )
+            flagsFromInput |= OGR_G_MEASURED;
+        if( bHasZ )
+            flagsFromInput |= OGR_G_3D;
+    }
 
-    pszInput = OGRWktReadPoints( pszInput, &paoPointsIn, &padfZIn, &nMaxPointsIn,
-                                 &nPointCountRead );
+    pszInput = OGRWktReadPointsM( pszInput, &paoPointsIn, &padfZIn, &padfMIn, &flagsFromInput,
+                                  &nMaxPointsIn, &nPointCountRead );
 
     if( pszInput == NULL )
+    {
+        OGRFree( padfMIn );
         return OGRERR_CORRUPT_DATA;
+    }
+    if( (flagsFromInput & OGR_G_3D) && !(flags & OGR_G_3D) )
+    {
+        flags |= OGR_G_3D;
+        bHasZ = TRUE;
+    }
+    if( (flagsFromInput & OGR_G_MEASURED) && !(flags & OGR_G_MEASURED) )
+    {
+        flags |= OGR_G_MEASURED;
+        bHasM = TRUE;
+    }
 
     *ppszInput = (char *) pszInput;
 
-    /* Ignore Z array when we have a POLYGON M */
-    if (bHasM && !bHasZ)
-        setPoints( nPointCountRead, paoPointsIn, NULL );
+    if (bHasM && bHasZ)
+        setPoints( nPointCountRead, paoPointsIn, padfZIn, padfMIn );
+    else if (bHasM && !bHasZ)
+        setPointsM( nPointCountRead, paoPointsIn, padfMIn );
     else
         setPoints( nPointCountRead, paoPointsIn, padfZIn );
 
+    CPLFree( padfMIn );
+
     return OGRERR_NONE;
 }
 
@@ -1033,15 +1653,15 @@ OGRErr OGRSimpleCurve::importFromWKTListOnly( char ** ppszInput, int bHasZ, int
 /*                            exportToWkt()                             */
 /*                                                                      */
 /*      Translate this structure into it's well known text format       */
-/*      equivelent.  This could be made alot more CPU efficient!        */
+/*      equivalent.  This could be made a lot more CPU efficient!        */
 /************************************************************************/
 
 OGRErr OGRSimpleCurve::exportToWkt( char ** ppszDstText,
                                    OGRwkbVariant eWkbVariant ) const
 
 {
-    int         nMaxString = nPointCount * 40 * 3 + 25;
-    int         nRetLen = 0;
+    size_t      nMaxString = static_cast<size_t>(nPointCount) * 40 * 4 + 26;
+    size_t      nRetLen = 0;
 
 /* -------------------------------------------------------------------- */
 /*      Handle special empty case.                                      */
@@ -1049,8 +1669,17 @@ OGRErr OGRSimpleCurve::exportToWkt( char ** ppszDstText,
     if( IsEmpty() )
     {
         CPLString osEmpty;
-        if( getCoordinateDimension() == 3 && eWkbVariant == wkbVariantIso )
-            osEmpty.Printf("%s Z EMPTY",getGeometryName());
+        if( eWkbVariant == wkbVariantIso )
+        {
+            if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
+                osEmpty.Printf("%s ZM EMPTY",getGeometryName());
+            else if( flags & OGR_G_MEASURED )
+                osEmpty.Printf("%s M EMPTY",getGeometryName());
+            else if( flags & OGR_G_3D )
+                osEmpty.Printf("%s Z EMPTY",getGeometryName());
+            else
+                osEmpty.Printf("%s EMPTY",getGeometryName());
+        }
         else
             osEmpty.Printf("%s EMPTY",getGeometryName());
         *ppszDstText = CPLStrdup(osEmpty);
@@ -1060,46 +1689,55 @@ OGRErr OGRSimpleCurve::exportToWkt( char ** ppszDstText,
 /* -------------------------------------------------------------------- */
 /*      General case.                                                   */
 /* -------------------------------------------------------------------- */
-    *ppszDstText = (char *) VSIMalloc( nMaxString );
+    *ppszDstText = (char *) VSI_MALLOC_VERBOSE( nMaxString );
     if( *ppszDstText == NULL )
         return OGRERR_NOT_ENOUGH_MEMORY;
 
-    if( getCoordinateDimension() == 3 && eWkbVariant == wkbVariantIso )
-        sprintf( *ppszDstText, "%s Z (", getGeometryName() );
+    if( eWkbVariant == wkbVariantIso )
+    {
+        if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
+            snprintf( *ppszDstText, nMaxString, "%s ZM (", getGeometryName() );
+        else if( flags & OGR_G_MEASURED )
+            snprintf( *ppszDstText, nMaxString, "%s M (", getGeometryName() );
+        else if( flags & OGR_G_3D )
+            snprintf( *ppszDstText, nMaxString, "%s Z (", getGeometryName() );
+        else
+            snprintf( *ppszDstText, nMaxString, "%s (", getGeometryName() );
+    }
     else
-        sprintf( *ppszDstText, "%s (", getGeometryName() );
+        snprintf( *ppszDstText, nMaxString, "%s (", getGeometryName() );
+
+    OGRBoolean hasZ = Is3D();
+    OGRBoolean hasM = IsMeasured();
+    if( eWkbVariant != wkbVariantIso )
+        hasM = FALSE;
 
     for( int i = 0; i < nPointCount; i++ )
     {
-        if( nMaxString <= (int) strlen(*ppszDstText+nRetLen) + 32 + nRetLen )
+        if( nMaxString <= strlen(*ppszDstText+nRetLen) + 32 + nRetLen )
         {
-            CPLDebug( "OGR", 
+            CPLDebug( "OGR",
                       "OGRSimpleCurve::exportToWkt() ... buffer overflow.\n"
                       "nMaxString=%d, strlen(*ppszDstText) = %d, i=%d\n"
-                      "*ppszDstText = %s", 
-                      nMaxString, (int) strlen(*ppszDstText), i, *ppszDstText );
+                      "*ppszDstText = %s",
+                      static_cast<int>(nMaxString),
+                      static_cast<int>(strlen(*ppszDstText)), i, *ppszDstText );
 
             VSIFree( *ppszDstText );
             *ppszDstText = NULL;
             return OGRERR_NOT_ENOUGH_MEMORY;
         }
-        
+
         if( i > 0 )
             strcat( *ppszDstText + nRetLen, "," );
 
         nRetLen += strlen(*ppszDstText + nRetLen);
-        if( getCoordinateDimension() == 3 )
-            OGRMakeWktCoordinate( *ppszDstText + nRetLen,
-                                  paoPoints[i].x,
-                                  paoPoints[i].y,
-                                  padfZ[i],
-                                  nCoordDimension );
-        else
-            OGRMakeWktCoordinate( *ppszDstText + nRetLen,
-                                  paoPoints[i].x,
-                                  paoPoints[i].y,
-                                  0.0,
-                                  nCoordDimension );
+        OGRMakeWktCoordinateM( *ppszDstText + nRetLen,
+                               paoPoints[i].x,
+                               paoPoints[i].y,
+                               padfZ ? padfZ[i] : 0.0,
+                               padfM ? padfM[i] : 0.0,
+                               hasZ, hasM );
 
         nRetLen += strlen(*ppszDstText + nRetLen);
     }
@@ -1112,7 +1750,7 @@ OGRErr OGRSimpleCurve::exportToWkt( char ** ppszDstText,
 /************************************************************************/
 /*                             get_Length()                             */
 /*                                                                      */
-/*      For now we return a simple euclidian 2D distance.               */
+/*      For now we return a simple euclidean 2D distance.               */
 /************************************************************************/
 
 double OGRSimpleCurve::get_Length() const
@@ -1129,7 +1767,7 @@ double OGRSimpleCurve::get_Length() const
         dfDeltaY = paoPoints[i+1].y - paoPoints[i].y;
         dfLength += sqrt(dfDeltaX*dfDeltaX + dfDeltaY*dfDeltaY);
     }
-    
+
     return dfLength;
 }
 
@@ -1181,7 +1819,7 @@ void OGRSimpleCurve::Value( double dfDistance, OGRPoint * poPoint ) const
 
         if (dfSegLength > 0)
         {
-            if( (dfLength <= dfDistance) && ((dfLength + dfSegLength) >= 
+            if( (dfLength <= dfDistance) && ((dfLength + dfSegLength) >=
                                              dfDistance) )
             {
                 double      dfRatio;
@@ -1196,14 +1834,14 @@ void OGRSimpleCurve::Value( double dfDistance, OGRPoint * poPoint ) const
                 if( getCoordinateDimension() == 3 )
                     poPoint->setZ( padfZ[i] * (1 - dfRatio)
                                    + padfZ[i+1] * dfRatio );
-                
+
                 return;
             }
 
             dfLength += dfSegLength;
         }
     }
-    
+
     EndPoint( poPoint );
 }
 
@@ -1216,11 +1854,11 @@ void OGRSimpleCurve::Value( double dfDistance, OGRPoint * poPoint ) const
 /**
 * \brief Project point on linestring.
 *
-* The input point projeted on linestring. This is the shortest distance 
+* The input point projected on linestring. This is the shortest distance
 * from point to the linestring. The distance from begin of linestring to
 * the point projection returned.
 *
-* This method is built on the GEOS library (GEOS >= 3.2.0), check it for the 
+* This method is built on the GEOS library (GEOS >= 3.2.0), check it for the
 * definition of the geometry operation.
 * If OGR is built without the GEOS library, this method will always return -1,
 * issuing a CPLE_NotSupported error.
@@ -1230,7 +1868,7 @@ void OGRSimpleCurve::Value( double dfDistance, OGRPoint * poPoint ) const
 * @since OGR 1.11.0
 */
 
-/* GEOS >= 3.2.0 for project capabilty */
+/* GEOS >= 3.2.0 for project capability */
 #if defined(HAVE_GEOS)
 #if GEOS_VERSION_MAJOR > 3 || (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR >= 2)
 #define HAVE_GEOS_PROJECT
@@ -1238,7 +1876,11 @@ void OGRSimpleCurve::Value( double dfDistance, OGRPoint * poPoint ) const
 #endif
 
 
-double OGRSimpleCurve::Project(const OGRPoint *poPoint) const
+double OGRSimpleCurve::Project(const OGRPoint *
+#ifdef HAVE_GEOS_PROJECT
+                                poPoint
+#endif
+                               ) const
 
 {
     double dfResult = -1;
@@ -1279,7 +1921,7 @@ double OGRSimpleCurve::Project(const OGRPoint *poPoint) const
 /**
 * \brief Get the portion of linestring.
 *
-* The portion of the linestring extracted to new one. The input distances 
+* The portion of the linestring extracted to new one. The input distances
 * (maybe present as ratio of length of linestring) set begin and end of
 * extracted portion.
 *
@@ -1370,7 +2012,7 @@ OGRLineString* OGRSimpleCurve::getSubLine(double dfDistanceFrom, double dfDistan
                     {
                         poNewLineString->addPoint(dfX, dfY);
                     }
-                    
+
                     //check if dfDistanceTo is in same segment
                     if ((dfLength <= dfDistanceTo) && ((dfLength + dfSegLength) >=
                         dfDistanceTo))
@@ -1483,7 +2125,7 @@ void OGRSimpleCurve::getEnvelope( OGREnvelope * psEnvelope ) const
         psEnvelope->MaxY = 0;
         return;
     }
-    
+
     dfMinX = dfMaxX = paoPoints[0].x;
     dfMinY = dfMaxY = paoPoints[0].y;
 
@@ -1545,26 +2187,25 @@ void OGRSimpleCurve::getEnvelope( OGREnvelope3D * psEnvelope ) const
 OGRBoolean OGRSimpleCurve::Equals( OGRGeometry * poOther ) const
 
 {
-    OGRLineString       *poOLine = (OGRLineString *) poOther;
-    
-    if( poOLine == this )
+    if( poOther == this )
         return TRUE;
-    
+
     if( poOther->getGeometryType() != getGeometryType() )
         return FALSE;
 
     if( IsEmpty() && poOther->IsEmpty() )
         return TRUE;
-    
+
     // we should eventually test the SRS.
 
+    OGRSimpleCurve       *poOLine = (OGRSimpleCurve *) poOther;
     if( getNumPoints() != poOLine->getNumPoints() )
         return FALSE;
 
     for( int iPoint = 0; iPoint < getNumPoints(); iPoint++ )
     {
         if( getX(iPoint) != poOLine->getX(iPoint)
-            || getY(iPoint) != poOLine->getY(iPoint) 
+            || getY(iPoint) != poOLine->getY(iPoint)
             || getZ(iPoint) != poOLine->getZ(iPoint) )
             return FALSE;
     }
@@ -1592,8 +2233,8 @@ OGRErr OGRSimpleCurve::transform( OGRCoordinateTransformation *poCT )
 /*   or keeping intact the original geometry if only full reprojection  */
 /*   allowed.                                                           */
 /* -------------------------------------------------------------------- */
-    xyz = (double *) VSIMalloc(sizeof(double) * nPointCount * 3);
-    pabSuccess = (int *) VSICalloc(sizeof(int), nPointCount);
+    xyz = (double *) VSI_MALLOC_VERBOSE(sizeof(double) * nPointCount * 3);
+    pabSuccess = (int *) VSI_CALLOC_VERBOSE(sizeof(int), nPointCount);
     if( xyz == NULL || pabSuccess == NULL )
     {
         VSIFree(xyz);
@@ -1635,20 +2276,20 @@ OGRErr OGRSimpleCurve::transform( OGRCoordinateTransformation *poCT )
                     CPLGetConfigOption("OGR_ENABLE_PARTIAL_REPROJECTION", NULL);
             if (pszEnablePartialReprojection == NULL)
             {
-                static int bHasWarned = FALSE;
+                static bool bHasWarned = false;
                 if (!bHasWarned)
                 {
                     /* Check that there is at least one valid reprojected point */
                     /* and issue an error giving an hint to use OGR_ENABLE_PARTIAL_REPROJECTION */
-                    int bHasOneValidPoint = (j != 0);
+                    bool bHasOneValidPoint = (j != 0);
                     for( ; i < nPointCount && !bHasOneValidPoint; i++ )
                     {
                         if (pabSuccess[i])
-                            bHasOneValidPoint = TRUE;
+                            bHasOneValidPoint = true;
                     }
                     if (bHasOneValidPoint)
                     {
-                        bHasWarned = TRUE;
+                        bHasWarned = true;
                         CPLError(CE_Failure, CPLE_AppDefined,
                                 "Full reprojection failed, but partial is possible if you define "
                                 "OGR_ENABLE_PARTIAL_REPROJECTION configuration option to TRUE");
@@ -1811,9 +2452,9 @@ class OGRSimpleCurvePointIterator: public OGRPointIterator
 {
         const OGRSimpleCurve* poSC;
         int                   iCurPoint;
-    
+
     public:
-        OGRSimpleCurvePointIterator(const OGRSimpleCurve* poSC) : poSC(poSC), iCurPoint(0) {}
+        OGRSimpleCurvePointIterator(const OGRSimpleCurve* poSCIn) : poSC(poSCIn), iCurPoint(0) {}
 
         virtual OGRBoolean getNextPoint(OGRPoint* p);
 };
@@ -1854,6 +2495,24 @@ OGRLineString::OGRLineString()
 }
 
 /************************************************************************/
+/*                  OGRLineString( const OGRLineString& )               */
+/************************************************************************/
+
+/**
+ * \brief Copy constructor.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the constructor
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRLineString::OGRLineString( const OGRLineString& other ) :
+    OGRSimpleCurve( other )
+{
+}
+
+/************************************************************************/
 /*                          ~OGRLineString()                            */
 /************************************************************************/
 
@@ -1863,13 +2522,39 @@ OGRLineString::~OGRLineString()
 }
 
 /************************************************************************/
+/*                    operator=( const OGRLineString& )                 */
+/************************************************************************/
+
+/**
+ * \brief Assignment operator.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the operator
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRLineString& OGRLineString::operator=( const OGRLineString& other )
+{
+    if( this != &other)
+    {
+        OGRSimpleCurve::operator=( other );
+    }
+    return *this;
+}
+
+/************************************************************************/
 /*                          getGeometryType()                           */
 /************************************************************************/
 
 OGRwkbGeometryType OGRLineString::getGeometryType() const
 
 {
-    if( nCoordDimension == 3 )
+    if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
+        return wkbLineStringZM;
+    else if( flags & OGR_G_MEASURED  )
+        return wkbLineStringM;
+    else if( flags & OGR_G_3D )
         return wkbLineString25D;
     else
         return wkbLineString;
@@ -1902,10 +2587,10 @@ OGRLineString* OGRLineString::CurveToLine(CPL_UNUSED double dfMaxAngleStepSizeDe
 /**
  * \brief Compute area of ring / closed linestring.
  *
- * The area is computed according to Green's Theorem:  
+ * The area is computed according to Green's Theorem:
  *
- * Area is "Sum(x(i)*(y(i+1) - y(i-1)))/2" for i = 0 to pointCount-1, 
- * assuming the last point is a duplicate of the first. 
+ * Area is "Sum(x(i)*(y(i+1) - y(i-1)))/2" for i = 0 to pointCount-1,
+ * assuming the last point is a duplicate of the first.
  *
  * @return computed area.
  */
@@ -1948,7 +2633,8 @@ OGRLineString* OGRLineString::TransferMembersAndDestroy(
                                             OGRLineString* poSrc,
                                             OGRLineString* poDst)
 {
-    poDst->setCoordinateDimension(poSrc->getCoordinateDimension());
+    poDst->set3D(poSrc->Is3D());
+    poDst->setMeasured(poSrc->IsMeasured());
     poDst->assignSpatialReference(poSrc->getSpatialReference());
     poDst->nPointCount = poSrc->nPointCount;
     poDst->paoPoints = poSrc->paoPoints;
@@ -1969,7 +2655,7 @@ OGRLineString* OGRLineString::TransferMembersAndDestroy(
  *
  * The passed in geometry is consumed and a new one returned (or NULL in case
  * of failure)
- * 
+ *
  * @param poLS the input geometry - ownership is passed to the method.
  * @return new geometry.
  */
diff --git a/ogr/ogrmulticurve.cpp b/ogr/ogrmulticurve.cpp
index 274f3f1..6ab41bc 100644
--- a/ogr/ogrmulticurve.cpp
+++ b/ogr/ogrmulticurve.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmulticurve.cpp 27960 2014-11-14 18:31:32Z rouault $
+ * $Id: ogrmulticurve.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRMultiCurve class.
@@ -31,7 +31,7 @@
 #include "ogr_p.h"
 #include "ogr_api.h"
 
-CPL_CVSID("$Id: ogrmulticurve.cpp 27960 2014-11-14 18:31:32Z rouault $");
+CPL_CVSID("$Id: ogrmulticurve.cpp 33631 2016-03-04 06:28:09Z goatbar $");
 
 /************************************************************************/
 /*                            OGRMultiCurve()                           */
@@ -46,6 +46,24 @@ OGRMultiCurve::OGRMultiCurve()
 }
 
 /************************************************************************/
+/*                OGRMultiCurve( const OGRMultiCurve& )                 */
+/************************************************************************/
+
+/**
+ * \brief Copy constructor.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the constructor
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRMultiCurve::OGRMultiCurve( const OGRMultiCurve& other ) :
+    OGRGeometryCollection(other)
+{
+}
+
+/************************************************************************/
 /*                           ~OGRMultiCurve()                           */
 /************************************************************************/
 
@@ -54,13 +72,39 @@ OGRMultiCurve::~OGRMultiCurve()
 }
 
 /************************************************************************/
+/*                  operator=( const OGRMultiCurve&)                    */
+/************************************************************************/
+
+/**
+ * \brief Assignment operator.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the operator
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRMultiCurve& OGRMultiCurve::operator=( const OGRMultiCurve& other )
+{
+    if( this != &other)
+    {
+        OGRGeometryCollection::operator=( other );
+    }
+    return *this;
+}
+
+/************************************************************************/
 /*                          getGeometryType()                           */
 /************************************************************************/
 
 OGRwkbGeometryType OGRMultiCurve::getGeometryType() const
 
 {
-    if( getCoordinateDimension() == 3 )
+    if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
+        return wkbMultiCurveZM;
+    else if( flags & OGR_G_MEASURED  )
+        return wkbMultiCurveM;
+    else if( flags & OGR_G_3D )
         return wkbMultiCurveZ;
     else
         return wkbMultiCurve;
@@ -155,11 +199,11 @@ OGRBoolean OGRMultiCurve::hasCurveGeometry(int bLookForNonLinear) const
  * instances of OGRLineString. This can be verified if hasCurveGeometry(TRUE)
  * returns FALSE. It is not intended to approximate circular curves. For that
  * use getLinearGeometry().
- * 
+ *
  * The passed in geometry is consumed and a new one returned (or NULL in case
- * of failure). 
- * 
- * @param poMS the input geometry - ownership is passed to the method.
+ * of failure).
+ *
+ * @param poMC the input geometry - ownership is passed to the method.
  * @return new geometry.
  */
 
diff --git a/ogr/ogrmultilinestring.cpp b/ogr/ogrmultilinestring.cpp
index 3273455..2a44c29 100644
--- a/ogr/ogrmultilinestring.cpp
+++ b/ogr/ogrmultilinestring.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmultilinestring.cpp 27959 2014-11-14 18:29:21Z rouault $
+ * $Id: ogrmultilinestring.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRMultiLineString class.
@@ -31,7 +31,7 @@
 #include "ogr_geometry.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrmultilinestring.cpp 27959 2014-11-14 18:29:21Z rouault $");
+CPL_CVSID("$Id: ogrmultilinestring.cpp 33631 2016-03-04 06:28:09Z goatbar $");
 
 /************************************************************************/
 /*                        OGRMultiLineString()                          */
@@ -46,6 +46,24 @@ OGRMultiLineString::OGRMultiLineString()
 }
 
 /************************************************************************/
+/*           OGRMultiLineString( const OGRMultiLineString& )            */
+/************************************************************************/
+
+/**
+ * \brief Copy constructor.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the constructor
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRMultiLineString::OGRMultiLineString( const OGRMultiLineString& other ) :
+    OGRMultiCurve(other)
+{
+}
+
+/************************************************************************/
 /*                       ~OGRMultiLineString()                          */
 /************************************************************************/
 
@@ -54,13 +72,40 @@ OGRMultiLineString::~OGRMultiLineString()
 }
 
 /************************************************************************/
+/*                  operator=( const OGRMultiCurve&)                    */
+/************************************************************************/
+
+/**
+ * \brief Assignment operator.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the operator
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRMultiLineString& OGRMultiLineString::operator=( const OGRMultiLineString& other )
+{
+    if( this != &other)
+    {
+        OGRMultiCurve::operator=( other );
+    }
+    return *this;
+}
+
+
+/************************************************************************/
 /*                          getGeometryType()                           */
 /************************************************************************/
 
 OGRwkbGeometryType OGRMultiLineString::getGeometryType() const
 
 {
-    if( getCoordinateDimension() == 3 )
+    if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
+        return wkbMultiLineStringZM;
+    else if( flags & OGR_G_MEASURED  )
+        return wkbMultiLineStringM;
+    else if( flags & OGR_G_3D )
         return wkbMultiLineString25D;
     else
         return wkbMultiLineString;
@@ -113,7 +158,7 @@ OGRBoolean OGRMultiLineString::hasCurveGeometry(CPL_UNUSED int bLookForNonLinear
  * \brief Cast to multicurve.
  *
  * The passed in geometry is consumed and a new one returned .
- * 
+ *
  * @param poMLS the input geometry - ownership is passed to the method.
  * @return new geometry.
  */
diff --git a/ogr/ogrmultipoint.cpp b/ogr/ogrmultipoint.cpp
index 88f1640..663c1e4 100644
--- a/ogr/ogrmultipoint.cpp
+++ b/ogr/ogrmultipoint.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmultipoint.cpp 27959 2014-11-14 18:29:21Z rouault $
+ * $Id: ogrmultipoint.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRMultiPoint class.
@@ -32,7 +32,7 @@
 #include "ogr_p.h"
 #include <assert.h>
 
-CPL_CVSID("$Id: ogrmultipoint.cpp 27959 2014-11-14 18:29:21Z rouault $");
+CPL_CVSID("$Id: ogrmultipoint.cpp 33631 2016-03-04 06:28:09Z goatbar $");
 
 /************************************************************************/
 /*                           OGRMultiPoint()                            */
@@ -47,6 +47,24 @@ OGRMultiPoint::OGRMultiPoint()
 }
 
 /************************************************************************/
+/*                OGRMultiPoint( const OGRMultiPoint& )                 */
+/************************************************************************/
+
+/**
+ * \brief Copy constructor.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the constructor
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRMultiPoint::OGRMultiPoint( const OGRMultiPoint& other ) :
+    OGRGeometryCollection(other)
+{
+}
+
+/************************************************************************/
 /*                          ~OGRMultiPoint()                            */
 /************************************************************************/
 
@@ -55,13 +73,39 @@ OGRMultiPoint::~OGRMultiPoint()
 }
 
 /************************************************************************/
+/*                  operator=( const OGRMultiPoint&)                    */
+/************************************************************************/
+
+/**
+ * \brief Assignment operator.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the operator
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRMultiPoint& OGRMultiPoint::operator=( const OGRMultiPoint& other )
+{
+    if( this != &other)
+    {
+        OGRGeometryCollection::operator=( other );
+    }
+    return *this;
+}
+
+/************************************************************************/
 /*                          getGeometryType()                           */
 /************************************************************************/
 
 OGRwkbGeometryType OGRMultiPoint::getGeometryType() const
 
 {
-    if( getCoordinateDimension() == 3 )
+    if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
+        return wkbMultiPointZM;
+    else if( flags & OGR_G_MEASURED  )
+        return wkbMultiPointM;
+    else if( flags & OGR_G_3D )
         return wkbMultiPoint25D;
     else
         return wkbMultiPoint;
@@ -100,38 +144,56 @@ OGRBoolean OGRMultiPoint::isCompatibleSubType( OGRwkbGeometryType eGeomType ) co
 /*                            exportToWkt()                             */
 /*                                                                      */
 /*      Translate this structure into it's well known text format       */
-/*      equivelent.  This could be made alot more CPU efficient!        */
+/*      equivalent.  This could be made a lot more CPU efficient!        */
 /************************************************************************/
 
 OGRErr OGRMultiPoint::exportToWkt( char ** ppszDstText,
                                    OGRwkbVariant eWkbVariant ) const
 
 {
-    int         nMaxString = getNumGeometries() * 22 + 128;
-    int         nRetLen = 0;
+    size_t      nMaxString = static_cast<size_t>(getNumGeometries()) * 22 + 130;
+    size_t      nRetLen = 0;
 
 /* -------------------------------------------------------------------- */
 /*      Return MULTIPOINT EMPTY if we get no valid points.              */
 /* -------------------------------------------------------------------- */
     if( IsEmpty() )
     {
-        if( getCoordinateDimension() == 3 && eWkbVariant == wkbVariantIso )
-            *ppszDstText = CPLStrdup("MULTIPOINT Z EMPTY");
+        if( eWkbVariant == wkbVariantIso )
+        {
+            if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
+                *ppszDstText = CPLStrdup("MULTIPOINT ZM EMPTY");
+            else if( flags & OGR_G_MEASURED )
+                *ppszDstText = CPLStrdup("MULTIPOINT M EMPTY");
+            else if( flags & OGR_G_3D )
+                *ppszDstText = CPLStrdup("MULTIPOINT Z EMPTY");
+            else
+                *ppszDstText = CPLStrdup("MULTIPOINT EMPTY");
+        }
         else
             *ppszDstText = CPLStrdup("MULTIPOINT EMPTY");
         return OGRERR_NONE;
     }
 
-    *ppszDstText = (char *) VSIMalloc( nMaxString );
+    *ppszDstText = (char *) VSI_MALLOC_VERBOSE( nMaxString );
     if( *ppszDstText == NULL )
         return OGRERR_NOT_ENOUGH_MEMORY;
 
-    if( getCoordinateDimension() == 3 && eWkbVariant == wkbVariantIso )
-        sprintf( *ppszDstText, "%s Z (", getGeometryName() );
+    if( eWkbVariant == wkbVariantIso )
+    {
+        if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
+            snprintf( *ppszDstText, nMaxString, "%s ZM (", getGeometryName() );
+        else if( flags & OGR_G_MEASURED )
+            snprintf( *ppszDstText, nMaxString, "%s M (", getGeometryName() );
+        else if( flags & OGR_G_3D )
+            snprintf( *ppszDstText, nMaxString, "%s Z (", getGeometryName() );
+        else
+            snprintf( *ppszDstText, nMaxString, "%s (", getGeometryName() );
+    }
     else
-        sprintf( *ppszDstText, "%s (", getGeometryName() );
+        snprintf( *ppszDstText, nMaxString, "%s (", getGeometryName() );
 
-    int bMustWriteComma = FALSE;
+    bool bMustWriteComma = false;
     for( int i = 0; i < getNumGeometries(); i++ )
     {
         OGRPoint        *poPoint = (OGRPoint *) getGeometryRef( i );
@@ -144,7 +206,7 @@ OGRErr OGRMultiPoint::exportToWkt( char ** ppszDstText,
 
         if( bMustWriteComma )
             strcat( *ppszDstText + nRetLen, "," );
-        bMustWriteComma = TRUE;
+        bMustWriteComma = true;
 
         nRetLen += strlen(*ppszDstText + nRetLen);
 
@@ -160,11 +222,13 @@ OGRErr OGRMultiPoint::exportToWkt( char ** ppszDstText,
             nRetLen ++;
         }
 
-        OGRMakeWktCoordinate( *ppszDstText + nRetLen,
-                              poPoint->getX(), 
-                              poPoint->getY(),
-                              poPoint->getZ(),
-                              poPoint->getCoordinateDimension() );
+        OGRMakeWktCoordinateM( *ppszDstText + nRetLen,
+                               poPoint->getX(),
+                               poPoint->getY(),
+                               poPoint->getZ(),
+                               poPoint->getM(),
+                               poPoint->Is3D(),
+                               poPoint->IsMeasured() && (eWkbVariant == wkbVariantIso) );
 
         if( eWkbVariant == wkbVariantIso )
         {
@@ -187,9 +251,15 @@ OGRErr OGRMultiPoint::importFromWkt( char ** ppszInput )
 {
     const char *pszInputBefore = *ppszInput;
     int bHasZ = FALSE, bHasM = FALSE;
-    OGRErr      eErr = importPreambuleFromWkt(ppszInput, &bHasZ, &bHasM);
-    if( eErr >= 0 )
+    bool bIsEmpty = false;
+    OGRErr      eErr = importPreambuleFromWkt(ppszInput, &bHasZ, &bHasM, &bIsEmpty);
+    flags = 0;
+    if( eErr != OGRERR_NONE )
         return eErr;
+    if( bHasZ ) flags |= OGR_G_3D;
+    if( bHasM ) flags |= OGR_G_MEASURED;
+    if( bIsEmpty )
+        return OGRERR_NONE;
 
     char        szToken[OGR_WKT_TOKEN_MAX];
     const char  *pszInput = *ppszInput;
@@ -199,7 +269,7 @@ OGRErr OGRMultiPoint::importFromWkt( char ** ppszInput )
     const char* pszPreScan = OGRWktReadToken( pszInput, szToken );
     OGRWktReadToken( pszPreScan, szToken );
 
-    // Do we have an inner bracket? 
+    // Do we have an inner bracket?
     if (EQUAL(szToken,"(") || EQUAL(szToken, "EMPTY") )
     {
         *ppszInput = (char*) pszInputBefore;
@@ -218,42 +288,73 @@ OGRErr OGRMultiPoint::importFromWkt( char ** ppszInput )
     int                 nPointCount = 0;
     OGRRawPoint         *paoPoints = NULL;
     double              *padfZ = NULL;
+    double              *padfM = NULL;
+    int                 flagsFromInput = flags;
 
-    pszInput = OGRWktReadPoints( pszInput, &paoPoints, &padfZ, &nMaxPoint,
-                                 &nPointCount );
+    pszInput = OGRWktReadPointsM( pszInput, &paoPoints, &padfZ, &padfM, &flagsFromInput,
+                                  &nMaxPoint, &nPointCount );
     if( pszInput == NULL )
     {
         OGRFree( paoPoints );
         OGRFree( padfZ );
+        OGRFree( padfM );
         return OGRERR_CORRUPT_DATA;
     }
+    if( (flagsFromInput & OGR_G_3D) && !(flags & OGR_G_3D) )
+    {
+        flags |= OGR_G_3D;
+        bHasZ = TRUE;
+    }
+    if( (flagsFromInput & OGR_G_MEASURED) && !(flags & OGR_G_MEASURED) )
+    {
+        flags |= OGR_G_MEASURED;
+        bHasM = TRUE;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Transform raw points into point objects.                        */
 /* -------------------------------------------------------------------- */
     for( iGeom = 0; iGeom < nPointCount && eErr == OGRERR_NONE; iGeom++ )
     {
-        OGRGeometry     *poGeom;
-        if( padfZ )
-            poGeom = new OGRPoint( paoPoints[iGeom].x, 
-                                   paoPoints[iGeom].y, 
-                                   padfZ[iGeom] );
-        else
-            poGeom =  new OGRPoint( paoPoints[iGeom].x, 
-                                    paoPoints[iGeom].y );
+        OGRGeometry     *poGeom = new OGRPoint( paoPoints[iGeom].x,
+                                                paoPoints[iGeom].y );
+        if( bHasM )
+        {
+            if( padfM != NULL )
+                ((OGRPoint*)poGeom)->setM(padfM[iGeom]);
+            else
+                ((OGRPoint*)poGeom)->setM(0.0);
+        }
+        if( bHasZ )
+        {
+            if( padfZ != NULL )
+                ((OGRPoint*)poGeom)->setZ(padfZ[iGeom]);
+            else
+                ((OGRPoint*)poGeom)->setZ(0.0);
+        }
 
         eErr = addGeometryDirectly( poGeom );
+        if( eErr != OGRERR_NONE )
+        {
+            OGRFree( paoPoints );
+            OGRFree( padfZ );
+            OGRFree( padfM );
+            delete poGeom;
+            return eErr;
+        }
     }
 
     OGRFree( paoPoints );
     if( padfZ )
         OGRFree( padfZ );
+    if( padfM )
+        OGRFree( padfM );
 
     if( eErr != OGRERR_NONE )
         return eErr;
 
     *ppszInput = (char *) pszInput;
-    
+
     return OGRERR_NONE;
 }
 
@@ -270,14 +371,11 @@ OGRErr OGRMultiPoint::importFromWkt( char ** ppszInput )
 OGRErr OGRMultiPoint::importFromWkt_Bracketed( char ** ppszInput, int bHasM, int bHasZ )
 
 {
-
-    char        szToken[OGR_WKT_TOKEN_MAX];
-    const char  *pszInput = *ppszInput;
-    OGRErr      eErr = OGRERR_NONE;
-
 /* -------------------------------------------------------------------- */
 /*      Skip MULTIPOINT keyword.                                        */
 /* -------------------------------------------------------------------- */
+    char        szToken[OGR_WKT_TOKEN_MAX];
+    const char  *pszInput = *ppszInput;
     pszInput = OGRWktReadToken( pszInput, szToken );
 
     if (bHasZ || bHasM)
@@ -289,66 +387,96 @@ OGRErr OGRMultiPoint::importFromWkt_Bracketed( char ** ppszInput, int bHasM, int
 /* -------------------------------------------------------------------- */
 /*      Read points till we get to the closing bracket.                 */
 /* -------------------------------------------------------------------- */
-    int                 nMaxPoint = 0;
-    int                 nPointCount = 0;
+
     OGRRawPoint         *paoPoints = NULL;
     double              *padfZ = NULL;
+    double              *padfM = NULL;
 
     while( (pszInput = OGRWktReadToken( pszInput, szToken )) != NULL
            && (EQUAL(szToken,"(") || EQUAL(szToken,",")) )
     {
-        OGRGeometry     *poGeom;
-
         const char* pszNext = OGRWktReadToken( pszInput, szToken );
         if (EQUAL(szToken,"EMPTY"))
         {
-            poGeom = new OGRPoint(0,0);
+            OGRGeometry *poGeom = new OGRPoint(0,0);
             poGeom->empty();
-            eErr = addGeometryDirectly( poGeom );
+            OGRErr eErr = addGeometryDirectly( poGeom );
             if( eErr != OGRERR_NONE )
+            {
+                OGRFree( paoPoints );
+                delete poGeom;
                 return eErr;
+            }
 
             pszInput = pszNext;
 
             continue;
         }
 
-        pszInput = OGRWktReadPoints( pszInput, &paoPoints, &padfZ, &nMaxPoint,
-                                     &nPointCount );
+        int nMaxPoint = 0;
+        int nPointCount = 0;
+        int flagsFromInput = flags;
+        pszInput = OGRWktReadPointsM( pszInput, &paoPoints, &padfZ, &padfM, &flagsFromInput,
+                                      &nMaxPoint, &nPointCount );
 
         if( pszInput == NULL || nPointCount != 1 )
         {
             OGRFree( paoPoints );
             OGRFree( padfZ );
+            OGRFree( padfM );
             return OGRERR_CORRUPT_DATA;
         }
+        if( (flagsFromInput & OGR_G_3D) && !(flags & OGR_G_3D) )
+        {
+            flags |= OGR_G_3D;
+            bHasZ = TRUE;
+        }
+        if( (flagsFromInput & OGR_G_MEASURED) && !(flags & OGR_G_MEASURED) )
+        {
+            flags |= OGR_G_MEASURED;
+            bHasM = TRUE;
+        }
 
-        /* Ignore Z array when we have a MULTIPOINT M */
-        if( padfZ && !(bHasM && !bHasZ))
-            poGeom = new OGRPoint( paoPoints[0].x, 
-                                   paoPoints[0].y, 
-                                   padfZ[0] );
-        else
-            poGeom =  new OGRPoint( paoPoints[0].x, 
-                                    paoPoints[0].y );
+        OGRGeometry *poGeom = new OGRPoint( paoPoints[0].x,
+                                            paoPoints[0].y );
+        if( bHasM )
+        {
+            if( padfM != NULL )
+                ((OGRPoint*)poGeom)->setM(padfM[0]);
+            else
+                ((OGRPoint*)poGeom)->setM(0.0);
+        }
+        if( bHasZ )
+        {
+            if( padfZ != NULL )
+                ((OGRPoint*)poGeom)->setZ(padfZ[0]);
+            else
+                ((OGRPoint*)poGeom)->setZ(0.0);
+        }
 
-        eErr = addGeometryDirectly( poGeom );
+        OGRErr eErr = addGeometryDirectly( poGeom );
         if( eErr != OGRERR_NONE )
+        {
+            OGRFree( paoPoints );
+            OGRFree( padfZ );
+            OGRFree( padfM );
+            delete poGeom;
             return eErr;
+        }
     }
 
 /* -------------------------------------------------------------------- */
 /*      Cleanup.                                                        */
 /* -------------------------------------------------------------------- */
     OGRFree( paoPoints );
-    if( padfZ )
-        OGRFree( padfZ );
+    OGRFree( padfZ );
+    OGRFree( padfM );
 
     if( !EQUAL(szToken,")") )
         return OGRERR_CORRUPT_DATA;
 
     *ppszInput = (char *) pszInput;
-    
+
     return OGRERR_NONE;
 }
 
diff --git a/ogr/ogrmultipolygon.cpp b/ogr/ogrmultipolygon.cpp
index 748ff3d..168ce57 100644
--- a/ogr/ogrmultipolygon.cpp
+++ b/ogr/ogrmultipolygon.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmultipolygon.cpp 27959 2014-11-14 18:29:21Z rouault $
+ * $Id: ogrmultipolygon.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRMultiPolygon class.
@@ -32,7 +32,7 @@
 #include "ogr_api.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrmultipolygon.cpp 27959 2014-11-14 18:29:21Z rouault $");
+CPL_CVSID("$Id: ogrmultipolygon.cpp 33631 2016-03-04 06:28:09Z goatbar $");
 
 /************************************************************************/
 /*                          OGRMultiPolygon()                           */
@@ -47,6 +47,24 @@ OGRMultiPolygon::OGRMultiPolygon()
 }
 
 /************************************************************************/
+/*              OGRMultiPolygon( const OGRMultiPolygon& )               */
+/************************************************************************/
+
+/**
+ * \brief Copy constructor.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the constructor
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRMultiPolygon::OGRMultiPolygon( const OGRMultiPolygon& other ) :
+    OGRMultiSurface(other)
+{
+}
+
+/************************************************************************/
 /*                         ~OGRMultiPolygon()                           */
 /************************************************************************/
 
@@ -55,13 +73,39 @@ OGRMultiPolygon::~OGRMultiPolygon()
 }
 
 /************************************************************************/
+/*                  operator=( const OGRMultiPolygon&)                    */
+/************************************************************************/
+
+/**
+ * \brief Assignment operator.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the operator
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRMultiPolygon& OGRMultiPolygon::operator=( const OGRMultiPolygon& other )
+{
+    if( this != &other)
+    {
+        OGRMultiSurface::operator=( other );
+    }
+    return *this;
+}
+
+/************************************************************************/
 /*                          getGeometryType()                           */
 /************************************************************************/
 
 OGRwkbGeometryType OGRMultiPolygon::getGeometryType() const
 
 {
-    if( getCoordinateDimension() == 3 )
+    if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
+        return wkbMultiPolygonZM;
+    else if( flags & OGR_G_MEASURED  )
+        return wkbMultiPolygonM;
+    else if( flags & OGR_G_3D )
         return wkbMultiPolygon25D;
     else
         return wkbMultiPolygon;
@@ -112,23 +156,7 @@ OGRBoolean OGRMultiPolygon::hasCurveGeometry(CPL_UNUSED int bLookForNonLinear) c
 
 OGRErr OGRMultiPolygon::PointOnSurface( OGRPoint * poPoint ) const
 {
-    if( poPoint == NULL || poPoint->IsEmpty() )
-        return OGRERR_FAILURE;
-
-    OGRGeometryH hInsidePoint = OGR_G_PointOnSurface( (OGRGeometryH) this );
-    if( hInsidePoint == NULL )
-        return OGRERR_FAILURE;
-
-    OGRPoint *poInsidePoint = (OGRPoint *) hInsidePoint;
-    if( poInsidePoint->IsEmpty() )
-        poPoint->empty();
-    else
-    {
-        poPoint->setX( poInsidePoint->getX() );
-        poPoint->setY( poInsidePoint->getY() );
-    }
-
-    return OGRERR_NONE;
+    return PointOnSurfaceInternal(poPoint);
 }
 
 /************************************************************************/
@@ -139,7 +167,7 @@ OGRErr OGRMultiPolygon::PointOnSurface( OGRPoint * poPoint ) const
  * \brief Cast to multisurface.
  *
  * The passed in geometry is consumed and a new one returned .
- * 
+ *
  * @param poMP the input geometry - ownership is passed to the method.
  * @return new geometry.
  */
diff --git a/ogr/ogrmultisurface.cpp b/ogr/ogrmultisurface.cpp
index e1c6cbd..b49df39 100644
--- a/ogr/ogrmultisurface.cpp
+++ b/ogr/ogrmultisurface.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmultisurface.cpp 27960 2014-11-14 18:31:32Z rouault $
+ * $Id: ogrmultisurface.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRMultiSurface class.
@@ -31,7 +31,7 @@
 #include "ogr_p.h"
 #include "ogr_api.h"
 
-CPL_CVSID("$Id: ogrmultisurface.cpp 27960 2014-11-14 18:31:32Z rouault $");
+CPL_CVSID("$Id: ogrmultisurface.cpp 33631 2016-03-04 06:28:09Z goatbar $");
 
 /************************************************************************/
 /*                          OGRMultiSurface()                           */
@@ -54,13 +54,57 @@ OGRMultiSurface::~OGRMultiSurface()
 }
 
 /************************************************************************/
+/*              OGRMultiSurface( const OGRMultiSurface& )               */
+/************************************************************************/
+
+/**
+ * \brief Copy constructor.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the constructor
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRMultiSurface::OGRMultiSurface( const OGRMultiSurface& other ) :
+    OGRGeometryCollection(other)
+{
+}
+
+/************************************************************************/
+/*                  operator=( const OGRMultiCurve&)                    */
+/************************************************************************/
+
+/**
+ * \brief Assignment operator.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the operator
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRMultiSurface& OGRMultiSurface::operator=( const OGRMultiSurface& other )
+{
+    if( this != &other)
+    {
+        OGRGeometryCollection::operator=( other );
+    }
+    return *this;
+}
+
+/************************************************************************/
 /*                          getGeometryType()                           */
 /************************************************************************/
 
 OGRwkbGeometryType OGRMultiSurface::getGeometryType() const
 
 {
-    if( getCoordinateDimension() == 3 )
+    if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
+        return wkbMultiSurfaceZM;
+    else if( flags & OGR_G_MEASURED  )
+        return wkbMultiSurfaceM;
+    else if( flags & OGR_G_3D )
         return wkbMultiSurfaceZ;
     else
         return wkbMultiSurface;
@@ -105,14 +149,15 @@ OGRErr OGRMultiSurface::importFromWkt( char ** ppszInput )
 
 {
     int bHasZ = FALSE, bHasM = FALSE;
-    OGRErr      eErr = importPreambuleFromWkt(ppszInput, &bHasZ, &bHasM);
-    if( eErr >= 0 )
+    bool bIsEmpty = false;
+    OGRErr      eErr = importPreambuleFromWkt(ppszInput, &bHasZ, &bHasM, &bIsEmpty);
+    flags = 0;
+    if( eErr != OGRERR_NONE )
         return eErr;
-
-    if( bHasZ )
-        setCoordinateDimension(3);
-
-    int bIsMultiSurface = (wkbFlatten(getGeometryType()) == wkbMultiSurface);
+    if( bHasZ ) flags |= OGR_G_3D;
+    if( bHasM ) flags |= OGR_G_MEASURED;
+    if( bIsEmpty )
+        return OGRERR_NONE;
 
     char        szToken[OGR_WKT_TOKEN_MAX];
     const char  *pszInput = *ppszInput;
@@ -158,8 +203,7 @@ OGRErr OGRMultiSurface::importFromWkt( char ** ppszInput )
         }
         /* We accept POLYGON() but this is an extension to the BNF, also */
         /* accepted by PostGIS */
-        else if (bIsMultiSurface &&
-                 (EQUAL(szToken,"POLYGON") ||
+        else if ((EQUAL(szToken,"POLYGON") ||
                   EQUAL(szToken,"CURVEPOLYGON")))
         {
             OGRGeometry* poGeom = NULL;
@@ -184,7 +228,7 @@ OGRErr OGRMultiSurface::importFromWkt( char ** ppszInput )
         }
 
 /* -------------------------------------------------------------------- */
-/*      Read the delimeter following the surface.                       */
+/*      Read the delimiter following the surface.                       */
 /* -------------------------------------------------------------------- */
         pszInput = OGRWktReadToken( pszInput, szToken );
 
@@ -202,7 +246,7 @@ OGRErr OGRMultiSurface::importFromWkt( char ** ppszInput )
 
     if( szToken[0] != ')' )
         return OGRERR_CORRUPT_DATA;
-    
+
     *ppszInput = (char *) pszInput;
     return OGRERR_NONE;
 }
@@ -237,17 +281,14 @@ OGRBoolean OGRMultiSurface::hasCurveGeometry(int bLookForNonLinear) const
  *
  * NOTE: Only implemented when GEOS included in build.
  *
- * @param poPoint point to be set with an internal point. 
+ * @param poPoint point to be set with an internal point.
  *
- * @return OGRERR_NONE if it succeeds or OGRERR_FAILURE otherwise. 
+ * @return OGRERR_NONE if it succeeds or OGRERR_FAILURE otherwise.
  */
 
 OGRErr OGRMultiSurface::PointOnSurface( OGRPoint * poPoint ) const
 {
-    OGRMultiPolygon* poMPoly = (OGRMultiPolygon*) getLinearGeometry();
-    OGRErr ret = poMPoly->PointOnSurface(poPoint);
-    delete poMPoly;
-    return ret;
+    return PointOnSurfaceInternal(poPoint);
 }
 
 /************************************************************************/
@@ -261,10 +302,10 @@ OGRErr OGRMultiSurface::PointOnSurface( OGRPoint * poPoint ) const
  * instances of OGRPolygon. This can be verified if hasCurveGeometry(TRUE)
  * returns FALSE. It is not intended to approximate curve polygons. For that
  * use getLinearGeometry().
- * 
+ *
  * The passed in geometry is consumed and a new one returned (or NULL in case
- * of failure). 
- * 
+ * of failure).
+ *
  * @param poMS the input geometry - ownership is passed to the method.
  * @return new geometry.
  */
diff --git a/ogr/ogrpgeogeometry.cpp b/ogr/ogrpgeogeometry.cpp
index e1722de..8baf13a 100644
--- a/ogr/ogrpgeogeometry.cpp
+++ b/ogr/ogrpgeogeometry.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgeogeometry.cpp 27959 2014-11-14 18:29:21Z rouault $
+ * $Id: ogrpgeogeometry.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements decoder of shapebin geometry for PGeo
@@ -33,8 +33,9 @@
 #include "ogrpgeogeometry.h"
 #include "ogr_p.h"
 #include "cpl_string.h"
+#include <limits>
 
-CPL_CVSID("$Id: ogrpgeogeometry.cpp 27959 2014-11-14 18:29:21Z rouault $");
+CPL_CVSID("$Id: ogrpgeogeometry.cpp 33631 2016-03-04 06:28:09Z goatbar $");
 
 #define SHPP_TRISTRIP   0
 #define SHPP_TRIFAN     1
@@ -61,15 +62,13 @@ void OGRCreateFromMultiPatchPart(OGRMultiPolygon *poMP,
 
     if( nPartType == SHPP_TRISTRIP )
     {
-        int iBaseVert;
-
         if( poLastPoly != NULL )
         {
             poMP->addGeometryDirectly( poLastPoly );
             poLastPoly = NULL;
         }
 
-        for( iBaseVert = 0; iBaseVert < nPartPoints-2; iBaseVert++ )
+        for( int iBaseVert = 0; iBaseVert < nPartPoints-2; iBaseVert++ )
         {
             OGRPolygon *poPoly = new OGRPolygon();
             OGRLinearRing *poRing = new OGRLinearRing();
@@ -99,15 +98,13 @@ void OGRCreateFromMultiPatchPart(OGRMultiPolygon *poMP,
     }
     else if( nPartType == SHPP_TRIFAN )
     {
-        int iBaseVert;
-
         if( poLastPoly != NULL )
         {
             poMP->addGeometryDirectly( poLastPoly );
             poLastPoly = NULL;
         }
 
-        for( iBaseVert = 0; iBaseVert < nPartPoints-2; iBaseVert++ )
+        for( int iBaseVert = 0; iBaseVert < nPartPoints-2; iBaseVert++ )
         {
             OGRPolygon *poPoly = new OGRPolygon();
             OGRLinearRing *poRing = new OGRLinearRing();
@@ -164,15 +161,13 @@ void OGRCreateFromMultiPatchPart(OGRMultiPolygon *poMP,
     }
     else if ( nPartType == SHPP_TRIANGLES )
     {
-        int iBaseVert;
-
         if( poLastPoly != NULL )
         {
             poMP->addGeometryDirectly( poLastPoly );
             poLastPoly = NULL;
         }
 
-        for( iBaseVert = 0; iBaseVert < nPartPoints-2; iBaseVert+=3 )
+        for( int iBaseVert = 0; iBaseVert < nPartPoints-2; iBaseVert+=3 )
         {
             OGRPolygon *poPoly = new OGRPolygon();
             OGRLinearRing *poRing = new OGRLinearRing();
@@ -201,8 +196,8 @@ void OGRCreateFromMultiPatchPart(OGRMultiPolygon *poMP,
         }
     }
     else
-        CPLDebug( "OGR", "Unrecognised parttype %d, ignored.",
-                nPartType );
+        CPLDebug( "OGR", "Unrecognized parttype %d, ignored.",
+                  nPartType );
 }
 
 /************************************************************************/
@@ -271,11 +266,10 @@ static OGRGeometry* OGRCreateFromMultiPatch(int nParts,
 /*      Translate OGR geometry to a shapefile binary representation     */
 /************************************************************************/
 
-OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom, 
+OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
                            GByte **ppabyShape,
                            int *pnBytes )
 {
-    GUInt32 nGType = SHPT_NULL;
     int nShpSize = 4; /* All types start with integer type number */
     int nShpZSize = 0; /* Z gets tacked onto the end */
     GUInt32 nPoints = 0;
@@ -286,7 +280,9 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
 /* -------------------------------------------------------------------- */
     if ( ! poGeom || poGeom->IsEmpty() )
     {
-        *ppabyShape = (GByte*)VSIMalloc(nShpSize);
+        *ppabyShape = (GByte*)VSI_MALLOC_VERBOSE(nShpSize);
+        if( *ppabyShape == NULL )
+            return OGRERR_FAILURE;
         GUInt32 zero = SHPT_NULL;
         memcpy(*ppabyShape, &zero, nShpSize);
         *pnBytes = nShpSize;
@@ -294,8 +290,9 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
     }
 
     OGRwkbGeometryType nOGRType = wkbFlatten(poGeom->getGeometryType());
-    int b3d = wkbHasZ(poGeom->getGeometryType());
-    int nCoordDims = b3d ? 3 : 2;
+    const bool b3d = wkbHasZ(poGeom->getGeometryType());
+    const bool bHasM = wkbHasM(poGeom->getGeometryType());
+    const int nCoordDims = poGeom->CoordinateDimension();
 
 /* -------------------------------------------------------------------- */
 /*      Calculate the shape buffer size                                 */
@@ -309,7 +306,7 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
         OGRLineString *poLine = (OGRLineString*)poGeom;
         nPoints = poLine->getNumPoints();
         nParts = 1;
-        nShpSize += 16 * nCoordDims; /* xy(z) box */ 
+        nShpSize += 16 * nCoordDims; /* xy(z)(m) box */
         nShpSize += 4; /* nparts */
         nShpSize += 4; /* npoints */
         nShpSize += 4; /* parts[1] */
@@ -330,11 +327,11 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
                 poRing = poPoly->getInteriorRing(i-1);
             nPoints += poRing->getNumPoints();
         }
-        nShpSize += 16 * nCoordDims; /* xy(z) box */ 
+        nShpSize += 16 * nCoordDims; /* xy(z)(m) box */
         nShpSize += 4; /* nparts */
         nShpSize += 4; /* npoints */
         nShpSize += 4 * nParts; /* parts[nparts] */
-        nShpSize += 8 * nCoordDims * nPoints; /* points */    
+        nShpSize += 8 * nCoordDims * nPoints; /* points */
         nShpZSize = 16 + 8 * nPoints;
     }
     else if ( nOGRType == wkbMultiPoint )
@@ -343,13 +340,13 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
         for ( int i = 0; i < poMPoint->getNumGeometries(); i++ )
         {
             OGRPoint *poPoint = (OGRPoint*)(poMPoint->getGeometryRef(i));
-            if ( poPoint->IsEmpty() ) 
+            if ( poPoint->IsEmpty() )
                 continue;
             nPoints++;
         }
-        nShpSize += 16 * nCoordDims; /* xy(z) box */ 
+        nShpSize += 16 * nCoordDims; /* xy(z)(m) box */
         nShpSize += 4; /* npoints */
-        nShpSize += 8 * nCoordDims * nPoints; /* points */    
+        nShpSize += 8 * nCoordDims * nPoints; /* points */
         nShpZSize = 16 + 8 * nPoints;
     }
     else if ( nOGRType == wkbMultiLineString )
@@ -359,16 +356,16 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
         {
             OGRLineString *poLine = (OGRLineString*)(poMLine->getGeometryRef(i));
             /* Skip empties */
-            if ( poLine->IsEmpty() ) 
+            if ( poLine->IsEmpty() )
                 continue;
             nParts++;
             nPoints += poLine->getNumPoints();
         }
-        nShpSize += 16 * nCoordDims; /* xy(z) box */ 
+        nShpSize += 16 * nCoordDims; /* xy(z)(m) box */
         nShpSize += 4; /* nparts */
         nShpSize += 4; /* npoints */
         nShpSize += 4 * nParts; /* parts[nparts] */
-        nShpSize += 8 * nCoordDims * nPoints ; /* points */    
+        nShpSize += 8 * nCoordDims * nPoints ; /* points */
         nShpZSize = 16 + 8 * nPoints;
     }
     else if ( nOGRType == wkbMultiPolygon )
@@ -381,7 +378,7 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
             int nRings = poPoly->getNumInteriorRings() + 1;
 
             /* Skip empties */
-            if ( poPoly->IsEmpty() ) 
+            if ( poPoly->IsEmpty() )
                 continue;
 
             nParts += nRings;
@@ -395,11 +392,11 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
                 nPoints += poRing->getNumPoints();
             }
         }
-        nShpSize += 16 * nCoordDims; /* xy(z) box */ 
+        nShpSize += 16 * nCoordDims; /* xy(z)(m) box */
         nShpSize += 4; /* nparts */
         nShpSize += 4; /* npoints */
         nShpSize += 4 * nParts; /* parts[nparts] */
-        nShpSize += 8 * nCoordDims * nPoints ; /* points */  
+        nShpSize += 8 * nCoordDims * nPoints ; /* points */
         nShpZSize = 16 + 8 * nPoints;
     }
     else
@@ -408,7 +405,7 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
     }
 
     /* Allocate our shape buffer */
-    *ppabyShape = (GByte*)VSIMalloc(nShpSize);
+    *ppabyShape = (GByte*)VSI_MALLOC_VERBOSE(nShpSize);
     if ( ! *ppabyShape )
         return OGRERR_FAILURE;
 
@@ -418,34 +415,56 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
     /* Set up write pointers */
     unsigned char *pabyPtr = *ppabyShape;
     unsigned char *pabyPtrZ = NULL;
+    unsigned char *pabyPtrM = NULL;
+    if( bHasM )
+        pabyPtrM = pabyPtr + nShpSize - nShpZSize;
     if ( b3d )
-        pabyPtrZ = pabyPtr + nShpSize - nShpZSize;
+    {
+        if( bHasM )
+            pabyPtrZ = pabyPtrM - nShpZSize;
+        else
+            pabyPtrZ = pabyPtr + nShpSize - nShpZSize;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Write in the Shape type number now                              */
 /* -------------------------------------------------------------------- */
+    GUInt32 nGType = SHPT_NULL;
+
     switch(nOGRType)
     {
         case wkbPoint:
         {
-            nGType = b3d ? SHPT_POINTZ : SHPT_POINT;
+            nGType = (b3d && bHasM) ? SHPT_POINTZM :
+                     (b3d)          ? SHPT_POINTZ :
+                     (bHasM)        ? SHPT_POINTM :
+                                      SHPT_POINT;
             break;
         }
         case wkbMultiPoint:
         {
-            nGType = b3d ? SHPT_MULTIPOINTZ : SHPT_MULTIPOINT;
+            nGType = (b3d && bHasM) ? SHPT_MULTIPOINTZM :
+                     (b3d)          ? SHPT_MULTIPOINTZ :
+                     (bHasM)        ? SHPT_MULTIPOINTM :
+                                      SHPT_MULTIPOINT;
             break;
         }
         case wkbLineString:
         case wkbMultiLineString:
         {
-            nGType = b3d ? SHPT_ARCZ : SHPT_ARC;
+            nGType = (b3d && bHasM) ? SHPT_ARCZM :
+                     (b3d)          ? SHPT_ARCZ :
+                     (bHasM)        ? SHPT_ARCM :
+                                      SHPT_ARC;
             break;
         }
         case wkbPolygon:
         case wkbMultiPolygon:
         {
-            nGType = b3d ? SHPT_POLYGONZ : SHPT_POLYGON;
+            nGType = (b3d && bHasM) ? SHPT_POLYGONZM :
+                     (b3d)          ? SHPT_POLYGONZ :
+                     (bHasM)        ? SHPT_POLYGONM :
+                                      SHPT_POLYGON;
             break;
         }
         default:
@@ -476,6 +495,11 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
             double z = poPoint->getZ();
             memcpy( pabyPtr+8+8, &z, 8 );
         }
+        if( bHasM )
+        {
+            double m = poPoint->getM();
+            memcpy( pabyPtr+8+((b3d) ? 16 : 8), &m, 8 );
+        }
 
         /* Swap if needed. Shape doubles always LSB */
         if( OGR_SWAP( wkbNDR ) )
@@ -484,9 +508,11 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
             CPL_SWAPDOUBLE( pabyPtr+8 );
             if( b3d )
                 CPL_SWAPDOUBLE( pabyPtr+8+8 );
+            if( bHasM )
+                CPL_SWAPDOUBLE( pabyPtr+8+((b3d) ? 16 : 8) );
         }
 
-        return OGRERR_NONE;    
+        return OGRERR_NONE;
     }
 
 /* -------------------------------------------------------------------- */
@@ -518,10 +544,20 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
         {
             for ( int i = 0; i < 2; i++ )
                 CPL_SWAPDOUBLE( pabyPtrZ + 8*i );
-        } 
+        }
         pabyPtrZ += 16;
     }
 
+    /* Reserve space for the M bounds at the end of the XY buffer */
+    GByte* pabyPtrMBounds = NULL;
+    double dfMinM = std::numeric_limits<double>::max();
+    double dfMaxM = -dfMinM;
+    if ( bHasM )
+    {
+        pabyPtrMBounds = pabyPtrM;
+        pabyPtrM += 16;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      LINESTRING and LINESTRINGZ                                      */
 /* -------------------------------------------------------------------- */
@@ -546,6 +582,17 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
 
         /* Write in the point data */
         poLine->getPoints((OGRRawPoint*)pabyPtr, (double*)pabyPtrZ);
+        if( bHasM )
+        {
+            for( GUInt32 k = 0; k < nPoints; k++ )
+            {
+                double dfM = poLine->getM(k);
+                memcpy( pabyPtrM + 8*k, &dfM, 8);
+                if( dfM < dfMinM ) dfMinM = dfM;
+                if( dfM > dfMaxM ) dfMaxM = dfM;
+            }
+        }
+
 
         /* Swap if necessary */
         if( OGR_SWAP( wkbNDR ) )
@@ -556,10 +603,10 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
                 CPL_SWAPDOUBLE( pabyPtr + 16*k + 8 );
                 if( b3d )
                     CPL_SWAPDOUBLE( pabyPtrZ + 8*k );
+                if( bHasM )
+                    CPL_SWAPDOUBLE( pabyPtrM + 8*k );
             }
         }
-        return OGRERR_NONE;    
-
     }
 /* -------------------------------------------------------------------- */
 /*      POLYGON and POLYGONZ                                            */
@@ -588,7 +635,7 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
 /* -------------------------------------------------------------------- */
 
         /* Just past the partindex[nparts] array */
-        unsigned char* pabyPoints = pabyPtr + 4*nParts; 
+        unsigned char* pabyPoints = pabyPtr + 4*nParts;
 
         int nPointIndexCount = 0;
 
@@ -596,7 +643,7 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
         {
             /* Check our Ring and condition it */
             OGRLinearRing *poRing;
-            if ( i == 0 ) 
+            if ( i == 0 )
             {
                 poRing = poPoly->getExteriorRing();
                 /* Outer ring must be clockwise */
@@ -623,6 +670,16 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
 
             /* Write in the point data */
             poRing->getPoints((OGRRawPoint*)pabyPoints, (double*)pabyPtrZ);
+            if( bHasM )
+            {
+                for( int k = 0; k < nRingNumPoints; k++ )
+                {
+                    double dfM = poRing->getM(k);
+                    memcpy( pabyPtrM + 8*k, &dfM, 8);
+                    if( dfM < dfMinM ) dfMinM = dfM;
+                    if( dfM > dfMaxM ) dfMaxM = dfM;
+                }
+            }
 
             /* Swap if necessary */
             if( OGR_SWAP( wkbNDR ) )
@@ -633,6 +690,8 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
                     CPL_SWAPDOUBLE( pabyPoints + 16*k + 8 );
                     if( b3d )
                         CPL_SWAPDOUBLE( pabyPtrZ + 8*k );
+                    if( bHasM )
+                        CPL_SWAPDOUBLE( pabyPtrM + 8*k );
                 }
             }
 
@@ -641,11 +700,10 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
             pabyPtr += 4;
             pabyPoints += 16 * nRingNumPoints;
             if ( b3d )
-                pabyPtrZ += 8 * nRingNumPoints; 
+                pabyPtrZ += 8 * nRingNumPoints;
+            if ( bHasM )
+                pabyPtrM += 8 * nRingNumPoints;
         }
-
-        return OGRERR_NONE;
-
     }
 /* -------------------------------------------------------------------- */
 /*      MULTIPOINT and MULTIPOINTZ                                      */
@@ -671,7 +729,7 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
             const OGRPoint *poPt = (OGRPoint*)(poMPoint->getGeometryRef(i));
 
             /* Skip empties */
-            if ( poPt->IsEmpty() ) 
+            if ( poPt->IsEmpty() )
                 continue;
 
             /* Write the coordinates */
@@ -684,6 +742,13 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
                 double z = poPt->getZ();
                 memcpy(pabyPtrZ, &z, 8);
             }
+            if ( bHasM )
+            {
+                double dfM = poPt->getM();
+                memcpy(pabyPtrM, &dfM, 8);
+                if( dfM < dfMinM ) dfMinM = dfM;
+                if( dfM > dfMaxM ) dfMaxM = dfM;
+            }
 
             /* Swap if necessary */
             if( OGR_SWAP( wkbNDR ) )
@@ -692,15 +757,17 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
                 CPL_SWAPDOUBLE( pabyPtr + 8 );
                 if( b3d )
                     CPL_SWAPDOUBLE( pabyPtrZ );
+                if( bHasM )
+                    CPL_SWAPDOUBLE( pabyPtrM );
             }
 
             /* Advance the write pointers */
             pabyPtr += 16;
             if ( b3d )
-                pabyPtrZ += 8; 
-        }    
-
-        return OGRERR_NONE;
+                pabyPtrZ += 8;
+            if ( bHasM )
+                pabyPtrM += 8;
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -721,7 +788,7 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
         pabyPtr += 4;
 
         /* Just past the partindex[nparts] array */
-        unsigned char* pabyPoints = pabyPtr + 4*nParts; 
+        unsigned char* pabyPoints = pabyPtr + 4*nParts;
 
         int nPointIndexCount = 0;
 
@@ -730,7 +797,7 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
             const OGRLineString *poLine = (OGRLineString*)(poMLine->getGeometryRef(i));
 
             /* Skip empties */
-            if ( poLine->IsEmpty() ) 
+            if ( poLine->IsEmpty() )
                 continue;
 
             int nLineNumPoints = poLine->getNumPoints();
@@ -741,6 +808,16 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
 
             /* Write in the point data */
             poLine->getPoints((OGRRawPoint*)pabyPoints, (double*)pabyPtrZ);
+            if( bHasM )
+            {
+                for( int k = 0; k < nLineNumPoints; k++ )
+                {
+                    double dfM = poLine->getM(k);
+                    memcpy( pabyPtrM + 8*k, &dfM, 8);
+                    if( dfM < dfMinM ) dfMinM = dfM;
+                    if( dfM > dfMaxM ) dfMaxM = dfM;
+                }
+            }
 
             /* Swap if necessary */
             if( OGR_SWAP( wkbNDR ) )
@@ -751,6 +828,8 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
                     CPL_SWAPDOUBLE( pabyPoints + 16*k + 8 );
                     if( b3d )
                         CPL_SWAPDOUBLE( pabyPtrZ + 8*k );
+                    if( bHasM )
+                        CPL_SWAPDOUBLE( pabyPtrM + 8*k );
                 }
             }
 
@@ -760,16 +839,15 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
             pabyPtr += 4;
             pabyPoints += 16 * nLineNumPoints;
             if ( b3d )
-                pabyPtrZ += 8 * nLineNumPoints; 
+                pabyPtrZ += 8 * nLineNumPoints;
+            if ( bHasM )
+                pabyPtrM += 8 * nLineNumPoints;
         }
-
-        return OGRERR_NONE;      
-
     }
 /* -------------------------------------------------------------------- */
 /*      MULTIPOLYGON and MULTIPOLYGONZ                                  */
 /* -------------------------------------------------------------------- */
-    else if ( nOGRType == wkbMultiPolygon )
+    else /* if ( nOGRType == wkbMultiPolygon ) */
     {
         OGRMultiPolygon *poMPoly = (OGRMultiPolygon*)poGeom;
 
@@ -793,7 +871,7 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
 /* -------------------------------------------------------------------- */
 
         /* Just past the partindex[nparts] array */
-        unsigned char* pabyPoints = pabyPtr + 4*nParts; 
+        unsigned char* pabyPoints = pabyPtr + 4*nParts;
 
         int nPointIndexCount = 0;
 
@@ -802,7 +880,7 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
             OGRPolygon *poPoly = (OGRPolygon*)(poMPoly->getGeometryRef(i));
 
             /* Skip empties */
-            if ( poPoly->IsEmpty() ) 
+            if ( poPoly->IsEmpty() )
                 continue;
 
             int nRings = 1 + poPoly->getNumInteriorRings();
@@ -838,6 +916,16 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
 
                 /* Write in the point data */
                 poRing->getPoints((OGRRawPoint*)pabyPoints, (double*)pabyPtrZ);
+                if( bHasM )
+                {
+                    for( int k = 0; k < nRingNumPoints; k++ )
+                    {
+                        double dfM = poRing->getM(k);
+                        memcpy( pabyPtrM + 8*k, &dfM, 8);
+                        if( dfM < dfMinM ) dfMinM = dfM;
+                        if( dfM > dfMaxM ) dfMaxM = dfM;
+                    }
+                }
 
                 /* Swap if necessary */
                 if( OGR_SWAP( wkbNDR ) )
@@ -848,6 +936,8 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
                         CPL_SWAPDOUBLE( pabyPoints + 16*k + 8 );
                         if( b3d )
                             CPL_SWAPDOUBLE( pabyPtrZ + 8*k );
+                        if( bHasM )
+                            CPL_SWAPDOUBLE( pabyPtrM + 8*k );
                     }
                 }
 
@@ -856,32 +946,46 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
                 pabyPtr += 4;
                 pabyPoints += 16 * nRingNumPoints;
                 if ( b3d )
-                    pabyPtrZ += 8 * nRingNumPoints; 
+                    pabyPtrZ += 8 * nRingNumPoints;
+                if ( bHasM )
+                    pabyPtrM += 8 * nRingNumPoints;
             }
         }
-
-        return OGRERR_NONE;
-
     }
-    else
+
+    if ( bHasM )
     {
-        return OGRERR_UNSUPPORTED_OPERATION;
+        if( dfMinM > dfMaxM )
+        {
+            dfMinM = 0.0;
+            dfMaxM = 0.0;
+        }
+        memcpy( pabyPtrMBounds, &(dfMinM), 8 );
+        memcpy( pabyPtrMBounds+8, &(dfMaxM), 8 );
+
+        /* Swap M bounds if necessary */
+        if( OGR_SWAP( wkbNDR ) )
+        {
+            for ( int i = 0; i < 2; i++ )
+                CPL_SWAPDOUBLE( pabyPtrMBounds + 8*i );
+        }
     }
 
-}  
+    return OGRERR_NONE;
+}
 
 
 /************************************************************************/
 /*                   OGRWriteMultiPatchToShapeBin()                     */
 /************************************************************************/
 
-OGRErr OGRWriteMultiPatchToShapeBin( OGRGeometry *poGeom, 
+OGRErr OGRWriteMultiPatchToShapeBin( OGRGeometry *poGeom,
                                      GByte **ppabyShape,
                                      int *pnBytes )
 {
     if( wkbFlatten(poGeom->getGeometryType()) != wkbMultiPolygon )
         return OGRERR_UNSUPPORTED_OPERATION;
-    
+
     poGeom->closeRings();
     OGRMultiPolygon *poMPoly = (OGRMultiPolygon*)poGeom;
     int nParts = 0;
@@ -898,13 +1002,13 @@ OGRErr OGRWriteMultiPatchToShapeBin( OGRGeometry *poGeom,
         int nRings = poPoly->getNumInteriorRings() + 1;
 
         /* Skip empties */
-        if ( poPoly->IsEmpty() ) 
+        if ( poPoly->IsEmpty() )
             continue;
 
         OGRLinearRing *poRing = poPoly->getExteriorRing();
         if( nRings == 1 && poRing->getNumPoints() == 4 )
         {
-            if( nParts > 0 &&
+            if( nParts > 0 && poPoints != NULL &&
                 ((panPartType[nParts-1] == SHPP_TRIANGLES && nPoints - panPartStart[nParts-1] == 3) ||
                  panPartType[nParts-1] == SHPP_TRIFAN) &&
                 poRing->getX(0) == poPoints[nBeginLastPart].x &&
@@ -924,7 +1028,7 @@ OGRErr OGRWriteMultiPatchToShapeBin( OGRGeometry *poGeom,
                 padfZ[nPoints] = poRing->getZ(2);
                 nPoints ++;
             }
-            else if( nParts > 0 &&
+            else if( nParts > 0 && poPoints != NULL &&
                 ((panPartType[nParts-1] == SHPP_TRIANGLES && nPoints - panPartStart[nParts-1] == 3) ||
                  panPartType[nParts-1] == SHPP_TRISTRIP) &&
                 poRing->getX(0) == poPoints[nPoints-2].x &&
@@ -1005,7 +1109,7 @@ OGRErr OGRWriteMultiPatchToShapeBin( OGRGeometry *poGeom,
     }
 
     int nShpSize = 4; /* All types start with integer type number */
-    nShpSize += 16 * 2; /* xy bbox */ 
+    nShpSize += 16 * 2; /* xy bbox */
     nShpSize += 4; /* nparts */
     nShpSize += 4; /* npoints */
     nShpSize += 4 * nParts; /* panPartStart[nparts] */
@@ -1063,7 +1167,9 @@ OGRErr OGRWriteMultiPatchToShapeBin( OGRGeometry *poGeom,
         pabyPtr += 4;
     }
 
-    memcpy(pabyPtr, poPoints, 2 * 8 * nPoints);
+    if( poPoints != NULL )
+        memcpy(pabyPtr, poPoints, 2 * 8 * nPoints);
+
     /* Swap box if needed. Shape doubles are always LSB */
     if( OGR_SWAP( wkbNDR ) )
     {
@@ -1080,16 +1186,17 @@ OGRErr OGRWriteMultiPatchToShapeBin( OGRGeometry *poGeom,
             CPL_SWAPDOUBLE( pabyPtr + 8*i );
     }
     pabyPtr += 16;
-    
-    memcpy(pabyPtr, padfZ, 8 * nPoints);
+
+    if( padfZ != NULL )
+        memcpy(pabyPtr, padfZ, 8 * nPoints);
     /* Swap box if needed. Shape doubles are always LSB */
     if( OGR_SWAP( wkbNDR ) )
     {
         for ( i = 0; i < nPoints; i++ )
             CPL_SWAPDOUBLE( pabyPtr + 8*i );
     }
-    pabyPtr +=  8 * nPoints;
-    
+    //pabyPtr +=  8 * nPoints;
+
     CPLFree(panPartStart);
     CPLFree(panPartType);
     CPLFree(poPoints);
@@ -1113,7 +1220,7 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
     *ppoGeom = NULL;
 
     if( nBytes < 4 )
-    {    
+    {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Shape buffer size (%d) too small",
                  nBytes);
@@ -1136,12 +1243,9 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
         if (nCompressedSize + 12 == nBytes &&
             nUncompressedSize > 0)
         {
-            GByte* pabyUncompressedBuffer = (GByte*)VSIMalloc(nUncompressedSize);
+            GByte* pabyUncompressedBuffer = (GByte*)VSI_MALLOC_VERBOSE(nUncompressedSize);
             if (pabyUncompressedBuffer == NULL)
             {
-                CPLError(CE_Failure, CPLE_OutOfMemory,
-                         "Cannot allocate %d bytes to uncompress zlib buffer",
-                         nUncompressedSize);
                 return OGRERR_FAILURE;
             }
 
@@ -1158,7 +1262,7 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
 
             OGRErr eErr = OGRCreateFromShapeBin(pabyUncompressedBuffer,
                                                 ppoGeom,
-                                                nRealUncompressedSize);
+                                                static_cast<int>(nRealUncompressedSize));
 
             VSIFree(pabyUncompressedBuffer);
 
@@ -1183,6 +1287,33 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
 //              "Shape type read from PGeo data is nSHPType = %d",
 //              nSHPType );
 
+    const bool bIsExtended = ( nSHPType >= SHPT_GENERALPOLYLINE && nSHPType <= SHPT_GENERALMULTIPATCH );
+
+    const bool bHasZ = (
+                   nSHPType == SHPT_POINTZ
+                || nSHPType == SHPT_POINTZM
+                || nSHPType == SHPT_MULTIPOINTZ
+                || nSHPType == SHPT_MULTIPOINTZM
+                || nSHPType == SHPT_POLYGONZ
+                || nSHPType == SHPT_POLYGONZM
+                || nSHPType == SHPT_ARCZ
+                || nSHPType == SHPT_ARCZM
+                || nSHPType == SHPT_MULTIPATCH
+                || nSHPType == SHPT_MULTIPATCHM
+                || (bIsExtended && (pabyShape[3] & 0x80) != 0 ) );
+
+    const bool bHasM = (
+                   nSHPType == SHPT_POINTM
+                || nSHPType == SHPT_POINTZM
+                || nSHPType == SHPT_MULTIPOINTM
+                || nSHPType == SHPT_MULTIPOINTZM
+                || nSHPType == SHPT_POLYGONM
+                || nSHPType == SHPT_POLYGONZM
+                || nSHPType == SHPT_ARCM
+                || nSHPType == SHPT_ARCZM
+                || nSHPType == SHPT_MULTIPATCHM
+                || (bIsExtended && (pabyShape[3] & 0x40) != 0 ) );
+
 /* -------------------------------------------------------------------- */
 /*      TODO: These types include additional attributes including       */
 /*      non-linear segments and such. They should be handled.           */
@@ -1251,13 +1382,6 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
             return OGRERR_FAILURE;
         }
 
-        int bHasZ = (  nSHPType == SHPT_POLYGONZ
-                    || nSHPType == SHPT_POLYGONZM
-                    || nSHPType == SHPT_ARCZ
-                    || nSHPType == SHPT_ARCZM
-                    || nSHPType == SHPT_MULTIPATCH
-                    || nSHPType == SHPT_MULTIPATCHM );
-
         int bIsMultiPatch = ( nSHPType == SHPT_MULTIPATCH || nSHPType == SHPT_MULTIPATCHM );
 
         /* With the previous checks on nPoints and nParts, */
@@ -1268,6 +1392,10 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
         {
             nRequiredSize += 16 + 8 * nPoints;
         }
+        if ( bHasM )
+        {
+            nRequiredSize += 16 + 8 * nPoints;
+        }
         if( bIsMultiPatch )
         {
             nRequiredSize += 4 * nParts;
@@ -1280,11 +1408,9 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
             return OGRERR_FAILURE;
         }
 
-        panPartStart = (GInt32 *) VSICalloc(nParts,sizeof(GInt32));
+        panPartStart = (GInt32 *) VSI_CALLOC_VERBOSE(nParts,sizeof(GInt32));
         if (panPartStart == NULL)
         {
-            CPLError(CE_Failure, CPLE_OutOfMemory,
-                     "Not enough memory for shape (nPoints=%d, nParts=%d)", nPoints, nParts);
             return OGRERR_FAILURE;
         }
 
@@ -1323,11 +1449,9 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
 /* -------------------------------------------------------------------- */
         if( bIsMultiPatch )
         {
-            panPartType = (GInt32 *) VSICalloc(nParts,sizeof(GInt32));
+            panPartType = (GInt32 *) VSI_CALLOC_VERBOSE(nParts,sizeof(GInt32));
             if (panPartType == NULL)
             {
-                CPLError(CE_Failure, CPLE_OutOfMemory,
-                        "Not enough memory for panPartType for shape (nPoints=%d, nParts=%d)", nPoints, nParts);
                 CPLFree(panPartStart);
                 return OGRERR_FAILURE;
             }
@@ -1343,18 +1467,18 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
 /* -------------------------------------------------------------------- */
 /*      Copy out the vertices from the record.                          */
 /* -------------------------------------------------------------------- */
-        double *padfX = (double *) VSIMalloc(sizeof(double)*nPoints);
-        double *padfY = (double *) VSIMalloc(sizeof(double)*nPoints);
-        double *padfZ = (double *) VSICalloc(sizeof(double),nPoints);
-        if (padfX == NULL || padfY == NULL || padfZ == NULL)
+        double *padfX = (double *) VSI_MALLOC_VERBOSE(sizeof(double)*nPoints);
+        double *padfY = (double *) VSI_MALLOC_VERBOSE(sizeof(double)*nPoints);
+        double *padfZ = (double *) VSI_CALLOC_VERBOSE(sizeof(double),nPoints);
+        double *padfM = (double *) (bHasM ? VSI_CALLOC_VERBOSE(sizeof(double),nPoints) : NULL);
+        if (padfX == NULL || padfY == NULL || padfZ == NULL || (bHasM && padfM == NULL))
         {
             CPLFree( panPartStart );
             CPLFree( panPartType );
             CPLFree( padfX );
             CPLFree( padfY );
             CPLFree( padfZ );
-            CPLError(CE_Failure, CPLE_OutOfMemory,
-                     "Not enough memory for shape (nPoints=%d, nParts=%d)", nPoints, nParts);
+            CPLFree( padfM );
             return OGRERR_FAILURE;
         }
 
@@ -1383,6 +1507,19 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
         }
 
 /* -------------------------------------------------------------------- */
+/*      If we have a M coordinate, collect that now.                    */
+/* -------------------------------------------------------------------- */
+        if( bHasM )
+        {
+            for( i = 0; i < nPoints; i++ )
+            {
+                memcpy( padfM + i, pabyShape + nOffset + 16 + i*8, 8 );
+                CPL_LSBPTR64( padfM + i );
+            }
+
+            //nOffset += 16 + 8*nPoints;
+        }
+/* -------------------------------------------------------------------- */
 /*      Build corresponding OGR objects.                                */
 /* -------------------------------------------------------------------- */
         if(    nSHPType == SHPT_ARC
@@ -1398,7 +1535,7 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
                 OGRLineString *poLine = new OGRLineString();
                 *ppoGeom = poLine;
 
-                poLine->setPoints( nPoints, padfX, padfY, padfZ );
+                poLine->setPoints( nPoints, padfX, padfY, padfZ, padfM );
             }
 
 /* -------------------------------------------------------------------- */
@@ -1423,7 +1560,8 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
                     poLine->setPoints( nVerticesInThisPart,
                                        padfX + panPartStart[i],
                                        padfY + panPartStart[i],
-                                       padfZ + panPartStart[i] );
+                                       padfZ + panPartStart[i],
+                                       (padfM != NULL) ? padfM + panPartStart[i] : NULL );
 
                     poMulti->addGeometryDirectly( poLine );
                 }
@@ -1450,7 +1588,8 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
                     poRing->setPoints( nVerticesInThisPart,
                                        padfX + panPartStart[0],
                                        padfY + panPartStart[0],
-                                       padfZ + panPartStart[0] );
+                                       padfZ + panPartStart[0],
+                                       (padfM != NULL) ? padfM + panPartStart[0] : NULL );
 
                     poOGRPoly->addRingDirectly( poRing );
                 }
@@ -1474,7 +1613,8 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
                         poRing->setPoints( nVerticesInThisPart,
                                            padfX + panPartStart[i],
                                            padfY + panPartStart[i],
-                                           padfZ + panPartStart[i] );
+                                           padfZ + panPartStart[i],
+                                           (padfM != NULL) ? padfM + panPartStart[i] : NULL );
                         tabPolygons[i]->addRingDirectly(poRing);
                     }
 
@@ -1515,9 +1655,13 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
         CPLFree( padfX );
         CPLFree( padfY );
         CPLFree( padfZ );
+        CPLFree( padfM );
 
         if (*ppoGeom != NULL)
-            (*ppoGeom)->setCoordinateDimension( bHasZ ? 3 : 2 );
+        {
+            if( !bHasZ )
+                (*ppoGeom)->set3D(FALSE);
+        }
 
         return OGRERR_NONE;
     }
@@ -1532,12 +1676,9 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
     {
       GInt32 nPoints;
       GInt32 nOffsetZ;
+      GInt32 nOffsetM = 0;
       int i;
 
-      int bHasZ = (  nSHPType == SHPT_MULTIPOINTZ
-                  || nSHPType == SHPT_MULTIPOINTZM );
-
-                
       memcpy( &nPoints, pabyShape + 36, 4 );
       CPL_LSBPTR32( &nPoints );
 
@@ -1549,38 +1690,51 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
       }
 
       nOffsetZ = 40 + 2*8*nPoints + 2*8;
-    
+      if( bHasM )
+          nOffsetM = (bHasZ) ? nOffsetZ + 2*8 * 8*nPoints : nOffsetZ;
+
       OGRMultiPoint *poMultiPt = new OGRMultiPoint;
       *ppoGeom = poMultiPt;
 
       for( i = 0; i < nPoints; i++ )
       {
-          double x, y, z;
+          double x, y;
           OGRPoint *poPt = new OGRPoint;
-        
+
           /* Copy X */
           memcpy(&x, pabyShape + 40 + i*16, 8);
           CPL_LSBPTR64(&x);
           poPt->setX(x);
-        
+
           /* Copy Y */
           memcpy(&y, pabyShape + 40 + i*16 + 8, 8);
           CPL_LSBPTR64(&y);
           poPt->setY(y);
-        
+
           /* Copy Z */
           if ( bHasZ )
           {
+            double z;
             memcpy(&z, pabyShape + nOffsetZ + i*8, 8);
             CPL_LSBPTR64(&z);
             poPt->setZ(z);
           }
-        
+
+          /* Copy M */
+          if ( bHasM )
+          {
+            double m;
+            memcpy(&m, pabyShape + nOffsetM + i*8, 8);
+            CPL_LSBPTR64(&m);
+            poPt->setM(m);
+          }
+
           poMultiPt->addGeometryDirectly( poPt );
       }
-      
-      poMultiPt->setCoordinateDimension( bHasZ ? 3 : 2 );
-      
+
+      poMultiPt->set3D( bHasZ );
+      poMultiPt->setMeasured( bHasM );
+
       return OGRERR_NONE;
     }
 
@@ -1593,11 +1747,9 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
              || nSHPType == SHPT_POINTZM )
     {
         /* int nOffset; */
-        double  dfX, dfY, dfZ = 0;
-
-        int bHasZ = (nSHPType == SHPT_POINTZ || nSHPType == SHPT_POINTZM);
+        double  dfX, dfY, dfZ = 0, dfM = 0;
 
-        if (nBytes < 4 + 8 + 8 + ((bHasZ) ? 8 : 0))
+        if (nBytes < 4 + 8 + 8 + ((bHasZ) ? 8 : 0) + ((bHasM) ? 8 : 0))
         {
             CPLError(CE_Failure, CPLE_AppDefined,
                      "Corrupted Shape : nBytes=%d, nSHPType=%d", nBytes, nSHPType);
@@ -1617,8 +1769,24 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
             CPL_LSBPTR64( &dfZ );
         }
 
-        *ppoGeom = new OGRPoint( dfX, dfY, dfZ );
-        (*ppoGeom)->setCoordinateDimension( bHasZ ? 3 : 2 );
+        if( bHasM )
+        {
+            memcpy( &dfM, pabyShape + 4 + 16 + ((bHasZ) ? 8 : 0), 8 );
+            CPL_LSBPTR64( &dfM );
+        }
+
+        if( bHasZ && bHasM )
+            *ppoGeom = new OGRPoint( dfX, dfY, dfZ, dfM );
+        else if( bHasZ )
+            *ppoGeom = new OGRPoint( dfX, dfY, dfZ );
+        else if( bHasM )
+        {
+            OGRPoint* poPoint = new OGRPoint( dfX, dfY );
+            poPoint->setM(dfM);
+            *ppoGeom = poPoint;
+        }
+        else
+            *ppoGeom = new OGRPoint( dfX, dfY );
 
         return OGRERR_NONE;
     }
diff --git a/ogr/ogrpgeogeometry.h b/ogr/ogrpgeogeometry.h
index 7b7b22b..c883875 100644
--- a/ogr/ogrpgeogeometry.h
+++ b/ogr/ogrpgeogeometry.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgeogeometry.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: ogrpgeogeometry.h 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements decoder of shapebin geometry for PGeo
@@ -28,8 +28,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_PGEOGEOMETRY_H_INCLUDED
-#define _OGR_PGEOGEOMETRY_H_INCLUDED
+#ifndef OGR_PGEOGEOMETRY_H_INCLUDED
+#define OGR_PGEOGEOMETRY_H_INCLUDED
 
 #include "ogr_geometry.h"
 
@@ -85,11 +85,11 @@ OGRErr CPL_DLL OGRCreateFromShapeBin( GByte *pabyShape,
                               OGRGeometry **ppoGeom,
                               int nBytes );
 
-OGRErr CPL_DLL OGRWriteToShapeBin( OGRGeometry *poGeom, 
+OGRErr CPL_DLL OGRWriteToShapeBin( OGRGeometry *poGeom,
                            GByte **ppabyShape,
                            int *pnBytes );
 
-OGRErr CPL_DLL OGRWriteMultiPatchToShapeBin( OGRGeometry *poGeom, 
+OGRErr CPL_DLL OGRWriteMultiPatchToShapeBin( OGRGeometry *poGeom,
                            GByte **ppabyShape,
                            int *pnBytes );
 
diff --git a/ogr/ogrpoint.cpp b/ogr/ogrpoint.cpp
index d46f4f7..03ec928 100644
--- a/ogr/ogrpoint.cpp
+++ b/ogr/ogrpoint.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpoint.cpp 27959 2014-11-14 18:29:21Z rouault $
+ * $Id: ogrpoint.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The Point geometry class.
@@ -33,25 +33,23 @@
 
 /* for std::numeric_limits */
 #include <limits>
+#include <new>
 
-CPL_CVSID("$Id: ogrpoint.cpp 27959 2014-11-14 18:29:21Z rouault $");
-
-/* CAUTION: we use nCoordDimension == -2 to mean POINT EMPTY (2D) and
-                   nCoordDimension == -3 to mean POINT Z EMPTY
-*/
+CPL_CVSID("$Id: ogrpoint.cpp 33631 2016-03-04 06:28:09Z goatbar $");
 
 /************************************************************************/
 /*                              OGRPoint()                              */
 /************************************************************************/
 
 /**
- * \brief Create a (0,0) point.
+ * \brief Create an empty point.
  */
 
 OGRPoint::OGRPoint()
 
 {
     empty();
+    flags = 0;
 }
 
 /************************************************************************/
@@ -66,7 +64,8 @@ OGRPoint::OGRPoint( double xIn, double yIn, double zIn )
     x = xIn;
     y = yIn;
     z = zIn;
-    nCoordDimension = 3;
+    m = 0.0;
+    flags = OGR_G_NOT_EMPTY_POINT | OGR_G_3D;
 }
 
 /************************************************************************/
@@ -81,7 +80,46 @@ OGRPoint::OGRPoint( double xIn, double yIn )
     x = xIn;
     y = yIn;
     z = 0.0;
-    nCoordDimension = 2;
+    m = 0.0;
+    flags = OGR_G_NOT_EMPTY_POINT;
+}
+
+/************************************************************************/
+/*                              OGRPoint()                              */
+/*                                                                      */
+/*      Initialize point to value.                                      */
+/************************************************************************/
+
+OGRPoint::OGRPoint( double xIn, double yIn, double zIn, double mIn )
+
+{
+    x = xIn;
+    y = yIn;
+    z = zIn;
+    m = mIn;
+    flags = OGR_G_NOT_EMPTY_POINT | OGR_G_3D | OGR_G_MEASURED;
+}
+
+/************************************************************************/
+/*                       OGRPoint( const OGRPoint& )                    */
+/************************************************************************/
+
+/**
+ * \brief Copy constructor.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the constructor
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRPoint::OGRPoint( const OGRPoint& other ) :
+    OGRGeometry( other ),
+    x( other.x ),
+    y( other.y ),
+    z( other.z ),
+    m( other.m )
+{
 }
 
 /************************************************************************/
@@ -94,6 +132,33 @@ OGRPoint::~OGRPoint()
 }
 
 /************************************************************************/
+/*                       operator=( const OGRPoint& )                   */
+/************************************************************************/
+
+/**
+ * \brief Assignment operator.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the operator
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRPoint& OGRPoint::operator=( const OGRPoint& other )
+{
+    if( this != &other)
+    {
+        OGRGeometry::operator=( other );
+
+        x = other.x;
+        y = other.y;
+        z = other.z;
+        m = other.m;
+    }
+    return *this;
+}
+
+/************************************************************************/
 /*                               clone()                                */
 /*                                                                      */
 /*      Make a new object that is a copy of this object.                */
@@ -102,10 +167,12 @@ OGRPoint::~OGRPoint()
 OGRGeometry *OGRPoint::clone() const
 
 {
-    OGRPoint    *poNewPoint = new OGRPoint( x, y, z );
+    OGRPoint    *poNewPoint = new (std::nothrow) OGRPoint( x, y, z, m );
+    if( poNewPoint == NULL )
+        return NULL;
 
     poNewPoint->assignSpatialReference( getSpatialReference() );
-    poNewPoint->setCoordinateDimension( nCoordDimension );
+    poNewPoint->flags = flags;
 
     return poNewPoint;
 }
@@ -116,8 +183,8 @@ OGRGeometry *OGRPoint::clone() const
 void OGRPoint::empty()
 
 {
-    x = y = z = 0.0;
-    nCoordDimension = -2;
+    x = y = z = m = 0.0;
+    flags &= ~OGR_G_NOT_EMPTY_POINT;
 }
 
 /************************************************************************/
@@ -137,7 +204,11 @@ int OGRPoint::getDimension() const
 OGRwkbGeometryType OGRPoint::getGeometryType() const
 
 {
-    if( getCoordinateDimension() == 3 )
+    if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
+        return wkbPointZM;
+    else if( flags & OGR_G_MEASURED )
+        return wkbPointM;
+    else if( flags & OGR_G_3D )
         return wkbPoint25D;
     else
         return wkbPoint;
@@ -160,19 +231,9 @@ const char * OGRPoint::getGeometryName() const
 void OGRPoint::flattenTo2D()
 
 {
-    z = 0;
-    if (nCoordDimension > 2)
-        nCoordDimension = 2;
-}
-
-/************************************************************************/
-/*                       getCoordinateDimension()                       */
-/************************************************************************/
-
-int OGRPoint::getCoordinateDimension() const
-
-{
-    return nCoordDimension < 0 ? -nCoordDimension : nCoordDimension;
+    z = m = 0;
+    flags &= ~OGR_G_3D;
+    setMeasured(FALSE);
 }
 
 /************************************************************************/
@@ -182,10 +243,12 @@ int OGRPoint::getCoordinateDimension() const
 void OGRPoint::setCoordinateDimension( int nNewDimension )
 
 {
-    nCoordDimension = nNewDimension;
-    
-    if( nCoordDimension == 2 )
-        z = 0;
+    if( nNewDimension == 2 )
+        flattenTo2D();
+    else if( nNewDimension == 3 )
+        flags |= OGR_G_3D;
+
+    setMeasured(FALSE);
 }
 
 /************************************************************************/
@@ -198,10 +261,12 @@ void OGRPoint::setCoordinateDimension( int nNewDimension )
 int OGRPoint::WkbSize() const
 
 {
-    if( getCoordinateDimension() != 3 )
-        return 21;
-    else
+    if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
+        return 37;
+    else if( (flags & OGR_G_3D) || (flags & OGR_G_MEASURED) )
         return 29;
+    else
+        return 21;
 }
 
 /************************************************************************/
@@ -217,45 +282,65 @@ OGRErr OGRPoint::importFromWkb( unsigned char * pabyData,
 
 {
     OGRwkbByteOrder     eByteOrder;
-    OGRBoolean          bIs3D = FALSE;
 
-    OGRErr eErr = importPreambuleFromWkb( pabyData, nSize, eByteOrder, bIs3D, eWkbVariant );
-    if( eErr >= 0 )
+    flags = 0;
+    OGRErr eErr = importPreambuleFromWkb( pabyData, nSize, eByteOrder, eWkbVariant );
+    pabyData += 5;
+    if( eErr != OGRERR_NONE )
         return eErr;
 
-    if ( nSize < ((bIs3D) ? 29 : 21) && nSize != -1 )
-        return OGRERR_NOT_ENOUGH_DATA;
+    if( nSize != -1 )
+    {
+        if( (nSize < 37) && ((flags & OGR_G_3D) && (flags & OGR_G_MEASURED)) )
+            return OGRERR_NOT_ENOUGH_DATA;
+        else if( (nSize < 29) && ((flags & OGR_G_3D) || (flags & OGR_G_MEASURED)) )
+            return OGRERR_NOT_ENOUGH_DATA;
+        else if( nSize < 21 )
+            return OGRERR_NOT_ENOUGH_DATA;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Get the vertex.                                                 */
 /* -------------------------------------------------------------------- */
-    memcpy( &x, pabyData + 5,     8 );
-    memcpy( &y, pabyData + 5 + 8, 8 );
-    
+    memcpy( &x, pabyData, 8 );
+    pabyData += 8;
+    memcpy( &y, pabyData, 8 );
+    pabyData += 8;
+
     if( OGR_SWAP( eByteOrder ) )
     {
         CPL_SWAPDOUBLE( &x );
         CPL_SWAPDOUBLE( &y );
     }
 
-    if( bIs3D )
+    if( flags & OGR_G_3D )
     {
-        memcpy( &z, pabyData + 5 + 16, 8 );
+        memcpy( &z, pabyData, 8 );
+        pabyData += 8;
         if( OGR_SWAP( eByteOrder ) )
-        {
             CPL_SWAPDOUBLE( &z );
-        }
-        nCoordDimension = 3;
     }
     else
     {
         z = 0;
-        nCoordDimension = 2;
+    }
+    if( flags & OGR_G_MEASURED )
+    {
+        memcpy( &m, pabyData, 8 );
+        /*pabyData += 8; */
+        if( OGR_SWAP( eByteOrder ) )
+        {
+            CPL_SWAPDOUBLE( &m );
+        }
+    }
+    else
+    {
+        m = 0;
     }
 
-    /* Detect NaN coordinates --> EMPTY */
-    if( x != x && y != y )
-        nCoordDimension = -nCoordDimension;
+    /* Detect coordinates are not NaN --> NOT EMPTY */
+    if(!( x != x && y != y ))
+        flags |= OGR_G_NOT_EMPTY_POINT;
 
     return OGRERR_NONE;
 }
@@ -275,54 +360,83 @@ OGRErr  OGRPoint::exportToWkb( OGRwkbByteOrder eByteOrder,
 /*      Set the byte order.                                             */
 /* -------------------------------------------------------------------- */
     pabyData[0] = DB2_V72_UNFIX_BYTE_ORDER((unsigned char) eByteOrder);
+    pabyData += 1;
 
 /* -------------------------------------------------------------------- */
 /*      Set the geometry feature type.                                  */
 /* -------------------------------------------------------------------- */
+
     GUInt32 nGType = getGeometryType();
-    
-    if ( eWkbVariant == wkbVariantIso )
+
+    if( eWkbVariant == wkbVariantPostGIS1 )
+    {
+        nGType = wkbFlatten(nGType);
+        if( Is3D() )
+            nGType = (OGRwkbGeometryType)(nGType | wkb25DBitInternalUse); /* yes we explicitly set wkb25DBit */
+        if( IsMeasured() )
+            nGType = (OGRwkbGeometryType)(nGType | 0x40000000);
+    }
+    else if ( eWkbVariant == wkbVariantIso )
         nGType = getIsoGeometryType();
-    
+
     if( eByteOrder == wkbNDR )
         nGType = CPL_LSBWORD32( nGType );
     else
         nGType = CPL_MSBWORD32( nGType );
 
-    memcpy( pabyData + 1, &nGType, 4 );
-    
+    memcpy( pabyData, &nGType, 4 );
+    pabyData += 4;
+
 /* -------------------------------------------------------------------- */
-/*      Copy in the raw data.                                           */
+/*      Copy in the raw data. Swap if needed.                           */
 /* -------------------------------------------------------------------- */
 
     if ( IsEmpty() && eWkbVariant == wkbVariantIso )
     {
         double dNan = std::numeric_limits<double>::quiet_NaN();
-        memcpy( pabyData+5, &dNan, 8 );
-        memcpy( pabyData+5+8, &dNan, 8 );
-        if( getCoordinateDimension() == 3 )
-            memcpy( pabyData+5+16, &dNan, 8 );
+        memcpy( pabyData, &dNan, 8 );
+        if( OGR_SWAP( eByteOrder ) )
+            CPL_SWAPDOUBLE( pabyData );
+        pabyData += 8;
+        memcpy( pabyData, &dNan, 8 );
+        if( OGR_SWAP( eByteOrder ) )
+            CPL_SWAPDOUBLE( pabyData );
+        pabyData += 8;
+        if( flags & OGR_G_3D ) {
+            memcpy( pabyData, &dNan, 8 );
+            if( OGR_SWAP( eByteOrder ) )
+                CPL_SWAPDOUBLE( pabyData );
+            pabyData += 8;
+        }
+        if( flags & OGR_G_MEASURED ) {
+            memcpy( pabyData, &dNan, 8 );
+            if( OGR_SWAP( eByteOrder ) )
+                CPL_SWAPDOUBLE( pabyData );
+        }
     }
     else
     {
-        memcpy( pabyData+5, &x, 16 );
-        if( getCoordinateDimension() == 3 )
+        memcpy( pabyData, &x, 8 );
+        if( OGR_SWAP( eByteOrder ) )
+            CPL_SWAPDOUBLE( pabyData );
+        pabyData += 8;
+        memcpy( pabyData, &y, 8 );
+        if( OGR_SWAP( eByteOrder ) )
+            CPL_SWAPDOUBLE( pabyData );
+        pabyData += 8;
+        if( flags & OGR_G_3D ) {
+            memcpy( pabyData, &z, 8 );
+            if( OGR_SWAP( eByteOrder ) )
+                CPL_SWAPDOUBLE( pabyData );
+            pabyData += 8;
+        }
+        if( flags & OGR_G_MEASURED )
         {
-            memcpy( pabyData + 5 + 16, &z, 8 );
+            memcpy( pabyData, &m, 8 );
+            if( OGR_SWAP( eByteOrder ) )
+                CPL_SWAPDOUBLE( pabyData );
         }
     }
-    
-/* -------------------------------------------------------------------- */
-/*      Swap if needed.                                                 */
-/* -------------------------------------------------------------------- */
-    if( OGR_SWAP( eByteOrder ) )
-    {
-        CPL_SWAPDOUBLE( pabyData + 5 );
-        CPL_SWAPDOUBLE( pabyData + 5 + 8 );
-
-        if( getCoordinateDimension() == 3 )
-            CPL_SWAPDOUBLE( pabyData + 5 + 16 );
-    }
 
     return OGRERR_NONE;
 }
@@ -338,14 +452,21 @@ OGRErr OGRPoint::importFromWkt( char ** ppszInput )
 
 {
     int bHasZ = FALSE, bHasM = FALSE;
-    OGRErr      eErr = importPreambuleFromWkt(ppszInput, &bHasZ, &bHasM);
-    if( eErr >= 0 )
-    {
-        if( eErr == OGRERR_NONE ) /* only the case for an EMPTY case */
-            nCoordDimension = (bHasZ) ? -3 : -2;
-
+    bool bIsEmpty = false;
+    OGRErr      eErr = importPreambuleFromWkt(ppszInput, &bHasZ, &bHasM, &bIsEmpty);
+    flags = 0;
+    if( eErr != OGRERR_NONE )
         return eErr;
-    }
+    if( bHasZ ) flags |= OGR_G_3D;
+    if( bHasM ) flags |= OGR_G_MEASURED;
+    if( bIsEmpty )
+    {
+        // we should be at the end
+        if( !((*ppszInput[0] == '\000') || (*ppszInput[0] == ',')) )
+            return OGRERR_CORRUPT_DATA;
+        return OGRERR_NONE;
+    } else
+        flags |= OGR_G_NOT_EMPTY_POINT;
 
     const char  *pszInput = *ppszInput;
 
@@ -354,46 +475,52 @@ OGRErr OGRPoint::importFromWkt( char ** ppszInput )
 /* -------------------------------------------------------------------- */
     OGRRawPoint         *poPoints = NULL;
     double              *padfZ = NULL;
+    double              *padfM = NULL;
     int                 nMaxPoint = 0, nPoints = 0;
+    int                 flagsFromInput = flags;
 
-    pszInput = OGRWktReadPoints( pszInput, &poPoints, &padfZ,
-                                 &nMaxPoint, &nPoints );
+    pszInput = OGRWktReadPointsM( pszInput, &poPoints, &padfZ, &padfM, &flagsFromInput,
+                                  &nMaxPoint, &nPoints );
     if( pszInput == NULL || nPoints != 1 )
     {
         CPLFree( poPoints );
         CPLFree( padfZ );
+        CPLFree( padfM );
         return OGRERR_CORRUPT_DATA;
     }
+    if( (flagsFromInput & OGR_G_3D) && !(flags & OGR_G_3D) )
+    {
+        flags |= OGR_G_3D;
+        bHasZ = TRUE;
+    }
+    if( (flagsFromInput & OGR_G_MEASURED) && !(flags & OGR_G_MEASURED) )
+    {
+        flags |= OGR_G_MEASURED;
+        bHasM = TRUE;
+    }
 
     x = poPoints[0].x;
     y = poPoints[0].y;
 
     CPLFree( poPoints );
 
-    if( padfZ != NULL )
+    if( bHasZ )
     {
-        /* If there's a 3rd value, and it is not a POINT M, */
-        /* then assume it is the Z */
-        if ((!(bHasM && !bHasZ)))
-        {
+        if( padfZ != NULL )
             z = padfZ[0];
-            nCoordDimension = 3;
-        }
-        else
-            nCoordDimension = 2;
-        CPLFree( padfZ );
     }
-    else if ( bHasZ )
+    if( bHasM )
     {
-        /* In theory we should have a z coordinate for POINT Z */
-        /* oh well, let be tolerant */
-        nCoordDimension = 3;
+        if( padfM != NULL )
+            m = padfM[0];
     }
-    else
-        nCoordDimension = 2;
+    if( padfZ != NULL )
+        CPLFree( padfZ );
+    if( padfM != NULL )
+        CPLFree( padfM );
 
     *ppszInput = (char *) pszInput;
-    
+
     return OGRERR_NONE;
 }
 
@@ -401,33 +528,53 @@ OGRErr OGRPoint::importFromWkt( char ** ppszInput )
 /*                            exportToWkt()                             */
 /*                                                                      */
 /*      Translate this structure into it's well known text format       */
-/*      equivelent.                                                     */
+/*      equivalent.                                                     */
 /************************************************************************/
 
 OGRErr OGRPoint::exportToWkt( char ** ppszDstText,
                               OGRwkbVariant eWkbVariant ) const
 
 {
-    char        szTextEquiv[140];
+    char        szTextEquiv[180];
     char        szCoordinate[80];
 
     if ( IsEmpty() )
     {
-        if( getCoordinateDimension() == 3 && eWkbVariant == wkbVariantIso )
-            *ppszDstText = CPLStrdup("POINT Z EMPTY");
+        if( eWkbVariant == wkbVariantIso )
+        {
+            if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
+                *ppszDstText = CPLStrdup("POINT ZM EMPTY");
+            else if( flags & OGR_G_MEASURED )
+                *ppszDstText = CPLStrdup("POINT M EMPTY");
+            else if( flags & OGR_G_3D )
+                *ppszDstText = CPLStrdup("POINT Z EMPTY");
+            else
+                *ppszDstText = CPLStrdup("POINT EMPTY");
+        }
         else
             *ppszDstText = CPLStrdup("POINT EMPTY");
     }
     else
     {
-        OGRMakeWktCoordinate(szCoordinate, x, y, z, getCoordinateDimension() );
-        if( getCoordinateDimension() == 3 && eWkbVariant == wkbVariantIso )
-            sprintf( szTextEquiv, "POINT Z (%s)", szCoordinate );
-        else
-            sprintf( szTextEquiv, "POINT (%s)", szCoordinate );
+        if( eWkbVariant == wkbVariantIso )
+        {
+            OGRMakeWktCoordinateM(szCoordinate, x, y, z, m, Is3D(), IsMeasured());
+            if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
+                snprintf( szTextEquiv, sizeof(szTextEquiv), "POINT ZM (%s)", szCoordinate);
+            else if( flags & OGR_G_MEASURED )
+                snprintf( szTextEquiv, sizeof(szTextEquiv), "POINT M (%s)", szCoordinate);
+            else if( flags & OGR_G_3D )
+                snprintf( szTextEquiv, sizeof(szTextEquiv), "POINT Z (%s)", szCoordinate);
+            else
+                snprintf( szTextEquiv, sizeof(szTextEquiv), "POINT (%s)", szCoordinate);
+        }
+        else {
+            OGRMakeWktCoordinateM(szCoordinate, x, y, z, m, Is3D(), FALSE);
+            snprintf( szTextEquiv, sizeof(szTextEquiv), "POINT (%s)", szCoordinate );
+        }
         *ppszDstText = CPLStrdup( szTextEquiv );
     }
-    
+
     return OGRERR_NONE;
 }
 
@@ -462,7 +609,7 @@ void OGRPoint::getEnvelope( OGREnvelope3D * psEnvelope ) const
  *
  * Relates to the SFCOM IPoint::get_X() method.
  *
- * @return the X coordinate of this point. 
+ * @return the X coordinate of this point.
  */
 
 /**
@@ -472,7 +619,7 @@ void OGRPoint::getEnvelope( OGREnvelope3D * psEnvelope ) const
  *
  * Relates to the SFCOM IPoint::get_Y() method.
  *
- * @return the Y coordinate of this point. 
+ * @return the Y coordinate of this point.
  */
 
 /**
@@ -491,7 +638,7 @@ void OGRPoint::getEnvelope( OGREnvelope3D * psEnvelope ) const
  * \brief Assign point X coordinate.
  *
  * There is no corresponding SFCOM method.
- */ 
+ */
 
 /**
  * \fn void OGRPoint::setY( double yIn );
@@ -499,7 +646,7 @@ void OGRPoint::getEnvelope( OGREnvelope3D * psEnvelope ) const
  * \brief Assign point Y coordinate.
  *
  * There is no corresponding SFCOM method.
- */ 
+ */
 
 /**
  * \fn void OGRPoint::setZ( double zIn );
@@ -508,8 +655,8 @@ void OGRPoint::getEnvelope( OGREnvelope3D * psEnvelope ) const
  * Calling this method will force the geometry
  * coordinate dimension to 3D (wkbPoint|wkbZ).
  *
- * There is no corresponding SFCOM method.  
- */ 
+ * There is no corresponding SFCOM method.
+ */
 
 /************************************************************************/
 /*                               Equal()                                */
@@ -518,19 +665,20 @@ void OGRPoint::getEnvelope( OGREnvelope3D * psEnvelope ) const
 OGRBoolean OGRPoint::Equals( OGRGeometry * poOther ) const
 
 {
-    OGRPoint    *poOPoint = (OGRPoint *) poOther;
-    
-    if( poOPoint== this )
+    if( poOther== this )
         return TRUE;
-    
+
     if( poOther->getGeometryType() != getGeometryType() )
         return FALSE;
 
-    if ( IsEmpty() && poOther->IsEmpty() )
+    OGRPoint    *poOPoint = (OGRPoint *) poOther;
+    if ( flags != poOPoint->flags )
+        return FALSE;
+
+    if ( IsEmpty() )
         return TRUE;
 
     // we should eventually test the SRS.
-    
     if( poOPoint->getX() != getX()
         || poOPoint->getY() != getY()
         || poOPoint->getZ() != getZ() )
@@ -560,15 +708,6 @@ OGRErr OGRPoint::transform( OGRCoordinateTransformation *poCT )
 }
 
 /************************************************************************/
-/*                               IsEmpty()                              */
-/************************************************************************/
-
-OGRBoolean OGRPoint::IsEmpty(  ) const
-{
-    return nCoordDimension < 0;
-}
-
-/************************************************************************/
 /*                               swapXY()                               */
 /************************************************************************/
 
diff --git a/ogr/ogrpolygon.cpp b/ogr/ogrpolygon.cpp
index 2ed1431..f3868bb 100644
--- a/ogr/ogrpolygon.cpp
+++ b/ogr/ogrpolygon.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpolygon.cpp 27959 2014-11-14 18:29:21Z rouault $
+ * $Id: ogrpolygon.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRPolygon geometry class.
@@ -33,7 +33,7 @@
 #include "ogr_geos.h"
 #include "ogr_api.h"
 
-CPL_CVSID("$Id: ogrpolygon.cpp 27959 2014-11-14 18:29:21Z rouault $");
+CPL_CVSID("$Id: ogrpolygon.cpp 33631 2016-03-04 06:28:09Z goatbar $");
 
 /************************************************************************/
 /*                             OGRPolygon()                             */
@@ -49,6 +49,24 @@ OGRPolygon::OGRPolygon()
 }
 
 /************************************************************************/
+/*                     OGRPolygon( const OGRPolygon& )                  */
+/************************************************************************/
+
+/**
+ * \brief Copy constructor.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the constructor
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRPolygon::OGRPolygon( const OGRPolygon& other ) :
+    OGRCurvePolygon(other)
+{
+}
+
+/************************************************************************/
 /*                            ~OGRPolygon()                             */
 /************************************************************************/
 
@@ -58,13 +76,39 @@ OGRPolygon::~OGRPolygon()
 }
 
 /************************************************************************/
+/*                     operator=( const OGRPolygon&)                    */
+/************************************************************************/
+
+/**
+ * \brief Assignment operator.
+ *
+ * Note: before GDAL 2.1, only the default implementation of the operator
+ * existed, which could be unsafe to use.
+ *
+ * @since GDAL 2.1
+ */
+
+OGRPolygon& OGRPolygon::operator=( const OGRPolygon& other )
+{
+    if( this != &other)
+    {
+        OGRCurvePolygon::operator=( other );
+    }
+    return *this;
+}
+
+/************************************************************************/
 /*                          getGeometryType()                           */
 /************************************************************************/
 
 OGRwkbGeometryType OGRPolygon::getGeometryType() const
 
 {
-    if( nCoordDimension == 3 )
+    if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
+        return wkbPolygonZM;
+    else if( flags & OGR_G_MEASURED  )
+        return wkbPolygonM;
+    else if( flags & OGR_G_3D )
         return wkbPolygon25D;
     else
         return wkbPolygon;
@@ -221,11 +265,10 @@ int OGRPolygon::WkbSize() const
 
 {
     int         nSize = 9;
-    int         b3D = getCoordinateDimension() == 3;
 
     for( int i = 0; i < oCC.nCurveCount; i++ )
     {
-        nSize += ((OGRLinearRing*)oCC.papoCurves[i])->_WkbSize( b3D );
+        nSize += ((OGRLinearRing*)oCC.papoCurves[i])->_WkbSize( flags );
     }
 
     return nSize;
@@ -245,22 +288,20 @@ OGRErr OGRPolygon::importFromWkb( unsigned char * pabyData,
 {
     OGRwkbByteOrder eByteOrder;
     int nDataOffset = 0;
+    /* coverity[tainted_data] */
     OGRErr eErr = oCC.importPreambuleFromWkb(this, pabyData, nSize, nDataOffset,
                                              eByteOrder, 4, eWkbVariant);
-    if( eErr >= 0 )
+    if( eErr != OGRERR_NONE )
         return eErr;
 
-    int b3D = (nCoordDimension == 3);
 /* -------------------------------------------------------------------- */
 /*      Get the rings.                                                  */
 /* -------------------------------------------------------------------- */
     for( int iRing = 0; iRing < oCC.nCurveCount; iRing++ )
     {
-        OGRErr  eErr;
-        
         OGRLinearRing* poLR = new OGRLinearRing();
         oCC.papoCurves[iRing] = poLR;
-        eErr = poLR->_importFromWkb( eByteOrder, b3D,
+        eErr = poLR->_importFromWkb( eByteOrder, flags,
                                                  pabyData + nDataOffset,
                                                  nSize );
         if( eErr != OGRERR_NONE )
@@ -271,11 +312,11 @@ OGRErr OGRPolygon::importFromWkb( unsigned char * pabyData,
         }
 
         if( nSize != -1 )
-            nSize -= poLR->_WkbSize( b3D );
+            nSize -= poLR->_WkbSize( flags );
 
-        nDataOffset += poLR->_WkbSize( b3D );
+        nDataOffset += poLR->_WkbSize( flags );
     }
-    
+
     return OGRERR_NONE;
 }
 
@@ -290,9 +331,7 @@ OGRErr  OGRPolygon::exportToWkb( OGRwkbByteOrder eByteOrder,
                                  OGRwkbVariant eWkbVariant ) const
 
 {
-    int         nOffset;
-    int         b3D = getCoordinateDimension() == 3;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Set the byte order.                                             */
 /* -------------------------------------------------------------------- */
@@ -303,16 +342,24 @@ OGRErr  OGRPolygon::exportToWkb( OGRwkbByteOrder eByteOrder,
 /* -------------------------------------------------------------------- */
     GUInt32 nGType = getGeometryType();
 
-    if ( eWkbVariant == wkbVariantIso )
+    if( eWkbVariant == wkbVariantPostGIS1 )
+    {
+        nGType = wkbFlatten(nGType);
+        if( Is3D() )
+            nGType = (OGRwkbGeometryType)(nGType | wkb25DBitInternalUse); /* yes we explicitly set wkb25DBit */
+        if( IsMeasured() )
+            nGType = (OGRwkbGeometryType)(nGType | 0x40000000);
+    }
+    else if ( eWkbVariant == wkbVariantIso )
         nGType = getIsoGeometryType();
-    
+
     if( eByteOrder == wkbNDR )
         nGType = CPL_LSBWORD32( nGType );
     else
         nGType = CPL_MSBWORD32( nGType );
 
     memcpy( pabyData + 1, &nGType, 4 );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Copy in the raw data.                                           */
 /* -------------------------------------------------------------------- */
@@ -327,21 +374,21 @@ OGRErr  OGRPolygon::exportToWkb( OGRwkbByteOrder eByteOrder,
     {
         memcpy( pabyData+5, &oCC.nCurveCount, 4 );
     }
-    
-    nOffset = 9;
-    
+
 /* ==================================================================== */
 /*      Serialize each of the rings.                                    */
 /* ==================================================================== */
+    int nOffset = 9;
+
     for( int iRing = 0; iRing < oCC.nCurveCount; iRing++ )
     {
         OGRLinearRing* poLR = (OGRLinearRing*) oCC.papoCurves[iRing];
-        poLR->_exportToWkb( eByteOrder, b3D,
+        poLR->_exportToWkb( eByteOrder, flags,
                                         pabyData + nOffset );
 
-        nOffset += poLR->_WkbSize(b3D);
+        nOffset += poLR->_WkbSize( flags );
     }
-    
+
     return OGRERR_NONE;
 }
 
@@ -356,9 +403,15 @@ OGRErr OGRPolygon::importFromWkt( char ** ppszInput )
 
 {
     int bHasZ = FALSE, bHasM = FALSE;
-    OGRErr      eErr = importPreambuleFromWkt(ppszInput, &bHasZ, &bHasM);
-    if( eErr >= 0 )
+    bool bIsEmpty = false;
+    OGRErr      eErr = importPreambuleFromWkt(ppszInput, &bHasZ, &bHasM, &bIsEmpty);
+    flags = 0;
+    if( eErr != OGRERR_NONE )
         return eErr;
+    if( bHasZ ) flags |= OGR_G_3D;
+    if( bHasM ) flags |= OGR_G_MEASURED;
+    if( bIsEmpty )
+        return OGRERR_NONE;
 
     OGRRawPoint *paoPoints = NULL;
     int          nMaxPoints = 0;
@@ -403,12 +456,10 @@ OGRErr OGRPolygon::importFromWKTListOnly( char ** ppszInput, int bHasZ, int bHas
 /*      allocate/deallocate overhead.                                   */
 /* ==================================================================== */
     int         nMaxRings = 0;
+    double      *padfM = NULL;
 
-    nCoordDimension = 2;
-    
     do
     {
-        int     nPoints = 0;
 
         const char* pszNext = OGRWktReadToken( pszInput, szToken );
         if (EQUAL(szToken,"EMPTY"))
@@ -435,14 +486,33 @@ OGRErr OGRPolygon::importFromWKTListOnly( char ** ppszInput, int bHasZ, int bHas
 /* -------------------------------------------------------------------- */
 /*      Read points for one ring from input.                            */
 /* -------------------------------------------------------------------- */
-        pszInput = OGRWktReadPoints( pszInput, &paoPoints, &padfZ, &nMaxPoints,
-                                     &nPoints );
+        int nPoints = 0;
+        int flagsFromInput = flags;
+        if( flagsFromInput == 0 ) /* flags was not set, this is not called by us */
+        {
+            if( bHasM )
+                flagsFromInput |= OGR_G_MEASURED;
+            if( bHasZ )
+                flagsFromInput |= OGR_G_3D;
+        }
 
+        pszInput = OGRWktReadPointsM( pszInput, &paoPoints, &padfZ, &padfM, &flagsFromInput,
+                                      &nMaxPoints, &nPoints );
         if( pszInput == NULL || nPoints == 0 )
         {
             return OGRERR_CORRUPT_DATA;
         }
-        
+        if( (flagsFromInput & OGR_G_3D) && !(flags & OGR_G_3D) )
+        {
+            flags |= OGR_G_3D;
+            bHasZ = TRUE;
+        }
+        if( (flagsFromInput & OGR_G_MEASURED) && !(flags & OGR_G_MEASURED) )
+        {
+            flags |= OGR_G_MEASURED;
+            bHasM = TRUE;
+        }
+
 /* -------------------------------------------------------------------- */
 /*      Do we need to grow the ring array?                              */
 /* -------------------------------------------------------------------- */
@@ -458,31 +528,34 @@ OGRErr OGRPolygon::importFromWKTListOnly( char ** ppszInput, int bHasZ, int bHas
 /* -------------------------------------------------------------------- */
         OGRLinearRing* poLR = new OGRLinearRing();
         oCC.papoCurves[oCC.nCurveCount] = poLR;
-        /* Ignore Z array when we have a POLYGON M */
-        if (bHasM && !bHasZ)
-            poLR->setPoints( nPoints, paoPoints, NULL );
+
+        if (bHasM && bHasZ)
+            poLR->setPoints( nPoints, paoPoints, padfZ, padfM );
+        else if (bHasM)
+            poLR->setPointsM( nPoints, paoPoints, padfM );
+        else if (bHasZ)
+            poLR->setPoints( nPoints, paoPoints, padfZ );
         else
             poLR->setPoints( nPoints, paoPoints, padfZ );
 
         oCC.nCurveCount++;
 
-        if( padfZ && !(bHasM && !bHasZ) )
-            nCoordDimension = 3;
-
 /* -------------------------------------------------------------------- */
-/*      Read the delimeter following the ring.                          */
+/*      Read the delimiter following the ring.                          */
 /* -------------------------------------------------------------------- */
-        
+
         pszInput = OGRWktReadToken( pszInput, szToken );
     } while( szToken[0] == ',' );
 
+    CPLFree( padfM );
+
 /* -------------------------------------------------------------------- */
 /*      freak if we don't get a closing bracket.                        */
 /* -------------------------------------------------------------------- */
 
     if( szToken[0] != ')' )
         return OGRERR_CORRUPT_DATA;
-    
+
     *ppszInput = (char *) pszInput;
     return OGRERR_NONE;
 }
@@ -491,26 +564,33 @@ OGRErr OGRPolygon::importFromWKTListOnly( char ** ppszInput, int bHasZ, int bHas
 /*                            exportToWkt()                             */
 /*                                                                      */
 /*      Translate this structure into it's well known text format       */
-/*      equivelent.  This could be made alot more CPU efficient!        */
+/*      equivalent.  This could be made a lot more CPU efficient!        */
 /************************************************************************/
 
 OGRErr OGRPolygon::exportToWkt( char ** ppszDstText,
                                 OGRwkbVariant eWkbVariant ) const
 
 {
-    char        **papszRings;
-    int         iRing, nCumulativeLength = 0, nNonEmptyRings = 0;
     OGRErr      eErr;
-    int         bMustWriteComma = FALSE;
+    bool        bMustWriteComma = false;
 
 /* -------------------------------------------------------------------- */
 /*      If we have no valid exterior ring, return POLYGON EMPTY.        */
 /* -------------------------------------------------------------------- */
-    if (getExteriorRing() == NULL || 
+    if (getExteriorRing() == NULL ||
         getExteriorRing()->IsEmpty() )
     {
-        if( getCoordinateDimension() == 3 && eWkbVariant == wkbVariantIso )
-            *ppszDstText = CPLStrdup("POLYGON Z EMPTY");
+        if( eWkbVariant == wkbVariantIso )
+        {
+            if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
+                *ppszDstText = CPLStrdup("POLYGON ZM EMPTY");
+            else if( flags & OGR_G_MEASURED )
+                *ppszDstText = CPLStrdup("POLYGON M EMPTY");
+            else if( flags & OGR_G_3D )
+                *ppszDstText = CPLStrdup("POLYGON Z EMPTY");
+            else
+                *ppszDstText = CPLStrdup("POLYGON EMPTY");
+        }
         else
             *ppszDstText = CPLStrdup("POLYGON EMPTY");
         return OGRERR_NONE;
@@ -519,24 +599,41 @@ OGRErr OGRPolygon::exportToWkt( char ** ppszDstText,
 /* -------------------------------------------------------------------- */
 /*      Build a list of strings containing the stuff for each ring.     */
 /* -------------------------------------------------------------------- */
-    papszRings = (char **) CPLCalloc(sizeof(char *),oCC.nCurveCount);
+    char **papszRings = (char **) CPLCalloc(sizeof(char *),oCC.nCurveCount);
+    size_t nCumulativeLength = 0;
+    size_t nNonEmptyRings = 0;
+    size_t *pnRingBeginning = (size_t *) CPLCalloc(sizeof(size_t),oCC.nCurveCount);
 
-    for( iRing = 0; iRing < oCC.nCurveCount; iRing++ )
+    for( int iRing = 0; iRing < oCC.nCurveCount; iRing++ )
     {
         OGRLinearRing* poLR = (OGRLinearRing*) oCC.papoCurves[iRing];
-        poLR->setCoordinateDimension( getCoordinateDimension() );
+        //poLR->setFlags( getFlags() );
+        poLR->set3D(Is3D());
+        poLR->setMeasured(IsMeasured());
         if( poLR->getNumPoints() == 0 )
         {
             papszRings[iRing] = NULL;
             continue;
         }
 
-        eErr = poLR->exportToWkt( &(papszRings[iRing]) );
+        eErr = poLR->exportToWkt( &(papszRings[iRing]), eWkbVariant );
         if( eErr != OGRERR_NONE )
             goto error;
 
-        CPLAssert( EQUALN(papszRings[iRing],"LINEARRING (", 12) );
-        nCumulativeLength += strlen(papszRings[iRing] + 11);
+        if( STARTS_WITH_CI(papszRings[iRing], "LINEARRING ZM (") )
+            pnRingBeginning[iRing] = 14;
+        else if( STARTS_WITH_CI(papszRings[iRing], "LINEARRING M (") )
+            pnRingBeginning[iRing] = 13;
+        else if( STARTS_WITH_CI(papszRings[iRing], "LINEARRING Z (") )
+            pnRingBeginning[iRing] = 13;
+        else if( STARTS_WITH_CI(papszRings[iRing], "LINEARRING (") )
+            pnRingBeginning[iRing] = 11;
+        else
+        {
+            CPLAssert( 0 );
+        }
+
+        nCumulativeLength += strlen(papszRings[iRing] + pnRingBeginning[iRing]);
 
         nNonEmptyRings++;
     }
@@ -545,7 +642,7 @@ OGRErr OGRPolygon::exportToWkt( char ** ppszDstText,
 /*      Allocate exactly the right amount of space for the              */
 /*      aggregated string.                                              */
 /* -------------------------------------------------------------------- */
-    *ppszDstText = (char *) VSIMalloc(nCumulativeLength + nNonEmptyRings + 15);
+    *ppszDstText = (char *) VSI_MALLOC_VERBOSE(nCumulativeLength + nNonEmptyRings + 16);
 
     if( *ppszDstText == NULL )
     {
@@ -556,14 +653,23 @@ OGRErr OGRPolygon::exportToWkt( char ** ppszDstText,
 /* -------------------------------------------------------------------- */
 /*      Build up the string, freeing temporary strings as we go.        */
 /* -------------------------------------------------------------------- */
-    if( getCoordinateDimension() == 3 && eWkbVariant == wkbVariantIso )
-        strcpy( *ppszDstText, "POLYGON Z (" );
+    if( eWkbVariant == wkbVariantIso )
+    {
+        if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
+            strcpy( *ppszDstText, "POLYGON ZM (" );
+        else if( flags & OGR_G_MEASURED )
+            strcpy( *ppszDstText, "POLYGON M (" );
+        else if( flags & OGR_G_3D )
+            strcpy( *ppszDstText, "POLYGON Z (" );
+        else
+            strcpy( *ppszDstText, "POLYGON (" );
+    }
     else
         strcpy( *ppszDstText, "POLYGON (" );
     nCumulativeLength = strlen(*ppszDstText);
 
-    for( iRing = 0; iRing < oCC.nCurveCount; iRing++ )
-    {                                                           
+    for( int iRing = 0; iRing < oCC.nCurveCount; iRing++ )
+    {
         if( papszRings[iRing] == NULL )
         {
             CPLDebug( "OGR", "OGRPolygon::exportToWkt() - skipping empty ring.");
@@ -572,10 +678,10 @@ OGRErr OGRPolygon::exportToWkt( char ** ppszDstText,
 
         if( bMustWriteComma )
             (*ppszDstText)[nCumulativeLength++] = ',';
-        bMustWriteComma = TRUE;
-        
-        int nRingLen = strlen(papszRings[iRing] + 11);
-        memcpy( *ppszDstText + nCumulativeLength, papszRings[iRing] + 11, nRingLen );
+        bMustWriteComma = true;
+
+        size_t nRingLen = strlen(papszRings[iRing] + pnRingBeginning[iRing]);
+        memcpy( *ppszDstText + nCumulativeLength, papszRings[iRing] + pnRingBeginning[iRing], nRingLen );
         nCumulativeLength += nRingLen;
         VSIFree( papszRings[iRing] );
     }
@@ -584,11 +690,12 @@ OGRErr OGRPolygon::exportToWkt( char ** ppszDstText,
     (*ppszDstText)[nCumulativeLength] = '\0';
 
     CPLFree( papszRings );
+    CPLFree( pnRingBeginning );
 
     return OGRERR_NONE;
 
 error:
-    for( iRing = 0; iRing < oCC.nCurveCount; iRing++ )
+    for( int iRing = 0; iRing < oCC.nCurveCount; iRing++ )
         CPLFree(papszRings[iRing]);
     CPLFree(papszRings);
     return eErr;
@@ -598,26 +705,10 @@ error:
 /*                           PointOnSurface()                           */
 /************************************************************************/
 
-int OGRPolygon::PointOnSurface( OGRPoint *poPoint ) const
+OGRErr OGRPolygon::PointOnSurface( OGRPoint *poPoint ) const
 
 {
-    if( poPoint == NULL || poPoint->IsEmpty() )
-        return OGRERR_FAILURE;
-
-    OGRGeometryH hInsidePoint = OGR_G_PointOnSurface( (OGRGeometryH) this );
-    if( hInsidePoint == NULL )
-        return OGRERR_FAILURE;
-
-    OGRPoint *poInsidePoint = (OGRPoint *) hInsidePoint;
-    if( poInsidePoint->IsEmpty() )
-        poPoint->empty();
-    else
-    {
-        poPoint->setX( poInsidePoint->getX() );
-        poPoint->setY( poInsidePoint->getY() );
-    }
-
-    return OGRERR_NONE;
+    return PointOnSurfaceInternal(poPoint);
 }
 
 /************************************************************************/
@@ -688,12 +779,12 @@ OGRGeometry* OGRPolygon::getCurveGeometry(const char* const* papszOptions) const
 {
     OGRCurvePolygon* poCC = new OGRCurvePolygon();
     poCC->assignSpatialReference( getSpatialReference() );
-    int bHasCurveGeometry = FALSE;
+    bool bHasCurveGeometry = false;
     for( int iRing = 0; iRing < oCC.nCurveCount; iRing++ )
     {
         OGRCurve* poSubGeom = (OGRCurve* )oCC.papoCurves[iRing]->getCurveGeometry(papszOptions);
         if( wkbFlatten(poSubGeom->getGeometryType()) != wkbLineString )
-            bHasCurveGeometry = TRUE;
+            bHasCurveGeometry = true;
         poCC->addRingDirectly( poSubGeom );
     }
     if( !bHasCurveGeometry )
@@ -712,7 +803,7 @@ OGRGeometry* OGRPolygon::getCurveGeometry(const char* const* papszOptions) const
  * \brief Cast to curve polygon.
  *
  * The passed in geometry is consumed and a new one returned .
- * 
+ *
  * @param poPoly the input geometry - ownership is passed to the method.
  * @return new geometry.
  */
@@ -720,7 +811,8 @@ OGRGeometry* OGRPolygon::getCurveGeometry(const char* const* papszOptions) const
 OGRCurvePolygon* OGRPolygon::CastToCurvePolygon(OGRPolygon* poPoly)
 {
     OGRCurvePolygon* poCP = new OGRCurvePolygon();
-    poCP->setCoordinateDimension(poPoly->getCoordinateDimension());
+    poCP->set3D(poPoly->Is3D());
+    poCP->setMeasured(poPoly->IsMeasured());
     poCP->assignSpatialReference(poPoly->getSpatialReference());
     poCP->oCC.nCurveCount = poPoly->oCC.nCurveCount;
     poCP->oCC.papoCurves = poPoly->oCC.papoCurves;
diff --git a/ogr/ogrsf_frmts/GNUmakefile b/ogr/ogrsf_frmts/GNUmakefile
index 4d8b371..351fe90 100644
--- a/ogr/ogrsf_frmts/GNUmakefile
+++ b/ogr/ogrsf_frmts/GNUmakefile
@@ -6,7 +6,7 @@ SUBDIRS-yes	:= \
 	mitab ntf gpx rec s57 sdts shape tiger vrt \
 	geoconcept xplane georss gtm dxf pgdump gpsbabel \
 	sua openair pds htf aeronavfaa edigeo svg idrisi \
-	arcgen segukooa segy sxf openfilegdb wasp selafin jml
+	arcgen segukooa segy sxf openfilegdb wasp selafin jml vdv
 
 SUBDIRS-$(HAVE_DODS)	+= dods
 SUBDIRS-$(HAVE_DWGDIRECT) += dxfdwg
@@ -30,7 +30,6 @@ SUBDIRS-$(HAVE_LIBKML)  += libkml
 SUBDIRS-$(CURL_SETTING) += wfs
 SUBDIRS-$(MDB_ENABLED)  += mdb
 SUBDIRS-$(CURL_SETTING) += gft
-SUBDIRS-$(CURL_SETTING) += gme
 SUBDIRS-$(CURL_SETTING) += couchdb
 SUBDIRS-$(CURL_SETTING) += cloudant
 SUBDIRS-$(HAVE_FREEXL)  += xls
@@ -41,8 +40,10 @@ SUBDIRS-$(HAVE_SQLITE)	+= gpkg
 SUBDIRS-$(HAVE_SQLITE)	+= osm
 SUBDIRS-$(HAVE_SOSI)	+= sosi
 SUBDIRS-$(CURL_SETTING) += cartodb
+SUBDIRS-$(CURL_SETTING) += amigocloud
 SUBDIRS-$(CURL_SETTING) += plscenes
 SUBDIRS-$(CURL_SETTING) += csw
+SUBDIRS-$(HAVE_MONGODB) += mongodb
 
 default:	$(foreach d,$(SUBDIRS-yes),$(d)-target)
 
diff --git a/ogr/ogrsf_frmts/aeronavfaa/ogr_aeronavfaa.h b/ogr/ogrsf_frmts/aeronavfaa/ogr_aeronavfaa.h
index 0dbf3b6..1183aa1 100644
--- a/ogr/ogrsf_frmts/aeronavfaa/ogr_aeronavfaa.h
+++ b/ogr/ogrsf_frmts/aeronavfaa/ogr_aeronavfaa.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_aeronavfaa.h 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogr_aeronavfaa.h 31777 2015-11-26 14:14:41Z rouault $
  *
  * Project:  AeronavFAA Translator
  * Purpose:  Definition of classes for OGR AeronavFAA driver.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_AeronavFAA_H_INCLUDED
-#define _OGR_AeronavFAA_H_INCLUDED
+#ifndef OGR_AeronavFAA_H_INCLUDED
+#define OGR_AeronavFAA_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 
@@ -185,4 +185,4 @@ class OGRAeronavFAADataSource : public OGRDataSource
 };
 
 
-#endif /* ndef _OGR_AeronavFAA_H_INCLUDED */
+#endif /* ndef OGR_AeronavFAA_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadatasource.cpp b/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadatasource.cpp
index 63329c7..d6ade08 100644
--- a/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadatasource.cpp
+++ b/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ograeronavfaadatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ograeronavfaadatasource.cpp 32247 2015-12-19 07:05:52Z goatbar $
  *
  * Project:  AeronavFAA Translator
  * Purpose:  Implements OGRAeronavFAADataSource class
@@ -31,20 +31,17 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ograeronavfaadatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ograeronavfaadatasource.cpp 32247 2015-12-19 07:05:52Z goatbar $");
 
 /************************************************************************/
 /*                      OGRAeronavFAADataSource()                       */
 /************************************************************************/
 
-OGRAeronavFAADataSource::OGRAeronavFAADataSource()
-
-{
-    papoLayers = NULL;
-    nLayers = 0;
-
-    pszName = NULL;
-}
+OGRAeronavFAADataSource::OGRAeronavFAADataSource() :
+    pszName(NULL),
+    papoLayers(NULL),
+    nLayers(0)
+{}
 
 /************************************************************************/
 /*                     ~OGRAeronavFAADataSource()                       */
@@ -106,13 +103,13 @@ int OGRAeronavFAADataSource::Open( const char * pszFilename )
     int bIsDOF = (szBuffer[128] == 13 && szBuffer[128+1] == 10 &&
                   szBuffer[130+128] == 13 && szBuffer[130+129] == 10 &&
                   szBuffer[2*130+128] == 13 && szBuffer[2*130+129] == 10 &&
-                  strncmp(szBuffer + 3 * 130, "------------------------------------------------------------------------------------------------------------------------- ", 122) == 0);
+                  STARTS_WITH(szBuffer + 3 * 130, "------------------------------------------------------------------------------------------------------------------------- "));
 
     int bIsNAVAID = (szBuffer[132] == 13 && szBuffer[132+1] == 10 &&
-                     strncmp(szBuffer + 20 - 1, "CREATION DATE", strlen("CREATION DATE")) == 0 &&
+                     STARTS_WITH(szBuffer + 20 - 1, "CREATION DATE") &&
                      szBuffer[134 + 132] == 13 && szBuffer[134 + 132+1] == 10);
 
-    int bIsROUTE = strncmp(szBuffer, "           UNITED STATES GOVERNMENT FLIGHT INFORMATION PUBLICATION             149343", 85) == 0 &&
+    int bIsROUTE = STARTS_WITH(szBuffer, "           UNITED STATES GOVERNMENT FLIGHT INFORMATION PUBLICATION             149343") &&
                    szBuffer[85] == 13 && szBuffer[85+1] == 10;
 
     int bIsIAP = strstr(szBuffer, "INSTRUMENT APPROACH PROCEDURE NAVAID & FIX DATA") != NULL &&
diff --git a/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadriver.cpp b/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadriver.cpp
index 8a6f9a1..54c9123 100644
--- a/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadriver.cpp
+++ b/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ograeronavfaadriver.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ograeronavfaadriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  AeronavFAA Translator
  * Purpose:  Implements OGRAeronavFAADriver.
@@ -30,7 +30,7 @@
 #include "ogr_aeronavfaa.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ograeronavfaadriver.cpp 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: ograeronavfaadriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
 
 // g++ ogr/ogrsf_frmts/aeronavfaa/*.cpp -Wall -g -fPIC -shared -o ogr_AeronavFAA.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts/aernovfaa -Iogr/ogrsf_frmts
 
@@ -69,24 +69,19 @@ static GDALDataset *OGRAeronavFAADriverOpen( GDALOpenInfo* poOpenInfo )
 void RegisterOGRAeronavFAA()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "AeronavFAA" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "AeronavFAA" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-
-        poDriver->SetDescription( "AeronavFAA" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Aeronav FAA" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_aeronavfaa.html" );
+    GDALDriver  *poDriver = new GDALDriver();
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetDescription( "AeronavFAA" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Aeronav FAA" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_aeronavfaa.html" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = OGRAeronavFAADriverOpen;
+    poDriver->pfnOpen = OGRAeronavFAADriverOpen;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
 
diff --git a/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaalayer.cpp b/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaalayer.cpp
index 7b1bfba..e411c9c 100644
--- a/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaalayer.cpp
+++ b/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaalayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ograeronavfaalayer.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: ograeronavfaalayer.cpp 32381 2015-12-20 21:37:32Z goatbar $
  *
  * Project:  AeronavFAA Translator
  * Purpose:  Implements OGRAeronavFAALayer class.
@@ -33,24 +33,21 @@
 #include "ogr_p.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ograeronavfaalayer.cpp 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: ograeronavfaalayer.cpp 32381 2015-12-20 21:37:32Z goatbar $");
 
 /************************************************************************/
 /*                        OGRAeronavFAALayer()                          */
 /************************************************************************/
 
-OGRAeronavFAALayer::OGRAeronavFAALayer( VSILFILE* fp, const char* pszLayerName )
-
+OGRAeronavFAALayer::OGRAeronavFAALayer( VSILFILE* fp,
+                                        const char* pszLayerName ) :
+    poFeatureDefn(new OGRFeatureDefn(pszLayerName)),
+    poSRS(new OGRSpatialReference(SRS_WKT_WGS84)),
+    fpAeronavFAA(fp),
+    bEOF(FALSE),
+    nNextFID(0),
+    psRecordDesc(NULL)
 {
-    fpAeronavFAA = fp;
-    nNextFID = 0;
-    bEOF = FALSE;
-
-    psRecordDesc = NULL;
-
-    poSRS = new OGRSpatialReference(SRS_WKT_WGS84);
-
-    poFeatureDefn = new OGRFeatureDefn( pszLayerName );
     poFeatureDefn->Reference();
     poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
     SetDescription( poFeatureDefn->GetName() );
@@ -93,7 +90,7 @@ OGRFeature *OGRAeronavFAALayer::GetNextFeature()
 {
     OGRFeature  *poFeature;
 
-    while(TRUE)
+    while( true )
     {
         if (bEOF)
             return NULL;
@@ -153,18 +150,20 @@ static const RecordDesc DOF = { sizeof(DOFFields)/sizeof(DOFFields[0]), DOFField
 /*                       OGRAeronavFAADOFLayer()                        */
 /************************************************************************/
 
-OGRAeronavFAADOFLayer::OGRAeronavFAADOFLayer( VSILFILE* fp, const char* pszLayerName ) :
-                                            OGRAeronavFAALayer(fp, pszLayerName)
+OGRAeronavFAADOFLayer::OGRAeronavFAADOFLayer( VSILFILE* fp,
+                                              const char* pszLayerName ) :
+    OGRAeronavFAALayer(fp, pszLayerName)
 {
     poFeatureDefn->SetGeomType( wkbPoint );
 
     psRecordDesc = &DOF;
 
-    int i;
-    for(i=0;i<psRecordDesc->nFields;i++)
+    for( int i = 0; i < psRecordDesc->nFields; i++ )
     {
-        OGRFieldDefn oField( psRecordDesc->pasFields[i].pszFieldName, psRecordDesc->pasFields[i].eType );
-        oField.SetWidth(psRecordDesc->pasFields[i].nLastCol - psRecordDesc->pasFields[i].nStartCol + 1);
+        OGRFieldDefn oField( psRecordDesc->pasFields[i].pszFieldName,
+                             psRecordDesc->pasFields[i].eType );
+        oField.SetWidth(psRecordDesc->pasFields[i].nLastCol
+                        - psRecordDesc->pasFields[i].nStartCol + 1);
         poFeatureDefn->AddFieldDefn( &oField );
     }
 }
@@ -230,7 +229,7 @@ OGRFeature *OGRAeronavFAADOFLayer::GetNextRawFeature()
     const char* pszLine;
     char szBuffer[130];
 
-    while(TRUE)
+    while( true )
     {
         pszLine = CPLReadLine2L(fpAeronavFAA, 130, NULL);
         if (pszLine == NULL)
@@ -247,8 +246,7 @@ OGRFeature *OGRAeronavFAADOFLayer::GetNextRawFeature()
         OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
         poFeature->SetFID(nNextFID ++);
 
-        int i;
-        for(i=0;i<psRecordDesc->nFields;i++)
+        for( int i=0; i < psRecordDesc->nFields; i++ )
         {
             int nWidth = psRecordDesc->pasFields[i].nLastCol - psRecordDesc->pasFields[i].nStartCol + 1;
             strncpy(szBuffer, pszLine + psRecordDesc->pasFields[i].nStartCol - 1, nWidth);
@@ -300,18 +298,20 @@ static const RecordDesc NAVAID = { sizeof(NAVAIDFields)/sizeof(NAVAIDFields[0]),
 /*                    OGRAeronavFAANAVAIDLayer()                        */
 /************************************************************************/
 
-OGRAeronavFAANAVAIDLayer::OGRAeronavFAANAVAIDLayer( VSILFILE* fp, const char* pszLayerName ) :
-                                            OGRAeronavFAALayer(fp, pszLayerName)
+OGRAeronavFAANAVAIDLayer::OGRAeronavFAANAVAIDLayer( VSILFILE* fp,
+                                                    const char* pszLayerName ) :
+    OGRAeronavFAALayer(fp, pszLayerName)
 {
     poFeatureDefn->SetGeomType( wkbPoint );
 
     psRecordDesc = &NAVAID;
 
-    int i;
-    for(i=0;i<psRecordDesc->nFields;i++)
+    for( int i=0; i < psRecordDesc->nFields; i++ )
     {
-        OGRFieldDefn oField( psRecordDesc->pasFields[i].pszFieldName, psRecordDesc->pasFields[i].eType );
-        oField.SetWidth(psRecordDesc->pasFields[i].nLastCol - psRecordDesc->pasFields[i].nStartCol + 1);
+        OGRFieldDefn oField( psRecordDesc->pasFields[i].pszFieldName,
+                             psRecordDesc->pasFields[i].eType );
+        oField.SetWidth( psRecordDesc->pasFields[i].nLastCol
+                         - psRecordDesc->pasFields[i].nStartCol + 1 );
         poFeatureDefn->AddFieldDefn( &oField );
     }
 }
@@ -335,7 +335,7 @@ OGRFeature *OGRAeronavFAANAVAIDLayer::GetNextRawFeature()
     const char* pszLine;
     char szBuffer[134];
 
-    while(TRUE)
+    while( true )
     {
         pszLine = CPLReadLine2L(fpAeronavFAA, 134, NULL);
         if (pszLine == NULL)
@@ -355,8 +355,7 @@ OGRFeature *OGRAeronavFAANAVAIDLayer::GetNextRawFeature()
         OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
         poFeature->SetFID(nNextFID ++);
 
-        int i;
-        for(i=0;i<psRecordDesc->nFields;i++)
+        for( int i=0; i < psRecordDesc->nFields; i++ )
         {
             int nWidth = psRecordDesc->pasFields[i].nLastCol - psRecordDesc->pasFields[i].nStartCol + 1;
             strncpy(szBuffer, pszLine + psRecordDesc->pasFields[i].nStartCol - 1, nWidth);
@@ -389,10 +388,12 @@ OGRFeature *OGRAeronavFAANAVAIDLayer::GetNextRawFeature()
 /*                    OGRAeronavFAARouteLayer()                        */
 /************************************************************************/
 
-OGRAeronavFAARouteLayer::OGRAeronavFAARouteLayer( VSILFILE* fp, const char* pszLayerName, int bIsDPOrSTARS ) :
-                        OGRAeronavFAALayer(fp, pszLayerName)
+OGRAeronavFAARouteLayer::OGRAeronavFAARouteLayer( VSILFILE* fp,
+                                                  const char* pszLayerName,
+                                                  int bIsDPOrSTARSIn ) :
+    OGRAeronavFAALayer(fp, pszLayerName)
 {
-    this->bIsDPOrSTARS = bIsDPOrSTARS;
+    this->bIsDPOrSTARS = bIsDPOrSTARSIn;
 
     poFeatureDefn->SetGeomType( wkbLineString );
 
@@ -413,7 +414,6 @@ OGRAeronavFAARouteLayer::OGRAeronavFAARouteLayer( VSILFILE* fp, const char* pszL
         OGRFieldDefn oField( "NAME", OFTString );
         poFeatureDefn->AddFieldDefn( &oField );
     }
-    
 }
 
 
@@ -436,7 +436,7 @@ OGRFeature *OGRAeronavFAARouteLayer::GetNextRawFeature()
     OGRFeature* poFeature = NULL;
     OGRLineString* poLS = NULL;
 
-    while(TRUE)
+    while( true )
     {
         if (osLastReadLine.size() != 0)
             pszLine = osLastReadLine.c_str();
@@ -447,12 +447,12 @@ OGRFeature *OGRAeronavFAARouteLayer::GetNextRawFeature()
         if (pszLine == NULL)
         {
             bEOF = TRUE;
-            return poFeature;
+            break;
         }
         if (strlen(pszLine) != 85)
             continue;
 
-        if (bIsDPOrSTARS && strncmp(pszLine, "===", 3) == 0 && pszLine[3] != '=')
+        if (bIsDPOrSTARS && STARTS_WITH(pszLine, "===") && pszLine[3] != '=')
         {
             osAPTName = pszLine + 3;
             const char* pszComma = strchr(pszLine + 3, ',');
@@ -473,15 +473,15 @@ OGRFeature *OGRAeronavFAARouteLayer::GetNextRawFeature()
             }
         }
 
-        if (strncmp(pszLine + 2, "FACILITY OR", strlen("FACILITY OR")) == 0)
+        if (STARTS_WITH(pszLine + 2, "FACILITY OR"))
             continue;
-        if (strncmp(pszLine + 2, "INTERSECTION", strlen("INTERSECTION")) == 0)
+        if (STARTS_WITH(pszLine + 2, "INTERSECTION"))
             continue;
 
         if (strcmp(pszLine, "================================DELETIONS LIST=================================198326") == 0)
         {
             bEOF = TRUE;
-            return poFeature;
+            break;
         }
 
         if (poFeature == NULL)
@@ -491,7 +491,7 @@ OGRFeature *OGRAeronavFAARouteLayer::GetNextRawFeature()
                 continue;
             }
 
-            if (strncmp(pszLine + 29, "                    ", 20) == 0 ||
+            if (STARTS_WITH(pszLine + 29, "                    ") ||
                 strchr(pszLine, '(') != NULL)
             {
                 CPLString osName = pszLine + 2;
@@ -518,17 +518,16 @@ OGRFeature *OGRAeronavFAARouteLayer::GetNextRawFeature()
                 else
                     poFeature->SetField(0, osName);
                 poLS = new OGRLineString();
-                poFeature->SetGeometryDirectly(poLS);
             }
             continue;
         }
 
-        if (strncmp(pszLine, "                                                                                    0", 85) == 0)
+        if (STARTS_WITH(pszLine, "                                                                                    0"))
         {
             if (poLS->getNumPoints() == 0)
                 continue;
             else
-                return poFeature;
+                break;
         }
 
         if (pszLine[29 - 1] == ' ' && pszLine[42 - 1] == ' ')
@@ -536,7 +535,7 @@ OGRFeature *OGRAeronavFAARouteLayer::GetNextRawFeature()
         if (strstr(pszLine, "RWY") || strchr(pszLine, '('))
         {
             osLastReadLine = pszLine;
-            return poFeature;
+            break;
         }
 
         double dfLat, dfLon;
@@ -546,6 +545,10 @@ OGRFeature *OGRAeronavFAARouteLayer::GetNextRawFeature()
                   dfLon);
         poLS->addPoint(dfLon, dfLat);
     }
+
+    if( poFeature != NULL )
+        poFeature->SetGeometryDirectly(poLS);
+    return poFeature;
 }
 
 /************************************************************************/
@@ -578,8 +581,9 @@ static const RecordDesc IAP = { sizeof(IAPFields)/sizeof(IAPFields[0]), IAPField
 /*                     OGRAeronavFAAIAPLayer()                          */
 /************************************************************************/
 
-OGRAeronavFAAIAPLayer::OGRAeronavFAAIAPLayer( VSILFILE* fp, const char* pszLayerName ) :
-                        OGRAeronavFAALayer(fp, pszLayerName)
+OGRAeronavFAAIAPLayer::OGRAeronavFAAIAPLayer( VSILFILE* fp,
+                                              const char* pszLayerName ) :
+    OGRAeronavFAALayer(fp, pszLayerName)
 {
     poFeatureDefn->SetGeomType( wkbPoint );
 
@@ -600,11 +604,9 @@ OGRAeronavFAAIAPLayer::OGRAeronavFAAIAPLayer( VSILFILE* fp, const char* pszLayer
         poFeatureDefn->AddFieldDefn( &oField );
     }
 
-
     psRecordDesc = &IAP;
 
-    int i;
-    for(i=0;i<psRecordDesc->nFields;i++)
+    for( int i=0; i < psRecordDesc->nFields; i++ )
     {
         OGRFieldDefn oField( psRecordDesc->pasFields[i].pszFieldName, psRecordDesc->pasFields[i].eType );
         oField.SetWidth(psRecordDesc->pasFields[i].nLastCol - psRecordDesc->pasFields[i].nStartCol + 1);
@@ -633,7 +635,7 @@ OGRFeature *OGRAeronavFAAIAPLayer::GetNextRawFeature()
     char szBuffer[87];
     int nCountUnderscoreLines = 0;
 
-    while(TRUE)
+    while( true )
     {
         pszLine = CPLReadLine2L(fpAeronavFAA, 87, NULL);
         if (pszLine == NULL)
@@ -644,7 +646,7 @@ OGRFeature *OGRAeronavFAAIAPLayer::GetNextRawFeature()
         if (strlen(pszLine) != 85)
             continue;
 
-        if (strncmp(pszLine, "DELETIONS", strlen("DELETIONS")) == 0)
+        if (STARTS_WITH(pszLine, "DELETIONS"))
         {
             bEOF = TRUE;
             return NULL;
@@ -659,7 +661,7 @@ OGRFeature *OGRAeronavFAAIAPLayer::GetNextRawFeature()
 
         if (pszLine[1] != ' ')
             continue;
-        if (strncmp(pszLine, "                                                                               ", 79) == 0)
+        if (STARTS_WITH(pszLine, "                                                                               "))
             continue;
         if (strstr(pszLine, "NAVIGATIONAL AIDS") != NULL)
             continue;
@@ -710,8 +712,7 @@ OGRFeature *OGRAeronavFAAIAPLayer::GetNextRawFeature()
         poFeature->SetField(2, osAPTName);
         poFeature->SetField(3, osAPTId);
 
-        int i;
-        for(i=0;i<psRecordDesc->nFields;i++)
+        for( int i=0; i<psRecordDesc->nFields; i++)
         {
             int nWidth = psRecordDesc->pasFields[i].nLastCol - psRecordDesc->pasFields[i].nStartCol + 1;
             strncpy(szBuffer, pszLine + psRecordDesc->pasFields[i].nStartCol - 1, nWidth);
diff --git a/ogr/ogrsf_frmts/amigocloud/GNUmakefile b/ogr/ogrsf_frmts/amigocloud/GNUmakefile
new file mode 100644
index 0000000..6953a5f
--- /dev/null
+++ b/ogr/ogrsf_frmts/amigocloud/GNUmakefile
@@ -0,0 +1,14 @@
+
+
+include ../../../GDALmake.opt
+
+OBJ	=	ogramigoclouddriver.o ogramigoclouddatasource.o ogramigocloudlayer.o ogramigocloudtablelayer.o ogramigocloudresultlayer.o
+
+CPPFLAGS	:=	$(JSON_INCLUDE) -I.. -I../.. -I../pgdump $(CPPFLAGS)
+
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+$(O_OBJ):	ogr_amigocloud.h
\ No newline at end of file
diff --git a/ogr/ogrsf_frmts/amigocloud/drv_amigocloud.html b/ogr/ogrsf_frmts/amigocloud/drv_amigocloud.html
new file mode 100644
index 0000000..b0ea785
--- /dev/null
+++ b/ogr/ogrsf_frmts/amigocloud/drv_amigocloud.html
@@ -0,0 +1,129 @@
+<html>
+<head>
+<title>AmigoCloud</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>AmigoCloud</h1>
+
+(GDAL/OGR >= 2.1)<p>
+
+This driver can connect to the services implementing the AmigoCloud API.
+GDAL/OGR must be built with Curl support in order for the
+AmigoCloud driver to be compiled.<p>
+
+The driver supports read and write operations.<p>
+
+<h2>Dataset name syntax</h2>
+
+The minimal syntax to open a AmigoCloud datasource is : <pre>AmigoCloud:[project_id]</pre><p>
+
+Additionnal optional parameters can be specified after the ':' sign.
+Currently the following one is supported :<p>
+
+<ul>
+<li> <b>tables=dataset_id1[,dataset_id2]*</b>: A list of AmigoCloud dataset IDs.
+This is necessary when you need to access a particular AmigoCloud datasets.
+</ul>
+
+If several parameters are specified, they must be separated by a space.<p>
+
+<h2>Configuration options</h2>
+
+The following configuration options are available :
+<ul>
+<li>AMIGOCLOUD_API_URL: defaults to https://www.amigocloud.com/api/v1.
+Can be used to point to another server.</li>
+<li>AMIGOCLOUD_HTTPS: can be set to NO to use http:// protocol instead of
+https:// (only if AMIGOCLOUD_API_URL is not defined).</li>
+<li>AMIGOCLOUD_API_KEY: see following paragraph.</li>
+</ul>
+
+
+<h2>Authentication</h2>
+
+All the access permissions are defined by AmigoCloud backend.<p>
+
+Authenticated access is obtained by specifying the API key given in the
+AmigoCloud dashboard web interface. It is specified with the
+AMIGOCLOUD_API_KEY configuration option.<p>
+
+<h2>Geometry</h2>
+
+The OGR driver will report as many geometry fields as available in the
+layer, following RFC 41.
+
+<h2>Filtering</h2>
+
+The driver will forward any spatial filter set with SetSpatialFilter() to
+the server. It also makes the same for attribute
+filters set with SetAttributeFilter().<p>
+
+<h2>Paging</h2>
+
+Features are retrieved from the server by chunks of 500 by default.
+This number can be altered with the AMIGOCLOUD_PAGE_SIZE
+configuration option.<p>
+
+<h2>Write support</h2>
+
+Dataset creation and deletion is possible.<p>
+
+Write support is only enabled when the datasource is opened in update mode.<p>
+
+The mapping between the operations of the AmigoCloud service and the OGR concepts is the following :
+<ul>
+<li>OGRFeature::CreateFeature() <==> INSERT operation</li>
+<li>OGRFeature::SetFeature() <==> UPDATE operation</li>
+<li>OGRFeature::DeleteFeature() <==> DELETE operation</li>
+<li>OGRDataSource::CreateLayer() <==> CREATE TABLE operation</li>
+<li>OGRDataSource::DeleteLayer() <==> DROP TABLE operation</li>
+</ul>
+
+When inserting a new feature with CreateFeature(), and if the command is successful, OGR will fetch the
+returned amigo_id (GUID) and use hash value of it as the OGR FID.<p>
+
+The above operations are by default issued to the server synchronously with the OGR API call. This however
+can cause performance penalties when issuing a lot of commands due to many client/server exchanges.<p>
+
+<p>
+
+<h2>Layer creation options</h2>
+
+<p>The following layer creation options are available:</p>
+<ul>
+<li><b>OVERWRITE</b>=YES/NO: Whether to overwrite an existing table with the
+layer name to be created. Defaults to NO.</li>
+
+<li><b>GEOMETRY_NULLABLE</b>=YES/NO: Whether the values of the geometry column
+can be NULL. Defaults to YES.</li>
+
+</ul>
+
+
+<h2>Examples</h2>
+
+<li>
+Acceccing data from a public table:
+<pre>
+ogrinfo -ro "AmigoCloud:1234 tables=1234,1235"
+</pre>
+<p>
+
+<li>
+Creating and populating a table from a shapefile:
+<pre>
+ogr2ogr --config AMIGOCLOUD_API_KEY abcdefghijklmnopqrstuvw -f "AmigoCloud" AmigoCloud:"1234" myshapefile.shp
+</pre>
+<p>
+
+<h2>See Also</h2>
+
+<ul>
+<li> <a href="https://www.amigocloud.com/accounts/tokens">AmigoCloud API Token management</a><p>
+<li> <a href="https://www.amigocloud.com/api/v1/">AmigoCloud API Browser</a><p>
+</ul>
+
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/amigocloud/makefile.vc b/ogr/ogrsf_frmts/amigocloud/makefile.vc
new file mode 100644
index 0000000..d85663c
--- /dev/null
+++ b/ogr/ogrsf_frmts/amigocloud/makefile.vc
@@ -0,0 +1,33 @@
+OBJ	=	ogramigoclouddriver.obj ogramigoclouddatasource.obj ogramigocloudlayer.obj ogramigocloudtablelayer.obj ogramigocloudresultlayer.obj
+EXTRAFLAGS =	-I.. -I..\.. -I..\geojson\libjson -I..\pgdump 
+
+GDAL_ROOT	=	..\..\..
+
+PLUGIN_DLL	=	ogr_AmigoCloud.dll
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+default:	$(OBJ)
+	$(INSTALL) *.obj ..\o
+
+all:	default
+
+clean:
+	-del *.obj
+	-del *.dll
+	-del *.exp
+	-del *.lib
+	-del *.manifest
+	-del *.pdb
+	-del *.tlh
+
+plugin:	$(PLUGIN_DLL)
+
+
+$(PLUGIN_DLL):	$(OBJ)
+	link /dll $(LDEBUG) /out:$(PLUGIN_DLL) $(OBJ) $(GDAL_ROOT)/gdal_i.lib ../geojson/libjson/*.obj
+	if exist $(PLUGIN_DLL).manifest mt -manifest $(PLUGIN_DLL).manifest -outputresource:$(PLUGIN_DLL);2
+
+plugin-install:
+	-mkdir $(PLUGINDIR)
+	$(INSTALL) $(PLUGIN_DLL) $(PLUGINDIR)
\ No newline at end of file
diff --git a/ogr/ogrsf_frmts/amigocloud/ogr_amigocloud.h b/ogr/ogrsf_frmts/amigocloud/ogr_amigocloud.h
new file mode 100644
index 0000000..7952663
--- /dev/null
+++ b/ogr/ogrsf_frmts/amigocloud/ogr_amigocloud.h
@@ -0,0 +1,296 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  AMIGOCLOUD Translator
+ * Purpose:  Definition of classes for OGR AmigoCloud driver.
+ * Author:   Victor Chernetsky, <victor at amigocloud dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Victor Chernetsky, <victor at amigocloud dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef OGR_AMIGOCLOUD_H_INCLUDED
+#define OGR_AMIGOCLOUD_H_INCLUDED
+
+#include "ogrsf_frmts.h"
+#include "cpl_http.h"
+
+#include <vector>
+#include <string>
+#include <json.h>
+#include <cpl_hash_set.h>
+#include <cstdlib>
+
+json_object* OGRAMIGOCLOUDGetSingleRow(json_object* poObj);
+CPLString OGRAMIGOCLOUDEscapeIdentifier(const char* pszStr);
+CPLString OGRAMIGOCLOUDEscapeLiteral(const char* pszStr);
+
+/************************************************************************/
+/*                      OGRAmigoCloudGeomFieldDefn                         */
+/************************************************************************/
+
+class OGRAmigoCloudGeomFieldDefn: public OGRGeomFieldDefn
+{
+    public:
+        int nSRID;
+
+        OGRAmigoCloudGeomFieldDefn(const char* pszNameIn, OGRwkbGeometryType eType) :
+                OGRGeomFieldDefn(pszNameIn, eType), nSRID(0)
+        {
+        }
+};
+
+class OGRAmigoCloudFID
+{
+    public:
+        GIntBig iIndex;
+        GIntBig iFID;
+        std::string osAmigoId;
+
+        OGRAmigoCloudFID(const std::string &amigo_id, GIntBig index)
+        {
+            iIndex = index;
+            OGRAmigoCloudFID::osAmigoId = amigo_id.c_str();
+            iFID = std::abs((long)CPLHashSetHashStr(amigo_id.c_str()));
+        }
+
+        OGRAmigoCloudFID()
+        {
+            iIndex=0;
+            iFID=0;
+        }
+
+        OGRAmigoCloudFID(const OGRAmigoCloudFID& fid)
+        {
+            iIndex = fid.iIndex;
+            iFID = fid.iFID;
+            osAmigoId = fid.osAmigoId.c_str();
+        }
+};
+
+/************************************************************************/
+/*                           OGRAmigoCloudLayer                            */
+/************************************************************************/
+class OGRAmigoCloudDataSource;
+
+class OGRAmigoCloudLayer : public OGRLayer
+{
+    protected:
+        OGRAmigoCloudDataSource* poDS;
+
+        OGRFeatureDefn      *poFeatureDefn;
+        CPLString            osBaseSQL;
+        CPLString            osFIDColName;
+
+        int                  bEOF;
+        int                  nFetchedObjects;
+        int                  iNextInFetchedObjects;
+        GIntBig              iNext;
+        json_object         *poCachedObj;
+
+        std::map<GIntBig, OGRAmigoCloudFID>  mFIDs;
+
+        virtual OGRFeature  *GetNextRawFeature();
+        OGRFeature          *BuildFeature(json_object* poRowObj);
+
+        void                 EstablishLayerDefn(const char* pszLayerName,
+                                                json_object* poObjIn);
+        OGRSpatialReference *GetSRS(const char* pszGeomCol, int *pnSRID);
+        virtual CPLString    GetSRS_SQL(const char* pszGeomCol) = 0;
+
+    public:
+         OGRAmigoCloudLayer(OGRAmigoCloudDataSource* poDS);
+        ~OGRAmigoCloudLayer();
+
+        virtual void                ResetReading();
+        virtual OGRFeature *        GetNextFeature();
+
+        virtual OGRFeatureDefn *    GetLayerDefn();
+        virtual OGRFeatureDefn *    GetLayerDefnInternal(json_object* poObjIn) = 0;
+        virtual json_object*        FetchNewFeatures(GIntBig iNext);
+
+        virtual const char*         GetFIDColumn() { return osFIDColName.c_str(); }
+
+        virtual int                 TestCapability( const char * );
+
+        int                         GetFeaturesToFetch() { return atoi(CPLGetConfigOption("AMIGOCLOUD_PAGE_SIZE", "500")); }
+};
+
+
+/************************************************************************/
+/*                        OGRAmigoCloudTableLayer                          */
+/************************************************************************/
+
+class OGRAmigoCloudTableLayer : public OGRAmigoCloudLayer
+{
+    CPLString           osTableName;
+    CPLString           osDatasetId;
+    CPLString           osQuery;
+    CPLString           osWHERE;
+    CPLString           osSELECTWithoutWHERE;
+
+    std::vector<std::string> vsDeferredInsertChangesets;
+    GIntBig             nNextFID;
+
+    int                 bDeferredCreation;
+    int                 nMaxChunkSize;
+
+    void                BuildWhere();
+
+    virtual CPLString    GetSRS_SQL(const char* pszGeomCol);
+
+    public:
+         OGRAmigoCloudTableLayer(OGRAmigoCloudDataSource* poDS, const char* pszName);
+        ~OGRAmigoCloudTableLayer();
+
+        virtual const char        *GetName() { return osTableName.c_str(); }
+                const char        *GetDatasetId() { return osDatasetId.c_str(); }
+        virtual OGRFeatureDefn    *GetLayerDefnInternal(json_object* poObjIn);
+        virtual json_object       *FetchNewFeatures(GIntBig iNext);
+
+        virtual GIntBig             GetFeatureCount( int bForce = TRUE );
+        virtual OGRFeature         *GetFeature( GIntBig nFeatureId );
+
+        virtual int                 TestCapability( const char * );
+
+        virtual OGRErr      CreateField( OGRFieldDefn *poField,
+                                         int bApproxOK = TRUE );
+
+        virtual OGRFeature  *GetNextRawFeature();
+
+        virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
+        virtual OGRErr      ISetFeature( OGRFeature *poFeature );
+        virtual OGRErr      DeleteFeature( GIntBig nFID );
+
+        virtual void        SetSpatialFilter( OGRGeometry *poGeom ) { SetSpatialFilter(0, poGeom); }
+        virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom );
+        virtual OGRErr      SetAttributeFilter( const char * );
+
+        virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce ) { return GetExtent(0, psExtent, bForce); }
+        virtual OGRErr      GetExtent( int iGeomField, OGREnvelope *psExtent, int bForce );
+
+        void                SetDeferredCreation(OGRwkbGeometryType eGType,
+                                   OGRSpatialReference *poSRS,
+                                   int bGeomNullable);
+
+        CPLString           GetAmigoCloudType(OGRFieldDefn& oField);
+
+        OGRErr              RunDeferredCreationIfNecessary();
+        int                 GetDeferredCreation() const { return bDeferredCreation; }
+        void                CancelDeferredCreation() { bDeferredCreation = FALSE; }
+
+        void                FlushDeferredInsert();
+        bool                IsDatasetExists();
+};
+
+/************************************************************************/
+/*                       OGRAmigoCloudResultLayer                          */
+/************************************************************************/
+
+class OGRAmigoCloudResultLayer : public OGRAmigoCloudLayer
+{
+        OGRFeature          *poFirstFeature;
+
+        virtual CPLString    GetSRS_SQL(const char* pszGeomCol);
+
+    public:
+        OGRAmigoCloudResultLayer( OGRAmigoCloudDataSource* poDS,
+                                               const char * pszRawStatement );
+        virtual             ~OGRAmigoCloudResultLayer();
+
+        virtual OGRFeatureDefn *GetLayerDefnInternal(json_object* poObjIn);
+        virtual OGRFeature  *GetNextRawFeature();
+
+        int                 IsOK();
+};
+
+/************************************************************************/
+/*                           OGRAmigoCloudDataSource                       */
+/************************************************************************/
+
+class OGRAmigoCloudDataSource : public OGRDataSource
+{
+        char*               pszName;
+        char*               pszProjetctId;
+
+        OGRAmigoCloudTableLayer**  papoLayers;
+        int                 nLayers;
+        int                 bReadWrite;
+
+        int                 bUseHTTPS;
+
+        CPLString           osAPIKey;
+
+        int                 bMustCleanPersistent;
+
+        CPLString           osCurrentSchema;
+
+        int                 bHasOGRMetadataFunction;
+
+    public:
+        OGRAmigoCloudDataSource();
+        ~OGRAmigoCloudDataSource();
+
+        int                 Open( const char * pszFilename,
+                                  char** papszOpenOptions,
+                                  int bUpdate );
+
+        virtual const char* GetName() { return pszName; }
+
+        virtual int         GetLayerCount() { return nLayers; }
+        virtual OGRLayer   *GetLayer( int );
+        virtual OGRLayer   *GetLayerByName(const char *);
+
+        virtual int         TestCapability( const char * );
+
+        virtual OGRLayer   *ICreateLayer( const char *pszName,
+                                         OGRSpatialReference *poSpatialRef = NULL,
+                                         OGRwkbGeometryType eGType = wkbUnknown,
+                                         char ** papszOptions = NULL );
+        virtual OGRErr      DeleteLayer(int);
+
+        virtual OGRLayer   *ExecuteSQL( const char *pszSQLCommand,
+                                        OGRGeometry *poSpatialFilter,
+                                        const char *pszDialect );
+        virtual void        ReleaseResultSet( OGRLayer * poLayer );
+
+        const char*                 GetAPIURL() const;
+        int                         IsReadWrite() const { return bReadWrite; }
+        const char*                 GetProjetcId() { return pszProjetctId;}
+        char**                      AddHTTPOptions();
+        json_object*                RunPOST(const char*pszURL, const char *pszPostData, const char *pszHeaders="HEADERS=Content-Type: application/json");
+        json_object*                RunGET(const char*pszURL);
+        json_object*                RunDELETE(const char*pszURL);
+        json_object*                RunSQL(const char* pszUnescapedSQL);
+        const CPLString&            GetCurrentSchema() { return osCurrentSchema; }
+        int                         FetchSRSId( OGRSpatialReference * poSRS );
+
+        int                         IsAuthenticatedConnection() { return osAPIKey.size() != 0; }
+        int                         HasOGRMetadataFunction() { return bHasOGRMetadataFunction; }
+        void                        SetOGRMetadataFunction(int bFlag) { bHasOGRMetadataFunction = bFlag; }
+
+        OGRLayer *                  ExecuteSQLInternal( const char *pszSQLCommand,
+                                                        OGRGeometry *poSpatialFilter = NULL,
+                                                        const char *pszDialect = NULL,
+                                                        int bRunDeferredActions = FALSE );
+};
+
+#endif /* ndef OGR_AMIGOCLOUD_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/amigocloud/ogramigoclouddatasource.cpp b/ogr/ogrsf_frmts/amigocloud/ogramigoclouddatasource.cpp
new file mode 100644
index 0000000..898faec
--- /dev/null
+++ b/ogr/ogrsf_frmts/amigocloud/ogramigoclouddatasource.cpp
@@ -0,0 +1,866 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  AmigoCloud Translator
+ * Purpose:  Implements OGRAmigoCloudDataSource class
+ * Author:   Victor Chernetsky, <victor at amigocloud dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Victor Chernetsky, <victor at amigocloud dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_amigocloud.h"
+#include "ogr_pgdump.h"
+#include <sstream>
+
+CPL_CVSID("$Id$");
+
+CPLString OGRAMIGOCLOUDGetOptionValue(const char* pszFilename, const char* pszOptionName);
+
+/************************************************************************/
+/*                        OGRAmigoCloudDataSource()                        */
+/************************************************************************/
+
+OGRAmigoCloudDataSource::OGRAmigoCloudDataSource() :
+    pszName(NULL),
+    pszProjetctId(NULL),
+    papoLayers(NULL),
+    nLayers(0),
+    bReadWrite(FALSE),
+    bUseHTTPS(FALSE),
+    bMustCleanPersistent(FALSE),
+    bHasOGRMetadataFunction(-1)
+{}
+
+/************************************************************************/
+/*                       ~OGRAmigoCloudDataSource()                        */
+/************************************************************************/
+
+OGRAmigoCloudDataSource::~OGRAmigoCloudDataSource()
+
+{
+    for( int i = 0; i < nLayers; i++ )
+        delete papoLayers[i];
+    CPLFree( papoLayers );
+
+    if (bMustCleanPersistent)
+    {
+        char** papszOptions = NULL;
+        papszOptions = CSLSetNameValue(papszOptions, "CLOSE_PERSISTENT", CPLSPrintf("AMIGOCLOUD:%p", this));
+        CPLHTTPDestroyResult( CPLHTTPFetch( GetAPIURL(), papszOptions) );
+        CSLDestroy(papszOptions);
+    }
+
+    CPLFree( pszName );
+    CPLFree(pszProjetctId);
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRAmigoCloudDataSource::TestCapability( const char * pszCap )
+
+{
+    if( bReadWrite && EQUAL(pszCap,ODsCCreateLayer) )
+        return TRUE;
+    else if( bReadWrite && EQUAL(pszCap,ODsCDeleteLayer) )
+        return TRUE;
+    else
+        return FALSE;
+}
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer *OGRAmigoCloudDataSource::GetLayer( int iLayer )
+
+{
+    if( iLayer < 0 || iLayer >= nLayers )
+        return NULL;
+    else
+        return papoLayers[iLayer];
+}
+
+/************************************************************************/
+/*                          GetLayerByName()                            */
+/************************************************************************/
+
+OGRLayer *OGRAmigoCloudDataSource::GetLayerByName(const char * pszLayerName)
+{
+    OGRLayer* poLayer = OGRDataSource::GetLayerByName(pszLayerName);
+    return poLayer;
+}
+
+/************************************************************************/
+/*                     OGRAMIGOCLOUDGetOptionValue()                       */
+/************************************************************************/
+
+CPLString OGRAMIGOCLOUDGetOptionValue(const char* pszFilename,
+                               const char* pszOptionName)
+{
+    CPLString osOptionName(pszOptionName);
+    osOptionName += "=";
+    const char* pszOptionValue = strstr(pszFilename, osOptionName);
+    if (!pszOptionValue)
+        return "";
+
+    CPLString osOptionValue(pszOptionValue + strlen(osOptionName));
+    const char* pszSpace = strchr(osOptionValue.c_str(), ' ');
+    if (pszSpace)
+        osOptionValue.resize(pszSpace - osOptionValue.c_str());
+    return osOptionValue;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+int OGRAmigoCloudDataSource::Open( const char * pszFilename,
+                                char** papszOpenOptionsIn,
+                                int bUpdateIn )
+
+{
+
+    bReadWrite = bUpdateIn;
+
+    pszName = CPLStrdup( pszFilename );
+    if( CSLFetchNameValue(papszOpenOptionsIn, "PROJECTID") )
+        pszProjetctId = CPLStrdup(CSLFetchNameValue(papszOpenOptionsIn, "PROJECTID"));
+    else
+    {
+        pszProjetctId = CPLStrdup(pszFilename + strlen("AMIGOCLOUD:"));
+        char* pchSpace = strchr(pszProjetctId, ' ');
+        if( pchSpace )
+            *pchSpace = '\0';
+        if( pszProjetctId[0] == 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Missing projetc id");
+            return FALSE;
+        }
+    }
+
+    osAPIKey = CSLFetchNameValueDef(papszOpenOptionsIn, "API_KEY",
+                                    CPLGetConfigOption("AMIGOCLOUD_API_KEY", ""));
+
+    CPLString osDatasets = OGRAMIGOCLOUDGetOptionValue(pszFilename, "datasets");
+
+    bUseHTTPS = CPLTestBool(CPLGetConfigOption("AMIGOCLOUD_HTTPS", "YES"));
+
+    OGRLayer* poSchemaLayer = ExecuteSQLInternal("SELECT current_schema()");
+    if( poSchemaLayer )
+    {
+        OGRFeature* poFeat = poSchemaLayer->GetNextFeature();
+        if( poFeat )
+        {
+            if( poFeat->GetFieldCount() == 1 )
+            {
+                osCurrentSchema = poFeat->GetFieldAsString(0);
+            }
+            delete poFeat;
+        }
+        ReleaseResultSet(poSchemaLayer);
+    }
+    if( osCurrentSchema.size() == 0 )
+        return FALSE;
+
+    if (osDatasets.size() != 0)
+    {
+        char** papszTables = CSLTokenizeString2(osDatasets, ",", 0);
+        for(int i=0;papszTables && papszTables[i];i++)
+        {
+            papoLayers = (OGRAmigoCloudTableLayer**) CPLRealloc(
+                papoLayers, (nLayers + 1) * sizeof(OGRAmigoCloudTableLayer*));
+            papoLayers[nLayers ++] = new OGRAmigoCloudTableLayer(this, papszTables[i]);
+        }
+        CSLDestroy(papszTables);
+        return TRUE;
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                            GetAPIURL()                               */
+/************************************************************************/
+
+const char* OGRAmigoCloudDataSource::GetAPIURL() const
+{
+    const char* pszAPIURL = CPLGetConfigOption("AMIGOCLOUD_API_URL", NULL);
+    if (pszAPIURL)
+        return pszAPIURL;
+
+    else if (bUseHTTPS)
+        return CPLSPrintf("https://www.amigocloud.com/api/v1");
+    else
+        return CPLSPrintf("http://www.amigocloud.com/api/v1");
+}
+
+/************************************************************************/
+/*                             FetchSRSId()                             */
+/************************************************************************/
+
+int OGRAmigoCloudDataSource::FetchSRSId( OGRSpatialReference * poSRS )
+
+{
+    const char*         pszAuthorityName;
+
+    if( poSRS == NULL )
+        return 0;
+
+    OGRSpatialReference oSRS(*poSRS);
+    poSRS = NULL;
+
+    pszAuthorityName = oSRS.GetAuthorityName(NULL);
+
+    if( pszAuthorityName == NULL || strlen(pszAuthorityName) == 0 )
+    {
+/* -------------------------------------------------------------------- */
+/*      Try to identify an EPSG code                                    */
+/* -------------------------------------------------------------------- */
+        oSRS.AutoIdentifyEPSG();
+
+        pszAuthorityName = oSRS.GetAuthorityName(NULL);
+        if (pszAuthorityName != NULL && EQUAL(pszAuthorityName, "EPSG"))
+        {
+            const char* pszAuthorityCode = oSRS.GetAuthorityCode(NULL);
+            if ( pszAuthorityCode != NULL && strlen(pszAuthorityCode) > 0 )
+            {
+                /* Import 'clean' SRS */
+                oSRS.importFromEPSG( atoi(pszAuthorityCode) );
+
+                pszAuthorityName = oSRS.GetAuthorityName(NULL);
+            }
+        }
+    }
+/* -------------------------------------------------------------------- */
+/*      Check whether the EPSG authority code is already mapped to a    */
+/*      SRS ID.                                                         */
+/* -------------------------------------------------------------------- */
+    if( pszAuthorityName != NULL && EQUAL( pszAuthorityName, "EPSG" ) )
+    {
+        int             nAuthorityCode;
+
+        /* For the root authority name 'EPSG', the authority code
+         * should always be integral
+         */
+        nAuthorityCode = atoi( oSRS.GetAuthorityCode(NULL) );
+
+        return nAuthorityCode;
+    }
+
+    return 0;
+}
+
+/************************************************************************/
+/*                          ICreateLayer()                              */
+/************************************************************************/
+
+OGRLayer   *OGRAmigoCloudDataSource::ICreateLayer( const char *pszNameIn,
+                                           OGRSpatialReference *poSpatialRef,
+                                           OGRwkbGeometryType eGType,
+                                           char ** papszOptions )
+{
+    if (!bReadWrite)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Operation not available in read-only mode");
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Do we already have this layer?  If so, should we blow it        */
+/*      away?                                                           */
+/* -------------------------------------------------------------------- */
+    CPLString osName(pszNameIn);
+
+    OGRAmigoCloudTableLayer* poLayer = new OGRAmigoCloudTableLayer(this, osName);
+    int bGeomNullable = CSLFetchBoolean(papszOptions, "GEOMETRY_NULLABLE", TRUE);
+    poLayer->SetDeferredCreation(eGType, poSpatialRef, bGeomNullable);
+    papoLayers = (OGRAmigoCloudTableLayer**) CPLRealloc(
+                    papoLayers, (nLayers + 1) * sizeof(OGRAmigoCloudTableLayer*));
+    papoLayers[nLayers ++] = poLayer;
+
+    return poLayer;
+}
+
+/************************************************************************/
+/*                            DeleteLayer()                             */
+/************************************************************************/
+
+OGRErr OGRAmigoCloudDataSource::DeleteLayer(int iLayer)
+{
+    if (!bReadWrite)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Operation not available in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
+    if( iLayer < 0 || iLayer >= nLayers )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Layer %d not in legal range of 0 to %d.",
+                  iLayer, nLayers-1 );
+        return OGRERR_FAILURE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Blow away our OGR structures related to the layer.  This is     */
+/*      pretty dangerous if anything has a reference to this layer!     */
+/* -------------------------------------------------------------------- */
+    CPLString osDatasetId = papoLayers[iLayer]->GetDatasetId();
+
+    CPLDebug( "AMIGOCLOUD", "DeleteLayer(%s)", osDatasetId.c_str() );
+
+    int bDeferredCreation = papoLayers[iLayer]->GetDeferredCreation();
+    papoLayers[iLayer]->CancelDeferredCreation();
+    delete papoLayers[iLayer];
+    memmove( papoLayers + iLayer, papoLayers + iLayer + 1,
+             sizeof(void *) * (nLayers - iLayer - 1) );
+    nLayers--;
+
+    if (osDatasetId.size() == 0)
+        return OGRERR_NONE;
+
+    if( !bDeferredCreation )
+    {
+        std::stringstream url;
+        url << std::string(GetAPIURL()) << "/users/0/projects/" + std::string(GetProjetcId()) + "/datasets/"+ osDatasetId.c_str();
+        json_object *poObj = RunDELETE(url.str().c_str());
+
+//        json_object* poObj = RunSQL(osSQL);
+        if( poObj == NULL )
+            return OGRERR_FAILURE;
+        json_object_put(poObj);
+    }
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                          AddHTTPOptions()                            */
+/************************************************************************/
+
+char** OGRAmigoCloudDataSource::AddHTTPOptions()
+{
+    bMustCleanPersistent = TRUE;
+
+    return CSLAddString(NULL, CPLSPrintf("PERSISTENT=AMIGOCLOUD:%p", this));
+}
+
+/************************************************************************/
+/*                               RunPOST()                               */
+/************************************************************************/
+
+json_object* OGRAmigoCloudDataSource::RunPOST(const char*pszURL, const char *pszPostData, const char *pszHeaders)
+{
+    CPLString osURL(pszURL);
+
+    /* -------------------------------------------------------------------- */
+    /*      Provide the API Key                                             */
+    /* -------------------------------------------------------------------- */
+    if( osAPIKey.size() > 0 )
+    {
+        osURL += "?token=";
+        osURL += osAPIKey;
+    }
+    char** papszOptions=NULL;
+    CPLString osPOSTFIELDS("POSTFIELDS=");
+    if (pszPostData)
+        osPOSTFIELDS += pszPostData;
+    papszOptions = CSLAddString(papszOptions, osPOSTFIELDS);
+    papszOptions = CSLAddString(papszOptions, pszHeaders);
+
+    CPLHTTPResult * psResult = CPLHTTPFetch( osURL.c_str(), papszOptions);
+    CSLDestroy(papszOptions);
+    if( psResult == NULL )
+        return NULL;
+
+    if (psResult->pszContentType &&
+        strncmp(psResult->pszContentType, "text/html", 9) == 0)
+    {
+        CPLDebug( "AMIGOCLOUD", "RunPOST HTML Response:%s", psResult->pabyData );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "HTML error page returned by server:%s", psResult->pabyData);
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+    if (psResult->pszErrBuf != NULL)
+    {
+        CPLDebug( "AMIGOCLOUD", "RunPOST Error Message:%s", psResult->pszErrBuf );
+    }
+    else if (psResult->nStatus != 0)
+    {
+        CPLDebug( "AMIGOCLOUD", "RunPOST Error Status:%d", psResult->nStatus );
+    }
+
+    if( psResult->pabyData == NULL )
+    {
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+
+    CPLDebug( "AMIGOCLOUD", "RunPOST Response:%s", psResult->pabyData );
+
+    json_tokener* jstok = NULL;
+    json_object* poObj = NULL;
+
+    jstok = json_tokener_new();
+    poObj = json_tokener_parse_ex(jstok, (const char*) psResult->pabyData, -1);
+    if( jstok->err != json_tokener_success)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "JSON parsing error: %s (at offset %d)",
+                  json_tokener_error_desc(jstok->err), jstok->char_offset);
+        json_tokener_free(jstok);
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+    json_tokener_free(jstok);
+
+    CPLHTTPDestroyResult(psResult);
+
+    if( poObj != NULL )
+    {
+        if( json_object_get_type(poObj) == json_type_object )
+        {
+            json_object* poError = json_object_object_get(poObj, "error");
+            if( poError != NULL && json_object_get_type(poError) == json_type_array &&
+                json_object_array_length(poError) > 0 )
+            {
+                poError = json_object_array_get_idx(poError, 0);
+                if( poError != NULL && json_object_get_type(poError) == json_type_string )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Error returned by server : %s", json_object_get_string(poError));
+                    json_object_put(poObj);
+                    return NULL;
+                }
+            }
+        }
+        else
+        {
+            json_object_put(poObj);
+            return NULL;
+        }
+    }
+
+    return poObj;
+}
+
+/************************************************************************/
+/*                               RunDELETE()                               */
+/************************************************************************/
+
+json_object* OGRAmigoCloudDataSource::RunDELETE(const char*pszURL)
+{
+    CPLString osURL(pszURL);
+
+    /* -------------------------------------------------------------------- */
+    /*      Provide the API Key                                             */
+    /* -------------------------------------------------------------------- */
+    if( osAPIKey.size() > 0 )
+    {
+        osURL += "?token=";
+        osURL += osAPIKey;
+    }
+    char** papszOptions=NULL;
+    CPLString osPOSTFIELDS("CUSTOMREQUEST=DELETE");
+    papszOptions = CSLAddString(papszOptions, osPOSTFIELDS);
+
+    CPLHTTPResult * psResult = CPLHTTPFetch( osURL.c_str(), papszOptions);
+    CSLDestroy(papszOptions);
+    if( psResult == NULL )
+        return NULL;
+
+    if (psResult->pszContentType &&
+        strncmp(psResult->pszContentType, "text/html", 9) == 0)
+    {
+        CPLDebug( "AMIGOCLOUD", "RunDELETE HTML Response:%s", psResult->pabyData );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "HTML error page returned by server:%s", psResult->pabyData);
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+    if (psResult->pszErrBuf != NULL)
+    {
+        CPLDebug( "AMIGOCLOUD", "RunDELETE Error Message:%s", psResult->pszErrBuf );
+    }
+    else if ( psResult->nStatus != 0)
+    {
+        CPLDebug( "AMIGOCLOUD", "RunDELETE Error Status:%d", psResult->nStatus );
+    }
+
+    if( psResult->pabyData == NULL )
+    {
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+
+    CPLDebug( "AMIGOCLOUD", "RunDELETE Response:%s", psResult->pabyData );
+
+    json_tokener* jstok = NULL;
+    json_object* poObj = NULL;
+
+    jstok = json_tokener_new();
+    poObj = json_tokener_parse_ex(jstok, (const char*) psResult->pabyData, -1);
+    if( jstok->err != json_tokener_success)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "JSON parsing error: %s (at offset %d)",
+                  json_tokener_error_desc(jstok->err), jstok->char_offset);
+        json_tokener_free(jstok);
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+    json_tokener_free(jstok);
+
+    CPLHTTPDestroyResult(psResult);
+
+    if( poObj != NULL )
+    {
+        if( json_object_get_type(poObj) == json_type_object )
+        {
+            json_object* poError = json_object_object_get(poObj, "error");
+            if( poError != NULL && json_object_get_type(poError) == json_type_array &&
+                json_object_array_length(poError) > 0 )
+            {
+                poError = json_object_array_get_idx(poError, 0);
+                if( poError != NULL && json_object_get_type(poError) == json_type_string )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Error returned by server : %s", json_object_get_string(poError));
+                    json_object_put(poObj);
+                    return NULL;
+                }
+            }
+        }
+        else
+        {
+            json_object_put(poObj);
+            return NULL;
+        }
+    }
+
+    return poObj;
+}
+
+/************************************************************************/
+/*                               RunGET()                               */
+/************************************************************************/
+
+json_object* OGRAmigoCloudDataSource::RunGET(const char*pszURL)
+{
+    CPLString osURL(pszURL);
+
+    /* -------------------------------------------------------------------- */
+    /*      Provide the API Key                                             */
+    /* -------------------------------------------------------------------- */
+    if( osAPIKey.size() > 0 )
+    {
+        osURL += "?token=";
+        osURL += osAPIKey;
+    }
+
+    CPLHTTPResult * psResult = CPLHTTPFetch( osURL.c_str(), NULL);
+    if( psResult == NULL )
+        return NULL;
+
+    if (psResult->pszContentType &&
+        strncmp(psResult->pszContentType, "text/html", 9) == 0)
+    {
+        CPLDebug( "AMIGOCLOUD", "RunGET HTML Response:%s", psResult->pabyData );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "HTML error page returned by server:%s", psResult->pabyData);
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+    if ( psResult->pszErrBuf != NULL)
+    {
+        CPLDebug( "AMIGOCLOUD", "RunGET Error Message:%s", psResult->pszErrBuf );
+    }
+    else if (psResult->nStatus != 0)
+    {
+        CPLDebug( "AMIGOCLOUD", "RunGET Error Status:%d", psResult->nStatus );
+    }
+
+    if( psResult->pabyData == NULL )
+    {
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+
+    CPLDebug( "AMIGOCLOUD", "RunGET Response:%s", psResult->pabyData );
+
+    json_tokener* jstok = NULL;
+    json_object* poObj = NULL;
+
+    jstok = json_tokener_new();
+    poObj = json_tokener_parse_ex(jstok, (const char*) psResult->pabyData, -1);
+    if( jstok->err != json_tokener_success)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "JSON parsing error: %s (at offset %d)",
+                  json_tokener_error_desc(jstok->err), jstok->char_offset);
+        json_tokener_free(jstok);
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+    json_tokener_free(jstok);
+
+    CPLHTTPDestroyResult(psResult);
+
+    if( poObj != NULL )
+    {
+        if( json_object_get_type(poObj) == json_type_object )
+        {
+            json_object* poError = json_object_object_get(poObj, "error");
+            if( poError != NULL && json_object_get_type(poError) == json_type_array &&
+                json_object_array_length(poError) > 0 )
+            {
+                poError = json_object_array_get_idx(poError, 0);
+                if( poError != NULL && json_object_get_type(poError) == json_type_string )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Error returned by server : %s", json_object_get_string(poError));
+                    json_object_put(poObj);
+                    return NULL;
+                }
+            }
+        }
+        else
+        {
+            json_object_put(poObj);
+            return NULL;
+        }
+    }
+
+    return poObj;
+}
+
+/************************************************************************/
+/*                               RunSQL()                               */
+/************************************************************************/
+
+json_object* OGRAmigoCloudDataSource::RunSQL(const char* pszUnescapedSQL)
+{
+    CPLString osSQL;
+    osSQL = "/users/0/projects/" + CPLString(pszProjetctId) + "/sql";
+
+    /* -------------------------------------------------------------------- */
+    /*      Provide the API Key                                             */
+    /* -------------------------------------------------------------------- */
+    if( osAPIKey.size() > 0 )
+    {
+        osSQL += "?token=";
+        osSQL += osAPIKey;
+    }
+
+    osSQL += "&query=";
+
+    char * pszEscaped = CPLEscapeString( pszUnescapedSQL, -1, CPLES_URL );
+    std::string escaped = pszEscaped;
+    CPLFree( pszEscaped );
+    osSQL += escaped;
+
+/* -------------------------------------------------------------------- */
+/*      Collection the header options and execute request.              */
+/* -------------------------------------------------------------------- */
+
+    std::string pszAPIURL = GetAPIURL();
+    char** papszOptions = NULL;
+
+    pszAPIURL += osSQL;
+
+    CPLHTTPResult * psResult = CPLHTTPFetch( pszAPIURL.c_str(), papszOptions);
+    CSLDestroy(papszOptions);
+    if( psResult == NULL )
+        return NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Check for some error conditions and report.  HTML Messages      */
+/*      are transformed info failure.                                   */
+/* -------------------------------------------------------------------- */
+    if (psResult->pszContentType &&
+        strncmp(psResult->pszContentType, "text/html", 9) == 0)
+    {
+        CPLDebug( "AMIGOCLOUD", "RunSQL HTML Response:%s", psResult->pabyData );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "HTML error page returned by server");
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+    if (psResult->pszErrBuf != NULL)
+    {
+        CPLDebug( "AMIGOCLOUD", "RunSQL Error Message:%s", psResult->pszErrBuf );
+    }
+    else if (psResult->nStatus != 0)
+    {
+        CPLDebug( "AMIGOCLOUD", "RunSQL Error Status:%d", psResult->nStatus );
+    }
+
+    if( psResult->pabyData == NULL )
+    {
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+
+    CPLDebug( "AMIGOCLOUD", "RunSQL Response:%s", psResult->pabyData );
+
+    json_tokener* jstok = NULL;
+    json_object* poObj = NULL;
+
+    jstok = json_tokener_new();
+    poObj = json_tokener_parse_ex(jstok, (const char*) psResult->pabyData, -1);
+    if( jstok->err != json_tokener_success)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                    "JSON parsing error: %s (at offset %d)",
+                    json_tokener_error_desc(jstok->err), jstok->char_offset);
+        json_tokener_free(jstok);
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+    json_tokener_free(jstok);
+
+    CPLHTTPDestroyResult(psResult);
+
+    if( poObj != NULL )
+    {
+        if( json_object_get_type(poObj) == json_type_object )
+        {
+            json_object* poError = json_object_object_get(poObj, "error");
+            if( poError != NULL && json_object_get_type(poError) == json_type_array &&
+                json_object_array_length(poError) > 0 )
+            {
+                poError = json_object_array_get_idx(poError, 0);
+                if( poError != NULL && json_object_get_type(poError) == json_type_string )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                            "Error returned by server : %s", json_object_get_string(poError));
+                    json_object_put(poObj);
+                    return NULL;
+                }
+            }
+        }
+        else
+        {
+            json_object_put(poObj);
+            return NULL;
+        }
+    }
+
+    return poObj;
+}
+
+/************************************************************************/
+/*                        OGRAMIGOCLOUDGetSingleRow()                      */
+/************************************************************************/
+
+json_object* OGRAMIGOCLOUDGetSingleRow(json_object* poObj)
+{
+    if( poObj == NULL )
+    {
+        return NULL;
+    }
+
+    json_object* poRows = json_object_object_get(poObj, "data");
+    if( poRows == NULL ||
+        json_object_get_type(poRows) != json_type_array ||
+        json_object_array_length(poRows) != 1 )
+    {
+        return NULL;
+    }
+
+    json_object* poRowObj = json_object_array_get_idx(poRows, 0);
+    if( poRowObj == NULL || json_object_get_type(poRowObj) != json_type_object )
+    {
+        return NULL;
+    }
+
+    return poRowObj;
+}
+
+/************************************************************************/
+/*                             ExecuteSQL()                             */
+/************************************************************************/
+
+OGRLayer * OGRAmigoCloudDataSource::ExecuteSQL( const char *pszSQLCommand,
+                                        OGRGeometry *poSpatialFilter,
+                                        const char *pszDialect )
+
+{
+    return ExecuteSQLInternal(pszSQLCommand, poSpatialFilter, pszDialect,
+                              TRUE);
+}
+
+OGRLayer * OGRAmigoCloudDataSource::ExecuteSQLInternal( const char *pszSQLCommand,
+                                                     OGRGeometry *poSpatialFilter,
+                                                     const char *,
+                                                     int bRunDeferredActions )
+
+{
+    if( bRunDeferredActions )
+    {
+        for( int iLayer = 0; iLayer < nLayers; iLayer++ )
+        {
+            papoLayers[iLayer]->RunDeferredCreationIfNecessary();
+            papoLayers[iLayer]->FlushDeferredInsert();
+        }
+    }
+
+    /* Skip leading spaces */
+    while(*pszSQLCommand == ' ')
+        pszSQLCommand ++;
+
+
+    if( !EQUALN(pszSQLCommand, "SELECT", strlen("SELECT")) &&
+        !EQUALN(pszSQLCommand, "EXPLAIN", strlen("EXPLAIN")) &&
+        !EQUALN(pszSQLCommand, "WITH", strlen("WITH")) )
+    {
+        RunSQL(pszSQLCommand);
+        return NULL;
+    }
+
+    OGRAmigoCloudResultLayer* poLayer = new OGRAmigoCloudResultLayer( this, pszSQLCommand );
+
+    if( poSpatialFilter != NULL )
+        poLayer->SetSpatialFilter( poSpatialFilter );
+
+    if( !poLayer->IsOK() )
+    {
+        delete poLayer;
+        return NULL;
+    }
+
+    return poLayer;
+}
+
+/************************************************************************/
+/*                          ReleaseResultSet()                          */
+/************************************************************************/
+
+void OGRAmigoCloudDataSource::ReleaseResultSet( OGRLayer * poLayer )
+
+{
+    delete poLayer;
+}
diff --git a/ogr/ogrsf_frmts/amigocloud/ogramigoclouddriver.cpp b/ogr/ogrsf_frmts/amigocloud/ogramigoclouddriver.cpp
new file mode 100644
index 0000000..1f3c22d
--- /dev/null
+++ b/ogr/ogrsf_frmts/amigocloud/ogramigoclouddriver.cpp
@@ -0,0 +1,138 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  AmigoCloud Translator
+ * Purpose:  Implements OGRAMIGOCLOUDDriver.
+ * Author:   Victor Chernetsky, <victor at amigocloud dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Victor Chernetsky, <victor at amigocloud dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_amigocloud.h"
+
+CPL_CVSID("$Id$");
+
+extern "C" void RegisterOGRAmigoCloud();
+
+/************************************************************************/
+/*                        OGRAmigoCloudDriverIdentify()                    */
+/************************************************************************/
+
+static int OGRAmigoCloudDriverIdentify( GDALOpenInfo* poOpenInfo )
+{
+    return EQUALN(poOpenInfo->pszFilename, "AMIGOCLOUD:", strlen("AMIGOCLOUD:"));
+}
+
+/************************************************************************/
+/*                           OGRAmigoCloudDriverOpen()                     */
+/************************************************************************/
+
+static GDALDataset *OGRAmigoCloudDriverOpen( GDALOpenInfo* poOpenInfo )
+
+{
+    if( !OGRAmigoCloudDriverIdentify(poOpenInfo) )
+        return NULL;
+
+    OGRAmigoCloudDataSource   *poDS = new OGRAmigoCloudDataSource();
+
+    if( !poDS->Open( poOpenInfo->pszFilename, poOpenInfo->papszOpenOptions,
+                     poOpenInfo->eAccess == GA_Update ) )
+    {
+        delete poDS;
+        poDS = NULL;
+    }
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                      OGRAmigoCloudDriverCreate()                        */
+/************************************************************************/
+
+static GDALDataset *OGRAmigoCloudDriverCreate( const char * pszName,
+                                            CPL_UNUSED int nBands,
+                                            CPL_UNUSED int nXSize,
+                                            CPL_UNUSED int nYSize,
+                                            CPL_UNUSED GDALDataType eDT,
+                                            CPL_UNUSED char **papszOptions )
+
+{
+    OGRAmigoCloudDataSource   *poDS = new OGRAmigoCloudDataSource();
+
+    if( !poDS->Open( pszName, NULL, TRUE ) )
+    {
+        delete poDS;
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "AmigoCloud driver doesn't support database creation." );
+        return NULL;
+    }
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                         RegisterOGRAMIGOCLOUD()                         */
+/************************************************************************/
+
+void RegisterOGRAmigoCloud()
+
+{
+    if( GDALGetDriverByName( "AmigoCloud" ) != NULL )
+        return;
+
+    GDALDriver* poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "AmigoCloud" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,  "AmigoCloud" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_amigocloud.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, "AMIGOCLOUD:" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+    "<OpenOptionList>"
+    "  <Option name='API_KEY' type='string' description='Account API key'/>"
+    "  <Option name='PROJECTID' type='string' description='Project id' required='true'/>"
+    "  <Option name='BATCH_INSERT' type='boolean' description='Whether to group features to be inserted in a batch' default='YES'/>"
+    "</OpenOptionList>");
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+                               "<CreationOptionList/>");
+
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+    "<LayerCreationOptionList>"
+    "  <Option name='OVERWRITE' type='boolean' description='Whether to overwrite an existing table with the layer name to be created' default='NO'/>"
+    "  <Option name='GEOMETRY_NULLABLE' type='boolean' description='Whether the values of the geometry column can be NULL' default='YES'/>"
+    "</LayerCreationOptionList>");
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
+                               "String Integer Integer64 Real" );
+    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_FIELDS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_DEFAULT_FIELDS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_GEOMFIELDS, "YES" );
+
+    poDriver->pfnOpen = OGRAmigoCloudDriverOpen;
+    poDriver->pfnIdentify = OGRAmigoCloudDriverIdentify;
+    poDriver->pfnCreate = OGRAmigoCloudDriverCreate;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
+
diff --git a/ogr/ogrsf_frmts/amigocloud/ogramigocloudlayer.cpp b/ogr/ogrsf_frmts/amigocloud/ogramigocloudlayer.cpp
new file mode 100644
index 0000000..a928a10
--- /dev/null
+++ b/ogr/ogrsf_frmts/amigocloud/ogramigocloudlayer.cpp
@@ -0,0 +1,465 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  AmigoCloud Translator
+ * Purpose:  Implements OGRAmigoCloudLayer class.
+ * Author:   Victor Chernetsky, <victor at amigocloud dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Victor Chernetsky, <victor at amigocloud dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_amigocloud.h"
+#include "ogr_p.h"
+
+CPL_CVSID("$Id$");
+
+/************************************************************************/
+/*                         OGRAmigoCloudLayer()                            */
+/************************************************************************/
+
+OGRAmigoCloudLayer::OGRAmigoCloudLayer(OGRAmigoCloudDataSource* poDSIn) :
+    poDS(poDSIn),
+    poFeatureDefn(NULL),
+    osFIDColName("amigo_id"),
+    poCachedObj(NULL)
+{
+    ResetReading();
+}
+
+/************************************************************************/
+/*                         ~OGRAmigoCloudLayer()                           */
+/************************************************************************/
+
+OGRAmigoCloudLayer::~OGRAmigoCloudLayer()
+
+{
+    if( poCachedObj != NULL )
+        json_object_put(poCachedObj);
+
+    if( poFeatureDefn != NULL )
+        poFeatureDefn->Release();
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRAmigoCloudLayer::ResetReading()
+
+{
+    if( poCachedObj != NULL )
+        json_object_put(poCachedObj);
+    poCachedObj = NULL;
+    bEOF = FALSE;
+    nFetchedObjects = -1;
+    iNextInFetchedObjects = 0;
+    iNext = 0;
+}
+
+/************************************************************************/
+/*                           GetLayerDefn()                             */
+/************************************************************************/
+
+OGRFeatureDefn * OGRAmigoCloudLayer::GetLayerDefn()
+{
+    return GetLayerDefnInternal(NULL);
+}
+
+/************************************************************************/
+/*                            BuildFeature()                            */
+/************************************************************************/
+
+OGRFeature *OGRAmigoCloudLayer::BuildFeature(json_object* poRowObj)
+{
+    OGRFeature* poFeature = NULL;
+    if( poRowObj != NULL &&
+        json_object_get_type(poRowObj) == json_type_object )
+    {
+        poFeature = new OGRFeature(poFeatureDefn);
+
+        if( osFIDColName.size() > 0 )
+        {
+            json_object* poVal = json_object_object_get(poRowObj, osFIDColName);
+            if( poVal != NULL &&
+                json_object_get_type(poVal) == json_type_string )
+            {
+                std::string amigo_id = json_object_get_string(poVal);
+                OGRAmigoCloudFID aFID(amigo_id, iNext);
+                mFIDs[aFID.iFID] = aFID;
+                poFeature->SetFID(aFID.iFID);
+
+            }
+        }
+
+
+        for(int i=0;i<poFeatureDefn->GetFieldCount();i++)
+        {
+            json_object* poVal = json_object_object_get(poRowObj,
+                            poFeatureDefn->GetFieldDefn(i)->GetNameRef());
+
+            if( poVal != NULL &&
+                json_object_get_type(poVal) == json_type_string )
+            {
+                if( poFeatureDefn->GetFieldDefn(i)->GetType() == OFTDateTime )
+                {
+                    OGRField sField;
+                    if( OGRParseXMLDateTime( json_object_get_string(poVal),
+                                             &sField) )
+                    {
+                        poFeature->SetField(i, &sField);
+                    }
+                }
+                else
+                {
+                    poFeature->SetField(i, json_object_get_string(poVal));
+                }
+            }
+            else if( poVal != NULL &&
+                (json_object_get_type(poVal) == json_type_int ||
+                 json_object_get_type(poVal) == json_type_boolean) )
+            {
+                poFeature->SetField(i, (GIntBig)json_object_get_int64(poVal));
+            }
+            else if( poVal != NULL &&
+                json_object_get_type(poVal) == json_type_double )
+            {
+                poFeature->SetField(i, json_object_get_double(poVal));
+            }
+        }
+
+        for(int i=0;i<poFeatureDefn->GetGeomFieldCount();i++)
+        {
+            OGRGeomFieldDefn* poGeomFldDefn = poFeatureDefn->GetGeomFieldDefn(i);
+            json_object* poVal = json_object_object_get(poRowObj,
+                            poGeomFldDefn->GetNameRef());
+            if( poVal != NULL &&
+                json_object_get_type(poVal) == json_type_string )
+            {
+                OGRGeometry* poGeom = OGRGeometryFromHexEWKB(
+                                        json_object_get_string(poVal), NULL, FALSE);
+                if( poGeom != NULL )
+                    poGeom->assignSpatialReference(poGeomFldDefn->GetSpatialRef());
+                poFeature->SetGeomFieldDirectly(i, poGeom);
+            }
+        }
+    }
+    return poFeature;
+}
+
+/************************************************************************/
+/*                        FetchNewFeatures()                            */
+/************************************************************************/
+
+json_object* OGRAmigoCloudLayer::FetchNewFeatures(GIntBig iNextIn)
+{
+    CPLString osSQL = osBaseSQL;
+    if( osSQL.ifind("SELECT") != std::string::npos &&
+        osSQL.ifind(" LIMIT ") == std::string::npos )
+    {
+        osSQL += " LIMIT ";
+        osSQL += CPLSPrintf("%d", GetFeaturesToFetch());
+        osSQL += " OFFSET ";
+        osSQL += CPLSPrintf(CPL_FRMT_GIB, iNextIn);
+    }
+    return poDS->RunSQL(osSQL);
+}
+
+/************************************************************************/
+/*                       GetNextRawFeature()                            */
+/************************************************************************/
+
+OGRFeature *OGRAmigoCloudLayer::GetNextRawFeature()
+{
+    if( bEOF )
+        return NULL;
+
+    if( iNextInFetchedObjects >= nFetchedObjects )
+    {
+        if( nFetchedObjects > 0 && nFetchedObjects < GetFeaturesToFetch() )
+        {
+            bEOF = TRUE;
+            return NULL;
+        }
+
+        if( poFeatureDefn == NULL && osBaseSQL.size() == 0 )
+        {
+            GetLayerDefn();
+        }
+
+        json_object* poObj = FetchNewFeatures(iNext);
+        if( poObj == NULL )
+        {
+            bEOF = TRUE;
+            return NULL;
+        }
+
+        if( poFeatureDefn == NULL )
+        {
+            GetLayerDefnInternal(poObj);
+        }
+
+        json_object* poRows = json_object_object_get(poObj, "data");
+
+        if( poRows == NULL ||
+            json_object_get_type(poRows) != json_type_array ||
+            json_object_array_length(poRows) == 0 )
+        {
+            json_object_put(poObj);
+            bEOF = TRUE;
+            return NULL;
+        }
+
+        if( poCachedObj != NULL )
+            json_object_put(poCachedObj);
+        poCachedObj = poObj;
+
+        nFetchedObjects = json_object_array_length(poRows);
+        iNextInFetchedObjects = 0;
+    }
+
+    json_object* poRows = json_object_object_get(poCachedObj, "data");
+    json_object* poRowObj = json_object_array_get_idx(poRows, iNextInFetchedObjects);
+
+    iNextInFetchedObjects ++;
+
+    OGRFeature* poFeature = BuildFeature(poRowObj);
+
+    std::map<GIntBig, OGRAmigoCloudFID>::iterator it = mFIDs.find(poFeature->GetFID());
+    if(it!=mFIDs.end())
+    {
+//        iNext = poFeature->GetFID() + 1;
+        iNext = it->second.iIndex + 1;
+    }
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature *OGRAmigoCloudLayer::GetNextFeature()
+{
+    OGRFeature  *poFeature;
+
+    while( true )
+    {
+        poFeature = GetNextRawFeature();
+        if (poFeature == NULL)
+            return NULL;
+
+        if((m_poFilterGeom == NULL
+            || FilterGeometry( poFeature->GetGeometryRef() ) )
+        && (m_poAttrQuery == NULL
+            || m_poAttrQuery->Evaluate( poFeature )) )
+        {
+            return poFeature;
+        }
+        else
+            delete poFeature;
+    }
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRAmigoCloudLayer::TestCapability( const char * pszCap )
+
+{
+    if ( EQUAL(pszCap, OLCStringsAsUTF8) )
+        return TRUE;
+    return FALSE;
+}
+
+/************************************************************************/
+/*                          EstablishLayerDefn()                        */
+/************************************************************************/
+
+void OGRAmigoCloudLayer::EstablishLayerDefn(const char* pszLayerName,
+                                         json_object* poObjIn)
+{
+    poFeatureDefn = new OGRFeatureDefn(pszLayerName);
+    poFeatureDefn->Reference();
+    poFeatureDefn->SetGeomType(wkbNone);
+
+    CPLString osSQL;
+    size_t nPos = osBaseSQL.ifind(" LIMIT ");
+    if( nPos != std::string::npos )
+    {
+        osSQL = osBaseSQL;
+        size_t nSize = osSQL.size();
+        for(size_t i = nPos + strlen(" LIMIT "); i < nSize; i++)
+        {
+            if( osSQL[i] == ' ' )
+                break;
+            osSQL[i] = '0';
+        }
+    }
+    else
+        osSQL.Printf("%s LIMIT 0", osBaseSQL.c_str());
+    json_object* poObj;
+    if( poObjIn != NULL )
+        poObj = poObjIn;
+    else
+    {
+        poObj = poDS->RunSQL(osSQL);
+        if( poObj == NULL )
+        {
+            return;
+        }
+    }
+
+    json_object* poFields = json_object_object_get(poObj, "columns");
+    if( poFields == NULL || json_object_get_type(poFields) != json_type_array)
+    {
+        if( poObjIn == NULL )
+            json_object_put(poObj);
+        return;
+    }
+
+    int size = json_object_array_length(poFields);
+
+    for(int i=0; i< size; i++)
+    {
+        json_object *obj = json_object_array_get_idx(poFields, i);
+
+        if(obj != NULL && json_object_get_type(obj) == json_type_object)
+        {
+            std::string fieldName;
+            std::string fieldType;
+
+            json_object_iter it;
+            it.key = NULL;
+            it.val = NULL;
+            it.entry = NULL;
+            json_object_object_foreachC(obj, it)
+            {
+                const char *pszColName = it.key;
+                if(it.val != NULL)
+                {
+                    if(EQUAL(pszColName, "name"))
+                    {
+                        fieldName = json_object_get_string(it.val);
+                    } else if(EQUAL(pszColName, "type"))
+                    {
+                        fieldType = json_object_get_string(it.val);
+                    }
+                }
+            }
+            if(!fieldName.empty() && !fieldType.empty())
+            {
+
+                if(EQUAL(fieldType.c_str(), "string") ||
+                   EQUAL(fieldType.c_str(), "unknown(19)") /* name */ )
+                {
+                    OGRFieldDefn oFieldDefn(fieldName.c_str(), OFTString);
+                    poFeatureDefn->AddFieldDefn(&oFieldDefn);
+                }
+                else if(EQUAL(fieldType.c_str(), "number"))
+                {
+                    OGRFieldDefn oFieldDefn(fieldName.c_str(), OFTReal);
+                    poFeatureDefn->AddFieldDefn(&oFieldDefn);
+                }
+                else if(EQUAL(fieldType.c_str(), "date"))
+                {
+                    if(!EQUAL(fieldName.c_str(), "created_at") &&
+                       !EQUAL(fieldName.c_str(), "updated_at"))
+                    {
+                        OGRFieldDefn oFieldDefn(fieldName.c_str(), OFTDateTime);
+                        poFeatureDefn->AddFieldDefn(&oFieldDefn);
+                    }
+                }
+                else if(EQUAL(fieldType.c_str(), "geometry"))
+                {
+                    OGRAmigoCloudGeomFieldDefn *poFieldDefn =
+                            new OGRAmigoCloudGeomFieldDefn(fieldName.c_str(), wkbUnknown);
+                    poFeatureDefn->AddGeomFieldDefn(poFieldDefn, FALSE);
+                    OGRSpatialReference* poSRS = GetSRS(fieldName.c_str(), &poFieldDefn->nSRID);
+                    if( poSRS != NULL )
+                    {
+                        poFeatureDefn->GetGeomFieldDefn(
+                                poFeatureDefn->GetGeomFieldCount() - 1)->SetSpatialRef(poSRS);
+                        poSRS->Release();
+                    } else {
+                        poFeatureDefn->GetGeomFieldDefn(
+                                poFeatureDefn->GetGeomFieldCount() - 1)->SetSpatialRef(poSRS);
+                    }
+                }
+                else if(EQUAL(fieldType.c_str(), "boolean"))
+                {
+                    OGRFieldDefn oFieldDefn(fieldName.c_str(), OFTInteger);
+                    oFieldDefn.SetSubType(OFSTBoolean);
+                    poFeatureDefn->AddFieldDefn(&oFieldDefn);
+                }
+                else
+                {
+                    CPLDebug("AMIGOCLOUD", "Unhandled type: %s. Defaulting to string", fieldType.c_str());
+                    OGRFieldDefn oFieldDefn(fieldName.c_str(), OFTString);
+                    poFeatureDefn->AddFieldDefn(&oFieldDefn);
+                }
+            }
+        }
+    }
+    if( poObjIn == NULL )
+        json_object_put(poObj);
+}
+
+/************************************************************************/
+/*                               GetSRS()                               */
+/************************************************************************/
+
+OGRSpatialReference* OGRAmigoCloudLayer::GetSRS(const char* pszGeomCol,
+                                             int *pnSRID)
+{
+    json_object* poObj = poDS->RunSQL(GetSRS_SQL(pszGeomCol));
+    json_object* poRowObj = OGRAMIGOCLOUDGetSingleRow(poObj);
+    if( poRowObj == NULL )
+    {
+        if( poObj != NULL )
+            json_object_put(poObj);
+        return NULL;
+    }
+
+    json_object* poSRID = json_object_object_get(poRowObj, "srid");
+    if( poSRID != NULL && json_object_get_type(poSRID) == json_type_int )
+    {
+        *pnSRID = json_object_get_int(poSRID);
+    }
+
+    json_object* poSRTEXT = json_object_object_get(poRowObj, "srtext");
+    OGRSpatialReference* poSRS = NULL;
+    if( poSRTEXT != NULL && json_object_get_type(poSRTEXT) == json_type_string )
+    {
+        const char* pszSRTEXT = json_object_get_string(poSRTEXT);
+        poSRS = new OGRSpatialReference();
+        char* pszTmp = (char* )pszSRTEXT;
+        if( poSRS->importFromWkt(&pszTmp) != OGRERR_NONE )
+        {
+            delete poSRS;
+            poSRS = NULL;
+        }
+    }
+    json_object_put(poObj);
+
+    return poSRS;
+}
diff --git a/ogr/ogrsf_frmts/amigocloud/ogramigocloudresultlayer.cpp b/ogr/ogrsf_frmts/amigocloud/ogramigocloudresultlayer.cpp
new file mode 100644
index 0000000..6818913
--- /dev/null
+++ b/ogr/ogrsf_frmts/amigocloud/ogramigocloudresultlayer.cpp
@@ -0,0 +1,134 @@
+/******************************************************************************
+ * $Id
+ *
+ * Project:  AmigoCloud Translator
+ * Purpose:  Implements OGRAmigoCloudResultLayer class.
+ * Author:   Victor Chernetsky, <victor at amigocloud dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Victor Chernetsky, <victor at amigocloud dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_amigocloud.h"
+
+CPL_CVSID("$Id");
+
+/************************************************************************/
+/*                          OGRAmigoCloudResultLayer()                     */
+/************************************************************************/
+
+OGRAmigoCloudResultLayer::OGRAmigoCloudResultLayer(
+    OGRAmigoCloudDataSource* poDSIn,
+    const char * pszRawQueryIn ) :
+    OGRAmigoCloudLayer(poDSIn)
+{
+    osBaseSQL = pszRawQueryIn;
+    SetDescription( "result" );
+    poFirstFeature = NULL;
+}
+
+/************************************************************************/
+/*                       ~OGRAmigoCloudResultLayer()                       */
+/************************************************************************/
+
+OGRAmigoCloudResultLayer::~OGRAmigoCloudResultLayer()
+
+{
+    delete poFirstFeature;
+}
+
+/************************************************************************/
+/*                          GetLayerDefnInternal()                      */
+/************************************************************************/
+
+OGRFeatureDefn * OGRAmigoCloudResultLayer::GetLayerDefnInternal(json_object* poObjIn)
+{
+    if( poFeatureDefn != NULL )
+        return poFeatureDefn;
+
+    EstablishLayerDefn("result", poObjIn);
+
+    return poFeatureDefn;
+}
+
+/************************************************************************/
+/*                           GetNextRawFeature()                        */
+/************************************************************************/
+
+OGRFeature  *OGRAmigoCloudResultLayer::GetNextRawFeature()
+{
+    if( poFirstFeature )
+    {
+        OGRFeature* poRet = poFirstFeature;
+        poFirstFeature = NULL;
+        return poRet;
+    }
+    else
+        return OGRAmigoCloudLayer::GetNextRawFeature();
+}
+
+/************************************************************************/
+/*                                IsOK()                                */
+/************************************************************************/
+
+int  OGRAmigoCloudResultLayer::IsOK()
+{
+    CPLErrorReset();
+    poFirstFeature = GetNextFeature();
+    return CPLGetLastErrorType() == 0;
+}
+
+/************************************************************************/
+/*                             GetSRS_SQL()                             */
+/************************************************************************/
+
+CPLString OGRAmigoCloudResultLayer::GetSRS_SQL(const char* pszGeomCol)
+{
+    CPLString osSQL;
+    CPLString osLimitedSQL;
+
+    size_t nPos = osBaseSQL.ifind(" LIMIT ");
+    if( nPos != std::string::npos )
+    {
+        osLimitedSQL = osBaseSQL;
+        size_t nSize = osLimitedSQL.size();
+        for(size_t i = nPos + strlen(" LIMIT "); i < nSize; i++)
+        {
+            if( osLimitedSQL[i] == ' ' && osLimitedSQL[i-1] == '0')
+            {
+                osLimitedSQL[i-1] = '1';
+                break;
+            }
+            osLimitedSQL[i] = '0';
+        }
+    }
+    else
+        osLimitedSQL.Printf("%s LIMIT 1", osBaseSQL.c_str());
+
+    /* Assuming that the SRID of the first non-NULL geometry applies */
+    /* to geometries of all rows. */
+    osSQL.Printf("SELECT srid, srtext FROM spatial_ref_sys WHERE srid IN "
+                "(SELECT ST_SRID(%s) FROM (%s) ogr_subselect)",
+                OGRAMIGOCLOUDEscapeIdentifier(pszGeomCol).c_str(),
+                osLimitedSQL.c_str());
+
+    return osSQL;
+}
diff --git a/ogr/ogrsf_frmts/amigocloud/ogramigocloudtablelayer.cpp b/ogr/ogrsf_frmts/amigocloud/ogramigocloudtablelayer.cpp
new file mode 100644
index 0000000..af01280
--- /dev/null
+++ b/ogr/ogrsf_frmts/amigocloud/ogramigocloudtablelayer.cpp
@@ -0,0 +1,1183 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  AmigoCloud Translator
+ * Purpose:  Implements OGRAmigoCloudTableLayer class.
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Victor Chernetsky, <victor at amigocloud dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_amigocloud.h"
+#include "ogr_p.h"
+#include "ogr_pgdump.h"
+#include <sstream>
+
+CPL_CVSID("$Id$");
+
+/************************************************************************/
+/*                    OGRAMIGOCLOUDEscapeIdentifier( )                     */
+/************************************************************************/
+
+CPLString OGRAMIGOCLOUDEscapeIdentifier(const char* pszStr)
+{
+    CPLString osStr;
+
+    osStr += "\"";
+
+    char ch;
+    for(int i=0; (ch = pszStr[i]) != '\0'; i++)
+    {
+        if (ch == '"')
+            osStr.append(1, ch);
+        osStr.append(1, ch);
+    }
+
+    osStr += "\"";
+
+    return osStr;
+}
+
+/************************************************************************/
+/*                    OGRAMIGOCLOUDEscapeLiteral( )                        */
+/************************************************************************/
+
+CPLString OGRAMIGOCLOUDEscapeLiteral(const char* pszStr)
+{
+    CPLString osStr;
+
+    char ch;
+    for(int i=0; (ch = pszStr[i]) != '\0'; i++)
+    {
+        if (ch == '\'')
+            osStr.append(1, ch);
+        osStr.append(1, ch);
+    }
+
+    return osStr;
+}
+
+static std::string json_encode(const std::string &value) {
+    std::stringstream escaped;
+    escaped.fill('0');
+    escaped << std::hex;
+
+    for (std::string::const_iterator i = value.begin(), n = value.end(); i != n; ++i) {
+        std::string::value_type c = (*i);
+
+        if ( c == '"') {
+            escaped << "\\\"";
+            continue;
+        }
+
+        escaped << c;
+    }
+
+    return escaped.str();
+}
+
+/************************************************************************/
+/*                        OGRAmigoCloudTableLayer()                        */
+/************************************************************************/
+
+OGRAmigoCloudTableLayer::OGRAmigoCloudTableLayer(
+    OGRAmigoCloudDataSource* poDSIn,
+    const char* pszName ) :
+    OGRAmigoCloudLayer(poDSIn),
+    osDatasetId(CPLString(pszName)),
+    nNextFID(-1),
+    bDeferredCreation(FALSE)
+{
+    osTableName = CPLString("dataset_") + osDatasetId;
+    SetDescription( osDatasetId );
+
+    nMaxChunkSize = atoi(
+        CPLGetConfigOption(
+            "AMIGOCLOUD_MAX_CHUNK_SIZE", "15" ) ) * 1024 * 1024;
+}
+
+/************************************************************************/
+/*                    ~OGRAmigoCloudTableLayer()                           */
+/************************************************************************/
+
+OGRAmigoCloudTableLayer::~OGRAmigoCloudTableLayer()
+
+{
+    if( bDeferredCreation ) RunDeferredCreationIfNecessary();
+    FlushDeferredInsert();
+}
+
+/************************************************************************/
+/*                        GetLayerDefnInternal()                        */
+/************************************************************************/
+
+OGRFeatureDefn * OGRAmigoCloudTableLayer::GetLayerDefnInternal(CPL_UNUSED json_object* poObjIn)
+{
+    if( poFeatureDefn != NULL )
+    {
+        return poFeatureDefn;
+    }
+
+    if( poFeatureDefn == NULL )
+    {
+        osBaseSQL.Printf("SELECT * FROM %s", OGRAMIGOCLOUDEscapeIdentifier(osTableName).c_str());
+        EstablishLayerDefn(osTableName, NULL);
+        osBaseSQL = "";
+    }
+
+    if( osFIDColName.size() > 0 )
+    {
+        CPLString sql;
+        sql.Printf("SELECT %s FROM %s", OGRAMIGOCLOUDEscapeIdentifier(osFIDColName).c_str(), OGRAMIGOCLOUDEscapeIdentifier(osTableName).c_str());
+        json_object* poObj = poDS->RunSQL(sql);
+        if( poObj != NULL && json_object_get_type(poObj) == json_type_object)
+        {
+            json_object* poRows = json_object_object_get(poObj, "data");
+
+            if(poRows!=NULL && json_object_get_type(poRows) == json_type_array)
+            {
+                mFIDs.clear();
+                for(int i = 0; i < json_object_array_length(poRows); i++)
+                {
+                    json_object *obj = json_object_array_get_idx(poRows, i);
+
+                    json_object_iter it;
+                    it.key = NULL;
+                    it.val = NULL;
+                    it.entry = NULL;
+                    json_object_object_foreachC(obj, it)
+                    {
+                        const char *pszColName = it.key;
+                        if(it.val != NULL)
+                        {
+                            if(EQUAL(pszColName, osFIDColName.c_str()))
+                            {
+                                std::string amigo_id = json_object_get_string(it.val);
+                                OGRAmigoCloudFID aFID(amigo_id, iNext);
+                                mFIDs[aFID.iFID] = aFID;
+                            }
+                        }
+                    }
+                }
+            }
+            json_object_put(poObj);
+        }
+    }
+
+    if( osFIDColName.size() > 0 )
+    {
+        osBaseSQL = "SELECT ";
+        osBaseSQL += OGRAMIGOCLOUDEscapeIdentifier(osFIDColName);
+    }
+    for(int i=0; i<poFeatureDefn->GetGeomFieldCount(); i++)
+    {
+        if( osBaseSQL.size() == 0 )
+            osBaseSQL = "SELECT ";
+        else
+            osBaseSQL += ", ";
+        osBaseSQL += OGRAMIGOCLOUDEscapeIdentifier(poFeatureDefn->GetGeomFieldDefn(i)->GetNameRef());
+    }
+    for(int i=0; i<poFeatureDefn->GetFieldCount(); i++)
+    {
+        if( osBaseSQL.size() == 0 )
+            osBaseSQL = "SELECT ";
+        else
+            osBaseSQL += ", ";
+        osBaseSQL += OGRAMIGOCLOUDEscapeIdentifier(poFeatureDefn->GetFieldDefn(i)->GetNameRef());
+    }
+    if( osBaseSQL.size() == 0 )
+        osBaseSQL = "SELECT *";
+    osBaseSQL += " FROM ";
+    osBaseSQL += OGRAMIGOCLOUDEscapeIdentifier(osTableName);
+
+    osSELECTWithoutWHERE = osBaseSQL;
+
+    return poFeatureDefn;
+}
+
+/************************************************************************/
+/*                        FetchNewFeatures()                            */
+/************************************************************************/
+
+json_object* OGRAmigoCloudTableLayer::FetchNewFeatures(GIntBig iNextIn)
+{
+    if( osFIDColName.size() > 0 )
+    {
+        CPLString osSQL;
+
+        if(osWHERE.size() > 0)
+        {
+            osSQL.Printf("%s WHERE %s ",
+                         osSELECTWithoutWHERE.c_str(),
+                         (osWHERE.size() > 0) ? CPLSPrintf("%s", osWHERE.c_str()) : "");
+        } else
+        {
+            osSQL.Printf("%s", osSELECTWithoutWHERE.c_str());
+        }
+        return poDS->RunSQL(osSQL);
+    }
+    else
+        return OGRAmigoCloudLayer::FetchNewFeatures(iNextIn);
+}
+
+/************************************************************************/
+/*                           GetNextRawFeature()                        */
+/************************************************************************/
+
+OGRFeature  *OGRAmigoCloudTableLayer::GetNextRawFeature()
+{
+    if( bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
+        return NULL;
+    FlushDeferredInsert();
+    return OGRAmigoCloudLayer::GetNextRawFeature();
+}
+
+/************************************************************************/
+/*                         SetAttributeFilter()                         */
+/************************************************************************/
+
+OGRErr OGRAmigoCloudTableLayer::SetAttributeFilter( const char *pszQuery )
+
+{
+    GetLayerDefn();
+
+    if( pszQuery == NULL )
+        osQuery = "";
+    else
+    {
+        osQuery = "(";
+        osQuery += pszQuery;
+        osQuery += ")";
+    }
+
+    BuildWhere();
+
+    ResetReading();
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                          SetSpatialFilter()                          */
+/************************************************************************/
+
+void OGRAmigoCloudTableLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poGeomIn )
+
+{
+    if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() ||
+        GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetType() == wkbNone )
+    {
+        if( iGeomField != 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Invalid geometry field index : %d", iGeomField);
+        }
+        return;
+    }
+    m_iGeomFieldFilter = iGeomField;
+
+    if( InstallFilter( poGeomIn ) )
+    {
+        BuildWhere();
+
+        ResetReading();
+    }
+}
+
+/************************************************************************/
+/*                         FlushDeferredInsert()                          */
+/************************************************************************/
+
+void OGRAmigoCloudTableLayer::FlushDeferredInsert()
+
+{
+    if(vsDeferredInsertChangesets.size()==0)
+        return;
+
+    std::stringstream url;
+    url << std::string(poDS->GetAPIURL()) << "/users/0/projects/" + std::string(poDS->GetProjetcId()) + "/datasets/"+ osDatasetId +"/submit_change";
+
+    std::stringstream query;
+
+    query << "{\"type\":\"DML\",\"entity\":\"" << osTableName << "\",";
+    query << "\"parent\":null,\"action\":\"INSERT\",\"data\":[";
+
+    int counter=0;
+    for(size_t i=0; i < vsDeferredInsertChangesets.size(); i++)
+    {
+        if(counter>0)
+            query << ",";
+        query << vsDeferredInsertChangesets[i].c_str();
+        counter++;
+    }
+    query << "]}";
+
+    std::stringstream changeset;
+    changeset << "{\"change\": \"" << json_encode(query.str()) << "\"}";
+
+    json_object* poObj = poDS->RunPOST(url.str().c_str(), changeset.str().c_str());
+    if( poObj != NULL )
+        json_object_put(poObj);
+
+    vsDeferredInsertChangesets.clear();
+    nNextFID = -1;
+}
+
+/************************************************************************/
+/*                            CreateField()                             */
+/************************************************************************/
+
+OGRErr OGRAmigoCloudTableLayer::CreateField( OGRFieldDefn *poFieldIn,
+                                          CPL_UNUSED int bApproxOK )
+{
+    GetLayerDefn();
+
+    if (!poDS->IsReadWrite())
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Operation not available in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
+    OGRFieldDefn oField(poFieldIn);
+/* -------------------------------------------------------------------- */
+/*      Create the new field.                                           */
+/* -------------------------------------------------------------------- */
+
+    if( !bDeferredCreation )
+    {
+        CPLString osSQL;
+        osSQL.Printf( "ALTER TABLE %s ADD COLUMN %s %s",
+                    OGRAMIGOCLOUDEscapeIdentifier(osTableName).c_str(),
+                    OGRAMIGOCLOUDEscapeIdentifier(oField.GetNameRef()).c_str(),
+                    OGRPGCommonLayerGetType(oField, FALSE, TRUE).c_str() );
+        if( !oField.IsNullable() )
+            osSQL += " NOT NULL";
+        if( oField.GetDefault() != NULL && !oField.IsDefaultDriverSpecific() )
+        {
+            osSQL += " DEFAULT ";
+            osSQL += OGRPGCommonLayerGetPGDefault(&oField);
+        }
+
+        json_object* poObj = poDS->RunSQL(osSQL);
+        if( poObj == NULL )
+            return OGRERR_FAILURE;
+        json_object_put(poObj);
+    }
+
+    poFeatureDefn->AddFieldDefn( &oField );
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           ICreateFeature()                            */
+/************************************************************************/
+
+OGRErr OGRAmigoCloudTableLayer::ICreateFeature( OGRFeature *poFeature )
+
+{
+    int i;
+
+    if( bDeferredCreation )
+    {
+        if( RunDeferredCreationIfNecessary() != OGRERR_NONE )
+            return OGRERR_FAILURE;
+    }
+
+    GetLayerDefn();
+
+    if (!poDS->IsReadWrite())
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Operation not available in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
+
+    std::stringstream record;
+
+    record << "{\"new\":{";
+
+    int counter=0;
+
+    // Add geometry field
+    for(i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++)
+    {
+        if( poFeature->GetGeomFieldRef(i) == NULL )
+            continue;
+
+        record << "\"" << OGRAMIGOCLOUDEscapeLiteral(poFeatureDefn->GetGeomFieldDefn(i)->GetNameRef()) << "\":";
+
+        OGRGeometry* poGeom = poFeature->GetGeomFieldRef(i);
+        if( poGeom == NULL )
+            continue;
+
+        OGRAmigoCloudGeomFieldDefn* poGeomFieldDefn =
+                (OGRAmigoCloudGeomFieldDefn *)poFeatureDefn->GetGeomFieldDefn(i);
+        int nSRID = poGeomFieldDefn->nSRID;
+        if( nSRID == 0 )
+            nSRID = 4326;
+        char* pszEWKB;
+        if( wkbFlatten(poGeom->getGeometryType()) == wkbPolygon &&
+            wkbFlatten(GetGeomType()) == wkbMultiPolygon )
+        {
+            OGRMultiPolygon* poNewGeom = new OGRMultiPolygon();
+            poNewGeom->addGeometry(poGeom);
+            pszEWKB = OGRGeometryToHexEWKB(poNewGeom, nSRID, 2, 1);
+            delete poNewGeom;
+        }
+        else
+            pszEWKB = OGRGeometryToHexEWKB(poGeom, nSRID, 2, 1);
+        record << "\"" << pszEWKB << "\"";
+        CPLFree(pszEWKB);
+
+        counter++;
+    }
+
+    std::string amigo_id_value;
+
+    // Add non-geometry field
+    for(i = 0; i < poFeatureDefn->GetFieldCount(); i++)
+    {
+        std::string name = poFeatureDefn->GetFieldDefn(i)->GetNameRef();
+        std::string value = poFeature->GetFieldAsString(i);
+
+        if(name=="amigo_id")
+        {
+            amigo_id_value = value;
+            continue;
+        }
+
+        if(counter > 0)
+            record << ",";
+
+        record << OGRAMIGOCLOUDEscapeIdentifier(name.c_str()) << ":";
+
+        if(!value.empty())
+        {
+            OGRFieldType eType = poFeatureDefn->GetFieldDefn(i)->GetType();
+            if( eType == OFTString || eType == OFTDateTime || eType == OFTDate || eType == OFTTime )
+            {
+                record << "\"" << OGRAMIGOCLOUDEscapeLiteral(value.c_str()) << "\"";
+            } else
+                record << OGRAMIGOCLOUDEscapeLiteral(value.c_str());
+        }
+        else
+            record << "null";
+
+        counter++;
+    }
+
+    record << "},";
+
+    if(!amigo_id_value.empty())
+    {
+        record << "\"amigo_id\":\"" << amigo_id_value << "\"";
+    } else
+    {
+        record << "\"amigo_id\":null";
+    }
+
+    record << "}";
+
+    vsDeferredInsertChangesets.push_back(record.str());
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                            ISetFeature()                              */
+/************************************************************************/
+
+OGRErr OGRAmigoCloudTableLayer::ISetFeature( OGRFeature *poFeature )
+
+{
+    int i;
+    OGRErr eRet = OGRERR_FAILURE;
+
+    if( bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
+        return OGRERR_FAILURE;
+    FlushDeferredInsert();
+
+    GetLayerDefn();
+
+    if (!poDS->IsReadWrite())
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Operation not available in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
+    if (poFeature->GetFID() == OGRNullFID)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "FID required on features given to SetFeature()." );
+        return OGRERR_FAILURE;
+    }
+
+
+    std::map<GIntBig, OGRAmigoCloudFID>::iterator it = mFIDs.find( poFeature->GetFID() );
+    if(it!=mFIDs.end())
+    {
+        OGRAmigoCloudFID &aFID = it->second;
+
+        CPLString osSQL;
+        osSQL.Printf("UPDATE %s SET ", OGRAMIGOCLOUDEscapeIdentifier(osTableName).c_str());
+        int bMustComma = FALSE;
+        for(i = 0; i < poFeatureDefn->GetFieldCount(); i++)
+        {
+            if(bMustComma)
+                osSQL += ", ";
+            else
+                bMustComma = TRUE;
+
+            osSQL += OGRAMIGOCLOUDEscapeIdentifier(poFeatureDefn->GetFieldDefn(i)->GetNameRef());
+            osSQL += " = ";
+
+            if(!poFeature->IsFieldSet(i))
+            {
+                osSQL += "NULL";
+            }
+            else
+            {
+                OGRFieldType eType = poFeatureDefn->GetFieldDefn(i)->GetType();
+                if(eType == OFTString || eType == OFTDateTime || eType == OFTDate || eType == OFTTime)
+                {
+                    osSQL += "'";
+                    osSQL += OGRAMIGOCLOUDEscapeLiteral(poFeature->GetFieldAsString(i));
+                    osSQL += "'";
+                }
+                else if((eType == OFTInteger || eType == OFTInteger64) &&
+                        poFeatureDefn->GetFieldDefn(i)->GetSubType() == OFSTBoolean)
+                {
+                    osSQL += poFeature->GetFieldAsInteger(i) ? "'t'" : "'f'";
+                }
+                else
+                    osSQL += poFeature->GetFieldAsString(i);
+            }
+        }
+
+        for(i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++)
+        {
+            if(bMustComma)
+                osSQL += ", ";
+            else
+                bMustComma = TRUE;
+
+            osSQL += OGRAMIGOCLOUDEscapeIdentifier(poFeatureDefn->GetGeomFieldDefn(i)->GetNameRef());
+            osSQL += " = ";
+
+            OGRGeometry *poGeom = poFeature->GetGeomFieldRef(i);
+            if(poGeom == NULL)
+            {
+                osSQL += "NULL";
+            }
+            else
+            {
+                OGRAmigoCloudGeomFieldDefn *poGeomFieldDefn =
+                        (OGRAmigoCloudGeomFieldDefn *) poFeatureDefn->GetGeomFieldDefn(i);
+                int nSRID = poGeomFieldDefn->nSRID;
+                if(nSRID == 0)
+                    nSRID = 4326;
+                char *pszEWKB = OGRGeometryToHexEWKB(poGeom, nSRID, 2, 1);
+                osSQL += "'";
+                osSQL += pszEWKB;
+                osSQL += "'";
+                CPLFree(pszEWKB);
+            }
+        }
+
+
+        osSQL += CPLSPrintf(" WHERE %s = '%s'",
+                            OGRAMIGOCLOUDEscapeIdentifier(osFIDColName).c_str(),
+                            aFID.osAmigoId.c_str());
+
+
+        std::stringstream changeset;
+        changeset << "{\"query\": \"" << json_encode(osSQL) << "\"}";
+        std::stringstream url;
+        url << std::string(poDS->GetAPIURL()) << "/users/0/projects/" + std::string(poDS->GetProjetcId()) + "/sql";
+        json_object *poObj = poDS->RunPOST(url.str().c_str(), changeset.str().c_str());
+
+
+        if(poObj != NULL)
+        {
+            json_object *poTotalRows = json_object_object_get(poObj, "total_rows");
+            if(poTotalRows != NULL && json_object_get_type(poTotalRows) == json_type_int)
+            {
+                int nTotalRows = json_object_get_int(poTotalRows);
+                if(nTotalRows > 0)
+                {
+                    eRet = OGRERR_NONE;
+                }
+                else
+                    eRet = OGRERR_NON_EXISTING_FEATURE;
+            }
+            json_object_put(poObj);
+        }
+    }
+    return eRet;
+}
+
+/************************************************************************/
+/*                          DeleteFeature()                             */
+/************************************************************************/
+
+OGRErr OGRAmigoCloudTableLayer::DeleteFeature( GIntBig nFID )
+
+{
+    OGRErr eRet = OGRERR_FAILURE;
+
+    if( bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
+        return OGRERR_FAILURE;
+    FlushDeferredInsert();
+
+    GetLayerDefn();
+
+    if (!poDS->IsReadWrite())
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Operation not available in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
+    if( osFIDColName.size() == 0 )
+        return OGRERR_FAILURE;
+
+    std::map<GIntBig, OGRAmigoCloudFID>::iterator it = mFIDs.find(nFID);
+    if(it!=mFIDs.end())
+    {
+        OGRAmigoCloudFID &aFID = it->second;
+
+        CPLString osSQL;
+        osSQL.Printf("DELETE FROM %s WHERE %s = '%s'" ,
+                     OGRAMIGOCLOUDEscapeIdentifier(osTableName).c_str(),
+                     OGRAMIGOCLOUDEscapeIdentifier(osFIDColName).c_str(),
+                     aFID.osAmigoId.c_str());
+
+        std::stringstream changeset;
+        changeset << "{\"query\": \"" << json_encode(osSQL) << "\"}";
+        std::stringstream url;
+        url << std::string(poDS->GetAPIURL()) << "/users/0/projects/" + std::string(poDS->GetProjetcId()) + "/sql";
+        json_object *poObj = poDS->RunPOST(url.str().c_str(), changeset.str().c_str());
+        if(poObj != NULL)
+        {
+            json_object_put(poObj);
+            eRet = OGRERR_NONE;
+        }
+    }
+    return eRet;
+}
+
+/************************************************************************/
+/*                             GetSRS_SQL()                             */
+/************************************************************************/
+
+CPLString OGRAmigoCloudTableLayer::GetSRS_SQL(const char* pszGeomCol)
+{
+    CPLString osSQL;
+
+    osSQL.Printf("SELECT srid, srtext FROM spatial_ref_sys WHERE srid IN "
+                "(SELECT Find_SRID('%s', '%s', '%s'))",
+                OGRAMIGOCLOUDEscapeLiteral(poDS->GetCurrentSchema()).c_str(),
+                OGRAMIGOCLOUDEscapeLiteral(osTableName).c_str(),
+                OGRAMIGOCLOUDEscapeLiteral(pszGeomCol).c_str());
+
+    return osSQL;
+}
+
+/************************************************************************/
+/*                             BuildWhere()                             */
+/*                                                                      */
+/*      Build the WHERE statement appropriate to the current set of     */
+/*      criteria (spatial and attribute queries).                       */
+/************************************************************************/
+
+void OGRAmigoCloudTableLayer::BuildWhere()
+
+{
+    osWHERE = "";
+
+    if( m_poFilterGeom != NULL &&
+        m_iGeomFieldFilter >= 0 &&
+        m_iGeomFieldFilter < poFeatureDefn->GetGeomFieldCount() )
+    {
+        OGREnvelope  sEnvelope;
+
+        m_poFilterGeom->getEnvelope( &sEnvelope );
+
+        CPLString osGeomColumn(poFeatureDefn->GetGeomFieldDefn(m_iGeomFieldFilter)->GetNameRef());
+
+        char szBox3D_1[128];
+        char szBox3D_2[128];
+        char* pszComma;
+
+        CPLsnprintf(szBox3D_1, sizeof(szBox3D_1), "%.18g %.18g", sEnvelope.MinX, sEnvelope.MinY);
+        while((pszComma = strchr(szBox3D_1, ',')) != NULL)
+            *pszComma = '.';
+        CPLsnprintf(szBox3D_2, sizeof(szBox3D_2), "%.18g %.18g", sEnvelope.MaxX, sEnvelope.MaxY);
+        while((pszComma = strchr(szBox3D_2, ',')) != NULL)
+            *pszComma = '.';
+        osWHERE.Printf("(%s && 'BOX3D(%s, %s)'::box3d)",
+                       OGRAMIGOCLOUDEscapeIdentifier(osGeomColumn).c_str(),
+                       szBox3D_1, szBox3D_2 );
+    }
+
+    if( strlen(osQuery) > 0 )
+    {
+        if( osWHERE.size() > 0 )
+            osWHERE += " AND ";
+        osWHERE += osQuery;
+    }
+
+    if( osFIDColName.size() == 0 )
+    {
+        osBaseSQL = osSELECTWithoutWHERE;
+        if( osWHERE.size() > 0 )
+        {
+            osBaseSQL += " WHERE ";
+            osBaseSQL += osWHERE;
+        }
+    }
+}
+
+/************************************************************************/
+/*                              GetFeature()                            */
+/************************************************************************/
+
+OGRFeature* OGRAmigoCloudTableLayer::GetFeature( GIntBig nFeatureId )
+{
+
+    if( bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
+        return NULL;
+    FlushDeferredInsert();
+
+    GetLayerDefn();
+
+    if( osFIDColName.size() == 0 )
+        return OGRAmigoCloudLayer::GetFeature(nFeatureId);
+
+    CPLString osSQL = osSELECTWithoutWHERE;
+    osSQL += " WHERE ";
+    osSQL += OGRAMIGOCLOUDEscapeIdentifier(osFIDColName).c_str();
+    osSQL += " = ";
+    osSQL += CPLSPrintf(CPL_FRMT_GIB, nFeatureId);
+
+    json_object* poObj = poDS->RunSQL(osSQL);
+    json_object* poRowObj = OGRAMIGOCLOUDGetSingleRow(poObj);
+    if( poRowObj == NULL )
+    {
+        if( poObj != NULL )
+            json_object_put(poObj);
+        return OGRAmigoCloudLayer::GetFeature(nFeatureId);
+    }
+
+    OGRFeature* poFeature = BuildFeature(poRowObj);
+    json_object_put(poObj);
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                          GetFeatureCount()                           */
+/************************************************************************/
+
+GIntBig OGRAmigoCloudTableLayer::GetFeatureCount(int bForce)
+{
+
+    if( bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
+        return 0;
+    FlushDeferredInsert();
+
+    GetLayerDefn();
+
+    CPLString osSQL(CPLSPrintf("SELECT COUNT(*) FROM %s",
+                               OGRAMIGOCLOUDEscapeIdentifier(osTableName).c_str()));
+    if( osWHERE.size() > 0 )
+    {
+        osSQL += " WHERE ";
+        osSQL += osWHERE;
+    }
+
+    json_object* poObj = poDS->RunSQL(osSQL);
+    json_object* poRowObj = OGRAMIGOCLOUDGetSingleRow(poObj);
+    if( poRowObj == NULL )
+    {
+        if( poObj != NULL )
+            json_object_put(poObj);
+        return OGRAmigoCloudLayer::GetFeatureCount(bForce);
+    }
+
+    json_object* poCount = json_object_object_get(poRowObj, "count");
+    if( poCount == NULL || json_object_get_type(poCount) != json_type_int )
+    {
+        json_object_put(poObj);
+        return OGRAmigoCloudLayer::GetFeatureCount(bForce);
+    }
+
+    GIntBig nRet = (GIntBig)json_object_get_int64(poCount);
+
+    json_object_put(poObj);
+
+    return nRet;
+}
+
+/************************************************************************/
+/*                             GetExtent()                              */
+/*                                                                      */
+/*      For PostGIS use internal Extend(geometry) function              */
+/*      in other cases we use standard OGRLayer::GetExtent()            */
+/************************************************************************/
+
+OGRErr OGRAmigoCloudTableLayer::GetExtent( int iGeomField, OGREnvelope *psExtent, int bForce )
+{
+    CPLString   osSQL;
+
+    if( bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
+        return OGRERR_FAILURE;
+    FlushDeferredInsert();
+
+    if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() ||
+        GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetType() == wkbNone )
+    {
+        if( iGeomField != 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Invalid geometry field index : %d", iGeomField);
+        }
+        return OGRERR_FAILURE;
+    }
+
+    OGRGeomFieldDefn* poGeomFieldDefn =
+        poFeatureDefn->GetGeomFieldDefn(iGeomField);
+
+    /* Do not take the spatial filter into account */
+    osSQL.Printf( "SELECT ST_Extent(%s) FROM %s",
+                  OGRAMIGOCLOUDEscapeIdentifier(poGeomFieldDefn->GetNameRef()).c_str(),
+                  OGRAMIGOCLOUDEscapeIdentifier(osTableName).c_str());
+
+    json_object* poObj = poDS->RunSQL(osSQL);
+    json_object* poRowObj = OGRAMIGOCLOUDGetSingleRow(poObj);
+    if( poRowObj != NULL )
+    {
+        json_object* poExtent = json_object_object_get(poRowObj, "st_extent");
+        if( poExtent != NULL && json_object_get_type(poExtent) == json_type_string )
+        {
+            const char* pszBox = json_object_get_string(poExtent);
+            const char * ptr, *ptrEndParenthesis;
+            char szVals[64*6+6];
+
+            ptr = strchr(pszBox, '(');
+            if (ptr)
+                ptr ++;
+            if (ptr == NULL ||
+                (ptrEndParenthesis = strchr(ptr, ')')) == NULL ||
+                ptrEndParenthesis - ptr > (int)(sizeof(szVals) - 1))
+            {
+                CPLError( CE_Failure, CPLE_IllegalArg,
+                            "Bad extent representation: '%s'", pszBox);
+
+                json_object_put(poObj);
+                return OGRERR_FAILURE;
+            }
+
+            strncpy(szVals,ptr,ptrEndParenthesis - ptr);
+            szVals[ptrEndParenthesis - ptr] = '\0';
+
+            char ** papszTokens = CSLTokenizeString2(szVals," ,",CSLT_HONOURSTRINGS);
+            int nTokenCnt = 4;
+
+            if ( CSLCount(papszTokens) != nTokenCnt )
+            {
+                CPLError( CE_Failure, CPLE_IllegalArg,
+                            "Bad extent representation: '%s'", pszBox);
+                CSLDestroy(papszTokens);
+
+                json_object_put(poObj);
+                return OGRERR_FAILURE;
+            }
+
+            // Take X,Y coords
+            // For PostGIS ver >= 1.0.0 -> Tokens: X1 Y1 X2 Y2 (nTokenCnt = 4)
+            // For PostGIS ver < 1.0.0 -> Tokens: X1 Y1 Z1 X2 Y2 Z2 (nTokenCnt = 6)
+            // =>   X2 index calculated as nTokenCnt/2
+            //      Y2 index calculated as nTokenCnt/2+1
+
+            psExtent->MinX = CPLAtof( papszTokens[0] );
+            psExtent->MinY = CPLAtof( papszTokens[1] );
+            psExtent->MaxX = CPLAtof( papszTokens[nTokenCnt/2] );
+            psExtent->MaxY = CPLAtof( papszTokens[nTokenCnt/2+1] );
+
+            CSLDestroy(papszTokens);
+
+            json_object_put(poObj);
+            return OGRERR_NONE;
+        }
+    }
+
+    if( poObj != NULL )
+        json_object_put(poObj);
+
+    if( iGeomField == 0 )
+        return OGRLayer::GetExtent( psExtent, bForce );
+    else
+        return OGRLayer::GetExtent( iGeomField, psExtent, bForce );
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRAmigoCloudTableLayer::TestCapability( const char * pszCap )
+
+{
+    if( EQUAL(pszCap, OLCFastFeatureCount) )
+        return TRUE;
+    if( EQUAL(pszCap, OLCFastGetExtent) )
+        return TRUE;
+    if( EQUAL(pszCap, OLCRandomRead) )
+    {
+        GetLayerDefn();
+        return osFIDColName.size() != 0;
+    }
+
+    if(
+        EQUAL(pszCap,OLCSequentialWrite)
+     || EQUAL(pszCap,OLCRandomWrite)
+     || EQUAL(pszCap,OLCDeleteFeature)
+     || EQUAL(pszCap,ODsCCreateLayer)
+     || EQUAL(pszCap,ODsCDeleteLayer)
+       )
+    {
+        return poDS->IsReadWrite();
+    }
+
+    return OGRAmigoCloudLayer::TestCapability(pszCap);
+}
+
+/************************************************************************/
+/*                        SetDeferredCreation()                          */
+/************************************************************************/
+
+void OGRAmigoCloudTableLayer::SetDeferredCreation(OGRwkbGeometryType eGType,
+                                     OGRSpatialReference *poSRS,
+                                     int bGeomNullable)
+{
+    bDeferredCreation = TRUE;
+    nNextFID = 1;
+    CPLAssert(poFeatureDefn == NULL);
+    poFeatureDefn = new OGRFeatureDefn(osTableName);
+    poFeatureDefn->Reference();
+    poFeatureDefn->SetGeomType(wkbNone);
+    if( eGType == wkbPolygon )
+        eGType = wkbMultiPolygon;
+    else if( eGType == wkbPolygon25D )
+        eGType = wkbMultiPolygon25D;
+    if( eGType != wkbNone )
+    {
+        OGRAmigoCloudGeomFieldDefn *poFieldDefn =
+            new OGRAmigoCloudGeomFieldDefn("wkb_geometry", eGType);
+        poFieldDefn->SetNullable(bGeomNullable);
+        poFeatureDefn->AddGeomFieldDefn(poFieldDefn, FALSE);
+        if( poSRS != NULL )
+        {
+            poFieldDefn->nSRID = poDS->FetchSRSId( poSRS );
+            poFeatureDefn->GetGeomFieldDefn(
+                poFeatureDefn->GetGeomFieldCount() - 1)->SetSpatialRef(poSRS);
+        }
+    }
+
+    osBaseSQL.Printf("SELECT * FROM %s",
+                     OGRAMIGOCLOUDEscapeIdentifier(osTableName).c_str());
+}
+
+CPLString OGRAmigoCloudTableLayer::GetAmigoCloudType(OGRFieldDefn& oField)
+{
+    char                szFieldType[256];
+
+/* -------------------------------------------------------------------- */
+/*      AmigoCloud supported types.                                   */
+/* -------------------------------------------------------------------- */
+    if( oField.GetType() == OFTInteger )
+    {
+            strcpy( szFieldType, "integer" );
+    }
+    else if( oField.GetType() == OFTInteger64 )
+    {
+        strcpy( szFieldType, "bigint" );
+    }
+    else if( oField.GetType() == OFTReal )
+    {
+       strcpy( szFieldType, "float" );
+    }
+    else if( oField.GetType() == OFTString )
+    {
+        strcpy( szFieldType, "string");
+    }
+    else if( oField.GetType() == OFTDate )
+    {
+        strcpy( szFieldType, "date" );
+    }
+    else if( oField.GetType() == OFTTime )
+    {
+        strcpy( szFieldType, "time" );
+    }
+    else if( oField.GetType() == OFTDateTime )
+    {
+        strcpy( szFieldType, "datetime" );
+    } else
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Can't create field %s with type %s on PostgreSQL layers.",
+                  oField.GetNameRef(),
+                  OGRFieldDefn::GetFieldTypeName(oField.GetType()) );
+        strcpy( szFieldType, "");
+    }
+
+    return szFieldType;
+}
+
+bool OGRAmigoCloudTableLayer::IsDatasetExists()
+{
+    std::stringstream url;
+
+    url << std::string(poDS->GetAPIURL()) << "/users/0/projects/" + std::string(poDS->GetProjetcId()) + "/datasets/"+ osDatasetId;
+
+    json_object* result = poDS->RunGET(url.str().c_str());
+    if( result == NULL )
+        return false;
+
+    if( result != NULL )
+    {
+        int type = json_object_get_type(result);
+        if(type == json_type_object)
+        {
+            json_object *poId = json_object_object_get(result, "id");
+            if(poId != NULL)
+            {
+                json_object_put(result);
+                return true;
+            }
+        }
+        json_object_put(result);
+    }
+
+    // Sleep 3 sec
+	CPLSleep(3);
+
+    return false;
+}
+
+/************************************************************************/
+/*                      RunDeferredCreationIfNecessary()                 */
+/************************************************************************/
+
+OGRErr OGRAmigoCloudTableLayer::RunDeferredCreationIfNecessary()
+{
+    if( !bDeferredCreation )
+        return OGRERR_NONE;
+    bDeferredCreation = FALSE;
+
+    std::stringstream json;
+
+    json << "{ \"name\":\"" << osDatasetId << "\",";
+
+    json << "\"schema\": \"[";
+
+    int counter=0;
+
+    OGRwkbGeometryType eGType = GetGeomType();
+    if( eGType != wkbNone )
+    {
+        CPLString osGeomType = OGRToOGCGeomType(eGType);
+        if( wkbHasZ(eGType) )
+            osGeomType += "Z";
+
+        OGRAmigoCloudGeomFieldDefn *poFieldDefn =
+                (OGRAmigoCloudGeomFieldDefn *)poFeatureDefn->GetGeomFieldDefn(0);
+
+        json << "{\\\"name\\\":\\\"" << poFieldDefn->GetNameRef() << "\\\",";
+        json << "\\\"type\\\":\\\"geometry\\\",";
+        json << "\\\"geometry_type\\\":\\\"" << osGeomType << "\\\",";
+
+        if( !poFieldDefn->IsNullable() )
+            json << "\\\"nullable\\\":false,";
+        else
+            json << "\\\"nullable\\\":true,";
+
+        json << "\\\"visible\\\": true}";
+
+        counter++;
+    }
+
+    for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
+    {
+        OGRFieldDefn* poFieldDefn = poFeatureDefn->GetFieldDefn(i);
+        if( strcmp(poFieldDefn->GetNameRef(), osFIDColName) != 0 )
+        {
+            if(counter>0)
+                json << ",";
+
+            json << "{\\\"name\\\":\\\"" << poFieldDefn->GetNameRef() << "\\\",";
+            json << "\\\"type\\\":\\\"" << GetAmigoCloudType(*poFieldDefn) << "\\\",";
+            if( !poFieldDefn->IsNullable() )
+                json << "\\\"nullable\\\":false,";
+            else
+                json << "\\\"nullable\\\":true,";
+
+            if( poFieldDefn->GetDefault() != NULL && !poFieldDefn->IsDefaultDriverSpecific() )
+            {
+                json << "\\\"default\\\":\\\"" << poFieldDefn->GetDefault() << "\\\",";
+            }
+            json << "\\\"visible\\\": true}";
+            counter++;
+        }
+    }
+
+    json << " ] \" }";
+
+    std::stringstream url;
+    url << std::string(poDS->GetAPIURL()) << "/users/0/projects/" + std::string(poDS->GetProjetcId()) + "/datasets/create";
+
+    json_object* result = poDS->RunPOST(url.str().c_str(), json.str().c_str());
+    if( result != NULL )
+    {
+        if(json_object_get_type(result) == json_type_object)
+        {
+            json_object *poId = json_object_object_get(result, "id");
+            if(poId!=NULL)
+            {
+                osTableName = CPLString("dataset_") + json_object_to_json_string(poId);
+                osDatasetId = json_object_to_json_string(poId);
+                int retry=10;
+                while(!IsDatasetExists() && retry >= 0)
+                {
+                    retry--;
+                }
+                json_object_put(result);
+                return OGRERR_NONE;
+            }
+        }
+    }
+    return OGRERR_FAILURE;
+}
diff --git a/ogr/ogrsf_frmts/amigocloud/pkg/Makefile.in b/ogr/ogrsf_frmts/amigocloud/pkg/Makefile.in
new file mode 100644
index 0000000..8a06eb6
--- /dev/null
+++ b/ogr/ogrsf_frmts/amigocloud/pkg/Makefile.in
@@ -0,0 +1,40 @@
+include ../../../GDALmake.opt
+
+CC	=	@CC@
+CXX	=	@CXX@
+LD	=	@CXX@
+
+CPPFLAGS = -DUSE_CPL $(JSON_INCLUDE) -I.. -I../.. -I../pgdump \
+	  @GDAL_INC@ @PQ_INCLUDE@ @CPPFLAGS@
+CXXFLAGS = @CXX_WFLAGS@ @CXX_PIC@
+CFLAGS   = @CFLAGS@
+LDFLAGS  = @LDFLAGS@
+
+RANLIB		=	@RANLIB@
+SO_EXT		=	@SO_EXT@
+LD_SHARED	=	@LD_SHARED@
+
+LIBS	=	@LIBS@ -ljson-c
+
+AUTOLOAD_DIR	=	@AUTOLOAD_DIR@
+
+GLIBNAME =	ogr_amigocloud.so
+
+default:	$(GLIBNAME)
+
+install:	default
+	install -d $(AUTOLOAD_DIR)
+	cp $(GLIBNAME) $(AUTOLOAD_DIR)
+
+clean:
+	rm -f $(GLIBNAME) *.o
+
+distclean: clean
+	rm -fr Makefile config.status config.log autom*.cache
+
+$(GLIBNAME):	ogramigoclouddatasource.o ogramigocloudlayer.o ogramigocloudtablelayer.o ogramigoclouddriver.o ogramigocloudresultlayer.o
+	$(LD_SHARED) $(LDFLAGS) ogramigoclouddatasource.o ogramigocloudlayer.o ogramigocloudtablelayer.o ogramigoclouddriver.o ogramigocloudresultlayer.o $(LIBS) -o $(GLIBNAME)
+
+%.o:	%.cpp
+	$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
+
diff --git a/ogr/ogrsf_frmts/amigocloud/pkg/configure b/ogr/ogrsf_frmts/amigocloud/pkg/configure
new file mode 100644
index 0000000..ef2c9e5
--- /dev/null
+++ b/ogr/ogrsf_frmts/amigocloud/pkg/configure
@@ -0,0 +1,4351 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+  # into an infinite loop, continuously re-executing ourselves.
+  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+    _as_can_reexec=no; export _as_can_reexec;
+    # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+  fi
+  # We don't want this to propagate to other subprocesses.
+          { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+"
+  as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+  exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1"
+  if (eval "$as_required") 2>/dev/null; then :
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  as_found=:
+  case $as_dir in #(
+	 /*)
+	   for as_base in sh bash ksh sh5; do
+	     # Try only shells that exist, to save several forks.
+	     as_shell=$as_dir/$as_base
+	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+		    { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  CONFIG_SHELL=$as_shell as_have_required=yes
+		   if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  break 2
+fi
+fi
+	   done;;
+       esac
+  as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+	      { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+  CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+      if test "x$CONFIG_SHELL" != x; then :
+  export CONFIG_SHELL
+             # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+    if test x$as_have_required = xno; then :
+  $as_echo "$0: This script requires a shell more modern than all"
+  $as_echo "$0: the shells that I found on your system."
+  if test x${ZSH_VERSION+set} = xset ; then
+    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+  else
+    $as_echo "$0: Please tell bug-autoconf at gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+  fi
+  exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+  as_lineno_1=$LINENO as_lineno_1a=$LINENO
+  as_lineno_2=$LINENO as_lineno_2a=$LINENO
+  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+  # already done that, so ensure we don't try to do so again and fall
+  # in an infinite loop.  This has already happened in practice.
+  _as_can_reexec=no; export _as_can_reexec
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+PACKAGE_URL=
+
+ac_unique_file="Makefile.in"
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+PQ_INCLUDE
+AUTOLOAD_DIR
+GDAL_INC
+GDAL_CONFIG
+C_WFLAGS
+CXX_WFLAGS
+SO_EXT
+LD_SHARED
+C_PIC
+CXX_PIC
+RANLIB
+ac_ct_CXX
+CXXFLAGS
+CXX
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+with_ld_shared
+with_gdal
+with_autoload
+with_postgres_includes
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CXX
+CXXFLAGS
+CCC'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *=)   ac_optarg= ;;
+  *)    ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    case $ac_envvar in #(
+      '' | [0-9]* | *[!_$as_cr_alnum]* )
+      as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+    esac
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
+		datadir sysconfdir sharedstatedir localstatedir includedir \
+		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+		libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_myself" : 'X\(//\)[^/]' \| \
+	 X"$as_myself" : 'X\(//\)$' \| \
+	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+	cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+	pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking ...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root [DATAROOTDIR/doc/PACKAGE]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+  cat <<\_ACEOF
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-ld-shared=cmd    provide shared library link
+  --with-gdal=PATH        GDAL (PATH is path to gdal-config)
+  --with-autoload=DIR     Directory for autoload drivers
+  --with-postgres-includes=DIR     use PostgreSQL includes in DIR
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  CXX         C++ compiler command
+  CXXFLAGS    C++ compiler flags
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_cxx_try_compile LINENO
+# ----------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 test -x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    $as_echo "PATH: $as_dir"
+  done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+    2)
+      as_fn_append ac_configure_args1 " '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      as_fn_append ac_configure_args " '$ac_arg'"
+      ;;
+    esac
+  done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+	"s/'\''/'\''\\\\'\'''\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      $as_echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=\$$ac_var
+	case $ac_val in
+	*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+	esac
+	$as_echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+  # We do not want a PATH search for config.site.
+  case $CONFIG_SITE in #((
+    -*)  ac_site_file1=./$CONFIG_SITE;;
+    */*) ac_site_file1=$CONFIG_SITE;;
+    *)   ac_site_file1=./$CONFIG_SITE;;
+  esac
+elif test "x$prefix" != xNONE; then
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
+else
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+  test "x$ac_site_file" = xNONE && continue
+  if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file" \
+      || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+  fi
+done
+
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	# differences in whitespace do not lead to failure.
+	ac_old_val_w=`echo x $ac_old_val`
+	ac_new_val_w=`echo x $ac_new_val`
+	if test "$ac_old_val_w" != "$ac_new_val_w"; then
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	  ac_cache_corrupted=:
+	else
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+	  eval $ac_var=\$ac_old_val
+	fi
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+	;;
+    [ab].out )
+	# We found the default executable, but exeext='' is most
+	# certainly right.
+	break;;
+    *.* )
+	if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+	then :; else
+	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	fi
+	# We set ac_cv_exeext here because the later test for it is not
+	# safe: cross compilers may not add the suffix if given an `-o'
+	# argument, so we may need to know it at that point already.
+	# Even if this section looks crufty: it has the advantage of
+	# actually working.
+	break;;
+    * )
+	break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+if test -z "$ac_file"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  break;;
+    * ) break;;
+  esac
+done
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+  { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+  if { ac_try='./conftest$ac_cv_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+    fi
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+else
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+  if test -n "$CCC"; then
+    CXX=$CCC
+  else
+    if test -n "$ac_tool_prefix"; then
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CXX"; then
+  ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
+$as_echo "$CXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CXX" && break
+  done
+fi
+if test -z "$CXX"; then
+  ac_ct_CXX=$CXX
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CXX"; then
+  ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CXX="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
+$as_echo "$ac_ct_CXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CXX" && break
+done
+
+  if test "x$ac_ct_CXX" = x; then
+    CXX="g++"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CXX=$ac_ct_CXX
+  fi
+fi
+
+  fi
+fi
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
+$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
+if ${ac_cv_cxx_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
+$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GXX=yes
+else
+  GXX=
+fi
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
+$as_echo_n "checking whether $CXX accepts -g... " >&6; }
+if ${ac_cv_prog_cxx_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+   ac_cxx_werror_flag=yes
+   ac_cv_prog_cxx_g=no
+   CXXFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_prog_cxx_g=yes
+else
+  CXXFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+else
+  ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+	 CXXFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_prog_cxx_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
+$as_echo "$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+  CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+  if test "$GXX" = yes; then
+    CXXFLAGS="-g -O2"
+  else
+    CXXFLAGS="-g"
+  fi
+else
+  if test "$GXX" = yes; then
+    CXXFLAGS="-O2"
+  else
+    CXXFLAGS=
+  fi
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_RANLIB+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_RANLIB" = x; then
+    RANLIB=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    RANLIB=$ac_ct_RANLIB
+  fi
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+
+	echo 'void f(){}' > conftest.c
+	if test -z "`${CC-cc} -fPIC -c conftest.c 2>&1`"; then
+	  C_PIC=-fPIC
+	else
+	  C_PIC=
+	fi
+	if test -z "`${CXX-g++} -fPIC -c conftest.c 2>&1`"; then
+	  CXX_PIC=-fPIC
+	else
+	  CXX_PIC=
+	fi
+	rm -f conftest*
+
+	CXX_PIC=$CXX_PIC
+
+	C_PIC=$C_PIC
+
+
+
+  echo 'void g(); int main(){ g(); return 0; }' > conftest1.c
+
+  echo '#include <stdio.h>' > conftest2.c
+  echo 'void g(); void g(){printf("");}' >> conftest2.c
+  ${CC} ${C_PIC} -c conftest2.c
+
+  SO_EXT="so"
+  export SO_EXT
+  LD_SHARED="/bin/true"
+  if test ! -z "`uname -a | grep IRIX`" ; then
+    IRIX_ALL=-all
+  else
+    IRIX_ALL=
+  fi
+
+
+# Check whether --with-ld-shared was given.
+if test "${with_ld_shared+set}" = set; then :
+  withval=$with_ld_shared;
+fi
+
+
+  if test "$with_ld_shared" != "" ; then
+    if test "$with_ld_shared" = "no" ; then
+      echo "user disabled shared library support."
+    else
+      echo "using user supplied .so link command ... $with_ld_shared"
+    fi
+    LD_SHARED="$with_ld_shared"
+  fi
+
+
+  if test ! -z "`uname -a | grep CYGWIN`" \
+        -a "$LD_SHARED" = "/bin/true" \
+	-a -z "`gcc -shared conftest2.o -o libconftest.dll`" ; then
+    if test -z "`${CC} conftest1.c -L./ -lconftest -o conftest1 2>&1`"; then
+      LD_LIBRARY_PATH_OLD="$LD_LIBRARY_PATH"
+      if test -z "$LD_LIBRARY_PATH" ; then
+        LD_LIBRARY_PATH="`pwd`"
+      else
+        LD_LIBRARY_PATH="`pwd`:$LD_LIBRARY_PATH"
+      fi
+      export LD_LIBRARY_PATH
+      if test -z "`./conftest1 2>&1`" ; then
+        echo "checking for Cygwin gcc -shared ... yes"
+        LD_SHARED="c++ -shared"
+        SO_EXT="dll"
+      fi
+      LD_LIBRARY_PATH="$LD_LIBRARY_PATH_OLD"
+    fi
+  fi
+
+
+  if test ! -z "`uname | grep Darwin`" \
+          -a "$LD_SHARED" = "/bin/true" \
+          -a -z "`${CXX} -dynamiclib conftest2.o -o libconftest.so 2>&1`" ; then
+    ${CC} -c conftest1.c
+    if test -z "`${CXX} conftest1.o libconftest.so -o conftest1 2>&1`"; then
+      DYLD_LIBRARY_PATH_OLD="$DYLD_LIBRARY_PATH"
+      if test -z "$DYLD_LIBRARY_PATH" ; then
+        DYLD_LIBRARY_PATH="`pwd`"
+      else
+        DYLD_LIBRARY_PATH="`pwd`:$DYLD_LIBRARY_PATH"
+      fi
+      export DYLD_LIBRARY_PATH
+      if test -z "`./conftest1 2>&1`" ; then
+        echo "checking for ${CXX} -dynamiclib ... yes"
+        LD_SHARED="${CXX} -dynamiclib"
+	SO_EXT=dylib
+      fi
+      DYLD_LIBRARY_PATH="$DYLD_LIBRARY_PATH_OLD"
+    fi
+    rm -f conftest1.o
+  fi
+
+  if test "$LD_SHARED" = "/bin/true" \
+	-a -z "`${CXX} -shared $IRIX_ALL conftest2.o -o libconftest.so 2>&1|grep -v WARNING`" ; then
+    if test -z "`${CC} conftest1.c libconftest.so -o conftest1 2>&1`"; then
+      LD_LIBRARY_PATH_OLD="$LD_LIBRARY_PATH"
+      if test -z "$LD_LIBRARY_PATH" ; then
+        LD_LIBRARY_PATH="`pwd`"
+      else
+        LD_LIBRARY_PATH="`pwd`:$LD_LIBRARY_PATH"
+      fi
+      export LD_LIBRARY_PATH
+      if test -z "`./conftest1 2>&1`" ; then
+        echo "checking for ${CXX} -shared ... yes"
+        LD_SHARED="${CXX} -shared $IRIX_ALL"
+      else
+        echo "checking for ${CXX} -shared ... no(3)"
+      fi
+      LD_LIBRARY_PATH="$LD_LIBRARY_PATH_OLD"
+    else
+      echo "checking for ${CXX} -shared ... no(2)"
+    fi
+  else
+    if test "$LD_SHARED" = "/bin/true" ; then
+      echo "checking for ${CXX} -shared ... no(1)"
+    fi
+  fi
+
+  if test "$LD_SHARED" = "/bin/true" \
+          -a -z "`ld -shared conftest2.o -o libconftest.so 2>&1`" ; then
+    if test -z "`${CC} conftest1.c libconftest.so -o conftest1 2>&1`"; then
+      LD_LIBRARY_PATH_OLD="$LD_LIBRARY_PATH"
+      if test -z "$LD_LIBRARY_PATH" ; then
+        LD_LIBRARY_PATH="`pwd`"
+      else
+        LD_LIBRARY_PATH="`pwd`:$LD_LIBRARY_PATH"
+      fi
+      export LD_LIBRARY_PATH
+      if test -z "`./conftest1 2>&1`" ; then
+        echo "checking for ld -shared ... yes"
+        LD_SHARED="ld -shared"
+      fi
+      LD_LIBRARY_PATH="$LD_LIBRARY_PATH_OLD"
+    fi
+  fi
+
+  if test "$LD_SHARED" = "/bin/true" ; then
+    echo "checking for ld -shared ... no"
+    if test ! -x /bin/true ; then
+      LD_SHARED=/usr/bin/true
+    fi
+  fi
+  if test "$LD_SHARED" = "no" ; then
+    if test -x /bin/true ; then
+      LD_SHARED=/bin/true
+    else
+      LD_SHARED=/usr/bin/true
+    fi
+  fi
+
+  rm -f conftest* libconftest*
+
+  LD_SHARED=$LD_SHARED
+
+  SO_EXT=$SO_EXT
+
+
+
+	# Remove -g from compile flags, we will add via CFG variable if
+	# we need it.
+	CXXFLAGS=`echo "$CXXFLAGS " | sed "s/-g //"`
+	CFLAGS=`echo "$CFLAGS " | sed "s/-g //"`
+
+	# check for GNU compiler, and use -Wall
+	if test "$GCC" = "yes"; then
+		C_WFLAGS="-Wall"
+
+$as_echo "#define USE_GNUCC 1" >>confdefs.h
+
+	fi
+	if test "$GXX" = "yes"; then
+		CXX_WFLAGS="-Wall"
+
+$as_echo "#define USE_GNUCC 1" >>confdefs.h
+
+	fi
+	CXX_WFLAGS=$CXX_WFLAGS
+
+	C_WFLAGS=$C_WFLAGS
+
+
+
+
+
+# Check whether --with-gdal was given.
+if test "${with_gdal+set}" = set; then :
+  withval=$with_gdal;
+fi
+
+
+if test "$with_gdal" = "yes" -o "$with_gdal" = "" ; then
+
+  if test "`basename xx/$with_gdal`" = "gdal-config" ; then
+    GDAL_CONFIG="$with_gdal"
+  fi
+
+  if test -z "$GDAL_CONFIG" ; then
+    # Extract the first word of "gdal-config", so it can be a program name with args.
+set dummy gdal-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_GDAL_CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $GDAL_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_GDAL_CONFIG="$GDAL_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_GDAL_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_GDAL_CONFIG" && ac_cv_path_GDAL_CONFIG="no"
+  ;;
+esac
+fi
+GDAL_CONFIG=$ac_cv_path_GDAL_CONFIG
+if test -n "$GDAL_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GDAL_CONFIG" >&5
+$as_echo "$GDAL_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+
+  if test "$GDAL_CONFIG" = "no" ; then
+    as_fn_error $? "couldn't find gdal-config" "$LINENO" 5
+  fi
+
+elif test -n "$with_gdal" -a "$with_gdal" != "no" ; then
+
+  GDAL_CONFIG=$with_gdal
+
+  if test -f "$GDAL_CONFIG" -a -x "$GDAL_CONFIG" ; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: user supplied gdal-config ($GDAL_CONFIG)" >&5
+$as_echo "user supplied gdal-config ($GDAL_CONFIG)" >&6; }
+  else
+    as_fn_error $? "'$GDAL_CONFIG' is not an executable.  Make sure you use --with-gdal=/path/to/gdal-config" "$LINENO" 5
+  fi
+
+else
+
+  as_fn_error $? "gdal required to build GDAL GRASS driver" "$LINENO" 5
+
+fi
+
+LIBS="`$GDAL_CONFIG --libs` $LIBS"
+GDAL_INC=`$GDAL_CONFIG --cflags`
+
+GDAL_INC=$GDAL_INC
+
+
+
+# Check whether --with-autoload was given.
+if test "${with_autoload+set}" = set; then :
+  withval=$with_autoload;
+fi
+
+
+if test "$with_autoload" != "" ; then
+  AUTOLOAD_DIR=$with_autoload
+else
+  if $GDAL_CONFIG --autoload > /dev/null 2>&1 ; then
+    AUTOLOAD_DIR=`$GDAL_CONFIG --autoload`
+  else
+    AUTOLOAD_DIR=`$GDAL_CONFIG --prefix`/lib/gdalplugins
+  fi
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: using $AUTOLOAD_DIR as GDAL shared library autoload directory" >&5
+$as_echo "using $AUTOLOAD_DIR as GDAL shared library autoload directory" >&6; }
+AUTOLOAD_DIR=$AUTOLOAD_DIR
+
+# Check whether --with-postgres_includes was given.
+if test "${with_postgres_includes+set}" = set; then :
+  withval=$with_postgres_includes; postgres_includes="$withval"
+else
+  postgres_includes=no
+fi
+
+
+PQ_INCLUDE=
+if test "x$postgres_includes" != "xno"; then
+# With PostgreSQL includes directory
+PQ_INCLUDE="-I$postgres_includes"
+fi
+
+
+
+
+rm -f conftest*
+
+ac_config_files="$ac_config_files Makefile"
+
+
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then branch to the quote section.  Otherwise,
+# look for a macro that doesn't take arguments.
+ac_script='
+:mline
+/\\$/{
+ N
+ s,\\\n,,
+ b mline
+}
+t clear
+:clear
+s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*([^)]*)\)[	 ]*\(.*\)/-D\1=\2/g
+t quote
+s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\)/-D\1=\2/g
+t quote
+b any
+:quote
+s/[	 `~#$^&*(){}\\|;'\''"<>?]/\\&/g
+s/\[/\\&/g
+s/\]/\\&/g
+s/\$/$$/g
+H
+:any
+${
+	g
+	s/^\n//
+	s/\n/ /g
+	p
+}
+'
+DEFS=`sed -n "$ac_script" confdefs.h`
+
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration.  Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+      --config     print configuration, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.69,
+  with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=?*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  --*=)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --config | --confi | --conf | --con | --co | --c )
+    $as_echo "$ac_cs_config"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    '') as_fn_error $? "missing file argument" ;;
+    esac
+    as_fn_append CONFIG_FILES " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h |  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+  *) as_fn_append ac_config_targets " $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+
+  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp= ac_tmp=
+  trap 'exit_status=$?
+  : "${ac_tmp:=$tmp}"
+  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+  trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+  eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  . ./conf$$subs.sh ||
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+  N
+  s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = ""
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+  || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=[	 ]*/{
+h
+s///
+s/^/:/
+s/[	 ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[	 ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[	 ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+
+eval set X "  :F $CONFIG_FILES      "
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$ac_tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
+	 # because $ac_f cannot contain `:'.
+	 test -f "$ac_f" ||
+	   case $ac_f in
+	   [\\/$]*) false;;
+	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+	   esac ||
+	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      as_fn_append ac_file_inputs " '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+	`' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$ac_tmp/stdin" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  as_dir="$ac_dir"; as_fn_mkdir_p
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+  s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
+      "$ac_tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&2;}
+
+  rm -f "$ac_tmp/stdin"
+  case $ac_file in
+  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+  esac \
+  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+
+
+
+  esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
+
+
+
diff --git a/ogr/ogrsf_frmts/amigocloud/pkg/configure.in b/ogr/ogrsf_frmts/amigocloud/pkg/configure.in
new file mode 100644
index 0000000..7afe6f4
--- /dev/null
+++ b/ogr/ogrsf_frmts/amigocloud/pkg/configure.in
@@ -0,0 +1,115 @@
+dnl ***************************************************************************
+dnl $Id$
+dnl
+dnl Project:  GDAL AmigoCloud Plugin
+dnl Purpose:  Configure source file.
+dnl Author:   Victor Chernetsky victor at amigocloud.com
+dnl
+dnl ***************************************************************************
+dnl Copyright (c) 2015, Victor Chernetsky
+dnl
+dnl Permission is hereby granted, free of charge, to any person obtaining a
+dnl copy of this software and associated documentation files (the "Software"),
+dnl to deal in the Software without restriction, including without limitation
+dnl the rights to use, copy, modify, merge, publish, distribute, sublicense,
+dnl and/or sell copies of the Software, and to permit persons to whom the
+dnl Software is furnished to do so, subject to the following conditions:
+dnl
+dnl The above copyright notice and this permission notice shall be included
+dnl in all copies or substantial portions of the Software.
+dnl
+dnl THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+dnl OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+dnl FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+dnl THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+dnl LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+dnl FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+dnl DEALINGS IN THE SOFTWARE.
+dnl ***************************************************************************
+
+dnl Disable configure caching ... it causes lots of hassles.
+define([AC_CACHE_LOAD], )
+define([AC_CACHE_SAVE], )
+
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(Makefile.in)
+
+dnl We require autoconf 2.52+ for libtool support on cygwin/mingw hosts
+AC_PREREQ(2.52)
+
+dnl Checks for programs.
+AC_PROG_CC
+AC_PROG_CXX
+
+AC_PROG_RANLIB
+AC_COMPILER_PIC
+AC_LD_SHARED
+AC_COMPILER_WFLAGS
+
+dnl ---------------------------------------------------------------------------
+dnl Find GDAL
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(gdal,
+[  --with-gdal[=PATH]        GDAL (PATH is path to gdal-config)],,)
+
+if test "$with_gdal" = "yes" -o "$with_gdal" = "" ; then
+
+  if test "`basename xx/$with_gdal`" = "gdal-config" ; then
+    GDAL_CONFIG="$with_gdal"
+  fi
+
+  if test -z "$GDAL_CONFIG" ; then
+    AC_PATH_PROG(GDAL_CONFIG, gdal-config, no)
+  fi
+
+  if test "$GDAL_CONFIG" = "no" ; then
+    AC_MSG_ERROR([couldn't find gdal-config])
+  fi
+
+elif test -n "$with_gdal" -a "$with_gdal" != "no" ; then
+
+  GDAL_CONFIG=$with_gdal
+
+  if test -f "$GDAL_CONFIG" -a -x "$GDAL_CONFIG" ; then
+    AC_MSG_RESULT([user supplied gdal-config ($GDAL_CONFIG)])
+  else
+    AC_MSG_ERROR(['$GDAL_CONFIG' is not an executable.  Make sure you use --with-gdal=/path/to/gdal-config])
+  fi
+
+else
+
+  AC_MSG_ERROR([gdal required to build GDAL GRASS driver])
+
+fi
+
+LIBS="`$GDAL_CONFIG --libs` $LIBS"
+GDAL_INC=`$GDAL_CONFIG --cflags`
+
+AC_SUBST(GDAL_INC,    $GDAL_INC)
+
+dnl ---------------------------------------------------------------------------
+dnl Where to put driver?
+dnl ---------------------------------------------------------------------------
+AC_ARG_WITH(autoload,[  --with-autoload[=DIR]     Directory for autoload drivers],,)
+
+if test "$with_autoload" != "" ; then
+  AUTOLOAD_DIR=$with_autoload
+else
+  if $GDAL_CONFIG --autoload > /dev/null 2>&1 ; then
+    AUTOLOAD_DIR=`$GDAL_CONFIG --autoload`
+  else
+    AUTOLOAD_DIR=`$GDAL_CONFIG --prefix`/lib/gdalplugins
+  fi
+fi
+
+AC_MSG_RESULT(using $AUTOLOAD_DIR as GDAL shared library autoload directory)
+AC_SUBST(AUTOLOAD_DIR,$AUTOLOAD_DIR)
+
+
+rm -f conftest*
+
+AC_OUTPUT(Makefile)
+
+
+
diff --git a/ogr/ogrsf_frmts/arcgen/ogr_arcgen.h b/ogr/ogrsf_frmts/arcgen/ogr_arcgen.h
index 263d6b7..535dd09 100644
--- a/ogr/ogrsf_frmts/arcgen/ogr_arcgen.h
+++ b/ogr/ogrsf_frmts/arcgen/ogr_arcgen.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_arcgen.h 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogr_arcgen.h 31777 2015-11-26 14:14:41Z rouault $
  *
  * Project:  Arc/Info Generate Translator
  * Purpose:  Definition of classes for OGR .arcgen driver.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_ARCGEN_H_INCLUDED
-#define _OGR_ARCGEN_H_INCLUDED
+#ifndef OGR_ARCGEN_H_INCLUDED
+#define OGR_ARCGEN_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 
@@ -86,4 +86,4 @@ class OGRARCGENDataSource : public OGRDataSource
     virtual int                 TestCapability( const char * );
 };
 
-#endif /* ndef _OGR_ARCGEN_H_INCLUDED */
+#endif /* ndef OGR_ARCGEN_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/arcgen/ograrcgendatasource.cpp b/ogr/ogrsf_frmts/arcgen/ograrcgendatasource.cpp
index eb7543b..cbb010d 100644
--- a/ogr/ogrsf_frmts/arcgen/ograrcgendatasource.cpp
+++ b/ogr/ogrsf_frmts/arcgen/ograrcgendatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ograrcgendatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ograrcgendatasource.cpp 32119 2015-12-11 05:47:58Z goatbar $
  *
  * Project:  Arc/Info Generate Translator
  * Purpose:  Implements OGRARCGENDataSource class
@@ -31,20 +31,17 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ograrcgendatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ograrcgendatasource.cpp 32119 2015-12-11 05:47:58Z goatbar $");
 
 /************************************************************************/
 /*                          OGRARCGENDataSource()                          */
 /************************************************************************/
 
-OGRARCGENDataSource::OGRARCGENDataSource()
-
-{
-    papoLayers = NULL;
-    nLayers = 0;
-
-    pszName = NULL;
-}
+OGRARCGENDataSource::OGRARCGENDataSource() :
+    pszName(NULL),
+    papoLayers(NULL),
+    nLayers(0)
+{}
 
 /************************************************************************/
 /*                         ~OGRARCGENDataSource()                          */
@@ -64,7 +61,7 @@ OGRARCGENDataSource::~OGRARCGENDataSource()
 /*                           TestCapability()                           */
 /************************************************************************/
 
-int OGRARCGENDataSource::TestCapability( CPL_UNUSED const char * pszCap )
+int OGRARCGENDataSource::TestCapability( const char * /* pszCap */ )
 {
     return FALSE;
 }
@@ -78,8 +75,8 @@ OGRLayer *OGRARCGENDataSource::GetLayer( int iLayer )
 {
     if( iLayer < 0 || iLayer >= nLayers )
         return NULL;
-    else
-        return papoLayers[iLayer];
+
+    return papoLayers[iLayer];
 }
 
 /************************************************************************/
@@ -91,7 +88,7 @@ int OGRARCGENDataSource::Open( const char * pszFilename )
 {
     pszName = CPLStrdup( pszFilename );
 
-// -------------------------------------------------------------------- 
+// --------------------------------------------------------------------
 //      Does this appear to be a Arc/Info generate file?
 // --------------------------------------------------------------------
 
@@ -116,7 +113,6 @@ int OGRARCGENDataSource::Open( const char * pszFilename )
 
     VSIFSeekL( fp, 0, SEEK_SET );
 
-    OGRwkbGeometryType eType;
     const char* szPtr = szBuffer;
     const char* szEnd = strstr(szPtr, "END");
     if (szEnd == NULL) szEnd = strstr(szPtr, "end");
@@ -128,6 +124,8 @@ int OGRARCGENDataSource::Open( const char * pszFilename )
     szPtr = szEnd + 3;
     szEnd = strstr(szPtr, "END");
     if (szEnd == NULL) szEnd = strstr(szPtr, "end");
+
+    OGRwkbGeometryType eType;
     if (szEnd == NULL)
     {
         const char* pszLine = CPLReadLine2L(fp,256,NULL);
@@ -210,7 +208,7 @@ int OGRARCGENDataSource::Open( const char * pszFilename )
     VSIFSeekL( fp, 0, SEEK_SET );
 
     nLayers = 1;
-    papoLayers = (OGRLayer**) CPLMalloc(sizeof(OGRLayer*));
+    papoLayers = static_cast<OGRLayer**>( CPLMalloc( sizeof(OGRLayer*) ) );
     papoLayers[0] = new OGRARCGENLayer(pszName, fp, eType);
 
     return TRUE;
diff --git a/ogr/ogrsf_frmts/arcgen/ograrcgendriver.cpp b/ogr/ogrsf_frmts/arcgen/ograrcgendriver.cpp
index 8a69e72..0d980f9 100644
--- a/ogr/ogrsf_frmts/arcgen/ograrcgendriver.cpp
+++ b/ogr/ogrsf_frmts/arcgen/ograrcgendriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ograrcgendriver.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ograrcgendriver.cpp 32119 2015-12-11 05:47:58Z goatbar $
  *
  * Project:  Arc/Info Generate Translator
  * Purpose:  Implements OGRARCGENDriver.
@@ -30,7 +30,7 @@
 #include "ogr_arcgen.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ograrcgendriver.cpp 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: ograrcgendriver.cpp 32119 2015-12-11 05:47:58Z goatbar $");
 
 extern "C" void RegisterOGRARCGEN();
 
@@ -50,14 +50,14 @@ static GDALDataset *OGRARCGENDriverOpen( GDALOpenInfo* poOpenInfo )
 
     /* Check that the first line is compatible with a generate file */
     /* and in particular contain >= 32 && <= 127 bytes */
-    int i;
-    int bFoundEOL = FALSE;
-    char* szFirstLine = CPLStrdup((const char*) poOpenInfo->pabyHeader);
-    for(i=0;szFirstLine[i] != '\0';i++)
+    bool bFoundEOL = false;
+    char* szFirstLine
+        = CPLStrdup(reinterpret_cast<char *>( poOpenInfo->pabyHeader ) );
+    for(int i=0;szFirstLine[i] != '\0';i++)
     {
         if (szFirstLine[i] == '\n' || szFirstLine[i] == '\r')
         {
-            bFoundEOL = TRUE;
+            bFoundEOL = true;
             szFirstLine[i] = '\0';
             break;
         }
@@ -75,7 +75,7 @@ static GDALDataset *OGRARCGENDriverOpen( GDALOpenInfo* poOpenInfo )
     }
 
     char** papszTokens = CSLTokenizeString2( szFirstLine, " ,", 0 );
-    int nTokens = CSLCount(papszTokens);
+    const int nTokens = CSLCount(papszTokens);
     if (nTokens != 1 && nTokens != 3 && nTokens != 4)
     {
         CSLDestroy(papszTokens);
@@ -94,7 +94,7 @@ static GDALDataset *OGRARCGENDriverOpen( GDALOpenInfo* poOpenInfo )
     CSLDestroy(papszTokens);
     CPLFree(szFirstLine);
 
-    OGRARCGENDataSource   *poDS = new OGRARCGENDataSource();
+    OGRARCGENDataSource *poDS = new OGRARCGENDataSource();
 
     if( !poDS->Open( poOpenInfo->pszFilename ) )
     {
@@ -112,24 +112,18 @@ static GDALDataset *OGRARCGENDriverOpen( GDALOpenInfo* poOpenInfo )
 void RegisterOGRARCGEN()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "ARCGEN" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "ARCGEN" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-
-        poDriver->SetDescription( "ARCGEN" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Arc/Info Generate" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_arcgen.html" );
+    GDALDriver  *poDriver = new GDALDriver();
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetDescription( "ARCGEN" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Arc/Info Generate" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_arcgen.html" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->pfnOpen = OGRARCGENDriverOpen;
 
-        poDriver->pfnOpen = OGRARCGENDriverOpen;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
 
diff --git a/ogr/ogrsf_frmts/arcgen/ograrcgenlayer.cpp b/ogr/ogrsf_frmts/arcgen/ograrcgenlayer.cpp
index 29bd01d..ea3c79a 100644
--- a/ogr/ogrsf_frmts/arcgen/ograrcgenlayer.cpp
+++ b/ogr/ogrsf_frmts/arcgen/ograrcgenlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ograrcgenlayer.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: ograrcgenlayer.cpp 32330 2015-12-20 14:24:33Z rouault $
  *
  * Project:  Arc/Info Generate Translator
  * Purpose:  Implements OGRARCGENLayer class.
@@ -33,25 +33,24 @@
 #include "ogr_p.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ograrcgenlayer.cpp 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: ograrcgenlayer.cpp 32330 2015-12-20 14:24:33Z rouault $");
 
 /************************************************************************/
 /*                            OGRARCGENLayer()                             */
 /************************************************************************/
 
 OGRARCGENLayer::OGRARCGENLayer( const char* pszFilename,
-                          VSILFILE* fp, OGRwkbGeometryType eType )
-
+                                VSILFILE* fpIn, OGRwkbGeometryType eType ) :
+    poFeatureDefn(NULL),
+    fp(fpIn),
+    bEOF(FALSE),
+    nNextFID(0)
 {
-    this->fp = fp;
-    nNextFID = 0;
-    bEOF = FALSE;
-
     poFeatureDefn = new OGRFeatureDefn( CPLGetBasename(pszFilename) );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( eType );
 
-    OGRFieldDefn    oField1( "ID", OFTInteger);
+    OGRFieldDefn oField1( "ID", OFTInteger);
     poFeatureDefn->AddFieldDefn( &oField1 );
     SetDescription( poFeatureDefn->GetName() );
 }
@@ -88,11 +87,9 @@ void OGRARCGENLayer::ResetReading()
 
 OGRFeature *OGRARCGENLayer::GetNextFeature()
 {
-    OGRFeature  *poFeature;
-
-    while(TRUE)
+    while( true )
     {
-        poFeature = GetNextRawFeature();
+        OGRFeature *poFeature = GetNextRawFeature();
         if (poFeature == NULL)
             return NULL;
 
@@ -103,8 +100,8 @@ OGRFeature *OGRARCGENLayer::GetNextFeature()
         {
             return poFeature;
         }
-        else
-            delete poFeature;
+
+        delete poFeature;
     }
 }
 
@@ -117,14 +114,13 @@ OGRFeature *OGRARCGENLayer::GetNextRawFeature()
     if (bEOF)
         return NULL;
 
-    const char* pszLine;
     OGRwkbGeometryType eType = poFeatureDefn->GetGeomType();
 
     if (wkbFlatten(eType) == wkbPoint)
     {
-        while(TRUE)
+        while( true )
         {
-            pszLine = CPLReadLine2L(fp,256,NULL);
+            const char* pszLine = CPLReadLine2L(fp,256,NULL);
             if (pszLine == NULL || EQUAL(pszLine, "END"))
             {
                 bEOF = TRUE;
@@ -149,19 +145,18 @@ OGRFeature *OGRARCGENLayer::GetNextRawFeature()
                 CSLDestroy(papszTokens);
                 return poFeature;
             }
-            else
-                CSLDestroy(papszTokens);
+
+            CSLDestroy(papszTokens);
         }
     }
 
     CPLString osID;
-    OGRLinearRing* poLR =
-        (wkbFlatten(eType) == wkbPolygon) ? new OGRLinearRing() : NULL;
-    OGRLineString* poLS =
-        (wkbFlatten(eType) == wkbLineString) ? new OGRLineString() : poLR;
-    while(TRUE)
+    const bool bIsPoly = (wkbFlatten(eType) == wkbPolygon);
+    OGRLineString* poLS = static_cast<OGRLineString*>(
+        OGRGeometryFactory::createGeometry( (bIsPoly) ? wkbLinearRing : wkbLineString ));
+    while( true )
     {
-        pszLine = CPLReadLine2L(fp,256,NULL);
+        const char* pszLine = CPLReadLine2L(fp,256,NULL);
         if (pszLine == NULL)
             break;
 
@@ -173,10 +168,10 @@ OGRFeature *OGRARCGENLayer::GetNextRawFeature()
             OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
             poFeature->SetFID(nNextFID ++);
             poFeature->SetField(0, osID.c_str());
-            if (wkbFlatten(eType) == wkbPolygon)
+            if( bIsPoly )
             {
                 OGRPolygon* poPoly = new OGRPolygon();
-                poPoly->addRingDirectly(poLR);
+                poPoly->addRingDirectly((OGRLinearRing*)poLS);
                 poFeature->SetGeometryDirectly(poPoly);
             }
             else
@@ -226,7 +221,7 @@ OGRFeature *OGRARCGENLayer::GetNextRawFeature()
 /*                           TestCapability()                           */
 /************************************************************************/
 
-int OGRARCGENLayer::TestCapability( CPL_UNUSED const char * pszCap )
+int OGRARCGENLayer::TestCapability( const char * /* pszCap */ )
 {
     return FALSE;
 }
diff --git a/ogr/ogrsf_frmts/arcobjects/aodriver.cpp b/ogr/ogrsf_frmts/arcobjects/aodriver.cpp
index cd326ce..34f1337 100644
--- a/ogr/ogrsf_frmts/arcobjects/aodriver.cpp
+++ b/ogr/ogrsf_frmts/arcobjects/aodriver.cpp
@@ -101,7 +101,7 @@ OGRDataSource *AODriver::Open( const char* pszFilename,
   // In order to avoid all the COM overhead, we are going to check
   // if we have an AO prefix
 
-  if( !EQUALN(pszFilename,"AO:",3) )
+  if( !STARTS_WITH_CI(pszFilename, "AO:") )
     return NULL;
 
   //OK, it is our turn, let's pay the price
@@ -198,8 +198,6 @@ void AODriver::OpenWorkspace(std::string conn, IWorkspace** ppWorkspace)
 int AODriver::TestCapability( const char * pszCap )
 
 {
-
-  
   /*
   if (EQUAL(pszCap, ODsCCreateLayer) )
     return FALSE;
diff --git a/ogr/ogrsf_frmts/arcobjects/aoutils.cpp b/ogr/ogrsf_frmts/arcobjects/aoutils.cpp
index 41d3f86..3e297ce 100644
--- a/ogr/ogrsf_frmts/arcobjects/aoutils.cpp
+++ b/ogr/ogrsf_frmts/arcobjects/aoutils.cpp
@@ -115,7 +115,7 @@ bool AOToOGRFields(IFields* pFields, OGRFeatureDefn* pOGRFeatureDef, std::vector
       CPLError( CE_Warning, CPLE_AppDefined, "Skipping field %s", CW2A(name) );
       continue;
     }
-      
+
     OGRFieldDefn fieldTemplate( CW2A(name), ogrType);
     pOGRFeatureDef->AddFieldDefn( &fieldTemplate );
 
@@ -127,8 +127,9 @@ bool AOToOGRFields(IFields* pFields, OGRFeatureDefn* pOGRFeatureDef, std::vector
   return true;
 }
 
-// We could make this function far more robust by doing automatic coertion of types,
-// and/or skipping fields we do not know. But our purposes this works fine
+// We could make this function far more robust by doing automatic coercion of
+// types, and/or skipping fields we do not know. But, for our purposes, this
+// works fine.
 
 bool AOToOGRFieldType(esriFieldType aoType, OGRFieldType* pOut)
 {
@@ -150,7 +151,7 @@ bool AOToOGRFieldType(esriFieldType aoType, OGRFieldType* pOut)
   */
 
   //OGR Types
-  
+
   //            Desc                                 Name                AO->OGR Mapped By Us?
   /** Simple 32bit integer *///                   OFTInteger = 0,             YES 
   /** List of 32bit integers *///                 OFTIntegerList = 1,         NO
@@ -315,7 +316,7 @@ bool AOToOGRSpatialReference(esriGeometry::ISpatialReference* pSR, OGRSpatialRef
   }
 
   *ppSR = new OGRSpatialReference(strESRIWKT);
-  
+
   OGRErr result = (*ppSR)->morphFromESRI();
 
   if (result == OGRERR_NONE)
@@ -327,8 +328,9 @@ bool AOToOGRSpatialReference(esriGeometry::ISpatialReference* pSR, OGRSpatialRef
     delete *ppSR;
     *ppSR = NULL;
 
-    CPLError( CE_Failure, CPLE_AppDefined, "Failed morhping from ESRI Geometry: %s", strESRIWKT);
-   
+    CPLError( CE_Failure, CPLE_AppDefined,
+              "Failed morphing from ESRI Geometry: %s", strESRIWKT);
+
     return false;
   }
 }
@@ -340,7 +342,7 @@ bool OGRGeometryToAOGeometry(OGRGeometry* pOGRGeom, esriGeometry::IGeometry** pp
   *ppGeometry = NULL;
 
   GByte* pWKB = NULL;
-  
+
   long wkbSize = pOGRGeom->WkbSize();
   pWKB = (GByte *) CPLMalloc(wkbSize);
 
diff --git a/ogr/ogrsf_frmts/arcobjects/aoutils.h b/ogr/ogrsf_frmts/arcobjects/aoutils.h
index ec830ef..4171fd1 100644
--- a/ogr/ogrsf_frmts/arcobjects/aoutils.h
+++ b/ogr/ogrsf_frmts/arcobjects/aoutils.h
@@ -1,6 +1,6 @@
 
-#ifndef _AO_UTILS_H_INCLUDED
-#define _AO_UTILS_H_INCLUDED
+#ifndef AO_UTILS_H_INCLUDED
+#define AO_UTILS_H_INCLUDED
 
 #include "ogr_ao.h"
 #include <iostream>
diff --git a/ogr/ogrsf_frmts/arcobjects/drv_ao.html b/ogr/ogrsf_frmts/arcobjects/drv_ao.html
index 3d988d7..9169d30 100644
--- a/ogr/ogrsf_frmts/arcobjects/drv_ao.html
+++ b/ogr/ogrsf_frmts/arcobjects/drv_ao.html
@@ -1,100 +1,100 @@
-<html>
-<head>
-<title>ESRI ArcObjects</title>
-</head>
-
-<body bgcolor="#ffffff">
-
-<h1>ESRI ArcObjects</h1>
-
-<h2>Overview</h2>
-
-<p>The OGR ArcObjects driver provides read-only access to ArcObjects based datasources. Since it uses the ESRI SDK, it has the requirement
-of needing an ESRI license to run. Nevertheless, this also means that the driver has full knowledge of ESRI abstractions. Among these, you have:</p>
-
-<ul>
-    <li>GeoDatabases:
-
-    	<ul>
-    		<li>Personal GeoDatabase (.mdb)</li>
-    		<li>File GeoDatabase (.gdb)</li>
-    		<li>Enterprise GeoDatabase (.sde).</li>
-    	</ul>
-    </li>
-
-    <li>ESRI Shapefiles</li>
-</ul>
-
-<p> Although it has not been extended to do this yet (there hasn't been a need), it can potentially also support the following GeoDatabase Abstractions </p>
-
-<ul>
-	<li>Annotation and Dimension feature classes</li>
-	<li>Relationship Classes</li>
-	<li>Networks (GN and ND)</li>
-	<li>Topologies</li>
-	<li>Terrains</li>
-	<li>Representations</li>
-	<li>Parcel Fabrics</li>
-</ul>
-
-<p> You can try those above and they may work - but they have not been tested. Note the abstractions above cannot be supported with the Open FileGeoDatabase API. </p>
-
-
-<h2>Requirements</h2>
-
-<p>
-	<ul>
-		<li>An ArcView license or ArcEngine license (or higher) - Required to run. </li>
-		<li>The ESRI libraries installed. This typically happens if you have ArcEngine or ArcGIS Desktop or Server installed - Required to compile. Note that this code should also compile
-		using the ArcEngine *nix SDKs, however I do not have access to these and thus I have not tried it myself</li>
-	</ul>
-</p>
-
-
-<h2>Usage</h2>
-
-<p> Prefix the Datasource with "AO:" </p>
-
-<ul>
-	<li> Read from FileGDB and load into PostGIS: </li>
-	<br/>
-	<code>ogr2ogr -overwrite -skipfailures -f "PostgreSQL" PG:"host=myhost user=myuser dbname=mydb password=mypass" AO:"C:\somefolder\BigFileGDB.gdb" "MyFeatureClass"</code>
-	<br/>
-	<br/>
-
-	<li> Get detailed info of Personal GeoDatabase: </li>
-	<br/>
-	<code>ogrinfo -al AO:"C:\somefolder\PersonalGDB.mdb"</code>
-	<br/>
-	<br>
-
-	<li> Get detailed info of Enterprise GeoDatabase (.sde contains target version to connect to): </li>
-		<br/>
-		<code>ogrinfo -al AO:"C:\somefolder\MySDEConnection.sde"</code>
-		<br/>
-	<br>
-
-</ul>
-
-
-<h2>Building Notes</h2>
-
-<p> Read the <a href="http://trac.osgeo.org/gdal/wiki/BuildingOnWindows">GDAL Windows Building example for Plugins</a>. You will find a similar section in nmake.opt for ArcObjects.
-After you are done, go to the <i>$gdal_source_root\ogr\ogrsf_frmts\arcobjects</i> folder and execute:</p>
-
-<p>
-	<code>
-		nmake /f makefile.vc plugin
-		nmake /f makefile.vc plugin-install
-	</code>
-</p>
-
-
-<h2>Known Issues</h2>
-
-<p>
-	Date and blob fields have not been implemented. It is probably just a few lines of code, I just have not had time (or need) to do it.
-</p>
-
-</body>
-</html>
+<html>
+<head>
+<title>ESRI ArcObjects</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>ESRI ArcObjects</h1>
+
+<h2>Overview</h2>
+
+<p>The OGR ArcObjects driver provides read-only access to ArcObjects based datasources. Since it uses the ESRI SDK, it has the requirement
+of needing an ESRI license to run. Nevertheless, this also means that the driver has full knowledge of ESRI abstractions. Among these, you have:</p>
+
+<ul>
+    <li>GeoDatabases:
+
+    	<ul>
+    		<li>Personal GeoDatabase (.mdb)</li>
+    		<li>File GeoDatabase (.gdb)</li>
+    		<li>Enterprise GeoDatabase (.sde).</li>
+    	</ul>
+    </li>
+
+    <li>ESRI Shapefiles</li>
+</ul>
+
+<p> Although it has not been extended to do this yet (there hasn't been a need), it can potentially also support the following GeoDatabase Abstractions </p>
+
+<ul>
+	<li>Annotation and Dimension feature classes</li>
+	<li>Relationship Classes</li>
+	<li>Networks (GN and ND)</li>
+	<li>Topologies</li>
+	<li>Terrains</li>
+	<li>Representations</li>
+	<li>Parcel Fabrics</li>
+</ul>
+
+<p> You can try those above and they may work - but they have not been tested. Note the abstractions above cannot be supported with the Open FileGeoDatabase API. </p>
+
+
+<h2>Requirements</h2>
+
+<p>
+	<ul>
+		<li>An ArcView license or ArcEngine license (or higher) - Required to run. </li>
+		<li>The ESRI libraries installed. This typically happens if you have ArcEngine or ArcGIS Desktop or Server installed - Required to compile. Note that this code should also compile
+		using the ArcEngine *nix SDKs, however I do not have access to these and thus I have not tried it myself</li>
+	</ul>
+</p>
+
+
+<h2>Usage</h2>
+
+<p> Prefix the Datasource with "AO:" </p>
+
+<ul>
+	<li> Read from FileGDB and load into PostGIS: </li>
+	<br/>
+	<code>ogr2ogr -overwrite -skipfailures -f "PostgreSQL" PG:"host=myhost user=myuser dbname=mydb password=mypass" AO:"C:\somefolder\BigFileGDB.gdb" "MyFeatureClass"</code>
+	<br/>
+	<br/>
+
+	<li> Get detailed info of Personal GeoDatabase: </li>
+	<br/>
+	<code>ogrinfo -al AO:"C:\somefolder\PersonalGDB.mdb"</code>
+	<br/>
+	<br>
+
+	<li> Get detailed info of Enterprise GeoDatabase (.sde contains target version to connect to): </li>
+		<br/>
+		<code>ogrinfo -al AO:"C:\somefolder\MySDEConnection.sde"</code>
+		<br/>
+	<br>
+
+</ul>
+
+
+<h2>Building Notes</h2>
+
+<p> Read the <a href="http://trac.osgeo.org/gdal/wiki/BuildingOnWindows">GDAL Windows Building example for Plugins</a>. You will find a similar section in nmake.opt for ArcObjects.
+After you are done, go to the <i>$gdal_source_root\ogr\ogrsf_frmts\arcobjects</i> folder and execute:</p>
+
+<p>
+	<code>
+		nmake /f makefile.vc plugin
+		nmake /f makefile.vc plugin-install
+	</code>
+</p>
+
+
+<h2>Known Issues</h2>
+
+<p>
+	Date and blob fields have not been implemented. It is probably just a few lines of code, I just have not had time (or need) to do it.
+</p>
+
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/arcobjects/ogr_ao.h b/ogr/ogrsf_frmts/arcobjects/ogr_ao.h
index d4849b0..ebbf48e 100644
--- a/ogr/ogrsf_frmts/arcobjects/ogr_ao.h
+++ b/ogr/ogrsf_frmts/arcobjects/ogr_ao.h
@@ -26,8 +26,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_AO_H_INCLUDED
-#define _OGR_AO_H_INCLUDED
+#ifndef OGR_AO_H_INCLUDED
+#define OGR_AO_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 
@@ -76,10 +76,14 @@ public:
 
 
   virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce );
+  virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
   virtual GIntBig     GetFeatureCount( int bForce );
   virtual OGRErr      SetAttributeFilter( const char *pszQuery );
   virtual void 	      SetSpatialFilterRect (double dfMinX, double dfMinY, double dfMaxX, double dfMaxY);
   virtual void        SetSpatialFilter( OGRGeometry * );
+  virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+                { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
 
 /*
   virtual OGRErr      CreateField( OGRFieldDefn *poFieldIn,
diff --git a/ogr/ogrsf_frmts/avc/avc.h b/ogr/ogrsf_frmts/avc/avc.h
index 527d2fb..b67d4f4 100644
--- a/ogr/ogrsf_frmts/avc/avc.h
+++ b/ogr/ogrsf_frmts/avc/avc.h
@@ -16,16 +16,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -112,13 +112,18 @@
  *
  **********************************************************************/
 
-#ifndef _AVC_H_INCLUDED_
-#define _AVC_H_INCLUDED_
+#ifndef AVC_H_INCLUDED_
+#define AVC_H_INCLUDED_
 
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
+#ifdef GDAL_COMPILATION
+#include "shapefil.h"
+#else
 #include "dbfopen.h"
+#endif
+
 #include "avc_mbyte.h"
 
 CPL_C_START
@@ -223,11 +228,11 @@ typedef struct AVCArc_t
     GInt32      nLPoly;
     GInt32      nRPoly;
     GInt32      numVertices;
-    AVCVertex   *pasVertices;   
+    AVCVertex   *pasVertices;
 }AVCArc;
 
 /*---------------------------------------------------------------------
- * AVCPal: A PAL (Polygon Arc List) references all the arcs that 
+ * AVCPal: A PAL (Polygon Arc List) references all the arcs that
  *         constitute a polygon.
  *--------------------------------------------------------------------*/
 typedef struct AVCPalArc_t
@@ -318,8 +323,8 @@ typedef struct AVCRxp_t
 
 
 /*---------------------------------------------------------------------
- * AVCTableDef: Definition of an INFO table's structure.  
- *               This info is read from several files: 
+ * AVCTableDef: Definition of an INFO table's structure.
+ *               This info is read from several files:
  *                   info/arc.dir
  *                   info/arc####.dat
  *                   info/arc####.nit
@@ -358,7 +363,7 @@ typedef struct AVCFieldInfo_t
 
 typedef struct AVCTableDef_t
 {
-    /* Stuff read from the arc.dir file 
+    /* Stuff read from the arc.dir file
      * (1 record, corresponding to this table, from the arc.dir file)
      */
     char        szTableName[33];
@@ -445,7 +450,7 @@ typedef struct AVCBinFile_t
         AVCTableDef  *psTableDef;
     }hdr;
 
-    /* cur.* : temp. storage used to read one record (ARC, PAL, ... or 
+    /* cur.* : temp. storage used to read one record (ARC, PAL, ... or
      *         Table record) from the file.
      */
     union
@@ -478,7 +483,7 @@ typedef struct AVCE00GenInfo_t
 {
     char        *pszBuf;
     int         nBufSize;
-    
+
     int         nPrecision;     /* AVC_SINGLE/DOUBLE_PREC       */
     int         iCurItem;
     int         numItems;
@@ -517,7 +522,7 @@ typedef struct AVCE00ParseInfo_t
                                      /* finished parsing */
     int         nTableE00RecLength;
 
-    /* cur.* : temp. storage used to store current object (ARC, PAL, ... or 
+    /* cur.* : temp. storage used to store current object (ARC, PAL, ... or
      *         Table record) from the file.
      */
     union
@@ -558,7 +563,7 @@ typedef struct AVCE00ReadInfo_t
     AVCCoverType eCoverType;
 
     /* pasSections is built when the coverage is opened and describes
-     * the squeleton of the E00 file.
+     * the skeleton of the E00 file.
      */
     AVCE00Section *pasSections;
     int            numSections;
@@ -567,7 +572,7 @@ typedef struct AVCE00ReadInfo_t
      * the next section when a section finishes. (This is the default)
      * Otherwise, you can use AVCE00ReadGotoSection() to read one section
      * at a time... this will set bReadAllSections=FALSE.
-     */ 
+     */
     GBool         bReadAllSections;
 
     /* Info about the file (or E00 section) currently being processed
@@ -602,7 +607,7 @@ typedef struct AVCE00ReadInfoE00_t
      * the next section when a section finishes. (This is the default)
      * Otherwise, you can use AVCE00ReadGotoSectionE00() to read one
      * section at a time.
-     */ 
+     */
     GBool         bReadAllSections;
 
     /* File handle of the E00 file currently being processed
@@ -670,13 +675,13 @@ void        AVCRawBinFSeek(AVCRawBinFile *psInfo, int nOffset, int nFrom);
 GBool       AVCRawBinEOF(AVCRawBinFile *psInfo);
 void        AVCRawBinSetFileDataSize(AVCRawBinFile *psInfo, int nDataSize);
 
-void        AVCRawBinReadBytes(AVCRawBinFile *psInfo, int nBytesToRead, 
+void        AVCRawBinReadBytes(AVCRawBinFile *psInfo, int nBytesToRead,
                                GByte *pBuf);
 GInt16      AVCRawBinReadInt16(AVCRawBinFile *psInfo);
 GInt32      AVCRawBinReadInt32(AVCRawBinFile *psInfo);
 float       AVCRawBinReadFloat(AVCRawBinFile *psInfo);
 double      AVCRawBinReadDouble(AVCRawBinFile *psInfo);
-void        AVCRawBinReadString(AVCRawBinFile *psFile, int nBytesToRead, 
+void        AVCRawBinReadString(AVCRawBinFile *psFile, int nBytesToRead,
                                 GByte *pBuf);
 
 void        AVCRawBinWriteBytes(AVCRawBinFile *psFile, int nBytesToWrite,
@@ -686,14 +691,14 @@ void        AVCRawBinWriteInt32(AVCRawBinFile *psFile, GInt32 n32Value);
 void        AVCRawBinWriteFloat(AVCRawBinFile *psFile, float fValue);
 void        AVCRawBinWriteDouble(AVCRawBinFile *psFile, double dValue);
 void        AVCRawBinWriteZeros(AVCRawBinFile *psFile, int nBytesToWrite);
-void        AVCRawBinWritePaddedString(AVCRawBinFile *psFile, int nFieldSize, 
+void        AVCRawBinWritePaddedString(AVCRawBinFile *psFile, int nFieldSize,
                                        const GByte *pszString);
 
 /*---------------------------------------------------------------------
  * Functions related to reading the binary coverage files
  *--------------------------------------------------------------------*/
 
-AVCBinFile *AVCBinReadOpen(const char *pszPath, const char *pszName, 
+AVCBinFile *AVCBinReadOpen(const char *pszPath, const char *pszName,
                            AVCCoverType eCoverType, AVCFileType eType,
                            AVCDBCSInfo *psDBCSInfo);
 void        AVCBinReadClose(AVCBinFile *psFile);
@@ -712,7 +717,7 @@ AVCRxp     *AVCBinReadNextRxp(AVCBinFile *psFile);
 AVCField   *AVCBinReadNextTableRec(AVCBinFile *psFile);
 char      **AVCBinReadNextPrj(AVCBinFile *psFile);
 
-char      **AVCBinReadListTables(const char *pszInfoPath, 
+char      **AVCBinReadListTables(const char *pszInfoPath,
                                  const char *pszCoverName,
                                  char ***ppapszArcDatFiles,
                                  AVCCoverType eCoverType,
@@ -721,11 +726,11 @@ char      **AVCBinReadListTables(const char *pszInfoPath,
 /*---------------------------------------------------------------------
  * Functions related to writing the binary coverage files
  *--------------------------------------------------------------------*/
-AVCBinFile *AVCBinWriteCreate(const char *pszPath, const char *pszName, 
+AVCBinFile *AVCBinWriteCreate(const char *pszPath, const char *pszName,
                               AVCCoverType eCoverType,
                               AVCFileType eType, int nPrecision,
                               AVCDBCSInfo *psDBCSInfo);
-AVCBinFile *AVCBinWriteCreateTable(const char *pszInfoPath, 
+AVCBinFile *AVCBinWriteCreateTable(const char *pszInfoPath,
                                    const char *pszCoverName,
                                    AVCTableDef *psSrcTableDef,
                                    AVCCoverType eCoverType,
@@ -751,12 +756,12 @@ AVCE00GenInfo  *AVCE00GenInfoAlloc(int nCoverPrecision);
 void        AVCE00GenInfoFree(AVCE00GenInfo *psInfo);
 void        AVCE00GenReset(AVCE00GenInfo  *psInfo);
 
-const char *AVCE00GenStartSection(AVCE00GenInfo *psInfo, AVCFileType eType, 
+const char *AVCE00GenStartSection(AVCE00GenInfo *psInfo, AVCFileType eType,
                                   const char *pszFilename);
 const char *AVCE00GenEndSection(AVCE00GenInfo *psInfo, AVCFileType eType,
                                 GBool bCont);
 
-const char *AVCE00GenObject(AVCE00GenInfo *psInfo, 
+const char *AVCE00GenObject(AVCE00GenInfo *psInfo,
                             AVCFileType eType, void *psObj, GBool bCont);
 const char *AVCE00GenArc(AVCE00GenInfo *psInfo, AVCArc *psArc, GBool bCont);
 const char *AVCE00GenPal(AVCE00GenInfo *psInfo, AVCPal *psPal, GBool bCont);
@@ -777,11 +782,11 @@ const char *AVCE00GenTableRec(AVCE00GenInfo *psInfo, int numFields,
 /*---------------------------------------------------------------------
  * Functions related to parsing E00 lines
  *--------------------------------------------------------------------*/
-AVCE00ParseInfo  *AVCE00ParseInfoAlloc();
+AVCE00ParseInfo  *AVCE00ParseInfoAlloc(void);
 void    AVCE00ParseInfoFree(AVCE00ParseInfo *psInfo);
 void    AVCE00ParseReset(AVCE00ParseInfo  *psInfo);
 
-AVCFileType AVCE00ParseSectionHeader(AVCE00ParseInfo  *psInfo, 
+AVCFileType AVCE00ParseSectionHeader(AVCE00ParseInfo  *psInfo,
                                      const char *pszLine);
 GBool   AVCE00ParseSectionEnd(AVCE00ParseInfo  *psInfo, const char *pszLine,
                               GBool bResetParseInfo);
@@ -800,16 +805,16 @@ AVCTxt  *AVCE00ParseNextTxtLine(AVCE00ParseInfo *psInfo, const char *pszLine);
 AVCTxt  *AVCE00ParseNextTx6Line(AVCE00ParseInfo *psInfo, const char *pszLine);
 char   **AVCE00ParseNextPrjLine(AVCE00ParseInfo *psInfo, const char *pszLine);
 AVCRxp  *AVCE00ParseNextRxpLine(AVCE00ParseInfo *psInfo, const char *pszLine);
-AVCTableDef *AVCE00ParseNextTableDefLine(AVCE00ParseInfo *psInfo, 
+AVCTableDef *AVCE00ParseNextTableDefLine(AVCE00ParseInfo *psInfo,
                                          const char *pszLine);
-AVCField    *AVCE00ParseNextTableRecLine(AVCE00ParseInfo *psInfo, 
+AVCField    *AVCE00ParseNextTableRecLine(AVCE00ParseInfo *psInfo,
                                          const char *pszLine);
 
 
 /*---------------------------------------------------------------------
  * Misc. functions shared by several parts of the lib.
  *--------------------------------------------------------------------*/
-int _AVCE00ComputeRecSize(int numFields, AVCFieldInfo *pasDef, 
+int _AVCE00ComputeRecSize(int numFields, AVCFieldInfo *pasDef,
                           GBool bMapType40ToDouble);
 
 void _AVCDestroyTableFields(AVCTableDef *psTableDef, AVCField *pasFields);
@@ -818,7 +823,7 @@ AVCTableDef *_AVCDupTableDef(AVCTableDef *psSrcDef);
 
 GBool AVCFileExists(const char *pszPath, const char *pszName);
 char *AVCAdjustCaseSensitiveFilename(char *pszFname);
-int  AVCPrintRealValue(char *pszBuf, int nPrecision, AVCFileType eType,
+int  AVCPrintRealValue(char *pszBuf, size_t nBufLen, int nPrecision, AVCFileType eType,
                        double dValue);
 
 /*=====================================================================
@@ -834,7 +839,7 @@ int              AVCE00ReadRewindE00(AVCE00ReadE00Ptr psRead);
 void            *AVCE00ReadNextObjectE00(AVCE00ReadE00Ptr psRead);
 
 AVCE00Section  *AVCE00ReadSectionsListE00(AVCE00ReadE00Ptr psRead, int *numSect);
-int             AVCE00ReadGotoSectionE00(AVCE00ReadE00Ptr psRead, 
+int             AVCE00ReadGotoSectionE00(AVCE00ReadE00Ptr psRead,
                                          AVCE00Section *psSect,
                                          GBool bContinue);
 
@@ -848,7 +853,7 @@ const char     *AVCE00ReadNextLine(AVCE00ReadPtr psInfo);
 int             AVCE00ReadRewind(AVCE00ReadPtr psInfo);
 
 AVCE00Section  *AVCE00ReadSectionsList(AVCE00ReadPtr psInfo, int *numSect);
-int             AVCE00ReadGotoSection(AVCE00ReadPtr psInfo, 
+int             AVCE00ReadGotoSection(AVCE00ReadPtr psInfo,
                                       AVCE00Section *psSect,
                                       GBool bContinue);
 
@@ -856,15 +861,13 @@ int             AVCE00ReadGotoSection(AVCE00ReadPtr psInfo,
  * Functions to write E00 lines to a binary coverage
  *--------------------------------------------------------------------*/
 
-AVCE00WritePtr  AVCE00WriteOpen(const char *pszCoverPath, 
+AVCE00WritePtr  AVCE00WriteOpen(const char *pszCoverPath,
                                 AVCCoverType eNewCoverType, int nPrecision);
 void            AVCE00WriteClose(AVCE00WritePtr psInfo);
-int             AVCE00WriteNextLine(AVCE00WritePtr psInfo, 
+int             AVCE00WriteNextLine(AVCE00WritePtr psInfo,
                                     const char *pszLine);
 int             AVCE00DeleteCoverage(const char *pszCoverPath);
 
 CPL_C_END
 
-#endif /* _AVC_H_INCLUDED_ */
-
-
+#endif /* AVC_H_INCLUDED_ */
diff --git a/ogr/ogrsf_frmts/avc/avc_bin.c b/ogr/ogrsf_frmts/avc/avc_bin.c
index 2c93f29..0404f8d 100644
--- a/ogr/ogrsf_frmts/avc/avc_bin.c
+++ b/ogr/ogrsf_frmts/avc/avc_bin.c
@@ -16,16 +16,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -133,6 +133,10 @@
 
 #include <ctype.h>      /* for isspace() */
 
+
+/* Used by avc_binwr.c */
+extern int _AVCBinReadNextArcDir(AVCRawBinFile *psFile, AVCTableDef *psArcDir);
+
 /*=====================================================================
  * Prototypes for some static functions
  *====================================================================*/
@@ -148,7 +152,7 @@ static AVCBinFile *_AVCBinReadOpenPrj(const char *pszPath,const char *pszName);
 static int _AVCBinReadNextTableRec(AVCRawBinFile *psFile, int nFields,
                                    AVCFieldInfo *pasDef, AVCField *pasFields,
                                    int nRecordSize);
-static int _AVCBinReadNextDBFTableRec(DBFHandle hDBFFile, int *piRecordIndex, 
+static int _AVCBinReadNextDBFTableRec(DBFHandle hDBFFile, int *piRecordIndex,
                                       int nFields, AVCFieldInfo *pasDef,
                                       AVCField *pasFields);
 
@@ -167,16 +171,16 @@ static int _AVCBinReadNextDBFTableRec(DBFHandle hDBFFile, int *piRecordIndex,
  *         a '/' or a '\\'
  * pszName is the name of the file to open relative to this directory.
  *
- * Note: For most file types except tables, passing pszPath="" and 
+ * Note: For most file types except tables, passing pszPath="" and
  * including the coverage path as part of pszName instead would work.
  *
  * Returns a valid AVCBinFile handle, or NULL if the file could
  * not be opened.
  *
- * AVCBinClose() will eventually have to be called to release the 
+ * AVCBinClose() will eventually have to be called to release the
  * resources used by the AVCBinFile structure.
  **********************************************************************/
-AVCBinFile *AVCBinReadOpen(const char *pszPath, const char *pszName, 
+AVCBinFile *AVCBinReadOpen(const char *pszPath, const char *pszName,
                            AVCCoverType eCoverType, AVCFileType eFileType,
                            AVCDBCSInfo *psDBCSInfo)
 {
@@ -191,7 +195,7 @@ AVCBinFile *AVCBinReadOpen(const char *pszPath, const char *pszName,
         if (eCoverType == AVCCoverPC || eCoverType == AVCCoverPC2)
             return _AVCBinReadOpenDBFTable(pszPath, pszName);
         else
-            return _AVCBinReadOpenTable(pszPath, pszName, 
+            return _AVCBinReadOpenTable(pszPath, pszName,
                                         eCoverType, psDBCSInfo);
     }
 
@@ -212,9 +216,9 @@ AVCBinFile *AVCBinReadOpen(const char *pszPath, const char *pszName,
     psFile->eFileType = eFileType;
     psFile->eCoverType = eCoverType;
 
-    psFile->pszFilename = (char*)CPLMalloc((strlen(pszPath)+strlen(pszName)+1)*
-                                           sizeof(char));
-    sprintf(psFile->pszFilename, "%s%s", pszPath, pszName);
+    psFile->pszFilename = (char*)CPLMalloc(strlen(pszPath)+strlen(pszName)+1);
+    snprintf(psFile->pszFilename,
+             strlen(pszPath)+strlen(pszName)+1, "%s%s", pszPath, pszName);
 
     AVCAdjustCaseSensitiveFilename(psFile->pszFilename);
 
@@ -341,7 +345,7 @@ void    AVCBinReadClose(AVCBinFile *psFile)
     {
         CSLDestroy(psFile->cur.papszPrj);
     }
-    else if (psFile->eFileType == AVCFileTXT || 
+    else if (psFile->eFileType == AVCFileTXT ||
              psFile->eFileType == AVCFileTX6)
     {
         if (psFile->cur.psTxt)
@@ -380,14 +384,15 @@ void    AVCBinReadClose(AVCBinFile *psFile)
  *
  * Returns 0 on success or -1 on error.
  **********************************************************************/
+static
 int _AVCBinReadHeader(AVCRawBinFile *psFile, AVCBinHeader *psHeader,
                       AVCCoverType eCoverType)
 {
     int nStatus = 0;
 
     /*-----------------------------------------------------------------
-     * For AVCCoverPC coverages (files without hte .adf extension), 
-     * there is a first 256 bytes header that we just skip and that 
+     * For AVCCoverPC coverages (files without hte .adf extension),
+     * there is a first 256 bytes header that we just skip and that
      * precedes the 100 bytes header block.
      *
      * In AVCCoverV7, we only have the 100 bytes header.
@@ -446,7 +451,7 @@ int AVCBinReadRewind(AVCBinFile *psFile)
      * For AVCCoverPC coverages, there is a first 256 bytes header
      * that we just skip and that precedes the 100 bytes header block.
      *
-     * In AVCCoverV7, AVCCoverPC2 and AVCCoverWeird, we only find the 
+     * In AVCCoverV7, AVCCoverPC2 and AVCCoverWeird, we only find the
      * 100 bytes header.
      *
      * Note: it is the call to _AVCBinReadHeader() that takes care
@@ -462,22 +467,22 @@ int AVCBinReadRewind(AVCBinFile *psFile)
          psFile->eFileType == AVCFileLAB ||
          psFile->eFileType == AVCFileTXT ||
          psFile->eFileType == AVCFileTX6  )
-    {   
-        nStatus = _AVCBinReadHeader(psFile->psRawBinFile, &sHeader, 
+    {
+        nStatus = _AVCBinReadHeader(psFile->psRawBinFile, &sHeader,
                                     psFile->eCoverType);
 
         /* Store the precision information inside the file handle.
          *
          * Of course, there had to be an exception...
-         * At least PAL and TXT files in PC Arc/Info coverages sometimes 
-         * have a negative precision flag even if they contain single 
+         * At least PAL and TXT files in PC Arc/Info coverages sometimes
+         * have a negative precision flag even if they contain single
          * precision data... why is that????  A PC Arc bug?
          *
          * 2000-06-05: Found a double-precision PAL file with a signature
          *             of 1011 (should have been -11).  So we'll assume
          *             that signature > 1000 also means double precision.
          */
-        if ((sHeader.nPrecision < 0 || sHeader.nPrecision > 1000) && 
+        if ((sHeader.nPrecision < 0 || sHeader.nPrecision > 1000) &&
             psFile->eCoverType != AVCCoverPC)
             psFile->nPrecision = AVC_DOUBLE_PREC;
         else
@@ -511,7 +516,7 @@ int AVCBinReadRewind(AVCBinFile *psFile)
     else if (psFile->eFileType == AVCFileTOL)
     {
         /*-------------------------------------------------------------
-         * For some reason, the tolerance files do not follow the 
+         * For some reason, the tolerance files do not follow the
          * general rules!
          * Single precision "tol.adf" have no header
          * Double precision "par.adf" have the usual 100 bytes header,
@@ -528,18 +533,18 @@ int AVCBinReadRewind(AVCBinFile *psFile)
 
         if (nSignature == 9993)
         {
-            /* We have a double precision par.adf... read the 100 bytes 
-             * header and set the precision information inside the file 
+            /* We have a double precision par.adf... read the 100 bytes
+             * header and set the precision information inside the file
              * handle.
              */
-            nStatus = _AVCBinReadHeader(psFile->psRawBinFile, &sHeader, 
+            nStatus = _AVCBinReadHeader(psFile->psRawBinFile, &sHeader,
                                         psFile->eCoverType);
 
             psFile->nPrecision = AVC_DOUBLE_PREC;
         }
         else
         {
-            /* It's a single precision tol.adf ... just set the 
+            /* It's a single precision tol.adf ... just set the
              * precision field.
              */
             AVCRawBinFSeek(psFile->psRawBinFile, 0, SEEK_SET);
@@ -555,7 +560,7 @@ int AVCBinReadRewind(AVCBinFile *psFile)
  *
  * Read the object with a particular index.  For fixed length record
  * files we seek directly to the object.  For variable files we try to
- * get the offset from the corresponding index file.  
+ * get the offset from the corresponding index file.
  *
  * NOTE: Currently only implemented for ARC, PAL and TABLE files.
  *
@@ -565,24 +570,25 @@ void *AVCBinReadObject(AVCBinFile *psFile, int iObjIndex )
 {
     int	 bIndexed = FALSE;
     int  nObjectOffset, nRecordSize=0, nRecordStart = 0, nLen;
-    char *pszExt = NULL;
+    char szExt[4] = {0,0,0,0};
+    char *pszExt = szExt;
 
     if( iObjIndex < 0 )
         return NULL;
 
     /*-----------------------------------------------------------------
-     * Determine some information from based on the coverage type.    
+     * Determine some information from based on the coverage type.
      *----------------------------------------------------------------*/
-    nLen = strlen(psFile->pszFilename);
+    nLen = (int)strlen(psFile->pszFilename);
     if( psFile->eFileType == AVCFileARC &&
-        ((nLen>=3 && EQUALN((pszExt=psFile->pszFilename+nLen-3), "arc", 3)) ||
-         (nLen>=7 && EQUALN((pszExt=psFile->pszFilename+nLen-7),"arc.adf",7))))
+        ((nLen>=3 && STARTS_WITH_CI((pszExt=psFile->pszFilename+nLen-3), "arc")) ||
+         (nLen>=7 && STARTS_WITH_CI((pszExt=psFile->pszFilename+nLen-7), "arc.adf"))))
     {
         bIndexed = TRUE;
     }
     else if( psFile->eFileType == AVCFilePAL &&
-        ((nLen>=3 && EQUALN((pszExt=psFile->pszFilename+nLen-3), "pal", 3)) ||
-         (nLen>=7 && EQUALN((pszExt=psFile->pszFilename+nLen-7),"pal.adf",7))))
+        ((nLen>=3 && STARTS_WITH_CI((pszExt=psFile->pszFilename+nLen-3), "pal")) ||
+         (nLen>=7 && STARTS_WITH_CI((pszExt=psFile->pszFilename+nLen-7), "pal.adf"))))
     {
         bIndexed = TRUE;
     }
@@ -603,18 +609,15 @@ void *AVCBinReadObject(AVCBinFile *psFile, int iObjIndex )
     {
         char chOrig;
 
-        if( pszExt == NULL )
-            return NULL;
-
         chOrig = pszExt[2];
         if( chOrig > 'A' && chOrig < 'Z' )
             pszExt[2] = 'X';
         else
             pszExt[2] = 'x';
 
-        psFile->psIndexFile = 
-            AVCRawBinOpen( psFile->pszFilename, "rb", 
-                           psFile->psRawBinFile->eByteOrder, 
+        psFile->psIndexFile =
+            AVCRawBinOpen( psFile->pszFilename, "rb",
+                           psFile->psRawBinFile->eByteOrder,
                            psFile->psRawBinFile->psDBCSInfo);
         pszExt[2] = chOrig;
 
@@ -669,11 +672,11 @@ void *AVCBinReadObject(AVCBinFile *psFile, int iObjIndex )
  *
  * Returns a (void*) to a static structure with the contents of the object
  * that was read.  The contents of the structure will be valid only until
- * the next call.  
+ * the next call.
  * If you use the returned value, then make sure that you cast it to
  * the right type for the current file! (AVCArc, AVCPal, AVCCnt, ...)
  *
- * Returns NULL if an error happened or if EOF was reached.  
+ * Returns NULL if an error happened or if EOF was reached.
  **********************************************************************/
 void *AVCBinReadNextObject(AVCBinFile *psFile)
 {
@@ -722,9 +725,9 @@ void *AVCBinReadNextObject(AVCBinFile *psFile)
  *
  * Reads the next record from an attribute table.
  *
- * Returns a pointer to an array of static AVCField structure whose 
+ * Returns a pointer to an array of static AVCField structure whose
  * contents will be valid only until the next call,
- * or NULL if an error happened or if EOF was reached.  
+ * or NULL if an error happened or if EOF was reached.
  **********************************************************************/
 AVCField *AVCBinReadNextTableRec(AVCBinFile *psFile)
 {
@@ -733,7 +736,7 @@ AVCField *AVCBinReadNextTableRec(AVCBinFile *psFile)
         psFile->eFileType == AVCFileTABLE &&
         psFile->hdr.psTableDef->numRecords > 0 &&
         ! AVCRawBinEOF(psFile->psRawBinFile) &&
-        _AVCBinReadNextTableRec(psFile->psRawBinFile, 
+        _AVCBinReadNextTableRec(psFile->psRawBinFile,
                                     psFile->hdr.psTableDef->numFields,
                                     psFile->hdr.psTableDef->pasFieldDef,
                                     psFile->cur.pasFields,
@@ -745,7 +748,7 @@ AVCField *AVCBinReadNextTableRec(AVCBinFile *psFile)
               psFile->eCoverType == AVCCoverPC2 ) &&
              psFile->eFileType == AVCFileTABLE &&
              psFile->hdr.psTableDef->numRecords > 0 &&
-             _AVCBinReadNextDBFTableRec(psFile->hDBFFile, 
+             _AVCBinReadNextDBFTableRec(psFile->hDBFFile,
                                         &(psFile->nCurDBFRecord),
                                         psFile->hdr.psTableDef->numFields,
                                         psFile->hdr.psTableDef->pasFieldDef,
@@ -778,6 +781,7 @@ AVCField *AVCBinReadNextTableRec(AVCBinFile *psFile)
  *
  * Returns 0 on success or -1 on error.
  **********************************************************************/
+static
 int _AVCBinReadNextArc(AVCRawBinFile *psFile, AVCArc *psArc,
                               int nPrecision)
 {
@@ -803,13 +807,19 @@ int _AVCBinReadNextArc(AVCRawBinFile *psFile, AVCArc *psArc,
      * double values in memory, even for single precision coverages.
      */
     if (psArc->pasVertices == NULL || numVertices > psArc->numVertices)
-        psArc->pasVertices = (AVCVertex*)CPLRealloc(psArc->pasVertices,
+    {
+        AVCVertex* pasNewVertices = (AVCVertex*)VSIRealloc(psArc->pasVertices,
                                                 numVertices*sizeof(AVCVertex));
+        if( pasNewVertices == NULL )
+            return -1;
+        psArc->pasVertices = pasNewVertices;
+    }
 
     psArc->numVertices = numVertices;
 
     if (nPrecision == AVC_SINGLE_PREC)
     {
+        /* coverity[tainted_data] */
         for(i=0; i<numVertices; i++)
         {
             psArc->pasVertices[i].x = AVCRawBinReadFloat(psFile);
@@ -818,6 +828,7 @@ int _AVCBinReadNextArc(AVCRawBinFile *psFile, AVCArc *psArc,
     }
     else
     {
+        /* coverity[tainted_data] */
         for(i=0; i<numVertices; i++)
         {
             psArc->pasVertices[i].x = AVCRawBinReadDouble(psFile);
@@ -844,7 +855,7 @@ int _AVCBinReadNextArc(AVCRawBinFile *psFile, AVCArc *psArc,
  *
  * Returns a pointer to a static AVCArc structure whose contents will be
  * valid only until the next call or NULL if an error happened or if EOF
- * was reached.  
+ * was reached.
  **********************************************************************/
 AVCArc *AVCBinReadNextArc(AVCBinFile *psFile)
 {
@@ -878,7 +889,8 @@ AVCArc *AVCBinReadNextArc(AVCBinFile *psFile)
  *
  * Returns 0 on success or -1 on error.
  **********************************************************************/
-int _AVCBinReadNextPal(AVCRawBinFile *psFile, AVCPal *psPal, 
+static
+int _AVCBinReadNextPal(AVCRawBinFile *psFile, AVCPal *psPal,
                               int nPrecision)
 {
     int i, numArcs;
@@ -912,11 +924,17 @@ int _AVCBinReadNextPal(AVCRawBinFile *psFile, AVCPal *psPal,
      * do not realloc to a smaller size.
      */
     if (psPal->pasArcs == NULL || numArcs > psPal->numArcs)
-        psPal->pasArcs = (AVCPalArc*)CPLRealloc(psPal->pasArcs,
+    {
+        AVCPalArc* pasNewArcs = (AVCPalArc*)VSIRealloc(psPal->pasArcs,
                                                  numArcs*sizeof(AVCPalArc));
+        if( pasNewArcs == NULL )
+            return -1;
+        psPal->pasArcs = pasNewArcs;
+    }
 
     psPal->numArcs = numArcs;
 
+    /* coverity[tainted_data] */
     for(i=0; i<numArcs; i++)
     {
         psPal->pasArcs[i].nArcId = AVCRawBinReadInt32(psFile);
@@ -942,7 +960,7 @@ int _AVCBinReadNextPal(AVCRawBinFile *psFile, AVCPal *psPal,
  *
  * Returns a pointer to a static AVCPal structure whose contents will be
  * valid only until the next call or NULL if an error happened or if EOF
- * was reached.  
+ * was reached.
  **********************************************************************/
 AVCPal *AVCBinReadNextPal(AVCBinFile *psFile)
 {
@@ -972,7 +990,8 @@ AVCPal *AVCBinReadNextPal(AVCBinFile *psFile)
  *
  * Returns 0 on success or -1 on error.
  **********************************************************************/
-int _AVCBinReadNextCnt(AVCRawBinFile *psFile, AVCCnt *psCnt, 
+static
+int _AVCBinReadNextCnt(AVCRawBinFile *psFile, AVCCnt *psCnt,
                               int nPrecision)
 {
     int i, numLabels;
@@ -1002,11 +1021,17 @@ int _AVCBinReadNextCnt(AVCRawBinFile *psFile, AVCCnt *psCnt,
      * do not realloc to a smaller size.
      */
     if (psCnt->panLabelIds == NULL || numLabels > psCnt->numLabels)
-        psCnt->panLabelIds = (GInt32 *)CPLRealloc(psCnt->panLabelIds,
+    {
+        GInt32* panIds = (GInt32 *)VSIRealloc(psCnt->panLabelIds,
                                                   numLabels*sizeof(GInt32));
+        if( panIds == NULL )
+            return -1;
+        psCnt->panLabelIds = panIds;
+    }
 
     psCnt->numLabels = numLabels;
 
+    /* coverity[tainted_data] */
     for(i=0; i<numLabels; i++)
     {
         psCnt->panLabelIds[i] = AVCRawBinReadInt32(psFile);
@@ -1030,7 +1055,7 @@ int _AVCBinReadNextCnt(AVCRawBinFile *psFile, AVCCnt *psCnt,
  *
  * Returns a pointer to a static AVCCnt structure whose contents will be
  * valid only until the next call or NULL if an error happened or if EOF
- * was reached.  
+ * was reached.
  **********************************************************************/
 AVCCnt *AVCBinReadNextCnt(AVCBinFile *psFile)
 {
@@ -1060,7 +1085,8 @@ AVCCnt *AVCBinReadNextCnt(AVCBinFile *psFile)
  *
  * Returns 0 on success or -1 on error.
  **********************************************************************/
-int _AVCBinReadNextLab(AVCRawBinFile *psFile, AVCLab *psLab, 
+static
+int _AVCBinReadNextLab(AVCRawBinFile *psFile, AVCLab *psLab,
                               int nPrecision)
 {
 
@@ -1099,7 +1125,7 @@ int _AVCBinReadNextLab(AVCRawBinFile *psFile, AVCLab *psLab,
  *
  * Returns a pointer to a static AVCLab structure whose contents will be
  * valid only until the next call or NULL if an error happened or if EOF
- * was reached.  
+ * was reached.
  **********************************************************************/
 AVCLab *AVCBinReadNextLab(AVCBinFile *psFile)
 {
@@ -1128,7 +1154,8 @@ AVCLab *AVCBinReadNextLab(AVCBinFile *psFile)
  *
  * Returns 0 on success or -1 on error.
  **********************************************************************/
-int _AVCBinReadNextTol(AVCRawBinFile *psFile, AVCTol *psTol, 
+static
+int _AVCBinReadNextTol(AVCRawBinFile *psFile, AVCTol *psTol,
                        int nPrecision)
 {
 
@@ -1157,7 +1184,7 @@ int _AVCBinReadNextTol(AVCRawBinFile *psFile, AVCTol *psTol,
  *
  * Returns a pointer to a static AVCTol structure whose contents will be
  * valid only until the next call or NULL if an error happened or if EOF
- * was reached.  
+ * was reached.
  **********************************************************************/
 AVCTol *AVCBinReadNextTol(AVCBinFile *psFile)
 {
@@ -1182,7 +1209,7 @@ AVCTol *AVCBinReadNextTol(AVCBinFile *psFile)
  * (This function is for internal library use... external calls should
  * go to AVCBinReadOpen() with type AVCFilePRJ instead)
  *
- * Open a PRJ file.  
+ * Open a PRJ file.
  *
  * This call will actually read the whole PRJ file in memory since PRJ
  * files are small text files.
@@ -1195,9 +1222,8 @@ AVCBinFile *_AVCBinReadOpenPrj(const char *pszPath, const char *pszName)
     /*-----------------------------------------------------------------
      * Load the PRJ file contents into a stringlist.
      *----------------------------------------------------------------*/
-    pszFname = (char*)CPLMalloc((strlen(pszPath)+strlen(pszName)+1)*
-                                sizeof(char));
-    sprintf(pszFname, "%s%s", pszPath, pszName);
+    pszFname = (char*)CPLMalloc(strlen(pszPath)+strlen(pszName)+1);
+    snprintf(pszFname, strlen(pszPath)+strlen(pszName)+1, "%s%s", pszPath, pszName);
 
     papszPrj = CSLLoad(pszFname);
 
@@ -1233,7 +1259,7 @@ AVCBinFile *_AVCBinReadOpenPrj(const char *pszPath, const char *pszName)
  * PRJ files are simple text files with variable length lines, so we
  * don't use the AVCRawBin*() functions for this case.
  *
- * Returns a reference to a static stringlist with the whole file 
+ * Returns a reference to a static stringlist with the whole file
  * contents, or NULL in case of error.
  *
  * The returned stringlist should NOT be freed by the caller.
@@ -1261,13 +1287,14 @@ char **AVCBinReadNextPrj(AVCBinFile *psFile)
  *
  * Returns 0 on success or -1 on error.
  **********************************************************************/
-int _AVCBinReadNextTxt(AVCRawBinFile *psFile, AVCTxt *psTxt, 
+static
+int _AVCBinReadNextTxt(AVCRawBinFile *psFile, AVCTxt *psTxt,
                               int nPrecision)
 {
     int i, numVerticesBefore, numVertices, numCharsToRead, nRecordSize;
     int numBytesRead;
 
-    numVerticesBefore = ABS(psTxt->numVerticesLine) + 
+    numVerticesBefore = ABS(psTxt->numVerticesLine) +
                         ABS(psTxt->numVerticesArrow);
 
     psTxt->nTxtId  = AVCRawBinReadInt32(psFile);
@@ -1312,11 +1339,15 @@ int _AVCBinReadNextTxt(AVCRawBinFile *psFile, AVCTxt *psTxt,
     if (psTxt->pszText == NULL ||
         ((int)(strlen((char*)psTxt->pszText)+3)/4)*4 < numCharsToRead )
     {
-        psTxt->pszText = (GByte*)CPLRealloc(psTxt->pszText,
+        GByte* pszNewText = (GByte*)VSIRealloc(psTxt->pszText,
                                             (numCharsToRead+1)*sizeof(char));
+        if( pszNewText == NULL )
+            return -1;
+        psTxt->pszText = pszNewText;
     }
 
     AVCRawBinReadString(psFile, numCharsToRead, psTxt->pszText);
+    /* coverity[tainted_data] */
     psTxt->pszText[psTxt->numChars] = '\0';
 
     /* Realloc the vertices array only if it needs to grow...
@@ -1346,7 +1377,7 @@ int _AVCBinReadNextTxt(AVCRawBinFile *psFile, AVCTxt *psTxt,
     }
 
     /* In V7 Coverages, we always have 8 bytes of junk at end of record.
-     * In Weird coverages, these 8 bytes are sometimes present, and 
+     * In Weird coverages, these 8 bytes are sometimes present, and
      * sometimes not!!! (Probably another AI "random feature"! ;-)
      * So we use the record size to establish if there is any junk to skip
      */
@@ -1368,17 +1399,18 @@ int _AVCBinReadNextTxt(AVCRawBinFile *psFile, AVCTxt *psTxt,
  * go to AVCBinReadNextTxt() instead)
  *
  * Read the next TXT (Annotation) structure from a PC Coverage file.
- * Note that it is assumed that PC Coverage files are always single 
+ * Note that it is assumed that PC Coverage files are always single
  * precision.
  *
  * Returns 0 on success or -1 on error.
  **********************************************************************/
-int _AVCBinReadNextPCCoverageTxt(AVCRawBinFile *psFile, AVCTxt *psTxt, 
+static
+int _AVCBinReadNextPCCoverageTxt(AVCRawBinFile *psFile, AVCTxt *psTxt,
                                  int nPrecision)
 {
     int i, numVerticesBefore, numVertices, numCharsToRead, nRecordSize;
 
-    numVerticesBefore = ABS(psTxt->numVerticesLine) + 
+    numVerticesBefore = ABS(psTxt->numVerticesLine) +
                         ABS(psTxt->numVerticesArrow);
 
     psTxt->nTxtId  = AVCRawBinReadInt32(psFile);
@@ -1390,7 +1422,7 @@ int _AVCBinReadNextPCCoverageTxt(AVCRawBinFile *psFile, AVCTxt *psTxt,
     psTxt->nUserId = 0;
     psTxt->nLevel  = AVCRawBinReadInt32(psFile);
 
-    psTxt->numVerticesLine  = AVCRawBinReadInt32(psFile);  
+    psTxt->numVerticesLine  = AVCRawBinReadInt32(psFile);
     /* We are not expecting more than 4 vertices */
     psTxt->numVerticesLine = MIN(psTxt->numVerticesLine, 4);
 
@@ -1470,7 +1502,7 @@ int _AVCBinReadNextPCCoverageTxt(AVCRawBinFile *psFile, AVCTxt *psTxt,
                                             (numCharsToRead+5)*sizeof(char));
     }
 
-
+    /* coverity[tainted_data] */
     AVCRawBinReadString(psFile, numCharsToRead, psTxt->pszText);
     psTxt->pszText[psTxt->numChars] = '\0';
 
@@ -1495,7 +1527,7 @@ int _AVCBinReadNextPCCoverageTxt(AVCRawBinFile *psFile, AVCTxt *psTxt,
  *
  * Returns a pointer to a static AVCTxt structure whose contents will be
  * valid only until the next call or NULL if an error happened or if EOF
- * was reached.  
+ * was reached.
  **********************************************************************/
 AVCTxt *AVCBinReadNextTxt(AVCBinFile *psFile)
 {
@@ -1516,16 +1548,16 @@ AVCTxt *AVCBinReadNextTxt(AVCBinFile *psFile)
     if (psFile->eFileType == AVCFileTXT &&
         (psFile->eCoverType == AVCCoverPC ||
          psFile->eCoverType == AVCCoverWeird) )
-    {    
+    {
         /* TXT file in PC Coverages (and some Weird Coverages)
          */
-        nStatus = _AVCBinReadNextPCCoverageTxt(psFile->psRawBinFile, 
+        nStatus = _AVCBinReadNextPCCoverageTxt(psFile->psRawBinFile,
                                                psFile->cur.psTxt,
                                                psFile->nPrecision);
     }
     else
-    {   
-        /* TXT in V7 Coverages (and some Weird Coverages), and TX6/TX7 in 
+    {
+        /* TXT in V7 Coverages (and some Weird Coverages), and TX6/TX7 in
          * all coverage types
          */
         nStatus = _AVCBinReadNextTxt(psFile->psRawBinFile, psFile->cur.psTxt,
@@ -1555,6 +1587,7 @@ AVCTxt *AVCBinReadNextTxt(AVCBinFile *psFile)
  *
  * Returns 0 on success or -1 on error.
  **********************************************************************/
+static
 int _AVCBinReadNextRxp(AVCRawBinFile *psFile,
                        AVCRxp *psRxp,
                        CPL_UNUSED int nPrecision)
@@ -1575,7 +1608,7 @@ int _AVCBinReadNextRxp(AVCRawBinFile *psFile,
  *
  * Returns a pointer to a static AVCRxp structure whose contents will be
  * valid only until the next call or NULL if an error happened or if EOF
- * was reached.  
+ * was reached.
  **********************************************************************/
 AVCRxp *AVCBinReadNextRxp(AVCBinFile *psFile)
 {
@@ -1609,11 +1642,12 @@ AVCRxp *AVCBinReadNextRxp(AVCBinFile *psFile)
  *
  * Returns 0 on success or -1 on error.
  **********************************************************************/
+
 int _AVCBinReadNextArcDir(AVCRawBinFile *psFile, AVCTableDef *psArcDir)
 {
     int i;
 
-    /* Arc/Info Table name 
+    /* Arc/Info Table name
      */
     AVCRawBinReadString(psFile, 32, (GByte *)psArcDir->szTableName);
     psArcDir->szTableName[32] = '\0';
@@ -1632,12 +1666,12 @@ int _AVCBinReadNextArcDir(AVCRawBinFile *psFile, AVCTableDef *psArcDir)
     psArcDir->nRecSize  = AVCRawBinReadInt16(psFile);
 
     AVCRawBinFSeek(psFile, 18, SEEK_CUR);     /* Skip 18 bytes */
-    
+
     psArcDir->bDeletedFlag = AVCRawBinReadInt16(psFile);
     psArcDir->numRecords = AVCRawBinReadInt32(psFile);
 
     AVCRawBinFSeek(psFile, 10, SEEK_CUR);     /* Skip 10 bytes */
-    
+
     AVCRawBinReadBytes(psFile, 2, (GByte *)psArcDir->szExternal);
     psArcDir->szExternal[2] = '\0';
 
@@ -1659,6 +1693,7 @@ int _AVCBinReadNextArcDir(AVCRawBinFile *psFile, AVCTableDef *psArcDir)
  *
  * Returns 0 on success or -1 on error.
  **********************************************************************/
+static
 int _AVCBinReadNextArcNit(AVCRawBinFile *psFile, AVCFieldInfo *psField)
 {
     AVCRawBinReadString(psFile, 16, (GByte *)psField->szName);
@@ -1685,7 +1720,7 @@ int _AVCBinReadNextArcNit(AVCRawBinFile *psFile, AVCFieldInfo *psField)
     psField->szAltName[16] = '\0';
 
     AVCRawBinFSeek(psFile, 56, SEEK_CUR);             /* Skip 56 bytes */
-    
+
     psField->nIndex    = AVCRawBinReadInt16(psFile);
 
     AVCRawBinFSeek(psFile, 28, SEEK_CUR);  /* Skip the remaining 28 bytes */
@@ -1699,32 +1734,40 @@ int _AVCBinReadNextArcNit(AVCRawBinFile *psFile, AVCFieldInfo *psField)
  * Look for the DAT or NIT files for a given table... returns TRUE if
  * they exist, or FALSE otherwise.
  *
- * If pszRetFnmae/pszRetNitFile != NULL then the filename with full path 
+ * If pszRetFnmae/pszRetNitFile != NULL then the filename with full path
  * will be copied to the specified buffer.
  **********************************************************************/
-GBool _AVCBinReadGetInfoFilename(const char *pszInfoPath, 
+static
+GBool _AVCBinReadGetInfoFilename(const char *pszInfoPath,
                                  const char *pszBasename,
                                  const char *pszDatOrNit,
                                  AVCCoverType eCoverType,
-                                 char *pszRetFname)
+                                 char *pszRetFname,
+                                 size_t nRetFnameLen)
 {
     GBool       bFilesExist = FALSE;
     char        *pszBuf = NULL;
     VSIStatBuf  sStatBuf;
+    size_t      nBufLen;
 
     if (pszRetFname)
+    {
         pszBuf = pszRetFname;
+        nBufLen = nRetFnameLen;
+    }
     else
-        pszBuf = (char*)CPLMalloc((strlen(pszInfoPath)+strlen(pszBasename)+10)*
-                                  sizeof(char));
+    {
+        nBufLen = strlen(pszInfoPath)+strlen(pszBasename)+10;
+        pszBuf = (char*)CPLMalloc(nBufLen);
+    }
 
     if (eCoverType == AVCCoverWeird)
     {
-        sprintf(pszBuf, "%s%s%s", pszInfoPath, pszBasename, pszDatOrNit);
+        snprintf(pszBuf, nBufLen, "%s%s%s", pszInfoPath, pszBasename, pszDatOrNit);
     }
     else
     {
-        sprintf(pszBuf, "%s%s.%s", pszInfoPath, pszBasename, pszDatOrNit);
+        snprintf(pszBuf, nBufLen, "%s%s.%s", pszInfoPath, pszBasename, pszDatOrNit);
     }
 
     AVCAdjustCaseSensitiveFilename(pszBuf);
@@ -1761,15 +1804,16 @@ GBool _AVCBinReadGetInfoFilename(const char *pszInfoPath,
  * If pszRetDatFile/pszRetNitFile != NULL then the .DAT and .NIT filename
  * without the info path will be copied to the specified buffers.
  **********************************************************************/
-GBool _AVCBinReadInfoFileExists(const char *pszInfoPath, 
+static
+GBool _AVCBinReadInfoFileExists(const char *pszInfoPath,
                                 const char *pszBasename,
                                 AVCCoverType eCoverType)
 {
 
-    return (_AVCBinReadGetInfoFilename(pszInfoPath, pszBasename, 
-                                       "dat", eCoverType, NULL) == TRUE &&
-            _AVCBinReadGetInfoFilename(pszInfoPath, pszBasename, 
-                                       "nit", eCoverType, NULL) == TRUE);
+    return (_AVCBinReadGetInfoFilename(pszInfoPath, pszBasename,
+                                       "dat", eCoverType, NULL, 0) == TRUE &&
+            _AVCBinReadGetInfoFilename(pszInfoPath, pszBasename,
+                                       "nit", eCoverType, NULL, 0) == TRUE);
 
 }
 
@@ -1806,32 +1850,32 @@ char **AVCBinReadListTables(const char *pszInfoPath, const char *pszCoverName,
     if (ppapszArcDatFiles)
         *ppapszArcDatFiles = NULL;
 
-    /*----------------------------------------------------------------- 
+    /*-----------------------------------------------------------------
      * For AVCCoverV7Tables type we do not look for tables for a specific
      * coverage, we return all tables from the info dir.
      *----------------------------------------------------------------*/
     if (eCoverType == AVCCoverV7Tables)
         pszCoverName = NULL;
 
-    /*----------------------------------------------------------------- 
+    /*-----------------------------------------------------------------
      * All tables that belong to a given coverage have their name starting
-     * with the coverage name (in uppercase letters), followed by a 3 
+     * with the coverage name (in uppercase letters), followed by a 3
      * letters extension.
      *----------------------------------------------------------------*/
     if (pszCoverName != NULL)
-        sprintf(szNameToFind, "%-.28s.", pszCoverName);
-    nLen = strlen(szNameToFind);
+        snprintf(szNameToFind, sizeof(szNameToFind), "%-.28s.", pszCoverName);
+    nLen = (int)strlen(szNameToFind);
 
-    /*----------------------------------------------------------------- 
+    /*-----------------------------------------------------------------
      * Open the arc.dir and add all entries that match the criteria
      * to our list.
      * In AVCCoverWeird, the file is called "arcdr9"
      *----------------------------------------------------------------*/
-    pszFname = (char*)CPLMalloc((strlen(pszInfoPath)+9)*sizeof(char));
+    pszFname = (char*)CPLMalloc(strlen(pszInfoPath)+9);
     if (eCoverType == AVCCoverWeird)
-        sprintf(pszFname, "%sarcdr9", pszInfoPath);
+        snprintf(pszFname, strlen(pszInfoPath)+9, "%sarcdr9", pszInfoPath);
     else
-        sprintf(pszFname, "%sarc.dir", pszInfoPath);
+        snprintf(pszFname, strlen(pszInfoPath)+9, "%sarc.dir", pszInfoPath);
 
     AVCAdjustCaseSensitiveFilename(pszFname);
 
@@ -1847,8 +1891,8 @@ char **AVCBinReadListTables(const char *pszInfoPath, const char *pszCoverName,
                 !sEntry.bDeletedFlag &&
                 (pszCoverName == NULL ||
                  EQUALN(szNameToFind, sEntry.szTableName, nLen)) &&
-                _AVCBinReadInfoFileExists(pszInfoPath, 
-                                          sEntry.szInfoFile, 
+                _AVCBinReadInfoFileExists(pszInfoPath,
+                                          sEntry.szInfoFile,
                                           eCoverType) )
             {
                 papszList = CSLAddString(papszList, sEntry.szTableName);
@@ -1879,7 +1923,7 @@ char **AVCBinReadListTables(const char *pszInfoPath, const char *pszCoverName,
  * Returns a valid AVCBinFile handle, or NULL if the file could
  * not be opened.
  *
- * _AVCBinReadCloseTable() will eventually have to be called to release the 
+ * _AVCBinReadCloseTable() will eventually have to be called to release the
  * resources used by the AVCBinFile structure.
  **********************************************************************/
 AVCBinFile *_AVCBinReadOpenTable(const char *pszInfoPath,
@@ -1894,18 +1938,22 @@ AVCBinFile *_AVCBinReadOpenTable(const char *pszInfoPath,
     char          *pszFname;
     GBool          bFound;
     int            i;
+    size_t         nFnameLen;
+
+    sTableDef.pasFieldDef = NULL;
 
     /* Alloc a buffer big enough for the longest possible filename...
      */
-    pszFname = (char*)CPLMalloc((strlen(pszInfoPath)+81)*sizeof(char));
+    nFnameLen = strlen(pszInfoPath)+81;
+    pszFname = (char*)CPLMalloc(nFnameLen);
 
     /*-----------------------------------------------------------------
      * Fetch info about this table from the "arc.dir"
      *----------------------------------------------------------------*/
     if (eCoverType == AVCCoverWeird)
-        sprintf(pszFname, "%sarcdr9", pszInfoPath);
+        snprintf(pszFname, nFnameLen, "%sarcdr9", pszInfoPath);
     else
-        sprintf(pszFname, "%sarc.dir", pszInfoPath);
+        snprintf(pszFname, nFnameLen, "%sarc.dir", pszInfoPath);
 
     AVCAdjustCaseSensitiveFilename(pszFname);
 
@@ -1918,10 +1966,9 @@ AVCBinFile *_AVCBinReadOpenTable(const char *pszInfoPath,
         while(!bFound && _AVCBinReadNextArcDir(hFile, &sTableDef) == 0)
         {
             if (!sTableDef.bDeletedFlag &&
-                EQUALN(sTableDef.szTableName, pszTableName, 
-                       strlen(pszTableName)) &&
-                _AVCBinReadInfoFileExists(pszInfoPath, 
-                                          sTableDef.szInfoFile, 
+                EQUALN(sTableDef.szTableName, pszTableName,
+                       strlen(pszTableName)) &&                _AVCBinReadInfoFileExists(pszInfoPath,
+                                          sTableDef.szInfoFile,
                                           eCoverType))
             {
                 bFound = TRUE;
@@ -1941,7 +1988,7 @@ AVCBinFile *_AVCBinReadOpenTable(const char *pszInfoPath,
     }
 
     /*-----------------------------------------------------------------
-     * Establish the location of the data file... depends on the 
+     * Establish the location of the data file... depends on the
      * szExternal[] field.
      *----------------------------------------------------------------*/
     if (EQUAL(sTableDef.szExternal, "XX"))
@@ -1951,9 +1998,9 @@ AVCBinFile *_AVCBinReadOpenTable(const char *pszInfoPath,
          * Read the path to the data file from the arc####.dat file
          *------------------------------------------------------------*/
         _AVCBinReadGetInfoFilename(pszInfoPath, sTableDef.szInfoFile,
-                                   "dat", eCoverType, pszFname);
+                                   "dat", eCoverType, pszFname, nFnameLen);
         AVCAdjustCaseSensitiveFilename(pszFname);
-    
+
         hFile = AVCRawBinOpen(pszFname, "r", AVC_COVER_BYTE_ORDER(eCoverType),
                               psDBCSInfo);
 
@@ -1964,7 +2011,7 @@ AVCBinFile *_AVCBinReadOpenTable(const char *pszInfoPath,
             AVCRawBinReadBytes(hFile, 80, (GByte *)sTableDef.szDataFile);
             sTableDef.szDataFile[80] = '\0';
 
-            for(i = strlen(sTableDef.szDataFile)-1;
+            for(i = (int)strlen(sTableDef.szDataFile)-1;
                 isspace((unsigned char)sTableDef.szDataFile[i]);
                 i--)
             {
@@ -1980,7 +2027,6 @@ AVCBinFile *_AVCBinReadOpenTable(const char *pszInfoPath,
             CPLFree(pszFname);
             return NULL;
         }
-         
     }
     else
     {
@@ -1989,15 +2035,15 @@ AVCBinFile *_AVCBinReadOpenTable(const char *pszInfoPath,
          * Note: sTableDef.szDataFile must be relative to info directory
          *------------------------------------------------------------*/
         _AVCBinReadGetInfoFilename(pszInfoPath, sTableDef.szInfoFile,
-                                   "dat", eCoverType, pszFname);
-        strcpy(sTableDef.szDataFile, pszFname+strlen(pszInfoPath));
+                                   "dat", eCoverType, pszFname, nFnameLen);
+        snprintf(sTableDef.szDataFile, sizeof(sTableDef.szDataFile), "%s", pszFname+strlen(pszInfoPath));
    }
 
     /*-----------------------------------------------------------------
      * Read the table field definitions from the "arc####.nit" file.
      *----------------------------------------------------------------*/
     _AVCBinReadGetInfoFilename(pszInfoPath, sTableDef.szInfoFile,
-                               "nit", eCoverType, pszFname);
+                               "nit", eCoverType, pszFname, nFnameLen);
     AVCAdjustCaseSensitiveFilename(pszFname);
 
     hFile = AVCRawBinOpen(pszFname, "r", AVC_COVER_BYTE_ORDER(eCoverType),
@@ -2058,12 +2104,12 @@ AVCBinFile *_AVCBinReadOpenTable(const char *pszInfoPath,
      * If the header says that table has 0 records, then we don't
      * try to open the file... but we don't consider that as an error.
      *----------------------------------------------------------------*/
-    if (sTableDef.numRecords > 0 && 
+    if (sTableDef.numRecords > 0 &&
         AVCFileExists(pszInfoPath, sTableDef.szDataFile))
     {
         VSIStatBuf      sStatBuf;
 
-        sprintf(pszFname, "%s%s", pszInfoPath, sTableDef.szDataFile);
+        snprintf(pszFname, nFnameLen, "%s%s", pszInfoPath, sTableDef.szDataFile);
         AVCAdjustCaseSensitiveFilename(pszFname);
 
         hFile = AVCRawBinOpen(pszFname, "r", AVC_COVER_BYTE_ORDER(eCoverType),
@@ -2080,7 +2126,7 @@ AVCBinFile *_AVCBinReadOpenTable(const char *pszInfoPath,
         }
 
         /*-------------------------------------------------------------
-         * In some cases, the number of records field for a table in the 
+         * In some cases, the number of records field for a table in the
          * arc.dir does not correspond to the real number of records
          * in the data file.  In this kind of situation, the number of
          * records returned by Arc/Info in an E00 file will be based
@@ -2093,7 +2139,7 @@ AVCBinFile *_AVCBinReadOpenTable(const char *pszInfoPath,
              sTableDef.nRecSize > 0 &&
              sStatBuf.st_size/sTableDef.nRecSize != sTableDef.numRecords)
         {
-            sTableDef.numRecords = sStatBuf.st_size/sTableDef.nRecSize;
+            sTableDef.numRecords = (int)(sStatBuf.st_size/sTableDef.nRecSize);
         }
 
     }
@@ -2137,7 +2183,7 @@ AVCBinFile *_AVCBinReadOpenTable(const char *pszInfoPath,
             pasFieldDef[i].nType1*10 == AVC_FT_FIXINT ||
             pasFieldDef[i].nType1*10 == AVC_FT_FIXNUM )
         {
-            psFile->cur.pasFields[i].pszStr = 
+            psFile->cur.pasFields[i].pszStr =
                 (GByte*)CPLCalloc(pasFieldDef[i].nSize+1, sizeof(char));
         }
     }
@@ -2152,15 +2198,16 @@ AVCBinFile *_AVCBinReadOpenTable(const char *pszInfoPath,
  * (This function is for internal library use... external calls should
  * go to AVCBinReadNextTableRec() instead)
  *
- * Reads the next record from an attribute table and fills the 
+ * Reads the next record from an attribute table and fills the
  * pasFields[] array.
  *
  * Note that it is assumed that the pasFields[] array has been properly
- * initialized, re the allocation of buffers for fields strored as
+ * initialized, re the allocation of buffers for fields stored as
  * strings.
  *
  * Returns 0 on success or -1 on error.
  **********************************************************************/
+static
 int _AVCBinReadNextTableRec(AVCRawBinFile *psFile, int nFields,
                             AVCFieldInfo *pasDef, AVCField *pasFields,
                             int nRecordSize)
@@ -2257,7 +2304,7 @@ void _AVCBinReadRepairDBFFieldName(char *pszFieldName);
  * Returns a valid AVCBinFile handle, or NULL if the file could
  * not be opened.
  *
- * _AVCBinReadCloseDBFTable() will eventually have to be called to release the 
+ * _AVCBinReadCloseDBFTable() will eventually have to be called to release the
  * resources used by the AVCBinFile structure.
  **********************************************************************/
 AVCBinFile *_AVCBinReadOpenDBFTable(const char *pszDBFFilename,
@@ -2293,7 +2340,7 @@ AVCBinFile *_AVCBinReadOpenDBFTable(const char *pszDBFFilename,
     psFile->hdr.psTableDef = NULL;
 
     /* nCurDBFRecord is used to keep track of the 0-based index of the
-     * last record we read from the DBF file... this is to emulate 
+     * last record we read from the DBF file... this is to emulate
      * sequential access which is assumed by the rest of the lib.
      * Since the first record (record 0) has not been read yet, then
      * we init the index at -1.
@@ -2312,12 +2359,12 @@ AVCBinFile *_AVCBinReadOpenDBFTable(const char *pszDBFFilename,
     psTableDef = (AVCTableDef*)CPLCalloc(1, sizeof(AVCTableDef));
     psFile->hdr.psTableDef = psTableDef;
 
-    sprintf(psTableDef->szTableName, "%-32.32s", pszArcInfoTableName);
+    snprintf(psTableDef->szTableName, sizeof(psTableDef->szTableName), "%-32.32s", pszArcInfoTableName);
 
-    psTableDef->numFields = DBFGetFieldCount(hDBFFile);
+    psTableDef->numFields = (GInt16)DBFGetFieldCount(hDBFFile);
 
     /* We'll compute nRecSize value when we read fields info later */
-    psTableDef->nRecSize = 0;  
+    psTableDef->nRecSize = 0;
 
     psTableDef->numRecords = DBFGetRecordCount(hDBFFile);
 
@@ -2353,7 +2400,7 @@ AVCBinFile *_AVCBinReadOpenDBFTable(const char *pszDBFFilename,
         pasFieldDef[iField].nFmtPrec = (GInt16)nDecimals;
 
         /* nIndex is the 1-based field index that we see in the E00 header */
-        pasFieldDef[iField].nIndex = iField+1;
+        pasFieldDef[iField].nIndex = (GInt16)(iField+1);
 
         if (cNativeType == 'F' || (cNativeType == 'N' && nDecimals > 0) )
         {
@@ -2374,9 +2421,9 @@ AVCBinFile *_AVCBinReadOpenDBFTable(const char *pszDBFFilename,
             pasFieldDef[iField].nSize = 4;
             pasFieldDef[iField].nFmtWidth = 5;  /* PC Arc/Info ignores the */
             pasFieldDef[iField].nFmtPrec = -1;  /* DBF width/precision     */
-        
+
             /*---------------------------------------------------------
-             * Some special integer fields need to have their names 
+             * Some special integer fields need to have their names
              * repaired because DBF does not support special characters.
              *--------------------------------------------------------*/
             _AVCBinReadRepairDBFFieldName(pasFieldDef[iField].szName);
@@ -2387,7 +2434,7 @@ AVCBinFile *_AVCBinReadOpenDBFTable(const char *pszDBFFilename,
              * DATE - Actually handled as a string internally
              *--------------------------------------------------------*/
             pasFieldDef[iField].nType1 = AVC_FT_DATE/10;
-            pasFieldDef[iField].nSize = nWidth;
+            pasFieldDef[iField].nSize = (GInt16)nWidth;
             pasFieldDef[iField].nFmtPrec = -1;
 
         }
@@ -2397,7 +2444,7 @@ AVCBinFile *_AVCBinReadOpenDBFTable(const char *pszDBFFilename,
              * CHAR STRINGS ... and all unknown types also handled as strings
              *--------------------------------------------------------*/
             pasFieldDef[iField].nType1 = AVC_FT_CHAR/10;
-            pasFieldDef[iField].nSize = nWidth;
+            pasFieldDef[iField].nSize = (GInt16)nWidth;
             pasFieldDef[iField].nFmtPrec = -1;
 
         }
@@ -2453,7 +2500,7 @@ AVCBinFile *_AVCBinReadOpenDBFTable(const char *pszDBFFilename,
             pasFieldDef[iField].nType1*10 == AVC_FT_FIXINT ||
             pasFieldDef[iField].nType1*10 == AVC_FT_FIXNUM )
         {
-            psFile->cur.pasFields[iField].pszStr = 
+            psFile->cur.pasFields[iField].pszStr =
                 (GByte*)CPLCalloc(pasFieldDef[iField].nSize+1, sizeof(GByte));
         }
     }
@@ -2468,7 +2515,7 @@ AVCBinFile *_AVCBinReadOpenDBFTable(const char *pszDBFFilename,
  * (This function is for internal library use... external calls should
  * go to AVCBinReadNextTableRec() instead)
  *
- * Reads the next record from a AVCCoverPC DBF attribute table and fills the 
+ * Reads the next record from a AVCCoverPC DBF attribute table and fills the
  * pasFields[] array.
  *
  * Note that it is assumed that the pasFields[] array has been properly
@@ -2477,7 +2524,8 @@ AVCBinFile *_AVCBinReadOpenDBFTable(const char *pszDBFFilename,
  *
  * Returns 0 on success or -1 on error.
  **********************************************************************/
-int _AVCBinReadNextDBFTableRec(DBFHandle hDBFFile, int *piRecordIndex, 
+static
+int _AVCBinReadNextDBFTableRec(DBFHandle hDBFFile, int *piRecordIndex,
                                       int nFields, AVCFieldInfo *pasDef,
                                       AVCField *pasFields)
 {
@@ -2486,10 +2534,10 @@ int _AVCBinReadNextDBFTableRec(DBFHandle hDBFFile, int *piRecordIndex,
     /*-----------------------------------------------------------------
      * Increment current record index.
      * We use nCurDBFRecord to keep track of the 0-based index of the
-     * last record we read from the DBF file... this is to emulate 
+     * last record we read from the DBF file... this is to emulate
      * sequential access which is assumed by the rest of the lib.
      *----------------------------------------------------------------*/
-    if (hDBFFile == NULL || piRecordIndex == NULL || 
+    if (hDBFFile == NULL || piRecordIndex == NULL ||
         pasDef == NULL || pasFields == NULL)
         return -1;
 
@@ -2512,7 +2560,7 @@ int _AVCBinReadNextDBFTableRec(DBFHandle hDBFFile, int *piRecordIndex,
              * Values stored as strings
              *--------------------------------------------------------*/
             const char *pszValue;
-            pszValue = DBFReadStringAttribute(hDBFFile, 
+            pszValue = DBFReadStringAttribute(hDBFFile,
                                               *piRecordIndex, i);
             strncpy((char*)pasFields[i].pszStr, pszValue, pasDef[i].nSize);
             pasFields[i].pszStr[pasDef[i].nSize] = '\0';
@@ -2522,7 +2570,7 @@ int _AVCBinReadNextDBFTableRec(DBFHandle hDBFFile, int *piRecordIndex,
             /*---------------------------------------------------------
              * 32 bit binary integers
              *--------------------------------------------------------*/
-            pasFields[i].nInt32 = DBFReadIntegerAttribute(hDBFFile, 
+            pasFields[i].nInt32 = DBFReadIntegerAttribute(hDBFFile,
                                                           *piRecordIndex, i);
         }
         else if (nType == AVC_FT_BININT && pasDef[i].nSize == 2)
@@ -2530,7 +2578,7 @@ int _AVCBinReadNextDBFTableRec(DBFHandle hDBFFile, int *piRecordIndex,
             /*---------------------------------------------------------
              * 16 bit binary integers
              *--------------------------------------------------------*/
-            pasFields[i].nInt16 = (GInt16)DBFReadIntegerAttribute(hDBFFile, 
+            pasFields[i].nInt16 = (GInt16)DBFReadIntegerAttribute(hDBFFile,
                                                                *piRecordIndex,
                                                                   i);
         }
@@ -2539,7 +2587,7 @@ int _AVCBinReadNextDBFTableRec(DBFHandle hDBFFile, int *piRecordIndex,
             /*---------------------------------------------------------
              * Single precision floats
              *--------------------------------------------------------*/
-            pasFields[i].fFloat = (float)DBFReadDoubleAttribute(hDBFFile, 
+            pasFields[i].fFloat = (float)DBFReadDoubleAttribute(hDBFFile,
                                                                 *piRecordIndex,
                                                                 i);
         }
@@ -2548,7 +2596,7 @@ int _AVCBinReadNextDBFTableRec(DBFHandle hDBFFile, int *piRecordIndex,
             /*---------------------------------------------------------
              * Double precision floats
              *--------------------------------------------------------*/
-            pasFields[i].dDouble = DBFReadDoubleAttribute(hDBFFile, 
+            pasFields[i].dDouble = DBFReadDoubleAttribute(hDBFFile,
                                                           *piRecordIndex,
                                                           i);
         }
diff --git a/ogr/ogrsf_frmts/avc/avc_binwr.c b/ogr/ogrsf_frmts/avc/avc_binwr.c
index 4f69f2d..07125b5 100644
--- a/ogr/ogrsf_frmts/avc/avc_binwr.c
+++ b/ogr/ogrsf_frmts/avc/avc_binwr.c
@@ -15,16 +15,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -89,6 +89,8 @@
 
 #include "avc.h"
 
+CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused) {}
+
 #include <ctype.h>  /* tolower() */
 
 /*=====================================================================
@@ -97,11 +99,11 @@
 
 static void    _AVCBinWriteCloseTable(AVCBinFile *psFile);
 
-static AVCBinFile *_AVCBinWriteCreateDBFTable(const char *pszPath, 
+static AVCBinFile *_AVCBinWriteCreateDBFTable(const char *pszPath,
                                               const char *pszCoverName,
                                               AVCTableDef *psSrcTableDef,
                                               AVCCoverType eCoverType,
-                                              int nPrecision, 
+                                              int nPrecision,
                                               AVCDBCSInfo *psDBCSInfo);
 
 /**********************************************************************
@@ -114,16 +116,16 @@ static AVCBinFile *_AVCBinWriteCreateDBFTable(const char *pszPath,
  *         a '/' or a '\\'
  * pszName is the name of the file to create relative to this directory.
  *
- * Note: For most file types except tables, passing pszPath="" and 
+ * Note: For most file types except tables, passing pszPath="" and
  * including the coverage path as part of pszName instead would work.
  *
  * Returns a valid AVCBinFile handle, or NULL if the file could
  * not be created.
  *
- * AVCBinClose() will eventually have to be called to release the 
+ * AVCBinClose() will eventually have to be called to release the
  * resources used by the AVCBinFile structure.
  **********************************************************************/
-AVCBinFile *AVCBinWriteCreate(const char *pszPath, const char *pszName, 
+AVCBinFile *AVCBinWriteCreate(const char *pszPath, const char *pszName,
                               AVCCoverType eCoverType,
                               AVCFileType eType, int nPrecision,
                               AVCDBCSInfo *psDBCSInfo)
@@ -164,9 +166,8 @@ AVCBinFile *AVCBinWriteCreate(const char *pszPath, const char *pszName,
     psFile->eFileType = eType;
     psFile->nPrecision = nPrecision;
 
-    psFile->pszFilename = (char*)CPLMalloc((strlen(pszPath)+strlen(pszName)+1)*
-                                           sizeof(char));
-    sprintf(psFile->pszFilename, "%s%s", pszPath, pszName);
+    psFile->pszFilename = (char*)CPLMalloc(strlen(pszPath)+strlen(pszName)+1);
+    snprintf(psFile->pszFilename, strlen(pszPath)+strlen(pszName)+1, "%s%s", pszPath, pszName);
 
     psFile->eCoverType = eCoverType;
 
@@ -204,33 +205,33 @@ AVCBinFile *AVCBinWriteCreate(const char *pszPath, const char *pszName,
      * For each type there is 3 possibilities, e.g. "pal", "pal.adf", "ttt.pal"
      *----------------------------------------------------------------*/
     pszFname = CPLStrdup(psFile->pszFilename);
-    nLen = strlen(pszFname);
+    nLen = (int)strlen(pszFname);
     if (eType == AVCFileARC &&
-        ( (nLen>=3 && EQUALN((pszExt=pszFname+nLen-3), "arc", 3)) ||
-          (nLen>=7 && EQUALN((pszExt=pszFname+nLen-7), "arc.adf", 7)) ) )
+        ( (nLen>=3 && STARTS_WITH_CI((pszExt=pszFname+nLen-3), "arc")) ||
+          (nLen>=7 && STARTS_WITH_CI((pszExt=pszFname+nLen-7), "arc.adf")) ) )
     {
-        strncpy(pszExt, "arx", 3);
+        memcpy(pszExt, "arx", 3);
         bCreateIndex = TRUE;
     }
     else if ((eType == AVCFilePAL || eType == AVCFileRPL) &&
-             ( (nLen>=3 && EQUALN((pszExt=pszFname+nLen-3), "pal", 3)) ||
-               (nLen>=7 && EQUALN((pszExt=pszFname+nLen-7), "pal.adf", 7)) ) )
+             ( (nLen>=3 && STARTS_WITH_CI((pszExt=pszFname+nLen-3), "pal")) ||
+               (nLen>=7 && STARTS_WITH_CI((pszExt=pszFname+nLen-7), "pal.adf")) ) )
     {
-        strncpy(pszExt, "pax", 3);
+        memcpy(pszExt, "pax", 3);
         bCreateIndex = TRUE;
     }
     else if (eType == AVCFileCNT &&
-             ( (nLen>=3 && EQUALN((pszExt=pszFname+nLen-3), "cnt", 3)) ||
-               (nLen>=7 && EQUALN((pszExt=pszFname+nLen-7), "cnt.adf", 7)) ) )
+             ( (nLen>=3 && STARTS_WITH_CI((pszExt=pszFname+nLen-3), "cnt")) ||
+               (nLen>=7 && STARTS_WITH_CI((pszExt=pszFname+nLen-7), "cnt.adf")) ) )
     {
-        strncpy(pszExt, "cnx", 3);
+        memcpy(pszExt, "cnx", 3);
         bCreateIndex = TRUE;
     }
     else if ((eType == AVCFileTXT || eType == AVCFileTX6) &&
-             ( (nLen>=3 && EQUALN((pszExt=pszFname+nLen-3), "txt", 3)) ||
-               (nLen>=7 && EQUALN((pszExt=pszFname+nLen-7), "txt.adf", 7)) ) )
+             ( (nLen>=3 && STARTS_WITH_CI((pszExt=pszFname+nLen-3), "txt")) ||
+               (nLen>=7 && STARTS_WITH_CI((pszExt=pszFname+nLen-7), "txt.adf")) ) )
     {
-        strncpy(pszExt, "txx", 3);
+        memcpy(pszExt, "txx", 3);
         bCreateIndex = TRUE;
     }
 
@@ -274,6 +275,7 @@ AVCBinFile *AVCBinWriteCreate(const char *pszPath, const char *pszName,
  *
  * Returns 0 on success or -1 on error.
  **********************************************************************/
+static
 int _AVCBinWriteHeader(AVCRawBinFile *psFile, AVCBinHeader *psHeader,
                        AVCCoverType eCoverType)
 {
@@ -391,7 +393,7 @@ int AVCBinWriteHeader(AVCBinFile *psFile)
 /**********************************************************************
  *                          AVCBinWriteClose()
  *
- * Close a coverage file opened for wirting, and release all memory 
+ * Close a coverage file opened for writing, and release all memory
  * (object strcut., buffers, etc.) associated with this file.
  **********************************************************************/
 
@@ -404,7 +406,7 @@ void    AVCBinWriteClose(AVCBinFile *psFile)
     }
 
     /*-----------------------------------------------------------------
-     * Write the file size (nbr of 2 byte words) in the header at 
+     * Write the file size (nbr of 2 byte words) in the header at
      * byte 24 in the 100 byte header (only if applicable)
      * (And write the same value at byte 2-5 in the first header of PC Cover)
      *----------------------------------------------------------------*/
@@ -416,7 +418,7 @@ void    AVCBinWriteClose(AVCBinFile *psFile)
          psFile->eFileType == AVCFileCNT ||
          psFile->eFileType == AVCFileTXT ||
          psFile->eFileType == AVCFileTX6 ||
-         (psFile->eFileType == AVCFileTOL && 
+         (psFile->eFileType == AVCFileTOL &&
           psFile->nPrecision == AVC_DOUBLE_PREC) ) )
     {
         GInt32 n32Size;
@@ -427,29 +429,29 @@ void    AVCBinWriteClose(AVCBinFile *psFile)
             /* PC Cover... Pad to multiple of 512 bytes and write 2 headers
              * extra bytes at EOF are not included in the size written in
              * header.
-             * The first 256 bytes header is not counted in the file size 
+             * The first 256 bytes header is not counted in the file size
              * written in both headers
              */
             n32Size -= 128;  /* minus 256 bytes */
 
             if (psFile->psRawBinFile->nCurPos%512 != 0)
-                AVCRawBinWriteZeros(psFile->psRawBinFile, 
+                AVCRawBinWriteZeros(psFile->psRawBinFile,
                                     512 - psFile->psRawBinFile->nCurPos%512);
-                
-            VSIFSeek(psFile->psRawBinFile->fp, 2, SEEK_SET);
+
+            CPL_IGNORE_RET_VAL_INT(VSIFSeek(psFile->psRawBinFile->fp, 2, SEEK_SET));
             AVCRawBinWriteInt32(psFile->psRawBinFile, n32Size);
 
-            VSIFSeek(psFile->psRawBinFile->fp, 256+24, SEEK_SET);
+            CPL_IGNORE_RET_VAL_INT(VSIFSeek(psFile->psRawBinFile->fp, 256+24, SEEK_SET));
             AVCRawBinWriteInt32(psFile->psRawBinFile, n32Size);
         }
         else
         {
             /* V7 Cover ... only 1 header */
-            VSIFSeek(psFile->psRawBinFile->fp, 24, SEEK_SET);
+            CPL_IGNORE_RET_VAL_INT(VSIFSeek(psFile->psRawBinFile->fp, 24, SEEK_SET));
             AVCRawBinWriteInt32(psFile->psRawBinFile, n32Size);
         }
     }
-        
+
     AVCRawBinClose(psFile->psRawBinFile);
     psFile->psRawBinFile = NULL;
 
@@ -470,19 +472,19 @@ void    AVCBinWriteClose(AVCBinFile *psFile)
             n32Size -= 128;  /* minus 256 bytes */
 
             if (psFile->psIndexFile->nCurPos%512 != 0)
-                AVCRawBinWriteZeros(psFile->psIndexFile, 
+                AVCRawBinWriteZeros(psFile->psIndexFile,
                                     512 - psFile->psIndexFile->nCurPos%512);
-                
-            VSIFSeek(psFile->psIndexFile->fp, 2, SEEK_SET);
+
+            CPL_IGNORE_RET_VAL_INT(VSIFSeek(psFile->psIndexFile->fp, 2, SEEK_SET));
             AVCRawBinWriteInt32(psFile->psIndexFile, n32Size);
 
-            VSIFSeek(psFile->psIndexFile->fp, 256+24, SEEK_SET);
+            CPL_IGNORE_RET_VAL_INT(VSIFSeek(psFile->psIndexFile->fp, 256+24, SEEK_SET));
             AVCRawBinWriteInt32(psFile->psIndexFile, n32Size);
         }
         else
         {
             /* V7 Cover ... only 1 header */
-            VSIFSeek(psFile->psIndexFile->fp, 24, SEEK_SET);
+            CPL_IGNORE_RET_VAL_INT(VSIFSeek(psFile->psIndexFile->fp, 24, SEEK_SET));
             AVCRawBinWriteInt32(psFile->psIndexFile, n32Size);
         }
 
@@ -510,7 +512,8 @@ void    AVCBinWriteClose(AVCBinFile *psFile)
  *
  * Returns 0 on success or -1 on error.
  **********************************************************************/
-int _AVCBinWriteIndexEntry(AVCRawBinFile *psFile, 
+static
+int _AVCBinWriteIndexEntry(AVCRawBinFile *psFile,
                            int nPosition, int nSize)
 {
     AVCRawBinWriteInt32(psFile, nPosition);
@@ -525,7 +528,7 @@ int _AVCBinWriteIndexEntry(AVCRawBinFile *psFile,
 /**********************************************************************
  *                          AVCBinWriteObject()
  *
- * Write a CNT (Polygon Centroid) structure to the fin object to a 
+ * Write a CNT (Polygon Centroid) structure to the fin object to a
  * coverage file.
  *
  * Simply redirects the call to the right function based on the value
@@ -593,11 +596,12 @@ int AVCBinWriteObject(AVCBinFile *psFile, void *psObj)
  * Write an Arc structure to the file.
  *
  * The contents of the psArc structure is assumed to be valid... this
- * function performs no validation on the consistency of what it is 
+ * function performs no validation on the consistency of what it is
  * given as input.
  *
  * Returns 0 on success or -1 on error.
  **********************************************************************/
+static
 int _AVCBinWriteArc(AVCRawBinFile *psFile, AVCArc *psArc,
                     int nPrecision, AVCRawBinFile *psIndexFile)
 {
@@ -613,7 +617,7 @@ int _AVCBinWriteArc(AVCRawBinFile *psFile, AVCArc *psArc,
      * Record size is expressed in 2 byte words, and does not count the
      * first 8 bytes of the ARC entry.
      *----------------------------------------------------------------*/
-    nRecSize = (6 * 4 + psArc->numVertices*2 * 
+    nRecSize = (6 * 4 + psArc->numVertices*2 *
                 ((nPrecision == AVC_SINGLE_PREC)? 4 : 8)) / 2;
     AVCRawBinWriteInt32(psFile, nRecSize);
     AVCRawBinWriteInt32(psFile, psArc->nUserId);
@@ -661,7 +665,7 @@ int _AVCBinWriteArc(AVCRawBinFile *psFile, AVCArc *psArc,
  * Write the next Arc structure to the file.
  *
  * The contents of the psArc structure is assumed to be valid... this
- * function performs no validation on the consistency of what it is 
+ * function performs no validation on the consistency of what it is
  * given as input.
  *
  * Returns 0 on success or -1 on error.
@@ -692,12 +696,13 @@ int AVCBinWriteArc(AVCBinFile *psFile, AVCArc *psArc)
  * Write a PAL (Polygon Arc List) structure to the file.
  *
  * The contents of the psPal structure is assumed to be valid... this
- * function performs no validation on the consistency of what it is 
+ * function performs no validation on the consistency of what it is
  * given as input.
  *
  * Returns 0 on success or -1 on error.
  **********************************************************************/
-int _AVCBinWritePal(AVCRawBinFile *psFile, AVCPal *psPal, 
+static
+int _AVCBinWritePal(AVCRawBinFile *psFile, AVCPal *psPal,
                     int nPrecision, AVCRawBinFile *psIndexFile)
 {
     int i, nRecSize, nCurPos;
@@ -712,7 +717,7 @@ int _AVCBinWritePal(AVCRawBinFile *psFile, AVCPal *psPal,
      * Record size is expressed in 2 byte words, and does not count the
      * first 8 bytes of the PAL entry.
      *----------------------------------------------------------------*/
-    nRecSize = ( 4 + psPal->numArcs*3 * 4 + 
+    nRecSize = ( 4 + psPal->numArcs*3 * 4 +
                 4 * ((nPrecision == AVC_SINGLE_PREC)? 4 : 8)) / 2;
 
     AVCRawBinWriteInt32(psFile, nRecSize);
@@ -761,7 +766,7 @@ int _AVCBinWritePal(AVCRawBinFile *psFile, AVCPal *psPal,
  * Write a PAL (Polygon Arc List) structure to the file.
  *
  * The contents of the psPal structure is assumed to be valid... this
- * function performs no validation on the consistency of what it is 
+ * function performs no validation on the consistency of what it is
  * given as input.
  *
  * Returns 0 on success or -1 on error.
@@ -792,7 +797,8 @@ int AVCBinWritePal(AVCBinFile *psFile, AVCPal *psPal)
  *
  * Returns 0 on success or -1 on error.
  **********************************************************************/
-int _AVCBinWriteCnt(AVCRawBinFile *psFile, AVCCnt *psCnt, 
+static
+int _AVCBinWriteCnt(AVCRawBinFile *psFile, AVCCnt *psCnt,
                               int nPrecision, AVCRawBinFile *psIndexFile)
 {
     int i, nRecSize, nCurPos;
@@ -807,7 +813,7 @@ int _AVCBinWriteCnt(AVCRawBinFile *psFile, AVCCnt *psCnt,
      * Record size is expressed in 2 byte words, and does not count the
      * first 8 bytes of the CNT entry.
      *----------------------------------------------------------------*/
-    nRecSize = ( 4 + psCnt->numLabels * 4 + 
+    nRecSize = ( 4 + psCnt->numLabels * 4 +
                  2 * ((nPrecision == AVC_SINGLE_PREC)? 4 : 8)) / 2;
 
     AVCRawBinWriteInt32(psFile, nRecSize);
@@ -850,7 +856,7 @@ int _AVCBinWriteCnt(AVCRawBinFile *psFile, AVCCnt *psCnt,
  * Write a CNT (Polygon Centroid) structure to the file.
  *
  * The contents of the psCnt structure is assumed to be valid... this
- * function performs no validation on the consistency of what it is 
+ * function performs no validation on the consistency of what it is
  * given as input.
  *
  * Returns 0 on success or -1 on error.
@@ -880,12 +886,13 @@ int AVCBinWriteCnt(AVCBinFile *psFile, AVCCnt *psCnt)
  * Write a LAB (Centroid Label) structure to the file.
  *
  * The contents of the psLab structure is assumed to be valid... this
- * function performs no validation on the consistency of what it is 
+ * function performs no validation on the consistency of what it is
  * given as input.
  *
  * Returns 0 on success or -1 on error.
  **********************************************************************/
-int _AVCBinWriteLab(AVCRawBinFile *psFile, AVCLab *psLab, 
+static
+int _AVCBinWriteLab(AVCRawBinFile *psFile, AVCLab *psLab,
                     int nPrecision)
 {
 
@@ -927,7 +934,7 @@ int _AVCBinWriteLab(AVCRawBinFile *psFile, AVCLab *psLab,
  * Write a LAB (Centroid Label) structure to the file.
  *
  * The contents of the psLab structure is assumed to be valid... this
- * function performs no validation on the consistency of what it is 
+ * function performs no validation on the consistency of what it is
  * given as input.
  *
  * Returns 0 on success or -1 on error.
@@ -957,12 +964,13 @@ int AVCBinWriteLab(AVCBinFile *psFile, AVCLab *psLab)
  * Write a TOL (tolerance) structure to the file.
  *
  * The contents of the psTol structure is assumed to be valid... this
- * function performs no validation on the consistency of what it is 
+ * function performs no validation on the consistency of what it is
  * given as input.
  *
  * Returns 0 on success or -1 on error.
  **********************************************************************/
-int _AVCBinWriteTol(AVCRawBinFile *psFile, AVCTol *psTol, 
+static
+int _AVCBinWriteTol(AVCRawBinFile *psFile, AVCTol *psTol,
                     int nPrecision)
 {
 
@@ -993,7 +1001,7 @@ int _AVCBinWriteTol(AVCRawBinFile *psFile, AVCTol *psTol,
  * Write a TOL (tolerance) structure to the file.
  *
  * The contents of the psTol structure is assumed to be valid... this
- * function performs no validation on the consistency of what it is 
+ * function performs no validation on the consistency of what it is
  * given as input.
  *
  * Returns 0 on success or -1 on error.
@@ -1020,12 +1028,12 @@ int AVCBinWriteTol(AVCBinFile *psFile, AVCTol *psTol)
  * Write a PRJ (Projection info) to the file.
  *
  * Since a PRJ file is a simple text file and there is only ONE projection
- * info per prj.adf file, this function behaves differently from the 
+ * info per prj.adf file, this function behaves differently from the
  * other ones... all the job is done here, including creating and closing
  * the output file.
  *
  * The contents of the papszPrj is assumed to be valid... this
- * function performs no validation on the consistency of what it is 
+ * function performs no validation on the consistency of what it is
  * given as input.
  *
  * Returns 0 on success or -1 on error.
@@ -1060,12 +1068,13 @@ int AVCBinWritePrj(AVCBinFile *psFile, char **papszPrj)
  * Write a TXT/TX6/TX7 (Annotation) structure to the file.
  *
  * The contents of the psTxt structure is assumed to be valid... this
- * function performs no validation on the consistency of what it is 
+ * function performs no validation on the consistency of what it is
  * given as input.
  *
  * Returns 0 on success or -1 on error.
  **********************************************************************/
-int _AVCBinWriteTxt(AVCRawBinFile *psFile, AVCTxt *psTxt, 
+static
+int _AVCBinWriteTxt(AVCRawBinFile *psFile, AVCTxt *psTxt,
                               int nPrecision, AVCRawBinFile *psIndexFile)
 {
     int i, nRecSize, nCurPos, nStrLen, numVertices;
@@ -1082,12 +1091,12 @@ int _AVCBinWriteTxt(AVCRawBinFile *psFile, AVCTxt *psTxt,
      *----------------------------------------------------------------*/
     /* String uses a multiple of 4 bytes of storage */
     if (psTxt->pszText)
-        nStrLen = ((strlen((char*)psTxt->pszText) + 3)/4)*4;
+        nStrLen = (((int)strlen((char*)psTxt->pszText) + 3)/4)*4;
     else
         nStrLen = 0;
 
     numVertices = ABS(psTxt->numVerticesLine) + ABS(psTxt->numVerticesArrow);
-    nRecSize = (112 + 8 + nStrLen + 
+    nRecSize = (112 + 8 + nStrLen +
                 (numVertices*2+3)* ((nPrecision == AVC_SINGLE_PREC)?4:8)) / 2;
 
     AVCRawBinWriteInt32(psFile, nRecSize);
@@ -1168,13 +1177,14 @@ int _AVCBinWriteTxt(AVCRawBinFile *psFile, AVCTxt *psTxt,
  * Write a TXT (Annotation) structure to a AVCCoverPC file.
  *
  * The contents of the psTxt structure is assumed to be valid... this
- * function performs no validation on the consistency of what it is 
+ * function performs no validation on the consistency of what it is
  * given as input.
  *
  * This function assumes that PC Coverages are always single precision.
  *
  * Returns 0 on success or -1 on error.
  **********************************************************************/
+static
 int _AVCBinWritePCCoverageTxt(AVCRawBinFile *psFile, AVCTxt *psTxt,
                               CPL_UNUSED int nPrecision,
                               AVCRawBinFile *psIndexFile)
@@ -1194,11 +1204,11 @@ int _AVCBinWritePCCoverageTxt(AVCRawBinFile *psFile, AVCTxt *psTxt,
      * first 8 bytes of the TXT entry.
      *----------------------------------------------------------------*/
     /* String uses a multiple of 4 bytes of storage,
-     * And if text is already a multiple of 4 bytes then we include 4 extra 
+     * And if text is already a multiple of 4 bytes then we include 4 extra
      * spaces anyways (was probably a bug in the software!).
      */
     if (psTxt->pszText)
-        nStrLen = ((strlen((char*)psTxt->pszText) + 4)/4)*4;
+        nStrLen = (((int)strlen((char*)psTxt->pszText) + 4)/4)*4;
     else
         nStrLen = 4;
 
@@ -1233,7 +1243,7 @@ int _AVCBinWritePCCoverageTxt(AVCRawBinFile *psFile, AVCTxt *psTxt,
     AVCRawBinWriteInt32(psFile, psTxt->numChars );
 
     if (nStrLen > 0)
-        AVCRawBinWritePaddedString(psFile, nStrLen, psTxt->pszText);
+        AVCRawBinWritePaddedString(psFile, nStrLen, psTxt->pszText ? psTxt->pszText : (const GByte*)"    ");
 
     /*-----------------------------------------------------------------
      * Write index entry (cnx.adf)
@@ -1256,7 +1266,7 @@ int _AVCBinWritePCCoverageTxt(AVCRawBinFile *psFile, AVCTxt *psTxt,
  * Write a TXT/TX6/TX7 (Annotation) structure to the file.
  *
  * The contents of the psTxt structure is assumed to be valid... this
- * function performs no validation on the consistency of what it is 
+ * function performs no validation on the consistency of what it is
  * given as input.
  *
  * Returns 0 on success or -1 on error.
@@ -1271,11 +1281,11 @@ int AVCBinWriteTxt(AVCBinFile *psFile, AVCTxt *psTxt)
 
     /* AVCCoverPC and AVCCoverWeird have a different TXT format than AVCCoverV7
      */
-    if (psFile->eCoverType == AVCCoverPC || 
+    if (psFile->eCoverType == AVCCoverPC ||
         psFile->eCoverType == AVCCoverWeird)
     {
         return _AVCBinWritePCCoverageTxt(psFile->psRawBinFile, psTxt,
-                                         psFile->nPrecision, 
+                                         psFile->nPrecision,
                                          psFile->psIndexFile);
     }
     else
@@ -1298,11 +1308,12 @@ int AVCBinWriteTxt(AVCBinFile *psFile, AVCTxt *psTxt)
  * Write a RXP (Region something...) structure to the file.
  *
  * The contents of the psRxp structure is assumed to be valid... this
- * function performs no validation on the consistency of what it is 
+ * function performs no validation on the consistency of what it is
  * given as input.
  *
  * Returns 0 on success or -1 on error.
  **********************************************************************/
+static
 int _AVCBinWriteRxp(AVCRawBinFile *psFile,
                     AVCRxp *psRxp,
                     CPL_UNUSED int nPrecision)
@@ -1326,7 +1337,7 @@ int _AVCBinWriteRxp(AVCRawBinFile *psFile,
  * Write a  RXP (Region something...) structure to the file.
  *
  * The contents of the psRxp structure is assumed to be valid... this
- * function performs no validation on the consistency of what it is 
+ * function performs no validation on the consistency of what it is
  * given as input.
  *
  * Returns 0 on success or -1 on error.
@@ -1357,11 +1368,12 @@ int AVCBinWriteRxp(AVCBinFile *psFile, AVCRxp *psRxp)
  * Write an ARC.DIR entry at the current position in file.
  *
  * The contents of the psTableDef structure is assumed to be valid... this
- * function performs no validation on the consistency of what it is 
+ * function performs no validation on the consistency of what it is
  * given as input.
  *
  * Returns 0 on success or -1 on error.
  **********************************************************************/
+static
 int _AVCBinWriteArcDir(AVCRawBinFile *psFile, AVCTableDef *psTableDef)
 {
     /* STRING values MUST be padded with spaces.
@@ -1408,11 +1420,12 @@ int _AVCBinWriteArcDir(AVCRawBinFile *psFile, AVCTableDef *psTableDef)
  * Write an ARC####.NIT entry at the current position in file.
  *
  * The contents of the psTableDef structure is assumed to be valid... this
- * function performs no validation on the consistency of what it is 
+ * function performs no validation on the consistency of what it is
  * given as input.
  *
  * Returns 0 on success or -1 on error.
  **********************************************************************/
+static
 int _AVCBinWriteArcNit(AVCRawBinFile *psFile, AVCFieldInfo *psField)
 {
     /* STRING values MUST be padded with spaces.
@@ -1460,7 +1473,7 @@ int _AVCBinWriteArcNit(AVCRawBinFile *psFile, AVCFieldInfo *psField)
  *
  * Note: there could be a problem if 2 processes try to add an entry
  * at the exact same time... does Arc/Info do any locking on that file???
- * 
+ *
  * Returns an integer value corresponding to the new table index (ARC####)
  * or -1 if something failed.
  **********************************************************************/
@@ -1469,8 +1482,9 @@ int _AVCBinWriteArcNit(AVCRawBinFile *psFile, AVCFieldInfo *psField)
  */
 int _AVCBinReadNextArcDir(AVCRawBinFile *psFile, AVCTableDef *psArcDir);
 
+static
 int _AVCBinWriteCreateArcDirEntry(const char *pszArcDirFile,
-                                  AVCTableDef *psTableDef, 
+                                  AVCTableDef *psTableDef,
                                   AVCDBCSInfo *psDBCSInfo)
 {
     int          iEntry, numDirEntries=0, nTableIndex = 0;
@@ -1486,14 +1500,14 @@ int _AVCBinWriteCreateArcDirEntry(const char *pszArcDirFile,
     /*-----------------------------------------------------------------
      * Note, DM, 20010507 - We used to use VSIFStat() to establish the
      * size of arc.dir, but when working on a WinNT4 networked drive, the
-     * stat() information was not always right, and we sometimes ended 
+     * stat() information was not always right, and we sometimes ended
      * up overwriting arc.dir entries.  The solution: open and scan arc.dir
-     * until EOF to establish its size.  
-     * That trick also seems to fix another network buffer problem: when 
+     * until EOF to establish its size.
+     * That trick also seems to fix another network buffer problem: when
      * writing a coverage in a new empty dir (with no info dir yet), we
-     * would get an error in fwrite() while writing the 3rd arc.dir 
-     * entry of the coverage.  That second problem could also have been 
-     * fixed by forcing a VSIFSeek() before the first fwrite()... we've 
+     * would get an error in fwrite() while writing the 3rd arc.dir
+     * entry of the coverage.  That second problem could also have been
+     * fixed by forcing a VSIFSeek() before the first fwrite()... we've
      * added it below.
      *----------------------------------------------------------------*/
     FILE *fp;
@@ -1510,12 +1524,12 @@ int _AVCBinWriteCreateArcDirEntry(const char *pszArcDirFile,
                                     AVC_COVER_BYTE_ORDER(AVCCoverV7),
                                     psDBCSInfo);
     }
-    else 
+    else
 #endif
     /* On Unix we can still use fstat() */
     if ( VSIStat(pszArcDirFile, &sStatBuf) != -1 )
     {
-        numDirEntries = sStatBuf.st_size/380;
+        numDirEntries = (int)(sStatBuf.st_size/380);
         hRawBinFile = AVCRawBinOpen(pszArcDirFile, "r+",
                                     AVC_COVER_BYTE_ORDER(AVCCoverV7),
                                     psDBCSInfo);
@@ -1523,8 +1537,8 @@ int _AVCBinWriteCreateArcDirEntry(const char *pszArcDirFile,
     else
     {
         numDirEntries = 0;
-        hRawBinFile = AVCRawBinOpen(pszArcDirFile, "w", 
-                                    AVC_COVER_BYTE_ORDER(AVCCoverV7), 
+        hRawBinFile = AVCRawBinOpen(pszArcDirFile, "w",
+                                    AVC_COVER_BYTE_ORDER(AVCCoverV7),
                                     psDBCSInfo);
     }
 
@@ -1536,8 +1550,8 @@ int _AVCBinWriteCreateArcDirEntry(const char *pszArcDirFile,
         return -1;
     }
 
-    /* Init nTableIndex at -1 so that first table created should have 
-     * index 0 
+    /* Init nTableIndex at -1 so that first table created should have
+     * index 0
      */
     nTableIndex = -1;
     iEntry = 0;
@@ -1546,9 +1560,8 @@ int _AVCBinWriteCreateArcDirEntry(const char *pszArcDirFile,
           _AVCBinReadNextArcDir(hRawBinFile, &sEntry) == 0)
     {
         nTableIndex = atoi(sEntry.szInfoFile+3);
-        if (EQUALN(psTableDef->szTableName, sEntry.szTableName, 
-                   strlen(psTableDef->szTableName)))
-        {   
+        if (EQUALN(psTableDef->szTableName, sEntry.szTableName,
+                   strlen(psTableDef->szTableName)))        {
             bFound = TRUE;
             break;
         }
@@ -1563,21 +1576,21 @@ int _AVCBinWriteCreateArcDirEntry(const char *pszArcDirFile,
      * ARC.DIR does not have a header and we will close it right away.
      *----------------------------------------------------------------*/
     if (bFound)
-        VSIFSeek(hRawBinFile->fp, iEntry*380, SEEK_SET);
+        CPL_IGNORE_RET_VAL_INT(VSIFSeek(hRawBinFile->fp, iEntry*380, SEEK_SET));
     else
     {
         /* Not found... Use the next logical table index */
         nTableIndex++;
 
-        /* We're already at EOF so we shouldn't need to fseek here, but
-         * ANSI-C requires that a file positioning function be called 
+        /* We are already at EOF so we should not need to fseek here, but
+         * ANSI-C requires that a file positioning function be called
          * between read and writes... this had never been a problem before
          * on any system except with NT4 network drives.
          */
-        VSIFSeek(hRawBinFile->fp, numDirEntries*380, SEEK_SET);
+        CPL_IGNORE_RET_VAL_INT(VSIFSeek(hRawBinFile->fp, numDirEntries*380, SEEK_SET));
     }
 
-    sprintf(psTableDef->szInfoFile, "ARC%4.4d", nTableIndex);
+    snprintf(psTableDef->szInfoFile, sizeof(psTableDef->szInfoFile), "ARC%4.4d", nTableIndex);
     _AVCBinWriteArcDir(hRawBinFile, psTableDef);
 
     AVCRawBinClose(hRawBinFile);
@@ -1603,11 +1616,11 @@ int _AVCBinWriteCreateArcDirEntry(const char *pszArcDirFile,
  * psTableDef should contain a valid table definition for this coverage.
  * This function will create and maintain its own copy of the structure.
  *
- * The name of the file to create and its location will be based on the 
- * table name and the external ("XX") flag values in the psTableDef 
+ * The name of the file to create and its location will be based on the
+ * table name and the external ("XX") flag values in the psTableDef
  * structure, so you have to make sure that these values are valid.
  *
- * If a table with the same name is already present in the arc.dir, then 
+ * If a table with the same name is already present in the arc.dir, then
  * the same arc.dir entry will be used and overwritten.  This happens
  * when a coverage directory is deleted by hand.  The behavior implemented
  * here correspond to Arc/Info's behavior.
@@ -1625,21 +1638,21 @@ int _AVCBinWriteCreateArcDirEntry(const char *pszArcDirFile,
  *    will be created in this coverage's directory... so it is assumed that
  *    the directory "../<covername>" already exists and is writable.
  *  - <EXT>:
- *    The coverage name is followed by a 3 chars extension that will be 
+ *    The coverage name is followed by a 3 chars extension that will be
  *    used to build the name of the external table to create.
  *  - <SUBCLASSNAME>:
  *    For some table types, the extension is followed by a subclass name.
- *    
+ *
  *  When <SUBCLASSNAME> is present, then the data file name will be:
  *            "../<covername>/<subclassname>.<ext>"
  *
  *    e.g. The table named "TEST.PATCOUNTY" would be stored in the file
- *         "../test/county.pat" (this path is realtive to the info directory)
+ *         "../test/county.pat" (this path is relative to the info directory)
  *
  *  When the <SUBCLASSNAME> is not present, then the name of the data file
  *  will be the "../<covername>/<ext>.adf"
  *
- *    e.g. The table named "TEST.PAT" would be stored in the file 
+ *    e.g. The table named "TEST.PAT" would be stored in the file
  *         "../test/pat.adf"
  *
  * Of course, it would be too easy if there were no exceptions to these
@@ -1650,10 +1663,10 @@ int _AVCBinWriteCreateArcDirEntry(const char *pszArcDirFile,
  * Returns a valid AVCBinFile handle, or NULL if the table could
  * not be created.
  *
- * AVCBinClose() will eventually have to be called to release the 
+ * AVCBinClose() will eventually have to be called to release the
  * resources used by the AVCBinFile structure.
  **********************************************************************/
-AVCBinFile *AVCBinWriteCreateTable(const char *pszInfoPath, 
+AVCBinFile *AVCBinWriteCreateTable(const char *pszInfoPath,
                                    const char *pszCoverName,
                                    AVCTableDef *psSrcTableDef,
                                    AVCCoverType eCoverType,
@@ -1664,10 +1677,11 @@ AVCBinFile *AVCBinWriteCreateTable(const char *pszInfoPath,
     AVCTableDef  *psTableDef = NULL;
     char         *pszFname = NULL, szInfoFile[8]="";
     int          i, nTableIndex = 0;
+    size_t       nFnameLen;
 
     if (eCoverType == AVCCoverPC || eCoverType == AVCCoverPC2)
         return _AVCBinWriteCreateDBFTable(pszInfoPath, pszCoverName,
-                                          psSrcTableDef, eCoverType, 
+                                          psSrcTableDef, eCoverType,
                                           nPrecision, psDBCSInfo);
 
     /*-----------------------------------------------------------------
@@ -1683,7 +1697,8 @@ AVCBinFile *AVCBinWriteCreateTable(const char *pszInfoPath,
 
     /* Alloc a buffer big enough for the longest possible filename...
      */
-    pszFname = (char*)CPLMalloc((strlen(pszInfoPath)+81)*sizeof(char));
+    nFnameLen = strlen(pszInfoPath)+81;
+    pszFname = (char*)CPLMalloc(nFnameLen);
 
 
     /*-----------------------------------------------------------------
@@ -1703,9 +1718,9 @@ AVCBinFile *AVCBinWriteCreateTable(const char *pszInfoPath,
      * Note: there could be a problem if 2 processes try to add an entry
      * at the exact same time... does Arc/Info do any locking on that file???
      *----------------------------------------------------------------*/
-    sprintf(pszFname, "%sarc.dir", pszInfoPath);
+    snprintf(pszFname, nFnameLen, "%sarc.dir", pszInfoPath);
 
-    nTableIndex = _AVCBinWriteCreateArcDirEntry(pszFname, psTableDef, 
+    nTableIndex = _AVCBinWriteCreateArcDirEntry(pszFname, psTableDef,
                                                 psDBCSInfo);
 
     if (nTableIndex < 0)
@@ -1719,12 +1734,12 @@ AVCBinFile *AVCBinWriteCreateTable(const char *pszInfoPath,
         return NULL;
     }
 
-    sprintf(szInfoFile, "arc%4.4d", nTableIndex);
+    snprintf(szInfoFile, sizeof(szInfoFile), "arc%4.4d", nTableIndex);
 
     /*-----------------------------------------------------------------
      * Create the "arc####.nit" with the attribute definitions.
      *----------------------------------------------------------------*/
-    sprintf(pszFname, "%s%s.nit", pszInfoPath, szInfoFile);
+    snprintf(pszFname, nFnameLen, "%s%s.nit", pszInfoPath, szInfoFile);
 
     hRawBinFile = AVCRawBinOpen(pszFname, "w",
                                 AVC_COVER_BYTE_ORDER(AVCCoverV7),
@@ -1758,7 +1773,7 @@ AVCBinFile *AVCBinWriteCreateTable(const char *pszInfoPath,
          * Internal table: data goes directly in "arc####.dat"
          *------------------------------------------------------------*/
         psTableDef->szDataFile[0] = '\0';
-        sprintf(pszFname, "%s%s.dat", pszInfoPath, szInfoFile);
+        snprintf(pszFname, nFnameLen, "%s%s.dat", pszInfoPath, szInfoFile);
         psFile->pszFilename = CPLStrdup(pszFname);
     }
     else
@@ -1772,14 +1787,14 @@ AVCBinFile *AVCBinWriteCreateTable(const char *pszInfoPath,
         int nLen;
         FILE *fpOut;
 
-        nLen = strlen(psTableDef->szTableName);
+        nLen = (int)strlen(psTableDef->szTableName);
         CPLAssert(nLen <= 32);
         if (nLen > 32) return NULL;
         pszPtr = psTableDef->szTableName;
 
         for(i=0; *pszPtr!='\0' && *pszPtr!='.' && *pszPtr!=' ';  i++, pszPtr++)
         {
-            szCoverName[i] = tolower(*pszPtr);
+            szCoverName[i] = (char) tolower(*pszPtr);
         }
         szCoverName[i] = '\0';
 
@@ -1788,13 +1803,13 @@ AVCBinFile *AVCBinWriteCreateTable(const char *pszInfoPath,
 
         for(i=0; i<3 && *pszPtr!='\0' && *pszPtr!=' ';  i++, pszPtr++)
         {
-            szExt[i] = tolower(*pszPtr);
+            szExt[i] = (char) tolower(*pszPtr);
         }
         szExt[i] = '\0';
 
         for(i=0; *pszPtr!='\0' && *pszPtr!=' ';  i++, pszPtr++)
         {
-            szSubclass[i] = tolower(*pszPtr);
+            szSubclass[i] = (char) tolower(*pszPtr);
         }
         szSubclass[i] = '\0';
 
@@ -1807,20 +1822,20 @@ AVCBinFile *AVCBinWriteCreateTable(const char *pszInfoPath,
                 (EQUAL(szExt, "TIC") || EQUAL(szExt, "BND")) )
             {
                 /* "../<covername>/dbl<ext>.adf" */
-                sprintf(psTableDef->szDataFile, 
+                snprintf(psTableDef->szDataFile, sizeof(psTableDef->szDataFile),
                         "../%s/dbl%s.adf", szCoverName, szExt);
             }
             else
             {
                 /* "../<covername>/<ext>.adf" */
-                sprintf(psTableDef->szDataFile, 
+                snprintf(psTableDef->szDataFile, sizeof(psTableDef->szDataFile),
                         "../%s/%s.adf", szCoverName, szExt);
             }
         }
         else
         {
             /* "../<covername>/<subclass>.<ext>" */
-            sprintf(psTableDef->szDataFile, 
+            snprintf(psTableDef->szDataFile, sizeof(psTableDef->szDataFile),
                     "../%s/%s.%s", szCoverName, szSubclass, szExt);
         }
 
@@ -1829,11 +1844,11 @@ AVCBinFile *AVCBinWriteCreateTable(const char *pszInfoPath,
          * Note that the path that is written in the arc####.dat contains
          * '/' as a directory delimiter, even on Windows systems.
          *------------------------------------------------------------*/
-        sprintf(pszFname, "%s%s.dat", pszInfoPath, szInfoFile);
+        snprintf(pszFname, nFnameLen, "%s%s.dat", pszInfoPath, szInfoFile);
         fpOut = VSIFOpen(pszFname, "wt");
         if (fpOut)
         {
-            VSIFPrintf(fpOut, "%-80.80s", psTableDef->szDataFile);
+            CPL_IGNORE_RET_VAL_INT(VSIFPrintf(fpOut, "%-80.80s", psTableDef->szDataFile));
             VSIFClose(fpOut);
         }
         else
@@ -1846,7 +1861,7 @@ AVCBinFile *AVCBinWriteCreateTable(const char *pszInfoPath,
             return NULL;
         }
 
-        sprintf(pszFname, "%s%s", 
+        snprintf(pszFname, nFnameLen, "%s%s",
                 pszInfoPath, psTableDef->szDataFile);
         psFile->pszFilename = CPLStrdup(pszFname);
 
@@ -1900,15 +1915,15 @@ AVCBinFile *AVCBinWriteCreateTable(const char *pszInfoPath,
  *    - TEST.BND -> BND.DBF
  *    - TEST.TIC -> TIC.DBF
  *
- * However, this function will not fail if it is passed a table name not 
- * supported by PC Arc/Info. 
+ * However, this function will not fail if it is passed a table name not
+ * supported by PC Arc/Info.
  * e.g. TEST.PATCOUNTY would be written as PATCOUNTY.DBF even if PC Arc/Info
  * would probably not recognize that name.
  *
  * Returns a valid AVCBinFile handle, or NULL if the table could
  * not be created.
  *
- * AVCBinClose() will eventually have to be called to release the 
+ * AVCBinClose() will eventually have to be called to release the
  * resources used by the AVCBinFile structure.
  **********************************************************************/
 AVCBinFile *_AVCBinWriteCreateDBFTable(const char *pszPath,
@@ -1937,7 +1952,7 @@ AVCBinFile *_AVCBinWriteCreateDBFTable(const char *pszPath,
     psFile->hdr.psTableDef = psTableDef = _AVCDupTableDef(psSrcTableDef);
 
     /* nCurDBFRecord is used to keep track of the 0-based index of the
-     * last record we read from the DBF file... this is to emulate 
+     * last record we read from the DBF file... this is to emulate
      * sequential access which is assumed by the rest of the lib.
      * Since the first record (record 0) has not been written yet, then
      * we init the index at -1.
@@ -1962,9 +1977,9 @@ AVCBinFile *_AVCBinWriteCreateDBFTable(const char *pszPath,
 
     strcpy(psFile->pszFilename, pszPath);
 
-    for(i=strlen(psFile->pszFilename); *pszDBFBasename; i++, pszDBFBasename++)
+    for(i=(int)strlen(psFile->pszFilename); *pszDBFBasename; i++, pszDBFBasename++)
     {
-        psFile->pszFilename[i] = tolower(*pszDBFBasename);
+        psFile->pszFilename[i] = (char) tolower(*pszDBFBasename);
     }
 
     strcat(psFile->pszFilename, ".dbf");
@@ -1994,7 +2009,7 @@ AVCBinFile *_AVCBinWriteCreateDBFTable(const char *pszPath,
         nType = pasDef[i].nType1*10;
 
         /*-------------------------------------------------------------
-         * Special characters '#' and '-' in field names have to be replaced 
+         * Special characters '#' and '-' in field names have to be replaced
          * with '_'.  PC Field names are limited to 10 chars.
          *------------------------------------------------------------*/
         strncpy(szFieldName, pasDef[i].szName, 10);
@@ -2010,7 +2025,7 @@ AVCBinFile *_AVCBinWriteCreateDBFTable(const char *pszPath,
             /*---------------------------------------------------------
              * Values stored as strings
              *--------------------------------------------------------*/
-            DBFAddField(psFile->hDBFFile, szFieldName, FTString, 
+            DBFAddField(psFile->hDBFFile, szFieldName, FTString,
                         pasDef[i].nSize, 0);
         }
         else if (nType == AVC_FT_FIXINT || nType == AVC_FT_FIXNUM)
@@ -2018,7 +2033,7 @@ AVCBinFile *_AVCBinWriteCreateDBFTable(const char *pszPath,
             /*---------------------------------------------------------
              * Numerics (internally stored as strings)
              *--------------------------------------------------------*/
-            DBFAddField(psFile->hDBFFile, szFieldName, FTDouble, 
+            DBFAddField(psFile->hDBFFile, szFieldName, FTDouble,
                         pasDef[i].nSize, pasDef[i].nFmtPrec);
         }
         else if (nType == AVC_FT_BININT)
@@ -2034,7 +2049,7 @@ AVCBinFile *_AVCBinWriteCreateDBFTable(const char *pszPath,
              * Single + Double precision floats
              * Set them as width=13, prec=6 in the header like PC/Arc does
              *--------------------------------------------------------*/
-            DBFAddField(psFile->hDBFFile, szFieldName, FTDouble, 
+            DBFAddField(psFile->hDBFFile, szFieldName, FTDouble,
                         13, 6);
         }
         else
@@ -2060,7 +2075,7 @@ AVCBinFile *_AVCBinWriteCreateDBFTable(const char *pszPath,
  * (This function is for internal library use... external calls should
  * go to AVCBinWriteClose() instead)
  *
- * Close an info table opened for wirting, and release all memory 
+ * Close an info table opened for writing, and release all memory
  * (object struct., buffers, etc.) associated with this file.
  **********************************************************************/
 static void    _AVCBinWriteCloseTable(AVCBinFile *psFile)
@@ -2082,7 +2097,7 @@ static void    _AVCBinWriteCloseTable(AVCBinFile *psFile)
     else if (psFile->psRawBinFile)
     {
         /*-------------------------------------------------------------
-         * __TODO__ make sure ARC.DIR entry contains accurate info about the 
+         * __TODO__ make sure ARC.DIR entry contains accurate info about the
          * number of records written, etc.
          *------------------------------------------------------------*/
         AVCRawBinClose(psFile->psRawBinFile);
@@ -2108,12 +2123,13 @@ static void    _AVCBinWriteCloseTable(AVCBinFile *psFile)
  *
  * Write a table data record at the current position in file.
  *
- * The contents of the pasDef and pasFields structures is assumed to 
- * be valid... this function performs no validation on the consistency 
+ * The contents of the pasDef and pasFields structures is assumed to
+ * be valid... this function performs no validation on the consistency
  * of what it is given as input.
  *
  * Returns 0 on success or -1 on error.
  **********************************************************************/
+static
 int _AVCBinWriteTableRec(AVCRawBinFile *psFile, int nFields,
                          AVCFieldInfo *pasDef, AVCField *pasFields,
                          int nRecordSize, const char *pszFname)
@@ -2183,7 +2199,7 @@ int _AVCBinWriteTableRec(AVCRawBinFile *psFile, int nFields,
 
     /*-----------------------------------------------------------------
      * Record size is rounded to a multiple of 2 bytes.
-     * Check the number of bytes written, and pad with zeros if 
+     * Check the number of bytes written, and pad with zeros if
      * necessary.
      *----------------------------------------------------------------*/
     nRecordSize = ((nRecordSize+1)/2)*2;
@@ -2204,12 +2220,13 @@ int _AVCBinWriteTableRec(AVCRawBinFile *psFile, int nFields,
  *
  * Write a table data record at the current position in DBF file.
  *
- * The contents of the pasDef and pasFields structures is assumed to 
- * be valid... this function performs no validation on the consistency 
+ * The contents of the pasDef and pasFields structures is assumed to
+ * be valid... this function performs no validation on the consistency
  * of what it is given as input.
  *
  * Returns 0 on success or -1 on error.
  **********************************************************************/
+static
 int _AVCBinWriteDBFTableRec(DBFHandle hDBFFile, int nFields,
                             AVCFieldInfo *pasDef, AVCField *pasFields,
                             int *nCurDBFRecord, const char *pszFname)
@@ -2233,7 +2250,7 @@ int _AVCBinWriteDBFTableRec(DBFHandle hDBFFile, int nFields,
             /*---------------------------------------------------------
              * Values stored as strings
              *--------------------------------------------------------*/
-            nStatus = DBFWriteStringAttribute(hDBFFile, *nCurDBFRecord, i, 
+            nStatus = DBFWriteStringAttribute(hDBFFile, *nCurDBFRecord, i,
                                               (char *)pasFields[i].pszStr);
         }
         else if (nType == AVC_FT_FIXINT || nType == AVC_FT_FIXNUM)
@@ -2241,7 +2258,7 @@ int _AVCBinWriteDBFTableRec(DBFHandle hDBFFile, int nFields,
             /*---------------------------------------------------------
              * Numbers stored as strings
              *--------------------------------------------------------*/
-            nStatus = DBFWriteAttributeDirectly(hDBFFile, *nCurDBFRecord, i, 
+            nStatus = DBFWriteAttributeDirectly(hDBFFile, *nCurDBFRecord, i,
                                                 pasFields[i].pszStr);
         }
         else if (nType == AVC_FT_BININT && pasDef[i].nSize == 4)
@@ -2249,7 +2266,7 @@ int _AVCBinWriteDBFTableRec(DBFHandle hDBFFile, int nFields,
             /*---------------------------------------------------------
              * 32 bit binary integers
              *--------------------------------------------------------*/
-            nStatus = DBFWriteIntegerAttribute(hDBFFile, *nCurDBFRecord, i, 
+            nStatus = DBFWriteIntegerAttribute(hDBFFile, *nCurDBFRecord, i,
                                                pasFields[i].nInt32);
         }
         else if (nType == AVC_FT_BININT && pasDef[i].nSize == 2)
@@ -2257,7 +2274,7 @@ int _AVCBinWriteDBFTableRec(DBFHandle hDBFFile, int nFields,
             /*---------------------------------------------------------
              * 16 bit binary integers
              *--------------------------------------------------------*/
-            nStatus = DBFWriteIntegerAttribute(hDBFFile, *nCurDBFRecord, i, 
+            nStatus = DBFWriteIntegerAttribute(hDBFFile, *nCurDBFRecord, i,
                                                pasFields[i].nInt16);
         }
         else if (nType == AVC_FT_BINFLOAT)
@@ -2269,15 +2286,15 @@ int _AVCBinWriteDBFTableRec(DBFHandle hDBFFile, int nFields,
             int nLen;
 
             if (pasDef[i].nSize == 4)
-                nLen = AVCPrintRealValue(szBuf, AVC_FORMAT_DBF_FLOAT,
+                nLen = AVCPrintRealValue(szBuf, sizeof(szBuf), AVC_FORMAT_DBF_FLOAT,
                                          AVCFileTABLE, pasFields[i].fFloat);
             else
-                nLen = AVCPrintRealValue(szBuf, AVC_FORMAT_DBF_FLOAT,
+                nLen = AVCPrintRealValue(szBuf, sizeof(szBuf), AVC_FORMAT_DBF_FLOAT,
                                          AVCFileTABLE, pasFields[i].dDouble);
 
             szBuf[nLen] = '\0';
 
-            nStatus = DBFWriteAttributeDirectly(hDBFFile, *nCurDBFRecord, i, 
+            nStatus = DBFWriteAttributeDirectly(hDBFFile, *nCurDBFRecord, i,
                                                 szBuf);
         }
         else
@@ -2309,8 +2326,8 @@ int _AVCBinWriteDBFTableRec(DBFHandle hDBFFile, int nFields,
  *
  * Write a table data record at the current position in file.
  *
- * The contents of the pasDef and pasFields structures is assumed to 
- * be valid... this function performs no validation on the consistency 
+ * The contents of the pasDef and pasFields structures is assumed to
+ * be valid... this function performs no validation on the consistency
  * of what it is given as input.
  *
  * Returns 0 on success or -1 on error.
@@ -2325,14 +2342,14 @@ int AVCBinWriteTableRec(AVCBinFile *psFile, AVCField *pasFields)
         return -1;
 
     if (psFile->eCoverType == AVCCoverPC || psFile->eCoverType == AVCCoverPC2)
-        return _AVCBinWriteDBFTableRec(psFile->hDBFFile, 
+        return _AVCBinWriteDBFTableRec(psFile->hDBFFile,
                                        psFile->hdr.psTableDef->numFields,
                                        psFile->hdr.psTableDef->pasFieldDef,
                                        pasFields,
                                        &(psFile->nCurDBFRecord),
                                        psFile->pszFilename);
     else
-        return _AVCBinWriteTableRec(psFile->psRawBinFile, 
+        return _AVCBinWriteTableRec(psFile->psRawBinFile,
                                     psFile->hdr.psTableDef->numFields,
                                     psFile->hdr.psTableDef->pasFieldDef,
                                     pasFields,
diff --git a/ogr/ogrsf_frmts/avc/avc_e00gen.c b/ogr/ogrsf_frmts/avc/avc_e00gen.c
index 21b0d77..d5aef54 100644
--- a/ogr/ogrsf_frmts/avc/avc_e00gen.c
+++ b/ogr/ogrsf_frmts/avc/avc_e00gen.c
@@ -16,16 +16,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -35,7 +35,7 @@
  * (GDAL/OGR ticket http://trac.osgeo.org/gdal/ticket/2495)
  *
  * Revision 1.17  2006/06/14 15:01:33  daniel
- * Remove any embeded '\0' from data line in AVCE00GenTableRec()
+ * Remove any embedded '\0' from data line in AVCE00GenTableRec()
  *
  * Revision 1.16  2005/06/03 03:49:58  daniel
  * Update email address, website url, and copyright dates
@@ -107,7 +107,7 @@ AVCE00GenInfo  *AVCE00GenInfoAlloc(int nCoverPrecision)
 
     psInfo = (AVCE00GenInfo*)CPLCalloc(1,sizeof(AVCE00GenInfo));
 
-    /* Allocate output buffer.  
+    /* Allocate output buffer.
      * 2k should be enough... the biggest thing we'll need to store
      * in it will be 1 complete INFO table record.
      */
@@ -153,23 +153,23 @@ void    AVCE00GenReset(AVCE00GenInfo  *psInfo)
  *
  * pszClassName applies only to JABBERWOCKY type of sections.
  **********************************************************************/
-const char *AVCE00GenStartSection(AVCE00GenInfo *psInfo, AVCFileType eType, 
+const char *AVCE00GenStartSection(AVCE00GenInfo *psInfo, AVCFileType eType,
                                   const char *pszClassName)
 {
-    char *pszName = "UNK";
+    const char *pszName = "UNK";
 
     AVCE00GenReset(psInfo);
 
     if (eType == AVCFileTX6 || eType == AVCFileRXP || eType == AVCFileRPL)
     {
-        /* TX6/RXP/RPL sections start with the class name (the basename 
+        /* TX6/RXP/RPL sections start with the class name (the basename
          * of the file) in uppercase.
          * ex:  The section for "cities.txt" would start with "CITIES"
          */
         int i;
         for(i=0; pszClassName[i] != '\0'; i++)
         {
-            psInfo->pszBuf[i] = toupper(pszClassName[i]);
+            psInfo->pszBuf[i] = (char) toupper(pszClassName[i]);
         }
         psInfo->pszBuf[i] = '\0';
     }
@@ -207,9 +207,9 @@ const char *AVCE00GenStartSection(AVCE00GenInfo *psInfo, AVCFileType eType,
         }
 
         if (psInfo->nPrecision == AVC_DOUBLE_PREC)
-            sprintf(psInfo->pszBuf, "%s  3", pszName);
+            snprintf(psInfo->pszBuf, psInfo->nBufSize, "%s  3", pszName);
         else
-            sprintf(psInfo->pszBuf, "%s  2", pszName);
+            snprintf(psInfo->pszBuf, psInfo->nBufSize,"%s  2", pszName);
     }
 
     return psInfo->pszBuf;
@@ -221,7 +221,7 @@ const char *AVCE00GenStartSection(AVCE00GenInfo *psInfo, AVCFileType eType,
  * Generate the last line(s) of an E00 section.
  *
  * This function should be called once with bCont=FALSE to get the
- * first "end of section" line for the current section, and then call 
+ * first "end of section" line for the current section, and then call
  * with bCont=TRUE to get all the other lines.
  *
  * The function returns NULL when there are no more lines to generate
@@ -232,7 +232,7 @@ const char *AVCE00GenEndSection(AVCE00GenInfo *psInfo, AVCFileType eType,
 {
     if (bCont == FALSE)
     {
-        /*------------------------------------------------------------- 
+        /*-------------------------------------------------------------
          * Most section types end with only 1 line.
          *------------------------------------------------------------*/
         AVCE00GenReset(psInfo);
@@ -246,25 +246,25 @@ const char *AVCE00GenEndSection(AVCE00GenInfo *psInfo, AVCFileType eType,
             eType == AVCFileTXT ||
             eType == AVCFileTX6 )
         {
-            sprintf(psInfo->pszBuf, 
+            snprintf(psInfo->pszBuf, psInfo->nBufSize,
     "        -1         0         0         0         0         0         0");
         }
         else if (eType == AVCFileLAB)
         {
             if (psInfo->nPrecision == AVC_DOUBLE_PREC)
-                sprintf(psInfo->pszBuf, 
+                snprintf(psInfo->pszBuf, psInfo->nBufSize,
           "        -1         0 0.00000000000000E+00 0.00000000000000E+00");
             else
-                sprintf(psInfo->pszBuf, 
+                snprintf(psInfo->pszBuf, psInfo->nBufSize,
           "        -1         0 0.0000000E+00 0.0000000E+00");
         }
         else if (eType == AVCFilePRJ)
         {
-            sprintf(psInfo->pszBuf, "EOP");
+            snprintf(psInfo->pszBuf, psInfo->nBufSize,"EOP");
         }
         else if (eType == AVCFileRXP )
         {
-            sprintf(psInfo->pszBuf,"        -1         0");
+            snprintf(psInfo->pszBuf, psInfo->nBufSize,"        -1         0");
         }
         else
         {
@@ -277,17 +277,17 @@ const char *AVCE00GenEndSection(AVCE00GenInfo *psInfo, AVCFileType eType,
               psInfo->nPrecision == AVC_DOUBLE_PREC &&
               (eType == AVCFilePAL || eType == AVCFileRPL)     )
     {
-        /*--------------------------------------------------------- 
+        /*---------------------------------------------------------
          * Return the 2nd line for the end of a PAL or RPL section.
          *--------------------------------------------------------*/
-        sprintf(psInfo->pszBuf, 
+        snprintf(psInfo->pszBuf, psInfo->nBufSize,
                 " 0.00000000000000E+00 0.00000000000000E+00");
 
         psInfo->iCurItem++;
     }
     else
     {
-        /*----------------------------------------------------- 
+        /*-----------------------------------------------------
          * All other section types end with only one line, and thus
          * we return NULL when bCont==TRUE
          *----------------------------------------------------*/
@@ -305,13 +305,13 @@ const char *AVCE00GenEndSection(AVCE00GenInfo *psInfo, AVCFileType eType,
  * call the right function according to argument eType.
  *
  * Since there is no compiler type checking on psObj, you have to
- * be very careful to make sure you pass an object of the right type 
+ * be very careful to make sure you pass an object of the right type
  * when you use this function!
  *
  * The function returns NULL when there are no more lines to generate
  * for this ARC.
  **********************************************************************/
-const char *AVCE00GenObject(AVCE00GenInfo *psInfo, 
+const char *AVCE00GenObject(AVCE00GenInfo *psInfo,
                             AVCFileType eType, void *psObj, GBool bCont)
 {
     const char *pszLine = NULL;
@@ -386,7 +386,7 @@ const char *AVCE00GenArc(AVCE00GenInfo *psInfo, AVCArc *psArc, GBool bCont)
 
         /* And return the ARC header line
          */
-        sprintf(psInfo->pszBuf, "%10d%10d%10d%10d%10d%10d%10d",
+        snprintf(psInfo->pszBuf, psInfo->nBufSize,"%10d%10d%10d%10d%10d%10d%10d",
                 psArc->nArcId, psArc->nUserId,
                 psArc->nFNode, psArc->nTNode,
                 psArc->nLPoly, psArc->nRPoly,
@@ -403,9 +403,9 @@ const char *AVCE00GenArc(AVCE00GenInfo *psInfo, AVCArc *psArc, GBool bCont)
             iVertex = psInfo->iCurItem;
 
             psInfo->pszBuf[0] = '\0';
-            AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileARC,
+            AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision, AVCFileARC,
                             psArc->pasVertices[iVertex].x);
-            AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileARC,
+            AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision, AVCFileARC,
                             psArc->pasVertices[iVertex].y);
         }
         else
@@ -413,9 +413,9 @@ const char *AVCE00GenArc(AVCE00GenInfo *psInfo, AVCArc *psArc, GBool bCont)
             iVertex = psInfo->iCurItem*2;
 
             psInfo->pszBuf[0] = '\0';
-            AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileARC,
+            AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision, AVCFileARC,
                             psArc->pasVertices[iVertex].x);
-            AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileARC,
+            AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision, AVCFileARC,
                             psArc->pasVertices[iVertex].y);
 
             /* Check because if we have a odd number of vertices then
@@ -423,9 +423,9 @@ const char *AVCE00GenArc(AVCE00GenInfo *psInfo, AVCArc *psArc, GBool bCont)
              */
             if (iVertex+1 < psArc->numVertices)
             {
-                AVCPrintRealValue(psInfo->pszBuf,psInfo->nPrecision,AVCFileARC,
+                AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize,psInfo->nPrecision,AVCFileARC,
                                 psArc->pasVertices[iVertex+1].x);
-                AVCPrintRealValue(psInfo->pszBuf,psInfo->nPrecision,AVCFileARC,
+                AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize,psInfo->nPrecision,AVCFileARC,
                                 psArc->pasVertices[iVertex+1].y);
             }
         }
@@ -469,11 +469,11 @@ const char *AVCE00GenPal(AVCE00GenInfo *psInfo, AVCPal *psPal, GBool bCont)
 
         /* And return the PAL header line.
          */
-        sprintf(psInfo->pszBuf, "%10d", psPal->numArcs);
+        snprintf(psInfo->pszBuf, psInfo->nBufSize,"%10d", psPal->numArcs);
 
-        AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFilePAL,
+        AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision, AVCFilePAL,
                         psPal->sMin.x);
-        AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFilePAL,
+        AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision, AVCFilePAL,
                         psPal->sMin.y);
 
         /* Double precision PAL entries have their header on 2 lines!
@@ -484,9 +484,9 @@ const char *AVCE00GenPal(AVCE00GenInfo *psInfo, AVCPal *psPal, GBool bCont)
         }
         else
         {
-            AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFilePAL,
+            AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision, AVCFilePAL,
                             psPal->sMax.x);
-            AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFilePAL,
+            AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision, AVCFilePAL,
                             psPal->sMax.y);
             psInfo->iCurItem = 0;       /* Next thing = first Arc entry */
         }
@@ -497,9 +497,9 @@ const char *AVCE00GenPal(AVCE00GenInfo *psInfo, AVCPal *psPal, GBool bCont)
         /* Second (and last) header line for double precision coverages
          */
         psInfo->pszBuf[0] = '\0';
-        AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFilePAL,
+        AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision, AVCFilePAL,
                         psPal->sMax.x);
-        AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFilePAL,
+        AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision, AVCFilePAL,
                         psPal->sMax.y);
 
         if ( psInfo->numItems == 0 )
@@ -514,7 +514,7 @@ const char *AVCE00GenPal(AVCE00GenInfo *psInfo, AVCPal *psPal, GBool bCont)
     }
     else if (psInfo->iCurItem == -2)
     {
-        sprintf(psInfo->pszBuf, "%10d%10d%10d", 0, 0, 0);
+        snprintf(psInfo->pszBuf, psInfo->nBufSize,"%10d%10d%10d", 0, 0, 0);
         psInfo->iCurItem = 0;       /* Next thing = first Arc entry */
     }
     else if (psInfo->iCurItem < psInfo->numItems)
@@ -530,7 +530,7 @@ const char *AVCE00GenPal(AVCE00GenInfo *psInfo, AVCPal *psPal, GBool bCont)
          */
         if (iArc+1 < psPal->numArcs)
         {
-            sprintf(psInfo->pszBuf, "%10d%10d%10d%10d%10d%10d",
+            snprintf(psInfo->pszBuf, psInfo->nBufSize,"%10d%10d%10d%10d%10d%10d",
                                     psPal->pasArcs[iArc].nArcId,
                                     psPal->pasArcs[iArc].nFNode,
                                     psPal->pasArcs[iArc].nAdjPoly,
@@ -541,7 +541,7 @@ const char *AVCE00GenPal(AVCE00GenInfo *psInfo, AVCPal *psPal, GBool bCont)
         }
         else
         {
-            sprintf(psInfo->pszBuf, "%10d%10d%10d", 
+            snprintf(psInfo->pszBuf, psInfo->nBufSize,"%10d%10d%10d",
                                     psPal->pasArcs[iArc].nArcId,
                                     psPal->pasArcs[iArc].nFNode,
                                     psPal->pasArcs[iArc].nAdjPoly);
@@ -587,17 +587,17 @@ const char *AVCE00GenCnt(AVCE00GenInfo *psInfo, AVCCnt *psCnt, GBool bCont)
 
         /* And return the CNT header line.
          */
-        sprintf(psInfo->pszBuf, "%10d", psCnt->numLabels);
+        snprintf(psInfo->pszBuf, psInfo->nBufSize,"%10d", psCnt->numLabels);
 
-        AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileCNT,
+        AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision, AVCFileCNT,
                         psCnt->sCoord.x);
-        AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileCNT,
+        AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision, AVCFileCNT,
                         psCnt->sCoord.y);
 
     }
     else if (psInfo->iCurItem < psInfo->numItems)
     {
-        /* Return CNT Label Ids, 8 label Ids per line... 
+        /* Return CNT Label Ids, 8 label Ids per line...
          */
         int i, nFirstLabel, numLabels;
 
@@ -607,7 +607,8 @@ const char *AVCE00GenCnt(AVCE00GenInfo *psInfo, AVCCnt *psCnt, GBool bCont)
         psInfo->pszBuf[0] = '\0';
         for(i=0; i < numLabels; i++)
         {
-            sprintf(psInfo->pszBuf + strlen(psInfo->pszBuf), "%10d", 
+            snprintf(psInfo->pszBuf + strlen(psInfo->pszBuf),
+                     psInfo->nBufSize - strlen(psInfo->pszBuf), "%10d",
                                         psCnt->panLabelIds[nFirstLabel+i] );
         }
 
@@ -655,30 +656,30 @@ const char *AVCE00GenLab(AVCE00GenInfo *psInfo, AVCLab *psLab, GBool bCont)
 
         /* And return the LAB header line.
          */
-        sprintf(psInfo->pszBuf, "%10d%10d", psLab->nValue, psLab->nPolyId);
+        snprintf(psInfo->pszBuf, psInfo->nBufSize,"%10d%10d", psLab->nValue, psLab->nPolyId);
 
-        AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileLAB,
+        AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision, AVCFileLAB,
                         psLab->sCoord1.x);
-        AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileLAB,
+        AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision, AVCFileLAB,
                         psLab->sCoord1.y);
 
     }
     else if (psInfo->iCurItem < psInfo->numItems)
     {
-        /* Return next Label coordinates... 
+        /* Return next Label coordinates...
          */
         if (psInfo->nPrecision != AVC_DOUBLE_PREC)
         {
             /* Single precision, all on the same line
              */
             psInfo->pszBuf[0] = '\0';
-            AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileLAB,
+            AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision, AVCFileLAB,
                             psLab->sCoord2.x);
-            AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileLAB,
+            AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision, AVCFileLAB,
                             psLab->sCoord2.y);
-            AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileLAB,
+            AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision, AVCFileLAB,
                             psLab->sCoord3.x);
-            AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileLAB,
+            AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision, AVCFileLAB,
                             psLab->sCoord3.y);
 
         }
@@ -687,9 +688,9 @@ const char *AVCE00GenLab(AVCE00GenInfo *psInfo, AVCLab *psLab, GBool bCont)
             /* 2nd line, in a double precision coverage
              */
             psInfo->pszBuf[0] = '\0';
-            AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileLAB,
+            AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision, AVCFileLAB,
                             psLab->sCoord2.x);
-            AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileLAB,
+            AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision, AVCFileLAB,
                             psLab->sCoord2.y);
         }
         else
@@ -697,9 +698,9 @@ const char *AVCE00GenLab(AVCE00GenInfo *psInfo, AVCLab *psLab, GBool bCont)
             /* 3rd line, in a double precision coverage
              */
             psInfo->pszBuf[0] = '\0';
-            AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileLAB,
+            AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision, AVCFileLAB,
                             psLab->sCoord3.x);
-            AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileLAB,
+            AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision, AVCFileLAB,
                             psLab->sCoord3.y);
         }
 
@@ -735,15 +736,15 @@ const char *AVCE00GenTol(AVCE00GenInfo *psInfo, AVCTol *psTol, GBool bCont)
 {
     if (bCont == TRUE)
     {
-        /*--------------------------------------------------------- 
+        /*---------------------------------------------------------
          * TOL entries are only 1 line, we support the bCont flag
          * only for compatibility with the other AVCE00Gen*() functions.
          *--------------------------------------------------------*/
         return NULL;
     }
 
-    sprintf(psInfo->pszBuf, "%10d%10d", psTol->nIndex, psTol->nFlag);
-    AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileTOL,
+    snprintf(psInfo->pszBuf, psInfo->nBufSize,"%10d%10d", psTol->nIndex, psTol->nFlag);
+    AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision, AVCFileTOL,
                     psTol->dValue);
 
     return psInfo->pszBuf;
@@ -769,7 +770,7 @@ const char *AVCE00GenPrj(AVCE00GenInfo *psInfo, char **papszPrj, GBool bCont)
 {
     if (bCont == FALSE)
     {
-        /*--------------------------------------------------------- 
+        /*---------------------------------------------------------
          * Initialize the psInfo structure with info about the
          * current PRJ. (numItems = Number of lines to output)
          *--------------------------------------------------------*/
@@ -779,7 +780,7 @@ const char *AVCE00GenPrj(AVCE00GenInfo *psInfo, char **papszPrj, GBool bCont)
 
     if (psInfo->iCurItem < psInfo->numItems)
     {
-        /*--------------------------------------------------------- 
+        /*---------------------------------------------------------
          * Return the next PRJ section line.  Note that every
          * second line of the output is only a "~".
          *--------------------------------------------------------*/
@@ -791,7 +792,7 @@ const char *AVCE00GenPrj(AVCE00GenInfo *psInfo, char **papszPrj, GBool bCont)
              * several lines, but I won't do it for now since I never
              * saw any projection line longer than 80 chars.
              *----------------------------------------------------*/
-            sprintf(psInfo->pszBuf, "%s", papszPrj[psInfo->iCurItem/2]);
+            snprintf(psInfo->pszBuf, psInfo->nBufSize,"%s", papszPrj[psInfo->iCurItem/2]);
         }
         else
         {
@@ -799,7 +800,7 @@ const char *AVCE00GenPrj(AVCE00GenInfo *psInfo, char **papszPrj, GBool bCont)
              * Every second line in a PRJ section contains only a "~",
              * this is a way to tell that the previous line was complete.
              *----------------------------------------------------*/
-            sprintf(psInfo->pszBuf, "~");
+            snprintf(psInfo->pszBuf, psInfo->nBufSize,"~");
         }
 
         psInfo->iCurItem++;
@@ -836,7 +837,7 @@ const char *AVCE00GenTxt(AVCE00GenInfo *psInfo, AVCTxt *psTxt, GBool bCont)
     int numFixedLines;
 
     /* numFixedLines is the number of lines to generate before the line(s)
-     * with the text string 
+     * with the text string
      */
     if (psInfo->nPrecision == AVC_SINGLE_PREC)
         numFixedLines = 4;
@@ -854,16 +855,16 @@ const char *AVCE00GenTxt(AVCE00GenInfo *psInfo, AVCTxt *psTxt, GBool bCont)
 
         /* And return the TXT header line.
          */
-        sprintf(psInfo->pszBuf, "%10d%10d%10d%10d%10d", 
-                psTxt->nLevel, psTxt->numVerticesLine - 1, 
+        snprintf(psInfo->pszBuf, psInfo->nBufSize,"%10d%10d%10d%10d%10d",
+                psTxt->nLevel, psTxt->numVerticesLine - 1,
                 psTxt->numVerticesArrow, psTxt->nSymbol, psTxt->numChars);
     }
     else if (psInfo->iCurItem < psInfo->numItems &&
              psInfo->iCurItem < numFixedLines-1)
     {
         /*-------------------------------------------------------------
-         * Return next line of coordinates... start by placing the coord. 
-         * values in the order that they should appear, and then generate the 
+         * Return next line of coordinates... start by placing the coord.
+         * values in the order that they should appear, and then generate the
          * current line
          * (This is a little bit less efficient, but will give much easier
          *  code to read ;-)
@@ -903,13 +904,13 @@ const char *AVCE00GenTxt(AVCE00GenInfo *psInfo, AVCTxt *psTxt, GBool bCont)
             /* Double precision
              */
             numValuesPerLine = 3;
-        }       
-     
-        nFirstValue = psInfo->iCurItem*numValuesPerLine; 
+        }
+
+        nFirstValue = psInfo->iCurItem*numValuesPerLine;
         psInfo->pszBuf[0] = '\0';
         for(i=0; i<numValuesPerLine; i++)
         {
-            AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileTXT,
+            AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision, AVCFileTXT,
                             dXY[nFirstValue+i] );
         }
 
@@ -922,7 +923,7 @@ const char *AVCE00GenTxt(AVCE00GenInfo *psInfo, AVCTxt *psTxt, GBool bCont)
          * Line with a -1.000E+02 value, ALWAYS SINGLE PRECISION !!!
          *------------------------------------------------------------*/
         psInfo->pszBuf[0] = '\0';
-        AVCPrintRealValue(psInfo->pszBuf, AVC_SINGLE_PREC, AVCFileTXT,
+        AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, AVC_SINGLE_PREC, AVCFileTXT,
                         psTxt->f_1e2 );
         psInfo->iCurItem++;
     }
@@ -938,8 +939,8 @@ const char *AVCE00GenTxt(AVCE00GenInfo *psInfo, AVCTxt *psTxt, GBool bCont)
         iLine = numLines - (psInfo->numItems - psInfo->iCurItem);
 
         if ((int)strlen((char*)psTxt->pszText) > (iLine*80))
-            sprintf(psInfo->pszBuf, "%-.80s", psTxt->pszText + (iLine*80) );
-        else 
+            snprintf(psInfo->pszBuf, psInfo->nBufSize,"%-.80s", psTxt->pszText + (iLine*80) );
+        else
             psInfo->pszBuf[0] = '\0';
 
         psInfo->iCurItem++;
@@ -984,18 +985,18 @@ const char *AVCE00GenTx6(AVCE00GenInfo *psInfo, AVCTxt *psTxt, GBool bCont)
          * current TX6. (numItems = Number of lines excluding header)
          *------------------------------------------------------------*/
         psInfo->iCurItem = 0;
-        psInfo->numItems = 8 + psTxt->numVerticesLine + 
-                               ABS(psTxt->numVerticesArrow) + 
+        psInfo->numItems = 8 + psTxt->numVerticesLine +
+                               ABS(psTxt->numVerticesArrow) +
                                          ((psTxt->numChars-1)/80 + 1);
 
         /* And return the TX6 header line.
          */
-        sprintf(psInfo->pszBuf, "%10d%10d%10d%10d%10d%10d%10d", 
-                psTxt->nUserId, psTxt->nLevel, psTxt->numVerticesLine, 
+        snprintf(psInfo->pszBuf, psInfo->nBufSize,"%10d%10d%10d%10d%10d%10d%10d",
+                psTxt->nUserId, psTxt->nLevel, psTxt->numVerticesLine,
                 psTxt->numVerticesArrow, psTxt->nSymbol, psTxt->n28,
                 psTxt->numChars);
     }
-    else if (psInfo->iCurItem < psInfo->numItems && 
+    else if (psInfo->iCurItem < psInfo->numItems &&
              psInfo->iCurItem < 6)
     {
         /*-------------------------------------------------------------
@@ -1010,42 +1011,43 @@ const char *AVCE00GenTx6(AVCE00GenInfo *psInfo, AVCTxt *psTxt, GBool bCont)
 
         if (psInfo->iCurItem == 2 || psInfo->iCurItem == 5)
         {
-            sprintf(psInfo->pszBuf, "%10d%10d%10d%10d%10d%10d",
-                                pValue[0], pValue[1], pValue[2], 
+            snprintf(psInfo->pszBuf, psInfo->nBufSize,"%10d%10d%10d%10d%10d%10d",
+                                pValue[0], pValue[1], pValue[2],
                                 pValue[3], pValue[4], pValue[5]);
         }
         else
         {
-            sprintf(psInfo->pszBuf, "%10d%10d%10d%10d%10d%10d%10d",
-                                pValue[0], pValue[1], pValue[2], 
+            /* coverity[overrun-local] */
+            snprintf(psInfo->pszBuf, psInfo->nBufSize,"%10d%10d%10d%10d%10d%10d%10d",
+                                pValue[0], pValue[1], pValue[2],
                                 pValue[3], pValue[4], pValue[5], pValue[6]);
         }
 
         psInfo->iCurItem++;
     }
-    else if (psInfo->iCurItem < psInfo->numItems && 
+    else if (psInfo->iCurItem < psInfo->numItems &&
              psInfo->iCurItem == 6)
     {
         /*-------------------------------------------------------------
          * Line with a -1.000E+02 value, ALWAYS SINGLE PRECISION !!!
          *------------------------------------------------------------*/
         psInfo->pszBuf[0] = '\0';
-        AVCPrintRealValue(psInfo->pszBuf, AVC_SINGLE_PREC, AVCFileTX6,
+        AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, AVC_SINGLE_PREC, AVCFileTX6,
                         psTxt->f_1e2 );
         psInfo->iCurItem++;
     }
-    else if (psInfo->iCurItem < psInfo->numItems && 
+    else if (psInfo->iCurItem < psInfo->numItems &&
              psInfo->iCurItem == 7)
     {
         /*-------------------------------------------------------------
          * Line with 3 values, 1st value is probably text height.
          *------------------------------------------------------------*/
         psInfo->pszBuf[0] = '\0';
-        AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileTX6,
+        AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision, AVCFileTX6,
                         psTxt->dHeight );
-        AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileTX6,
+        AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision, AVCFileTX6,
                         psTxt->dV2 );
-        AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileTX6,
+        AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision, AVCFileTX6,
                         psTxt->dV3 );
         psInfo->iCurItem++;
     }
@@ -1056,9 +1058,9 @@ const char *AVCE00GenTx6(AVCE00GenInfo *psInfo, AVCTxt *psTxt, GBool bCont)
          *------------------------------------------------------------*/
         psInfo->pszBuf[0] = '\0';
 
-        AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileTX6,
+        AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision, AVCFileTX6,
                         psTxt->pasVertices[ psInfo->iCurItem-8 ].x );
-        AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileTX6,
+        AVCPrintRealValue(psInfo->pszBuf, psInfo->nBufSize, psInfo->nPrecision, AVCFileTX6,
                         psTxt->pasVertices[ psInfo->iCurItem-8 ].y );
 
         psInfo->iCurItem++;
@@ -1075,8 +1077,8 @@ const char *AVCE00GenTx6(AVCE00GenInfo *psInfo, AVCTxt *psTxt, GBool bCont)
         iLine = numLines - (psInfo->numItems - psInfo->iCurItem);
 
         if ((int)strlen((char*)psTxt->pszText) > (iLine*80))
-            sprintf(psInfo->pszBuf, "%-.80s", psTxt->pszText + (iLine*80) );
-        else 
+            snprintf(psInfo->pszBuf, psInfo->nBufSize,"%-.80s", psTxt->pszText + (iLine*80) );
+        else
             psInfo->pszBuf[0] = '\0';
 
         psInfo->iCurItem++;
@@ -1112,14 +1114,14 @@ const char *AVCE00GenRxp(AVCE00GenInfo *psInfo, AVCRxp *psRxp, GBool bCont)
 {
     if (bCont == TRUE)
     {
-        /*--------------------------------------------------------- 
+        /*---------------------------------------------------------
          * RXP entries are only 1 line, we support the bCont flag
          * only for compatibility with the other AVCE00Gen*() functions.
          *--------------------------------------------------------*/
         return NULL;
     }
 
-    sprintf(psInfo->pszBuf, "%10d%10d", psRxp->n1, psRxp->n2);
+    snprintf(psInfo->pszBuf, psInfo->nBufSize,"%10d%10d", psRxp->n1, psRxp->n2);
 
     return psInfo->pszBuf;
 }
@@ -1136,7 +1138,7 @@ const char *AVCE00GenRxp(AVCE00GenInfo *psInfo, AVCRxp *psRxp, GBool bCont)
  * Generate the next line of an E00 Table header.
  *
  * This function should be called once with bCont=FALSE to get the
- * first E00 line for the current table header, and then call with 
+ * first E00 line for the current table header, and then call with
  * bCont=TRUE to get all the other lines.
  *
  * The function returns NULL when there are no more lines to generate.
@@ -1173,7 +1175,7 @@ const char *AVCE00GenTableHdr(AVCE00GenInfo *psInfo, AVCTableDef *psDef,
 
         /* And return the header's header line(!).
          */
-        sprintf(psInfo->pszBuf, "%-32.32s%s%4d%4d%4d%10d", 
+        snprintf(psInfo->pszBuf, psInfo->nBufSize,"%-32.32s%s%4d%4d%4d%10d",
                                             psDef->szTableName,
                                             psDef->szExternal,
                                             psDef->numFields,
@@ -1191,9 +1193,9 @@ const char *AVCE00GenTableHdr(AVCE00GenInfo *psInfo, AVCTableDef *psDef,
 
 #ifdef AVC_MAP_TYPE40_TO_DOUBLE
         /* Type 40 fields with more than 12 digits written to E00 by Arc/Info
-         * will lose some digits of precision (and we starts losing them at 8 
-         * with the way AVC lib writes type 40).  This (optional) hack will 
-         * remap type 40 fields with more than 8 digits to double precision 
+         * will lose some digits of precision (and we starts losing them at 8
+         * with the way AVC lib writes type 40).  This (optional) hack will
+         * remap type 40 fields with more than 8 digits to double precision
          * floats which can carry up to 18 digits of precision.  (bug 599)
          */
         if (nType == AVC_FT_FIXNUM && nSize > 8)
@@ -1204,7 +1206,7 @@ const char *AVCE00GenTableHdr(AVCE00GenInfo *psInfo, AVCTableDef *psDef,
         }
 
         /* Adjust field offset if this field is preceded by any type40 fields
-         * that were remapped. 
+         * that were remapped.
          */
         {
             int i;
@@ -1221,7 +1223,7 @@ const char *AVCE00GenTableHdr(AVCE00GenInfo *psInfo, AVCTableDef *psDef,
 #endif
         /* Return next Field definition line
          */
-        sprintf(psInfo->pszBuf,
+        snprintf(psInfo->pszBuf, psInfo->nBufSize,
                 "%-16.16s%3d%2d%4d%1d%2d%4d%2d%3d%2d%4d%4d%2d%-16.16s%4d-",
                 psDef->pasFieldDef[psInfo->iCurItem].szName,
                 nSize,
@@ -1258,7 +1260,7 @@ const char *AVCE00GenTableHdr(AVCE00GenInfo *psInfo, AVCTableDef *psDef,
  * Generate the next line of an E00 Table Data Record.
  *
  * This function should be called once with bCont=FALSE to get the
- * first E00 line for the current table record, and then call with 
+ * first E00 line for the current table record, and then call with
  * bCont=TRUE to get all the other lines.
  *
  * The function returns NULL when there are no more lines to generate.
@@ -1272,7 +1274,7 @@ const char *AVCE00GenTableRec(AVCE00GenInfo *psInfo, int numFields,
 
     if (bCont == FALSE)
     {
-        /*------------------------------------------------------------- 
+        /*-------------------------------------------------------------
          * Initialize the psInfo structure to be ready to process this
          * new Table Record
          *------------------------------------------------------------*/
@@ -1283,8 +1285,8 @@ const char *AVCE00GenTableRec(AVCE00GenInfo *psInfo, int numFields,
         psInfo->numItems = _AVCE00ComputeRecSize(numFields, pasDef, FALSE);
 #endif
 
-        /*------------------------------------------------------------- 
-         * First, we need to make sure that the output buffer is big 
+        /*-------------------------------------------------------------
+         * First, we need to make sure that the output buffer is big
          * enough to hold the whole record, plus 81 chars to hold
          * the line that we'll return to the caller.
          *------------------------------------------------------------*/
@@ -1297,10 +1299,10 @@ const char *AVCE00GenTableRec(AVCE00GenInfo *psInfo, int numFields,
             psInfo->nBufSize = nSize;
         }
 
-        /*------------------------------------------------------------- 
+        /*-------------------------------------------------------------
          * Generate the whole record now, and we'll return it to the
          * caller by chunks of 80 chars.
-         * The first 80 chars of the buffer will be used to return 
+         * The first 80 chars of the buffer will be used to return
          * one line at a time, and the rest of the buffer is used to
          * hold the whole record.
          *------------------------------------------------------------*/
@@ -1328,7 +1330,9 @@ const char *AVCE00GenTableRec(AVCE00GenInfo *psInfo, int numFields,
                  * defined by its binary size, not by the coverage's
                  * precision.
                  */
-                nLen = AVCPrintRealValue(pszBuf2, AVC_DOUBLE_PREC,
+                nLen = AVCPrintRealValue(pszBuf2,
+                                         psInfo->nBufSize - (pszBuf2 - psInfo->pszBuf),
+                                         AVC_DOUBLE_PREC,
                                          AVCFileTABLE,
                                          CPLAtof((char*)pasFields[i].pszStr));
                 pszBuf2 += nLen;
@@ -1341,19 +1345,21 @@ const char *AVCE00GenTableRec(AVCE00GenInfo *psInfo, int numFields,
                  * E00 tables, even in double precision coverages.
                  */
                 pszBuf2[0] = '\0';
-                nLen = AVCPrintRealValue(pszBuf2, AVC_SINGLE_PREC, 
-                                       AVCFileTABLE,
+                nLen = AVCPrintRealValue(pszBuf2,
+                                         psInfo->nBufSize - (pszBuf2 - psInfo->pszBuf),
+                                         AVC_SINGLE_PREC,
+                                         AVCFileTABLE,
                                          CPLAtof((char*)pasFields[i].pszStr));
                 pszBuf2 += nLen;
             }
             else if (nType == AVC_FT_BININT && nSize == 4)
             {
-                sprintf(pszBuf2, "%11d", pasFields[i].nInt32);
+                snprintf(pszBuf2, psInfo->nBufSize - (pszBuf2 - psInfo->pszBuf), "%11d", pasFields[i].nInt32);
                 pszBuf2 += 11;
             }
             else if (nType == AVC_FT_BININT && nSize == 2)
             {
-                sprintf(pszBuf2, "%6d", pasFields[i].nInt16);
+                snprintf(pszBuf2, psInfo->nBufSize - (pszBuf2 - psInfo->pszBuf), "%6d", pasFields[i].nInt16);
                 pszBuf2 += 6;
             }
             else if (nType == AVC_FT_BINFLOAT && nSize == 4)
@@ -1363,9 +1369,11 @@ const char *AVCE00GenTableRec(AVCE00GenInfo *psInfo, int numFields,
                  * defined by its binary size, not by the coverage's
                  * precision.
                  */
-                nLen = AVCPrintRealValue(pszBuf2, AVC_SINGLE_PREC, 
-                                       AVCFileTABLE,
-                                       pasFields[i].fFloat);
+                nLen = AVCPrintRealValue(pszBuf2,
+                                         psInfo->nBufSize - (pszBuf2 - psInfo->pszBuf),
+                                         AVC_SINGLE_PREC,
+                                         AVCFileTABLE,
+                                         pasFields[i].fFloat);
                 pszBuf2 += nLen;
             }
             else if (nType == AVC_FT_BINFLOAT && nSize == 8)
@@ -1375,9 +1383,11 @@ const char *AVCE00GenTableRec(AVCE00GenInfo *psInfo, int numFields,
                  * defined by its binary size, not by the coverage's
                  * precision.
                  */
-                nLen = AVCPrintRealValue(pszBuf2, AVC_DOUBLE_PREC,
-                                       AVCFileTABLE,
-                                       pasFields[i].dDouble);
+                nLen = AVCPrintRealValue(pszBuf2,
+                                         psInfo->nBufSize - (pszBuf2 - psInfo->pszBuf),
+                                         AVC_DOUBLE_PREC,
+                                         AVCFileTABLE,
+                                         pasFields[i].dDouble);
                 pszBuf2 += nLen;
             }
             else
@@ -1409,9 +1419,9 @@ const char *AVCE00GenTableRec(AVCE00GenInfo *psInfo, int numFields,
 
     if (psInfo->iCurItem < psInfo->numItems)
     {
-        /*------------------------------------------------------------- 
+        /*-------------------------------------------------------------
          * Return the next 80 chars chunk.
-         * The first 80 chars of the buffer is used to return 
+         * The first 80 chars of the buffer is used to return
          * one line at a time, and the rest of the buffer (chars 81+)
          * is used to hold the whole record.
          *------------------------------------------------------------*/
@@ -1425,8 +1435,8 @@ const char *AVCE00GenTableRec(AVCE00GenInfo *psInfo, int numFields,
 
         psInfo->iCurItem += nLen;
 
-        /*------------------------------------------------------------- 
-         * Arc/Info removes spaces at the end of the lines... let's 
+        /*-------------------------------------------------------------
+         * Arc/Info removes spaces at the end of the lines... let's
          * remove them as well since it can reduce the E00 file size.
          *------------------------------------------------------------*/
         nLen--;
@@ -1445,4 +1455,3 @@ const char *AVCE00GenTableRec(AVCE00GenInfo *psInfo, int numFields,
 
     return psInfo->pszBuf;
 }
-
diff --git a/ogr/ogrsf_frmts/avc/avc_e00parse.c b/ogr/ogrsf_frmts/avc/avc_e00parse.c
index 4c47d5f..c04a5d4 100644
--- a/ogr/ogrsf_frmts/avc/avc_e00parse.c
+++ b/ogr/ogrsf_frmts/avc/avc_e00parse.c
@@ -16,16 +16,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -103,10 +103,11 @@
  *
  * Convert a portion of a string to an integer value.
  * The difference between this function and atoi() is that this version
- * takes only the specified number of characters... so it can handle the 
- * case of 2 numbers that are part of the same string but are not separated 
+ * takes only the specified number of characters... so it can handle the
+ * case of 2 numbers that are part of the same string but are not separated
  * by a space.
  **********************************************************************/
+static
 int    AVCE00Str2Int(const char *pszStr, int numChars)
 {
     int nValue = 0;
@@ -140,7 +141,7 @@ int    AVCE00Str2Int(const char *pszStr, int numChars)
  *
  * The structure will eventually have to be freed with AVCE00ParseInfoFree().
  **********************************************************************/
-AVCE00ParseInfo  *AVCE00ParseInfoAlloc()
+AVCE00ParseInfo  *AVCE00ParseInfoAlloc(void)
 {
     AVCE00ParseInfo       *psInfo;
 
@@ -149,7 +150,7 @@ AVCE00ParseInfo  *AVCE00ParseInfoAlloc()
     psInfo->eFileType = AVCFileUnknown;
     psInfo->eSuperSectionType = AVCFileUnknown;
 
-    /* Allocate output buffer.  
+    /* Allocate output buffer.
      * 2k should be enough... the biggest thing we'll need to store
      * in it will be 1 complete INFO table record.
      */
@@ -170,6 +171,7 @@ AVCE00ParseInfo  *AVCE00ParseInfoAlloc()
  * Release mem. associated with the psInfo->cur.* object we are
  * currently using.
  **********************************************************************/
+static
 void    _AVCE00ParseDestroyCurObject(AVCE00ParseInfo  *psInfo)
 {
     if (psInfo->eFileType == AVCFileUnknown)
@@ -203,7 +205,7 @@ void    _AVCE00ParseDestroyCurObject(AVCE00ParseInfo  *psInfo)
     {
         CSLDestroy(psInfo->cur.papszPrj);
     }
-    else if (psInfo->eFileType == AVCFileTXT || 
+    else if (psInfo->eFileType == AVCFileTXT ||
              psInfo->eFileType == AVCFileTX6)
     {
         CPLFree(psInfo->cur.psTxt->pasVertices);
@@ -264,14 +266,14 @@ void    AVCE00ParseReset(AVCE00ParseInfo  *psInfo)
 /**********************************************************************
  *                          AVCE00ParseSuperSectionHeader()
  *
- * Check if pszLine is a valid "supersection" header line, if it is one 
+ * Check if pszLine is a valid "supersection" header line, if it is one
  * then store the supersection type in the ParseInfo structure.
  *
  * What I call a "supersection" is a section that contains several
  * files, such as the TX6/TX7, RPL, RXP, ... and also the IFO (TABLEs).
  *
  * The ParseInfo structure won't be ready to read objects until
- * a call to AVCE00ParseSectionHeader() (see below) succesfully
+ * a call to AVCE00ParseSectionHeader() (see below) successfully
  * recognizes the beginning of a subsection of this type.
  *
  * Returns the new supersection type, or AVCFileUnknown if the line is
@@ -294,13 +296,13 @@ AVCFileType  AVCE00ParseSuperSectionHeader(AVCE00ParseInfo  *psInfo,
     /*-----------------------------------------------------------------
      * Check if pszLine is a valid supersection header line.
      *----------------------------------------------------------------*/
-    if (EQUALN(pszLine, "RPL  ", 5))
+    if (STARTS_WITH_CI(pszLine, "RPL  "))
         psInfo->eSuperSectionType = AVCFileRPL;
-    else if (EQUALN(pszLine, "TX6  ", 5) || EQUALN(pszLine, "TX7  ", 5))
+    else if (STARTS_WITH_CI(pszLine, "TX6  ") || STARTS_WITH_CI(pszLine, "TX7  "))
         psInfo->eSuperSectionType = AVCFileTX6;
-    else if (EQUALN(pszLine, "RXP  ", 5))
+    else if (STARTS_WITH_CI(pszLine, "RXP  "))
         psInfo->eSuperSectionType = AVCFileRXP;
-    else if (EQUALN(pszLine, "IFO  ", 5))
+    else if (STARTS_WITH_CI(pszLine, "IFO  "))
         psInfo->eSuperSectionType = AVCFileTABLE;
     else
         return AVCFileUnknown;
@@ -311,7 +313,7 @@ AVCFileType  AVCE00ParseSuperSectionHeader(AVCE00ParseInfo  *psInfo,
     psInfo->nStartLineNum = psInfo->nCurLineNum;
 
     /*-----------------------------------------------------------------
-     * OK, we have a valid new section header. Set the precision and 
+     * OK, we have a valid new section header. Set the precision and
      * get ready to read objects from it.
      *----------------------------------------------------------------*/
     if (atoi(pszLine+4) == 2)
@@ -320,8 +322,8 @@ AVCFileType  AVCE00ParseSuperSectionHeader(AVCE00ParseInfo  *psInfo,
         psInfo->nPrecision = AVC_DOUBLE_PREC;
     else
     {
-        CPLError(CE_Failure, CPLE_AppDefined, 
-                 "Parse Error: Invalid section header line (\"%s\")!", 
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Parse Error: Invalid section header line (\"%s\")!",
                  pszLine);
         psInfo->eSuperSectionType = AVCFileUnknown;
         /* psInfo->nStartLineNum = -1; */
@@ -335,7 +337,7 @@ AVCFileType  AVCE00ParseSuperSectionHeader(AVCE00ParseInfo  *psInfo,
  *
  * Check if pszLine marks the end of a supersection, and if it is the
  * case, then reset the supersection flag in the ParseInfo.
- * 
+ *
  * Supersections always end with the line "JABBERWOCKY", except for
  * the IFO section.
  **********************************************************************/
@@ -344,9 +346,9 @@ GBool  AVCE00ParseSuperSectionEnd(AVCE00ParseInfo  *psInfo,
 {
     if (psInfo->eFileType == AVCFileUnknown &&
         psInfo->eSuperSectionType != AVCFileUnknown &&
-        (EQUALN(pszLine, "JABBERWOCKY", 11) ||
-         (psInfo->eSuperSectionType == AVCFileTABLE && 
-          EQUALN(pszLine, "EOI", 3) )  ) )
+        (STARTS_WITH_CI(pszLine, "JABBERWOCKY") ||
+         (psInfo->eSuperSectionType == AVCFileTABLE &&
+          STARTS_WITH_CI(pszLine, "EOI") )  ) )
     {
         psInfo->eSuperSectionType = AVCFileUnknown;
         /* psInfo->nStartLineNum = -1; */
@@ -387,28 +389,27 @@ AVCFileType  AVCE00ParseSectionHeader(AVCE00ParseInfo  *psInfo,
         /*-------------------------------------------------------------
          * We're looking for a top-level section...
          *------------------------------------------------------------*/
-        if (EQUALN(pszLine, "ARC  ", 5))
+        if (STARTS_WITH_CI(pszLine, "ARC  "))
             eNewType = AVCFileARC;
-        else if (EQUALN(pszLine, "PAL  ", 5))
+        else if (STARTS_WITH_CI(pszLine, "PAL  "))
             eNewType = AVCFilePAL;
-        else if (EQUALN(pszLine, "CNT  ", 5))
+        else if (STARTS_WITH_CI(pszLine, "CNT  "))
             eNewType = AVCFileCNT;
-        else if (EQUALN(pszLine, "LAB  ", 5))
+        else if (STARTS_WITH_CI(pszLine, "LAB  "))
             eNewType = AVCFileLAB;
-        else if (EQUALN(pszLine, "TOL  ", 5))
+        else if (STARTS_WITH_CI(pszLine, "TOL  "))
             eNewType = AVCFileTOL;
-        else if (EQUALN(pszLine, "PRJ  ", 5))
+        else if (STARTS_WITH_CI(pszLine, "PRJ  "))
             eNewType = AVCFilePRJ;
-        else if (EQUALN(pszLine, "TXT  ", 5))
+        else if (STARTS_WITH_CI(pszLine, "TXT  "))
             eNewType = AVCFileTXT;
         else
         {
-            eNewType = AVCFileUnknown;
             return AVCFileUnknown;
         }
 
         /*-------------------------------------------------------------
-         * OK, we have a valid new section header. Set the precision and 
+         * OK, we have a valid new section header. Set the precision and
          * get ready to read objects from it.
          *------------------------------------------------------------*/
         if (atoi(pszLine+4) == 2)
@@ -417,10 +418,9 @@ AVCFileType  AVCE00ParseSectionHeader(AVCE00ParseInfo  *psInfo,
             psInfo->nPrecision = AVC_DOUBLE_PREC;
         else
         {
-            CPLError(CE_Failure, CPLE_AppDefined, 
-                     "Parse Error: Invalid section header line (\"%s\")!", 
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Parse Error: Invalid section header line (\"%s\")!",
                      pszLine);
-            eNewType = AVCFileUnknown;
             return AVCFileUnknown;
         }
 
@@ -448,11 +448,11 @@ AVCFileType  AVCE00ParseSectionHeader(AVCE00ParseInfo  *psInfo,
              */
             eNewType = psInfo->eSuperSectionType;
         }
-        else if (strlen(pszLine) > 0 && !isspace((unsigned char)pszLine[0]) && 
-                 !EQUALN(pszLine, "JABBERWOCKY", 11) &&
-                 !EQUALN(pszLine, "EOI", 3) &&
+        else if (strlen(pszLine) > 0 && !isspace((unsigned char)pszLine[0]) &&
+                 !STARTS_WITH_CI(pszLine, "JABBERWOCKY") &&
+                 !STARTS_WITH_CI(pszLine, "EOI") &&
                  ! ( psInfo->eSuperSectionType == AVCFileRPL &&
-                     EQUALN(pszLine, " 0.00000", 6)  ) )
+                     STARTS_WITH_CI(pszLine, " 0.00000")  ) )
         {
             eNewType = psInfo->eSuperSectionType;
         }
@@ -463,13 +463,12 @@ AVCFileType  AVCE00ParseSectionHeader(AVCE00ParseInfo  *psInfo,
         }
         else
         {
-            eNewType = AVCFileUnknown;
             return AVCFileUnknown;
         }
     }
 
     /*-----------------------------------------------------------------
-     * nCurObjectId is used to keep track of sequential ids that are 
+     * nCurObjectId is used to keep track of sequential ids that are
      * not explicitly stored in E00.  e.g. polygon Id in a PAL section.
      *----------------------------------------------------------------*/
     psInfo->nCurObjectId = 0;
@@ -552,10 +551,10 @@ AVCFileType  AVCE00ParseSectionHeader(AVCE00ParseInfo  *psInfo,
 /**********************************************************************
  *                          AVCE00ParseSectionEnd()
  *
- * Check if pszLine marks the end of the current section.  
- * 
+ * Check if pszLine marks the end of the current section.
+ *
  * Passing bResetParseInfo=TRUE will reset the parser struct if an end of
- * section is found.  Passing FALSE simply tests for the end of section 
+ * section is found.  Passing FALSE simply tests for the end of section
  * without affecting the parse info struct.
  *
  * Return TRUE if this is the end of the section (and reset the
@@ -573,10 +572,10 @@ GBool  AVCE00ParseSectionEnd(AVCE00ParseInfo  *psInfo, const char *pszLine,
            psInfo->eFileType == AVCFileTOL ||
            psInfo->eFileType == AVCFileTXT ||
            psInfo->eFileType == AVCFileTX6 ||
-           psInfo->eFileType == AVCFileRXP )  && 
-          EQUALN(pszLine, "        -1         0", 20)  ) )
+           psInfo->eFileType == AVCFileRXP )  &&
+          STARTS_WITH_CI(pszLine, "        -1         0")  ) )
     {
-        /* Reset ParseInfo only if explicitly requested. 
+        /* Reset ParseInfo only if explicitly requested.
          */
         if (bResetParseInfo)
         {
@@ -610,7 +609,7 @@ GBool  AVCE00ParseSectionEnd(AVCE00ParseInfo  *psInfo, const char *pszLine,
  *
  * If the input is invalid or other problems happen, then a CPLError()
  * will be generated.  CPLGetLastErrorNo() should be called to check
- * that the line was parsed succesfully.
+ * that the line was parsed successfully.
  *
  * Note for TABLES:
  * When parsing input from info tables, the first valid object that
@@ -683,12 +682,12 @@ void   *AVCE00ParseNextLine(AVCE00ParseInfo  *psInfo, const char *pszLine)
  *
  * If the input is invalid or other problems happen, then a CPLError()
  * will be generated.  CPLGetLastErrorNo() should be called to check
- * that the line was parsed succesfully.
+ * that the line was parsed successfully.
  **********************************************************************/
 AVCArc   *AVCE00ParseNextArcLine(AVCE00ParseInfo *psInfo, const char *pszLine)
 {
     AVCArc *psArc;
-    int     nLen;
+    size_t  nLen;
 
     CPLAssert(psInfo->eFileType == AVCFileARC);
 
@@ -704,7 +703,7 @@ AVCArc   *AVCE00ParseNextArcLine(AVCE00ParseInfo *psInfo, const char *pszLine)
          *------------------------------------------------------------*/
         if (nLen < 70)
         {
-            CPLError(CE_Failure, CPLE_AppDefined, 
+            CPLError(CE_Failure, CPLE_AppDefined,
                      "Error parsing E00 ARC line: \"%s\"", pszLine);
             return NULL;
         }
@@ -717,8 +716,8 @@ AVCArc   *AVCE00ParseNextArcLine(AVCE00ParseInfo *psInfo, const char *pszLine)
             psArc->nLPoly = AVCE00Str2Int(pszLine+40, 10);
             psArc->nRPoly = AVCE00Str2Int(pszLine+50, 10);
             psArc->numVertices = AVCE00Str2Int(pszLine+60, 10);
-            
-            /* Realloc the array of vertices 
+
+            /* Realloc the array of vertices
              */
             psArc->pasVertices = (AVCVertex*)CPLRealloc(psArc->pasVertices,
                                                         psArc->numVertices*
@@ -731,7 +730,7 @@ AVCArc   *AVCE00ParseNextArcLine(AVCE00ParseInfo *psInfo, const char *pszLine)
             psInfo->numItems = psArc->numVertices;
         }
     }
-    else if (psInfo->iCurItem < psInfo->numItems && 
+    else if (psInfo->iCurItem < psInfo->numItems &&
              psInfo->nPrecision == AVC_SINGLE_PREC &&
              ( (psInfo->iCurItem==psInfo->numItems-1 && nLen >= 28) ||
                nLen >= 56 )  )
@@ -748,7 +747,7 @@ AVCArc   *AVCE00ParseNextArcLine(AVCE00ParseInfo *psInfo, const char *pszLine)
             psArc->pasVertices[psInfo->iCurItem++].y = CPLAtof(pszLine+42);
         }
     }
-    else if (psInfo->iCurItem < psInfo->numItems && 
+    else if (psInfo->iCurItem < psInfo->numItems &&
              psInfo->nPrecision == AVC_DOUBLE_PREC &&
              nLen >= 42)
     {
@@ -760,7 +759,7 @@ AVCArc   *AVCE00ParseNextArcLine(AVCE00ParseInfo *psInfo, const char *pszLine)
     }
     else
     {
-        CPLError(CE_Failure, CPLE_AppDefined, 
+        CPLError(CE_Failure, CPLE_AppDefined,
                  "Error parsing E00 ARC line: \"%s\"", pszLine);
         psInfo->numItems = psInfo->iCurItem = 0;
         return NULL;
@@ -795,12 +794,12 @@ AVCArc   *AVCE00ParseNextArcLine(AVCE00ParseInfo *psInfo, const char *pszLine)
  *
  * If the input is invalid or other problems happen, then a CPLError()
  * will be generated.  CPLGetLastErrorNo() should be called to check
- * that the line was parsed succesfully.
+ * that the line was parsed successfully.
  **********************************************************************/
 AVCPal   *AVCE00ParseNextPalLine(AVCE00ParseInfo *psInfo, const char *pszLine)
 {
     AVCPal *psPal;
-    int     nLen;
+    size_t  nLen;
 
     CPLAssert(psInfo->eFileType == AVCFilePAL ||
               psInfo->eFileType == AVCFileRPL );
@@ -818,14 +817,14 @@ AVCPal   *AVCE00ParseNextPalLine(AVCE00ParseInfo *psInfo, const char *pszLine)
          *------------------------------------------------------------*/
         if (nLen < 52)
         {
-            CPLError(CE_Failure, CPLE_AppDefined, 
+            CPLError(CE_Failure, CPLE_AppDefined,
                      "Error parsing E00 PAL line: \"%s\"", pszLine);
             return NULL;
         }
         else
         {
             /* Polygon Id is not stored in the E00 file.  Polygons are
-             * stored in increasing order, starting at 1... so we just 
+             * stored in increasing order, starting at 1... so we just
              * increment the previous value.
              */
             psPal->nPolyId = ++psInfo->nCurObjectId;
@@ -877,12 +876,12 @@ AVCPal   *AVCE00ParseNextPalLine(AVCE00ParseInfo *psInfo, const char *pszLine)
         psPal->sMax.y = CPLAtof(pszLine + 21);
         psInfo->iCurItem++;
     }
-    else if (psInfo->iCurItem < psPal->numArcs && 
+    else if (psInfo->iCurItem < psPal->numArcs &&
              (nLen >= 60 ||
               (psInfo->iCurItem == psPal->numArcs-1 && nLen >= 30)) )
     {
         /*-------------------------------------------------------------
-         * 2 PAL entries (ArcId, FNode, AdjPoly) per line, 
+         * 2 PAL entries (ArcId, FNode, AdjPoly) per line,
          * (Except on the last line with an odd number of vertices)
          *------------------------------------------------------------*/
         psPal->pasArcs[psInfo->iCurItem].nArcId = AVCE00Str2Int(pszLine, 10);
@@ -896,14 +895,14 @@ AVCPal   *AVCE00ParseNextPalLine(AVCE00ParseInfo *psInfo, const char *pszLine)
                                                                     10);
             psPal->pasArcs[psInfo->iCurItem].nFNode = AVCE00Str2Int(pszLine+40,
                                                                     10);
-            psPal->pasArcs[psInfo->iCurItem++].nAdjPoly = 
+            psPal->pasArcs[psInfo->iCurItem++].nAdjPoly =
                                                 AVCE00Str2Int(pszLine+50, 10);
         }
- 
+
     }
     else
     {
-        CPLError(CE_Failure, CPLE_AppDefined, 
+        CPLError(CE_Failure, CPLE_AppDefined,
                  "Error parsing E00 PAL line: \"%s\"", pszLine);
         psInfo->numItems = psInfo->iCurItem = 0;
         return NULL;
@@ -939,12 +938,12 @@ AVCPal   *AVCE00ParseNextPalLine(AVCE00ParseInfo *psInfo, const char *pszLine)
  *
  * If the input is invalid or other problems happen, then a CPLError()
  * will be generated.  CPLGetLastErrorNo() should be called to check
- * that the line was parsed succesfully.
+ * that the line was parsed successfully.
  **********************************************************************/
 AVCCnt   *AVCE00ParseNextCntLine(AVCE00ParseInfo *psInfo, const char *pszLine)
 {
     AVCCnt *psCnt;
-    int     nLen;
+    size_t  nLen;
 
     CPLAssert(psInfo->eFileType == AVCFileCNT);
 
@@ -960,7 +959,7 @@ AVCCnt   *AVCE00ParseNextCntLine(AVCE00ParseInfo *psInfo, const char *pszLine)
          *------------------------------------------------------------*/
         if (nLen < 38)
         {
-            CPLError(CE_Failure, CPLE_AppDefined, 
+            CPLError(CE_Failure, CPLE_AppDefined,
                      "Error parsing E00 CNT line: \"%s\"", pszLine);
             return NULL;
         }
@@ -1007,10 +1006,10 @@ AVCCnt   *AVCE00ParseNextCntLine(AVCE00ParseInfo *psInfo, const char *pszLine)
         /*-------------------------------------------------------------
          * Each line can contain up to 8 label ids (10 chars each)
          *------------------------------------------------------------*/
-        int i=0;
+        size_t i=0;
         while(psInfo->iCurItem < psInfo->numItems && nLen >= (i+1)*10)
         {
-            psCnt->panLabelIds[psInfo->iCurItem++] = 
+            psCnt->panLabelIds[psInfo->iCurItem++] =
                                   AVCE00Str2Int(pszLine + i*10, 10);
             i++;
         }
@@ -1018,7 +1017,7 @@ AVCCnt   *AVCE00ParseNextCntLine(AVCE00ParseInfo *psInfo, const char *pszLine)
     }
     else
     {
-        CPLError(CE_Failure, CPLE_AppDefined, 
+        CPLError(CE_Failure, CPLE_AppDefined,
                  "Error parsing E00 CNT line: \"%s\"", pszLine);
         psInfo->numItems = psInfo->iCurItem = 0;
         return NULL;
@@ -1053,12 +1052,12 @@ AVCCnt   *AVCE00ParseNextCntLine(AVCE00ParseInfo *psInfo, const char *pszLine)
  *
  * If the input is invalid or other problems happen, then a CPLError()
  * will be generated.  CPLGetLastErrorNo() should be called to check
- * that the line was parsed succesfully.
+ * that the line was parsed successfully.
  **********************************************************************/
 AVCLab   *AVCE00ParseNextLabLine(AVCE00ParseInfo *psInfo, const char *pszLine)
 {
     AVCLab *psLab;
-    int     nLen;
+    size_t  nLen;
 
     CPLAssert(psInfo->eFileType == AVCFileLAB);
 
@@ -1128,7 +1127,7 @@ AVCLab   *AVCE00ParseNextLabLine(AVCE00ParseInfo *psInfo, const char *pszLine)
     }
     else
     {
-        CPLError(CE_Failure, CPLE_AppDefined, 
+        CPLError(CE_Failure, CPLE_AppDefined,
                  "Error parsing E00 LAB line: \"%s\"", pszLine);
         psInfo->numItems = psInfo->iCurItem = 0;
         return NULL;
@@ -1165,12 +1164,12 @@ AVCLab   *AVCE00ParseNextLabLine(AVCE00ParseInfo *psInfo, const char *pszLine)
  *
  * If the input is invalid or other problems happen, then a CPLError()
  * will be generated.  CPLGetLastErrorNo() should be called to check
- * that the line was parsed succesfully.
+ * that the line was parsed successfully.
  **********************************************************************/
 AVCTol   *AVCE00ParseNextTolLine(AVCE00ParseInfo *psInfo, const char *pszLine)
 {
     AVCTol *psTol;
-    int     nLen;
+    size_t  nLen;
 
     CPLAssert(psInfo->eFileType == AVCFileTOL);
 
@@ -1191,7 +1190,7 @@ AVCTol   *AVCE00ParseNextTolLine(AVCE00ParseInfo *psInfo, const char *pszLine)
     }
     else
     {
-        CPLError(CE_Failure, CPLE_AppDefined, 
+        CPLError(CE_Failure, CPLE_AppDefined,
                  "Error parsing E00 TOL line: \"%s\"", pszLine);
         psInfo->numItems = psInfo->iCurItem = 0;
         return NULL;
@@ -1232,7 +1231,7 @@ AVCTol   *AVCE00ParseNextTolLine(AVCE00ParseInfo *psInfo, const char *pszLine)
  *
  * If the input is invalid or other problems happen, then a CPLError()
  * will be generated.  CPLGetLastErrorNo() should be called to check
- * that the line was parsed succesfully.
+ * that the line was parsed successfully.
  **********************************************************************/
 char  **AVCE00ParseNextPrjLine(AVCE00ParseInfo *psInfo, const char *pszLine)
 {
@@ -1246,7 +1245,7 @@ char  **AVCE00ParseNextPrjLine(AVCE00ParseInfo *psInfo, const char *pszLine)
      * of the section (the end-of-section line).
      *------------------------------------------------------------*/
 
-    if (EQUALN(pszLine, "EOP", 3))
+    if (STARTS_WITH_CI(pszLine, "EOP"))
     {
         /*-------------------------------------------------------------
          * We reached end of section... return the PRJ.
@@ -1271,17 +1270,17 @@ char  **AVCE00ParseNextPrjLine(AVCE00ParseInfo *psInfo, const char *pszLine)
         int  iLastLine, nNewLen;
 
         iLastLine = CSLCount(psInfo->cur.papszPrj) - 1;
-        nNewLen = strlen(psInfo->cur.papszPrj[iLastLine])+strlen(pszLine)-1+1;
+        nNewLen = (int)strlen(psInfo->cur.papszPrj[iLastLine])+(int)strlen(pszLine)-1+1;
         if (iLastLine >= 0)
         {
-            psInfo->cur.papszPrj[iLastLine] = 
+            psInfo->cur.papszPrj[iLastLine] =
                   (char*)CPLRealloc(psInfo->cur.papszPrj[iLastLine],
                                     nNewLen * sizeof(char));
 
             strcat(psInfo->cur.papszPrj[iLastLine], pszLine+1);
         }
     }
-    
+
     return NULL;
 }
 
@@ -1300,12 +1299,13 @@ char  **AVCE00ParseNextPrjLine(AVCE00ParseInfo *psInfo, const char *pszLine)
  *
  * If the input is invalid or other problems happen, then a CPLError()
  * will be generated.  CPLGetLastErrorNo() should be called to check
- * that the line was parsed succesfully.
+ * that the line was parsed successfully.
  **********************************************************************/
 AVCTxt   *AVCE00ParseNextTxtLine(AVCE00ParseInfo *psInfo, const char *pszLine)
 {
     AVCTxt *psTxt;
-    int     i, nLen, numFixedLines;
+    int     i, numFixedLines;
+    size_t  nLen;
 
     CPLAssert(psInfo->eFileType == AVCFileTXT);
 
@@ -1314,7 +1314,7 @@ AVCTxt   *AVCE00ParseNextTxtLine(AVCE00ParseInfo *psInfo, const char *pszLine)
     nLen = strlen(pszLine);
 
     /* numFixedLines is the number of lines to expect before the line(s)
-     * with the text string 
+     * with the text string
      */
     if (psInfo->nPrecision == AVC_SINGLE_PREC)
         numFixedLines = 4;
@@ -1328,7 +1328,7 @@ AVCTxt   *AVCE00ParseNextTxtLine(AVCE00ParseInfo *psInfo, const char *pszLine)
          *------------------------------------------------------------*/
         if (nLen < 50)
         {
-            CPLError(CE_Failure, CPLE_AppDefined, 
+            CPLError(CE_Failure, CPLE_AppDefined,
                      "Error parsing E00 TXT line: \"%s\"", pszLine);
             return NULL;
         }
@@ -1354,7 +1354,7 @@ AVCTxt   *AVCE00ParseNextTxtLine(AVCE00ParseInfo *psInfo, const char *pszLine)
 
             psTxt->nLevel          = AVCE00Str2Int(pszLine, 10);
 
-            /* Add 1 to numVerticesLine because the first vertex is 
+            /* Add 1 to numVerticesLine because the first vertex is
              * always duplicated in the TXT binary structure...
              */
             psTxt->numVerticesLine = AVCE00Str2Int(pszLine+10, 10) + 1;
@@ -1370,7 +1370,7 @@ AVCTxt   *AVCE00ParseNextTxtLine(AVCE00ParseInfo *psInfo, const char *pszLine)
             psTxt->pszText = (GByte *)CPLRealloc(psTxt->pszText,
                                                  (psTxt->numChars+1)*
                                                      sizeof(GByte));
-            numVertices = ABS(psTxt->numVerticesLine) + 
+            numVertices = ABS(psTxt->numVerticesLine) +
                                  ABS(psTxt->numVerticesArrow);
             if (numVertices > 0)
                 psTxt->pasVertices = (AVCVertex*)CPLRealloc(psTxt->pasVertices,
@@ -1423,7 +1423,7 @@ AVCTxt   *AVCE00ParseNextTxtLine(AVCE00ParseInfo *psInfo, const char *pszLine)
 
         for(i=0; i<numCoordPerLine; i++, iCurCoord++)
         {
-            if (iCurCoord < 4 && 
+            if (iCurCoord < 4 &&
                 (iVertex = iCurCoord % 4) < psTxt->numVerticesLine-1)
             {
                 psTxt->pasVertices[iVertex+1].x = CPLAtof(pszLine+i*nItemSize);
@@ -1484,8 +1484,8 @@ AVCTxt   *AVCE00ParseNextTxtLine(AVCE00ParseInfo *psInfo, const char *pszLine)
 
         if (iLine == numLines-1)
         {
-            strncpy((char*)psTxt->pszText+(iLine*80), pszLine, 
-                    MIN( nLen, (psTxt->numChars - (iLine*80)) ) );
+            strncpy((char*)psTxt->pszText+(iLine*80), pszLine,
+                    MIN( (int)nLen, (psTxt->numChars - (iLine*80)) ) );
         }
         else
         {
@@ -1496,7 +1496,7 @@ AVCTxt   *AVCE00ParseNextTxtLine(AVCE00ParseInfo *psInfo, const char *pszLine)
     }
     else
     {
-        CPLError(CE_Failure, CPLE_AppDefined, 
+        CPLError(CE_Failure, CPLE_AppDefined,
                  "Error parsing E00 TXT line: \"%s\"", pszLine);
         psInfo->numItems = psInfo->iCurItem = 0;
         return NULL;
@@ -1532,12 +1532,13 @@ AVCTxt   *AVCE00ParseNextTxtLine(AVCE00ParseInfo *psInfo, const char *pszLine)
  *
  * If the input is invalid or other problems happen, then a CPLError()
  * will be generated.  CPLGetLastErrorNo() should be called to check
- * that the line was parsed succesfully.
+ * that the line was parsed successfully.
  **********************************************************************/
 AVCTxt   *AVCE00ParseNextTx6Line(AVCE00ParseInfo *psInfo, const char *pszLine)
 {
     AVCTxt *psTxt;
-    int     i, nLen;
+    int     i;
+    size_t  nLen;
 
     CPLAssert(psInfo->eFileType == AVCFileTX6);
 
@@ -1552,7 +1553,7 @@ AVCTxt   *AVCE00ParseNextTx6Line(AVCE00ParseInfo *psInfo, const char *pszLine)
          *------------------------------------------------------------*/
         if (nLen < 70)
         {
-            CPLError(CE_Failure, CPLE_AppDefined, 
+            CPLError(CE_Failure, CPLE_AppDefined,
                      "Error parsing E00 TX6/TX7 line: \"%s\"", pszLine);
             return NULL;
         }
@@ -1581,7 +1582,7 @@ AVCTxt   *AVCE00ParseNextTx6Line(AVCE00ParseInfo *psInfo, const char *pszLine)
                                                  (psTxt->numChars+1)*
                                                  sizeof(GByte));
 
-            numVertices = ABS(psTxt->numVerticesLine) + 
+            numVertices = ABS(psTxt->numVerticesLine) +
                                  ABS(psTxt->numVerticesArrow);
             if (numVertices > 0)
                 psTxt->pasVertices = (AVCVertex*)CPLRealloc(psTxt->pasVertices,
@@ -1602,7 +1603,7 @@ AVCTxt   *AVCE00ParseNextTx6Line(AVCE00ParseInfo *psInfo, const char *pszLine)
             psInfo->numItems = 8 + numVertices + ((psTxt->numChars-1)/80 + 1);
         }
     }
-    else if (psInfo->iCurItem < psInfo->numItems && 
+    else if (psInfo->iCurItem < psInfo->numItems &&
              psInfo->iCurItem < 6 && nLen >=60)
     {
         /*-------------------------------------------------------------
@@ -1621,11 +1622,11 @@ AVCTxt   *AVCE00ParseNextTx6Line(AVCE00ParseInfo *psInfo, const char *pszLine)
             numValPerLine = 6;
 
         for(i=0; i<numValPerLine; i++)
-            pValue[i] = AVCE00Str2Int(pszLine + i*10, 10);
+            pValue[i] = (GInt16)AVCE00Str2Int(pszLine + i*10, 10);
 
         psInfo->iCurItem++;
     }
-    else if (psInfo->iCurItem < psInfo->numItems && 
+    else if (psInfo->iCurItem < psInfo->numItems &&
              psInfo->iCurItem == 6 && nLen >=14)
     {
         /*-------------------------------------------------------------
@@ -1634,7 +1635,7 @@ AVCTxt   *AVCE00ParseNextTx6Line(AVCE00ParseInfo *psInfo, const char *pszLine)
         psTxt->f_1e2 = (float)CPLAtof(pszLine);
         psInfo->iCurItem++;
     }
-    else if (psInfo->iCurItem < psInfo->numItems && 
+    else if (psInfo->iCurItem < psInfo->numItems &&
              psInfo->iCurItem == 7 && nLen >=42)
     {
         /*-------------------------------------------------------------
@@ -1654,7 +1655,7 @@ AVCTxt   *AVCE00ParseNextTx6Line(AVCE00ParseInfo *psInfo, const char *pszLine)
 
         psInfo->iCurItem++;
     }
-    else if (psInfo->iCurItem < (8 + ABS(psTxt->numVerticesLine) + 
+    else if (psInfo->iCurItem < (8 + ABS(psTxt->numVerticesLine) +
                                    ABS(psTxt->numVerticesArrow)) && nLen >= 28)
     {
         /*-------------------------------------------------------------
@@ -1682,8 +1683,8 @@ AVCTxt   *AVCE00ParseNextTx6Line(AVCE00ParseInfo *psInfo, const char *pszLine)
 
         if (iLine == numLines-1)
         {
-            strncpy((char*)psTxt->pszText+(iLine*80), pszLine, 
-                    MIN( nLen, (psTxt->numChars - (iLine*80)) ) );
+            strncpy((char*)psTxt->pszText+(iLine*80), pszLine,
+                    MIN( (int)nLen, (psTxt->numChars - (iLine*80)) ) );
         }
         else
         {
@@ -1694,7 +1695,7 @@ AVCTxt   *AVCE00ParseNextTx6Line(AVCE00ParseInfo *psInfo, const char *pszLine)
     }
     else
     {
-        CPLError(CE_Failure, CPLE_AppDefined, 
+        CPLError(CE_Failure, CPLE_AppDefined,
                  "Error parsing E00 TX6/TX7 line: \"%s\"", pszLine);
         psInfo->numItems = psInfo->iCurItem = 0;
         return NULL;
@@ -1731,12 +1732,12 @@ AVCTxt   *AVCE00ParseNextTx6Line(AVCE00ParseInfo *psInfo, const char *pszLine)
  *
  * If the input is invalid or other problems happen, then a CPLError()
  * will be generated.  CPLGetLastErrorNo() should be called to check
- * that the line was parsed succesfully.
+ * that the line was parsed successfully.
  **********************************************************************/
 AVCRxp   *AVCE00ParseNextRxpLine(AVCE00ParseInfo *psInfo, const char *pszLine)
 {
     AVCRxp *psRxp;
-    int     nLen;
+    size_t  nLen;
 
     CPLAssert(psInfo->eFileType == AVCFileRXP);
 
@@ -1755,7 +1756,7 @@ AVCRxp   *AVCE00ParseNextRxpLine(AVCE00ParseInfo *psInfo, const char *pszLine)
     }
     else
     {
-        CPLError(CE_Failure, CPLE_AppDefined, 
+        CPLError(CE_Failure, CPLE_AppDefined,
                  "Error parsing E00 RXP line: \"%s\"", pszLine);
         psInfo->numItems = psInfo->iCurItem = 0;
         return NULL;
@@ -1795,13 +1796,13 @@ AVCRxp   *AVCE00ParseNextRxpLine(AVCE00ParseInfo *psInfo, const char *pszLine)
  *
  * If the input is invalid or other problems happen, then a CPLError()
  * will be generated.  CPLGetLastErrorNo() should be called to check
- * that the line was parsed succesfully.
+ * that the line was parsed successfully.
  **********************************************************************/
-AVCTableDef   *AVCE00ParseNextTableDefLine(AVCE00ParseInfo *psInfo, 
+AVCTableDef   *AVCE00ParseNextTableDefLine(AVCE00ParseInfo *psInfo,
                                            const char *pszLine)
 {
     AVCTableDef *psTableDef;
-    int     nLen;
+    size_t   nLen;
 
     CPLAssert(psInfo->eFileType == AVCFileTABLE);
 
@@ -1818,7 +1819,7 @@ AVCTableDef   *AVCE00ParseNextTableDefLine(AVCE00ParseInfo *psInfo,
         if (nLen < 56)
         {
             CPLError(CE_Failure, CPLE_AppDefined,
-                     "Error parsing E00 Table Definition line: \"%s\"", 
+                     "Error parsing E00 Table Definition line: \"%s\"",
                      pszLine);
             return NULL;
         }
@@ -1827,7 +1828,7 @@ AVCTableDef   *AVCE00ParseNextTableDefLine(AVCE00ParseInfo *psInfo,
             /*---------------------------------------------------------
              * Parse header line and alloc and init. a new psTableDef struct
              *--------------------------------------------------------*/
-            psTableDef = psInfo->hdr.psTableDef = 
+            psTableDef = psInfo->hdr.psTableDef =
                                (AVCTableDef*)CPLCalloc(1, sizeof(AVCTableDef));
             psInfo->bTableHdrComplete = FALSE;
 
@@ -1836,14 +1837,14 @@ AVCTableDef   *AVCE00ParseNextTableDefLine(AVCE00ParseInfo *psInfo,
             strncpy(psTableDef->szExternal, pszLine+32, 2);
             psTableDef->szExternal[2] = '\0';
 
-            psTableDef->numFields  = AVCE00Str2Int(pszLine+34, 4);
-            psTableDef->nRecSize   = AVCE00Str2Int(pszLine+42, 4);
+            psTableDef->numFields  = (GInt16)AVCE00Str2Int(pszLine+34, 4);
+            psTableDef->nRecSize   = (GInt16)AVCE00Str2Int(pszLine+42, 4);
             psTableDef->numRecords = AVCE00Str2Int(pszLine+46, 10);
 
             /*---------------------------------------------------------
              * Alloc array of fields defs, will be filled in further calls
              *--------------------------------------------------------*/
-            psTableDef->pasFieldDef = 
+            psTableDef->pasFieldDef =
                     (AVCFieldInfo*)CPLCalloc(psTableDef->numFields,
                                              sizeof(AVCFieldInfo));
 
@@ -1870,7 +1871,7 @@ AVCTableDef   *AVCE00ParseNextTableDefLine(AVCE00ParseInfo *psInfo,
 
         if (nIndex > 0 && psInfo->nCurObjectId >= psTableDef->numFields)
         {
-            CPLError(CE_Failure, CPLE_AppDefined, 
+            CPLError(CE_Failure, CPLE_AppDefined,
                      "Error parsing E00 INFO Table Header: "
                      "number of fields is invalid "
                      "(expected %d, got at least %d)",
@@ -1884,26 +1885,26 @@ AVCTableDef   *AVCE00ParseNextTableDefLine(AVCE00ParseInfo *psInfo,
             AVCFieldInfo *psDef;
             psDef = &(psTableDef->pasFieldDef[psInfo->iCurItem]);
 
-            psDef->nIndex   = nIndex;
-            
+            psDef->nIndex   = (GInt16)nIndex;
+
             strncpy(psDef->szName, pszLine, 16);
             psDef->szName[16] = '\0';
 
-            psDef->nSize    = AVCE00Str2Int(pszLine + 16, 3);
-            psDef->v2       = AVCE00Str2Int(pszLine + 19, 2);
+            psDef->nSize    = (GInt16)AVCE00Str2Int(pszLine + 16, 3);
+            psDef->v2       = (GInt16)AVCE00Str2Int(pszLine + 19, 2);
 
-            psDef->nOffset  = AVCE00Str2Int(pszLine + 21, 4);
+            psDef->nOffset  = (GInt16)AVCE00Str2Int(pszLine + 21, 4);
 
-            psDef->v4       = AVCE00Str2Int(pszLine + 25, 1);
-            psDef->v5       = AVCE00Str2Int(pszLine + 26, 2);
-            psDef->nFmtWidth= AVCE00Str2Int(pszLine + 28, 4);
-            psDef->nFmtPrec = AVCE00Str2Int(pszLine + 32, 2);
-            psDef->nType1   = AVCE00Str2Int(pszLine + 34, 3)/10;
+            psDef->v4       = (GInt16)AVCE00Str2Int(pszLine + 25, 1);
+            psDef->v5       = (GInt16)AVCE00Str2Int(pszLine + 26, 2);
+            psDef->nFmtWidth= (GInt16)AVCE00Str2Int(pszLine + 28, 4);
+            psDef->nFmtPrec = (GInt16)AVCE00Str2Int(pszLine + 32, 2);
+            psDef->nType1   = (GInt16)AVCE00Str2Int(pszLine + 34, 3)/10;
             psDef->nType2   = AVCE00Str2Int(pszLine + 34, 3)%10;
-            psDef->v10      = AVCE00Str2Int(pszLine + 37, 2);
-            psDef->v11      = AVCE00Str2Int(pszLine + 39, 4);
-            psDef->v12      = AVCE00Str2Int(pszLine + 43, 4);
-            psDef->v13      = AVCE00Str2Int(pszLine + 47, 2);
+            psDef->v10      = (GInt16)AVCE00Str2Int(pszLine + 37, 2);
+            psDef->v11      = (GInt16)AVCE00Str2Int(pszLine + 39, 4);
+            psDef->v12      = (GInt16)AVCE00Str2Int(pszLine + 43, 4);
+            psDef->v13      = (GInt16)AVCE00Str2Int(pszLine + 47, 2);
 
             strncpy(psDef->szAltName, pszLine+49, 16);
             psDef->szAltName[16] = '\0';
@@ -1914,7 +1915,7 @@ AVCTableDef   *AVCE00ParseNextTableDefLine(AVCE00ParseInfo *psInfo,
     }
     else
     {
-        CPLError(CE_Failure, CPLE_AppDefined, 
+        CPLError(CE_Failure, CPLE_AppDefined,
                  "Error parsing E00 Table Definition line: \"%s\"", pszLine);
         psInfo->numItems = psInfo->iCurItem = 0;
         return NULL;
@@ -1954,7 +1955,7 @@ AVCTableDef   *AVCE00ParseNextTableDefLine(AVCE00ParseInfo *psInfo,
  * Parse the record data present inside psInfo->pszBuf and fill and
  * return the psInfo->cur.pasFields[].
  *
- * This function should not be called directly... it is used by 
+ * This function should not be called directly... it is used by
  * AVCE00ParseNextTableRecLine().
  **********************************************************************/
 static AVCField   *_AVCE00ParseTableRecord(AVCE00ParseInfo *psInfo)
@@ -2000,7 +2001,7 @@ static AVCField   *_AVCE00ParseTableRecord(AVCE00ParseInfo *psInfo)
              * exponent format, but in this case the decimal point is shifted
              * one position to the right, resulting in a value 10 times bigger
              * than expected.  So if the value is not in exponent format then
-             * we should shift the decimal point to the left before we 
+             * we should shift the decimal point to the left before we
              * interpret it.  (bug 599)
              */
             if (!strchr(szTmp, 'E') && !strchr(szTmp, 'e'))
@@ -2017,10 +2018,10 @@ static AVCField   *_AVCE00ParseTableRecord(AVCE00ParseInfo *psInfo)
              * be different from nSize, but nSize has priority since it
              * is the actual size of the field in memory.
              */
-            sprintf(szFormat, "%%%d.%df", nSize, pasDef[i].nFmtPrec);
+            snprintf(szFormat, sizeof(szFormat), "%%%d.%df", nSize, pasDef[i].nFmtPrec);
             pszTmpStr = CPLSPrintf(szFormat, CPLAtof(szTmp));
 
-            /* If value is bigger than size, then it's too bad... we 
+            /* If value is bigger than size, then it's too bad... we
              * truncate it... but this should never happen in clean datasets.
              */
             if ((int)strlen(pszTmpStr) > nSize)
@@ -2035,7 +2036,7 @@ static AVCField   *_AVCE00ParseTableRecord(AVCE00ParseInfo *psInfo)
         }
         else if (nType == AVC_FT_BININT && nSize == 2)
         {
-            pasFields[i].nInt16 = AVCE00Str2Int(pszBuf, 6);
+            pasFields[i].nInt16 = (GInt16)AVCE00Str2Int(pszBuf, 6);
             pszBuf += 6;
         }
         else if (nType == AVC_FT_BINFLOAT && pasDef[i].nSize == 4)
@@ -2092,9 +2093,9 @@ static AVCField   *_AVCE00ParseTableRecord(AVCE00ParseInfo *psInfo)
  *
  * If the input is invalid or other problems happen, then a CPLError()
  * will be generated.  CPLGetLastErrorNo() should be called to check
- * that the line was parsed succesfully.
+ * that the line was parsed successfully.
  **********************************************************************/
-AVCField   *AVCE00ParseNextTableRecLine(AVCE00ParseInfo *psInfo, 
+AVCField   *AVCE00ParseNextTableRecLine(AVCE00ParseInfo *psInfo,
                                         const char *pszLine)
 {
     AVCField    *pasFields = NULL;
@@ -2125,9 +2126,13 @@ AVCField   *AVCE00ParseNextTableRecLine(AVCE00ParseInfo *psInfo,
         /*-------------------------------------------------------------
          * Realloc E00 buffer
          *------------------------------------------------------------*/
-        psInfo->nTableE00RecLength = 
-            _AVCE00ComputeRecSize(psTableDef->numFields, 
+        psInfo->nTableE00RecLength =
+            _AVCE00ComputeRecSize(psTableDef->numFields,
                                   psTableDef->pasFieldDef, FALSE);
+        if( psInfo->nTableE00RecLength < 0 )
+        {
+            return NULL;
+        }
 
         if (psInfo->nBufSize < psInfo->nTableE00RecLength + 1)
         {
@@ -2149,8 +2154,8 @@ AVCField   *AVCE00ParseNextTableRecLine(AVCE00ParseInfo *psInfo,
                 psTableDef->pasFieldDef[i].nType1*10 == AVC_FT_FIXINT ||
                 psTableDef->pasFieldDef[i].nType1*10 == AVC_FT_FIXNUM )
             {
-                psInfo->cur.pasFields[i].pszStr = 
-                    (GByte*)CPLCalloc(psTableDef->pasFieldDef[i].nSize+1, 
+                psInfo->cur.pasFields[i].pszStr =
+                    (GByte*)CPLCalloc(psTableDef->pasFieldDef[i].nSize+1,
                                       sizeof(GByte));
             }
         }
@@ -2161,7 +2166,7 @@ AVCField   *AVCE00ParseNextTableRecLine(AVCE00ParseInfo *psInfo,
     {
     /*-----------------------------------------------------------------
      * Begin processing a new record... we'll accumulate the 80
-     * chars lines until we have the whole record in our buffer 
+     * chars lines until we have the whole record in our buffer
      * and parse it only at the end.
      * Lines shorter than 80 chars are legal, and in this case
      * they will be padded with spaces up to 80 chars.
@@ -2187,14 +2192,14 @@ AVCField   *AVCE00ParseNextTableRecLine(AVCE00ParseInfo *psInfo,
     if (psInfo->iCurItem < psInfo->numItems)
     {
         /*-------------------------------------------------------------
-         * Continue to accumulate the 80 chars lines until we have 
+         * Continue to accumulate the 80 chars lines until we have
          * the whole record in our buffer.  We'll parse it only at the end.
          * Lines shorter than 80 chars are legal, and in this case
          * they padded with spaces up to 80 chars.
          *------------------------------------------------------------*/
         int nSrcLen, nLenToCopy;
 
-        nSrcLen = strlen(pszLine);
+        nSrcLen = (int)strlen(pszLine);
         nLenToCopy = MIN(80, MIN(nSrcLen,(psInfo->numItems-psInfo->iCurItem)));
         strncpy(psInfo->pszBuf+psInfo->iCurItem, pszLine, nLenToCopy);
 
@@ -2212,8 +2217,8 @@ AVCField   *AVCE00ParseNextTableRecLine(AVCE00ParseInfo *psInfo,
 
         if (pasFields == NULL)
         {
-            CPLError(CE_Failure, CPLE_AppDefined, 
-                     "Error parsing E00 Table Record: \"%s\"", 
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Error parsing E00 Table Record: \"%s\"",
                      psInfo->pszBuf);
             return NULL;
         }
@@ -2223,7 +2228,7 @@ AVCField   *AVCE00ParseNextTableRecLine(AVCE00ParseInfo *psInfo,
     }
 
     /*-----------------------------------------------------------------
-     * Since there is no explicit "end of table" line, we set the 
+     * Since there is no explicit "end of table" line, we set the
      * bForceEndOfSection flag when the last record is read.
      *----------------------------------------------------------------*/
     if (psInfo->nCurObjectId >= psTableDef->numRecords)
@@ -2233,5 +2238,3 @@ AVCField   *AVCE00ParseNextTableRecLine(AVCE00ParseInfo *psInfo,
 
     return pasFields;
 }
-
-
diff --git a/ogr/ogrsf_frmts/avc/avc_e00read.c b/ogr/ogrsf_frmts/avc/avc_e00read.c
index b7f5932..c558cfb 100644
--- a/ogr/ogrsf_frmts/avc/avc_e00read.c
+++ b/ogr/ogrsf_frmts/avc/avc_e00read.c
@@ -18,16 +18,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -157,7 +157,7 @@ static AVCCoverType _AVCE00ReadFindCoverType(char **papszCoverDir);
  *               /home/data/country/arc.adf
  * (Of course you should replace the '/' with '\\' on DOS systems!)
  *
- * Returns a new AVCE00ReadPtr handle or NULL if the coverage could 
+ * Returns a new AVCE00ReadPtr handle or NULL if the coverage could
  * not be opened or if it does not appear to be a valid Arc/Info coverage.
  *
  * The handle will eventually have to be released with AVCE00ReadClose().
@@ -178,8 +178,8 @@ AVCE00ReadPtr  AVCE00ReadOpen(const char *pszCoverPath)
     if (pszCoverPath == NULL || strlen(pszCoverPath) == 0 ||
         VSIStat(pszCoverPath, &sStatBuf) == -1)
     {
-        CPLError(CE_Failure, CPLE_OpenFailed, 
-                 "Invalid coverage path: %s.", 
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "Invalid coverage path: %s.",
                  pszCoverPath?pszCoverPath:"(NULL)");
         return NULL;
     }
@@ -201,10 +201,10 @@ AVCE00ReadPtr  AVCE00ReadOpen(const char *pszCoverPath)
     if (VSI_ISDIR(sStatBuf.st_mode))
     {
         /*-------------------------------------------------------------
-         * OK, we have a valid directory name... make sure it is 
+         * OK, we have a valid directory name... make sure it is
          * terminated with a '/' (or '\\')
          *------------------------------------------------------------*/
-        nLen = strlen(pszCoverPath);
+        nLen = (int)strlen(pszCoverPath);
 
         if (pszCoverPath[nLen-1] == '/' || pszCoverPath[nLen-1] == '\\')
             psInfo->pszCoverPath = CPLStrdup(pszCoverPath);
@@ -226,7 +226,7 @@ AVCE00ReadPtr  AVCE00ReadOpen(const char *pszCoverPath)
          *------------------------------------------------------------*/
         psInfo->pszCoverPath = CPLStrdup(pszCoverPath);
 
-        for( i = strlen(psInfo->pszCoverPath)-1; 
+        for( i = (int)strlen(psInfo->pszCoverPath)-1;
              i > 0 && psInfo->pszCoverPath[i] != '/' &&
                  psInfo->pszCoverPath[i] != '\\';
              i-- ) {}
@@ -243,11 +243,11 @@ AVCE00ReadPtr  AVCE00ReadOpen(const char *pszCoverPath)
      * but for now we'll just produce an error if this happens.
      *----------------------------------------------------------------*/
     nLen = 0;
-    for( i = strlen(psInfo->pszCoverPath)-1; 
+    for( i = (int)strlen(psInfo->pszCoverPath)-1;
 	 i > 0 && psInfo->pszCoverPath[i-1] != '/' &&
 	          psInfo->pszCoverPath[i-1] != '\\'&&
 	          psInfo->pszCoverPath[i-1] != ':';
-	 i-- ) 
+	 i-- )
     {
         nLen++;
     }
@@ -259,7 +259,7 @@ AVCE00ReadPtr  AVCE00ReadOpen(const char *pszCoverPath)
     }
     else
     {
-        CPLError(CE_Failure, CPLE_OpenFailed, 
+        CPLError(CE_Failure, CPLE_OpenFailed,
                  "Invalid coverage path (%s): "
                  "coverage name must be included in path.", pszCoverPath);
 
@@ -271,13 +271,13 @@ AVCE00ReadPtr  AVCE00ReadOpen(const char *pszCoverPath)
     /*-----------------------------------------------------------------
      * Read the coverage directory listing and try to establish the cover type
      *----------------------------------------------------------------*/
-    papszCoverDir = CPLReadDir(psInfo->pszCoverPath);
+    papszCoverDir = VSIReadDir(psInfo->pszCoverPath);
 
     psInfo->eCoverType = _AVCE00ReadFindCoverType(papszCoverDir);
 
     if (psInfo->eCoverType == AVCCoverTypeUnknown  )
     {
-        CPLError(CE_Failure, CPLE_OpenFailed, 
+        CPLError(CE_Failure, CPLE_OpenFailed,
                  "Invalid coverage (%s): directory does not appear to "
                  "contain any supported vector coverage file.",  pszCoverPath);
         CPLFree(psInfo->pszCoverName);
@@ -288,7 +288,6 @@ AVCE00ReadPtr  AVCE00ReadOpen(const char *pszCoverPath)
         return NULL;
     }
 
-   
     /*-----------------------------------------------------------------
      * INFO path: PC Coverages have all files in the same dir, and unix
      * covers have the INFO files in ../info
@@ -303,34 +302,34 @@ AVCE00ReadPtr  AVCE00ReadOpen(const char *pszCoverPath)
          * Lazy way to build the INFO path: simply add "../info/"...
          * this could probably be improved!
          *------------------------------------------------------------*/
-        psInfo->pszInfoPath =(char*)CPLMalloc((strlen(psInfo->pszCoverPath)+9)*
-                                           sizeof(char));
+        size_t nInfoPathLen = strlen(psInfo->pszCoverPath)+9;
+        psInfo->pszInfoPath =(char*)CPLMalloc(nInfoPathLen);
 #ifdef WIN32
 #  define AVC_INFOPATH "..\\info\\"
 #else
 #  define AVC_INFOPATH "../info/"
 #endif
-        sprintf(psInfo->pszInfoPath, "%s%s", psInfo->pszCoverPath, 
+        snprintf(psInfo->pszInfoPath, nInfoPathLen, "%s%s", psInfo->pszCoverPath,
                                              AVC_INFOPATH);
 
         AVCAdjustCaseSensitiveFilename(psInfo->pszInfoPath);
     }
 
     /*-----------------------------------------------------------------
-     * For Unix coverages, check that the info directory exists and 
-     * contains the "arc.dir".  In AVCCoverWeird, the arc.dir is 
+     * For Unix coverages, check that the info directory exists and
+     * contains the "arc.dir".  In AVCCoverWeird, the arc.dir is
      * called "../INFO/ARCDR9".
-     * PC Coverages have their info tables in the same direcotry as 
+     * PC Coverages have their info tables in the same directory as
      * the coverage files.
      *----------------------------------------------------------------*/
-    if (((psInfo->eCoverType == AVCCoverV7 || 
+    if (((psInfo->eCoverType == AVCCoverV7 ||
           psInfo->eCoverType == AVCCoverV7Tables) &&
          ! AVCFileExists(psInfo->pszInfoPath, "arc.dir") ) ||
          (psInfo->eCoverType == AVCCoverWeird &&
          ! AVCFileExists(psInfo->pszInfoPath, "arcdr9") ) )
     {
-        CPLError(CE_Failure, CPLE_OpenFailed, 
-             "Invalid coverage (%s): 'info' directory not found or invalid.", 
+        CPLError(CE_Failure, CPLE_OpenFailed,
+             "Invalid coverage (%s): 'info' directory not found or invalid.",
                                               pszCoverPath);
         CPLFree(psInfo->pszCoverName);
         CPLFree(psInfo->pszCoverPath);
@@ -341,7 +340,7 @@ AVCE00ReadPtr  AVCE00ReadOpen(const char *pszCoverPath)
     }
 
     /*-----------------------------------------------------------------
-     * Make sure there was no error until now before we build squeleton.
+     * Make sure there was no error until now before we build skeleton.
      *----------------------------------------------------------------*/
     if (CPLGetLastErrorNo() != 0)
     {
@@ -354,12 +353,12 @@ AVCE00ReadPtr  AVCE00ReadOpen(const char *pszCoverPath)
     }
 
     /*-----------------------------------------------------------------
-     * Build the E00 file squeleton and be ready to return a E00 header...
+     * Build the E00 file skeleton and be ready to return a E00 header...
      * We'll also read the coverage precision by the same way.
      *----------------------------------------------------------------*/
     nCoverPrecision = _AVCE00ReadBuildSqueleton(psInfo, papszCoverDir);
 
-    /* Ignore warnings produced while building squeleton */
+    /* Ignore warnings produced while building skeleton */
     CPLErrorReset();
 
     CSLDestroy(papszCoverDir);
@@ -420,8 +419,8 @@ AVCE00ReadE00Ptr AVCE00ReadOpenE00(const char *pszE00FileName)
         VSIStat(pszE00FileName, &sStatBuf) == -1 ||
         VSI_ISDIR(sStatBuf.st_mode))
     {
-        CPLError(CE_Failure, CPLE_OpenFailed, 
-                 "Invalid E00 file path: %s.", 
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "Invalid E00 file path: %s.",
                  pszE00FileName?pszE00FileName:"(NULL)");
         return NULL;
     }
@@ -432,9 +431,9 @@ AVCE00ReadE00Ptr AVCE00ReadOpenE00(const char *pszE00FileName)
     /*-----------------------------------------------------------------
      * Make sure the file starts with a "EXP  0" or "EXP  1" header
      *----------------------------------------------------------------*/
-    if (VSIFGets(szHeader, 5, fp) == NULL || !EQUALN("EXP ", szHeader, 4) )
+    if (VSIFGets(szHeader, 5, fp) == NULL || !STARTS_WITH_CI(szHeader, "EXP ") )
     {
-        CPLError(CE_Failure, CPLE_OpenFailed, 
+        CPLError(CE_Failure, CPLE_OpenFailed,
                  "This does not look like a E00 file: does not start with "
                  "a EXP header." );
         VSIFClose(fp);
@@ -606,7 +605,7 @@ static int _AVCIncreaseSectionsArray(AVCE00Section **pasArray, int *pnumItems,
 {
     int i;
 
-    *pasArray = (AVCE00Section*)CPLRealloc(*pasArray, 
+    *pasArray = (AVCE00Section*)CPLRealloc(*pasArray,
                                            (*pnumItems+numToAdd)*
                                                     sizeof(AVCE00Section));
 
@@ -635,13 +634,13 @@ static int _AVCIncreaseSectionsArray(AVCE00Section **pasArray, int *pnumItems,
  *                AVCCoverPC for PC Arc/Info coverages.
  *                AVCCoverWeird for an hybrid between V7 and PC
  *
- * If coverage type cannot be established then AVCCoverTypeUnknown is 
+ * If coverage type cannot be established then AVCCoverTypeUnknown is
  * returned.
  **********************************************************************/
 static AVCCoverType _AVCE00ReadFindCoverType(char **papszCoverDir)
 {
     int         i, nLen;
-    GBool       bFoundAdfFile=FALSE, bFoundArcFile=FALSE, 
+    GBool       bFoundAdfFile=FALSE, bFoundArcFile=FALSE,
                 bFoundTableFile=FALSE, bFoundDbfFile=FALSE,
                 bFoundArcDirFile=FALSE;
 
@@ -651,7 +650,7 @@ static AVCCoverType _AVCE00ReadFindCoverType(char **papszCoverDir)
      *----------------------------------------------------------------*/
     for(i=0; papszCoverDir && papszCoverDir[i]; i++)
     {
-        nLen = strlen(papszCoverDir[i]);
+        nLen = (int)strlen(papszCoverDir[i]);
         if (nLen > 4 && EQUAL(papszCoverDir[i]+nLen-4, ".adf") )
         {
             bFoundAdfFile = TRUE;
@@ -702,7 +701,7 @@ static AVCCoverType _AVCE00ReadFindCoverType(char **papszCoverDir)
 
     /*-----------------------------------------------------------------
      * Check for the weird coverages.
-     * Their coverage files have no extension just like PC Coverages, 
+     * Their coverage files have no extension just like PC Coverages,
      * and their tables have 3 letters filenames with no extension
      * either (e.g. "AAT", "PAT", etc.)
      * They also have a ../info directory, but we don't really need
@@ -733,7 +732,7 @@ static AVCCoverType _AVCE00ReadFindCoverType(char **papszCoverDir)
 /**********************************************************************
  *                         _AVCE00ReadAddJabberwockySection()
  *
- * Add to the squeleton a section that contains subsections 
+ * Add to the skeleton a section that contains subsections
  * for all the files with a given extension.
  *
  * Returns Updated Coverage precision
@@ -749,7 +748,7 @@ static int _AVCE00ReadAddJabberwockySection(AVCE00ReadPtr psInfo,
     GBool       bFoundFiles = FALSE;
     AVCBinFile *psFile=NULL;
 
-    nExtLen = strlen(pszFileExtension);
+    nExtLen = (int)strlen(pszFileExtension);
 
     /*-----------------------------------------------------------------
      * Scan the directory for files with a ".txt" extension.
@@ -757,11 +756,11 @@ static int _AVCE00ReadAddJabberwockySection(AVCE00ReadPtr psInfo,
 
     for (iDirEntry=0; papszCoverDir && papszCoverDir[iDirEntry]; iDirEntry++)
     {
-        nLen = strlen(papszCoverDir[iDirEntry]);
+        nLen = (int)strlen(papszCoverDir[iDirEntry]);
 
-        if (nLen > nExtLen && EQUAL(papszCoverDir[iDirEntry] + nLen-nExtLen, 
+        if (nLen > nExtLen && EQUAL(papszCoverDir[iDirEntry] + nLen-nExtLen,
                                     pszFileExtension) &&
-            (psFile = AVCBinReadOpen(psInfo->pszCoverPath, 
+            (psFile = AVCBinReadOpen(psInfo->pszCoverPath,
                                      papszCoverDir[iDirEntry],
                                      psInfo->eCoverType, eFileType,
                                      psInfo->psDBCSInfo)) != NULL)
@@ -774,27 +773,27 @@ static int _AVCE00ReadAddJabberwockySection(AVCE00ReadPtr psInfo,
             {
                 /* Insert a "TX6 #" header before the first TX6 file
                  */
-                iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections), 
+                iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections),
                                                   &(psInfo->numSections), 1);
                 psInfo->pasSections[iSect].eType = AVCFileUnknown;
 
-                psInfo->pasSections[iSect].pszName = 
+                psInfo->pasSections[iSect].pszName =
                             CPLStrdup(CPLSPrintf("%s  %c", pszSectionName,
                                   (nCoverPrecision==AVC_DOUBLE_PREC)?'3':'2'));
 
                 bFoundFiles = TRUE;
             }
 
-            /* Add this file to the squeleton 
+            /* Add this file to the skeleton
              */
-            iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections), 
+            iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections),
                                               &(psInfo->numSections), 1);
 
             psInfo->pasSections[iSect].eType = eFileType;
-            psInfo->pasSections[iSect].pszFilename= 
+            psInfo->pasSections[iSect].pszFilename=
                                    CPLStrdup(papszCoverDir[iDirEntry]);
 
-            /* pszName will contain only the classname without the file 
+            /* pszName will contain only the classname without the file
              * extension */
             psInfo->pasSections[iSect].pszName =
                                    CPLStrdup(papszCoverDir[iDirEntry]);
@@ -806,7 +805,7 @@ static int _AVCE00ReadAddJabberwockySection(AVCE00ReadPtr psInfo,
     {
         /* Add a line to close the TX6 section.
          */
-        iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections), 
+        iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections),
                                           &(psInfo->numSections), 1);
         psInfo->pasSections[iSect].eType = AVCFileUnknown;
         psInfo->pasSections[iSect].pszName = CPLStrdup("JABBERWOCKY");
@@ -854,15 +853,15 @@ static void *_AVCE00ReadNextLineE00(AVCE00ReadE00Ptr psRead,
      *----------------------------------------------------------------*/
     if (AVCE00ParseSuperSectionEnd(psInfo, pszLine) == TRUE)
     {
-        /* Nothing to do... it's all been done by the call to 
+        /* Nothing to do... it's all been done by the call to
          * AVCE00ParseSuperSectionEnd()
          */
     }
     else if (psRead->eCurFileType == AVCFileUnknown)
     {
         /*-------------------------------------------------------------
-         * We're at the top level or inside a supersection... waiting 
-         * to encounter a valid section or supersection header 
+         * We're at the top level or inside a supersection... waiting
+         * to encounter a valid section or supersection header
          * (i.e. "ARC  2", etc...)
          *------------------------------------------------------------*/
 
@@ -890,7 +889,7 @@ static void *_AVCE00ReadNextLineE00(AVCE00ReadE00Ptr psRead,
              * send the first header line to the parser and wait until
              * the whole header has been read.
              *--------------------------------------------------------*/
-            AVCE00ParseNextLine(psInfo, pszLine); 
+            AVCE00ParseNextLine(psInfo, pszLine);
         }
         else if (psRead->eCurFileType != AVCFileUnknown)
         {
@@ -906,10 +905,10 @@ static void *_AVCE00ReadNextLineE00(AVCE00ReadE00Ptr psRead,
          * We're reading a TABLE header... continue reading lines
          * from the header
          *
-         * Note: When parsing a TABLE, the first object returned will 
+         * Note: When parsing a TABLE, the first object returned will
          * be the AVCTableDef, then data records will follow.
          *------------------------------------------------------------*/
-        psObj = AVCE00ParseNextLine(psInfo, pszLine); 
+        psObj = AVCE00ParseNextLine(psInfo, pszLine);
         if (psObj)
         {
 			/* got table header */
@@ -923,7 +922,7 @@ static void *_AVCE00ReadNextLineE00(AVCE00ReadE00Ptr psRead,
          * We're are in the middle of a section... first check if we
          * have reached the end.
          *
-         * note: The first call to AVCE00ParseSectionEnd() with FALSE will 
+         * note: The first call to AVCE00ParseSectionEnd() with FALSE will
          *       not reset the parser until we close the file... and then
          *       we call the function again to reset the parser.
          *------------------------------------------------------------*/
@@ -957,16 +956,16 @@ static void *_AVCE00ReadNextLineE00(AVCE00ReadE00Ptr psRead,
 /**********************************************************************
  *                         _AVCE00ReadBuildSqueleton()
  *
- * Build the squeleton of the E00 file corresponding to the specified
+ * Build the skeleton of the E00 file corresponding to the specified
  * coverage and set the appropriate fields in the AVCE00ReadPtr struct.
  *
- * Note that the order of the sections in the squeleton is important
+ * Note that the order of the sections in the skeleton is important
  * since some software may rely on this ordering when they read E00 files.
  *
  * The function returns the coverage precision that it will read from one
- * of the file headers.  
+ * of the file headers.
  **********************************************************************/
-static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo, 
+static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo,
                                      char **papszCoverDir)
 {
     int         iSect, iTable, numTables, iFile, nLen;
@@ -999,7 +998,7 @@ static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo,
         if (getcwd(szCWD, 74) == NULL)
             szCWD[0] = '\0';    /* Failed: buffer may be too small */
 
-        nLen = strlen(szCWD);
+        nLen = (int)strlen(szCWD);
 
 #ifdef WIN32
         if (nLen > 0 && szCWD[nLen -1] != '\\')
@@ -1015,12 +1014,12 @@ static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo,
                                       psInfo->pszCoverPath));
     pcTmp = pszEXPPath;
     for( ; *pcTmp != '\0'; pcTmp++)
-        *pcTmp = toupper(*pcTmp);
+        *pcTmp = (char) toupper(*pcTmp);
 
     /*-----------------------------------------------------------------
      * EXP Header
      *----------------------------------------------------------------*/
-    iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections), 
+    iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections),
                                   &(psInfo->numSections), 1);
     psInfo->pasSections[iSect].eType = AVCFileUnknown;
     psInfo->pasSections[iSect].pszName = pszEXPPath;
@@ -1036,7 +1035,7 @@ static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo,
     /*-----------------------------------------------------------------
      * ARC section (arc.adf)
      *----------------------------------------------------------------*/
-    szFname = (psInfo->eCoverType==AVCCoverV7 || 
+    szFname = (psInfo->eCoverType==AVCCoverV7 ||
                psInfo->eCoverType==AVCCoverPC2 ) ? "arc.adf": "arc";
     if ( (iFile=CSLFindString(papszCoverDir, szFname)) != -1 &&
          (psFile = AVCBinReadOpen(psInfo->pszCoverPath, szFname,
@@ -1046,7 +1045,7 @@ static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo,
         if (nCoverPrecision == AVC_DEFAULT_PREC)
             nCoverPrecision = psFile->nPrecision;
         AVCBinReadClose(psFile);
-        iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections), 
+        iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections),
                                       &(psInfo->numSections), 1);
 
         psInfo->pasSections[iSect].eType = AVCFileARC;
@@ -1057,7 +1056,7 @@ static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo,
     /*-----------------------------------------------------------------
      * CNT section (cnt.adf)
      *----------------------------------------------------------------*/
-    szFname = (psInfo->eCoverType==AVCCoverV7 || 
+    szFname = (psInfo->eCoverType==AVCCoverV7 ||
                psInfo->eCoverType==AVCCoverPC2 ) ? "cnt.adf": "cnt";
     if ( (iFile=CSLFindString(papszCoverDir, szFname)) != -1 &&
          (psFile = AVCBinReadOpen(psInfo->pszCoverPath, szFname,
@@ -1067,7 +1066,7 @@ static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo,
         if (nCoverPrecision == AVC_DEFAULT_PREC)
             nCoverPrecision = psFile->nPrecision;
         AVCBinReadClose(psFile);
-        iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections), 
+        iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections),
                                       &(psInfo->numSections), 1);
 
         psInfo->pasSections[iSect].eType = AVCFileCNT;
@@ -1078,7 +1077,7 @@ static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo,
     /*-----------------------------------------------------------------
      * LAB section (lab.adf)
      *----------------------------------------------------------------*/
-    szFname = (psInfo->eCoverType==AVCCoverV7 || 
+    szFname = (psInfo->eCoverType==AVCCoverV7 ||
                psInfo->eCoverType==AVCCoverPC2 ) ? "lab.adf": "lab";
     if ( (iFile=CSLFindString(papszCoverDir, szFname)) != -1 &&
          (psFile = AVCBinReadOpen(psInfo->pszCoverPath, szFname,
@@ -1088,7 +1087,7 @@ static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo,
         if (nCoverPrecision == AVC_DEFAULT_PREC)
             nCoverPrecision = psFile->nPrecision;
         AVCBinReadClose(psFile);
-        iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections), 
+        iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections),
                                       &(psInfo->numSections), 1);
 
         psInfo->pasSections[iSect].eType = AVCFileLAB;
@@ -1099,7 +1098,7 @@ static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo,
     /*-----------------------------------------------------------------
      * PAL section (pal.adf)
      *----------------------------------------------------------------*/
-    szFname = (psInfo->eCoverType==AVCCoverV7 || 
+    szFname = (psInfo->eCoverType==AVCCoverV7 ||
                psInfo->eCoverType==AVCCoverPC2 ) ? "pal.adf": "pal";
     if ( (iFile=CSLFindString(papszCoverDir, szFname)) != -1 &&
          (psFile = AVCBinReadOpen(psInfo->pszCoverPath, szFname,
@@ -1109,7 +1108,7 @@ static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo,
         if (nCoverPrecision == AVC_DEFAULT_PREC)
             nCoverPrecision = psFile->nPrecision;
         AVCBinReadClose(psFile);
-        iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections), 
+        iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections),
                                       &(psInfo->numSections), 1);
 
         psInfo->pasSections[iSect].eType = AVCFilePAL;
@@ -1120,7 +1119,7 @@ static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo,
     /*-----------------------------------------------------------------
      * TOL section (tol.adf for single precision, par.adf for double)
      *----------------------------------------------------------------*/
-    szFname = (psInfo->eCoverType==AVCCoverV7 || 
+    szFname = (psInfo->eCoverType==AVCCoverV7 ||
                psInfo->eCoverType==AVCCoverPC2 ) ? "tol.adf": "tol";
     if ( (iFile=CSLFindString(papszCoverDir, szFname)) != -1 &&
          (psFile = AVCBinReadOpen(psInfo->pszCoverPath, szFname,
@@ -1130,7 +1129,7 @@ static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo,
         if (nCoverPrecision == AVC_DEFAULT_PREC)
             nCoverPrecision = psFile->nPrecision;
         AVCBinReadClose(psFile);
-        iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections), 
+        iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections),
                                       &(psInfo->numSections), 1);
 
         psInfo->pasSections[iSect].eType = AVCFileTOL;
@@ -1138,7 +1137,7 @@ static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo,
         psInfo->pasSections[iSect].pszFilename=CPLStrdup(papszCoverDir[iFile]);
     }
 
-    szFname = (psInfo->eCoverType==AVCCoverV7 || 
+    szFname = (psInfo->eCoverType==AVCCoverV7 ||
                psInfo->eCoverType==AVCCoverPC2 ) ? "par.adf": "par";
     if ( (iFile=CSLFindString(papszCoverDir, szFname)) != -1 &&
          (psFile = AVCBinReadOpen(psInfo->pszCoverPath, szFname,
@@ -1148,7 +1147,7 @@ static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo,
         if (nCoverPrecision == AVC_DEFAULT_PREC)
             nCoverPrecision = psFile->nPrecision;
         AVCBinReadClose(psFile);
-        iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections), 
+        iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections),
                                       &(psInfo->numSections), 1);
 
         psInfo->pasSections[iSect].eType = AVCFileTOL;
@@ -1159,7 +1158,7 @@ static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo,
     /*-----------------------------------------------------------------
      * TXT section (txt.adf)
      *----------------------------------------------------------------*/
-    szFname = (psInfo->eCoverType==AVCCoverV7 || 
+    szFname = (psInfo->eCoverType==AVCCoverV7 ||
                psInfo->eCoverType==AVCCoverPC2 ) ? "txt.adf": "txt";
     if ( (iFile=CSLFindString(papszCoverDir, szFname)) != -1 &&
          (psFile = AVCBinReadOpen(psInfo->pszCoverPath, szFname,
@@ -1169,7 +1168,7 @@ static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo,
         if (nCoverPrecision == AVC_DEFAULT_PREC)
             nCoverPrecision = psFile->nPrecision;
         AVCBinReadClose(psFile);
-        iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections), 
+        iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections),
                                       &(psInfo->numSections), 1);
 
         psInfo->pasSections[iSect].eType = AVCFileTXT;
@@ -1185,19 +1184,19 @@ static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo,
      *----------------------------------------------------------------*/
     if (psInfo->eCoverType == AVCCoverV7)
         nCoverPrecision = _AVCE00ReadAddJabberwockySection(psInfo, AVCFileTX6,
-                                                           "TX6", 
+                                                           "TX6",
                                                            nCoverPrecision,
                                                            ".txt",
                                                            papszCoverDir);
     else if (psInfo->eCoverType == AVCCoverWeird)
         nCoverPrecision = _AVCE00ReadAddJabberwockySection(psInfo, AVCFileTX6,
-                                                           "TX6", 
+                                                           "TX6",
                                                            nCoverPrecision,
                                                            "txt",
                                                            papszCoverDir);
 
     /*-----------------------------------------------------------------
-     * At this point, we should have read the coverage precsion... and if
+     * At this point, we should have read the coverage precision... and if
      * we haven't yet then we'll just use single by default.
      * We'll need cPrecisionCode for some of the sections that follow.
      *----------------------------------------------------------------*/
@@ -1209,7 +1208,7 @@ static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo,
     /*-----------------------------------------------------------------
      * SIN  2/3 and EOX lines ... ???
      *----------------------------------------------------------------*/
-    iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections), 
+    iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections),
                                   &(psInfo->numSections), 2);
     psInfo->pasSections[iSect].eType = AVCFileUnknown;
     psInfo->pasSections[iSect].pszName = CPLStrdup("SIN  X");
@@ -1226,11 +1225,11 @@ static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo,
     /*-----------------------------------------------------------------
      * PRJ section (prj.adf) (ends with EOP)
      *----------------------------------------------------------------*/
-    szFname = (psInfo->eCoverType==AVCCoverV7 || 
+    szFname = (psInfo->eCoverType==AVCCoverV7 ||
                psInfo->eCoverType==AVCCoverPC2 ) ? "prj.adf": "prj";
     if ( (iFile=CSLFindString(papszCoverDir, szFname)) != -1 )
     {
-        iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections), 
+        iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections),
                                       &(psInfo->numSections), 1);
 
         psInfo->pasSections[iSect].eType = AVCFilePRJ;
@@ -1243,10 +1242,10 @@ static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo,
      * Scan the directory for files with a ".rxp" extension.
      *----------------------------------------------------------------*/
     if (psInfo->eCoverType == AVCCoverV7)
-        _AVCE00ReadAddJabberwockySection(psInfo, AVCFileRXP, "RXP", 
+        _AVCE00ReadAddJabberwockySection(psInfo, AVCFileRXP, "RXP",
                                          nCoverPrecision,".rxp",papszCoverDir);
     else if (psInfo->eCoverType == AVCCoverWeird)
-        _AVCE00ReadAddJabberwockySection(psInfo, AVCFileRXP, "RXP", 
+        _AVCE00ReadAddJabberwockySection(psInfo, AVCFileRXP, "RXP",
                                          nCoverPrecision,"rxp",papszCoverDir);
 
 
@@ -1255,25 +1254,25 @@ static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo,
      * Scan the directory for files with a ".rpl" extension.
      *----------------------------------------------------------------*/
     if (psInfo->eCoverType == AVCCoverV7)
-        _AVCE00ReadAddJabberwockySection(psInfo, AVCFileRPL, "RPL", 
+        _AVCE00ReadAddJabberwockySection(psInfo, AVCFileRPL, "RPL",
                                          nCoverPrecision,".pal",papszCoverDir);
     else if (psInfo->eCoverType == AVCCoverWeird)
-        _AVCE00ReadAddJabberwockySection(psInfo, AVCFileRPL, "RPL", 
+        _AVCE00ReadAddJabberwockySection(psInfo, AVCFileRPL, "RPL",
                                          nCoverPrecision,"rpl",papszCoverDir);
 
     /*-----------------------------------------------------------------
      * IFO section (tables)
      *----------------------------------------------------------------*/
     papszTables = papszFiles = NULL;
-    if (psInfo->eCoverType == AVCCoverV7 || 
-        psInfo->eCoverType == AVCCoverV7Tables || 
+    if (psInfo->eCoverType == AVCCoverV7 ||
+        psInfo->eCoverType == AVCCoverV7Tables ||
         psInfo->eCoverType == AVCCoverWeird)
     {
         /*-------------------------------------------------------------
          * Unix coverages: get tables from the ../info/arc.dir
          * Weird coverages: the arc.dir is similar but called "arcdr9"
          *------------------------------------------------------------*/
-        papszTables = AVCBinReadListTables(psInfo->pszInfoPath, 
+        papszTables = AVCBinReadListTables(psInfo->pszInfoPath,
                                            psInfo->pszCoverName,
                                            &papszFiles, psInfo->eCoverType,
                                            psInfo->psDBCSInfo);
@@ -1289,7 +1288,7 @@ static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo,
          *------------------------------------------------------------*/
         for(iFile=0; papszCoverDir && papszCoverDir[iFile]; iFile++)
         {
-            if ((nLen = strlen(papszCoverDir[iFile])) == 7 &&
+            if ((nLen = (int)strlen(papszCoverDir[iFile])) == 7 &&
                 EQUAL(papszCoverDir[iFile] + nLen -4, ".dbf"))
             {
                 papszCoverDir[iFile][nLen - 4] = '\0';
@@ -1297,7 +1296,7 @@ static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo,
                                               papszCoverDir[iFile]);
                 pcTmp = (char*)szFname;
                 for( ; *pcTmp != '\0'; pcTmp++)
-                    *pcTmp = toupper(*pcTmp);
+                    *pcTmp = (char)toupper(*pcTmp);
                 papszCoverDir[iFile][nLen - 4] = '.';
 
                 papszTables = CSLAddString(papszTables, szFname);
@@ -1306,9 +1305,9 @@ static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo,
         }
     }
 
-    if ((numTables = CSLCount(papszTables)) > 0)
+    if (papszTables != NULL && (numTables = CSLCount(papszTables)) > 0)
     {
-        iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections), 
+        iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections),
                                       &(psInfo->numSections), numTables+2);
 
         psInfo->pasSections[iSect].eType = AVCFileUnknown;
@@ -1339,7 +1338,7 @@ static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo,
     /*-----------------------------------------------------------------
      * File ends with EOS
      *----------------------------------------------------------------*/
-    iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections), 
+    iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections),
                                   &(psInfo->numSections), 1);
     psInfo->pasSections[iSect].eType = AVCFileUnknown;
     psInfo->pasSections[iSect].pszName = CPLStrdup("EOS");
@@ -1370,32 +1369,33 @@ static void _AVCE00ReadScanE00(AVCE00ReadE00Ptr psRead)
         if (bFirstLine)
         {
             /* Look for the first non-empty line, after the EXP header,
-             * trying to detect compressed E00 files. If the file is 
+             * trying to detect compressed E00 files. If the file is
              * compressed, the first line of data should be 79 or 80 chars
              * long and contain several '~' characters.
              */
-            int nLen = strlen(pszLine);
-            if (nLen == 0 || EQUALN("EXP ", pszLine, 4))
+            int nLen = (int)strlen(pszLine);
+            if (nLen == 0 || STARTS_WITH_CI(pszLine, "EXP "))
                 continue;  /* Skip empty and EXP header lines */
             else if ( (nLen == 79 || nLen == 80) &&
                       strchr(pszLine, '~') != NULL )
             {
                 /* Looks like a compressed file. Just log an error and return.
-                 * The caller should reject the file because it contains 0 
-                 * sections 
+                 * The caller should reject the file because it contains 0
+                 * sections
                  */
-                CPLError(CE_Failure, CPLE_OpenFailed, 
+                CPLError(CE_Failure, CPLE_OpenFailed,
                          "This looks like a compressed E00 file and cannot be "
                          "processed directly. You may need to uncompress it "
                          "first using the E00compr library or the e00conv "
                          "program." );
-                return;  
+                return;
             }
 
             /* All seems fine. Continue with normal processing */
             bFirstLine = FALSE;
         }
 
+        /* coverity[tainted_data] */
         obj = _AVCE00ReadNextLineE00(psRead, pszLine);
 
         if (obj)
@@ -1447,7 +1447,7 @@ static void _AVCE00ReadScanE00(AVCE00ReadE00Ptr psRead)
                     psRead->pasSections[iSect].eType != psInfo->eFileType ||
                     !EQUAL(pszName, psRead->pasSections[iSect].pszName)))
             {
-                iSect = _AVCIncreaseSectionsArray(&(psRead->pasSections), 
+                iSect = _AVCIncreaseSectionsArray(&(psRead->pasSections),
                                       &(psRead->numSections), 1);
 
                 psRead->pasSections[iSect].eType = psInfo->eFileType;
@@ -1499,7 +1499,7 @@ static const char *_AVCE00ReadNextTableLine(AVCE00ReadPtr psInfo)
             char *pszFname;
             pszFname = CPLStrdup(CPLSPrintf("%s%s", psInfo->pszInfoPath,
                                                     psSect->pszFilename ));
-            psInfo->hFile = AVCBinReadOpen(pszFname, psSect->pszName, 
+            psInfo->hFile = AVCBinReadOpen(pszFname, psSect->pszName,
                                            psInfo->eCoverType, psSect->eType,
                                            psInfo->psDBCSInfo);
             CPLFree(pszFname);
@@ -1507,19 +1507,19 @@ static const char *_AVCE00ReadNextTableLine(AVCE00ReadPtr psInfo)
         else
         {
             /*---------------------------------------------------------
-             * AVCCoverV7 and AVCCoverWeird: 
+             * AVCCoverV7 and AVCCoverWeird:
              * We pass the INFO dir's path, and the Arc/Info table name
              * will be searched in the arc.dir
              *--------------------------------------------------------*/
-            psInfo->hFile = AVCBinReadOpen(psInfo->pszInfoPath, 
-                                           psSect->pszName, 
+            psInfo->hFile = AVCBinReadOpen(psInfo->pszInfoPath,
+                                           psSect->pszName,
                                            psInfo->eCoverType, psSect->eType,
                                            psInfo->psDBCSInfo);
         }
 
 
         /* For some reason the file could not be opened... abort now.
-         * An error message should have already been produced by 
+         * An error message should have already been produced by
          * AVCBinReadOpen()
          */
         if (psInfo->hFile == NULL)
@@ -1531,7 +1531,7 @@ static const char *_AVCE00ReadNextTableLine(AVCE00ReadPtr psInfo)
                                     psInfo->hFile->hdr.psTableDef,
                                     FALSE);
     }
-        
+
     if (pszLine == NULL &&
         psInfo->iCurStep == AVC_GEN_TABLEHEADER)
     {
@@ -1547,7 +1547,7 @@ static const char *_AVCE00ReadNextTableLine(AVCE00ReadPtr psInfo)
             /* Finished with table header... time to proceed with the
              * table data.
              * Reset the AVCE00GenInfo struct. so that it returns NULL,
-             * which will force reading of the first record from the 
+             * which will force reading of the first record from the
              * file on the next call to AVCE00ReadNextLine()
              */
             AVCE00GenReset(psInfo->hGenInfo);
@@ -1563,7 +1563,7 @@ static const char *_AVCE00ReadNextTableLine(AVCE00ReadPtr psInfo)
          * Continue with records of data
          *--------------------------------------------------------*/
 
-        pszLine = AVCE00GenTableRec(psInfo->hGenInfo, 
+        pszLine = AVCE00GenTableRec(psInfo->hGenInfo,
                                     psInfo->hFile->hdr.psTableDef->numFields,
                                     psInfo->hFile->hdr.psTableDef->pasFieldDef,
                                     psInfo->hFile->cur.pasFields,
@@ -1571,18 +1571,17 @@ static const char *_AVCE00ReadNextTableLine(AVCE00ReadPtr psInfo)
 
         if (pszLine == NULL)
         {
-            /* Current record is finished generating... we need to read 
+            /* Current record is finished generating... we need to read
              * a new one from the file.
              */
             if (AVCBinReadNextObject(psInfo->hFile) != NULL)
             {
-                pszLine = AVCE00GenTableRec(psInfo->hGenInfo, 
+                pszLine = AVCE00GenTableRec(psInfo->hGenInfo,
                                     psInfo->hFile->hdr.psTableDef->numFields,
                                     psInfo->hFile->hdr.psTableDef->pasFieldDef,
                                     psInfo->hFile->cur.pasFields,
                                     FALSE);
-            }            
-
+            }
         }
     }
 
@@ -1596,9 +1595,9 @@ static const char *_AVCE00ReadNextTableLine(AVCE00ReadPtr psInfo)
 
         /*---------------------------------------------------------
          * And now proceed to the next section...
-         * OK, I don't really like recursivity either... but it was
+         * OK, I don't really like recursion, but it was
          * the simplest way to do this, and anyways we should never
-         * have more than one level of recursivity.
+         * have more than one level of recursion.
          *--------------------------------------------------------*/
         if (psInfo->bReadAllSections)
             psInfo->iCurSection++;
@@ -1610,7 +1609,7 @@ static const char *_AVCE00ReadNextTableLine(AVCE00ReadPtr psInfo)
     }
 
     /*-----------------------------------------------------------------
-     * Check for errors... if any error happened, tehn return NULL
+     * Check for errors... if any error happened, then return NULL.
      *----------------------------------------------------------------*/
     if (CPLGetLastErrorNo() != 0)
     {
@@ -1629,8 +1628,8 @@ static const char *_AVCE00ReadNextTableLine(AVCE00ReadPtr psInfo)
  * The returned line is a null-terminated string, and it does not
  * include a newline character.
  *
- * Call CPLGetLastErrorNo() after calling AVCE00ReadNextLine() to 
- * make sure that the line was generated succesfully.
+ * Call CPLGetLastErrorNo() after calling AVCE00ReadNextLine() to
+ * make sure that the line was generated successfully.
  *
  * Note that AVCE00ReadNextLine() returns a reference to an
  * internal buffer whose contents will
@@ -1691,29 +1690,29 @@ const char *AVCE00ReadNextLine(AVCE00ReadPtr psInfo)
     {
     /*-----------------------------------------------------------------
      * Start processing of an ARC, PAL, CNT, LAB or TOL section:
-     *   Open the file, get ready to read the first object from the 
+     *   Open the file, get ready to read the first object from the
      *   file, and return the header line.
      *  If the file fails to open then we will return NULL.
      *----------------------------------------------------------------*/
-        psInfo->hFile = AVCBinReadOpen(psInfo->pszCoverPath, 
-                                       psSect->pszFilename, 
+        psInfo->hFile = AVCBinReadOpen(psInfo->pszCoverPath,
+                                       psSect->pszFilename,
                                        psInfo->eCoverType, psSect->eType,
                                        psInfo->psDBCSInfo);
 
         /*-------------------------------------------------------------
          * For some reason the file could not be opened... abort now.
-         * An error message should have already been produced by 
+         * An error message should have already been produced by
          * AVCBinReadOpen()
          *------------------------------------------------------------*/
         if (psInfo->hFile == NULL)
             return NULL;
 
-        pszLine = AVCE00GenStartSection(psInfo->hGenInfo, 
+        pszLine = AVCE00GenStartSection(psInfo->hGenInfo,
                                         psSect->eType, psSect->pszName);
 
         /*-------------------------------------------------------------
          * Reset the AVCE00GenInfo struct. so that it returns NULL,
-         * which will force reading of the first object from the 
+         * which will force reading of the first object from the
          * file on the next call to AVCE00ReadNextLine()
          *------------------------------------------------------------*/
         AVCE00GenReset(psInfo->hGenInfo);
@@ -1731,10 +1730,10 @@ const char *AVCE00ReadNextLine(AVCE00ReadPtr psInfo)
               psSect->eType == AVCFileRXP    ) )
     {
     /*-----------------------------------------------------------------
-     * Return the next line of an ARC/PAL/CNT/TOL/TXT object... 
+     * Return the next line of an ARC/PAL/CNT/TOL/TXT object...
      * if necessary, read the next object from the binary file.
      *----------------------------------------------------------------*/
-        pszLine = AVCE00GenObject(psInfo->hGenInfo, 
+        pszLine = AVCE00GenObject(psInfo->hGenInfo,
                                   psSect->eType,
                   (psSect->eType==AVCFileARC?(void*)(psInfo->hFile->cur.psArc):
                    psSect->eType==AVCFilePAL?(void*)(psInfo->hFile->cur.psPal):
@@ -1750,12 +1749,12 @@ const char *AVCE00ReadNextLine(AVCE00ReadPtr psInfo)
         if (pszLine == NULL)
         {
             /*---------------------------------------------------------
-             * Current object is finished generating... we need to read 
+             * Current object is finished generating... we need to read
              * a new one from the file.
              *--------------------------------------------------------*/
             if (AVCBinReadNextObject(psInfo->hFile) != NULL)
             {
-                pszLine = AVCE00GenObject(psInfo->hGenInfo, 
+                pszLine = AVCE00GenObject(psInfo->hGenInfo,
                                           psSect->eType,
                   (psSect->eType==AVCFileARC?(void*)(psInfo->hFile->cur.psArc):
                    psSect->eType==AVCFilePAL?(void*)(psInfo->hFile->cur.psPal):
@@ -1768,7 +1767,7 @@ const char *AVCE00ReadNextLine(AVCE00ReadPtr psInfo)
                    psSect->eType==AVCFileRXP?(void*)(psInfo->hFile->cur.psRxp):
                    NULL),
                                           FALSE);
-            }            
+            }
         }
         if (pszLine == NULL)
         {
@@ -1792,7 +1791,7 @@ const char *AVCE00ReadNextLine(AVCE00ReadPtr psInfo)
         /*-------------------------------------------------------------
          * Start processing of PRJ section... return first header line.
          *------------------------------------------------------------*/
-        pszLine = AVCE00GenStartSection(psInfo->hGenInfo, 
+        pszLine = AVCE00GenStartSection(psInfo->hGenInfo,
                                         psSect->eType, NULL);
 
         psInfo->hFile = NULL;
@@ -1810,19 +1809,19 @@ const char *AVCE00ReadNextLine(AVCE00ReadPtr psInfo)
              * File has not been read yet...
              * Read the PRJ file, and return the first PRJ line.
              *--------------------------------------------------------*/
-            psInfo->hFile = AVCBinReadOpen(psInfo->pszCoverPath, 
-                                           psSect->pszFilename, 
+            psInfo->hFile = AVCBinReadOpen(psInfo->pszCoverPath,
+                                           psSect->pszFilename,
                                            psInfo->eCoverType, psSect->eType,
                                            psInfo->psDBCSInfo);
 
             /* For some reason the file could not be opened... abort now.
-             * An error message should have already been produced by 
+             * An error message should have already been produced by
              * AVCBinReadOpen()
              */
             if (psInfo->hFile == NULL)
                 return NULL;
 
-            pszLine = AVCE00GenPrj(psInfo->hGenInfo, 
+            pszLine = AVCE00GenPrj(psInfo->hGenInfo,
                                    psInfo->hFile->cur.papszPrj, FALSE);
         }
         else
@@ -1830,14 +1829,14 @@ const char *AVCE00ReadNextLine(AVCE00ReadPtr psInfo)
             /*---------------------------------------------------------
              * Generate the next line of output.
              *--------------------------------------------------------*/
-            pszLine = AVCE00GenPrj(psInfo->hGenInfo, 
+            pszLine = AVCE00GenPrj(psInfo->hGenInfo,
                                    psInfo->hFile->cur.papszPrj, TRUE);
         }
 
         if (pszLine == NULL)
         {
             /*---------------------------------------------------------
-             * Still NULL ??? This means we finished generating this PRJ 
+             * Still NULL ??? This means we finished generating this PRJ
              * section...
              * Start returning the "end of section" line(s)...
              *--------------------------------------------------------*/
@@ -1873,9 +1872,9 @@ const char *AVCE00ReadNextLine(AVCE00ReadPtr psInfo)
             /*---------------------------------------------------------
              * Finished returning the last lines of the section...
              * proceed to the next section...
-             * OK, I don't really like recursivity either... but it was
+             * OK, I don't really like recursivion, but it was
              * the simplest way to do this, and anyways we should never
-             * have more than one level of recursivity.
+             * have more than one level of recursion.
              *--------------------------------------------------------*/
             if (psInfo->bReadAllSections)
                 psInfo->iCurSection++;
@@ -1896,7 +1895,7 @@ const char *AVCE00ReadNextLine(AVCE00ReadPtr psInfo)
  *                         AVCE00ReadSectionsList()
  *
  * Returns an array of AVCE00Section structures that describe the
- * squeleton of the whole coverage.  The value of *numSect will be
+ * skeleton of the whole coverage.  The value of *numSect will be
  * set to the number of sections in the array.
  *
  * You can scan the returned array, and use AVCE00ReadGotoSection() to move
@@ -1904,7 +1903,7 @@ const char *AVCE00ReadNextLine(AVCE00ReadPtr psInfo)
  * of the file.
  *
  * Sections of type AVCFileUnknown correspond to lines in the
- * E00 output that are not directly linked to any coverage file, like 
+ * E00 output that are not directly linked to any coverage file, like
  * the "EXP 0" line, the "IFO X", "SIN X", etc.
  *
  * THE RETURNED ARRAY IS AN INTERNAL STRUCTURE AND SHOULD NOT BE
@@ -1922,14 +1921,14 @@ AVCE00Section *AVCE00ReadSectionsList(AVCE00ReadPtr psInfo, int *numSect)
 /**********************************************************************
  *                         AVCE00ReadGotoSection()
  *
- * Move the read pointer to the E00 section (coverage file) described in 
+ * Move the read pointer to the E00 section (coverage file) described in
  * the psSect structure.  Call AVCE00ReadSectionsList() to get the list of
  * sections for the current coverage.
  *
  * if bContinue=TRUE, then reading will automatically continue with the
  * next sections of the file once the requested section is finished.
  * Otherwise, if bContinue=FALSE then reading will stop at the end
- * of this section (i.e. AVCE00ReadNextLine() will return NULL when 
+ * of this section (i.e. AVCE00ReadNextLine() will return NULL when
  * it reaches the end of this section)
  *
  * Sections of type AVCFileUnknown returned by AVCE00ReadSectionsList()
@@ -1965,13 +1964,13 @@ int AVCE00ReadGotoSection(AVCE00ReadPtr psInfo, AVCE00Section *psSect,
      *----------------------------------------------------------------*/
     if (!bFound)
     {
-        CPLError(CE_Failure, CPLE_IllegalArg, 
+        CPLError(CE_Failure, CPLE_IllegalArg,
                  "Requested E00 section does not exist!");
         return -1;
     }
 
     /*-----------------------------------------------------------------
-     * Found it ... close current section and get ready to read 
+     * Found it ... close current section and get ready to read
      * the new one.
      *----------------------------------------------------------------*/
     if (psInfo->hFile)
@@ -1990,7 +1989,7 @@ int AVCE00ReadGotoSection(AVCE00ReadPtr psInfo, AVCE00Section *psSect,
 /**********************************************************************
  *                         AVCE00ReadRewind()
  *
- * Rewinds the AVCE00ReadPtr just like the stdio rewind() 
+ * Rewinds the AVCE00ReadPtr just like the stdio rewind()
  * function would do if you were reading an ASCII E00 file.
  *
  * Returns 0 on success or -1 on error.
@@ -2005,7 +2004,7 @@ int  AVCE00ReadRewind(AVCE00ReadPtr psInfo)
 /**********************************************************************
  *                         AVCE00ReadRewindE00()
  *
- * Rewinds the AVCE00ReadE00Ptr just like the stdio rewind() 
+ * Rewinds the AVCE00ReadE00Ptr just like the stdio rewind()
  * function would do if you were reading an ASCII E00 file.
  *
  * Returns 0 on success or -1 on error.
@@ -2062,6 +2061,7 @@ static int _AVCE00ReadSeekE00(AVCE00ReadE00Ptr psRead, int nOffset,
             (pszLine = CPLReadLine(psRead->hFile) ) != NULL )
     {
         /* obj = */
+        /* coverity[tainted_data] */
         _AVCE00ReadNextLineE00(psRead, pszLine);
     }
 
@@ -2091,6 +2091,7 @@ void *AVCE00ReadNextObjectE00(AVCE00ReadE00Ptr psRead)
         pszLine = CPLReadLine(psRead->hFile);
         if (pszLine == 0)
             break;
+        /* coverity[tainted_data] */
         obj = _AVCE00ReadNextLineE00(psRead, pszLine);
     }
     while (obj == NULL &&
@@ -2165,7 +2166,7 @@ int AVCE00ReadGotoSectionE00(AVCE00ReadE00Ptr psRead,
      *----------------------------------------------------------------*/
     if (!bFound)
     {
-        CPLError(CE_Failure, CPLE_IllegalArg, 
+        CPLError(CE_Failure, CPLE_IllegalArg,
                  "Requested E00 section does not exist!");
         return -1;
     }
diff --git a/ogr/ogrsf_frmts/avc/avc_e00write.c b/ogr/ogrsf_frmts/avc/avc_e00write.c
index f3fc844..3c11c57 100644
--- a/ogr/ogrsf_frmts/avc/avc_e00write.c
+++ b/ogr/ogrsf_frmts/avc/avc_e00write.c
@@ -17,16 +17,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -75,7 +75,7 @@
  * Added Japanese DBCS support
  *
  * Revision 1.7  2000/02/14 17:19:53  daniel
- * Accept '-' cahracter in new coverage name
+ * Accept '-' character in new coverage name
  *
  * Revision 1.6  2000/01/10 02:57:44  daniel
  * Little changes to accommodate read support for "weird" coverages
@@ -114,43 +114,43 @@ static GBool _IsStringAlnum(const char *pszFname);
  * (and may quite well never be!)... you can only create new coverages.
  *
  * Important Note: The E00 source lines are assumed to be valid... the
- * library performs no validation on the consistency of what it is 
+ * library performs no validation on the consistency of what it is
  * given as input (i.e. topology, polygons consistency, etc.).
- * So the coverage that will be created will be only as good as the 
+ * So the coverage that will be created will be only as good as the
  * E00 input that is used to generate it.
  *
- * pszCoverPath MUST be the name of the coverage directory, including 
+ * pszCoverPath MUST be the name of the coverage directory, including
  * the path to it.
  * (contrary to AVCE00ReadOpen(), you cannot pass the name of one of
  *  the files in the coverage directory).
- * The name of the coverage MUST be included in pszCoverPath... this 
+ * The name of the coverage MUST be included in pszCoverPath... this
  * means that passing "." is invalid.
  *
- * eNewCoverType is the type of coverage to create.  
+ * eNewCoverType is the type of coverage to create.
  *               Either AVCCoverV7 (Arc/Info V7 (Unix) coverage)
  *               or     AVCCoverPC (PC Arc/Info coverage)
  *
  * nPrecision should always be AVC_DEFAULT_PREC to automagically detect the
  *            source coverage's precision and use that same precision
- *            for the new coverage.  
+ *            for the new coverage.
  *
- *            This parameter has been included to allow adding the 
- *            possibility to eventually create coverages with a precision 
+ *            This parameter has been included to allow adding the
+ *            possibility to eventually create coverages with a precision
  *            different from the source E00.
  *            Given the way the lib is built, it could be possible to
  *            also pass  AVC_SINGLE_PREC or AVC_DOUBLE_PREC to explicitly
- *            request the creation of a coverage with that precision, 
- *            but the library does not (not yet!) properly convert the 
+ *            request the creation of a coverage with that precision,
+ *            but the library does not (not yet!) properly convert the
  *            TABLE attributes' precision, and the resulting coverage may
- *            be invalid in some cases.  
+ *            be invalid in some cases.
  *            This improvement is on the ToDo list!
  *
- * Returns a new AVCE00WritePtr handle or NULL if the coverage could 
+ * Returns a new AVCE00WritePtr handle or NULL if the coverage could
  * not be created or if a coverage with that name already exists.
  *
  * The handle will eventually have to be released with AVCE00ReadClose().
  **********************************************************************/
-AVCE00WritePtr  AVCE00WriteOpen(const char *pszCoverPath, 
+AVCE00WritePtr  AVCE00WriteOpen(const char *pszCoverPath,
                                 AVCCoverType eNewCoverType, int nPrecision )
 {
     AVCE00WritePtr  psInfo;
@@ -160,11 +160,11 @@ AVCE00WritePtr  AVCE00WriteOpen(const char *pszCoverPath,
     CPLErrorReset();
 
     /*-----------------------------------------------------------------
-     * Create pszCoverPath directory.  
+     * Create pszCoverPath directory.
      *----------------------------------------------------------------*/
     if (pszCoverPath == NULL || strlen(pszCoverPath) == 0)
     {
-        CPLError(CE_Failure, CPLE_AssertionFailed, 
+        CPLError(CE_Failure, CPLE_AssertionFailed,
                  "Invalid (empty) coverage directory name.");
         return NULL;
     }
@@ -176,13 +176,13 @@ AVCE00WritePtr  AVCE00WriteOpen(const char *pszCoverPath,
          * otherwise we can't use it as a coverage directory.
          *------------------------------------------------------------*/
         char **papszFiles;
-        papszFiles = CPLReadDir(pszCoverPath);
+        papszFiles = VSIReadDir(pszCoverPath);
         for(i=0; papszFiles && papszFiles[i]; i++)
         {
             if (!EQUAL(".", papszFiles[i]) &&
                 !EQUAL("..", papszFiles[i]))
             {
-                CPLError(CE_Failure, CPLE_OpenFailed, 
+                CPLError(CE_Failure, CPLE_OpenFailed,
                          "Cannot create coverage %s: directory already exists "
                          "and is not empty.", pszCoverPath);
                 CSLDestroy(papszFiles);
@@ -197,12 +197,12 @@ AVCE00WritePtr  AVCE00WriteOpen(const char *pszCoverPath,
     else
     {
         /*-------------------------------------------------------------
-         * Create new pszCoverPath directory.  
+         * Create new pszCoverPath directory.
          * This will fail if a file with the same name already exists.
          *------------------------------------------------------------*/
         if( VSIMkdir(pszCoverPath, 0777) != 0 )
         {
-            CPLError(CE_Failure, CPLE_OpenFailed, 
+            CPLError(CE_Failure, CPLE_OpenFailed,
                      "Unable to create coverage directory: %s.", pszCoverPath);
             return NULL;
         }
@@ -220,7 +220,7 @@ AVCE00WritePtr  AVCE00WriteOpen(const char *pszCoverPath,
         psInfo->eCoverType = eNewCoverType;
     else
     {
-        CPLError(CE_Failure, CPLE_NotSupported, 
+        CPLError(CE_Failure, CPLE_NotSupported,
                  "Requested coverage type cannot be created.  Please use "
                  "the AVCCoverV7 or AVCCoverPC coverage type.");
         CPLFree(psInfo);
@@ -239,7 +239,7 @@ AVCE00WritePtr  AVCE00WriteOpen(const char *pszCoverPath,
         psInfo->nPrecision = nPrecision;
     else
     {
-        CPLError(CE_Failure, CPLE_IllegalArg, 
+        CPLError(CE_Failure, CPLE_IllegalArg,
                  "Coverages can only be created using AVC_DEFAULT_PREC. "
                  "Please see the documentation for AVCE00WriteOpen().");
         CPLFree(psInfo);
@@ -249,7 +249,7 @@ AVCE00WritePtr  AVCE00WriteOpen(const char *pszCoverPath,
     /*-----------------------------------------------------------------
      * Make sure coverage directory name is terminated with a '/' (or '\\')
      *----------------------------------------------------------------*/
-    nLen = strlen(pszCoverPath);
+    nLen = (int)strlen(pszCoverPath);
 
     if (pszCoverPath[nLen-1] == '/' || pszCoverPath[nLen-1] == '\\')
         psInfo->pszCoverPath = CPLStrdup(pszCoverPath);
@@ -270,11 +270,11 @@ AVCE00WritePtr  AVCE00WriteOpen(const char *pszCoverPath,
      * but for now we'll just produce an error if this happens.
      *----------------------------------------------------------------*/
     nLen = 0;
-    for( i = strlen(psInfo->pszCoverPath)-1; 
+    for( i = (int)strlen(psInfo->pszCoverPath)-1;
 	 i > 0 && psInfo->pszCoverPath[i-1] != '/' &&
 	          psInfo->pszCoverPath[i-1] != '\\'&&
 	          psInfo->pszCoverPath[i-1] != ':';
-	 i-- ) 
+	 i-- )
     {
         nLen++;
     }
@@ -286,7 +286,7 @@ AVCE00WritePtr  AVCE00WriteOpen(const char *pszCoverPath,
     }
     else
     {
-        CPLError(CE_Failure, CPLE_OpenFailed, 
+        CPLError(CE_Failure, CPLE_OpenFailed,
                  "Invalid coverage path (%s): "
                  "coverage name must be included in path.", pszCoverPath);
 
@@ -298,10 +298,10 @@ AVCE00WritePtr  AVCE00WriteOpen(const char *pszCoverPath,
     if (strlen(psInfo->pszCoverName) > 13 ||
         !_IsStringAlnum(psInfo->pszCoverName) )
     {
-        CPLError(CE_Failure, CPLE_OpenFailed, 
+        CPLError(CE_Failure, CPLE_OpenFailed,
                  "Invalid coverage name (%s): "
                  "coverage name must be 13 chars or less and contain only "
-                 "alphanumerical characters, '-' or '_'.", 
+                 "alphanumerical characters, '-' or '_'.",
                  psInfo->pszCoverName);
 
         CPLFree(psInfo->pszCoverPath);
@@ -323,14 +323,14 @@ AVCE00WritePtr  AVCE00WriteOpen(const char *pszCoverPath,
          * Lazy way to build the INFO path: simply add "../info/"...
          * this could probably be improved!
          *------------------------------------------------------------*/
-        psInfo->pszInfoPath = (char*)CPLMalloc((strlen(psInfo->pszCoverPath)+9)
-                                               *sizeof(char));
+        size_t nInfoPathLen = strlen(psInfo->pszCoverPath)+9;
+        psInfo->pszInfoPath = (char*)CPLMalloc(nInfoPathLen);
 #ifdef WIN32
 #  define AVC_INFOPATH "..\\info\\"
 #else
 #  define AVC_INFOPATH "../info/"
 #endif
-        sprintf(psInfo->pszInfoPath, "%s%s", psInfo->pszCoverPath, 
+        snprintf(psInfo->pszInfoPath, nInfoPathLen, "%s%s", psInfo->pszCoverPath,
                                              AVC_INFOPATH);
 
         /*-------------------------------------------------------------
@@ -338,10 +338,10 @@ AVCE00WritePtr  AVCE00WriteOpen(const char *pszCoverPath,
          * if the info dir does not exist, then make sure we can create
          * the arc.dir file (i.e. try to create an empty one)
          *
-         * Note: On Windows, this VSIStat() call seems to sometimes fail even 
-         *       when the directory exists (buffering issue?), and the 
-         *       following if() block is sometimes executed even if it 
-         *       should not, but this should not cause problems since the 
+         * Note: On Windows, this VSIStat() call seems to sometimes fail even
+         *       when the directory exists (buffering issue?), and the
+         *       following if() block is sometimes executed even if it
+         *       should not, but this should not cause problems since the
          *       arc.dir is opened with "a+b" access.
          *------------------------------------------------------------*/
         if ( VSIStat(psInfo->pszInfoPath, &sStatBuf) == -1)
@@ -350,7 +350,7 @@ AVCE00WritePtr  AVCE00WriteOpen(const char *pszCoverPath,
             char *pszArcDir;
             char *pszInfoDir;
 
-            pszArcDir = CPLStrdup(CPLSPrintf("%s%s", 
+            pszArcDir = CPLStrdup(CPLSPrintf("%s%s",
                                              psInfo->pszInfoPath, "arc.dir"));
 
             /* Remove the trailing "/" from pszInfoPath.  Most OSes are
@@ -359,7 +359,7 @@ AVCE00WritePtr  AVCE00WriteOpen(const char *pszCoverPath,
              */
             pszInfoDir = CPLStrdup(psInfo->pszInfoPath);
             pszInfoDir[strlen(pszInfoDir)-1] = '\0';
-            
+
             VSIMkdir(pszInfoDir, 0777);
             fp = VSIFOpen(pszArcDir, "a+b");
 
@@ -371,8 +371,8 @@ AVCE00WritePtr  AVCE00WriteOpen(const char *pszCoverPath,
             }
             else
             {
-                CPLError(CE_Failure, CPLE_OpenFailed, 
-                         "Unable to create (or write to) 'info' directory %s", 
+                CPLError(CE_Failure, CPLE_OpenFailed,
+                         "Unable to create (or write to) 'info' directory %s",
                          psInfo->pszInfoPath);
                 CPLFree(psInfo->pszCoverPath);
                 CPLFree(psInfo->pszInfoPath);
@@ -437,11 +437,11 @@ void AVCE00WriteClose(AVCE00WritePtr psInfo)
 /**********************************************************************
  *                          _IsStringAlnum()
  *
- * Scan a string, and return TRUE if it contains only valid characters, 
+ * Scan a string, and return TRUE if it contains only valid characters,
  * Return FALSE otherwise.
  *
  * We used to accept only isalnum() chars, but since extended chars with
- * accents seem to be accepted, we will only check for chars that 
+ * accents seem to be accepted, we will only check for chars that
  * could confuse the lib.
  **********************************************************************/
 static GBool _IsStringAlnum(const char *pszFname)
@@ -464,16 +464,16 @@ static GBool _IsStringAlnum(const char *pszFname)
  * Rename the table and the system fields in a tabledef that will
  * be written to a new coverage.
  **********************************************************************/
-static void _AVCE00WriteRenameTable(AVCTableDef *psTableDef, 
+static void _AVCE00WriteRenameTable(AVCTableDef *psTableDef,
                                     const char *pszNewCoverName)
 {
     char szOldName[40], szOldExt[40], szNewName[40], *pszTmp;
     char szSysId[40], szUserId[40];
     int  i;
 
-    strcpy(szNewName, pszNewCoverName);
+    snprintf(szNewName, sizeof(szNewName), "%s", pszNewCoverName);
     for(i=0; szNewName[i] != '\0'; i++)
-        szNewName[i] = toupper(szNewName[i]);
+        szNewName[i] = (char) toupper(szNewName[i]);
 
     /*-----------------------------------------------------------------
      * Extract components from the current table name.
@@ -487,7 +487,7 @@ static void _AVCE00WriteRenameTable(AVCTableDef *psTableDef,
     *pszTmp = '\0';
     pszTmp++;
 
-    strcpy(szOldExt, pszTmp);
+    snprintf(szOldExt, sizeof(szOldExt), "%s", pszTmp);
     if ( (pszTmp = strchr(szOldExt, ' ')) != NULL )
         *pszTmp = '\0';
 
@@ -496,17 +496,17 @@ static void _AVCE00WriteRenameTable(AVCTableDef *psTableDef,
 
     /*-----------------------------------------------------------------
      * Look for system attributes with same name as table
-     * If the table name extension is followed by a subclass name 
+     * If the table name extension is followed by a subclass name
      * (e.g. "TEST.PATCOUNTY") then this subclass is used to build
-     * the system attributes (COUNTY# and COUNTY-ID) and thus we do 
+     * the system attributes (COUNTY# and COUNTY-ID) and thus we do
      * not need to rename them
-     * Otherwise (e.g. COUNTY.PAT) the coverage name is used and then 
+     * Otherwise (e.g. COUNTY.PAT) the coverage name is used and then
      * we need to rename these attribs for the new coverage name.
      *----------------------------------------------------------------*/
     if (strlen(szOldExt) == 3)
     {
-        sprintf(szSysId, "%s#", szOldName);
-        sprintf(szUserId, "%s-ID", szOldName);
+        snprintf(szSysId, sizeof(szSysId), "%s#", szOldName);
+        snprintf(szUserId, sizeof(szUserId),"%s-ID", szOldName);
 
         for(i=0; i<psTableDef->numFields; i++)
         {
@@ -516,11 +516,15 @@ static void _AVCE00WriteRenameTable(AVCTableDef *psTableDef,
 
             if (EQUAL(psTableDef->pasFieldDef[i].szName, szSysId))
             {
-                sprintf(psTableDef->pasFieldDef[i].szName, "%s#", szNewName);
+                snprintf(psTableDef->pasFieldDef[i].szName,
+                         sizeof(psTableDef->pasFieldDef[i].szName),
+                         "%s#", szNewName);
             }
             else if (EQUAL(psTableDef->pasFieldDef[i].szName, szUserId))
             {
-                sprintf(psTableDef->pasFieldDef[i].szName, "%s-ID", szNewName);
+                snprintf(psTableDef->pasFieldDef[i].szName,
+                         sizeof(psTableDef->pasFieldDef[i].szName),
+                         "%s-ID", szNewName);
             }
         }
     }
@@ -528,7 +532,8 @@ static void _AVCE00WriteRenameTable(AVCTableDef *psTableDef,
     /*-----------------------------------------------------------------
      * Build new table name
      *----------------------------------------------------------------*/
-    sprintf(psTableDef->szTableName, "%s.%s", szNewName, szOldExt);
+    snprintf(psTableDef->szTableName,
+             sizeof(psTableDef->szTableName), "%s.%s", szNewName, szOldExt);
 
 }
 
@@ -538,14 +543,15 @@ static void _AVCE00WriteRenameTable(AVCTableDef *psTableDef,
  * Create a coverage file for the specified file type.
  *
  * The main part of the work is to find the right filename to use based on
- * the file type, the coverage precision, etc... the rest of job is 
+ * the file type, the coverage precision, etc... the rest of job is
  * done by AVCBinWriteCreate().
  *
  * Returns 0 on success, or -1 if an error happened.
  *
- * AVCWriteCloseCoverFile() will eventually have to be called to release the 
+ * AVCWriteCloseCoverFile() will eventually have to be called to release the
  * resources used by the AVCBinFile structure.
  **********************************************************************/
+static
 int  _AVCE00WriteCreateCoverFile(AVCE00WritePtr psInfo, AVCFileType eType,
                                  const char *pszLine, AVCTableDef *psTableDef)
 {
@@ -587,7 +593,7 @@ int  _AVCE00WriteCreateCoverFile(AVCE00WritePtr psInfo, AVCFileType eType,
         strcpy(szFname, "txt");
         break;
       case AVCFileTX6:
-      /* For TX6/TX7: the filename is subclass_name.txt 
+      /* For TX6/TX7: the filename is subclass_name.txt
        */
 
         /* See bug 1261: It seems that empty subclass names are valid
@@ -598,34 +604,34 @@ int  _AVCE00WriteCreateCoverFile(AVCE00WritePtr psInfo, AVCFileType eType,
             strcpy(szFname, "txt.txt");
         }
         else if (strlen(pszLine) > 30 || strchr(pszLine, ' ') != NULL)
-            CPLError(CE_Failure, CPLE_IllegalArg, 
+            CPLError(CE_Failure, CPLE_IllegalArg,
                      "Invalid TX6/TX7 subclass name \"%s\"", pszLine);
         else
-            sprintf(szFname, "%s.txt", pszLine);
+            snprintf(szFname, sizeof(szFname), "%s.txt", pszLine);
         break;
       case AVCFileRPL:
       /* For RPL and RXP: the filename is region_name.pal or region_name.rxp
        */
         if (strlen(pszLine) > 30 || strchr(pszLine, ' ') != NULL)
-            CPLError(CE_Failure, CPLE_IllegalArg, 
+            CPLError(CE_Failure, CPLE_IllegalArg,
                      "Invalid RPL region name \"%s\"", pszLine);
         else
-            sprintf(szFname, "%s.pal", pszLine);
+            snprintf(szFname, sizeof(szFname), "%s.pal", pszLine);
         break;
       case AVCFileRXP:
         if (strlen(pszLine) > 30 || strchr(pszLine, ' ') != NULL)
-            CPLError(CE_Failure, CPLE_IllegalArg, 
+            CPLError(CE_Failure, CPLE_IllegalArg,
                      "Invalid RXP name \"%s\"", pszLine);
         else
-            sprintf(szFname, "%s.rxp", pszLine);
+            snprintf(szFname, sizeof(szFname), "%s.rxp", pszLine);
         break;
       case AVCFileTABLE:
         /*-------------------------------------------------------------
-         * For tables, Filename will be based on info in the psTableDef 
-         * but we need to rename the table and the system attributes 
+         * For tables, Filename will be based on info in the psTableDef
+         * but we need to rename the table and the system attributes
          * based on the new coverage name.
          *------------------------------------------------------------*/
-        if (psInfo->eCoverType != AVCCoverPC && 
+        if (psInfo->eCoverType != AVCCoverPC &&
             psInfo->eCoverType != AVCCoverPC2)
             pszPath = psInfo->pszInfoPath;
         _AVCE00WriteRenameTable(psTableDef, psInfo->pszCoverName);
@@ -648,22 +654,22 @@ int  _AVCE00WriteCreateCoverFile(AVCE00WritePtr psInfo, AVCFileType eType,
      * Make sure filename is all lowercase and attempt to create the file
      *----------------------------------------------------------------*/
     for(i=0; szFname[i] != '\0'; i++)
-        szFname[i] = tolower(szFname[i]);
+        szFname[i] = (char) tolower(szFname[i]);
 
     if (nStatus == 0)
     {
         psInfo->eCurFileType = eType;
 
         if (eType == AVCFileTABLE)
-            psInfo->hFile = AVCBinWriteCreateTable(pszPath, 
-                                                   psInfo->pszCoverName, 
+            psInfo->hFile = AVCBinWriteCreateTable(pszPath,
+                                                   psInfo->pszCoverName,
                                                    psTableDef,
                                                    psInfo->eCoverType,
                                                    psInfo->nPrecision,
                                                    psInfo->psDBCSInfo);
         else
 
-            psInfo->hFile = AVCBinWriteCreate(pszPath, szFname, 
+            psInfo->hFile = AVCBinWriteCreate(pszPath, szFname,
                                               psInfo->eCoverType,
                                               eType, psInfo->nPrecision,
                                               psInfo->psDBCSInfo);
@@ -686,11 +692,12 @@ int  _AVCE00WriteCreateCoverFile(AVCE00WritePtr psInfo, AVCFileType eType,
  * File should have been previously opened by _AVCE00WriteCreateCoverFile().
  *
  **********************************************************************/
+static
 void  _AVCE00WriteCloseCoverFile(AVCE00WritePtr psInfo)
 {
     /*-----------------------------------------------------------------
      * PRJ sections behave differently... since there is only one "object"
-     * per section, they accumulate lines while we read them, and we 
+     * per section, they accumulate lines while we read them, and we
      * write everything at once when we reach the end-of-section (EOP) line.
      *----------------------------------------------------------------*/
     if (psInfo->eCurFileType == AVCFilePRJ)
@@ -706,13 +713,13 @@ void  _AVCE00WriteCloseCoverFile(AVCE00WritePtr psInfo)
 /**********************************************************************
  *                          AVCE00WriteNextLine()
  *
- * Take the next line of E00 input for this coverage, parse it and 
+ * Take the next line of E00 input for this coverage, parse it and
  * write the result to the coverage.
  *
  * Important Note: The E00 source lines are assumed to be valid... the
- * library performs no validation on the consistency of what it is 
+ * library performs no validation on the consistency of what it is
  * given as input (i.e. topology, polygons consistency, etc.).
- * So the coverage that will be created will be only as good as the 
+ * So the coverage that will be created will be only as good as the
  * E00 input that is used to generate it.
  *
  * Returns 0 on success or -1 on error.
@@ -734,15 +741,15 @@ int     AVCE00WriteNextLine(AVCE00WritePtr psInfo, const char *pszLine)
      *----------------------------------------------------------------*/
     if (AVCE00ParseSuperSectionEnd(psInfo->hParseInfo, pszLine) == TRUE)
     {
-        /* Nothing to do... it's all been done by the call to 
+        /* Nothing to do... it's all been done by the call to
          * AVCE00ParseSuperSectionEnd()
          */
     }
     else if (psInfo->eCurFileType == AVCFileUnknown)
     {
         /*-------------------------------------------------------------
-         * We're at the top level or inside a supersection... waiting 
-         * to encounter a valid section or supersection header 
+         * We're at the top level or inside a supersection... waiting
+         * to encounter a valid section or supersection header
          * (i.e. "ARC  2", etc...)
          *------------------------------------------------------------*/
 
@@ -764,7 +771,7 @@ int     AVCE00WriteNextLine(AVCE00WritePtr psInfo, const char *pszLine)
          * If the coverage was created using AVC_DEFAULT_PREC and we are
          * processing the first section header, then use this section's
          * precision for the new coverage.
-         * (Note: this code segment will be executed only once per 
+         * (Note: this code segment will be executed only once per
          *        coverage and only if AVC_DEFAULT_PREC was selected)
          *------------------------------------------------------------*/
         if (psInfo->nPrecision == AVC_DEFAULT_PREC &&
@@ -778,21 +785,21 @@ int     AVCE00WriteNextLine(AVCE00WritePtr psInfo, const char *pszLine)
             /*---------------------------------------------------------
              * We can't create the file for a TABLE until the
              * whole header has been read... send the first header
-             * line to the parser and wait until the whole header has 
+             * line to the parser and wait until the whole header has
              * been read.
              *--------------------------------------------------------*/
-            AVCE00ParseNextLine(psInfo->hParseInfo, pszLine); 
+            AVCE00ParseNextLine(psInfo->hParseInfo, pszLine);
         }
         else if (psInfo->eCurFileType != AVCFileUnknown)
         {
             /*---------------------------------------------------------
-             * OK, we've found a valid section header... create the 
+             * OK, we've found a valid section header... create the
              * corresponding file in the coverage.
              * Note: supersection headers don't trigger the creation
              *       of any output file... they just alter the psInfo state.
              *--------------------------------------------------------*/
 
-            nStatus = _AVCE00WriteCreateCoverFile(psInfo, 
+            nStatus = _AVCE00WriteCreateCoverFile(psInfo,
                                                   psInfo->eCurFileType,
                                        psInfo->hParseInfo->pszSectionHdrLine,
                                                   NULL);
@@ -806,15 +813,15 @@ int     AVCE00WriteNextLine(AVCE00WritePtr psInfo, const char *pszLine)
          * from the header, and create the output file only once
          * the header will have been completely read.
          *
-         * Note: When parsing a TABLE, the first object returned will 
+         * Note: When parsing a TABLE, the first object returned will
          * be the AVCTableDef, then data records will follow.
          *------------------------------------------------------------*/
         AVCTableDef *psTableDef;
-        psTableDef = (AVCTableDef*)AVCE00ParseNextLine(psInfo->hParseInfo, 
-                                                       pszLine); 
+        psTableDef = (AVCTableDef*)AVCE00ParseNextLine(psInfo->hParseInfo,
+                                                       pszLine);
         if (psTableDef)
         {
-            nStatus = _AVCE00WriteCreateCoverFile(psInfo, 
+            nStatus = _AVCE00WriteCreateCoverFile(psInfo,
                                                   psInfo->eCurFileType,
                                        psInfo->hParseInfo->pszSectionHdrLine,
                                                   psTableDef);
@@ -826,7 +833,7 @@ int     AVCE00WriteNextLine(AVCE00WritePtr psInfo, const char *pszLine)
          * We're are in the middle of a section... first check if we
          * have reached the end.
          *
-         * note: The first call to AVCE00ParseSectionEnd() with FALSE will 
+         * note: The first call to AVCE00ParseSectionEnd() with FALSE will
          *       not reset the parser until we close the file... and then
          *       we call the function again to reset the parser.
          *------------------------------------------------------------*/
@@ -922,7 +929,7 @@ int     AVCE00DeleteCoverage(const char *pszCoverToDelete)
     /*-----------------------------------------------------------------
      * Delete files in cover directory.
      *----------------------------------------------------------------*/
-    papszFiles = CPLReadDir(pszCoverPath);
+    papszFiles = VSIReadDir(pszCoverPath);
     for(i=0; nStatus==0 && papszFiles && papszFiles[i]; i++)
     {
         if (!EQUAL(".", papszFiles[i]) &&
@@ -931,8 +938,8 @@ int     AVCE00DeleteCoverage(const char *pszCoverToDelete)
             pszFname = CPLSPrintf("%s%s", pszCoverPath, papszFiles[i]);
             if (unlink(pszFname) != 0)
             {
-                CPLError(CE_Failure, CPLE_FileIO, 
-                         "Failed deleting %s%s", 
+                CPLError(CE_Failure, CPLE_FileIO,
+                         "Failed deleting %s%s",
                          pszCoverPath, papszFiles[i]);
                 nStatus = -1;
                 break;
@@ -949,7 +956,7 @@ int     AVCE00DeleteCoverage(const char *pszCoverToDelete)
      *----------------------------------------------------------------*/
     if (nStatus == 0 && eCoverType != AVCCoverPC && eCoverType != AVCCoverPC2)
     {
-        papszTables = AVCBinReadListTables(pszInfoPath, pszCoverName, 
+        papszTables = AVCBinReadListTables(pszInfoPath, pszCoverName,
                                            &papszFiles, eCoverType,
                                            NULL /*DBCSInfo*/);
 
@@ -957,15 +964,15 @@ int     AVCE00DeleteCoverage(const char *pszCoverToDelete)
         {
             /* Convert table filename to lowercases */
             for(j=0; papszFiles[i] && papszFiles[i][j]!='\0'; j++)
-                papszFiles[i][j] = tolower(papszFiles[i][j]);
+                papszFiles[i][j] = (char) tolower(papszFiles[i][j]);
 
             /* Delete the .DAT file */
             pszFname = CPLSPrintf("%s%s.dat", pszInfoPath, papszFiles[i]);
             if ( VSIStat(pszFname, &sStatBuf) != -1 &&
                  unlink(pszFname) != 0)
             {
-                CPLError(CE_Failure, CPLE_FileIO, 
-                         "Failed deleting %s%s", 
+                CPLError(CE_Failure, CPLE_FileIO,
+                         "Failed deleting %s%s",
                          pszInfoPath, papszFiles[i]);
                 nStatus = -1;
                 break;
@@ -976,8 +983,8 @@ int     AVCE00DeleteCoverage(const char *pszCoverToDelete)
             if ( VSIStat(pszFname, &sStatBuf) != -1 &&
                  unlink(pszFname) != 0)
             {
-                CPLError(CE_Failure, CPLE_FileIO, 
-                         "Failed deleting %s%s", 
+                CPLError(CE_Failure, CPLE_FileIO,
+                         "Failed deleting %s%s",
                          pszInfoPath, papszFiles[i]);
                 nStatus = -1;
                 break;
@@ -990,15 +997,15 @@ int     AVCE00DeleteCoverage(const char *pszCoverToDelete)
 
     /*-----------------------------------------------------------------
      * Delete the coverage directory itself
-     * In some cases, the directory could be locked by another application 
-     * on the same system or somewhere on the network.  
-     * Define AVC_IGNORE_RMDIR_ERROR at compile time if you want this 
+     * In some cases, the directory could be locked by another application
+     * on the same system or somewhere on the network.
+     * Define AVC_IGNORE_RMDIR_ERROR at compile time if you want this
      * error to be ignored.
      *----------------------------------------------------------------*/
     if (VSIRmdir(pszCoverPath) != 0)
     {
 #ifndef AVC_IGNORE_RMDIR_ERROR
-        CPLError(CE_Failure, CPLE_FileIO, 
+        CPLError(CE_Failure, CPLE_FileIO,
                  "Failed deleting directory %s", pszCoverPath);
         nStatus = -1;
 #endif
@@ -1010,4 +1017,3 @@ int     AVCE00DeleteCoverage(const char *pszCoverToDelete)
 
     return nStatus;
 }
-
diff --git a/ogr/ogrsf_frmts/avc/avc_mbyte.c b/ogr/ogrsf_frmts/avc/avc_mbyte.c
index 022333d..b98049e 100644
--- a/ogr/ogrsf_frmts/avc/avc_mbyte.c
+++ b/ogr/ogrsf_frmts/avc/avc_mbyte.c
@@ -15,33 +15,17 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: avc_mbyte.c,v $
- * Revision 1.4  2008/07/23 20:51:38  dmorissette
- * Fixed GCC 4.1.x compile warnings related to use of char vs unsigned char
- * (GDAL/OGR ticket http://trac.osgeo.org/gdal/ticket/2495)
- *
- * Revision 1.3  2005/06/03 03:49:59  daniel
- * Update email address, website url, and copyright dates
- *
- * Revision 1.2  2000/09/22 19:45:21  daniel
- * Switch to MIT-style license
- *
- * Revision 1.1  2000/05/29 15:31:03  daniel
- * Initial revision - Japanese support
- *
  **********************************************************************/
 
 #include "avc.h"
@@ -54,7 +38,7 @@ static int _AVCDetectJapaneseEncoding(const GByte *pszLine);
 static const GByte *_AVCJapanese2ArcDBCS(AVCDBCSInfo *psDBCSInfo,
                                          const GByte *pszLine,
                                          int nMaxOutputLen);
-static const GByte *_AVCArcDBCS2JapaneseShiftJIS(AVCDBCSInfo *psDBCSInfo, 
+static const GByte *_AVCArcDBCS2JapaneseShiftJIS(AVCDBCSInfo *psDBCSInfo,
                                                  const GByte *pszLine,
                                                  int nMaxOutputLen);
 
@@ -70,7 +54,7 @@ static const GByte *_AVCArcDBCS2JapaneseShiftJIS(AVCDBCSInfo *psDBCSInfo,
  *
  * Alloc and init a new AVCDBCSInfo structure.
  **********************************************************************/
-AVCDBCSInfo *AVCAllocDBCSInfo()
+AVCDBCSInfo *AVCAllocDBCSInfo(void)
 {
     AVCDBCSInfo *psInfo;
 
@@ -101,11 +85,11 @@ void AVCFreeDBCSInfo(AVCDBCSInfo *psInfo)
 /**********************************************************************
  *                          AVCGetDBCSCodePage()
  *
- * Fetch current multibyte codepage on the system.  
+ * Fetch current multibyte codepage on the system.
  * Returns a valid codepage number, or 0 if the codepage is single byte or
  * unsupported.
  **********************************************************************/
-int AVCGetDBCSCodePage()
+int AVCGetDBCSCodePage(void)
 {
 #ifdef _WIN32
     int nCP;
@@ -142,14 +126,14 @@ GBool AVCE00DetectEncoding(AVCDBCSInfo *psDBCSInfo, const GByte *pszLine)
     switch (psDBCSInfo->nDBCSCodePage)
     {
       case AVC_DBCS_JAPANESE:
-        psDBCSInfo->nDBCSEncoding = 
+        psDBCSInfo->nDBCSEncoding =
                   _AVCDetectJapaneseEncoding(pszLine);
         break;
       default:
         psDBCSInfo->nDBCSEncoding = AVC_CODE_UNKNOWN;
         return TRUE;  /* Codepage not supported... no need to scan more lines*/
     }
-    
+
     if (psDBCSInfo->nDBCSEncoding != AVC_CODE_UNKNOWN)
         return TRUE;  /* We detected the encoding! */
 
@@ -168,7 +152,7 @@ GBool AVCE00DetectEncoding(AVCDBCSInfo *psDBCSInfo, const GByte *pszLine)
  * caller.  It can be either the original string buffer or a ref. to an
  * internal buffer.
  **********************************************************************/
-const GByte *AVCE00Convert2ArcDBCS(AVCDBCSInfo *psDBCSInfo, 
+const GByte *AVCE00Convert2ArcDBCS(AVCDBCSInfo *psDBCSInfo,
                                        const GByte *pszLine,
                                        int nMaxOutputLen)
 {
@@ -176,7 +160,7 @@ const GByte *AVCE00Convert2ArcDBCS(AVCDBCSInfo *psDBCSInfo,
     GByte *pszTmp = NULL;
     GBool bAllAscii;
 
-    if (psDBCSInfo == NULL || 
+    if (psDBCSInfo == NULL ||
         psDBCSInfo->nDBCSCodePage == 0 || pszLine == NULL)
     {
         /* Single byte codepage... nothing to do
@@ -199,17 +183,17 @@ const GByte *AVCE00Convert2ArcDBCS(AVCDBCSInfo *psDBCSInfo,
      * We add 2 chars to buffer size to simplify processing... no need to
      * check if second byte of a pair would overflow buffer.
      */
-    if (psDBCSInfo->pszDBCSBuf == NULL || 
+    if (psDBCSInfo->pszDBCSBuf == NULL ||
         psDBCSInfo->nDBCSBufSize < nMaxOutputLen+2)
     {
         psDBCSInfo->nDBCSBufSize = nMaxOutputLen+2;
-        psDBCSInfo->pszDBCSBuf = 
+        psDBCSInfo->pszDBCSBuf =
             (GByte *)CPLRealloc(psDBCSInfo->pszDBCSBuf,
                                 psDBCSInfo->nDBCSBufSize*
                                 sizeof(GByte));
     }
 
-    /* Do the conversion according to current code page 
+    /* Do the conversion according to current code page
      */
     switch (psDBCSInfo->nDBCSCodePage)
     {
@@ -219,12 +203,12 @@ const GByte *AVCE00Convert2ArcDBCS(AVCDBCSInfo *psDBCSInfo,
                                          nMaxOutputLen);
         break;
       default:
-        /* We should never get here anyways, but just in case return pszLine 
+        /* We should never get here anyways, but just in case return pszLine
          */
-        CPLAssert( !"SHOULD NEVER GET HERE" );
+        CPLAssert( FALSE ); /* Should never get here. */
         pszOutBuf = pszLine;
     }
-    
+
     return pszOutBuf;
 }
 
@@ -237,7 +221,7 @@ const GByte *AVCE00Convert2ArcDBCS(AVCDBCSInfo *psDBCSInfo,
  * caller.  It can be either the original string buffer or a ref. to an
  * internal buffer.
  **********************************************************************/
-const GByte *AVCE00ConvertFromArcDBCS(AVCDBCSInfo *psDBCSInfo, 
+const GByte *AVCE00ConvertFromArcDBCS(AVCDBCSInfo *psDBCSInfo,
                                       const GByte *pszLine,
                                       int nMaxOutputLen)
 {
@@ -245,7 +229,7 @@ const GByte *AVCE00ConvertFromArcDBCS(AVCDBCSInfo *psDBCSInfo,
     GByte *pszTmp;
     GBool bAllAscii;
 
-    if (psDBCSInfo == NULL || 
+    if (psDBCSInfo == NULL ||
         psDBCSInfo->nDBCSCodePage == 0 || pszLine == NULL)
     {
         /* Single byte codepage... nothing to do
@@ -268,17 +252,17 @@ const GByte *AVCE00ConvertFromArcDBCS(AVCDBCSInfo *psDBCSInfo,
      * We add 2 chars to buffer size to simplify processing... no need to
      * check if second byte of a pair would overflow buffer.
      */
-    if (psDBCSInfo->pszDBCSBuf == NULL || 
+    if (psDBCSInfo->pszDBCSBuf == NULL ||
         psDBCSInfo->nDBCSBufSize < nMaxOutputLen+2)
     {
         psDBCSInfo->nDBCSBufSize = nMaxOutputLen+2;
-        psDBCSInfo->pszDBCSBuf = 
+        psDBCSInfo->pszDBCSBuf =
             (GByte *)CPLRealloc(psDBCSInfo->pszDBCSBuf,
                                 psDBCSInfo->nDBCSBufSize*
                                 sizeof(GByte));
     }
 
-    /* Do the conversion according to current code page 
+    /* Do the conversion according to current code page
      */
     switch (psDBCSInfo->nDBCSCodePage)
     {
@@ -288,17 +272,17 @@ const GByte *AVCE00ConvertFromArcDBCS(AVCDBCSInfo *psDBCSInfo,
                                                  nMaxOutputLen);
         break;
       default:
-        /* We should never get here anyways, but just in case return pszLine 
+        /* We should never get here anyways, but just in case return pszLine
          */
         pszOutBuf = pszLine;
     }
-    
+
     return pszOutBuf;
 }
 
 /*=====================================================================
  *=====================================================================
- * Functions Specific to Japanese encoding (CodePage 932).  
+ * Functions Specific to Japanese encoding (CodePage 932).
  *
  * For now we assume that we can receive only Katakana, Shift-JIS, or EUC
  * encoding as input.  Coverages use EUC encoding in most cases, except
@@ -340,7 +324,7 @@ static int _AVCDetectJapaneseEncoding(const GByte *pszLine)
             break;
         }
         else if (IS_JAP_KANA(*pszLine) && *(pszLine+1) &&
-                 (IS_ASCII(*(pszLine+1)) || 
+                 (IS_ASCII(*(pszLine+1)) ||
                   (*(pszLine+1)>=0x80 && *(pszLine+1)<=0xA0) ) )
         {
             nEncoding = AVC_CODE_JAP_SHIFTJIS; /* SHIFT-JIS + Kana */
@@ -377,7 +361,7 @@ static int _AVCDetectJapaneseEncoding(const GByte *pszLine)
  * Try to detect type of Japanese encoding if not done yet, and convert
  * string from Japanese to proper coverage DBCS encoding.
  **********************************************************************/
-static const GByte *_AVCJapanese2ArcDBCS(AVCDBCSInfo *psDBCSInfo, 
+static const GByte *_AVCJapanese2ArcDBCS(AVCDBCSInfo *psDBCSInfo,
                                          const GByte *pszLine,
                                          int nMaxOutputLen)
 {
@@ -450,17 +434,17 @@ static const GByte *_AVCJapanese2ArcDBCS(AVCDBCSInfo *psDBCSInfo,
                 trailer -= 0x7D;
                 leader ++;
             }
-            else 
+            else
             {
                 trailer -= 0x1F;
-            }  
+            }
 
             pszOut[iDst++] = leader | 0x80;
             pszOut[iDst++] = trailer | 0x80;
         }
         else
         {
-            /* We should never get here unless a double-byte pair was 
+            /* We should never get here unless a double-byte pair was
              * truncated... but just in case...
              */
             pszOut[iDst++] = *pszLine;
@@ -483,7 +467,7 @@ static const GByte *_AVCJapanese2ArcDBCS(AVCDBCSInfo *psDBCSInfo,
  * which is EUC + all Katakana chars are prefixed with 0x8e.  So this
  * function just does a simple conversion.
  **********************************************************************/
-static const GByte *_AVCArcDBCS2JapaneseShiftJIS(AVCDBCSInfo *psDBCSInfo, 
+static const GByte *_AVCArcDBCS2JapaneseShiftJIS(AVCDBCSInfo *psDBCSInfo,
                                                  const GByte *pszLine,
                                                  int nMaxOutputLen)
 {
@@ -497,7 +481,7 @@ static const GByte *_AVCArcDBCS2JapaneseShiftJIS(AVCDBCSInfo *psDBCSInfo,
         if (IS_ASCII(*pszLine))
         {
             /* No transformation required for ASCII */
-            pszOut[iDst++] = *pszLine;            
+            pszOut[iDst++] = *pszLine;
         }
         else if (*pszLine == 0x8e && *(pszLine+1))
         {
@@ -506,7 +490,7 @@ static const GByte *_AVCArcDBCS2JapaneseShiftJIS(AVCDBCSInfo *psDBCSInfo,
         }
         else if (*(pszLine+1))
         {
-            /* This is a pair of EUC chars... convert them to Shift-JIS 
+            /* This is a pair of EUC chars... convert them to Shift-JIS
              */
             unsigned char leader, trailer;
             leader  = *(pszLine++) & 0x7F;
@@ -515,7 +499,7 @@ static const GByte *_AVCArcDBCS2JapaneseShiftJIS(AVCDBCSInfo *psDBCSInfo,
             if((leader & 0x01) != 0)    trailer += 0x1F;
             else                        trailer += 0x7D;
             if(trailer >= 0x7F)         trailer ++;
-    
+
             leader = ((leader - 0x21) >> 1) + 0x81;
             if(leader > 0x9F)          leader += 0x40;
 
@@ -524,7 +508,7 @@ static const GByte *_AVCArcDBCS2JapaneseShiftJIS(AVCDBCSInfo *psDBCSInfo,
         }
         else
         {
-            /* We should never get here unless a double-byte pair was 
+            /* We should never get here unless a double-byte pair was
              * truncated... but just in case...
              */
             pszOut[iDst++] = *pszLine;
@@ -536,4 +520,3 @@ static const GByte *_AVCArcDBCS2JapaneseShiftJIS(AVCDBCSInfo *psDBCSInfo,
 
     return psDBCSInfo->pszDBCSBuf;
 }
-
diff --git a/ogr/ogrsf_frmts/avc/avc_mbyte.h b/ogr/ogrsf_frmts/avc/avc_mbyte.h
index 0f90a37..432fb5f 100644
--- a/ogr/ogrsf_frmts/avc/avc_mbyte.h
+++ b/ogr/ogrsf_frmts/avc/avc_mbyte.h
@@ -16,16 +16,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -45,8 +45,8 @@
  *
  **********************************************************************/
 
-#ifndef _AVC_MBYTE_H_INCLUDED_
-#define _AVC_MBYTE_H_INCLUDED_
+#ifndef AVC_MBYTE_H_INCLUDED_
+#define AVC_MBYTE_H_INCLUDED_
 
 CPL_C_START
 
@@ -80,9 +80,9 @@ typedef struct AVCDBCSInfo_t
  * Functions prototypes
  *--------------------------------------------------------------------*/
 
-AVCDBCSInfo *AVCAllocDBCSInfo();
+AVCDBCSInfo *AVCAllocDBCSInfo(void);
 void AVCFreeDBCSInfo(AVCDBCSInfo *psInfo);
-int AVCGetDBCSCodePage();
+int AVCGetDBCSCodePage(void);
 GBool AVCE00DetectEncoding(AVCDBCSInfo *psDBCSInfo, const GByte *pszLine);
 const GByte *AVCE00Convert2ArcDBCS(AVCDBCSInfo *psDBCSInfo,
                                    const GByte *pszLine,
@@ -93,6 +93,4 @@ const GByte *AVCE00ConvertFromArcDBCS(AVCDBCSInfo *psDBCSInfo,
 
 CPL_C_END
 
-#endif /* _AVC_MBYTE_H_INCLUDED_ */
-
-
+#endif /* AVC_MBYTE_H_INCLUDED_ */
diff --git a/ogr/ogrsf_frmts/avc/avc_misc.c b/ogr/ogrsf_frmts/avc/avc_misc.c
index 7f1b200..d837711 100644
--- a/ogr/ogrsf_frmts/avc/avc_misc.c
+++ b/ogr/ogrsf_frmts/avc/avc_misc.c
@@ -16,16 +16,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -78,7 +78,7 @@ int _AVCE00ComputeRecSize(int numFields, AVCFieldInfo *pasDef,
 {
     int i, nType, nBufSize=0;
 
-    /*------------------------------------------------------------- 
+    /*-------------------------------------------------------------
      * Add up the nbr of chars used by each field
      *------------------------------------------------------------*/
     for(i=0; i < numFields; i++)
@@ -93,7 +93,7 @@ int _AVCE00ComputeRecSize(int numFields, AVCFieldInfo *pasDef,
             nBufSize += 11;
         else if (nType == AVC_FT_BININT && pasDef[i].nSize == 2)
             nBufSize += 6;
-        else if (bMapType40ToDouble && 
+        else if (bMapType40ToDouble &&
                  nType == AVC_FT_FIXNUM && pasDef[i].nSize > 8)
         {
             /* See explanation in AVCE00GenTableHdr() about this hack to remap
@@ -186,7 +186,7 @@ AVCTableDef *_AVCDupTableDef(AVCTableDef *psSrcDef)
     psNewDef->pasFieldDef = (AVCFieldInfo*)CPLMalloc(psSrcDef->numFields*
                                                      sizeof(AVCFieldInfo));
 
-    memcpy(psNewDef->pasFieldDef, psSrcDef->pasFieldDef, 
+    memcpy(psNewDef->pasFieldDef, psSrcDef->pasFieldDef,
            psSrcDef->numFields*sizeof(AVCFieldInfo));
 
    return psNewDef;
@@ -208,9 +208,9 @@ GBool AVCFileExists(const char *pszPath, const char *pszName)
     GBool       bFileExists = FALSE;
     FILE        *fp;
 
-    pszBuf = (char*)CPLMalloc((strlen(pszPath)+strlen(pszName)+1)*
-                              sizeof(char));
-    sprintf(pszBuf, "%s%s", pszPath, pszName);
+    pszBuf = (char*)CPLMalloc(strlen(pszPath)+strlen(pszName)+1);
+    snprintf(pszBuf,
+             strlen(pszPath)+strlen(pszName)+1, "%s%s", pszPath, pszName);
 
     AVCAdjustCaseSensitiveFilename(pszBuf);
 
@@ -235,11 +235,11 @@ GBool AVCFileExists(const char *pszPath, const char *pszName)
  * It does nothing on Windows systems where filenames are not case sensitive.
  *
  * NFW: It seems like this could be made somewhat more efficient by
- * getting a directory listing and doing a case insensitive search in 
+ * getting a directory listing and doing a case insensitive search in
  * that list rather than all this stating that can be very expensive
  * in some circumstances.  However, at least with Carl's fix this is
  * somewhat faster.
- * see: http://buzilla.remotesensing.org/show_bug.cgi?id=314
+ * see: http://bugzilla.remotesensing.org/show_bug.cgi?id=314
  **********************************************************************/
 char *AVCAdjustCaseSensitiveFilename(char *pszFname)
 {
@@ -277,7 +277,7 @@ char *AVCAdjustCaseSensitiveFilename(char *pszFname)
     }
 
     pszTmpPath = CPLStrdup(pszFname);
-    nTotalLen = strlen(pszTmpPath);
+    nTotalLen = (int)strlen(pszTmpPath);
 
     /*-----------------------------------------------------------------
      * Try all lower case, check if the filename is OK as that.
@@ -343,7 +343,7 @@ char *AVCAdjustCaseSensitiveFilename(char *pszFname)
 
     /*-----------------------------------------------------------------
      * OK, now that we have a valid base, reconstruct the whole path
-     * by scanning all the sub-directories.  
+     * by scanning all the sub-directories.
      * If we get to a point where a path component does not exist then
      * we simply return the rest of the path as is.
      *----------------------------------------------------------------*/
@@ -353,7 +353,7 @@ char *AVCAdjustCaseSensitiveFilename(char *pszFname)
         int     iEntry, iLastPartStart;
 
         iLastPartStart = iTmpPtr;
-        papszDir = CPLReadDir(pszTmpPath);
+        papszDir = VSIReadDir(pszTmpPath);
 
         /*-------------------------------------------------------------
          * Add one component to the current path
@@ -413,12 +413,12 @@ char *AVCAdjustCaseSensitiveFilename(char *pszFname)
  *                          AVCPrintRealValue()
  *
  * Format a floating point value according to the specified coverage
- * precision (AVC_SINGLE/DOUBLE_PREC),  and append the formatted value 
+ * precision (AVC_SINGLE/DOUBLE_PREC),  and append the formatted value
  * to the end of the pszBuf buffer.
  *
  * The function returns the number of characters added to the buffer.
  **********************************************************************/
-int  AVCPrintRealValue(char *pszBuf, int nPrecision, AVCFileType eType,
+int  AVCPrintRealValue(char *pszBuf, size_t nBufLen, int nPrecision, AVCFileType eType,
                         double dValue)
 {
     static int numExpDigits=-1;
@@ -435,9 +435,9 @@ int  AVCPrintRealValue(char *pszBuf, int nPrecision, AVCFileType eType,
         char szBuf[50];
         int  i;
 
-        sprintf(szBuf, "%10.7E", 123.45);
+        CPLsnprintf(szBuf, sizeof(szBuf), "%10.7E", 123.45);
         numExpDigits = 0;
-        for(i=strlen(szBuf)-1; i>0; i--)
+        for(i=(int)strlen(szBuf)-1; i>0; i--)
         {
             if (szBuf[i] == '+' || szBuf[i] == '-')
                 break;
@@ -447,6 +447,7 @@ int  AVCPrintRealValue(char *pszBuf, int nPrecision, AVCFileType eType,
 
     /* We will append the value at the end of the current buffer contents.
      */
+    nBufLen -= strlen(pszBuf);
     pszBuf = pszBuf+strlen(pszBuf);
 
     if (dValue < 0.0)
@@ -458,29 +459,29 @@ int  AVCPrintRealValue(char *pszBuf, int nPrecision, AVCFileType eType,
         *pszBuf = ' ';
 
 
-    /* Just to make things more complicated, double values are 
-     * output in a different format in attribute tables than in 
+    /* Just to make things more complicated, double values are
+     * output in a different format in attribute tables than in
      * the other files!
      */
     if (nPrecision == AVC_FORMAT_DBF_FLOAT)
     {
         /* Float stored in DBF table in PC coverages */
-        sprintf(pszBuf+1, "%9.6E", dValue);
+        CPLsnprintf(pszBuf+1, nBufLen-1, "%9.6E", dValue);
         nLen = 13;
     }
     else if (nPrecision == AVC_DOUBLE_PREC && eType == AVCFileTABLE)
     {
-        sprintf(pszBuf+1, "%20.17E", dValue);
+        CPLsnprintf(pszBuf+1, nBufLen-1,"%20.17E", dValue);
         nLen = 24;
     }
     else if (nPrecision == AVC_DOUBLE_PREC)
     {
-        sprintf(pszBuf+1, "%17.14E", dValue);
+        CPLsnprintf(pszBuf+1, nBufLen-1,"%17.14E", dValue);
         nLen = 21;
     }
-    else 
+    else
     {
-        sprintf(pszBuf+1, "%10.7E", dValue);
+        CPLsnprintf(pszBuf+1, nBufLen-1,"%10.7E", dValue);
         nLen = 14;
     }
 
@@ -489,7 +490,7 @@ int  AVCPrintRealValue(char *pszBuf, int nPrecision, AVCFileType eType,
     if (numExpDigits > 2)
     {
         int n;
-        n = strlen(pszBuf);
+        n = (int)strlen(pszBuf);
 
         pszBuf[n - numExpDigits]    = pszBuf[n-2];
         pszBuf[n - numExpDigits +1] = pszBuf[n-1];
diff --git a/ogr/ogrsf_frmts/avc/avc_rawbin.c b/ogr/ogrsf_frmts/avc/avc_rawbin.c
index 1eb517e..c450f40 100644
--- a/ogr/ogrsf_frmts/avc/avc_rawbin.c
+++ b/ogr/ogrsf_frmts/avc/avc_rawbin.c
@@ -16,16 +16,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -80,7 +80,7 @@
 
 /*---------------------------------------------------------------------
  * Define a static flag and set it with the byte ordering on this machine
- * we will then compare with this value to decide if we nned to swap
+ * we will then compare with this value to decide if we need to swap
  * bytes or not.
  *
  * CPL_MSB or CPL_LSB should be set in the makefile... the default is
@@ -104,7 +104,7 @@ static AVCByteOrder geSystemByteOrder = AVCLittleEndian;
  * Returns a valid AVCRawBinFile structure, or NULL if the file could
  * not be opened or created.
  *
- * AVCRawBinClose() will eventually have to be called to release the 
+ * AVCRawBinClose() will eventually have to be called to release the
  * resources used by the AVCRawBinFile structure.
  **********************************************************************/
 AVCRawBinFile *AVCRawBinOpen(const char *pszFname, const char *pszAccess,
@@ -116,29 +116,29 @@ AVCRawBinFile *AVCRawBinOpen(const char *pszFname, const char *pszAccess,
     psFile = (AVCRawBinFile*)CPLCalloc(1, sizeof(AVCRawBinFile));
 
     /*-----------------------------------------------------------------
-     * Validate access mode and open/create file.  
+     * Validate access mode and open/create file.
      * For now we support only: "r" for read-only or "w" for write-only
      * or "a" for append.
      *
      * A case for "r+" is included here, but random access is not
      * properly supported yet... so this option should be used with care.
      *----------------------------------------------------------------*/
-    if (EQUALN(pszAccess, "r+", 2))
+    if (STARTS_WITH_CI(pszAccess, "r+"))
     {
         psFile->eAccess = AVCReadWrite;
         psFile->fp = VSIFOpen(pszFname, "r+b");
     }
-    else if (EQUALN(pszAccess, "r", 1))
+    else if (STARTS_WITH_CI(pszAccess, "r"))
     {
         psFile->eAccess = AVCRead;
         psFile->fp = VSIFOpen(pszFname, "rb");
     }
-    else if (EQUALN(pszAccess, "w", 1))
+    else if (STARTS_WITH_CI(pszAccess, "w"))
     {
         psFile->eAccess = AVCWrite;
         psFile->fp = VSIFOpen(pszFname, "wb");
     }
-    else if (EQUALN(pszAccess, "a", 1))
+    else if (STARTS_WITH_CI(pszAccess, "a"))
     {
         psFile->eAccess = AVCWrite;
         psFile->fp = VSIFOpen(pszFname, "ab");
@@ -146,13 +146,13 @@ AVCRawBinFile *AVCRawBinOpen(const char *pszFname, const char *pszAccess,
     else
     {
         CPLError(CE_Failure, CPLE_IllegalArg,
-                 "Acces mode \"%s\" not supported.", pszAccess);
+                 "Access mode \"%s\" not supported.", pszAccess);
         CPLFree(psFile);
         return NULL;
     }
 
     /*-----------------------------------------------------------------
-     * Check that file was opened succesfully, and init struct.
+     * Check that file was opened successfully, and init struct.
      *----------------------------------------------------------------*/
     if (psFile->fp == NULL)
     {
@@ -206,7 +206,7 @@ void AVCRawBinClose(AVCRawBinFile *psFile)
  * PC Arc/Info where the physical file size is always a multiple of
  * 256 bytes padded with some junk at the end.
  *
- * The default value is -1 which just looks for the real EOF. 
+ * The default value is -1 which just looks for the real EOF.
  **********************************************************************/
 void AVCRawBinSetFileDataSize(AVCRawBinFile *psFile, int nFileDataSize)
 {
@@ -219,7 +219,7 @@ void AVCRawBinSetFileDataSize(AVCRawBinFile *psFile, int nFileDataSize)
 /**********************************************************************
  *                          AVCRawBinReadBytes()
  *
- * Copy the number of bytes from the input file to the specified 
+ * Copy the number of bytes from the input file to the specified
  * memory location.
  **********************************************************************/
 static GBool bDisableReadBytesEOFError = FALSE;
@@ -230,7 +230,7 @@ void AVCRawBinReadBytes(AVCRawBinFile *psFile, int nBytesToRead, GByte *pBuf)
 
     /* Make sure file is opened with Read access
      */
-    if (psFile == NULL || 
+    if (psFile == NULL ||
         (psFile->eAccess != AVCRead && psFile->eAccess != AVCReadWrite))
     {
         CPLError(CE_Failure, CPLE_FileIO,
@@ -248,7 +248,7 @@ void AVCRawBinReadBytes(AVCRawBinFile *psFile, int nBytesToRead, GByte *pBuf)
         return;
     }
 
-    /* This is the long method... it supports reading data that 
+    /* This is the long method... it supports reading data that
      * overlaps the input buffer boundaries.
      */
     while(nBytesToRead > 0)
@@ -260,7 +260,7 @@ void AVCRawBinReadBytes(AVCRawBinFile *psFile, int nBytesToRead, GByte *pBuf)
         if (psFile->nCurPos == psFile->nCurSize)
         {
             psFile->nOffset += psFile->nCurSize;
-            psFile->nCurSize = VSIFRead(psFile->abyBuf, sizeof(GByte),
+            psFile->nCurSize = (int)VSIFRead(psFile->abyBuf, sizeof(GByte),
                                         AVCRAWBIN_READBUFSIZE, psFile->fp);
             psFile->nCurPos = 0;
         }
@@ -270,7 +270,7 @@ void AVCRawBinReadBytes(AVCRawBinFile *psFile, int nBytesToRead, GByte *pBuf)
             /* Attempt to read past EOF... generate an error.
              *
              * Note: AVCRawBinEOF() can set bDisableReadBytesEOFError=TRUE
-             *       to disable the error message whils it is testing
+             *       to disable the error message while it is testing
              *       for EOF.
              *
              * TODO: We are not resetting the buffer. Also, there is no easy
@@ -286,7 +286,7 @@ void AVCRawBinReadBytes(AVCRawBinFile *psFile, int nBytesToRead, GByte *pBuf)
         }
 
         /* If the requested bytes are not all in the current buffer then
-         * just read the part that's in memory for now... the loop will 
+         * just read the part that's in memory for now... the loop will
          * take care of the rest.
          */
         if (psFile->nCurPos + nBytesToRead > psFile->nCurSize)
@@ -300,7 +300,7 @@ void AVCRawBinReadBytes(AVCRawBinFile *psFile, int nBytesToRead, GByte *pBuf)
         }
         else
         {
-            /* All the requested bytes are now in the buffer... 
+            /* All the requested bytes are now in the buffer...
              * simply copy them and return.
              */
             memcpy(pBuf, psFile->abyBuf+psFile->nCurPos, nBytesToRead);
@@ -328,7 +328,7 @@ void AVCRawBinReadString(AVCRawBinFile *psFile, int nBytesToRead, GByte *pBuf)
     pBuf[nBytesToRead] = '\0';
 
     pszConvBuf = AVCE00ConvertFromArcDBCS(psFile->psDBCSInfo,
-                                          pBuf, 
+                                          pBuf,
                                           nBytesToRead);
 
     if (pszConvBuf != pBuf)
@@ -342,7 +342,7 @@ void AVCRawBinReadString(AVCRawBinFile *psFile, int nBytesToRead, GByte *pBuf)
  *
  * Move the read pointer to the specified location.
  *
- * As with fseek(), the specified position can be relative to the 
+ * As with fseek(), the specified position can be relative to the
  * beginning of the file (SEEK_SET), or the current position (SEEK_CUR).
  * SEEK_END is not supported.
  **********************************************************************/
@@ -358,7 +358,7 @@ void AVCRawBinFSeek(AVCRawBinFile *psFile, int nOffset, int nFrom)
     if (psFile == NULL || psFile->eAccess == AVCWrite)
         return;
 
-    /* Compute destination relative to current memory buffer 
+    /* Compute destination relative to current memory buffer
      */
     if (nFrom == SEEK_SET)
         nTarget = nOffset - psFile->nOffset;
@@ -369,7 +369,7 @@ void AVCRawBinFSeek(AVCRawBinFile *psFile, int nOffset, int nFrom)
      */
     if (nTarget > 0 && nTarget <= psFile->nCurSize)
     {
-        /* Requested location is already in memory... just move the 
+        /* Requested location is already in memory... just move the
          * read pointer
          */
         psFile->nCurPos = nTarget;
@@ -377,13 +377,14 @@ void AVCRawBinFSeek(AVCRawBinFile *psFile, int nOffset, int nFrom)
     else
     {
         /* Requested location is not part of the memory buffer...
-         * move the FILE * to the right location and be ready to 
+         * move the FILE * to the right location and be ready to
          * read from there.
          */
-        VSIFSeek(psFile->fp, psFile->nOffset+nTarget, SEEK_SET);
         psFile->nCurPos = 0;
         psFile->nCurSize = 0;
         psFile->nOffset = psFile->nOffset+nTarget;
+        if( VSIFSeek(psFile->fp, psFile->nOffset+nTarget, SEEK_SET) < 0 )
+            return;
     }
 
 }
@@ -405,7 +406,7 @@ GBool AVCRawBinEOF(AVCRawBinFile *psFile)
     if (psFile->eAccess != AVCRead && psFile->eAccess != AVCReadWrite)
         return TRUE;
 
-    /* If file data size was specified, then check that we have not 
+    /* If file data size was specified, then check that we have not
      * passed that point yet...
      */
     if (psFile->nFileDataSize > 0 &&
@@ -414,14 +415,14 @@ GBool AVCRawBinEOF(AVCRawBinFile *psFile)
 
     /* If the file pointer has been moved by AVCRawBinFSeek(), then
      * we may be at a position past EOF, but VSIFeof() would still
-     * return FALSE. It also returns false if we have read just upto
+     * return FALSE. It also returns false if we have read just up to
      * the end of the file. EOF marker would not have been set unless
      * we try to read past that.
-     * 
+     *
      * To prevent this situation, if the memory buffer is empty,
      * we will try to read 1 byte from the file to force the next
-     * chunk of data to be loaded (and we'll move the the read pointer
-     * back by 1 char after of course!).  
+     * chunk of data to be loaded (and we'll move the read pointer
+     * back by 1 char after of course!).
      * If we are at the end of the file, this will trigger the EOF flag.
      */
     if ((psFile->nCurPos == 0 && psFile->nCurSize == 0) ||
@@ -429,7 +430,7 @@ GBool AVCRawBinEOF(AVCRawBinFile *psFile)
          psFile->nCurSize == AVCRAWBIN_READBUFSIZE))
     {
         GByte c;
-        /* Set bDisableReadBytesEOFError=TRUE to temporarily disable 
+        /* Set bDisableReadBytesEOFError=TRUE to temporarily disable
          * the EOF error message from AVCRawBinReadBytes().
          */
         bDisableReadBytesEOFError = TRUE;
@@ -440,7 +441,7 @@ GBool AVCRawBinEOF(AVCRawBinFile *psFile)
             AVCRawBinFSeek(psFile, -1, SEEK_CUR);
     }
 
-    return (psFile->nCurPos == psFile->nCurSize && 
+    return (psFile->nCurPos == psFile->nCurSize &&
             VSIFEof(psFile->fp));
 }
 
@@ -448,9 +449,9 @@ GBool AVCRawBinEOF(AVCRawBinFile *psFile)
 /**********************************************************************
  *                          AVCRawBinRead<datatype>()
  *
- * Arc/Info files are binary files with MSB first (Motorola) byte 
+ * Arc/Info files are binary files with MSB first (Motorola) byte
  * ordering.  The following functions will read from the input file
- * and return a value with the bytes ordered properly for the current 
+ * and return a value with the bytes ordered properly for the current
  * platform.
  **********************************************************************/
 GInt16  AVCRawBinReadInt16(AVCRawBinFile *psFile)
@@ -516,17 +517,17 @@ double  AVCRawBinReadDouble(AVCRawBinFile *psFile)
  *
  * Write the number of bytes from the buffer to the file.
  *
- * If a problem happens, then CPLError() will be called and 
- * CPLGetLastErrNo() can be used to test if a write operation was 
- * succesful.
+ * If a problem happens, then CPLError() will be called and
+ * CPLGetLastErrNo() can be used to test if a write operation was
+ * successful.
  **********************************************************************/
-void AVCRawBinWriteBytes(AVCRawBinFile *psFile, int nBytesToWrite, 
+void AVCRawBinWriteBytes(AVCRawBinFile *psFile, int nBytesToWrite,
                          const GByte *pBuf)
 {
     /*----------------------------------------------------------------
      * Make sure file is opened with Write access
      *---------------------------------------------------------------*/
-    if (psFile == NULL || 
+    if (psFile == NULL ||
         (psFile->eAccess != AVCWrite && psFile->eAccess != AVCReadWrite))
     {
         CPLError(CE_Failure, CPLE_FileIO,
@@ -549,13 +550,13 @@ void AVCRawBinWriteBytes(AVCRawBinFile *psFile, int nBytesToWrite,
 /**********************************************************************
  *                          AVCRawBinWrite<datatype>()
  *
- * Arc/Info files are binary files with MSB first (Motorola) byte 
+ * Arc/Info files are binary files with MSB first (Motorola) byte
  * ordering.  The following functions will reorder the byte for the
  * value properly and write that to the output file.
  *
- * If a problem happens, then CPLError() will be called and 
- * CPLGetLastErrNo() can be used to test if a write operation was 
- * succesful.
+ * If a problem happens, then CPLError() will be called and
+ * CPLGetLastErrNo() can be used to test if a write operation was
+ * successful.
  **********************************************************************/
 void  AVCRawBinWriteInt16(AVCRawBinFile *psFile, GInt16 n16Value)
 {
@@ -601,23 +602,23 @@ void  AVCRawBinWriteDouble(AVCRawBinFile *psFile, double dValue)
 /**********************************************************************
  *                          AVCRawBinWriteZeros()
  *
- * Write a number of zeros (sepcified in bytes) at the current position 
+ * Write a number of zeros (specified in bytes) at the current position
  * in the file.
  *
- * If a problem happens, then CPLError() will be called and 
- * CPLGetLastErrNo() can be used to test if a write operation was 
- * succesful.
+ * If a problem happens, then CPLError() will be called and
+ * CPLGetLastErrNo() can be used to test if a write operation was
+ * successful.
  **********************************************************************/
 void AVCRawBinWriteZeros(AVCRawBinFile *psFile, int nBytesToWrite)
 {
     char acZeros[8] = {0, 0, 0, 0, 0, 0, 0, 0};
     int i;
 
-    /* Write by 8 bytes chunks.  The last chunk may be less than 8 bytes 
+    /* Write by 8 bytes chunks.  The last chunk may be less than 8 bytes
      */
     for(i=0; i< nBytesToWrite; i+=8)
     {
-        AVCRawBinWriteBytes(psFile, MIN(8,(nBytesToWrite-i)), 
+        AVCRawBinWriteBytes(psFile, MIN(8,(nBytesToWrite-i)),
                             (GByte*)acZeros);
     }
 }
@@ -628,9 +629,9 @@ void AVCRawBinWriteZeros(AVCRawBinFile *psFile, int nBytesToWrite)
  * Write a string and pad the end of the field (up to nFieldSize) with
  * spaces number of spaces at the current position in the file.
  *
- * If a problem happens, then CPLError() will be called and 
- * CPLGetLastErrNo() can be used to test if a write operation was 
- * succesful.
+ * If a problem happens, then CPLError() will be called and
+ * CPLGetLastErrNo() can be used to test if a write operation was
+ * successful.
  **********************************************************************/
 void AVCRawBinWritePaddedString(AVCRawBinFile *psFile, int nFieldSize,
                                 const GByte *pszString)
@@ -644,7 +645,7 @@ void AVCRawBinWritePaddedString(AVCRawBinFile *psFile, int nFieldSize,
     pszString = AVCE00Convert2ArcDBCS(psFile->psDBCSInfo,
                                       pszString, nFieldSize);
 
-    nLen = strlen((const char *)pszString);
+    nLen = (int)strlen((const char *)pszString);
     nLen = MIN(nLen, nFieldSize);
     numSpaces = nFieldSize - nLen;
 
@@ -655,8 +656,7 @@ void AVCRawBinWritePaddedString(AVCRawBinFile *psFile, int nFieldSize,
      */
     for(i=0; i< numSpaces; i+=8)
     {
-        AVCRawBinWriteBytes(psFile, MIN(8,(numSpaces-i)), 
+        AVCRawBinWriteBytes(psFile, MIN(8,(numSpaces-i)),
                             (GByte*)acSpaces);
     }
 }
-
diff --git a/ogr/ogrsf_frmts/avc/dbfopen.h b/ogr/ogrsf_frmts/avc/dbfopen.h
deleted file mode 100644
index 7f7043c..0000000
--- a/ogr/ogrsf_frmts/avc/dbfopen.h
+++ /dev/null
@@ -1,192 +0,0 @@
-#ifndef _SHAPEFILE_H_INCLUDED
-#define _SHAPEFILE_H_INCLUDED
-
-/* NOTE: This file (dbfopen.h) is a copy of shapefil.h (described below)
- *       in which only the DBF-related stuff was kept to include it in
- *       the AVCE00 library.
- */
-
-/******************************************************************************
- * $Id: dbfopen.h,v 1.2 2000/09/26 20:21:05 daniel Exp $
- *
- * Project:  Shapelib
- * Purpose:  Primary include file for Shapelib.
- * Author:   Frank Warmerdam, warmerda at home.com
- *
- ******************************************************************************
- * Copyright (c) 1999, Frank Warmerdam
- *
- * This software is available under the following "MIT Style" license,
- * or at the option of the licensee under the LGPL (see LICENSE.LGPL).  This
- * option is discussed in more detail in shapelib.html.
- *
- * --
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ******************************************************************************
- *
- * $Log: dbfopen.h,v $
- * Revision 1.2  2000/09/26 20:21:05  daniel
- * Added AVCCoverPC write
- *
- * Revision 1.1  1999/12/24 07:16:41  daniel
- * Checked into AVCE00 lib + Added DBFGetNativeFieldType()
- *
- * Revision 1.14  1999/11/05 14:12:05  warmerda
- * updated license terms
- *
- * Revision 1.13  1999/06/02 18:24:21  warmerda
- * added trimming code
- *
- * Revision 1.12  1999/06/02 17:56:12  warmerda
- * added quad'' subnode support for trees
- *
- * Revision 1.11  1999/05/18 19:11:11  warmerda
- * Added example searching capability
- *
- * Revision 1.10  1999/05/18 17:49:38  warmerda
- * added initial quadtree support
- *
- * Revision 1.9  1999/05/11 03:19:28  warmerda
- * added new Tuple api, and improved extension handling - add from candrsn
- *
- * Revision 1.8  1999/03/23 17:22:27  warmerda
- * Added extern "C" protection for C++ users of shapefil.h.
- *
- * Revision 1.7  1998/12/31 15:31:07  warmerda
- * Added the TRIM_DBF_WHITESPACE and DISABLE_MULTIPATCH_MEASURE options.
- *
- * Revision 1.6  1998/12/03 15:48:15  warmerda
- * Added SHPCalculateExtents().
- *
- * Revision 1.5  1998/11/09 20:57:16  warmerda
- * Altered SHPGetInfo() call.
- *
- * Revision 1.4  1998/11/09 20:19:33  warmerda
- * Added 3D support, and use of SHPObject.
- *
- * Revision 1.3  1995/08/23 02:24:05  warmerda
- * Added support for reading bounds.
- *
- * Revision 1.2  1995/08/04  03:17:39  warmerda
- * Added header.
- *
- */
-
-#include <stdio.h>
-
-#ifdef USE_DBMALLOC
-#include <dbmalloc.h>
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-    
-/************************************************************************/
-/*                        Configuration options.                        */
-/************************************************************************/
-
-/* -------------------------------------------------------------------- */
-/*      Should the DBFReadStringAttribute() strip leading and           */
-/*      trailing white space?                                           */
-/* -------------------------------------------------------------------- */
-
-/* Note: For AVCE00 purposes, we do not want the spaces to be stripped.
- *
- * #define TRIM_DBF_WHITESPACE
- */
-
-/************************************************************************/
-/*                             DBF Support.                             */
-/************************************************************************/
-typedef	struct
-{
-    FILE	*fp;
-
-    int         nRecords;
-
-    int		nRecordLength;
-    int		nHeaderLength;
-    int		nFields;
-    int		*panFieldOffset;
-    int		*panFieldSize;
-    int		*panFieldDecimals;
-    char	*pachFieldType;
-
-    char	*pszHeader;
-
-    int		nCurrentRecord;
-    int		bCurrentRecordModified;
-    char	*pszCurrentRecord;
-    
-    int		bNoHeader;
-    int		bUpdated;
-} DBFInfo;
-
-typedef DBFInfo * DBFHandle;
-
-typedef enum {
-  FTString,
-  FTInteger,
-  FTDouble,
-  FTInvalid
-} DBFFieldType;
-
-#define XBASE_FLDHDR_SZ       32
-
-DBFHandle DBFOpen( const char * pszDBFFile, const char * pszAccess );
-DBFHandle DBFCreate( const char * pszDBFFile );
-
-int	DBFGetFieldCount( DBFHandle psDBF );
-int	DBFGetRecordCount( DBFHandle psDBF );
-int	DBFAddField( DBFHandle hDBF, const char * pszFieldName,
-		     DBFFieldType eType, int nWidth, int nDecimals );
-
-DBFFieldType DBFGetFieldInfo( DBFHandle psDBF, int iField, 
-			      char * pszFieldName, 
-			      int * pnWidth, int * pnDecimals );
-
-char    DBFGetNativeFieldType( DBFHandle psDBF, int iField );
-
-int 	DBFReadIntegerAttribute( DBFHandle hDBF, int iShape, int iField );
-double 	DBFReadDoubleAttribute( DBFHandle hDBF, int iShape, int iField );
-const char *DBFReadStringAttribute( DBFHandle hDBF, int iShape, int iField );
-
-int DBFWriteIntegerAttribute( DBFHandle hDBF, int iShape, int iField, 
-			      int nFieldValue );
-int DBFWriteDoubleAttribute( DBFHandle hDBF, int iShape, int iField,
-			     double dFieldValue );
-int DBFWriteStringAttribute( DBFHandle hDBF, int iShape, int iField,
-			     const char * pszFieldValue );
-int DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField,
-                              void * pValue );
-
-const char *DBFReadTuple(DBFHandle psDBF, int hEntity );
-int DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple );
-
-DBFHandle DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename );
- 
-void	DBFClose( DBFHandle hDBF );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* ndef _SHAPEFILE_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/avc/drv_avcbin.html b/ogr/ogrsf_frmts/avc/drv_avcbin.html
index e20e14d..59ba10c 100644
--- a/ogr/ogrsf_frmts/avc/drv_avcbin.html
+++ b/ogr/ogrsf_frmts/avc/drv_avcbin.html
@@ -10,27 +10,27 @@
 Arc/Info Binary Coverages (eg. Arc/Info V7 and earlier) are supported by
 OGR for read access.  <p>
 
-The label, arc, polygon, centroid, region and text 
+The label, arc, polygon, centroid, region and text
 sections of a coverage are all supported as layers.  Attributes from INFO
 are appended to labels, arcs, polygons or region where appropriate.  When
-available the projection information is read and translated.  Polygon 
+available the projection information is read and translated.  Polygon
 geometries are collected for polygon and region layers from the composing arcs.
 <p>
 
 Text sections are represented as point layers.  Display height is preserved
-in the HEIGHT attribute field; however, other information about text 
+in the HEIGHT attribute field; however, other information about text
 orientation is discarded.<p>
 
-Info tables associated with a coverage, but not sepecifically named to be
-attached to one of the existing geometric layers is currently not accessable
+Info tables associated with a coverage, but not specifically named to be
+attached to one of the existing geometric layers is currently not accessible
 through OGR.  Note that info tables are stored in an 'info' directory at
-the same level as the coverage directory.  If this is inaccessable or 
+the same level as the coverage directory.  If this is inaccessible or
 corrupt no info attributes will be appended to coverage layers, but the
-geometry should still be accessable.<p>
+geometry should still be accessible.<p>
 
 If the directory contains files with names like w001001.adf then the coverage is
 a <a href="http://www.gdal.org/frmt_various.html#AIG">grid coverage</a>
-suitable to read with GDAL, not a vector coverage supported by OGR.<p>  
+suitable to read with GDAL, not a vector coverage supported by OGR.<p>
 
 The layers are named as follows:
 
@@ -48,13 +48,13 @@ The Arc/Info binary coverage driver attempts to optimize spatial queries
 but due to the lack of a spatial index this is just accomplished by minimizing
 processing for features not within the spatial window.<p>
 
-Random (by FID) reads of arcs, and polygons is supported it may not be 
+Random (by FID) reads of arcs, and polygons is supported it may not be
 supported for other feature types.<p>
 
 <h2>See Also</h2>
 <ul>
-<li> <a href="http://avce00.maptools.org/">AVCE00 Library Page</a> 
-<li> <a href="ogr_avce00.html">AVCE00 OGR Driver (.E00)</a>
+<li> <a href="http://avce00.maptools.org/">AVCE00 Library Page</a>
+<li> <a href="drv_avce00.html">AVCE00 OGR Driver (.E00)</a>
 </ul>
 
 </body>
diff --git a/ogr/ogrsf_frmts/avc/drv_avce00.html b/ogr/ogrsf_frmts/avc/drv_avce00.html
index bdbacf5..98d3668 100644
--- a/ogr/ogrsf_frmts/avc/drv_avce00.html
+++ b/ogr/ogrsf_frmts/avc/drv_avce00.html
@@ -10,23 +10,23 @@
 Arc/Info E00 Coverages (eg. Arc/Info V7 and earlier) are supported by
 OGR for read access.  <p>
 
-The label, arc, polygon, centroid, region and text 
+The label, arc, polygon, centroid, region and text
 sections of a coverage are all supported as layers.  Attributes from INFO
 are appended to labels, arcs, polygons or region where appropriate.  When
-available the projection information is read and translated.  Polygon 
+available the projection information is read and translated.  Polygon
 geometries are collected for polygon and region layers from the composing arcs.
 <p>
 
 Text sections are represented as point layers.  Display height is preserved
-in the HEIGHT attribute field; however, other information about text 
+in the HEIGHT attribute field; however, other information about text
 orientation is discarded.<p>
 
-Info tables associated with a coverage, but not sepecifically named to be
-attached to one of the existing geometric layers is currently not accessable
+Info tables associated with a coverage, but not specifically named to be
+attached to one of the existing geometric layers is currently not accessible
 through OGR.  Note that info tables are stored in an 'info' directory at
-the same level as the coverage directory.  If this is inaccessable or 
+the same level as the coverage directory.  If this is inaccessible or
 corrupt no info attributes will be appended to coverage layers, but the
-geometry should still be accessable.<p>
+geometry should still be accessible.<p>
 
 The layers are named as follows:
 
@@ -40,14 +40,14 @@ LAB if present. <p>
 <li> A region subclass is named according to the subclass name. <p>
 </ol>
 
-Random (by FID) reads of arcs, and polygons is supported it may not be 
+Random (by FID) reads of arcs, and polygons is supported it may not be
 supported for other feature types.  Random ascess to E00 files is generally
 slow.<p>
 
 <h2>See Also</h2>
 <ul>
-<li> <a href="http://avce00.maptools.org/">AVCE00 Library Page</a> 
-<li> <a href="ogr_avcbin.html">AVCBin OGR Driver (Binary Coverage)</a>
+<li> <a href="http://avce00.maptools.org/">AVCE00 Library Page</a>
+<li> <a href="drv_avcbin.html">AVCBin OGR Driver (Binary Coverage)</a>
 </ul>
 
 </body>
diff --git a/ogr/ogrsf_frmts/avc/ogr_avc.h b/ogr/ogrsf_frmts/avc/ogr_avc.h
index c66a936..db53a28 100644
--- a/ogr/ogrsf_frmts/avc/ogr_avc.h
+++ b/ogr/ogrsf_frmts/avc/ogr_avc.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_avc.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogr_avc.h 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Arc/Info Coverage (E00 & Binary) Reader
  * Purpose:  Declarations for OGR wrapper classes for coverage access.
@@ -14,21 +14,21 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_AVC_H_INCLUDED
-#define _OGR_AVC_H_INCLUDED
+#ifndef OGR_AVC_H_INCLUDED
+#define OGR_AVC_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "avc.h"
@@ -45,29 +45,29 @@ class OGRAVCLayer : public OGRLayer
     OGRFeatureDefn      *poFeatureDefn;
 
     OGRAVCDataSource    *poDS;
-    
+
     AVCFileType         eSectionType;
 
-    int                 SetupFeatureDefinition( const char *pszName ); 
+    int                 SetupFeatureDefinition( const char *pszName );
     int                 AppendTableDefinition( AVCTableDef *psTableDef );
 
     int                 MatchesSpatialFilter( void * );
     OGRFeature          *TranslateFeature( void * );
 
-    int                 TranslateTableFields( OGRFeature *poFeature, 
-                                              int nFieldBase, 
+    int                 TranslateTableFields( OGRFeature *poFeature,
+                                              int nFieldBase,
                                               AVCTableDef *psTableDef,
                                               AVCField *pasFields );
 
   public:
-                        OGRAVCLayer( AVCFileType eSectionType, 
+                        OGRAVCLayer( AVCFileType eSectionType,
                                      OGRAVCDataSource *poDS );
     			~OGRAVCLayer();
 
     OGRFeatureDefn *	GetLayerDefn() { return poFeatureDefn; }
 
     virtual OGRSpatialReference *GetSpatialRef();
-    
+
     virtual int         TestCapability( const char * );
 };
 
@@ -102,7 +102,7 @@ class OGRAVCBinDataSource;
 
 class OGRAVCBinLayer : public OGRAVCLayer
 {
-    AVCE00Section       *psSection;
+    AVCE00Section       *m_psSection;
     AVCBinFile          *hFile;
 
     OGRAVCBinLayer      *poArcLayer;
@@ -142,11 +142,11 @@ class OGRAVCBinDataSource : public OGRAVCDataSource
 {
     OGRLayer            **papoLayers;
     int			nLayers;
-    
+
     char		*pszName;
 
     AVCE00ReadPtr       psAVC;
-    
+
   public:
     			OGRAVCBinDataSource();
     			~OGRAVCBinDataSource();
@@ -231,4 +231,4 @@ class OGRAVCE00DataSource : public OGRAVCDataSource
 };
 
 
-#endif /* _OGR_AVC_H_INCLUDED */
+#endif /* OGR_AVC_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/avc/ogravcbindatasource.cpp b/ogr/ogrsf_frmts/avc/ogravcbindatasource.cpp
index b827555..8aaceee 100644
--- a/ogr/ogrsf_frmts/avc/ogravcbindatasource.cpp
+++ b/ogr/ogrsf_frmts/avc/ogravcbindatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogravcbindatasource.cpp 28039 2014-11-30 18:24:59Z rouault $
+ * $Id: ogravcbindatasource.cpp 32122 2015-12-11 16:01:28Z goatbar $
  *
  * Project:  OGR
  * Purpose:  Implements OGRAVCBinDataSource class.
@@ -31,18 +31,18 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogravcbindatasource.cpp 28039 2014-11-30 18:24:59Z rouault $");
+CPL_CVSID("$Id: ogravcbindatasource.cpp 32122 2015-12-11 16:01:28Z goatbar $");
 
 /************************************************************************/
 /*                        OGRAVCBinDataSource()                         */
 /************************************************************************/
 
-OGRAVCBinDataSource::OGRAVCBinDataSource()
-
+OGRAVCBinDataSource::OGRAVCBinDataSource() :
+    papoLayers(NULL),
+    nLayers(0),
+    pszName(NULL),
+    psAVC(NULL)
 {
-    pszName = NULL;
-    papoLayers = NULL;
-    nLayers = 0;
     poSRS = NULL;
 }
 
@@ -63,7 +63,7 @@ OGRAVCBinDataSource::~OGRAVCBinDataSource()
 
     for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
-    
+
     CPLFree( papoLayers );
 }
 
@@ -98,13 +98,12 @@ int OGRAVCBinDataSource::Open( const char * pszNewName, int bTestOpen )
 /* -------------------------------------------------------------------- */
 /*      Create layers for the "interesting" sections of the coverage.   */
 /* -------------------------------------------------------------------- */
-    int		iSection;
 
-    papoLayers = (OGRLayer **)
-        CPLCalloc( sizeof(OGRLayer *), psAVC->numSections );
+    papoLayers = static_cast<OGRLayer **>(
+        CPLCalloc( sizeof(OGRLayer *), psAVC->numSections ) );
     nLayers = 0;
 
-    for( iSection = 0; iSection < psAVC->numSections; iSection++ )
+    for( int iSection = 0; iSection < psAVC->numSections; iSection++ )
     {
         AVCE00Section *psSec = psAVC->pasSections + iSection;
 
@@ -122,26 +121,26 @@ int OGRAVCBinDataSource::Open( const char * pszNewName, int bTestOpen )
 
           case AVCFilePRJ:
           {
-              char 	**papszPRJ;
-              AVCBinFile *hFile;
-              
-              hFile = AVCBinReadOpen(psAVC->pszCoverPath, 
-                                     psSec->pszFilename, 
-                                     psAVC->eCoverType, 
-                                     psSec->eType,
-                                     psAVC->psDBCSInfo);
+              AVCBinFile *hFile = AVCBinReadOpen(psAVC->pszCoverPath,
+                                                 psSec->pszFilename,
+                                                 psAVC->eCoverType,
+                                                 psSec->eType,
+                                                 psAVC->psDBCSInfo);
               if( hFile && poSRS == NULL )
               {
-                  papszPRJ = AVCBinReadNextPrj( hFile );
+                  char **papszPRJ = AVCBinReadNextPrj( hFile );
 
                   poSRS = new OGRSpatialReference();
                   if( poSRS->importFromESRI( papszPRJ ) != OGRERR_NONE )
                   {
-                      CPLError( CE_Warning, CPLE_AppDefined, 
+                      CPLError( CE_Warning, CPLE_AppDefined,
                                 "Failed to parse PRJ section, ignoring." );
                       delete poSRS;
                       poSRS = NULL;
                   }
+              }
+              if( hFile )
+              {
                   AVCBinReadClose( hFile );
               }
           }
@@ -151,7 +150,7 @@ int OGRAVCBinDataSource::Open( const char * pszNewName, int bTestOpen )
             ;
         }
     }
-    
+
     return nLayers > 0;
 }
 
@@ -173,6 +172,6 @@ OGRLayer *OGRAVCBinDataSource::GetLayer( int iLayer )
 {
     if( iLayer < 0 || iLayer >= nLayers )
         return NULL;
-    else
-        return papoLayers[iLayer];
+
+    return papoLayers[iLayer];
 }
diff --git a/ogr/ogrsf_frmts/avc/ogravcbindriver.cpp b/ogr/ogrsf_frmts/avc/ogravcbindriver.cpp
index 7a339f0..2ba2bc7 100644
--- a/ogr/ogrsf_frmts/avc/ogravcbindriver.cpp
+++ b/ogr/ogrsf_frmts/avc/ogravcbindriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogravcbindriver.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogravcbindriver.cpp 32122 2015-12-11 16:01:28Z goatbar $
  *
  * Project:  OGR
  * Purpose:  OGRAVCBinDriver implementation (Arc/Info Binary Coverages)
@@ -29,7 +29,7 @@
 
 #include "ogr_avc.h"
 
-CPL_CVSID("$Id: ogravcbindriver.cpp 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: ogravcbindriver.cpp 32122 2015-12-11 16:01:28Z goatbar $");
 
 /************************************************************************/
 /*                                Open()                                */
@@ -38,9 +38,6 @@ CPL_CVSID("$Id: ogravcbindriver.cpp 27384 2014-05-24 12:28:12Z rouault $");
 static GDALDataset *OGRAVCBinDriverOpen( GDALOpenInfo* poOpenInfo )
 
 {
-    OGRAVCBinDataSource	*poDS;
-    OGRAVCE00DataSource *poDSE00;
-
     if( poOpenInfo->eAccess == GA_Update )
         return NULL;
     if( !poOpenInfo->bStatOK )
@@ -56,13 +53,12 @@ static GDALDataset *OGRAVCBinDriverOpen( GDALOpenInfo* poOpenInfo )
             char** papszSiblingFiles = poOpenInfo->GetSiblingFiles();
             if( papszSiblingFiles != NULL )
             {
-                int i;
-                int bFoundCandidateFile = FALSE;
-                for( i = 0; papszSiblingFiles[i] != NULL; i++ )
+                bool bFoundCandidateFile = false;
+                for( int i = 0; papszSiblingFiles[i] != NULL; i++ )
                 {
                     if( EQUAL(CPLGetExtension(papszSiblingFiles[i]), "ADF") )
                     {
-                        bFoundCandidateFile = TRUE;
+                        bFoundCandidateFile = true;
                         break;
                     }
                 }
@@ -72,7 +68,7 @@ static GDALDataset *OGRAVCBinDriverOpen( GDALOpenInfo* poOpenInfo )
         }
     }
 
-    poDS = new OGRAVCBinDataSource();
+    OGRAVCBinDataSource *poDS = new OGRAVCBinDataSource();
 
     if( poDS->Open( poOpenInfo->pszFilename, TRUE )
         && poDS->GetLayerCount() > 0 )
@@ -81,7 +77,7 @@ static GDALDataset *OGRAVCBinDriverOpen( GDALOpenInfo* poOpenInfo )
     }
     delete poDS;
 
-    poDSE00 = new OGRAVCE00DataSource();
+    OGRAVCE00DataSource *poDSE00 = new OGRAVCE00DataSource();
 
     if( poDSE00->Open( poOpenInfo->pszFilename, TRUE )
         && poDSE00->GetLayerCount() > 0 )
@@ -100,21 +96,17 @@ static GDALDataset *OGRAVCBinDriverOpen( GDALOpenInfo* poOpenInfo )
 void RegisterOGRAVCBin()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "AVCBin" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "AVCBin" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver  *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "AVCBin" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Arc/Info Binary Coverage" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_avcbin.html" );
+    poDriver->SetDescription( "AVCBin" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Arc/Info Binary Coverage" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_avcbin.html" );
 
-        poDriver->pfnOpen = OGRAVCBinDriverOpen;
+    poDriver->pfnOpen = OGRAVCBinDriverOpen;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/avc/ogravcbinlayer.cpp b/ogr/ogrsf_frmts/avc/ogravcbinlayer.cpp
index b330e3d..1ae9a9a 100644
--- a/ogr/ogrsf_frmts/avc/ogravcbinlayer.cpp
+++ b/ogr/ogrsf_frmts/avc/ogravcbinlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogravcbinlayer.cpp 28383 2015-01-30 15:47:59Z rouault $
+ * $Id: ogravcbinlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OGR
  * Purpose:  Implements OGRAVCBinLayer class.
@@ -32,42 +32,43 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogravcbinlayer.cpp 28383 2015-01-30 15:47:59Z rouault $");
+CPL_CVSID("$Id: ogravcbinlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                           OGRAVCBinLayer()                           */
 /************************************************************************/
 
 OGRAVCBinLayer::OGRAVCBinLayer( OGRAVCBinDataSource *poDSIn,
-                                AVCE00Section *psSectionIn )
-        : OGRAVCLayer( psSectionIn->eType, poDSIn )
-
+                                AVCE00Section *psSectionIn ) :
+    OGRAVCLayer( psSectionIn->eType, poDSIn ),
+    m_psSection(psSectionIn),
+    hFile(NULL),
+    poArcLayer(NULL),
+    bNeedReset(FALSE),
+    hTable(NULL),
+    nTableBaseField(-1),
+    nTableAttrIndex(-1),
+    nNextFID(1)
 {
-    psSection = psSectionIn;
-    hFile = NULL;
-    poArcLayer = NULL;
-    bNeedReset = FALSE;
-    nNextFID = 1;
-
-    hTable = NULL;
-    nTableBaseField = -1;
-    nTableAttrIndex = -1;
+    SetupFeatureDefinition( m_psSection->pszName );
 
-    SetupFeatureDefinition( psSection->pszName );
-    
     szTableName[0] = '\0';
-    if( psSection->eType == AVCFilePAL )
-        sprintf( szTableName, "%s.PAT", poDS->GetCoverageName() );
-    else if( psSection->eType == AVCFileRPL )
-        sprintf( szTableName, "%s.PAT%s", poDS->GetCoverageName(),
-                 psSectionIn->pszName );
-    else if( psSection->eType == AVCFileARC )
-        sprintf( szTableName, "%s.AAT", poDS->GetCoverageName() );
-    else if( psSection->eType == AVCFileLAB )
+    if( m_psSection->eType == AVCFilePAL )
+        snprintf( szTableName, sizeof(szTableName), "%s.PAT",
+                  poDS->GetCoverageName() );
+    else if( m_psSection->eType == AVCFileRPL )
+        snprintf( szTableName, sizeof(szTableName), "%s.PAT%s",
+                  poDS->GetCoverageName(), m_psSection->pszName );
+    else if( m_psSection->eType == AVCFileARC )
+        snprintf( szTableName, sizeof(szTableName), "%s.AAT",
+                  poDS->GetCoverageName() );
+    else if( m_psSection->eType == AVCFileLAB )
     {
-        AVCE00ReadPtr psInfo = ((OGRAVCBinDataSource *) poDS)->GetInfo();
+        AVCE00ReadPtr psInfo
+            = static_cast<OGRAVCBinDataSource *>( poDS) ->GetInfo();
 
-        sprintf( szTableName, "%s.PAT", poDS->GetCoverageName() );
+        snprintf( szTableName, sizeof(szTableName), "%s.PAT",
+                  poDS->GetCoverageName() );
 
         for( int iSection = 0; iSection < psInfo->numSections; iSection++ )
         {
@@ -119,7 +120,7 @@ void OGRAVCBinLayer::ResetReading()
 OGRFeature *OGRAVCBinLayer::GetFeature( GIntBig nFID )
 
 {
-    if( (GIntBig)(int)nFID != nFID )
+    if( !CPL_INT64_FITS_ON_INT32(nFID) )
         return NULL;
 
 /* -------------------------------------------------------------------- */
@@ -127,12 +128,13 @@ OGRFeature *OGRAVCBinLayer::GetFeature( GIntBig nFID )
 /* -------------------------------------------------------------------- */
     if( hFile == NULL )
     {
-        AVCE00ReadPtr psInfo = ((OGRAVCBinDataSource *) poDS)->GetInfo();
+        AVCE00ReadPtr psInfo
+            = static_cast<OGRAVCBinDataSource *>( poDS )->GetInfo();
 
-        hFile = AVCBinReadOpen(psInfo->pszCoverPath, 
-                               psSection->pszFilename, 
-                               psInfo->eCoverType, 
-                               psSection->eType,
+        hFile = AVCBinReadOpen(psInfo->pszCoverPath,
+                               m_psSection->pszFilename,
+                               psInfo->eCoverType,
+                               m_psSection->eType,
                                psInfo->psDBCSInfo);
     }
 
@@ -140,7 +142,7 @@ OGRFeature *OGRAVCBinLayer::GetFeature( GIntBig nFID )
 /*      Read the raw feature - the -3 fid is a special flag             */
 /*      indicating serial access.                                       */
 /* -------------------------------------------------------------------- */
-    void *pFeature;
+    void *pFeature = NULL;
 
     if( nFID == -3 )
     {
@@ -155,7 +157,7 @@ OGRFeature *OGRAVCBinLayer::GetFeature( GIntBig nFID )
         bNeedReset = TRUE;
         pFeature = AVCBinReadObject( hFile, (int)nFID );
     }
-        
+
     if( pFeature == NULL )
         return NULL;
 
@@ -172,7 +174,7 @@ OGRFeature *OGRAVCBinLayer::GetFeature( GIntBig nFID )
 /*      LAB's we have to assign the FID to directly, since it           */
 /*      doesn't seem to be stored in the file structure.                */
 /* -------------------------------------------------------------------- */
-    if( psSection->eType == AVCFileLAB )
+    if( m_psSection->eType == AVCFileLAB )
     {
         if( nFID == -3 )
             poFeature->SetFID( nNextFID++ );
@@ -184,8 +186,8 @@ OGRFeature *OGRAVCBinLayer::GetFeature( GIntBig nFID )
 /*      If this is a polygon layer, try to assemble the arcs to form    */
 /*      the whole polygon geometry.                                     */
 /* -------------------------------------------------------------------- */
-    if( psSection->eType == AVCFilePAL 
-        || psSection->eType == AVCFileRPL )
+    if( m_psSection->eType == AVCFilePAL
+        || m_psSection->eType == AVCFileRPL )
         FormPolygonGeometry( poFeature, (AVCPal *) pFeature );
 
 /* -------------------------------------------------------------------- */
@@ -209,14 +211,14 @@ OGRFeature *OGRAVCBinLayer::GetNextFeature()
     OGRFeature *poFeature = GetFeature( -3 );
 
     // Skip universe polygon.
-    if( poFeature != NULL && poFeature->GetFID() == 1 
-        && psSection->eType == AVCFilePAL )
+    if( poFeature != NULL && poFeature->GetFID() == 1
+        && m_psSection->eType == AVCFilePAL )
     {
         OGRFeature::DestroyFeature( poFeature );
         poFeature = GetFeature( -3 );
     }
 
-    while( poFeature != NULL 
+    while( poFeature != NULL
            && ((m_poAttrQuery != NULL
                 && !m_poAttrQuery->Evaluate( poFeature ) )
                || !FilterGeometry( poFeature->GetGeometryRef() ) ) )
@@ -240,8 +242,8 @@ int OGRAVCBinLayer::TestCapability( const char * pszCap )
 {
     if( eSectionType == AVCFileARC && EQUAL(pszCap,OLCRandomRead) )
         return TRUE;
-    else 
-        return OGRAVCLayer::TestCapability( pszCap );
+
+    return OGRAVCLayer::TestCapability( pszCap );
 }
 
 /************************************************************************/
@@ -251,7 +253,7 @@ int OGRAVCBinLayer::TestCapability( const char * pszCap )
 /*      them into the appropriate OGR geometry on the target feature.   */
 /************************************************************************/
 
-int OGRAVCBinLayer::FormPolygonGeometry( OGRFeature *poFeature, 
+int OGRAVCBinLayer::FormPolygonGeometry( OGRFeature *poFeature,
                                          AVCPal *psPAL )
 
 {
@@ -261,11 +263,10 @@ int OGRAVCBinLayer::FormPolygonGeometry( OGRFeature *poFeature,
 /* -------------------------------------------------------------------- */
     if( poArcLayer == NULL )
     {
-        int	i;
-
-        for( i = 0; i < poDS->GetLayerCount(); i++ )
+        for( int i = 0; i < poDS->GetLayerCount(); i++ )
         {
-            OGRAVCBinLayer *poLayer = (OGRAVCBinLayer *) poDS->GetLayer(i);
+            OGRAVCBinLayer *poLayer
+                = static_cast<OGRAVCBinLayer *>( poDS->GetLayer(i) );
 
             if( poLayer->eSectionType == AVCFileARC )
                 poArcLayer = poLayer;
@@ -276,16 +277,13 @@ int OGRAVCBinLayer::FormPolygonGeometry( OGRFeature *poFeature,
     }
 
 /* -------------------------------------------------------------------- */
-/*	Read all the arcs related to this polygon, making a working	*/
-/*	copy of them since the one returned by AVC is temporary.	*/
+/*      Read all the arcs related to this polygon, making a working     */
+/*      copy of them since the one returned by AVC is temporary.        */
 /* -------------------------------------------------------------------- */
     OGRGeometryCollection oArcs;
-    int		iArc;
 
-    for( iArc = 0; iArc < psPAL->numArcs; iArc++ )
+    for( int iArc = 0; iArc < psPAL->numArcs; iArc++ )
     {
-        OGRFeature *poArc;
-
         if( psPAL->pasArcs[iArc].nArcId == 0 )
             continue;
 
@@ -293,11 +291,12 @@ int OGRAVCBinLayer::FormPolygonGeometry( OGRFeature *poFeature,
         // arc is a "bridge" arc and can be discarded.  If we don't discard
         // it, then we should double it as bridge arcs seem to only appear
         // once.  But by discarding it we ensure a multi-ring polygon will be
-        // properly formed. 
+        // properly formed.
         if( psPAL->pasArcs[iArc].nAdjPoly == psPAL->nPolyId )
             continue;
 
-        poArc = poArcLayer->GetFeature( ABS(psPAL->pasArcs[iArc].nArcId) );
+        OGRFeature *poArc
+            = poArcLayer->GetFeature( ABS(psPAL->pasArcs[iArc].nArcId) );
 
         if( poArc == NULL )
             return FALSE;
@@ -309,12 +308,11 @@ int OGRAVCBinLayer::FormPolygonGeometry( OGRFeature *poFeature,
         OGRFeature::DestroyFeature( poArc );
     }
 
-    OGRErr  eErr;
-    OGRPolygon *poPolygon;
-
-    poPolygon = (OGRPolygon *) 
-        OGRBuildPolygonFromEdges( (OGRGeometryH) &oArcs, TRUE, FALSE,  
-                                  0.0, &eErr );
+    OGRErr eErr;
+    OGRPolygon *poPolygon
+      = reinterpret_cast<OGRPolygon *>(
+        OGRBuildPolygonFromEdges( (OGRGeometryH) &oArcs, TRUE, FALSE,
+                                  0.0, &eErr ) );
     if( poPolygon != NULL )
         poFeature->SetGeometryDirectly( poPolygon );
 
@@ -338,22 +336,22 @@ int OGRAVCBinLayer::CheckSetupTable()
 /* -------------------------------------------------------------------- */
 /*      Scan for the indicated section.                                 */
 /* -------------------------------------------------------------------- */
-    AVCE00ReadPtr psInfo = ((OGRAVCBinDataSource *) poDS)->GetInfo();
-    int           iSection;
-    AVCE00Section *psSection = NULL;
-    char	  szPaddedName[65];
-    
-    sprintf( szPaddedName, "%s%32s", szTableName, " " );
+    AVCE00ReadPtr psInfo
+        = static_cast<OGRAVCBinDataSource *>( poDS )->GetInfo();
+    char szPaddedName[65];
+
+    snprintf( szPaddedName, sizeof(szPaddedName), "%s%32s", szTableName, " " );
     szPaddedName[32] = '\0';
 
-    for( iSection = 0; iSection < psInfo->numSections; iSection++ )
+    AVCE00Section *l_psSection = NULL;
+    for( int iSection = 0; iSection < psInfo->numSections; iSection++ )
     {
-        if( EQUAL(szPaddedName,psInfo->pasSections[iSection].pszName) 
+        if( EQUAL(szPaddedName,psInfo->pasSections[iSection].pszName)
             && psInfo->pasSections[iSection].eType == AVCFileTABLE )
-            psSection = psInfo->pasSections + iSection;
+            l_psSection = psInfo->pasSections + iSection;
     }
 
-    if( psSection == NULL )
+    if( l_psSection == NULL )
     {
         szTableName[0] = '\0';
         return FALSE;
@@ -365,18 +363,18 @@ int OGRAVCBinLayer::CheckSetupTable()
     hTable = AVCBinReadOpen( psInfo->pszInfoPath,  szTableName,
                              psInfo->eCoverType, AVCFileTABLE,
                              psInfo->psDBCSInfo);
-    
+
     if( hTable == NULL )
     {
         szTableName[0] = '\0';
         return FALSE;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Setup attributes.                                               */
 /* -------------------------------------------------------------------- */
     nTableBaseField = poFeatureDefn->GetFieldCount();
-    
+
     AppendTableDefinition( hTable->hdr.psTableDef );
 
 /* -------------------------------------------------------------------- */
@@ -396,7 +394,8 @@ int OGRAVCBinLayer::CheckSetupTable()
 int OGRAVCBinLayer::AppendTableFields( OGRFeature *poFeature )
 
 {
-    AVCE00ReadPtr psInfo = ((OGRAVCBinDataSource *) poDS)->GetInfo();
+    AVCE00ReadPtr psInfo
+        = static_cast<OGRAVCBinDataSource *>( poDS)->GetInfo();
 
     if( szTableName[0] == '\0' )
         return FALSE;
@@ -423,27 +422,21 @@ int OGRAVCBinLayer::AppendTableFields( OGRFeature *poFeature )
 /*      nTableAttrIndex will already be setup to refer to the           */
 /*      PolyId field.                                                   */
 /* -------------------------------------------------------------------- */
-    int	nRecordId;
-    void *hRecord;
+    int nRecordId;
 
     if( nTableAttrIndex == -1 )
-        nRecordId = (int) poFeature->GetFID();
+        nRecordId = static_cast<int>( poFeature->GetFID() );
     else
         nRecordId = poFeature->GetFieldAsInteger( nTableAttrIndex );
 
-    hRecord = AVCBinReadObject( hTable, nRecordId );
+    void *hRecord = AVCBinReadObject( hTable, nRecordId );
     if( hRecord == NULL )
         return FALSE;
 
 /* -------------------------------------------------------------------- */
 /*      Translate it.                                                   */
 /* -------------------------------------------------------------------- */
-    return TranslateTableFields( poFeature, nTableBaseField, 
-                                 hTable->hdr.psTableDef, 
+    return TranslateTableFields( poFeature, nTableBaseField,
+                                 hTable->hdr.psTableDef,
                                  (AVCField *) hRecord );
 }
-
-
-
-
-
diff --git a/ogr/ogrsf_frmts/avc/ogravcdatasource.cpp b/ogr/ogrsf_frmts/avc/ogravcdatasource.cpp
index a4ffcb7..94f82aa 100644
--- a/ogr/ogrsf_frmts/avc/ogravcdatasource.cpp
+++ b/ogr/ogrsf_frmts/avc/ogravcdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogravcdatasource.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: ogravcdatasource.cpp 32122 2015-12-11 16:01:28Z goatbar $
  *
  * Project:  OGR
  * Purpose:  Implements OGRAVCDataSource class.
@@ -29,18 +29,16 @@
 
 #include "ogr_avc.h"
 
-CPL_CVSID("$Id: ogravcdatasource.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: ogravcdatasource.cpp 32122 2015-12-11 16:01:28Z goatbar $");
 
 /************************************************************************/
 /*                          OGRAVCDataSource()                          */
 /************************************************************************/
 
-OGRAVCDataSource::OGRAVCDataSource()
-
-{
-    poSRS = NULL;
-    pszCoverageName = NULL;
-}
+OGRAVCDataSource::OGRAVCDataSource() :
+    poSRS(NULL),
+    pszCoverageName(NULL)
+{}
 
 /************************************************************************/
 /*                         ~OGRAVCDataSource()                          */
@@ -73,6 +71,6 @@ const char *OGRAVCDataSource::GetCoverageName()
 {
     if( pszCoverageName == NULL )
         return "";
-    else
-        return pszCoverageName;
+
+    return pszCoverageName;
 }
diff --git a/ogr/ogrsf_frmts/avc/ogravce00datasource.cpp b/ogr/ogrsf_frmts/avc/ogravce00datasource.cpp
index b759c5a..ac85bd3 100644
--- a/ogr/ogrsf_frmts/avc/ogravce00datasource.cpp
+++ b/ogr/ogrsf_frmts/avc/ogravce00datasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogravce00datasource.cpp 28039 2014-11-30 18:24:59Z rouault $
+ * $Id: ogravce00datasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OGR
  * Purpose:  Implements OGRAVCE00DataSource class.
@@ -33,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogravce00datasource.cpp 28039 2014-11-30 18:24:59Z rouault $");
+CPL_CVSID("$Id: ogravce00datasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                        OGRAVCE00DataSource()                         */
@@ -61,7 +61,7 @@ OGRAVCE00DataSource::~OGRAVCE00DataSource()
 
     for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
-    
+
     CPLFree( papoLayers );
 }
 
@@ -76,7 +76,7 @@ int OGRAVCE00DataSource::Open( const char * pszNewName, int bTestOpen )
 /*      Open the source file.  Suppress error reporting if we are in    */
 /*      TestOpen mode.                                                  */
 /* -------------------------------------------------------------------- */
-    int bCompressed = FALSE;
+    bool bCompressed = false;
 
     if( bTestOpen )
         CPLPushErrorHandler( CPLQuietErrorHandler );
@@ -84,9 +84,9 @@ int OGRAVCE00DataSource::Open( const char * pszNewName, int bTestOpen )
     psE00 = AVCE00ReadOpenE00(pszNewName);
 
     if( CPLGetLastErrorNo() == CPLE_OpenFailed
-        && strstr(CPLGetLastErrorMsg(),"compressed E00") != NULL ) 
+        && strstr(CPLGetLastErrorMsg(), "compressed E00") != NULL )
     {
-        bCompressed = TRUE;
+        bCompressed = true;
     }
 
     if( bTestOpen )
@@ -97,9 +97,9 @@ int OGRAVCE00DataSource::Open( const char * pszNewName, int bTestOpen )
 
     if( psE00 == NULL )
     {
-        if( bCompressed ) 
+        if( bCompressed )
         {
-            CPLError(CE_Failure, CPLE_OpenFailed, 
+            CPLError(CE_Failure, CPLE_OpenFailed,
                      "This looks like a compressed E00 file and cannot be "
                      "processed directly. You may need to uncompress it "
                      "first using the E00compr library or the e00conv "
@@ -115,13 +115,11 @@ int OGRAVCE00DataSource::Open( const char * pszNewName, int bTestOpen )
 /* -------------------------------------------------------------------- */
 /*      Create layers for the "interesting" sections of the coverage.   */
 /* -------------------------------------------------------------------- */
-    int iSection;
-
-    papoLayers = (OGRAVCE00Layer **)
-        CPLCalloc( sizeof(OGRAVCE00Layer *), psE00->numSections );
+    papoLayers = static_cast<OGRAVCE00Layer **>(
+        CPLCalloc( sizeof(OGRAVCE00Layer *), psE00->numSections ) );
     nLayers = 0;
 
-    for( iSection = 0; iSection < psE00->numSections; iSection++ )
+    for( int iSection = 0; iSection < psE00->numSections; iSection++ )
     {
         AVCE00Section *psSec = psE00->pasSections + iSection;
 
@@ -147,22 +145,20 @@ int OGRAVCE00DataSource::Open( const char * pszNewName, int bTestOpen )
           {
 #if 0
               poSRS = new OGRSpatialReference();
-              char  **papszPRJ;
-              AVCE00File *hFile;
-              
-              hFile = AVCE00ReadOpen(psE00->pszCoverPath, 
-                                     psSec->pszFilename, 
-                                     psE00->eCoverType, 
-                                     psSec->eType,
-                                     psE00->psDBCSInfo);
+              AVCE00File *hFile
+                  = AVCE00ReadOpen( psE00->pszCoverPath,
+                                    psSec->pszFilename,
+                                    psE00->eCoverType,
+                                    psSec->eType,
+                                    psE00->psDBCSInfo);
               if( hFile && poSRS == NULL )
               {
-                  papszPRJ = AVCE00ReadNextPrj( hFile );
+                  char **papszPRJ = AVCE00ReadNextPrj( hFile );
 
                   poSRS = new OGRSpatialReference();
                   if( poSRS->importFromESRI( papszPRJ ) != OGRERR_NONE )
                   {
-                      CPLError( CE_Warning, CPLE_AppDefined, 
+                      CPLError( CE_Warning, CPLE_AppDefined,
                                 "Failed to parse PRJ section, ignoring." );
                       delete poSRS;
                       poSRS = NULL;
@@ -177,14 +173,14 @@ int OGRAVCE00DataSource::Open( const char * pszNewName, int bTestOpen )
             ;
         }
     }
-    
+
     return nLayers > 0;
 }
 
 int OGRAVCE00DataSource::CheckAddTable( AVCE00Section *psTblSection )
 {
-    int i, nCount = 0;
-    for (i = 0; i < nLayers; ++i)
+    int nCount = 0;
+    for (int i = 0; i < nLayers; ++i)
     {
         if (papoLayers[i]->CheckSetupTable(psTblSection))
             ++nCount;
@@ -196,7 +192,7 @@ int OGRAVCE00DataSource::CheckAddTable( AVCE00Section *psTblSection )
 /*                           TestCapability()                           */
 /************************************************************************/
 
-int OGRAVCE00DataSource::TestCapability( CPL_UNUSED const char * pszCap )
+int OGRAVCE00DataSource::TestCapability( const char * /* pszCap */ )
 {
     return FALSE;
 }
@@ -210,8 +206,8 @@ OGRLayer *OGRAVCE00DataSource::GetLayer( int iLayer )
 {
     if( iLayer < 0 || iLayer >= nLayers )
         return NULL;
-    else
-        return papoLayers[iLayer];
+
+    return papoLayers[iLayer];
 }
 
 /************************************************************************/
@@ -219,31 +215,31 @@ OGRLayer *OGRAVCE00DataSource::GetLayer( int iLayer )
 /************************************************************************/
 OGRSpatialReference *OGRAVCE00DataSource::GetSpatialRef()
 {
-    if (NULL == poSRS && psE00 != NULL)
-    /* if (psE00 != NULL) */
-    {
-        int iSection;
-        AVCE00Section *psSec;
-        char **pszPRJ;
+    if (poSRS != NULL)
+        return poSRS;
+    if (psE00 == NULL)
+        return NULL;
 
-        for( iSection = 0; iSection < psE00->numSections; iSection++ )
+
+    for( int iSection = 0; iSection < psE00->numSections; iSection++ )
+    {
+        AVCE00Section *psSec = psE00->pasSections + iSection;
+        if (psSec->eType == AVCFilePRJ)
         {
-            psSec = psE00->pasSections + iSection;
-            if (psSec->eType == AVCFilePRJ)
+            AVCE00ReadGotoSectionE00(psE00, psSec, 0);
+            char **pszPRJ
+                = static_cast<char **>( AVCE00ReadNextObjectE00(psE00) );
+            poSRS = new OGRSpatialReference();
+            if( poSRS->importFromESRI( pszPRJ ) != OGRERR_NONE )
             {
-		        AVCE00ReadGotoSectionE00(psE00, psSec, 0);
-	            pszPRJ = (char **)AVCE00ReadNextObjectE00(psE00);
-                poSRS = new OGRSpatialReference();
-                if( poSRS->importFromESRI( pszPRJ ) != OGRERR_NONE )
-                {
-                    CPLError( CE_Warning, CPLE_AppDefined, 
-                              "Failed to parse PRJ section, ignoring." );
-                    delete poSRS;
-                    poSRS = NULL;
-                }
-                break;
+                CPLError( CE_Warning, CPLE_AppDefined,
+                          "Failed to parse PRJ section, ignoring." );
+                delete poSRS;
+                poSRS = NULL;
             }
+            break;
         }
     }
+
     return poSRS;
 }
diff --git a/ogr/ogrsf_frmts/avc/ogravce00driver.cpp b/ogr/ogrsf_frmts/avc/ogravce00driver.cpp
index d5d8659..9adccf9 100644
--- a/ogr/ogrsf_frmts/avc/ogravce00driver.cpp
+++ b/ogr/ogrsf_frmts/avc/ogravce00driver.cpp
@@ -38,8 +38,6 @@ CPL_CVSID("$Id: ogravcbindriver.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
 static GDALDataset *OGRAVCE00DriverOpen( GDALOpenInfo* poOpenInfo )
 
 {
-    OGRAVCE00DataSource *poDSE00;
-
     if( poOpenInfo->eAccess == GA_Update )
         return NULL;
     if( !poOpenInfo->bStatOK )
@@ -47,7 +45,7 @@ static GDALDataset *OGRAVCE00DriverOpen( GDALOpenInfo* poOpenInfo )
     if( !EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "E00") )
         return NULL;
 
-    poDSE00 = new OGRAVCE00DataSource();
+    OGRAVCE00DataSource *poDSE00 = new OGRAVCE00DataSource();
 
     if( poDSE00->Open( poOpenInfo->pszFilename, TRUE )
         && poDSE00->GetLayerCount() > 0 )
@@ -66,22 +64,19 @@ static GDALDataset *OGRAVCE00DriverOpen( GDALOpenInfo* poOpenInfo )
 void RegisterOGRAVCE00()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "AVCE00" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "AVCE00" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver  *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "AVCE00" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Arc/Info E00 (ASCII) Coverage" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "e00" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_avce00.html" );
+    poDriver->SetDescription( "AVCE00" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Arc/Info E00 (ASCII) Coverage" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "e00" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_avce00.html" );
 
-        poDriver->pfnOpen = OGRAVCE00DriverOpen;
+    poDriver->pfnOpen = OGRAVCE00DriverOpen;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/avc/ogravce00layer.cpp b/ogr/ogrsf_frmts/avc/ogravce00layer.cpp
index 6056e09..b9f0296 100644
--- a/ogr/ogrsf_frmts/avc/ogravce00layer.cpp
+++ b/ogr/ogrsf_frmts/avc/ogravce00layer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogravce00layer.cpp 28382 2015-01-30 15:29:41Z rouault $
+ * $Id: ogravce00layer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OGR
  * Purpose:  Implements OGRAVCE00Layer class.
@@ -34,7 +34,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogravce00layer.cpp 28382 2015-01-30 15:29:41Z rouault $");
+CPL_CVSID("$Id: ogravce00layer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                           OGRAVCE00Layer()                           */
@@ -49,16 +49,16 @@ OGRAVCE00Layer::OGRAVCE00Layer( OGRAVCDataSource *poDSIn,
           nFeatureCount(-1),
           bNeedReset(0),
           nNextFID(1),
-		  psTableSection(NULL),
+          psTableSection(NULL),
           psTableRead(NULL),
           pszTableFilename(NULL),
           nTablePos(0),
-		  nTableBaseField(0),
+          nTableBaseField(0),
           nTableAttrIndex(-1)
 {
     SetupFeatureDefinition( psSection->pszName );
     /* psRead = AVCE00ReadOpenE00(psSection->pszFilename); */
-    
+
 #if 0
     szTableName[0] = '\0';
     if( psSection->eType == AVCFilePAL )
@@ -156,7 +156,7 @@ OGRFeature *OGRAVCE00Layer::GetFeature( GIntBig nFID )
 /*      Read the raw feature - the -3 fid is a special flag             */
 /*      indicating serial access.                                       */
 /* -------------------------------------------------------------------- */
-    void *pFeature;
+    void *pFeature = NULL;
 
     if( nFID == -3 )
     {
@@ -185,16 +185,14 @@ OGRFeature *OGRAVCE00Layer::GetFeature( GIntBig nFID )
         }
         while (NULL != pFeature && nNextFID <= nFID);
     }
-        
+
     if( pFeature == NULL )
         return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Translate the feature.                                          */
 /* -------------------------------------------------------------------- */
-    OGRFeature *poFeature;
-
-    poFeature = TranslateFeature( pFeature );
+    OGRFeature *poFeature = TranslateFeature( pFeature );
     if( poFeature == NULL )
         return NULL;
 
@@ -214,10 +212,10 @@ OGRFeature *OGRAVCE00Layer::GetFeature( GIntBig nFID )
 /*      If this is a polygon layer, try to assemble the arcs to form    */
 /*      the whole polygon geometry.                                     */
 /* -------------------------------------------------------------------- */
-    if( psSection->eType == AVCFilePAL 
+    if( psSection->eType == AVCFilePAL
         || psSection->eType == AVCFileRPL )
     {
-        FormPolygonGeometry( poFeature, (AVCPal *) pFeature );
+        FormPolygonGeometry( poFeature, static_cast<AVCPal *>( pFeature ) );
     }
 
 /* -------------------------------------------------------------------- */
@@ -241,14 +239,14 @@ OGRFeature *OGRAVCE00Layer::GetNextFeature()
     OGRFeature *poFeature = GetFeature( -3 );
 
     // Skip universe polygon.
-    if( poFeature != NULL && poFeature->GetFID() == 1 
+    if( poFeature != NULL && poFeature->GetFID() == 1
         && psSection->eType == AVCFilePAL )
     {
         OGRFeature::DestroyFeature( poFeature );
         poFeature = GetFeature( -3 );
     }
 
-    while( poFeature != NULL 
+    while( poFeature != NULL
            && ((m_poAttrQuery != NULL
                 && !m_poAttrQuery->Evaluate( poFeature ) )
                || !FilterGeometry( poFeature->GetGeometryRef() ) ) )
@@ -273,8 +271,8 @@ int OGRAVCE00Layer::TestCapability( const char * pszCap )
 {
     if( eSectionType == AVCFileARC && EQUAL(pszCap,OLCRandomRead) )
         return TRUE;
-    else 
-        return OGRAVCLayer::TestCapability( pszCap );
+
+    return OGRAVCLayer::TestCapability( pszCap );
 }
 #endif
 
@@ -285,7 +283,7 @@ int OGRAVCE00Layer::TestCapability( const char * pszCap )
 /*      them into the appropriate OGR geometry on the target feature.   */
 /************************************************************************/
 
-int OGRAVCE00Layer::FormPolygonGeometry( OGRFeature *poFeature, 
+int OGRAVCE00Layer::FormPolygonGeometry( OGRFeature *poFeature,
                                          AVCPal *psPAL )
 {
 /* -------------------------------------------------------------------- */
@@ -294,11 +292,10 @@ int OGRAVCE00Layer::FormPolygonGeometry( OGRFeature *poFeature,
 /* -------------------------------------------------------------------- */
     if( poArcLayer == NULL )
     {
-        int i;
-
-        for( i = 0; i < poDS->GetLayerCount(); i++ )
+        for( int i = 0; i < poDS->GetLayerCount(); i++ )
         {
-            OGRAVCE00Layer *poLayer = (OGRAVCE00Layer *) poDS->GetLayer(i);
+            OGRAVCE00Layer *poLayer
+                = static_cast<OGRAVCE00Layer *>( poDS->GetLayer(i) );
 
             if( poLayer->eSectionType == AVCFileARC )
                 poArcLayer = poLayer;
@@ -313,12 +310,9 @@ int OGRAVCE00Layer::FormPolygonGeometry( OGRFeature *poFeature,
 /*  copy of them since the one returned by AVC is temporary.            */
 /* -------------------------------------------------------------------- */
     OGRGeometryCollection oArcs;
-    int iArc;
 
-    for( iArc = 0; iArc < psPAL->numArcs; iArc++ )
+    for( int iArc = 0; iArc < psPAL->numArcs; iArc++ )
     {
-        OGRFeature *poArc;
-
         if( psPAL->pasArcs[iArc].nArcId == 0 )
             continue;
 
@@ -326,11 +320,12 @@ int OGRAVCE00Layer::FormPolygonGeometry( OGRFeature *poFeature,
         // arc is a "bridge" arc and can be discarded.  If we don't discard
         // it, then we should double it as bridge arcs seem to only appear
         // once.  But by discarding it we ensure a multi-ring polygon will be
-        // properly formed. 
+        // properly formed.
         if( psPAL->pasArcs[iArc].nAdjPoly == psPAL->nPolyId )
             continue;
 
-        poArc = poArcLayer->GetFeature( ABS(psPAL->pasArcs[iArc].nArcId) );
+        OGRFeature *poArc
+            = poArcLayer->GetFeature( ABS(psPAL->pasArcs[iArc].nArcId) );
 
         if( poArc == NULL )
             return FALSE;
@@ -342,12 +337,10 @@ int OGRAVCE00Layer::FormPolygonGeometry( OGRFeature *poFeature,
         OGRFeature::DestroyFeature( poArc );
     }
 
-    OGRErr  eErr;
-    OGRPolygon *poPolygon;
-
-    poPolygon = (OGRPolygon *) 
-        OGRBuildPolygonFromEdges( (OGRGeometryH) &oArcs, TRUE, FALSE,  
-                                  0.0, &eErr );
+    OGRErr eErr;
+    OGRPolygon *poPolygon = reinterpret_cast<OGRPolygon *>(
+        OGRBuildPolygonFromEdges( reinterpret_cast<OGRGeometryH>( &oArcs ),
+                                  TRUE, FALSE, 0.0, &eErr ) );
     if( poPolygon != NULL )
         poFeature->SetGeometryDirectly( poPolygon );
 
@@ -389,14 +382,14 @@ int OGRAVCE00Layer::CheckSetupTable(AVCE00Section *psTblSectionIn)
 /* -------------------------------------------------------------------- */
     if( pszTableType == NULL )
         return FALSE;
-    
-    int iCheckOff;
-    for( iCheckOff = 0; 
-         psTblSectionIn->pszName[iCheckOff] != '\0'; 
+
+    int iCheckOff = 0;
+    for( ;
+         psTblSectionIn->pszName[iCheckOff] != '\0';
          iCheckOff++ )
     {
-        if( EQUALN(psTblSectionIn->pszName + iCheckOff, 
-                   pszTableType, strlen(pszTableType) ) )
+        if( EQUALN( psTblSectionIn->pszName + iCheckOff,
+                    pszTableType, strlen(pszTableType) ) )
             break;
     }
 
@@ -419,22 +412,23 @@ int OGRAVCE00Layer::CheckSetupTable(AVCE00Section *psTblSectionIn)
         psTableRead = NULL;
         return FALSE;
     }
-    
+
     AVCE00ReadNextObjectE00(psTableRead);
     bNeedReset = 1;
 
     pszTableFilename = CPLStrdup(psTblSectionIn->pszFilename);
     nTableBaseField = poFeatureDefn->GetFieldCount();
 
-	if (eSectionType == AVCFileLAB)
-	{
-        AVCE00ReadE00Ptr psInfo = ((OGRAVCE00DataSource *) poDS)->GetInfo();
+    if (eSectionType == AVCFileLAB)
+    {
+        AVCE00ReadE00Ptr psInfo
+            = static_cast<OGRAVCE00DataSource *>( poDS )->GetInfo();
         for( int iSection = 0; iSection < psInfo->numSections; iSection++ )
         {
             if( psInfo->pasSections[iSection].eType == AVCFilePAL )
                 nTableAttrIndex = poFeatureDefn->GetFieldIndex( "PolyId" );
         }
-	}
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Setup attributes.                                               */
@@ -468,8 +462,8 @@ int OGRAVCE00Layer::AppendTableFields( OGRFeature *poFeature )
         if (psTableRead == NULL)
             return FALSE;
 
-        /* advance to the specified line number */
-    	if (AVCE00ReadGotoSectionE00(psTableRead, psTableSection, 0) != 0)
+        /* Advance to the specified line number */
+        if (AVCE00ReadGotoSectionE00(psTableRead, psTableSection, 0) != 0)
         {
             AVCE00ReadCloseE00(psTableRead);
             psTableRead = NULL;
@@ -488,20 +482,20 @@ int OGRAVCE00Layer::AppendTableFields( OGRFeature *poFeature )
 /*      PolyId field.                                                   */
 /* -------------------------------------------------------------------- */
     int nRecordId;
-    void *hRecord;
 
     if( nTableAttrIndex == -1 )
-        nRecordId = (int) poFeature->GetFID();
+        nRecordId = static_cast<int>( poFeature->GetFID() );
     else
         nRecordId = poFeature->GetFieldAsInteger( nTableAttrIndex );
 
     if (nRecordId <= nTablePos)
     {
-    	if (AVCE00ReadGotoSectionE00(psTableRead, psTableSection, 0) != 0)
-			return FALSE;
+        if( AVCE00ReadGotoSectionE00(psTableRead, psTableSection, 0) != 0 )
+            return FALSE;
         nTablePos = 0;
     }
 
+    void *hRecord = NULL;
     do
     {
         hRecord = AVCE00ReadNextObjectE00(psTableRead);
@@ -512,13 +506,12 @@ int OGRAVCE00Layer::AppendTableFields( OGRFeature *poFeature )
     if( hRecord == NULL )
         return FALSE;
 
-
 /* -------------------------------------------------------------------- */
 /*      Translate it.                                                   */
 /* -------------------------------------------------------------------- */
-    return TranslateTableFields( poFeature, nTableBaseField, 
-                                 psTableRead->hParseInfo->hdr.psTableDef, 
-                                 (AVCField *) hRecord );
+    return TranslateTableFields( poFeature, nTableBaseField,
+                                 psTableRead->hParseInfo->hdr.psTableDef,
+                                 static_cast<AVCField *>( hRecord ) );
 }
 
 
diff --git a/ogr/ogrsf_frmts/avc/ogravclayer.cpp b/ogr/ogrsf_frmts/avc/ogravclayer.cpp
index 9f79981..b8fa3dd 100644
--- a/ogr/ogrsf_frmts/avc/ogravclayer.cpp
+++ b/ogr/ogrsf_frmts/avc/ogravclayer.cpp
@@ -1,10 +1,10 @@
 /******************************************************************************
- * $Id: ogravclayer.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogravclayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OGR
  * Purpose:  Implements OGRAVCLayer class.  This is the base class for E00
  *           and binary coverage layer implementations.  It provides some base
- *           layer operations, and methods for transforming between OGR 
+ *           layer operations, and methods for transforming between OGR
  *           features, and the in memory structures of the AVC library.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -34,21 +34,18 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogravclayer.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogravclayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                           OGRAVCLayer()                           */
 /************************************************************************/
 
-OGRAVCLayer::OGRAVCLayer( AVCFileType eSectionTypeIn, 
-                          OGRAVCDataSource *poDSIn )
-
-{
-    eSectionType = eSectionTypeIn;
-    
-    poFeatureDefn = NULL;
-    poDS = poDSIn;
-}
+OGRAVCLayer::OGRAVCLayer( AVCFileType eSectionTypeIn,
+                          OGRAVCDataSource *poDSIn ) :
+    poFeatureDefn(NULL),
+    poDS(poDSIn),
+    eSectionType(eSectionTypeIn)
+{}
 
 /************************************************************************/
 /*                          ~OGRAVCLayer()                           */
@@ -60,7 +57,7 @@ OGRAVCLayer::~OGRAVCLayer()
     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     {
         CPLDebug( "AVC", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
+                  static_cast<int>( m_nFeaturesRead ),
                   poFeatureDefn->GetName() );
     }
 
@@ -72,7 +69,7 @@ OGRAVCLayer::~OGRAVCLayer()
 /*                           TestCapability()                           */
 /************************************************************************/
 
-int OGRAVCLayer::TestCapability( CPL_UNUSED const char * pszCap )
+int OGRAVCLayer::TestCapability( const char * /* pszCap */ )
 {
     return FALSE;
 }
@@ -94,6 +91,7 @@ OGRSpatialReference *OGRAVCLayer::GetSpatialRef()
 int OGRAVCLayer::SetupFeatureDefinition( const char *pszName )
 
 {
+    bool bRet = false;
     switch( eSectionType )
     {
       case AVCFileARC:
@@ -102,19 +100,21 @@ int OGRAVCLayer::SetupFeatureDefinition( const char *pszName )
             poFeatureDefn->Reference();
             poFeatureDefn->SetGeomType( wkbLineString );
 
-            OGRFieldDefn	oUserId( "UserId", OFTInteger );
-            OGRFieldDefn	oFNode( "FNODE_", OFTInteger );
-            OGRFieldDefn	oTNode( "TNODE_", OFTInteger );
-            OGRFieldDefn	oLPoly( "LPOLY_", OFTInteger );
-            OGRFieldDefn	oRPoly( "RPOLY_", OFTInteger );
+            OGRFieldDefn oUserId( "UserId", OFTInteger );
+            OGRFieldDefn oFNode( "FNODE_", OFTInteger );
+            OGRFieldDefn oTNode( "TNODE_", OFTInteger );
+            OGRFieldDefn oLPoly( "LPOLY_", OFTInteger );
+            OGRFieldDefn oRPoly( "RPOLY_", OFTInteger );
 
             poFeatureDefn->AddFieldDefn( &oUserId );
             poFeatureDefn->AddFieldDefn( &oFNode );
             poFeatureDefn->AddFieldDefn( &oTNode );
             poFeatureDefn->AddFieldDefn( &oLPoly );
             poFeatureDefn->AddFieldDefn( &oRPoly );
+
+            bRet = true;
+            break;
         }
-        return TRUE;
 
       case AVCFilePAL:
       case AVCFileRPL:
@@ -123,10 +123,12 @@ int OGRAVCLayer::SetupFeatureDefinition( const char *pszName )
             poFeatureDefn->Reference();
             poFeatureDefn->SetGeomType( wkbPolygon );
 
-            OGRFieldDefn	oArcIds( "ArcIds", OFTIntegerList );
+            OGRFieldDefn oArcIds( "ArcIds", OFTIntegerList );
             poFeatureDefn->AddFieldDefn( &oArcIds );
+
+            bRet = true;
+            break;
         }
-        return TRUE;
 
       case AVCFileCNT:
         {
@@ -134,10 +136,12 @@ int OGRAVCLayer::SetupFeatureDefinition( const char *pszName )
             poFeatureDefn->Reference();
             poFeatureDefn->SetGeomType( wkbPoint );
 
-            OGRFieldDefn	oLabelIds( "LabelIds", OFTIntegerList );
+            OGRFieldDefn oLabelIds( "LabelIds", OFTIntegerList );
             poFeatureDefn->AddFieldDefn( &oLabelIds );
+
+            bRet = true;
+            break;
         }
-        return TRUE;
 
       case AVCFileLAB:
         {
@@ -145,13 +149,15 @@ int OGRAVCLayer::SetupFeatureDefinition( const char *pszName )
             poFeatureDefn->Reference();
             poFeatureDefn->SetGeomType( wkbPoint );
 
-            OGRFieldDefn	oValueId( "ValueId", OFTInteger );
+            OGRFieldDefn oValueId( "ValueId", OFTInteger );
             poFeatureDefn->AddFieldDefn( &oValueId );
 
-            OGRFieldDefn	oPolyId( "PolyId", OFTInteger );
+            OGRFieldDefn oPolyId( "PolyId", OFTInteger );
             poFeatureDefn->AddFieldDefn( &oPolyId );
+
+            bRet = true;
+            break;
         }
-        return TRUE;
 
       case AVCFileTXT:
       case AVCFileTX6:
@@ -160,32 +166,35 @@ int OGRAVCLayer::SetupFeatureDefinition( const char *pszName )
             poFeatureDefn->Reference();
             poFeatureDefn->SetGeomType( wkbPoint );
 
-            OGRFieldDefn	oUserId( "UserId", OFTInteger );
+            OGRFieldDefn oUserId( "UserId", OFTInteger );
             poFeatureDefn->AddFieldDefn( &oUserId );
 
-            OGRFieldDefn	oText( "Text", OFTString );
+            OGRFieldDefn oText( "Text", OFTString );
             poFeatureDefn->AddFieldDefn( &oText );
 
-            OGRFieldDefn	oHeight( "Height", OFTReal );
+            OGRFieldDefn oHeight( "Height", OFTReal );
             poFeatureDefn->AddFieldDefn( &oHeight );
 
-            OGRFieldDefn	oLevel( "Level", OFTInteger );
+            OGRFieldDefn oLevel( "Level", OFTInteger );
             poFeatureDefn->AddFieldDefn( &oLevel );
+
+            bRet = true;
+            break;
         }
-        return TRUE;
 
       default:
         poFeatureDefn = NULL;
-        return FALSE;
+        break;
     }
 
     SetDescription( pszName );
+    return bRet;
 }
 
 /************************************************************************/
 /*                          TranslateFeature()                          */
 /*                                                                      */
-/*      Translate the AVC structure for a feature to the the            */
+/*      Translate the AVC structure for a feature to the                */
 /*      corresponding OGR definition.  It is assumed that the passed    */
 /*      in feature is of a type matching the section type               */
 /*      established by SetupFeatureDefinition().                        */
@@ -203,7 +212,7 @@ OGRFeature *OGRAVCLayer::TranslateFeature( void *pAVCFeature )
 /* ==================================================================== */
       case AVCFileARC:
       {
-          AVCArc *psArc = (AVCArc *) pAVCFeature;
+          AVCArc *psArc = static_cast<AVCArc *>( pAVCFeature );
 
 /* -------------------------------------------------------------------- */
 /*      Create feature.                                                 */
@@ -218,8 +227,8 @@ OGRFeature *OGRAVCLayer::TranslateFeature( void *pAVCFeature )
 
           poLine->setNumPoints( psArc->numVertices );
           for( int iVert = 0; iVert < psArc->numVertices; iVert++ )
-              poLine->setPoint( iVert, 
-                                psArc->pasVertices[iVert].x, 
+              poLine->setPoint( iVert,
+                                psArc->pasVertices[iVert].x,
                                 psArc->pasVertices[iVert].y );
 
           poOGRFeature->SetGeometryDirectly( poLine );
@@ -242,7 +251,7 @@ OGRFeature *OGRAVCLayer::TranslateFeature( void *pAVCFeature )
       case AVCFilePAL:
       case AVCFileRPL:
       {
-          AVCPal *psPAL = (AVCPal *) pAVCFeature;
+          AVCPal *psPAL = static_cast<AVCPal *>( pAVCFeature );
 
 /* -------------------------------------------------------------------- */
 /*      Create feature.                                                 */
@@ -253,11 +262,10 @@ OGRFeature *OGRAVCLayer::TranslateFeature( void *pAVCFeature )
 /* -------------------------------------------------------------------- */
 /*      Apply attributes.                                               */
 /* -------------------------------------------------------------------- */
-          // Setup ArcId list. 
-          int	       *panArcs, i;
-
-          panArcs = (int *) CPLMalloc(sizeof(int) * psPAL->numArcs );
-          for( i = 0; i < psPAL->numArcs; i++ )
+          // Setup ArcId list.
+          int *panArcs
+              = static_cast<int *>( CPLMalloc(sizeof(int) * psPAL->numArcs ) );
+          for( int i = 0; i < psPAL->numArcs; i++ )
               panArcs[i] = psPAL->pasArcs[i].nArcId;
           poOGRFeature->SetField( 0, psPAL->numArcs, panArcs );
           CPLFree( panArcs );
@@ -281,7 +289,7 @@ OGRFeature *OGRAVCLayer::TranslateFeature( void *pAVCFeature )
 /* -------------------------------------------------------------------- */
 /*      Apply Geometry                                                  */
 /* -------------------------------------------------------------------- */
-          poOGRFeature->SetGeometryDirectly( 
+          poOGRFeature->SetGeometryDirectly(
               new OGRPoint( psCNT->sCoord.x, psCNT->sCoord.y ) );
 
 /* -------------------------------------------------------------------- */
@@ -297,7 +305,7 @@ OGRFeature *OGRAVCLayer::TranslateFeature( void *pAVCFeature )
 /* ==================================================================== */
       case AVCFileLAB:
       {
-          AVCLab *psLAB = (AVCLab *) pAVCFeature;
+          AVCLab *psLAB = static_cast<AVCLab *>( pAVCFeature );
 
 /* -------------------------------------------------------------------- */
 /*      Create feature.                                                 */
@@ -308,7 +316,7 @@ OGRFeature *OGRAVCLayer::TranslateFeature( void *pAVCFeature )
 /* -------------------------------------------------------------------- */
 /*      Apply Geometry                                                  */
 /* -------------------------------------------------------------------- */
-          poOGRFeature->SetGeometryDirectly( 
+          poOGRFeature->SetGeometryDirectly(
               new OGRPoint( psLAB->sCoord1.x, psLAB->sCoord1.y ) );
 
 /* -------------------------------------------------------------------- */
@@ -321,12 +329,12 @@ OGRFeature *OGRAVCLayer::TranslateFeature( void *pAVCFeature )
       }
 
 /* ==================================================================== */
-/*      TXT/TX6 (Text)							*/
+/*      TXT/TX6 (Text)                                                  */
 /* ==================================================================== */
       case AVCFileTXT:
       case AVCFileTX6:
       {
-          AVCTxt *psTXT = (AVCTxt *) pAVCFeature;
+          AVCTxt *psTXT = static_cast<AVCTxt *>( pAVCFeature );
 
 /* -------------------------------------------------------------------- */
 /*      Create feature.                                                 */
@@ -338,15 +346,16 @@ OGRFeature *OGRAVCLayer::TranslateFeature( void *pAVCFeature )
 /*      Apply Geometry                                                  */
 /* -------------------------------------------------------------------- */
           if( psTXT->numVerticesLine > 0 )
-              poOGRFeature->SetGeometryDirectly( 
-                  new OGRPoint( psTXT->pasVertices[0].x, 
+              poOGRFeature->SetGeometryDirectly(
+                  new OGRPoint( psTXT->pasVertices[0].x,
                                 psTXT->pasVertices[0].y ) );
 
 /* -------------------------------------------------------------------- */
 /*      Apply attributes.                                               */
 /* -------------------------------------------------------------------- */
           poOGRFeature->SetField( 0, psTXT->nUserId );
-          poOGRFeature->SetField( 1, (const char *)psTXT->pszText );
+          poOGRFeature->SetField(
+              1, reinterpret_cast<char *>( psTXT->pszText ) );
           poOGRFeature->SetField( 2, psTXT->dHeight );
           poOGRFeature->SetField( 3, psTXT->nLevel );
 
@@ -377,7 +386,7 @@ int OGRAVCLayer::MatchesSpatialFilter( void *pFeature )
 /* ==================================================================== */
       case AVCFileARC:
       {
-          AVCArc *psArc = (AVCArc *) pFeature;
+          AVCArc *psArc = static_cast<AVCArc *>( pFeature );
 
           for( int iVert = 0; iVert < psArc->numVertices-1; iVert++ )
           {
@@ -425,8 +434,8 @@ int OGRAVCLayer::MatchesSpatialFilter( void *pFeature )
 /* ==================================================================== */
       case AVCFileCNT:
       {
-          AVCCnt *psCNT = (AVCCnt *) pFeature;
-          
+          AVCCnt *psCNT = static_cast<AVCCnt *>( pFeature );
+
           if( psCNT->sCoord.x < m_sFilterEnvelope.MinX
               || psCNT->sCoord.x > m_sFilterEnvelope.MaxX
               || psCNT->sCoord.y < m_sFilterEnvelope.MinY
@@ -453,12 +462,12 @@ int OGRAVCLayer::MatchesSpatialFilter( void *pFeature )
       }
 
 /* ==================================================================== */
-/*      TXT/TX6 (Text)							*/
+/*      TXT/TX6 (Text)                                                  */
 /* ==================================================================== */
       case AVCFileTXT:
       case AVCFileTX6:
       {
-          AVCTxt *psTXT = (AVCTxt *) pFeature;
+          AVCTxt *psTXT = static_cast<AVCTxt *>( pFeature );
 
           if( psTXT->numVerticesLine == 0 )
               return TRUE;
@@ -468,8 +477,8 @@ int OGRAVCLayer::MatchesSpatialFilter( void *pFeature )
               || psTXT->pasVertices[0].y < m_sFilterEnvelope.MinY
               || psTXT->pasVertices[0].y > m_sFilterEnvelope.MaxY )
               return FALSE;
-          else
-              return TRUE;
+
+          return TRUE;
       }
 
       default:
@@ -490,14 +499,14 @@ int OGRAVCLayer::AppendTableDefinition( AVCTableDef *psTableDef )
     for( int iField = 0; iField < psTableDef->numFields; iField++ )
     {
         AVCFieldInfo *psFInfo = psTableDef->pasFieldDef + iField;
-        char	szFieldName[128];
+        char szFieldName[128];
 
         /* Strip off white space */
         strcpy( szFieldName, psFInfo->szName );
         if( strstr(szFieldName," ") != NULL )
             *(strstr(szFieldName," ")) = '\0';
-        
-        OGRFieldDefn  oFDefn( szFieldName, OFTInteger );
+
+        OGRFieldDefn oFDefn( szFieldName, OFTInteger );
 
         if( psFInfo->nIndex < 0 )
             continue;
@@ -508,15 +517,15 @@ int OGRAVCLayer::AppendTableDefinition( AVCTableDef *psTableDef )
 
         oFDefn.SetWidth( psFInfo->nFmtWidth );
 
-        if( psFInfo->nType1 * 10 == AVC_FT_DATE 
+        if( psFInfo->nType1 * 10 == AVC_FT_DATE
             || psFInfo->nType1 * 10 == AVC_FT_CHAR )
             oFDefn.SetType( OFTString );
 
-        else if( psFInfo->nType1 * 10 == AVC_FT_FIXINT 
+        else if( psFInfo->nType1 * 10 == AVC_FT_FIXINT
                  || psFInfo->nType1 * 10 == AVC_FT_BININT )
             oFDefn.SetType( OFTInteger );
 
-        else if( psFInfo->nType1 * 10 == AVC_FT_FIXNUM 
+        else if( psFInfo->nType1 * 10 == AVC_FT_FIXNUM
                  || psFInfo->nType1 * 10 == AVC_FT_BINFLOAT )
         {
             oFDefn.SetType( OFTReal );
@@ -533,13 +542,13 @@ int OGRAVCLayer::AppendTableDefinition( AVCTableDef *psTableDef )
 /*                        TranslateTableFields()                        */
 /************************************************************************/
 
-int OGRAVCLayer::TranslateTableFields( OGRFeature *poFeature, 
-                                       int nFieldBase, 
+int OGRAVCLayer::TranslateTableFields( OGRFeature *poFeature,
+                                       int nFieldBase,
                                        AVCTableDef *psTableDef,
                                        AVCField *pasFields )
 
 {
-    int	iOutField = nFieldBase;
+    int iOutField = nFieldBase;
 
     for( int iField=0; iField < psTableDef->numFields; iField++ )
     {
@@ -548,7 +557,7 @@ int OGRAVCLayer::TranslateTableFields( OGRFeature *poFeature,
 
         if( psFInfo->nIndex < 0 )
             continue;
-        
+
         // Skip FNODE#, TNODE#, LPOLY# and RPOLY# from AAT table.
         if( eSectionType == AVCFileARC && iField < 4 )
             continue;
@@ -559,13 +568,15 @@ int OGRAVCLayer::TranslateTableFields( OGRFeature *poFeature,
             if (nType == AVC_FT_CHAR)
             {
                 /* Remove trailing spaces in char fields */
-                int nLen = strlen((const char*)pasFields[iField].pszStr);
+                size_t nLen = strlen( reinterpret_cast<char *>(
+                    pasFields[iField].pszStr) );
                 while (nLen > 0 && pasFields[iField].pszStr[nLen-1] == ' ')
                     nLen--;
                 pasFields[iField].pszStr[nLen] = '\0';
             }
-            poFeature->SetField( iOutField++, 
-                                 (const char *)pasFields[iField].pszStr );
+            poFeature->SetField(
+                iOutField++,
+                reinterpret_cast<char *>( pasFields[iField].pszStr ) );
         }
         else if (nType == AVC_FT_BININT && psFInfo->nSize == 4)
         {
diff --git a/ogr/ogrsf_frmts/bna/GNUmakefile b/ogr/ogrsf_frmts/bna/GNUmakefile
index 3861a40..c73f23e 100644
--- a/ogr/ogrsf_frmts/bna/GNUmakefile
+++ b/ogr/ogrsf_frmts/bna/GNUmakefile
@@ -1,5 +1,3 @@
-
-
 include ../../../GDALmake.opt
 
 OBJ	=	ogrbnadriver.o ogrbnadatasource.o ogrbnalayer.o ogrbnaparser.o
diff --git a/ogr/ogrsf_frmts/bna/drv_bna.html b/ogr/ogrsf_frmts/bna/drv_bna.html
index 20b33d7..b096a55 100644
--- a/ogr/ogrsf_frmts/bna/drv_bna.html
+++ b/ogr/ogrsf_frmts/bna/drv_bna.html
@@ -36,7 +36,7 @@ The BNA driver support reading of polygons with holes or lakes. It determines wh
 geometrical analysis (inclusion, non-intersection tests) and ignores completely the notion of polygon winding (whether the
 polygon edges are described clockwise or counter-clockwise). GDAL must be built with GEOS enabled to make geometry test work. Polygons are exposed as multipolygons in the OGR Simple Feature model.<p>
 
-Ellipses and circles are discretized as polygons with 360 points.<p> 
+Ellipses and circles are discretized as polygons with 360 points.<p>
 
 <h2>Creation Issues</h2>
 
@@ -48,7 +48,7 @@ The BNA writer supports the following creation options (dataset options):
 <ul>
 <li> <b>LINEFORMAT</b>:
 By default when creating new .BNA files they are created with the line
-termination conventions of the local platform (CR/LF on win32 or 
+termination conventions of the local platform (CR/LF on win32 or
 LF on all other systems).  This may be overridden through use of the
 LINEFORMAT layer creation option which may have a value of <b>CRLF</b>
 (DOS format) or <b>LF</b> (Unix format). <p>
diff --git a/ogr/ogrsf_frmts/bna/makefile.vc b/ogr/ogrsf_frmts/bna/makefile.vc
index c7ae1c8..dc63cfa 100644
--- a/ogr/ogrsf_frmts/bna/makefile.vc
+++ b/ogr/ogrsf_frmts/bna/makefile.vc
@@ -1,4 +1,3 @@
-
 OBJ	=	ogrbnadriver.obj ogrbnadatasource.obj ogrbnalayer.obj \
 		ogrbnaparser.obj
 
diff --git a/ogr/ogrsf_frmts/bna/ogr_bna.h b/ogr/ogrsf_frmts/bna/ogr_bna.h
index 0a778e1..bef50c0 100644
--- a/ogr/ogrsf_frmts/bna/ogr_bna.h
+++ b/ogr/ogrsf_frmts/bna/ogr_bna.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_bna.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogr_bna.h 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  BNA Translator
  * Purpose:  Definition of classes for OGR .bna driver.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_BNA_H_INCLUDED
-#define _OGR_BNA_H_INCLUDED
+#ifndef OGR_BNA_H_INCLUDED
+#define OGR_BNA_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 
@@ -49,7 +49,7 @@ typedef struct
 class OGRBNALayer : public OGRLayer
 {
     OGRFeatureDefn*    poFeatureDefn;
-    
+
     OGRBNADataSource*  poDS;
     int                bWriter;
 
@@ -58,7 +58,7 @@ class OGRBNALayer : public OGRLayer
     int                failed;
     int                curLine;
     int                nNextFID;
-    VSILFILE*              fpBNA;
+    VSILFILE*          fpBNA;
     int                nFeatures;
     int                partialIndexTable;
     OffsetAndLine*     offsetAndLineFeaturesTable;
@@ -69,7 +69,7 @@ class OGRBNALayer : public OGRLayer
     void               FastParseUntil ( int interestFID);
     void               WriteFeatureAttributes(VSILFILE* fp, OGRFeature *poFeature);
     void               WriteCoord(VSILFILE* fp, double dfX, double dfY);
-    
+
   public:
                         OGRBNALayer(const char *pszFilename,
                                     const char* layerName,
@@ -86,12 +86,12 @@ class OGRBNALayer : public OGRLayer
 
     void                ResetReading();
     OGRFeature *        GetNextFeature();
-    
+
     OGRErr              ICreateFeature( OGRFeature *poFeature );
     OGRErr              CreateField( OGRFieldDefn *poField, int bApproxOK );
 
     OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
-    
+
     OGRFeature *        GetFeature( GIntBig nFID );
 
     int                 TestCapability( const char * );
@@ -110,7 +110,7 @@ class OGRBNADataSource : public OGRDataSource
     int                 nLayers;
 
     int                 bUpdate;
-    
+
     /*  Export related */
     VSILFILE                *fpOutput; /* Virtual file API */
     int                 bUseCRLF;
@@ -120,7 +120,7 @@ class OGRBNADataSource : public OGRDataSource
     int                 nbPairPerLine;
     int                 coordinatePrecision;
     char*               pszCoordinateSeparator;
-    
+
   public:
                         OGRBNADataSource();
                         ~OGRBNADataSource();
@@ -136,15 +136,15 @@ class OGRBNADataSource : public OGRDataSource
 
     int                 Open( const char * pszFilename,
                               int bUpdate );
-    
-    int                 Create( const char *pszFilename, 
+
+    int                 Create( const char *pszFilename,
                               char **papszOptions );
-    
+
     const char*         GetName() { return pszName; }
 
     int                 GetLayerCount() { return nLayers; }
     OGRLayer*           GetLayer( int );
-    
+
     OGRLayer *          ICreateLayer( const char * pszLayerName,
                                     OGRSpatialReference *poSRS,
                                     OGRwkbGeometryType eType,
@@ -153,4 +153,4 @@ class OGRBNADataSource : public OGRDataSource
     int                 TestCapability( const char * );
 };
 
-#endif /* ndef _OGR_BNA_H_INCLUDED */
+#endif /* ndef OGR_BNA_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/bna/ogrbnadatasource.cpp b/ogr/ogrsf_frmts/bna/ogrbnadatasource.cpp
index 2d6130a..17975a3 100644
--- a/ogr/ogrsf_frmts/bna/ogrbnadatasource.cpp
+++ b/ogr/ogrsf_frmts/bna/ogrbnadatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrbnadatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogrbnadatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  BNA Translator
  * Purpose:  Implements OGRBNADataSource class
@@ -37,20 +37,20 @@
 /*                          OGRBNADataSource()                          */
 /************************************************************************/
 
-OGRBNADataSource::OGRBNADataSource()
-
-{
-    papoLayers = NULL;
-    nLayers = 0;
-    
-    fpOutput = NULL;
-
-    pszName = NULL;
-    
-    pszCoordinateSeparator = NULL;
-
-    bUpdate = FALSE;
-}
+OGRBNADataSource::OGRBNADataSource() :
+    pszName(NULL),
+    papoLayers(NULL),
+    nLayers(0),
+    bUpdate(FALSE),
+    fpOutput(NULL),
+    bUseCRLF(FALSE),
+    bMultiLine(FALSE),
+    nbOutID(0),
+    bEllipsesAsEllipses(FALSE),
+    nbPairPerLine(FALSE),
+    coordinatePrecision(0),
+    pszCoordinateSeparator(NULL)
+{ }
 
 /************************************************************************/
 /*                         ~OGRBNADataSource()                          */
@@ -67,7 +67,7 @@ OGRBNADataSource::~OGRBNADataSource()
     for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
     CPLFree( papoLayers );
-    
+
     CPLFree( pszCoordinateSeparator );
 
     CPLFree( pszName );
@@ -82,10 +82,8 @@ int OGRBNADataSource::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,ODsCCreateLayer) )
         return TRUE;
-    else if( EQUAL(pszCap,ODsCDeleteLayer) )
-        return FALSE;
-    else
-        return FALSE;
+
+    return FALSE;
 }
 
 /************************************************************************/
@@ -97,8 +95,8 @@ OGRLayer *OGRBNADataSource::GetLayer( int iLayer )
 {
     if( iLayer < 0 || iLayer >= nLayers )
         return NULL;
-    else
-        return papoLayers[iLayer];
+
+    return papoLayers[iLayer];
 }
 
 /************************************************************************/
@@ -106,9 +104,9 @@ OGRLayer *OGRBNADataSource::GetLayer( int iLayer )
 /************************************************************************/
 
 OGRLayer * OGRBNADataSource::ICreateLayer( const char * pszLayerName,
-                                           CPL_UNUSED OGRSpatialReference *poSRS,
+                                           OGRSpatialReference * /*poSRS */,
                                            OGRwkbGeometryType eType,
-                                           CPL_UNUSED char ** papszOptions )
+                                           char ** /* papszOptions */ )
 {
     BNAFeatureType bnaFeatureType;
 
@@ -120,28 +118,30 @@ OGRLayer * OGRBNADataSource::ICreateLayer( const char * pszLayerName,
         case wkbMultiPolygon25D:
             bnaFeatureType = BNA_POLYGON;
             break;
-        
+
         case wkbPoint:
         case wkbPoint25D:
             bnaFeatureType = BNA_POINT;
             break;
-            
+
         case wkbLineString:
         case wkbLineString25D:
             bnaFeatureType = BNA_POLYLINE;
             break;
-            
+
         default:
             CPLError( CE_Failure, CPLE_NotSupported,
                     "Geometry type of `%s' not supported in BNAs.\n",
                     OGRGeometryTypeToName(eType) );
             return NULL;
     }
-    
+
     nLayers++;
-    papoLayers = (OGRBNALayer **) CPLRealloc(papoLayers, nLayers * sizeof(OGRBNALayer*));
-    papoLayers[nLayers-1] = new OGRBNALayer( pszName, pszLayerName, bnaFeatureType, eType, TRUE, this );
-    
+    papoLayers = static_cast<OGRBNALayer **>(
+        CPLRealloc( papoLayers, nLayers * sizeof(OGRBNALayer*) ) );
+    papoLayers[nLayers-1] = new OGRBNALayer(
+        pszName, pszLayerName, bnaFeatureType, eType, TRUE, this );
+
     return papoLayers[nLayers-1];
 }
 
@@ -156,15 +156,17 @@ int OGRBNADataSource::Open( const char * pszFilename, int bUpdateIn)
 
     pszName = CPLStrdup( pszFilename );
     bUpdate = bUpdateIn;
-    
+
     VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
     if (fp)
     {
         BNARecord* record;
         int curLine = 0;
-        const char* layerRadixName[] = { "points", "polygons", "lines", "ellipses"};
-        OGRwkbGeometryType wkbGeomTypes[] = { wkbPoint, wkbMultiPolygon, wkbLineString, wkbPolygon };
-        int i;
+        static const char* const layerRadixName[]
+            = { "points", "polygons", "lines", "ellipses"};
+        static const OGRwkbGeometryType wkbGeomTypes[]
+            = { wkbPoint, wkbMultiPolygon, wkbLineString, wkbPolygon };
+
 #if defined(BNA_FAST_DS_OPEN)
         record = BNA_GetNextRecord(fp, &ok, &curLine, FALSE, BNA_READ_NONE);
         BNA_FreeRecord(record);
@@ -173,11 +175,14 @@ int OGRBNADataSource::Open( const char * pszFilename, int bUpdateIn)
         {
             nLayers = 4;
 
-            papoLayers = (OGRBNALayer **) CPLMalloc(nLayers * sizeof(OGRBNALayer*));
+            papoLayers = static_cast<OGRBNALayer **>(
+                CPLMalloc(nLayers * sizeof(OGRBNALayer*) ) );
             for(i=0;i<4;i++)
-                papoLayers[i] = new OGRBNALayer( pszFilename,
-                                                 layerRadixName[i],
-                                                 (BNAFeatureType)i, wkbGeomTypes[i], FALSE, this );
+                papoLayers[i] = new OGRBNALayer(
+                    pszFilename,
+                    layerRadixName[i],
+                    static_cast<BNAFeatureType>( i ),
+                    wkbGeomTypes[i], FALSE, this );
         }
 #else
         int nFeatures[4] = { 0, 0, 0, 0 };
@@ -187,7 +192,7 @@ int OGRBNADataSource::Open( const char * pszFilename, int bUpdateIn)
 
         while(1)
         {
-            int offset = (int) VSIFTellL(fp);
+            int offset = static_cast<int>( VSIFTellL(fp) );
             int line = curLine;
             record =  BNA_GetNextRecord(fp, &ok, &curLine, FALSE, BNA_READ_NONE);
             if (ok == FALSE)
@@ -212,8 +217,9 @@ int OGRBNADataSource::Open( const char * pszFilename, int bUpdateIn)
 
             nFeatures[record->featureType]++;
             offsetAndLineFeaturesTable[record->featureType] =
-                (OffsetAndLine*)CPLRealloc(offsetAndLineFeaturesTable[record->featureType],
-                                           nFeatures[record->featureType] * sizeof(OffsetAndLine));
+              static_cast<OffsetAndLine *>( CPLRealloc(
+                  offsetAndLineFeaturesTable[record->featureType],
+                  nFeatures[record->featureType] * sizeof(OffsetAndLine) ) );
             offsetAndLineFeaturesTable[record->featureType][nFeatures[record->featureType]-1].offset = offset;
             offsetAndLineFeaturesTable[record->featureType][nFeatures[record->featureType]-1].line = line;
 
@@ -221,9 +227,10 @@ int OGRBNADataSource::Open( const char * pszFilename, int bUpdateIn)
         }
 
         nLayers = (nFeatures[0] != 0) + (nFeatures[1] != 0) + (nFeatures[2] != 0) + (nFeatures[3] != 0);
-        papoLayers = (OGRBNALayer **) CPLMalloc(nLayers * sizeof(OGRBNALayer*));
+        papoLayers = static_cast<OGRBNALayer **>(
+            CPLMalloc(nLayers * sizeof(OGRBNALayer*)) );
         int iLayer = 0;
-        for(i=0;i<4;i++)
+        for( int i = 0; i < 4; i++ )
         {
             if (nFeatures[i])
             {
@@ -252,7 +259,7 @@ int OGRBNADataSource::Open( const char * pszFilename, int bUpdateIn)
 /*                               Create()                               */
 /************************************************************************/
 
-int OGRBNADataSource::Create( const char *pszFilename, 
+int OGRBNADataSource::Create( const char *pszFilename,
                               char **papszOptions )
 {
     if( fpOutput != NULL)
@@ -271,7 +278,7 @@ int OGRBNADataSource::Create( const char *pszFilename,
 
     if( VSIStatL( pszFilename, &sStatBuf ) == 0 )
         return FALSE;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create the output file.                                         */
 /* -------------------------------------------------------------------- */
@@ -280,12 +287,12 @@ int OGRBNADataSource::Create( const char *pszFilename,
     fpOutput = VSIFOpenL( pszFilename, "wb" );
     if( fpOutput == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Failed to create BNA file %s.", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to create BNA file %s.",
                   pszFilename );
         return FALSE;
     }
-    
+
     /* EOL token */
     const char *pszCRLFFormat = CSLFetchNameValue( papszOptions, "LINEFORMAT");
 
@@ -303,7 +310,7 @@ int OGRBNADataSource::Create( const char *pszFilename,
         bUseCRLF = FALSE;
     else
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "LINEFORMAT=%s not understood, use one of CRLF or LF.",
                   pszCRLFFormat );
 #ifdef WIN32
@@ -315,7 +322,7 @@ int OGRBNADataSource::Create( const char *pszFilename,
 
     /* Multi line or single line format ? */
     bMultiLine = CSLFetchBoolean( papszOptions, "MULTILINE", TRUE);
-    
+
     /* Number of identifiers per record */
     const char* pszNbOutID = CSLFetchNameValue ( papszOptions, "NB_IDS");
     if (pszNbOutID == NULL)
@@ -331,23 +338,23 @@ int OGRBNADataSource::Create( const char *pszFilename,
         nbOutID = atoi(pszNbOutID);
         if (nbOutID <= 0)
         {
-            CPLError( CE_Warning, CPLE_AppDefined, 
+            CPLError( CE_Warning, CPLE_AppDefined,
                   "NB_ID=%s not understood. Must be >=%d and <=%d or equal to NB_SOURCE_FIELDS",
                   pszNbOutID, NB_MIN_BNA_IDS, NB_MAX_BNA_IDS );
             nbOutID = NB_MIN_BNA_IDS;
         }
         if (nbOutID > NB_MAX_BNA_IDS)
         {
-            CPLError( CE_Warning, CPLE_AppDefined, 
+            CPLError( CE_Warning, CPLE_AppDefined,
                   "NB_ID=%s not understood. Must be >=%d and <=%d or equal to NB_SOURCE_FIELDS",
                   pszNbOutID, NB_MIN_BNA_IDS, NB_MAX_BNA_IDS );
             nbOutID = NB_MAX_BNA_IDS;
         }
     }
-    
+
     /* Ellipses export as ellipses or polygons ? */
     bEllipsesAsEllipses = CSLFetchBoolean( papszOptions, "ELLIPSES_AS_ELLIPSES", TRUE);
-    
+
     /* Number of coordinate pairs per line */
     const char* pszNbPairPerLine = CSLFetchNameValue( papszOptions, "NB_PAIRS_PER_LINE");
     if (pszNbPairPerLine)
@@ -357,16 +364,18 @@ int OGRBNADataSource::Create( const char *pszFilename,
             nbPairPerLine = (bMultiLine == FALSE) ? 1000000000 : 1;
         if (bMultiLine == FALSE)
         {
-            CPLError( CE_Warning, CPLE_AppDefined, "NB_PAIR_PER_LINE option is ignored when MULTILINE=NO");
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "NB_PAIR_PER_LINE option is ignored when MULTILINE=NO" );
         }
     }
     else
     {
         nbPairPerLine = (bMultiLine == FALSE) ? 1000000000 : 1;
     }
-    
+
     /* Coordinate precision */
-    const char* pszCoordinatePrecision = CSLFetchNameValue( papszOptions, "COORDINATE_PRECISION");
+    const char* pszCoordinatePrecision
+        = CSLFetchNameValue( papszOptions, "COORDINATE_PRECISION" );
     if (pszCoordinatePrecision)
     {
         coordinatePrecision = atoi(pszCoordinatePrecision);
@@ -379,8 +388,9 @@ int OGRBNADataSource::Create( const char *pszFilename,
     {
         coordinatePrecision = 10;
     }
-    
-    pszCoordinateSeparator = (char*)CSLFetchNameValue( papszOptions, "COORDINATE_SEPARATOR");
+
+    pszCoordinateSeparator = const_cast<char *>(
+        CSLFetchNameValue( papszOptions, "COORDINATE_SEPARATOR" ) );
     if (pszCoordinateSeparator == NULL)
         pszCoordinateSeparator = CPLStrdup(",");
     else
diff --git a/ogr/ogrsf_frmts/bna/ogrbnadriver.cpp b/ogr/ogrsf_frmts/bna/ogrbnadriver.cpp
index 41dbb4b..e26059a 100644
--- a/ogr/ogrsf_frmts/bna/ogrbnadriver.cpp
+++ b/ogr/ogrsf_frmts/bna/ogrbnadriver.cpp
@@ -37,22 +37,27 @@
 static GDALDataset *OGRBNADriverOpen( GDALOpenInfo* poOpenInfo )
 
 {
-// -------------------------------------------------------------------- 
+// --------------------------------------------------------------------
 //      Does this appear to be a .bna file?
 // --------------------------------------------------------------------
-    if( poOpenInfo->fpL == NULL ||
-        !(EQUAL( CPLGetExtension(poOpenInfo->pszFilename), "bna" )
-           || ((EQUALN( poOpenInfo->pszFilename, "/vsigzip/", 9) ||
-                EQUALN( poOpenInfo->pszFilename, "/vsizip/", 8)) &&
-               (strstr( poOpenInfo->pszFilename, ".bna") ||
-                strstr( poOpenInfo->pszFilename, ".BNA")))) )
+    const char* pszFilename = poOpenInfo->pszFilename;
+    if( STARTS_WITH_CI(pszFilename, "BNA:") )
+    {
+        pszFilename += 4;
+    }
+    else if( poOpenInfo->fpL == NULL ||
+        !(EQUAL( CPLGetExtension(pszFilename), "bna" )
+           || ((STARTS_WITH_CI(pszFilename, "/vsigzip/") ||
+                STARTS_WITH_CI(pszFilename, "/vsizip/")) &&
+               (strstr( pszFilename, ".bna") ||
+                strstr( pszFilename, ".BNA")))) )
     {
         return NULL;
     }
 
     OGRBNADataSource   *poDS = new OGRBNADataSource();
 
-    if( !poDS->Open( poOpenInfo->pszFilename, poOpenInfo->eAccess == GA_Update ) )
+    if( !poDS->Open( pszFilename, poOpenInfo->eAccess == GA_Update ) )
     {
         delete poDS;
         poDS = NULL;
@@ -66,13 +71,13 @@ static GDALDataset *OGRBNADriverOpen( GDALOpenInfo* poOpenInfo )
 /************************************************************************/
 
 static GDALDataset *OGRBNADriverCreate( const char * pszName,
-                                        CPL_UNUSED int nBands,
-                                        CPL_UNUSED int nXSize,
-                                        CPL_UNUSED int nYSize,
-                                        CPL_UNUSED GDALDataType eDT,
+                                        int /* nBands */,
+                                        int /* nXSize */,
+                                        int /* nYSize */,
+                                        GDALDataType /* eDT */,
                                         char **papszOptions )
 {
-    OGRBNADataSource   *poDS = new OGRBNADataSource();
+    OGRBNADataSource *poDS = new OGRBNADataSource();
 
     if( !poDS->Create( pszName, papszOptions ) )
     {
@@ -92,8 +97,8 @@ static CPLErr OGRBNADriverDelete( const char *pszFilename )
 {
     if( VSIUnlink( pszFilename ) == 0 )
         return CE_None;
-    else
-        return CE_Failure;
+
+    return CE_Failure;
 }
 
 /************************************************************************/
@@ -103,23 +108,18 @@ static CPLErr OGRBNADriverDelete( const char *pszFilename )
 void RegisterOGRBNA()
 
 {
-    GDALDriver  *poDriver;
-
-    if( GDALGetDriverByName( "BNA" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-
-        poDriver->SetDescription( "BNA" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Atlas BNA" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "bna" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_bna.html" );
-
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    if( GDALGetDriverByName( "BNA" ) != NULL )
+        return;
+
+    GDALDriver  *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "BNA" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Atlas BNA" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "bna" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_bna.html" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 #ifdef WIN32
 "  <Option name='LINEFORMAT' type='string-select' description='end-of-line sequence' default='CRLF'>"
@@ -140,12 +140,12 @@ void RegisterOGRBNA()
 "  <Option name='NB_PAIRS_PER_LINE' type='int' description='Maximum number of coordinate pair per line in multiline format'/>"
 "  <Option name='COORDINATE_PRECISION' type='int' description='Number of decimal for coordinates' default='10'/>"
 "</CreationOptionList>");
-        poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST, "<LayerCreationOptionList/>");
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+                               "<LayerCreationOptionList/>");
 
-        poDriver->pfnOpen = OGRBNADriverOpen;
-        poDriver->pfnCreate = OGRBNADriverCreate;
-        poDriver->pfnDelete = OGRBNADriverDelete;
+    poDriver->pfnOpen = OGRBNADriverOpen;
+    poDriver->pfnCreate = OGRBNADriverCreate;
+    poDriver->pfnDelete = OGRBNADriverDelete;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/bna/ogrbnalayer.cpp b/ogr/ogrsf_frmts/bna/ogrbnalayer.cpp
index e1cdb33..05bd32b 100644
--- a/ogr/ogrsf_frmts/bna/ogrbnalayer.cpp
+++ b/ogr/ogrsf_frmts/bna/ogrbnalayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrbnalayer.cpp 28382 2015-01-30 15:29:41Z rouault $
+ * $Id: ogrbnalayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  BNA Translator
  * Purpose:  Implements OGRBNALayer class.
@@ -33,10 +33,6 @@
 #include "cpl_csv.h"
 #include "ogr_p.h"
 
-#ifndef M_PI
-# define M_PI  3.1415926535897932384626433832795
-#endif
-
 /************************************************************************/
 /*                            OGRBNALayer()                             */
 /*                                                                      */
@@ -46,51 +42,49 @@
 
 OGRBNALayer::OGRBNALayer( const char *pszFilename,
                           const char* layerName,
-                          BNAFeatureType bnaFeatureType,
+                          BNAFeatureType bnaFeatureTypeIn,
                           OGRwkbGeometryType eLayerGeomType,
-                          int bWriter,
-                          OGRBNADataSource* poDS,
-                          int nIDs)
-
+                          int bWriterIn,
+                          OGRBNADataSource* poDSIn,
+                          int nIDsIn) :
+    poDS(poDSIn),
+    bWriter(bWriterIn),
+    nIDs(nIDsIn),
+    eof(FALSE),
+    failed(FALSE),
+    curLine(0),
+    nNextFID(0),
+    nFeatures(0),
+    partialIndexTable(TRUE),
+    offsetAndLineFeaturesTable(NULL)
 {
-    eof = FALSE;
-    failed = FALSE;
-    curLine = 0;
-    nNextFID = 0;
-    
-    this->bWriter = bWriter;
-    this->poDS = poDS;
-    this->nIDs = nIDs;
-
-    nFeatures = 0;
-    partialIndexTable = TRUE;
-    offsetAndLineFeaturesTable = NULL;
-
-    const char* iKnowHowToCount[] = { "Primary", "Secondary", "Third", "Fourth", "Fifth" };
+    static const char* const iKnowHowToCount[]
+        = { "Primary", "Secondary", "Third", "Fourth", "Fifth" };
     char tmp[32];
 
-    poFeatureDefn = new OGRFeatureDefn( CPLSPrintf("%s_%s", 
-                                                   CPLGetBasename( pszFilename ) , 
-                                                   layerName ));
+    poFeatureDefn = new OGRFeatureDefn(
+        CPLSPrintf( "%s_%s",
+                    CPLGetBasename( pszFilename ),
+                    layerName ));
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( eLayerGeomType );
     SetDescription( poFeatureDefn->GetName() );
-    this->bnaFeatureType = bnaFeatureType;
+    this->bnaFeatureType = bnaFeatureTypeIn;
 
     if (! bWriter )
     {
-        int i;
-        for(i=0;i<nIDs;i++)
+        for(int i=0;i<nIDs;i++)
         {
-            if (i < (int) (sizeof(iKnowHowToCount)/sizeof(iKnowHowToCount[0])) )
+            if (i < static_cast<int>(
+                        sizeof(iKnowHowToCount)/sizeof(iKnowHowToCount[0]) ) )
             {
-                sprintf(tmp, "%s ID", iKnowHowToCount[i]);
+                snprintf(tmp, sizeof(tmp), "%s ID", iKnowHowToCount[i]);
                 OGRFieldDefn oFieldID(tmp, OFTString );
                 poFeatureDefn->AddFieldDefn( &oFieldID );
             }
             else
             {
-                sprintf(tmp, "%dth ID", i+1);
+                snprintf(tmp, sizeof(tmp), "%dth ID", i+1);
                 OGRFieldDefn oFieldID(tmp, OFTString );
                 poFeatureDefn->AddFieldDefn( &oFieldID );
             }
@@ -133,11 +127,14 @@ OGRBNALayer::~OGRBNALayer()
 /************************************************************************/
 /*                         SetFeatureIndexTable()                       */
 /************************************************************************/
-void  OGRBNALayer::SetFeatureIndexTable(int nFeatures, OffsetAndLine* offsetAndLineFeaturesTable, int partialIndexTable)
+void OGRBNALayer::SetFeatureIndexTable(
+    int nFeaturesIn,
+    OffsetAndLine* offsetAndLineFeaturesTableIn,
+    int partialIndexTableIn )
 {
-    this->nFeatures = nFeatures;
-    this->offsetAndLineFeaturesTable = offsetAndLineFeaturesTable;
-    this->partialIndexTable = partialIndexTable;
+    nFeatures = nFeaturesIn;
+    offsetAndLineFeaturesTable = offsetAndLineFeaturesTableIn;
+    partialIndexTable = partialIndexTableIn;
 }
 
 /************************************************************************/
@@ -153,7 +150,7 @@ void OGRBNALayer::ResetReading()
     failed = FALSE;
     curLine = 0;
     nNextFID = 0;
-    VSIFSeekL( fpBNA, 0, SEEK_SET );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( fpBNA, 0, SEEK_SET ));
 }
 
 
@@ -163,23 +160,23 @@ void OGRBNALayer::ResetReading()
 
 OGRFeature *OGRBNALayer::GetNextFeature()
 {
-    OGRFeature  *poFeature;
-    BNARecord* record;
-    int offset, line;
-
-    if (failed || eof || fpBNA == NULL) return NULL;
+    if (failed || eof || fpBNA == NULL)
+        return NULL;
 
     while(1)
     {
         int ok = FALSE;
-        offset = (int) VSIFTellL(fpBNA);
-        line = curLine;
+        const int offset = static_cast<int>( VSIFTellL(fpBNA) );
+        const int line = curLine;
         if (nNextFID < nFeatures)
         {
-            VSIFSeekL( fpBNA, offsetAndLineFeaturesTable[nNextFID].offset, SEEK_SET );
+            if( VSIFSeekL( fpBNA, offsetAndLineFeaturesTable[nNextFID].offset,
+                           SEEK_SET ) < 0 )
+                return NULL;
             curLine = offsetAndLineFeaturesTable[nNextFID].line;
         }
-        record =  BNA_GetNextRecord(fpBNA, &ok, &curLine, TRUE, bnaFeatureType);
+        BNARecord* record
+            = BNA_GetNextRecord(fpBNA, &ok, &curLine, TRUE, bnaFeatureType);
         if (ok == FALSE)
         {
             BNA_FreeRecord(record);
@@ -202,12 +199,15 @@ OGRFeature *OGRBNALayer::GetNextFeature()
             {
                 nFeatures++;
                 offsetAndLineFeaturesTable =
-                    (OffsetAndLine*)CPLRealloc(offsetAndLineFeaturesTable, nFeatures * sizeof(OffsetAndLine));
+                    static_cast<OffsetAndLine *>(
+                        CPLRealloc( offsetAndLineFeaturesTable,
+                                    nFeatures * sizeof(OffsetAndLine) ) );
                 offsetAndLineFeaturesTable[nFeatures-1].offset = offset;
                 offsetAndLineFeaturesTable[nFeatures-1].line = line;
             }
 
-            poFeature = BuildFeatureFromBNARecord(record, nNextFID++);
+            OGRFeature *poFeature
+                = BuildFeatureFromBNARecord(record, nNextFID++);
 
             BNA_FreeRecord(record);
 
@@ -235,13 +235,12 @@ OGRFeature *OGRBNALayer::GetNextFeature()
 
 void OGRBNALayer::WriteFeatureAttributes(VSILFILE* fp, OGRFeature *poFeature )
 {
-    int i;
     OGRFieldDefn *poFieldDefn;
     int nbOutID = poDS->GetNbOutId();
     if (nbOutID < 0)
         nbOutID = poFeatureDefn->GetFieldCount();
-    for(i=0;i<nbOutID;i++)
-    { 
+    for(int i = 0; i < nbOutID; i++ )
+    {
         if (i < poFeatureDefn->GetFieldCount())
         {
             poFieldDefn = poFeatureDefn->GetFieldDefn( i );
@@ -252,22 +251,22 @@ void OGRBNALayer::WriteFeatureAttributes(VSILFILE* fp, OGRFeature *poFeature )
                     char szBuffer[64];
                     OGRFormatDouble(szBuffer, sizeof(szBuffer),
                                     poFeature->GetFieldAsDouble(i), '.');
-                    VSIFPrintfL( fp, "\"%s\",", szBuffer);
+                    CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "\"%s\",", szBuffer));
                 }
                 else
                 {
                     const char *pszRaw = poFeature->GetFieldAsString( i );
-                    VSIFPrintfL( fp, "\"%s\",", pszRaw);
+                    CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "\"%s\",", pszRaw));
                 }
             }
             else
             {
-                VSIFPrintfL( fp, "\"\",");
+                CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "\"\","));
             }
         }
         else
         {
-            VSIFPrintfL( fp, "\"\",");
+            CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "\"\","));
         }
     }
 }
@@ -280,10 +279,10 @@ void OGRBNALayer::WriteCoord(VSILFILE* fp, double dfX, double dfY)
 {
     char szBuffer[64];
     OGRFormatDouble(szBuffer, sizeof(szBuffer), dfX, '.', poDS->GetCoordinatePrecision());
-    VSIFPrintfL( fp, "%s", szBuffer);
-    VSIFPrintfL( fp, "%s", poDS->GetCoordinateSeparator());
+    CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "%s", szBuffer));
+    CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "%s", poDS->GetCoordinateSeparator()));
     OGRFormatDouble(szBuffer, sizeof(szBuffer), dfY, '.', poDS->GetCoordinatePrecision());
-    VSIFPrintfL( fp, "%s", szBuffer);
+    CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "%s", szBuffer));
 }
 
 /************************************************************************/
@@ -293,7 +292,6 @@ void OGRBNALayer::WriteCoord(VSILFILE* fp, double dfX, double dfY)
 OGRErr OGRBNALayer::ICreateFeature( OGRFeature *poFeature )
 
 {
-    int i,j,k,n;
     OGRGeometry     *poGeom = poFeature->GetGeometryRef();
     char eol[3];
     const char* partialEol = (poDS->GetMultiLine()) ? eol : poDS->GetCoordinateSeparator();
@@ -316,15 +314,15 @@ OGRErr OGRBNALayer::ICreateFeature( OGRFeature *poFeature )
         eol[0] = 10;
         eol[1] = 0;
     }
-    
+
     if ( ! bWriter )
     {
         return OGRERR_FAILURE;
     }
-    
+
     if( poFeature->GetFID() == OGRNullFID )
         poFeature->SetFID( nFeatures++ );
-    
+
     VSILFILE* fp = poDS->GetOutputFP();
     int nbPairPerLine = poDS->GetNbPairPerLine();
 
@@ -335,13 +333,13 @@ OGRErr OGRBNALayer::ICreateFeature( OGRFeature *poFeature )
         {
             OGRPoint* point = (OGRPoint*)poGeom;
             WriteFeatureAttributes(fp, poFeature);
-            VSIFPrintfL( fp, "1");
-            VSIFPrintfL( fp, "%s", partialEol);
+            CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "1"));
+            CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "%s", partialEol));
             WriteCoord(fp, point->getX(), point->getY());
-            VSIFPrintfL( fp, "%s", eol);
+            CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "%s", eol));
             break;
         }
-            
+
         case wkbPolygon:
         case wkbPolygon25D:
         {
@@ -351,12 +349,12 @@ OGRErr OGRBNALayer::ICreateFeature( OGRFeature *poFeature )
             {
                 return OGRERR_FAILURE;
             }
-            
+
             double firstX = ring->getX(0);
             double firstY = ring->getY(0);
             int nBNAPoints = ring->getNumPoints();
             int is_ellipse = FALSE;
-            
+
             /* This code tries to detect an ellipse in a polygon geometry */
             /* This will only work presumably on ellipses already read from a BNA file */
             /* Mostly a BNA to BNA feature... */
@@ -381,7 +379,7 @@ OGRErr OGRBNALayer::ICreateFeature( OGRFeature *poFeature )
                     double major_radius = fabs(firstX - center1X);
                     double minor_radius = fabs(quarterY - center1Y);
                     is_ellipse = TRUE;
-                    for(i=0;i<360;i++)
+                    for(int i=0;i<360;i++)
                     {
                         if (!(fabs(center1X + major_radius * cos(i * (M_PI / 180)) - ring->getX(i)) < 1e-5 &&
                               fabs(center1Y + minor_radius * sin(i * (M_PI / 180)) - ring->getY(i)) < 1e-5))
@@ -393,12 +391,12 @@ OGRErr OGRBNALayer::ICreateFeature( OGRFeature *poFeature )
                     if ( is_ellipse == TRUE )
                     {
                         WriteFeatureAttributes(fp, poFeature);
-                        VSIFPrintfL( fp, "2");
-                        VSIFPrintfL( fp, "%s", partialEol);
+                        CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "2"));
+                        CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "%s", partialEol));
                         WriteCoord(fp, center1X, center1Y);
-                        VSIFPrintfL( fp, "%s", partialEol);
+                        CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "%s", partialEol));
                         WriteCoord(fp, major_radius, minor_radius);
-                        VSIFPrintfL( fp, "%s", eol);
+                        CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "%s", eol));
                     }
                 }
             }
@@ -406,7 +404,7 @@ OGRErr OGRBNALayer::ICreateFeature( OGRFeature *poFeature )
             if ( is_ellipse == FALSE)
             {
                 int nInteriorRings = polygon->getNumInteriorRings();
-                for(i=0;i<nInteriorRings;i++)
+                for(int i=0;i<nInteriorRings;i++)
                 {
                     nBNAPoints += polygon->getInteriorRing(i)->getNumPoints() + 1;
                 }
@@ -416,30 +414,30 @@ OGRErr OGRBNALayer::ICreateFeature( OGRFeature *poFeature )
                     return OGRERR_FAILURE;
                 }
                 WriteFeatureAttributes(fp, poFeature);
-                VSIFPrintfL( fp, "%d", nBNAPoints);
-                n = ring->getNumPoints();
+                CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "%d", nBNAPoints));
+                int n = ring->getNumPoints();
                 int nbPair = 0;
-                for(i=0;i<n;i++)
+                for(int i=0;i<n;i++)
                 {
-                    VSIFPrintfL( fp, "%s", ((nbPair % nbPairPerLine) == 0) ? partialEol : " ");
+                    CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "%s", ((nbPair % nbPairPerLine) == 0) ? partialEol : " "));
                     WriteCoord(fp, ring->getX(i), ring->getY(i));
                     nbPair++;
                 }
-                for(i=0;i<nInteriorRings;i++)
+                for(int i=0;i<nInteriorRings;i++)
                 {
                     ring = polygon->getInteriorRing(i);
                     n = ring->getNumPoints();
-                    for(j=0;j<n;j++)
+                    for(int j=0;j<n;j++)
                     {
-                        VSIFPrintfL( fp, "%s", ((nbPair % nbPairPerLine) == 0) ? partialEol : " ");
+                        CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "%s", ((nbPair % nbPairPerLine) == 0) ? partialEol : " "));
                         WriteCoord(fp, ring->getX(j), ring->getY(j));
                         nbPair++;
                     }
-                    VSIFPrintfL( fp, "%s", ((nbPair % nbPairPerLine) == 0) ? partialEol : " ");
+                    CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "%s", ((nbPair % nbPairPerLine) == 0) ? partialEol : " "));
                     WriteCoord(fp, firstX, firstY);
                     nbPair++;
                 }
-                VSIFPrintfL( fp, "%s", eol);
+                CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "%s", eol));
             }
             break;
         }
@@ -450,8 +448,8 @@ OGRErr OGRBNALayer::ICreateFeature( OGRFeature *poFeature )
             OGRMultiPolygon* multipolygon = (OGRMultiPolygon*)poGeom;
             int N = multipolygon->getNumGeometries();
             int nBNAPoints = 0;
-            double firstX = 0, firstY = 0; 
-            for(i=0;i<N;i++)
+            double firstX = 0, firstY = 0;
+            for(int i=0;i<N;i++)
             {
                 OGRPolygon* polygon = (OGRPolygon*)multipolygon->getGeometryRef(i);
                 OGRLinearRing* ring = polygon->getExteriorRing();
@@ -467,7 +465,7 @@ OGRErr OGRBNALayer::ICreateFeature( OGRFeature *poFeature )
                 }
                 nBNAPoints += ring->getNumPoints();
                 int nInteriorRings = polygon->getNumInteriorRings();
-                for(j=0;j<nInteriorRings;j++)
+                for(int j=0;j<nInteriorRings;j++)
                 {
                     nBNAPoints += polygon->getInteriorRing(j)->getNumPoints() + 1;
                 }
@@ -478,45 +476,45 @@ OGRErr OGRBNALayer::ICreateFeature( OGRFeature *poFeature )
                 return OGRERR_FAILURE;
             }
             WriteFeatureAttributes(fp, poFeature);
-            VSIFPrintfL( fp, "%d", nBNAPoints);
+            CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "%d", nBNAPoints));
             int nbPair = 0;
-            for(i=0;i<N;i++)
+            for(int i=0;i<N;i++)
             {
                 OGRPolygon* polygon = (OGRPolygon*)multipolygon->getGeometryRef(i);
                 OGRLinearRing* ring = polygon->getExteriorRing();
                 if (ring == NULL)
                     continue;
 
-                n = ring->getNumPoints();
+                int n = ring->getNumPoints();
                 int nInteriorRings = polygon->getNumInteriorRings();
-                for(j=0;j<n;j++)
+                for(int j=0;j<n;j++)
                 {
-                    VSIFPrintfL( fp, "%s", ((nbPair % nbPairPerLine) == 0) ? partialEol : " ");
+                    CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "%s", ((nbPair % nbPairPerLine) == 0) ? partialEol : " "));
                     WriteCoord(fp, ring->getX(j), ring->getY(j));
                     nbPair++;
                 }
                 if (i != 0)
                 {
-                    VSIFPrintfL( fp, "%s", ((nbPair % nbPairPerLine) == 0) ? partialEol : " ");
+                    CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "%s", ((nbPair % nbPairPerLine) == 0) ? partialEol : " "));
                     WriteCoord(fp, firstX, firstY);
                     nbPair++;
                 }
-                for(j=0;j<nInteriorRings;j++)
+                for(int j=0;j<nInteriorRings;j++)
                 {
                     ring = polygon->getInteriorRing(j);
                     n = ring->getNumPoints();
-                    for(k=0;k<n;k++)
+                    for(int k=0;k<n;k++)
                     {
-                        VSIFPrintfL( fp, "%s", ((nbPair % nbPairPerLine) == 0) ? partialEol : " ");
+                        CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "%s", ((nbPair % nbPairPerLine) == 0) ? partialEol : " "));
                         WriteCoord(fp, ring->getX(k), ring->getY(k));
                         nbPair++;
                     }
-                    VSIFPrintfL( fp, "%s", ((nbPair % nbPairPerLine) == 0) ? partialEol : " ");
+                    CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "%s", ((nbPair % nbPairPerLine) == 0) ? partialEol : " "));
                     WriteCoord(fp, firstX, firstY);
                     nbPair++;
                 }
             }
-            VSIFPrintfL( fp, "%s", eol);
+            CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "%s", eol));
             break;
         }
 
@@ -525,25 +523,24 @@ OGRErr OGRBNALayer::ICreateFeature( OGRFeature *poFeature )
         {
             OGRLineString* line = (OGRLineString*)poGeom;
             int n = line->getNumPoints();
-            int i;
             if (n < 2)
             {
                 CPLError( CE_Failure, CPLE_AppDefined, "Invalid geometry" );
                 return OGRERR_FAILURE;
             }
             WriteFeatureAttributes(fp, poFeature);
-            VSIFPrintfL( fp, "-%d", n);
+            CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "-%d", n));
             int nbPair = 0;
-            for(i=0;i<n;i++)
+            for(int i=0;i<n;i++)
             {
-                VSIFPrintfL( fp, "%s", partialEol);
+                CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "%s", partialEol));
                 WriteCoord(fp, line->getX(i), line->getY(i));
                 nbPair++;
             }
-            VSIFPrintfL( fp, "%s", eol);
+            CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "%s", eol));
             break;
         }
-            
+
         default:
         {
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -553,7 +550,7 @@ OGRErr OGRBNALayer::ICreateFeature( OGRFeature *poFeature )
             return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
         }
     }
-    
+
     return OGRERR_NONE;
 }
 
@@ -563,8 +560,7 @@ OGRErr OGRBNALayer::ICreateFeature( OGRFeature *poFeature )
 /*                            CreateField()                             */
 /************************************************************************/
 
-OGRErr OGRBNALayer::CreateField( OGRFieldDefn *poField,
-                                 CPL_UNUSED int bApproxOK )
+OGRErr OGRBNALayer::CreateField( OGRFieldDefn *poField, int /* bApproxOK */ )
 {
     if( !bWriter || nFeatures != 0)
         return OGRERR_FAILURE;
@@ -578,29 +574,28 @@ OGRErr OGRBNALayer::CreateField( OGRFieldDefn *poField,
 /************************************************************************/
 /*                           BuildFeatureFromBNARecord()                */
 /************************************************************************/
-OGRFeature *    OGRBNALayer::BuildFeatureFromBNARecord (BNARecord* record, long fid)
+OGRFeature *OGRBNALayer::BuildFeatureFromBNARecord (BNARecord* record, long fid)
 {
-    OGRFeature  *poFeature;
-    int i;
-
-    poFeature = new OGRFeature( poFeatureDefn );
-    for(i=0;i<nIDs;i++)
+    OGRFeature  *poFeature = new OGRFeature( poFeatureDefn );
+    for( int i = 0; i < nIDs; i++ )
     {
         poFeature->SetField( i, record->ids[i] ? record->ids[i] : "");
     }
     poFeature->SetFID( fid );
     if (bnaFeatureType == BNA_POINT)
     {
-        poFeature->SetGeometryDirectly( new OGRPoint( record->tabCoords[0][0], record->tabCoords[0][1] ) );
+        poFeature->SetGeometryDirectly(
+            new OGRPoint( record->tabCoords[0][0], record->tabCoords[0][1] ) );
     }
     else if (bnaFeatureType == BNA_POLYLINE)
     {
         OGRLineString* lineString = new OGRLineString ();
         lineString->setCoordinateDimension(2);
         lineString->setNumPoints(record->nCoords);
-        for(i=0;i<record->nCoords;i++)
+        for( int i = 0; i < record->nCoords; i++)
         {
-            lineString->setPoint(i, record->tabCoords[i][0], record->tabCoords[i][1] );
+            lineString->setPoint( i, record->tabCoords[i][0],
+                                  record->tabCoords[i][1] );
         }
         poFeature->SetGeometryDirectly(lineString);
     }
@@ -610,17 +605,19 @@ OGRFeature *    OGRBNALayer::BuildFeatureFromBNARecord (BNARecord* record, long
         double firstY = record->tabCoords[0][1];
         int isFirstPolygon = 1;
         double secondaryFirstX = 0, secondaryFirstY = 0;
-  
+
         OGRLinearRing* ring = new OGRLinearRing ();
         ring->setCoordinateDimension(2);
         ring->addPoint(record->tabCoords[0][0], record->tabCoords[0][1] );
-  
+
         /* record->nCoords is really a safe upper bound */
         int nbPolygons = 0;
         OGRPolygon** tabPolygons =
-            (OGRPolygon**)CPLMalloc(record->nCoords * sizeof(OGRPolygon*));
+            static_cast<OGRPolygon**>(
+                CPLMalloc( record->nCoords * sizeof(OGRPolygon*) ) );
 
-        for(i=1;i<record->nCoords;i++)
+        int i = 1;
+        for( ; i < record->nCoords; i++ )
         {
             ring->addPoint(record->tabCoords[i][0], record->tabCoords[i][1] );
             if (isFirstPolygon == 1 &&
@@ -631,20 +628,21 @@ OGRFeature *    OGRBNALayer::BuildFeatureFromBNARecord (BNARecord* record, long
                 polygon->addRingDirectly(ring);
                 tabPolygons[nbPolygons] = polygon;
                 nbPolygons++;
-    
+
                 if (i == record->nCoords - 1)
                 {
                     break;
                 }
-    
+
                 isFirstPolygon = 0;
-    
-                i ++;
+
+                i++;
                 secondaryFirstX = record->tabCoords[i][0];
                 secondaryFirstY = record->tabCoords[i][1];
                 ring = new OGRLinearRing ();
                 ring->setCoordinateDimension(2);
-                ring->addPoint(record->tabCoords[i][0], record->tabCoords[i][1] );
+                ring->addPoint( record->tabCoords[i][0],
+                                record->tabCoords[i][1] );
             }
             else if (isFirstPolygon == 0 &&
                     record->tabCoords[i][0] == secondaryFirstX &&
@@ -658,9 +656,11 @@ OGRFeature *    OGRBNALayer::BuildFeatureFromBNARecord (BNARecord* record, long
 
                 if (i < record->nCoords - 1)
                 {
-                    /* After the closing of a subpolygon, the first coordinates of the first polygon */
-                    /* should be recalled... in theory */
-                    if (record->tabCoords[i+1][0] == firstX &&  record->tabCoords[i+1][1] == firstY)
+                    // After the closing of a subpolygon, the first
+                    // coordinates of the first polygon should be
+                    // recalled... in theory
+                    if (record->tabCoords[i+1][0] == firstX
+                        && record->tabCoords[i+1][1] == firstY)
                     {
                         if (i + 1 == record->nCoords - 1)
                             break;
@@ -669,8 +669,9 @@ OGRFeature *    OGRBNALayer::BuildFeatureFromBNARecord (BNARecord* record, long
                     else
                     {
 #if 0
-                        CPLError(CE_Warning, CPLE_AppDefined, 
-                                 "Geometry of polygon of fid %d starting at line %d is not strictly conformant. "
+                        CPLError(CE_Warning, CPLE_AppDefined,
+                                 "Geometry of polygon of fid %d starting at "
+                                 "line %d is not strictly conformant. "
                                  "Trying to go on...\n",
                                  fid,
                                  offsetAndLineFeaturesTable[fid].line + 1);
@@ -682,25 +683,29 @@ OGRFeature *    OGRBNALayer::BuildFeatureFromBNARecord (BNARecord* record, long
                     secondaryFirstY = record->tabCoords[i][1];
                     ring = new OGRLinearRing ();
                     ring->setCoordinateDimension(2);
-                    ring->addPoint(record->tabCoords[i][0], record->tabCoords[i][1] );
+                    ring->addPoint( record->tabCoords[i][0],
+                                    record->tabCoords[i][1] );
                 }
                 else
                 {
 #if 0
-                    CPLError(CE_Warning, CPLE_AppDefined, 
-                        "Geometry of polygon of fid %d starting at line %d is not strictly conformant. Trying to go on...\n",
-                        fid,
-                        offsetAndLineFeaturesTable[fid].line + 1);
+                    CPLError( CE_Warning, CPLE_AppDefined,
+                              "Geometry of polygon of fid %d starting at "
+                              "line %d is not strictly conformant. "
+                              "Trying to go on...\n",
+                              fid,
+                              offsetAndLineFeaturesTable[fid].line + 1);
 #endif
                 }
             }
         }
         if (i == record->nCoords)
         {
-            /* Let's be a bit tolerant abount non closing polygons */
+            /* Let's be a bit tolerant about non-closing polygons. */
             if (isFirstPolygon)
             {
-                ring->addPoint(record->tabCoords[0][0], record->tabCoords[0][1] );
+                ring->addPoint( record->tabCoords[0][0],
+                                record->tabCoords[0][1] );
 
                 OGRPolygon* polygon = new OGRPolygon ();
                 polygon->addRingDirectly(ring);
@@ -708,11 +713,11 @@ OGRFeature *    OGRBNALayer::BuildFeatureFromBNARecord (BNARecord* record, long
                 nbPolygons++;
             }
         }
-        
+
         if (nbPolygons == 1)
         {
-            /* Special optimization here : we directly put the polygon into the multipolygon. */
-            /* This should save quite a few useless copies */
+            // Special optimization here : we directly put the polygon into
+            // the multipolygon.  This should save quite a few useless copies
             OGRMultiPolygon* multipolygon = new OGRMultiPolygon();
             multipolygon->addGeometryDirectly(tabPolygons[0]);
             poFeature->SetGeometryDirectly(multipolygon);
@@ -721,15 +726,18 @@ OGRFeature *    OGRBNALayer::BuildFeatureFromBNARecord (BNARecord* record, long
         {
             int isValidGeometry;
             poFeature->SetGeometryDirectly(
-                OGRGeometryFactory::organizePolygons((OGRGeometry**)tabPolygons, nbPolygons, &isValidGeometry, NULL));
-            
+                OGRGeometryFactory::organizePolygons(
+                    reinterpret_cast<OGRGeometry**>( tabPolygons ),
+                    nbPolygons, &isValidGeometry, NULL ) );
+
             if (!isValidGeometry)
             {
-                CPLError(CE_Warning, CPLE_AppDefined, 
-                        "Geometry of polygon of fid %ld starting at line %d cannot be translated to Simple Geometry. "
-                        "All polygons will be contained in a multipolygon.\n",
-                        fid,
-                        offsetAndLineFeaturesTable[fid].line + 1);
+                CPLError( CE_Warning, CPLE_AppDefined,
+                          "Geometry of polygon of fid %ld starting at line %d "
+                          "cannot be translated to Simple Geometry. "
+                          "All polygons will be contained in a multipolygon.\n",
+                          fid,
+                          offsetAndLineFeaturesTable[fid].line + 1);
             }
         }
 
@@ -737,8 +745,8 @@ OGRFeature *    OGRBNALayer::BuildFeatureFromBNARecord (BNARecord* record, long
     }
     else
     {
-        /* Circle or ellipses are not part of the OGR Simple Geometry, so we discretize them
-           into polygons by 1 degree step */
+        // Circle or ellipses are not part of the OGR Simple Geometry, so we
+        // discretize them into polygons by 1 degree step.
         OGRPolygon* polygon = new OGRPolygon ();
         OGRLinearRing* ring = new OGRLinearRing ();
         ring->setCoordinateDimension(2);
@@ -748,7 +756,7 @@ OGRFeature *    OGRBNALayer::BuildFeatureFromBNARecord (BNARecord* record, long
         double minor_radius = record->tabCoords[1][1];
         if (minor_radius == 0)
             minor_radius = major_radius;
-        for(i=0;i<360;i++)
+        for( int i = 0; i < 360; i++ )
         {
             ring->addPoint(center_x + major_radius * cos(i * (M_PI / 180)),
                            center_y + minor_radius * sin(i * (M_PI / 180)) );
@@ -760,7 +768,7 @@ OGRFeature *    OGRBNALayer::BuildFeatureFromBNARecord (BNARecord* record, long
         poFeature->SetField( nIDs, major_radius);
         poFeature->SetField( nIDs+1, minor_radius);
     }
-    
+
     return poFeature;
 }
 
@@ -774,25 +782,30 @@ void OGRBNALayer::FastParseUntil ( int interestFID)
     {
         ResetReading();
 
-        BNARecord* record;
+        BNARecord *record = NULL;
 
         if (nFeatures > 0)
         {
-            VSIFSeekL( fpBNA, offsetAndLineFeaturesTable[nFeatures-1].offset, SEEK_SET );
+            if( VSIFSeekL( fpBNA,
+                           offsetAndLineFeaturesTable[nFeatures-1].offset,
+                           SEEK_SET ) < 0 )
+                return;
             curLine = offsetAndLineFeaturesTable[nFeatures-1].line;
 
             /* Just skip the last read one */
             int ok = FALSE;
-            record =  BNA_GetNextRecord(fpBNA, &ok, &curLine, TRUE, BNA_READ_NONE);
+            record = BNA_GetNextRecord(fpBNA, &ok, &curLine, TRUE,
+                                       BNA_READ_NONE);
             BNA_FreeRecord(record);
         }
 
         while(1)
         {
             int ok = FALSE;
-            int offset = (int) VSIFTellL(fpBNA);
+            int offset = static_cast<int>( VSIFTellL(fpBNA) );
             int line = curLine;
-            record =  BNA_GetNextRecord(fpBNA, &ok, &curLine, TRUE, BNA_READ_NONE);
+            record = BNA_GetNextRecord(fpBNA, &ok, &curLine, TRUE,
+                                       BNA_READ_NONE);
             if (ok == FALSE)
             {
                 failed = TRUE;
@@ -812,7 +825,9 @@ void OGRBNALayer::FastParseUntil ( int interestFID)
             {
                 nFeatures++;
                 offsetAndLineFeaturesTable =
-                    (OffsetAndLine*)CPLRealloc(offsetAndLineFeaturesTable, nFeatures * sizeof(OffsetAndLine));
+                    static_cast<OffsetAndLine *>(
+                        CPLRealloc( offsetAndLineFeaturesTable,
+                                    nFeatures * sizeof(OffsetAndLine) ) );
                 offsetAndLineFeaturesTable[nFeatures-1].offset = offset;
                 offsetAndLineFeaturesTable[nFeatures-1].line = line;
 
@@ -835,23 +850,23 @@ void OGRBNALayer::FastParseUntil ( int interestFID)
 
 OGRFeature *  OGRBNALayer::GetFeature( GIntBig nFID )
 {
-    OGRFeature  *poFeature;
-    BNARecord* record;
-    int ok;
-    
-    if (nFID < 0 || (GIntBig)(int)nFID != nFID)
+    if (nFID < 0 || !CPL_INT64_FITS_ON_INT32(nFID))
         return NULL;
 
-    FastParseUntil((int)nFID);
+    FastParseUntil( static_cast<int>( nFID ) );
 
     if (nFID >= nFeatures)
         return NULL;
 
-    VSIFSeekL( fpBNA, offsetAndLineFeaturesTable[nFID].offset, SEEK_SET );
+    int ok;
+    if( VSIFSeekL( fpBNA, offsetAndLineFeaturesTable[nFID].offset, SEEK_SET ) < 0 )
+        return NULL;
+
     curLine = offsetAndLineFeaturesTable[nFID].line;
-    record =  BNA_GetNextRecord(fpBNA, &ok, &curLine, TRUE, bnaFeatureType);
+    BNARecord* record
+        = BNA_GetNextRecord(fpBNA, &ok, &curLine, TRUE, bnaFeatureType);
 
-    poFeature = BuildFeatureFromBNARecord(record, (int)nFID);
+    OGRFeature *poFeature = BuildFeatureFromBNARecord(record, (int)nFID);
 
     BNA_FreeRecord(record);
 
diff --git a/ogr/ogrsf_frmts/bna/ogrbnaparser.cpp b/ogr/ogrsf_frmts/bna/ogrbnaparser.cpp
index 17b7cc0..1b269f0 100644
--- a/ogr/ogrsf_frmts/bna/ogrbnaparser.cpp
+++ b/ogr/ogrsf_frmts/bna/ogrbnaparser.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrbnaparser.cpp 27721 2014-09-22 12:42:28Z goatbar $
+ * $Id: ogrbnaparser.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  BNA Parser
  * Purpose:  Parse a BNA record
@@ -36,8 +36,7 @@ void BNA_FreeRecord(BNARecord* record)
 {
   if (record)
   {
-    int i;
-    for(i=0;i<NB_MAX_BNA_IDS;i++)
+    for( int i = 0; i < NB_MAX_BNA_IDS; i++)
     {
         if (record->ids[i]) VSIFree(record->ids[i]);
         record->ids[i] = NULL;
@@ -67,14 +66,14 @@ const char* BNA_FeatureTypeToStr(BNAFeatureType featureType)
 
 void BNA_Display(BNARecord* record)
 {
-  int i;
   fprintf(stderr, "\"%s\", \"%s\", \"%s\", %s\n",
           record->ids[0] ? record->ids[0] : "",
           record->ids[1] ? record->ids[1] : "",
           record->ids[2] ? record->ids[2] : "",
           BNA_FeatureTypeToStr(record->featureType));
-  for(i=0;i<record->nCoords;i++)
-    fprintf(stderr, "%f, %f\n", record->tabCoords[i][0], record->tabCoords[i][1]);
+  for( int i = 0; i < record->nCoords; i++ )
+    fprintf( stderr, "%f, %f\n", record->tabCoords[i][0],
+             record->tabCoords[i][1] );
 }
 
 /*
@@ -113,31 +112,32 @@ and http://64.145.236.125/forum/topic.asp?topic_id=1930&forum_id=1&Topic_Title=h
 -73.000000, 41.087010 -73.035597, 41.114420 -73.049337, 41.125000
 */
 
-/* We are (and must be) a bit tolerant : BNA files format has several variations */
-/* and most don't follow strictly the 'specification' */
-/* Extra spaces, tabulations or line feed are accepted and ignored */
-/* We allow one line format and several line format in the same file */
-/* We allow from NB_MIN_BNA_IDS to NB_MAX_BNA_IDS ids */
-/* We allow that couples of coordinates on the same line may be separated only by spaces */
-/* (instead of being separated by a comma) */
-
-#define STRING_NOT_TERMINATED      "string not terminated when end of line occured"
-#define MISSING_FIELDS             "missing fields"
-#define BAD_INTEGER_NUMBER_FORMAT  "bad integer number format"
-#define BAD_FLOAT_NUMBER_FORMAT    "bad float number format"
-#define PRIMARY_ID_MANDATORY       "primary ID can't be empty or missing"
-#define STRING_EXPECTED            "string expected"
-#define NUMBER_EXPECTED            "number expected"
-#define INTEGER_NUMBER_EXPECTED    "integer number expected"
-#define FLOAT_NUMBER_EXPECTED      "float number expected"
-#define INVALID_GEOMETRY_TYPE      "invalid geometry type"
-#define TOO_LONG_ID                "too long id (> 256 characters)"
-#define MAX_BNA_IDS_REACHED        "maximum number of IDs reached"
-#define NOT_ENOUGH_MEMORY          "not enough memory for request number of coordinates"
-#define LINE_TOO_LONG              "line too long"
-
-#define TMP_BUFFER_SIZE             256
-#define LINE_BUFFER_SIZE            1024
+// We are (and must be) a bit tolerant : BNA files format has several variations
+// and most don't follow strictly the 'specification'.
+// Extra spaces, tabulations or line feed are accepted and ignored.
+// We allow one line format and several line format in the same file.
+// We allow from NB_MIN_BNA_IDS to NB_MAX_BNA_IDS ids.
+// We allow that couples of coordinates on the same line may be separated only
+// by spaces (instead of being separated by a comma).
+
+static const char *const STRING_NOT_TERMINATED
+    = "string not terminated when end of line occurred";
+static const char *const MISSING_FIELDS            = "missing fields";
+static const char *const BAD_INTEGER_NUMBER_FORMAT = "bad integer number format";
+static const char *const BAD_FLOAT_NUMBER_FORMAT   = "bad float number format";
+static const char *const STRING_EXPECTED           = "string expected";
+static const char *const NUMBER_EXPECTED           = "number expected";
+static const char *const INTEGER_NUMBER_EXPECTED   = "integer number expected";
+static const char *const FLOAT_NUMBER_EXPECTED     = "float number expected";
+static const char *const INVALID_GEOMETRY_TYPE     = "invalid geometry type";
+static const char *const TOO_LONG_ID               = "too long id (> 256 characters)";
+static const char *const MAX_BNA_IDS_REACHED       = "maximum number of IDs reached";
+static const char *const NOT_ENOUGH_MEMORY
+    = "not enough memory for request number of coordinates";
+static const char *const LINE_TOO_LONG             = "line too long";
+
+static const int TMP_BUFFER_SIZE = 256;
+static const int LINE_BUFFER_SIZE = 1024;
 
 enum
 {
@@ -149,7 +149,8 @@ enum
 static int BNA_GetLine(char szLineBuffer[LINE_BUFFER_SIZE+1], VSILFILE* f)
 {
     char* ptrCurLine = szLineBuffer;
-    int nRead = VSIFReadL(szLineBuffer, 1, LINE_BUFFER_SIZE, f);
+    int nRead
+        = static_cast<int>( VSIFReadL(szLineBuffer, 1, LINE_BUFFER_SIZE, f) );
     szLineBuffer[nRead] = 0;
     if (nRead == 0)
     {
@@ -171,8 +172,8 @@ static int BNA_GetLine(char szLineBuffer[LINE_BUFFER_SIZE+1], VSILFILE* f)
     {
         if (nRead < LINE_BUFFER_SIZE)
             return BNA_LINE_OK;
-        else
-            return BNA_LINE_TOO_LONG;
+
+        return BNA_LINE_TOO_LONG;
     }
 
     if (*ptrCurLine == 0x0d)
@@ -180,7 +181,7 @@ static int BNA_GetLine(char szLineBuffer[LINE_BUFFER_SIZE+1], VSILFILE* f)
         if (ptrCurLine == szLineBuffer + LINE_BUFFER_SIZE - 1)
         {
             char c;
-            nRead = VSIFReadL(&c, 1, 1, f);
+            nRead = static_cast<int>(VSIFReadL(&c, 1, 1, f));
             if (nRead == 1)
             {
                 if (c == 0x0a)
@@ -189,22 +190,34 @@ static int BNA_GetLine(char szLineBuffer[LINE_BUFFER_SIZE+1], VSILFILE* f)
                 }
                 else
                 {
-                    VSIFSeekL(f, VSIFTellL(f) - 1, SEEK_SET);
+                    if( VSIFSeekL(f, VSIFTellL(f) - 1, SEEK_SET) != 0 )
+                        return BNA_LINE_EOF;
                 }
             }
         }
         else if (ptrCurLine[1] == 0x0a)
         {
-            VSIFSeekL(f, VSIFTellL(f) + ptrCurLine + 2 - (szLineBuffer + nRead), SEEK_SET);
+            if( VSIFSeekL( f,
+                           VSIFTellL(f) + ptrCurLine + 2
+                           - (szLineBuffer + nRead),
+                           SEEK_SET ) != 0 )
+                return BNA_LINE_EOF;
         }
         else
         {
-            VSIFSeekL(f, VSIFTellL(f) + ptrCurLine + 1 - (szLineBuffer + nRead), SEEK_SET);
+            if( VSIFSeekL( f,
+                           VSIFTellL(f) + ptrCurLine + 1
+                           - (szLineBuffer + nRead),
+                           SEEK_SET ) != 0 )
+                return BNA_LINE_EOF;
         }
     }
     else /* *ptrCurLine == 0x0a */
     {
-        VSIFSeekL(f, VSIFTellL(f) + ptrCurLine + 1 - (szLineBuffer + nRead), SEEK_SET);
+        if( VSIFSeekL( f,
+                       VSIFTellL(f) + ptrCurLine + 1 - (szLineBuffer + nRead),
+                       SEEK_SET) != 0 )
+            return BNA_LINE_EOF;
     }
     *ptrCurLine = 0;
 
@@ -218,14 +231,12 @@ BNARecord* BNA_GetNextRecord(VSILFILE* f,
                              int verbose,
                              BNAFeatureType interestFeatureType)
 {
-    BNARecord* record;
-    char c;
-    int inQuotes = FALSE;
+    bool inQuotes = false;
     int numField = 0;
     char* ptrBeginningOfNumber = NULL;
-    int exponentFound = 0;
-    int exponentSignFound = 0;
-    int dotFound = 0;
+    bool exponentFound = false;
+    bool exponentSignFound = false;
+    bool dotFound = false;
     int numChar = 0;
     const char* detailedErrorMsg = NULL;
     BNAFeatureType currentFeatureType = BNA_UNKNOWN;
@@ -234,10 +245,11 @@ BNARecord* BNA_GetNextRecord(VSILFILE* f,
     int  tmpBufferLength[NB_MAX_BNA_IDS] = {0, 0, 0};
     char szLineBuffer[LINE_BUFFER_SIZE + 1];
 
-    record = (BNARecord*)CPLMalloc(sizeof(BNARecord));
+    BNARecord* record
+        = static_cast<BNARecord *>( CPLMalloc(sizeof(BNARecord)) );
     memset(record, 0, sizeof(BNARecord));
 
-    while (TRUE)
+    while( true )
     {
       numChar = 0;
       (*curLine)++;
@@ -254,15 +266,16 @@ BNARecord* BNA_GetNextRecord(VSILFILE* f,
       }
 
       char* ptrCurLine = szLineBuffer;
-      const char* ptrBeginLine = szLineBuffer;
 
       if (*ptrCurLine == 0)
         continue;
 
+      const char* ptrBeginLine = szLineBuffer;
+
       while(1)
       {
-        numChar = ptrCurLine - ptrBeginLine;
-        c = *ptrCurLine;
+        numChar = static_cast<int>(ptrCurLine - ptrBeginLine);
+        char c = *ptrCurLine;
         if (c == 0) c = 10;
         if (inQuotes)
         {
@@ -275,7 +288,7 @@ BNARecord* BNA_GetNextRecord(VSILFILE* f,
           {
             if (tmpBufferLength[numField] == TMP_BUFFER_SIZE)
             {
-              detailedErrorMsg = TOO_LONG_ID; 
+              detailedErrorMsg = TOO_LONG_ID;
               goto error;
             }
             tmpBuffer[numField][tmpBufferLength[numField]++] = c;
@@ -290,7 +303,7 @@ BNARecord* BNA_GetNextRecord(VSILFILE* f,
           {
             if (tmpBufferLength[numField] == TMP_BUFFER_SIZE)
             {
-              detailedErrorMsg = TOO_LONG_ID; 
+              detailedErrorMsg = TOO_LONG_ID;
               goto error;
             }
             tmpBuffer[numField][tmpBufferLength[numField]++] = c;
@@ -303,7 +316,7 @@ BNARecord* BNA_GetNextRecord(VSILFILE* f,
             do
             {
               ptrCurLine++;
-              numChar = ptrCurLine - ptrBeginLine;
+              numChar = static_cast<int>(ptrCurLine - ptrBeginLine);
               c = *ptrCurLine;
               if (!(c == ' ' || c == '\t'))
                 break;
@@ -328,9 +341,10 @@ BNARecord* BNA_GetNextRecord(VSILFILE* f,
               {
                 if (verbose)
                 {
-                  CPLError(CE_Warning, CPLE_AppDefined, 
-                           "At line %d, at char %d, extra data will be ignored!\n",
-                           *curLine, numChar+1);
+                  CPLError( CE_Warning, CPLE_AppDefined,
+                            "At line %d, at char %d, extra data will be "
+                            "ignored",
+                            *curLine, numChar+1 );
                 }
               }
               *ok = 1;
@@ -338,9 +352,9 @@ BNARecord* BNA_GetNextRecord(VSILFILE* f,
             }
 
             ptrBeginningOfNumber = NULL;
-            exponentFound = 0;
-            exponentSignFound = 0;
-            dotFound = 0;
+            exponentFound = false;
+            exponentSignFound = false;
+            dotFound = false;
             numField++;
 
             if (c == 10)
@@ -348,7 +362,7 @@ BNARecord* BNA_GetNextRecord(VSILFILE* f,
 
             if (c != ',')
             {
-              /* don't increment ptrCurLine */
+              // Do not increment ptrCurLine.
               continue;
             }
           }
@@ -377,7 +391,8 @@ BNARecord* BNA_GetNextRecord(VSILFILE* f,
 
           if (numField == 0)
           {
-            /* Maybe not so mandatory.. Atlas MapMaker(TM) exports BNA files with empty primaryID */
+            // Maybe not so mandatory...
+            // Atlas MapMaker(TM) exports BNA files with empty primaryID.
             /*
             if (record->primaryID == NULL || *(record->primaryID) == 0)
             {
@@ -395,7 +410,8 @@ BNARecord* BNA_GetNextRecord(VSILFILE* f,
               goto error;
             }
             nCoords = atoi(ptrBeginningOfNumber);
-            if (nCoords == 0 || nCoords == -1)
+            if (nCoords == 0 || nCoords == -1 || nCoords >= INT_MAX / 16 ||
+                nCoords <= INT_MIN / 16 )
             {
               detailedErrorMsg = INVALID_GEOMETRY_TYPE;
               goto error;
@@ -426,8 +442,7 @@ BNARecord* BNA_GetNextRecord(VSILFILE* f,
             if (interestFeatureType == BNA_READ_ALL ||
                 interestFeatureType == currentFeatureType)
             {
-              int i;
-              for(i=0;i<NB_MAX_BNA_IDS;i++)
+              for( int i=0; i < NB_MAX_BNA_IDS; i++ )
               {
                 if (tmpBufferLength[i] && tmpBuffer[i][0])
                 {
@@ -438,7 +453,7 @@ BNARecord* BNA_GetNextRecord(VSILFILE* f,
               }
 
               record->tabCoords =
-                  (double(*)[2])VSIMalloc(record->nCoords * 2 * sizeof(double));
+                  (double(*)[2])VSI_MALLOC2_VERBOSE(record->nCoords, 2 * sizeof(double));
               if (record->tabCoords == NULL)
               {
                   detailedErrorMsg = NOT_ENOUGH_MEMORY;
@@ -465,15 +480,17 @@ BNARecord* BNA_GetNextRecord(VSILFILE* f,
               if (pszComma)
                   *pszComma = ',';
             }
-            if (numField == NB_MIN_BNA_IDS + 1 + nbExtraId + 2 * record->nCoords - 1)
+            if (numField ==
+                NB_MIN_BNA_IDS + 1 + nbExtraId + 2 * record->nCoords - 1)
             {
               if (c != 10)
               {
                 if (verbose)
                 {
-                  CPLError(CE_Warning, CPLE_AppDefined, 
-                           "At line %d, at char %d, extra data will be ignored!\n",
-                           *curLine, numChar+1);
+                  CPLError( CE_Warning, CPLE_AppDefined,
+                            "At line %d, at char %d, extra data will be "
+                            "ignored",
+                            *curLine, numChar+1);
                 }
               }
               *ok = 1;
@@ -482,9 +499,9 @@ BNARecord* BNA_GetNextRecord(VSILFILE* f,
           }
 
           ptrBeginningOfNumber = NULL;
-          exponentFound = 0;
-          exponentSignFound = 0;
-          dotFound = 0;
+          exponentFound = false;
+          exponentSignFound = false;
+          dotFound = false;
           numField++;
 
           if (c == 10)
@@ -496,7 +513,8 @@ BNARecord* BNA_GetNextRecord(VSILFILE* f,
           {
             inQuotes = TRUE;
           }
-          else if (numField >= NB_MIN_BNA_IDS && currentFeatureType == BNA_UNKNOWN)
+          else if ( numField >= NB_MIN_BNA_IDS
+                    && currentFeatureType == BNA_UNKNOWN)
           {
             if (ptrBeginningOfNumber == NULL)
             {
@@ -522,7 +540,8 @@ BNARecord* BNA_GetNextRecord(VSILFILE* f,
         }
         else
         {
-          if (numField < NB_MIN_BNA_IDS || (numField == NB_MIN_BNA_IDS + nbExtraId - 1))
+          if( numField < NB_MIN_BNA_IDS
+              || (numField == NB_MIN_BNA_IDS + nbExtraId - 1) )
           {
             detailedErrorMsg = STRING_EXPECTED;
             goto error;
@@ -560,7 +579,7 @@ BNARecord* BNA_GetNextRecord(VSILFILE* f,
                 detailedErrorMsg = BAD_FLOAT_NUMBER_FORMAT;
                 goto error;
               }
-              dotFound = 1;
+              dotFound = true;
             }
             else if (c == '+' || c == '-')
             {
@@ -569,11 +588,11 @@ BNARecord* BNA_GetNextRecord(VSILFILE* f,
               }
               else if (exponentFound)
               {
-                if (exponentSignFound == 0 && ptrCurLine > ptrBeginLine &&
+                if (!exponentSignFound && ptrCurLine > ptrBeginLine &&
                     (ptrCurLine[-1] == 'e' || ptrCurLine[-1] == 'E' ||
                      ptrCurLine[-1] == 'd' || ptrCurLine[-1] == 'D'))
                 {
-                  exponentSignFound = 1;
+                  exponentSignFound = true;
                 }
                 else
                 {
@@ -591,12 +610,12 @@ BNARecord* BNA_GetNextRecord(VSILFILE* f,
             {
               if (ptrBeginningOfNumber == NULL ||
                   !(ptrCurLine[-1] >= '0' && ptrCurLine[-1] <= '9') ||
-                  exponentFound == 1)
+                  exponentFound )
               {
                 detailedErrorMsg = BAD_FLOAT_NUMBER_FORMAT;
                 goto error;
               }
-              exponentFound = 1;
+              exponentFound = true;
             }
             else
             {
@@ -628,15 +647,15 @@ error:
     {
       if (detailedErrorMsg)
       {
-        CPLError(CE_Failure, CPLE_AppDefined, 
-                "Parsing failed at line %d, at char %d : %s!\n",
-                 *curLine, numChar+1, detailedErrorMsg);
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Parsing failed at line %d, at char %d : %s",
+                  *curLine, numChar+1, detailedErrorMsg );
       }
       else
       {
-        CPLError(CE_Failure, CPLE_AppDefined, 
-                "Parsing failed at line %d, at char %d!\n",
-                 *curLine, numChar+1);
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Parsing failed at line %d, at char %d",
+                  *curLine, numChar+1 );
       }
     }
     BNA_FreeRecord(record);
diff --git a/ogr/ogrsf_frmts/bna/ogrbnaparser.h b/ogr/ogrsf_frmts/bna/ogrbnaparser.h
index b7c63ad..66a3097 100644
--- a/ogr/ogrsf_frmts/bna/ogrbnaparser.h
+++ b/ogr/ogrsf_frmts/bna/ogrbnaparser.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrbnaparser.h 27721 2014-09-22 12:42:28Z goatbar $
+ * $Id: ogrbnaparser.h 31955 2015-12-02 06:07:22Z goatbar $
  *
  * Project:  BNA Parser header
  * Purpose:  Definition of structures, enums and functions of BNA parser
@@ -28,8 +28,8 @@
  ****************************************************************************/
 
 
-#ifndef _OGR_BNA_PARSER_INCLUDED
-#define _OGR_BNA_PARSER_INCLUDED
+#ifndef OGR_BNA_PARSER_INCLUDED
+#define OGR_BNA_PARSER_INCLUDED
 
 #include "cpl_vsi.h"
 
@@ -68,7 +68,7 @@ typedef struct
 /** Get the next BNA record in the file
    @param f open BNA files (VSI Large API handle)
    @param ok (out) set to TRUE if reading was OK (or EOF detected)
-   @param curLine (in/out) incremenet number line
+   @param curLine (in/out) increment number line
    @param verbose if TRUE, errors will be reported
    @param interestFeatureType if BNA_READ_ALL, any BNA feature will be parsed and read in details.
                               if BNA_READ_NONE, no BNA feature will be parsed and read in details.
diff --git a/ogr/ogrsf_frmts/cartodb/drv_cartodb.html b/ogr/ogrsf_frmts/cartodb/drv_cartodb.html
index b501425..784084a 100644
--- a/ogr/ogrsf_frmts/cartodb/drv_cartodb.html
+++ b/ogr/ogrsf_frmts/cartodb/drv_cartodb.html
@@ -126,7 +126,7 @@ can be NULL. Defaults to YES.</li>
 <li> <b>LAUNDER</b>=YES/NO: This may be "YES" to force new fields created on this
 layer to have their field names "laundered" into a form more compatible with
 PostgreSQL.  This converts to lower case and converts some special characters
-like "-" and "#" to "_".  If "NO" exact names are preserved.  
+like "-" and "#" to "_".  If "NO" exact names are preserved.
 The default value is "YES".  If enabled the table (layer) name will also be laundered.</li>
 
 </ul>
diff --git a/ogr/ogrsf_frmts/cartodb/ogr_cartodb.h b/ogr/ogrsf_frmts/cartodb/ogr_cartodb.h
index 1ca38b2..b44b764 100644
--- a/ogr/ogrsf_frmts/cartodb/ogr_cartodb.h
+++ b/ogr/ogrsf_frmts/cartodb/ogr_cartodb.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_cartodb.h 29003 2015-04-25 08:26:30Z rouault $
+ * $Id: ogr_cartodb.h 33647 2016-03-05 16:43:00Z rouault $
  *
  * Project:  CARTODB Translator
  * Purpose:  Definition of classes for OGR CartoDB driver.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_CARTODB_H_INCLUDED
-#define _OGR_CARTODB_H_INCLUDED
+#ifndef OGR_CARTODB_H_INCLUDED
+#define OGR_CARTODB_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "cpl_http.h"
@@ -49,8 +49,8 @@ class OGRCartoDBGeomFieldDefn: public OGRGeomFieldDefn
     public:
         int nSRID;
 
-        OGRCartoDBGeomFieldDefn(const char* pszName, OGRwkbGeometryType eType) :
-                OGRGeomFieldDefn(pszName, eType), nSRID(0)
+        OGRCartoDBGeomFieldDefn(const char* pszNameIn, OGRwkbGeometryType eType) :
+                OGRGeomFieldDefn(pszNameIn, eType), nSRID(0)
         {
         }
 };
@@ -66,7 +66,6 @@ protected:
     OGRCARTODBDataSource* poDS;
 
     OGRFeatureDefn      *poFeatureDefn;
-    OGRSpatialReference *poSRS;
     CPLString            osBaseSQL;
     CPLString            osFIDColName;
 
@@ -94,7 +93,7 @@ protected:
     virtual OGRFeatureDefn *    GetLayerDefn();
     virtual OGRFeatureDefn *    GetLayerDefnInternal(json_object* poObjIn) = 0;
     virtual json_object*        FetchNewFeatures(GIntBig iNext);
-    
+
     virtual const char*         GetFIDColumn() { return osFIDColName.c_str(); }
 
     virtual int                 TestCapability( const char * );
@@ -102,6 +101,12 @@ protected:
     int                         GetFeaturesToFetch() { return atoi(CPLGetConfigOption("CARTODB_PAGE_SIZE", "500")); }
 };
 
+typedef enum
+{
+    INSERT_UNINIT,
+    INSERT_SINGLE_FEATURE,
+    INSERT_MULTIPLE_FEATURE
+} InsertState;
 
 /************************************************************************/
 /*                        OGRCARTODBTableLayer                          */
@@ -116,11 +121,12 @@ class OGRCARTODBTableLayer : public OGRCARTODBLayer
 
     int                 bLaunderColumnNames;
 
-    int                 bInDeferedInsert;
-    CPLString           osDeferedInsertSQL;
+    int                 bInDeferredInsert;
+    InsertState         eDeferredInsertState;
+    CPLString           osDeferredInsertSQL;
     GIntBig             nNextFID;
-    
-    int                 bDeferedCreation;
+
+    int                 bDeferredCreation;
     int                 bCartoDBify;
     int                 nMaxChunkSize;
 
@@ -144,6 +150,8 @@ class OGRCARTODBTableLayer : public OGRCARTODBLayer
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
                                      int bApproxOK = TRUE );
 
+    virtual OGRErr		DeleteField( int iField );
+
     virtual OGRFeature  *GetNextRawFeature();
 
     virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
@@ -159,15 +167,16 @@ class OGRCARTODBTableLayer : public OGRCARTODBLayer
 
     void                SetLaunderFlag( int bFlag )
                                 { bLaunderColumnNames = bFlag; }
-    void                SetDeferedCreation( OGRwkbGeometryType eGType,
+    void                SetDeferredCreation( OGRwkbGeometryType eGType,
                                             OGRSpatialReference* poSRS,
                                             int bGeomNullable,
                                             int bCartoDBify);
-    OGRErr              RunDeferedCreationIfNecessary();
-    int                 GetDeferedCreation() const { return bDeferedCreation; }
-    void                CancelDeferedCreation() { bDeferedCreation = FALSE; }
+    OGRErr              RunDeferredCreationIfNecessary();
+    int                 GetDeferredCreation() const { return bDeferredCreation; }
+    void                CancelDeferredCreation() { bDeferredCreation = FALSE; bCartoDBify = FALSE; }
 
-    void                FlushDeferedInsert();
+    OGRErr              FlushDeferredInsert(bool bReset = true);
+    void                RunDeferredCartoDBfy();
 };
 
 /************************************************************************/
@@ -187,7 +196,7 @@ class OGRCARTODBResultLayer : public OGRCARTODBLayer
 
     virtual OGRFeatureDefn *GetLayerDefnInternal(json_object* poObjIn);
     virtual OGRFeature  *GetNextRawFeature();
-    
+
     int                 IsOK();
 };
 
@@ -210,12 +219,15 @@ class OGRCARTODBDataSource : public OGRDataSource
 
     CPLString           osAPIKey;
 
-    int                 bMustCleanPersistant;
-    
+    int                 bMustCleanPersistent;
+
     CPLString           osCurrentSchema;
-    
+
     int                 bHasOGRMetadataFunction;
 
+    int                 nPostGISMajor;
+    int                 nPostGISMinor;
+
   public:
                         OGRCARTODBDataSource();
                         ~OGRCARTODBDataSource();
@@ -254,11 +266,14 @@ class OGRCARTODBDataSource : public OGRDataSource
     int                         IsAuthenticatedConnection() { return osAPIKey.size() != 0; }
     int                         HasOGRMetadataFunction() { return bHasOGRMetadataFunction; }
     void                        SetOGRMetadataFunction(int bFlag) { bHasOGRMetadataFunction = bFlag; }
-    
+
     OGRLayer *                  ExecuteSQLInternal( const char *pszSQLCommand,
                                                     OGRGeometry *poSpatialFilter = NULL,
                                                     const char *pszDialect = NULL,
-                                                    int bRunDeferedActions = FALSE );
+                                                    int bRunDeferredActions = FALSE );
+
+    int                         GetPostGISMajor() const { return nPostGISMajor; }
+    int                         GetPostGISMinor() const { return nPostGISMinor; }
 };
 
-#endif /* ndef _OGR_CARTODB_H_INCLUDED */
+#endif /* ndef OGR_CARTODB_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/cartodb/ogrcartodbdatasource.cpp b/ogr/ogrsf_frmts/cartodb/ogrcartodbdatasource.cpp
index 138aa5d..1e51176 100644
--- a/ogr/ogrsf_frmts/cartodb/ogrcartodbdatasource.cpp
+++ b/ogr/ogrsf_frmts/cartodb/ogrcartodbdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrcartodbdatasource.cpp 29019 2015-04-25 20:34:19Z rouault $
+ * $Id: ogrcartodbdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  CartoDB Translator
  * Purpose:  Implements OGRCARTODBDataSource class
@@ -30,28 +30,25 @@
 #include "ogr_cartodb.h"
 #include "ogr_pgdump.h"
 
-CPL_CVSID("$Id: ogrcartodbdatasource.cpp 29019 2015-04-25 20:34:19Z rouault $");
+CPL_CVSID("$Id: ogrcartodbdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                        OGRCARTODBDataSource()                        */
 /************************************************************************/
 
-OGRCARTODBDataSource::OGRCARTODBDataSource()
-
-{
-    papoLayers = NULL;
-    nLayers = 0;
-
-    pszName = NULL;
-    pszAccount = NULL;
-
-    bReadWrite = FALSE;
-    bBatchInsert = TRUE;
-    bUseHTTPS = FALSE;
-
-    bMustCleanPersistant = FALSE;
-    bHasOGRMetadataFunction = -1;
-}
+OGRCARTODBDataSource::OGRCARTODBDataSource() :
+    pszName(NULL),
+    pszAccount(NULL),
+    papoLayers(NULL),
+    nLayers(0),
+    bReadWrite(FALSE),
+    bBatchInsert(TRUE),
+    bUseHTTPS(FALSE),
+    bMustCleanPersistent(FALSE),
+    bHasOGRMetadataFunction(-1),
+    nPostGISMajor(2),
+    nPostGISMinor(0)
+{}
 
 /************************************************************************/
 /*                       ~OGRCARTODBDataSource()                        */
@@ -64,11 +61,11 @@ OGRCARTODBDataSource::~OGRCARTODBDataSource()
         delete papoLayers[i];
     CPLFree( papoLayers );
 
-    if (bMustCleanPersistant)
+    if (bMustCleanPersistent)
     {
         char** papszOptions = NULL;
         papszOptions = CSLSetNameValue(papszOptions, "CLOSE_PERSISTENT", CPLSPrintf("CARTODB:%p", this));
-        CPLHTTPFetch( GetAPIURL(), papszOptions);
+        CPLHTTPDestroyResult( CPLHTTPFetch( GetAPIURL(), papszOptions) );
         CSLDestroy(papszOptions);
     }
 
@@ -118,7 +115,7 @@ OGRLayer *OGRCARTODBDataSource::GetLayerByName(const char * pszLayerName)
 /*                     OGRCARTODBGetOptionValue()                       */
 /************************************************************************/
 
-CPLString OGRCARTODBGetOptionValue(const char* pszFilename,
+static CPLString OGRCARTODBGetOptionValue(const char* pszFilename,
                                const char* pszOptionName)
 {
     CPLString osOptionName(pszOptionName);
@@ -139,16 +136,16 @@ CPLString OGRCARTODBGetOptionValue(const char* pszFilename,
 /************************************************************************/
 
 int OGRCARTODBDataSource::Open( const char * pszFilename,
-                                char** papszOpenOptions,
+                                char** papszOpenOptionsIn,
                                 int bUpdateIn )
 
 {
     bReadWrite = bUpdateIn;
-    bBatchInsert = CSLTestBoolean(CSLFetchNameValueDef(papszOpenOptions, "BATCH_INSERT", "YES"));
+    bBatchInsert = CPLTestBool(CSLFetchNameValueDef(papszOpenOptionsIn, "BATCH_INSERT", "YES"));
 
     pszName = CPLStrdup( pszFilename );
-    if( CSLFetchNameValue(papszOpenOptions, "ACCOUNT") )
-        pszAccount = CPLStrdup(CSLFetchNameValue(papszOpenOptions, "ACCOUNT"));
+    if( CSLFetchNameValue(papszOpenOptionsIn, "ACCOUNT") )
+        pszAccount = CPLStrdup(CSLFetchNameValue(papszOpenOptionsIn, "ACCOUNT"));
     else
     {
         pszAccount = CPLStrdup(pszFilename + strlen("CARTODB:"));
@@ -162,11 +159,11 @@ int OGRCARTODBDataSource::Open( const char * pszFilename,
         }
     }
 
-    osAPIKey = CSLFetchNameValueDef(papszOpenOptions, "API_KEY",
+    osAPIKey = CSLFetchNameValueDef(papszOpenOptionsIn, "API_KEY",
                                     CPLGetConfigOption("CARTODB_API_KEY", ""));
 
     CPLString osTables = OGRCARTODBGetOptionValue(pszFilename, "tables");
-    
+
     /*if( osTables.size() == 0 && osAPIKey.size() == 0 )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -174,7 +171,7 @@ int OGRCARTODBDataSource::Open( const char * pszFilename,
         return FALSE;
     }*/
 
-    bUseHTTPS = CSLTestBoolean(CPLGetConfigOption("CARTODB_HTTPS", "YES"));
+    bUseHTTPS = CPLTestBool(CPLGetConfigOption("CARTODB_HTTPS", "YES"));
 
     OGRLayer* poSchemaLayer = ExecuteSQLInternal("SELECT current_schema()");
     if( poSchemaLayer )
@@ -193,6 +190,32 @@ int OGRCARTODBDataSource::Open( const char * pszFilename,
     if( osCurrentSchema.size() == 0 )
         return FALSE;
 
+/* -------------------------------------------------------------------- */
+/*      Find out PostGIS version                                        */
+/* -------------------------------------------------------------------- */
+    if( bReadWrite )
+    {
+        OGRLayer* poPostGISVersionLayer = ExecuteSQLInternal("SELECT postgis_version()");
+        if( poPostGISVersionLayer )
+        {
+            OGRFeature* poFeat = poPostGISVersionLayer->GetNextFeature();
+            if( poFeat )
+            {
+                if( poFeat->GetFieldCount() == 1 )
+                {
+                    const char* pszVersion = poFeat->GetFieldAsString(0);
+                    nPostGISMajor = atoi(pszVersion);
+                    const char* pszDot = strchr(pszVersion, '.');
+                    nPostGISMinor = 0;
+                    if( pszDot )
+                        nPostGISMinor = atoi(pszDot + 1);
+                }
+                delete poFeat;
+            }
+            ReleaseResultSet(poPostGISVersionLayer);
+        }
+    }
+
     if( osAPIKey.size() && bUpdateIn )
     {
         ExecuteSQLInternal(
@@ -225,7 +248,7 @@ int OGRCARTODBDataSource::Open( const char * pszFilename,
                 "ORDER BY a.attnum "
                 "$$ LANGUAGE SQL");
     }
-    
+
     if (osTables.size() != 0)
     {
         char** papszTables = CSLTokenizeString2(osTables, ",", 0);
@@ -365,7 +388,7 @@ int OGRCARTODBDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 /*                          ICreateLayer()                              */
 /************************************************************************/
 
-OGRLayer   *OGRCARTODBDataSource::ICreateLayer( const char *pszName,
+OGRLayer   *OGRCARTODBDataSource::ICreateLayer( const char *pszNameIn,
                                            OGRSpatialReference *poSpatialRef,
                                            OGRwkbGeometryType eGType,
                                            char ** papszOptions )
@@ -384,7 +407,7 @@ OGRLayer   *OGRCARTODBDataSource::ICreateLayer( const char *pszName,
 
     for( iLayer = 0; iLayer < nLayers; iLayer++ )
     {
-        if( EQUAL(pszName,papoLayers[iLayer]->GetName()) )
+        if( EQUAL(pszNameIn,papoLayers[iLayer]->GetName()) )
         {
             if( CSLFetchNameValue( papszOptions, "OVERWRITE" ) != NULL
                 && !EQUAL(CSLFetchNameValue(papszOptions,"OVERWRITE"),"NO") )
@@ -397,26 +420,43 @@ OGRLayer   *OGRCARTODBDataSource::ICreateLayer( const char *pszName,
                           "Layer %s already exists, CreateLayer failed.\n"
                           "Use the layer creation option OVERWRITE=YES to "
                           "replace it.",
-                          pszName );
+                          pszNameIn );
                 return NULL;
             }
         }
     }
-    
-    CPLString osName(pszName);
+
+    CPLString osName(pszNameIn);
     if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) )
     {
-        char* pszTmp = OGRPGCommonLaunderName(pszName);
+        char* pszTmp = OGRPGCommonLaunderName(pszNameIn);
         osName = pszTmp;
         CPLFree(pszTmp);
     }
 
+
     OGRCARTODBTableLayer* poLayer = new OGRCARTODBTableLayer(this, osName);
     int bGeomNullable = CSLFetchBoolean(papszOptions, "GEOMETRY_NULLABLE", TRUE);
+    int nSRID = (poSpatialRef && eGType != wkbNone) ? FetchSRSId( poSpatialRef ) : 0;
     int bCartoDBify = CSLFetchBoolean(papszOptions, "CARTODBFY",
-                                      CSLFetchBoolean(papszOptions, "CARTODBIFY", TRUE));
+                                      CSLFetchBoolean(papszOptions, "CARTODBIFY",
+                                      TRUE));
+    if( bCartoDBify )
+    {
+        if( nSRID != 4326 )
+        {
+            if( eGType != wkbNone )
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                        "Cannot register table in dashboard with "
+                        "cdb_cartodbfytable() since its SRS is not EPSG:4326");
+            }
+            bCartoDBify = FALSE;
+        }
+    }
+
     poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) );
-    poLayer->SetDeferedCreation(eGType, poSpatialRef, bGeomNullable, bCartoDBify);
+    poLayer->SetDeferredCreation(eGType, poSpatialRef, bGeomNullable, bCartoDBify);
     papoLayers = (OGRCARTODBTableLayer**) CPLRealloc(
                     papoLayers, (nLayers + 1) * sizeof(OGRCARTODBTableLayer*));
     papoLayers[nLayers ++] = poLayer;
@@ -453,8 +493,8 @@ OGRErr OGRCARTODBDataSource::DeleteLayer(int iLayer)
 
     CPLDebug( "CARTODB", "DeleteLayer(%s)", osLayerName.c_str() );
 
-    int bDeferedCreation = papoLayers[iLayer]->GetDeferedCreation();
-    papoLayers[iLayer]->CancelDeferedCreation();
+    int bDeferredCreation = papoLayers[iLayer]->GetDeferredCreation();
+    papoLayers[iLayer]->CancelDeferredCreation();
     delete papoLayers[iLayer];
     memmove( papoLayers + iLayer, papoLayers + iLayer + 1,
              sizeof(void *) * (nLayers - iLayer - 1) );
@@ -463,7 +503,7 @@ OGRErr OGRCARTODBDataSource::DeleteLayer(int iLayer)
     if (osLayerName.size() == 0)
         return OGRERR_NONE;
 
-    if( !bDeferedCreation )
+    if( !bDeferredCreation )
     {
         CPLString osSQL;
         osSQL.Printf("DROP TABLE %s",
@@ -484,7 +524,7 @@ OGRErr OGRCARTODBDataSource::DeleteLayer(int iLayer)
 
 char** OGRCARTODBDataSource::AddHTTPOptions()
 {
-    bMustCleanPersistant = TRUE;
+    bMustCleanPersistent = TRUE;
 
     return CSLAddString(NULL, CPLSPrintf("PERSISTENT=CARTODB:%p", this));
 }
@@ -520,30 +560,34 @@ json_object* OGRCARTODBDataSource::RunSQL(const char* pszUnescapedSQL)
 /* -------------------------------------------------------------------- */
     const char* pszAPIURL = GetAPIURL();
     char** papszOptions = CSLAddString(
-        strncmp(pszAPIURL, "/vsimem/", strlen("/vsimem/")) != 0 ? AddHTTPOptions(): NULL, osSQL);
+        !STARTS_WITH(pszAPIURL, "/vsimem/") ? AddHTTPOptions(): NULL, osSQL);
     CPLHTTPResult * psResult = CPLHTTPFetch( GetAPIURL(), papszOptions);
     CSLDestroy(papszOptions);
+    if( psResult == NULL )
+        return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Check for some error conditions and report.  HTML Messages      */
 /*      are transformed info failure.                                   */
 /* -------------------------------------------------------------------- */
-    if (psResult && psResult->pszContentType &&
-        strncmp(psResult->pszContentType, "text/html", 9) == 0)
+    if (psResult->pszContentType &&
+        STARTS_WITH(psResult->pszContentType, "text/html"))
     {
         CPLDebug( "CARTODB", "RunSQL HTML Response:%s", psResult->pabyData );
-        CPLError(CE_Failure, CPLE_AppDefined, 
+        CPLError(CE_Failure, CPLE_AppDefined,
                  "HTML error page returned by server");
         CPLHTTPDestroyResult(psResult);
         return NULL;
     }
-    if (psResult && psResult->pszErrBuf != NULL) 
+    if (psResult->pszErrBuf != NULL)
     {
-        CPLDebug( "CARTODB", "RunSQL Error Message:%s", psResult->pszErrBuf );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "RunSQL Error Message:%s", psResult->pszErrBuf );
     }
-    else if (psResult && psResult->nStatus != 0) 
+    else if (psResult->nStatus != 0)
     {
-        CPLDebug( "CARTODB", "RunSQL Error Status:%d", psResult->nStatus );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "RunSQL Error Status:%d", psResult->nStatus );
     }
 
     if( psResult->pabyData == NULL )
@@ -551,10 +595,10 @@ json_object* OGRCARTODBDataSource::RunSQL(const char* pszUnescapedSQL)
         CPLHTTPDestroyResult(psResult);
         return NULL;
     }
-    
+
     if( strlen((const char*)psResult->pabyData) < 1000 )
         CPLDebug( "CARTODB", "RunSQL Response:%s", psResult->pabyData );
-    
+
     json_tokener* jstok = NULL;
     json_object* poObj = NULL;
 
@@ -584,7 +628,7 @@ json_object* OGRCARTODBDataSource::RunSQL(const char* pszUnescapedSQL)
                 poError = json_object_array_get_idx(poError, 0);
                 if( poError != NULL && json_object_get_type(poError) == json_type_string )
                 {
-                    CPLError(CE_Failure, CPLE_AppDefined, 
+                    CPLError(CE_Failure, CPLE_AppDefined,
                             "Error returned by server : %s", json_object_get_string(poError));
                     json_object_put(poObj);
                     return NULL;
@@ -645,15 +689,16 @@ OGRLayer * OGRCARTODBDataSource::ExecuteSQL( const char *pszSQLCommand,
 OGRLayer * OGRCARTODBDataSource::ExecuteSQLInternal( const char *pszSQLCommand,
                                                      OGRGeometry *poSpatialFilter,
                                                      const char *pszDialect,
-                                                     int bRunDeferedActions )
+                                                     int bRunDeferredActions )
 
 {
-    if( bRunDeferedActions )
+    if( bRunDeferredActions )
     {
         for( int iLayer = 0; iLayer < nLayers; iLayer++ )
         {
-            papoLayers[iLayer]->RunDeferedCreationIfNecessary();
-            papoLayers[iLayer]->FlushDeferedInsert();
+            papoLayers[iLayer]->RunDeferredCreationIfNecessary();
+            CPL_IGNORE_RET_VAL(papoLayers[iLayer]->FlushDeferredInsert());
+            papoLayers[iLayer]->RunDeferredCartoDBfy();
         }
     }
 
@@ -672,16 +717,16 @@ OGRLayer * OGRCARTODBDataSource::ExecuteSQLInternal( const char *pszSQLCommand,
 /* -------------------------------------------------------------------- */
 /*      Special case DELLAYER: command.                                 */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszSQLCommand,"DELLAYER:",9) )
+    if( STARTS_WITH_CI(pszSQLCommand, "DELLAYER:") )
     {
         const char *pszLayerName = pszSQLCommand + 9;
 
         while( *pszLayerName == ' ' )
             pszLayerName++;
-        
+
         for( int iLayer = 0; iLayer < nLayers; iLayer++ )
         {
-            if( EQUAL(papoLayers[iLayer]->GetName(), 
+            if( EQUAL(papoLayers[iLayer]->GetName(),
                       pszLayerName ))
             {
                 DeleteLayer( iLayer );
@@ -690,10 +735,10 @@ OGRLayer * OGRCARTODBDataSource::ExecuteSQLInternal( const char *pszSQLCommand,
         }
         return NULL;
     }
-    
-    if( !EQUALN(pszSQLCommand, "SELECT", strlen("SELECT")) &&
-        !EQUALN(pszSQLCommand, "EXPLAIN", strlen("EXPLAIN")) &&
-        !EQUALN(pszSQLCommand, "WITH", strlen("WITH")) )
+
+    if( !STARTS_WITH_CI(pszSQLCommand, "SELECT") &&
+        !STARTS_WITH_CI(pszSQLCommand, "EXPLAIN") &&
+        !STARTS_WITH_CI(pszSQLCommand, "WITH") )
     {
         RunSQL(pszSQLCommand);
         return NULL;
diff --git a/ogr/ogrsf_frmts/cartodb/ogrcartodbdriver.cpp b/ogr/ogrsf_frmts/cartodb/ogrcartodbdriver.cpp
index b15d8ea..79a9232 100644
--- a/ogr/ogrsf_frmts/cartodb/ogrcartodbdriver.cpp
+++ b/ogr/ogrsf_frmts/cartodb/ogrcartodbdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrcartodbdriver.cpp 29019 2015-04-25 20:34:19Z rouault $
+ * $Id: ogrcartodbdriver.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  CartoDB Translator
  * Purpose:  Implements OGRCARTODBDriver.
@@ -29,9 +29,9 @@
 
 #include "ogr_cartodb.h"
 
-// g++ -g -Wall -fPIC -shared -o ogr_CARTODB.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/cartodb ogr/ogrsf_frmts/cartodb/*.c* -L. -lgdal -Iogr/ogrsf_frmts/geojson/libjson 
+// g++ -g -Wall -fPIC -shared -o ogr_CARTODB.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/cartodb ogr/ogrsf_frmts/cartodb/*.c* -L. -lgdal -Iogr/ogrsf_frmts/geojson/libjson
 
-CPL_CVSID("$Id: ogrcartodbdriver.cpp 29019 2015-04-25 20:34:19Z rouault $");
+CPL_CVSID("$Id: ogrcartodbdriver.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 extern "C" void RegisterOGRCartoDB();
 
@@ -41,7 +41,7 @@ extern "C" void RegisterOGRCartoDB();
 
 static int OGRCartoDBDriverIdentify( GDALOpenInfo* poOpenInfo )
 {
-    return EQUALN(poOpenInfo->pszFilename, "CARTODB:", strlen("CARTODB:"));
+    return STARTS_WITH_CI(poOpenInfo->pszFilename, "CARTODB:");
 }
 
 /************************************************************************/
@@ -83,7 +83,7 @@ static GDALDataset *OGRCartoDBDriverCreate( const char * pszName,
     if( !poDS->Open( pszName, NULL, TRUE ) )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "CartoDB driver doesn't support database creation." );
         return NULL;
     }
@@ -98,46 +98,45 @@ static GDALDataset *OGRCartoDBDriverCreate( const char * pszName,
 void RegisterOGRCartoDB()
 
 {
-    if( GDALGetDriverByName( "CartoDB" ) == NULL )
-    {
-        GDALDriver* poDriver = new GDALDriver();
+    if( GDALGetDriverByName( "CartoDB" ) != NULL )
+      return;
+
+    GDALDriver* poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "CartoDB" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+    poDriver->SetDescription( "CartoDB" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
                                   "CartoDB" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
                                     "drv_cartodb.html" );
 
-        poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, "CARTODB:" );
+    poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, "CARTODB:" );
 
-        poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
     "<OpenOptionList>"
     "  <Option name='API_KEY' type='string' description='Account API key'/>"
     "  <Option name='ACCOUNT' type='string' description='Account name' required='true'/>"
     "  <Option name='BATCH_INSERT' type='boolean' description='Whether to group features to be inserted in a batch' default='YES'/>"
     "</OpenOptionList>");
 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, "<CreationOptionList/>");
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, "<CreationOptionList/>");
 
-        poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
     "<LayerCreationOptionList>"
     "  <Option name='OVERWRITE' type='boolean' description='Whether to overwrite an existing table with the layer name to be created' default='NO'/>"
     "  <Option name='LAUNDER' type='boolean' description='Whether layer and field names will be laundered' default='YES'/>"
     "  <Option name='GEOMETRY_NULLABLE' type='boolean' description='Whether the values of the geometry column can be NULL' default='YES'/>"
     "  <Option name='CARTODBFY' alias='CARTODBIFY' type='boolean' description='Whether the created layer should be \"CartoDBifi'ed\" (i.e. registered in dashboard)' default='YES'/>"
     "</LayerCreationOptionList>");
-        
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES, "Integer Integer64 Real String Date DateTime Time" );
-        poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_FIELDS, "YES" );
-        poDriver->SetMetadataItem( GDAL_DCAP_DEFAULT_FIELDS, "YES" );
-        poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_GEOMFIELDS, "YES" );
 
-        poDriver->pfnOpen = OGRCartoDBDriverOpen;
-        poDriver->pfnIdentify = OGRCartoDBDriverIdentify;
-        poDriver->pfnCreate = OGRCartoDBDriverCreate;
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES, "Integer Integer64 Real String Date DateTime Time" );
+    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_FIELDS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_DEFAULT_FIELDS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_GEOMFIELDS, "YES" );
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
-}
+    poDriver->pfnOpen = OGRCartoDBDriverOpen;
+    poDriver->pfnIdentify = OGRCartoDBDriverIdentify;
+    poDriver->pfnCreate = OGRCartoDBDriverCreate;
 
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/ogr/ogrsf_frmts/cartodb/ogrcartodblayer.cpp b/ogr/ogrsf_frmts/cartodb/ogrcartodblayer.cpp
index c72f1c4..7d0791b 100644
--- a/ogr/ogrsf_frmts/cartodb/ogrcartodblayer.cpp
+++ b/ogr/ogrsf_frmts/cartodb/ogrcartodblayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrcartodblayer.cpp 29000 2015-04-24 21:46:17Z rouault $
+ * $Id: ogrcartodblayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  CartoDB Translator
  * Purpose:  Implements OGRCARTODBLayer class.
@@ -30,23 +30,17 @@
 #include "ogr_cartodb.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrcartodblayer.cpp 29000 2015-04-24 21:46:17Z rouault $");
+CPL_CVSID("$Id: ogrcartodblayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                         OGRCARTODBLayer()                            */
 /************************************************************************/
 
-OGRCARTODBLayer::OGRCARTODBLayer(OGRCARTODBDataSource* poDS)
-
+OGRCARTODBLayer::OGRCARTODBLayer(OGRCARTODBDataSource* poDSIn) :
+    poDS(poDSIn),
+    poFeatureDefn(NULL),
+    poCachedObj(NULL)
 {
-    this->poDS = poDS;
-
-    poSRS = NULL;
-
-    poFeatureDefn = NULL;
-    
-    poCachedObj = NULL;
-
     ResetReading();
 }
 
@@ -60,9 +54,6 @@ OGRCARTODBLayer::~OGRCARTODBLayer()
     if( poCachedObj != NULL )
         json_object_put(poCachedObj);
 
-    if( poSRS != NULL )
-        poSRS->Release();
-
     if( poFeatureDefn != NULL )
         poFeatureDefn->Release();
 }
@@ -102,6 +93,7 @@ OGRFeature *OGRCARTODBLayer::BuildFeature(json_object* poRowObj)
     if( poRowObj != NULL &&
         json_object_get_type(poRowObj) == json_type_object )
     {
+        //CPLDebug("CartoDB", "Row: %s", json_object_to_json_string(poRowObj));
         poFeature = new OGRFeature(poFeatureDefn);
 
         if( osFIDColName.size() )
@@ -175,7 +167,7 @@ OGRFeature *OGRCARTODBLayer::BuildFeature(json_object* poRowObj)
 /*                        FetchNewFeatures()                            */
 /************************************************************************/
 
-json_object* OGRCARTODBLayer::FetchNewFeatures(GIntBig iNext)
+json_object* OGRCARTODBLayer::FetchNewFeatures(GIntBig iNextIn)
 {
     CPLString osSQL = osBaseSQL;
     if( osSQL.ifind("SELECT") != std::string::npos &&
@@ -184,7 +176,7 @@ json_object* OGRCARTODBLayer::FetchNewFeatures(GIntBig iNext)
         osSQL += " LIMIT ";
         osSQL += CPLSPrintf("%d", GetFeaturesToFetch());
         osSQL += " OFFSET ";
-        osSQL += CPLSPrintf(CPL_FRMT_GIB, iNext);
+        osSQL += CPLSPrintf(CPL_FRMT_GIB, iNextIn);
     }
     return poDS->RunSQL(osSQL);
 }
@@ -195,7 +187,7 @@ json_object* OGRCARTODBLayer::FetchNewFeatures(GIntBig iNext)
 
 OGRFeature *OGRCARTODBLayer::GetNextRawFeature()
 {
-    if( bEOF ) 
+    if( bEOF )
         return NULL;
 
     if( iNextInFetchedObjects >= nFetchedObjects )
@@ -260,7 +252,7 @@ OGRFeature *OGRCARTODBLayer::GetNextFeature()
 {
     OGRFeature  *poFeature;
 
-    while(TRUE)
+    while( true )
     {
         poFeature = GetNextRawFeature();
         if (poFeature == NULL)
@@ -382,12 +374,12 @@ void OGRCARTODBLayer::EstablishLayerDefn(const char* pszLayerName,
                         OGRCartoDBGeomFieldDefn *poFieldDefn =
                             new OGRCartoDBGeomFieldDefn(pszColName, wkbUnknown);
                         poFeatureDefn->AddGeomFieldDefn(poFieldDefn, FALSE);
-                        OGRSpatialReference* poSRS = GetSRS(pszColName, &poFieldDefn->nSRID);
-                        if( poSRS != NULL )
+                        OGRSpatialReference* l_poSRS = GetSRS(pszColName, &poFieldDefn->nSRID);
+                        if( l_poSRS != NULL )
                         {
                             poFeatureDefn->GetGeomFieldDefn(
-                                poFeatureDefn->GetGeomFieldCount() - 1)->SetSpatialRef(poSRS);
-                            poSRS->Release();
+                                poFeatureDefn->GetGeomFieldCount() - 1)->SetSpatialRef(l_poSRS);
+                            l_poSRS->Release();
                         }
                     }
                 }
@@ -410,12 +402,12 @@ void OGRCARTODBLayer::EstablishLayerDefn(const char* pszLayerName,
                 OGRCartoDBGeomFieldDefn *poFieldDefn =
                     new OGRCartoDBGeomFieldDefn(pszColName, wkbUnknown);
                 poFeatureDefn->AddGeomFieldDefn(poFieldDefn, FALSE);
-                OGRSpatialReference* poSRS = GetSRS(pszColName, &poFieldDefn->nSRID);
-                if( poSRS != NULL )
+                OGRSpatialReference* l_poSRS = GetSRS(pszColName, &poFieldDefn->nSRID);
+                if( l_poSRS != NULL )
                 {
                     poFeatureDefn->GetGeomFieldDefn(
-                        poFeatureDefn->GetGeomFieldCount() - 1)->SetSpatialRef(poSRS);
-                    poSRS->Release();
+                        poFeatureDefn->GetGeomFieldCount() - 1)->SetSpatialRef(l_poSRS);
+                    l_poSRS->Release();
                 }
             }
         }
@@ -447,19 +439,19 @@ OGRSpatialReference* OGRCARTODBLayer::GetSRS(const char* pszGeomCol,
     }
 
     json_object* poSRTEXT = json_object_object_get(poRowObj, "srtext");
-    OGRSpatialReference* poSRS = NULL;
+    OGRSpatialReference* l_poSRS = NULL;
     if( poSRTEXT != NULL && json_object_get_type(poSRTEXT) == json_type_string )
     {
         const char* pszSRTEXT = json_object_get_string(poSRTEXT);
-        poSRS = new OGRSpatialReference();
+        l_poSRS = new OGRSpatialReference();
         char* pszTmp = (char* )pszSRTEXT;
-        if( poSRS->importFromWkt(&pszTmp) != OGRERR_NONE )
+        if( l_poSRS->importFromWkt(&pszTmp) != OGRERR_NONE )
         {
-            delete poSRS;
-            poSRS = NULL;
+            delete l_poSRS;
+            l_poSRS = NULL;
         }
     }
     json_object_put(poObj);
 
-    return poSRS;
+    return l_poSRS;
 }
diff --git a/ogr/ogrsf_frmts/cartodb/ogrcartodbresultlayer.cpp b/ogr/ogrsf_frmts/cartodb/ogrcartodbresultlayer.cpp
index 8440fa0..bb26d49 100644
--- a/ogr/ogrsf_frmts/cartodb/ogrcartodbresultlayer.cpp
+++ b/ogr/ogrsf_frmts/cartodb/ogrcartodbresultlayer.cpp
@@ -35,13 +35,13 @@ CPL_CVSID("$Id");
 /*                          OGRCARTODBResultLayer()                     */
 /************************************************************************/
 
-OGRCARTODBResultLayer::OGRCARTODBResultLayer( OGRCARTODBDataSource* poDS,
+OGRCARTODBResultLayer::OGRCARTODBResultLayer( OGRCARTODBDataSource* poDSIn,
                                               const char * pszRawQueryIn ) :
-                                              OGRCARTODBLayer(poDS)
+    OGRCARTODBLayer(poDSIn),
+    poFirstFeature(NULL)
 {
     osBaseSQL = pszRawQueryIn;
     SetDescription( "result" );
-    poFirstFeature = NULL;
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/cartodb/ogrcartodbtablelayer.cpp b/ogr/ogrsf_frmts/cartodb/ogrcartodbtablelayer.cpp
index 45bff30..ed44984 100644
--- a/ogr/ogrsf_frmts/cartodb/ogrcartodbtablelayer.cpp
+++ b/ogr/ogrsf_frmts/cartodb/ogrcartodbtablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrcartodbtablelayer.cpp 30281 2015-09-11 15:17:03Z rouault $
+ * $Id: ogrcartodbtablelayer.cpp 33647 2016-03-05 16:43:00Z rouault $
  *
  * Project:  CartoDB Translator
  * Purpose:  Implements OGRCARTODBTableLayer class.
@@ -31,7 +31,7 @@
 #include "ogr_p.h"
 #include "ogr_pgdump.h"
 
-CPL_CVSID("$Id: ogrcartodbtablelayer.cpp 30281 2015-09-11 15:17:03Z rouault $");
+CPL_CVSID("$Id: ogrcartodbtablelayer.cpp 33647 2016-03-05 16:43:00Z rouault $");
 
 /************************************************************************/
 /*                    OGRCARTODBEscapeIdentifier( )                     */
@@ -79,17 +79,18 @@ CPLString OGRCARTODBEscapeLiteral(const char* pszStr)
 /*                        OGRCARTODBTableLayer()                        */
 /************************************************************************/
 
-OGRCARTODBTableLayer::OGRCARTODBTableLayer(OGRCARTODBDataSource* poDS,
+OGRCARTODBTableLayer::OGRCARTODBTableLayer(OGRCARTODBDataSource* poDSIn,
                                            const char* pszName) :
-                                           OGRCARTODBLayer(poDS)
+                                           OGRCARTODBLayer(poDSIn)
 
 {
     osName = pszName;
     SetDescription( osName );
     bLaunderColumnNames = TRUE;
-    bInDeferedInsert = poDS->DoBatchInsert();
+    bInDeferredInsert = poDS->DoBatchInsert();
+    eDeferredInsertState = INSERT_UNINIT;
     nNextFID = -1;
-    bDeferedCreation = FALSE;
+    bDeferredCreation = FALSE;
     bCartoDBify = FALSE;
     nMaxChunkSize = atoi(CPLGetConfigOption("CARTODB_MAX_CHUNK_SIZE", "15")) * 1024 * 1024;
 }
@@ -101,8 +102,9 @@ OGRCARTODBTableLayer::OGRCARTODBTableLayer(OGRCARTODBDataSource* poDS,
 OGRCARTODBTableLayer::~OGRCARTODBTableLayer()
 
 {
-    if( bDeferedCreation ) RunDeferedCreationIfNecessary();
-    FlushDeferedInsert();
+    if( bDeferredCreation ) RunDeferredCreationIfNecessary();
+    CPL_IGNORE_RET_VAL(FlushDeferredInsert());
+    RunDeferredCartoDBfy();
 }
 
 /************************************************************************/
@@ -229,20 +231,20 @@ OGRFeatureDefn * OGRCARTODBTableLayer::GetLayerDefnInternal(CPL_UNUSED json_obje
                             new OGRCartoDBGeomFieldDefn(pszAttname, eType);
                         if( bNotNull )
                             poFieldDefn->SetNullable(FALSE);
-                        OGRSpatialReference* poSRS = NULL;
+                        OGRSpatialReference* l_poSRS = NULL;
                         if( pszSRText != NULL )
                         {
-                            poSRS = new OGRSpatialReference();
+                            l_poSRS = new OGRSpatialReference();
                             char* pszTmp = (char* )pszSRText;
-                            if( poSRS->importFromWkt(&pszTmp) != OGRERR_NONE )
+                            if( l_poSRS->importFromWkt(&pszTmp) != OGRERR_NONE )
                             {
-                                delete poSRS;
-                                poSRS = NULL;
+                                delete l_poSRS;
+                                l_poSRS = NULL;
                             }
-                            if( poSRS != NULL )
+                            if( l_poSRS != NULL )
                             {
-                                poFieldDefn->SetSpatialRef(poSRS);
-                                poSRS->Release();
+                                poFieldDefn->SetSpatialRef(l_poSRS);
+                                l_poSRS->Release();
                             }
                         }
                         poFieldDefn->nSRID = nSRID;
@@ -309,7 +311,7 @@ OGRFeatureDefn * OGRCARTODBTableLayer::GetLayerDefnInternal(CPL_UNUSED json_obje
 /*                        FetchNewFeatures()                            */
 /************************************************************************/
 
-json_object* OGRCARTODBTableLayer::FetchNewFeatures(GIntBig iNext)
+json_object* OGRCARTODBTableLayer::FetchNewFeatures(GIntBig iNextIn)
 {
     if( osFIDColName.size() > 0 )
     {
@@ -324,7 +326,7 @@ json_object* OGRCARTODBTableLayer::FetchNewFeatures(GIntBig iNext)
         return poDS->RunSQL(osSQL);
     }
     else
-        return OGRCARTODBLayer::FetchNewFeatures(iNext);
+        return OGRCARTODBLayer::FetchNewFeatures(iNextIn);
 }
 
 /************************************************************************/
@@ -333,9 +335,10 @@ json_object* OGRCARTODBTableLayer::FetchNewFeatures(GIntBig iNext)
 
 OGRFeature  *OGRCARTODBTableLayer::GetNextRawFeature()
 {
-    if( bDeferedCreation && RunDeferedCreationIfNecessary() != OGRERR_NONE )
+    if( bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
+        return NULL;
+    if( FlushDeferredInsert() != OGRERR_NONE )
         return NULL;
-    FlushDeferedInsert();
     return OGRCARTODBLayer::GetNextRawFeature();
 }
 
@@ -392,25 +395,69 @@ void OGRCARTODBTableLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poGeo
 }
 
 /************************************************************************/
-/*                         FlushDeferedInsert()                          */
+/*                         RunDeferredCartoDBfy()                         */
 /************************************************************************/
 
-void OGRCARTODBTableLayer::FlushDeferedInsert()
+
+void OGRCARTODBTableLayer::RunDeferredCartoDBfy()
 
 {
-    if( bInDeferedInsert && osDeferedInsertSQL.size() > 0 )
+    if( bCartoDBify )
     {
-        osDeferedInsertSQL = "BEGIN;" + osDeferedInsertSQL + "COMMIT;";
-        json_object* poObj = poDS->RunSQL(osDeferedInsertSQL);
+        bCartoDBify = FALSE;
+
+        CPLString osSQL;
+        if( poDS->GetCurrentSchema() == "public" )
+            osSQL.Printf("SELECT cdb_cartodbfytable('%s')",
+                                OGRCARTODBEscapeLiteral(osName).c_str());
+        else
+            osSQL.Printf("SELECT cdb_cartodbfytable('%s', '%s')",
+                                OGRCARTODBEscapeLiteral(poDS->GetCurrentSchema()).c_str(),
+                                OGRCARTODBEscapeLiteral(osName).c_str());
+
+        json_object* poObj = poDS->RunSQL(osSQL);
+        if( poObj != NULL )
+            json_object_put(poObj);
+    }
+}
+
+/************************************************************************/
+/*                         FlushDeferredInsert()                         */
+/************************************************************************/
+
+OGRErr OGRCARTODBTableLayer::FlushDeferredInsert(bool bReset)
+
+{
+    OGRErr eErr = OGRERR_NONE;
+    if( bInDeferredInsert && osDeferredInsertSQL.size() > 0 )
+    {
+        osDeferredInsertSQL = "BEGIN;" + osDeferredInsertSQL;
+        if( eDeferredInsertState == INSERT_MULTIPLE_FEATURE )
+        {
+            osDeferredInsertSQL += ";";
+            eDeferredInsertState = INSERT_UNINIT;
+        }
+        osDeferredInsertSQL += "COMMIT;";
+
+        json_object* poObj = poDS->RunSQL(osDeferredInsertSQL);
         if( poObj != NULL )
         {
             json_object_put(poObj);
         }
+        else
+        {
+            bInDeferredInsert = FALSE;
+            eErr = OGRERR_FAILURE;
+        }
     }
 
-    bInDeferedInsert = FALSE;
-    osDeferedInsertSQL = "";
-    nNextFID = -1;
+    osDeferredInsertSQL = "";
+    if( bReset )
+    {
+        bInDeferredInsert = FALSE;
+        nNextFID = -1;
+    }
+    return eErr;
 }
 
 /************************************************************************/
@@ -429,6 +476,12 @@ OGRErr OGRCARTODBTableLayer::CreateField( OGRFieldDefn *poFieldIn,
         return OGRERR_FAILURE;
     }
 
+    if( eDeferredInsertState == INSERT_MULTIPLE_FEATURE )
+    {
+        if( FlushDeferredInsert() != OGRERR_NONE )
+            return OGRERR_FAILURE;
+    }
+
     OGRFieldDefn oField(poFieldIn);
     if( bLaunderColumnNames )
     {
@@ -441,7 +494,7 @@ OGRErr OGRCARTODBTableLayer::CreateField( OGRFieldDefn *poFieldIn,
 /*      Create the new field.                                           */
 /* -------------------------------------------------------------------- */
 
-    if( !bDeferedCreation )
+    if( !bDeferredCreation )
     {
         CPLString osSQL;
         osSQL.Printf( "ALTER TABLE %s ADD COLUMN %s %s",
@@ -468,6 +521,50 @@ OGRErr OGRCARTODBTableLayer::CreateField( OGRFieldDefn *poFieldIn,
 }
 
 /************************************************************************/
+/*                            DeleteField()                             */
+/************************************************************************/
+
+OGRErr OGRCARTODBTableLayer::DeleteField( int iField )
+{
+    CPLString           osSQL;
+
+    if (!poDS->IsReadWrite())
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Operation not available in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
+    if (iField < 0 || iField >= poFeatureDefn->GetFieldCount())
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Invalid field index");
+        return OGRERR_FAILURE;
+    }
+
+    if( eDeferredInsertState == INSERT_MULTIPLE_FEATURE )
+    {
+        if( FlushDeferredInsert() != OGRERR_NONE )
+            return OGRERR_FAILURE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Drop the field.                                                 */
+/* -------------------------------------------------------------------- */
+
+    osSQL.Printf( "ALTER TABLE %s DROP COLUMN %s",
+                  OGRCARTODBEscapeIdentifier(osName).c_str(),
+                  OGRCARTODBEscapeIdentifier(poFeatureDefn->GetFieldDefn(iField)->GetNameRef()).c_str() );
+
+    json_object* poObj = poDS->RunSQL(osSQL);
+    if( poObj == NULL )
+        return OGRERR_FAILURE;
+    json_object_put(poObj);
+
+    return poFeatureDefn->DeleteFieldDefn( iField );
+}
+
+/************************************************************************/
 /*                           ICreateFeature()                            */
 /************************************************************************/
 
@@ -476,9 +573,9 @@ OGRErr OGRCARTODBTableLayer::ICreateFeature( OGRFeature *poFeature )
 {
     int i;
 
-    if( bDeferedCreation )
+    if( bDeferredCreation )
     {
-        if( RunDeferedCreationIfNecessary() != OGRERR_NONE )
+        if( RunDeferredCreationIfNecessary() != OGRERR_NONE )
             return OGRERR_FAILURE;
     }
 
@@ -497,7 +594,7 @@ OGRErr OGRCARTODBTableLayer::ICreateFeature( OGRFeature *poFeature )
     CPLString osSQL;
 
     int bHasJustGotNextFID = FALSE;
-    if( !bHasUserFieldMatchingFID && bInDeferedInsert && nNextFID < 0 && osFIDColName.size() )
+    if( !bHasUserFieldMatchingFID && bInDeferredInsert && nNextFID < 0 && osFIDColName.size() )
     {
         osSQL.Printf("SELECT nextval('%s') AS nextid",
                      OGRCARTODBEscapeLiteral(CPLSPrintf("%s_%s_seq", osName.c_str(), osFIDColName.c_str())).c_str());
@@ -518,71 +615,128 @@ OGRErr OGRCARTODBTableLayer::ICreateFeature( OGRFeature *poFeature )
             json_object_put(poObj);
     }
 
-    osSQL.Printf("INSERT INTO %s ", OGRCARTODBEscapeIdentifier(osName).c_str());
-    int bMustComma = FALSE;
-    for(i = 0; i < poFeatureDefn->GetFieldCount(); i++)
+    // Check if we can go on with multiple insertion mode
+    if( eDeferredInsertState == INSERT_MULTIPLE_FEATURE )
     {
-        if( !poFeature->IsFieldSet(i) )
-            continue;
+        if( !bHasUserFieldMatchingFID && osFIDColName.size() &&
+            (poFeature->GetFID() != OGRNullFID || (nNextFID >= 0 && bHasJustGotNextFID)) )
+        {
+            if( FlushDeferredInsert(false) != OGRERR_NONE )
+                return OGRERR_FAILURE;
+        }
+    }
 
-        if( bMustComma )
-            osSQL += ", ";
+    bool bWriteInsertInto = (eDeferredInsertState != INSERT_MULTIPLE_FEATURE);
+    bool bResetToUninitInsertStateAfterwards = false;
+    if( eDeferredInsertState == INSERT_UNINIT )
+    {
+        if( !bInDeferredInsert )
+        {
+            eDeferredInsertState = INSERT_SINGLE_FEATURE;
+        }
+        else if( !bHasUserFieldMatchingFID && osFIDColName.size() &&
+            (poFeature->GetFID() != OGRNullFID || (nNextFID >= 0 && bHasJustGotNextFID)) )
+        {
+            eDeferredInsertState = INSERT_SINGLE_FEATURE;
+            bResetToUninitInsertStateAfterwards = true;
+        }
         else
         {
-            osSQL += "(";
-            bMustComma = TRUE;
+            eDeferredInsertState = INSERT_MULTIPLE_FEATURE;
+            for(i = 0; i < poFeatureDefn->GetFieldCount(); i++)
+            {
+                if( poFeatureDefn->GetFieldDefn(i)->GetDefault() != NULL )
+                    eDeferredInsertState = INSERT_SINGLE_FEATURE;
+            }
         }
-
-        osSQL += OGRCARTODBEscapeIdentifier(poFeatureDefn->GetFieldDefn(i)->GetNameRef());
     }
 
-    for(i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++)
+    int bMustComma = FALSE;
+    if( bWriteInsertInto )
     {
-        if( poFeature->GetGeomFieldRef(i) == NULL )
-            continue;
+        osSQL.Printf("INSERT INTO %s ", OGRCARTODBEscapeIdentifier(osName).c_str());
+        for(i = 0; i < poFeatureDefn->GetFieldCount(); i++)
+        {
+            if( eDeferredInsertState != INSERT_MULTIPLE_FEATURE &&
+                !poFeature->IsFieldSet(i) )
+                continue;
 
-        if( bMustComma )
-            osSQL += ", ";
-        else
+            if( bMustComma )
+                osSQL += ", ";
+            else
+            {
+                osSQL += "(";
+                bMustComma = TRUE;
+            }
+
+            osSQL += OGRCARTODBEscapeIdentifier(poFeatureDefn->GetFieldDefn(i)->GetNameRef());
+        }
+
+        for(i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++)
         {
-            osSQL += "(";
-            bMustComma = TRUE;
+            if( eDeferredInsertState != INSERT_MULTIPLE_FEATURE &&
+                poFeature->GetGeomFieldRef(i) == NULL )
+                continue;
+
+            if( bMustComma )
+                osSQL += ", ";
+            else
+            {
+                osSQL += "(";
+                bMustComma = TRUE;
+            }
+
+            osSQL += OGRCARTODBEscapeIdentifier(poFeatureDefn->GetGeomFieldDefn(i)->GetNameRef());
         }
 
-        osSQL += OGRCARTODBEscapeIdentifier(poFeatureDefn->GetGeomFieldDefn(i)->GetNameRef());
-    }
-    
-    if( !bHasUserFieldMatchingFID &&
-        osFIDColName.size() && (poFeature->GetFID() != OGRNullFID || nNextFID >= 0) )
-    {
-        if( bMustComma )
-            osSQL += ", ";
-        else
+        if( !bHasUserFieldMatchingFID &&
+            osFIDColName.size() && (poFeature->GetFID() != OGRNullFID || (nNextFID >= 0 && bHasJustGotNextFID)) )
         {
-            osSQL += "(";
-            bMustComma = TRUE;
+            if( bMustComma )
+                osSQL += ", ";
+            else
+            {
+                osSQL += "(";
+                bMustComma = TRUE;
+            }
+
+            osSQL += OGRCARTODBEscapeIdentifier(osFIDColName);
         }
 
-        osSQL += OGRCARTODBEscapeIdentifier(osFIDColName);
+        if( !bMustComma && eDeferredInsertState == INSERT_MULTIPLE_FEATURE )
+            eDeferredInsertState = INSERT_SINGLE_FEATURE;
     }
 
-    if( !bMustComma )
-        osSQL += " DEFAULT VALUES";
+    if( !bMustComma && eDeferredInsertState == INSERT_SINGLE_FEATURE )
+        osSQL += "DEFAULT VALUES";
     else
     {
-        osSQL += ") VALUES (";
-        
+        if( !bWriteInsertInto && eDeferredInsertState == INSERT_MULTIPLE_FEATURE )
+            osSQL += ", (";
+        else
+            osSQL += ") VALUES (";
+
         bMustComma = FALSE;
         for(i = 0; i < poFeatureDefn->GetFieldCount(); i++)
         {
             if( !poFeature->IsFieldSet(i) )
+            {
+                if( eDeferredInsertState == INSERT_MULTIPLE_FEATURE )
+                {
+                    if( bMustComma )
+                        osSQL += ", ";
+                    else
+                        bMustComma = TRUE;
+                    osSQL += "NULL";
+                }
                 continue;
-        
+            }
+
             if( bMustComma )
                 osSQL += ", ";
             else
                 bMustComma = TRUE;
-            
+
             OGRFieldType eType = poFeatureDefn->GetFieldDefn(i)->GetType();
             if( eType == OFTString || eType == OFTDateTime || eType == OFTDate || eType == OFTTime )
             {
@@ -598,13 +752,23 @@ OGRErr OGRCARTODBTableLayer::ICreateFeature( OGRFeature *poFeature )
             else
                 osSQL += poFeature->GetFieldAsString(i);
         }
-        
+
         for(i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++)
         {
             OGRGeometry* poGeom = poFeature->GetGeomFieldRef(i);
             if( poGeom == NULL )
+            {
+                if( eDeferredInsertState == INSERT_MULTIPLE_FEATURE )
+                {
+                    if( bMustComma )
+                        osSQL += ", ";
+                    else
+                        bMustComma = TRUE;
+                    osSQL += "NULL";
+                }
                 continue;
-        
+            }
+
             if( bMustComma )
                 osSQL += ", ";
             else
@@ -621,11 +785,15 @@ OGRErr OGRCARTODBTableLayer::ICreateFeature( OGRFeature *poFeature )
             {
                 OGRMultiPolygon* poNewGeom = new OGRMultiPolygon();
                 poNewGeom->addGeometry(poGeom);
-                pszEWKB = OGRGeometryToHexEWKB(poNewGeom, nSRID, FALSE);
+                pszEWKB = OGRGeometryToHexEWKB(poNewGeom, nSRID,
+                                               poDS->GetPostGISMajor(),
+                                               poDS->GetPostGISMinor());
                 delete poNewGeom;
             }
             else
-                pszEWKB = OGRGeometryToHexEWKB(poGeom, nSRID, FALSE);
+                pszEWKB = OGRGeometryToHexEWKB(poGeom, nSRID,
+                                               poDS->GetPostGISMajor(),
+                                               poDS->GetPostGISMinor());
             osSQL += "'";
             osSQL += pszEWKB;
             osSQL += "'";
@@ -636,22 +804,15 @@ OGRErr OGRCARTODBTableLayer::ICreateFeature( OGRFeature *poFeature )
         {
             if( osFIDColName.size() && nNextFID >= 0 )
             {
-                if( bMustComma )
-                    osSQL += ", ";
-                else
-                    bMustComma = TRUE;
-
                 if( bHasJustGotNextFID )
                 {
+                    if( bMustComma )
+                        osSQL += ", ";
+                    else
+                        bMustComma = TRUE;
+
                     osSQL += CPLSPrintf(CPL_FRMT_GIB, nNextFID);
                 }
-                else
-                {
-                    osSQL += CPLSPrintf("nextval('%s')",
-                            OGRCARTODBEscapeLiteral(CPLSPrintf("%s_%s_seq", osName.c_str(), osFIDColName.c_str())).c_str());
-                }
-                poFeature->SetFID(nNextFID);
-                nNextFID ++;
             }
             else if( osFIDColName.size() && poFeature->GetFID() != OGRNullFID )
             {
@@ -666,45 +827,39 @@ OGRErr OGRCARTODBTableLayer::ICreateFeature( OGRFeature *poFeature )
 
         osSQL += ")";
     }
+    CPL_IGNORE_RET_VAL(bMustComma);
+
+    if( !bHasUserFieldMatchingFID && osFIDColName.size() && nNextFID >= 0 )
+    {
+        poFeature->SetFID(nNextFID);
+        nNextFID ++;
+    }
 
-    if( bInDeferedInsert )
+    if( bInDeferredInsert )
     {
         OGRErr eRet = OGRERR_NONE;
-        if( osDeferedInsertSQL.size() != 0 &&
-            (int)osDeferedInsertSQL.size() + (int)osSQL.size() > nMaxChunkSize )
+        if( eDeferredInsertState == INSERT_SINGLE_FEATURE && /* in multiple mode, this would require rebuilding the osSQL buffer. Annoying... */
+            osDeferredInsertSQL.size() != 0 &&
+            (int)osDeferredInsertSQL.size() + (int)osSQL.size() > nMaxChunkSize )
         {
-            osDeferedInsertSQL = "BEGIN;" + osDeferedInsertSQL + "COMMIT;";
-            json_object* poObj = poDS->RunSQL(osDeferedInsertSQL);
-            if( poObj != NULL )
-                json_object_put(poObj);
-            else
-            {
-                bInDeferedInsert = FALSE;
-                eRet = OGRERR_FAILURE;
-            }
-            osDeferedInsertSQL = "";
+            eRet = FlushDeferredInsert(false);
         }
 
-        osDeferedInsertSQL += osSQL;
-        osDeferedInsertSQL += ";";
+        osDeferredInsertSQL += osSQL;
+        if( eDeferredInsertState == INSERT_SINGLE_FEATURE )
+            osDeferredInsertSQL += ";";
 
-        if( (int)osDeferedInsertSQL.size() > nMaxChunkSize )
+        if( (int)osDeferredInsertSQL.size() > nMaxChunkSize )
         {
-            osDeferedInsertSQL = "BEGIN;" + osDeferedInsertSQL + "COMMIT;";
-            json_object* poObj = poDS->RunSQL(osDeferedInsertSQL);
-            if( poObj != NULL )
-                json_object_put(poObj);
-            else
-            {
-                bInDeferedInsert = FALSE;
-                eRet = OGRERR_FAILURE;
-            }
-            osDeferedInsertSQL = "";
+            eRet = FlushDeferredInsert(false);
         }
 
+        if( bResetToUninitInsertStateAfterwards )
+            eDeferredInsertState = INSERT_UNINIT;
+
         return eRet;
     }
-    
+
     if( osFIDColName.size() )
     {
         osSQL += " RETURNING ";
@@ -759,11 +914,10 @@ OGRErr OGRCARTODBTableLayer::ICreateFeature( OGRFeature *poFeature )
 OGRErr OGRCARTODBTableLayer::ISetFeature( OGRFeature *poFeature )
 
 {
-    int i;
-
-    if( bDeferedCreation && RunDeferedCreationIfNecessary() != OGRERR_NONE )
+    if( bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
+        return OGRERR_FAILURE;
+    if( FlushDeferredInsert() != OGRERR_NONE )
         return OGRERR_FAILURE;
-    FlushDeferedInsert();
 
     GetLayerDefn();
 
@@ -780,11 +934,11 @@ OGRErr OGRCARTODBTableLayer::ISetFeature( OGRFeature *poFeature )
                   "FID required on features given to SetFeature()." );
         return OGRERR_FAILURE;
     }
-    
+
     CPLString osSQL;
     osSQL.Printf("UPDATE %s SET ", OGRCARTODBEscapeIdentifier(osName).c_str());
     int bMustComma = FALSE;
-    for(i = 0; i < poFeatureDefn->GetFieldCount(); i++)
+    for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
     {
         if( bMustComma )
             osSQL += ", ";
@@ -817,7 +971,7 @@ OGRErr OGRCARTODBTableLayer::ISetFeature( OGRFeature *poFeature )
         }
     }
 
-    for(i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++)
+    for( int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
     {
         if( bMustComma )
             osSQL += ", ";
@@ -839,7 +993,9 @@ OGRErr OGRCARTODBTableLayer::ISetFeature( OGRFeature *poFeature )
             int nSRID = poGeomFieldDefn->nSRID;
             if( nSRID == 0 )
                 nSRID = 4326;
-            char* pszEWKB = OGRGeometryToHexEWKB(poGeom, nSRID, FALSE);
+            char* pszEWKB = OGRGeometryToHexEWKB(poGeom, nSRID,
+                                               poDS->GetPostGISMajor(),
+                                               poDS->GetPostGISMinor());
             osSQL += "'";
             osSQL += pszEWKB;
             osSQL += "'";
@@ -880,9 +1036,10 @@ OGRErr OGRCARTODBTableLayer::DeleteFeature( GIntBig nFID )
 
 {
 
-    if( bDeferedCreation && RunDeferedCreationIfNecessary() != OGRERR_NONE )
+    if( bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
+        return OGRERR_FAILURE;
+    if( FlushDeferredInsert() != OGRERR_NONE )
         return OGRERR_FAILURE;
-    FlushDeferedInsert();
 
     GetLayerDefn();
 
@@ -892,10 +1049,10 @@ OGRErr OGRCARTODBTableLayer::DeleteFeature( GIntBig nFID )
                  "Operation not available in read-only mode");
         return OGRERR_FAILURE;
     }
-    
+
     if( osFIDColName.size() == 0 )
         return OGRERR_FAILURE;
-    
+
     CPLString osSQL;
     osSQL.Printf("DELETE FROM %s WHERE %s = " CPL_FRMT_GIB,
                     OGRCARTODBEscapeIdentifier(osName).c_str(),
@@ -1002,12 +1159,13 @@ void OGRCARTODBTableLayer::BuildWhere()
 OGRFeature* OGRCARTODBTableLayer::GetFeature( GIntBig nFeatureId )
 {
 
-    if( bDeferedCreation && RunDeferedCreationIfNecessary() != OGRERR_NONE )
+    if( bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
+        return NULL;
+    if( FlushDeferredInsert() != OGRERR_NONE )
         return NULL;
-    FlushDeferedInsert();
 
     GetLayerDefn();
-    
+
     if( osFIDColName.size() == 0 )
         return OGRCARTODBLayer::GetFeature(nFeatureId);
 
@@ -1039,9 +1197,10 @@ OGRFeature* OGRCARTODBTableLayer::GetFeature( GIntBig nFeatureId )
 GIntBig OGRCARTODBTableLayer::GetFeatureCount(int bForce)
 {
 
-    if( bDeferedCreation && RunDeferedCreationIfNecessary() != OGRERR_NONE )
+    if( bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
+        return 0;
+    if( FlushDeferredInsert() != OGRERR_NONE )
         return 0;
-    FlushDeferedInsert();
 
     GetLayerDefn();
 
@@ -1087,9 +1246,10 @@ OGRErr OGRCARTODBTableLayer::GetExtent( int iGeomField, OGREnvelope *psExtent, i
 {
     CPLString   osSQL;
 
-    if( bDeferedCreation && RunDeferedCreationIfNecessary() != OGRERR_NONE )
+    if( bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
+        return OGRERR_FAILURE;
+    if( FlushDeferredInsert() != OGRERR_NONE )
         return OGRERR_FAILURE;
-    FlushDeferedInsert();
 
     if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() ||
         GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetType() == wkbNone )
@@ -1152,11 +1312,11 @@ OGRErr OGRCARTODBTableLayer::GetExtent( int iGeomField, OGREnvelope *psExtent, i
             }
 
             // Take X,Y coords
-            // For PostGis ver >= 1.0.0 -> Tokens: X1 Y1 X2 Y2 (nTokenCnt = 4)
+            // For PostGIS ver >= 1.0.0 -> Tokens: X1 Y1 X2 Y2 (nTokenCnt = 4)
             // For PostGIS ver < 1.0.0 -> Tokens: X1 Y1 Z1 X2 Y2 Z2 (nTokenCnt = 6)
             // =>   X2 index calculated as nTokenCnt/2
-            //      Y2 index caluclated as nTokenCnt/2+1
-            
+            //      Y2 index calculated as nTokenCnt/2+1
+
             psExtent->MinX = CPLAtof( papszTokens[0] );
             psExtent->MinY = CPLAtof( papszTokens[1] );
             psExtent->MaxX = CPLAtof( papszTokens[nTokenCnt/2] );
@@ -1198,7 +1358,8 @@ int OGRCARTODBTableLayer::TestCapability( const char * pszCap )
     if( EQUAL(pszCap,OLCSequentialWrite)
      || EQUAL(pszCap,OLCRandomWrite)
      || EQUAL(pszCap,OLCDeleteFeature)
-     || EQUAL(pszCap,OLCCreateField) )
+     || EQUAL(pszCap,OLCCreateField)
+     || EQUAL(pszCap,OLCDeleteField) )
     {
         return poDS->IsReadWrite();
     }
@@ -1207,18 +1368,18 @@ int OGRCARTODBTableLayer::TestCapability( const char * pszCap )
 }
 
 /************************************************************************/
-/*                        SetDeferedCreation()                          */
+/*                        SetDeferredCreation()                          */
 /************************************************************************/
 
-void OGRCARTODBTableLayer::SetDeferedCreation (OGRwkbGeometryType eGType,
-                                               OGRSpatialReference* poSRS,
+void OGRCARTODBTableLayer::SetDeferredCreation (OGRwkbGeometryType eGType,
+                                               OGRSpatialReference* poSRSIn,
                                                int bGeomNullable,
-                                               int bCartoDBify)
+                                               int bCartoDBifyIn)
 {
-    bDeferedCreation = TRUE;
+    bDeferredCreation = TRUE;
     nNextFID = 1;
     CPLAssert(poFeatureDefn == NULL);
-    this->bCartoDBify = bCartoDBify;
+    this->bCartoDBify = bCartoDBifyIn;
     poFeatureDefn = new OGRFeatureDefn(osName);
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType(wkbNone);
@@ -1232,11 +1393,11 @@ void OGRCARTODBTableLayer::SetDeferedCreation (OGRwkbGeometryType eGType,
             new OGRCartoDBGeomFieldDefn("the_geom", eGType);
         poFieldDefn->SetNullable(bGeomNullable);
         poFeatureDefn->AddGeomFieldDefn(poFieldDefn, FALSE);
-        if( poSRS != NULL )
+        if( poSRSIn != NULL )
         {
-            poFieldDefn->nSRID = poDS->FetchSRSId( poSRS );
+            poFieldDefn->nSRID = poDS->FetchSRSId( poSRSIn );
             poFeatureDefn->GetGeomFieldDefn(
-                poFeatureDefn->GetGeomFieldCount() - 1)->SetSpatialRef(poSRS);
+                poFeatureDefn->GetGeomFieldCount() - 1)->SetSpatialRef(poSRSIn);
         }
     }
     osFIDColName = "cartodb_id";
@@ -1246,14 +1407,14 @@ void OGRCARTODBTableLayer::SetDeferedCreation (OGRwkbGeometryType eGType,
 }
 
 /************************************************************************/
-/*                      RunDeferedCreationIfNecessary()                 */
+/*                      RunDeferredCreationIfNecessary()                 */
 /************************************************************************/
 
-OGRErr OGRCARTODBTableLayer::RunDeferedCreationIfNecessary()
+OGRErr OGRCARTODBTableLayer::RunDeferredCreationIfNecessary()
 {
-    if( !bDeferedCreation )
+    if( !bDeferredCreation )
         return OGRERR_NONE;
-    bDeferedCreation = FALSE;
+    bDeferredCreation = FALSE;
 
     CPLString osSQL;
     osSQL.Printf("CREATE TABLE %s ( %s SERIAL,",
@@ -1302,7 +1463,7 @@ OGRErr OGRCARTODBTableLayer::RunDeferedCreationIfNecessary()
     }
 
     osSQL += CPLSPrintf("PRIMARY KEY (%s) )", osFIDColName.c_str());
-    
+
     CPLString osSeqName(OGRCARTODBEscapeIdentifier(CPLSPrintf("%s_%s_seq",
                                 osName.c_str(), osFIDColName.c_str())));
 
@@ -1320,33 +1481,5 @@ OGRErr OGRCARTODBTableLayer::RunDeferedCreationIfNecessary()
         return OGRERR_FAILURE;
     json_object_put(poObj);
 
-    if( bCartoDBify )
-    {
-        if( nSRID != 4326 )
-        {
-            if( eGType != wkbNone )
-            {
-                CPLError(CE_Warning, CPLE_AppDefined,
-                        "Cannot register table in dashboard with "
-                        "cdb_cartodbfytable() since its SRS is not EPSG:4326");
-            }
-        }
-        else
-        {
-            if( poDS->GetCurrentSchema() == "public" )
-                osSQL.Printf("SELECT cdb_cartodbfytable('%s')",
-                                    OGRCARTODBEscapeLiteral(osName).c_str());
-            else
-                osSQL.Printf("SELECT cdb_cartodbfytable('%s', '%s')",
-                                    OGRCARTODBEscapeLiteral(poDS->GetCurrentSchema()).c_str(),
-                                    OGRCARTODBEscapeLiteral(osName).c_str());
-
-            poObj = poDS->RunSQL(osSQL);
-            if( poObj == NULL )
-                return OGRERR_FAILURE;
-            json_object_put(poObj);
-        }
-    }
-
     return OGRERR_NONE;
 }
diff --git a/ogr/ogrsf_frmts/cloudant/drv_cloudant.html b/ogr/ogrsf_frmts/cloudant/drv_cloudant.html
index 172fa55..a223f7a 100644
--- a/ogr/ogrsf_frmts/cloudant/drv_cloudant.html
+++ b/ogr/ogrsf_frmts/cloudant/drv_cloudant.html
@@ -10,7 +10,7 @@
 (GDAL/OGR >= 2.0.0)<p>
 
 Cloudant and CouchDB are API compatible and based on the same core technology. The geospatial extension for Cloudant
-is separate to GeoCouch. 
+is separate to GeoCouch.
 
 This driver can connect to the a Cloudant service, potentially enabled with the Cloudant spatial extension.<p>
 GDAL/OGR must be built with Curl support in order to the Cloudant driver to be compiled.<p>
@@ -25,7 +25,7 @@ OGR preferably handles Cloudant documents following the GeoJSON specification.<p
 <h2>Dataset name syntax</h2>
 
 The syntax to open a Cloudant datasource is : <pre>cloudant:http://example.com[/layername]</pre> where
-http://example.com points to the root of a CouchDB repository and, optionaly, layername is the name of a CouchDB database.<p>
+http://example.com points to the root of a CouchDB repository and, optionally, layername is the name of a CouchDB database.<p>
 
 It is also possible to directly open a view : <pre>cloudant:http://example.com/layername/_design/adesigndoc/_view/aview[?include_docs=true]</pre>
 The include_docs=true might be needed depending on the value returned by the emit() call in the map() function.<p>
@@ -79,7 +79,7 @@ The following layer creation options are supported:
 <li>Otherwise, all users will be allowed to make changes in non-design documents.</li>
 </ul>
 </li>
-<li><b>GEOJSON</b> = YES|NO : Set to NO to avoid writting documents as GeoJSON documents. Default to YES.</li>
+<li><b>GEOJSON</b> = YES|NO : Set to NO to avoid writing documents as GeoJSON documents. Default to YES.</li>
 <li><b>COORDINATE_PRECISION</b> = int_number : Maximum number of figures after decimal separator to write in coordinates.
 Default to 15. "Smart" truncation will occur to remove trailing zeros.
 Note: when opening a dataset in update mode, the OGR_CLOUDANT_COORDINATE_PRECISION configuration option can be set to have a similar role.</li>
diff --git a/ogr/ogrsf_frmts/cloudant/ogr_cloudant.h b/ogr/ogrsf_frmts/cloudant/ogr_cloudant.h
index 45abe24..93a468c 100644
--- a/ogr/ogrsf_frmts/cloudant/ogr_cloudant.h
+++ b/ogr/ogrsf_frmts/cloudant/ogr_cloudant.h
@@ -28,8 +28,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_CLOUDANT_H_INCLUDED
-#define _OGR_CLOUDANT_H_INCLUDED
+#ifndef OGR_CLOUDANT_H_INCLUDED
+#define OGR_CLOUDANT_H_INCLUDED
 
 #include "ogr_couchdb.h"
 
@@ -51,7 +51,7 @@ class OGRCloudantTableLayer : public OGRCouchDBTableLayer
     char*                     pszSpatialDDoc;
 
     protected:
-            virtual int               GetFeaturesToFetch() { 
+            virtual int               GetFeaturesToFetch() {
                return atoi(CPLGetConfigOption("CLOUDANT_PAGE_SIZE", "200"));
             }
 
@@ -59,7 +59,7 @@ class OGRCloudantTableLayer : public OGRCouchDBTableLayer
             virtual void              GetSpatialView();
             virtual void              WriteMetadata();
             virtual void              LoadMetadata();
-            
+
     public:
             OGRCloudantTableLayer(OGRCloudantDataSource* poDS,
                                  const char* pszName);
@@ -77,7 +77,7 @@ class OGRCloudantDataSource : public OGRCouchDBDataSource
   public:
                         OGRCloudantDataSource();
                         ~OGRCloudantDataSource();
-    virtual int Open( const char * pszFilename, int bUpdateIn);                       
+    virtual int Open( const char * pszFilename, int bUpdateIn);
     virtual OGRLayer   *ICreateLayer( const char *pszName,
              OGRSpatialReference *poSpatialRef = NULL,
              OGRwkbGeometryType eGType = wkbUnknown,
@@ -101,4 +101,4 @@ class OGRCloudantDriver : public OGRCouchDBDriver
 
 };
 
-#endif /* ndef _OGR_CLOUDANT_H_INCLUDED */
+#endif /* ndef OGR_CLOUDANT_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/cloudant/ogrcloudantdatasource.cpp b/ogr/ogrsf_frmts/cloudant/ogrcloudantdatasource.cpp
index 833ebe7..a7b1d1b 100644
--- a/ogr/ogrsf_frmts/cloudant/ogrcloudantdatasource.cpp
+++ b/ogr/ogrsf_frmts/cloudant/ogrcloudantdatasource.cpp
@@ -39,21 +39,13 @@ CPL_CVSID("$Id$");
 /*                        OGRCloudantDataSource()                       */
 /************************************************************************/
 
-OGRCloudantDataSource::OGRCloudantDataSource()
-
-{
-
-}
+OGRCloudantDataSource::OGRCloudantDataSource() {}
 
 /************************************************************************/
 /*                       ~OGRCloudantDataSource()                       */
 /************************************************************************/
 
-OGRCloudantDataSource::~OGRCloudantDataSource()
-
-{
-
-}
+OGRCloudantDataSource::~OGRCloudantDataSource() {}
 
 /************************************************************************/
 /*                             OpenDatabase()                           */
@@ -78,9 +70,9 @@ OGRLayer* OGRCloudantDataSource::OpenDatabase(const char* pszLayerName)
         if (pszLastSlash)
         {
             osEscapedName = pszLastSlash + 1;
-            char* pszName = CPLUnescapeString(osEscapedName, NULL, CPLES_URL);
-            osTableName = pszName;
-            CPLFree(pszName);
+            char* l_pszName = CPLUnescapeString(osEscapedName, NULL, CPLES_URL);
+            osTableName = l_pszName;
+            CPLFree(l_pszName);
             *pszLastSlash = 0;
         }
         osURL = pszURL;
@@ -132,10 +124,10 @@ int OGRCloudantDataSource::Open( const char * pszFilename, int bUpdateIn)
 
 {
     int bHTTP = FALSE;
-    if (strncmp(pszFilename, "http://", 7) == 0 ||
-        strncmp(pszFilename, "https://", 8) == 0)
+    if (STARTS_WITH(pszFilename, "http://") ||
+        STARTS_WITH(pszFilename, "https://"))
         bHTTP = TRUE;
-    else if (!EQUALN(pszFilename, "cloudant:", 9))
+    else if (!STARTS_WITH_CI(pszFilename, "cloudant:"))
         return FALSE;
 
     bReadWrite = bUpdateIn;
@@ -212,7 +204,7 @@ int OGRCloudantDataSource::Open( const char * pszFilename, int bUpdateIn)
     }
 
     int nTables = json_object_array_length(poAnswerObj);
-    
+
     for(int i=0;i<nTables;i++)
     {
         json_object* poAnswerObjDBName = json_object_array_get_idx(poAnswerObj, i);
@@ -238,7 +230,7 @@ int OGRCloudantDataSource::Open( const char * pszFilename, int bUpdateIn)
 /*                          ICreateLayer()                              */
 /************************************************************************/
 
-OGRLayer   *OGRCloudantDataSource::ICreateLayer( const char *pszName,
+OGRLayer   *OGRCloudantDataSource::ICreateLayer( const char *l_pszName,
                                            OGRSpatialReference *poSpatialRef,
                                            OGRwkbGeometryType eGType,
                                            char ** papszOptions )
@@ -249,7 +241,7 @@ OGRLayer   *OGRCloudantDataSource::ICreateLayer( const char *pszName,
         return NULL;
     }
 
-    char *pszLayerName = CPLStrlwr(CPLStrdup(pszName));
+    char *pszLayerName = CPLStrlwr(CPLStrdup(l_pszName));
     CPLString osLayerName = pszLayerName;
     CPLFree(pszLayerName);
 
@@ -311,7 +303,7 @@ OGRLayer   *OGRCloudantDataSource::ICreateLayer( const char *pszName,
     if (eGType != wkbNone)
     {
         char szSrid[100];
-        bool bSrid = FALSE;
+        bool bSrid = false;
         const char* designDoc = "_design/SpatialView";
         osURI = "/";
         osURI += osEscapedName;
@@ -326,27 +318,26 @@ OGRLayer   *OGRCloudantDataSource::ICreateLayer( const char *pszName,
             if (poSpatialRef->IsProjected())
             {
                 pszAuthName = poSpatialRef->GetAuthorityName("PROJCS");
-                if ((pszAuthName != NULL) && (strncmp(pszAuthName, "EPSG", 4) == 0))
+                if ((pszAuthName != NULL) && (STARTS_WITH(pszAuthName, "EPSG")))
                     pszEpsg = poSpatialRef->GetAuthorityCode("PROJCS");
             }
             else
             {
                 pszAuthName = poSpatialRef->GetAuthorityName("GEOGCS");
-                if ((pszAuthName != NULL) && (strncmp(pszAuthName, "EPSG", 4) == 0))
+                if ((pszAuthName != NULL) && (STARTS_WITH(pszAuthName, "EPSG")))
                     pszEpsg = poSpatialRef->GetAuthorityCode("GEOGCS");
             }
 
             if (pszEpsg != NULL)
             {
-                const char * pszUrn = "urn:ogc:def:crs:epsg::";
-                CPLStrlcpy(szSrid, pszUrn, sizeof(szSrid));
-                if (CPLStrlcpy(szSrid + sizeof(pszUrn), pszEpsg, sizeof(szSrid)) >= sizeof(szSrid))
+                if( snprintf(szSrid, sizeof(szSrid), "urn:ogc:def:crs:epsg::%s",
+                             pszEpsg) >= (int)sizeof(szSrid) )
                 {
                     CPLError(CE_Failure, CPLE_AppDefined, "Unable to parse SRID");
                     return NULL;
                 }
                 else
-                    bSrid = TRUE;
+                    bSrid = true;
             }
         }
 
@@ -358,9 +349,9 @@ OGRLayer   *OGRCloudantDataSource::ICreateLayer( const char *pszName,
         json_object_object_add(poDoc, "_id",
                                json_object_new_string(designDoc));
         json_object_object_add(poStIndexes, "spatial", poSpatial);
-        json_object_object_add(poSpatial, "index", 
+        json_object_object_add(poSpatial, "index",
             json_object_new_string("function(doc) {if (doc.geometry && doc.geometry.coordinates && doc.geometry.coordinates.length != 0){st_index(doc.geometry);}}"));
-        
+
         if (bSrid)
             json_object_object_add(poStIndexes, "srsid", json_object_new_string(szSrid));
 
@@ -375,7 +366,7 @@ OGRLayer   *OGRCloudantDataSource::ICreateLayer( const char *pszName,
         json_object_put(poAnswerObj);
     }
 
-    int bGeoJSONDocument = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "GEOJSON", "TRUE"));
+    int bGeoJSONDocument = CPLTestBool(CSLFetchNameValueDef(papszOptions, "GEOJSON", "TRUE"));
     int nCoordPrecision = atoi(CSLFetchNameValueDef(papszOptions, "COORDINATE_PRECISION", "-1"));
 
     OGRCloudantTableLayer* poLayer = new OGRCloudantTableLayer(this, osLayerName);
@@ -385,4 +376,4 @@ OGRLayer   *OGRCloudantDataSource::ICreateLayer( const char *pszName,
     papoLayers = (OGRLayer**) CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
     papoLayers[nLayers ++] = poLayer;
     return poLayer;
-}   
+}
diff --git a/ogr/ogrsf_frmts/cloudant/ogrcloudantdriver.cpp b/ogr/ogrsf_frmts/cloudant/ogrcloudantdriver.cpp
index 0b68cd3..37f9610 100644
--- a/ogr/ogrsf_frmts/cloudant/ogrcloudantdriver.cpp
+++ b/ogr/ogrsf_frmts/cloudant/ogrcloudantdriver.cpp
@@ -59,7 +59,7 @@ const char *OGRCloudantDriver::GetName()
 OGRDataSource *OGRCloudantDriver::Open( const char * pszFilename, int bUpdate )
 
 {
-    if (!EQUALN(pszFilename, "cloudant:", 9))
+    if (!STARTS_WITH_CI(pszFilename, "cloudant:"))
         return NULL;
 
     OGRCloudantDataSource   *poDS = new OGRCloudantDataSource();
diff --git a/ogr/ogrsf_frmts/cloudant/ogrcloudanttablelayer.cpp b/ogr/ogrsf_frmts/cloudant/ogrcloudanttablelayer.cpp
index b9829e3..97a0b54 100644
--- a/ogr/ogrsf_frmts/cloudant/ogrcloudanttablelayer.cpp
+++ b/ogr/ogrsf_frmts/cloudant/ogrcloudanttablelayer.cpp
@@ -41,15 +41,13 @@ CPL_CVSID("$Id$");
 /*                       OGRCloudantTableLayer()                         */
 /************************************************************************/
 
-OGRCloudantTableLayer::OGRCloudantTableLayer(OGRCloudantDataSource* poDS,
-                                           const char* pszName) :
-                                                        OGRCouchDBTableLayer((OGRCouchDBDataSource*) poDS, pszName)
-
-{
-    bHasStandardSpatial = -1;
-    pszSpatialView = NULL;
-    pszSpatialDDoc = NULL;
-}
+OGRCloudantTableLayer::OGRCloudantTableLayer( OGRCloudantDataSource* poDSIn,
+                                              const char* pszName) :
+    OGRCouchDBTableLayer((OGRCouchDBDataSource*) poDSIn, pszName),
+    bHasStandardSpatial(-1),
+    pszSpatialView(NULL),
+    pszSpatialDDoc(NULL)
+{}
 
 /************************************************************************/
 /*                      ~OGRCouchDBTableLayer()                         */
@@ -57,7 +55,7 @@ OGRCloudantTableLayer::OGRCloudantTableLayer(OGRCloudantDataSource* poDS,
 
 OGRCloudantTableLayer::~OGRCloudantTableLayer()
 
-{ 
+{
     if( bMustWriteMetadata )
     {
         WriteMetadata();
@@ -65,7 +63,7 @@ OGRCloudantTableLayer::~OGRCloudantTableLayer()
     }
 
     if (pszSpatialDDoc)
-        free((void*)pszSpatialDDoc);
+        CPLFree(pszSpatialDDoc);
 }
 
 /************************************************************************/
@@ -220,21 +218,22 @@ void OGRCloudantTableLayer::GetSpatialView()
         if (bHasStandardSpatial)
             pszSpatialView = "_design/SpatialView/_geo/spatial";
 
-        papszTokens = 
+        papszTokens =
             CSLTokenizeString2( pszSpatialView, "/", 0);
 
         if ((papszTokens[0] == NULL) || (papszTokens[1] == NULL))
         {
             CPLError(CE_Failure, CPLE_AppDefined, "GetSpatialView() failed, invalid spatial design doc.");
+            CSLDestroy(papszTokens);
             return;
         }
 
-        pszSpatialDDoc = (char*) calloc(strlen(papszTokens[0]) + strlen(papszTokens[1]) + 2, 1);
-
-        sprintf(pszSpatialDDoc, "%s/%s", papszTokens[0], papszTokens[1]);
+        const size_t nLen = strlen(papszTokens[0]) + strlen(papszTokens[1]) + 2;
+        pszSpatialDDoc = (char*) CPLCalloc(nLen, 1);
 
-        CSLDestroy(papszTokens);  
+        snprintf(pszSpatialDDoc, nLen, "%s/%s", papszTokens[0], papszTokens[1]);
 
+        CSLDestroy(papszTokens);
     }
 }
 
@@ -294,17 +293,17 @@ void OGRCloudantTableLayer::WriteMetadata()
         if (poSRS->IsProjected())
         {
             pszAuthName = poSRS->GetAuthorityName("PROJCS");
-            if ((pszAuthName != NULL) && (strncmp(pszAuthName, "EPSG", 4) == 0))
+            if ((pszAuthName != NULL) && (STARTS_WITH(pszAuthName, "EPSG")))
                 pszEpsg = poSRS->GetAuthorityCode("PROJCS");
         }
         else
         {
             pszAuthName = poSRS->GetAuthorityName("GEOGCS");
-            if ((pszAuthName != NULL) && (strncmp(pszAuthName, "EPSG", 4) == 0))
+            if ((pszAuthName != NULL) && (STARTS_WITH(pszAuthName, "EPSG")))
                 pszEpsg = poSRS->GetAuthorityCode("GEOGCS");
         }
 
-        if (pszEpsg != NULL) 
+        if (pszEpsg != NULL)
         {
             const char * pszUrn = "urn:ogc:def:crs:epsg::";
             CPLStrlcpy(szSrid, pszUrn, sizeof(szSrid));
@@ -313,7 +312,7 @@ void OGRCloudantTableLayer::WriteMetadata()
                 json_object_object_add(poDDocObj, "srsid",
                                    json_object_new_string(pszUrn));
 
-            } 
+            }
         }
     }
 
@@ -339,7 +338,7 @@ void OGRCloudantTableLayer::WriteMetadata()
     json_object* poFields = json_object_new_array();
     json_object_object_add(poDDocObj, "fields", poFields);
 
-    for(int i=FIRST_FIELD;i<poFeatureDefn->GetFieldCount();i++)
+    for(int i=COUCHDB_FIRST_FIELD;i<poFeatureDefn->GetFieldCount();i++)
     {
         json_object* poField = json_object_new_object();
         json_object_array_add(poFields, poField);
@@ -494,7 +493,7 @@ void OGRCloudantTableLayer::LoadMetadata()
         poFeatureDefn->Reference();
 
         poFeatureDefn->SetGeomType(eGeomType);
-        if( poFeatureDefn->GetGeomFieldCount() != 0 ) 
+        if( poFeatureDefn->GetGeomFieldCount() != 0 )
             poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 
         OGRFieldDefn oFieldId("_id", OFTString);
diff --git a/ogr/ogrsf_frmts/couchdb/drv_couchdb.html b/ogr/ogrsf_frmts/couchdb/drv_couchdb.html
index a8ae415..fb68013 100644
--- a/ogr/ogrsf_frmts/couchdb/drv_couchdb.html
+++ b/ogr/ogrsf_frmts/couchdb/drv_couchdb.html
@@ -22,7 +22,7 @@ OGR handles preferably CouchDB documents following the GeoJSON specification.<p>
 <h2>Dataset name syntax</h2>
 
 The syntax to open a CouchDB datasource is : <pre>couchdb:http://example.com[/layername]</pre> where
-http://example.com points to the root of a CouchDB repository and, optionaly, layername is the name of a CouchDB database.<p>
+http://example.com points to the root of a CouchDB repository and, optionally, layername is the name of a CouchDB database.<p>
 
 It is also possible to directly open a view : <pre>couchdb:http://example.com/layername/_design/adesigndoc/_view/aview[?include_docs=true]</pre>
 The include_docs=true might be needed depending on the value returned by the emit() call in the map() function.<p>
@@ -80,7 +80,7 @@ The following layer creation options are supported:
 <li>Otherwise, all users will be allowed to make changes in non-design documents.</li>
 </ul>
 </li>
-<li><b>GEOJSON</b> = YES|NO : Set to NO to avoid writting documents as GeoJSON documents. Default to YES.</li>
+<li><b>GEOJSON</b> = YES|NO : Set to NO to avoid writing documents as GeoJSON documents. Default to YES.</li>
 <li><b>COORDINATE_PRECISION</b> = int_number : Maximum number of figures after decimal separator to write in coordinates.
 Default to 15. "Smart" truncation will occur to remove trailing zeros.
 Note: when opening a dataset in update mode, the OGR_COUCHDB_COORDINATE_PRECISION configuration option can be set to have a similar role.</li>
diff --git a/ogr/ogrsf_frmts/couchdb/ogr_couchdb.h b/ogr/ogrsf_frmts/couchdb/ogr_couchdb.h
index f543034..9ab4f2b 100644
--- a/ogr/ogrsf_frmts/couchdb/ogr_couchdb.h
+++ b/ogr/ogrsf_frmts/couchdb/ogr_couchdb.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_couchdb.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogr_couchdb.h 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  CouchDB Translator
  * Purpose:  Definition of classes for OGR CouchDB / GeoCouch driver.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_COUCHDB_H_INCLUDED
-#define _OGR_COUCHDB_H_INCLUDED
+#ifndef OGR_COUCHDB_H_INCLUDED
+#define OGR_COUCHDB_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "cpl_http.h"
@@ -37,9 +37,9 @@
 #include <vector>
 #include <map>
 
-#define _ID_FIELD       0
-#define _REV_FIELD      1
-#define FIRST_FIELD     2
+#define COUCHDB_ID_FIELD       0
+#define COUCHDB_REV_FIELD      1
+#define COUCHDB_FIRST_FIELD    2
 
 typedef enum
 {
@@ -142,7 +142,7 @@ class OGRCouchDBTableLayer : public OGRCouchDBLayer
     CPLString                 osEscapedName;
     int                       bMustWriteMetadata;
     int                       bMustRunSpatialFilter;
-    std::vector<CPLString>    aosIdsToFetch;   
+    std::vector<CPLString>    aosIdsToFetch;
     int                       bServerSideSpatialFilteringWorks;
     int                       bHasLoadedMetadata;
     CPLString                 osMetadataRev;
@@ -173,10 +173,14 @@ class OGRCouchDBTableLayer : public OGRCouchDBLayer
 
     virtual GIntBig             GetFeatureCount( int bForce = TRUE );
     virtual OGRErr              GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual OGRErr              GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
     virtual OGRFeature *        GetFeature( GIntBig nFID );
 
     virtual void                SetSpatialFilter( OGRGeometry * );
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+                { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
     virtual OGRErr              SetAttributeFilter( const char * );
 
     virtual OGRErr              CreateField( OGRFieldDefn *poField,
@@ -200,7 +204,7 @@ class OGRCouchDBTableLayer : public OGRCouchDBLayer
 
     int                       HasFilterOnFieldOrCreateIfNecessary(const char* pszFieldName);
 
-    void                        SetCoordinatePrecision(int nCoordPrecision) { this->nCoordPrecision = nCoordPrecision; }
+    void                        SetCoordinatePrecision(int nCoordPrecisionIn) { this->nCoordPrecision = nCoordPrecisionIn; }
 
     virtual CouchDBLayerType    GetLayerType() { return COUCHDB_TABLE_LAYER; }
 
@@ -242,7 +246,7 @@ class OGRCouchDBDataSource : public OGRDataSource
 
     int                 bReadWrite;
 
-    int                 bMustCleanPersistant;
+    int                 bMustCleanPersistent;
 
     CPLString           osURL;
     CPLString           osUserPwd;
@@ -315,4 +319,4 @@ class OGRCouchDBDriver : public OGRSFDriver
     virtual int                 TestCapability( const char * );
 };
 
-#endif /* ndef _OGR_COUCHDB_H_INCLUDED */
+#endif /* ndef OGR_COUCHDB_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/couchdb/ogrcouchdbdatasource.cpp b/ogr/ogrsf_frmts/couchdb/ogrcouchdbdatasource.cpp
index 1891a34..a7c19e8 100644
--- a/ogr/ogrsf_frmts/couchdb/ogrcouchdbdatasource.cpp
+++ b/ogr/ogrsf_frmts/couchdb/ogrcouchdbdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrcouchdbdatasource.cpp 29101 2015-05-01 22:17:43Z rouault $
+ * $Id: ogrcouchdbdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  CouchDB Translator
  * Purpose:  Implements OGRCouchDBDataSource class
@@ -30,7 +30,7 @@
 #include "ogr_couchdb.h"
 #include "swq.h"
 
-CPL_CVSID("$Id: ogrcouchdbdatasource.cpp 29101 2015-05-01 22:17:43Z rouault $");
+CPL_CVSID("$Id: ogrcouchdbdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                        OGRCouchDBDataSource()                        */
@@ -46,7 +46,7 @@ OGRCouchDBDataSource::OGRCouchDBDataSource()
 
     bReadWrite = FALSE;
 
-    bMustCleanPersistant = FALSE;
+    bMustCleanPersistent = FALSE;
 }
 
 /************************************************************************/
@@ -60,11 +60,11 @@ OGRCouchDBDataSource::~OGRCouchDBDataSource()
         delete papoLayers[i];
     CPLFree( papoLayers );
 
-    if (bMustCleanPersistant)
+    if (bMustCleanPersistent)
     {
         char** papszOptions = NULL;
         papszOptions = CSLSetNameValue(papszOptions, "CLOSE_PERSISTENT", CPLSPrintf("CouchDB:%p", this));
-        CPLHTTPFetch( osURL, papszOptions);
+        CPLHTTPDestroyResult( CPLHTTPFetch( osURL, papszOptions ) );
         CSLDestroy(papszOptions);
     }
 
@@ -135,9 +135,9 @@ OGRLayer* OGRCouchDBDataSource::OpenDatabase(const char* pszLayerName)
         if (pszLastSlash)
         {
             osEscapedName = pszLastSlash + 1;
-            char* pszName = CPLUnescapeString(osEscapedName, NULL, CPLES_URL);
-            osTableName = pszName;
-            CPLFree(pszName);
+            char* l_pszName = CPLUnescapeString(osEscapedName, NULL, CPLES_URL);
+            osTableName = l_pszName;
+            CPLFree(l_pszName);
             *pszLastSlash = 0;
         }
         osURL = pszURL;
@@ -207,16 +207,16 @@ int OGRCouchDBDataSource::Open( const char * pszFilename, int bUpdateIn)
 
 {
     int bHTTP = FALSE;
-    if (strncmp(pszFilename, "http://", 7) == 0 ||
-        strncmp(pszFilename, "https://", 8) == 0)
+    if (STARTS_WITH(pszFilename, "http://") ||
+        STARTS_WITH(pszFilename, "https://"))
         bHTTP = TRUE;
-    else if (!EQUALN(pszFilename, "CouchDB:", 8))
+    else if (!STARTS_WITH_CI(pszFilename, "CouchDB:"))
         return FALSE;
 
     bReadWrite = bUpdateIn;
 
     pszName = CPLStrdup( pszFilename );
- 
+
     if (bHTTP)
         osURL = pszFilename;
     else
@@ -255,7 +255,7 @@ int OGRCouchDBDataSource::Open( const char * pszFilename, int bUpdateIn)
 
     if (poAnswerObj == NULL)
     {
-        if (!EQUALN(pszFilename, "CouchDB:", 8))
+        if (!STARTS_WITH_CI(pszFilename, "CouchDB:"))
             CPLErrorReset();
         return FALSE;
     }
@@ -316,7 +316,7 @@ int OGRCouchDBDataSource::Open( const char * pszFilename, int bUpdateIn)
 /*                          ICreateLayer()                              */
 /************************************************************************/
 
-OGRLayer   *OGRCouchDBDataSource::ICreateLayer( const char *pszName,
+OGRLayer   *OGRCouchDBDataSource::ICreateLayer( const char *pszNameIn,
                                            OGRSpatialReference *poSpatialRef,
                                            OGRwkbGeometryType eGType,
                                            char ** papszOptions )
@@ -335,12 +335,12 @@ OGRLayer   *OGRCouchDBDataSource::ICreateLayer( const char *pszName,
 
     for( iLayer = 0; iLayer < nLayers; iLayer++ )
     {
-        if( EQUAL(pszName,papoLayers[iLayer]->GetName()) )
+        if( EQUAL(pszNameIn,papoLayers[iLayer]->GetName()) )
         {
             if( CSLFetchNameValue( papszOptions, "OVERWRITE" ) != NULL
                 && !EQUAL(CSLFetchNameValue(papszOptions,"OVERWRITE"),"NO") )
             {
-                DeleteLayer( pszName );
+                DeleteLayer( pszNameIn );
                 break;
             }
             else
@@ -349,13 +349,13 @@ OGRLayer   *OGRCouchDBDataSource::ICreateLayer( const char *pszName,
                           "Layer %s already exists, CreateLayer failed.\n"
                           "Use the layer creation option OVERWRITE=YES to "
                           "replace it.",
-                          pszName );
+                          pszNameIn );
                 return NULL;
             }
         }
     }
 
-    char* pszEscapedName = CPLEscapeString(pszName, -1, CPLES_URL);
+    char* pszEscapedName = CPLEscapeString(pszNameIn, -1, CPLES_URL);
     CPLString osEscapedName = pszEscapedName;
     CPLFree(pszEscapedName);
 
@@ -416,7 +416,7 @@ OGRLayer   *OGRCouchDBDataSource::ICreateLayer( const char *pszName,
     {
         osValidation = "{\"validate_doc_update\": \"function(new_doc, old_doc, userCtx) {if (userCtx.roles.indexOf('_admin') === -1) { throw({forbidden: \\\"No changes allowed except by admin.\\\"}); } }\" }";
     }
-    else if (strncmp(pszUpdatePermissions, "function(", 9) == 0)
+    else if (STARTS_WITH(pszUpdatePermissions, "function("))
     {
         osValidation = "{\"validate_doc_update\": \"";
         osValidation += pszUpdatePermissions;
@@ -437,10 +437,10 @@ OGRLayer   *OGRCouchDBDataSource::ICreateLayer( const char *pszName,
         json_object_put(poAnswerObj);
     }
 
-    int bGeoJSONDocument = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "GEOJSON", "TRUE"));
+    int bGeoJSONDocument = CPLTestBool(CSLFetchNameValueDef(papszOptions, "GEOJSON", "TRUE"));
     int nCoordPrecision = atoi(CSLFetchNameValueDef(papszOptions, "COORDINATE_PRECISION", "-1"));
 
-    OGRCouchDBTableLayer* poLayer = new OGRCouchDBTableLayer(this, pszName);
+    OGRCouchDBTableLayer* poLayer = new OGRCouchDBTableLayer(this, pszNameIn);
     if (nCoordPrecision != -1)
         poLayer->SetCoordinatePrecision(nCoordPrecision);
     poLayer->SetInfoAfterCreation(eGType, poSpatialRef, nUpdateSeq, bGeoJSONDocument);
@@ -559,7 +559,7 @@ OGRLayer * OGRCouchDBDataSource::ExecuteSQL( const char *pszSQLCommand,
 /* -------------------------------------------------------------------- */
 /*      Special case DELLAYER: command.                                 */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszSQLCommand,"DELLAYER:",9) )
+    if( STARTS_WITH_CI(pszSQLCommand, "DELLAYER:") )
     {
         const char *pszLayerName = pszSQLCommand + 9;
 
@@ -573,7 +573,7 @@ OGRLayer * OGRCouchDBDataSource::ExecuteSQL( const char *pszSQLCommand,
 /* -------------------------------------------------------------------- */
 /*      Special case 'COMPACT ON ' command.                             */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszSQLCommand,"COMPACT ON ",11) )
+    if( STARTS_WITH_CI(pszSQLCommand, "COMPACT ON ") )
     {
         const char *pszLayerName = pszSQLCommand + 11;
 
@@ -594,7 +594,7 @@ OGRLayer * OGRCouchDBDataSource::ExecuteSQL( const char *pszSQLCommand,
 /* -------------------------------------------------------------------- */
 /*      Special case 'VIEW CLEANUP ON ' command.                        */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszSQLCommand,"VIEW CLEANUP ON ",16) )
+    if( STARTS_WITH_CI(pszSQLCommand, "VIEW CLEANUP ON ") )
     {
         const char *pszLayerName = pszSQLCommand + 16;
 
@@ -615,7 +615,7 @@ OGRLayer * OGRCouchDBDataSource::ExecuteSQL( const char *pszSQLCommand,
 /* -------------------------------------------------------------------- */
 /*      Deal with "DELETE FROM layer_name WHERE expression" statement   */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszSQLCommand, "DELETE FROM ", 12) )
+    if( STARTS_WITH_CI(pszSQLCommand, "DELETE FROM ") )
     {
         const char* pszIter = pszSQLCommand + 12;
         while(*pszIter && *pszIter != ' ')
@@ -641,7 +641,7 @@ OGRLayer * OGRCouchDBDataSource::ExecuteSQL( const char *pszSQLCommand,
 
         while(*pszIter && *pszIter == ' ')
             pszIter ++;
-        if (!EQUALN(pszIter, "WHERE ", 5))
+        if (!STARTS_WITH_CI(pszIter, "WHERE "))
         {
             CPLError(CE_Failure, CPLE_AppDefined, "WHERE clause missing");
             return NULL;
@@ -664,7 +664,7 @@ OGRLayer * OGRCouchDBDataSource::ExecuteSQL( const char *pszSQLCommand,
             pNode->nSubExprCount == 2 &&
             pNode->papoSubExpr[0]->eNodeType == SNT_COLUMN &&
             pNode->papoSubExpr[1]->eNodeType == SNT_CONSTANT &&
-            pNode->papoSubExpr[0]->field_index == _ID_FIELD &&
+            pNode->papoSubExpr[0]->field_index == COUCHDB_ID_FIELD &&
             pNode->papoSubExpr[1]->field_type == SWQ_STRING)
         {
             poTableLayer->DeleteFeature(pNode->papoSubExpr[1]->string_value);
@@ -683,7 +683,7 @@ OGRLayer * OGRCouchDBDataSource::ExecuteSQL( const char *pszSQLCommand,
 /* -------------------------------------------------------------------- */
 /*      Try an optimized implementation when doing only stats           */
 /* -------------------------------------------------------------------- */
-    if (poSpatialFilter == NULL && EQUALN(pszSQLCommand, "SELECT", 6))
+    if (poSpatialFilter == NULL && STARTS_WITH_CI(pszSQLCommand, "SELECT"))
     {
         OGRLayer* poRet = ExecuteSQLStats(pszSQLCommand);
         if (poRet)
@@ -736,7 +736,7 @@ class OGRCouchDBOneLineLayer : public OGRLayer
 OGRLayer * OGRCouchDBDataSource::ExecuteSQLStats( const char *pszSQLCommand )
 {
     swq_select sSelectInfo;
-    if( sSelectInfo.preparse( pszSQLCommand ) != CPLE_None )
+    if( sSelectInfo.preparse( pszSQLCommand ) != CE_None )
     {
         return NULL;
     }
@@ -845,7 +845,7 @@ OGRLayer * OGRCouchDBDataSource::ExecuteSQLStats( const char *pszSQLCommand )
 /*      Finish the parse operation.                                     */
 /* -------------------------------------------------------------------- */
 
-    if( sSelectInfo.parse( &sFieldList, 0 ) != CE_None )
+    if( sSelectInfo.parse( &sFieldList, NULL ) != CE_None )
     {
         return NULL;
     }
@@ -1032,12 +1032,12 @@ char* OGRCouchDBDataSource::GetETag(const char* pszURI)
     char **papszTokens;
     char** papszOptions = NULL;
 
-    bMustCleanPersistant = TRUE;
+    bMustCleanPersistent = TRUE;
 
     papszOptions = CSLAddString(papszOptions, CPLSPrintf("PERSISTENT=CouchDB:%p", this));
     papszOptions = CSLAddString(papszOptions, "HEADERS=Content-Type: application/json");
     papszOptions = CSLAddString(papszOptions, "NO_BODY=1");
-    
+
     if (osUserPwd.size())
     {
         CPLString osUserPwdOption("USERPWD=");
@@ -1059,9 +1059,9 @@ char* OGRCouchDBDataSource::GetETag(const char* pszURI)
 
     if (CSLFetchNameValue(psResult->papszHeaders, "Etag") != NULL)
     {
-        papszTokens = 
+        papszTokens =
             CSLTokenizeString2( CSLFetchNameValue(psResult->papszHeaders, "Etag"), "\"\r\n", 0 );
-        
+
         pszEtag = CPLStrdup(papszTokens[0]);
 
         CSLDestroy( papszTokens );
@@ -1079,7 +1079,7 @@ json_object* OGRCouchDBDataSource::REQUEST(const char* pszVerb,
                                            const char* pszURI,
                                            const char* pszData)
 {
-    bMustCleanPersistant = TRUE;
+    bMustCleanPersistent = TRUE;
 
     char** papszOptions = NULL;
     papszOptions = CSLAddString(papszOptions, CPLSPrintf("PERSISTENT=CouchDB:%p", this));
@@ -1114,7 +1114,7 @@ json_object* OGRCouchDBDataSource::REQUEST(const char* pszVerb,
         return NULL;
 
     const char* pszServer = CSLFetchNameValue(psResult->papszHeaders, "Server");
-    if (pszServer == NULL || !EQUALN(pszServer, "CouchDB", 7))
+    if (pszServer == NULL || !STARTS_WITH_CI(pszServer, "CouchDB"))
     {
         CPLHTTPDestroyResult(psResult);
         return NULL;
@@ -1207,7 +1207,7 @@ int OGRCouchDBDataSource::IsError(json_object* poAnswerObj,
         CPLError(CE_Failure, CPLE_AppDefined,
                  "%s : %s, %s",
                  pszErrorMsg,
-                 pszError ? pszError : "",
+                 pszError,
                  pszReason ? pszReason : "");
 
         return TRUE;
@@ -1241,7 +1241,7 @@ int OGRCouchDBDataSource::IsOK(json_object* poAnswerObj,
     }
 
     const char* pszOK = json_object_get_string(poOK);
-    if ( !pszOK || !CSLTestBoolean(pszOK) )
+    if ( !pszOK || !CPLTestBool(pszOK) )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "%s", pszErrorMsg);
 
diff --git a/ogr/ogrsf_frmts/couchdb/ogrcouchdbdriver.cpp b/ogr/ogrsf_frmts/couchdb/ogrcouchdbdriver.cpp
index 786337e..61327d6 100644
--- a/ogr/ogrsf_frmts/couchdb/ogrcouchdbdriver.cpp
+++ b/ogr/ogrsf_frmts/couchdb/ogrcouchdbdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrcouchdbdriver.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogrcouchdbdriver.cpp 31122 2015-10-25 09:28:57Z rouault $
  *
  * Project:  CouchDB Translator
  * Purpose:  Implements OGRCouchDBDriver.
@@ -31,7 +31,7 @@
 
 // g++ -g -Wall -fPIC -shared -o ogr_CouchDB.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/couchdb ogr/ogrsf_frmts/couchdb/*.c* -L. -lgdal -Iogr/ogrsf_frmts/geojson/jsonc
 
-CPL_CVSID("$Id: ogrcouchdbdriver.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogrcouchdbdriver.cpp 31122 2015-10-25 09:28:57Z rouault $");
 
 extern "C" void RegisterOGRCouchDB();
 
@@ -61,12 +61,12 @@ const char *OGRCouchDBDriver::GetName()
 OGRDataSource *OGRCouchDBDriver::Open( const char * pszFilename, int bUpdate )
 
 {
-    if (strncmp(pszFilename, "http://", 7) == 0 ||
-        strncmp(pszFilename, "https://", 8) == 0)
+    if (STARTS_WITH(pszFilename, "http://") ||
+        STARTS_WITH(pszFilename, "https://"))
     {
         /* ok */
     }
-    else if (!EQUALN(pszFilename, "CouchDB:", 8))
+    else if (!STARTS_WITH_CI(pszFilename, "CouchDB:"))
         return NULL;
 
     OGRCouchDBDataSource   *poDS = new OGRCouchDBDataSource();
diff --git a/ogr/ogrsf_frmts/couchdb/ogrcouchdblayer.cpp b/ogr/ogrsf_frmts/couchdb/ogrcouchdblayer.cpp
index a070362..500a01f 100644
--- a/ogr/ogrsf_frmts/couchdb/ogrcouchdblayer.cpp
+++ b/ogr/ogrsf_frmts/couchdb/ogrcouchdblayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrcouchdblayer.cpp 28382 2015-01-30 15:29:41Z rouault $
+ * $Id: ogrcouchdblayer.cpp 32247 2015-12-19 07:05:52Z goatbar $
  *
  * Project:  CouchDB Translator
  * Purpose:  Implements OGRCouchDBLayer class.
@@ -31,30 +31,22 @@
 #include "ogrgeojsonreader.h"
 #include "ogrgeojsonutils.h"
 
-CPL_CVSID("$Id: ogrcouchdblayer.cpp 28382 2015-01-30 15:29:41Z rouault $");
+CPL_CVSID("$Id: ogrcouchdblayer.cpp 32247 2015-12-19 07:05:52Z goatbar $");
 
 /************************************************************************/
 /*                            OGRCouchDBLayer()                             */
 /************************************************************************/
 
-OGRCouchDBLayer::OGRCouchDBLayer(OGRCouchDBDataSource* poDS)
-
-{
-    this->poDS = poDS;
-
-    nNextInSeq = 0;
-
-    poSRS = NULL;
-
-    poFeatureDefn = NULL;
-
-    nOffset = 0;
-    bEOF = FALSE;
-
-    poFeatures = NULL;
-
-    bGeoJSONDocument = TRUE;
-}
+OGRCouchDBLayer::OGRCouchDBLayer(OGRCouchDBDataSource* poDSIn) :
+    poDS(poDSIn),
+    poFeatureDefn(NULL),
+    poSRS(NULL),
+    nNextInSeq(0),
+    nOffset(0),
+    bEOF(FALSE),
+    poFeatures(NULL),
+    bGeoJSONDocument(TRUE)
+{}
 
 /************************************************************************/
 /*                            ~OGRCouchDBLayer()                            */
@@ -104,15 +96,15 @@ OGRFeature *OGRCouchDBLayer::GetNextFeature()
 
     GetLayerDefn();
 
-    while(TRUE)
+    while( true )
     {
         if (nNextInSeq < nOffset ||
-            nNextInSeq >= nOffset + (int)aoFeatures.size())
+            nNextInSeq >= nOffset + static_cast<int>(aoFeatures.size()))
         {
             if (bEOF)
                 return NULL;
 
-            nOffset += aoFeatures.size();
+            nOffset += static_cast<int>(aoFeatures.size());
             if (!FetchNextRows())
                 return NULL;
         }
@@ -192,7 +184,7 @@ OGRFeature* OGRCouchDBLayer::TranslateFeature( json_object* poObj )
     const char* pszId = json_object_get_string(poId);
     if (pszId)
     {
-        poFeature->SetField(_ID_FIELD, pszId);
+        poFeature->SetField(COUCHDB_ID_FIELD, pszId);
 
         int nFID = atoi(pszId);
         const char* pszFID = CPLSPrintf("%09d", nFID);
@@ -203,7 +195,7 @@ OGRFeature* OGRCouchDBLayer::TranslateFeature( json_object* poObj )
     json_object* poRev = json_object_object_get(poObj, "_rev");
     const char* pszRev = json_object_get_string(poRev);
     if (pszRev)
-        poFeature->SetField(_REV_FIELD, pszRev);
+        poFeature->SetField(COUCHDB_REV_FIELD, pszRev);
 
 /* -------------------------------------------------------------------- */
 /*      Translate GeoJSON "properties" object to feature attributes.    */
@@ -526,7 +518,7 @@ int OGRCouchDBLayer::FetchNextRowsAnalyseDocs(json_object* poAnswerObj)
 
         json_object* poId = json_object_object_get(poDoc, "_id");
         const char* pszId = json_object_get_string(poId);
-        if (pszId != NULL && strncmp(pszId, "_design/", 8) != 0)
+        if (pszId != NULL && !STARTS_WITH(pszId, "_design/"))
         {
             aoFeatures.push_back(poDoc);
         }
diff --git a/ogr/ogrsf_frmts/couchdb/ogrcouchdbrowslayer.cpp b/ogr/ogrsf_frmts/couchdb/ogrcouchdbrowslayer.cpp
index 0f565cd..01b6357 100644
--- a/ogr/ogrsf_frmts/couchdb/ogrcouchdbrowslayer.cpp
+++ b/ogr/ogrsf_frmts/couchdb/ogrcouchdbrowslayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrcouchdbrowslayer.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogrcouchdbrowslayer.cpp 32370 2015-12-20 19:40:13Z rouault $
  *
  * Project:  CouchDB Translator
  * Purpose:  Implements OGRCouchDBRowsLayer class.
@@ -29,15 +29,15 @@
 
 #include "ogr_couchdb.h"
 
-CPL_CVSID("$Id: ogrcouchdbrowslayer.cpp 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: ogrcouchdbrowslayer.cpp 32370 2015-12-20 19:40:13Z rouault $");
 
 /************************************************************************/
 /*                         OGRCouchDBRowsLayer()                        */
 /************************************************************************/
 
-OGRCouchDBRowsLayer::OGRCouchDBRowsLayer(OGRCouchDBDataSource* poDS) :
-                                                    OGRCouchDBLayer(poDS)
-
+OGRCouchDBRowsLayer::OGRCouchDBRowsLayer(OGRCouchDBDataSource* poDSIn) :
+    OGRCouchDBLayer(poDSIn),
+    bAllInOne(FALSE)
 {
     poFeatureDefn = new OGRFeatureDefn( "rows" );
     poFeatureDefn->Reference();
@@ -49,18 +49,13 @@ OGRCouchDBRowsLayer::OGRCouchDBRowsLayer(OGRCouchDBDataSource* poDS) :
     poFeatureDefn->AddFieldDefn(&oFieldRev);
 
     SetDescription( poFeatureDefn->GetName() );
-
-    bAllInOne = FALSE;
 }
 
 /************************************************************************/
 /*                        ~OGRCouchDBRowsLayer()                        */
 /************************************************************************/
 
-OGRCouchDBRowsLayer::~OGRCouchDBRowsLayer()
-
-{
-}
+OGRCouchDBRowsLayer::~OGRCouchDBRowsLayer() {}
 
 /************************************************************************/
 /*                            ResetReading()                            */
@@ -111,7 +106,7 @@ int OGRCouchDBRowsLayer::FetchNextRows()
     {
         if (!bHasEsperluet)
         {
-            bHasEsperluet = TRUE;
+            /*bHasEsperluet = TRUE;*/
             osURI += "?";
         }
 
diff --git a/ogr/ogrsf_frmts/couchdb/ogrcouchdbtablelayer.cpp b/ogr/ogrsf_frmts/couchdb/ogrcouchdbtablelayer.cpp
index 4fbbd15..d3814e0 100644
--- a/ogr/ogrsf_frmts/couchdb/ogrcouchdbtablelayer.cpp
+++ b/ogr/ogrsf_frmts/couchdb/ogrcouchdbtablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrcouchdbtablelayer.cpp 28928 2015-04-17 10:24:19Z rouault $
+ * $Id: ogrcouchdbtablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  CouchDB Translator
  * Purpose:  Implements OGRCouchDBTableLayer class.
@@ -34,50 +34,43 @@
 
 #include <algorithm>
 
-CPL_CVSID("$Id: ogrcouchdbtablelayer.cpp 28928 2015-04-17 10:24:19Z rouault $");
+CPL_CVSID("$Id: ogrcouchdbtablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                       OGRCouchDBTableLayer()                         */
 /************************************************************************/
 
-OGRCouchDBTableLayer::OGRCouchDBTableLayer(OGRCouchDBDataSource* poDS,
-                                           const char* pszName) :
-                                                        OGRCouchDBLayer(poDS)
-
+OGRCouchDBTableLayer::OGRCouchDBTableLayer( OGRCouchDBDataSource* poDSIn,
+                                            const char* pszName) :
+    OGRCouchDBLayer(poDSIn),
+    nNextFIDForCreate(-1),
+    bInTransaction(FALSE),
+    bHasOGRSpatial(-1),
+    bHasGeocouchUtilsMinimalSpatialView(FALSE),
+    bServerSideAttributeFilteringWorks(TRUE),
+    bHasInstalledAttributeFilter(FALSE),
+    nUpdateSeq(-1),
+    bAlwaysValid(FALSE),
+    osName(pszName),
+    bMustWriteMetadata(FALSE),
+    bMustRunSpatialFilter(FALSE),
+    bServerSideSpatialFilteringWorks(TRUE),
+    bHasLoadedMetadata(FALSE),
+    bExtentValid(FALSE),
+    bExtentSet(FALSE),
+    dfMinX(0),
+    dfMinY(0),
+    dfMaxX(0),
+    dfMaxY(0),
+    eGeomType(wkbUnknown)
 {
-    osName = pszName;
     char* pszEscapedName = CPLEscapeString(pszName, -1, CPLES_URL);
     osEscapedName = pszEscapedName;
     CPLFree(pszEscapedName);
 
-    bInTransaction = FALSE;
-
-    eGeomType = wkbUnknown;
-
-    nNextFIDForCreate = -1;
-    bHasLoadedMetadata = FALSE;
-    bMustWriteMetadata = FALSE;
-
-    bMustRunSpatialFilter = FALSE;
-    bServerSideSpatialFilteringWorks = TRUE;
-    bHasOGRSpatial = -1;
-    bHasGeocouchUtilsMinimalSpatialView = FALSE;
+    nCoordPrecision = atoi(
+        CPLGetConfigOption( "OGR_COUCHDB_COORDINATE_PRECISION", "-1" ) );
 
-    bServerSideAttributeFilteringWorks = TRUE;
-    bHasInstalledAttributeFilter = FALSE;
-
-    nUpdateSeq = -1;
-    bAlwaysValid = FALSE;
-
-    bExtentValid = FALSE;
-    bExtentSet = FALSE;
-    dfMinX = 0;
-    dfMinY = 0;
-    dfMaxX = 0;
-    dfMaxY = 0;
-
-    nCoordPrecision = atoi(CPLGetConfigOption("OGR_COUCHDB_COORDINATE_PRECISION", "-1"));
-    
     SetDescription( osName );
 }
 
@@ -433,7 +426,7 @@ int OGRCouchDBTableLayer::HasFilterOnFieldOrCreateIfNecessary(const char* pszFie
         else
             json_object_object_add(poFilter, "reduce", json_object_new_string("_count"));
 
-        json_object* poAnswerObj = poDS->PUT(osURI,
+        poAnswerObj = poDS->PUT(osURI,
                                             json_object_to_json_string(poDoc));
 
         json_object_put(poDoc);
@@ -561,7 +554,7 @@ CPLString OGRCouchDBTableLayer::BuildAttrQueryURI(int& bOutHasStrictComparisons)
         const char* pszFieldName = poFeatureDefn->GetFieldDefn(nIndex)->GetNameRef();
 
         if (pNode->nOperation == SWQ_EQ &&
-            nIndex == _ID_FIELD && eType == SWQ_STRING)
+            nIndex == COUCHDB_ID_FIELD && eType == SWQ_STRING)
         {
             bCanHandleFilter = TRUE;
 
@@ -569,7 +562,7 @@ CPLString OGRCouchDBTableLayer::BuildAttrQueryURI(int& bOutHasStrictComparisons)
             osURI += osEscapedName;
             osURI += "/_all_docs?";
         }
-        else if (nIndex >= FIRST_FIELD &&
+        else if (nIndex >= COUCHDB_FIRST_FIELD &&
             (eType == SWQ_STRING || eType == SWQ_INTEGER ||
              eType == SWQ_INTEGER64 || eType == SWQ_FLOAT))
         {
@@ -624,7 +617,7 @@ CPLString OGRCouchDBTableLayer::BuildAttrQueryURI(int& bOutHasStrictComparisons)
         const char* pszFieldName = poFeatureDefn->GetFieldDefn(nIndex0)->GetNameRef();
 
         if (nIndex0 == nIndex1 && eType0 == eType1 &&
-            nIndex0 == _ID_FIELD && eType0 == SWQ_STRING)
+            nIndex0 == COUCHDB_ID_FIELD && eType0 == SWQ_STRING)
         {
             bCanHandleFilter = TRUE;
 
@@ -633,7 +626,7 @@ CPLString OGRCouchDBTableLayer::BuildAttrQueryURI(int& bOutHasStrictComparisons)
             osURI += "/_all_docs?";
         }
         else if (nIndex0 == nIndex1 && eType0 == eType1 &&
-            nIndex0 >= FIRST_FIELD &&
+            nIndex0 >= COUCHDB_FIRST_FIELD &&
             (eType0 == SWQ_STRING || eType0 == SWQ_INTEGER ||
              eType0 == SWQ_INTEGER64 || eType0 == SWQ_FLOAT))
         {
@@ -686,7 +679,7 @@ CPLString OGRCouchDBTableLayer::BuildAttrQueryURI(int& bOutHasStrictComparisons)
         swq_field_type eType = pNode->papoSubExpr[0]->field_type;
         const char* pszFieldName = poFeatureDefn->GetFieldDefn(nIndex)->GetNameRef();
 
-        if (nIndex == _ID_FIELD && eType == SWQ_STRING)
+        if (nIndex == COUCHDB_ID_FIELD && eType == SWQ_STRING)
         {
             bCanHandleFilter = TRUE;
 
@@ -694,7 +687,7 @@ CPLString OGRCouchDBTableLayer::BuildAttrQueryURI(int& bOutHasStrictComparisons)
             osURI += osEscapedName;
             osURI += "/_all_docs?";
         }
-        else if (nIndex >= FIRST_FIELD &&
+        else if (nIndex >= COUCHDB_FIRST_FIELD &&
             (eType == SWQ_STRING || eType == SWQ_INTEGER ||
              eType == SWQ_INTEGER64 || eType == SWQ_FLOAT))
         {
@@ -1076,9 +1069,9 @@ static json_object* OGRCouchDBWriteFeature( OGRFeature* poFeature,
     json_object* poObj = json_object_new_object();
     CPLAssert( NULL != poObj );
 
-    if (poFeature->IsFieldSet(_ID_FIELD))
+    if (poFeature->IsFieldSet(COUCHDB_ID_FIELD))
     {
-        const char* pszId = poFeature->GetFieldAsString(_ID_FIELD);
+        const char* pszId = poFeature->GetFieldAsString(COUCHDB_ID_FIELD);
         json_object_object_add( poObj, "_id",
                                 json_object_new_string(pszId) );
 
@@ -1097,9 +1090,9 @@ static json_object* OGRCouchDBWriteFeature( OGRFeature* poFeature,
                                 json_object_new_string(CPLSPrintf("%09ld", (long)poFeature->GetFID())) );
     }
 
-    if (poFeature->IsFieldSet(_REV_FIELD))
+    if (poFeature->IsFieldSet(COUCHDB_REV_FIELD))
     {
-        const char* pszRev = poFeature->GetFieldAsString(_REV_FIELD);
+        const char* pszRev = poFeature->GetFieldAsString(COUCHDB_REV_FIELD);
         json_object_object_add( poObj, "_rev",
                                 json_object_new_string(pszRev) );
     }
@@ -1115,7 +1108,7 @@ static json_object* OGRCouchDBWriteFeature( OGRFeature* poFeature,
 /* -------------------------------------------------------------------- */
     json_object* poObjProps = NULL;
 
-    poObjProps = OGRGeoJSONWriteAttributes( poFeature );
+    poObjProps = OGRGeoJSONWriteAttributes( poFeature, -1 );
     if (poObjProps)
     {
         json_object_object_del(poObjProps, "_id");
@@ -1150,7 +1143,7 @@ static json_object* OGRCouchDBWriteFeature( OGRFeature* poFeature,
         OGRGeometry* poGeometry = poFeature->GetGeometryRef();
         if ( NULL != poGeometry )
         {
-            poObjGeom = OGRGeoJSONWriteGeometry( poGeometry, nCoordPrecision );
+            poObjGeom = OGRGeoJSONWriteGeometry( poGeometry, nCoordPrecision, -1 );
             if ( poObjGeom != NULL &&
                  wkbFlatten(poGeometry->getGeometryType()) != wkbPoint &&
                  !poGeometry->IsEmpty() )
@@ -1215,7 +1208,7 @@ int OGRCouchDBTableLayer::GetMaximumId()
         json_object_put(poAnswerObj);
         return -1;
     }
-    
+
     json_object* poRow = json_object_array_get_idx(poRows, 0);
     if ( poRow == NULL ||
             !json_object_is_type(poRow, json_type_object) )
@@ -1254,7 +1247,7 @@ OGRErr OGRCouchDBTableLayer::ICreateFeature( OGRFeature *poFeature )
         return OGRERR_FAILURE;
     }
 
-    if (poFeature->IsFieldSet(_REV_FIELD))
+    if (poFeature->IsFieldSet(COUCHDB_REV_FIELD))
     {
         static int bOnce = FALSE;
         if (!bOnce)
@@ -1262,7 +1255,7 @@ OGRErr OGRCouchDBTableLayer::ICreateFeature( OGRFeature *poFeature )
             bOnce = TRUE;
             CPLDebug("CouchDB", "CreateFeature() should be called with an unset _rev field. Ignoring it");
         }
-        poFeature->UnsetField(_REV_FIELD);
+        poFeature->UnsetField(COUCHDB_REV_FIELD);
     }
 
     if (nNextFIDForCreate < 0)
@@ -1302,8 +1295,8 @@ OGRErr OGRCouchDBTableLayer::ICreateFeature( OGRFeature *poFeature )
 
     int nFID = nNextFIDForCreate ++;
     CPLString osFID;
-    if (!poFeature->IsFieldSet(_ID_FIELD) ||
-        !CSLTestBoolean(CPLGetConfigOption("COUCHDB_PRESERVE_ID_ON_INSERT", "FALSE")))
+    if (!poFeature->IsFieldSet(COUCHDB_ID_FIELD) ||
+        !CPLTestBool(CPLGetConfigOption("COUCHDB_PRESERVE_ID_ON_INSERT", "FALSE")))
     {
         if (poFeature->GetFID() != OGRNullFID)
         {
@@ -1311,12 +1304,12 @@ OGRErr OGRCouchDBTableLayer::ICreateFeature( OGRFeature *poFeature )
         }
         osFID = CPLSPrintf("%09d", nFID);
 
-        poFeature->SetField(_ID_FIELD, osFID);
+        poFeature->SetField(COUCHDB_ID_FIELD, osFID);
         poFeature->SetFID(nFID);
     }
     else
     {
-        const char* pszId = poFeature->GetFieldAsString(_ID_FIELD);
+        const char* pszId = poFeature->GetFieldAsString(COUCHDB_ID_FIELD);
         osFID = pszId;
     }
 
@@ -1356,18 +1349,18 @@ OGRErr OGRCouchDBTableLayer::ICreateFeature( OGRFeature *poFeature )
 
     if (pszId)
     {
-        poFeature->SetField(_ID_FIELD, pszId);
+        poFeature->SetField(COUCHDB_ID_FIELD, pszId);
 
-        int nFID = atoi(pszId);
-        const char* pszFID = CPLSPrintf("%09d", nFID);
+        int l_nFID = atoi(pszId);
+        const char* pszFID = CPLSPrintf("%09d", l_nFID);
         if (strcmp(pszId, pszFID) == 0)
-            poFeature->SetFID(nFID);
+            poFeature->SetFID(l_nFID);
         else
             poFeature->SetFID(-1);
     }
     if (pszRev)
     {
-        poFeature->SetField(_REV_FIELD, pszRev);
+        poFeature->SetField(COUCHDB_REV_FIELD, pszRev);
     }
 
     json_object_put(poAnswerObj);
@@ -1392,7 +1385,7 @@ OGRErr      OGRCouchDBTableLayer::ISetFeature( OGRFeature *poFeature )
         return OGRERR_FAILURE;
     }
 
-    if (!poFeature->IsFieldSet(_ID_FIELD))
+    if (!poFeature->IsFieldSet(COUCHDB_ID_FIELD))
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "SetFeature() requires non null _id field");
@@ -1407,7 +1400,7 @@ OGRErr      OGRCouchDBTableLayer::ISetFeature( OGRFeature *poFeature )
     CPLString osURI("/");
     osURI += osEscapedName;
     osURI += "/";
-    osURI += poFeature->GetFieldAsString(_ID_FIELD);
+    osURI += poFeature->GetFieldAsString(COUCHDB_ID_FIELD);
     json_object* poAnswerObj = poDS->PUT(osURI, pszJson);
     json_object_put( poObj );
 
@@ -1422,7 +1415,7 @@ OGRErr      OGRCouchDBTableLayer::ISetFeature( OGRFeature *poFeature )
 
     json_object* poRev = json_object_object_get(poAnswerObj, "rev");
     const char* pszRev = json_object_get_string(poRev);
-    poFeature->SetField(_REV_FIELD, pszRev);
+    poFeature->SetField(COUCHDB_REV_FIELD, pszRev);
 
     json_object_put(poAnswerObj);
 
@@ -1486,15 +1479,15 @@ OGRErr OGRCouchDBTableLayer::DeleteFeature( const char* pszId )
 
 OGRErr OGRCouchDBTableLayer::DeleteFeature( OGRFeature* poFeature )
 {
-    if (!poFeature->IsFieldSet(_ID_FIELD) ||
-        !poFeature->IsFieldSet(_REV_FIELD))
+    if (!poFeature->IsFieldSet(COUCHDB_ID_FIELD) ||
+        !poFeature->IsFieldSet(COUCHDB_REV_FIELD))
     {
         delete poFeature;
         return OGRERR_FAILURE;
     }
 
-    const char* pszId = poFeature->GetFieldAsString(_ID_FIELD);
-    const char* pszRev = poFeature->GetFieldAsString(_REV_FIELD);
+    const char* pszId = poFeature->GetFieldAsString(COUCHDB_ID_FIELD);
+    const char* pszRev = poFeature->GetFieldAsString(COUCHDB_REV_FIELD);
 
     CPLString osURI("/");
     osURI += osEscapedName;
@@ -1885,7 +1878,7 @@ void OGRCouchDBTableLayer::LoadMetadata()
         poFeatureDefn->Reference();
 
         poFeatureDefn->SetGeomType(eGeomType);
-        if( poFeatureDefn->GetGeomFieldCount() != 0 ) 
+        if( poFeatureDefn->GetGeomFieldCount() != 0 )
             poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 
         OGRFieldDefn oFieldId("_id", OFTString);
@@ -2007,7 +2000,7 @@ void OGRCouchDBTableLayer::WriteMetadata()
     json_object_object_add(poDoc, "fields", poFields);
 
 
-    for(int i=FIRST_FIELD;i<poFeatureDefn->GetFieldCount();i++)
+    for(int i=COUCHDB_FIRST_FIELD;i<poFeatureDefn->GetFieldCount();i++)
     {
         json_object* poField = json_object_new_object();
         json_object_array_add(poFields, poField);
diff --git a/ogr/ogrsf_frmts/csv/GNUmakefile b/ogr/ogrsf_frmts/csv/GNUmakefile
index 61a10d3..dfafad4 100644
--- a/ogr/ogrsf_frmts/csv/GNUmakefile
+++ b/ogr/ogrsf_frmts/csv/GNUmakefile
@@ -4,12 +4,12 @@ include ../../../GDALmake.opt
 
 OBJ	=	ogrcsvdriver.o ogrcsvdatasource.o ogrcsvlayer.o
 
-CPPFLAGS	:=	-I.. -I../..  $(CPPFLAGS)
+CPPFLAGS	:=	-I.. -I../.. -I../generic $(CPPFLAGS)
 
 default:	$(O_OBJ:.o=.$(OBJ_EXT))
 
 clean:
 	rm -f *.o $(O_OBJ)
 
-$(O_OBJ):	ogr_csv.h
+$(O_OBJ):	ogr_csv.h ../generic/ogreditablelayer.h
 
diff --git a/ogr/ogrsf_frmts/csv/drv_csv.html b/ogr/ogrsf_frmts/csv/drv_csv.html
index 5f48439..977e356 100644
--- a/ogr/ogrsf_frmts/csv/drv_csv.html
+++ b/ogr/ogrsf_frmts/csv/drv_csv.html
@@ -8,13 +8,13 @@
 <h1>Comma Separated Value (.csv)</h1>
 
 <p>OGR supports reading and writing primarily non-spatial tabular data stored in
-text CSV files.  CSV files are a common interchange format between 
+text CSV files.  CSV files are a common interchange format between
 software packages supporting tabular data and are also easily produced
 manually with a text editor or with end-user written scripts or programs.</p>
 
 <p>While in theory .csv files could have any extension, in order to
 auto-recognise the format OGR only supports CSV files ending with the
-extention ".csv".  The datasource name may be either a single CSV file
+extension ".csv".  The datasource name may be either a single CSV file
 or point to a directory.  For a directory to be recognised as a .csv datasource
 at least half the files in the directory need to have the extension .csv.
 One layer (table) is produced from each .csv file accessed.</p>
@@ -23,16 +23,16 @@ One layer (table) is produced from each .csv file accessed.</p>
 .CSV extension, the 'CSV:' prefix can be added before the filename to force
 loading by the CSV driver.</p>
 
-<p>The OGR CSV driver supports reading and writing. Because the CSV format 
-has variable length text lines, reading is done sequentially. Reading 
-features in random order will generally be very slow. OGR CSV layer never
-have any coordinate system.  When reading a field named "WKT" is assumed
+<p>The OGR CSV driver supports reading and writing. Because the CSV format
+has variable length text lines, reading is done sequentially. Reading
+features in random order will generally be very slow. OGR CSV layer might
+have a coordinate system stored in a .prj file (see GeoCSV specification).  When reading a field named "WKT" is assumed
 to contain WKT geometry, but also is treated as a regular field.
 The OGR CSV driver returns all attribute columns as string data types
 if no field type information file (with .csvt extension) is
 available.</p>
 
-<p>Limited type recognition can be done for Integer, Real, String, Date 
+<p>Limited type recognition can be done for Integer, Real, String, Date
 (YYYY-MM-DD), Time (HH:MM:SS+nn), DateTime (YYYY-MM-DD HH:MM:SS+nn) columns
 through a descriptive file with the same name as the CSV file, but a .csvt extension.
 In a single line the types for each column have to be listed with double quotes and
@@ -40,14 +40,17 @@ be comma separated (e.g., "Integer","String"). It is also possible to specify
 explicitly the width and precision of each column, e.g. "Integer(5)","Real(10.7)","String(15)".
 The driver will then use these types as specified for the csv columns.
 Starting with GDAL 2.0, subtypes can be passed between parenthesis, such as
-"Integer(Boolean)", "Integer(Int16)" and "Real(Float32)"</p>
+"Integer(Boolean)", "Integer(Int16)" and "Real(Float32)". Starting with GDAL 2.1,
+accordingly with the <a href="http://giswiki.hsr.ch/GeoCSV">GeoCSV specification</a>,
+the "CoordX" or "Point(X)" type can be used to specify a column with longitude/easting values,
+"CoordY" or "Point(Y)" for latitude/northing values and "WKT" for geometries encoded in WKT </p>
 
 <p>Starting with GDAL 2.0, automatic field type guessing can also be done if
 specifying the open options described in the below "Open options" section.</p>
 
 <h2>Format</h2>
 
-<p>CSV files have one line for each feature (record) in the layer (table).  
+<p>CSV files have one line for each feature (record) in the layer (table).
 The attribute field values are separated by commas. At least two fields
 per line must be present. Lines may be terminated by a DOS (CR/LF) or
 Unix (LF) style line terminators. Each record should have the same number
@@ -56,21 +59,22 @@ of fields. The driver will also accept a semicolon, a tabulation or a space
 if there's no other potential separator on the first line of the CSV file.
 Otherwise it will default to comma as separator.</p>
 
-<p>Complex attribute values (such as those containing commas, quotes or newlines) 
-may be placed in double quotes. Any occurances of double quotes within 
+<p>Complex attribute values (such as those containing commas, quotes or newlines)
+may be placed in double quotes. Any occurrences of double quotes within
 the quoted string should be doubled up to "escape" them.</p>
 
-<p>The driver attempts to treat the first line of the file as a list of field 
-names for all the fields. However, if one or more of the names is all 
+<p>By default, the driver attempts to treat the first line of the file as a list of field
+names for all the fields. However, if one or more of the names is all
 numeric it is assumed that the first line is actually data values and
 dummy field names are generated internally (field_1 through field_n) and
-the first record is treated as a feature. Starting with GDAL 1.9.0 
-numeric values are treated as field names if they are enclosed in double quotes. 
+the first record is treated as a feature. Starting with GDAL 1.9.0
+numeric values are treated as field names if they are enclosed in double quotes.
+Starting with GDAL 2.1, this behaviour can be modified via the HEADERS open option.
 </p>
 
 <p>All CSV files are treated as UTF-8 encoded. Starting with GDAL 1.9.0, a Byte
 Order Mark (BOM) at the beginning of the file will be parsed correctly. From 1.9.2,
-The option WRITE_BOM can be used to create a file with a Byte Order Mark, which can 
+The option WRITE_BOM can be used to create a file with a Byte Order Mark, which can
 improve compatibility with some software (particularly Excel).
 </p>
 
@@ -81,7 +85,7 @@ ID,Salary,Name,Comments
 133,11000.0,Jane Lake,Cleaning Staff
 </pre>
 
-<p>Note that the Comments value for the first data record is placed in 
+<p>Note that the Comments value for the first data record is placed in
 double quotes because the value contains quotes, and those quotes have
 to be doubled up so we know we haven't reached the end of the quoted string
 yet.</p>
@@ -89,16 +93,14 @@ yet.</p>
 <p>Many variations of textual input are sometimes called Comma Separated
 Value files, including files without commas, but fixed column widths,
 those using tabs as separators or those with other auxiliary data defining
-field types or structure. This driver does not attempt to support all 
-such files, but instead to support simple .csv files that can be 
+field types or structure. This driver does not attempt to support all
+such files, but instead to support simple .csv files that can be
 auto-recognised. Scripts or other mechanisms can generally be used to convert
 other variations into a form that is compatible with the OGR CSV driver.</p>
 
 <h2>Reading CSV containing spatial information</h2>
 
-<p>It is possible to extract spatial information (points) from a CSV file
-which has columns for the X and Y coordinates, through the use of the
-<a href="drv_vrt.html">VRT</a> driver.</p>
+<h3>Building point geometries</h3>
 
 <p>Consider the following CSV file (test.csv):
 <pre>
@@ -107,6 +109,34 @@ Latitude,Longitude,Name
 49.2,1.1,"Second point"
 47.5,0.75,"Third point"
 </pre>
+</p>
+
+<p>Starting with GDAL 2.1, it is possible to directly specify the potential
+names of the columns that can contain X/longitude and Y/latitude with the
+X_POSSIBLE_NAMES and Y_POSSIBLE_NAMES open option.</p>
+
+<p><i>ogrinfo -ro -al test.csv -oo X_POSSIBLE_NAMES=Lon* -oo Y_POSSIBLE_NAMES=Lat* -oo KEEP_GEOM_COLUMNS=NO</i> will return :</p>
+<pre>
+OGRFeature(test):1
+  Name (String) = First point
+  POINT (0.25 48.1)
+
+OGRFeature(test):2
+  Name (String) = Second point
+  POINT (1.1 49.2)
+
+OGRFeature(test):3
+  Name (String) = Third point
+  POINT (0.75 47.5)
+</pre>
+
+<p>Otherwise, if one
+or several columns contain a geometry definition encoded as WKT, WKB (encoded
+in hexadecimal) or GeoJSON, the name of such column(s) the GEOM_POSSIBLE_NAMES open option.</p>
+
+<p>For older versions, it is possible to extract spatial information (points) from a CSV file
+which has columns for the X and Y coordinates, through the use of the
+<a href="drv_vrt.html">VRT</a> driver.</p>
 
 You can write the associated VRT file (test.vrt):
 <pre>
@@ -142,6 +172,32 @@ OGRFeature(test):3
   POINT (0.75 47.5 0)
 </pre>
 
+<h3>Building line geometries</h3>
+
+<p>Consider the following CSV file (test.csv):
+<pre>
+way_id,pt_id,x,y
+1,1,2,49
+1,2,3,50
+2,1,-2,49
+2,2,-3,50
+</pre>
+</p>
+
+With a GDAL build with Spatialite enabled,
+
+<i>ogrinfo test.csv -dialect SQLite -sql "SELECT way_id, MakeLine(MakePoint(CAST(x AS float),CAST(y AS float))) FROM test GROUP BY way_id"</i> will return :
+<pre>
+OGRFeature(SELECT):0
+  way_id (String) = 1
+  LINESTRING (2 49,3 50)
+
+OGRFeature(SELECT):1
+  way_id (String) = 2
+  LINESTRING (-2 49,-3 50)
+</pre>
+
+
 <h2>Open options</h2>
 
 Starting with GDAL 2.0, the following open options can be specified
@@ -174,20 +230,51 @@ Setting 0 means inspecting the whole file.  Note : specifying a value over 1 MB
 Whether to enforce quoted fields as string fields when set to YES. Otherwise,
 by default, the content of quoted fields will be tested for real, integer, etc...
 data types.</li>
+<li><b>X_POSSIBLE_NAMES</b>=list_of_names. (GDAL >= 2.1) Comma separated list of
+possible names for X/longitude coordinate of a point. Each name might be a pattern
+using the star character in starting and/or ending position. E.g.: prefix*, *suffix or *middle*.
+The values in the column must be floating point values.
+X_POSSIBLE_NAMES and Y_POSSIBLE_NAMES must be both specified and a matching for
+each must be found in the columns of the CSV file. Only one geometry column per
+layer might be built when using X_POSSIBLE_NAMES/Y_POSSIBLE_NAMES.</li>
+<li><b>Y_POSSIBLE_NAMES</b>=list_of_names. (GDAL >= 2.1) Comma separated list of
+possible names for Y/latitude coordinate of a point. Each name might be a pattern
+using the star character in starting and/or ending position. E.g.: prefix*, *suffix or *middle*.
+The values in the column must be floating point values.
+X_POSSIBLE_NAMES and Y_POSSIBLE_NAMES must be both specified and a matching for
+each must be found in the columns of the CSV file.</li>
+<li><b>Z_POSSIBLE_NAMES</b>=list_of_names. (GDAL >= 2.1) Comma separated list of
+possible names for Z/elevation coordinate of a point. Each name might be a pattern
+using the star character in starting and/or ending position. E.g.: prefix*, *suffix or *middle*.
+The values in the column must be floating point values.
+Only taken into account in combination with X_POSSIBLE_NAMES and Y_POSSIBLE_NAMES.</li>
+<li><b>GEOM_POSSIBLE_NAMES</b>=list_of_names. (GDAL >= 2.1) Comma separated list of
+possible names for geometry columns that contain geometry definitions encoded as
+WKT, WKB (in hexadecimal form, potentially in PostGIS 2.0 extended WKB) or GeoJSON. Each name might be a pattern
+using the star character in starting and/or ending position. E.g.: prefix*, *suffix or *middle*</li>
+<li><b>KEEP_GEOM_COLUMNS</b>=YES/NO (default YES) Expose the detected X,Y,Z or geometry columns
+as regular attribute fields.</li>
+<li><b>HEADERS</b>=YES/NO/AUTO (default AUTO) (GDAL >= 2.1) Whether the first line of the file
+contains column names or not. When set to AUTO, GDAL will assume the first line is column names if none
+of the values are strictly numeric.
+<li><b>EMPTY_STRING_AS_NULL</b>=YES/NO (default NO) (GDAL >= 2.1)
+Whether to consider empty strings as null fields on reading'.</li>
 </ul>
 
 <h2>Creation Issues</h2>
 
 <p>The driver supports creating new databases (as a directory
 of .csv files), adding new .csv files to an existing directory or .csv
-files or appending features to an existing .csv table. Deleting or
-replacing existing features is not supported.</p>
+files or appending features to an existing .csv table. Starting with GDAL 2.1,
+deleting or replacing existing features, or adding/modifying/deleting fields is
+supported, provided the modifications done are small enough to be stored in RAM
+temporarily before flushing to disk.</p>
 
 <p>Layer Creation options:
 
 <ul>
 <li><b>LINEFORMAT</b>: By default when creating new .csv files they are created with the line
-termination conventions of the local platform (CR/LF on win32 or 
+termination conventions of the local platform (CR/LF on win32 or
 LF on all other systems).  This may be overridden through use of the
 LINEFORMAT layer creation option which may have a value of <b>CRLF</b>
 (DOS format) or <b>LF</b> (Unix format).</li><p>
@@ -199,7 +286,8 @@ The geometry column(s) will be prepended to the columns with the attributes valu
 <li><b>CREATE_CSVT</b>=YES/NO (Starting with GDAL 1.7.0): Create the associated .csvt file (see above paragraph)
 to describe the type of each column of the layer and its optional width and precision. Default value : NO</li><p>
 <li><b>SEPARATOR</b>=COMMA/SEMICOLON/TAB/SPACE (Starting with GDAL 1.7.0): Field separator character. Default value : COMMA</li><p>
-<li><b>WRITE_BOM</b>=YES/NO (Starting with GDAL >1.9.2): Write a UTF-8 Byte Order Mark (BOM) at the start of the file. Default value : NO</li><p>
+<li><b>WRITE_BOM</b>=YES/NO (Starting with GDAL 1.9.2): Write a UTF-8 Byte Order Mark (BOM) at the start of the file. Default value : NO</li><p>
+<lib><b>GEOMETRY_NAME</b>=name (Starting with GDAL 2.1): Name of geometry column. Only used if GEOMETRY=AS_WKT. Defaults to WKT</li><p>
 </ul>
 </p>
 
@@ -235,10 +323,11 @@ The CSV driver can also read files whose structure is close to CSV files :
 
 <p>
 <ul>
-<li>Initial development of the OGR CSV driver was supported by 
-<a href="http://www.dmsolutions.ca/">DM Solutions Group</a> and 
+<li><a href="http://giswiki.hsr.ch/GeoCSV">GeoCSV specification</a> (supported by GDAL >= 2.1)</li>
+<li>Initial development of the OGR CSV driver was supported by
+<a href="http://www.dmsolutions.ca/">DM Solutions Group</a> and
 <a href="http://www.gomoos.org/">GoMOOS</a>.
-<li><a href="https://cartodb.com/">CartoDB</a> funded field type auto-detection.</li>
+<li><a href="https://cartodb.com/">CartoDB</a> funded field type auto-detection and open options related to geometry columns.</li>
 </ul>
 </p>
 
diff --git a/ogr/ogrsf_frmts/csv/makefile.vc b/ogr/ogrsf_frmts/csv/makefile.vc
index b8b9c05..cf73890 100644
--- a/ogr/ogrsf_frmts/csv/makefile.vc
+++ b/ogr/ogrsf_frmts/csv/makefile.vc
@@ -1,6 +1,6 @@
 
 OBJ	=	ogrcsvdriver.obj ogrcsvdatasource.obj ogrcsvlayer.obj
-EXTRAFLAGS =	-I.. -I..\..
+EXTRAFLAGS =	-I.. -I..\.. -I..\generic
 
 GDAL_ROOT	=	..\..\..
 
diff --git a/ogr/ogrsf_frmts/csv/ogr_csv.h b/ogr/ogrsf_frmts/csv/ogr_csv.h
index 8e73dd3..f542e93 100644
--- a/ogr/ogrsf_frmts/csv/ogr_csv.h
+++ b/ogr/ogrsf_frmts/csv/ogr_csv.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_csv.h 29237 2015-05-24 08:38:20Z rouault $
+ * $Id: ogr_csv.h 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  CSV Translator
  * Purpose:  Definition of classes for OGR .csv driver.
@@ -28,8 +28,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_CSV_H_INCLUDED
-#define _OGR_CSV_H_INCLUDED
+#ifndef OGR_CSV_H_INCLUDED
+#define OGR_CSV_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 
@@ -37,6 +37,7 @@ typedef enum
 {
     OGR_CSV_GEOM_NONE,
     OGR_CSV_GEOM_AS_WKT,
+    OGR_CSV_GEOM_AS_SOME_GEOM_FORMAT,
     OGR_CSV_GEOM_AS_XYZ,
     OGR_CSV_GEOM_AS_XY,
     OGR_CSV_GEOM_AS_YX,
@@ -49,6 +50,15 @@ char **OGRCSVReadParseLineL( VSILFILE * fp, char chDelimiter,
                              int bKeepLeadingAndClosingQuotes = FALSE,
                              int bMergeDelimiter = FALSE);
 
+typedef enum
+{
+    CREATE_FIELD_DO_NOTHING,
+    CREATE_FIELD_PROCEED,
+    CREATE_FIELD_ERROR
+} OGRCSVCreateFieldAction;
+
+void OGRCSVDriverRemoveFromMap(const char* pszName, GDALDataset* poDS);
+
 /************************************************************************/
 /*                             OGRCSVLayer                              */
 /************************************************************************/
@@ -82,11 +92,16 @@ class OGRCSVLayer : public OGRLayer
     int                 bHiddenWKTColumn;
 
     /*http://www.faa.gov/airports/airport_safety/airportdata_5010/menu/index.cfm specific */
-    int                 iNfdcLatitudeS, iNfdcLongitudeS;
+    int                 iNfdcLongitudeS;
+    int                 iNfdcLatitudeS;
     int                 bDontHonourStrings;
 
-    /* GNIS specific */
-    int                 iLongitudeField, iLatitudeField;
+    int                 iLongitudeField;
+    int                 iLatitudeField;
+    int                 iZField;
+    CPLString           osXField;
+    CPLString           osYField;
+    CPLString           osZField;
 
     int                 bIsEurostatTSV;
     int                 nEurostatDims;
@@ -94,19 +109,36 @@ class OGRCSVLayer : public OGRLayer
     GIntBig             nTotalFeatures;
 
     char              **AutodetectFieldTypes(char** papszOpenOptions, int nFieldCount);
-    
+
     int                 bWarningBadTypeOrWidth;
     int                 bKeepSourceColumns;
-    
+    int                 bKeepGeomColumns;
+
     int                 bMergeDelimiter;
-    
+
+    int                 bEmptyStringNull;
+
     char              **GetNextLineTokens();
 
+    static int          Matches(const char* pszFieldName, char** papszPossibleNames);
+
   public:
     OGRCSVLayer( const char *pszName, VSILFILE *fp, const char *pszFilename,
                  int bNew, int bInWriteMode, char chDelimiter );
    ~OGRCSVLayer();
-  
+
+    const char*         GetFilename() const { return pszFilename; }
+    char                GetDelimiter() const { return chDelimiter; }
+    int                 GetCRLF() const { return bUseCRLF; }
+    int                 GetCreateCSVT() const { return bCreateCSVT; }
+    int                 GetWriteBOM() const { return bWriteBOM; }
+    OGRCSVGeometryFormat GetGeometryFormat() const { return eGeometryFormat; }
+    int                 HasHiddenWKTColumn() const { return bHiddenWKTColumn; }
+    GIntBig             GetTotalFeatureCount() const { return nTotalFeatures; }
+    const CPLString&    GetXField() const { return osXField; }
+    const CPLString&    GetYField() const { return osYField; }
+    const CPLString&    GetZField() const { return osZField; }
+
     void                BuildFeatureDefn( const char* pszNfdcGeomField = NULL,
                                           const char* pszGeonamesGeomFieldPrefix = NULL,
                                           char** papszOpenOptions = NULL );
@@ -121,6 +153,9 @@ class OGRCSVLayer : public OGRLayer
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
                                      int bApproxOK = TRUE );
+
+    static OGRCSVCreateFieldAction PreCreateField( OGRFeatureDefn* poFeatureDefn,
+                                    OGRFieldDefn *poNewField, int bApproxOK );
     virtual OGRErr      CreateGeomField( OGRGeomFieldDefn *poGeomField,
                                          int bApproxOK = TRUE );
 
@@ -128,11 +163,13 @@ class OGRCSVLayer : public OGRLayer
 
     void                SetCRLF(int);
     void                SetWriteGeometry(OGRwkbGeometryType eGType,
-                                         OGRCSVGeometryFormat eGeometryFormat);
+                                         OGRCSVGeometryFormat eGeometryFormat,
+                                         const char* pszGeomCol = NULL);
     void                SetCreateCSVT(int bCreateCSVT);
     void                SetWriteBOM(int bWriteBOM);
 
     virtual GIntBig     GetFeatureCount( int bForce = TRUE );
+    virtual OGRErr      SyncToDisk();
 
     OGRErr              WriteHeader();
 };
@@ -145,13 +182,13 @@ class OGRCSVDataSource : public OGRDataSource
 {
     char                *pszName;
 
-    OGRCSVLayer       **papoLayers;
+    OGRLayer          **papoLayers;
     int                 nLayers;
 
     int                 bUpdate;
 
     CPLString           osDefaultCSVName;
-    
+
     int                 bEnableGeometryFields;
 
   public:
@@ -165,13 +202,13 @@ class OGRCSVDataSource : public OGRDataSource
                                    char** papszOpenOptions,
                                    const char* pszNfdcRunwaysGeomField = NULL,
                                    const char* pszGeonamesGeomFieldPrefix = NULL);
-    
+
     const char          *GetName() { return pszName; }
 
     int                 GetLayerCount() { return nLayers; }
     OGRLayer            *GetLayer( int );
 
-    virtual OGRLayer   *ICreateLayer( const char *pszName, 
+    virtual OGRLayer   *ICreateLayer( const char *pszName,
                                      OGRSpatialReference *poSpatialRef = NULL,
                                      OGRwkbGeometryType eGType = wkbUnknown,
                                      char ** papszOptions = NULL );
@@ -180,12 +217,12 @@ class OGRCSVDataSource : public OGRDataSource
 
     int                 TestCapability( const char * );
 
-    void                SetDefaultCSVName( const char *pszName ) 
-        { osDefaultCSVName = pszName; }
+    void                CreateForSingleFile( const char* pszDirname,
+                                             const char *pszFilename );
 
     void                EnableGeometryFields() { bEnableGeometryFields = TRUE; }
 
     static CPLString    GetRealExtension(CPLString osFilename);
 };
 
-#endif /* ndef _OGR_CSV_H_INCLUDED */
+#endif /* ndef OGR_CSV_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/csv/ogrcsvdatasource.cpp b/ogr/ogrsf_frmts/csv/ogrcsvdatasource.cpp
index 0302f9b..3764717 100644
--- a/ogr/ogrsf_frmts/csv/ogrcsvdatasource.cpp
+++ b/ogr/ogrsf_frmts/csv/ogrcsvdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrcsvdatasource.cpp 29897 2015-08-29 12:36:40Z rouault $
+ * $Id: ogrcsvdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  CSV Translator
  * Purpose:  Implements OGRCSVDataSource class
@@ -28,31 +28,302 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_csv.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
 #include "cpl_csv.h"
 #include "cpl_vsi_virtual.h"
 
-CPL_CVSID("$Id: ogrcsvdatasource.cpp 29897 2015-08-29 12:36:40Z rouault $");
+#include "ogr_csv.h"
+
+#include "ogreditablelayer.h"
+
+CPL_CVSID("$Id: ogrcsvdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
-/*                          OGRCSVDataSource()                          */
+/*                     OGRCSVEditableLayerSynchronizer                  */
+/************************************************************************/
+
+class OGRCSVEditableLayerSynchronizer: public IOGREditableLayerSynchronizer
+{
+            OGRCSVLayer *m_poCSVLayer;
+            char        **m_papszOpenOptions;
+
+    public:
+                            OGRCSVEditableLayerSynchronizer(OGRCSVLayer* poCSVLayer,
+                                                            char** papszOpenOptions) :
+                                                m_poCSVLayer(poCSVLayer),
+                                                m_papszOpenOptions(CSLDuplicate(papszOpenOptions)) {}
+                           ~OGRCSVEditableLayerSynchronizer();
+
+            virtual OGRErr EditableSyncToDisk(OGRLayer* poEditableLayer,
+                                              OGRLayer** ppoDecoratedLayer);
+};
+
+/************************************************************************/
+/*                     ~OGRCSVEditableLayerSynchronizer()               */
 /************************************************************************/
 
-OGRCSVDataSource::OGRCSVDataSource()
+OGRCSVEditableLayerSynchronizer::~OGRCSVEditableLayerSynchronizer()
+{
+    CSLDestroy(m_papszOpenOptions);
+}
 
+/************************************************************************/
+/*                       EditableSyncToDisk()                           */
+/************************************************************************/
+
+OGRErr OGRCSVEditableLayerSynchronizer::EditableSyncToDisk(OGRLayer* poEditableLayer,
+                                                           OGRLayer** ppoDecoratedLayer)
 {
-    papoLayers = NULL;
-    nLayers = 0;
+    CPLAssert( m_poCSVLayer == *ppoDecoratedLayer );
+
+    CPLString osLayerName(m_poCSVLayer->GetName());
+    CPLString osFilename(m_poCSVLayer->GetFilename());
+    const bool bCreateCSVT = m_poCSVLayer->GetCreateCSVT() != FALSE;
+    CPLString osCSVTFilename(CPLResetExtension(osFilename, "csvt"));
+    VSIStatBufL sStatBuf;
+    const bool bHasCSVT = VSIStatL(osCSVTFilename, &sStatBuf) == 0;
+    CPLString osTmpFilename(osFilename);
+    CPLString osTmpCSVTFilename(osFilename);
+    if( VSIStatL(osFilename, &sStatBuf) == 0 )
+    {
+        osTmpFilename += "_ogr_tmp.csv";
+        osTmpCSVTFilename += "_ogr_tmp.csvt";
+    }
+    const char chDelimiter = m_poCSVLayer->GetDelimiter();
+    OGRCSVLayer* poCSVTmpLayer = new OGRCSVLayer( osLayerName, NULL,
+                                                  osTmpFilename,
+                                                  TRUE, TRUE, chDelimiter );
+    poCSVTmpLayer->BuildFeatureDefn(NULL, NULL, m_papszOpenOptions);
+    poCSVTmpLayer->SetCRLF( m_poCSVLayer->GetCRLF() );
+    poCSVTmpLayer->SetCreateCSVT( bCreateCSVT || bHasCSVT );
+    poCSVTmpLayer->SetWriteBOM( m_poCSVLayer->GetWriteBOM() );
+
+    if( m_poCSVLayer->GetGeometryFormat() == OGR_CSV_GEOM_AS_WKT )
+        poCSVTmpLayer->SetWriteGeometry( wkbNone, OGR_CSV_GEOM_AS_WKT, NULL );
+
+    OGRErr eErr = OGRERR_NONE;
+    OGRFeatureDefn* poEditableFDefn =  poEditableLayer->GetLayerDefn();
+    for( int i=0; eErr == OGRERR_NONE &&
+                  i < poEditableFDefn->GetFieldCount(); i++ )
+    {
+        OGRFieldDefn oFieldDefn(poEditableFDefn->GetFieldDefn(i));
+        int iGeomFieldIdx;
+        if( (EQUAL(oFieldDefn.GetNameRef(), "WKT") &&
+             (iGeomFieldIdx = poEditableFDefn->GetGeomFieldIndex("")) >= 0) ||
+            (iGeomFieldIdx = poEditableFDefn->GetGeomFieldIndex(oFieldDefn.GetNameRef())) >= 0 )
+        {
+            OGRGeomFieldDefn oGeomFieldDefn(
+                poEditableFDefn->GetGeomFieldDefn(iGeomFieldIdx) );
+            eErr = poCSVTmpLayer->CreateGeomField( &oGeomFieldDefn );
+        }
+        else
+        {
+            eErr = poCSVTmpLayer->CreateField( &oFieldDefn );
+        }
+    }
+
+    const bool bHasXY = ( m_poCSVLayer->GetXField().size() != 0 &&
+                          m_poCSVLayer->GetYField().size() != 0 );
+    const bool bHasZ = ( m_poCSVLayer->GetZField().size() != 0 );
+    if( bHasXY && !CSLFetchBoolean(m_papszOpenOptions, "KEEP_GEOM_COLUMNS", TRUE) )
+    {
+        if( poCSVTmpLayer->GetLayerDefn()->GetFieldIndex(m_poCSVLayer->GetXField()) < 0 )
+        {
+            OGRFieldDefn oFieldDefn(m_poCSVLayer->GetXField(), OFTReal);
+            if( eErr == OGRERR_NONE )
+                eErr = poCSVTmpLayer->CreateField( &oFieldDefn );
+        }
+        if( poCSVTmpLayer->GetLayerDefn()->GetFieldIndex(m_poCSVLayer->GetYField()) < 0 )
+        {
+            OGRFieldDefn oFieldDefn(m_poCSVLayer->GetYField(), OFTReal);
+            if( eErr == OGRERR_NONE )
+                eErr = poCSVTmpLayer->CreateField( &oFieldDefn );
+        }
+        if( bHasZ && poCSVTmpLayer->GetLayerDefn()->GetFieldIndex(m_poCSVLayer->GetZField()) < 0 )
+        {
+            OGRFieldDefn oFieldDefn(m_poCSVLayer->GetZField(), OFTReal);
+            if( eErr == OGRERR_NONE )
+                eErr = poCSVTmpLayer->CreateField( &oFieldDefn );
+        }
+    }
+
+    int nFirstGeomColIdx = 0;
+    if( m_poCSVLayer->HasHiddenWKTColumn() )
+    {
+        poCSVTmpLayer->SetWriteGeometry(
+            poEditableFDefn->GetGeomFieldDefn(0)->GetType(),
+            OGR_CSV_GEOM_AS_WKT,
+            poEditableFDefn->GetGeomFieldDefn(0)->GetNameRef());
+        nFirstGeomColIdx = 1;
+    }
 
-    pszName = NULL;
+    if( !(poEditableFDefn->GetGeomFieldCount() == 1 && bHasXY) )
+    {
+        for( int i=nFirstGeomColIdx; eErr == OGRERR_NONE &&
+                i < poEditableFDefn->GetGeomFieldCount(); i++ )
+        {
+            OGRGeomFieldDefn oGeomFieldDefn( poEditableFDefn->GetGeomFieldDefn(i) );
+            if( poCSVTmpLayer->GetLayerDefn()->GetGeomFieldIndex(oGeomFieldDefn.GetNameRef()) >= 0 )
+                continue;
+            eErr = poCSVTmpLayer->CreateGeomField( &oGeomFieldDefn );
+        }
+    }
 
-    bUpdate = FALSE;
-    bEnableGeometryFields = FALSE;
+    OGRFeature* poFeature;
+    poEditableLayer->ResetReading();
+    while( eErr == OGRERR_NONE &&
+           (poFeature = poEditableLayer->GetNextFeature()) != NULL )
+    {
+        OGRFeature* poNewFeature = new OGRFeature( poCSVTmpLayer->GetLayerDefn() );
+        poNewFeature->SetFrom(poFeature);
+        if( bHasXY )
+        {
+            OGRGeometry* poGeom = poFeature->GetGeometryRef();
+            if( poGeom != NULL && wkbFlatten(poGeom->getGeometryType()) == wkbPoint )
+            {
+                poNewFeature->SetField( m_poCSVLayer->GetXField(),
+                                        static_cast<OGRPoint*>(poGeom)->getX());
+                poNewFeature->SetField( m_poCSVLayer->GetYField(),
+                                        static_cast<OGRPoint*>(poGeom)->getY());
+                if( bHasZ )
+                {
+                    poNewFeature->SetField( m_poCSVLayer->GetZField(),
+                                        static_cast<OGRPoint*>(poGeom)->getZ());
+                }
+            }
+        }
+        eErr = poCSVTmpLayer->CreateFeature(poNewFeature);
+        delete poFeature;
+        delete poNewFeature;
+    }
+    delete poCSVTmpLayer;
+
+    if( eErr != OGRERR_NONE )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Error while creating %s",
+                 osTmpFilename.c_str());
+        VSIUnlink( osTmpFilename );
+        VSIUnlink( CPLResetExtension(osTmpFilename, "csvt") );
+        return eErr;
+    }
+
+    delete m_poCSVLayer;
+
+    if( osFilename != osTmpFilename )
+    {
+        CPLString osTmpOriFilename(osFilename + ".ogr_bak");
+        CPLString osTmpOriCSVTFilename(osCSVTFilename + ".ogr_bak");
+        if( VSIRename( osFilename, osTmpOriFilename ) != 0 ||
+            (bHasCSVT && VSIRename( osCSVTFilename, osTmpOriCSVTFilename ) != 0 ) ||
+            VSIRename( osTmpFilename, osFilename) != 0 ||
+            (bHasCSVT && VSIRename( osTmpCSVTFilename, osCSVTFilename ) != 0) )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Cannot rename files");
+            *ppoDecoratedLayer = m_poCSVLayer = NULL;
+            return OGRERR_FAILURE;
+        }
+        VSIUnlink( osTmpOriFilename );
+        if( bHasCSVT )
+            VSIUnlink( osTmpOriCSVTFilename );
+    }
+
+    VSILFILE* fp = VSIFOpenL( osFilename, "rb+" );
+    if( fp == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot reopen updated %s",
+                 osFilename.c_str());
+        *ppoDecoratedLayer = m_poCSVLayer = NULL;
+        return OGRERR_FAILURE;
+    }
+
+    m_poCSVLayer = new OGRCSVLayer( osLayerName, fp,
+                                    osFilename,
+                                    FALSE, /* new */
+                                    TRUE, /* update */
+                                    chDelimiter );
+    m_poCSVLayer->BuildFeatureDefn(NULL, NULL, m_papszOpenOptions);
+    *ppoDecoratedLayer = m_poCSVLayer;
+
+    return OGRERR_NONE;
 }
 
 /************************************************************************/
+/*                        OGRCSVEditableLayer                           */
+/************************************************************************/
+
+class OGRCSVEditableLayer: public OGREditableLayer
+{
+    public:
+        OGRCSVEditableLayer(OGRCSVLayer* poCSVLayer,
+                            char** papszOpenOptions);
+
+    virtual OGRErr      CreateField( OGRFieldDefn *poField,
+                                     int bApproxOK = TRUE );
+    virtual GIntBig     GetFeatureCount( int bForce = TRUE );
+};
+
+/************************************************************************/
+/*                       GRCSVEditableLayer()                           */
+/************************************************************************/
+
+OGRCSVEditableLayer::OGRCSVEditableLayer(OGRCSVLayer* poCSVLayer,
+                                         char** papszOpenOptions) :
+        OGREditableLayer(poCSVLayer, true,
+                         new OGRCSVEditableLayerSynchronizer(
+                                         poCSVLayer, papszOpenOptions),
+                         true)
+{
+    SetSupportsCreateGeomField(true);
+    SetSupportsCurveGeometries(true);
+}
+
+/************************************************************************/
+/*                            CreateField()                             */
+/************************************************************************/
+
+OGRErr OGRCSVEditableLayer::CreateField( OGRFieldDefn *poNewField, int bApproxOK )
+
+{
+    OGRCSVCreateFieldAction eAction = OGRCSVLayer::PreCreateField(
+                            m_poEditableFeatureDefn, poNewField, bApproxOK );
+    if( eAction == CREATE_FIELD_DO_NOTHING )
+        return OGRERR_NONE;
+    if( eAction == CREATE_FIELD_ERROR )
+        return OGRERR_FAILURE;
+    return OGREditableLayer::CreateField(poNewField, bApproxOK);
+}
+
+/************************************************************************/
+/*                        GetFeatureCount()                             */
+/************************************************************************/
+
+GIntBig OGRCSVEditableLayer::GetFeatureCount( int bForce )
+{
+    GIntBig nRet = OGREditableLayer::GetFeatureCount(bForce);
+    if( m_poDecoratedLayer != NULL && m_nNextFID <= 0 )
+    {
+        GIntBig nTotalFeatureCount =
+            static_cast<OGRCSVLayer*>(m_poDecoratedLayer)->GetTotalFeatureCount();
+        if( nTotalFeatureCount >= 0 )
+            SetNextFID(nTotalFeatureCount+1);
+    }
+    return nRet;
+}
+
+/************************************************************************/
+/*                          OGRCSVDataSource()                          */
+/************************************************************************/
+
+OGRCSVDataSource::OGRCSVDataSource() :
+    pszName(NULL),
+    papoLayers(NULL),
+    nLayers(0),
+    bUpdate(FALSE),
+    bEnableGeometryFields(FALSE)
+{}
+
+/************************************************************************/
 /*                         ~OGRCSVDataSource()                          */
 /************************************************************************/
 
@@ -63,6 +334,9 @@ OGRCSVDataSource::~OGRCSVDataSource()
         delete papoLayers[i];
     CPLFree( papoLayers );
 
+    if( bUpdate )
+        OGRCSVDriverRemoveFromMap(pszName, this);
+
     CPLFree( pszName );
 }
 
@@ -81,6 +355,8 @@ int OGRCSVDataSource::TestCapability( const char * pszCap )
         return bUpdate && bEnableGeometryFields;
     else if( EQUAL(pszCap,ODsCCurveGeometries) )
         return TRUE;
+    else if( EQUAL(pszCap,ODsCMeasuredGeometries) )
+        return TRUE;
     else
         return FALSE;
 }
@@ -94,8 +370,8 @@ OGRLayer *OGRCSVDataSource::GetLayer( int iLayer )
 {
     if( iLayer < 0 || iLayer >= nLayers )
         return NULL;
-    else
-        return papoLayers[iLayer];
+
+    return papoLayers[iLayer];
 }
 
 /************************************************************************/
@@ -105,11 +381,13 @@ OGRLayer *OGRCSVDataSource::GetLayer( int iLayer )
 CPLString OGRCSVDataSource::GetRealExtension(CPLString osFilename)
 {
     CPLString osExt = CPLGetExtension(osFilename);
-    if( strncmp(osFilename, "/vsigzip/", 9) == 0 && EQUAL(osExt, "gz") )
+    if( STARTS_WITH(osFilename, "/vsigzip/") && EQUAL(osExt, "gz") )
     {
-        if( strlen(osFilename) > 7 && EQUAL(osFilename + strlen(osFilename) - 7, ".csv.gz") )
+        if( strlen(osFilename) > 7
+            && EQUAL(osFilename + strlen(osFilename) - 7, ".csv.gz") )
             osExt = "csv";
-        else if( strlen(osFilename) > 7 && EQUAL(osFilename + strlen(osFilename) - 7, ".tsv.gz") )
+        else if( strlen(osFilename) > 7
+                 && EQUAL(osFilename + strlen(osFilename) - 7, ".tsv.gz") )
             osExt = "tsv";
     }
     return osExt;
@@ -120,7 +398,7 @@ CPLString OGRCSVDataSource::GetRealExtension(CPLString osFilename)
 /************************************************************************/
 
 int OGRCSVDataSource::Open( const char * pszFilename, int bUpdateIn,
-                            int bForceOpen, char** papszOpenOptions )
+                            int bForceOpen, char** papszOpenOptionsIn )
 
 {
     pszName = CPLStrdup( pszFilename );
@@ -130,23 +408,24 @@ int OGRCSVDataSource::Open( const char * pszFilename, int bUpdateIn,
         return TRUE;
 
     /* For writable /vsizip/, do nothing more */
-    if (bUpdateIn && bForceOpen && strncmp(pszFilename, "/vsizip/", 8) == 0)
+    if (bUpdateIn && bForceOpen && STARTS_WITH(pszFilename, "/vsizip/"))
         return TRUE;
 
     CPLString osFilename(pszFilename);
     CPLString osBaseFilename = CPLGetFilename(pszFilename);
     CPLString osExt = GetRealExtension(osFilename);
-    pszFilename = NULL;
+    // pszFilename = NULL;
 
-    int bIgnoreExtension = EQUALN(osFilename, "CSV:", 4);
-    int bUSGeonamesFile = FALSE;
-    /* int bGeonamesOrgFile = FALSE; */
+    bool bIgnoreExtension = STARTS_WITH_CI(osFilename, "CSV:");
+    bool bUSGeonamesFile = false;
+    /* bool bGeonamesOrgFile = false; */
     if (bIgnoreExtension)
     {
         osFilename = osFilename + 4;
     }
 
-    /* Those are *not* real .XLS files, but text file with tab as column separator */
+    // Those are *not* real .XLS files, but text file with tab as column
+    // separator.
     if (EQUAL(osBaseFilename, "NfdcFacilities.xls") ||
         EQUAL(osBaseFilename, "NfdcRunways.xls") ||
         EQUAL(osBaseFilename, "NfdcRemarks.xls") ||
@@ -154,27 +433,29 @@ int OGRCSVDataSource::Open( const char * pszFilename, int bUpdateIn,
     {
         if (bUpdateIn)
             return FALSE;
-        bIgnoreExtension = TRUE;
-    }
-    else if ((EQUALN(osBaseFilename, "NationalFile_", 13) ||
-              EQUALN(osBaseFilename, "POP_PLACES_", 11) ||
-              EQUALN(osBaseFilename, "HIST_FEATURES_", 14) ||
-              EQUALN(osBaseFilename, "US_CONCISE_", 11) ||
-              EQUALN(osBaseFilename, "AllNames_", 9) ||
-              EQUALN(osBaseFilename, "Feature_Description_History_", 28) ||
-              EQUALN(osBaseFilename, "ANTARCTICA_", 11) ||
-              EQUALN(osBaseFilename, "GOVT_UNITS_", 11) ||
-              EQUALN(osBaseFilename, "NationalFedCodes_", 17) ||
-              EQUALN(osBaseFilename, "AllStates_", 10) ||
-              EQUALN(osBaseFilename, "AllStatesFedCodes_", 18) ||
-              (strlen(osBaseFilename) > 2 && EQUALN(osBaseFilename+2, "_Features_", 10)) ||
-              (strlen(osBaseFilename) > 2 && EQUALN(osBaseFilename+2, "_FedCodes_", 10))) &&
+        bIgnoreExtension = true;
+    }
+    else if ((STARTS_WITH_CI(osBaseFilename, "NationalFile_") ||
+              STARTS_WITH_CI(osBaseFilename, "POP_PLACES_") ||
+              STARTS_WITH_CI(osBaseFilename, "HIST_FEATURES_") ||
+              STARTS_WITH_CI(osBaseFilename, "US_CONCISE_") ||
+              STARTS_WITH_CI(osBaseFilename, "AllNames_") ||
+              STARTS_WITH_CI(osBaseFilename, "Feature_Description_History_") ||
+              STARTS_WITH_CI(osBaseFilename, "ANTARCTICA_") ||
+              STARTS_WITH_CI(osBaseFilename, "GOVT_UNITS_") ||
+              STARTS_WITH_CI(osBaseFilename, "NationalFedCodes_") ||
+              STARTS_WITH_CI(osBaseFilename, "AllStates_") ||
+              STARTS_WITH_CI(osBaseFilename, "AllStatesFedCodes_") ||
+              ( strlen(osBaseFilename) > 2 &&
+                STARTS_WITH_CI(osBaseFilename+2, "_Features_")) ||
+              ( strlen(osBaseFilename) > 2 &&
+                STARTS_WITH_CI(osBaseFilename+2, "_FedCodes_"))) &&
              (EQUAL(osExt, "txt") || EQUAL(osExt, "zip")) )
     {
         if (bUpdateIn)
             return FALSE;
-        bIgnoreExtension = TRUE;
-        bUSGeonamesFile = TRUE;
+        bIgnoreExtension = true;
+        bUSGeonamesFile = true;
 
         if (EQUAL(osExt, "zip") &&
             strstr(osFilename, "/vsizip/") == NULL )
@@ -187,8 +468,8 @@ int OGRCSVDataSource::Open( const char * pszFilename, int bUpdateIn,
     {
         if (bUpdateIn)
             return FALSE;
-        bIgnoreExtension = TRUE;
-        /* bGeonamesOrgFile = TRUE; */
+        bIgnoreExtension = true;
+        /* bGeonamesOrgFile = true; */
 
         if (EQUAL(osExt, "zip") &&
             strstr(osFilename, "/vsizip/") == NULL )
@@ -213,46 +494,49 @@ int OGRCSVDataSource::Open( const char * pszFilename, int bUpdateIn,
     {
         if (EQUAL(CPLGetFilename(osFilename), "NfdcFacilities.xls"))
         {
-            return OpenTable( osFilename, papszOpenOptions, "ARP");
+            return OpenTable( osFilename, papszOpenOptionsIn, "ARP");
         }
         else if (EQUAL(CPLGetFilename(osFilename), "NfdcRunways.xls"))
         {
-            OpenTable( osFilename, papszOpenOptions, "BaseEndPhysical");
-            OpenTable( osFilename, papszOpenOptions, "BaseEndDisplaced");
-            OpenTable( osFilename, papszOpenOptions, "ReciprocalEndPhysical");
-            OpenTable( osFilename, papszOpenOptions, "ReciprocalEndDisplaced");
+            OpenTable( osFilename, papszOpenOptionsIn, "BaseEndPhysical");
+            OpenTable( osFilename, papszOpenOptionsIn, "BaseEndDisplaced");
+            OpenTable( osFilename, papszOpenOptionsIn, "ReciprocalEndPhysical");
+            OpenTable( osFilename, papszOpenOptionsIn,
+                       "ReciprocalEndDisplaced");
             return nLayers != 0;
         }
         else if (bUSGeonamesFile)
         {
             /* GNIS specific */
-            if (EQUALN(osBaseFilename, "NationalFedCodes_", 17) ||
-                EQUALN(osBaseFilename, "AllStatesFedCodes_", 18) ||
-                EQUALN(osBaseFilename, "ANTARCTICA_", 11) ||
-                (strlen(osBaseFilename) > 2 && EQUALN(osBaseFilename+2, "_FedCodes_", 10)))
+            if (STARTS_WITH_CI(osBaseFilename, "NationalFedCodes_") ||
+                STARTS_WITH_CI(osBaseFilename, "AllStatesFedCodes_") ||
+                STARTS_WITH_CI(osBaseFilename, "ANTARCTICA_") ||
+                ( strlen(osBaseFilename) > 2 &&
+                  STARTS_WITH_CI(osBaseFilename+2, "_FedCodes_")))
             {
-                OpenTable( osFilename, papszOpenOptions, NULL, "PRIMARY");
+                OpenTable( osFilename, papszOpenOptionsIn, NULL, "PRIMARY");
             }
-            else if (EQUALN(osBaseFilename, "GOVT_UNITS_", 11) ||
-                     EQUALN(osBaseFilename, "Feature_Description_History_", 28))
+            else if (STARTS_WITH_CI(osBaseFilename, "GOVT_UNITS_") ||
+                     STARTS_WITH_CI(osBaseFilename,
+                                    "Feature_Description_History_"))
             {
-                OpenTable( osFilename, papszOpenOptions, NULL, "");
+                OpenTable( osFilename, papszOpenOptionsIn, NULL, "");
             }
             else
             {
-                OpenTable( osFilename, papszOpenOptions, NULL, "PRIM");
-                OpenTable( osFilename, papszOpenOptions, NULL, "SOURCE");
+                OpenTable( osFilename, papszOpenOptionsIn, NULL, "PRIM");
+                OpenTable( osFilename, papszOpenOptionsIn, NULL, "SOURCE");
             }
             return nLayers != 0;
         }
 
-        return OpenTable( osFilename, papszOpenOptions );
+        return OpenTable( osFilename, papszOpenOptionsIn );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Is this a single a ZIP file with only a CSV file inside ?       */
 /* -------------------------------------------------------------------- */
-    if( strncmp(osFilename, "/vsizip/", 8) == 0 &&
+    if( STARTS_WITH(osFilename, "/vsizip/") &&
         EQUAL(osExt, "zip") &&
         VSI_ISREG(sStatBuf.st_mode) )
     {
@@ -265,7 +549,7 @@ int OGRCSVDataSource::Open( const char * pszFilename, int bUpdateIn,
         }
         osFilename = CPLFormFilename(osFilename, papszFiles[0], NULL);
         CSLDestroy(papszFiles);
-        return OpenTable( osFilename, papszOpenOptions );
+        return OpenTable( osFilename, papszOpenOptionsIn );
     }
 
 /* -------------------------------------------------------------------- */
@@ -277,12 +561,12 @@ int OGRCSVDataSource::Open( const char * pszFilename, int bUpdateIn,
 /* -------------------------------------------------------------------- */
 /*      Scan through for entries ending in .csv.                        */
 /* -------------------------------------------------------------------- */
-    int nNotCSVCount = 0, i;
-    char **papszNames = CPLReadDir( osFilename );
+    int nNotCSVCount = 0;
+    char **papszNames = VSIReadDir( osFilename );
 
-    for( i = 0; papszNames != NULL && papszNames[i] != NULL; i++ )
+    for( int i = 0; papszNames != NULL && papszNames[i] != NULL; i++ )
     {
-        CPLString oSubFilename = 
+        CPLString oSubFilename =
             CPLFormFilename( osFilename, papszNames[i], NULL );
 
         if( EQUAL(papszNames[i],".") || EQUAL(papszNames[i],"..") )
@@ -291,7 +575,7 @@ int OGRCSVDataSource::Open( const char * pszFilename, int bUpdateIn,
         if (EQUAL(CPLGetExtension(oSubFilename),"csvt"))
             continue;
 
-        if( VSIStatL( oSubFilename, &sStatBuf ) != 0 
+        if( VSIStatL( oSubFilename, &sStatBuf ) != 0
             || !VSI_ISREG(sStatBuf.st_mode) )
         {
             nNotCSVCount++;
@@ -300,7 +584,7 @@ int OGRCSVDataSource::Open( const char * pszFilename, int bUpdateIn,
 
         if (EQUAL(CPLGetExtension(oSubFilename),"csv"))
         {
-            if( !OpenTable( oSubFilename, papszOpenOptions ) )
+            if( !OpenTable( oSubFilename, papszOpenOptionsIn ) )
             {
                 CPLDebug("CSV", "Cannot open %s", oSubFilename.c_str());
                 nNotCSVCount++;
@@ -310,11 +594,13 @@ int OGRCSVDataSource::Open( const char * pszFilename, int bUpdateIn,
 
         /* GNIS specific */
         else if ( strlen(papszNames[i]) > 2 &&
-                  EQUALN(papszNames[i]+2, "_Features_", 10) &&
+                  STARTS_WITH_CI(papszNames[i]+2, "_Features_") &&
                   EQUAL(CPLGetExtension(papszNames[i]), "txt") )
         {
-            int bRet = OpenTable( oSubFilename, papszOpenOptions, NULL, "PRIM");
-            bRet |= OpenTable( oSubFilename, papszOpenOptions, NULL, "SOURCE");
+            int bRet
+                = OpenTable( oSubFilename, papszOpenOptionsIn, NULL, "PRIM");
+            bRet |=
+                OpenTable( oSubFilename, papszOpenOptionsIn, NULL, "SOURCE");
             if ( !bRet )
             {
                 CPLDebug("CSV", "Cannot open %s", oSubFilename.c_str());
@@ -324,10 +610,11 @@ int OGRCSVDataSource::Open( const char * pszFilename, int bUpdateIn,
         }
         /* GNIS specific */
         else if ( strlen(papszNames[i]) > 2 &&
-                  EQUALN(papszNames[i]+2, "_FedCodes_", 10) &&
+                  STARTS_WITH_CI(papszNames[i]+2, "_FedCodes_") &&
                   EQUAL(CPLGetExtension(papszNames[i]), "txt") )
         {
-            if ( !OpenTable( oSubFilename, papszOpenOptions, NULL, "PRIMARY") )
+            if ( !OpenTable( oSubFilename, papszOpenOptionsIn,
+                             NULL, "PRIMARY") )
             {
                 CPLDebug("CSV", "Cannot open %s", oSubFilename.c_str());
                 nNotCSVCount++;
@@ -355,7 +642,7 @@ int OGRCSVDataSource::Open( const char * pszFilename, int bUpdateIn,
 /************************************************************************/
 
 int OGRCSVDataSource::OpenTable( const char * pszFilename,
-                                 char** papszOpenOptions,
+                                 char** papszOpenOptionsIn,
                                  const char* pszNfdcRunwaysGeomField,
                                  const char* pszGeonamesGeomFieldPrefix)
 
@@ -363,7 +650,7 @@ int OGRCSVDataSource::OpenTable( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Open the file.                                                  */
 /* -------------------------------------------------------------------- */
-    VSILFILE       * fp;
+    VSILFILE *fp = NULL;
 
     if( bUpdate )
         fp = VSIFOpenL( pszFilename, "rb+" );
@@ -371,26 +658,30 @@ int OGRCSVDataSource::OpenTable( const char * pszFilename,
         fp = VSIFOpenL( pszFilename, "rb" );
     if( fp == NULL )
     {
-        CPLError( CE_Warning, CPLE_OpenFailed, 
-                  "Failed to open %s, %s.", 
+        CPLError( CE_Warning, CPLE_OpenFailed,
+                  "Failed to open %s, %s.",
                   pszFilename, VSIStrerror( errno ) );
         return FALSE;
     }
 
     if( !bUpdate && strstr(pszFilename, "/vsigzip/") == NULL &&
         strstr(pszFilename, "/vsizip/") == NULL )
-        fp = (VSILFILE*) VSICreateBufferedReaderHandle((VSIVirtualHandle*)fp);
+        fp = reinterpret_cast<VSILFILE *>(
+            VSICreateBufferedReaderHandle(
+                reinterpret_cast<VSIVirtualHandle *>( fp ) ) );
 
     CPLString osLayerName = CPLGetBasename(pszFilename);
     CPLString osExt = CPLGetExtension(pszFilename);
-    if( strncmp(pszFilename, "/vsigzip/", 9) == 0 && EQUAL(osExt, "gz") )
+    if( STARTS_WITH(pszFilename, "/vsigzip/") && EQUAL(osExt, "gz") )
     {
-        if( strlen(pszFilename) > 7 && EQUAL(pszFilename + strlen(pszFilename) - 7, ".csv.gz") )
+        if( strlen(pszFilename) > 7
+            && EQUAL(pszFilename + strlen(pszFilename) - 7, ".csv.gz") )
         {
             osLayerName = osLayerName.substr(0, osLayerName.size() - 4);
             osExt = "csv";
         }
-        else if( strlen(pszFilename) > 7 && EQUAL(pszFilename + strlen(pszFilename) - 7, ".tsv.gz") )
+        else if( strlen(pszFilename) > 7
+                 && EQUAL(pszFilename + strlen(pszFilename) - 7, ".tsv.gz") )
         {
             osLayerName = osLayerName.substr(0, osLayerName.size() - 4);
             osExt = "tsv";
@@ -410,22 +701,27 @@ int OGRCSVDataSource::OpenTable( const char * pszFilename,
     char chDelimiter = CSVDetectSeperator(pszLine);
     if( chDelimiter != '\t' && strchr(pszLine, '\t') != NULL )
     {
-        /* Force the delimiter to be TAB for a .tsv file that has a tabulation */
-        /* in its first line */
+        // Force the delimiter to be TAB for a .tsv file that has a tabulation
+        // in its first line */
         if( EQUAL(osExt, "tsv") )
         {
             chDelimiter = '\t';
         }
         else
         {
-            for(int bDontHonourStrings=0; bDontHonourStrings<=1; bDontHonourStrings++)
+            for( int bDontHonourStrings = 0;
+                 bDontHonourStrings <= 1;
+                 bDontHonourStrings++ )
             {
-                // Read the first 2 lines to see if they have the same number of fields, if using tabulation
+                // Read the first 2 lines to see if they have the same number
+                // of fields, if using tabulation.
                 VSIRewindL( fp );
-                char** papszTokens = OGRCSVReadParseLineL( fp, '\t', bDontHonourStrings );
+                char** papszTokens = OGRCSVReadParseLineL( fp, '\t',
+                                                           bDontHonourStrings );
                 int nTokens1 = CSLCount(papszTokens);
                 CSLDestroy(papszTokens);
-                papszTokens = OGRCSVReadParseLineL( fp, '\t', bDontHonourStrings );
+                papszTokens = OGRCSVReadParseLineL( fp, '\t',
+                                                    bDontHonourStrings );
                 int nTokens2 = CSLCount(papszTokens);
                 CSLDestroy(papszTokens);
                 if( nTokens1 >= 2 && nTokens1 == nTokens2 )
@@ -440,7 +736,8 @@ int OGRCSVDataSource::OpenTable( const char * pszFilename,
     VSIRewindL( fp );
 
 #if 0
-    const char *pszDelimiter = CSLFetchNameValueDef( papszOpenOptions, "SEPARATOR", "AUTO");
+    const char *pszDelimiter = CSLFetchNameValueDef( papszOpenOptionsIn,
+                                                     "SEPARATOR", "AUTO");
     if( !EQUAL(pszDelimiter, "AUTO") )
     {
         if (EQUAL(pszDelimiter, "COMMA"))
@@ -453,9 +750,10 @@ int OGRCSVDataSource::OpenTable( const char * pszFilename,
             chDelimiter = ' ';
         else
         {
-            CPLError( CE_Warning, CPLE_AppDefined, 
-                  "SEPARATOR=%s not understood, use one of COMMA, SEMICOLON, SPACE or TAB.",
-                  pszDelimiter );
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "SEPARATOR=%s not understood, use one of COMMA, "
+                      "SEMICOLON, SPACE or TAB.",
+                      pszDelimiter );
         }
     }
 #endif
@@ -466,7 +764,7 @@ int OGRCSVDataSource::OpenTable( const char * pszFilename,
         chDelimiter = '|';
 
     char **papszFields = OGRCSVReadParseLineL( fp, chDelimiter, FALSE );
-						
+
     if( CSLCount(papszFields) < 2 )
     {
         VSIFCloseL( fp );
@@ -481,8 +779,8 @@ int OGRCSVDataSource::OpenTable( const char * pszFilename,
 /*      Create a layer.                                                 */
 /* -------------------------------------------------------------------- */
     nLayers++;
-    papoLayers = (OGRCSVLayer **) CPLRealloc(papoLayers, 
-                                             sizeof(void*) * nLayers);
+    papoLayers = static_cast<OGRLayer **>(
+        CPLRealloc( papoLayers, sizeof(void*) * nLayers ) );
 
     if (pszNfdcRunwaysGeomField != NULL)
     {
@@ -497,12 +795,19 @@ int OGRCSVDataSource::OpenTable( const char * pszFilename,
     }
     if (EQUAL(pszFilename, "/vsistdin/"))
         osLayerName = "layer";
-    papoLayers[nLayers-1] = 
-        new OGRCSVLayer( osLayerName, fp, pszFilename, FALSE, bUpdate,
-                         chDelimiter  );
-    papoLayers[nLayers-1]->BuildFeatureDefn( pszNfdcRunwaysGeomField,
+
+    OGRCSVLayer* poCSVLayer = new OGRCSVLayer( osLayerName, fp, pszFilename, FALSE, bUpdate,
+                                            chDelimiter  );
+    poCSVLayer->BuildFeatureDefn( pszNfdcRunwaysGeomField,
                                              pszGeonamesGeomFieldPrefix,
-                                             papszOpenOptions );
+                                             papszOpenOptionsIn );
+    OGRLayer* poLayer = poCSVLayer;
+    if( bUpdate )
+    {
+        poLayer = new OGRCSVEditableLayer(poCSVLayer, papszOpenOptionsIn);
+    }
+    papoLayers[nLayers-1] = poLayer;
+
     return TRUE;
 }
 
@@ -512,7 +817,7 @@ int OGRCSVDataSource::OpenTable( const char * pszFilename,
 
 OGRLayer *
 OGRCSVDataSource::ICreateLayer( const char *pszLayerName,
-                                CPL_UNUSED OGRSpatialReference *poSpatialRef,
+                                OGRSpatialReference *poSpatialRef,
                                 OGRwkbGeometryType eGType,
                                 char ** papszOptions  )
 {
@@ -523,7 +828,7 @@ OGRCSVDataSource::ICreateLayer( const char *pszLayerName,
     {
         CPLError( CE_Failure, CPLE_NoWriteAccess,
                   "Data source %s opened read-only.\n"
-                  "New layer %s cannot be created.\n",
+                  "New layer %s cannot be created.",
                   pszName, pszLayerName );
 
         return NULL;
@@ -534,7 +839,7 @@ OGRCSVDataSource::ICreateLayer( const char *pszLayerName,
 /* -------------------------------------------------------------------- */
     VSIStatBufL sStatBuf;
 
-    if( strncmp(pszName, "/vsizip/", 8) == 0)
+    if( STARTS_WITH(pszName, "/vsizip/"))
     {
         /* Do nothing */
     }
@@ -542,8 +847,9 @@ OGRCSVDataSource::ICreateLayer( const char *pszLayerName,
         (VSIStatL( pszName, &sStatBuf ) != 0
         || !VSI_ISDIR( sStatBuf.st_mode )) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Attempt to create csv layer (file) against a non-directory datasource." );
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Attempt to create csv layer (file) against a "
+                  "non-directory datasource." );
         return NULL;
     }
 
@@ -567,7 +873,7 @@ OGRCSVDataSource::ICreateLayer( const char *pszLayerName,
 /* -------------------------------------------------------------------- */
     if( VSIStatL( osFilename, &sStatBuf ) == 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Attempt to create layer %s, but %s already exists.",
                   pszLayerName, osFilename.c_str() );
         return NULL;
@@ -591,25 +897,24 @@ OGRCSVDataSource::ICreateLayer( const char *pszLayerName,
             chDelimiter = ' ';
         else
         {
-            CPLError( CE_Warning, CPLE_AppDefined, 
-                  "SEPARATOR=%s not understood, use one of COMMA, SEMICOLON, SPACE or TAB.",
-                  pszDelimiter );
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "SEPARATOR=%s not understood, use one of "
+                      "COMMA, SEMICOLON, SPACE or TAB.",
+                      pszDelimiter );
         }
     }
 
 /* -------------------------------------------------------------------- */
 /*      Create a layer.                                                 */
 /* -------------------------------------------------------------------- */
-    nLayers++;
-    papoLayers = (OGRCSVLayer **) CPLRealloc(papoLayers, 
-                                             sizeof(void*) * nLayers);
-    
-    papoLayers[nLayers-1] = new OGRCSVLayer( pszLayerName, NULL, osFilename,
+
+    OGRCSVLayer* poCSVLayer = new OGRCSVLayer( pszLayerName, NULL, osFilename,
                                              TRUE, TRUE, chDelimiter );
-    papoLayers[nLayers-1]->BuildFeatureDefn();
+
+    poCSVLayer->BuildFeatureDefn();
 
 /* -------------------------------------------------------------------- */
-/*      Was a partiuclar CRLF order requested?                          */
+/*      Was a particular CRLF order requested?                          */
 /* -------------------------------------------------------------------- */
     const char *pszCRLFFormat = CSLFetchNameValue( papszOptions, "LINEFORMAT");
     int bUseCRLF;
@@ -628,7 +933,7 @@ OGRCSVDataSource::ICreateLayer( const char *pszLayerName,
         bUseCRLF = FALSE;
     else
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "LINEFORMAT=%s not understood, use one of CRLF or LF.",
                   pszCRLFFormat );
 #ifdef WIN32
@@ -637,8 +942,8 @@ OGRCSVDataSource::ICreateLayer( const char *pszLayerName,
         bUseCRLF = FALSE;
 #endif
     }
-    
-    papoLayers[nLayers-1]->SetCRLF( bUseCRLF );
+
+    poCSVLayer->SetCRLF( bUseCRLF );
 
 /* -------------------------------------------------------------------- */
 /*      Should we write the geometry ?                                  */
@@ -646,13 +951,15 @@ OGRCSVDataSource::ICreateLayer( const char *pszLayerName,
     const char *pszGeometry = CSLFetchNameValue( papszOptions, "GEOMETRY");
     if( bEnableGeometryFields )
     {
-        papoLayers[nLayers-1]->SetWriteGeometry(eGType, OGR_CSV_GEOM_AS_WKT);
+        poCSVLayer->SetWriteGeometry(eGType, OGR_CSV_GEOM_AS_WKT,
+            CSLFetchNameValueDef(papszOptions, "GEOMETRY_NAME", "WKT"));
     }
     else if (pszGeometry != NULL)
     {
         if (EQUAL(pszGeometry, "AS_WKT"))
         {
-            papoLayers[nLayers-1]->SetWriteGeometry(eGType, OGR_CSV_GEOM_AS_WKT);
+            poCSVLayer->SetWriteGeometry(eGType, OGR_CSV_GEOM_AS_WKT,
+                CSLFetchNameValueDef(papszOptions, "GEOMETRY_NAME", "WKT"));
         }
         else if (EQUAL(pszGeometry, "AS_XYZ") ||
                  EQUAL(pszGeometry, "AS_XY") ||
@@ -660,21 +967,23 @@ OGRCSVDataSource::ICreateLayer( const char *pszLayerName,
         {
             if (eGType == wkbUnknown || wkbFlatten(eGType) == wkbPoint)
             {
-                papoLayers[nLayers-1]->SetWriteGeometry(eGType,
-                                                        EQUAL(pszGeometry, "AS_XYZ") ? OGR_CSV_GEOM_AS_XYZ :
-                                                        EQUAL(pszGeometry, "AS_XY") ?  OGR_CSV_GEOM_AS_XY :
-                                                                                       OGR_CSV_GEOM_AS_YX);
+                poCSVLayer->SetWriteGeometry(
+                    eGType,
+                    EQUAL(pszGeometry, "AS_XYZ") ? OGR_CSV_GEOM_AS_XYZ :
+                    EQUAL(pszGeometry, "AS_XY") ?  OGR_CSV_GEOM_AS_XY :
+                    OGR_CSV_GEOM_AS_YX);
             }
             else
             {
-                CPLError( CE_Warning, CPLE_AppDefined, 
-                          "Geometry type %s is not compatible with GEOMETRY=AS_XYZ.",
+                CPLError( CE_Warning, CPLE_AppDefined,
+                          "Geometry type %s is not compatible with "
+                          "GEOMETRY=AS_XYZ.",
                           OGRGeometryTypeToName(eGType) );
             }
         }
         else
         {
-            CPLError( CE_Warning, CPLE_AppDefined, 
+            CPLError( CE_Warning, CPLE_AppDefined,
                       "Unsupported value %s for creation option GEOMETRY",
                        pszGeometry );
         }
@@ -685,8 +994,31 @@ OGRCSVDataSource::ICreateLayer( const char *pszLayerName,
 /* -------------------------------------------------------------------- */
 
     const char *pszCreateCSVT = CSLFetchNameValue( papszOptions, "CREATE_CSVT");
-    if (pszCreateCSVT)
-        papoLayers[nLayers-1]->SetCreateCSVT(CSLTestBoolean(pszCreateCSVT));
+    if (pszCreateCSVT && CPLTestBool(pszCreateCSVT))
+    {
+        poCSVLayer->SetCreateCSVT(TRUE);
+
+/* -------------------------------------------------------------------- */
+/*      Create .prj file                                                */
+/* -------------------------------------------------------------------- */
+
+        if( poSpatialRef != NULL && osFilename != "/vsistdout/" )
+        {
+            char* pszWKT = NULL;
+            poSpatialRef->exportToWkt(&pszWKT);
+            if( pszWKT )
+            {
+                VSILFILE* fpPRJ
+                    = VSIFOpenL(CPLResetExtension(osFilename, "prj"), "wb");
+                if( fpPRJ )
+                {
+                    CPL_IGNORE_RET_VAL(VSIFPrintfL(fpPRJ, "%s\n", pszWKT));
+                    VSIFCloseL(fpPRJ);
+                }
+                CPLFree(pszWKT);
+            }
+        }
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Should we write a UTF8 BOM ?                                    */
@@ -694,9 +1026,16 @@ OGRCSVDataSource::ICreateLayer( const char *pszLayerName,
 
     const char *pszWriteBOM = CSLFetchNameValue( papszOptions, "WRITE_BOM");
     if (pszWriteBOM)
-        papoLayers[nLayers-1]->SetWriteBOM(CSLTestBoolean(pszWriteBOM));
+        poCSVLayer->SetWriteBOM(CPLTestBool(pszWriteBOM));
 
-    return papoLayers[nLayers-1];
+    nLayers++;
+    papoLayers = static_cast<OGRLayer **>(
+        CPLRealloc( papoLayers, sizeof(void*) * nLayers ) );
+    OGRLayer* poLayer = poCSVLayer;
+    if( osFilename != "/vsistdout/" )
+        poLayer = new OGRCSVEditableLayer(poCSVLayer, NULL);
+    papoLayers[nLayers-1] = poLayer;
+    return poLayer;
 }
 
 /************************************************************************/
@@ -706,9 +1045,6 @@ OGRCSVDataSource::ICreateLayer( const char *pszLayerName,
 OGRErr OGRCSVDataSource::DeleteLayer( int iLayer )
 
 {
-    char *pszFilename;
-    char *pszFilenameCSVT;
-
 /* -------------------------------------------------------------------- */
 /*      Verify we are in update mode.                                   */
 /* -------------------------------------------------------------------- */
@@ -724,16 +1060,22 @@ OGRErr OGRCSVDataSource::DeleteLayer( int iLayer )
 
     if( iLayer < 0 || iLayer >= nLayers )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Layer %d not in legal range of 0 to %d.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Layer %d not in legal range of 0 to %d.",
                   iLayer, nLayers-1 );
         return OGRERR_FAILURE;
     }
 
-    pszFilename = 
-        CPLStrdup(CPLFormFilename(pszName,papoLayers[iLayer]->GetLayerDefn()->GetName(),"csv"));
-    pszFilenameCSVT = 
-        CPLStrdup(CPLFormFilename(pszName,papoLayers[iLayer]->GetLayerDefn()->GetName(),"csvt"));
+    char *pszFilename =
+        CPLStrdup(
+            CPLFormFilename( pszName,
+                             papoLayers[iLayer]->GetLayerDefn()->GetName(),
+                             "csv" ) );
+    char *pszFilenameCSVT =
+        CPLStrdup(
+            CPLFormFilename( pszName,
+                             papoLayers[iLayer]->GetLayerDefn()->GetName(),
+                             "csvt" ) );
 
     delete papoLayers[iLayer];
 
@@ -752,3 +1094,15 @@ OGRErr OGRCSVDataSource::DeleteLayer( int iLayer )
 
     return OGRERR_NONE;
 }
+
+/************************************************************************/
+/*                       CreateForSingleFile()                          */
+/************************************************************************/
+
+void OGRCSVDataSource::CreateForSingleFile( const char* pszDirname,
+                                            const char *pszFilename )
+{
+    pszName = CPLStrdup( pszDirname );
+    bUpdate = TRUE;
+    osDefaultCSVName = CPLGetFilename(pszFilename);
+}
diff --git a/ogr/ogrsf_frmts/csv/ogrcsvdriver.cpp b/ogr/ogrsf_frmts/csv/ogrcsvdriver.cpp
index 9044ee4..84f88de 100644
--- a/ogr/ogrsf_frmts/csv/ogrcsvdriver.cpp
+++ b/ogr/ogrsf_frmts/csv/ogrcsvdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrcsvdriver.cpp 29237 2015-05-24 08:38:20Z rouault $
+ * $Id: ogrcsvdriver.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  CSV Translator
  * Purpose:  Implements OGRCSVDriver.
@@ -30,8 +30,13 @@
 
 #include "ogr_csv.h"
 #include "cpl_conv.h"
+#include "cpl_multiproc.h"
+#include <map>
 
-CPL_CVSID("$Id: ogrcsvdriver.cpp 29237 2015-05-24 08:38:20Z rouault $");
+CPL_CVSID("$Id: ogrcsvdriver.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+
+static CPLMutex* hMutex = NULL;
+static std::map<CPLString, GDALDataset*> *poMap = NULL;
 
 /************************************************************************/
 /*                         OGRCSVDriverIdentify()                       */
@@ -42,8 +47,10 @@ static int OGRCSVDriverIdentify( GDALOpenInfo* poOpenInfo )
 {
     if( poOpenInfo->fpL != NULL )
     {
-        CPLString osBaseFilename = CPLGetFilename(poOpenInfo->pszFilename);
-        CPLString osExt = OGRCSVDataSource::GetRealExtension(poOpenInfo->pszFilename);
+        const CPLString osBaseFilename
+            = CPLGetFilename(poOpenInfo->pszFilename);
+        const CPLString osExt
+            = OGRCSVDataSource::GetRealExtension(poOpenInfo->pszFilename);
 
         if (EQUAL(osBaseFilename, "NfdcFacilities.xls") ||
             EQUAL(osBaseFilename, "NfdcRunways.xls") ||
@@ -52,19 +59,21 @@ static int OGRCSVDriverIdentify( GDALOpenInfo* poOpenInfo )
         {
             return TRUE;
         }
-        else if ((EQUALN(osBaseFilename, "NationalFile_", 13) ||
-              EQUALN(osBaseFilename, "POP_PLACES_", 11) ||
-              EQUALN(osBaseFilename, "HIST_FEATURES_", 14) ||
-              EQUALN(osBaseFilename, "US_CONCISE_", 11) ||
-              EQUALN(osBaseFilename, "AllNames_", 9) ||
-              EQUALN(osBaseFilename, "Feature_Description_History_", 28) ||
-              EQUALN(osBaseFilename, "ANTARCTICA_", 11) ||
-              EQUALN(osBaseFilename, "GOVT_UNITS_", 11) ||
-              EQUALN(osBaseFilename, "NationalFedCodes_", 17) ||
-              EQUALN(osBaseFilename, "AllStates_", 10) ||
-              EQUALN(osBaseFilename, "AllStatesFedCodes_", 18) ||
-              (strlen(osBaseFilename) > 2 && EQUALN(osBaseFilename+2, "_Features_", 10)) ||
-              (strlen(osBaseFilename) > 2 && EQUALN(osBaseFilename+2, "_FedCodes_", 10))) &&
+        else if ((STARTS_WITH_CI(osBaseFilename, "NationalFile_") ||
+              STARTS_WITH_CI(osBaseFilename, "POP_PLACES_") ||
+              STARTS_WITH_CI(osBaseFilename, "HIST_FEATURES_") ||
+              STARTS_WITH_CI(osBaseFilename, "US_CONCISE_") ||
+              STARTS_WITH_CI(osBaseFilename, "AllNames_") ||
+              STARTS_WITH_CI(osBaseFilename, "Feature_Description_History_") ||
+              STARTS_WITH_CI(osBaseFilename, "ANTARCTICA_") ||
+              STARTS_WITH_CI(osBaseFilename, "GOVT_UNITS_") ||
+              STARTS_WITH_CI(osBaseFilename, "NationalFedCodes_") ||
+              STARTS_WITH_CI(osBaseFilename, "AllStates_") ||
+              STARTS_WITH_CI(osBaseFilename, "AllStatesFedCodes_") ||
+              (strlen(osBaseFilename) > 2
+               && STARTS_WITH_CI(osBaseFilename+2, "_Features_")) ||
+              (strlen(osBaseFilename) > 2
+               && STARTS_WITH_CI(osBaseFilename+2, "_FedCodes_"))) &&
              (EQUAL(osExt, "txt") || EQUAL(osExt, "zip")) )
         {
             return TRUE;
@@ -78,7 +87,7 @@ static int OGRCSVDriverIdentify( GDALOpenInfo* poOpenInfo )
         {
             return TRUE;
         }
-        else if (strncmp(poOpenInfo->pszFilename, "/vsizip/", 8) == 0 &&
+        else if (STARTS_WITH(poOpenInfo->pszFilename, "/vsizip/") &&
                  EQUAL(osExt,"zip"))
         {
             return -1; /* unsure */
@@ -88,7 +97,7 @@ static int OGRCSVDriverIdentify( GDALOpenInfo* poOpenInfo )
             return FALSE;
         }
     }
-    else if( EQUALN(poOpenInfo->pszFilename, "CSV:", 4) )
+    else if( STARTS_WITH_CI(poOpenInfo->pszFilename, "CSV:") )
     {
         return TRUE;
     }
@@ -101,6 +110,24 @@ static int OGRCSVDriverIdentify( GDALOpenInfo* poOpenInfo )
 }
 
 /************************************************************************/
+/*                        OGRCSVDriverRemoveFromMap()                   */
+/************************************************************************/
+
+void OGRCSVDriverRemoveFromMap(const char* pszName, GDALDataset* poDS)
+{
+    if( poMap == NULL )
+        return;
+    CPLMutexHolderD(&hMutex);
+    std::map<CPLString, GDALDataset*>::iterator oIter = poMap->find(pszName);
+    if( oIter != poMap->end() )
+    {
+        GDALDataset* poOtherDS = oIter->second;
+        if( poDS == poOtherDS )
+            poMap->erase(oIter);
+    }
+}
+
+/************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
 
@@ -110,7 +137,19 @@ static GDALDataset *OGRCSVDriverOpen( GDALOpenInfo* poOpenInfo )
     if( OGRCSVDriverIdentify(poOpenInfo) == FALSE )
         return NULL;
 
-    OGRCSVDataSource   *poDS = new OGRCSVDataSource();
+    if( poMap != NULL )
+    {
+        CPLMutexHolderD(&hMutex);
+        std::map<CPLString, GDALDataset*>::iterator oIter =
+            poMap->find(poOpenInfo->pszFilename);
+        if( oIter != poMap->end() )
+        {
+            GDALDataset* poOtherDS = oIter->second;
+            poOtherDS->FlushCache();
+        }
+    }
+
+    OGRCSVDataSource *poDS = new OGRCSVDataSource();
 
     if( !poDS->Open( poOpenInfo->pszFilename, poOpenInfo->eAccess == GA_Update, FALSE,
                      poOpenInfo->papszOpenOptions ) )
@@ -119,6 +158,17 @@ static GDALDataset *OGRCSVDriverOpen( GDALOpenInfo* poOpenInfo )
         poDS = NULL;
     }
 
+    if( poOpenInfo->eAccess == GA_Update && poDS != NULL )
+    {
+        CPLMutexHolderD(&hMutex);
+        if( poMap == NULL )
+            poMap = new std::map<CPLString, GDALDataset*>();
+        if( poMap->find(poOpenInfo->pszFilename) == poMap->end() )
+        {
+            (*poMap)[poOpenInfo->pszFilename] = poDS;
+        }
+    }
+
     return poDS;
 }
 
@@ -169,15 +219,15 @@ static GDALDataset *OGRCSVDriverCreate( const char * pszName,
     }
     else
     {
-        if( strncmp(pszName, "/vsizip/", 8) == 0)
+        if( STARTS_WITH(pszName, "/vsizip/"))
         {
             /* do nothing */
         }
         else if( !EQUAL(pszName, "/vsistdout/") &&
             VSIMkdir( pszName, 0755 ) != 0 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Failed to create directory %s:\n%s", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Failed to create directory %s:\n%s",
                       pszName, VSIStrerror( errno ) );
             return NULL;
         }
@@ -189,15 +239,14 @@ static GDALDataset *OGRCSVDriverCreate( const char * pszName,
 /* -------------------------------------------------------------------- */
     OGRCSVDataSource   *poDS = new OGRCSVDataSource();
 
-    if( !poDS->Open( osDirName, TRUE, TRUE ) )
+     if( EQUAL(CPLGetExtension(pszName),"csv") )
+        poDS->CreateForSingleFile( osDirName, pszName );
+    else if( !poDS->Open( osDirName, TRUE, TRUE ) )
     {
         delete poDS;
         return NULL;
     }
 
-    if( osDirName != pszName )
-        poDS->SetDefaultCSVName( CPLGetFilename(pszName) );
-    
     const char *pszGeometry = CSLFetchNameValue( papszOptions, "GEOMETRY");
     if (pszGeometry != NULL && EQUAL(pszGeometry, "AS_WKT"))
         poDS->EnableGeometryFields();
@@ -214,8 +263,22 @@ static CPLErr OGRCSVDriverDelete( const char *pszFilename )
 {
     if( CPLUnlinkTree( pszFilename ) == 0 )
         return CE_None;
-    else
-        return CE_Failure;
+
+    return CE_Failure;
+}
+
+
+/************************************************************************/
+/*                           OGRCSVDriverUnload()                       */
+/************************************************************************/
+
+static void OGRCSVDriverUnload( GDALDriver* )
+{
+    if( hMutex != NULL )
+        CPLDestroyMutex(hMutex);
+    hMutex = NULL;
+    delete poMap;
+    poMap = NULL;
 }
 
 /************************************************************************/
@@ -225,28 +288,26 @@ static CPLErr OGRCSVDriverDelete( const char *pszFilename )
 void RegisterOGRCSV()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "CSV" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "CSV" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver  *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "CSV" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Comma Separated Value (.csv)" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "csv" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_csv.html" );
+    poDriver->SetDescription( "CSV" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Comma Separated Value (.csv)" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "csv" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_csv.html" );
 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "  <Option name='GEOMETRY' type='string-select' description='how to encode geometry fields'>"
 "    <Value>AS_WKT</Value>"
 "  </Option>"
 "</CreationOptionList>");
 
-        poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
 "<LayerCreationOptionList>"
 "  <Option name='SEPARATOR' type='string-select' description='field separator' default='COMMA'>"
 "    <Value>COMMA</Value>"
@@ -270,9 +331,10 @@ void RegisterOGRCSV()
 "  </Option>"
 "  <Option name='CREATE_CSVT' type='boolean' description='whether to create a .csvt file' default='NO'/>"
 "  <Option name='WRITE_BOM' type='boolean' description='whether to write a UTF-8 BOM prefix' default='NO'/>"
+"  <Option name='GEOMETRY_NAME' type='string' description='Name of geometry column. Only used if GEOMETRY=AS_WKT' default='WKT'/>"
 "</LayerCreationOptionList>");
 
-        poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
 "<OpenOptionList>"
 #if 0
 "  <Option name='SEPARATOR' type='string-select' description='field separator' default='AUTO'>"
@@ -293,17 +355,29 @@ void RegisterOGRCSV()
 "  </Option>"
 "  <Option name='AUTODETECT_SIZE_LIMIT' type='int' description='number of bytes to inspect for auto-detection of data type. Only used if AUTODETECT_TYPE=YES' default='1000000'/>"
 "  <Option name='QUOTED_FIELDS_AS_STRING' type='boolean' description='Only used if AUTODETECT_TYPE=YES. Whether to enforce quoted fields as string fields.' default='NO'/>"
+"  <Option name='X_POSSIBLE_NAMES' type='string' description='Comma separated list of possible names for X/longitude coordinate of a point.'/>"
+"  <Option name='Y_POSSIBLE_NAMES' type='string' description='Comma separated list of possible names for Y/latitude coordinate of a point.'/>"
+"  <Option name='Z_POSSIBLE_NAMES' type='string' description='Comma separated list of possible names for Z/elevation coordinate of a point.'/>"
+"  <Option name='GEOM_POSSIBLE_NAMES' type='string' description='Comma separated list of possible names for geometry columns.' default='WKT'/>"
+"  <Option name='KEEP_GEOM_COLUMNS' type='boolean' description='whether to add original x/y/geometry columns as regular fields.' default='YES'/>"
+"  <Option name='HEADERS' type='string-select' description='Whether the first line of the file contains column names or not' default='AUTO'>"
+"    <Value>YES</Value>"
+"    <Value>NO</Value>"
+"    <Value>AUTO</Value>"
+"  </Option>"
+"  <Option name='EMPTY_STRING_AS_NULL' type='boolean' description='Whether to consider empty strings as null fields on reading' default='NO'/>"
 "</OpenOptionList>");
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-        
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES, "Integer Integer64 Real String Date DateTime Time" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
+                               "Integer Integer64 Real String Date DateTime "
+                               "Time" );
 
-        poDriver->pfnOpen = OGRCSVDriverOpen;
-        poDriver->pfnIdentify = OGRCSVDriverIdentify;
-        poDriver->pfnCreate = OGRCSVDriverCreate;
-        poDriver->pfnDelete = OGRCSVDriverDelete;
+    poDriver->pfnOpen = OGRCSVDriverOpen;
+    poDriver->pfnIdentify = OGRCSVDriverIdentify;
+    poDriver->pfnCreate = OGRCSVDriverCreate;
+    poDriver->pfnDelete = OGRCSVDriverDelete;
+    poDriver->pfnUnloadDriver = OGRCSVDriverUnload;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/csv/ogrcsvlayer.cpp b/ogr/ogrsf_frmts/csv/ogrcsvlayer.cpp
index fab0366..11221bb 100644
--- a/ogr/ogrsf_frmts/csv/ogrcsvlayer.cpp
+++ b/ogr/ogrsf_frmts/csv/ogrcsvlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrcsvlayer.cpp 32442 2015-12-24 19:13:22Z rouault $
+ * $Id: ogrcsvlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  CSV Translator
  * Purpose:  Implements OGRCSVLayer class.
@@ -34,8 +34,7 @@
 #include "cpl_csv.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrcsvlayer.cpp 32442 2015-12-24 19:13:22Z rouault $");
-
+CPL_CVSID("$Id: ogrcsvlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 
 /************************************************************************/
@@ -52,24 +51,22 @@ static char **CSVSplitLine( const char *pszString, char chDelimiter,
                             int bMergeDelimiter )
 
 {
-    char        **papszRetList = NULL;
-    char        *pszToken;
-    int         nTokenMax, nTokenLen;
+    char **papszRetList = NULL;
 
-    pszToken = (char *) CPLCalloc(10,1);
-    nTokenMax = 10;
+    char *pszToken = static_cast<char *>( CPLCalloc(10, 1) );
+    int nTokenMax = 10;
 
     while( pszString != NULL && *pszString != '\0' )
     {
-        int     bInString = FALSE;
+        bool bInString = false;
 
-        nTokenLen = 0;
+        int nTokenLen = 0;
 
-        /* Try to find the next delimeter, marking end of token */
+        /* Try to find the next delimiter, marking end of token. */
         for( ; *pszString != '\0'; pszString++ )
         {
 
-            /* End if this is a delimeter skip it and break. */
+            /* End if this is a delimiter skip it and break. */
             if( !bInString && *pszString == chDelimiter )
             {
                 pszString++;
@@ -98,7 +95,8 @@ static char **CSVSplitLine( const char *pszString, char chDelimiter,
             if( nTokenLen >= nTokenMax-2 )
             {
                 nTokenMax = nTokenMax * 2 + 10;
-                pszToken = (char *) CPLRealloc( pszToken, nTokenMax );
+                pszToken
+                    = static_cast<char *>( CPLRealloc( pszToken, nTokenMax ) );
             }
 
             pszToken[nTokenLen] = *pszString;
@@ -138,20 +136,16 @@ char **OGRCSVReadParseLineL( VSILFILE * fp, char chDelimiter,
                              int bMergeDelimiter )
 
 {
-    const char  *pszLine;
-    char        *pszWorkLine;
-    char        **papszReturn;
-
-    pszLine = CPLReadLineL( fp );
+    const char *pszLine = CPLReadLineL( fp );
     if( pszLine == NULL )
         return( NULL );
 
     /* Skip BOM */
-    GByte* pabyData = (GByte*) pszLine;
+    const GByte* pabyData = reinterpret_cast<const GByte *>( pszLine );
     if (pabyData[0] == 0xEF && pabyData[1] == 0xBB && pabyData[2] == 0xBF)
         pszLine += 3;
 
-    /* Special fix to read NdfcFacilities.xls that has non-balanced double quotes */
+    // Special fix to read NdfcFacilities.xls with un-balanced double quotes.
     if (chDelimiter == '\t' && bDontHonourStrings)
     {
         return CSLTokenizeStringComplex(pszLine, "\t", FALSE, TRUE);
@@ -169,12 +163,13 @@ char **OGRCSVReadParseLineL( VSILFILE * fp, char chDelimiter,
 /*      We must now count the quotes in our working string, and as      */
 /*      long as it is odd, keep adding new lines.                       */
 /* -------------------------------------------------------------------- */
-    pszWorkLine = CPLStrdup( pszLine );
+    char *pszWorkLine = CPLStrdup( pszLine );
 
-    int i = 0, nCount = 0;
-    int nWorkLineLength = strlen(pszWorkLine);
+    int i = 0;
+    int nCount = 0;
+    size_t nWorkLineLength = strlen(pszWorkLine);
 
-    while( TRUE )
+    while( true )
     {
         for( ; pszWorkLine[i] != '\0'; i++ )
         {
@@ -189,22 +184,25 @@ char **OGRCSVReadParseLineL( VSILFILE * fp, char chDelimiter,
         if( pszLine == NULL )
             break;
 
-        int nLineLen = strlen(pszLine);
+        const size_t nLineLen = strlen(pszLine);
 
-        char* pszWorkLineTmp = (char *)
-            VSIRealloc(pszWorkLine,
-                       nWorkLineLength + nLineLen + 2);
+        char* pszWorkLineTmp = static_cast<char *>(
+            VSI_REALLOC_VERBOSE(
+                pszWorkLine, nWorkLineLength + nLineLen + 2) );
         if (pszWorkLineTmp == NULL)
             break;
         pszWorkLine = pszWorkLineTmp;
-        strcat( pszWorkLine + nWorkLineLength, "\n" ); // This gets lost in CPLReadLine().
+
+        // The '\n' gets lost in CPLReadLine().
+        strcat( pszWorkLine + nWorkLineLength, "\n" );
         strcat( pszWorkLine + nWorkLineLength, pszLine );
 
         nWorkLineLength += nLineLen + 1;
     }
 
-    papszReturn = CSVSplitLine( pszWorkLine, chDelimiter,
-                                bKeepLeadingAndClosingQuotes, bMergeDelimiter );
+    char **papszReturn = CSVSplitLine( pszWorkLine, chDelimiter,
+                                       bKeepLeadingAndClosingQuotes,
+                                       bMergeDelimiter );
 
     CPLFree( pszWorkLine );
 
@@ -218,49 +216,99 @@ char **OGRCSVReadParseLineL( VSILFILE * fp, char chDelimiter,
 /*      file pointer.                                                   */
 /************************************************************************/
 
-OGRCSVLayer::OGRCSVLayer( const char *pszLayerNameIn, 
-                          VSILFILE * fp, const char *pszFilename,
-                          int bNew, int bInWriteMode,
-                          char chDelimiter )
-
+OGRCSVLayer::OGRCSVLayer( const char *pszLayerNameIn,
+                          VSILFILE * fp, const char *pszFilenameIn,
+                          int bNewIn, int bInWriteModeIn,
+                          char chDelimiterIn ) :
+    poFeatureDefn(NULL),
+    fpCSV(fp),
+    nNextFID(1),
+    bHasFieldNames(FALSE),
+    bNew(bNewIn),
+    bInWriteMode(bInWriteModeIn),
+    bUseCRLF(FALSE),
+    bNeedRewindBeforeRead(FALSE),
+    eGeometryFormat(OGR_CSV_GEOM_NONE),
+    pszFilename(CPLStrdup(pszFilenameIn)),
+    bCreateCSVT(FALSE),
+    bWriteBOM(FALSE),
+    chDelimiter(chDelimiterIn),
+    nCSVFieldCount(0),
+    panGeomFieldIndex(NULL),
+    bFirstFeatureAppendedDuringSession(TRUE),
+    bHiddenWKTColumn(FALSE),
+    iNfdcLongitudeS(-1),
+    iNfdcLatitudeS(-1),
+    bDontHonourStrings(FALSE),
+    iLongitudeField(-1),
+    iLatitudeField(-1),
+    iZField(-1),
+    bIsEurostatTSV(FALSE),
+    nEurostatDims(0),
+    nTotalFeatures( bNewIn ? 0 : -1 ),
+    bWarningBadTypeOrWidth(FALSE),
+    bKeepSourceColumns(FALSE),
+    bKeepGeomColumns(TRUE),
+    bMergeDelimiter(FALSE),
+    bEmptyStringNull(FALSE)
 {
-    fpCSV = fp;
-
-    nCSVFieldCount = 0;
-    panGeomFieldIndex = NULL;
-    iNfdcLatitudeS = iNfdcLongitudeS = -1;
-    iLatitudeField = iLongitudeField = -1;
-    bHasFieldNames = FALSE;
-    this->bInWriteMode = bInWriteMode;
-    this->bNew = bNew;
-    this->pszFilename = CPLStrdup(pszFilename);
-    this->chDelimiter = chDelimiter;
-
-    bFirstFeatureAppendedDuringSession = TRUE;
-    bHiddenWKTColumn = FALSE;
-    bUseCRLF = FALSE;
-    bNeedRewindBeforeRead = FALSE;
-    eGeometryFormat = OGR_CSV_GEOM_NONE;
-
-    nNextFID = 1;
-
     poFeatureDefn = new OGRFeatureDefn( pszLayerNameIn );
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbNone );
+}
 
-    bCreateCSVT = FALSE;
-    bDontHonourStrings = FALSE;
-    bWriteBOM = FALSE;
-
-    bIsEurostatTSV = FALSE;
-    nEurostatDims = 0;
+/************************************************************************/
+/*                             Matches()                                */
+/************************************************************************/
 
-    nTotalFeatures = -1;
-    bWarningBadTypeOrWidth = FALSE;
-    bKeepSourceColumns = FALSE;
-    
-    bMergeDelimiter = FALSE;
+int OGRCSVLayer::Matches(const char* pszFieldName, char** papszPossibleNames)
+{
+    if( papszPossibleNames == NULL )
+        return FALSE;
+    for(char** papszIter = papszPossibleNames; *papszIter; papszIter++)
+    {
+        const char* pszPattern = *papszIter;
+        const char* pszStar = strstr(pszPattern, "*");
+        if( pszStar == NULL )
+        {
+            if( EQUAL(pszFieldName, pszPattern) )
+                return TRUE;
+        }
+        else
+        {
+            if( pszStar == pszPattern )
+            {
+                if( strlen(pszPattern) >= 3 &&
+                    pszPattern[strlen(pszPattern)-1] == '*' )
+                {
+                    // *pattern*
+                    CPLString oPattern(pszPattern+1);
+                    oPattern.resize(oPattern.size()-1);
+                    if( CPLString(pszFieldName).ifind(oPattern)
+                        != std::string::npos )
+                        return TRUE;
+                }
+                else
+                {
+                    // *pattern
+                    if( strlen(pszFieldName) >= strlen(pszPattern)-1 &&
+                        EQUAL( pszFieldName + strlen(pszFieldName)
+                               - (strlen(pszPattern)-1), pszPattern+1) )
+                    {
+                        return TRUE;
+                    }
+                }
+            }
+            else if( pszPattern[strlen(pszPattern)-1] == '*' )
+            {
+                // pattern*
+                if( EQUALN(pszFieldName, pszPattern, strlen(pszPattern)-1) )
+                    return TRUE;
+            }
+        }
+    }
+    return FALSE;
 }
 
 /************************************************************************/
@@ -272,7 +320,10 @@ void OGRCSVLayer::BuildFeatureDefn( const char* pszNfdcGeomField,
                                     char** papszOpenOptions )
 {
 
-    bMergeDelimiter = CSLFetchBoolean(papszOpenOptions, "MERGE_SEPARATOR", FALSE);
+    bMergeDelimiter
+        = CSLFetchBoolean(papszOpenOptions, "MERGE_SEPARATOR", FALSE);
+    bEmptyStringNull
+        = CSLFetchBoolean(papszOpenOptions, "EMPTY_STRING_AS_NULL", FALSE);
 
 /* -------------------------------------------------------------------- */
 /*      If this is not a new file, read ahead to establish if it is     */
@@ -297,65 +348,79 @@ void OGRCSVLayer::BuildFeatureDefn( const char* pszNfdcGeomField,
 
 /* -------------------------------------------------------------------- */
 /*      Check if the first record seems to be field definitions or      */
-/*      not.  We assume it is field definitions if none of the          */
-/*      values are strictly numeric.                                    */
+/*      not.  We assume it is field definitions if the HEADERS option   */
+/*      not supplied and none of the values are strictly numeric.       */
 /* -------------------------------------------------------------------- */
     char **papszTokens = NULL;
-    int nFieldCount=0, iField;
+    int nFieldCount=0;
 
     if( !bNew )
     {
-        const char *pszLine = NULL;
-        char szDelimiter[2];
-        szDelimiter[0] = chDelimiter; szDelimiter[1] = '\0';
-
-        pszLine = CPLReadLineL( fpCSV );
+        const char *pszLine = CPLReadLineL( fpCSV );
         if ( pszLine != NULL )
         {
             /* Detect and remove UTF-8 BOM marker if found (#4623) */
-            if (pszLine[0] == (char)0xEF &&
-                pszLine[1] == (char)0xBB &&
-                pszLine[2] == (char)0xBF)
+            if (((unsigned char*)pszLine)[0] == 0xEF &&
+                ((unsigned char*)pszLine)[1] == 0xBB &&
+                ((unsigned char*)pszLine)[2] == 0xBF)
             {
                 pszLine += 3;
             }
 
-            /* tokenize the strings and preserve quotes, so we can separate string from numeric */
-            /* this is only used in the test for bHasFieldNames (bug #4361) */
-            papszTokens = CSLTokenizeString2( pszLine, szDelimiter, 
+            // Tokenize the strings and preserve quotes, so we can separate
+            // string from numeric this is only used in the test for
+            // bHasFieldNames (bug #4361).
+            char szDelimiter[2] = { chDelimiter, '\0' };
+            papszTokens = CSLTokenizeString2( pszLine, szDelimiter,
                                               (CSLT_HONOURSTRINGS |
                                                CSLT_ALLOWEMPTYTOKENS |
                                                CSLT_PRESERVEQUOTES) );
             nFieldCount = CSLCount( papszTokens );
-            bHasFieldNames = TRUE;
 
-            for( iField = 0; iField < nFieldCount && bHasFieldNames; iField++ )
-            {
-                CPLValueType eType = CPLGetValueType(papszTokens[iField]);
-                if ( (eType == CPL_VALUE_INTEGER ||
-                      eType == CPL_VALUE_REAL) ) {
-                    /* we have a numeric field, therefore do not consider the first line as field names */
-                    bHasFieldNames = FALSE;
+            const char* pszCSVHeaders
+                = CSLFetchNameValueDef(papszOpenOptions, "HEADERS", "AUTO");
+
+            if (EQUAL(pszCSVHeaders, "YES"))
+                bHasFieldNames = TRUE;
+            else if (EQUAL(pszCSVHeaders, "NO"))
+                bHasFieldNames = FALSE;
+            else {
+                // detect via checking for the presence of numeric values.
+                bHasFieldNames = TRUE;
+                for( int iField = 0;
+                     iField < nFieldCount && bHasFieldNames;
+                     iField++ )
+                {
+                    const CPLValueType eType
+                        = CPLGetValueType(papszTokens[iField]);
+                    if ( (eType == CPL_VALUE_INTEGER ||
+                          eType == CPL_VALUE_REAL) ) {
+                        // We have a numeric field, therefore do not consider
+                        // the first line as field names.
+                        bHasFieldNames = FALSE;
+                    }
                 }
-            }
 
-            CPLString osExt = OGRCSVDataSource::GetRealExtension(pszFilename);
+                const CPLString osExt
+                    = OGRCSVDataSource::GetRealExtension(pszFilename);
 
-            /* Eurostat .tsv files */
-            if( EQUAL(osExt, "tsv") && nFieldCount > 1 &&
-                strchr(papszTokens[0], ',') != NULL && strchr(papszTokens[0], '\\') != NULL )
-            {
-                bHasFieldNames = TRUE;
-                bIsEurostatTSV = TRUE;
+                /* Eurostat .tsv files */
+                if( EQUAL(osExt, "tsv") && nFieldCount > 1 &&
+                    strchr(papszTokens[0], ',') != NULL
+                    && strchr(papszTokens[0], '\\') != NULL )
+                {
+                    bHasFieldNames = TRUE;
+                    bIsEurostatTSV = TRUE;
+                }
             }
 
             /* tokenize without quotes to get the actual values */
             CSLDestroy( papszTokens );
-            // papszTokens = OGRCSVReadParseLineL( fpCSV, chDelimiter, FALSE );   
-            int nFlags = CSLT_HONOURSTRINGS;
+            // papszTokens = OGRCSVReadParseLineL( fpCSV, chDelimiter, FALSE );
+            int l_nFlags = CSLT_HONOURSTRINGS;
             if( !bMergeDelimiter )
-                nFlags |= CSLT_ALLOWEMPTYTOKENS;
-            papszTokens = CSLTokenizeString2( pszLine, szDelimiter,  nFlags );
+                l_nFlags |= CSLT_ALLOWEMPTYTOKENS;
+            papszTokens = CSLTokenizeString2( pszLine, szDelimiter,  l_nFlags );
             nFieldCount = CSLCount( papszTokens );
         }
     }
@@ -364,11 +429,12 @@ void OGRCSVLayer::BuildFeatureDefn( const char* pszNfdcGeomField,
 
     if( !bNew )
         ResetReading();
- 
+
     nCSVFieldCount = nFieldCount;
-    
-    panGeomFieldIndex = (int*) CPLCalloc(nFieldCount, sizeof(int));
-    for( iField = 0; iField < nFieldCount; iField++ )
+
+    panGeomFieldIndex
+        = static_cast<int *>( CPLCalloc(nFieldCount, sizeof(int)) );
+    for( int iField = 0; iField < nFieldCount; iField++ )
     {
         panGeomFieldIndex[iField] = -1;
     }
@@ -413,7 +479,7 @@ void OGRCSVLayer::BuildFeatureDefn( const char* pszNfdcGeomField,
                 { "TIMEZONE", OFTString },
                 { "MODDATE", OFTString }
             };
-            for(iField = 0; iField < nFieldCount; iField++)
+            for( int iField = 0; iField < nFieldCount; iField++)
             {
                 OGRFieldDefn oFieldDefn(asGeonamesFieldDesc[iField].pszName,
                                         asGeonamesFieldDesc[iField].eType);
@@ -431,13 +497,14 @@ void OGRCSVLayer::BuildFeatureDefn( const char* pszNfdcGeomField,
 
 
 /* -------------------------------------------------------------------- */
-/*      Search a csvt file for types                                */
+/*      Search a csvt file for types                                    */
 /* -------------------------------------------------------------------- */
     char** papszFieldTypes = NULL;
     if (!bNew) {
         char* dname = CPLStrdup(CPLGetDirname(pszFilename));
         char* fname = CPLStrdup(CPLGetBasename(pszFilename));
-        VSILFILE* fpCSVT = VSIFOpenL(CPLFormFilename(dname, fname, ".csvt"), "r");
+        VSILFILE* fpCSVT = VSIFOpenL(
+            CPLFormFilename( dname, fname, ".csvt" ), "r" );
         CPLFree(dname);
         CPLFree(fname);
         if (fpCSVT!=NULL) {
@@ -448,24 +515,42 @@ void OGRCSVLayer::BuildFeatureDefn( const char* pszNfdcGeomField,
     }
 
 /* -------------------------------------------------------------------- */
-/*      Optionaly auto-detect types                                     */
+/*      Optionally auto-detect types                                    */
 /* -------------------------------------------------------------------- */
     if( !bNew && papszFieldTypes == NULL &&
-        CSLTestBoolean(CSLFetchNameValueDef(papszOpenOptions,
+        CPLTestBool(CSLFetchNameValueDef(papszOpenOptions,
                                                      "AUTODETECT_TYPE", "NO")) )
     {
         papszFieldTypes = AutodetectFieldTypes(papszOpenOptions, nFieldCount);
         if( papszFieldTypes != NULL )
         {
-            bKeepSourceColumns = CSLTestBoolean(CSLFetchNameValueDef(papszOpenOptions,
-                                                     "KEEP_SOURCE_COLUMNS", "NO"));
+            bKeepSourceColumns = CPLTestBool(
+                CSLFetchNameValueDef( papszOpenOptions,
+                                      "KEEP_SOURCE_COLUMNS", "NO" ) );
         }
     }
 
+    char** papszGeomPossibleNames =
+         CSLTokenizeString2(
+             CSLFetchNameValue(papszOpenOptions, "GEOM_POSSIBLE_NAMES"),
+             ",", 0);
+    char** papszXPossibleNames =
+         CSLTokenizeString2(
+             CSLFetchNameValue(papszOpenOptions, "X_POSSIBLE_NAMES"),
+             ",", 0);
+    char** papszYPossibleNames =
+         CSLTokenizeString2(
+             CSLFetchNameValue(papszOpenOptions, "Y_POSSIBLE_NAMES"), ",", 0);
+    char** papszZPossibleNames =
+         CSLTokenizeString2(
+              CSLFetchNameValue(papszOpenOptions, "Z_POSSIBLE_NAMES"), ",", 0);
+    bKeepGeomColumns = CPLTestBool(
+        CSLFetchNameValueDef(papszOpenOptions, "KEEP_GEOM_COLUMNS", "YES" ) );
+
 /* -------------------------------------------------------------------- */
 /*      Build field definitions.                                        */
 /* -------------------------------------------------------------------- */
-    for( iField = 0; !bIsEurostatTSV && iField < nFieldCount; iField++ )
+    for( int iField = 0; !bIsEurostatTSV && iField < nFieldCount; iField++ )
     {
         char *pszFieldName = NULL;
         char szFieldNameBuffer[100];
@@ -474,11 +559,11 @@ void OGRCSVLayer::BuildFeatureDefn( const char* pszNfdcGeomField,
         {
             pszFieldName = papszTokens[iField];
 
-            // trim white space. 
+            // Trim white space.
             while( *pszFieldName == ' ' )
                 pszFieldName++;
 
-            while( pszFieldName[0] != '\0' 
+            while( pszFieldName[0] != '\0'
                 && pszFieldName[strlen(pszFieldName)-1] == ' ' )
                 pszFieldName[strlen(pszFieldName)-1] = '\0';
 
@@ -496,12 +581,54 @@ void OGRCSVLayer::BuildFeatureDefn( const char* pszNfdcGeomField,
                 break;
             }
             pszFieldName = szFieldNameBuffer;
-            sprintf( szFieldNameBuffer, "field_%d", iField+1 );
+            snprintf( szFieldNameBuffer, sizeof(szFieldNameBuffer),
+                      "field_%d", iField+1 );
         }
 
         OGRFieldDefn oField(pszFieldName, OFTString);
         if (papszFieldTypes!=NULL && iField<CSLCount(papszFieldTypes)) {
-            if (EQUAL(papszFieldTypes[iField], "Integer(Boolean)"))
+            if( EQUAL(papszFieldTypes[iField], "WKT") )
+            {
+                eGeometryFormat = OGR_CSV_GEOM_AS_WKT;
+                panGeomFieldIndex[iField] = poFeatureDefn->GetGeomFieldCount();
+                OGRGeomFieldDefn oGeomFieldDefn( oField.GetNameRef(),
+                                                 wkbUnknown );
+                poFeatureDefn->AddGeomFieldDefn(&oGeomFieldDefn);
+                if( bKeepGeomColumns )
+                    poFeatureDefn->AddFieldDefn( &oField );
+                continue;
+            }
+            else if( EQUAL(papszFieldTypes[iField], "CoordX")
+                     || EQUAL(papszFieldTypes[iField], "Point(X)") )
+            {
+                oField.SetType(OFTReal);
+                iLongitudeField = iField;
+                osXField = oField.GetNameRef();
+                if( bKeepGeomColumns )
+                    poFeatureDefn->AddFieldDefn( &oField );
+                continue;
+            }
+            else if( EQUAL(papszFieldTypes[iField], "CoordY")
+                     || EQUAL(papszFieldTypes[iField], "Point(Y)") )
+            {
+                oField.SetType(OFTReal);
+                iLatitudeField = iField;
+                osYField = oField.GetNameRef();
+                if( bKeepGeomColumns )
+                    poFeatureDefn->AddFieldDefn( &oField );
+                continue;
+            }
+            else if( EQUAL(papszFieldTypes[iField], "CoordZ")
+                     || EQUAL(papszFieldTypes[iField], "Point(Z)") )
+            {
+                oField.SetType(OFTReal);
+                iZField = iField;
+                osZField = oField.GetNameRef();
+                if( bKeepGeomColumns )
+                    poFeatureDefn->AddFieldDefn( &oField );
+                continue;
+            }
+            else if (EQUAL(papszFieldTypes[iField], "Integer(Boolean)"))
             {
                 oField.SetType(OFTInteger);
                 oField.SetSubType(OFSTBoolean);
@@ -520,8 +647,10 @@ void OGRCSVLayer::BuildFeatureDefn( const char* pszNfdcGeomField,
             else
             {
                 char* pszLeftParenthesis = strchr(papszFieldTypes[iField], '(');
-                if (pszLeftParenthesis && pszLeftParenthesis != papszFieldTypes[iField] &&
-                    pszLeftParenthesis[1] >= '0' && pszLeftParenthesis[1] <= '9')
+                if ( pszLeftParenthesis &&
+                     pszLeftParenthesis != papszFieldTypes[iField] &&
+                     pszLeftParenthesis[1] >= '0' &&
+                     pszLeftParenthesis[1] <= '9')
                 {
                     int nWidth = 0;
                     int nPrecision = 0;
@@ -550,23 +679,36 @@ void OGRCSVLayer::BuildFeatureDefn( const char* pszNfdcGeomField,
                 else if (EQUAL(papszFieldTypes[iField], "String"))
                     oField.SetType(OFTString);
                 else if (EQUAL(papszFieldTypes[iField], "Date"))
-                    oField.SetType(OFTDate); 
+                    oField.SetType(OFTDate);
                 else if (EQUAL(papszFieldTypes[iField], "Time"))
                     oField.SetType(OFTTime);
                 else if (EQUAL(papszFieldTypes[iField], "DateTime"))
                     oField.SetType(OFTDateTime);
                 else
-                    CPLError(CE_Warning, CPLE_NotSupported, "Unknown type : %s", papszFieldTypes[iField]);
+                    CPLError( CE_Warning, CPLE_NotSupported,
+                              "Unknown type : %s", papszFieldTypes[iField]);
             }
         }
 
-        if( (EQUAL(oField.GetNameRef(),"WKT") ||
-             EQUALN(oField.GetNameRef(),"_WKT", 4) )
+        if( Matches(oField.GetNameRef(),papszZPossibleNames) )
+        {
+            oField.SetType(OFTReal);
+            iZField = iField;
+            osZField = oField.GetNameRef();
+            if( !bKeepGeomColumns )
+                continue;
+        }
+        else if( ( iNfdcLatitudeS != -1 && iNfdcLongitudeS != -1 ) ||
+            ( iLatitudeField != -1 && iLongitudeField != -1 ) )
+        {
+            /* do nothing */
+        }
+        else if( (EQUAL(oField.GetNameRef(),"WKT") ||
+             STARTS_WITH_CI(oField.GetNameRef(), "_WKT") )
             && oField.GetType() == OFTString )
         {
             eGeometryFormat = OGR_CSV_GEOM_AS_WKT;
 
-            const char* pszFieldName = oField.GetNameRef();
             panGeomFieldIndex[iField] = poFeatureDefn->GetGeomFieldCount();
             OGRGeomFieldDefn oGeomFieldDefn(
                 EQUAL(pszFieldName,"WKT") ? "" : CPLSPrintf("geom_%s", pszFieldName),
@@ -597,43 +739,91 @@ void OGRCSVLayer::BuildFeatureDefn( const char* pszNfdcGeomField,
                 oGeomFieldDefn.SetType(wkbMultiPolygon);
 
             poFeatureDefn->AddGeomFieldDefn(&oGeomFieldDefn);
+            if( !bKeepGeomColumns )
+                continue;
+        }
+        else if( Matches(oField.GetNameRef(),papszGeomPossibleNames) )
+        {
+            eGeometryFormat = OGR_CSV_GEOM_AS_SOME_GEOM_FORMAT;
+            panGeomFieldIndex[iField] = poFeatureDefn->GetGeomFieldCount();
+            OGRGeomFieldDefn oGeomFieldDefn(oField.GetNameRef(), wkbUnknown );
+            poFeatureDefn->AddGeomFieldDefn(&oGeomFieldDefn);
+            if( !bKeepGeomColumns )
+                continue;
+        }
+        else if( Matches(oField.GetNameRef(),papszXPossibleNames) &&
+                 poFeatureDefn->GetGeomFieldCount() == 0 )
+        {
+            oField.SetType(OFTReal);
+            iLongitudeField = iField;
+            osXField = oField.GetNameRef();
+            if( !bKeepGeomColumns )
+                continue;
+        }
+        else if( Matches(oField.GetNameRef(),papszYPossibleNames) &&
+                 poFeatureDefn->GetGeomFieldCount() == 0 )
+        {
+            oField.SetType(OFTReal);
+            iLatitudeField = iField;
+            osYField = oField.GetNameRef();
+            if( !bKeepGeomColumns )
+                continue;
         }
 
         /*http://www.faa.gov/airports/airport_safety/airportdata_5010/menu/index.cfm specific */
-        if ( pszNfdcGeomField != NULL &&
+        else if ( pszNfdcGeomField != NULL &&
                   EQUALN(oField.GetNameRef(), pszNfdcGeomField, strlen(pszNfdcGeomField)) &&
-                  EQUAL(oField.GetNameRef() + strlen(pszNfdcGeomField), "LatitudeS") )
+                  EQUAL(oField.GetNameRef() + strlen(pszNfdcGeomField), "LatitudeS") &&
+                 poFeatureDefn->GetGeomFieldCount() == 0  )
+        {
             iNfdcLatitudeS = iField;
+            if( !bKeepGeomColumns )
+                continue;
+        }
         else if ( pszNfdcGeomField != NULL &&
                   EQUALN(oField.GetNameRef(), pszNfdcGeomField, strlen(pszNfdcGeomField)) &&
-                  EQUAL(oField.GetNameRef() + strlen(pszNfdcGeomField), "LongitudeS") )
+                  EQUAL(oField.GetNameRef() + strlen(pszNfdcGeomField), "LongitudeS") &&
+                 poFeatureDefn->GetGeomFieldCount() == 0  )
+        {
             iNfdcLongitudeS = iField;
+            if( !bKeepGeomColumns )
+                continue;
+        }
 
         /* GNIS specific */
         else if ( pszGeonamesGeomFieldPrefix != NULL &&
                   EQUALN(oField.GetNameRef(), pszGeonamesGeomFieldPrefix, strlen(pszGeonamesGeomFieldPrefix)) &&
                   (EQUAL(oField.GetNameRef() + strlen(pszGeonamesGeomFieldPrefix), "_LAT_DEC") ||
                    EQUAL(oField.GetNameRef() + strlen(pszGeonamesGeomFieldPrefix), "_LATITUDE_DEC") ||
-                   EQUAL(oField.GetNameRef() + strlen(pszGeonamesGeomFieldPrefix), "_LATITUDE")) )
+                   EQUAL(oField.GetNameRef() + strlen(pszGeonamesGeomFieldPrefix), "_LATITUDE")) &&
+                 poFeatureDefn->GetGeomFieldCount() == 0  )
         {
             oField.SetType(OFTReal);
             iLatitudeField = iField;
+            osYField = oField.GetNameRef();
+            if( !bKeepGeomColumns )
+                continue;
         }
         else if ( pszGeonamesGeomFieldPrefix != NULL &&
                   EQUALN(oField.GetNameRef(), pszGeonamesGeomFieldPrefix, strlen(pszGeonamesGeomFieldPrefix)) &&
                   (EQUAL(oField.GetNameRef() + strlen(pszGeonamesGeomFieldPrefix), "_LONG_DEC") ||
                    EQUAL(oField.GetNameRef() + strlen(pszGeonamesGeomFieldPrefix), "_LONGITUDE_DEC") ||
-                   EQUAL(oField.GetNameRef() + strlen(pszGeonamesGeomFieldPrefix), "_LONGITUDE")) )
+                   EQUAL(oField.GetNameRef() + strlen(pszGeonamesGeomFieldPrefix), "_LONGITUDE")) &&
+                 poFeatureDefn->GetGeomFieldCount() == 0  )
         {
             oField.SetType(OFTReal);
             iLongitudeField = iField;
+            osXField = oField.GetNameRef();
+            if( !bKeepGeomColumns )
+                continue;
         }
 
         poFeatureDefn->AddFieldDefn( &oField );
 
         if( bKeepSourceColumns && oField.GetType() != OFTString )
         {
-            OGRFieldDefn oFieldOriginal( CPLSPrintf("%s_original", oField.GetNameRef()), OFTString);
+            OGRFieldDefn oFieldOriginal(
+                CPLSPrintf("%s_original", oField.GetNameRef()), OFTString);
             poFeatureDefn->AddFieldDefn( &oFieldOriginal );
         }
     }
@@ -641,19 +831,57 @@ void OGRCSVLayer::BuildFeatureDefn( const char* pszNfdcGeomField,
     if ( iNfdcLatitudeS != -1 && iNfdcLongitudeS != -1 )
     {
         bDontHonourStrings = TRUE;
-        poFeatureDefn->SetGeomType( wkbPoint );
+        if( poFeatureDefn->GetGeomFieldCount() == 0 )
+            poFeatureDefn->SetGeomType( wkbPoint );
+        else
+        {
+            iNfdcLatitudeS = iNfdcLongitudeS = -1;
+            iLatitudeField = iLongitudeField = -1;
+        }
     }
     else if ( iLatitudeField != -1 && iLongitudeField != -1 )
     {
-        poFeatureDefn->SetGeomType( wkbPoint );
+        if( poFeatureDefn->GetGeomFieldCount() == 0 )
+            poFeatureDefn->SetGeomType( (iZField >= 0) ? wkbPoint25D : wkbPoint );
+        else
+        {
+            iNfdcLatitudeS = iNfdcLongitudeS = -1;
+            iLatitudeField = iLongitudeField = -1;
+        }
+    }
+
+    if( poFeatureDefn->GetGeomFieldCount() > 0 &&
+        poFeatureDefn->GetGeomFieldDefn(0)->GetSpatialRef() == NULL )
+    {
+        VSILFILE* fpPRJ = VSIFOpenL(CPLResetExtension(pszFilename, "prj"), "rb");
+        if( fpPRJ != NULL )
+        {
+            GByte* pabyRet = NULL;
+            if( VSIIngestFile( fpPRJ, NULL, &pabyRet, NULL, 1000000 ) )
+            {
+                OGRSpatialReference* poSRS = new OGRSpatialReference();
+                if( poSRS->SetFromUserInput((const char*)pabyRet) == OGRERR_NONE )
+                {
+                    poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
+                }
+                poSRS->Release();
+            }
+            CPLFree(pabyRet);
+            VSIFCloseL(fpPRJ);
+        }
     }
 
+    CSLDestroy(papszGeomPossibleNames);
+    CSLDestroy(papszXPossibleNames);
+    CSLDestroy(papszYPossibleNames);
+    CSLDestroy(papszZPossibleNames);
+
 /* -------------------------------------------------------------------- */
 /*      Build field definitions for Eurostat TSV files.                 */
 /* -------------------------------------------------------------------- */
 
     CPLString osSeqDim;
-    for( iField = 0; bIsEurostatTSV && iField < nFieldCount; iField++ )
+    for( int iField = 0; bIsEurostatTSV && iField < nFieldCount; iField++ )
     {
         if( iField == 0 )
         {
@@ -670,14 +898,18 @@ void OGRCSVLayer::BuildFeatureDefn( const char* pszNfdcGeomField,
         }
         else
         {
-            if( papszTokens[iField][0] != '\0' 
+            if( papszTokens[iField][0] != '\0'
                 && papszTokens[iField][strlen(papszTokens[iField])-1] == ' ' )
                 papszTokens[iField][strlen(papszTokens[iField])-1] = '\0';
 
-            OGRFieldDefn oField(CPLSPrintf("%s_%s", osSeqDim.c_str(), papszTokens[iField]), OFTReal);
+            OGRFieldDefn oField(
+                CPLSPrintf("%s_%s", osSeqDim.c_str(), papszTokens[iField]),
+                OFTReal);
             poFeatureDefn->AddFieldDefn( &oField );
 
-            OGRFieldDefn oField2(CPLSPrintf("%s_%s_flag", osSeqDim.c_str(), papszTokens[iField]), OFTString);
+            OGRFieldDefn oField2(
+                CPLSPrintf("%s_%s_flag", osSeqDim.c_str(), papszTokens[iField]),
+                OFTString);
             poFeatureDefn->AddFieldDefn( &oField2 );
         }
     }
@@ -716,19 +948,18 @@ static int OGRCSVIsFalse(const char* pszStr)
 
 char** OGRCSVLayer::AutodetectFieldTypes(char** papszOpenOptions, int nFieldCount)
 {
-    int iField;
     char** papszFieldTypes = NULL;
 
-    /* Use 1000000 as default maximum distance to be compatible with /vsistdin/ */
-    /* caching */
+    // Use 1000000 as default maximum distance to be compatible with /vsistdin/
+    // caching.
     int nBytes = atoi(CSLFetchNameValueDef(papszOpenOptions,
                                             "AUTODETECT_SIZE_LIMIT", "1000000"));
     if( nBytes == 0 )
     {
         vsi_l_offset nCurPos = VSIFTellL(fpCSV);
-        VSIFSeekL(fpCSV, 0, SEEK_END);
+        CPL_IGNORE_RET_VAL(VSIFSeekL(fpCSV, 0, SEEK_END));
         vsi_l_offset nFileSize = VSIFTellL(fpCSV);
-        VSIFSeekL(fpCSV, nCurPos, SEEK_SET);
+        CPL_IGNORE_RET_VAL(VSIFSeekL(fpCSV, nCurPos, SEEK_SET));
         if( nFileSize < INT_MAX )
             nBytes = (int)nFileSize;
         else
@@ -737,8 +968,8 @@ char** OGRCSVLayer::AutodetectFieldTypes(char** papszOpenOptions, int nFieldCoun
     else if( nBytes < 0 || (vsi_l_offset)nBytes < VSIFTellL(fpCSV) )
         nBytes = 1000000;
 
-    const char* pszAutodetectWidth = CSLFetchNameValueDef(papszOpenOptions,
-                                                          "AUTODETECT_WIDTH", "NO");
+    const char* pszAutodetectWidth
+        = CSLFetchNameValueDef(papszOpenOptions, "AUTODETECT_WIDTH", "NO");
     int bAutodetectWidth = FALSE;
     int bAutodetectWidthForIntOrReal = FALSE;
     if( EQUAL(pszAutodetectWidth, "YES") )
@@ -746,14 +977,15 @@ char** OGRCSVLayer::AutodetectFieldTypes(char** papszOpenOptions, int nFieldCoun
     else if( EQUAL(pszAutodetectWidth, "STRING_ONLY") )
         bAutodetectWidth = TRUE;
 
-    int bQuotedFieldAsString = CSLTestBoolean(CSLFetchNameValueDef(papszOpenOptions,
-                                                      "QUOTED_FIELDS_AS_STRING", "NO"));
+    int bQuotedFieldAsString = CPLTestBool(
+        CSLFetchNameValueDef( papszOpenOptions, "QUOTED_FIELDS_AS_STRING",
+                              "NO" ) );
 
-    char* pszData = (char*) VSIMalloc( nBytes );
+    char* pszData = (char*) VSI_MALLOC_VERBOSE( nBytes );
     if( pszData != NULL && (vsi_l_offset)nBytes > VSIFTellL(fpCSV) )
     {
         int nRequested = nBytes - 1 - (int)VSIFTellL(fpCSV);
-        int nRead = VSIFReadL(pszData, 1, nRequested, fpCSV);
+        int nRead = static_cast<int>(VSIFReadL(pszData, 1, nRequested, fpCSV));
         pszData[nRead] = 0;
 
         CPLString osTmpMemFile(CPLSPrintf("/vsimem/tmp%p", this));
@@ -776,7 +1008,8 @@ char** OGRCSVLayer::AutodetectFieldTypes(char** papszOpenOptions, int nFieldCoun
 
         while( !VSIFEofL(fpMem) )
         {
-            char** papszTokens = OGRCSVReadParseLineL( fpMem, chDelimiter, FALSE,
+            char** papszTokens = OGRCSVReadParseLineL( fpMem, chDelimiter,
+                                                       FALSE,
                                                        bQuotedFieldAsString,
                                                        bMergeDelimiter );
             /* Can happen if we just reach EOF while trying to read new bytes */
@@ -791,11 +1024,9 @@ char** OGRCSVLayer::AutodetectFieldTypes(char** papszOpenOptions, int nFieldCoun
                 break;
             }
 
-            for( iField = 0; papszTokens[iField] != NULL &&
+            for( int iField = 0; papszTokens[iField] != NULL &&
                              iField < nFieldCount; iField++ )
             {
-                int nFieldWidth = 0, nFieldPrecision = 0;
-
                 if( papszTokens[iField][0] == 0 )
                     continue;
                 if (chDelimiter == ';')
@@ -806,28 +1037,33 @@ char** OGRCSVLayer::AutodetectFieldTypes(char** papszOpenOptions, int nFieldCoun
                 }
                 CPLValueType eType = CPLGetValueType(papszTokens[iField]);
 
+                int nFieldWidth = 0;
+                int nFieldPrecision = 0;
+
                 if( bAutodetectWidth )
                 {
-                    nFieldWidth = strlen(papszTokens[iField]);
-                    if( papszTokens[iField][0] == '"' && 
+                    nFieldWidth = static_cast<int>(strlen(papszTokens[iField]));
+                    if( papszTokens[iField][0] == '"' &&
                         papszTokens[iField][nFieldWidth-1] == '"' )
                     {
                         nFieldWidth -= 2;
                     }
-                    if( eType == CPL_VALUE_REAL && bAutodetectWidthForIntOrReal )
+                    if( eType == CPL_VALUE_REAL &&
+                        bAutodetectWidthForIntOrReal )
                     {
                         const char* pszDot = strchr(papszTokens[iField], '.');
                         if( pszDot != NULL )
-                            nFieldPrecision = strlen(pszDot + 1);
+                            nFieldPrecision
+                                = static_cast<int>(strlen(pszDot + 1));
                     }
                 }
 
                 OGRFieldType eOGRFieldType;
-                int bIsBoolean = FALSE;
+                bool bIsBoolean = false;
                 if( eType == CPL_VALUE_INTEGER )
                 {
                     GIntBig nVal = CPLAtoGIntBig(papszTokens[iField]);
-                    if( (GIntBig)(int)nVal != nVal )
+                    if( !CPL_INT64_FITS_ON_INT32(nVal) )
                         eOGRFieldType = OFTInteger64;
                     else
                         eOGRFieldType = OFTInteger;
@@ -903,7 +1139,7 @@ char** OGRCSVLayer::AutodetectFieldTypes(char** papszOpenOptions, int nFieldCoun
                             aeFieldType[iField] = OFTString;
                             nStringFieldCount ++;
                         }
-                    } 
+                    }
                     else if ( aeFieldType[iField] == OFTReal )
                     {
                         if( eOGRFieldType != OFTInteger &&
@@ -953,8 +1189,9 @@ char** OGRCSVLayer::AutodetectFieldTypes(char** papszOpenOptions, int nFieldCoun
                 break;
         }
 
-        papszFieldTypes = (char**) CPLCalloc( nFieldCount + 1, sizeof(char*) );
-        for(iField = 0; iField < nFieldCount; iField ++ )
+        papszFieldTypes = static_cast<char**>(
+            CPLCalloc( nFieldCount + 1, sizeof(char*) ) );
+        for( int iField = 0; iField < nFieldCount; iField ++ )
         {
             CPLString osFieldType;
             if( !abFieldSet[iField] )
@@ -1017,15 +1254,15 @@ char** OGRCSVLayer::AutodetectFieldTypes(char** papszOpenOptions, int nFieldCoun
 OGRCSVLayer::~OGRCSVLayer()
 
 {
-    if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
+    if( m_nFeaturesRead > 0 )
     {
         CPLDebug( "CSV", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
+                  (int) m_nFeaturesRead,
                   poFeatureDefn->GetName() );
     }
 
     // Make sure the header file is written even if no features are written.
-    if (bNew && bInWriteMode)
+    if ( bNew && bInWriteMode )
         WriteHeader();
 
     CPLFree( panGeomFieldIndex );
@@ -1066,7 +1303,7 @@ char** OGRCSVLayer::GetNextLineTokens()
 /* -------------------------------------------------------------------- */
     char **papszTokens;
 
-    while(TRUE)
+    while( true )
     {
         papszTokens = OGRCSVReadParseLineL( fpCSV, chDelimiter, bDontHonourStrings,
                                             FALSE, bMergeDelimiter );
@@ -1111,7 +1348,7 @@ OGRFeature * OGRCSVLayer::GetNextUnfilteredFeature()
 {
     if (fpCSV == NULL)
         return NULL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read the CSV record.                                            */
 /* -------------------------------------------------------------------- */
@@ -1131,25 +1368,61 @@ OGRFeature * OGRCSVLayer::GetNextUnfilteredFeature()
 /* -------------------------------------------------------------------- */
     int         iAttr;
     int         iOGRField = 0;
-    int         nAttrCount = MIN(CSLCount(papszTokens), nCSVFieldCount );
+    int         nAttrCount = MIN(CSLCount(papszTokens), nCSVFieldCount + (bHiddenWKTColumn ? 1 : 0) );
     CPLValueType eType;
-    
-    for( iAttr = 0; !bIsEurostatTSV && iAttr < nAttrCount; iAttr++, iOGRField++)
+
+    for( iAttr = 0; !bIsEurostatTSV && iAttr < nAttrCount; iAttr++)
     {
-        int iGeom = panGeomFieldIndex[iAttr];
-        if( iGeom >= 0 && papszTokens[iAttr][0] != '\0'&&
-            !(poFeatureDefn->GetGeomFieldDefn(iGeom)->IsIgnored()) )
+        if( (iAttr == iLongitudeField || iAttr == iLatitudeField || iAttr == iZField ) &&
+            !bKeepGeomColumns )
         {
-            char *pszWKT = papszTokens[iAttr];
-            OGRGeometry *poGeom = NULL;
-
-            if( OGRGeometryFactory::createFromWkt( &pszWKT, NULL, &poGeom )
-                == OGRERR_NONE )
+            continue;
+        }
+        int iGeom;
+        if( bHiddenWKTColumn )
+        {
+            if(iAttr == 0)
+                iGeom = 0;
+            else
+                iGeom = panGeomFieldIndex[iAttr - 1];
+        }
+        else
+            iGeom = panGeomFieldIndex[iAttr];
+        if( iGeom >= 0 )
+        {
+            if ( papszTokens[iAttr][0] != '\0'&&
+                 !(poFeatureDefn->GetGeomFieldDefn(iGeom)->IsIgnored()) )
             {
-                poGeom->assignSpatialReference(
-                    poFeatureDefn->GetGeomFieldDefn(iGeom)->GetSpatialRef());
-                poFeature->SetGeomFieldDirectly( iGeom, poGeom );
+                const char* pszStr = papszTokens[iAttr];
+                while( *pszStr == ' ' )
+                    pszStr ++;
+                char *pszWKT = (char*)pszStr;
+                OGRGeometry *poGeom = NULL;
+
+                CPLPushErrorHandler(CPLQuietErrorHandler);
+                if( OGRGeometryFactory::createFromWkt( &pszWKT, NULL, &poGeom )
+                    == OGRERR_NONE )
+                {
+                    poGeom->assignSpatialReference(
+                        poFeatureDefn->GetGeomFieldDefn(iGeom)->GetSpatialRef());
+                    poFeature->SetGeomFieldDirectly( iGeom, poGeom );
+                }
+                else if( *pszStr == '{' &&
+                    (poGeom = (OGRGeometry*)OGR_G_CreateGeometryFromJson(pszStr)) != NULL )
+                {
+                    poFeature->SetGeomFieldDirectly( iGeom, poGeom );
+                }
+                else if( ((*pszStr >= '0' && *pszStr <= '9') ||
+                        (*pszStr >= 'a' && *pszStr <= 'z') ||
+                        (*pszStr >= 'A' && *pszStr <= 'Z') ) &&
+                        (poGeom = OGRGeometryFromHexEWKB(pszStr, NULL, FALSE)) != NULL )
+                {
+                    poFeature->SetGeomFieldDirectly( iGeom, poGeom );
+                }
+                CPLPopErrorHandler();
             }
+            if( !bKeepGeomColumns || (iAttr == 0 && bHiddenWKTColumn) )
+                continue;
         }
 
         OGRFieldDefn* poFieldDefn = poFeatureDefn->GetFieldDefn(iOGRField);
@@ -1218,7 +1491,7 @@ OGRFeature * OGRCSVLayer::GetNextUnfilteredFeature()
                         const char* pszDot = strchr(papszTokens[iAttr], '.');
                         int nPrecision = 0;
                         if( pszDot != NULL )
-                            nPrecision = strlen(pszDot + 1);
+                            nPrecision = static_cast<int>(strlen(pszDot + 1));
                         if( nPrecision > poFieldDefn->GetPrecision() )
                         {
                              bWarningBadTypeOrWidth = TRUE;
@@ -1259,7 +1532,8 @@ OGRFeature * OGRCSVLayer::GetNextUnfilteredFeature()
         }
         else
         {
-            if( !poFieldDefn->IsIgnored() )
+            if( !poFieldDefn->IsIgnored() &&
+                (!bEmptyStringNull || papszTokens[iAttr][0] != '\0') )
             {
                 poFeature->SetField( iOGRField, papszTokens[iAttr] );
                 if( !bWarningBadTypeOrWidth && poFieldDefn->GetWidth() > 0 &&
@@ -1283,6 +1557,8 @@ OGRFeature * OGRCSVLayer::GetNextUnfilteredFeature()
                 poFeature->SetField( iOGRField, papszTokens[iAttr] );
             }
         }
+
+        iOGRField++;
     }
 
 /* -------------------------------------------------------------------- */
@@ -1366,7 +1642,12 @@ OGRFeature * OGRCSVLayer::GetNextUnfilteredFeature()
             double dfLon = CPLAtof(papszTokens[iLongitudeField]);
             double dfLat = CPLAtof(papszTokens[iLatitudeField]);
             if( !(poFeatureDefn->GetGeomFieldDefn(0)->IsIgnored()) )
-                poFeature->SetGeometryDirectly( new OGRPoint(dfLon, dfLat) );
+            {
+                if( iZField != -1 && nAttrCount > iZField && papszTokens[iZField][0] != 0 )
+                    poFeature->SetGeometryDirectly( new OGRPoint(dfLon, dfLat, CPLAtof(papszTokens[iZField])) );
+                else
+                    poFeature->SetGeometryDirectly( new OGRPoint(dfLon, dfLat) );
+            }
         }
     }
 
@@ -1394,12 +1675,12 @@ OGRFeature *OGRCSVLayer::GetNextFeature()
 
     if( bNeedRewindBeforeRead )
         ResetReading();
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read features till we find one that satisfies our current       */
 /*      spatial criteria.                                               */
 /* -------------------------------------------------------------------- */
-    while( TRUE )
+    while( true )
     {
         poFeature = GetNextUnfilteredFeature();
         if( poFeature == NULL )
@@ -1425,7 +1706,7 @@ int OGRCSVLayer::TestCapability( const char * pszCap )
 
 {
     if( EQUAL(pszCap,OLCSequentialWrite) )
-        return bInWriteMode && !bKeepSourceColumns;
+        return bInWriteMode && !bKeepSourceColumns && bKeepGeomColumns;
     else if( EQUAL(pszCap,OLCCreateField) )
         return bNew && !bHasFieldNames;
     else if( EQUAL(pszCap,OLCCreateGeomField) )
@@ -1434,43 +1715,35 @@ int OGRCSVLayer::TestCapability( const char * pszCap )
         return TRUE;
     else if( EQUAL(pszCap,OLCCurveGeometries) )
         return TRUE;
+    else if( EQUAL(pszCap,OLCMeasuredGeometries) )
+        return TRUE;
     else
         return FALSE;
 }
 
 /************************************************************************/
-/*                            CreateField()                             */
+/*                          PreCreateField()                            */
 /************************************************************************/
 
-OGRErr OGRCSVLayer::CreateField( OGRFieldDefn *poNewField, int bApproxOK )
-
+OGRCSVCreateFieldAction OGRCSVLayer::PreCreateField( OGRFeatureDefn* poFeatureDefn,
+                                    OGRFieldDefn *poNewField, int bApproxOK )
 {
-/* -------------------------------------------------------------------- */
-/*      If we have already written our field names, then we are not     */
-/*      allowed to add new fields.                                      */
-/* -------------------------------------------------------------------- */
-    if( !TestCapability(OLCCreateField) )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Unable to create new fields after first feature written.");
-        return OGRERR_FAILURE;
-    }
 
 /* -------------------------------------------------------------------- */
 /*      Does this duplicate an existing field?                          */
 /* -------------------------------------------------------------------- */
-    if( poFeatureDefn->GetFieldIndex( poNewField->GetNameRef() ) != -1 )
+    if( poFeatureDefn->GetFieldIndex( poNewField->GetNameRef() ) >= 0 )
     {
-        if( poFeatureDefn->GetGeomFieldIndex( poNewField->GetNameRef() ) != -1 )
-            return OGRERR_NONE;
-        if( poFeatureDefn->GetGeomFieldIndex( CPLSPrintf("geom_%s", poNewField->GetNameRef()) ) != -1 )
-            return OGRERR_NONE;
-
+        if( poFeatureDefn->GetGeomFieldIndex( poNewField->GetNameRef() ) >= 0 ||
+            poFeatureDefn->GetGeomFieldIndex( CPLSPrintf("geom_%s", poNewField->GetNameRef()) ) >= 0 )
+        {
+            return CREATE_FIELD_DO_NOTHING;
+        }
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Attempt to create field %s, but a field with this name already exists.",
                   poNewField->GetNameRef() );
 
-        return OGRERR_FAILURE;
+        return CREATE_FIELD_ERROR;
     }
 
 /* -------------------------------------------------------------------- */
@@ -1489,21 +1762,47 @@ OGRErr OGRCSVLayer::CreateField( OGRFieldDefn *poNewField, int bApproxOK )
       default:
         if( bApproxOK )
         {
-            CPLError( CE_Warning, CPLE_AppDefined, 
+            CPLError( CE_Warning, CPLE_AppDefined,
                       "Attempt to create field of type %s, but this is not supported\n"
                       "for .csv files.  Just treating as a plain string.",
                       poNewField->GetFieldTypeName( poNewField->GetType() ) );
         }
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Attempt to create field of type %s, but this is not supported\n"
                       "for .csv files.",
                       poNewField->GetFieldTypeName( poNewField->GetType() ) );
-            return OGRERR_FAILURE;
+            return CREATE_FIELD_ERROR;
         }
     }
-    
+    return CREATE_FIELD_PROCEED;
+}
+
+/************************************************************************/
+/*                            CreateField()                             */
+/************************************************************************/
+
+OGRErr OGRCSVLayer::CreateField( OGRFieldDefn *poNewField, int bApproxOK )
+
+{
+/* -------------------------------------------------------------------- */
+/*      If we have already written our field names, then we are not     */
+/*      allowed to add new fields.                                      */
+/* -------------------------------------------------------------------- */
+    if( !TestCapability(OLCCreateField) )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Unable to create new fields after first feature written.");
+        return OGRERR_FAILURE;
+    }
+
+    OGRCSVCreateFieldAction eAction = PreCreateField( poFeatureDefn, poNewField, bApproxOK );
+    if( eAction == CREATE_FIELD_DO_NOTHING )
+        return OGRERR_NONE;
+    if( eAction == CREATE_FIELD_ERROR )
+        return OGRERR_FAILURE;
+
 /* -------------------------------------------------------------------- */
 /*      Seems ok, add to field list.                                    */
 /* -------------------------------------------------------------------- */
@@ -1523,21 +1822,42 @@ OGRErr OGRCSVLayer::CreateField( OGRFieldDefn *poNewField, int bApproxOK )
 /************************************************************************/
 
 OGRErr OGRCSVLayer::CreateGeomField( OGRGeomFieldDefn *poGeomField,
-                                     CPL_UNUSED int bApproxOK )
+                                     int /* bApproxOK */ )
 {
     if( !TestCapability(OLCCreateGeomField) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to create new fields after first feature written.");
         return OGRERR_FAILURE;
     }
+/* -------------------------------------------------------------------- */
+/*      Does this duplicate an existing field?                          */
+/* -------------------------------------------------------------------- */
+    if( poFeatureDefn->GetGeomFieldIndex( poGeomField->GetNameRef() ) >= 0 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Attempt to create geom field %s, but a field with this name already exists.",
+                  poGeomField->GetNameRef() );
+
+        return OGRERR_FAILURE;
+    }
 
     poFeatureDefn->AddGeomFieldDefn( poGeomField );
 
     const char* pszName = poGeomField->GetNameRef();
-    if( EQUALN(pszName, "geom_", strlen("geom_")) )
+    if( EQUAL(pszName, "") )
+    {
+        int nIdx = poFeatureDefn->GetFieldIndex("WKT");
+        if( nIdx >= 0 )
+        {
+            panGeomFieldIndex[nIdx] = poFeatureDefn->GetGeomFieldCount() - 1;
+            return OGRERR_NONE;
+        }
+        pszName = "WKT";
+    }
+    if( STARTS_WITH_CI(pszName, "geom_") )
         pszName += strlen("geom_");
-    if( !EQUAL(pszName, "WKT") && !EQUALN(pszName, "_WKT", 4) )
+    if( !EQUAL(pszName, "WKT") && !STARTS_WITH_CI(pszName, "_WKT") )
         pszName = CPLSPrintf("_WKT%s", pszName);
 
     OGRFieldDefn oRegularFieldDefn( pszName, OFTString );
@@ -1570,6 +1890,7 @@ OGRErr OGRCSVLayer::WriteHeader()
 /* -------------------------------------------------------------------- */
     bNew = FALSE;
     bHasFieldNames = TRUE;
+    bool bOK = true;
 
     for(int iFile=0;iFile<((bCreateCSVT) ? 2 : 1);iFile++)
     {
@@ -1584,8 +1905,8 @@ OGRErr OGRCSVLayer::WriteHeader()
         }
         else
         {
-            if( strncmp(pszFilename, "/vsistdout/", 11) == 0 ||
-                strncmp(pszFilename, "/vsizip/", 8) == 0 )
+            if( STARTS_WITH(pszFilename, "/vsistdout/") ||
+                STARTS_WITH(pszFilename, "/vsizip/") )
                 fpCSV = VSIFOpenL( pszFilename, "wb" );
             else
                 fpCSV = VSIFOpenL( pszFilename, "w+b" );
@@ -1601,44 +1922,44 @@ OGRErr OGRCSVLayer::WriteHeader()
 
         if (bWriteBOM && fpCSV)
         {
-            VSIFWriteL("\xEF\xBB\xBF", 1, 3, fpCSV);
+            bOK &= VSIFWriteL("\xEF\xBB\xBF", 1, 3, fpCSV) > 0;
         }
 
         if (eGeometryFormat == OGR_CSV_GEOM_AS_XYZ)
         {
-            if (fpCSV) VSIFPrintfL( fpCSV, "X%cY%cZ", chDelimiter, chDelimiter);
-            if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", "Real,Real,Real");
+            if (fpCSV) bOK &= VSIFPrintfL( fpCSV, "X%cY%cZ", chDelimiter, chDelimiter) > 0;
+            if (fpCSVT) bOK &= VSIFPrintfL( fpCSVT, "%s", "CoordX,CoordY,Real") > 0;
             if (poFeatureDefn->GetFieldCount() > 0)
             {
-                if (fpCSV) VSIFPrintfL( fpCSV, "%c", chDelimiter );
-                if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", ",");
+                if (fpCSV) bOK &= VSIFPrintfL( fpCSV, "%c", chDelimiter ) > 0;
+                if (fpCSVT) bOK &= VSIFPrintfL( fpCSVT, "%s", ",") > 0;
             }
         }
         else if (eGeometryFormat == OGR_CSV_GEOM_AS_XY)
         {
-            if (fpCSV) VSIFPrintfL( fpCSV, "X%cY", chDelimiter);
-            if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", "Real,Real");
+            if (fpCSV) bOK &= VSIFPrintfL( fpCSV, "X%cY", chDelimiter) > 0;
+            if (fpCSVT) bOK &= VSIFPrintfL( fpCSVT, "%s", "CoordX,CoordY") > 0;
             if (poFeatureDefn->GetFieldCount() > 0)
             {
-                if (fpCSV) VSIFPrintfL( fpCSV, "%c", chDelimiter );
-                if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", ",");
+                if (fpCSV) bOK &= VSIFPrintfL( fpCSV, "%c", chDelimiter ) > 0;
+                if (fpCSVT) bOK &= VSIFPrintfL( fpCSVT, "%s", ",") > 0;
             }
         }
         else if (eGeometryFormat == OGR_CSV_GEOM_AS_YX)
         {
-            if (fpCSV) VSIFPrintfL( fpCSV, "Y%cX", chDelimiter);
-            if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", "Real,Real");
+            if (fpCSV) bOK &= VSIFPrintfL( fpCSV, "Y%cX", chDelimiter) > 0;
+            if (fpCSVT) bOK &= VSIFPrintfL( fpCSVT, "%s", "CoordY,CoordX") > 0;
             if (poFeatureDefn->GetFieldCount() > 0)
             {
-                if (fpCSV) VSIFPrintfL( fpCSV, "%c", chDelimiter );
-                if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", ",");
+                if (fpCSV) bOK &= VSIFPrintfL( fpCSV, "%c", chDelimiter ) > 0;
+                if (fpCSVT) bOK &= VSIFPrintfL( fpCSVT, "%s", ",") > 0;
             }
         }
 
         if( bHiddenWKTColumn )
         {
-            if (fpCSV) VSIFPrintfL( fpCSV, "%s", "WKT" );
-            if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", "String");
+            if (fpCSV) bOK &= VSIFPrintfL( fpCSV, "%s", poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef() ) >= 0;
+            if (fpCSVT) bOK &= VSIFPrintfL( fpCSVT, "%s", "WKT") > 0;
         }
 
         for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
@@ -1647,12 +1968,12 @@ OGRErr OGRCSVLayer::WriteHeader()
 
             if( iField > 0 || bHiddenWKTColumn )
             {
-                if (fpCSV) VSIFPrintfL( fpCSV, "%c", chDelimiter );
-                if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", ",");
+                if (fpCSV) bOK &= VSIFPrintfL( fpCSV, "%c", chDelimiter ) > 0;
+                if (fpCSVT) bOK &= VSIFPrintfL( fpCSVT, "%s", ",") > 0;
             }
 
-            pszEscaped = 
-                CPLEscapeString( poFeatureDefn->GetFieldDefn(iField)->GetNameRef(), 
+            pszEscaped =
+                CPLEscapeString( poFeatureDefn->GetFieldDefn(iField)->GetNameRef(),
                                  -1, CPLES_CSV );
 
             if (fpCSV)
@@ -1661,10 +1982,10 @@ OGRErr OGRCSVLayer::WriteHeader()
                 if( chDelimiter == ' ' && pszEscaped[0] != '"' && strchr(pszEscaped, ' ') != NULL )
                     bAddDoubleQuote = TRUE;
                 if( bAddDoubleQuote )
-                    VSIFWriteL( "\"", 1, 1, fpCSV );
-                VSIFPrintfL( fpCSV, "%s", pszEscaped );
+                    bOK &= VSIFWriteL( "\"", 1, 1, fpCSV ) > 0;
+                bOK &= VSIFPrintfL( fpCSV, "%s", pszEscaped ) >= 0;
                 if( bAddDoubleQuote )
-                    VSIFWriteL( "\"", 1, 1, fpCSV );
+                    bOK &= VSIFWriteL( "\"", 1, 1, fpCSV ) > 0;
             }
             CPLFree( pszEscaped );
 
@@ -1675,71 +1996,71 @@ OGRErr OGRCSVLayer::WriteHeader()
 
                 switch( poFeatureDefn->GetFieldDefn(iField)->GetType() )
                 {
-                  case OFTInteger:  
+                  case OFTInteger:
                   {
                       if( poFeatureDefn->GetFieldDefn(iField)->GetSubType() == OFSTBoolean )
                       {
                           nWidth = 0;
-                          VSIFPrintfL( fpCSVT, "%s", "Integer(Boolean)");
+                          bOK &= VSIFPrintfL( fpCSVT, "%s", "Integer(Boolean)") > 0;
                       }
                       else if( poFeatureDefn->GetFieldDefn(iField)->GetSubType() == OFSTInt16 )
                       {
                           nWidth = 0;
-                          VSIFPrintfL( fpCSVT, "%s", "Integer(Int16)");
+                          bOK &= VSIFPrintfL( fpCSVT, "%s", "Integer(Int16)") > 0;
                       }
                       else
-                          VSIFPrintfL( fpCSVT, "%s", "Integer");
+                          bOK &= VSIFPrintfL( fpCSVT, "%s", "Integer") > 0;
                       break;
                   }
                   case OFTInteger64:
-                      VSIFPrintfL( fpCSVT, "%s", "Integer64");
+                      bOK &= VSIFPrintfL( fpCSVT, "%s", "Integer64") > 0;
                       break;
                   case OFTReal:
                   {
                       if( poFeatureDefn->GetFieldDefn(iField)->GetSubType() == OFSTFloat32 )
                       {
                           nWidth = 0;
-                          VSIFPrintfL( fpCSVT, "%s", "Real(Float32)");
+                          bOK &= VSIFPrintfL( fpCSVT, "%s", "Real(Float32)") > 0;
                       }
                       else
-                          VSIFPrintfL( fpCSVT, "%s", "Real");
+                          bOK &= VSIFPrintfL( fpCSVT, "%s", "Real") > 0;
                       break;
                   }
-                  case OFTDate:     VSIFPrintfL( fpCSVT, "%s", "Date"); break;
-                  case OFTTime:     VSIFPrintfL( fpCSVT, "%s", "Time"); break;
-                  case OFTDateTime: VSIFPrintfL( fpCSVT, "%s", "DateTime"); break;
-                  default:          VSIFPrintfL( fpCSVT, "%s", "String"); break;
+                  case OFTDate:     bOK &= VSIFPrintfL( fpCSVT, "%s", "Date") > 0; break;
+                  case OFTTime:     bOK &= VSIFPrintfL( fpCSVT, "%s", "Time") > 0; break;
+                  case OFTDateTime: bOK &= VSIFPrintfL( fpCSVT, "%s", "DateTime") > 0; break;
+                  default:          bOK &= VSIFPrintfL( fpCSVT, "%s", "String") > 0; break;
                 }
 
                 if (nWidth != 0)
                 {
                     if (nPrecision != 0)
-                        VSIFPrintfL( fpCSVT, "(%d.%d)", nWidth, nPrecision);
+                        bOK &= VSIFPrintfL( fpCSVT, "(%d.%d)", nWidth, nPrecision) > 0;
                     else
-                        VSIFPrintfL( fpCSVT, "(%d)", nWidth);
+                        bOK &= VSIFPrintfL( fpCSVT, "(%d)", nWidth) > 0;
                 }
             }
         }
 
         /* The CSV driver will not recognize single column tables, so add */
         /* a fake second blank field */
-        if( poFeatureDefn->GetFieldCount() == 1 ||
+        if( (poFeatureDefn->GetFieldCount() == 1 && !bHiddenWKTColumn) ||
             (poFeatureDefn->GetFieldCount() == 0 && bHiddenWKTColumn) )
         {
-            if (fpCSV) VSIFPrintfL( fpCSV, "%c", chDelimiter );
+            if (fpCSV) bOK &= VSIFPrintfL( fpCSV, "%c", chDelimiter ) > 0;
         }
 
         if( bUseCRLF )
         {
-            if (fpCSV) VSIFPutcL( 13, fpCSV );
-            if (fpCSVT) VSIFPutcL( 13, fpCSVT );
+            if (fpCSV) bOK &= VSIFPutcL( 13, fpCSV ) > 0;
+            if (fpCSVT) bOK &= VSIFPutcL( 13, fpCSVT ) > 0;
         }
-        if (fpCSV) VSIFPutcL( '\n', fpCSV );
-        if (fpCSVT) VSIFPutcL( '\n', fpCSVT );
+        if (fpCSV) bOK &= VSIFPutcL( '\n', fpCSV ) > 0;
+        if (fpCSVT) bOK &= VSIFPutcL( '\n', fpCSVT ) > 0;
         if (fpCSVT) VSIFCloseL(fpCSVT);
     }
 
-    if (fpCSV == NULL) 
+    if (!bOK || fpCSV == NULL)
         return OGRERR_FAILURE;
     else
         return OGRERR_NONE;
@@ -1756,7 +2077,7 @@ OGRErr OGRCSVLayer::ICreateFeature( OGRFeature *poNewFeature )
 
     if( !bInWriteMode )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
             "The CreateFeature() operation is not permitted on a read-only CSV." );
         return OGRERR_FAILURE;
     }
@@ -1783,6 +2104,7 @@ OGRErr OGRCSVLayer::ICreateFeature( OGRFeature *poNewFeature )
     if (fpCSV == NULL)
         return OGRERR_FAILURE;
 
+    bool bRet = true;
 /* -------------------------------------------------------------------- */
 /*      Make sure we are at the end of the file.                        */
 /* -------------------------------------------------------------------- */
@@ -1792,21 +2114,21 @@ OGRErr OGRCSVLayer::ICreateFeature( OGRFeature *poNewFeature )
         {
             /* Add a newline character to the end of the file if necessary */
             bFirstFeatureAppendedDuringSession = FALSE;
-            VSIFSeekL( fpCSV, 0, SEEK_END );
-            VSIFSeekL( fpCSV, VSIFTellL(fpCSV) - 1, SEEK_SET);
+            bRet &= VSIFSeekL( fpCSV, 0, SEEK_END ) >= 0;
+            bRet &= VSIFSeekL( fpCSV, VSIFTellL(fpCSV) - 1, SEEK_SET) >= 0;
             char chLast;
-            VSIFReadL( &chLast, 1, 1, fpCSV );
-            VSIFSeekL( fpCSV, 0, SEEK_END );
+            bRet &= VSIFReadL( &chLast, 1, 1, fpCSV ) > 0;
+            bRet &= VSIFSeekL( fpCSV, 0, SEEK_END ) >= 0;
             if (chLast != '\n')
             {
                 if( bUseCRLF )
-                    VSIFPutcL( 13, fpCSV );
-                VSIFPutcL( '\n', fpCSV );
+                    bRet &= VSIFPutcL( 13, fpCSV ) != EOF;
+                bRet &= VSIFPutcL( '\n', fpCSV ) != EOF;
             }
         }
         else
         {
-            VSIFSeekL( fpCSV, 0, SEEK_END );
+            bRet &= VSIFSeekL( fpCSV, 0, SEEK_END ) >= 0;
         }
     }
 
@@ -1835,16 +2157,16 @@ OGRErr OGRCSVLayer::ICreateFeature( OGRFeature *poNewFeature )
                     *pc = chDelimiter;
                 pc ++;
             }
-            VSIFPrintfL( fpCSV, "%s", szBuffer );
+            bRet &= VSIFPrintfL( fpCSV, "%s", szBuffer ) > 0;
         }
         else
         {
-            VSIFPrintfL( fpCSV, "%c", chDelimiter );
+            bRet &= VSIFPrintfL( fpCSV, "%c", chDelimiter ) > 0;
             if (eGeometryFormat == OGR_CSV_GEOM_AS_XYZ)
-                VSIFPrintfL( fpCSV, "%c", chDelimiter );
+                bRet &= VSIFPrintfL( fpCSV, "%c", chDelimiter ) > 0;
         }
         if (poFeatureDefn->GetFieldCount() > 0)
-            VSIFPrintfL( fpCSV, "%c", chDelimiter );
+            bRet &= VSIFPrintfL( fpCSV, "%c", chDelimiter ) > 0;
     }
 
 /* -------------------------------------------------------------------- */
@@ -1856,12 +2178,12 @@ OGRErr OGRCSVLayer::ICreateFeature( OGRFeature *poNewFeature )
     {
         char *pszWKT = NULL;
         OGRGeometry     *poGeom = poNewFeature->GetGeomFieldRef(0);
-        if (poGeom && poGeom->exportToWkt(&pszWKT) == OGRERR_NONE)
+        if (poGeom && poGeom->exportToWkt(&pszWKT, wkbVariantIso) == OGRERR_NONE)
         {
             bNonEmptyLine = TRUE;
-            VSIFWriteL( "\"", 1, 1, fpCSV );
-            VSIFWriteL( pszWKT, 1, strlen(pszWKT), fpCSV );
-            VSIFWriteL( "\"", 1, 1, fpCSV );
+            bRet &= VSIFWriteL( "\"", 1, 1, fpCSV ) > 0;
+            bRet &= VSIFWriteL( pszWKT, strlen(pszWKT), 1, fpCSV ) > 0;
+            bRet &= VSIFWriteL( "\"", 1, 1, fpCSV ) > 0;
         }
         CPLFree(pszWKT);
     }
@@ -1873,16 +2195,16 @@ OGRErr OGRCSVLayer::ICreateFeature( OGRFeature *poNewFeature )
     for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     {
         char *pszEscaped;
-        
+
         if( iField > 0 || bHiddenWKTColumn )
-            VSIFPrintfL( fpCSV, "%c", chDelimiter );
+            bRet &= VSIFPrintfL( fpCSV, "%c", chDelimiter ) > 0;
 
         if (eGeometryFormat == OGR_CSV_GEOM_AS_WKT &&
             panGeomFieldIndex[iField] >= 0 )
         {
             int iGeom = panGeomFieldIndex[iField];
             OGRGeometry     *poGeom = poNewFeature->GetGeomFieldRef(iGeom);
-            if (poGeom && poGeom->exportToWkt(&pszEscaped) == OGRERR_NONE)
+            if (poGeom && poGeom->exportToWkt(&pszEscaped, wkbVariantIso) == OGRERR_NONE)
             {
                 int nLenWKT = (int)strlen(pszEscaped);
                 char* pszNew = (char*) CPLMalloc(1 + nLenWKT + 1 + 1);
@@ -1898,7 +2220,13 @@ OGRErr OGRCSVLayer::ICreateFeature( OGRFeature *poNewFeature )
         }
         else if (poFeatureDefn->GetFieldDefn(iField)->GetType() == OFTReal)
         {
-            pszEscaped = CPLStrdup(poNewFeature->GetFieldAsString(iField));
+            if( poFeatureDefn->GetFieldDefn(iField)->GetSubType() == OFSTFloat32 &&
+                poNewFeature->IsFieldSet(iField) )
+            {
+                pszEscaped = CPLStrdup(CPLSPrintf("%.8g", poNewFeature->GetFieldAsDouble(iField)));
+            }
+            else
+                pszEscaped = CPLStrdup(poNewFeature->GetFieldAsString(iField));
         }
         else
         {
@@ -1913,22 +2241,26 @@ OGRErr OGRCSVLayer::ICreateFeature( OGRFeature *poNewFeature )
         if( chDelimiter == ' ' && pszEscaped[0] != '"' && strchr(pszEscaped, ' ') != NULL )
             bAddDoubleQuote = TRUE;
         if( bAddDoubleQuote )
-            VSIFWriteL( "\"", 1, 1, fpCSV );
-        VSIFWriteL( pszEscaped, 1, nLen, fpCSV );
+            bRet &= VSIFWriteL( "\"", 1, 1, fpCSV ) > 0;
+        if( nLen )
+            bRet &= VSIFWriteL( pszEscaped, nLen, 1, fpCSV ) > 0;
         if( bAddDoubleQuote )
-            VSIFWriteL( "\"", 1, 1, fpCSV );
+            bRet &= VSIFWriteL( "\"", 1, 1, fpCSV ) > 0;
         CPLFree( pszEscaped );
     }
 
     if( (poFeatureDefn->GetFieldCount() == 1 ||
          (poFeatureDefn->GetFieldCount() == 0 && bHiddenWKTColumn)) && !bNonEmptyLine )
-        VSIFPrintfL( fpCSV, "%c", chDelimiter );
+        bRet &= VSIFPrintfL( fpCSV, "%c", chDelimiter ) > 0;
 
     if( bUseCRLF )
-        VSIFPutcL( 13, fpCSV );
-    VSIFPutcL( '\n', fpCSV );
+        bRet &= VSIFPutcL( 13, fpCSV ) != EOF;
+    bRet &= VSIFPutcL( '\n', fpCSV ) != EOF;
 
-    return OGRERR_NONE;
+    if( nTotalFeatures >= 0 )
+        nTotalFeatures ++;
+
+    return (bRet) ? OGRERR_NONE : OGRERR_FAILURE;
 }
 
 /************************************************************************/
@@ -1946,12 +2278,13 @@ void OGRCSVLayer::SetCRLF( int bNewValue )
 /************************************************************************/
 
 void OGRCSVLayer::SetWriteGeometry(OGRwkbGeometryType eGType,
-                                   OGRCSVGeometryFormat eGeometryFormat)
+                                   OGRCSVGeometryFormat eGeometryFormatIn,
+                                   const char* pszGeomCol)
 {
-    this->eGeometryFormat = eGeometryFormat;
+    this->eGeometryFormat = eGeometryFormatIn;
     if (eGeometryFormat == OGR_CSV_GEOM_AS_WKT && eGType != wkbNone )
     {
-        OGRGeomFieldDefn oGFld("WKT", eGType);
+        OGRGeomFieldDefn oGFld(pszGeomCol, eGType);
         bHiddenWKTColumn = TRUE;
         /* We don't use CreateGeomField() since we don't want to generate */
         /* a geometry field in first position, as it confuses applications */
@@ -1967,18 +2300,18 @@ void OGRCSVLayer::SetWriteGeometry(OGRwkbGeometryType eGType,
 /*                          SetCreateCSVT()                             */
 /************************************************************************/
 
-void OGRCSVLayer::SetCreateCSVT(int bCreateCSVT)
+void OGRCSVLayer::SetCreateCSVT(int bCreateCSVTIn)
 {
-    this->bCreateCSVT = bCreateCSVT;
+    this->bCreateCSVT = bCreateCSVTIn;
 }
 
 /************************************************************************/
 /*                          SetWriteBOM()                               */
 /************************************************************************/
 
-void OGRCSVLayer::SetWriteBOM(int bWriteBOM)
+void OGRCSVLayer::SetWriteBOM(int bWriteBOMIn)
 {
-    this->bWriteBOM = bWriteBOM;
+    this->bWriteBOM = bWriteBOMIn;
 }
 
 /************************************************************************/
@@ -1987,8 +2320,15 @@ void OGRCSVLayer::SetWriteBOM(int bWriteBOM)
 
 GIntBig OGRCSVLayer::GetFeatureCount( int bForce )
 {
-    if (bInWriteMode || m_poFilterGeom != NULL || m_poAttrQuery != NULL)
-        return OGRLayer::GetFeatureCount(bForce);
+    if (m_poFilterGeom != NULL || m_poAttrQuery != NULL)
+    {
+        GIntBig nRet = OGRLayer::GetFeatureCount(bForce);
+        if( nRet >= 0 )
+        {
+            nTotalFeatures = nNextFID - 1;
+        }
+        return nRet;
+    }
 
     if (nTotalFeatures >= 0)
         return nTotalFeatures;
@@ -1998,20 +2338,65 @@ GIntBig OGRCSVLayer::GetFeatureCount( int bForce )
 
     ResetReading();
 
-    char **papszTokens;
-    nTotalFeatures = 0;
-    while(TRUE)
+    if( chDelimiter == '\t' && bDontHonourStrings )
     {
-        papszTokens = GetNextLineTokens();
-        if( papszTokens == NULL )
-            break;
+        char szBuffer[4096+1];
 
-        nTotalFeatures ++;
+        nTotalFeatures = 0;
+        int bLastWasNewLine = FALSE;
+        while( true )
+        {
+            int nRead = static_cast<int>(VSIFReadL(szBuffer, 1, 4096, fpCSV));
+            szBuffer[nRead] = 0;
+            if( nTotalFeatures == 0 && szBuffer[0] != 13 && szBuffer[0] != 10 )
+                nTotalFeatures = 1;
+            for(int i=0;i<nRead;i++)
+            {
+                if( szBuffer[i] == 13 || szBuffer[i] == 10 )
+                {
+                    bLastWasNewLine = TRUE;
+                }
+                else if( bLastWasNewLine )
+                {
+                    nTotalFeatures ++;
+                    bLastWasNewLine = FALSE;
+                }
+            }
 
-        CSLDestroy(papszTokens);
+            if( nRead < 4096 )
+                break;
+        }
+    }
+    else
+    {
+        nTotalFeatures = 0;
+        while( true )
+        {
+            char **papszTokens = GetNextLineTokens();
+            if( papszTokens == NULL )
+                break;
+
+            nTotalFeatures ++;
+
+            CSLDestroy(papszTokens);
+        }
     }
 
     ResetReading();
 
     return nTotalFeatures;
 }
+
+/************************************************************************/
+/*                          SyncToDisk()                                */
+/************************************************************************/
+
+OGRErr OGRCSVLayer::SyncToDisk()
+{
+    if( bInWriteMode && fpCSV != NULL )
+    {
+        if( VSIFFlushL(fpCSV) != 0 )
+            return OGRERR_FAILURE;
+    }
+    return OGRERR_NONE;
+}
diff --git a/ogr/ogrsf_frmts/csw/ogrcswdataset.cpp b/ogr/ogrsf_frmts/csw/ogrcswdataset.cpp
index 0d5bbe3..a4ffc38 100644
--- a/ogr/ogrsf_frmts/csw/ogrcswdataset.cpp
+++ b/ogr/ogrsf_frmts/csw/ogrcswdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrcswdataset.cpp 29034 2015-04-27 11:53:19Z rouault $
+ * $Id: ogrcswdataset.cpp 32983 2016-01-14 18:32:10Z goatbar $
  *
  * Project:  CSW Translator
  * Purpose:  Implements OGRCSWDriver.
@@ -34,7 +34,7 @@
 #include "ogr_p.h"
 #include "gmlutils.h"
 
-CPL_CVSID("$Id: ogrcswdataset.cpp 29034 2015-04-27 11:53:19Z rouault $");
+CPL_CVSID("$Id: ogrcswdataset.cpp 32983 2016-01-14 18:32:10Z goatbar $");
 
 extern "C" void RegisterOGRCSW();
 
@@ -75,6 +75,8 @@ class OGRCSWLayer : public OGRLayer
     virtual int                 TestCapability( const char * ) { return FALSE; }
 
     virtual void                SetSpatialFilter( OGRGeometry * );
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+                { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
     virtual OGRErr              SetAttributeFilter( const char * );
 };
 
@@ -124,10 +126,15 @@ class OGRCSWDataSource : public OGRDataSource
 /*                           OGRCSWLayer()                              */
 /************************************************************************/
 
-OGRCSWLayer::OGRCSWLayer(OGRCSWDataSource* poDS)
+OGRCSWLayer::OGRCSWLayer(OGRCSWDataSource* poDSIn) :
+    poDS(poDSIn),
+    poFeatureDefn(new OGRFeatureDefn("records")),
+    poBaseDS(NULL),
+    poBaseLayer(NULL),
+    nPagingStartIndex(0),
+    nFeatureRead(0),
+    nFeaturesInCurrentPage(0)
 {
-    this->poDS = poDS;
-    poFeatureDefn = new OGRFeatureDefn("records");
     SetDescription(poFeatureDefn->GetName());
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType(wkbPolygon);
@@ -208,13 +215,6 @@ OGRCSWLayer::OGRCSWLayer(OGRCSWDataSource* poDS)
         poFeatureDefn->AddFieldDefn(&oField);
     }
 
-    poBaseDS = NULL;
-    poBaseLayer = NULL;
-
-    nPagingStartIndex = 0;
-    nFeatureRead = 0;
-    nFeaturesInCurrentPage = 0;
-
     poSRS->Release();
 }
 
@@ -250,7 +250,7 @@ void OGRCSWLayer::ResetReading()
 
 OGRFeature* OGRCSWLayer::GetNextFeature()
 {
-    while(TRUE)
+    while( true )
     {
         if (nFeatureRead == nPagingStartIndex + nFeaturesInCurrentPage)
         {
@@ -506,7 +506,7 @@ GDALDataset* OGRCSWLayer::FetchGetRecords()
 
     CPLHTTPDestroyResult(psResult);
 
-    GDALDataset* poBaseDS = NULL;
+    GDALDataset* l_poBaseDS = NULL;
 
     if( poDS->GetOutputSchema().size() )
     {
@@ -534,8 +534,8 @@ GDALDataset* OGRCSWLayer::FetchGetRecords()
             return NULL;
         }
 
-        poBaseDS = poDrv->Create("", 0, 0, 0, GDT_Unknown, NULL);
-        OGRLayer* poLyr = poBaseDS->CreateLayer("records");
+        l_poBaseDS = poDrv->Create("", 0, 0, 0, GDT_Unknown, NULL);
+        OGRLayer* poLyr = l_poBaseDS->CreateLayer("records");
         OGRFieldDefn oField("raw_xml", OFTString);
         poLyr->CreateField(&oField);
         for( CPLXMLNode* psIter = psSearchResults->psChild; psIter; psIter = psIter->psNext )
@@ -592,12 +592,12 @@ GDALDataset* OGRCSWLayer::FetchGetRecords()
                     CPLString osSRS = CPLGetXMLValue(psBBox, "crs", "");
                     OGRGeometry* poGeom = GML2OGRGeometry_XMLNode( psBBox,
                                                           FALSE,
-                                                          0, 0, FALSE, TRUE,
-                                                          FALSE );
-                    int bLatLongOrder = TRUE;
+                                                          0, 0, false, true,
+                                                          false );
+                    bool bLatLongOrder = true;
                     if( osSRS.size() )
                         bLatLongOrder = GML_IsSRSLatLongOrder(osSRS);
-                    if( bLatLongOrder && CSLTestBoolean(
+                    if( bLatLongOrder && CPLTestBool(
                             CPLGetConfigOption("GML_INVERT_AXIS_ORDER_IF_LAT_LONG", "YES")) )
                         poGeom->swapXY();
                     poFeature->SetGeometryDirectly(poGeom);
@@ -606,7 +606,7 @@ GDALDataset* OGRCSWLayer::FetchGetRecords()
                 psIter->psNext = psNext;
 
                 poFeature->SetField(0, pszXML);
-                poLyr->CreateFeature(poFeature);
+                CPL_IGNORE_RET_VAL(poLyr->CreateFeature(poFeature));
                 CPLFree(pszXML);
                 delete poFeature;
             }
@@ -615,8 +615,8 @@ GDALDataset* OGRCSWLayer::FetchGetRecords()
     }
     else
     {
-        poBaseDS = (GDALDataset*) OGROpen(osTmpFileName, FALSE, NULL);
-        if (poBaseDS == NULL)
+        l_poBaseDS = (GDALDataset*) OGROpen(osTmpFileName, FALSE, NULL);
+        if (l_poBaseDS == NULL)
         {
             if( strstr((const char*)pabyData, "<csw:GetRecordsResponse") == NULL &&
                 strstr((const char*)pabyData, "<GetRecordsResponse") == NULL )
@@ -630,14 +630,14 @@ GDALDataset* OGRCSWLayer::FetchGetRecords()
         }
     }
 
-    OGRLayer* poLayer = poBaseDS->GetLayer(0);
+    OGRLayer* poLayer = l_poBaseDS->GetLayer(0);
     if (poLayer == NULL)
     {
-        GDALClose(poBaseDS);
+        GDALClose(l_poBaseDS);
         return NULL;
     }
 
-    return poBaseDS;
+    return l_poBaseDS;
 }
 
 /************************************************************************/
@@ -734,7 +734,7 @@ OGRErr OGRCSWLayer::SetAttributeFilter( const char * pszFilter )
 
     delete m_poAttrQuery;
     m_poAttrQuery = NULL;
-    
+
     if( pszFilter != NULL )
     {
         m_poAttrQuery = new OGRFeatureQuery();
@@ -807,7 +807,7 @@ void OGRCSWLayer::BuildQuery()
             osQuery += "<gml:Envelope srsName=\"urn:ogc:def:crs:EPSG::4326\">";
             OGREnvelope sEnvelope;
             m_poFilterGeom->getEnvelope(&sEnvelope);
-            if( CSLTestBoolean(
+            if( CPLTestBool(
                     CPLGetConfigOption("GML_INVERT_AXIS_ORDER_IF_LAT_LONG", "YES")) )
             {
                 osQuery += CPLSPrintf("<gml:lowerCorner>%.16g %.16g</gml:lowerCorner>", sEnvelope.MinY, sEnvelope.MinX);
@@ -835,13 +835,12 @@ void OGRCSWLayer::BuildQuery()
 /*                          OGRCSWDataSource()                          */
 /************************************************************************/
 
-OGRCSWDataSource::OGRCSWDataSource()
-{
-    pszName = NULL;
-    poLayer = NULL;
-    bFullExtentRecordsAsNonSpatial = FALSE;
-    nMaxRecords = 500;
-}
+OGRCSWDataSource::OGRCSWDataSource() :
+    pszName(NULL),
+    nMaxRecords(500),
+    poLayer(NULL),
+    bFullExtentRecordsAsNonSpatial(FALSE)
+{}
 
 /************************************************************************/
 /*                         ~OGRCSWDataSource()                          */
@@ -895,13 +894,13 @@ CPLHTTPResult* OGRCSWDataSource::SendGetCapabilities()
 /************************************************************************/
 
 int OGRCSWDataSource::Open( const char * pszFilename,
-                            char** papszOpenOptions )
+                            char** papszOpenOptionsIn )
 {
-    const char* pszBaseURL = CSLFetchNameValue(papszOpenOptions, "URL");
+    const char* pszBaseURL = CSLFetchNameValue(papszOpenOptionsIn, "URL");
     if( pszBaseURL == NULL )
     {
         pszBaseURL = pszFilename;
-        if (EQUALN(pszFilename, "CSW:", 4))
+        if (STARTS_WITH_CI(pszFilename, "CSW:"))
             pszBaseURL += 4;
         if( pszBaseURL[0] == '\0' )
         {
@@ -910,27 +909,27 @@ int OGRCSWDataSource::Open( const char * pszFilename,
         }
     }
     osBaseURL = pszBaseURL;
-    osElementSetName = CSLFetchNameValueDef(papszOpenOptions, "ELEMENTSETNAME",
+    osElementSetName = CSLFetchNameValueDef(papszOpenOptionsIn, "ELEMENTSETNAME",
                                             "full");
-    bFullExtentRecordsAsNonSpatial = CSLFetchBoolean(papszOpenOptions,
+    bFullExtentRecordsAsNonSpatial = CSLFetchBoolean(papszOpenOptionsIn,
                                                      "FULL_EXTENT_RECORDS_AS_NON_SPATIAL",
                                                      FALSE);
-    osOutputSchema = CSLFetchNameValueDef(papszOpenOptions, "OUTPUT_SCHEMA", "");
+    osOutputSchema = CSLFetchNameValueDef(papszOpenOptionsIn, "OUTPUT_SCHEMA", "");
     if( EQUAL(osOutputSchema, "gmd") )
         osOutputSchema = "http://www.isotc211.org/2005/gmd";
     else if( EQUAL(osOutputSchema, "csw") )
         osOutputSchema = "http://www.opengis.net/cat/csw/2.0.2";
-    nMaxRecords = atoi(CSLFetchNameValueDef(papszOpenOptions, "MAX_RECORDS", "500"));
+    nMaxRecords = atoi(CSLFetchNameValueDef(papszOpenOptionsIn, "MAX_RECORDS", "500"));
 
-    if (strncmp(osBaseURL, "http://", 7) != 0 &&
-        strncmp(osBaseURL, "https://", 8) != 0 &&
-        strncmp(osBaseURL, "/vsimem/", strlen("/vsimem/")) != 0)
+    if (!STARTS_WITH(osBaseURL, "http://") &&
+        !STARTS_WITH(osBaseURL, "https://") &&
+        !STARTS_WITH(osBaseURL, "/vsimem/"))
         return FALSE;
 
     CPLHTTPResult* psResult = SendGetCapabilities();
     if( psResult == NULL )
         return FALSE;
-    
+
     CPLXMLNode* psXML = CPLParseXMLString( (const char*) psResult->pabyData );
     if (psXML == NULL)
     {
@@ -1016,7 +1015,7 @@ CPLHTTPResult* OGRCSWDataSource::HTTPFetch( const char* pszURL, const char* pszP
 static int OGRCSWDriverIdentify( GDALOpenInfo* poOpenInfo )
 
 {
-    return EQUALN(poOpenInfo->pszFilename, "CSW:", 4);
+    return STARTS_WITH_CI(poOpenInfo->pszFilename, "CSW:");
 }
 
 /************************************************************************/
@@ -1048,22 +1047,20 @@ static GDALDataset *OGRCSWDriverOpen( GDALOpenInfo* poOpenInfo )
 void RegisterOGRCSW()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "CSW" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "CSW" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver  *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "CSW" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "OGC CSW (Catalog  Service for the Web)" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_csw.html" );
+    poDriver->SetDescription( "CSW" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "OGC CSW (Catalog  Service for the Web)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_csw.html" );
 
-        poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, "CSW:" );
+    poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, "CSW:" );
 
-        poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
 "<OpenOptionList>"
 "  <Option name='URL' type='string' description='URL to the CSW server endpoint' required='true'/>"
 "  <Option name='ELEMENTSETNAME' type='string-select' description='Level of details of properties' default='full'>"
@@ -1076,10 +1073,9 @@ void RegisterOGRCSW()
 "  <Option name='MAX_RECORDS' type='int' description='Maximum number of records to retrieve in a single time' default='500'/>"
 "</OpenOptionList>" );
 
-        poDriver->pfnIdentify = OGRCSWDriverIdentify;
-        poDriver->pfnOpen = OGRCSWDriverOpen;
+    poDriver->pfnIdentify = OGRCSWDriverIdentify;
+    poDriver->pfnOpen = OGRCSWDriverOpen;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
 
diff --git a/ogr/ogrsf_frmts/db2/GNUmakefile b/ogr/ogrsf_frmts/db2/GNUmakefile
new file mode 100644
index 0000000..6a8ddaa
--- /dev/null
+++ b/ogr/ogrsf_frmts/db2/GNUmakefile
@@ -0,0 +1,10 @@
+include ../../../GDALmake.opt
+
+OBJ	=	ogrdb2cli.o gdaldb2rasterband.o ogrdb2datasourcemd.o ogrdb2driver.o ogrdb2datasource.o ogrdb2layer.o ogrdb2tablelayer.o ogrdb2selectlayer.o
+
+CPPFLAGS	:=	 -I.. -I../.. -I../../../frmts/mem $(CPPFLAGS)
+
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
diff --git a/ogr/ogrsf_frmts/db2/drv_db2.html b/ogr/ogrsf_frmts/db2/drv_db2.html
new file mode 100644
index 0000000..597f495
--- /dev/null
+++ b/ogr/ogrsf_frmts/db2/drv_db2.html
@@ -0,0 +1,119 @@
+<html>
+<head>
+<title>DB2 Spatial</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>DB2 Spatial</h1>
+
+<p>This driver implements support for access to spatial tables in
+the IBM DB2 for Linux, Unix and Windows (DB2 LUW) and the IBM DB2
+for z/OS relational databases using the default ODBC support
+incorporated into GDAL.
+</p>
+<p>
+The documentation for the DB2 spatial features can be found online
+for
+<a href="http://www-01.ibm.com/support/knowledgecenter/SSEPEK_11.0.0/com.ibm.db2z11.doc.spatl/src/spatl/dasz_spatl.dita?lang=en">
+DB2 for z/OS</a>
+and
+<a href="http://www-01.ibm.com/support/knowledgecenter/SSEPGG_10.5.0/com.ibm.db2.luw.spatial.topics.doc/doc/db2sb03.html">
+DB2 LUW</a>
+<p>
+This driver is currently supported only in the Windows environment.
+</p>
+<h2>Connecting to a database</h2>
+
+To connect to a DB2 datasource, use a connection string specifying the database name,
+with additional parameters as necessary. The connection strings must be prefixed
+    with '<i>DB2ODBC:</i>'.<br>
+You can specify either a DSN that has been registered or use parameters that
+specify the host, port and protocol.
+<blockquote><pre>
+DB2ODBC:database=dbname;DSN=datasourcename</pre></blockquote>
+or
+<blockquote><pre>
+DB2ODBC:database=dbname;DRIVER={IBM DB2 ODBC DRIVER};Hostname=hostipaddr;PROTOCOL=TCPIP;port=db2port;UID=myuserid;PWD=mypw</pre></blockquote>
+The following custom parameters can also be used in the following syntax:
+
+<ul>
+
+<li> <b>Tables=schema1.table1(geometry column1),schema2.table2(geometry column2)</b>:
+    By using this parameter you can specify the subset of the layers to be used by the driver. If this parameter is not set,
+	the layers are retrieved from the DB2GSE.ST_GEOMETRY_COLUMNS metadata view.
+	You can omit specifying the schema and the geometry column portions of the syntax. </li>
+
+</ul>
+    <p>The parameter names are not case sensitive in the connection strings.</p>
+    <p>Specifying the <b>
+    Database</b> parameter is required by the driver in order to select the proper database.</p>
+
+<h2>Layers</h2>
+
+<p>By default the DB2 driver will only look for layers that are registered in the <i>DB2GSE.ST_GEOMETRY_COLUMNS</i> metadata table.
+
+<h2>SQL statements</h2>
+
+<p>The DB2 driver passes SQL statements directly to DB2 by default,
+rather than evaluating them internally when using the ExecuteSQL() call on the
+OGRDataSource, or the -sql command option to ogr2ogr.  Attribute query
+expressions are also passed directly through to DB2.
+It's also possible to request the OGR DB2 driver to handle SQL commands
+with the <a href="ogr_sql.html">OGR SQL</a> engine, by passing <strong>"OGRSQL"</strong>
+string to the ExecuteSQL() method, as the name of the SQL dialect.</p>
+
+<p>The DB2 driver in OGR supports the OGRLayer::StartTransaction(),
+OGRLayer::CommitTransaction() and OGRLayer::RollbackTransaction()
+calls in the normal SQL sense.</p>
+
+<h2>Creation Issues</h2>
+
+<p>This driver doesn't support creating new databases.
+Use the DB2 command line or tools like IBM Data Studio to create the database.
+It does allow creation of new layers within an existing database.</P>
+
+<h3>Layer Creation Options</h3>
+
+<ul>
+
+<li> <b>OVERWRITE</b>: This may be "YES" to force an existing layer of the
+desired name to be destroyed before creating the requested layer.</li>
+<li> <b>LAUNDER</b>: This may be "YES" to force new fields created on this
+layer to have their field names "laundered" into a form more compatible with
+DB2.  This converts to lower case and converts some special characters
+like "-" and "#" to "_".  If "NO" exact names are preserved.
+The default value is "YES".  If enabled the table (layer) name will also be laundered.</li>
+<li> <b>PRECISION</b>: This may be "YES" to force new fields created on this
+layer to try and represent the width and precision information, if available
+using numeric(width,precision) or char(width) types.  If "NO" then the types
+float, int and varchar will be used instead.  The default is "YES".
+<li> <b>DIM={2,3}</b>: Control the dimension of the layer.  Defaults to 2.</li>
+<li> <b>GEOM_NAME</b>: Set the name of geometry column in the new table.  If
+omitted it defaults to <i>ogr_geometry</i>.</li>
+<li> <b>SCHEMA</b>: Set name of schema for new table.
+The default schema is that of the userid used to connect to the database</li>
+<li> <b>SRID</b>: Set the spatial reference id of the new table explicitly.
+The corresponding entry should already be added to the spatial_ref_sys metadata table. If this parameter is not set the SRID is derived from the authority code of source layer SRS.</li>
+</ul>
+
+<h3>Spatial Index Creation</h3>
+
+<p>By default the DB2 driver doesn't add spatial indexes to the tables during the layer creation.
+Spatial indexes should be created using the DB2 CREATE INDEX command.
+</p>
+
+
+
+<h2>Examples</h2>
+
+<p>Creating a layer from an OGR data source</p>
+<blockquote><pre>
+ogr2ogr -overwrite  DB2ODBC:database=sample;DSN=sampDSN zipcodes.shp</pre></blockquote>
+
+<p>Connecting to a layer and dump the contents</p>
+<blockquote><pre>
+ogrinfo -al DB2ODBC:database=sample;DSN=sampDSN;tables=zipcodes</pre></blockquote>
+
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/db2/drv_db2_raster.html b/ogr/ogrsf_frmts/db2/drv_db2_raster.html
new file mode 100644
index 0000000..6d93f0f
--- /dev/null
+++ b/ogr/ogrsf_frmts/db2/drv_db2_raster.html
@@ -0,0 +1,394 @@
+<!DOCTYPE HTML SYSTEM>
+<html>
+<head>
+<title>DB2 raster</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h3>Note</h3>
+
+<p>The DB2 driver is based largely on the source code for the
+OGR/DB2 GeoPackage (GPKG) driver, replaceing SQLITE functionality with
+corresponding DB2 functionality. Appreciation is expressed for the
+major development required to produce the GeoPackage driver which
+dramatically reduced the effort to produce the DB2 driver.
+At some point it may be worthwhile to explore whether refactoring of
+the class structure to share common functionality is practical.</p>
+<p>
+The DB2 driver largely implements the GeoPackage standard, with the main
+difference that the "gpkg_" prefix is replaced with "gpkg." in the
+DB2 table name, assigning them to a distinct database schema.
+</p>
+<p>
+The documentation below is largely copied from the drv_geopackage_raster.html
+documentation.
+References to the GeoPackage standard have been left as such.
+References to the implementation have been changed to DB2.
+In some cases it isn't clear whether we should refer to
+"DB2 tiles" or "GeoPackage tiles".
+</p>
+
+<h1>DB2 raster</h1>
+
+<p>Starting with GDAL 2.0, this driver implements full read/creation/update of
+tables containing raster tiles in the
+<a href="http://www.geopackage.org/spec/">OGC GeoPackage format standard</a>.
+The GeoPackage standard uses a SQLite database file as a generic container, and the standard defines:
+</p>
+<ul>
+  <li>Expected metadata tables (<code>gpkg.contents</code>,
+     <code>gpkg.spatial_ref_sys</code>, <code>gpkg.tile_matrix</code>,
+     <code>gpkg.tile_matrix_set</code>, ...)</li>
+  <li>Tile format encoding (PNG and JPEG for base specification, WebP as extension) and tiling conventions</li>
+  <li>Naming and conventions for extensions</li>
+</ul>
+<p>This driver reads and writes DB2 tables in the DB2 database, so it must be
+run by a user with create authority on the database it is working with.</p>
+
+<p>The driver can also handle DB2 vectors. See
+<a href="drv_DB2.html">DB2 vector</a> documentation page</p>
+
+<p>Various kind of input datasets can be converted to DB2 raster :
+<ul>
+<li>Single band grey level</li>
+<li>Single band with R,G,B or R,G,B,A color table</li>
+<li>Two bands: first band with grey level, second band with alpha channel</li>
+<li>Three bands: Red, Green, Blue</li>
+<li>Four band: Red, Green, Blue, Alpha</li>
+</ul>
+DB2 rasters only support Byte data type.
+
+<p>
+All raster extensions standardized by the GeoPackage specification are supported in read and creation :
+</p>
+<ul>
+<li><i>gpkg.webp</i>: when storing WebP tiles, provided that GDAL is compiled against libwebp.</li>
+<li><i>gpkg.zoom_other</i>: when resolution of consecutive zoom levels does not vary with a factor of 2.</li>
+</ul>
+
+<h2>Opening options</h2>
+
+<p>By default, the driver will expose a DB2 dataset as a four band (Red,Green,
+Blue,Alpha) dataset, which gives the maximum compatibility with the various encodings of
+tiles that can be stored. It is possible to specify an explicit number of bands
+with the BAND_COUNT opening option.</p>
+
+<p>The driver will use the geographic/projected extent indicated in the
+<a href="http://www.geopackage.org/spec/#_contents"><i>gpkg.contents</i></a> table,
+and do necessary clipping, if needed, to respect
+that extent. However that information being optional, if omitted, the driver
+will use the extent provided by the
+<a href="http://www.geopackage.org/spec/#_tile_matrix_set"><i>gpkg.tile_matrix_set</i></a>,
+which covers the extent at all zoom levels. The user can also specify the USE_TILE_EXTENT=YES
+open option to use the actual extent of tiles at the maximum zoom level. Or
+it can specify any of MINX/MINY/MAXX/MAXY to have a custom extent.<p>
+
+The following open options are available:
+<ul>
+<li><b>TABLE</b>=table_name: Name of the table containing the tiles (called
+<a href="http://www.geopackage.org/spec/#tiles_user_tables">"Tile Pyramid User Data Table"</a>
+in the GeoPackage specification language). If
+the DB2 dataset only contains one table, this option is not necessary.
+Otherwise, it is required.</li>
+<li><b>ZOOM_LEVEL</b>=value: Integer value between 0 and the maximum filled in
+the <i>gpkg.tile_matrix</i> table. By default, the driver will select the maximum
+zoom level, such as at least one tile at that zoom level is found in the raster table.</li>
+<li><b>BAND_COUNT</b>=1/2/3/4: Number of bands of the dataset exposed after opening.
+Some conversions will be done when possible and implemented, but this might fail
+in some cases, depending on the BAND_COUNT value and the number of bands of the tile.
+Defaults to 4 (which is the always safe value).</li>
+<li><b>MINX</b>=value: Minimum longitude/easting of the area of interest.</li>
+<li><b>MINY</b>=value: Minimum latitude/northing of the area of interest.</li>
+<li><b>MAXX</b>=value: Maximum longitude/easting of the area of interest.</li>
+<li><b>MAXY</b>=value: Maximum latitude/northing of the area of interest.</li>
+<li><b>USE_TILE_EXTENT</b>=YES/NO: Whether to use the extent of actual existing
+tiles at the zoom level of the full resolution dataset. Defaults to NO.</li>
+<li><b>TILE_FORMAT</b>=PNG_JPEG/PNG/PNG8/JPEG/WEBP: Format used to store tiles. See
+<a href="#tile_format">Tile format</a> section. Only used in update mode. Defaults to PNG_JPEG.</li>
+<li><b>QUALITY</b>=1-100: Quality setting for JPEG and WEBP compression. Only used in update mode. Default to 75.</li>
+<li><b>ZLEVEL</b>=1-9: DEFLATE compression level for PNG tiles. Only used in update mode. Default to 6.</li>
+<li><b>DITHER</b>=YES/NO: Whether to use Floyd-Steinberg dithering (for TILE_FORMAT=PNG8).
+Only used in update mode. Defaults to NO.</li>
+</ul>
+
+Note: open options are typically specified with "-oo name=value" syntax in
+most GDAL utilities, or with the GDALOpenEx() API call.
+
+<h2>Creation issues</h2>
+
+<p>Depending of the number of bands of the input dataset and the tile format
+selected, the driver will do the necessary conversions to be compatible with the
+tile format.</p>
+
+<p>To add several tile tables to a DB2 dataset (seen as GDAL subdatasets),
+or to add a tile table to an existing vector-only DB2, the generic
+APPEND_SUBDATASET=YES creation option must be provided.</p>
+
+<p>Fully transparent tiles will not be written to the database, as allowed by
+the format.</p>
+
+<p>The driver implements the Create() and IWriteBlock() methods, so that arbitrary
+writing of raster blocks is possible, enabling the direct use of DB2 as
+the output dataset of utilities such as gdalwarp.</p>
+
+<p>On creation, raster blocks can be written only if the geotransformation
+matrix has been set with SetGeoTransform() This is effectively needed to determine
+the zoom level of the full resolution dataset based on the pixel resolution, dataset
+and tile dimensions.</p>
+
+<p>Technical/implementation note: when a dataset is opened with a non-default area of interest
+(i.e. use of MINX,MINY,MAXX,MAXY or USE_TILE_EXTENT open option), or when creating/
+opening a dataset with a non-custom tiling scheme, it is possible that GDAL blocks
+do not exactly match a single DB2 tile. In which case, each GDAL
+block will overlap four DB2 tiles. This is easily handled on the read side,
+but on creation/update side, such configuration could cause numerous decompression/
+recompression of tiles to be done, which might cause unnecessary quality loss when using
+lossy compression (JPEG, WebP). To avoid that, the driver will create a temporary
+database next to the main DB2 table to store partial DB2 tiles in a
+lossless (and uncompressed) way. Once a tile has received data for its four quadrants
+and for all the bands (or the dataset is closed or explicitly flushed with FlushCache()),
+those uncompressed tiles are definitely transferred to the DB2 table with
+the appropriate compression. All of this is transparent to the user of GDAL API/utilities</p>
+
+<h3><a id="tile_formats">Tile formats</a></h3>
+
+<p>DB2 can store tiles in different formats, PNG and/or JPEG for the baseline
+specification, and WebP for extended DB2. Support for those tile formats
+depend if the underlying drivers are available in GDAL, which is generally the
+case for PNG and JPEG, but not necessarily for WebP since it requires GDAL to
+be compiled against the optional libwebp.<p>
+
+<p>By default, GDAL will use a mix of PNG and JPEG tiles. PNG tiles will be used
+to store tiles that are not completely opaque, either because input dataset has
+an alpha channel with non fully opaque content, or because tiles are partial due
+to clipping at the right or bottom edges of the raster, or when a dataset is opened
+with a non-default area of interest, or with a non-custom tiling scheme. On the
+contrary, for fully opaque tiles, JPEG format will be used.</p>
+
+<p>It is possible to select one unique tile format by setting the creation/open
+option TILE_FORMAT to one of PNG, JPEG or WEBP. When using JPEG, the alpha channel
+will not be stored. When using WebP, the
+<a href="http://www.geopackage.org/spec/#extension_tiles_webp"><i>gpkg.webp</i></a>
+extension will be registered. The lossy compression of WebP is used.
+Note that a recent enough libwebp
+(>=0.1.4) must be used to support alpha channel in WebP tiles.</p>
+
+<p>PNG8 can be selected to use 8-bit PNG with a color table up to 256 colors.
+On creation, an optimized color table is computed for each tile. The DITHER
+option can be set to YES to use Floyd/Steinberg dithering algorithm, which
+spreads the quantization error on neighbouring pixels for better rendering (note
+however than when zooming in, this can cause non desirable visual artifacts).
+Setting it to YES will generally cause less effective compression.
+Note that at that time, such an 8-bit PNG formulation is only used for fully opaque tiles,
+as the median-cut algorithm currently implemented to compute the optimal color
+table does not support alpha channel (even if PNG8 format would potentially allow
+color table with transparency). So when selecting PNG8, non fully opaque tiles
+will be stored as 32-bit PNG.</p>
+
+<h3><a id="tiling_schemes">Tiling schemes</a></h3>
+
+<p>
+By default, conversion to DB2 will create a custom tiling scheme, such
+that the input dataset can be losslessly converted, both at the pixel and
+georeferencing level (if using a lossless tile format such as PNG). That
+tiling scheme is such that its origin (<i>min_x</i>, <i>max_y</i>) in the
+<a href="http://www.geopackage.org/spec/#_tile_matrix_set"><i>gpkg.tile_matrix_set</i></a>
+table perfectly matches the top left corner of the dataset, and the selected
+resolution (<i>pixel_x_size</i>, <i>pixel_y_size</i>) at the computed maximum zoom_level of the
+<a href="http://www.geopackage.org/spec/#_tile_matrix"><i>gpkg.tile_matrix</i></a> table will
+match the pixel width and height of the raster.
+</p>
+<p>However to ease interoperability with other implementations, and enable use
+of DB2 with tile servicing software, it is possible to select a predefined
+tiling scheme that has world coverage. The available tiling schemes are :</p>
+<ul>
+<li><i>GoogleCRS84Quad</i>, as described in
+<a href="http://portal.opengeospatial.org/files/?artifact_id=35326">OGC 07-057r7
+WMTS 1.0</a> specification, Annex E.3. That tiling schemes consists of a single
+256x256 tile at its zoom level 0, in EPSG:4326 CRS, with extent in longitude and
+latitude in the range [-180,180]. Consequently, at zoom level 0, 64 lines are
+unused at the top and bottom of that tile. This may cause issues with some
+implementations of the specification, and there are some ambiguities about the
+exact definition of this tiling scheme. Using InspireCRS84Quad/PseudoTMS_GlobalGeodetic
+instead is therefore recommended.</li>
+<li><i>GoogleMapsCompatible</i>, as described in WMTS 1.0 specification, Annex E.4.
+That tiling schemes consists of a single 256x256 tile at its zoom level 0,
+in EPSG:3857 CRS, with extent in easting and northing in the range
+[-20037508.34,20037508.34].</li>
+<li><i>InspireCRS84Quad</i>, as described in
+<a href="http://inspire.ec.europa.eu/documents/Network_Services/TechnicalGuidance_ViewServices_v3.0.pdf">
+<i>Inspire View Services</i></a>.
+That tiling schemes consists of two 256x256 tiles at its zoom level 0, in
+EPSG:4326 CRS, with extent in longitude in the range [-180,180] and in latitude
+in the range [-90,90].</li>
+<li><i>PseudoTMS_GlobalGeodetic</i>, based on the
+<a href="http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification#global-geodetic">
+<i>global-geodetic</i></a> profile of OSGeo TMS (Tile Map Service) specification.
+This has exactly the same definition as <i>InspireCRS84Quad</i> tiling scheme. Note
+however that full interoperability with TMS is not
+possible due to the origin of numbering of tiles being the top left corner in
+DB2 (consistently with WMTS convention), whereas TMS uses the bottom left
+corner as origin.</li>
+<li><i>PseudoTMS_GlobalMercator</i>, based on the
+<a href="http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification#global-mercator">
+<i>global-mercator</i></a> profile of OSGeo TMS (Tile Map Service) specification.
+That tiling schemes consists of four 256x256 tiles at its zoom level 0,
+in EPSG:3857 CRS, with extent extent in easting and northing in the range
+[-20037508.34,20037508.34]. The same remark as with PseudoTMS_GlobalGeodetic applies
+regarding interoperability with TMS.</li>
+</ul>
+
+<p>In all the above tiling schemes, consecutive zoom levels defer by a resolution
+of a factor of two.</p>
+
+<h3>Creation options</h3>
+
+<p>The following creation options are available:</p>
+
+<ul>
+<li><b>RASTER_TABLE</b>=string. Name of tile user table. By default, based on
+the source filename.</li>
+<li><b>APPEND_SUBDATASET</b>=YES/NO: If set to YES, an existing DB2 table
+will not be priorly destroyed, such as to be able to add new content to it. Defaults to NO.</li>
+<li><b>RASTER_IDENTIFIER</b>=string. Human-readable identifier (e.g. short name), put
+in the <i>identifier</i> column of the <i>gpkg.contents</i> table.</li>
+<li><b>RASTER_DESCRIPTION</b>=string. Human-readable description, put
+in the <i>description</i> column of the <i>gpkg.contents</i> table.</li>
+<li><b>BLOCKSIZE</b>=integer. Block size in width and height in pixels.
+Defaults to 256. Maximum supported is 4096. Should not be set when using a non-custom TILING_SCHEME.</li>
+<li><b>BLOCKXSIZE</b>=integer. Block width in pixels.
+Defaults to 256. Maximum supported is 4096.</li>
+<li><b>BLOCKYSIZE</b>=integer. Block height in pixels.
+Defaults to 256. Maximum supported is 4096.</li>
+<li><b>TILE_FORMAT</b>=PNG_JPEG/PNG/PNG8/JPEG/WEBP: Format used to store tiles. See
+<a href="#tile_formats">Tile formats</a> section. Defaults to PNG_JPEG.</li>
+<li><b>QUALITY</b>=1-100: Quality setting for JPEG and WEBP compression. Default to 75.</li>
+<li><b>ZLEVEL</b>=1-9: DEFLATE compression level for PNG tiles. Default to 6.</li>
+<li><b>DITHER</b>=YES/NO: Whether to use Floyd-Steinberg dithering (for TILE_FORMAT=PNG8).
+Defaults to NO.</li>
+<li><b>TILING_SCHEME</b>=CUSTOM/GoogleCRS84Quad/GoogleMapsCompatible/InspireCRS84Quad/PseudoTMS_GlobalGeodetic/PseudoTMS_GlobalMercator.
+See <a href="#tiling_schemes">Tiling schemes</a> section. Defaults to CUSTOM.</li>
+<li><b>ZOOM_LEVEL_STRATEGY</b>=AUTO/LOWER/UPPER. Strategy to determine zoom level.
+Only used for TILING_SCHEME is different from CUSTOM. LOWER will select the
+zoom level immediately below the theoretical computed non-integral zoom level,
+leading to subsampling. On the contrary, UPPER will select the immediately above
+zoom level, leading to oversampling. Defaults to AUTO which selects the closest
+zoom level.</li>
+<li><b>RESAMPLING</b>=NEAREST/BILINEAR/CUBIC/CUBICSPLINE/LANCZOS/MODE/AVERAGE.
+Resampling algorithm. Only used for TILING_SCHEME is different from CUSTOM. Defaults
+to BILINEAR.</li>
+</ul>
+
+<h2>Overviews</h2>
+
+<p>gdaladdo / BuildOverviews() can be used to compute overviews. Power-of-two
+overview factors (2,4,8,16,...) should be favored to be conformant with the
+baseline GeoPackage specification. Use of other overview factors will work with the GDAL
+driver, and cause the <a href="http://www.geopackage.org/spec/#extension_zoom_other_intervals">
+<i>gpkg.zoom_other</i></a> extension to be registered, but
+that could potentially cause interoperability problems with other
+implementations that do not support that extension.</p>
+
+<p>Overviews can also be cleared with the -clean option of gdaladdo (or
+BuildOverviews() with nOverviews=0)</p>
+
+<h2>Metadata</h2>
+
+<p>GDAL uses the standardized <a href="http://www.geopackage.org/spec/#_metadata_table">
+<code>gpkg.metadata</code></a> and <a href="http://www.geopackage.org/spec/#_metadata_reference_table">
+<code>gpkg.metadata_reference</code></a> tables to read and write metadata.</p>
+
+<p>GDAL metadata, from the default metadata domain and possibly other metadata
+domains, is serialized in a single XML document, conformant with the format used
+in GDAL PAM (Persistent Auxiliary Metadata) .aux.xml files, and registered with
+md_scope=dataset and md_standard_uri=http://gdal.org in gpkg.metadata. In
+gpkg.metadata_reference, this entry is referenced with a reference_scope=table and
+table_name={name of the raster table}</p>
+
+<p>It is possible to read and write metadata that applies to the global DB2,
+and not only to the raster table, by using the <i>GEOPACKAGE</i> metadata
+domain.</p>
+
+<p>Metadata not originating from GDAL can be read by the driver and will be
+exposed as metadata items with keys of the form gpkg.METADATA_ITEM_XXX and
+values the content of the <i>metadata</i> columns of the gpkg.metadata table.
+Update of such metadata is not currently supported through GDAL interfaces (
+although it can be through direct SQL commands).</p>
+
+<p>The specific DESCRIPTION and IDENTIFIER metadata item of the default metadata
+domain can be used in read/write to read from/update the corresponding columns of
+the gpkg.contents table.</p>
+
+<h2>Examples</h2>
+
+<ul>
+<li>
+Simple translation of a GeoTIFF into DB2.  The table 'byte' will
+be created with the tiles.
+<pre>
+% gdal_translate -of DB2ODBC byte.tif DB2ODBC:database=sample;DSN=SAMPLE
+</pre>
+</li>
+
+<li>
+Translation of a GeoTIFF into DB2 using WebP tiles
+<pre>
+% gdal_translate -of DB2ODBC byte.tif DB2ODBC:database=sample;DSN=SAMPLE -co TILE_FORMAT=WEBP
+</pre>
+</li>
+
+<li>
+Translation of a GeoTIFF into DB2 using GoogleMapsCompatible tiling scheme
+(with reprojection and resampling if needed)
+<pre>
+% gdal_translate -of DB2ODBC byte.tif DB2ODBC:database=sample;DSN=SAMPLE -co TILING_SCHEME=GoogleMapsCompatible
+</pre>
+</li>
+
+<li>
+Building of overviews of an existing DB2
+<pre>
+% gdaladdo -oo RASTER_TABLE=world -r cubic DB2ODBC:database=sample;DSN=SAMPLE 2 4 8 16 32 64
+</pre>
+</li>
+
+<li>
+Addition of a new subdataset to an existing DB2, and choose a non
+default name for the raster table.
+<pre>
+% gdal_translate -of DB2ODBC new.tif DB2ODBC:database=sample;DSN=SAMPLE -co APPEND_SUBDATASET=YES -co RASTER_TABLE=new_table
+</pre>
+</li>
+
+<li>
+Reprojection of an input dataset to DB2
+<pre>
+% gdalwarp -of DB2ODBC -co RASTER_TABLE=new_table in.tif DB2ODBC:database=sample;DSN=SAMPLE -t_srs EPSG:3857
+</pre>
+</li>
+
+<li>
+Open a specific raster table in a DB2
+<pre>
+% gdalinfo DB2ODBC:database=sample;DSN=SAMPLE -oo TABLE=a_table
+</pre>
+</li>
+
+</ul>
+
+<h3>See Also</h3>
+
+<ul>
+<li> <a href="drv_DB2.html">DB2 vector</a> documentation page</li>
+<li> <a href="frmt_various.html#PNG">PNG driver</a> documentation page</li>
+<li> <a href="frmt_jpeg.html">JPEG driver</a> documentation page</li>
+<li> <a href="frmt_webp.html">WEBP driver</a> documentation page</li>
+<li> <a href="http://portal.opengeospatial.org/files/?artifact_id=35326">OGC 07-057r7 WMTS 1.0</a> specification</li>
+<li> <a href="http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification">OSGeo TMS (Tile Map Service)</a> specification</li>
+</ul>
+
+
+
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/db2/gdaldb2rasterband.cpp b/ogr/ogrsf_frmts/db2/gdaldb2rasterband.cpp
new file mode 100644
index 0000000..b9af75c
--- /dev/null
+++ b/ogr/ogrsf_frmts/db2/gdaldb2rasterband.cpp
@@ -0,0 +1,2163 @@
+/******************************************************************************
+ *
+ * Project:  DB2 Translator
+ * Purpose:  Implements GDALDB2RasterBand class
+ * Author:   Even Rouault <even dot rouault at spatialys dot com>
+ * Author:   David Adler, dadler at adtechgeospatial dot com
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Even Rouault <even dot rouault at spatialys dot com>
+ * Copyright (c) 2015, David Adler
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_db2.h"
+#include "memdataset.h"
+#include "gdal_alg_priv.h"
+static char* GByteArrayToHexString( const GByte* pabyData, int nLen);
+//#define DEBUG_VERBOSE
+
+/************************************************************************/
+/*                      GDALDB2RasterBand()                      */
+/************************************************************************/
+
+GDALDB2RasterBand::GDALDB2RasterBand(OGRDB2DataSource* poDS,
+                                     int nBand,
+                                     int nTileWidth, int nTileHeight)
+{
+    this->poDS = poDS;
+    this->nBand = nBand;
+    eDataType = GDT_Byte;
+    nBlockXSize = nTileWidth;
+    nBlockYSize = nTileHeight;
+}
+
+/************************************************************************/
+/*                              FlushCache()                            */
+/************************************************************************/
+
+CPLErr GDALDB2RasterBand::FlushCache()
+{
+    CPLDebug("GDALDB2RasterBand::FlushCache","Entering");
+    OGRDB2DataSource* poGDS = (OGRDB2DataSource* )poDS;
+    CPLDebug("GDALDB2RasterBand::FlushCache","Calling FGDALPamRasterBand::FlushCache");
+
+    if( GDALPamRasterBand::FlushCache() != CE_None )
+        return CE_Failure;
+    CPLDebug("GDALDB2RasterBand::FlushCache","Calling FlushCacheWithErrCode");
+    return poGDS->FlushCacheWithErrCode();
+}
+
+/************************************************************************/
+/*                             GetColorTable()                          */
+/************************************************************************/
+
+GDALColorTable* GDALDB2RasterBand::GetColorTable()
+{
+
+    OGRDB2DataSource* poGDS = (OGRDB2DataSource* )poDS;
+    if( poGDS->nBands != 1 )
+        return NULL;
+
+    if( !poGDS->m_bTriedEstablishingCT )
+    {
+        poGDS->m_bTriedEstablishingCT = TRUE;
+        if( poGDS->m_poParentDS != NULL )
+        {
+            poGDS->m_poCT = poGDS->m_poParentDS->GetRasterBand(1)->GetColorTable();
+            if( poGDS->m_poCT )
+                poGDS->m_poCT = poGDS->m_poCT->Clone();
+            return poGDS->m_poCT;
+        }
+        CPL_SQLLEN nBlobLen = 0;
+        SQLINTEGER nDataLen;
+        OGRDB2Session *oSession =  poGDS->GetSession();
+        OGRDB2Statement oStatement( poGDS->GetSession() );
+        oStatement.Appendf("SELECT LENGTH(tile_data), tile_data FROM %s "
+                           "WHERE zoom_level = %d FETCH FIRST ROW ONLY",
+                           poGDS->m_osRasterTable.c_str(), poGDS->m_nZoomLevel);
+#ifdef DEBUG_SQL
+        CPLDebug("GDALDB2RasterBand::GetColorTable",
+                 "stmt: '%s'", oStatement.GetCommand());
+#endif
+
+        int nRetCode = SQLExecDirect(oStatement.GetStatement(),
+                                     (SQLCHAR *) oStatement.GetCommand(),
+                                     SQL_NTS);
+
+        if (nRetCode)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Failed reading color table; error: %s",
+                     oSession->GetLastError());
+            CPLDebug("GDALDB2RasterBand::GetColorTable",
+                     "Failed reading color table; error: %s",
+                     oSession->GetLastError());
+            return NULL;
+        }
+
+        nRetCode = SQLFetch(oStatement.GetStatement() );
+        CPLDebug("GDALDB2RasterBand::GetColorTable",
+                 "Fetch nRetCode: %d", nRetCode);
+        if( !(nRetCode == SQL_SUCCESS || nRetCode == SQL_NO_DATA))
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Failed fetching color table; error: %s",
+                     oSession->GetLastError());
+            CPLDebug("GDALDB2RasterBand::GetColorTable",
+                     "Failed fetching color table; error: %s",
+                     oSession->GetLastError());
+            return NULL;
+        }
+
+// If we got color data, process it.
+        if( nRetCode == SQL_SUCCESS)
+        {
+// Get the length
+            nRetCode = SQLGetData(oStatement.GetStatement(),
+                                  (SQLUSMALLINT) 1,
+                                  SQL_C_SLONG,
+                                  (SQLPOINTER) &nDataLen,
+                                  4,
+                                  0);
+
+// Allocate a buffer to read the tile BLOB into based on the
+// length(tile_data) value
+            GByte* pabyBlob = (GByte*) VSIMalloc(nDataLen);
+            CPLDebug("OGRDB2DataSource::ReadTile2",
+                     "nDataLen: %d; pabyBlob: %p", nDataLen, pabyBlob);
+            nRetCode = SQLGetData(oStatement.GetStatement(),
+                                  (SQLUSMALLINT) 2,
+                                  SQL_C_BINARY,
+                                  (SQLPOINTER) pabyBlob,
+                                  nDataLen,
+                                  &nBlobLen);
+
+            if (nRetCode != SQL_SUCCESS)
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Failed fetching tile_data; error: %s",
+                         oSession->GetLastError());
+                CPLDebug("OGRDB2DataSource::ReadTile",
+                         "Failed fetching tile_data; error: %s",
+                         oSession->GetLastError());
+                return NULL;
+            }
+
+            CPLString osMemFileName;
+            osMemFileName.Printf("/vsimem/gpkg_read_tile_%p", this);
+            VSILFILE * fp = VSIFileFromMemBuffer( osMemFileName.c_str(), pabyBlob,
+                                                  nDataLen, FALSE);
+            VSIFCloseL(fp);
+
+            /* Only PNG can have color table */
+            const char* apszDrivers[] = { "PNG", NULL };
+            GDALDataset* poDSTile = (GDALDataset*)GDALOpenEx(osMemFileName.c_str(),
+                                    GDAL_OF_RASTER | GDAL_OF_INTERNAL,
+                                    apszDrivers, NULL, NULL);
+            if( poDSTile != NULL )
+            {
+                if( poDSTile->GetRasterCount() == 1 )
+                {
+                    poGDS->m_poCT = poDSTile->GetRasterBand(1)->GetColorTable();
+                    if( poGDS->m_poCT != NULL )
+                        poGDS->m_poCT = poGDS->m_poCT->Clone();
+                }
+                GDALClose( poDSTile );
+            }
+
+            VSIUnlink(osMemFileName);
+        }
+    }
+
+    return poGDS->m_poCT;
+
+}
+
+/************************************************************************/
+/*                             SetColorTable()                          */
+/************************************************************************/
+
+CPLErr GDALDB2RasterBand::SetColorTable(GDALColorTable* poCT)
+{
+    OGRDB2DataSource* poGDS = (OGRDB2DataSource* )poDS;
+    if( poGDS->nBands != 1 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "SetColorTable() only supported for a single band dataset");
+        return CE_Failure;
+    }
+    if( !poGDS->m_bNew || poGDS->m_bTriedEstablishingCT )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "SetColorTable() only supported on a newly created dataset");
+        return CE_Failure;
+    }
+
+    poGDS->m_bTriedEstablishingCT = TRUE;
+    delete poGDS->m_poCT;
+    if( poCT != NULL )
+        poGDS->m_poCT = poCT->Clone();
+    else
+        poGDS->m_poCT = NULL;
+    return CE_None;
+}
+
+/************************************************************************/
+/*                        GetColorInterpretation()                      */
+/************************************************************************/
+
+GDALColorInterp GDALDB2RasterBand::GetColorInterpretation()
+{
+    OGRDB2DataSource* poGDS = (OGRDB2DataSource* )poDS;
+    if( poGDS->nBands == 1 )
+        return GetColorTable() ? GCI_PaletteIndex : GCI_GrayIndex;
+    else if( poGDS->nBands == 2 )
+        return (nBand == 1) ? GCI_GrayIndex : GCI_AlphaBand;
+    else
+        return (GDALColorInterp) (GCI_RedBand + (nBand - 1));
+}
+
+/************************************************************************/
+/*                        SetColorInterpretation()                      */
+/************************************************************************/
+
+CPLErr GDALDB2RasterBand::SetColorInterpretation( GDALColorInterp eInterp )
+{
+    OGRDB2DataSource* poGDS = (OGRDB2DataSource* )poDS;
+    if( eInterp == GCI_Undefined )
+        return CE_None;
+    if( poGDS->nBands == 1 && (eInterp == GCI_GrayIndex || eInterp == GCI_PaletteIndex) )
+        return CE_None;
+    if( poGDS->nBands == 2 &&
+            ((nBand == 1 && eInterp == GCI_GrayIndex) || (nBand == 2 && eInterp == GCI_AlphaBand)) )
+        return CE_None;
+    if( poGDS->nBands >= 3 && eInterp == GCI_RedBand + nBand - 1 )
+        return CE_None;
+    CPLError(CE_Warning, CPLE_NotSupported, "%s color interpretation not supported. Will be ignored",
+             GDALGetColorInterpretationName(eInterp));
+    return CE_Warning;
+}
+
+/************************************************************************/
+/*                        GPKGFindBestEntry()                           */
+/************************************************************************/
+
+static int GPKGFindBestEntry(GDALColorTable* poCT,
+                             GByte c1, GByte c2, GByte c3, GByte c4,
+                             int nTileBandCount)
+{
+    int nEntries = MIN(256, poCT->GetColorEntryCount());
+    int iBestIdx = 0;
+    int nBestDistance = 4 * 256 * 256;
+    for(int i=0; i<nEntries; i++)
+    {
+        const GDALColorEntry* psEntry = poCT->GetColorEntry(i);
+        int nDistance = (psEntry->c1 - c1) * (psEntry->c1 - c1) +
+                        (psEntry->c2 - c2) * (psEntry->c2 - c2) +
+                        (psEntry->c3 - c3) * (psEntry->c3 - c3);
+        if( nTileBandCount == 4 )
+            nDistance += (psEntry->c4 - c4) * (psEntry->c4 - c4);
+        if( nDistance < nBestDistance )
+        {
+            iBestIdx = i;
+            nBestDistance = nDistance;
+        }
+    }
+    return iBestIdx;
+}
+
+/************************************************************************/
+/*                           ReadTile()                                 */
+/************************************************************************/
+
+CPLErr OGRDB2DataSource::ReadTile(const CPLString& osMemFileName,
+                                  GByte* pabyTileData,
+                                  int* pbIsLossyFormat)
+{
+    CPLDebug("OGRDB2DataSource::ReadTile0","Entering; memFile: %s", osMemFileName.c_str());
+    const char* apszDrivers[] = { "JPEG", "PNG", "WEBP", NULL };
+    int nBlockXSize, nBlockYSize;
+    GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
+    GDALDataset* poDSTile = (GDALDataset*)GDALOpenEx(osMemFileName.c_str(),
+                            GDAL_OF_RASTER | GDAL_OF_INTERNAL,
+                            apszDrivers, NULL, NULL);
+    if( poDSTile == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot parse tile data");
+        memset(pabyTileData, 0, nBands * nBlockXSize * nBlockYSize );
+        return CE_Failure;
+    }
+
+    int nTileBandCount = poDSTile->GetRasterCount();
+
+    if( !(poDSTile->GetRasterXSize() == nBlockXSize &&
+            poDSTile->GetRasterYSize() == nBlockYSize &&
+            (nTileBandCount >= 1 && nTileBandCount <= 4)) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Inconsistent tiles characteristics");
+        GDALClose(poDSTile);
+        memset(pabyTileData, 0, nBands * nBlockXSize * nBlockYSize );
+        return CE_Failure;
+    }
+
+    if( poDSTile->RasterIO(GF_Read, 0, 0, nBlockXSize, nBlockYSize,
+                           pabyTileData,
+                           nBlockXSize, nBlockYSize,
+                           GDT_Byte,
+                           poDSTile->GetRasterCount(), NULL,
+                           0, 0, 0, NULL) != CE_None )
+    {
+        GDALClose(poDSTile);
+        memset(pabyTileData, 0, nBands * nBlockXSize * nBlockYSize );
+        return CE_Failure;
+    }
+
+    GDALColorTable* poCT = NULL;
+    if( nBands == 1 || nTileBandCount == 1 )
+    {
+        poCT = poDSTile->GetRasterBand(1)->GetColorTable();
+        GetRasterBand(1)->GetColorTable();
+    }
+    CPLDebug("DB2_RB","get description: '%s'", poDSTile->GetDriver()->GetDescription());
+    if( pbIsLossyFormat )
+        *pbIsLossyFormat = !EQUAL(poDSTile->GetDriver()->GetDescription(), "PNG") ||
+                           (poCT != NULL && poCT->GetColorEntryCount() == 256) /* PNG8 */;
+
+    /* Map RGB(A) tile to single-band color indexed */
+    if( nBands == 1 && m_poCT != NULL && nTileBandCount != 1 )
+    {
+        std::map< GUInt32, int > oMapEntryToIndex;
+        int nEntries = MIN(256, m_poCT->GetColorEntryCount());
+        for(int i=0; i<nEntries; i++)
+        {
+            const GDALColorEntry* psEntry = m_poCT->GetColorEntry(i);
+            GByte c1 = (GByte)psEntry->c1;
+            GByte c2 = (GByte)psEntry->c2;
+            GByte c3 = (GByte)psEntry->c3;
+            GUInt32 nVal = c1 + (c2 << 8) + (c3 << 16);
+            if( nTileBandCount == 4 ) nVal += ((GByte)psEntry->c4 << 24);
+            oMapEntryToIndex[nVal] = i;
+        }
+        int iBestEntryFor0 = GPKGFindBestEntry(m_poCT, 0, 0, 0, 0, nTileBandCount);
+        for(int i=0; i<nBlockXSize*nBlockYSize; i++)
+        {
+            GByte c1 = pabyTileData[i];
+            GByte c2 = pabyTileData[i + nBlockXSize * nBlockYSize];
+            GByte c3 = pabyTileData[i + 2 * nBlockXSize * nBlockYSize];
+            GByte c4 = pabyTileData[i + 3 * nBlockXSize * nBlockYSize];
+            GUInt32 nVal = c1 + (c2 << 8) + (c3 << 16);
+            if( nTileBandCount == 4 ) nVal += (c4 << 24);
+            if( nVal == 0 ) /* In most cases we will reach that point at partial tiles */
+                pabyTileData[i] = (GByte) iBestEntryFor0;
+            else
+            {
+                std::map< GUInt32, int >::iterator oMapEntryToIndexIter = oMapEntryToIndex.find(nVal);
+                if( oMapEntryToIndexIter == oMapEntryToIndex.end() )
+                    /* Could happen with JPEG tiles */
+                    pabyTileData[i] = (GByte) GPKGFindBestEntry(m_poCT, c1, c2, c3, c4, nTileBandCount);
+                else
+                    pabyTileData[i] = (GByte) oMapEntryToIndexIter->second;
+            }
+        }
+        GDALClose( poDSTile );
+        return CE_None;
+    }
+
+    if( nBands == 1 && nTileBandCount == 1 && poCT != NULL && m_poCT != NULL &&
+            !poCT->IsSame(m_poCT) )
+    {
+        CPLError(CE_Warning, CPLE_NotSupported, "Different color tables. Unhandled for now");
+    }
+    else if( (nBands == 1 && nTileBandCount >= 3) ||
+             (nBands == 1 && nTileBandCount == 1 && m_poCT != NULL && poCT == NULL) ||
+             ((nBands == 1 || nBands == 2) && nTileBandCount == 1 && m_poCT == NULL && poCT != NULL) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Inconsistent dataset and tiles band characteristics");
+    }
+
+    if( nBands == 2 )
+    {
+        if( nTileBandCount == 1 || nTileBandCount == 3 /* assuming that the RGB is Grey,Grey,Grey */ )
+        {
+            /* Create fully opaque alpha */
+            memset(pabyTileData + 1 * nBlockXSize * nBlockYSize,
+                   255, nBlockXSize * nBlockYSize);
+        }
+        else if( nTileBandCount == 4 )
+        {
+            /* Transfer alpha band */
+            memcpy(pabyTileData + 1 * nBlockXSize * nBlockYSize,
+                   pabyTileData + 3 * nBlockXSize * nBlockYSize,
+                   nBlockXSize * nBlockYSize);
+        }
+    }
+    else if( nTileBandCount == 2 )
+    {
+        /* Do Grey+Alpha -> RGBA */
+        memcpy(pabyTileData + 3 * nBlockXSize * nBlockYSize,
+               pabyTileData + 1 * nBlockXSize * nBlockYSize,
+               nBlockXSize * nBlockYSize);
+        memcpy(pabyTileData + 1 * nBlockXSize * nBlockYSize,
+               pabyTileData, nBlockXSize * nBlockYSize);
+        memcpy(pabyTileData + 2 * nBlockXSize * nBlockYSize,
+               pabyTileData, nBlockXSize * nBlockYSize);
+    }
+    else if( nTileBandCount == 1 && !(nBands == 1 && m_poCT != NULL) )
+    {
+        /* Expand color indexed to RGB(A) */
+        if( poCT != NULL )
+        {
+            int i;
+            GByte abyCT[4*256];
+            int nEntries = MIN(256, poCT->GetColorEntryCount());
+            for(i=0; i<nEntries; i++)
+            {
+                const GDALColorEntry* psEntry = poCT->GetColorEntry(i);
+                abyCT[4*i] = (GByte)psEntry->c1;
+                abyCT[4*i+1] = (GByte)psEntry->c2;
+                abyCT[4*i+2] = (GByte)psEntry->c3;
+                abyCT[4*i+3] = (GByte)psEntry->c4;
+            }
+            for(; i<256; i++)
+            {
+                abyCT[4*i] = 0;
+                abyCT[4*i+1] = 0;
+                abyCT[4*i+2] = 0;
+                abyCT[4*i+3] = 0;
+            }
+            for(i=0; i<nBlockXSize * nBlockYSize; i++)
+            {
+                GByte byVal = pabyTileData[i];
+                pabyTileData[i] = abyCT[4*byVal];
+                pabyTileData[i + 1 * nBlockXSize * nBlockYSize] = abyCT[4*byVal+1];
+                pabyTileData[i + 2 * nBlockXSize * nBlockYSize] = abyCT[4*byVal+2];
+                pabyTileData[i + 3 * nBlockXSize * nBlockYSize] = abyCT[4*byVal+3];
+            }
+        }
+        else
+        {
+            memcpy(pabyTileData + 1 * nBlockXSize * nBlockYSize,
+                   pabyTileData, nBlockXSize * nBlockYSize);
+            memcpy(pabyTileData + 2 * nBlockXSize * nBlockYSize,
+                   pabyTileData, nBlockXSize * nBlockYSize);
+            if( nBands == 4 )
+            {
+                memset(pabyTileData + 3 * nBlockXSize * nBlockYSize,
+                       255, nBlockXSize * nBlockYSize);
+            }
+        }
+    }
+    else if( nTileBandCount == 3 && nBands == 4 )
+    {
+        /* Create fully opaque alpha */
+        memset(pabyTileData + 3 * nBlockXSize * nBlockYSize,
+               255, nBlockXSize * nBlockYSize);
+    }
+
+    GDALClose( poDSTile );
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                           ReadTile()                                 */
+/************************************************************************/
+
+GByte* OGRDB2DataSource::ReadTile(int nRow, int nCol)
+{
+    CPLDebug("OGRDB2DataSource::ReadTile1","Entering; nRow: %d; nCol: %d", nRow, nCol);
+    GByte* pabyData = NULL;
+
+    int nBlockXSize, nBlockYSize;
+    GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
+    if( m_nShiftXPixelsMod )
+    {
+        int i;
+        for(i = 0; i < 4; i ++)
+        {
+            if( m_asCachedTilesDesc[i].nRow == nRow &&
+                    m_asCachedTilesDesc[i].nCol == nCol )
+            {
+                if( m_asCachedTilesDesc[i].nIdxWithinTileData >= 0 )
+                {
+                    return m_pabyCachedTiles +
+                           m_asCachedTilesDesc[i].nIdxWithinTileData * 4 * nBlockXSize * nBlockYSize;
+                }
+                else
+                {
+                    if( i == 0 )
+                        m_asCachedTilesDesc[i].nIdxWithinTileData =
+                            (m_asCachedTilesDesc[1].nIdxWithinTileData == 0 ) ? 1 : 0;
+                    else if( i == 1 )
+                        m_asCachedTilesDesc[i].nIdxWithinTileData =
+                            (m_asCachedTilesDesc[0].nIdxWithinTileData == 0 ) ? 1 : 0;
+                    else if( i == 2 )
+                        m_asCachedTilesDesc[i].nIdxWithinTileData =
+                            (m_asCachedTilesDesc[3].nIdxWithinTileData == 2 ) ? 3 : 2;
+                    else
+                        m_asCachedTilesDesc[i].nIdxWithinTileData =
+                            (m_asCachedTilesDesc[2].nIdxWithinTileData == 2 ) ? 3 : 2;
+                    pabyData = m_pabyCachedTiles +
+                               m_asCachedTilesDesc[i].nIdxWithinTileData * 4 * nBlockXSize * nBlockYSize;
+                    break;
+                }
+            }
+        }
+        CPLAssert(i < 4);
+    }
+    else
+        pabyData = m_pabyCachedTiles;
+
+    return ReadTile(nRow, nCol, pabyData);
+}
+
+/************************************************************************/
+/*                           ReadTile()                                 */
+/************************************************************************/
+
+GByte* OGRDB2DataSource::ReadTile(int nRow, int nCol, GByte* pabyData,
+                                  int* pbIsLossyFormat)
+{
+    CPLDebug("OGRDB2DataSource::ReadTile2","Entering; nRow: %d; nCol: %d", nRow, nCol);
+
+    int nBlockXSize, nBlockYSize;
+    GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
+    SQLINTEGER nBlockSize = nBlockXSize * nBlockYSize;
+    CPL_SQLLEN nBlobLen = 0;
+    SQLINTEGER nDataLen;
+    if( pbIsLossyFormat ) *pbIsLossyFormat = FALSE;
+
+    if( nRow < 0 || nCol < 0 || nRow >= m_nTileMatrixHeight ||
+            nCol >= m_nTileMatrixWidth )
+    {
+        memset(pabyData, 0, nBands * nBlockSize );
+        return pabyData;
+    }
+
+    OGRDB2Statement oStatement( GetSession() );
+    oStatement.Appendf("SELECT LENGTH(tile_data), tile_data FROM %s "
+                       "WHERE zoom_level = %d AND tile_row = %d "
+                       "AND tile_column = %d%s",
+                       m_osRasterTable.c_str(), m_nZoomLevel, nRow, nCol,
+                       m_osWHERE.size() ? CPLSPrintf(" AND (%s)", m_osWHERE.c_str()): "");
+
+#ifdef DEBUG_SQL
+    CPLDebug("OGRDB2DataSource::ReadTile2",
+             "stmt: '%s'", oStatement.GetCommand());
+#endif
+
+// Use native ODBC / CLI functions here to avoid oStatement.Fetch()
+// wanting to fetch tile data (BLOB) in multiple pieces and then
+// returning as a character string
+    int nRetCode = SQLExecDirect(oStatement.GetStatement(),
+                                 (SQLCHAR *) oStatement.GetCommand(),
+                                 SQL_NTS);
+    if (nRetCode)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Failed reading tile_data; error: %s",
+                 GetSession()->GetLastError());
+        return NULL;
+    }
+
+    nRetCode = SQLFetch(oStatement.GetStatement() );
+    CPLDebug("OGRDB2DataSource::ReadTile2",
+             "Fetch nRetCode: %d", nRetCode);
+    if( !(nRetCode == SQL_SUCCESS || nRetCode == SQL_NO_DATA))
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Failed fetching tile_data; error: %s",
+                 GetSession()->GetLastError());
+        return NULL;
+    }
+
+// If we got tile_data, process it. SQL_NO_DATA means try partial
+    if( nRetCode == SQL_SUCCESS)
+    {
+        nRetCode = SQLGetData(oStatement.GetStatement(),
+                              (SQLUSMALLINT) 1,
+                              SQL_C_SLONG,
+                              (SQLPOINTER) &nDataLen,
+                              4,
+                              0);
+
+// Allocate a buffer to read the tile BLOB into based on the
+// length(tile_data) value
+        GByte* pabyBlob = (GByte*) VSIMalloc(nDataLen);
+        CPLDebug("OGRDB2DataSource::ReadTile2",
+                 "nDataLen: %d; pabyBlob: %p", nDataLen, pabyBlob);
+        nRetCode = SQLGetData(oStatement.GetStatement(),
+                              (SQLUSMALLINT) 2,
+                              SQL_C_BINARY,
+                              (SQLPOINTER) pabyBlob,
+                              nDataLen,
+                              &nBlobLen);
+
+        if (nRetCode != SQL_SUCCESS)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Failed fetching tile_data; error: %s",
+                     GetSession()->GetLastError());
+            CPLDebug("OGRDB2DataSource::ReadTile",
+                     "Failed fetching tile_data; error: %s",
+                     GetSession()->GetLastError());
+            return NULL;
+        }
+
+        CPLString osMemFileName;
+        osMemFileName.Printf("/vsimem/gpkg_read_tile_%p", this);
+        VSILFILE * fp = VSIFileFromMemBuffer( osMemFileName.c_str(), pabyBlob,
+                                              nDataLen, FALSE);
+        VSIFCloseL(fp);
+        CPLDebug("OGRDB2DataSource::ReadTile2",
+                 "osMemFileName: %s; nDataLen %d", osMemFileName.c_str(), nDataLen);
+
+        ReadTile(osMemFileName, pabyData, pbIsLossyFormat);
+        VSIUnlink(osMemFileName);
+        VSIFree(pabyBlob);
+        return pabyData;
+    }
+
+    else
+    {
+        oStatement.Clear();
+
+        if( m_hTempDB && (m_nShiftXPixelsMod || m_nShiftYPixelsMod) )
+        {
+            oStatement.Appendf(
+                "SELECT partial_flag, tile_data_band_1, tile_data_band_2, "
+                "tile_data_band_3, tile_data_band_4 FROM partial_tiles WHERE "
+                "zoom_level = %d AND tile_row = %d AND tile_column = %d",
+                m_nZoomLevel, nRow, nCol);
+#ifdef DEBUG_SQL
+            CPLDebug("OGRDB2DataSource::ReadTile2",
+                     "stmt: '%s'", oStatement.GetCommand());
+#endif
+            if( !oStatement.ExecuteSQL() )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Read of partial_tiles failed; %s",
+                         GetSession()->GetLastError());
+                CPLDebug("OGRDB2DataSource::ReadTile2",
+                         "Read of partial_tiles failed; %s",
+                         GetSession()->GetLastError() );
+                memset(pabyData, 0, nBands * nBlockXSize * nBlockYSize );
+                return pabyData;
+            }
+
+            nRetCode = SQLFetch(oStatement.GetStatement() );
+            CPLDebug("OGRDB2DataSource::ReadTile2",
+                     "Fetch nRetCode: %d", nRetCode);
+
+            if ( nRetCode!= SQL_SUCCESS )
+            {
+                SQLINTEGER nPartialFlag;
+                nRetCode = SQLGetData(oStatement.GetStatement(),
+                                      (SQLUSMALLINT) 1,
+                                      SQL_C_SLONG,
+                                      (SQLPOINTER) &nPartialFlag,
+                                      4,
+                                      0);
+
+// Allocate a buffer to read the tile BLOB into based on the
+// length(tile_data) value
+                GByte* pabyBlob = (GByte*) VSIMalloc(nBlockSize);
+                CPLDebug("OGRDB2DataSource::ReadTile2",
+                         "nBlockSize: %d; pabyBlob: %p", nBlockSize, pabyBlob);
+                for(int iBand = 1; iBand <= nBands; iBand ++ )
+                {
+                    GByte* pabyDestBand = pabyData + (iBand - 1) * nBlockSize;
+                    nRetCode = SQLGetData(oStatement.GetStatement(),
+                                          (SQLUSMALLINT) iBand + 1,
+                                          SQL_C_BINARY,
+                                          (SQLPOINTER) pabyBlob,
+                                          nBlockSize,
+                                          &nBlobLen);
+                    if( nRetCode != SQL_SUCCESS )
+                    {
+                        CPLError(CE_Failure, CPLE_AppDefined,
+                                 "Read of partial_tiles failed; %s",
+                                 GetSession()->GetLastError());
+                        CPLDebug("OGRDB2DataSource::ReadTile2",
+                                 "Read of partial_tiles failed; %s",
+                                 GetSession()->GetLastError() );
+                        memset(pabyData, 0, nBands * nBlockSize );
+                        return pabyData;
+                    }
+                    if( nPartialFlag & (((1 << 4)-1) << (4 * (iBand - 1))) )
+                    {
+                        CPLAssert( nBlobLen == nBlockXSize * nBlockYSize );
+                        memcpy( pabyDestBand,
+                                pabyBlob,
+                                nBlockSize );
+                    }
+                    else
+                    {
+                        memset(pabyDestBand, 0, nBlockSize );
+                    }
+                }
+                VSIFree(pabyBlob);
+            }
+            else
+            {
+                memset(pabyData, 0, nBands * nBlockSize );
+            }
+        }
+        else
+        {
+            memset(pabyData, 0, nBands * nBlockSize );
+        }
+    }
+
+    return pabyData;
+}
+
+/************************************************************************/
+/*                         IReadBlock()                                 */
+/************************************************************************/
+
+CPLErr GDALDB2RasterBand::IReadBlock(int nBlockXOff, int nBlockYOff,
+                                     void* pData)
+{
+    OGRDB2DataSource* poGDS = (OGRDB2DataSource* )poDS;
+    CPLDebug("GDALDB2RasterBand::IReadBlock", "IReadBlock(nBand=%d,nBlockXOff=%d,nBlockYOff=%d",
+             nBand,nBlockXOff,nBlockYOff);
+
+    int nRowMin = nBlockYOff + poGDS->m_nShiftYTiles;
+    int nRowMax = nRowMin;
+    if( poGDS->m_nShiftYPixelsMod )
+        nRowMax ++;
+
+    int nColMin = nBlockXOff + poGDS->m_nShiftXTiles;
+    int nColMax = nColMin;
+    if( poGDS->m_nShiftXPixelsMod )
+        nColMax ++;
+
+    /* Optimize for left to right reading at constant row */
+    if( poGDS->m_nShiftXPixelsMod )
+    {
+        if( nRowMin == poGDS->m_asCachedTilesDesc[0].nRow &&
+                nColMin == poGDS->m_asCachedTilesDesc[0].nCol + 1 &&
+                poGDS->m_asCachedTilesDesc[0].nIdxWithinTileData >= 0 )
+        {
+            CPLAssert(nRowMin == poGDS->m_asCachedTilesDesc[1].nRow);
+            CPLAssert(nColMin == poGDS->m_asCachedTilesDesc[1].nCol);
+            CPLAssert(poGDS->m_asCachedTilesDesc[0].nIdxWithinTileData == 0 ||
+                      poGDS->m_asCachedTilesDesc[0].nIdxWithinTileData == 1);
+
+            /* 0 1  --> 1 -1 */
+            /* 2 3      3 -1 */
+            /* or */
+            /* 1 0  --> 0 -1 */
+            /* 3 2      2 -1 */
+            poGDS->m_asCachedTilesDesc[0].nIdxWithinTileData = poGDS->m_asCachedTilesDesc[1].nIdxWithinTileData;
+            poGDS->m_asCachedTilesDesc[2].nIdxWithinTileData = poGDS->m_asCachedTilesDesc[3].nIdxWithinTileData;
+        }
+        else
+        {
+            poGDS->m_asCachedTilesDesc[0].nIdxWithinTileData = -1;
+            poGDS->m_asCachedTilesDesc[2].nIdxWithinTileData = -1;
+        }
+        poGDS->m_asCachedTilesDesc[0].nRow = nRowMin;
+        poGDS->m_asCachedTilesDesc[0].nCol = nColMin;
+        poGDS->m_asCachedTilesDesc[1].nRow = nRowMin;
+        poGDS->m_asCachedTilesDesc[1].nCol = nColMin + 1;
+        poGDS->m_asCachedTilesDesc[2].nRow = nRowMin + 1;
+        poGDS->m_asCachedTilesDesc[2].nCol = nColMin;
+        poGDS->m_asCachedTilesDesc[3].nRow = nRowMin + 1;
+        poGDS->m_asCachedTilesDesc[3].nCol = nColMin + 1;
+        poGDS->m_asCachedTilesDesc[1].nIdxWithinTileData = -1;
+        poGDS->m_asCachedTilesDesc[3].nIdxWithinTileData = -1;
+
+    }
+
+    for(int nRow = nRowMin; nRow <= nRowMax; nRow ++)
+    {
+        for(int nCol = nColMin; nCol <= nColMax; nCol++ )
+        {
+            GByte* pabyTileData = poGDS->ReadTile(nRow, nCol);
+            if( pabyTileData == NULL )
+                return CE_Failure;
+
+            for(int iBand=1; iBand<=poGDS->nBands; iBand++)
+            {
+                GDALRasterBlock* poBlock = NULL;
+                GByte* pabyDest;
+                if( iBand == nBand )
+                {
+                    pabyDest = (GByte*)pData;
+                }
+                else
+                {
+                    poBlock =
+                        poGDS->GetRasterBand(iBand)->GetLockedBlockRef(nBlockXOff, nBlockYOff, TRUE);
+                    if( poBlock == NULL )
+                        continue;
+                    if( poBlock->GetDirty() )
+                    {
+                        poBlock->DropLock();
+                        continue;
+                    }
+                    pabyDest = (GByte*) poBlock->GetDataRef();
+                }
+
+                // Composite tile data into block data
+                if( poGDS->m_nShiftXPixelsMod == 0 && poGDS->m_nShiftYPixelsMod == 0 )
+                {
+                    memcpy(pabyDest,
+                           pabyTileData + (iBand - 1) * nBlockXSize * nBlockYSize,
+                           nBlockXSize * nBlockYSize);
+                }
+                else
+                {
+                    int nSrcXOffset, nSrcXSize, nSrcYOffset, nSrcYSize;
+                    int nDstXOffset, nDstYOffset;
+                    if( nCol == nColMin )
+                    {
+                        nSrcXOffset = poGDS->m_nShiftXPixelsMod;
+                        nSrcXSize = nBlockXSize - poGDS->m_nShiftXPixelsMod;
+                        nDstXOffset = 0;
+                    }
+                    else
+                    {
+                        nSrcXOffset = 0;
+                        nSrcXSize = poGDS->m_nShiftXPixelsMod;
+                        nDstXOffset = nBlockXSize - poGDS->m_nShiftXPixelsMod;
+                    }
+                    if( nRow == nRowMin )
+                    {
+                        nSrcYOffset = poGDS->m_nShiftYPixelsMod;
+                        nSrcYSize = nBlockYSize - poGDS->m_nShiftYPixelsMod;
+                        nDstYOffset = 0;
+                    }
+                    else
+                    {
+                        nSrcYOffset = 0;
+                        nSrcYSize = poGDS->m_nShiftYPixelsMod;
+                        nDstYOffset = nBlockYSize - poGDS->m_nShiftYPixelsMod;
+                    }
+                    CPLDebug("GDALDB2RasterBand::IReadBlock", "Copy source tile x=%d,w=%d,y=%d,h=%d into buffet at x=%d,y=%d",
+                             nSrcXOffset, nSrcXSize, nSrcYOffset, nSrcYSize, nDstXOffset, nDstYOffset);
+                    for( int y=0; y<nSrcYSize; y++ )
+                    {
+                        GByte* pSrc = pabyTileData + (iBand - 1) * nBlockXSize * nBlockYSize +
+                                      (y + nSrcYOffset) * nBlockXSize + nSrcXOffset;
+                        GByte* pDst = pabyDest + (y + nDstYOffset) * nBlockXSize + nDstXOffset;
+                        GDALCopyWords(pSrc, GDT_Byte, 1,
+                                      pDst, GDT_Byte, 1,
+                                      nSrcXSize);
+                    }
+                }
+
+                if( poBlock )
+                    poBlock->DropLock();
+
+            }
+        }
+    }
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                       WEBPSupports4Bands()                           */
+/************************************************************************/
+
+static int WEBPSupports4Bands()
+{
+    static int bRes = -1;
+    if( bRes < 0 )
+    {
+        GDALDriver* poDrv = (GDALDriver*) GDALGetDriverByName("WEBP");
+        if( poDrv == NULL || CPLTestBool(CPLGetConfigOption("GPKG_SIMUL_WEBP_3BAND", "FALSE")) )
+            bRes = FALSE;
+        else
+        {
+            // LOSSLESS and RGBA support appeared in the same version
+            bRes = strstr(poDrv->GetMetadataItem(GDAL_DMD_CREATIONOPTIONLIST), "LOSSLESS") != NULL;
+        }
+        if( poDrv != NULL && !bRes )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "The version of WEBP available does not support 4-band RGBA");
+        }
+    }
+    return bRes;
+}
+
+/************************************************************************/
+/*                         WriteTile()                                  */
+/************************************************************************/
+
+CPLErr OGRDB2DataSource::WriteTile()
+{
+    CPLAssert(!m_bInWriteTile);
+    m_bInWriteTile = TRUE;
+    CPLErr eErr = WriteTileInternal();
+    m_bInWriteTile = FALSE;
+    CPLDebug("OGRDB2DataSource::WriteTile","exit; eErr: %d", eErr);
+    return eErr;
+}
+
+/* should only be called by WriteTile() */
+CPLErr OGRDB2DataSource::WriteTileInternal()
+{
+    CPLDebug("OGRDB2DataSource::WriteTileInternal","entering");
+
+    if( !(m_bUpdate && m_asCachedTilesDesc[0].nRow >= 0 &&
+            m_asCachedTilesDesc[0].nCol >= 0 &&
+            m_asCachedTilesDesc[0].nIdxWithinTileData == 0) )
+        return CE_None;
+
+    int nRow = m_asCachedTilesDesc[0].nRow;
+    int nCol = m_asCachedTilesDesc[0].nCol;
+
+    int bAllDirty = TRUE;
+    int bAllNonDirty = TRUE;
+    int i;
+    for(i=0; i<nBands; i++)
+    {
+        if( m_asCachedTilesDesc[0].abBandDirty[i] )
+            bAllNonDirty = FALSE;
+        else
+            bAllDirty = FALSE;
+    }
+    if( bAllNonDirty )
+        return CE_None;
+
+    int nBlockXSize, nBlockYSize;
+    GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
+
+    /* If all bands for that block are not dirty/written, we need to */
+    /* fetch the missing ones if the tile exists */
+    int bIsLossyFormat = FALSE;
+    if( !bAllDirty )
+    {
+        for(i=1; i<=3; i++)
+        {
+            m_asCachedTilesDesc[i].nRow = -1;
+            m_asCachedTilesDesc[i].nCol = -1;
+            m_asCachedTilesDesc[i].nIdxWithinTileData = -1;
+        }
+        ReadTile(nRow, nCol, m_pabyCachedTiles + 4 * nBlockXSize * nBlockYSize,
+                 &bIsLossyFormat);
+        for(i=0; i<nBands; i++)
+        {
+            if( !m_asCachedTilesDesc[0].abBandDirty[i] )
+            {
+                memcpy(m_pabyCachedTiles + i * nBlockXSize * nBlockYSize,
+                       m_pabyCachedTiles + (4 + i) * nBlockXSize * nBlockYSize,
+                       nBlockXSize * nBlockYSize);
+            }
+        }
+    }
+
+    /* Compute origin of tile in GDAL raster space */
+    int nXOff = (nCol - m_nShiftXTiles) * nBlockXSize - m_nShiftXPixelsMod;
+    int nYOff = (nRow - m_nShiftYTiles) * nBlockYSize - m_nShiftYPixelsMod;
+
+    /* Assert that the tile at least intersects some of the GDAL raster space */
+    CPLAssert(nXOff + nBlockXSize > 0);
+    CPLAssert(nYOff + nBlockYSize > 0);
+    /* Can happen if the tile of the raster is less than the block size */
+    if( nXOff >= nRasterXSize || nYOff >= nRasterYSize )
+        return CE_None;
+
+    /* Validity area of tile data in intra-tile coordinate space */
+    int iXOff = 0;
+    int iYOff = 0;
+    int iXCount = nBlockXSize;
+    int iYCount = nBlockYSize;
+
+    int bPartialTile = FALSE;
+    int nAlphaBand = (nBands == 2) ? 2 : (nBands == 4) ? 4 : 0;
+    if( nAlphaBand == 0 )
+    {
+        if( nXOff < 0 )
+        {
+            bPartialTile = TRUE;
+            iXOff = -nXOff;
+            iXCount += nXOff;
+        }
+        if( nXOff + nBlockXSize > nRasterXSize )
+        {
+            bPartialTile = TRUE;
+            iXCount -= nXOff + nBlockXSize - nRasterXSize;
+        }
+        if( nYOff < 0 )
+        {
+            bPartialTile = TRUE;
+            iYOff = -nYOff;
+            iYCount += nYOff;
+        }
+        if( nYOff + nBlockYSize > nRasterYSize )
+        {
+            bPartialTile = TRUE;
+            iYCount -= nYOff + nBlockYSize - nRasterYSize;
+        }
+        CPLAssert(iXOff >= 0);
+        CPLAssert(iYOff >= 0);
+        CPLAssert(iXCount > 0);
+        CPLAssert(iYCount > 0);
+        CPLAssert(iXOff + iXCount <= nBlockXSize);
+        CPLAssert(iYOff + iYCount <= nBlockYSize);
+    }
+
+    m_asCachedTilesDesc[0].nRow = -1;
+    m_asCachedTilesDesc[0].nCol = -1;
+    m_asCachedTilesDesc[0].nIdxWithinTileData = -1;
+    m_asCachedTilesDesc[0].abBandDirty[0] = FALSE;
+    m_asCachedTilesDesc[0].abBandDirty[1] = FALSE;
+    m_asCachedTilesDesc[0].abBandDirty[2] = FALSE;
+    m_asCachedTilesDesc[0].abBandDirty[3] = FALSE;
+
+    CPLErr eErr = CE_Failure;
+
+    int bAllOpaque = TRUE;
+    if( m_poCT == NULL && nAlphaBand != 0 )
+    {
+        GByte byFirstAlphaVal =  m_pabyCachedTiles[(nAlphaBand-1) * nBlockXSize * nBlockYSize];
+        for(i=1; i<nBlockXSize * nBlockYSize; i++)
+        {
+            if( m_pabyCachedTiles[(nAlphaBand-1) * nBlockXSize * nBlockYSize + i] != byFirstAlphaVal )
+                break;
+        }
+        if( i == nBlockXSize * nBlockYSize )
+        {
+            // If tile is fully transparent, don't serialize it and remove it if it exists
+            if( byFirstAlphaVal == 0 )
+            {
+                CPLDebug("OGRDB2DataSource::WriteTileInternal","want to do delete");
+                OGRDB2Statement oStatement( GetSession() );
+                oStatement.Appendf( "DELETE FROM %s "
+                                    "WHERE zoom_level = %d AND tile_row = %d "
+                                    "AND tile_column = %d",
+                                    m_osRasterTable.c_str(), m_nZoomLevel,
+                                    nRow, nCol);
+                CPLDebug("OGRDB2DataSource::WriteTileInternal",
+                         "stmt: '%s'", oStatement.GetCommand());
+                if( !oStatement.ExecuteSQL() )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Failure when deleting tile (row=%d,col=%d) "
+                             "at zoom_level=%d : %s",
+                             nRow, nCol, m_nZoomLevel,
+                             GetSession()->GetLastError());
+                    CPLDebug("OGRDB2DataSource::WriteTileInternal",
+                             " insert failed; '%s'",
+                             GetSession()->GetLastError() );
+                    return CE_Failure;
+                }
+            }
+            bAllOpaque = (byFirstAlphaVal == 255);
+        }
+        else
+            bAllOpaque = FALSE;
+    }
+
+    if( bIsLossyFormat )
+    {
+        CPLDebug("OGRDB2DataSource::WriteTileInternal", "Had to read tile (row=%d,col=%d) at zoom_level=%d, "
+                 "stored in a lossy format, before rewriting it, causing potential extra quality loss",
+                 nRow, nCol, m_nZoomLevel);
+    }
+
+    CPLString osMemFileName;
+    osMemFileName.Printf("/vsimem/gpkg_write_tile_%p", this);
+    const char* pszDriverName = "PNG";
+    int bTileDriverSupports1Band = FALSE;
+    int bTileDriverSupports2Bands = FALSE;
+    int bTileDriverSupports4Bands = FALSE;
+    int bTileDriverSupportsCT = FALSE;
+
+    if( nBands == 1 )
+        GetRasterBand(1)->GetColorTable();
+
+    if( m_eTF == GPKG_TF_PNG_JPEG )
+    {
+        bTileDriverSupports1Band = TRUE;
+
+        if( bPartialTile || (nBands == 2 && !bAllOpaque)
+                || (nBands == 4 && !bAllOpaque) || m_poCT != NULL )
+        {
+            pszDriverName = "PNG";
+            bTileDriverSupports2Bands = TRUE;
+            bTileDriverSupports4Bands = TRUE;
+            bTileDriverSupportsCT = TRUE;
+        }
+        else
+            pszDriverName = "JPEG";
+    }
+    else if( m_eTF == GPKG_TF_PNG ||
+             m_eTF == GPKG_TF_PNG8 )
+    {
+        pszDriverName = "PNG";
+        bTileDriverSupports1Band = TRUE;
+        bTileDriverSupports2Bands = TRUE;
+        bTileDriverSupports4Bands = TRUE;
+        bTileDriverSupportsCT = TRUE;
+    }
+    else if( m_eTF == GPKG_TF_JPEG )
+    {
+        pszDriverName = "JPEG";
+        bTileDriverSupports1Band = TRUE;
+    }
+    else if( m_eTF == GPKG_TF_WEBP )
+    {
+        pszDriverName = "WEBP";
+        bTileDriverSupports4Bands = WEBPSupports4Bands();
+    }
+    else
+    {
+        CPLAssert(0);
+    }
+
+    GDALDriver* poDriver = (GDALDriver*) GDALGetDriverByName(pszDriverName);
+    if( poDriver != NULL)
+    {
+        GDALDataset* poMEMDS = MEMDataset::Create("", nBlockXSize, nBlockYSize,
+                               0, GDT_Byte, NULL);
+        int nTileBands = nBands;
+        if( bPartialTile && nBands == 1 && m_poCT == NULL && bTileDriverSupports2Bands )
+            nTileBands = 2;
+        else if( bPartialTile && bTileDriverSupports4Bands )
+            nTileBands = 4;
+        else if( m_eTF == GPKG_TF_PNG8 && nBands >= 3 && bAllOpaque && !bPartialTile )
+            nTileBands = 1;
+        else if( nBands == 2 )
+        {
+            if ( bAllOpaque )
+            {
+                if (bTileDriverSupports2Bands )
+                    nTileBands = 1;
+                else
+                    nTileBands = 3;
+            }
+            else if( !bTileDriverSupports2Bands )
+            {
+                if( bTileDriverSupports4Bands )
+                    nTileBands = 4;
+                else
+                    nTileBands = 3;
+            }
+        }
+        else if( nBands == 4 && (bAllOpaque || !bTileDriverSupports4Bands) )
+            nTileBands = 3;
+        else if( nBands == 1 && m_poCT != NULL && !bTileDriverSupportsCT )
+        {
+            nTileBands = 3;
+            if( bTileDriverSupports4Bands )
+            {
+                for(i=0; i<m_poCT->GetColorEntryCount(); i++)
+                {
+                    const GDALColorEntry* psEntry = m_poCT->GetColorEntry(i);
+                    if( psEntry->c4 == 0 )
+                    {
+                        nTileBands = 4;
+                        break;
+                    }
+                }
+            }
+        }
+        else if( nBands == 1 && m_poCT == NULL && !bTileDriverSupports1Band )
+            nTileBands = 3;
+
+        if( bPartialTile && (nTileBands == 2 || nTileBands == 4) )
+        {
+            int nTargetAlphaBand = nTileBands;
+            memset(m_pabyCachedTiles + (nTargetAlphaBand-1) * nBlockXSize * nBlockYSize, 0,
+                   nBlockXSize * nBlockYSize);
+            for(int iY = iYOff; iY < iYOff + iYCount; iY ++)
+            {
+                memset(m_pabyCachedTiles + ((nTargetAlphaBand-1) * nBlockYSize + iY) * nBlockXSize + iXOff,
+                       255, iXCount);
+            }
+        }
+
+        for(i=0; i<nTileBands; i++)
+        {
+            char** papszOptions = NULL;
+            char szDataPointer[32];
+            int iSrc = i;
+            if( nBands == 1 && m_poCT == NULL && nTileBands == 3 )
+                iSrc = 0;
+            else if( nBands == 1 && m_poCT == NULL && bPartialTile && nTileBands == 4 )
+                iSrc = (i < 3) ? 0 : 3;
+            else if( nBands == 2 && nTileBands >= 3 )
+                iSrc = (i < 3) ? 0 : 1;
+            int nRet = CPLPrintPointer(szDataPointer,
+                                       m_pabyCachedTiles + iSrc * nBlockXSize * nBlockYSize,
+                                       sizeof(szDataPointer));
+            szDataPointer[nRet] = '\0';
+            papszOptions = CSLSetNameValue(papszOptions, "DATAPOINTER", szDataPointer);
+            poMEMDS->AddBand(GDT_Byte, papszOptions);
+            if( i == 0 && nTileBands == 1 && m_poCT != NULL )
+                poMEMDS->GetRasterBand(1)->SetColorTable(m_poCT);
+            CSLDestroy(papszOptions);
+        }
+
+        if( m_eTF == GPKG_TF_PNG8 && nTileBands == 1 && nBands >= 3 )
+        {
+            GDALDataset* poMEM_RGB_DS = MEMDataset::Create("", nBlockXSize, nBlockYSize,
+                                        0, GDT_Byte, NULL);
+            for(i=0; i<3; i++)
+            {
+                char** papszOptions = NULL;
+                char szDataPointer[32];
+                int nRet = CPLPrintPointer(szDataPointer,
+                                           m_pabyCachedTiles + i * nBlockXSize * nBlockYSize,
+                                           sizeof(szDataPointer));
+                szDataPointer[nRet] = '\0';
+                papszOptions = CSLSetNameValue(papszOptions, "DATAPOINTER", szDataPointer);
+                poMEM_RGB_DS->AddBand(GDT_Byte, papszOptions);
+                CSLDestroy(papszOptions);
+            }
+
+            if( m_pabyHugeColorArray == NULL )
+            {
+                if( nBlockXSize <= 65536 / nBlockYSize )
+                    m_pabyHugeColorArray = (GByte*) VSIMalloc(MEDIAN_CUT_AND_DITHER_BUFFER_SIZE_65536);
+                else
+                    m_pabyHugeColorArray = (GByte*) VSIMalloc2(256 * 256 * 256, sizeof(GUInt32));
+            }
+
+            GDALColorTable* poCT = new GDALColorTable();
+            GDALComputeMedianCutPCTInternal( poMEM_RGB_DS->GetRasterBand(1),
+                                             poMEM_RGB_DS->GetRasterBand(2),
+                                             poMEM_RGB_DS->GetRasterBand(3),
+                                             /*NULL, NULL, NULL,*/
+                                             m_pabyCachedTiles,
+                                             m_pabyCachedTiles + nBlockXSize * nBlockYSize,
+                                             m_pabyCachedTiles + 2 * nBlockXSize * nBlockYSize,
+                                             NULL,
+                                             256, /* max colors */
+                                             8, /* bit depth */
+                                             (GUInt32*)m_pabyHugeColorArray, /* preallocated histogram */
+                                             poCT,
+                                             NULL, NULL );
+
+            GDALDitherRGB2PCTInternal( poMEM_RGB_DS->GetRasterBand(1),
+                                       poMEM_RGB_DS->GetRasterBand(2),
+                                       poMEM_RGB_DS->GetRasterBand(3),
+                                       poMEMDS->GetRasterBand(1),
+                                       poCT,
+                                       8, /* bit depth */
+                                       (GInt16*)m_pabyHugeColorArray, /* pasDynamicColorMap */
+                                       m_bDither,
+                                       NULL, NULL );
+            poMEMDS->GetRasterBand(1)->SetColorTable(poCT);
+            delete poCT;
+            GDALClose( poMEM_RGB_DS );
+        }
+        else if( nBands == 1 && m_poCT != NULL && nTileBands > 1 )
+        {
+            GByte abyCT[4*256];
+            int nEntries = MIN(256, m_poCT->GetColorEntryCount());
+            for(i=0; i<nEntries; i++)
+            {
+                const GDALColorEntry* psEntry = m_poCT->GetColorEntry(i);
+                abyCT[4*i] = (GByte)psEntry->c1;
+                abyCT[4*i+1] = (GByte)psEntry->c2;
+                abyCT[4*i+2] = (GByte)psEntry->c3;
+                abyCT[4*i+3] = (GByte)psEntry->c4;
+            }
+            for(; i<256; i++)
+            {
+                abyCT[4*i] = 0;
+                abyCT[4*i+1] = 0;
+                abyCT[4*i+2] = 0;
+                abyCT[4*i+3] = 0;
+            }
+            if( iYOff > 0 )
+            {
+                memset(m_pabyCachedTiles + 0 * nBlockXSize * nBlockYSize, 0, nBlockXSize * iYOff);
+                memset(m_pabyCachedTiles + 1 * nBlockXSize * nBlockYSize, 0, nBlockXSize * iYOff);
+                memset(m_pabyCachedTiles + 2 * nBlockXSize * nBlockYSize, 0, nBlockXSize * iYOff);
+                memset(m_pabyCachedTiles + 3 * nBlockXSize * nBlockYSize, 0, nBlockXSize * iYOff);
+            }
+            for(int iY = iYOff; iY < iYOff + iYCount; iY ++)
+            {
+                if( iXOff > 0 )
+                {
+                    i = iY * nBlockXSize;
+                    memset(m_pabyCachedTiles + 0 * nBlockXSize * nBlockYSize + i, 0, iXOff);
+                    memset(m_pabyCachedTiles + 1 * nBlockXSize * nBlockYSize + i, 0, iXOff);
+                    memset(m_pabyCachedTiles + 2 * nBlockXSize * nBlockYSize + i, 0, iXOff);
+                    memset(m_pabyCachedTiles + 3 * nBlockXSize * nBlockYSize + i, 0, iXOff);
+                }
+                for(int iX = iXOff; iX < iXOff + iXCount; iX ++)
+                {
+                    i = iY * nBlockXSize + iX;
+                    GByte byVal = m_pabyCachedTiles[i];
+                    m_pabyCachedTiles[i] = abyCT[4*byVal];
+                    m_pabyCachedTiles[i + 1 * nBlockXSize * nBlockYSize] = abyCT[4*byVal+1];
+                    m_pabyCachedTiles[i + 2 * nBlockXSize * nBlockYSize] = abyCT[4*byVal+2];
+                    m_pabyCachedTiles[i + 3 * nBlockXSize * nBlockYSize] = abyCT[4*byVal+3];
+                }
+                if( iXOff + iXCount < nBlockXSize )
+                {
+                    i = iY * nBlockXSize + iXOff + iXCount;
+                    memset(m_pabyCachedTiles + 0 * nBlockXSize * nBlockYSize + i, 0, nBlockXSize - (iXOff + iXCount));
+                    memset(m_pabyCachedTiles + 1 * nBlockXSize * nBlockYSize + i, 0, nBlockXSize - (iXOff + iXCount));
+                    memset(m_pabyCachedTiles + 2 * nBlockXSize * nBlockYSize + i, 0, nBlockXSize - (iXOff + iXCount));
+                    memset(m_pabyCachedTiles + 3 * nBlockXSize * nBlockYSize + i, 0, nBlockXSize - (iXOff + iXCount));
+                }
+            }
+            if( iYOff + iYCount < nBlockYSize )
+            {
+                i = (iYOff + iYCount) * nBlockXSize;
+                memset(m_pabyCachedTiles + 0 * nBlockXSize * nBlockYSize + i, 0, nBlockXSize * (nBlockYSize - (iYOff + iYCount)));
+                memset(m_pabyCachedTiles + 1 * nBlockXSize * nBlockYSize + i, 0, nBlockXSize * (nBlockYSize - (iYOff + iYCount)));
+                memset(m_pabyCachedTiles + 2 * nBlockXSize * nBlockYSize + i, 0, nBlockXSize * (nBlockYSize - (iYOff + iYCount)));
+                memset(m_pabyCachedTiles + 3 * nBlockXSize * nBlockYSize + i, 0, nBlockXSize * (nBlockYSize - (iYOff + iYCount)));
+            }
+        }
+
+        char** papszDriverOptions = CSLSetNameValue(NULL, "_INTERNAL_DATASET", "YES");
+        if( EQUAL(pszDriverName, "JPEG") || EQUAL(pszDriverName, "WEBP") )
+        {
+            papszDriverOptions = CSLSetNameValue(
+                                     papszDriverOptions, "QUALITY", CPLSPrintf("%d", m_nQuality));
+        }
+        else if( EQUAL(pszDriverName, "PNG") )
+        {
+            papszDriverOptions = CSLSetNameValue(
+                                     papszDriverOptions, "ZLEVEL", CPLSPrintf("%d", m_nZLevel));
+        }
+#ifdef DEBUG
+        VSIStatBufL sStat;
+        CPLAssert(VSIStatL(osMemFileName, &sStat) != 0);
+#endif
+        GDALDataset* poOutDS = poDriver->CreateCopy(osMemFileName, poMEMDS,
+                               FALSE, papszDriverOptions, NULL, NULL);
+        CSLDestroy( papszDriverOptions );
+        if( poOutDS )
+        {
+            GDALClose( poOutDS );
+            vsi_l_offset nBlobSize;
+            GByte* pabyBlob = VSIGetMemFileBuffer(osMemFileName, &nBlobSize, TRUE);
+
+            /* Create or commit and recreate transaction */
+            OGRDB2DataSource* poMainDS = m_poParentDS ? m_poParentDS : this;
+            if( poMainDS->m_nTileInsertionCount == 0 )
+            {
+                poMainDS->SoftStartTransaction();
+            }
+            else if( poMainDS->m_nTileInsertionCount == 1000 )
+            {
+                poMainDS->SoftCommitTransaction();
+                poMainDS->SoftStartTransaction();
+                poMainDS->m_nTileInsertionCount = 0;
+            }
+            poMainDS->m_nTileInsertionCount ++;
+
+/* -------------------------------------------------------------------- */
+/*      Form the INSERT command.                                        */
+/* -------------------------------------------------------------------- */
+            OGRDB2Statement oStatement( GetSession() );
+            oStatement.Appendf( "INSERT INTO %s "
+                                "(zoom_level, tile_row, tile_column, "
+                                " tile_data) VALUES (%d, %d, %d, ?)",
+                                m_osRasterTable.c_str(),
+                                m_nZoomLevel, nRow, nCol);
+
+            CPLDebug("OGRDB2DataSource::WriteTileInternal",
+                     "stmt: '%s'", oStatement.GetCommand());
+            CPL_SQLLEN  nBlobLen = (CPL_SQLLEN) nBlobSize;
+            int nRetCode = SQLBindParameter(oStatement.GetStatement(),
+                                            (SQLUSMALLINT)1,
+                                            SQL_PARAM_INPUT,
+                                            SQL_C_BINARY,
+                                            SQL_LONGVARBINARY,
+                                            MAXBLOB, 0,
+                                            (SQLPOINTER)pabyBlob,
+                                            MAXBLOB, &nBlobLen);
+
+            char* pszBytes = GByteArrayToHexString( pabyBlob, 100);
+            CPLDebug("OGRDB2DataSource::WriteTileInternal",
+                     "nBlobSize: %d; pabyBlob: %s",
+                     (int) nBlobSize, pszBytes);
+            CPLFree(pszBytes);
+            if ( !(nRetCode == SQL_SUCCESS
+                    || nRetCode == SQL_SUCCESS_WITH_INFO) )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Failure binding BLOB value,error: '%s'",
+                         GetSession()->GetLastError());
+                CPLFree(pabyBlob);
+                return CE_Failure;
+            }
+
+            if( !oStatement.ExecuteSQL() )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Failure when inserting tile (row=%d,col=%d) "
+                         "at zoom_level=%d : %s",
+                         nRow, nCol, m_nZoomLevel,
+                         GetSession()->GetLastError());
+                CPLDebug("OGRDB2DataSource::WriteTileInternal",
+                         " insert failed; '%s'",
+                         GetSession()->GetLastError() );
+                return CE_Failure;
+            }
+        }
+        eErr = CE_None;
+        VSIUnlink(osMemFileName);
+        delete poMEMDS;
+    }
+    else
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Cannot find driver %s", pszDriverName);
+    }
+    CPLDebug("OGRDB2DataSource::WriteTileInternal","exit; eErr: %d", eErr);
+    return eErr;
+}
+
+/************************************************************************/
+/*                     FlushRemainingShiftedTiles()                     */
+/************************************************************************/
+
+CPLErr OGRDB2DataSource::FlushRemainingShiftedTiles()
+{
+    CPLDebug("OGRDB2DataSource::FlushRemainingShiftedTiles","NO-OP");
+#ifdef LATER
+    if( m_hTempDB == NULL )
+        return CE_None;
+
+    for(int i=0; i<=3; i++)
+    {
+        m_asCachedTilesDesc[i].nRow = -1;
+        m_asCachedTilesDesc[i].nCol = -1;
+        m_asCachedTilesDesc[i].nIdxWithinTileData = -1;
+    }
+
+    int nBlockXSize, nBlockYSize;
+    GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
+
+    CPLString osSQL = "SELECT tile_row, tile_column, partial_flag";
+    for(int nBand = 1; nBand <= nBands; nBand++ )
+    {
+        osSQL += CPLSPrintf(", tile_data_band_%d", nBand);
+    }
+    osSQL += CPLSPrintf(" FROM partial_tiles WHERE "
+                        "zoom_level = %d AND partial_flag != 0",
+                        m_nZoomLevel);
+    const char* pszSQL = osSQL.c_str();
+
+#ifdef DEBUG_VERBOSE
+    CPLDebug("GPKG", "%s", pszSQL);
+#endif
+    sqlite3_stmt* hStmt = NULL;
+    int rc = sqlite3_prepare_v2(m_hTempDB, pszSQL, strlen(pszSQL), &hStmt, NULL);
+    if ( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "sqlite3_prepare(%s) failed: %s",
+                  pszSQL, sqlite3_errmsg( m_hTempDB ) );
+        return CE_Failure;
+    }
+
+    CPLErr eErr = CE_None;
+    int bGotPartialTiles = FALSE;
+    do
+    {
+        int rc = sqlite3_step(hStmt);
+        if ( rc == SQLITE_ROW )
+        {
+            bGotPartialTiles = TRUE;
+
+            int nRow = sqlite3_column_int(hStmt, 0);
+            int nCol = sqlite3_column_int(hStmt, 1);
+            int nPartialFlags = sqlite3_column_int(hStmt, 2);
+            for( int nBand = 1; nBand <= nBands; nBand++ )
+            {
+                if( nPartialFlags & (((1 << 4)-1) << (4*(nBand - 1))) )
+                {
+                    CPLAssert( sqlite3_column_bytes(hStmt, 2 + nBand) == nBlockXSize * nBlockYSize );
+                    memcpy( m_pabyCachedTiles + (nBand-1) * nBlockXSize * nBlockYSize,
+                            sqlite3_column_blob(hStmt, 2 + nBand),
+                            nBlockXSize * nBlockYSize );
+                }
+                else
+                {
+                    memset( m_pabyCachedTiles + (nBand-1) * nBlockXSize * nBlockYSize,
+                            0,
+                            nBlockXSize * nBlockYSize );
+                }
+            }
+
+            int nFullFlags = (1 << (4 * nBands)) - 1;
+
+            // In case the partial flags indicate that there's some quadrant
+            // missing, check in the main database if there is already a tile
+            // In which case, use the parts of that tile that aren't in the
+            // temporary database
+            if( nPartialFlags != nFullFlags )
+            {
+                char* pszNewSQL = sqlite3_mprintf("SELECT tile_data FROM '%q' "
+                                                  "WHERE zoom_level = %d AND tile_row = %d AND tile_column = %d%s",
+                                                  m_osRasterTable.c_str(), m_nZoomLevel, nRow, nCol,
+                                                  m_osWHERE.size() ? CPLSPrintf(" AND (%s)", m_osWHERE.c_str()): "");
+#ifdef DEBUG_VERBOSE
+                CPLDebug("GPKG", "%s", pszNewSQL);
+#endif
+                sqlite3_stmt* hNewStmt = NULL;
+                rc = sqlite3_prepare(GetDB(), pszNewSQL, -1, &hNewStmt, NULL);
+                if ( rc == SQLITE_OK )
+                {
+                    rc = sqlite3_step( hNewStmt );
+                    if( rc == SQLITE_ROW && sqlite3_column_type( hNewStmt, 0 ) == SQLITE_BLOB )
+                    {
+                        const int nBytes = sqlite3_column_bytes( hNewStmt, 0 );
+                        GByte* pabyRawData = (GByte*)sqlite3_column_blob( hNewStmt, 0 );
+                        CPLString osMemFileName;
+                        osMemFileName.Printf("/vsimem/gpkg_read_tile_%p", this);
+                        VSILFILE * fp = VSIFileFromMemBuffer( osMemFileName.c_str(), pabyRawData,
+                                                              nBytes, FALSE);
+                        VSIFCloseL(fp);
+
+                        int bIsLossyFormat;
+                        ReadTile(osMemFileName,
+                                 m_pabyCachedTiles + 4 * nBlockXSize * nBlockYSize,
+                                 &bIsLossyFormat);
+                        VSIUnlink(osMemFileName);
+
+                        int iYQuadrantMax = ( m_nShiftYPixelsMod ) ? 1 : 0;
+                        int iXQuadrantMax = ( m_nShiftXPixelsMod ) ? 1 : 0;
+                        for( int iYQuadrant = 0; iYQuadrant <= iYQuadrantMax; iYQuadrant ++ )
+                        {
+                            for( int iXQuadrant = 0; iXQuadrant <= iXQuadrantMax; iXQuadrant ++ )
+                            {
+                                for( int nBand = 1; nBand <= nBands; nBand ++ )
+                                {
+                                    int iQuadrantFlag = 0;
+                                    if( iXQuadrant == 0 && iYQuadrant == 0 )
+                                        iQuadrantFlag |= (1 << 0);
+                                    if( iXQuadrant == iXQuadrantMax && iYQuadrant == 0  )
+                                        iQuadrantFlag |= (1 << 1);
+                                    if( iXQuadrant == 0 && iYQuadrant == iYQuadrantMax )
+                                        iQuadrantFlag |= (1 << 2);
+                                    if( iXQuadrant == iXQuadrantMax && iYQuadrant == iYQuadrantMax )
+                                        iQuadrantFlag |= (1 << 3);
+                                    int nLocalFlag = iQuadrantFlag << (4 * (nBand - 1));
+                                    if( !(nPartialFlags & nLocalFlag) )
+                                    {
+                                        int nXOff, nYOff, nXSize, nYSize;
+                                        if( iXQuadrant == 0 && m_nShiftXPixelsMod != 0 )
+                                        {
+                                            nXOff = 0;
+                                            nXSize = m_nShiftXPixelsMod;
+                                        }
+                                        else
+                                        {
+                                            nXOff = m_nShiftXPixelsMod;
+                                            nXSize = nBlockXSize - m_nShiftXPixelsMod;
+                                        }
+                                        if( iYQuadrant == 0 && m_nShiftYPixelsMod != 0 )
+                                        {
+                                            nYOff = 0;
+                                            nYSize = m_nShiftYPixelsMod;
+                                        }
+                                        else
+                                        {
+                                            nYOff = m_nShiftYPixelsMod;
+                                            nYSize = nBlockYSize - m_nShiftYPixelsMod;
+                                        }
+                                        for( int iY = nYOff; iY < nYOff + nYSize; iY ++ )
+                                        {
+                                            memcpy( m_pabyCachedTiles + ((nBand - 1) * nBlockYSize + iY) * nBlockXSize + nXOff,
+                                                    m_pabyCachedTiles + ((4 + nBand - 1) * nBlockYSize + iY) * nBlockXSize + nXOff,
+                                                    nXSize );
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    sqlite3_finalize(hNewStmt);
+                }
+                sqlite3_free(pszNewSQL);
+            }
+
+            m_asCachedTilesDesc[0].nRow = nRow;
+            m_asCachedTilesDesc[0].nCol = nCol;
+            m_asCachedTilesDesc[0].nIdxWithinTileData = 0;
+            m_asCachedTilesDesc[0].abBandDirty[0] = TRUE;
+            m_asCachedTilesDesc[0].abBandDirty[1] = TRUE;
+            m_asCachedTilesDesc[0].abBandDirty[2] = TRUE;
+            m_asCachedTilesDesc[0].abBandDirty[3] = TRUE;
+
+            eErr = WriteTile();
+        }
+        else
+            break;
+    }
+    while( eErr == CE_None);
+
+    sqlite3_finalize(hStmt);
+
+    if( bGotPartialTiles )
+    {
+        pszSQL = CPLSPrintf("UPDATE partial_tiles SET zoom_level = %d, "
+                            "partial_flag = 0 WHERE zoom_level = %d AND partial_flag != 0",
+                            -1-m_nZoomLevel, m_nZoomLevel);
+#ifdef DEBUG_VERBOSE
+        CPLDebug("GPKG", "%s", pszSQL);
+#endif
+        SQLCommand(m_hTempDB, pszSQL);
+    }
+
+    return eErr;
+#endif
+    return CE_Failure;
+}
+
+/************************************************************************/
+/*                         WriteShiftedTile()                           */
+/************************************************************************/
+
+CPLErr OGRDB2DataSource::WriteShiftedTile(int nRow, int nCol, int nBand,
+        int nDstXOffset, int nDstYOffset,
+        int nDstXSize, int nDstYSize)
+{
+#ifdef LATER
+    CPLAssert( m_nShiftXPixelsMod || m_nShiftYPixelsMod );
+    CPLAssert( nRow >= 0 );
+    CPLAssert( nCol >= 0 );
+    CPLAssert( nRow < m_nTileMatrixHeight );
+    CPLAssert( nCol < m_nTileMatrixWidth );
+
+    if( m_hTempDB == NULL &&
+            (m_poParentDS == NULL || m_poParentDS->m_hTempDB == NULL) )
+    {
+        const char* pszBaseFilename = m_poParentDS ?
+                                      m_poParentDS->m_pszFilename : m_pszFilename;
+        m_osTempDBFilename = CPLResetExtension(pszBaseFilename, "gpkg.tmp");
+        CPLPushErrorHandler(CPLQuietErrorHandler);
+        VSIUnlink(m_osTempDBFilename);
+        CPLPopErrorHandler();
+        m_hTempDB = NULL;
+        sqlite3_open(m_osTempDBFilename, &m_hTempDB);
+        if( m_hTempDB == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Cannot create temporary database %s",
+                     m_osTempDBFilename.c_str());
+            return CE_Failure;
+        }
+        SQLCommand(m_hTempDB, "PRAGMA synchronous = OFF");
+        SQLCommand(m_hTempDB, "PRAGMA journal_mode = OFF");
+        SQLCommand(m_hTempDB, "CREATE TABLE partial_tiles("
+                   "id INTEGER PRIMARY KEY AUTOINCREMENT,"
+                   "zoom_level INTEGER NOT NULL,"
+                   "tile_column INTEGER NOT NULL,"
+                   "tile_row INTEGER NOT NULL,"
+                   "tile_data_band_1 BLOB,"
+                   "tile_data_band_2 BLOB,"
+                   "tile_data_band_3 BLOB,"
+                   "tile_data_band_4 BLOB,"
+                   "partial_flag INTEGER NOT NULL,"
+                   "UNIQUE (zoom_level, tile_column, tile_row))" );
+        SQLCommand(m_hTempDB, "CREATE INDEX partial_tiles_partial_flag_idx "
+                   "ON partial_tiles(partial_flag)");
+
+        if( m_poParentDS != NULL )
+        {
+            m_poParentDS->m_osTempDBFilename = m_osTempDBFilename;
+            m_poParentDS->m_hTempDB = m_hTempDB;
+        }
+    }
+    if( m_poParentDS != NULL )
+        m_hTempDB = m_poParentDS->m_hTempDB;
+
+    int nBlockXSize, nBlockYSize;
+    GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
+
+    int iQuadrantFlag = 0;
+    if( nDstXOffset == 0 && nDstYOffset == 0 )
+        iQuadrantFlag |= (1 << 0);
+    if( nDstXOffset + nDstXSize == nBlockXSize && nDstYOffset == 0  )
+        iQuadrantFlag |= (1 << 1);
+    if( nDstXOffset == 0 && nDstYOffset + nDstYSize == nBlockYSize )
+        iQuadrantFlag |= (1 << 2);
+    if( nDstXOffset + nDstXSize == nBlockXSize && nDstYOffset + nDstYSize == nBlockYSize )
+        iQuadrantFlag |= (1 << 3);
+    int nFlags = iQuadrantFlag << (4 * (nBand - 1));
+    int nFullFlags = (1 << (4 * nBands)) - 1;
+    int nOldFlags = 0;
+
+    for(int i=1; i<=3; i++)
+    {
+        m_asCachedTilesDesc[i].nRow = -1;
+        m_asCachedTilesDesc[i].nCol = -1;
+        m_asCachedTilesDesc[i].nIdxWithinTileData = -1;
+    }
+
+    int nExistingId = 0;
+    const char* pszSQL = CPLSPrintf("SELECT id, partial_flag, tile_data_band_%d FROM partial_tiles WHERE "
+                                    "zoom_level = %d AND tile_row = %d AND tile_column = %d",
+                                    nBand, m_nZoomLevel, nRow, nCol);
+#ifdef DEBUG_VERBOSE
+    CPLDebug("GPKG", "%s", pszSQL);
+#endif
+    sqlite3_stmt* hStmt = NULL;
+    int rc = sqlite3_prepare_v2(m_hTempDB, pszSQL, strlen(pszSQL), &hStmt, NULL);
+    if ( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "sqlite3_prepare(%s) failed: %s",
+                  pszSQL, sqlite3_errmsg( m_hTempDB ) );
+        return CE_Failure;
+    }
+
+    rc = sqlite3_step(hStmt);
+    if ( rc == SQLITE_ROW )
+    {
+        nExistingId = sqlite3_column_int(hStmt, 0);
+#ifdef DEBUG_VERBOSE
+        CPLDebug("GPKG", "Using partial_tile id=%d", nExistingId);
+#endif
+        nOldFlags = sqlite3_column_int(hStmt, 1);
+        CPLAssert(nOldFlags != 0);
+        if( (nOldFlags & (((1 << 4)-1) << (4*(nBand - 1)))) == 0 )
+        {
+            memset( m_pabyCachedTiles + (4 + nBand - 1) * nBlockXSize * nBlockYSize,
+                    0,
+                    nBlockXSize * nBlockYSize );
+        }
+        else
+        {
+            CPLAssert( sqlite3_column_bytes(hStmt, 2) == nBlockXSize * nBlockYSize );
+            memcpy( m_pabyCachedTiles + (4 + nBand - 1) * nBlockXSize * nBlockYSize,
+                    sqlite3_column_blob(hStmt, 2),
+                    nBlockXSize * nBlockYSize );
+        }
+    }
+    else
+    {
+        memset( m_pabyCachedTiles + (4 + nBand - 1) * nBlockXSize * nBlockYSize,
+                0,
+                nBlockXSize * nBlockYSize );
+    }
+    sqlite3_finalize(hStmt);
+    hStmt = NULL;
+
+    /* Copy the updated rectangle into the full tile */
+    for(int iY = nDstYOffset; iY < nDstYOffset + nDstYSize; iY ++ )
+    {
+        memcpy( m_pabyCachedTiles + (4 + nBand - 1) * nBlockXSize * nBlockYSize +
+                iY * nBlockXSize + nDstXOffset,
+                m_pabyCachedTiles + (nBand - 1) * nBlockXSize * nBlockYSize +
+                iY * nBlockXSize + nDstXOffset,
+                nDstXSize );
+    }
+
+#ifdef notdef
+    static int nCounter = 1;
+    GDALDataset* poLogDS = ((GDALDriver*)GDALGetDriverByName("GTiff"))->Create(
+                               CPLSPrintf("/tmp/partial_band_%d_%d.tif", 1, nCounter++),
+                               nBlockXSize, nBlockYSize, nBands, GDT_Byte, NULL);
+    poLogDS->RasterIO(GF_Write, 0, 0, nBlockXSize, nBlockYSize,
+                      m_pabyCachedTiles + (4 + nBand - 1) * nBlockXSize * nBlockYSize,
+                      nBlockXSize, nBlockYSize,
+                      GDT_Byte,
+                      1, NULL,
+                      0, 0, 0, NULL);
+    GDALClose(poLogDS);
+#endif
+
+    if( (nOldFlags & nFlags) != 0 )
+    {
+        CPLDebug("GPKG",
+                 "Rewriting quadrant %d of band %d of tile (row=%d,col=%d)",
+                 iQuadrantFlag, nBand, nRow, nCol);
+    }
+
+    nFlags |= nOldFlags;
+    if( nFlags == nFullFlags )
+    {
+#ifdef DEBUG_VERBOSE
+        CPLDebug("GPKG", "Got all quadrants for that tile");
+#endif
+        for( int iBand = 1; iBand <= nBands; iBand ++ )
+        {
+            if( iBand != nBand && nExistingId )
+            {
+                pszSQL = CPLSPrintf("SELECT tile_data_band_%d FROM partial_tiles WHERE "
+                                    "id = %d", iBand, nExistingId);
+#ifdef DEBUG_VERBOSE
+                CPLDebug("GPKG", "%s", pszSQL);
+#endif
+                hStmt = NULL;
+                rc = sqlite3_prepare_v2(m_hTempDB, pszSQL, strlen(pszSQL), &hStmt, NULL);
+                if ( rc != SQLITE_OK )
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined, "sqlite3_prepare(%s) failed: %s",
+                              pszSQL, sqlite3_errmsg( m_hTempDB ) );
+                    return CE_Failure;
+                }
+
+                rc = sqlite3_step(hStmt);
+                if ( rc == SQLITE_ROW )
+                {
+                    CPLAssert( sqlite3_column_bytes(hStmt, 0) == nBlockXSize * nBlockYSize );
+                    memcpy( m_pabyCachedTiles + (iBand - 1) * nBlockXSize * nBlockYSize,
+                            sqlite3_column_blob(hStmt, 0),
+                            nBlockXSize * nBlockYSize );
+                }
+                sqlite3_finalize(hStmt);
+                hStmt = NULL;
+            }
+            else
+            {
+                memcpy( m_pabyCachedTiles + (iBand - 1) * nBlockXSize * nBlockYSize,
+                        m_pabyCachedTiles + (4 + iBand - 1) * nBlockXSize * nBlockYSize,
+                        nBlockXSize * nBlockYSize );
+            }
+        }
+
+        m_asCachedTilesDesc[0].nRow = nRow;
+        m_asCachedTilesDesc[0].nCol = nCol;
+        m_asCachedTilesDesc[0].nIdxWithinTileData = 0;
+        m_asCachedTilesDesc[0].abBandDirty[0] = TRUE;
+        m_asCachedTilesDesc[0].abBandDirty[1] = TRUE;
+        m_asCachedTilesDesc[0].abBandDirty[2] = TRUE;
+        m_asCachedTilesDesc[0].abBandDirty[3] = TRUE;
+
+        pszSQL = CPLSPrintf("UPDATE partial_tiles SET zoom_level = %d, "
+                            "partial_flag = 0 WHERE id = %d",
+                            -1-m_nZoomLevel, nExistingId);
+        SQLCommand(m_hTempDB, pszSQL);
+#ifdef DEBUG_VERBOSE
+        CPLDebug("GPKG", "%s", pszSQL);
+#endif
+        return WriteTile();
+    }
+
+    if( nExistingId == 0 )
+    {
+        OGRErr err;
+        pszSQL = CPLSPrintf("SELECT id FROM partial_tiles WHERE "
+                            "partial_flag = 0 AND zoom_level = %d "
+                            "AND tile_column = %d AND tile_row = %d",
+                            -1-m_nZoomLevel, nRow, nCol);
+#ifdef DEBUG_VERBOSE
+        CPLDebug("GPKG", "%s", pszSQL);
+#endif
+        nExistingId = SQLGetInteger(m_hTempDB, pszSQL, &err);
+        if( nExistingId == 0 )
+        {
+            pszSQL = "SELECT id FROM partial_tiles WHERE partial_flag = 0 LIMIT 1";
+#ifdef DEBUG_VERBOSE
+            CPLDebug("GPKG", "%s", pszSQL);
+#endif
+            nExistingId = SQLGetInteger(m_hTempDB, pszSQL, &err);
+        }
+    }
+
+    if( nExistingId == 0 )
+    {
+        pszSQL = CPLSPrintf("INSERT INTO partial_tiles "
+                            "(zoom_level, tile_row, tile_column, tile_data_band_%d, partial_flag) VALUES (%d, %d, %d, ?, %d)",
+                            nBand, m_nZoomLevel, nRow, nCol, nFlags);
+    }
+    else
+    {
+        pszSQL = CPLSPrintf("UPDATE partial_tiles SET zoom_level = %d, "
+                            "tile_row = %d, tile_column = %d, "
+                            "tile_data_band_%d = ?, partial_flag = %d WHERE id = %d",
+                            m_nZoomLevel, nRow, nCol, nBand, nFlags, nExistingId);
+    }
+#ifdef DEBUG_VERBOSE
+    CPLDebug("GPKG", "%s", pszSQL);
+#endif
+
+    hStmt = NULL;
+    rc = sqlite3_prepare_v2(m_hTempDB, pszSQL, -1, &hStmt, NULL);
+    if ( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "failed to prepare SQL %s: %s",
+                  pszSQL, sqlite3_errmsg(m_hTempDB) );
+        return CE_Failure;
+    }
+
+    sqlite3_bind_blob( hStmt, 1,
+                       m_pabyCachedTiles + (4 + nBand - 1) * nBlockXSize * nBlockYSize,
+                       nBlockXSize * nBlockYSize,
+                       SQLITE_TRANSIENT );
+    rc = sqlite3_step( hStmt );
+    CPLErr eErr = CE_Failure;
+    if( rc == SQLITE_DONE )
+        eErr = CE_None;
+    else
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Failure when inserting partial tile (row=%d,col=%d) at zoom_level=%d : %s",
+                 nRow, nCol, m_nZoomLevel, sqlite3_errmsg(m_hTempDB));
+    }
+
+    sqlite3_finalize(hStmt);
+
+    return eErr;
+#endif
+    return CE_Failure;
+}
+
+/************************************************************************/
+/*                         IWriteBlock()                                */
+/************************************************************************/
+
+CPLErr GDALDB2RasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff,
+                                      void* pData)
+{
+    CPLDebug("GDALDB2RasterBand::IWriteBlock", "IWriteBlock(nBand=%d,nBlockXOff=%d,nBlockYOff=%d",
+             nBand,nBlockXOff,nBlockYOff);
+
+    OGRDB2DataSource* poGDS = (OGRDB2DataSource* )poDS;
+    if( !poGDS->m_bUpdate )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "IWriteBlock() not supported on dataset opened in read-only mode");
+        return CE_Failure;
+    }
+
+    if( !poGDS->m_bGeoTransformValid || poGDS->m_nSRID == UNKNOWN_SRID )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "IWriteBlock() not supported if georeferencing not set");
+        return CE_Failure;
+    }
+
+    int nRow = nBlockYOff + poGDS->m_nShiftYTiles;
+    int nCol = nBlockXOff + poGDS->m_nShiftXTiles;
+
+    int nRowMin = nRow;
+    int nRowMax = nRowMin;
+    if( poGDS->m_nShiftYPixelsMod )
+        nRowMax ++;
+
+    int nColMin = nCol;
+    int nColMax = nColMin;
+    if( poGDS->m_nShiftXPixelsMod )
+        nColMax ++;
+
+    CPLErr eErr = CE_None;
+
+    for(nRow = nRowMin; eErr == CE_None && nRow <= nRowMax; nRow ++)
+    {
+        for(nCol = nColMin; eErr == CE_None && nCol <= nColMax; nCol++ )
+        {
+            CPLDebug("GDALDB2RasterBand::IWriteBlock1",
+                    "nRow: %d,nCol: %d, height: %d, width: %d",
+                    nRow,nCol,
+                    poGDS->m_nTileMatrixHeight,poGDS->m_nTileMatrixWidth);
+             if( nRow < 0 || nCol < 0 || nRow >= poGDS->m_nTileMatrixHeight ||
+                    nCol >= poGDS->m_nTileMatrixWidth )
+            {
+                continue;
+            }
+
+            if( poGDS->m_nShiftXPixelsMod == 0
+                && poGDS->m_nShiftYPixelsMod == 0 )
+            {
+                if( !(nRow == poGDS->m_asCachedTilesDesc[0].nRow &&
+                        nCol == poGDS->m_asCachedTilesDesc[0].nCol &&
+                        poGDS->m_asCachedTilesDesc[0].nIdxWithinTileData == 0) )
+                {
+                    eErr = poGDS->WriteTile();
+
+                    poGDS->m_asCachedTilesDesc[0].nRow = nRow;
+                    poGDS->m_asCachedTilesDesc[0].nCol = nCol;
+                    poGDS->m_asCachedTilesDesc[0].nIdxWithinTileData = 0;
+                }
+            }
+
+            // Composite block data into tile, and check if all bands for this block
+            // are dirty, and if so write the tile
+            int bAllDirty = TRUE;
+            for(int iBand=1; iBand<=poGDS->nBands; iBand++)
+            {
+                GDALRasterBlock* poBlock = NULL;
+                GByte* pabySrc;
+                if( iBand == nBand )
+                {
+                    pabySrc = (GByte*)pData;
+                }
+                else
+                {
+                    if( !(poGDS->m_nShiftXPixelsMod == 0 && poGDS->m_nShiftYPixelsMod == 0) )
+                        continue;
+
+                    // If the block for this band is not dirty, it might be dirty in cache
+                    if( poGDS->m_asCachedTilesDesc[0].abBandDirty[iBand-1] )
+                        continue;
+                    else
+                    {
+                        poBlock =
+                            ((GDALDB2RasterBand*)poGDS->GetRasterBand(iBand))->
+                            TryGetLockedBlockRef(nBlockXOff, nBlockYOff);
+                        if( poBlock && poBlock->GetDirty() )
+                        {
+                            pabySrc = (GByte*)poBlock->GetDataRef(),
+                            poBlock->MarkClean();
+                        }
+                        else
+                        {
+                            if( poBlock )
+                                poBlock->DropLock();
+                            bAllDirty = FALSE;
+                            continue;
+                        }
+                    }
+                }
+
+                if( poGDS->m_nShiftXPixelsMod == 0 && poGDS->m_nShiftYPixelsMod == 0 )
+                    poGDS->m_asCachedTilesDesc[0].abBandDirty[iBand - 1] = TRUE;
+
+                int nDstXOffset = 0, nDstXSize = nBlockXSize,
+                    nDstYOffset = 0, nDstYSize = nBlockYSize;
+                int nSrcXOffset = 0, nSrcYOffset = 0;
+                // Composite block data into tile data
+                if( poGDS->m_nShiftXPixelsMod == 0 && poGDS->m_nShiftYPixelsMod == 0 )
+                {
+                    memcpy( poGDS->m_pabyCachedTiles + (iBand - 1) * nBlockXSize * nBlockYSize,
+                            pabySrc, nBlockXSize * nBlockYSize );
+                }
+                else
+                {
+                    if( nCol == nColMin )
+                    {
+                        nDstXOffset = poGDS->m_nShiftXPixelsMod;
+                        nDstXSize = nBlockXSize - poGDS->m_nShiftXPixelsMod;
+                        nSrcXOffset = 0;
+                    }
+                    else
+                    {
+                        nDstXOffset = 0;
+                        nDstXSize = poGDS->m_nShiftXPixelsMod;
+                        nSrcXOffset = nBlockXSize - poGDS->m_nShiftXPixelsMod;
+                    }
+                    if( nRow == nRowMin )
+                    {
+                        nDstYOffset = poGDS->m_nShiftYPixelsMod;
+                        nDstYSize = nBlockYSize - poGDS->m_nShiftYPixelsMod;
+                        nSrcYOffset = 0;
+                    }
+                    else
+                    {
+                        nDstYOffset = 0;
+                        nDstYSize = poGDS->m_nShiftYPixelsMod;
+                        nSrcYOffset = nBlockYSize - poGDS->m_nShiftYPixelsMod;
+                    }
+                    CPLDebug("GDALDB2RasterBand::IWriteBlock", "Copy source tile x=%d,w=%d,y=%d,h=%d into buffet at x=%d,y=%d",
+                             nDstXOffset, nDstXSize, nDstYOffset, nDstYSize, nSrcXOffset, nSrcYOffset);
+                    for( int y=0; y<nDstYSize; y++ )
+                    {
+                        GByte* pDst = poGDS->m_pabyCachedTiles + (iBand - 1) * nBlockXSize * nBlockYSize +
+                                      (y + nDstYOffset) * nBlockXSize + nDstXOffset;
+                        GByte* pSrc = pabySrc + (y + nSrcYOffset) * nBlockXSize + nSrcXOffset;
+                        GDALCopyWords(pSrc, GDT_Byte, 1,
+                                      pDst, GDT_Byte, 1,
+                                      nDstXSize);
+                    }
+                }
+
+                if( poBlock )
+                    poBlock->DropLock();
+
+                if( !(poGDS->m_nShiftXPixelsMod == 0 && poGDS->m_nShiftYPixelsMod == 0) )
+                {
+                    poGDS->m_asCachedTilesDesc[0].nRow = -1;
+                    poGDS->m_asCachedTilesDesc[0].nCol = -1;
+                    poGDS->m_asCachedTilesDesc[0].nIdxWithinTileData = -1;
+                    eErr = poGDS->WriteShiftedTile(nRow, nCol, iBand,
+                                                   nDstXOffset, nDstYOffset,
+                                                   nDstXSize, nDstYSize);
+                }
+            }
+
+            if( poGDS->m_nShiftXPixelsMod == 0 && poGDS->m_nShiftYPixelsMod == 0 )
+            {
+                if( bAllDirty )
+                {
+                    eErr = poGDS->WriteTile();
+                }
+            }
+        }
+    }
+    CPLDebug("GDALDB2RasterBand::IWriteBlock", "Exit, eErr: %d", eErr);
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                         GetOverviewCount()                           */
+/************************************************************************/
+
+int GDALDB2RasterBand::GetOverviewCount()
+{
+    OGRDB2DataSource* poGDS = (OGRDB2DataSource* )poDS;
+    return poGDS->m_nOverviewCount;
+}
+
+/************************************************************************/
+/*                         GetOverviewCount()                           */
+/************************************************************************/
+
+GDALRasterBand* GDALDB2RasterBand::GetOverview(int nIdx)
+{
+    OGRDB2DataSource* poGDS = (OGRDB2DataSource* )poDS;
+    if( nIdx < 0 || nIdx >= poGDS->m_nOverviewCount )
+        return NULL;
+    return poGDS->m_papoOverviewDS[nIdx]->GetRasterBand(nBand);
+}
+
+/************************************************************************/
+/*                        GByteArrayToHexString()                       */
+/************************************************************************/
+
+static char* GByteArrayToHexString( const GByte* pabyData, int nLen)
+{
+    char* pszTextBuf;
+
+    pszTextBuf = (char *) CPLMalloc(nLen*2+3);
+
+    int  iSrc, iDst=0;
+
+    for( iSrc = 0; iSrc < nLen; iSrc++ )
+    {
+        if( iSrc == 0 )
+        {
+            sprintf( pszTextBuf+iDst, "0x%02x", pabyData[iSrc] );
+            iDst += 4;
+        }
+        else
+        {
+            sprintf( pszTextBuf+iDst, "%02x", pabyData[iSrc] );
+            iDst += 2;
+        }
+    }
+    pszTextBuf[iDst] = 0;
+
+    return pszTextBuf;
+}
diff --git a/ogr/ogrsf_frmts/db2/makefile.vc b/ogr/ogrsf_frmts/db2/makefile.vc
new file mode 100644
index 0000000..e8bf259
--- /dev/null
+++ b/ogr/ogrsf_frmts/db2/makefile.vc
@@ -0,0 +1,14 @@
+
+
+OBJ	=	ogrdb2cli.obj gdaldb2rasterband.obj ogrdb2datasourcemd.obj ogrdb2driver.obj ogrdb2datasource.obj ogrdb2layer.obj ogrdb2tablelayer.obj ogrdb2selectlayer.obj
+
+GDAL_ROOT	=	..\..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+#EXTRAFLAGS = -I.. -I..\.. -I..\..\..\frmts\mem -DDEBUG_SQL -DDEBUG_DB2
+EXTRAFLAGS = -I.. -I..\.. -I..\..\..\frmts\mem
+default:	$(OBJ)
+
+clean:
+	-del *.obj *.pdb
diff --git a/ogr/ogrsf_frmts/db2/makeplugin.vc b/ogr/ogrsf_frmts/db2/makeplugin.vc
new file mode 100644
index 0000000..b740a1f
--- /dev/null
+++ b/ogr/ogrsf_frmts/db2/makeplugin.vc
@@ -0,0 +1,34 @@
+
+OBJ	=	ogrdb2cli.obj gdaldb2rasterband.obj ogrdb2datasourcemd.obj ogrdb2driver.obj ogrdb2datasource.obj ogrdb2layer.obj ogrdb2tablelayer.obj ogrdb2selectlayer.obj
+
+PLUGIN_DLL = ogr_DB2.dll
+
+GDAL_ROOT	=	..\..\..
+
+DB2_INC_DIR = d:\sqllib105\include
+
+DB2_LIB = d:\sqllib105\lib\Win32
+#DB2_LIB = e:\dwacode\odbc\C++\odbc32.lib
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+EXTRAFLAGS = -I.. -I..\.. -I..\..\..\frmts\mem -I$(DB2_INC_DIR) -DDB2_CLI -DDEBUG_SQL -DDEBUG_DB2
+
+default:	$(OBJ)
+
+plugin: $(PLUGIN_DLL)
+
+$(PLUGIN_DLL):	$(OBJ)
+	link /dll /out:$(PLUGIN_DLL) $(OBJ) $(GDALLIB) $(DB2_LIB)
+	if exist $(PLUGIN_DLL).manifest mt -manifest $(PLUGIN_DLL).manifest -outputresource:$(PLUGIN_DLL);2
+
+clean:
+	-del *.lib
+	-del *.obj *.pdb *.exp
+	-del *.exe
+	-del *.dll
+	-del *.manifest
+
+plugin-install:
+	-mkdir $(PLUGINDIR)
+	$(INSTALL) $(PLUGIN_DLL) $(PLUGINDIR)
diff --git a/ogr/ogrsf_frmts/db2/ogr_db2.h b/ogr/ogrsf_frmts/db2/ogr_db2.h
new file mode 100644
index 0000000..52e37fc
--- /dev/null
+++ b/ogr/ogrsf_frmts/db2/ogr_db2.h
@@ -0,0 +1,911 @@
+/*****************************************************************************
+ *
+ * Project:  DB2 Spatial driver
+ * Purpose:  Definition of classes for OGR DB2 Spatial driver.
+ * Author:   David Adler, dadler at adtechgeospatial dot com
+ *
+ *****************************************************************************
+ * Copyright (c) 2010, Tamas Szekeres
+ * Copyright (c) 2015, David Adler
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef OGR_DB2_H_INCLUDED
+#define OGR_DB2_H_INCLUDED
+#ifdef DB2_CLI
+#include <sqlcli1.h>   // needed for CLI support
+#endif
+#include "ogrsf_frmts.h"
+#include "cpl_port.h"
+#include "cpl_error.h"
+#include "gdal_pam.h"
+#include "gdalwarper.h"
+#include <time.h>
+
+#ifdef WIN32
+#  include <windows.h>
+#endif
+
+#ifndef DB2_CLI
+#include <sql.h>
+#include <sqlext.h>
+#endif
+#include <odbcinst.h>
+#include "cpl_string.h"
+
+// Map ODBC handles to DB2 CLI handles
+#ifndef HDBC
+#define HDBC SQLHDBC
+#define HSTMT SQLHSTMT
+#define HENV SQLHENV
+#endif
+
+#ifdef PATH_MAX
+#  define ODBC_FILENAME_MAX PATH_MAX
+#else
+#  define ODBC_FILENAME_MAX (255 + 1) /* Max path length */
+#endif
+
+class OGRDB2DataSource;
+
+#ifdef DEBUG_SQL
+#define DB2_DEBUG_SQL(ogrdb2fn,ogrdb2stmt) \
+              CPLDebug(ogrdb2fn, "stmt: '%s'", ogrdb2stmt.GetCommand());
+#else
+#define DB2_DEBUG_SQL(ogrdb2fn,ogrdb2stmt)
+#endif
+
+#ifdef DEBUG_DB2
+#define DB2_DEBUG_ENTER(ogrdb2fn) \
+            CPLDebug(ogrdb2fn,"Entering");
+
+#define DB2_DEBUG_EXIT(ogrdb2fn) \
+            CPLDebug(ogrdb2fn,"Exiting");
+
+#else
+#define DB2_DEBUG_ENTER(ogrdb2fn)
+#define DB2_DEBUG_EXIT(ogrdb2fn)
+#endif
+
+
+#define DB2ODBC_PREFIX "DB2ODBC:"
+
+#define UNKNOWN_SRID   -2
+#define DEFAULT_SRID    0
+
+// LATER - not sure what the maximum blob size should be
+#define MAXBLOB 1000000
+
+class GDALDB2RasterBand;
+class OGRDB2TableLayer;
+
+typedef struct
+{
+    int     nRow;
+    int     nCol;
+    int     nIdxWithinTileData;
+    int     abBandDirty[4];
+} CachedTileDesc;
+
+typedef enum
+{
+    GPKG_TF_PNG_JPEG,
+    GPKG_TF_PNG,
+    GPKG_TF_PNG8,
+    GPKG_TF_JPEG,
+    GPKG_TF_WEBP
+} GPKGTileFormat;
+
+/* On MSVC SQLULEN is missing in some cases (i.e. VC6)
+** but it is always a #define so test this way.   On Unix
+** it is a typedef so we can't always do this.
+*/
+#if defined(_MSC_VER) && !defined(SQLULEN) && !defined(_WIN64)
+#  define MISSING_SQLULEN
+#endif
+
+#if !defined(MISSING_SQLULEN)
+/* ODBC types to support 64 bit compilation */
+#  define CPL_SQLULEN SQLULEN
+#  define CPL_SQLLEN  SQLLEN
+#else
+#  define CPL_SQLULEN SQLUINTEGER
+#  define CPL_SQLLEN  SQLINTEGER
+#endif	/* ifdef SQLULEN */
+
+
+/**
+ * A class representing an ODBC database session.
+ *
+ * Includes error collection services.
+ *
+ * Copied from cpl_odbc.h - to resolve issue with needing to include
+ * different header files for ODBC and CLI.
+ */
+
+/************************************************************************/
+/*                             OGRDB2Session                            */
+/************************************************************************/
+
+class OGRDB2Session
+{
+protected:
+// From CPLODBCSession
+    char      m_szLastError[SQL_MAX_MESSAGE_LENGTH + 1];
+    HENV      m_hEnv;
+    HDBC      m_hDBC;
+    int       m_bInTransaction;
+    int       m_bAutoCommit;
+
+public:
+    OGRDB2Session( );
+    ~OGRDB2Session();
+// From CPLODBCSession
+    int         EstablishSession( const char *pszDSN,
+                                  const char *pszUserid,
+                                  const char *pszPassword );
+    const char  *GetLastError();
+
+    // Transaction handling
+
+    int         ClearTransaction();
+    int         BeginTransaction();
+    int         CommitTransaction();
+    virtual int RollbackTransaction();
+    int         IsInTransaction() { return m_bInTransaction; }
+
+    // Essentially internal.
+
+    int         CloseSession();
+
+    int         Failed( int, HSTMT = NULL );
+    HDBC        GetConnection() { return m_hDBC; }
+    HENV        GetEnvironment()  { return m_hEnv; }
+};
+
+/**
+ * Abstraction for statement, and resultset.
+ *
+ * Includes methods for executing an SQL statement, and for accessing the
+ * resultset from that statement.  Also provides for executing other ODBC
+ * requests that produce results sets such as SQLColumns() and SQLTables()
+ * requests.
+ *
+ * Copied from cpl_odbc.h - to resolve issue with needing to include
+ * different header files for ODBC and CLI
+ */
+
+/************************************************************************/
+/*                             OGRDB2Statement                          */
+/************************************************************************/
+
+class OGRDB2Statement
+{
+protected:
+    int             m_nLastRetCode;
+    int             m_bPrepared;
+// From CPLODBCStatement
+    OGRDB2Session     *m_poSession;
+    HSTMT               m_hStmt;
+
+    SQLSMALLINT    m_nColCount;
+    char         **m_papszColNames;
+    SQLSMALLINT   *m_panColType;
+    char         **m_papszColTypeNames;
+    CPL_SQLULEN      *m_panColSize;
+    SQLSMALLINT   *m_panColPrecision;
+    SQLSMALLINT   *m_panColNullable;
+    char         **m_papszColColumnDef;
+
+    char         **m_papszColValues;
+    CPL_SQLLEN       *m_panColValueLengths;
+
+
+
+    char          *m_pszStatement;
+    size_t         m_nStatementMax;
+    size_t         m_nStatementLen;
+public:
+    OGRDB2Statement( OGRDB2Session * );
+    OGRDB2Statement( );
+    ~OGRDB2Statement();
+    int             DB2Execute(const char *pszCallingFunction);
+    int             DB2Prepare(const char *pszCallingFunction);
+    int             GetLastRetCode() {
+        return m_nLastRetCode;
+    };
+    int             DB2BindParameterIn(const char *pszCallingFunction,
+                                            int nBindNum,
+                                            int nValueType,
+                                            int nParameterType,
+                                            int nLen,
+                                            void * pValuePointer);
+
+// From CPLODBCStatement
+    HSTMT          GetStatement() { return m_hStmt; }
+    int            Failed( int );
+    // Command buffer related.
+    void           Clear();
+    void           AppendEscaped( const char * );
+    void           Append( const char * );
+    void           Append( int );
+    void           Append( double );
+    int            Appendf( const char *, ... ) CPL_PRINT_FUNC_FORMAT (2, 3);
+    const char    *GetCommand() { return m_pszStatement; }
+
+    int            ExecuteSQL( const char * = NULL );
+
+    // Results fetching
+    int            Fetch( int nOrientation = SQL_FETCH_NEXT,
+                          int nOffset = 0 );
+    void           ClearColumnData();
+
+    int            GetColCount();
+    const char    *GetColName( int );
+    short          GetColType( int );
+    const char    *GetColTypeName( int );
+    short          GetColSize( int );
+    short          GetColPrecision( int );
+    short          GetColNullable( int );
+    const char    *GetColColumnDef( int );
+
+    int            GetColId( const char * );
+    const char    *GetColData( int, const char * = NULL );
+    const char    *GetColData( const char *, const char * = NULL );
+    int            GetColDataLength( int );
+    int            GetRowCountAffected();
+
+    // Fetch special metadata.
+    int            GetColumns( const char *pszTable,
+                               const char *pszCatalog = NULL,
+                               const char *pszSchema = NULL );
+    int            GetPrimaryKeys( const char *pszTable,
+                                   const char *pszCatalog = NULL,
+                                   const char *pszSchema = NULL );
+
+    int            GetTables( const char *pszCatalog = NULL,
+                              const char *pszSchema = NULL );
+
+    void           DumpResult( FILE *fp, int bShowSchema = FALSE );
+
+    static CPLString GetTypeName( int );
+    static SQLSMALLINT GetTypeMapping( SQLSMALLINT );
+
+    int            CollectResultsInfo();
+};
+
+/************************************************************************/
+/*                         OGRDB2AppendEscaped( )                       */
+/************************************************************************/
+
+void OGRDB2AppendEscaped( OGRDB2Statement* poStatement,
+                          const char* pszStrValue);
+
+
+
+
+/************************************************************************/
+/*                             OGRDB2Layer                              */
+/************************************************************************/
+
+class OGRDB2Layer : public OGRLayer
+{
+protected:
+    OGRDB2DataSource *m_poDS; // GPKG - where set?
+    OGRFeatureDefn     *poFeatureDefn;
+
+    OGRDB2Statement   *m_poStmt;
+
+    OGRDB2Statement   *m_poPrepStmt;
+
+    // Layer spatial reference system, and srid.
+    OGRSpatialReference *poSRS;
+    int                 nSRSId;
+
+    GIntBig            iNextShapeId;
+
+    OGRDB2DataSource   *poDS;
+
+    char               *pszGeomColumn;
+    char               *pszFIDColumn;
+
+    int                bIsIdentityFid;
+    char               cGenerated;// 'A' always generated, 'D' default,' ' not
+    int                nLayerStatus;
+    int                *panFieldOrdinals;
+
+    CPLErr             BuildFeatureDefn( const char *pszLayerName,
+                                         OGRDB2Statement *poStmt );
+
+    virtual OGRDB2Statement *  GetStatement() {
+        return m_poStmt;
+    }
+
+public:
+    OGRDB2Layer();
+    virtual             ~OGRDB2Layer();
+
+    virtual void        ResetReading();
+    virtual OGRFeature *GetNextRawFeature();
+    virtual OGRFeature *GetNextFeature();
+
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+
+    virtual OGRFeatureDefn *GetLayerDefn() {
+        return poFeatureDefn;
+    }
+
+    virtual OGRSpatialReference *GetSpatialRef();
+
+    virtual OGRErr     StartTransaction();
+    virtual OGRErr     CommitTransaction();
+    virtual OGRErr     RollbackTransaction();
+
+    virtual const char *GetFIDColumn();
+    virtual const char *GetGeometryColumn();
+
+    virtual int         TestCapability( const char * );
+    char*               GByteArrayToHexString( const GByte* pabyData,
+            int nLen);
+
+    void               SetLayerStatus( int nStatus ) {
+        nLayerStatus = nStatus;
+    }
+    int                GetLayerStatus() {
+        return nLayerStatus;
+    }
+    int                GetSRSId() {
+        return nSRSId;
+    }
+};
+
+/************************************************************************/
+/*                       OGRDB2TableLayer                               */
+/************************************************************************/
+
+class OGRDB2TableLayer : public OGRDB2Layer
+{
+    int                 bUpdateAccess;
+    int                 bLaunderColumnNames;
+    int                 bPreservePrecision;
+    int                 bNeedSpatialIndex;
+
+    int                 nUploadGeometryFormat;
+    char                *m_pszQuery;
+
+    void                ClearStatement();
+    OGRDB2Statement* BuildStatement(const char* pszColumns);
+    void                FreeBindBuffer(int nBindNum, void **bind_buffer);
+    CPLString BuildFields();
+
+    virtual OGRDB2Statement *  GetStatement();
+
+    char               *pszTableName;
+    char               *m_pszLayerName;
+    char               *pszSchemaName;
+
+    OGRwkbGeometryType eGeomType;
+
+// From GPKG
+    char*                       m_pszTableName;
+    int                         m_iSrs;
+    OGREnvelope*                m_poExtent;
+    CPLString                   m_soColumns;
+    CPLString                   m_soFilter;
+    CPLString                   osQuery;
+    OGRBoolean                  m_bExtentChanged;
+
+    int                         m_bInsertStatementWithFID;
+
+    int                         bDeferredSpatialIndexCreation;
+    int                         m_bHasSpatialIndex;
+    int                         bDropRTreeTable;
+    int                         m_anHasGeometryExtension[wkbMultiSurface+1];
+    int                         m_bPreservePrecision;
+    int                         m_bTruncateFields;
+    int                         m_bDeferredCreation;
+    int                         m_iFIDAsRegularColumnIndex;
+
+    CPLString                   m_osIdentifierLCO;
+    CPLString                   m_osDescriptionLCO;
+    int                         m_bHasReadMetadataFromStorage;
+    OGRErr              RegisterGeometryColumn();
+    void                BuildWhere(void);
+//    OGRErr              SyncToDisk();
+
+    OGRErr              BindFieldValue(OGRDB2Statement *poStatement,
+                                       OGRFeature* poFeature, int i,
+                                       int nBindNum, void **papBindBuffer);
+
+public:
+    OGRDB2TableLayer( OGRDB2DataSource * );
+    ~OGRDB2TableLayer();
+
+    CPLErr              Initialize( const char *pszSchema,
+                                    const char *pszTableName,
+                                    const char *pszGeomCol,
+                                    int nCoordDimension,
+                                    int nSRId,
+                                    const char *pszSRText,
+                                    OGRwkbGeometryType eType);
+    OGRErr              isFieldTypeSupported( OGRFieldType nFieldType );
+    OGRErr              CreateSpatialIndex();
+    void                DropSpatialIndex();
+
+    virtual void        ResetReading();
+    virtual GIntBig         GetFeatureCount( int );
+
+    virtual OGRFeatureDefn *GetLayerDefn();
+
+    virtual const char* GetName();
+
+    virtual OGRErr      SetAttributeFilter( const char * );
+
+    virtual OGRErr      ISetFeature( OGRFeature *poFeature );
+    virtual OGRErr      DeleteFeature( GIntBig nFID );
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
+    virtual OGRErr      PrepareFeature( OGRFeature *poFeature, char cType );
+
+    const char*         GetTableName() {
+        return pszTableName;
+    }
+    const char*         GetLayerName() {
+        return m_pszLayerName;
+    }
+    const char*         GetSchemaName() {
+        return pszSchemaName;
+    }
+
+    virtual OGRErr      CreateField( OGRFieldDefn *poField,
+                                     int bApproxOK = TRUE );
+
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+
+    virtual int         TestCapability( const char * );
+
+    void                SetLaunderFlag( int bFlag )
+    {
+        bLaunderColumnNames = bFlag;
+    }
+    void                SetPrecisionFlag( int bFlag )
+    {
+        bPreservePrecision = bFlag;
+    }
+    void                SetSpatialIndexFlag( int bFlag )
+    {
+        bNeedSpatialIndex = bFlag;
+    }
+
+    int                 FetchSRSId();
+    void                CreateSpatialIndexIfNecessary();
+
+    int                 DropSpatialIndex(int bCalledFromSQLFunction = FALSE);
+    /*
+        virtual char **     GetMetadata( const char *pszDomain = NULL );
+        virtual const char *GetMetadataItem( const char * pszName,
+                                             const char * pszDomain = "" );
+        virtual char **     GetMetadataDomainList();
+
+        virtual CPLErr      SetMetadata( char ** papszMetadata,
+                                         const char * pszDomain = "" );
+        virtual CPLErr      SetMetadataItem( const char * pszName,
+                                             const char * pszValue,
+                                             const char * pszDomain = "" );
+
+        void                RenameTo(const char* pszDstTableName);
+
+        virtual int          HasFastSpatialFilter(int iGeomCol);
+        virtual CPLString    GetSpatialWhere(int iGeomCol,
+                                             OGRGeometry* poFilterGeom);
+
+        int                 HasSpatialIndex();
+        void                SetTruncateFieldsFlag( int bFlag )
+        {
+            m_bTruncateFields = bFlag;
+        }
+
+        OGRErr              ReadTableDefinition(int bIsSpatial);
+        void                SetCreationParameters( OGRwkbGeometryType eGType,
+                const char* pszGeomColumnName,
+                int bGeomNullable,
+                OGRSpatialReference* poSRS,
+                const char* pszFIDColumnName,
+                const char* pszIdentifier,
+                const char* pszDescription );
+    */
+    OGRErr              RunDeferredCreationIfNecessary();
+    /************************************************************************/
+    /* GPKG methods */
+
+private:
+
+    OGRErr              UpdateExtent( const OGREnvelope *poExtent );
+    OGRErr              SaveExtent();
+    OGRErr              BuildColumns();
+    OGRBoolean          IsGeomFieldSet( OGRFeature *poFeature );
+    void                CheckUnknownExtensions();
+    int                 CreateGeometryExtensionIfNecessary(
+                                OGRwkbGeometryType eGType);
+
+};
+
+/************************************************************************/
+/*                      OGRDB2SelectLayer                      */
+/************************************************************************/
+
+class OGRDB2SelectLayer : public OGRDB2Layer
+{
+    char                *pszBaseStatement;
+
+    void                ClearStatement();
+    OGRErr              ResetStatement();
+
+    virtual OGRDB2Statement *  GetStatement();
+
+public:
+    OGRDB2SelectLayer( OGRDB2DataSource *,
+                       OGRDB2Statement * );
+    ~OGRDB2SelectLayer();
+
+    virtual void        ResetReading();
+    virtual GIntBig     GetFeatureCount( int );
+
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+
+    virtual int         TestCapability( const char * );
+};
+
+/************************************************************************/
+/*                           OGRDB2DataSource                           */
+/************************************************************************/
+
+class OGRDB2DataSource : public GDALPamDataset
+{
+    friend class GDALDB2RasterBand;
+    friend class OGRDB2TableLayer;
+
+// Utility stuff
+    double              clock1, clock2;
+    time_t              time1, time2;
+    double              dtime;
+    double              dclock;
+    char                stime[256];
+    double              getDTime();
+
+    char                **m_papszTableNames;
+    char                **m_papszSchemaNames;
+    char                **m_papszGeomColumnNames;
+    char                **m_papszCoordDimensions;
+    char                **m_papszSRIds;
+    char                **m_papszSRTexts;
+    char                *m_pszFilename;
+    int                 m_bIsVector;
+
+    OGRDB2TableLayer    **papoLayers;
+    OGRDB2TableLayer    **m_papoLayers;    //DWA
+
+    char               *m_pszName;
+
+    char               *m_pszCatalog;
+    int                 m_bIsZ;
+    int                 bDSUpdate;
+    OGRDB2Session       m_oSession;
+
+    int                 bUseGeometryColumns;
+
+    int                 bListAllTables;
+    int                 m_bHasMetadataTables;
+    // We maintain a list of known SRID to reduce the number of trips to
+    // the database to get SRSes.
+    int                 m_nKnownSRID;
+    int                *m_panSRID;
+    OGRSpatialReference **m_papoSRS;
+//***************** For raster support
+    int                 m_bUpdate;
+    int                 m_nLayers;
+    int                 m_bUtf8;
+    void                CheckUnknownExtensions(int bCheckRasterTable = FALSE);
+
+    int                 m_bNew;
+
+    CPLString           m_osRasterTable;
+    CPLString           m_osIdentifier;
+    int                 m_bIdentifierAsCO;
+    CPLString           m_osDescription;
+    int                 m_bDescriptionAsCO;
+    int                 m_bHasReadMetadataFromStorage;
+    int                 m_bMetadataDirty;
+    char              **m_papszSubDatasets;
+    char               *m_pszProjection;
+    int                 m_bRecordInsertedInGPKGContent;
+    int                 m_bGeoTransformValid;
+    double              m_adfGeoTransform[6];
+    int                 m_nSRID;
+    double              m_dfTMSMinX;
+    double              m_dfTMSMaxY;
+    int                 m_nZoomLevel;
+    GByte              *m_pabyCachedTiles;
+    CachedTileDesc      m_asCachedTilesDesc[4];
+    int                 m_nShiftXTiles;
+    int                 m_nShiftXPixelsMod;
+    int                 m_nShiftYTiles;
+    int                 m_nShiftYPixelsMod;
+    int                 m_nTileMatrixWidth;
+    int                 m_nTileMatrixHeight;
+
+    GPKGTileFormat      m_eTF;
+    int                 m_nZLevel;
+    int                 m_nQuality;
+    int                 m_bDither;
+
+    GDALColorTable*     m_poCT;
+    int                 m_bTriedEstablishingCT;
+    GByte*              m_pabyHugeColorArray;
+
+    OGRDB2DataSource* m_poParentDS;
+    int                 m_nOverviewCount;
+    OGRDB2DataSource** m_papoOverviewDS;
+    int                 m_bZoomOther;
+
+    CPLString           m_osWHERE;
+
+    int                 m_hTempDB;  //LATER - flag that partial_tiles exists
+    CPLString           m_osTempDBFilename;
+
+    int                 m_bInFlushCache;
+
+    int                 m_nTileInsertionCount;
+
+    CPLString           m_osTilingScheme;
+
+    void            ComputeTileAndPixelShifts();
+    int             InitRaster ( OGRDB2DataSource* poParentDS,
+                                 const char* pszTableName,
+                                 double dfMinX,
+                                 double dfMinY,
+                                 double dfMaxX,
+                                 double dfMaxY,
+                                 const char* pszContentsMinX,
+                                 const char* pszContentsMinY,
+                                 const char* pszContentsMaxX,
+                                 const char* pszContentsMaxY,
+                                 char** papszOpenOptions,
+                                 OGRDB2Statement* oStmt,
+                                 int nIdxInResult );
+    int             InitRaster ( OGRDB2DataSource* poParentDS,
+                                 const char* pszTableName,
+                                 int nZoomLevel,
+                                 int nBandCount,
+                                 double dfTMSMinX,
+                                 double dfTMSMaxY,
+                                 double dfPixelXSize,
+                                 double dfPixelYSize,
+                                 int nTileWidth,
+                                 int nTileHeight,
+                                 int nTileMatrixWidth,
+                                 int nTileMatrixHeight,
+                                 double dfGDALMinX,
+                                 double dfGDALMinY,
+                                 double dfGDALMaxX,
+                                 double dfGDALMaxY );
+
+    int     OpenRaster( const char* pszTableName,
+                        const char* pszIdentifier,
+                        const char* pszDescription,
+                        int nSRSId,
+                        double dfMinX,
+                        double dfMinY,
+                        double dfMaxX,
+                        double dfMaxY,
+                        const char* pszContentsMinX,
+                        const char* pszContentsMinY,
+                        const char* pszContentsMaxX,
+                        const char* pszContentsMaxY,
+                        char** papszOptions );
+    CPLErr   FinalizeRasterRegistration();
+
+    CPLErr                  ReadTile(const CPLString& osMemFileName,
+                                     GByte* pabyTileData,
+                                     int* pbIsLossyFormat = NULL);
+    GByte*                  ReadTile(int nRow, int nCol);
+    GByte*                  ReadTile(int nRow, int nCol, GByte* pabyData,
+                                     int* pbIsLossyFormat = NULL);
+
+    int                     m_bInWriteTile;
+    CPLErr                  WriteTile();
+
+    CPLErr                  WriteTileInternal();
+    CPLErr                  FlushRemainingShiftedTiles();
+    CPLErr                  WriteShiftedTile(int nRow, int nCol, int iBand,
+            int nDstXOffset, int nDstYOffset,
+            int nDstXSize, int nDstYSize);
+
+    int                     RegisterWebPExtension();
+    int                     RegisterZoomOtherExtension();
+    void                    ParseCompressionOptions(char** papszOptions);
+
+    int                     HasMetadataTables();
+    int                     CreateMetadataTables();
+    const char*             CheckMetadataDomain( const char* pszDomain );
+    void                    WriteMetadata(CPLXMLNode* psXMLNode,
+                                          const char* pszTableName);
+    CPLErr                  FlushMetadata();
+
+//***************** For raster support
+
+public:
+    OGRDB2DataSource();
+    ~OGRDB2DataSource();
+//***************** For raster support
+
+    virtual char **     GetMetadata( const char *pszDomain = NULL );
+    virtual const char *GetMetadataItem( const char * pszName,
+                                         const char * pszDomain = "" );
+    virtual char **     GetMetadataDomainList();
+    virtual CPLErr      SetMetadata( char ** papszMetadata,
+                                     const char * pszDomain = "" );
+    virtual CPLErr      SetMetadataItem( const char * pszName,
+                                         const char * pszValue,
+                                         const char * pszDomain = "" );
+    CPLErr              FlushCacheWithErrCode();
+
+
+    virtual const char* GetProjectionRef();
+    virtual CPLErr      SetProjection( const char* pszProjection );
+
+    virtual CPLErr      GetGeoTransform( double* padfGeoTransform );
+    virtual CPLErr      SetGeoTransform( double* padfGeoTransform );
+
+
+
+    virtual CPLErr      IBuildOverviews( const char *, int, int *,
+                                         int, int *,
+                                         GDALProgressFunc, void * );
+
+    OGRErr              CreateGDALAspatialExtension();
+    void                SetMetadataDirty() {
+        m_bMetadataDirty = TRUE;
+    }
+    /*
+    */
+    OGRErr              CreateExtensionsTableIfNecessary();
+    int                 HasExtensionsTable();
+    virtual void        FlushCache();
+    static GDALDataset* CreateCopy( const char *pszFilename,
+                                    GDALDataset *poSrcDS,
+                                    int bStrict,
+                                    char ** papszOptions,
+                                    GDALProgressFunc pfnProgress,
+                                    void * pProgressData );
+//*****************
+
+    int                 DeleteLayer( OGRDB2TableLayer * poLayer );
+    const char          *GetCatalog() {
+        return m_pszCatalog;
+    }
+
+    int                 ParseValue(char** pszValue, char* pszSource,
+                                   const char* pszKey,
+                                   int nStart, int nNext, int nTerm,
+                                   int bRemove);
+
+    int                 Open(GDALOpenInfo* poOpenInfo);
+    int                 Create( const char * pszFilename,
+                                int nXSize,
+                                int nYSize,
+                                int nBands,
+                                GDALDataType eDT,
+                                char **papszOptions );
+    int                 Open( const char *, int bTestOpen );
+    int                 OpenTable( const char *pszSchemaName,
+                                   const char *pszTableName,
+                                   const char *pszGeomCol,
+                                   int nCoordDimension,
+                                   int nSRID, const char *pszSRText,
+                                   OGRwkbGeometryType eType);
+
+    const char          *GetName() {
+        return m_pszName;
+    }
+    int                 GetLayerCount();
+    OGRLayer            *GetLayer( int );
+    OGRLayer            *GetLayerByName( const char* pszLayerName );
+
+    int                 UseGeometryColumns() {
+        return bUseGeometryColumns;
+    }
+
+    virtual int         DeleteLayer( int iLayer );
+    virtual OGRLayer    *ICreateLayer( const char *,
+                                       OGRSpatialReference * = NULL,
+                                       OGRwkbGeometryType = wkbUnknown,
+                                       char ** = NULL );
+
+    int                 TestCapability( const char * );
+
+    virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
+                                    OGRGeometry *poSpatialFilter,
+                                    const char *pszDialect );
+    virtual void        ReleaseResultSet( OGRLayer * poLayer );
+
+    char                *LaunderName( const char *pszSrcName );
+    char                *ToUpper( const char *pszSrcName );
+    OGRErr              InitializeMetadataTables();
+
+    OGRSpatialReference* FetchSRS( int nId );
+    int                 FetchSRSId( OGRSpatialReference * poSRS );
+
+    OGRErr              StartTransaction(CPL_UNUSED int bForce);
+    OGRErr              CommitTransaction();
+    OGRErr              RollbackTransaction();
+    OGRErr              SoftStartTransaction();
+    OGRErr              SoftCommitTransaction();
+    OGRErr              SoftRollbackTransaction();
+    // Internal use
+    OGRDB2Session     *GetSession() {
+        return &m_oSession;
+    }
+    int                 InitializeSession( const char * pszNewName,
+                                           int bTestOpen );
+
+
+};
+
+/************************************************************************/
+/*                             OGRDB2Driver                             */
+/************************************************************************/
+
+class OGRDB2Driver : public GDALDriver
+{
+public:
+    ~OGRDB2Driver();
+};
+
+/************************************************************************/
+/*                        GDALDB2RasterBand                             */
+/************************************************************************/
+
+class GDALDB2RasterBand: public GDALPamRasterBand
+{
+public:
+
+    GDALDB2RasterBand(OGRDB2DataSource* poDS,
+                      int nBand,
+                      int nTileWidth, int nTileHeight);
+
+    virtual CPLErr          IReadBlock(int nBlockXOff, int nBlockYOff,
+                                       void* pData);
+    virtual CPLErr          IWriteBlock(int nBlockXOff, int nBlockYOff,
+                                        void* pData);
+    virtual CPLErr          FlushCache();
+
+    virtual GDALColorTable* GetColorTable();
+    virtual CPLErr          SetColorTable(GDALColorTable* poCT);
+
+    virtual GDALColorInterp GetColorInterpretation();
+    virtual CPLErr          SetColorInterpretation( GDALColorInterp );
+
+    virtual int             GetOverviewCount();
+    virtual GDALRasterBand* GetOverview(int nIdx);
+    char*           GByteArrayToHexString( const GByte* pabyData, int nLen);
+};
+#endif /* ndef OGR_DB2_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/db2/ogrdb2cli.cpp b/ogr/ogrsf_frmts/db2/ogrdb2cli.cpp
new file mode 100644
index 0000000..c5dd92c
--- /dev/null
+++ b/ogr/ogrsf_frmts/db2/ogrdb2cli.cpp
@@ -0,0 +1,1849 @@
+/*****************************************************************************
+ *
+ * Project:  DB2 Spatial driver
+ * Purpose:  Implements DB2-specific SQL support.
+ * Author:   David Adler, dadler at adtechgeospatial dot com
+ *
+ *****************************************************************************
+ * Copyright (c) 2015, David Adler
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_conv.h"
+#include "ogr_db2.h"
+
+// From cpl_odbc.cpp
+#include "cpl_vsi.h"
+#include "cpl_string.h"
+#include "cpl_error.h"
+
+#ifndef SQLColumns_TABLE_CAT
+#define SQLColumns_TABLE_CAT 1
+#define SQLColumns_TABLE_SCHEM 2
+#define SQLColumns_TABLE_NAME 3
+#define SQLColumns_COLUMN_NAME 4
+#define SQLColumns_DATA_TYPE 5
+#define SQLColumns_TYPE_NAME 6
+#define SQLColumns_COLUMN_SIZE 7
+#define SQLColumns_BUFFER_LENGTH 8
+#define SQLColumns_DECIMAL_DIGITS 9
+#define SQLColumns_NUM_PREC_RADIX 10
+#define SQLColumns_NULLABLE 11
+#define SQLColumns_REMARKS 12
+#define SQLColumns_COLUMN_DEF 13
+#define SQLColumns_SQL_DATA_TYPE 14
+#define SQLColumns_SQL_DATETIME_SUB 15
+#define SQLColumns_CHAR_OCTET_LENGTH 16
+#define SQLColumns_ORDINAL_POSITION 17
+#define SQLColumns_IS_NULLABLE 18
+#endif /* ndef SQLColumns_TABLE_CAT */
+
+// Most of the code here is copied from cpl_odbc.cpp
+// This was done to resolve issues with different header files
+// for MS ODBC and DB2 CLI.
+
+/************************************************************************/
+/*                          OGRDB2Session()                          */
+/************************************************************************/
+
+OGRDB2Session::OGRDB2Session()
+
+{
+    DB2_DEBUG_ENTER("OGRDB2Session::OGRDB2Session");
+    m_szLastError[0] = '\0';
+    m_hEnv = NULL;
+    m_hDBC = NULL;
+    m_bInTransaction = FALSE;
+    m_bAutoCommit = TRUE;
+}
+
+/************************************************************************/
+/*                         ~OGRDB2Session()                          */
+/************************************************************************/
+
+OGRDB2Session::~OGRDB2Session()
+
+{
+    DB2_DEBUG_ENTER("OGRDB2Session::~OGRDB2Session");
+    CloseSession();
+}
+
+
+/************************************************************************/
+/*                       RollbackTransaction()                          */
+/************************************************************************/
+// Override parent method, don't invoke Fail() which clears the message
+int OGRDB2Session::RollbackTransaction()
+{
+    DB2_DEBUG_ENTER("OGRDB2Session::RollbackTransaction");
+
+    if (m_bInTransaction)
+    {
+        m_bInTransaction = FALSE;
+        CPLDebug("OGRDB2Session::RollbackTransaction", "In transaction, rollback");
+        if( SQLEndTran( SQL_HANDLE_DBC, m_hDBC, SQL_ROLLBACK ))
+        {
+            return FALSE;
+        }
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                            CloseSession()                            */
+/************************************************************************/
+
+int OGRDB2Session::CloseSession()
+
+{
+    if( m_hDBC!=NULL )
+    {
+        if ( IsInTransaction() )
+            CPLError( CE_Warning, CPLE_AppDefined, "Closing session with active transactions." );
+        CPLDebug( "ODBC", "SQLDisconnect()" );
+        SQLDisconnect( m_hDBC );
+        SQLFreeConnect( m_hDBC );
+        m_hDBC = NULL;
+    }
+
+    if( m_hEnv!=NULL )
+    {
+        SQLFreeEnv( m_hEnv );
+        m_hEnv = NULL;
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                       ClearTransaction()                             */
+/************************************************************************/
+
+int OGRDB2Session::ClearTransaction()
+
+{
+#if (ODBCVER >= 0x0300)
+
+    if (m_bAutoCommit)
+        return TRUE;
+
+    SQLUINTEGER bAutoCommit;
+    /* See if we already in manual commit mode */
+    if ( Failed( SQLGetConnectAttr( m_hDBC, SQL_ATTR_AUTOCOMMIT, &bAutoCommit, sizeof(SQLUINTEGER), NULL) ) )
+        return FALSE;
+
+    if (bAutoCommit == SQL_AUTOCOMMIT_OFF)
+    {
+        /* switch the connection to auto commit mode (default) */
+        if( Failed( SQLSetConnectAttr( m_hDBC, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, 0 ) ) )
+            return FALSE;
+    }
+
+    m_bInTransaction = FALSE;
+    m_bAutoCommit = TRUE;
+
+#endif
+    return TRUE;
+}
+
+/************************************************************************/
+/*                       CommitTransaction()                            */
+/************************************************************************/
+
+int OGRDB2Session::BeginTransaction()
+
+{
+#if (ODBCVER >= 0x0300)
+CPLDebug("int OGRDB2Session::BeginTransaction","Enter");
+    SQLUINTEGER bAutoCommit;
+    /* See if we already in manual commit mode */
+    if ( Failed( SQLGetConnectAttr( m_hDBC, SQL_ATTR_AUTOCOMMIT, &bAutoCommit, sizeof(SQLUINTEGER), NULL) ) )
+        return FALSE;
+
+    if (bAutoCommit == SQL_AUTOCOMMIT_ON)
+    {
+        /* switch the connection to manual commit mode */
+        if( Failed( SQLSetConnectAttr( m_hDBC, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF, 0 ) ) )
+            return FALSE;
+    }
+
+    m_bInTransaction = TRUE;
+    m_bAutoCommit = FALSE;
+
+#endif
+    return TRUE;
+}
+
+/************************************************************************/
+/*                       CommitTransaction()                            */
+/************************************************************************/
+
+int OGRDB2Session::CommitTransaction()
+
+{
+#if (ODBCVER >= 0x0300)
+
+    if (m_bInTransaction)
+    {
+        if( Failed( SQLEndTran( SQL_HANDLE_DBC, m_hDBC, SQL_COMMIT ) ) )
+        {
+            return FALSE;
+        }
+        m_bInTransaction = FALSE;
+    }
+
+#endif
+    return TRUE;
+}
+
+/************************************************************************/
+/*                               Failed()                               */
+/*                                                                      */
+/*      Test if a return code indicates failure, return TRUE if that    */
+/*      is the case. Also update error text.                            */
+/************************************************************************/
+
+int OGRDB2Session::Failed( int nRetCode, HSTMT hStmt )
+
+{
+    SQLCHAR achSQLState[SQL_MAX_MESSAGE_LENGTH];
+    SQLINTEGER nNativeError;
+    SQLSMALLINT nTextLength=0;
+
+    m_szLastError[0] = '\0';
+//CPLDebug("OGRDB2Session::Failed","nRetCode: %d", nRetCode);
+
+    if( nRetCode == SQL_SUCCESS || nRetCode == SQL_SUCCESS_WITH_INFO )
+        return FALSE;
+
+    SQLError( m_hEnv, m_hDBC, hStmt, achSQLState, &nNativeError,
+              (SQLCHAR *) m_szLastError, sizeof(m_szLastError)-1,
+              &nTextLength );
+    m_szLastError[nTextLength] = '\0';
+//CPLDebug("OGRDB2Session::Failed","m_bInTransaction: %d, msg: '%s'", m_bInTransaction, m_szLastError);
+    if( nRetCode == SQL_ERROR && m_bInTransaction )
+        RollbackTransaction();
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                          EstablishSession()                          */
+/************************************************************************/
+
+/**
+ * Connect to database and logon.
+ *
+ * @param pszDSN The name of the DSN being used to connect.  This is not
+ * optional.
+ *
+ * @param pszUserid the userid to logon as, may be NULL if not not required,
+ * or provided by the DSN.
+ *
+ * @param pszPassword the password to logon with.   May be NULL if not required
+ * or provided by the DSN.
+ *
+ * @return TRUE on success or FALSE on failure.  Call GetLastError() to get
+ * details on failure.
+ */
+
+int OGRDB2Session::EstablishSession( const char *pszDSN,
+                                      const char *pszUserid,
+                                      const char *pszPassword )
+
+{
+    CloseSession();
+
+    if( Failed( SQLAllocEnv( &m_hEnv ) ) )
+        return FALSE;
+
+    if( Failed( SQLAllocConnect( m_hEnv, &m_hDBC ) ) )
+    {
+        CloseSession();
+        return FALSE;
+    }
+
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable : 4996 )  /*  warning C4996: 'SQLSetConnectOption': ODBC API: SQLSetConnectOption is deprecated. Please use SQLSetConnectAttr instead */
+#endif
+    SQLSetConnectOption( m_hDBC,SQL_LOGIN_TIMEOUT,30 );
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
+
+    if( pszUserid == NULL )
+        pszUserid = "";
+    if( pszPassword == NULL )
+        pszPassword = "";
+    CPLDebug( "OGRDB2Session::EstablishSession",
+            "pszDSN: '%s'", pszDSN );
+    int bFailed;
+    if( strstr(pszDSN,"=") != NULL )
+    {
+        SQLCHAR szOutConnString[1024];
+        SQLSMALLINT nOutConnStringLen = 0;
+
+        CPLDebug( "OGRDB2Session::EstablishSession",
+                "SQLDriverConnect(%s)", pszDSN );
+        bFailed = Failed(
+            SQLDriverConnect( m_hDBC, NULL,
+                              (SQLCHAR *) pszDSN, (SQLSMALLINT)strlen(pszDSN),
+                              szOutConnString, sizeof(szOutConnString),
+                              &nOutConnStringLen, SQL_DRIVER_NOPROMPT ) );
+        CPLDebug( "OGRDB2Session::EstablishSession",
+                "szOutConnString: '%s'", szOutConnString );
+    }
+    else
+    {
+        CPLDebug( "OGRDB2Session::EstablishSession",
+                "SQLConnect(%s)", pszDSN );
+        bFailed = Failed(
+            SQLConnect( m_hDBC, (SQLCHAR *) pszDSN, SQL_NTS,
+                        (SQLCHAR *) pszUserid, SQL_NTS,
+                        (SQLCHAR *) pszPassword, SQL_NTS ) );
+    }
+
+    if( bFailed )
+    {
+        CPLDebug( "OGRDB2Session::EstablishSession",
+                "... failed: %s", GetLastError() );
+        CloseSession();
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                            GetLastError()                            */
+/************************************************************************/
+
+/**
+ * Returns the last ODBC error message.
+ *
+ * @return pointer to an internal buffer with the error message in it.
+ * Do not free or alter.  Will be an empty (but not NULL) string if there is
+ * no pending error info.
+ */
+
+const char *OGRDB2Session::GetLastError()
+
+{
+//    CPLDebug("GetLastError","Enter; last error: '%s'", m_szLastError);
+    return m_szLastError;
+}
+
+
+
+/************************************************************************/
+/* ==================================================================== */
+/*                           OGRDB2Statement                           */
+/* ==================================================================== */
+/************************************************************************/
+
+/************************************************************************/
+/*                          OGRDB2Statement()                          */
+/************************************************************************/
+
+OGRDB2Statement::OGRDB2Statement( OGRDB2Session *poSession )
+
+{
+    DB2_DEBUG_ENTER("OGRDB2Statement::OGRDB2Statement");
+    m_bPrepared = FALSE;
+
+    m_poSession = poSession;
+
+    if( Failed(
+            SQLAllocStmt( poSession->GetConnection(), &m_hStmt ) ) )
+    {
+        m_hStmt = NULL;
+        return;
+    }
+
+    m_nColCount = 0;
+    m_papszColNames = NULL;
+    m_panColType = NULL;
+    m_papszColTypeNames = NULL;
+    m_panColSize = NULL;
+    m_panColPrecision = NULL;
+    m_panColNullable = NULL;
+    m_papszColColumnDef = NULL;
+
+    m_papszColValues = NULL;
+    m_panColValueLengths = NULL;
+
+    m_pszStatement = NULL;
+    m_nStatementMax = 0;
+    m_nStatementLen = 0;
+}
+
+/************************************************************************/
+/*                         ~OGRDB2Statement()                          */
+/************************************************************************/
+
+OGRDB2Statement::~OGRDB2Statement()
+
+{
+    DB2_DEBUG_ENTER("OGRDB2Statement::~OGRDB2Statement");
+
+    Clear();
+
+    if( m_hStmt != NULL )
+        SQLFreeStmt( m_hStmt, SQL_DROP );
+}
+
+/************************************************************************/
+/*                               DB2Prepare()                           */
+/************************************************************************/
+
+int OGRDB2Statement::DB2Prepare(const char *pszCallingFunction)
+{
+    if ( m_poSession == NULL || m_hStmt == NULL )
+    {
+        // we should post an error.
+        return FALSE;
+    }
+    CPLDebug(pszCallingFunction, "prepare: '%s'", m_pszStatement);
+
+    m_nLastRetCode = SQLPrepare( m_hStmt, (SQLCHAR *) m_pszStatement, SQL_NTS );
+
+    if (m_nLastRetCode != SQL_SUCCESS
+            && m_nLastRetCode != SQL_SUCCESS_WITH_INFO)
+    {
+        Failed(m_nLastRetCode);
+        return FALSE;
+    }
+    m_bPrepared = TRUE;
+    return TRUE;
+}
+
+/************************************************************************/
+/*                               DB2BindParameterIn()                   */
+/************************************************************************/
+
+int OGRDB2Statement::DB2BindParameterIn(const char *pszCallingFunction,
+                                        int nBindNum,
+                                        int nValueType,
+                                        int nParameterType,
+                                        int nLen,
+                                        void * pValuePointer)
+{
+    if ( m_poSession == NULL || m_hStmt == NULL )
+    {
+        // we should post an error.
+        return FALSE;
+    }
+    CPLDebug(pszCallingFunction,
+             "bind: nBindNum: %d; p: %p; nLen: %d; vType: %d; pType: %d",
+             nBindNum, pValuePointer, nLen, nValueType, nParameterType);
+
+    m_nLastRetCode = SQLBindParameter(m_hStmt,
+                                      (SQLUSMALLINT) (nBindNum),
+                                      SQL_PARAM_INPUT,
+                                      (SQLSMALLINT) nValueType,
+                                      (SQLSMALLINT) nParameterType,
+                                      nLen, 0, pValuePointer,
+                                      0, NULL);
+    if (m_nLastRetCode != SQL_SUCCESS
+            && m_nLastRetCode != SQL_SUCCESS_WITH_INFO)
+    {
+        Failed(m_nLastRetCode);
+        return FALSE;
+    }
+    return TRUE;
+}
+/************************************************************************/
+/*                               DB2Execute()                           */
+/************************************************************************/
+
+int OGRDB2Statement::DB2Execute(const char *pszCallingFunction)
+{
+    if ( m_poSession == NULL || m_hStmt == NULL )
+    {
+        // we should post an error.
+        return FALSE;
+    }
+    CPLDebug(pszCallingFunction, "execute: '%s'", m_pszStatement);
+    if (m_bPrepared)
+    {
+        m_nLastRetCode = SQLExecute(m_hStmt);
+
+    } else {
+        m_nLastRetCode = SQLExecDirect( m_hStmt, (SQLCHAR *) m_pszStatement, SQL_NTS );
+    }
+
+    if (m_nLastRetCode != SQL_SUCCESS
+            && m_nLastRetCode != SQL_SUCCESS_WITH_INFO)
+    {
+        Failed(m_nLastRetCode);
+        return FALSE;
+    }
+    return CollectResultsInfo();
+}
+
+
+/************************************************************************/
+/*                             ExecuteSQL()                             */
+/************************************************************************/
+
+/**
+ * Execute an SQL statement.
+ *
+ * This method will execute the passed (or stored) SQL statement,
+ * and initialize information about the resultset if there is one.
+ * If a NULL statement is passed, the internal stored statement that
+ * has been previously set via Append() or Appendf() calls will be used.
+ *
+ * @param pszStatement the SQL statement to execute, or NULL if the
+ * internally saved one should be used.
+ *
+ * @return TRUE on success or FALSE if there is an error.  Error details
+ * can be fetched with OGRODBCSession::GetLastError().
+ */
+
+int OGRDB2Statement::ExecuteSQL( const char *pszStatement )
+
+{
+    if( m_poSession == NULL || m_hStmt == NULL )
+    {
+        // we should post an error.
+        return FALSE;
+    }
+
+    if( pszStatement != NULL )
+    {
+        Clear();
+        Append( pszStatement );
+    }
+
+#if (ODBCVER >= 0x0300)
+
+    if ( !m_poSession->IsInTransaction() )
+    {
+        /* commit pending transactions and set to autocommit mode*/
+        m_poSession->ClearTransaction();
+    }
+
+#endif
+
+    if( Failed(
+            SQLExecDirect( m_hStmt, (SQLCHAR *) m_pszStatement, SQL_NTS ) ) )
+        return FALSE;
+
+    return CollectResultsInfo();
+}
+
+/************************************************************************/
+/*                         CollectResultsInfo()                         */
+/************************************************************************/
+
+int OGRDB2Statement::CollectResultsInfo()
+
+{
+    if( m_poSession == NULL || m_hStmt == NULL )
+    {
+        // we should post an error.
+        return FALSE;
+    }
+
+    if( Failed( SQLNumResultCols(m_hStmt,&m_nColCount) ) )
+        return FALSE;
+
+/* -------------------------------------------------------------------- */
+/*      Allocate per column information.                                */
+/* -------------------------------------------------------------------- */
+    m_papszColNames = (char **) CPLCalloc(sizeof(char *),(m_nColCount+1));
+    m_papszColValues = (char **) CPLCalloc(sizeof(char *),(m_nColCount+1));
+    m_panColValueLengths = (CPL_SQLLEN *) CPLCalloc(sizeof(CPL_SQLLEN),(m_nColCount+1));
+
+    m_panColType = (SQLSMALLINT *) CPLCalloc(sizeof(SQLSMALLINT),m_nColCount);
+    m_papszColTypeNames = (char **) CPLCalloc(sizeof(char *),(m_nColCount+1));
+    m_panColSize = (CPL_SQLULEN *) CPLCalloc(sizeof(CPL_SQLULEN),m_nColCount);
+    m_panColPrecision = (SQLSMALLINT *) CPLCalloc(sizeof(SQLSMALLINT),m_nColCount);
+    m_panColNullable = (SQLSMALLINT *) CPLCalloc(sizeof(SQLSMALLINT),m_nColCount);
+    m_papszColColumnDef = (char **) CPLCalloc(sizeof(char *),(m_nColCount+1));
+
+/* -------------------------------------------------------------------- */
+/*      Fetch column descriptions.                                      */
+/* -------------------------------------------------------------------- */
+    for( SQLUSMALLINT iCol = 0; iCol < m_nColCount; iCol++ )
+    {
+        SQLCHAR     szName[256];
+        SQLSMALLINT nNameLength = 0;
+
+        if ( Failed( SQLDescribeCol(m_hStmt, iCol+1,
+                                    szName, sizeof(szName), &nNameLength,
+                                    m_panColType + iCol,
+                                    m_panColSize + iCol,
+                                    m_panColPrecision + iCol,
+                                    m_panColNullable + iCol) ) )
+            return FALSE;
+
+        szName[nNameLength] = '\0';  // Paranoid; the string should be
+                                      // null-terminated by the driver
+        m_papszColNames[iCol] = CPLStrdup((const char*)szName);
+
+        // SQLDescribeCol() fetches just a subset of column attributes.
+        // In addition to above data we need data type name.
+        if ( Failed( SQLColAttribute(m_hStmt, iCol + 1, SQL_DESC_TYPE_NAME,
+                                     szName, sizeof(szName),
+                                     &nNameLength, NULL) ) )
+            return FALSE;
+
+        szName[nNameLength] = '\0';  // Paranoid
+        m_papszColTypeNames[iCol] = CPLStrdup((const char*)szName);
+
+//        CPLDebug( "ODBC", "%s %s %d", m_papszColNames[iCol],
+//                  szName, m_panColType[iCol] );
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                            GetRowCountAffected()                     */
+/************************************************************************/
+
+int OGRDB2Statement::GetRowCountAffected()
+{
+    SQLLEN nResultCount=0;
+    SQLRowCount( m_hStmt, &nResultCount );
+
+    return (int)nResultCount;
+}
+
+/************************************************************************/
+/*                            GetColCount()                             */
+/************************************************************************/
+
+/**
+ * Fetch the resultset column count.
+ *
+ * @return the column count, or zero if there is no resultset.
+ */
+
+int OGRDB2Statement::GetColCount()
+
+{
+    return m_nColCount;
+}
+
+/************************************************************************/
+/*                             GetColName()                             */
+/************************************************************************/
+
+/**
+ * Fetch a column name.
+ *
+ * @param iCol the zero based column index.
+ *
+ * @return NULL on failure (out of bounds column), or a pointer to an
+ * internal copy of the column name.
+ */
+
+const char *OGRDB2Statement::GetColName( int iCol )
+
+{
+    if( iCol < 0 || iCol >= m_nColCount )
+        return NULL;
+    else
+        return m_papszColNames[iCol];
+}
+
+/************************************************************************/
+/*                             GetColType()                             */
+/************************************************************************/
+
+/**
+ * Fetch a column data type.
+ *
+ * The return type code is a an ODBC SQL_ code, one of SQL_UNKNOWN_TYPE,
+ * SQL_CHAR, SQL_NUMERIC, SQL_DECIMAL, SQL_INTEGER, SQL_SMALLINT, SQL_FLOAT,
+ * SQL_REAL, SQL_DOUBLE, SQL_DATETIME, SQL_VARCHAR, SQL_TYPE_DATE,
+ * SQL_TYPE_TIME, SQL_TYPE_TIMESTAMPT.
+ *
+ * @param iCol the zero based column index.
+ *
+ * @return type code or -1 if the column is illegal.
+ */
+
+short OGRDB2Statement::GetColType( int iCol )
+
+{
+    if( iCol < 0 || iCol >= m_nColCount )
+        return -1;
+    else
+        return m_panColType[iCol];
+}
+
+/************************************************************************/
+/*                             GetColTypeName()                         */
+/************************************************************************/
+
+/**
+ * Fetch a column data type name.
+ *
+ * Returns data source-dependent data type name; for example, "CHAR",
+ * "VARCHAR", "MONEY", "LONG VARBINAR", or "CHAR ( ) FOR BIT DATA".
+ *
+ * @param iCol the zero based column index.
+ *
+ * @return NULL on failure (out of bounds column), or a pointer to an
+ * internal copy of the column dat type name.
+ */
+
+const char *OGRDB2Statement::GetColTypeName( int iCol )
+
+{
+    if( iCol < 0 || iCol >= m_nColCount )
+        return NULL;
+    else
+        return m_papszColTypeNames[iCol];
+}
+
+/************************************************************************/
+/*                             GetColSize()                             */
+/************************************************************************/
+
+/**
+ * Fetch the column width.
+ *
+ * @param iCol the zero based column index.
+ *
+ * @return column width, zero for unknown width columns.
+ */
+
+short OGRDB2Statement::GetColSize( int iCol )
+
+{
+    if( iCol < 0 || iCol >= m_nColCount )
+        return -1;
+    else
+        return (short) m_panColSize[iCol];
+}
+
+/************************************************************************/
+/*                          GetColPrecision()                           */
+/************************************************************************/
+
+/**
+ * Fetch the column precision.
+ *
+ * @param iCol the zero based column index.
+ *
+ * @return column precision, may be zero or the same as column size for
+ * columns to which it does not apply.
+ */
+
+short OGRDB2Statement::GetColPrecision( int iCol )
+
+{
+    if( iCol < 0 || iCol >= m_nColCount )
+        return -1;
+    else
+        return m_panColPrecision[iCol];
+}
+
+/************************************************************************/
+/*                           GetColNullable()                           */
+/************************************************************************/
+
+/**
+ * Fetch the column nullability.
+ *
+ * @param iCol the zero based column index.
+ *
+ * @return TRUE if the column may contains or FALSE otherwise.
+ */
+
+short OGRDB2Statement::GetColNullable( int iCol )
+
+{
+    if( iCol < 0 || iCol >= m_nColCount )
+        return -1;
+    else
+        return m_panColNullable[iCol];
+}
+
+/************************************************************************/
+/*                             GetColColumnDef()                        */
+/************************************************************************/
+
+/**
+ * Fetch a column default value.
+ *
+ * Returns the default value of a column.
+ *
+ * @param iCol the zero based column index.
+ *
+ * @return NULL if the default value is not dpecified
+ * or the internal copy of the default value.
+ */
+
+const char *OGRDB2Statement::GetColColumnDef( int iCol )
+
+{
+    if( iCol < 0 || iCol >= m_nColCount )
+        return NULL;
+    else
+        return m_papszColColumnDef[iCol];
+}
+
+/************************************************************************/
+/*                               Fetch()                                */
+/************************************************************************/
+
+/**
+ * Fetch a new record.
+ *
+ * Requests the next row in the current resultset using the SQLFetchScroll()
+ * call.  Note that many ODBC drivers only support the default forward
+ * fetching one record at a time.  Only SQL_FETCH_NEXT (the default) should
+ * be considered reliable on all drivers.
+ *
+ * Currently it isn't clear how to determine whether an error or a normal
+ * out of data condition has occurred if Fetch() fails.
+ *
+ * @param nOrientation One of SQL_FETCH_NEXT, SQL_FETCH_LAST, SQL_FETCH_PRIOR,
+ * SQL_FETCH_ABSOLUTE, or SQL_FETCH_RELATIVE (default is SQL_FETCH_NEXT).
+ *
+ * @param nOffset the offset (number of records), ignored for some
+ * orientations.
+ *
+ * @return TRUE if a new row is successfully fetched, or FALSE if not.
+ */
+
+int OGRDB2Statement::Fetch( int nOrientation, int nOffset )
+
+{
+    ClearColumnData();
+    if( m_hStmt == NULL || m_nColCount < 1 )
+        return FALSE;
+
+/* -------------------------------------------------------------------- */
+/*      Fetch a new row.  Note that some brain dead drives (such as     */
+/*      the unixodbc text file driver) don't implement                  */
+/*      SQLScrollFetch(), so we try to stick to SQLFetch() if we        */
+/*      can).                                                           */
+/* -------------------------------------------------------------------- */
+    SQLRETURN nRetCode;
+
+    if( nOrientation == SQL_FETCH_NEXT && nOffset == 0 )
+    {
+        nRetCode = SQLFetch( m_hStmt );
+
+        if( Failed(nRetCode) )
+        {
+            if ( nRetCode != SQL_NO_DATA )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined, "%s",
+                          m_poSession->GetLastError() );
+            }
+
+
+            return FALSE;
+        }
+    }
+    else
+    {
+        nRetCode = SQLFetchScroll(m_hStmt, (SQLSMALLINT) nOrientation, nOffset);
+
+        if( Failed(nRetCode) )
+        {
+            if ( nRetCode == SQL_NO_DATA )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined, "%s",
+                          m_poSession->GetLastError() );
+            }
+
+            return FALSE;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Pull out all the column values.                                 */
+/* -------------------------------------------------------------------- */
+    SQLSMALLINT iCol;
+
+    for( iCol = 0; iCol < m_nColCount; iCol++ )
+    {
+
+        char szWrkData[513];
+        CPL_SQLLEN cbDataLen;
+        SQLSMALLINT nFetchType = GetTypeMapping( m_panColType[iCol] );
+
+        // Handle values other than WCHAR and BINARY as CHAR.
+        if( nFetchType != SQL_C_BINARY && nFetchType != SQL_C_WCHAR )
+            nFetchType = SQL_C_CHAR;
+
+        szWrkData[0] = '\0';
+        szWrkData[sizeof(szWrkData)-1] = '\0';
+
+        nRetCode = SQLGetData( m_hStmt, iCol + 1, nFetchType,
+                               szWrkData, sizeof(szWrkData)-1,
+                               &cbDataLen );
+
+/* SQLGetData() is giving garbage values in the first 4 bytes of cbDataLen *
+ * in some architectures. Converting it to (int) discards the unnecessary  *
+ * bytes. This should not be a problem unless the buffer size reaches      *
+ * 2GB. (#3385)                                                            */
+        cbDataLen = (int) cbDataLen;
+
+        if( Failed( nRetCode ) )
+        {
+            if ( nRetCode == SQL_NO_DATA )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined, "%s",
+                          m_poSession->GetLastError() );
+            }
+            return FALSE;
+        }
+
+        if( cbDataLen == SQL_NULL_DATA )
+        {
+            m_papszColValues[iCol] = NULL;
+            m_panColValueLengths[iCol] = 0;
+        }
+
+        // assume big result: should check for state=SQLSATE 01004.
+        else if( nRetCode == SQL_SUCCESS_WITH_INFO  )
+        {
+            if( cbDataLen >= (CPL_SQLLEN)(sizeof(szWrkData)-1) )
+            {
+                cbDataLen = (CPL_SQLLEN)(sizeof(szWrkData)-1);
+                if (nFetchType == SQL_C_CHAR)
+                    while ((cbDataLen > 1) && (szWrkData[cbDataLen - 1] == 0))
+                        --cbDataLen; // trimming the extra terminators: bug 990
+                else if (nFetchType == SQL_C_WCHAR)
+                    while ((cbDataLen > 1) && (szWrkData[cbDataLen - 1] == 0)
+                        && (szWrkData[cbDataLen - 2] == 0))
+                        cbDataLen -= 2; // trimming the extra terminators
+
+            }
+
+            m_papszColValues[iCol] = (char *) CPLMalloc(cbDataLen+2);
+            memcpy( m_papszColValues[iCol], szWrkData, cbDataLen );
+            m_papszColValues[iCol][cbDataLen] = '\0';
+            m_papszColValues[iCol][cbDataLen+1] = '\0';
+            m_panColValueLengths[iCol] = cbDataLen;
+
+            while( true )
+            {
+                CPL_SQLLEN nChunkLen;
+
+                nRetCode = SQLGetData( m_hStmt, (SQLUSMALLINT) iCol+1,
+                                       nFetchType,
+                                       szWrkData, sizeof(szWrkData)-1,
+                                       &cbDataLen );
+                if( nRetCode == SQL_NO_DATA )
+                    break;
+
+                if( Failed( nRetCode ) )
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined, "%s",
+                              m_poSession->GetLastError() );
+                    return FALSE;
+                }
+
+                if( cbDataLen >= (int) (sizeof(szWrkData) - 1)
+                    || cbDataLen == SQL_NO_TOTAL )
+                {
+                    nChunkLen = sizeof(szWrkData)-1;
+                    if (nFetchType == SQL_C_CHAR)
+                        while ( (nChunkLen > 1)
+                                && (szWrkData[nChunkLen - 1] == 0) )
+                            --nChunkLen;  // trimming the extra terminators
+                    else if (nFetchType == SQL_C_WCHAR)
+                        while ( (nChunkLen > 1)
+                                && (szWrkData[nChunkLen - 1] == 0)
+                                && (szWrkData[nChunkLen - 2] == 0) )
+                            nChunkLen -= 2;  // trimming the extra terminators
+                }
+                else
+                    nChunkLen = cbDataLen;
+                szWrkData[nChunkLen] = '\0';
+
+                m_papszColValues[iCol] = (char *)
+                    CPLRealloc( m_papszColValues[iCol],
+                                m_panColValueLengths[iCol] + nChunkLen + 2 );
+                memcpy( m_papszColValues[iCol] + m_panColValueLengths[iCol],
+                        szWrkData, nChunkLen );
+                m_panColValueLengths[iCol] += nChunkLen;
+                m_papszColValues[iCol][m_panColValueLengths[iCol]] = '\0';
+                m_papszColValues[iCol][m_panColValueLengths[iCol]+1] = '\0';
+            }
+        }
+        else
+        {
+            m_panColValueLengths[iCol] = cbDataLen;
+            m_papszColValues[iCol] = (char *) CPLMalloc(cbDataLen+2);
+            memcpy( m_papszColValues[iCol], szWrkData, cbDataLen );
+            m_papszColValues[iCol][cbDataLen] = '\0';
+            m_papszColValues[iCol][cbDataLen+1] = '\0';
+        }
+
+        // Trim white space off end, if there is any.
+        if( nFetchType == SQL_C_CHAR && m_papszColValues[iCol] != NULL )
+        {
+            char *pszTarget = m_papszColValues[iCol];
+            size_t iEnd = strlen(pszTarget);
+
+            while ( iEnd > 0 && pszTarget[iEnd - 1] == ' ' )
+                pszTarget[--iEnd] = '\0';
+        }
+
+        // Convert WCHAR to UTF-8, assuming the WCHAR is UCS-2.
+        if( nFetchType == SQL_C_WCHAR && m_papszColValues[iCol] != NULL
+            && m_panColValueLengths[iCol] > 0 )
+        {
+            wchar_t *pwszSrc = (wchar_t *) m_papszColValues[iCol];
+
+            m_papszColValues[iCol] =
+                CPLRecodeFromWChar( pwszSrc, CPL_ENC_UCS2, CPL_ENC_UTF8 );
+            m_panColValueLengths[iCol] = strlen(m_papszColValues[iCol]);
+
+            CPLFree( pwszSrc );
+        }
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                             GetColData()                             */
+/************************************************************************/
+
+/**
+ * Fetch column data.
+ *
+ * Fetches the data contents of the requested column for the currently loaded
+ * row.  The result is returned as a string regardless of the column type.
+ * NULL is returned if an illegal column is given, or if the actual column
+ * is "NULL".
+ *
+ * @param iCol the zero based column to fetch.
+ *
+ * @param pszDefault the value to return if the column does not exist, or is
+ * NULL.  Defaults to NULL.
+ *
+ * @return pointer to internal column data or NULL on failure.
+ */
+
+const char *OGRDB2Statement::GetColData( int iCol, const char *pszDefault )
+
+{
+    if( iCol < 0 || iCol >= m_nColCount )
+        return pszDefault;
+    else if( m_papszColValues[iCol] != NULL )
+        return m_papszColValues[iCol];
+    else
+        return pszDefault;
+}
+
+/************************************************************************/
+/*                             GetColData()                             */
+/************************************************************************/
+
+/**
+ * Fetch column data.
+ *
+ * Fetches the data contents of the requested column for the currently loaded
+ * row.  The result is returned as a string regardless of the column type.
+ * NULL is returned if an illegal column is given, or if the actual column
+ * is "NULL".
+ *
+ * @param pszColName the name of the column requested.
+ *
+ * @param pszDefault the value to return if the column does not exist, or is
+ * NULL.  Defaults to NULL.
+ *
+ * @return pointer to internal column data or NULL on failure.
+ */
+
+const char *OGRDB2Statement::GetColData( const char *pszColName,
+                                          const char *pszDefault )
+
+{
+    int iCol = GetColId( pszColName );
+
+    if( iCol == -1 )
+        return pszDefault;
+    else
+        return GetColData( iCol, pszDefault );
+}
+
+/************************************************************************/
+/*                          GetColDataLength()                          */
+/************************************************************************/
+
+int OGRDB2Statement::GetColDataLength( int iCol )
+
+{
+    if( iCol < 0 || iCol >= m_nColCount )
+        return 0;
+    else if( m_papszColValues[iCol] != NULL )
+        return (int)m_panColValueLengths[iCol];
+    else
+        return 0;
+}
+
+/************************************************************************/
+/*                              GetColId()                              */
+/************************************************************************/
+
+/**
+ * Fetch column index.
+ *
+ * Gets the column index corresponding with the passed name.  The
+ * name comparisons are case insensitive.
+ *
+ * @param pszColName the name to search for.
+ *
+ * @return the column index, or -1 if not found.
+ */
+
+int OGRDB2Statement::GetColId( const char *pszColName )
+
+{
+    for( SQLSMALLINT iCol = 0; iCol < m_nColCount; iCol++ )
+        if( EQUAL(pszColName, m_papszColNames[iCol]) )
+            return iCol;
+
+    return -1;
+}
+
+/************************************************************************/
+/*                          ClearColumnData()                           */
+/************************************************************************/
+
+void OGRDB2Statement::ClearColumnData()
+
+{
+    if( m_nColCount > 0 )
+    {
+        for( int iCol = 0; iCol < m_nColCount; iCol++ )
+        {
+            if( m_papszColValues[iCol] != NULL )
+            {
+                CPLFree( m_papszColValues[iCol] );
+                m_papszColValues[iCol] = NULL;
+            }
+        }
+    }
+}
+
+/************************************************************************/
+/*                               Failed()                               */
+/************************************************************************/
+
+int OGRDB2Statement::Failed( int nResultCode )
+
+{
+    if( m_poSession != NULL )
+        return m_poSession->Failed( nResultCode, m_hStmt );
+    return TRUE;
+}
+
+/************************************************************************/
+/*                         Append(const char *)                         */
+/************************************************************************/
+
+/**
+ * Append text to internal command.
+ *
+ * The passed text is appended to the internal SQL command text.
+ *
+ * @param pszText text to append.
+ */
+
+void OGRDB2Statement::Append( const char *pszText )
+
+{
+    size_t  nTextLen = strlen(pszText);
+
+    if( m_nStatementMax < m_nStatementLen + nTextLen + 1 )
+    {
+        m_nStatementMax = (m_nStatementLen + nTextLen) * 2 + 100;
+        if( m_pszStatement == NULL )
+        {
+            m_pszStatement = (char *) VSIMalloc(m_nStatementMax);
+            m_pszStatement[0] = '\0';
+        }
+        else
+        {
+            m_pszStatement = (char *) VSIRealloc(m_pszStatement, m_nStatementMax);
+        }
+    }
+
+    strcpy( m_pszStatement + m_nStatementLen, pszText );
+    m_nStatementLen += nTextLen;
+}
+
+/************************************************************************/
+/*                     AppendEscaped(const char *)                      */
+/************************************************************************/
+
+/**
+ * Append text to internal command.
+ *
+ * The passed text is appended to the internal SQL command text after
+ * escaping any special characters so it can be used as a character string
+ * in an SQL statement.
+ *
+ * @param pszText text to append.
+ */
+
+void OGRDB2Statement::AppendEscaped( const char *pszText )
+
+{
+    size_t  iIn, iOut ,nTextLen = strlen(pszText);
+    char    *pszEscapedText = (char *) VSIMalloc(nTextLen*2 + 1);
+
+    for( iIn = 0, iOut = 0; iIn < nTextLen; iIn++ )
+    {
+        switch( pszText[iIn] )
+        {
+            case '\'':
+            case '\\':
+                pszEscapedText[iOut++] = '\\';
+                pszEscapedText[iOut++] = pszText[iIn];
+                break;
+
+            default:
+                pszEscapedText[iOut++] = pszText[iIn];
+                break;
+        }
+    }
+
+    pszEscapedText[iOut] = '\0';
+
+    Append( pszEscapedText );
+    CPLFree( pszEscapedText );
+}
+
+/************************************************************************/
+/*                             Append(int)                              */
+/************************************************************************/
+
+/**
+ * Append to internal command.
+ *
+ * The passed value is formatted and appended to the internal SQL command text.
+ *
+ * @param nValue value to append to the command.
+ */
+
+void OGRDB2Statement::Append( int nValue )
+
+{
+    char szFormattedValue[32];
+
+    snprintf( szFormattedValue, sizeof(szFormattedValue), "%d", nValue );
+    Append( szFormattedValue );
+}
+
+/************************************************************************/
+/*                            Append(double)                            */
+/************************************************************************/
+
+/**
+ * Append to internal command.
+ *
+ * The passed value is formatted and appended to the internal SQL command text.
+ *
+ * @param dfValue value to append to the command.
+ */
+
+void OGRDB2Statement::Append( double dfValue )
+
+{
+    char szFormattedValue[100];
+
+    snprintf( szFormattedValue, sizeof(szFormattedValue), "%24g", dfValue );
+    Append( szFormattedValue );
+}
+
+/************************************************************************/
+/*                              Appendf()                               */
+/************************************************************************/
+
+/**
+ * Append to internal command.
+ *
+ * The passed format is used to format other arguments and the result is
+ * appended to the internal command text.  Long results may not be formatted
+ * properly, and should be appended with the direct Append() methods.
+ *
+ * @param pszFormat printf() style format string.
+ *
+ * @return FALSE if formatting fails due to result being too large.
+ */
+
+int OGRDB2Statement::Appendf( const char *pszFormat, ... )
+
+{
+    va_list args;
+    char    szFormattedText[8000];
+    int     bSuccess;
+
+    va_start( args, pszFormat );
+#if defined(HAVE_VSNPRINTF)
+    bSuccess = vsnprintf( szFormattedText, sizeof(szFormattedText)-1,
+                          pszFormat, args ) < (int) sizeof(szFormattedText)-1;
+#else
+    vsprintf( szFormattedText, pszFormat, args );
+    bSuccess = TRUE;
+#endif
+    va_end( args );
+
+    if( bSuccess )
+        Append( szFormattedText );
+
+    return bSuccess;
+}
+
+/************************************************************************/
+/*                               Clear()                                */
+/************************************************************************/
+
+/**
+ * Clear internal command text and result set definitions.
+ */
+
+void OGRDB2Statement::Clear()
+
+{
+    /* Closing the cursor if opened */
+    if( m_hStmt != NULL )
+        SQLFreeStmt( m_hStmt, SQL_CLOSE );
+
+    ClearColumnData();
+
+    if( m_pszStatement != NULL )
+    {
+        CPLFree( m_pszStatement );
+        m_pszStatement = NULL;
+    }
+
+    m_nStatementLen = 0;
+    m_nStatementMax = 0;
+
+    m_nColCount = 0;
+
+    if( m_papszColNames )
+    {
+        CPLFree( m_panColType );
+        m_panColType = NULL;
+
+        CSLDestroy( m_papszColTypeNames );
+        m_papszColTypeNames = NULL;
+
+        CPLFree( m_panColSize );
+        m_panColSize = NULL;
+
+        CPLFree( m_panColPrecision );
+        m_panColPrecision = NULL;
+
+        CPLFree( m_panColNullable );
+        m_panColNullable = NULL;
+
+        CSLDestroy( m_papszColColumnDef );
+        m_papszColColumnDef = NULL;
+
+        CSLDestroy( m_papszColNames );
+        m_papszColNames = NULL;
+
+        CPLFree( m_papszColValues );
+        m_papszColValues = NULL;
+
+        CPLFree( m_panColValueLengths );
+        m_panColValueLengths = NULL;
+    }
+
+}
+
+/************************************************************************/
+/*                             GetColumns()                             */
+/************************************************************************/
+
+/**
+ * Fetch column definitions for a table.
+ *
+ * The SQLColumn() method is used to fetch the definitions for the columns
+ * of a table (or other queryable object such as a view).  The column
+ * definitions are digested and used to populate the OGRDB2Statement
+ * column definitions essentially as if a "SELECT * FROM tablename" had
+ * been done; however, no resultset will be available.
+ *
+ * @param pszTable the name of the table to query information on.  This
+ * should not be empty.
+ *
+ * @param pszCatalog the catalog to find the table in, use NULL (the
+ * default) if no catalog is available.
+ *
+ * @param pszSchema the schema to find the table in, use NULL (the
+ * default) if no schema is available.
+ *
+ * @return TRUE on success or FALSE on failure.
+ */
+
+int OGRDB2Statement::GetColumns( const char *pszTable,
+                                  const char *pszCatalog,
+                                  const char *pszSchema )
+
+{
+#ifdef notdef
+    if( pszCatalog == NULL )
+        pszCatalog = "";
+    if( pszSchema == NULL )
+        pszSchema = "";
+#endif
+
+#if (ODBCVER >= 0x0300)
+
+    if ( !m_poSession->IsInTransaction() )
+    {
+        /* commit pending transactions and set to autocommit mode*/
+        m_poSession->ClearTransaction();
+    }
+
+#endif
+/* -------------------------------------------------------------------- */
+/*      Fetch columns resultset for this table.                         */
+/* -------------------------------------------------------------------- */
+    if( Failed( SQLColumns( m_hStmt,
+                            (SQLCHAR *) pszCatalog, SQL_NTS,
+                            (SQLCHAR *) pszSchema, SQL_NTS,
+                            (SQLCHAR *) pszTable, SQL_NTS,
+                            (SQLCHAR *) NULL /* "" */, SQL_NTS ) ) )
+        return FALSE;
+
+/* -------------------------------------------------------------------- */
+/*      Allocate per column information.                                */
+/* -------------------------------------------------------------------- */
+#ifdef notdef
+    // SQLRowCount() is too unreliable (with unixodbc on AIX for instance)
+    // so we now avoid it.
+    SQLINTEGER nResultCount=0;
+
+    if( Failed(SQLRowCount( m_hStmt, &nResultCount ) ) )
+        nResultCount = 0;
+
+    if( nResultCount < 1 )
+        m_nColCount = 500; // Hopefully lots.
+    else
+        m_nColCount = nResultCount;
+#endif
+
+    m_nColCount = 500;
+
+    m_papszColNames = (char **) CPLCalloc(sizeof(char *),(m_nColCount+1));
+    m_papszColValues = (char **) CPLCalloc(sizeof(char *),(m_nColCount+1));
+
+    m_panColType = (SQLSMALLINT *) CPLCalloc(sizeof(SQLSMALLINT),m_nColCount);
+    m_papszColTypeNames = (char **) CPLCalloc(sizeof(char *),(m_nColCount+1));
+    m_panColSize = (CPL_SQLULEN *) CPLCalloc(sizeof(CPL_SQLULEN),m_nColCount);
+    m_panColPrecision = (SQLSMALLINT *) CPLCalloc(sizeof(SQLSMALLINT),m_nColCount);
+    m_panColNullable = (SQLSMALLINT *) CPLCalloc(sizeof(SQLSMALLINT),m_nColCount);
+    m_papszColColumnDef = (char **) CPLCalloc(sizeof(char *),(m_nColCount+1));
+
+/* -------------------------------------------------------------------- */
+/*      Establish columns to use for key information.                   */
+/* -------------------------------------------------------------------- */
+    SQLUSMALLINT iCol;
+
+    for( iCol = 0; iCol < m_nColCount; iCol++ )
+    {
+        char szWrkData[8193];
+        CPL_SQLLEN cbDataLen;
+
+        if( Failed( SQLFetch( m_hStmt ) ) )
+        {
+            m_nColCount = iCol;
+            break;
+        }
+
+        szWrkData[0] = '\0';
+
+        SQLGetData( m_hStmt, SQLColumns_COLUMN_NAME, SQL_C_CHAR,
+                    szWrkData, sizeof(szWrkData)-1, &cbDataLen );
+        m_papszColNames[iCol] = CPLStrdup(szWrkData);
+
+        SQLGetData( m_hStmt, SQLColumns_DATA_TYPE, SQL_C_CHAR,
+                    szWrkData, sizeof(szWrkData)-1, &cbDataLen );
+        m_panColType[iCol] = (short) atoi(szWrkData);
+
+        SQLGetData( m_hStmt, SQLColumns_TYPE_NAME, SQL_C_CHAR,
+                    szWrkData, sizeof(szWrkData)-1, &cbDataLen );
+        m_papszColTypeNames[iCol] = CPLStrdup(szWrkData);
+
+        SQLGetData( m_hStmt, SQLColumns_COLUMN_SIZE, SQL_C_CHAR,
+                    szWrkData, sizeof(szWrkData)-1, &cbDataLen );
+        m_panColSize[iCol] = atoi(szWrkData);
+
+        SQLGetData( m_hStmt, SQLColumns_DECIMAL_DIGITS, SQL_C_CHAR,
+                    szWrkData, sizeof(szWrkData)-1, &cbDataLen );
+        m_panColPrecision[iCol] = (short) atoi(szWrkData);
+
+        SQLGetData( m_hStmt, SQLColumns_NULLABLE, SQL_C_CHAR,
+                    szWrkData, sizeof(szWrkData)-1, &cbDataLen );
+        m_panColNullable[iCol] = atoi(szWrkData) == SQL_NULLABLE;
+#if (ODBCVER >= 0x0300)
+        SQLGetData( m_hStmt, SQLColumns_COLUMN_DEF, SQL_C_CHAR,
+                    szWrkData, sizeof(szWrkData)-1, &cbDataLen );
+        if (cbDataLen > 0)
+            m_papszColColumnDef[iCol] = CPLStrdup(szWrkData);
+#endif
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                           GetPrimaryKeys()                           */
+/************************************************************************/
+
+/**
+ * Fetch primary keys for a table.
+ *
+ * The SQLPrimaryKeys() function is used to fetch a list of fields
+ * forming the primary key.  The result is returned as a result set matching
+ * the SQLPrimaryKeys() function result set.  The 4th column in the result
+ * set is the column name of the key, and if the result set contains only
+ * one record then that single field will be the complete primary key.
+ *
+ * @param pszTable the name of the table to query information on.  This
+ * should not be empty.
+ *
+ * @param pszCatalog the catalog to find the table in, use NULL (the
+ * default) if no catalog is available.
+ *
+ * @param pszSchema the schema to find the table in, use NULL (the
+ * default) if no schema is available.
+ *
+ * @return TRUE on success or FALSE on failure.
+ */
+
+int OGRDB2Statement::GetPrimaryKeys( const char *pszTable,
+                                      const char *pszCatalog,
+                                      const char *pszSchema )
+
+{
+    if( pszCatalog == NULL )
+        pszCatalog = "";
+    if( pszSchema == NULL )
+        pszSchema = "";
+
+#if (ODBCVER >= 0x0300)
+
+    if ( !m_poSession->IsInTransaction() )
+    {
+        /* commit pending transactions and set to autocommit mode*/
+        m_poSession->ClearTransaction();
+    }
+
+#endif
+
+/* -------------------------------------------------------------------- */
+/*      Fetch columns resultset for this table.                         */
+/* -------------------------------------------------------------------- */
+    if( Failed( SQLPrimaryKeys( m_hStmt,
+                                (SQLCHAR *) pszCatalog, SQL_NTS,
+                                (SQLCHAR *) pszSchema, SQL_NTS,
+                                (SQLCHAR *) pszTable, SQL_NTS ) ) )
+        return FALSE;
+    else
+        return CollectResultsInfo();
+}
+
+/************************************************************************/
+/*                             GetTables()                              */
+/************************************************************************/
+
+/**
+ * Fetch tables in database.
+ *
+ * The SQLTables() function is used to fetch a list tables in the
+ * database.    The result is returned as a result set matching
+ * the SQLTables() function result set.  The 3rd column in the result
+ * set is the table name.  Only tables of type "TABLE" are returned.
+ *
+ * @param pszCatalog the catalog to find the table in, use NULL (the
+ * default) if no catalog is available.
+ *
+ * @param pszSchema the schema to find the table in, use NULL (the
+ * default) if no schema is available.
+ *
+ * @return TRUE on success or FALSE on failure.
+ */
+
+int OGRDB2Statement::GetTables( const char *pszCatalog,
+                                 const char *pszSchema )
+
+{
+    CPLDebug( "ODBC", "CatalogNameL: %s\nSchema name: %s\n",
+                pszCatalog, pszSchema );
+
+#if (ODBCVER >= 0x0300)
+
+    if ( !m_poSession->IsInTransaction() )
+    {
+        /* commit pending transactions and set to autocommit mode*/
+        m_poSession->ClearTransaction();
+    }
+
+#endif
+
+/* -------------------------------------------------------------------- */
+/*      Fetch columns resultset for this table.                         */
+/* -------------------------------------------------------------------- */
+    if( Failed( SQLTables( m_hStmt,
+                           (SQLCHAR *) pszCatalog, SQL_NTS,
+                           (SQLCHAR *) pszSchema, SQL_NTS,
+                           (SQLCHAR *) NULL, SQL_NTS,
+                           (SQLCHAR *) "'TABLE','VIEW'", SQL_NTS ) ) )
+        return FALSE;
+    else
+        return CollectResultsInfo();
+}
+
+/************************************************************************/
+/*                             DumpResult()                             */
+/************************************************************************/
+
+/**
+ * Dump resultset to file.
+ *
+ * The contents of the current resultset are dumped in a simply formatted
+ * form to the provided file.  If requested, the schema definition will
+ * be written first.
+ *
+ * @param fp the file to write to.  stdout or stderr are acceptable.
+ *
+ * @param bShowSchema TRUE to force writing schema information for the rowset
+ * before the rowset data itself.  Default is FALSE.
+ */
+
+void OGRDB2Statement::DumpResult( FILE *fp, int bShowSchema )
+
+{
+    int iCol;
+
+/* -------------------------------------------------------------------- */
+/*      Display schema                                                  */
+/* -------------------------------------------------------------------- */
+    if( bShowSchema )
+    {
+        fprintf( fp, "Column Definitions:\n" );
+        for( iCol = 0; iCol < GetColCount(); iCol++ )
+        {
+            fprintf( fp, " %2d: %-24s ", iCol, GetColName(iCol) );
+            if( GetColPrecision(iCol) > 0
+                && GetColPrecision(iCol) != GetColSize(iCol) )
+                fprintf( fp, " Size:%3d.%d",
+                         GetColSize(iCol), GetColPrecision(iCol) );
+            else
+                fprintf( fp, " Size:%5d", GetColSize(iCol) );
+
+            CPLString osType = GetTypeName( GetColType(iCol) );
+            fprintf( fp, " Type:%s", osType.c_str() );
+            if( GetColNullable(iCol) )
+                fprintf( fp, " NULLABLE" );
+            fprintf( fp, "\n" );
+        }
+        fprintf( fp, "\n" );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Display results                                                 */
+/* -------------------------------------------------------------------- */
+    int iRecord = 0;
+    while( Fetch() )
+    {
+        fprintf( fp, "Record %d\n", iRecord++ );
+
+        for( iCol = 0; iCol < GetColCount(); iCol++ )
+        {
+            fprintf( fp, "  %s: %s\n", GetColName(iCol), GetColData(iCol) );
+        }
+    }
+}
+
+/************************************************************************/
+/*                            GetTypeName()                             */
+/************************************************************************/
+
+/**
+ * Get name for SQL column type.
+ *
+ * Returns a string name for the indicated type code (as returned
+ * from OGRDB2Statement::GetColType()).
+ *
+ * @param nTypeCode the SQL_ code, such as SQL_CHAR.
+ *
+ * @return internal string, "UNKNOWN" if code not recognised.
+ */
+
+CPLString OGRDB2Statement::GetTypeName( int nTypeCode )
+
+{
+    switch( nTypeCode )
+    {
+      case SQL_CHAR:
+        return "CHAR";
+
+      case SQL_NUMERIC:
+        return "NUMERIC";
+
+      case SQL_DECIMAL:
+        return "DECIMAL";
+
+      case SQL_INTEGER:
+        return "INTEGER";
+
+      case SQL_SMALLINT:
+        return "SMALLINT";
+
+      case SQL_FLOAT:
+        return "FLOAT";
+
+      case SQL_REAL:
+        return "REAL";
+
+      case SQL_DOUBLE:
+        return "DOUBLE";
+
+      case SQL_DATETIME:
+        return "DATETIME";
+
+      case SQL_VARCHAR:
+        return "VARCHAR";
+
+      case SQL_TYPE_DATE:
+        return "DATE";
+
+      case SQL_TYPE_TIME:
+        return "TIME";
+
+      case SQL_TYPE_TIMESTAMP:
+        return "TIMESTAMP";
+
+      default:
+        CPLString osResult;
+        osResult.Printf( "UNKNOWN:%d", nTypeCode );
+        return osResult;
+    }
+}
+
+/************************************************************************/
+/*                            GetTypeMapping()                          */
+/************************************************************************/
+
+/**
+ * Get appropriate C data type for SQL column type.
+ *
+ * Returns a C data type code, corresponding to the indicated SQL data
+ * type code (as returned from OGRDB2Statement::GetColType()).
+ *
+ * @param nTypeCode the SQL_ code, such as SQL_CHAR.
+ *
+ * @return data type code. The valid code is always returned. If SQL
+ * code is not recognised, SQL_C_BINARY will be returned.
+ */
+
+SQLSMALLINT OGRDB2Statement::GetTypeMapping( SQLSMALLINT nTypeCode )
+
+{
+    switch( nTypeCode )
+    {
+        case SQL_CHAR:
+        case SQL_VARCHAR:
+        case SQL_LONGVARCHAR:
+            return SQL_C_CHAR;
+
+        case SQL_WCHAR:
+        case SQL_WVARCHAR:
+        case SQL_WLONGVARCHAR:
+            return SQL_C_WCHAR;
+
+        case SQL_DECIMAL:
+        case SQL_NUMERIC:
+            return SQL_C_NUMERIC;
+
+        case SQL_SMALLINT:
+            return SQL_C_SSHORT;
+
+        case SQL_INTEGER:
+            return SQL_C_SLONG;
+
+        case SQL_REAL:
+            return SQL_C_FLOAT;
+
+        case SQL_FLOAT:
+        case SQL_DOUBLE:
+            return SQL_C_DOUBLE;
+
+        case SQL_BIGINT:
+            return SQL_C_SBIGINT;
+
+        case SQL_BIT:
+        case SQL_TINYINT:
+/*        case SQL_TYPE_UTCDATETIME:
+        case SQL_TYPE_UTCTIME:*/
+        case SQL_INTERVAL_MONTH:
+        case SQL_INTERVAL_YEAR:
+        case SQL_INTERVAL_YEAR_TO_MONTH:
+        case SQL_INTERVAL_DAY:
+        case SQL_INTERVAL_HOUR:
+        case SQL_INTERVAL_MINUTE:
+        case SQL_INTERVAL_SECOND:
+        case SQL_INTERVAL_DAY_TO_HOUR:
+        case SQL_INTERVAL_DAY_TO_MINUTE:
+        case SQL_INTERVAL_DAY_TO_SECOND:
+        case SQL_INTERVAL_HOUR_TO_MINUTE:
+        case SQL_INTERVAL_HOUR_TO_SECOND:
+        case SQL_INTERVAL_MINUTE_TO_SECOND:
+        case SQL_GUID:
+            return SQL_C_CHAR;
+
+        case SQL_DATE:
+        case SQL_TYPE_DATE:
+            return SQL_C_DATE;
+
+        case SQL_TIME:
+        case SQL_TYPE_TIME:
+            return SQL_C_TIME;
+
+        case SQL_TIMESTAMP:
+        case SQL_TYPE_TIMESTAMP:
+            return SQL_C_TIMESTAMP;
+
+        case SQL_BINARY:
+        case SQL_VARBINARY:
+        case SQL_LONGVARBINARY:
+            return SQL_C_BINARY;
+
+        default:
+            return SQL_C_CHAR;
+    }
+}
+
+
diff --git a/ogr/ogrsf_frmts/db2/ogrdb2datasource.cpp b/ogr/ogrsf_frmts/db2/ogrdb2datasource.cpp
new file mode 100644
index 0000000..e9b1aa9
--- /dev/null
+++ b/ogr/ogrsf_frmts/db2/ogrdb2datasource.cpp
@@ -0,0 +1,3622 @@
+/****************************************************************************
+ *
+ * Project:  DB2 Spatial driver
+ * Purpose:  Implements OGRDB2DataSource class
+ * Author:   David Adler, dadler at adtechgeospatial dot com
+ *
+ ****************************************************************************
+ * Copyright (c) 2010, Tamas Szekeres
+ * Copyright (c) 2015, David Adler
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_db2.h"
+static GPKGTileFormat GetTileFormat(const char* pszTF );
+
+/* layer status */
+#define DB2LAYERSTATUS_ORIGINAL 0
+#define DB2LAYERSTATUS_INITIAL  1
+#define DB2LAYERSTATUS_CREATED  2
+#define DB2LAYERSTATUS_DISABLED 3
+
+
+/************************************************************************/
+/*                             Tiling schemes                           */
+/************************************************************************/
+
+typedef struct
+{
+    const char* pszName;
+    int         nEPSGCode;
+    double      dfMinX;
+    double      dfMaxY;
+    int         nTileXCountZoomLevel0;
+    int         nTileYCountZoomLevel0;
+    int         nTileWidth;
+    int         nTileHeight;
+    double      dfPixelXSizeZoomLevel0;
+    double      dfPixelYSizeZoomLevel0;
+} TilingSchemeDefinition;
+
+static const TilingSchemeDefinition asTilingShemes[] =
+{
+    /* See http://portal.opengeospatial.org/files/?artifact_id=35326 (WMTS 1.0), Annex E.3 */
+    {   "GoogleCRS84Quad",
+        4326,
+        -180.0, 180.0,
+        1, 1,
+        256, 256,
+        360.0 / 256, 360.0 / 256
+    },
+
+    /* See http://portal.opengeospatial.org/files/?artifact_id=35326 (WMTS 1.0), Annex E.4 */
+    {   "GoogleMapsCompatible",
+        3857,
+        -(156543.0339280410*256) /2, (156543.0339280410*256) /2,
+        1, 1,
+        256, 256,
+        156543.0339280410, 156543.0339280410
+    },
+
+    /* See InspireCRS84Quad at http://inspire.ec.europa.eu/documents/Network_Services/TechnicalGuidance_ViewServices_v3.0.pdf */
+    /* This is exactly the same as PseudoTMS_GlobalGeodetic */
+    {   "InspireCRS84Quad",
+        4326,
+        -180.0, 90.0,
+        2, 1,
+        256, 256,
+        180.0 / 256, 180.0 / 256
+    },
+
+    /* See global-geodetic at http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification */
+    {   "PseudoTMS_GlobalGeodetic",
+        4326,
+        -180.0, 90.0,
+        2, 1,
+        256, 256,
+        180.0 / 256, 180.0 / 256
+    },
+
+    /* See global-mercator at http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification */
+    {   "PseudoTMS_GlobalMercator",
+        3857,
+        -20037508.34, 20037508.34,
+        2, 2,
+        256, 256,
+        78271.516, 78271.516
+    },
+};
+
+/************************************************************************/
+/*                          OGRDB2DataSource()                 */
+/************************************************************************/
+
+OGRDB2DataSource::OGRDB2DataSource()
+
+{
+    clock1 = clock();
+    time1 = time(NULL);
+    m_bIsVector = TRUE;
+    m_papszTableNames = NULL;
+    m_papszSchemaNames = NULL;
+    m_papszGeomColumnNames = NULL;
+    m_papszCoordDimensions = NULL;
+    m_papszSRIds = NULL;
+    m_papszSRTexts = NULL;
+    m_pszName = NULL;
+    m_pszCatalog = NULL;
+
+    m_bHasMetadataTables = FALSE;
+    m_nKnownSRID = 0;
+    m_panSRID = NULL;
+    m_papoSRS = NULL;
+
+    bUseGeometryColumns = CPLTestBool(CPLGetConfigOption(
+            "DB2SPATIAL_USE_GEOMETRY_COLUMNS",
+            "YES"));
+    bListAllTables = CPLTestBool(CPLGetConfigOption(
+                                        "DB2SPATIAL_LIST_ALL_TABLES", "NO"));
+
+// from GPKG
+    m_bUpdate = FALSE;
+    m_bNew = FALSE;
+    m_papoLayers = NULL;
+    m_nLayers = 0;
+    m_bUtf8 = FALSE;
+    m_bIdentifierAsCO = FALSE;
+    m_bDescriptionAsCO = FALSE;
+    m_bHasReadMetadataFromStorage = FALSE;
+    m_bMetadataDirty = FALSE;
+    m_papszSubDatasets = NULL;
+    m_pszProjection = NULL;
+    m_bRecordInsertedInGPKGContent = FALSE;
+    m_bGeoTransformValid = FALSE;
+    m_nSRID = -1; /* unknown cartesian */
+    m_adfGeoTransform[0] = 0.0;
+    m_adfGeoTransform[1] = 1.0;
+    m_adfGeoTransform[2] = 0.0;
+    m_adfGeoTransform[3] = 0.0;
+    m_adfGeoTransform[4] = 0.0;
+    m_adfGeoTransform[5] = 1.0;
+    m_nZoomLevel = -1;
+    m_pabyCachedTiles = NULL;
+    for(int i=0; i<4; i++)
+    {
+        m_asCachedTilesDesc[i].nRow = -1;
+        m_asCachedTilesDesc[i].nCol = -1;
+        m_asCachedTilesDesc[i].nIdxWithinTileData = -1;
+        m_asCachedTilesDesc[i].abBandDirty[0] = FALSE;
+        m_asCachedTilesDesc[i].abBandDirty[1] = FALSE;
+        m_asCachedTilesDesc[i].abBandDirty[2] = FALSE;
+        m_asCachedTilesDesc[i].abBandDirty[3] = FALSE;
+    }
+    m_nShiftXTiles = 0;
+    m_nShiftXPixelsMod = 0;
+    m_nShiftYTiles = 0;
+    m_nShiftYPixelsMod = 0;
+    m_eTF = GPKG_TF_PNG_JPEG;
+    m_nTileMatrixWidth = 0;
+    m_nTileMatrixHeight = 0;
+    m_nZLevel = 6;
+    m_nQuality = 75;
+    m_bDither = FALSE;
+    m_poParentDS = NULL;
+    m_nOverviewCount = 0;
+    m_papoOverviewDS = NULL;
+    m_bZoomOther = FALSE;
+    m_bTriedEstablishingCT = FALSE;
+    m_pabyHugeColorArray = NULL;
+    m_poCT = NULL;
+    m_bInWriteTile = FALSE;
+    m_hTempDB = NULL;
+    m_bInFlushCache = FALSE;
+    m_nTileInsertionCount = 0;
+    m_osTilingScheme = "CUSTOM";
+}
+
+/************************************************************************/
+/*                         ~OGRDB2DataSource()                 */
+/************************************************************************/
+
+OGRDB2DataSource::~OGRDB2DataSource()
+
+{
+    DB2_DEBUG_ENTER("OGRDB2DataSource::~OGRDB2DataSource");
+    int         i;
+    SetPamFlags(0);
+    CPLFree( m_pszName );
+    CPLFree( m_pszCatalog );
+    CSLDestroy( m_papszTableNames );
+    CSLDestroy( m_papszSchemaNames );
+    CSLDestroy( m_papszGeomColumnNames );
+    CSLDestroy( m_papszCoordDimensions );
+    CSLDestroy( m_papszSRIds );
+    CSLDestroy( m_papszSRTexts );
+
+    if (!m_bIsVector)
+    {
+        if( m_poParentDS == NULL && m_osRasterTable.size() &&
+                !m_bGeoTransformValid )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                    "Raster table %s not correctly initialized due to missing call "
+                    "to SetGeoTransform()",
+                    m_osRasterTable.c_str());
+        }
+
+        FlushCache();
+        FlushMetadata();
+    }
+
+    for( i = 0; i < m_nLayers; i++ )
+        delete m_papoLayers[i];
+
+    CPLFree( m_papoLayers );
+
+    for( i = 0; i < m_nKnownSRID; i++ )
+    {
+        if( m_papoSRS[i] != NULL )
+            CPLDebug("OGRDB2DataSource::~OGRDB2DataSource","m_papoSRS[%d] is not null", i);
+//LATER            m_papoSRS[i]->Release(); //fails for some reason
+
+    }
+    CPLFree( m_panSRID );
+    CPLFree( m_papoSRS );
+    DB2_DEBUG_EXIT("OGRDB2DataSource::~OGRDB2DataSource");
+}
+
+/*======================================================================*/
+/*                                                                      */
+/*                         getDTime()                                   */
+/*                                                                      */
+/*   Return the time since last called.                                 */
+/*======================================================================*/
+double OGRDB2DataSource::getDTime()
+{
+    clock2 = clock();
+    time2 = time(NULL);
+    dclock = (clock2 - clock1) / CLOCKS_PER_SEC;
+    dtime  = (double)(time2  - time1 );
+
+    clock1 = clock2;
+    time1 = time2;
+    strcpy(stime, ctime(&time2));   /* get current time as a string */
+    stime[strlen(stime) - 1] = '\0';  /* get rid of newline */
+    CPLDebug("getDTime","stime: '%s', dclock: %f, dtime: %f",
+             stime, dclock, dtime);
+    return dclock;
+}
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRDB2DataSource::TestCapability( const char * pszCap )
+
+{
+    if( EQUAL(pszCap,ODsCCreateLayer) || EQUAL(pszCap,ODsCDeleteLayer) )
+        return TRUE;
+    else
+        return FALSE;
+}
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer *OGRDB2DataSource::GetLayer( int iLayer )
+
+{
+    CPLDebug("OGR_DB2DataSource::GetLayer", "pszLayer %d", iLayer);
+    if( iLayer < 0 || iLayer >= m_nLayers )
+        return NULL;
+    else
+        return m_papoLayers[iLayer];
+}
+
+/************************************************************************/
+/*                           GetLayerByName()                           */
+/************************************************************************/
+// Layer names are always uppercased - for now
+OGRLayer *OGRDB2DataSource::GetLayerByName( const char* pszLayerName )
+
+{
+    if (!pszLayerName)
+        return NULL;
+    char *pszTableName = NULL;
+    char *pszSchemaName = NULL;
+    OGRLayer *poLayer = NULL;
+    char *pszLayerNameUpper = NULL;
+    CPLDebug("OGR_DB2DataSource::GetLayerByName", "pszLayerName: '%s'",
+             pszLayerName);
+    pszLayerNameUpper = ToUpper(pszLayerName);
+    const char* pszDotPos = strstr(pszLayerNameUpper,".");
+    if ( pszDotPos != NULL )
+    {
+        int length = static_cast<int>(pszDotPos - pszLayerNameUpper);
+        pszSchemaName = (char*)CPLMalloc(length+1);
+        strncpy(pszSchemaName, pszLayerNameUpper, length);
+        pszSchemaName[length] = '\0';
+        pszTableName = CPLStrdup( pszDotPos + 1 ); //skip "."
+    }
+    else
+    {
+        pszTableName = CPLStrdup( pszLayerNameUpper );
+    }
+
+    for( int iLayer = 0; iLayer < m_nLayers; iLayer++ )
+    {
+        if( EQUAL(pszTableName,m_papoLayers[iLayer]->GetTableName()) &&
+                (pszSchemaName == NULL ||
+                 EQUAL(pszSchemaName,m_papoLayers[iLayer]->GetSchemaName())))
+        {
+            CPLDebug("OGR_DB2DataSource::GetLayerByName",
+                     "found layer: %d; schema: '%s'; table: '%s'",
+                     iLayer,m_papoLayers[iLayer]->GetSchemaName(),
+                     m_papoLayers[iLayer]->GetTableName());
+
+            poLayer = m_papoLayers[iLayer];
+        }
+    }
+
+    CPLFree( pszSchemaName );
+    CPLFree( pszTableName );
+    CPLFree( pszLayerNameUpper );
+
+    return poLayer;
+}
+
+
+/************************************************************************/
+/*                    DeleteLayer(OGRDB2TableLayer * poLayer)           */
+/************************************************************************/
+
+int OGRDB2DataSource::DeleteLayer( OGRDB2TableLayer * poLayer )
+{
+    int iLayer = 0;
+    if( poLayer == NULL )
+        return OGRERR_FAILURE;
+
+    /* -------------------------------------------------------------------- */
+    /*      Blow away our OGR structures related to the layer.  This is     */
+    /*      pretty dangerous if anything has a reference to this layer!     */
+    /* -------------------------------------------------------------------- */
+    const char* pszTableName = poLayer->GetTableName();
+    const char* pszSchemaName = poLayer->GetSchemaName();
+
+    OGRDB2Statement oStatement( &m_oSession );
+
+    oStatement.Appendf("DROP TABLE %s.%s", pszSchemaName, pszTableName );
+
+    CPLDebug( "OGR_DB2DataSource::DeleteLayer", "Drop stmt: '%s'",
+              oStatement.GetCommand());
+
+    for( iLayer = 0; iLayer < m_nLayers; iLayer++ )
+    {
+        if (poLayer == m_papoLayers[iLayer]) break;
+    }
+    delete m_papoLayers[iLayer]; // free the layer object
+    // move remaining layers down
+    memmove( m_papoLayers + iLayer, m_papoLayers + iLayer + 1,
+             sizeof(void *) * (m_nLayers - iLayer - 1) );
+    m_nLayers--;
+
+    /* -------------------------------------------------------------------- */
+    /*      Remove from the database.                                       */
+    /* -------------------------------------------------------------------- */
+
+    m_oSession.BeginTransaction();
+
+    if( !oStatement.DB2Execute("OGR_DB2DataSource::DeleteLayer") )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Error deleting layer: %s", GetSession()->GetLastError() );
+
+        return OGRERR_FAILURE;
+    }
+
+    m_oSession.CommitTransaction();
+
+    return OGRERR_NONE;
+}
+
+
+/************************************************************************/
+/*                            DeleteLayer(int iLayer)                   */
+/************************************************************************/
+
+int OGRDB2DataSource::DeleteLayer( int iLayer )
+
+{
+    if( iLayer < 0 || iLayer >= m_nLayers )
+        return OGRERR_FAILURE;
+
+    return DeleteLayer(m_papoLayers[iLayer]);
+
+}
+
+/************************************************************************/
+/*                            ICreateLayer()                            */
+/************************************************************************/
+
+OGRLayer * OGRDB2DataSource::ICreateLayer( const char * pszLayerName,
+        OGRSpatialReference *poSRS,
+        OGRwkbGeometryType eType,
+        char ** papszOptions )
+
+{
+    char                *pszTableName = NULL;
+    char                *pszSchemaName = NULL;
+    const char          *pszGeomColumn = NULL;
+    int                 nCoordDimension = 3;
+    CPLDebug("OGR_DB2DataSource::ICreateLayer",
+             "layer name: %s",pszLayerName);
+    CSLPrint(papszOptions, stderr);
+    /* determine the dimension */
+    if( eType == wkbFlatten(eType) )
+        nCoordDimension = 2;
+
+    if( CSLFetchNameValue( papszOptions, "DIM") != NULL )
+        nCoordDimension = atoi(CSLFetchNameValue( papszOptions, "DIM"));
+
+    /* DB2 Schema handling:
+       Extract schema name from input layer name or passed with -lco SCHEMA.
+       Set layer name to "schema.table" or to "table" if schema is not
+       specified
+    */
+    const char* pszDotPos = strstr(pszLayerName,".");
+    if ( pszDotPos != NULL )
+    {
+        int length = static_cast<int>(pszDotPos - pszLayerName);
+        pszSchemaName = (char*)CPLMalloc(length+1);
+        strncpy(pszSchemaName, pszLayerName, length);
+        pszSchemaName[length] = '\0';
+
+        /* For now, always convert layer name to uppercase table name*/
+        pszTableName = ToUpper( pszDotPos + 1 );
+
+    }
+    else
+    {
+        pszSchemaName = NULL;
+        /* For now, always convert layer name to uppercase table name*/
+        pszTableName = ToUpper( pszLayerName );
+    }
+
+    if( CSLFetchNameValue( papszOptions, "SCHEMA" ) != NULL )
+    {
+        CPLFree(pszSchemaName);
+        pszSchemaName = CPLStrdup(CSLFetchNameValue(papszOptions, "SCHEMA"));
+    }
+
+
+    /* -------------------------------------------------------------------- */
+    /*      Do we already have this layer?  If so, should we blow it        */
+    /*      away?                                                           */
+    /* -------------------------------------------------------------------- */
+    int iLayer;
+
+    for( iLayer = 0; iLayer < m_nLayers; iLayer++ )
+    {
+        CPLDebug("OGR_DB2DataSource::ICreateLayer",
+                 "schema: '%s'; table: '%s'",
+                 m_papoLayers[iLayer]->GetSchemaName(),
+                 m_papoLayers[iLayer]->GetTableName());
+
+        if( EQUAL(pszTableName,m_papoLayers[iLayer]->GetTableName()) &&
+                (pszSchemaName == NULL ||
+                 EQUAL(pszSchemaName,m_papoLayers[iLayer]->GetSchemaName())) )
+        {
+            CPLDebug("OGR_DB2DataSource::ICreateLayer",
+                     "Found match, schema: '%s'; table: '%s'"   ,
+                     pszSchemaName, pszTableName);
+            if( CSLFetchNameValue( papszOptions, "OVERWRITE" ) != NULL
+                    && !EQUAL(CSLFetchNameValue(papszOptions,"OVERWRITE"),
+                              "NO"))
+            {
+                if (!pszSchemaName)
+                    pszSchemaName = CPLStrdup(m_papoLayers[iLayer]->
+                                              GetSchemaName());
+
+                DeleteLayer( iLayer );
+            }
+            else
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Layer %s already exists, CreateLayer failed.\n"
+                          "Use the layer creation option OVERWRITE=YES to "
+                          "replace it.",
+                          pszLayerName );
+
+                CPLFree( pszSchemaName );
+                CPLFree( pszTableName );
+                return NULL;
+            }
+        }
+    }
+
+    /* determine the geometry column name */
+    pszGeomColumn =  CSLFetchNameValue( papszOptions, "GEOM_NAME");
+    if (!pszGeomColumn)
+        pszGeomColumn = "OGR_geometry";
+
+
+    /* -------------------------------------------------------------------- */
+    /*      Try to get the SRS Id of this spatial reference system,         */
+    /*      adding to the srs table if needed.                              */
+    /* -------------------------------------------------------------------- */
+    int nSRSId = 0;
+
+    if( CSLFetchNameValue( papszOptions, "SRID") != NULL )
+        nSRSId = atoi(CSLFetchNameValue( papszOptions, "SRID"));
+
+    if( nSRSId == 0 && poSRS != NULL )
+        nSRSId = FetchSRSId( poSRS );
+
+    OGRDB2Statement oStatement( &m_oSession );
+
+    if (pszSchemaName != NULL)
+        oStatement.Appendf("CREATE TABLE %s.%s ",
+                           pszSchemaName, pszTableName);
+    else
+        oStatement.Appendf("CREATE TABLE %s" ,
+                           pszTableName);
+    oStatement.Appendf(" (ogr_fid int not null "
+//                  "primary key , "
+                       "primary key GENERATED BY DEFAULT AS IDENTITY, "
+                       "%s db2gse.st_%s )",
+                       pszGeomColumn, OGRToOGCGeomType(eType));
+
+    m_oSession.BeginTransaction();
+
+    if( !oStatement.DB2Execute("OGR_DB2DataSource::ICreateLayer") )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Error creating layer: %s", GetSession()->GetLastError() );
+        CPLDebug("OGR_DB2DataSource::ICreateLayer", "create failed");
+
+        return NULL;
+    }
+
+    m_oSession.CommitTransaction();
+
+    // If we didn't have a schema name when the table was created,
+    // get the schema that was created by implicit
+    if (pszSchemaName == NULL) {
+        oStatement.Clear();
+        oStatement.Appendf( "SELECT table_schema FROM db2gse.st_geometry_columns "
+                            "WHERE table_name = '%s'",
+                            pszTableName);
+
+        if( oStatement.DB2Execute("OGR_DB2DataSource::ICreateLayer")
+                && oStatement.Fetch())
+        {
+            pszSchemaName = CPLStrdup( oStatement.GetColData(0) );
+        }
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Create the layer object.                                        */
+    /* -------------------------------------------------------------------- */
+    OGRDB2TableLayer   *poLayer;
+
+    poLayer = new OGRDB2TableLayer( this );
+
+    poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) );
+    poLayer->SetPrecisionFlag( CSLFetchBoolean(papszOptions,"PRECISION",
+                               TRUE));
+
+    char *pszWKT = NULL;
+    if( poSRS && poSRS->exportToWkt( &pszWKT ) != OGRERR_NONE )
+    {
+        CPLFree(pszWKT);
+        pszWKT = NULL;
+    }
+    CPLDebug("OGR_DB2DataSource::ICreateLayer", "srs wkt: %s",pszWKT);
+    if (poLayer->Initialize(pszSchemaName, pszTableName, pszGeomColumn,
+                            nCoordDimension, nSRSId, pszWKT, eType)
+            == OGRERR_FAILURE)
+    {
+        CPLFree( pszSchemaName );
+        CPLFree( pszTableName );
+        CPLFree( pszWKT );
+        return NULL;
+    }
+
+    CPLFree( pszSchemaName );
+    CPLFree( pszTableName );
+    CPLFree( pszWKT );
+
+    /* -------------------------------------------------------------------- */
+    /*      Add layer to data source layer list.                            */
+    /* -------------------------------------------------------------------- */
+    m_papoLayers = (OGRDB2TableLayer **)
+                   CPLRealloc( m_papoLayers, sizeof(OGRDB2TableLayer *)
+                               * (m_nLayers+1));
+
+    m_papoLayers[m_nLayers++] = poLayer;
+
+
+    return poLayer;
+}
+
+/************************************************************************/
+/*                             OpenTable()                              */
+/************************************************************************/
+
+int OGRDB2DataSource::OpenTable( const char *pszSchemaName,
+                                 const char *pszTableName,
+                                 const char *pszGeomCol, int nCoordDimension,
+                                 int nSRID, const char *pszSRText,
+                                 OGRwkbGeometryType eType)
+{
+    /* -------------------------------------------------------------------- */
+    /*      Create the layer object.                                        */
+    /* -------------------------------------------------------------------- */
+    OGRDB2TableLayer  *poLayer = new OGRDB2TableLayer( this );
+    CPLDebug( "OGR_DB2DataSource::OpenTable",
+              "pszSchemaName: '%s'; pszTableName: '%s'; pszGeomCol: '%s'",
+              pszSchemaName , pszTableName, pszGeomCol);
+    if( poLayer->Initialize( pszSchemaName, pszTableName, pszGeomCol,
+                             nCoordDimension, nSRID, pszSRText, eType ) )
+    {
+        delete poLayer;
+        return FALSE;
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Add layer to data source layer list.                            */
+    /* -------------------------------------------------------------------- */
+    m_papoLayers = (OGRDB2TableLayer **)
+                   CPLRealloc( m_papoLayers,  sizeof(OGRDB2TableLayer *)
+                               * (m_nLayers+1) );
+    m_papoLayers[m_nLayers++] = poLayer;
+
+    return TRUE;
+}
+
+
+/************************************************************************/
+/*                       GetLayerCount()                                */
+/************************************************************************/
+
+int OGRDB2DataSource::GetLayerCount()
+{
+    return m_nLayers;
+}
+
+/************************************************************************/
+/*                       ParseValue()                                   */
+/************************************************************************/
+
+int OGRDB2DataSource::ParseValue(char** pszValue, char* pszSource,
+                                 const char* pszKey, int nStart, int nNext,
+                                 int nTerm, int bRemove)
+{
+    int nLen = static_cast<int>(strlen(pszKey));
+    if ((*pszValue) == NULL && nStart + nLen < nNext &&
+            EQUALN(pszSource + nStart, pszKey, nLen))
+    {
+        *pszValue = (char*)CPLMalloc( sizeof(char)
+                                      * (nNext - nStart - nLen + 1) );
+        if (*pszValue)
+            strncpy(*pszValue, pszSource + nStart + nLen,
+                    nNext - nStart - nLen);
+        (*pszValue)[nNext - nStart - nLen] = 0;
+
+        if (bRemove)
+        {
+            // remove the value from the source string
+            if (pszSource[nNext] == ';')
+                memmove( pszSource + nStart, pszSource + nNext + 1,
+                         nTerm - nNext);
+            else
+                memmove( pszSource + nStart, pszSource + nNext,
+                         nTerm - nNext + 1);
+        }
+        return TRUE;
+    }
+    return FALSE;
+}
+
+/************************************************************************/
+/*                                Create()                              */
+/************************************************************************/
+
+int OGRDB2DataSource::Create( const char * pszFilename,
+                              int nXSize,
+                              int nYSize,
+                              int nBandsIn,
+                              GDALDataType eDT,
+                              char **papszOptions )
+{
+    CPLString osCommand;
+
+    /* First, ensure there isn't any such file yet. */
+    VSIStatBufL sStatBuf;
+
+    CPLDebug( "OGR_DB2DataSource::Create", "pszFileName: '%s'", pszFilename);
+    CPLDebug( "OGR_DB2DataSource::Create", "(%s,%s,%d,%d,%d,%s,%p)",
+              GetDescription(), pszFilename, nXSize, nYSize, nBandsIn,
+              GDALGetDataTypeName( eDT ),
+              papszOptions );
+
+    if (!InitializeSession(pszFilename, 0)) {
+        CPLDebug( "OGR_DB2DataSource::Create",
+                  "Session initialization failed");
+        return FALSE;
+    }
+
+    if (!HasMetadataTables()) {
+        CPLDebug( "OGR_DB2DataSource::Create",
+                  "No metadata tables and create failed");
+        return FALSE;
+    }
+
+    if( nBandsIn != 0 )
+    {
+        if( eDT != GDT_Byte )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported, "Only Byte supported");
+            return FALSE;
+        }
+        if( nBandsIn != 1 && nBandsIn != 2 && nBandsIn != 3 && nBandsIn != 4 )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Only 1 (Grey/ColorTable), 2 (Grey+Alpha), 3 (RGB) or 4 (RGBA) band dataset supported");
+            return FALSE;
+        }
+    }
+
+    int bFileExists = FALSE;
+    if( VSIStatL( pszFilename, &sStatBuf ) == 0 )
+    {
+        bFileExists = TRUE;
+        if( nBandsIn == 0 ||
+                !CPLTestBool(CSLFetchNameValueDef(papszOptions, "APPEND_SUBDATASET", "NO")) )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "A file system object called '%s' already exists.",
+                      pszFilename );
+
+            return FALSE;
+        }
+    }
+
+    m_bIsVector = FALSE;
+    m_pszFilename = CPLStrdup(pszFilename);
+    m_bNew = true;
+    m_bUpdate = TRUE;
+    eAccess = GA_Update; /* hum annoying duplication */
+
+    if( nBandsIn != 0 )
+    {
+        CPLDebug( "OGR_DB2DataSource::Create", "pszFileName: '%s'", pszFilename);
+        m_osRasterTable = CSLFetchNameValueDef(papszOptions,
+                                               "RASTER_TABLE", "RASTERTABLE");
+        m_bIdentifierAsCO = CSLFetchNameValue(papszOptions,
+                                              "RASTER_IDENTIFIER" ) != NULL;
+        m_osIdentifier = CSLFetchNameValueDef(papszOptions,
+                                              "RASTER_IDENTIFIER", m_osRasterTable);
+        m_bDescriptionAsCO = CSLFetchNameValue(papszOptions,
+                                               "RASTER_DESCRIPTION" ) != NULL;
+        m_osDescription = CSLFetchNameValueDef(papszOptions,
+                                               "RASTER_DESCRIPTION", "");
+        CPLDebug("OGR_DB2DataSource::Create", "m_osRasterTable: '%s'",
+                 m_osRasterTable.c_str());
+        CPLDebug("OGR_DB2DataSource::Create", "m_osIdentifier: '%s'",
+                 m_osIdentifier.c_str());
+        CPLDebug("OGR_DB2DataSource::Create", "m_osDescription: '%s'",
+                 m_osDescription.c_str());
+        m_oSession.BeginTransaction();
+        OGRDB2Statement oStatement( &m_oSession );
+
+// Drop the table with raster data
+        oStatement.Appendf("DROP TABLE %s",
+                           m_osRasterTable.c_str());
+
+        if( !oStatement.DB2Execute("OGR_DB2DataSource::Create") )
+        {
+            CPLDebug("OGR_DB2DataSource::Create", "DROP failed: %s", GetSession()->GetLastError() );
+        }
+
+        oStatement.Clear();
+        oStatement.Appendf("CREATE TABLE %s" ,
+                           m_osRasterTable.c_str());
+        oStatement.Appendf("("
+                           "id INTEGER NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,"
+                           "zoom_level INTEGER NOT NULL,"
+                           "tile_column INTEGER NOT NULL,"
+                           "tile_row INTEGER NOT NULL,"
+                           "tile_data BLOB NOT NULL,"
+                           "UNIQUE (zoom_level, tile_column, tile_row)"
+                           ")");
+
+        if( !oStatement.DB2Execute("OGR_DB2DataSource::Create") )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Error creating layer: %s", GetSession()->GetLastError() );
+            CPLDebug("OGR_DB2DataSource::Create", "create failed");
+            return NULL;
+        }
+
+        // Remove entries from raster catalog tables - will cascade
+        oStatement.Clear();
+        oStatement.Appendf("DELETE FROM gpkg.contents WHERE table_name = '%s'",
+                           m_osRasterTable.c_str());
+
+        if( !oStatement.DB2Execute("OGR_DB2DataSource::Create") )
+        {
+            CPLDebug("OGR_DB2DataSource::Create", "DELETE failed: %s", GetSession()->GetLastError() );
+        }
+        m_oSession.CommitTransaction();
+
+        nRasterXSize = nXSize;
+        nRasterYSize = nYSize;
+
+        const char* pszTileSize = CSLFetchNameValueDef(papszOptions, "BLOCKSIZE", "256");
+        const char* pszTileWidth = CSLFetchNameValueDef(papszOptions, "BLOCKXSIZE", pszTileSize);
+        const char* pszTileHeight = CSLFetchNameValueDef(papszOptions, "BLOCKYSIZE", pszTileSize);
+        int nTileWidth = atoi(pszTileWidth);
+        int nTileHeight = atoi(pszTileHeight);
+        if( (nTileWidth < 8 || nTileWidth > 4096 || nTileHeight < 8 || nTileHeight > 4096) &&
+                !CPLTestBool(CPLGetConfigOption("GPKG_ALLOW_CRAZY_SETTINGS", "NO")) )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Invalid block dimensions: %dx%d",
+                     nTileWidth, nTileHeight);
+            return FALSE;
+        }
+
+        m_pabyCachedTiles = (GByte*) VSI_MALLOC3_VERBOSE(4 * 4, nTileWidth, nTileHeight);
+        if( m_pabyCachedTiles == NULL )
+        {
+            return FALSE;
+        }
+
+        for(int i = 1; i <= nBandsIn; i ++)
+            SetBand( i, new GDALDB2RasterBand(this, i, nTileWidth, nTileHeight) );
+        CPLDebug("OGR_DB2DataSource::Create","setting metadata PIXEL");
+        GDALPamDataset::SetMetadataItem("INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE");
+        GDALPamDataset::SetMetadataItem("IDENTIFIER", m_osIdentifier);
+        if( m_osDescription.size() )
+            GDALPamDataset::SetMetadataItem("DESCRIPTION", m_osDescription);
+
+        const char* pszTF = CSLFetchNameValue(papszOptions, "TILE_FORMAT");
+        if( pszTF )
+            m_eTF = GetTileFormat(pszTF);
+
+        ParseCompressionOptions(papszOptions);
+
+        if( m_eTF == GPKG_TF_WEBP )
+        {
+            if( !RegisterWebPExtension() )
+                return FALSE;
+        }
+
+        const char* pszTilingScheme = CSLFetchNameValue(papszOptions, "TILING_SCHEME");
+        if( pszTilingScheme )
+        {
+            m_osTilingScheme = pszTilingScheme;
+            int bFound = FALSE;
+            for(size_t iScheme = 0;
+                    iScheme < sizeof(asTilingShemes)/sizeof(asTilingShemes[0]);
+                    iScheme++ )
+            {
+                if( EQUAL(m_osTilingScheme, asTilingShemes[iScheme].pszName) )
+                {
+                    if( nTileWidth != asTilingShemes[iScheme].nTileWidth ||
+                            nTileHeight != asTilingShemes[iScheme].nTileHeight )
+                    {
+                        CPLError(CE_Failure, CPLE_NotSupported,
+                                 "Tile dimension should be %dx%d for %s tiling scheme",
+                                 asTilingShemes[iScheme].nTileWidth,
+                                 asTilingShemes[iScheme].nTileHeight,
+                                 m_osTilingScheme.c_str());
+                        return FALSE;
+                    }
+
+                    /* Implicitly sets SRS */
+                    OGRSpatialReference oSRS;
+                    if( oSRS.importFromEPSG(asTilingShemes[iScheme].nEPSGCode) != OGRERR_NONE )
+                        return FALSE;
+                    char* pszWKT = NULL;
+                    oSRS.exportToWkt(&pszWKT);
+                    SetProjection(pszWKT);
+                    CPLFree(pszWKT);
+
+                    bFound = TRUE;
+                    break;
+                }
+            }
+            if( !bFound )
+                m_osTilingScheme = "CUSTOM";
+        }
+    }
+    CPLDebug("OGR_DB2DataSource::Create","exiting");
+    return TRUE;
+
+
+}
+
+
+
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+int OGRDB2DataSource::Open( GDALOpenInfo* poOpenInfo )
+{
+    int bRet = FALSE;
+    SetDescription( poOpenInfo->pszFilename );
+#ifdef DEBUG_DB2
+    CPLDebug("OGR_DB2DataSource::OpenNew", "papszOpenOptions");
+    CSLPrint((char **) poOpenInfo->papszOpenOptions, stderr);
+#endif
+    CPLString osFilename( poOpenInfo->pszFilename );
+    CPLString osSubdatasetTableName;
+    m_bUpdate = poOpenInfo->eAccess == GA_Update;
+    CPLDebug( "OGR_DB2DataSource::OpenNew",
+              "pszFileName: '%s'; m_bUpdate: %d, eAccess: %d; GA_Update: %d",
+              poOpenInfo->pszFilename, m_bUpdate, poOpenInfo->eAccess, GA_Update);
+    eAccess = poOpenInfo->eAccess; /* hum annoying duplication */
+    m_pszFilename = CPLStrdup( osFilename );
+
+    if( poOpenInfo->nOpenFlags & GDAL_OF_VECTOR )
+    {
+        CPLDebug( "OGR_DB2DataSource::OpenNew", "Open vector");
+        return Open(poOpenInfo->pszFilename, 0);
+    }
+
+    if( poOpenInfo->nOpenFlags & GDAL_OF_RASTER )
+    {
+        CPLDebug( "OGR_DB2DataSource::OpenNew", "Open raster");
+        m_bIsVector = FALSE;
+        if (!InitializeSession(poOpenInfo->pszFilename, 0)) {
+            CPLDebug( "OGR_DB2DataSource::Open",
+                      "Session initialization failed");
+            return FALSE;
+        }
+
+        OGRDB2Statement oStatement( GetSession() );
+        oStatement.Appendf( "SELECT c.table_name, c.identifier, c.description, c.srs_id, c.min_x, c.min_y, c.max_x, c.max_y, "
+                            "tms.min_x, tms.min_y, tms.max_x, tms.max_y FROM gpkg.contents c JOIN gpkg.tile_matrix_set tms ON "
+                            "c.table_name = tms.table_name WHERE data_type = 'tiles'");
+
+        if( CSLFetchNameValue( poOpenInfo->papszOpenOptions, "TABLE") ) {
+            osSubdatasetTableName = CSLFetchNameValue( poOpenInfo->papszOpenOptions, "TABLE");
+        }
+        if( osSubdatasetTableName.size() )
+        {
+            oStatement.Appendf(" AND c.table_name='%s'", osSubdatasetTableName.c_str());
+            SetPhysicalFilename( osFilename.c_str() ); //LATER
+        }
+
+        if( !oStatement.DB2Execute("OGR_DB2DataSource::OpenNew") )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Raster query failed: %s",
+                     GetSession()->GetLastError());
+            return FALSE;
+        }
+        if( oStatement.Fetch() )
+        {
+            CPLDebug("OGRDB2DataSource::OpenNew",
+                     "Raster table_name: %s",
+                     oStatement.GetColData(0));
+            const char *pszTableName = oStatement.GetColData(0);
+            const char* pszIdentifier = oStatement.GetColData(1);
+            const char* pszDescription = oStatement.GetColData(2);
+            const char* pszSRSId = oStatement.GetColData(3);
+            const char* pszMinX = oStatement.GetColData(4);
+            const char* pszMinY = oStatement.GetColData(5);
+            const char* pszMaxX = oStatement.GetColData(6);
+            const char* pszMaxY = oStatement.GetColData(7);
+            const char* pszTMSMinX = oStatement.GetColData(8);
+            const char* pszTMSMinY = oStatement.GetColData(9);
+            const char* pszTMSMaxX = oStatement.GetColData(10);
+            const char* pszTMSMaxY = oStatement.GetColData(11);
+            if( pszTableName != NULL && pszTMSMinX != NULL && pszTMSMinY != NULL &&
+                    pszTMSMaxX != NULL && pszTMSMaxY != NULL )
+            {
+                eAccess = GA_Update; //LATER - where should this be set?
+                bRet = OpenRaster( pszTableName, pszIdentifier, pszDescription,
+                                   pszSRSId ? atoi(pszSRSId) : 0,
+                                   CPLAtof(pszTMSMinX), CPLAtof(pszTMSMinY),
+                                   CPLAtof(pszTMSMaxX), CPLAtof(pszTMSMaxY),
+                                   pszMinX, pszMinY, pszMaxX, pszMaxY,
+                                   poOpenInfo->papszOpenOptions );
+                CPLDebug("OGRDB2DataSource::OpenNew","back from OpenRaster; bRet: %d", bRet);
+                if (bRet) {
+                    return TRUE;
+                }
+            }
+        }
+    }
+    CPLError(CE_Failure, CPLE_AppDefined, "Table '%s' not found", osSubdatasetTableName.c_str());
+    CPLDebug("OGRDB2DataSource::OpenNew","exiting FALSE");
+    return FALSE;
+}
+
+/************************************************************************/
+/*                                InializeSession()                     */
+/************************************************************************/
+
+int OGRDB2DataSource::InitializeSession( const char * pszNewName,
+        int bTestOpen )
+
+{
+    CPLDebug( "OGR_DB2DataSource::InitializeSession",
+              "pszNewName: '%s'; bTestOpen: %d",
+              pszNewName, bTestOpen);
+
+// If we already have a connection, assume that it is good and we don't
+// have to do anything else.
+    if (m_oSession.GetConnection()) {
+        CPLDebug("OGR_DB2DataSource::InitializeSession",
+                 "connected already: %p", m_oSession.GetConnection());
+        return TRUE;
+    }
+
+    /* Determine if the connection string contains specific values */
+    char* pszTableSpec = NULL;
+    char* pszConnectionName = CPLStrdup(pszNewName + strlen(DB2ODBC_PREFIX));
+    char* pszDriver = NULL;
+    int nCurrent, nNext, nTerm;
+    nCurrent = nNext = nTerm = static_cast<int>(strlen(pszConnectionName));
+
+    while (nCurrent > 0)
+    {
+        --nCurrent;
+        if (pszConnectionName[nCurrent] == ';')
+        {
+            nNext = nCurrent;
+            continue;
+        }
+
+        if (ParseValue(&m_pszCatalog, pszConnectionName, "database=",
+                       nCurrent, nNext, nTerm, FALSE))
+            continue;
+
+        if (ParseValue(&pszTableSpec, pszConnectionName, "tables=",
+                       nCurrent, nNext, nTerm, TRUE))
+            continue;
+
+        if (ParseValue(&pszDriver, pszConnectionName, "driver=",
+                       nCurrent, nNext, nTerm, FALSE))
+            continue;
+    }
+    CPLDebug( "OGR_DB2DataSource::Open", "m_pszCatalog: '%s'", m_pszCatalog);
+    CPLDebug( "OGR_DB2DataSource::Open", "pszTableSpec: '%s'", pszTableSpec);
+    CPLDebug( "OGR_DB2DataSource::Open", "pszDriver: '%s'", pszDriver);
+    CPLDebug( "OGR_DB2DataSource::Open", "pszConnectionName: '%s'",
+              pszConnectionName);
+
+    /* Determine if the connection string contains the database portion */
+    if( m_pszCatalog == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "'%s' does not contain the 'database' portion\n",
+                  pszNewName );
+        CPLFree(pszTableSpec);
+        CPLFree(pszConnectionName);
+        CPLFree(pszDriver);
+        return FALSE;
+    }
+
+    m_pszName = CPLStrdup(pszNewName);
+
+
+
+    // if the table parameter was specified, pull out the table names
+    if( pszTableSpec != NULL )
+    {
+        char          **papszTableList;
+        int             i;
+
+        papszTableList = CSLTokenizeString2( pszTableSpec, ",", 0 );
+
+
+        for( i = 0; i < CSLCount(papszTableList); i++ )
+        {
+            char      **papszQualifiedParts;
+
+            // Get schema and table name
+            papszQualifiedParts = CSLTokenizeString2( papszTableList[i],
+                                  ".", 0 );
+
+            /* Find the geometry column name if specified */
+            if( CSLCount( papszQualifiedParts ) >= 1 )
+            {
+                char* pszGeomColumnName = NULL;
+                char* pos = strchr(papszQualifiedParts[
+                                       CSLCount( papszQualifiedParts ) - 1], '(');
+                if (pos != NULL)
+                {
+                    *pos = '\0';
+                    pszGeomColumnName = pos+1;
+                    int len = static_cast<int>(strlen(pszGeomColumnName));
+                    if (len > 0)
+                        pszGeomColumnName[len - 1] = '\0';
+                }
+                m_papszGeomColumnNames = CSLAddString( m_papszGeomColumnNames,
+                                                       pszGeomColumnName ?
+                                                       pszGeomColumnName : "");
+            }
+
+            if( CSLCount( papszQualifiedParts ) == 2 )
+            {
+                m_papszSchemaNames = CSLAddString( m_papszSchemaNames,
+                                                   ToUpper(papszQualifiedParts[0]));
+
+                m_papszTableNames = CSLAddString( m_papszTableNames,
+                                                  ToUpper(papszQualifiedParts[1]));
+            }
+            else if( CSLCount( papszQualifiedParts ) == 1 )
+            {
+                m_papszSchemaNames = CSLAddString( m_papszSchemaNames, "NULL");
+                m_papszTableNames = CSLAddString( m_papszTableNames,
+                                                  ToUpper(papszQualifiedParts[0]));
+            }
+
+            CSLDestroy(papszQualifiedParts);
+        }
+
+        CSLDestroy(papszTableList);
+    }
+
+    CPLFree(pszTableSpec);
+
+    /* Initialize the DB2 connection. */
+    int nResult;
+
+    nResult = m_oSession.EstablishSession( pszConnectionName, "", "" );
+
+    CPLFree(pszDriver);
+
+    if( !nResult )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Unable to initialize connection to the server for %s,\n"
+                  "%s", pszNewName, m_oSession.GetLastError() );
+        CPLFree(pszConnectionName);
+        return FALSE;
+    }
+
+// Determine whether we are running on LUW or zoom
+    OGRDB2Statement oStatement( &m_oSession );
+    oStatement.Append("SELECT COUNT(*) FROM SYSCAT.TABLES");
+
+// We assume that if the statement fails, the table doesn't exist
+
+    if( !oStatement.DB2Execute("OGR_DB2DataSource::InitializeSession") )
+    {
+        CPLDebug("OGRDB2DataSource::InitializeSession","Must be z/OS");
+        m_bIsZ = TRUE;
+    } else {
+        CPLDebug("OGRDB2DataSource::InitializeSession","Must be LUW");
+        m_bIsZ = FALSE;
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+int OGRDB2DataSource::Open( const char * pszNewName,
+                            int bTestOpen )
+
+{
+
+    CPLAssert( m_nLayers == 0 );
+
+    CPLDebug( "OGR_DB2DataSource::Open",
+              "pszNewName: '%s'; bTestOpen: %d",
+              pszNewName, bTestOpen);
+
+    if( !STARTS_WITH_CI(pszNewName, DB2ODBC_PREFIX) )
+    {
+        if( !bTestOpen )
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "%s does not conform to DB2 naming convention,"
+                      " DB2:*\n", pszNewName );
+        return FALSE;
+    }
+
+    if (!InitializeSession(pszNewName, bTestOpen)) {
+        CPLDebug( "OGR_DB2DataSource::Open",
+                  "Session initialization failed");
+        return FALSE;
+    }
+    char** papszTypes = NULL;
+
+    /* read metadata for the specified tables */
+    if (m_papszTableNames != NULL)
+    {
+
+        for( int iTable = 0;
+                m_papszTableNames != NULL && m_papszTableNames[iTable] != NULL;
+                iTable++ )
+        {
+            int found = FALSE;
+            OGRDB2Statement oStatement( &m_oSession );
+// If a table name was specified, get the information from ST_Geometry_Columns
+// for this table
+            oStatement.Appendf( "SELECT table_schema, column_name, 2, srs_id, "
+                                "srs_name, type_name "
+                                "FROM db2gse.st_geometry_columns "
+                                "WHERE table_name = '%s'",
+                                m_papszTableNames[iTable]);
+
+// If the schema was specified, add it to the SELECT statement
+            if (strcmp(m_papszSchemaNames[iTable], "NULL"))
+                oStatement.Appendf("  AND table_schema = '%s' ",
+                                   m_papszSchemaNames[iTable]);
+
+            if( oStatement.DB2Execute("OGR_DB2DataSource::Open") )
+            {
+                while( oStatement.Fetch() )
+                {
+                    found = TRUE;
+
+                    /* set schema for table if it was not specified */
+                    if (!strcmp(m_papszSchemaNames[iTable], "NULL")) {
+                        CPLFree(m_papszSchemaNames[iTable]);
+                        m_papszSchemaNames[iTable] = CPLStrdup(
+                                                         oStatement.GetColData(0) );
+                    }
+                    if (m_papszGeomColumnNames == NULL)
+                        m_papszGeomColumnNames = CSLAddString(
+                                                     m_papszGeomColumnNames,
+                                                     oStatement.GetColData(1) );
+                    else if (*m_papszGeomColumnNames[iTable] == 0)
+                    {
+                        CPLFree(m_papszGeomColumnNames[iTable]);
+                        m_papszGeomColumnNames[iTable] = CPLStrdup(
+                                                             oStatement.GetColData(1) );
+                    }
+
+                    m_papszCoordDimensions =
+                        CSLAddString( m_papszCoordDimensions,
+                                      oStatement.GetColData(2, "2") );
+                    m_papszSRIds =
+                        CSLAddString( m_papszSRIds, oStatement.GetColData(3, "-1") );
+                    m_papszSRTexts =
+                        CSLAddString( m_papszSRTexts, oStatement.GetColData(4, "") );
+                    // Convert the DB2 spatial type to the OGC spatial type
+                    // which just entails stripping off the "ST_" at the
+                    // beginning of the DB2 type name
+                    char DB2SpatialType[20], OGCSpatialType [20];
+                    strcpy(DB2SpatialType, oStatement.GetColData(5));
+                    strcpy(OGCSpatialType, DB2SpatialType+3);
+//                  CPLDebug("OGR_DB2DataSource::Open","DB2SpatialType: %s, OGCSpatialType: %s",DB2SpatialType, OGCSpatialType);
+                    papszTypes = CSLAddString( papszTypes, OGCSpatialType );
+                }
+            }
+
+            if (!found) {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Table %s.%s not found in "
+                          "db2gse.st_geometry_columns"
+                          , m_papszSchemaNames[iTable], m_papszTableNames[iTable] );
+                return FALSE;
+            }
+        }
+    }
+
+
+    /* Determine the available tables if not specified. */
+    if (m_papszTableNames == NULL)
+    {
+        OGRDB2Statement oStatement( &m_oSession );
+
+        oStatement.Append( "SELECT table_schema, table_name, column_name, 2, "
+                           "srs_id, srs_name, type_name "
+                           "FROM db2gse.st_geometry_columns");
+
+        if( oStatement.DB2Execute("OGR_DB2DataSource::Open") )
+        {
+            while( oStatement.Fetch() )
+            {
+                m_papszSchemaNames =
+                    CSLAddString( m_papszSchemaNames, oStatement.GetColData(0) );
+                m_papszTableNames =
+                    CSLAddString( m_papszTableNames, oStatement.GetColData(1) );
+                m_papszGeomColumnNames =
+                    CSLAddString( m_papszGeomColumnNames, oStatement.GetColData(2) );
+                m_papszCoordDimensions =
+                    CSLAddString( m_papszCoordDimensions, oStatement.GetColData(3) );
+                m_papszSRIds =
+                    CSLAddString( m_papszSRIds, oStatement.GetColData(4,"-1") );
+                m_papszSRTexts =
+                    CSLAddString( m_papszSRTexts, oStatement.GetColData(5,"") );
+                char DB2SpatialType[20], OGCSpatialType [20];
+                strcpy(DB2SpatialType, oStatement.GetColData(6));
+                strcpy(OGCSpatialType, DB2SpatialType+3);
+//              CPLDebug("OGR_DB2DataSource::Open","DB2SpatialType: %s, OGCSpatialType: %s",DB2SpatialType, OGCSpatialType);
+                papszTypes =
+                    CSLAddString( papszTypes, OGCSpatialType );
+            }
+        }
+    }
+    /*
+    CPLDebug("OGR_DB2DataSource::Open", "m_papszSchemaNames");
+    CSLPrint(m_papszSchemaNames, stderr);
+    CPLDebug("OGR_DB2DataSource::Open", "m_papszTableNames");
+    CSLPrint(m_papszTableNames, stderr);
+    CPLDebug("OGR_DB2DataSource::Open", "m_papszGeomColumnNames");
+    CSLPrint(m_papszGeomColumnNames, stderr);
+    CPLDebug("OGR_DB2DataSource::Open", "m_papszSRIds");
+    CSLPrint(m_papszSRIds, stderr);
+    CPLDebug("OGR_DB2DataSource::Open", "m_papszSRTexts");
+    CSLPrint(m_papszSRTexts, stderr);
+    CPLDebug("OGR_DB2DataSource::Open", "papszTypes");
+    CSLPrint(papszTypes, stderr);
+    */
+
+    int nSRId, nCoordDimension;
+    char * pszSRText = NULL;
+    OGRwkbGeometryType eType;
+
+    for( int iTable = 0;
+            m_papszTableNames != NULL && m_papszTableNames[iTable] != NULL;
+            iTable++ )
+    {
+        pszSRText = NULL;
+        nSRId = -1;
+        if (m_papszSRIds != NULL) {
+            nSRId = atoi(m_papszSRIds[iTable]);
+            CPLDebug("OGR_DB2DataSource::Open", "iTable: %d; schema: %s; "
+                     "table: %s; geomCol: %s; geomType: %s; srid: '%s'",
+                     iTable, m_papszSchemaNames[iTable],
+                     m_papszTableNames[iTable],
+                     m_papszGeomColumnNames[iTable], papszTypes[iTable],
+                     m_papszSRIds[iTable]);
+            // If srid is not defined it was probably because the table
+            // was not registered.
+            // In that case, try to get it from the actual data table.
+            if (nSRId < 0) {
+                OGRDB2Statement oStatement( &m_oSession );
+                oStatement.Appendf( "select db2gse.st_srsid(%s) from %s.%s "
+                                    "fetch first row only",
+                                    m_papszGeomColumnNames[iTable],
+                                    m_papszSchemaNames[iTable],
+                                    m_papszTableNames[iTable] );
+
+                if( oStatement.DB2Execute("OGR_DB2DataSource::Open")
+                        && oStatement.Fetch())
+                {
+                    nSRId = atoi( oStatement.GetColData( 0 ) );
+                    OGRDB2Statement oStatement2( &m_oSession );
+                    oStatement2.Appendf( "select definition from "
+                                         "db2gse.st_spatial_reference_systems "
+                                         "where srs_id = %d",
+                                         nSRId);
+                    if( oStatement2.DB2Execute("OGR_DB2DataSource::Open")
+                            && oStatement2.Fetch() )
+                    {
+                        if ( oStatement2.GetColData( 0 ) )
+                            pszSRText = CPLStrdup(oStatement2.GetColData( 0 ));;
+                    }
+                }
+                if (nSRId < 0) { // something went wrong - didn't find srid - use default
+                    nSRId = 0;
+                    pszSRText = CPLStrdup("UNSPECIFIED");
+                    CPLDebug("OGR_DB2DataSource::Open", "Using default srid 0");
+                }
+            } else {
+                pszSRText = CPLStrdup(m_papszSRTexts[iTable]);
+            }
+        }
+        CPLDebug("OGR_DB2DataSource::Open", "nSRId: %d; srText: %s",
+                 nSRId, pszSRText);
+        if (m_papszCoordDimensions != NULL)
+            nCoordDimension = atoi(m_papszCoordDimensions[iTable]);
+        else
+            nCoordDimension = 2;
+
+        if (papszTypes != NULL)
+            eType = OGRFromOGCGeomType(papszTypes[iTable]);
+        else
+            eType = wkbUnknown;
+
+        if( strlen(m_papszGeomColumnNames[iTable]) > 0 )
+            OpenTable( m_papszSchemaNames[iTable], m_papszTableNames[iTable],
+                       m_papszGeomColumnNames[iTable],
+                       nCoordDimension, nSRId, pszSRText, eType);
+        else
+            OpenTable( m_papszSchemaNames[iTable], m_papszTableNames[iTable],
+                       NULL,
+                       nCoordDimension, nSRId, pszSRText, wkbNone);
+    }
+
+    CPLFree(pszSRText);
+
+    bDSUpdate = m_bUpdate; //LATER what is bDSUpdate?
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                             ExecuteSQL()                             */
+/************************************************************************/
+
+OGRLayer * OGRDB2DataSource::ExecuteSQL( const char *pszSQLCommand,
+        OGRGeometry *poSpatialFilter,
+        const char *pszDialect )
+
+{
+    /* -------------------------------------------------------------------- */
+    /*      Use generic implementation for recognized dialects              */
+    /* -------------------------------------------------------------------- */
+    CPLDebug("OGRDB2DataSource::ExecuteSQL", "SQL: '%s'; dialect: '%s'",
+             pszSQLCommand, pszDialect);
+    if( IsGenericSQLDialect(pszDialect) )
+        return GDALDataset::ExecuteSQL( pszSQLCommand, poSpatialFilter,
+                                        pszDialect );
+
+    /* -------------------------------------------------------------------- */
+    /*      Special case DELLAYER: command.                                 */
+    /* -------------------------------------------------------------------- */
+    if( EQUALN(pszSQLCommand,"DELLAYER:",9) )
+    {
+        const char *pszLayerName = pszSQLCommand + 9;
+
+        while( *pszLayerName == ' ' )
+            pszLayerName++;
+
+        OGRLayer* poLayer = GetLayerByName(pszLayerName);
+
+        for( int iLayer = 0; iLayer < m_nLayers; iLayer++ )
+        {
+            if( m_papoLayers[iLayer] == poLayer )
+            {
+                DeleteLayer( iLayer );
+                break;
+            }
+        }
+        return NULL;
+    }
+
+    CPLDebug( "OGRDB2DataSource::ExecuteSQL", "ExecuteSQL(%s) called.",
+              pszSQLCommand );
+
+
+    /* Execute the command natively */
+    OGRDB2Statement *poStatement = new OGRDB2Statement( &m_oSession );
+    poStatement->Append( pszSQLCommand );
+
+    if( !poStatement->ExecuteSQL() )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "%s", m_oSession.GetLastError() );
+        delete poStatement;
+        return NULL;
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Are there result columns for this statement?                    */
+    /* -------------------------------------------------------------------- */
+    if( poStatement->GetColCount() == 0 )
+    {
+        delete poStatement;
+        CPLErrorReset();
+        return NULL;
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Create a results layer.  It will take ownership of the          */
+    /*      statement.                                                      */
+    /* -------------------------------------------------------------------- */
+
+    OGRDB2SelectLayer *poLayer = NULL;
+
+    poLayer = new OGRDB2SelectLayer( this, poStatement );
+
+    if( poSpatialFilter != NULL )
+        poLayer->SetSpatialFilter( poSpatialFilter );
+
+    return poLayer;
+}
+
+/************************************************************************/
+/*                          ReleaseResultSet()                          */
+/************************************************************************/
+
+void OGRDB2DataSource::ReleaseResultSet( OGRLayer * poLayer )
+
+{
+    delete poLayer;
+}
+
+/************************************************************************/
+/*                            ToUpper()                                 */
+/************************************************************************/
+
+char *OGRDB2DataSource::ToUpper( const char *pszSrcName )
+
+{
+    char    *pszSafeName = CPLStrdup( pszSrcName );
+    int     i;
+
+    for( i = 0; pszSafeName[i] != '\0'; i++ )
+    {
+        pszSafeName[i] = (char) toupper( pszSafeName[i] );
+    }
+
+    return pszSafeName;
+}
+
+/************************************************************************/
+/*                            LaunderName()                             */
+/************************************************************************/
+
+char *OGRDB2DataSource::LaunderName( const char *pszSrcName )
+
+{
+    char    *pszSafeName = CPLStrdup( pszSrcName );
+    int     i;
+
+    for( i = 0; pszSafeName[i] != '\0'; i++ )
+    {
+        pszSafeName[i] = (char) tolower( pszSafeName[i] );
+        if( pszSafeName[i] == '-' || pszSafeName[i] == '#' )
+            pszSafeName[i] = '_';
+    }
+
+    return pszSafeName;
+}
+
+/************************************************************************/
+/*                      InitializeMetadataTables()                      */
+/*                                                                      */
+/*      Create the metadata tables (SPATIAL_REF_SYS and                 */
+/*      GEOMETRY_COLUMNS).                                              */
+/************************************************************************/
+
+OGRErr OGRDB2DataSource::InitializeMetadataTables()
+
+{
+    CPLDebug( "OGR_DB2DataSource::InitializeMetadataTables", "Not supported");
+
+    CPLError( CE_Failure, CPLE_AppDefined,
+              "Dynamically creating DB2 spatial metadata tables is "
+              "not supported" );
+    return OGRERR_FAILURE;
+
+}
+
+
+/************************************************************************/
+/*                              FetchSRS()                              */
+/*                                                                      */
+/*      Return a SRS corresponding to a particular id.  Note that       */
+/*      reference counting should be honoured on the returned           */
+/*      OGRSpatialReference, as handles may be cached.                  */
+/************************************************************************/
+
+OGRSpatialReference *OGRDB2DataSource::FetchSRS( int nId )
+
+{
+    CPLDebug("OGRDB2DataSource::FetchSRS", "nId: %d", nId);
+    if( nId <= 0 )
+        return NULL;
+
+    /* -------------------------------------------------------------------- */
+    /*      First, we look through our SRID cache, is it there?             */
+    /* -------------------------------------------------------------------- */
+    int  i;
+
+    for( i = 0; i < m_nKnownSRID; i++ )
+    {
+        if( m_panSRID[i] == nId )
+            return m_papoSRS[i];
+    }
+
+    OGRSpatialReference *poSRS = NULL;
+
+    /* -------------------------------------------------------------------- */
+    /*      Try looking up in spatial_ref_sys table                         */
+    /* -------------------------------------------------------------------- */
+    if (bUseGeometryColumns)
+    {
+        OGRDB2Statement oStatement( GetSession() );
+        oStatement.Appendf( "SELECT definition FROM "
+                            "db2gse.st_spatial_reference_systems "
+                            "WHERE srs_id = %d", nId );
+
+        if( oStatement.ExecuteSQL() && oStatement.Fetch() )
+        {
+            if ( oStatement.GetColData( 0 ) )
+            {
+                poSRS = new OGRSpatialReference();
+                char* pszWKT = (char*)oStatement.GetColData( 0 );
+                CPLDebug("OGR_DB2DataSource::FetchSRS", "SRS = %s", pszWKT);
+                if( poSRS->importFromWkt( &pszWKT ) != OGRERR_NONE )
+                {
+                    delete poSRS;
+                    poSRS = NULL;
+                }
+            }
+        }
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Try looking up the EPSG list                                    */
+    /* -------------------------------------------------------------------- */
+    if (!poSRS)
+    {
+        poSRS = new OGRSpatialReference();
+        if( poSRS->importFromEPSG( nId ) != OGRERR_NONE )
+        {
+            delete poSRS;
+            poSRS = NULL;
+        }
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Add to the cache.                                               */
+    /* -------------------------------------------------------------------- */
+    if (poSRS)
+    {
+        m_panSRID = (int *) CPLRealloc(m_panSRID,sizeof(int) * (m_nKnownSRID+1) );
+        m_papoSRS = (OGRSpatialReference **)
+                    CPLRealloc(m_papoSRS, sizeof(void*) * (m_nKnownSRID + 1) );
+        m_panSRID[m_nKnownSRID] = nId;
+        m_papoSRS[m_nKnownSRID] = poSRS;
+        m_nKnownSRID++;
+        CPLDebug("OGRDB2DataSource::FetchSRS", "Add to cache; m_nKnownSRID: %d", m_nKnownSRID);
+    }
+
+    return poSRS;
+}
+
+/************************************************************************/
+/*                             FetchSRSId()                             */
+/*                                                                      */
+/*      Fetch the id corresponding to an SRS, and if not found, add     */
+/*      it to the table.                                                */
+/************************************************************************/
+
+int OGRDB2DataSource::FetchSRSId( OGRSpatialReference * poSRS)
+
+{
+    char                *pszWKT = NULL;
+    int                 nSRSId = 0;
+    const char*         pszAuthorityName;
+
+    if( poSRS == NULL )
+        return 0;
+
+    OGRSpatialReference oSRS(*poSRS);
+    poSRS = NULL;
+
+    pszAuthorityName = oSRS.GetAuthorityName(NULL);
+    CPLDebug("OGRDB2DataSource::FetchSRSId",
+        "pszAuthorityName: '%s'", pszAuthorityName);
+    if( pszAuthorityName == NULL || strlen(pszAuthorityName) == 0 )
+    {
+        /* -----------------------------------------------------------------*/
+        /*      Try to identify an EPSG code                                */
+        /* -----------------------------------------------------------------*/
+        oSRS.AutoIdentifyEPSG();
+
+        pszAuthorityName = oSRS.GetAuthorityName(NULL);
+        if (pszAuthorityName != NULL && EQUAL(pszAuthorityName, "EPSG"))
+        {
+            const char* pszAuthorityCode = oSRS.GetAuthorityCode(NULL);
+            if ( pszAuthorityCode != NULL && strlen(pszAuthorityCode) > 0 )
+            {
+                /* Import 'clean' SRS */
+                oSRS.importFromEPSG( atoi(pszAuthorityCode) );
+
+                pszAuthorityName = oSRS.GetAuthorityName(NULL);
+            }
+        }
+    }
+    /* -------------------------------------------------------------------- */
+    /*      Check whether the EPSG authority code is already mapped to a    */
+    /*      SRS ID.                                                         */
+    /* -------------------------------------------------------------------- */
+    int  nAuthorityCode = 0;
+    if( pszAuthorityName != NULL && EQUAL( pszAuthorityName, "EPSG" ) )
+    {
+        /* For the root authority name 'EPSG', the authority code
+         * should always be integral
+         */
+        nAuthorityCode = atoi( oSRS.GetAuthorityCode(NULL) );
+
+        OGRDB2Statement oStatement( &m_oSession );
+        oStatement.Appendf("SELECT srs_id "
+                           "FROM db2gse.st_spatial_reference_systems WHERE "
+                           "organization = '%s' "
+                           "AND organization_coordsys_id = %d",
+                           pszAuthorityName,
+                           nAuthorityCode );
+
+        if( oStatement.DB2Execute("OGR_DB2DataSource::FetchSRSId")
+            && oStatement.Fetch() && oStatement.GetColData( 0 ) )
+        {
+            nSRSId = atoi(oStatement.GetColData( 0 ));
+            CPLDebug("OGR_DB2DataSource::FetchSRSId", "nSRSId = %d", nSRSId);
+            return nSRSId;
+        }
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Translate SRS to WKT.                                           */
+    /* -------------------------------------------------------------------- */
+    if( oSRS.exportToWkt( &pszWKT ) != OGRERR_NONE )
+    {
+        CPLFree(pszWKT);
+        return 0;
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Try to find in the existing table.                              */
+    /* -------------------------------------------------------------------- */
+    OGRDB2Statement oStatement( &m_oSession );
+
+    oStatement.Append( "SELECT srs_id FROM db2gse.st_spatial_reference_systems "
+                       "WHERE description = ");
+    OGRDB2AppendEscaped(&oStatement, pszWKT);
+
+    /* -------------------------------------------------------------------- */
+    /*      We got it!  Return it.                                          */
+    /* -------------------------------------------------------------------- */
+    if( oStatement.DB2Execute("OGR_DB2DataSource::FetchSRSId") )
+    {
+        if ( oStatement.Fetch() && oStatement.GetColData( 0 ) )
+        {
+            nSRSId = atoi(oStatement.GetColData( 0 ));
+            CPLFree(pszWKT);
+            return nSRSId;
+        }
+    }
+    else
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Didn't find srs_id for %s", pszWKT );
+    }
+    return -1;
+}
+
+/************************************************************************/
+/*                         StartTransaction()                           */
+/*                                                                      */
+/* Should only be called by user code. Not driver internals.            */
+/************************************************************************/
+
+OGRErr OGRDB2DataSource::StartTransaction(CPL_UNUSED int bForce)
+{
+    if (!m_oSession.BeginTransaction())
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Failed to start transaction: %s", m_oSession.GetLastError());
+        return OGRERR_FAILURE;
+    }
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                         CommitTransaction()                          */
+/*                                                                      */
+/* Should only be called by user code. Not driver internals.            */
+/************************************************************************/
+
+OGRErr OGRDB2DataSource::CommitTransaction()
+{
+    if (!m_oSession.CommitTransaction())
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Failed to commit transaction: %s",
+                  m_oSession.GetLastError() );
+
+        for( int iLayer = 0; iLayer < m_nLayers; iLayer++ )
+        {
+            if( m_papoLayers[iLayer]->GetLayerStatus()
+                    == DB2LAYERSTATUS_INITIAL )
+                m_papoLayers[iLayer]->SetLayerStatus(DB2LAYERSTATUS_DISABLED);
+        }
+        return OGRERR_FAILURE;
+    }
+
+    /* set the status for the newly created layers */
+    for( int iLayer = 0; iLayer < m_nLayers; iLayer++ )
+    {
+        if( m_papoLayers[iLayer]->GetLayerStatus() == DB2LAYERSTATUS_INITIAL )
+            m_papoLayers[iLayer]->SetLayerStatus(DB2LAYERSTATUS_CREATED);
+    }
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                        RollbackTransaction()                         */
+/*                                                                      */
+/* Should only be called by user code. Not driver internals.            */
+/************************************************************************/
+
+OGRErr OGRDB2DataSource::RollbackTransaction()
+{
+    /* set the status for the newly created layers */
+    for( int iLayer = 0; iLayer < m_nLayers; iLayer++ )
+    {
+        if( m_papoLayers[iLayer]->GetLayerStatus() == DB2LAYERSTATUS_INITIAL )
+            m_papoLayers[iLayer]->SetLayerStatus(DB2LAYERSTATUS_DISABLED);
+    }
+
+    if (!m_oSession.RollbackTransaction())
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Failed to roll back transaction: %s",
+                  m_oSession.GetLastError() );
+        return OGRERR_FAILURE;
+    }
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                         OpenRaster()                                 */
+/************************************************************************/
+
+int OGRDB2DataSource::OpenRaster( const char* pszTableName,
+                                  const char* pszIdentifier,
+                                  const char* pszDescription,
+                                  int nSRSId,
+                                  double dfMinX,
+                                  double dfMinY,
+                                  double dfMaxX,
+                                  double dfMaxY,
+                                  const char* pszContentsMinX,
+                                  const char* pszContentsMinY,
+                                  const char* pszContentsMaxX,
+                                  const char* pszContentsMaxY,
+                                  char** papszOpenOptionsIn )
+{
+    if( dfMinX >= dfMaxX || dfMinY >= dfMaxY )
+        return FALSE;
+    CPLDebug("OGRDB2DataSource::OpenRaster", "pszTableName: '%s'", pszTableName);
+    m_bRecordInsertedInGPKGContent = TRUE;
+    m_nSRID = nSRSId;
+    if( nSRSId > 0 )
+    {
+        OGRSpatialReference* poSRS = FetchSRS( nSRSId );
+        CPLDebug("OGRDB2DataSource::OpenRaster", "nSRSId: '%d'", nSRSId);
+        if( poSRS )
+        {
+            poSRS->exportToWkt(&m_pszProjection);
+            CPLDebug("OGRDB2DataSource::OpenRaster", "m_pszProjection: '%s'", m_pszProjection);
+//LATER            delete poSRS;
+        }
+    }
+
+    OGRDB2Statement oStatement( &m_oSession );
+    oStatement.Appendf( "SELECT zoom_level, pixel_x_size, pixel_y_size, "
+                        "tile_width, tile_height, matrix_width, matrix_height "
+                        "FROM gpkg.tile_matrix tm "
+                        "WHERE table_name = '%s' AND pixel_x_size > 0 "
+                        "AND pixel_y_size > 0 AND tile_width > 0 "
+                        "AND tile_height > 0 AND matrix_width > 0 "
+                        "AND matrix_height > 0",
+                        pszTableName);
+    char* pszSQL = CPLStrdup(oStatement.GetCommand());  // save to use later
+    int   bGotRow = FALSE;
+    const char* pszZoomLevel =  CSLFetchNameValue(papszOpenOptionsIn, "ZOOM_LEVEL");
+    CPLDebug("OGRDB2DataSource::OpenRaster",
+             "pszZoomLevel: '%s', m_bUpdate: %d", pszZoomLevel, m_bUpdate);
+
+    if( pszZoomLevel )
+    {
+        if( m_bUpdate )
+            oStatement.Appendf(" AND zoom_level <= %d", atoi(pszZoomLevel));
+        else
+        {
+            oStatement.Appendf(" AND (zoom_level = %d OR (zoom_level < %d "
+                               "AND EXISTS(SELECT 1 FROM '%s' "
+                               "WHERE zoom_level = tm.zoom_level FETCH FIRST ROW ONLY)))",
+                               atoi(pszZoomLevel), atoi(pszZoomLevel),
+                               pszTableName);
+        }
+    }
+    // In read-only mode, only lists non empty zoom levels
+    else if( !m_bUpdate )
+    {
+        oStatement.Appendf(" AND EXISTS(SELECT 1 FROM %s "
+                           "WHERE zoom_level = tm.zoom_level FETCH FIRST ROW ONLY)",
+                           pszTableName);
+    }
+    else if( pszZoomLevel == NULL )
+    {
+        oStatement.Appendf(" AND zoom_level <= (SELECT MAX(zoom_level) FROM %s)",
+                           pszTableName);
+    }
+    oStatement.Appendf(" ORDER BY zoom_level DESC");
+
+    if( oStatement.DB2Execute("OGR_DB2DataSource::OpenRaster"))
+    {
+        if( oStatement.Fetch())
+        {
+
+            CPLDebug("OGR_DB2DataSource::OpenRaster", "col 0: %s",
+                     oStatement.GetColData(0));
+            bGotRow = TRUE;
+        } else {
+            CPLDebug("OGR_DB2DataSource::OpenRaster", "Fetch1 failed");
+        }
+    } else {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "%s", m_oSession.GetLastError() );
+        CPLFree(pszSQL);
+        return FALSE;
+    }
+
+    if( !bGotRow &&
+            pszContentsMinX != NULL && pszContentsMinY != NULL &&
+            pszContentsMaxX != NULL && pszContentsMaxY != NULL )
+    {
+        oStatement.Clear();
+        oStatement.Append(pszSQL);
+        oStatement.Append(" ORDER BY zoom_level DESC FETCH FIRST ROW ONLY");
+        CPLDebug("OGR_DB2DataSource::OpenRaster", "SQL: %s",
+                 oStatement.GetCommand());
+        if( oStatement.DB2Execute("OGR_DB2DataSource::OpenRaster"))
+        {
+            if( oStatement.Fetch())
+            {
+
+                CPLDebug("OGR_DB2DataSource::OpenRaster", "col 0: %s",
+                         oStatement.GetColData(0));
+                bGotRow = TRUE;
+            }
+        } else {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "%s", m_oSession.GetLastError() );
+            CPLDebug("OGR_DB2DataSource::OpenRaster", "error: %s",
+                     m_oSession.GetLastError() );
+            CPLFree(pszSQL);
+            return FALSE;
+        }
+    }
+    if( !bGotRow )
+    {
+        CPLFree(pszSQL);
+        return FALSE;
+    }
+    CPLFree(pszSQL);
+
+    OGRDB2Statement oStatement2( &m_oSession );
+    // If USE_TILE_EXTENT=YES, then query the tile table to find which tiles
+    // actually exist.
+    CPLString osContentsMinX, osContentsMinY, osContentsMaxX, osContentsMaxY;
+    if( CPLTestBool(CSLFetchNameValueDef(papszOpenOptionsIn, "USE_TILE_EXTENT", "NO")) )
+    {
+        oStatement2.Appendf(
+            "SELECT MIN(tile_column), MIN(tile_row), MAX(tile_column), MAX(tile_row) FROM %s WHERE zoom_level = %d",
+            pszTableName, atoi(oStatement.GetColData(0)));
+
+        if( oStatement2.DB2Execute("OGR_DB2DataSource::OpenRaster"))
+        {
+            if( oStatement2.Fetch())
+            {
+                CPLDebug("OGR_DB2DataSource::OpenRaster", "col 0: %s",
+                         oStatement2.GetColData(0));
+            } else {
+                return FALSE;
+            }
+        } else {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "%s", m_oSession.GetLastError() );
+            CPLDebug("OGR_DB2DataSource::OpenRaster", "error: %s",
+                     m_oSession.GetLastError() );
+            return FALSE;
+        }
+
+        double dfPixelXSize = CPLAtof(oStatement.GetColData( 1));
+        double dfPixelYSize = CPLAtof(oStatement.GetColData( 2));
+        int nTileWidth = atoi(oStatement.GetColData( 3));
+        int nTileHeight = atoi(oStatement.GetColData( 4));
+        osContentsMinX = CPLSPrintf("%.18g", dfMinX + dfPixelXSize * nTileWidth * atoi(oStatement2.GetColData( 0)));
+        osContentsMaxY = CPLSPrintf("%.18g", dfMaxY - dfPixelYSize * nTileHeight * atoi(oStatement2.GetColData( 1)));
+        osContentsMaxX = CPLSPrintf("%.18g", dfMinX + dfPixelXSize * nTileWidth * (1 + atoi(oStatement2.GetColData( 2))));
+        osContentsMinY = CPLSPrintf("%.18g", dfMaxY - dfPixelYSize * nTileHeight * (1 + atoi(oStatement2.GetColData( 3))));
+        pszContentsMinX = osContentsMinX.c_str();
+        pszContentsMinY = osContentsMinY.c_str();
+        pszContentsMaxX = osContentsMaxX.c_str();
+        pszContentsMaxY = osContentsMaxY.c_str();
+
+    }
+
+    if(! InitRaster ( NULL, pszTableName, dfMinX, dfMinY, dfMaxX, dfMaxY,
+                      pszContentsMinX, pszContentsMinY, pszContentsMaxX, pszContentsMaxY,
+                      papszOpenOptionsIn, &oStatement, 0) )
+    {
+        return FALSE;
+    }
+
+    CheckUnknownExtensions(TRUE);
+
+    // Do this after CheckUnknownExtensions() so that m_eTF is set to GPKG_TF_WEBP
+    // if the table already registers the gpkg_webp extension
+    const char* pszTF = CSLFetchNameValue(papszOpenOptionsIn, "TILE_FORMAT");
+    if( pszTF )
+    {
+        if( !m_bUpdate )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "DRIVER open option ignored in read-only mode");
+        }
+        else
+        {
+            GPKGTileFormat eTF = GetTileFormat(pszTF);
+            if( eTF == GPKG_TF_WEBP && m_eTF != eTF )
+            {
+                if( !RegisterWebPExtension() )
+                    return FALSE;
+            }
+            m_eTF = eTF;
+        }
+    }
+
+    ParseCompressionOptions(papszOpenOptionsIn);
+    CPLDebug("OGR_DB2DataSource::OpenRaster", "after ParseCompress");
+    m_osWHERE = CSLFetchNameValueDef(papszOpenOptionsIn, "WHERE", "");
+
+    // Set metadata
+    if( pszIdentifier && pszIdentifier[0] )
+        GDALPamDataset::SetMetadataItem("IDENTIFIER", pszIdentifier);
+    if( pszDescription && pszDescription[0] )
+        GDALPamDataset::SetMetadataItem("DESCRIPTION", pszDescription);
+    CPLDebug("OGR_DB2DataSource::OpenRaster", "check for overviews");
+    // Add overviews
+    for( int i = 1; oStatement.Fetch(); i++ )
+    {
+        CPLDebug("OGR_DB2DataSource::OpenRaster",
+                 "fetch overview row: %d", i);
+        OGRDB2DataSource* poOvrDS = new OGRDB2DataSource();
+        poOvrDS->InitRaster ( this, pszTableName, dfMinX, dfMinY, dfMaxX, dfMaxY,
+                              pszContentsMinX, pszContentsMinY, pszContentsMaxX, pszContentsMaxY,
+                              papszOpenOptionsIn, &oStatement, i);
+
+        m_papoOverviewDS = (OGRDB2DataSource**) CPLRealloc(m_papoOverviewDS,
+                           sizeof(OGRDB2DataSource*) * (m_nOverviewCount+1));
+        m_papoOverviewDS[m_nOverviewCount ++] = poOvrDS;
+
+        int nTileWidth, nTileHeight;
+        poOvrDS->GetRasterBand(1)->GetBlockSize(&nTileWidth, &nTileHeight);
+        if( poOvrDS->GetRasterXSize() < nTileWidth &&
+                poOvrDS->GetRasterYSize() < nTileHeight )
+        {
+            break;
+        }
+    }
+
+    CPLDebug("OGR_DB2DataSource::OpenRaster", "exiting");
+
+    return TRUE;
+}
+
+
+/************************************************************************/
+/*                         InitRaster()                                 */
+/************************************************************************/
+
+int OGRDB2DataSource::InitRaster ( OGRDB2DataSource* poParentDS,
+                                   const char* pszTableName,
+                                   double dfMinX,
+                                   double dfMinY,
+                                   double dfMaxX,
+                                   double dfMaxY,
+                                   const char* pszContentsMinX,
+                                   const char* pszContentsMinY,
+                                   const char* pszContentsMaxX,
+                                   const char* pszContentsMaxY,
+                                   char** papszOpenOptionsIn,
+                                   OGRDB2Statement* oStatement,
+                                   int nIdxInResult )
+{
+    m_osRasterTable = pszTableName;
+    m_dfTMSMinX = dfMinX;
+    m_dfTMSMaxY = dfMaxY;
+    CPLDebug("OGRDB2DataSource::InitRaster1", "nIdxInResult: %d", nIdxInResult);
+    if (nIdxInResult > 0) {
+        CPLDebug("OGRDB2DataSource::InitRaster1",
+                 "Serious problem as we don't support nIdxInResult");
+
+    }
+    int nZoomLevel = atoi(oStatement->GetColData( 0));
+    double dfPixelXSize = CPLAtof(oStatement->GetColData( 1));
+    double dfPixelYSize = CPLAtof(oStatement->GetColData( 2));
+    int nTileWidth = atoi(oStatement->GetColData( 3));
+    int nTileHeight = atoi(oStatement->GetColData( 4));
+    int nTileMatrixWidth = atoi(oStatement->GetColData( 5));
+    int nTileMatrixHeight = atoi(oStatement->GetColData( 6));
+
+    /* Use content bounds in priority over tile_matrix_set bounds */
+    double dfGDALMinX = dfMinX;
+    double dfGDALMinY = dfMinY;
+    double dfGDALMaxX = dfMaxX;
+    double dfGDALMaxY = dfMaxY;
+    pszContentsMinX = CSLFetchNameValueDef(papszOpenOptionsIn, "MINX", pszContentsMinX);
+    pszContentsMinY = CSLFetchNameValueDef(papszOpenOptionsIn, "MINY", pszContentsMinY);
+    pszContentsMaxX = CSLFetchNameValueDef(papszOpenOptionsIn, "MAXX", pszContentsMaxX);
+    pszContentsMaxY = CSLFetchNameValueDef(papszOpenOptionsIn, "MAXY", pszContentsMaxY);
+    if( pszContentsMinX != NULL && pszContentsMinY != NULL &&
+            pszContentsMaxX != NULL && pszContentsMaxY != NULL )
+    {
+        dfGDALMinX = CPLAtof(pszContentsMinX);
+        dfGDALMinY = CPLAtof(pszContentsMinY);
+        dfGDALMaxX = CPLAtof(pszContentsMaxX);
+        dfGDALMaxY = CPLAtof(pszContentsMaxY);
+    }
+    if( dfGDALMinX >= dfGDALMaxX || dfGDALMinY >= dfGDALMaxY )
+    {
+        return FALSE;
+    }
+
+    int nBandCount = atoi(CSLFetchNameValueDef(papszOpenOptionsIn, "BAND_COUNT", "4"));
+    if( nBandCount != 1 && nBandCount != 2 && nBandCount != 3 && nBandCount != 4 )
+        nBandCount = 4;
+
+    return InitRaster(poParentDS, pszTableName, nZoomLevel, nBandCount, dfMinX, dfMaxY,
+                      dfPixelXSize, dfPixelYSize, nTileWidth, nTileHeight,
+                      nTileMatrixWidth, nTileMatrixHeight,
+                      dfGDALMinX, dfGDALMinY, dfGDALMaxX, dfGDALMaxY );
+}
+
+/************************************************************************/
+/*                         InitRaster()                                 */
+/************************************************************************/
+
+int OGRDB2DataSource::InitRaster ( OGRDB2DataSource* poParentDS,
+                                   const char* pszTableName,
+                                   int nZoomLevel,
+                                   int nBandCount,
+                                   double dfTMSMinX,
+                                   double dfTMSMaxY,
+                                   double dfPixelXSize,
+                                   double dfPixelYSize,
+                                   int nTileWidth,
+                                   int nTileHeight,
+                                   int nTileMatrixWidth,
+                                   int nTileMatrixHeight,
+                                   double dfGDALMinX,
+                                   double dfGDALMinY,
+                                   double dfGDALMaxX,
+                                   double dfGDALMaxY )
+{
+    CPLDebug("OGRDB2DataSource::InitRaster2","Entering");
+    m_osRasterTable = pszTableName;
+    m_dfTMSMinX = dfTMSMinX;
+    m_dfTMSMaxY = dfTMSMaxY;
+    m_nZoomLevel = nZoomLevel;
+    m_nTileMatrixWidth = nTileMatrixWidth;
+    m_nTileMatrixHeight = nTileMatrixHeight;
+
+    m_bGeoTransformValid = TRUE;
+    m_adfGeoTransform[0] = dfGDALMinX;
+    m_adfGeoTransform[1] = dfPixelXSize;
+    m_adfGeoTransform[3] = dfGDALMaxY;
+    m_adfGeoTransform[5] = -dfPixelYSize;
+    double dfRasterXSize = 0.5 + (dfGDALMaxX - dfGDALMinX) / dfPixelXSize;
+    double dfRasterYSize = 0.5 + (dfGDALMaxY - dfGDALMinY) / dfPixelYSize;
+    if( dfRasterXSize > INT_MAX || dfRasterYSize > INT_MAX )
+        return FALSE;
+    nRasterXSize = (int)dfRasterXSize;
+    nRasterYSize = (int)dfRasterYSize;
+
+    m_pabyCachedTiles = (GByte*) VSI_MALLOC3_VERBOSE(4 * 4, nTileWidth, nTileHeight);
+    if( m_pabyCachedTiles == NULL )
+    {
+        return FALSE;
+    }
+
+    for(int i = 1; i <= nBandCount; i ++)
+        SetBand( i, new GDALDB2RasterBand(this, i, nTileWidth, nTileHeight) );
+
+    ComputeTileAndPixelShifts();
+
+    GDALPamDataset::SetMetadataItem("INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE");
+    GDALPamDataset::SetMetadataItem("ZOOM_LEVEL", CPLSPrintf("%d", m_nZoomLevel));
+
+    if( poParentDS )
+    {
+        m_poParentDS = poParentDS;
+        m_bUpdate = poParentDS->m_bUpdate;
+        eAccess = poParentDS->eAccess;
+        m_eTF = poParentDS->m_eTF;
+        m_nQuality = poParentDS->m_nQuality;
+        m_nZLevel = poParentDS->m_nZLevel;
+        m_bDither = poParentDS->m_bDither;
+        /*m_nSRID = poParentDS->m_nSRID;*/
+        m_osWHERE = poParentDS->m_osWHERE;
+        SetDescription(CPLSPrintf("%s - zoom_level=%d",
+                                  poParentDS->GetDescription(), m_nZoomLevel));
+    }
+
+    return TRUE;
+}
+
+
+/************************************************************************/
+/*                         GetTileFormat()                              */
+/************************************************************************/
+
+static GPKGTileFormat GetTileFormat(const char* pszTF )
+{
+    GPKGTileFormat eTF = GPKG_TF_PNG_JPEG;
+    if( pszTF )
+    {
+        if( EQUAL(pszTF, "PNG_JPEG") )
+            eTF = GPKG_TF_PNG_JPEG;
+        else if( EQUAL(pszTF, "PNG") )
+            eTF = GPKG_TF_PNG;
+        else if( EQUAL(pszTF, "PNG8") )
+            eTF = GPKG_TF_PNG8;
+        else if( EQUAL(pszTF, "JPEG") )
+            eTF = GPKG_TF_JPEG;
+        else if( EQUAL(pszTF, "WEBP") )
+            eTF = GPKG_TF_WEBP;
+    }
+    return eTF;
+}
+
+/************************************************************************/
+/*                          RegisterWebPExtension()                     */
+/************************************************************************/
+
+int OGRDB2DataSource::RegisterWebPExtension()
+{
+    CPLDebug("OGRDB2DataSource::RegisterWebPExtension", "NO-OP");
+
+    CreateExtensionsTableIfNecessary();
+#ifdef LATER
+    char* pszSQL = sqlite3_mprintf(
+                       "INSERT INTO gpkg_extensions "
+                       "(table_name, column_name, extension_name, definition, scope) "
+                       "VALUES "
+                       "('%q', 'tile_data', 'gpkg_webp', 'GeoPackage 1.0 Specification Annex P', 'read-write')",
+                       m_osRasterTable.c_str());
+    OGRErr eErr = SQLCommand(hDB, pszSQL);
+    sqlite3_free(pszSQL);
+    if ( OGRERR_NONE != eErr )
+        return FALSE;
+#endif
+    return TRUE;
+}
+
+
+/************************************************************************/
+/*                    CheckUnknownExtensions()                          */
+/************************************************************************/
+
+void OGRDB2DataSource::CheckUnknownExtensions(int bCheckRasterTable)
+{
+    if( !HasExtensionsTable() )
+        return;
+    CPLDebug("OGRDB2DataSource::CheckUnknownExtensions","NO-OP");
+#ifdef LATER
+    char* pszSQL;
+    if( !bCheckRasterTable)
+        pszSQL = sqlite3_mprintf(
+                     "SELECT extension_name, definition, scope FROM gpkg_extensions WHERE table_name IS NULL AND extension_name != 'gdal_aspatial'");
+    else
+        pszSQL = sqlite3_mprintf(
+                     "SELECT extension_name, definition, scope FROM gpkg_extensions WHERE table_name = '%q'",
+                     m_osRasterTable.c_str());
+
+    SQLResult oResultTable;
+    OGRErr err = SQLQuery(GetDB(), pszSQL, &oResultTable);
+    sqlite3_free(pszSQL);
+    if ( err == OGRERR_NONE && oResultTable.nRowCount > 0 )
+    {
+        for(int i=0; i<oResultTable.nRowCount; i++)
+        {
+            const char* pszExtName = SQLResultGetValue(&oResultTable, 0, i);
+            const char* pszDefinition = SQLResultGetValue(&oResultTable, 1, i);
+            const char* pszScope = SQLResultGetValue(&oResultTable, 2, i);
+            if( pszExtName == NULL ) pszExtName = "(null)";
+            if( pszDefinition == NULL ) pszDefinition = "(null)";
+            if( pszScope == NULL ) pszScope = "(null)";
+
+            if( EQUAL(pszExtName, "gpkg_webp") )
+            {
+                if( GDALGetDriverByName("WEBP") == NULL )
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "Table %s contains WEBP tiles, but GDAL configured "
+                             "without WEBP support. Data will be missing",
+                             m_osRasterTable.c_str());
+                }
+                m_eTF = GPKG_TF_WEBP;
+                continue;
+            }
+            if( EQUAL(pszExtName, "gpkg_zoom_other") )
+            {
+                m_bZoomOther = TRUE;
+                continue;
+            }
+
+            if( GetUpdate() && EQUAL(pszScope, "write-only") )
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "Database relies on the '%s' (%s) extension that should "
+                         "be implemented for safe write-support, but is not currently. "
+                         "Update of that database are strongly discouraged to avoid corruption.",
+                         pszExtName, pszDefinition);
+            }
+            else if( GetUpdate() && EQUAL(pszScope, "read-write") )
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "Database relies on the '%s' (%s) extension that should "
+                         "be implemented in order to read/write it safely, but is not currently. "
+                         "Some data may be missing while reading that database, and updates are strongly discouraged.",
+                         pszExtName, pszDefinition);
+            }
+            else if( EQUAL(pszScope, "read-write") )
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "Database relies on the '%s' (%s) extension that should "
+                         "be implemented in order to read it safely, but is not currently. "
+                         "Some data may be missing while reading that database.",
+                         pszExtName, pszDefinition);
+            }
+        }
+    }
+    SQLResultFree(&oResultTable);
+#endif
+}
+
+/************************************************************************/
+/*                        ParseCompressionOptions()                     */
+/************************************************************************/
+
+void OGRDB2DataSource::ParseCompressionOptions(char** papszOptions)
+{
+    const char* pszZLevel = CSLFetchNameValue(papszOptions, "ZLEVEL");
+    if( pszZLevel )
+        m_nZLevel = atoi(pszZLevel);
+
+    const char* pszQuality = CSLFetchNameValue(papszOptions, "QUALITY");
+    if( pszQuality )
+        m_nQuality = atoi(pszQuality);
+
+    const char* pszDither = CSLFetchNameValue(papszOptions, "DITHER");
+    if( pszDither )
+        m_bDither = CPLTestBool(pszDither);
+}
+
+
+/************************************************************************/
+/*                      ComputeTileAndPixelShifts()                     */
+/************************************************************************/
+
+void OGRDB2DataSource::ComputeTileAndPixelShifts()
+{
+    CPLDebug("OGRDB2DataSource::ComputeTileAndPixelShifts", "Entering");
+    int nTileWidth, nTileHeight;
+    GetRasterBand(1)->GetBlockSize(&nTileWidth, &nTileHeight);
+
+    // Compute shift between GDAL origin and TileMatrixSet origin
+    int nShiftXPixels = (int)floor(0.5 + (m_adfGeoTransform[0] - m_dfTMSMinX) /  m_adfGeoTransform[1]);
+    m_nShiftXTiles = (int)floor(1.0 * nShiftXPixels / nTileWidth);
+    m_nShiftXPixelsMod = ((nShiftXPixels % nTileWidth) + nTileWidth) % nTileWidth;
+    int nShiftYPixels = (int)floor(0.5 + (m_adfGeoTransform[3] - m_dfTMSMaxY) /  m_adfGeoTransform[5]);
+    m_nShiftYTiles = (int)floor(1.0 * nShiftYPixels / nTileHeight);
+    m_nShiftYPixelsMod = ((nShiftYPixels % nTileHeight) + nTileHeight) % nTileHeight;
+
+}
+
+
+/************************************************************************/
+/*                  CreateExtensionsTableIfNecessary()                  */
+/************************************************************************/
+
+OGRErr OGRDB2DataSource::CreateExtensionsTableIfNecessary()
+{
+
+    /* Check if the table gpkg_extensions exists */
+    if( HasExtensionsTable() )
+        return OGRERR_NONE;
+    CPLDebug("OGRDB2DataSource::CreateExtensionsTableIfNecessary", "NO-OP");
+#ifdef LATER
+    /* Requirement 79 : Every extension of a GeoPackage SHALL be registered */
+    /* in a corresponding row in the gpkg_extensions table. The absence of a */
+    /* gpkg_extensions table or the absence of rows in gpkg_extensions table */
+    /* SHALL both indicate the absence of extensions to a GeoPackage. */
+    const char* pszCreateGpkgExtensions =
+        "CREATE TABLE gpkg_extensions ("
+        "table_name TEXT,"
+        "column_name TEXT,"
+        "extension_name TEXT NOT NULL,"
+        "definition TEXT NOT NULL,"
+        "scope TEXT NOT NULL,"
+        "CONSTRAINT ge_tce UNIQUE (table_name, column_name, extension_name)"
+        ")";
+
+    return SQLCommand(hDB, pszCreateGpkgExtensions);
+#endif
+    return OGRERR_NONE;
+}
+
+
+/************************************************************************/
+/*                         HasExtensionsTable()                         */
+/************************************************************************/
+
+int OGRDB2DataSource::HasExtensionsTable()
+{
+    CPLDebug("OGRDB2DataSource::HasExtensionsTable", "NO-OP");
+#ifdef LATER
+    SQLResult oResultTable;
+    OGRErr err = SQLQuery(hDB,
+                          "SELECT * FROM sqlite_master WHERE name = 'gpkg_extensions' "
+                          "AND type IN ('table', 'view')", &oResultTable);
+    int bHasExtensionsTable = ( err == OGRERR_NONE && oResultTable.nRowCount == 1 );
+    SQLResultFree(&oResultTable);
+    return bHasExtensionsTable;
+#endif
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                             FlushCache()                             */
+/************************************************************************/
+
+void OGRDB2DataSource::FlushCache()
+{
+    DB2_DEBUG_ENTER("OGRDB2DataSource::FlushCache");
+    FlushCacheWithErrCode();
+    DB2_DEBUG_EXIT("OGRDB2DataSource::FlushCache");
+
+}
+
+CPLErr OGRDB2DataSource::FlushCacheWithErrCode()
+
+{
+    CPLDebug("OGRDB2DataSource::FlushCacheWithErrCode","m_bInFlushCache %d", m_bInFlushCache);
+
+    if( m_bInFlushCache )
+        return CE_None;
+    m_bInFlushCache = TRUE;
+    // Short circuit GDALPamDataset to avoid serialization to .aux.xml
+    CPLDebug("OGRDB2DataSource::FlushCacheWithErrCode","calling GDALDataset::FlushCache");
+    GDALDataset::FlushCache();
+/* Not sure what this has to do with raster operations
+    for( int i = 0; i < m_nLayers; i++ )
+    {
+        m_papoLayers[i]->RunDeferredCreationIfNecessary();
+        m_papoLayers[i]->CreateSpatialIndexIfNecessary();
+    }
+*/
+
+    CPLErr eErr = CE_None;
+    CPLDebug("OGRDB2DataSource::FlushCacheWithErrCode","m_bUpdate %d", m_bUpdate);
+
+    if( m_bUpdate )
+    {
+        if( m_nShiftXPixelsMod || m_nShiftYPixelsMod )
+        {
+            eErr = FlushRemainingShiftedTiles();
+        }
+        else
+        {
+            eErr = WriteTile();
+        }
+    }
+
+    OGRDB2DataSource* poMainDS = m_poParentDS ? m_poParentDS : this;
+    CPLDebug("OGRDB2DataSource::FlushCacheWithErrCode",
+             "m_nTileInsertionCount: %d", poMainDS->m_nTileInsertionCount);
+
+    if( poMainDS->m_nTileInsertionCount )
+    {
+        poMainDS->SoftCommitTransaction();
+        poMainDS->m_nTileInsertionCount = 0;
+    }
+
+    m_bInFlushCache = FALSE;
+    CPLDebug("OGRDB2DataSource::FlushCacheWithErrCode","exiting; eErr: %d", eErr);
+
+    return eErr;
+
+}
+
+
+/************************************************************************/
+/*                         SoftStartTransaction()                       */
+/************************************************************************/
+
+int OGRDB2DataSource::SoftStartTransaction()
+{
+    CPLDebug("OGRDB2DataSource::SoftStartTransaction", "enter");
+    return m_oSession.BeginTransaction();
+}
+
+
+
+/************************************************************************/
+/*                         SoftCommitTransaction()                      */
+/************************************************************************/
+
+int OGRDB2DataSource::SoftCommitTransaction()
+{
+    CPLDebug("OGRDB2DataSource::SoftCommitTransaction", "enter");
+    return m_oSession.CommitTransaction();
+}
+
+
+
+/************************************************************************/
+/*                         SoftRollbackTransaction()                    */
+/************************************************************************/
+
+int OGRDB2DataSource::SoftRollbackTransaction()
+{
+    CPLDebug("OGRDB2DataSource::SoftRollbackTransaction", "enter");
+    return m_oSession.RollbackTransaction();
+}
+
+
+
+/************************************************************************/
+/*                            CreateCopy()                              */
+/************************************************************************/
+
+typedef struct
+{
+    const char*         pszName;
+    GDALResampleAlg     eResampleAlg;
+} WarpResamplingAlg;
+
+static const WarpResamplingAlg asResamplingAlg[] =
+{
+    { "BILINEAR", GRA_Bilinear },
+    { "CUBIC", GRA_Cubic },
+    { "CUBICSPLINE", GRA_CubicSpline },
+    { "LANCZOS", GRA_Lanczos },
+    { "MODE", GRA_Mode },
+    { "AVERAGE", GRA_Average },
+};
+
+void DumpStringList(char **papszStrList)
+{
+    if (papszStrList == NULL)
+        return ;
+
+    while( *papszStrList != NULL )
+    {
+        CPLDebug("DumpStringList",": '%s'", *papszStrList);
+        ++papszStrList;
+    }
+    return ;
+}
+
+
+
+GDALDataset* OGRDB2DataSource::CreateCopy( const char *pszFilename,
+        GDALDataset *poSrcDS,
+        int bStrict,
+        char ** papszOptions,
+        GDALProgressFunc pfnProgress,
+        void * pProgressData )
+{
+    CPLDebug("OGRDB2DataSource::CreateCopy","pszFilename: '%s'", pszFilename);
+    CPLDebug("OGRDB2DataSource::CreateCopy","srcDescription: '%s'", poSrcDS->GetDescription());
+    const char* pszTilingScheme =
+        CSLFetchNameValueDef(papszOptions, "TILING_SCHEME", "CUSTOM");
+    DumpStringList(papszOptions);
+    char** papszUpdatedOptions = CSLDuplicate(papszOptions);
+    if( CSLFetchNameValue(papszOptions, "RASTER_TABLE") == NULL )
+    {
+        papszUpdatedOptions = CSLSetNameValue(papszUpdatedOptions,
+                                              "RASTER_TABLE",
+                                              CPLGetBasename(poSrcDS->GetDescription()));
+    }
+    DumpStringList(papszUpdatedOptions);
+    if( EQUAL(pszTilingScheme, "CUSTOM") )
+    {
+        GDALDriver* poThisDriver = (GDALDriver*)GDALGetDriverByName("DB2ODBC");
+        if( !poThisDriver )
+        {
+            CSLDestroy(papszUpdatedOptions);
+            return NULL;
+        }
+        CPLDebug("OGRDB2DataSource::CreateCopy","calling DefaultCreateCopy");
+
+        GDALDataset* poDS = poThisDriver->DefaultCreateCopy(
+                                pszFilename, poSrcDS, bStrict,
+                                papszUpdatedOptions, pfnProgress, pProgressData );
+        CPLDebug("OGRDB2DataSource::CreateCopy","returned from DefaultCreateCopy");
+        CSLDestroy(papszUpdatedOptions);
+        return poDS;
+    }
+
+    int nBands = poSrcDS->GetRasterCount();
+    if( nBands != 1 && nBands != 2 && nBands != 3 && nBands != 4 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Only 1 (Grey/ColorTable), 2 (Grey+Alpha), 3 (RGB) or 4 (RGBA) band dataset supported");
+        CSLDestroy(papszUpdatedOptions);
+        return NULL;
+    }
+
+    int bFound = FALSE;
+    int nEPSGCode = 0;
+    size_t iScheme;
+    for(iScheme = 0;
+            iScheme < sizeof(asTilingShemes)/sizeof(asTilingShemes[0]);
+            iScheme++ )
+    {
+        if( EQUAL(pszTilingScheme, asTilingShemes[iScheme].pszName) )
+        {
+            nEPSGCode = asTilingShemes[iScheme].nEPSGCode;
+            bFound = TRUE;
+            break;
+        }
+    }
+    if( !bFound )
+    {
+        CSLDestroy(papszUpdatedOptions);
+        return NULL;
+    }
+
+    OGRSpatialReference oSRS;
+    if( oSRS.importFromEPSG(nEPSGCode) != OGRERR_NONE )
+    {
+        CSLDestroy(papszUpdatedOptions);
+        return NULL;
+    }
+    char* pszWKT = NULL;
+    oSRS.exportToWkt(&pszWKT);
+    char** papszTO = CSLSetNameValue( NULL, "DST_SRS", pszWKT );
+    void* hTransformArg =
+        GDALCreateGenImgProjTransformer2( poSrcDS, NULL, papszTO );
+    if( hTransformArg == NULL )
+    {
+        CSLDestroy(papszUpdatedOptions);
+        CPLFree(pszWKT);
+        CSLDestroy(papszTO);
+        return NULL;
+    }
+
+    GDALTransformerInfo* psInfo = (GDALTransformerInfo*)hTransformArg;
+    double adfGeoTransform[6];
+    double adfExtent[4];
+    int    nXSize, nYSize;
+
+    if ( GDALSuggestedWarpOutput2( poSrcDS,
+                                   psInfo->pfnTransform, hTransformArg,
+                                   adfGeoTransform,
+                                   &nXSize, &nYSize,
+                                   adfExtent, 0 ) != CE_None )
+    {
+        CSLDestroy(papszUpdatedOptions);
+        CPLFree(pszWKT);
+        CSLDestroy(papszTO);
+        GDALDestroyGenImgProjTransformer( hTransformArg );
+        return NULL;
+    }
+
+    GDALDestroyGenImgProjTransformer( hTransformArg );
+    hTransformArg = NULL;
+
+    int nZoomLevel;
+    double dfComputedRes = adfGeoTransform[1];
+    double dfPrevRes = 0, dfRes = 0;
+    for(nZoomLevel = 0; nZoomLevel < 25; nZoomLevel++)
+    {
+        dfRes = asTilingShemes[iScheme].dfPixelXSizeZoomLevel0 / (1 << nZoomLevel);
+        if( dfComputedRes > dfRes )
+            break;
+        dfPrevRes = dfRes;
+    }
+    if( nZoomLevel == 25 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Could not find an appropriate zoom level");
+        CSLDestroy(papszUpdatedOptions);
+        CPLFree(pszWKT);
+        CSLDestroy(papszTO);
+        return NULL;
+    }
+
+    const char* pszZoomLevelStrategy = CSLFetchNameValueDef(papszOptions,
+                                       "ZOOM_LEVEL_STRATEGY",
+                                       "AUTO");
+    if( fabs( dfComputedRes - dfRes ) / dfRes > 1e-8 )
+    {
+        if( EQUAL(pszZoomLevelStrategy, "LOWER") )
+        {
+            if( nZoomLevel > 0 )
+                nZoomLevel --;
+        }
+        else if( EQUAL(pszZoomLevelStrategy, "UPPER") )
+        {
+            /* do nothing */
+        }
+        else if( nZoomLevel > 0 )
+        {
+            if( dfPrevRes / dfComputedRes < dfComputedRes / dfRes )
+                nZoomLevel --;
+        }
+    }
+
+    dfRes = asTilingShemes[iScheme].dfPixelXSizeZoomLevel0 / (1 << nZoomLevel);
+
+    double dfMinX = adfExtent[0];
+    double dfMinY = adfExtent[1];
+    double dfMaxX = adfExtent[2];
+    double dfMaxY = adfExtent[3];
+
+    nXSize = (int) ( 0.5 + ( dfMaxX - dfMinX ) / dfRes );
+    nYSize = (int) ( 0.5 + ( dfMaxY - dfMinY ) / dfRes );
+    adfGeoTransform[1] = dfRes;
+    adfGeoTransform[5] = -dfRes;
+
+    int nTargetBands = nBands;
+    /* For grey level or RGB, if there's reprojection involved, add an alpha */
+    /* channel */
+    if( (nBands == 1 && poSrcDS->GetRasterBand(1)->GetColorTable() == NULL) ||
+            nBands == 3 )
+    {
+        OGRSpatialReference oSrcSRS;
+        oSrcSRS.SetFromUserInput(poSrcDS->GetProjectionRef());
+        oSrcSRS.AutoIdentifyEPSG();
+        if( oSrcSRS.GetAuthorityCode(NULL) == NULL ||
+                atoi(oSrcSRS.GetAuthorityCode(NULL)) != nEPSGCode )
+        {
+            nTargetBands ++;
+        }
+    }
+
+    OGRDB2DataSource* poDS = new OGRDB2DataSource();
+    if( !(poDS->Create( pszFilename, nXSize, nYSize, nTargetBands, GDT_Byte,
+                        papszUpdatedOptions )) )
+    {
+        delete poDS;
+        CSLDestroy(papszUpdatedOptions);
+        CPLFree(pszWKT);
+        CSLDestroy(papszTO);
+        return NULL;
+    }
+    CSLDestroy(papszUpdatedOptions);
+    papszUpdatedOptions = NULL;
+    poDS->SetGeoTransform(adfGeoTransform);
+    poDS->SetProjection(pszWKT);
+    CPLFree(pszWKT);
+    pszWKT = NULL;
+
+    hTransformArg =
+        GDALCreateGenImgProjTransformer2( poSrcDS, poDS, papszTO );
+    CSLDestroy(papszTO);
+    if( hTransformArg == NULL )
+    {
+        delete poDS;
+        return NULL;
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Warp the transformer with a linear approximator                 */
+    /* -------------------------------------------------------------------- */
+    hTransformArg =
+        GDALCreateApproxTransformer( GDALGenImgProjTransform,
+                                     hTransformArg, 0.125 );
+    GDALApproxTransformerOwnsSubtransformer(hTransformArg, TRUE);
+
+    /* -------------------------------------------------------------------- */
+    /*      Setup warp options.                                             */
+    /* -------------------------------------------------------------------- */
+    GDALWarpOptions *psWO = GDALCreateWarpOptions();
+
+    psWO->papszWarpOptions = NULL;
+    psWO->eWorkingDataType = GDT_Byte;
+
+    GDALResampleAlg eResampleAlg = GRA_Bilinear;
+    const char* pszResampling = CSLFetchNameValue(papszOptions, "RESAMPLING");
+    if( pszResampling )
+    {
+        for(size_t iAlg = 0; iAlg < sizeof(asResamplingAlg)/sizeof(asResamplingAlg[0]); iAlg ++)
+        {
+            if( EQUAL(pszResampling, asResamplingAlg[iAlg].pszName) )
+            {
+                eResampleAlg = asResamplingAlg[iAlg].eResampleAlg;
+                break;
+            }
+        }
+    }
+    psWO->eResampleAlg = eResampleAlg;
+
+    psWO->hSrcDS = poSrcDS;
+    psWO->hDstDS = poDS;
+
+    psWO->pfnTransformer = GDALApproxTransform;
+    psWO->pTransformerArg = hTransformArg;
+
+    psWO->pfnProgress = pfnProgress;
+    psWO->pProgressArg = pProgressData;
+
+    /* -------------------------------------------------------------------- */
+    /*      Setup band mapping.                                             */
+    /* -------------------------------------------------------------------- */
+
+    if( nBands == 2 || nBands == 4 )
+        psWO->nBandCount = nBands - 1;
+    else
+        psWO->nBandCount = nBands;
+
+    psWO->panSrcBands = (int *) CPLMalloc(psWO->nBandCount*sizeof(int));
+    psWO->panDstBands = (int *) CPLMalloc(psWO->nBandCount*sizeof(int));
+
+    for( int i = 0; i < psWO->nBandCount; i++ )
+    {
+        psWO->panSrcBands[i] = i+1;
+        psWO->panDstBands[i] = i+1;
+    }
+
+    if( nBands == 2 || nBands == 4 )
+    {
+        psWO->nSrcAlphaBand = nBands;
+    }
+    if( nTargetBands == 2 || nTargetBands == 4 )
+    {
+        psWO->nDstAlphaBand = nTargetBands;
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Initialize and execute the warp.                                */
+    /* -------------------------------------------------------------------- */
+    GDALWarpOperation oWO;
+
+    CPLErr eErr = oWO.Initialize( psWO );
+    if( eErr == CE_None )
+    {
+        /*if( bMulti )
+            eErr = oWO.ChunkAndWarpMulti( 0, 0, nXSize, nYSize );
+        else*/
+        eErr = oWO.ChunkAndWarpImage( 0, 0, nXSize, nYSize );
+    }
+    if (eErr != CE_None)
+    {
+        delete poDS;
+        poDS = NULL;
+    }
+
+    GDALDestroyTransformer( hTransformArg );
+    GDALDestroyWarpOptions( psWO );
+
+    return poDS;
+}
+
+
+/************************************************************************/
+/*                         GetProjectionRef()                           */
+/************************************************************************/
+
+const char* OGRDB2DataSource::GetProjectionRef()
+{
+    return (m_pszProjection) ? m_pszProjection : "";
+}
+
+/************************************************************************/
+/*                           SetProjection()                            */
+/************************************************************************/
+
+CPLErr OGRDB2DataSource::SetProjection( const char* pszProjection )
+{
+    CPLDebug("OGRDB2DataSource::SetProjection",
+            "pszProjection: '%s'", pszProjection);
+    if( nBands == 0)
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "SetProjection() not supported on a dataset with 0 band");
+        return CE_Failure;
+    }
+    if( eAccess != GA_Update )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "SetProjection() not supported on read-only dataset");
+        return CE_Failure;
+    }
+
+    int nSRID;
+    if( pszProjection == NULL || pszProjection[0] == '\0' )
+    {
+        nSRID = -1;
+    }
+    else
+    {
+        OGRSpatialReference oSRS;
+        if( oSRS.SetFromUserInput(pszProjection) != OGRERR_NONE )
+            return CE_Failure;
+        nSRID = FetchSRSId( &oSRS );
+        nSRID = FetchSRSId( &oSRS );
+    }
+
+    for(size_t iScheme = 0;
+            iScheme < sizeof(asTilingShemes)/sizeof(asTilingShemes[0]);
+            iScheme++ )
+    {
+        if( EQUAL(m_osTilingScheme, asTilingShemes[iScheme].pszName) )
+        {
+            if( nSRID != asTilingShemes[iScheme].nEPSGCode )
+            {
+                CPLError(CE_Failure, CPLE_NotSupported,
+                         "Projection should be EPSG:%d for %s tiling scheme",
+                         asTilingShemes[iScheme].nEPSGCode,
+                         m_osTilingScheme.c_str());
+                return CE_Failure;
+            }
+        }
+    }
+
+    m_nSRID = nSRID;
+    CPLFree(m_pszProjection);
+    m_pszProjection = pszProjection ? CPLStrdup(pszProjection): CPLStrdup("");
+
+    if( m_bRecordInsertedInGPKGContent )
+    {
+
+        OGRDB2Statement oStatement( GetSession() );
+        oStatement.Appendf( "UPDATE gpkg.contents SET srs_id = %d "
+                            "WHERE table_name = '%s'",
+                            m_nSRID, m_osRasterTable.c_str());
+
+        if( !oStatement.DB2Execute("OGRDB2DataSource::SetProjection") )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Set projection failed in gpkg.contents "
+                     "for table %s; ",
+                     m_osRasterTable.c_str(),
+                     GetSession()->GetLastError());
+            CPLDebug("OGRDB2DataSource::SetProjection",
+                     "Set projection failed in gpkg.contents "
+                     "for table %s; ",
+                     m_osRasterTable.c_str(),
+                     GetSession()->GetLastError());
+            return CE_Failure;
+        }
+        oStatement.Clear();
+        oStatement.Appendf( "UPDATE gpkg.tile_matrix_set SET srs_id = %d "
+                            "WHERE table_name = '%s'",
+                            m_nSRID, m_osRasterTable.c_str());
+
+        if( !oStatement.DB2Execute("OGRDB2DataSource::SetProjection") )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Set projection in gpkg.tile_matrix_set failed "
+                     "for table %s; ",
+                     m_osRasterTable.c_str(),
+                     GetSession()->GetLastError());
+            CPLDebug("OGRDB2DataSource::SetProjection",
+                     "Set projection in gpkg.tile_matrix_set failed "
+                     "for table %s; ",
+                     m_osRasterTable.c_str(),
+                     GetSession()->GetLastError());
+            return CE_Failure;
+        }
+    }
+    return CE_None;
+}
+
+/************************************************************************/
+/*                          GetGeoTransform()                           */
+/************************************************************************/
+
+CPLErr OGRDB2DataSource::GetGeoTransform( double* padfGeoTransform )
+{
+    memcpy(padfGeoTransform, m_adfGeoTransform, 6 * sizeof(double));
+    if( !m_bGeoTransformValid )
+        return CE_Failure;
+    else
+        return CE_None;
+}
+
+/************************************************************************/
+/*                          SetGeoTransform()                           */
+/************************************************************************/
+
+CPLErr OGRDB2DataSource::SetGeoTransform( double* padfGeoTransform )
+{
+    if( nBands == 0)
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "SetGeoTransform() not supported on a dataset with 0 band");
+        return CE_Failure;
+    }
+    if( eAccess != GA_Update )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "SetGeoTransform() not supported on read-only dataset");
+        return CE_Failure;
+    }
+    if( m_bGeoTransformValid )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Cannot modify geotransform once set");
+        return CE_Failure;
+    }
+    if( padfGeoTransform[2] != 0.0 || padfGeoTransform[4] != 0 ||
+            padfGeoTransform[5] > 0.0 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Only north-up non rotated geotransform supported");
+        return CE_Failure;
+    }
+
+    for(size_t iScheme = 0;
+            iScheme < sizeof(asTilingShemes)/sizeof(asTilingShemes[0]);
+            iScheme++ )
+    {
+        if( EQUAL(m_osTilingScheme, asTilingShemes[iScheme].pszName) )
+        {
+            double dfPixelXSizeZoomLevel0 = asTilingShemes[iScheme].dfPixelXSizeZoomLevel0;
+            double dfPixelYSizeZoomLevel0 = asTilingShemes[iScheme].dfPixelYSizeZoomLevel0;
+            for( m_nZoomLevel = 0; m_nZoomLevel < 25; m_nZoomLevel++ )
+            {
+                double dfExpectedPixelXSize = dfPixelXSizeZoomLevel0 / (1 << m_nZoomLevel);
+                double dfExpectedPixelYSize = dfPixelYSizeZoomLevel0 / (1 << m_nZoomLevel);
+                if( fabs( padfGeoTransform[1] - dfExpectedPixelXSize ) < 1e-8 * dfExpectedPixelXSize &&
+                        fabs( fabs(padfGeoTransform[5]) - dfExpectedPixelYSize ) < 1e-8 * dfExpectedPixelYSize )
+                {
+                    break;
+                }
+            }
+            if( m_nZoomLevel == 25 )
+            {
+                m_nZoomLevel = -1;
+                CPLError(CE_Failure, CPLE_NotSupported,
+                         "Could not find an appropriate zoom level of %s tiling scheme that matches raster pixel size",
+                         m_osTilingScheme.c_str());
+                return CE_Failure;
+            }
+            break;
+        }
+    }
+
+    memcpy(m_adfGeoTransform, padfGeoTransform, 6 * sizeof(double));
+    m_bGeoTransformValid = TRUE;
+
+    return FinalizeRasterRegistration();
+}
+
+/************************************************************************/
+/*                      FinalizeRasterRegistration()                    */
+/************************************************************************/
+
+CPLErr OGRDB2DataSource::FinalizeRasterRegistration()
+{
+    CPLDebug("OGRDB2DataSource::FinalizeRasterRegistration","Entering");
+
+    m_dfTMSMinX = m_adfGeoTransform[0];
+    m_dfTMSMaxY = m_adfGeoTransform[3];
+
+    int nTileWidth, nTileHeight;
+    GetRasterBand(1)->GetBlockSize(&nTileWidth, &nTileHeight);
+    m_nTileMatrixWidth = (nRasterXSize + nTileWidth - 1) / nTileWidth;
+    m_nTileMatrixHeight = (nRasterYSize + nTileHeight - 1) / nTileHeight;
+    CPLDebug("OGRDB2DataSource::FinalizeRasterRegistration",
+             "m_nZoomLevel: %d; nTileWidth: %d; nTileHeight %d",
+             m_nZoomLevel, nTileWidth, nTileHeight);
+    CPLDebug("OGRDB2DataSource::FinalizeRasterRegistration",
+             "nRasterXSize: %d; nRasterYSize %d",
+             nRasterXSize, nRasterYSize);
+    if( m_nZoomLevel < 0 )
+    {
+        m_nZoomLevel = 0;
+        while( (nRasterXSize >> m_nZoomLevel) > nTileWidth ||
+                (nRasterYSize >> m_nZoomLevel) > nTileHeight )
+            m_nZoomLevel ++;
+    }
+
+    double dfPixelXSizeZoomLevel0 = m_adfGeoTransform[1] * (1 << m_nZoomLevel);
+    double dfPixelYSizeZoomLevel0 = fabs(m_adfGeoTransform[5]) * (1 << m_nZoomLevel);
+    int nTileXCountZoomLevel0 = ((nRasterXSize >> m_nZoomLevel) + nTileWidth - 1) / nTileWidth;
+    int nTileYCountZoomLevel0 = ((nRasterYSize >> m_nZoomLevel) + nTileHeight - 1) / nTileHeight;
+
+    for(size_t iScheme = 0;
+            iScheme < sizeof(asTilingShemes)/sizeof(asTilingShemes[0]);
+            iScheme++ )
+    {
+        if( EQUAL(m_osTilingScheme, asTilingShemes[iScheme].pszName) )
+        {
+            CPLAssert( m_nZoomLevel >= 0 );
+            m_dfTMSMinX = asTilingShemes[iScheme].dfMinX;
+            m_dfTMSMaxY = asTilingShemes[iScheme].dfMaxY;
+            dfPixelXSizeZoomLevel0 = asTilingShemes[iScheme].dfPixelXSizeZoomLevel0;
+            dfPixelYSizeZoomLevel0 = asTilingShemes[iScheme].dfPixelYSizeZoomLevel0;
+            nTileXCountZoomLevel0 = asTilingShemes[iScheme].nTileXCountZoomLevel0;
+            nTileYCountZoomLevel0 = asTilingShemes[iScheme].nTileYCountZoomLevel0;
+            m_nTileMatrixWidth = nTileXCountZoomLevel0 * (1 << m_nZoomLevel);
+            m_nTileMatrixHeight = nTileYCountZoomLevel0 * (1 << m_nZoomLevel);
+            break;
+        }
+    }
+
+    ComputeTileAndPixelShifts();
+
+    double dfGDALMinX = m_adfGeoTransform[0];
+    double dfGDALMinY = m_adfGeoTransform[3] + nRasterYSize * m_adfGeoTransform[5];
+    double dfGDALMaxX = m_adfGeoTransform[0] + nRasterXSize * m_adfGeoTransform[1];
+    double dfGDALMaxY = m_adfGeoTransform[3];
+
+    OGRDB2Statement oStatement( GetSession() );
+    oStatement.Appendf( "INSERT INTO gpkg.contents "
+                        "(table_name,data_type,identifier,description,min_x,min_y,max_x,max_y,srs_id) VALUES "
+                        "('%s','tiles','%s','%s',%.18g,%.18g,%.18g,%.18g,%d)",
+                        m_osRasterTable.c_str(),
+                        m_osIdentifier.c_str(),
+                        m_osDescription.c_str(),
+                        dfGDALMinX, dfGDALMinY, dfGDALMaxX, dfGDALMaxY,
+                        m_nSRID);
+
+    if( !oStatement.DB2Execute("OGRDB2DataSource::FinalizeRasterRegistration") )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Insert into gpkg.contents failed");
+        CPLDebug("OGRDB2DataSource::FinalizeRasterRegistration",
+                 "Insert into gpkg.contents failed;"
+                 "error: %s; ",
+                 GetSession()->GetLastError());
+        return CE_Failure;
+    }
+
+    double dfTMSMaxX = m_dfTMSMinX + nTileXCountZoomLevel0 * nTileWidth * dfPixelXSizeZoomLevel0;
+    double dfTMSMinY = m_dfTMSMaxY - nTileYCountZoomLevel0 * nTileHeight * dfPixelYSizeZoomLevel0;
+
+    oStatement.Clear();
+    oStatement.Appendf( "INSERT INTO gpkg.tile_matrix_set "
+                        "(table_name,srs_id,min_x,min_y,max_x,max_y) VALUES "
+                        "('%s',%d,%.18g,%.18g,%.18g,%.18g)",
+                        m_osRasterTable.c_str(), m_nSRID,
+                        m_dfTMSMinX,dfTMSMinY,dfTMSMaxX,m_dfTMSMaxY);
+
+    if( !oStatement.DB2Execute("OGRDB2DataSource::FinalizeRasterRegistration") )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Insert into gpkg.tile_matrix_set failed");
+        CPLDebug("OGRDB2DataSource::FinalizeRasterRegistration",
+                 "Insert into gpkg.tile_matrix_set failed;"
+                 "error: %s; ",
+                 GetSession()->GetLastError());
+        return CE_Failure;
+    }
+
+    m_papoOverviewDS = (OGRDB2DataSource**) CPLCalloc(sizeof(OGRDB2DataSource*),
+                       m_nZoomLevel);
+    CPLDebug("OGRDB2DataSource::FinalizeRasterRegistration",
+             "m_nZoomLevel: %d", m_nZoomLevel);
+    for(int i=0; i<=m_nZoomLevel; i++)
+    {
+        double dfPixelXSizeZoomLevel, dfPixelYSizeZoomLevel;
+        int nTileMatrixWidth, nTileMatrixHeight;
+        if( EQUAL(m_osTilingScheme, "CUSTOM") )
+        {
+            dfPixelXSizeZoomLevel = m_adfGeoTransform[1] * (1 << (m_nZoomLevel-i));
+            dfPixelYSizeZoomLevel = fabs(m_adfGeoTransform[5]) * (1 << (m_nZoomLevel-i));
+            nTileMatrixWidth = ((nRasterXSize >> (m_nZoomLevel-i)) + nTileWidth - 1) / nTileWidth;
+            nTileMatrixHeight = ((nRasterYSize >> (m_nZoomLevel-i)) + nTileHeight - 1) / nTileHeight;
+        }
+        else
+        {
+            dfPixelXSizeZoomLevel = dfPixelXSizeZoomLevel0 / (1 << i);
+            dfPixelYSizeZoomLevel = dfPixelYSizeZoomLevel0 / (1 << i);
+            nTileMatrixWidth = nTileXCountZoomLevel0 * (1 << i);
+            nTileMatrixHeight = nTileYCountZoomLevel0 * (1 << i);
+        }
+        oStatement.Clear();
+        oStatement.Appendf( "INSERT INTO gpkg.tile_matrix "
+                            "(table_name,zoom_level,matrix_width,matrix_height, "
+                            "tile_width,tile_height,pixel_x_size,pixel_y_size) "
+                            "VALUES "
+                            "('%s',%d,%d,%d,%d,%d,%.18g,%.18g)",
+                            m_osRasterTable.c_str(),i,nTileMatrixWidth,
+                            nTileMatrixHeight,
+                            nTileWidth,nTileHeight,dfPixelXSizeZoomLevel,
+                            dfPixelYSizeZoomLevel);
+
+        if( !oStatement.DB2Execute("OGRDB2DataSource::FinalizeRasterRegistration") )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Insert into gpkg.tile_matrix_set failed");
+            CPLDebug("OGRDB2DataSource::FinalizeRasterRegistration",
+                     "Insert into gpkg.tile_matrix_set failed;"
+                     "error: %s; ",
+                     GetSession()->GetLastError());
+            return CE_Failure;
+        }
+
+        if( i < m_nZoomLevel )
+        {
+            OGRDB2DataSource* poOvrDS = new OGRDB2DataSource();
+            poOvrDS->InitRaster ( this, m_osRasterTable, i, nBands,
+                                  m_dfTMSMinX, m_dfTMSMaxY,
+                                  dfPixelXSizeZoomLevel, dfPixelYSizeZoomLevel,
+                                  nTileWidth, nTileHeight,
+                                  nTileMatrixWidth,nTileMatrixHeight,
+                                  dfGDALMinX, dfGDALMinY,
+                                  dfGDALMaxX, dfGDALMaxY );
+
+            m_papoOverviewDS[m_nZoomLevel-1-i] = poOvrDS;
+        }
+    }
+
+    SoftCommitTransaction();
+
+    m_nOverviewCount = m_nZoomLevel;
+    m_bRecordInsertedInGPKGContent = TRUE;
+    return CE_None;
+}
+
+
+
+/************************************************************************/
+/*                          IBuildOverviews()                           */
+/************************************************************************/
+
+static int GetFloorPowerOfTwo(int n)
+{
+    int p2 = 1;
+    while( (n = n >> 1) > 0 )
+    {
+        p2 <<= 1;
+    }
+    return p2;
+}
+
+CPLErr OGRDB2DataSource::IBuildOverviews(
+    const char * pszResampling,
+    int nOverviews, int * panOverviewList,
+    int nBandsIn, CPL_UNUSED int * panBandList,
+    GDALProgressFunc pfnProgress, void * pProgressData )
+{
+    CPLDebug("OGRDB2DataSource::IBuildOverviews",
+             "nOverviews: %d; m_nOverviewCount: %d",
+             nOverviews, m_nOverviewCount);
+    if( GetAccess() != GA_Update )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Overview building not supported on a database opened in read-only mode");
+        return CE_Failure;
+    }
+    if( m_poParentDS != NULL )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Overview building not supported on overview dataset");
+        return CE_Failure;
+    }
+    OGRDB2Statement oStatement( &m_oSession );
+    if( nOverviews == 0 )
+    {
+        for(int i=0; i<m_nOverviewCount; i++)
+            m_papoOverviewDS[i]->FlushCache();
+        oStatement.Appendf("DELETE FROM %s WHERE zoom_level < %d",
+                           m_osRasterTable.c_str(),
+                           m_nZoomLevel);
+#ifdef DEBUG_SQL
+        CPLDebug("OGRDB2DataSource::IBuildOverviews", "stmt: '%s'",oStatement.GetCommand());
+#endif
+        if( !oStatement.ExecuteSQL() )
+        {
+            CPLDebug("OGRDB2DataSource::IBuildOverviews", "DELETE failed: %s", GetSession()->GetLastError() );
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Delete of overviews failed: %s", GetSession()->GetLastError() );
+            return CE_Failure;
+        }
+
+        return CE_None;
+    }
+
+    if( nBandsIn != nBands )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Generation of overviews in GPKG only"
+                  "supported when operating on all bands." );
+        return CE_Failure;
+    }
+
+    if( m_nOverviewCount == 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Image too small to support overviews");
+        return CE_Failure;
+    }
+
+    FlushCache();
+    for(int i=0; i<nOverviews; i++)
+    {
+        if( panOverviewList[i] < 2 )
+        {
+            CPLError(CE_Failure, CPLE_IllegalArg, "Overview factor must be >= 2");
+            return CE_Failure;
+        }
+
+        int bFound = FALSE;
+        int jCandidate = -1;
+        int nMaxOvFactor = 0;
+        for(int j=0; j<m_nOverviewCount; j++)
+        {
+            int    nOvFactor;
+
+            GDALDataset* poODS = m_papoOverviewDS[j];
+
+            nOvFactor = (int)
+                        (0.5 + GetRasterXSize() / (double) poODS->GetRasterXSize());
+            nMaxOvFactor = nOvFactor;
+
+            if( nOvFactor == panOverviewList[i]
+                    || nOvFactor == GDALOvLevelAdjust2( panOverviewList[i],
+                            GetRasterXSize(),
+                            GetRasterYSize() ) )
+            {
+                bFound = TRUE;
+                break;
+            }
+
+            if( jCandidate < 0 && nOvFactor > panOverviewList[i] )
+                jCandidate = j;
+        }
+
+        if( !bFound )
+        {
+            /* Mostly for debug */
+            if( !CPLTestBool(CPLGetConfigOption("ALLOW_GPKG_ZOOM_OTHER_EXTENSION", "YES")) )
+            {
+                CPLString osOvrList;
+                for(int j=0; j<m_nOverviewCount; j++)
+                {
+                    int    nOvFactor;
+
+                    GDALDataset* poODS = m_papoOverviewDS[j];
+
+                    /* Compute overview factor */
+                    nOvFactor = (int)
+                                (0.5 + GetRasterXSize() / (double) poODS->GetRasterXSize());
+                    int nODSXSize = (int)(0.5 + GetRasterXSize() / (double) nOvFactor);
+                    if( nODSXSize != poODS->GetRasterXSize() )
+                    {
+                        int nOvFactorPowerOfTwo = GetFloorPowerOfTwo(nOvFactor);
+                        nODSXSize = (int)(0.5 + GetRasterXSize() / (double) nOvFactorPowerOfTwo);
+                        if( nODSXSize == poODS->GetRasterXSize() )
+                            nOvFactor = nOvFactorPowerOfTwo;
+                        else
+                        {
+                            nOvFactorPowerOfTwo <<= 1;
+                            nODSXSize = (int)(0.5 + GetRasterXSize() / (double) nOvFactorPowerOfTwo);
+                            if( nODSXSize == poODS->GetRasterXSize() )
+                                nOvFactor = nOvFactorPowerOfTwo;
+                        }
+                    }
+                    if( j != 0 )
+                        osOvrList += " ";
+                    osOvrList += CPLSPrintf("%d", nOvFactor);
+                }
+                CPLError(CE_Failure, CPLE_NotSupported,
+                         "Only overviews %s can be computed", osOvrList.c_str());
+                return CE_Failure;
+            }
+            else
+            {
+                int nOvFactor = panOverviewList[i];
+                if( jCandidate < 0 )
+                    jCandidate = m_nOverviewCount;
+
+                int nOvXSize = GetRasterXSize() / nOvFactor;
+                int nOvYSize = GetRasterYSize() / nOvFactor;
+                if( nOvXSize < 8 || nOvYSize < 8)
+                {
+                    CPLError(CE_Failure, CPLE_NotSupported,
+                             "Too big overview factor : %d. Would result in a %dx%d overview",
+                             nOvFactor, nOvXSize, nOvYSize);
+                    return CE_Failure;
+                }
+                if( !(jCandidate == m_nOverviewCount && nOvFactor == 2 * nMaxOvFactor) &&
+                        !m_bZoomOther )
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "Use of overview factor %d cause gpkg_zoom_other extension to be needed",
+                             nOvFactor);
+                    RegisterZoomOtherExtension();
+                    m_bZoomOther = TRUE;
+                }
+
+                SoftStartTransaction();
+
+                CPLAssert(jCandidate > 0);
+                int nNewZoomLevel = m_papoOverviewDS[jCandidate-1]->m_nZoomLevel;
+
+                for(int k=0; k<=jCandidate; k++)
+                {
+                    oStatement.Appendf( "UPDATE gpkg.tile_matrix SET zoom_level = %d "
+                                        "WHERE table_name = %s AND zoom_level = %d",
+                                        m_nZoomLevel - k + 1,
+                                        m_osRasterTable.c_str(),
+                                        m_nZoomLevel - k);
+#ifdef DEBUG_SQL
+                    CPLDebug("OGRDB2DataSource::IBuildOverviews",
+                             "stmt: '%s'", oStatement.GetCommand());
+#endif
+                    if( !oStatement.ExecuteSQL() )
+                    {
+                        SoftRollbackTransaction();
+                        CPLError(CE_Failure, CPLE_AppDefined,
+                                 "updating tile_matrix failed "
+                                 "for table %s; ",
+                                 m_osRasterTable.c_str(),
+                                 GetSession()->GetLastError());
+                        CPLDebug("OGRDB2DataSource::IBuildOverviews",
+                                 "updating tile_matrix failed "
+                                 "for table %s; ",
+                                 m_osRasterTable.c_str(),
+                                 GetSession()->GetLastError());
+                        return CE_Failure;
+                    }
+                    oStatement.Clear();
+
+                    oStatement.Appendf( "UPDATE %s SET zoom_level = %d "
+                                        "WHERE zoom_level = %d",
+                                        m_osRasterTable.c_str(),
+                                        m_nZoomLevel - k + 1,
+                                        m_nZoomLevel - k);
+#ifdef DEBUG_SQL
+                    CPLDebug("OGRDB2DataSource::IBuildOverviews",
+                             "stmt: '%s'", oStatement.GetCommand());
+#endif
+                    if( !oStatement.ExecuteSQL() )
+                    {
+                        SoftRollbackTransaction();
+                        CPLError(CE_Failure, CPLE_AppDefined,
+                                 "update failed "
+                                 "for table %s; ",
+                                 m_osRasterTable.c_str(),
+                                 GetSession()->GetLastError());
+                        CPLDebug("OGRDB2DataSource::IBuildOverviews",
+                                 "update failed "
+                                 "for table %s; ",
+                                 m_osRasterTable.c_str(),
+                                 GetSession()->GetLastError());
+                        return CE_Failure;
+                    }
+                }
+
+                double dfGDALMinX = m_adfGeoTransform[0];
+                double dfGDALMinY = m_adfGeoTransform[3] + nRasterYSize * m_adfGeoTransform[5];
+                double dfGDALMaxX = m_adfGeoTransform[0] + nRasterXSize * m_adfGeoTransform[1];
+                double dfGDALMaxY = m_adfGeoTransform[3];
+                double dfPixelXSizeZoomLevel = m_adfGeoTransform[1] * nOvFactor;
+                double dfPixelYSizeZoomLevel = fabs(m_adfGeoTransform[5]) * nOvFactor;
+                int nTileWidth, nTileHeight;
+                GetRasterBand(1)->GetBlockSize(&nTileWidth, &nTileHeight);
+                int nTileMatrixWidth = (nOvXSize + nTileWidth - 1) / nTileWidth;
+                int nTileMatrixHeight = (nOvYSize + nTileHeight - 1) / nTileHeight;
+                oStatement.Clear();
+
+                oStatement.Appendf( "INSERT INTO gpkg.tile_matrix "
+                                    "(table_name,zoom_level,matrix_width,matrix_height,tile_width,tile_height,pixel_x_size,pixel_y_size) VALUES "
+                                    "(%s,%d,%d,%d,%d,%d,%.18g,%.18g)",
+                                    m_osRasterTable.c_str(),nNewZoomLevel,nTileMatrixWidth,nTileMatrixHeight,
+                                    nTileWidth,nTileHeight,dfPixelXSizeZoomLevel,dfPixelYSizeZoomLevel);
+#ifdef DEBUG_SQL
+                CPLDebug("OGRDB2DataSource::IBuildOverviews",
+                         "stmt: '%s'", oStatement.GetCommand());
+#endif
+                if( !oStatement.ExecuteSQL() )
+                {
+                    SoftRollbackTransaction();
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "insert into tile_matrix failed "
+                             "for table %s; ",
+                             m_osRasterTable.c_str(),
+                             GetSession()->GetLastError());
+                    CPLDebug("OGRDB2DataSource::IBuildOverviews",
+                             "insert into tile_matrix failed "
+                             "for table %s; ",
+                             m_osRasterTable.c_str(),
+                             GetSession()->GetLastError());
+                    return CE_Failure;
+                }
+
+                SoftCommitTransaction();
+
+                m_nZoomLevel ++; /* this change our zoom level as well as previous overviews */
+                for(int k=0; k<jCandidate; k++)
+                    m_papoOverviewDS[k]->m_nZoomLevel ++;
+
+                OGRDB2DataSource* poOvrDS = new OGRDB2DataSource();
+                poOvrDS->InitRaster ( this, m_osRasterTable,
+                                      nNewZoomLevel, nBands,
+                                      m_dfTMSMinX, m_dfTMSMaxY,
+                                      dfPixelXSizeZoomLevel, dfPixelYSizeZoomLevel,
+                                      nTileWidth, nTileHeight,
+                                      nTileMatrixWidth,nTileMatrixHeight,
+                                      dfGDALMinX, dfGDALMinY,
+                                      dfGDALMaxX, dfGDALMaxY );
+                m_papoOverviewDS = (OGRDB2DataSource**) CPLRealloc(
+                                       m_papoOverviewDS, sizeof(OGRDB2DataSource*) * (m_nOverviewCount+1));
+
+                if( jCandidate < m_nOverviewCount )
+                {
+                    memmove(m_papoOverviewDS + jCandidate + 1,
+                            m_papoOverviewDS + jCandidate,
+                            sizeof(OGRDB2DataSource*) * (m_nOverviewCount-jCandidate));
+                }
+                m_papoOverviewDS[jCandidate] = poOvrDS;
+                m_nOverviewCount ++;
+            }
+        }
+    }
+
+    GDALRasterBand*** papapoOverviewBands = (GDALRasterBand ***) CPLCalloc(sizeof(void*),nBands);
+    for( int iBand = 0; iBand < nBands; iBand++ )
+    {
+        papapoOverviewBands[iBand] = (GDALRasterBand **) CPLCalloc(sizeof(void*),nOverviews);
+        int iCurOverview = 0;
+        for(int i=0; i<nOverviews; i++)
+        {
+            int   j;
+            for( j = 0; j < m_nOverviewCount; j++ )
+            {
+                int    nOvFactor;
+                GDALDataset* poODS = m_papoOverviewDS[j];
+
+                nOvFactor = GDALComputeOvFactor(poODS->GetRasterXSize(),
+                                                GetRasterXSize(),
+                                                poODS->GetRasterYSize(),
+                                                GetRasterYSize());
+
+                if( nOvFactor == panOverviewList[i]
+                        || nOvFactor == GDALOvLevelAdjust2( panOverviewList[i],
+                                GetRasterXSize(),
+                                GetRasterYSize() ) )
+                {
+                    papapoOverviewBands[iBand][iCurOverview] = poODS->GetRasterBand(iBand+1);
+                    iCurOverview++ ;
+                    break;
+                }
+            }
+            CPLAssert(j < m_nOverviewCount);
+        }
+        CPLAssert(iCurOverview == nOverviews);
+    }
+
+    CPLErr eErr = GDALRegenerateOverviewsMultiBand(nBands, papoBands,
+                  nOverviews, papapoOverviewBands,
+                  pszResampling, pfnProgress, pProgressData );
+
+    for( int iBand = 0; iBand < nBands; iBand++ )
+    {
+        CPLFree(papapoOverviewBands[iBand]);
+    }
+    CPLFree(papapoOverviewBands);
+
+    return eErr;
+}
+
+
+/************************************************************************/
+/*                       RegisterZoomOtherExtension()                   */
+/************************************************************************/
+
+int OGRDB2DataSource::RegisterZoomOtherExtension()
+{
+    CPLDebug("OGRDB2DataSource::RegisterZoomOtherExtension", "NO-OP");
+    CreateExtensionsTableIfNecessary();
+#ifdef LATER
+    char* pszSQL = sqlite3_mprintf(
+                       "INSERT INTO gpkg_extensions "
+                       "(table_name, extension_name, definition, scope) "
+                       "VALUES "
+                       "('%q', 'gpkg_zoom_other', 'GeoPackage 1.0 Specification Annex O', 'read-write')",
+                       m_osRasterTable.c_str());
+    OGRErr eErr = SQLCommand(hDB, pszSQL);
+    sqlite3_free(pszSQL);
+    if ( OGRERR_NONE != eErr )
+        return FALSE;
+#endif
+    return TRUE;
+}
+
+/************************************************************************/
+/*                  CreateGDALAspatialExtension()                       */
+/************************************************************************/
+
+OGRErr OGRDB2DataSource::CreateGDALAspatialExtension()
+{
+    CreateExtensionsTableIfNecessary();
+    CPLDebug("OGRDB2DataSource::CreateGDALAspatialExtension", "NO-OP");
+#ifdef LATER
+    if( HasGDALAspatialExtension() )
+        return OGRERR_NONE;
+
+    const char* pszCreateAspatialExtension =
+        "INSERT INTO gpkg_extensions "
+        "(table_name, column_name, extension_name, definition, scope) "
+        "VALUES "
+        "(NULL, NULL, 'gdal_aspatial', 'http://gdal.org/geopackage_aspatial.html', 'read-write')";
+
+    return SQLCommand(hDB, pszCreateAspatialExtension);
+#endif
+    return OGRERR_NONE;
+}
+
+
+
diff --git a/ogr/ogrsf_frmts/db2/ogrdb2datasourcemd.cpp b/ogr/ogrsf_frmts/db2/ogrdb2datasourcemd.cpp
new file mode 100644
index 0000000..bdafbda
--- /dev/null
+++ b/ogr/ogrsf_frmts/db2/ogrdb2datasourcemd.cpp
@@ -0,0 +1,930 @@
+/****************************************************************************
+ *
+ * Project:  DB2 Spatial driver
+ * Purpose:  Implements OGRDB2DataSource class
+ *           Metadata functions
+ * Author:   David Adler, dadler at adtechgeospatial dot com
+ *
+ ****************************************************************************
+ * Copyright (c) 2010, Tamas Szekeres
+ * Copyright (c) 2015, David Adler
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_db2.h"
+
+/************************************************************************/
+/*                            FlushMetadata()                           */
+/************************************************************************/
+
+CPLErr OGRDB2DataSource::FlushMetadata()
+{
+    CPLDebug("OGRDB2DataSource::FlushMetadata","Entering");
+// LATER - where is m_bMetadataDirty set?
+    if( !m_bMetadataDirty || m_poParentDS != NULL ||
+            !CPLTestBool(CPLGetConfigOption("CREATE_METADATA_TABLES", "YES")) )
+        return CE_None;
+    if( !HasMetadataTables() && !CreateMetadataTables() )
+        return CE_Failure;
+    CPLDebug("OGRDB2DataSource::FlushMetadata","Write Metadata");
+    m_bMetadataDirty = FALSE;
+
+    if( m_osRasterTable.size() )
+    {
+        const char* pszIdentifier = GetMetadataItem("IDENTIFIER");
+        const char* pszDescription = GetMetadataItem("DESCRIPTION");
+        if( !m_bIdentifierAsCO && pszIdentifier != NULL &&
+                pszIdentifier != m_osIdentifier )
+        {
+            m_osIdentifier = pszIdentifier;
+            OGRDB2Statement oStatement( GetSession() );
+            oStatement.Appendf( "UPDATE gpkg.contents SET identifier = '%s' "
+                                "WHERE table_name = '%s'",
+                                pszIdentifier, m_osRasterTable.c_str());
+
+            if( !oStatement.DB2Execute("OGR_DB2DataSource::FlushMetadata") )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Set identifier failed in gpkg.contents"
+                         "for table %s; ",
+                         m_osRasterTable.c_str(),
+                         GetSession()->GetLastError());
+                return CE_Failure;
+            }
+
+        }
+        if( !m_bDescriptionAsCO && pszDescription != NULL &&
+                pszDescription != m_osDescription )
+        {
+            m_osDescription = pszDescription;
+            OGRDB2Statement oStatement( GetSession() );
+            oStatement.Appendf( "UPDATE gpkg.contents SET description = '%s' "
+                                "WHERE table_name = '%s'",
+                                pszDescription, m_osRasterTable.c_str());
+
+            if( !oStatement.DB2Execute("OGR_DB2DataSource::FlushMetadata") )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Set description failed in gpkg.contents"
+                         "for table %s; ",
+                         m_osRasterTable.c_str(),
+                         GetSession()->GetLastError());
+                return CE_Failure;
+            }
+        }
+    }
+
+    char** papszMDDup = NULL;
+    for( char** papszIter = GetMetadata(); papszIter && *papszIter; ++papszIter )
+    {
+        if( STARTS_WITH_CI(*papszIter, "IDENTIFIER=") )
+            continue;
+        if( STARTS_WITH_CI(*papszIter, "DESCRIPTION=") )
+            continue;
+        if( STARTS_WITH_CI(*papszIter, "ZOOM_LEVEL=") )
+            continue;
+        if( STARTS_WITH_CI(*papszIter, "GPKG_METADATA_ITEM_") )
+            continue;
+        papszMDDup = CSLInsertString(papszMDDup, -1, *papszIter);
+    }
+
+    CPLXMLNode* psXMLNode;
+    {
+        GDALMultiDomainMetadata oLocalMDMD;
+        char** papszDomainList = oMDMD.GetDomainList();
+        char** papszIter = papszDomainList;
+        oLocalMDMD.SetMetadata(papszMDDup);
+        while( papszIter && *papszIter )
+        {
+            if( !EQUAL(*papszIter, "") &&
+                    !EQUAL(*papszIter, "IMAGE_STRUCTURE") &&
+                    !EQUAL(*papszIter, "GEOPACKAGE") )
+                oLocalMDMD.SetMetadata(oMDMD.GetMetadata(*papszIter), *papszIter);
+            papszIter ++;
+        }
+        psXMLNode = oLocalMDMD.Serialize();
+    }
+
+    CSLDestroy(papszMDDup);
+    papszMDDup = NULL;
+
+    WriteMetadata(psXMLNode, m_osRasterTable.c_str() );
+
+    if( m_osRasterTable.size() )
+    {
+        char** papszGeopackageMD = GetMetadata("GEOPACKAGE");
+
+        papszMDDup = NULL;
+        for( char** papszIter = papszGeopackageMD; papszIter && *papszIter; ++papszIter )
+        {
+            papszMDDup = CSLInsertString(papszMDDup, -1, *papszIter);
+        }
+
+        GDALMultiDomainMetadata oLocalMDMD;
+        oLocalMDMD.SetMetadata(papszMDDup);
+        CSLDestroy(papszMDDup);
+        papszMDDup = NULL;
+        psXMLNode = oLocalMDMD.Serialize();
+
+        WriteMetadata(psXMLNode, NULL);
+    }
+
+    for(int i=0; i<m_nLayers; i++)
+    {
+        const char* pszIdentifier = m_papoLayers[i]->GetMetadataItem("IDENTIFIER");
+        const char* pszDescription = m_papoLayers[i]->GetMetadataItem("DESCRIPTION");
+        if( pszIdentifier != NULL )
+        {
+            OGRDB2Statement oStatement( GetSession() );
+            oStatement.Appendf( "UPDATE gpkg.contents SET identifier = '%s' "
+                                "WHERE table_name = '%s'",
+                                pszIdentifier, m_papoLayers[i]->GetName());
+
+            if( !oStatement.DB2Execute("OGR_DB2DataSource::FlushMetadata") )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Set identifier failed in gpkg.contents"
+                         "for table %s; ",
+                         m_osRasterTable.c_str(),
+                         GetSession()->GetLastError());
+                CPLDebug("OGRDB2DataSource::FlushMetadata",
+                         "Set identifier failed in gpkg.contents"
+                         "for table %s; ",
+                         m_osRasterTable.c_str(),
+                         GetSession()->GetLastError());
+                return CE_Failure;
+            }
+        }
+        if( pszDescription != NULL )
+        {
+            OGRDB2Statement oStatement( GetSession() );
+            oStatement.Appendf( "UPDATE gpkg.contents SET description = '%s' "
+                                "WHERE table_name = '%s'",
+                                pszDescription, m_papoLayers[i]->GetName());
+
+            if( !oStatement.DB2Execute("OGR_DB2DataSource::ICreateLayer") )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Set description failed in gpkg.contents"
+                         "for table %s; ",
+                         m_osRasterTable.c_str(),
+                         GetSession()->GetLastError());
+                CPLDebug("OGRDB2DataSource::FlushMetadata",
+                         "Set description failed in gpkg.contents"
+                         "for table %s; ",
+                         m_osRasterTable.c_str(),
+                         GetSession()->GetLastError());
+                return CE_Failure;
+            }
+        }
+
+        papszMDDup = NULL;
+        for( char** papszIter = m_papoLayers[i]->GetMetadata(); papszIter && *papszIter; ++papszIter )
+        {
+            if( STARTS_WITH_CI(*papszIter, "IDENTIFIER=") )
+                continue;
+            if( STARTS_WITH_CI(*papszIter, "DESCRIPTION=") )
+                continue;
+            if( STARTS_WITH_CI(*papszIter, "OLMD_FID64=") )
+                continue;
+            papszMDDup = CSLInsertString(papszMDDup, -1, *papszIter);
+        }
+
+        {
+            GDALMultiDomainMetadata oLocalMDMD;
+            char** papszDomainList = m_papoLayers[i]->GetMetadataDomainList();
+            char** papszIter = papszDomainList;
+            oLocalMDMD.SetMetadata(papszMDDup);
+            while( papszIter && *papszIter )
+            {
+                if( !EQUAL(*papszIter, "") )
+                    oLocalMDMD.SetMetadata(m_papoLayers[i]->GetMetadata(*papszIter), *papszIter);
+                papszIter ++;
+            }
+            CSLDestroy(papszDomainList);
+            psXMLNode = oLocalMDMD.Serialize();
+        }
+
+        CSLDestroy(papszMDDup);
+        papszMDDup = NULL;
+
+        WriteMetadata(psXMLNode, m_papoLayers[i]->GetName() );
+    }
+
+    return CE_None;
+}
+
+
+/************************************************************************/
+/*                            WriteMetadata()                           */
+/************************************************************************/
+
+void OGRDB2DataSource::WriteMetadata(CPLXMLNode* psXMLNode, /* will be destroyed by the method */
+                                     const char* pszTableName)
+{
+
+
+    int bIsEmpty = (psXMLNode == NULL);
+    char *pszXML = NULL;
+    if( !bIsEmpty )
+    {
+        CPLXMLNode* psMasterXMLNode = CPLCreateXMLNode( NULL, CXT_Element,
+                                      "GDALMultiDomainMetadata" );
+        psMasterXMLNode->psChild = psXMLNode;
+        pszXML = CPLSerializeXMLTree(psMasterXMLNode);
+        CPLDestroyXMLNode(psMasterXMLNode);
+    }
+    psXMLNode = NULL;
+    CPLDebug("OGRDB2DataSource::WriteMetadata",
+             "pszTableName: %s; bIsEmpty: %d", pszTableName, bIsEmpty);
+    OGRDB2Statement oStatement( GetSession() );
+    oStatement.Append(
+        "SELECT md.id FROM gpkg.metadata md "
+        "JOIN gpkg.metadata_reference mdr "
+        "ON (md.id = mdr.md_file_id ) "
+        "WHERE md.md_scope = 'dataset' "
+        "AND md.md_standard_uri='http://gdal.org' "
+        "AND md.mime_type='text/xml' ");
+    if( pszTableName && pszTableName[0] != '\0' )
+    {
+        oStatement.Appendf(
+            "AND mdr.reference_scope = 'table' "
+            "AND mdr.table_name = '%s'",
+            pszTableName);
+    }
+    else
+    {
+        oStatement.Append(
+            "AND mdr.reference_scope = 'geopackage'");
+    }
+
+    if( !oStatement.DB2Execute("OGR_DB2DataSource::WriteMetadata") )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Failed getting md.id; error: %s",
+                 GetSession()->GetLastError());
+    }
+
+    int mdId = -1;
+    if (oStatement.Fetch()) {
+        CPLDebug("OGRDB2DataSource::WriteMetadata",
+                 "col(0): %s", oStatement.GetColData(0));
+        mdId = atoi(oStatement.GetColData(0));
+    }
+    CPLDebug("OGRDB2DataSource::WriteMetadata",
+             "mdId: %d", mdId);
+    oStatement.Clear();
+    if( bIsEmpty )
+    {
+        if( mdId >= 0 )
+        {
+            oStatement.Appendf("DELETE FROM gpkg.metadata_reference "
+                               "WHERE md_file_id = %d", mdId);
+            if( !oStatement.DB2Execute("OGR_DB2DataSource::WriteMetadata") )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Failed getting md.id; error: %s",
+                         GetSession()->GetLastError());
+            }
+            oStatement.Clear();
+            oStatement.Appendf("DELETE FROM gpkg.metadata "
+                               "WHERE id = %d", mdId);
+            if( !oStatement.DB2Execute("OGR_DB2DataSource::WriteMetadata") )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Failed deleting md.id; error: %s",
+                         GetSession()->GetLastError());
+            }
+            oStatement.Clear();
+        }
+    } else
+    {
+        if ( mdId >= 0 )
+        {
+            oStatement.Appendf( "UPDATE gpkg.metadata "
+                                "SET metadata = '%s' WHERE id = %d",
+                                pszXML, mdId);
+        }
+        else
+        {
+            oStatement.Appendf(
+                "INSERT INTO gpkg.metadata (md_scope, "
+                "md_standard_uri, mime_type, metadata) VALUES "
+                "('dataset','http://gdal.org','text/xml','%s')",
+                pszXML);
+        }
+        if( !oStatement.DB2Execute("OGR_DB2DataSource::WriteMetadata") )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Failed updating metadata; error: %s",
+                     GetSession()->GetLastError());
+        }
+        int nNewId = -1;
+        if (mdId < 0 ) {
+            OGRDB2Statement oStatement2( GetSession() );
+            oStatement2.Append( "select IDENTITY_VAL_LOCAL() AS IDENTITY "
+                                "FROM SYSIBM.SYSDUMMY1");
+            if( oStatement2.DB2Execute("OGR_DB2DataSource::WriteMetadata")
+                    && oStatement2.Fetch() )
+            {
+                if ( oStatement2.GetColData( 0 ) )
+                    nNewId = atoi(oStatement2.GetColData( 0 ) );
+            }
+        }
+
+        CPLDebug("OGRDB2DataSource::WriteMetadata",
+                 "nNewId: %d", nNewId);
+        oStatement.Clear();
+
+        CPLFree(pszXML);
+
+        if( mdId < 0 )
+        {
+            if( pszTableName != NULL && pszTableName[0] != '\0' )
+            {
+                oStatement.Appendf("INSERT INTO gpkg.metadata_reference "
+                                   "(reference_scope, table_name, md_file_id) "
+                                   "VALUES ('table', '%s', %d)",
+                                   pszTableName, nNewId);
+            }
+            else
+            {
+                oStatement.Appendf("INSERT INTO gpkg.metadata_reference "
+                                   "(reference_scope, table_name, md_file_id) "
+                                   "VALUES ('table', '%s', %d)",
+                                   pszTableName, nNewId);
+            }
+        }
+        else
+        {
+            oStatement.Appendf("UPDATE gpkg.metadata_reference "
+                               "SET timestamp = CURRENT TIMESTAMP "
+                               "WHERE md_file_id = %d",
+                               mdId);
+        }
+
+        if( !oStatement.DB2Execute("OGR_DB2DataSource::WriteMetadata") )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Failed updating metadata; error: %s",
+                     GetSession()->GetLastError());
+        }
+    }
+    CPLDebug("OGRDB2DataSource::WriteMetadata",
+             "exiting");
+    return;
+}
+
+
+/************************************************************************/
+/*                        CreateMetadataTables()                        */
+/************************************************************************/
+
+int OGRDB2DataSource::CreateMetadataTables()
+{
+    CPLDebug("OGRDB2DataSource::CreateMetadataTables","Enter");
+
+//    int bCreateTriggers = CPLTestBool(CPLGetConfigOption("CREATE_TRIGGERS", "YES"));
+    OGRDB2Statement oStatement( GetSession() );
+    m_oSession.BeginTransaction();
+    /* Requirement 13: A GeoPackage file SHALL include a gpkg_contents table */
+    /* http://opengis.github.io/geopackage/#_contents */
+
+    oStatement.Appendf("CREATE TABLE gpkg.contents ( "
+                       "table_name VARCHAR(128) NOT NULL PRIMARY KEY, "
+                       "data_type VARCHAR(128) NOT NULL, "
+
+                       "identifier VARCHAR(128) NOT NULL UNIQUE, "
+                       "description VARCHAR(128) DEFAULT '', "
+                       "last_change TIMESTAMP NOT NULL DEFAULT , "
+                       "min_x DOUBLE, "
+                       "min_y DOUBLE, "
+                       "max_x DOUBLE, "
+                       "max_y DOUBLE, "
+                       "srs_id INTEGER "
+//              "CONSTRAINT fk_gc_r_srs_id FOREIGN KEY (srs_id) REFERENCES "
+//              "db2gse.gse_spatial_reference_systems(srs_id)" // Fails???
+                       ")");
+
+    if( !oStatement.DB2Execute("OGR_DB2DataSource::CreateMetadataTables") )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Error creating gpkg.contents: %s",
+                  GetSession()->GetLastError() );
+        CPLDebug("OGRDB2DataSource::CreateMetadataTables", "Error creating gpkg.contents");
+        m_oSession.RollbackTransaction();
+        return FALSE;
+    }
+
+    /* From C.5. gpkg_tile_matrix_set Table 28. gpkg_tile_matrix_set Table Creation SQL  */
+    oStatement.Clear();
+    oStatement.Appendf("CREATE TABLE gpkg.tile_matrix_set ( "
+                       "table_name VARCHAR(128) NOT NULL PRIMARY KEY, "
+                       "srs_id INTEGER NOT NULL, "
+                       "min_x DOUBLE, "
+                       "min_y DOUBLE, "
+                       "max_x DOUBLE, "
+                       "max_y DOUBLE, "
+                       "CONSTRAINT fk_gtms_table_name FOREIGN KEY (table_name) "
+                       "REFERENCES gpkg.contents(table_name) "
+                       "ON DELETE CASCADE"
+//              "CONSTRAINT fk_gtms_srs_id FOREIGN KEY (srs_id) REFERENCES "
+//              "db2gse.gse_spatial_reference_systems(srs_id)" // Fails???
+                       ")");
+
+    if( !oStatement.DB2Execute("OGR_DB2DataSource::CreateMetadataTables") )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Error creating gpkg.tile_matrix_set: %s",
+                  GetSession()->GetLastError() );
+        CPLDebug("OGRDB2DataSource::CreateMetadataTables",
+                 "Error creating gpkg.tile_matrix_set");
+        m_oSession.RollbackTransaction();
+        return FALSE;
+    }
+
+    /* From C.6. gpkg_tile_matrix Table 29. */
+    /* gpkg_tile_matrix Table Creation SQL */
+    oStatement.Clear();
+    oStatement.Appendf("CREATE TABLE gpkg.tile_matrix ( "
+                       "table_name VARCHAR(128) NOT NULL, "
+                       "zoom_level INTEGER NOT NULL, "
+                       "matrix_width INTEGER NOT NULL, "
+                       "matrix_height INTEGER NOT NULL, "
+                       "tile_width INTEGER NOT NULL, "
+                       "tile_height INTEGER NOT NULL, "
+                       "pixel_x_size DOUBLE NOT NULL, "
+                       "pixel_y_size DOUBLE NOT NULL, "
+                       "CONSTRAINT pk_ttm PRIMARY KEY (table_name, zoom_level), "
+                       "CONSTRAINT fk_tmm_table_name FOREIGN KEY (table_name) "
+                       "REFERENCES gpkg.contents(table_name) "
+                       "ON DELETE CASCADE"
+                       ")");
+
+    if( !oStatement.DB2Execute("OGR_DB2DataSource::CreateMetadataTables") )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Error creating gpkg.tile_matrix: %s",
+                  GetSession()->GetLastError() );
+        m_oSession.RollbackTransaction();
+        return FALSE;
+    }
+
+    /* From C.10. gpkg_metadata Table 35. */
+    /* gpkg_metadata Table Definition SQL  */
+    oStatement.Clear();
+    oStatement.Append("CREATE TABLE gpkg.metadata ( "
+                      "id INTEGER PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY, "
+                      "md_scope VARCHAR(128) NOT NULL DEFAULT 'dataset', "
+                      "md_standard_uri VARCHAR(128) NOT NULL, "
+                      "mime_type VARCHAR(128) NOT NULL DEFAULT 'text/xml', "
+                      "metadata VARCHAR(32000) NOT NULL "
+                      ")");
+
+    if( !oStatement.DB2Execute("OGR_DB2DataSource::CreateMetadataTables") )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Error creating gpkg.metadata: %s",
+                  GetSession()->GetLastError() );
+        CPLDebug("OGRDB2DataSource::CreateMetadataTables",
+                 "Error creating gpkg.metadata");
+        m_oSession.RollbackTransaction();
+        return FALSE;
+    }
+
+#ifdef LATER
+    /* From D.2. metadata Table 40. metadata Trigger Definition SQL  */
+    const char* pszMetadataTriggers =
+        "CREATE TRIGGER 'gpkg_metadata_md_scope_insert' "
+        "BEFORE INSERT ON 'gpkg_metadata' "
+        "FOR EACH ROW BEGIN "
+        "SELECT RAISE(ABORT, 'insert on table gpkg_metadata violates "
+        "constraint: md_scope must be one of undefined | fieldSession | "
+        "collectionSession | series | dataset | featureType | feature | "
+        "attributeType | attribute | tile | model | catalogue | schema | "
+        "taxonomy software | service | collectionHardware | "
+        "nonGeographicDataset | dimensionGroup') "
+        "WHERE NOT(NEW.md_scope IN "
+        "('undefined','fieldSession','collectionSession','series','dataset', "
+        "'featureType','feature','attributeType','attribute','tile','model', "
+        "'catalogue','schema','taxonomy','software','service', "
+        "'collectionHardware','nonGeographicDataset','dimensionGroup')); "
+        "END; "
+        "CREATE TRIGGER 'gpkg_metadata_md_scope_update' "
+        "BEFORE UPDATE OF 'md_scope' ON 'gpkg_metadata' "
+        "FOR EACH ROW BEGIN "
+        "SELECT RAISE(ABORT, 'update on table gpkg_metadata violates "
+        "constraint: md_scope must be one of undefined | fieldSession | "
+        "collectionSession | series | dataset | featureType | feature | "
+        "attributeType | attribute | tile | model | catalogue | schema | "
+        "taxonomy software | service | collectionHardware | "
+        "nonGeographicDataset | dimensionGroup') "
+        "WHERE NOT(NEW.md_scope IN "
+        "('undefined','fieldSession','collectionSession','series','dataset', "
+        "'featureType','feature','attributeType','attribute','tile','model', "
+        "'catalogue','schema','taxonomy','software','service', "
+        "'collectionHardware','nonGeographicDataset','dimensionGroup')); "
+        "END";
+    if ( bCreateTriggers && OGRERR_NONE != SQLCommand(hDB, pszMetadataTriggers) )
+        return FALSE;
+#endif
+
+
+
+    /* From C.11. gpkg_metadata_reference Table 36. gpkg_metadata_reference Table Definition SQL */
+    oStatement.Clear();
+    oStatement.Appendf("CREATE TABLE gpkg.metadata_reference ( "
+                       "reference_scope VARCHAR(128) NOT NULL, "
+                       "table_name VARCHAR(128), "
+                       "column_name VARCHAR(128), "
+                       "row_id_value INTEGER, "
+                       "timestamp TIMESTAMP NOT NULL DEFAULT, "
+                       "md_file_id INTEGER NOT NULL, "
+                       "md_parent_id INTEGER, "
+                       "CONSTRAINT crmr_mfi_fk FOREIGN KEY (md_file_id) "
+                       "REFERENCES gpkg.metadata(id), "
+                       "CONSTRAINT crmr_mpi_fk FOREIGN KEY (md_parent_id) "
+                       "REFERENCES gpkg.metadata(id) "
+                       ")");
+
+    if( !oStatement.DB2Execute("OGR_DB2DataSource::CreateMetadataTables") )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Error creating gpkg.metadata_reference: %s",
+                  GetSession()->GetLastError() );
+        m_oSession.RollbackTransaction();
+        return FALSE;
+    }
+
+#ifdef LATER
+    /* From D.3. metadata_reference Table 41. gpkg_metadata_reference Trigger Definition SQL   */
+    const char* pszMetadataReferenceTriggers =
+        "CREATE TRIGGER 'gpkg_metadata_reference_reference_scope_insert' "
+        "BEFORE INSERT ON 'gpkg_metadata_reference' "
+        "FOR EACH ROW BEGIN "
+        "SELECT RAISE(ABORT, 'insert on table gpkg_metadata_reference "
+        "violates constraint: reference_scope must be one of \"geopackage\", "
+        "table\", \"column\", \"row\", \"row/col\"') "
+        "WHERE NOT NEW.reference_scope IN "
+        "('geopackage','table','column','row','row/col'); "
+        "END; "
+        "CREATE TRIGGER 'gpkg_metadata_reference_reference_scope_update' "
+        "BEFORE UPDATE OF 'reference_scope' ON 'gpkg_metadata_reference' "
+        "FOR EACH ROW BEGIN "
+        "SELECT RAISE(ABORT, 'update on table gpkg_metadata_reference "
+        "violates constraint: referrence_scope must be one of \"geopackage\", "
+        "\"table\", \"column\", \"row\", \"row/col\"') "
+        "WHERE NOT NEW.reference_scope IN "
+        "('geopackage','table','column','row','row/col'); "
+        "END; "
+        "CREATE TRIGGER 'gpkg_metadata_reference_column_name_insert' "
+        "BEFORE INSERT ON 'gpkg_metadata_reference' "
+        "FOR EACH ROW BEGIN "
+        "SELECT RAISE(ABORT, 'insert on table gpkg_metadata_reference "
+        "violates constraint: column name must be NULL when reference_scope "
+        "is \"geopackage\", \"table\" or \"row\"') "
+        "WHERE (NEW.reference_scope IN ('geopackage','table','row') "
+        "AND NEW.column_name IS NOT NULL); "
+        "SELECT RAISE(ABORT, 'insert on table gpkg_metadata_reference "
+        "violates constraint: column name must be defined for the specified "
+        "table when reference_scope is \"column\" or \"row/col\"') "
+        "WHERE (NEW.reference_scope IN ('column','row/col') "
+        "AND NOT NEW.table_name IN ( "
+        "SELECT name FROM SQLITE_MASTER WHERE type = 'table' "
+        "AND name = NEW.table_name "
+        "AND sql LIKE ('%' || NEW.column_name || '%'))); "
+        "END; "
+        "CREATE TRIGGER 'gpkg_metadata_reference_column_name_update' "
+        "BEFORE UPDATE OF column_name ON 'gpkg_metadata_reference' "
+        "FOR EACH ROW BEGIN "
+        "SELECT RAISE(ABORT, 'update on table gpkg_metadata_reference "
+        "violates constraint: column name must be NULL when reference_scope "
+        "is \"geopackage\", \"table\" or \"row\"') "
+        "WHERE (NEW.reference_scope IN ('geopackage','table','row') "
+        "AND NEW.column_nameIS NOT NULL); "
+        "SELECT RAISE(ABORT, 'update on table gpkg_metadata_reference "
+        "violates constraint: column name must be defined for the specified "
+        "table when reference_scope is \"column\" or \"row/col\"') "
+        "WHERE (NEW.reference_scope IN ('column','row/col') "
+        "AND NOT NEW.table_name IN ( "
+        "SELECT name FROM SQLITE_MASTER WHERE type = 'table' "
+        "AND name = NEW.table_name "
+        "AND sql LIKE ('%' || NEW.column_name || '%'))); "
+        "END; "
+        "CREATE TRIGGER 'gpkg_metadata_reference_row_id_value_insert' "
+        "BEFORE INSERT ON 'gpkg_metadata_reference' "
+        "FOR EACH ROW BEGIN "
+        "SELECT RAISE(ABORT, 'insert on table gpkg_metadata_reference "
+        "violates constraint: row_id_value must be NULL when reference_scope "
+        "is \"geopackage\", \"table\" or \"column\"') "
+        "WHERE NEW.reference_scope IN ('geopackage','table','column') "
+        "AND NEW.row_id_value IS NOT NULL; "
+        "SELECT RAISE(ABORT, 'insert on table gpkg_metadata_reference "
+        "violates constraint: row_id_value must exist in specified table when "
+        "reference_scope is \"row\" or \"row/col\"') "
+        "WHERE NEW.reference_scope IN ('row','row/col') "
+        "AND NOT EXISTS (SELECT rowid "
+        "FROM (SELECT NEW.table_name AS table_name) WHERE rowid = "
+        "NEW.row_id_value); "
+        "END; "
+        "CREATE TRIGGER 'gpkg_metadata_reference_row_id_value_update' "
+        "BEFORE UPDATE OF 'row_id_value' ON 'gpkg_metadata_reference' "
+        "FOR EACH ROW BEGIN "
+        "SELECT RAISE(ABORT, 'update on table gpkg_metadata_reference "
+        "violates constraint: row_id_value must be NULL when reference_scope "
+        "is \"geopackage\", \"table\" or \"column\"') "
+        "WHERE NEW.reference_scope IN ('geopackage','table','column') "
+        "AND NEW.row_id_value IS NOT NULL; "
+        "SELECT RAISE(ABORT, 'update on table gpkg_metadata_reference "
+        "violates constraint: row_id_value must exist in specified table when "
+        "reference_scope is \"row\" or \"row/col\"') "
+        "WHERE NEW.reference_scope IN ('row','row/col') "
+        "AND NOT EXISTS (SELECT rowid "
+        "FROM (SELECT NEW.table_name AS table_name) WHERE rowid = "
+        "NEW.row_id_value); "
+        "END; "
+        "CREATE TRIGGER 'gpkg_metadata_reference_timestamp_insert' "
+        "BEFORE INSERT ON 'gpkg_metadata_reference' "
+        "FOR EACH ROW BEGIN "
+        "SELECT RAISE(ABORT, 'insert on table gpkg_metadata_reference "
+        "violates constraint: timestamp must be a valid time in ISO 8601 "
+        "\"yyyy-mm-ddThh:mm:ss.cccZ\" form') "
+        "WHERE NOT (NEW.timestamp GLOB "
+        "'[1-2][0-9][0-9][0-9]-[0-1][0-9]-[0-3][0-9]T[0-2][0-9]:[0-5][0-9]:[0-5][0-9].[0-9][0-9][0-9]Z' "
+        "AND strftime('%s',NEW.timestamp) NOT NULL); "
+        "END; "
+        "CREATE TRIGGER 'gpkg_metadata_reference_timestamp_update' "
+        "BEFORE UPDATE OF 'timestamp' ON 'gpkg_metadata_reference' "
+        "FOR EACH ROW BEGIN "
+        "SELECT RAISE(ABORT, 'update on table gpkg_metadata_reference "
+        "violates constraint: timestamp must be a valid time in ISO 8601 "
+        "\"yyyy-mm-ddThh:mm:ss.cccZ\" form') "
+        "WHERE NOT (NEW.timestamp GLOB "
+        "'[1-2][0-9][0-9][0-9]-[0-1][0-9]-[0-3][0-9]T[0-2][0-9]:[0-5][0-9]:[0-5][0-9].[0-9][0-9][0-9]Z' "
+        "AND strftime('%s',NEW.timestamp) NOT NULL); "
+        "END";
+    if ( bCreateTriggers && OGRERR_NONE != SQLCommand(hDB, pszMetadataReferenceTriggers) )
+        return FALSE;
+
+    return TRUE;
+#endif
+    m_oSession.CommitTransaction();
+    return TRUE;
+}
+
+/************************************************************************/
+/*                           HasMetadataTables()                        */
+/************************************************************************/
+
+int OGRDB2DataSource::HasMetadataTables()
+{
+    if (m_bHasMetadataTables) return TRUE;
+
+    OGRDB2Statement oStatement( GetSession() );
+    oStatement.Append("SELECT COUNT(md.id) FROM gpkg.metadata md");
+
+// We assume that if the statement fails, the table doesn't exist
+    if( !oStatement.DB2Execute("OGR_DB2DataSource::HasMetadataTables") )
+    {
+        CPLDebug("OGRDB2DataSource::HasMetadataTables","Tables not found");
+        if (!CreateMetadataTables()) {
+            return FALSE;
+        }
+    }
+    m_bHasMetadataTables = TRUE;
+
+    return TRUE;
+}
+
+
+/************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **OGRDB2DataSource::GetMetadataDomainList()
+{
+    CPLDebug("OGRDB2DataSource::GetMetadataDomainList","Entering");
+    GetMetadata();
+    if( m_osRasterTable.size() != 0 )
+        GetMetadata("GEOPACKAGE");
+    return BuildMetadataDomainList(GDALPamDataset::GetMetadataDomainList(),
+                                   TRUE,
+                                   "SUBDATASETS", NULL);
+}
+
+/************************************************************************/
+/*                        CheckMetadataDomain()                         */
+/************************************************************************/
+
+const char* OGRDB2DataSource::CheckMetadataDomain( const char* pszDomain )
+{
+    DB2_DEBUG_ENTER("OGRDB2DataSource::CheckMetadataDomain");
+    if( pszDomain != NULL && EQUAL(pszDomain, "GEOPACKAGE") &&
+            m_osRasterTable.size() == 0 )
+    {
+        CPLError(CE_Warning, CPLE_IllegalArg,
+                 "Using GEOPACKAGE for a non-raster geopackage is not supported. "
+                 "Using default domain instead");
+        return NULL;
+    }
+    return pszDomain;
+}
+
+
+/************************************************************************/
+/*                            GetMetadata()                             */
+/************************************************************************/
+
+char **OGRDB2DataSource::GetMetadata( const char *pszDomain )
+
+{
+    DB2_DEBUG_ENTER("OGRDB2DataSource::GetMetadata");
+    if( pszDomain != NULL && EQUAL(pszDomain,"SUBDATASETS") )
+        return m_papszSubDatasets;
+    CPLDebug("OGRDB2DataSource::GetMetadata","m_bHasReadMetadataFromStorage1: %d", m_bHasReadMetadataFromStorage);
+    if( m_bHasReadMetadataFromStorage )
+        return GDALPamDataset::GetMetadata( pszDomain );
+
+    m_bHasReadMetadataFromStorage = TRUE;
+    CPLDebug("OGRDB2DataSource::GetMetadata","m_bHasReadMetadataFromStorage2: %d", m_bHasReadMetadataFromStorage);
+
+    if ( !HasMetadataTables() )
+        return GDALPamDataset::GetMetadata( pszDomain );
+
+    OGRDB2Statement oStatement( GetSession() );
+    if( m_osRasterTable.size() )
+    {
+
+        oStatement.Appendf(
+            "SELECT md.metadata, md.md_standard_uri, md.mime_type, "
+            "mdr.reference_scope FROM gpkg.metadata md "
+            "JOIN gpkg.metadata_reference mdr ON (md.id = mdr.md_file_id ) "
+            "WHERE mdr.reference_scope = 'geopackage' OR "
+            "(mdr.reference_scope = 'table' AND mdr.table_name = '%s') "
+            " ORDER BY md.id",
+            m_osRasterTable.c_str());
+    }
+    else
+    {
+        oStatement.Append(
+            "SELECT md.metadata, md.md_standard_uri, md.mime_type, "
+            "mdr.reference_scope FROM gpkg.metadata md "
+            "JOIN gpkg.metadata_reference mdr ON (md.id = mdr.md_file_id ) "
+            "WHERE mdr.reference_scope = 'geopackage' ORDER BY md.id");
+    }
+
+    if( !oStatement.DB2Execute("OGR_DB2DataSource::GetMetadata") )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Failed getting metadata; error: %s",
+                 GetSession()->GetLastError());
+        return GDALPamDataset::GetMetadata( pszDomain );
+    }
+
+    char** papszMetadata = CSLDuplicate(GDALPamDataset::GetMetadata());
+
+    /* GDAL metadata */
+    while(oStatement.Fetch())
+    {
+        const char* pszMetadata = oStatement.GetColData( 0);
+        const char* pszMDStandardURI = oStatement.GetColData( 1);
+        const char* pszMimeType = oStatement.GetColData( 2);
+        const char* pszReferenceScope = oStatement.GetColData( 3);
+        int bIsGPKGScope = EQUAL(pszReferenceScope, "geopackage");
+        if( pszMetadata == NULL )
+            continue;
+        if( pszMDStandardURI != NULL && EQUAL(pszMDStandardURI, "http://gdal.org") &&
+                pszMimeType != NULL && EQUAL(pszMimeType, "text/xml") )
+        {
+            CPLXMLNode* psXMLNode = CPLParseXMLString(pszMetadata);
+            if( psXMLNode )
+            {
+                GDALMultiDomainMetadata oLocalMDMD;
+                oLocalMDMD.XMLInit(psXMLNode, FALSE);
+                if( m_osRasterTable.size() && bIsGPKGScope )
+                {
+                    oMDMD.SetMetadata( oLocalMDMD.GetMetadata(), "GEOPACKAGE" );
+                }
+                else
+                {
+                    papszMetadata = CSLMerge(papszMetadata, oLocalMDMD.GetMetadata());
+                    char** papszDomainList = oLocalMDMD.GetDomainList();
+                    char** papszIter = papszDomainList;
+                    while( papszIter && *papszIter )
+                    {
+                        if( !EQUAL(*papszIter, "") && !EQUAL(*papszIter, "IMAGE_STRUCTURE") )
+                            oMDMD.SetMetadata(oLocalMDMD.GetMetadata(*papszIter), *papszIter);
+                        papszIter ++;
+                    }
+                }
+                CPLDestroyXMLNode(psXMLNode);
+            }
+        }
+    }
+
+    GDALPamDataset::SetMetadata(papszMetadata);
+    CSLDestroy(papszMetadata);
+    papszMetadata = NULL;
+    CPLDebug("OGRDB2DataSource::GetMetadata","Exiting");
+#ifdef LATER
+// where is the result set for this section created????
+    /* Add non-GDAL metadata now */
+    int nNonGDALMDILocal = 1;
+    int nNonGDALMDIGeopackage = 1;
+    for(int i=0; i<oResult.nRowCount; i++)
+    {
+        const char *pszMetadata = oStatement.GetColData( 0, i);
+        const char* pszMDStandardURI = oStatement.GetColData( 1, i);
+        const char* pszMimeType = oStatement.GetColData( 2, i);
+        const char* pszReferenceScope = oStatement.GetColData( 3, i);
+        int bIsGPKGScope = EQUAL(pszReferenceScope, "geopackage");
+        if( pszMetadata == NULL )
+            continue;
+        if( pszMDStandardURI != NULL && EQUAL(pszMDStandardURI, "http://gdal.org") &&
+                pszMimeType != NULL && EQUAL(pszMimeType, "text/xml") )
+            continue;
+
+        if( m_osRasterTable.size() && bIsGPKGScope )
+        {
+            oMDMD.SetMetadataItem( CPLSPrintf("GPKG_METADATA_ITEM_%d", nNonGDALMDIGeopackage),
+                                   pszMetadata,
+                                   "GEOPACKAGE" );
+            nNonGDALMDIGeopackage ++;
+        }
+        /*else if( strcmp( pszMDStandardURI, "http://www.isotc211.org/2005/gmd" ) == 0 &&
+            strcmp( pszMimeType, "text/xml" ) == 0 )
+        {
+            char* apszMD[2];
+            apszMD[0] = (char*)pszMetadata;
+            apszMD[1] = NULL;
+            oMDMD.SetMetadata(apszMD, "xml:MD_Metadata");
+        }*/
+        else
+        {
+            oMDMD.SetMetadataItem( CPLSPrintf("GPKG_METADATA_ITEM_%d", nNonGDALMDILocal),
+                                   pszMetadata );
+            nNonGDALMDILocal ++;
+        }
+    }
+#endif
+
+    return GDALPamDataset::GetMetadata(pszDomain);
+
+}
+
+
+/************************************************************************/
+/*                          GetMetadataItem()                           */
+/************************************************************************/
+
+const char *OGRDB2DataSource::GetMetadataItem( const char * pszName,
+        const char * pszDomain )
+{
+    pszDomain = CheckMetadataDomain(pszDomain);
+    CPLDebug("OGRDB2DataSource::GetMetadataItem","'%s'; '%s'; '%s'",pszName,pszDomain,CSLFetchNameValue( GetMetadata(pszDomain), pszName ));
+    return CSLFetchNameValue( GetMetadata(pszDomain), pszName );
+}
+
+/************************************************************************/
+/*                            SetMetadata()                             */
+/************************************************************************/
+
+CPLErr OGRDB2DataSource::SetMetadata( char ** papszMetadata, const char * pszDomain )
+{
+    pszDomain = CheckMetadataDomain(pszDomain);
+    m_bMetadataDirty = TRUE;
+    GetMetadata(); /* force loading from storage if needed */
+    return GDALPamDataset::SetMetadata(papszMetadata, pszDomain);
+}
+
+/************************************************************************/
+/*                          SetMetadataItem()                           */
+/************************************************************************/
+
+CPLErr OGRDB2DataSource::SetMetadataItem( const char * pszName,
+        const char * pszValue,
+        const char * pszDomain )
+{
+    pszDomain = CheckMetadataDomain(pszDomain);
+    m_bMetadataDirty = TRUE;
+    GetMetadata(); /* force loading from storage if needed */
+    CPLDebug("OGRDB2DataSource::SetMetadataItem","'%s'; '%s'; '%s'",pszName,pszDomain,pszValue);
+    return GDALPamDataset::SetMetadataItem(pszName, pszValue, pszDomain);
+}
diff --git a/ogr/ogrsf_frmts/db2/ogrdb2driver.cpp b/ogr/ogrsf_frmts/db2/ogrdb2driver.cpp
new file mode 100644
index 0000000..8b78f92
--- /dev/null
+++ b/ogr/ogrsf_frmts/db2/ogrdb2driver.cpp
@@ -0,0 +1,252 @@
+/*****************************************************************************
+ *
+ * Project:  DB2 Spatial driver
+ * Purpose:  Definition of classes for OGR DB2 Spatial driver.
+ * Author:   David Adler, dadler at adtechgeospatial dot com
+ *
+ *****************************************************************************
+ * Copyright (c) 2010, Tamas Szekeres
+ * Copyright (c) 2015, David Adler
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+#include "ogr_db2.h"
+#include "cpl_conv.h"
+
+/************************************************************************/
+/*                       OGRDB2DriverIdentify()                  */
+/************************************************************************/
+
+static int OGRDB2DriverIdentify( GDALOpenInfo* poOpenInfo )
+{
+    if( STARTS_WITH_CI(poOpenInfo->pszFilename, DB2ODBC_PREFIX) )
+        return TRUE;
+
+    return FALSE;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+static GDALDataset *OGRDB2DriverOpen( GDALOpenInfo* poOpenInfo )
+{
+    if( !OGRDB2DriverIdentify(poOpenInfo) )
+        return NULL;
+
+    CPLDebug( "OGRDB2DriverOpen", "pszFilename: '%s'",
+              poOpenInfo->pszFilename);
+
+    OGRDB2DataSource   *poDS = new OGRDB2DataSource();
+
+    if( !poDS->Open( poOpenInfo ) )
+    {
+        CPLDebug( "OGRDB2DriverOpen", "open error");
+        delete poDS;
+        poDS = NULL;
+    }
+    CPLDebug( "OGRDB2DriverOpen", "Exit");
+    return poDS;
+}
+
+/************************************************************************/
+/*                               Create()                               */
+/************************************************************************/
+
+static GDALDataset* OGRDB2DriverCreate( const char * pszFilename,
+                                        int nXSize,
+                                        int nYSize,
+                                        int nBands,
+                                        GDALDataType eDT,
+                                        char **papszOptions )
+{
+    OGRDB2DataSource   *poDS = new OGRDB2DataSource();
+    CPLDebug( "OGRDB2DriverCreate", "pszFilename: '%s'", pszFilename);
+    CPLDebug( "OGRDB2DriverCreate", "eDT: %d", eDT);
+    if( !poDS->Create( pszFilename, nXSize, nYSize,
+                       nBands, eDT, papszOptions ) )
+    {
+        delete poDS;
+        poDS = NULL;
+    }
+    return poDS;
+}
+
+/************************************************************************/
+/*                               Delete()                               */
+/************************************************************************/
+
+static CPLErr OGRDB2DriverDelete( const char *pszFilename )
+
+{
+#ifdef DEBUG_DB2
+    CPLDebug( "OGRDB2DriverDelete", "pszFilename: '%s'", pszFilename);
+#endif
+    if( VSIUnlink(pszFilename) == 0 )
+        return CE_None;
+    else
+        return CE_Failure;
+}
+
+
+/************************************************************************/
+/*                           RegisterOGRDB2()                  */
+/************************************************************************/
+
+void RegisterOGRDB2()
+{
+    if( GDALGetDriverByName("DB2ODBC") != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+    poDriver->SetDescription( "DB2ODBC" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "IBM DB2 Spatial Database" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_db2.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte" );
+#define COMPRESSION_OPTIONS \
+"  <Option name='TILE_FORMAT' type='string-select' description='Format to use to create tiles' default='PNG_JPEG'>" \
+"    <Value>PNG_JPEG</Value>" \
+"    <Value>PNG</Value>" \
+"    <Value>PNG8</Value>" \
+"    <Value>JPEG</Value>" \
+"    <Value>WEBP</Value>" \
+"  </Option>" \
+"  <Option name='QUALITY' type='int' min='1' max='100' description='Quality for JPEG and WEBP tiles' default='75'/>" \
+"  <Option name='ZLEVEL' type='int' min='1' max='9' description='DEFLATE compression level for PNG tiles' default='6'/>" \
+"  <Option name='DITHER' type='boolean' description='Whether to apply Floyd-Steinberg dithering (for TILE_FORMAT=PNG8)' default='NO'/>"
+
+
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST, "<OpenOptionList>"
+                               "  <Option name='TABLE' type='string' description='Name of tile user-table'/>"
+                               "  <Option name='ZOOM_LEVEL' type='integer' description='Zoom level of full resolution. If not specified, maximum non-empty zoom level'/>"
+                               "  <Option name='BAND_COUNT' type='int' min='1' max='4' description='Number of raster bands' default='4'/>"
+                               "  <Option name='MINX' type='float' description='Minimum X of area of interest'/>"
+                               "  <Option name='MINY' type='float' description='Minimum Y of area of interest'/>"
+                               "  <Option name='MAXX' type='float' description='Maximum X of area of interest'/>"
+                               "  <Option name='MAXY' type='float' description='Maximum Y of area of interest'/>"
+                               "  <Option name='USE_TILE_EXTENT' type='boolean' description='Use tile extent of content to determine area of interest' default='NO'/>"
+                               "  <Option name='WHERE' type='string' description='SQL WHERE clause to be appended to tile requests'/>"
+                               COMPRESSION_OPTIONS
+                               "</OpenOptionList>");
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, "<CreationOptionList>"
+                               "  <Option name='RASTER_TABLE' type='string' description='Name of tile user table'/>"
+                               "  <Option name='APPEND_SUBDATASET' type='boolean' description='Set to YES to add a new tile user table to an existing GeoPackage instead of replacing it' default='NO'/>"
+                               "  <Option name='RASTER_IDENTIFIER' type='string' description='Human-readable identifier (e.g. short name)'/>"
+                               "  <Option name='RASTER_DESCRIPTION' type='string' description='Human-readable description'/>"
+                               "  <Option name='BLOCKSIZE' type='int' description='Block size in pixels' default='256' max='4096'/>"
+                               "  <Option name='BLOCKXSIZE' type='int' description='Block width in pixels' default='256' max='4096'/>"
+                               "  <Option name='BLOCKYSIZE' type='int' description='Block height in pixels' default='256' max='4096'/>"
+                               COMPRESSION_OPTIONS
+                               "  <Option name='TILING_SCHEME' type='string-select' description='Which tiling scheme to use' default='CUSTOM'>"
+                               "    <Value>CUSTOM</Value>"
+                               "    <Value>GoogleCRS84Quad</Value>"
+                               "    <Value>GoogleMapsCompatible</Value>"
+                               "    <Value>InspireCRS84Quad</Value>"
+                               "    <Value>PseudoTMS_GlobalGeodetic</Value>"
+                               "    <Value>PseudoTMS_GlobalMercator</Value>"
+                               "  </Option>"
+                               "  <Option name='ZOOM_LEVEL_STRATEGY' type='string-select' description='Strategy to determine zoom level. Only used for TILING_SCHEME != CUSTOM' default='AUTO'>"
+                               "    <Value>AUTO</Value>"
+                               "    <Value>LOWER</Value>"
+                               "    <Value>UPPER</Value>"
+                               "  </Option>"
+                               "  <Option name='RESAMPLING' type='string-select' description='Resampling algorithm. Only used for TILING_SCHEME != CUSTOM' default='BILINEAR'>"
+                               "    <Value>NEAREST</Value>"
+                               "    <Value>BILINEAR</Value>"
+                               "    <Value>CUBIC</Value>"
+                               "    <Value>CUBICSPLINE</Value>"
+                               "    <Value>LANCZOS</Value>"
+                               "    <Value>MODE</Value>"
+                               "    <Value>AVERAGE</Value>"
+                               "  </Option>"
+                               "</CreationOptionList>");
+
+    poDriver->SetMetadataItem(
+        GDAL_DS_LAYER_CREATIONOPTIONLIST,
+        "<LayerCreationOptionList>"
+        "  <Option name='GEOM_TYPE' type='string-select' "
+        "          description='Format of geometry columns' "
+        "          default='geometry'>"
+        "    <Value>geometry</Value>"
+        "  </Option>"
+        "  <Option name='OVERWRITE' type='boolean' "
+        "          description='Whether to overwrite an existing table "
+        "                       with the layer name to be created' "
+        "          default='NO'/>"
+        "  <Option name='LAUNDER' type='boolean' "
+        "          description='Whether layer and field names will be "
+        "                       laundered' default='YES'/>"
+        "  <Option name='PRECISION' type='boolean' "
+        "          description='Whether fields created should keep the "
+        "                       width and precision' default='YES'/>"
+        "  <Option name='DIM' type='integer' "
+        "          description='Set to 2 to force the geometries to be "
+        "                       2D, or 3 to be 2.5D'/>"
+        "  <Option name='GEOMETRY_NAME' type='string' "
+        "          description='Name of geometry column.' "
+        "          default='ogr_geometry' deprecated_alias='GEOM_NAME'/>"
+        "  <Option name='SCHEMA' type='string' "
+        "          description='Name of schema into which to create the "
+        "                       new table' "
+        "          default='dbo'/>"
+        "  <Option name='SRID' type='int' "
+        "          description='Forced SRID of the layer'/>"
+        "  <Option name='SPATIAL_INDEX' type='boolean' "
+        "          description='Whether to create a spatial index' "
+        "          default='YES'/>"
+        "  <Option name='UPLOAD_GEOM_FORMAT' type='string-select' "
+        "          description='Geometry format when creating or "
+        "                       modifying features' "
+        "          default='wkb'>"
+        "    <Value>wkb</Value>"
+        "    <Value>wkt</Value>"
+        "  </Option>"
+        "  <Option name='FID' type='string' "
+        "          description='Name of the FID column to create' "
+        "          default='OBJECTID'/>"
+        "  <Option name='FID64' type='boolean' "
+        "          description='Whether to create the FID column with "
+        "                       bigint type to handle 64bit wide ids' "
+        "          default='YES'/>"
+        "  <Option name='GEOMETRY_NULLABLE' type='boolean' "
+        "          description='Whether the values of the geometry "
+        "                       column can be NULL' "
+        "          default='YES'/>"
+        "</LayerCreationOptionList>");
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
+                               "Integer Integer64 Real String Date Time "
+                               "DateTime Binary" );
+    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_FIELDS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_DEFAULT_FIELDS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_GEOMFIELDS, "YES" );
+
+    poDriver->pfnOpen = OGRDB2DriverOpen;
+    poDriver->pfnIdentify = OGRDB2DriverIdentify;
+    poDriver->pfnCreate = OGRDB2DriverCreate;
+    poDriver->pfnDelete = OGRDB2DriverDelete;
+    poDriver->pfnCreateCopy = OGRDB2DataSource::CreateCopy;
+
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/ogr/ogrsf_frmts/db2/ogrdb2geometryvalidator.cpp b/ogr/ogrsf_frmts/db2/ogrdb2geometryvalidator.cpp
new file mode 100644
index 0000000..4e827cb
--- /dev/null
+++ b/ogr/ogrsf_frmts/db2/ogrdb2geometryvalidator.cpp
@@ -0,0 +1,505 @@
+/*****************************************************************************
+ *
+ * Project:  DB2 Spatial driver
+ * Purpose:  Implements OGRDB2GeometryValidator class to create valid
+ *           Geometries.
+ * Author:   David Adler, dadler at adtechgeospatial dot com
+ *
+ *****************************************************************************
+ * Copyright (c) 2010, Tamas Szekeres
+ * Copyright (c) 2015, David Adler
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_conv.h"
+#include "ogr_db2.h"
+
+/************************************************************************/
+/*                   OGRDB2GeometryValidator()                        */
+/************************************************************************/
+
+OGRDB2GeometryValidator::OGRDB2GeometryValidator(OGRGeometry *poGeom)
+{
+    poOriginalGeometry = poGeom;
+    poValidGeometry = NULL;
+    bIsValid = ValidateGeometry(poGeom);
+}
+
+/************************************************************************/
+/*                      ~OGRDB2GeometryValidator()                    */
+/************************************************************************/
+
+OGRDB2GeometryValidator::~OGRDB2GeometryValidator()
+{
+    if (poValidGeometry)
+        delete poValidGeometry;
+}
+
+/************************************************************************/
+/*                         ValidatePoint()                              */
+/************************************************************************/
+
+int OGRDB2GeometryValidator::ValidatePoint(CPL_UNUSED OGRPoint* poGeom)
+{
+    return TRUE;
+}
+
+/************************************************************************/
+/*                     ValidateMultiPoint()                             */
+/************************************************************************/
+
+int OGRDB2GeometryValidator::ValidateMultiPoint(
+                                        CPL_UNUSED OGRMultiPoint* poGeom)
+{
+    return TRUE;
+}
+
+/************************************************************************/
+/*                         ValidateLineString()                         */
+/************************************************************************/
+
+int OGRDB2GeometryValidator::ValidateLineString(OGRLineString * poGeom)
+{
+    OGRPoint* poPoint0 = NULL;
+    int i;
+    int bResult = FALSE;
+
+    for (i = 0; i < poGeom->getNumPoints(); i++)
+    {
+        if (poPoint0 == NULL)
+        {
+            poPoint0 = new OGRPoint();
+            poGeom->getPoint(i, poPoint0);
+            continue;
+        }
+
+        if (poPoint0->getX() == poGeom->getX(i)
+            && poPoint0->getY() == poGeom->getY(i))
+            continue;
+
+        bResult = TRUE;
+        break;
+    }
+
+    if (!bResult)
+    {
+        if (poValidGeometry)
+            delete poValidGeometry;
+
+        poValidGeometry = NULL;
+
+        // create a compatible geometry
+        if (poPoint0 != NULL)
+        {
+            CPLError( CE_Warning, CPLE_NotSupported,
+                      "Linestring has no distinct points "
+                      "constructing point geometry instead." );
+
+            // create a point
+            poValidGeometry = poPoint0;
+            poPoint0 = NULL;
+        }
+        else
+        {
+            CPLError( CE_Warning, CPLE_NotSupported,
+                      "Linestring has no points. Removing the geometry "
+                      "from the output." );
+        }
+    }
+
+    if (poPoint0)
+        delete poPoint0;
+
+    return bResult;
+}
+
+/************************************************************************/
+/*                         ValidateLinearRing()                         */
+/************************************************************************/
+
+int OGRDB2GeometryValidator::ValidateLinearRing(OGRLinearRing * poGeom)
+{
+    OGRPoint* poPoint0 = NULL;
+    OGRPoint* poPoint1 = NULL;
+    int i;
+    int bResult = FALSE;
+
+    poGeom->closeRings();
+
+    for (i = 0; i < poGeom->getNumPoints(); i++)
+    {
+        if (poPoint0 == NULL)
+        {
+            poPoint0 = new OGRPoint();
+            poGeom->getPoint(i, poPoint0);
+            continue;
+        }
+
+        if (poPoint0->getX() == poGeom->getX(i)
+            && poPoint0->getY() == poGeom->getY(i))
+            continue;
+
+        if (poPoint1 == NULL)
+        {
+            poPoint1 = new OGRPoint();
+            poGeom->getPoint(i, poPoint1);
+            continue;
+        }
+
+        if (poPoint1->getX() == poGeom->getX(i)
+            && poPoint1->getY() == poGeom->getY(i))
+            continue;
+
+        bResult = TRUE;
+        break;
+    }
+
+    if (!bResult)
+    {
+        if (poValidGeometry)
+            delete poValidGeometry;
+
+        poValidGeometry = NULL;
+
+        // create a compatible geometry
+        if (poPoint1 != NULL)
+        {
+            CPLError( CE_Warning, CPLE_NotSupported,
+                      "Linear ring has only 2 distinct points constructing "
+                      "linestring geometry instead." );
+
+            // create a linestring
+            poValidGeometry = new OGRLineString();
+            ((OGRLineString*)poValidGeometry)->setNumPoints( 2 );
+            ((OGRLineString*)poValidGeometry)->addPoint(poPoint0);
+            ((OGRLineString*)poValidGeometry)->addPoint(poPoint1);
+        }
+        else if (poPoint0 != NULL)
+        {
+            CPLError( CE_Warning, CPLE_NotSupported,
+                      "Linear ring has no distinct points constructing point "
+                      "geometry instead." );
+
+            // create a point
+            poValidGeometry = poPoint0;
+            poPoint0 = NULL;
+        }
+        else
+        {
+            CPLError( CE_Warning, CPLE_NotSupported,
+                      "Linear ring has no points. Removing the geometry "
+                      "from the output." );
+        }
+    }
+
+    if (poPoint0)
+        delete poPoint0;
+
+    if (poPoint1)
+        delete poPoint1;
+
+    return bResult;
+}
+
+/************************************************************************/
+/*                     ValidateMultiLineString()                        */
+/************************************************************************/
+
+int OGRDB2GeometryValidator::ValidateMultiLineString(
+                                            OGRMultiLineString * poGeom)
+{
+    int i, j;
+    OGRGeometry* poLineString;
+    OGRGeometryCollection* poGeometries = NULL;
+
+    for (i = 0; i < poGeom->getNumGeometries(); i++)
+    {
+        poLineString = poGeom->getGeometryRef(i);
+        if (poLineString->getGeometryType() != wkbLineString
+            && poLineString->getGeometryType() != wkbLineString25D)
+        {
+            // non linestring geometry
+            if (!poGeometries)
+            {
+                poGeometries = new OGRGeometryCollection();
+                for (j = 0; j < i; j++)
+                    poGeometries->addGeometry(poGeom->getGeometryRef(j));
+            }
+            if (ValidateGeometry(poLineString))
+                poGeometries->addGeometry(poLineString);
+            else
+                poGeometries->addGeometry(poValidGeometry);
+
+            continue;
+        }
+
+        if (!ValidateLineString((OGRLineString*)poLineString))
+        {
+            // non valid linestring
+            if (!poGeometries)
+            {
+                poGeometries = new OGRGeometryCollection();
+                for (j = 0; j < i; j++)
+                    poGeometries->addGeometry(poGeom->getGeometryRef(j));
+            }
+
+            poGeometries->addGeometry(poValidGeometry);
+            continue;
+        }
+
+        if (poGeometries)
+            poGeometries->addGeometry(poLineString);
+    }
+
+    if (poGeometries)
+    {
+        if (poValidGeometry)
+            delete poValidGeometry;
+
+        poValidGeometry = poGeometries;
+    }
+
+    return (poValidGeometry == NULL);
+}
+
+/************************************************************************/
+/*                         ValidatePolygon()                            */
+/************************************************************************/
+
+int OGRDB2GeometryValidator::ValidatePolygon(OGRPolygon* poGeom)
+{
+    int i,j;
+    OGRLinearRing* poRing = poGeom->getExteriorRing();
+    OGRGeometry* poInteriorRing;
+
+    if (poRing == NULL)
+        return FALSE;
+
+    OGRGeometryCollection* poGeometries = NULL;
+
+    if (!ValidateLinearRing(poRing))
+    {
+        if (poGeom->getNumInteriorRings() > 0)
+        {
+            poGeometries = new OGRGeometryCollection();
+            poGeometries->addGeometryDirectly(poValidGeometry);
+        }
+    }
+
+    for (i = 0; i < poGeom->getNumInteriorRings(); i++)
+    {
+        poInteriorRing = poGeom->getInteriorRing(i);
+        if (!ValidateLinearRing((OGRLinearRing*)poInteriorRing))
+        {
+            if (!poGeometries)
+            {
+                poGeometries = new OGRGeometryCollection();
+                poGeometries->addGeometry(poRing);
+                for (j = 0; j < i; j++)
+                    poGeometries->addGeometry(poGeom->getInteriorRing(j));
+            }
+
+            poGeometries->addGeometry(poValidGeometry);
+            continue;
+        }
+
+        if (poGeometries)
+            poGeometries->addGeometry(poInteriorRing);
+    }
+
+    if (poGeometries)
+    {
+        if (poValidGeometry)
+            delete poValidGeometry;
+
+        poValidGeometry = poGeometries;
+    }
+
+    return (poValidGeometry == NULL);
+}
+
+/************************************************************************/
+/*                         ValidateMultiPolygon()                       */
+/************************************************************************/
+
+int OGRDB2GeometryValidator::ValidateMultiPolygon(OGRMultiPolygon* poGeom)
+{
+    int i, j;
+    OGRGeometry* poPolygon;
+    OGRGeometryCollection* poGeometries = NULL;
+
+    for (i = 0; i < poGeom->getNumGeometries(); i++)
+    {
+        poPolygon = poGeom->getGeometryRef(i);
+        if (poPolygon->getGeometryType() != wkbPolygon
+            && poPolygon->getGeometryType() != wkbPolygon25D)
+        {
+            // non polygon geometry
+            if (!poGeometries)
+            {
+                poGeometries = new OGRGeometryCollection();
+                for (j = 0; j < i; j++)
+                    poGeometries->addGeometry(poGeom->getGeometryRef(j));
+            }
+            if (ValidateGeometry(poPolygon))
+                poGeometries->addGeometry(poPolygon);
+            else
+                poGeometries->addGeometry(poValidGeometry);
+
+            continue;
+        }
+
+        if (!ValidatePolygon((OGRPolygon*)poPolygon))
+        {
+            // non valid polygon
+            if (!poGeometries)
+            {
+                poGeometries = new OGRGeometryCollection();
+                for (j = 0; j < i; j++)
+                    poGeometries->addGeometry(poGeom->getGeometryRef(j));
+            }
+
+            poGeometries->addGeometry(poValidGeometry);
+            continue;
+        }
+
+        if (poGeometries)
+            poGeometries->addGeometry(poPolygon);
+    }
+
+    if (poGeometries)
+    {
+        if (poValidGeometry)
+            delete poValidGeometry;
+
+        poValidGeometry = poGeometries;
+    }
+
+    return poValidGeometry == NULL;
+}
+
+/************************************************************************/
+/*                     ValidateGeometryCollection()                     */
+/************************************************************************/
+
+int OGRDB2GeometryValidator::ValidateGeometryCollection(
+                                            OGRGeometryCollection* poGeom)
+{
+    int i, j;
+    OGRGeometry* poGeometry;
+    OGRGeometryCollection* poGeometries = NULL;
+
+    for (i = 0; i < poGeom->getNumGeometries(); i++)
+    {
+        poGeometry = poGeom->getGeometryRef(i);
+
+        if (!ValidateGeometry(poGeometry))
+        {
+            // non valid geometry
+            if (!poGeometries)
+            {
+                poGeometries = new OGRGeometryCollection();
+                for (j = 0; j < i; j++)
+                    poGeometries->addGeometry(poGeom->getGeometryRef(j));
+            }
+
+            if (poValidGeometry)
+                poGeometries->addGeometry(poValidGeometry);
+            continue;
+        }
+
+        if (poGeometries)
+            poGeometries->addGeometry(poGeometry);
+    }
+
+    if (poGeometries)
+    {
+        if (poValidGeometry)
+            delete poValidGeometry;
+
+        poValidGeometry = poGeometries;
+    }
+
+    return (poValidGeometry == NULL);
+}
+
+/************************************************************************/
+/*                         ValidateGeometry()                           */
+/************************************************************************/
+
+int OGRDB2GeometryValidator::ValidateGeometry(OGRGeometry* poGeom)
+{
+    if (!poGeom)
+        return FALSE;
+
+    switch (poGeom->getGeometryType())
+    {
+    case wkbPoint:
+    case wkbPoint25D:
+        return ValidatePoint((OGRPoint*)poGeom);
+    case wkbLineString:
+    case wkbLineString25D:
+        return ValidateLineString((OGRLineString*)poGeom);
+    case wkbPolygon:
+    case wkbPolygon25D:
+        return ValidatePolygon((OGRPolygon*)poGeom);
+    case wkbMultiPoint:
+    case wkbMultiPoint25D:
+        return ValidateMultiPoint((OGRMultiPoint*)poGeom);
+    case wkbMultiLineString:
+    case wkbMultiLineString25D:
+        return ValidateMultiLineString((OGRMultiLineString*)poGeom);
+    case wkbMultiPolygon:
+    case wkbMultiPolygon25D:
+        return ValidateMultiPolygon((OGRMultiPolygon*)poGeom);
+    case wkbGeometryCollection:
+    case wkbGeometryCollection25D:
+        return ValidateGeometryCollection((OGRGeometryCollection*)poGeom);
+    case wkbLinearRing:
+        return ValidateLinearRing((OGRLinearRing*)poGeom);
+    default:
+        return FALSE;
+    }
+}
+
+/************************************************************************/
+/*                      GetValidGeometryRef()                           */
+/************************************************************************/
+OGRGeometry* OGRDB2GeometryValidator::GetValidGeometryRef()
+{
+    if (bIsValid || poOriginalGeometry == NULL)
+        return poOriginalGeometry;
+
+    if (poValidGeometry)
+    {
+        CPLError( CE_Warning, CPLE_NotSupported,
+                  "Invalid geometry has been converted from %s to %s.",
+                  poOriginalGeometry->getGeometryName(),
+                  poValidGeometry->getGeometryName() );
+    }
+    else
+    {
+        CPLError( CE_Warning, CPLE_NotSupported,
+                  "Invalid geometry has been converted from %s to null.",
+                  poOriginalGeometry->getGeometryName());
+    }
+
+    return poValidGeometry;
+}
diff --git a/ogr/ogrsf_frmts/db2/ogrdb2layer.cpp b/ogr/ogrsf_frmts/db2/ogrdb2layer.cpp
new file mode 100644
index 0000000..6aa8f84
--- /dev/null
+++ b/ogr/ogrsf_frmts/db2/ogrdb2layer.cpp
@@ -0,0 +1,497 @@
+/*****************************************************************************
+ *
+ * Project:  DB2 Spatial driver
+ * Purpose:  Definition of classes for OGR DB2 Spatial driver.
+ * Author:   David Adler, dadler at adtechgeospatial dot com
+ *
+ *****************************************************************************
+ * Copyright (c) 2010, Tamas Szekeres
+ * Copyright (c) 2015, David Adler
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_db2.h"
+
+/************************************************************************/
+/*                        OGRDB2Layer()                        */
+/************************************************************************/
+
+OGRDB2Layer::OGRDB2Layer()
+
+{
+    poDS = NULL;
+    pszGeomColumn = NULL;
+    pszFIDColumn = NULL;
+    bIsIdentityFid = FALSE;
+    cGenerated = ' ';
+    panFieldOrdinals = NULL;
+    m_poStmt = NULL;
+    iNextShapeId = 0;
+    poSRS = NULL;
+    nSRSId = -1; // we haven't even queried the database for it yet.
+}
+
+/************************************************************************/
+/*                      ~OGRDB2Layer()                         */
+/************************************************************************/
+
+OGRDB2Layer::~OGRDB2Layer()
+
+{
+    CPLDebug("OGRDB2Layer::~OGRDB2Layer","entering");
+    CPLDebug("OGRDB2Layer::~OGRDB2Layer",
+             "m_nFeaturesRead: %d; poFeatureDefn: %p", m_nFeaturesRead,poFeatureDefn);
+    if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
+    {
+        CPLDebug( "OGR_DB2Layer",
+                  "%d features read on layer '%s'.",
+                  (int) m_nFeaturesRead,
+                  poFeatureDefn->GetName() );
+    }
+
+    if( m_poStmt )
+    {
+        delete m_poStmt;
+        m_poStmt = NULL;
+    }
+
+    CPLFree( pszGeomColumn );
+    CPLFree( pszFIDColumn );
+    CPLFree( panFieldOrdinals );
+
+    if( poFeatureDefn )
+    {
+        poFeatureDefn->Release();
+        poFeatureDefn = NULL;
+    }
+
+    if( poSRS )
+        poSRS->Release();
+    CPLDebug("OGRDB2Layer::~OGRDB2Layer","exiting") ;
+}
+
+/************************************************************************/
+/*                          BuildFeatureDefn()                          */
+/*                                                                      */
+/*      Build feature definition from a set of column definitions       */
+/*      set on a statement.  Sift out geometry and FID fields.          */
+/************************************************************************/
+
+CPLErr OGRDB2Layer::BuildFeatureDefn( const char *pszLayerName,
+                                      OGRDB2Statement *poStmt )
+
+{
+    poFeatureDefn = new OGRFeatureDefn( pszLayerName );
+    int    nRawColumns = poStmt->GetColCount();
+    CPLDebug( "OGR_DB2Layer::BuildFeatureDefn",
+              "pszLayerName: '%s'; pszGeomColumn: '%s'",
+              pszLayerName, pszGeomColumn);
+    poFeatureDefn->Reference();
+
+    CPLFree(panFieldOrdinals);
+    panFieldOrdinals = (int *) CPLMalloc( sizeof(int) * nRawColumns );
+
+    /* -------------------------------------------------------------------- */
+    /*      If we don't already have an FID, check if there is a special    */
+    /*      FID named column available.                                     */
+    /* -------------------------------------------------------------------- */
+    if( pszFIDColumn == NULL )
+    {
+        const char *pszOGR_FID = CPLGetConfigOption("DB2SPATIAL_OGR_FID",
+                                 "OBJECTID");
+        for( int iCol = 0; iCol < nRawColumns; iCol++ )
+        {
+            if( EQUAL(poStmt->GetColName(iCol),pszOGR_FID) )
+            {
+                pszFIDColumn = CPLStrdup(pszOGR_FID);
+                break;
+            }
+        }
+    }
+
+    if( pszFIDColumn != NULL )
+        CPLDebug( "OGR_DB2Layer::BuildFeatureDefn",
+                  "Using column %s as FID for table %s.",
+                  pszFIDColumn, poFeatureDefn->GetName() );
+    else
+        CPLDebug( "OGR_DB2Layer::BuildFeatureDefn",
+                  "Table %s has no identified FID column.",
+                  poFeatureDefn->GetName() );
+
+    for( int iCol = 0; iCol < nRawColumns; iCol++ )
+    {
+        if ( pszGeomColumn == NULL )
+        {
+            /* need to identify the geometry column */
+            if ( EQUAL(poStmt->GetColTypeName( iCol ),
+                       "VARCHAR () FOR BIT DATA") )
+            {
+                pszGeomColumn = CPLStrdup( poStmt->GetColName(iCol) );
+                continue;
+            }
+        }
+        else
+        {
+            if( EQUAL(poStmt->GetColName(iCol),pszGeomColumn) ) {
+                continue;
+            }
+        }
+        if( pszFIDColumn != NULL &&
+                EQUAL(poStmt->GetColName(iCol), pszFIDColumn) )
+        {
+            /* skip FID */
+            continue;
+        }
+        // default field type is string
+        OGRFieldDefn    oField( poStmt->GetColName(iCol), OFTString );
+        oField.SetWidth( MAX(0,poStmt->GetColSize( iCol )) );
+
+        int colType = poStmt->GetColType(iCol);
+        switch( colType )
+        {
+        case SQL_C_SSHORT:
+        case SQL_C_USHORT:
+        case SQL_C_SLONG:
+        case SQL_C_ULONG:
+            oField.SetType( OFTInteger );
+            break;
+
+        case SQL_C_SBIGINT:
+        case SQL_C_UBIGINT:
+            oField.SetType( OFTInteger64 );
+            break;
+
+        case SQL_C_BINARY:
+            oField.SetType( OFTBinary );
+            break;
+
+        case SQL_C_NUMERIC:
+            oField.SetType( OFTReal );
+            oField.SetPrecision( poStmt->GetColPrecision(iCol) );
+            break;
+
+        case SQL_C_FLOAT:
+        case SQL_C_DOUBLE:
+            oField.SetType( OFTReal );
+            oField.SetWidth( 0 );
+            break;
+
+        case SQL_C_DATE:
+            oField.SetType( OFTDate );
+            break;
+
+        case SQL_C_TIME:
+            oField.SetType( OFTTime );
+            break;
+
+        case SQL_C_TIMESTAMP:
+            oField.SetType( OFTDateTime );
+            break;
+
+        default:
+            /* leave it as OFTString */
+            ;
+        }
+
+        poFeatureDefn->AddFieldDefn( &oField );
+        panFieldOrdinals[poFeatureDefn->GetFieldCount() - 1] = iCol;
+    }
+
+    return CE_None;
+}
+
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRDB2Layer::ResetReading()
+
+{
+    iNextShapeId = 0;
+    CPLDebug("OGR_DB2Layer::ResetReading","Reset");
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature *OGRDB2Layer::GetNextFeature()
+
+{
+    while( TRUE )
+    {
+        OGRFeature      *poFeature;
+
+        poFeature = GetNextRawFeature();
+        if( poFeature == NULL )
+            return NULL;
+        if( (m_poFilterGeom == NULL
+                || FilterGeometry( poFeature->GetGeometryRef() ) )
+                && (m_poAttrQuery == NULL
+                    || m_poAttrQuery->Evaluate( poFeature )) ) {
+            return poFeature;
+        }
+
+        delete poFeature;
+    }
+}
+
+/************************************************************************/
+/*                         GetNextRawFeature()                          */
+/************************************************************************/
+
+OGRFeature *OGRDB2Layer::GetNextRawFeature()
+
+{
+
+    if( GetStatement() == NULL )
+        return NULL;
+
+    /* -------------------------------------------------------------------- */
+    /*      If we are marked to restart then do so, and fetch a record.     */
+    /* -------------------------------------------------------------------- */
+    if( !m_poStmt->Fetch() )  // fail is normal for final fetch
+    {
+//      CPLDebug("OGR_DB2Layer::GetNextRawFeature","Fetch failed");
+        delete m_poStmt;
+        m_poStmt = NULL;
+        return NULL;
+    }
+//      CPLDebug("OGR_DB2Layer::GetNextRawFeature","Create feature");
+    /* -------------------------------------------------------------------- */
+    /*      Create a feature from the current result.                       */
+    /* -------------------------------------------------------------------- */
+    int         iField;
+    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
+    if( pszFIDColumn != NULL && m_poStmt->GetColId(pszFIDColumn) > -1 )
+        poFeature->SetFID(
+            atoi(m_poStmt->GetColData(m_poStmt->GetColId(pszFIDColumn))) );
+    else
+        poFeature->SetFID( iNextShapeId );
+
+    iNextShapeId++;
+    m_nFeaturesRead++;
+
+    /* -------------------------------------------------------------------- */
+    /*      Set the fields.                                                 */
+    /* -------------------------------------------------------------------- */
+
+    for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
+    {
+        if ( poFeatureDefn->GetFieldDefn(iField)->IsIgnored() )
+            continue;
+
+        int iSrcField = panFieldOrdinals[iField];
+        const char *pszValue = m_poStmt->GetColData( iSrcField );
+
+        if( pszValue == NULL )
+            /* no value */;
+        else if( poFeature->GetFieldDefnRef(iField)->GetType() == OFTBinary )
+            poFeature->SetField( iField,
+                                 m_poStmt->GetColDataLength(iSrcField),
+                                 (GByte *) pszValue );
+        else
+            poFeature->SetField( iField, pszValue );
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Try to extract a geometry.                                      */
+    /* -------------------------------------------------------------------- */
+
+    if( pszGeomColumn != NULL && !poFeatureDefn->IsGeometryIgnored())
+    {
+        iField = m_poStmt->GetColId( pszGeomColumn );
+        const char *pszGeomText = m_poStmt->GetColData( iField );
+        OGRGeometry *poGeom = NULL;
+        OGRErr eErr = OGRERR_NONE;
+        if( pszGeomText != NULL )
+        {
+            eErr = OGRGeometryFactory::createFromWkt((char **) &pszGeomText,
+                    NULL, &poGeom);
+        }
+
+        if ( eErr != OGRERR_NONE )
+        {
+            const char *pszMessage;
+
+            switch ( eErr )
+            {
+            case OGRERR_NOT_ENOUGH_DATA:
+                pszMessage = "Not enough data to deserialize";
+                break;
+            case OGRERR_UNSUPPORTED_GEOMETRY_TYPE:
+                pszMessage = "Unsupported geometry type";
+                break;
+            case OGRERR_CORRUPT_DATA:
+                pszMessage = "Corrupt data";
+                break;
+            default:
+                pszMessage = "Unrecognized error";
+            }
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "GetNextRawFeature(): %s", pszMessage);
+        }
+
+        if( poGeom != NULL )
+        {
+            if ( GetSpatialRef() )
+                poGeom->assignSpatialReference( poSRS );
+
+            poFeature->SetGeometryDirectly( poGeom );
+        }
+    }
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                             GetFeature()                             */
+/************************************************************************/
+
+OGRFeature *OGRDB2Layer::GetFeature( GIntBig nFeatureId )
+
+{
+    /* This should be implemented directly! */
+
+    return OGRLayer::GetFeature( nFeatureId );
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRDB2Layer::TestCapability( CPL_UNUSED const char * pszCap )
+{
+    return FALSE;
+}
+
+/************************************************************************/
+/*                          StartTransaction()                          */
+/************************************************************************/
+
+OGRErr OGRDB2Layer::StartTransaction()
+
+{
+    poDS->GetSession()->BeginTransaction();
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                         CommitTransaction()                          */
+/************************************************************************/
+
+OGRErr OGRDB2Layer::CommitTransaction()
+
+{
+    poDS->GetSession()->CommitTransaction();
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                        RollbackTransaction()                         */
+/************************************************************************/
+
+OGRErr OGRDB2Layer::RollbackTransaction()
+
+{
+    poDS->GetSession()->RollbackTransaction();
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           GetSpatialRef()                            */
+/************************************************************************/
+
+OGRSpatialReference *OGRDB2Layer::GetSpatialRef()
+
+{
+//CPLDebug("OGR_DB2Layer::GetSpatialRef", "nSrsId: %d", nSRSId);
+    if( poSRS == NULL && nSRSId > 0 )
+    {
+        poSRS = poDS->FetchSRS( nSRSId );
+        if( poSRS != NULL )
+            poSRS->Reference();
+        else
+            nSRSId = 0;
+    }
+
+    return poSRS;
+}
+
+/************************************************************************/
+/*                            GetFIDColumn()                            */
+/************************************************************************/
+
+const char *OGRDB2Layer::GetFIDColumn()
+
+{
+    GetLayerDefn();
+
+    if( pszFIDColumn != NULL )
+        return pszFIDColumn;
+    else
+        return "";
+}
+
+/************************************************************************/
+/*                         GetGeometryColumn()                          */
+/************************************************************************/
+
+const char *OGRDB2Layer::GetGeometryColumn()
+
+{
+    GetLayerDefn();
+
+    if( pszGeomColumn != NULL )
+        return pszGeomColumn;
+    else
+        return "";
+}
+
+/************************************************************************/
+/*                        GByteArrayToHexString()                       */
+/************************************************************************/
+
+char* OGRDB2Layer::GByteArrayToHexString( const GByte* pabyData, int nLen)
+{
+    char* pszTextBuf;
+
+    pszTextBuf = (char *) CPLMalloc(nLen*2+3);
+
+    int  iSrc, iDst=0;
+
+    for( iSrc = 0; iSrc < nLen; iSrc++ )
+    {
+        if( iSrc == 0 )
+        {
+            sprintf( pszTextBuf+iDst, "0x%02x", pabyData[iSrc] );
+            iDst += 4;
+        }
+        else
+        {
+            sprintf( pszTextBuf+iDst, "%02x", pabyData[iSrc] );
+            iDst += 2;
+        }
+    }
+    pszTextBuf[iDst] = 0;
+
+    return pszTextBuf;
+}
diff --git a/ogr/ogrsf_frmts/db2/ogrdb2selectlayer.cpp b/ogr/ogrsf_frmts/db2/ogrdb2selectlayer.cpp
new file mode 100644
index 0000000..594a0b0
--- /dev/null
+++ b/ogr/ogrsf_frmts/db2/ogrdb2selectlayer.cpp
@@ -0,0 +1,239 @@
+/*****************************************************************************
+ *
+ * Project:  DB2 Spatial driver
+ * Purpose:  Implements OGRDB2SelectLayer class, layer access to the results
+ *           of a SELECT statement executed via ExecuteSQL().
+ * Author:   David Adler, dadler at adtechgeospatial dot com
+ *
+ *****************************************************************************
+ * Copyright (c) 2010, Tamas Szekeres
+ * Copyright (c) 2015, David Adler
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_conv.h"
+#include "ogr_db2.h"
+
+/************************************************************************/
+/*                     OGRDB2SelectLayer()                     */
+/************************************************************************/
+
+OGRDB2SelectLayer::OGRDB2SelectLayer( OGRDB2DataSource *poDSIn,
+                                      OGRDB2Statement * poStmtIn )
+
+{
+
+    SQLCHAR     szTableName[256];
+    SQLCHAR     szSchemaName[256];
+    SQLSMALLINT nNameLength = 0;
+    OGRDB2Layer *poBaseLayer = NULL;
+    poDS = poDSIn;
+
+    iNextShapeId = 0;
+    nSRSId = -1;
+    poFeatureDefn = NULL;
+
+    m_poStmt = poStmtIn;
+    pszBaseStatement = CPLStrdup( poStmtIn->GetCommand() );
+    CPLDebug("OGR_DB2SelectLayer::OGRDB2SelectLayer", "SQL: '%s'",
+             pszBaseStatement);
+
+    pszGeomColumn = NULL;
+
+    /* get schema and table names for first column, column 1 */
+    SQLColAttribute(m_poStmt->GetStatement(), (SQLSMALLINT)(1),
+                    SQL_DESC_SCHEMA_NAME,
+                    szSchemaName, sizeof(szSchemaName),
+                    &nNameLength, NULL);
+    /* The schema name is sometimes right padded with blanks */
+    /* Replace blanks with nulls to terminate string for sprintf below */
+    for (int i = 0; i < nNameLength; i++) {
+        if (szSchemaName[i] == ' ') szSchemaName[i] = 0;
+    };
+    SQLColAttribute(m_poStmt->GetStatement(), (SQLSMALLINT)(1),
+                    SQL_DESC_TABLE_NAME,
+                    szTableName, sizeof(szTableName),
+                    &nNameLength, NULL);
+    CPLDebug("OGR_DB2SelectLayer::OGRDB2SelectLayer",
+             "szSchemaName: '%s'; szTableName: '%s'",
+             szSchemaName, szTableName);
+    if (nNameLength > 0)
+    {
+        char szLayerName[512];
+        sprintf(szLayerName, "%s.%s",szSchemaName, szTableName);
+        poBaseLayer = (OGRDB2Layer *) poDS->GetLayerByName((const char*)
+                      szLayerName);
+        if (poBaseLayer != NULL)
+            CPLDebug("OGR_DB2SelectLayer::OGRDB2SelectLayer",
+                     "base geom col: '%s'", poBaseLayer->GetGeometryColumn());
+        else CPLDebug("OGR_DB2SelectLayer::OGRDB2SelectLayer",
+                          "base layer not found");
+    }
+
+    /* identify the geometry column */
+    for ( int iColumn = 0; iColumn < m_poStmt->GetColCount(); iColumn++ )
+    {
+        if ( EQUAL(m_poStmt->GetColTypeName( iColumn ), "CLOB") ||
+                EQUAL(m_poStmt->GetColTypeName( iColumn ),
+                      "VARCHAR () FOR BIT DATA"))
+        {
+            if (poBaseLayer != NULL
+                    && EQUAL(poBaseLayer->GetGeometryColumn(),
+                             m_poStmt->GetColName(iColumn)))
+            {
+                pszGeomColumn = CPLStrdup(m_poStmt->GetColName(iColumn));
+                /* copy spatial reference */
+                if (!poSRS && poBaseLayer->GetSpatialRef())
+                    poSRS = poBaseLayer->GetSpatialRef()->Clone();
+                nSRSId = poBaseLayer->GetSRSId();
+                break;
+            }
+        }
+    }
+
+    BuildFeatureDefn( "SELECT", m_poStmt );
+
+    if ( GetSpatialRef() && poFeatureDefn->GetGeomFieldCount() == 1)
+        poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef( poSRS );
+}
+
+/************************************************************************/
+/*                    ~OGRDB2SelectLayer()                     */
+/************************************************************************/
+
+OGRDB2SelectLayer::~OGRDB2SelectLayer()
+
+{
+    ClearStatement();
+    CPLFree(pszBaseStatement);
+}
+
+/************************************************************************/
+/*                           ClearStatement()                           */
+/************************************************************************/
+
+void OGRDB2SelectLayer::ClearStatement()
+
+{
+    if( m_poStmt != NULL )
+    {
+        delete m_poStmt;
+        m_poStmt = NULL;
+    }
+}
+
+/************************************************************************/
+/*                            GetStatement()                            */
+/************************************************************************/
+
+OGRDB2Statement *OGRDB2SelectLayer::GetStatement()
+
+{
+    if( m_poStmt == NULL )
+        ResetStatement();
+
+    return m_poStmt;
+}
+
+/************************************************************************/
+/*                           ResetStatement()                           */
+/************************************************************************/
+
+OGRErr OGRDB2SelectLayer::ResetStatement()
+
+{
+    ClearStatement();
+
+    iNextShapeId = 0;
+
+    CPLDebug( "OGR_DB2SelectLayer::ResetStatement", "Recreating statement." );
+    m_poStmt = new OGRDB2Statement( poDS->GetSession() );
+    m_poStmt->Append( pszBaseStatement );
+
+    if( m_poStmt->ExecuteSQL() )
+        return OGRERR_NONE;
+    else
+    {
+        delete m_poStmt;
+        m_poStmt = NULL;
+        return OGRERR_FAILURE;
+    }
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRDB2SelectLayer::ResetReading()
+
+{
+    if( iNextShapeId != 0 )
+        ClearStatement();
+
+    OGRDB2Layer::ResetReading();
+}
+
+/************************************************************************/
+/*                             GetFeature()                             */
+/************************************************************************/
+
+OGRFeature *OGRDB2SelectLayer::GetFeature( GIntBig nFeatureId )
+
+{
+    return OGRDB2Layer::GetFeature( nFeatureId );
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRDB2SelectLayer::TestCapability( const char * pszCap )
+
+{
+    return OGRDB2Layer::TestCapability( pszCap );
+}
+
+/************************************************************************/
+/*                             GetExtent()                              */
+/*                                                                      */
+/*      Since SELECT layers currently cannot ever have geometry, we     */
+/*      can optimize the GetExtent() method!                            */
+/************************************************************************/
+
+OGRErr OGRDB2SelectLayer::GetExtent(OGREnvelope *, int )
+
+{
+    return OGRERR_FAILURE;
+}
+
+/************************************************************************/
+/*                          GetFeatureCount()                           */
+/*                                                                      */
+/*      If a spatial filter is in effect, we turn control over to       */
+/*      the generic counter.  Otherwise we return the total count.      */
+/*      Eventually we should consider implementing a more efficient     */
+/*      way of counting features matching a spatial query.              */
+/************************************************************************/
+
+GIntBig OGRDB2SelectLayer::GetFeatureCount( int bForce )
+
+{
+    return OGRDB2Layer::GetFeatureCount( bForce );
+}
diff --git a/ogr/ogrsf_frmts/db2/ogrdb2tablelayer.cpp b/ogr/ogrsf_frmts/db2/ogrdb2tablelayer.cpp
new file mode 100644
index 0000000..d1241c4
--- /dev/null
+++ b/ogr/ogrsf_frmts/db2/ogrdb2tablelayer.cpp
@@ -0,0 +1,1524 @@
+/*****************************************************************************
+ *
+ * Project:  DB2 Spatial driver
+ * Purpose:  Implements OGRDB2TableLayer class, access to an existing table.
+ * Author:   David Adler, dadler at adtechgeospatial dot com
+ *
+ *****************************************************************************
+ * Copyright (c) 2010, Tamas Szekeres
+ * Copyright (c) 2015, David Adler
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_conv.h"
+#include "ogr_db2.h"
+
+/************************************************************************/
+/*                         OGRDB2AppendEscaped( )                     */
+/************************************************************************/
+
+void OGRDB2AppendEscaped( OGRDB2Statement* poStatement,
+                          const char* pszStrValue)
+{
+    if (!pszStrValue)
+        poStatement->Append("null");
+
+    size_t  iIn, iOut , nTextLen = strlen(pszStrValue);
+    char    *pszEscapedText = (char *) VSIMalloc(nTextLen*2 + 3);
+
+    pszEscapedText[0] = '\'';
+
+    for( iIn = 0, iOut = 1; iIn < nTextLen; iIn++ )
+    {
+        switch( pszStrValue[iIn] )
+        {
+        case '\'':
+            pszEscapedText[iOut++] = '\''; // double quote
+            pszEscapedText[iOut++] = pszStrValue[iIn];
+            break;
+
+        default:
+            pszEscapedText[iOut++] = pszStrValue[iIn];
+            break;
+        }
+    }
+
+    pszEscapedText[iOut++] = '\'';
+
+    pszEscapedText[iOut] = '\0';
+
+    poStatement->Append(pszEscapedText);
+
+    CPLFree( pszEscapedText );
+}
+
+/************************************************************************/
+/*                          OGRDB2TableLayer()                 */
+/************************************************************************/
+
+OGRDB2TableLayer::OGRDB2TableLayer( OGRDB2DataSource *poDSIn )
+
+{
+    poDS = poDSIn;
+    m_poStmt = NULL;
+    m_poPrepStmt = NULL;
+    m_pszQuery = NULL;
+    m_nFeaturesRead = 0;
+
+    bUpdateAccess = TRUE;
+
+    iNextShapeId = 0;
+
+    nSRSId = -1;
+
+    poFeatureDefn = NULL;
+
+    pszTableName = NULL;
+    m_pszLayerName = NULL;
+    pszSchemaName = NULL;
+    pszFIDColumn = NULL;
+    eGeomType = wkbNone;
+}
+
+/************************************************************************/
+/*                          ~OGRDB2TableLayer()                */
+/************************************************************************/
+
+OGRDB2TableLayer::~OGRDB2TableLayer()
+
+{
+    CPLDebug("OGRDB2TableLayer::~OGRDB2TableLayer","entering");
+    CPLFree( pszTableName );
+    CPLFree( m_pszLayerName );
+    CPLFree( pszSchemaName );
+
+    CPLFree( m_pszQuery );
+    ClearStatement();
+    if( m_poPrepStmt != NULL )
+    {
+        delete m_poPrepStmt;
+        m_poPrepStmt = NULL;
+    }
+    CPLDebug("OGRDB2TableLayer::~OGRDB2TableLayer","exiting");
+}
+
+/************************************************************************/
+/*                               GetName()                              */
+/************************************************************************/
+
+const char *OGRDB2TableLayer::GetName()
+
+{
+    return m_pszLayerName;
+}
+
+/************************************************************************/
+/*                             GetLayerDefn()                           */
+/************************************************************************/
+OGRFeatureDefn* OGRDB2TableLayer::GetLayerDefn()
+{
+    if (poFeatureDefn)
+        return poFeatureDefn;
+
+    OGRDB2Session *poSession = poDS->GetSession();
+    /* -------------------------------------------------------------------- */
+    /*      Do we have a simple primary key?                                */
+    /* -------------------------------------------------------------------- */
+    OGRDB2Statement oGetKey( poSession );
+    CPLDebug( "OGR_DB2TableLayer::GetLayerDefn",
+              "pszTableName: %s; pszSchemaName: %s",
+              pszTableName, pszSchemaName);
+    if( oGetKey.GetPrimaryKeys( pszTableName, NULL, pszSchemaName ) ) {
+        if( oGetKey.Fetch() )
+        {
+            pszFIDColumn = CPLStrdup(oGetKey.GetColData( 3 ));
+            if( oGetKey.Fetch() ) // more than one field in key!
+            {
+                oGetKey.Clear();
+                CPLFree( pszFIDColumn );
+                pszFIDColumn = NULL;
+                CPLDebug( "OGR_DB2TableLayer::GetLayerDefn",
+                          "Table %s has multiple primary key fields, "
+                          "ignoring them all.", pszTableName );
+            } else {
+                // Attempt to get the 'identity' and 'generated' information
+                // from syscat.columns. This is only valid on DB2 LUW so if it
+                // fails, we assume that we are running on z/OS.
+                OGRDB2Statement oStatement = OGRDB2Statement(
+                                                 poDS->GetSession());
+                oStatement.Appendf( "select identity, generated "
+                                    "from syscat.columns "
+                                    "where tabschema = '%s' "
+                                    "and tabname = '%s' and colname = '%s'",
+                                    pszSchemaName, pszTableName,
+                                    pszFIDColumn );
+
+                if( oStatement.DB2Execute("OGR_DB2TableLayer::GetLayerDefn") )
+                {
+                    if( oStatement.Fetch() )
+                    {
+                        if ( oStatement.GetColData( 0 )
+                                && EQUAL(oStatement.GetColData( 0 ), "Y")) {
+                            bIsIdentityFid = TRUE;
+                            if ( oStatement.GetColData( 1 ) ) {
+                                cGenerated = oStatement.GetColData( 1 )[0];
+                            }
+                        }
+                    }
+                } else {
+                    CPLDebug( "OGR_DB2TableLayer::GetLayerDefn",
+                              "Must be z/OS");
+                    // on z/OS, get all the column data for table and loop
+                    // through looking for the FID column, then check the
+                    // column default information for 'IDENTIY' and 'ALWAYS'
+                    if (oGetKey.GetColumns(pszTableName, NULL, pszSchemaName))
+                    {
+                        CPLDebug( "OGR_DB2TableLayer::GetLayerDefn",
+                                  "GetColumns succeeded");
+                        CPLDebug( "OGR_DB2TableLayer::GetLayerDefn",
+                                  "ColName[0]: '%s'",oGetKey.GetColName(0));
+                        for (int idx = 0; idx < oGetKey.GetColCount(); idx++)
+                        {
+                            CPLDebug( "OGR_DB2TableLayer::GetLayerDefn",
+                                      "ColName[0]: '%s'",
+                                      oGetKey.GetColName(idx));
+                            if (!strcmp(pszFIDColumn,oGetKey.GetColName(idx)))
+                            {
+                                CPLDebug( "OGR_DB2TableLayer::GetLayerDefn",
+                                          "ColDef[0]: '%s'",
+                                          oGetKey.GetColColumnDef(idx));
+                                if (strstr(oGetKey.GetColColumnDef(idx),
+                                           "IDENTITY"))
+                                    bIsIdentityFid = TRUE;
+                                if (strstr(oGetKey.GetColColumnDef(idx),
+                                           "ALWAYS"))
+                                    cGenerated = 'A';
+                            }
+                        }
+                    }
+                }
+                CPLDebug( "OGR_DB2TableLayer::GetLayerDefn",
+                          "FIDColumn: '%s', identity: '%d', generated: '%c'",
+                          pszFIDColumn, bIsIdentityFid, cGenerated);
+            }
+        }
+    } else
+        CPLDebug( "OGR_DB2TableLayer::GetLayerDefn", "GetPrimaryKeys failed");
+
+    /* -------------------------------------------------------------------- */
+    /*      Get the column definitions for this table.                      */
+    /* -------------------------------------------------------------------- */
+    OGRDB2Statement oGetCol( poSession );
+    CPLErr eErr;
+
+    if( !oGetCol.GetColumns( pszTableName, "", pszSchemaName ) )
+        return NULL;
+
+    eErr = BuildFeatureDefn( m_pszLayerName, &oGetCol );
+    if( eErr != CE_None )
+        return NULL;
+
+    if (eGeomType != wkbNone)
+        poFeatureDefn->SetGeomType(eGeomType);
+
+    if ( GetSpatialRef() && poFeatureDefn->GetGeomFieldCount() == 1)
+        poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef( poSRS );
+
+    if( poFeatureDefn->GetFieldCount() == 0 &&
+            pszFIDColumn == NULL && pszGeomColumn == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "No column definitions found for table '%s', "
+                  "layer not usable.",
+                  m_pszLayerName );
+        return NULL;
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      If we got a geometry column, does it exist?  Is it binary?      */
+    /* -------------------------------------------------------------------- */
+
+    if( pszGeomColumn != NULL )
+    {
+        poFeatureDefn->GetGeomFieldDefn(0)->SetName( pszGeomColumn );
+        int iColumn = oGetCol.GetColId( pszGeomColumn );
+        if( iColumn < 0 )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Column %s requested for geometry, "
+                      "but it does not exist.",
+                      pszGeomColumn );
+            CPLFree( pszGeomColumn );
+            pszGeomColumn = NULL;
+        }
+    }
+
+    return poFeatureDefn;
+}
+
+/************************************************************************/
+/*                             Initialize()                             */
+/************************************************************************/
+
+CPLErr OGRDB2TableLayer::Initialize( const char *pszSchema,
+                                     const char *pszLayerName,
+                                     const char *pszGeomCol,
+                                     CPL_UNUSED int nCoordDimension,
+                                     int nSRId,
+                                     const char *pszSRText,
+                                     OGRwkbGeometryType eType )
+{
+//    CPLFree( pszFIDColumn );
+    pszFIDColumn = NULL;
+
+    CPLDebug( "OGR_DB2TableLayer::Initialize",
+              "schema: '%s', layerName: '%s', geomCol: '%s'",
+              pszSchema, pszLayerName, pszGeomCol);
+    CPLDebug( "OGR_DB2TableLayer::Initialize",
+              "nSRId: '%d', eType: '%d', srText: '%s'",
+              nSRId, eType, pszSRText);
+
+
+    /* -------------------------------------------------------------------- */
+    /*      Parse out schema name if present in layer.  We assume a         */
+    /*      schema is provided if there is a dot in the name, and that      */
+    /*      it is in the form <schema>.<tablename>                          */
+    /* -------------------------------------------------------------------- */
+    const char *pszDot = strstr(pszLayerName,".");
+    if( pszDot != NULL )
+    {
+        pszTableName = CPLStrdup(pszDot + 1);
+        pszSchemaName = CPLStrdup(pszLayerName);
+        pszSchemaName[pszDot - pszLayerName] = '\0';
+        this->m_pszLayerName = CPLStrdup(pszLayerName);
+    }
+    else
+    {
+        pszTableName = CPLStrdup(pszLayerName);
+        pszSchemaName = CPLStrdup(pszSchema);
+        this->m_pszLayerName = CPLStrdup(CPLSPrintf("%s.%s", pszSchemaName,
+                                         pszTableName));
+    }
+    SetDescription( this->m_pszLayerName );
+    CPLDebug( "OGR_DB2TableLayer::Initialize",
+              "this->m_pszLayerName: '%s', layerName: '%s', geomCol: '%s'",
+              this->m_pszLayerName, pszLayerName, pszGeomCol);
+    /* -------------------------------------------------------------------- */
+    /*      Have we been provided a geometry column?                        */
+    /* -------------------------------------------------------------------- */
+//    CPLFree( pszGeomColumn ); LATER
+    if( pszGeomCol == NULL )
+        GetLayerDefn(); /* fetch geom column if not specified */
+    else
+        pszGeomColumn = CPLStrdup( pszGeomCol );
+
+    if (eType != wkbNone)
+        eGeomType = eType;
+
+    /* -------------------------------------------------------------------- */
+    /*             Try to find out the spatial reference                    */
+    /* -------------------------------------------------------------------- */
+
+    nSRSId = nSRId;
+
+    if (pszSRText)
+    {
+        /* Process srtext directly if specified */
+        poSRS = new OGRSpatialReference();
+        if( poSRS->importFromWkt( (char**)&pszSRText ) != OGRERR_NONE )
+        {
+            delete poSRS;
+            poSRS = NULL;
+        }
+    }
+
+    if (!poSRS)
+    {
+        if (nSRSId < 0)
+            nSRSId = FetchSRSId();
+
+        GetSpatialRef();
+    }
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                         FetchSRSId()                                 */
+/************************************************************************/
+
+int OGRDB2TableLayer::FetchSRSId()
+{
+    OGRDB2Statement oStatement = OGRDB2Statement( poDS->GetSession() );
+
+// first try to get the srid from st_geometry_columns
+// if the spatial column was registered
+    oStatement.Appendf( "select srs_id from db2gse.st_geometry_columns "
+                        "where table_schema = '%s' and table_name = '%s'",
+                        pszSchemaName, pszTableName );
+
+    if( oStatement.DB2Execute("OGRDB2TableLayer::FetchSRSId")
+            && oStatement.Fetch() )
+    {
+        if ( oStatement.GetColData( 0 ) )
+            nSRSId = atoi( oStatement.GetColData( 0 ) );
+    }
+
+// If it was not found there, try to get it from the data table.
+// This only works if there is spatial data in the first row.
+    if (nSRSId < 0 )
+    {
+        oStatement.Clear();
+        oStatement.Appendf("select db2gse.st_srid(%s) from %s.%s "
+                           "fetch first row only",
+                           pszGeomColumn, pszSchemaName, pszTableName);
+        if ( oStatement.DB2Execute("OGR_DB2TableLayer::FetchSRSId")
+                && oStatement.Fetch() )
+        {
+            if ( oStatement.GetColData( 0 ) )
+                nSRSId = atoi( oStatement.GetColData( 0 ) );
+        }
+    }
+    CPLDebug( "OGR_DB2TableLayer::FetchSRSId", "nSRSId: '%d'",
+              nSRSId);
+    return nSRSId;
+}
+
+/************************************************************************/
+/*                       CreateSpatialIndex()                           */
+/*                                                                      */
+/*      Create a spatial index on the geometry column of the layer      */
+/************************************************************************/
+
+OGRErr OGRDB2TableLayer::CreateSpatialIndex()
+{
+    CPLDebug("OGRDB2TableLayer::CreateSpatialIndex","Enter");
+    if (poDS->m_bIsZ) {
+        CPLDebug("OGRDB2TableLayer::CreateSpatialIndex",
+                 "Don't create spatial index on z/OS");
+        return OGRERR_NONE;
+    }
+    GetLayerDefn();
+
+    OGRDB2Statement oStatement( poDS->GetSession() );
+
+
+    OGREnvelope oExt;
+    if (GetExtent(&oExt, TRUE) != OGRERR_NONE)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Failed to get extent for spatial index." );
+        return OGRERR_FAILURE;
+    }
+    CPLDebug("OGRDB2TableLayer::CreateSpatialIndex",
+             "BOUNDING_BOX =(%.15g, %.15g, %.15g, %.15g)",
+             oExt.MinX, oExt.MinY, oExt.MaxX, oExt.MaxY );
+
+    oStatement.Appendf("CREATE  INDEX %s.%s_sidx ON %s.%s ( %s ) "
+                       "extend using db2gse.spatial_index(.1,0.5,0)",
+                       pszSchemaName, pszTableName,
+                       pszSchemaName, pszTableName, pszGeomColumn );
+
+    if( !oStatement.DB2Execute("OGR_DB2TableLayer::CreateSpatialIndex") )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Failed to create the spatial index, %s.",
+                  poDS->GetSession()->GetLastError());
+        return OGRERR_FAILURE;
+    }
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                       DropSpatialIndex()                             */
+/*                                                                      */
+/*      Drop the spatial index on the geometry column of the layer      */
+/************************************************************************/
+
+void OGRDB2TableLayer::DropSpatialIndex()
+{
+    GetLayerDefn();
+
+    OGRDB2Statement oStatement( poDS->GetSession() );
+
+    oStatement.Appendf("DROP INDEX %s.%s",
+                       pszSchemaName, pszTableName);
+
+    //poDS->GetSession()->BeginTransaction();
+
+    if( !oStatement.DB2Execute("OGR_DB2TableLayer::DropSpatialIndex") )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Failed to drop the spatial index, %s.",
+                  poDS->GetSession()->GetLastError());
+        return;
+    }
+
+    //poDS->GetSession()->CommitTransaction();
+}
+
+/************************************************************************/
+/*                            BuildFields()                             */
+/*                                                                      */
+/*      Build list of fields to fetch, performing any required          */
+/*      transformations (such as on geometry).                          */
+/************************************************************************/
+
+CPLString OGRDB2TableLayer::BuildFields()
+
+{
+    int i = 0;
+    int nColumn = 0;
+    CPLString osFieldList;
+
+    GetLayerDefn();
+
+    if( pszFIDColumn && poFeatureDefn->GetFieldIndex( pszFIDColumn ) == -1 )
+    {
+        /* Always get the FID column */
+        osFieldList += " ";
+        osFieldList += pszFIDColumn;
+        osFieldList += " ";
+        ++nColumn;
+    }
+
+    if( pszGeomColumn && !poFeatureDefn->IsGeometryIgnored())
+    {
+        if( nColumn > 0 )
+            osFieldList += ", ";
+
+        osFieldList += " db2gse.st_astext(";
+        osFieldList += pszGeomColumn;
+        osFieldList += ") as ";
+        osFieldList += pszGeomColumn;
+
+        osFieldList += " ";
+
+        ++nColumn;
+    }
+
+    if (poFeatureDefn->GetFieldCount() > 0)
+    {
+        /* need to reconstruct the field ordinals list */
+        CPLFree(panFieldOrdinals);
+        panFieldOrdinals = (int *) CPLMalloc( sizeof(int)
+                                    * poFeatureDefn->GetFieldCount() );
+
+        for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
+        {
+            if ( poFeatureDefn->GetFieldDefn(i)->IsIgnored() )
+                continue;
+
+            const char *pszName =poFeatureDefn->GetFieldDefn(i)->GetNameRef();
+
+            if( nColumn > 0 )
+                osFieldList += ", ";
+
+            osFieldList += " ";
+            osFieldList += pszName;
+            osFieldList += " ";
+
+            panFieldOrdinals[i] = nColumn;
+
+            ++nColumn;
+        }
+    }
+
+    return osFieldList;
+}
+
+/************************************************************************/
+/*                           ClearStatement()                           */
+/************************************************************************/
+
+void OGRDB2TableLayer::ClearStatement()
+
+{
+    if( m_poStmt != NULL )
+    {
+        delete m_poStmt;
+        m_poStmt = NULL;
+    }
+}
+
+/************************************************************************/
+/*                            GetStatement()                            */
+/************************************************************************/
+
+OGRDB2Statement *OGRDB2TableLayer::GetStatement()
+
+{
+    if( m_poStmt == NULL )
+    {
+        m_poStmt = BuildStatement(BuildFields());
+        iNextShapeId = 0;
+    }
+
+    return m_poStmt;
+}
+
+
+/************************************************************************/
+/*                           BuildStatement()                           */
+/************************************************************************/
+
+OGRDB2Statement* OGRDB2TableLayer::BuildStatement(const char* pszColumns)
+
+{
+    OGRDB2Statement* poStatement = new OGRDB2Statement( poDS->GetSession());
+    poStatement->Append( "select " );
+    poStatement->Append( pszColumns );
+    poStatement->Append( " from " );
+    poStatement->Append( pszSchemaName );
+    poStatement->Append( "." );
+    poStatement->Append( pszTableName );
+
+    /* Append attribute query if we have it */
+    if( m_pszQuery != NULL )
+        poStatement->Appendf( " where (%s)", m_pszQuery );
+
+    /* If we have a spatial filter, query on it */
+    if ( m_poFilterGeom != NULL )
+    {
+        if( m_pszQuery == NULL )
+            poStatement->Append( " where" );
+        else
+            poStatement->Append( " and" );
+
+        poStatement->Appendf(" db2gse.envelopesintersect(%s,%.15g,%.15g,"
+                             "%.15g,%.15g, 0) = 1",
+                             pszGeomColumn, m_sFilterEnvelope.MinX,
+                             m_sFilterEnvelope.MinY, m_sFilterEnvelope.MaxX,
+                             m_sFilterEnvelope.MaxY );
+    }
+
+    if( poStatement->DB2Execute("OGR_DB2TableLayer::BuildStatement") ) {
+        return poStatement;
+    }
+    else
+    {
+        delete poStatement;
+        CPLDebug( "OGR_DB2TableLayer::BuildStatement", "ExecuteSQL Failed" );
+        return NULL;
+    }
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRDB2TableLayer::ResetReading()
+
+{
+    ClearStatement();
+    OGRDB2Layer::ResetReading();
+}
+
+/************************************************************************/
+/*                             GetFeature()                             */
+/************************************************************************/
+
+OGRFeature *OGRDB2TableLayer::GetFeature( GIntBig nFeatureId )
+
+{
+
+    if( pszFIDColumn == NULL )
+        return OGRDB2Layer::GetFeature( nFeatureId );
+
+    ClearStatement();
+
+    iNextShapeId = nFeatureId;
+
+    m_poStmt = new OGRDB2Statement( poDS->GetSession() );
+    CPLString osFields = BuildFields();
+    m_poStmt->Appendf( "select %s from %s where %s = %ld", osFields.c_str(),
+                       poFeatureDefn->GetName(), pszFIDColumn, nFeatureId );
+
+    if( !m_poStmt->DB2Execute("OGR_DB2TableLayer::GetFeature") )
+    {
+        delete m_poStmt;
+        m_poStmt = NULL;
+        return NULL;
+    }
+
+    return GetNextRawFeature();
+}
+
+/************************************************************************/
+/*                         SetAttributeFilter()                         */
+/************************************************************************/
+
+OGRErr OGRDB2TableLayer::SetAttributeFilter( const char *pszQuery )
+
+{
+    CPLFree(m_pszAttrQueryString);
+    m_pszAttrQueryString = (pszQuery) ? CPLStrdup(pszQuery) : NULL;
+
+    if( (pszQuery == NULL && this->m_pszQuery == NULL)
+            || (pszQuery != NULL && this->m_pszQuery != NULL
+                && EQUAL(pszQuery,this->m_pszQuery)) )
+        return OGRERR_NONE;
+
+    CPLFree( this->m_pszQuery );
+    this->m_pszQuery = (pszQuery) ? CPLStrdup( pszQuery ) : NULL;
+
+    ClearStatement();
+
+    return OGRERR_NONE;
+}
+
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRDB2TableLayer::TestCapability( const char * pszCap )
+
+{
+    if ( bUpdateAccess )
+    {
+        if( EQUAL(pszCap,OLCSequentialWrite) || EQUAL(pszCap,OLCCreateField)
+                || EQUAL(pszCap,OLCDeleteFeature) )
+            return TRUE;
+
+        else if( EQUAL(pszCap,OLCRandomWrite) )
+            return (pszFIDColumn != NULL);
+    }
+
+    if( EQUAL(pszCap,OLCTransactions) )
+        return TRUE;
+
+    if( EQUAL(pszCap,OLCIgnoreFields) )
+        return TRUE;
+
+    if( EQUAL(pszCap,OLCRandomRead) )
+        return (pszFIDColumn != NULL);
+    else if( EQUAL(pszCap,OLCFastFeatureCount) )
+        return TRUE;
+    else
+        return OGRDB2Layer::TestCapability( pszCap );
+}
+
+/************************************************************************/
+/*                          GetFeatureCount()                           */
+/************************************************************************/
+
+GIntBig OGRDB2TableLayer::GetFeatureCount( int bForce )
+
+{
+    GetLayerDefn();
+
+    if( TestCapability(OLCFastFeatureCount) == FALSE )
+        return OGRDB2Layer::GetFeatureCount( bForce );
+
+    ClearStatement();
+
+    OGRDB2Statement* poStatement = BuildStatement( "count(*)" );
+
+    if (poStatement == NULL || !poStatement->Fetch())
+    {
+        delete poStatement;
+        return OGRDB2Layer::GetFeatureCount( bForce );
+    }
+
+    int nRet = atoi(poStatement->GetColData( 0 ));
+    delete poStatement;
+    return nRet;
+}
+
+
+/************************************************************************/
+/*                            CreateField()                             */
+/************************************************************************/
+
+OGRErr OGRDB2TableLayer::CreateField( OGRFieldDefn *poFieldIn,
+                                      int bApproxOK )
+
+{
+    char                szFieldType[256];
+    OGRFieldDefn        oField( poFieldIn );
+
+    GetLayerDefn();
+
+    /* -------------------------------------------------------------------- */
+    /*      Do we want to "launder" the column names into DB2               */
+    /*      friendly format?                                                */
+    /* -------------------------------------------------------------------- */
+    if( bLaunderColumnNames )
+    {
+        char    *pszSafeName = poDS->LaunderName( oField.GetNameRef() );
+
+        oField.SetName( pszSafeName );
+        CPLFree( pszSafeName );
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Identify the DB2 type.                                          */
+    /* -------------------------------------------------------------------- */
+
+    int fieldType = oField.GetType();
+    CPLDebug("OGR_DB2TableLayer::CreateField","fieldType: %d", fieldType);
+    if( oField.GetType() == OFTInteger )
+    {
+        if( oField.GetWidth() > 0 && bPreservePrecision )
+            sprintf( szFieldType, "numeric(%d,0)", oField.GetWidth() );
+        else
+            strcpy( szFieldType, "int" );
+    }
+    else if( oField.GetType() == OFTInteger64 )
+    {
+        if( oField.GetWidth() > 0 && bPreservePrecision )
+            sprintf( szFieldType, "numeric(%d,0)", oField.GetWidth() );
+        else
+            strcpy( szFieldType, "bigint" );
+    }
+    else if( oField.GetType() == OFTReal )
+    {
+        if( oField.GetWidth() > 0 && oField.GetPrecision() > 0
+                && bPreservePrecision )
+            sprintf( szFieldType, "numeric(%d,%d)",
+                     oField.GetWidth(), oField.GetPrecision() );
+        else
+            strcpy( szFieldType, "float" );
+    }
+    else if( oField.GetType() == OFTString )
+    {
+        if( oField.GetWidth() == 0 || !bPreservePrecision )
+            strcpy( szFieldType, "varchar(MAX)" );
+        else
+            sprintf( szFieldType, "varchar(%d)", oField.GetWidth() );
+    }
+    else if( oField.GetType() == OFTDate )
+    {
+        strcpy( szFieldType, "date" );
+    }
+    else if( oField.GetType() == OFTTime )
+    {
+        strcpy( szFieldType, "time(7)" );
+    }
+    else if( oField.GetType() == OFTDateTime )
+    {
+        strcpy( szFieldType, "datetime" );
+    }
+    else if( oField.GetType() == OFTBinary )
+    {
+        strcpy( szFieldType, "image" );
+    }
+    else if( bApproxOK )
+    {
+        CPLError( CE_Warning, CPLE_NotSupported,
+                  "Can't create field %s with type %s on DB2 layers.  "
+                  "Creating as varchar.",
+                  oField.GetNameRef(),
+                  OGRFieldDefn::GetFieldTypeName(oField.GetType()) );
+        strcpy( szFieldType, "varchar" );
+    }
+    else
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Can't create field %s with type %s on DB2 layers.",
+                  oField.GetNameRef(),
+                  OGRFieldDefn::GetFieldTypeName(oField.GetType()) );
+
+        return OGRERR_FAILURE;
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Create the new field.                                           */
+    /* -------------------------------------------------------------------- */
+
+    OGRDB2Statement oStmt( poDS->GetSession() );
+
+    oStmt.Appendf( "ALTER TABLE %s.%s ADD COLUMN %s %s",
+                   pszSchemaName, pszTableName, oField.GetNameRef(),
+                   szFieldType);
+
+    if( !oStmt.DB2Execute("OGR_DB2TableLayer::CreateField") )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Error creating field %s, %s", oField.GetNameRef(),
+                  poDS->GetSession()->GetLastError() );
+
+        return OGRERR_FAILURE;
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Add the field to the OGRFeatureDefn.                            */
+    /* -------------------------------------------------------------------- */
+
+    poFeatureDefn->AddFieldDefn( &oField );
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                            ISetFeature()                             */
+/*                                                                      */
+/*     ISetFeature() is implemented by an UPDATE SQL command            */
+/************************************************************************/
+
+OGRErr OGRDB2TableLayer::ISetFeature( OGRFeature *poFeature )
+
+{
+    OGRErr              eErr = OGRERR_FAILURE;
+
+    GetLayerDefn();
+
+    if( NULL == poFeature )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "NULL pointer to OGRFeature passed to SetFeature()." );
+        return eErr;
+    }
+
+    if( poFeature->GetFID() == OGRNullFID )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "FID required on features given to SetFeature()." );
+        return eErr;
+    }
+
+    if( !pszFIDColumn )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Unable to update features in tables without\n"
+                  "a recognised FID column.");
+        return eErr;
+
+    }
+
+    ClearStatement();
+
+    /* -------------------------------------------------------------------- */
+    /*      Form the UPDATE command.                                        */
+    /* -------------------------------------------------------------------- */
+    if (PrepareFeature(poFeature, 'U'))
+        return OGRERR_FAILURE;
+
+
+    int nFieldCount = poFeatureDefn->GetFieldCount();
+    int nBindNum = 0;
+    void** papBindBuffer = (void**)CPLMalloc(sizeof(void*) * nFieldCount);
+
+    /* Set the geometry */
+    OGRGeometry *poGeom = poFeature->GetGeometryRef();
+    char    *pszWKT = NULL;
+
+    if (poGeom != NULL && pszGeomColumn != NULL)
+    {
+        if( poGeom->exportToWkt( &pszWKT ) == OGRERR_NONE)
+        {
+            int nLen = (int) strlen(pszWKT);
+            if (m_poPrepStmt->DB2BindParameterIn(
+                        "OGRDB2TableLayer::UpdateFeature",
+                        (nBindNum + 1),
+                        SQL_C_CHAR,
+                        SQL_LONGVARCHAR,
+                        nLen,
+                        (void *)(pszWKT)))
+            {
+                papBindBuffer[nBindNum] = pszWKT;
+                nBindNum++;
+            } else {
+                CPLDebug("OGRDB2TableLayer::UpdateFeature",
+                         "Bind parameter failed");
+                FreeBindBuffer(nBindNum, papBindBuffer);
+                return OGRERR_FAILURE;
+            }
+        }
+    }
+
+    for( int i = 0; i < nFieldCount; i++ )
+    {
+//        int nOGRFieldType = poFeatureDefn->GetFieldDefn(i)->GetType();
+//        CPLDebug("OGRDB2TableLayer::UpdateFeature",
+//               "i: %d; nOGRFieldType: %d",
+//                i, nOGRFieldType);
+
+        if (BindFieldValue(m_poPrepStmt,
+                           poFeature, i,
+                           nBindNum, papBindBuffer) != OGRERR_NONE) {
+            CPLDebug("OGRDB2TableLayer::UpdateFeature",
+                     "Bind parameter failed");
+            FreeBindBuffer(nBindNum, papBindBuffer);
+            return OGRERR_FAILURE;
+        }
+        nBindNum++;
+    }
+
+
+    /* -------------------------------------------------------------------- */
+    /*      Execute the update.                                             */
+    /* -------------------------------------------------------------------- */
+    if( !m_poPrepStmt->DB2Execute("OGR_DB2TableLayer::UpdateFeature") )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Error updating feature with FID:" CPL_FRMT_GIB ", %s",
+                  poFeature->GetFID(),
+                  poDS->GetSession()->GetLastError() );
+
+        return OGRERR_FAILURE;
+    }
+
+    FreeBindBuffer(nBindNum, papBindBuffer);
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                          DeleteFeature()                             */
+/************************************************************************/
+
+OGRErr OGRDB2TableLayer::DeleteFeature( GIntBig nFID )
+
+{
+    CPLDebug("OGR_DB2TableLayer::DeleteFeature",
+             " entering, nFID: " CPL_FRMT_GIB,nFID);
+    GetLayerDefn();
+
+    if( pszFIDColumn == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "DeleteFeature() without any FID column." );
+        return OGRERR_FAILURE;
+    }
+
+    if( nFID == OGRNullFID )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "DeleteFeature() with unset FID fails." );
+        return OGRERR_FAILURE;
+    }
+
+    ClearStatement();
+
+    /* -------------------------------------------------------------------- */
+    /*      Drop the record with this FID.                                  */
+    /* -------------------------------------------------------------------- */
+    OGRDB2Statement oStatement( poDS->GetSession() );
+
+    oStatement.Appendf("DELETE FROM %s WHERE %s = " CPL_FRMT_GIB,
+                       poFeatureDefn->GetName(), pszFIDColumn, nFID);
+    if( !oStatement.DB2Execute("OGR_DB2TableLayer::DeleteFeature") )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Attempt to delete feature with FID " CPL_FRMT_GIB
+                  " failed. %s",
+                  nFID, poDS->GetSession()->GetLastError() );
+        return OGRERR_FAILURE;
+    }
+    return OGRERR_NONE;
+}
+
+
+
+
+
+
+/************************************************************************/
+/*                          isFieldTypeSupported()                      */
+/************************************************************************/
+
+OGRErr OGRDB2TableLayer::isFieldTypeSupported( OGRFieldType nFieldType )
+
+{
+    switch(nFieldType) {
+    case OFTInteger:
+    case OFTReal:
+    case OFTString:
+    case OFTDateTime:
+    case OFTInteger64:
+        return OGRERR_NONE;
+    default:
+        return OGRERR_FAILURE;
+    }
+}
+
+/************************************************************************/
+/*                          PrepareFeature()                            */
+/************************************************************************/
+
+OGRErr OGRDB2TableLayer::PrepareFeature( OGRFeature *poFeature, char cType )
+
+{
+// LATER - this defeats the point of prepared statements but need to find
+// some place to clean up to avoid reusing the wrong statement
+    if (m_poPrepStmt) delete m_poPrepStmt;
+    m_poPrepStmt =  new OGRDB2Statement( poDS->GetSession());
+
+    char    *pszWKT = NULL;
+    CPLString osValues= " VALUES(";
+    int nFieldCount = poFeatureDefn->GetFieldCount();
+
+    if (cType == 'I')
+        m_poPrepStmt->Appendf( "INSERT INTO %s.%s (",
+                               pszSchemaName, pszTableName );
+    else
+        m_poPrepStmt->Appendf( "UPDATE %s.%s SET ",
+                               pszSchemaName, pszTableName);
+    int bNeedComma = FALSE;
+    OGRGeometry *poGeom = poFeature->GetGeometryRef();
+
+    if (poGeom != NULL && pszGeomColumn != NULL)
+    {
+        if( poGeom->exportToWkt( &pszWKT ) == OGRERR_NONE)
+        {
+            int nLen = (int) strlen(pszWKT);
+            if (cType == 'I')
+            {
+                m_poPrepStmt->Append( pszGeomColumn );
+                CPLString geomValue;
+                geomValue.Printf( "DB2GSE.ST_%s(CAST( ? AS CLOB(2M)),%d)",
+                                  poGeom->getGeometryName(), nSRSId );
+                osValues.append(geomValue);
+            } else {
+                m_poPrepStmt->Appendf( "%s = "
+                                    "DB2GSE.ST_%s(CAST( ? AS CLOB(%d)),%d)",
+                                    pszGeomColumn, poGeom->getGeometryName(),
+                                    nLen, nSRSId );
+            }
+            bNeedComma = TRUE;
+        }
+    }
+
+// Explicitly add FID column and value if needed
+    if( cType == 'I' && poFeature->GetFID() != OGRNullFID
+            && pszFIDColumn != NULL && cGenerated != 'A' )
+    {
+        if (bNeedComma)
+        {
+            m_poPrepStmt->Appendf( ", ");
+            osValues.append(", ");
+        }
+        m_poPrepStmt->Appendf( "%s", pszFIDColumn );
+        osValues.append("?");
+        bNeedComma = TRUE;
+    }
+
+    for( int i = 0; i < nFieldCount; i++ )
+    {
+
+        if( !poFeature->IsFieldSet( i ) )
+            continue;
+
+        if (bNeedComma)
+        {
+            m_poPrepStmt->Appendf( ", ");
+            osValues.append(", ");
+        }
+        bNeedComma = TRUE;
+        if (cType == 'I') {
+            m_poPrepStmt->Appendf( "%s",
+                                poFeatureDefn->GetFieldDefn(i)->GetNameRef());
+            osValues.append("?");
+        } else {
+            m_poPrepStmt->Appendf( "%s = ?",
+                                poFeatureDefn->GetFieldDefn(i)->GetNameRef());
+        }
+    }
+    if (cType == 'I') {
+        m_poPrepStmt->Appendf( ") %s )", osValues.c_str() );
+    } else {
+        /* Add the WHERE clause */
+        m_poPrepStmt->Appendf( " WHERE (%s) = " CPL_FRMT_GIB, pszFIDColumn,
+                               poFeature->GetFID());
+    }
+    if (!m_poPrepStmt->DB2Prepare("OGR_DB2TableLayer::PrepareFeature"))
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "PREPARE command for feature failed. %s",
+                  poDS->GetSession()->GetLastError() );
+        return OGRERR_FAILURE;
+    }
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                          ICreateFeature()                            */
+/************************************************************************/
+
+OGRErr OGRDB2TableLayer::ICreateFeature( OGRFeature *poFeature )
+{
+    GetLayerDefn();
+
+    if( NULL == poFeature )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "NULL pointer to OGRFeature passed to CreateFeature()." );
+        return OGRERR_FAILURE;
+    }
+
+    if (PrepareFeature(poFeature, 'I'))
+        return OGRERR_FAILURE;
+
+    char    *pszWKT = NULL;
+    int nFieldCount = poFeatureDefn->GetFieldCount();
+    int nBindNum = 0;
+    void** papBindBuffer = (void**)CPLMalloc(sizeof(void*)
+                                                * (nFieldCount + 1));
+    OGRGeometry *poGeom = poFeature->GetGeometryRef();
+
+    if (poGeom != NULL && pszGeomColumn != NULL)
+    {
+        if( poGeom->exportToWkt( &pszWKT ) == OGRERR_NONE)
+        {
+            int nLen = (int) strlen(pszWKT);
+            if (m_poPrepStmt->DB2BindParameterIn(
+                        "OGRDB2TableLayer::ICreateFeature",
+                        (nBindNum + 1),
+                        SQL_C_CHAR,
+                        SQL_LONGVARCHAR,
+                        nLen,
+                        (void *)(pszWKT)))
+            {
+                papBindBuffer[nBindNum] = pszWKT;
+                nBindNum++;
+
+            } else {
+                CPLDebug("OGRDB2TableLayer::ICreateFeature",
+                         "Bind parameter failed");
+                FreeBindBuffer(nBindNum, papBindBuffer);
+                return OGRERR_FAILURE;
+            }
+        }
+    }
+
+// Explicitly add FID column and value if needed
+    if( poFeature->GetFID() != OGRNullFID
+            && pszFIDColumn != NULL && cGenerated != 'A' )
+    {
+        GIntBig nFID = poFeature->GetFID();
+        if (m_poPrepStmt->DB2BindParameterIn(
+                    "OGRDB2TableLayer::ICreateFeature",
+                    (nBindNum + 1),
+                    SQL_C_SBIGINT,
+                    SQL_BIGINT,
+                    sizeof(GIntBig),
+                    (void *)(&nFID)))
+        {
+            papBindBuffer[nBindNum] = NULL;
+            nBindNum++;
+
+        } else {
+            CPLDebug("OGRDB2TableLayer::ICreateFeature",
+                     "Bind parameter failed");
+            FreeBindBuffer(nBindNum, papBindBuffer);
+            return OGRERR_FAILURE;
+        }
+    }
+
+    for( int i = 0; i < nFieldCount; i++ )
+    {
+
+        if( !poFeature->IsFieldSet( i ) )
+            continue;
+
+//        int nOGRFieldType = poFeatureDefn->GetFieldDefn(i)->GetType();
+//        CPLDebug("OGRDB2TableLayer::ICreateFeature",
+//               "i: %d; nOGRFieldType: %d",
+//                i, nOGRFieldType);
+
+        if (BindFieldValue(m_poPrepStmt,
+                           poFeature, i,
+                           nBindNum, papBindBuffer) != OGRERR_NONE) {
+            CPLDebug("OGRDB2TableLayer::ICreateFeature",
+                     "Bind parameter failed");
+            FreeBindBuffer(nBindNum, papBindBuffer);
+            return OGRERR_FAILURE;
+        }
+        nBindNum++;
+    }
+
+    poDS->getDTime();
+    /* -------------------------------------------------------------------- */
+    /*      Execute the insert.                                             */
+    /* -------------------------------------------------------------------- */
+
+    if (!m_poPrepStmt->DB2Execute("OGR_DB2TableLayer::ICreateFeature"))
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "INSERT command for new feature failed. %s",
+                  poDS->GetSession()->GetLastError() );
+        FreeBindBuffer(nBindNum, papBindBuffer);
+        return OGRERR_FAILURE;
+    }
+    poDS->getDTime();
+
+    if( bIsIdentityFid) {
+        GIntBig oldFID = poFeature->GetFID();
+        OGRDB2Statement oStatement2( poDS->GetSession() );
+        oStatement2.Append( "select IDENTITY_VAL_LOCAL() AS IDENTITY "
+                            "FROM SYSIBM.SYSDUMMY1");
+        if( oStatement2.DB2Execute("OGR_DB2TableLayer::ICreateFeature")
+                && oStatement2.Fetch() )
+        {
+            poFeature->SetFID( atoi(oStatement2.GetColData( 0 ) ));
+
+            if ( oStatement2.GetColData( 0 ) )
+            {
+                poFeature->SetFID( atoi(oStatement2.GetColData( 0 ) ));
+
+            }
+        }
+        CPLDebug("OGR_DB2TableLayer::ICreateFeature","Old FID: " CPL_FRMT_GIB
+                 "; New FID: " CPL_FRMT_GIB, oldFID, poFeature->GetFID());
+    }
+
+    FreeBindBuffer(nBindNum, papBindBuffer);
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                          FreeBindBuffer()                            */
+/************************************************************************/
+
+void OGRDB2TableLayer::FreeBindBuffer(int nBindNum, void **papBindBuffer)
+{
+    for( int i = 0; i < nBindNum; i++ ) {
+        if (papBindBuffer[i] ) CPLFree(papBindBuffer[i]); // only free if set
+    };
+    CPLFree(papBindBuffer);
+}
+
+/************************************************************************/
+/*                          BindFieldValue()                            */
+/*                                                                      */
+/* Used by CreateFeature() and SetFeature() to bind a                   */
+/* non-empty field value                                                */
+/************************************************************************/
+
+OGRErr OGRDB2TableLayer::BindFieldValue(OGRDB2Statement *poStatement,
+                                        OGRFeature* poFeature, int i,
+                                        int nBindNum, void **papBindBuffer)
+{
+    int nOGRFieldType = poFeatureDefn->GetFieldDefn(i)->GetType();
+
+    int nLen = 0;
+    void * pValuePointer = NULL;
+    int nValueType = 0;
+    int nParameterType = 0;
+
+    if( nOGRFieldType == OFTString ) {
+        const char *stringValue = NULL;
+        stringValue = poFeature->GetFieldAsString(i);
+        papBindBuffer[nBindNum] = NULL; // Don't free
+        nLen = (int) strlen(stringValue);
+        pValuePointer = (void *) stringValue;
+        nValueType = SQL_C_CHAR;
+        nParameterType = SQL_VARCHAR;
+    }
+
+    if ( nOGRFieldType == OFTReal ) {
+        double *pnRealValue = (double *)CPLMalloc(sizeof(double));
+        papBindBuffer[nBindNum] = pnRealValue;
+        *pnRealValue = poFeature->GetFieldAsInteger(i);
+        nLen = sizeof(double);
+        pValuePointer = (void *) pnRealValue;
+        nValueType = SQL_C_DOUBLE;
+        nParameterType = SQL_DOUBLE;
+    }
+
+    if ( nOGRFieldType == OFTInteger ) {
+        int *pnIntValue = (int *)CPLMalloc(sizeof(int));
+        papBindBuffer[nBindNum] = pnIntValue;
+        *pnIntValue = poFeature->GetFieldAsInteger(i);
+        nLen = sizeof(int);
+        pValuePointer = (void *) pnIntValue;
+        nValueType = SQL_C_SLONG;
+        nParameterType = SQL_INTEGER;
+    }
+
+    if ( nOGRFieldType == OFTInteger64 ) {
+        GIntBig *pnLongValue = (GIntBig *)CPLMalloc(sizeof(GIntBig));
+        papBindBuffer[nBindNum] = pnLongValue;
+        *pnLongValue = poFeature->GetFieldAsInteger64(i);
+        nLen = sizeof(GIntBig);
+        pValuePointer = (void *) pnLongValue;
+        nValueType = SQL_C_SBIGINT;
+        nParameterType = SQL_BIGINT;
+    }
+
+
+    if (pValuePointer) {
+        if (!m_poPrepStmt->DB2BindParameterIn(
+                    "OGRDB2TableLayer::BindFieldValue",
+                    (nBindNum + 1),
+                    nValueType,
+                    nParameterType,
+                    nLen,
+                    pValuePointer))
+        {
+            CPLDebug("OGRDB2TableLayer::BindFieldValue",
+                     "Bind parameter failed");
+            return OGRERR_FAILURE;
+        }
+    }
+    return OGRERR_NONE;
+}
+
+
+/************************************************************************/
+/*                     CreateSpatialIndexIfNecessary()                  */
+/************************************************************************/
+
+void OGRDB2TableLayer::CreateSpatialIndexIfNecessary()
+{
+    if( bDeferredSpatialIndexCreation )
+    {
+        CreateSpatialIndex();
+    }
+}
+
+
+
+/************************************************************************/
+/*                      RunDeferredCreationIfNecessary()                */
+/************************************************************************/
+
+OGRErr OGRDB2TableLayer::RunDeferredCreationIfNecessary()
+{
+    CPLDebug("OGRDB2TableLayer::RunDeferredCreationIfNecessary","NO-OP");
+#ifdef LATER
+    if( !m_bDeferredCreation )
+        return OGRERR_NONE;
+    m_bDeferredCreation = FALSE;
+
+    const char* pszLayerName = m_poFeatureDefn->GetName();
+    OGRwkbGeometryType eGType = GetGeomType();
+
+    int bIsSpatial = (eGType != wkbNone);
+
+ /* Requirement 25: The geometry_type_name value in a gpkg_geometry_columns */
+ /* row SHALL be one of the uppercase geometry type names specified in */
+ /* Geometry Types (Normative). */
+    const char *pszGeometryType = m_poDS->GetGeometryTypeString(eGType);
+
+    /* Create the table! */
+    char *pszSQL = NULL;
+    CPLString osCommand;
+
+    pszSQL = sqlite3_mprintf(
+                 "CREATE TABLE \"%s\" ( "
+                 "\"%s\" INTEGER PRIMARY KEY AUTOINCREMENT",
+                 pszLayerName, m_pszFidColumn);
+    osCommand += pszSQL;
+    sqlite3_free(pszSQL);
+
+    if( GetGeomType() != wkbNone )
+    {
+        pszSQL = sqlite3_mprintf(", '%q' %s",
+                                 GetGeometryColumn(), pszGeometryType);
+        osCommand += pszSQL;
+        sqlite3_free(pszSQL);
+        if( !m_poFeatureDefn->GetGeomFieldDefn(0)->IsNullable() )
+        {
+            osCommand += " NOT NULL";
+        }
+    }
+
+    for(int i = 0; i < m_poFeatureDefn->GetFieldCount(); i++ )
+    {
+        if( i == m_iFIDAsRegularColumnIndex )
+            continue;
+        OGRFieldDefn* poFieldDefn = m_poFeatureDefn->GetFieldDefn(i);
+        pszSQL = sqlite3_mprintf(", '%q' %s",
+                                 poFieldDefn->GetNameRef(),
+                                 GPkgFieldFromOGR(poFieldDefn->GetType(),
+                                         poFieldDefn->GetSubType(),
+                                         poFieldDefn->GetWidth()));
+        osCommand += pszSQL;
+        sqlite3_free(pszSQL);
+        if( !poFieldDefn->IsNullable() )
+        {
+            osCommand += " NOT NULL";
+        }
+        const char* pszDefault = poFieldDefn->GetDefault();
+        if( pszDefault != NULL &&
+                (!poFieldDefn->IsDefaultDriverSpecific() ||
+                 (pszDefault[0] == '('
+                 && pszDefault[strlen(pszDefault)-1] == ')'
+                 && (STARTS_WITH_CI(pszDefault+1, "strftime")
+                 || STARTS_WITH_CI(pszDefault+1, " strftime")))) )
+        {
+            osCommand += " DEFAULT ";
+            OGRField sField;
+            if( poFieldDefn->GetType() == OFTDateTime &&
+                    OGRParseDate(pszDefault, &sField, 0) )
+            {
+                char* pszXML = OGRGetXMLDateTime(&sField);
+                osCommand += pszXML;
+                CPLFree(pszXML);
+            }
+/* Make sure CURRENT_TIMESTAMP is translated into appropriate format */
+/* for GeoPackage */
+            else if( poFieldDefn->GetType() == OFTDateTime &&
+                     EQUAL(pszDefault, "CURRENT_TIMESTAMP") )
+            {
+                osCommand += "(strftime('%Y-%m-%dT%H:%M:%fZ','now'))";
+            }
+            else
+            {
+                osCommand += poFieldDefn->GetDefault();
+            }
+        }
+    }
+
+    osCommand += ")";
+
+
+    OGRErr err = SQLCommand(m_poDS->GetDB(), osCommand.c_str());
+    if ( OGRERR_NONE != err )
+        return OGRERR_FAILURE;
+
+    /* Update gpkg_contents with the table info */
+    if ( bIsSpatial )
+        err = RegisterGeometryColumn();
+    else
+        err = m_poDS->CreateGDALAspatialExtension();
+
+    if ( err != OGRERR_NONE )
+        return OGRERR_FAILURE;
+
+    const char* pszIdentifier = GetMetadataItem("IDENTIFIER");
+    if( pszIdentifier == NULL )
+        pszIdentifier = pszLayerName;
+    const char* pszDescription = GetMetadataItem("DESCRIPTION");
+    if( pszDescription == NULL )
+        pszDescription = "";
+    pszSQL = sqlite3_mprintf(
+                 "INSERT INTO gpkg_contents "
+                 "(table_name,data_type,identifier,description,"
+                 "last_change,srs_id)"
+                 " VALUES "
+                 "('%q','%q','%q','%q',strftime('%%Y-%%m-%%dT%%H:%%M:%%fZ',"
+                 "CURRENT_TIMESTAMP),%d)",
+                 pszLayerName, (bIsSpatial ? "features": "aspatial"),
+                 pszIdentifier, pszDescription, m_iSrs);
+
+    err = SQLCommand(m_poDS->GetDB(), pszSQL);
+    sqlite3_free(pszSQL);
+    if ( err != OGRERR_NONE )
+        return OGRERR_FAILURE;
+
+    ResetReading();
+#endif
+    return OGRERR_NONE;
+}
diff --git a/ogr/ogrsf_frmts/dgn/dgndump.c b/ogr/ogrsf_frmts/dgn/dgndump.c
index b0e4c78..571a045 100644
--- a/ogr/ogrsf_frmts/dgn/dgndump.c
+++ b/ogr/ogrsf_frmts/dgn/dgndump.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dgndump.c 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: dgndump.c 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Microstation DGN Access Library
  * Purpose:  Temporary low level DGN dumper application.
@@ -29,7 +29,7 @@
 
 #include "dgnlibp.h"
 
-CPL_CVSID("$Id: dgndump.c 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: dgndump.c 33713 2016-03-12 17:41:57Z goatbar $");
 
 static void DGNDumpRawElement( DGNHandle hDGN, DGNElemCore *psCore,
                                FILE *fpOut );
@@ -92,7 +92,7 @@ int main( int argc, char ** argv )
         }
         else if( argv[iArg][0] == '-' || pszFilename != NULL )
             Usage();
-        else 
+        else
             pszFilename = argv[iArg];
     }
 
@@ -125,7 +125,7 @@ int main( int argc, char ** argv )
                 if( DGNGetElementExtents( hDGN, psElement, &sMin, &sMax ) )
                     printf( "  Extents: (%.6f,%.6f,%.6f)\n"
                             "        to (%.6f,%.6f,%.6f)\n",
-                            sMin.x, sMin.y, sMin.z, 
+                            sMin.x, sMin.y, sMin.z,
                             sMax.x, sMax.y, sMax.z );
             }
 
@@ -142,17 +142,17 @@ int main( int argc, char ** argv )
         double                  adfExtents[6];
 
         DGNGetExtents( hDGN, adfExtents );
-        printf( "X Range: %.2f to %.2f\n", 
+        printf( "X Range: %.2f to %.2f\n",
                 adfExtents[0], adfExtents[3] );
-        printf( "Y Range: %.2f to %.2f\n", 
+        printf( "Y Range: %.2f to %.2f\n",
                 adfExtents[1], adfExtents[4] );
-        printf( "Z Range: %.2f to %.2f\n", 
+        printf( "Z Range: %.2f to %.2f\n",
                 adfExtents[2], adfExtents[5] );
 
         pasEI = DGNGetElementIndex( hDGN, &nCount );
 
         printf( "Total Elements: %d\n", nCount );
-        
+
         memset( anLevelTypeCount, 0, 128*64*sizeof(int) );
         memset( anLevelCount, 0, 64*sizeof(int) );
         memset( anTypeCount, 0, 128*sizeof(int) );
@@ -172,8 +172,8 @@ int main( int argc, char ** argv )
         {
             if( anTypeCount[nType] != 0 )
             {
-                printf( "Type %s: %d\n", 
-                        DGNTypeToName( nType ), 
+                printf( "Type %s: %d\n",
+                        DGNTypeToName( nType ),
                         anTypeCount[nType] );
             }
         }
@@ -187,16 +187,16 @@ int main( int argc, char ** argv )
             if( anLevelCount[nLevel] == 0 )
                 continue;
 
-            printf( "Level %d, %d elements:\n", 
-                    nLevel, 
+            printf( "Level %d, %d elements:\n",
+                    nLevel,
                     anLevelCount[nLevel] );
 
             for( nType = 0; nType < 128; nType++ )
             {
                 if( anLevelTypeCount[nLevel * 128 + nType] != 0 )
                 {
-                    printf( "  Type %s: %d\n", 
-                            DGNTypeToName( nType ), 
+                    printf( "  Type %s: %d\n",
+                            DGNTypeToName( nType ),
                             anLevelTypeCount[nLevel*128 + nType] );
                 }
             }
@@ -214,7 +214,7 @@ int main( int argc, char ** argv )
 /*                         DGNDumpRawElement()                          */
 /************************************************************************/
 
-static void DGNDumpRawElement( DGNHandle hDGN, DGNElemCore *psCore, 
+static void DGNDumpRawElement( DGNHandle hDGN, DGNElemCore *psCore,
                                FILE *fpOut )
 
 {
@@ -226,7 +226,7 @@ static void DGNDumpRawElement( DGNHandle hDGN, DGNElemCore *psCore,
     {
         char    szHex[3];
 
-        if( (i % 16) == 0 )                                             
+        if( (i % 16) == 0 )
         {
             sprintf( szLine, "%6d: %71s", i, " " );
             iChar = 0;
@@ -234,7 +234,7 @@ static void DGNDumpRawElement( DGNHandle hDGN, DGNElemCore *psCore,
 
         sprintf( szHex, "%02x", psCore->raw_data[i] );
         strncpy( szLine+8+iChar*2, szHex, 2 );
-        
+
         if( psCore->raw_data[i] < 32 || psCore->raw_data[i] > 127 )
             szLine[42+iChar] = '.';
         else
@@ -248,6 +248,3 @@ static void DGNDumpRawElement( DGNHandle hDGN, DGNElemCore *psCore,
         iChar++;
     }
 }
-
-
-
diff --git a/ogr/ogrsf_frmts/dgn/dgnfloat.cpp b/ogr/ogrsf_frmts/dgn/dgnfloat.cpp
index 20f19ba..287aa54 100644
--- a/ogr/ogrsf_frmts/dgn/dgnfloat.cpp
+++ b/ogr/ogrsf_frmts/dgn/dgnfloat.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dgnfloat.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: dgnfloat.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Microstation DGN Access Library
  * Purpose:  Functions for translating DGN floats into IEEE floats.
@@ -29,7 +29,7 @@
 
 #include "dgnlibp.h"
 
-CPL_CVSID("$Id: dgnfloat.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: dgnfloat.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 typedef struct dbl {
     GUInt32 hi;
@@ -82,7 +82,7 @@ void    DGN2IEEEDouble(void * dbl)
     sign         = dt.hi & 0x80000000;
 
 /* -------------------------------------------------------------------- */
-/*      Adjust the exponent so that we may work with it                 */      
+/*      Adjust the exponent so that we may work with it                 */
 /* -------------------------------------------------------------------- */
     exponent = dt.hi >> 23;
     exponent = exponent & 0x000000ff;
@@ -94,7 +94,7 @@ void    DGN2IEEEDouble(void * dbl)
 /*      Save the bits that we are discarding so we can round properly   */
 /* -------------------------------------------------------------------- */
     rndbits = dt.lo & 0x00000007;
-        
+
     dt.lo = dt.lo >> 3;
     dt.lo = (dt.lo & 0x1fffffff) | (dt.hi << 29);
 
@@ -117,14 +117,8 @@ void    DGN2IEEEDouble(void * dbl)
     src = (unsigned char *) &dt;
     dest = (unsigned char *) dbl;
 
-    dest[0] = src[4];
-    dest[1] = src[5];
-    dest[2] = src[6];
-    dest[3] = src[7];
-    dest[4] = src[0];
-    dest[5] = src[1];
-    dest[6] = src[2];
-    dest[7] = src[3];
+    memcpy(dest + 0, src + 4, 4);
+    memcpy(dest + 4, src + 0, 4);
 #else
     memcpy( dbl, &dt, 8 );
 #endif
@@ -141,7 +135,7 @@ void    IEEE2DGNDouble(void * dbl)
     GInt32      exponent;
     GInt32      sign;
     GByte       *src,*dest;
-        
+
 #ifdef CPL_LSB
     src  = (GByte *) dbl;
     dest = (GByte *) &dt;
@@ -175,7 +169,7 @@ void    IEEE2DGNDouble(void * dbl)
     {
         dest = (GByte *) dbl;
 
-        if (sign) 
+        if (sign)
             dest[1] = 0xff;
         else
             dest[1] = 0x7f;
@@ -189,7 +183,7 @@ void    IEEE2DGNDouble(void * dbl)
         dest[7] = 0xff;
 
         return;
-    }   
+    }
 
 /* -------------------------------------------------------------------- */
 /*      In the case of of underflow return zero                         */
@@ -219,7 +213,7 @@ void    IEEE2DGNDouble(void * dbl)
         dt.hi = dt.hi | (dt.lo >> 29);
         dt.hi = dt.hi & 0x007fffff;
         dt.hi = dt.hi | (exponent << 23) | sign;
-            
+
         dt.lo = dt.lo << 3;
     }
 
@@ -230,14 +224,10 @@ void    IEEE2DGNDouble(void * dbl)
     dest = (GByte *) dbl;
 
 #ifdef CPL_LSB
-    dest[2] = src[0];
-    dest[3] = src[1];
-    dest[0] = src[2];
-    dest[1] = src[3];
-    dest[6] = src[4];
-    dest[7] = src[5];
-    dest[4] = src[6];
-    dest[5] = src[7];
+    memcpy(dest + 2, src + 0, 2);
+    memcpy(dest + 0, src + 2, 2);
+    memcpy(dest + 6, src + 4, 2);
+    memcpy(dest + 4, src + 6, 2);
 #else
     dest[1] = src[0];
     dest[0] = src[1];
diff --git a/ogr/ogrsf_frmts/dgn/dgnhelp.cpp b/ogr/ogrsf_frmts/dgn/dgnhelp.cpp
index 0a34a6d..ff3bb56 100644
--- a/ogr/ogrsf_frmts/dgn/dgnhelp.cpp
+++ b/ogr/ogrsf_frmts/dgn/dgnhelp.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dgnhelp.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: dgnhelp.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Microstation DGN Access Library
  * Purpose:  Application visible helper functions for parsing DGN information.
@@ -29,9 +29,9 @@
 
 #include "dgnlibp.h"
 
-CPL_CVSID("$Id: dgnhelp.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: dgnhelp.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
-static unsigned char abyDefaultPCT[256][3] = 
+static const unsigned char abyDefaultPCT[256][3] =
 {
   {255,255,255},
   {0,0,255},
@@ -314,7 +314,7 @@ static unsigned char abyDefaultPCT[256][3] =
  * out of range.
  */
 
-int DGNLookupColor( DGNHandle hDGN, int color_index, 
+int DGNLookupColor( DGNHandle hDGN, int color_index,
                     int * red, int * green, int * blue )
 
 {
@@ -353,7 +353,7 @@ int DGNLookupColor( DGNHandle hDGN, int color_index,
  *
  * @param hDGN the file.
  * @param psElem the element.
- * @param pnColor the location to return the fill color. 
+ * @param pnColor the location to return the fill color.
  *
  * @return TRUE on success or FALSE on failure.
  */
@@ -362,13 +362,13 @@ int DGNGetShapeFillInfo( DGNHandle hDGN, DGNElemCore *psElem, int *pnColor )
 
 {
     int iLink;
-    
-    for( iLink = 0; TRUE; iLink++ )
+
+    for( iLink = 0; true; iLink++ )
     {
         int nLinkType, nLinkSize;
         unsigned char *pabyData;
 
-        pabyData = DGNGetLinkage( hDGN, psElem, iLink, &nLinkType, 
+        pabyData = DGNGetLinkage( hDGN, psElem, iLink, &nLinkType,
                                   NULL, NULL, &nLinkSize );
         if( pabyData == NULL )
             return FALSE;
@@ -402,21 +402,21 @@ int DGNGetAssocID( DGNHandle hDGN, DGNElemCore *psElem )
 
 {
     int iLink;
-    
-    for( iLink = 0; TRUE; iLink++ )
+
+    for( iLink = 0; true; iLink++ )
     {
         int nLinkType, nLinkSize;
         unsigned char *pabyData;
 
-        pabyData = DGNGetLinkage( hDGN, psElem, iLink, &nLinkType, 
+        pabyData = DGNGetLinkage( hDGN, psElem, iLink, &nLinkType,
                                   NULL, NULL, &nLinkSize );
         if( pabyData == NULL )
             return -1;
 
         if( nLinkType == DGNLT_ASSOC_ID && nLinkSize >= 8 )
         {
-            return pabyData[4] 
-                + pabyData[5] * 256 
+            return pabyData[4]
+                + pabyData[5] * 256
                 + pabyData[6]*256*256
                 + pabyData[7] * 256*256*256;
         }
@@ -441,15 +441,15 @@ void DGNRad50ToAscii(unsigned short sRad50, char *str )
         sValue = sRad50;
         sValue /= saQuots[i];
         /* Map 0..39 to ASCII */
-        if (sValue==0)                     
+        if (sValue==0)
             ch = ' ';          /* space */
-        else if (sValue >= 1 && sValue <= 26) 
+        else if (sValue >= 1 && sValue <= 26)
             ch = (char) (sValue-1+'A');/* printable alpha A..Z */
-        else if (sValue == 27)             
+        else if (sValue == 27)
             ch = '$';          /* dollar */
-        else if (sValue == 28)             
+        else if (sValue == 28)
             ch = '.';          /* period */
-        else if (sValue == 29)             
+        else if (sValue == 29)
             ch = ' ';          /* unused char, emit a space instead */
         else if (sValue >= 30 && sValue <= 39)
             ch = (char) (sValue-30+'0');   /* digit 0..9 */
@@ -511,7 +511,7 @@ void DGNAsciiToRad50( const char *str, unsigned short *pRad50 )
 /*      Read the line style name from symbol table.                     */
 /*      The got name is stored in psLine.                               */
 /************************************************************************/
-
+#ifdef unused
 int DGNGetLineStyleName(CPL_UNUSED DGNInfo *psDGN,
                         DGNElemMultiPoint *psLine,
                         char szLineStyle[65] )
@@ -529,7 +529,7 @@ int DGNGetLineStyleName(CPL_UNUSED DGNInfo *psDGN,
                 *((unsigned char*)psDGN->buffer + 0x21e7 + i) == psLine->core.attr_data[6] &&
                 *((unsigned char*)psDGN->buffer + 0x21e8 + i) == psLine->core.attr_data[7])
             {
-                memcpy( szLineStyle, 
+                memcpy( szLineStyle,
                         (unsigned char*)psDGN->buffer + 0x21e9 + i, 64 );
                 szLineStyle[64] = '\0';
                 return TRUE;
@@ -544,6 +544,7 @@ int DGNGetLineStyleName(CPL_UNUSED DGNInfo *psDGN,
         return FALSE;
     }
 }
+#endif
 
 /************************************************************************/
 /*                           DGNDumpElement()                           */
@@ -553,7 +554,7 @@ int DGNGetLineStyleName(CPL_UNUSED DGNInfo *psDGN,
  * Emit textual report of an element.
  *
  * This function exists primarily for debugging, and will produce a textual
- * report about any element type to the designated file. 
+ * report about any element type to the designated file.
  *
  * @param hDGN the file from which the element originated.
  * @param psElement the element to report on.
@@ -568,7 +569,7 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
     fprintf( fp, "\n" );
     fprintf( fp, "Element:%-12s Level:%2d id:%-6d ",
              DGNTypeToName( psElement->type ),
-             psElement->level, 
+             psElement->level,
              psElement->element_id );
 
     if( psElement->complex )
@@ -579,11 +580,11 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
 
     fprintf( fp, "\n" );
 
-    fprintf( fp, "  offset=%d  size=%d bytes\n", 
+    fprintf( fp, "  offset=%d  size=%d bytes\n",
              psElement->offset, psElement->size );
 
-    fprintf( fp, 
-             "  graphic_group:%-3d color:%d weight:%d style:%d\n", 
+    fprintf( fp,
+             "  graphic_group:%-3d color:%d weight:%d style:%d\n",
              psElement->graphic_group,
              psElement->color,
              psElement->weight,
@@ -624,7 +625,7 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
             fprintf( fp, ",LINEAR PATTERNED ELEMENT" );
         else if( nClass == DGNC_CONSTRUCTION_RULE_ELEMENT )
             fprintf( fp, ",CONSTRUCTION_RULE_ELEMENT" );
-            
+
         fprintf( fp, "\n" );
     }
 
@@ -634,11 +635,11 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
       {
           DGNElemMultiPoint     *psLine = (DGNElemMultiPoint *) psElement;
           int                   i;
-          
+
           for( i=0; i < psLine->num_vertices; i++ )
-              fprintf( fp, "  (%.6f,%.6f,%.6f)\n", 
-                       psLine->vertices[i].x, 
-                       psLine->vertices[i].y, 
+              fprintf( fp, "  (%.6f,%.6f,%.6f)\n",
+                       psLine->vertices[i].x,
+                       psLine->vertices[i].y,
                        psLine->vertices[i].z );
       }
       break;
@@ -657,7 +658,7 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
                    psCell->rnghigh.x, psCell->rnghigh.y, psCell->rnghigh.z );
           fprintf( fp, "  origin=(%.5f,%.5f,%.5f)\n",
                    psCell->origin.x, psCell->origin.y, psCell->origin.z);
-          
+
           if( psInfo->dimension == 2 )
               fprintf( fp, "  xscale=%g, yscale=%g, rotation=%g\n",
                        psCell->xscale, psCell->yscale, psCell->rotation );
@@ -679,12 +680,12 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
       {
           DGNElemCellLibrary    *psCell = (DGNElemCellLibrary*) psElement;
 
-          fprintf( fp, 
-                   "  name=%s, class=%x, levels=%02x%02x%02x%02x, numwords=%d\n", 
-                   psCell->name, psCell->cclass, 
-                   psCell->levels[0], psCell->levels[1], psCell->levels[2], 
+          fprintf( fp,
+                   "  name=%s, class=%x, levels=%02x%02x%02x%02x, numwords=%d\n",
+                   psCell->name, psCell->cclass,
+                   psCell->levels[0], psCell->levels[1], psCell->levels[2],
                    psCell->levels[3], psCell->numwords );
-          fprintf( fp, "  dispsymb=%d, description=%s\n", 
+          fprintf( fp, "  dispsymb=%d, description=%s\n",
                    psCell->dispsymb, psCell->description );
       }
       break;
@@ -703,23 +704,23 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
 
           if( psInfo->dimension == 2 )
               fprintf( fp, "  origin=(%.5f,%.5f), rotation=%f\n",
-                       psArc->origin.x, 
-                       psArc->origin.y, 
+                       psArc->origin.x,
+                       psArc->origin.y,
                        psArc->rotation );
           else
               fprintf( fp, "  origin=(%.5f,%.5f,%.5f), quat=%d,%d,%d,%d\n",
-                       psArc->origin.x, 
-                       psArc->origin.y, 
-                       psArc->origin.z, 
-                       psArc->quat[0], 
-                       psArc->quat[1], 
-                       psArc->quat[2], 
+                       psArc->origin.x,
+                       psArc->origin.y,
+                       psArc->origin.z,
+                       psArc->quat[0],
+                       psArc->quat[1],
+                       psArc->quat[2],
                        psArc->quat[3] );
-          fprintf( fp, "  axes=(%.5f,%.5f), start angle=%f, sweep=%f\n", 
+          fprintf( fp, "  axes=(%.5f,%.5f), start angle=%f, sweep=%f\n",
                    psArc->primary_axis,
                    psArc->secondary_axis,
                    psArc->startang,
-                   psArc->sweepang );                   
+                   psArc->sweepang );
       }
       break;
 
@@ -727,12 +728,12 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
       {
           DGNElemText   *psText = (DGNElemText *) psElement;
 
-          fprintf( fp, 
+          fprintf( fp,
                    "  origin=(%.5f,%.5f), rotation=%f\n"
                    "  font=%d, just=%d, length_mult=%g, height_mult=%g\n"
                    "  string = \"%s\"\n",
-                   psText->origin.x, 
-                   psText->origin.y, 
+                   psText->origin.x,
+                   psText->origin.y,
                    psText->rotation,
                    psText->font_id,
                    psText->justification,
@@ -746,26 +747,26 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
       {
           DGNElemTextNode *psNode = (DGNElemTextNode *) psElement;
 
-          fprintf( fp, 
+          fprintf( fp,
                    "  totlength=%d, num_texts=%d\n",
                    psNode->totlength,
                    psNode->numelems );
-          fprintf( fp, 
+          fprintf( fp,
                    "  origin=(%.5f,%.5f), rotation=%f\n"
                    "  font=%d, just=%d, length_mult=%g, height_mult=%g\n",
-                   psNode->origin.x, 
-                   psNode->origin.y, 
+                   psNode->origin.x,
+                   psNode->origin.y,
                    psNode->rotation,
                    psNode->font_id,
                    psNode->justification,
                    psNode->length_mult,
                    psNode->height_mult );
-          fprintf( fp, 
+          fprintf( fp,
 		   "  max_length=%d, used=%d,",
-		   psNode->max_length, 
+		   psNode->max_length,
 		   psNode->max_used );
-          fprintf( fp, 
-		   "  node_number=%d\n", 
+          fprintf( fp,
+		   "  node_number=%d\n",
 		   psNode->node_number );
       }
       break;
@@ -774,14 +775,14 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
       {
           DGNElemComplexHeader  *psHdr = (DGNElemComplexHeader *) psElement;
 
-          fprintf( fp, 
+          fprintf( fp,
                    "  totlength=%d, numelems=%d\n",
                    psHdr->totlength,
                    psHdr->numelems );
           if (psElement->type  == DGNT_3DSOLID_HEADER ||
               psElement->type  == DGNT_3DSURFACE_HEADER) {
-            fprintf( fp, 
-                     "  surftype=%d, boundelms=%d\n", 
+            fprintf( fp,
+                     "  surftype=%d, boundelms=%d\n",
                      psHdr->surftype, psHdr->boundelms );
           }
       }
@@ -796,9 +797,9 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
           for( i = 0; i < 256; i++ )
           {
               fprintf( fp, "  %3d: (%3d,%3d,%3d)\n",
-                       i, 
-                       psCT->color_info[i][0], 
-                       psCT->color_info[i][1], 
+                       i,
+                       psCT->color_info[i][0],
+                       psCT->color_info[i][1],
                        psCT->color_info[i][2] );
           }
       }
@@ -814,7 +815,7 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
                    psTCB->uor_per_subunit, psTCB->sub_units );
           fprintf( fp, "  subunits_per_master = %ld, master units = `%s'\n",
                    psTCB->subunits_per_master, psTCB->master_units );
-          fprintf( fp, "  origin = (%.5f,%.5f,%.5f)\n", 
+          fprintf( fp, "  origin = (%.5f,%.5f,%.5f)\n",
                    psTCB->origin_x,
                    psTCB->origin_y,
                    psTCB->origin_z );
@@ -822,11 +823,11 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
           for( iView = 0; iView < 8; iView++ )
           {
               DGNViewInfo *psView = psTCB->views + iView;
-              
-              fprintf(fp, 
+
+              fprintf(fp,
                       "  View%d: flags=%04X, levels=%02X%02X%02X%02X%02X%02X%02X%02X\n",
                       iView,
-                      psView->flags, 
+                      psView->flags,
                       psView->levels[0],
                       psView->levels[1],
                       psView->levels[2],
@@ -835,11 +836,11 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
                       psView->levels[5],
                       psView->levels[6],
                       psView->levels[7] );
-              fprintf(fp, 
-                      "        origin=(%g,%g,%g)\n        delta=(%g,%g,%g)\n", 
+              fprintf(fp,
+                      "        origin=(%g,%g,%g)\n        delta=(%g,%g,%g)\n",
                       psView->origin.x, psView->origin.y, psView->origin.z,
                       psView->delta.x, psView->delta.y, psView->delta.z );
-              fprintf(fp, 
+              fprintf(fp,
                       "       trans=(%g,%g,%g,%g,%g,%g,%g,%g,%g)\n",
                       psView->transmatrx[0],
                       psView->transmatrx[1],
@@ -859,24 +860,24 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
           DGNElemTagSet *psTagSet = (DGNElemTagSet*) psElement;
           int            iTag;
 
-          fprintf( fp, "  tagSetName=%s, tagSet=%d, tagCount=%d, flags=%d\n", 
-                   psTagSet->tagSetName, psTagSet->tagSet, 
+          fprintf( fp, "  tagSetName=%s, tagSet=%d, tagCount=%d, flags=%d\n",
+                   psTagSet->tagSetName, psTagSet->tagSet,
                    psTagSet->tagCount, psTagSet->flags );
           for( iTag = 0; iTag < psTagSet->tagCount; iTag++ )
           {
               DGNTagDef *psTagDef = psTagSet->tagList + iTag;
 
-              fprintf( fp, "    %d: name=%s, type=%d, prompt=%s", 
-                       psTagDef->id, psTagDef->name, psTagDef->type, 
+              fprintf( fp, "    %d: name=%s, type=%d, prompt=%s",
+                       psTagDef->id, psTagDef->name, psTagDef->type,
                        psTagDef->prompt );
               if( psTagDef->type == 1 )
-                  fprintf( fp, ", default=%s\n", 
+                  fprintf( fp, ", default=%s\n",
                            psTagDef->defaultValue.string );
               else if( psTagDef->type == 3 || psTagDef->type == 5 )
-                  fprintf( fp, ", default=%d\n", 
+                  fprintf( fp, ", default=%d\n",
                            psTagDef->defaultValue.integer );
               else if( psTagDef->type == 4 )
-                  fprintf( fp, ", default=%g\n", 
+                  fprintf( fp, ", default=%g\n",
                            psTagDef->defaultValue.real );
               else
                   fprintf( fp, ", default=<unknown>\n" );
@@ -888,8 +889,8 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
       {
           DGNElemTagValue *psTag = (DGNElemTagValue*) psElement;
 
-          fprintf( fp, "  tagType=%d, tagSet=%d, tagIndex=%d, tagLength=%d\n", 
-                   psTag->tagType, psTag->tagSet, psTag->tagIndex, 
+          fprintf( fp, "  tagType=%d, tagSet=%d, tagIndex=%d, tagLength=%d\n",
+                   psTag->tagType, psTag->tagSet, psTag->tagIndex,
                    psTag->tagLength );
           if( psTag->tagType == 1 )
               fprintf( fp, "  value=%s\n", psTag->tagValue.string );
@@ -904,14 +905,14 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
       {
           DGNElemCone *psCone = (DGNElemCone *) psElement;
 
-          fprintf( fp, 
+          fprintf( fp,
                    "  center_1=(%g,%g,%g) radius=%g\n"
                    "  center_2=(%g,%g,%g) radius=%g\n"
-                   "  quat=%d,%d,%d,%d unknown=%d\n", 
+                   "  quat=%d,%d,%d,%d unknown=%d\n",
                    psCone->center_1.x, psCone->center_1.y, psCone->center_1.z,
-                   psCone->radius_1, 
+                   psCone->radius_1,
                    psCone->center_2.x, psCone->center_2.y, psCone->center_2.z,
-                   psCone->radius_2, 
+                   psCone->radius_2,
                    psCone->quat[0], psCone->quat[1],
                    psCone->quat[2], psCone->quat[3],
                    psCone->unknown );
@@ -944,7 +945,7 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
           }
           fprintf(fp, "\n");
           fprintf( fp, "     order=%d\n  %d poles, %d knots, %d rule lines\n",
-                   psSpline->u_order, psSpline->num_poles_u, 
+                   psSpline->u_order, psSpline->num_poles_u,
                    psSpline->num_knots_u, psSpline->rule_lines_u);
 
           fprintf( fp, "  V: properties=%02x",
@@ -959,7 +960,7 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
           }
           fprintf(fp, "\n");
           fprintf( fp, "     order=%d\n  %d poles, %d knots, %d rule lines\n",
-                   psSpline->v_order, psSpline->num_poles_v, 
+                   psSpline->v_order, psSpline->num_poles_v,
                    psSpline->num_knots_v, psSpline->rule_lines_v);
       }
       break;
@@ -969,7 +970,7 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
           DGNElemBSplineCurveHeader *psSpline =
             (DGNElemBSplineCurveHeader *) psElement;
 
-          fprintf( fp, 
+          fprintf( fp,
                    "  desc_words=%ld, curve type=%d\n"
                    "  properties=%02x",
                    psSpline->desc_words, psSpline->curve_type,
@@ -1028,30 +1029,30 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
         int iLink;
 
         fprintf( fp, "Attributes (%d bytes):\n", psElement->attr_bytes );
-        
-        for( iLink = 0; TRUE; iLink++ )
+
+        for( iLink = 0; true; iLink++ )
 
         {
             int nLinkType, nEntityNum=0, nMSLink=0, nLinkSize, i;
             unsigned char *pabyData;
 
-            pabyData = DGNGetLinkage( hDGN, psElement, iLink, &nLinkType, 
+            pabyData = DGNGetLinkage( hDGN, psElement, iLink, &nLinkType,
                                       &nEntityNum, &nMSLink, &nLinkSize );
             if( pabyData == NULL )
                 break;
 
             fprintf( fp, "Type=0x%04x", nLinkType );
             if( nMSLink != 0 || nEntityNum != 0 )
-                fprintf( fp, ", EntityNum=%d, MSLink=%d", 
+                fprintf( fp, ", EntityNum=%d, MSLink=%d",
                          nEntityNum, nMSLink );
 
-            int nBytes = psElement->attr_data + psElement->attr_bytes - pabyData;
+            int nBytes = static_cast<int>(psElement->attr_data + psElement->attr_bytes - pabyData);
             if( nBytes < nLinkSize )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
                         "Corrupt linkage, element id:%d, link:%d",
                         psElement->element_id, iLink);
-                fprintf(fp, " (Corrupt, declared size: %d, assuming size: %d)", 
+                fprintf(fp, " (Corrupt, declared size: %d, assuming size: %d)",
                     nLinkSize, nBytes);
                 nLinkSize = nBytes;
             }
@@ -1060,7 +1061,7 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
             for( i = 0; i < nLinkSize; i++ )
                 fprintf( fp, "%02x", pabyData[i] );
             fprintf( fp, "\n" );
-            
+
         }
     }
 }
@@ -1090,13 +1091,13 @@ const char *DGNTypeToName( int nType )
     {
       case DGNT_CELL_LIBRARY:
         return "Cell Library";
-        
+
       case DGNT_CELL_HEADER:
         return "Cell Header";
-        
+
       case DGNT_LINE:
         return "Line";
-        
+
       case DGNT_LINE_STRING:
         return "Line String";
 
@@ -1108,34 +1109,34 @@ const char *DGNTypeToName( int nType )
 
       case DGNT_SHAPE:
         return "Shape";
-        
+
       case DGNT_TEXT_NODE:
         return "Text Node";
 
       case DGNT_DIGITIZER_SETUP:
         return "Digitizer Setup";
-        
+
       case DGNT_TCB:
         return "TCB";
-        
+
       case DGNT_LEVEL_SYMBOLOGY:
         return "Level Symbology";
-        
+
       case DGNT_CURVE:
         return "Curve";
-        
+
       case DGNT_COMPLEX_CHAIN_HEADER:
         return "Complex Chain Header";
-        
+
       case DGNT_COMPLEX_SHAPE_HEADER:
         return "Complex Shape Header";
-        
+
       case DGNT_ELLIPSE:
         return "Ellipse";
-        
+
       case DGNT_ARC:
         return "Arc";
-        
+
       case DGNT_TEXT:
         return "Text";
 
@@ -1162,13 +1163,13 @@ const char *DGNTypeToName( int nType )
 
       case DGNT_SHARED_CELL_DEFN:
         return "Shared Cell Definition";
-        
+
       case DGNT_SHARED_CELL_ELEM:
         return "Shared Cell Element";
-        
+
       case DGNT_TAG_VALUE:
         return "Tag Value";
-        
+
       case DGNT_CONE:
         return "Cone";
 
@@ -1179,7 +1180,7 @@ const char *DGNTypeToName( int nType )
         return "3D Solid Header";
 
       default:
-        sprintf( szNumericResult, "%d", nType );
+        snprintf( szNumericResult, sizeof(szNumericResult), "%d", nType );
         return szNumericResult;
     }
 }
@@ -1189,7 +1190,7 @@ const char *DGNTypeToName( int nType )
 /************************************************************************/
 
 /**
- * Get attribute linkage size. 
+ * Get attribute linkage size.
  *
  * Returns the size, in bytes, of the attribute linkage starting at byte
  * offset nOffset.  On failure a value of 0 is returned.
@@ -1198,7 +1199,7 @@ const char *DGNTypeToName( int nType )
  * @param psElement the element to report on.
  * @param nOffset byte offset within attribute data of linkage to check.
  *
- * @return size of linkage in bytes, or zero. 
+ * @return size of linkage in bytes, or zero.
  */
 
 int DGNGetAttrLinkSize( CPL_UNUSED DGNHandle hDGN,
@@ -1209,9 +1210,9 @@ int DGNGetAttrLinkSize( CPL_UNUSED DGNHandle hDGN,
         return 0;
 
     /* DMRS Linkage */
-    if( (psElement->attr_data[nOffset+0] == 0 
+    if( (psElement->attr_data[nOffset+0] == 0
          && psElement->attr_data[nOffset+1] == 0)
-        || (psElement->attr_data[nOffset+0] == 0 
+        || (psElement->attr_data[nOffset+0] == 0
             && psElement->attr_data[nOffset+1] == 0x80) )
         return 8;
 
@@ -1228,20 +1229,20 @@ int DGNGetAttrLinkSize( CPL_UNUSED DGNHandle hDGN,
 /************************************************************************/
 
 /**
- * Returns requested linkage raw data. 
+ * Returns requested linkage raw data.
  *
  * A pointer to the raw data for the requested attribute linkage is returned
  * as well as (potentially) various information about the linkage including
  * the linkage type, database entity number and MSLink value, and the length
  * of the raw linkage data in bytes.
  *
- * If the requested linkage (iIndex) does not exist a value of zero is 
+ * If the requested linkage (iIndex) does not exist a value of zero is
  * returned.
  *
  * The entity number is (loosely speaking) the index of the table within
  * the current database to which the MSLINK value will refer.  The entity
- * number should be used to lookup the table name in the MSCATALOG table. 
- * The MSLINK value is the key value for the record in the target table. 
+ * number should be used to lookup the table name in the MSCATALOG table.
+ * The MSLINK value is the key value for the record in the target table.
  *
  * @param hDGN the file from which the element originated.
  * @param psElement the element to report on.
@@ -1249,19 +1250,19 @@ int DGNGetAttrLinkSize( CPL_UNUSED DGNHandle hDGN,
  * @param pnLinkageType variable to return linkage type.  This may be one of
  * the predefined DGNLT_ values or a different value. This pointer may be NULL.
  * @param pnEntityNum variable to return the entity number in or NULL if not
- * required.  
- * @param pnMSLink variable to return the MSLINK value in, or NULL if not 
+ * required.
+ * @param pnMSLink variable to return the MSLINK value in, or NULL if not
  * required.
  * @param pnLength variable to returned the linkage size in bytes or NULL.
- * 
+ *
  * @return pointer to raw internal linkage data.  This data should not be
- * altered or freed.  NULL returned on failure. 
+ * altered or freed.  NULL returned on failure.
  */
 
-unsigned char *DGNGetLinkage( DGNHandle hDGN, DGNElemCore *psElement, 
+unsigned char *DGNGetLinkage( DGNHandle hDGN, DGNElemCore *psElement,
                               int iIndex, int *pnLinkageType,
                               int *pnEntityNum, int *pnMSLink, int *pnLength )
-    
+
 {
     int nAttrOffset;
     int iLinkage, nLinkSize;
@@ -1273,33 +1274,37 @@ unsigned char *DGNGetLinkage( DGNHandle hDGN, DGNElemCore *psElement,
         if( iLinkage == iIndex )
         {
             int  nLinkageType=0, nEntityNum=0, nMSLink = 0;
-            CPLAssert( nLinkSize > 4 );
+            if( nLinkSize <= 4 )
+            {
+                CPLError(CE_Failure, CPLE_AssertionFailed, "nLinkSize <= 4");
+                return NULL;
+            }
 
             if( psElement->attr_data[nAttrOffset+0] == 0x00
                 && (psElement->attr_data[nAttrOffset+1] == 0x00
                     || psElement->attr_data[nAttrOffset+1] == 0x80) )
             {
                 nLinkageType = DGNLT_DMRS;
-                nEntityNum = psElement->attr_data[nAttrOffset+2] 
+                nEntityNum = psElement->attr_data[nAttrOffset+2]
                     + psElement->attr_data[nAttrOffset+3] * 256;
-                nMSLink = psElement->attr_data[nAttrOffset+4] 
+                nMSLink = psElement->attr_data[nAttrOffset+4]
                     + psElement->attr_data[nAttrOffset+5] * 256
                     + psElement->attr_data[nAttrOffset+6] * 65536;
             }
             else
-                nLinkageType = psElement->attr_data[nAttrOffset+2] 
+                nLinkageType = psElement->attr_data[nAttrOffset+2]
                     + psElement->attr_data[nAttrOffset+3] * 256;
 
             // Possibly an external database linkage?
             if( nLinkSize == 16 && nLinkageType != DGNLT_SHAPE_FILL )
             {
-                nEntityNum = psElement->attr_data[nAttrOffset+6] 
+                nEntityNum = psElement->attr_data[nAttrOffset+6]
                     + psElement->attr_data[nAttrOffset+7] * 256;
-                nMSLink = psElement->attr_data[nAttrOffset+8] 
+                nMSLink = psElement->attr_data[nAttrOffset+8]
                     + psElement->attr_data[nAttrOffset+9] * 256
                     + psElement->attr_data[nAttrOffset+10] * 65536
                     + psElement->attr_data[nAttrOffset+11] * 65536 * 256;
-                
+
             }
 
             if( pnLinkageType != NULL )
@@ -1314,7 +1319,7 @@ unsigned char *DGNGetLinkage( DGNHandle hDGN, DGNElemCore *psElement,
             return psElement->attr_data + nAttrOffset;
         }
     }
-             
+
     return NULL;
 }
 
@@ -1327,7 +1332,7 @@ unsigned char *DGNGetLinkage( DGNHandle hDGN, DGNElemCore *psElement,
 void DGNRotationToQuaternion( double dfRotation, int *panQuaternion )
 
 {
-    double dfRadianRot = (dfRotation / 180.0)  * PI;
+    double dfRadianRot = (dfRotation / 180.0)  * M_PI;
 
     panQuaternion[0] = (int) (cos(-dfRadianRot/2.0) * 2147483647);
     panQuaternion[1] = 0;
@@ -1359,7 +1364,7 @@ void DGNQuaternionToMatrix( int *quat, float *mat )
   mat[1*3+0] = (float) (2 * (q[0]*q[1] - q[2]*q[3]));
   mat[1*3+1] = (float) (-q[0]*q[0] + q[1]*q[1] - q[2]*q[2] + q[3]*q[3]);
   mat[1*3+2] = (float) (2 * (q[0]*q[3] + q[1]*q[2]));
-  mat[2*3+0] = (float) (2 * (q[0]*q[2] + q[1]*q[3])); 
+  mat[2*3+0] = (float) (2 * (q[0]*q[2] + q[1]*q[3]));
   mat[2*3+1] = (float) (2 * (q[1]*q[2] - q[0]*q[3]));
   mat[2*3+2] = (float) (-q[0]*q[0] - q[1]*q[1] + q[2]*q[2] + q[3]*q[3]);
 }
@@ -1368,6 +1373,7 @@ void DGNQuaternionToMatrix( int *quat, float *mat )
 /*                  DGNTransformPointWithQuaternion()                   */
 /************************************************************************/
 
+#ifdef unused
 void DGNTransformPointWithQuaternionVertex( CPL_UNUSED int *quat,
                                             CPL_UNUSED DGNPoint *v1,
                                             CPL_UNUSED DGNPoint *v2 )
@@ -1381,26 +1387,26 @@ void DGNTransformPointWithQuaternionVertex( CPL_UNUSED int *quat,
     See below for sketched implementation. kintel 20030819.
                                float x,y,z,w;
     // FIXME: Convert quat to x,y,z,w
-    v2.x = w*w*v1.x + 2*y*w*v1.z - 2*z*w*v1.y + x*x*v1.x + 2*y*x*v1.y + 2*z*x*v1.z - z*z*v1.x - y*y*v1.x; 
-    v2.y = 2*x*y*v1.x + y*y*v1.y + 2*z*y*v1.z + 2*w*z*v1.x - z*z*v1.y + w*w*v1.y - 2*x*w*v1.z - x*x*v1.y; 
+    v2.x = w*w*v1.x + 2*y*w*v1.z - 2*z*w*v1.y + x*x*v1.x + 2*y*x*v1.y + 2*z*x*v1.z - z*z*v1.x - y*y*v1.x;
+    v2.y = 2*x*y*v1.x + y*y*v1.y + 2*z*y*v1.z + 2*w*z*v1.x - z*z*v1.y + w*w*v1.y - 2*x*w*v1.z - x*x*v1.y;
     v2.z = 2*x*z*v1.x + 2*y*z*v1.y + z*z*v1.z - 2*w*y*v1.x - y*y*v1.z + 2*w*x*v1.y - x*x*v1.z + w*w*v1.z;
 #endif
 
 /* ==================================================================== */
-/*      Impelementation provided by Peggy Jung - 2004/03/05.            */
+/*      Implementation provided by Peggy Jung - 2004/03/05.            */
 /*      peggy.jung at moskito-gis dot de.  I haven't tested it.         */
 /* ==================================================================== */
 
 /*  Version: 0.1                                 Datum: 26.01.2004
- 
+
 IN:
 x,y,z               // DGNPoint &v1
-quat[]              // 
- 
+quat[]              //
+
 OUT:
 newX, newY, newZ    // DGNPoint &v2
 
-A u t o r  :  Peggy Jung
+Author: Peggy Jung
 */
 /*
     double ROT[12];  //rotation matrix for a given quaternion
@@ -1410,41 +1416,42 @@ A u t o r  :  Peggy Jung
     x = v1->x;
     y = v1->y;
     z = v1->z;
- 
+
     n = sqrt((double)PDP2PC_long(quat[0])*(double)PDP2PC_long(quat[0])+(double)PDP2PC_long(quat[1])*(double)PDP2PC_long(quat[1])+
              (double)PDP2PC_long(quat[2])*(double)PDP2PC_long(quat[2])+(double)PDP2PC_long(quat[3])*(double)PDP2PC_long(quat[3]));
- 
+
     a = (double)PDP2PC_long(quat[0])/n; //w
     b = (double)PDP2PC_long(quat[1])/n; //x
     c = (double)PDP2PC_long(quat[2])/n; //y
     d = (double)PDP2PC_long(quat[3])/n; //z
- 
+
     xx      = b*b;
     xy      = b*c;
     xz      = b*d;
     xw      = b*a;
- 
+
     yy      = c*c;
     yz      = c*d;
     yw      = c*a;
- 
+
     zz      = d*d;
     zw      = d+a;
- 
+
     ROT[0] = 1 - 2 * yy - 2 * zz ;
     ROT[1] =     2 * xy - 2 * zw ;
     ROT[2] =     2 * xz + 2 * yw ;
- 
+
     ROT[4] =     2 * xy + 2 * zw ;
     ROT[5] = 1 - 2 * xx - 2 * zz ;
     ROT[6] =     2 * yz - 2 * xw ;
- 
+
     ROT[8] =     2 * xz - 2 * yw ;
     ROT[9] =     2 * yz + 2 * xw ;
     ROT[10] = 1 - 2 * xx - 2 * yy ;
- 
+
     v2->x = ROT[0]*x + ROT[1]*y + ROT[2]*z;
     v2->y = ROT[4]*x + ROT[5]*y + ROT[6]*z;
     v2->z = ROT[8]*x + ROT[9]*y + ROT[10]*z;
 */
 }
+#endif
diff --git a/ogr/ogrsf_frmts/dgn/dgnlib.h b/ogr/ogrsf_frmts/dgn/dgnlib.h
index 1265839..41f1c72 100644
--- a/ogr/ogrsf_frmts/dgn/dgnlib.h
+++ b/ogr/ogrsf_frmts/dgn/dgnlib.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dgnlib.h 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: dgnlib.h 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Microstation DGN Access Library
  * Purpose:  Definitions of public structures and API of DGN Library.
@@ -27,8 +27,10 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _DGNLIB_H_INCLUDED
-#define _DGNLIB_H_INCLUDED
+#ifndef DGNLIB_H_INCLUDED
+#define DGNLIB_H_INCLUDED
+
+#undef STRICT_CPLERRORNUM_TYPE
 
 #include "cpl_conv.h"
 
@@ -48,7 +50,7 @@ CPL_C_START
  *
  * Note that the DGNReadElement() function transforms points into "master"
  * coordinate system space when they are in the file in UOR (units of
- * resolution) coordinates. 
+ * resolution) coordinates.
  */
 
 typedef struct {
@@ -69,16 +71,16 @@ typedef struct {
     unsigned char       stype;   /*!< Structure type (DGNST_*) */
     unsigned char       flags;   /*!< Other flags */
     long                offset;  /*!< Offset within file (private) */
-} DGNElementInfo;  
+} DGNElementInfo;
 
 /**
- * Core element structure. 
+ * Core element structure.
  *
  * Core information kept about each element that can be read from a DGN
- * file.  This structure is the first component of each specific element 
+ * file.  This structure is the first component of each specific element
  * structure (like DGNElemMultiPoint).  Normally the DGNElemCore.stype
  * field would be used to decide what specific structure type to case the
- * DGNElemCore pointer to. 
+ * DGNElemCore pointer to.
  *
  */
 
@@ -106,8 +108,8 @@ typedef struct {
     unsigned char *raw_data;    /*!< All raw element data including header. */
 } DGNElemCore;
 
-/** 
- * Multipoint element 
+/**
+ * Multipoint element
  *
  * The core.stype code is DGNST_MULTIPOINT.
  *
@@ -121,10 +123,10 @@ typedef struct {
   int           num_vertices;  /*!< Number of vertices in "vertices" */
   DGNPoint      vertices[2];   /*!< Array of two or more vertices */
 
-} DGNElemMultiPoint;    
+} DGNElemMultiPoint;
 
-/** 
- * Ellipse element 
+/**
+ * Ellipse element
  *
  * The core.stype code is DGNST_ARC.
  *
@@ -147,8 +149,8 @@ typedef struct {
 
 } DGNElemArc;
 
-/** 
- * Text element 
+/**
+ * Text element
  *
  * The core.stype code is DGNST_TEXT.
  *
@@ -158,8 +160,8 @@ typedef struct {
  */
 
 typedef struct {
-    DGNElemCore core;
-    
+    DGNElemCore core;   /* must be at first position ! */
+
     int         font_id;       /*!< Microstation font id, no list available*/
     int         justification; /*!< Justification, see DGNJ_* */
     double      length_mult;   /*!< Char width in master (if square) */
@@ -169,8 +171,8 @@ typedef struct {
     char        string[1];     /*!< Actual text (length varies, \0 terminated*/
 } DGNElemText;
 
-/** 
- * Complex header element 
+/**
+ * Complex header element
  *
  * The core.stype code is DGNST_COMPLEX_HEADER.
  *
@@ -181,25 +183,25 @@ typedef struct {
  */
 
 typedef struct {
-    DGNElemCore core;
-    
+    DGNElemCore core;   /* must be at first position ! */
+
     int         totlength;     /*!< Total length of surface in words,
                                     excluding the first 19 words
                                     (header + totlength field) */
     int         numelems;      /*!< # of elements in surface */
-    int         surftype;      /*!< surface/solid type 
-                                    (only used for 3D surface/solid). 
+    int         surftype;      /*!< surface/solid type
+                                    (only used for 3D surface/solid).
                                     One of  DGNSUT_* or DGNSOT_*. */
     int         boundelms;     /*!< # of elements in each boundary
-                                    (only used for 3D surface/solid). */ 
+                                    (only used for 3D surface/solid). */
 } DGNElemComplexHeader;
 
-/** 
+/**
  * Color table.
  *
  * The core.stype code is DGNST_COLORTABLE.
  *
- * Returned for DGNT_GROUP_DATA(5) elements, with a level number of 
+ * Returned for DGNT_GROUP_DATA(5) elements, with a level number of
  * DGN_GDL_COLOR_TABLE(1).
  */
 
@@ -220,7 +222,7 @@ typedef struct {
     unsigned long activez;
 } DGNViewInfo;
 
-/** 
+/**
  * Terminal Control Block (header).
  *
  * The core.stype code is DGNST_TCB.
@@ -235,14 +237,14 @@ typedef struct {
  */
 
 typedef struct {
-    DGNElemCore core;
+    DGNElemCore core;   /* must be at first position ! */
 
     int         dimension;         /*!< Dimension (2 or 3) */
 
     double      origin_x;       /*!< X origin of UOR space in master units(?)*/
     double      origin_y;       /*!< Y origin of UOR space in master units(?)*/
     double      origin_z;       /*!< Z origin of UOR space in master units(?)*/
-    
+
     long        uor_per_subunit;   /*!< UOR per subunit. */
     char        sub_units[3];      /*!< User name for subunits (2 chars)*/
     long        subunits_per_master; /*!< Subunits per master unit. */
@@ -252,7 +254,7 @@ typedef struct {
 
 } DGNElemTCB;
 
-/** 
+/**
  * Cell Header.
  *
  * The core.stype code is DGNST_CELL_HEADER.
@@ -261,7 +263,7 @@ typedef struct {
  */
 
 typedef struct {
-    DGNElemCore core;
+    DGNElemCore core;   /* must be at first position ! */
 
     int         totlength;         /*!< Total length of cell in words,
                                         excluding the first 19 words
@@ -269,10 +271,10 @@ typedef struct {
     char        name[7];           /*!< Cell name */
  unsigned short cclass;            /*!< Class bitmap */
  unsigned short levels[4];         /*!< Levels used in cell */
-    
+
     DGNPoint    rnglow;            /*!< X/Y/Z minimums for cell */
     DGNPoint    rnghigh;           /*!< X/Y/Z maximums for cell */
-    
+
     double      trans[9];          /*!< 2D/3D Transformation Matrix */
     DGNPoint    origin;            /*!< Cell Origin */
 
@@ -282,7 +284,7 @@ typedef struct {
 
 } DGNElemCellHeader;
 
-/** 
+/**
  * Cell Library.
  *
  * The core.stype code is DGNST_CELL_LIBRARY.
@@ -291,7 +293,7 @@ typedef struct {
  */
 
 typedef struct {
-    DGNElemCore core;
+    DGNElemCore core;   /* must be at first position ! */
 
     short       celltype;          /*!< Cell type. */
     short       attindx;           /*!< Attribute linkage. */
@@ -304,10 +306,10 @@ typedef struct {
  unsigned short levels[4];         /*!< Levels used in cell */
 
     char        description[28];   /*!< Description */
-    
+
 } DGNElemCellLibrary;
 
-/** 
+/**
  * Shared Cell Definition.
  *
  * The core.stype code is DGNST_SHARED_CELL_DEFN.
@@ -316,7 +318,7 @@ typedef struct {
  */
 
 typedef struct {
-    DGNElemCore core;
+    DGNElemCore core;   /* must be at first position ! */
 
     int         totlength;         /*!< Total length of cell in words,
                                         excluding the first 19 words
@@ -328,7 +330,7 @@ typedef struct {
 
 typedef union { char *string; GInt32 integer; double real; } tagValueUnion;
 
-/** 
+/**
  * Tag Value.
  *
  * The core.stype code is DGNST_TAG_VALUE.
@@ -337,7 +339,7 @@ typedef union { char *string; GInt32 integer; double real; } tagValueUnion;
  */
 
 typedef struct {
-    DGNElemCore core;
+    DGNElemCore core;   /* must be at first position ! */
 
     int         tagType;           /*!< Tag type indicator, DGNTT_* */
     int         tagSet;            /*!< Which tag set does this relate to? */
@@ -364,7 +366,7 @@ typedef struct _DGNTagDef {
 #define DGNTT_INTEGER     3
 #define DGNTT_FLOAT       4
 
-/** 
+/**
  * Tag Set.
  *
  * The core.stype code is DGNST_TAG_SET.
@@ -373,7 +375,7 @@ typedef struct _DGNTagDef {
  */
 
 typedef struct {
-    DGNElemCore core;
+    DGNElemCore core;   /* must be at first position ! */
 
     int        tagCount;    /*!< Number of tags in tagList. */
     int        tagSet;      /*!< Tag set index. */
@@ -384,15 +386,15 @@ typedef struct {
 
 } DGNElemTagSet;
 
-/** 
- * Cone element 
+/**
+ * Cone element
  *
  * The core.stype code is DGNST_CONE.
  *
  * Used for: DGNT_CONE(23)
  */
 typedef struct {
-  DGNElemCore core;
+  DGNElemCore core;   /* must be at first position ! */
 
   short unknown;     /*!< Unknown data */
   int quat[4];      /*!< Orientation quaternion */
@@ -404,8 +406,8 @@ typedef struct {
 } DGNElemCone;
 
 
-/** 
- * Text Node Header. 
+/**
+ * Text Node Header.
  *
  * The core.stype code is DGNST_TEXT_NODE.
  *
@@ -415,8 +417,8 @@ typedef struct {
  */
 
 typedef struct {
-  DGNElemCore core;
- 
+  DGNElemCore core;   /* must be at first position ! */
+
   int       totlength; 	 	/*!<  Total length of the node
 				      (bytes = totlength * 2 + 38) */
   int       numelems;    	/*!<  Number of text strings */
@@ -434,29 +436,29 @@ typedef struct {
 } DGNElemTextNode;
 
 
-/** 
- * B-Spline Surface Header element 
+/**
+ * B-Spline Surface Header element
  *
  * The core.stype code is DGNST_BSPLINE_SURFACE_HEADER.
  *
  * Used for: DGNT_BSPLINE_SURFACE_HEADER(24)
  */
 typedef struct {
-  DGNElemCore core;
+  DGNElemCore core;   /* must be at first position ! */
 
   long desc_words;               /*!< Total length of B-Spline surface in
                                       words, excluding the first 20 words
                                       (header + desc_words field) */
   unsigned char curve_type;      /*!< curve type */
   unsigned char u_order;         /*!< B-spline U order: 2-15 */
-  unsigned short u_properties;   /*!< surface U properties: 
+  unsigned short u_properties;   /*!< surface U properties:
                                       ORing of DGNBSC_ flags */
   short num_poles_u;             /*!< number of poles */
   short num_knots_u;             /*!< number of knots */
   short rule_lines_u;            /*!< number of rule lines */
 
   unsigned char v_order;         /*!< B-spline V order: 2-15 */
-  unsigned short v_properties;   /*!< surface V properties: 
+  unsigned short v_properties;   /*!< surface V properties:
                                       Oring of DGNBSS_ flags */
   short num_poles_v;             /*!< number of poles */
   short num_knots_v;             /*!< number of knots */
@@ -465,15 +467,15 @@ typedef struct {
   short num_bounds;              /*!< number of boundaries */
 } DGNElemBSplineSurfaceHeader;
 
-/** 
- * B-Spline Curve Header element 
+/**
+ * B-Spline Curve Header element
  *
  * The core.stype code is DGNST_BSPLINE_CURVE_HEADER.
  *
  * Used for: DGNT_BSPLINE_CURVE_HEADER(27)
  */
 typedef struct {
-  DGNElemCore core;
+  DGNElemCore core;   /* must be at first position ! */
 
   long desc_words;               /*!< Total length of B-Spline curve in words,
                                       excluding the first 20 words
@@ -485,15 +487,15 @@ typedef struct {
   short num_knots;               /*!< number of knots */
 } DGNElemBSplineCurveHeader;
 
-/** 
- * B-Spline Surface Boundary element 
+/**
+ * B-Spline Surface Boundary element
  *
  * The core.stype code is DGNST_BSPLINE_SURFACE_BOUNDARY
  *
  * Used for: DGNT_BSPLINE_SURFACE_BOUNDARY(25)
  */
 typedef struct {
-  DGNElemCore core;
+  DGNElemCore core;   /* must be at first position ! */
 
   short number;         /*!< boundary number */
   short numverts;       /*!< number of boundary vertices */
@@ -501,15 +503,15 @@ typedef struct {
                             (in UV space) */
 } DGNElemBSplineSurfaceBoundary;
 
-/** 
- * B-Spline Knot/Weight element 
+/**
+ * B-Spline Knot/Weight element
  *
  * The core.stype code is DGNST_KNOT_WEIGHT
  *
  * Used for: DGNT_BSPLINE_KNOT(26), DGNT_BSPLINE_WEIGHT_FACTOR(28)
  */
 typedef struct {
-  DGNElemCore core;
+  DGNElemCore core;   /* must be at first position ! */
 
   float array[1];         /*!< array (variable length). Length is
                              given in the corresponding B-Spline
@@ -522,22 +524,22 @@ typedef struct {
 /* -------------------------------------------------------------------- */
 
 /** DGNElemCore style: Element uses DGNElemCore structure */
-#define DGNST_CORE                 1 
+#define DGNST_CORE                 1
 
 /** DGNElemCore style: Element uses DGNElemMultiPoint structure */
-#define DGNST_MULTIPOINT           2 
+#define DGNST_MULTIPOINT           2
 
 /** DGNElemCore style: Element uses DGNElemColorTable structure */
-#define DGNST_COLORTABLE           3 
+#define DGNST_COLORTABLE           3
 
 /** DGNElemCore style: Element uses DGNElemTCB structure */
-#define DGNST_TCB                  4 
+#define DGNST_TCB                  4
 
 /** DGNElemCore style: Element uses DGNElemArc structure */
-#define DGNST_ARC                  5 
+#define DGNST_ARC                  5
 
 /** DGNElemCore style: Element uses DGNElemText structure */
-#define DGNST_TEXT                 6 
+#define DGNST_TEXT                 6
 
 /** DGNElemCore style: Element uses DGNElemComplexHeader structure */
 #define DGNST_COMPLEX_HEADER       7
@@ -765,7 +767,7 @@ int  CPL_DLL         DGNLoadTCB( DGNHandle );
 int  CPL_DLL         DGNLookupColor( DGNHandle, int, int *, int *, int * );
 int  CPL_DLL         DGNGetShapeFillInfo( DGNHandle, DGNElemCore *, int * );
 int  CPL_DLL         DGNGetAssocID( DGNHandle, DGNElemCore * );
-int  CPL_DLL         DGNGetElementExtents( DGNHandle, DGNElemCore *, 
+int  CPL_DLL         DGNGetElementExtents( DGNHandle, DGNElemCore *,
                                            DGNPoint *, DGNPoint * );
 
 void CPL_DLL         DGNDumpElement( DGNHandle, DGNElemCore *, FILE * );
@@ -775,47 +777,47 @@ void CPL_DLL  DGNRotationToQuaternion( double, int * );
 void CPL_DLL  DGNQuaternionToMatrix( int *, float * );
 int CPL_DLL   DGNStrokeArc( DGNHandle, DGNElemArc *, int, DGNPoint * );
 int CPL_DLL   DGNStrokeCurve( DGNHandle, DGNElemMultiPoint*, int, DGNPoint * );
-void CPL_DLL  DGNSetSpatialFilter( DGNHandle hDGN, 
-                                   double dfXMin, double dfYMin, 
+void CPL_DLL  DGNSetSpatialFilter( DGNHandle hDGN,
+                                   double dfXMin, double dfYMin,
                                    double dfXMax, double dfYMax );
 int  CPL_DLL  DGNGetAttrLinkSize( DGNHandle, DGNElemCore *, int );
 unsigned char CPL_DLL *
-              DGNGetLinkage( DGNHandle hDGN, DGNElemCore *psElement, 
+              DGNGetLinkage( DGNHandle hDGN, DGNElemCore *psElement,
                              int iIndex, int *pnLinkageType,
                              int *pnEntityNum, int *pnMSLink, int *pnLinkSize);
 
 /* Write API */
-    
+
 int  CPL_DLL  DGNWriteElement( DGNHandle, DGNElemCore * );
 int  CPL_DLL  DGNResizeElement( DGNHandle, DGNElemCore *, int );
-DGNHandle CPL_DLL 
-      DGNCreate( const char *pszNewFilename, const char *pszSeedFile, 
-                 int nCreationFlags, 
+DGNHandle CPL_DLL
+      DGNCreate( const char *pszNewFilename, const char *pszSeedFile,
+                 int nCreationFlags,
                  double dfOriginX, double dfOriginY, double dfOriginZ,
-                 int nMasterUnitPerSubUnit, int nUORPerSubUnit, 
+                 int nMasterUnitPerSubUnit, int nUORPerSubUnit,
                  const char *pszMasterUnits, const char *pszSubUnits );
-DGNElemCore CPL_DLL *DGNCloneElement( DGNHandle hDGNSrc, DGNHandle hDGNDst, 
+DGNElemCore CPL_DLL *DGNCloneElement( DGNHandle hDGNSrc, DGNHandle hDGNDst,
                                       DGNElemCore *psSrcElement );
-int CPL_DLL   DGNUpdateElemCore( DGNHandle hDGN, DGNElemCore *psElement, 
-                                 int nLevel, int nGraphicGroup, int nColor, 
+int CPL_DLL   DGNUpdateElemCore( DGNHandle hDGN, DGNElemCore *psElement,
+                                 int nLevel, int nGraphicGroup, int nColor,
                                  int nWeight, int nStyle );
-int CPL_DLL   DGNUpdateElemCoreExtended( DGNHandle hDGN, 
+int CPL_DLL   DGNUpdateElemCoreExtended( DGNHandle hDGN,
                                          DGNElemCore *psElement );
 
 DGNElemCore CPL_DLL *
-              DGNCreateMultiPointElem( DGNHandle hDGN, int nType, 
+              DGNCreateMultiPointElem( DGNHandle hDGN, int nType,
                                        int nPointCount, DGNPoint*pasVertices );
 DGNElemCore CPL_DLL  *
-              DGNCreateArcElem2D( DGNHandle hDGN, int nType, 
+              DGNCreateArcElem2D( DGNHandle hDGN, int nType,
                                   double dfOriginX, double dfOriginY,
                                   double dfPrimaryAxis, double dfSecondaryAxis,
-                                  double dfRotation, 
+                                  double dfRotation,
                                   double dfStartAngle, double dfSweepAngle );
 
 DGNElemCore CPL_DLL  *
-              DGNCreateArcElem( DGNHandle hDGN, int nType, 
+              DGNCreateArcElem( DGNHandle hDGN, int nType,
                                 double dfOriginX, double dfOriginY,
-                                double dfOriginZ, 
+                                double dfOriginZ,
                                 double dfPrimaryAxis, double dfSecondaryAxis,
                                 double dfStartAngle, double dfSweepAngle,
                                 double dfRotation, int *panQuaternion );
@@ -829,56 +831,56 @@ DGNElemCore CPL_DLL  *
                                  int *panQuaternion );
 
 DGNElemCore CPL_DLL *
-             DGNCreateTextElem( DGNHandle hDGN, const char *pszText, 
-                                int nFontId, int nJustification, 
-                                double dfLengthMult, double dfHeightMult, 
+             DGNCreateTextElem( DGNHandle hDGN, const char *pszText,
+                                int nFontId, int nJustification,
+                                double dfLengthMult, double dfHeightMult,
                                 double dfRotation, int *panQuaternion,
                        double dfOriginX, double dfOriginY, double dfOriginZ );
 
 DGNElemCore CPL_DLL *
-            DGNCreateColorTableElem( DGNHandle hDGN, int nScreenFlag, 
+            DGNCreateColorTableElem( DGNHandle hDGN, int nScreenFlag,
                                      GByte abyColorInfo[256][3] );
 DGNElemCore CPL_DLL *
-DGNCreateComplexHeaderElem( DGNHandle hDGN, int nType, 
+DGNCreateComplexHeaderElem( DGNHandle hDGN, int nType,
                             int nTotLength, int nNumElems );
 DGNElemCore CPL_DLL *
-DGNCreateComplexHeaderFromGroup( DGNHandle hDGN, int nType, 
+DGNCreateComplexHeaderFromGroup( DGNHandle hDGN, int nType,
                                  int nNumElems, DGNElemCore **papsElems );
 
 DGNElemCore CPL_DLL *
-DGNCreateSolidHeaderElem( DGNHandle hDGN, int nType, int nSurfType, 
+DGNCreateSolidHeaderElem( DGNHandle hDGN, int nType, int nSurfType,
                           int nBoundElems, int nTotLength, int nNumElems );
 DGNElemCore CPL_DLL *
 DGNCreateSolidHeaderFromGroup( DGNHandle hDGN, int nType, int nSurfType,
-                               int nBoundElems, int nNumElems, 
+                               int nBoundElems, int nNumElems,
                                DGNElemCore **papsElems );
 
 DGNElemCore CPL_DLL  *
-DGNCreateCellHeaderElem( DGNHandle hDGN, int nTotLength, const char *pszName, 
-                         short nClass, short *panLevels, 
-                         DGNPoint *psRangeLow, DGNPoint *psRangeHigh, 
+DGNCreateCellHeaderElem( DGNHandle hDGN, int nTotLength, const char *pszName,
+                         short nClass, short *panLevels,
+                         DGNPoint *psRangeLow, DGNPoint *psRangeHigh,
                          DGNPoint *psOrigin, double dfXScale, double dfYScale,
                          double dfRotation );
-                     
+
 DGNElemCore CPL_DLL *
-DGNCreateCellHeaderFromGroup( DGNHandle hDGN, const char *pszName, 
-                              short nClass, short *panLevels, 
+DGNCreateCellHeaderFromGroup( DGNHandle hDGN, const char *pszName,
+                              short nClass, short *panLevels,
                               int nNumElems, DGNElemCore **papsElems,
                               DGNPoint *psOrigin,
                               double dfXScale, double dfYScale,
                               double dfRotation );
 
-int CPL_DLL DGNAddMSLink( DGNHandle hDGN, DGNElemCore *psElement, 
+int CPL_DLL DGNAddMSLink( DGNHandle hDGN, DGNElemCore *psElement,
                           int nLinkageType, int nEntityNum, int nMSLink );
 
-int CPL_DLL DGNAddRawAttrLink( DGNHandle hDGN, DGNElemCore *psElement, 
+int CPL_DLL DGNAddRawAttrLink( DGNHandle hDGN, DGNElemCore *psElement,
                                int nLinkSize, unsigned char *pabyRawLinkData );
 
-int CPL_DLL DGNAddShapeFillInfo( DGNHandle hDGN, DGNElemCore *psElement, 
+int CPL_DLL DGNAddShapeFillInfo( DGNHandle hDGN, DGNElemCore *psElement,
                                  int nColor );
 
 int CPL_DLL DGNElemTypeHasDispHdr( int nElemType );
 
 CPL_C_END
 
-#endif /* ndef _DGNLIB_H_INCLUDED */
+#endif /* ndef DGNLIB_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/dgn/dgnlibp.h b/ogr/ogrsf_frmts/dgn/dgnlibp.h
index 189e151..c4f77cb 100644
--- a/ogr/ogrsf_frmts/dgn/dgnlibp.h
+++ b/ogr/ogrsf_frmts/dgn/dgnlibp.h
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: dgnlibp.h 22381 2011-05-16 21:14:22Z rouault $
+ * $Id: dgnlibp.h 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Microstation DGN Access Library
- * Purpose:  Internal (privatE) datastructures, and prototypes for DGN Access 
+ * Purpose:  Internal (privatE) datastructures, and prototypes for DGN Access
  *           Library.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -28,16 +28,11 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _DGNLIBP_H_INCLUDED
-#define _DGNLIBP_H_INCLUDED
+#ifndef DGNLIBP_H_INCLUDED
+#define DGNLIBP_H_INCLUDED
 
 #include "dgnlib.h"
 
-
-#ifndef PI
-#define PI  3.1415926535897932384626433832795
-#endif
-
 typedef struct {
     FILE        *fp;
     int         next_element_id;
@@ -90,7 +85,7 @@ typedef struct {
                         + ((p)[3] << 8) \
                         + ((p)[1] << 24) \
                         + ((p)[0] << 16))
-#define DGN_WRITE_INT32( n, p ) { GInt32 nMacroWork = (n);                   \
+#define DGN_WRITE_INT32( n, p ) { GInt32 nMacroWork = (GInt32)(n);                   \
  ((unsigned char *)p)[0] = (unsigned char)((nMacroWork & 0x00ff0000) >> 16); \
  ((unsigned char *)p)[1] = (unsigned char)((nMacroWork & 0xff000000) >> 24); \
  ((unsigned char *)p)[2] = (unsigned char)((nMacroWork & 0x000000ff) >> 0);  \
@@ -108,4 +103,4 @@ void DGNAsciiToRad50( const char *str, unsigned short *rad50 );
 void DGNSpatialFilterToUOR( DGNInfo *);
 int  DGNLoadRawElement( DGNInfo *psDGN, int *pnType, int *pnLevel );
 
-#endif /* ndef _DGNLIBP_H_INCLUDED */
+#endif /* ndef DGNLIBP_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/dgn/dgnopen.cpp b/ogr/ogrsf_frmts/dgn/dgnopen.cpp
index 8dd456c..85c842b 100644
--- a/ogr/ogrsf_frmts/dgn/dgnopen.cpp
+++ b/ogr/ogrsf_frmts/dgn/dgnopen.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dgnopen.cpp 27272 2014-05-01 23:14:58Z rouault $
+ * $Id: dgnopen.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Microstation DGN Access Library
  * Purpose:  DGN Access Library file open code.
@@ -29,17 +29,17 @@
 
 #include "dgnlibp.h"
 
-CPL_CVSID("$Id: dgnopen.cpp 27272 2014-05-01 23:14:58Z rouault $");
+CPL_CVSID("$Id: dgnopen.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                            DGNTestOpen()                             */
 /************************************************************************/
 
-/** 
+/**
  * Test if header is DGN.
  *
  * @param pabyHeader block of header data from beginning of file.
- * @param nByteCount number of bytes in pabyHeader. 
+ * @param nByteCount number of bytes in pabyHeader.
  *
  * @return TRUE if the header appears to be from a DGN file, otherwise FALSE.
  */
@@ -58,7 +58,7 @@ int DGNTestOpen( GByte *pabyHeader, int nByteCount )
         return TRUE;
 
     // Is it not a regular 2D or 3D file?
-    if( (pabyHeader[0] != 0x08 && pabyHeader[0] != 0xC8) 
+    if( (pabyHeader[0] != 0x08 && pabyHeader[0] != 0xC8)
         || pabyHeader[1] != 0x09
         || pabyHeader[2] != 0xFE || pabyHeader[3] != 0x02 )
         return FALSE;
@@ -71,20 +71,20 @@ int DGNTestOpen( GByte *pabyHeader, int nByteCount )
 /************************************************************************/
 
 /**
- * Open a DGN file. 
+ * Open a DGN file.
  *
  * The file is opened, and minimally verified to ensure it is a DGN (ISFF)
  * file.  If the file cannot be opened for read access an error with code
- * CPLE_OpenFailed with be reported via CPLError() and NULL returned.  
+ * CPLE_OpenFailed with be reported via CPLError() and NULL returned.
  * If the file header does
  * not appear to be a DGN file, an error with code CPLE_AppDefined will be
  * reported via CPLError(), and NULL returned.
  *
  * If successful a handle for further access is returned.  This should be
- * closed with DGNClose() when no longer needed.  
+ * closed with DGNClose() when no longer needed.
  *
  * DGNOpen() does not scan the file on open, and should be very fast even for
- * large files.  
+ * large files.
  *
  * @param pszFilename name of file to try opening.
  * @param bUpdate should the file be opened with read+update (r+) mode?
@@ -96,20 +96,20 @@ int DGNTestOpen( GByte *pabyHeader, int nByteCount )
 DGNHandle DGNOpen( const char * pszFilename, int bUpdate )
 
 {
-    DGNInfo     *psDGN;
-    FILE        *fp;
 
 /* -------------------------------------------------------------------- */
 /*      Open the file.                                                  */
 /* -------------------------------------------------------------------- */
+    FILE *fp;
+
     if( bUpdate )
         fp = VSIFOpen( pszFilename, "rb+" );
     else
         fp = VSIFOpen( pszFilename, "rb" );
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Unable to open `%s' for read access.\n", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Unable to open `%s' for read access.\n",
                   pszFilename );
         return NULL;
     }
@@ -117,13 +117,12 @@ DGNHandle DGNOpen( const char * pszFilename, int bUpdate )
 /* -------------------------------------------------------------------- */
 /*      Verify the format ... add later.                                */
 /* -------------------------------------------------------------------- */
-    GByte       abyHeader[512];
-
-    VSIFRead( abyHeader, 1, sizeof(abyHeader), fp );
-    if( !DGNTestOpen( abyHeader, sizeof(abyHeader) ) )
+    GByte abyHeader[512];
+    const int nHeaderBytes = static_cast<int>(VSIFRead( abyHeader, 1, sizeof(abyHeader), fp ));
+    if( !DGNTestOpen( abyHeader, nHeaderBytes ) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "File `%s' does not have expected DGN header.\n", 
+                  "File `%s' does not have expected DGN header.\n",
                   pszFilename );
         VSIFClose( fp );
         return NULL;
@@ -134,7 +133,7 @@ DGNHandle DGNOpen( const char * pszFilename, int bUpdate )
 /* -------------------------------------------------------------------- */
 /*      Create the info structure.                                      */
 /* -------------------------------------------------------------------- */
-    psDGN = (DGNInfo *) CPLCalloc(sizeof(DGNInfo),1);
+    DGNInfo *psDGN = (DGNInfo *) CPLCalloc(sizeof(DGNInfo),1);
     psDGN->fp = fp;
     psDGN->next_element_id = 0;
 
@@ -142,7 +141,7 @@ DGNHandle DGNOpen( const char * pszFilename, int bUpdate )
     psDGN->scale = 1.0;
     psDGN->origin_x = 0.0;
     psDGN->origin_y = 0.0;
-    psDGN->origin_z = 0.0;                                             
+    psDGN->origin_z = 0.0;
 
     psDGN->index_built = FALSE;
     psDGN->element_count = 0;
@@ -176,12 +175,12 @@ DGNHandle DGNOpen( const char * pszFilename, int bUpdate )
  * DGNO_CAPTURE_RAW_DATA: If this is enabled (it is off by default),
  * then the raw binary data associated with elements will be kept in
  * the raw_data field within the DGNElemCore when they are read.  This
- * is required if the application needs to interprete the raw data itself.
+ * is required if the application needs to interpret the raw data itself.
  * It is also necessary if the element is to be written back to this file,
  * or another file using DGNWriteElement().  Off by default (to conserve
- * memory). 
+ * memory).
  *
- * @param hDGN handle to file returned by DGNOpen(). 
+ * @param hDGN handle to file returned by DGNOpen().
  * @param nOptions ORed option flags.
  */
 
@@ -203,23 +202,23 @@ void DGNSetOptions( DGNHandle hDGN, int nOptions )
  * If a spatial filter is set with this function, DGNReadElement() will
  * only return spatial elements (elements with a known bounding box) and
  * only those elements for which this bounding box overlaps the requested
- * region. 
+ * region.
  *
  * If all four values (dfXMin, dfXMax, dfYMin and dfYMax) are zero, the
  * spatial filter is disabled.   Note that installing a spatial filter
  * won't reduce the amount of data read from disk.  All elements are still
- * scanned, but the amount of processing work for elements outside the 
- * spatial filter is minimized.  
+ * scanned, but the amount of processing work for elements outside the
+ * spatial filter is minimized.
  *
  * @param hDGN Handle from DGNOpen() for file to update.
  * @param dfXMin minimum x coordinate for extents (georeferenced coordinates).
  * @param dfYMin minimum y coordinate for extents (georeferenced coordinates).
  * @param dfXMax maximum x coordinate for extents (georeferenced coordinates).
  * @param dfYMax maximum y coordinate for extents (georeferenced coordinates).
- */ 
+ */
 
-void DGNSetSpatialFilter( DGNHandle hDGN, 
-                          double dfXMin, double dfYMin, 
+void DGNSetSpatialFilter( DGNHandle hDGN,
+                          double dfXMin, double dfYMin,
                           double dfXMax, double dfYMax )
 
 {
@@ -253,15 +252,15 @@ void DGNSpatialFilterToUOR( DGNInfo *psDGN )
 {
     DGNPoint    sMin, sMax;
 
-    if( psDGN->sf_converted_to_uor 
-        || !psDGN->has_spatial_filter 
+    if( psDGN->sf_converted_to_uor
+        || !psDGN->has_spatial_filter
         || !psDGN->got_tcb )
         return;
 
     sMin.x = psDGN->sf_min_x_geo;
     sMin.y = psDGN->sf_min_y_geo;
     sMin.z = 0;
-    
+
     sMax.x = psDGN->sf_max_x_geo;
     sMax.y = psDGN->sf_max_y_geo;
     sMax.z = 0;
@@ -282,7 +281,7 @@ void DGNSpatialFilterToUOR( DGNInfo *psDGN )
 /************************************************************************/
 
 /**
- * Close DGN file. 
+ * Close DGN file.
  *
  * @param hDGN Handle from DGNOpen() for file to close.
  */
diff --git a/ogr/ogrsf_frmts/dgn/dgnread.cpp b/ogr/ogrsf_frmts/dgn/dgnread.cpp
index aa31a4f..8a9609f 100644
--- a/ogr/ogrsf_frmts/dgn/dgnread.cpp
+++ b/ogr/ogrsf_frmts/dgn/dgnread.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dgnread.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: dgnread.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Microstation DGN Access Library
  * Purpose:  DGN Access Library element reading code.
@@ -29,7 +29,7 @@
 
 #include "dgnlibp.h"
 
-CPL_CVSID("$Id: dgnread.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: dgnread.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 static DGNElemCore *DGNParseTCB( DGNInfo * );
 static DGNElemCore *DGNParseColorTable( DGNInfo * );
@@ -43,15 +43,15 @@ static DGNElemCore *DGNParseTagSet( DGNInfo * );
 /**
  * Seek to indicated element.
  *
- * Changes what element will be read on the next call to DGNReadElement(). 
+ * Changes what element will be read on the next call to DGNReadElement().
  * Note that this function requires and index, and one will be built if
  * not already available.
  *
  * @param hDGN the file to affect.
  * @param element_id the element to seek to.  These values are sequentially
  * ordered starting at zero for the first element.
- * 
- * @return returns TRUE on success or FALSE on failure. 
+ *
+ * @return returns TRUE on success or FALSE on failure.
  */
 
 int DGNGotoElement( DGNHandle hDGN, int element_id )
@@ -64,7 +64,7 @@ int DGNGotoElement( DGNHandle hDGN, int element_id )
     if( element_id < 0 || element_id >= psDGN->element_count )
         return FALSE;
 
-    if( VSIFSeek( psDGN->fp, psDGN->element_index[element_id].offset, 
+    if( VSIFSeek( psDGN->fp, psDGN->element_index[element_id].offset,
                   SEEK_SET ) != 0 )
         return FALSE;
 
@@ -101,8 +101,10 @@ int DGNLoadRawElement( DGNInfo *psDGN, int *pnType, int *pnLevel )
 /* -------------------------------------------------------------------- */
 /*      Read the rest of the element data into the working buffer.      */
 /* -------------------------------------------------------------------- */
-    CPLAssert( nWords * 2 + 4 <= (int) sizeof(psDGN->abyElem) );
+    if( nWords * 2 + 4 > (int) sizeof(psDGN->abyElem) )
+        return FALSE;
 
+    /* coverity[tainted_data] */
     if( (int) VSIFRead( psDGN->abyElem + 4, 2, nWords, psDGN->fp ) != nWords )
         return FALSE;
 
@@ -115,10 +117,10 @@ int DGNLoadRawElement( DGNInfo *psDGN, int *pnType, int *pnLevel )
 /* -------------------------------------------------------------------- */
     if( pnType != NULL )
         *pnType = nType;
-    
+
     if( pnLevel != NULL )
         *pnLevel = nLevel;
-    
+
     return TRUE;
 }
 
@@ -126,16 +128,16 @@ int DGNLoadRawElement( DGNInfo *psDGN, int *pnType, int *pnLevel )
 /************************************************************************/
 /*                          DGNGetRawExtents()                          */
 /*                                                                      */
-/*      Returns FALSE if the element type does not have reconisable     */
+/*      Returns FALSE if the element type does not have recognizable    */
 /*      element extents, other TRUE and the extents will be updated.    */
 /*                                                                      */
 /*      It is assumed the raw element data has been loaded into the     */
 /*      working area by DGNLoadRawElement().                            */
 /************************************************************************/
 
-static int 
+static int
 DGNGetRawExtents( DGNInfo *psDGN, int nType, unsigned char *pabyRawData,
-                  GUInt32 *pnXMin, GUInt32 *pnYMin, GUInt32 *pnZMin, 
+                  GUInt32 *pnXMin, GUInt32 *pnYMin, GUInt32 *pnZMin,
                   GUInt32 *pnXMax, GUInt32 *pnYMax, GUInt32 *pnZMax )
 
 {
@@ -186,27 +188,27 @@ DGNGetRawExtents( DGNInfo *psDGN, int nType, unsigned char *pabyRawData,
  *
  * This function will return the extents of the passed element if possible.
  * The extents are extracted from the element header if it contains them,
- * and transformed into master georeferenced format.  Some element types 
- * do not have extents at all and will fail.  
+ * and transformed into master georeferenced format.  Some element types
+ * do not have extents at all and will fail.
  *
  * This call will also fail if the extents raw data for the element is not
  * available.  This will occur if it was not the most recently read element,
- * and if the raw_data field is not loaded. 
+ * and if the raw_data field is not loaded.
  *
  * @param hDGN the handle of the file to read from.
  *
  * @param psElement the element to extract extents from.
  *
- * @param psMin structure loaded with X, Y and Z minimum values for the 
- * extent. 
+ * @param psMin structure loaded with X, Y and Z minimum values for the
+ * extent.
  *
- * @param psMax structure loaded with X, Y and Z maximum values for the 
- * extent. 
+ * @param psMax structure loaded with X, Y and Z maximum values for the
+ * extent.
  *
- * @return TRUE on success of FALSE if extracting extents fails. 
+ * @return TRUE on success of FALSE if extracting extents fails.
  */
 
-int DGNGetElementExtents( DGNHandle hDGN, DGNElemCore *psElement, 
+int DGNGetElementExtents( DGNHandle hDGN, DGNElemCore *psElement,
                           DGNPoint *psMin, DGNPoint *psMax )
 
 {
@@ -219,18 +221,18 @@ int DGNGetElementExtents( DGNHandle hDGN, DGNElemCore *psElement,
 /*      loaded in the file buffer.                                      */
 /* -------------------------------------------------------------------- */
     if( psElement->raw_data != NULL )
-        bResult = DGNGetRawExtents( psDGN, psElement->type, 
-                                    psElement->raw_data, 
+        bResult = DGNGetRawExtents( psDGN, psElement->type,
+                                    psElement->raw_data,
                                     anMin + 0, anMin + 1, anMin + 2,
                                     anMax + 0, anMax + 1, anMax + 2 );
     else if( psElement->element_id == psDGN->next_element_id - 1 )
-        bResult = DGNGetRawExtents( psDGN, psElement->type, 
-                                    psDGN->abyElem + 0, 
+        bResult = DGNGetRawExtents( psDGN, psElement->type,
+                                    psDGN->abyElem + 0,
                                     anMin + 0, anMin + 1, anMin + 2,
                                     anMax + 0, anMax + 1, anMax + 2 );
     else
     {
-        CPLError(CE_Warning, CPLE_AppDefined, 
+        CPLError(CE_Warning, CPLE_AppDefined,
                  "DGNGetElementExtents() fails because the requested element\n"
                  " does not have raw data available." );
         return FALSE;
@@ -278,7 +280,7 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
       {
           DGNElemCellHeader *psCell;
 
-          psCell = (DGNElemCellHeader *) 
+          psCell = (DGNElemCellHeader *)
               CPLCalloc(sizeof(DGNElemCellHeader),1);
           psElement = (DGNElemCore *) psCell;
           psElement->stype = DGNST_CELL_HEADER;
@@ -286,9 +288,9 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
 
           psCell->totlength = psDGN->abyElem[36] + psDGN->abyElem[37] * 256;
 
-          DGNRad50ToAscii( psDGN->abyElem[38] + psDGN->abyElem[39] * 256, 
+          DGNRad50ToAscii( psDGN->abyElem[38] + psDGN->abyElem[39] * 256,
                            psCell->name + 0 );
-          DGNRad50ToAscii( psDGN->abyElem[40] + psDGN->abyElem[41] * 256, 
+          DGNRad50ToAscii( psDGN->abyElem[40] + psDGN->abyElem[41] * 256,
                            psCell->name + 3 );
 
           psCell->cclass = psDGN->abyElem[42] + psDGN->abyElem[43] * 256;
@@ -306,11 +308,11 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
 
               psCell->trans[0] =
                 1.0 * DGN_INT32( psDGN->abyElem + 68 ) / (1<<31);
-              psCell->trans[1] = 
+              psCell->trans[1] =
                 1.0 * DGN_INT32( psDGN->abyElem + 72 ) / (1<<31);
-              psCell->trans[2] = 
+              psCell->trans[2] =
                 1.0 * DGN_INT32( psDGN->abyElem + 76 ) / (1<<31);
-              psCell->trans[3] = 
+              psCell->trans[3] =
                 1.0 * DGN_INT32( psDGN->abyElem + 80 ) / (1<<31);
 
               psCell->origin.x = DGN_INT32( psDGN->abyElem + 84 );
@@ -324,7 +326,7 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
               d = DGN_INT32( psDGN->abyElem + 80 );
               a2 = a * a;
               c2 = c * c;
-              
+
               psCell->xscale = sqrt(a2 + c2) / 214748;
               psCell->yscale = sqrt(b*b + d*d) / 214748;
               if( (a2 + c2) <= 0.0 )
@@ -333,9 +335,9 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
                   psCell->rotation = acos(a / sqrt(a2 + c2));
 
               if (b <= 0)
-                  psCell->rotation = psCell->rotation * 180 / PI;
+                  psCell->rotation = psCell->rotation * 180 / M_PI;
               else
-                  psCell->rotation = 360 - psCell->rotation * 180 / PI;
+                  psCell->rotation = 360 - psCell->rotation * 180 / M_PI;
               }
           }
           else
@@ -349,21 +351,21 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
 
               psCell->trans[0] =
                 1.0 * DGN_INT32( psDGN->abyElem + 76 ) / (1<<31);
-              psCell->trans[1] = 
+              psCell->trans[1] =
                 1.0 * DGN_INT32( psDGN->abyElem + 80 ) / (1<<31);
-              psCell->trans[2] = 
+              psCell->trans[2] =
                 1.0 * DGN_INT32( psDGN->abyElem + 84 ) / (1<<31);
-              psCell->trans[3] = 
+              psCell->trans[3] =
                 1.0 * DGN_INT32( psDGN->abyElem + 88 ) / (1<<31);
-              psCell->trans[4] = 
+              psCell->trans[4] =
                 1.0 * DGN_INT32( psDGN->abyElem + 92 ) / (1<<31);
-              psCell->trans[5] = 
+              psCell->trans[5] =
                 1.0 * DGN_INT32( psDGN->abyElem + 96 ) / (1<<31);
-              psCell->trans[6] = 
+              psCell->trans[6] =
                 1.0 * DGN_INT32( psDGN->abyElem + 100 ) / (1<<31);
-              psCell->trans[7] = 
+              psCell->trans[7] =
                 1.0 * DGN_INT32( psDGN->abyElem + 104 ) / (1<<31);
-              psCell->trans[8] = 
+              psCell->trans[8] =
                 1.0 * DGN_INT32( psDGN->abyElem + 108 ) / (1<<31);
 
               psCell->origin.x = DGN_INT32( psDGN->abyElem + 112 );
@@ -382,18 +384,18 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
           DGNElemCellLibrary *psCell;
           int                 iWord;
 
-          psCell = (DGNElemCellLibrary *) 
+          psCell = (DGNElemCellLibrary *)
               CPLCalloc(sizeof(DGNElemCellLibrary),1);
           psElement = (DGNElemCore *) psCell;
           psElement->stype = DGNST_CELL_LIBRARY;
           DGNParseCore( psDGN, psElement );
 
-          DGNRad50ToAscii( psDGN->abyElem[32] + psDGN->abyElem[33] * 256, 
+          DGNRad50ToAscii( psDGN->abyElem[32] + psDGN->abyElem[33] * 256,
                            psCell->name + 0 );
-          DGNRad50ToAscii( psDGN->abyElem[34] + psDGN->abyElem[35] * 256, 
+          DGNRad50ToAscii( psDGN->abyElem[34] + psDGN->abyElem[35] * 256,
                            psCell->name + 3 );
 
-          psElement->properties = psDGN->abyElem[38] 
+          psElement->properties = psDGN->abyElem[38]
               + psDGN->abyElem[39] * 256;
 
           psCell->dispsymb = psDGN->abyElem[40] + psDGN->abyElem[41] * 256;
@@ -407,13 +409,13 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
           psCell->numwords = psDGN->abyElem[36] + psDGN->abyElem[37] * 256;
 
           memset( psCell->description, 0, sizeof(psCell->description) );
-          
+
           for( iWord = 0; iWord < 9; iWord++ )
           {
               int iOffset = 52 + iWord * 2;
 
-              DGNRad50ToAscii( psDGN->abyElem[iOffset] 
-                               + psDGN->abyElem[iOffset+1] * 256, 
+              DGNRad50ToAscii( psDGN->abyElem[iOffset]
+                               + psDGN->abyElem[iOffset+1] * 256,
                                psCell->description + iWord * 3 );
           }
       }
@@ -423,7 +425,7 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
       {
           DGNElemMultiPoint *psLine;
 
-          psLine = (DGNElemMultiPoint *) 
+          psLine = (DGNElemMultiPoint *)
               CPLCalloc(sizeof(DGNElemMultiPoint),1);
           psElement = (DGNElemCore *) psLine;
           psElement->stype = DGNST_MULTIPOINT;
@@ -461,7 +463,12 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
           int                pntsize = psDGN->dimension * 4;
 
           count = psDGN->abyElem[36] + psDGN->abyElem[37]*256;
-          psLine = (DGNElemMultiPoint *) 
+          if( count < 2 )
+          {
+              CPLError(CE_Failure, CPLE_AssertionFailed, "count < 2");
+              return NULL;
+          }
+          psLine = (DGNElemMultiPoint *)
               CPLCalloc(sizeof(DGNElemMultiPoint)+(count-2)*sizeof(DGNPoint),1);
           psElement = (DGNElemCore *) psLine;
           psElement->stype = DGNST_MULTIPOINT;
@@ -469,22 +476,29 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
 
           if( psDGN->nElemBytes < 38 + count * pntsize )
           {
-              CPLError( CE_Warning, CPLE_AppDefined, 
+              int new_count = (psDGN->nElemBytes - 38) / pntsize;
+              if( new_count < 0 )
+              {
+                  CPLError(CE_Failure, CPLE_AssertionFailed, "new_count < 2");
+                  DGNFreeElement(psDGN, psElement);
+                  return NULL;
+              }
+              CPLError( CE_Warning, CPLE_AppDefined,
                         "Trimming multipoint vertices to %d from %d because\n"
-                        "element is short.\n", 
-                        (psDGN->nElemBytes - 38) / pntsize,
+                        "element is short.\n",
+                        new_count,
                         count );
-              count = (psDGN->nElemBytes - 38) / pntsize;
+              count = new_count;
           }
           psLine->num_vertices = count;
           for( i = 0; i < psLine->num_vertices; i++ )
           {
-              psLine->vertices[i].x = 
+              psLine->vertices[i].x =
                   DGN_INT32( psDGN->abyElem + 38 + i*pntsize );
-              psLine->vertices[i].y = 
+              psLine->vertices[i].y =
                   DGN_INT32( psDGN->abyElem + 42 + i*pntsize );
               if( psDGN->dimension == 3 )
-                  psLine->vertices[i].z = 
+                  psLine->vertices[i].z =
                       DGN_INT32( psDGN->abyElem + 46 + i*pntsize );
 
               DGNTransformPoint( psDGN, psLine->vertices + i );
@@ -568,10 +582,10 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
           {
               psEllipse->rotation = DGN_INT32( psDGN->abyElem + 52 );
               psEllipse->rotation = psEllipse->rotation / 360000.0;
-              
+
               memcpy( &(psEllipse->origin.x), psDGN->abyElem + 56, 8 );
               DGN2IEEEDouble( &(psEllipse->origin.x) );
-              
+
               memcpy( &(psEllipse->origin.y), psDGN->abyElem + 64, 8 );
               DGN2IEEEDouble( &(psEllipse->origin.y) );
           }
@@ -581,10 +595,10 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
 
               memcpy( &(psEllipse->origin.x), psDGN->abyElem + 68, 8 );
               DGN2IEEEDouble( &(psEllipse->origin.x) );
-              
+
               memcpy( &(psEllipse->origin.y), psDGN->abyElem + 76, 8 );
               DGN2IEEEDouble( &(psEllipse->origin.y) );
-              
+
               memcpy( &(psEllipse->origin.z), psDGN->abyElem + 84, 8 );
               DGN2IEEEDouble( &(psEllipse->origin.z) );
 
@@ -625,7 +639,7 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
               psEllipse->sweepang = 360.0;
           else
               psEllipse->sweepang = nSweepVal / 360000.0;
-          
+
           memcpy( &(psEllipse->primary_axis), psDGN->abyElem + 44, 8 );
           DGN2IEEEDouble( &(psEllipse->primary_axis) );
           psEllipse->primary_axis *= psDGN->scale;
@@ -633,26 +647,26 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
           memcpy( &(psEllipse->secondary_axis), psDGN->abyElem + 52, 8 );
           DGN2IEEEDouble( &(psEllipse->secondary_axis) );
           psEllipse->secondary_axis *= psDGN->scale;
-          
+
           if( psDGN->dimension == 2 )
           {
               psEllipse->rotation = DGN_INT32( psDGN->abyElem + 60 );
               psEllipse->rotation = psEllipse->rotation / 360000.0;
-          
+
               memcpy( &(psEllipse->origin.x), psDGN->abyElem + 64, 8 );
               DGN2IEEEDouble( &(psEllipse->origin.x) );
-              
+
               memcpy( &(psEllipse->origin.y), psDGN->abyElem + 72, 8 );
               DGN2IEEEDouble( &(psEllipse->origin.y) );
           }
-          else 
+          else
           {
               /* for now we don't try to handle quaternion */
               psEllipse->rotation = 0;
-          
+
               memcpy( &(psEllipse->origin.x), psDGN->abyElem + 76, 8 );
               DGN2IEEEDouble( &(psEllipse->origin.x) );
-              
+
               memcpy( &(psEllipse->origin.y), psDGN->abyElem + 84, 8 );
               DGN2IEEEDouble( &(psEllipse->origin.y) );
 
@@ -713,19 +727,19 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
           DGNTransformPoint( psDGN, &(psText->origin) );
 
           /* experimental multibyte support from Ason Kang (hiska at netian.com)*/
-          if (*(psDGN->abyElem + text_off) == 0xFF 
-              && *(psDGN->abyElem + text_off + 1) == 0xFD) 
+          if (*(psDGN->abyElem + text_off) == 0xFF
+              && *(psDGN->abyElem + text_off + 1) == 0xFD)
           {
               int n=0;
               for (int i=0;i<num_chars/2-1;i++) {
                   unsigned short w;
                   memcpy(&w,psDGN->abyElem + text_off + 2 + i*2 ,2);
                   w = CPL_LSBWORD16(w);
-                  if (w<256) { // if alpa-numeric code area : Normal character 
-                      *(psText->string + n) = (char) (w & 0xFF); 
+                  if (w<256) { // if alpa-numeric code area : Normal character
+                      *(psText->string + n) = (char) (w & 0xFF);
                       n++; // skip 1 byte;
                   }
-                  else { // if extend code area : 2 byte Korean character 
+                  else { // if extend code area : 2 byte Korean character
                       *(psText->string + n)     = (char) (w >> 8);   // hi
                       *(psText->string + n + 1) = (char) (w & 0xFF); // lo
                       n+=2; // 2 byte
@@ -750,7 +764,7 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
       {
           DGNElemComplexHeader *psHdr;
 
-          psHdr = (DGNElemComplexHeader *) 
+          psHdr = (DGNElemComplexHeader *)
               CPLCalloc(sizeof(DGNElemComplexHeader),1);
           psElement = (DGNElemCore *) psHdr;
           psElement->stype = DGNST_COMPLEX_HEADER;
@@ -765,7 +779,7 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
       {
           DGNElemTagValue *psTag;
 
-          psTag = (DGNElemTagValue *) 
+          psTag = (DGNElemTagValue *)
               CPLCalloc(sizeof(DGNElemTagValue),1);
           psElement = (DGNElemCore *) psTag;
           psElement->stype = DGNST_TAG_VALUE;
@@ -779,19 +793,19 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
 
           if( psTag->tagType == 1 )
           {
-              psTag->tagValue.string = 
+              psTag->tagValue.string =
                   CPLStrdup( (char *) psDGN->abyElem + 154 );
           }
           else if( psTag->tagType == 3 )
           {
-              memcpy( &(psTag->tagValue.integer), 
+              memcpy( &(psTag->tagValue.integer),
                       psDGN->abyElem + 154, 4 );
-              psTag->tagValue.integer = 
+              psTag->tagValue.integer =
                   CPL_LSBWORD32( psTag->tagValue.integer );
           }
           else if( psTag->tagType == 4 )
           {
-              memcpy( &(psTag->tagValue.real), 
+              memcpy( &(psTag->tagValue.real),
                       psDGN->abyElem + 154, 8 );
               DGN2IEEEDouble( &(psTag->tagValue.real) );
           }
@@ -815,18 +829,23 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
         {
           DGNElemCone *psCone;
 
+          if( psDGN->dimension != 3 )
+          {
+              CPLError(CE_Failure, CPLE_AssertionFailed, "psDGN->dimension != 3");
+              return NULL;
+          }
+
           psCone = (DGNElemCone *) CPLCalloc(sizeof(DGNElemCone),1);
           psElement = (DGNElemCore *) psCone;
           psElement->stype = DGNST_CONE;
           DGNParseCore( psDGN, psElement );
 
-          CPLAssert( psDGN->dimension == 3 );
           psCone->unknown = psDGN->abyElem[36] + psDGN->abyElem[37] * 256;
           psCone->quat[0] = DGN_INT32( psDGN->abyElem + 38 );
           psCone->quat[1] = DGN_INT32( psDGN->abyElem + 42 );
           psCone->quat[2] = DGN_INT32( psDGN->abyElem + 46 );
           psCone->quat[3] = DGN_INT32( psDGN->abyElem + 50 );
- 
+
           memcpy( &(psCone->center_1.x), psDGN->abyElem + 54, 8 );
           DGN2IEEEDouble( &(psCone->center_1.x) );
           memcpy( &(psCone->center_1.y), psDGN->abyElem + 62, 8 );
@@ -857,7 +876,7 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
         {
           DGNElemComplexHeader *psShape;
 
-          psShape = 
+          psShape =
             (DGNElemComplexHeader *) CPLCalloc(sizeof(DGNElemComplexHeader),1);
           psElement = (DGNElemCore *) psShape;
           psElement->stype = DGNST_COMPLEX_HEADER;
@@ -881,7 +900,7 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
           DGNParseCore( psDGN, psElement );
 
           // Read B-Spline surface header
-          psSpline->desc_words = DGN_INT32(psDGN->abyElem + 36);
+          psSpline->desc_words = static_cast<long>(DGN_INT32(psDGN->abyElem + 36));
           psSpline->curve_type = psDGN->abyElem[41];
 
           // U
@@ -912,7 +931,7 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
           DGNParseCore( psDGN, psElement );
 
           // Read B-Spline curve header
-          psSpline->desc_words = DGN_INT32(psDGN->abyElem + 36);
+          psSpline->desc_words = static_cast<long>(DGN_INT32(psDGN->abyElem + 36));
 
           // flags
           psSpline->order = (psDGN->abyElem[40] & 0x0f) + 2;
@@ -927,6 +946,11 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
         {
           DGNElemBSplineSurfaceBoundary *psBounds;
           short numverts = psDGN->abyElem[38] + psDGN->abyElem[39]*256;
+          if( numverts <= 0 )
+          {
+              CPLError(CE_Failure, CPLE_AssertionFailed, "numverts <= 0");
+              return NULL;
+          }
 
           psBounds = (DGNElemBSplineSurfaceBoundary *)
             CPLCalloc(sizeof(DGNElemBSplineSurfaceBoundary)+
@@ -952,7 +976,7 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
           DGNElemKnotWeight *psArray;
           // FIXME: Is it OK to assume that the # of elements corresponds
           // directly to the element size? kintel 20051215.
-          int attr_bytes = psDGN->nElemBytes - 
+          int attr_bytes = psDGN->nElemBytes -
             (psDGN->abyElem[30] + psDGN->abyElem[31]*256)*2 - 32;
           int numelems = (psDGN->nElemBytes - 36 - attr_bytes)/4;
 
@@ -974,7 +998,7 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
       {
           DGNElemSharedCellDefn *psShared;
 
-          psShared = (DGNElemSharedCellDefn *) 
+          psShared = (DGNElemSharedCellDefn *)
               CPLCalloc(sizeof(DGNElemSharedCellDefn),1);
           psElement = (DGNElemCore *) psShared;
           psElement->stype = DGNST_SHARED_CELL_DEFN;
@@ -997,7 +1021,7 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
 /*      in "capture all" mode, record the complete binary image of      */
 /*      the element.                                                    */
 /* -------------------------------------------------------------------- */
-    if( psElement->stype == DGNST_CORE 
+    if( psElement->stype == DGNST_CORE
         || (psDGN->options & DGNO_CAPTURE_RAW_DATA) )
     {
         psElement->raw_bytes = psDGN->nElemBytes;
@@ -1011,7 +1035,7 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
 /* -------------------------------------------------------------------- */
     psElement->element_id = psDGN->next_element_id - 1;
 
-    psElement->offset = VSIFTell( psDGN->fp ) - psDGN->nElemBytes;
+    psElement->offset = static_cast<int>(VSIFTell( psDGN->fp )) - psDGN->nElemBytes;
     psElement->size = psDGN->nElemBytes;
 
     return psElement;
@@ -1025,12 +1049,12 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
  * Read a DGN element.
  *
  * This function will return the next element in the file, starting with the
- * first.  It is affected by DGNGotoElement() calls. 
+ * first.  It is affected by DGNGotoElement() calls.
  *
- * The element is read into a structure which includes the DGNElemCore 
+ * The element is read into a structure which includes the DGNElemCore
  * structure.  It is expected that applications will inspect the stype
  * field of the returned DGNElemCore and use it to cast the pointer to the
- * appropriate element structure type such as DGNElemMultiPoint. 
+ * appropriate element structure type such as DGNElemMultiPoint.
  *
  * @param hDGN the handle of the file to read from.
  *
@@ -1051,16 +1075,16 @@ DGNElemCore *DGNReadElement( DGNHandle hDGN )
 /*      filter is in effect, loop until we get something within our     */
 /*      spatial constraints.                                            */
 /* -------------------------------------------------------------------- */
-    do { 
+    do {
         bInsideFilter = TRUE;
 
         if( !DGNLoadRawElement( psDGN, &nType, &nLevel ) )
             return NULL;
-        
+
         if( psDGN->has_spatial_filter )
         {
             GUInt32     nXMin, nXMax, nYMin, nYMax;
-            
+
             if( !psDGN->sf_converted_to_uor )
                 DGNSpatialFilterToUOR( psDGN );
 
@@ -1068,7 +1092,7 @@ DGNElemCore *DGNReadElement( DGNHandle hDGN )
                                    &nXMin, &nYMin, NULL,
                                    &nXMax, &nYMax, NULL ) )
             {
-                /* If we don't have spatial characterists for the element
+                /* If we don't have spatial characteristics for the element
                    we will pass it through. */
                 bInsideFilter = TRUE;
             }
@@ -1113,10 +1137,10 @@ DGNElemCore *DGNReadElement( DGNHandle hDGN )
 /**
  * Does element type have display header.
  *
- * @param nElemType element type (0-63) to test. 
+ * @param nElemType element type (0-63) to test.
  *
  * @return TRUE if elements of passed in type have a display header after the
- * core element header, or FALSE otherwise. 
+ * core element header, or FALSE otherwise.
  */
 
 int DGNElemTypeHasDispHdr( int nElemType )
@@ -1140,7 +1164,7 @@ int DGNElemTypeHasDispHdr( int nElemType )
       case 62:
       case 63:
         return FALSE;
-        
+
       default:
         return TRUE;
     }
@@ -1181,13 +1205,13 @@ int DGNParseCore( DGNInfo *psDGN, DGNElemCore *psElement )
     if( psElement->properties & DGNPF_ATTRIBUTES )
     {
         int   nAttIndex;
-        
+
         nAttIndex = psData[30] + psData[31] * 256;
 
         psElement->attr_bytes = psDGN->nElemBytes - nAttIndex*2 - 32;
         if( psElement->attr_bytes > 0 )
         {
-            psElement->attr_data = (unsigned char *) 
+            psElement->attr_data = (unsigned char *)
                 CPLMalloc(psElement->attr_bytes);
             memcpy( psElement->attr_data, psData + nAttIndex * 2 + 32,
                     psElement->attr_bytes );
@@ -1195,14 +1219,14 @@ int DGNParseCore( DGNInfo *psDGN, DGNElemCore *psElement )
         else
         {
             CPLError(
-                CE_Warning, CPLE_AppDefined, 
+                CE_Warning, CPLE_AppDefined,
                 "Computed %d bytes for attribute info on element,\n"
                 "perhaps this element type doesn't really have a disphdr?",
                 psElement->attr_bytes );
             psElement->attr_bytes = 0;
         }
     }
-    
+
     return TRUE;
 }
 
@@ -1215,28 +1239,28 @@ static DGNElemCore *DGNParseColorTable( DGNInfo * psDGN )
 {
     DGNElemCore *psElement;
     DGNElemColorTable  *psColorTable;
-            
-    psColorTable = (DGNElemColorTable *) 
+
+    psColorTable = (DGNElemColorTable *)
         CPLCalloc(sizeof(DGNElemColorTable),1);
     psElement = (DGNElemCore *) psColorTable;
     psElement->stype = DGNST_COLORTABLE;
 
     DGNParseCore( psDGN, psElement );
 
-    psColorTable->screen_flag = 
+    psColorTable->screen_flag =
         psDGN->abyElem[36] + psDGN->abyElem[37] * 256;
 
     memcpy( psColorTable->color_info[255], psDGN->abyElem+38, 3 );
-    memcpy( psColorTable->color_info, psDGN->abyElem+41, 765 ); 
+    memcpy( psColorTable->color_info, psDGN->abyElem+41, 765 );
 
     // We used to only install a color table as the default color
     // table if it was the first in the file.  But apparently we should
     // really be using the last one.  This doesn't necessarily accomplish
     // that either if the elements are being read out of order but it will
-    // usually do better at least. 
+    // usually do better at least.
     memcpy( psDGN->color_table, psColorTable->color_info, 768 );
     psDGN->got_color_table = 1;
-    
+
     return psElement;
 }
 
@@ -1249,8 +1273,9 @@ static DGNElemCore *DGNParseTagSet( DGNInfo * psDGN )
 {
     DGNElemCore *psElement;
     DGNElemTagSet *psTagSet;
-    int          nDataOffset, iTag;
-            
+    size_t      nDataOffset;
+    int         iTag;
+
     psTagSet = (DGNElemTagSet *) CPLCalloc(sizeof(DGNElemTagSet),1);
     psElement = (DGNElemCore *) psTagSet;
     psElement->stype = DGNST_TAG_SET;
@@ -1260,9 +1285,9 @@ static DGNElemCore *DGNParseTagSet( DGNInfo * psDGN )
 /* -------------------------------------------------------------------- */
 /*      Parse the overall information.                                  */
 /* -------------------------------------------------------------------- */
-    psTagSet->tagCount = 
+    psTagSet->tagCount =
         psDGN->abyElem[44] + psDGN->abyElem[45] * 256;
-    psTagSet->flags = 
+    psTagSet->flags =
         psDGN->abyElem[46] + psDGN->abyElem[47] * 256;
     psTagSet->tagSetName = CPLStrdup( (const char *) (psDGN->abyElem + 48) );
 
@@ -1271,7 +1296,7 @@ static DGNElemCore *DGNParseTagSet( DGNInfo * psDGN )
 /* -------------------------------------------------------------------- */
     psTagSet->tagSet = -1;
 
-    if( psElement->attr_bytes >= 8 
+    if( psElement->attr_bytes >= 8
         && psElement->attr_data[0] == 0x03
         && psElement->attr_data[1] == 0x10
         && psElement->attr_data[2] == 0x2f
@@ -1282,16 +1307,22 @@ static DGNElemCore *DGNParseTagSet( DGNInfo * psDGN )
 /* -------------------------------------------------------------------- */
 /*      Parse each of the tag definitions.                              */
 /* -------------------------------------------------------------------- */
-    psTagSet->tagList = (DGNTagDef *) 
-        CPLMalloc(sizeof(DGNTagDef) * psTagSet->tagCount);
+    psTagSet->tagList = (DGNTagDef *)
+        CPLCalloc(sizeof(DGNTagDef), psTagSet->tagCount);
 
-    nDataOffset = 48 + strlen(psTagSet->tagSetName) + 1 + 1; 
+    nDataOffset = 48 + strlen(psTagSet->tagSetName) + 1 + 1;
 
     for( iTag = 0; iTag < psTagSet->tagCount; iTag++ )
     {
         DGNTagDef *tagDef = psTagSet->tagList + iTag;
 
-        CPLAssert( nDataOffset < psDGN->nElemBytes );
+        if( nDataOffset >= static_cast<size_t>(psDGN->nElemBytes) )
+        {
+            CPLError(CE_Failure, CPLE_AssertionFailed,
+                     "nDataOffset >= static_cast<size_t>(psDGN->nElemBytes)");
+            DGNFreeElement(psDGN, psElement);
+            return NULL;
+        }
 
         /* collect tag name. */
         tagDef->name = CPLStrdup( (char *) psDGN->abyElem + nDataOffset );
@@ -1318,21 +1349,21 @@ static DGNElemCore *DGNParseTagSet( DGNInfo * psDGN )
         /* Get the default */
         if( tagDef->type == 1 )
         {
-            tagDef->defaultValue.string = 
+            tagDef->defaultValue.string =
                 CPLStrdup( (char *) psDGN->abyElem + nDataOffset );
             nDataOffset += strlen(tagDef->defaultValue.string)+1;
         }
         else if( tagDef->type == 3 || tagDef->type == 5 )
         {
-            memcpy( &(tagDef->defaultValue.integer), 
+            memcpy( &(tagDef->defaultValue.integer),
                     psDGN->abyElem + nDataOffset, 4 );
-            tagDef->defaultValue.integer = 
+            tagDef->defaultValue.integer =
                 CPL_LSBWORD32( tagDef->defaultValue.integer );
             nDataOffset += 4;
         }
         else if( tagDef->type == 4 )
         {
-            memcpy( &(tagDef->defaultValue.real), 
+            memcpy( &(tagDef->defaultValue.real),
                     psDGN->abyElem + nDataOffset, 8 );
             DGN2IEEEDouble( &(tagDef->defaultValue.real) );
             nDataOffset += 8;
@@ -1363,14 +1394,14 @@ static DGNElemCore *DGNParseTCB( DGNInfo * psDGN )
         psTCB->dimension = 3;
     else
         psTCB->dimension = 2;
-          
-    psTCB->subunits_per_master = DGN_INT32( psDGN->abyElem + 1112 );
+
+    psTCB->subunits_per_master = static_cast<long>(DGN_INT32( psDGN->abyElem + 1112 ));
 
     psTCB->master_units[0] = (char) psDGN->abyElem[1120];
     psTCB->master_units[1] = (char) psDGN->abyElem[1121];
     psTCB->master_units[2] = '\0';
 
-    psTCB->uor_per_subunit = DGN_INT32( psDGN->abyElem + 1116 );
+    psTCB->uor_per_subunit = static_cast<long>(DGN_INT32( psDGN->abyElem + 1116 ));
 
     psTCB->sub_units[0] = (char) psDGN->abyElem[1122];
     psTCB->sub_units[1] = (char) psDGN->abyElem[1123];
@@ -1390,11 +1421,11 @@ static DGNElemCore *DGNParseTCB( DGNInfo * psDGN )
     if( psTCB->uor_per_subunit != 0
         && psTCB->subunits_per_master != 0 )
     {
-        psTCB->origin_x = psTCB->origin_x / 
+        psTCB->origin_x = psTCB->origin_x /
             (psTCB->uor_per_subunit * psTCB->subunits_per_master);
-        psTCB->origin_y = psTCB->origin_y / 
+        psTCB->origin_y = psTCB->origin_y /
             (psTCB->uor_per_subunit * psTCB->subunits_per_master);
-        psTCB->origin_z = psTCB->origin_z / 
+        psTCB->origin_z = psTCB->origin_z /
             (psTCB->uor_per_subunit * psTCB->subunits_per_master);
     }
 
@@ -1408,7 +1439,7 @@ static DGNElemCore *DGNParseTCB( DGNInfo * psDGN )
 
         if( psTCB->uor_per_subunit != 0
             && psTCB->subunits_per_master != 0 )
-            psDGN->scale = 1.0 
+            psDGN->scale = 1.0
                 / (psTCB->uor_per_subunit * psTCB->subunits_per_master);
     }
 
@@ -1421,7 +1452,7 @@ static DGNElemCore *DGNParseTCB( DGNInfo * psDGN )
 
         psView->flags = pabyRawView[0] + pabyRawView[1] * 256;
         memcpy( psView->levels, pabyRawView + 2, 8 );
-        
+
         psView->origin.x = DGN_INT32( pabyRawView + 10 );
         psView->origin.y = DGN_INT32( pabyRawView + 14 );
         psView->origin.z = DGN_INT32( pabyRawView + 18 );
@@ -1443,7 +1474,7 @@ static DGNElemCore *DGNParseTCB( DGNInfo * psDGN )
         memcpy( &(psView->conversion), pabyRawView + 106, sizeof(double) );
         DGN2IEEEDouble( &(psView->conversion) );
 
-        psView->activez = DGN_INT32( pabyRawView + 114 );
+        psView->activez = static_cast<unsigned long>(DGN_INT32( pabyRawView + 114 ));
     }
 
     return psElement;
@@ -1457,7 +1488,7 @@ static DGNElemCore *DGNParseTCB( DGNInfo * psDGN )
  * Free an element structure.
  *
  * This function will deallocate all resources associated with any element
- * structure returned by DGNReadElement(). 
+ * structure returned by DGNReadElement().
  *
  * @param hDGN handle to file from which the element was read.
  * @param psElement the element structure returned by DGNReadElement().
@@ -1504,7 +1535,7 @@ void DGNFreeElement( CPL_UNUSED DGNHandle hDGN, DGNElemCore *psElement )
 /**
  * Rewind element reading.
  *
- * Rewind the indicated DGN file, so the next element read with 
+ * Rewind the indicated DGN file, so the next element read with
  * DGNReadElement() will be the first.  Does not require indexing like
  * the more general DGNReadElement() function.
  *
@@ -1565,14 +1596,15 @@ void DGNInverseTransformPointToInt( DGNInfo *psDGN, DGNPoint *psPoint,
     adfCT[1] = (psPoint->y + psDGN->origin_y) / psDGN->scale;
     adfCT[2] = (psPoint->z + psDGN->origin_z) / psDGN->scale;
 
-    for( i = 0; i < psDGN->dimension; i++ )
+    const int nIter = MIN(3, psDGN->dimension);
+    for( i = 0; i < nIter; i++ )
     {
         GInt32 nCTI;
         unsigned char *pabyCTI = (unsigned char *) &nCTI;
 
         nCTI = (GInt32) MAX(-2147483647,MIN(2147483647,adfCT[i]));
-        
-#ifdef WORDS_BIGENDIAN 
+
+#ifdef WORDS_BIGENDIAN
         pabyTarget[i*4+0] = pabyCTI[1];
         pabyTarget[i*4+1] = pabyCTI[0];
         pabyTarget[i*4+2] = pabyCTI[3];
@@ -1582,7 +1614,7 @@ void DGNInverseTransformPointToInt( DGNInfo *psDGN, DGNPoint *psPoint,
         pabyTarget[i*4+2] = pabyCTI[0];
         pabyTarget[i*4+1] = pabyCTI[3];
         pabyTarget[i*4+0] = pabyCTI[2];
-#endif        
+#endif
     }
 }
 
@@ -1591,11 +1623,11 @@ void DGNInverseTransformPointToInt( DGNInfo *psDGN, DGNPoint *psPoint,
 /************************************************************************/
 
 /**
- * Load TCB if not already loaded. 
+ * Load TCB if not already loaded.
  *
  * This function will load the TCB element if it is not already loaded.
  * It is used primarily to ensure the TCB is loaded before doing any operations
- * that require TCB values (like creating new elements). 
+ * that require TCB values (like creating new elements).
  *
  * @return FALSE on failure or TRUE on success.
  */
@@ -1613,7 +1645,7 @@ int DGNLoadTCB( DGNHandle hDGN )
         DGNElemCore *psElem = DGNReadElement( hDGN );
         if( psElem == NULL )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "DGNLoadTCB() - unable to find TCB in file." );
             return FALSE;
         }
@@ -1632,23 +1664,23 @@ int DGNLoadTCB( DGNHandle hDGN )
  *
  * This function will return an array with brief information about every
  * element in a DGN file.  It requires one pass through the entire file to
- * generate (this is not repeated on subsequent calls). 
+ * generate (this is not repeated on subsequent calls).
  *
- * The returned array of DGNElementInfo structures contain the level, type, 
+ * The returned array of DGNElementInfo structures contain the level, type,
  * stype, and other flags for each element in the file.  This can facilitate
  * application level code representing the number of elements of various types
- * effeciently. 
+ * efficiently.
  *
  * Note that while building the index requires one pass through the whole file,
- * it does not generally request much processing for each element. 
+ * it does not generally request much processing for each element.
  *
  * @param hDGN the file to get an index for.
- * @param pnElementCount the integer to put the total element count into. 
+ * @param pnElementCount the integer to put the total element count into.
  *
- * @return a pointer to an internal array of DGNElementInfo structures (there 
+ * @return a pointer to an internal array of DGNElementInfo structures (there
  * will be *pnElementCount entries in the array), or NULL on failure.  The
  * returned array should not be modified or freed, and will last only as long
- * as the DGN file remains open. 
+ * as the DGN file remains open.
  */
 
 const DGNElementInfo *DGNGetElementIndex( DGNHandle hDGN, int *pnElementCount )
@@ -1660,7 +1692,7 @@ const DGNElementInfo *DGNGetElementIndex( DGNHandle hDGN, int *pnElementCount )
 
     if( pnElementCount != NULL )
         *pnElementCount = psDGN->element_count;
-    
+
     return psDGN->element_index;
 }
 
@@ -1672,12 +1704,12 @@ const DGNElementInfo *DGNGetElementIndex( DGNHandle hDGN, int *pnElementCount )
  * Fetch overall file extents.
  *
  * The extents are collected for each element while building an index, so
- * if an index has not already been built, it will be built when 
- * DGNGetExtents() is called.  
- * 
+ * if an index has not already been built, it will be built when
+ * DGNGetExtents() is called.
+ *
  * The Z min/max values are generally meaningless (0 and 0xffffffff in uor
- * space). 
- * 
+ * space).
+ *
  * @param hDGN the file to get extents for.
  * @param padfExtents pointer to an array of six doubles into which are loaded
  * the values xmin, ymin, zmin, xmax, ymax, and zmax.
@@ -1699,13 +1731,13 @@ int DGNGetExtents( DGNHandle hDGN, double * padfExtents )
     sMin.x = psDGN->min_x - 2147483648.0;
     sMin.y = psDGN->min_y - 2147483648.0;
     sMin.z = psDGN->min_z - 2147483648.0;
-    
+
     DGNTransformPoint( psDGN, &sMin );
 
     padfExtents[0] = sMin.x;
     padfExtents[1] = sMin.y;
     padfExtents[2] = sMin.z;
-    
+
     sMax.x = psDGN->max_x - 2147483648.0;
     sMax.y = psDGN->max_y - 2147483648.0;
     sMax.z = psDGN->max_z - 2147483648.0;
@@ -1730,11 +1762,11 @@ void DGNBuildIndex( DGNInfo *psDGN )
     long nLastOffset;
     GUInt32 anRegion[6];
 
-    if( psDGN->index_built ) 
+    if( psDGN->index_built )
         return;
 
     psDGN->index_built = TRUE;
-    
+
     DGNRewind( psDGN );
 
     nMaxElements = 0;
@@ -1747,9 +1779,9 @@ void DGNBuildIndex( DGNInfo *psDGN )
         if( psDGN->element_count == nMaxElements )
         {
             nMaxElements = (int) (nMaxElements * 1.5) + 500;
-            
-            psDGN->element_index = (DGNElementInfo *) 
-                CPLRealloc( psDGN->element_index, 
+
+            psDGN->element_index = (DGNElementInfo *)
+                CPLRealloc( psDGN->element_index,
                             nMaxElements * sizeof(DGNElementInfo) );
         }
 
@@ -1778,13 +1810,13 @@ void DGNBuildIndex( DGNInfo *psDGN )
         }
         else if( nType == DGNT_ELLIPSE || nType == DGNT_ARC )
             psEI->stype = DGNST_ARC;
-        
-        else if( nType == DGNT_COMPLEX_SHAPE_HEADER 
+
+        else if( nType == DGNT_COMPLEX_SHAPE_HEADER
                  || nType == DGNT_COMPLEX_CHAIN_HEADER
                  || nType == DGNT_3DSURFACE_HEADER
                  || nType == DGNT_3DSOLID_HEADER)
             psEI->stype = DGNST_COMPLEX_HEADER;
-        
+
         else if( nType == DGNT_TEXT )
             psEI->stype = DGNST_TEXT;
 
@@ -1810,13 +1842,13 @@ void DGNBuildIndex( DGNInfo *psDGN )
             psEI->stype = DGNST_CORE;
 
         if( !(psEI->flags & DGNEIF_DELETED)
-            && !(psEI->flags & DGNEIF_COMPLEX) 
+            && !(psEI->flags & DGNEIF_COMPLEX)
             && DGNGetRawExtents( psDGN, nType, NULL,
                                  anRegion+0, anRegion+1, anRegion+2,
                                  anRegion+3, anRegion+4, anRegion+5 ) )
         {
 #ifdef notdef
-            printf( "panRegion[%d]=%.1f,%.1f,%.1f,%.1f,%.1f,%.1f\n", 
+            printf( "panRegion[%d]=%.1f,%.1f,%.1f,%.1f,%.1f,%.1f\n",
                     psDGN->element_count,
                     anRegion[0] - 2147483648.0,
                     anRegion[1] - 2147483648.0,
@@ -1824,7 +1856,7 @@ void DGNBuildIndex( DGNInfo *psDGN )
                     anRegion[3] - 2147483648.0,
                     anRegion[4] - 2147483648.0,
                     anRegion[5] - 2147483648.0 );
-#endif            
+#endif
             if( psDGN->got_bounds )
             {
                 psDGN->min_x = MIN(psDGN->min_x, anRegion[0]);
@@ -1836,7 +1868,12 @@ void DGNBuildIndex( DGNInfo *psDGN )
             }
             else
             {
-                memcpy( &(psDGN->min_x), anRegion, sizeof(GInt32) * 6 );
+                psDGN->min_x = anRegion[0];
+                psDGN->min_y = anRegion[1];
+                psDGN->min_z = anRegion[2];
+                psDGN->max_x = anRegion[3];
+                psDGN->max_y = anRegion[4];
+                psDGN->max_z = anRegion[5];
                 psDGN->got_bounds = TRUE;
             }
         }
diff --git a/ogr/ogrsf_frmts/dgn/dgnstroke.cpp b/ogr/ogrsf_frmts/dgn/dgnstroke.cpp
index a7386de..a76af07 100644
--- a/ogr/ogrsf_frmts/dgn/dgnstroke.cpp
+++ b/ogr/ogrsf_frmts/dgn/dgnstroke.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dgnstroke.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: dgnstroke.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Microstation DGN Access Library
  * Purpose:  Code to stroke Arcs/Ellipses into polylines.
@@ -30,20 +30,20 @@
 #include "dgnlibp.h"
 #include <math.h>
 
-CPL_CVSID("$Id: dgnstroke.cpp 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: dgnstroke.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
-#define DEG_TO_RAD (PI/180.0)
+#define DEG_TO_RAD (M_PI/180.0)
 
 /************************************************************************/
 /*                         ComputePointOnArc()                          */
 /************************************************************************/
 
-static void ComputePointOnArc2D( double dfPrimary, double dfSecondary, 
+static void ComputePointOnArc2D( double dfPrimary, double dfSecondary,
                                  double dfAxisRotation, double dfAngle,
                                  double *pdfX, double *pdfY )
 
 {
-    //dfAxisRotation and dfAngle are suposed to be in Radians
+    // dfAxisRotation and dfAngle are supposed to be in Radians
     double      dfCosRotation = cos(dfAxisRotation);
     double      dfSinRotation = sin(dfAxisRotation);
     double      dfEllipseX = dfPrimary * cos(dfAngle);
@@ -61,12 +61,12 @@ static void ComputePointOnArc2D( double dfPrimary, double dfSecondary,
  * Generate a polyline approximation of an arc.
  *
  * Produce a series of equidistant (actually equi-angle) points along
- * an arc.  Currently this only works for 2D arcs (and ellipses). 
+ * an arc.  Currently this only works for 2D arcs (and ellipses).
  *
  * @param hFile the DGN file to which the arc belongs (currently not used).
  * @param psArc the arc to be approximated.
  * @param nPoints the number of points to use to approximate the arc.
- * @param pasPoints the array of points into which to put the results. 
+ * @param pasPoints the array of points into which to put the results.
  * There must be room for at least nPoints points.
  *
  * @return TRUE on success or FALSE on failure.
@@ -84,7 +84,7 @@ int DGNStrokeArc( CPL_UNUSED DGNHandle hFile,
 
     if( psArc->primary_axis == 0.0 || psArc->secondary_axis == 0.0 )
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "Zero primary or secondary axis in DGNStrokeArc()." );
         return FALSE;
     }
@@ -93,8 +93,8 @@ int DGNStrokeArc( CPL_UNUSED DGNHandle hFile,
     for( i = 0; i < nPoints; i++ )
     {
         dfAngle = (psArc->startang + dfAngleStep * i) * DEG_TO_RAD;
-        
-        ComputePointOnArc2D( psArc->primary_axis, 
+
+        ComputePointOnArc2D( psArc->primary_axis,
                              psArc->secondary_axis,
                              psArc->rotation * DEG_TO_RAD,
                              dfAngle,
@@ -121,7 +121,7 @@ int DGNStrokeArc( CPL_UNUSED DGNHandle hFile,
  * @param hFile the DGN file to which the arc belongs (currently not used).
  * @param psCurve the curve to be approximated.
  * @param nPoints the number of points to use to approximate the curve.
- * @param pasPoints the array of points into which to put the results. 
+ * @param pasPoints the array of points into which to put the results.
  * There must be room for at least nPoints points.
  *
  * @return TRUE on success or FALSE on failure.
@@ -155,6 +155,7 @@ int DGNStrokeCurve( CPL_UNUSED DGNHandle hFile,
 
     for( k = 0; k < nDGNPoints-1; k++ )
     {
+        /* coverity[overrun-local] */
         padfD[k] = sqrt( (pasDGNPoints[k+1].x-pasDGNPoints[k].x)
                            * (pasDGNPoints[k+1].x-pasDGNPoints[k].x)
                          + (pasDGNPoints[k+1].y-pasDGNPoints[k].y)
@@ -228,7 +229,7 @@ int DGNStrokeCurve( CPL_UNUSED DGNHandle hFile,
         dfCx = padfTx[k];
         dfBx = (3.0 * (pasDGNPoints[k+1].x - pasDGNPoints[k].x) / padfD[k]
                 - 2.0 * padfTx[k] - padfTx[k+1]) / padfD[k];
-        dfAx = (padfTx[k] + padfTx[k+1] 
+        dfAx = (padfTx[k] + padfTx[k+1]
                 - 2 * (pasDGNPoints[k+1].x - pasDGNPoints[k].x) / padfD[k])
             / (padfD[k] * padfD[k]);
 
@@ -238,7 +239,7 @@ int DGNStrokeCurve( CPL_UNUSED DGNHandle hFile,
         dfCy = padfTy[k];
         dfBy = (3.0 * (pasDGNPoints[k+1].y - pasDGNPoints[k].y) / padfD[k]
                 - 2.0 * padfTy[k] - padfTy[k+1]) / padfD[k];
-        dfAy = (padfTy[k] + padfTy[k+1] 
+        dfAy = (padfTy[k] + padfTy[k+1]
                 - 2 * (pasDGNPoints[k+1].y - pasDGNPoints[k].y) / padfD[k])
             / (padfD[k] * padfD[k]);
 
@@ -257,11 +258,11 @@ int DGNStrokeCurve( CPL_UNUSED DGNHandle hFile,
         {
             pasPoints[iOutPoint].x = dfAx * dfD * dfD * dfD
                                    + dfBx * dfD * dfD
-                                   + dfCx * dfD 
+                                   + dfCx * dfD
                                    + pasDGNPoints[k].x;
             pasPoints[iOutPoint].y = dfAy * dfD * dfD * dfD
                                    + dfBy * dfD * dfD
-                                   + dfCy * dfD 
+                                   + dfCy * dfD
                                    + pasDGNPoints[k].y;
             pasPoints[iOutPoint].z = 0.0;
             iOutPoint++;
@@ -314,10 +315,10 @@ int main( int argc, char ** argv )
 
     dfPrimary = CPLAtof(argv[1]);
     dfSecondary = CPLAtof(argv[2]);
-    dfAxisRotation = CPLAtof(argv[3]) / 180 * PI;
-    dfAngle = CPLAtof(argv[4]) / 180 * PI;
+    dfAxisRotation = CPLAtof(argv[3]) / 180 * M_PI;
+    dfAngle = CPLAtof(argv[4]) / 180 * M_PI;
 
-    ComputePointOnArc2D( dfPrimary, dfSecondary, dfAxisRotation, dfAngle, 
+    ComputePointOnArc2D( dfPrimary, dfSecondary, dfAxisRotation, dfAngle,
                          &dfX, &dfY );
 
     printf( "X=%.2f, Y=%.2f\n", dfX, dfY );
diff --git a/ogr/ogrsf_frmts/dgn/dgnwrite.cpp b/ogr/ogrsf_frmts/dgn/dgnwrite.cpp
index 4258a60..ee853f4 100644
--- a/ogr/ogrsf_frmts/dgn/dgnwrite.cpp
+++ b/ogr/ogrsf_frmts/dgn/dgnwrite.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dgnwrite.cpp 28435 2015-02-07 14:35:34Z rouault $
+ * $Id: dgnwrite.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Microstation DGN Access Library
  * Purpose:  DGN Access functions related to writing DGN elements.
@@ -30,9 +30,9 @@
 
 #include "dgnlibp.h"
 
-CPL_CVSID("$Id: dgnwrite.cpp 28435 2015-02-07 14:35:34Z rouault $");
+CPL_CVSID("$Id: dgnwrite.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
-static void DGNPointToInt( DGNInfo *psDGN, DGNPoint *psPoint, 
+static void DGNPointToInt( DGNInfo *psDGN, DGNPoint *psPoint,
                            unsigned char *pabyTarget );
 
 /************************************************************************/
@@ -42,26 +42,26 @@ static void DGNPointToInt( DGNInfo *psDGN, DGNPoint *psPoint,
 /**
  * Resize an existing element.
  *
- * If the new size is the same as the old nothing happens. 
+ * If the new size is the same as the old nothing happens.
  *
  * Otherwise, the old element in the file is marked as deleted, and the
  * DGNElemCore.offset and element_id are set to -1 indicating that the
  * element should be written to the end of file when next written by
  * DGNWriteElement().  The internal raw data buffer is updated to the new
  * size.
- * 
+ *
  * Only elements with "raw_data" loaded may be moved.
  *
  * In normal use the DGNResizeElement() call would be called on a previously
  * loaded element, and afterwards the raw_data would be updated before calling
- * DGNWriteElement().  If DGNWriteElement() isn't called after 
+ * DGNWriteElement().  If DGNWriteElement() isn't called after
  * DGNResizeElement() then the element will be lost having been marked as
- * deleted in it's old position but never written at the new location. 
+ * deleted in it's old position but never written at the new location.
  *
  * @param hDGN the DGN file on which the element lives.
- * @param psElement the element to alter.  
+ * @param psElement the element to alter.
  * @param nNewSize the desired new size of the element in bytes.  Must be
- * a multiple of 2. 
+ * a multiple of 2.
  *
  * @return TRUE on success, or FALSE on error.
  */
@@ -74,19 +74,19 @@ int DGNResizeElement( DGNHandle hDGN, DGNElemCore *psElement, int nNewSize )
 /* -------------------------------------------------------------------- */
 /*      Check various conditions.                                       */
 /* -------------------------------------------------------------------- */
-    if( psElement->raw_bytes == 0 
+    if( psElement->raw_bytes == 0
         || psElement->raw_bytes != psElement->size )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Raw bytes not loaded, or not matching element size." );
         return FALSE;
     }
 
     if( nNewSize % 2 == 1 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "DGNResizeElement(%d): "
-                  "can't change to odd (not divisible by two) size.", 
+                  "can't change to odd (not divisible by two) size.",
                   nNewSize );
         return FALSE;
     }
@@ -101,33 +101,32 @@ int DGNResizeElement( DGNHandle hDGN, DGNElemCore *psElement, int nNewSize )
 
     if( psElement->offset != -1 )
     {
-        int nOldFLoc = VSIFTell( psDGN->fp );
+        long nOldFLoc = VSIFTell( psDGN->fp );
         unsigned char abyLeader[2];
-        
+
         if( VSIFSeek( psDGN->fp, psElement->offset, SEEK_SET ) != 0
             || VSIFRead( abyLeader, sizeof(abyLeader), 1, psDGN->fp ) != 1 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Failed seek or read when trying to mark existing\n"
                       "element as deleted in DGNResizeElement()\n" );
             return FALSE;
         }
 
         abyLeader[1] |= 0x80;
-        
+
         if( VSIFSeek( psDGN->fp, psElement->offset, SEEK_SET ) != 0
-            || VSIFWrite( abyLeader, sizeof(abyLeader), 1, psDGN->fp ) != 1 )
+            || VSIFWrite( abyLeader, sizeof(abyLeader), 1, psDGN->fp ) != 1
+            || VSIFSeek( psDGN->fp, nOldFLoc, SEEK_SET ) != 0 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Failed seek or write when trying to mark existing\n"
                       "element as deleted in DGNResizeElement()\n" );
             return FALSE;
         }
 
-        VSIFSeek( psDGN->fp, SEEK_SET, nOldFLoc );
-
         if( psElement->element_id != -1 && psDGN->index_built )
-            psDGN->element_index[psElement->element_id].flags 
+            psDGN->element_index[psElement->element_id].flags
                 |= DGNEIF_DELETED;
     }
 
@@ -138,7 +137,7 @@ int DGNResizeElement( DGNHandle hDGN, DGNElemCore *psElement, int nNewSize )
 /*      Set the new size information, and realloc the raw data buffer.  */
 /* -------------------------------------------------------------------- */
     psElement->size = nNewSize;
-    psElement->raw_data = (unsigned char *) 
+    psElement->raw_data = (unsigned char *)
         CPLRealloc( psElement->raw_data, nNewSize );
     psElement->raw_bytes = nNewSize;
 
@@ -157,27 +156,27 @@ int DGNResizeElement( DGNHandle hDGN, DGNElemCore *psElement, int nNewSize )
 /*                          DGNWriteElement()                           */
 /************************************************************************/
 
-/** 
- * Write element to file. 
+/**
+ * Write element to file.
  *
  * Only elements with "raw_data" loaded may be written.  This should
  * include elements created with the various DGNCreate*() functions, and
  * those read from the file with the DGNO_CAPTURE_RAW_DATA flag turned on
- * with DGNSetOptions(). 
+ * with DGNSetOptions().
  *
- * The passed element is written to the indicated file.  If the 
+ * The passed element is written to the indicated file.  If the
  * DGNElemCore.offset field is -1 then the element is written at the end of
- * the file (and offset/element are reset properly) otherwise the element 
- * is written back to the location indicated by DGNElemCore.offset.  
+ * the file (and offset/element are reset properly) otherwise the element
+ * is written back to the location indicated by DGNElemCore.offset.
  *
  * If the element is added at the end of the file, and if an element index
  * has already been built, it will be updated to reference the new element.
  *
- * This function takes care of ensuring that the end-of-file marker is 
+ * This function takes care of ensuring that the end-of-file marker is
  * maintained after the last element.
  *
  * @param hDGN the file to write the element to.
- * @param psElement the element to write. 
+ * @param psElement the element to write.
  *
  * @return TRUE on success or FALSE in case of failure.
  */
@@ -193,9 +192,7 @@ int DGNWriteElement( DGNHandle hDGN, DGNElemCore *psElement )
 /* ==================================================================== */
     if( psElement->offset == -1 )
     {
-        int nJunk;
-
-        // We must have an index, in order to properly assign the 
+        // We must have an index, in order to properly assign the
         // element id of the newly written element.  Ensure it is built.
         if( !psDGN->index_built )
             DGNBuildIndex( psDGN );
@@ -204,27 +201,26 @@ int DGNWriteElement( DGNHandle hDGN, DGNElemCore *psElement )
         if( !DGNGotoElement( hDGN, psDGN->element_count-1 ) )
             return FALSE;
 
+        int nJunk;
         if( !DGNLoadRawElement( psDGN, &nJunk, &nJunk ) )
             return FALSE;
 
         // Establish the position of the new element.
-        psElement->offset = VSIFTell( psDGN->fp );
+        psElement->offset = static_cast<int>(VSIFTell( psDGN->fp ));
         psElement->element_id = psDGN->element_count;
 
         // Grow element buffer if needed.
         if( psDGN->element_count == psDGN->max_element_count )
         {
             psDGN->max_element_count += 500;
-            
-            psDGN->element_index = (DGNElementInfo *) 
-                CPLRealloc( psDGN->element_index, 
+
+            psDGN->element_index = (DGNElementInfo *)
+                CPLRealloc( psDGN->element_index,
                             psDGN->max_element_count * sizeof(DGNElementInfo));
         }
 
         // Set up the element info
-        DGNElementInfo *psInfo;
-        
-        psInfo = psDGN->element_index + psDGN->element_count;
+        DGNElementInfo *psInfo = psDGN->element_index + psDGN->element_count;
         psInfo->level = (unsigned char) psElement->level;
         psInfo->type = (unsigned char) psElement->type;
         psInfo->stype = (unsigned char) psElement->stype;
@@ -233,20 +229,20 @@ int DGNWriteElement( DGNHandle hDGN, DGNElemCore *psElement )
             psInfo->flags = DGNEIF_COMPLEX;
         else
             psInfo->flags = 0;
-    
+
         psDGN->element_count++;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Write out the element.                                          */
 /* -------------------------------------------------------------------- */
-    if( VSIFSeek( psDGN->fp, psElement->offset, SEEK_SET ) != 0 
-        || VSIFWrite( psElement->raw_data, psElement->raw_bytes, 
+    if( VSIFSeek( psDGN->fp, psElement->offset, SEEK_SET ) != 0
+        || VSIFWrite( psElement->raw_data, psElement->raw_bytes,
                       1, psDGN->fp) != 1 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Error seeking or writing new element of %d bytes at %d.",
-                  psElement->offset, 
+                  psElement->offset,
                   psElement->raw_bytes );
         return FALSE;
     }
@@ -268,10 +264,10 @@ int DGNWriteElement( DGNHandle hDGN, DGNElemCore *psElement )
         VSIFWrite( abyEOF, 2, 1, psDGN->fp );
         VSIFSeek( psDGN->fp, -2, SEEK_CUR );
     }
-        
+
     return TRUE;
 }
-    
+
 /************************************************************************/
 /*                             DGNCreate()                              */
 /************************************************************************/
@@ -288,33 +284,33 @@ int DGNWriteElement( DGNHandle hDGN, DGNElemCore *psElement )
  * from the seed file will be used in the new file.  The nMasterUnitPerSubUnit,
  * nUORPerSubUnit, pszMasterUnits, and pszSubUnits arguments will be ignored.
  * <li> DGNCF_USE_SEED_ORIGIN: The origin from the seed file will be used
- * and the X, Y and Z origin passed into the call will be ignored. 
- * <li> DGNCF_COPY_SEED_FILE_COLOR_TABLE: Should the first color table occuring
- * in the seed file also be copied? 
+ * and the X, Y and Z origin passed into the call will be ignored.
+ * <li> DGNCF_COPY_SEED_FILE_COLOR_TABLE: Should the first color table occurring
+ * in the seed file also be copied?
  * <li> DGNCF_COPY_WHOLE_SEED_FILE: By default only the first three elements
- * (TCB, Digitizer Setup and Level Symbology) are copied from the seed file. 
+ * (TCB, Digitizer Setup and Level Symbology) are copied from the seed file.
  * If this flag is provided the entire seed file is copied verbatim (with the
  * TCB origin and units possibly updated).
  * </ul>
- * 
+ *
  * @param pszNewFilename the filename to create.  If it already exists
  * it will be overwritten.
  * @param pszSeedFile the seed file to copy header from.
  * @param nCreationFlags An ORing of DGNCF_* flags that are to take effect.
- * @param dfOriginX the X origin for the file.  
- * @param dfOriginY the Y origin for the file. 
- * @param dfOriginZ the Z origin for the file. 
+ * @param dfOriginX the X origin for the file.
+ * @param dfOriginY the Y origin for the file.
+ * @param dfOriginZ the Z origin for the file.
  * @param nSubUnitsPerMasterUnit the number of subunits in one master unit.
  * @param nUORPerSubUnit the number of UOR (units of resolution) per subunit.
- * @param pszMasterUnits the name of the master units (2 characters). 
- * @param pszSubUnits the name of the subunits (2 characters). 
+ * @param pszMasterUnits the name of the master units (2 characters).
+ * @param pszSubUnits the name of the subunits (2 characters).
  */
 
 DGNHandle
-      DGNCreate( const char *pszNewFilename, const char *pszSeedFile, 
-                 int nCreationFlags, 
+      DGNCreate( const char *pszNewFilename, const char *pszSeedFile,
+                 int nCreationFlags,
                  double dfOriginX, double dfOriginY, double dfOriginZ,
-                 int nSubUnitsPerMasterUnit, int nUORPerSubUnit, 
+                 int nSubUnitsPerMasterUnit, int nUORPerSubUnit,
                  const char *pszMasterUnits, const char *pszSubUnits )
 
 {
@@ -330,18 +326,18 @@ DGNHandle
         return NULL;
 
     DGNSetOptions( psSeed, DGNO_CAPTURE_RAW_DATA );
-    
+
     psSrcTCB = DGNReadElement( psSeed );
 
     CPLAssert( psSrcTCB->raw_bytes >= 1536 );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Open output file.                                               */
 /* -------------------------------------------------------------------- */
     fpNew = VSIFOpen( pszNewFilename, "wb" );
     if( fpNew == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "Failed to open output file: %s", pszNewFilename );
         return NULL;
     }
@@ -350,7 +346,7 @@ DGNHandle
 /*      Modify TCB appropriately for the output file.                   */
 /* -------------------------------------------------------------------- */
     GByte *pabyRawTCB = (GByte *) CPLMalloc(psSrcTCB->raw_bytes);
-    
+
     memcpy( pabyRawTCB, psSrcTCB->raw_data, psSrcTCB->raw_bytes );
 
     if( !(nCreationFlags & DGNCF_USE_SEED_UNITS) )
@@ -386,13 +382,13 @@ DGNHandle
 /*      Write TCB and EOF to new file.                                  */
 /* -------------------------------------------------------------------- */
     unsigned char abyEOF[2];
-    
+
     VSIFWrite( pabyRawTCB, psSrcTCB->raw_bytes, 1, fpNew );
     CPLFree( pabyRawTCB );
 
     abyEOF[0] = 0xff;
     abyEOF[1] = 0xff;
-    
+
     VSIFWrite( abyEOF, 2, 1, fpNew );
 
     DGNFreeElement( psSeed, psSrcTCB );
@@ -412,7 +408,7 @@ DGNHandle
     while( (psSrcElement = DGNReadElement( psSeed )) != NULL )
     {
         if( (nCreationFlags & DGNCF_COPY_WHOLE_SEED_FILE)
-            || (psSrcElement->stype == DGNST_COLORTABLE 
+            || (psSrcElement->stype == DGNST_COLORTABLE
                 && nCreationFlags & DGNCF_COPY_SEED_FILE_COLOR_TABLE)
             || psSrcElement->element_id <= 2 )
         {
@@ -425,7 +421,7 @@ DGNHandle
     }
 
     DGNClose( psSeed );
-    
+
     return psDGN;
 }
 
@@ -434,21 +430,21 @@ DGNHandle
 /************************************************************************/
 
 /**
- * Clone a retargetted element.
+ * Clone a retargeted element.
  *
  * Creates a copy of an element in a suitable form to write to a
- * different file than that it was read from. 
+ * different file than that it was read from.
  *
  * NOTE: At this time the clone operation will fail if the source
- * and destination file have a different origin or master/sub units. 
+ * and destination file have a different origin or master/sub units.
  *
  * @param hDGNSrc the source file (from which psSrcElement was read).
  * @param hDGNDst the destination file (to which the returned element may be
- * written). 
- * @param psSrcElement the element to be cloned (from hDGNSrc). 
+ * written).
+ * @param psSrcElement the element to be cloned (from hDGNSrc).
  *
- * @return NULL on failure, or an appropriately modified copy of 
- * the source element suitable to write to hDGNDst. 
+ * @return NULL on failure, or an appropriately modified copy of
+ * the source element suitable to write to hDGNDst.
  */
 
 DGNElemCore *DGNCloneElement( CPL_UNUSED DGNHandle hDGNSrc,
@@ -471,11 +467,11 @@ DGNElemCore *DGNCloneElement( CPL_UNUSED DGNHandle hDGNSrc,
     else if( psSrcElement->stype == DGNST_MULTIPOINT )
     {
         DGNElemMultiPoint *psMP, *psSrcMP;
-        int               nSize;
+        size_t             nSize;
 
         psSrcMP = (DGNElemMultiPoint *) psSrcElement;
 
-        nSize = sizeof(DGNElemMultiPoint) 
+        nSize = sizeof(DGNElemMultiPoint)
             + sizeof(DGNPoint) * (psSrcMP->num_vertices-2);
 
         psMP = (DGNElemMultiPoint *) CPLMalloc( nSize );
@@ -495,7 +491,7 @@ DGNElemCore *DGNCloneElement( CPL_UNUSED DGNHandle hDGNSrc,
     else if( psSrcElement->stype == DGNST_TEXT )
     {
         DGNElemText       *psText, *psSrcText;
-        int               nSize;
+        size_t             nSize;
 
         psSrcText = (DGNElemText *) psSrcElement;
         nSize = sizeof(DGNElemText) + strlen(psSrcText->string);
@@ -509,7 +505,7 @@ DGNElemCore *DGNCloneElement( CPL_UNUSED DGNHandle hDGNSrc,
     {
         DGNElemTextNode *psNode;
 
-        psNode = (DGNElemTextNode *) 
+        psNode = (DGNElemTextNode *)
             CPLMalloc(sizeof(DGNElemTextNode));
         memcpy( psNode, psSrcElement, sizeof(DGNElemTextNode) );
 
@@ -519,7 +515,7 @@ DGNElemCore *DGNCloneElement( CPL_UNUSED DGNHandle hDGNSrc,
     {
         DGNElemComplexHeader *psCH;
 
-        psCH = (DGNElemComplexHeader *) 
+        psCH = (DGNElemComplexHeader *)
             CPLMalloc(sizeof(DGNElemComplexHeader));
         memcpy( psCH, psSrcElement, sizeof(DGNElemComplexHeader) );
 
@@ -555,7 +551,7 @@ DGNElemCore *DGNCloneElement( CPL_UNUSED DGNHandle hDGNSrc,
     else if( psSrcElement->stype == DGNST_CELL_LIBRARY )
     {
         DGNElemCellLibrary *psCL;
-        
+
         psCL = (DGNElemCellLibrary *) CPLMalloc(sizeof(DGNElemCellLibrary));
         memcpy( psCL, psSrcElement, sizeof(DGNElemCellLibrary) );
 
@@ -564,7 +560,7 @@ DGNElemCore *DGNCloneElement( CPL_UNUSED DGNHandle hDGNSrc,
     else if( psSrcElement->stype == DGNST_TAG_VALUE )
     {
         DGNElemTagValue *psTV;
-        
+
         psTV = (DGNElemTagValue *) CPLMalloc(sizeof(DGNElemTagValue));
         memcpy( psTV, psSrcElement, sizeof(DGNElemTagValue) );
 
@@ -578,15 +574,15 @@ DGNElemCore *DGNCloneElement( CPL_UNUSED DGNHandle hDGNSrc,
         DGNElemTagSet *psTS;
         int iTag;
         DGNTagDef *pasTagList;
-        
+
         psTS = (DGNElemTagSet *) CPLMalloc(sizeof(DGNElemTagSet));
         memcpy( psTS, psSrcElement, sizeof(DGNElemTagSet) );
 
         psTS->tagSetName = CPLStrdup( psTS->tagSetName );
-        
-        pasTagList = (DGNTagDef *) 
+
+        pasTagList = (DGNTagDef *)
             CPLMalloc( sizeof(DGNTagDef) * psTS->tagCount );
-        memcpy( pasTagList, psTS->tagList, 
+        memcpy( pasTagList, psTS->tagList,
                 sizeof(DGNTagDef) * psTS->tagCount );
 
         for( iTag = 0; iTag < psTS->tagCount; iTag++ )
@@ -594,7 +590,7 @@ DGNElemCore *DGNCloneElement( CPL_UNUSED DGNHandle hDGNSrc,
             pasTagList[iTag].name = CPLStrdup( pasTagList[iTag].name );
             pasTagList[iTag].prompt = CPLStrdup( pasTagList[iTag].prompt );
             if( pasTagList[iTag].type == 1 )
-                pasTagList[iTag].defaultValue.string = 
+                pasTagList[iTag].defaultValue.string =
                     CPLStrdup( pasTagList[iTag].defaultValue.string);
         }
 
@@ -614,7 +610,7 @@ DGNElemCore *DGNCloneElement( CPL_UNUSED DGNHandle hDGNSrc,
     {
         DGNElemBSplineSurfaceHeader *psSurface;
 
-        psSurface = (DGNElemBSplineSurfaceHeader *) 
+        psSurface = (DGNElemBSplineSurfaceHeader *)
           CPLMalloc(sizeof(DGNElemBSplineSurfaceHeader));
         memcpy( psSurface, psSrcElement, sizeof(DGNElemBSplineSurfaceHeader) );
 
@@ -624,7 +620,7 @@ DGNElemCore *DGNCloneElement( CPL_UNUSED DGNHandle hDGNSrc,
     {
         DGNElemBSplineCurveHeader *psCurve;
 
-        psCurve = (DGNElemBSplineCurveHeader *) 
+        psCurve = (DGNElemBSplineCurveHeader *)
           CPLMalloc(sizeof(DGNElemBSplineCurveHeader));
         memcpy( psCurve, psSrcElement, sizeof(DGNElemBSplineCurveHeader) );
 
@@ -633,11 +629,11 @@ DGNElemCore *DGNCloneElement( CPL_UNUSED DGNHandle hDGNSrc,
     else if( psSrcElement->stype == DGNST_BSPLINE_SURFACE_BOUNDARY )
     {
         DGNElemBSplineSurfaceBoundary *psBSB, *psSrcBSB;
-        int               nSize;
+        size_t             nSize;
 
         psSrcBSB = (DGNElemBSplineSurfaceBoundary *) psSrcElement;
 
-        nSize = sizeof(DGNElemBSplineSurfaceBoundary) 
+        nSize = sizeof(DGNElemBSplineSurfaceBoundary)
             + sizeof(DGNPoint) * (psSrcBSB->numverts-1);
 
         psBSB = (DGNElemBSplineSurfaceBoundary *) CPLMalloc( nSize );
@@ -648,7 +644,8 @@ DGNElemCore *DGNCloneElement( CPL_UNUSED DGNHandle hDGNSrc,
     else if( psSrcElement->stype == DGNST_KNOT_WEIGHT )
     {
         DGNElemKnotWeight *psArray /* , *psSrcArray*/;
-        int               nSize, numelems;
+        size_t             nSize;
+        int                numelems;
 
         // FIXME: Is it OK to assume that the # of elements corresponds
         // directly to the element size? kintel 20051218.
@@ -684,14 +681,14 @@ DGNElemCore *DGNCloneElement( CPL_UNUSED DGNHandle hDGNSrc,
     if( psClone->raw_bytes != 0 )
     {
         psClone->raw_data = (unsigned char *) CPLMalloc(psClone->raw_bytes);
-        memcpy( psClone->raw_data, psSrcElement->raw_data, 
+        memcpy( psClone->raw_data, psSrcElement->raw_data,
                 psClone->raw_bytes );
     }
 
     if( psClone->attr_bytes != 0 )
     {
         psClone->attr_data = (unsigned char *) CPLMalloc(psClone->attr_bytes);
-        memcpy( psClone->attr_data, psSrcElement->attr_data, 
+        memcpy( psClone->attr_data, psSrcElement->attr_data,
                 psClone->attr_bytes );
     }
 
@@ -710,13 +707,13 @@ DGNElemCore *DGNCloneElement( CPL_UNUSED DGNHandle hDGNSrc,
 
 /**
  * Change element core values.
- * 
+ *
  * The indicated values in the element are updated in the structure, as well
  * as in the raw data.  The updated element is not written to disk.  That
  * must be done with DGNWriteElement().   The element must have raw_data
  * loaded.
- * 
- * @param hDGN the file on which the element belongs. 
+ *
+ * @param hDGN the file on which the element belongs.
  * @param psElement the element to modify.
  * @param nLevel the new level value.
  * @param nGraphicGroup the new graphic group value.
@@ -727,8 +724,8 @@ DGNElemCore *DGNCloneElement( CPL_UNUSED DGNHandle hDGNSrc,
  * @return Returns TRUE on success or FALSE on failure.
  */
 
-int DGNUpdateElemCore( DGNHandle hDGN, DGNElemCore *psElement, 
-                       int nLevel, int nGraphicGroup, int nColor, 
+int DGNUpdateElemCore( DGNHandle hDGN, DGNElemCore *psElement,
+                       int nLevel, int nGraphicGroup, int nColor,
                        int nWeight, int nStyle )
 
 {
@@ -750,12 +747,12 @@ int DGNUpdateElemCore( DGNHandle hDGN, DGNElemCore *psElement,
  *
  * The raw_data representation of the passed element is updated to reflect
  * the various core fields.  The DGNElemCore level, type, complex, deleted,
- * graphic_group, properties, color, weight and style values are all 
+ * graphic_group, properties, color, weight and style values are all
  * applied to the raw_data representation.  Spatial bounds, element type
- * specific information and attributes are not updated in the raw data. 
+ * specific information and attributes are not updated in the raw data.
  *
- * @param hDGN the file to which the element belongs. 
- * @param psElement the element to be updated. 
+ * @param hDGN the file to which the element belongs.
+ * @param psElement the element to be updated.
  *
  * @return TRUE on success, or FALSE on failure.
  */
@@ -795,7 +792,7 @@ int DGNUpdateElemCoreExtended( CPL_UNUSED DGNHandle hDGN,
     if( psElement->raw_data[30] == 0 && psElement->raw_data[31] == 0 )
     {
         int     nAttIndex = (psElement->raw_bytes - 32) / 2;
-        
+
         psElement->raw_data[30] = (GByte) (nAttIndex % 256);
         psElement->raw_data[31] = (GByte) (nAttIndex / 256);
     }
@@ -811,7 +808,7 @@ int DGNUpdateElemCoreExtended( CPL_UNUSED DGNHandle hDGN,
         rd[34] = (GByte) (psElement->style | (psElement->weight << 3));
         rd[35] = (GByte) psElement->color;
     }
-    
+
     return TRUE;
 }
 
@@ -858,36 +855,35 @@ static void DGNWriteBounds( DGNInfo *psInfo, DGNElemCore *psElement,
 /************************************************************************/
 
 /**
- * Create new multi-point element. 
+ * Create new multi-point element.
  *
  * The newly created element will still need to be written to file using
  * DGNWriteElement(). Also the level and other core values will be defaulted.
  * Use DGNUpdateElemCore() on the element before writing to set these values.
  *
  * NOTE: There are restrictions on the nPointCount for some elements. For
- * instance, DGNT_LINE can only have 2 points. Maximum element size 
- * precludes very large numbers of points. 
+ * instance, DGNT_LINE can only have 2 points. Maximum element size
+ * precludes very large numbers of points.
  *
  * @param hDGN the file on which the element will eventually be written.
  * @param nType the type of the element to be created.  It must be one of
- * DGNT_LINE, DGNT_LINE_STRING, DGNT_SHAPE, DGNT_CURVE or DGNT_BSPLINE_POLE. 
+ * DGNT_LINE, DGNT_LINE_STRING, DGNT_SHAPE, DGNT_CURVE or DGNT_BSPLINE_POLE.
  * @param nPointCount the number of points in the pasVertices list.
- * @param pasVertices the list of points to be written. 
+ * @param pasVertices the list of points to be written.
  *
  * @return the new element (a DGNElemMultiPoint structure) or NULL on failure.
  */
 
-DGNElemCore *DGNCreateMultiPointElem( DGNHandle hDGN, int nType, 
+DGNElemCore *DGNCreateMultiPointElem( DGNHandle hDGN, int nType,
                                       int nPointCount, DGNPoint *pasVertices )
 
 {
     DGNElemMultiPoint *psMP;
     DGNElemCore *psCore;
     DGNInfo *psDGN = (DGNInfo *) hDGN;
-    int i;
     DGNPoint sMin, sMax;
 
-    CPLAssert( nType == DGNT_LINE 
+    CPLAssert( nType == DGNT_LINE
                || nType == DGNT_LINE_STRING
                || nType == DGNT_SHAPE
                || nType == DGNT_CURVE
@@ -900,7 +896,7 @@ DGNElemCore *DGNCreateMultiPointElem( DGNHandle hDGN, int nType,
 /* -------------------------------------------------------------------- */
     if( nPointCount > 101 )
     {
-        CPLError( CE_Failure, CPLE_ElementTooBig, 
+        CPLError( CE_Failure, CPLE_ElementTooBig,
                   "Attempt to create %s element with %d points failed.\n"
                   "Element would be too large.",
                   DGNTypeToName( nType ), nPointCount );
@@ -910,7 +906,7 @@ DGNElemCore *DGNCreateMultiPointElem( DGNHandle hDGN, int nType,
 /* -------------------------------------------------------------------- */
 /*      Allocate element.                                               */
 /* -------------------------------------------------------------------- */
-    psMP = (DGNElemMultiPoint *) 
+    psMP = (DGNElemMultiPoint *)
         CPLCalloc( sizeof(DGNElemMultiPoint)
                    + sizeof(DGNPoint) * (nPointCount-2), 1 );
     psCore = &(psMP->core);
@@ -923,6 +919,7 @@ DGNElemCore *DGNCreateMultiPointElem( DGNHandle hDGN, int nType,
 /*      Set multipoint specific information in the structure.           */
 /* -------------------------------------------------------------------- */
     psMP->num_vertices = nPointCount;
+    // coverity[overrun-buffer-arg]
     memcpy( psMP->vertices + 0, pasVertices, sizeof(DGNPoint) * nPointCount );
 
 /* -------------------------------------------------------------------- */
@@ -936,9 +933,9 @@ DGNElemCore *DGNCreateMultiPointElem( DGNHandle hDGN, int nType,
 
         psCore->raw_data = (unsigned char*) CPLCalloc(psCore->raw_bytes,1);
 
-        DGNInverseTransformPointToInt( psDGN, pasVertices + 0, 
+        DGNInverseTransformPointToInt( psDGN, pasVertices + 0,
                                        psCore->raw_data + 36 );
-        DGNInverseTransformPointToInt( psDGN, pasVertices + 1, 
+        DGNInverseTransformPointToInt( psDGN, pasVertices + 1,
                                        psCore->raw_data + 36
                                        + psDGN->dimension * 4 );
     }
@@ -952,19 +949,19 @@ DGNElemCore *DGNCreateMultiPointElem( DGNHandle hDGN, int nType,
         psCore->raw_data[36] = (unsigned char) (nPointCount % 256);
         psCore->raw_data[37] = (unsigned char) (nPointCount/256);
 
-        for( i = 0; i < nPointCount; i++ )
-            DGNInverseTransformPointToInt( psDGN, pasVertices + i, 
-                                           psCore->raw_data + 38 
+        for( int i = 0; i < nPointCount; i++ )
+            DGNInverseTransformPointToInt( psDGN, pasVertices + i,
+                                           psCore->raw_data + 38
                                            + psDGN->dimension * i * 4 );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Set the core raw data, including the bounds.                    */
 /* -------------------------------------------------------------------- */
     DGNUpdateElemCoreExtended( hDGN, psCore );
 
     sMin = sMax = pasVertices[0];
-    for( i = 1; i < nPointCount; i++ )
+    for( int i = 1; i < nPointCount; i++ )
     {
         sMin.x = MIN(pasVertices[i].x,sMin.x);
         sMin.y = MIN(pasVertices[i].y,sMin.y);
@@ -975,8 +972,8 @@ DGNElemCore *DGNCreateMultiPointElem( DGNHandle hDGN, int nType,
     }
 
     DGNWriteBounds( psDGN, psCore, &sMin, &sMax );
-    
-    return psCore;
+
+    return (DGNElemCore*) psMP;
 }
 
 /************************************************************************/
@@ -984,19 +981,19 @@ DGNElemCore *DGNCreateMultiPointElem( DGNHandle hDGN, int nType,
 /************************************************************************/
 
 DGNElemCore *
-DGNCreateArcElem2D( DGNHandle hDGN, int nType, 
+DGNCreateArcElem2D( DGNHandle hDGN, int nType,
                     double dfOriginX, double dfOriginY,
-                    double dfPrimaryAxis, double dfSecondaryAxis, 
-                    double dfRotation, 
+                    double dfPrimaryAxis, double dfSecondaryAxis,
+                    double dfRotation,
                     double dfStartAngle, double dfSweepAngle )
 
 {
-    return DGNCreateArcElem( hDGN, nType, dfOriginX, dfOriginY, 0.0, 
-                             dfPrimaryAxis, dfSecondaryAxis, 
-                             dfStartAngle, dfSweepAngle, 
+    return DGNCreateArcElem( hDGN, nType, dfOriginX, dfOriginY, 0.0,
+                             dfPrimaryAxis, dfSecondaryAxis,
+                             dfStartAngle, dfSweepAngle,
                              dfRotation, NULL );
 }
-                                 
+
 /************************************************************************/
 /*                          DGNCreateArcElem()                          */
 /************************************************************************/
@@ -1004,7 +1001,7 @@ DGNCreateArcElem2D( DGNHandle hDGN, int nType,
 /**
  * Create Arc or Ellipse element.
  *
- * Create a new 2D or 3D arc or ellipse element.  The start angle, and sweep 
+ * Create a new 2D or 3D arc or ellipse element.  The start angle, and sweep
  * angle are ignored for DGNT_ELLIPSE but used for DGNT_ARC.
  *
  * The newly created element will still need to be written to file using
@@ -1012,24 +1009,24 @@ DGNCreateArcElem2D( DGNHandle hDGN, int nType,
  * Use DGNUpdateElemCore() on the element before writing to set these values.
  *
  * @param hDGN the DGN file on which the element will eventually be written.
- * @param nType either DGNT_ELLIPSE or DGNT_ARC to select element type. 
+ * @param nType either DGNT_ELLIPSE or DGNT_ARC to select element type.
  * @param dfOriginX the origin (center of rotation) of the arc (X).
  * @param dfOriginY the origin (center of rotation) of the arc (Y).
  * @param dfOriginZ the origin (center of rotation) of the arc (Y).
  * @param dfPrimaryAxis the length of the primary axis.
- * @param dfSecondaryAxis the length of the secondary axis. 
+ * @param dfSecondaryAxis the length of the secondary axis.
  * @param dfStartAngle start angle, degrees counterclockwise of primary axis.
  * @param dfSweepAngle sweep angle, degrees
- * @param dfRotation Counterclockwise rotation in degrees. 
+ * @param dfRotation Counterclockwise rotation in degrees.
  * @param panQuaternion 3D orientation quaternion (NULL to use rotation).
- * 
+ *
  * @return the new element (DGNElemArc) or NULL on failure.
  */
 
 DGNElemCore *
-DGNCreateArcElem( DGNHandle hDGN, int nType, 
+DGNCreateArcElem( DGNHandle hDGN, int nType,
                   double dfOriginX, double dfOriginY, double dfOriginZ,
-                  double dfPrimaryAxis, double dfSecondaryAxis, 
+                  double dfPrimaryAxis, double dfSecondaryAxis,
                   double dfStartAngle, double dfSweepAngle,
                   double dfRotation, int *panQuaternion )
 
@@ -1127,7 +1124,7 @@ DGNCreateArcElem( DGNHandle hDGN, int nType,
             DGN_WRITE_INT32( psArc->quat[1], psCore->raw_data + 64 );
             DGN_WRITE_INT32( psArc->quat[2], psCore->raw_data + 68 );
             DGN_WRITE_INT32( psArc->quat[3], psCore->raw_data + 72 );
-            
+
             /* origin */
             DGNInverseTransformPoint( psDGN, &sOrigin );
             memcpy( psCore->raw_data + 76, &(sOrigin.x), 8 );
@@ -1142,7 +1139,7 @@ DGNCreateArcElem( DGNHandle hDGN, int nType,
             /* rotation */
             nAngle = (int) (dfRotation * 360000.0);
             DGN_WRITE_INT32( nAngle, psCore->raw_data + 60 );
-            
+
             /* origin */
             DGNInverseTransformPoint( psDGN, &sOrigin );
             memcpy( psCore->raw_data + 64, &(sOrigin.x), 8 );
@@ -1181,7 +1178,7 @@ DGNCreateArcElem( DGNHandle hDGN, int nType,
             DGN_WRITE_INT32( psArc->quat[1], psCore->raw_data + 56 );
             DGN_WRITE_INT32( psArc->quat[2], psCore->raw_data + 60 );
             DGN_WRITE_INT32( psArc->quat[3], psCore->raw_data + 64 );
-            
+
             /* origin */
             DGNInverseTransformPoint( psDGN, &sOrigin );
             memcpy( psCore->raw_data + 68, &(sOrigin.x), 8 );
@@ -1196,7 +1193,7 @@ DGNCreateArcElem( DGNHandle hDGN, int nType,
             /* rotation */
             nAngle = (int) (dfRotation * 360000.0);
             DGN_WRITE_INT32( nAngle, psCore->raw_data + 52 );
-            
+
             /* origin */
             DGNInverseTransformPoint( psDGN, &sOrigin );
             memcpy( psCore->raw_data + 56, &(sOrigin.x), 8 );
@@ -1204,11 +1201,11 @@ DGNCreateArcElem( DGNHandle hDGN, int nType,
             IEEE2DGNDouble( psCore->raw_data + 56 );
             IEEE2DGNDouble( psCore->raw_data + 64 );
         }
-        
+
         psArc->startang = 0.0;
         psArc->sweepang = 360.0;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Set the core raw data, including the bounds.                    */
 /* -------------------------------------------------------------------- */
@@ -1222,10 +1219,10 @@ DGNCreateArcElem( DGNHandle hDGN, int nType,
     sMax.z = dfOriginZ + MAX(dfPrimaryAxis,dfSecondaryAxis);
 
     DGNWriteBounds( psDGN, psCore, &sMin, &sMax );
-    
-    return psCore;
+
+    return (DGNElemCore*) psArc;
 }
-                                 
+
 /************************************************************************/
 /*                          DGNCreateConeElem()                         */
 /************************************************************************/
@@ -1249,7 +1246,7 @@ DGNCreateArcElem( DGNHandle hDGN, int nType,
  * @param dfCenter_2Z the center of the second bounding circle (Z).
  * @param dfRadius_2 the radius of the second bounding circle.
  * @param panQuaternion 3D orientation quaternion (NULL for default orientation - circles parallel to the X-Y plane).
- * 
+ *
  * @return the new element (DGNElemCone) or NULL on failure.
  */
 
@@ -1314,7 +1311,7 @@ DGNCreateConeElem( DGNHandle hDGN,
     /* unknown data */
     psCore->raw_data[36] = 0;
     psCore->raw_data[37] = 0;
-    
+
     /* quaternion */
     DGN_WRITE_INT32( psCone->quat[0], psCore->raw_data + 38 );
     DGN_WRITE_INT32( psCone->quat[1], psCore->raw_data + 42 );
@@ -1348,7 +1345,7 @@ DGNCreateConeElem( DGNHandle hDGN,
     dfScaledRadius = psCone->radius_2 / psDGN->scale;
     memcpy( psCore->raw_data + 110, &dfScaledRadius, 8 );
     IEEE2DGNDouble( psCore->raw_data + 110 );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Set the core raw data, including the bounds.                    */
 /* -------------------------------------------------------------------- */
@@ -1359,7 +1356,7 @@ DGNCreateConeElem( DGNHandle hDGN,
 
     // Old implementation attempt:
     // What if center_1.z > center_2.z ?
-//     double largestRadius = 
+//     double largestRadius =
 //       psCone->radius_1>psCone->radius_2?psCone->radius_1:psCone->radius_2;
 //     sMin.x = psCone->center_1.x-largestRadius;
 //     sMin.y = psCone->center_1.y-largestRadius;
@@ -1369,10 +1366,10 @@ DGNCreateConeElem( DGNHandle hDGN,
 //     sMax.z = psCone->center_2.z;
 
     DGNWriteBounds( psDGN, psCore, &sMin, &sMax );
-    
-    return psCore;
+
+    return (DGNElemCore*) psCone;
 }
-                                 
+
 /************************************************************************/
 /*                         DGNCreateTextElem()                          */
 /************************************************************************/
@@ -1385,10 +1382,10 @@ DGNCreateConeElem( DGNHandle hDGN,
  * Use DGNUpdateElemCore() on the element before writing to set these values.
  *
  * @param hDGN the file on which the element will eventually be written.
- * @param pszText the string of text. 
+ * @param pszText the string of text.
  * @param nFontId microstation font id for the text.  1 may be used as default.
- * @param nJustification text justification.  One of DGNJ_LEFT_TOP, 
- * DGNJ_LEFT_CENTER, DGNJ_LEFT_BOTTOM, DGNJ_CENTER_TOP, DGNJ_CENTER_CENTER, 
+ * @param nJustification text justification.  One of DGNJ_LEFT_TOP,
+ * DGNJ_LEFT_CENTER, DGNJ_LEFT_BOTTOM, DGNJ_CENTER_TOP, DGNJ_CENTER_CENTER,
  * DGNJ_CENTER_BOTTOM, DGNJ_RIGHT_TOP, DGNJ_RIGHT_CENTER, DGNJ_RIGHT_BOTTOM.
  * @param dfLengthMult character width in master units.
  * @param dfHeightMult character height in master units.
@@ -1397,14 +1394,14 @@ DGNCreateConeElem( DGNHandle hDGN,
  * @param dfOriginX Text origin (X).
  * @param dfOriginY Text origin (Y).
  * @param dfOriginZ Text origin (Z).
- * 
+ *
  * @return the new element (DGNElemText) or NULL on failure.
  */
 
 DGNElemCore *
-DGNCreateTextElem( DGNHandle hDGN, const char *pszText, 
-                   int nFontId, int nJustification, 
-                   double dfLengthMult, double dfHeightMult, 
+DGNCreateTextElem( DGNHandle hDGN, const char *pszText,
+                   int nFontId, int nJustification,
+                   double dfLengthMult, double dfHeightMult,
                    double dfRotation, int *panQuaternion,
                    double dfOriginX, double dfOriginY, double dfOriginZ )
 
@@ -1421,7 +1418,7 @@ DGNCreateTextElem( DGNHandle hDGN, const char *pszText,
 /* -------------------------------------------------------------------- */
 /*      Allocate element.                                               */
 /* -------------------------------------------------------------------- */
-    psText = (DGNElemText *) 
+    psText = (DGNElemText *)
         CPLCalloc( sizeof(DGNElemText)+strlen(pszText), 1 );
     psCore = &(psText->core);
 
@@ -1446,9 +1443,9 @@ DGNCreateTextElem( DGNHandle hDGN, const char *pszText,
 /*      Setup Raw data for the text specific portion.                   */
 /* -------------------------------------------------------------------- */
     if( psDGN->dimension == 2 )
-        psCore->raw_bytes = 60 + strlen(pszText);
+        psCore->raw_bytes = 60 + static_cast<int>(strlen(pszText));
     else
-        psCore->raw_bytes = 76 + strlen(pszText);
+        psCore->raw_bytes = 76 + static_cast<int>(strlen(pszText));
 
     psCore->raw_bytes += (psCore->raw_bytes % 2);
     psCore->raw_data = (unsigned char*) CPLCalloc(psCore->raw_bytes,1);
@@ -1458,7 +1455,7 @@ DGNCreateTextElem( DGNHandle hDGN, const char *pszText,
 
     nIntValue = (int) (dfLengthMult * 1000.0 / (psDGN->scale * 6.0) + 0.5);
     DGN_WRITE_INT32( nIntValue, psCore->raw_data + 38 );
-    
+
     nIntValue = (int) (dfHeightMult * 1000.0 / (psDGN->scale * 6.0) + 0.5);
     DGN_WRITE_INT32( nIntValue, psCore->raw_data + 42 );
 
@@ -1467,7 +1464,7 @@ DGNCreateTextElem( DGNHandle hDGN, const char *pszText,
         nIntValue = (int) (dfRotation * 360000.0);
         DGN_WRITE_INT32( nIntValue, psCore->raw_data + 46 );
 
-        DGNInverseTransformPointToInt( psDGN, &(psText->origin), 
+        DGNInverseTransformPointToInt( psDGN, &(psText->origin),
                                        psCore->raw_data + 50 );
 
         nBase = 58;
@@ -1486,7 +1483,7 @@ DGNCreateTextElem( DGNHandle hDGN, const char *pszText,
         DGN_WRITE_INT32( anQuaternion[2], psCore->raw_data + 54 );
         DGN_WRITE_INT32( anQuaternion[3], psCore->raw_data + 58 );
 
-        DGNInverseTransformPointToInt( psDGN, &(psText->origin), 
+        DGNInverseTransformPointToInt( psDGN, &(psText->origin),
                                        psCore->raw_data + 62 );
         nBase = 74;
     }
@@ -1494,7 +1491,7 @@ DGNCreateTextElem( DGNHandle hDGN, const char *pszText,
     psCore->raw_data[nBase] = (unsigned char) strlen(pszText);
     psCore->raw_data[nBase+1] = 0; /* edflds? */
     memcpy( psCore->raw_data + nBase+2, pszText, strlen(pszText) );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Set the core raw data, including the bounds.                    */
 /*                                                                      */
@@ -1516,12 +1513,12 @@ DGNCreateTextElem( DGNHandle hDGN, const char *pszText,
     diagonal=sqrt(length*length+height*height);
     sLowLeft.x=sMin.x;
     sLowLeft.y=sMin.y;
-    sLowRight.x=sMin.x+cos(psText->rotation*PI/180.0)*length;
-    sLowRight.y=sMin.y+sin(psText->rotation*PI/180.0)*length;
-    sUpRight.x=sMin.x+cos((psText->rotation*PI/180.0)+atan(height/length))*diagonal;
-    sUpRight.y=sMin.y+sin((psText->rotation*PI/180.0)+atan(height/length))*diagonal;
-    sUpLeft.x=sMin.x+cos((psText->rotation+90.0)*PI/180.0)*height;
-    sUpLeft.y=sMin.y+sin((psText->rotation+90.0)*PI/180.0)*height;
+    sLowRight.x=sMin.x+cos(psText->rotation*M_PI/180.0)*length;
+    sLowRight.y=sMin.y+sin(psText->rotation*M_PI/180.0)*length;
+    sUpRight.x=sMin.x+cos((psText->rotation*M_PI/180.0)+atan(height/length))*diagonal;
+    sUpRight.y=sMin.y+sin((psText->rotation*M_PI/180.0)+atan(height/length))*diagonal;
+    sUpLeft.x=sMin.x+cos((psText->rotation+90.0)*M_PI/180.0)*height;
+    sUpLeft.y=sMin.y+sin((psText->rotation+90.0)*M_PI/180.0)*height;
 
     //calculate new values for bounding box
     sMin.x=MIN(sLowLeft.x,MIN(sLowRight.x,MIN(sUpLeft.x,sUpRight.x)));
@@ -1536,8 +1533,8 @@ DGNCreateTextElem( DGNHandle hDGN, const char *pszText,
     sMax.z = 0.0;
 
     DGNWriteBounds( psDGN, psCore, &sMin, &sMax );
-    
-    return psCore;
+
+    return (DGNElemCore*) psText;
 }
 
 /************************************************************************/
@@ -1547,11 +1544,11 @@ DGNCreateTextElem( DGNHandle hDGN, const char *pszText,
 /**
  * Create color table element.
  *
- * Creates a color table element with the indicated color table. 
+ * Creates a color table element with the indicated color table.
  *
- * Note that color table elements are actally of type DGNT_GROUP_DATA(5)
+ * Note that color table elements are actually of type DGNT_GROUP_DATA(5)
  * and always on level 1.  Do not alter the level with DGNUpdateElemCore()
- * or the element will essentially be corrupt. 
+ * or the element will essentially be corrupt.
  *
  * The newly created element will still need to be written to file using
  * DGNWriteElement(). Also the level and other core values will be defaulted.
@@ -1559,16 +1556,16 @@ DGNCreateTextElem( DGNHandle hDGN, const char *pszText,
  *
  * @param hDGN the file to which the element will eventually be written.
  * @param nScreenFlag the screen to which the color table applies
- * (0 = left, 1 = right). 
+ * (0 = left, 1 = right).
  * @param abyColorInfo array of 256 color entries. The first is
- * the background color. 
+ * the background color.
  *
- * @return the new element (DGNElemColorTable) or NULL on failure. 
+ * @return the new element (DGNElemColorTable) or NULL on failure.
  */
 
 
 DGNElemCore *
-DGNCreateColorTableElem( DGNHandle hDGN, int nScreenFlag, 
+DGNCreateColorTableElem( DGNHandle hDGN, int nScreenFlag,
                          GByte abyColorInfo[256][3] )
 
 {
@@ -1595,21 +1592,21 @@ DGNCreateColorTableElem( DGNHandle hDGN, int nScreenFlag,
 /* -------------------------------------------------------------------- */
 /*      Setup Raw data for the color table specific portion.            */
 /* -------------------------------------------------------------------- */
-    psCore->raw_bytes = 806; /* FIXME: this is invalid : 806 < 41 + 783 (see below lines) */
+    psCore->raw_bytes = 41+(256-1)*3;
     psCore->raw_data = (unsigned char*) CPLCalloc(psCore->raw_bytes,1);
 
     psCore->raw_data[36] = (unsigned char) (nScreenFlag % 256);
     psCore->raw_data[37] = (unsigned char) (nScreenFlag / 256);
 
     memcpy( psCore->raw_data + 38, abyColorInfo[255], 3 );
-    memcpy( psCore->raw_data + 41, abyColorInfo, 783 );
-    
+    memcpy( psCore->raw_data + 41, abyColorInfo, (256-1)*3 );
+
 /* -------------------------------------------------------------------- */
 /*      Set the core raw data.                                          */
 /* -------------------------------------------------------------------- */
     DGNUpdateElemCoreExtended( hDGN, psCore );
-    
-    return psCore;
+
+    return (DGNElemCore*) psCT;
 }
 
 /************************************************************************/
@@ -1623,9 +1620,9 @@ DGNCreateColorTableElem( DGNHandle hDGN, int nScreenFlag,
  * DGNWriteElement(). Also the level and other core values will be defaulted.
  * Use DGNUpdateElemCore() on the element before writing to set these values.
  *
- * The nTotLength is the sum of the size of all elements in the complex 
+ * The nTotLength is the sum of the size of all elements in the complex
  * group plus 5.  The DGNCreateComplexHeaderFromGroup() can be used to build
- * a complex element from the members more conveniently.  
+ * a complex element from the members more conveniently.
  *
  * @param hDGN the file on which the element will be written.
  * @param nType DGNT_COMPLEX_CHAIN_HEADER or DGNT_COMPLEX_SHAPE_HEADER.
@@ -1633,19 +1630,19 @@ DGNCreateColorTableElem( DGNHandle hDGN, int nScreenFlag,
  * or if the object represents a surface or a solid.
  * @param nTotLength the value of the totlength field in the element.
  * @param nNumElems the number of elements in the complex group not including
- * the header element. 
+ * the header element.
  *
- * @return the new element (DGNElemComplexHeader) or NULL on failure. 
+ * @return the new element (DGNElemComplexHeader) or NULL on failure.
  */
 DGNElemCore *
-DGNCreateComplexHeaderElem( DGNHandle hDGN, int nType, 
+DGNCreateComplexHeaderElem( DGNHandle hDGN, int nType,
                             int nTotLength, int nNumElems )
 {
     DGNElemComplexHeader *psCH;
     DGNElemCore *psCore;
     unsigned char abyRawZeroLinkage[8] = {0,0,0,0,0,0,0,0};
 
-    CPLAssert( nType == DGNT_COMPLEX_CHAIN_HEADER 
+    CPLAssert( nType == DGNT_COMPLEX_CHAIN_HEADER
                || nType == DGNT_COMPLEX_SHAPE_HEADER );
 
     DGNLoadTCB( hDGN );
@@ -1653,7 +1650,7 @@ DGNCreateComplexHeaderElem( DGNHandle hDGN, int nType,
 /* -------------------------------------------------------------------- */
 /*      Allocate element.                                               */
 /* -------------------------------------------------------------------- */
-    psCH = (DGNElemComplexHeader *) 
+    psCH = (DGNElemComplexHeader *)
         CPLCalloc( sizeof(DGNElemComplexHeader), 1 );
     psCore = &(psCH->core);
 
@@ -1691,8 +1688,8 @@ DGNCreateComplexHeaderElem( DGNHandle hDGN, int nType,
 /*      add a dummy bit of attribute data to fill out the length.       */
 /* -------------------------------------------------------------------- */
     DGNAddRawAttrLink( hDGN, psCore, 8, abyRawZeroLinkage );
-    
-    return psCore;
+
+    return (DGNElemCore*) psCH;
 }
 
 /************************************************************************/
@@ -1703,25 +1700,25 @@ DGNCreateComplexHeaderElem( DGNHandle hDGN, int nType,
  * Create complex chain/shape header.
  *
  * This function is similar to DGNCreateComplexHeaderElem(), but it takes
- * care of computing the total size of the set of elements being written, 
+ * care of computing the total size of the set of elements being written,
  * and collecting the bounding extents.  It also takes care of some other
- * convenience issues, like marking all the member elements as complex, and 
- * setting the level based on the level of the member elements. 
- * 
+ * convenience issues, like marking all the member elements as complex, and
+ * setting the level based on the level of the member elements.
+ *
  * @param hDGN the file on which the element will be written.
  * @param nType DGNT_COMPLEX_CHAIN_HEADER or DGNT_COMPLEX_SHAPE_HEADER.
  * depending on whether the list is open or closed (last point equal to last)
  * or if the object represents a surface or a solid.
  * @param nNumElems the number of elements in the complex group not including
- * the header element. 
+ * the header element.
  * @param papsElems array of pointers to nNumElems elements in the complex
- * group.  Some updates may be made to these elements. 
+ * group.  Some updates may be made to these elements.
  *
- * @return the new element (DGNElemComplexHeader) or NULL on failure. 
+ * @return the new element (DGNElemComplexHeader) or NULL on failure.
  */
 
 DGNElemCore *
-DGNCreateComplexHeaderFromGroup( DGNHandle hDGN, int nType, 
+DGNCreateComplexHeaderFromGroup( DGNHandle hDGN, int nType,
                                  int nNumElems, DGNElemCore **papsElems )
 
 {
@@ -1734,7 +1731,7 @@ DGNCreateComplexHeaderFromGroup( DGNHandle hDGN, int nType,
 
     if( nNumElems < 1 || papsElems == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Need at least one element to form a complex group." );
         return NULL;
     }
@@ -1755,7 +1752,7 @@ DGNCreateComplexHeaderFromGroup( DGNHandle hDGN, int nType,
 
         if( papsElems[i]->level != nLevel )
         {
-            CPLError( CE_Warning, CPLE_AppDefined, 
+            CPLError( CE_Warning, CPLE_AppDefined,
                       "Not all level values matching in a complex set group!");
         }
 
@@ -1784,7 +1781,7 @@ DGNCreateComplexHeaderFromGroup( DGNHandle hDGN, int nType,
                        psCH->color, psCH->weight, psCH->style );
 
     DGNWriteBounds( (DGNInfo *) hDGN, psCH, &sMin, &sMax );
-    
+
     return psCH;
 }
 
@@ -1801,27 +1798,23 @@ DGNCreateComplexHeaderFromGroup( DGNHandle hDGN, int nType,
  *
  * The nTotLength is the sum of the size of all elements in the solid
  * group plus 6.  The DGNCreateSolidHeaderFromGroup() can be used to build
- * a solid element from the members more conveniently.  
+ * a solid element from the members more conveniently.
  *
  * @param hDGN the file on which the element will be written.
  * @param nType DGNT_3DSURFACE_HEADER or DGNT_3DSOLID_HEADER.
- * @param nSurfType the surface/solid type, one of DGNSUT_* or DGNSOT_*. 
- * @param nBoundElems the number of elements in each boundary. 
+ * @param nSurfType the surface/solid type, one of DGNSUT_* or DGNSOT_*.
+ * @param nBoundElems the number of elements in each boundary.
  * @param nTotLength the value of the totlength field in the element.
  * @param nNumElems the number of elements in the solid not including
- * the header element. 
+ * the header element.
  *
- * @return the new element (DGNElemComplexHeader) or NULL on failure. 
+ * @return the new element (DGNElemComplexHeader) or NULL on failure.
  */
 DGNElemCore *
 DGNCreateSolidHeaderElem( DGNHandle hDGN, int nType, int nSurfType,
                           int nBoundElems, int nTotLength, int nNumElems )
 {
-    DGNElemComplexHeader *psCH;
-    DGNElemCore *psCore;
-    unsigned char abyRawZeroLinkage[8] = {0,0,0,0,0,0,0,0};
-
-    CPLAssert( nType == DGNT_3DSURFACE_HEADER 
+    CPLAssert( nType == DGNT_3DSURFACE_HEADER
                || nType == DGNT_3DSOLID_HEADER );
 
     DGNLoadTCB( hDGN );
@@ -1829,9 +1822,9 @@ DGNCreateSolidHeaderElem( DGNHandle hDGN, int nType, int nSurfType,
 /* -------------------------------------------------------------------- */
 /*      Allocate element.                                               */
 /* -------------------------------------------------------------------- */
-    psCH = (DGNElemComplexHeader *) 
+    DGNElemComplexHeader *psCH = (DGNElemComplexHeader *)
         CPLCalloc( sizeof(DGNElemComplexHeader), 1 );
-    psCore = &(psCH->core);
+    DGNElemCore *psCore = &(psCH->core);
 
     DGNInitializeElemCore( hDGN, psCore );
     psCore->complex = TRUE;
@@ -1869,9 +1862,10 @@ DGNCreateSolidHeaderElem( DGNHandle hDGN, int nType, int nSurfType,
 /*      Elements have to be at least 48 bytes long, so we have to       */
 /*      add a dummy bit of attribute data to fill out the length.       */
 /* -------------------------------------------------------------------- */
+    unsigned char abyRawZeroLinkage[8] = {0, 0, 0, 0, 0, 0, 0, 0};
     DGNAddRawAttrLink( hDGN, psCore, 8, abyRawZeroLinkage );
-    
-    return psCore;
+
+    return (DGNElemCore*) psCH;
 }
 
 /************************************************************************/
@@ -1882,26 +1876,26 @@ DGNCreateSolidHeaderElem( DGNHandle hDGN, int nType, int nSurfType,
  * Create 3D solid/surface header.
  *
  * This function is similar to DGNCreateSolidHeaderElem(), but it takes
- * care of computing the total size of the set of elements being written, 
+ * care of computing the total size of the set of elements being written,
  * and collecting the bounding extents.  It also takes care of some other
- * convenience issues, like marking all the member elements as complex, and 
- * setting the level based on the level of the member elements. 
- * 
+ * convenience issues, like marking all the member elements as complex, and
+ * setting the level based on the level of the member elements.
+ *
  * @param hDGN the file on which the element will be written.
  * @param nType DGNT_3DSURFACE_HEADER or DGNT_3DSOLID_HEADER.
- * @param nSurfType the surface/solid type, one of DGNSUT_* or DGNSOT_*. 
- * @param nBoundElems the number of boundary elements. 
+ * @param nSurfType the surface/solid type, one of DGNSUT_* or DGNSOT_*.
+ * @param nBoundElems the number of boundary elements.
  * @param nNumElems the number of elements in the solid not including
- * the header element. 
+ * the header element.
  * @param papsElems array of pointers to nNumElems elements in the solid.
- * Some updates may be made to these elements. 
+ * Some updates may be made to these elements.
  *
- * @return the new element (DGNElemComplexHeader) or NULL on failure. 
+ * @return the new element (DGNElemComplexHeader) or NULL on failure.
  */
 
 DGNElemCore *
 DGNCreateSolidHeaderFromGroup( DGNHandle hDGN, int nType, int nSurfType,
-                               int nBoundElems, int nNumElems, 
+                               int nBoundElems, int nNumElems,
                                DGNElemCore **papsElems )
 
 {
@@ -1914,7 +1908,7 @@ DGNCreateSolidHeaderFromGroup( DGNHandle hDGN, int nType, int nSurfType,
 
     if( nNumElems < 1 || papsElems == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Need at least one element to form a solid." );
         return NULL;
     }
@@ -1935,7 +1929,7 @@ DGNCreateSolidHeaderFromGroup( DGNHandle hDGN, int nType, int nSurfType,
 
         if( papsElems[i]->level != nLevel )
         {
-            CPLError( CE_Warning, CPLE_AppDefined, 
+            CPLError( CE_Warning, CPLE_AppDefined,
                       "Not all level values matching in a complex set group!");
         }
 
@@ -1959,13 +1953,13 @@ DGNCreateSolidHeaderFromGroup( DGNHandle hDGN, int nType, int nSurfType,
 /* -------------------------------------------------------------------- */
 /*      Create the corresponding solid header.                          */
 /* -------------------------------------------------------------------- */
-    psCH = DGNCreateSolidHeaderElem( hDGN, nType, nSurfType, nBoundElems, 
+    psCH = DGNCreateSolidHeaderElem( hDGN, nType, nSurfType, nBoundElems,
                                      nTotalLength, nNumElems );
     DGNUpdateElemCore( hDGN, psCH, papsElems[0]->level, psCH->graphic_group,
                        psCH->color, psCH->weight, psCH->style );
 
     DGNWriteBounds( (DGNInfo *) hDGN, psCH, &sMin, &sMax );
-    
+
     return psCH;
 }
 
@@ -1974,9 +1968,9 @@ DGNCreateSolidHeaderFromGroup( DGNHandle hDGN, int nType, int nSurfType,
 /************************************************************************/
 
 DGNElemCore CPL_DLL  *
-DGNCreateCellHeaderElem( DGNHandle hDGN, int nTotLength, const char *pszName, 
-                         short nClass, short *panLevels, 
-                         DGNPoint *psRangeLow, DGNPoint *psRangeHigh, 
+DGNCreateCellHeaderElem( DGNHandle hDGN, int nTotLength, const char *pszName,
+                         short nClass, short *panLevels,
+                         DGNPoint *psRangeLow, DGNPoint *psRangeHigh,
                          DGNPoint *psOrigin, double dfXScale, double dfYScale,
                          double dfRotation )
 
@@ -1992,23 +1986,23 @@ DGNCreateCellHeaderElem( DGNHandle hDGN, int nTotLength, const char *pszName,
  *
  * @param hDGN the file handle on which the element is to be written.
  * @param nTotLength total length of cell in words not including the 38 bytes
- * of the cell header that occur before the totlength indicator. 
- * @param nClass the class value for the cell. 
+ * of the cell header that occur before the totlength indicator.
+ * @param nClass the class value for the cell.
  * @param panLevels an array of shorts holding the bit mask of levels in
- * effect for this cell.  This array should contain 4 shorts (64 bits). 
- * @param psRangeLow the cell diagonal origin in original cell file 
+ * effect for this cell.  This array should contain 4 shorts (64 bits).
+ * @param psRangeLow the cell diagonal origin in original cell file
  * coordinates.
- * @param psRangeHigh the cell diagonal top left corner in original cell file 
+ * @param psRangeHigh the cell diagonal top left corner in original cell file
  * coordinates.
- * @param psOrigin the origin of the cell in output file coordinates. 
- * @param dfXScale the amount of scaling applied in the X dimension in 
+ * @param psOrigin the origin of the cell in output file coordinates.
+ * @param dfXScale the amount of scaling applied in the X dimension in
  * mapping from cell file coordinates to output file coordinates.
- * @param dfYScale the amount of scaling applied in the Y dimension in 
+ * @param dfYScale the amount of scaling applied in the Y dimension in
  * mapping from cell file coordinates to output file coordinates.
- * @param dfRotation the amount of rotation (degrees counterclockwise) in 
- * mapping from cell coordinates to output file coordinates. 
+ * @param dfRotation the amount of rotation (degrees counterclockwise) in
+ * mapping from cell coordinates to output file coordinates.
  *
- * @return the new element (DGNElemCellHeader) or NULL on failure. 
+ * @return the new element (DGNElemCellHeader) or NULL on failure.
  */
 
 {
@@ -2044,7 +2038,7 @@ DGNCreateCellHeaderElem( DGNHandle hDGN, int nTotLength, const char *pszName,
 
     psCore->raw_data[36] = (unsigned char) (nTotLength % 256);
     psCore->raw_data[37] = (unsigned char) (nTotLength / 256);
-    
+
     DGNAsciiToRad50( pszName, (unsigned short *) (psCore->raw_data + 38) );
     if( strlen(pszName) > 3 )
         DGNAsciiToRad50( pszName+3, (unsigned short *) (psCore->raw_data+40) );
@@ -2058,16 +2052,16 @@ DGNCreateCellHeaderElem( DGNHandle hDGN, int nTotLength, const char *pszName,
     {
         DGNPointToInt( psInfo, psRangeLow, psCore->raw_data + 52 );
         DGNPointToInt( psInfo, psRangeHigh, psCore->raw_data+ 60 );
-        
-        DGNInverseTransformPointToInt( psInfo, psOrigin, 
+
+        DGNInverseTransformPointToInt( psInfo, psOrigin,
                                        psCore->raw_data + 84 );
     }
     else
     {
         DGNPointToInt( psInfo, psRangeLow, psCore->raw_data + 52 );
         DGNPointToInt( psInfo, psRangeHigh, psCore->raw_data+ 64 );
-        
-        DGNInverseTransformPointToInt( psInfo, psOrigin, 
+
+        DGNInverseTransformPointToInt( psInfo, psOrigin,
                                        psCore->raw_data + 112 );
     }
 
@@ -2078,14 +2072,14 @@ DGNCreateCellHeaderElem( DGNHandle hDGN, int nTotLength, const char *pszName,
     if( psInfo->dimension == 2 )
     {
         long anTrans[4];
-        double cos_a = cos(-dfRotation * PI / 180.0);
-        double sin_a = sin(-dfRotation * PI / 180.0);
-        
+        double cos_a = cos(-dfRotation * M_PI / 180.0);
+        double sin_a = sin(-dfRotation * M_PI / 180.0);
+
         anTrans[0] = (long) (cos_a * dfXScale * 214748);
         anTrans[1] = (long) (sin_a * dfYScale * 214748);
         anTrans[2] = (long)(-sin_a * dfXScale * 214748);
         anTrans[3] = (long) (cos_a * dfYScale * 214748);
-        
+
         DGN_WRITE_INT32( anTrans[0], psCore->raw_data + 68 );
         DGN_WRITE_INT32( anTrans[1], psCore->raw_data + 72 );
         DGN_WRITE_INT32( anTrans[2], psCore->raw_data + 76 );
@@ -2093,14 +2087,42 @@ DGNCreateCellHeaderElem( DGNHandle hDGN, int nTotLength, const char *pszName,
     }
     else
     {
+        long anTrans[9];
+
+        // NOTE: This is still just rotation in the plane
+        double cos_a = cos(-dfRotation * M_PI / 180.0);
+        double sin_a = sin(-dfRotation * M_PI / 180.0);
+        double dfZScale = 1.0; // Should we get this from somewhere?
+
+        anTrans[0] = (long) ( cos_a * dfXScale * 214748);
+        anTrans[1] = (long) ( sin_a * dfYScale * 214748);
+        anTrans[2] = (long) ( sin_a * dfZScale * 214748);
+
+        anTrans[3] = (long) (-sin_a * dfXScale * 214748);
+        anTrans[4] = (long) ( cos_a * dfYScale * 214748);
+        anTrans[5] = (long) ( sin_a * dfZScale * 214748);
+
+        anTrans[6] = (long) (-sin_a * dfXScale * 214748);
+        anTrans[7] = (long) (-sin_a * dfYScale * 214748);
+        anTrans[8] = (long) ( cos_a * dfZScale * 214748);
+
+        DGN_WRITE_INT32( anTrans[0], psCore->raw_data + 76 );
+        DGN_WRITE_INT32( anTrans[1], psCore->raw_data + 80 );
+        DGN_WRITE_INT32( anTrans[2], psCore->raw_data + 84 );
+        DGN_WRITE_INT32( anTrans[3], psCore->raw_data + 88 );
+        DGN_WRITE_INT32( anTrans[4], psCore->raw_data + 92 );
+        DGN_WRITE_INT32( anTrans[5], psCore->raw_data + 96 );
+        DGN_WRITE_INT32( anTrans[6], psCore->raw_data + 100 );
+        DGN_WRITE_INT32( anTrans[7], psCore->raw_data + 104 );
+        DGN_WRITE_INT32( anTrans[8], psCore->raw_data + 108 );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Set the core raw data.                                          */
 /* -------------------------------------------------------------------- */
     DGNUpdateElemCoreExtended( hDGN, psCore );
-    
-    return psCore;
+
+    return (DGNElemCore*) psCH;
 }
 
 /************************************************************************/
@@ -2111,7 +2133,7 @@ DGNCreateCellHeaderElem( DGNHandle hDGN, int nTotLength, const char *pszName,
 /*      range section of the CELL HEADER.                               */
 /************************************************************************/
 
-static void DGNPointToInt( DGNInfo *psDGN, DGNPoint *psPoint, 
+static void DGNPointToInt( DGNInfo *psDGN, DGNPoint *psPoint,
                            unsigned char *pabyTarget )
 
 {
@@ -2122,14 +2144,15 @@ static void DGNPointToInt( DGNInfo *psDGN, DGNPoint *psPoint,
     adfCT[1] = psPoint->y;
     adfCT[2] = psPoint->z;
 
-    for( i = 0; i < psDGN->dimension; i++ )
+    const int nIter = MIN(3, psDGN->dimension);
+    for( i = 0; i < nIter; i++ )
     {
         GInt32 nCTI;
         unsigned char *pabyCTI = (unsigned char *) &nCTI;
 
         nCTI = (GInt32) MAX(-2147483647,MIN(2147483647,adfCT[i]));
-        
-#ifdef WORDS_BIGENDIAN 
+
+#ifdef WORDS_BIGENDIAN
         pabyTarget[i*4+0] = pabyCTI[1];
         pabyTarget[i*4+1] = pabyCTI[0];
         pabyTarget[i*4+2] = pabyCTI[3];
@@ -2139,7 +2162,7 @@ static void DGNPointToInt( DGNInfo *psDGN, DGNPoint *psPoint,
         pabyTarget[i*4+2] = pabyCTI[0];
         pabyTarget[i*4+1] = pabyCTI[3];
         pabyTarget[i*4+0] = pabyCTI[2];
-#endif        
+#endif
     }
 }
 
@@ -2159,30 +2182,30 @@ static void DGNPointToInt( DGNInfo *psDGN, DGNPoint *psPoint,
  * diagonal range values will only be written if 1.0 is used for the x and y
  * scale values, and 0.0 for the rotation.  Use of other values will result
  * in incorrect scaling handles being presented to the user in Microstation
- * when they select the element.  
+ * when they select the element.
  *
  * @param hDGN the file handle on which the element is to be written.
- * @param nClass the class value for the cell. 
+ * @param nClass the class value for the cell.
  * @param panLevels an array of shorts holding the bit mask of levels in
- * effect for this cell.  This array should contain 4 shorts (64 bits). 
+ * effect for this cell.  This array should contain 4 shorts (64 bits).
  * This array would normally be passed in as NULL, and the function will
- * build a mask from the passed list of elements. 
- * @param psOrigin the origin of the cell in output file coordinates. 
- * @param dfXScale the amount of scaling applied in the X dimension in 
+ * build a mask from the passed list of elements.
+ * @param psOrigin the origin of the cell in output file coordinates.
+ * @param dfXScale the amount of scaling applied in the X dimension in
  * mapping from cell file coordinates to output file coordinates.
- * @param dfYScale the amount of scaling applied in the Y dimension in 
+ * @param dfYScale the amount of scaling applied in the Y dimension in
  * mapping from cell file coordinates to output file coordinates.
- * @param dfRotation the amount of rotation (degrees counterclockwise) in 
- * mapping from cell coordinates to output file coordinates. 
+ * @param dfRotation the amount of rotation (degrees counterclockwise) in
+ * mapping from cell coordinates to output file coordinates.
  *
- * @return the new element (DGNElemCellHeader) or NULL on failure. 
+ * @return the new element (DGNElemCellHeader) or NULL on failure.
  */
 
 DGNElemCore *
-DGNCreateCellHeaderFromGroup( DGNHandle hDGN, const char *pszName, 
-                              short nClass, short *panLevels, 
+DGNCreateCellHeaderFromGroup( DGNHandle hDGN, const char *pszName,
+                              short nClass, short *panLevels,
                               int nNumElems, DGNElemCore **papsElems,
-                              DGNPoint *psOrigin, 
+                              DGNPoint *psOrigin,
                               double dfXScale, double dfYScale,
                               double dfRotation )
 
@@ -2191,14 +2214,14 @@ DGNCreateCellHeaderFromGroup( DGNHandle hDGN, const char *pszName,
     int         i /* , nLevel */;
     DGNElemCore *psCH;
     DGNPoint    sMin={0.0,0.0,0.0}, sMax={0.0,0.0,0.0};
-    unsigned char abyLevelsOccuring[8] = {0,0,0,0,0,0,0,0};
+    unsigned char abyLevelsOccurring[8] = {0,0,0,0,0,0,0,0};
     DGNInfo *psInfo = (DGNInfo *) hDGN;
 
     DGNLoadTCB( hDGN );
 
     if( nNumElems < 1 || papsElems == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Need at least one element to form a cell." );
         return NULL;
     }
@@ -2227,8 +2250,8 @@ DGNCreateCellHeaderFromGroup( DGNHandle hDGN, const char *pszName,
         /* establish level */
         nLevel = papsElems[i]->level;
         nLevel = MAX(1,MIN(nLevel,64));
-        abyLevelsOccuring[(nLevel-1) >> 3] |= (0x1 << ((nLevel-1)&0x7));
-        
+        abyLevelsOccurring[(nLevel-1) >> 3] |= (0x1 << ((nLevel-1)&0x7));
+
         DGNGetElementExtents( hDGN, papsElems[i], &sThisMin, &sThisMax );
         if( i == 0 )
         {
@@ -2273,16 +2296,16 @@ DGNCreateCellHeaderFromGroup( DGNHandle hDGN, const char *pszName,
 /*      Create the corresponding cell header.                           */
 /* -------------------------------------------------------------------- */
     if( panLevels == NULL )
-        panLevels = (short *) abyLevelsOccuring + 0;
+        panLevels = (short *) abyLevelsOccurring + 0;
 
-    psCH = DGNCreateCellHeaderElem( hDGN, nTotalLength, pszName, 
-                                    nClass, panLevels, 
-                                    &sMin, &sMax, psOrigin, 
+    psCH = DGNCreateCellHeaderElem( hDGN, nTotalLength, pszName,
+                                    nClass, panLevels,
+                                    &sMin, &sMax, psOrigin,
                                     dfXScale, dfYScale, dfRotation );
     DGNWriteBounds( (DGNInfo *) hDGN, psCH, &sMin, &sMax );
-    
+
     return psCH;
-    
+
 }
 
 /************************************************************************/
@@ -2292,23 +2315,23 @@ DGNCreateCellHeaderFromGroup( DGNHandle hDGN, const char *pszName,
 /**
  * Add a database link to element.
  *
- * The target element must already have raw_data loaded, and it will be 
- * resized (see DGNResizeElement()) as needed for the new attribute data. 
- * Note that the element is not written to disk immediate.  Use 
- * DGNWriteElement() for that. 
+ * The target element must already have raw_data loaded, and it will be
+ * resized (see DGNResizeElement()) as needed for the new attribute data.
+ * Note that the element is not written to disk immediate.  Use
+ * DGNWriteElement() for that.
  *
  * @param hDGN the file to which the element corresponds.
  * @param psElement the element being updated.
- * @param nLinkageType link type (DGNLT_*).  Usually one of DGNLT_DMRS, 
- * DGNLT_INFORMIX, DGNLT_ODBC, DGNLT_ORACLE, DGNLT_RIS, DGNLT_SYBASE, 
- * or DGNLT_XBASE. 
+ * @param nLinkageType link type (DGNLT_*).  Usually one of DGNLT_DMRS,
+ * DGNLT_INFORMIX, DGNLT_ODBC, DGNLT_ORACLE, DGNLT_RIS, DGNLT_SYBASE,
+ * or DGNLT_XBASE.
  * @param nEntityNum indicator of the table referenced on target database.
  * @param nMSLink indicator of the record referenced on target table.
  *
- * @return -1 on failure, or the link index. 
- */ 
+ * @return -1 on failure, or the link index.
+ */
 
-int DGNAddMSLink( DGNHandle hDGN, DGNElemCore *psElement, 
+int DGNAddMSLink( DGNHandle hDGN, DGNElemCore *psElement,
                   int nLinkageType, int nEntityNum, int nMSLink )
 
 {
@@ -2359,26 +2382,26 @@ int DGNAddMSLink( DGNHandle hDGN, DGNElemCore *psElement,
  * Add a raw attribute linkage to element.
  *
  * Given a raw data buffer, append it to this element as an attribute linkage
- * without trying to interprete the linkage data.   
+ * without trying to interpret the linkage data.
  *
- * The target element must already have raw_data loaded, and it will be 
- * resized (see DGNResizeElement()) as needed for the new attribute data. 
- * Note that the element is not written to disk immediate.  Use 
- * DGNWriteElement() for that. 
+ * The target element must already have raw_data loaded, and it will be
+ * resized (see DGNResizeElement()) as needed for the new attribute data.
+ * Note that the element is not written to disk immediate.  Use
+ * DGNWriteElement() for that.
  *
- * This function will take care of updating the "totlength" field of 
+ * This function will take care of updating the "totlength" field of
  * complex chain or shape headers to account for the extra attribute space
  * consumed in the header element.
  *
  * @param hDGN the file to which the element corresponds.
  * @param psElement the element being updated.
- * @param nLinkSize the size of the linkage in bytes. 
- * @param pabyRawLinkData the raw linkage data (nLinkSize bytes worth). 
+ * @param nLinkSize the size of the linkage in bytes.
+ * @param pabyRawLinkData the raw linkage data (nLinkSize bytes worth).
  *
- * @return -1 on failure, or the link index. 
- */ 
+ * @return -1 on failure, or the link index.
+ */
 
-int DGNAddRawAttrLink( DGNHandle hDGN, DGNElemCore *psElement, 
+int DGNAddRawAttrLink( DGNHandle hDGN, DGNElemCore *psElement,
                        int nLinkSize, unsigned char *pabyRawLinkData )
 
 {
@@ -2389,13 +2412,13 @@ int DGNAddRawAttrLink( DGNHandle hDGN, DGNElemCore *psElement,
 
     if( psElement->size + nLinkSize > 768 )
     {
-        CPLError( CE_Failure, CPLE_ElementTooBig, 
+        CPLError( CE_Failure, CPLE_ElementTooBig,
                   "Attempt to add %d byte linkage to element exceeds maximum"
-                  " element size.", 
+                  " element size.",
                   nLinkSize );
         return -1;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Ensure the attribute linkage bit is set.                        */
 /* -------------------------------------------------------------------- */
@@ -2405,10 +2428,10 @@ int DGNAddRawAttrLink( DGNHandle hDGN, DGNElemCore *psElement,
 /*      Append the attribute linkage to the linkage area.               */
 /* -------------------------------------------------------------------- */
     psElement->attr_bytes += nLinkSize;
-    psElement->attr_data = (unsigned char *) 
+    psElement->attr_data = (unsigned char *)
         CPLRealloc( psElement->attr_data, psElement->attr_bytes );
-    
-    memcpy( psElement->attr_data + (psElement->attr_bytes-nLinkSize), 
+
+    memcpy( psElement->attr_data + (psElement->attr_bytes-nLinkSize),
             pabyRawLinkData, nLinkSize );
 
 /* -------------------------------------------------------------------- */
@@ -2462,23 +2485,23 @@ int DGNAddRawAttrLink( DGNHandle hDGN, DGNElemCore *psElement,
 /**
  * Add a shape fill attribute linkage.
  *
- * The target element must already have raw_data loaded, and it will be 
- * resized (see DGNResizeElement()) as needed for the new attribute data. 
- * Note that the element is not written to disk immediate.  Use 
- * DGNWriteElement() for that. 
+ * The target element must already have raw_data loaded, and it will be
+ * resized (see DGNResizeElement()) as needed for the new attribute data.
+ * Note that the element is not written to disk immediate.  Use
+ * DGNWriteElement() for that.
  *
  * @param hDGN the file to which the element corresponds.
  * @param psElement the element being updated.
  * @param nColor fill color (color index from palette).
  *
- * @return -1 on failure, or the link index. 
- */ 
+ * @return -1 on failure, or the link index.
+ */
 
-int DGNAddShapeFillInfo( DGNHandle hDGN, DGNElemCore *psElement, 
+int DGNAddShapeFillInfo( DGNHandle hDGN, DGNElemCore *psElement,
                           int nColor )
 
 {
-    unsigned char abyFillInfo[16] = 
+    unsigned char abyFillInfo[16] =
     { 0x07, 0x10, 0x41, 0x00, 0x02, 0x08, 0x01, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 
diff --git a/ogr/ogrsf_frmts/dgn/dgnwritetest.c b/ogr/ogrsf_frmts/dgn/dgnwritetest.c
index 1d9e86c..25c808d 100644
--- a/ogr/ogrsf_frmts/dgn/dgnwritetest.c
+++ b/ogr/ogrsf_frmts/dgn/dgnwritetest.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dgnwritetest.c 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: dgnwritetest.c 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Microstation DGN Access Library
  * Purpose:  Test program for use of write api.
@@ -29,7 +29,7 @@
 
 #include "dgnlib.h"
 
-CPL_CVSID("$Id: dgnwritetest.c 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: dgnwritetest.c 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                                main()                                */
@@ -46,9 +46,9 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
 /*      Create new DGN file.                                            */
 /* -------------------------------------------------------------------- */
-    hNewDGN = DGNCreate( "out.dgn", "seed.dgn", 
+    hNewDGN = DGNCreate( "out.dgn", "seed.dgn",
                          DGNCF_USE_SEED_UNITS
-                         | DGNCF_USE_SEED_ORIGIN, 
+                         | DGNCF_USE_SEED_ORIGIN,
                          0.0, 0.0, 0.0, 0, 0, "", "" );
 
     if( hNewDGN == NULL )
@@ -92,10 +92,10 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
 /*      Write an Arc.                                                   */
 /* -------------------------------------------------------------------- */
-    psLine = DGNCreateArcElem( hNewDGN, DGNT_ARC, 
-                               2000.0, 3000.0, 500.0, 2000.0, 1000.0, 
+    psLine = DGNCreateArcElem( hNewDGN, DGNT_ARC,
+                               2000.0, 3000.0, 500.0, 2000.0, 1000.0,
                                0.0, 270.0, 0.0, NULL );
-    
+
     DGNUpdateElemCore( hNewDGN, psLine, 15, 0, 3, 1, 0 );
     DGNWriteElement( hNewDGN, psLine );
     DGNFreeElement( hNewDGN, psLine );
@@ -103,10 +103,10 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
 /*      Write an Ellipse with fill info.                                */
 /* -------------------------------------------------------------------- */
-    psLine = DGNCreateArcElem( hNewDGN, DGNT_ELLIPSE, 
-                               200.0, 30.0, 5.0, 10.0, 10.0, 
+    psLine = DGNCreateArcElem( hNewDGN, DGNT_ELLIPSE,
+                               200.0, 30.0, 5.0, 10.0, 10.0,
                                0.0, 360.0, 0.0, NULL );
-    
+
     DGNUpdateElemCore( hNewDGN, psLine, 15, 0, 3, 1, 0 );
     DGNWriteElement( hNewDGN, psLine );
     DGNFreeElement( hNewDGN, psLine );
@@ -114,7 +114,7 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
 /*      Write some text.                                                */
 /* -------------------------------------------------------------------- */
-    psLine = DGNCreateTextElem( hNewDGN, "This is a test string", 
+    psLine = DGNCreateTextElem( hNewDGN, "This is a test string",
                                 0, DGNJ_CENTER_TOP, 200.0, 200.0, 0.0, NULL,
                                 2000.0, 3000.0, 0.0 );
 
@@ -150,7 +150,7 @@ int main( int argc, char ** argv )
     asPoints[2].x = 6000;
     asPoints[2].y = 6000;
 
-    psMembers[0] = DGNCreateMultiPointElem( hNewDGN, DGNT_LINE_STRING, 3, 
+    psMembers[0] = DGNCreateMultiPointElem( hNewDGN, DGNT_LINE_STRING, 3,
                                             asPoints );
     DGNUpdateElemCore( hNewDGN, psMembers[0], 9, 0, 3, 1, 0 );
 
@@ -161,11 +161,11 @@ int main( int argc, char ** argv )
     asPoints[2].x = 8000;
     asPoints[2].y = 8000;
 
-    psMembers[1] = DGNCreateMultiPointElem( hNewDGN, DGNT_LINE_STRING, 3, 
+    psMembers[1] = DGNCreateMultiPointElem( hNewDGN, DGNT_LINE_STRING, 3,
                                             asPoints );
     DGNUpdateElemCore( hNewDGN, psMembers[1], 9, 0, 3, 1, 0 );
 
-    psLine = DGNCreateComplexHeaderFromGroup( hNewDGN, 
+    psLine = DGNCreateComplexHeaderFromGroup( hNewDGN,
                                               DGNT_COMPLEX_SHAPE_HEADER,
                                               2, psMembers );
 
@@ -190,7 +190,7 @@ int main( int argc, char ** argv )
     asPoints[2].x = 5000;
     asPoints[2].y = 5000;
 
-    psMembers[0] = DGNCreateMultiPointElem( hNewDGN, DGNT_LINE_STRING, 3, 
+    psMembers[0] = DGNCreateMultiPointElem( hNewDGN, DGNT_LINE_STRING, 3,
                                             asPoints );
     DGNUpdateElemCore( hNewDGN, psMembers[0], 10, 0, 3, 1, 0 );
 
@@ -201,7 +201,7 @@ int main( int argc, char ** argv )
     asPoints[2].x = 7000;
     asPoints[2].y = 7000;
 
-    psMembers[1] = DGNCreateMultiPointElem( hNewDGN, DGNT_LINE_STRING, 3, 
+    psMembers[1] = DGNCreateMultiPointElem( hNewDGN, DGNT_LINE_STRING, 3,
                                             asPoints );
     DGNUpdateElemCore( hNewDGN, psMembers[1], 9, 0, 3, 1, 0 );
 
@@ -209,7 +209,7 @@ int main( int argc, char ** argv )
     asPoints[0].y = 5000;
 
     psLine = DGNCreateCellHeaderFromGroup( hNewDGN, "BE70", 1, NULL,
-                                           2, psMembers, asPoints + 0, 
+                                           2, psMembers, asPoints + 0,
                                            1.0, 1.0, 0.0 );
 
     DGNWriteElement( hNewDGN, psLine );
@@ -227,6 +227,3 @@ int main( int argc, char ** argv )
 
     return 0;
 }
-
-
-
diff --git a/ogr/ogrsf_frmts/dgn/dist/README b/ogr/ogrsf_frmts/dgn/dist/README
index d3b5451..f6ae5f4 100644
--- a/ogr/ogrsf_frmts/dgn/dist/README
+++ b/ogr/ogrsf_frmts/dgn/dist/README
@@ -119,7 +119,7 @@ Release 1.8
 Release 1.7
 -----------
 
- o Improved calcuation of bounding box in DGLCreateTextElem() based on code
+ o Improved calculation of bounding box in DGLCreateTextElem() based on code
    from Matt Kelder. 
 
  o Added preliminary 3D write support. 
@@ -172,15 +172,15 @@ Release 1.4
    This basically just reads the extents information at beginning of 
    geometric features to see if they should be returned. 
 
- o Actually extract the global origin from the TCB, and use it when 
-   transforming points.  Only a few files (ie. Brazos County roads.rds) use
+ o Actually extract the global origin from the TCB, and use it when
+   transforming points.  Only a few files (i.e. Brazos County roads.rds) use
    a non-zero origin.
 
  o Added experimental multi byte text support from Ason Kang
    (hiska at netian.com). 
 
- o Add experimental support for 3D files.  Somes 3d elements not supported. 
-   3d quaterion for ellipse and arc elements not utilized. 
+ o Add experimental support for 3D files.  Some 3D elements not supported.
+   3D quaternion for ellipse and arc elements not utilized.
 
  o Added preliminary support for reading cell header structures based
    on input from Mike Cane. 
diff --git a/ogr/ogrsf_frmts/dgn/drv_dgn.html b/ogr/ogrsf_frmts/dgn/drv_dgn.html
index 8708e50..c706d24 100644
--- a/ogr/ogrsf_frmts/dgn/drv_dgn.html
+++ b/ogr/ogrsf_frmts/dgn/drv_dgn.html
@@ -11,20 +11,20 @@ Microstation DGN files from Microstation versions predating version 8.0
 are supported for reading.  The entire file is represented as one layer
 (named "elements").<p>
 
-DGN files are considered to have no georeferencing information through OGR. 
+DGN files are considered to have no georeferencing information through OGR.
 Features will all have the following generic attributes:
 
 <ul>
-<li> Type: The integer type code as listed below in supported elements. 
-<li> Level: The DGN level number (0-63). 
+<li> Type: The integer type code as listed below in supported elements.
+<li> Level: The DGN level number (0-63).
 <li> GraphicGroup: The graphic group number.
 <li> ColorIndex: The color index from the dgn palette.
-<li> Weight: The drawing weight (thickness) for the element. 
-<li> Style: The style value for the element. 
+<li> Weight: The drawing weight (thickness) for the element.
+<li> Style: The style value for the element.
 </ul>
 
 DGN files do not contain spatial indexes; however, the DGN driver does take
-advantage of the extents information at the beginning of each element to 
+advantage of the extents information at the beginning of each element to
 minimize processing of elements outside the current spatial filter window
 when in effect.<p>
 
@@ -33,9 +33,9 @@ when in effect.<p>
 The following element types are supported:<p>
 
 <ul>
-<li> Line (3): Line geometry. 
+<li> Line (3): Line geometry.
 <li> Line String (4): Multi segment line geometry.
-<li> Shape (6): Polygon geometry. 
+<li> Shape (6): Polygon geometry.
 <li> Curve (11): Approximated as a line geometry.
 <li> B-Spline (21): Treated (inaccurately) as a line geometry.
 <li> Arc (16): Approximated as a line geometry.
@@ -54,13 +54,13 @@ Weight and Style generic attributes; however, for all features an OGR
 style string has been prepared with the values encoded in ready-to-use form
 for applications supporting OGR style strings.<p>
 
-The various kinds of linear geomtries will carry style information indicating
-the color, thickness and line style (ie. dotted, solid, etc).<p>
+The various kinds of linear geometries will carry style information indicating
+the color, thickness and line style (i.e. dotted, solid, etc).<p>
 
-Polygons (Shape elements) will carry styling information for the edge as well 
+Polygons (Shape elements) will carry styling information for the edge as well
 as a fill color if provided.  Fill patterns are not supported.<p>
 
-Text elements will contain the text, angle, color and size information 
+Text elements will contain the text, angle, color and size information
 (expressed in ground units) in the style string.<p>
 
 <h2>Creation Issues</h2>
@@ -81,13 +81,13 @@ line element. <p>
 <li> Polygon, and multipolygon objects will be translated to simple polygons
 with all rings other than the first discarded.<p>
 
-<li> Polygons and line strings with too many vertices will be split into 
-a group of elmements prefixed with a Complex Shape Header or Complex Chain
+<li> Polygons and line strings with too many vertices will be split into
+a group of elements prefixed with a Complex Shape Header or Complex Chain
 Header element as appropriate. <p>
 
-<li> A seed file must be provided (or if not provided, 
+<li> A seed file must be provided (or if not provided,
 $PREFIX/share/gdal/seed_2d.dgn will be used).  Many aspects of the resulting
-DGN file are determined by the seed file, and cannot be affected via OGR, 
+DGN file are determined by the seed file, and cannot be affected via OGR,
 such as initial view window. <p>
 
 <li> The various collection geometries other than MultiPolygon are completely
@@ -105,14 +105,14 @@ The dataset creation supports the following options:<p>
 
 <ul>
 
-<li> <b>3D=</b><i>YES</i> or <i>NO</i>: Determine whether 2D (seed_2d.dgn) 
-or 3D (seed_3d.dgn) seed file should be used.  This option is ignored if the 
+<li> <b>3D=</b><i>YES</i> or <i>NO</i>: Determine whether 2D (seed_2d.dgn)
+or 3D (seed_3d.dgn) seed file should be used.  This option is ignored if the
 SEED option is provided.<p>
 
 <li> <b>SEED=</b><i>filename</i>: Override the seed file to use.<p>
 
 <li> <b>COPY_WHOLE_SEED_FILE=</b><i>YES/NO</i>: Indicate whether the whole
-seed file should be copied.  If not, only the first three elements (and 
+seed file should be copied.  If not, only the first three elements (and
 potentially the color table) will be copied.  Default is NO.<p>
 
 <li> <b>COPY_SEED_FILE_COLOR_TABLE=</b><i>YES/NO</i>: Indicates whether the
@@ -128,7 +128,7 @@ the seed file with the provided one or two character unit name. <p>
 subunits per master unit.  By default the seed file value is used.<p>
 
 <li> <b>UOR_PER_SUB_UNIT=</b><i>count</i>: Override the number of
-UORs (Units of Resolution) per sub unit.  By default the seed file value is 
+UORs (Units of Resolution) per sub unit.  By default the seed file value is
 used.<p>
 
 <li> <b>ORIGIN</b>=<i>x,y,z</i>: Override the origin of the design plane.  By
@@ -140,7 +140,7 @@ default the origin from the seed file is used.<p>
 
 <ul>
 <li> <a href="http://dgnlib.maptools.org/">Dgnlib Page</a>
-<li> <a href="http://home.gdal.org/projects/opengis/ogr_feature_style.html">OGR Feature Style Specification</a>
+<li> <a href="http://gdal.org/ogr_feature_style.html">OGR Feature Style Specification</a>
 </ul>
 
 </body>
diff --git a/ogr/ogrsf_frmts/dgn/ogr_dgn.h b/ogr/ogrsf_frmts/dgn/ogr_dgn.h
index 654d64a..ba78405 100644
--- a/ogr/ogrsf_frmts/dgn/ogr_dgn.h
+++ b/ogr/ogrsf_frmts/dgn/ogr_dgn.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_dgn.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogr_dgn.h 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGR Driver for DGN Reader.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_DGN_H_INCLUDED
-#define _OGR_DGN_H_INCLUDED
+#ifndef OGR_DGN_H_INCLUDED
+#define OGR_DGN_H_INCLUDED
 
 #include "dgnlib.h"
 #include "ogrsf_frmts.h"
@@ -56,7 +56,8 @@ class OGRDGNLayer : public OGRLayer
     DGNElemCore       **LineStringToElementGroup( OGRLineString *, int );
     DGNElemCore       **TranslateLabel( OGRFeature * );
 
-    int                 bHaveSimpleQuery;
+    // Unused:
+    // int                 bHaveSimpleQuery;
     OGRFeature         *poEvalFeature;
 
     OGRErr              CreateFeatureWithGeom( OGRFeature *, OGRGeometry * );
@@ -67,6 +68,8 @@ class OGRDGNLayer : public OGRLayer
                         ~OGRDGNLayer();
 
     void                SetSpatialFilter( OGRGeometry * );
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+                { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
 
     void                ResetReading();
     OGRFeature *        GetNextFeature();
@@ -74,6 +77,8 @@ class OGRDGNLayer : public OGRLayer
 
     virtual GIntBig     GetFeatureCount( int bForce = TRUE );
     virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
     OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
 
@@ -91,12 +96,12 @@ class OGRDGNDataSource : public OGRDataSource
 {
     OGRDGNLayer     **papoLayers;
     int                 nLayers;
-    
+
     char                *pszName;
     DGNHandle           hDGN;
 
     char                **papszOptions;
-    
+
   public:
                         OGRDGNDataSource();
                         ~OGRDGNDataSource();
@@ -104,7 +109,7 @@ class OGRDGNDataSource : public OGRDataSource
     int                 Open( const char *, int bTestOpen, int bUpdate );
     int                 PreCreate( const char *, char ** );
 
-    OGRLayer           *ICreateLayer( const char *, 
+    OGRLayer           *ICreateLayer( const char *,
                                      OGRSpatialReference * = NULL,
                                      OGRwkbGeometryType = wkbUnknown,
                                      char ** = NULL );
@@ -116,4 +121,4 @@ class OGRDGNDataSource : public OGRDataSource
     int                 TestCapability( const char * );
 };
 
-#endif /* ndef _OGR_DGN_H_INCLUDED */
+#endif /* ndef OGR_DGN_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/dgn/ogrdgndatasource.cpp b/ogr/ogrsf_frmts/dgn/ogrdgndatasource.cpp
index bdd8db0..7a29c5c 100644
--- a/ogr/ogrsf_frmts/dgn/ogrdgndatasource.cpp
+++ b/ogr/ogrsf_frmts/dgn/ogrdgndatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdgndatasource.cpp 27959 2014-11-14 18:29:21Z rouault $
+ * $Id: ogrdgndatasource.cpp 33105 2016-01-23 15:27:32Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGDataSource class.
@@ -31,21 +31,19 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrdgndatasource.cpp 27959 2014-11-14 18:29:21Z rouault $");
+CPL_CVSID("$Id: ogrdgndatasource.cpp 33105 2016-01-23 15:27:32Z rouault $");
 
 /************************************************************************/
 /*                         OGRDGNDataSource()                           */
 /************************************************************************/
 
-OGRDGNDataSource::OGRDGNDataSource()
-
-{
-    papoLayers = NULL;
-    nLayers = 0;
-    hDGN = NULL;
-    pszName = NULL;
-    papszOptions = NULL;
-}
+OGRDGNDataSource::OGRDGNDataSource() :
+    papoLayers(NULL),
+    nLayers(0),
+    pszName(NULL),
+    hDGN(NULL),
+    papszOptions(NULL)
+{}
 
 /************************************************************************/
 /*                        ~OGRDGNDataSource()                           */
@@ -56,7 +54,7 @@ OGRDGNDataSource::~OGRDGNDataSource()
 {
     for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
-    
+
     CPLFree( papoLayers );
     CPLFree( pszName );
     CSLDestroy( papszOptions );
@@ -69,8 +67,8 @@ OGRDGNDataSource::~OGRDGNDataSource()
 /*                                Open()                                */
 /************************************************************************/
 
-int OGRDGNDataSource::Open( const char * pszNewName, 
-                            int bTestOpen, 
+int OGRDGNDataSource::Open( const char * pszNewName,
+                            int bTestOpen,
                             int bUpdate )
 
 {
@@ -83,15 +81,14 @@ int OGRDGNDataSource::Open( const char * pszNewName,
 /* -------------------------------------------------------------------- */
     if( bTestOpen )
     {
-        FILE    *fp;
-        GByte   abyHeader[512];
-        int     nHeaderBytes = 0;
 
-        fp = VSIFOpen( pszNewName, "rb" );
+        FILE *fp = VSIFOpen( pszNewName, "rb" );
         if( fp == NULL )
             return FALSE;
 
-        nHeaderBytes = (int) VSIFRead( abyHeader, 1, sizeof(abyHeader), fp );
+        GByte abyHeader[512];
+        const int nHeaderBytes = static_cast<int>(
+            VSIFRead( abyHeader, 1, sizeof(abyHeader), fp ) );
 
         VSIFClose( fp );
 
@@ -109,8 +106,8 @@ int OGRDGNDataSource::Open( const char * pszNewName,
     if( hDGN == NULL )
     {
         if( !bTestOpen )
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Unable to open %s as a Microstation .dgn file.\n", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Unable to open %s as a Microstation .dgn file.",
                       pszNewName );
         return FALSE;
     }
@@ -118,18 +115,16 @@ int OGRDGNDataSource::Open( const char * pszNewName,
 /* -------------------------------------------------------------------- */
 /*      Create the layer object.                                        */
 /* -------------------------------------------------------------------- */
-    OGRDGNLayer *poLayer;
-
-    poLayer = new OGRDGNLayer( "elements", hDGN, bUpdate );
+    OGRDGNLayer *poLayer = new OGRDGNLayer( "elements", hDGN, bUpdate );
     pszName = CPLStrdup( pszNewName );
 
 /* -------------------------------------------------------------------- */
 /*      Add layer to data source layer list.                            */
 /* -------------------------------------------------------------------- */
-    papoLayers = (OGRDGNLayer **)
-        CPLRealloc( papoLayers,  sizeof(OGRDGNLayer *) * (nLayers+1) );
+    papoLayers = static_cast<OGRDGNLayer **>(
+        CPLRealloc( papoLayers,  sizeof(OGRDGNLayer *) * (nLayers+1) ) );
     papoLayers[nLayers++] = poLayer;
-    
+
     return TRUE;
 }
 
@@ -142,8 +137,8 @@ int OGRDGNDataSource::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,ODsCCreateLayer) )
         return TRUE;
-    else
-        return FALSE;
+
+    return FALSE;
 }
 
 /************************************************************************/
@@ -155,8 +150,8 @@ OGRLayer *OGRDGNDataSource::GetLayer( int iLayer )
 {
     if( iLayer < 0 || iLayer >= nLayers )
         return NULL;
-    else
-        return papoLayers[iLayer];
+
+    return papoLayers[iLayer];
 }
 
 
@@ -168,11 +163,11 @@ OGRLayer *OGRDGNDataSource::GetLayer( int iLayer )
 /*      yet.  It will be created by theICreateLayer() call.             */
 /************************************************************************/
 
-int OGRDGNDataSource::PreCreate( const char *pszFilename, 
-                                 char **papszOptions )
+int OGRDGNDataSource::PreCreate( const char *pszFilename,
+                                 char **papszOptionsIn )
 
 {
-    this->papszOptions = CSLDuplicate( papszOptions );
+    this->papszOptions = CSLDuplicate( papszOptionsIn );
     pszName = CPLStrdup( pszFilename );
 
     return TRUE;
@@ -182,27 +177,20 @@ int OGRDGNDataSource::PreCreate( const char *pszFilename,
 /*                           ICreateLayer()                             */
 /************************************************************************/
 
-OGRLayer *OGRDGNDataSource::ICreateLayer( const char *pszLayerName, 
-                                         OGRSpatialReference *poSRS, 
-                                         OGRwkbGeometryType eGeomType, 
+OGRLayer *OGRDGNDataSource::ICreateLayer( const char *pszLayerName,
+                                         OGRSpatialReference *poSRS,
+                                         OGRwkbGeometryType eGeomType,
                                          char **papszExtraOptions )
 
 {
-    const char *pszSeed, *pszMasterUnit = "m", *pszSubUnit = "cm";
-    const char *pszValue;
-    int nUORPerSU=1, nSUPerMU=100;
-    int nCreationFlags = 0, b3DRequested;
-    double dfOriginX = -21474836.0,  /* default origin centered on zero */
-           dfOriginY = -21474836.0,  /* with two decimals of precision */
-           dfOriginZ = -21474836.0;
-
 /* -------------------------------------------------------------------- */
 /*      Ensure only one layer gets created.                             */
 /* -------------------------------------------------------------------- */
     if( nLayers > 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "DGN driver only supports one layer will all the elements in it." );
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "DGN driver only supports one layer will all the elements "
+                  "in it." );
         return NULL;
     }
 
@@ -210,11 +198,21 @@ OGRLayer *OGRDGNDataSource::ICreateLayer( const char *pszLayerName,
 /*      If the coordinate system is geographic, we should use a         */
 /*      localized default origin and resolution.                        */
 /* -------------------------------------------------------------------- */
+    const char *pszMasterUnit = "m";
+    const char *pszSubUnit = "cm";
+
+    int nUORPerSU = 1;
+    int nSUPerMU = 100;
+
+    double dfOriginX = -21474836.0;  // Default origin centered on zero
+    double dfOriginY = -21474836.0;  // with two decimals of precision.
+    double dfOriginZ = -21474836.0;
+
     if( poSRS != NULL && poSRS->IsGeographic() )
     {
         dfOriginX = -200.0;
         dfOriginY = -200.0;
-        
+
         pszMasterUnit = "d";
         pszSubUnit = "s";
         nSUPerMU = 3600;
@@ -226,10 +224,12 @@ OGRLayer *OGRDGNDataSource::ICreateLayer( const char *pszLayerName,
 /* -------------------------------------------------------------------- */
     papszOptions = CSLInsertStrings( papszOptions, 0, papszExtraOptions );
 
-    b3DRequested = CSLFetchBoolean( papszOptions, "3D", 
-                                    wkbHasZ(eGeomType) );
+    const bool b3DRequested
+        = CPL_TO_BOOL(CSLFetchBoolean( papszOptions, "3D",
+                           wkbHasZ(eGeomType) ));
 
-    pszSeed = CSLFetchNameValue( papszOptions, "SEED" );
+    const char *pszSeed = CSLFetchNameValue( papszOptions, "SEED" );
+    int nCreationFlags = 0;
     if( pszSeed )
         nCreationFlags |= DGNCF_USE_SEED_ORIGIN | DGNCF_USE_SEED_UNITS;
     else if( b3DRequested )
@@ -239,23 +239,24 @@ OGRLayer *OGRDGNDataSource::ICreateLayer( const char *pszLayerName,
 
     if( pszSeed == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "No seed file provided, and unable to find seed_2d.dgn." );
         return NULL;
     }
-    
+
     if( CSLFetchBoolean( papszOptions, "COPY_WHOLE_SEED_FILE", TRUE ) )
         nCreationFlags |= DGNCF_COPY_WHOLE_SEED_FILE;
     if( CSLFetchBoolean( papszOptions, "COPY_SEED_FILE_COLOR_TABLE", TRUE ) )
         nCreationFlags |= DGNCF_COPY_SEED_FILE_COLOR_TABLE;
-    
-    pszValue = CSLFetchNameValue( papszOptions, "MASTER_UNIT_NAME" );
+
+    const char *pszValue
+        = CSLFetchNameValue( papszOptions, "MASTER_UNIT_NAME" );
     if( pszValue != NULL )
     {
         nCreationFlags &= ~DGNCF_USE_SEED_UNITS;
         pszMasterUnit = pszValue;
     }
-    
+
     pszValue = CSLFetchNameValue( papszOptions, "SUB_UNIT_NAME" );
     if( pszValue != NULL )
     {
@@ -263,7 +264,6 @@ OGRLayer *OGRDGNDataSource::ICreateLayer( const char *pszLayerName,
         pszSubUnit = pszValue;
     }
 
-
     pszValue = CSLFetchNameValue( papszOptions, "SUB_UNITS_PER_MASTER_UNIT" );
     if( pszValue != NULL )
     {
@@ -281,7 +281,7 @@ OGRLayer *OGRDGNDataSource::ICreateLayer( const char *pszLayerName,
     pszValue = CSLFetchNameValue( papszOptions, "ORIGIN" );
     if( pszValue != NULL )
     {
-        char **papszTuple = CSLTokenizeStringComplex( pszValue, " ,", 
+        char **papszTuple = CSLTokenizeStringComplex( pszValue, " ,",
                                                       FALSE, FALSE );
 
         nCreationFlags &= ~DGNCF_USE_SEED_ORIGIN;
@@ -300,10 +300,10 @@ OGRLayer *OGRDGNDataSource::ICreateLayer( const char *pszLayerName,
         else
         {
             CSLDestroy(papszTuple);
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "ORIGIN is not a valid 2d or 3d tuple.\n"
                       "Separate tuple values with comma." );
-            return FALSE;
+            return NULL;
         }
         CSLDestroy(papszTuple);
     }
@@ -311,8 +311,8 @@ OGRLayer *OGRDGNDataSource::ICreateLayer( const char *pszLayerName,
 /* -------------------------------------------------------------------- */
 /*      Try creating the base file.                                     */
 /* -------------------------------------------------------------------- */
-    hDGN = DGNCreate( pszName, pszSeed, nCreationFlags, 
-                      dfOriginX, dfOriginY, dfOriginZ, 
+    hDGN = DGNCreate( pszName, pszSeed, nCreationFlags,
+                      dfOriginX, dfOriginY, dfOriginZ,
                       nSUPerMU, nUORPerSU, pszMasterUnit, pszSubUnit );
     if( hDGN == NULL )
         return NULL;
@@ -320,16 +320,14 @@ OGRLayer *OGRDGNDataSource::ICreateLayer( const char *pszLayerName,
 /* -------------------------------------------------------------------- */
 /*      Create the layer object.                                        */
 /* -------------------------------------------------------------------- */
-    OGRDGNLayer *poLayer;
-
-    poLayer = new OGRDGNLayer( pszLayerName, hDGN, TRUE );
+    OGRDGNLayer *poLayer = new OGRDGNLayer( pszLayerName, hDGN, TRUE );
 
 /* -------------------------------------------------------------------- */
 /*      Add layer to data source layer list.                            */
 /* -------------------------------------------------------------------- */
-    papoLayers = (OGRDGNLayer **)
-        CPLRealloc( papoLayers,  sizeof(OGRDGNLayer *) * (nLayers+1) );
+    papoLayers = static_cast<OGRDGNLayer **>(
+        CPLRealloc( papoLayers,  sizeof(OGRDGNLayer *) * (nLayers+1) ) );
     papoLayers[nLayers++] = poLayer;
-    
+
     return poLayer;
 }
diff --git a/ogr/ogrsf_frmts/dgn/ogrdgndriver.cpp b/ogr/ogrsf_frmts/dgn/ogrdgndriver.cpp
index 95d3092..d8cc84c 100644
--- a/ogr/ogrsf_frmts/dgn/ogrdgndriver.cpp
+++ b/ogr/ogrsf_frmts/dgn/ogrdgndriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdgndriver.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogrdgndriver.cpp 32154 2015-12-13 05:34:45Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRDGNDriver class.
@@ -30,7 +30,7 @@
 #include "ogr_dgn.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrdgndriver.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogrdgndriver.cpp 32154 2015-12-13 05:34:45Z goatbar $");
 
 /************************************************************************/
 /*                                Open()                                */
@@ -51,21 +51,20 @@ static int OGRDGNDriverIdentify( GDALOpenInfo* poOpenInfo )
 static GDALDataset *OGRDGNDriverOpen( GDALOpenInfo* poOpenInfo )
 
 {
-    OGRDGNDataSource    *poDS;
-    
     if( !OGRDGNDriverIdentify(poOpenInfo) )
         return NULL;
 
-    poDS = new OGRDGNDataSource();
+    OGRDGNDataSource *poDS = new OGRDGNDataSource();
 
-    if( !poDS->Open( poOpenInfo->pszFilename, TRUE, (poOpenInfo->eAccess == GA_Update) )
+    if( !poDS->Open( poOpenInfo->pszFilename, TRUE,
+                     (poOpenInfo->eAccess == GA_Update) )
         || poDS->GetLayerCount() == 0 )
     {
         delete poDS;
         return NULL;
     }
-    else
-        return poDS;
+
+    return poDS;
 }
 
 /************************************************************************/
@@ -73,10 +72,10 @@ static GDALDataset *OGRDGNDriverOpen( GDALOpenInfo* poOpenInfo )
 /************************************************************************/
 
 static GDALDataset *OGRDGNDriverCreate( const char * pszName,
-                                        CPL_UNUSED int nBands,
-                                        CPL_UNUSED int nXSize,
-                                        CPL_UNUSED int nYSize,
-                                        CPL_UNUSED GDALDataType eDT,
+                                        int /* nBands */,
+                                        int /* nXSize */,
+                                        int /* nYSize */,
+                                        GDALDataType /* eDT */,
                                         char **papszOptions )
 {
 /* -------------------------------------------------------------------- */
@@ -91,8 +90,8 @@ static GDALDataset *OGRDGNDriverCreate( const char * pszName,
         delete poDS;
         return NULL;
     }
-    else
-        return poDS;
+
+    return poDS;
 }
 
 /************************************************************************/
@@ -102,21 +101,18 @@ static GDALDataset *OGRDGNDriverCreate( const char * pszName,
 void RegisterOGRDGN()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "DGN" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "DGN" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver  *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "DGN" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Microstation DGN" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "dgn" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_dgn.html" );
+    poDriver->SetDescription( "DGN" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Microstation DGN" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "dgn" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_dgn.html" );
 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "  <Option name='3D' type='boolean' description='whether 2D (seed_2d.dgn) or 3D (seed_3d.dgn) seed file should be used. This option is ignored if the SEED option is provided'/>"
 "  <Option name='SEED' type='string' description='Filename of seed file to use'/>"
@@ -131,12 +127,12 @@ void RegisterOGRDGN()
 "  <Option name='ORIGIN' type='string' description='Value as x,y,z. Override the origin of the design plane. By default the origin from the seed file is used.'/>"
 "</CreationOptionList>");
 
-        poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST, "<LayerCreationOptionList/>" );
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+                               "<LayerCreationOptionList/>" );
 
-        poDriver->pfnOpen = OGRDGNDriverOpen;
-        poDriver->pfnIdentify = OGRDGNDriverIdentify;
-        poDriver->pfnCreate = OGRDGNDriverCreate;
+    poDriver->pfnOpen = OGRDGNDriverOpen;
+    poDriver->pfnIdentify = OGRDGNDriverIdentify;
+    poDriver->pfnCreate = OGRDGNDriverCreate;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/dgn/ogrdgnlayer.cpp b/ogr/ogrsf_frmts/dgn/ogrdgnlayer.cpp
index aecf85f..7734220 100644
--- a/ogr/ogrsf_frmts/dgn/ogrdgnlayer.cpp
+++ b/ogr/ogrsf_frmts/dgn/ogrdgnlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdgnlayer.cpp 28382 2015-01-30 15:29:41Z rouault $
+ * $Id: ogrdgnlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRDGNLayer class.
@@ -33,25 +33,30 @@
 #include "ogr_api.h"
 #include <list>
 
-CPL_CVSID("$Id: ogrdgnlayer.cpp 28382 2015-01-30 15:29:41Z rouault $");
+CPL_CVSID("$Id: ogrdgnlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                           OGRDGNLayer()                              */
 /************************************************************************/
 
-OGRDGNLayer::OGRDGNLayer( const char * pszName, DGNHandle hDGN,
-                          int bUpdate )
-    
+OGRDGNLayer::OGRDGNLayer( const char * pszName, DGNHandle hDGNIn,
+                          int bUpdateIn ) :
+    poFeatureDefn(new OGRFeatureDefn( pszName )),
+    iNextShapeId(0),
+    hDGN(hDGNIn),
+    bUpdate(bUpdateIn)
+    // Unused:
+    // bHaveSimpleQuery(FALSE)
 {
-    this->hDGN = hDGN;
-    this->bUpdate = bUpdate;
 
 /* -------------------------------------------------------------------- */
 /*      Work out what link format we are using.                         */
 /* -------------------------------------------------------------------- */
     OGRFieldType eLinkFieldType;
 
-    pszLinkFormat = (char *) CPLGetConfigOption( "DGN_LINK_FORMAT", "FIRST" );
+    pszLinkFormat = const_cast<char *>(
+        CPLGetConfigOption( "DGN_LINK_FORMAT", "FIRST" ) );
+
     if( EQUAL(pszLinkFormat,"FIRST") )
         eLinkFieldType = OFTInteger;
     else if( EQUAL(pszLinkFormat,"LIST") )
@@ -60,10 +65,11 @@ OGRDGNLayer::OGRDGNLayer( const char * pszName, DGNHandle hDGN,
         eLinkFieldType = OFTString;
     else
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
-                  "DGN_LINK_FORMAT=%s, but only FIRST, LIST or STRING supported.",
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "DGN_LINK_FORMAT=%s, but only FIRST, LIST or STRING "
+                  "supported.",
                   pszLinkFormat );
-        pszLinkFormat = (char *) "FIRST";
+        pszLinkFormat = const_cast<char *>( "FIRST" );
         eLinkFieldType = OFTInteger;
     }
     pszLinkFormat = CPLStrdup(pszLinkFormat);
@@ -71,11 +77,10 @@ OGRDGNLayer::OGRDGNLayer( const char * pszName, DGNHandle hDGN,
 /* -------------------------------------------------------------------- */
 /*      Create the feature definition.                                  */
 /* -------------------------------------------------------------------- */
-    poFeatureDefn = new OGRFeatureDefn( pszName );
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
-    
-    OGRFieldDefn        oField( "", OFTInteger );
+
+    OGRFieldDefn oField( "", OFTInteger );
 
 /* -------------------------------------------------------------------- */
 /*      Element type                                                    */
@@ -161,7 +166,6 @@ OGRDGNLayer::OGRDGNLayer( const char * pszName, DGNHandle hDGN,
 /* -------------------------------------------------------------------- */
 /*      Create template feature for evaluating simple expressions.      */
 /* -------------------------------------------------------------------- */
-    bHaveSimpleQuery = FALSE;
     poEvalFeature = new OGRFeature( poFeatureDefn );
 
     /* TODO: I am intending to keep track of simple attribute queries (ones
@@ -179,10 +183,10 @@ OGRDGNLayer::OGRDGNLayer( const char * pszName, DGNHandle hDGN,
 OGRDGNLayer::~OGRDGNLayer()
 
 {
-    if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
+    if( m_nFeaturesRead > 0 )
     {
         CPLDebug( "Mem", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
+                  static_cast<int>( m_nFeaturesRead ),
                   poFeatureDefn->GetName() );
     }
 
@@ -205,10 +209,10 @@ void OGRDGNLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
 
     if( m_poFilterGeom != NULL )
     {
-        DGNSetSpatialFilter( hDGN, 
-                             m_sFilterEnvelope.MinX, 
-                             m_sFilterEnvelope.MinY, 
-                             m_sFilterEnvelope.MaxX, 
+        DGNSetSpatialFilter( hDGN,
+                             m_sFilterEnvelope.MinX,
+                             m_sFilterEnvelope.MinY,
+                             m_sFilterEnvelope.MaxX,
                              m_sFilterEnvelope.MaxY );
     }
     else
@@ -237,17 +241,14 @@ void OGRDGNLayer::ResetReading()
 OGRFeature *OGRDGNLayer::GetFeature( GIntBig nFeatureId )
 
 {
-    OGRFeature *poFeature;
-    DGNElemCore *psElement;
-
     if( nFeatureId > INT_MAX || !DGNGotoElement( hDGN, (int)nFeatureId ) )
         return NULL;
 
-    // We should likely clear the spatial search region as it affects 
-    // DGNReadElement() but I will defer that for now. 
+    // We should likely clear the spatial search region as it affects
+    // DGNReadElement(), but I will defer that for now.
 
-    psElement = DGNReadElement( hDGN );
-    poFeature = ElementToFeature( psElement );
+    DGNElemCore *psElement = DGNReadElement( hDGN );
+    OGRFeature *poFeature = ElementToFeature( psElement );
     DGNFreeElement( hDGN, psElement );
 
     if( poFeature == NULL )
@@ -273,18 +274,20 @@ void OGRDGNLayer::ConsiderBrush( DGNElemCore *psElement, const char *pszPen,
                                  OGRFeature *poFeature )
 
 {
-    int         gv_red, gv_green, gv_blue;
-    char                szFullStyle[256];
-    int                 nFillColor;
+    int nFillColor = 0;
+    int gv_red = 0;
+    int gv_green = 0;
+    int gv_blue = 0;
 
-    if( DGNGetShapeFillInfo( hDGN, psElement, &nFillColor ) 
-        && DGNLookupColor( hDGN, nFillColor, 
+    if( DGNGetShapeFillInfo( hDGN, psElement, &nFillColor )
+        && DGNLookupColor( hDGN, nFillColor,
                            &gv_red, &gv_green, &gv_blue ) )
     {
-        sprintf( szFullStyle, 
+        char szFullStyle[256];
+        snprintf( szFullStyle, sizeof(szFullStyle),
                  "BRUSH(fc:#%02x%02x%02x,id:\"ogr-brush-0\")",
                  gv_red, gv_green, gv_blue );
-              
+
         if( nFillColor != psElement->color )
         {
             strcat( szFullStyle, ";" );
@@ -312,23 +315,27 @@ OGRFeature *OGRDGNLayer::ElementToFeature( DGNElemCore *psElement )
     poFeature->SetField( "ColorIndex", psElement->color );
     poFeature->SetField( "Weight", psElement->weight );
     poFeature->SetField( "Style", psElement->style );
-    
 
     m_nFeaturesRead++;
 
 /* -------------------------------------------------------------------- */
 /*      Collect linkage information                                     */
 /* -------------------------------------------------------------------- */
-#define MAX_LINK 100    
-    int anEntityNum[MAX_LINK], anMSLink[MAX_LINK];
-    unsigned char *pabyData;
-    int iLink=0, nLinkCount=0;
+    const int MAX_LINK = 100;
 
+    int anEntityNum[MAX_LINK];
     anEntityNum[0] = 0;
+
+    int anMSLink[MAX_LINK];
     anMSLink[0] = 0;
 
-    pabyData = DGNGetLinkage( hDGN, psElement, iLink, NULL, 
-                              anEntityNum+iLink, anMSLink+iLink, NULL );
+    unsigned char *pabyData = NULL;
+    int iLink = 0;
+    int nLinkCount = 0;
+
+
+    pabyData = DGNGetLinkage( hDGN, psElement, iLink, NULL,
+                              anEntityNum + iLink, anMSLink + iLink, NULL );
     while( pabyData && nLinkCount < MAX_LINK )
     {
         iLink++;
@@ -339,8 +346,8 @@ OGRFeature *OGRDGNLayer::ElementToFeature( DGNElemCore *psElement )
         anEntityNum[nLinkCount] = 0;
         anMSLink[nLinkCount] = 0;
 
-        pabyData = DGNGetLinkage( hDGN, psElement, iLink, NULL, 
-                                  anEntityNum+nLinkCount, anMSLink+nLinkCount, 
+        pabyData = DGNGetLinkage( hDGN, psElement, iLink, NULL,
+                                  anEntityNum+nLinkCount, anMSLink+nLinkCount,
                                   NULL );
     }
 
@@ -361,8 +368,10 @@ OGRFeature *OGRDGNLayer::ElementToFeature( DGNElemCore *psElement )
         }
         else if( EQUAL(pszLinkFormat,"STRING") )
         {
-            char szEntityList[MAX_LINK*9], szMSLinkList[MAX_LINK*9];
-            int nEntityLen = 0, nMSLinkLen = 0;
+            char szEntityList[MAX_LINK * 9];
+            char szMSLinkList[MAX_LINK * 9];
+            int nEntityLen = 0;
+            int nMSLinkLen = 0;
 
             for( iLink = 0; iLink < nLinkCount; iLink++ )
             {
@@ -372,11 +381,17 @@ OGRFeature *OGRDGNLayer::ElementToFeature( DGNElemCore *psElement )
                     szMSLinkList[nMSLinkLen++] = ',';
                 }
 
-                sprintf( szEntityList + nEntityLen, "%d", anEntityNum[iLink]);
-                sprintf( szMSLinkList + nMSLinkLen, "%d", anMSLink[iLink] );
-                
-                nEntityLen += strlen(szEntityList + nEntityLen );
-                nMSLinkLen += strlen(szMSLinkList + nMSLinkLen );
+                snprintf( szEntityList + nEntityLen,
+                          sizeof(szEntityList) - nEntityLen,
+                          "%d", anEntityNum[iLink]);
+                snprintf( szMSLinkList + nMSLinkLen,
+                          sizeof(szMSLinkList) - nMSLinkLen,
+                          "%d", anMSLink[iLink] );
+
+                nEntityLen +=
+                    static_cast<int>(strlen(szEntityList + nEntityLen ));
+                nMSLinkLen +=
+                    static_cast<int>(strlen(szMSLinkList + nMSLinkLen ));
             }
 
             poFeature->SetField( "EntityNum", szEntityList );
@@ -387,49 +402,56 @@ OGRFeature *OGRDGNLayer::ElementToFeature( DGNElemCore *psElement )
 /* -------------------------------------------------------------------- */
 /*      Lookup color.                                                   */
 /* -------------------------------------------------------------------- */
-    char        gv_color[128];
-    int         gv_red, gv_green, gv_blue;
-    char        szFSColor[128], szPen[256];
+    int gv_red;
+    int gv_green;
+    int gv_blue;
 
+    char szFSColor[128];
     szFSColor[0] = '\0';
-    if( DGNLookupColor( hDGN, psElement->color, 
+    if( DGNLookupColor( hDGN, psElement->color,
                         &gv_red, &gv_green, &gv_blue ) )
     {
-        sprintf( gv_color, "%f %f %f 1.0", 
+        char gv_color[128];
+        CPLsnprintf( gv_color, sizeof(gv_color), "%f %f %f 1.0",
                  gv_red / 255.0, gv_green / 255.0, gv_blue / 255.0 );
 
-        sprintf( szFSColor, "c:#%02x%02x%02x", 
+        snprintf( szFSColor, sizeof(szFSColor), "c:#%02x%02x%02x",
                  gv_red, gv_green, gv_blue );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Generate corresponding PEN style.                               */
 /* -------------------------------------------------------------------- */
+    char szPen[256];
+    szPen[0] = '\0';
+
     if( psElement->style == DGNS_SOLID )
-        sprintf( szPen, "PEN(id:\"ogr-pen-0\"" );
+        snprintf( szPen, sizeof(szPen), "PEN(id:\"ogr-pen-0\"" );
     else if( psElement->style == DGNS_DOTTED )
-        sprintf( szPen, "PEN(id:\"ogr-pen-5\"" );
+        snprintf( szPen, sizeof(szPen), "PEN(id:\"ogr-pen-5\"" );
     else if( psElement->style == DGNS_MEDIUM_DASH )
-        sprintf( szPen, "PEN(id:\"ogr-pen-2\"" );
+        snprintf( szPen, sizeof(szPen), "PEN(id:\"ogr-pen-2\"" );
     else if( psElement->style == DGNS_LONG_DASH )
-        sprintf( szPen, "PEN(id:\"ogr-pen-4\"" );
+        snprintf( szPen, sizeof(szPen), "PEN(id:\"ogr-pen-4\"" );
     else if( psElement->style == DGNS_DOT_DASH )
-        sprintf( szPen, "PEN(id:\"ogr-pen-6\"" );
+        snprintf( szPen, sizeof(szPen), "PEN(id:\"ogr-pen-6\"" );
     else if( psElement->style == DGNS_SHORT_DASH )
-        sprintf( szPen, "PEN(id:\"ogr-pen-3\"" );
+        snprintf( szPen, sizeof(szPen), "PEN(id:\"ogr-pen-3\"" );
     else if( psElement->style == DGNS_DASH_DOUBLE_DOT )
-        sprintf( szPen, "PEN(id:\"ogr-pen-7\"" );
+        snprintf( szPen, sizeof(szPen), "PEN(id:\"ogr-pen-7\"" );
     else if( psElement->style == DGNS_LONG_DASH_SHORT_DASH )
-        sprintf( szPen, "PEN(p:\"10px 5px 4px 5px\"" );
+        snprintf( szPen, sizeof(szPen), "PEN(p:\"10px 5px 4px 5px\"" );
     else
-        sprintf( szPen, "PEN(id:\"ogr-pen-0\"" );
+        snprintf( szPen, sizeof(szPen), "PEN(id:\"ogr-pen-0\"" );
 
     if( strlen(szFSColor) > 0 )
-        sprintf( szPen+strlen(szPen), ",%s", szFSColor );
+        snprintf( szPen+strlen(szPen), sizeof(szPen)-strlen(szPen),
+                  ",%s", szFSColor );
 
     if( psElement->weight > 1 )
-        sprintf( szPen+strlen(szPen), ",w:%dpx", psElement->weight );
-        
+        snprintf( szPen+strlen(szPen), sizeof(szPen)-strlen(szPen),
+                  ",w:%dpx", psElement->weight );
+
     strcat( szPen, ")" );
 
     switch( psElement->stype )
@@ -437,19 +459,20 @@ OGRFeature *OGRDGNLayer::ElementToFeature( DGNElemCore *psElement )
       case DGNST_MULTIPOINT:
         if( psElement->type == DGNT_SHAPE )
         {
-            OGRLinearRing       *poLine = new OGRLinearRing();
-            OGRPolygon          *poPolygon = new OGRPolygon();
-            DGNElemMultiPoint *psEMP = (DGNElemMultiPoint *) psElement;
-            
+            OGRLinearRing *poLine = new OGRLinearRing();
+            DGNElemMultiPoint *psEMP
+                = reinterpret_cast<DGNElemMultiPoint *>( psElement );
+
             poLine->setNumPoints( psEMP->num_vertices );
             for( int i = 0; i < psEMP->num_vertices; i++ )
             {
-                poLine->setPoint( i, 
+                poLine->setPoint( i,
                                   psEMP->vertices[i].x,
                                   psEMP->vertices[i].y,
                                   psEMP->vertices[i].z );
             }
 
+            OGRPolygon *poPolygon = new OGRPolygon();
             poPolygon->addRingDirectly( poLine );
 
             poFeature->SetGeometryDirectly( poPolygon );
@@ -458,20 +481,19 @@ OGRFeature *OGRDGNLayer::ElementToFeature( DGNElemCore *psElement )
         }
         else if( psElement->type == DGNT_CURVE )
         {
-            DGNElemMultiPoint *psEMP = (DGNElemMultiPoint *) psElement;
-            OGRLineString       *poLine = new OGRLineString();
-            DGNPoint            *pasPoints;
-            int                 nPoints;
+            OGRLineString *poLine = new OGRLineString();
+            DGNElemMultiPoint *psEMP
+                = reinterpret_cast<DGNElemMultiPoint *>( psElement );
+            const int nPoints = 5 * psEMP->num_vertices;
+            DGNPoint *pasPoints = static_cast<DGNPoint *>(
+                CPLMalloc( sizeof(DGNPoint) * nPoints ) );
 
-            nPoints = 5 * psEMP->num_vertices;
-            pasPoints = (DGNPoint *) CPLMalloc(sizeof(DGNPoint) * nPoints);
-            
             DGNStrokeCurve( hDGN, psEMP, nPoints, pasPoints );
 
             poLine->setNumPoints( nPoints );
             for( int i = 0; i < nPoints; i++ )
             {
-                poLine->setPoint( i, 
+                poLine->setPoint( i,
                                   pasPoints[i].x,
                                   pasPoints[i].y,
                                   pasPoints[i].z );
@@ -484,20 +506,20 @@ OGRFeature *OGRDGNLayer::ElementToFeature( DGNElemCore *psElement )
         }
         else
         {
-            OGRLineString       *poLine = new OGRLineString();
             DGNElemMultiPoint *psEMP = (DGNElemMultiPoint *) psElement;
-            
+
             if( psEMP->num_vertices > 0 )
             {
+                OGRLineString       *poLine = new OGRLineString();
                 poLine->setNumPoints( psEMP->num_vertices );
                 for( int i = 0; i < psEMP->num_vertices; i++ )
                 {
-                    poLine->setPoint( i, 
+                    poLine->setPoint( i,
                                       psEMP->vertices[i].x,
                                       psEMP->vertices[i].y,
                                       psEMP->vertices[i].z );
                 }
-                
+
                 poFeature->SetGeometryDirectly( poLine );
             }
 
@@ -510,15 +532,16 @@ OGRFeature *OGRDGNLayer::ElementToFeature( DGNElemCore *psElement )
           OGRLineString *poLine = new OGRLineString();
           DGNElemArc    *psArc = (DGNElemArc *) psElement;
           DGNPoint      asPoints[90];
-          int           nPoints;
-
-          nPoints = (int) (MAX(1,ABS(psArc->sweepang) / 5) + 1);
+          // TODO: std::abs abd std::max
+          int nPoints = static_cast<int>(MAX(1,ABS(psArc->sweepang) / 5) + 1);
+          if( nPoints > 90 )
+              nPoints = 90;
           DGNStrokeArc( hDGN, psArc, nPoints, asPoints );
 
           poLine->setNumPoints( nPoints );
           for( int i = 0; i < nPoints; i++ )
           {
-              poLine->setPoint( i, 
+              poLine->setPoint( i,
                                 asPoints[i].x,
                                 asPoints[i].y,
                                 asPoints[i].z );
@@ -531,9 +554,8 @@ OGRFeature *OGRDGNLayer::ElementToFeature( DGNElemCore *psElement )
 
       case DGNST_TEXT:
       {
-          OGRPoint      *poPoint = new OGRPoint();
-          DGNElemText   *psText = (DGNElemText *) psElement;
-          char          *pszOgrFS;
+          OGRPoint *poPoint = new OGRPoint();
+          DGNElemText *psText = reinterpret_cast<DGNElemText *>( psElement );
 
           poPoint->setX( psText->origin.x );
           poPoint->setY( psText->origin.y );
@@ -541,35 +563,43 @@ OGRFeature *OGRDGNLayer::ElementToFeature( DGNElemCore *psElement )
 
           poFeature->SetGeometryDirectly( poPoint );
 
-          pszOgrFS = (char *) CPLMalloc(strlen(psText->string) + 150);
+          const size_t nOgrFSLen = strlen(psText->string) + 150;
+          char *pszOgrFS = static_cast<char *>( CPLMalloc(nOgrFSLen) );
 
           // setup the basic label.
-          sprintf( pszOgrFS, "LABEL(t:\"%s\"",  psText->string );
+          snprintf( pszOgrFS, nOgrFSLen, "LABEL(t:\"%s\"",  psText->string );
 
-          // set the color if we have it. 
+          // set the color if we have it.
           if( strlen(szFSColor) > 0 )
-              sprintf( pszOgrFS+strlen(pszOgrFS), ",%s", szFSColor );
+              snprintf( pszOgrFS+strlen(pszOgrFS), nOgrFSLen-strlen(pszOgrFS),
+                        ",%s", szFSColor );
 
           // Add the size info in ground units.
+          // TODO: std::abs
           if( ABS(psText->height_mult) >= 6.0 )
-              CPLsprintf( pszOgrFS+strlen(pszOgrFS), ",s:%dg", 
-                       (int) psText->height_mult );
+              CPLsnprintf( pszOgrFS+strlen(pszOgrFS),
+                           nOgrFSLen-strlen(pszOgrFS), ",s:%dg",
+                           static_cast<int>( psText->height_mult ) );
           else if( ABS(psText->height_mult) > 0.1 )
-              CPLsprintf( pszOgrFS+strlen(pszOgrFS), ",s:%.3fg", 
-                       psText->height_mult );
+              CPLsnprintf( pszOgrFS+strlen(pszOgrFS),
+                          nOgrFSLen-strlen(pszOgrFS), ",s:%.3fg",
+                           psText->height_mult );
           else
-              CPLsprintf( pszOgrFS+strlen(pszOgrFS), ",s:%.12fg", 
-                       psText->height_mult );
+              CPLsnprintf( pszOgrFS+strlen(pszOgrFS),
+                          nOgrFSLen-strlen(pszOgrFS), ",s:%.12fg",
+                           psText->height_mult );
 
           // Add the font name. Name it MstnFont<FONTNUMBER> if not available
           // in the font list. #3392
-          static const char *papszFontList[] =
-          { "STANDARD", "WORKING", "FANCY", "ENGINEERING", "NEWZERO", "STENCEL", //0-5
+          static const char * const papszFontList[] =
+          { "STANDARD", "WORKING", "FANCY", "ENGINEERING", "NEWZERO",
+            "STENCEL", // 0-5
             "USTN_FANCY", "COMPRESSED", "STENCEQ", NULL, "hand", "ARCH", //6-11
             "ARCHB", NULL, NULL, "IGES1001", "IGES1002", "IGES1003", //12-17
             "CENTB", "MICROS", NULL, NULL, "ISOFRACTIONS", "ITALICS", //18-23
             "ISO30", NULL, "GREEK", "ISOREC", "Isoeq", NULL, //24-29
-            "ISO_FONTLEFT", "ISO_FONTRIGHT", "INTL_ENGINEERING", "INTL_WORKING", "ISOITEQ", NULL, //30-35
+            "ISO_FONTLEFT", "ISO_FONTRIGHT", "INTL_ENGINEERING", "INTL_WORKING",
+            "ISOITEQ", NULL, // 30-35
             "USTN FONT 26", NULL, NULL, NULL, NULL, "ARCHITECTURAL", //36-41
             "BLOCK_OUTLINE", "LOW_RES_FILLED", NULL, NULL, NULL, NULL, //42-47
             NULL, NULL, "UPPERCASE", NULL, NULL, NULL, //48-53
@@ -580,27 +610,33 @@ OGRFeature *OGRDGNLayer::ElementToFeature( DGNElemCore *psElement )
             "DOTIT", NULL, NULL, NULL, NULL, NULL, //78-83
             NULL, NULL, NULL, NULL, NULL, NULL, //84-89
             NULL, NULL, "FONT092", NULL, "FONT094", NULL, //90-95
-            NULL, NULL, NULL, NULL, "ANSI_SYMBOLS", "FEATURE_CONTROL_SYSMBOLS", //96-101
-            "SYMB_FAST", NULL, NULL, "INTL_ISO", "INTL_ISO_EQUAL", "INTL_ISO_ITALIC", //102-107
+            NULL, NULL, NULL, NULL, "ANSI_SYMBOLS",
+            "FEATURE_CONTROL_SYSMBOLS", // 96-101
+            "SYMB_FAST", NULL, NULL, "INTL_ISO", "INTL_ISO_EQUAL",
+            "INTL_ISO_ITALIC", // 102-107
             "INTL_ISO_ITALIC_EQUAL" }; //108
 
           if(psText->font_id <= 108 && papszFontList[psText->font_id] != NULL )
           {
-              sprintf( pszOgrFS+strlen(pszOgrFS), ",f:%s",
+              snprintf( pszOgrFS+strlen(pszOgrFS),
+                        nOgrFSLen-strlen(pszOgrFS), ",f:%s",
                        papszFontList[psText->font_id] );
           }
           else
           {
-              sprintf( pszOgrFS+strlen(pszOgrFS), ",f:MstnFont%d",
+              snprintf( pszOgrFS+strlen(pszOgrFS),
+                        nOgrFSLen-strlen(pszOgrFS), ",f:MstnFont%d",
                        psText->font_id );
           }
 
           // Add the angle, if not horizontal
           if( psText->rotation != 0.0 )
-              sprintf( pszOgrFS+strlen(pszOgrFS), ",a:%d", 
+              snprintf( pszOgrFS+strlen(pszOgrFS),
+                        nOgrFSLen-strlen(pszOgrFS), ",a:%d",
                        (int) (psText->rotation+0.5) );
 
-          strcat( pszOgrFS, ")" );
+          snprintf( pszOgrFS+strlen(pszOgrFS),
+                        nOgrFSLen-strlen(pszOgrFS), ")" );
 
           poFeature->SetStyleString( pszOgrFS );
           CPLFree( pszOgrFS );
@@ -612,12 +648,11 @@ OGRFeature *OGRDGNLayer::ElementToFeature( DGNElemCore *psElement )
       case DGNST_COMPLEX_HEADER:
       {
           DGNElemComplexHeader *psHdr = (DGNElemComplexHeader *) psElement;
-          int           iChild;
           OGRMultiLineString  oChildren;
 
           /* collect subsequent child geometries. */
           // we should disable the spatial filter ... add later.
-          for( iChild = 0; iChild < psHdr->numelems; iChild++ )
+          for( int iChild = 0; iChild < psHdr->numelems; iChild++ )
           {
               OGRFeature *poChildFeature = NULL;
               DGNElemCore *psChildElement;
@@ -646,12 +681,13 @@ OGRFeature *OGRDGNLayer::ElementToFeature( DGNElemCore *psElement )
           }
 
           // Try to assemble into polygon geometry.
-          OGRGeometry *poGeom;
+          OGRGeometry *poGeom = NULL;;
 
           if( psElement->type == DGNT_COMPLEX_SHAPE_HEADER )
-              poGeom = (OGRPolygon *) 
-                  OGRBuildPolygonFromEdges( (OGRGeometryH) &oChildren, 
-                                            TRUE, TRUE, 100000, NULL );
+              poGeom = reinterpret_cast<OGRPolygon *>(
+                  OGRBuildPolygonFromEdges(
+                      reinterpret_cast<OGRGeometryH>( &oChildren ),
+                      TRUE, TRUE, 100000, NULL ) );
           else
               poGeom = oChildren.clone();
 
@@ -665,12 +701,12 @@ OGRFeature *OGRDGNLayer::ElementToFeature( DGNElemCore *psElement )
       default:
         break;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Fixup geometry dimension.                                       */
 /* -------------------------------------------------------------------- */
     if( poFeature->GetGeometryRef() != NULL )
-        poFeature->GetGeometryRef()->setCoordinateDimension( 
+        poFeature->GetGeometryRef()->setCoordinateDimension(
             DGNGetDimension( hDGN ) );
 
     return poFeature;
@@ -683,21 +719,18 @@ OGRFeature *OGRDGNLayer::ElementToFeature( DGNElemCore *psElement )
 OGRFeature *OGRDGNLayer::GetNextFeature()
 
 {
-    DGNElemCore *psElement;
-
     DGNGetElementIndex( hDGN, NULL );
 
+    DGNElemCore *psElement = NULL;
     while( (psElement = DGNReadElement( hDGN )) != NULL )
     {
-        OGRFeature      *poFeature;
-
         if( psElement->deleted )
         {
             DGNFreeElement( hDGN, psElement );
             continue;
         }
 
-        poFeature = ElementToFeature( psElement );
+        OGRFeature *poFeature = ElementToFeature( psElement );
         DGNFreeElement( hDGN, psElement );
 
         if( poFeature == NULL )
@@ -715,7 +748,7 @@ OGRFeature *OGRDGNLayer::GetNextFeature()
             return poFeature;
 
         delete poFeature;
-    }        
+    }
 
     return NULL;
 }
@@ -744,8 +777,7 @@ int OGRDGNLayer::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCFastGetExtent) )
         return TRUE;
 
-    else 
-        return FALSE;
+    return FALSE;
 }
 
 /************************************************************************/
@@ -765,11 +797,13 @@ GIntBig OGRDGNLayer::GetFeatureCount( int bForce )
 /* -------------------------------------------------------------------- */
 /*      Otherwise scan the index.                                       */
 /* -------------------------------------------------------------------- */
-    int nElementCount, i, nFeatureCount = 0;
-    int bInComplexShape = FALSE;
+    int nElementCount;
     const DGNElementInfo *pasIndex = DGNGetElementIndex(hDGN,&nElementCount);
 
-    for( i = 0; i < nElementCount; i++ )
+    int nFeatureCount = 0;
+    bool bInComplexShape = false;
+
+    for( int i = 0; i < nElementCount; i++ )
     {
         if( pasIndex[i].flags & DGNEIF_DELETED )
             continue;
@@ -803,9 +837,9 @@ GIntBig OGRDGNLayer::GetFeatureCount( int bForce )
 /*                             GetExtent()                              */
 /************************************************************************/
 
-OGRErr OGRDGNLayer::GetExtent( OGREnvelope *psExtent, CPL_UNUSED int bForce )
+OGRErr OGRDGNLayer::GetExtent( OGREnvelope *psExtent, int /* bForce */ )
 {
-    double      adfExtents[6];
+    double adfExtents[6];
 
     if( !DGNGetExtents( hDGN, adfExtents ) )
         return OGRERR_FAILURE;
@@ -831,41 +865,40 @@ OGRErr OGRDGNLayer::GetExtent( OGREnvelope *psExtent, CPL_UNUSED int bForce )
 /*      complex shape group are always line strings.                    */
 /************************************************************************/
 
-#define MAX_ELEM_POINTS 38
+static const int MAX_ELEM_POINTS = 38;
 
 DGNElemCore **OGRDGNLayer::LineStringToElementGroup( OGRLineString *poLS,
                                                      int nGroupType )
 
 {
     int nTotalPoints = poLS->getNumPoints();
-    int iNextPoint = 0, iGeom = 0;
-    DGNElemCore **papsGroup;
-
-    papsGroup = (DGNElemCore **) 
-        CPLCalloc( sizeof(void*), (nTotalPoints/(MAX_ELEM_POINTS-1))+3 );
+    int iNextPoint = 0;
+    int iGeom = 0;
+    DGNElemCore **papsGroup = static_cast<DGNElemCore **>(
+        CPLCalloc( sizeof(void*), (nTotalPoints/(MAX_ELEM_POINTS-1))+3 ) );
 
     for( iNextPoint = 0; iNextPoint < nTotalPoints;  )
     {
-        DGNPoint asPoints[38];
+        DGNPoint asPoints[MAX_ELEM_POINTS];
         int nThisCount = 0;
 
         // we need to repeat end points of elements.
         if( iNextPoint != 0 )
             iNextPoint--;
 
-        for( ; iNextPoint < nTotalPoints && nThisCount < MAX_ELEM_POINTS; 
+        for( ; iNextPoint < nTotalPoints && nThisCount < MAX_ELEM_POINTS;
              iNextPoint++, nThisCount++ )
         {
             asPoints[nThisCount].x = poLS->getX( iNextPoint );
             asPoints[nThisCount].y = poLS->getY( iNextPoint );
             asPoints[nThisCount].z = poLS->getZ( iNextPoint );
         }
-        
+
         if( nTotalPoints <= MAX_ELEM_POINTS )
             papsGroup[0] = DGNCreateMultiPointElem( hDGN, nGroupType,
                                                  nThisCount, asPoints);
         else
-            papsGroup[++iGeom] = 
+            papsGroup[++iGeom] =
                 DGNCreateMultiPointElem( hDGN, DGNT_LINE_STRING,
                                          nThisCount, asPoints);
     }
@@ -880,9 +913,9 @@ DGNElemCore **OGRDGNLayer::LineStringToElementGroup( OGRLineString *poLS,
             nGroupType = DGNT_COMPLEX_SHAPE_HEADER;
         else
             nGroupType = DGNT_COMPLEX_CHAIN_HEADER;
-        
-        papsGroup[0] = 
-            DGNCreateComplexHeaderFromGroup( hDGN, nGroupType, 
+
+        papsGroup[0] =
+            DGNCreateComplexHeaderFromGroup( hDGN, nGroupType,
                                              iGeom, papsGroup + 1 );
     }
 
@@ -898,24 +931,24 @@ DGNElemCore **OGRDGNLayer::LineStringToElementGroup( OGRLineString *poLS,
 DGNElemCore **OGRDGNLayer::TranslateLabel( OGRFeature *poFeature )
 
 {
-    DGNElemCore **papsGroup;
-    OGRPoint *poPoint = (OGRPoint *) poFeature->GetGeometryRef();
-    OGRStyleMgr oMgr;
-    OGRStyleLabel *poLabel;
+    OGRPoint *poPoint
+        = reinterpret_cast<OGRPoint *>( poFeature->GetGeometryRef() );
     const char *pszText = poFeature->GetFieldAsString( "Text" );
-    double dfRotation = 0.0;
-    double dfCharHeight = 100.0;
-    const char *pszFontName;
-    int nFontID = 1; // 1 is the default font for DGN. Not 0.
 
+    OGRStyleMgr oMgr;
     oMgr.InitFromFeature( poFeature );
-    poLabel = (OGRStyleLabel *) oMgr.GetPart( 0 );
+    OGRStyleLabel *poLabel
+        = reinterpret_cast<OGRStyleLabel *>( oMgr.GetPart( 0 ) );
     if( poLabel != NULL && poLabel->GetType() != OGRSTCLabel )
     {
         delete poLabel;
         poLabel = NULL;
     }
 
+    double dfRotation = 0.0;
+    double dfCharHeight = 100.0;
+    int nFontID = 1; // 1 is the default font for DGN. Not 0.
+
     if( poLabel != NULL )
     {
         GBool bDefault;
@@ -932,27 +965,28 @@ DGNElemCore **OGRDGNLayer::TranslateLabel( OGRFeature *poFeature )
             dfCharHeight = poLabel->Size(bDefault)/1000.0;
 
         /* get font id */
-        static const char  *papszFontNumbers[] =
+        static const char * const papszFontNumbers[] =
           { "STANDARD=0", "WORKING=1", "FANCY=2", "ENGINEERING=3", "NEWZERO=4",
             "STENCEL=5", "USTN_FANCY=7", "COMPRESSED=8", "STENCEQ=9", "hand=10",
-            "ARCH=11", "ARCHB=12", "IGES1001=15", "IGES1002=16", "IGES1003=17", 
+            "ARCH=11", "ARCHB=12", "IGES1001=15", "IGES1002=16", "IGES1003=17",
             "CENTB=18", "MICROS=19", "ISOFRACTIONS=22", "ITALICS=23",
             "ISO30=24", "GREEK=25", "ISOREC=26", "Isoeq=27", "ISO_FONTLEFT=30",
             "ISO_FONTRIGHT=31", "INTL_ENGINEERING=32", "INTL_WORKING=33",
             "ISOITEQ=34", "USTN FONT 26=36", "ARCHITECTURAL=41",
             "BLOCK_OUTLINE=42", "LOW_RES_FILLED=43", "UPPERCASE50",
             "FONT060=60", "din=61", "dinit=62", "helvl=63", "HELVLIT=64",
-            "helv=65", "HELVIT=66", "cent=67", "CENTIT=68", "SCRIPT=69", 
+            "helv=65", "HELVIT=66", "cent=67", "CENTIT=68", "SCRIPT=69",
             "MICROQ=76", "dotfont=77", "DOTIT=78", "FONT092=92", "FONT094=94",
             "ANSI_SYMBOLS=100", "FEATURE_CONTROL_SYSMBOLS=101", "SYMB_FAST=102",
-            "INTL_ISO=105", "INTL_ISO_EQUAL=106", "INTL_ISO_ITALIC=107", 
-            "INTL_ISO_ITALIC_EQUAL=108", NULL }; 
+            "INTL_ISO=105", "INTL_ISO_EQUAL=106", "INTL_ISO_ITALIC=107",
+            "INTL_ISO_ITALIC_EQUAL=108", NULL };
 
-        pszFontName = poLabel->FontName( bDefault );
+        const char *pszFontName = poLabel->FontName( bDefault );
         if( !bDefault && pszFontName != NULL )
         {
-            const char *pszFontNumber = 
-                CSLFetchNameValue((char**)papszFontNumbers, pszFontName);
+            const char *pszFontNumber =
+              CSLFetchNameValue( const_cast<char**>( papszFontNumbers ),
+                                 pszFontName );
 
             if( pszFontNumber != NULL )
             {
@@ -961,12 +995,13 @@ DGNElemCore **OGRDGNLayer::TranslateLabel( OGRFeature *poFeature )
         }
     }
 
-    papsGroup = (DGNElemCore **) CPLCalloc(sizeof(void*),2);
-    papsGroup[0] = 
-        DGNCreateTextElem( hDGN, pszText, nFontID, DGNJ_LEFT_BOTTOM, 
+    DGNElemCore **papsGroup
+        = static_cast<DGNElemCore **>( CPLCalloc(sizeof(void*), 2) );
+    papsGroup[0] =
+        DGNCreateTextElem( hDGN, pszText, nFontID, DGNJ_LEFT_BOTTOM,
                            dfCharHeight, dfCharHeight, dfRotation, NULL,
-                           poPoint->getX(), 
-                           poPoint->getY(), 
+                           poPoint->getX(),
+                           poPoint->getY(),
                            poPoint->getZ() );
 
     if( poLabel )
@@ -986,14 +1021,14 @@ OGRErr OGRDGNLayer::ICreateFeature( OGRFeature *poFeature )
 {
     if( !bUpdate )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Attempt to create feature on read-only DGN file." );
         return OGRERR_FAILURE;
     }
-    
+
     if( poFeature->GetGeometryRef() == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Features with empty, geometry collection geometries not\n"
                   "supported in DGN format." );
         return OGRERR_FAILURE;
@@ -1018,28 +1053,26 @@ OGRErr OGRDGNLayer::CreateFeatureWithGeom( OGRFeature *poFeature,
 /*      Translate the geometry.                                         */
 /* -------------------------------------------------------------------- */
     DGNElemCore **papsGroup = NULL;
-    int i;
     const char *pszStyle = poFeature->GetStyleString();
 
     if( wkbFlatten(poGeom->getGeometryType()) == wkbPoint )
     {
-        OGRPoint *poPoint = (OGRPoint *) poGeom;
+        OGRPoint *poPoint = reinterpret_cast<OGRPoint *>( poGeom );
         const char *pszText = poFeature->GetFieldAsString("Text");
 
         if( (pszText == NULL || strlen(pszText) == 0)
             && (pszStyle == NULL || strstr(pszStyle,"LABEL") == NULL) )
         {
-            DGNPoint asPoints[2];
-
-            papsGroup = (DGNElemCore **) CPLCalloc(sizeof(void*),2);
-
             // Treat a non text point as a degenerate line.
+            DGNPoint asPoints[2];
             asPoints[0].x = poPoint->getX();
             asPoints[0].y = poPoint->getY();
             asPoints[0].z = poPoint->getZ();
             asPoints[1] = asPoints[0];
-            
-            papsGroup[0] = DGNCreateMultiPointElem( hDGN, DGNT_LINE, 
+
+            papsGroup
+                = static_cast<DGNElemCore **>( CPLCalloc(sizeof(void*), 2) );
+            papsGroup[0] = DGNCreateMultiPointElem( hDGN, DGNT_LINE,
                                                     2, asPoints );
         }
         else
@@ -1049,23 +1082,24 @@ OGRErr OGRDGNLayer::CreateFeatureWithGeom( OGRFeature *poFeature,
     }
     else if( wkbFlatten(poGeom->getGeometryType()) == wkbLineString )
     {
-        papsGroup = LineStringToElementGroup( (OGRLineString *) poGeom, 
-                                              DGNT_LINE_STRING );
+        papsGroup = LineStringToElementGroup(
+            reinterpret_cast<OGRLineString *>( poGeom ),
+            DGNT_LINE_STRING );
     }
     else if( wkbFlatten(poGeom->getGeometryType()) == wkbPolygon )
     {
-        OGRPolygon *poPoly = ((OGRPolygon *) poGeom);
+        OGRPolygon *poPoly = reinterpret_cast<OGRPolygon *>( poGeom );
 
         DGNElemCore **papsGroupExt = LineStringToElementGroup(
                 poPoly->getExteriorRing(), DGNT_SHAPE);
 
-        int innerRingsCnt = poPoly->getNumInteriorRings();
+        const int innerRingsCnt = poPoly->getNumInteriorRings();
 
         if (innerRingsCnt > 0) {
             CPLDebug("InnerRings", "there are %d inner rings", innerRingsCnt);
             std::list<DGNElemCore*> dgnElements;
 
-            for (i = 0; papsGroupExt[i] != NULL; i++) {
+            for( int i = 0; papsGroupExt[i] != NULL; i++) {
                 dgnElements.push_back(papsGroupExt[i]);
             }
             CPLFree(papsGroupExt);
@@ -1076,7 +1110,7 @@ OGRErr OGRDGNLayer::CreateFeatureWithGeom( OGRFeature *poFeature,
                         poPoly->getInteriorRing(iRing), DGNT_SHAPE);
                 papsGroupInner[0]->properties |= DGNPF_HOLE;
                 DGNUpdateElemCoreExtended(hDGN, papsGroupInner[0]);
-                for (i = 0; papsGroupInner[i] != NULL; i++) {
+                for( int i = 0; papsGroupInner[i] != NULL; i++ ) {
                     dgnElements.push_back(papsGroupInner[i]);
                 }
                 CPLFree(papsGroupInner);
@@ -1084,36 +1118,39 @@ OGRErr OGRDGNLayer::CreateFeatureWithGeom( OGRFeature *poFeature,
             int index = 1;
             papsGroup = (DGNElemCore **) CPLCalloc(sizeof(void*),
                     dgnElements.size() + 2);
-            for (std::list<DGNElemCore*>::iterator list_iter =
-                    dgnElements.begin(); list_iter != dgnElements.end();
-                    list_iter++) {
+            for( std::list<DGNElemCore*>::iterator list_iter
+                     = dgnElements.begin();
+                 list_iter != dgnElements.end();
+                 ++list_iter) {
                 papsGroup[index++] = *list_iter;
             }
 
-            //papsGroup[0] = DGNCreateComplexHeaderFromGroup( hDGN, DGNT_COMPLEX_SHAPE_HEADER, dgnElements.size(), papsGroup+1);
+            // papsGroup[0] = DGNCreateComplexHeaderFromGroup(
+            //     hDGN, DGNT_COMPLEX_SHAPE_HEADER, dgnElements.size(),
+            //     papsGroup+1 );
             DGNPoint asPoints[1];
             asPoints[0].x = 0;
             asPoints[0].y = 0;
             asPoints[0].z = 0;
-            papsGroup[0] = DGNCreateCellHeaderFromGroup(hDGN, "", 1, NULL,
-                    dgnElements.size(), papsGroup + 1, asPoints + 0, 1.0, 1.0,
-                    0.0);
+            papsGroup[0] = DGNCreateCellHeaderFromGroup(
+                hDGN, "", 1, NULL,
+                static_cast<int>(dgnElements.size()), papsGroup + 1,
+                asPoints + 0, 1.0, 1.0, 0.0) ;
             DGNAddShapeFillInfo(hDGN, papsGroup[0], 6);
         } else {
             papsGroup = papsGroupExt;
         }
     }
-    else if( wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon 
+    else if( wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon
              || wkbFlatten(poGeom->getGeometryType()) == wkbMultiPoint
              || wkbFlatten(poGeom->getGeometryType()) == wkbMultiLineString
              || wkbFlatten(poGeom->getGeometryType()) == wkbGeometryCollection)
     {
         OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeom;
-        int iGeom;
 
-        for( iGeom = 0; iGeom < poGC->getNumGeometries(); iGeom++ )
+        for( int iGeom = 0; iGeom < poGC->getNumGeometries(); iGeom++ )
         {
-            OGRErr eErr = CreateFeatureWithGeom( poFeature, 
+            OGRErr eErr = CreateFeatureWithGeom( poFeature,
                                                  poGC->getGeometryRef(iGeom) );
             if( eErr != OGRERR_NONE )
                 return eErr;
@@ -1123,7 +1160,7 @@ OGRErr OGRDGNLayer::CreateFeatureWithGeom( OGRFeature *poFeature,
     }
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unsupported geometry type (%s) for DGN.",
                   OGRGeometryTypeToName( poGeom->getGeometryType() ) );
         return OGRERR_FAILURE;
@@ -1139,19 +1176,20 @@ OGRErr OGRDGNLayer::CreateFeatureWithGeom( OGRFeature *poFeature,
     int nStyle = poFeature->GetFieldAsInteger( "Style" );
     int nMSLink = poFeature->GetFieldAsInteger( "MSLink" );
 
+    // TODO: Use std::max and std::min.
     nLevel = MAX(0,MIN(63,nLevel));
     nColor = MAX(0,MIN(255,nColor));
     nWeight = MAX(0,MIN(31,nWeight));
     nStyle = MAX(0,MIN(7,nStyle));
     nMSLink = MAX(0,nMSLink);
 
-    DGNUpdateElemCore( hDGN, papsGroup[0], nLevel, nGraphicGroup, nColor, 
+    DGNUpdateElemCore( hDGN, papsGroup[0], nLevel, nGraphicGroup, nColor,
                        nWeight, nStyle );
     DGNAddMSLink( hDGN, papsGroup[0], DGNLT_ODBC, 0, nMSLink );
 /* -------------------------------------------------------------------- */
 /*      Write to file.                                                  */
 /* -------------------------------------------------------------------- */
-    for( i = 0; papsGroup[i] != NULL; i++ )
+    for( int i = 0; papsGroup[i] != NULL; i++ )
     {
         DGNWriteElement( hDGN, papsGroup[i] );
 
diff --git a/ogr/ogrsf_frmts/dgn/web/index.html b/ogr/ogrsf_frmts/dgn/web/index.html
index 33423dd..c851219 100644
--- a/ogr/ogrsf_frmts/dgn/web/index.html
+++ b/ogr/ogrsf_frmts/dgn/web/index.html
@@ -7,19 +7,19 @@
 
 <h1>DGNLib: a Microstation DGN (ISFF) Reader</h1>
 
-I (<a href="http://pobox.com/~warmerdam">Frank Warmerdam</a>) 
-have implemented a Microstation DGN reading library on contract to 
-<a href="http://www.avenza.com/">Avenza Systems Inc.</a>, makers of 
-MAPublisher.  The library will be OpenSource (under my usual X/MIT license), 
-portable and callable from C/C++.  While it has been incorporated into my 
-<a href="http://gdal.maptools.org/ogr">OGR Simple Features</a> library, it is 
+I (<a href="http://pobox.com/~warmerdam">Frank Warmerdam</a>)
+have implemented a Microstation DGN reading library on contract to
+<a href="http://www.avenza.com/">Avenza Systems Inc.</a>, makers of
+MAPublisher.  The library will be OpenSource (under my usual X/MIT license),
+portable and callable from C/C++.  While it has been incorporated into my
+<a href="http://gdal.maptools.org/ogr">OGR Simple Features</a> library, it is
 also be usable standalone with minimal overhead.  The dgnlib library, and this
-page of DGN related information are primarily hosted at 
+page of DGN related information are primarily hosted at
 <a href="http://dgnlib.maptools.org/">http://dgnlib.maptools.org</a>.<p>
 
 <h2>DGNLib</h2>
 
-DGNLib is a small C/C++ library for reading and writing DGN files.  
+DGNLib is a small C/C++ library for reading and writing DGN files.
 
 <ul>
 
@@ -31,8 +31,8 @@ with <i>dgndump</i> example mainline.<p>
 <li> <b>Does DGNLib support all DGN elements?</b><p>
 
 No, but it does support most 2D and 3D elements.  Some of the more esoteric
-elements are read in "raw data mode", but not interpreted.  It does support 
-lines, line strings, curves, bsplines, ellipses, 
+elements are read in "raw data mode", but not interpreted.  It does support
+lines, line strings, curves, bsplines, ellipses,
 arcs, and text elements, as well as extracting color tables, and master
 coordinate information.<p>
 
@@ -44,11 +44,11 @@ Alliance</a> does support DGN v8.<p>
 
 <li> <b>Is it portable?</b><p>
 
-Yes, fairly, though as distributed it may be necessary to tweak the 
+Yes, fairly, though as distributed it may be necessary to tweak the
 cpl_port.h and cpl_config.h files for different platforms.  It was developed
 on Linux for a client deploying on MacOS, and Windows.<p>
 
-<li> <b>Does it require alot of memory?</b><p>
+<li> <b>Does it require a lot of memory?</b><p>
 
 Generally speaking no.  Only one element at a time is kept in memory.  If
 the file is "indexed" an additional 12 bytes per element is kept in memory
@@ -58,9 +58,9 @@ after a pre-scan, but this isn't required.<P>
 
 No, but there is a <a href="representation.html">document</a> that tries to
 indicate how to properly draw DGN elements given the structures returned by
-DGNLib.  The OGR layer re-interprets the drawing information into 
-<a href="http://www.gdal.org/ogr/ogr_feature_style.html">OGR Feature Style</a>
-format which is understood by some applications such as 
+DGNLib.  The OGR layer re-interprets the drawing information into
+<a href="http://www.gdal.org/ogr_feature_style.html">OGR Feature Style</a>
+format which is understood by some applications such as
 <a href="http://mapserver.gis.umn.edu/">UMN MapServer</a>.
 <p>
 
@@ -72,7 +72,7 @@ issues.  See the header of any source file for the full license text. <p>
 
 <li> <b>Is there support for writing DGN files?</b><p>
 
-Yes, there is preliminary support for writing 2D and 3D DGN files in 
+Yes, there is preliminary support for writing 2D and 3D DGN files in
 recent releases.<p>
 
 <li> <b>Is there documentation?</b><p>
@@ -93,15 +93,15 @@ bugs and adding minor features.  Improvements are welcome.<p>
 <ul>
 
 <li> <a href="dgn.html">ISFF/DGN File Format</a>: I have taken the venerable
-<a href="isff.txt">isff.txt</a> description, and am reformatting it in 
+<a href="isff.txt">isff.txt</a> description, and am reformatting it in
 HTML and filling in missing information.<P>
 
-<li> <a href="dl/ref18.pdf">Microstation 95/ISFF Description (pdf)</a>: 
+<li> <a href="dl/ref18.pdf">Microstation 95/ISFF Description (pdf)</a>:
 Information on the ISFF/DGN file format as distributed with Microstation 95.
 <P>
 
-<li> The most recently 
-<a href="http://www.gdal.org/srctree/ogr/ogrsf_frmts/dgn/">committed code</a> 
+<li> The most recently
+<a href="http://www.gdal.org/srctree/ogr/ogrsf_frmts/dgn/">committed code</a>
 is available in <a href="http://www.gdal.org/">GDAL</a> CVS tree.<p>
 
 
@@ -112,13 +112,13 @@ is available in <a href="http://www.gdal.org/">GDAL</a> CVS tree.<p>
 drawing DGN elements properly.<p>
 
 <li> <a href="http://www.intergraph.com/gis/support/technotes/db_link.asp">
-Intergraph Notes on Database Linkages</a> 
+Intergraph Notes on Database Linkages</a>
 (also <a href="dl/db_link.doc">db_link.doc</a> in MS Word format)<p>
 
-<li> The <a href="mailto:dgnlib at yahoogroups.com">dgnlib at yahoogroups.com</a> mailing list is for discussion of general DGN issues as well as dgnlib in 
-particular.  The group includes an <a href="http://groups.yahoo.com/group/dgnlib/">email archive</a> and can be subscribed from the following subscribe box. 
+<li> The <a href="mailto:dgnlib at yahoogroups.com">dgnlib at yahoogroups.com</a> mailing list is for discussion of general DGN issues as well as dgnlib in
+particular.  The group includes an <a href="http://groups.yahoo.com/group/dgnlib/">email archive</a> and can be subscribed from the following subscribe box.
 Please confirm your interest with <a href="mailto:warmerdam at pobox.com">me</a>
-by email if you are using a relatively anonymous email service so I can 
+by email if you are using a relatively anonymous email service so I can
 verify you aren't a spammer.<p>
 
 <form method=GET action="http://groups.yahoo.com/subscribe/dgnlib">
@@ -128,11 +128,11 @@ verify you aren't a spammer.<p>
                          <b>Subscribe to dgnlib</b>
                        </td>
                      </tr>
-                     <tr> 
-                       <td> 
+                     <tr>
+                       <td>
                          <input type=text name="user" value="enter email address" size=20>
                        </td>
-                       <td> 
+                       <td>
                          <input type=image border=0 alt="Click here to join dgnlib"
                           name="Click here to join dgnlib" src="http://groups.yahoo.com/img/ui/join.gif">
                        </td>
@@ -148,7 +148,7 @@ verify you aren't a spammer.<p>
 
 <li> DGNdirect is a library from the <a href="http://www.opendwg.org/">
 Open Design  Alliance</a> that supports reading (and to some extent) writing DGN
-v8 files.  It also supports reading DGN v7 files.  The Open Design Alliance 
+v8 files.  It also supports reading DGN v7 files.  The Open Design Alliance
 offers it under quite reasonable (but not Open Source) licensing terms.<p>
 
 <li> Bentley itself offers DGN libraries, and tools as part of their
@@ -166,7 +166,7 @@ document viewer which includes DGN support.<p>
 excellent DGN read and write support, and can be used as a standalone product,
 or FMEObjects acts as a library.<p>
 
-<li> My own <A href="http://openev.sf.net/">OpenEV</a> uses dgnlib for DGN 
+<li> My own <A href="http://openev.sf.net/">OpenEV</a> uses dgnlib for DGN
 support.<p>
 
 </ul>
@@ -186,20 +186,20 @@ Oregon DOT</a><p>
 I would like to thank:<p>
 
 <ul>
-<li> Dennis Christopher (and <a href="http://www.avenza.com/">Avenza Systems 
+<li> Dennis Christopher (and <a href="http://www.avenza.com/">Avenza Systems
 Inc</a>) for funding this development, and allowing me to release it as
 open source.<p>
 
 <li> Rodney Jenson who gave me some hints, and moral support.<p>
 
-<li> Patrick van Dijk, for information and code related to Quaternion 
+<li> Patrick van Dijk, for information and code related to Quaternion
 handling.<p>
 
-<li> Cybertal Components, whose's OpenDGN based dumping program was helpful to 
-me in testing.  Unfortunately, Cybertal does not appear to still be in 
+<li> Cybertal Components, whose's OpenDGN based dumping program was helpful to
+me in testing.  Unfortunately, Cybertal does not appear to still be in
 business.<p>
 
-<li> Ason Kang who provided a sample multi-byte text file and code to 
+<li> Ason Kang who provided a sample multi-byte text file and code to
 handle it properly.<p>
 
 <li> The various US DOTs and other government organizations who are progressive
@@ -208,21 +208,24 @@ a great store of sample data. <p>
 
 <li> Mike Cane for held with Radix50 names, and support for cell headers.<p>
 
-<li> Jeff Smith (Geographic Software Specialists) who funded DGN write 
+<li> Jeff Smith (Geographic Software Specialists) who funded DGN write
 support.<p>
 
-<li> Jamie Cecchetto (<a href="http://www.centurysystems.net">Century 
+<li> Jamie Cecchetto (<a href="http://www.centurysystems.net">Century
 Systems</a>) for funding 3D write support. <p>
 
-<li> <a href="http://www.dmsolutions.ca/">DM Solutions Group</a> for 
-providing the <a href="http://maptools.org">maptools.org</a> site to 
-host this on, and for funding (also thanks to Tyler Mitchell of 
+<li> <a href="http://www.dmsolutions.ca/">DM Solutions Group</a> for
+providing the <a href="http://maptools.org">maptools.org</a> site to
+host this on, and for funding (also thanks to Tyler Mitchell of
 <a href="http://www.lignum.com">Lignum</a>) integration into
 OGR.<p>
 
 <li> Marius Kintel (<a href="http://www.sim.no">Systems In Motion</a>) for
-adding support for reading 3D cone (23), 3D surface (18) and 3D solid (19) 
+adding support for reading 3D cone (23), 3D surface (18) and 3D solid (19)
 elements.<p>
+
+<li> Paulo Pires for adding 3D transformation support in DGNCreateCellHeaderElem().<p>
+
 </ul>
 
 </BODY>
diff --git a/ogr/ogrsf_frmts/dgn/web/representation.html b/ogr/ogrsf_frmts/dgn/web/representation.html
index ea59054..6923cec 100644
--- a/ogr/ogrsf_frmts/dgn/web/representation.html
+++ b/ogr/ogrsf_frmts/dgn/web/representation.html
@@ -7,13 +7,13 @@
 <h1>Microstation DGN Feature Representation</h1>
 
 This document addresses how DGN features should be drawn to match the
-behaviour of Microstation as closely as possible.  It is written for 
-users of the <a href="index.html">dgnlib</a> reader code, but the information 
+behaviour of Microstation as closely as possible.  It is written for
+users of the <a href="index.html">dgnlib</a> reader code, but the information
 should be applicable to anyone working with DGN.<p>
 
-The information is based on the ISFF.TXT document, supposition, and 
+The information is based on the ISFF.TXT document, supposition, and
 review of display effects in various viewers.  It is incomplete, and at times
-likely incorrect.  I would appreciate feedback at 
+likely incorrect.  I would appreciate feedback at
 <a href="mailto:warmerdam at pobox.com">warmerdam at pobox.com</a>.<p>
 
 <h2>General Symbology Information</h2>
@@ -30,10 +30,10 @@ the following fields in DGNElemCore.<p>
 
 <h3>Color</h3>
 
-The color field of the DGNElemCore is a color index number (0-255), 
-referencing a color from the appropriate color table.  This is normally 
+The color field of the DGNElemCore is a color index number (0-255),
+referencing a color from the appropriate color table.  This is normally
 translated into an
-RGB color for use using DGNLookupColor().  The returned color should be 
+RGB color for use using DGNLookupColor().  The returned color should be
 considered the foreground color for drawing the element.<p>
 
 <i>NOTE: There can be more than one color table in a DGN file, and
@@ -78,7 +78,7 @@ used have been found.<p>
 
 If used with a line element, the <b>DBNPF_HOLE</b> flag indicates that
 the line should be treated as infinite, while it is otherwise just a segment
-between the two provided points.  If used with a closed element (shape, 
+between the two provided points.  If used with a closed element (shape,
 complex shape, ellipse, ...) it indicates that shape is a hole (unfilled) while
 by default such elements are filled.<p>
 
@@ -101,8 +101,8 @@ linkage will also be included.  The fill color may differ from the element
 color in which case the element should be filled with the fill color, and
 then the boundary drawn in the element (outline) color.<p>
 
-If the DGNPF_HOLE flag is set the shape is really a hole within another 
-element and should be "cleared".  The exact semantics are unclear.  The 
+If the DGNPF_HOLE flag is set the shape is really a hole within another
+element and should be "cleared".  The exact semantics are unclear.  The
 first and last vertices of a shape are always the same.<p>
 
 <h3>DGNT_CURVE</h3>
@@ -117,9 +117,9 @@ Thus, for a segment k, the interpolated points P are expressed as a function of
        Pk(d) = {Fk,x(d), Fk,y(d), Fk,z(d)} with 0 <= d <= Dk
 </pre>
 
-Fk,x, Fk,y, and Fk,z are cubic polynomials and Dk is the length of segment k. 
+Fk,x, Fk,y, and Fk,z are cubic polynomials and Dk is the length of segment k.
 In addition, the polynomial coefficients are functions of the segment
-length and the endpoint derivatives of Fk,x, Fk,y, and Fk,z. The subscript k 
+length and the endpoint derivatives of Fk,x, Fk,y, and Fk,z. The subscript k
 is merely a reminder that these functions depend on the segment.<p>
 
 The cubic polynomials are defined as follows:<p>
@@ -133,12 +133,12 @@ The m variable is analogous to the slope of the segment.<p>
 
 <pre>
  If (|mk+1,x-mk,x| + |mk-1,x-mk-2,x|) <> 0, then:
-    tk,x = (mk-1,x|mk+1,x-mk,x| + mk,x|mk-1,x-mk-2,x|)/(|mk+1,x-mk,x| + 
+    tk,x = (mk-1,x|mk+1,x-mk,x| + mk,x|mk-1,x-mk-2,x|)/(|mk+1,x-mk,x| +
     |mk-1,x-mk-2,x|)
  else:
     tk,x = (mk+1,x+mk,x) / 2
     mk,x = (Xk+1 - Xk) / Dk
-</pre>    
+</pre>
 Fk,y(d) and Fk,z(d) are defined analogously.<p>
 
 <h3>DGNT_BSPLINE</h3>
@@ -148,7 +148,7 @@ Fk,y(d) and Fk,z(d) are defined analogously.<p>
 <h3>DGNT_ELLIPSE</h3>
 
 Ellipse.  See DGNT_ARC for details of geometry.  The DGNPF_HOLE and
-fill color information are applied to ellipses in the same manner as 
+fill color information are applied to ellipses in the same manner as
 they are applied to the Shape. <p>
 
 <h3>DGNT_ARC</h3>
@@ -174,7 +174,7 @@ The origin is the center of rotation for the ellipse or arc.<P>
 The primary_axis and secondary_axis define the distance from the origin to
 the ellipse edge on the primary (horizontal) and secondary (vertical) axis.<P>
 
-The rotation indicates the counterclockwise (or clockwise if negative) 
+The rotation indicates the counterclockwise (or clockwise if negative)
 rotation in degrees of the defined ellipse around the origin.  <p>
 
 The startang indicates the start angle (degrees, counterclockwise) of the
@@ -193,7 +193,7 @@ Text.  Should be drawn using color.  The text structure looks like:<p>
 <pre>
 typedef struct {
     DGNElemCore core;
-    
+
     int		font_id;
     int		justification;
     long        length_mult;
diff --git a/ogr/ogrsf_frmts/dods/drv_dods.html b/ogr/ogrsf_frmts/dods/drv_dods.html
index db9cc84..c857523 100644
--- a/ogr/ogrsf_frmts/dods/drv_dods.html
+++ b/ogr/ogrsf_frmts/dods/drv_dods.html
@@ -27,7 +27,7 @@ into corresponding layers.  Sequences are (by default) treated as point
 layers with the point geometries picked up from lat and lon variables if
 available.  To provide more sophisticated translation of sequence, grid or
 array items into features it is necessary to provide additional information
-to OGR as DAS (dataset auxiliary informaton) either from the remote server, 
+to OGR as DAS (dataset auxiliary information) either from the remote server,
 or locally via the AIS mechanism.<p>
 
 A DAS definition for an OGR layer might look something like:
diff --git a/ogr/ogrsf_frmts/dods/ogr_dods.h b/ogr/ogrsf_frmts/dods/ogr_dods.h
index 1a10707..627a90c 100644
--- a/ogr/ogrsf_frmts/dods/ogr_dods.h
+++ b/ogr/ogrsf_frmts/dods/ogr_dods.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_dods.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogr_dods.h 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/DODS driver.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_DODS_H_INCLUDED
-#define _OGR_DODS_H_INCLUDED
+#ifndef OGR_DODS_H_INCLUDED
+#define OGR_DODS_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "cpl_error.h"
@@ -84,8 +84,8 @@ class OGRDODSFieldDefn {
 public:
     OGRDODSFieldDefn();
     ~OGRDODSFieldDefn();
-    
-    int Initialize( AttrTable *, 
+
+    int Initialize( AttrTable *,
                     BaseType *poTarget = NULL, BaseType *poSuperSeq = NULL );
     int Initialize( const char *, const char * = "das",
                     BaseType *poTarget = NULL, BaseType *poSuperSeq = NULL );
@@ -106,7 +106,7 @@ public:
 /************************************************************************/
 
 class OGRDODSDataSource;
-    
+
 class OGRDODSLayer : public OGRLayer
 {
   protected:
@@ -133,14 +133,14 @@ class OGRDODSLayer : public OGRLayer
     DataDDS            *poDataDDS;
 
     BaseType           *poTargetVar;
-    
+
     AttrTable          *poOGRLayerInfo;
 
     int                 bKnowExtent;
     OGREnvelope         sExtent;
 
   public:
-                        OGRDODSLayer( OGRDODSDataSource *poDS, 
+                        OGRDODSLayer( OGRDODSDataSource *poDS,
                                       const char *pszTarget,
                                       AttrTable *poAttrInfo );
     virtual             ~OGRDODSLayer();
@@ -156,6 +156,8 @@ class OGRDODSLayer : public OGRLayer
     virtual int         TestCapability( const char * );
 
     virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 };
 
 /************************************************************************/
@@ -176,7 +178,7 @@ private:
     int                 iLastSuperSeq;
 
     int                 nRecordCount; /* -1 if not yet known */
-    int                 nSuperSeqCount; 
+    int                 nSuperSeqCount;
     int                *panSubSeqSize;
 
     double              GetFieldValueAsDouble( OGRDODSFieldDefn *, int );
@@ -184,8 +186,8 @@ private:
                                        Sequence * );
 
     double              BaseTypeToDouble( BaseType * );
-    
-    int                 BuildFields( BaseType *, const char *, 
+
+    int                 BuildFields( BaseType *, const char *,
                                      const char * );
 
     Sequence           *FindSuperSequence( BaseType * );
@@ -194,13 +196,13 @@ protected:
     virtual int         ProvideDataDDS();
 
 public:
-                        OGRDODSSequenceLayer( OGRDODSDataSource *poDS, 
+                        OGRDODSSequenceLayer( OGRDODSDataSource *poDS,
                                               const char *pszTarget,
                                               AttrTable *poAttrInfo );
     virtual             ~OGRDODSSequenceLayer();
 
     virtual OGRFeature *GetFeature( GIntBig nFeatureId );
-    
+
     virtual GIntBig     GetFeatureCount( int );
 };
 
@@ -211,7 +213,7 @@ public:
 class OGRDODSDim
 {
 public:
-    OGRDODSDim() { 
+    OGRDODSDim() {
         pszDimName = NULL;
         nDimStart = 0;
         nDimEnd = 0;
@@ -239,7 +241,7 @@ public:
 class OGRDODSArrayRef
 {
 public:
-    OGRDODSArrayRef() { 
+    OGRDODSArrayRef() {
         pszName = NULL;
         iFieldIndex = -1;
         poArray = NULL;
@@ -274,21 +276,21 @@ class OGRDODSGridLayer : public OGRDODSLayer
 
     void               *pRawData;
 
-    int                 ArrayEntryToField( Array *poArray, void *pRawData, 
+    int                 ArrayEntryToField( Array *poArray, void *pRawData,
                                            int iArrayIndex,
                                            OGRFeature *poFeature, int iField);
-								       
+
 protected:
     virtual int         ProvideDataDDS();
 
 public:
-                        OGRDODSGridLayer( OGRDODSDataSource *poDS, 
+                        OGRDODSGridLayer( OGRDODSDataSource *poDS,
                                          const char *pszTarget,
                                          AttrTable *poAttrInfo );
     virtual             ~OGRDODSGridLayer();
 
     virtual OGRFeature *GetFeature( GIntBig nFeatureId );
-    
+
     virtual GIntBig     GetFeatureCount( int );
 
 };
@@ -301,7 +303,7 @@ class OGRDODSDataSource : public OGRDataSource
 {
     OGRDODSLayer        **papoLayers;
     int                 nLayers;
-    
+
     char               *pszName;
 
     void                AddLayer( OGRDODSLayer * );
@@ -350,6 +352,4 @@ int  OGRDODSGetVarIndex( Sequence *poParent, string oVarName );
 int  OGRDODSIsFloatInvalid( const float * );
 int  OGRDODSIsDoubleInvalid( const double * );
 
-#endif /* ndef _OGR_DODS_H_INCLUDED */
-
-
+#endif /* ndef OGR_DODS_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/dods/ogrdodsdatasource.cpp b/ogr/ogrsf_frmts/dods/ogrdodsdatasource.cpp
index 1ab4590..ad9f773 100644
--- a/ogr/ogrsf_frmts/dods/ogrdodsdatasource.cpp
+++ b/ogr/ogrsf_frmts/dods/ogrdodsdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdodsdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: ogrdodsdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OGR/DODS Interface
  * Purpose:  Implements OGRDODSDataSource class.
@@ -32,20 +32,19 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrdodsdatasource.cpp 27044 2014-03-16 23:41:27Z rouault $");
+CPL_CVSID("$Id: ogrdodsdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 /************************************************************************/
 /*                         OGRDODSDataSource()                          */
 /************************************************************************/
 
-OGRDODSDataSource::OGRDODSDataSource()
-
+OGRDODSDataSource::OGRDODSDataSource() :
+    papoLayers(NULL),
+    nLayers(0),
+    pszName(NULL),
+    poConnection(NULL),
+    poBTF(new BaseTypeFactory())
 {
-    pszName = NULL;
-    papoLayers = NULL;
-    nLayers = 0;
-    poConnection = NULL;
-
-    poBTF = new BaseTypeFactory();
+    // TODO: This implies that the order in the class declaration is wrong.
     poDDS = new DDS( poBTF );
 }
 
@@ -56,13 +55,11 @@ OGRDODSDataSource::OGRDODSDataSource()
 OGRDODSDataSource::~OGRDODSDataSource()
 
 {
-    int         i;
-
     CPLFree( pszName );
 
-    for( i = 0; i < nLayers; i++ )
+    for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
-    
+
     CPLFree( papoLayers );
 
     if( poConnection != NULL )
@@ -79,7 +76,7 @@ OGRDODSDataSource::~OGRDODSDataSource()
 int OGRDODSDataSource::Open( const char * pszNewName )
 
 {
-    CPLAssert( nLayers == 0 );					     
+    CPLAssert( nLayers == 0 );
 
     pszName = CPLStrdup( pszNewName );
 
@@ -96,7 +93,7 @@ int OGRDODSDataSource::Open( const char * pszNewName )
         oConstraints = pszFound;
         *pszFound = '\0';
     }
-        
+
     pszFound = strstr(pszWrkURL,"?");
     if( pszFound )
     {
@@ -116,7 +113,7 @@ int OGRDODSDataSource::Open( const char * pszNewName )
         pszWrkURL[nLen-5] = '\0';
     else if( strcmp(pszWrkURL+nLen-5,".html") == 0 )
         pszWrkURL[nLen-5] = '\0';
-        
+
     oBaseURL = pszWrkURL;
     CPLFree( pszWrkURL );
 
@@ -125,12 +122,12 @@ int OGRDODSDataSource::Open( const char * pszNewName )
 /*      the putenv() if there isn't already a DODS_CONF in the          */
 /*      environment.                                                    */
 /* -------------------------------------------------------------------- */
-    if( CPLGetConfigOption( "DODS_CONF", NULL ) != NULL 
+    if( CPLGetConfigOption( "DODS_CONF", NULL ) != NULL
         && getenv("DODS_CONF") == NULL )
     {
         static char szDODS_CONF[1000];
 
-        sprintf( szDODS_CONF, "DODS_CONF=%.980s", 
+        sprintf( szDODS_CONF, "DODS_CONF=%.980s",
                  CPLGetConfigOption( "DODS_CONF", "" ) );
         putenv( szDODS_CONF );
     }
@@ -149,14 +146,14 @@ int OGRDODSDataSource::Open( const char * pszNewName )
 /* -------------------------------------------------------------------- */
     string version;
 
-    try 
+    try
     {
         poConnection = new AISConnect( oBaseURL );
         version = poConnection->request_version();
-    } 
-    catch (Error &e) 
+    }
+    catch (Error &e)
     {
-        CPLError(CE_Failure, CPLE_OpenFailed, 
+        CPLError(CE_Failure, CPLE_OpenFailed,
                  "%s", e.get_error_message().c_str() );
         return FALSE;
     }
@@ -167,7 +164,7 @@ int OGRDODSDataSource::Open( const char * pszNewName )
 
     if (version.empty() || version.find("/3.") == string::npos)
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "I connected to the URL but could not get a DAP 3.x version string\n"
                   "from the server.  I will continue to connect but access may fail.");
     }
@@ -180,10 +177,10 @@ int OGRDODSDataSource::Open( const char * pszNewName )
         poConnection->request_das( oDAS );
         poConnection->request_dds( *poDDS, oProjection + oConstraints );
     }
-    catch (Error &e) 
+    catch (Error &e)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
-                 "Error fetching DAS or DDS:\n%s", 
+                 "Error fetching DAS or DDS:\n%s",
                  e.get_error_message().c_str() );
         return FALSE;
     }
@@ -207,36 +204,36 @@ int OGRDODSDataSource::Open( const char * pszNewName )
 
     for( dv_i = poTable->attr_begin(); dv_i != poTable->attr_end(); dv_i++ )
     {
-        if( EQUALN(poTable->get_name(dv_i).c_str(),"ogr_layer_info",14) 
+        if( STARTS_WITH_CI(poTable->get_name(dv_i).c_str(), "ogr_layer_info")
             && poTable->is_container( dv_i ) )
         {
             AttrTable *poAttr = poTable->get_attr_table( dv_i );
             string target_container = poAttr->get_attr( "target_container" );
             BaseType *poVar = poDDS->var( target_container.c_str() );
-            
+
             if( poVar == NULL )
             {
-                CPLError( CE_Warning, CPLE_AppDefined, 
+                CPLError( CE_Warning, CPLE_AppDefined,
                           "Unable to find variable '%s' named in\n"
-                          "ogr_layer_info.target_container, skipping.", 
+                          "ogr_layer_info.target_container, skipping.",
                           target_container.c_str() );
                 continue;
             }
 
             if( poVar->type() == dods_sequence_c )
-                AddLayer( 
+                AddLayer(
                     new OGRDODSSequenceLayer(this,
                                              target_container.c_str(),
                                              poAttr) );
-            else if( poVar->type() == dods_grid_c 
+            else if( poVar->type() == dods_grid_c
                      || poVar->type() == dods_array_c )
                 AddLayer( new OGRDODSGridLayer(this,target_container.c_str(),
                                                poAttr) );
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
-/*      Walk through the DODS variables looking for easily targetted    */
+/*      Walk through the DODS variables looking for easily targeted     */
 /*      ones.  Eventually this will need to be driven by the AIS info.  */
 /* -------------------------------------------------------------------- */
     if( nLayers == 0 )
@@ -246,11 +243,11 @@ int OGRDODSDataSource::Open( const char * pszNewName )
         for( v_i = poDDS->var_begin(); v_i != poDDS->var_end(); v_i++ )
         {
             BaseType *poVar = *v_i;
-            
+
             if( poVar->type() == dods_sequence_c )
                 AddLayer( new OGRDODSSequenceLayer(this,poVar->name().c_str(),
                                                    NULL) );
-            else if( poVar->type() == dods_grid_c 
+            else if( poVar->type() == dods_grid_c
                      || poVar->type() == dods_array_c )
                 AddLayer( new OGRDODSGridLayer(this,poVar->name().c_str(),
                                                NULL) );
diff --git a/ogr/ogrsf_frmts/dods/ogrdodsdriver.cpp b/ogr/ogrsf_frmts/dods/ogrdodsdriver.cpp
index 9f2c5cd..34cc260 100644
--- a/ogr/ogrsf_frmts/dods/ogrdodsdriver.cpp
+++ b/ogr/ogrsf_frmts/dods/ogrdodsdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdodsdriver.cpp 27597 2014-08-22 17:15:49Z rouault $
+ * $Id: ogrdodsdriver.cpp 31120 2015-10-24 19:55:09Z rouault $
  *
  * Project:  OGR/DODS Interface
  * Purpose:  Implements OGRDODSDriver class.
@@ -30,7 +30,7 @@
 #include "ogr_dods.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrdodsdriver.cpp 27597 2014-08-22 17:15:49Z rouault $");
+CPL_CVSID("$Id: ogrdodsdriver.cpp 31120 2015-10-24 19:55:09Z rouault $");
 
 /************************************************************************/
 /*                            ~OGRDODSDriver()                            */
@@ -61,7 +61,7 @@ OGRDataSource *OGRDODSDriver::Open( const char * pszFilename,
 {
     OGRDODSDataSource     *poDS;
 
-    if( !EQUALN(pszFilename,"DODS:http:",10) )
+    if( !STARTS_WITH_CI(pszFilename, "DODS:http:") )
         return NULL;
 
     poDS = new OGRDODSDataSource();
diff --git a/ogr/ogrsf_frmts/dods/ogrdodsfielddefn.cpp b/ogr/ogrsf_frmts/dods/ogrdodsfielddefn.cpp
index 1801c10..a72f1da 100644
--- a/ogr/ogrsf_frmts/dods/ogrdodsfielddefn.cpp
+++ b/ogr/ogrsf_frmts/dods/ogrdodsfielddefn.cpp
@@ -1,9 +1,9 @@
 /******************************************************************************
- * $Id: ogrdodsfielddefn.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: ogrdodsfielddefn.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OGR/DODS Interface
  * Purpose:  Implements OGRDODSFieldDefn class.  This is a small class used
- *           to encapsulate information about a referenced field. 
+ *           to encapsulate information about a referenced field.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -31,24 +31,22 @@
 #include "ogr_dods.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrdodsfielddefn.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: ogrdodsfielddefn.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                          OGRDODSFieldDefn()                          */
 /************************************************************************/
 
-OGRDODSFieldDefn::OGRDODSFieldDefn()
-
-{
-    pszFieldName = NULL;
-    pszFieldScope = NULL;
-    iFieldIndex = -1;
-    pszFieldValue = NULL;
-    bValid = FALSE;
-    pszPathToSequence = NULL;
-    bRelativeToSuperSequence = FALSE;
-    bRelativeToSequence = FALSE;
-}
+OGRDODSFieldDefn::OGRDODSFieldDefn() :
+    bValid(FALSE),
+    pszFieldName(NULL),
+    pszFieldScope(NULL),
+    iFieldIndex(-1),
+    pszFieldValue(NULL),
+    pszPathToSequence(NULL),
+    bRelativeToSuperSequence(FALSE),
+    bRelativeToSequence(FALSE)
+{}
 
 /************************************************************************/
 /*                         ~OGRDODSFieldDefn()                          */
@@ -73,7 +71,7 @@ OGRDODSFieldDefn::~OGRDODSFieldDefn()
 /************************************************************************/
 
 int OGRDODSFieldDefn::Initialize( AttrTable *poEntry,
-                                  BaseType *poTarget, 
+                                  BaseType *poTarget,
                                   BaseType *poSuperSeq )
 
 {
@@ -89,9 +87,9 @@ int OGRDODSFieldDefn::Initialize( AttrTable *poEntry,
 /*                             Initialize()                             */
 /************************************************************************/
 
-int OGRDODSFieldDefn::Initialize( const char *pszFieldNameIn, 
+int OGRDODSFieldDefn::Initialize( const char *pszFieldNameIn,
                                   const char *pszFieldScopeIn,
-                                  BaseType *poTarget, 
+                                  BaseType *poTarget,
                                   BaseType *poSuperSeq )
 
 {
@@ -103,14 +101,14 @@ int OGRDODSFieldDefn::Initialize( const char *pszFieldNameIn,
         string oTargPath = OGRDODSGetVarPath( poTarget );
         int    nTargPathLen = strlen(oTargPath.c_str());
 
-        if( EQUALN(oTargPath.c_str(),pszFieldNameIn,nTargPathLen) 
+        if( EQUALN(oTargPath.c_str(),pszFieldNameIn,nTargPathLen)
             && pszFieldNameIn[nTargPathLen] == '.' )
         {
             CPLFree( pszFieldName );
             pszFieldName = CPLStrdup( pszFieldNameIn + nTargPathLen + 1 );
 
             bRelativeToSequence = TRUE;
-            iFieldIndex = OGRDODSGetVarIndex( 
+            iFieldIndex = OGRDODSGetVarIndex(
                 dynamic_cast<Sequence *>( poTarget ), pszFieldName );
         }
         else if( poSuperSeq != NULL  )
@@ -118,14 +116,14 @@ int OGRDODSFieldDefn::Initialize( const char *pszFieldNameIn,
             string oTargPath = OGRDODSGetVarPath( poSuperSeq );
             int    nTargPathLen = strlen(oTargPath.c_str());
 
-            if( EQUALN(oTargPath.c_str(),pszFieldNameIn,nTargPathLen) 
+            if( EQUALN(oTargPath.c_str(),pszFieldNameIn,nTargPathLen)
                 && pszFieldNameIn[nTargPathLen] == '.' )
             {
                 CPLFree( pszFieldName );
                 pszFieldName = CPLStrdup( pszFieldNameIn + nTargPathLen + 1 );
 
                 bRelativeToSuperSequence = TRUE;
-                iFieldIndex = OGRDODSGetVarIndex( 
+                iFieldIndex = OGRDODSGetVarIndex(
                     dynamic_cast<Sequence *>( poSuperSeq ), pszFieldName );
             }
         }
@@ -167,8 +165,8 @@ int  OGRDODSGetVarIndex( Sequence *poParent, string oVarName )
     Sequence::Vars_iter v_i;
     int                 i;
 
-    for( v_i = poParent->var_begin(), i=0; 
-         v_i != poParent->var_end(); 
+    for( v_i = poParent->var_begin(), i=0;
+         v_i != poParent->var_end();
          v_i++, i++ )
     {
         if( EQUAL((*v_i)->name().c_str(),oVarName.c_str()) )
diff --git a/ogr/ogrsf_frmts/dods/ogrdodsgrid.cpp b/ogr/ogrsf_frmts/dods/ogrdodsgrid.cpp
index aa31e97..7c9c6ab 100644
--- a/ogr/ogrsf_frmts/dods/ogrdodsgrid.cpp
+++ b/ogr/ogrsf_frmts/dods/ogrdodsgrid.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdodsgrid.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrdodsgrid.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OGR/DODS Interface
  * Purpose:  Implements OGRDODSGridLayer class, which implements the
@@ -32,20 +32,25 @@
 #include "ogr_dods.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrdodsgrid.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrdodsgrid.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                          OGRDODSGridLayer()                          */
 /************************************************************************/
 
-OGRDODSGridLayer::OGRDODSGridLayer( OGRDODSDataSource *poDSIn, 
-                                            const char *pszTargetIn,
-                                            AttrTable *poOGRLayerInfoIn )
-
-        : OGRDODSLayer( poDSIn, pszTargetIn, poOGRLayerInfoIn )
-
+OGRDODSGridLayer::OGRDODSGridLayer( OGRDODSDataSource *poDSIn,
+                                    const char *pszTargetIn,
+                                    AttrTable *poOGRLayerInfoIn ) :
+    OGRDODSLayer( poDSIn, pszTargetIn, poOGRLayerInfoIn ),
+    poTargetGrid(NULL),
+    poTargetArray(NULL),
+    nArrayRefCount(0),
+    paoArrayRefs(NULL),
+    nDimCount(0),
+    paoDimensions(NULL),
+    nMaxRawIndex(0),
+    pRawData(NULL)
 {
-    pRawData = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      What is the layer name?                                         */
@@ -59,7 +64,7 @@ OGRDODSGridLayer::OGRDODSGridLayer( OGRDODSDataSource *poDSIn,
         if( strlen(oLayerName.c_str()) > 0 )
             pszLayerName = oLayerName.c_str();
     }
-        
+
     poFeatureDefn = new OGRFeatureDefn( pszLayerName );
     poFeatureDefn->Reference();
 
@@ -97,7 +102,7 @@ OGRDODSGridLayer::OGRDODSGridLayer( OGRDODSDataSource *poDSIn,
     {
         AttrTable::Attr_iter dv_i;
 
-        for( dv_i = poExtraContainers->attr_begin(); 
+        for( dv_i = poExtraContainers->attr_begin();
              dv_i != poExtraContainers->attr_end(); dv_i++ )
         {
             nArrayRefCount++;
@@ -117,7 +122,7 @@ OGRDODSGridLayer::OGRDODSGridLayer( OGRDODSDataSource *poDSIn,
     {
         AttrTable::Attr_iter dv_i;
 
-        for( dv_i = poExtraContainers->attr_begin(); 
+        for( dv_i = poExtraContainers->attr_begin();
              dv_i != poExtraContainers->attr_end(); dv_i++ )
         {
             const char *pszTargetName=poExtraContainers->get_attr(dv_i).c_str();
@@ -125,25 +130,25 @@ OGRDODSGridLayer::OGRDODSGridLayer( OGRDODSDataSource *poDSIn,
 
             if( poExtraTarget == NULL )
             {
-                CPLError( CE_Warning, CPLE_AppDefined, 
-                          "Unable to find extra_container '%s', skipping.", 
+                CPLError( CE_Warning, CPLE_AppDefined,
+                          "Unable to find extra_container '%s', skipping.",
                           pszTargetName );
                 continue;
             }
 
             if( poExtraTarget->type() == dods_array_c )
-                paoArrayRefs[nArrayRefCount].poArray = 
+                paoArrayRefs[nArrayRefCount].poArray =
                     dynamic_cast<Array *>( poExtraTarget );
             else if( poExtraTarget->type() == dods_grid_c )
             {
                 Grid *poGrid = dynamic_cast<Grid *>( poExtraTarget );
-                paoArrayRefs[nArrayRefCount].poArray = 
+                paoArrayRefs[nArrayRefCount].poArray =
                     dynamic_cast<Array *>( poGrid->array_var() );
             }
             else
             {
-                CPLError( CE_Warning, CPLE_AppDefined, 
-                          "Target container '%s' is not grid or array, skipping.", 
+                CPLError( CE_Warning, CPLE_AppDefined,
+                          "Target container '%s' is not grid or array, skipping.",
                           pszTargetName );
                 continue;
             }
@@ -163,22 +168,22 @@ OGRDODSGridLayer::OGRDODSGridLayer( OGRDODSDataSource *poDSIn,
     nMaxRawIndex = 1;
 
     for( iterDim = poTargetArray->dim_begin(), iDim = 0;
-         iterDim != poTargetArray->dim_end(); 
+         iterDim != poTargetArray->dim_end();
          iterDim++, iDim++ )
     {
-        paoDimensions[iDim].pszDimName = 
+        paoDimensions[iDim].pszDimName =
             CPLStrdup(poTargetArray->dimension_name(iterDim).c_str());
-        paoDimensions[iDim].nDimStart = 
+        paoDimensions[iDim].nDimStart =
             poTargetArray->dimension_start(iterDim);
-        paoDimensions[iDim].nDimEnd = 
+        paoDimensions[iDim].nDimEnd =
             poTargetArray->dimension_stop(iterDim);
-        paoDimensions[iDim].nDimStride = 
+        paoDimensions[iDim].nDimStride =
             poTargetArray->dimension_stride(iterDim);
         paoDimensions[iDim].poMap = NULL;
 
-        paoDimensions[iDim].nDimEntries = 
+        paoDimensions[iDim].nDimEntries =
             (paoDimensions[iDim].nDimEnd + 1 - paoDimensions[iDim].nDimStart
-             + paoDimensions[iDim].nDimStride - 1) 
+             + paoDimensions[iDim].nDimStride - 1)
             / paoDimensions[iDim].nDimStride;
 
         nMaxRawIndex *= paoDimensions[iDim].nDimEntries;
@@ -193,7 +198,7 @@ OGRDODSGridLayer::OGRDODSGridLayer( OGRDODSDataSource *poDSIn,
         Grid::Map_iter iterMap;
 
         for( iterMap = poTargetGrid->map_begin(), iMap = 0;
-             iterMap != poTargetGrid->map_end(); 
+             iterMap != poTargetGrid->map_end();
              iterMap++, iMap++ )
         {
             paoDimensions[iMap].poMap = dynamic_cast<Array *>(*iterMap);
@@ -253,7 +258,7 @@ OGRDODSGridLayer::OGRDODSGridLayer( OGRDODSDataSource *poDSIn,
     {
         OGRDODSArrayRef *poRef = paoArrayRefs + iArray;
         OGRFieldDefn oArrayField( poRef->poArray->name().c_str(), OFTInteger );
-        
+
         switch( poRef->poArray->var()->type() )
         {
           case dods_byte_c:
@@ -292,7 +297,7 @@ OGRDODSGridLayer::OGRDODSGridLayer( OGRDODSDataSource *poDSIn,
         if( poField != NULL )
         {
             oXField.Initialize( poField );
-            oXField.iFieldIndex = 
+            oXField.iFieldIndex =
                 poFeatureDefn->GetFieldIndex( oXField.pszFieldName );
         }
 
@@ -300,7 +305,7 @@ OGRDODSGridLayer::OGRDODSGridLayer( OGRDODSDataSource *poDSIn,
         if( poField != NULL )
         {
             oYField.Initialize( poField );
-            oYField.iFieldIndex = 
+            oYField.iFieldIndex =
                 poFeatureDefn->GetFieldIndex( oYField.pszFieldName );
         }
 
@@ -308,7 +313,7 @@ OGRDODSGridLayer::OGRDODSGridLayer( OGRDODSDataSource *poDSIn,
         if( poField != NULL )
         {
             oZField.Initialize( poField );
-            oZField.iFieldIndex = 
+            oZField.iFieldIndex =
                 poFeatureDefn->GetFieldIndex( oZField.pszFieldName );
         }
 
@@ -364,7 +369,7 @@ OGRDODSGridLayer::~OGRDODSGridLayer()
 /*                         ArrayEntryToField()                          */
 /************************************************************************/
 
-int OGRDODSGridLayer::ArrayEntryToField( Array *poArray, void *pRawData, 
+int OGRDODSGridLayer::ArrayEntryToField( Array *poArray, void *pRawData,
                                          int iArrayIndex,
                                          OGRFeature *poFeature, int iField)
 
@@ -425,7 +430,7 @@ int OGRDODSGridLayer::ArrayEntryToField( Array *poArray, void *pRawData,
     }
 
     return TRUE;
-}								       
+}
 
 /************************************************************************/
 /*                             GetFeature()                             */
@@ -460,9 +465,9 @@ OGRFeature *OGRDODSGridLayer::GetFeature( GIntBig nFeatureId )
 
     for( iDim = nDimCount-1; iDim >= 0; iDim-- )
     {
-        paoDimensions[iDim].iLastValue = 
-            (nRemainder % paoDimensions[iDim].nDimEntries) 
-            * paoDimensions[iDim].nDimStride 
+        paoDimensions[iDim].iLastValue =
+            (nRemainder % paoDimensions[iDim].nDimEntries)
+            * paoDimensions[iDim].nDimStride
             + paoDimensions[iDim].nDimStart;
         nRemainder = nRemainder / paoDimensions[iDim].nDimEntries;
 
@@ -479,9 +484,9 @@ OGRFeature *OGRDODSGridLayer::GetFeature( GIntBig nFeatureId )
     {
         for( iDim = 0; iDim < nDimCount; iDim++ )
         {
-            ArrayEntryToField( paoDimensions[iDim].poMap, 
-                               paoDimensions[iDim].pRawData, 
-                               paoDimensions[iDim].iLastValue, 
+            ArrayEntryToField( paoDimensions[iDim].poMap,
+                               paoDimensions[iDim].pRawData,
+                               paoDimensions[iDim].iLastValue,
                                poFeature, iDim );
         }
     }
@@ -494,7 +499,7 @@ OGRFeature *OGRDODSGridLayer::GetFeature( GIntBig nFeatureId )
     {
         OGRDODSArrayRef *poRef = paoArrayRefs + iArray;
 
-        ArrayEntryToField( poRef->poArray, poRef->pRawData, nFeatureId, 
+        ArrayEntryToField( poRef->poArray, poRef->pRawData, nFeatureId,
                            poFeature, poRef->iFieldIndex );
     }
 
@@ -563,8 +568,8 @@ int OGRDODSGridLayer::ProvideDataDDS()
         // Allocate appropriate raw data array, and pull out data into it.
         poRef->pRawData = CPLMalloc( poRef->poArray->width() );
         poRef->poArray->buf2val( &(poRef->pRawData) );
-    }        
-        
+    }
+
     // Setup pointers to each of the map objects.
     if( poTargetGrid != NULL )
     {
@@ -572,15 +577,15 @@ int OGRDODSGridLayer::ProvideDataDDS()
         Grid::Map_iter iterMap;
 
         for( iterMap = poTargetGrid->map_begin(), iMap = 0;
-             iterMap != poTargetGrid->map_end(); 
+             iterMap != poTargetGrid->map_end();
              iterMap++, iMap++ )
         {
             paoDimensions[iMap].poMap = dynamic_cast<Array *>(*iterMap);
-            paoDimensions[iMap].pRawData = 
+            paoDimensions[iMap].pRawData =
                 CPLMalloc( paoDimensions[iMap].poMap->width() );
             paoDimensions[iMap].poMap->buf2val( &(paoDimensions[iMap].pRawData) );
         }
-    }    
+    }
 
     return bResult;
 }
diff --git a/ogr/ogrsf_frmts/dods/ogrdodslayer.cpp b/ogr/ogrsf_frmts/dods/ogrdodslayer.cpp
index 9056a78..7352b2d 100644
--- a/ogr/ogrsf_frmts/dods/ogrdodslayer.cpp
+++ b/ogr/ogrsf_frmts/dods/ogrdodslayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdodslayer.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: ogrdodslayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OGR/DODS Interface
  * Purpose:  Implements OGRDODSLayer class.
@@ -30,34 +30,30 @@
 #include "ogr_dods.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrdodslayer.cpp 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: ogrdodslayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                            OGRDODSLayer()                            */
 /************************************************************************/
 
-OGRDODSLayer::OGRDODSLayer( OGRDODSDataSource *poDSIn, 
+OGRDODSLayer::OGRDODSLayer( OGRDODSDataSource *poDSIn,
                             const char *pszTargetIn,
-                            AttrTable *poOGRLayerInfoIn )
-
+                            AttrTable *poOGRLayerInfoIn ) :
+    poFeatureDefn(NULL),
+    poSRS(NULL),
+    iNextShapeId(0),
+    poDS(poDSIn),
+    pszQuery(NULL),
+    pszFIDColumn (NULL),
+    pszTarget(CPLStrdup( pszTargetIn )),
+    papoFields(NULL),
+    bDataLoaded(FALSE),
+    poConnection(NULL),
+    poDataDDS(new DataDDS( poDSIn->poBTF )),
+    poTargetVar(NULL),
+    poOGRLayerInfo(poOGRLayerInfoIn),
+    bKnowExtent(FALSE)
 {
-    poDS = poDSIn;
-    poFeatureDefn = NULL;
-    pszQuery = NULL;
-    pszFIDColumn = NULL;
-    poSRS = NULL;
-    iNextShapeId = 0;
-    pszTarget = CPLStrdup( pszTargetIn );
-    papoFields = NULL;
-
-    bDataLoaded = FALSE;
-    poConnection = NULL;
-    poTargetVar = NULL;
-    poOGRLayerInfo = poOGRLayerInfoIn;
-    bKnowExtent = FALSE;
-
-    poDataDDS = new DataDDS( poDSIn->poBTF );
-
 /* ==================================================================== */
 /*      Harvest some metadata if available.                             */
 /* ==================================================================== */
@@ -74,8 +70,8 @@ OGRDODSLayer::OGRDODSLayer( OGRDODSDataSource *poDSIn,
             poSRS = new OGRSpatialReference();
             if( poSRS->SetFromUserInput( oMValue.c_str() ) != OGRERR_NONE )
             {
-                CPLError( CE_Warning, CPLE_AppDefined, 
-                          "Ignoring unreconised SRS '%s'", 
+                CPLError( CE_Warning, CPLE_AppDefined,
+                          "Ignoring unrecognized SRS '%s'",
                           oMValue.c_str() );
                 delete poSRS;
                 poSRS = NULL;
@@ -114,7 +110,7 @@ OGRDODSLayer::~OGRDODSLayer()
     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     {
         CPLDebug( "DODS", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
+                  (int) m_nFeaturesRead,
                   poFeatureDefn->GetName() );
     }
 
@@ -165,7 +161,7 @@ OGRFeature *OGRDODSLayer::GetNextFeature()
 {
     OGRFeature *poFeature;
 
-    for( poFeature = GetFeature( iNextShapeId++ ); 
+    for( poFeature = GetFeature( iNextShapeId++ );
          poFeature != NULL;
          poFeature = GetFeature( iNextShapeId++ ) )
     {
@@ -218,14 +214,14 @@ int OGRDODSLayer::ProvideDataDDS()
                   poDS->oBaseURL.c_str(),
                   (poDS->oProjection + poDS->oConstraints).c_str() );
 
-        // We may need to use custom constraints here. 
-        poConnection->request_data( *poDataDDS, 
+        // We may need to use custom constraints here.
+        poConnection->request_data( *poDataDDS,
                                     poDS->oProjection + poDS->oConstraints );
     }
     catch (Error &e)
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "DataDDS request failed:\n%s", 
+                  "DataDDS request failed:\n%s",
                   e.get_error_message().c_str() );
         return FALSE;
     }
diff --git a/ogr/ogrsf_frmts/dods/ogrdodssequencelayer.cpp b/ogr/ogrsf_frmts/dods/ogrdodssequencelayer.cpp
index e8dcd53..5fa4983 100644
--- a/ogr/ogrsf_frmts/dods/ogrdodssequencelayer.cpp
+++ b/ogr/ogrsf_frmts/dods/ogrdodssequencelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdodssequencelayer.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrdodssequencelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OGR/DODS Interface
  * Purpose:  Implements OGRDODSSequenceLayer class, which implements the
@@ -32,23 +32,20 @@
 #include "ogr_dods.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrdodssequencelayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrdodssequencelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                        OGRDODSSequenceLayer()                        */
 /************************************************************************/
 
-OGRDODSSequenceLayer::OGRDODSSequenceLayer( OGRDODSDataSource *poDSIn, 
+OGRDODSSequenceLayer::OGRDODSSequenceLayer( OGRDODSDataSource *poDSIn,
                                             const char *pszTargetIn,
-                                            AttrTable *poOGRLayerInfoIn )
-
-        : OGRDODSLayer( poDSIn, pszTargetIn, poOGRLayerInfoIn )
-
+                                            AttrTable *poOGRLayerInfoIn ) :
+    OGRDODSLayer( poDSIn, pszTargetIn, poOGRLayerInfoIn ),
+    pszSubSeqPath("profile"), // hardcode for now.
+    iLastSuperSeq(-1),
+    panSubSeqSize(NULL)
 {
-    pszSubSeqPath = "profile"; // hardcode for now. 
-    panSubSeqSize = NULL;
-    iLastSuperSeq = -1;
-
 /* -------------------------------------------------------------------- */
 /*      What is the layer name?                                         */
 /* -------------------------------------------------------------------- */
@@ -61,7 +58,7 @@ OGRDODSSequenceLayer::OGRDODSSequenceLayer( OGRDODSDataSource *poDSIn,
         if( strlen(oLayerName.c_str()) > 0 )
             pszLayerName = oLayerName.c_str();
     }
-        
+
     poFeatureDefn = new OGRFeatureDefn( pszLayerName );
     poFeatureDefn->Reference();
 
@@ -106,7 +103,7 @@ OGRDODSSequenceLayer::OGRDODSSequenceLayer( OGRDODSDataSource *poDSIn,
         else
             oSSTargName = "impossiblexxx";
 
-        if( poDS->poDDS->var( oTargName + ".lon" ) != NULL 
+        if( poDS->poDDS->var( oTargName + ".lon" ) != NULL
             && poDS->poDDS->var( oTargName + ".lat" ) != NULL )
         {
             oXField.Initialize( (oTargName + ".lon").c_str(), "dds",
@@ -114,7 +111,7 @@ OGRDODSSequenceLayer::OGRDODSSequenceLayer( OGRDODSDataSource *poDSIn,
             oYField.Initialize( (oTargName + ".lat").c_str(), "dds",
                                 poTargetVar, poSuperSeq );
         }
-        else if( poDS->poDDS->var( oSSTargName + ".lon" ) != NULL 
+        else if( poDS->poDDS->var( oSSTargName + ".lon" ) != NULL
                  && poDS->poDDS->var( oSSTargName + ".lat" ) != NULL )
         {
             oXField.Initialize( (oSSTargName + ".lon").c_str(), "dds",
@@ -138,8 +135,8 @@ OGRDODSSequenceLayer::OGRDODSSequenceLayer( OGRDODSDataSource *poDSIn,
 /* -------------------------------------------------------------------- */
     if( poSuperSeq != NULL )
     {
-        for( v_i = poSuperSeq->var_begin(); 
-             v_i != poSuperSeq->var_end(); 
+        for( v_i = poSuperSeq->var_begin();
+             v_i != poSuperSeq->var_end();
              v_i++ )
             BuildFields( *v_i, NULL, NULL );
     }
@@ -165,8 +162,8 @@ Sequence *OGRDODSSequenceLayer::FindSuperSequence( BaseType *poChild )
 {
     BaseType *poParent;
 
-    for( poParent = poChild->get_parent(); 
-         poParent != NULL; 
+    for( poParent = poChild->get_parent();
+         poParent != NULL;
          poParent = poParent->get_parent() )
     {
         if( poParent->type() == dods_sequence_c )
@@ -185,10 +182,10 @@ Sequence *OGRDODSSequenceLayer::FindSuperSequence( BaseType *poChild )
 /*      the passed variable and it's children (if it has them).         */
 /************************************************************************/
 
-int OGRDODSSequenceLayer::BuildFields( BaseType *poFieldVar, 
+int OGRDODSSequenceLayer::BuildFields( BaseType *poFieldVar,
                                        const char *pszPathToVar,
                                        const char *pszPathToSequence )
-    
+
 {
     OGRFieldDefn oField( "", OFTInteger );
 
@@ -198,9 +195,9 @@ int OGRDODSSequenceLayer::BuildFields( BaseType *poFieldVar,
     if( pszPathToVar == NULL )
         oField.SetName( poFieldVar->name().c_str() );
     else
-        oField.SetName( CPLSPrintf( "%s.%s", pszPathToVar, 
+        oField.SetName( CPLSPrintf( "%s.%s", pszPathToVar,
                                     poFieldVar->name().c_str() ) );
-                                    
+
 /* -------------------------------------------------------------------- */
 /*      Capture this field definition.                                  */
 /* -------------------------------------------------------------------- */
@@ -243,7 +240,7 @@ int OGRDODSSequenceLayer::BuildFields( BaseType *poFieldVar,
               return FALSE;
 
           // We don't explore down into the target sequence if we
-          // are recursing from a supersequence. 
+          // are recursing from a supersequence.
           if( poFieldVar == this->poTargetVar )
               return FALSE;
 
@@ -263,19 +260,19 @@ int OGRDODSSequenceLayer::BuildFields( BaseType *poFieldVar,
 /* -------------------------------------------------------------------- */
     poFeatureDefn->AddFieldDefn( &oField );
 
-    papoFields = (OGRDODSFieldDefn **) 
+    papoFields = (OGRDODSFieldDefn **)
         CPLRealloc( papoFields, sizeof(void*) * poFeatureDefn->GetFieldCount());
 
-    papoFields[poFeatureDefn->GetFieldCount()-1] = 
+    papoFields[poFeatureDefn->GetFieldCount()-1] =
         new OGRDODSFieldDefn();
 
     papoFields[poFeatureDefn->GetFieldCount()-1]->Initialize(
-        OGRDODSGetVarPath(poFieldVar).c_str(), "dds", 
+        OGRDODSGetVarPath(poFieldVar).c_str(), "dds",
         poTargetVar, poSuperSeq );
 
-    
+
     if( pszPathToSequence )
-        papoFields[poFeatureDefn->GetFieldCount()-1]->pszPathToSequence 
+        papoFields[poFeatureDefn->GetFieldCount()-1]->pszPathToSequence
             = CPLStrdup( pszPathToSequence );
 
     return TRUE;
@@ -336,7 +333,7 @@ double OGRDODSSequenceLayer::BaseTypeToDouble( BaseType *poBT )
       {
           signed char byVal;
           void *pValPtr = &byVal;
-              
+
           poBT->buf2val( &pValPtr );
           return (double) byVal;
       }
@@ -346,7 +343,7 @@ double OGRDODSSequenceLayer::BaseTypeToDouble( BaseType *poBT )
       {
           GInt16 nIntVal;
           void *pValPtr = &nIntVal;
-              
+
           poBT->buf2val( &pValPtr );
           return (double) nIntVal;
       }
@@ -356,7 +353,7 @@ double OGRDODSSequenceLayer::BaseTypeToDouble( BaseType *poBT )
       {
           GUInt16 nIntVal;
           void *pValPtr = &nIntVal;
-              
+
           poBT->buf2val( &pValPtr );
           return (double) nIntVal;
       }
@@ -366,7 +363,7 @@ double OGRDODSSequenceLayer::BaseTypeToDouble( BaseType *poBT )
       {
           GInt32 nIntVal;
           void *pValPtr = &nIntVal;
-              
+
           poBT->buf2val( &pValPtr );
           return (double) nIntVal;
       }
@@ -376,7 +373,7 @@ double OGRDODSSequenceLayer::BaseTypeToDouble( BaseType *poBT )
       {
           GUInt32 nIntVal;
           void *pValPtr = &nIntVal;
-              
+
           poBT->buf2val( &pValPtr );
           return (double) nIntVal;
       }
@@ -460,8 +457,8 @@ OGRFeature *OGRDODSSequenceLayer::GetFeature( GIntBig nFeatureId )
         // for now we just scan through till find find out what
         // super sequence this in.  In the long term we need a better (cached)
         // approach that doesn't involve this quadratic cost.
-        for( iSuperSeq = 0; 
-             iSuperSeq < nSuperSeqCount; 
+        for( iSuperSeq = 0;
+             iSuperSeq < nSuperSeqCount;
              iSuperSeq++ )
         {
             if( nSeqOffset + panSubSeqSize[iSuperSeq] > nFeatureId )
@@ -474,8 +471,8 @@ OGRFeature *OGRDODSSequenceLayer::GetFeature( GIntBig nFeatureId )
 
         CPLAssert( iSubSeq != -1 );
 
-        // Make sure we have the right target var ... the one 
-        // corresponding to our current super sequence. 
+        // Make sure we have the right target var ... the one
+        // corresponding to our current super sequence.
         if( iSuperSeq != iLastSuperSeq )
         {
             iLastSuperSeq = iSuperSeq;
@@ -515,7 +512,7 @@ OGRFeature *OGRDODSSequenceLayer::GetFeature( GIntBig nFeatureId )
           {
               signed char byVal;
               void *pValPtr = &byVal;
-              
+
               poFieldVar->buf2val( &pValPtr );
               poFeature->SetField( iField, byVal );
           }
@@ -525,7 +522,7 @@ OGRFeature *OGRDODSSequenceLayer::GetFeature( GIntBig nFeatureId )
           {
               GInt16 nIntVal;
               void *pValPtr = &nIntVal;
-              
+
               poFieldVar->buf2val( &pValPtr );
               poFeature->SetField( iField, nIntVal );
           }
@@ -535,7 +532,7 @@ OGRFeature *OGRDODSSequenceLayer::GetFeature( GIntBig nFeatureId )
           {
               GUInt16 nIntVal;
               void *pValPtr = &nIntVal;
-              
+
               poFieldVar->buf2val( &pValPtr );
               poFeature->SetField( iField, nIntVal );
           }
@@ -545,7 +542,7 @@ OGRFeature *OGRDODSSequenceLayer::GetFeature( GIntBig nFeatureId )
           {
               GInt32 nIntVal;
               void *pValPtr = &nIntVal;
-              
+
               poFieldVar->buf2val( &pValPtr );
               poFeature->SetField( iField, nIntVal );
           }
@@ -555,19 +552,19 @@ OGRFeature *OGRDODSSequenceLayer::GetFeature( GIntBig nFeatureId )
           {
               GUInt32 nIntVal;
               void *pValPtr = &nIntVal;
-              
+
               poFieldVar->buf2val( &pValPtr );
               poFeature->SetField( iField, (int) nIntVal );
           }
           break;
 
           case dods_float32_c:
-            poFeature->SetField( iField, 
+            poFeature->SetField( iField,
                                  dynamic_cast<Float32 *>(poFieldVar)->value());
             break;
 
           case dods_float64_c:
-            poFeature->SetField( iField, 
+            poFeature->SetField( iField,
                                  dynamic_cast<Float64 *>(poFieldVar)->value());
             break;
 
@@ -585,7 +582,7 @@ OGRFeature *OGRDODSSequenceLayer::GetFeature( GIntBig nFeatureId )
             break;
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Handle data nested in sequences.                                */
 /* -------------------------------------------------------------------- */
@@ -597,11 +594,11 @@ OGRFeature *OGRDODSSequenceLayer::GetFeature( GIntBig nFeatureId )
         if( poFD->pszPathToSequence == NULL )
             continue;
 
-        CPLAssert( strlen(poFD->pszPathToSequence) 
+        CPLAssert( strlen(poFD->pszPathToSequence)
                    < strlen(poFD->pszFieldName)-1 );
 
         if( strstr(poFD->pszFieldName,poFD->pszPathToSequence) != NULL )
-            pszPathFromSubSeq = 
+            pszPathFromSubSeq =
                 strstr(poFD->pszFieldName,poFD->pszPathToSequence)
                 + strlen(poFD->pszPathToSequence) + 1;
         else
@@ -610,7 +607,7 @@ OGRFeature *OGRDODSSequenceLayer::GetFeature( GIntBig nFeatureId )
 /* -------------------------------------------------------------------- */
 /*      Get the sequence out of which this variable will be collected.  */
 /* -------------------------------------------------------------------- */
-        BaseType *poFieldVar = seq->var_value( iSubSeq, 
+        BaseType *poFieldVar = seq->var_value( iSubSeq,
                                                poFD->pszPathToSequence );
         Sequence *poSubSeq;
         int nSubSeqCount;
@@ -623,7 +620,7 @@ OGRFeature *OGRDODSSequenceLayer::GetFeature( GIntBig nFeatureId )
             continue;
 
         nSubSeqCount = poSubSeq->number_of_rows();
-            
+
 /* -------------------------------------------------------------------- */
 /*      Allocate array to put values into.                              */
 /* -------------------------------------------------------------------- */
@@ -664,37 +661,37 @@ OGRFeature *OGRDODSSequenceLayer::GetFeature( GIntBig nFeatureId )
               {
                   signed char byVal;
                   void *pValPtr = &byVal;
-                  
+
                   poFieldVar->buf2val( &pValPtr );
                   panIntList[iSubIndex] = byVal;
               }
               break;
-              
+
               case dods_int16_c:
               {
                   GInt16 nIntVal;
                   void *pValPtr = &nIntVal;
-                  
+
                   poFieldVar->buf2val( &pValPtr );
                   panIntList[iSubIndex] = nIntVal;
               }
               break;
-              
+
               case dods_uint16_c:
               {
                   GUInt16 nIntVal;
                   void *pValPtr = &nIntVal;
-                  
+
                   poFieldVar->buf2val( &pValPtr );
                   panIntList[iSubIndex] = nIntVal;
               }
               break;
-              
+
               case dods_int32_c:
               {
                   GInt32 nIntVal;
                   void *pValPtr = &nIntVal;
-                  
+
                   poFieldVar->buf2val( &pValPtr );
                   panIntList[iSubIndex] = nIntVal;
               }
@@ -704,19 +701,19 @@ OGRFeature *OGRDODSSequenceLayer::GetFeature( GIntBig nFeatureId )
               {
                   GUInt32 nIntVal;
                   void *pValPtr = &nIntVal;
-              
+
                   poFieldVar->buf2val( &pValPtr );
                   panIntList[iSubIndex] = nIntVal;
               }
               break;
 
               case dods_float32_c:
-                padfDblList[iSubIndex] = 
+                padfDblList[iSubIndex] =
                     dynamic_cast<Float32 *>(poFieldVar)->value();
                 break;
 
               case dods_float64_c:
-                padfDblList[iSubIndex] = 
+                padfDblList[iSubIndex] =
                     dynamic_cast<Float64 *>(poFieldVar)->value();
                 break;
 
@@ -754,7 +751,7 @@ OGRFeature *OGRDODSSequenceLayer::GetFeature( GIntBig nFeatureId )
             CSLDestroy( papszStrList );
         }
     }
-    
+
 /* ==================================================================== */
 /*      Fetch the geometry.                                             */
 /* ==================================================================== */
@@ -771,11 +768,11 @@ OGRFeature *OGRDODSSequenceLayer::GetFeature( GIntBig nFeatureId )
 /*      If we can't find the values in attributes then use the more     */
 /*      general mechanism to fetch the value.                           */
 /* -------------------------------------------------------------------- */
-        
-        if( iXField == -1 || iYField == -1 
+
+        if( iXField == -1 || iYField == -1
             || (oZField.bValid && iZField == -1) )
         {
-            poFeature->SetGeometryDirectly( 
+            poFeature->SetGeometryDirectly(
                 new OGRPoint( GetFieldValueAsDouble( &oXField, iSubSeq ),
                               GetFieldValueAsDouble( &oYField, iSubSeq ),
                               GetFieldValueAsDouble( &oZField, iSubSeq ) ) );
@@ -789,7 +786,7 @@ OGRFeature *OGRDODSSequenceLayer::GetFeature( GIntBig nFeatureId )
             const double *padfX, *padfY, *padfZ = NULL;
             int nPointCount, i;
             OGRLineString *poLS = new OGRLineString();
-            
+
             padfX = poFeature->GetFieldAsDoubleList( iXField, &nPointCount );
             padfY = poFeature->GetFieldAsDoubleList( iYField, &nPointCount );
             if( iZField != -1 )
@@ -798,7 +795,7 @@ OGRFeature *OGRDODSSequenceLayer::GetFeature( GIntBig nFeatureId )
             poLS->setPoints( nPointCount, (double *) padfX, (double *) padfY,
                              (double *) padfZ );
 
-            // Make a pass clearing out NaN or Inf values. 
+            // Make a pass clearing out NaN or Inf values.
             for( i = 0; i < nPointCount; i++ )
             {
                 double dfX = poLS->getX(i);
@@ -834,8 +831,8 @@ OGRFeature *OGRDODSSequenceLayer::GetFeature( GIntBig nFeatureId )
 /* -------------------------------------------------------------------- */
         else
         {
-            poFeature->SetGeometryDirectly( 
-                new OGRPoint( 
+            poFeature->SetGeometryDirectly(
+                new OGRPoint(
                     poFeature->GetFieldAsDouble( iXField ),
                     poFeature->GetFieldAsDouble( iYField ),
                     poFeature->GetFieldAsDouble( iZField ) ) );
@@ -876,7 +873,7 @@ int OGRDODSSequenceLayer::ProvideDataDDS()
         return bResult;
 
     // If we are in nested sequence mode, we now need to properly set
-    // the poTargetVar based on the current step in the supersequence. 
+    // the poTargetVar based on the current step in the supersequence.
     poSuperSeq = FindSuperSequence( poTargetVar );
 
 /* ==================================================================== */
@@ -902,12 +899,12 @@ int OGRDODSSequenceLayer::ProvideDataDDS()
         nRecordCount = 0;
         for( iSuper = 0; iSuper < nSuperSeqCount; iSuper++ )
         {
-            Sequence *poSubSeq = dynamic_cast<Sequence *>( 
+            Sequence *poSubSeq = dynamic_cast<Sequence *>(
                 poSuperSeq->var_value( iSuper, pszSubSeqPath ) );
 
             panSubSeqSize[iSuper] = poSubSeq->number_of_rows();
             nRecordCount += poSubSeq->number_of_rows();
-        }    
+        }
     }
 
     return poTargetVar != NULL;
@@ -930,7 +927,7 @@ The value V represented by the word may be determined as follows:
     * If 0<E<255 then V=(-1)**S * 2 ** (E-127) * (1.F) where "1.F" is intended to represent the binary number created by prefixing F with an implicit leading 1 and a binary point.
     * If E=0 and F is nonzero, then V=(-1)**S * 2 ** (-126) * (0.F) These are "unnormalized" values.
     * If E=0 and F is zero and S is 1, then V=-0
-    * If E=0 and F is zero and S is 0, then V=0 
+    * If E=0 and F is zero and S is 0, then V=0
 
 In particular,
 
@@ -948,9 +945,9 @@ In particular,
   1 10000001 10100000000000000000000 = -1 * 2**(129-127) * 1.101 = -6.5
 
   0 00000001 00000000000000000000000 = +1 * 2**(1-127) * 1.0 = 2**(-126)
-  0 00000000 10000000000000000000000 = +1 * 2**(-126) * 0.1 = 2**(-127) 
-  0 00000000 00000000000000000000001 = +1 * 2**(-126) * 
-                                       0.00000000000000000000001 = 
+  0 00000000 10000000000000000000000 = +1 * 2**(-126) * 0.1 = 2**(-127)
+  0 00000000 00000000000000000000001 = +1 * 2**(-126) *
+                                       0.00000000000000000000001 =
                                        2**(-149)  (Smallest positive value)
 
 Double Precision:
@@ -968,7 +965,7 @@ The value V represented by the word may be determined as follows:
     * If 0<E<2047 then V=(-1)**S * 2 ** (E-1023) * (1.F) where "1.F" is intended to represent the binary number created by prefixing F with an implicit leading 1 and a binary point.
     * If E=0 and F is nonzero, then V=(-1)**S * 2 ** (-1022) * (0.F) These are "unnormalized" values.
     * If E=0 and F is zero and S is 1, then V=-0
-    * If E=0 and F is zero and S is 0, then V=0 
+    * If E=0 and F is zero and S is 0, then V=0
 
 */
 
@@ -986,16 +983,16 @@ int OGRDODSIsFloatInvalid( const float * pfValToCheck )
     const unsigned char *pabyValToCheck = (unsigned char *) pfValToCheck;
 
 #if CPL_IS_LSB == 0
-    if( (pabyValToCheck[0] & 0x7f) == 0x7f 
+    if( (pabyValToCheck[0] & 0x7f) == 0x7f
         && (pabyValToCheck[1] & 0x80) == 0x80 )
         return TRUE;
-    else 
+    else
         return FALSE;
 #else
-    if( (pabyValToCheck[3] & 0x7f) == 0x7f 
+    if( (pabyValToCheck[3] & 0x7f) == 0x7f
         && (pabyValToCheck[2] & 0x80) == 0x80 )
         return TRUE;
-    else 
+    else
         return FALSE;
 #endif
 }
@@ -1013,17 +1010,17 @@ int OGRDODSIsDoubleInvalid( const double * pdfValToCheck )
 {
     const unsigned char *pabyValToCheck = (unsigned char *) pdfValToCheck;
 
-#if CPL_IS_LSB == 0 
-    if( (pabyValToCheck[0] & 0x7f) == 0x7f 
+#if CPL_IS_LSB == 0
+    if( (pabyValToCheck[0] & 0x7f) == 0x7f
         && (pabyValToCheck[1] & 0xf0) == 0xf0 )
         return TRUE;
-    else 
+    else
         return FALSE;
 #else
-    if( (pabyValToCheck[7] & 0x7f) == 0x7f 
+    if( (pabyValToCheck[7] & 0x7f) == 0x7f
         && (pabyValToCheck[6] & 0xf0) == 0xf0 )
         return TRUE;
-    else 
+    else
         return FALSE;
 #endif
 }
diff --git a/ogr/ogrsf_frmts/dwg/drv_dwg.html b/ogr/ogrsf_frmts/dwg/drv_dwg.html
index f64fb33..cb5fc0b 100644
--- a/ogr/ogrsf_frmts/dwg/drv_dwg.html
+++ b/ogr/ogrsf_frmts/dwg/drv_dwg.html
@@ -33,7 +33,7 @@ attributes.<p>
 
 The approximation of arcs, ellipses, circles and rounded polylines as
 linestrings is done by splitting the arcs into subarcs of no more than a
-threshhold angle.  This angle is the OGR_ARC_STEPSIZE.  This defaults to
+threshold angle.  This angle is the OGR_ARC_STEPSIZE.  This defaults to
 four degrees, but may be overridden by setting the configuration variable
 OGR_ARC_STEPSIZE.<p>
 
@@ -51,7 +51,7 @@ attributes, they will also have a BlockName attribute indicate what block
 they are part of.
 <li> The entities layer will have new attributes BlockName, BlockScale,
 and BlockAngle.
-<li> block referencesd will populate these new fields with the corresponding
+<li> block referenced will populate these new fields with the corresponding
 information (they are null for all other entities).
 <li> block references will not have block geometry inlined - instead they will
 have a point geometry for the insertion point.
diff --git a/ogr/ogrsf_frmts/dwg/ogr_dwg.h b/ogr/ogrsf_frmts/dwg/ogr_dwg.h
index 934db88..4dd3305 100644
--- a/ogr/ogrsf_frmts/dwg/ogr_dwg.h
+++ b/ogr/ogrsf_frmts/dwg/ogr_dwg.h
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_DWG_H_INCLUDED
-#define _OGR_DWG_H_INCLUDED
+#ifndef OGR_DWG_H_INCLUDED
+#define OGR_DWG_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "cpl_conv.h"
@@ -86,7 +86,7 @@ class OGRDWGBlocksLayer : public OGRLayer
     OGRDWGDataSource   *poDS;
 
     OGRFeatureDefn     *poFeatureDefn;
-    
+
     int                 iNextFID;
     unsigned int        iNextSubFeature;
 
@@ -122,8 +122,8 @@ class OGRDWGLayer : public OGRLayer
     void                ClearPendingFeatures();
 
     std::map<CPLString,CPLString> oStyleProperties;
-    
-    void                TranslateGenericProperties( OGRFeature *poFeature, 
+
+    void                TranslateGenericProperties( OGRFeature *poFeature,
                                                     OdDbEntityPtr poEntity );
     void                PrepareLineStyle( OGRFeature *poFeature );
 //    void                ApplyOCSTransformer( OGRGeometry * );
@@ -187,7 +187,7 @@ class OGRDWGDataSource : public OGRDataSource
     CPLString           osEncoding;
 
     // indexed by layer name, then by property name.
-    std::map< CPLString, std::map<CPLString,CPLString> > 
+    std::map< CPLString, std::map<CPLString,CPLString> >
                         oLayerTable;
 
     std::map<CPLString,CPLString> oLineTypeTable;
@@ -227,13 +227,13 @@ class OGRDWGDataSource : public OGRDataSource
     // Layer and other Table Handling (ogrdatasource.cpp)
     void                ReadLayerDefinitions();
     void                ReadLineTypeDefinitions();
-    const char         *LookupLayerProperty( const char *pszLayer, 
+    const char         *LookupLayerProperty( const char *pszLayer,
                                              const char *pszProperty );
     const char         *LookupLineType( const char *pszName );
 
-    // Header variables. 
+    // Header variables.
     void                ReadHeaderSection();
-    const char         *GetVariable(const char *pszName, 
+    const char         *GetVariable(const char *pszName,
                                     const char *pszDefault=NULL );
 
     const char         *GetEncoding() { return osEncoding; }
@@ -259,7 +259,7 @@ class OGRDWGDriver : public OGRSFDriver
 {
     int     bInitialized;
     void    Initialize();
-    
+
     OdStaticRxObject<OGRDWGServices> oServices;
 
     static void ErrorHandler( OdResult oRes );
@@ -276,4 +276,4 @@ class OGRDWGDriver : public OGRSFDriver
 };
 
 
-#endif /* ndef _OGR_DWG_H_INCLUDED */
+#endif /* ndef OGR_DWG_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/dwg/ogrdwg_blockmap.cpp b/ogr/ogrsf_frmts/dwg/ogrdwg_blockmap.cpp
index 0cebe23..3b7cf2c 100644
--- a/ogr/ogrsf_frmts/dwg/ogrdwg_blockmap.cpp
+++ b/ogr/ogrsf_frmts/dwg/ogrdwg_blockmap.cpp
@@ -2,7 +2,7 @@
  * $Id: ogrdwg_blockmap.cpp 22011 2011-03-22 20:13:38Z warmerdam $
  *
  * Project:  DWG Translator
- * Purpose:  Implements BlockMap reading and management portion of 
+ * Purpose:  Implements BlockMap reading and management portion of
  *           OGRDWGDataSource class
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -43,7 +43,7 @@ void OGRDWGDataSource::ReadBlocksSection()
 
 {
     OGRDWGLayer *poReaderLayer = (OGRDWGLayer *) GetLayerByName( "Entities" );
-    int bMergeBlockGeometries = CSLTestBoolean(
+    int bMergeBlockGeometries = CPLTestBool(
         CPLGetConfigOption( "DWG_MERGE_BLOCK_GEOMETRIES", "TRUE" ) );
 
 /* -------------------------------------------------------------------- */
@@ -53,7 +53,7 @@ void OGRDWGDataSource::ReadBlocksSection()
     OdDbBlockTableRecordPtr  poModelSpace, poBlock;
     OdDbBlockTablePtr pTable = GetDB()->getBlockTableId().safeOpenObject();
     OdDbSymbolTableIteratorPtr pBlkIter = pTable->newIterator();
-    
+
     for (pBlkIter->start(); ! pBlkIter->done(); pBlkIter->step())
     {
         poBlock = pBlkIter->getRecordId().safeOpenObject();
@@ -99,7 +99,7 @@ void OGRDWGDataSource::ReadBlocksSection()
             oBlockMap[osBlockName].apoFeatures = apoFeatures;
     }
 
-    CPLDebug( "DWG", "Read %d blocks with meaningful geometry.", 
+    CPLDebug( "DWG", "Read %d blocks with meaningful geometry.",
               (int) oBlockMap.size() );
 
     poReaderLayer->SetBlockTable( poModelSpace );
@@ -109,7 +109,7 @@ void OGRDWGDataSource::ReadBlocksSection()
 /*                       SimplifyBlockGeometry()                        */
 /************************************************************************/
 
-OGRGeometry *OGRDWGDataSource::SimplifyBlockGeometry( 
+OGRGeometry *OGRDWGDataSource::SimplifyBlockGeometry(
     OGRGeometryCollection *poCollection )
 
 {
@@ -130,7 +130,7 @@ OGRGeometry *OGRDWGDataSource::SimplifyBlockGeometry(
 /*      polygon, multipolygon, multilinestring or multipoint but        */
 /*      I'll put that off till it would be meaningful.                  */
 /* -------------------------------------------------------------------- */
-    
+
     return poCollection;
 }
 
diff --git a/ogr/ogrsf_frmts/dwg/ogrdwg_dimension.cpp b/ogr/ogrsf_frmts/dwg/ogrdwg_dimension.cpp
index eec2576..b5194ee 100644
--- a/ogr/ogrsf_frmts/dwg/ogrdwg_dimension.cpp
+++ b/ogr/ogrsf_frmts/dwg/ogrdwg_dimension.cpp
@@ -3,7 +3,7 @@
  *
  * Project:  DWG Translator
  * Purpose:  Implements translation support for DIMENSION elements as a part
- *           of the OGRDWGLayer class.  
+ *           of the OGRDWGLayer class.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -37,10 +37,6 @@
 
 CPL_CVSID("$Id: ogrdxf_dimension.cpp 19643 2010-05-08 21:56:18Z rouault $");
 
-#ifndef PI
-#define PI  3.14159265358979323846
-#endif 
-
 /************************************************************************/
 /*                         TranslateDIMENSION()                         */
 /************************************************************************/
@@ -70,7 +66,7 @@ OGRFeature *OGRDWGLayer::TranslateDIMENSION( OdDbEntityPtr poEntity )
     OdRxClass *poClass = poEntity->isA();
     const OdString osName = poClass->name();
     const char *pszEntityClassName = (const char *) osName;
-    
+
     if( EQUAL(pszEntityClassName,"AcDbRotatedDimension") )
     {
         OdDbRotatedDimensionPtr poRDim = OdDbDimension::cast( poEntity );
@@ -79,7 +75,7 @@ OGRFeature *OGRDWGLayer::TranslateDIMENSION( OdDbEntityPtr poEntity )
         oTarget1 = poRDim->xLine2Point();
         oArrow1 = poRDim->dimLinePoint();
     }
-    
+
     else if( EQUAL(pszEntityClassName,"AcDbAlignedDimension") )
     {
         OdDbAlignedDimensionPtr poADim = OdDbDimension::cast( poEntity );
@@ -91,7 +87,7 @@ OGRFeature *OGRDWGLayer::TranslateDIMENSION( OdDbEntityPtr poEntity )
 
 /*************************************************************************
 
-   DIMENSION geometry layout 
+   DIMENSION geometry layout
 
                   (11,21)(text center point)
         |          DimText                  |
@@ -102,17 +98,16 @@ OGRFeature *OGRDWGLayer::TranslateDIMENSION( OdDbEntityPtr poEntity )
         |
         X (14,24) (Target1)
 
-
 Given:
   Locations Arrow1, Target1, and Target2 we need to compute Arrow2.
- 
+
 Steps:
  1) Compute direction vector from Target1 to Arrow1 (Vec1).
  2) Compute direction vector for arrow as perpendicular to Vec1 (call Vec2).
- 3) Compute Arrow2 location as intersection between line defined by 
+ 3) Compute Arrow2 location as intersection between line defined by
     Vec2 and Arrow1 and line defined by Target2 and direction Vec1 (call Arrow2)
 
-Then we can draw lines for the various components.  
+Then we can draw lines for the various components.
 
 Note that Vec1 and Vec2 may be horizontal, vertical or on an angle but
 the approach is as above in all these cases.
@@ -126,13 +121,13 @@ the approach is as above in all these cases.
 
     dfVec1X = (oArrow1.x - oTarget1.x);
     dfVec1Y = (oArrow1.y - oTarget1.y);
-    
+
 /* -------------------------------------------------------------------- */
 /*      Step 2, compute the direction vector from Arrow1 to Arrow2      */
-/*      as a perpendicluar to Vec1.                                     */
+/*      as a perpendicular to Vec1.                                     */
 /* -------------------------------------------------------------------- */
     double dfVec2X, dfVec2Y;
-    
+
     dfVec2X = dfVec1Y;
     dfVec2Y = -dfVec1X;
 
@@ -143,7 +138,7 @@ the approach is as above in all these cases.
 /* -------------------------------------------------------------------- */
     double dfL1M, dfL1B, dfL2M, dfL2B;
     double dfArrowX2, dfArrowY2;
-    
+
     // special case if vec1 is vertical.
     if( dfVec1X == 0.0 )
     {
@@ -166,12 +161,12 @@ the approach is as above in all these cases.
         dfL1B = oTarget2.y - dfL1M * oTarget2.x;
 
         // convert vec2 + Arrow1 into y = mx + b format, call this L2
-        
+
         dfL2M = dfVec2Y / dfVec2X;
         dfL2B = oArrow1.y - dfL2M * oArrow1.x;
-        
+
         // Compute intersection x = (b2-b1) / (m1-m2)
-        
+
         dfArrowX2 = (dfL2B - dfL1B) / (dfL1M-dfL2M);
         dfArrowY2 = dfL2M * dfArrowX2 + dfL2B;
     }
@@ -181,7 +176,7 @@ the approach is as above in all these cases.
 /* -------------------------------------------------------------------- */
     double dfAngle = 0.0;
 
-    dfAngle = atan2(dfVec2Y,dfVec2X) * 180.0 / PI;
+    dfAngle = atan2(dfVec2Y,dfVec2X) * 180.0 / M_PI;
 
 /* -------------------------------------------------------------------- */
 /*      Rescale the direction vectors so we can use them in             */
@@ -204,7 +199,7 @@ the approach is as above in all these cases.
     dfScaleFactor = dfTargetLength / VECTOR_LEN(dfVec1X,dfVec1Y);
     dfVec1X *= dfScaleFactor;
     dfVec1Y *= dfScaleFactor;
-    
+
     // vector 2
     dfScaleFactor = dfTargetLength / VECTOR_LEN(dfVec2X,dfVec2Y);
     dfVec2X *= dfScaleFactor;
@@ -226,7 +221,7 @@ the approach is as above in all these cases.
     oLine.setPoint( 0, oTarget1.x, oTarget1.y );
     oLine.setPoint( 1, oArrow1.x + dfVec1X, oArrow1.y + dfVec1Y );
     poMLS->addGeometry( &oLine );
-    
+
     // dimension line from Target2 to Arrow2 with a small extension.
     oLine.setPoint( 0, oTarget2.x, oTarget2.y );
     oLine.setPoint( 1, dfArrowX2 + dfVec1X, dfArrowY2 + dfVec1Y );
@@ -235,13 +230,13 @@ the approach is as above in all these cases.
     // add arrow1 arrow head.
 
     oLine.setPoint( 0, oArrow1.x, oArrow1.y );
-    oLine.setPoint( 1, 
+    oLine.setPoint( 1,
                     oArrow1.x + dfVec2X*3 + dfVec1X,
                     oArrow1.y + dfVec2Y*3 + dfVec1Y );
     poMLS->addGeometry( &oLine );
 
     oLine.setPoint( 0, oArrow1.x, oArrow1.y );
-    oLine.setPoint( 1, 
+    oLine.setPoint( 1,
                     oArrow1.x + dfVec2X*3 - dfVec1X,
                     oArrow1.y + dfVec2Y*3 - dfVec1Y );
     poMLS->addGeometry( &oLine );
@@ -249,13 +244,13 @@ the approach is as above in all these cases.
     // add arrow2 arrow head.
 
     oLine.setPoint( 0, dfArrowX2, dfArrowY2 );
-    oLine.setPoint( 1, 
+    oLine.setPoint( 1,
                     dfArrowX2 - dfVec2X*3 + dfVec1X,
                     dfArrowY2 - dfVec2Y*3 + dfVec1Y );
     poMLS->addGeometry( &oLine );
 
     oLine.setPoint( 0, dfArrowX2, dfArrowY2 );
-    oLine.setPoint( 1, 
+    oLine.setPoint( 1,
                     dfArrowX2 - dfVec2X*3 - dfVec1X,
                     dfArrowY2 - dfVec2Y*3 - dfVec1Y );
     poMLS->addGeometry( &oLine );
@@ -269,7 +264,7 @@ the approach is as above in all these cases.
 /* -------------------------------------------------------------------- */
     CPLString osLayer = poFeature->GetFieldAsString("Layer");
 
-    int bHidden = 
+    int bHidden =
         EQUAL(poDS->LookupLayerProperty( osLayer, "Hidden" ), "1");
 
 /* -------------------------------------------------------------------- */
@@ -280,14 +275,14 @@ the approach is as above in all these cases.
     if( oStyleProperties.count("Color") > 0 )
         nColor = atoi(oStyleProperties["Color"]);
 
-    // Use layer color? 
+    // Use layer color?
     if( nColor < 1 || nColor > 255 )
     {
         const char *pszValue = poDS->LookupLayerProperty( osLayer, "Color" );
         if( pszValue != NULL )
             nColor = atoi(pszValue);
     }
-        
+
     if( nColor < 1 || nColor > 255 )
         nColor = 8;
 
@@ -308,7 +303,7 @@ the approach is as above in all these cases.
     // Do we need to compute the dimension value?
     if( osText.size() == 0 )
     {
-        FormatDimension( osText, POINT_DIST( oArrow1.x, oArrow1.y, 
+        FormatDimension( osText, POINT_DIST( oArrow1.x, oArrow1.y,
                                              dfArrowX2, dfArrowY2 ) );
     }
 
@@ -338,14 +333,14 @@ the approach is as above in all these cases.
 
     const unsigned char *pabyDWGColors = ACGetColorTable();
 
-    snprintf( szBuffer, sizeof(szBuffer), ",c:#%02x%02x%02x", 
+    snprintf( szBuffer, sizeof(szBuffer), ",c:#%02x%02x%02x",
               pabyDWGColors[nColor*3+0],
               pabyDWGColors[nColor*3+1],
               pabyDWGColors[nColor*3+2] );
     osStyle += szBuffer;
 
     if( bHidden )
-        osStyle += "00"; 
+        osStyle += "00";
 
     osStyle += ")";
 
@@ -372,7 +367,7 @@ void OGRDWGLayer::FormatDimension( CPLString &osText, double dfValue )
 
     // we could do a significantly more precise formatting if we want
     // to spend the effort.  See QCAD's rs_dimlinear.cpp and related files
-    // for example.  
+    // for example.
 
     sprintf(szFormat, "%%.%df", nPrecision );
     CPLsnprintf(szBuffer, sizeof(szBuffer), szFormat, dfValue);
diff --git a/ogr/ogrsf_frmts/dwg/ogrdwg_hatch.cpp b/ogr/ogrsf_frmts/dwg/ogrdwg_hatch.cpp
index 5ca9853..cf346f8 100644
--- a/ogr/ogrsf_frmts/dwg/ogrdwg_hatch.cpp
+++ b/ogr/ogrsf_frmts/dwg/ogrdwg_hatch.cpp
@@ -1,9 +1,9 @@
 /******************************************************************************
- * $Id: ogrdwg_hatch.cpp 26672 2013-11-28 13:10:36Z rouault $
+ * $Id: ogrdwg_hatch.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  DWG Translator
  * Purpose:  Implements translation support for HATCH elements as part
- *           of the OGRDWGLayer class.  
+ *           of the OGRDWGLayer class.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -41,11 +41,8 @@
 #include "Ge/GeCircArc2d.h"
 #include "Ge/GeEllipArc2d.h"
 
-CPL_CVSID("$Id: ogrdwg_hatch.cpp 26672 2013-11-28 13:10:36Z rouault $");
+CPL_CVSID("$Id: ogrdwg_hatch.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
-#ifndef PI
-#define PI  3.14159265358979323846
-#endif 
 
 static OGRErr DWGCollectBoundaryLoop( OdDbHatchPtr poHatch, int iLoop,
                                       OGRGeometryCollection *poGC );
@@ -67,7 +64,7 @@ OGRFeature *OGRDWGLayer::TranslateHATCH( OdDbEntityPtr poEntity )
 
     TranslateGenericProperties( poFeature, poEntity );
 
-    poFeature->SetField( "Text", 
+    poFeature->SetField( "Text",
                          (const char *) poHatch->patternName() );
 
 /* -------------------------------------------------------------------- */
@@ -83,7 +80,7 @@ OGRFeature *OGRDWGLayer::TranslateHATCH( OdDbEntityPtr poEntity )
 /* -------------------------------------------------------------------- */
     OGRErr eErr;
 
-    OGRGeometryH hFinalGeom = 
+    OGRGeometryH hFinalGeom =
         OGRBuildPolygonFromEdges( (OGRGeometryH) &oGC,
                                   TRUE, TRUE, 0.0000001, &eErr );
 
@@ -101,14 +98,14 @@ OGRFeature *OGRDWGLayer::TranslateHATCH( OdDbEntityPtr poEntity )
     if( oStyleProperties.count("Color") > 0 )
         nColor = atoi(oStyleProperties["Color"]);
 
-    // Use layer color? 
+    // Use layer color?
     if( nColor < 1 || nColor > 255 )
     {
         const char *pszValue = poDS->LookupLayerProperty( osLayer, "Color" );
         if( pszValue != NULL )
             nColor = atoi(pszValue);
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Setup the style string.                                         */
 /* -------------------------------------------------------------------- */
@@ -116,12 +113,12 @@ OGRFeature *OGRDWGLayer::TranslateHATCH( OdDbEntityPtr poEntity )
     {
         CPLString osStyle;
         const unsigned char *pabyDWGColors = ACGetColorTable();
-        
+
         osStyle.Printf( "BRUSH(fc:#%02x%02x%02x)",
                         pabyDWGColors[nColor*3+0],
                         pabyDWGColors[nColor*3+1],
                         pabyDWGColors[nColor*3+2] );
-        
+
         poFeature->SetStyleString( osStyle );
     }
 
@@ -152,10 +149,10 @@ static OGRErr DWGCollectBoundaryLoop( OdDbHatchPtr poHatch, int iLoop,
         for (i = 0; i < (int) vertices.size(); i++)
         {
             if( i >= (int) bulges.size() )
-                oSmoothPolyline.AddPoint( vertices[i].x, vertices[i].y, 0.0, 
+                oSmoothPolyline.AddPoint( vertices[i].x, vertices[i].y, 0.0,
                                           0.0 );
             else
-                oSmoothPolyline.AddPoint( vertices[i].x, vertices[i].y, 0.0, 
+                oSmoothPolyline.AddPoint( vertices[i].x, vertices[i].y, 0.0,
                                           bulges[i] );
         }
 
@@ -191,9 +188,9 @@ static OGRErr DWGCollectBoundaryLoop( OdDbHatchPtr poHatch, int iLoop,
         {
             OdGeCircArc2d* poCircArc = (OdGeCircArc2d*) poEdge;
             OdGePoint2d oCenter = poCircArc->center();
-            double dfStartAngle = poCircArc->startAng() * 180 / PI;
-            double dfEndAngle = poCircArc->endAng() * 180 / PI;
-            
+            double dfStartAngle = poCircArc->startAng() * 180 / M_PI;
+            double dfEndAngle = poCircArc->endAng() * 180 / M_PI;
+
             if( !poCircArc->isClockWise() )
             {
                 dfStartAngle *= -1;
@@ -204,8 +201,8 @@ static OGRErr DWGCollectBoundaryLoop( OdDbHatchPtr poHatch, int iLoop,
                 dfEndAngle += 360.0;
             }
 
-            OGRLineString *poLS = (OGRLineString *) 
-                OGRGeometryFactory::approximateArcAngles( 
+            OGRLineString *poLS = (OGRLineString *)
+                OGRGeometryFactory::approximateArcAngles(
                     oCenter.x, oCenter.y, 0.0,
                     poCircArc->radius(), poCircArc->radius(), 0.0,
                     dfStartAngle, dfEndAngle, 0.0 );
@@ -221,11 +218,11 @@ static OGRErr DWGCollectBoundaryLoop( OdDbHatchPtr poHatch, int iLoop,
             double dfRotation;
             double dfStartAng, dfEndAng;
 
-            dfRotation = -1 * atan2( oMajorAxis.y, oMajorAxis.x ) * 180 / PI;
+            dfRotation = -1 * atan2( oMajorAxis.y, oMajorAxis.x ) * 180 / M_PI;
+
+            dfStartAng = poArc->startAng()*180/M_PI;
+            dfEndAng = poArc->endAng()*180/M_PI;
 
-            dfStartAng = poArc->startAng()*180/PI;
-            dfEndAng = poArc->endAng()*180/PI;
- 
             if( !poArc->isClockWise() )
             {
                 dfStartAng *= -1;
@@ -236,8 +233,8 @@ static OGRErr DWGCollectBoundaryLoop( OdDbHatchPtr poHatch, int iLoop,
                 dfEndAng += 360.0;
             }
 
-            OGRLineString *poLS = (OGRLineString *) 
-                OGRGeometryFactory::approximateArcAngles( 
+            OGRLineString *poLS = (OGRLineString *)
+                OGRGeometryFactory::approximateArcAngles(
                     oCenter.x, oCenter.y, 0.0,
                     poArc->majorRadius(), poArc->minorRadius(), dfRotation,
                     OGRDWGLayer::AngleCorrect(dfStartAng,dfRatio),
@@ -249,9 +246,8 @@ static OGRErr DWGCollectBoundaryLoop( OdDbHatchPtr poHatch, int iLoop,
             CPLDebug( "DWG", "Unsupported edge type (%d) in hatch loop.",
                       (int) poEdge->type() );
 
-        //case OdGe::kNurbCurve2d : dumpNurbCurveEdge(indent + 1, pEdge);    
+        //case OdGe::kNurbCurve2d : dumpNurbCurveEdge(indent + 1, pEdge);
     }
 
     return OGRERR_NONE;
 }
-
diff --git a/ogr/ogrsf_frmts/dwg/ogrdwgblockslayer.cpp b/ogr/ogrsf_frmts/dwg/ogrdwgblockslayer.cpp
index 8911732..288f0b3 100644
--- a/ogr/ogrsf_frmts/dwg/ogrdwgblockslayer.cpp
+++ b/ogr/ogrsf_frmts/dwg/ogrdwgblockslayer.cpp
@@ -36,14 +36,12 @@ CPL_CVSID("$Id: ogrdwglayer.cpp 19643 2010-05-08 21:56:18Z rouault $");
 /*                         OGRDWGBlocksLayer()                          */
 /************************************************************************/
 
-OGRDWGBlocksLayer::OGRDWGBlocksLayer( OGRDWGDataSource *poDS )
-
+OGRDWGBlocksLayer::OGRDWGBlocksLayer( OGRDWGDataSource *poDSIn ) :
+    poDS(poDSIn),
+    poFeatureDefn(new OGRFeatureDefn( "blocks" )),
 {
-    this->poDS = poDS;
-
     ResetReading();
 
-    poFeatureDefn = new OGRFeatureDefn( "blocks" );
     poFeatureDefn->Reference();
 
     poDS->AddStandardFields( poFeatureDefn );
@@ -59,7 +57,7 @@ OGRDWGBlocksLayer::~OGRDWGBlocksLayer()
     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     {
         CPLDebug( "DWG", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
+                  (int) m_nFeaturesRead,
                   poFeatureDefn->GetName() );
     }
 
@@ -114,7 +112,7 @@ OGRFeature *OGRDWGBlocksLayer::GetNextUnfilteredFeature()
 
         psBlock = &(oIt->second);
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Is this a geometry based block?                                 */
 /* -------------------------------------------------------------------- */
@@ -155,7 +153,7 @@ OGRFeature *OGRDWGBlocksLayer::GetNextUnfilteredFeature()
 OGRFeature *OGRDWGBlocksLayer::GetNextFeature()
 
 {
-    while( TRUE )
+    while( true )
     {
         OGRFeature *poFeature = GetNextUnfilteredFeature();
 
@@ -186,4 +184,3 @@ int OGRDWGBlocksLayer::TestCapability( const char * pszCap )
     else
         return FALSE;
 }
-
diff --git a/ogr/ogrsf_frmts/dwg/ogrdwgdatasource.cpp b/ogr/ogrsf_frmts/dwg/ogrdwgdatasource.cpp
index 5ef139e..dd2abae 100644
--- a/ogr/ogrsf_frmts/dwg/ogrdwgdatasource.cpp
+++ b/ogr/ogrsf_frmts/dwg/ogrdwgdatasource.cpp
@@ -43,7 +43,8 @@ CPL_CVSID("$Id: ogrdxfdatasource.cpp 22009 2011-03-22 20:01:34Z warmerdam $");
 /*                          OGRDWGDataSource()                          */
 /************************************************************************/
 
-OGRDWGDataSource::OGRDWGDataSource()
+OGRDWGDataSource::OGRDWGDataSource() :
+  fp(NULL)
 
 {
     poDb = NULL;
@@ -107,27 +108,27 @@ int OGRDWGDataSource::Open( OGRDWGServices *poServices,
 
     osName = pszFilename;
 
-    bInlineBlocks = CSLTestBoolean(
+    bInlineBlocks = CPLTestBool(
         CPLGetConfigOption( "DWG_INLINE_BLOCKS", "TRUE" ) );
 
 /* -------------------------------------------------------------------- */
 /*      Open the file.                                                  */
 /* -------------------------------------------------------------------- */
-    try 
+    try
     {
         OdString f(pszFilename);
-        poDb = poServices->readFile(f.c_str(), true, false, Oda::kShareDenyNo); 
+        poDb = poServices->readFile(f.c_str(), true, false, Oda::kShareDenyNo);
     }
     catch( OdError& e )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "%s",
                   (const char *) poServices->getErrorDescription(e.code()) );
     }
     catch( ... )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "DWG readFile(%s) failed with generic exception.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "DWG readFile(%s) failed with generic exception.",
                   pszFilename );
     }
 
@@ -176,16 +177,16 @@ void OGRDWGDataSource::ReadLayerDefinitions()
         std::map<CPLString,CPLString> oLayerProperties;
 
         CPLString osLayerName = ACTextUnescape(poLD->getName(),GetEncoding());
-        
+
         oLayerProperties["Exists"] = "1";
-        
+
         OdDbLinetypeTableRecordPtr poLT = poLD->linetypeObjectId().safeOpenObject();
-        oLayerProperties["Linetype"] = 
+        oLayerProperties["Linetype"] =
             ACTextUnescape(poLT->getName(),GetEncoding());
 
         osValue.Printf( "%d", poLD->colorIndex() );
         oLayerProperties["Color"] = osValue;
-            
+
         osValue.Printf( "%d", (int) poLD->lineWeight() );
         oLayerProperties["LineWeight"] = osValue;
 
@@ -197,7 +198,7 @@ void OGRDWGDataSource::ReadLayerDefinitions()
         oLayerTable[osLayerName] = oLayerProperties;
     }
 
-    CPLDebug( "DWG", "Read %d layer definitions.", 
+    CPLDebug( "DWG", "Read %d layer definitions.",
               (int) oLayerTable.size() );
 }
 
@@ -228,7 +229,7 @@ void OGRDWGDataSource::ReadLineTypeDefinitions()
 {
     OdDbLinetypeTablePtr poTable = poDb->getLinetypeTableId().safeOpenObject();
     OdDbSymbolTableIteratorPtr poIter = poTable->newIterator();
-    
+
     for (poIter->start(); !poIter->done(); poIter->step())
     {
         CPLString osLineTypeName;
@@ -237,9 +238,9 @@ void OGRDWGDataSource::ReadLineTypeDefinitions()
 
         osLineTypeName = ACTextUnescape(poLT->getName(),GetEncoding());
 
-        if (poLT->numDashes()) 
+        if (poLT->numDashes())
         {
-            for (int i=0; i < poLT->numDashes(); i++) 
+            for (int i=0; i < poLT->numDashes(); i++)
             {
                 if( i > 0 )
                     osLineTypeDef += " ";
@@ -253,7 +254,7 @@ void OGRDWGDataSource::ReadLineTypeDefinitions()
 
             oLineTypeTable[osLineTypeName] = osLineTypeDef;
             CPLDebug( "DWG", "LineType '%s' = '%s'",
-                       osLineTypeName.c_str(), 
+                       osLineTypeName.c_str(),
                        osLineTypeDef.c_str() );
         }
     }
@@ -289,7 +290,7 @@ void OGRDWGDataSource::ReadHeaderSection()
     osValue.Printf( "%g", poDb->dimtxt() );
     oHeaderVariables["$DIMTXT"] = osValue;
 
-    CPLDebug( "DWG", "Read %d header variables.", 
+    CPLDebug( "DWG", "Read %d header variables.",
               (int) oHeaderVariables.size() );
 
 /* -------------------------------------------------------------------- */
@@ -300,23 +301,23 @@ void OGRDWGDataSource::ReadHeaderSection()
 
     // not strictly accurate but works even without iconv.
     if( osCodepage == "ANSI_1252" )
-        osEncoding = CPL_ENC_ISO8859_1; 
-    else if( EQUALN(osCodepage,"ANSI_",5) )
+        osEncoding = CPL_ENC_ISO8859_1;
+    else if( STARTS_WITH_CI(osCodepage, "ANSI_") )
     {
         osEncoding = "CP";
         osEncoding += osCodepage + 5;
     }
     else
     {
-        // fallback to the default 
+        // fallback to the default
         osEncoding = CPL_ENC_ISO8859_1;
     }
-                                       
+
     if( CPLGetConfigOption( "DWG_ENCODING", NULL ) != NULL )
         osEncoding = CPLGetConfigOption( "DWG_ENCODING", NULL );
 
     if( osEncoding != CPL_ENC_ISO8859_1 )
-        CPLDebug( "DWG", "Treating DWG as encoding '%s', $DWGCODEPAGE='%s'", 
+        CPLDebug( "DWG", "Treating DWG as encoding '%s', $DWGCODEPAGE='%s'",
                   osEncoding.c_str(), osCodepage.c_str() );
 }
 
@@ -326,13 +327,13 @@ void OGRDWGDataSource::ReadHeaderSection()
 /*      Fetch a variable that came from the HEADER section.             */
 /************************************************************************/
 
-const char *OGRDWGDataSource::GetVariable( const char *pszName, 
+const char *OGRDWGDataSource::GetVariable( const char *pszName,
                                            const char *pszDefault )
 
 {
     if( oHeaderVariables.count(pszName) == 0 )
         return pszDefault;
-    else 
+    else
         return oHeaderVariables[pszName];
 }
 
diff --git a/ogr/ogrsf_frmts/dwg/ogrdwgdriver.cpp b/ogr/ogrsf_frmts/dwg/ogrdwgdriver.cpp
index 8650d80..7bcbdc2 100644
--- a/ogr/ogrsf_frmts/dwg/ogrdwgdriver.cpp
+++ b/ogr/ogrsf_frmts/dwg/ogrdwgdriver.cpp
@@ -53,7 +53,7 @@ OGRDWGDriver::OGRDWGDriver()
 OGRDWGDriver::~OGRDWGDriver()
 
 {
-    if( bInitialized && !CSLTestBoolean(
+    if( bInitialized && !CPLTestBool(
             CPLGetConfigOption("IN_GDAL_GLOBAL_DESTRUCTOR", "NO")) )
     {
         bInitialized = FALSE;
@@ -72,7 +72,7 @@ void OGRDWGDriver::Initialize()
         return;
 
     bInitialized = TRUE;
-    
+
     OdGeContext::gErrorFunc = ErrorHandler;
 
     odInitialize(&oServices);
@@ -95,7 +95,7 @@ void OGRDWGDriver::ErrorHandler( OdResult oResult )
 
 {
     CPLError( CE_Failure, CPLE_AppDefined,
-              "GeError:%s", 
+              "GeError:%s",
               (const char *) OdError(oResult).description().c_str() );
 }
 
@@ -117,7 +117,7 @@ OGRDataSource *OGRDWGDriver::Open( const char * pszFilename, int bUpdate )
 
 {
     Initialize();
-    
+
     OGRDWGDataSource   *poDS = new OGRDWGDataSource();
 
     if( !poDS->Open( &oServices, pszFilename ) )
@@ -154,4 +154,3 @@ void RegisterOGRDWG()
                                 "drv_dwg.html" );
     OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( poDriver );
 }
-
diff --git a/ogr/ogrsf_frmts/dwg/ogrdwglayer.cpp b/ogr/ogrsf_frmts/dwg/ogrdwglayer.cpp
index 00c3741..8ca42b1 100644
--- a/ogr/ogrsf_frmts/dwg/ogrdwglayer.cpp
+++ b/ogr/ogrsf_frmts/dwg/ogrdwglayer.cpp
@@ -51,10 +51,6 @@
 
 CPL_CVSID("$Id: ogrdwglayer.cpp 22008 2011-03-22 19:45:20Z warmerdam $");
 
-#ifndef PI
-#define PI  3.14159265358979323846
-#endif 
-
 /************************************************************************/
 /*                            OGRDWGLayer()                             */
 /************************************************************************/
@@ -87,7 +83,7 @@ OGRDWGLayer::OGRDWGLayer( OGRDWGDataSource *poDS )
 /* -------------------------------------------------------------------- */
     OdDbBlockTablePtr pTable = poDS->GetDB()->getBlockTableId().safeOpenObject();
     OdDbSymbolTableIteratorPtr pBlkIter = pTable->newIterator();
-    
+
     for (pBlkIter->start(); ! pBlkIter->done(); pBlkIter->step())
     {
         poBlock = pBlkIter->getRecordId().safeOpenObject();
@@ -112,7 +108,7 @@ OGRDWGLayer::~OGRDWGLayer()
     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     {
         CPLDebug( "DWG", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
+                  (int) m_nFeaturesRead,
                   poFeatureDefn->GetName() );
     }
 
@@ -126,7 +122,7 @@ OGRDWGLayer::~OGRDWGLayer()
 
 CPLString OGRDWGLayer::TextUnescape( OdString oString )
 
-{ 
+{
     return ACTextUnescape( (const char *) oString, poDS->GetEncoding() );
 }
 
@@ -182,7 +178,7 @@ void OGRDWGLayer::ResetReading()
 /*      or all entity types                                             */
 /************************************************************************/
 
-void OGRDWGLayer::TranslateGenericProperties( OGRFeature *poFeature, 
+void OGRDWGLayer::TranslateGenericProperties( OGRFeature *poFeature,
                                               OdDbEntityPtr poEntity )
 
 {
@@ -196,7 +192,7 @@ void OGRDWGLayer::TranslateGenericProperties( OGRFeature *poFeature,
     OdDbHandle oHandle = poEntity->getDbHandle();
     poFeature->SetField( "EntityHandle", (const char *) oHandle.ascii() );
 
-    
+
     if( poEntity->colorIndex() != 256 )
     {
         osValue.Printf( "%d", poEntity->colorIndex() );
@@ -213,14 +209,14 @@ void OGRDWGLayer::TranslateGenericProperties( OGRFeature *poFeature,
     {
         if( osSubClasses.size() > 0 )
             osSubClasses = ":" + osSubClasses;
-        
+
         osSubClasses = ((const char *) poClass->name()) + osSubClasses;
         if( EQUAL(poClass->name(),"AcDbEntity") )
             break;
 
         poClass = poClass->myParent();
     }
-    
+
     poFeature->SetField( "SubClasses", osSubClasses.c_str() );
 
 /* -------------------------------------------------------------------- */
@@ -233,7 +229,7 @@ void OGRDWGLayer::TranslateGenericProperties( OGRFeature *poFeature,
     for ( ; poResBuf != NULL; poResBuf = poResBuf->next() )
     {
         CPLString osXDataItem;
-    
+
         switch (OdDxfCode::_getType(poResBuf->restype()))
         {
           case OdDxfCode::Name:
@@ -248,31 +244,31 @@ void OGRDWGLayer::TranslateGenericProperties( OGRFeature *poFeature,
             else
                 osXDataItem = "false";
             break;
-            
+
           case OdDxfCode::Integer8:
             osXDataItem.Printf( "%d", (int) poResBuf->getInt8() );
             break;
-            
+
           case OdDxfCode::Integer16:
             osXDataItem.Printf( "%d", (int) poResBuf->getInt16() );
             break;
-            
+
           case OdDxfCode::Integer32:
             osXDataItem.Printf( "%d", (int) poResBuf->getInt32() );
             break;
-            
+
           case OdDxfCode::Double:
           case OdDxfCode::Angle:
             osXDataItem.Printf( "%g", poResBuf->getDouble() );
             break;
-            
+
           case OdDxfCode::Point:
           {
               OdGePoint3d oPoint = poResBuf->getPoint3d();
               osXDataItem.Printf( "(%g,%g,%g)", oPoint.x, oPoint.y, oPoint.z );
           }
           break;
-          
+
           case OdDxfCode::BinaryChunk:
           {
               OdBinaryData oBinData = poResBuf->getBinaryChunk();
@@ -282,7 +278,7 @@ void OGRDWGLayer::TranslateGenericProperties( OGRFeature *poFeature,
               CPLFree( pszAsHex );
           }
           break;
-            
+
           case OdDxfCode::ObjectId:
           case OdDxfCode::SoftPointerId:
           case OdDxfCode::HardPointerId:
@@ -291,7 +287,7 @@ void OGRDWGLayer::TranslateGenericProperties( OGRFeature *poFeature,
           case OdDxfCode::Handle:
             osXDataItem = (const char *) poResBuf->getHandle().ascii();
             break;
-            
+
           default:
             break;
         }
@@ -300,7 +296,7 @@ void OGRDWGLayer::TranslateGenericProperties( OGRFeature *poFeature,
             osFullXData += " ";
         osFullXData += (const char *) osXDataItem;
     }
-    
+
     poFeature->SetField( "ExtendedEntity", osFullXData );
 
 
@@ -309,11 +305,11 @@ void OGRDWGLayer::TranslateGenericProperties( OGRFeature *poFeature,
       case 210:
         oStyleProperties["210_N.dX"] = pszValue;
         break;
-        
+
       case 220:
         oStyleProperties["220_N.dY"] = pszValue;
         break;
-        
+
       case 230:
         oStyleProperties["230_N.dZ"] = pszValue;
         break;
@@ -337,7 +333,7 @@ void OGRDWGLayer::PrepareLineStyle( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
 /*      Is the layer disabled/hidden/frozen/off?                        */
 /* -------------------------------------------------------------------- */
-    int bHidden = 
+    int bHidden =
         EQUAL(poDS->LookupLayerProperty( osLayer, "Hidden" ), "1");
 
 /* -------------------------------------------------------------------- */
@@ -348,14 +344,14 @@ void OGRDWGLayer::PrepareLineStyle( OGRFeature *poFeature )
     if( oStyleProperties.count("Color") > 0 )
         nColor = atoi(oStyleProperties["Color"]);
 
-    // Use layer color? 
+    // Use layer color?
     if( nColor < 1 || nColor > 255 )
     {
         const char *pszValue = poDS->LookupLayerProperty( osLayer, "Color" );
         if( pszValue != NULL )
             nColor = atoi(pszValue);
     }
-        
+
     if( nColor < 1 || nColor > 255 )
         return;
 
@@ -386,13 +382,13 @@ void OGRDWGLayer::PrepareLineStyle( OGRFeature *poFeature )
     CPLString osStyle;
     const unsigned char *pabyDWGColors = ACGetColorTable();
 
-    osStyle.Printf( "PEN(c:#%02x%02x%02x", 
+    osStyle.Printf( "PEN(c:#%02x%02x%02x",
                     pabyDWGColors[nColor*3+0],
                     pabyDWGColors[nColor*3+1],
                     pabyDWGColors[nColor*3+2] );
 
     if( bHidden )
-        osStyle += "00"; 
+        osStyle += "00";
 
     if( dfWeight > 0.0 )
     {
@@ -412,7 +408,7 @@ void OGRDWGLayer::PrepareLineStyle( OGRFeature *poFeature )
     }
 
     osStyle += ")";
-    
+
     poFeature->SetStyleString( osStyle );
 }
 
@@ -433,7 +429,7 @@ OGRFeature *OGRDWGLayer::TranslateMTEXT( OdDbEntityPtr poEntity )
 /* -------------------------------------------------------------------- */
     OdGePoint3d oLocation = poMTE->location();
 
-    poFeature->SetGeometryDirectly( 
+    poFeature->SetGeometryDirectly(
         new OGRPoint( oLocation.x, oLocation.y, oLocation.z ) );
 
 /* -------------------------------------------------------------------- */
@@ -473,7 +469,7 @@ OGRFeature *OGRDWGLayer::TranslateMTEXT( OdDbEntityPtr poEntity )
     if( oStyleProperties.count("Color") > 0 )
         nColor = atoi(oStyleProperties["Color"]);
 
-    // Use layer color? 
+    // Use layer color?
     if( nColor < 1 || nColor > 255 )
     {
         CPLString osLayer = poFeature->GetFieldAsString("Layer");
@@ -481,11 +477,11 @@ OGRFeature *OGRDWGLayer::TranslateMTEXT( OdDbEntityPtr poEntity )
         if( pszValue != NULL )
             nColor = atoi(pszValue);
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Prepare style string.                                           */
 /* -------------------------------------------------------------------- */
-    double dfAngle = poMTE->rotation() * 180 / PI;
+    double dfAngle = poMTE->rotation() * 180 / M_PI;
     double dfHeight = poMTE->textHeight();
     int nAttachmentPoint = (int) poMTE->attachment();
 
@@ -515,18 +511,18 @@ OGRFeature *OGRDWGLayer::TranslateMTEXT( OdDbEntityPtr poEntity )
 
     if( nAttachmentPoint >= 0 && nAttachmentPoint <= 9 )
     {
-        const static int anAttachmentMap[10] = 
+        const static int anAttachmentMap[10] =
             { -1, 7, 8, 9, 4, 5, 6, 1, 2, 3 };
-        
-        osStyle += 
+
+        osStyle +=
             CPLString().Printf(",p:%d", anAttachmentMap[nAttachmentPoint]);
     }
 
     if( nColor > 0 && nColor < 256 )
     {
         const unsigned char *pabyDWGColors = ACGetColorTable();
-        osStyle += 
-            CPLString().Printf( ",c:#%02x%02x%02x", 
+        osStyle +=
+            CPLString().Printf( ",c:#%02x%02x%02x",
                                 pabyDWGColors[nColor*3+0],
                                 pabyDWGColors[nColor*3+1],
                                 pabyDWGColors[nColor*3+2] );
@@ -556,7 +552,7 @@ OGRFeature *OGRDWGLayer::TranslateTEXT( OdDbEntityPtr poEntity )
 /* -------------------------------------------------------------------- */
     OdGePoint3d oLocation = poText->position();
 
-    poFeature->SetGeometryDirectly( 
+    poFeature->SetGeometryDirectly(
         new OGRPoint( oLocation.x, oLocation.y, oLocation.z ) );
 
 /* -------------------------------------------------------------------- */
@@ -593,7 +589,7 @@ OGRFeature *OGRDWGLayer::TranslateTEXT( OdDbEntityPtr poEntity )
 /* -------------------------------------------------------------------- */
     CPLString osLayer = poFeature->GetFieldAsString("Layer");
 
-    int bHidden = 
+    int bHidden =
         EQUAL(poDS->LookupLayerProperty( osLayer, "Hidden" ), "1");
 
 /* -------------------------------------------------------------------- */
@@ -604,21 +600,21 @@ OGRFeature *OGRDWGLayer::TranslateTEXT( OdDbEntityPtr poEntity )
     if( oStyleProperties.count("Color") > 0 )
         nColor = atoi(oStyleProperties["Color"]);
 
-    // Use layer color? 
+    // Use layer color?
     if( nColor < 1 || nColor > 255 )
     {
         const char *pszValue = poDS->LookupLayerProperty( osLayer, "Color" );
         if( pszValue != NULL )
             nColor = atoi(pszValue);
     }
-        
+
     if( nColor < 1 || nColor > 255 )
         nColor = 8;
 
 /* -------------------------------------------------------------------- */
 /*      Prepare style string.                                           */
 /* -------------------------------------------------------------------- */
-    double dfAngle = poText->rotation() * 180 / PI;
+    double dfAngle = poText->rotation() * 180 / M_PI;
     double dfHeight = poText->height();
 
     CPLString osStyle;
@@ -647,14 +643,14 @@ OGRFeature *OGRDWGLayer::TranslateTEXT( OdDbEntityPtr poEntity )
 
     const unsigned char *pabyDWGColors = ACGetColorTable();
 
-    snprintf( szBuffer, sizeof(szBuffer), ",c:#%02x%02x%02x", 
+    snprintf( szBuffer, sizeof(szBuffer), ",c:#%02x%02x%02x",
               pabyDWGColors[nColor*3+0],
               pabyDWGColors[nColor*3+1],
               pabyDWGColors[nColor*3+2] );
     osStyle += szBuffer;
 
     if( bHidden )
-        osStyle += "00"; 
+        osStyle += "00";
 
     osStyle += ")";
 
@@ -704,7 +700,7 @@ OGRFeature *OGRDWGLayer::TranslateLWPOLYLINE( OdDbEntityPtr poEntity )
         OdGePoint3d oPoint;
         poPL->getPointAt( i, oPoint );
 
-        oSmoothPolyline.AddPoint( oPoint.x, oPoint.y, 0.0, 
+        oSmoothPolyline.AddPoint( oPoint.x, oPoint.y, 0.0,
                                  poPL->getBulgeAt( i ) );
     }
 
@@ -717,7 +713,7 @@ OGRFeature *OGRDWGLayer::TranslateLWPOLYLINE( OdDbEntityPtr poEntity )
     if( poPL->isClosed() )
         oSmoothPolyline.Close();
 
-    poFeature->SetGeometryDirectly( 
+    poFeature->SetGeometryDirectly(
         oSmoothPolyline.Tesselate() );
 
     PrepareLineStyle( poFeature );
@@ -843,8 +839,8 @@ OGRFeature *OGRDWGLayer::TranslateCIRCLE( OdDbEntityPtr poEntity )
 /* -------------------------------------------------------------------- */
 /*      Create geometry                                                 */
 /* -------------------------------------------------------------------- */
-    OGRGeometry *poCircle = 
-        OGRGeometryFactory::approximateArcAngles( 
+    OGRGeometry *poCircle =
+        OGRGeometryFactory::approximateArcAngles(
             oCenter.x, oCenter.y, oCenter.z,
             dfRadius, dfRadius, 0.0, 0.0, 360.0, 0.0 );
 
@@ -868,18 +864,18 @@ double OGRDWGLayer::AngleCorrect( double dfTrueAngle, double dfRatio )
     double dfRotAngle;
     double dfDeltaX, dfDeltaY;
 
-    dfTrueAngle *= (PI / 180); // convert to radians.
+    dfTrueAngle *= (M_PI / 180); // convert to radians.
 
     dfDeltaX = cos(dfTrueAngle);
     dfDeltaY = sin(dfTrueAngle);
 
     dfRotAngle = atan2( dfDeltaY, dfDeltaX * dfRatio);
 
-    dfRotAngle *= (180 / PI); // convert to degrees.
+    dfRotAngle *= (180 / M_PI); // convert to degrees.
 
     if( dfTrueAngle < 0 && dfRotAngle > 0 )
         dfRotAngle -= 360.0;
-    
+
     if( dfTrueAngle > 360 && dfRotAngle < 360 )
         dfRotAngle += 360.0;
 
@@ -906,11 +902,11 @@ OGRFeature *OGRDWGLayer::TranslateELLIPSE( OdDbEntityPtr poEntity )
     OdGeVector3d oMajorAxis, oUnitNormal;
 
     // note we reverse start and end angles to account for ogr orientation.
-    poEE->get( oCenter, oUnitNormal, oMajorAxis, 
-               dfRatio, dfEndAngle, dfStartAngle ); 
+    poEE->get( oCenter, oUnitNormal, oMajorAxis,
+               dfRatio, dfEndAngle, dfStartAngle );
 
-    dfStartAngle = -1 * dfStartAngle * 180 / PI;
-    dfEndAngle   = -1 * dfEndAngle * 180 / PI;
+    dfStartAngle = -1 * dfStartAngle * 180 / M_PI;
+    dfEndAngle   = -1 * dfEndAngle * 180 / M_PI;
 
 /* -------------------------------------------------------------------- */
 /*      The DWG SDK expresses the angles as the angle to a real         */
@@ -921,7 +917,7 @@ OGRFeature *OGRDWGLayer::TranslateELLIPSE( OdDbEntityPtr poEntity )
 /* -------------------------------------------------------------------- */
     dfStartAngle = AngleCorrect( dfStartAngle, dfRatio );
     dfEndAngle = AngleCorrect( dfEndAngle, dfRatio );
-    
+
     if( dfStartAngle > dfEndAngle )
         dfEndAngle += 360.0;
 
@@ -938,15 +934,15 @@ OGRFeature *OGRDWGLayer::TranslateELLIPSE( OdDbEntityPtr poEntity )
 
     dfSecondaryRadius = dfRatio * dfPrimaryRadius;
 
-    dfRotation = -1 * atan2( oMajorAxis.y, oMajorAxis.x ) * 180 / PI;
+    dfRotation = -1 * atan2( oMajorAxis.y, oMajorAxis.x ) * 180 / M_PI;
 
 /* -------------------------------------------------------------------- */
 /*      Create geometry                                                 */
 /* -------------------------------------------------------------------- */
-    OGRGeometry *poEllipse = 
-        OGRGeometryFactory::approximateArcAngles( 
+    OGRGeometry *poEllipse =
+        OGRGeometryFactory::approximateArcAngles(
             oCenter.x, oCenter.y, oCenter.z,
-            dfPrimaryRadius, dfSecondaryRadius, dfRotation, 
+            dfPrimaryRadius, dfSecondaryRadius, dfRotation,
             dfStartAngle, dfEndAngle, 0.0 );
 
     poFeature->SetGeometryDirectly( poEllipse );
@@ -974,19 +970,19 @@ OGRFeature *OGRDWGLayer::TranslateARC( OdDbEntityPtr poEntity )
 /* -------------------------------------------------------------------- */
 /*      Collect parameters.                                             */
 /* -------------------------------------------------------------------- */
-    dfEndAngle = -1 * poAE->startAngle() * 180 / PI;
-    dfStartAngle = -1 * poAE->endAngle() * 180 / PI;
+    dfEndAngle = -1 * poAE->startAngle() * 180 / M_PI;
+    dfStartAngle = -1 * poAE->endAngle() * 180 / M_PI;
     dfRadius = poAE->radius();
     oCenter = poAE->center();
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create geometry                                                 */
 /* -------------------------------------------------------------------- */
     if( dfStartAngle > dfEndAngle )
         dfEndAngle += 360.0;
 
-    OGRGeometry *poArc = 
-        OGRGeometryFactory::approximateArcAngles( 
+    OGRGeometry *poArc =
+        OGRGeometryFactory::approximateArcAngles(
             oCenter.x, oCenter.y, oCenter.z,
             dfRadius, dfRadius, 0.0, dfStartAngle, dfEndAngle, 0.0 );
 
@@ -1022,7 +1018,7 @@ OGRFeature *OGRDWGLayer::TranslateSPLINE( OdDbEntityPtr poEntity )
     int nControlPoints = poSpline->numControlPoints();
 
     adfControlPoints.push_back( 0.0 ); // some sort of control info.
-    
+
     for( i = 0; i < nControlPoints; i++ )
     {
         OdGePoint3d oCP;
@@ -1055,7 +1051,7 @@ OGRFeature *OGRDWGLayer::TranslateSPLINE( OdDbEntityPtr poEntity )
     h.push_back(1.0);
     for( i = 0; i < nControlPoints; i++ )
         h.push_back( 1.0 );
-    
+
     // resolution:
     //int p1 = getGraphicVariableInt("$SPLINESEGS", 8) * npts;
     int p1 = nControlPoints * 8;
@@ -1065,12 +1061,12 @@ OGRFeature *OGRDWGLayer::TranslateSPLINE( OdDbEntityPtr poEntity )
         p.push_back( 0.0 );
 
     if( poSpline->isClosed() )
-        rbsplinu( nControlPoints, nDegree+1, p1, &(adfControlPoints[0]), 
+        rbsplinu( nControlPoints, nDegree+1, p1, &(adfControlPoints[0]),
                   &(h[0]), &(p[0]) );
     else
-        rbspline( nControlPoints, nDegree+1, p1, &(adfControlPoints[0]), 
+        rbspline( nControlPoints, nDegree+1, p1, &(adfControlPoints[0]),
                   &(h[0]), &(p[0]) );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Turn into OGR geometry.                                         */
 /* -------------------------------------------------------------------- */
@@ -1095,7 +1091,7 @@ OGRFeature *OGRDWGLayer::TranslateSPLINE( OdDbEntityPtr poEntity )
 class GeometryInsertTransformer : public OGRCoordinateTransformation
 {
 public:
-    GeometryInsertTransformer() : 
+    GeometryInsertTransformer() :
             dfXOffset(0),dfYOffset(0),dfZOffset(0),
             dfXScale(1.0),dfYScale(1.0),dfZScale(1.0),
             dfAngle(0.0) {}
@@ -1110,11 +1106,11 @@ public:
 
     OGRSpatialReference *GetSourceCS() { return NULL; }
     OGRSpatialReference *GetTargetCS() { return NULL; }
-    int Transform( int nCount, 
+    int Transform( int nCount,
                    double *x, double *y, double *z )
         { return TransformEx( nCount, x, y, z, NULL ); }
-    
-    int TransformEx( int nCount, 
+
+    int TransformEx( int nCount,
                      double *x, double *y, double *z = NULL,
                      int *pabSuccess = NULL )
         {
@@ -1161,16 +1157,16 @@ OGRFeature *OGRDWGLayer::TranslateINSERT( OdDbEntityPtr poEntity )
 /* -------------------------------------------------------------------- */
     GeometryInsertTransformer oTransformer;
     CPLString osBlockName;
-    double dfAngle = poRef->rotation() * 180 / PI;
+    double dfAngle = poRef->rotation() * 180 / M_PI;
     OdGePoint3d oPosition = poRef->position();
     OdGeScale3d oScale = poRef->scaleFactors();
-    
+
     oTransformer.dfXOffset = oPosition.x;
     oTransformer.dfYOffset = oPosition.y;
     oTransformer.dfZOffset = oPosition.z;
 
-    oTransformer.dfXScale = oScale.sx;    
-    oTransformer.dfYScale = oScale.sy;    
+    oTransformer.dfXScale = oScale.sx;
+    oTransformer.dfYScale = oScale.sy;
     oTransformer.dfZScale = oScale.sz;
 
     oTransformer.dfAngle = poRef->rotation();
@@ -1186,7 +1182,7 @@ OGRFeature *OGRDWGLayer::TranslateINSERT( OdDbEntityPtr poEntity )
     if( !poDS->InlineBlocks() )
     {
         poFeature->SetGeometryDirectly(
-            new OGRPoint( oTransformer.dfXOffset, 
+            new OGRPoint( oTransformer.dfXOffset,
                           oTransformer.dfYOffset,
                           oTransformer.dfZOffset ) );
 
@@ -1202,7 +1198,7 @@ OGRFeature *OGRDWGLayer::TranslateINSERT( OdDbEntityPtr poEntity )
 /*      Lookup the block.                                               */
 /* -------------------------------------------------------------------- */
     DWGBlockDefinition *poBlock = poDS->LookupBlock( osBlockName );
-    
+
     if( poBlock == NULL )
     {
         delete poFeature;
@@ -1316,7 +1312,7 @@ OGRFeature *OGRDWGLayer::GetNextUnfilteredFeature()
 
         OdDbObjectId oId = poEntIter->objectId();
         OdDbEntityPtr poEntity = OdDbEntity::cast( oId.openObject() );
-        
+
         if (poEntity.isNull())
             return NULL;
 
@@ -1326,7 +1322,7 @@ OGRFeature *OGRDWGLayer::GetNextUnfilteredFeature()
         OdRxClass *poClass = poEntity->isA();
         const OdString osName = poClass->name();
         const char *pszEntityClassName = (const char *) osName;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Handle the entity.                                              */
 /* -------------------------------------------------------------------- */
@@ -1364,12 +1360,12 @@ OGRFeature *OGRDWGLayer::GetNextUnfilteredFeature()
         {
             poFeature = TranslateMTEXT( poEntity );
         }
-        else if( EQUAL(pszEntityClassName,"AcDbText") 
+        else if( EQUAL(pszEntityClassName,"AcDbText")
                  || EQUAL(pszEntityClassName,"AcDbAttributeDefinition") )
         {
             poFeature = TranslateTEXT( poEntity );
         }
-        else if( EQUAL(pszEntityClassName,"AcDbAlignedDimension") 
+        else if( EQUAL(pszEntityClassName,"AcDbAlignedDimension")
                  || EQUAL(pszEntityClassName,"AcDbRotatedDimension") )
         {
             poFeature = TranslateDIMENSION( poEntity );
@@ -1394,14 +1390,14 @@ OGRFeature *OGRDWGLayer::GetNextUnfilteredFeature()
                 poFeature = apoPendingFeatures.front();
                 apoPendingFeatures.pop();
             }
-               
+
         }
         else
         {
             if( oIgnoredEntities.count(pszEntityClassName) == 0 )
             {
                 oIgnoredEntities.insert( pszEntityClassName );
-                CPLDebug( "DWG", "Ignoring one or more of entity '%s'.", 
+                CPLDebug( "DWG", "Ignoring one or more of entity '%s'.",
                           pszEntityClassName );
             }
         }
@@ -1417,7 +1413,7 @@ OGRFeature *OGRDWGLayer::GetNextUnfilteredFeature()
         poFeature->SetFID( iNextFID++ );
         m_nFeaturesRead++;
     }
-    
+
     return poFeature;
 }
 
@@ -1428,7 +1424,7 @@ OGRFeature *OGRDWGLayer::GetNextUnfilteredFeature()
 OGRFeature *OGRDWGLayer::GetNextFeature()
 
 {
-    while( TRUE )
+    while( true )
     {
         OGRFeature *poFeature = GetNextUnfilteredFeature();
 
@@ -1459,4 +1455,3 @@ int OGRDWGLayer::TestCapability( const char * pszCap )
     else
         return FALSE;
 }
-
diff --git a/ogr/ogrsf_frmts/dxf/drv_dxf.html b/ogr/ogrsf_frmts/dxf/drv_dxf.html
index e4752ea..159d138 100644
--- a/ogr/ogrsf_frmts/dxf/drv_dxf.html
+++ b/ogr/ogrsf_frmts/dxf/drv_dxf.html
@@ -8,12 +8,12 @@
 <h1>AutoCAD DXF</h1>
 
 OGR supports reading most versions of AutoCAD DXF and writing AutoCAD 2000
-version files.  DXF is an ASCII format used for interchanging AutoCAD drawings 
-between different software packages.  The entire contents of the file is 
+version files.  DXF is an ASCII format used for interchanging AutoCAD drawings
+between different software packages.  The entire contents of the file is
 represented as a single layer named "entities".  <p>
 
 
-DXF files are considered to have no georeferencing information through OGR. 
+DXF files are considered to have no georeferencing information through OGR.
 Features will all have the following generic attributes:
 
 <ul>
@@ -22,7 +22,7 @@ Features will all have the following generic attributes:
 <li> ExtendedEntity: Where available, extended entity attributes all appended to form a single text attribute.
 <li> Linetype: Where available, the line type used for this entity.
 <li> EntityHandle: The hexadecimal entity handle.  A sort of feature id.
-<li> Text: The text of labels. 
+<li> Text: The text of labels.
 </ul>
 
 <h2>Supported Elements</h2>
@@ -32,19 +32,19 @@ The following element types are supported:<p>
 <ul>
 <li> POINT: Produces a simple point geometry feature.
 <li> MTEXT, TEXT: Produces a point feature with LABEL style information.
-<li> LINE, POLYLINE, LWPOLYLINE: translated as a LINESTRING. Rounded 
-polylines (those with their vertices' budge attributes set) will be tesselated.
+<li> LINE, POLYLINE, LWPOLYLINE: translated as a LINESTRING. Rounded
+polylines (those with their vertices' budge attributes set) will be tessellated.
 Single-vertex polylines are translated to POINT.
-<li> CIRCLE, ELLIPSE, ARC:  Translated as a LINESTRING, tesselating the 
-arc into line segments. 
+<li> CIRCLE, ELLIPSE, ARC:  Translated as a LINESTRING, tessellating the
+arc into line segments.
 <li> INSERT: An attempt is made to insert the block definition as defined
 in the insert.  Linework blocks are aggregated into a single feature with
 a geometry collection for the geometry.  Text blocks are returned as one or
-more text features.  To avoid merging blocks into a geometry collection the 
+more text features.  To avoid merging blocks into a geometry collection the
 DXF_MERGE_BLOCK_GEOMETRIES config option may be set to FALSE.
 <li> DIMENSION: This element is exploded into a feature with arrows and
 leaders, and a feature with the dimension label.
-<li> HATCH: Line and arc boundaries are collected as a polygon geometry, but 
+<li> HATCH: Line and arc boundaries are collected as a polygon geometry, but
 no effort is currently made to represent the fill style of HATCH entities.
 <li> 3DFACE, SOLID: Translated as POLYGON.
 
@@ -55,29 +55,29 @@ and orientation via OGR feature styling information when translating elements.
 Currently no effort is made to preserve fill styles or complex line style
 attributes.<p>
 
-The approximation of arcs, ellipses, circles and rounded polylines as 
-linestrings is done by splitting the arcs into subarcs of no more than a 
-threshhold angle.  This angle is the OGR_ARC_STEPSIZE.  This defaults to 
-four degrees, but may be overridden by setting the configuration variable 
+The approximation of arcs, ellipses, circles and rounded polylines as
+linestrings is done by splitting the arcs into subarcs of no more than a
+threshold angle.  This angle is the OGR_ARC_STEPSIZE.  This defaults to
+four degrees, but may be overridden by setting the configuration variable
 OGR_ARC_STEPSIZE.<p>
 
 <h2>DXF_INLINE_BLOCKS</h2>
 
-The default behavior is for INSERT entities to be expanded with the 
-geometry of the BLOCK they reference.  However, if the DXF_INLINE_BLOCKS 
+The default behavior is for INSERT entities to be expanded with the
+geometry of the BLOCK they reference.  However, if the DXF_INLINE_BLOCKS
 configuration option is set to the value FALSE, then the behavior is different
 as described here.
 
 <ul>
-<li> A new layer will be available called blocks.  It will contain one or 
+<li> A new layer will be available called blocks.  It will contain one or
 more features for each BLOCK defined in the file.  In addition to the usual
 attributes, they will also have a BlockName attribute indicate what block
 they are part of.
-<li> The entities layer will have new attributes BlockName, BlockScale, 
-and BlockAngle. 
+<li> The entities layer will have new attributes BlockName, BlockScale,
+and BlockAngle.
 <li> INSERT entities will populate these new fields with the corresponding
-information (they are null for all other entities). 
-<li> INSERT entities will not have block geometry inlined - instead they will 
+information (they are null for all other entities).
+<li> INSERT entities will not have block geometry inlined - instead they will
 have a point geometry for the insertion point.
 </ul>
 
@@ -88,21 +88,21 @@ creation of similar blocks. <p>
 
 <h2>Character Encodings</h2>
 
-Normally DXF files are in the ANSI_1252 / Win1252 encoding.  GDAL/OGR attempts 
+Normally DXF files are in the ANSI_1252 / Win1252 encoding.  GDAL/OGR attempts
 to translate this to UTF-8 when reading and back into ANSI_1252 when writing.
-DXF files can also have a header field ($DWGCODEPAGE) indicating the 
+DXF files can also have a header field ($DWGCODEPAGE) indicating the
 encoding of the file.  In GDAL 1.8.x and earlier this was ignored but from
-GDAL 1.9.0 and later an attempt is made to use this to recode other 
+GDAL 1.9.0 and later an attempt is made to use this to recode other
 code pages to UTF-8.  Whether this works will depend on the code page naming
 and whether GDAL/OGR is built against the iconv library for character recoding.
 <p>
 
 In some cases the $DWGCODEPAGE setting in a DXF file will be wrong, or
-unrecognised by OGR.  It could be edited manually, or the DXF_ENCODING 
-configuration variable can be used to override what id will be used by 
+unrecognised by OGR.  It could be edited manually, or the DXF_ENCODING
+configuration variable can be used to override what id will be used by
 OGR in transcoding.  The value of DXF_ENCODING should be an encoding name
-supported by CPLRecode() (ie. an iconv name), not a DXF $DWGCODEPAGE name.
-Using a DXF_ENCODING name of "UTF-8" will avoid any attempt to recode the 
+supported by CPLRecode() (i.e. an iconv name), not a DXF $DWGCODEPAGE name.
+Using a DXF_ENCODING name of "UTF-8" will avoid any attempt to recode the
 text as it is read.<p>
 
 <hr>
@@ -118,7 +118,7 @@ on the styling information.<p>
 
 Point features without LABEL styling are written as POINT entities.<p>
 
-LineString and MultiLineString features are written as one or more 
+LineString and MultiLineString features are written as one or more
 LWPOLYLINE entities, closed in the case of polygon rings.  An effort is
 made to preserve line width and color.<p>
 
@@ -128,10 +128,10 @@ The dataset creation supports the following dataset creation options:<p>
 
 <ul>
 
-<li> <b>HEADER=</b><i>filename</i>: Override the header file used - in place 
+<li> <b>HEADER=</b><i>filename</i>: Override the header file used - in place
 of header.dxf located in the GDAL_DATA directory.
 
-<li> <b>TRAILER=</b><i>filename</i>: Override the trailer file used - in place 
+<li> <b>TRAILER=</b><i>filename</i>: Override the trailer file used - in place
 of trailer.dxf located in the GDAL_DATA directory. <p>
 
 </ul>
@@ -142,33 +142,33 @@ portions (portion before or after the ENTITIES section). <p>
 
 <h3>Block References</h3>
 
-It is possible to export a "blocks" layer to DXF in addition to the 
-"entities" layer in order to produce actual DXF BLOCKs definitions 
+It is possible to export a "blocks" layer to DXF in addition to the
+"entities" layer in order to produce actual DXF BLOCKs definitions
 in the output file.  It is also possible to write INSERT entities if
 a block name is provided for an entity.  To make this work the follow
 conditions apply.
 
 <ul>
-<li> A "blocks" layer may be created, and it must be created before the 
-entities layer. 
+<li> A "blocks" layer may be created, and it must be created before the
+entities layer.
 <li> The entities in the blocks layer should have the BlockName field
 populated.
-<li> Objects to be written as INSERTs in the entities layer should have a 
-POINT geometry, and the BlockName field set. 
+<li> Objects to be written as INSERTs in the entities layer should have a
+POINT geometry, and the BlockName field set.
 <li> If a block (name) is already defined in the template header, that will be
 used regardless of whether a new definition was provided in the blocks layer.
 </ul>
 
-The intention is that a simple translation from DXF to with DXF_INLINE_BLOCKS 
-set to FALSE will approximately reproduce the original blocks and keep 
+The intention is that a simple translation from DXF to with DXF_INLINE_BLOCKS
+set to FALSE will approximately reproduce the original blocks and keep
 INSERT entities as INSERT entities rather than exploding them.<p>
 
 <h3>Layer Definitions</h3>
 
-When writing entities, if populated the Layer field is used to set the 
+When writing entities, if populated the Layer field is used to set the
 written entities layer.  If the layer is not already defined in the template
-header then a new layer definition will be introduced, copied from the 
-definition of the default layer ("0"). 
+header then a new layer definition will be introduced, copied from the
+definition of the default layer ("0").
 
 <h3>Line Type Definitions</h2>
 
@@ -179,12 +179,12 @@ Linetype definitions.<p>
 <li> If the Linetype field is set on the written features, and that Linetype
 is already defined in the template header then it will be referenced from
 the entities regardless of whether an OGR style string existed.
-<li> If the Linetype is set, but the Linetype is not predefined in the 
-header template, then a definition will be added if the feature has an 
-OGR style string with a PEN tool and a "p" pattern setting. 
+<li> If the Linetype is set, but the Linetype is not predefined in the
+header template, then a definition will be added if the feature has an
+OGR style string with a PEN tool and a "p" pattern setting.
 <li> If the feature has no Linetype field set, but it does have an OGR
 style string with a PEN tool with a "p" pattern set then an automatically
-named Linetype will be created in the output file. 
+named Linetype will be created in the output file.
 <li> It is assumed that patterns are using "g" (georeferenced) units for
 defining the line pattern.  If not the scaling of the DXF patterns is likely to be wrong - potentially very wrong.
 </ul>
@@ -195,7 +195,7 @@ and referenced using the Linetype field if desired.<p>
 
 <h3>Units</h2>
 
-At the moment GDAL writes DXF to report the the measurement units as "English - Inches". 
+At the moment GDAL writes DXF to report the measurement units as "English - Inches".
 For changing the units edit $MEASUREMENT and $INSUNITS variables in the header template.
 
 <h3>See also</h2>
diff --git a/ogr/ogrsf_frmts/dxf/intronurbs.cpp b/ogr/ogrsf_frmts/dxf/intronurbs.cpp
index b32294b..d3a4b89 100644
--- a/ogr/ogrsf_frmts/dxf/intronurbs.cpp
+++ b/ogr/ogrsf_frmts/dxf/intronurbs.cpp
@@ -17,34 +17,38 @@ available at:
 Copyright (c) 2009, David F. Rogers
 All rights reserved.
 
-Redistribution and use in source and binary forms, with or without 
+Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
 
-    * Redistributions of source code must retain the above copyright notice, 
+    * Redistributions of source code must retain the above copyright notice,
       this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright notice,
       this list of conditions and the following disclaimer in the documentation
       and/or other materials provided with the distribution.
     * Neither the name of David F. Rogers nor the names of its contributors
-      may be used to endorse or promote products derived from this software 
+      may be used to endorse or promote products derived from this software
       without specific prior written permission.
 
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
 */
 
 #include <stdio.h>
 #include <vector>
 
+/* used by ogrdxflayer.cpp */
+void rbspline(int npts,int k,int p1,double b[],double h[], double p[]);
+void rbsplinu(int npts,int k,int p1,double b[],double h[], double p[]);
+
 /************************************************************************/
 /*                               knotu()                                */
 /************************************************************************/
@@ -53,7 +57,7 @@ POSSIBILITY OF SUCH DAMAGE.
 
     c            = order of the basis function
     n            = the number of defining polygon vertices
-    nplus2       = index of x() for the first occurence of the maximum knot vector value
+    nplus2       = index of x() for the first occurrence of the maximum knot vector value
     nplusc       = maximum value of the knot vector -- $n + c$
     x[]          = array containing the knot vector
 */
@@ -79,10 +83,10 @@ static void knotu(int n,int c,int x[])
 /*
     Subroutine to generate a B-spline open knot vector with multiplicity
     equal to the order at the ends.
-	
+
     c            = order of the basis function
     n            = the number of defining polygon vertices
-    nplus2       = index of x() for the first occurence of the maximum knot vector value
+    nplus2       = index of x() for the first occurrence of the maximum knot vector value
     nplusc       = maximum value of the knot vector -- $n + c$
     x()          = array containing the knot vector
 */
@@ -113,7 +117,7 @@ static void knot(int n,int c,int x[])
 	C code for An Introduction to NURBS
 	by David F. Rogers. Copyright (C) 2000 David F. Rogers,
 	All rights reserved.
-	
+
 	Name: rbais
 	Language: C
 	Subroutines called: none
@@ -130,7 +134,7 @@ static void knot(int n,int c,int x[])
     t        = parameter value
     temp[]   = temporary array
     x[]      = knot vector
-*/	
+*/
 
 static void rbasis(int c,double t,int npts, int x[], double h[], double r[])
 
@@ -202,7 +206,7 @@ static void rbasis(int c,double t,int npts, int x[], double h[], double r[])
 	C code for An Introduction to NURBS
 	by David F. Rogers. Copyright (C) 2000 David F. Rogers,
 	All rights reserved.
-	
+
 	Name: rbspline.c
 	Language: C
 	Subroutines called: knot.c, rbasis.c, fmtmul.c
@@ -212,7 +216,7 @@ static void rbasis(int c,double t,int npts, int x[], double h[], double r[])
                   b[1] contains the x-component of the vertex
                   b[2] contains the y-component of the vertex
                   b[3] contains the z-component of the vertex
-	h[]			= array containing the homogeneous weighting factors 
+	h[]			= array containing the homogeneous weighting factors
     k           = order of the B-spline basis function
     nbasis      = array containing the basis functions for a single value of t
     nplusc      = number of knot values
@@ -280,7 +284,7 @@ void rbspline(int npts,int k,int p1,double b[],double h[], double p[])
         }
 
         /* generate the basis function for this value of t */
-        rbasis(k,t,npts,&(x[0]),h,&(nbasis[0])); 
+        rbasis(k,t,npts,&(x[0]),h,&(nbasis[0]));
         for (j = 1; j <= 3; j++){      /* generate a point on the curve */
             jcount = j;
             p[icount+j] = 0.;
@@ -311,7 +315,7 @@ void rbspline(int npts,int k,int p1,double b[],double h[], double p[])
 	C code for An Introduction to NURBS
 	by David F. Rogers. Copyright (C) 2000 David F. Rogers,
 	All rights reserved.
-	
+
 	Name: rbsplinu.c
 	Language: C
 	Subroutines called: knotu.c, rbasis.c, fmtmul.c
@@ -321,7 +325,7 @@ void rbspline(int npts,int k,int p1,double b[],double h[], double p[])
                   b[1] contains the x-component of the vertex
                   b[2] contains the y-component of the vertex
                   b[3] contains the z-component of the vertex
-	h[]			= array containing the homogeneous weighting factors 
+	h[]			= array containing the homogeneous weighting factors
     k           = order of the B-spline basis function
     nbasis      = array containing the basis functions for a single value of t
     nplusc      = number of knot values
diff --git a/ogr/ogrsf_frmts/dxf/ogr_autocad_services.cpp b/ogr/ogrsf_frmts/dxf/ogr_autocad_services.cpp
index ac2f561..fe8949e 100644
--- a/ogr/ogrsf_frmts/dxf/ogr_autocad_services.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogr_autocad_services.cpp
@@ -33,10 +33,6 @@
 
 CPL_CVSID("$Id: ogrdwglayer.cpp 22008 2011-03-22 19:45:20Z warmerdam $");
 
-#ifndef PI
-#define PI  3.14159265358979323846
-#endif 
-
 /************************************************************************/
 /*                           ACTextUnescape()                           */
 /*                                                                      */
@@ -49,7 +45,7 @@ CPLString ACTextUnescape( const char *pszRawInput, const char *pszEncoding )
 {
     CPLString osResult;
     CPLString osInput = pszRawInput;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Translate text from Win-1252 to UTF8.  We approximate this      */
 /*      by treating Win-1252 as Latin-1.  Note that we likely ought     */
@@ -77,7 +73,7 @@ CPLString ACTextUnescape( const char *pszRawInput, const char *pszEncoding )
             osResult += ' ';
             pszInput++;
         }
-        else if( pszInput[0] == '\\' && pszInput[1] == 'U' 
+        else if( pszInput[0] == '\\' && pszInput[1] == 'U'
                  && pszInput[2] == '+' )
         {
             CPLString osHex;
@@ -89,27 +85,27 @@ CPLString ACTextUnescape( const char *pszRawInput, const char *pszEncoding )
             wchar_t anWCharString[2];
             anWCharString[0] = (wchar_t) iChar;
             anWCharString[1] = 0;
-            
+
             char *pszUTF8Char = CPLRecodeFromWChar( anWCharString,
-                                                    CPL_ENC_UCS2, 
+                                                    CPL_ENC_UCS2,
                                                     CPL_ENC_UTF8 );
 
             osResult += pszUTF8Char;
             CPLFree( pszUTF8Char );
-            
+
             pszInput += 6;
         }
         else if( pszInput[0] == '\\'
-                 && (pszInput[1] == 'W' 
+                 && (pszInput[1] == 'W'
                      || pszInput[1] == 'T'
                      || pszInput[1] == 'A' ) )
         {
             // eg. \W1.073172x;\T1.099;Bonneuil de Verrines
             // See data/dwg/EP/42002.dwg
-            // Not sure what \W and \T do, but we skip them. 
+            // Not sure what \W and \T do, but we skip them.
             // According to qcad rs_text.cpp, \A values are vertical
             // alignment, 0=bottom, 1=mid, 2=top but we ignore for now.
-            
+
             while( *pszInput != ';' && *pszInput != '\0' )
                 pszInput++;
         }
@@ -118,37 +114,37 @@ CPLString ACTextUnescape( const char *pszRawInput, const char *pszEncoding )
             osResult += '\\';
             pszInput++;
         }
-        else if( EQUALN(pszInput,"%%c",3) 
-                 || EQUALN(pszInput,"%%d",3)
-                 || EQUALN(pszInput,"%%p",3) )
+        else if( STARTS_WITH_CI(pszInput, "%%c")
+                 || STARTS_WITH_CI(pszInput, "%%d")
+                 || STARTS_WITH_CI(pszInput, "%%p") )
         {
             wchar_t anWCharString[2];
 
             anWCharString[1] = 0;
 
             // These are especial symbol representations for autocad.
-            if( EQUALN(pszInput,"%%c",3) )
+            if( STARTS_WITH_CI(pszInput, "%%c") )
                 anWCharString[0] = 0x2300; // diameter (0x00F8 is a good approx)
-            else if( EQUALN(pszInput,"%%d",3) )
+            else if( STARTS_WITH_CI(pszInput, "%%d") )
                 anWCharString[0] = 0x00B0; // degree
-            else if( EQUALN(pszInput,"%%p",3) )
+            else if( STARTS_WITH_CI(pszInput, "%%p") )
                 anWCharString[0] = 0x00B1; // plus/minus
 
             char *pszUTF8Char = CPLRecodeFromWChar( anWCharString,
-                                                    CPL_ENC_UCS2, 
+                                                    CPL_ENC_UCS2,
                                                     CPL_ENC_UTF8 );
 
             osResult += pszUTF8Char;
             CPLFree( pszUTF8Char );
-            
+
             pszInput += 2;
         }
-        else 
+        else
             osResult += *pszInput;
 
         pszInput++;
     }
-    
+
     return osResult;
 }
 
@@ -160,262 +156,262 @@ const unsigned char *ACGetColorTable()
 
 {
     static const unsigned char abyDXFColors[768] = {
-          0,  0,  0, // 0 
-        255,  0,  0, // 1 
-        255,255,  0, // 2 
-          0,255,  0, // 3 
-          0,255,255, // 4 
-          0,  0,255, // 5 
-        255,  0,255, // 6 
+          0,  0,  0, // 0
+        255,  0,  0, // 1
+        255,255,  0, // 2
+          0,255,  0, // 3
+          0,255,255, // 4
+          0,  0,255, // 5
+        255,  0,255, // 6
           0,  0,  0, // 7 - it should be white, but that plots poorly
-        127,127,127, // 8 
-        191,191,191, // 9 
-        255,  0,  0, // 10 
-        255,127,127, // 11 
-        165,  0,  0, // 12 
-        165, 82, 82, // 13 
-        127,  0,  0, // 14 
-        127, 63, 63, // 15 
-         76,  0,  0, // 16 
-         76, 38, 38, // 17 
-         38,  0,  0, // 18 
-         38, 19, 19, // 19 
-        255, 63,  0, // 20 
-        255,159,127, // 21 
-        165, 41,  0, // 22 
-        165,103, 82, // 23 
-        127, 31,  0, // 24 
-        127, 79, 63, // 25 
-         76, 19,  0, // 26 
-         76, 47, 38, // 27 
-         38,  9,  0, // 28 
-         38, 23, 19, // 29 
-        255,127,  0, // 30 
-        255,191,127, // 31 
-        165, 82,  0, // 32 
-        165,124, 82, // 33 
-        127, 63,  0, // 34 
-        127, 95, 63, // 35 
-         76, 38,  0, // 36 
-         76, 57, 38, // 37 
-         38, 19,  0, // 38 
-         38, 28, 19, // 39 
-        255,191,  0, // 40 
-        255,223,127, // 41 
-        165,124,  0, // 42 
-        165,145, 82, // 43 
-        127, 95,  0, // 44 
-        127,111, 63, // 45 
-         76, 57,  0, // 46 
-         76, 66, 38, // 47 
-         38, 28,  0, // 48 
-         38, 33, 19, // 49 
-        255,255,  0, // 50 
-        255,255,127, // 51 
-        165,165,  0, // 52 
-        165,165, 82, // 53 
-        127,127,  0, // 54 
-        127,127, 63, // 55 
-         76, 76,  0, // 56 
-         76, 76, 38, // 57 
-         38, 38,  0, // 58 
-         38, 38, 19, // 59 
-        191,255,  0, // 60 
-        223,255,127, // 61 
-        124,165,  0, // 62 
-        145,165, 82, // 63 
-         95,127,  0, // 64 
-        111,127, 63, // 65 
-         57, 76,  0, // 66 
-         66, 76, 38, // 67 
-         28, 38,  0, // 68 
-         33, 38, 19, // 69 
-        127,255,  0, // 70 
-        191,255,127, // 71 
-         82,165,  0, // 72 
-        124,165, 82, // 73 
-         63,127,  0, // 74 
-         95,127, 63, // 75 
-         38, 76,  0, // 76 
-         57, 76, 38, // 77 
-         19, 38,  0, // 78 
-         28, 38, 19, // 79 
-         63,255,  0, // 80 
-        159,255,127, // 81 
-         41,165,  0, // 82 
-        103,165, 82, // 83 
-         31,127,  0, // 84 
-         79,127, 63, // 85 
-         19, 76,  0, // 86 
-         47, 76, 38, // 87 
-          9, 38,  0, // 88 
-         23, 38, 19, // 89 
-          0,255,  0, // 90 
-        127,255,127, // 91 
-          0,165,  0, // 92 
-         82,165, 82, // 93 
-          0,127,  0, // 94 
-         63,127, 63, // 95 
-          0, 76,  0, // 96 
-         38, 76, 38, // 97 
-          0, 38,  0, // 98 
-         19, 38, 19, // 99 
-          0,255, 63, // 100 
-        127,255,159, // 101 
-          0,165, 41, // 102 
-         82,165,103, // 103 
-          0,127, 31, // 104 
-        63,127, 79, // 105 
-        0, 76, 19, // 106 
-        38, 76, 47, // 107 
-        0, 38,  9, // 108 
-        19, 38, 23, // 109 
-        0,255,127, // 110 
-        127,255,191, // 111 
-        0,165, 82, // 112 
-        82,165,124, // 113 
-        0,127, 63, // 114 
-        63,127, 95, // 115 
-        0, 76, 38, // 116 
-        38, 76, 57, // 117 
-        0, 38, 19, // 118 
-        19, 38, 28, // 119 
-        0,255,191, // 120 
-        127,255,223, // 121 
-        0,165,124, // 122 
-        82,165,145, // 123 
-        0,127, 95, // 124 
-        63,127,111, // 125 
-        0, 76, 57, // 126 
-        38, 76, 66, // 127 
-        0, 38, 28, // 128 
-        19, 38, 33, // 129 
-        0,255,255, // 130 
-        127,255,255, // 131 
-        0,165,165, // 132 
-        82,165,165, // 133 
-        0,127,127, // 134 
-        63,127,127, // 135 
-        0, 76, 76, // 136 
-        38, 76, 76, // 137 
-        0, 38, 38, // 138 
-        19, 38, 38, // 139 
-        0,191,255, // 140 
-        127,223,255, // 141 
-        0,124,165, // 142 
-        82,145,165, // 143 
-        0, 95,127, // 144 
-        63,111,127, // 145 
-        0, 57, 76, // 146 
-        38, 66, 76, // 147 
-        0, 28, 38, // 148 
-        19, 33, 38, // 149 
-        0,127,255, // 150 
-        127,191,255, // 151 
-        0, 82,165, // 152 
-        82,124,165, // 153 
-        0, 63,127, // 154 
-        63, 95,127, // 155 
-        0, 38, 76, // 156 
-        38, 57, 76, // 157 
-        0, 19, 38, // 158 
-        19, 28, 38, // 159 
-        0, 63,255, // 160 
-        127,159,255, // 161 
-        0, 41,165, // 162 
-        82,103,165, // 163 
-        0, 31,127, // 164 
-        63, 79,127, // 165 
-        0, 19, 76, // 166 
-        38, 47, 76, // 167 
-        0,  9, 38, // 168 
-        19, 23, 38, // 169 
-        0,  0,255, // 170 
-        127,127,255, // 171 
-        0,  0,165, // 172 
-        82, 82,165, // 173 
-        0,  0,127, // 174 
-        63, 63,127, // 175 
-        0,  0, 76, // 176 
-        38, 38, 76, // 177 
-        0,  0, 38, // 178 
-        19, 19, 38, // 179 
-        63,  0,255, // 180 
-        159,127,255, // 181 
-        41,  0,165, // 182 
-        103, 82,165, // 183 
-        31,  0,127, // 184 
-        79, 63,127, // 185 
-        19,  0, 76, // 186 
-        47, 38, 76, // 187 
-        9,  0, 38, // 188 
-        23, 19, 38, // 189 
-        127,  0,255, // 190 
-        191,127,255, // 191 
-        82,  0,165, // 192 
-        124, 82,165, // 193 
-        63,  0,127, // 194 
-        95, 63,127, // 195 
-        38,  0, 76, // 196 
-        57, 38, 76, // 197 
-        19,  0, 38, // 198 
-        28, 19, 38, // 199 
-        191,  0,255, // 200 
-        223,127,255, // 201 
-        124,  0,165, // 202 
-        145, 82,165, // 203 
-        95,  0,127, // 204 
-        111, 63,127, // 205 
-        57,  0, 76, // 206 
-        66, 38, 76, // 207 
-        28,  0, 38, // 208 
-        33, 19, 38, // 209 
-        255,  0,255, // 210 
-        255,127,255, // 211 
-        165,  0,165, // 212 
-        165, 82,165, // 213 
-        127,  0,127, // 214 
-        127, 63,127, // 215 
-        76,  0, 76, // 216 
-        76, 38, 76, // 217 
-        38,  0, 38, // 218 
-        38, 19, 38, // 219 
-        255,  0,191, // 220 
-        255,127,223, // 221 
-        165,  0,124, // 222 
-        165, 82,145, // 223 
-        127,  0, 95, // 224 
-        127, 63,111, // 225 
-        76,  0, 57, // 226 
-        76, 38, 66, // 227 
-        38,  0, 28, // 228 
-        38, 19, 33, // 229 
-        255,  0,127, // 230 
-        255,127,191, // 231 
-        165,  0, 82, // 232 
-        165, 82,124, // 233 
-        127,  0, 63, // 234 
-        127, 63, 95, // 235 
-        76,  0, 38, // 236 
-        76, 38, 57, // 237 
-        38,  0, 19, // 238 
-        38, 19, 28, // 239 
-        255,  0, 63, // 240 
-        255,127,159, // 241 
-        165,  0, 41, // 242 
-        165, 82,103, // 243 
-        127,  0, 31, // 244 
-        127, 63, 79, // 245 
-        76,  0, 19, // 246 
-        76, 38, 47, // 247 
-        38,  0,  9, // 248 
-        38, 19, 23, // 249 
-        84, 84, 84, // 250 
-        118,118,118, // 251 
-        152,152,152, // 252 
-        186,186,186, // 253 
-        220,220,220, // 254 
-        255,255,255  // 255 
+        127,127,127, // 8
+        191,191,191, // 9
+        255,  0,  0, // 10
+        255,127,127, // 11
+        165,  0,  0, // 12
+        165, 82, 82, // 13
+        127,  0,  0, // 14
+        127, 63, 63, // 15
+         76,  0,  0, // 16
+         76, 38, 38, // 17
+         38,  0,  0, // 18
+         38, 19, 19, // 19
+        255, 63,  0, // 20
+        255,159,127, // 21
+        165, 41,  0, // 22
+        165,103, 82, // 23
+        127, 31,  0, // 24
+        127, 79, 63, // 25
+         76, 19,  0, // 26
+         76, 47, 38, // 27
+         38,  9,  0, // 28
+         38, 23, 19, // 29
+        255,127,  0, // 30
+        255,191,127, // 31
+        165, 82,  0, // 32
+        165,124, 82, // 33
+        127, 63,  0, // 34
+        127, 95, 63, // 35
+         76, 38,  0, // 36
+         76, 57, 38, // 37
+         38, 19,  0, // 38
+         38, 28, 19, // 39
+        255,191,  0, // 40
+        255,223,127, // 41
+        165,124,  0, // 42
+        165,145, 82, // 43
+        127, 95,  0, // 44
+        127,111, 63, // 45
+         76, 57,  0, // 46
+         76, 66, 38, // 47
+         38, 28,  0, // 48
+         38, 33, 19, // 49
+        255,255,  0, // 50
+        255,255,127, // 51
+        165,165,  0, // 52
+        165,165, 82, // 53
+        127,127,  0, // 54
+        127,127, 63, // 55
+         76, 76,  0, // 56
+         76, 76, 38, // 57
+         38, 38,  0, // 58
+         38, 38, 19, // 59
+        191,255,  0, // 60
+        223,255,127, // 61
+        124,165,  0, // 62
+        145,165, 82, // 63
+         95,127,  0, // 64
+        111,127, 63, // 65
+         57, 76,  0, // 66
+         66, 76, 38, // 67
+         28, 38,  0, // 68
+         33, 38, 19, // 69
+        127,255,  0, // 70
+        191,255,127, // 71
+         82,165,  0, // 72
+        124,165, 82, // 73
+         63,127,  0, // 74
+         95,127, 63, // 75
+         38, 76,  0, // 76
+         57, 76, 38, // 77
+         19, 38,  0, // 78
+         28, 38, 19, // 79
+         63,255,  0, // 80
+        159,255,127, // 81
+         41,165,  0, // 82
+        103,165, 82, // 83
+         31,127,  0, // 84
+         79,127, 63, // 85
+         19, 76,  0, // 86
+         47, 76, 38, // 87
+          9, 38,  0, // 88
+         23, 38, 19, // 89
+          0,255,  0, // 90
+        127,255,127, // 91
+          0,165,  0, // 92
+         82,165, 82, // 93
+          0,127,  0, // 94
+         63,127, 63, // 95
+          0, 76,  0, // 96
+         38, 76, 38, // 97
+          0, 38,  0, // 98
+         19, 38, 19, // 99
+          0,255, 63, // 100
+        127,255,159, // 101
+          0,165, 41, // 102
+         82,165,103, // 103
+          0,127, 31, // 104
+        63,127, 79, // 105
+        0, 76, 19, // 106
+        38, 76, 47, // 107
+        0, 38,  9, // 108
+        19, 38, 23, // 109
+        0,255,127, // 110
+        127,255,191, // 111
+        0,165, 82, // 112
+        82,165,124, // 113
+        0,127, 63, // 114
+        63,127, 95, // 115
+        0, 76, 38, // 116
+        38, 76, 57, // 117
+        0, 38, 19, // 118
+        19, 38, 28, // 119
+        0,255,191, // 120
+        127,255,223, // 121
+        0,165,124, // 122
+        82,165,145, // 123
+        0,127, 95, // 124
+        63,127,111, // 125
+        0, 76, 57, // 126
+        38, 76, 66, // 127
+        0, 38, 28, // 128
+        19, 38, 33, // 129
+        0,255,255, // 130
+        127,255,255, // 131
+        0,165,165, // 132
+        82,165,165, // 133
+        0,127,127, // 134
+        63,127,127, // 135
+        0, 76, 76, // 136
+        38, 76, 76, // 137
+        0, 38, 38, // 138
+        19, 38, 38, // 139
+        0,191,255, // 140
+        127,223,255, // 141
+        0,124,165, // 142
+        82,145,165, // 143
+        0, 95,127, // 144
+        63,111,127, // 145
+        0, 57, 76, // 146
+        38, 66, 76, // 147
+        0, 28, 38, // 148
+        19, 33, 38, // 149
+        0,127,255, // 150
+        127,191,255, // 151
+        0, 82,165, // 152
+        82,124,165, // 153
+        0, 63,127, // 154
+        63, 95,127, // 155
+        0, 38, 76, // 156
+        38, 57, 76, // 157
+        0, 19, 38, // 158
+        19, 28, 38, // 159
+        0, 63,255, // 160
+        127,159,255, // 161
+        0, 41,165, // 162
+        82,103,165, // 163
+        0, 31,127, // 164
+        63, 79,127, // 165
+        0, 19, 76, // 166
+        38, 47, 76, // 167
+        0,  9, 38, // 168
+        19, 23, 38, // 169
+        0,  0,255, // 170
+        127,127,255, // 171
+        0,  0,165, // 172
+        82, 82,165, // 173
+        0,  0,127, // 174
+        63, 63,127, // 175
+        0,  0, 76, // 176
+        38, 38, 76, // 177
+        0,  0, 38, // 178
+        19, 19, 38, // 179
+        63,  0,255, // 180
+        159,127,255, // 181
+        41,  0,165, // 182
+        103, 82,165, // 183
+        31,  0,127, // 184
+        79, 63,127, // 185
+        19,  0, 76, // 186
+        47, 38, 76, // 187
+        9,  0, 38, // 188
+        23, 19, 38, // 189
+        127,  0,255, // 190
+        191,127,255, // 191
+        82,  0,165, // 192
+        124, 82,165, // 193
+        63,  0,127, // 194
+        95, 63,127, // 195
+        38,  0, 76, // 196
+        57, 38, 76, // 197
+        19,  0, 38, // 198
+        28, 19, 38, // 199
+        191,  0,255, // 200
+        223,127,255, // 201
+        124,  0,165, // 202
+        145, 82,165, // 203
+        95,  0,127, // 204
+        111, 63,127, // 205
+        57,  0, 76, // 206
+        66, 38, 76, // 207
+        28,  0, 38, // 208
+        33, 19, 38, // 209
+        255,  0,255, // 210
+        255,127,255, // 211
+        165,  0,165, // 212
+        165, 82,165, // 213
+        127,  0,127, // 214
+        127, 63,127, // 215
+        76,  0, 76, // 216
+        76, 38, 76, // 217
+        38,  0, 38, // 218
+        38, 19, 38, // 219
+        255,  0,191, // 220
+        255,127,223, // 221
+        165,  0,124, // 222
+        165, 82,145, // 223
+        127,  0, 95, // 224
+        127, 63,111, // 225
+        76,  0, 57, // 226
+        76, 38, 66, // 227
+        38,  0, 28, // 228
+        38, 19, 33, // 229
+        255,  0,127, // 230
+        255,127,191, // 231
+        165,  0, 82, // 232
+        165, 82,124, // 233
+        127,  0, 63, // 234
+        127, 63, 95, // 235
+        76,  0, 38, // 236
+        76, 38, 57, // 237
+        38,  0, 19, // 238
+        38, 19, 28, // 239
+        255,  0, 63, // 240
+        255,127,159, // 241
+        165,  0, 41, // 242
+        165, 82,103, // 243
+        127,  0, 31, // 244
+        127, 63, 79, // 245
+        76,  0, 19, // 246
+        76, 38, 47, // 247
+        38,  0,  9, // 248
+        38, 19, 23, // 249
+        84, 84, 84, // 250
+        118,118,118, // 251
+        152,152,152, // 252
+        186,186,186, // 253
+        220,220,220, // 254
+        255,255,255  // 255
     };
 
     return abyDXFColors;
@@ -458,7 +454,7 @@ void ACAdjustText( double dfAngle, double dfScale, OGRFeature *poFeature )
 
         osPreAngle.assign( osOldStyle, 0, nAngleOff );
         osPostAngle.assign( osOldStyle, nEndOfAngleOff, std::string::npos );
-        
+
         dfOldAngle = CPLAtof( osOldStyle.c_str() + nAngleOff + 3 );
     }
     else
@@ -473,8 +469,8 @@ void ACAdjustText( double dfAngle, double dfScale, OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
     CPLString osNewStyle;
 
-    osNewStyle.Printf( "%s,a:%g%s", 
-                       osPreAngle.c_str(), 
+    osNewStyle.Printf( "%s,a:%g%s",
+                       osPreAngle.c_str(),
                        dfOldAngle + dfAngle,
                        osPostAngle.c_str() );
 
@@ -486,7 +482,7 @@ void ACAdjustText( double dfAngle, double dfScale, OGRFeature *poFeature )
     double dfOldScale = 1.0;
     CPLString osPreScale, osPostScale;
     size_t nScaleOff = osOldStyle.find( ",s:" );
-    
+
     if( nScaleOff != std::string::npos )
     {
         size_t nEndOfScaleOff = osOldStyle.find( ",", nScaleOff + 1 );
@@ -496,7 +492,7 @@ void ACAdjustText( double dfAngle, double dfScale, OGRFeature *poFeature )
 
         osPreScale.assign( osOldStyle, 0, nScaleOff );
         osPostScale.assign( osOldStyle, nEndOfScaleOff, std::string::npos );
-        
+
         dfOldScale = CPLAtof( osOldStyle.c_str() + nScaleOff + 3 );
     }
     else
@@ -509,11 +505,10 @@ void ACAdjustText( double dfAngle, double dfScale, OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
 /*      Format with the new scale.                                      */
 /* -------------------------------------------------------------------- */
-    osNewStyle.Printf( "%s,s:%gg%s", 
-                       osPreScale.c_str(), 
+    osNewStyle.Printf( "%s,s:%gg%s",
+                       osPreScale.c_str(),
                        dfOldScale * dfScale,
                        osPostScale.c_str() );
 
     poFeature->SetStyleString( osNewStyle );
 }
-
diff --git a/ogr/ogrsf_frmts/dxf/ogr_autocad_services.h b/ogr/ogrsf_frmts/dxf/ogr_autocad_services.h
index a557a65..3da6690 100644
--- a/ogr/ogrsf_frmts/dxf/ogr_autocad_services.h
+++ b/ogr/ogrsf_frmts/dxf/ogr_autocad_services.h
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_AUTOCAD_SERVICES_H_INCLUDED
-#define _OGR_AUTOCAD_SERVICES_H_INCLUDED
+#ifndef OGR_AUTOCAD_SERVICES_H_INCLUDED
+#define OGR_AUTOCAD_SERVICES_H_INCLUDED
 
 #include "cpl_conv.h"
 #include "cpl_string.h"
@@ -44,4 +44,4 @@ const unsigned char *ACGetColorTable( void );
 
 void ACAdjustText( double dfAngle, double dfScale, OGRFeature *poFeature );
 
-#endif /* ndef _OGR_AUTOCAD_SERVICES_H_INCLUDED */
+#endif /* ndef OGR_AUTOCAD_SERVICES_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/dxf/ogr_dxf.h b/ogr/ogrsf_frmts/dxf/ogr_dxf.h
index 187fc54..e4ddd4f 100644
--- a/ogr/ogrsf_frmts/dxf/ogr_dxf.h
+++ b/ogr/ogrsf_frmts/dxf/ogr_dxf.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_dxf.h 27959 2014-11-14 18:29:21Z rouault $
+ * $Id: ogr_dxf.h 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  DXF Translator
  * Purpose:  Definition of classes for OGR .dxf driver.
@@ -28,8 +28,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_DXF_H_INCLUDED
-#define _OGR_DXF_H_INCLUDED
+#ifndef OGR_DXF_H_INCLUDED
+#define OGR_DXF_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "ogr_autocad_services.h"
@@ -66,9 +66,9 @@ class OGRDXFBlocksLayer : public OGRLayer
     OGRDXFDataSource   *poDS;
 
     OGRFeatureDefn     *poFeatureDefn;
-    
-    int                 iNextFID;
-    unsigned int        iNextSubFeature;
+
+    GIntBig             iNextFID;
+    size_t              iNextSubFeature;
 
     std::map<CPLString,DXFBlockDefinition>::iterator oIt;
 
@@ -94,7 +94,7 @@ class OGRDXFLayer : public OGRLayer
     OGRDXFDataSource   *poDS;
 
     OGRFeatureDefn     *poFeatureDefn;
-    int                 iNextFID;
+    GIntBig             iNextFID;
 
     std::set<CPLString> oIgnoredEntities;
 
@@ -102,8 +102,8 @@ class OGRDXFLayer : public OGRLayer
     void                ClearPendingFeatures();
 
     std::map<CPLString,CPLString> oStyleProperties;
-    
-    void                TranslateGenericProperty( OGRFeature *poFeature, 
+
+    void                TranslateGenericProperty( OGRFeature *poFeature,
                                                   int nCode, char *pszValue );
     void                PrepareLineStyle( OGRFeature *poFeature );
     void                ApplyOCSTransformer( OGRGeometry * );
@@ -150,14 +150,21 @@ class OGRDXFLayer : public OGRLayer
 /*      A class for very low level DXF reading without interpretation.  */
 /************************************************************************/
 
+#define DXF_READER_ERROR()\
+    do { CPLError(CE_Failure, CPLE_AppDefined, "%s, %d: error at line %d of %s", \
+         __FILE__, __LINE__, GetLineNumber(), GetName()); } while(0)
+#define DXF_LAYER_READER_ERROR()\
+    do { CPLError(CE_Failure, CPLE_AppDefined, "%s, %d: error at line %d of %s", \
+         __FILE__, __LINE__, poDS->GetLineNumber(), poDS->GetName()); } while(0)
+
 class OGRDXFReader
 {
 public:
     OGRDXFReader();
     ~OGRDXFReader();
-    
+
     void                Initialize( VSILFILE * fp );
-    
+
     VSILFILE           *fp;
 
     int                 iSrcBufferOffset;
@@ -168,7 +175,7 @@ public:
     int                 nLastValueSize;
     int                 nLineNumber;
 
-    int                 ReadValue( char *pszValueBuffer, 
+    int                 ReadValue( char *pszValueBuffer,
                                    int nValueBufferSize = 81 );
     void                UnreadValue();
     void                LoadDiskChunk();
@@ -195,7 +202,7 @@ class OGRDXFDataSource : public OGRDataSource
     CPLString           osEncoding;
 
     // indexed by layer name, then by property name.
-    std::map< CPLString, std::map<CPLString,CPLString> > 
+    std::map< CPLString, std::map<CPLString,CPLString> >
                         oLayerTable;
 
     std::map<CPLString,CPLString> oLineTypeTable;
@@ -212,7 +219,7 @@ class OGRDXFDataSource : public OGRDataSource
 
     const char          *GetName() { return osName; }
 
-    int                 GetLayerCount() { return apoLayers.size(); }
+    int                 GetLayerCount() { return static_cast<int>(apoLayers.size()); }
     OGRLayer            *GetLayer( int );
 
     int                 TestCapability( const char * );
@@ -223,30 +230,31 @@ class OGRDXFDataSource : public OGRDataSource
     void                AddStandardFields( OGRFeatureDefn *poDef );
 
     // Implemented in ogrdxf_blockmap.cpp
-    void                ReadBlocksSection();
+    bool                ReadBlocksSection();
     OGRGeometry        *SimplifyBlockGeometry( OGRGeometryCollection * );
     DXFBlockDefinition *LookupBlock( const char *pszName );
     std::map<CPLString,DXFBlockDefinition> &GetBlockMap() { return oBlockMap; }
 
     // Layer and other Table Handling (ogrdatasource.cpp)
-    void                ReadTablesSection();
-    void                ReadLayerDefinition();
-    void                ReadLineTypeDefinition();
-    const char         *LookupLayerProperty( const char *pszLayer, 
+    bool                ReadTablesSection();
+    bool                ReadLayerDefinition();
+    bool                ReadLineTypeDefinition();
+    const char         *LookupLayerProperty( const char *pszLayer,
                                              const char *pszProperty );
     const char         *LookupLineType( const char *pszName );
 
-    // Header variables. 
-    void                ReadHeaderSection();
-    const char         *GetVariable(const char *pszName, 
+    // Header variables.
+    bool               ReadHeaderSection();
+    const char         *GetVariable(const char *pszName,
                                     const char *pszDefault=NULL );
 
     const char         *GetEncoding() { return osEncoding; }
 
     // reader related.
+    int  GetLineNumber() { return oReader.nLineNumber; }
     int  ReadValue( char *pszValueBuffer, int nValueBufferSize = 81 )
         { return oReader.ReadValue( pszValueBuffer, nValueBufferSize ); }
-    void RestartEntities() 
+    void RestartEntities()
         { oReader.ResetReadPointer(iEntitiesSectionOffset); }
     void UnreadValue()
         { oReader.UnreadValue(); }
@@ -338,7 +346,7 @@ class OGRDXFBlocksWriterLayer : public OGRLayer
 class OGRDXFWriterDS : public OGRDataSource
 {
     friend class OGRDXFWriterLayer;
-    
+
     int                 nNextFID;
 
     CPLString           osName;
@@ -377,9 +385,9 @@ class OGRDXFWriterDS : public OGRDataSource
                         OGRDXFWriterDS();
                         ~OGRDXFWriterDS();
 
-    int                 Open( const char * pszFilename, 
+    int                 Open( const char * pszFilename,
                               char **papszOptions );
-    
+
     const char          *GetName() { return osName; }
 
     int                 GetLayerCount();
@@ -387,7 +395,7 @@ class OGRDXFWriterDS : public OGRDataSource
 
     int                 TestCapability( const char * );
 
-    OGRLayer           *ICreateLayer( const char *pszName, 
+    OGRLayer           *ICreateLayer( const char *pszName,
                                      OGRSpatialReference *poSpatialRef = NULL,
                                      OGRwkbGeometryType eGType = wkbUnknown,
                                      char ** papszOptions = NULL );
@@ -399,4 +407,4 @@ class OGRDXFWriterDS : public OGRDataSource
     void                UpdateExtent( OGREnvelope* psEnvelope );
 };
 
-#endif /* ndef _OGR_DXF_H_INCLUDED */
+#endif /* ndef OGR_DXF_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxf_blockmap.cpp b/ogr/ogrsf_frmts/dxf/ogrdxf_blockmap.cpp
index 84b8cd8..b4355f6 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxf_blockmap.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxf_blockmap.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: ogrdxf_blockmap.cpp 23668 2011-12-30 21:44:47Z rouault $
+ * $Id: ogrdxf_blockmap.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  DXF Translator
- * Purpose:  Implements BlockMap reading and management portion of 
+ * Purpose:  Implements BlockMap reading and management portion of
  *           OGRDXFDataSource class
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -33,31 +33,31 @@
 #include "cpl_string.h"
 #include "cpl_csv.h"
 
-CPL_CVSID("$Id: ogrdxf_blockmap.cpp 23668 2011-12-30 21:44:47Z rouault $");
+CPL_CVSID("$Id: ogrdxf_blockmap.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                          ReadBlockSection()                          */
 /************************************************************************/
 
-void OGRDXFDataSource::ReadBlocksSection()
+bool OGRDXFDataSource::ReadBlocksSection()
 
 {
     char szLineBuf[257];
     int  nCode;
     OGRDXFLayer *poReaderLayer = (OGRDXFLayer *) GetLayerByName( "Entities" );
-    int bMergeBlockGeometries = CSLTestBoolean(
+    int bMergeBlockGeometries = CPLTestBool(
         CPLGetConfigOption( "DXF_MERGE_BLOCK_GEOMETRIES", "TRUE" ) );
 
     iEntitiesSectionOffset = oReader.iSrcBufferFileOffset + oReader.iSrcBufferOffset;
 
-    while( (nCode = ReadValue( szLineBuf, sizeof(szLineBuf) )) > -1 
+    while( (nCode = ReadValue( szLineBuf, sizeof(szLineBuf) )) > -1
            && !EQUAL(szLineBuf,"ENDSEC") )
     {
         // We are only interested in extracting blocks.
         if( nCode != 0 || !EQUAL(szLineBuf,"BLOCK") )
             continue;
 
-        // Process contents of BLOCK definition till we find the 
+        // Process contents of BLOCK definition till we find the
         // first entity.
         CPLString osBlockName;
 
@@ -66,7 +66,12 @@ void OGRDXFDataSource::ReadBlocksSection()
             if( nCode == 2 )
                 osBlockName = szLineBuf;
 
-            // anything else we want? 
+            // anything else we want?
+        }
+        if( nCode < 0 )
+        {
+            DXF_READER_ERROR();
+            return false;
         }
 
         if( EQUAL(szLineBuf,"ENDBLK") )
@@ -106,16 +111,22 @@ void OGRDXFDataSource::ReadBlocksSection()
         if( apoFeatures.size() > 0 )
             oBlockMap[osBlockName].apoFeatures = apoFeatures;
     }
+    if( nCode < 0 )
+    {
+        DXF_READER_ERROR();
+        return false;
+    }
 
-    CPLDebug( "DXF", "Read %d blocks with meaningful geometry.", 
+    CPLDebug( "DXF", "Read %d blocks with meaningful geometry.",
               (int) oBlockMap.size() );
+    return true;
 }
 
 /************************************************************************/
 /*                       SimplifyBlockGeometry()                        */
 /************************************************************************/
 
-OGRGeometry *OGRDXFDataSource::SimplifyBlockGeometry( 
+OGRGeometry *OGRDXFDataSource::SimplifyBlockGeometry(
     OGRGeometryCollection *poCollection )
 
 {
@@ -136,7 +147,7 @@ OGRGeometry *OGRDXFDataSource::SimplifyBlockGeometry(
 /*      polygon, multipolygon, multilinestring or multipoint but        */
 /*      I'll put that off till it would be meaningful.                  */
 /* -------------------------------------------------------------------- */
-    
+
     return poCollection;
 }
 
@@ -152,12 +163,12 @@ OGRGeometry *OGRDXFDataSource::SimplifyBlockGeometry(
 DXFBlockDefinition *OGRDXFDataSource::LookupBlock( const char *pszName )
 
 {
-    CPLString osName = pszName;
+    CPLString l_osName = pszName;
 
-    if( oBlockMap.count( osName ) == 0 )
+    if( oBlockMap.count( l_osName ) == 0 )
         return NULL;
     else
-        return &(oBlockMap[osName]);
+        return &(oBlockMap[l_osName]);
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxf_dimension.cpp b/ogr/ogrsf_frmts/dxf/ogrdxf_dimension.cpp
index 717bd5d..7ccca55 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxf_dimension.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxf_dimension.cpp
@@ -1,9 +1,9 @@
 /******************************************************************************
- * $Id: ogrdxf_dimension.cpp 28039 2014-11-30 18:24:59Z rouault $
+ * $Id: ogrdxf_dimension.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  DXF Translator
  * Purpose:  Implements translation support for DIMENSION elements as a part
- *           of the OGRDXFLayer class.  
+ *           of the OGRDXFLayer class.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -32,11 +32,7 @@
 #include "ogr_dxf.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrdxf_dimension.cpp 28039 2014-11-30 18:24:59Z rouault $");
-
-#ifndef PI
-#define PI  3.14159265358979323846
-#endif
+CPL_CVSID("$Id: ogrdxf_dimension.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                         TranslateDIMENSION()                         */
@@ -128,7 +124,7 @@ OGRFeature *OGRDXFLayer::TranslateDIMENSION()
 
 /*************************************************************************
 
-   DIMENSION geometry layout 
+   DIMENSION geometry layout
 
                   (11,21)(text center point)
         |          DimText                  |
@@ -142,14 +138,14 @@ OGRFeature *OGRDXFLayer::TranslateDIMENSION()
 
 Given:
   Locations Arrow1, Target1, and Target2 we need to compute Arrow2.
- 
+
 Steps:
  1) Compute direction vector from Target1 to Arrow1 (Vec1).
  2) Compute direction vector for arrow as perpendicular to Vec1 (call Vec2).
- 3) Compute Arrow2 location as intersection between line defined by 
+ 3) Compute Arrow2 location as intersection between line defined by
     Vec2 and Arrow1 and line defined by Target2 and direction Vec1 (call Arrow2)
 
-Then we can draw lines for the various components.  
+Then we can draw lines for the various components.
 
 Note that Vec1 and Vec2 may be horizontal, vertical or on an angle but
 the approach is as above in all these cases.
@@ -157,7 +153,7 @@ the approach is as above in all these cases.
 *************************************************************************/
 
     ;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Step 1, compute direction vector between Target1 and Arrow1.    */
 /* -------------------------------------------------------------------- */
@@ -165,13 +161,13 @@ the approach is as above in all these cases.
 
     dfVec1X = (dfArrowX1 - dfTargetX1);
     dfVec1Y = (dfArrowY1 - dfTargetY1);
-    
+
 /* -------------------------------------------------------------------- */
 /*      Step 2, compute the direction vector from Arrow1 to Arrow2      */
-/*      as a perpendicluar to Vec1.                                     */
+/*      as a perpendicular to Vec1.                                     */
 /* -------------------------------------------------------------------- */
     double dfVec2X, dfVec2Y;
-    
+
     dfVec2X = dfVec1Y;
     dfVec2Y = -dfVec1X;
 
@@ -182,7 +178,7 @@ the approach is as above in all these cases.
 /* -------------------------------------------------------------------- */
     double dfL1M, dfL1B, dfL2M, dfL2B;
     double dfArrowX2, dfArrowY2;
-    
+
     // special case if vec1 is vertical.
     if( dfVec1X == 0.0 )
     {
@@ -205,12 +201,12 @@ the approach is as above in all these cases.
         dfL1B = dfTargetY2 - dfL1M * dfTargetX2;
 
         // convert vec2 + Arrow1 into y = mx + b format, call this L2
-        
+
         dfL2M = dfVec2Y / dfVec2X;
         dfL2B = dfArrowY1 - dfL2M * dfArrowX1;
-        
+
         // Compute intersection x = (b2-b1) / (m1-m2)
-        
+
         dfArrowX2 = (dfL2B - dfL1B) / (dfL1M-dfL2M);
         dfArrowY2 = dfL2M * dfArrowX2 + dfL2B;
     }
@@ -218,7 +214,7 @@ the approach is as above in all these cases.
 /* -------------------------------------------------------------------- */
 /*      Compute the text angle.                                         */
 /* -------------------------------------------------------------------- */
-    dfAngle = atan2(dfVec2Y,dfVec2X) * 180.0 / PI;
+    dfAngle = atan2(dfVec2Y,dfVec2X) * 180.0 / M_PI;
 
 /* -------------------------------------------------------------------- */
 /*      Rescale the direction vectors so we can use them in             */
@@ -241,7 +237,7 @@ the approach is as above in all these cases.
     dfScaleFactor = dfTargetLength / VECTOR_LEN(dfVec1X,dfVec1Y);
     dfVec1X *= dfScaleFactor;
     dfVec1Y *= dfScaleFactor;
-    
+
     // vector 2
     dfScaleFactor = dfTargetLength / VECTOR_LEN(dfVec2X,dfVec2Y);
     dfVec2X *= dfScaleFactor;
@@ -263,7 +259,7 @@ the approach is as above in all these cases.
     oLine.setPoint( 0, dfTargetX1, dfTargetY1 );
     oLine.setPoint( 1, dfArrowX1 + dfVec1X, dfArrowY1 + dfVec1Y );
     poMLS->addGeometry( &oLine );
-    
+
     // dimension line from Target2 to Arrow2 with a small extension.
     oLine.setPoint( 0, dfTargetX2, dfTargetY2 );
     oLine.setPoint( 1, dfArrowX2 + dfVec1X, dfArrowY2 + dfVec1Y );
@@ -272,13 +268,13 @@ the approach is as above in all these cases.
     // add arrow1 arrow head.
 
     oLine.setPoint( 0, dfArrowX1, dfArrowY1 );
-    oLine.setPoint( 1, 
+    oLine.setPoint( 1,
                     dfArrowX1 + dfVec2X*3 + dfVec1X,
                     dfArrowY1 + dfVec2Y*3 + dfVec1Y );
     poMLS->addGeometry( &oLine );
 
     oLine.setPoint( 0, dfArrowX1, dfArrowY1 );
-    oLine.setPoint( 1, 
+    oLine.setPoint( 1,
                     dfArrowX1 + dfVec2X*3 - dfVec1X,
                     dfArrowY1 + dfVec2Y*3 - dfVec1Y );
     poMLS->addGeometry( &oLine );
@@ -286,13 +282,13 @@ the approach is as above in all these cases.
     // add arrow2 arrow head.
 
     oLine.setPoint( 0, dfArrowX2, dfArrowY2 );
-    oLine.setPoint( 1, 
+    oLine.setPoint( 1,
                     dfArrowX2 - dfVec2X*3 + dfVec1X,
                     dfArrowY2 - dfVec2Y*3 + dfVec1Y );
     poMLS->addGeometry( &oLine );
 
     oLine.setPoint( 0, dfArrowX2, dfArrowY2 );
-    oLine.setPoint( 1, 
+    oLine.setPoint( 1,
                     dfArrowX2 - dfVec2X*3 - dfVec1X,
                     dfArrowY2 - dfVec2Y*3 - dfVec1Y );
     poMLS->addGeometry( &oLine );
@@ -318,7 +314,7 @@ the approach is as above in all these cases.
     // Do we need to compute the dimension value?
     if( osText.size() == 0 )
     {
-        FormatDimension( osText, POINT_DIST( dfArrowX1, dfArrowY1, 
+        FormatDimension( osText, POINT_DIST( dfArrowX1, dfArrowY1,
                                              dfArrowX2, dfArrowY2 ) );
     }
 
@@ -366,9 +362,9 @@ void OGRDXFLayer::FormatDimension( CPLString &osText, double dfValue )
 
     // we could do a significantly more precise formatting if we want
     // to spend the effort.  See QCAD's rs_dimlinear.cpp and related files
-    // for example.  
+    // for example.
 
-    sprintf(szFormat, "%%.%df", nPrecision );
+    snprintf(szFormat, sizeof(szFormat), "%%.%df", nPrecision );
     CPLsnprintf(szBuffer, sizeof(szBuffer), szFormat, dfValue);
     osText = szBuffer;
 }
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxf_hatch.cpp b/ogr/ogrsf_frmts/dxf/ogrdxf_hatch.cpp
index ab841ac..c493228 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxf_hatch.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxf_hatch.cpp
@@ -1,9 +1,9 @@
 /******************************************************************************
- * $Id: ogrdxf_hatch.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogrdxf_hatch.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  DXF Translator
  * Purpose:  Implements translation support for HATCH elements as part
- *           of the OGRDXFLayer class.  
+ *           of the OGRDXFLayer class.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -35,11 +35,7 @@
 
 #include "ogrdxf_polyline_smooth.h"
 
-CPL_CVSID("$Id: ogrdxf_hatch.cpp 27745 2014-09-27 16:38:57Z goatbar $");
-
-#ifndef PI
-#define PI  3.14159265358979323846
-#endif
+CPL_CVSID("$Id: ogrdxf_hatch.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                           TranslateHATCH()                           */
@@ -91,6 +87,12 @@ OGRFeature *OGRDXFLayer::TranslateHATCH()
             break;
         }
     }
+    if( nCode < 0 )
+    {
+        DXF_LAYER_READER_ERROR();
+        delete poFeature;
+        return NULL;
+    }
 
     if( nCode == 0 )
         poDS->UnreadValue();
@@ -127,14 +129,14 @@ OGRFeature *OGRDXFLayer::TranslateHATCH()
     if( oStyleProperties.count("Color") > 0 )
         nColor = atoi(oStyleProperties["Color"]);
 
-    // Use layer color? 
+    // Use layer color?
     if( nColor < 1 || nColor > 255 )
     {
         const char *pszValue = poDS->LookupLayerProperty( osLayer, "Color" );
         if( pszValue != NULL )
             nColor = atoi(pszValue);
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Setup the style string.                                         */
 /* -------------------------------------------------------------------- */
@@ -142,12 +144,12 @@ OGRFeature *OGRDXFLayer::TranslateHATCH()
     {
         CPLString osStyle;
         const unsigned char *pabyDXFColors = ACGetColorTable();
-        
+
         osStyle.Printf( "BRUSH(fc:#%02x%02x%02x)",
                         pabyDXFColors[nColor*3+0],
                         pabyDXFColors[nColor*3+1],
                         pabyDXFColors[nColor*3+2] );
-        
+
         poFeature->SetStyleString( osStyle );
     }
 
@@ -169,7 +171,10 @@ OGRErr OGRDXFLayer::CollectBoundaryPath( OGRGeometryCollection *poGC )
 /* -------------------------------------------------------------------- */
     nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf));
     if( nCode != 92 )
+    {
+        DXF_LAYER_READER_ERROR();
         return OGRERR_FAILURE;
+    }
 
     int  nBoundaryPathType = atoi(szLineBuf);
 
@@ -188,10 +193,13 @@ OGRErr OGRDXFLayer::CollectBoundaryPath( OGRGeometryCollection *poGC )
 /* -------------------------------------------------------------------- */
     nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf));
     if( nCode != 93 )
+    {
+        DXF_LAYER_READER_ERROR();
         return OGRERR_FAILURE;
+    }
 
     int nEdgeCount = atoi(szLineBuf);
-    
+
 /* -------------------------------------------------------------------- */
 /*      Loop reading edges.                                             */
 /* -------------------------------------------------------------------- */
@@ -209,10 +217,13 @@ OGRErr OGRDXFLayer::CollectBoundaryPath( OGRGeometryCollection *poGC )
 
         nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf));
         if( nCode != 72 )
+        {
+            DXF_LAYER_READER_ERROR();
             return OGRERR_FAILURE;
+        }
 
         int nEdgeType = atoi(szLineBuf);
-        
+
 /* -------------------------------------------------------------------- */
 /*      Process a line edge.                                            */
 /* -------------------------------------------------------------------- */
@@ -223,22 +234,22 @@ OGRErr OGRDXFLayer::CollectBoundaryPath( OGRGeometryCollection *poGC )
             double dfEndX;
             double dfEndY;
 
-            if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 10 )
+            if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 10 )
                 dfStartX = CPLAtof(szLineBuf);
             else
                 break;
 
-            if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 20 )
+            if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 20 )
                 dfStartY = CPLAtof(szLineBuf);
             else
                 break;
 
-            if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 11 )
+            if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 11 )
                 dfEndX = CPLAtof(szLineBuf);
             else
                 break;
 
-            if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 21 )
+            if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 21 )
                 dfEndY = CPLAtof(szLineBuf);
             else
                 break;
@@ -262,27 +273,27 @@ OGRErr OGRDXFLayer::CollectBoundaryPath( OGRGeometryCollection *poGC )
             double dfEndAngle;
             int    bCounterClockwise = FALSE;
 
-            if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 10 )
+            if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 10 )
                 dfCenterX = CPLAtof(szLineBuf);
             else
                 break;
 
-            if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 20 )
+            if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 20 )
                 dfCenterY = CPLAtof(szLineBuf);
             else
                 break;
 
-            if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 40 )
+            if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 40 )
                 dfRadius = CPLAtof(szLineBuf);
             else
                 break;
 
-            if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 50 )
+            if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 50 )
                 dfStartAngle = CPLAtof(szLineBuf);
             else
                 break;
 
-            if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 51 )
+            if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 51 )
                 dfEndAngle = CPLAtof(szLineBuf);
             else
                 break;
@@ -291,16 +302,18 @@ OGRErr OGRDXFLayer::CollectBoundaryPath( OGRGeometryCollection *poGC )
                 bCounterClockwise = atoi(szLineBuf);
             else if (nCode >= 0)
                 poDS->UnreadValue();
+            else
+                break;
 
             if( dfStartAngle > dfEndAngle )
                 dfEndAngle += 360.0;
             if( bCounterClockwise )
             {
-                dfStartAngle *= -1; 
-                dfEndAngle *= -1; 
+                dfStartAngle *= -1;
+                dfEndAngle *= -1;
             }
 
-            OGRGeometry *poArc = OGRGeometryFactory::approximateArcAngles( 
+            OGRGeometry *poArc = OGRGeometryFactory::approximateArcAngles(
                 dfCenterX, dfCenterY, 0.0,
                 dfRadius, dfRadius, 0.0,
                 dfStartAngle, dfEndAngle, 0.0 );
@@ -325,37 +338,37 @@ OGRErr OGRDXFLayer::CollectBoundaryPath( OGRGeometryCollection *poGC )
             double dfRatio;
             int    bCounterClockwise = FALSE;
 
-            if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 10 )
+            if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 10 )
                 dfCenterX = CPLAtof(szLineBuf);
             else
                 break;
 
-            if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 20 )
+            if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 20 )
                 dfCenterY = CPLAtof(szLineBuf);
             else
                 break;
 
-            if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 11 )
+            if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 11 )
                 dfMajorX = CPLAtof(szLineBuf);
             else
                 break;
 
-            if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 21 )
+            if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 21 )
                 dfMajorY = CPLAtof(szLineBuf);
             else
                 break;
 
-            if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 40 )
+            if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 40 )
                 dfRatio = CPLAtof(szLineBuf) / 100.0;
             else
                 break;
 
-            if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 50 )
+            if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 50 )
                 dfStartAngle = CPLAtof(szLineBuf);
             else
                 break;
 
-            if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 51 )
+            if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 51 )
                 dfEndAngle = CPLAtof(szLineBuf);
             else
                 break;
@@ -364,21 +377,23 @@ OGRErr OGRDXFLayer::CollectBoundaryPath( OGRGeometryCollection *poGC )
                 bCounterClockwise = atoi(szLineBuf);
             else if (nCode >= 0)
                 poDS->UnreadValue();
+            else
+                break;
 
             if( dfStartAngle > dfEndAngle )
                 dfEndAngle += 360.0;
             if( bCounterClockwise )
             {
-                dfStartAngle *= -1; 
-                dfEndAngle *= -1; 
+                dfStartAngle *= -1;
+                dfEndAngle *= -1;
             }
 
             dfMajorRadius = sqrt( dfMajorX * dfMajorX + dfMajorY * dfMajorY );
             dfMinorRadius = dfMajorRadius * dfRatio;
 
-            dfRotation = -1 * atan2( dfMajorY, dfMajorX ) * 180 / PI;
+            dfRotation = -1 * atan2( dfMajorY, dfMajorX ) * 180 / M_PI;
 
-            OGRGeometry *poArc = OGRGeometryFactory::approximateArcAngles( 
+            OGRGeometry *poArc = OGRGeometryFactory::approximateArcAngles(
                 dfCenterX, dfCenterY, 0.0,
                 dfMajorRadius, dfMinorRadius, dfRotation,
                 dfStartAngle, dfEndAngle, 0.0 );
@@ -395,6 +410,12 @@ OGRErr OGRDXFLayer::CollectBoundaryPath( OGRGeometryCollection *poGC )
         }
     }
 
+    if( nCode < 0 )
+    {
+        DXF_LAYER_READER_ERROR();
+        return OGRERR_FAILURE;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Skip through source boundary objects if present.                */
 /* -------------------------------------------------------------------- */
@@ -500,8 +521,13 @@ OGRErr OGRDXFLayer::CollectPolylinePath( OGRGeometryCollection *poGC )
             break;
         }
     }
+    if( nCode < 0 )
+    {
+        DXF_LAYER_READER_ERROR();
+        return OGRERR_FAILURE;
+    }
 
-    if( nCode != 10 && nCode != 20 && nCode != 42 && nCode >= 0)
+    if( nCode != 10 && nCode != 20 && nCode != 42 )
         poDS->UnreadValue();
 
     if( bHaveX && bHaveY )
@@ -510,6 +536,11 @@ OGRErr OGRDXFLayer::CollectPolylinePath( OGRGeometryCollection *poGC )
     if( bIsClosed )
         oSmoothPolyline.Close();
 
+    if(oSmoothPolyline.IsEmpty())
+    {
+        return OGRERR_FAILURE;
+    }
+
     poGC->addGeometryDirectly( oSmoothPolyline.Tesselate() );
 
 /* -------------------------------------------------------------------- */
@@ -534,5 +565,3 @@ OGRErr OGRDXFLayer::CollectPolylinePath( OGRGeometryCollection *poGC )
     }
     return OGRERR_NONE;
 }
-
-    
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.cpp b/ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.cpp
index f950d3b..01c58be 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.cpp
@@ -46,7 +46,7 @@ static double GetRadius(double bulge, double length)
 
 static double GetLength
 (
-    const DXFSmoothPolylineVertex& start, 
+    const DXFSmoothPolylineVertex& start,
     const DXFSmoothPolylineVertex& end
 )
 {
@@ -56,7 +56,7 @@ static double GetLength
 
 static double GetAngle
 (
-    const DXFSmoothPolylineVertex& start, 
+    const DXFSmoothPolylineVertex& start,
     const DXFSmoothPolylineVertex& end
 )
 {
@@ -72,6 +72,7 @@ static double GetOGRangle(double angle)
 }
 
 
+// TODO: Spelling Tesselate -> Tessellate
 /************************************************************************/
 /*                DXFSmoothPolyline::Tesselate()                        */
 /************************************************************************/
@@ -102,20 +103,20 @@ OGRGeometry* DXFSmoothPolyline::Tesselate() const
 
     m_blinestringstarted = false;
 
-    std::vector<DXFSmoothPolylineVertex>::const_iterator iter = m_vertices.begin();
-    std::vector<DXFSmoothPolylineVertex>::const_iterator eiter = m_vertices.end();
+    std::vector<DXFSmoothPolylineVertex>::const_iterator oIter = m_vertices.begin();
+    std::vector<DXFSmoothPolylineVertex>::const_iterator oEndIter = m_vertices.end();
 
-    eiter--;
+    oEndIter--;
 
-    DXFSmoothPolylineVertex begin = *iter;
+    DXFSmoothPolylineVertex begin = *oIter;
 
     double dfZ = 0.0;
     const bool bConstantZ = this->HasConstantZ(dfZ);
 
-    while(iter != eiter)
+    while(oIter != oEndIter)
     {
-        iter++;
-        DXFSmoothPolylineVertex end = *iter;
+        oIter++;
+        DXFSmoothPolylineVertex end = *oIter;
 
         const double len = GetLength(begin,end);
 
@@ -175,7 +176,7 @@ OGRGeometry* DXFSmoothPolyline::Tesselate() const
 
 void DXFSmoothPolyline::EmitArc
 (
-    const DXFSmoothPolylineVertex& start, 
+    const DXFSmoothPolylineVertex& start,
     const DXFSmoothPolylineVertex& end,
     double radius, double len, double bulge,
     OGRLineString* poLS,
@@ -203,7 +204,7 @@ void DXFSmoothPolyline::EmitArc
 /* -------------------------------------------------------------------- */
 
     const double saggita = fabs(bulge * (len / 2.0));
-    const double apo = bClockwise 
+    const double apo = bClockwise
                         ? -(ogrArcRadius - saggita)
                         : -(saggita - ogrArcRadius);
 
@@ -262,8 +263,8 @@ void DXFSmoothPolyline::EmitArc
     if(!bClockwise && (ogrArcStartAngle < ogrArcEndAngle))
         ogrArcEndAngle = -180.0 + (linedir * a);
 
-    if(bClockwise && (ogrArcStartAngle > ogrArcEndAngle)) 
-        ogrArcEndAngle += 360.0; 
+    if(bClockwise && (ogrArcStartAngle > ogrArcEndAngle))
+        ogrArcEndAngle += 360.0;
 
 /* -------------------------------------------------------------------- */
 /*      Flip arc's rotation if necessary.                               */
@@ -274,10 +275,10 @@ void DXFSmoothPolyline::EmitArc
 
 
 /* -------------------------------------------------------------------- */
-/*      Tesselate the arc segment and append to the linestring.         */
+/*      Tessellate the arc segment and append to the linestring.        */
 /* -------------------------------------------------------------------- */
 
-    OGRLineString* poArcpoLS = 
+    OGRLineString* poArcpoLS =
         (OGRLineString*)OGRGeometryFactory::approximateArcAngles(
             ogrArcCenter.x, ogrArcCenter.y, dfZ,
             ogrArcRadius, ogrArcRadius, ogrArcRotation,
@@ -297,7 +298,7 @@ void DXFSmoothPolyline::EmitArc
 
 void DXFSmoothPolyline::EmitLine
 (
-    const DXFSmoothPolylineVertex& start, 
+    const DXFSmoothPolylineVertex& start,
     const DXFSmoothPolylineVertex& end,
     OGRLineString* poLS,
     bool bConstantZ,
@@ -308,12 +309,12 @@ void DXFSmoothPolyline::EmitLine
 
     if(!m_blinestringstarted)
     {
-        poLS->addPoint(start.x, start.y, 
+        poLS->addPoint(start.x, start.y,
             bConstantZ ? dfZ : start.z);
         m_blinestringstarted = true;
     }
 
-    poLS->addPoint(end.x, end.y, 
+    poLS->addPoint(end.x, end.y,
         bConstantZ ? dfZ : end.z);
 }
 
@@ -367,4 +368,3 @@ bool DXFSmoothPolyline::HasConstantZ(double& dfZ) const
     dfZ = d;
     return true;
 }
-
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.h b/ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.h
index a785d83..09a2c21 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.h
+++ b/ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.h
@@ -29,18 +29,14 @@
  ****************************************************************************/
 
 
-#ifndef __OGRDXF_SMOOTH_POLYLINE_H__
-#define __OGRDXF_SMOOTH_POLYLINE_H__
+#ifndef OGRDXF_SMOOTH_POLYLINE_H_INCLUDED
+#define OGRDXF_SMOOTH_POLYLINE_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "cpl_conv.h"
 #include <vector>
 #include "assert.h"
 
-#ifndef M_PI
-    #define M_PI        3.14159265358979323846  /* pi */
-#endif
-
 
 class DXFSmoothPolylineVertex
 {
@@ -75,7 +71,7 @@ public:
             y *= s;
         }
 
-          
+
     double length() const
         {
             return (sqrt(x*x + y*y));
@@ -114,15 +110,11 @@ private:
     bool                                    m_bClosed;
     int										m_dim;
 
-       
 public:
-    DXFSmoothPolyline()
-        {
-            m_bClosed = false;
-            m_dim = 2;
-        }
+    DXFSmoothPolyline() : m_blinestringstarted(false), m_bClosed(false),
+                          m_dim(2) { }
 
-    OGRGeometry* Tesselate() const;
+    OGRGeometry* Tesselate() const;  // TODO: Spelling.
 
     size_t size() { return m_vertices.size(); }
 
@@ -145,12 +137,11 @@ public:
 
 private:
     void EmitArc(const DXFSmoothPolylineVertex&, const DXFSmoothPolylineVertex&,
-                 double radius, double len, double saggita, 
+                 double radius, double len, double saggita,
                  OGRLineString*, double dfZ = 0.0) const;
 
-    void EmitLine(const DXFSmoothPolylineVertex&, const DXFSmoothPolylineVertex&, 
+    void EmitLine(const DXFSmoothPolylineVertex&, const DXFSmoothPolylineVertex&,
                   OGRLineString*, bool bConstantZ, double dfZ) const;
 };
 
-#endif  /* __OGRDXF_SMOOTH_POLYLINE_H__ */
-
+#endif  /* OGRDXF_SMOOTH_POLYLINE_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxfblockslayer.cpp b/ogr/ogrsf_frmts/dxf/ogrdxfblockslayer.cpp
index 2b49535..b08b2a5 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxfblockslayer.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxfblockslayer.cpp
@@ -36,14 +36,12 @@ CPL_CVSID("$Id: ogrdxflayer.cpp 19643 2010-05-08 21:56:18Z rouault $");
 /*                         OGRDXFBlocksLayer()                          */
 /************************************************************************/
 
-OGRDXFBlocksLayer::OGRDXFBlocksLayer( OGRDXFDataSource *poDS )
-
+OGRDXFBlocksLayer::OGRDXFBlocksLayer( OGRDXFDataSource *poDSIn ) :
+    poDS(poDSIn),
+    poFeatureDefn(new OGRFeatureDefn( "blocks" ))
 {
-    this->poDS = poDS;
-
     ResetReading();
 
-    poFeatureDefn = new OGRFeatureDefn( "blocks" );
     poFeatureDefn->Reference();
 
     poDS->AddStandardFields( poFeatureDefn );
@@ -59,7 +57,7 @@ OGRDXFBlocksLayer::~OGRDXFBlocksLayer()
     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     {
         CPLDebug( "DXF", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
+                  (int) m_nFeaturesRead,
                   poFeatureDefn->GetName() );
     }
 
@@ -98,7 +96,7 @@ OGRFeature *OGRDXFBlocksLayer::GetNextUnfilteredFeature()
 /*      Are we done reading the current blocks features?                */
 /* -------------------------------------------------------------------- */
     DXFBlockDefinition *psBlock = &(oIt->second);
-    unsigned int nSubFeatureCount = psBlock->apoFeatures.size();
+    size_t nSubFeatureCount = psBlock->apoFeatures.size();
 
     if( psBlock->poGeometry != NULL )
         nSubFeatureCount++;
@@ -114,7 +112,7 @@ OGRFeature *OGRDXFBlocksLayer::GetNextUnfilteredFeature()
 
         psBlock = &(oIt->second);
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Is this a geometry based block?                                 */
 /* -------------------------------------------------------------------- */
@@ -155,7 +153,7 @@ OGRFeature *OGRDXFBlocksLayer::GetNextUnfilteredFeature()
 OGRFeature *OGRDXFBlocksLayer::GetNextFeature()
 
 {
-    while( TRUE )
+    while( true )
     {
         OGRFeature *poFeature = GetNextUnfilteredFeature();
 
@@ -186,4 +184,3 @@ int OGRDXFBlocksLayer::TestCapability( const char * pszCap )
     else
         return FALSE;
 }
-
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxfblockswriterlayer.cpp b/ogr/ogrsf_frmts/dxf/ogrdxfblockswriterlayer.cpp
index 3239b9d..8277a92 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxfblockswriterlayer.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxfblockswriterlayer.cpp
@@ -2,7 +2,7 @@
  * $Id: ogrdxfwriterlayer.cpp 20670 2010-09-22 00:21:17Z warmerdam $
  *
  * Project:  DXF Translator
- * Purpose:  Implements OGRDXFBlocksWriterLayer used for capturing block 
+ * Purpose:  Implements OGRDXFBlocksWriterLayer used for capturing block
  *           definitions for writing to a DXF file.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -39,12 +39,10 @@ CPL_CVSID("$Id: ogrdxfwriterlayer.cpp 20670 2010-09-22 00:21:17Z warmerdam $");
 /*                      OGRDXFBlocksWriterLayer()                       */
 /************************************************************************/
 
-OGRDXFBlocksWriterLayer::OGRDXFBlocksWriterLayer( OGRDXFWriterDS *poDS )
-
+OGRDXFBlocksWriterLayer::OGRDXFBlocksWriterLayer(
+    OGRDXFWriterDS * /* poDS */ ) :
+    poFeatureDefn(new OGRFeatureDefn( "blocks" ))
 {
-    (void) poDS;
-
-    poFeatureDefn = new OGRFeatureDefn( "blocks" );
     poFeatureDefn->Reference();
 
     OGRFieldDefn  oLayerField( "Layer", OFTString );
@@ -92,7 +90,7 @@ int OGRDXFBlocksWriterLayer::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,OLCSequentialWrite) )
         return TRUE;
-    else 
+    else
         return FALSE;
 }
 
@@ -146,6 +144,6 @@ OGRFeature *OGRDXFBlocksWriterLayer::FindBlock( const char *pszBlockName )
         if( pszThisName != NULL && strcmp(pszBlockName,pszThisName) == 0 )
             return apoBlocks[i];
     }
-    
+
     return NULL;
 }
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxfdatasource.cpp b/ogr/ogrsf_frmts/dxf/ogrdxfdatasource.cpp
index ece823d..95d5684 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxfdatasource.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxfdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdxfdatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogrdxfdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  DXF Translator
  * Purpose:  Implements OGRDXFDataSource class
@@ -32,17 +32,17 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrdxfdatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogrdxfdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                          OGRDXFDataSource()                          */
 /************************************************************************/
 
-OGRDXFDataSource::OGRDXFDataSource()
-
-{
-    fp = NULL;
-}
+OGRDXFDataSource::OGRDXFDataSource() :
+    fp(NULL),
+    iEntitiesSectionOffset(0),
+    bInlineBlocks(FALSE)
+{ }
 
 /************************************************************************/
 /*                         ~OGRDXFDataSource()                          */
@@ -104,10 +104,10 @@ int OGRDXFDataSource::Open( const char * pszFilename, int bHeaderOnly )
 
     osName = pszFilename;
 
-    bInlineBlocks = CSLTestBoolean(
+    bInlineBlocks = CPLTestBool(
         CPLGetConfigOption( "DXF_INLINE_BLOCKS", "TRUE" ) );
 
-    if( CSLTestBoolean(
+    if( CPLTestBool(
             CPLGetConfigOption( "DXF_HEADER_ONLY", "FALSE" ) ) )
         bHeaderOnly = TRUE;
 
@@ -119,7 +119,7 @@ int OGRDXFDataSource::Open( const char * pszFilename, int bHeaderOnly )
         return FALSE;
 
     oReader.Initialize( fp );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Confirm we have a header section.                               */
 /* -------------------------------------------------------------------- */
@@ -130,7 +130,7 @@ int OGRDXFDataSource::Open( const char * pszFilename, int bHeaderOnly )
     if( ReadValue( szLineBuf ) != 0 || !EQUAL(szLineBuf,"SECTION") )
         return FALSE;
 
-    if( ReadValue( szLineBuf ) != 2 
+    if( ReadValue( szLineBuf ) != 2
         || (!EQUAL(szLineBuf,"HEADER") && !EQUAL(szLineBuf,"ENTITIES") && !EQUAL(szLineBuf,"TABLES")) )
         return FALSE;
 
@@ -143,8 +143,13 @@ int OGRDXFDataSource::Open( const char * pszFilename, int bHeaderOnly )
         if( CPLGetConfigOption( "DXF_ENCODING", NULL ) != NULL )
             osEncoding = CPLGetConfigOption( "DXF_ENCODING", NULL );
 
-        ReadTablesSection();
-        ReadValue(szLineBuf);
+        if( !ReadTablesSection() )
+            return FALSE;
+        if( ReadValue(szLineBuf) < 0 )
+        {
+            DXF_READER_ERROR();
+            return FALSE;
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -153,21 +158,38 @@ int OGRDXFDataSource::Open( const char * pszFilename, int bHeaderOnly )
 /* -------------------------------------------------------------------- */
     else /* if( EQUAL(szLineBuf,"HEADER") ) */
     {
-        ReadHeaderSection();
-        ReadValue(szLineBuf);
+        if( !ReadHeaderSection() )
+            return FALSE;
+        if( ReadValue(szLineBuf) < 0 )
+        {
+            DXF_READER_ERROR();
+            return FALSE;
+        }
 
 /* -------------------------------------------------------------------- */
 /*      Process the CLASSES section, if present.                        */
 /* -------------------------------------------------------------------- */
         if( EQUAL(szLineBuf,"ENDSEC") )
-            ReadValue(szLineBuf);
+        {
+            if( ReadValue(szLineBuf) < 0 )
+            {
+                DXF_READER_ERROR();
+                return FALSE;
+            }
+        }
 
         if( EQUAL(szLineBuf,"SECTION") )
-            ReadValue(szLineBuf);
-        
+        {
+            if( ReadValue(szLineBuf) < 0 )
+            {
+                DXF_READER_ERROR();
+                return FALSE;
+            }
+        }
+
         if( EQUAL(szLineBuf,"CLASSES") )
         {
-            while( (nCode = ReadValue( szLineBuf,sizeof(szLineBuf) )) > -1 
+            while( (nCode = ReadValue( szLineBuf,sizeof(szLineBuf) )) > -1
                    && !EQUAL(szLineBuf,"ENDSEC") )
             {
                 //printf("C:%d/%s\n", nCode, szLineBuf );
@@ -178,15 +200,32 @@ int OGRDXFDataSource::Open( const char * pszFilename, int bHeaderOnly )
 /*      Process the TABLES section, if present.                         */
 /* -------------------------------------------------------------------- */
         if( EQUAL(szLineBuf,"ENDSEC") )
-            ReadValue(szLineBuf);
-        
+        {
+            if( ReadValue(szLineBuf) < 0 )
+            {
+                DXF_READER_ERROR();
+                return FALSE;
+            }
+        }
+
         if( EQUAL(szLineBuf,"SECTION") )
-            ReadValue(szLineBuf);
-        
+        {
+            if( ReadValue(szLineBuf) < 0 )
+            {
+                DXF_READER_ERROR();
+                return FALSE;
+            }
+        }
+
         if( EQUAL(szLineBuf,"TABLES") )
         {
-            ReadTablesSection();
-            ReadValue(szLineBuf);
+            if( !ReadTablesSection() )
+                return FALSE;
+            if( ReadValue(szLineBuf) < 0 )
+            {
+                DXF_READER_ERROR();
+                return FALSE;
+            }
         }
     }
 
@@ -208,15 +247,32 @@ int OGRDXFDataSource::Open( const char * pszFilename, int bHeaderOnly )
     if( !bEntitiesOnly )
     {
         if( EQUAL(szLineBuf,"ENDSEC") )
-            ReadValue(szLineBuf);
-        
+        {
+            if( ReadValue(szLineBuf) < 0 )
+            {
+                DXF_READER_ERROR();
+                return FALSE;
+            }
+        }
+
         if( EQUAL(szLineBuf,"SECTION") )
-            ReadValue(szLineBuf);
-        
+        {
+            if( ReadValue(szLineBuf) < 0 )
+            {
+                DXF_READER_ERROR();
+                return FALSE;
+            }
+        }
+
         if( EQUAL(szLineBuf,"BLOCKS") )
         {
-            ReadBlocksSection();
-            ReadValue(szLineBuf);
+            if( !ReadBlocksSection() )
+                return FALSE;
+            if( ReadValue(szLineBuf) < 0 )
+            {
+                DXF_READER_ERROR();
+                return FALSE;
+            }
         }
     }
 
@@ -227,10 +283,19 @@ int OGRDXFDataSource::Open( const char * pszFilename, int bHeaderOnly )
 /*      Now we are at the entities section, hopefully.  Confirm.        */
 /* -------------------------------------------------------------------- */
     if( EQUAL(szLineBuf,"SECTION") )
-        ReadValue(szLineBuf);
+    {
+        if( ReadValue(szLineBuf) < 0 )
+        {
+            DXF_READER_ERROR();
+            return FALSE;
+        }
+    }
 
     if( !EQUAL(szLineBuf,"ENTITIES") )
+    {
+        DXF_READER_ERROR();
         return FALSE;
+    }
 
     iEntitiesSectionOffset = oReader.iSrcBufferFileOffset + oReader.iSrcBufferOffset;
     apoLayers[0]->ResetReading();
@@ -242,13 +307,13 @@ int OGRDXFDataSource::Open( const char * pszFilename, int bHeaderOnly )
 /*                         ReadTablesSection()                          */
 /************************************************************************/
 
-void OGRDXFDataSource::ReadTablesSection()
+bool OGRDXFDataSource::ReadTablesSection()
 
 {
     char szLineBuf[257];
     int  nCode;
 
-    while( (nCode = ReadValue( szLineBuf, sizeof(szLineBuf) )) > -1 
+    while( (nCode = ReadValue( szLineBuf, sizeof(szLineBuf) )) > -1
            && !EQUAL(szLineBuf,"ENDSEC") )
     {
         // We are only interested in extracting tables.
@@ -257,6 +322,11 @@ void OGRDXFDataSource::ReadTablesSection()
 
         // Currently we are only interested in the LAYER table.
         nCode = ReadValue( szLineBuf, sizeof(szLineBuf) );
+        if( nCode < 0 )
+        {
+            DXF_READER_ERROR();
+            return false;
+        }
 
         if( nCode != 2 )
             continue;
@@ -267,20 +337,32 @@ void OGRDXFDataSource::ReadTablesSection()
                && !EQUAL(szLineBuf,"ENDTAB") )
         {
             if( nCode == 0 && EQUAL(szLineBuf,"LAYER") )
-                ReadLayerDefinition();
+            {
+                if( !ReadLayerDefinition() )
+                    return false;
+            }
             if( nCode == 0 && EQUAL(szLineBuf,"LTYPE") )
-                ReadLineTypeDefinition();
+            {
+                if( !ReadLineTypeDefinition() )
+                    return false;
+            }
         }
     }
+    if( nCode < 0 )
+    {
+        DXF_READER_ERROR();
+        return false;
+    }
 
     CPLDebug( "DXF", "Read %d layer definitions.", (int) oLayerTable.size() );
+    return true;
 }
 
 /************************************************************************/
 /*                        ReadLayerDefinition()                         */
 /************************************************************************/
 
-void OGRDXFDataSource::ReadLayerDefinition()
+bool OGRDXFDataSource::ReadLayerDefinition()
 
 {
     char szLineBuf[257];
@@ -303,14 +385,14 @@ void OGRDXFDataSource::ReadLayerDefinition()
             oLayerProperties["Linetype"] = ACTextUnescape(szLineBuf,
                                                           GetEncoding());
             break;
-            
+
           case 62:
             oLayerProperties["Color"] = szLineBuf;
 
             if( atoi(szLineBuf) < 0 ) // Is layer off?
                 oLayerProperties["Hidden"] = "1";
             break;
-            
+
           case 70:
             oLayerProperties["Flags"] = szLineBuf;
             if( atoi(szLineBuf) & 0x01 ) // Is layer frozen?
@@ -326,12 +408,18 @@ void OGRDXFDataSource::ReadLayerDefinition()
             break;
         }
     }
+    if( nCode < 0 )
+    {
+        DXF_READER_ERROR();
+        return false;
+    }
 
     if( oLayerProperties.size() > 0 )
         oLayerTable[osLayerName] = oLayerProperties;
-    
+
     if( nCode == 0 )
         UnreadValue();
+    return true;
 }
 
 /************************************************************************/
@@ -356,7 +444,7 @@ const char *OGRDXFDataSource::LookupLayerProperty( const char *pszLayer,
 /*                       ReadLineTypeDefinition()                       */
 /************************************************************************/
 
-void OGRDXFDataSource::ReadLineTypeDefinition()
+bool OGRDXFDataSource::ReadLineTypeDefinition()
 
 {
     char szLineBuf[257];
@@ -385,17 +473,23 @@ void OGRDXFDataSource::ReadLineTypeDefinition()
               osLineTypeDef += "g";
           }
           break;
-            
+
           default:
             break;
         }
     }
+    if( nCode < 0 )
+    {
+        DXF_READER_ERROR();
+        return false;
+    }
 
     if( osLineTypeDef != "" )
         oLineTypeTable[osLineTypeName] = osLineTypeDef;
-    
+
     if( nCode == 0 )
         UnreadValue();
+    return true;
 }
 
 /************************************************************************/
@@ -415,37 +509,48 @@ const char *OGRDXFDataSource::LookupLineType( const char *pszName )
 /*                         ReadHeaderSection()                          */
 /************************************************************************/
 
-void OGRDXFDataSource::ReadHeaderSection()
+bool OGRDXFDataSource::ReadHeaderSection()
 
 {
     char szLineBuf[257];
     int  nCode;
 
-    while( (nCode = ReadValue( szLineBuf, sizeof(szLineBuf) )) > -1 
+    while( (nCode = ReadValue( szLineBuf, sizeof(szLineBuf) )) > -1
            && !EQUAL(szLineBuf,"ENDSEC") )
     {
         if( nCode != 9 )
             continue;
 
-        CPLString osName = szLineBuf;
+        CPLString l_osName = szLineBuf;
 
-        ReadValue( szLineBuf, sizeof(szLineBuf) );
+        if(ReadValue( szLineBuf, sizeof(szLineBuf) )<0)
+        {
+            DXF_READER_ERROR();
+            return false;
+        }
 
         CPLString osValue = szLineBuf;
 
-        oHeaderVariables[osName] = osValue;
+        oHeaderVariables[l_osName] = osValue;
+    }
+    if( nCode < 0 )
+    {
+        DXF_READER_ERROR();
+        return false;
     }
 
-    if (nCode != -1)
+    nCode = ReadValue( szLineBuf, sizeof(szLineBuf) );
+    if( nCode < 0 )
     {
-        nCode = ReadValue( szLineBuf, sizeof(szLineBuf) );
-        UnreadValue();
+        DXF_READER_ERROR();
+        return false;
     }
+    UnreadValue();
 
     /* Unusual DXF files produced by dxflib */
     /* such as http://www.ribbonsoft.com/library/architecture/plants/decd5.dxf */
     /* where there is a spurious ENDSEC in the middle of the header variables */
-    if (nCode == 9 && EQUALN(szLineBuf,"$", 1) )
+    if (nCode == 9 && STARTS_WITH_CI(szLineBuf, "$") )
     {
         while( (nCode = ReadValue( szLineBuf, sizeof(szLineBuf) )) > -1
             && !EQUAL(szLineBuf,"ENDSEC") )
@@ -453,17 +558,26 @@ void OGRDXFDataSource::ReadHeaderSection()
             if( nCode != 9 )
                 continue;
 
-            CPLString osName = szLineBuf;
+            CPLString l_osName = szLineBuf;
 
-            ReadValue( szLineBuf, sizeof(szLineBuf) );
+            if( ReadValue( szLineBuf, sizeof(szLineBuf) ) < 0 )
+            {
+                DXF_READER_ERROR();
+                return false;
+            }
 
             CPLString osValue = szLineBuf;
 
-            oHeaderVariables[osName] = osValue;
+            oHeaderVariables[l_osName] = osValue;
+        }
+        if( nCode < 0 )
+        {
+            DXF_READER_ERROR();
+            return false;
         }
     }
 
-    CPLDebug( "DXF", "Read %d header variables.", 
+    CPLDebug( "DXF", "Read %d header variables.",
               (int) oHeaderVariables.size() );
 
 /* -------------------------------------------------------------------- */
@@ -474,24 +588,25 @@ void OGRDXFDataSource::ReadHeaderSection()
 
     // not strictly accurate but works even without iconv.
     if( osCodepage == "ANSI_1252" )
-        osEncoding = CPL_ENC_ISO8859_1; 
-    else if( EQUALN(osCodepage,"ANSI_",5) )
+        osEncoding = CPL_ENC_ISO8859_1;
+    else if( STARTS_WITH_CI(osCodepage, "ANSI_") )
     {
         osEncoding = "CP";
         osEncoding += osCodepage + 5;
     }
     else
     {
-        // fallback to the default 
+        // fallback to the default
         osEncoding = CPL_ENC_ISO8859_1;
     }
-                                       
+
     if( CPLGetConfigOption( "DXF_ENCODING", NULL ) != NULL )
         osEncoding = CPLGetConfigOption( "DXF_ENCODING", NULL );
 
     if( osEncoding != CPL_ENC_ISO8859_1 )
-        CPLDebug( "DXF", "Treating DXF as encoding '%s', $DWGCODEPAGE='%s'", 
+        CPLDebug( "DXF", "Treating DXF as encoding '%s', $DWGCODEPAGE='%s'",
                   osEncoding.c_str(), osCodepage.c_str() );
+    return true;
 }
 
 /************************************************************************/
@@ -500,13 +615,13 @@ void OGRDXFDataSource::ReadHeaderSection()
 /*      Fetch a variable that came from the HEADER section.             */
 /************************************************************************/
 
-const char *OGRDXFDataSource::GetVariable( const char *pszName, 
+const char *OGRDXFDataSource::GetVariable( const char *pszName,
                                            const char *pszDefault )
 
 {
     if( oHeaderVariables.count(pszName) == 0 )
         return pszDefault;
-    else 
+    else
         return oHeaderVariables[pszName];
 }
 
@@ -537,7 +652,7 @@ void OGRDXFDataSource::AddStandardFields( OGRFeatureDefn *poFeatureDefn )
 
     if( !bInlineBlocks )
     {
-        OGRFieldDefn  oTextField( "BlockName", OFTString );
-        poFeatureDefn->AddFieldDefn( &oTextField );
+        OGRFieldDefn  oBlockNameField( "BlockName", OFTString );
+        poFeatureDefn->AddFieldDefn( &oBlockNameField );
     }
 }
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxfdriver.cpp b/ogr/ogrsf_frmts/dxf/ogrdxfdriver.cpp
index de4394f..3320299 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxfdriver.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxfdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdxfdriver.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogrdxfdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  DXF Translator
  * Purpose:  Implements OGRDXFDriver.
@@ -30,7 +30,7 @@
 #include "ogr_dxf.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrdxfdriver.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogrdxfdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
 
 /************************************************************************/
 /*                       OGRDXFDriverIdentify()                         */
@@ -39,8 +39,41 @@ CPL_CVSID("$Id: ogrdxfdriver.cpp 27745 2014-09-27 16:38:57Z goatbar $");
 static int OGRDXFDriverIdentify( GDALOpenInfo* poOpenInfo )
 
 {
-    return poOpenInfo->fpL != NULL &&
-           EQUAL(CPLGetExtension(poOpenInfo->pszFilename),"dxf");
+    if( poOpenInfo->fpL == NULL || poOpenInfo->nHeaderBytes == 0 )
+        return FALSE;
+    if( EQUAL(CPLGetExtension(poOpenInfo->pszFilename),"dxf") )
+        return TRUE;
+    const char* pszIter = (const char*)poOpenInfo->pabyHeader;
+    int bFoundZero = FALSE;
+    int i = 0;
+    for(i=0; pszIter[i]; i++)
+    {
+        if( pszIter[i] == '0' )
+        {
+            int j=i-1;
+            for(; j>=0; j--)
+            {
+                if( pszIter[j] != ' ' )
+                    break;
+            }
+            if( j < 0 || pszIter[j] == '\n'|| pszIter[j] == '\r' )
+            {
+                bFoundZero = TRUE;
+                break;
+            }
+        }
+    }
+    if( !bFoundZero )
+        return FALSE;
+    i ++;
+    while( pszIter[i] == ' ' )
+        i ++;
+    while( pszIter[i] == '\n' || pszIter[i] == '\r' )
+        i ++;
+    if( !STARTS_WITH_CI(pszIter + i, "SECTION") )
+        return FALSE;
+    i += static_cast<int>(strlen("SECTION"));
+    return pszIter[i] == '\n' || pszIter[i] == '\r';
 }
 
 /************************************************************************/
@@ -93,36 +126,32 @@ static GDALDataset *OGRDXFDriverCreate( const char * pszName,
 void RegisterOGRDXF()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "DXF" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "DXF" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver  *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "DXF" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "AutoCAD DXF" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "dxf" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_dxf.html" );
+    poDriver->SetDescription( "DXF" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "AutoCAD DXF" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "dxf" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_dxf.html" );
 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "  <Option name='HEADER' type='string' description='Template header file' default='header.dxf'/>"
 "  <Option name='TRAILER' type='string' description='Template trailer file' default='trailer.dxf'/>"
 "  <Option name='FIRST_ENTITY' type='int' description='Identifier of first entity'/>"
 "</CreationOptionList>");
 
-        poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
-                                            "<LayerCreationOptionList/>" );
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+                               "<LayerCreationOptionList/>" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = OGRDXFDriverOpen;
-        poDriver->pfnIdentify = OGRDXFDriverIdentify;
-        poDriver->pfnCreate = OGRDXFDriverCreate;
+    poDriver->pfnOpen = OGRDXFDriverOpen;
+    poDriver->pfnIdentify = OGRDXFDriverIdentify;
+    poDriver->pfnCreate = OGRDXFDriverCreate;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxflayer.cpp b/ogr/ogrsf_frmts/dxf/ogrdxflayer.cpp
index eea57e1..a1ae616 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxflayer.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxflayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdxflayer.cpp 27945 2014-11-11 01:33:15Z rouault $
+ * $Id: ogrdxflayer.cpp 33770 2016-03-22 19:52:27Z rouault $
  *
  * Project:  DXF Translator
  * Purpose:  Implements OGRDXFLayer class.
@@ -33,24 +33,17 @@
 #include "ogrdxf_polyline_smooth.h"
 #include "ogr_api.h"
 
-CPL_CVSID("$Id: ogrdxflayer.cpp 27945 2014-11-11 01:33:15Z rouault $");
-
-#ifndef PI
-#define PI  3.14159265358979323846
-#endif 
+CPL_CVSID("$Id: ogrdxflayer.cpp 33770 2016-03-22 19:52:27Z rouault $");
 
 /************************************************************************/
 /*                            OGRDXFLayer()                             */
 /************************************************************************/
 
-OGRDXFLayer::OGRDXFLayer( OGRDXFDataSource *poDS )
-
+OGRDXFLayer::OGRDXFLayer( OGRDXFDataSource *poDSIn ) :
+    poDS(poDSIn),
+    poFeatureDefn(new OGRFeatureDefn( "entities" )),
+    iNextFID(0)
 {
-    this->poDS = poDS;
-
-    iNextFID = 0;
-
-    poFeatureDefn = new OGRFeatureDefn( "entities" );
     poFeatureDefn->Reference();
 
     poDS->AddStandardFields( poFeatureDefn );
@@ -63,7 +56,7 @@ OGRDXFLayer::OGRDXFLayer( OGRDXFDataSource *poDS )
         OGRFieldDefn  oBlockAngleField( "BlockAngle", OFTReal );
         poFeatureDefn->AddFieldDefn( &oBlockAngleField );
     }
-    
+
     SetDescription( poFeatureDefn->GetName() );
 }
 
@@ -78,7 +71,7 @@ OGRDXFLayer::~OGRDXFLayer()
     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     {
         CPLDebug( "DXF", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
+                  (int) m_nFeaturesRead,
                   poFeatureDefn->GetName() );
     }
 
@@ -119,17 +112,17 @@ void OGRDXFLayer::ResetReading()
 /*      or all entity types.                                            */
 /************************************************************************/
 
-void OGRDXFLayer::TranslateGenericProperty( OGRFeature *poFeature, 
+void OGRDXFLayer::TranslateGenericProperty( OGRFeature *poFeature,
                                             int nCode, char *pszValue )
 
 {
     switch( nCode )
     {
-      case 8: 
+      case 8:
         poFeature->SetField( "Layer", TextUnescape(pszValue) );
         break;
-            
-      case 100: 
+
+      case 100:
       {
           CPLString osSubClass = poFeature->GetFieldAsString("SubClasses");
           if( osSubClass.size() > 0 )
@@ -171,7 +164,7 @@ void OGRDXFLayer::TranslateGenericProperty( OGRFeature *poFeature,
           if( osAggregate.size() > 0 )
               osAggregate += " ";
           osAggregate += pszValue;
-            
+
           poFeature->SetField( "ExtendedEntity", osAggregate );
       }
       break;
@@ -180,11 +173,11 @@ void OGRDXFLayer::TranslateGenericProperty( OGRFeature *poFeature,
       case 210:
         oStyleProperties["210_N.dX"] = pszValue;
         break;
-        
+
       case 220:
         oStyleProperties["220_N.dY"] = pszValue;
         break;
-        
+
       case 230:
         oStyleProperties["230_N.dZ"] = pszValue;
         break;
@@ -207,7 +200,7 @@ void OGRDXFLayer::PrepareLineStyle( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
 /*      Is the layer disabled/hidden/frozen/off?                        */
 /* -------------------------------------------------------------------- */
-    int bHidden = 
+    int bHidden =
         EQUAL(poDS->LookupLayerProperty( osLayer, "Hidden" ), "1");
 
 /* -------------------------------------------------------------------- */
@@ -218,14 +211,14 @@ void OGRDXFLayer::PrepareLineStyle( OGRFeature *poFeature )
     if( oStyleProperties.count("Color") > 0 )
         nColor = atoi(oStyleProperties["Color"]);
 
-    // Use layer color? 
+    // Use layer color?
     if( nColor < 1 || nColor > 255 )
     {
         const char *pszValue = poDS->LookupLayerProperty( osLayer, "Color" );
         if( pszValue != NULL )
             nColor = atoi(pszValue);
     }
-        
+
     if( nColor < 1 || nColor > 255 )
         return;
 
@@ -256,13 +249,13 @@ void OGRDXFLayer::PrepareLineStyle( OGRFeature *poFeature )
     CPLString osStyle;
     const unsigned char *pabyDXFColors = ACGetColorTable();
 
-    osStyle.Printf( "PEN(c:#%02x%02x%02x", 
+    osStyle.Printf( "PEN(c:#%02x%02x%02x",
                     pabyDXFColors[nColor*3+0],
                     pabyDXFColors[nColor*3+1],
                     pabyDXFColors[nColor*3+2] );
 
     if( bHidden )
-        osStyle += "00"; 
+        osStyle += "00";
 
     if( dfWeight > 0.0 )
     {
@@ -279,7 +272,7 @@ void OGRDXFLayer::PrepareLineStyle( OGRFeature *poFeature )
     }
 
     osStyle += ")";
-    
+
     poFeature->SetStyleString( osStyle );
 }
 
@@ -293,14 +286,14 @@ private:
     double adfN[3];
     double adfAX[3];
     double adfAY[3];
-    
+
 public:
-    OCSTransformer( double adfN[3] ) {
+    OCSTransformer( double adfNIn[3] ) {
         static const double dSmall = 1.0 / 64.0;
         static const double adfWZ[3] = {0, 0, 1};
         static const double adfWY[3] = {0, 1, 0};
 
-        memcpy( this->adfN, adfN, sizeof(double)*3 );
+        memcpy( this->adfN, adfNIn, sizeof(double)*3 );
 
     if ((ABS(adfN[0]) < dSmall) && (ABS(adfN[1]) < dSmall))
             CrossProduct(adfWY, adfN, adfAX);
@@ -329,11 +322,11 @@ public:
     }
     OGRSpatialReference *GetSourceCS() { return NULL; }
     OGRSpatialReference *GetTargetCS() { return NULL; }
-    int Transform( int nCount, 
+    int Transform( int nCount,
                    double *x, double *y, double *z )
         { return TransformEx( nCount, x, y, z, NULL ); }
-    
-    int TransformEx( int nCount, 
+
+    int TransformEx( int nCount,
                      double *adfX, double *adfY, double *adfZ = NULL,
                      int *pabSuccess = NULL )
         {
@@ -341,7 +334,7 @@ public:
             for( i = 0; i < nCount; i++ )
             {
                 double x = adfX[i], y = adfY[i], z = adfZ[i];
-                
+
                 adfX[i] = x * adfAX[0] + y * adfAY[0] + z * adfN[0];
                 adfY[i] = x * adfAX[1] + y * adfAY[1] + z * adfN[1];
                 adfZ[i] = x * adfAX[2] + y * adfAY[2] + z * adfN[2];
@@ -444,7 +437,7 @@ OGRFeature *OGRDXFLayer::TranslateMTEXT()
 
           case 21:
             dfYDirection = CPLAtof(szLineBuf);
-            dfAngle = atan2( dfYDirection, dfXDirection ) * 180.0 / PI;
+            dfAngle = atan2( dfYDirection, dfXDirection ) * 180.0 / M_PI;
             break;
 
           case 1:
@@ -463,6 +456,12 @@ OGRFeature *OGRDXFLayer::TranslateMTEXT()
             break;
         }
     }
+    if( nCode < 0 )
+    {
+        DXF_LAYER_READER_ERROR();
+        delete poFeature;
+        return NULL;
+    }
 
     if( nCode == 0 )
         poDS->UnreadValue();
@@ -483,7 +482,7 @@ OGRFeature *OGRDXFLayer::TranslateMTEXT()
 
     poFeature->SetField( "Text", osText );
 
-    
+
 /* -------------------------------------------------------------------- */
 /*      We need to escape double quotes with backslashes before they    */
 /*      can be inserted in the style string.                            */
@@ -511,7 +510,7 @@ OGRFeature *OGRDXFLayer::TranslateMTEXT()
     if( oStyleProperties.count("Color") > 0 )
         nColor = atoi(oStyleProperties["Color"]);
 
-    // Use layer color? 
+    // Use layer color?
     if( nColor < 1 || nColor > 255 )
     {
         CPLString osLayer = poFeature->GetFieldAsString("Layer");
@@ -519,7 +518,7 @@ OGRFeature *OGRDXFLayer::TranslateMTEXT()
         if( pszValue != NULL )
             nColor = atoi(pszValue);
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Prepare style string.                                           */
 /* -------------------------------------------------------------------- */
@@ -542,18 +541,18 @@ OGRFeature *OGRDXFLayer::TranslateMTEXT()
 
     if( nAttachmentPoint >= 0 && nAttachmentPoint <= 9 )
     {
-        const static int anAttachmentMap[10] = 
+        const static int anAttachmentMap[10] =
             { -1, 7, 8, 9, 4, 5, 6, 1, 2, 3 };
-        
-        osStyle += 
+
+        osStyle +=
             CPLString().Printf(",p:%d", anAttachmentMap[nAttachmentPoint]);
     }
 
     if( nColor > 0 && nColor < 256 )
     {
         const unsigned char *pabyDXFColors = ACGetColorTable();
-        osStyle += 
-            CPLString().Printf( ",c:#%02x%02x%02x", 
+        osStyle +=
+            CPLString().Printf( ",c:#%02x%02x%02x",
                                 pabyDXFColors[nColor*3+0],
                                 pabyDXFColors[nColor*3+1],
                                 pabyDXFColors[nColor*3+2] );
@@ -617,6 +616,12 @@ OGRFeature *OGRDXFLayer::TranslateTEXT()
             break;
         }
     }
+    if( nCode < 0 )
+    {
+        DXF_LAYER_READER_ERROR();
+        delete poFeature;
+        return NULL;
+    }
 
     if( nCode == 0 )
         poDS->UnreadValue();
@@ -661,7 +666,7 @@ OGRFeature *OGRDXFLayer::TranslateTEXT()
 /* -------------------------------------------------------------------- */
     CPLString osLayer = poFeature->GetFieldAsString("Layer");
 
-    int bHidden = 
+    int bHidden =
         EQUAL(poDS->LookupLayerProperty( osLayer, "Hidden" ), "1");
 
 /* -------------------------------------------------------------------- */
@@ -672,14 +677,14 @@ OGRFeature *OGRDXFLayer::TranslateTEXT()
     if( oStyleProperties.count("Color") > 0 )
         nColor = atoi(oStyleProperties["Color"]);
 
-    // Use layer color? 
+    // Use layer color?
     if( nColor < 1 || nColor > 255 )
     {
         const char *pszValue = poDS->LookupLayerProperty( osLayer, "Color" );
         if( pszValue != NULL )
             nColor = atoi(pszValue);
     }
-        
+
     if( nColor < 1 || nColor > 255 )
         nColor = 8;
 
@@ -705,14 +710,14 @@ OGRFeature *OGRDXFLayer::TranslateTEXT()
 
     const unsigned char *pabyDWGColors = ACGetColorTable();
 
-    snprintf( szBuffer, sizeof(szBuffer), ",c:#%02x%02x%02x", 
+    snprintf( szBuffer, sizeof(szBuffer), ",c:#%02x%02x%02x",
               pabyDWGColors[nColor*3+0],
               pabyDWGColors[nColor*3+1],
               pabyDWGColors[nColor*3+2] );
     osStyle += szBuffer;
 
     if( bHidden )
-        osStyle += "00"; 
+        osStyle += "00";
 
     osStyle += ")";
 
@@ -756,6 +761,12 @@ OGRFeature *OGRDXFLayer::TranslatePOINT()
             break;
         }
     }
+    if( nCode < 0 )
+    {
+        DXF_LAYER_READER_ERROR();
+        delete poFeature;
+        return NULL;
+    }
 
     OGRPoint* poGeom;
     if( bHaveZ )
@@ -767,10 +778,10 @@ OGRFeature *OGRDXFLayer::TranslatePOINT()
 
     if( nCode == 0 )
         poDS->UnreadValue();
-    
+
     // Set style pen color
     PrepareLineStyle( poFeature );
- 
+
     return poFeature;
 }
 
@@ -826,6 +837,12 @@ OGRFeature *OGRDXFLayer::TranslateLINE()
             break;
         }
     }
+    if( nCode < 0 )
+    {
+        DXF_LAYER_READER_ERROR();
+        delete poFeature;
+        return NULL;
+    }
 
     if( nCode == 0 )
         poDS->UnreadValue();
@@ -944,6 +961,12 @@ OGRFeature *OGRDXFLayer::TranslateLWPOLYLINE()
             break;
         }
     }
+    if( nCode < 0 )
+    {
+        DXF_LAYER_READER_ERROR();
+        delete poFeature;
+        return NULL;
+    }
 
     if( nCode == 0 )
         poDS->UnreadValue();
@@ -951,7 +974,7 @@ OGRFeature *OGRDXFLayer::TranslateLWPOLYLINE()
     if( bHaveX && bHaveY )
         smoothPolyline.AddPoint(dfX, dfY, dfZ, dfBulge);
 
-    
+
     if(smoothPolyline.IsEmpty())
     {
         delete poFeature;
@@ -1004,6 +1027,12 @@ OGRFeature *OGRDXFLayer::TranslatePOLYLINE()
             break;
         }
     }
+    if( nCode < 0 )
+    {
+        DXF_LAYER_READER_ERROR();
+        delete poFeature;
+        return NULL;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Collect VERTEXes as a smooth polyline.                          */
@@ -1021,6 +1050,13 @@ OGRFeature *OGRDXFLayer::TranslatePOLYLINE()
         if( !EQUAL(szLineBuf,"VERTEX") )
         {
             while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf)))>0 ) {}
+            if( nCode < 0 )
+            {
+                DXF_LAYER_READER_ERROR();
+                delete poFeature;
+                return NULL;
+            }
+
             continue;
         }
 
@@ -1032,11 +1068,11 @@ OGRFeature *OGRDXFLayer::TranslatePOLYLINE()
               case 10:
                 dfX = CPLAtof(szLineBuf);
                 break;
-                
+
               case 20:
                 dfY = CPLAtof(szLineBuf);
                 break;
-                
+
               case 30:
                 dfZ = CPLAtof(szLineBuf);
                 smoothPolyline.setCoordinateDimension(3);
@@ -1054,6 +1090,13 @@ OGRFeature *OGRDXFLayer::TranslatePOLYLINE()
                 break;
             }
         }
+        if( nCode < 0 )
+        {
+            DXF_LAYER_READER_ERROR();
+            delete poFeature;
+            return NULL;
+        }
+
 
         // Ignore Spline frame control points ( see #4683 )
         if ((nVertexFlag & 16) == 0)
@@ -1066,7 +1109,7 @@ OGRFeature *OGRDXFLayer::TranslatePOLYLINE()
         delete poFeature;
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Close polyline if necessary.                                    */
 /* -------------------------------------------------------------------- */
@@ -1124,6 +1167,12 @@ OGRFeature *OGRDXFLayer::TranslateCIRCLE()
             break;
         }
     }
+    if( nCode < 0 )
+    {
+        DXF_LAYER_READER_ERROR();
+        delete poFeature;
+        return NULL;
+    }
 
     if( nCode == 0 )
         poDS->UnreadValue();
@@ -1131,10 +1180,10 @@ OGRFeature *OGRDXFLayer::TranslateCIRCLE()
 /* -------------------------------------------------------------------- */
 /*      Create geometry                                                 */
 /* -------------------------------------------------------------------- */
-    OGRGeometry *poCircle = 
-        OGRGeometryFactory::approximateArcAngles( dfX1, dfY1, dfZ1, 
+    OGRGeometry *poCircle =
+        OGRGeometryFactory::approximateArcAngles( dfX1, dfY1, dfZ1,
                                                   dfRadius, dfRadius, 0.0,
-                                                  0.0, 360.0, 
+                                                  0.0, 360.0,
                                                   0.0 );
 
     if( !bHaveZ )
@@ -1200,12 +1249,12 @@ OGRFeature *OGRDXFLayer::TranslateELLIPSE()
 
           case 41:
             // These *seem* to always be in radians regardless of $AUNITS
-            dfEndAngle = -1 * CPLAtof(szLineBuf) * 180.0 / PI;
+            dfEndAngle = -1 * CPLAtof(szLineBuf) * 180.0 / M_PI;
             break;
 
           case 42:
             // These *seem* to always be in radians regardless of $AUNITS
-            dfStartAngle = -1 * CPLAtof(szLineBuf) * 180.0 / PI;
+            dfStartAngle = -1 * CPLAtof(szLineBuf) * 180.0 / M_PI;
             break;
 
           default:
@@ -1213,6 +1262,12 @@ OGRFeature *OGRDXFLayer::TranslateELLIPSE()
             break;
         }
     }
+    if( nCode < 0 )
+    {
+        DXF_LAYER_READER_ERROR();
+        delete poFeature;
+        return NULL;
+    }
 
     if( nCode == 0 )
         poDS->UnreadValue();
@@ -1224,32 +1279,53 @@ OGRFeature *OGRDXFLayer::TranslateELLIPSE()
     double dfPrimaryRadius, dfSecondaryRadius;
     double dfRotation;
 
-    if( dfStartAngle > dfEndAngle )
-        dfEndAngle += 360.0;
-
-    dfPrimaryRadius = sqrt( dfAxisX * dfAxisX 
+    dfPrimaryRadius = sqrt( dfAxisX * dfAxisX
                             + dfAxisY * dfAxisY
                             + dfAxisZ * dfAxisZ );
 
     dfSecondaryRadius = dfRatio * dfPrimaryRadius;
 
-    dfRotation = -1 * atan2( dfAxisY, dfAxisX ) * 180 / PI;
+    dfRotation = -1 * atan2( dfAxisY, dfAxisX ) * 180 / M_PI;
 
 /* -------------------------------------------------------------------- */
 /*      Create geometry                                                 */
 /* -------------------------------------------------------------------- */
-    OGRGeometry *poEllipse = 
-        OGRGeometryFactory::approximateArcAngles( dfX1, dfY1, dfZ1, 
-                                                  dfPrimaryRadius, 
+    if( oStyleProperties.count("210_N.dX") != 0
+        && oStyleProperties.count("220_N.dY") != 0
+        && oStyleProperties.count("230_N.dZ") != 0 )
+    {
+	    double adfN[3];
+
+	    adfN[0] = CPLAtof(oStyleProperties["210_N.dX"]);
+	    adfN[1] = CPLAtof(oStyleProperties["220_N.dY"]);
+	    adfN[2] = CPLAtof(oStyleProperties["230_N.dZ"]);
+
+            if( adfN[0] == 0.0 && adfN[1] == 0.0 && adfN[2] == -1.0 )
+            {
+                // reverse angles
+		double temp = dfEndAngle;
+
+		dfEndAngle = 360.0 - dfStartAngle;
+		dfStartAngle = 360.0 - temp;
+            }
+    }
+
+    if( dfStartAngle > dfEndAngle )
+        dfEndAngle += 360.0;
+
+    OGRGeometry *poEllipse =
+        OGRGeometryFactory::approximateArcAngles( dfX1, dfY1, dfZ1,
+                                                  dfPrimaryRadius,
                                                   dfSecondaryRadius,
-                                                  dfRotation, 
+                                                  dfRotation,
                                                   dfStartAngle, dfEndAngle,
                                                   0.0 );
 
     if( !bHaveZ )
         poEllipse->flattenTo2D();
 
-    ApplyOCSTransformer( poEllipse );
+    // disabled for ellipse entity
+    //ApplyOCSTransformer( poEllipse );
     poFeature->SetGeometryDirectly( poEllipse );
 
     PrepareLineStyle( poFeature );
@@ -1310,6 +1386,12 @@ OGRFeature *OGRDXFLayer::TranslateARC()
             break;
         }
     }
+    if( nCode < 0 )
+    {
+        DXF_LAYER_READER_ERROR();
+        delete poFeature;
+        return NULL;
+    }
 
     if( nCode == 0 )
         poDS->UnreadValue();
@@ -1320,8 +1402,8 @@ OGRFeature *OGRDXFLayer::TranslateARC()
     if( dfStartAngle > dfEndAngle )
         dfEndAngle += 360.0;
 
-    OGRGeometry *poArc = 
-        OGRGeometryFactory::approximateArcAngles( dfX1, dfY1, dfZ1, 
+    OGRGeometry *poArc =
+        OGRGeometryFactory::approximateArcAngles( dfX1, dfY1, dfZ1,
                                                   dfRadius, dfRadius, 0.0,
                                                   dfStartAngle, dfEndAngle,
                                                   0.0 );
@@ -1347,7 +1429,7 @@ OGRFeature *OGRDXFLayer::TranslateSPLINE()
 
 {
     char szLineBuf[257];
-    int nCode, nDegree = -1, nFlags = -1, bClosed = FALSE, i;
+    int nCode, nDegree = -1, bClosed = FALSE, i;
     OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
     std::vector<double> adfControlPoints;
 
@@ -1370,10 +1452,12 @@ OGRFeature *OGRDXFLayer::TranslateSPLINE()
             break;
 
           case 70:
-            nFlags = atoi(szLineBuf);
-            if( nFlags & 1 )
+          {
+            int l_nFlags = atoi(szLineBuf);
+            if( l_nFlags & 1 )
                 bClosed = TRUE;
             break;
+          }
 
           case 71:
             nDegree = atoi(szLineBuf);
@@ -1384,6 +1468,12 @@ OGRFeature *OGRDXFLayer::TranslateSPLINE()
             break;
         }
     }
+    if( nCode < 0 )
+    {
+        DXF_LAYER_READER_ERROR();
+        delete poFeature;
+        return NULL;
+    }
 
     if( nCode == 0 )
         poDS->UnreadValue();
@@ -1401,13 +1491,13 @@ OGRFeature *OGRDXFLayer::TranslateSPLINE()
 /* -------------------------------------------------------------------- */
 /*      Interpolate spline                                              */
 /* -------------------------------------------------------------------- */
-    int nControlPoints = adfControlPoints.size() / 3;
+    int nControlPoints = static_cast<int>(adfControlPoints.size()) / 3;
     std::vector<double> h, p;
 
     h.push_back(1.0);
     for( i = 0; i < nControlPoints; i++ )
         h.push_back( 1.0 );
-    
+
     // resolution:
     //int p1 = getGraphicVariableInt("$SPLINESEGS", 8) * npts;
     int p1 = nControlPoints * 8;
@@ -1417,12 +1507,12 @@ OGRFeature *OGRDXFLayer::TranslateSPLINE()
         p.push_back( 0.0 );
 
     if( bClosed )
-        rbsplinu( nControlPoints, nDegree+1, p1, &(adfControlPoints[0]), 
+        rbsplinu( nControlPoints, nDegree+1, p1, &(adfControlPoints[0]),
                   &(h[0]), &(p[0]) );
     else
-        rbspline( nControlPoints, nDegree+1, p1, &(adfControlPoints[0]), 
+        rbspline( nControlPoints, nDegree+1, p1, &(adfControlPoints[0]),
                   &(h[0]), &(p[0]) );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Turn into OGR geometry.                                         */
 /* -------------------------------------------------------------------- */
@@ -1515,6 +1605,12 @@ OGRFeature *OGRDXFLayer::Translate3DFACE()
             break;
         }
     }
+    if( nCode < 0 )
+    {
+        DXF_LAYER_READER_ERROR();
+        delete poFeature;
+        return NULL;
+    }
 
     if( nCode == 0 )
         poDS->UnreadValue();
@@ -1650,6 +1746,12 @@ OGRFeature *OGRDXFLayer::TranslateSOLID()
             break;
         }
     }
+    if( nCode < 0 )
+    {
+        DXF_LAYER_READER_ERROR();
+        delete poFeature;
+        return NULL;
+    }
 
     CPLDebug("Corner coordinates are", "%f,%f,%f,%f,%f,%f,%f,%f", dfX1, dfY1,
             dfX2, dfY2, dfX3, dfY3, dfX4, dfY4);
@@ -1708,7 +1810,7 @@ OGRFeature *OGRDXFLayer::TranslateSOLID()
 class GeometryInsertTransformer : public OGRCoordinateTransformation
 {
 public:
-    GeometryInsertTransformer() : 
+    GeometryInsertTransformer() :
             dfXOffset(0),dfYOffset(0),dfZOffset(0),
             dfXScale(1.0),dfYScale(1.0),dfZScale(1.0),
             dfAngle(0.0) {}
@@ -1723,11 +1825,11 @@ public:
 
     OGRSpatialReference *GetSourceCS() { return NULL; }
     OGRSpatialReference *GetTargetCS() { return NULL; }
-    int Transform( int nCount, 
+    int Transform( int nCount,
                    double *x, double *y, double *z )
         { return TransformEx( nCount, x, y, z, NULL ); }
-    
-    int TransformEx( int nCount, 
+
+    int TransformEx( int nCount,
                      double *x, double *y, double *z = NULL,
                      int *pabSuccess = NULL )
         {
@@ -1804,20 +1906,26 @@ OGRFeature *OGRDXFLayer::TranslateINSERT()
 
           case 50:
             dfAngle = CPLAtof(szLineBuf);
-            // We want to transform this to radians. 
+            // We want to transform this to radians.
             // It is apparently always in degrees regardless of $AUNITS
-            oTransformer.dfAngle = dfAngle * PI / 180.0;
+            oTransformer.dfAngle = dfAngle * M_PI / 180.0;
             break;
 
-          case 2: 
+          case 2:
             osBlockName = szLineBuf;
             break;
-            
+
           default:
             TranslateGenericProperty( poFeature, nCode, szLineBuf );
             break;
         }
     }
+    if( nCode < 0 )
+    {
+        DXF_LAYER_READER_ERROR();
+        delete poFeature;
+        return NULL;
+    }
 
     if( nCode == 0 )
         poDS->UnreadValue();
@@ -1830,7 +1938,7 @@ OGRFeature *OGRDXFLayer::TranslateINSERT()
     {
         // ApplyOCSTransformer( poGeom ); ?
         poFeature->SetGeometryDirectly(
-            new OGRPoint( oTransformer.dfXOffset, 
+            new OGRPoint( oTransformer.dfXOffset,
                           oTransformer.dfYOffset,
                           oTransformer.dfZOffset ) );
 
@@ -1846,7 +1954,7 @@ OGRFeature *OGRDXFLayer::TranslateINSERT()
 /*      Lookup the block.                                               */
 /* -------------------------------------------------------------------- */
     DXFBlockDefinition *poBlock = poDS->LookupBlock( osBlockName );
-    
+
     if( poBlock == NULL )
     {
         delete poFeature;
@@ -1945,13 +2053,12 @@ OGRFeature *OGRDXFLayer::GetNextUnfilteredFeature()
     {
         // read ahead to an entity.
         while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 ) {}
-
-        if( nCode == -1 )
+        if( nCode < 0 )
         {
-            CPLDebug( "DXF", "Unexpected end of data without ENDSEC." );
+            DXF_LAYER_READER_ERROR();
             return NULL;
         }
-        
+
         if( EQUAL(szLineBuf,"ENDSEC") )
         {
             //CPLDebug( "DXF", "Clean end of features at ENDSEC." );
@@ -1979,7 +2086,7 @@ OGRFeature *OGRDXFLayer::GetNextUnfilteredFeature()
         {
             poFeature = TranslateMTEXT();
         }
-        else if( EQUAL(szLineBuf,"TEXT") 
+        else if( EQUAL(szLineBuf,"TEXT")
                  || EQUAL(szLineBuf,"ATTDEF") )
         {
             poFeature = TranslateTEXT();
@@ -2037,7 +2144,7 @@ OGRFeature *OGRDXFLayer::GetNextUnfilteredFeature()
             if( oIgnoredEntities.count(szLineBuf) == 0 )
             {
                 oIgnoredEntities.insert( szLineBuf );
-                CPLDebug( "DWG", "Ignoring one or more of entity '%s'.", 
+                CPLDebug( "DWG", "Ignoring one or more of entity '%s'.",
                           szLineBuf );
             }
         }
@@ -2059,7 +2166,7 @@ OGRFeature *OGRDXFLayer::GetNextUnfilteredFeature()
 OGRFeature *OGRDXFLayer::GetNextFeature()
 
 {
-    while( TRUE )
+    while( true )
     {
         OGRFeature *poFeature = GetNextUnfilteredFeature();
 
@@ -2090,4 +2197,3 @@ int OGRDXFLayer::TestCapability( const char * pszCap )
     else
         return FALSE;
 }
-
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxfreader.cpp b/ogr/ogrsf_frmts/dxf/ogrdxfreader.cpp
index 79ddd90..9cec993 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxfreader.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxfreader.cpp
@@ -3,7 +3,7 @@
  *
  * Project:  DXF Translator
  * Purpose:  Implements low level DXF reading with caching and parsing of
- *           of the code/value pairs. 
+ *           of the code/value pairs.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -39,18 +39,14 @@ CPL_CVSID("$Id: ogrdxf_diskio.cpp 20278 2010-08-14 15:11:01Z warmerdam $");
 /*                            OGRDXFReader()                            */
 /************************************************************************/
 
-OGRDXFReader::OGRDXFReader()
-
-{
-    fp = NULL;
-
-    iSrcBufferOffset = 0;
-    nSrcBufferBytes = 0;
-    iSrcBufferFileOffset = 0;
-
-    nLastValueSize = 0;
-    nLineNumber = 0;
-}
+OGRDXFReader::OGRDXFReader() :
+    fp(NULL),
+    iSrcBufferOffset(0),
+    nSrcBufferBytes(0),
+    iSrcBufferFileOffset(0),
+    nLastValueSize(0),
+    nLineNumber(0)
+{}
 
 /************************************************************************/
 /*                           ~OGRDXFReader()                            */
@@ -65,10 +61,10 @@ OGRDXFReader::~OGRDXFReader()
 /*                             Initialize()                             */
 /************************************************************************/
 
-void OGRDXFReader::Initialize( VSILFILE *fp )
+void OGRDXFReader::Initialize( VSILFILE *fpIn )
 
 {
-    this->fp = fp;
+    fp = fpIn;
 }
 
 /************************************************************************/
@@ -109,13 +105,13 @@ void OGRDXFReader::LoadDiskChunk()
 
         memmove( achSrcBuffer, achSrcBuffer + iSrcBufferOffset,
                  nSrcBufferBytes - iSrcBufferOffset );
-        iSrcBufferFileOffset += iSrcBufferOffset; 
+        iSrcBufferFileOffset += iSrcBufferOffset;
         nSrcBufferBytes -= iSrcBufferOffset;
         iSrcBufferOffset = 0;
     }
 
-    nSrcBufferBytes += VSIFReadL( achSrcBuffer + nSrcBufferBytes, 
-                                  1, 512, fp );
+    nSrcBufferBytes += static_cast<int>(VSIFReadL( achSrcBuffer + nSrcBufferBytes,
+                                  1, 512, fp ));
     achSrcBuffer[nSrcBufferBytes] = '\0';
 
     CPLAssert( nSrcBufferBytes <= 1024 );
@@ -149,9 +145,9 @@ int OGRDXFReader::ReadValue( char *pszValueBuf, int nValueBufSize )
     nLineNumber ++;
 
     // proceed to newline.
-    while( achSrcBuffer[iSrcBufferOffset] != '\n' 
-           && achSrcBuffer[iSrcBufferOffset] != '\r' 
-           && achSrcBuffer[iSrcBufferOffset] != '\0' ) 
+    while( achSrcBuffer[iSrcBufferOffset] != '\n'
+           && achSrcBuffer[iSrcBufferOffset] != '\r'
+           && achSrcBuffer[iSrcBufferOffset] != '\0' )
         iSrcBufferOffset++;
 
     if( achSrcBuffer[iSrcBufferOffset] == '\0' )
@@ -177,9 +173,9 @@ int OGRDXFReader::ReadValue( char *pszValueBuf, int nValueBufSize )
     nLineNumber ++;
 
     // proceed to newline.
-    while( achSrcBuffer[iEOL] != '\n' 
-           && achSrcBuffer[iEOL] != '\r' 
-           && achSrcBuffer[iEOL] != '\0' ) 
+    while( achSrcBuffer[iEOL] != '\n'
+           && achSrcBuffer[iEOL] != '\r'
+           && achSrcBuffer[iEOL] != '\0' )
         iEOL++;
 
     if( achSrcBuffer[iEOL] == '\0' )
@@ -187,7 +183,7 @@ int OGRDXFReader::ReadValue( char *pszValueBuf, int nValueBufSize )
 
     if( (iEOL - iSrcBufferOffset) > nValueBufSize-1 )
     {
-        strncpy( pszValueBuf, achSrcBuffer + iSrcBufferOffset, 
+        strncpy( pszValueBuf, achSrcBuffer + iSrcBufferOffset,
                  nValueBufSize-1 );
         pszValueBuf[nValueBufSize-1] = '\0';
 
@@ -197,7 +193,7 @@ int OGRDXFReader::ReadValue( char *pszValueBuf, int nValueBufSize )
     }
     else
     {
-        strncpy( pszValueBuf, achSrcBuffer + iSrcBufferOffset, 
+        strncpy( pszValueBuf, achSrcBuffer + iSrcBufferOffset,
                  iEOL - iSrcBufferOffset );
         pszValueBuf[iEOL - iSrcBufferOffset] = '\0';
     }
@@ -244,4 +240,3 @@ void OGRDXFReader::UnreadValue()
 
     nLastValueSize = 0;
 }
-
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxfwriterds.cpp b/ogr/ogrsf_frmts/dxf/ogrdxfwriterds.cpp
index 9d61abb..adca3cf 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxfwriterds.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxfwriterds.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdxfwriterds.cpp 27945 2014-11-11 01:33:15Z rouault $
+ * $Id: ogrdxfwriterds.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  DXF Translator
  * Purpose:  Implements OGRDXFWriterDS - the OGRDataSource class used for
@@ -33,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrdxfwriterds.cpp 27945 2014-11-11 01:33:15Z rouault $");
+CPL_CVSID("$Id: ogrdxfwriterds.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                          OGRDXFWriterDS()                          */
@@ -83,7 +83,7 @@ OGRDXFWriterDS::~OGRDXFWriterDS()
                 VSIFWriteL( pszLine, 1, strlen(pszLine), fp );
                 VSIFWriteL( "\n", 1, 1, fp );
             }
-                    
+
 /* -------------------------------------------------------------------- */
 /*      Cleanup temporary file.                                         */
 /* -------------------------------------------------------------------- */
@@ -178,7 +178,7 @@ int OGRDXFWriterDS::Open( const char * pszFilename, char **papszOptions )
         const char *pszValue = CPLFindFile( "gdal", "header.dxf" );
         if( pszValue == NULL )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
+            CPLError( CE_Failure, CPLE_OpenFailed,
                       "Failed to find template header file header.dxf for reading,\nis GDAL_DATA set properly?" );
             return FALSE;
         }
@@ -231,8 +231,8 @@ int OGRDXFWriterDS::Open( const char * pszFilename, char **papszOptions )
 
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Failed to open '%s' for writing.", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to open '%s' for writing.",
                   pszFilename );
         return FALSE;
     }
@@ -246,8 +246,8 @@ int OGRDXFWriterDS::Open( const char * pszFilename, char **papszOptions )
     fpTemp = VSIFOpenL( osTempFilename, "w" );
     if( fpTemp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Failed to open '%s' for writing.", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to open '%s' for writing.",
                   osTempFilename.c_str() );
         return FALSE;
     }
@@ -259,9 +259,9 @@ int OGRDXFWriterDS::Open( const char * pszFilename, char **papszOptions )
 /*                           ICreateLayer()                             */
 /************************************************************************/
 
-OGRLayer *OGRDXFWriterDS::ICreateLayer( const char *pszName, 
-                                       OGRSpatialReference *, 
-                                       OGRwkbGeometryType, 
+OGRLayer *OGRDXFWriterDS::ICreateLayer( const char *pszName,
+                                       OGRSpatialReference *,
+                                       OGRwkbGeometryType,
                                        char ** )
 
 {
@@ -340,12 +340,12 @@ int OGRDXFWriterDS::TransferUpdateHeader( VSILFILE *fpOut )
     int nCode;
     CPLString osSection, osTable, osEntity;
 
-    while( (nCode = oHeaderDS.ReadValue( szLineBuf, sizeof(szLineBuf) )) != -1 
+    while( (nCode = oHeaderDS.ReadValue( szLineBuf, sizeof(szLineBuf) )) != -1
            && osSection != "ENTITIES" )
     {
         if( nCode == 0 && EQUAL(szLineBuf,"ENDTAB") )
         {
-            // If we are at the end of the LAYER TABLE consider inserting 
+            // If we are at the end of the LAYER TABLE consider inserting
             // missing definitions.
             if( osTable == "LAYER" )
             {
@@ -353,7 +353,7 @@ int OGRDXFWriterDS::TransferUpdateHeader( VSILFILE *fpOut )
                     return FALSE;
             }
 
-            // If at the end of the BLOCK_RECORD TABLE consider inserting 
+            // If at the end of the BLOCK_RECORD TABLE consider inserting
             // missing definitions.
             if( osTable == "BLOCK_RECORD" && poBlocksLayer )
             {
@@ -361,7 +361,7 @@ int OGRDXFWriterDS::TransferUpdateHeader( VSILFILE *fpOut )
                     return FALSE;
             }
 
-            // If at the end of the LTYPE TABLE consider inserting 
+            // If at the end of the LTYPE TABLE consider inserting
             // missing layer type definitions.
             if( osTable == "LTYPE" )
             {
@@ -373,8 +373,8 @@ int OGRDXFWriterDS::TransferUpdateHeader( VSILFILE *fpOut )
         }
 
         // If we are at the end of the BLOCKS section, consider inserting
-        // suplementary blocks. 
-        if( nCode == 0 && osSection == "BLOCKS" && EQUAL(szLineBuf,"ENDSEC") 
+        // supplementary blocks.
+        if( nCode == 0 && osSection == "BLOCKS" && EQUAL(szLineBuf,"ENDSEC")
             && poBlocksLayer != NULL )
         {
             if( !WriteNewBlockDefinitions( fp ) )
@@ -382,7 +382,7 @@ int OGRDXFWriterDS::TransferUpdateHeader( VSILFILE *fpOut )
         }
 
         // We need to keep track of where $HANDSEED is so that we can
-        // come back and fix it up when we have generated all entity ids. 
+        // come back and fix it up when we have generated all entity ids.
         if( nCode == 9 && EQUAL(szLineBuf,"$HANDSEED") )
         {
             if( !WriteValue( fpOut, nCode, szLineBuf ) )
@@ -463,7 +463,7 @@ int OGRDXFWriterDS::TransferUpdateHeader( VSILFILE *fpOut )
 
             if( !WriteValue( fpOut, nCode, szLineBuf ) )
                 return FALSE;
-                
+
             osSection = szLineBuf;
         }
 
@@ -476,14 +476,14 @@ int OGRDXFWriterDS::TransferUpdateHeader( VSILFILE *fpOut )
 
             osTable = szLineBuf;
         }
-        
+
         // If we are starting the first layer, then capture
         // the layer contents while copying so we can duplicate
         // it for any new layer definitions.
         if( nCode == 0 && EQUAL(szLineBuf,"LAYER")
             && osTable == "LAYER" && aosDefaultLayerText.size() == 0 )
         {
-            do { 
+            do {
                 anDefaultLayerCode.push_back( nCode );
                 aosDefaultLayerText.push_back( szLineBuf );
 
@@ -505,7 +505,7 @@ int OGRDXFWriterDS::TransferUpdateHeader( VSILFILE *fpOut )
     }
 
     return TRUE;
-}    
+}
 
 /************************************************************************/
 /*                       TransferUpdateTrailer()                        */
@@ -514,17 +514,17 @@ int OGRDXFWriterDS::TransferUpdateHeader( VSILFILE *fpOut )
 int OGRDXFWriterDS::TransferUpdateTrailer( VSILFILE *fpOut )
 {
     OGRDXFReader oReader;
-    VSILFILE *fp;
+    VSILFILE *l_fp;
 
 /* -------------------------------------------------------------------- */
 /*      Open the file and setup a reader.                               */
 /* -------------------------------------------------------------------- */
-    fp = VSIFOpenL( osTrailerFile, "r" );
+    l_fp = VSIFOpenL( osTrailerFile, "r" );
 
-    if( fp == NULL )
+    if( l_fp == NULL )
         return FALSE;
 
-    oReader.Initialize( fp );
+    oReader.Initialize( l_fp );
 
 /* -------------------------------------------------------------------- */
 /*      Scan ahead to find the OBJECTS section.                         */
@@ -570,7 +570,7 @@ int OGRDXFWriterDS::TransferUpdateTrailer( VSILFILE *fpOut )
         }
     }
 
-    VSIFCloseL( fp );
+    VSIFCloseL( l_fp );
 
     return TRUE;
 }
@@ -582,7 +582,7 @@ int OGRDXFWriterDS::TransferUpdateTrailer( VSILFILE *fpOut )
 /*      variable.                                                       */
 /************************************************************************/
 
-int OGRDXFWriterDS::FixupHANDSEED( VSILFILE *fp )
+int OGRDXFWriterDS::FixupHANDSEED( VSILFILE *fpIn )
 
 {
 /* -------------------------------------------------------------------- */
@@ -591,7 +591,7 @@ int OGRDXFWriterDS::FixupHANDSEED( VSILFILE *fp )
     unsigned int   nHighestHandle = 0;
     std::set<CPLString>::iterator it;
 
-    for( it = aosUsedEntities.begin(); it != aosUsedEntities.end(); it++ ) 
+    for( it = aosUsedEntities.begin(); it != aosUsedEntities.end(); it++ )
     {
         unsigned int nHandle;
         if( sscanf( (*it).c_str(), "%x", &nHandle ) == 1 )
@@ -610,22 +610,22 @@ int OGRDXFWriterDS::FixupHANDSEED( VSILFILE *fp )
     if( nHANDSEEDOffset == 0 )
         return FALSE;
 
-    VSIFSeekL( fp, nHANDSEEDOffset, SEEK_SET );
-    VSIFReadL( szWorkBuf, 1, sizeof(szWorkBuf), fp );
-    
+    VSIFSeekL( fpIn, nHANDSEEDOffset, SEEK_SET );
+    VSIFReadL( szWorkBuf, 1, sizeof(szWorkBuf), fpIn );
+
     while( szWorkBuf[i] != '\n' )
         i++;
 
     i++;
     if( szWorkBuf[i] == '\r' )
         i++;
-    
+
     CPLString osNewValue;
 
     osNewValue.Printf( "%08X", nHighestHandle + 1 );
     strncpy( szWorkBuf + i, osNewValue.c_str(), osNewValue.size() );
 
-    VSIFSeekL( fp, nHANDSEEDOffset, SEEK_SET );
+    VSIFSeekL( fpIn, nHANDSEEDOffset, SEEK_SET );
     VSIFWriteL( szWorkBuf, 1, sizeof(szWorkBuf), fp );
 
     return TRUE;
@@ -637,7 +637,7 @@ int OGRDXFWriterDS::FixupHANDSEED( VSILFILE *fp )
 
 int  OGRDXFWriterDS::WriteNewLayerDefinitions( VSILFILE * fpOut )
 
-{                                               
+{
     int iLayer, nNewLayers = CSLCount(papszLayersToCreate);
 
     for( iLayer = 0; iLayer < nNewLayers; iLayer++ )
@@ -670,30 +670,30 @@ int  OGRDXFWriterDS::WriteNewLayerDefinitions( VSILFILE * fpOut )
 /*                      WriteNewLineTypeRecords()                       */
 /************************************************************************/
 
-int OGRDXFWriterDS::WriteNewLineTypeRecords( VSILFILE *fp )
+int OGRDXFWriterDS::WriteNewLineTypeRecords( VSILFILE *fpIn )
 
 {
     if( poLayer == NULL )
         return TRUE;
 
     std::map<CPLString,CPLString>::iterator oIt;
-    std::map<CPLString,CPLString>& oNewLineTypes = 
+    std::map<CPLString,CPLString>& oNewLineTypes =
         poLayer->GetNewLineTypeMap();
 
-    for( oIt = oNewLineTypes.begin(); 
+    for( oIt = oNewLineTypes.begin();
          oIt != oNewLineTypes.end(); oIt++ )
     {
-        WriteValue( fp, 0, "LTYPE" );
-        WriteEntityID( fp );
-        WriteValue( fp, 100, "AcDbSymbolTableRecord" );
-        WriteValue( fp, 100, "AcDbLinetypeTableRecord" );
-        WriteValue( fp, 2, (*oIt).first );
-        WriteValue( fp, 70, "0" );
-        WriteValue( fp, 3, "" );
-        WriteValue( fp, 72, "65" );
-        VSIFWriteL( (*oIt).second.c_str(), 1, (*oIt).second.size(), fp );
-
-        CPLDebug( "DXF", "Define Line type '%s'.", 
+        WriteValue( fpIn, 0, "LTYPE" );
+        WriteEntityID( fpIn );
+        WriteValue( fpIn, 100, "AcDbSymbolTableRecord" );
+        WriteValue( fpIn, 100, "AcDbLinetypeTableRecord" );
+        WriteValue( fpIn, 2, (*oIt).first );
+        WriteValue( fpIn, 70, "0" );
+        WriteValue( fpIn, 3, "" );
+        WriteValue( fpIn, 72, "65" );
+        VSIFWriteL( (*oIt).second.c_str(), 1, (*oIt).second.size(), fpIn );
+
+        CPLDebug( "DXF", "Define Line type '%s'.",
                   (*oIt).first.c_str() );
     }
 
@@ -704,7 +704,7 @@ int OGRDXFWriterDS::WriteNewLineTypeRecords( VSILFILE *fp )
 /*                        WriteNewBlockRecords()                        */
 /************************************************************************/
 
-int OGRDXFWriterDS::WriteNewBlockRecords( VSILFILE * fp )
+int OGRDXFWriterDS::WriteNewBlockRecords( VSILFILE * fpIn )
 
 {
     std::set<CPLString> aosAlreadyHandled;
@@ -735,12 +735,12 @@ int OGRDXFWriterDS::WriteNewBlockRecords( VSILFILE * fp )
 /* -------------------------------------------------------------------- */
 /*      Write the block record.                                         */
 /* -------------------------------------------------------------------- */
-        WriteValue( fp, 0, "BLOCK_RECORD" );
-        WriteEntityID( fp );
-        WriteValue( fp, 100, "AcDbSymbolTableRecord" );
-        WriteValue( fp, 100, "AcDbBlockTableRecord" );
-        WriteValue( fp, 2, poThisBlockFeat->GetFieldAsString("BlockName") );
-        if( !WriteValue( fp, 340, "0" ) )
+        WriteValue( fpIn, 0, "BLOCK_RECORD" );
+        WriteEntityID( fpIn );
+        WriteValue( fpIn, 100, "AcDbSymbolTableRecord" );
+        WriteValue( fpIn, 100, "AcDbBlockTableRecord" );
+        WriteValue( fpIn, 2, poThisBlockFeat->GetFieldAsString("BlockName") );
+        if( !WriteValue( fpIn, 340, "0" ) )
             return FALSE;
     }
 
@@ -751,10 +751,10 @@ int OGRDXFWriterDS::WriteNewBlockRecords( VSILFILE * fp )
 /*                      WriteNewBlockDefinitions()                      */
 /************************************************************************/
 
-int OGRDXFWriterDS::WriteNewBlockDefinitions( VSILFILE * fp )
+int OGRDXFWriterDS::WriteNewBlockDefinitions( VSILFILE * fpIn )
 
 {
-    poLayer->ResetFP( fp );
+    poLayer->ResetFP( fpIn );
 
 /* ==================================================================== */
 /*      Loop over all block objects written via the blocks layer.       */
@@ -777,24 +777,24 @@ int OGRDXFWriterDS::WriteNewBlockDefinitions( VSILFILE * fp )
         CPLDebug( "DXF", "Writing BLOCK definition for '%s'.",
                   poThisBlockFeat->GetFieldAsString("BlockName") );
 
-        WriteValue( fp, 0, "BLOCK" );
-        WriteEntityID( fp );
-        WriteValue( fp, 100, "AcDbEntity" );
+        WriteValue( fpIn, 0, "BLOCK" );
+        WriteEntityID( fpIn );
+        WriteValue( fpIn, 100, "AcDbEntity" );
         if( strlen(poThisBlockFeat->GetFieldAsString("Layer")) > 0 )
-            WriteValue( fp, 8, poThisBlockFeat->GetFieldAsString("Layer") );
+            WriteValue( fpIn, 8, poThisBlockFeat->GetFieldAsString("Layer") );
         else
-            WriteValue( fp, 8, "0" );
-        WriteValue( fp, 100, "AcDbBlockBegin" );
-        WriteValue( fp, 2, poThisBlockFeat->GetFieldAsString("BlockName") );
-        WriteValue( fp, 70, "0" );
+            WriteValue( fpIn, 8, "0" );
+        WriteValue( fpIn, 100, "AcDbBlockBegin" );
+        WriteValue( fpIn, 2, poThisBlockFeat->GetFieldAsString("BlockName") );
+        WriteValue( fpIn, 70, "0" );
 
         // Origin
-        WriteValue( fp, 10, "0.0" );
-        WriteValue( fp, 20, "0.0" );
-        WriteValue( fp, 30, "0.0" );
+        WriteValue( fpIn, 10, "0.0" );
+        WriteValue( fpIn, 20, "0.0" );
+        WriteValue( fpIn, 30, "0.0" );
 
-        WriteValue( fp, 3, poThisBlockFeat->GetFieldAsString("BlockName") );
-        WriteValue( fp, 1, "" );
+        WriteValue( fpIn, 3, poThisBlockFeat->GetFieldAsString("BlockName") );
+        WriteValue( fpIn, 1, "" );
 
 /* -------------------------------------------------------------------- */
 /*      Write out the feature entities.                                 */
@@ -805,28 +805,28 @@ int OGRDXFWriterDS::WriteNewBlockDefinitions( VSILFILE * fp )
 /* -------------------------------------------------------------------- */
 /*      Write out following features if they are the same block.        */
 /* -------------------------------------------------------------------- */
-        while( iBlock < poBlocksLayer->apoBlocks.size()-1 
+        while( iBlock < poBlocksLayer->apoBlocks.size()-1
             && EQUAL(poBlocksLayer->apoBlocks[iBlock+1]->GetFieldAsString("BlockName"),
                      osBlockName) )
         {
             iBlock++;
-            
+
             if( poLayer->CreateFeature( poBlocksLayer->apoBlocks[iBlock] )
                 != OGRERR_NONE )
                 return FALSE;
         }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Write out the block definition postamble.                       */
 /* -------------------------------------------------------------------- */
-        WriteValue( fp, 0, "ENDBLK" );
-        WriteEntityID( fp );
-        WriteValue( fp, 100, "AcDbEntity" );
+        WriteValue( fpIn, 0, "ENDBLK" );
+        WriteEntityID( fpIn );
+        WriteValue( fpIn, 100, "AcDbEntity" );
         if( strlen(poThisBlockFeat->GetFieldAsString("Layer")) > 0 )
-            WriteValue( fp, 8, poThisBlockFeat->GetFieldAsString("Layer") );
+            WriteValue( fpIn, 8, poThisBlockFeat->GetFieldAsString("Layer") );
         else
-            WriteValue( fp, 8, "0" );
-        WriteValue( fp, 100, "AcDbBlockEnd" );
+            WriteValue( fpIn, 8, "0" );
+        WriteValue( fpIn, 100, "AcDbBlockEnd" );
     }
 
     return TRUE;
@@ -845,17 +845,17 @@ void OGRDXFWriterDS::ScanForEntities( const char *pszFilename,
 
 {
     OGRDXFReader oReader;
-    VSILFILE *fp;
+    VSILFILE *l_fp;
 
 /* -------------------------------------------------------------------- */
 /*      Open the file and setup a reader.                               */
 /* -------------------------------------------------------------------- */
-    fp = VSIFOpenL( pszFilename, "r" );
+    l_fp = VSIFOpenL( pszFilename, "r" );
 
-    if( fp == NULL )
+    if( l_fp == NULL )
         return;
 
-    oReader.Initialize( fp );
+    oReader.Initialize( l_fp );
 
 /* -------------------------------------------------------------------- */
 /*      Add every code "5" line to our entities list.                   */
@@ -871,7 +871,7 @@ void OGRDXFWriterDS::ScanForEntities( const char *pszFilename,
             CPLString osEntity( szLineBuf );
 
             if( CheckEntityID( osEntity ) )
-                CPLDebug( "DXF", "Encounted entity '%s' multiple times.",
+                CPLDebug( "DXF", "Encountered entity '%s' multiple times.",
                           osEntity.c_str() );
             else
                 aosUsedEntities.insert( osEntity );
@@ -887,7 +887,7 @@ void OGRDXFWriterDS::ScanForEntities( const char *pszFilename,
         }
     }
 
-    VSIFCloseL( fp );
+    VSIFCloseL( l_fp );
 }
 
 /************************************************************************/
@@ -912,31 +912,31 @@ int OGRDXFWriterDS::CheckEntityID( const char *pszEntityID )
 /*                           WriteEntityID()                            */
 /************************************************************************/
 
-long OGRDXFWriterDS::WriteEntityID( VSILFILE *fp, long nPreferredFID )
+long OGRDXFWriterDS::WriteEntityID( VSILFILE *fpIn, long nPreferredFID )
 
 {
     CPLString osEntityID;
 
     if( nPreferredFID != OGRNullFID )
     {
-        
+
         osEntityID.Printf( "%X", (unsigned int) nPreferredFID );
         if( !CheckEntityID( osEntityID ) )
         {
             aosUsedEntities.insert( osEntityID );
-            WriteValue( fp, 5, osEntityID );
+            WriteValue( fpIn, 5, osEntityID );
             return nPreferredFID;
         }
     }
 
-    do 
+    do
     {
         osEntityID.Printf( "%X", nNextFID++ );
     }
     while( CheckEntityID( osEntityID ) );
-    
+
     aosUsedEntities.insert( osEntityID );
-    WriteValue( fp, 5, osEntityID );
+    WriteValue( fpIn, 5, osEntityID );
 
     return nNextFID - 1;
 }
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxfwriterlayer.cpp b/ogr/ogrsf_frmts/dxf/ogrdxfwriterlayer.cpp
index de8c832..aa6de22 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxfwriterlayer.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxfwriterlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdxfwriterlayer.cpp 28382 2015-01-30 15:29:41Z rouault $
+ * $Id: ogrdxfwriterlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  DXF Translator
  * Purpose:  Implements OGRDXFWriterLayer - the OGRLayer class used for
@@ -34,24 +34,20 @@
 #include "cpl_string.h"
 #include "ogr_featurestyle.h"
 
-CPL_CVSID("$Id: ogrdxfwriterlayer.cpp 28382 2015-01-30 15:29:41Z rouault $");
-
-#ifndef PI
-#define PI  3.14159265358979323846
-#endif 
+CPL_CVSID("$Id: ogrdxfwriterlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                         OGRDXFWriterLayer()                          */
 /************************************************************************/
 
-OGRDXFWriterLayer::OGRDXFWriterLayer( OGRDXFWriterDS *poDS, VSILFILE *fp )
+OGRDXFWriterLayer::OGRDXFWriterLayer( OGRDXFWriterDS *poDSIn, VSILFILE *fpIn )
 
 {
-    this->fp = fp;
-    this->poDS = poDS;
+    this->fp = fpIn;
+    this->poDS = poDSIn;
 
     nNextAutoID = 1;
-    bWriteHatch = CSLTestBoolean(CPLGetConfigOption("DXF_WRITE_HATCH", "YES"));
+    bWriteHatch = CPLTestBool(CPLGetConfigOption("DXF_WRITE_HATCH", "YES"));
 
     poFeatureDefn = new OGRFeatureDefn( "entities" );
     poFeatureDefn->Reference();
@@ -76,10 +72,10 @@ OGRDXFWriterLayer::OGRDXFWriterLayer( OGRDXFWriterDS *poDS, VSILFILE *fp )
 
     OGRFieldDefn  oBlockField( "BlockName", OFTString );
     poFeatureDefn->AddFieldDefn( &oBlockField );
-    
+
     OGRFieldDefn  oScaleField( "BlockScale", OFTRealList );
     poFeatureDefn->AddFieldDefn( &oScaleField );
-    
+
     OGRFieldDefn  oBlockAngleField( "BlockAngle", OFTReal );
     poFeatureDefn->AddFieldDefn( &oBlockAngleField );
 }
@@ -118,7 +114,7 @@ int OGRDXFWriterLayer::TestCapability( const char * pszCap )
         return TRUE;
     else if( EQUAL(pszCap,OLCSequentialWrite) )
         return TRUE;
-    else 
+    else
         return FALSE;
 }
 
@@ -161,7 +157,7 @@ int OGRDXFWriterLayer::WriteValue( int nCode, const char *pszValue )
 
     osLinePair += "\n";
 
-    return VSIFWriteL( osLinePair.c_str(), 
+    return VSIFWriteL( osLinePair.c_str(),
                        1, osLinePair.size(), fp ) == osLinePair.size();
 }
 
@@ -176,7 +172,7 @@ int OGRDXFWriterLayer::WriteValue( int nCode, int nValue )
 
     osLinePair.Printf( "%3d\n%d\n", nCode, nValue );
 
-    return VSIFWriteL( osLinePair.c_str(), 
+    return VSIFWriteL( osLinePair.c_str(),
                        1, osLinePair.size(), fp ) == osLinePair.size();
 }
 
@@ -192,7 +188,7 @@ int OGRDXFWriterLayer::WriteValue( int nCode, double dfValue )
     CPLsnprintf(szLinePair, sizeof(szLinePair), "%3d\n%.15g\n", nCode, dfValue );
     size_t nLen = strlen(szLinePair);
 
-    return VSIFWriteL( szLinePair, 
+    return VSIFWriteL( szLinePair,
                        1, nLen, fp ) == nLen;
 }
 
@@ -225,12 +221,12 @@ OGRErr OGRDXFWriterLayer::WriteCore( OGRFeature *poFeature )
     }
     else
     {
-        const char *pszExists = 
+        const char *pszExists =
             poDS->oHeaderDS.LookupLayerProperty( pszLayer, "Exists" );
         if( (pszExists == NULL || strlen(pszExists) == 0)
             && CSLFindString( poDS->papszLayersToCreate, pszLayer ) == -1 )
         {
-            poDS->papszLayersToCreate = 
+            poDS->papszLayersToCreate =
                 CSLAddString( poDS->papszLayersToCreate, pszLayer );
         }
 
@@ -272,14 +268,14 @@ OGRErr OGRDXFWriterLayer::WriteINSERT( OGRFeature *poFeature )
             WriteValue( 62, ColorStringToDXFColor( poSymbol->Color(bDefault) ) );
     }
     delete poTool;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Write location.                                                 */
 /* -------------------------------------------------------------------- */
     OGRPoint *poPoint = (OGRPoint *) poFeature->GetGeometryRef();
 
     WriteValue( 10, poPoint->getX() );
-    if( !WriteValue( 20, poPoint->getY() ) ) 
+    if( !WriteValue( 20, poPoint->getY() ) )
         return OGRERR_FAILURE;
 
     if( poPoint->getGeometryType() == wkbPoint25D )
@@ -287,12 +283,12 @@ OGRErr OGRDXFWriterLayer::WriteINSERT( OGRFeature *poFeature )
         if( !WriteValue( 30, poPoint->getZ() ) )
             return OGRERR_FAILURE;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Write scaling.                                                  */
 /* -------------------------------------------------------------------- */
     int nScaleCount;
-    const double *padfScale = 
+    const double *padfScale =
         poFeature->GetFieldAsDoubleList( "BlockScale", &nScaleCount );
 
     if( nScaleCount == 3 )
@@ -350,7 +346,7 @@ OGRErr OGRDXFWriterLayer::WritePOINT( OGRFeature *poFeature )
     OGRPoint *poPoint = (OGRPoint *) poFeature->GetGeometryRef();
 
     WriteValue( 10, poPoint->getX() );
-    if( !WriteValue( 20, poPoint->getY() ) ) 
+    if( !WriteValue( 20, poPoint->getY() ) )
         return OGRERR_FAILURE;
 
     if( poPoint->getGeometryType() == wkbPoint25D )
@@ -358,7 +354,7 @@ OGRErr OGRDXFWriterLayer::WritePOINT( OGRFeature *poFeature )
         if( !WriteValue( 30, poPoint->getZ() ) )
             return OGRERR_FAILURE;
     }
-    
+
     return OGRERR_NONE;
 }
 
@@ -375,8 +371,8 @@ CPLString OGRDXFWriterLayer::TextEscape( const char *pszInput )
 
 {
     CPLString osResult;
-    wchar_t *panInput = CPLRecodeToWChar( pszInput, 
-                                          CPL_ENC_UTF8, 
+    wchar_t *panInput = CPLRecodeToWChar( pszInput,
+                                          CPL_ENC_UTF8,
                                           CPL_ENC_UCS2 );
     int i;
 
@@ -400,7 +396,7 @@ CPLString OGRDXFWriterLayer::TextEscape( const char *pszInput )
     }
 
     CPLFree(panInput);
-    
+
     return osResult;
 }
 
@@ -442,7 +438,7 @@ OGRErr OGRDXFWriterLayer::WriteTEXT( OGRFeature *poFeature )
 /*      Color                                                           */
 /* -------------------------------------------------------------------- */
         if( poLabel->ForeColor(bDefault) != NULL && !bDefault )
-            WriteValue( 62, ColorStringToDXFColor( 
+            WriteValue( 62, ColorStringToDXFColor(
                             poLabel->ForeColor(bDefault) ) );
 
 /* -------------------------------------------------------------------- */
@@ -469,10 +465,10 @@ OGRErr OGRDXFWriterLayer::WriteTEXT( OGRFeature *poFeature )
 /*      Anchor / Attachment Point                                       */
 /* -------------------------------------------------------------------- */
         int nAnchor = poLabel->Anchor(bDefault);
-        
+
         if( !bDefault )
         {
-            const static int anAnchorMap[] = 
+            const static int anAnchorMap[] =
                 { -1, 7, 8, 9, 4, 5, 6, 1, 2, 3, 7, 8, 9 };
 
             if( nAnchor > 0 && nAnchor < 13 )
@@ -499,7 +495,7 @@ OGRErr OGRDXFWriterLayer::WriteTEXT( OGRFeature *poFeature )
     OGRPoint *poPoint = (OGRPoint *) poFeature->GetGeometryRef();
 
     WriteValue( 10, poPoint->getX() );
-    if( !WriteValue( 20, poPoint->getY() ) ) 
+    if( !WriteValue( 20, poPoint->getY() ) )
         return OGRERR_FAILURE;
 
     if( poPoint->getGeometryType() == wkbPoint25D )
@@ -507,7 +503,7 @@ OGRErr OGRDXFWriterLayer::WriteTEXT( OGRFeature *poFeature )
         if( !WriteValue( 30, poPoint->getZ() ) )
             return OGRERR_FAILURE;
     }
-    
+
     return OGRERR_NONE;
 
 }
@@ -528,7 +524,7 @@ OGRDXFWriterLayer::PrepareLineTypeDefinition( CPL_UNUSED OGRFeature *poFeature,
 /*      Fetch pattern.                                                  */
 /* -------------------------------------------------------------------- */
     pszPattern = poPen->Pattern( bDefault );
-    if( bDefault || strlen(pszPattern) == 0 ) 
+    if( bDefault || strlen(pszPattern) == 0 )
         return "";
 
 /* -------------------------------------------------------------------- */
@@ -546,23 +542,21 @@ OGRDXFWriterLayer::PrepareLineTypeDefinition( CPL_UNUSED OGRFeature *poFeature,
         CPLString osDXFEntry;
 
         // Split amount and unit.
-        for( pszUnit = pszToken; 
+        for( pszUnit = pszToken;
              strchr( "0123456789.", *pszUnit) != NULL;
              pszUnit++ ) {}
 
         osAmount.assign(pszToken,(int) (pszUnit-pszToken));
-        
-        // If the unit is other than 'g' we really should be trying to 
+
+        // If the unit is other than 'g' we really should be trying to
         // do some type of transformation - but what to do?  Pretty hard.
-        
-        // 
 
         // Even entries are "pen down" represented as negative in DXF.
         if( i%2 == 0 )
             osDXFEntry.Printf( " 49\n-%s\n 74\n0\n", osAmount.c_str() );
         else
             osDXFEntry.Printf( " 49\n%s\n 74\n0\n", osAmount.c_str() );
-        
+
         osDef += osDXFEntry;
 
         dfTotalLength += CPLAtof(osAmount);
@@ -572,9 +566,9 @@ OGRDXFWriterLayer::PrepareLineTypeDefinition( CPL_UNUSED OGRFeature *poFeature,
 /*      Prefix 73 and 40 items to the definition.                       */
 /* -------------------------------------------------------------------- */
     CPLString osPrefix;
-    
-    osPrefix.Printf( " 73\n%d\n 40\n%.6g\n", 
-                     CSLCount(papszTokens), 
+
+    osPrefix.Printf( " 73\n%d\n 40\n%.6g\n",
+                     CSLCount(papszTokens),
                      dfTotalLength );
     osDef = osPrefix + osDef;
 
@@ -602,16 +596,16 @@ OGRErr OGRDXFWriterLayer::WritePOLYLINE( OGRFeature *poFeature,
     {
         return OGRERR_NONE;
     }
-            
-    if( wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon 
+
+    if( wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon
         || wkbFlatten(poGeom->getGeometryType()) == wkbMultiLineString )
     {
         OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeom;
         int iGeom;
         OGRErr eErr = OGRERR_NONE;
 
-        for( iGeom = 0; 
-             eErr == OGRERR_NONE && iGeom < poGC->getNumGeometries(); 
+        for( iGeom = 0;
+             eErr == OGRERR_NONE && iGeom < poGC->getNumGeometries();
              iGeom++ )
         {
             eErr = WritePOLYLINE( poFeature, poGC->getGeometryRef( iGeom ) );
@@ -630,8 +624,8 @@ OGRErr OGRDXFWriterLayer::WritePOLYLINE( OGRFeature *poFeature,
         OGRErr eErr;
 
         eErr = WritePOLYLINE( poFeature, poPoly->getExteriorRing() );
-        for( iGeom = 0; 
-             eErr == OGRERR_NONE && iGeom < poPoly->getNumInteriorRings(); 
+        for( iGeom = 0;
+             eErr == OGRERR_NONE && iGeom < poPoly->getNumInteriorRings();
              iGeom++ )
         {
             eErr = WritePOLYLINE( poFeature, poPoly->getInteriorRing(iGeom) );
@@ -713,7 +707,7 @@ OGRErr OGRDXFWriterLayer::WritePOLYLINE( OGRFeature *poFeature,
         if( poPen->Color(bDefault) != NULL && !bDefault )
             WriteValue( 62, ColorStringToDXFColor( poPen->Color(bDefault) ) );
 
-        // we want to fetch the width in ground units. 
+        // we want to fetch the width in ground units.
         poPen->SetUnit( OGRSTUGround, 1.0 );
         double dfWidth = poPen->Width(bDefault);
 
@@ -726,8 +720,8 @@ OGRErr OGRDXFWriterLayer::WritePOLYLINE( OGRFeature *poFeature,
 /* -------------------------------------------------------------------- */
     CPLString osLineType = poFeature->GetFieldAsString( "Linetype" );
 
-    if( osLineType.size() > 0 
-        && (poDS->oHeaderDS.LookupLineType( osLineType ) != NULL 
+    if( osLineType.size() > 0
+        && (poDS->oHeaderDS.LookupLineType( osLineType ) != NULL
             || oNewLineTypes.count(osLineType) > 0 ) )
     {
         // Already define -> just reference it.
@@ -735,7 +729,7 @@ OGRErr OGRDXFWriterLayer::WritePOLYLINE( OGRFeature *poFeature,
     }
     else if( poTool != NULL && poTool->GetType() == OGRSTCPen )
     {
-        CPLString osDefinition = PrepareLineTypeDefinition( poFeature, 
+        CPLString osDefinition = PrepareLineTypeDefinition( poFeature,
                                                             poTool );
 
         if( osDefinition != "" && osLineType == "" )
@@ -757,8 +751,8 @@ OGRErr OGRDXFWriterLayer::WritePOLYLINE( OGRFeature *poFeature,
             // create an automatic name for it.
             if( osLineType == "" )
             {
-                do 
-                { 
+                do
+                {
                     osLineType.Printf( "AutoLineType-%d", nNextAutoID++ );
                 }
                 while( poDS->oHeaderDS.LookupLineType(osLineType) != NULL );
@@ -788,7 +782,7 @@ OGRErr OGRDXFWriterLayer::WritePOLYLINE( OGRFeature *poFeature,
 
     for( iVert = 0; iVert < poLS->getNumPoints(); iVert++ )
     {
-        if( bHasDifferentZ ) 
+        if( bHasDifferentZ )
         {
             WriteValue( 0, "VERTEX" );
             WriteValue( 100, "AcDbEntity" );
@@ -797,7 +791,7 @@ OGRErr OGRDXFWriterLayer::WritePOLYLINE( OGRFeature *poFeature,
             WriteCore( poFeature );
         }
         WriteValue( 10, poLS->getX(iVert) );
-        if( !WriteValue( 20, poLS->getY(iVert) ) ) 
+        if( !WriteValue( 20, poLS->getY(iVert) ) )
             return OGRERR_FAILURE;
 
         if( bHasDifferentZ )
@@ -814,7 +808,7 @@ OGRErr OGRDXFWriterLayer::WritePOLYLINE( OGRFeature *poFeature,
         WriteCore( poFeature );
         WriteValue( 100, "AcDbEntity" );
     }
-    
+
     delete poTool;
 
     return OGRERR_NONE;
@@ -840,7 +834,7 @@ OGRErr OGRDXFWriterLayer::WritePOLYLINE( OGRFeature *poFeature,
         WriteValue( 0, "VERTEX" );
         WriteValue( 8, "0" );
         WriteValue( 10, poLS->getX(iVert) );
-        if( !WriteValue( 20, poLS->getY(iVert) ) ) 
+        if( !WriteValue( 20, poLS->getY(iVert) ) )
             return OGRERR_FAILURE;
 
         if( poLS->getGeometryType() == wkbLineString25D )
@@ -852,7 +846,7 @@ OGRErr OGRDXFWriterLayer::WritePOLYLINE( OGRFeature *poFeature,
 
     WriteValue( 0, "SEQEND" );
     WriteValue( 8, "0" );
-    
+
     return OGRERR_NONE;
 #endif
 }
@@ -876,15 +870,15 @@ OGRErr OGRDXFWriterLayer::WriteHATCH( OGRFeature *poFeature,
     {
         return OGRERR_NONE;
     }
-            
+
     if( wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon )
     {
         OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeom;
         int iGeom;
         OGRErr eErr = OGRERR_NONE;
 
-        for( iGeom = 0; 
-             eErr == OGRERR_NONE && iGeom < poGC->getNumGeometries(); 
+        for( iGeom = 0;
+             eErr == OGRERR_NONE && iGeom < poGC->getNumGeometries();
              iGeom++ )
         {
             eErr = WriteHATCH( poFeature, poGC->getGeometryRef( iGeom ) );
@@ -916,7 +910,7 @@ OGRErr OGRDXFWriterLayer::WriteHATCH( OGRFeature *poFeature,
 
     WriteValue( 2, "SOLID" ); // fill pattern
     WriteValue( 70, 1 ); // solid fill
-    WriteValue( 71, 0 ); // associativity 
+    WriteValue( 71, 0 ); // associativity
 
 /* -------------------------------------------------------------------- */
 /*      Do we have styling information?                                 */
@@ -954,7 +948,7 @@ OGRErr OGRDXFWriterLayer::WriteHATCH( OGRFeature *poFeature,
 
         if( poPen->Color(bDefault) != NULL && !bDefault )
             WriteValue( 62, ColorStringToDXFColor( poPen->Color(bDefault) ) );
-        
+
         double dfWidthInMM = poPen->Width(bDefault);
 
         if( !bDefault )
@@ -966,8 +960,8 @@ OGRErr OGRDXFWriterLayer::WriteHATCH( OGRFeature *poFeature,
 /* -------------------------------------------------------------------- */
     CPLString osLineType = poFeature->GetFieldAsString( "Linetype" );
 
-    if( osLineType.size() > 0 
-        && (poDS->oHeaderDS.LookupLineType( osLineType ) != NULL 
+    if( osLineType.size() > 0
+        && (poDS->oHeaderDS.LookupLineType( osLineType ) != NULL
             || oNewLineTypes.count(osLineType) > 0 ) )
     {
         // Already define -> just reference it.
@@ -975,7 +969,7 @@ OGRErr OGRDXFWriterLayer::WriteHATCH( OGRFeature *poFeature,
     }
     else if( poTool != NULL && poTool->GetType() == OGRSTCPen )
     {
-        CPLString osDefinition = PrepareLineTypeDefinition( poFeature, 
+        CPLString osDefinition = PrepareLineTypeDefinition( poFeature,
                                                             poTool );
 
         if( osDefinition != "" && osLineType == "" )
@@ -997,8 +991,8 @@ OGRErr OGRDXFWriterLayer::WriteHATCH( OGRFeature *poFeature,
             // create an automatic name for it.
             if( osLineType == "" )
             {
-                do 
-                { 
+                do
+                {
                     osLineType.Printf( "AutoLineType-%d", nNextAutoID++ );
                 }
                 while( poDS->oHeaderDS.LookupLineType(osLineType) != NULL );
@@ -1035,7 +1029,7 @@ OGRErr OGRDXFWriterLayer::WriteHATCH( OGRFeature *poFeature,
         WriteValue( 72, 0 ); // has bulge
         WriteValue( 73, 1 ); // is closed
         WriteValue( 93, poLR->getNumPoints() );
-        
+
         for( int iVert = 0; iVert < poLR->getNumPoints(); iVert++ )
         {
             WriteValue( 10, poLR->getX(iVert) );
@@ -1048,7 +1042,7 @@ OGRErr OGRDXFWriterLayer::WriteHATCH( OGRFeature *poFeature,
     WriteValue( 75, 0 ); // hatch style = Hatch "odd parity" area (Normal style)
     WriteValue( 76, 1 ); // hatch pattern type = predefined
     WriteValue( 98, 0 ); // 0 seed points
-    
+
     return OGRERR_NONE;
 
 #ifdef notdef
@@ -1072,7 +1066,7 @@ OGRErr OGRDXFWriterLayer::WriteHATCH( OGRFeature *poFeature,
         WriteValue( 0, "VERTEX" );
         WriteValue( 8, "0" );
         WriteValue( 10, poLS->getX(iVert) );
-        if( !WriteValue( 20, poLS->getY(iVert) ) ) 
+        if( !WriteValue( 20, poLS->getY(iVert) ) )
             return OGRERR_FAILURE;
 
         if( poLS->getGeometryType() == wkbLineString25D )
@@ -1084,7 +1078,7 @@ OGRErr OGRDXFWriterLayer::WriteHATCH( OGRFeature *poFeature,
 
     WriteValue( 0, "SEQEND" );
     WriteValue( 8, "0" );
-    
+
     return OGRERR_NONE;
 #endif
 }
@@ -1098,7 +1092,7 @@ OGRErr OGRDXFWriterLayer::ICreateFeature( OGRFeature *poFeature )
 {
     OGRGeometry *poGeom = poFeature->GetGeometryRef();
     OGRwkbGeometryType eGType = wkbNone;
-    
+
     if( poGeom != NULL )
     {
         if( !poGeom->IsEmpty() )
@@ -1116,33 +1110,33 @@ OGRErr OGRDXFWriterLayer::ICreateFeature( OGRFeature *poFeature )
 
         // we don't want to treat as a block ref if we are writing blocks layer
         if( pszBlockName != NULL
-            && poDS->poBlocksLayer != NULL 
+            && poDS->poBlocksLayer != NULL
             && poFeature->GetDefnRef() == poDS->poBlocksLayer->GetLayerDefn())
             pszBlockName = NULL;
 
         // We don't want to treat as a blocks ref if the block is not defined
-        if( pszBlockName 
+        if( pszBlockName
             && poDS->oHeaderDS.LookupBlock(pszBlockName) == NULL )
         {
             if( poDS->poBlocksLayer == NULL
                 || poDS->poBlocksLayer->FindBlock(pszBlockName) == NULL )
                 pszBlockName = NULL;
         }
-                                  
+
         if( pszBlockName != NULL )
             return WriteINSERT( poFeature );
-            
+
         else if( poFeature->GetStyleString() != NULL
-            && EQUALN(poFeature->GetStyleString(),"LABEL",5) )
+            && STARTS_WITH_CI(poFeature->GetStyleString(), "LABEL") )
             return WriteTEXT( poFeature );
         else
             return WritePOINT( poFeature );
     }
-    else if( eGType == wkbLineString 
+    else if( eGType == wkbLineString
              || eGType == wkbMultiLineString )
         return WritePOLYLINE( poFeature );
 
-    else if( eGType == wkbPolygon 
+    else if( eGType == wkbPolygon
              || eGType == wkbMultiPolygon )
     {
         if( bWriteHatch )
@@ -1161,18 +1155,18 @@ OGRErr OGRDXFWriterLayer::ICreateFeature( OGRFeature *poFeature )
         for( iGeom = 0; iGeom < poGC->getNumGeometries(); iGeom++ )
         {
             poFeature->SetGeometry( poGC->getGeometryRef(iGeom) );
-                                    
+
             OGRErr eErr = CreateFeature( poFeature );
-            
+
             if( eErr != OGRERR_NONE )
                 return eErr;
 
         }
-        
+
         poFeature->SetGeometryDirectly( poGC );
         return OGRERR_NONE;
     }
-    else 
+    else
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "No known way to write feature with geometry '%s'.",
@@ -1196,9 +1190,9 @@ int OGRDXFWriterLayer::ColorStringToDXFColor( const char *pszRGB )
 
     int nRed, nGreen, nBlue, nTransparency = 255;
 
-    int nCount  = sscanf(pszRGB,"#%2x%2x%2x%2x",&nRed,&nGreen,&nBlue, 
+    int nCount  = sscanf(pszRGB,"#%2x%2x%2x%2x",&nRed,&nGreen,&nBlue,
                          &nTransparency);
-   
+
     if (nCount < 3 )
         return -1;
 
@@ -1222,6 +1216,6 @@ int OGRDXFWriterLayer::ColorStringToDXFColor( const char *pszRGB )
             nMinDist = nDist;
         }
     }
-    
+
     return nBestColor;
 }
diff --git a/ogr/ogrsf_frmts/edigeo/drv_edigeo.html b/ogr/ogrsf_frmts/edigeo/drv_edigeo.html
index 3d2ca6b..715306a 100644
--- a/ogr/ogrsf_frmts/edigeo/drv_edigeo.html
+++ b/ogr/ogrsf_frmts/edigeo/drv_edigeo.html
@@ -11,7 +11,7 @@
 
 This driver reads files encoded in the French EDIGEO exchange format,
 a text based file format aimed at exchanging geographical information between GIS, with
-powerful description capabilities, topology modelling, etc.<p>
+powerful description capabilities, topology modeling, etc.<p>
 
 The driver has been developed to read files of the French PCI
 (Plan Cadastral Informatisé - Digital Cadastral Plan) as produced by the
@@ -22,7 +22,7 @@ The driver must be provided with the .THF file describing the EDIGEO exchange an
 read the associated .DIC, .GEO, .SCD, .QAL and .VEC files.<p>
 
 In order the SRS of the layers to be correctly built, the IGNF file that contains
-the defintion of IGN SRS must be placed in the directory of PROJ.4 resource files.<p>
+the definition of IGN SRS must be placed in the directory of PROJ.4 resource files.<p>
 
 The whole set of files will be parsed into memory. This may be a limitation if dealing with
 big EDIGEO exchanges.<p>
@@ -35,7 +35,7 @@ the layers of the French PCI will be ordered such as they overlay nicely when op
 <h3>Labels</h3>
 
 For EDIGEO PCI files, the labels are contained in the ID_S_OBJ_Z_1_2_2 layer. OGR will export
-styling following the <a href="http://gdal.org/ogr/ogr_feature_style.html">OGR Feature Style specification</a>.<p>
+styling following the <a href="http://gdal.org/ogr_feature_style.html">OGR Feature Style specification</a>.<p>
 
 It will also add the following fields :
 <ul>
diff --git a/ogr/ogrsf_frmts/edigeo/ogr_edigeo.h b/ogr/ogrsf_frmts/edigeo/ogr_edigeo.h
index 1a11f9c..86614e2 100644
--- a/ogr/ogrsf_frmts/edigeo/ogr_edigeo.h
+++ b/ogr/ogrsf_frmts/edigeo/ogr_edigeo.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_edigeo.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogr_edigeo.h 31777 2015-11-26 14:14:41Z rouault $
  *
  * Project:  EDIGEO Translator
  * Purpose:  Definition of classes for OGR .edigeo driver.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_EDIGEO_H_INCLUDED
-#define _OGR_EDIGEO_H_INCLUDED
+#ifndef OGR_EDIGEO_H_INCLUDED
+#define OGR_EDIGEO_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include <vector>
@@ -74,7 +74,8 @@ class OGREDIGEOLayer : public OGRLayer
     virtual int                 TestCapability( const char * );
 
     virtual OGRErr              GetExtent(OGREnvelope *psExtent, int bForce);
-
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
     void                        AddFeature(OGRFeature* poFeature);
 
@@ -119,7 +120,7 @@ class OGREDIGEOObjectDescriptor
 class OGREDIGEOAttributeDescriptor
 {
     public:
-        OGREDIGEOAttributeDescriptor() {}
+        OGREDIGEOAttributeDescriptor() : nWidth(0) {}
 
         CPLString osRID;        /* e.g. TEX2_id */
         CPLString osNameRID;    /* e.g. ID_N_ATT_TEX2 */
@@ -150,6 +151,7 @@ class OGREDIGEODataSource : public OGRDataSource
     VSILFILE*           OpenFile(const char *pszType,
                                  const CPLString& osExt);
 
+    // TODO: Tranlate comments to English.
     CPLString osLON; /* Nom du lot */
     CPLString osGNN; /* Nom du sous-ensemble de données générales */
     CPLString osGON; /* Nom du sous-ensemble de la référence de coordonnées */
@@ -241,4 +243,4 @@ class OGREDIGEODataSource : public OGRDataSource
 };
 
 
-#endif /* ndef _OGR_EDIGEO_H_INCLUDED */
+#endif /* ndef OGR_EDIGEO_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/edigeo/ogredigeodatasource.cpp b/ogr/ogrsf_frmts/edigeo/ogredigeodatasource.cpp
index 0577b3b..723b451 100644
--- a/ogr/ogrsf_frmts/edigeo/ogredigeodatasource.cpp
+++ b/ogr/ogrsf_frmts/edigeo/ogredigeodatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogredigeodatasource.cpp 28039 2014-11-30 18:24:59Z rouault $
+ * $Id: ogredigeodatasource.cpp 32983 2016-01-14 18:32:10Z goatbar $
  *
  * Project:  EDIGEO Translator
  * Purpose:  Implements OGREDIGEODataSource class
@@ -31,11 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogredigeodatasource.cpp 28039 2014-11-30 18:24:59Z rouault $");
-
-#ifndef M_PI
-# define M_PI  3.1415926535897932384626433832795
-#endif
+CPL_CVSID("$Id: ogredigeodatasource.cpp 32983 2016-01-14 18:32:10Z goatbar $");
 
 /************************************************************************/
 /*                        OGREDIGEODataSource()                         */
@@ -56,7 +52,7 @@ OGREDIGEODataSource::OGREDIGEODataSource()
     fpTHF = NULL;
     bHasReadEDIGEO = FALSE;
 
-    bIncludeFontFamily = CSLTestBoolean(CPLGetConfigOption(
+    bIncludeFontFamily = CPLTestBool(CPLGetConfigOption(
                                  "OGR_EDIGEO_INCLUDE_FONT_FAMILY", "YES"));
 
     iATR = iDI3 = iDI4 = iHEI = iFON = -1;
@@ -65,7 +61,7 @@ OGREDIGEODataSource::OGREDIGEODataSource()
     if (dfSizeFactor <= 0 || dfSizeFactor >= 100)
         dfSizeFactor = 2;
 
-    bRecodeToUTF8 = CSLTestBoolean(CPLGetConfigOption(
+    bRecodeToUTF8 = CPLTestBool(CPLGetConfigOption(
                                         "OGR_EDIGEO_RECODE_TO_UTF8", "YES"));
     bHasUTF8ContentOnly = TRUE;
 }
@@ -137,7 +133,7 @@ int OGREDIGEODataSource::ReadTHF(VSILFILE* fp)
 
         /* Cf Z 52000 tableau 56 for field list*/
 
-        if (strncmp(pszLine, "LONSA", 5) == 0)
+        if (STARTS_WITH(pszLine, "LONSA"))
         {
             if (osLON.size() != 0)
             {
@@ -146,17 +142,17 @@ int OGREDIGEODataSource::ReadTHF(VSILFILE* fp)
             }
             osLON = pszLine + 8;
         }
-        else if (strncmp(pszLine, "GNNSA", 5) == 0)
+        else if (STARTS_WITH(pszLine, "GNNSA"))
             osGNN = pszLine + 8;
-        else if (strncmp(pszLine, "GONSA", 5) == 0)
+        else if (STARTS_WITH(pszLine, "GONSA"))
             osGON = pszLine + 8;
-        else if (strncmp(pszLine, "QANSA", 5) == 0)
+        else if (STARTS_WITH(pszLine, "QANSA"))
             osQAN = pszLine + 8;
-        else if (strncmp(pszLine, "DINSA", 5) == 0)
+        else if (STARTS_WITH(pszLine, "DINSA"))
             osDIN = pszLine + 8;
-        else if (strncmp(pszLine, "SCNSA", 5) == 0)
+        else if (STARTS_WITH(pszLine, "SCNSA"))
             osSCN = pszLine + 8;
-        else if (strncmp(pszLine, "GDNSA", 5) == 0)
+        else if (STARTS_WITH(pszLine, "GDNSA"))
             aosGDN.push_back(pszLine + 8);
     }
     if (osLON.size() == 0)
@@ -188,7 +184,7 @@ int OGREDIGEODataSource::ReadTHF(VSILFILE* fp)
     CPLDebug("EDIGEO", "SCN = %s", osSCN.c_str());
     for(int i=0;i<(int)aosGDN.size();i++)
         CPLDebug("EDIGEO", "GDN[%d] = %s", i, aosGDN[i].c_str());
-    
+
     return TRUE;
 }
 
@@ -236,7 +232,7 @@ int OGREDIGEODataSource::ReadGEO()
         if (strlen(pszLine) < 8 || pszLine[7] != ':')
             continue;
 
-        if (strncmp(pszLine, "RELSA", 5) == 0)
+        if (STARTS_WITH(pszLine, "RELSA"))
         {
             osREL = pszLine + 8;
             CPLDebug("EDIGEO", "REL = %s", osREL.c_str());
@@ -252,7 +248,7 @@ int OGREDIGEODataSource::ReadGEO()
         return FALSE;
     }
 
-    /* All the SRS names mentionned in B.8.2.3 and B.8.3.1 are in the IGN file */
+    /* All the SRS names mentioned in B.8.2.3 and B.8.3.1 are in the IGN file */
     poSRS = new OGRSpatialReference();
     CPLString osProj4Str = "+init=IGNF:" + osREL;
     if (poSRS->SetFromUserInput(osProj4Str.c_str()) != OGRERR_NONE)
@@ -275,7 +271,7 @@ int OGREDIGEODataSource::ReadGEO()
             poSRS = NULL;
         }
     }
-    
+
     return TRUE;
 }
 
@@ -296,11 +292,11 @@ int OGREDIGEODataSource::ReadGEN()
         if (strlen(pszLine) < 8 || pszLine[7] != ':')
             continue;
 
-        if (strncmp(pszLine, "CM1CC", 5) == 0)
+        if (STARTS_WITH(pszLine, "CM1CC"))
         {
             osCM1 = pszLine + 8;
         }
-        else if (strncmp(pszLine, "CM2CC", 5) == 0)
+        else if (STARTS_WITH(pszLine, "CM2CC"))
         {
             osCM2 = pszLine + 8;
         }
@@ -339,7 +335,7 @@ int OGREDIGEODataSource::ReadDIC()
 
     const char* pszLine;
     CPLString osRTY, osRID, osLAB, osTYP;
-    while(TRUE)
+    while( true )
     {
         pszLine = CPLReadLine2L(fp, 81, NULL);
         if (pszLine != NULL)
@@ -348,7 +344,7 @@ int OGREDIGEODataSource::ReadDIC()
                 continue;
         }
 
-        if (pszLine == NULL || strncmp(pszLine, "RTYSA", 5) == 0)
+        if (pszLine == NULL || STARTS_WITH(pszLine, "RTYSA"))
         {
             if (osRTY == "DID")
             {
@@ -372,11 +368,11 @@ int OGREDIGEODataSource::ReadDIC()
             osLAB = "";
             osTYP = "";
         }
-        if (strncmp(pszLine, "RIDSA", 5) == 0)
+        if (STARTS_WITH(pszLine, "RIDSA"))
             osRID = pszLine + 8;
-        else if (strncmp(pszLine, "LABSA", 5) == 0)
+        else if (STARTS_WITH(pszLine, "LABSA"))
             osLAB = pszLine + 8;
-        else if (strncmp(pszLine, "TYPSA", 5) == 0)
+        else if (STARTS_WITH(pszLine, "TYPSA"))
             osTYP = pszLine + 8;
     }
 
@@ -400,7 +396,7 @@ int OGREDIGEODataSource::ReadSCD()
     CPLString osRTY, osRID, osNameRID, osKND;
     strListType aosAttrRID;
     int nWidth = 0;
-    while(TRUE)
+    while( true )
     {
         pszLine = CPLReadLine2L(fp, 81, NULL);
         if (pszLine != NULL)
@@ -409,7 +405,7 @@ int OGREDIGEODataSource::ReadSCD()
                 continue;
         }
 
-        if (pszLine == NULL || strncmp(pszLine, "RTYSA", 5) == 0)
+        if (pszLine == NULL || STARTS_WITH(pszLine, "RTYSA"))
         {
             if (osRTY == "OBJ")
             {
@@ -460,9 +456,9 @@ int OGREDIGEODataSource::ReadSCD()
             aosAttrRID.resize(0);
             nWidth = 0;
         }
-        if (strncmp(pszLine, "RIDSA", 5) == 0)
+        if (STARTS_WITH(pszLine, "RIDSA"))
             osRID = pszLine + 8;
-        else if (strncmp(pszLine, "DIPCP", 5) == 0)
+        else if (STARTS_WITH(pszLine, "DIPCP"))
         {
             const char* pszDIP = pszLine + 8;
             char** papszTokens = CSLTokenizeString2(pszDIP, ";", 0);
@@ -472,9 +468,9 @@ int OGREDIGEODataSource::ReadSCD()
             }
             CSLDestroy(papszTokens);
         }
-        else if (strncmp(pszLine, "KNDSA", 5) == 0)
+        else if (STARTS_WITH(pszLine, "KNDSA"))
             osKND = pszLine + 8;
-        else if (strncmp(pszLine, "AAPCP", 5) == 0)
+        else if (STARTS_WITH(pszLine, "AAPCP"))
         {
             const char* pszAAP = pszLine + 8;
             char** papszTokens = CSLTokenizeString2(pszAAP, ";", 0);
@@ -485,7 +481,7 @@ int OGREDIGEODataSource::ReadSCD()
             }
             CSLDestroy(papszTokens);
         }
-        else if (strncmp(pszLine, "CANSN", 5) == 0)
+        else if (STARTS_WITH(pszLine, "CANSN"))
             nWidth = atoi(pszLine + 8);
     }
 
@@ -508,7 +504,7 @@ int OGREDIGEODataSource::ReadQAL()
     const char* pszLine;
     CPLString osRTY, osRID;
     int nODA = 0, nUDA = 0;
-    while(TRUE)
+    while( true )
     {
         pszLine = CPLReadLine2L(fp, 81, NULL);
         if (pszLine != NULL)
@@ -517,7 +513,7 @@ int OGREDIGEODataSource::ReadQAL()
                 continue;
         }
 
-        if (pszLine == NULL || strncmp(pszLine, "RTYSA", 5) == 0)
+        if (pszLine == NULL || STARTS_WITH(pszLine, "RTYSA"))
         {
             if (osRTY == "QUP")
             {
@@ -530,11 +526,11 @@ int OGREDIGEODataSource::ReadQAL()
             nODA = 0;
             nUDA = 0;
         }
-        else if (strncmp(pszLine, "RIDSA", 5) == 0)
+        else if (STARTS_WITH(pszLine, "RIDSA"))
             osRID = pszLine + 8;
-        else if (strncmp(pszLine, "ODASD", 5) == 0)
+        else if (STARTS_WITH(pszLine, "ODASD"))
             nODA = atoi(pszLine + 8);
-        else if (strncmp(pszLine, "UDASD", 5) == 0)
+        else if (STARTS_WITH(pszLine, "UDASD"))
             nUDA = atoi(pszLine + 8);
     }
 
@@ -578,13 +574,13 @@ int OGREDIGEODataSource::CreateLayerFromObjectDesc(const OGREDIGEOObjectDescript
             const OGREDIGEOAttributeDescriptor& attrDesc = it->second;
             const OGREDIGEOAttributeDef& attrDef =
                                     mapAttributes[attrDesc.osNameRID];
-            OGRFieldType eType = OFTString;
+            OGRFieldType eFieldType = OFTString;
             if (attrDef.osTYP == "R" || attrDef.osTYP == "E")
-                eType = OFTReal;
+                eFieldType = OFTReal;
             else if (attrDef.osTYP == "I" || attrDef.osTYP == "N")
-                eType = OFTInteger;
+                eFieldType = OFTInteger;
 
-            poLayer->AddFieldDefn(attrDef.osLAB, eType, objDesc.aosAttrRID[j]);
+            poLayer->AddFieldDefn(attrDef.osLAB, eFieldType, objDesc.aosAttrRID[j]);
         }
     }
 
@@ -651,7 +647,7 @@ int OGREDIGEODataSource::ReadVEC(const char* pszVECName)
     CPLString osQUP_RID;
     int bIso8859_1 = FALSE;
 
-    while(TRUE)
+    while( true )
     {
         pszLine = CPLReadLine2L(fp, 81, NULL);
 skip_read_next_line:
@@ -661,7 +657,7 @@ skip_read_next_line:
                 continue;
         }
 
-        if (pszLine == NULL || strncmp(pszLine, "RTYSA", 5) == 0)
+        if (pszLine == NULL || STARTS_WITH(pszLine, "RTYSA"))
         {
             if (osRTY == "PAR")
             {
@@ -764,9 +760,9 @@ skip_read_next_line:
             osQUP_RID = "";
             bIso8859_1 = FALSE;
         }
-        else if (strncmp(pszLine, "RIDSA", 5) == 0)
+        else if (STARTS_WITH(pszLine, "RIDSA"))
             osRID = pszLine + 8;
-        else if (strncmp(pszLine, "CORCC", 5) == 0)
+        else if (STARTS_WITH(pszLine, "CORCC"))
         {
             const char* pszY = strchr(pszLine+8, ';');
             if (pszY)
@@ -776,7 +772,7 @@ skip_read_next_line:
                 aXY.push_back(xyPairType (dfX, dfY));
             }
         }
-        else if (strncmp(pszLine, "FTPCP", 5) == 0)
+        else if (STARTS_WITH(pszLine, "FTPCP"))
         {
             char** papszTokens = CSLTokenizeString2(pszLine + 8, ";", 0);
             if (CSLCount(papszTokens) == 4)
@@ -795,7 +791,7 @@ skip_read_next_line:
             }
             CSLDestroy(papszTokens);
         }
-        else if (strncmp(pszLine, "SCPCP", 5) == 0)
+        else if (STARTS_WITH(pszLine, "SCPCP"))
         {
             char** papszTokens = CSLTokenizeString2(pszLine + 8, ";", 0);
             if (CSLCount(papszTokens) == 4)
@@ -810,7 +806,7 @@ skip_read_next_line:
             }
             CSLDestroy(papszTokens);
         }
-        else if (strncmp(pszLine, "ATPCP", 5) == 0)
+        else if (STARTS_WITH(pszLine, "ATPCP"))
         {
             char** papszTokens = CSLTokenizeString2(pszLine + 8, ";", 0);
             if (CSLCount(papszTokens) == 4)
@@ -824,23 +820,21 @@ skip_read_next_line:
         {
             bIso8859_1 = TRUE;
         }
-        else if (strncmp(pszLine, "ATVS", 4) == 0)
+        else if (STARTS_WITH(pszLine, "ATVS"))
         {
             CPLString osAttVal = pszLine + 8;
-            int bSkipReadNextLine = FALSE;
-            while(TRUE)
+            while( true )
             {
                 pszLine = CPLReadLine2L(fp, 81, NULL);
                 if (pszLine != NULL &&
                     strlen(pszLine) >= 8 &&
                     pszLine[7] == ':' &&
-                    strncmp(pszLine, "NEXT ", 5) == 0)
+                    STARTS_WITH(pszLine, "NEXT "))
                 {
                     osAttVal += pszLine + 8;
                 }
                 else
                 {
-                    bSkipReadNextLine = TRUE;
                     break;
                 }
             }
@@ -859,10 +853,9 @@ skip_read_next_line:
                 aosAttIdVal.push_back( strstrType (osAttId, osAttVal) );
             osAttId = "";
             bIso8859_1 = FALSE;
-            if (bSkipReadNextLine)
-                goto skip_read_next_line;
+            goto skip_read_next_line;
         }
-        else if (strncmp(pszLine, "ATVCP", 5) == 0)
+        else if (STARTS_WITH(pszLine, "ATVCP"))
         {
             char** papszTokens = CSLTokenizeString2(pszLine + 8, ";", 0);
             if (CSLCount(papszTokens) == 4)
@@ -877,7 +870,7 @@ skip_read_next_line:
             }
             CSLDestroy(papszTokens);
         }
-        else if (strncmp(pszLine, "QAPCP", 5) == 0)
+        else if (STARTS_WITH(pszLine, "QAPCP"))
         {
             char** papszTokens = CSLTokenizeString2(pszLine + 8, ";", 0);
             if (CSLCount(papszTokens) == 4)
@@ -1095,6 +1088,7 @@ int OGREDIGEODataSource::BuildLineStrings()
         OGRFeature* poFeature = CreateFeature(osFEA);
         if (poFeature)
         {
+            OGRGeometry* poGeom = NULL;
             OGRMultiLineString* poMulti = NULL;
             for(int k=0;k<(int)aosPAR.size();k++)
             {
@@ -1111,27 +1105,28 @@ int OGREDIGEODataSource::BuildLineStrings()
                         poLS->setPoint(i, arc[i].first, arc[i].second);
                     }
 
-                    if (poFeature->GetGeometryRef() != NULL)
+                    if (poGeom != NULL)
                     {
                         if (poMulti == NULL)
                         {
-                            OGRLineString* poPrevLS =
-                                (OGRLineString*) poFeature->StealGeometry();
                             poMulti = new OGRMultiLineString();
-                            poMulti->addGeometryDirectly(poPrevLS);
-                            poFeature->SetGeometryDirectly(poMulti);
+                            poMulti->addGeometryDirectly(poGeom);
+                            poGeom = poMulti;
                         }
                         poMulti->addGeometryDirectly(poLS);
                     }
                     else
-                        poFeature->SetGeometryDirectly(poLS);
+                        poGeom = poLS;
                 }
                 else
                     CPLDebug("EDIGEO",
                              "ERROR: Cannot find ARC %s", aosPAR[k].c_str());
             }
-            if (poFeature->GetGeometryRef())
-                poFeature->GetGeometryRef()->assignSpatialReference(poSRS);
+            if( poGeom != NULL )
+            {
+                poGeom->assignSpatialReference(poSRS);
+                poFeature->SetGeometryDirectly(poGeom);
+            }
         }
     }
 
@@ -1329,7 +1324,7 @@ static int OGREDIGEOSortForQGIS(const void* a, const void* b)
         if (nCmp == 0)
             return 0;
 
-        static const char* apszPolyOrder[] =
+        static const char* const apszPolyOrder[] =
             { "COMMUNE_id", "LIEUDIT_id", "SECTION_id", "SUBDSECT_id",
               "SUBDFISC_id", "PARCELLE_id", "BATIMENT_id" };
         for(int i=0;i<(int)(sizeof(apszPolyOrder)/sizeof(char*));i++)
@@ -1491,13 +1486,13 @@ void OGREDIGEODataSource::ReadEDIGEO()
 /*      When added from QGIS, the layers must be ordered from           */
 /*      bottom (Polygon) to top (Point) to get nice visual effect       */
 /* -------------------------------------------------------------------- */
-    if (CSLTestBoolean(CPLGetConfigOption("OGR_EDIGEO_SORT_FOR_QGIS", "YES")))
+    if (CPLTestBool(CPLGetConfigOption("OGR_EDIGEO_SORT_FOR_QGIS", "YES")))
         qsort(papoLayers, nLayers, sizeof(OGREDIGEOLayer*), OGREDIGEOSortForQGIS);
 
 /* -------------------------------------------------------------------- */
 /*      Create a label layer for each feature layer                     */
 /* -------------------------------------------------------------------- */
-    if (CSLTestBoolean(CPLGetConfigOption("OGR_EDIGEO_CREATE_LABEL_LAYERS", "YES")))
+    if (CPLTestBool(CPLGetConfigOption("OGR_EDIGEO_CREATE_LABEL_LAYERS", "YES")))
         CreateLabelLayers();
 
     return;
diff --git a/ogr/ogrsf_frmts/edigeo/ogredigeodriver.cpp b/ogr/ogrsf_frmts/edigeo/ogredigeodriver.cpp
index 91caf42..4fe0aac 100644
--- a/ogr/ogrsf_frmts/edigeo/ogredigeodriver.cpp
+++ b/ogr/ogrsf_frmts/edigeo/ogredigeodriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogredigeodriver.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogredigeodriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  EDIGEO Translator
  * Purpose:  Implements OGREDIGEODriver.
@@ -30,7 +30,7 @@
 #include "ogr_edigeo.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogredigeodriver.cpp 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: ogredigeodriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
 
 extern "C" void RegisterOGREDIGEO();
 
@@ -76,26 +76,23 @@ static GDALDataset *OGREDIGEODriverOpen( GDALOpenInfo * poOpenInfo )
 void RegisterOGREDIGEO()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "EDIGEO" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "EDIGEO" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver  *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "EDIGEO" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "French EDIGEO exchange format" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "thf" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_edigeo.html" );
+    poDriver->SetDescription( "EDIGEO" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "French EDIGEO exchange format" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "thf" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_edigeo.html" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = OGREDIGEODriverOpen;
-        poDriver->pfnIdentify = OGREDIGEODriverIdentify;
+    poDriver->pfnOpen = OGREDIGEODriverOpen;
+    poDriver->pfnIdentify = OGREDIGEODriverIdentify;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
 
diff --git a/ogr/ogrsf_frmts/edigeo/ogredigeolayer.cpp b/ogr/ogrsf_frmts/edigeo/ogredigeolayer.cpp
index 5d4eec7..758a8b1 100644
--- a/ogr/ogrsf_frmts/edigeo/ogredigeolayer.cpp
+++ b/ogr/ogrsf_frmts/edigeo/ogredigeolayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogredigeolayer.cpp 28382 2015-01-30 15:29:41Z rouault $
+ * $Id: ogredigeolayer.cpp 32011 2015-12-06 10:19:18Z rouault $
  *
  * Project:  EDIGEO Translator
  * Purpose:  Implements OGREDIGEOLayer class.
@@ -33,21 +33,21 @@
 #include "ogr_p.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ogredigeolayer.cpp 28382 2015-01-30 15:29:41Z rouault $");
+CPL_CVSID("$Id: ogredigeolayer.cpp 32011 2015-12-06 10:19:18Z rouault $");
 
 /************************************************************************/
 /*                          OGREDIGEOLayer()                            */
 /************************************************************************/
 
-OGREDIGEOLayer::OGREDIGEOLayer( OGREDIGEODataSource* poDS,
+OGREDIGEOLayer::OGREDIGEOLayer( OGREDIGEODataSource* poDSIn,
                                 const char* pszName, OGRwkbGeometryType eType,
-                                OGRSpatialReference* poSRS )
+                                OGRSpatialReference* poSRSIn )
 
 {
-    this->poDS = poDS;
+    this->poDS = poDSIn;
     nNextFID = 0;
 
-    this->poSRS = poSRS;
+    this->poSRS = poSRSIn;
     if (poSRS)
         poSRS->Reference();
 
@@ -95,7 +95,7 @@ OGRFeature *OGREDIGEOLayer::GetNextFeature()
 {
     OGRFeature  *poFeature;
 
-    while(TRUE)
+    while( true )
     {
         poFeature = GetNextRawFeature();
         if (poFeature == NULL)
diff --git a/ogr/ogrsf_frmts/elastic/drv_elasticsearch.html b/ogr/ogrsf_frmts/elastic/drv_elasticsearch.html
index 299125c..22de086 100644
--- a/ogr/ogrsf_frmts/elastic/drv_elasticsearch.html
+++ b/ogr/ogrsf_frmts/elastic/drv_elasticsearch.html
@@ -9,79 +9,311 @@
 
 (Driver available in GDAL 1.10 or later)</br>
 
-Driver is <b>WRITE Only</b>
+Driver is read-write starting with GDAL 2.1 (was write only in GDAL 2.0 or earlier)
 <p>
 
-<a href="http://elasticsearch.org/">ElasticSearch</a> is an Enterprise-level search engine for a variety of data sources. It supports full-text indexing and geospatial querying of those data in a fast and efficient manor using a predefined REST API. This driver serializes all of the supported OGR file formats in to an ElasticSearch index.
-<br> However, the driver is limited in the geometry it handles: even if polygons are provided as input, they are stored as <a href="http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/mapping-geo-point-type.html">geo point</a> and the "center" of the polygon is used as value of the point.
-</p><h2>Field definitions</h2>
+<a href="http://elasticsearch.org/">ElasticSearch</a> is an Enterprise-level
+search engine for a variety of data sources. It supports full-text indexing and
+geospatial querying of those data in a fast and efficient manor using a predefined REST API.
 
-Fields are dynamically mapped from the input OGR data source. However, the driver will take advantage of advanced options within ElasticSearch as defined in a <a href="http://code.google.com/p/ogr2elasticsearch/wiki/ModifyingtheIndex">field mapping file</a>.
+<h2>Opening dataset name syntax</h2>
+
+Starting with GDAL 2.1, the driver supports reading existing indices from a
+ElasticSearch host. There are two main possible syntaxes to open a dataset:
+<ul>
+<li>Using <i>ES:http://hostname:port</i> (where port is typically 9200)</li>
+<li>Using <i>ES:</i> with the open options to specify HOST and PORT</li>
+</ul>
+
+The open options available are :
+<ul>
+<li><b>HOST</b>=hostname: Server hostname. Default to localhost.</li>
+<li><b>PORT</b>=port. Server port. Default to 9200.</li>
+<li><b>BATCH_SIZE</b>=number. Number of features to retrieve per batch. Default is 100.</li>
+<li><b>FEATURE_COUNT_TO_ESTABLISH_FEATURE_DEFN</b>=number. Number of features to
+retrieve to establish feature definition. -1 = unlimited. Defaults to 100.</li>
+<li><b>JSON_FIELD</b>=YES/NO. Whether to include a field called "_json" with
+the full document as JSON. Defaults to NO.</li>
+<li><b>FLATTEN_NESTED_ATTRIBUTE</b>=YES/NO. Whether to recursively explore nested
+objects and produce flatten OGR attributes. Defaults to YES.</li>
+<li><b>FID</b>=string. Field name, with integer values, to use as FID. Defaults to 'ogc_fid'</li>
+</ul>
+
+<h2>ElasticSearch vs OGR concepts</h2>
+
+Each mapping type inside a ElasticSearch index will be considered as a OGR layer.
+A ElasticSearch document is considered as a OGR feature.<p>
+
+<h2>Field definitions</h2>
+
+Fields are dynamically mapped from the input OGR data source. However, the
+driver will take advantage of advanced options within ElasticSearch as defined
+in a <a href="http://code.google.com/p/ogr2elasticsearch/wiki/ModifyingtheIndex">field mapping file</a>.
 
 <p>
-The mapping file allows you to modify the mapping according to the <a href="http://www.elasticsearch.org/guide/reference/mapping/core-types.html">ElasticSearch field-specific types</a>. There are many options to choose from, however, most of the functionality is based on all the different things you are able to do with text fields within ElasticSearch.
+The mapping file allows you to modify the mapping according to the
+<a href="http://www.elasticsearch.org/guide/reference/mapping/core-types.html">ElasticSearch field-specific types</a>.
+There are many options to choose from, however, most of the functionality is
+based on all the different things you are able to do with text fields within ElasticSearch.
 <pre>
 ogr2ogr -progress --config ES_WRITEMAP /path/to/file/map.txt -f "ElasticSearch" http://localhost:9200 my_shapefile.shp
 </pre>
-<p> 
+<p>
 
-The ElasticSearch writer supports the following Configuration Options:
+The ElasticSearch writer supports the following Configuration Options. Starting
+with GDAL 2.1, layer creation options are also available and should be preferred:
 <ul>
-<li> <b>ES_WRITEMAP</b>=/path/to/mapfile.txt Creates a mapping file that can be modified by the user prior to insert in to the index.<br>
-<li> <b>ES_META</b>=/path/to/mapfile.txt Tells the driver to the user-defined field mappings.<br>
-<li> <b>ES_BULK</b>=10000 Identifies the number of records to be inserted at a time. Lower record counts help with memory consumption within ElasticSearch but take longer to insert.<br>
-<li> <b>ES_OVERWRITE</b>=1 Overwrites the current index by deleting an existing one.<br>
-
+<li> <b>ES_WRITEMAP</b>=/path/to/mapfile.txt. Creates a mapping file that can be
+modified by the user prior to insert in to the index. No feature will be written.
+Note that this will properly work only if only one single layer is created.
+Starting with GDAL 2.1, the <b>WRITE_MAPPING</b> layer creation option should rather be used.<br>
+<li> <b>ES_META</b>=/path/to/mapfile.txt. Tells the driver to the user-defined
+field mappings. Starting with GDAL 2.1, the <b>MAPPING</b> layer creation option should rather be used.<br>
+<li> <b>ES_BULK</b>=10000. Identifies the maximum size in bytes of the buffer
+to store documents to be inserted at a time. Lower record counts help with
+memory consumption within ElasticSearch but take longer to insert.
+Starting with GDAL 2.1, the <b>BULK_SIZE</b> layer creation option should rather be used.<br>
+<li> <b>ES_OVERWRITE</b>=1. Overwrites the current index by deleting an existing one.
+Starting with GDAL 2.1, the <b>OVERWRITE</b> layer creation option should rather be used.<br>
 </ul>
 <p>
 
+<h2>Geometry types</h2>
+
+In GDAL 2.0 and earlier, the driver was limited in the geometry it handles:
+even if polygons were provided as input, they were stored as
+<a href="http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/mapping-geo-point-type.html">geo point</a>
+and the "center" of the polygon is used as value of the point.
+Starting with GDAL 2.1,
+<a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-geo-shape-type.html">geo_shape</a>
+is used to store all geometry types (except curve geometries that are not handled
+by ElasticSearch and will be approximated to their linear equivalents).
+</p>
+
+<h2>Filtering</h2>
+
+The driver will forward any spatial filter set with SetSpatialFilter() to the server.<p>
+
+However, in the current state, SQL attribute filters set with SetAttributeFilter()
+are evaluated only on client-side. To enable server-side filtering, the string
+passed to SetAttributeFilter() must be a JSon object in the
+<a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-filters.html">ElasticSearch filter syntax</a>.
+e.g. <pre>{ "filter": { "term": { "EAS_ID": 169 } } }</pre>
 <p>
-It is possible to apply several options at a time. The following use case takes advantage of a predefined mapping file as well as a limited <b>BULK</b> insert count.
+
+Note: if defining an Elastic Search JSon filter, the spatial filter specified
+through SetSpatialFilter() will be ignored, and must thus be included in the JSon
+filter if needed.<p>
+
+<h2>Paging</h2>
+
+Features are retrieved from the server by chunks of 100. This can be
+altered with the BATCH_SIZE open option.<p>
+
+<h2>Schema</h2>
+
+When reading a Elastic Search index/type, OGR must establish the schema of attribute and geometry
+fields, since OGR has a fixed schema concept.<p>
+
+In the general case, OGR will read the mapping definition and the first 100 documents (can be altered with
+the FEATURE_COUNT_TO_ESTABLISH_FEATURE_DEFN open option) of the index/type and build
+the schema that best fit to the found fields and values.<p>
+
+It is also possible to set the JSON_FIELD=YES open option so that a _json special
+field is added to the OGR schema. When reading Elastic Search documents as OGR features,
+the full JSon version of the document will be stored in the _json field. This might
+be useful in case of complex documents or with data types that do not translate well
+in OGR data types. On creation/update of documents, if the _json field is present
+and set, its content will be used directly (other fields will be ignored).<p>
+
+<h2>Feature ID</h2>
+
+Elastic Search have a special _id field that contains the unique ID of the document. This
+field is returned as an OGR field, but cannot be used as the OGR special FeatureID
+field, which must be of integer type. By default, OGR will try to read a potential
+'ogc_fid' field to set the OGR FeatureID. The name of this field to look up can
+be set with the FID open option. If the field is not found, the FID returned by
+OGR will be a sequential number starting at 1, but it is not guaranteed to be
+stable at all.<p>
+
+<h2>ExecuteSQL() interface</h2>
+
+If specifying "ES" as the dialect of ExecuteSQL(), a JSon string with a
+serialized <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-filters.html">Elastic Search filter</a>
+can be passed. The search will be done on all indices and types, unless the
+filter itself restricts the search. The returned layer will be a union of the
+types returned by the FEATURE_COUNT_TO_ESTABLISH_FEATURE_DEFN first documents. It
+will also contain the _index and _type special fields to indicate the provenance
+of the features.<p>
+
+The following filter can be used to restrict the search to the "poly" index and its "FeatureCollection" type mapping:
 <pre>
-ogr2ogr -progress --config ES_OVERWRITE 1 --config ES_BULK 10000 --config ES_META /path/to/file/map.txt -f "ElasticSearch" http://localhost:9200 PG:"host=localhost user=postgres dbname=my_db password=password" "my_table" -nln thetable
+{ "filter": {
+    "indices" : {
+        "no_match_filter": "none",
+        "index": "poly",
+        "filter": {
+           "and" : [
+             { "type": { "value": "FeatureCollection" } },
+             { "term" : { "EAS_ID" : 158.0 } }
+           ]
+        }
+      }
+    }
+}
 </pre>
-</li>
+
+Aggregations are not supported.<p>
+
+Standard SQL requests will be executed on client-side.<p>
+
+<h2>Getting metadata</h2>
+
+Getting feature count is efficient.<p>
+
+Getting extent is efficient, only on geometry columns mapped to ElasticSearch type geo_point.
+On geo_shape fields, feature retrieval of the whole layer is done, which might be slow.<p>
+
+<h2>Write support</h2>
+
+Index/type creation and deletion is possible.<p>
+
+Write support is only enabled when the datasource is opened in update mode.<p>
+
+When inserting a new feature with CreateFeature() in non-bulk mode, and if the command is successful, OGR will fetch the
+returned _id and use it for the SetFeature() operation.<p>
+
+<h2>Spatial reference system</h2>
+
+Geometries stored in Elastic Search are supposed to be referenced as longitude/latitude
+over WGS84 datum (EPSG:4326). On creation, the driver will automatically reproject
+from the layer (or geometry field) SRS to EPSG:4326, provided that the input SRS
+is set and that is not already EPSG:4326.<p>
+
+<h2>Layer creation options</h2>
+
+Starting with GDAL 2.1, the driver supports the following layer creation options:
+<ul>
+<li><b>INDEX_NAME</b>=name. Name of the index to create (or reuse). By default the index name is the layer name.</li>
+<li><b>MAPPING_NAME=</b>=name. Name of the mapping type within the index.
+By default, the mapping name is "FeatureCollection" and the documents will be
+written as GeoJSON Feature objects. If another mapping name is chosen, a more "flat" structure will be used.</li>
+<li><b>MAPPING</b>=filename or JSon. Filename from which to read a user-defined
+mapping, or mapping as serialized JSon.</li>
+<li><b>WRITE_MAPPING</b>=filename. Creates a mapping file that can be modified
+by the user prior to insert in to the index. No feature will be written.
+This option is exclusive with MAPPING.</li>
+<li><b>OVERWRITE</b>=YES/NO. Whether to overwrite an existing collection with
+the layer name to be created. Defaults to NO.</li>
+<li><b>GEOMETRY_NAME</b>=name. Name of geometry column. Defaults to 'geometry'.</li>
+<li><b>GEOM_MAPPING_TYPE</b>=AUTO/GEO_POINT/GEO_SHAPE. Mapping type for geometry fields. Defaults to AUTO.
+GEO_POINT uses the <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-geo-point-type.html">geo_point</a>
+mapping type. If used, the "centroid" of the geometry is used.
+This is the behaviour of GDAL < 2.1.
+GEO_SHAPE uses the <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-geo-shape-type.html">geo_shape</a>
+mapping type, compatible of all geometry types.
+When using AUTO, if there is a single geometry field of type Point, a geo_point is used.
+In other cases, geo_shape is used.</li>
+<li><b>GEOM_PRECISION</b>={value}{unit}'. Desired geometry precision. Number followed by unit. For example 1m.
+For a geo_point geometry field, this causes a compressed geometry format to be used.
+This option is without effect if MAPPING is specified.</li>
+<li><b>STORE_FIELDS</b>=YES/NO. Whether fields should be stored in the index.
+Setting to YES sets the <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-core-types.html">"store" property</a> of the field mapping to "true" for all fields. Defaults to NO.
+(Note: prior to GDAL 2.1, the default behaviour was to store fields)
+This option is without effect if MAPPING is specified.</li>
+<li><b>STORED_FIELDS</b>=List of comma separated field names that should be stored in the index.
+Those fields will have their <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-core-types.html">"store" property</a> of the field mapping set to "true".
+If all fields must be stored, then using STORE_FIELDS=YES is a shortcut.
+This option is without effect if MAPPING is specified.</li>
+<li><b>NOT_ANALYZED_FIELDS</b>=List of comma separated field names that should not be analyzed during indexing.
+Those fields will have their <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-core-types.html">"index" property</a> of the field mapping set to "not_analyzed"
+(the default in ElasticSearch is "analyzed"). A same field should not be
+specified both in NOT_ANALYZED_FIELDS and NOT_INDEXED_FIELDS.
+This option is without effect if MAPPING is specified.</li>
+<li><b>NOT_INDEXED_FIELDS</b>=List of comma separated field names that should not be indexed.
+Those fields will have their <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-core-types.html">"index" property</a> of the field mapping set to "no"
+(the default in ElasticSearch is "analyzed"). A same field should not be
+specified both in NOT_ANALYZED_FIELDS and NOT_INDEXED_FIELDS.
+This option is without effect if MAPPING is specified.</li>
+<li><b>BULK_INSERT</b>=YES/NO. Whether to use bulk insert for feature creation. Defaults to YES.</li>
+<li><b>BULK_SIZE</b>=value. Size in bytes of the buffer for bulk upload. Defaults to 1000000 (1 million).</li>
+<li><b>FID</b>=string. Field name, with integer values, to use as FID. Can be set to empty to disable the writing of the FID value. Defaults to 'ogc_fid'</li>
+<li><b>DOT_AS_NESTED_FIELD</b>=YES/NO. Whether to consider dot character in field name as sub-document. Defaults to YES.</li>
+<li><b>IGNORE_SOURCE_ID</b>=YES/NO. Whether to ignore _id field in features passed to CreateFeature(). Defaults to NO.</li>
+</ul>
 
 <h2>Examples</h2>
 
-<b>Basic Transform:</b> </br>
+<b>Open the local store:</b></br>
 <pre>
-ogr2ogr -progress -f "ElasticSearch" http://localhost:9200 my_shapefile.shp
+ogrinfo ES:
+</pre>
+
+<b>Open a remote store:</b></br>
+<pre>
+ogrinfo ES:http://example.com:9200
+</pre>
+
+<b>Filtering on a Elastic Search field:</b><br>
+<pre>
+ogrinfo -ro ES: my_type -where '{ "filter": { "term": { "EAS_ID": 168 } } }'
+</pre>
+
+<b>Using "match" query on Windows:</b><br>
+On Windows the query must be between double quotes and double quotes inside the query must be escaped.
+<pre>
+C:\GDAL_on_Windows>ogrinfo ES: my_type -where "{\"query\": { \"match\": { \"NAME\": \"Helsinki\" } } }"
+</pre>
+<b>Load an ElasticSearch index with a shapefile:</b> </br>
+<pre>
+ogr2ogr -f "ElasticSearch" http://localhost:9200 my_shapefile.shp
 </pre>
 
 <b>Create a Mapping File:</b> </br>
-The mapping file allows you to modify the mapping according to the <a href="http://www.elasticsearch.org/guide/reference/mapping/core-types.html">ElasticSearch field-specific types</a>. There are many options to choose from, however, most of the functionality is based on all the different things you are able to do with text fields. 
+The mapping file allows you to modify the mapping according to the
+<a href="http://www.elasticsearch.org/guide/reference/mapping/core-types.html">ElasticSearch field-specific types</a>.
+There are many options to choose from, however, most of the functionality is based
+on all the different things you are able to do with text fields.
 </br>
 <pre>
 ogr2ogr -progress --config ES_WRITEMAP /path/to/file/map.txt -f "ElasticSearch" http://localhost:9200 my_shapefile.shp
 </pre>
+or (GDAL >= 2.1):
+<pre>
+ogr2ogr -progress -lco WRITE_MAPPING=/path/to/file/map.txt -f "ElasticSearch" http://localhost:9200 my_shapefile.shp
+</pre>
 
 <b>Read the Mapping File:</b> </br>
 Reads the mapping file during the transformation</br>
 <pre>
 ogr2ogr -progress --config ES_META /path/to/file/map.txt -f "ElasticSearch" http://localhost:9200 my_shapefile.shp
 </pre>
+or (GDAL >= 2.1):
+<pre>
+ogr2ogr -progress -lco MAPPING=/path/to/file/map.txt -f "ElasticSearch" http://localhost:9200 my_shapefile.shp
+</pre>
 
 <b>Bulk Uploading (for larger datasets):</b> </br>
-Bulk loading helps when uploading a lot of data. The integer value is the number of bytes that are collection before being inserted. 
+Bulk loading helps when uploading a lot of data. The integer value is the number of bytes that are collection before being inserted.
 </br>
 <pre>
 ogr2ogr -progress --config ES_BULK 10000 -f "ElasticSearch" http://localhost:9200 PG:"host=localhost user=postgres dbname=my_db password=password" "my_table" -nln thetable
 </pre>
+or (GDAL >= 2.1):
+<pre>
+ogr2ogr -progress -lco BULK_SIZE=10000 -f "ElasticSearch" http://localhost:9200 my_shapefile.shp
+</pre>
 
 <b>Overwrite the current Index:</b> </br>
-If specified, this will overwrite the current index. Otherwise, the data will be appended. 
+If specified, this will overwrite the current index. Otherwise, the data will be appended.
 </br>
 <pre>
 ogr2ogr -progress --config ES_OVERWRITE 1 -f "ElasticSearch" http://localhost:9200 PG:"host=localhost user=postgres dbname=my_db password=password" "my_table" -nln thetable
 </pre>
-
-<b>Specify several at a time:</b> </br>
-Several flags can be set at the same time. </br>
+or (GDAL >= 2.1):
 <pre>
-ogr2ogr -progress --config ES_OVERWRITE 1 --config ES_BULK 10000 --config ES_META /path/to/file/map.txt -f "ElasticSearch" http://localhost:9200 PG:"host=localhost user=postgres dbname=my_db password=password" "my_table" -nln thetable
+ogr2ogr -progress -overwrite ES:http://localhost:9200 PG:"host=localhost user=postgres dbname=my_db password=password" "my_table" -nln thetable
 </pre>
-<p>
 
 <h2>See Also</h2>
 
diff --git a/ogr/ogrsf_frmts/elastic/ogr_elastic.h b/ogr/ogrsf_frmts/elastic/ogr_elastic.h
index 0722dd1..0df6779 100644
--- a/ogr/ogrsf_frmts/elastic/ogr_elastic.h
+++ b/ogr/ogrsf_frmts/elastic/ogr_elastic.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_elastic.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogr_elastic.h 32177 2015-12-14 07:25:30Z goatbar $
  *
  * Project:  ElasticSearch Translator
  * Purpose:
@@ -27,12 +27,21 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_ELASTIC_H_INCLUDED
-#define _OGR_ELASTIC_H_INCLUDED
+#ifndef OGR_ELASTIC_H_INCLUDED
+#define OGR_ELASTIC_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "ogr_p.h"
 #include "cpl_hash_set.h"
+#include <vector>
+#include <json.h>
+
+typedef enum
+{
+    ES_GEOMTYPE_AUTO,
+    ES_GEOMTYPE_GEO_POINT,
+    ES_GEOMTYPE_GEO_SHAPE
+} ESGeometryTypeMapping;
 
 class OGRElasticDataSource;
 
@@ -41,80 +50,189 @@ class OGRElasticDataSource;
 /************************************************************************/
 
 class OGRElasticLayer : public OGRLayer {
-    OGRFeatureDefn* poFeatureDefn;
-    OGRSpatialReference* poSRS;
-    OGRElasticDataSource* poDS;
-    CPLString sIndex;
-    void* pAttributes;
-    char* pszLayerName;
+    OGRElasticDataSource                *m_poDS;
+
+    CPLString                            m_osIndexName;
+    CPLString                            m_osMappingName;
+
+    OGRFeatureDefn                      *m_poFeatureDefn;
+    int                                  m_bFeatureDefnFinalized;
+
+    int                                  m_bManualMapping;
+    int                                  m_bSerializeMapping;
+    CPLString                            m_osWriteMapFilename;
+    bool                                 m_bStoreFields;
+    char                               **m_papszStoredFields;
+    char                               **m_papszNotAnalyzedFields;
+    char                               **m_papszNotIndexedFields;
+
+    CPLString                            m_osESSearch;
+
+    CPLString                            m_osBulkContent;
+    int                                  m_nBulkUpload;
+
+    CPLString                            m_osFID;
+
+    std::vector< std::vector<CPLString> > m_aaosFieldPaths;
+    std::map< CPLString, int>             m_aosMapToFieldIndex;
+
+    std::vector< std::vector<CPLString> > m_aaosGeomFieldPaths;
+    std::map< CPLString, int>             m_aosMapToGeomFieldIndex;
+    std::vector< OGRCoordinateTransformation* > m_apoCT;
+    std::vector< int >                    m_abIsGeoPoint;
+    ESGeometryTypeMapping                 m_eGeomTypeMapping;
+    CPLString                             m_osPrecision;
+
+    CPLString                             m_osScrollID;
+    GIntBig                               m_iCurID;
+    GIntBig                               m_nNextFID;
+    int                                   m_iCurFeatureInPage;
+    std::vector<OGRFeature*>              m_apoCachedFeatures;
+    int                                   m_bEOF;
+
+    json_object*                          m_poSpatialFilter;
+    CPLString                             m_osJSONFilter;
+
+    int                                   m_bIgnoreSourceID;
+    int                                   m_bDotAsNestedField;
+
+    int                                   m_bAddPretty;
+
+    int                                   PushIndex();
+    CPLString                             BuildMap();
+
+    OGRErr                                WriteMapIfNecessary();
+    OGRFeature                           *GetNextRawFeature();
+    void                                  BuildFeature(OGRFeature* poFeature,
+                                                       json_object* poSource,
+                                                       CPLString osPath);
+    void                                  CreateFieldFromSchema(const char* pszName,
+                                                    const char* pszPrefix,
+                                                    std::vector<CPLString> aosPath,
+                                                    json_object* poObj);
+    void                                  AddOrUpdateField(const char* pszAttrName,
+                                                const char* pszKey,
+                                                json_object* poObj,
+                                                char chNestedAttributeSeparator,
+                                                std::vector<CPLString>& aosPath);
+
+    CPLString                             BuildJSonFromFeature(OGRFeature *poFeature);
+
+    static CPLString                      BuildPathFromArray(const std::vector<CPLString>& aosPath);
+
+    void                                  AddFieldDefn( const char* pszName,
+                                            OGRFieldType eType,
+                                            const std::vector<CPLString>& aosPath,
+                                            OGRFieldSubType eSubType = OFSTNone );
+    void                                  AddGeomFieldDefn( const char* pszName,
+                                            OGRwkbGeometryType eType,
+                                            const std::vector<CPLString>& aosPath,
+                                            int bIsGeoPoint );
 
 public:
-    OGRElasticLayer(const char *pszFilename,
-            const char* layerName,
-            OGRElasticDataSource* poDS,
-            OGRSpatialReference *poSRSIn,
-            int bWriteMode = FALSE);
-    ~OGRElasticLayer();
+                        OGRElasticLayer( const char* pszLayerName,
+                                         const char* pszIndexName,
+                                         const char* pszMappingName,
+                                         OGRElasticDataSource* poDS,
+                                         char** papszOptions,
+                                         const char* pszESSearch = NULL);
+                        ~OGRElasticLayer();
+
+    virtual void        ResetReading();
+    virtual OGRFeature *GetNextFeature();
+
+    virtual OGRErr      ICreateFeature(OGRFeature *poFeature);
+    virtual OGRErr      ISetFeature(OGRFeature *poFeature);
+    virtual OGRErr      CreateField(OGRFieldDefn *poField, int bApproxOK);
+    virtual OGRErr      CreateGeomField(OGRGeomFieldDefn *poField, int bApproxOK);
+
+    virtual const char* GetName() { return m_poFeatureDefn->GetName(); }
+    virtual OGRFeatureDefn *GetLayerDefn();
+    virtual const char *GetFIDColumn();
+
+    virtual int         TestCapability(const char *);
 
-    void ResetReading();
-    OGRFeature * GetNextFeature();
+    virtual GIntBig     GetFeatureCount(int bForce);
 
-    OGRErr ICreateFeature(OGRFeature *poFeature);
-    OGRErr CreateField(OGRFieldDefn *poField, int bApproxOK);
+    virtual void        SetSpatialFilter( OGRGeometry *poGeom ) { SetSpatialFilter(0, poGeom); }
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom );
+    virtual OGRErr      SetAttributeFilter(const char* pszFilter);
 
-    OGRFeatureDefn * GetLayerDefn();
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) { return GetExtent(0, psExtent, bForce); }
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce = TRUE);
 
-    int TestCapability(const char *);
+    virtual OGRErr      SyncToDisk();
 
-    GIntBig GetFeatureCount(int bForce);
+    void                FinalizeFeatureDefn(int bReadFeatures = TRUE);
+    void                InitFeatureDefnFromMapping(json_object* poSchema,
+                                    const char* pszPrefix,
+                                    const std::vector<CPLString>& aosPath);
 
-    void PushIndex();
-    CPLString BuildMap();
+    const CPLString&    GetIndexName() const { return m_osIndexName; }
+    const CPLString&    GetMappingName() const { return m_osMappingName; }
+
+    void                SetIgnoreSourceID(int bFlag) { m_bIgnoreSourceID = bFlag; }
+    void                SetManualMapping() { m_bManualMapping = TRUE; }
+    void                SetDotAsNestedField(int bFlag) { m_bDotAsNestedField = bFlag; }
+    void                SetFID(const CPLString& m_osFIDIn) { m_osFID = m_osFIDIn; }
+    void                SetNextFID(GIntBig nNextFID) { m_nNextFID = nNextFID; }
 };
 
 /************************************************************************/
 /*                         OGRElasticDataSource                         */
 /************************************************************************/
 
-class OGRElasticDataSource : public OGRDataSource {
-    char* pszName;
+class OGRElasticDataSource : public GDALDataset {
+    char               *m_pszName;
+    CPLString           m_osURL;
+    CPLString           m_osFID;
 
-    OGRElasticLayer** papoLayers;
-    int nLayers;
+    OGRElasticLayer   **m_papoLayers;
+    int                 m_nLayers;
 
 public:
-    OGRElasticDataSource();
-    ~OGRElasticDataSource();
+                            OGRElasticDataSource();
+                            ~OGRElasticDataSource();
+
+    int                 m_bOverwrite;
+    int                 m_nBulkUpload;
+    char               *m_pszWriteMap;
+    char               *m_pszMapping;
+    int                 m_nBatchSize;
+    int                 m_nFeatureCountToEstablishFeatureDefn;
+    int                 m_bJSonField;
+    int                 m_bFlattenNestedAttributes;
 
-    int Open(const char * pszFilename,
-            int bUpdate);
+    int Open(GDALOpenInfo* poOpenInfo);
 
     int Create(const char *pszFilename,
-            char **papszOptions);
+               char **papszOptions);
+
+    const char         *GetURL() { return m_osURL.c_str(); }
+
+    virtual const char *GetName() { return m_pszName; }
 
-    const char* GetName() {
-        return pszName;
-    }
+    virtual int         GetLayerCount() { return m_nLayers; }
+    virtual OGRLayer   *GetLayer(int);
 
-    int GetLayerCount() {
-        return nLayers;
-    }
-    OGRLayer* GetLayer(int);
+    virtual OGRLayer   *ICreateLayer(const char * pszLayerName,
+                                    OGRSpatialReference *poSRS,
+                                    OGRwkbGeometryType eType,
+                                    char ** papszOptions);
+    virtual OGRErr      DeleteLayer( int iLayer );
 
-    OGRLayer * ICreateLayer(const char * pszLayerName,
-            OGRSpatialReference *poSRS,
-            OGRwkbGeometryType eType,
-            char ** papszOptions);
+    virtual OGRLayer   *ExecuteSQL( const char *pszSQLCommand,
+                                            OGRGeometry *poSpatialFilter,
+                                            const char *pszDialect );
+    virtual void        ReleaseResultSet( OGRLayer * poLayer );
 
-    int TestCapability(const char *);
+    virtual int         TestCapability(const char *);
 
-    void UploadFile(const CPLString &url, const CPLString &data);
-    void DeleteIndex(const CPLString &url);
+    int                 UploadFile(const CPLString &url, const CPLString &data);
+    void                Delete(const CPLString &url);
 
-    int bOverwrite;
-    int nBulkUpload;
-    char* pszWriteMap;
-    char* pszMapping;
+    json_object*        RunRequest(const char* pszURL, const char* pszPostContent = NULL);
+    const CPLString&    GetFID() const { return m_osFID; }
 };
 
 
diff --git a/ogr/ogrsf_frmts/elastic/ogrelasticdatasource.cpp b/ogr/ogrsf_frmts/elastic/ogrelasticdatasource.cpp
index 2ff5210..934201e 100644
--- a/ogr/ogrsf_frmts/elastic/ogrelasticdatasource.cpp
+++ b/ogr/ogrsf_frmts/elastic/ogrelasticdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrelasticdatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogrelasticdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  ElasticSearch Translator
  * Purpose:
@@ -37,18 +37,29 @@
 #include "cpl_csv.h"
 #include "cpl_http.h"
 
-CPL_CVSID("$Id: ogrelasticdatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogrelasticdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                        OGRElasticDataSource()                        */
 /************************************************************************/
 
 OGRElasticDataSource::OGRElasticDataSource() {
-    papoLayers = NULL;
-    nLayers = 0;
-    pszName = NULL;
-    pszMapping = NULL;
-    pszWriteMap = NULL;
+    m_papoLayers = NULL;
+    m_nLayers = 0;
+    m_pszName = NULL;
+    m_pszMapping = NULL;
+    m_pszWriteMap = NULL;
+    m_bOverwrite = FALSE;
+    m_nBulkUpload = 0;
+    m_nBatchSize = 100;
+    m_nFeatureCountToEstablishFeatureDefn = 100;
+    m_bJSonField = FALSE;
+    m_bFlattenNestedAttributes = TRUE;
+
+    const char* pszWriteMapIn = CPLGetConfigOption("ES_WRITEMAP", NULL);
+    if (pszWriteMapIn != NULL) {
+        m_pszWriteMap = CPLStrdup(pszWriteMapIn);
+    }
 }
 
 /************************************************************************/
@@ -56,12 +67,12 @@ OGRElasticDataSource::OGRElasticDataSource() {
 /************************************************************************/
 
 OGRElasticDataSource::~OGRElasticDataSource() {
-    for (int i = 0; i < nLayers; i++)
-        delete papoLayers[i];
-    CPLFree(papoLayers);
-    CPLFree(pszName);
-    CPLFree(pszMapping);
-    CPLFree(pszWriteMap);
+    for (int i = 0; i < m_nLayers; i++)
+        delete m_papoLayers[i];
+    CPLFree(m_papoLayers);
+    CPLFree(m_pszName);
+    CPLFree(m_pszMapping);
+    CPLFree(m_pszWriteMap);
 }
 
 /************************************************************************/
@@ -69,7 +80,9 @@ OGRElasticDataSource::~OGRElasticDataSource() {
 /************************************************************************/
 
 int OGRElasticDataSource::TestCapability(const char * pszCap) {
-    if (EQUAL(pszCap, ODsCCreateLayer))
+    if (EQUAL(pszCap, ODsCCreateLayer) ||
+        EQUAL(pszCap, ODsCDeleteLayer) ||
+        EQUAL(pszCap, ODsCCreateGeomFieldAfterCreateLayer) )
         return TRUE;
     else
         return FALSE;
@@ -80,10 +93,47 @@ int OGRElasticDataSource::TestCapability(const char * pszCap) {
 /************************************************************************/
 
 OGRLayer *OGRElasticDataSource::GetLayer(int iLayer) {
-    if (iLayer < 0 || iLayer >= nLayers)
+    if (iLayer < 0 || iLayer >= m_nLayers)
         return NULL;
     else
-        return papoLayers[iLayer];
+        return m_papoLayers[iLayer];
+}
+
+/************************************************************************/
+/*                            DeleteLayer()                             */
+/************************************************************************/
+
+OGRErr OGRElasticDataSource::DeleteLayer( int iLayer )
+
+{
+    if( eAccess != GA_Update )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Dataset opened in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
+    if( iLayer < 0 || iLayer >= m_nLayers )
+        return OGRERR_FAILURE;
+
+/* -------------------------------------------------------------------- */
+/*      Blow away our OGR structures related to the layer.  This is     */
+/*      pretty dangerous if anything has a reference to this layer!     */
+/* -------------------------------------------------------------------- */
+    CPLString osLayerName = m_papoLayers[iLayer]->GetName();
+    CPLString osIndex = m_papoLayers[iLayer]->GetIndexName();
+    CPLString osMapping = m_papoLayers[iLayer]->GetMappingName();
+
+    CPLDebug( "ES", "DeleteLayer(%s)", osLayerName.c_str() );
+
+    delete m_papoLayers[iLayer];
+    memmove(m_papoLayers + iLayer, m_papoLayers + iLayer + 1,
+            (m_nLayers - 1 - iLayer) * sizeof(OGRLayer*));
+    m_nLayers --;
+
+    Delete(CPLSPrintf("%s/%s/_mapping/%s",
+                      GetURL(), osIndex.c_str(), osMapping.c_str()));
+
+    return OGRERR_NONE;
 }
 
 /************************************************************************/
@@ -92,32 +142,337 @@ OGRLayer *OGRElasticDataSource::GetLayer(int iLayer) {
 
 OGRLayer * OGRElasticDataSource::ICreateLayer(const char * pszLayerName,
                                               OGRSpatialReference *poSRS,
-                                              CPL_UNUSED OGRwkbGeometryType eType,
-                                              CPL_UNUSED char ** papszOptions) {
-    nLayers++;
-    papoLayers = (OGRElasticLayer **) CPLRealloc(papoLayers, nLayers * sizeof (OGRElasticLayer*));
-    papoLayers[nLayers - 1] = new OGRElasticLayer(pszName, pszLayerName, this, poSRS, TRUE);
+                                              OGRwkbGeometryType eGType,
+                                              char ** papszOptions)
+{
+    if( eAccess != GA_Update )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Dataset opened in read-only mode");
+        return NULL;
+    }
+
+    CPLString osLaunderedName(pszLayerName);
+
+    const char* pszIndexName = CSLFetchNameValue(papszOptions, "INDEX_NAME");
+    if( pszIndexName != NULL )
+        osLaunderedName = pszIndexName;
+
+    for(size_t i=0;i<osLaunderedName.size();i++)
+    {
+        if( osLaunderedName[i] >= 'A' && osLaunderedName[i] <= 'Z' )
+            osLaunderedName[i] += 'a' - 'A';
+        else if( osLaunderedName[i] == '/' || osLaunderedName[i] == '?' )
+            osLaunderedName[i] = '_';
+    }
+    if( strcmp(osLaunderedName.c_str(), pszLayerName) != 0 )
+        CPLDebug("ES", "Laundered layer name to %s", osLaunderedName.c_str());
+
+    // Backup error state
+    CPLErr eLastErrorType = CPLGetLastErrorType();
+    CPLErrorNum nLastErrorNo = CPLGetLastErrorNo();
+    CPLString osLastErrorMsg = CPLGetLastErrorMsg();
+
+    // Check if the index exists
+    int bIndexExists = FALSE;
+    CPLPushErrorHandler(CPLQuietErrorHandler);
+    CPLHTTPResult* psResult = CPLHTTPFetch(CPLSPrintf("%s/%s",
+                                           GetURL(), osLaunderedName.c_str()), NULL);
+    CPLPopErrorHandler();
+    if (psResult) {
+        bIndexExists = (psResult->pszErrBuf == NULL);
+        CPLHTTPDestroyResult(psResult);
+    }
+
+    const char* m_pszMappingName = CSLFetchNameValueDef(papszOptions,
+                                        "MAPPING_NAME", "FeatureCollection");
+
+    int bMappingExists = FALSE;
+    if( bIndexExists )
+    {
+        CPLPushErrorHandler(CPLQuietErrorHandler);
+        psResult = CPLHTTPFetch(CPLSPrintf("%s/%s/_mapping/%s",
+                        GetURL(), osLaunderedName.c_str(), m_pszMappingName), NULL);
+        CPLPopErrorHandler();
+        bMappingExists = psResult != NULL && psResult->pabyData != NULL &&
+                         !STARTS_WITH_CI((const char*)psResult->pabyData, "{}");
+        CPLHTTPDestroyResult(psResult);
+    }
+
+    // Restore error state
+    CPLErrorSetState( eLastErrorType, nLastErrorNo, osLastErrorMsg );
+
+    if( m_bOverwrite || CSLFetchBoolean(papszOptions, "OVERWRITE", FALSE) )
+    {
+        if( bMappingExists )
+        {
+            Delete(CPLSPrintf("%s/%s/_mapping/%s",
+                              GetURL(), osLaunderedName.c_str(), m_pszMappingName));
+        }
+    }
+    else if( bMappingExists )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "%s/%s already exists",
+                 osLaunderedName.c_str(), m_pszMappingName);
+        return NULL;
+    }
+
+    // Create the index
+    if( !bIndexExists )
+    {
+        if( !UploadFile(CPLSPrintf("%s/%s", GetURL(), osLaunderedName.c_str()), "") )
+            return NULL;
+    }
 
-    return papoLayers[nLayers - 1];
+    // If we have a user specified mapping, then go ahead and update it now
+    const char* pszLayerMapping = CSLFetchNameValueDef(papszOptions, "MAPPING", m_pszMapping);
+    if (pszLayerMapping != NULL) {
+        CPLString osLayerMapping;
+        if( strchr(pszLayerMapping, '{') == NULL )
+        {
+            VSILFILE* fp = VSIFOpenL(pszLayerMapping, "rb");
+            if( fp )
+            {
+                GByte* pabyRet = NULL;
+                CPL_IGNORE_RET_VAL(VSIIngestFile( fp, pszLayerMapping, &pabyRet, NULL, -1));
+                if( pabyRet )
+                {
+                    osLayerMapping = (char*)pabyRet;
+                    pszLayerMapping = osLayerMapping.c_str();
+                    VSIFree(pabyRet);
+                }
+                VSIFCloseL(fp);
+            }
+        }
+
+        if( !UploadFile(CPLSPrintf("%s/%s/%s/_mapping",
+                            GetURL(), osLaunderedName.c_str(), m_pszMappingName),
+                        pszLayerMapping) )
+        {
+            return NULL;
+        }
+    }
+
+    OGRElasticLayer* poLayer = new OGRElasticLayer(osLaunderedName.c_str(),
+                                                   osLaunderedName.c_str(),
+                                                   m_pszMappingName,
+                                                   this, papszOptions);
+    m_nLayers++;
+    m_papoLayers = (OGRElasticLayer **) CPLRealloc(m_papoLayers, m_nLayers * sizeof (OGRElasticLayer*));
+    m_papoLayers[m_nLayers - 1] = poLayer;
+
+    poLayer->FinalizeFeatureDefn(FALSE);
+
+    if( eGType != wkbNone )
+    {
+        const char* pszGeometryName = CSLFetchNameValueDef(papszOptions, "GEOMETRY_NAME", "geometry");
+        OGRGeomFieldDefn oFieldDefn(pszGeometryName, eGType);
+        oFieldDefn.SetSpatialRef(poSRS);
+        poLayer->CreateGeomField(&oFieldDefn, FALSE);
+    }
+    if( pszLayerMapping )
+        poLayer->SetManualMapping();
+
+    poLayer->SetIgnoreSourceID(CSLFetchBoolean(papszOptions, "IGNORE_SOURCE_ID", FALSE));
+    poLayer->SetDotAsNestedField(CSLFetchBoolean(papszOptions, "DOT_AS_NESTED_FIELD", TRUE));
+    poLayer->SetFID(CSLFetchNameValueDef(papszOptions, "FID", "ogc_fid"));
+    poLayer->SetNextFID(0);
+
+    return poLayer;
+}
+
+/************************************************************************/
+/*                               RunRequest()                           */
+/************************************************************************/
+
+json_object* OGRElasticDataSource::RunRequest(const char* pszURL, const char* pszPostContent)
+{
+    char** papszOptions = NULL;
+
+    if( pszPostContent && pszPostContent[0] )
+    {
+        papszOptions = CSLSetNameValue(papszOptions, "POSTFIELDS",
+                                       pszPostContent);
+    }
+
+    CPLHTTPResult * psResult = CPLHTTPFetch( pszURL, papszOptions );
+    CSLDestroy(papszOptions);
+
+    if( psResult->pszErrBuf != NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "%s",
+                psResult->pabyData ? (const char*) psResult->pabyData :
+                psResult->pszErrBuf);
+
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+
+    if( psResult->pabyData == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Empty content returned by server");
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+
+    if( STARTS_WITH((const char*) psResult->pabyData, "{\"error\":") )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "%s",
+                    (const char*) psResult->pabyData );
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+
+    json_tokener* jstok = NULL;
+    json_object* poObj = NULL;
+
+    jstok = json_tokener_new();
+    poObj = json_tokener_parse_ex(jstok, (const char*) psResult->pabyData, -1);
+    if( jstok->err != json_tokener_success)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                    "JSON parsing error: %s (at offset %d)",
+                    json_tokener_error_desc(jstok->err), jstok->char_offset);
+        json_tokener_free(jstok);
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+    json_tokener_free(jstok);
+
+    CPLHTTPDestroyResult(psResult);
+
+    if( json_object_get_type(poObj) != json_type_object )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Return is not a JSON dictionary");
+        json_object_put(poObj);
+        poObj = NULL;
+    }
+
+    return poObj;
 }
 
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
 
-int OGRElasticDataSource::Open(CPL_UNUSED const char * pszFilename,
-                               CPL_UNUSED int bUpdateIn) {
-    CPLError(CE_Failure, CPLE_NotSupported,
-            "OGR/Elastic driver does not support opening a file");
-    return FALSE;
+int OGRElasticDataSource::Open(GDALOpenInfo* poOpenInfo)
+{
+    eAccess = poOpenInfo->eAccess;
+    m_pszName = CPLStrdup(poOpenInfo->pszFilename);
+    m_osURL = (STARTS_WITH_CI(m_pszName, "ES:")) ? m_pszName + 3 : m_pszName;
+    if( m_osURL.size() == 0 )
+    {
+        const char* pszHost =
+            CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "HOST", "localhost");
+        m_osURL = pszHost;
+        m_osURL += ":";
+        const char* pszPort = CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "PORT", "9200");
+        m_osURL += pszPort;
+    }
+    m_nBatchSize = atoi(CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "BATCH_SIZE", "100"));
+    m_nFeatureCountToEstablishFeatureDefn = atoi(CSLFetchNameValueDef(
+        poOpenInfo->papszOpenOptions, "FEATURE_COUNT_TO_ESTABLISH_FEATURE_DEFN", "100"));
+    m_bJSonField = CSLFetchBoolean(poOpenInfo->papszOpenOptions, "JSON_FIELD", FALSE);
+    m_bFlattenNestedAttributes = CSLFetchBoolean(
+            poOpenInfo->papszOpenOptions, "FLATTEN_NESTED_ATTRIBUTES", TRUE);
+    m_osFID = CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "FID", "ogc_fid");
+
+    CPLHTTPResult* psResult = CPLHTTPFetch((m_osURL + "/_cat/indices?h=i").c_str(), NULL);
+    if( psResult == NULL || psResult->pszErrBuf != NULL )
+    {
+        CPLHTTPDestroyResult(psResult);
+        return FALSE;
+    }
+
+    // If no indices, fallback to querying _stats
+    if( psResult->pabyData == NULL )
+    {
+        CPLHTTPDestroyResult(psResult);
+
+        json_object* poRes = RunRequest((m_osURL + "/_stats").c_str());
+        if( poRes == NULL )
+            return FALSE;
+        json_object_put(poRes);
+        return TRUE;
+    }
+
+    char* pszCur = (char*)psResult->pabyData;
+    char* pszNextEOL = strchr(pszCur, '\n');
+    while( pszNextEOL && pszNextEOL > pszCur )
+    {
+        *pszNextEOL = '\0';
+
+        char* pszBeforeEOL = pszNextEOL - 1;
+        while( *pszBeforeEOL == ' ' )
+        {
+            *pszBeforeEOL = '\0';
+            pszBeforeEOL  --;
+        }
+
+        const char* pszIndexName = pszCur;
+
+        json_object* poRes = RunRequest((m_osURL + CPLString("/") + pszIndexName + CPLString("?pretty")).c_str());
+        if( poRes )
+        {
+            json_object* poLayerObj = json_object_object_get(poRes, pszIndexName);
+            json_object* poMappings = NULL;
+            if( poLayerObj && json_object_get_type(poLayerObj) == json_type_object )
+                poMappings = json_object_object_get(poLayerObj, "mappings");
+            if( poMappings && json_object_get_type(poMappings) == json_type_object )
+            {
+                json_object_iter it;
+                it.key = NULL;
+                it.val = NULL;
+                it.entry = NULL;
+                std::vector<CPLString> aosMappings;
+                json_object_object_foreachC( poMappings, it )
+                {
+                    aosMappings.push_back(it.key);
+                }
+                if( aosMappings.size() == 1 &&
+                    (aosMappings[0] == "FeatureCollection" || aosMappings[0] == "default") )
+                {
+                    OGRElasticLayer* poLayer = new OGRElasticLayer(
+                        pszCur, pszCur, aosMappings[0], this, poOpenInfo->papszOpenOptions);
+                    poLayer->InitFeatureDefnFromMapping(json_object_object_get(poMappings, aosMappings[0]),
+                                                        "", std::vector<CPLString>());
+
+                    m_nLayers++;
+                    m_papoLayers = (OGRElasticLayer **) CPLRealloc(m_papoLayers, m_nLayers * sizeof (OGRElasticLayer*));
+                    m_papoLayers[m_nLayers - 1] = poLayer;
+                }
+                else
+                {
+                    for(size_t i=0; i<aosMappings.size();i++)
+                    {
+                        OGRElasticLayer* poLayer = new OGRElasticLayer(
+                            (pszCur + CPLString("_") + aosMappings[i]).c_str(), pszCur, aosMappings[i], this, poOpenInfo->papszOpenOptions);
+                        poLayer->InitFeatureDefnFromMapping(json_object_object_get(poMappings, aosMappings[i]),
+                                                            "", std::vector<CPLString>());
+
+                        m_nLayers++;
+                        m_papoLayers = (OGRElasticLayer **) CPLRealloc(m_papoLayers, m_nLayers * sizeof (OGRElasticLayer*));
+                        m_papoLayers[m_nLayers - 1] = poLayer;
+                    }
+                }
+            }
+
+            json_object_put(poRes);
+        }
+
+        pszCur = pszNextEOL + 1;
+        pszNextEOL = strchr(pszCur, '\n');
+    }
+
+    CPLHTTPDestroyResult(psResult);
+    return TRUE;
 }
 
 
 /************************************************************************/
-/*                             DeleteIndex()                            */
+/*                             Delete()                                 */
 /************************************************************************/
 
-void OGRElasticDataSource::DeleteIndex(const CPLString &url) {
+void OGRElasticDataSource::Delete(const CPLString &url) {
     char** papszOptions = NULL;
     papszOptions = CSLAddNameValue(papszOptions, "CUSTOMREQUEST", "DELETE");
     CPLHTTPResult* psResult = CPLHTTPFetch(url, papszOptions);
@@ -131,7 +486,8 @@ void OGRElasticDataSource::DeleteIndex(const CPLString &url) {
 /*                            UploadFile()                              */
 /************************************************************************/
 
-void OGRElasticDataSource::UploadFile(const CPLString &url, const CPLString &data) {
+int OGRElasticDataSource::UploadFile(const CPLString &url, const CPLString &data) {
+    int bRet = TRUE;
     char** papszOptions = NULL;
     papszOptions = CSLAddNameValue(papszOptions, "POSTFIELDS", data.c_str());
     papszOptions = CSLAddNameValue(papszOptions, "HEADERS",
@@ -140,8 +496,18 @@ void OGRElasticDataSource::UploadFile(const CPLString &url, const CPLString &dat
     CPLHTTPResult* psResult = CPLHTTPFetch(url, papszOptions);
     CSLDestroy(papszOptions);
     if (psResult) {
+        if( psResult->pszErrBuf != NULL ||
+            (psResult->pabyData && STARTS_WITH((const char*) psResult->pabyData, "{\"error\":")) ||
+            (psResult->pabyData && strstr((const char*) psResult->pabyData, "\"errors\":true,") != NULL) )
+        {
+            bRet = FALSE;
+            CPLError(CE_Failure, CPLE_AppDefined, "%s",
+                        psResult->pabyData ? (const char*) psResult->pabyData :
+                        psResult->pszErrBuf);
+        }
         CPLHTTPDestroyResult(psResult);
     }
+    return bRet;
 }
 
 /************************************************************************/
@@ -149,45 +515,36 @@ void OGRElasticDataSource::UploadFile(const CPLString &url, const CPLString &dat
 /************************************************************************/
 
 int OGRElasticDataSource::Create(const char *pszFilename,
-                                 CPL_UNUSED char **papszOptions) {
-    this->pszName = CPLStrdup(pszFilename);
+                                 CPL_UNUSED char **papszOptions)
+{
+    eAccess = GA_Update;
+    this->m_pszName = CPLStrdup(pszFilename);
+    m_osURL = (STARTS_WITH_CI(pszFilename, "ES:")) ? pszFilename + 3 : pszFilename;
+    if( m_osURL.size() == 0 )
+        m_osURL = "localhost:9200";
 
     const char* pszMetaFile = CPLGetConfigOption("ES_META", NULL);
-    const char* pszWriteMap = CPLGetConfigOption("ES_WRITEMAP", NULL);;
-    this->bOverwrite = CSLTestBoolean(CPLGetConfigOption("ES_OVERWRITE", "0"));
-    this->nBulkUpload = (int) CPLAtof(CPLGetConfigOption("ES_BULK", "0"));
-
-    if (pszWriteMap != NULL) {
-        this->pszWriteMap = CPLStrdup(pszWriteMap);
-    }
+    this->m_bOverwrite = CPLTestBool(CPLGetConfigOption("ES_OVERWRITE", "0"));
+    this->m_nBulkUpload = (int) CPLAtof(CPLGetConfigOption("ES_BULK", "0"));
 
     // Read in the meta file from disk
     if (pszMetaFile != NULL)
     {
-        int fsize;
-        char *fdata;
-        FILE *fp;
-
-        fp = fopen(pszMetaFile, "rb");
-        if (fp != NULL) {
-            fseek(fp, 0, SEEK_END);
-            fsize = (int) ftell(fp);
-
-            fdata = (char *) malloc(fsize + 1);
-
-            fseek(fp, 0, SEEK_SET);
-            if (0 == fread(fdata, fsize, 1, fp)) {
-                CPLError(CE_Failure, CPLE_FileIO,
-                         "OGRElasticDataSource::Create read failed.");
+        VSILFILE* fp = VSIFOpenL(pszMetaFile, "rb");
+        if( fp )
+        {
+            GByte* pabyRet = NULL;
+            CPL_IGNORE_RET_VAL(VSIIngestFile( fp, pszMetaFile, &pabyRet, NULL, -1));
+            if( pabyRet )
+            {
+                this->m_pszMapping = (char*)pabyRet;
             }
-            fdata[fsize] = 0;
-            this->pszMapping = fdata;
-            fclose(fp);
+            VSIFCloseL(fp);
         }
     }
 
     // Do a status check to ensure that the server is valid
-    CPLHTTPResult* psResult = CPLHTTPFetch(CPLSPrintf("%s/_status", pszFilename), NULL);
+    CPLHTTPResult* psResult = CPLHTTPFetch(CPLSPrintf("%s/_stats", m_osURL.c_str()), NULL);
     int bOK = (psResult != NULL && psResult->pszErrBuf == NULL);
     if (!bOK)
     {
@@ -199,3 +556,61 @@ int OGRElasticDataSource::Create(const char *pszFilename,
 
     return bOK;
 }
+
+/************************************************************************/
+/*                             ExecuteSQL()                             */
+/************************************************************************/
+
+OGRLayer* OGRElasticDataSource::ExecuteSQL( const char *pszSQLCommand,
+                                            OGRGeometry *poSpatialFilter,
+                                            const char *pszDialect )
+{
+    for(int i=0; i<m_nLayers; i++ )
+    {
+        m_papoLayers[i]->SyncToDisk();
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Special case DELLAYER: command.                                 */
+/* -------------------------------------------------------------------- */
+    if( STARTS_WITH_CI(pszSQLCommand, "DELLAYER:") )
+    {
+        const char *pszLayerName = pszSQLCommand + 9;
+
+        while( *pszLayerName == ' ' )
+            pszLayerName++;
+
+        for( int iLayer = 0; iLayer < m_nLayers; iLayer++ )
+        {
+            if( EQUAL(m_papoLayers[iLayer]->GetName(),
+                      pszLayerName ))
+            {
+                DeleteLayer( iLayer );
+                break;
+            }
+        }
+        return NULL;
+    }
+
+    if( pszDialect != NULL && EQUAL(pszDialect, "ES") )
+    {
+        return new OGRElasticLayer("RESULT",
+                                   NULL,
+                                   NULL,
+                                   this, papszOpenOptions,
+                                   pszSQLCommand);
+    }
+    else
+    {
+        return GDALDataset::ExecuteSQL(pszSQLCommand, poSpatialFilter, pszDialect);
+    }
+}
+
+/************************************************************************/
+/*                          ReleaseResultSet()                          */
+/************************************************************************/
+
+void OGRElasticDataSource::ReleaseResultSet( OGRLayer * poLayer )
+{
+    delete poLayer;
+}
diff --git a/ogr/ogrsf_frmts/elastic/ogrelasticdriver.cpp b/ogr/ogrsf_frmts/elastic/ogrelasticdriver.cpp
index 3b2f616..61af233 100644
--- a/ogr/ogrsf_frmts/elastic/ogrelasticdriver.cpp
+++ b/ogr/ogrsf_frmts/elastic/ogrelasticdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrelasticdriver.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogrelasticdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  ElasticSearch Translator
  * Purpose:
@@ -30,7 +30,36 @@
 #include "ogr_elastic.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrelasticdriver.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogrelasticdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
+
+/************************************************************************/
+/*                   OGRElasticSearchDriverIdentify()                   */
+/************************************************************************/
+
+static int OGRElasticSearchDriverIdentify( GDALOpenInfo* poOpenInfo )
+
+{
+    return STARTS_WITH_CI(poOpenInfo->pszFilename, "ES:");
+}
+
+/************************************************************************/
+/*                  OGRElasticSearchDriverOpen()                        */
+/************************************************************************/
+
+static GDALDataset* OGRElasticSearchDriverOpen( GDALOpenInfo* poOpenInfo )
+
+{
+    if( !OGRElasticSearchDriverIdentify(poOpenInfo) )
+        return NULL;
+
+    OGRElasticDataSource *poDS = new OGRElasticDataSource();
+    if (!poDS->Open(poOpenInfo)) {
+        delete poDS;
+        poDS = NULL;
+    }
+
+    return poDS;
+}
 
 /************************************************************************/
 /*                     OGRElasticSearchDriverCreate()                   */
@@ -59,27 +88,66 @@ static GDALDataset* OGRElasticSearchDriverCreate( const char * pszName,
 void RegisterOGRElastic() {
     if (!GDAL_CHECK_VERSION("OGR/Elastic Search driver"))
         return;
-    GDALDriver  *poDriver;
 
-    if( GDALGetDriverByName( "ElasticSearch" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    if( GDALGetDriverByName( "ElasticSearch" ) != NULL )
+      return;
 
-        poDriver->SetDescription( "ElasticSearch" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                    "Elastic Search" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                    "drv_elasticsearch.html" );
+    GDALDriver  *poDriver = new GDALDriver();
 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
-    "<CreationOptionList/>");
+    poDriver->SetDescription( "ElasticSearch" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Elastic Search" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_elasticsearch.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, "ES:" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+                               "<CreationOptionList/>");
 
-        poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
-    "<LayerCreationOptionList/>");
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+    "<LayerCreationOptionList>"
+    "  <Option name='INDEX_NAME' type='string' description='Name of the index to create (or reuse). By default the index name is the layer name.'/>"
+    "  <Option name='MAPPING_NAME' type='string' description='Name of the mapping type within the index.' default='FeatureCollection'/>"
+    "  <Option name='MAPPING' type='string' description='Filename from which to read a user-defined mapping, or mapping as serialized JSon.'/>"
+    "  <Option name='WRITE_MAPPING' type='string' description='Filename where to write the OGR generated mapping.'/>"
+    "  <Option name='OVERWRITE' type='boolean' description='Whether to overwrite an existing collection with the layer name to be created' default='NO'/>"
+    "  <Option name='GEOMETRY_NAME' type='string' description='Name of geometry column.' default='geometry'/>"
+    "  <Option name='GEOM_MAPPING_TYPE' type='string-select' description='Mapping type for geometry fields' default='AUTO'>"
+    "    <Value>AUTO</Value>"
+    "    <Value>GEO_POINT</Value>"
+    "    <Value>GEO_SHAPE</Value>"
+    "  </Option>"
+    "  <Option name='GEOM_PRECISION' type='string' description='Desired geometry precision. Number followed by unit. For example 1m'/>"
+    "  <Option name='STORE_FIELDS' type='boolean' description='Whether fields should be stored in the index' default='NO'/>"
+    "  <Option name='STORED_FIELDS' type='string' description='List of comma separated field names that should be stored in the index'/>"
+    "  <Option name='NOT_ANALYZED_FIELDS' type='string' description='List of comma separated field names that should not be analyzed during indexing'/>"
+    "  <Option name='NOT_INDEXED_FIELDS' type='string' description='List of comma separated field names that should not be indexed'/>"
+    "  <Option name='BULK_INSERT' type='boolean' description='Whether to use bulk insert for feature creation' default='YES'/>"
+    "  <Option name='BULK_SIZE' type='integer' description='Size in bytes of the buffer for bulk upload' default='1000000'/>"
+    "  <Option name='DOT_AS_NESTED_FIELD' type='boolean' description='Whether to consider dot character in field name as sub-document' default='YES'/>"
+    "  <Option name='IGNORE_SOURCE_ID' type='boolean' description='Whether to ignore _id field in features passed to CreateFeature()' default='NO'/>"
+    "  <Option name='FID' type='string' description='Field name, with integer values, to use as FID' default='ogc_fid'/>"
+    "</LayerCreationOptionList>");
 
-        poDriver->pfnCreate = OGRElasticSearchDriverCreate;
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+"<OpenOptionList>"
+"  <Option name='HOST' type='string' description='Server hostname' default='localhost'/>"
+"  <Option name='PORT' type='integer' description='Server port' default='9200'/>"
+"  <Option name='BATCH_SIZE' type='integer' description='Number of features to retrieve per batch' default='100'/>"
+"  <Option name='FEATURE_COUNT_TO_ESTABLISH_FEATURE_DEFN' type='integer' description='Number of features to retrieve to establish feature definition. -1 = unlimited' default='100'/>"
+"  <Option name='JSON_FIELD' type='boolean' description='Whether to include a field with the full document as JSON' default='NO'/>"
+"  <Option name='FLATTEN_NESTED_ATTRIBUTES' type='boolean' description='Whether to recursively explore nested objects and produce flatten OGR attributes' default='YES'/>"
+"  <Option name='BULK_INSERT' type='boolean' description='Whether to use bulk insert for feature creation' default='YES'/>"
+"  <Option name='BULK_SIZE' type='integer' description='Size in bytes of the buffer for bulk upload' default='1000000'/>"
+"  <Option name='FID' type='string' description='Field name, with integer values, to use as FID' default='ogc_fid'/>"
+"</OpenOptionList>");
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
+                               "Integer Integer64 Real String Date DateTime "
+                               "Time IntegerList Integer64List RealList "
+                               "StringList Binary" );
+
+    poDriver->pfnIdentify = OGRElasticSearchDriverIdentify;
+    poDriver->pfnOpen = OGRElasticSearchDriverOpen;
+    poDriver->pfnCreate = OGRElasticSearchDriverCreate;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/elastic/ogrelasticlayer.cpp b/ogr/ogrsf_frmts/elastic/ogrelasticlayer.cpp
index 266530a..acfd6f5 100644
--- a/ogr/ogrsf_frmts/elastic/ogrelasticlayer.cpp
+++ b/ogr/ogrsf_frmts/elastic/ogrelasticlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrelasticlayer.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrelasticlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  ElasticSearch Translator
  * Purpose:
@@ -31,48 +31,99 @@
 #include "ogr_elastic.h"
 #include "cpl_conv.h"
 #include "cpl_minixml.h"
+#include "cpl_http.h"
 #include "ogr_api.h"
 #include "ogr_p.h"
-#include <json.h> // JSON-C
+#include "../geojson/ogrgeojsonwriter.h"
+#include "../geojson/ogrgeojsonreader.h"
+#include "../geojson/ogrgeojsonutils.h"
+#include "../xplane/ogr_xplane_geo_utils.h"
+#include <set>
 
-CPL_CVSID("$Id: ogrelasticlayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrelasticlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                           OGRElasticLayer()                          */
 /************************************************************************/
 
-OGRElasticLayer::OGRElasticLayer(CPL_UNUSED const char* pszFilename,
-                                 const char* pszLayerName,
+OGRElasticLayer::OGRElasticLayer(const char* pszLayerName,
+                                 const char* pszIndexName,
+                                 const char* pszMappingName,
                                  OGRElasticDataSource* poDS,
-                                 OGRSpatialReference *poSRSIn,
-                                 CPL_UNUSED int bWriteMode) {
-    this->pszLayerName = CPLStrdup(pszLayerName);
-    this->poDS = poDS;
-    this->pAttributes = NULL;
+                                 char** papszOptions,
+                                 const char* pszESSearch)
+{
+    m_poDS = poDS;
 
-    // If we are overwriting, then delete the current index if it exists
-    if (poDS->bOverwrite) {
-        poDS->DeleteIndex(CPLSPrintf("%s/%s", poDS->GetName(), pszLayerName));
+    m_osIndexName = pszIndexName ? pszIndexName : "";
+    m_osMappingName = pszMappingName ? pszMappingName : "";
+    m_osESSearch = pszESSearch ? pszESSearch : "";
+    m_osWriteMapFilename = CSLFetchNameValueDef(papszOptions, "WRITE_MAPPING",
+                                      m_poDS->m_pszWriteMap ? m_poDS->m_pszWriteMap : "");
+
+    m_eGeomTypeMapping = ES_GEOMTYPE_AUTO;
+    const char* pszESGeomType = CSLFetchNameValue(papszOptions, "GEOM_MAPPING_TYPE");
+    if( pszESGeomType != NULL )
+    {
+        if( EQUAL(pszESGeomType, "GEO_POINT") )
+            m_eGeomTypeMapping = ES_GEOMTYPE_GEO_POINT;
+        else if( EQUAL(pszESGeomType, "GEO_SHAPE") )
+            m_eGeomTypeMapping = ES_GEOMTYPE_GEO_SHAPE;
+    }
+    m_nBulkUpload = m_poDS->m_nBulkUpload;
+    if( CSLFetchBoolean(papszOptions, "BULK_INSERT", TRUE) )
+    {
+        m_nBulkUpload = atoi(CSLFetchNameValueDef(papszOptions, "BULK_SIZE", "1000000"));
     }
 
-    // Create the index
-    poDS->UploadFile(CPLSPrintf("%s/%s", poDS->GetName(), pszLayerName), "");
+    m_osPrecision = CSLFetchNameValueDef(papszOptions, "GEOM_PRECISION", "");
+    m_bStoreFields = CPL_TO_BOOL(CSLFetchBoolean(papszOptions, "STORE_FIELDS", false));
+
+    const char* pszStoredFields = CSLFetchNameValue(papszOptions, "STORED_FIELDS");
+    if( pszStoredFields )
+        m_papszStoredFields = CSLTokenizeString2(pszStoredFields, ",", 0);
+    else
+        m_papszStoredFields = NULL;
+
+    const char* pszNotAnalyzedFields = CSLFetchNameValue(papszOptions, "NOT_ANALYZED_FIELDS");
+    if( pszNotAnalyzedFields )
+        m_papszNotAnalyzedFields = CSLTokenizeString2(pszNotAnalyzedFields, ",", 0);
+    else
+        m_papszNotAnalyzedFields = NULL;
+
+    const char* pszNotIndexedFields = CSLFetchNameValue(papszOptions, "NOT_INDEXED_FIELDS");
+    if( pszNotIndexedFields )
+        m_papszNotIndexedFields = CSLTokenizeString2(pszNotIndexedFields, ",", 0);
+    else
+        m_papszNotIndexedFields = NULL;
+
+    m_poFeatureDefn = new OGRFeatureDefn(pszLayerName);
+    SetDescription( m_poFeatureDefn->GetName() );
+    m_poFeatureDefn->Reference();
+    m_poFeatureDefn->SetGeomType(wkbNone);
+
+    AddFieldDefn("_id", OFTString, std::vector<CPLString>());
 
-    // If we have a user specified mapping, then go ahead and update it now
-    if (poDS->pszMapping != NULL) {
-        poDS->UploadFile(CPLSPrintf("%s/%s/FeatureCollection/_mapping", poDS->GetName(), pszLayerName),
-                poDS->pszMapping);
+    if( m_osESSearch.size() )
+    {
+        AddFieldDefn("_index", OFTString, std::vector<CPLString>());
+        AddFieldDefn("_type", OFTString, std::vector<CPLString>());
     }
 
-    poFeatureDefn = new OGRFeatureDefn(pszLayerName);
-    SetDescription( poFeatureDefn->GetName() );
-    poFeatureDefn->Reference();
+    m_bFeatureDefnFinalized = FALSE;
+    m_bSerializeMapping = FALSE;
+    m_bManualMapping = FALSE;
+    m_bDotAsNestedField = TRUE;
 
-    poSRS = poSRSIn;
-    if (poSRS)
-        poSRS->Reference();
+    m_iCurID = 0;
+    m_nNextFID = -1;
+    m_iCurFeatureInPage = 0;
+    m_bEOF = FALSE;
+    m_poSpatialFilter = NULL;
+    m_bIgnoreSourceID = FALSE;
 
-    poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
+    // Undocumented. Only useful for developers
+    m_bAddPretty = CPLTestBool(CPLGetConfigOption("ES_ADD_PRETTY", "FALSE"));
 
     ResetReading();
     return;
@@ -83,274 +134,2394 @@ OGRElasticLayer::OGRElasticLayer(CPL_UNUSED const char* pszFilename,
 /************************************************************************/
 
 OGRElasticLayer::~OGRElasticLayer() {
-    PushIndex();
-
-    CPLFree(pszLayerName);
+    SyncToDisk();
 
-    poFeatureDefn->Release();
+    ResetReading();
 
-    if (poSRS != NULL)
-        poSRS->Release();
-}
+    json_object_put(m_poSpatialFilter);
 
+    for(int i=0;i<(int)m_apoCT.size();i++)
+        delete m_apoCT[i];
 
-/************************************************************************/
-/*                            GetLayerDefn()                            */
-/************************************************************************/
+    m_poFeatureDefn->Release();
 
-OGRFeatureDefn * OGRElasticLayer::GetLayerDefn() {
-    return poFeatureDefn;
+    CSLDestroy(m_papszStoredFields);
+    CSLDestroy(m_papszNotAnalyzedFields);
+    CSLDestroy(m_papszNotIndexedFields);
 }
 
 /************************************************************************/
-/*                            ResetReading()                            */
+/*                              AddFieldDefn()                          */
 /************************************************************************/
 
-void OGRElasticLayer::ResetReading() {
-    return;
+void OGRElasticLayer::AddFieldDefn( const char* pszName,
+                                    OGRFieldType eType,
+                                    const std::vector<CPLString>& aosPath,
+                                    OGRFieldSubType eSubType )
+{
+    OGRFieldDefn oFieldDefn(pszName, eType);
+    oFieldDefn.SetSubType(eSubType);
+    if( eSubType == OFSTBoolean )
+        oFieldDefn.SetWidth(1);
+    m_aaosFieldPaths.push_back(aosPath);
+    if( aosPath.size() )
+        m_aosMapToFieldIndex[ BuildPathFromArray(aosPath) ] = m_poFeatureDefn->GetFieldCount();
+    m_poFeatureDefn->AddFieldDefn(&oFieldDefn);
 }
 
 /************************************************************************/
-/*                           GetNextFeature()                           */
+/*                           AddGeomFieldDefn()                         */
 /************************************************************************/
 
-OGRFeature *OGRElasticLayer::GetNextFeature() {
-    CPLError(CE_Failure, CPLE_NotSupported,
-            "Cannot read features when writing a Elastic file");
-    return NULL;
-}
+void OGRElasticLayer::AddGeomFieldDefn( const char* pszName,
+                                        OGRwkbGeometryType eType,
+                                        const std::vector<CPLString>& aosPath,
+                                        int bIsGeoPoint )
+{
+    OGRGeomFieldDefn oFieldDefn(pszName, eType);
+    m_aaosGeomFieldPaths.push_back(aosPath);
+    m_aosMapToGeomFieldIndex[ BuildPathFromArray(aosPath) ] = m_poFeatureDefn->GetGeomFieldCount();
+    m_abIsGeoPoint.push_back(bIsGeoPoint);
 
-/************************************************************************/
-/*                            AppendGroup()                             */
-/************************************************************************/
+    OGRSpatialReference* poSRS_WGS84 = new OGRSpatialReference();
+    poSRS_WGS84->SetFromUserInput(SRS_WKT_WGS84);
+    oFieldDefn.SetSpatialRef(poSRS_WGS84);
+    poSRS_WGS84->Dereference();
 
-json_object *AppendGroup(json_object *parent, const CPLString &name) {
-    json_object *obj = json_object_new_object();
-    json_object *properties = json_object_new_object();
-    json_object_object_add(parent, name, obj);
-    json_object_object_add(obj, "properties", properties);
-    return properties;
+    m_poFeatureDefn->AddGeomFieldDefn(&oFieldDefn);
+
+    m_apoCT.push_back(NULL);
 }
 
 /************************************************************************/
-/*                           AddPropertyMap()                           */
+/*                     InitFeatureDefnFromMapping()                     */
 /************************************************************************/
 
-json_object *AddPropertyMap(const CPLString &type, const CPLString &format = "") {
-    json_object *obj = json_object_new_object();
-    json_object_object_add(obj, "store", json_object_new_string("yes"));
-    json_object_object_add(obj, "type", json_object_new_string(type.c_str()));
-    if (!format.empty()) {
-        json_object_object_add(obj, "format", json_object_new_string(format.c_str()));
+void OGRElasticLayer::InitFeatureDefnFromMapping(json_object* poSchema,
+                                                 const char* pszPrefix,
+                                                 const std::vector<CPLString>& aosPath)
+{
+    json_object* poTopProperties = json_object_object_get(poSchema, "properties");
+    if( poTopProperties == NULL || json_object_get_type(poTopProperties) != json_type_object )
+        return;
+    json_object_iter it;
+    it.key = NULL;
+    it.val = NULL;
+    it.entry = NULL;
+    json_object_object_foreachC( poTopProperties, it )
+    {
+        json_object* poProperties = json_object_object_get(it.val, "properties");
+        if( poProperties && json_object_get_type(poProperties) == json_type_object )
+        {
+            json_object* poType = json_ex_get_object_by_path(poProperties, "coordinates.type");
+            if( poType && json_object_get_type(poType) == json_type_string &&
+                strcmp(json_object_get_string(poType), "geo_point") == 0 )
+            {
+                CPLString osFieldName;
+                if( pszPrefix[0] )
+                {
+                    osFieldName = pszPrefix;
+                    osFieldName += ".";
+                }
+                osFieldName += it.key;
+
+                if( m_poFeatureDefn->GetGeomFieldIndex(osFieldName) < 0 )
+                {
+                    std::vector<CPLString> aosNewPaths = aosPath;
+                    aosNewPaths.push_back(osFieldName);
+                    aosNewPaths.push_back("coordinates");
+
+                    AddGeomFieldDefn(osFieldName, wkbPoint, aosNewPaths, TRUE);
+                }
+
+                continue;
+            }
+
+            if( aosPath.size() == 0 && m_osMappingName == "FeatureCollection" && strcmp(it.key, "properties") == 0 )
+            {
+                std::vector<CPLString> aosNewPaths = aosPath;
+                aosNewPaths.push_back(it.key);
+
+                InitFeatureDefnFromMapping(it.val, pszPrefix, aosNewPaths);
+
+                continue;
+            }
+            else if( m_poDS->m_bFlattenNestedAttributes )
+            {
+                std::vector<CPLString> aosNewPaths = aosPath;
+                aosNewPaths.push_back(it.key);
+
+                CPLString osPrefix;
+                if( pszPrefix[0] )
+                {
+                    osPrefix = pszPrefix;
+                    osPrefix += ".";
+                }
+                osPrefix += it.key;
+
+                InitFeatureDefnFromMapping(it.val, osPrefix, aosNewPaths);
+
+                continue;
+            }
+        }
+
+        if( aosPath.size() == 0 && EQUAL(it.key, m_poDS->GetFID()) )
+        {
+            m_osFID = it.key;
+        }
+        else
+        {
+            CreateFieldFromSchema(it.key, pszPrefix, aosPath, it.val);
+        }
+    }
+
+    if( aosPath.size() == 0 )
+    {
+        json_object* poMeta = json_object_object_get(poSchema, "_meta");
+        if( poMeta && json_object_get_type(poMeta) == json_type_object )
+        {
+            json_object* poFID = json_object_object_get(poMeta, "fid");
+            if( poFID && json_object_get_type(poFID) == json_type_string )
+                m_osFID = json_object_get_string(poFID);
+
+            json_object* poGeomFields = json_object_object_get(poMeta, "geomfields");
+            if( poGeomFields && json_object_get_type(poGeomFields) == json_type_object )
+            {
+                for( int i=0; i< m_poFeatureDefn->GetGeomFieldCount(); i++ )
+                {
+                    json_object* poObj = json_object_object_get(poGeomFields,
+                            m_poFeatureDefn->GetGeomFieldDefn(i)->GetNameRef());
+                    if( poObj && json_object_get_type(poObj) == json_type_string )
+                    {
+                        OGRwkbGeometryType eType = OGRFromOGCGeomType(json_object_get_string(poObj));
+                        if( eType != wkbUnknown )
+                            m_poFeatureDefn->GetGeomFieldDefn(i)->SetType(eType);
+                    }
+                }
+            }
+
+            json_object* poFields = json_object_object_get(poMeta, "fields");
+            if( poFields && json_object_get_type(poFields) == json_type_object )
+            {
+                for( int i=0; i< m_poFeatureDefn->GetFieldCount(); i++ )
+                {
+                    json_object* poObj = json_object_object_get(poFields,
+                            m_poFeatureDefn->GetFieldDefn(i)->GetNameRef());
+                    if( poObj && json_object_get_type(poObj) == json_type_string )
+                    {
+                        for(int j=0; j<=OFTMaxType;j++)
+                        {
+                            if( EQUAL(OGR_GetFieldTypeName((OGRFieldType)j),
+                                      json_object_get_string(poObj)) )
+                            {
+                                m_poFeatureDefn->GetFieldDefn(i)->SetType((OGRFieldType)j);
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
     }
-    return obj;
 }
 
 /************************************************************************/
-/*                             BuildMap()                               */
+/*                        CreateFieldFromSchema()                       */
 /************************************************************************/
 
-CPLString OGRElasticLayer::BuildMap() {
-    json_object *map = json_object_new_object();
-    json_object *properties = json_object_new_object();
+void OGRElasticLayer::CreateFieldFromSchema(const char* pszName,
+                                            const char* pszPrefix,
+                                            std::vector<CPLString> aosPath,
+                                            json_object* poObj)
+{
+    const char* pszType = "";
+    json_object* poType = json_object_object_get(poObj, "type");
+    if( poType && json_object_get_type(poType) == json_type_string )
+    {
+        pszType = json_object_get_string(poType);
+    }
 
-    json_object *Feature = AppendGroup(map, "FeatureCollection");
-    json_object_object_add(Feature, "type", AddPropertyMap("string"));
-    json_object_object_add(Feature, "properties", properties);
-    if (pAttributes) json_object_object_add(properties, "properties", (json_object *) pAttributes);
-    json_object *geometry = AppendGroup(Feature, "geometry");
-    json_object_object_add(geometry, "type", AddPropertyMap("string"));
-    json_object_object_add(geometry, "coordinates", AddPropertyMap("geo_point"));
+    CPLString osFieldName;
+    if( pszPrefix[0] )
+    {
+        osFieldName = pszPrefix;
+        osFieldName += ".";
+    }
+    osFieldName += pszName;
 
-    CPLString jsonMap(json_object_to_json_string(map));
-    json_object_put(map);
+    if( EQUAL(pszType, "geo_point") || EQUAL(pszType, "geo_shape") )
+    {
+        if( m_poFeatureDefn->GetGeomFieldIndex(osFieldName) >= 0 )
+            return;
 
-    // The attribute's were freed from the deletion of the map object
-	// because we added it as a child of one of the map object attributes
-    if (pAttributes) {
-        pAttributes = NULL;
+        aosPath.push_back(pszName);
+        AddGeomFieldDefn(osFieldName,
+                         EQUAL(pszType, "geo_point") ? wkbPoint : wkbUnknown,
+                         aosPath, EQUAL(pszType, "geo_point"));
     }
+    else if( !( aosPath.size() == 0 && m_osMappingName == "FeatureCollection" ) )
+    {
+        if( m_poFeatureDefn->GetFieldIndex(osFieldName) >= 0 )
+            return;
 
-    return jsonMap;
+        OGRFieldType eType = OFTString;
+        OGRFieldSubType eSubType = OFSTNone;
+        if( EQUAL(pszType, "integer") )
+            eType = OFTInteger;
+        else if( EQUAL(pszType, "boolean") )
+        {
+            eType = OFTInteger;
+            eSubType = OFSTBoolean;
+        }
+        else if( EQUAL(pszType, "long") )
+            eType = OFTInteger64;
+        else if( EQUAL(pszType, "float") )
+            eType = OFTReal;
+        else if( EQUAL(pszType, "double") )
+            eType = OFTReal;
+        else if( EQUAL(pszType, "date") )
+        {
+            eType = OFTDateTime;
+            json_object* poFormat = json_object_object_get(poObj, "format");
+            if( poFormat && json_object_get_type(poFormat) == json_type_string )
+            {
+                const char* pszFormat = json_object_get_string(poFormat);
+                if( EQUAL(pszFormat, "HH:mm:ss.SSS") || EQUAL(pszFormat, "time") )
+                    eType = OFTTime;
+                else if( EQUAL(pszFormat, "yyyy/MM/dd") || EQUAL(pszFormat, "date") )
+                    eType = OFTDate;
+            }
+        }
+        else if( EQUAL(pszType, "binary") )
+            eType = OFTBinary;
+
+        aosPath.push_back( pszName );
+        AddFieldDefn(osFieldName, eType, aosPath, eSubType);
+    }
 }
 
 /************************************************************************/
-/*                           ICreateFeature()                            */
+/*                        FinalizeFeatureDefn()                         */
 /************************************************************************/
 
-OGRErr OGRElasticLayer::ICreateFeature(OGRFeature *poFeature) {
+void OGRElasticLayer::FinalizeFeatureDefn(int bReadFeatures)
+{
+    if( m_bFeatureDefnFinalized )
+        return;
 
-    // Check to see if the user has elected to only write out the mapping file
-    // This method will only write out one layer from the vector file in cases where there are multiple layers
-    if (poDS->pszWriteMap != NULL) {
-        if (pAttributes) {
-            CPLString map = BuildMap();
+    m_bFeatureDefnFinalized = TRUE;
 
-            // Write the map to a file
-            FILE *f = fopen(poDS->pszWriteMap, "wb");
-            if (f) {
-                fwrite(map.c_str(), 1, map.length(), f);
-                fclose(f);
+    int nFeatureCountToEstablishFeatureDefn = m_poDS->m_nFeatureCountToEstablishFeatureDefn;
+    if( m_osESSearch.size() && nFeatureCountToEstablishFeatureDefn <= 0 )
+        nFeatureCountToEstablishFeatureDefn = 1;
+    std::set< std::pair<CPLString, CPLString> > oVisited;
+
+    if( bReadFeatures && nFeatureCountToEstablishFeatureDefn != 0 )
+    {
+        //CPLDebug("ES", "Try to get %d features to establish feature definition",
+        //         FeatureCountToEstablishFeatureDefn);
+        int bFirst = TRUE;
+        int nAlreadyQueried = 0;
+        while( true )
+        {
+            json_object* poResponse;
+            CPLString osRequest, osPostData;
+            if( bFirst )
+            {
+                bFirst = FALSE;
+                if(  m_osESSearch.size() )
+                {
+                    osRequest = CPLSPrintf("%s/_search?scroll=1m&size=%d",
+                           m_poDS->GetURL(), m_poDS->m_nBatchSize);
+                    osPostData = m_osESSearch;
+                }
+                else
+                    osRequest = CPLSPrintf("%s/%s/%s/_search?scroll=1m&size=%d",
+                           m_poDS->GetURL(), m_osIndexName.c_str(),
+                           m_osMappingName.c_str(), m_poDS->m_nBatchSize);
+            }
+            else
+            {
+                if( m_osScrollID.size() == 0 )
+                    break;
+                osRequest = CPLSPrintf("%s/_search/scroll?scroll=1m&size=%d&scroll_id=%s",
+                               m_poDS->GetURL(), m_poDS->m_nBatchSize, m_osScrollID.c_str());
+            }
+
+            if( m_bAddPretty )
+                osRequest += "&pretty";
+            poResponse = m_poDS->RunRequest(osRequest, osPostData);
+            if( poResponse == NULL )
+            {
+                break;
+            }
+            json_object* poScrollID = json_object_object_get(poResponse, "_scroll_id");
+            if( poScrollID )
+            {
+                const char* pszScrollID = json_object_get_string(poScrollID);
+                if( pszScrollID )
+                    m_osScrollID = pszScrollID;
+            }
+
+            json_object* poHits = json_ex_get_object_by_path(poResponse, "hits.hits");
+            if( poHits == NULL || json_object_get_type(poHits) != json_type_array )
+            {
+                json_object_put(poResponse);
+                break;
+            }
+            int nHits = json_object_array_length(poHits);
+            if( nHits == 0 )
+            {
+                m_osScrollID = "";
+                json_object_put(poResponse);
+                break;
+            }
+            for(int i=0;i<nHits;i++)
+            {
+                json_object* poHit = json_object_array_get_idx(poHits, i);
+                if( poHit == NULL || json_object_get_type(poHit) != json_type_object )
+                {
+                    continue;
+                }
+                json_object* poSource = json_object_object_get(poHit, "_source");
+                if( poSource == NULL || json_object_get_type(poSource) != json_type_object )
+                {
+                    continue;
+                }
+
+                if( m_osESSearch.size() )
+                {
+                    json_object* poIndex = json_object_object_get(poHit, "_index");
+                    if( poIndex == NULL || json_object_get_type(poIndex) != json_type_string )
+                        break;
+                    json_object* poType = json_object_object_get(poHit, "_type");
+                    if( poType == NULL || json_object_get_type(poType) != json_type_string )
+                        break;
+                    CPLString osIndex(json_object_get_string(poIndex));
+                    m_osMappingName = json_object_get_string(poType);
+
+                    if( oVisited.find( std::pair<CPLString,CPLString>(osIndex, m_osMappingName) ) == oVisited.end() )
+                    {
+                        oVisited.insert( std::pair<CPLString,CPLString>(osIndex, m_osMappingName) );
+
+                        json_object* poMappingRes = m_poDS->RunRequest(
+                            (m_poDS->GetURL() + CPLString("/") + osIndex + CPLString("/_mapping/") + m_osMappingName + CPLString("?pretty")).c_str());
+                        if( poMappingRes )
+                        {
+                            json_object* poLayerObj = json_object_object_get(poMappingRes, osIndex);
+                            json_object* poMappings = NULL;
+                            if( poLayerObj && json_object_get_type(poLayerObj) == json_type_object )
+                                poMappings = json_object_object_get(poLayerObj, "mappings");
+                            if( poMappings && json_object_get_type(poMappings) == json_type_object )
+                            {
+                                json_object* poMapping = json_object_object_get(poMappings, m_osMappingName);
+                                if( poMapping)
+                                {
+                                    InitFeatureDefnFromMapping(poMapping, "", std::vector<CPLString>());
+                                }
+                            }
+                            json_object_put(poMappingRes);
+                        }
+                    }
+                }
+
+                json_object_iter it;
+                it.key = NULL;
+                it.val = NULL;
+                it.entry = NULL;
+                json_object_object_foreachC( poSource, it )
+                {
+                    if( m_osFID.size() )
+                    {
+                        if( EQUAL(it.key, m_osFID) )
+                            continue;
+                    }
+                    else if( EQUAL(it.key, m_poDS->GetFID()) )
+                    {
+                        m_osFID = it.key;
+                        continue;
+                    }
+
+                    if( m_osMappingName == "FeatureCollection" )
+                    {
+                        if( strcmp(it.key, "properties") == 0 &&
+                            json_object_get_type(it.val) == json_type_object )
+                        {
+                            json_object_iter it2;
+                            it2.key = NULL;
+                            it2.val = NULL;
+                            it2.entry = NULL;
+                            json_object_object_foreachC( it.val, it2 )
+                            {
+                                std::vector<CPLString> aosPath;
+                                aosPath.push_back("properties");
+                                AddOrUpdateField(it2.key, it2.key, it2.val, '.', aosPath);
+                            }
+                        }
+                    }
+                    else
+                    {
+                        std::vector<CPLString> aosPath;
+                        AddOrUpdateField(it.key, it.key, it.val, '.', aosPath);
+                    }
+                }
+
+                nAlreadyQueried ++;
+                if( nFeatureCountToEstablishFeatureDefn > 0 &&
+                    nAlreadyQueried >= nFeatureCountToEstablishFeatureDefn )
+                {
+                    break;
+                }
+            }
+
+            json_object_put(poResponse);
+
+            if( nFeatureCountToEstablishFeatureDefn > 0 &&
+                nAlreadyQueried >= nFeatureCountToEstablishFeatureDefn )
+            {
+                break;
             }
         }
-        return OGRERR_NONE;
+
+        ResetReading();
     }
 
-    // Check to see if we have any fields to upload to this index
-    if (poDS->pszMapping == NULL && pAttributes) {
-        poDS->UploadFile(CPLSPrintf("%s/%s/FeatureCollection/_mapping", poDS->GetName(), pszLayerName), BuildMap());
+    if( m_poDS->m_bJSonField )
+    {
+        AddFieldDefn("_json", OFTString, std::vector<CPLString>() );
     }
+}
 
-    // Get the center point of the geometry
-    OGREnvelope env;
-	if (!poFeature->GetGeometryRef()) {
-		return OGRERR_FAILURE;
-	}
-    poFeature->GetGeometryRef()->getEnvelope(&env);
+/************************************************************************/
+/*                         BuildPathFromArray()                         */
+/************************************************************************/
 
-    json_object *fieldObject = json_object_new_object();
-    json_object *geometry = json_object_new_object();
-    json_object *coordinates = json_object_new_array();
-    json_object *properties = json_object_new_object();
+CPLString OGRElasticLayer::BuildPathFromArray(const std::vector<CPLString>& aosPath)
+{
+    CPLString osPath(aosPath[0]);
+    for(size_t i=1;i<aosPath.size();i++)
+    {
+        osPath += ".";
+        osPath += aosPath[i];
+    }
+    return osPath;
+}
 
-    json_object_object_add(fieldObject, "geometry", geometry);
-    json_object_object_add(geometry, "type", json_object_new_string("POINT"));
-    json_object_object_add(geometry, "coordinates", coordinates);
-    json_object_array_add(coordinates, json_object_new_double((env.MaxX + env.MinX)*0.5));
-    json_object_array_add(coordinates, json_object_new_double((env.MaxY + env.MinY)*0.5));
-    json_object_object_add(fieldObject, "type", json_object_new_string("Feature"));
-    json_object_object_add(fieldObject, "properties", properties);
-
-    // For every field that
-    int fieldCount = poFeatureDefn->GetFieldCount();
-    for (int i = 0; i < fieldCount; i++) {
-		if(!poFeature->IsFieldSet( i ) ) {
-			continue;
-		}
-        switch (poFeatureDefn->GetFieldDefn(i)->GetType()) {
-            case OFTInteger:
-                json_object_object_add(properties,
-                        poFeatureDefn->GetFieldDefn(i)->GetNameRef(),
-                        json_object_new_int(poFeature->GetFieldAsInteger(i)));
-                break;
-            case OFTReal:
-                json_object_object_add(properties,
-                        poFeatureDefn->GetFieldDefn(i)->GetNameRef(),
-                        json_object_new_double(poFeature->GetFieldAsDouble(i)));
-                break;
-            default:
+/************************************************************************/
+/*                         GetOGRGeomTypeFromES()                       */
+/************************************************************************/
+
+static OGRwkbGeometryType GetOGRGeomTypeFromES(const char* pszType)
+{
+    if( EQUAL( pszType, "envelope") )
+        return wkbPolygon;
+    if( EQUAL( pszType, "circle") )
+        return wkbPolygon;
+    return OGRFromOGCGeomType(pszType);
+}
+
+/************************************************************************/
+/*                         AddOrUpdateField()                           */
+/************************************************************************/
+
+void OGRElasticLayer::AddOrUpdateField(const char* pszAttrName,
+                                       const char* pszKey,
+                                       json_object* poObj,
+                                       char chNestedAttributeSeparator,
+                                       std::vector<CPLString>& aosPath)
+{
+    json_type eJSONType = json_object_get_type(poObj);
+    if( eJSONType == json_type_null )
+        return;
+
+    if( eJSONType == json_type_object )
+    {
+        json_object* poType = json_object_object_get(poObj, "type");
+        OGRwkbGeometryType eGeomType;
+        if( poType && json_object_get_type(poType) == json_type_string &&
+            (eGeomType = GetOGRGeomTypeFromES(json_object_get_string(poType))) != wkbUnknown &&
+            json_object_object_get(poObj, (eGeomType == wkbGeometryCollection) ? "geometries" : "coordinates") )
+        {
+            int nIndex = m_poFeatureDefn->GetGeomFieldIndex(pszAttrName);
+            if( nIndex < 0 )
+            {
+                aosPath.push_back(pszKey);
+                AddGeomFieldDefn( pszAttrName, eGeomType, aosPath, FALSE );
+            }
+            else
+            {
+                OGRGeomFieldDefn* poFDefn = m_poFeatureDefn->GetGeomFieldDefn(nIndex);
+                if( poFDefn->GetType() != eGeomType )
+                    poFDefn->SetType(wkbUnknown);
+            }
+        }
+        else if( m_poDS->m_bFlattenNestedAttributes )
+        {
+            if( m_poFeatureDefn->GetGeomFieldIndex(pszAttrName) >= 0 )
+                return;
+            aosPath.push_back(pszKey);
+
+            json_object_iter it;
+            it.key = NULL;
+            it.val = NULL;
+            it.entry = NULL;
+            json_object_object_foreachC( poObj, it )
             {
-                CPLString tmp = poFeature->GetFieldAsString(i);
-                json_object_object_add(properties,
-                        poFeatureDefn->GetFieldDefn(i)->GetNameRef(),
-                        json_object_new_string(tmp));
+                char szSeparator[2];
+                szSeparator[0] = chNestedAttributeSeparator;
+                szSeparator[1] = 0;
+                CPLString osAttrName(CPLSPrintf("%s%s%s", pszAttrName, szSeparator,
+                                                it.key));
+
+                std::vector<CPLString> aosNewPaths(aosPath);
+                AddOrUpdateField(osAttrName, it.key, it.val, chNestedAttributeSeparator,
+                                 aosNewPaths);
             }
+            return;
         }
     }
+    /*else if( eJSONType == json_type_array )
+    {
+        if( m_poFeatureDefn->GetGeomFieldIndex(pszAttrName) >= 0 )
+            return;
+    }*/
 
-    // Build the field string
-    CPLString fields(json_object_to_json_string(fieldObject));
-    json_object_put(fieldObject);
+    if( m_poFeatureDefn->GetGeomFieldIndex(pszAttrName) >= 0 )
+        return;
 
-    // Check to see if we're using bulk uploading
-    if (poDS->nBulkUpload > 0) {
-        sIndex += CPLSPrintf("{\"index\" :{\"_index\":\"%s\", \"_type\":\"FeatureCollection\"}}\n", pszLayerName) +
-                fields + "\n\n";
+    OGRFieldSubType eNewSubType;
+    OGRFieldType eNewType = GeoJSONPropertyToFieldType( poObj, eNewSubType );
 
-        // Only push the data if we are over our bulk upload limit
-        if ((int) sIndex.length() > poDS->nBulkUpload) {
-            PushIndex();
+    int nIndex = m_poFeatureDefn->GetFieldIndex(pszAttrName);
+    OGRFieldDefn* poFDefn = NULL;
+    if( nIndex >= 0 )
+        poFDefn = m_poFeatureDefn->GetFieldDefn(nIndex);
+    if( (poFDefn == NULL && eNewType == OFTString) ||
+        (poFDefn != NULL &&
+         (poFDefn->GetType() == OFTDate || poFDefn->GetType() == OFTDateTime || poFDefn->GetType() == OFTTime) ) )
+    {
+        int nYear, nMonth, nDay, nHour, nMinute;
+        float fSecond;
+        if( sscanf(json_object_get_string(poObj),
+                   "%04d/%02d/%02d %02d:%02d",
+                   &nYear, &nMonth, &nDay, &nHour, &nMinute) == 5 ||
+            sscanf(json_object_get_string(poObj),
+                   "%04d-%02d-%02dT%02d:%02d",
+                   &nYear, &nMonth, &nDay, &nHour, &nMinute) == 5 )
+        {
+            eNewType = OFTDateTime;
+        }
+        else if( sscanf(json_object_get_string(poObj),
+                    "%04d/%02d/%02d",
+                    &nYear, &nMonth, &nDay) == 3 ||
+                 sscanf(json_object_get_string(poObj),
+                    "%04d-%02d-%02d",
+                    &nYear, &nMonth, &nDay) == 3)
+        {
+            eNewType = OFTDate;
         }
+        else if( sscanf(json_object_get_string(poObj),
+                    "%02d:%02d:%f",
+                    &nHour, &nMinute, &fSecond) == 3 )
+        {
+            eNewType = OFTTime;
+        }
+    }
 
-    } else { // Fall back to using single item upload for every feature
-        poDS->UploadFile(CPLSPrintf("%s/%s/FeatureCollection/", poDS->GetName(), pszLayerName), fields);
+    if( poFDefn == NULL )
+    {
+        aosPath.push_back(pszKey);
+        AddFieldDefn( pszAttrName, eNewType, aosPath, eNewSubType );
+    }
+    else
+    {
+        OGRUpdateFieldType(poFDefn, eNewType, eNewSubType);
     }
+}
+
+/************************************************************************/
+/*                              SyncToDisk()                            */
+/************************************************************************/
+
+OGRErr OGRElasticLayer::SyncToDisk()
+{
+    if( WriteMapIfNecessary() != OGRERR_NONE )
+        return OGRERR_FAILURE;
+
+    if( !PushIndex() )
+        return OGRERR_FAILURE;
 
     return OGRERR_NONE;
 }
 
+
 /************************************************************************/
-/*                             PushIndex()                              */
+/*                            GetLayerDefn()                            */
 /************************************************************************/
 
-void OGRElasticLayer::PushIndex() {
-    if (sIndex.empty()) {
-        return;
-    }
+OGRFeatureDefn * OGRElasticLayer::GetLayerDefn() {
+
+    FinalizeFeatureDefn();
 
-    poDS->UploadFile(CPLSPrintf("%s/_bulk", poDS->GetName()), sIndex);
-    sIndex.clear();
+    return m_poFeatureDefn;
 }
 
 /************************************************************************/
-/*                            CreateField()                             */
+/*                            GetFIDColumn()                            */
 /************************************************************************/
 
-OGRErr OGRElasticLayer::CreateField(OGRFieldDefn *poFieldDefn,
-                                    CPL_UNUSED int bApproxOK) {
-    if (!pAttributes) {
-        pAttributes = json_object_new_object();
+const char* OGRElasticLayer::GetFIDColumn()
+{
+    GetLayerDefn();
+    return m_osFID.c_str();
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRElasticLayer::ResetReading()
+{
+    if( m_osScrollID.size() )
+    {
+        char** papszOptions = CSLAddNameValue(NULL, "CUSTOMREQUEST", "DELETE");
+        CPLHTTPResult* psResult = CPLHTTPFetch((m_poDS->GetURL() + CPLString("/_search/scroll?scroll_id=") + m_osScrollID).c_str(), papszOptions);
+        CSLDestroy(papszOptions);
+        CPLHTTPDestroyResult(psResult);
+
+        m_osScrollID = "";
     }
+    for(int i=0;i<(int)m_apoCachedFeatures.size();i++)
+        delete m_apoCachedFeatures[i];
+    m_apoCachedFeatures.resize(0);
+    m_iCurID = 0;
+    m_iCurFeatureInPage = 0;
+    m_bEOF = FALSE;
+}
 
-    switch (poFieldDefn->GetType()) {
-        case OFTInteger:
-            json_object_object_add((json_object *) pAttributes, poFieldDefn->GetNameRef(), AddPropertyMap("integer"));
-            break;
-        case OFTReal:
-            json_object_object_add((json_object *) pAttributes, poFieldDefn->GetNameRef(), AddPropertyMap("float"));
-            break;
-        case OFTString:
-            json_object_object_add((json_object *) pAttributes, poFieldDefn->GetNameRef(), AddPropertyMap("string"));
-            break;
-        case OFTDateTime:
-        case OFTDate:
-            json_object_object_add((json_object *) pAttributes, poFieldDefn->GetNameRef(), AddPropertyMap("date", "yyyy/MM/dd HH:mm:ss||yyyy/MM/dd"));
-            break;
-        default:
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
 
-            // These types are mapped as strings and may not be correct
-            /*
-                            OFTTime:
-                            OFTIntegerList = 1,
-                            OFTRealList = 3,
-                            OFTStringList = 5,
-                            OFTWideString = 6,
-                            OFTWideStringList = 7,
-                            OFTBinary = 8,
-                            OFTMaxType = 11
-             */
-            json_object_object_add((json_object *) pAttributes, poFieldDefn->GetNameRef(), AddPropertyMap("string"));
-    }
-
-    poFeatureDefn->AddFieldDefn(poFieldDefn);
-    return OGRERR_NONE;
+OGRFeature *OGRElasticLayer::GetNextFeature()
+
+{
+    FinalizeFeatureDefn();
+
+    while( true )
+    {
+        OGRFeature      *poFeature;
+
+        poFeature = GetNextRawFeature();
+        if( poFeature == NULL )
+            return NULL;
+
+        if( (m_poFilterGeom == NULL
+            || FilterGeometry( poFeature->GetGeomFieldRef(m_iGeomFieldFilter) ) )
+            && (m_poAttrQuery == NULL
+                || m_poAttrQuery->Evaluate( poFeature )) )
+            return poFeature;
+
+        delete poFeature;
+    }
 }
 
 /************************************************************************/
-/*                           TestCapability()                           */
+/*                         GetNextRawFeature()                          */
 /************************************************************************/
 
-int OGRElasticLayer::TestCapability(const char * pszCap) {
-    if (EQUAL(pszCap, OLCFastFeatureCount))
-        return FALSE;
+OGRFeature *OGRElasticLayer::GetNextRawFeature()
+{
+    json_object* poResponse = NULL;
 
-    else if (EQUAL(pszCap, OLCStringsAsUTF8))
-        return TRUE;
+    if( m_bEOF )
+        return NULL;
 
-    else if (EQUAL(pszCap, OLCSequentialWrite))
-        return TRUE;
-    else if (EQUAL(pszCap, OLCCreateField))
-        return TRUE;
+    if( m_iCurFeatureInPage < (int)m_apoCachedFeatures.size() )
+    {
+        OGRFeature* poRet = m_apoCachedFeatures[m_iCurFeatureInPage];
+        m_apoCachedFeatures[m_iCurFeatureInPage] = NULL;
+        m_iCurFeatureInPage ++;
+        return poRet;
+    }
+
+    for(int i=0;i<(int)m_apoCachedFeatures.size();i++)
+        delete m_apoCachedFeatures[i];
+    m_apoCachedFeatures.resize(0);
+    m_iCurFeatureInPage = 0;
+
+    CPLString osRequest, osPostData;
+    if( m_osScrollID.size() == 0 )
+    {
+        if( m_osESSearch.size() )
+        {
+           osRequest = CPLSPrintf("%s/_search?scroll=1m&size=%d",
+                           m_poDS->GetURL(), m_poDS->m_nBatchSize);
+            osPostData = m_osESSearch;
+        }
+        else if( m_poSpatialFilter && m_osJSONFilter.size() == 0 )
+        {
+            CPLString osFilter = CPLSPrintf("{ \"query\": { \"filtered\" : { \"query\" : { \"match_all\" : {} }, \"filter\": %s } } }",
+                                            json_object_to_json_string( m_poSpatialFilter ));
+            osRequest = CPLSPrintf("%s/%s/%s/_search?scroll=1m&size=%d",
+                           m_poDS->GetURL(), m_osIndexName.c_str(),
+                           m_osMappingName.c_str(), m_poDS->m_nBatchSize);
+            osPostData = osFilter;
+        }
+        else
+        {
+            osRequest =
+                CPLSPrintf("%s/%s/%s/_search?scroll=1m&size=%d",
+                           m_poDS->GetURL(), m_osIndexName.c_str(),
+                           m_osMappingName.c_str(), m_poDS->m_nBatchSize);
+            osPostData = m_osJSONFilter;
+        }
+    }
     else
-        return FALSE;
+    {
+        osRequest =
+            CPLSPrintf("%s/_search/scroll?scroll=1m&size=%d&scroll_id=%s",
+                       m_poDS->GetURL(), m_poDS->m_nBatchSize, m_osScrollID.c_str());
+    }
+
+    if( m_bAddPretty )
+        osRequest += "&pretty";
+    poResponse = m_poDS->RunRequest(osRequest, osPostData);
+    if( poResponse == NULL )
+    {
+        m_bEOF = TRUE;
+        return NULL;
+    }
+    json_object* poScrollID = json_object_object_get(poResponse, "_scroll_id");
+    if( poScrollID )
+    {
+        const char* pszScrollID = json_object_get_string(poScrollID);
+        if( pszScrollID )
+            m_osScrollID = pszScrollID;
+    }
+
+    json_object* poHits = json_object_object_get(poResponse, "hits");
+    if( poHits == NULL || json_object_get_type(poHits) != json_type_object )
+    {
+        m_bEOF = TRUE;
+        json_object_put(poResponse);
+        return NULL;
+    }
+    poHits = json_object_object_get(poHits, "hits");
+    if( poHits == NULL || json_object_get_type(poHits) != json_type_array )
+    {
+        m_bEOF = TRUE;
+        json_object_put(poResponse);
+        return NULL;
+    }
+    int nHits = json_object_array_length(poHits);
+    if( nHits == 0 )
+    {
+        m_osScrollID = "";
+        m_bEOF = TRUE;
+        json_object_put(poResponse);
+        return NULL;
+    }
+    for(int i=0;i<nHits;i++)
+    {
+        json_object* poHit = json_object_array_get_idx(poHits, i);
+        if( poHit == NULL || json_object_get_type(poHit) != json_type_object )
+        {
+            continue;
+        }
+        json_object* poSource = json_object_object_get(poHit, "_source");
+        if( poSource == NULL || json_object_get_type(poSource) != json_type_object )
+        {
+            continue;
+        }
+
+        const char* pszId = NULL;
+        json_object* poId = json_object_object_get(poHit, "_id");
+        if( poId != NULL && json_object_get_type(poId) == json_type_string )
+            pszId = json_object_get_string(poId);
+
+        OGRFeature* poFeature = new OGRFeature(m_poFeatureDefn);
+        if( pszId )
+            poFeature->SetField("_id", pszId);
+
+        if( m_osESSearch.size() )
+        {
+            json_object* poIndex = json_object_object_get(poHit, "_index");
+            if( poIndex != NULL && json_object_get_type(poIndex) == json_type_string )
+                poFeature->SetField("_index", json_object_get_string(poIndex));
+
+            json_object* poType = json_object_object_get(poHit, "_type");
+            if( poType != NULL && json_object_get_type(poType) == json_type_string )
+                poFeature->SetField("_type", json_object_get_string(poType));
+        }
+
+        if( m_poDS->m_bJSonField )
+            poFeature->SetField("_json", json_object_to_json_string(poSource));
+
+        BuildFeature(poFeature, poSource, CPLString());
+        if( poFeature->GetFID() < 0 )
+            poFeature->SetFID( ++m_iCurID );
+        m_apoCachedFeatures.push_back(poFeature);
+    }
+
+    json_object_put(poResponse);
+    if( m_apoCachedFeatures.size() )
+    {
+        OGRFeature* poRet = m_apoCachedFeatures[ 0 ];
+        m_apoCachedFeatures[ 0 ] = NULL;
+        m_iCurFeatureInPage ++;
+        return poRet;
+    }
+    return NULL;
 }
 
 /************************************************************************/
-/*                          GetFeatureCount()                           */
+/*                      decode_geohash_bbox()                           */
+/************************************************************************/
+
+/* Derived from routine from https://github.com/davetroy/geohash/blob/master/ext/geohash_native.c */
+/* (c) 2008-2010 David Troy, davetroy at gmail.com, (The MIT License) */
+
+static const char BASE32[] = "0123456789bcdefghjkmnpqrstuvwxyz";
+
+static void decode_geohash_bbox(const char *geohash, double lat[2], double lon[2])
+{
+    int i, j, hashlen;
+    char c, cd, mask, is_even=1;
+    static const char bits[] = {16,8,4,2,1};
+    lat[0] = -90.0; lat[1] = 90.0;
+    lon[0] = -180.0; lon[1] = 180.0;
+    hashlen = static_cast<int>(strlen(geohash));
+    for (i=0; i<hashlen; i++) {
+        c = static_cast<char>(tolower(geohash[i]));
+        cd = static_cast<char>(strchr(BASE32, c)-BASE32);
+        for (j=0; j<5; j++) {
+            mask = bits[j];
+            if (is_even) {
+                lon[!(cd&mask)] = (lon[0] + lon[1])/2;
+            } else {
+                lat[!(cd&mask)] = (lat[0] + lat[1])/2;
+            }
+            is_even = !is_even;
+        }
+    }
+}
+
 /************************************************************************/
+/*                            BuildFeature()                            */
+/************************************************************************/
+
+void OGRElasticLayer::BuildFeature(OGRFeature* poFeature, json_object* poSource,
+                                   CPLString osPath)
+{
+    json_object_iter it;
+    it.key = NULL;
+    it.val = NULL;
+    it.entry = NULL;
+    CPLString osCurPath;
+    json_object_object_foreachC( poSource, it )
+    {
+        if( osPath.size() == 0 &&
+            m_osFID.size() && EQUAL(m_osFID, it.key) )
+        {
+            json_type eJSONType = json_object_get_type(it.val);
+            if( eJSONType == json_type_int )
+            {
+                poFeature->SetFID((GIntBig)json_object_get_int64(it.val));
+                continue;
+            }
+        }
+
+        if( osPath.size() )
+            osCurPath = osPath + "." + it.key;
+        else
+            osCurPath = it.key;
+        std::map<CPLString,int>::iterator oIter = m_aosMapToFieldIndex.find(osCurPath);
+        if( oIter != m_aosMapToFieldIndex.end() )
+        {
+            switch( json_object_get_type(it.val) )
+            {
+                case json_type_boolean:
+                    poFeature->SetField( oIter->second, json_object_get_boolean(it.val));
+                    break;
+                case json_type_int:
+                    poFeature->SetField( oIter->second, (GIntBig)json_object_get_int64(it.val));
+                    break;
+                case json_type_double:
+                    poFeature->SetField( oIter->second, json_object_get_double(it.val));
+                    break;
+                case json_type_array:
+                {
+                    if( m_poFeatureDefn->GetFieldDefn(oIter->second)->GetType() == OFTIntegerList )
+                    {
+                        std::vector<int> anValues;
+                        int nLength = json_object_array_length(it.val);
+                        for(int i=0;i<nLength;i++)
+                        {
+                            anValues.push_back( json_object_get_int( json_object_array_get_idx( it.val, i ) ) );
+                        }
+                        if( nLength )
+                            poFeature->SetField( oIter->second, nLength, &anValues[0] );
+                    }
+                    else if( m_poFeatureDefn->GetFieldDefn(oIter->second)->GetType() == OFTInteger64List )
+                    {
+                        std::vector<GIntBig> anValues;
+                        int nLength = json_object_array_length(it.val);
+                        for(int i=0;i<nLength;i++)
+                        {
+                            anValues.push_back( json_object_get_int64( json_object_array_get_idx( it.val, i ) ) );
+                        }
+                        if( nLength )
+                            poFeature->SetField( oIter->second, nLength, &anValues[0] );
+                    }
+                    else if( m_poFeatureDefn->GetFieldDefn(oIter->second)->GetType() == OFTRealList )
+                    {
+                        std::vector<double> adfValues;
+                        int nLength = json_object_array_length(it.val);
+                        for(int i=0;i<nLength;i++)
+                        {
+                            adfValues.push_back( json_object_get_double( json_object_array_get_idx( it.val, i ) ) );
+                        }
+                        if( nLength )
+                            poFeature->SetField( oIter->second, nLength, &adfValues[0] );
+                    }
+                    else if( m_poFeatureDefn->GetFieldDefn(oIter->second)->GetType() == OFTStringList )
+                    {
+                        std::vector<char*> apszValues;
+                        int nLength = json_object_array_length(it.val);
+                        for(int i=0;i<nLength;i++)
+                        {
+                            apszValues.push_back( CPLStrdup(json_object_get_string( json_object_array_get_idx( it.val, i ) )) );
+                        }
+                        apszValues.push_back( NULL);
+                        poFeature->SetField( oIter->second, &apszValues[0] );
+                        for(int i=0;i<nLength;i++)
+                        {
+                            CPLFree(apszValues[i]);
+                        }
+                    }
+                    break;
+                }
+                default:
+                {
+                    if( m_poFeatureDefn->GetFieldDefn(oIter->second)->GetType() == OFTBinary )
+                    {
+                        GByte* pabyBase64 = (GByte*) CPLStrdup( json_object_get_string(it.val) );
+                        int nBytes = CPLBase64DecodeInPlace( pabyBase64 );
+                        poFeature->SetField( oIter->second, nBytes, pabyBase64 );
+                        CPLFree(pabyBase64);
+                    }
+                    else
+                    {
+                        poFeature->SetField( oIter->second, json_object_get_string(it.val));
+                    }
+                    break;
+                }
+            }
+        }
+        else if( ( oIter = m_aosMapToGeomFieldIndex.find(osCurPath) ) != m_aosMapToGeomFieldIndex.end() )
+        {
+            OGRGeometry* poGeom = NULL;
+            if( m_abIsGeoPoint[oIter->second] )
+            {
+                json_type eJSONType = json_object_get_type(it.val);
+                if( eJSONType == json_type_array &&
+                    json_object_array_length(it.val) == 2 )
+                {
+                    json_object* poX = json_object_array_get_idx(it.val, 0);
+                    json_object* poY = json_object_array_get_idx(it.val, 1);
+                    if( poX != NULL && poY != NULL )
+                    {
+                        poGeom = new OGRPoint( json_object_get_double(poX),
+                                               json_object_get_double(poY) );
+                    }
+                }
+                else if( eJSONType == json_type_object )
+                {
+                    json_object* poX = json_object_object_get(it.val, "lon");
+                    json_object* poY = json_object_object_get(it.val, "lat");
+                    if( poX != NULL && poY != NULL )
+                    {
+                        poGeom = new OGRPoint( json_object_get_double(poX),
+                                               json_object_get_double(poY) );
+                    }
+                }
+                else if( eJSONType == json_type_string )
+                {
+                    const char* pszLatLon = json_object_get_string(it.val);
+                    char** papszTokens = CSLTokenizeString2(pszLatLon, ",", 0);
+                    if( CSLCount(papszTokens) == 2 )
+                    {
+                        poGeom = new OGRPoint( CPLAtof(papszTokens[1]),
+                                               CPLAtof(papszTokens[0]) );
+                    }
+                    else
+                    {
+                        double lat[2], lon[2];
+                        decode_geohash_bbox(pszLatLon, lat, lon);
+                        poGeom = new OGRPoint( (lon[0] + lon[1]) / 2,
+                                               (lat[0] + lat[1]) / 2 );
+                    }
+
+                    CSLDestroy(papszTokens);
+                }
+            }
+            else if( json_object_get_type(it.val) == json_type_object )
+            {
+                json_object* poType = json_object_object_get(it.val, "type");
+                json_object* poRadius = json_object_object_get(it.val, "radius");
+                json_object* poCoordinates = json_object_object_get(it.val, "coordinates");
+                if( poType && poRadius && poCoordinates &&
+                    json_object_get_type(poType) == json_type_string &&
+                    EQUAL( json_object_get_string(poType), "circle" ) &&
+                    (json_object_get_type(poRadius) == json_type_string ||
+                     json_object_get_type(poRadius) == json_type_double ||
+                     json_object_get_type(poRadius) == json_type_int ) &&
+                    json_object_get_type(poCoordinates) == json_type_array &&
+                    json_object_array_length(poCoordinates) == 2 )
+                {
+                    const char* pszRadius = json_object_get_string(poRadius);
+                    double dfX = json_object_get_double(json_object_array_get_idx(poCoordinates, 0));
+                    double dfY = json_object_get_double(json_object_array_get_idx(poCoordinates, 1));
+                    int nRadiusLength = (int)strlen(pszRadius);
+                    double dfRadius = CPLAtof(pszRadius);
+                    double dfUnit = 0.0;
+                    if( nRadiusLength >= 1 && pszRadius[nRadiusLength-1] == 'm' )
+                    {
+                        if( nRadiusLength >= 2 && pszRadius[nRadiusLength-2] == 'k' )
+                            dfUnit = 1000;
+                        else if( nRadiusLength >= 2 &&
+                                 pszRadius[nRadiusLength-2] >= '0' &&
+                                 pszRadius[nRadiusLength-2] <= '9' )
+                            dfUnit = 1;
+                    }
+                    else if ( nRadiusLength >= 1 &&
+                                 pszRadius[nRadiusLength-1] >= '0' &&
+                                 pszRadius[nRadiusLength-1] <= '9' )
+                    {
+                        dfUnit = 1;
+                    }
+
+                    if( dfRadius == 0 )
+                        CPLError(CE_Warning, CPLE_AppDefined, "Unknown unit in %s", pszRadius);
+                    else
+                    {
+                        dfRadius *= dfUnit;
+                        OGRLinearRing* poRing = new OGRLinearRing();
+                        for(double dfStep = 0; dfStep <= 360; dfStep += 4 )
+                        {
+                            double dfLat, dfLon;
+                            OGRXPlane_ExtendPosition( dfY, dfX, dfRadius, dfStep, &dfLat, &dfLon);
+                            poRing->addPoint(dfLon, dfLat);
+                        }
+                        OGRPolygon* poPoly = new OGRPolygon();
+                        poPoly->addRingDirectly(poRing);
+                        poGeom = poPoly;
+                    }
+                }
+                else if( poType && poCoordinates &&
+                    json_object_get_type(poType) == json_type_string &&
+                    EQUAL( json_object_get_string(poType), "envelope" ) &&
+                    json_object_get_type(poCoordinates) == json_type_array &&
+                    json_object_array_length(poCoordinates) == 2 )
+                {
+                    json_object* poCorner1 = json_object_array_get_idx(poCoordinates, 0);
+                    json_object* poCorner2 = json_object_array_get_idx(poCoordinates, 1);
+                    if( poCorner1 && poCorner2 &&
+                        json_object_get_type(poCorner1) == json_type_array &&
+                        json_object_array_length(poCorner1) == 2 &&
+                        json_object_get_type(poCorner2) == json_type_array &&
+                        json_object_array_length(poCorner2) == 2 )
+                    {
+                        double dfX1 = json_object_get_double(json_object_array_get_idx(poCorner1, 0));
+                        double dfY1 = json_object_get_double(json_object_array_get_idx(poCorner1, 1));
+                        double dfX2 = json_object_get_double(json_object_array_get_idx(poCorner2, 0));
+                        double dfY2 = json_object_get_double(json_object_array_get_idx(poCorner2, 1));
+                        OGRLinearRing* poRing = new OGRLinearRing();
+                        poRing->addPoint(dfX1, dfY1);
+                        poRing->addPoint(dfX2, dfY1);
+                        poRing->addPoint(dfX2, dfY2);
+                        poRing->addPoint(dfX1, dfY2);
+                        poRing->addPoint(dfX1, dfY1);
+                        OGRPolygon* poPoly = new OGRPolygon();
+                        poPoly->addRingDirectly(poRing);
+                        poGeom = poPoly;
+                    }
+                }
+                else
+                {
+                    poGeom = OGRGeoJSONReadGeometry( it.val );
+                }
+            }
+
+            if( poGeom != NULL )
+            {
+                poGeom->assignSpatialReference( m_poFeatureDefn->GetGeomFieldDefn(oIter->second)->GetSpatialRef() );
+                poFeature->SetGeomFieldDirectly( oIter->second, poGeom );
+            }
+        }
+        else if( json_object_get_type(it.val) == json_type_object &&
+                 (m_poDS->m_bFlattenNestedAttributes ||
+                  (osPath.size() == 0 && m_osMappingName == "FeatureCollection" && strcmp(it.key, "properties") == 0)) )
+        {
+            BuildFeature(poFeature, it.val, osCurPath);
+        }
+        else if( json_object_get_type(it.val) == json_type_object &&
+                 !m_poDS->m_bFlattenNestedAttributes )
+        {
+            if( ( oIter = m_aosMapToGeomFieldIndex.find(osCurPath + ".coordinates") ) != m_aosMapToGeomFieldIndex.end() )
+            {
+                BuildFeature(poFeature, it.val, osCurPath);
+            }
+        }
+    }
+}
+
+/************************************************************************/
+/*                            AppendGroup()                             */
+/************************************************************************/
+
+static
+json_object *AppendGroup(json_object *parent, const CPLString &name) {
+    json_object *obj = json_object_new_object();
+    json_object *properties = json_object_new_object();
+    json_object_object_add(parent, name, obj);
+    json_object_object_add(obj, "properties", properties);
+    return properties;
+}
+
+/************************************************************************/
+/*                           AddPropertyMap()                           */
+/************************************************************************/
+
+static json_object* AddPropertyMap(const CPLString &type) {
+    json_object *obj = json_object_new_object();
+    json_object_object_add(obj, "type", json_object_new_string(type.c_str()));
+    return obj;
+}
+
+/************************************************************************/
+/*                      GetContainerForMapping()                        */
+/************************************************************************/
+
+static json_object* GetContainerForMapping( json_object* poContainer,
+                                            const std::vector<CPLString>& aosPath,
+                                            std::map< std::vector<CPLString>, json_object* >& oMap )
+{
+    std::vector<CPLString> aosSubPath;
+    for(int j=0;j<(int)aosPath.size()-1;j++)
+    {
+        aosSubPath.push_back(aosPath[j]);
+        std::map< std::vector<CPLString>, json_object* >::iterator oIter = oMap.find(aosSubPath);
+        if( oIter == oMap.end() )
+        {
+            json_object* poNewContainer = json_object_new_object();
+            json_object* poProperties = json_object_new_object();
+            json_object_object_add(poContainer, aosPath[j], poNewContainer);
+            json_object_object_add(poNewContainer, "properties", poProperties);
+            oMap[aosSubPath] = poProperties;
+            poContainer = poProperties;
+        }
+        else
+        {
+            poContainer = oIter->second;
+        }
+    }
+    return poContainer;
+}
+
+
+/************************************************************************/
+/*                             BuildMap()                               */
+/************************************************************************/
+
+CPLString OGRElasticLayer::BuildMap() {
+    json_object *map = json_object_new_object();
+
+    std::map< std::vector<CPLString>, json_object* > oMap;
+
+    json_object *poMapping = json_object_new_object();
+    json_object *poMappingProperties = json_object_new_object();
+    json_object_object_add(map, m_osMappingName, poMapping);
+    json_object_object_add(poMapping, "properties", poMappingProperties);
+
+    if( m_osMappingName == "FeatureCollection" )
+    {
+        json_object_object_add(poMappingProperties, "type", AddPropertyMap("string"));
+
+        std::vector<CPLString> aosPath;
+        aosPath.push_back("properties");
+        aosPath.push_back("dummy");
+        GetContainerForMapping(poMappingProperties, aosPath, oMap);
+    }
+
+    /* skip _id field */
+    for(int i=1;i<m_poFeatureDefn->GetFieldCount();i++)
+    {
+        OGRFieldDefn* poFieldDefn = m_poFeatureDefn->GetFieldDefn(i);
+
+        json_object* poContainer = GetContainerForMapping(poMappingProperties,
+                                                          m_aaosFieldPaths[i],
+                                                          oMap);
+        const char* pszLastComponent = m_aaosFieldPaths[i][(int)m_aaosFieldPaths[i].size()-1];
+
+        const char* pszType = "string";
+        const char* pszFormat = NULL;
+
+        switch (poFieldDefn->GetType())
+        {
+            case OFTInteger:
+            case OFTIntegerList:
+            {
+                if( poFieldDefn->GetSubType() == OFSTBoolean )
+                    pszType = "boolean";
+                else
+                    pszType = "integer";
+                break;
+            }
+            case OFTInteger64:
+            case OFTInteger64List:
+                pszType = "long";
+                break;
+            case OFTReal:
+            case OFTRealList:
+                pszType = "double";
+                break;
+            case OFTDateTime:
+            case OFTDate:
+                pszType = "date";
+                pszFormat = "yyyy/MM/dd HH:mm:ss.SSSZZ||yyyy/MM/dd HH:mm:ss.SSS||yyyy/MM/dd";
+                break;
+            case OFTTime:
+                pszType = "date";
+                pszFormat = "HH:mm:ss.SSS";
+                break;
+            case OFTBinary:
+                pszType = "binary";
+                break;
+            default:
+                break;
+        }
+
+        json_object* poPropertyMap = json_object_new_object();
+        json_object_object_add(poPropertyMap, "type", json_object_new_string(pszType));
+        if( pszFormat )
+            json_object_object_add(poPropertyMap, "format", json_object_new_string(pszFormat));
+        if( m_bStoreFields || CSLFindString(m_papszStoredFields, poFieldDefn->GetNameRef()) >= 0 )
+            json_object_object_add(poPropertyMap, "store", json_object_new_string("yes"));
+        if( CSLFindString(m_papszNotAnalyzedFields, poFieldDefn->GetNameRef()) >= 0 )
+            json_object_object_add(poPropertyMap, "index", json_object_new_string("not_analyzed"));
+        else if( CSLFindString(m_papszNotIndexedFields, poFieldDefn->GetNameRef()) >= 0 )
+            json_object_object_add(poPropertyMap, "index", json_object_new_string("no"));
+
+        json_object_object_add(poContainer, pszLastComponent, poPropertyMap);
+
+    }
+
+    for(int i=0;i<m_poFeatureDefn->GetGeomFieldCount();i++)
+    {
+        std::vector<CPLString> aosPath = m_aaosGeomFieldPaths[i];
+        int bAddGeoJSONType = FALSE;
+        if( m_abIsGeoPoint[i] &&
+            aosPath.size() >= 2 &&
+            aosPath[(int)aosPath.size()-1] == "coordinates" )
+        {
+            bAddGeoJSONType = TRUE;
+            aosPath.resize( (int)aosPath.size() - 1 );
+        }
+
+        json_object* poContainer = GetContainerForMapping(poMappingProperties,
+                                                        aosPath,
+                                                        oMap);
+        const char* pszLastComponent = aosPath[(int)aosPath.size()-1];
+
+        if( m_abIsGeoPoint[i] )
+        {
+            json_object* geo_point = AddPropertyMap("geo_point");
+            if( bAddGeoJSONType )
+            {
+                json_object *geometry = AppendGroup(poContainer, pszLastComponent);
+                json_object_object_add(geometry, "type", AddPropertyMap("string"));
+                json_object_object_add(geometry, "coordinates", geo_point);
+            }
+            else
+            {
+                json_object_object_add(poContainer, pszLastComponent, geo_point);
+            }
+            if( m_osPrecision.size() )
+            {
+                json_object* field_data = json_object_new_object();
+                json_object_object_add(geo_point, "fielddata", field_data);
+                json_object_object_add(field_data, "format", json_object_new_string("compressed"));
+                json_object_object_add(field_data, "precision", json_object_new_string(m_osPrecision.c_str()));
+            }
+        }
+        else
+        {
+            json_object *geometry = json_object_new_object();
+            json_object_object_add(poContainer,
+                                pszLastComponent,
+                                geometry);
+            json_object_object_add(geometry, "type", json_object_new_string("geo_shape"));
+            if( m_osPrecision.size() )
+                json_object_object_add(geometry, "precision", json_object_new_string(m_osPrecision.c_str()));
+        }
+    }
+
+    json_object* poMeta = NULL;
+    json_object* poGeomFields = NULL;
+    json_object* poFields = NULL;
+    if( m_osFID.size() )
+    {
+        poMeta = json_object_new_object();
+        json_object_object_add(poMeta, "fid",
+                               json_object_new_string(m_osFID.c_str()));
+    }
+    for( int i=0; i < m_poFeatureDefn->GetGeomFieldCount(); i++ )
+    {
+        OGRGeomFieldDefn* poGeomFieldDefn = m_poFeatureDefn->GetGeomFieldDefn(i);
+        if( !m_abIsGeoPoint[i] &&
+            poGeomFieldDefn->GetType() != wkbUnknown )
+        {
+            if( poMeta == NULL )
+                poMeta = json_object_new_object();
+            if( poGeomFields == NULL )
+            {
+                poGeomFields = json_object_new_object();
+                json_object_object_add(poMeta, "geomfields", poGeomFields);
+            }
+            json_object_object_add(poGeomFields,
+                                   poGeomFieldDefn->GetNameRef(),
+                                   json_object_new_string(OGRToOGCGeomType(poGeomFieldDefn->GetType())));
+        }
+    }
+    for( int i=0; i < m_poFeatureDefn->GetFieldCount(); i++ )
+    {
+        OGRFieldDefn* poFieldDefn = m_poFeatureDefn->GetFieldDefn(i);
+        OGRFieldType eType = poFieldDefn->GetType();
+        if( eType == OFTIntegerList || eType == OFTInteger64List ||
+            eType == OFTRealList || eType == OFTStringList )
+        {
+            if( poMeta == NULL )
+                poMeta = json_object_new_object();
+            if( poFields == NULL )
+            {
+                poFields = json_object_new_object();
+                json_object_object_add(poMeta, "fields", poFields);
+            }
+            json_object_object_add(poFields,
+                                   poFieldDefn->GetNameRef(),
+                                   json_object_new_string(OGR_GetFieldTypeName(eType)));
+        }
+    }
+    if( poMeta )
+        json_object_object_add(poMapping, "_meta", poMeta );
+
+    CPLString jsonMap(json_object_to_json_string(map));
+    json_object_put(map);
+
+    // Got personally caught by that...
+    if( CSLCount(m_papszStoredFields) == 1 &&
+        (EQUAL(m_papszStoredFields[0], "YES") || EQUAL(m_papszStoredFields[0], "TRUE")) &&
+        m_poFeatureDefn->GetFieldIndex(m_papszStoredFields[0]) < 0 )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "STORED_FIELDS=%s was specified. Perhaps you meant STORE_FIELDS=%s instead?",
+                 m_papszStoredFields[0], m_papszStoredFields[0]);
+    }
+
+    return jsonMap;
+}
+
+/************************************************************************/
+/*                       BuildGeoJSONGeometry()                         */
+/************************************************************************/
+
+static void BuildGeoJSONGeometry(json_object* geometry, OGRGeometry* poGeom)
+{
+    const int nPrecision = 10;
+    double dfEps = pow(10.0, -(double)nPrecision);
+    const char* pszGeomType = "";
+    switch( wkbFlatten(poGeom->getGeometryType()) )
+    {
+        case wkbPoint: pszGeomType = "point"; break;
+        case wkbLineString: pszGeomType = "linestring"; break;
+        case wkbPolygon: pszGeomType = "polygon"; break;
+        case wkbMultiPoint: pszGeomType = "multipoint"; break;
+        case wkbMultiLineString: pszGeomType = "multilinestring"; break;
+        case wkbMultiPolygon: pszGeomType = "multipolygon"; break;
+        case wkbGeometryCollection: pszGeomType = "geometrycollection"; break;
+        default: break;
+    }
+    json_object_object_add(geometry, "type", json_object_new_string(pszGeomType));
+
+    switch( wkbFlatten(poGeom->getGeometryType()) )
+    {
+        case wkbPoint:
+        {
+            OGRPoint* poPoint = (OGRPoint*)poGeom;
+            json_object *coordinates = json_object_new_array();
+            json_object_object_add(geometry, "coordinates", coordinates);
+            json_object_array_add(coordinates, json_object_new_double_with_precision(poPoint->getX(), nPrecision));
+            json_object_array_add(coordinates, json_object_new_double_with_precision(poPoint->getY(), nPrecision));
+            break;
+        }
+
+        case wkbLineString:
+        {
+            OGRLineString* poLS = (OGRLineString*)poGeom;
+            json_object *coordinates = json_object_new_array();
+            json_object_object_add(geometry, "coordinates", coordinates);
+            for(int i=0;i<poLS->getNumPoints();i++)
+            {
+                json_object *point = json_object_new_array();
+                json_object_array_add(coordinates, point);
+                json_object_array_add(point, json_object_new_double_with_precision(poLS->getX(i), nPrecision));
+                json_object_array_add(point, json_object_new_double_with_precision(poLS->getY(i), nPrecision));
+            }
+            break;
+        }
+
+        case wkbPolygon:
+        {
+            OGRPolygon* poPoly = (OGRPolygon*)poGeom;
+            json_object *coordinates = json_object_new_array();
+            json_object_object_add(geometry, "coordinates", coordinates);
+            for(int i=0;i<1+poPoly->getNumInteriorRings();i++)
+            {
+                json_object *ring = json_object_new_array();
+                json_object_array_add(coordinates, ring);
+                OGRLineString* poLS = (i==0)?poPoly->getExteriorRing():poPoly->getInteriorRing(i-1);
+                for(int j=0;j<poLS->getNumPoints();j++)
+                {
+                    if( j > 0 && fabs(poLS->getX(j) - poLS->getX(j-1)) < dfEps &&
+                        fabs(poLS->getY(j) - poLS->getY(j-1)) < dfEps )
+                        continue;
+                    json_object *point = json_object_new_array();
+                    json_object_array_add(ring, point);
+                    json_object_array_add(point, json_object_new_double_with_precision(poLS->getX(j), nPrecision));
+                    json_object_array_add(point, json_object_new_double_with_precision(poLS->getY(j), nPrecision));
+                }
+            }
+            break;
+        }
+
+        case wkbMultiPoint:
+        {
+            OGRMultiPoint* poMP = (OGRMultiPoint*)poGeom;
+            json_object *coordinates = json_object_new_array();
+            json_object_object_add(geometry, "coordinates", coordinates);
+            for(int i=0;i<poMP->getNumGeometries();i++)
+            {
+                json_object *point = json_object_new_array();
+                json_object_array_add(coordinates, point);
+                OGRPoint* poPoint = (OGRPoint*) poMP->getGeometryRef(i);
+                json_object_array_add(point, json_object_new_double_with_precision(poPoint->getX(), nPrecision));
+                json_object_array_add(point, json_object_new_double_with_precision(poPoint->getY(), nPrecision));
+            }
+            break;
+        }
+
+        case wkbMultiLineString:
+        {
+            OGRMultiLineString* poMLS = (OGRMultiLineString*)poGeom;
+            json_object *coordinates = json_object_new_array();
+            json_object_object_add(geometry, "coordinates", coordinates);
+            for(int i=0;i<poMLS->getNumGeometries();i++)
+            {
+                json_object *ls = json_object_new_array();
+                json_object_array_add(coordinates, ls);
+                OGRLineString* poLS = (OGRLineString*) poMLS->getGeometryRef(i);
+                for(int j=0;j<poLS->getNumPoints();j++)
+                {
+                    json_object *point = json_object_new_array();
+                    json_object_array_add(ls, point);
+                    json_object_array_add(point, json_object_new_double_with_precision(poLS->getX(j), nPrecision));
+                    json_object_array_add(point, json_object_new_double_with_precision(poLS->getY(j), nPrecision));
+                }
+            }
+            break;
+        }
+
+        case wkbMultiPolygon:
+        {
+            OGRMultiPolygon* poMP = (OGRMultiPolygon*)poGeom;
+            json_object *coordinates = json_object_new_array();
+            json_object_object_add(geometry, "coordinates", coordinates);
+            for(int i=0;i<poMP->getNumGeometries();i++)
+            {
+                json_object *poly = json_object_new_array();
+                json_object_array_add(coordinates, poly);
+                OGRPolygon* poPoly = (OGRPolygon*) poMP->getGeometryRef(i);
+                for(int j=0;j<1+poPoly->getNumInteriorRings();j++)
+                {
+                    json_object *ring = json_object_new_array();
+                    json_object_array_add(poly, ring);
+                    OGRLineString* poLS = (j==0)?poPoly->getExteriorRing():poPoly->getInteriorRing(j-1);
+                    for(int k=0;k<poLS->getNumPoints();k++)
+                    {
+                        if( k > 0 && fabs(poLS->getX(k)- poLS->getX(k-1)) < dfEps &&
+                            fabs(poLS->getY(k) - poLS->getY(k-1)) < dfEps )
+                            continue;
+                        json_object *point = json_object_new_array();
+                        json_object_array_add(ring, point);
+                        json_object_array_add(point, json_object_new_double_with_precision(poLS->getX(k), nPrecision));
+                        json_object_array_add(point, json_object_new_double_with_precision(poLS->getY(k), nPrecision));
+                    }
+                }
+            }
+            break;
+        }
+
+        case wkbGeometryCollection:
+        {
+            OGRGeometryCollection* poGC = (OGRGeometryCollection*)poGeom;
+            json_object *geometries = json_object_new_array();
+            json_object_object_add(geometry, "geometries", geometries);
+            for(int i=0;i<poGC->getNumGeometries();i++)
+            {
+                json_object *subgeom = json_object_new_object();
+                json_object_array_add(geometries, subgeom);
+                BuildGeoJSONGeometry(subgeom, poGC->getGeometryRef(i));
+            }
+            break;
+        }
+
+        default:
+            break;
+    }
+
+}
+
+/************************************************************************/
+/*                       WriteMapIfNecessary()                          */
+/************************************************************************/
+
+OGRErr OGRElasticLayer::WriteMapIfNecessary()
+{
+    if( m_bManualMapping )
+        return OGRERR_NONE;
+
+    // Check to see if the user has elected to only write out the mapping file
+    // This method will only write out one layer from the vector file in cases where there are multiple layers
+    if (m_osWriteMapFilename.size()) {
+        if (m_bSerializeMapping) {
+            m_bSerializeMapping = FALSE;
+            CPLString map = BuildMap();
+
+            // Write the map to a file
+            VSILFILE *f = VSIFOpenL(m_osWriteMapFilename, "wb");
+            if (f) {
+                VSIFWriteL(map.c_str(), 1, map.length(), f);
+                VSIFCloseL(f);
+            }
+        }
+        return OGRERR_NONE;
+    }
+
+    // Check to see if we have any fields to upload to this index
+    if (m_osWriteMapFilename.size() == 0 && m_bSerializeMapping ) {
+        m_bSerializeMapping = FALSE;
+        if( !m_poDS->UploadFile(CPLSPrintf("%s/%s/%s/_mapping", m_poDS->GetURL(), m_osIndexName.c_str(), m_osMappingName.c_str()), BuildMap()) )
+        {
+            return OGRERR_FAILURE;
+        }
+    }
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                      GetContainerForFeature()                        */
+/************************************************************************/
+
+static json_object* GetContainerForFeature( json_object* poContainer,
+                                            const std::vector<CPLString>& aosPath,
+                                            std::map< std::vector<CPLString>, json_object* >& oMap )
+{
+    std::vector<CPLString> aosSubPath;
+    for(int j=0;j<(int)aosPath.size()-1;j++)
+    {
+        aosSubPath.push_back(aosPath[j]);
+         std::map< std::vector<CPLString>, json_object* >::iterator oIter = oMap.find(aosSubPath);
+         if( oIter == oMap.end() )
+         {
+             json_object* poNewContainer = json_object_new_object();
+             json_object_object_add(poContainer, aosPath[j], poNewContainer);
+             oMap[aosSubPath] = poNewContainer;
+             poContainer = poNewContainer;
+         }
+         else
+         {
+             poContainer = oIter->second;
+         }
+    }
+    return poContainer;
+}
+
+
+/************************************************************************/
+/*                        BuildJSonFromFeature()                        */
+/************************************************************************/
+
+CPLString OGRElasticLayer::BuildJSonFromFeature(OGRFeature *poFeature)
+{
+
+    CPLString fields;
+    int nJSonFieldIndex = m_poFeatureDefn->GetFieldIndex("_json");
+    if( nJSonFieldIndex >= 0 && poFeature->IsFieldSet(nJSonFieldIndex) )
+    {
+        fields = poFeature->GetFieldAsString(nJSonFieldIndex);
+    }
+    else
+    {
+        json_object *fieldObject = json_object_new_object();
+
+        if( poFeature->GetFID() >= 0 && m_osFID.size() )
+        {
+            json_object_object_add(fieldObject,
+                                   m_osFID.c_str(),
+                                   json_object_new_int64(poFeature->GetFID()) );
+        }
+
+        std::map< std::vector<CPLString>, json_object* > oMap;
+
+        for(int i=0;i<poFeature->GetGeomFieldCount();i++)
+        {
+            OGRGeometry* poGeom = poFeature->GetGeomFieldRef(i);
+            if( poGeom != NULL && !poGeom->IsEmpty() )
+            {
+                OGREnvelope env;
+                poGeom->getEnvelope(&env);
+
+                if( m_apoCT[i] != NULL )
+                    poGeom->transform( m_apoCT[i] );
+                else if( env.MinX < -180 || env.MinY < -90 ||
+                         env.MaxX > 180 || env.MaxY > 90 )
+                {
+                    static int bHasWarned = FALSE;
+                    if( !bHasWarned )
+                    {
+                        bHasWarned = TRUE;
+                        CPLError(CE_Warning, CPLE_AppDefined,
+                                 "At least one geometry has a bounding box outside "
+                                 "of [-180,180] longitude range and/or [-90,90] latitude range. Undefined behaviour");
+                    }
+                }
+
+                std::vector<CPLString> aosPath = m_aaosGeomFieldPaths[i];
+                int bAddGeoJSONType = FALSE;
+                if( m_abIsGeoPoint[i] &&
+                    aosPath.size() >= 2 &&
+                    aosPath[(int)aosPath.size()-1] == "coordinates" )
+                {
+                    bAddGeoJSONType = TRUE;
+                    aosPath.resize( (int)aosPath.size() - 1 );
+                }
+
+                json_object* poContainer = GetContainerForFeature(fieldObject, aosPath, oMap);
+                const char* pszLastComponent = aosPath[(int)aosPath.size()-1];
+
+                if( m_abIsGeoPoint[i] )
+                {
+                    json_object *coordinates = json_object_new_array();
+                    const int nPrecision = 10;
+                    json_object_array_add(coordinates, json_object_new_double_with_precision((env.MaxX + env.MinX)*0.5, nPrecision));
+                    json_object_array_add(coordinates, json_object_new_double_with_precision((env.MaxY + env.MinY)*0.5, nPrecision));
+
+                    if( bAddGeoJSONType )
+                    {
+                        json_object *geometry = json_object_new_object();
+                        json_object_object_add(poContainer, pszLastComponent, geometry);
+                        json_object_object_add(geometry, "type", json_object_new_string("POINT"));
+                        json_object_object_add(geometry, "coordinates", coordinates);
+                    }
+                    else
+                    {
+                        json_object_object_add(poContainer, pszLastComponent, coordinates);
+                    }
+                }
+                else
+                {
+                    json_object *geometry = json_object_new_object();
+                    json_object_object_add(poContainer, pszLastComponent, geometry);
+                    BuildGeoJSONGeometry(geometry, poGeom);
+                }
+            }
+        }
+
+        if( m_osMappingName == "FeatureCollection" )
+        {
+            if( poFeature->GetGeomFieldCount() == 1 &&
+                poFeature->GetGeomFieldRef(0) )
+            {
+                json_object_object_add(fieldObject, "type", json_object_new_string("Feature"));
+            }
+
+            std::vector<CPLString> aosPath;
+            aosPath.push_back("properties");
+            aosPath.push_back("dummy");
+            GetContainerForFeature(fieldObject, aosPath, oMap);
+        }
+
+        // For every field (except _id)
+        int fieldCount = m_poFeatureDefn->GetFieldCount();
+        for (int i = 1; i < fieldCount; i++)
+        {
+            if(!poFeature->IsFieldSet( i ) ) {
+                    continue;
+            }
+
+            json_object* poContainer = GetContainerForFeature(fieldObject, m_aaosFieldPaths[i], oMap);
+            const char* pszLastComponent = m_aaosFieldPaths[i][(int)m_aaosFieldPaths[i].size()-1];
+
+            switch (m_poFeatureDefn->GetFieldDefn(i)->GetType()) {
+                case OFTInteger:
+                    if( m_poFeatureDefn->GetFieldDefn(i)->GetSubType() == OFSTBoolean )
+                        json_object_object_add(poContainer,
+                            pszLastComponent,
+                            json_object_new_boolean(poFeature->GetFieldAsInteger(i)));
+                    else
+                        json_object_object_add(poContainer,
+                            pszLastComponent,
+                            json_object_new_int(poFeature->GetFieldAsInteger(i)));
+                    break;
+                case OFTInteger64:
+                    json_object_object_add(poContainer,
+                            pszLastComponent,
+                            json_object_new_int64(poFeature->GetFieldAsInteger64(i)));
+                    break;
+                case OFTReal:
+                    json_object_object_add(poContainer,
+                            pszLastComponent,
+                            json_object_new_double_with_significant_figures(poFeature->GetFieldAsDouble(i), -1));
+                    break;
+                case OFTIntegerList:
+                {
+                    int nCount;
+                    const int* panValues = poFeature->GetFieldAsIntegerList(i, &nCount);
+                    json_object* poArray = json_object_new_array();
+                    for(int j=0;j<nCount;j++)
+                        json_object_array_add(poArray, json_object_new_int(panValues[j]));
+                    json_object_object_add(poContainer,
+                            pszLastComponent, poArray);
+                    break;
+                }
+                case OFTInteger64List:
+                {
+                    int nCount;
+                    const GIntBig* panValues = poFeature->GetFieldAsInteger64List(i, &nCount);
+                    json_object* poArray = json_object_new_array();
+                    for(int j=0;j<nCount;j++)
+                        json_object_array_add(poArray, json_object_new_int64(panValues[j]));
+                    json_object_object_add(poContainer,
+                            pszLastComponent, poArray);
+                    break;
+                }
+                case OFTRealList:
+                {
+                    int nCount;
+                    const double* padfValues = poFeature->GetFieldAsDoubleList(i, &nCount);
+                    json_object* poArray = json_object_new_array();
+                    for(int j=0;j<nCount;j++)
+                        json_object_array_add(poArray, json_object_new_double_with_significant_figures(padfValues[j], -1));
+                    json_object_object_add(poContainer,
+                            pszLastComponent, poArray);
+                    break;
+                }
+                case OFTStringList:
+                {
+                    char** papszValues = poFeature->GetFieldAsStringList(i);
+                    json_object* poArray = json_object_new_array();
+                    for(int j=0;papszValues[j]!= NULL;j++)
+                        json_object_array_add(poArray, json_object_new_string(papszValues[j]));
+                    json_object_object_add(poContainer,
+                            pszLastComponent, poArray);
+                    break;
+                }
+                case OFTBinary:
+                {
+                    int nCount;
+                    GByte* pabyVal = poFeature->GetFieldAsBinary(i, &nCount);
+                    char* pszVal = CPLBase64Encode(nCount, pabyVal);
+                    json_object_object_add(poContainer,
+                            pszLastComponent,
+                            json_object_new_string(pszVal));
+                    CPLFree(pszVal);
+                    break;
+                }
+                case OFTDateTime:
+                {
+                    int nYear, nMonth, nDay, nHour, nMin, nTZ;
+                    float fSec;
+                    poFeature->GetFieldAsDateTime(i, &nYear, &nMonth, &nDay,
+                                                  &nHour, &nMin, &fSec, &nTZ);
+                    if( nTZ == 0 )
+                    {
+                        json_object_object_add(poContainer,
+                                pszLastComponent,
+                                json_object_new_string(
+                                    CPLSPrintf("%04d/%02d/%02d %02d:%02d:%06.3f",
+                                            nYear, nMonth, nDay, nHour, nMin, fSec)));
+                    }
+                    else
+                    {
+                        int TZOffset = ABS(nTZ - 100) * 15;
+                        int TZHour = TZOffset / 60;
+                        int TZMinute = TZOffset - TZHour * 60;
+                        json_object_object_add(poContainer,
+                                pszLastComponent,
+                                json_object_new_string(
+                                    CPLSPrintf("%04d/%02d/%02d %02d:%02d:%06.3f%c%02d:%02d",
+                                            nYear, nMonth, nDay, nHour, nMin, fSec,
+                                            (nTZ >= 100) ? '+' : '-', TZHour, TZMinute)));
+                    }
+                    break;
+                }
+                default:
+                {
+                    const char* pszVal = poFeature->GetFieldAsString(i);
+                    json_object_object_add(poContainer,
+                            pszLastComponent,
+                            json_object_new_string(pszVal));
+                }
+            }
+        }
+
+        // Build the field string
+        fields = json_object_to_json_string(fieldObject);
+        json_object_put(fieldObject);
+    }
+
+    return fields;
+}
+
+/************************************************************************/
+/*                          ICreateFeature()                            */
+/************************************************************************/
+
+OGRErr OGRElasticLayer::ICreateFeature(OGRFeature *poFeature)
+{
+    FinalizeFeatureDefn();
+
+    if( WriteMapIfNecessary() != OGRERR_NONE )
+        return OGRERR_FAILURE;
+
+    if (m_osWriteMapFilename.size())
+        return OGRERR_NONE;
+
+    if( poFeature->GetFID() < 0 )
+    {
+        if( m_nNextFID < 0 )
+            m_nNextFID = GetFeatureCount(FALSE);
+        poFeature->SetFID(++m_nNextFID);
+    }
+
+    CPLString osFields(BuildJSonFromFeature(poFeature));
+
+    const char* pszId = NULL;
+    if( poFeature->IsFieldSet(0) && !m_bIgnoreSourceID )
+        pszId = poFeature->GetFieldAsString(0);
+
+    // Check to see if we're using bulk uploading
+    if (m_nBulkUpload > 0) {
+        m_osBulkContent += CPLSPrintf("{\"index\" :{\"_index\":\"%s\", \"_type\":\"%s\"", m_osIndexName.c_str(), m_osMappingName.c_str());
+        if( pszId )
+            m_osBulkContent += CPLSPrintf(",\"_id\":\"%s\"", pszId);
+        m_osBulkContent += "}}\n" + osFields + "\n\n";
+
+        // Only push the data if we are over our bulk upload limit
+        if ((int) m_osBulkContent.length() > m_nBulkUpload) {
+            if( !PushIndex() )
+            {
+                return OGRERR_FAILURE;
+            }
+        }
+
+    } else { // Fall back to using single item upload for every feature
+        CPLString osURL(CPLSPrintf("%s/%s/%s/", m_poDS->GetURL(), m_osIndexName.c_str(), m_osMappingName.c_str()));
+        if( pszId )
+            osURL += pszId;
+        json_object* poRes = m_poDS->RunRequest(osURL, osFields);
+        if( poRes == NULL )
+        {
+            return OGRERR_FAILURE;
+        }
+        if( pszId == NULL )
+        {
+            json_object* poId = json_object_object_get(poRes, "_id");
+            if( poId != NULL && json_object_get_type(poId) == json_type_string )
+            {
+                pszId = json_object_get_string(poId);
+                poFeature->SetField(0, pszId);
+            }
+
+        }
+        json_object_put(poRes);
+    }
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           ISetFeature()                              */
+/************************************************************************/
+
+OGRErr OGRElasticLayer::ISetFeature(OGRFeature *poFeature)
+{
+    FinalizeFeatureDefn();
+
+    if( !poFeature->IsFieldSet(0) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "_id field not set");
+        return OGRERR_FAILURE;
+    }
+    if( poFeature->GetFID() < 0 && m_osFID.size() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Invalid FID");
+        return OGRERR_FAILURE;
+    }
+
+    if( WriteMapIfNecessary() != OGRERR_NONE )
+        return OGRERR_FAILURE;
+    PushIndex();
+
+    CPLString osFields(BuildJSonFromFeature(poFeature));
+
+    // TODO? we should theoretically detect if the provided _id doesn't exist
+    CPLString osURL(CPLSPrintf("%s/%s/%s/%s",
+                               m_poDS->GetURL(), m_osIndexName.c_str(),
+                               m_osMappingName.c_str(),poFeature->GetFieldAsString(0)));
+    json_object* poRes = m_poDS->RunRequest(osURL, osFields);
+    if( poRes == NULL )
+    {
+        return OGRERR_FAILURE;
+    }
+    //CPLDebug("ES", "SetFeature(): %s", json_object_to_json_string(poRes));
+    json_object_put(poRes);
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                             PushIndex()                              */
+/************************************************************************/
+
+int OGRElasticLayer::PushIndex() {
+    if (m_osBulkContent.empty()) {
+        return TRUE;
+    }
+
+    int bRet = m_poDS->UploadFile(CPLSPrintf("%s/_bulk", m_poDS->GetURL()), m_osBulkContent);
+    m_osBulkContent.clear();
+
+    return bRet;
+}
+
+/************************************************************************/
+/*                            CreateField()                             */
+/************************************************************************/
+
+OGRErr OGRElasticLayer::CreateField(OGRFieldDefn *poFieldDefn,
+                                    CPL_UNUSED int bApproxOK)
+{
+    FinalizeFeatureDefn();
+    ResetReading();
+
+    if( m_poFeatureDefn->GetFieldIndex(poFieldDefn->GetNameRef()) >= 0 )
+    {
+        if( !EQUAL(poFieldDefn->GetNameRef(), "_id") &&
+            !EQUAL(poFieldDefn->GetNameRef(), "_json") )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "CreateField() called with an already existing field name: %s",
+                      poFieldDefn->GetNameRef());
+        }
+        return OGRERR_FAILURE;
+    }
+
+    std::vector<CPLString> aosPath;
+    if( m_osMappingName == "FeatureCollection" )
+        aosPath.push_back("properties");
+
+    if( m_bDotAsNestedField )
+    {
+        char** papszTokens = CSLTokenizeString2(poFieldDefn->GetNameRef(), ".", 0);
+        for(int i=0; papszTokens[i]; i++ )
+            aosPath.push_back(papszTokens[i]);
+        CSLDestroy(papszTokens);
+    }
+    else
+        aosPath.push_back(poFieldDefn->GetNameRef());
+
+    AddFieldDefn( poFieldDefn->GetNameRef(),
+                  poFieldDefn->GetType(),
+                  aosPath,
+                  poFieldDefn->GetSubType() );
+
+    m_bSerializeMapping = TRUE;
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           CreateGeomField()                          */
+/************************************************************************/
+
+OGRErr OGRElasticLayer::CreateGeomField( OGRGeomFieldDefn *poFieldIn, CPL_UNUSED int bApproxOK )
+
+{
+    FinalizeFeatureDefn();
+    ResetReading();
+
+    if( m_poFeatureDefn->GetGeomFieldIndex(poFieldIn->GetNameRef()) >= 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "CreateGeomField() called with an already existing field name: %s",
+                  poFieldIn->GetNameRef());
+        return OGRERR_FAILURE;
+    }
+
+    if( m_eGeomTypeMapping == ES_GEOMTYPE_GEO_POINT &&
+        m_poFeatureDefn->GetGeomFieldCount() > 0 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "ES_GEOM_TYPE=GEO_POINT only supported for single geometry field");
+        return OGRERR_FAILURE;
+    }
+
+    OGRGeomFieldDefn oFieldDefn(poFieldIn);
+    if( EQUAL(oFieldDefn.GetNameRef(), "") )
+        oFieldDefn.SetName("geometry");
+
+    std::vector<CPLString> aosPath;
+    if( m_bDotAsNestedField )
+    {
+        char** papszTokens = CSLTokenizeString2(oFieldDefn.GetNameRef(), ".", 0);
+        for(int i=0; papszTokens[i]; i++ )
+            aosPath.push_back(papszTokens[i]);
+        CSLDestroy(papszTokens);
+    }
+    else
+        aosPath.push_back(oFieldDefn.GetNameRef());
+
+    if( m_eGeomTypeMapping == ES_GEOMTYPE_GEO_SHAPE ||
+        (m_eGeomTypeMapping == ES_GEOMTYPE_AUTO &&
+         poFieldIn->GetType() != wkbPoint) ||
+        m_poFeatureDefn->GetGeomFieldCount() > 0 )
+    {
+        m_abIsGeoPoint.push_back(FALSE);
+    }
+    else
+    {
+        m_abIsGeoPoint.push_back(TRUE);
+        aosPath.push_back("coordinates");
+    }
+
+    m_aaosGeomFieldPaths.push_back(aosPath);
+
+    m_aosMapToGeomFieldIndex[ BuildPathFromArray(aosPath) ] = m_poFeatureDefn->GetGeomFieldCount();
+
+    m_poFeatureDefn->AddGeomFieldDefn( &oFieldDefn );
+
+    OGRCoordinateTransformation* poCT = NULL;
+    if( oFieldDefn.GetSpatialRef() != NULL )
+    {
+        OGRSpatialReference oSRS_WGS84;
+        oSRS_WGS84.SetFromUserInput(SRS_WKT_WGS84);
+        if( !oSRS_WGS84.IsSame(oFieldDefn.GetSpatialRef()) )
+        {
+            poCT = OGRCreateCoordinateTransformation( oFieldDefn.GetSpatialRef(), &oSRS_WGS84 );
+            if( poCT == NULL )
+            {
+                CPLError( CE_Warning, CPLE_AppDefined,
+                          "On-the-fly reprojection to WGS84 long/lat would be "
+                          "needed, but instantiation of transformer failed");
+            }
+        }
+    }
+    else
+    {
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "No SRS given for geometry column %s. SRS is assumed to "
+                  "be EPSG:4326 (WGS84 long/lat)",
+                  oFieldDefn.GetNameRef());
+    }
+
+    m_apoCT.push_back(poCT);
+
+    m_bSerializeMapping = TRUE;
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRElasticLayer::TestCapability(const char * pszCap) {
+    if (EQUAL(pszCap, OLCFastFeatureCount))
+        return m_poAttrQuery == NULL && m_poFilterGeom == NULL;
+
+    else if (EQUAL(pszCap, OLCStringsAsUTF8))
+        return TRUE;
+
+    else if (EQUAL(pszCap, OLCSequentialWrite) ||
+             EQUAL(pszCap, OLCRandomWrite)
+    )
+        return TRUE;
+    else if (EQUAL(pszCap, OLCCreateField) ||
+             EQUAL(pszCap, OLCCreateGeomField) )
+        return TRUE;
+    else
+        return FALSE;
+}
+
+/************************************************************************/
+/*                          GetFeatureCount()                           */
+/************************************************************************/
+
+GIntBig OGRElasticLayer::GetFeatureCount(int bForce)
+{
+    if( m_poAttrQuery != NULL )
+        return OGRLayer::GetFeatureCount(bForce);
+
+    json_object* poResponse;
+    if( m_osESSearch.size() )
+    {
+        poResponse = m_poDS->RunRequest(
+            CPLSPrintf("%s/_search?search_type=count&pretty", m_poDS->GetURL()),
+            m_osESSearch.c_str());
+    }
+    else if( m_poSpatialFilter )
+    {
+        CPLString osFilter = CPLSPrintf("{ \"query\": { \"filtered\" : { \"query\" : { \"match_all\" : {} }, \"filter\": %s } } }",
+                                        json_object_to_json_string( m_poSpatialFilter ));
+        poResponse = m_poDS->RunRequest(
+            CPLSPrintf("%s/%s/%s/_search?search_type=count&pretty", m_poDS->GetURL(), m_osIndexName.c_str(), m_osMappingName.c_str()),
+            osFilter.c_str());
+    }
+    else
+    {
+        poResponse = m_poDS->RunRequest(
+            CPLSPrintf("%s/%s/%s/_search?search_type=count&pretty", m_poDS->GetURL(), m_osIndexName.c_str(), m_osMappingName.c_str()),
+            m_osJSONFilter.c_str());
+    }
+
+    json_object* poCount = json_ex_get_object_by_path(poResponse, "hits.count");
+    if( poCount == NULL )
+        poCount = json_ex_get_object_by_path(poResponse, "hits.total");
+    if( poCount == NULL || json_object_get_type(poCount) != json_type_int )
+    {
+        json_object_put(poResponse);
+        return OGRLayer::GetFeatureCount(bForce);
+    }
+
+    GIntBig nCount = json_object_get_int64(poCount);
+    json_object_put(poResponse);
+    return nCount;
+}
+
+/************************************************************************/
+/*                          SetAttributeFilter()                        */
+/************************************************************************/
+
+OGRErr OGRElasticLayer::SetAttributeFilter(const char* pszFilter)
+{
+    if( pszFilter != NULL && pszFilter[0] == '{' )
+    {
+        if( m_osESSearch.size() )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Setting an ElasticSearch filter on a resulting layer is not supported");
+            return OGRERR_FAILURE;
+        }
+        OGRLayer::SetAttributeFilter(NULL);
+        m_osJSONFilter = pszFilter;
+        return OGRERR_NONE;
+    }
+    else
+    {
+        m_osJSONFilter = "";
+        return OGRLayer::SetAttributeFilter(pszFilter);
+    }
+}
+
+/************************************************************************/
+/*                          SetSpatialFilter()                          */
+/************************************************************************/
+
+void OGRElasticLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poGeomIn )
+
+{
+    FinalizeFeatureDefn();
+
+    if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() ||
+        GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetType() == wkbNone )
+    {
+        if( iGeomField != 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Invalid geometry field index : %d", iGeomField);
+        }
+        return;
+    }
+    m_iGeomFieldFilter = iGeomField;
+
+    InstallFilter( poGeomIn );
+
+    json_object_put(m_poSpatialFilter);
+    m_poSpatialFilter = NULL;
+
+    if( poGeomIn == NULL )
+        return;
+
+    if( m_osESSearch.size() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                    "Setting a spatial filter on a resulting layer is not supported");
+        return;
+    }
+
+    OGREnvelope sEnvelope;
+    poGeomIn->getEnvelope(&sEnvelope);
+
+    if( sEnvelope.MinX < -180 )
+        sEnvelope.MinX = -180;
+    if( sEnvelope.MinX > 180 )
+        sEnvelope.MinX = 180;
+
+    if( sEnvelope.MinY < -90 )
+        sEnvelope.MinY = -90;
+    if( sEnvelope.MinY > 90 )
+        sEnvelope.MinY = 90;
+
+    if( sEnvelope.MaxX > 180 )
+        sEnvelope.MaxX = 180;
+    if( sEnvelope.MaxX < -180 )
+        sEnvelope.MaxX = -180;
+
+    if( sEnvelope.MaxY > 90 )
+        sEnvelope.MaxY = 90;
+    if( sEnvelope.MaxY < -90 )
+        sEnvelope.MaxY = -90;
+
+    if( sEnvelope.MinX == -180 && sEnvelope.MinY == -90 &&
+        sEnvelope.MaxX == 180 && sEnvelope.MaxY == 90 )
+    {
+        return;
+    }
+
+    m_poSpatialFilter = json_object_new_object();
+
+    if( m_abIsGeoPoint[iGeomField] )
+    {
+        json_object* geo_bounding_box = json_object_new_object();
+        json_object_object_add(m_poSpatialFilter, "geo_bounding_box", geo_bounding_box);
+
+        CPLString osPath = BuildPathFromArray(m_aaosGeomFieldPaths[iGeomField]);
+
+        json_object* field = json_object_new_object();
+        json_object_object_add(geo_bounding_box, osPath.c_str(), field);
+
+        json_object* top_left = json_object_new_object();
+        json_object_object_add(field, "top_left", top_left);
+        json_object_object_add(top_left, "lat", json_object_new_double(sEnvelope.MaxY));
+        json_object_object_add(top_left, "lon", json_object_new_double(sEnvelope.MinX));
+
+        json_object* bottom_right = json_object_new_object();
+        json_object_object_add(field, "bottom_right", bottom_right);
+        json_object_object_add(bottom_right, "lat", json_object_new_double(sEnvelope.MinY));
+        json_object_object_add(bottom_right, "lon", json_object_new_double(sEnvelope.MaxX));
+    }
+    else
+    {
+        json_object* geo_shape = json_object_new_object();
+        json_object_object_add(m_poSpatialFilter, "geo_shape", geo_shape);
+
+        CPLString osPath = BuildPathFromArray(m_aaosGeomFieldPaths[iGeomField]);
+
+        json_object* field = json_object_new_object();
+        json_object_object_add(geo_shape, osPath.c_str(), field);
+
+        json_object* shape = json_object_new_object();
+        json_object_object_add(field, "shape", shape);
+
+        json_object_object_add(shape, "type", json_object_new_string("envelope"));
+
+        json_object* coordinates = json_object_new_array();
+        json_object_object_add(shape, "coordinates", coordinates);
+
+        json_object* top_left = json_object_new_array();
+        json_object_array_add(top_left, json_object_new_double(sEnvelope.MinX));
+        json_object_array_add(top_left, json_object_new_double(sEnvelope.MaxY));
+        json_object_array_add(coordinates, top_left);
+
+        json_object* bottom_right = json_object_new_array();
+        json_object_array_add(bottom_right, json_object_new_double(sEnvelope.MaxX));
+        json_object_array_add(bottom_right, json_object_new_double(sEnvelope.MinY));
+        json_object_array_add(coordinates, bottom_right);
+    }
+}
+
+/************************************************************************/
+/*                            GetExtent()                                */
+/************************************************************************/
+
+OGRErr OGRElasticLayer::GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce )
+{
+    FinalizeFeatureDefn();
+
+    if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() )
+    {
+        if( iGeomField != 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Invalid geometry field index : %d", iGeomField);
+        }
+        return OGRERR_FAILURE;
+    }
+
+    if( !m_abIsGeoPoint[iGeomField] )
+        return OGRLayer::GetExtentInternal(iGeomField, psExtent, bForce);
+
+    json_object* poResponse;
+    CPLString osFilter = CPLSPrintf("{ \"aggs\" : { \"bbox\" : { \"geo_bounds\" : { \"field\" : \"%s\" } } } }",
+                                    BuildPathFromArray(m_aaosGeomFieldPaths[iGeomField]).c_str() );
+    poResponse = m_poDS->RunRequest(
+        CPLSPrintf("%s/%s/%s/_search?search_type=count&pretty",
+                    m_poDS->GetURL(), m_osIndexName.c_str(), m_osMappingName.c_str()),
+        osFilter.c_str());
+
+    json_object* poBounds = json_ex_get_object_by_path(poResponse, "aggregations.bbox.bounds");
+    json_object* poTopLeft = json_ex_get_object_by_path(poBounds, "top_left");
+    json_object* poBottomRight = json_ex_get_object_by_path(poBounds, "bottom_right");
+    json_object* poTopLeftLon = json_ex_get_object_by_path(poTopLeft, "lon");
+    json_object* poTopLeftLat = json_ex_get_object_by_path(poTopLeft, "lat");
+    json_object* poBottomRightLon = json_ex_get_object_by_path(poBottomRight, "lon");
+    json_object* poBottomRightLat = json_ex_get_object_by_path(poBottomRight, "lat");
+
+    OGRErr eErr;
+    if( poTopLeftLon == NULL || poTopLeftLat == NULL ||
+        poBottomRightLon == NULL || poBottomRightLat == NULL )
+    {
+        eErr = OGRLayer::GetExtentInternal(iGeomField, psExtent, bForce);
+    }
+    else
+    {
+        double dfMinX = json_object_get_double( poTopLeftLon );
+        double dfMaxY = json_object_get_double( poTopLeftLat );
+        double dfMaxX = json_object_get_double( poBottomRightLon );
+        double dfMinY = json_object_get_double( poBottomRightLat );
+
+        psExtent->MinX = dfMinX;
+        psExtent->MaxY = dfMaxY;
+        psExtent->MaxX = dfMaxX;
+        psExtent->MinY = dfMinY;
+
+        eErr = OGRERR_NONE;
+    }
+    json_object_put(poResponse);
 
-GIntBig OGRElasticLayer::GetFeatureCount(CPL_UNUSED int bForce) {
-    CPLError(CE_Failure, CPLE_NotSupported,
-            "Cannot read features when writing a Elastic file");
-    return 0;
+    return eErr;
 }
diff --git a/ogr/ogrsf_frmts/filegdb/FGdbDatasource.cpp b/ogr/ogrsf_frmts/filegdb/FGdbDatasource.cpp
index 806f0db..ebba8ba 100644
--- a/ogr/ogrsf_frmts/filegdb/FGdbDatasource.cpp
+++ b/ogr/ogrsf_frmts/filegdb/FGdbDatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: FGdbDatasource.cpp 29330 2015-06-14 12:11:11Z rouault $
+ * $Id: FGdbDatasource.cpp 33563 2016-02-26 14:57:06Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements FileGDB OGR Datasource.
@@ -37,7 +37,7 @@
 #include "FGdbUtils.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: FGdbDatasource.cpp 29330 2015-06-14 12:11:11Z rouault $");
+CPL_CVSID("$Id: FGdbDatasource.cpp 33563 2016-02-26 14:57:06Z rouault $");
 
 using std::vector;
 using std::wstring;
@@ -46,11 +46,13 @@ using std::wstring;
 /*                          FGdbDataSource()                           */
 /************************************************************************/
 
-FGdbDataSource::FGdbDataSource(FGdbDriver* poDriver, 
+FGdbDataSource::FGdbDataSource(FGdbDriver* poDriverIn, 
                                FGdbDatabaseConnection* pConnection):
 OGRDataSource(),
-m_poDriver(poDriver), m_pConnection(pConnection), m_pszName(0), m_pGeodatabase(NULL), m_bUpdate(false)
+m_poDriver(poDriverIn), m_pConnection(pConnection), m_pGeodatabase(NULL), m_bUpdate(false),
+m_poOpenFileGDBDrv(NULL)
 {
+    bPerLayerCopyingForTransaction = -1;
 }
 
 /************************************************************************/
@@ -59,29 +61,107 @@ m_poDriver(poDriver), m_pConnection(pConnection), m_pszName(0), m_pGeodatabase(N
 
 FGdbDataSource::~FGdbDataSource()
 {
-    CPLMutexHolderOptionalLockD(m_poDriver->GetMutex());
+    CPLMutexHolderOptionalLockD(m_poDriver ? m_poDriver->GetMutex() : NULL);
     
-    if( m_pConnection->IsLocked() )
+    if( m_pConnection && m_pConnection->IsLocked() )
         CommitTransaction();
 
+    //Close();
     size_t count = m_layers.size();
     for(size_t i = 0; i < count; ++i )
-        delete m_layers[i];
+    {
+        m_layers[i]->CloseGDBObjects();
+    }
 
-    m_poDriver->Release( m_pszName );
-    CPLFree( m_pszName );
+    FixIndexes();
+
+    if( m_poDriver )
+        m_poDriver->Release( m_osPublicName );
+
+    //size_t count = m_layers.size();
+    for(size_t i = 0; i < count; ++i )
+    {
+        delete m_layers[i];
+    }
 }
 
+/************************************************************************/
+/*                             FixIndexes()                             */
+/************************************************************************/
+
+int FGdbDataSource::FixIndexes()
+{
+    int bRet = TRUE;
+    if( m_pConnection && m_pConnection->IsFIDHackInProgress() )
+    {
+        m_pConnection->CloseGeodatabase();
+
+        char* apszDrivers[2];
+        apszDrivers[0] = (char*) "OpenFileGDB";
+        apszDrivers[1] = NULL;
+        const char* pszSystemCatalog = CPLFormFilename(m_osFSName, "a00000001.gdbtable", NULL);
+        GDALDataset* poOpenFileGDBDS = (GDALDataset*)
+            GDALOpenEx(pszSystemCatalog, GDAL_OF_VECTOR,
+                       apszDrivers, NULL, NULL);
+        if( poOpenFileGDBDS == NULL || poOpenFileGDBDS->GetLayer(0) == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Cannot open %s with OpenFileGDB driver. "
+                     "Should not happen. Some layers will be corrupted",
+                     pszSystemCatalog);
+            bRet = FALSE;
+        }
+        else
+        {
+            OGRLayer* poLayer = poOpenFileGDBDS->GetLayer(0);
+            size_t count = m_layers.size();
+            for(size_t i = 0; i < count; ++i )
+            {
+                if( m_layers[i]->m_oMapOGRFIDToFGDBFID.size() == 0)
+                    continue;
+                CPLString osFilter = "name = '";
+                osFilter += m_layers[i]->GetName();
+                osFilter += "'";
+                poLayer->SetAttributeFilter(osFilter);
+                poLayer->ResetReading();
+                OGRFeature* poF = poLayer->GetNextFeature();
+                if( poF == NULL )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Cannot find filename for layer %s",
+                             m_layers[i]->GetName());
+                    bRet = FALSE;
+                }
+                else
+                {
+                    if( !m_layers[i]->EditIndexesForFIDHack(CPLFormFilename(m_osFSName,
+                                        CPLSPrintf("a%08x", (int)poF->GetFID()), NULL)) )
+                    {
+                        bRet = FALSE;
+                    }
+                }
+                delete poF;
+            }
+        }
+        GDALClose(poOpenFileGDBDS);
+
+        m_pConnection->SetFIDHackInProgress(FALSE);
+    }
+    return bRet;
+}
 
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
 
-int FGdbDataSource::Open(const char * pszNewName, int bUpdate )
+int FGdbDataSource::Open(const char * pszNewName, int bUpdate,
+                         const char* pszPublicName )
 {
-    m_pszName = CPLStrdup( pszNewName );
+    m_osFSName = pszNewName;
+    m_osPublicName = (pszPublicName) ? pszPublicName : pszNewName;
     m_pGeodatabase = m_pConnection->GetGDB();
-    m_bUpdate = bUpdate;
+    m_bUpdate = CPL_TO_BOOL(bUpdate);
+    m_poOpenFileGDBDrv = (GDALDriver*) GDALGetDriverByName("OpenFileGDB");
 
     std::vector<std::wstring> typesRequested;
 
@@ -96,6 +176,85 @@ int FGdbDataSource::Open(const char * pszNewName, int bUpdate )
 }
 
 /************************************************************************/
+/*                               Close()                                */
+/************************************************************************/
+
+int FGdbDataSource::Close(int bCloseGeodatabase)
+{
+    size_t count = m_layers.size();
+    for(size_t i = 0; i < count; ++i )
+    {
+        m_layers[i]->CloseGDBObjects();
+    }
+
+    int bRet = FixIndexes();
+    if( m_pConnection && bCloseGeodatabase )
+        m_pConnection->CloseGeodatabase();
+    m_pGeodatabase = NULL;
+    return bRet;
+}
+
+/************************************************************************/
+/*                               ReOpen()                               */
+/************************************************************************/
+
+int FGdbDataSource::ReOpen()
+{
+    CPLAssert(m_pGeodatabase == NULL);
+
+    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL_REOPEN", ""), "CASE1") ||
+        !m_pConnection->OpenGeodatabase(m_osFSName) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot reopen %s",
+                 m_osFSName.c_str());
+        return FALSE;
+    }
+
+    FGdbDataSource* pDS = new FGdbDataSource(m_poDriver, m_pConnection);
+    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL_REOPEN", ""), "CASE2") ||
+        !pDS->Open(m_osPublicName, TRUE, m_osFSName) )
+    {
+        pDS->m_poDriver = NULL;
+        delete pDS;
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot reopen %s",
+                 m_osFSName.c_str());
+        return FALSE;
+    }
+    
+    int bRet = TRUE;
+    size_t count = m_layers.size();
+    for(size_t i = 0; i < count; ++i )
+    {
+        FGdbLayer* pNewLayer = (FGdbLayer*)pDS->GetLayerByName(m_layers[i]->GetName());
+        if( pNewLayer &&
+            !EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL_REOPEN", ""), "CASE3") )
+        {
+            m_layers[i]->m_pTable = pNewLayer->m_pTable;
+            pNewLayer->m_pTable = NULL;
+            m_layers[i]->m_pEnumRows = pNewLayer->m_pEnumRows;
+            pNewLayer->m_pEnumRows = NULL;
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Cannot reopen %s",
+                     m_layers[i]->GetName());
+            bRet = FALSE;
+        }
+        m_layers[i]->m_oMapOGRFIDToFGDBFID.clear();
+        m_layers[i]->m_oMapFGDBFIDToOGRFID.clear();
+    }
+    
+    m_pGeodatabase = pDS->m_pGeodatabase;
+    pDS->m_pGeodatabase = NULL;
+
+    pDS->m_poDriver = NULL;
+    pDS->m_pConnection = NULL;
+    delete pDS;
+    
+    return bRet;
+}
+
+/************************************************************************/
 /*                          OpenFGDBTables()                            */
 /************************************************************************/
 
@@ -110,10 +269,23 @@ bool FGdbDataSource::OpenFGDBTables(const std::wstring &type,
         if (FAILED(hr = m_pGeodatabase->OpenTable(layers[i], *pTable)))
         {
             delete pTable;
+            
+            std::wstring fgdb_error_desc_w;
+            fgdbError er;
+            er = FileGDBAPI::ErrorInfo::GetErrorDescription(hr, fgdb_error_desc_w);
+            const char* pszLikelyReason = "Might be due to unsupported spatial reference system. Using OpenFileGDB driver or FileGDB SDK >= 1.4 should solve it";
+            if ( er == S_OK )
+            {
+                std::string fgdb_error_desc = WStringToString(fgdb_error_desc_w);
+                if( fgdb_error_desc == "FileGDB compression is not installed." )
+                {
+                    pszLikelyReason = "Using FileGDB SDK 1.4 or later should solve this issue.";
+                }
+            }
+
             GDBErr(hr, "Error opening " + WStringToString(layers[i]),
                    CE_Warning,
-                   ". Skipping it. "
-                   "Might be due to unsupported spatial reference system. Using OpenFileGDB driver should solve it");
+                   (". Skipping it. " + CPLString(pszLikelyReason)).c_str());
             continue;
         }
         FGdbLayer* pLayer = new FGdbLayer();
@@ -184,7 +356,7 @@ bool FGdbDataSource::LoadLayers(const std::wstring &root)
 /* Old recursive LoadLayers. Removed in favor of simple one that only
    looks at FeatureClasses and Tables. */
 
-// Flattens out hierarchichal GDB structure
+// Flattens out hierarchical GDB structure.
 bool FGdbDataSource::LoadLayersOld(const std::vector<wstring> & datasetTypes,
                                 const wstring & parent)
 {
@@ -215,7 +387,7 @@ bool FGdbDataSource::LoadLayersOld(const std::vector<wstring> & datasetTypes,
 
                 // do something with it
                 // For now, we just ignore dataset containers and only open the children
-                //std::wcout << datasetTypes[dsTypeIndex] << L" " << childDatasets[childDatasetIndex] << std::endl;
+                // std::wcout << datasetTypes[dsTypeIndex] << L" " << childDatasets[childDatasetIndex] << std::endl;
 
                 if (!LoadLayersOld(datasetTypes, childDatasets[childDatasetIndex]))
                     errorsEncountered = true;
@@ -227,7 +399,7 @@ bool FGdbDataSource::LoadLayersOld(const std::vector<wstring> & datasetTypes,
 
     if ((!childrenFound) && parent != L"\\")
     {
-        //wcout << "Opening " << parent << "...";
+        // wcout << "Opening " << parent << "...";
         Table* pTable = new Table;
         if (FAILED(hr = m_pGeodatabase->OpenTable(parent,*pTable)))
         {
@@ -260,7 +432,7 @@ bool FGdbDataSource::LoadLayersOld(const std::vector<wstring> & datasetTypes,
 
 OGRErr FGdbDataSource::DeleteLayer( int iLayer )
 {
-    if( !m_bUpdate )
+    if( !m_bUpdate || m_pGeodatabase == NULL )
         return OGRERR_FAILURE;
 
     if( iLayer < 0 || iLayer >= static_cast<int>(m_layers.size()) )
@@ -307,7 +479,8 @@ int FGdbDataSource::TestCapability( const char * pszCap )
 
     else if( EQUAL(pszCap,ODsCDeleteLayer) )
         return m_bUpdate;
-
+    else if EQUAL(pszCap,ODsCCreateGeomFieldAfterCreateLayer)
+        return TRUE;
     return FALSE;
 }
 
@@ -338,7 +511,7 @@ FGdbDataSource::ICreateLayer( const char * pszLayerName,
                               OGRwkbGeometryType eType,
                               char ** papszOptions )
 {
-    if( !m_bUpdate )
+    if( !m_bUpdate || m_pGeodatabase == NULL )
         return NULL;
 
     FGdbLayer* pLayer = new FGdbLayer();
@@ -381,7 +554,7 @@ class OGRFGdbSingleFeatureLayer : public OGRLayer
 /************************************************************************/
 
 OGRFGdbSingleFeatureLayer::OGRFGdbSingleFeatureLayer(const char* pszLayerName,
-                                                     const char *pszVal )
+                                                     const char *pszValIn )
 {
     poFeatureDefn = new OGRFeatureDefn( pszLayerName );
     SetDescription( poFeatureDefn->GetName() );
@@ -390,7 +563,7 @@ OGRFGdbSingleFeatureLayer::OGRFGdbSingleFeatureLayer(const char* pszLayerName,
     poFeatureDefn->AddFieldDefn( &oField );
 
     iNextShapeId = 0;
-    this->pszVal = pszVal ? CPLStrdup(pszVal) : NULL;
+    this->pszVal = pszValIn ? CPLStrdup(pszValIn) : NULL;
 }
 
 /************************************************************************/
@@ -430,6 +603,14 @@ OGRLayer * FGdbDataSource::ExecuteSQL( const char *pszSQLCommand,
                                        const char *pszDialect )
 
 {
+    if( m_pConnection && m_pConnection->IsFIDHackInProgress() )
+    {
+        if( Close() )
+            ReOpen();
+    }
+    if( m_pGeodatabase == NULL )
+         return NULL;
+
     size_t count = m_layers.size();
     for(size_t i = 0; i < count; ++i )
     {
@@ -447,7 +628,7 @@ OGRLayer * FGdbDataSource::ExecuteSQL( const char *pszSQLCommand,
 /* -------------------------------------------------------------------- */
 /*      Special case GetLayerDefinition                                 */
 /* -------------------------------------------------------------------- */
-    if (EQUALN(pszSQLCommand, "GetLayerDefinition ", strlen("GetLayerDefinition ")))
+    if (STARTS_WITH_CI(pszSQLCommand, "GetLayerDefinition "))
     {
         FGdbLayer* poLayer = (FGdbLayer*) GetLayerByName(pszSQLCommand + strlen("GetLayerDefinition "));
         if (poLayer)
@@ -465,7 +646,7 @@ OGRLayer * FGdbDataSource::ExecuteSQL( const char *pszSQLCommand,
 /* -------------------------------------------------------------------- */
 /*      Special case GetLayerMetadata                                   */
 /* -------------------------------------------------------------------- */
-    if (EQUALN(pszSQLCommand, "GetLayerMetadata ", strlen("GetLayerMetadata ")))
+    if (STARTS_WITH_CI(pszSQLCommand, "GetLayerMetadata "))
     {
         FGdbLayer* poLayer = (FGdbLayer*) GetLayerByName(pszSQLCommand + strlen("GetLayerMetadata "));
         if (poLayer)
@@ -482,16 +663,19 @@ OGRLayer * FGdbDataSource::ExecuteSQL( const char *pszSQLCommand,
 
     /* TODO: remove that workaround when the SDK has finally a decent */
     /* SQL support ! */
-    if( EQUALN(pszSQLCommand, "SELECT ", 7) && pszDialect == NULL )
+    if( STARTS_WITH_CI(pszSQLCommand, "SELECT ") && pszDialect == NULL )
     {
         CPLDebug("FGDB", "Support for SELECT is known to be partially "
                          "non-compliant with FileGDB SDK API v1.2.\n"
                          "So for now, we use default OGR SQL engine. "
                          "Explicitly specify -dialect FileGDB\n"
                          "to use the SQL engine from the FileGDB SDK API");
-        return OGRDataSource::ExecuteSQL( pszSQLCommand,
+        OGRLayer* poLayer = OGRDataSource::ExecuteSQL( pszSQLCommand,
                                         poSpatialFilter,
                                         pszDialect );
+        if( poLayer )
+            m_oSetSelectLayers.insert(poLayer);
+        return poLayer;
     }
 
 /* -------------------------------------------------------------------- */
@@ -506,8 +690,9 @@ OGRLayer * FGdbDataSource::ExecuteSQL( const char *pszSQLCommand,
     }
     catch(...)
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Exception occured at executing '%s'. Application may become unstable", pszSQLCommand);
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Exception occurred at executing '%s'. Application may "
+                  "become unstable", pszSQLCommand );
         delete pEnumRows;
         return NULL;
     }
@@ -519,9 +704,11 @@ OGRLayer * FGdbDataSource::ExecuteSQL( const char *pszSQLCommand,
         return NULL;
     }
 
-    if( EQUALN(pszSQLCommand, "SELECT ", 7) )
+    if( STARTS_WITH_CI(pszSQLCommand, "SELECT ") )
     {
-        return new FGdbResultLayer(this, pszSQLCommand, pEnumRows);
+        OGRLayer* poLayer = new FGdbResultLayer(this, pszSQLCommand, pEnumRows);
+        m_oSetSelectLayers.insert(poLayer);
+        return poLayer;
     }
     else
     {
@@ -536,5 +723,38 @@ OGRLayer * FGdbDataSource::ExecuteSQL( const char *pszSQLCommand,
 
 void FGdbDataSource::ReleaseResultSet( OGRLayer * poResultsSet )
 {
+    if( poResultsSet )
+        m_oSetSelectLayers.erase(poResultsSet);
     delete poResultsSet;
 }
+
+/************************************************************************/
+/*                      HasPerLayerCopyingForTransaction()              */
+/************************************************************************/
+
+int FGdbDataSource::HasPerLayerCopyingForTransaction()
+{
+    if( bPerLayerCopyingForTransaction >= 0 )
+        return bPerLayerCopyingForTransaction;
+#ifdef WIN32
+    bPerLayerCopyingForTransaction = FALSE;
+#else
+    bPerLayerCopyingForTransaction =
+        m_poOpenFileGDBDrv != NULL &&
+        CPLTestBool(CPLGetConfigOption("FGDB_PER_LAYER_COPYING_TRANSACTION", "TRUE"));
+#endif
+    return bPerLayerCopyingForTransaction;
+}
+
+/************************************************************************/
+/*                        SetSymlinkFlagOnAllLayers()                    */
+/************************************************************************/
+
+void FGdbDataSource::SetSymlinkFlagOnAllLayers()
+{
+    size_t count = m_layers.size();
+    for(size_t i = 0; i < count; ++i )
+    {
+        m_layers[i]->SetSymlinkFlag();
+    }
+}
diff --git a/ogr/ogrsf_frmts/filegdb/FGdbDriver.cpp b/ogr/ogrsf_frmts/filegdb/FGdbDriver.cpp
index 0c63ebc..b0cb957 100644
--- a/ogr/ogrsf_frmts/filegdb/FGdbDriver.cpp
+++ b/ogr/ogrsf_frmts/filegdb/FGdbDriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: FGdbDriver.cpp 29180 2015-05-10 15:07:48Z rouault $
+ * $Id: FGdbDriver.cpp 32833 2016-01-08 11:43:51Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements FileGDB OGR driver.
@@ -36,7 +36,7 @@
 #include "cpl_multiproc.h"
 #include "ogrmutexeddatasource.h"
 
-CPL_CVSID("$Id: FGdbDriver.cpp 29180 2015-05-10 15:07:48Z rouault $");
+CPL_CVSID("$Id: FGdbDriver.cpp 32833 2016-01-08 11:43:51Z rouault $");
 
 extern "C" void RegisterOGRFileGDB();
 
@@ -80,7 +80,7 @@ OGRDataSource *FGdbDriver::Open( const char* pszFilename, int bUpdate )
 
 {
     // First check if we have to do any work.
-    int nLen = strlen(pszFilename);
+    size_t nLen = strlen(pszFilename);
     if(! ((nLen >= 4 && EQUAL(pszFilename + nLen - 4, ".gdb")) ||
           (nLen >= 5 && EQUAL(pszFilename + nLen - 5, ".gdb/"))) )
         return NULL;
@@ -98,22 +98,27 @@ OGRDataSource *FGdbDriver::Open( const char* pszFilename, int bUpdate )
     }
 
     CPLMutexHolderD(&hMutex);
-    Geodatabase* pGeoDatabase = NULL;
 
     FGdbDatabaseConnection* pConnection = oMapConnections[pszFilename];
     if( pConnection != NULL )
     {
-        pGeoDatabase = pConnection->m_pGeodatabase;
+        if( pConnection->IsFIDHackInProgress() )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Cannot open geodatabase at the moment since it is in 'FID hack mode'");
+            return NULL;
+        }
+
         pConnection->m_nRefCount ++;
         CPLDebug("FileGDB", "ref_count of %s = %d now", pszFilename,
                  pConnection->m_nRefCount);
     }
     else
     {
-        pGeoDatabase = new Geodatabase;
+        Geodatabase* pGeoDatabase = new Geodatabase;
         hr = ::OpenGeodatabase(StringToWString(pszFilename), *pGeoDatabase);
 
-        if (FAILED(hr) || pGeoDatabase == NULL)
+        if (FAILED(hr))
         {
             delete pGeoDatabase;
             
@@ -122,7 +127,7 @@ OGRDataSource *FGdbDriver::Open( const char* pszFilename, int bUpdate )
                 std::wstring fgdb_error_desc_w;
                 std::string fgdb_error_desc("Unknown error");
                 fgdbError er;
-                er = FileGDBAPI::ErrorInfo::GetErrorDescription(hr, fgdb_error_desc_w);
+                er = FileGDBAPI::ErrorInfo::GetErrorDescription(static_cast<fgdbError>(hr), fgdb_error_desc_w);
                 if ( er == S_OK )
                 {
                     fgdb_error_desc = WStringToString(fgdb_error_desc_w);
@@ -140,7 +145,7 @@ OGRDataSource *FGdbDriver::Open( const char* pszFilename, int bUpdate )
         }
 
         CPLDebug("FileGDB", "Really opening %s", pszFilename);
-        pConnection = new FGdbDatabaseConnection(pGeoDatabase);
+        pConnection = new FGdbDatabaseConnection(pszFilename, pGeoDatabase);
         oMapConnections[pszFilename] = pConnection;
     }
 
@@ -148,7 +153,7 @@ OGRDataSource *FGdbDriver::Open( const char* pszFilename, int bUpdate )
 
     pDS = new FGdbDataSource(this, pConnection);
 
-    if(!pDS->Open( pszFilename, bUpdate ) )
+    if(!pDS->Open( pszFilename, bUpdate, NULL ) )
     {
         delete pDS;
         return NULL;
@@ -218,12 +223,12 @@ OGRDataSource* FGdbDriver::CreateDataSource( const char * conn,
         return NULL;
     }
 
-    FGdbDatabaseConnection* pConnection = new FGdbDatabaseConnection(pGeodatabase);
+    FGdbDatabaseConnection* pConnection = new FGdbDatabaseConnection(conn, pGeodatabase);
     oMapConnections[conn] = pConnection;
 
     /* Ready to embed the Geodatabase in an OGR Datasource */
     FGdbDataSource* pDS = new FGdbDataSource(this, pConnection);
-    if ( ! pDS->Open(conn, bUpdate) )
+    if ( ! pDS->Open(conn, bUpdate, NULL) )
     {
         delete pDS;
         return NULL;
@@ -265,38 +270,106 @@ OGRErr FGdbDriver::StartTransaction(OGRDataSource*& poDSInOut, int& bOutHasReope
     bOutHasReopenedDS = TRUE;
 
     CPLString osName(poMutexedDS->GetName());
+    CPLString osNameOri(osName);
     if( osName[osName.size()-1] == '/' || osName[osName.size()-1] == '\\' )
         osName.resize(osName.size()-1);
 
+#ifndef WIN32
+    int bPerLayerCopyingForTransaction = poDS->HasPerLayerCopyingForTransaction();
+#endif
+
     pConnection->m_nRefCount ++;
     delete poDSInOut;
     poDSInOut = NULL;
     poMutexedDS = NULL;
     poDS = NULL;
 
-    ::CloseGeodatabase(*(pConnection->m_pGeodatabase));
-    delete pConnection->m_pGeodatabase;
-    pConnection->m_pGeodatabase = NULL;
+    pConnection->CloseGeodatabase();
 
     CPLString osEditedName(osName);
     osEditedName += ".ogredited";
 
     CPLPushErrorHandler(CPLQuietErrorHandler);
-    CPLUnlinkTree(osEditedName);
+    CPL_IGNORE_RET_VAL(CPLUnlinkTree(osEditedName));
     CPLPopErrorHandler();
 
     OGRErr eErr = OGRERR_NONE;
+    
     CPLString osDatabaseToReopen;
-    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE1") ||
-        CPLCopyTree( osEditedName, osName ) != 0 )
+#ifndef WIN32
+    if( bPerLayerCopyingForTransaction )
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Cannot backup geodatabase");
-        eErr = OGRERR_FAILURE;
-        osDatabaseToReopen = osName;
+        int bError = FALSE;
+        
+        if( VSIMkdir( osEditedName, 0755 ) != 0 )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, 
+                      "Cannot create directory '%s'.",
+                      osEditedName.c_str() );
+            bError = TRUE;
+        }
+
+        // Only copy a0000000X.Y files with X >= 1 && X <= 8, gdb and timestamps
+        // and symlink others
+        char** papszFiles = VSIReadDir(osName);
+        for(char** papszIter = papszFiles; !bError && *papszIter; ++papszIter)
+        {
+            if( strcmp(*papszIter, ".") == 0 || strcmp(*papszIter, "..") == 0 )
+                continue;
+            if( ((*papszIter)[0] == 'a' && atoi((*papszIter)+1) >= 1 &&
+                 atoi((*papszIter)+1) <= 8) || EQUAL(*papszIter, "gdb") ||
+                 EQUAL(*papszIter, "timestamps") )
+            {
+                if( CPLCopyFile(CPLFormFilename(osEditedName, *papszIter, NULL),
+                                CPLFormFilename(osName, *papszIter, NULL)) != 0 )
+                {
+                    bError = TRUE;
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Cannot copy %s", *papszIter);
+                }
+            }
+            else
+            {
+                CPLString osSourceFile;
+                if( CPLIsFilenameRelative(osName) )
+                    osSourceFile = CPLFormFilename(CPLSPrintf("../%s", CPLGetFilename(osName.c_str())), *papszIter, NULL);
+                else
+                    osSourceFile = osName;
+                if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE1") ||
+                    CPLSymlink( osSourceFile,
+                                CPLFormFilename(osEditedName.c_str(), *papszIter, NULL),
+                                NULL ) != 0 )
+                {
+                    bError = TRUE;
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Cannot symlink %s", *papszIter);
+                }
+            }
+        }
+        CSLDestroy(papszFiles);
+
+        if( bError )
+        {
+            eErr = OGRERR_FAILURE;
+            osDatabaseToReopen = osName;
+        }
+        else
+            osDatabaseToReopen = osEditedName;
     }
     else
-        osDatabaseToReopen = osEditedName;
+#endif
+    {
+        if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE1") ||
+            CPLCopyTree( osEditedName, osName ) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                    "Cannot backup geodatabase");
+            eErr = OGRERR_FAILURE;
+            osDatabaseToReopen = osName;
+        }
+        else
+            osDatabaseToReopen = osEditedName;
+    }
 
     pConnection->m_pGeodatabase = new Geodatabase;
     long hr = ::OpenGeodatabase(StringToWString(osDatabaseToReopen), *(pConnection->m_pGeodatabase));
@@ -312,7 +385,16 @@ OGRErr FGdbDriver::StartTransaction(OGRDataSource*& poDSInOut, int& bOutHasReope
     }
 
     FGdbDataSource* pDS = new FGdbDataSource(this, pConnection);
-    pDS->Open(osName, TRUE);
+    pDS->Open(osDatabaseToReopen, TRUE, osNameOri);
+
+#ifndef WIN32
+    if( eErr == OGRERR_NONE && bPerLayerCopyingForTransaction )
+    {
+        pDS->SetPerLayerCopyingForTransaction(bPerLayerCopyingForTransaction);
+        pDS->SetSymlinkFlagOnAllLayers();
+    }
+#endif
+
     poDSInOut = new OGRMutexedDataSource(pDS, TRUE, hMutex, TRUE);
 
     if( eErr == OGRERR_NONE )
@@ -344,63 +426,186 @@ OGRErr FGdbDriver::CommitTransaction(OGRDataSource*& poDSInOut, int& bOutHasReop
     bOutHasReopenedDS = TRUE;
 
     CPLString osName(poMutexedDS->GetName());
+    CPLString osNameOri(osName);
     if( osName[osName.size()-1] == '/' || osName[osName.size()-1] == '\\' )
         osName.resize(osName.size()-1);
 
+#ifndef WIN32
+    int bPerLayerCopyingForTransaction = poDS->HasPerLayerCopyingForTransaction();
+#endif
+
     pConnection->m_nRefCount ++;
     delete poDSInOut;
     poDSInOut = NULL;
     poMutexedDS = NULL;
     poDS = NULL;
 
-    ::CloseGeodatabase(*(pConnection->m_pGeodatabase));
-    delete pConnection->m_pGeodatabase;
-    pConnection->m_pGeodatabase = NULL;
+    pConnection->CloseGeodatabase();
 
     CPLString osEditedName(osName);
     osEditedName += ".ogredited";
-    CPLString osTmpName(osName);
-    osTmpName += ".ogrtmp";
     
-    /* Install the backup copy as the main database in 3 steps : */
-    /* first rename the main directory  in .tmp */
-    /* then rename the edited copy under regular name */
-    /* and finally dispose the .tmp directory */
-    /* That way there's no risk definitely losing data */
-    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE1") || 
-        VSIRename(osName, osTmpName) != 0 )
+#ifndef WIN32
+    if( bPerLayerCopyingForTransaction )
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Cannot rename %s to %s. Edited database during transaction is in %s"
-                 "Dataset should be closed",
-                 osName.c_str(), osTmpName.c_str(), osEditedName.c_str());
-        pConnection->SetLocked(FALSE);
-        Release(osName);
-        return OGRERR_FAILURE;
+        int bError = FALSE;
+        char** papszFiles;
+        std::vector<CPLString> aosTmpFilesToClean;
+        
+        // Check for files present in original copy that are not in edited copy
+        // That is to say deleted layers
+        papszFiles = VSIReadDir(osName);
+        for(char** papszIter = papszFiles; !bError && *papszIter; ++papszIter)
+        {
+            if( strcmp(*papszIter, ".") == 0 || strcmp(*papszIter, "..") == 0 )
+                continue;
+            VSIStatBufL sStat;
+            if( (*papszIter)[0] == 'a' &&
+                VSIStatL( CPLFormFilename(osEditedName, *papszIter, NULL), &sStat ) != 0 )
+            {
+                if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE1") || 
+                    VSIRename( CPLFormFilename(osName, *papszIter, NULL),
+                               CPLFormFilename(osName, *papszIter, "tmp") ) != 0 )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined, "Cannot rename %s to %s",
+                             CPLFormFilename(osName, *papszIter, NULL),
+                             CPLFormFilename(osName, *papszIter, "tmp"));
+                    bError = TRUE;
+                }
+                else
+                    aosTmpFilesToClean.push_back(CPLFormFilename(osName, *papszIter, "tmp"));
+            }
+        }
+        CSLDestroy(papszFiles);
+
+        // Move modified files from edited directory to main directory
+        papszFiles = VSIReadDir(osEditedName);
+        for(char** papszIter = papszFiles; !bError && *papszIter; ++papszIter)
+        {
+            if( strcmp(*papszIter, ".") == 0 || strcmp(*papszIter, "..") == 0 )
+                continue;
+            struct stat sStat;
+            if( lstat( CPLFormFilename(osEditedName, *papszIter, NULL), &sStat ) != 0 )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "Cannot stat %s",
+                         CPLFormFilename(osEditedName, *papszIter, NULL));
+                bError = TRUE;
+            }
+            else if( !S_ISLNK(sStat.st_mode) )
+            {
+                // If there was such a file in original directory, first rename it
+                // as a temporary file
+                if( lstat( CPLFormFilename(osName, *papszIter, NULL), &sStat ) == 0 )
+                {
+                    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE2") || 
+                        VSIRename( CPLFormFilename(osName, *papszIter, NULL),
+                                   CPLFormFilename(osName, *papszIter, "tmp") ) != 0 )
+                    {
+                        CPLError(CE_Failure, CPLE_AppDefined, "Cannot rename %s to %s",
+                                 CPLFormFilename(osName, *papszIter, NULL),
+                                 CPLFormFilename(osName, *papszIter, "tmp"));
+                        bError = TRUE;
+                    }
+                    else
+                        aosTmpFilesToClean.push_back(CPLFormFilename(osName, *papszIter, "tmp"));
+                }
+                if( !bError )
+                {
+                    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE3") || 
+                        CPLMoveFile( CPLFormFilename(osName, *papszIter, NULL),
+                                     CPLFormFilename(osEditedName, *papszIter, NULL) ) != 0 )
+                    {
+                        CPLError(CE_Failure, CPLE_AppDefined, "Cannot move %s to %s",
+                                 CPLFormFilename(osEditedName, *papszIter, NULL),
+                                 CPLFormFilename(osName, *papszIter, NULL));
+                        bError = TRUE;
+                    }
+                    else
+                        CPLDebug("FileGDB", "Move %s to %s",
+                                 CPLFormFilename(osEditedName, *papszIter, NULL),
+                                 CPLFormFilename(osName, *papszIter, NULL));
+                }
+            }
+        }
+        CSLDestroy(papszFiles);
+
+        if( !bError )
+        {
+            for(size_t i=0;i<aosTmpFilesToClean.size();i++)
+            {
+                if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE4") || 
+                    VSIUnlink(aosTmpFilesToClean[i]) != 0 )
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "Cannot remove %s. Manual cleanup required", aosTmpFilesToClean[i].c_str());
+                }
+            }
+        }
+
+        if( bError )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "An error occurred while moving files from %s back to %s. "
+                     "Manual cleaning must be done and dataset should be closed",
+                     osEditedName.c_str(),
+                     osName.c_str());
+            pConnection->SetLocked(FALSE);
+            Release(osName);
+            return OGRERR_FAILURE;
+        }
+        else if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE5") || 
+                 CPLUnlinkTree(osEditedName) != 0 )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                    "Cannot remove %s. Manual cleanup required", osEditedName.c_str());
+        }
     }
-    
-    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE2") || 
-        VSIRename(osEditedName, osName) != 0 )
+    else
+#endif
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Cannot rename %s to %s. The original geodatabase is in '%s'. "
-                 "Dataset should be closed",
-                 osEditedName.c_str(), osName.c_str(), osTmpName.c_str());
-        pConnection->SetLocked(FALSE);
-        Release(osName);
-        return OGRERR_FAILURE;
-    }
+        CPLString osTmpName(osName);
+        osTmpName += ".ogrtmp";
+        
+        /* Install the backup copy as the main database in 3 steps : */
+        /* first rename the main directory  in .tmp */
+        /* then rename the edited copy under regular name */
+        /* and finally dispose the .tmp directory */
+        /* That way there's no risk definitely losing data */
+        if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE1") || 
+            VSIRename(osName, osTmpName) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                    "Cannot rename %s to %s. Edited database during transaction is in %s"
+                    "Dataset should be closed",
+                    osName.c_str(), osTmpName.c_str(), osEditedName.c_str());
+            pConnection->SetLocked(FALSE);
+            Release(osName);
+            return OGRERR_FAILURE;
+        }
+        
+        if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE2") || 
+            VSIRename(osEditedName, osName) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                    "Cannot rename %s to %s. The original geodatabase is in '%s'. "
+                    "Dataset should be closed",
+                    osEditedName.c_str(), osName.c_str(), osTmpName.c_str());
+            pConnection->SetLocked(FALSE);
+            Release(osName);
+            return OGRERR_FAILURE;
+        }
 
-    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE3") || 
-        CPLUnlinkTree(osTmpName) != 0 )
-    {
-        CPLError(CE_Warning, CPLE_AppDefined,
-                 "Cannot remove %s. Manual cleanup required", osTmpName.c_str());
+        if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE3") || 
+            CPLUnlinkTree(osTmpName) != 0 )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                    "Cannot remove %s. Manual cleanup required", osTmpName.c_str());
+        }
     }
 
     pConnection->m_pGeodatabase = new Geodatabase;
     long hr = ::OpenGeodatabase(StringToWString(osName), *(pConnection->m_pGeodatabase));
-    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE4") || FAILED(hr))
+    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE_REOPEN") || FAILED(hr))
     {
         delete pConnection->m_pGeodatabase;
         pConnection->m_pGeodatabase = NULL;
@@ -411,7 +616,8 @@ OGRErr FGdbDriver::CommitTransaction(OGRDataSource*& poDSInOut, int& bOutHasReop
     }
 
     FGdbDataSource* pDS = new FGdbDataSource(this, pConnection);
-    pDS->Open(osName, TRUE);
+    pDS->Open(osNameOri, TRUE, NULL);
+    //pDS->SetPerLayerCopyingForTransaction(bPerLayerCopyingForTransaction);
     poDSInOut = new OGRMutexedDataSource(pDS, TRUE, hMutex, TRUE);
 
     pConnection->SetLocked(FALSE);
@@ -442,18 +648,19 @@ OGRErr FGdbDriver::RollbackTransaction(OGRDataSource*& poDSInOut, int& bOutHasRe
     bOutHasReopenedDS = TRUE;
 
     CPLString osName(poMutexedDS->GetName());
+    CPLString osNameOri(osName);
     if( osName[osName.size()-1] == '/' || osName[osName.size()-1] == '\\' )
         osName.resize(osName.size()-1);
 
+    //int bPerLayerCopyingForTransaction = poDS->HasPerLayerCopyingForTransaction();
+
     pConnection->m_nRefCount ++;
     delete poDSInOut;
     poDSInOut = NULL;
     poMutexedDS = NULL;
     poDS = NULL;
 
-    ::CloseGeodatabase(*(pConnection->m_pGeodatabase));
-    delete pConnection->m_pGeodatabase;
-    pConnection->m_pGeodatabase = NULL;
+    pConnection->CloseGeodatabase();
 
     CPLString osEditedName(osName);
     osEditedName += ".ogredited";
@@ -481,7 +688,8 @@ OGRErr FGdbDriver::RollbackTransaction(OGRDataSource*& poDSInOut, int& bOutHasRe
     }
 
     FGdbDataSource* pDS = new FGdbDataSource(this, pConnection);
-    pDS->Open(osName, TRUE);
+    pDS->Open(osNameOri, TRUE, NULL);
+    //pDS->SetPerLayerCopyingForTransaction(bPerLayerCopyingForTransaction);
     poDSInOut = new OGRMutexedDataSource(pDS, TRUE, hMutex, TRUE);
 
     pConnection->SetLocked(FALSE);
@@ -505,13 +713,7 @@ void FGdbDriver::Release(const char* pszName)
                  pConnection->m_nRefCount);
         if( pConnection->m_nRefCount == 0 )
         {
-            if( pConnection->m_pGeodatabase != NULL )
-            {
-                CPLDebug("FileGDB", "Really closing %s now", pszName);
-                ::CloseGeodatabase(*(pConnection->m_pGeodatabase));
-                delete pConnection->m_pGeodatabase;
-                pConnection->m_pGeodatabase = NULL;
-            }
+            pConnection->CloseGeodatabase();
             delete pConnection;
             oMapConnections.erase(pszName);
         }
@@ -519,6 +721,38 @@ void FGdbDriver::Release(const char* pszName)
 }
 
 /***********************************************************************/
+/*                         CloseGeodatabase()                          */
+/***********************************************************************/
+
+void FGdbDatabaseConnection::CloseGeodatabase()
+{
+    if( m_pGeodatabase != NULL )
+    {
+        CPLDebug("FileGDB", "Really closing %s now", m_osName.c_str());
+        ::CloseGeodatabase(*m_pGeodatabase);
+        delete m_pGeodatabase;
+        m_pGeodatabase = NULL;
+    }
+}
+
+/***********************************************************************/
+/*                         OpenGeodatabase()                           */
+/***********************************************************************/
+
+int FGdbDatabaseConnection::OpenGeodatabase(const char* pszFSName)
+{
+    m_pGeodatabase = new Geodatabase;
+    long hr = ::OpenGeodatabase(StringToWString(CPLString(pszFSName)), *m_pGeodatabase);
+    if (FAILED(hr))
+    {
+        delete m_pGeodatabase;
+        m_pGeodatabase = NULL;
+        return FALSE;
+    }
+    return TRUE;
+}
+
+/***********************************************************************/
 /*                         TestCapability()                            */
 /***********************************************************************/
 
@@ -562,14 +796,15 @@ void RegisterOGRFileGDB()
 {
     if (! GDAL_CHECK_VERSION("OGR FGDB"))
         return;
+
     OGRSFDriver* poDriver = new FGdbDriver;
     poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
                                 "ESRI FileGDB" );
     poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gdb" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                "drv_filegdb.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_filegdb.html" );
 
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, "<CreationOptionList/>" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+                               "<CreationOptionList/>" );
 
     poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
 "<LayerCreationOptionList>"
@@ -597,8 +832,9 @@ void RegisterOGRFileGDB()
 "    <Value>GEOMETRY_AND_BLOB_OUTOFLINE</Value>"
 "  </Option>"
 "</LayerCreationOptionList>");
-    
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES, "Integer Real String Date DateTime Binary" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
+                               "Integer Real String Date DateTime Binary" );
     poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_FIELDS, "YES" );
     poDriver->SetMetadataItem( GDAL_DCAP_DEFAULT_FIELDS, "YES" );
     poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_GEOMFIELDS, "YES" );
diff --git a/ogr/ogrsf_frmts/filegdb/FGdbLayer.cpp b/ogr/ogrsf_frmts/filegdb/FGdbLayer.cpp
index e68936b..d1ac7c8 100644
--- a/ogr/ogrsf_frmts/filegdb/FGdbLayer.cpp
+++ b/ogr/ogrsf_frmts/filegdb/FGdbLayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
-* $Id: FGdbLayer.cpp 29330 2015-06-14 12:11:11Z rouault $
+* $Id: FGdbLayer.cpp 33563 2016-02-26 14:57:06Z rouault $
 *
 * Project:  OpenGIS Simple Features Reference Implementation
 * Purpose:  Implements FileGDB OGR layer.
@@ -37,7 +37,7 @@
 #include "FGdbUtils.h"
 #include "cpl_minixml.h" // the only way right now to extract schema information
 
-CPL_CVSID("$Id: FGdbLayer.cpp 29330 2015-06-14 12:11:11Z rouault $");
+CPL_CVSID("$Id: FGdbLayer.cpp 33563 2016-02-26 14:57:06Z rouault $");
 
 using std::string;
 using std::wstring;
@@ -62,11 +62,7 @@ FGdbBaseLayer::~FGdbBaseLayer()
         m_pFeatureDefn = NULL;
     }
 
-    if (m_pEnumRows)
-    {
-        delete m_pEnumRows;
-        m_pEnumRows = NULL;
-    }
+    CloseGDBObjects();
 
     if (m_pSRS)
     {
@@ -76,6 +72,19 @@ FGdbBaseLayer::~FGdbBaseLayer()
 }
 
 /************************************************************************/
+/*                          CloseGDBObjects()                           */
+/************************************************************************/
+
+void FGdbBaseLayer::CloseGDBObjects()
+{
+    if (m_pEnumRows)
+    {
+        delete m_pEnumRows;
+        m_pEnumRows = NULL;
+    }
+}
+
+/************************************************************************/
 /*                           GetNextFeature()                           */
 /************************************************************************/
 
@@ -98,7 +107,7 @@ OGRFeature* FGdbBaseLayer::GetNextFeature()
 
         if (hr != S_OK)
         {
-        // It's OK, we are done fetching - failure is catched by FAILED macro
+        // It's OK, we are done fetching - failure is caught by FAILED macro
             return NULL;
         }
 
@@ -137,6 +146,8 @@ FGdbLayer::FGdbLayer():
 #endif
     m_papszOptions = NULL;
     m_bCreateMultipatch = FALSE;
+    m_nResyncThreshold = atoi(CPLGetConfigOption("FGDB_RESYNC_THRESHOLD", "1000000"));
+    m_bSymlinkFlag = FALSE;
 }
 
 /************************************************************************/
@@ -145,31 +156,719 @@ FGdbLayer::FGdbLayer():
 
 FGdbLayer::~FGdbLayer()
 {
+    CloseGDBObjects();
+
+    if (m_pOGRFilterGeometry)
+    {
+        OGRGeometryFactory::destroyGeometry(m_pOGRFilterGeometry);
+        m_pOGRFilterGeometry = NULL;
+    }
+    
+    for(size_t i = 0; i < m_apoByteArrays.size(); i++ )
+        delete m_apoByteArrays[i];
+    m_apoByteArrays.resize(0);
+
+    CSLDestroy(m_papszOptions);
+    m_papszOptions = NULL;
+    
+}
+
+/************************************************************************/
+/*                        CloseGDBObjects()                             */
+/************************************************************************/
+
+void FGdbLayer::CloseGDBObjects()
+{
     EndBulkLoad();
 
 #ifdef EXTENT_WORKAROUND
     WorkAroundExtentProblem();
 #endif
 
-    // NOTE: never delete m_pDS - the memory doesn't belong to us
-    // TODO: check if we need to close the table or if the destructor 
-    // takes care of closing as it should
     if (m_pTable)
     {
         delete m_pTable;
         m_pTable = NULL;
     }
 
-    if (m_pOGRFilterGeometry)
+    FGdbBaseLayer::CloseGDBObjects();
+}
+
+/************************************************************************/
+/*                     EditIndexesForFIDHack()                          */
+/************************************************************************/
+
+int FGdbLayer::EditIndexesForFIDHack(const char* pszRadixTablename)
+{
+    // Fix FIDs in .gdbtablx, .spx and .atx's
+
+    CPLString osGDBTablX = CPLResetExtension(pszRadixTablename, "gdbtablx");
+    CPLString osNewGDBTablX = CPLResetExtension(pszRadixTablename, "gdbtablx.new");
+
+    if( !EditGDBTablX(osGDBTablX, osNewGDBTablX) )
     {
-        OGRGeometryFactory::destroyGeometry(m_pOGRFilterGeometry);
-        m_pOGRFilterGeometry = NULL;
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Error occurred when editing %s", osNewGDBTablX.c_str());
+        VSIUnlink(osNewGDBTablX);
+        return FALSE;
+    }
+
+    CPLString osDirectory(CPLGetPath(pszRadixTablename));;
+    char** papszFiles = VSIReadDir(osDirectory);
+    CPLString osBasename(CPLGetBasename(pszRadixTablename));
+    int bRet = TRUE;
+    for(char** papszIter = papszFiles; papszIter && *papszIter; papszIter++)
+    {
+        if( strncmp(*papszIter, osBasename.c_str(), osBasename.size()) == 0 &&
+            (EQUAL(CPLGetExtension(*papszIter), "atx") ||
+             EQUAL(CPLGetExtension(*papszIter), "spx")) )
+        {
+            CPLString osIndex(CPLFormFilename(osDirectory, *papszIter, NULL));
+            if( !EditATXOrSPX(osIndex) )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Error occurred when editing %s", osIndex.c_str());
+                bRet = FALSE;
+            }
+        }
+    }
+    CSLDestroy(papszFiles);
+
+    CPLString osGDBTablXTmp(CPLSPrintf("%s.tmp", osGDBTablX.c_str()));
+    int bRet2 = (VSIRename(osGDBTablX,osGDBTablXTmp) == 0 &&
+                 VSIRename(osNewGDBTablX, osGDBTablX) == 0);
+    VSIUnlink(osGDBTablXTmp);
+    if( !bRet2 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot rename %s to %s", osNewGDBTablX.c_str(), osGDBTablX.c_str());
+        bRet = FALSE;
+    }
+
+    return bRet;
+}
+
+/************************************************************************/
+/*                           EditATXOrSPX()                             */
+/************************************************************************/
+
+/* See https://github.com/rouault/dump_gdbtable/wiki/FGDB-Spec */
+int FGdbLayer::EditATXOrSPX( const CPLString& osIndex )
+{
+    VSILFILE* fp = VSIFOpenL(osIndex, "rb+");
+    if (fp == NULL )
+    {
+        CPLError(CE_Failure, CPLE_FileIO, "Cannot open %s", osIndex.c_str());
+        return FALSE;
+    }
+    VSIFSeekL(fp, 0, SEEK_END);
+    vsi_l_offset nPos = VSIFTellL(fp);
+    int bRet = FALSE;
+    int bInvalidateIndex = FALSE;
+    if( nPos > 22 )
+    {
+        VSIFSeekL(fp, nPos - 22, SEEK_SET);
+        GByte nSizeIndexedValue;
+        if( VSIFReadL(&nSizeIndexedValue, 1, 1, fp) == 1 &&
+            nSizeIndexedValue > 0 )
+        {
+            GByte abyIndexedValue[255];
+            VSIFSeekL(fp, nPos - 22 + 6, SEEK_SET);
+            int nDepth;
+            if( VSIFReadL(&nDepth, 1, 4, fp) == 4 )
+            {
+                nDepth = CPL_LSBWORD32(nDepth);
+
+                int bIndexedValueIsValid = FALSE;
+                int nFirstIndexAtThisValue = -1;
+                std::vector<int> anPagesAtThisValue;
+                int bSortThisValue = FALSE;
+                int nLastPageVisited = 0;
+                bRet = EditATXOrSPX(fp,
+                                    1,
+                                    nLastPageVisited,
+                                    nDepth,
+                                    nSizeIndexedValue,
+                                    abyIndexedValue,
+                                    bIndexedValueIsValid,
+                                    nFirstIndexAtThisValue,
+                                    anPagesAtThisValue,
+                                    bSortThisValue,
+                                    bInvalidateIndex);
+            }
+        }
+    }
+    VSIFCloseL(fp);
+    if( bInvalidateIndex )
+    {
+        //CPLDebug("FGDB", "Invalidate %s", osIndex.c_str());
+        CPLError(CE_Warning, CPLE_AppDefined, "Invalidate %s", osIndex.c_str());
+        VSIUnlink(osIndex);
     }
+    return bRet;
+}
+
+static int FGdbLayerSortATX(const void* _pa, const void* _pb)
+{
+    int a = CPL_LSBWORD32(*(int*)_pa);
+    int b = CPL_LSBWORD32(*(int*)_pb);
+    if( a < b )
+        return -1;
+    else if( a > b )
+        return 1;
+    CPLAssert(FALSE);
+    return 0;
+}
+
+int FGdbLayer::EditATXOrSPX(VSILFILE* fp,
+                            int nThisPage,
+                            int& nLastPageVisited,
+                            int nDepth,
+                            int nSizeIndexedValue,
+                            GByte* pabyLastIndexedValue,
+                            int& bIndexedValueIsValid,
+                            int& nFirstIndexAtThisValue,
+                            std::vector<int>& anPagesAtThisValue,
+                            int& bSortThisValue,
+                            int& bInvalidateIndex)
+{
+    GByte abyBuffer[4096];
     
-    for(size_t i = 0; i < m_apoByteArrays.size(); i++ )
-        delete m_apoByteArrays[i];
+    VSIFSeekL(fp, (nThisPage - 1) * 4096, SEEK_SET);
+
+    if( nDepth == 1 )
+    {
+        if( nThisPage == nLastPageVisited )
+            return TRUE;
+
+        /* This page directly references features */
+        int bRewritePage = FALSE;
+        if( VSIFReadL(abyBuffer, 1, 4096, fp) != 4096 )
+            return FALSE;
+        int nNextPageID;
+        memcpy(&nNextPageID, abyBuffer, 4);
+        int nFeatures;
+        memcpy(&nFeatures, abyBuffer + 4, 4);
+        nFeatures = CPL_LSBWORD32(nFeatures);
+        
+        //if( nLastPageVisited == 0 )
+        //    printf("nFeatures = %d\n", nFeatures);
+        
+        const int nMaxPerPages = (4096 - 12) / (4 + nSizeIndexedValue);
+        const int nOffsetFirstValInPage = 12 + nMaxPerPages * 4;
+        if( nFeatures > nMaxPerPages )
+            return FALSE;
+        for(int i=0; i < nFeatures; i++)
+        {
+            int bNewVal = ( !bIndexedValueIsValid ||
+                            memcmp(pabyLastIndexedValue,
+                                   abyBuffer + nOffsetFirstValInPage + i * nSizeIndexedValue,
+                                   nSizeIndexedValue) != 0 );
+
+            int nFID;
+            memcpy(&nFID, abyBuffer + 12 + 4 * i, 4);
+            nFID = CPL_LSBWORD32(nFID);
+            int nOGRFID = m_oMapFGDBFIDToOGRFID[nFID];
+            if( nOGRFID )
+            {
+                nFID = nOGRFID;
+                nOGRFID = CPL_LSBWORD32(nOGRFID);
+                memcpy(abyBuffer + 12 + 4 * i, &nOGRFID, 4);
+                bRewritePage = TRUE;
+                
+                if( bIndexedValueIsValid && i == nFeatures - 1 && nNextPageID == 0 )
+                    bSortThisValue = TRUE;
+            }
+             
+            // We must make sure that features with same indexed values are
+            // sorted by increasing FID, even when that spans over several
+            // pages           
+            if( bSortThisValue && (bNewVal || (i == nFeatures - 1 && nNextPageID == 0)) )
+            {
+                if( anPagesAtThisValue[0] == nThisPage )
+                {
+                    CPLAssert(anPagesAtThisValue.size() == 1);
+                    int nFeaturesToSortThisPage = i - nFirstIndexAtThisValue;
+                    if( !bNewVal && i == nFeatures - 1 && nNextPageID == 0 )
+                        nFeaturesToSortThisPage ++;
+                    CPLAssert(nFeaturesToSortThisPage > 0);
+                    
+                    bRewritePage = TRUE;
+                    qsort(abyBuffer + 12 + 4 * nFirstIndexAtThisValue,
+                          nFeaturesToSortThisPage, 4, FGdbLayerSortATX);
+                }
+                else
+                {
+                    std::vector<int> anValues;
+                    int nFeaturesToSort = 0;
+                    anValues.resize(anPagesAtThisValue.size() * nMaxPerPages);
+                    
+                    int nFeaturesToSortLastPage = i;
+                    if( !bNewVal && i == nFeatures - 1 && nNextPageID == 0 )
+                        nFeaturesToSortLastPage ++;
+                    
+                    for(size_t j=0;j<anPagesAtThisValue.size();j++)
+                    {
+                        int nFeaturesPrevPage;
+                        VSIFSeekL(fp, (anPagesAtThisValue[j]-1) * 4096 + 4, SEEK_SET);
+                        VSIFReadL(&nFeaturesPrevPage, 1, 4, fp);
+                        nFeaturesPrevPage = CPL_LSBWORD32(nFeaturesPrevPage);
+                        if( j == 0 )
+                        {
+                            VSIFSeekL(fp, (anPagesAtThisValue[j]-1) * 4096 + 12 + 4 * nFirstIndexAtThisValue, SEEK_SET);
+                            VSIFReadL(&anValues[nFeaturesToSort], 4, nFeaturesPrevPage - nFirstIndexAtThisValue, fp);
+                            nFeaturesToSort += nFeaturesPrevPage - nFirstIndexAtThisValue;
+                        }
+                        else if( j == anPagesAtThisValue.size() - 1 && anPagesAtThisValue[j] == nThisPage )
+                        {
+                            bRewritePage = TRUE;
+                            memcpy(&anValues[nFeaturesToSort], abyBuffer + 12, nFeaturesToSortLastPage * 4);
+                            nFeaturesToSort += nFeaturesToSortLastPage;
+                        }
+                        else
+                        {
+                            VSIFSeekL(fp, (anPagesAtThisValue[j]-1) * 4096 + 12, SEEK_SET);
+                            VSIFReadL(&anValues[nFeaturesToSort], 4, nFeaturesPrevPage, fp);
+                            nFeaturesToSort += nFeaturesPrevPage;
+                        }
+                    }
 
-    CSLDestroy(m_papszOptions);
+                    qsort(&anValues[0], nFeaturesToSort, 4, FGdbLayerSortATX);
+                    
+                    nFeaturesToSort = 0;
+                    for(size_t j=0;j<anPagesAtThisValue.size();j++)
+                    {
+                        int nFeaturesPrevPage;
+                        VSIFSeekL(fp, (anPagesAtThisValue[j]-1) * 4096 + 4, SEEK_SET);
+                        VSIFReadL(&nFeaturesPrevPage, 1, 4, fp);
+                        nFeaturesPrevPage = CPL_LSBWORD32(nFeaturesPrevPage);
+                        if( j == 0 )
+                        {
+                            VSIFSeekL(fp, (anPagesAtThisValue[j]-1) * 4096 + 12 + 4 * nFirstIndexAtThisValue, SEEK_SET);
+                            VSIFWriteL(&anValues[nFeaturesToSort], 4, nFeaturesPrevPage - nFirstIndexAtThisValue, fp);
+                            nFeaturesToSort += nFeaturesPrevPage - nFirstIndexAtThisValue;
+                        }
+                        else if( j == anPagesAtThisValue.size() - 1 && anPagesAtThisValue[j] == nThisPage )
+                        {
+                            memcpy(abyBuffer + 12, &anValues[nFeaturesToSort], nFeaturesToSortLastPage * 4);
+                            nFeaturesToSort += nFeaturesToSortLastPage;
+                        }
+                        else
+                        {
+                            VSIFSeekL(fp, (anPagesAtThisValue[j]-1) * 4096 + 12, SEEK_SET);
+                            VSIFWriteL(&anValues[nFeaturesToSort], 4, nFeaturesPrevPage, fp);
+                            nFeaturesToSort += nFeaturesPrevPage;
+                        }
+                    }
+                }
+            }
+            
+            if( bNewVal )
+            {
+                nFirstIndexAtThisValue = i;
+                anPagesAtThisValue.clear();
+                anPagesAtThisValue.push_back(nThisPage);
+                
+                memcpy(pabyLastIndexedValue,
+                       abyBuffer + nOffsetFirstValInPage + i * nSizeIndexedValue,
+                       nSizeIndexedValue);
+                bSortThisValue = FALSE;
+            }
+            else if( i == 0 )
+            {
+                if( anPagesAtThisValue.size() > 100000 )
+                {
+                    bInvalidateIndex = TRUE;
+                    return FALSE;
+                }
+                else
+                {
+                    anPagesAtThisValue.push_back(nThisPage);
+                }
+            }
+
+            if( nOGRFID )
+                bSortThisValue = TRUE;
+
+            bIndexedValueIsValid = TRUE;
+        }
+        
+        if( bRewritePage )
+        {
+            VSIFSeekL(fp, (nThisPage - 1) * 4096, SEEK_SET);
+            if( VSIFWriteL(abyBuffer, 1, 4096, fp) != 4096 )
+                return FALSE;
+        }
+        
+        nLastPageVisited = nThisPage;
+
+        return TRUE;
+    }
+    else
+    {
+        /* This page references other pages */
+        if( VSIFReadL(abyBuffer, 1, 4096, fp) != 4096 )
+            return FALSE;
+        int nSubPages;
+        memcpy(&nSubPages, abyBuffer + 4, 4);
+        nSubPages = CPL_LSBWORD32(nSubPages);
+        nSubPages ++;
+        if( nSubPages > (4096 - 8) / 4 )
+            return FALSE;
+        for(int i=0; i < nSubPages; i++)
+        {
+            int nSubPageID;
+            memcpy(&nSubPageID, abyBuffer + 8 + 4 * i, 4);
+            nSubPageID = CPL_LSBWORD32(nSubPageID);
+            if( nSubPageID < 1 )
+                return FALSE;
+            if( !EditATXOrSPX(fp,
+                              nSubPageID,
+                              nLastPageVisited,
+                              nDepth - 1,
+                              nSizeIndexedValue,
+                              pabyLastIndexedValue,
+                              bIndexedValueIsValid,
+                              nFirstIndexAtThisValue,
+                              anPagesAtThisValue,
+                              bSortThisValue,
+                              bInvalidateIndex) )
+            {
+                return FALSE;
+            }
+        }
+        
+        return TRUE;
+    }
+}
+
+/************************************************************************/
+/*                              GetInt32()                              */
+/************************************************************************/
+
+static GInt32 GetInt32(const GByte* pBaseAddr, int iOffset)
+{
+    GInt32 nVal;
+    memcpy(&nVal, pBaseAddr + sizeof(nVal) * iOffset, sizeof(nVal));
+    CPL_LSBPTR32(&nVal);
+    return nVal;
+}
+
+/************************************************************************/
+/*                     UpdateNextOGRFIDAndFGDBFID()                     */
+/************************************************************************/
+
+static CPL_INLINE void UpdateNextOGRFIDAndFGDBFID(int i,
+                                       std::map<int,int>& oMapOGRFIDToFGDBFID,
+                                       std::map<int,int>::iterator& oIterO2F,
+                                       int& nNextOGRFID,
+                                       std::map<int,int>& oMapFGDBFIDToOGRFID,
+                                       std::map<int,int>::iterator& oIterF2O,
+                                       int& nNextFGDBFID)
+{
+    while( nNextOGRFID > 0 && i > nNextOGRFID )
+    {
+        ++ oIterO2F;
+        if( oIterO2F == oMapOGRFIDToFGDBFID.end() )
+            nNextOGRFID = -1;
+        else
+            nNextOGRFID = oIterO2F->first;
+    }
+
+    while( nNextFGDBFID > 0 && i > nNextFGDBFID )
+    {
+        ++ oIterF2O;
+        if( oIterF2O == oMapFGDBFIDToOGRFID.end() )
+            nNextFGDBFID = -1;
+        else
+            nNextFGDBFID = oIterF2O->first;
+    }
+}
+
+/************************************************************************/
+/*                          EditGDBTablX()                              */
+/************************************************************************/
+
+#define TEST_BIT(ar, bit)                       (ar[(bit) / 8] & (1 << ((bit) % 8)))
+#define SET_BIT(ar,bit)                         ar[(bit)/8] |= (1 << ((bit) % 8))
+#define BIT_ARRAY_SIZE_IN_BYTES(bitsize)        (((bitsize)+7)/8)
+
+/* See https://github.com/rouault/dump_gdbtable/wiki/FGDB-Spec */
+int  FGdbLayer::EditGDBTablX( const CPLString& osGDBTablX,
+                              const CPLString& osNewGDBTablX )
+{
+    VSILFILE* fp = VSIFOpenL(osGDBTablX, "rb");
+    if (fp == NULL )
+    {
+        CPLError(CE_Failure, CPLE_FileIO, "Cannot open %s", osGDBTablX.c_str());
+        return FALSE;
+    }
+    VSILFILE* fpNew = VSIFOpenL(osNewGDBTablX, "wb");
+    if (fpNew == NULL )
+    {
+        CPLError(CE_Failure, CPLE_FileIO, "Cannot create %s", osNewGDBTablX.c_str());
+        VSIFCloseL(fp);
+        return FALSE;
+    }
+    GByte abyBuffer[16];
+    VSIFReadL(abyBuffer, 1, 16, fp);
+    int n1024Blocks = GetInt32(abyBuffer, 1);
+    int nInMaxFID = GetInt32(abyBuffer, 2);
+#ifdef DEBUG
+    const int nInMaxFIDOri = nInMaxFID;
+#endif
+    int nRecordSize = GetInt32(abyBuffer, 3);
+    CPLAssert(nRecordSize >= 4 && nRecordSize <= 6);
+
+    std::map<int,int>::iterator oIterO2F = m_oMapOGRFIDToFGDBFID.begin();
+    int nMaxOGRFID = 0;
+    for(; oIterO2F != m_oMapOGRFIDToFGDBFID.end(); ++oIterO2F )
+        nMaxOGRFID = oIterO2F->first;
+    //printf("nInMaxFID = %d\n", nInMaxFID);
+    //printf("nMaxOGRFID = %d\n", nMaxOGRFID);
+    int nOutMaxFID = MAX(nInMaxFID, nMaxOGRFID);
+
+    // Optimization: If the feature ids at the end of the file all map to a OGR fid
+    // then they don't need to be included in the final file
+    for(int i=nInMaxFID; i>nMaxOGRFID; i--)
+    {
+        if( m_oMapFGDBFIDToOGRFID.find(i) != m_oMapFGDBFIDToOGRFID.end() )
+        {
+            nOutMaxFID --;
+            nInMaxFID --;
+        }
+        else
+            break;
+    }
+    
+    //printf("nInMaxFID = %d\n", nInMaxFID);
+    //printf("nOutMaxFID = %d\n", nOutMaxFID);
+
+    int n1024BlocksOut = (int)(((GIntBig)nOutMaxFID + 1023) / 1024);
+    int nTmp;
+
+    nTmp = CPL_LSBWORD32(n1024BlocksOut);
+    memcpy(abyBuffer + 4, &nTmp, 4);
+
+    nTmp = CPL_LSBWORD32(nOutMaxFID);
+    memcpy(abyBuffer + 8, &nTmp, 4);
+    VSIFWriteL(abyBuffer, 1, 16, fpNew);
+
+    VSIFSeekL(fp, 1024 * n1024Blocks * nRecordSize, SEEK_CUR);
+    VSIFReadL(abyBuffer, 1, 16, fp);
+    int nBitmapInt32Words = GetInt32(abyBuffer, 0);
+    int n1024BlocksTotal = GetInt32(abyBuffer, 1);
+    CPLAssert(n1024BlocksTotal == (int)(((GIntBig)nInMaxFIDOri + 1023 ) / 1024) );
+    GByte* pabyBlockMap = NULL;
+    if( nBitmapInt32Words != 0 )
+    {
+        int nSizeInBytes = BIT_ARRAY_SIZE_IN_BYTES(n1024BlocksTotal);
+        pabyBlockMap = (GByte*) CPLMalloc( nSizeInBytes );
+        VSIFReadL( pabyBlockMap, nSizeInBytes, 1, fp );
+    }
+    int nSizeInBytesOut = BIT_ARRAY_SIZE_IN_BYTES(n1024BlocksOut);
+    /* Round to the next multiple of 128 bytes (32 int4 words) */
+    nSizeInBytesOut = ((nSizeInBytesOut + 127) / 128) * 128;
+    GByte* pabyBlockMapOut = (GByte*) VSI_CALLOC_VERBOSE( 1, nSizeInBytesOut );
+    GByte* pabyPage = (GByte*)VSI_MALLOC_VERBOSE( 1024 * nRecordSize );
+    if( pabyBlockMapOut == NULL || pabyPage == NULL )
+    {
+        VSIFree(pabyBlockMapOut);
+        VSIFree(pabyPage);
+        VSIFCloseL(fp);
+        return FALSE;
+    }
+    GByte abyEmptyOffset[6];
+    memset(abyEmptyOffset, 0, 6);
+    int nNonEmptyPages = 0;
+    int nOffsetInPage = 0, nLastWrittenOffset = 0;
+    int bDisableSparsePages = CPLTestBool(CPLGetConfigOption("FILEGDB_DISABLE_SPARSE_PAGES", "NO"));
+    
+    oIterO2F = m_oMapOGRFIDToFGDBFID.begin();
+    int nNextOGRFID = oIterO2F->first;
+    std::map<int,int>::iterator oIterF2O = m_oMapFGDBFIDToOGRFID.begin();
+    int nNextFGDBFID = oIterF2O->first;
+    
+    int nCountBlocksBeforeIBlockIdx = 0;
+    int nCountBlocksBeforeIBlockValue = 0;
+    
+    int bRet = TRUE;
+    for(int i=1; i<=nOutMaxFID;i++, nOffsetInPage += nRecordSize)
+    {
+        if( nOffsetInPage == 1024 * nRecordSize )
+        {
+            if( nLastWrittenOffset > 0 || bDisableSparsePages )
+            {
+                SET_BIT(pabyBlockMapOut, (i - 2) / 1024);
+                nNonEmptyPages ++;
+                if( nLastWrittenOffset < nOffsetInPage )
+                    memset(pabyPage + nLastWrittenOffset, 0, nOffsetInPage - nLastWrittenOffset);
+                if( VSIFWriteL(pabyPage, 1024 * nRecordSize, 1, fpNew) != 1 )
+                {
+                    bRet = FALSE;
+                    goto end;
+                }
+            }
+            nOffsetInPage = 0;
+            nLastWrittenOffset = 0;
+
+            // A few optimizations :
+            if( !bDisableSparsePages && i > nInMaxFID && nNextOGRFID > 0 && i < nNextOGRFID - 1024 )
+            {
+                // If we created a OGR FID far away from the latest FGDB FID
+                // then skip to it
+                i = ((nNextOGRFID-1) / 1024) * 1024 + 1;
+            }
+            else if( !bDisableSparsePages && pabyBlockMap != NULL && i <= nInMaxFID &&
+                     TEST_BIT(pabyBlockMap, (i-1)/1024) == 0 )
+            {
+                // Skip empty pages
+                UpdateNextOGRFIDAndFGDBFID(i,
+                                  m_oMapOGRFIDToFGDBFID, oIterO2F, nNextOGRFID,
+                                  m_oMapFGDBFIDToOGRFID, oIterF2O, nNextFGDBFID);
+                if( (nNextOGRFID < 0 || i < nNextOGRFID - 1024) &&
+                    (nNextFGDBFID < 0 || i < nNextFGDBFID - 1024) )
+                {
+                    if( i > INT_MAX - 1024 )
+                        break;
+                    i += 1023;
+                    nOffsetInPage += 1023 * nRecordSize;
+                    continue;
+                }
+            }
+        }
+
+       UpdateNextOGRFIDAndFGDBFID(i,
+                                  m_oMapOGRFIDToFGDBFID, oIterO2F, nNextOGRFID,
+                                  m_oMapFGDBFIDToOGRFID, oIterF2O, nNextFGDBFID);
+
+        int nSrcFID;
+        if( i == nNextOGRFID )
+        {
+            // This FID matches a user defined OGR FID, then find the
+            // corresponding FGDB record
+            nSrcFID = oIterO2F->second;
+            //printf("(1) i = %d, nSrcFID = %d\n", i, nSrcFID);
+        }
+        else if( i == nNextFGDBFID || i > nInMaxFID )
+        {
+            // This record is a temporary one (will be moved to a user-define FID)
+            // or we are out of the validity zone of input records
+            //printf("(2) i = %d, nNextFGDBFID = %d, nInMaxFID = %d\n", i, nNextFGDBFID, nInMaxFID);
+            continue;
+        }
+        else
+        {
+            // Regular record, not overloaded by user defined FID
+            nSrcFID = i;
+            //printf("(3) i = %d, nSrcFID = %d\n", i, nSrcFID);
+        }
+
+        if( pabyBlockMap != NULL )
+        {
+            int iBlock = (nSrcFID-1) / 1024;
+
+            // Check if the block is not empty
+            if( TEST_BIT(pabyBlockMap, iBlock) )
+            {
+                int nCountBlocksBefore;
+                if( iBlock >= nCountBlocksBeforeIBlockIdx )
+                {
+                    nCountBlocksBefore = nCountBlocksBeforeIBlockValue;
+                    for(int j=nCountBlocksBeforeIBlockIdx;j<iBlock;j++)
+                        nCountBlocksBefore += TEST_BIT(pabyBlockMap, j) != 0;
+                }
+                else
+                {
+                    nCountBlocksBefore = 0;
+                    for(int j=0;j<iBlock;j++)
+                        nCountBlocksBefore += TEST_BIT(pabyBlockMap, j) != 0;
+                }
+                nCountBlocksBeforeIBlockIdx = iBlock;
+                nCountBlocksBeforeIBlockValue = nCountBlocksBefore;
+                int iCorrectedRow = nCountBlocksBefore * 1024 + ((nSrcFID-1) % 1024);
+                VSIFSeekL(fp, 16 + nRecordSize * iCorrectedRow, SEEK_SET);
+                VSIFReadL(abyBuffer, 1, nRecordSize, fp);
+                if( memcmp( abyBuffer, abyEmptyOffset, nRecordSize) != 0 )
+                {
+                    if( nLastWrittenOffset < nOffsetInPage )
+                        memset(pabyPage + nLastWrittenOffset, 0, nOffsetInPage - nLastWrittenOffset);
+                    memcpy(pabyPage + nOffsetInPage, abyBuffer, nRecordSize);
+                    nLastWrittenOffset = nOffsetInPage + nRecordSize;
+                }
+            }
+        }
+        else
+        {
+            VSIFSeekL(fp, 16 + nRecordSize * (nSrcFID-1), SEEK_SET);
+            VSIFReadL(abyBuffer, 1, nRecordSize, fp);
+            if( memcmp( abyBuffer, abyEmptyOffset, nRecordSize) != 0 )
+            {
+                if( nLastWrittenOffset < nOffsetInPage )
+                    memset(pabyPage + nLastWrittenOffset, 0, nOffsetInPage - nLastWrittenOffset);
+                memcpy(pabyPage + nOffsetInPage, abyBuffer, nRecordSize);
+                nLastWrittenOffset = nOffsetInPage + nRecordSize;
+            }
+        }
+    }
+    //printf("nLastWrittenOffset = %d\n", nLastWrittenOffset);
+    if( nLastWrittenOffset > 0 || bDisableSparsePages )
+    {
+        SET_BIT(pabyBlockMapOut, (nOutMaxFID - 1) / 1024);
+        nNonEmptyPages ++;
+        if( nLastWrittenOffset < 1024 * nRecordSize )
+            memset(pabyPage + nLastWrittenOffset, 0, 1024 * nRecordSize - nLastWrittenOffset);
+        if( VSIFWriteL(pabyPage, 1024 * nRecordSize, 1, fpNew) != 1 )
+        {
+            bRet = FALSE;
+            goto end;
+        }
+    }
+
+    memset(abyBuffer, 0, 16);
+
+    /* Number of total blocks, including omitted ones */
+    nTmp = CPL_LSBWORD32(n1024BlocksOut);
+    memcpy(abyBuffer + 4, &nTmp, 4);
+
+    nTmp = CPL_LSBWORD32(nNonEmptyPages);
+    memcpy(abyBuffer + 8, &nTmp, 4);
+
+    if( nNonEmptyPages < n1024BlocksOut )
+    {
+        /* Number of int4 words for the bitmap (rounded to the next multiple of 32) */
+        nTmp = CPL_LSBWORD32(nSizeInBytesOut / 4);
+        memcpy(abyBuffer + 0, &nTmp, 4);
+
+        /* Number of int4 words in the bitmap where there's at least a non-zero bit */
+        /* Seems to be unused */
+        nTmp = CPL_LSBWORD32(((nOutMaxFID - 1) / 1024 + 31) / 32);
+        memcpy(abyBuffer + 12, &nTmp, 4);
+    }
+
+    if( VSIFWriteL(abyBuffer, 1, 16, fpNew) != 16 )
+    {
+        bRet = FALSE;
+        goto end;
+    }
+
+    if( nNonEmptyPages < n1024BlocksOut )
+    {
+        VSIFWriteL(pabyBlockMapOut, 1, nSizeInBytesOut, fpNew);
+
+        VSIFSeekL(fpNew, 4, SEEK_SET);
+        nTmp = CPL_LSBWORD32(nNonEmptyPages);
+        VSIFWriteL(&nTmp, 1, 4, fpNew);
+    }
+
+end:
+    CPLFree(pabyBlockMap);
+    CPLFree(pabyBlockMapOut);
+    CPLFree(pabyPage);
+    VSIFCloseL(fpNew);
+    VSIFCloseL(fp);
+
+    return bRet;
 }
 
 #ifdef EXTENT_WORKAROUND
@@ -187,7 +886,10 @@ bool FGdbLayer::UpdateRowWithGeometry(Row& row, OGRGeometry* poGeom)
     GByte *pabyShape = NULL;
     int nShapeSize = 0;
     if ( OGRWriteToShapeBin( poGeom, &pabyShape, &nShapeSize ) != OGRERR_NONE )
+    {
+        CPLFree(pabyShape);
         return false;
+    }
 
     /* Copy it into a ShapeBuffer */
     if ( nShapeSize > 0 )
@@ -227,6 +929,7 @@ void FGdbLayer::WorkAroundExtentProblem()
 {
     if (!m_bLayerJustCreated || !m_bLayerEnvelopeValid)
         return;
+    m_bLayerJustCreated = FALSE;
 
     OGREnvelope sEnvelope;
     if (GetExtent(&sEnvelope, TRUE) != OGRERR_NONE)
@@ -350,20 +1053,76 @@ void FGdbLayer::WorkAroundExtentProblem()
 
 OGRErr FGdbLayer::ICreateFeature( OGRFeature *poFeature )
 {
-    Table *fgdb_table = m_pTable;
     Row fgdb_row;
     fgdbError hr;
 
-    if( !m_pDS->GetUpdate() )
+    if( !m_pDS->GetUpdate() || m_pTable == NULL )
+        return OGRERR_FAILURE;
+
+    GIntBig nFID = poFeature->GetFID();
+    if( nFID < -1 || nFID == 0 || !CPL_INT64_FITS_ON_INT32(nFID) )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Only 32 bit positive integers FID supported by FileGDB");
+        return OGRERR_FAILURE;
+    }
+
+    if( nFID > 0 )
+    {
+        if( m_pDS->GetOpenFileGDBDrv() == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Cannot call CreateFeature() with a set FID when OpenFileGDB driver not available");
+            return OGRERR_FAILURE;
+        }
+        
+        if( m_pDS->HasSelectLayers() )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Cannot call CreateFeature() with a set FID when a layer resulting from ExecuteSQL() is still opened");
+            return OGRERR_FAILURE;
+        }
+        
+        if( m_pDS->GetConnection()->GetRefCount() > 1 )
+            {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Cannot call CreateFeature() with a set FID when a dataset is opened more than once");
+            return OGRERR_FAILURE;
+        }
+        
+        if( m_oMapOGRFIDToFGDBFID.find((int)poFeature->GetFID()) != m_oMapOGRFIDToFGDBFID.end() )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "A feature with same FID already exists");
+            return OGRERR_FAILURE;
+        }
+        
+        if( m_oMapFGDBFIDToOGRFID.find((int)poFeature->GetFID()) == m_oMapFGDBFIDToOGRFID.end() )
+        {
+            EnumRows       enumRows;
+            Row            row;
+            if (GetRow(enumRows, row, (int)poFeature->GetFID()) == OGRERR_NONE)
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                        "A feature with same FID already exists");
+                return OGRERR_FAILURE;
+            }
+        }
+
+        if( (int)m_oMapOGRFIDToFGDBFID.size() == m_nResyncThreshold )
+            ResyncIDs();
+    }
+
+    if( m_bSymlinkFlag && !CreateRealCopy() )
         return OGRERR_FAILURE;
 
     if (m_bBulkLoadAllowed < 0)
-        m_bBulkLoadAllowed = CSLTestBoolean(CPLGetConfigOption("FGDB_BULK_LOAD", "NO"));
+        m_bBulkLoadAllowed = CPLTestBool(CPLGetConfigOption("FGDB_BULK_LOAD", "NO"));
 
     if (m_bBulkLoadAllowed && !m_bBulkLoadInProgress)
         StartBulkLoad();
 
-    hr = fgdb_table->CreateRowObject(fgdb_row);
+    hr = m_pTable->CreateRowObject(fgdb_row);
 
     /* Check the status of the Row create */
     if (FAILED(hr))
@@ -385,7 +1144,7 @@ OGRErr FGdbLayer::ICreateFeature( OGRFeature *poFeature )
     //hr = fgdb_row.SetInteger(wfield_name, poFeature->GetFID());
 
     /* Write the row to the table */
-    hr = fgdb_table->Insert(fgdb_row);
+    hr = m_pTable->Insert(fgdb_row);
     if (FAILED(hr))
     {
         GDBErr(hr, "Failed at writing Row to Table in CreateFeature.");
@@ -395,7 +1154,38 @@ OGRErr FGdbLayer::ICreateFeature( OGRFeature *poFeature )
     int32 oid = -1;
     if (!FAILED(hr = fgdb_row.GetOID(oid)))
     {
-        poFeature->SetFID(oid);
+        if( poFeature->GetFID() < 0 )
+        {
+            // Avoid colliding with a user set FID
+            while( m_oMapOGRFIDToFGDBFID.find(oid) != m_oMapOGRFIDToFGDBFID.end() )
+            {
+                EndBulkLoad();
+
+                CPLDebug("FGDB", "Collision with user set FID %d", oid);
+                if (FAILED(hr = m_pTable->Delete(fgdb_row)))
+                {
+                    GDBErr(hr, "Failed deleting row ");
+                    return OGRERR_FAILURE;
+                }
+                hr = m_pTable->Insert(fgdb_row);
+                if (FAILED(hr))
+                {
+                    GDBErr(hr, "Failed at writing Row to Table in CreateFeature.");
+                    return OGRERR_FAILURE;
+                }
+                if (FAILED(hr = fgdb_row.GetOID(oid)))
+                {
+                    return OGRERR_FAILURE;
+                }
+            }
+            poFeature->SetFID(oid);
+        }
+        else if( (int)poFeature->GetFID() != oid )
+        {
+            m_pDS->GetConnection()->SetFIDHackInProgress(TRUE);
+            m_oMapOGRFIDToFGDBFID[(int)poFeature->GetFID()] = oid;
+            m_oMapFGDBFIDToOGRFID[oid] = (int)poFeature->GetFID();
+        }
     }
 
 #ifdef EXTENT_WORKAROUND
@@ -604,7 +1394,10 @@ OGRErr FGdbLayer::PopulateRowWithFeature( Row& fgdb_row, OGRFeature *poFeature )
                 err = OGRWriteToShapeBin( poGeom, &pabyShape, &nShapeSize );
             }
             if ( err != OGRERR_NONE )
+            {
+                CPLFree(pabyShape);
                 return err;
+            }
 
             /* Copy it into a ShapeBuffer */
             if ( nShapeSize > 0 )
@@ -641,7 +1434,7 @@ OGRErr FGdbLayer::GetRow( EnumRows& enumRows, Row& row, GIntBig nFID )
     CPLString      osQuery;
     
     /* Querying a 64bit FID causes a runtime exception in FileGDB... */
-    if( (GIntBig)(int)nFID != nFID )
+    if( !CPL_INT64_FITS_ON_INT32(nFID) )
     {
         return OGRERR_FAILURE;
     }
@@ -677,12 +1470,28 @@ OGRErr FGdbLayer::DeleteFeature( GIntBig nFID )
     EnumRows       enumRows;
     Row            row;
 
-    if( !m_pDS->GetUpdate() )
+    if( !m_pDS->GetUpdate() || m_pTable == NULL )
+        return OGRERR_FAILURE;
+    if( !CPL_INT64_FITS_ON_INT32(nFID) )
+        return OGRERR_NON_EXISTING_FEATURE;
+
+    if( m_bSymlinkFlag && !CreateRealCopy() )
         return OGRERR_FAILURE;
 
+    int nFID32 = (int)nFID;
+    std::map<int,int>::iterator oIter = m_oMapOGRFIDToFGDBFID.find(nFID32);
+    if( oIter != m_oMapOGRFIDToFGDBFID.end() )
+    {
+        nFID32 = oIter->second;
+        m_oMapFGDBFIDToOGRFID.erase(nFID32);
+        m_oMapOGRFIDToFGDBFID.erase(oIter);
+    }
+    else if( m_oMapFGDBFIDToOGRFID.find(nFID32) != m_oMapFGDBFIDToOGRFID.end() )
+        return OGRERR_NON_EXISTING_FEATURE;
+
     EndBulkLoad();
 
-    OGRErr eErr = GetRow(enumRows, row, nFID);
+    OGRErr eErr = GetRow(enumRows, row, nFID32);
     if( eErr != OGRERR_NONE)
         return eErr;
 
@@ -706,19 +1515,32 @@ OGRErr FGdbLayer::ISetFeature( OGRFeature* poFeature )
     EnumRows       enumRows;
     Row            row;
 
-    if( !m_pDS->GetUpdate() )
+    if( !m_pDS->GetUpdate()|| m_pTable == NULL )
         return OGRERR_FAILURE;
 
-    if( poFeature->GetFID() == OGRNullFID )
+    GIntBig nFID64 = poFeature->GetFID();
+    if( nFID64 == OGRNullFID )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "SetFeature() with unset FID fails." );
         return OGRERR_FAILURE;
     }
+    if( !CPL_INT64_FITS_ON_INT32(nFID64) )
+        return OGRERR_NON_EXISTING_FEATURE;
 
     EndBulkLoad();
 
-    OGRErr eErr = GetRow(enumRows, row, poFeature->GetFID());
+    if( m_bSymlinkFlag && !CreateRealCopy() )
+        return OGRERR_FAILURE;
+
+    int nFID = (int)nFID64;
+    std::map<int,int>::iterator oIter = m_oMapOGRFIDToFGDBFID.find(nFID);
+    if( oIter != m_oMapOGRFIDToFGDBFID.end() )
+        nFID = oIter->second;
+    else if( m_oMapFGDBFIDToOGRFID.find((int)poFeature->GetFID()) != m_oMapFGDBFIDToOGRFID.end() )
+        return OGRERR_NON_EXISTING_FEATURE;
+
+    OGRErr eErr = GetRow(enumRows, row, nFID);
     if( eErr != OGRERR_NONE)
         return eErr;
 
@@ -946,7 +1768,7 @@ OGRErr FGdbLayer::CreateField(OGRFieldDefn* poField, int bApproxOK)
     std::string fieldname_clean;
     std::string gdbFieldType;
 
-    if( !m_pDS->GetUpdate() )
+    if( !m_pDS->GetUpdate()|| m_pTable == NULL )
         return OGRERR_FAILURE;
 
     char* defn_str = CreateFieldDefn(oField, bApproxOK,
@@ -987,7 +1809,7 @@ OGRErr FGdbLayer::CreateField(OGRFieldDefn* poField, int bApproxOK)
 OGRErr FGdbLayer::DeleteField( int iFieldToDelete )
 {
 
-    if( !m_pDS->GetUpdate() )
+    if( !m_pDS->GetUpdate()|| m_pTable == NULL )
         return OGRERR_FAILURE;
 
     if (iFieldToDelete < 0 || iFieldToDelete >= m_pFeatureDefn->GetFieldCount())
@@ -1024,7 +1846,7 @@ OGRErr FGdbLayer::DeleteField( int iFieldToDelete )
 OGRErr FGdbLayer::AlterFieldDefn( int iFieldToAlter, OGRFieldDefn* poNewFieldDefn, int nFlags )
 {
 
-    if( !m_pDS->GetUpdate() )
+    if( !m_pDS->GetUpdate()|| m_pTable == NULL )
         return OGRERR_FAILURE;
 
     if (iFieldToAlter < 0 || iFieldToAlter >= m_pFeatureDefn->GetFieldCount())
@@ -1094,7 +1916,7 @@ OGRErr FGdbLayer::AlterFieldDefn( int iFieldToAlter, OGRFieldDefn* poNewFieldDef
 /*                                                                      */
 /************************************************************************/
 
-CPLXMLNode* XMLSpatialReference(OGRSpatialReference* poSRS, char** papszOptions)
+static CPLXMLNode* XMLSpatialReference(OGRSpatialReference* poSRS, char** papszOptions)
 {
     /* We always need a SpatialReference */
     CPLXMLNode *srs_xml = CPLCreateXMLNode(NULL, CXT_Element, "SpatialReference");
@@ -1152,7 +1974,7 @@ CPLXMLNode* XMLSpatialReference(OGRSpatialReference* poSRS, char** papszOptions)
                 nSRID = 0;
 
                 /* Enumerate SRS from ESRI DB and find a match */
-                while(TRUE)
+                while( true )
                 {
                     if ( poSRS->IsProjected() )
                     {
@@ -1253,7 +2075,7 @@ CPLXMLNode* XMLSpatialReference(OGRSpatialReference* poSRS, char** papszOptions)
     // default tolerance is 1mm in the units of the coordinate system
     double ztol = 0.001 * (poSRS ? poSRS->GetTargetLinearUnits("VERT_CS") : 1.0);
     // default scale is 10x the tolerance
-    long zscale = 1 / ztol * 10;
+    long zscale = (long)(1 / ztol * 10);
 
     char s_xyscale[50], s_xytol[50], s_zscale[50], s_ztol[50];
     CPLsnprintf(s_ztol, 50, "%f", ztol);
@@ -1264,7 +2086,7 @@ CPLXMLNode* XMLSpatialReference(OGRSpatialReference* poSRS, char** papszOptions)
         // default tolerance is 1mm in the units of the coordinate system
         double xytol = 0.001 * (poSRS ? poSRS->GetTargetLinearUnits("PROJCS") : 1.0);
         // default scale is 10x the tolerance
-        long xyscale = 1 / xytol * 10;
+        long xyscale = (long)(1 / xytol * 10);
 
         CPLsnprintf(s_xytol, 50, "%f", xytol);
         snprintf(s_xyscale, 50, "%ld", xyscale);
@@ -1351,7 +2173,7 @@ bool FGdbLayer::CreateFeatureDataset(FGdbDataSource* pParentDataSource,
     CPLAddXMLChild(defn_xml, extent_xml);
 
     /* Add the SRS */
-    if( TRUE ) // TODO: conditional on existence of SRS
+    if( true ) // TODO: conditional on existence of SRS
     {
         CPLXMLNode *srs_xml = XMLSpatialReference(poSRS, papszOptions);
         if ( srs_xml )
@@ -1408,6 +2230,7 @@ bool FGdbLayer::Create(FGdbDataSource* pParentDataSource,
     std::string fid_name = FGDB_OID_NAME;
     std::string esri_type;
     bool has_z = false;
+    bool has_m = false;
 
 #ifdef EXTENT_WORKAROUND
     m_bLayerJustCreated = true;
@@ -1497,11 +2320,11 @@ bool FGdbLayer::Create(FGdbDataSource* pParentDataSource,
         {
             return GDBErr(-1, "FGDB layers cannot be created with a wkbUnknown layer geometry type.");
         }
-        if ( ! OGRGeometryToGDB(eType, &esri_type, &has_z) )
+        if ( ! OGRGeometryToGDB(eType, &esri_type, &has_z, &has_m) )
             return GDBErr(-1, "Unable to map OGR type to ESRI type");
 
         if( wkbFlatten(eType) == wkbMultiPolygon &&
-            CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "CREATE_MULTIPATCH", "NO")) )
+            CPLTestBool(CSLFetchNameValueDef(papszOptions, "CREATE_MULTIPATCH", "NO")) )
         {
             esri_type = "esriGeometryMultiPatch";
             has_z = true;
@@ -1572,7 +2395,7 @@ bool FGdbLayer::Create(FGdbDataSource* pParentDataSource,
         FGDB_CPLAddXMLAttribute(geom_xml, "xsi:type", "esri:GeometryDef");
         CPLCreateXMLElementAndValue(geom_xml, "AvgNumPoints", "0");
         CPLCreateXMLElementAndValue(geom_xml, "GeometryType", esri_type.c_str());
-        CPLCreateXMLElementAndValue(geom_xml,"HasM", "false");
+        CPLCreateXMLElementAndValue(geom_xml,"HasM", (has_m ? "true" : "false"));
         CPLCreateXMLElementAndValue(geom_xml,"HasZ", (has_z ? "true" : "false"));
 
         /* Add the SRS if we have one */
@@ -1625,7 +2448,7 @@ bool FGdbLayer::Create(FGdbDataSource* pParentDataSource,
         CPLCreateXMLElementAndValue(defn_xml,"ShapeFieldName", geometry_name.c_str());
 
         /* Dimensionality */
-        CPLCreateXMLElementAndValue(defn_xml,"HasM", "false");
+        CPLCreateXMLElementAndValue(defn_xml,"HasM", (has_m ? "true" : "false"));
         CPLCreateXMLElementAndValue(defn_xml,"HasZ", (has_z ? "true" : "false"));
 
         /* TODO: Handle spatial indexes (layer creation option?) */
@@ -1675,10 +2498,10 @@ bool FGdbLayer::Create(FGdbDataSource* pParentDataSource,
     }
 
     m_papszOptions = CSLDuplicate(papszOptions);
-    m_bCreateMultipatch = CSLTestBoolean(CSLFetchNameValueDef(m_papszOptions, "CREATE_MULTIPATCH", "NO"));
+    m_bCreateMultipatch = CPLTestBool(CSLFetchNameValueDef(m_papszOptions, "CREATE_MULTIPATCH", "NO"));
     
     // Default to YES here assuming ogr2ogr scenario
-    m_bBulkLoadAllowed = CSLTestBoolean(CPLGetConfigOption("FGDB_BULK_LOAD", "YES"));
+    m_bBulkLoadAllowed = CPLTestBool(CPLGetConfigOption("FGDB_BULK_LOAD", "YES"));
 
     /* Store the new FGDB Table pointer and set up the OGRFeatureDefn */
     return FGdbLayer::Initialize(pParentDataSource, table, wtable_path, L"Table");
@@ -1805,7 +2628,7 @@ bool FGdbLayer::ParseGeometryDef(CPLXMLNode* psRoot)
     CPLXMLNode *psGeometryDefItem;
 
     string geometryType;
-    bool hasZ = false;
+    bool hasZ = false, hasM = false;
     string wkt, wkid, latestwkid;
 
     for (psGeometryDefItem = psRoot->psChild;
@@ -1832,17 +2655,15 @@ bool FGdbLayer::ParseGeometryDef(CPLXMLNode* psRoot)
                 ParseSpatialReference(psGeometryDefItem, &wkt, &wkid, &latestwkid); // we don't check for success because it
                                                                 // may not be there
             }
-            /* No M support in OGR yet
-            else if (EQUAL(psFieldNode->pszValue,"HasM")
+            else if (EQUAL(psGeometryDefItem->pszValue,"HasM"))
             {
-                char* pszUnescaped = CPLUnescapeString(psNode->psChild->pszValue, NULL, CPLES_XML);
+                char* pszUnescaped = CPLUnescapeString(psGeometryDefItem->psChild->pszValue, NULL, CPLES_XML);
 
-                if (!strcmp(szUnescaped, "true"))
-                hasM = true;
+                if (!strcmp(pszUnescaped, "true"))
+                    hasM = true;
 
                 CPLFree(pszUnescaped);
             }
-            */
             else if (EQUAL(psGeometryDefItem->pszValue,"HasZ"))
             {
                 char* pszUnescaped = CPLUnescapeString(
@@ -1858,7 +2679,7 @@ bool FGdbLayer::ParseGeometryDef(CPLXMLNode* psRoot)
     }
 
     OGRwkbGeometryType ogrGeoType;
-    if (!GDBToOGRGeometry(geometryType, hasZ, &ogrGeoType))
+    if (!GDBToOGRGeometry(geometryType, hasZ, hasM, &ogrGeoType))
         return false;
 
     m_pFeatureDefn->SetGeomType(ogrGeoType);
@@ -2015,7 +2836,7 @@ bool FGdbLayer::GDBToOGRFields(CPLXMLNode* psRoot)
             std::string fieldName;
             std::string fieldType;
             int nLength = 0;
-            int nPrecision = 0;
+            //int nPrecision = 0;
             int bNullable = TRUE;
             std::string osDefault;
 
@@ -2053,7 +2874,7 @@ bool FGdbLayer::GDBToOGRFields(CPLXMLNode* psRoot)
                     }
                     else if (EQUAL(psFieldItemNode->pszValue,"Precision") )
                     {
-                        nPrecision = atoi(psFieldItemNode->psChild->pszValue);
+                        //nPrecision = atoi(psFieldItemNode->psChild->pszValue);
                     }
                     else if (EQUAL(psFieldItemNode->pszValue,"IsNullable") )
                     {
@@ -2166,7 +2987,7 @@ bool FGdbLayer::GDBToOGRFields(CPLXMLNode* psRoot)
     if( bShouldQueryOpenFileGDB )
     {
         const char* apszDrivers[] = { "OpenFileGDB", NULL };
-        GDALDataset* poDS = (GDALDataset*) GDALOpenEx(m_pDS->GetName(),
+        GDALDataset* poDS = (GDALDataset*) GDALOpenEx(m_pDS->GetFSName(),
                             GDAL_OF_VECTOR, (char**)apszDrivers, NULL, NULL);
         if( poDS != NULL )
         {
@@ -2200,6 +3021,9 @@ bool FGdbLayer::GDBToOGRFields(CPLXMLNode* psRoot)
 void FGdbLayer::ResetReading()
 {
     long hr;
+    
+    if( m_pTable == NULL )
+        return;
 
     EndBulkLoad();
 
@@ -2263,40 +3087,26 @@ void FGdbLayer::SetSpatialFilter( OGRGeometry* pOGRGeom )
 }
 
 /************************************************************************/
-/*                         SetSpatialFilterRect()                       */
+/*                             ResyncIDs()                              */
 /************************************************************************/
 
-void FGdbLayer::SetSpatialFilterRect (double dfMinX, double dfMinY, double dfMaxX, double dfMaxY)
+void  FGdbLayer::ResyncIDs()
 {
-
-    //TODO: can optimize this by changing how the filter gets generated -
-    //this will work for now
-
-    OGRGeometry* pTemp = OGRGeometryFactory::createGeometry(wkbPolygon);
-
-    pTemp->assignSpatialReference(m_pSRS);
-
-    OGRLinearRing ring;
-
-    ring.addPoint( dfMinX, dfMinY );
-    ring.addPoint( dfMinX, dfMaxY );
-    ring.addPoint( dfMaxX, dfMaxY );
-    ring.addPoint( dfMaxX, dfMinY );
-    ring.addPoint( dfMinX, dfMinY );
-    ((OGRPolygon *) pTemp)->addRing( &ring );
-
-    SetSpatialFilter(pTemp);
-
-    OGRGeometryFactory::destroyGeometry(pTemp);
+    if( m_oMapOGRFIDToFGDBFID.size() == 0 )
+        return;
+    if( m_pDS->Close() )
+        m_pDS->ReOpen();
 }
 
-
 /************************************************************************/
 /*                         SetAttributeFilter()                         */
 /************************************************************************/
 
 OGRErr FGdbLayer::SetAttributeFilter( const char* pszQuery )
 {
+    if( pszQuery != NULL && CPLString(pszQuery).ifind(GetFIDColumn()) != std::string::npos )
+        ResyncIDs();
+
     m_wstrWhereClause = StringToWString( (pszQuery != NULL) ? pszQuery : "" );
 
     m_bFilterDirty = true;
@@ -2355,11 +3165,11 @@ bool FGdbBaseLayer::OGRFeatureFromGdbRow(Row* pRow, OGRFeature** ppFeature)
     //
 
 
-    size_t mappedFieldCount = m_vOGRFieldToESRIField.size();
+    int mappedFieldCount = static_cast<int>(m_vOGRFieldToESRIField.size());
 
     bool foundBadColumn = false;
 
-    for (size_t i = 0; i < mappedFieldCount; ++i)
+    for (int i = 0; i < mappedFieldCount; ++i)
     {
         OGRFieldDefn* poFieldDefn = m_pFeatureDefn->GetFieldDefn(i);
         // The IsNull() and GetXXX() API are very slow when there are a 
@@ -2530,7 +3340,7 @@ bool FGdbBaseLayer::OGRFeatureFromGdbRow(Row* pRow, OGRFeature** ppFeature)
                 }
 
                 pOutFeature->SetField(i, val.tm_year + 1900, val.tm_mon + 1,
-                                      val.tm_mday, val.tm_hour, val.tm_min, val.tm_sec);
+                                      val.tm_mday, val.tm_hour, val.tm_min, (float)val.tm_sec);
             // Examine test data to figure out how to extract that
             }
             break;
@@ -2569,7 +3379,16 @@ OGRFeature* FGdbLayer::GetNextFeature()
 
     EndBulkLoad();
 
-    return FGdbBaseLayer::GetNextFeature();
+    OGRFeature* poFeature = FGdbBaseLayer::GetNextFeature();
+    if( poFeature )
+    {
+        std::map<int,int>::iterator oIter = m_oMapFGDBFIDToOGRFID.find((int)poFeature->GetFID());
+        if( oIter != m_oMapFGDBFIDToOGRFID.end() )
+        {
+            poFeature->SetFID(oIter->second);
+        }
+    }
+    return poFeature;
 }
 
 /************************************************************************/
@@ -2581,10 +3400,19 @@ OGRFeature *FGdbLayer::GetFeature( GIntBig oid )
     // do query to fetch individual row
     EnumRows       enumRows;
     Row            row;
+    if( !CPL_INT64_FITS_ON_INT32(oid) || m_pTable == NULL )
+        return NULL;
 
     EndBulkLoad();
 
-    if (GetRow(enumRows, row, oid) != OGRERR_NONE)
+    int nFID32 = (int)oid;
+    std::map<int,int>::iterator oIter = m_oMapOGRFIDToFGDBFID.find(nFID32);
+    if( oIter != m_oMapOGRFIDToFGDBFID.end() )
+        nFID32 = oIter->second;
+    else if( m_oMapFGDBFIDToOGRFID.find(nFID32) != m_oMapFGDBFIDToOGRFID.end() )
+        return NULL;
+
+    if (GetRow(enumRows, row, nFID32) != OGRERR_NONE)
         return NULL;
 
     OGRFeature* pOGRFeature = NULL;
@@ -2593,6 +3421,10 @@ OGRFeature *FGdbLayer::GetFeature( GIntBig oid )
     {
         return NULL;
     }
+    if( pOGRFeature )
+    {
+        pOGRFeature->SetFID(oid);
+    }
 
     return pOGRFeature;
 }
@@ -2604,8 +3436,10 @@ OGRFeature *FGdbLayer::GetFeature( GIntBig oid )
 
 GIntBig FGdbLayer::GetFeatureCount( CPL_UNUSED int bForce )
 {
-    long           hr;
     int32          rowCount = 0;
+    
+    if( m_pTable == NULL )
+        return 0;
 
     EndBulkLoad();
 
@@ -2616,7 +3450,7 @@ GIntBig FGdbLayer::GetFeatureCount( CPL_UNUSED int bForce )
             return 0;
 
         int nFeatures = 0;
-        while( TRUE )
+        while( true )
         {
             long hr;
 
@@ -2638,6 +3472,7 @@ GIntBig FGdbLayer::GetFeatureCount( CPL_UNUSED int bForce )
         return nFeatures;
     }
 
+    long hr;
     if (FAILED(hr = m_pTable->GetRowCount(rowCount)))
     {
         GDBErr(hr, "Failed counting rows");
@@ -2647,7 +3482,24 @@ GIntBig FGdbLayer::GetFeatureCount( CPL_UNUSED int bForce )
     return static_cast<int>(rowCount);
 }
 
+/************************************************************************/
+/*                         GetMetadataItem()                            */
+/************************************************************************/
 
+const char* FGdbLayer::GetMetadataItem(const char* pszName, const char* pszDomain)
+{
+    if( pszDomain != NULL && EQUAL(pszDomain, "MAP_OGR_FID_TO_FGDB_FID") )
+    {
+        if( m_oMapOGRFIDToFGDBFID.find(atoi(pszName)) != m_oMapOGRFIDToFGDBFID.end() )
+            return CPLSPrintf("%d", m_oMapOGRFIDToFGDBFID[atoi(pszName)]);
+    }
+    else if( pszDomain != NULL && EQUAL(pszDomain, "MAP_FGDB_FID_TO_OGR_FID") )
+    {
+        if( m_oMapFGDBFIDToOGRFID.find(atoi(pszName)) != m_oMapFGDBFIDToOGRFID.end() )
+            return CPLSPrintf("%d", m_oMapFGDBFIDToOGRFID[atoi(pszName)]);
+    }
+    return OGRLayer::GetMetadataItem(pszName, pszDomain);
+}
 
 /************************************************************************/
 /*                             GetExtent()                              */
@@ -2655,6 +3507,9 @@ GIntBig FGdbLayer::GetFeatureCount( CPL_UNUSED int bForce )
 
 OGRErr FGdbLayer::GetExtent (OGREnvelope* psExtent, int bForce)
 {
+    if( m_pTable == NULL )
+        return OGRERR_FAILURE;
+
     if (m_pOGRFilterGeometry != NULL || m_wstrWhereClause.size() != 0 ||
         m_strShapeFieldName.size() == 0)
     {
@@ -2776,6 +3631,9 @@ OGRErr FGdbLayer::GetLayerXML (char **ppXml)
     long hr;
     std::string xml;
 
+    if( m_pTable == NULL )
+        return OGRERR_FAILURE;
+    
     if ( FAILED(hr = m_pTable->GetDefinition(xml)) )
     {
         GDBErr(hr, "Failed fetching XML table definition");
@@ -2798,6 +3656,9 @@ OGRErr FGdbLayer::GetLayerMetadataXML (char **ppXml)
 {
     long hr;
     std::string xml;
+    
+    if( m_pTable == NULL )
+        return OGRERR_FAILURE;
 
     if ( FAILED(hr = m_pTable->GetDocumentation(xml)) )
     {
@@ -2863,7 +3724,97 @@ int FGdbLayer::TestCapability( const char* pszCap )
     else if( EQUAL(pszCap,OLCIgnoreFields) )
         return TRUE;
 
+    else if( EQUAL(pszCap,OLCMeasuredGeometries) )
+        return TRUE;
+
     else 
         return FALSE;
 }
 
+/************************************************************************/
+/*                           CreateRealCopy()                           */
+/************************************************************************/
+
+int FGdbLayer::CreateRealCopy()
+{
+    CPLAssert( m_bSymlinkFlag );
+
+    // Find the FID of the layer in the system catalog
+    char* apszDrivers[2];
+    apszDrivers[0] = (char*) "OpenFileGDB";
+    apszDrivers[1] = NULL;
+    const char* pszSystemCatalog
+        = CPLFormFilename(m_pDS->GetFSName(), "a00000001.gdbtable", NULL);
+    GDALDataset* poOpenFileGDBDS = (GDALDataset*)
+        GDALOpenEx(pszSystemCatalog, GDAL_OF_VECTOR,
+                    apszDrivers, NULL, NULL);
+    if( poOpenFileGDBDS == NULL || poOpenFileGDBDS->GetLayer(0) == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Cannot open %s with OpenFileGDB driver. Should not happen.",
+                  pszSystemCatalog);
+        GDALClose(poOpenFileGDBDS);
+        return FALSE;
+    }
+
+    OGRLayer* poLayer = poOpenFileGDBDS->GetLayer(0);
+    CPLString osFilter = "name = '";
+    osFilter += GetName();
+    osFilter += "'";
+    poLayer->SetAttributeFilter(osFilter);
+    poLayer->ResetReading();
+    OGRFeature* poF = poLayer->GetNextFeature();
+    if( poF == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Cannot find filename for layer %s",
+                  GetName());
+        GDALClose(poOpenFileGDBDS);
+        return FALSE;
+    }
+    int nLayerFID = (int)poF->GetFID();
+    delete poF;
+    GDALClose(poOpenFileGDBDS);
+
+    if( !m_pDS->Close(TRUE) )
+        return FALSE;
+
+    // Create real copies (in .tmp files now) instead of symlinks
+    char** papszFiles = VSIReadDir(m_pDS->GetFSName());
+    CPLString osBasename(CPLSPrintf("a%08x", nLayerFID));
+    int bError = FALSE;
+    std::vector<CPLString> aoFiles;
+    for(char** papszIter = papszFiles; !bError && papszIter && *papszIter; papszIter++)
+    {
+        if( strncmp(*papszIter, osBasename.c_str(), osBasename.size()) == 0 )
+        {
+            if(CPLCopyFile( CPLFormFilename(m_pDS->GetFSName(), *papszIter, "tmp"),
+                            CPLFormFilename(m_pDS->GetFSName(), *papszIter, NULL) ) != 0 )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                             "Cannot copy %s", *papszIter);
+                bError = TRUE;
+            }
+            else
+                aoFiles.push_back(*papszIter);
+        }
+    }
+    CSLDestroy(papszFiles);
+    
+    // Rename the .tmp into normal filenames
+    for(size_t i=0; !bError && i<aoFiles.size(); i++ )
+    {
+        if( VSIUnlink( CPLFormFilename(m_pDS->GetFSName(), aoFiles[i], NULL) ) != 0 ||
+            VSIRename( CPLFormFilename(m_pDS->GetFSName(), aoFiles[i], "tmp"),
+                       CPLFormFilename(m_pDS->GetFSName(), aoFiles[i], NULL) ) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Cannot rename %s.tmp", aoFiles[i].c_str());
+            bError = TRUE;
+        }
+    }
+
+    int bRet = !bError && m_pDS->ReOpen();
+    if( bRet )
+        m_bSymlinkFlag = FALSE;
+    return bRet;
+}
diff --git a/ogr/ogrsf_frmts/filegdb/FGdbUtils.cpp b/ogr/ogrsf_frmts/filegdb/FGdbUtils.cpp
index 98c38f0..c2028bc 100644
--- a/ogr/ogrsf_frmts/filegdb/FGdbUtils.cpp
+++ b/ogr/ogrsf_frmts/filegdb/FGdbUtils.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
-* $Id: FGdbUtils.cpp 28573 2015-02-27 18:13:19Z rouault $
+* $Id: FGdbUtils.cpp 33563 2016-02-26 14:57:06Z rouault $
 *
 * Project:  OpenGIS Simple Features Reference Implementation
 * Purpose:  Different utility functions used in FileGDB OGR driver.
@@ -36,7 +36,7 @@
 #include "ogr_api.h"
 #include "ogrpgeogeometry.h"
 
-CPL_CVSID("$Id: FGdbUtils.cpp 28573 2015-02-27 18:13:19Z rouault $");
+CPL_CVSID("$Id: FGdbUtils.cpp 33563 2016-02-26 14:57:06Z rouault $");
 
 using std::string;
 
@@ -72,7 +72,7 @@ bool GDBErr(long int hr, std::string desc, CPLErr errType, const char* pszAddMsg
 {
     std::wstring fgdb_error_desc_w;
     fgdbError er;
-    er = FileGDBAPI::ErrorInfo::GetErrorDescription(hr, fgdb_error_desc_w);
+    er = FileGDBAPI::ErrorInfo::GetErrorDescription(static_cast<fgdbError>(hr), fgdb_error_desc_w);
     if ( er == S_OK )
     {
         std::string fgdb_error_desc = WStringToString(fgdb_error_desc_w);
@@ -99,7 +99,7 @@ bool GDBDebug(long int hr, std::string desc)
 {
     std::wstring fgdb_error_desc_w;
     fgdbError er;
-    er = FileGDBAPI::ErrorInfo::GetErrorDescription(hr, fgdb_error_desc_w);
+    er = FileGDBAPI::ErrorInfo::GetErrorDescription(static_cast<fgdbError>(hr), fgdb_error_desc_w);
     if ( er == S_OK )
     {
         std::string fgdb_error_desc = WStringToString(fgdb_error_desc_w);
@@ -120,28 +120,28 @@ bool GDBDebug(long int hr, std::string desc)
 /*                            GDBToOGRGeometry()                         */
 /*************************************************************************/
 
-bool GDBToOGRGeometry(string geoType, bool hasZ, OGRwkbGeometryType* pOut)
+bool GDBToOGRGeometry(string geoType, bool hasZ, bool hasM, OGRwkbGeometryType* pOut)
 {
     if (geoType == "esriGeometryPoint")
     {
-        *pOut = hasZ? wkbPoint25D : wkbPoint;
+        *pOut = wkbPoint;
     }
     else if (geoType == "esriGeometryMultipoint")
     {
-        *pOut = hasZ? wkbMultiPoint25D : wkbMultiPoint;
+        *pOut = wkbMultiPoint;
     }
     else if (geoType == "esriGeometryLine")
     {
-        *pOut = hasZ? wkbLineString25D : wkbLineString;
+        *pOut = wkbLineString;
     }
     else if (geoType == "esriGeometryPolyline")
     {
-        *pOut = hasZ? wkbMultiLineString25D : wkbMultiLineString;
+        *pOut = wkbMultiLineString;
     }
     else if (geoType == "esriGeometryPolygon" ||
             geoType == "esriGeometryMultiPatch")
     {
-        *pOut = hasZ? wkbMultiPolygon25D : wkbMultiPolygon; // no mapping to single polygon
+        *pOut = wkbMultiPolygon; // no mapping to single polygon
     }
     else
     {
@@ -149,6 +149,10 @@ bool GDBToOGRGeometry(string geoType, bool hasZ, OGRwkbGeometryType* pOut)
                 "Cannot map esriGeometryType(%s) to OGRwkbGeometryType", geoType.c_str());
         return false;
     }
+    if( hasZ )
+        *pOut = wkbSetZ(*pOut);
+    if( hasM )
+        *pOut = wkbSetM(*pOut);
 
     return true;
 }
@@ -157,53 +161,21 @@ bool GDBToOGRGeometry(string geoType, bool hasZ, OGRwkbGeometryType* pOut)
 /*                            OGRGeometryToGDB()                         */
 /*************************************************************************/
 
-bool OGRGeometryToGDB(OGRwkbGeometryType ogrType, std::string *gdbType, bool *hasZ)
+bool OGRGeometryToGDB(OGRwkbGeometryType ogrType, std::string *gdbType, bool *hasZ, bool *hasM)
 {
-    switch (ogrType)
+    *hasZ = wkbHasZ(ogrType);
+    *hasM = wkbHasM(ogrType);
+    switch (wkbFlatten(ogrType))
     {
-        /* 3D forms */
-        case wkbPoint25D:
-        {
-            *gdbType = "esriGeometryPoint";
-            *hasZ = true;
-            break;
-        }
-
-        case wkbMultiPoint25D:
-        {
-            *gdbType = "esriGeometryMultipoint";
-            *hasZ = true;
-            break;
-        }
-
-        case wkbLineString25D:
-        case wkbMultiLineString25D:
-        {
-            *gdbType = "esriGeometryPolyline";
-            *hasZ = true;
-            break;
-        }
-
-        case wkbPolygon25D:
-        case wkbMultiPolygon25D:
-        {
-            *gdbType = "esriGeometryPolygon";
-            *hasZ = true;
-            break;
-        }
-
-        /* 2D forms */
         case wkbPoint:
         {
             *gdbType = "esriGeometryPoint";
-            *hasZ = false;
             break;
         }
 
         case wkbMultiPoint:
         {
             *gdbType = "esriGeometryMultipoint";
-            *hasZ = false;
             break;
         }
 
@@ -211,7 +183,6 @@ bool OGRGeometryToGDB(OGRwkbGeometryType ogrType, std::string *gdbType, bool *ha
         case wkbMultiLineString:
         {
             *gdbType = "esriGeometryPolyline";
-            *hasZ = false;
             break;
         }
 
@@ -219,7 +190,6 @@ bool OGRGeometryToGDB(OGRwkbGeometryType ogrType, std::string *gdbType, bool *ha
         case wkbMultiPolygon:
         {
             *gdbType = "esriGeometryPolygon";
-            *hasZ = false;
             break;
         }
         
@@ -237,8 +207,9 @@ bool OGRGeometryToGDB(OGRwkbGeometryType ogrType, std::string *gdbType, bool *ha
 /*                            GDBToOGRFieldType()                        */
 /*************************************************************************/
 
-// We could make this function far more robust by doing automatic coertion of types,
-// and/or skipping fields we do not know. But our purposes this works fine
+// We could make this function far more robust by doing automatic coercion of
+// types, and/or skipping fields we do not know. But, for our purposes. this
+// works fine.
 bool GDBToOGRFieldType(std::string gdbType, OGRFieldType* pOut, OGRFieldSubType* pSubType)
 {
     /*
@@ -456,7 +427,7 @@ bool GDBGeometryToOGRGeometry(bool forceMulti, FileGDBAPI::ShapeBuffer* pGdbGeom
 
     OGRErr eErr = OGRCreateFromShapeBin( pGdbGeometry->shapeBuffer,
                                 &pOGRGeometry,
-                                pGdbGeometry->inUseLength);
+                                static_cast<int>(pGdbGeometry->inUseLength));
 
     //OGRErr eErr = OGRGeometryFactory::createFromWkb(pGdbGeometry->shapeBuffer, pOGRSR, &pOGRGeometry, pGdbGeometry->inUseLength );
 
@@ -523,7 +494,7 @@ bool GDBToOGRSpatialReference(const string & wkt, OGRSpatialReference** ppSR)
         *ppSR = NULL;
 
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Failed morhping from ESRI Geometry: %s", wkt.c_str());
+                  "Failed morphing from ESRI Geometry: %s", wkt.c_str());
 
         return false;
     }
@@ -576,7 +547,7 @@ std::string FGDBEscapeUnsupportedPrefixes(const std::string className)
     std::string newName = className;
     // From ESRI docs
     // Feature classes starting with these strings are unsupported.
-    static const char* UNSUPPORTED_PREFIXES[] = {"sde_", "gdb_", "delta_", NULL};
+    static const char* const UNSUPPORTED_PREFIXES[] = {"sde_", "gdb_", "delta_", NULL};
 
     for (int i = 0; UNSUPPORTED_PREFIXES[i] != NULL; i++)
     {
@@ -601,7 +572,7 @@ std::string FGDBEscapeReservedKeywords(const std::string name)
     std::transform(upperName.begin(), upperName.end(), upperName.begin(), ::toupper);
 
     // From ESRI docs
-    static const char* RESERVED_WORDS[] = {FGDB_OID_NAME, "ADD", "ALTER", "AND", "AS", "ASC", "BETWEEN",
+    static const char* const RESERVED_WORDS[] = {FGDB_OID_NAME, "ADD", "ALTER", "AND", "AS", "ASC", "BETWEEN",
                                     "BY", "COLUMN", "CREATE", "DATE", "DELETE", "DESC",
                                     "DROP", "EXISTS", "FOR", "FROM", "IN", "INSERT", "INTO",
                                     "IS", "LIKE", "NOT", "NULL", "OR", "ORDER", "SELECT",
diff --git a/ogr/ogrsf_frmts/filegdb/FGdbUtils.h b/ogr/ogrsf_frmts/filegdb/FGdbUtils.h
index 215eb9d..e46e6c9 100644
--- a/ogr/ogrsf_frmts/filegdb/FGdbUtils.h
+++ b/ogr/ogrsf_frmts/filegdb/FGdbUtils.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: FGdbUtils.h 28573 2015-02-27 18:13:19Z rouault $
+ * $Id: FGdbUtils.h 33563 2016-02-26 14:57:06Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Various FileGDB OGR Datasource utility functions
@@ -28,8 +28,8 @@
  ****************************************************************************/
 
 
-#ifndef _FGDB_UTILS_H_INCLUDED
-#define _FGDB_UTILS_H_INCLUDED
+#ifndef FGDB_UTILS_H_INCLUDED
+#define FGDB_UTILS_H_INCLUDED
 
 #include "ogr_fgdb.h"
 #include <iostream>
@@ -44,8 +44,8 @@ std::string WStringToString(const std::wstring& s);
 //
 
 // Type mapping
-bool GDBToOGRGeometry(std::string geoType, bool hasZ, OGRwkbGeometryType* pOut);
-bool OGRGeometryToGDB(OGRwkbGeometryType ogrType, std::string *gdbType, bool *hasZ);
+bool GDBToOGRGeometry(std::string geoType, bool hasZ, bool hasM, OGRwkbGeometryType* pOut);
+bool OGRGeometryToGDB(OGRwkbGeometryType ogrType, std::string *gdbType, bool *hasZ, bool *hasM);
 
 
 bool GDBToOGRSpatialReference(const std::string & wkt, OGRSpatialReference** ppSR);
diff --git a/ogr/ogrsf_frmts/filegdb/drv_filegdb.html b/ogr/ogrsf_frmts/filegdb/drv_filegdb.html
index 17a13a8..dab35bd 100644
--- a/ogr/ogrsf_frmts/filegdb/drv_filegdb.html
+++ b/ogr/ogrsf_frmts/filegdb/drv_filegdb.html
@@ -1,124 +1,135 @@
-<html>
-<head>
-<title>ESRI File Geodatabase (FileGDB)</title>
-</head>
-
-<body bgcolor="#ffffff">
-
-<h1>ESRI File Geodatabase (FileGDB)</h1>
-
-<p>The FileGDB driver provides read and write access to File Geodatabases (.gdb directories) created by ArcGIS 10 and above.</p>
-
-<p>Note : starting with OGR 1.11, the <a href="drv_openfilegdb.html">OpenFileGDB driver</a> driver exists as an alternative built-in
-i.e. not depending on a third-party library) read-only driver.</p>
-
-<h2>Requirements</h2>
-
-<p>
-	<ul>
-		<li><a href="http://www.esri.com/apps/products/download/#File_Geodatabase_API_1.3">FileGDB API SDK</a></li>
-        <li>OGR >= 1.9.0</li>
-	</ul>
-</p>
-
-<h2>Bulk feature loading (OGR >= 1.9.2)</h2>
-
-The FGDB_BULK_LOAD configuration option can be set to YES to speed-up feature insertion (or sometimes solve problems
-when inserting a lot of features (see http://trac.osgeo.org/gdal/ticket/4420). The effect of this configuration option
-is to cause a write lock to be taken and a temporary disabling of the indexes. Those are restored when the datasource is
-closed or when a read operation is done.<p>
-
-Starting with GDAL 2.0, bulk load is enabled by default for newly created layers (unless otherwise specified).
-
-<h2>SQL support (OGR >= 1.10)</h2>
-
-Starting with OGR 1.10, SQL statements are run through the SQL engine of the FileGDB SDK API. This holds for non-SELECT
-statements. However, due to partial/inaccurate support for SELECT statements in current FileGDB SDK API versions (v1.2),
-SELECT statements will be run by default by the OGR SQL engine. This can be changed by specifying the
-<i>-dialect FileGDB</i> option to ogrinfo or ogr2ogr.
-
-<h3>Special SQL requests</h3>
-
-"GetLayerDefinition a_layer_name" and "GetLayerMetadata a_layer_name" can be used as special SQL requests to get
-respectively the definition and metadata of a FileGDB table as XML content.
-
-<h2>Transaction support (OGR >= 2.0)</h2>
-
-The FileGDB driver implements transactions at the database level, through an
-emulation (as per <a href="http://trac.osgeo.org/gdal/wiki/rfc54_dataset_transactions">RFC 54</a>),
-since the FileGDB SDK itself does not offer it. This works by backing up the
-current state of a geodatabase when StartTransaction(force=TRUE) is called.
-If the transaction is committed, the backup copy is destroyed. If the transaction
-is rolled back, the backup copy is restored. So this might be costly when operating
-on huge geodatabases.<p>
-
-Note that this emulation has an unspecified behaviour in case of concurrent updates
-(with different connections in the same or another process).<p>
-
-<h2>Dataset Creation Options</h2>
-
-<p>None.</p>
-
-<h2>Layer Creation Options</h2>
-
-<ul>
-	<li><b>FEATURE_DATASET</b>: When this option is set, the new layer will be created inside the named FeatureDataset folder. If the folder does not already exist, it will be created.</li>
-	<li><b>GEOMETRY_NAME</b>: Set name of geometry column in new layer. Defaults to "SHAPE".</li>
-        <li><b>GEOMETRY_NULLABLE</b>: (GDAL >=2.0)  Whether the values of the geometry column can be NULL. Can be set to NO so that geometry is required. Default to "YES"</li>
-	<li><b>FID</b>: Name of the OID column to create. Defaults to "OBJECTID". Note: option was called OID_NAME in releases before GDAL 2</li>
-	<li><b>XYTOLERANCE, ZTOLERANCE</b>: These parameters control the snapping tolerance used for advanced ArcGIS features like network and topology rules. They won't effect any 	OGR operations, but they will by used by ArcGIS. The units of the parameters are the units of the coordinate reference system.
-		<p>ArcMap 10.0 and OGR defaults for XYTOLERANCE are 0.001m (or equivalent) for projected coordinate systems, and 0.000000008983153° for geographic coordinate systems.</p></li>
-	<li><b>XORIGIN, YORIGIN, ZORIGIN, XYSCALE, ZSCALE</b>: These parameters control the <a href="http://help.arcgis.com/en/sdk/10.0/java_ao_adf/conceptualhelp/engine/index.html#//00010000037m000000">coordinate precision grid</a>  inside the file geodatabase. The dimensions of the grid are determined by the origin, and the scale. The origin defines the location of a reference grid point in space. The scale is the reciprocal of the resolution. So, to get a grid with an origin at 0 and a resol [...]
-		<p><em>Important</em>: The domain specified by <code>(xmin=XORIGIN, ymin=YORIGIN, xmax=(XORIGIN + 9E+15 / XYSCALE), ymax=(YORIGIN + 9E+15 / XYSCALE))</code> needs to encompass every possible coordinate value for the feature class. If features are added with coordinates that fall outside the domain, errors will occur in ArcGIS with spatial indexing, feature selection, and exporting data.</p>
-		<p>ArcMap 10.0 and OGR defaults:<ul>
-			<li>For geographic coordinate systems: XORIGIN=-400, YORIGIN=-400, XYSCALE=1000000000</li>
-			<li>For projected coordinate systems: XYSCALE=10000 for the default XYTOLERANCE of 0.001m. XORIGIN and YORIGIN change based on the coordinate system, but the OGR default of -2147483647 is suitable with the default XYSCALE for all coordinate systems.</li></ul></p></li>
-	<li><b>XML_DEFINITION</b> : (GDAL >= 1.10) When this option is set, its value will be used as the XML definition to create the new table. The root node of such a XML definition must be a <esri:DataElement> element conformant to FileGDBAPI.xsd</li>
-    <li><b>CREATE_MULTIPATCH</b>=YES : (GDAL >= 1.11) When this option is set, geometries of layers of type MultiPolygon will be written as MultiPatch</li>
-    <li><b>CONFIGURATION_KEYWORD</b>=DEFAULTS/TEXT_UTF16/MAX_FILE_SIZE_4GB/MAX_FILE_SIZE_256TB/GEOMETRY_OUTOFLINE/BLOB_OUTOFLINE/GEOMETRY_AND_BLOB_OUTOFLINE : (GDAL >= 2.0) Customize how data is stored. By default text in UTF-8 and data up to 1TB</li>
-</ul>
-
-<h2>Examples</h2>
-
-<ul>
-	<li>Read layer from FileGDB and load into PostGIS:</li>
-	<code>ogr2ogr -overwrite -skipfailures -f "PostgreSQL" PG:"host=myhost user=myuser dbname=mydb password=mypass" "C:\somefolder\BigFileGDB.gdb" "MyFeatureClass"</code>
-
-	<li>Get detailed info for FileGDB:</li>
-	<code>ogrinfo -al "C:\somefolder\MyGDB.gdb"</code>
-
-</ul>
-
-<h2>Building Notes</h2>
-
-<p> Read the <a href="http://trac.osgeo.org/gdal/wiki/BuildingOnWindows">GDAL Windows Building example for Plugins</a>. You will find a similar section in nmake.opt for FileGDB. After you are done, go to the <i>$gdal_source_root\ogr\ogrsf_frmts\filegdb</i> folder and execute:</p>
-
-<p>
-	<code>
-		nmake /f makefile.vc plugin
-		nmake /f makefile.vc plugin-install
-	</code>
-</p>
-
-
-<h2>Known Issues</h2>
-
-<ul>
-        <li>The SDK is known to be unable to open layers with particular spatialy reference systems.
-            This might be the case if messages "FGDB: Error opening XXXXXXX. Skipping it (Invalid function arguments.)"
-            when running "ogrinfo --debug on the.gdb" (reported as warning in GDAL 2.0).
-            Using the OpenFileGDB driver will generally solve that issue.</li>
-	<li>Blob fields have not been implemented.</li>
-	<li>FGDB coordinate snapping will cause geometries to be altered during writing. Use the origin and scale layer creation options to control the snapping behavior.</li>
-	<li>Driver can't read data from compressed feature classes (SDC, Smart Data Compression) because operation is not supported by the ESRI SDK.</li>
-</ul>
-
-<h2>Links</h2>
-
-<ul>
-<li><a href="http://www.esri.com/apps/products/download/#File_Geodatabase_API_1.3">ESRI File Geodatabase API Page</a></li>
-<li><a href="drv_openfilegdb.html">OpenFileGDB driver</a>, not depending on a third-party library/SDK</li>
-</ul>
-
-</body>
-</html>
+<html>
+<head>
+<title>ESRI File Geodatabase (FileGDB)</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>ESRI File Geodatabase (FileGDB)</h1>
+
+<p>The FileGDB driver provides read and write access to File Geodatabases (.gdb directories) created by ArcGIS 10 and above.</p>
+
+<p>Note : starting with OGR 1.11, the <a href="drv_openfilegdb.html">OpenFileGDB driver</a> driver exists as an alternative built-in
+i.e. not depending on a third-party library) read-only driver.</p>
+
+<h2>Requirements</h2>
+
+<p>
+	<ul>
+		<li><a href="http://www.esri.com/apps/products/download/#File_Geodatabase_API_1.3">FileGDB API SDK</a></li>
+        <li>OGR >= 1.9.0</li>
+	</ul>
+</p>
+
+<h2>Bulk feature loading (OGR >= 1.9.2)</h2>
+
+The FGDB_BULK_LOAD configuration option can be set to YES to speed-up feature insertion (or sometimes solve problems
+when inserting a lot of features (see http://trac.osgeo.org/gdal/ticket/4420). The effect of this configuration option
+is to cause a write lock to be taken and a temporary disabling of the indexes. Those are restored when the datasource is
+closed or when a read operation is done.<p>
+
+Starting with GDAL 2.0, bulk load is enabled by default for newly created layers (unless otherwise specified).
+
+<h2>SQL support (OGR >= 1.10)</h2>
+
+Starting with OGR 1.10, SQL statements are run through the SQL engine of the FileGDB SDK API. This holds for non-SELECT
+statements. However, due to partial/inaccurate support for SELECT statements in current FileGDB SDK API versions (v1.2),
+SELECT statements will be run by default by the OGR SQL engine. This can be changed by specifying the
+<i>-dialect FileGDB</i> option to ogrinfo or ogr2ogr.
+
+<h3>Special SQL requests</h3>
+
+"GetLayerDefinition a_layer_name" and "GetLayerMetadata a_layer_name" can be used as special SQL requests to get
+respectively the definition and metadata of a FileGDB table as XML content.
+
+<h2>Transaction support (OGR >= 2.0)</h2>
+
+The FileGDB driver implements transactions at the database level, through an
+emulation (as per <a href="http://trac.osgeo.org/gdal/wiki/rfc54_dataset_transactions">RFC 54</a>),
+since the FileGDB SDK itself does not offer it. This works by backing up the
+current state of a geodatabase when StartTransaction(force=TRUE) is called.
+If the transaction is committed, the backup copy is destroyed. If the transaction
+is rolled back, the backup copy is restored. So this might be costly when operating
+on huge geodatabases.<p>
+
+Starting with GDAL 2.1, on Linux/Unix, instead of a full backup copy only layers
+that are modified are backed up.<p>
+
+Note that this emulation has an unspecified behaviour in case of concurrent updates
+(with different connections in the same or another process).<p>
+
+<h2>CreateFeature() support</h2>
+
+The FileGDB SDK API does not allow to create a feature with a FID specified by
+the user. Starting with GDAL 2.1, the FileGDB driver implements a special FID
+remapping technique to enable the user to create features at the FID of their choice.<p>
+
+<h2>Dataset Creation Options</h2>
+
+<p>None.</p>
+
+<h2>Layer Creation Options</h2>
+
+<ul>
+	<li><b>FEATURE_DATASET</b>: When this option is set, the new layer will be created inside the named FeatureDataset folder. If the folder does not already exist, it will be created.</li>
+	<li><b>GEOMETRY_NAME</b>: Set name of geometry column in new layer. Defaults to "SHAPE".</li>
+        <li><b>GEOMETRY_NULLABLE</b>: (GDAL >=2.0)  Whether the values of the geometry column can be NULL. Can be set to NO so that geometry is required. Default to "YES"</li>
+	<li><b>FID</b>: Name of the OID column to create. Defaults to "OBJECTID". Note: option was called OID_NAME in releases before GDAL 2</li>
+	<li><b>XYTOLERANCE, ZTOLERANCE</b>: These parameters control the snapping tolerance used for advanced ArcGIS features like network and topology rules. They won't effect any 	OGR operations, but they will by used by ArcGIS. The units of the parameters are the units of the coordinate reference system.
+		<p>ArcMap 10.0 and OGR defaults for XYTOLERANCE are 0.001m (or equivalent) for projected coordinate systems, and 0.000000008983153° for geographic coordinate systems.</p></li>
+	<li><b>XORIGIN, YORIGIN, ZORIGIN, XYSCALE, ZSCALE</b>: These parameters control the <a href="http://help.arcgis.com/en/sdk/10.0/java_ao_adf/conceptualhelp/engine/index.html#//00010000037m000000">coordinate precision grid</a>  inside the file geodatabase. The dimensions of the grid are determined by the origin, and the scale. The origin defines the location of a reference grid point in space. The scale is the reciprocal of the resolution. So, to get a grid with an origin at 0 and a resol [...]
+		<p><em>Important</em>: The domain specified by <code>(xmin=XORIGIN, ymin=YORIGIN, xmax=(XORIGIN + 9E+15 / XYSCALE), ymax=(YORIGIN + 9E+15 / XYSCALE))</code> needs to encompass every possible coordinate value for the feature class. If features are added with coordinates that fall outside the domain, errors will occur in ArcGIS with spatial indexing, feature selection, and exporting data.</p>
+		<p>ArcMap 10.0 and OGR defaults:<ul>
+			<li>For geographic coordinate systems: XORIGIN=-400, YORIGIN=-400, XYSCALE=1000000000</li>
+			<li>For projected coordinate systems: XYSCALE=10000 for the default XYTOLERANCE of 0.001m. XORIGIN and YORIGIN change based on the coordinate system, but the OGR default of -2147483647 is suitable with the default XYSCALE for all coordinate systems.</li></ul></p></li>
+	<li><b>XML_DEFINITION</b> : (GDAL >= 1.10) When this option is set, its value will be used as the XML definition to create the new table. The root node of such a XML definition must be a <esri:DataElement> element conformant to FileGDBAPI.xsd</li>
+    <li><b>CREATE_MULTIPATCH</b>=YES : (GDAL >= 1.11) When this option is set, geometries of layers of type MultiPolygon will be written as MultiPatch</li>
+    <li><b>CONFIGURATION_KEYWORD</b>=DEFAULTS/TEXT_UTF16/MAX_FILE_SIZE_4GB/MAX_FILE_SIZE_256TB/GEOMETRY_OUTOFLINE/BLOB_OUTOFLINE/GEOMETRY_AND_BLOB_OUTOFLINE : (GDAL >= 2.0) Customize how data is stored. By default text in UTF-8 and data up to 1TB</li>
+</ul>
+
+<h2>Examples</h2>
+
+<ul>
+	<li>Read layer from FileGDB and load into PostGIS:</li>
+	<code>ogr2ogr -overwrite -skipfailures -f "PostgreSQL" PG:"host=myhost user=myuser dbname=mydb password=mypass" "C:\somefolder\BigFileGDB.gdb" "MyFeatureClass"</code>
+
+	<li>Get detailed info for FileGDB:</li>
+	<code>ogrinfo -al "C:\somefolder\MyGDB.gdb"</code>
+
+</ul>
+
+<h2>Building Notes</h2>
+
+<p> Read the <a href="http://trac.osgeo.org/gdal/wiki/BuildingOnWindows">GDAL Windows Building example for Plugins</a>. You will find a similar section in nmake.opt for FileGDB. After you are done, go to the <i>$gdal_source_root\ogr\ogrsf_frmts\filegdb</i> folder and execute:</p>
+
+<p>
+	<code>
+		nmake /f makefile.vc plugin
+		nmake /f makefile.vc plugin-install
+	</code>
+</p>
+
+
+<h2>Known Issues</h2>
+
+<ul>
+        <li>The SDK is known to be unable to open layers with particular spatial reference systems.
+            This might be the case if messages "FGDB: Error opening XXXXXXX. Skipping it (Invalid function arguments.)"
+            when running "ogrinfo --debug on the.gdb" (reported as warning in GDAL 2.0).
+            Using the OpenFileGDB driver will generally solve that issue.</li>
+	<li>Blob fields have not been implemented.</li>
+	<li>FGDB coordinate snapping will cause geometries to be altered during writing. Use the origin and scale layer creation options to control the snapping behavior.</li>
+	<li>Driver can't read data  in SDC format (Smart Data Compression) because operation is not supported by the ESRI SDK.</li>
+        <li>Reading data compressed in CDF format (Compressed Data Format) requires ESRI SDK 1.4 or later.</li>
+        <li>Curve in geometries are not currently supported.</li>
+</ul>
+
+<h2>Links</h2>
+
+<ul>
+<li><a href="http://www.esri.com/apps/products/download/#File_Geodatabase_API_1.3">ESRI File Geodatabase API Page</a></li>
+<li><a href="drv_openfilegdb.html">OpenFileGDB driver</a>, not depending on a third-party library/SDK</li>
+</ul>
+
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/filegdb/filegdbsdk_headers.h b/ogr/ogrsf_frmts/filegdb/filegdbsdk_headers.h
new file mode 100644
index 0000000..e253638
--- /dev/null
+++ b/ogr/ogrsf_frmts/filegdb/filegdbsdk_headers.h
@@ -0,0 +1,41 @@
+/******************************************************************************
+ *
+ * Project:  FileGDB
+ * Purpose:  Import FileGDB SDK headers
+ * Author:   Even Rouault <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+#ifndef FILEGDBSDK_HEADERS_H
+#define FILEGDBSDK_HEADERS_H
+
+#include "cpl_port.h"
+
+#ifdef HAVE_GCC_SYSTEM_HEADER
+#pragma GCC system_header
+#endif
+
+/* FGDB API headers */
+#include "FileGDBAPI.h"
+
+#endif
diff --git a/ogr/ogrsf_frmts/filegdb/makefile.vc b/ogr/ogrsf_frmts/filegdb/makefile.vc
index aa3332a..f88ab78 100644
--- a/ogr/ogrsf_frmts/filegdb/makefile.vc
+++ b/ogr/ogrsf_frmts/filegdb/makefile.vc
@@ -1,6 +1,12 @@
 OBJ     =       FGdbDriver.obj FGdbDatasource.obj FGdbLayer.obj FGdbUtils.obj FGdbResultLayer.obj
 EXTRAFLAGS =	-I.. -I..\generic -I..\.. -I$(FGDB_INC)
 
+!IFDEF FGDB_VERSION
+EXTRAFLAGS = $(EXTRAFLAGS) -DFGDB_VERSION=$(FGDB_VERSION)
+!ELSE
+EXTRAFLAGS = $(EXTRAFLAGS) -DFGDB_VERSION=010300
+!ENDIF
+
 GDAL_ROOT	=	..\..\..
 
 PLUGIN_DLL 	=	ogr_FileGDB.dll
diff --git a/ogr/ogrsf_frmts/filegdb/ogr_fgdb.h b/ogr/ogrsf_frmts/filegdb/ogr_fgdb.h
index 039085b..edd6923 100644
--- a/ogr/ogrsf_frmts/filegdb/ogr_fgdb.h
+++ b/ogr/ogrsf_frmts/filegdb/ogr_fgdb.h
@@ -1,5 +1,5 @@
 /******************************************************************************
-* $Id: ogr_fgdb.h 29330 2015-06-14 12:11:11Z rouault $
+* $Id: ogr_fgdb.h 33138 2016-01-24 11:18:11Z rouault $
 *
 * Project:  OpenGIS Simple Features Reference Implementation
 * Purpose:  Standard includes and class definitions ArcObjects OGR driver.
@@ -28,10 +28,15 @@
 * DEALINGS IN THE SOFTWARE.
 ****************************************************************************/
 
-#ifndef _OGR_FGDB_H_INCLUDED
-#define _OGR_FGDB_H_INCLUDED
+#ifndef OGR_FGDB_H_INCLUDED
+#define OGR_FGDB_H_INCLUDED
+
+#ifdef DEBUG_BOOL
+#define DO_NOT_USE_DEBUG_BOOL
+#endif
 
 #include <vector>
+#include <set>
 #include "ogrsf_frmts.h"
 #include "ogremulatedtransaction.h"
 
@@ -41,8 +46,8 @@
 /* GDAL XML handler */
 #include "cpl_minixml.h"
 
-/* FGDB API headers */
-#include "FileGDBAPI.h"
+/* FGDB API headers through our own inclusion file */
+#include "filegdbsdk_headers.h"
 
 /* Workaround needed for Linux, at least for FileGDB API 1.1 (#4455) */
 #if defined(__linux__)
@@ -86,6 +91,8 @@ protected:
   bool  m_forceMulti;
 
   bool OGRFeatureFromGdbRow(Row* pRow, OGRFeature** ppFeature);
+  
+  virtual void       CloseGDBObjects();
 
 public:
           virtual OGRFeature* GetNextFeature();
@@ -104,6 +111,23 @@ class FGdbLayer : public FGdbBaseLayer
   int                 m_bBulkLoadAllowed;
   int                 m_bBulkLoadInProgress;
 
+  virtual void        CloseGDBObjects();
+  int                 EditIndexesForFIDHack(const char* pszRadixTablename);
+  int                 EditGDBTablX(const CPLString& osGDBTablX,
+                                   const CPLString& osNewGDBTablX);
+  int                 EditATXOrSPX(const CPLString& osIndex);
+  int                 EditATXOrSPX( VSILFILE* fp,
+                                    int nThisPage,
+                                    int& nLastPageVisited,
+                                    int nDepth,
+                                    int nSizeIndexedValue,
+                                    GByte* pabyLastIndexedValue,
+                                    int& bIndexedValueIsValid,
+                                    int& nFirstIndexAtThisValue,
+                                    std::vector<int>& anPagesAtThisValue,
+                                    int& bSortThisValue,
+                                    int& bInvalidateIndex );
+
   void                StartBulkLoad();
   void                EndBulkLoad();
 
@@ -123,6 +147,14 @@ class FGdbLayer : public FGdbBaseLayer
   
   int                 m_bCreateMultipatch;
 
+  std::map<int,int>   m_oMapOGRFIDToFGDBFID;
+  std::map<int,int>   m_oMapFGDBFIDToOGRFID;
+  int                 m_nResyncThreshold;
+  void                ResyncIDs();
+  
+  int                 m_bSymlinkFlag;
+  int                 CreateRealCopy();
+
   char*               CreateFieldDefn(OGRFieldDefn& oField,
                                       int bApproxOK,
                                       std::string& fieldname_clean,
@@ -161,10 +193,15 @@ public:
   virtual OGRErr      DeleteFeature( GIntBig nFID );
 
   virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce );
+  virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
+
   virtual GIntBig     GetFeatureCount( int bForce );
   virtual OGRErr      SetAttributeFilter( const char *pszQuery );
-  virtual void 	      SetSpatialFilterRect (double dfMinX, double dfMinY, double dfMaxX, double dfMaxY);
+
   virtual void        SetSpatialFilter( OGRGeometry * );
+  virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+                { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
 
 //  virtual OGRErr        StartTransaction( );
 //  virtual OGRErr        CommitTransaction( );
@@ -179,6 +216,10 @@ public:
   OGRErr              GetLayerXML ( char **poXml );
   OGRErr              GetLayerMetadataXML ( char **poXmlMeta );
   
+  void                SetSymlinkFlag() { m_bSymlinkFlag = TRUE; }
+  
+  virtual const char* GetMetadataItem(const char* pszName, const char* pszDomain);
+  
 protected:
 
   bool GDBToOGRFields(CPLXMLNode* psFields);  
@@ -238,14 +279,23 @@ class FGdbDatabaseConnection;
 
 class FGdbDataSource : public OGRDataSource
 {
+  CPLString             m_osFSName;
+  CPLString             m_osPublicName;
+  std::set<OGRLayer*>   m_oSetSelectLayers;
+
+  int        FixIndexes();
+  int        bPerLayerCopyingForTransaction;
 
 public:
   FGdbDataSource(FGdbDriver* poDriver, FGdbDatabaseConnection* pConnection);
   virtual ~FGdbDataSource();
 
-  int         Open(const char *, int );
+  int         Open(const char* pszFSName, int bUpdate,
+                   const char* pszPublicName);
+
+  const char* GetName() { return m_osPublicName.c_str(); }
+  const char* GetFSName() { return m_osFSName.c_str(); }
 
-  const char* GetName() { return m_pszName; }
   int         GetLayerCount() { return static_cast<int>(m_layers.size()); }
 
   OGRLayer*   GetLayer( int );
@@ -264,6 +314,17 @@ public:
   Geodatabase* GetGDB() { return m_pGeodatabase; }
   bool         GetUpdate() { return m_bUpdate; }
   FGdbDatabaseConnection* GetConnection() { return m_pConnection; }
+  
+  GDALDriver* GetOpenFileGDBDrv() { return m_poOpenFileGDBDrv; }
+  int         HasSelectLayers() { return m_oSetSelectLayers.size() != 0; }
+  
+  int         Close(int bCloseGeodatabase = FALSE);
+  int         ReOpen();
+  
+  
+  int         HasPerLayerCopyingForTransaction();
+  void        SetPerLayerCopyingForTransaction(int bFlag) { bPerLayerCopyingForTransaction = bFlag; }
+  void        SetSymlinkFlagOnAllLayers();
 
   /*
   protected:
@@ -278,10 +339,10 @@ protected:
 
   FGdbDriver* m_poDriver;
   FGdbDatabaseConnection* m_pConnection;
-  char* m_pszName;
   std::vector <FGdbLayer*> m_layers;
   Geodatabase* m_pGeodatabase;
   bool m_bUpdate;
+  GDALDriver* m_poOpenFileGDBDrv;
 };
 
 /************************************************************************/
@@ -291,17 +352,25 @@ protected:
 class FGdbDatabaseConnection
 {
 public:
-    FGdbDatabaseConnection(Geodatabase* pGeodatabase) :
-        m_pGeodatabase(pGeodatabase), m_nRefCount(1), m_bLocked(FALSE) {}
+    FGdbDatabaseConnection(CPLString osName, Geodatabase* pGeodatabase) :
+        m_osName(osName), m_pGeodatabase(pGeodatabase), m_nRefCount(1), m_bLocked(FALSE),
+        m_bFIDHackInProgress(FALSE) {}
 
+    CPLString    m_osName;
     Geodatabase* m_pGeodatabase;
     int          m_nRefCount;
     int          m_bLocked;
+    int          m_bFIDHackInProgress;
     
     Geodatabase* GetGDB() { return m_pGeodatabase; }
     void         SetLocked(int bLockedIn) { m_bLocked = bLockedIn; }
     int          GetRefCount() const { return m_nRefCount; }
     int          IsLocked() const { return m_bLocked; }
+    
+    int          IsFIDHackInProgress() const { return m_bFIDHackInProgress; }
+    void         SetFIDHackInProgress(int bFlag) { m_bFIDHackInProgress = bFlag; }
+    int          OpenGeodatabase(const char* pszOverriddenName);
+    void         CloseGeodatabase();
 };
 
 class FGdbDriver : public OGRSFDriver, public IOGRTransactionBehaviour
diff --git a/ogr/ogrsf_frmts/fme/drv_fme.html b/ogr/ogrsf_frmts/fme/drv_fme.html
index b406679..0b951cc 100644
--- a/ogr/ogrsf_frmts/fme/drv_fme.html
+++ b/ogr/ogrsf_frmts/fme/drv_fme.html
@@ -8,23 +8,23 @@
 <h1>FMEObjects Gateway</h1>
 
 Feature sources supported by FMEObjects are supported for reading by OGR
-if the FMEObjects gateway is configured, and if a licensed copy of 
-FMEObjects is installed and accessable.<p>
+if the FMEObjects gateway is configured, and if a licensed copy of
+FMEObjects is installed and accessible.<p>
 
 To using the FMEObjects based readers the data source name passed should
 be the name of the FME reader to use, a colon and then the actual data
-source name (ie. the filename).  For instance, "NTF:F:\DATA\NTF\2144.NTF"
+source name (i.e. the filename).  For instance, "NTF:F:\DATA\NTF\2144.NTF"
 would indicate the NTF reader should be used to read the file
 
 There are a number of special cases:<p>
 
 <ul>
-<li> A data source ending in .fdd will be assumed to be an "FME Datasource 
-   Definition" file which will contain the reader name, the data source name, 
+<li> A data source ending in .fdd will be assumed to be an "FME Datasource
+   Definition" file which will contain the reader name, the data source name,
    and then a set of name/value pairs of lines for the macros suitable to pass
    to the createReader() call.  <p>
 
-<li> A datasource named PROMPT will result in prompting the user for 
+<li> A datasource named PROMPT will result in prompting the user for
    information using the regular FME dialogs.   This only works on Windows.<p>
 
 <li> A datasource named "PROMPT:filename" will result in prompting, and then
@@ -43,19 +43,19 @@ All FME geometry types should be properly supported.  FME graphical attributes
 
 In order to enable fast access to large datasets without having to
 retranslate them each time they are accessed, the FMEObjects gateway
-supports a mechanism to cache features read from FME readers in 
+supports a mechanism to cache features read from FME readers in
 "Fast Feature Stores", a native vector format for FME with a spatial
 index for fast spatial searches.  These cached files are kept in the
-directory indicated by the OGRFME_TMPDIR environment variable (or 
+directory indicated by the OGRFME_TMPDIR environment variable (or
 TMPDIR or /tmp or C:\ if that is not available). <p>
 
-The cached featur files will have the prefix FME_OLEDB_ and a master index
+The cached feature files will have the prefix FME_OLEDB_ and a master index
 is kept in the file ogrfmeds.ind.  To clear away the index delete all these
 files.  Do not just delete some.<p>
 
-By default features in the cache are re-read after 3600s (60 minutes).  
-Cache rentention times can be altered at compile time by altering 
-the fme2ogr.h include file. <p>
+By default features in the cache are re-read after 3600s (60 minutes).
+Cache retention times can be altered at compile time by altering
+the fme2ogr.h include file.<p>
 
 Input from the SDE and ORACLE readers are not cached.  These sources are
 treated specially in a number of other ways as well.<p>
@@ -64,12 +64,12 @@ treated specially in a number of other ways as well.<p>
 
 <ol>
 
-<li> Establishing an FME session is quite an expensive operation, on a 
-350Mhz Linux system this can be in exceess of 10s.<p>
+<li> Establishing an FME session is quite an expensive operation, on a
+350Mhz Linux system this can be in excess of 10s.<p>
 
 <li> Old files in the feature cache are cleaned up, but only on subsequent
 visits to the FMEObjects gateway code in OGR.  This means that if unused
-the FMEObjects gateway will leave old cached features around indefinately.<p>
+the FMEObjects gateway will leave old cached features around indefinitely.<p>
 
 </ol>
 
@@ -77,7 +77,7 @@ the FMEObjects gateway will leave old cached features around indefinately.<p>
 
 To include the FMEObjects gateway in an OGR build it is necessary to have
 FME loaded on the system.  The <i>--with-fme=</i><b>$FME_HOME</b> configuration
-switch should be supplied to configure.  The FMEObjects gateway is not 
+switch should be supplied to configure.  The FMEObjects gateway is not
 explicitly linked against (it is loaded later when it may be needed) so it
 is practical to distribute an OGR binary build with FMEObjects support without
 distributing FMEObjects.  It will just "work" for people who have FMEObjects
@@ -88,7 +88,7 @@ The FMEObjects gateway has been tested on Linux and Windows.<p>
 <hr>
 
 More information on the FME product line, and how to purchase a license for
-the FME software (enabling FMEObjects support) can be found on the 
+the FME software (enabling FMEObjects support) can be found on the
 Safe Software web site at <a href="http://www.safe.com/">www.safe.com</a>.
 Development of this driver was financially supported by Safe Software.<p>
 
diff --git a/ogr/ogrsf_frmts/fme/fme2ogr.h b/ogr/ogrsf_frmts/fme/fme2ogr.h
index d62915c..a172e36 100644
--- a/ogr/ogrsf_frmts/fme/fme2ogr.h
+++ b/ogr/ogrsf_frmts/fme/fme2ogr.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: fme2ogr.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: fme2ogr.h 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  FMEObjects Translator
  * Purpose:  Declarations for translating IFMEFeatures to OGRFeatures.
@@ -14,21 +14,21 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _FME2OGR_H_INCLUDED
-#define _FME2OGR_H_INCLUDED
+#ifndef FME2OGR_H_INCLUDED
+#define FME2OGR_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "cpl_minixml.h"
@@ -68,7 +68,7 @@ class OGRFMELayer : public OGRLayer
                                     OGRSpatialReference * );
 
     virtual OGRErr      SetAttributeFilter( const char * );
-    
+
     OGRSpatialReference *GetSpatialRef();
 
     OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
@@ -85,23 +85,23 @@ class OGRFMELayerCached : public OGRFMELayer
 
     char               *pszIndexBase;
     IFMESpatialIndex   *poIndex;
-    
+
     OGRFeature *        ReadNextIndexFeature();
 
     OGREnvelope         sExtents;
 
     int                 bQueryActive;
-    
+
   public:
                        OGRFMELayerCached( OGRFMEDataSource * );
     virtual            ~OGRFMELayerCached();
-                       
+
     virtual void        ResetReading();
     virtual OGRFeature *GetNextFeature();
     virtual GIntBig     GetFeatureCount( int bForce );
 
     virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
-    
+
     virtual int         TestCapability( const char * );
 
     int                 AssignIndex( const char *pszBase, const OGREnvelope*,
@@ -126,16 +126,16 @@ class OGRFMELayerDB : public OGRFMELayer
     IFMEStringArray     *poUserDirectives;
 
     int                 CreateReader();
-    
+
   public:
                        OGRFMELayerDB( OGRFMEDataSource * poDSIn,
                                       const char *pszReaderName,
                                       const char *pszDataset,
                                       IFMEStringArray *poUserDirectives );
     virtual            ~OGRFMELayerDB();
-                       
+
     virtual OGRErr      SetAttributeFilter( const char * );
-    
+
     virtual void        ResetReading();
     virtual OGRFeature *GetNextFeature();
     virtual GIntBig     GetFeatureCount( int bForce );
@@ -151,12 +151,12 @@ class OGRFMELayerDB : public OGRFMELayer
 
 class OGRFMEDataSource : public OGRDataSource
 {
-    char                *pszName;          // full name, ie. "SHAPE:D:\DATA"
-    char                *pszReaderName;    // reader/driver name, ie. "SHAPE"
-    char                *pszDataset;       // FME dataset name, ie. "D:\DATA"
+    char                *pszName;          // full name, i.e. "SHAPE:D:\DATA"
+    char                *pszReaderName;    // reader/driver name, i.e. "SHAPE"
+    char                *pszDataset;       // FME dataset name, i.e. "D:\DATA"
 
     IFMEStringArray   *poUserDirectives;
-    
+
     IFMESession         *poSession;
     IFMEUniversalReader *poReader;
 
@@ -182,15 +182,14 @@ class OGRFMEDataSource : public OGRDataSource
 
     void                ClarifyGeometryClass( IFMEFeature *poFeature,
                                           OGRwkbGeometryType &eBestGeomType );
-                                              
-    
+
   public:
                         OGRFMEDataSource();
                         ~OGRFMEDataSource();
 
     IFMESession *       AcquireSession();
     void                ReleaseSession();
-    
+
     int                 TestCapability( const char * );
 
     OGRGeometry        *ProcessGeometry( OGRFMELayer *, IFMEFeature *,
@@ -210,8 +209,8 @@ class OGRFMEDataSource : public OGRDataSource
     void                BuildSpatialIndexes();
 
     OGRSpatialReference *FME2OGRSpatialRef( const char *pszFMECoordsys );
-    
-    // Stuff related to persistent feature caches. 
+
+    // Stuff related to persistent feature caches.
     CPLXMLNode          *SerializeToXML();
     int                 InitializeFromXML( CPLXMLNode * );
 };
@@ -257,12 +256,12 @@ class OGRFMECacheIndex
 
     int         Lock();
     int         Unlock();
-    
+
     void        Touch( CPLXMLNode * );
     void        Add( CPLXMLNode * );
     void        Reference( CPLXMLNode * );
     void        Dereference( CPLXMLNode * );
-    
+
     int         ExpireOldCaches( IFMESession * );
 };
 
@@ -280,10 +279,10 @@ class OGRFMECacheIndex
 #endif
 
 // The number of seconds from creation a spatial cache should be retained in
-// the cache index before cleaning it up. 
+// the cache index before cleaning it up.
 // Default: 1hour
 #ifndef FMECACHE_MAX_RETENTION
-#  define FMECACHE_MAX_RETENTION    3600   
+#  define FMECACHE_MAX_RETENTION    3600
 #endif
 
 
@@ -291,4 +290,4 @@ CPL_C_START
 void RegisterOGRFME();
 CPL_C_END
 
-#endif /* ndef _FME2OGR_H_INCLUDED */
+#endif /* ndef FME2OGR_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/fme/fme2ogr_utils.cpp b/ogr/ogrsf_frmts/fme/fme2ogr_utils.cpp
index 7c71d11..56e4f4d 100644
--- a/ogr/ogrsf_frmts/fme/fme2ogr_utils.cpp
+++ b/ogr/ogrsf_frmts/fme/fme2ogr_utils.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: fme2ogr_utils.cpp 12123 2007-09-11 23:57:40Z warmerdam $
+ * $Id: fme2ogr_utils.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  FMEObjects Translator
  * Purpose:  Various FME related support functions.
@@ -14,16 +14,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
@@ -60,7 +60,7 @@ void CPLFMEError( IFMESession * poSession, const char *pszFormat, ... )
     {
         pszFMEErrorString = "FME reports no error message.";
     }
-   
+
 /* -------------------------------------------------------------------- */
 /*      Send composite error through CPL, and cleanup.                  */
 /* -------------------------------------------------------------------- */
@@ -70,6 +70,3 @@ void CPLFMEError( IFMESession * poSession, const char *pszFormat, ... )
 
     CPLFree( pszErrorBuf );
 }
-
-
-                  
diff --git a/ogr/ogrsf_frmts/fme/ogrfmecacheindex.cpp b/ogr/ogrsf_frmts/fme/ogrfmecacheindex.cpp
index 3452060..938a0c5 100644
--- a/ogr/ogrsf_frmts/fme/ogrfmecacheindex.cpp
+++ b/ogr/ogrsf_frmts/fme/ogrfmecacheindex.cpp
@@ -1,9 +1,9 @@
 /******************************************************************************
- * $Id: ogrfmecacheindex.cpp 12123 2007-09-11 23:57:40Z warmerdam $
+ * $Id: ogrfmecacheindex.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  FMEObjects Translator
  * Purpose:  Implement the OGRFMECacheIndex class, a mechanism to manage a
- *           persisent index list of cached datasets.
+ *           persistent index list of cached datasets.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -15,16 +15,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
@@ -35,13 +35,13 @@
 #include "cpl_string.h"
 #include <time.h>
 
-CPL_CVSID("$Id: ogrfmecacheindex.cpp 12123 2007-09-11 23:57:40Z warmerdam $");
+CPL_CVSID("$Id: ogrfmecacheindex.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                          OGRFMECacheIndex()                          */
 /************************************************************************/
 
-OGRFMECacheIndex::OGRFMECacheIndex( const char * pszPathIn ) 
+OGRFMECacheIndex::OGRFMECacheIndex( const char * pszPathIn )
 
 {
     psTree = NULL;
@@ -61,7 +61,7 @@ OGRFMECacheIndex::~OGRFMECacheIndex()
         Unlock();
         CPLDestroyXMLNode( psTree );
         psTree = NULL;
-    }       
+    }
     CPLFree( pszPath );
 }
 
@@ -130,7 +130,7 @@ int OGRFMECacheIndex::Load()
         psTree = CPLCreateXMLNode( NULL, CXT_Element, "OGRFMECacheIndex" );
         return TRUE;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Load the data from the file.                                    */
 /* -------------------------------------------------------------------- */
@@ -141,7 +141,7 @@ int OGRFMECacheIndex::Load()
     pszIndexBuffer = (char *) CPLMalloc(nLength+1);
     if( (int) VSIFRead( pszIndexBuffer, 1, nLength, fpIndex ) != nLength )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   "Read of %d byte index file failed.", nLength );
         return FALSE;
     }
@@ -154,7 +154,7 @@ int OGRFMECacheIndex::Load()
     psTree = CPLParseXMLString( pszIndexBuffer );
 
     CPLFree( pszIndexBuffer );
-    
+
     return psTree != NULL;
 }
 
@@ -198,8 +198,8 @@ int OGRFMECacheIndex::Save()
 /*      component values.                                               */
 /************************************************************************/
 
-CPLXMLNode *OGRFMECacheIndex::FindMatch( const char *pszDriver, 
-                                         const char *pszDataset, 
+CPLXMLNode *OGRFMECacheIndex::FindMatch( const char *pszDriver,
+                                         const char *pszDataset,
                                          IFMEStringArray &oUserDirectives )
 
 {
@@ -221,8 +221,8 @@ CPLXMLNode *OGRFMECacheIndex::FindMatch( const char *pszDriver,
         int        iDir;
 
         psDirective = CPLGetXMLNode( psCDS, "UserDirectives.Directive" );
-        for( iDir = 0; 
-             iDir < (int)oUserDirectives.entries() && bMatch; 
+        for( iDir = 0;
+             iDir < (int)oUserDirectives.entries() && bMatch;
              iDir++ )
         {
             if( psDirective == NULL || psDirective->psChild == NULL )
@@ -230,11 +230,11 @@ CPLXMLNode *OGRFMECacheIndex::FindMatch( const char *pszDriver,
             else if( !EQUAL(psDirective->psChild->pszValue,
                             oUserDirectives(iDir)) )
                 bMatch = FALSE;
-            else 
+            else
                 psDirective = psDirective->psNext;
         }
 
-        if( iDir < (int) oUserDirectives.entries() || !bMatch 
+        if( iDir < (int) oUserDirectives.entries() || !bMatch
             || (psDirective != NULL && psDirective->psNext != NULL) )
             continue;
 
@@ -281,7 +281,7 @@ void OGRFMECacheIndex::Reference( CPLXMLNode *psDSNode )
 
     char szNewRefCount[32];
 
-    sprintf( szNewRefCount, "%d", 
+    sprintf( szNewRefCount, "%d",
              atoi(CPLGetXMLValue(psDSNode, "RefCount", "0")) + 1 );
 
     CPLSetXMLValue( psDSNode, "RefCount", szNewRefCount );
@@ -296,8 +296,8 @@ void OGRFMECacheIndex::Reference( CPLXMLNode *psDSNode )
 void OGRFMECacheIndex::Dereference( CPLXMLNode *psDSNode )
 
 {
-    if( psDSNode == NULL 
-        || !EQUAL(psDSNode->pszValue,"DataSource") 
+    if( psDSNode == NULL
+        || !EQUAL(psDSNode->pszValue,"DataSource")
         || CPLGetXMLNode(psDSNode,"RefCount") == NULL )
         return;
 
@@ -365,7 +365,7 @@ int OGRFMECacheIndex::ExpireOldCaches( IFMESession *poSession )
     if( psTree == NULL )
         return FALSE;
 
-    for( psLastDSNode = NULL; TRUE; psLastDSNode = psDSNode )
+    for( psLastDSNode = NULL; true; psLastDSNode = psDSNode )
     {
         if( psLastDSNode != NULL )
             psDSNode = psLastDSNode->psNext;
@@ -376,21 +376,21 @@ int OGRFMECacheIndex::ExpireOldCaches( IFMESession *poSession )
 
         if( !EQUAL(psDSNode->pszValue,"DataSource") )
             continue;
-        
+
 /* -------------------------------------------------------------------- */
 /*      When was this datasource last accessed?                         */
 /* -------------------------------------------------------------------- */
         unsigned long nLastUseTime = 0;
 
-        sscanf( CPLGetXMLValue( psDSNode, "LastUseTime", "0" ), 
+        sscanf( CPLGetXMLValue( psDSNode, "LastUseTime", "0" ),
                 "%lu", &nLastUseTime );
-        
+
 /* -------------------------------------------------------------------- */
 /*      When was this datasource created.                               */
 /* -------------------------------------------------------------------- */
         unsigned long nCreationTime = 0;
 
-        sscanf( CPLGetXMLValue( psDSNode, "CreationTime", "0" ), 
+        sscanf( CPLGetXMLValue( psDSNode, "CreationTime", "0" ),
                 "%lu", &nCreationTime );
 
 /* -------------------------------------------------------------------- */
@@ -399,16 +399,16 @@ int OGRFMECacheIndex::ExpireOldCaches( IFMESession *poSession )
 /* -------------------------------------------------------------------- */
         int bCleanup = FALSE;
 
-        // Do we want to cleanup this node? 
-        if( atoi(CPLGetXMLValue( psDSNode, "RefCount", "0" )) > 0 
+        // Do we want to cleanup this node?
+        if( atoi(CPLGetXMLValue( psDSNode, "RefCount", "0" )) > 0
              && nLastUseTime + FMECACHE_REF_TIMEOUT < nCurTime )
             bCleanup = TRUE;
 
-        if( atoi(CPLGetXMLValue( psDSNode, "RefCount", "0" )) < 1 
+        if( atoi(CPLGetXMLValue( psDSNode, "RefCount", "0" )) < 1
             && nLastUseTime + FMECACHE_RETENTION < nCurTime )
             bCleanup = TRUE;
 
-        if( atoi(CPLGetXMLValue( psDSNode, "RefCount", "0" )) < 1 
+        if( atoi(CPLGetXMLValue( psDSNode, "RefCount", "0" )) < 1
             && nCreationTime + FMECACHE_MAX_RETENTION < nCurTime )
             bCleanup = TRUE;
 
@@ -417,7 +417,7 @@ int OGRFMECacheIndex::ExpireOldCaches( IFMESession *poSession )
 
         bChangeMade = TRUE;
 
-        CPLDebug( "OGRFMECacheIndex", 
+        CPLDebug( "OGRFMECacheIndex",
                   "ExpireOldCaches() cleaning up data source %s - %ds since last use, %ds old.",
                   CPLGetXMLValue( psDSNode, "DSName", "<missing name>" ),
                   nCurTime - nLastUseTime,
@@ -429,7 +429,7 @@ int OGRFMECacheIndex::ExpireOldCaches( IFMESession *poSession )
 /* -------------------------------------------------------------------- */
         CPLXMLNode *psLayerN;
 
-        for( psLayerN = psDSNode->psChild; 
+        for( psLayerN = psDSNode->psChild;
              psLayerN != NULL;
              psLayerN = psLayerN->psNext )
         {
@@ -454,11 +454,11 @@ int OGRFMECacheIndex::ExpireOldCaches( IFMESession *poSession )
             {
                 CPLDebug( "OGRFMECacheIndex", "Failed to open FME index %s.",
                           pszBase );
-                          
+
                 poSession->destroySpatialIndex( poIndex );
                 continue;
             }
-         
+
             poIndex->close( FME_TRUE );
             poSession->destroySpatialIndex( poIndex );
         }
diff --git a/ogr/ogrsf_frmts/fme/ogrfmedatasource.cpp b/ogr/ogrsf_frmts/fme/ogrfmedatasource.cpp
index a855747..3d972bd 100644
--- a/ogr/ogrsf_frmts/fme/ogrfmedatasource.cpp
+++ b/ogr/ogrsf_frmts/fme/ogrfmedatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrfmedatasource.cpp 27959 2014-11-14 18:29:21Z rouault $
+ * $Id: ogrfmedatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  FMEObjects Translator
  * Purpose:  Implementations of the OGRFMEDataSource class.
@@ -14,16 +14,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
@@ -39,7 +39,7 @@
 
 const char* kPROVIDERNAME = "FME_OLEDB";
 
-CPL_CVSID("$Id: ogrfmedatasource.cpp 27959 2014-11-14 18:29:21Z rouault $");
+CPL_CVSID("$Id: ogrfmedatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 #ifdef WIN32
 #define FMEDLL_NAME "fme.dll"
@@ -84,7 +84,7 @@ void FME_Logger( FME_MsgLevel severity, const char *message )
 
     if( pszMessageCopy[strlen(pszMessageCopy)-1] == '\n' )
         pszMessageCopy[strlen(pszMessageCopy)-1] = '\0';
-        
+
     CPLDebug( "FME_LOG", "%d:%s", severity, pszMessageCopy );
 
     CPLFree( pszMessageCopy );
@@ -121,13 +121,13 @@ static const char *GetTmpDir()
 }
 
 /************************************************************************/
-/*                            BuildTmpNam()                             */
+/*                            BuildTmpName()                             */
 /*                                                                      */
 /*      Create a basename for the temporary file for a given layer      */
 /*      on this dataset.                                                */
 /************************************************************************/
 
-static char *BuildTmpNam( const char *pszLayerName )
+static char *BuildTmpName( const char *pszLayerName )
 
 {
     int            i;
@@ -138,15 +138,15 @@ static char *BuildTmpNam( const char *pszLayerName )
 /* -------------------------------------------------------------------- */
 /*      Look for an unused name.                                        */
 /* -------------------------------------------------------------------- */
-    for( i = -1; TRUE; i++ )
+    for( i = -1; true; i++ )
     {
         if( i == -1 )
-            sprintf( szFilename, "%s%c%s_%s", 
+            sprintf( szFilename, "%s%c%s_%s",
                      pszTmpDir, PATH_CHAR, kPROVIDERNAME, pszLayerName );
         else
-            sprintf( szFilename, "%s%c%s_%s_%d", 
+            sprintf( szFilename, "%s%c%s_%s_%d",
                      pszTmpDir, PATH_CHAR, kPROVIDERNAME, pszLayerName, i );
-        
+
         if( VSIStat( szFilename, &sStat ) != 0 )
             break;
     }
@@ -196,7 +196,7 @@ OGRFMEDataSource::~OGRFMEDataSource()
 /* -------------------------------------------------------------------- */
     for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
-    
+
     CPLFree( papoLayers );
 
 /* -------------------------------------------------------------------- */
@@ -204,15 +204,15 @@ OGRFMEDataSource::~OGRFMEDataSource()
 /* -------------------------------------------------------------------- */
 #ifdef SUPPORT_PERSISTENT_CACHE
     {
-        OGRFMECacheIndex   oCacheIndex( 
+        OGRFMECacheIndex   oCacheIndex(
             CPLFormFilename(GetTmpDir(), "ogrfmeds", "ind" ) );
 
-        if( pszReaderName != NULL && nLayers > 0 
+        if( pszReaderName != NULL && nLayers > 0
             && bUseCaching && oCacheIndex.Lock() && oCacheIndex.Load() )
         {
             CPLXMLNode        *psMatchDS = NULL;
 
-            psMatchDS = oCacheIndex.FindMatch( pszReaderName, pszDataset, 
+            psMatchDS = oCacheIndex.FindMatch( pszReaderName, pszDataset,
                                                *poUserDirectives );
 
             if( psMatchDS != NULL )
@@ -242,7 +242,7 @@ OGRFMEDataSource::~OGRFMEDataSource()
         else
             CPLDebug( kPROVIDERNAME, "Preserving cached reader on destructor");
     }
-    
+
     if( poSession != NULL )
     {
         if( --nSharedSessionRefCount == 0 )
@@ -251,10 +251,10 @@ OGRFMEDataSource::~OGRFMEDataSource()
 #ifdef SUPPORT_INDIRECT_FMEDLL
             int (*pfnFME_destroySession)(void *);
 
-            pfnFME_destroySession = (int (*)(void*)) 
+            pfnFME_destroySession = (int (*)(void*))
                 CPLGetSymbol(FMEDLL_NAME, "FME_DestroySession" );
             if( pfnFME_destroySession == NULL )
-                CPLError( CE_Warning, CPLE_AppDefined, 
+                CPLError( CE_Warning, CPLE_AppDefined,
                           "Failed to fetch FME_DestroySession entry point." );
             else
                 pfnFME_destroySession( (void *) (&poSession) );
@@ -297,14 +297,14 @@ char *OGRFMEDataSource::PromptForSource()
     if( poDialog->sourcePrompt( NULL, NULL, *poSourceFormat, *poSourceDSName,
                                 *poUserDirectives ) )
     {
-        pszResult = CPLStrdup(CPLSPrintf("%s:%s", 
-                                         poSourceFormat->data(), 
+        pszResult = CPLStrdup(CPLSPrintf("%s:%s",
+                                         poSourceFormat->data(),
                                          poSourceDSName->data()));
     }
 
     poSession->destroyString( poSourceFormat );
     poSession->destroyString( poSourceDSName );
-        
+
     return pszResult;
 }
 
@@ -325,8 +325,8 @@ char *OGRFMEDataSource::ReadFileSource( const char *pszFilename )
     fp = VSIFOpen( pszFilename, "rt" );
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Failed to open file %s.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Failed to open file %s.",
                   pszFilename );
         return NULL;
     }
@@ -344,12 +344,12 @@ char *OGRFMEDataSource::ReadFileSource( const char *pszFilename )
 /* -------------------------------------------------------------------- */
     if( CSLCount(papszLines) < 2 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Insufficient lines in FME Data Definition file."
                   "At least a readername and data source name is required." );
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Apply extra values to user directives.                          */
 /* -------------------------------------------------------------------- */
@@ -374,8 +374,8 @@ char *OGRFMEDataSource::ReadFileSource( const char *pszFilename )
 /*                         SaveDefinitionFile()                         */
 /************************************************************************/
 
-static void SaveDefinitionFile( const char *pszFilename, 
-                                const char *pszReader, 
+static void SaveDefinitionFile( const char *pszFilename,
+                                const char *pszReader,
                                 const char *pszDatasource,
                                 IFMEStringArray &oUserDirectives )
 
@@ -449,24 +449,24 @@ int OGRFMEDataSource::Open( const char * pszCompositeName )
             || pszCompositeName[i] == '.' )
             break;
     }
-         
-    if( (i < 2 || pszCompositeName[i] != ':' 
-         || EQUALN(pszCompositeName,"OCI:",4)
-         || EQUALN(pszCompositeName,"gltp:",5)
-         || EQUALN(pszCompositeName,"http",4)
-         || EQUALN(pszCompositeName,"DODS:",5)
-         || EQUALN(pszCompositeName,"ODBC:",5)
-         || EQUALN(pszCompositeName,"MYSQL:",5))
+
+    if( (i < 2 || pszCompositeName[i] != ':'
+         || STARTS_WITH_CI(pszCompositeName, "OCI:")
+         || STARTS_WITH_CI(pszCompositeName, "gltp:")
+         || STARTS_WITH_CI(pszCompositeName, "http")
+         || STARTS_WITH_CI(pszCompositeName, "DODS:")
+         || STARTS_WITH_CI(pszCompositeName, "ODBC:")
+         || STARTS_WITH_CI(pszCompositeName, "MYSQL:"))
         && !EQUAL(CPLGetExtension( pszCompositeName ), "fdd")
-        && !EQUALN(pszCompositeName,"PROMPT",6) )
+        && !STARTS_WITH_CI(pszCompositeName, "PROMPT") )
     {
-        CPLDebug( kPROVIDERNAME, 
-                  "OGRFMEDataSource::Open(%s) don't try to open via FME.", 
+        CPLDebug( kPROVIDERNAME,
+                  "OGRFMEDataSource::Open(%s) don't try to open via FME.",
                   pszCompositeName );
         return FALSE;
     }
 
-    CPLDebug( kPROVIDERNAME, "OGRFMEDataSource::Open(%s):%p/%ld", 
+    CPLDebug( kPROVIDERNAME, "OGRFMEDataSource::Open(%s):%p/%ld",
               pszCompositeName, this, (long) CPLGetPID() );
 
 /* -------------------------------------------------------------------- */
@@ -495,7 +495,7 @@ int OGRFMEDataSource::Open( const char * pszCompositeName )
 /* -------------------------------------------------------------------- */
 /*      Prompt for a source, if none is provided.                       */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszCompositeName,"") || EQUALN(pszCompositeName,"PROMPT",6) )
+    if( EQUAL(pszCompositeName,"") || STARTS_WITH_CI(pszCompositeName, "PROMPT") )
     {
         pszName = PromptForSource();
         if( pszName == NULL )
@@ -520,7 +520,7 @@ int OGRFMEDataSource::Open( const char * pszCompositeName )
     }
 
 /* -------------------------------------------------------------------- */
-/*      Extract the reader name and password compontents.  The          */
+/*      Extract the reader name and password components.  The          */
 /*      reader name will be followed by a single colon and then the     */
 /*      FME DATASET name.                                               */
 /* -------------------------------------------------------------------- */
@@ -528,8 +528,8 @@ int OGRFMEDataSource::Open( const char * pszCompositeName )
 
     if( pszName[i] == '\0' || i < 2 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Failed to parse reader and data source from:\n%s", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Failed to parse reader and data source from:\n%s",
                   pszName );
         ReleaseSession();
         return FALSE;
@@ -543,14 +543,14 @@ int OGRFMEDataSource::Open( const char * pszCompositeName )
     CPLDebug( kPROVIDERNAME, "%s:parsed out dataset", pszDataset );
 
 /* -------------------------------------------------------------------- */
-/*      If we prompted for a defintion that includes a file to save     */
+/*      If we prompted for a definition that includes a file to save    */
 /*      it to, do the save now.                                         */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszCompositeName,"PROMPT:",7) 
+    if( STARTS_WITH_CI(pszCompositeName, "PROMPT:")
         && strlen(pszCompositeName) > 7 )
     {
-        SaveDefinitionFile( pszCompositeName+7, 
-                            pszReaderName, pszDataset, 
+        SaveDefinitionFile( pszCompositeName+7,
+                            pszReaderName, pszDataset,
                             *poUserDirectives );
     }
 
@@ -572,17 +572,17 @@ int OGRFMEDataSource::Open( const char * pszCompositeName )
 
 /* -------------------------------------------------------------------- */
 /*      Are we going to use the direct access DB mechanism, or the      */
-/*      spatiallly cached (dumb reader) mechanism.                      */
+/*      spatially cached (dumb reader) mechanism.                       */
 /* -------------------------------------------------------------------- */
-    bUseCaching = !EQUALN(pszReaderName,"SDE",3) 
-               && !EQUALN(pszReaderName,"ORACLE",6);
+    bUseCaching = !STARTS_WITH_CI(pszReaderName, "SDE")
+               && !STARTS_WITH_CI(pszReaderName, "ORACLE");
 
 /* -------------------------------------------------------------------- */
 /*      Is there already a cache for this dataset?  If so, we will      */
 /*      use it.                                                         */
 /* -------------------------------------------------------------------- */
 #ifdef SUPPORT_PERSISTENT_CACHE
-    OGRFMECacheIndex   oCacheIndex( 
+    OGRFMECacheIndex   oCacheIndex(
                            CPLFormFilename(GetTmpDir(), "ogrfmeds", "ind" ) );
     CPLXMLNode        *psMatchDS = NULL;
 
@@ -590,7 +590,7 @@ int OGRFMEDataSource::Open( const char * pszCompositeName )
     {
         int bNeedSave = oCacheIndex.ExpireOldCaches( poSession );
 
-        psMatchDS = oCacheIndex.FindMatch( pszReaderName, pszDataset, 
+        psMatchDS = oCacheIndex.FindMatch( pszReaderName, pszDataset,
                                            *poUserDirectives );
 
         if( psMatchDS != NULL )
@@ -631,10 +631,10 @@ int OGRFMEDataSource::Open( const char * pszCompositeName )
     IFMEStringArray     *poParms = poSession->createStringArray();
 
     for( i = 0; i < (int) poUserDirectives->entries(); i++ )
-        CPLDebug( kPROVIDERNAME, "oUserDirectives(%d) = '%s'", 
+        CPLDebug( kPROVIDERNAME, "oUserDirectives(%d) = '%s'",
                   i, (*poUserDirectives)(i) );
 
-    poReader = poSession->createReader(pszReaderName, FME_FALSE, 
+    poReader = poSession->createReader(pszReaderName, FME_FALSE,
                                        poUserDirectives);
     if( poReader == NULL )
     {
@@ -667,7 +667,7 @@ int OGRFMEDataSource::Open( const char * pszCompositeName )
 /*      "connection" open for a data source.  Offer this reader for     */
 /*      connection caching.                                             */
 /* -------------------------------------------------------------------- */
-    OfferForConnectionCaching( poReader, pszReaderName, 
+    OfferForConnectionCaching( poReader, pszReaderName,
                                pszDataset );
 
 /* -------------------------------------------------------------------- */
@@ -675,7 +675,7 @@ int OGRFMEDataSource::Open( const char * pszCompositeName )
 /* -------------------------------------------------------------------- */
     FME_Boolean         eEndOfSchema;
 
-    while( TRUE )
+    while( true )
     {
         err = poReader->readSchema( *poFMEFeature, eEndOfSchema );
         if( err )
@@ -688,7 +688,7 @@ int OGRFMEDataSource::Open( const char * pszCompositeName )
         if( eEndOfSchema == FME_TRUE )
             break;
 
-        CPLDebug( kPROVIDERNAME, "%p:readSchema() got %s.", 
+        CPLDebug( kPROVIDERNAME, "%p:readSchema() got %s.",
                   this, poFMEFeature->getFeatureType() );
 
         OGRFMELayer     *poNewLayer = NULL;
@@ -784,21 +784,21 @@ void OGRFMEDataSource::BuildSpatialIndexes()
 
         psCLI->pszCoordSys = NULL;
 
-        psCLI->pszIndFile = 
-            BuildTmpNam( papoLayers[iLayer]->GetLayerDefn()->GetName() );
+        psCLI->pszIndFile =
+            BuildTmpName( papoLayers[iLayer]->GetLayerDefn()->GetName() );
 
-        psCLI->poIndex = 
+        psCLI->poIndex =
             poSession->createSpatialIndex( psCLI->pszIndFile, "WRITE", NULL );
-        
+
         if( psCLI->poIndex == NULL || psCLI->poIndex->open() != 0 )
         {
-            CPLDebug( kPROVIDERNAME, 
+            CPLDebug( kPROVIDERNAME,
                       "Serious error creating or opening spatial index ... bailing." );
             return;
         }
 
         // our special marker meaning unset.
-        psCLI->eBestGeomType = (OGRwkbGeometryType) 500; 
+        psCLI->eBestGeomType = (OGRwkbGeometryType) 500;
     }
 
 /* -------------------------------------------------------------------- */
@@ -810,7 +810,7 @@ void OGRFMEDataSource::BuildSpatialIndexes()
         CacheLayerInfo *psCLI = NULL;
 
         poFMEFeature->getFeatureType( *poFMEString );
-        
+
         for( iLayer = 0; iLayer < nLayers; iLayer++ )
         {
             if( EQUAL(papoLayers[iLayer]->GetLayerDefn()->GetName(),
@@ -820,11 +820,11 @@ void OGRFMEDataSource::BuildSpatialIndexes()
                 break;
             }
         }
-        
+
         if( psCLI == NULL )
         {
-            CPLDebug( "FME_LOG", 
-                      "Skipping %s feature, doesn't match a layer.", 
+            CPLDebug( "FME_LOG",
+                      "Skipping %s feature, doesn't match a layer.",
                       poFMEString->data() );
             continue;
         }
@@ -835,7 +835,7 @@ void OGRFMEDataSource::BuildSpatialIndexes()
         FME_Real64  dfMinX, dfMaxX, dfMinY, dfMaxY;
 
         poFMEFeature->boundingBox( dfMinX, dfMaxX, dfMinY, dfMaxY );
-        
+
         if( psCLI->poIndex->entries() == 1 )
         {
             psCLI->sExtent.MinX = dfMinX;
@@ -863,10 +863,10 @@ void OGRFMEDataSource::BuildSpatialIndexes()
             else
             {
                 if( !EQUAL(psCLI->pszCoordSys,poFMEFeature->getCoordSys()) )
-                    CPLDebug( "FME_OLEDB", 
+                    CPLDebug( "FME_OLEDB",
                               "Conflicting coordsys %s (vs. %s) on layer %s.",
-                              poFMEFeature->getCoordSys(), 
-                              psCLI->pszCoordSys, 
+                              poFMEFeature->getCoordSys(),
+                              psCLI->pszCoordSys,
                               papoLayers[iLayer]->GetLayerDefn()->GetName() );
             }
         }
@@ -896,31 +896,31 @@ void OGRFMEDataSource::BuildSpatialIndexes()
 
             psCLI->poIndex->close(FME_FALSE);
             poSession->destroySpatialIndex( psCLI->poIndex );
-            
+
             if( psCLI->pszCoordSys != NULL && !bCoordSysOverride )
             {
-                CPLDebug("FME_OLEDB", 
+                CPLDebug("FME_OLEDB",
                          "Applying COORDSYS=%s to layer %s from feature scan.",
-                         psCLI->pszCoordSys, 
+                         psCLI->pszCoordSys,
                          papoLayers[iLayer]->GetLayerDefn()->GetName() );
-                       
+
                 poSpatialRef = FME2OGRSpatialRef( psCLI->pszCoordSys );
             }
 
             poLayer->AssignIndex( psCLI->pszIndFile, &(psCLI->sExtent),
                                   poSpatialRef );
-            if( psCLI->eBestGeomType != 500 
-                && psCLI->eBestGeomType 
+            if( psCLI->eBestGeomType != 500
+                && psCLI->eBestGeomType
                          != poLayer->GetLayerDefn()->GetGeomType() )
             {
-                CPLDebug( "FME_LOG", "Setting geom type from %d to %d", 
+                CPLDebug( "FME_LOG", "Setting geom type from %d to %d",
                           poLayer->GetLayerDefn()->GetGeomType(),
                           psCLI->eBestGeomType );
-                          
+
                 poLayer->GetLayerDefn()->SetGeomType( psCLI->eBestGeomType );
             }
         }
-            
+
         CPLFree( psCLI->pszIndFile );
         CPLFree( psCLI->pszCoordSys );
     }
@@ -956,7 +956,7 @@ void OGRFMEDataSource::BuildSpatialIndexes()
 /*      the polygons to multipolygon.                                   */
 /************************************************************************/
 
-void OGRFMEDataSource::ClarifyGeometryClass( 
+void OGRFMEDataSource::ClarifyGeometryClass(
     IFMEFeature *poFeature,
     OGRwkbGeometryType &eBestGeomType )
 
@@ -981,9 +981,9 @@ void OGRFMEDataSource::ClarifyGeometryClass(
         IFMEFeatureVector *poFeatVector;
 
         poFeatVector = poSession->createFeatureVector();
-        
+
         poFeature->splitAggregate( *poFeatVector );
-        
+
         for( int iPart = 0; iPart < (int)poFeatVector->entries(); iPart++ )
         {
             IFMEFeature      *poFMEPart = (*poFeatVector)(iPart);
@@ -1003,13 +1003,13 @@ void OGRFMEDataSource::ClarifyGeometryClass(
         else
             eThisType = wkbGeometryCollection;
     }
-    else 
+    else
         eThisType = wkbUnknown;
 
     // Is this 3D?
     if( poFeature->getDimension() == FME_THREE_D )
         eThisType = wkbSetZ(eThisType);
-    
+
 /* -------------------------------------------------------------------- */
 /*      Now adjust the working type.                                    */
 /* -------------------------------------------------------------------- */
@@ -1021,24 +1021,24 @@ void OGRFMEDataSource::ClarifyGeometryClass(
         /* do nothing */;
     else if( wkbFlatten(eThisType) == wkbFlatten(eBestGeomType) )
         /* no change */;
-    else if( wkbFlatten(eThisType) == wkbPolygon 
+    else if( wkbFlatten(eThisType) == wkbPolygon
              && wkbFlatten(eBestGeomType) == wkbMultiPolygon )
         /* do nothing */;
-    else if( wkbFlatten(eThisType) == wkbMultiPolygon 
+    else if( wkbFlatten(eThisType) == wkbMultiPolygon
              && wkbFlatten(eBestGeomType) == wkbPolygon )
         eNewBestGeomType = wkbMultiPolygon;
-    else if( wkbFlatten(eThisType) >= 4 && wkbFlatten(eThisType) <= 7 
+    else if( wkbFlatten(eThisType) >= 4 && wkbFlatten(eThisType) <= 7
           && wkbFlatten(eBestGeomType) >= 4 && wkbFlatten(eBestGeomType) <= 7 )
         /* they are both collections, but not the same ... go to generic coll*/
         eNewBestGeomType = wkbGeometryCollection;
     else
         eNewBestGeomType = wkbUnknown;
 
-    if( (wkbHasZ(eBestGeomType) || wkbHasZ(eThisType)) 
+    if( (wkbHasZ(eBestGeomType) || wkbHasZ(eThisType))
         && (int) eNewBestGeomType != 500 )
     {
         eNewBestGeomType = wkbSetZ(eNewBestGeomType);
-    } 
+    }
 
     eBestGeomType = eNewBestGeomType;
 }
@@ -1081,14 +1081,14 @@ int OGRFMEDataSource::ReadFMEFeature()
 /************************************************************************/
 
 OGRGeometry *
-OGRFMEDataSource::ProcessGeometry( OGRFMELayer * poLayer, 
+OGRFMEDataSource::ProcessGeometry( OGRFMELayer * poLayer,
                                    IFMEFeature * poGeomFeat,
                                    OGRwkbGeometryType eDesiredType  )
 {
-    
+
     FME_GeometryType      eGeomType = poGeomFeat->getGeometryType();
     int                   bForceToMulti = FALSE;
-    
+
     if( wkbFlatten(eDesiredType) == wkbGeometryCollection
         || wkbFlatten(eDesiredType) == wkbMultiPolygon )
         bForceToMulti = TRUE;
@@ -1112,10 +1112,10 @@ OGRFMEDataSource::ProcessGeometry( OGRFMELayer * poLayer,
         OGRLineString *poLine = new OGRLineString();
 
         poLine->setNumPoints( poGeomFeat->numCoords() );
-        
+
         for( int iPoint = 0; iPoint < (int) poGeomFeat->numCoords(); iPoint++ )
         {
-            poLine->setPoint( iPoint, 
+            poLine->setPoint( iPoint,
                               poGeomFeat->getXCoordinate(iPoint),
                               poGeomFeat->getYCoordinate(iPoint),
                               poGeomFeat->getZCoordinate(iPoint) );
@@ -1133,10 +1133,10 @@ OGRFMEDataSource::ProcessGeometry( OGRFMELayer * poLayer,
         OGRPolygon *poPolygon = new OGRPolygon();
 
         poLine->setNumPoints( poGeomFeat->numCoords() );
-        
+
         for( int iPoint = 0; iPoint < (int)poGeomFeat->numCoords(); iPoint++ )
         {
-            poLine->setPoint( iPoint, 
+            poLine->setPoint( iPoint,
                               poGeomFeat->getXCoordinate(iPoint),
                               poGeomFeat->getYCoordinate(iPoint),
                               poGeomFeat->getZCoordinate(iPoint) );
@@ -1163,9 +1163,9 @@ OGRFMEDataSource::ProcessGeometry( OGRFMELayer * poLayer,
         IFMEFeature      *poFMERing = NULL;
 
         poFeatVector = poSession->createFeatureVector();
-        
+
         poGeomFeat->getDonutParts( *poFeatVector );
-        
+
         for( int iPart = 0; iPart < (int)poFeatVector->entries(); iPart++ )
         {
             OGRLinearRing      *poRing;
@@ -1175,12 +1175,12 @@ OGRFMEDataSource::ProcessGeometry( OGRFMELayer * poLayer,
                 continue;
 
             poRing = new OGRLinearRing();
-            
+
             poRing->setNumPoints( poFMERing->numCoords() );
-        
+
             for( int iPoint=0; iPoint < (int)poFMERing->numCoords(); iPoint++ )
             {
-                poRing->setPoint( iPoint, 
+                poRing->setPoint( iPoint,
                                   poFMERing->getXCoordinate(iPoint),
                                   poFMERing->getYCoordinate(iPoint),
                                   poFMERing->getZCoordinate(iPoint) );
@@ -1220,9 +1220,9 @@ OGRFMEDataSource::ProcessGeometry( OGRFMELayer * poLayer,
             poCollection = new OGRGeometryCollection();
 
         poFeatVector = poSession->createFeatureVector();
-        
+
         poGeomFeat->splitAggregate( *poFeatVector );
-        
+
         for( int iPart = 0; iPart < (int)poFeatVector->entries(); iPart++ )
         {
             OGRGeometry      *poOGRPart;
@@ -1250,14 +1250,14 @@ OGRFMEDataSource::ProcessGeometry( OGRFMELayer * poLayer,
     }
     else
     {
-        CPLDebug( kPROVIDERNAME, 
+        CPLDebug( kPROVIDERNAME,
                   "unable to translate unsupported geometry type: %d\n",
                   eGeomType  );
 
         return NULL;
     }
 }
- 
+
 /************************************************************************/
 /*                           ProcessFeature()                           */
 /*                                                                      */
@@ -1283,7 +1283,7 @@ OGRFeature *OGRFMEDataSource::ProcessFeature( OGRFMELayer *poLayer,
     {
         OGRFieldDefn      *poField = poDefn->GetFieldDefn(iAttr);
 
-        if( poSrcFeature->getAttribute( poField->GetNameRef(), 
+        if( poSrcFeature->getAttribute( poField->GetNameRef(),
                                         *poFMEString ) == FME_TRUE )
         {
             poFeature->SetField( iAttr, poFMEString->data() );
@@ -1294,7 +1294,7 @@ OGRFeature *OGRFMEDataSource::ProcessFeature( OGRFMELayer *poLayer,
 /*      Translate the geometry.                                         */
 /* -------------------------------------------------------------------- */
     OGRGeometry      *poOGRGeom = NULL;
-    
+
     poOGRGeom = ProcessGeometry( poLayer, poSrcFeature,
                                  poLayer->GetLayerDefn()->GetGeomType() );
     if( poOGRGeom != NULL )
@@ -1329,8 +1329,8 @@ void OGRFMEDataSource::OfferForConnectionCaching(IFMEUniversalReader *poReader,
 /* -------------------------------------------------------------------- */
 /*      For now we only cache SDE readers.                              */
 /* -------------------------------------------------------------------- */
-    if( !EQUALN(pszReaderType,"SDE",3) 
-        && !EQUALN(pszReaderType,"ORACLE",6) )
+    if( !STARTS_WITH_CI(pszReaderType, "SDE")
+        && !STARTS_WITH_CI(pszReaderType, "ORACLE") )
         return;
 
 /* -------------------------------------------------------------------- */
@@ -1346,17 +1346,17 @@ void OGRFMEDataSource::OfferForConnectionCaching(IFMEUniversalReader *poReader,
 
     for( i = 0; i < (int) poUserDirectives->entries()-1; i += 2 )
     {
-        if( EQUALN((const char *) (*poUserDirectives)(i),"RUNTIME_MACROS",14) )
+        if( STARTS_WITH_CI((const char *) (*poUserDirectives)(i), "RUNTIME_MACROS") )
             pszRuntimeMacros = (*poUserDirectives)(i+1);
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Break into name/value pairs.                                    */
 /* -------------------------------------------------------------------- */
     char **papszTokens = NULL;
 
     if( pszRuntimeMacros != NULL )
-        papszTokens = CSLTokenizeStringComplex( pszRuntimeMacros, ",", 
+        papszTokens = CSLTokenizeStringComplex( pszRuntimeMacros, ",",
                                                 TRUE, TRUE);
 
 /* -------------------------------------------------------------------- */
@@ -1378,7 +1378,7 @@ void OGRFMEDataSource::OfferForConnectionCaching(IFMEUniversalReader *poReader,
             if( strlen(papszTokens[i+1]) + strlen(papszTokens[i]) + 20
                 < sizeof(szDefinition) - strlen(szDefinition) )
             {
-                sprintf( szDefinition + strlen(szDefinition), "%s=%s;", 
+                sprintf( szDefinition + strlen(szDefinition), "%s=%s;",
                          papszTokens[i], papszTokens[i+1] );
             }
         }
@@ -1392,24 +1392,24 @@ void OGRFMEDataSource::OfferForConnectionCaching(IFMEUniversalReader *poReader,
         if( strcmp(szDefinition, pasCachedConnections[i].pszDefinition) == 0 )
             return;
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Added this reader to the cache.                                 */
 /* -------------------------------------------------------------------- */
-    CPLDebug( kPROVIDERNAME, 
+    CPLDebug( kPROVIDERNAME,
               "Caching IFMEUniversalReader to maintain connection.\n"
-              "ReaderType=%s, Definition=%s", 
+              "ReaderType=%s, Definition=%s",
               pszReaderType, szDefinition );
 
     nCachedConnectionCount++;
-    pasCachedConnections = (CachedConnection *) 
-        CPLRealloc(pasCachedConnections, 
+    pasCachedConnections = (CachedConnection *)
+        CPLRealloc(pasCachedConnections,
                    sizeof(CachedConnection) * nCachedConnectionCount);
-    
+
     pasCachedConnections[nCachedConnectionCount-1].poReader = poReader;
-    pasCachedConnections[nCachedConnectionCount-1].pszReaderType = 
+    pasCachedConnections[nCachedConnectionCount-1].pszReaderType =
         CPLStrdup(pszReaderType);
-    pasCachedConnections[nCachedConnectionCount-1].pszDefinition = 
+    pasCachedConnections[nCachedConnectionCount-1].pszDefinition =
         CPLStrdup(szDefinition);
 }
 
@@ -1422,7 +1422,7 @@ int OGRFMEDataSource::IsPartOfConnectionCache( IFMEUniversalReader *poReader )
 
 {
     int            i;
-    
+
     for( i = 0; i < nCachedConnectionCount; i++ )
         if( poReader == pasCachedConnections[i].poReader )
             return TRUE;
@@ -1448,7 +1448,7 @@ IFMESession *OGRFMEDataSource::AcquireSession()
     {
         hSessionMutex = CPLCreateMutex();
 
-        CPLDebug( kPROVIDERNAME, "%p:Creating FME session, mutex=%d.", 
+        CPLDebug( kPROVIDERNAME, "%p:Creating FME session, mutex=%d.",
                   this, hSessionMutex );
     }
 
@@ -1464,7 +1464,7 @@ IFMESession *OGRFMEDataSource::AcquireSession()
 
         if( !CPLAcquireMutex( hSessionMutex, 5.0 ) )
         {
-            CPLDebug( kPROVIDERNAME, "%p:Failed to acquire session mutex in 5s.", 
+            CPLDebug( kPROVIDERNAME, "%p:Failed to acquire session mutex in 5s.",
                       this );
         }
 
@@ -1481,7 +1481,7 @@ IFMESession *OGRFMEDataSource::AcquireSession()
     {
 #ifdef SUPPORT_INDIRECT_FMEDLL
         FME_MsgNum (*pfnFME_CreateSession)( void * );
-        pfnFME_CreateSession = (FME_MsgNum (*)(void*)) 
+        pfnFME_CreateSession = (FME_MsgNum (*)(void*))
             CPLGetSymbol( FMEDLL_NAME, "FME_CreateSession" );
         if( pfnFME_CreateSession == NULL )
         {
@@ -1506,13 +1506,13 @@ IFMESession *OGRFMEDataSource::AcquireSession()
         // Dale Nov 26 '01 -- Set up to log "badnews" from FME
         // to help track down problems
 
-        IFMEStringArray *poSessionDirectives = 
+        IFMEStringArray *poSessionDirectives =
             poSharedSession->createStringArray();
 
         if( poSessionDirectives == NULL )
         {
             err = 1;
-            CPLError( CE_Warning, CPLE_AppDefined, 
+            CPLError( CE_Warning, CPLE_AppDefined,
                       "Something has gone wonky with createStringArray() on the IFMESession.\n"
                       "Is it possible you built with gcc 3.2 on Linux?  This seems problematic." );
 
@@ -1521,7 +1521,7 @@ IFMESession *OGRFMEDataSource::AcquireSession()
         {
             poSessionDirectives->append("FME_DEBUG");
             poSessionDirectives->append("BADNEWS");
-            
+
             err = poSharedSession->init( poSessionDirectives );
 
             poSharedSession->destroyStringArray( poSessionDirectives );
@@ -1539,7 +1539,7 @@ IFMESession *OGRFMEDataSource::AcquireSession()
 #ifdef SUPPORT_INDIRECT_FMEDLL
             int (*pfnFME_destroySession)(void *);
 
-            pfnFME_destroySession = (int (*)(void*)) 
+            pfnFME_destroySession = (int (*)(void*))
                 CPLGetSymbol(FMEDLL_NAME, "FME_DestroySession" );
             if( pfnFME_destroySession != NULL )
                 pfnFME_destroySession( (void *) (&poSharedSession) );
@@ -1605,7 +1605,7 @@ CPLXMLNode *OGRFMEDataSource::SerializeToXML()
 
     psUD = CPLCreateXMLNode( psDS, CXT_Element, "UserDirectives" );
     for( int i = 0; i < (int) poUserDirectives->entries(); i++ )
-        CPLCreateXMLElementAndValue( psUD, "Directive", 
+        CPLCreateXMLElementAndValue( psUD, "Directive",
                                      (*poUserDirectives)(i) );
 
 /* -------------------------------------------------------------------- */
@@ -1637,7 +1637,7 @@ int OGRFMEDataSource::InitializeFromXML( CPLXMLNode *psDS )
 /* -------------------------------------------------------------------- */
     CPLXMLNode *psLayerN;
 
-    for( psLayerN = psDS->psChild; psLayerN != NULL; 
+    for( psLayerN = psDS->psChild; psLayerN != NULL;
          psLayerN = psLayerN->psNext )
     {
         OGRFMELayerCached *poNewLayer;
@@ -1663,8 +1663,8 @@ int OGRFMEDataSource::InitializeFromXML( CPLXMLNode *psDS )
 /*      Assign the spatial index.  We should really change this to      */
 /*      check if it succeeds!                                           */
 /* -------------------------------------------------------------------- */
-        poNewLayer->AssignIndex( 
-            CPLGetXMLValue( psLayerN, "SpatialCacheName", 
+        poNewLayer->AssignIndex(
+            CPLGetXMLValue( psLayerN, "SpatialCacheName",
                             "<missing cachename>" ),
             NULL, NULL );
 
@@ -1696,7 +1696,7 @@ OGRFMEDataSource::FME2OGRSpatialRef( const char *pszCoordsys )
 
     poOGCDef = poSession->createString();
 
-    poSession->coordSysManager()->getCoordSysAsOGCDef( 
+    poSession->coordSysManager()->getCoordSysAsOGCDef(
         pszCoordsys, *poOGCDef );
 
     char *pszWKT = (char *) poOGCDef->data();
@@ -1713,8 +1713,3 @@ OGRFMEDataSource::FME2OGRSpatialRef( const char *pszCoordsys )
         return NULL;
     }
 }
-
-
-
-
-
diff --git a/ogr/ogrsf_frmts/fme/ogrfmedriver.cpp b/ogr/ogrsf_frmts/fme/ogrfmedriver.cpp
index 902a863..e84668f 100644
--- a/ogr/ogrsf_frmts/fme/ogrfmedriver.cpp
+++ b/ogr/ogrsf_frmts/fme/ogrfmedriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrfmedriver.cpp 12396 2007-10-13 10:02:17Z rouault $
+ * $Id: ogrfmedriver.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  FMEObjects Translator
  * Purpose:  Implementations of the OGRFMEDriver class.
@@ -14,23 +14,23 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
 #include "fme2ogr.h"
 #include "cpl_error.h"
 
-CPL_CVSID("$Id: ogrfmedriver.cpp 12396 2007-10-13 10:02:17Z rouault $");
+CPL_CVSID("$Id: ogrfmedriver.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -90,7 +90,7 @@ OGRDataSource *OGRFMEDriver::Open( const char * pszFilename, int bUpdate )
                   "FMEObjects Driver doesn't support update." );
         return NULL;
     }
-    
+
     return poDS;
 }
 
diff --git a/ogr/ogrsf_frmts/fme/ogrfmelayer.cpp b/ogr/ogrsf_frmts/fme/ogrfmelayer.cpp
index f45a45b..8d77d8b 100644
--- a/ogr/ogrsf_frmts/fme/ogrfmelayer.cpp
+++ b/ogr/ogrsf_frmts/fme/ogrfmelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrfmelayer.cpp 27959 2014-11-14 18:29:21Z rouault $
+ * $Id: ogrfmelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  FMEObjects Translator
  * Purpose:  Implementation of the OGRFMELayer base class.  The class
@@ -16,16 +16,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
@@ -33,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrfmelayer.cpp 27959 2014-11-14 18:29:21Z rouault $");
+CPL_CVSID("$Id: ogrfmelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                            OGRFMELayer()                             */
@@ -61,7 +61,7 @@ OGRFMELayer::~OGRFMELayer()
     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     {
         CPLDebug( "FME", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
+                  (int) m_nFeaturesRead,
                   poFeatureDefn->GetName() );
     }
 
@@ -91,7 +91,7 @@ int OGRFMELayer::Initialize( IFMEFeature * poSchemaFeature,
 
 {
     IFMEString  *poFMEString = NULL;
-    
+
     poFMEString = poDS->GetFMESession()->createString();
     poFMEFeature = poDS->GetFMESession()->createFeature();
 
@@ -124,7 +124,7 @@ int OGRFMELayer::Initialize( IFMEFeature * poSchemaFeature,
     OGRwkbGeometryType eGeomType = wkbNone;
     IFMEString  *poAttrValue;
     poAttrValue = poDS->GetFMESession()->createString();
-    
+
     for( int iAttr = 0; iAttr < (int)poAttrNames->entries(); iAttr++ )
     {
         const char       *pszAttrName = (*poAttrNames)(iAttr);
@@ -140,7 +140,7 @@ int OGRFMELayer::Initialize( IFMEFeature * poSchemaFeature,
 /*      the geometry type of this layer.  If we get conflicting         */
 /*      geometries just fall back to the generic geometry type.         */
 /* -------------------------------------------------------------------- */
-        if( EQUALN(pszAttrName,"fme_geometry",12) )
+        if( STARTS_WITH_CI(pszAttrName, "fme_geometry") )
         {
             OGRwkbGeometryType eAttrGeomType = wkbNone;
 
@@ -166,9 +166,9 @@ int OGRFMELayer::Initialize( IFMEFeature * poSchemaFeature,
                 eAttrGeomType = wkbNone;
             else
             {
-                CPLDebug( "FME_OLEDB", 
+                CPLDebug( "FME_OLEDB",
                           "geometry field %s has unknown value %s, ignored.",
-                          pszAttrName, 
+                          pszAttrName,
                           poAttrValue->data() );
                 continue;
             }
@@ -185,9 +185,9 @@ int OGRFMELayer::Initialize( IFMEFeature * poSchemaFeature,
 /*      with * appear to be massaged suitably for use, with fme         */
 /*      standard data types.                                            */
 /* -------------------------------------------------------------------- */
-        if( EQUALN(pszAttrName,"fme_geometry",12) 
+        if( STARTS_WITH_CI(pszAttrName, "fme_geometry")
             || pszAttrName[0] == '*'
-            || EQUALN(pszAttrName,"fme_geomattr",12) )
+            || STARTS_WITH_CI(pszAttrName, "fme_geomattr") )
         {
             continue;
         }
@@ -211,7 +211,7 @@ int OGRFMELayer::Initialize( IFMEFeature * poSchemaFeature,
             eType = OFTString;
             nWidth = atoi(papszTokens[1]);
         }
-        else if( CSLCount(papszTokens) == 3 
+        else if( CSLCount(papszTokens) == 3
                  && EQUAL(papszTokens[0],"fme_decimal") )
         {
             nWidth = atoi(papszTokens[1]);
@@ -236,7 +236,7 @@ int OGRFMELayer::Initialize( IFMEFeature * poSchemaFeature,
             eType = OFTInteger;
         }
         else if( CSLCount(papszTokens) == 1
-                 && (EQUAL(papszTokens[0],"fme_real32") 
+                 && (EQUAL(papszTokens[0],"fme_real32")
                      || EQUAL(papszTokens[0],"fme_real64")) )
         {
             nWidth = 0;
@@ -252,7 +252,7 @@ int OGRFMELayer::Initialize( IFMEFeature * poSchemaFeature,
         }
         else
         {
-            printf( "Not able to translate field type: %s\n", 
+            printf( "Not able to translate field type: %s\n",
                     poAttrValue->data() );
             CSLDestroy( papszTokens );
             continue;
@@ -262,7 +262,7 @@ int OGRFMELayer::Initialize( IFMEFeature * poSchemaFeature,
 /*      Add the field to the feature definition.                        */
 /* -------------------------------------------------------------------- */
         OGRFieldDefn  oFieldDefn( pszAttrName, eType );
-        
+
         oFieldDefn.SetWidth( nWidth );
         oFieldDefn.SetPrecision( nPrecision );
 
@@ -282,12 +282,12 @@ int OGRFMELayer::Initialize( IFMEFeature * poSchemaFeature,
 /* -------------------------------------------------------------------- */
 /*      Translate the spatial reference system.                         */
 /* -------------------------------------------------------------------- */
-    if( poSchemaFeature->getCoordSys() != NULL 
+    if( poSchemaFeature->getCoordSys() != NULL
         && strlen(poSchemaFeature->getCoordSys()) > 0
         && poSpatialRef == NULL )
     {
         CPLDebug( "FME_OLEDB", "Layer %s has COORDSYS=%s on schema feature.",
-                  poFeatureDefn->GetName(), 
+                  poFeatureDefn->GetName(),
                   poSchemaFeature->getCoordSys() );
         poSpatialRef = poDS->FME2OGRSpatialRef(poSchemaFeature->getCoordSys());
     }
diff --git a/ogr/ogrsf_frmts/fme/ogrfmelayercached.cpp b/ogr/ogrsf_frmts/fme/ogrfmelayercached.cpp
index 0bd17b6..a67cbad 100644
--- a/ogr/ogrsf_frmts/fme/ogrfmelayercached.cpp
+++ b/ogr/ogrsf_frmts/fme/ogrfmelayercached.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrfmelayercached.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrfmelayercached.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  FMEObjects Translator
  * Purpose:  Implementation of the OGRFMELayerCached class.  This is the
@@ -16,16 +16,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
@@ -33,13 +33,13 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrfmelayercached.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrfmelayercached.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                         OGRFMELayerCached()                          */
 /************************************************************************/
 
-OGRFMELayerCached::OGRFMELayerCached( OGRFMEDataSource *poDSIn ) 
+OGRFMELayerCached::OGRFMELayerCached( OGRFMEDataSource *poDSIn )
         : OGRFMELayer( poDSIn )
 
 {
@@ -82,12 +82,12 @@ OGRFMELayerCached::~OGRFMELayerCached()
 int OGRFMELayerCached::AssignIndex( const char *pszBase,
                                     const OGREnvelope *psExtents,
                                     OGRSpatialReference *poSRS )
-    
+
 {
     CPLAssert( poIndex == NULL );
-    
+
     pszIndexBase = CPLStrdup( pszBase );
-    poIndex = 
+    poIndex =
         poDS->GetFMESession()->createSpatialIndex( pszBase, "READ", NULL );
     if( poIndex == NULL )
         return FALSE;
@@ -121,7 +121,7 @@ int OGRFMELayerCached::TestCapability( const char * pszCap )
     if( EQUAL(pszCap,OLCRandomRead) )
         return FALSE;
 
-    else if( EQUAL(pszCap,OLCSequentialWrite) 
+    else if( EQUAL(pszCap,OLCSequentialWrite)
              || EQUAL(pszCap,OLCRandomWrite) )
         return FALSE;
 
@@ -134,7 +134,7 @@ int OGRFMELayerCached::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCFastGetExtent) )
         return TRUE;
 
-    else 
+    else
         return FALSE;
 }
 
@@ -182,7 +182,7 @@ OGRFeature *OGRFMELayerCached::GetNextFeature()
 {
     OGRFeature      *poFeature;
 
-    while( TRUE ) 
+    while( true )
     {
         poFeature = ReadNextIndexFeature();
 
@@ -191,7 +191,7 @@ OGRFeature *OGRFMELayerCached::GetNextFeature()
         else
             break;
 
-        if( m_poAttrQuery == NULL 
+        if( m_poAttrQuery == NULL
             || poIndex == NULL
             || m_poAttrQuery->Evaluate( poFeature ) )
             break;
@@ -205,7 +205,7 @@ OGRFeature *OGRFMELayerCached::GetNextFeature()
 /************************************************************************/
 /*                            ResetReading()                            */
 /************************************************************************/
- 
+
 void OGRFMELayerCached::ResetReading()
 
 {
@@ -235,7 +235,7 @@ void OGRFMELayerCached::ResetReading()
         poFMEFeature->setGeometryType( FME_GEOM_LINE );
         poFMEFeature->addCoordinate( oEnvelope.MinX, oEnvelope.MinY );
         poFMEFeature->addCoordinate( oEnvelope.MaxX, oEnvelope.MaxY );
-            
+
         poIndex->queryEnvelope( *poFMEFeature );
     }
 
@@ -297,17 +297,17 @@ CPLXMLNode *OGRFMELayerCached::SerializeToXML()
     char            szGeomType[64];
 
     psLayer = CPLCreateXMLNode( NULL, CXT_Element, "OGRLayer" );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Handle various layer values.                                    */
 /* -------------------------------------------------------------------- */
     CPLCreateXMLElementAndValue( psLayer, "Name", poFeatureDefn->GetName());
     sprintf( szGeomType, "%d", (int) poFeatureDefn->GetGeomType() );
-    CPLCreateXMLElementAndValue( psLayer, "GeomType", szGeomType );    
+    CPLCreateXMLElementAndValue( psLayer, "GeomType", szGeomType );
 
-    CPLCreateXMLElementAndValue( psLayer, "SpatialCacheName", 
+    CPLCreateXMLElementAndValue( psLayer, "SpatialCacheName",
                                  pszIndexBase );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Handle spatial reference if available.                          */
 /* -------------------------------------------------------------------- */
@@ -315,7 +315,7 @@ CPLXMLNode *OGRFMELayerCached::SerializeToXML()
     {
         char *pszWKT = NULL;
         OGRSpatialReference *poSRS = GetSpatialRef();
-        
+
         poSRS->exportToWkt( &pszWKT );
 
         if( pszWKT != NULL )
@@ -333,8 +333,8 @@ CPLXMLNode *OGRFMELayerCached::SerializeToXML()
     {
         char szExtent[512];
 
-        sprintf( szExtent, "%24.15E,%24.15E,%24.15E,%24.15E", 
-                 sEnvelope.MinX, sEnvelope.MinY, 
+        sprintf( szExtent, "%24.15E,%24.15E,%24.15E,%24.15E",
+                 sEnvelope.MinX, sEnvelope.MinY,
                  sEnvelope.MaxX, sEnvelope.MaxY );
         CPLCreateXMLElementAndValue( psLayer, "Extent", szExtent );
     }
@@ -343,7 +343,7 @@ CPLXMLNode *OGRFMELayerCached::SerializeToXML()
 /*      Emit the field schemas.                                         */
 /* -------------------------------------------------------------------- */
     CPLXMLNode *psSchema = CPLCreateXMLNode( psLayer, CXT_Element, "Schema" );
-    
+
     for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     {
         OGRFieldDefn *poFieldDef = poFeatureDefn->GetFieldDefn( iField );
@@ -353,7 +353,7 @@ CPLXMLNode *OGRFMELayerCached::SerializeToXML()
 
         sprintf( szWidth, "%d", poFieldDef->GetWidth() );
         sprintf( szPrecision, "%d", poFieldDef->GetPrecision() );
-        
+
         if( poFieldDef->GetType() == OFTInteger )
             pszType = "Integer";
         else if( poFieldDef->GetType() == OFTIntegerList )
@@ -393,12 +393,12 @@ int OGRFMELayerCached::InitializeFromXML( CPLXMLNode *psLayer )
 /* -------------------------------------------------------------------- */
     poFeatureDefn = new OGRFeatureDefn( CPLGetXMLValue(psLayer,"Name","X") );
     poFeatureDefn->Reference();
-    
+
 /* -------------------------------------------------------------------- */
 /*      Set the geometry type, if available.                            */
 /* -------------------------------------------------------------------- */
     if( CPLGetXMLNode( psLayer, "GeomType" ) != NULL )
-        poFeatureDefn->SetGeomType( (OGRwkbGeometryType) 
+        poFeatureDefn->SetGeomType( (OGRwkbGeometryType)
                      atoi(CPLGetXMLValue( psLayer, "GeomType", "0" )) );
 
 /* -------------------------------------------------------------------- */
@@ -406,11 +406,11 @@ int OGRFMELayerCached::InitializeFromXML( CPLXMLNode *psLayer )
 /* -------------------------------------------------------------------- */
     if( CPLGetXMLNode( psLayer, "Extent" ) != NULL )
     {
-        if( sscanf( CPLGetXMLValue( psLayer, "Extent", "" ), 
-                    "%lf,%lf,%lf,%lf", 
-                    &sExtents.MinX, 
-                    &sExtents.MaxX, 
-                    &sExtents.MinY, 
+        if( sscanf( CPLGetXMLValue( psLayer, "Extent", "" ),
+                    "%lf,%lf,%lf,%lf",
+                    &sExtents.MinX,
+                    &sExtents.MaxX,
+                    &sExtents.MinY,
                     &sExtents.MaxY ) != 4 )
         {
             memset( &sExtents, 0, sizeof(sExtents) );
diff --git a/ogr/ogrsf_frmts/fme/ogrfmelayerdb.cpp b/ogr/ogrsf_frmts/fme/ogrfmelayerdb.cpp
index 0b61a54..a8d3cd8 100644
--- a/ogr/ogrsf_frmts/fme/ogrfmelayerdb.cpp
+++ b/ogr/ogrsf_frmts/fme/ogrfmelayerdb.cpp
@@ -1,11 +1,11 @@
 /******************************************************************************
- * $Id: ogrfmelayerdb.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrfmelayerdb.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  FMEObjects Translator
  * Purpose:  Implementation of the OGRFMELayerDB class.  This is the
  *           class implementing behaviour for layers that are built on
- *           smart readers representing databases with spatial constraints, 
- *           and where clause support. 
+ *           smart readers representing databases with spatial constraints,
+ *           and where clause support.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -17,16 +17,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
@@ -34,14 +34,14 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrfmelayerdb.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrfmelayerdb.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                           OGRFMELayerDB()                            */
 /************************************************************************/
 
-OGRFMELayerDB::OGRFMELayerDB( OGRFMEDataSource *poDSIn, 
-                              const char *pszReaderNameIn, 
+OGRFMELayerDB::OGRFMELayerDB( OGRFMEDataSource *poDSIn,
+                              const char *pszReaderNameIn,
                               const char *pszDatasetIn,
                               IFMEStringArray *poUserDirectivesIn )
         : OGRFMELayer( poDSIn )
@@ -58,7 +58,7 @@ OGRFMELayerDB::OGRFMELayerDB( OGRFMEDataSource *poDSIn,
 
     for( FME_UInt32 i = 0; i < poUserDirectivesIn->entries(); i++ )
     {
-        CPLDebug( "FMEOLEDB", "userDirective[%d] = %s\n", 
+        CPLDebug( "FMEOLEDB", "userDirective[%d] = %s\n",
                   i, (const char *) (*poUserDirectivesIn)(i) );
 
         poUserDirectives->append( (*poUserDirectivesIn)(i) );
@@ -89,7 +89,7 @@ int OGRFMELayerDB::TestCapability( const char * pszCap )
     if( EQUAL(pszCap,OLCRandomRead) )
         return FALSE;
 
-    else if( EQUAL(pszCap,OLCSequentialWrite) 
+    else if( EQUAL(pszCap,OLCSequentialWrite)
              || EQUAL(pszCap,OLCRandomWrite) )
         return FALSE;
 
@@ -99,7 +99,7 @@ int OGRFMELayerDB::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCFastSpatialFilter) )
         return TRUE;
 
-    else 
+    else
         return FALSE;
 }
 
@@ -143,7 +143,7 @@ OGRFeature *OGRFMELayerDB::GetNextFeature()
     poFeature = poDS->ProcessFeature( this, poFMEFeature );
 
     if( nPreviousFeature == -1 )
-        CPLDebug( "FMEOLEDB", "Fetching first feature from layer `%s'.", 
+        CPLDebug( "FMEOLEDB", "Fetching first feature from layer `%s'.",
                   GetLayerDefn()->GetName() );
 
     poFeature->SetFID( ++nPreviousFeature );
@@ -157,7 +157,7 @@ OGRFeature *OGRFMELayerDB::GetNextFeature()
 /************************************************************************/
 /*                            ResetReading()                            */
 /************************************************************************/
- 
+
 void OGRFMELayerDB::ResetReading()
 
 {
@@ -179,30 +179,30 @@ void OGRFMELayerDB::ResetReading()
 /*                              SetMacro()                              */
 /*                                                                      */
 /*      Set the value of one macro within a set of macros stored in     */
-/*      comma delimeted name value pairs (as per RUNTIME_MACROS in      */
+/*      comma delimited name value pairs (as per RUNTIME_MACROS in      */
 /*      user directives).                                               */
 /************************************************************************/
 
-static void SetMacro( IFMEString *poMacros, const char *pszTarget, 
+static void SetMacro( IFMEString *poMacros, const char *pszTarget,
                       const char *pszNewValue )
 
 {
     char      *pszWorking, *pszValStart;
     int       nOldValLength;
 
-    pszWorking = (char *) CPLMalloc(strlen(poMacros->data()) 
-                                    + strlen(pszNewValue) 
+    pszWorking = (char *) CPLMalloc(strlen(poMacros->data())
+                                    + strlen(pszNewValue)
                                     + strlen(pszTarget) + 20 );
     strcpy( pszWorking, poMacros->data() );
 
     pszValStart = strstr( pszWorking, pszTarget );
-    if( pszValStart == NULL 
+    if( pszValStart == NULL
         || pszValStart[strlen(pszTarget)] != ',' )
     {
         if( strlen(pszWorking) > 0 )
             strcat( pszWorking, "," );
 
-        sprintf( pszWorking + strlen(pszWorking), "%s,%s", 
+        sprintf( pszWorking + strlen(pszWorking), "%s,%s",
                  pszTarget, pszNewValue );
         *poMacros = pszWorking;
         CPLFree( pszWorking );
@@ -211,13 +211,13 @@ static void SetMacro( IFMEString *poMacros, const char *pszTarget,
 
     pszValStart += strlen(pszTarget) + 1;
 
-    for( nOldValLength = 0; 
-         pszValStart[nOldValLength] != ',' 
-             && pszValStart[nOldValLength] != '\0'; 
+    for( nOldValLength = 0;
+         pszValStart[nOldValLength] != ','
+             && pszValStart[nOldValLength] != '\0';
          nOldValLength++ ) {}
 
-    memmove( pszValStart + strlen(pszNewValue), 
-            pszValStart + nOldValLength, 
+    memmove( pszValStart + strlen(pszNewValue),
+            pszValStart + nOldValLength,
             strlen(pszValStart + nOldValLength)+1 );
 
     memcpy( pszValStart, pszNewValue, strlen( pszNewValue ) );
@@ -265,11 +265,11 @@ int OGRFMELayerDB::CreateReader()
 
     for( i = 0; i < poUserDirectives->entries(); i++ )
         poUDC->append( (*poUserDirectives)(i) );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Update the IDLIST to just select the desired table.             */
 /* -------------------------------------------------------------------- */
-    
+
     for( i = 0; i < poUDC->entries(); i++ )
     {
         if( EQUAL((const char *) (*poUDC)(i),"IDLIST") )
@@ -310,18 +310,18 @@ int OGRFMELayerDB::CreateReader()
                 poUDC->getElement( i+1, *poMacroValue );
 
                 m_poFilterGeom->getEnvelope( &oEnvelope );
-                
-                if( EQUALN(pszReaderName,"SDE",3) )
+
+                if( STARTS_WITH_CI(pszReaderName, "SDE") )
                 {
                     sprintf( szSEARCH_ENVELOPE, "%.16f", oEnvelope.MinX );
                     SetMacro( poMacroValue, "_SDE3MINX", szSEARCH_ENVELOPE );
-                    
+
                     sprintf( szSEARCH_ENVELOPE, "%.16f", oEnvelope.MinY );
                     SetMacro( poMacroValue, "_SDE3MINY", szSEARCH_ENVELOPE );
-                    
+
                     sprintf( szSEARCH_ENVELOPE, "%.16f", oEnvelope.MaxX );
                     SetMacro( poMacroValue, "_SDE3MAXX", szSEARCH_ENVELOPE );
-                    
+
                     sprintf( szSEARCH_ENVELOPE, "%.16f", oEnvelope.MaxY );
                     SetMacro( poMacroValue, "_SDE3MAXY", szSEARCH_ENVELOPE );
                 }
@@ -329,20 +329,20 @@ int OGRFMELayerDB::CreateReader()
                 {
                     sprintf( szSEARCH_ENVELOPE, "%.16f", oEnvelope.MinX );
                     SetMacro( poMacroValue, "_ORACLE_MINX", szSEARCH_ENVELOPE);
-                    
+
                     sprintf( szSEARCH_ENVELOPE, "%.16f", oEnvelope.MinY );
                     SetMacro( poMacroValue, "_ORACLE_MINY", szSEARCH_ENVELOPE);
-                    
+
                     sprintf( szSEARCH_ENVELOPE, "%.16f", oEnvelope.MaxX );
                     SetMacro( poMacroValue, "_ORACLE_MAXX", szSEARCH_ENVELOPE);
-                    
+
                     sprintf( szSEARCH_ENVELOPE, "%.16f", oEnvelope.MaxY );
                     SetMacro( poMacroValue, "_ORACLE_MAXY", szSEARCH_ENVELOPE);
                 }
 
                 poUDC->setElement( i+1, *poMacroValue );
 
-                CPLDebug( "FMEOLEDB", "Update %s to:\n%s", 
+                CPLDebug( "FMEOLEDB", "Update %s to:\n%s",
                           pszDirective, poMacroValue->data() );
 
                 poSession->destroyString( poMacroValue );
@@ -350,7 +350,7 @@ int OGRFMELayerDB::CreateReader()
             }
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create new reader with desired constraints.                     */
 /* -------------------------------------------------------------------- */
@@ -371,7 +371,7 @@ int OGRFMELayerDB::CreateReader()
 
     if( pszAttributeFilter != NULL && strlen(pszAttributeFilter) > 0 )
     {
-        if( EQUALN(pszReaderName,"SDE",3) )
+        if( STARTS_WITH_CI(pszReaderName, "SDE") )
             poParms->append( "WHERE" );
         else
             poParms->append( "WHERE_CLAUSE" );
@@ -406,7 +406,7 @@ int OGRFMELayerDB::CreateReader()
 
     for( i = 0; i < poParms->entries(); i++ )
     {
-        CPLDebug( "FMEOLEDB", "openParms[%d] = %s", 
+        CPLDebug( "FMEOLEDB", "openParms[%d] = %s",
                   i, (const char *) (*poParms)(i) );
     }
 
diff --git a/ogr/ogrsf_frmts/generic/GNUmakefile b/ogr/ogrsf_frmts/generic/GNUmakefile
index 70a2e70..6d0a865 100644
--- a/ogr/ogrsf_frmts/generic/GNUmakefile
+++ b/ogr/ogrsf_frmts/generic/GNUmakefile
@@ -7,11 +7,9 @@ OBJ	=	ogrsfdriverregistrar.o ogrlayer.o ogrdatasource.o \
 		ogr_attrind.o ogr_miattrind.o ogrlayerdecorator.o \
 		ogrwarpedlayer.o ogrunionlayer.o ogrlayerpool.o \
 		ogrmutexedlayer.o ogrmutexeddatasource.o \
-		ogremulatedtransaction.o
+		ogremulatedtransaction.o ogreditablelayer.o
 
-CXXFLAGS :=     $(CXXFLAGS) -DINST_DATA=\"$(INST_DATA)\"
-
-ifeq ($(OGR_ENABLED),yes)
+CXXFLAGS :=     $(CXXFLAGS) $(SHADOW_WFLAGS) -DINST_DATA=\"$(INST_DATA)\"
 
 BASEFORMATS = \
 	-DAVCBIN_ENABLED \
@@ -54,7 +52,8 @@ BASEFORMATS = \
 	-DOPENFILEGDB_ENABLED \
 	-DWASP_ENABLED \
 	-DSELAFIN_ENABLED \
-	-DJML_ENABLED
+	-DJML_ENABLED \
+	-DVDV_ENABLED
 
 CXXFLAGS :=     $(CXXFLAGS) $(BASEFORMATS)
 
@@ -172,10 +171,6 @@ CXXFLAGS :=	$(CXXFLAGS) -DGFT_ENABLED
 endif
 
 ifeq ($(CURL_SETTING),yes)
-CXXFLAGS :=	$(CXXFLAGS) -DGME_ENABLED
-endif
-
-ifeq ($(CURL_SETTING),yes)
 CXXFLAGS :=	$(CXXFLAGS) -DCOUCHDB_ENABLED
 endif
 
@@ -212,9 +207,15 @@ CXXFLAGS :=	$(CXXFLAGS) -DCARTODB_ENABLED
 endif
 
 ifeq ($(CURL_SETTING),yes)
+CXXFLAGS :=	$(CXXFLAGS) -DAMIGOCLOUD_ENABLED
+endif
+
+ifeq ($(CURL_SETTING),yes)
 CXXFLAGS :=	$(CXXFLAGS) -DPLSCENES_ENABLED
 endif
 
+ifeq ($(HAVE_MONGODB),yes)
+CXXFLAGS :=	$(CXXFLAGS) -DMONGODB_ENABLED
 endif
 
 CPPFLAGS	:=	-I.. -I../..  $(CPPFLAGS)
diff --git a/ogr/ogrsf_frmts/generic/makefile.vc b/ogr/ogrsf_frmts/generic/makefile.vc
index 00de6ba..2a188b3 100644
--- a/ogr/ogrsf_frmts/generic/makefile.vc
+++ b/ogr/ogrsf_frmts/generic/makefile.vc
@@ -4,7 +4,7 @@ OBJ	=	ogrsfdriverregistrar.obj ogrlayer.obj ogr_gensql.obj \
 		ogr_attrind.obj ogr_miattrind.obj ogrlayerdecorator.obj \
 		ogrwarpedlayer.obj ogrunionlayer.obj ogrlayerpool.obj \
 		ogrmutexedlayer.obj ogrmutexeddatasource.obj \
-		ogremulatedtransaction.obj
+		ogremulatedtransaction.obj ogreditablelayer.obj
 
 
 GDAL_ROOT	=	..\..\..
@@ -13,21 +13,21 @@ GDAL_ROOT	=	..\..\..
 
 !IFDEF INCLUDE_OGR_FRMTS
 
-BASEFORMATS = -DSHAPE_ENABLED -DTAB_ENABLED -DNTF_ENABLED -DSDTS_ENABLED -DTIGER_ENABLED -DS57_ENABLED -DDGN_ENABLED -DVRT_ENABLED -DAVCBIN_ENABLED -DREC_ENABLED -DMEM_ENABLED -DCSV_ENABLED -DGML_ENABLED -DGMT_ENABLED -DBNA_ENABLED -DKML_ENABLED -DGEOJSON_ENABLED -DGPX_ENABLED -DGEOCONCEPT_ENABLED -DXPLANE_ENABLED -DGEORSS_ENABLED -DGTM_ENABLED -DDXF_ENABLED -DPGDUMP_ENABLED -DGPSBABEL_ENABLED -DSUA_ENABLED -DOPENAIR_ENABLED -DPDS_ENABLED -DHTF_ENABLED -DAERONAVFAA_ENABLED -DEDIGEO_ENABL [...]
+BASEFORMATS = -DSHAPE_ENABLED -DTAB_ENABLED -DNTF_ENABLED -DSDTS_ENABLED -DTIGER_ENABLED -DS57_ENABLED -DDGN_ENABLED -DVRT_ENABLED -DAVCBIN_ENABLED -DREC_ENABLED -DMEM_ENABLED -DCSV_ENABLED -DGML_ENABLED -DGMT_ENABLED -DBNA_ENABLED -DKML_ENABLED -DGEOJSON_ENABLED -DGPX_ENABLED -DGEOCONCEPT_ENABLED -DXPLANE_ENABLED -DGEORSS_ENABLED -DGTM_ENABLED -DDXF_ENABLED -DPGDUMP_ENABLED -DGPSBABEL_ENABLED -DSUA_ENABLED -DOPENAIR_ENABLED -DPDS_ENABLED -DHTF_ENABLED -DAERONAVFAA_ENABLED -DEDIGEO_ENABL [...]
 
 EXTRAFLAGS =	-I.. -I..\.. $(OGDIDEF) $(FMEDEF) $(OCIDEF) $(PGDEF) \
 		$(ODBCDEF) $(SQLITEDEF) $(MYSQLDEF) $(ILIDEF) $(DWGDEF) \
 		$(SDEDEF) $(BASEFORMATS) $(IDBDEF) $(NASDEF) $(DODSDEF) \
 		$(LIBKMLDEF) $(WFSDEF) $(SOSIDEF) $(GFTDEF) \
 		$(COUCHDBDEF) $(CLOUDANTDEF) $(FGDBDEF) $(XLSDEF) $(ODSDEF) $(XLSXDEF) $(INGRESDEF) \
-		$(ELASTICDEF) $(OSMDEF) $(VFKDEF) $(CARTODBDEF) $(GMEDEF) $(PLSCENESDEF) $(CSWDEF)
+		$(ELASTICDEF) $(OSMDEF) $(VFKDEF) $(CARTODBDEF) $(AMIGOCLOUDDEF) $(PLSCENESDEF) $(CSWDEF) $(MONGODBDEF)
 
 !IFDEF OGDIDIR
 OGDIDEF	=	-DOGDI_ENABLED
 !ENDIF
 
 !IFDEF ODBC_SUPPORTED
-ODBCDEF	=	-DODBC_ENABLED -DPGEO_ENABLED -DMSSQLSPATIAL_ENABLED -DGEOMEDIA_ENABLED -DWALK_ENABLED
+ODBCDEF	=	-DODBC_ENABLED -DPGEO_ENABLED -DDB2_ENABLED -DMSSQLSPATIAL_ENABLED -DGEOMEDIA_ENABLED -DWALK_ENABLED
 !ENDIF
 
 !IFDEF PG_LIB
@@ -147,13 +147,21 @@ CARTODBDEF = -DCARTODB_ENABLED
 !ENDIF
 
 !IFDEF CURL_LIB
-GMEDEF = -DGME_ENABLED
+!IF "$(AMIGOCLOUD_PLUGIN)" != "YES"
+AMIGOCLOUDDEF = -DAMIGOCLOUD_ENABLED
+!ENDIF
 !ENDIF
 
 !IFDEF CURL_LIB
 PLSCENESDEF = -DPLSCENES_ENABLED
 !ENDIF
 
+!IFDEF MONGODB_INC
+!IF "$(MONGODB_PLUGIN)" != "YES"
+MONGODBDEF = -DMONGODB_ENABLED
+!ENDIF
+!ENDIF
+
 !ELSE
 
 EXTRAFLAGS =	-I.. -I..\..
diff --git a/ogr/ogrsf_frmts/generic/ogr_attrind.cpp b/ogr/ogrsf_frmts/generic/ogr_attrind.cpp
index 3354f3a..b8e9c24 100644
--- a/ogr/ogrsf_frmts/generic/ogr_attrind.cpp
+++ b/ogr/ogrsf_frmts/generic/ogr_attrind.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_attrind.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: ogr_attrind.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of OGRLayerAttrIndex and OGRAttrIndex base classes.
@@ -30,7 +30,7 @@
 #include "ogr_attrind.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogr_attrind.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: ogr_attrind.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -70,7 +70,7 @@ OGRLayerAttrIndex::~OGRLayerAttrIndex()
 /*                            OGRAttrIndex()                            */
 /************************************************************************/
 
-OGRAttrIndex::OGRAttrIndex() 
+OGRAttrIndex::OGRAttrIndex()
 
 {
 }
diff --git a/ogr/ogrsf_frmts/generic/ogr_gensql.cpp b/ogr/ogrsf_frmts/generic/ogr_gensql.cpp
index b85a67b..a97e333 100644
--- a/ogr/ogrsf_frmts/generic/ogr_gensql.cpp
+++ b/ogr/ogrsf_frmts/generic/ogr_gensql.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_gensql.cpp 31016 2015-10-16 08:11:46Z rouault $
+ * $Id: ogr_gensql.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGenSQLResultsLayer.
@@ -36,7 +36,7 @@
 #include "cpl_time.h"
 #include <vector>
 
-CPL_CVSID("$Id: ogr_gensql.cpp 31016 2015-10-16 08:11:46Z rouault $");
+CPL_CVSID("$Id: ogr_gensql.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 
 class OGRGenSQLGeomFieldDefn: public OGRGeomFieldDefn
@@ -84,36 +84,28 @@ int OGRGenSQLResultsLayerHasSpecialField(swq_expr_node* expr,
 /*                       OGRGenSQLResultsLayer()                        */
 /************************************************************************/
 
-OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( GDALDataset *poSrcDS,
-                                              void *pSelectInfo, 
+OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( GDALDataset *poSrcDSIn,
+                                              void *pSelectInfoIn,
                                               OGRGeometry *poSpatFilter,
-                                              const char *pszWHERE,
-                                              const char *pszDialect )
-
+                                              const char *pszWHEREIn,
+                                              const char *pszDialect ) :
+    poSrcLayer(NULL), pszWHERE(NULL), papoTableLayers(NULL), poDefn(NULL),
+    panGeomFieldToSrcGeomField(NULL), nIndexSize(0),
+    panFIDIndex(NULL), bOrderByValid(FALSE), nNextIndexFID(0),
+    poSummaryFeature(NULL), iFIDFieldIndex(), nExtraDSCount(0), papoExtraDS(NULL)
 {
-    swq_select *psSelectInfo = (swq_select *) pSelectInfo;
+    swq_select *psSelectInfo = (swq_select *) pSelectInfoIn;
 
-    this->poSrcDS = poSrcDS;
-    this->pSelectInfo = pSelectInfo;
-    poDefn = NULL;
-    poSummaryFeature = NULL;
-    panFIDIndex = NULL;
-    bOrderByValid = FALSE;
-    nIndexSize = 0;
-    nNextIndexFID = 0;
-    nExtraDSCount = 0;
-    papoExtraDS = NULL;
-    panGeomFieldToSrcGeomField = NULL;
+    poSrcDS = poSrcDSIn;
+    pSelectInfo = pSelectInfoIn;
 
 /* -------------------------------------------------------------------- */
 /*      Identify all the layers involved in the SELECT.                 */
 /* -------------------------------------------------------------------- */
-    int iTable;
-
-    papoTableLayers = (OGRLayer **) 
+    papoTableLayers = (OGRLayer **)
         CPLCalloc( sizeof(OGRLayer *), psSelectInfo->table_count );
 
-    for( iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
+    for( int iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
     {
         swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
         GDALDataset *poTableDS = poSrcDS;
@@ -125,7 +117,7 @@ OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( GDALDataset *poSrcDS,
             if( poTableDS == NULL )
             {
                 if( strlen(CPLGetLastErrorMsg()) == 0 )
-                    CPLError( CE_Failure, CPLE_AppDefined, 
+                    CPLError( CE_Failure, CPLE_AppDefined,
                               "Unable to open secondary datasource\n"
                               "`%s' required by JOIN.",
                               psTableDef->data_source );
@@ -138,16 +130,17 @@ OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( GDALDataset *poSrcDS,
             papoExtraDS[nExtraDSCount-1] = poTableDS;
         }
 
-        papoTableLayers[iTable] = 
+        papoTableLayers[iTable] =
             poTableDS->GetLayerByName( psTableDef->table_name );
-        
+
         CPLAssert( papoTableLayers[iTable] != NULL );
 
         if( papoTableLayers[iTable] == NULL )
             return;
     }
-    
+
     poSrcLayer = papoTableLayers[0];
+    SetMetadata( poSrcLayer->GetMetadata( "NATIVE_DATA" ), "NATIVE_DATA" );
 
 /* -------------------------------------------------------------------- */
 /*      If the user has explicitly requested a OGRSQL dialect, then    */
@@ -155,7 +148,7 @@ OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( GDALDataset *poSrcDS,
 /*      when there is a risk it cannot understand it (#4022)            */
 /* -------------------------------------------------------------------- */
     int bForwardWhereToSourceLayer = TRUE;
-    if( pszWHERE )
+    if( pszWHEREIn )
     {
         if( psSelectInfo->where_expr && pszDialect != NULL &&
             EQUAL(pszDialect, "OGRSQL") )
@@ -165,12 +158,12 @@ OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( GDALDataset *poSrcDS,
                             (psSelectInfo->where_expr, nMinIndexForSpecialField);
         }
         if (bForwardWhereToSourceLayer)
-            this->pszWHERE = CPLStrdup(pszWHERE);
+            pszWHERE = CPLStrdup(pszWHEREIn);
         else
-            this->pszWHERE = NULL;
+            pszWHERE = NULL;
     }
     else
-        this->pszWHERE = NULL;
+        pszWHERE = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Prepare a feature definition based on the query.                */
@@ -199,10 +192,10 @@ OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( GDALDataset *poSrcDS,
         int iSrcGeomField = -1;
 
         if( psColDef->table_index != -1 )
-            poLayerDefn = 
+            poLayerDefn =
                 papoTableLayers[psColDef->table_index]->GetLayerDefn();
 
-        if( psColDef->field_index > -1 
+        if( psColDef->field_index > -1
             && poLayerDefn != NULL
             && psColDef->field_index < poLayerDefn->GetFieldCount() )
         {
@@ -228,7 +221,7 @@ OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( GDALDataset *poSrcDS,
         {
             CPLFree( psColDef->field_name );
             psColDef->field_name = (char *) CPLMalloc(40);
-            sprintf( psColDef->field_name, "FIELD_%d", poDefn->GetFieldCount()+1 );
+            snprintf( psColDef->field_name, 40, "FIELD_%d", poDefn->GetFieldCount()+1 );
         }
 
         if( psColDef->field_alias != NULL )
@@ -240,7 +233,7 @@ OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( GDALDataset *poSrcDS,
         }
         else if( psColDef->col_func != SWQCF_NONE )
         {
-            const swq_operation *op = swq_op_registrar::GetOperator( 
+            const swq_operation *op = swq_op_registrar::GetOperator(
                 (swq_op) psColDef->col_func );
 
             oFDefn.SetName( CPLSPrintf( "%s_%s",
@@ -435,7 +428,7 @@ OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( GDALDataset *poSrcDS,
     {
         psSelectInfo->result_columns++;
 
-        psSelectInfo->column_defs = (swq_col_def *) 
+        psSelectInfo->column_defs = (swq_col_def *)
             CPLRealloc( psSelectInfo->column_defs, sizeof(swq_col_def) * psSelectInfo->result_columns );
 
         swq_col_def *col_def = psSelectInfo->column_defs + psSelectInfo->result_columns - 1;
@@ -478,7 +471,7 @@ OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( GDALDataset *poSrcDS,
     FindAndSetIgnoredFields();
 
     if( !bForwardWhereToSourceLayer )
-        SetAttributeFilter( pszWHERE );
+        SetAttributeFilter( pszWHEREIn );
 }
 
 /************************************************************************/
@@ -491,7 +484,7 @@ OGRGenSQLResultsLayer::~OGRGenSQLResultsLayer()
     if( m_nFeaturesRead > 0 && poDefn != NULL )
     {
         CPLDebug( "GenSQL", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
+                  (int) m_nFeaturesRead,
                   poDefn->GetName() );
     }
 
@@ -502,7 +495,7 @@ OGRGenSQLResultsLayer::~OGRGenSQLResultsLayer()
 /* -------------------------------------------------------------------- */
     CPLFree( papoTableLayers );
     papoTableLayers = NULL;
-             
+
     CPLFree( panFIDIndex );
     CPLFree( panGeomFieldToSrcGeomField );
 
@@ -555,9 +548,9 @@ void OGRGenSQLResultsLayer::ClearFilters()
         for( iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++ )
         {
             swq_join_def *psJoinInfo = psSelectInfo->join_defs + iJoin;
-            OGRLayer *poJoinLayer = 
+            OGRLayer *poJoinLayer =
                 papoTableLayers[psJoinInfo->secondary_table];
-            
+
             poJoinLayer->SetAttributeFilter( "" );
         }
     }
@@ -615,7 +608,7 @@ void OGRGenSQLResultsLayer::ApplyFiltersToSource()
 /*                            ResetReading()                            */
 /************************************************************************/
 
-void OGRGenSQLResultsLayer::ResetReading() 
+void OGRGenSQLResultsLayer::ResetReading()
 
 {
     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
@@ -631,7 +624,7 @@ void OGRGenSQLResultsLayer::ResetReading()
 /************************************************************************/
 /*                           SetNextByIndex()                           */
 /*                                                                      */
-/*      If we already have an FID list, we can easily resposition       */
+/*      If we already have an FID list, we can easily reposition        */
 /*      ourselves in it.                                                */
 /************************************************************************/
 
@@ -642,8 +635,8 @@ OGRErr OGRGenSQLResultsLayer::SetNextByIndex( GIntBig nIndex )
 
     CreateOrderByIndex();
 
-    if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD 
-        || psSelectInfo->query_mode == SWQM_DISTINCT_LIST 
+    if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD
+        || psSelectInfo->query_mode == SWQM_DISTINCT_LIST
         || panFIDIndex != NULL )
     {
         nNextIndexFID = nIndex;
@@ -660,7 +653,7 @@ OGRErr OGRGenSQLResultsLayer::SetNextByIndex( GIntBig nIndex )
 /************************************************************************/
 
 OGRErr OGRGenSQLResultsLayer::GetExtent( int iGeomField,
-                                         OGREnvelope *psExtent, 
+                                         OGREnvelope *psExtent,
                                          int bForce )
 
 {
@@ -733,17 +726,17 @@ int OGRGenSQLResultsLayer::TestCapability( const char *pszCap )
 
     if( EQUAL(pszCap,OLCFastSetNextByIndex) )
     {
-        if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD 
-            || psSelectInfo->query_mode == SWQM_DISTINCT_LIST 
+        if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD
+            || psSelectInfo->query_mode == SWQM_DISTINCT_LIST
             || panFIDIndex != NULL )
             return TRUE;
-        else 
+        else
             return poSrcLayer->TestCapability( pszCap );
     }
 
     if( psSelectInfo->query_mode == SWQM_RECORDSET
-        && (EQUAL(pszCap,OLCFastFeatureCount) 
-            || EQUAL(pszCap,OLCRandomRead) 
+        && (EQUAL(pszCap,OLCFastFeatureCount)
+            || EQUAL(pszCap,OLCRandomRead)
             || EQUAL(pszCap,OLCFastGetExtent)) )
         return poSrcLayer->TestCapability( pszCap );
 
@@ -857,14 +850,14 @@ int OGRGenSQLResultsLayer::PrepareSummary()
 /*      GetFeatureCount().                                            */
 /* -------------------------------------------------------------------- */
 
-    if( psSelectInfo->result_columns == 1 
+    if( psSelectInfo->result_columns == 1
         && psSelectInfo->column_defs[0].col_func == SWQCF_COUNT
         && psSelectInfo->column_defs[0].field_index < 0 )
     {
         GIntBig nRes = poSrcLayer->GetFeatureCount( TRUE );
         poSummaryFeature->SetField( 0, nRes );
 
-        if( (GIntBig)(int)nRes == nRes )
+        if( CPL_INT64_FITS_ON_INT32(nRes) )
         {
             poDefn->GetFieldDefn(0)->SetType(OFTInteger);
             delete poSummaryFeature;
@@ -920,7 +913,7 @@ int OGRGenSQLResultsLayer::PrepareSummary()
                                                 psColDef->field_index );
                 pszError = swq_select_summarize( psSelectInfo, iField, pszVal );
             }
-            
+
             if( pszError != NULL )
             {
                 delete poSrcFeature;
@@ -944,7 +937,7 @@ int OGRGenSQLResultsLayer::PrepareSummary()
     {
         delete poSummaryFeature;
         poSummaryFeature = NULL;
-        
+
         CPLError( CE_Failure, CPLE_AppDefined, "%s", pszError );
         return FALSE;
     }
@@ -971,7 +964,7 @@ int OGRGenSQLResultsLayer::PrepareSummary()
                 swq_summary *psSummary = psSelectInfo->column_summary + iField;
                 if( psColDef->col_func == SWQCF_COUNT )
                 {
-                    if( (GIntBig)(int)psSummary->count == psSummary->count ) 
+                    if( CPL_INT64_FITS_ON_INT32(psSummary->count) )
                     {
                         delete poSummaryFeature;
                         poSummaryFeature = NULL;
@@ -1009,7 +1002,8 @@ int OGRGenSQLResultsLayer::PrepareSummary()
                                                     brokendowntime.tm_mday,
                                                     brokendowntime.tm_hour,
                                                     brokendowntime.tm_min,
-                                                    brokendowntime.tm_sec + fmod(dfAvg, 1), 0);
+                                                    static_cast<float>(brokendowntime.tm_sec + fmod(dfAvg, 1)),
+                                                    0);
                     }
                     else
                         poSummaryFeature->SetField( iField,
@@ -1050,11 +1044,11 @@ int OGRGenSQLResultsLayer::PrepareSummary()
 /*                       OGRMultiFeatureFetcher()                       */
 /************************************************************************/
 
-static swq_expr_node *OGRMultiFeatureFetcher( swq_expr_node *op, 
+static swq_expr_node *OGRMultiFeatureFetcher( swq_expr_node *op,
                                               void *pFeatureList )
 
 {
-    std::vector<OGRFeature*> *papoFeatures = 
+    std::vector<OGRFeature*> *papoFeatures =
         (std::vector<OGRFeature*> *) pFeatureList;
     OGRFeature *poFeature;
     swq_expr_node *poRetNode = NULL;
@@ -1071,7 +1065,7 @@ static swq_expr_node *OGRMultiFeatureFetcher( swq_expr_node *op,
                   op->table_index );
         return NULL;
     }
-    
+
     poFeature = (*papoFeatures)[op->table_index];
 
 /* -------------------------------------------------------------------- */
@@ -1081,41 +1075,41 @@ static swq_expr_node *OGRMultiFeatureFetcher( swq_expr_node *op,
     {
       case SWQ_INTEGER:
       case SWQ_BOOLEAN:
-        if( poFeature == NULL 
+        if( poFeature == NULL
             || !poFeature->IsFieldSet(op->field_index) )
         {
             poRetNode = new swq_expr_node(0);
             poRetNode->is_null = TRUE;
         }
         else
-            poRetNode = new swq_expr_node( 
+            poRetNode = new swq_expr_node(
                 poFeature->GetFieldAsInteger(op->field_index) );
         break;
 
       case SWQ_INTEGER64:
-        if( poFeature == NULL 
+        if( poFeature == NULL
             || !poFeature->IsFieldSet(op->field_index) )
         {
             poRetNode = new swq_expr_node((GIntBig)0);
             poRetNode->is_null = TRUE;
         }
         else
-            poRetNode = new swq_expr_node( 
+            poRetNode = new swq_expr_node(
                 poFeature->GetFieldAsInteger64(op->field_index) );
         break;
 
       case SWQ_FLOAT:
-        if( poFeature == NULL 
+        if( poFeature == NULL
             || !poFeature->IsFieldSet(op->field_index) )
         {
             poRetNode = new swq_expr_node( 0.0 );
             poRetNode->is_null = TRUE;
         }
         else
-            poRetNode = new swq_expr_node( 
+            poRetNode = new swq_expr_node(
                 poFeature->GetFieldAsDouble(op->field_index) );
         break;
-        
+
       case SWQ_GEOMETRY:
         if( poFeature == NULL )
         {
@@ -1131,14 +1125,14 @@ static swq_expr_node *OGRMultiFeatureFetcher( swq_expr_node *op,
         break;
 
       default:
-        if( poFeature == NULL 
+        if( poFeature == NULL
             || !poFeature->IsFieldSet(op->field_index) )
         {
             poRetNode = new swq_expr_node("");
             poRetNode->is_null = TRUE;
         }
         else
-            poRetNode = new swq_expr_node( 
+            poRetNode = new swq_expr_node(
                 poFeature->GetFieldAsString(op->field_index) );
         break;
     }
@@ -1175,7 +1169,7 @@ static CPLString GetFilterForJoin(swq_expr_node* poExpr, OGRFeature* poSrcFeat,
             }
             OGRFieldType ePrimaryFieldType =
                     poSrcFeat->GetFieldDefnRef(poExpr->field_index)->GetType();
-            OGRField *psSrcField = 
+            OGRField *psSrcField =
                     poSrcFeat->GetRawFieldRef(poExpr->field_index);
 
             switch( ePrimaryFieldType )
@@ -1194,8 +1188,8 @@ static CPLString GetFilterForJoin(swq_expr_node* poExpr, OGRFeature* poSrcFeat,
 
             case OFTString:
             {
-                char *pszEscaped = CPLEscapeString( psSrcField->String, 
-                                                    strlen(psSrcField->String),
+                char *pszEscaped = CPLEscapeString( psSrcField->String,
+                                                    static_cast<int>(strlen(psSrcField->String)),
                                                     CPLES_SQL );
                 CPLString osRes = "'";
                 osRes += pszEscaped;
@@ -1210,7 +1204,7 @@ static CPLString GetFilterForJoin(swq_expr_node* poExpr, OGRFeature* poSrcFeat,
                 return "";
             }
         }
-        
+
         if(  poExpr->table_index == secondary_table )
         {
             OGRFieldDefn* poSecondaryFieldDefn =
@@ -1224,13 +1218,11 @@ static CPLString GetFilterForJoin(swq_expr_node* poExpr, OGRFeature* poSrcFeat,
 
     if( poExpr->eNodeType == SNT_OPERATION )
     {
-        /* -------------------------------------------------------------------- */
-        /*      Operation - start by unparsing all the subexpressions.          */
-        /* -------------------------------------------------------------------- */
+        /* ----------------------------------------------------------------- */
+        /*      Operation - start by unparsing all the subexpressions.       */
+        /* ----------------------------------------------------------------- */
         std::vector<char*> apszSubExpr;
-        int i;
-
-        for( i = 0; i < poExpr->nSubExprCount; i++ )
+        for( int i = 0; i < poExpr->nSubExprCount; i++ )
         {
             CPLString osSubExpr = GetFilterForJoin(poExpr->papoSubExpr[i], poSrcFeat,
                                                    poJoinLayer, secondary_table);
@@ -1245,10 +1237,10 @@ static CPLString GetFilterForJoin(swq_expr_node* poExpr, OGRFeature* poSrcFeat,
 
         CPLString osExpr = poExpr->UnparseOperationFromUnparsedSubExpr(&apszSubExpr[0]);
 
-        /* -------------------------------------------------------------------- */
-        /*      cleanup subexpressions.                                         */
-        /* -------------------------------------------------------------------- */
-        for( i = 0; i < poExpr->nSubExprCount; i++ )
+        /* ----------------------------------------------------------------- */
+        /*      cleanup subexpressions.                                      */
+        /* ----------------------------------------------------------------- */
+        for( int i = 0; i < poExpr->nSubExprCount; i++ )
             CPLFree( apszSubExpr[i] );
 
         return osExpr;
@@ -1292,8 +1284,8 @@ OGRFeature *OGRGenSQLResultsLayer::TranslateFeature( OGRFeature *poSrcFeat )
         CPLAssert(psJoinInfo->secondary_table == iJoin + 1);
 
         OGRLayer *poJoinLayer = papoTableLayers[psJoinInfo->secondary_table];
-        
-        osFilter = GetFilterForJoin(psJoinInfo->poExpr, poSrcFeat, poJoinLayer, 
+
+        osFilter = GetFilterForJoin(psJoinInfo->poExpr, poSrcFeat, poJoinLayer,
                                     psJoinInfo->secondary_table);
         //CPLDebug("OGR", "Filter = %s\n", osFilter.c_str());
 
@@ -1321,6 +1313,8 @@ OGRFeature *OGRGenSQLResultsLayer::TranslateFeature( OGRFeature *poSrcFeat )
     poDstFeat->SetFID( poSrcFeat->GetFID() );
 
     poDstFeat->SetStyleString( poSrcFeat->GetStyleString() );
+    poDstFeat->SetNativeData( poSrcFeat->GetNativeData() );
+    poDstFeat->SetNativeMediaType( poSrcFeat->GetNativeMediaType() );
 
 /* -------------------------------------------------------------------- */
 /*      Evaluate fields that are complex expressions.                   */
@@ -1342,9 +1336,9 @@ OGRFeature *OGRGenSQLResultsLayer::TranslateFeature( OGRFeature *poSrcFeat )
             continue;
         }
 
-        poResult = psColDef->expr->Evaluate( OGRMultiFeatureFetcher, 
+        poResult = psColDef->expr->Evaluate( OGRMultiFeatureFetcher,
                                              (void *) &apoFeatures );
-        
+
         if( poResult == NULL )
         {
             delete poDstFeat;
@@ -1371,11 +1365,11 @@ OGRFeature *OGRGenSQLResultsLayer::TranslateFeature( OGRFeature *poSrcFeat )
           case SWQ_INTEGER64:
             poDstFeat->SetField( iRegularField++, poResult->int_value );
             break;
-            
+
           case SWQ_FLOAT:
             poDstFeat->SetField( iRegularField++, poResult->float_value );
             break;
-            
+
           case SWQ_GEOMETRY:
           {
             OGRGenSQLGeomFieldDefn* poGeomFieldDefn =
@@ -1413,7 +1407,7 @@ OGRFeature *OGRGenSQLResultsLayer::TranslateFeature( OGRFeature *poSrcFeat )
             poDstFeat->SetGeomField( iGeomField++, poResult->geometry_value );
             break;
           }
-            
+
           default:
             poDstFeat->SetField( iRegularField++, poResult->string_value );
             break;
@@ -1421,7 +1415,7 @@ OGRFeature *OGRGenSQLResultsLayer::TranslateFeature( OGRFeature *poSrcFeat )
 
         delete poResult;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Copy fields from primary record to the destination feature.     */
 /* -------------------------------------------------------------------- */
@@ -1482,14 +1476,14 @@ OGRFeature *OGRGenSQLResultsLayer::TranslateFeature( OGRFeature *poSrcFeat )
               case SWQ_FLOAT:
                 poDstFeat->SetField( iRegularField, poSrcFeat->GetFieldAsDouble(psColDef->field_index) );
                 break;
-              
+
               case SWQ_STRING:
               case SWQ_TIMESTAMP:
               case SWQ_DATE:
               case SWQ_TIME:
                 poDstFeat->SetField( iRegularField, poSrcFeat->GetFieldAsString(psColDef->field_index) );
                 break;
-                
+
               case SWQ_GEOMETRY:
                   CPLAssert(0);
                   break;
@@ -1515,7 +1509,7 @@ OGRFeature *OGRGenSQLResultsLayer::TranslateFeature( OGRFeature *poSrcFeat )
         if( poJoinFeature == NULL )
             continue;
 
-        // Copy over selected field values. 
+        // Copy over selected field values.
         iRegularField = 0;
         for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
         {
@@ -1527,7 +1521,7 @@ OGRFeature *OGRGenSQLResultsLayer::TranslateFeature( OGRFeature *poSrcFeat )
 
             if( psColDef->table_index == psJoinInfo->secondary_table )
                 poDstFeat->SetField( iRegularField,
-                                     poJoinFeature->GetRawFieldRef( 
+                                     poJoinFeature->GetRawFieldRef(
                                          psColDef->field_index ) );
 
             iRegularField ++;
@@ -1553,7 +1547,7 @@ OGRFeature *OGRGenSQLResultsLayer::GetNextFeature()
 /* -------------------------------------------------------------------- */
 /*      Handle summary sets.                                            */
 /* -------------------------------------------------------------------- */
-    if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD 
+    if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD
         || psSelectInfo->query_mode == SWQM_DISTINCT_LIST )
         return GetFeature( nNextIndexFID++ );
 
@@ -1562,7 +1556,7 @@ OGRFeature *OGRGenSQLResultsLayer::GetNextFeature()
 /* -------------------------------------------------------------------- */
 /*      Handle ordered sets.                                            */
 /* -------------------------------------------------------------------- */
-    while( TRUE )
+    while( true )
     {
         OGRFeature *poFeature;
 
@@ -1574,7 +1568,7 @@ OGRFeature *OGRGenSQLResultsLayer::GetNextFeature()
 
             if( poSrcFeat == NULL )
                 return NULL;
-            
+
             poFeature = TranslateFeature( poSrcFeat );
             delete poSrcFeat;
         }
@@ -1664,7 +1658,7 @@ OGRFeature *OGRGenSQLResultsLayer::GetFeature( GIntBig nFID )
 
     poResult = TranslateFeature( poSrcFeature );
     poResult->SetFID( nFID );
-    
+
     delete poSrcFeature;
 
     return poResult;
@@ -1674,7 +1668,7 @@ OGRFeature *OGRGenSQLResultsLayer::GetFeature( GIntBig nFID )
 /*                          GetSpatialFilter()                          */
 /************************************************************************/
 
-OGRGeometry *OGRGenSQLResultsLayer::GetSpatialFilter() 
+OGRGeometry *OGRGenSQLResultsLayer::GetSpatialFilter()
 
 {
     return NULL;
@@ -1751,7 +1745,7 @@ void OGRGenSQLResultsLayer::CreateOrderByIndex()
     size_t nFeaturesAlloc = 100;
 
     panFIDIndex = NULL;
-    pasIndexFields = (OGRField *) 
+    pasIndexFields = (OGRField *)
         CPLCalloc(sizeof(OGRField), nOrderItems * nFeaturesAlloc);
     panFIDList = (GIntBig *) CPLMalloc(sizeof(GIntBig) * nFeaturesAlloc);
 
@@ -1778,7 +1772,7 @@ void OGRGenSQLResultsLayer::CreateOrderByIndex()
                 return;
             }
             OGRField* pasNewIndexFields = (OGRField *)
-                VSIRealloc(pasIndexFields,
+                VSI_REALLOC_VERBOSE(pasIndexFields,
                            sizeof(OGRField) * nOrderItems * (size_t)nNewFeaturesAlloc);
             if (pasNewIndexFields == NULL)
             {
@@ -1791,7 +1785,7 @@ void OGRGenSQLResultsLayer::CreateOrderByIndex()
             pasIndexFields = pasNewIndexFields;
 
             GIntBig* panNewFIDList = (GIntBig *)
-                VSIRealloc(panFIDList, sizeof(GIntBig) *  (size_t)nNewFeaturesAlloc);
+                VSI_REALLOC_VERBOSE(panFIDList, sizeof(GIntBig) *  (size_t)nNewFeaturesAlloc);
             if (panNewFIDList == NULL)
             {
                 VSIFree(pasIndexFields);
@@ -1840,14 +1834,14 @@ void OGRGenSQLResultsLayer::CreateOrderByIndex()
                 }
                 continue;
             }
-            
-            poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn( 
+
+            poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn(
                 psKeyDef->field_index );
 
             psSrcField = poSrcFeat->GetRawFieldRef( psKeyDef->field_index );
 
-            if( poFDefn->GetType() == OFTInteger 
-                || poFDefn->GetType() == OFTInteger64 
+            if( poFDefn->GetType() == OFTInteger
+                || poFDefn->GetType() == OFTInteger64
                 || poFDefn->GetType() == OFTReal
                 || poFDefn->GetType() == OFTDate
                 || poFDefn->GetType() == OFTTime
@@ -1873,10 +1867,9 @@ void OGRGenSQLResultsLayer::CreateOrderByIndex()
 /* -------------------------------------------------------------------- */
 /*      Initialize panFIDIndex                                          */
 /* -------------------------------------------------------------------- */
-    panFIDIndex = (GIntBig *) VSIMalloc(sizeof(GIntBig) * (size_t)nIndexSize);
+    panFIDIndex = (GIntBig *) VSI_MALLOC_VERBOSE(sizeof(GIntBig) * (size_t)nIndexSize);
     if( panFIDIndex == NULL )
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "Cannot allocate panFIDIndex");
         VSIFree(pasIndexFields);
         VSIFree(panFIDList);
         nIndexSize = 0;
@@ -1934,7 +1927,7 @@ void OGRGenSQLResultsLayer::CreateOrderByIndex()
             continue;
         }
 
-        poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn( 
+        poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn(
             psKeyDef->field_index );
 
         if( poFDefn->GetType() == OFTString )
@@ -1942,8 +1935,8 @@ void OGRGenSQLResultsLayer::CreateOrderByIndex()
             for( i = 0; i < nIndexSize; i++ )
             {
                 OGRField *psField = pasIndexFields + iKey + i * nOrderItems;
-                
-                if( psField->Set.nMarker1 != OGRUnsetMarker 
+
+                if( psField->Set.nMarker1 != OGRUnsetMarker
                     || psField->Set.nMarker2 != OGRUnsetMarker )
                     CPLFree( psField->String );
             }
@@ -1974,7 +1967,7 @@ void OGRGenSQLResultsLayer::CreateOrderByIndex()
 /*      Sort the records in a section of the index.                     */
 /************************************************************************/
 
-int OGRGenSQLResultsLayer::SortIndexSection( OGRField *pasIndexFields, 
+int OGRGenSQLResultsLayer::SortIndexSection( OGRField *pasIndexFields,
                                               GIntBig nStart, GIntBig nEntries )
 
 {
@@ -1995,13 +1988,12 @@ int OGRGenSQLResultsLayer::SortIndexSection( OGRField *pasIndexFields,
         !SortIndexSection( pasIndexFields, nSecondStart, nSecondGroup ) )
         return FALSE;
 
-    panMerged = (GIntBig *) VSIMalloc( sizeof(GIntBig) * (size_t)nEntries );
+    panMerged = (GIntBig *) VSI_MALLOC_VERBOSE( sizeof(GIntBig) * (size_t)nEntries );
     if( panMerged == NULL )
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "Cannot allocated panMerged");
         return FALSE;
     }
-        
+
     while( iMerge < nEntries )
     {
         int  nResult;
@@ -2011,9 +2003,9 @@ int OGRGenSQLResultsLayer::SortIndexSection( OGRField *pasIndexFields,
         else if( nSecondGroup == 0 )
             nResult = 1;
         else
-            nResult = Compare( pasIndexFields 
-                               + panFIDIndex[nFirstStart] * nOrderItems, 
-                               pasIndexFields 
+            nResult = Compare( pasIndexFields
+                               + panFIDIndex[nFirstStart] * nOrderItems,
+                               pasIndexFields
                                + panFIDIndex[nSecondStart] * nOrderItems );
 
         if( nResult < 0 )
@@ -2032,7 +2024,7 @@ int OGRGenSQLResultsLayer::SortIndexSection( OGRField *pasIndexFields,
 
     memcpy( panFIDIndex + nStart, panMerged, sizeof(GIntBig) * (size_t)nEntries );
     CPLFree( panMerged );
-    
+
     return TRUE;
 }
 
@@ -2060,19 +2052,19 @@ int OGRGenSQLResultsLayer::Compare( OGRField *pasFirstTuple,
         else if( psKeyDef->field_index >= iFIDFieldIndex )
             poFDefn = NULL;
         else
-            poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn( 
+            poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn(
                 psKeyDef->field_index );
-        
-        if( pasFirstTuple[iKey].Set.nMarker1 == OGRUnsetMarker 
+
+        if( pasFirstTuple[iKey].Set.nMarker1 == OGRUnsetMarker
              && pasFirstTuple[iKey].Set.nMarker2 == OGRUnsetMarker )
         {
-            if( pasSecondTuple[iKey].Set.nMarker1 == OGRUnsetMarker 
+            if( pasSecondTuple[iKey].Set.nMarker1 == OGRUnsetMarker
                 && pasSecondTuple[iKey].Set.nMarker2 == OGRUnsetMarker )
                 nResult = 0;
             else
                 nResult = -1;
         }
-        else if ( pasSecondTuple[iKey].Set.nMarker1 == OGRUnsetMarker 
+        else if ( pasSecondTuple[iKey].Set.nMarker1 == OGRUnsetMarker
                 && pasSecondTuple[iKey].Set.nMarker2 == OGRUnsetMarker )
         {
             nResult = 1;
@@ -2113,7 +2105,7 @@ int OGRGenSQLResultsLayer::Compare( OGRField *pasFirstTuple,
         {
             if( pasFirstTuple[iKey].Integer < pasSecondTuple[iKey].Integer )
                 nResult = -1;
-            else if( pasFirstTuple[iKey].Integer 
+            else if( pasFirstTuple[iKey].Integer
                      > pasSecondTuple[iKey].Integer )
                 nResult = 1;
         }
@@ -2121,7 +2113,7 @@ int OGRGenSQLResultsLayer::Compare( OGRField *pasFirstTuple,
         {
             if( pasFirstTuple[iKey].Integer64 < pasSecondTuple[iKey].Integer64 )
                 nResult = -1;
-            else if( pasFirstTuple[iKey].Integer64 
+            else if( pasFirstTuple[iKey].Integer64
                      > pasSecondTuple[iKey].Integer64 )
                 nResult = 1;
         }
diff --git a/ogr/ogrsf_frmts/generic/ogr_gensql.h b/ogr/ogrsf_frmts/generic/ogr_gensql.h
index fe5fe64..07773e3 100644
--- a/ogr/ogrsf_frmts/generic/ogr_gensql.h
+++ b/ogr/ogrsf_frmts/generic/ogr_gensql.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_gensql.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogr_gensql.h 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Classes related to generic implementation of ExecuteSQL().
@@ -28,8 +28,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_GENSQL_H_INCLUDED
-#define _OGR_GENSQL_H_INCLUDED
+#ifndef OGR_GENSQL_H_INCLUDED
+#define OGR_GENSQL_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "swq.h"
@@ -62,8 +62,6 @@ class CPL_DLL OGRGenSQLResultsLayer : public OGRLayer
 
     OGRFeatureDefn *poDefn;
 
-    int         PrepareSummary();
-    
     int        *panGeomFieldToSrcGeomField;
 
     GIntBig     nIndexSize;
@@ -78,9 +76,11 @@ class CPL_DLL OGRGenSQLResultsLayer : public OGRLayer
     int         nExtraDSCount;
     GDALDataset **papoExtraDS;
 
+    int         PrepareSummary();
+
     OGRFeature *TranslateFeature( OGRFeature * );
     void        CreateOrderByIndex();
-    int         SortIndexSection( OGRField *pasIndexFields, 
+    int         SortIndexSection( OGRField *pasIndexFields,
                                   GIntBig nStart, GIntBig nEntries );
     int         Compare( OGRField *pasFirst, OGRField *pasSecond );
 
@@ -94,11 +94,11 @@ class CPL_DLL OGRGenSQLResultsLayer : public OGRLayer
     int         ContainGeomSpecialField(swq_expr_node* expr);
 
     void        InvalidateOrderByIndex();
-    
+
     int         MustEvaluateSpatialFilterOnGenSQL();
 
   public:
-                OGRGenSQLResultsLayer( GDALDataset *poSrcDS, 
+                OGRGenSQLResultsLayer( GDALDataset *poSrcDS,
                                        void *pSelectInfo,
                                        OGRGeometry *poSpatFilter,
                                        const char *pszWHERE,
@@ -125,5 +125,4 @@ class CPL_DLL OGRGenSQLResultsLayer : public OGRLayer
     virtual OGRErr      SetAttributeFilter( const char * );
 };
 
-#endif /* ndef _OGR_GENSQL_H_INCLUDED */
-
+#endif /* ndef OGR_GENSQL_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/generic/ogr_miattrind.cpp b/ogr/ogrsf_frmts/generic/ogr_miattrind.cpp
index 40bdaf2..f60c411 100644
--- a/ogr/ogrsf_frmts/generic/ogr_miattrind.cpp
+++ b/ogr/ogrsf_frmts/generic/ogr_miattrind.cpp
@@ -1,9 +1,9 @@
 /******************************************************************************
- * $Id: ogr_miattrind.cpp 28382 2015-01-30 15:29:41Z rouault $
+ * $Id: ogr_miattrind.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements interface to MapInfo .ID files used as attribute
- *           indexes.  
+ *           indexes.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -33,7 +33,7 @@
 #include "mitab/mitab_priv.h"
 #include "cpl_minixml.h"
 
-CPL_CVSID("$Id: ogr_miattrind.cpp 28382 2015-01-30 15:29:41Z rouault $");
+CPL_CVSID("$Id: ogr_miattrind.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                            OGRMIAttrIndex                            */
@@ -159,7 +159,7 @@ OGRMILayerAttrIndex::~OGRMILayerAttrIndex()
 /*                             Initialize()                             */
 /************************************************************************/
 
-OGRErr OGRMILayerAttrIndex::Initialize( const char *pszIndexPathIn, 
+OGRErr OGRMILayerAttrIndex::Initialize( const char *pszIndexPathIn,
                                         OGRLayer *poLayerIn )
 
 {
@@ -174,12 +174,12 @@ OGRErr OGRMILayerAttrIndex::Initialize( const char *pszIndexPathIn,
     pszIndexPath = CPLStrdup( pszIndexPathIn );
 
     /* try to process the XML string directly */
-    if (EQUALN(pszIndexPathIn, "<OGRMILayerAttrIndex>", 21))
+    if (STARTS_WITH_CI(pszIndexPathIn, "<OGRMILayerAttrIndex>"))
         return LoadConfigFromXML(pszIndexPathIn);
-    
+
     pszMetadataFilename = CPLStrdup(
         CPLResetExtension( pszIndexPathIn, "idm" ) );
-    
+
     pszMIINDFilename = CPLStrdup(CPLResetExtension( pszIndexPathIn, "ind" ));
 
 /* -------------------------------------------------------------------- */
@@ -217,10 +217,10 @@ OGRErr OGRMILayerAttrIndex::LoadConfigFromXML(const char* pszRawXML)
 /*      Open the index file.                                            */
 /* -------------------------------------------------------------------- */
     poINDFile = new TABINDFile();
-    
+
     if (pszMIINDFilename == NULL)
         pszMIINDFilename = CPLStrdup(CPLGetXMLValue(psRoot,"MIIDFilename",""));
-    
+
     if( pszMIINDFilename == NULL )
         return OGRERR_FAILURE;
 
@@ -232,7 +232,7 @@ OGRErr OGRMILayerAttrIndex::LoadConfigFromXML(const char* pszRawXML)
     {
         CPLDestroyXMLNode( psRoot );
         CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Failed to open index file %s.", 
+                  "Failed to open index file %s.",
                   pszMIINDFilename );
         return OGRERR_FAILURE;
     }
@@ -241,13 +241,13 @@ OGRErr OGRMILayerAttrIndex::LoadConfigFromXML(const char* pszRawXML)
 /* -------------------------------------------------------------------- */
     CPLXMLNode *psAttrIndex;
 
-    for( psAttrIndex = psRoot->psChild; 
-         psAttrIndex != NULL; 
+    for( psAttrIndex = psRoot->psChild;
+         psAttrIndex != NULL;
          psAttrIndex = psAttrIndex->psNext )
     {
         int iField, iIndexIndex;
 
-        if( psAttrIndex->eType != CXT_Element 
+        if( psAttrIndex->eType != CXT_Element
             || !EQUAL(psAttrIndex->pszValue,"OGRMIAttrIndex") )
             continue;
 
@@ -256,7 +256,7 @@ OGRErr OGRMILayerAttrIndex::LoadConfigFromXML(const char* pszRawXML)
 
         if( iField == -1 || iIndexIndex == -1 )
         {
-            CPLError( CE_Warning, CPLE_AppDefined, 
+            CPLError( CE_Warning, CPLE_AppDefined,
                       "Skipping corrupt OGRMIAttrIndex entry." );
             continue;
         }
@@ -267,7 +267,7 @@ OGRErr OGRMILayerAttrIndex::LoadConfigFromXML(const char* pszRawXML)
     CPLDestroyXMLNode( psRoot );
 
     CPLDebug( "OGR", "Restored %d field indexes for layer %s from %s on %s.",
-              nIndexCount, poLayer->GetLayerDefn()->GetName(), 
+              nIndexCount, poLayer->GetLayerDefn()->GetName(),
               pszMetadataFilename ? pszMetadataFilename : "--unknown--",
               pszMIINDFilename );
 
@@ -276,8 +276,8 @@ OGRErr OGRMILayerAttrIndex::LoadConfigFromXML(const char* pszRawXML)
 
 OGRErr OGRMILayerAttrIndex::LoadConfigFromXML()
 {
-    FILE *fp;
-    int  nXMLSize;
+    VSILFILE *fp;
+    vsi_l_offset  nXMLSize;
     char *pszRawXML;
 
     CPLAssert( poINDFile == NULL );
@@ -285,19 +285,32 @@ OGRErr OGRMILayerAttrIndex::LoadConfigFromXML()
 /* -------------------------------------------------------------------- */
 /*      Read the XML file.                                              */
 /* -------------------------------------------------------------------- */
-    fp = VSIFOpen( pszMetadataFilename, "rb" );
+    fp = VSIFOpenL( pszMetadataFilename, "rb" );
     if( fp == NULL )
-        return OGRERR_NONE;
+        return OGRERR_FAILURE;
 
-    VSIFSeek( fp, 0, SEEK_END );
-    nXMLSize = VSIFTell( fp );
-    VSIFSeek( fp, 0, SEEK_SET );
+    if( VSIFSeekL( fp, 0, SEEK_END ) != 0 )
+    {
+        VSIFCloseL(fp);
+        return OGRERR_FAILURE;
+    }
+    nXMLSize = VSIFTellL( fp );
+    if( nXMLSize > 10 * 1024 * 1024 ||
+        VSIFSeekL( fp, 0, SEEK_SET ) != 0 )
+    {
+        VSIFCloseL(fp);
+        return OGRERR_FAILURE;
+    }
 
-    pszRawXML = (char *) CPLMalloc(nXMLSize+1);
+    pszRawXML = (char *) CPLMalloc((size_t)nXMLSize+1);
     pszRawXML[nXMLSize] = '\0';
-    VSIFRead( pszRawXML, nXMLSize, 1, fp );
+    if( VSIFReadL( pszRawXML, (size_t)nXMLSize, 1, fp ) != 1 )
+    {
+        VSIFCloseL(fp);
+        return OGRERR_FAILURE;
+    }
 
-    VSIFClose( fp );
+    VSIFCloseL( fp );
 
     OGRErr eErr = LoadConfigFromXML(pszRawXML);
     CPLFree(pszRawXML);
@@ -322,9 +335,9 @@ OGRErr OGRMILayerAttrIndex::SaveConfigToXML()
 
     psRoot = CPLCreateXMLNode( NULL, CXT_Element, "OGRMILayerAttrIndex" );
 
-    CPLCreateXMLElementAndValue( psRoot, "MIIDFilename", 
+    CPLCreateXMLElementAndValue( psRoot, "MIIDFilename",
                                  CPLGetFilename( pszMIINDFilename ) );
-    
+
     for( int i = 0; i < nIndexCount; i++ )
     {
         OGRMIAttrIndex *poAI = papoIndexList[i];
@@ -332,14 +345,14 @@ OGRErr OGRMILayerAttrIndex::SaveConfigToXML()
 
         psIndex = CPLCreateXMLNode( psRoot, CXT_Element, "OGRMIAttrIndex" );
 
-        CPLCreateXMLElementAndValue( psIndex, "FieldIndex", 
+        CPLCreateXMLElementAndValue( psIndex, "FieldIndex",
                                      CPLSPrintf( "%d", poAI->iField ) );
-                                     
-        CPLCreateXMLElementAndValue( psIndex, "FieldName", 
+
+        CPLCreateXMLElementAndValue( psIndex, "FieldName",
                                      poLayer->GetLayerDefn()->GetFieldDefn(poAI->iField)->GetNameRef() );
 
-                                     
-        CPLCreateXMLElementAndValue( psIndex, "IndexIndex", 
+
+        CPLCreateXMLElementAndValue( psIndex, "IndexIndex",
                                      CPLSPrintf( "%d", poAI->iIndex ) );
     }
 
@@ -354,19 +367,19 @@ OGRErr OGRMILayerAttrIndex::SaveConfigToXML()
     fp = VSIFOpen( pszMetadataFilename, "wb" );
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Failed to pen `%s' for write.", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to pen `%s' for write.",
                   pszMetadataFilename );
         CPLFree( pszRawXML );
         return OGRERR_FAILURE;
     }
 
-    VSIFWrite( pszRawXML, 1, strlen(pszRawXML), fp );
+    OGRErr eErr = (VSIFWrite( pszRawXML, strlen(pszRawXML), 1, fp ) == 1) ? OGRERR_NONE : OGRERR_FAILURE;
     VSIFClose( fp );
 
     CPLFree( pszRawXML );
-    
-    return OGRERR_NONE;
+
+    return eErr;
 }
 
 /************************************************************************/
@@ -379,14 +392,14 @@ OGRErr OGRMILayerAttrIndex::IndexAllFeatures( int iField )
     OGRFeature *poFeature;
 
     poLayer->ResetReading();
-    
+
     while( (poFeature = poLayer->GetNextFeature()) != NULL )
     {
         OGRErr eErr = AddToIndex( poFeature, iField );
-        
+
         delete poFeature;
 
-        if( eErr != CE_None )
+        if( eErr != OGRERR_NONE )
             return eErr;
     }
 
@@ -415,8 +428,8 @@ OGRErr OGRMILayerAttrIndex::CreateIndex( int iField )
         {
             delete poINDFile;
             poINDFile = NULL;
-            
-            CPLError( CE_Failure, CPLE_OpenFailed, 
+
+            CPLError( CE_Failure, CPLE_OpenFailed,
                       "Failed to create %s.",
                       pszMIINDFilename );
             return OGRERR_FAILURE;
@@ -427,13 +440,13 @@ OGRErr OGRMILayerAttrIndex::CreateIndex( int iField )
         poINDFile->Close();
         if( poINDFile->Open( pszMIINDFilename, "r+" ) != 0 )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
+            CPLError( CE_Failure, CPLE_OpenFailed,
                       "Failed to open %s as write-only.",
                       pszMIINDFilename );
 
             if( poINDFile->Open( pszMIINDFilename, "r" ) != 0 )
             {
-                CPLError( CE_Failure, CPLE_OpenFailed, 
+                CPLError( CE_Failure, CPLE_OpenFailed,
                       "Cannot re-open %s as read-only.",
                       pszMIINDFilename );
                 delete poINDFile;
@@ -451,16 +464,15 @@ OGRErr OGRMILayerAttrIndex::CreateIndex( int iField )
 /* -------------------------------------------------------------------- */
 /*      Do we have this field indexed already?                          */
 /* -------------------------------------------------------------------- */
-    int i;
     OGRFieldDefn *poFldDefn=poLayer->GetLayerDefn()->GetFieldDefn(iField);
 
-    for( i = 0; i < nIndexCount; i++ )
+    for( int i = 0; i < nIndexCount; i++ )
     {
         if( papoIndexList[i]->iField == iField )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "It seems we already have an index for field %d/%s\n"
-                      "of layer %s.", 
+                      "of layer %s.",
                       iField, poFldDefn->GetNameRef(),
                       poLayer->GetLayerDefn()->GetName() );
             return OGRERR_FAILURE;
@@ -493,7 +505,7 @@ OGRErr OGRMILayerAttrIndex::CreateIndex( int iField )
         break;
 
       default:
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Indexing not support for the field type of field %s.",
                   poFldDefn->GetNameRef() );
         return OGRERR_FAILURE;
@@ -534,10 +546,10 @@ OGRErr OGRMILayerAttrIndex::DropIndex( int iField )
 /* -------------------------------------------------------------------- */
 /*      Do we have this field indexed already?                          */
 /* -------------------------------------------------------------------- */
-    int i;
     OGRFieldDefn *poFldDefn=poLayer->GetLayerDefn()->GetFieldDefn(iField);
 
-    for( i = 0; i < nIndexCount; i++ )
+    int i = 0;
+    for( ; i < nIndexCount; i++ )
     {
         if( papoIndexList[i]->iField == iField )
             break;
@@ -546,7 +558,7 @@ OGRErr OGRMILayerAttrIndex::DropIndex( int iField )
 
     if( i == nIndexCount )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "DROP INDEX on field (%s) that doesn't have an index.",
                   poFldDefn->GetNameRef() );
         return OGRERR_FAILURE;
@@ -557,13 +569,13 @@ OGRErr OGRMILayerAttrIndex::DropIndex( int iField )
 /* -------------------------------------------------------------------- */
     OGRMIAttrIndex *poAI = papoIndexList[i];
 
-    memmove( papoIndexList + i, papoIndexList + i + 1, 
+    memmove( papoIndexList + i, papoIndexList + i + 1,
              sizeof(void*) * (nIndexCount - i - 1) );
 
     delete poAI;
 
     nIndexCount--;
-             
+
 /* -------------------------------------------------------------------- */
 /*      Save the new configuration, or if there is nothing left try     */
 /*      to clean up the index files.                                    */
@@ -590,9 +602,9 @@ void OGRMILayerAttrIndex::AddAttrInd( int iField, int iINDIndex )
     OGRMIAttrIndex *poAttrInd = new OGRMIAttrIndex( this, iINDIndex, iField);
 
     nIndexCount++;
-    papoIndexList = (OGRMIAttrIndex **) 
+    papoIndexList = (OGRMIAttrIndex **)
         CPLRealloc(papoIndexList, sizeof(void*) * nIndexCount);
-    
+
     papoIndexList[nIndexCount-1] = poAttrInd;
 }
 
@@ -624,7 +636,7 @@ OGRErr OGRMILayerAttrIndex::AddToIndex( OGRFeature *poFeature,
 
     if( poFeature->GetFID() == OGRNullFID )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Attempt to index feature with no FID." );
         return OGRERR_FAILURE;
     }
@@ -639,7 +651,7 @@ OGRErr OGRMILayerAttrIndex::AddToIndex( OGRFeature *poFeature,
         if( !poFeature->IsFieldSet( iField ) )
             continue;
 
-        eErr = 
+        eErr =
             papoIndexList[i]->AddEntry( poFeature->GetRawFieldRef( iField ),
                                         poFeature->GetFID() );
     }
@@ -679,7 +691,7 @@ OGRLayerAttrIndex *OGRCreateDefaultLayerIndex()
 /*                           OGRMIAttrIndex()                           */
 /************************************************************************/
 
-OGRMIAttrIndex::OGRMIAttrIndex( OGRMILayerAttrIndex *poLayerIndex, 
+OGRMIAttrIndex::OGRMIAttrIndex( OGRMILayerAttrIndex *poLayerIndex,
                                 int iIndexIn, int iFieldIn )
 
 {
@@ -706,14 +718,17 @@ OGRMIAttrIndex::~OGRMIAttrIndex()
 OGRErr OGRMIAttrIndex::AddEntry( OGRField *psKey, GIntBig nFID )
 
 {
-    GByte *pabyKey = BuildKey( psKey );
-
     if( psKey == NULL )
         return OGRERR_FAILURE;
 
     if( nFID >= INT_MAX )
         return OGRERR_FAILURE;
 
+    GByte *pabyKey = BuildKey( psKey );
+
+    if( pabyKey == NULL )
+        return OGRERR_FAILURE;
+
     if( poINDFile->AddEntry( iIndex, pabyKey, (int)nFID+1 ) != 0 )
         return OGRERR_FAILURE;
     else
@@ -745,7 +760,7 @@ GByte *OGRMIAttrIndex::BuildKey( OGRField *psKey )
 
       case OFTInteger64:
       {
-        if( (GIntBig)(int)psKey->Integer64 != psKey->Integer64 )
+        if( !CPL_INT64_FITS_ON_INT32(psKey->Integer64) )
         {
             CPLError(CE_Warning, CPLE_NotSupported,
                      "64bit integer value passed to OGRMIAttrIndex::BuildKey()");
@@ -811,12 +826,12 @@ GIntBig *OGRMIAttrIndex::GetAllMatches( OGRField *psKey, GIntBig* panFIDList, in
             panFIDList = (GIntBig *) CPLRealloc(panFIDList, sizeof(GIntBig)* (*nLength));
         }
         panFIDList[(*nFIDCount)++] = nFID - 1;
-        
+
         nFID = poINDFile->FindNext( iIndex, pabyKey );
     }
 
     panFIDList[*nFIDCount] = OGRNullFID;
-    
+
     return panFIDList;
 }
 
diff --git a/ogr/ogrsf_frmts/generic/ogrdatasource.cpp b/ogr/ogrsf_frmts/generic/ogrdatasource.cpp
index 0204b12..3dfd661 100644
--- a/ogr/ogrsf_frmts/generic/ogrdatasource.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdatasource.cpp 28806 2015-03-28 14:37:47Z rouault $
+ * $Id: ogrdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The generic portions of the GDALDataset class.
@@ -32,7 +32,7 @@
 #include "ogr_api.h"
 #include "ograpispy.h"
 
-CPL_CVSID("$Id: ogrdatasource.cpp 28806 2015-03-28 14:37:47Z rouault $");
+CPL_CVSID("$Id: ogrdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                           ~OGRDataSource()                           */
@@ -70,7 +70,7 @@ void OGR_DS_Destroy( OGRDataSourceH hDS )
     //VALIDATE_POINTER0( hDS, "OGR_DS_Destroy" );
 #ifdef OGRAPISPY_ENABLED
     if( bOGRAPISpyEnabled )
-        OGRAPISpyPostClose(hDS);
+      OGRAPISpyPostClose();
 #endif
 }
 
@@ -126,7 +126,7 @@ int OGR_DS_GetSummaryRefCount( OGRDataSourceH hDataSource )
 /*                         OGR_DS_CreateLayer()                         */
 /************************************************************************/
 
-OGRLayerH OGR_DS_CreateLayer( OGRDataSourceH hDS, 
+OGRLayerH OGR_DS_CreateLayer( OGRDataSourceH hDS,
                               const char * pszName,
                               OGRSpatialReferenceH hSpatialRef,
                               OGRwkbGeometryType eType,
@@ -138,9 +138,9 @@ OGRLayerH OGR_DS_CreateLayer( OGRDataSourceH hDS,
     if (pszName == NULL)
     {
         CPLError ( CE_Failure, CPLE_ObjectNull, "Name was NULL in OGR_DS_CreateLayer");
-        return 0;
+        return NULL;
     }
-    OGRLayerH hLayer = (OGRLayerH) ((GDALDataset *)hDS)->CreateLayer( 
+    OGRLayerH hLayer = (OGRLayerH) ((GDALDataset *)hDS)->CreateLayer(
         pszName, (OGRSpatialReference *) hSpatialRef, eType, papszOptions );
 
 #ifdef OGRAPISPY_ENABLED
@@ -155,7 +155,7 @@ OGRLayerH OGR_DS_CreateLayer( OGRDataSourceH hDS,
 /*                          OGR_DS_CopyLayer()                          */
 /************************************************************************/
 
-OGRLayerH OGR_DS_CopyLayer( OGRDataSourceH hDS, 
+OGRLayerH OGR_DS_CopyLayer( OGRDataSourceH hDS,
                             OGRLayerH hSrcLayer, const char *pszNewName,
                             char **papszOptions )
 
@@ -164,8 +164,8 @@ OGRLayerH OGR_DS_CopyLayer( OGRDataSourceH hDS,
     VALIDATE_POINTER1( hSrcLayer, "OGR_DS_CopyLayer", NULL );
     VALIDATE_POINTER1( pszNewName, "OGR_DS_CopyLayer", NULL );
 
-    return (OGRLayerH) 
-        ((GDALDataset *) hDS)->CopyLayer( (OGRLayer *) hSrcLayer, 
+    return (OGRLayerH)
+        ((GDALDataset *) hDS)->CopyLayer( (OGRLayer *) hSrcLayer,
                                             pszNewName, papszOptions );
 }
 
@@ -211,7 +211,7 @@ OGRLayerH OGR_DS_GetLayerByName( OGRDataSourceH hDS, const char *pszName )
 /*                         OGR_DS_ExecuteSQL()                          */
 /************************************************************************/
 
-OGRLayerH OGR_DS_ExecuteSQL( OGRDataSourceH hDS, 
+OGRLayerH OGR_DS_ExecuteSQL( OGRDataSourceH hDS,
                              const char *pszStatement,
                              OGRGeometryH hSpatialFilter,
                              const char *pszDialect )
@@ -219,7 +219,7 @@ OGRLayerH OGR_DS_ExecuteSQL( OGRDataSourceH hDS,
 {
     VALIDATE_POINTER1( hDS, "OGR_DS_ExecuteSQL", NULL );
 
-    OGRLayerH hLayer = (OGRLayerH) 
+    OGRLayerH hLayer = (OGRLayerH)
         ((GDALDataset *)hDS)->ExecuteSQL( pszStatement,
                                             (OGRGeometry *) hSpatialFilter,
                                             pszDialect );
@@ -346,7 +346,7 @@ OGRStyleTableH OGR_DS_GetStyleTable( OGRDataSourceH hDS )
 
 {
     VALIDATE_POINTER1( hDS, "OGR_DS_GetStyleTable", NULL );
-    
+
     return (OGRStyleTableH) ((GDALDataset *) hDS)->GetStyleTable( );
 }
 
@@ -359,7 +359,7 @@ void OGR_DS_SetStyleTableDirectly( OGRDataSourceH hDS,
 
 {
     VALIDATE_POINTER0( hDS, "OGR_DS_SetStyleTableDirectly" );
-    
+
     ((GDALDataset *) hDS)->SetStyleTableDirectly( (OGRStyleTable *) hStyleTable);
 }
 
@@ -372,6 +372,6 @@ void OGR_DS_SetStyleTable( OGRDataSourceH hDS, OGRStyleTableH hStyleTable )
 {
     VALIDATE_POINTER0( hDS, "OGR_DS_SetStyleTable" );
     VALIDATE_POINTER0( hStyleTable, "OGR_DS_SetStyleTable" );
-    
+
     ((GDALDataset *) hDS)->SetStyleTable( (OGRStyleTable *) hStyleTable);
 }
diff --git a/ogr/ogrsf_frmts/generic/ogreditablelayer.cpp b/ogr/ogrsf_frmts/generic/ogreditablelayer.cpp
new file mode 100644
index 0000000..d0bad9e
--- /dev/null
+++ b/ogr/ogrsf_frmts/generic/ogreditablelayer.cpp
@@ -0,0 +1,816 @@
+/******************************************************************************
+ * $Id: ogreditablelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements OGREditableLayer class
+ * Author:   Even Rouault <even.rouault at spatialys.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogreditablelayer.h"
+#include "../mem/ogr_mem.h"
+
+CPL_CVSID("$Id: ogreditablelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+
+/************************************************************************/
+/*                  ~IOGREditableLayerSynchronizer()                    */
+/************************************************************************/
+
+IOGREditableLayerSynchronizer::~IOGREditableLayerSynchronizer()
+{
+}
+
+/************************************************************************/
+/*                          OGREditableLayer()                          */
+/************************************************************************/
+
+OGREditableLayer::OGREditableLayer(OGRLayer* poDecoratedLayer,
+                                   bool bTakeOwnershipDecoratedLayer,
+                                   IOGREditableLayerSynchronizer* poSynchronizer,
+                                   bool bTakeOwnershipSynchronizer):
+    OGRLayerDecorator(poDecoratedLayer,
+                      bTakeOwnershipDecoratedLayer),
+    m_poSynchronizer(poSynchronizer),
+    m_bTakeOwnershipSynchronizer(bTakeOwnershipSynchronizer),
+    m_nNextFID(0),
+    m_bStructureModified(false),
+    m_bSupportsCreateGeomField(false),
+    m_bSupportsCurveGeometries(false)
+{
+    m_poEditableFeatureDefn = poDecoratedLayer->GetLayerDefn()->Clone();
+    m_poEditableFeatureDefn->Reference();
+
+    m_poMemLayer = new OGRMemLayer( "", NULL, wkbNone );
+    for(int i=0;i<m_poEditableFeatureDefn->GetFieldCount();i++)
+        m_poMemLayer->CreateField(m_poEditableFeatureDefn->GetFieldDefn(i));
+    for(int i=0;i<m_poEditableFeatureDefn->GetGeomFieldCount();i++)
+        m_poMemLayer->CreateGeomField(m_poEditableFeatureDefn->GetGeomFieldDefn(i));
+    m_oIter = m_oSetCreated.begin();
+}
+
+/************************************************************************/
+/*                         ~OGREditableLayer()                          */
+/************************************************************************/
+
+OGREditableLayer::~OGREditableLayer()
+{
+    SyncToDisk();
+
+    m_poEditableFeatureDefn->Release();
+    delete m_poMemLayer;
+    if( m_bTakeOwnershipSynchronizer )
+        delete m_poSynchronizer;
+}
+
+/************************************************************************/
+/*                           SetNextFID()                               */
+/************************************************************************/
+
+void OGREditableLayer::SetNextFID(GIntBig nNextFID)
+{
+    m_nNextFID = nNextFID;
+}
+
+/************************************************************************/
+/*                       SetSupportsCurveGeometries()                   */
+/************************************************************************/
+
+void OGREditableLayer::SetSupportsCurveGeometries(bool bSupportsCurveGeometries)
+{
+    m_bSupportsCurveGeometries = bSupportsCurveGeometries;
+}
+
+/************************************************************************/
+/*                       SetSupportsCreateGeomField()                   */
+/************************************************************************/
+
+void OGREditableLayer::SetSupportsCreateGeomField(bool bSupportsCreateGeomField)
+{
+    m_bSupportsCreateGeomField = bSupportsCreateGeomField;
+}
+
+/************************************************************************/
+/*                           DetectNextFID()                            */
+/************************************************************************/
+
+void OGREditableLayer::DetectNextFID()
+{
+    if( m_nNextFID > 0 )
+        return;
+    m_nNextFID = 0;
+    m_poDecoratedLayer->ResetReading();
+    OGRFeature* poFeat;
+    while( (poFeat = m_poDecoratedLayer->GetNextFeature()) != NULL )
+    {
+        if( poFeat->GetFID() > m_nNextFID )
+            m_nNextFID = poFeat->GetFID();
+        delete poFeat;
+    }
+    m_nNextFID ++;
+}
+
+/************************************************************************/
+/*                         GetSrcGeomFieldIndex()                       */
+/************************************************************************/
+
+int OGREditableLayer::GetSrcGeomFieldIndex(int iGeomField)
+{
+    if( m_poDecoratedLayer == NULL ||
+        iGeomField < 0 ||
+        iGeomField >= m_poEditableFeatureDefn->GetGeomFieldCount() )
+    {
+        return -1;
+    }
+    OGRGeomFieldDefn* poGeomFieldDefn =
+                m_poEditableFeatureDefn->GetGeomFieldDefn(iGeomField);
+    return m_poDecoratedLayer->GetLayerDefn()->GetGeomFieldIndex(
+                                                poGeomFieldDefn->GetNameRef());
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void        OGREditableLayer::ResetReading()
+{
+    if( !m_poDecoratedLayer ) return;
+    m_poDecoratedLayer->ResetReading();
+    m_oIter = m_oSetCreated.begin();
+}
+
+/************************************************************************/
+/*                             Translate()                              */
+/************************************************************************/
+
+OGRFeature* OGREditableLayer::Translate(OGRFeatureDefn* poTargetDefn,
+                                        OGRFeature* poSrcFeature,
+                                        bool bCanStealSrcFeature,
+                                        bool bHideDeletedFields)
+{
+    if( poSrcFeature == NULL )
+        return NULL;
+    OGRFeature* poRet = new OGRFeature(poTargetDefn);
+
+    int* panMap = (int *) CPLMalloc( sizeof(int) * poSrcFeature->GetFieldCount() );
+    for( int iField = 0; iField < poSrcFeature->GetFieldCount(); iField++ )
+    {
+        const char* pszFieldName = poSrcFeature->GetFieldDefnRef(iField)->GetNameRef();
+        if( bHideDeletedFields &&
+            m_oSetDeletedFields.find(pszFieldName) != m_oSetDeletedFields.end() )
+        {
+            panMap[iField] = -1;
+        }
+        else
+            panMap[iField] = poRet->GetFieldIndex(pszFieldName);
+    }
+    poRet->SetFieldsFrom( poSrcFeature, panMap, TRUE );
+    CPLFree(panMap);
+
+    for( int i=0; i < poTargetDefn->GetGeomFieldCount(); i++ )
+    {
+        OGRGeomFieldDefn* poGeomField = poTargetDefn->GetGeomFieldDefn(i);
+        int iSrcGeomFieldIdx = poTargetDefn->GetGeomFieldIndex(
+                                                poGeomField->GetNameRef());
+        if( iSrcGeomFieldIdx >= 0 )
+        {
+            if( bCanStealSrcFeature )
+            {
+                poRet->SetGeomFieldDirectly( i,
+                         poSrcFeature->StealGeometry(iSrcGeomFieldIdx) );
+            }
+            else
+            {
+                poRet->SetGeomField( i,
+                         poSrcFeature->GetGeomFieldRef(iSrcGeomFieldIdx) );
+            }
+            OGRGeometry* poGeom = poRet->GetGeomFieldRef(i);
+            if( poGeom != NULL )
+                poGeom->assignSpatialReference( poGeomField->GetSpatialRef() );
+        }
+    }
+    poRet->SetStyleString( poSrcFeature->GetStyleString() );
+    poRet->SetNativeData( poSrcFeature->GetNativeData() );
+    poRet->SetNativeMediaType( poSrcFeature->GetNativeMediaType() );
+    poRet->SetFID(poSrcFeature->GetFID());
+
+    return poRet;
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature *OGREditableLayer::GetNextFeature()
+{
+    if( !m_poDecoratedLayer ) return NULL;
+    while( true )
+    {
+        OGRFeature* poSrcFeature = m_poDecoratedLayer->GetNextFeature();
+        bool bHideDeletedFields = true;
+        if( poSrcFeature != NULL )
+        {
+            const GIntBig nFID = poSrcFeature->GetFID();
+            if( m_oSetDeleted.find(nFID) != m_oSetDeleted.end() )
+            {
+                delete poSrcFeature;
+                continue;
+            }
+            else if( m_oSetCreated.find(nFID) != m_oSetCreated.end() ||
+                     m_oSetEdited.find(nFID) != m_oSetEdited.end() )
+            {
+                delete poSrcFeature;
+                poSrcFeature = m_poMemLayer->GetFeature(nFID);
+                bHideDeletedFields = false;
+            }
+        }
+        else
+        {
+            if( m_oIter != m_oSetCreated.end() )
+            {
+                poSrcFeature = m_poMemLayer->GetFeature(*m_oIter);
+                bHideDeletedFields = false;
+                ++ m_oIter;
+            }
+            else
+            {
+                return NULL;
+            }
+        }
+        OGRFeature* poRet = Translate(m_poEditableFeatureDefn, poSrcFeature,
+                                      true, bHideDeletedFields);
+        delete poSrcFeature;
+
+        if( (m_poFilterGeom == NULL
+             || FilterGeometry( poRet->GetGeomFieldRef(m_iGeomFieldFilter) ) )
+            && (m_poAttrQuery == NULL
+                || m_poAttrQuery->Evaluate( poRet ) ) )
+        {
+            return poRet;
+        }
+        delete poRet;
+    }
+}
+
+/************************************************************************/
+/*                          SetNextByIndex()                            */
+/************************************************************************/
+
+OGRErr      OGREditableLayer::SetNextByIndex( GIntBig nIndex )
+{
+    if( m_poDecoratedLayer != NULL &&
+        m_oSetCreated.size() == 0 &&
+        m_oSetDeleted.size() == 0 &&
+        m_oSetEdited.size() == 0 )
+    {
+        return m_poDecoratedLayer->SetNextByIndex(nIndex);
+    }
+
+    return OGRLayer::SetNextByIndex(nIndex);
+}
+
+/************************************************************************/
+/*                              GetFeature()                            */
+/************************************************************************/
+
+OGRFeature *OGREditableLayer::GetFeature( GIntBig nFID )
+{
+    if( !m_poDecoratedLayer ) return NULL;
+
+    OGRFeature* poSrcFeature;
+    bool bHideDeletedFields = true;
+    if( m_oSetCreated.find(nFID) != m_oSetCreated.end() ||
+        m_oSetEdited.find(nFID) != m_oSetEdited.end() )
+    {
+        poSrcFeature = m_poMemLayer->GetFeature(nFID);
+        bHideDeletedFields = false;
+    }
+    else if( m_oSetDeleted.find(nFID) != m_oSetDeleted.end() )
+    {
+        poSrcFeature = NULL;
+    }
+    else
+    {
+        poSrcFeature = m_poDecoratedLayer->GetFeature(nFID);
+    }
+    OGRFeature* poRet = Translate(m_poEditableFeatureDefn, poSrcFeature,
+                                  true, bHideDeletedFields);
+    delete poSrcFeature;
+    return poRet;
+}
+
+/************************************************************************/
+/*                            ISetFeature()                             */
+/************************************************************************/
+
+OGRErr      OGREditableLayer::ISetFeature( OGRFeature *poFeature )
+{
+    if( !m_poDecoratedLayer ) return OGRERR_FAILURE;
+
+    OGRFeature* poMemFeature = Translate(m_poMemLayer->GetLayerDefn(),
+                                         poFeature, false, false);
+    OGRErr eErr = m_poMemLayer->SetFeature(poMemFeature);
+    if( eErr == OGRERR_NONE )
+    {
+        const GIntBig nFID = poMemFeature->GetFID();
+        m_oSetDeleted.erase(nFID);
+        // If the feature isn't in the created list, insert it in the edited list
+        if( m_oSetCreated.find(nFID) == m_oSetCreated.end() )
+        {
+            m_oSetEdited.insert(nFID);
+        }
+        poFeature->SetFID(nFID);
+    }
+    delete poMemFeature;
+
+    ResetReading();
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                          ICreateFeature()                            */
+/************************************************************************/
+
+OGRErr      OGREditableLayer::ICreateFeature( OGRFeature *poFeature )
+{
+    if( !m_poDecoratedLayer ) return OGRERR_FAILURE;
+
+    if( !m_bStructureModified &&
+        m_poDecoratedLayer->TestCapability(OLCSequentialWrite) )
+    {
+        OGRFeature* poTargetFeature = Translate(m_poDecoratedLayer->GetLayerDefn(),
+                                                poFeature, false, false);
+        OGRErr eErr = m_poDecoratedLayer->CreateFeature(poTargetFeature);
+        delete poTargetFeature;
+        return eErr;
+    }
+
+    OGRFeature* poMemFeature = Translate(m_poMemLayer->GetLayerDefn(),
+                                         poFeature, false, false);
+    DetectNextFID();
+    if( poMemFeature->GetFID() < 0 )
+        poMemFeature->SetFID( m_nNextFID ++ );
+    OGRErr eErr = m_poMemLayer->CreateFeature(poMemFeature);
+    if( eErr == OGRERR_NONE )
+    {
+        const GIntBig nFID = poMemFeature->GetFID();
+        m_oSetDeleted.erase(nFID);
+        m_oSetEdited.erase(nFID);
+        m_oSetCreated.insert(nFID);
+        poFeature->SetFID(nFID);
+    }
+    delete poMemFeature;
+
+    ResetReading();
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                          DeleteFeature()                             */
+/************************************************************************/
+
+OGRErr      OGREditableLayer::DeleteFeature( GIntBig nFID )
+{
+    if( !m_poDecoratedLayer ) return OGRERR_FAILURE;
+
+    OGRErr eErr;
+    if( m_oSetDeleted.find(nFID) != m_oSetDeleted.end() )
+    {
+        eErr = OGRERR_NON_EXISTING_FEATURE;
+    }
+    else if( m_oSetCreated.find(nFID) != m_oSetCreated.end() )
+    {
+        m_oSetCreated.erase(nFID);
+        eErr = m_poMemLayer->DeleteFeature(nFID);
+    }
+    else if( m_oSetEdited.find(nFID) != m_oSetEdited.end() )
+    {
+        m_oSetEdited.erase(nFID);
+        m_oSetDeleted.insert(nFID);
+        eErr = m_poMemLayer->DeleteFeature(nFID);
+    }
+    else
+    {
+        OGRFeature* poFeature = m_poDecoratedLayer->GetFeature(nFID);
+        if( poFeature != NULL )
+        {
+            m_oSetDeleted.insert(nFID);
+            eErr = OGRERR_NONE;
+            delete poFeature;
+        }
+        else
+        {
+            eErr = OGRERR_NON_EXISTING_FEATURE;
+        }
+    }
+
+    ResetReading();
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                             GetGeomType()                            */
+/************************************************************************/
+
+OGRwkbGeometryType OGREditableLayer::GetGeomType()
+{
+    return OGRLayer::GetGeomType();
+}
+
+/************************************************************************/
+/*                             GetLayerDefn()                           */
+/************************************************************************/
+
+OGRFeatureDefn *OGREditableLayer::GetLayerDefn()
+{
+    return m_poEditableFeatureDefn;
+}
+
+/************************************************************************/
+/*                             GetSpatialRef()                          */
+/************************************************************************/
+
+OGRSpatialReference *OGREditableLayer::GetSpatialRef()
+{
+    return OGRLayer::GetSpatialRef();
+}
+
+/************************************************************************/
+/*                           GetSpatialFilter()                         */
+/************************************************************************/
+
+OGRGeometry *OGREditableLayer::GetSpatialFilter()
+{
+    return OGRLayer::GetSpatialFilter();
+}
+
+/************************************************************************/
+/*                           SetAttributeFilter()                       */
+/************************************************************************/
+
+OGRErr      OGREditableLayer::SetAttributeFilter( const char * poAttrFilter )
+{
+    return OGRLayer::SetAttributeFilter(poAttrFilter);
+}
+
+/************************************************************************/
+/*                           SetSpatialFilter()                         */
+/************************************************************************/
+
+void        OGREditableLayer::SetSpatialFilter( OGRGeometry * poGeom )
+{
+    SetSpatialFilter(0, poGeom);
+}
+
+/************************************************************************/
+/*                           SetSpatialFilter()                         */
+/************************************************************************/
+
+void        OGREditableLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poGeom )
+{
+    if( iGeomField < 0 ||
+        (iGeomField != 0 && iGeomField >= GetLayerDefn()->GetGeomFieldCount()) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Invalid geometry field index : %d", iGeomField);
+        return;
+    }
+
+    m_iGeomFieldFilter = iGeomField;
+    if( InstallFilter( poGeom ) )
+        ResetReading();
+
+    int iSrcGeomFieldIdx = GetSrcGeomFieldIndex(iGeomField);
+    if( iSrcGeomFieldIdx >= 0 )
+    {
+        m_poDecoratedLayer->SetSpatialFilter(iSrcGeomFieldIdx, poGeom);
+    }
+    m_poMemLayer->SetSpatialFilter(iGeomField, poGeom);
+}
+
+/************************************************************************/
+/*                         SetSpatialFilterRect()                       */
+/************************************************************************/
+
+void        OGREditableLayer::SetSpatialFilterRect( double dfMinX, double dfMinY,
+                                                    double dfMaxX, double dfMaxY )
+{
+   return OGRLayer::SetSpatialFilterRect(dfMinX, dfMinY, dfMaxX, dfMaxY);
+}
+
+/************************************************************************/
+/*                         SetSpatialFilterRect()                       */
+/************************************************************************/
+
+void        OGREditableLayer::SetSpatialFilterRect(
+                                  int iGeomField, double dfMinX, double dfMinY,
+                                  double dfMaxX, double dfMaxY )
+{
+    return OGRLayer::SetSpatialFilterRect(iGeomField, dfMinX, dfMinY, dfMaxX, dfMaxY);
+}
+
+/************************************************************************/
+/*                          GetFeatureCount()                           */
+/************************************************************************/
+
+GIntBig         OGREditableLayer::GetFeatureCount( int bForce )
+{
+    if( !m_poDecoratedLayer ) return 0;
+    if( m_poAttrQuery == NULL && m_poFilterGeom == NULL &&
+        m_oSetDeleted.size() == 0 &&
+        m_oSetEdited.size() == 0 )
+    {
+        GIntBig nFC = m_poDecoratedLayer->GetFeatureCount(bForce);
+        if( nFC >= 0 )
+        {
+            nFC += m_oSetCreated.size();
+        }
+        return nFC;
+    }
+    return OGRLayer::GetFeatureCount(bForce);
+}
+
+/************************************************************************/
+/*                             GetExtent()                              */
+/************************************************************************/
+
+OGRErr      OGREditableLayer::GetExtent(OGREnvelope *psExtent, int bForce)
+{
+    return GetExtent(0, psExtent, bForce);
+}
+
+/************************************************************************/
+/*                               GetExtent()                            */
+/************************************************************************/
+
+OGRErr      OGREditableLayer::GetExtent(int iGeomField, OGREnvelope *psExtent,
+                                        int bForce)
+{
+    if( !m_poDecoratedLayer ) return OGRERR_FAILURE;
+    int iSrcGeomFieldIdx = GetSrcGeomFieldIndex(iGeomField);
+    if( iSrcGeomFieldIdx >= 0 && m_oSetEdited.size() == 0 &&
+        m_oSetDeleted.size() == 0 )
+    {
+        OGRErr eErr = m_poDecoratedLayer->GetExtent(iSrcGeomFieldIdx, psExtent,
+                                                    bForce);
+        if( eErr == OGRERR_NONE )
+        {
+            OGREnvelope sExtentMemLayer;
+            if( m_poMemLayer->GetExtent(iGeomField,
+                                    &sExtentMemLayer, bForce) == OGRERR_NONE )
+            {
+                psExtent->Merge(sExtentMemLayer);
+            }
+        }
+        return eErr;
+    }
+    return GetExtentInternal(iGeomField, psExtent, bForce);
+}
+
+/************************************************************************/
+/*                            TestCapability()                          */
+/************************************************************************/
+
+int         OGREditableLayer::TestCapability( const char * pszCap )
+{
+    if( !m_poDecoratedLayer ) return FALSE;
+    if( EQUAL(pszCap, OLCSequentialWrite) ||
+        EQUAL(pszCap, OLCRandomWrite) ||
+        EQUAL(pszCap, OLCCreateField) ||
+        EQUAL(pszCap, OLCDeleteField) ||
+        EQUAL(pszCap, OLCReorderFields) ||
+        EQUAL(pszCap, OLCAlterFieldDefn) ||
+        EQUAL(pszCap, OLCDeleteFeature) )
+    {
+        return TRUE;
+    }
+    if( EQUAL(pszCap, OLCCreateGeomField) )
+        return m_bSupportsCreateGeomField;
+    if( EQUAL(pszCap, OLCCurveGeometries) )
+        return m_bSupportsCurveGeometries;
+    if( EQUAL(pszCap, OLCTransactions) )
+        return FALSE;
+
+    return m_poDecoratedLayer->TestCapability(pszCap);
+}
+
+/************************************************************************/
+/*                            CreateField()                             */
+/************************************************************************/
+
+OGRErr      OGREditableLayer::CreateField( OGRFieldDefn *poField,
+                                            int bApproxOK )
+{
+    if( !m_poDecoratedLayer ) return OGRERR_FAILURE;
+
+    // workarounds a bug in certain QGIS versions (2.0 for example)
+    SetIgnoredFields(NULL);
+
+    if( !m_bStructureModified &&
+        m_poDecoratedLayer->TestCapability(OLCCreateField) )
+    {
+        OGRErr eErr = m_poDecoratedLayer->CreateField(poField, bApproxOK);
+        if( eErr == OGRERR_NONE )
+        {
+            eErr = m_poMemLayer->CreateField(poField, bApproxOK);
+            if( eErr == OGRERR_NONE )
+            {
+                m_poEditableFeatureDefn->AddFieldDefn(poField);
+            }
+        }
+        return eErr;
+    }
+
+    OGRErr eErr = m_poMemLayer->CreateField(poField, bApproxOK);
+    if( eErr == OGRERR_NONE )
+    {
+        m_poEditableFeatureDefn->AddFieldDefn(poField);
+        m_bStructureModified = true;
+    }
+    return eErr;
+}
+
+/************************************************************************/
+/*                             DeleteField()                            */
+/************************************************************************/
+
+OGRErr      OGREditableLayer::DeleteField( int iField )
+{
+    if( !m_poDecoratedLayer ) return OGRERR_FAILURE;
+
+    // workarounds a bug in certain QGIS versions (2.0 for example)
+    SetIgnoredFields(NULL);
+
+    CPLString osDeletedField;
+    if( iField >= 0 && iField < m_poEditableFeatureDefn->GetFieldCount() )
+    {
+        osDeletedField = m_poEditableFeatureDefn->GetFieldDefn(iField)->GetNameRef();
+    }
+
+    OGRErr eErr = m_poMemLayer->DeleteField(iField);
+    if( eErr == OGRERR_NONE )
+    {
+        m_poEditableFeatureDefn->DeleteFieldDefn(iField);
+        m_bStructureModified = true;
+        m_oSetDeletedFields.insert(osDeletedField);
+    }
+    return eErr;
+}
+
+/************************************************************************/
+/*                             ReorderFields()                          */
+/************************************************************************/
+
+OGRErr      OGREditableLayer::ReorderFields( int* panMap )
+{
+    if( !m_poDecoratedLayer ) return OGRERR_FAILURE;
+    OGRErr eErr = m_poMemLayer->ReorderFields(panMap);
+    if( eErr == OGRERR_NONE )
+    {
+        m_poEditableFeatureDefn->ReorderFieldDefns(panMap);
+        m_bStructureModified = true;
+    }
+    return eErr;
+}
+
+/************************************************************************/
+/*                            AlterFieldDefn()                          */
+/************************************************************************/
+
+OGRErr      OGREditableLayer::AlterFieldDefn( int iField,
+                                              OGRFieldDefn* poNewFieldDefn,
+                                              int nFlagsIn )
+{
+    if( !m_poDecoratedLayer ) return OGRERR_FAILURE;
+    OGRErr eErr = m_poMemLayer->AlterFieldDefn(iField, poNewFieldDefn, nFlagsIn);
+    if( eErr == OGRERR_NONE )
+    {
+        OGRFieldDefn* poFieldDefn = m_poEditableFeatureDefn->GetFieldDefn(iField);
+        OGRFieldDefn* poMemFieldDefn = m_poMemLayer->GetLayerDefn()->GetFieldDefn(iField);
+        poFieldDefn->SetName(poMemFieldDefn->GetNameRef());
+        poFieldDefn->SetType(poMemFieldDefn->GetType());
+        poFieldDefn->SetWidth(poMemFieldDefn->GetWidth());
+        poFieldDefn->SetPrecision(poMemFieldDefn->GetPrecision());
+        m_bStructureModified = true;
+    }
+    return eErr;
+}
+
+/************************************************************************/
+/*                          CreateGeomField()                          */
+/************************************************************************/
+
+OGRErr      OGREditableLayer::CreateGeomField( OGRGeomFieldDefn *poField,
+                                            int bApproxOK )
+{
+    if( !m_poDecoratedLayer || !m_bSupportsCreateGeomField ) return OGRERR_FAILURE;
+
+    if( !m_bStructureModified && m_poDecoratedLayer->TestCapability(OLCCreateGeomField) )
+    {
+        OGRErr eErr = m_poDecoratedLayer->CreateGeomField(poField, bApproxOK);
+        if( eErr == OGRERR_NONE )
+        {
+            eErr = m_poMemLayer->CreateGeomField(poField, bApproxOK);
+            if( eErr == OGRERR_NONE )
+            {
+                m_poEditableFeatureDefn->AddGeomFieldDefn(poField);
+            }
+        }
+        return eErr;
+    }
+
+    OGRErr eErr = m_poMemLayer->CreateGeomField(poField, bApproxOK);
+    if( eErr == OGRERR_NONE )
+    {
+        m_poEditableFeatureDefn->AddGeomFieldDefn(poField);
+        m_bStructureModified = true;
+    }
+    return eErr;
+}
+
+/************************************************************************/
+/*                             SyncToDisk()                             */
+/************************************************************************/
+
+OGRErr      OGREditableLayer::SyncToDisk()
+{
+    if( !m_poDecoratedLayer || m_poSynchronizer == NULL ) return OGRERR_FAILURE;
+    OGRErr eErr = m_poDecoratedLayer->SyncToDisk();
+    if( eErr == OGRERR_NONE )
+    {
+        if( m_oSetCreated.size() == 0 && m_oSetEdited.size() == 0 &&
+            m_oSetDeleted.size() == 0 && !m_bStructureModified )
+        {
+            return OGRERR_NONE;
+        }
+        eErr = m_poSynchronizer->EditableSyncToDisk(this, &m_poDecoratedLayer);
+    }
+    m_oSetCreated.clear();
+    m_oSetEdited.clear();
+    m_oSetDeleted.clear();
+    m_oSetDeletedFields.clear();
+    m_bStructureModified = false;
+    return eErr;
+}
+
+/************************************************************************/
+/*                          StartTransaction()                          */
+/************************************************************************/
+
+OGRErr OGREditableLayer::StartTransaction()
+
+{
+    return OGRLayer::StartTransaction();
+}
+
+/************************************************************************/
+/*                         CommitTransaction()                          */
+/************************************************************************/
+
+OGRErr OGREditableLayer::CommitTransaction()
+
+{
+    return OGRLayer::CommitTransaction();
+}
+
+/************************************************************************/
+/*                        RollbackTransaction()                         */
+/************************************************************************/
+
+OGRErr OGREditableLayer::RollbackTransaction()
+
+{
+    return OGRLayer::RollbackTransaction();
+}
+
+/************************************************************************/
+/*                         GetGeometryColumn()                          */
+/************************************************************************/
+
+const char *OGREditableLayer::GetGeometryColumn()
+
+{
+    return OGRLayer::GetGeometryColumn();
+}
diff --git a/ogr/ogrsf_frmts/generic/ogreditablelayer.h b/ogr/ogrsf_frmts/generic/ogreditablelayer.h
new file mode 100644
index 0000000..e3b092f
--- /dev/null
+++ b/ogr/ogrsf_frmts/generic/ogreditablelayer.h
@@ -0,0 +1,129 @@
+/******************************************************************************
+ * $Id: ogreditablelayer.h 33714 2016-03-13 05:42:13Z goatbar $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Defines OGREditableLayer class
+ * Author:   Even Rouault <even.rouault at spatialys.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef OGREDITABLELAYER_H_INCLUDED
+#define OGREDITABLELAYER_H_INCLUDED
+
+#include "ogrlayerdecorator.h"
+#include <set>
+
+class CPL_DLL IOGREditableLayerSynchronizer
+{
+    public:
+        virtual ~IOGREditableLayerSynchronizer();
+
+        virtual OGRErr EditableSyncToDisk(OGRLayer* poEditableLayer,
+                                          OGRLayer** ppoDecoratedLayer) = 0;
+};
+
+class CPL_DLL OGREditableLayer : public OGRLayerDecorator
+{
+  protected:
+
+    IOGREditableLayerSynchronizer *m_poSynchronizer;
+    bool                           m_bTakeOwnershipSynchronizer;
+    OGRFeatureDefn                *m_poEditableFeatureDefn;
+    GIntBig                        m_nNextFID;
+    std::set<GIntBig>              m_oSetCreated;
+    std::set<GIntBig>              m_oSetEdited;
+    std::set<GIntBig>              m_oSetDeleted;
+    std::set<GIntBig>::iterator    m_oIter;
+    std::set<CPLString>            m_oSetDeletedFields;
+    OGRLayer                      *m_poMemLayer;
+    bool                           m_bStructureModified;
+    bool                           m_bSupportsCreateGeomField;
+    bool                           m_bSupportsCurveGeometries;
+
+    OGRFeature                    *Translate(OGRFeatureDefn* poTargetDefn,
+                                             OGRFeature* poSrcFeature,
+                                             bool bCanStealSrcFeature,
+                                             bool bHideDeletedFields);
+    void                           DetectNextFID();
+    int                            GetSrcGeomFieldIndex(int iGeomField);
+
+  public:
+
+                       OGREditableLayer(OGRLayer* poDecoratedLayer,
+                                        bool bTakeOwnershipDecoratedLayer,
+                                        IOGREditableLayerSynchronizer* poSynchronizer,
+                                        bool bTakeOwnershipSynchronizer);
+    virtual           ~OGREditableLayer();
+
+    void                SetNextFID(GIntBig nNextFID);
+    void                SetSupportsCreateGeomField(bool SupportsCreateGeomField);
+    void                SetSupportsCurveGeometries(bool bSupportsCurveGeometries);
+
+    virtual OGRGeometry *GetSpatialFilter();
+    virtual void        SetSpatialFilter( OGRGeometry * );
+    virtual void        SetSpatialFilterRect( double dfMinX, double dfMinY,
+                                              double dfMaxX, double dfMaxY );
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * );
+    virtual void        SetSpatialFilterRect( int iGeomField, double dfMinX, double dfMinY,
+                                              double dfMaxX, double dfMaxY );
+
+    virtual OGRErr      SetAttributeFilter( const char * );
+
+    virtual void        ResetReading();
+    virtual OGRFeature *GetNextFeature();
+    virtual OGRErr      SetNextByIndex( GIntBig nIndex );
+    virtual OGRFeature *GetFeature( GIntBig nFID );
+    virtual OGRErr      ISetFeature( OGRFeature *poFeature );
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
+    virtual OGRErr      DeleteFeature( GIntBig nFID );
+
+    virtual OGRwkbGeometryType GetGeomType();
+    virtual OGRFeatureDefn *GetLayerDefn();
+
+    virtual OGRSpatialReference *GetSpatialRef();
+
+    virtual GIntBig     GetFeatureCount( int bForce = TRUE );
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce = TRUE);
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+
+    virtual int         TestCapability( const char * );
+
+    virtual OGRErr      CreateField( OGRFieldDefn *poField,
+                                     int bApproxOK = TRUE );
+    virtual OGRErr      DeleteField( int iField );
+    virtual OGRErr      ReorderFields( int* panMap );
+    virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags );
+
+    virtual OGRErr      CreateGeomField( OGRGeomFieldDefn *poField,
+                                         int bApproxOK = TRUE );
+
+    virtual OGRErr      SyncToDisk();
+
+    virtual OGRErr      StartTransaction();
+    virtual OGRErr      CommitTransaction();
+    virtual OGRErr      RollbackTransaction();
+
+    virtual const char *GetGeometryColumn();
+};
+
+#endif // OGREDITABLELAYER_H_INCLUDED
diff --git a/ogr/ogrsf_frmts/generic/ogremulatedtransaction.cpp b/ogr/ogrsf_frmts/generic/ogremulatedtransaction.cpp
index e60fc7a..7833cae 100644
--- a/ogr/ogrsf_frmts/generic/ogremulatedtransaction.cpp
+++ b/ogr/ogrsf_frmts/generic/ogremulatedtransaction.cpp
@@ -43,9 +43,9 @@ class OGRLayerWithTransaction: public OGRLayerDecorator
 
         OGRDataSourceWithTransaction* m_poDS;
         OGRFeatureDefn* m_poFeatureDefn;
-    
+
     public:
-        
+
         OGRLayerWithTransaction(OGRDataSourceWithTransaction* poDS,
                                 OGRLayer* poBaseLayer);
        ~OGRLayerWithTransaction();
@@ -66,7 +66,7 @@ class OGRLayerWithTransaction: public OGRLayerDecorator
     virtual OGRFeature *GetFeature( GIntBig nFID );
     virtual OGRErr      ISetFeature( OGRFeature *poFeature );
     virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
-  
+
 };
 
 
@@ -94,7 +94,7 @@ class OGRDataSourceWithTransaction : public OGRDataSource
                                           int bTakeOwnershipTransactionBehaviour);
 
     virtual     ~OGRDataSourceWithTransaction();
-    
+
     int                 IsInTransaction() const { return m_bInTransaction; }
 
     virtual const char  *GetName();
@@ -106,24 +106,24 @@ class OGRDataSourceWithTransaction : public OGRDataSource
 
     virtual int         TestCapability( const char * );
 
-    virtual OGRLayer   *ICreateLayer( const char *pszName, 
+    virtual OGRLayer   *ICreateLayer( const char *pszName,
                                      OGRSpatialReference *poSpatialRef = NULL,
                                      OGRwkbGeometryType eGType = wkbUnknown,
                                      char ** papszOptions = NULL );
-    virtual OGRLayer   *CopyLayer( OGRLayer *poSrcLayer, 
-                                   const char *pszNewName, 
+    virtual OGRLayer   *CopyLayer( OGRLayer *poSrcLayer,
+                                   const char *pszNewName,
                                    char **papszOptions = NULL );
 
     virtual OGRStyleTable *GetStyleTable();
     virtual void        SetStyleTableDirectly( OGRStyleTable *poStyleTable );
-                            
+
     virtual void        SetStyleTable(OGRStyleTable *poStyleTable);
 
     virtual OGRLayer *  ExecuteSQL( const char *pszStatement,
                                     OGRGeometry *poSpatialFilter,
                                     const char *pszDialect );
     virtual void        ReleaseResultSet( OGRLayer * poResultsSet );
-    
+
     virtual void        FlushCache();
 
     virtual OGRErr      StartTransaction(int bForce=FALSE);
@@ -204,10 +204,10 @@ OGRLayer* OGRDataSourceWithTransaction::WrapLayer(OGRLayer* poLayer)
             poLayer = poWrappedLayer;
         else
         {
-            OGRLayerWithTransaction* poWrappedLayer = new OGRLayerWithTransaction(this,poLayer);
-            m_oMapLayers[poLayer->GetName()] = poWrappedLayer;
-            m_oSetLayers.insert(poWrappedLayer);
-            poLayer = poWrappedLayer;
+            OGRLayerWithTransaction* poMutexedLayer = new OGRLayerWithTransaction(this,poLayer);
+            m_oMapLayers[poLayer->GetName()] = poMutexedLayer;
+            m_oSetLayers.insert(poMutexedLayer);
+            poLayer = poMutexedLayer;
         }
     }
     return poLayer;
@@ -246,7 +246,7 @@ OGRLayer    *OGRDataSourceWithTransaction::GetLayer(int iIndex)
 {
     if( !m_poBaseDataSource ) return NULL;
     return WrapLayer(m_poBaseDataSource->GetLayer(iIndex));
-    
+
 }
 
 OGRLayer    *OGRDataSourceWithTransaction::GetLayerByName(const char *pszName)
@@ -286,7 +286,7 @@ int         OGRDataSourceWithTransaction::TestCapability( const char * pszCap )
     return m_poBaseDataSource->TestCapability(pszCap);
 }
 
-OGRLayer   *OGRDataSourceWithTransaction::ICreateLayer( const char *pszName, 
+OGRLayer   *OGRDataSourceWithTransaction::ICreateLayer( const char *pszName,
                                      OGRSpatialReference *poSpatialRef,
                                      OGRwkbGeometryType eGType,
                                      char ** papszOptions)
@@ -295,8 +295,8 @@ OGRLayer   *OGRDataSourceWithTransaction::ICreateLayer( const char *pszName,
     return WrapLayer(m_poBaseDataSource->CreateLayer(pszName, poSpatialRef, eGType, papszOptions));
 }
 
-OGRLayer   *OGRDataSourceWithTransaction::CopyLayer( OGRLayer *poSrcLayer, 
-                                   const char *pszNewName, 
+OGRLayer   *OGRDataSourceWithTransaction::CopyLayer( OGRLayer *poSrcLayer,
+                                   const char *pszNewName,
                                    char **papszOptions )
 {
     if( !m_poBaseDataSource ) return NULL;
@@ -541,10 +541,10 @@ OGRErr      OGRLayerWithTransaction::ReorderFields( int* panMap )
 
 OGRErr      OGRLayerWithTransaction::AlterFieldDefn( int iField,
                                                      OGRFieldDefn* poNewFieldDefn,
-                                                     int nFlags )
+                                                     int nFlagsIn )
 {
     if( !m_poDecoratedLayer ) return OGRERR_FAILURE;
-    OGRErr eErr = m_poDecoratedLayer->AlterFieldDefn(iField, poNewFieldDefn, nFlags);
+    OGRErr eErr = m_poDecoratedLayer->AlterFieldDefn(iField, poNewFieldDefn, nFlagsIn);
     if( m_poFeatureDefn && eErr == OGRERR_NONE )
     {
         OGRFieldDefn* poSrcFieldDefn = m_poDecoratedLayer->GetLayerDefn()->GetFieldDefn(iField);
@@ -608,4 +608,3 @@ OGRErr       OGRLayerWithTransaction::ICreateFeature( OGRFeature *poFeature )
     delete poSrcFeature;
     return eErr;
 }
-
diff --git a/ogr/ogrsf_frmts/generic/ogremulatedtransaction.h b/ogr/ogrsf_frmts/generic/ogremulatedtransaction.h
index d0477c1..71ff366 100644
--- a/ogr/ogrsf_frmts/generic/ogremulatedtransaction.h
+++ b/ogr/ogrsf_frmts/generic/ogremulatedtransaction.h
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGREMULATEDTRANSACTION_H_INCLUDED
-#define _OGREMULATEDTRANSACTION_H_INCLUDED
+#ifndef OGREMULATEDTRANSACTION_H_INCLUDED
+#define OGREMULATEDTRANSACTION_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 
@@ -93,7 +93,7 @@ class CPL_DLL IOGRTransactionBehaviour
 
 
 /** Returns a new datasource object that adds transactional behaviour to an existing datasource.
- * 
+ *
  * The provided poTransactionBehaviour object should implement driver-specific
  * behaviour for transactions.
  *
@@ -125,4 +125,4 @@ OGRDataSource CPL_DLL* OGRCreateEmulatedTransactionDataSourceWrapper(
                                 int bTakeOwnershipDataSource,
                                 int bTakeOwnershipTransactionBehaviour);
 
-#endif // _OGREMULATEDTRANSACTION_H_INCLUDED
+#endif // OGREMULATEDTRANSACTION_H_INCLUDED
diff --git a/ogr/ogrsf_frmts/generic/ogrlayer.cpp b/ogr/ogrsf_frmts/generic/ogrlayer.cpp
index 87aa925..74b7fbd 100644
--- a/ogr/ogrsf_frmts/generic/ogrlayer.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrlayer.cpp 33074 2016-01-22 09:31:13Z rouault $
+ * $Id: ogrlayer.cpp 33754 2016-03-20 17:03:43Z ajolma $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The generic portions of the OGRSFLayer class.
@@ -35,7 +35,7 @@
 #include "swq.h"
 #include "ograpispy.h"
 
-CPL_CVSID("$Id: ogrlayer.cpp 33074 2016-01-22 09:31:13Z rouault $");
+CPL_CVSID("$Id: ogrlayer.cpp 33754 2016-03-20 17:03:43Z ajolma $");
 
 /************************************************************************/
 /*                              OGRLayer()                              */
@@ -282,13 +282,13 @@ OGRErr OGRLayer::GetExtentInternal(int iGeomField, OGREnvelope *psExtent, int bF
         else
         {
             poGeom->getEnvelope(&oEnv);
-            if (oEnv.MinX < psExtent->MinX) 
+            if (oEnv.MinX < psExtent->MinX)
                 psExtent->MinX = oEnv.MinX;
-            if (oEnv.MinY < psExtent->MinY) 
+            if (oEnv.MinY < psExtent->MinY)
                 psExtent->MinY = oEnv.MinY;
-            if (oEnv.MaxX > psExtent->MaxX) 
+            if (oEnv.MaxX > psExtent->MaxX)
                 psExtent->MaxX = oEnv.MaxX;
-            if (oEnv.MaxY > psExtent->MaxY) 
+            if (oEnv.MaxY > psExtent->MaxY)
                 psExtent->MaxY = oEnv.MaxY;
         }
         delete poFeature;
@@ -464,13 +464,13 @@ OGRFeature *OGRLayer::GetFeature( GIntBig nFID )
         else
             delete poFeature;
     }
-    
+
     /* Restore filters */
     SetAttributeFilter(pszOldFilter);
     CPLFree(pszOldFilter);
     SetSpatialFilter(iOldGeomFieldFilter, poOldFilterGeom);
     delete poOldFilterGeom;
-    
+
     return poFeature;
 }
 
@@ -551,18 +551,24 @@ OGRFeatureH OGR_L_GetNextFeature( OGRLayerH hLayer )
 }
 
 /************************************************************************/
-/*                    ConvertNonLinearGeomsIfNecessary()                */
+/*                       ConvertGeomsIfNecessary()                      */
 /************************************************************************/
 
-void OGRLayer::ConvertNonLinearGeomsIfNecessary( OGRFeature *poFeature )
+void OGRLayer::ConvertGeomsIfNecessary( OGRFeature *poFeature )
 {
-    if( !TestCapability(OLCCurveGeometries) )
+    const bool bSupportsCurve = CPL_TO_BOOL(TestCapability(OLCCurveGeometries));
+    const bool bSupportsM = CPL_TO_BOOL(TestCapability(OLCMeasuredGeometries));
+    if( !bSupportsCurve || !bSupportsM )
     {
         int nGeomFieldCount = GetLayerDefn()->GetGeomFieldCount();
         for(int i=0;i<nGeomFieldCount;i++)
         {
             OGRGeometry* poGeom = poFeature->GetGeomFieldRef(i);
-            if( poGeom != NULL && OGR_GT_IsNonLinear(poGeom->getGeometryType()) )
+            if( poGeom != NULL && (!bSupportsM && OGR_GT_HasM(poGeom->getGeometryType())) )
+            {
+                poGeom->setMeasured(FALSE);
+            }
+            if( poGeom != NULL && (!bSupportsCurve && OGR_GT_IsNonLinear(poGeom->getGeometryType())) )
             {
                 OGRwkbGeometryType eTargetType = OGR_GT_GetLinear(poGeom->getGeometryType());
                 poFeature->SetGeomFieldDirectly(i,
@@ -579,7 +585,7 @@ void OGRLayer::ConvertNonLinearGeomsIfNecessary( OGRFeature *poFeature )
 OGRErr OGRLayer::SetFeature( OGRFeature *poFeature )
 
 {
-    ConvertNonLinearGeomsIfNecessary(poFeature);
+    ConvertGeomsIfNecessary(poFeature);
     return ISetFeature(poFeature);
 }
 
@@ -618,7 +624,7 @@ OGRErr OGR_L_SetFeature( OGRLayerH hLayer, OGRFeatureH hFeat )
 OGRErr OGRLayer::CreateFeature( OGRFeature *poFeature )
 
 {
-    ConvertNonLinearGeomsIfNecessary(poFeature);
+    ConvertGeomsIfNecessary(poFeature);
     return ICreateFeature(poFeature);
 }
 
@@ -662,7 +668,7 @@ OGRErr OGRLayer::CreateField( OGRFieldDefn * poField, int bApproxOK )
 
     CPLError( CE_Failure, CPLE_NotSupported,
               "CreateField() not supported by this layer.\n" );
-              
+
     return OGRERR_UNSUPPORTED_OPERATION;
 }
 
@@ -670,7 +676,7 @@ OGRErr OGRLayer::CreateField( OGRFieldDefn * poField, int bApproxOK )
 /*                         OGR_L_CreateField()                          */
 /************************************************************************/
 
-OGRErr OGR_L_CreateField( OGRLayerH hLayer, OGRFieldDefnH hField, 
+OGRErr OGR_L_CreateField( OGRLayerH hLayer, OGRFieldDefnH hField,
                           int bApproxOK )
 
 {
@@ -682,7 +688,7 @@ OGRErr OGR_L_CreateField( OGRLayerH hLayer, OGRFieldDefnH hField,
         OGRAPISpy_L_CreateField(hLayer, hField, bApproxOK);
 #endif
 
-    return ((OGRLayer *) hLayer)->CreateField( (OGRFieldDefn *) hField, 
+    return ((OGRLayer *) hLayer)->CreateField( (OGRFieldDefn *) hField,
                                                bApproxOK );
 }
 
@@ -829,14 +835,11 @@ OGRErr OGR_L_ReorderField( OGRLayerH hLayer, int iOldFieldPos, int iNewFieldPos
 /*                           AlterFieldDefn()                           */
 /************************************************************************/
 
-OGRErr OGRLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn,
-                                 int nFlags )
+OGRErr OGRLayer::AlterFieldDefn( int /* iField*/,
+                                 OGRFieldDefn* /*poNewFieldDefn*/,
+                                 int /* nFlags */ )
 
 {
-    (void) iField;
-    (void) poNewFieldDefn;
-    (void) nFlags;
-
     CPLError( CE_Failure, CPLE_NotSupported,
               "AlterFieldDefn() not supported by this layer.\n" );
 
@@ -874,7 +877,7 @@ OGRErr OGRLayer::CreateGeomField( OGRGeomFieldDefn * poField, int bApproxOK )
 
     CPLError( CE_Failure, CPLE_NotSupported,
               "CreateGeomField() not supported by this layer.\n" );
-              
+
     return OGRERR_UNSUPPORTED_OPERATION;
 }
 
@@ -882,7 +885,7 @@ OGRErr OGRLayer::CreateGeomField( OGRGeomFieldDefn * poField, int bApproxOK )
 /*                        OGR_L_CreateGeomField()                       */
 /************************************************************************/
 
-OGRErr OGR_L_CreateGeomField( OGRLayerH hLayer, OGRGeomFieldDefnH hField, 
+OGRErr OGR_L_CreateGeomField( OGRLayerH hLayer, OGRGeomFieldDefnH hField,
                               int bApproxOK )
 
 {
@@ -894,7 +897,7 @@ OGRErr OGR_L_CreateGeomField( OGRLayerH hLayer, OGRGeomFieldDefnH hField,
         OGRAPISpy_L_CreateGeomField(hLayer, hField, bApproxOK);
 #endif
 
-    return ((OGRLayer *) hLayer)->CreateGeomField( (OGRGeomFieldDefn *) hField, 
+    return ((OGRLayer *) hLayer)->CreateGeomField( (OGRGeomFieldDefn *) hField,
                                                    bApproxOK );
 }
 
@@ -1027,7 +1030,7 @@ int OGRLayer::FindFieldIndex( const char *pszFieldName, CPL_UNUSED int bExactMat
 /************************************************************************/
 
 OGRSpatialReference *OGRLayer::GetSpatialRef()
-{ 
+{
     if( GetLayerDefn()->GetGeomFieldCount() > 0 )
         return GetLayerDefn()->GetGeomFieldDefn(0)->GetSpatialRef();
     else
@@ -1153,7 +1156,7 @@ void OGR_L_SetSpatialFilter( OGRLayerH hLayer, OGRGeometryH hGeom )
 /*                      OGR_L_SetSpatialFilterEx()                      */
 /************************************************************************/
 
-void OGR_L_SetSpatialFilterEx( OGRLayerH hLayer, int iGeomField, 
+void OGR_L_SetSpatialFilterEx( OGRLayerH hLayer, int iGeomField,
                                OGRGeometryH hGeom )
 
 {
@@ -1170,7 +1173,7 @@ void OGR_L_SetSpatialFilterEx( OGRLayerH hLayer, int iGeomField,
 /*                        SetSpatialFilterRect()                        */
 /************************************************************************/
 
-void OGRLayer::SetSpatialFilterRect( double dfMinX, double dfMinY, 
+void OGRLayer::SetSpatialFilterRect( double dfMinX, double dfMinY,
                                      double dfMaxX, double dfMaxY )
 
 {
@@ -1178,8 +1181,8 @@ void OGRLayer::SetSpatialFilterRect( double dfMinX, double dfMinY,
 }
 
 
-void OGRLayer::SetSpatialFilterRect( int iGeomField, 
-                                     double dfMinX, double dfMinY, 
+void OGRLayer::SetSpatialFilterRect( int iGeomField,
+                                     double dfMinX, double dfMinY,
                                      double dfMaxX, double dfMaxY )
 
 {
@@ -1205,8 +1208,8 @@ void OGRLayer::SetSpatialFilterRect( int iGeomField,
 /*                     OGR_L_SetSpatialFilterRect()                     */
 /************************************************************************/
 
-void OGR_L_SetSpatialFilterRect( OGRLayerH hLayer, 
-                                 double dfMinX, double dfMinY, 
+void OGR_L_SetSpatialFilterRect( OGRLayerH hLayer,
+                                 double dfMinX, double dfMinY,
                                  double dfMaxX, double dfMaxY )
 
 {
@@ -1217,7 +1220,7 @@ void OGR_L_SetSpatialFilterRect( OGRLayerH hLayer,
         OGRAPISpy_L_SetSpatialFilterRect(hLayer, dfMinX, dfMinY, dfMaxX, dfMaxY);
 #endif
 
-    ((OGRLayer *) hLayer)->SetSpatialFilterRect( dfMinX, dfMinY, 
+    ((OGRLayer *) hLayer)->SetSpatialFilterRect( dfMinX, dfMinY,
                                                  dfMaxX, dfMaxY );
 }
 
@@ -1227,7 +1230,7 @@ void OGR_L_SetSpatialFilterRect( OGRLayerH hLayer,
 
 void OGR_L_SetSpatialFilterRectEx( OGRLayerH hLayer,
                                    int iGeomField,
-                                   double dfMinX, double dfMinY, 
+                                   double dfMinX, double dfMinY,
                                    double dfMaxX, double dfMaxY )
 
 {
@@ -1239,7 +1242,7 @@ void OGR_L_SetSpatialFilterRectEx( OGRLayerH hLayer,
 #endif
 
     ((OGRLayer *) hLayer)->SetSpatialFilterRect( iGeomField,
-                                                 dfMinX, dfMinY, 
+                                                 dfMinX, dfMinY,
                                                  dfMaxX, dfMaxY );
 }
 
@@ -1310,20 +1313,20 @@ int OGRLayer::InstallFilter( OGRGeometry * poFilter )
     if( poRing->getNumPoints() > 5 || poRing->getNumPoints() < 4 )
         return TRUE;
 
-    // If the ring has 5 points, the last should be the first. 
-    if( poRing->getNumPoints() == 5 
+    // If the ring has 5 points, the last should be the first.
+    if( poRing->getNumPoints() == 5
         && ( poRing->getX(0) != poRing->getX(4)
              || poRing->getY(0) != poRing->getY(4) ) )
         return TRUE;
 
-    // Polygon with first segment in "y" direction. 
+    // Polygon with first segment in "y" direction.
     if( poRing->getX(0) == poRing->getX(1)
         && poRing->getY(1) == poRing->getY(2)
         && poRing->getX(2) == poRing->getX(3)
         && poRing->getY(3) == poRing->getY(0) )
         m_bFilterIsEnvelope = TRUE;
 
-    // Polygon with first segment in "x" direction. 
+    // Polygon with first segment in "x" direction.
     if( poRing->getY(0) == poRing->getY(1)
         && poRing->getX(1) == poRing->getX(2)
         && poRing->getY(2) == poRing->getY(3)
@@ -1670,7 +1673,7 @@ OGRStyleTableH OGR_L_GetStyleTable( OGRLayerH hLayer )
 
 {
     VALIDATE_POINTER1( hLayer, "OGR_L_GetStyleTable", NULL );
-    
+
     return (OGRStyleTableH) ((OGRLayer *) hLayer)->GetStyleTable( );
 }
 
@@ -1683,7 +1686,7 @@ void OGR_L_SetStyleTableDirectly( OGRLayerH hLayer,
 
 {
     VALIDATE_POINTER0( hLayer, "OGR_L_SetStyleTableDirectly" );
-    
+
     ((OGRLayer *) hLayer)->SetStyleTableDirectly( (OGRStyleTable *) hStyleTable);
 }
 
@@ -1697,7 +1700,7 @@ void OGR_L_SetStyleTable( OGRLayerH hLayer,
 {
     VALIDATE_POINTER0( hLayer, "OGR_L_SetStyleTable" );
     VALIDATE_POINTER0( hStyleTable, "OGR_L_SetStyleTable" );
-    
+
     ((OGRLayer *) hLayer)->SetStyleTable( (OGRStyleTable *) hStyleTable);
 }
 
@@ -1783,7 +1786,7 @@ OGRErr OGRLayer::SetIgnoredFields( const char **papszFields )
         poDefn->GetGeomFieldDefn(iField)->SetIgnored( FALSE );
     }
     poDefn->SetStyleIgnored( FALSE );
-    
+
     if ( papszFields == NULL )
         return OGRERR_NONE;
 
@@ -1856,7 +1859,7 @@ OGRErr create_field_map(OGRFeatureDefn *poDefn, int **map)
     OGRErr ret = OGRERR_NONE;
     int n = poDefn->GetFieldCount();
     if (n > 0) {
-        *map = (int*)VSIMalloc(sizeof(int) * n);
+        *map = (int*)VSI_MALLOC_VERBOSE(sizeof(int) * n);
         if (!(*map)) return OGRERR_NOT_ENOUGH_MEMORY;
         for(int i=0;i<n;i++)
             (*map)[i] = -1;
@@ -1866,7 +1869,7 @@ OGRErr create_field_map(OGRFeatureDefn *poDefn, int **map)
 
 static
 OGRErr set_result_schema(OGRLayer *pLayerResult,
-                         OGRFeatureDefn *poDefnInput, 
+                         OGRFeatureDefn *poDefnInput,
                          OGRFeatureDefn *poDefnMethod,
                          int *mapInput,
                          int *mapMethod,
@@ -1877,7 +1880,7 @@ OGRErr set_result_schema(OGRLayer *pLayerResult,
     OGRFeatureDefn *poDefnResult = pLayerResult->GetLayerDefn();
     const char* pszInputPrefix = CSLFetchNameValue(papszOptions, "INPUT_PREFIX");
     const char* pszMethodPrefix = CSLFetchNameValue(papszOptions, "METHOD_PREFIX");
-    int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
+    int bSkipFailures = CPLTestBool(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
     if (poDefnResult->GetFieldCount() > 0) {
         // the user has defined the schema of the output layer
         for( int iField = 0; iField < poDefnInput->GetFieldCount(); iField++ ) {
@@ -1902,7 +1905,7 @@ OGRErr set_result_schema(OGRLayer *pLayerResult,
                 oFieldDefn.SetName(CPLSPrintf("%s%s", pszInputPrefix, oFieldDefn.GetNameRef()));
             ret = pLayerResult->CreateField(&oFieldDefn);
             if (ret != OGRERR_NONE) {
-                if (!bSkipFailures) 
+                if (!bSkipFailures)
                     return ret;
                 else {
                     CPLErrorReset();
@@ -1919,7 +1922,7 @@ OGRErr set_result_schema(OGRLayer *pLayerResult,
                 oFieldDefn.SetName(CPLSPrintf("%s%s", pszMethodPrefix, oFieldDefn.GetNameRef()));
             ret = pLayerResult->CreateField(&oFieldDefn);
             if (ret != OGRERR_NONE) {
-                if (!bSkipFailures) 
+                if (!bSkipFailures)
                     return ret;
                 else {
                     CPLErrorReset();
@@ -1940,8 +1943,11 @@ OGRGeometry *set_filter_from(OGRLayer *pLayer, OGRGeometry *pGeometryExistingFil
     if (pGeometryExistingFilter) {
         if (!geom->Intersects(pGeometryExistingFilter)) return NULL;
         OGRGeometry *intersection = geom->Intersection(pGeometryExistingFilter);
-        pLayer->SetSpatialFilter(intersection);
-        if (intersection) delete intersection;
+        if (intersection) {
+            pLayer->SetSpatialFilter(intersection);
+            delete intersection;
+        } else
+            return NULL;
     } else {
         pLayer->SetSpatialFilter(geom);
     }
@@ -1983,16 +1989,23 @@ static OGRGeometry* promote_to_multi(OGRGeometry* poGeom)
  * \note This method relies on GEOS support. Do not use unless the
  * GEOS support is compiled in.
  *
- * The recognized list of options is :
+ * The recognized list of options is:
  * <ul>
- * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
- *     feature could not be inserted.
- * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
+ * <li>SKIP_FAILURES=YES/NO. Set to YES to go on, even when a
+ *     feature could not be inserted or a GEOS call failed.
+ * <li>PROMOTE_TO_MULTI=YES/NO. Set to YES to convert Polygons
  *     into MultiPolygons, or LineStrings to MultiLineStrings.
  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
  *     will be created from the fields of the input layer.
  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
  *     will be created from the fields of the method layer.
+ * <li>USE_PREPARED_GEOMETRIES=YES/NO. Set to NO to not use prepared
+ *     geometries to pretest intersection of features of method layer
+ *     with features of this layer.
+ * <li>PRETEST_CONTAINMENT=YES/NO. Set to YES to pretest the
+ *     containment of features of method layer within the features of
+ *     this layer. This will speed up the method significantly in some
+ *     cases. Requires that the prepared geometries are in effect.
  * </ul>
  *
  * This method is the same as the C function OGR_L_Intersection().
@@ -2013,13 +2026,15 @@ static OGRGeometry* promote_to_multi(OGRGeometry* poGeom)
  * @return an error code if there was an error or the execution was
  * interrupted, OGRERR_NONE otherwise.
  *
+ * @note The first geometry field is always used.
+ *
  * @since OGR 1.10
  */
 
-OGRErr OGRLayer::Intersection( OGRLayer *pLayerMethod, 
-                               OGRLayer *pLayerResult, 
-                               char** papszOptions, 
-                               GDALProgressFunc pfnProgress, 
+OGRErr OGRLayer::Intersection( OGRLayer *pLayerMethod,
+                               OGRLayer *pLayerResult,
+                               char** papszOptions,
+                               GDALProgressFunc pfnProgress,
                                void * pProgressArg )
 {
     OGRErr ret = OGRERR_NONE;
@@ -2034,8 +2049,11 @@ OGRErr OGRLayer::Intersection( OGRLayer *pLayerMethod,
     double progress_max = (double) GetFeatureCount(0);
     double progress_counter = 0;
     double progress_ticker = 0;
-    int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
-    int bPromoteToMulti = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
+    int bSkipFailures = CPLTestBool(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
+    int bPromoteToMulti = CPLTestBool(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
+    int bUsePreparedGeometries = CPLTestBool(CSLFetchNameValueDef(papszOptions, "USE_PREPARED_GEOMETRIES", "YES"));
+    if (bUsePreparedGeometries) bUsePreparedGeometries = OGRHasPreparedGeometrySupport();
+    int bPretestContainment = CPLTestBool(CSLFetchNameValueDef(papszOptions, "PRETEST_CONTAINMENT", "NO"));
 
     // check for GEOS
     if (!OGRGeometryFactory::haveGEOS()) {
@@ -2076,7 +2094,7 @@ OGRErr OGRLayer::Intersection( OGRLayer *pLayerMethod,
             if (x_geom) {
                 OGREnvelope x_env;
                 x_geom->getEnvelope(&x_env);
-                if (x_env.MaxX < sEnvelopeMethod.MinX 
+                if (x_env.MaxX < sEnvelopeMethod.MinX
                     || x_env.MaxY < sEnvelopeMethod.MinY
                     || sEnvelopeMethod.MaxX < x_env.MinX
                     || sEnvelopeMethod.MaxY < x_env.MinY) {
@@ -2090,48 +2108,115 @@ OGRErr OGRLayer::Intersection( OGRLayer *pLayerMethod,
         }
 
         // set up the filter for method layer
+        CPLErrorReset();
         OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
+        if (CPLGetLastErrorType() != CE_None) {
+            if (!bSkipFailures) {
+                ret = OGRERR_FAILURE;
+                delete x;
+                goto done;
+            } else {
+                CPLErrorReset();
+                ret = OGRERR_NONE;
+            }
+        }
         if (!x_geom) {
             delete x;
             continue;
         }
 
+        OGRPreparedGeometry* x_prepared_geom = NULL;
+        if (bUsePreparedGeometries) {
+            x_prepared_geom = OGRCreatePreparedGeometry(x_geom);
+            if (!x_prepared_geom) {
+                delete x;
+                goto done;
+            }
+        }
+
         pLayerMethod->ResetReading();
         while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
             OGRGeometry *y_geom = y->GetGeometryRef();
             if (!y_geom) {delete y; continue;}
-            OGRGeometry* poIntersection = x_geom->Intersection(y_geom);
-            if( poIntersection == NULL || poIntersection->IsEmpty() ||
-                (x_geom->getDimension() == 2 &&
-                y_geom->getDimension() == 2 &&
-                poIntersection->getDimension() < 2) )
-            {
-                delete poIntersection;
-                delete y;
+            OGRGeometry *z_geom = NULL;
+
+            if (x_prepared_geom) {
+                CPLErrorReset();
+                ret = OGRERR_NONE;
+                if (bPretestContainment && OGRPreparedGeometryContains(x_prepared_geom, y_geom))
+                {
+                    if (CPLGetLastErrorType() == CE_None)
+                        z_geom = y_geom->clone();
+                }
+                else if (!(OGRPreparedGeometryIntersects(x_prepared_geom, y_geom)))
+                {
+                    if (CPLGetLastErrorType() == CE_None) {
+                        delete y;
+                        continue;
+                    }
+                }
+                if (CPLGetLastErrorType() != CE_None) {
+                    delete y;
+                    if (!bSkipFailures) {
+                        ret = OGRERR_FAILURE;
+                        OGRDestroyPreparedGeometry(x_prepared_geom);
+                        delete x;
+                        goto done;
+                    } else {
+                        CPLErrorReset();
+                        ret = OGRERR_NONE;
+                        continue;
+                    }
+                }
             }
-            else
-            {
-                OGRFeature *z = new OGRFeature(poDefnResult);
-                z->SetFieldsFrom(x, mapInput);
-                z->SetFieldsFrom(y, mapMethod);
-                if( bPromoteToMulti )
-                    poIntersection = promote_to_multi(poIntersection);
-                z->SetGeometryDirectly(poIntersection);
-                delete y;
-                ret = pLayerResult->CreateFeature(z);
-                delete z;
-                if (ret != OGRERR_NONE) {
+            if (!z_geom) {
+                CPLErrorReset();
+                z_geom = x_geom->Intersection(y_geom);
+                if (CPLGetLastErrorType() != CE_None || z_geom == NULL) {
+                    delete y;
                     if (!bSkipFailures) {
-                        delete x; 
+                        ret = OGRERR_FAILURE;
+                        OGRDestroyPreparedGeometry(x_prepared_geom);
+                        delete x;
                         goto done;
                     } else {
                         CPLErrorReset();
                         ret = OGRERR_NONE;
+                        continue;
                     }
                 }
+                if (z_geom->IsEmpty() ||
+                    (x_geom->getDimension() == 2 &&
+                     y_geom->getDimension() == 2 &&
+                     z_geom->getDimension() < 2))
+                {
+                    delete z_geom;
+                    delete y;
+                    continue;
+                }
+            }
+            OGRFeature *z = new OGRFeature(poDefnResult);
+            z->SetFieldsFrom(x, mapInput);
+            z->SetFieldsFrom(y, mapMethod);
+            if (bPromoteToMulti)
+                z_geom = promote_to_multi(z_geom);
+            z->SetGeometryDirectly(z_geom);
+            delete y;
+            ret = pLayerResult->CreateFeature(z);
+            delete z;
+            if (ret != OGRERR_NONE) {
+                if (!bSkipFailures) {
+                    OGRDestroyPreparedGeometry(x_prepared_geom);
+                    delete x;
+                    goto done;
+                } else {
+                    CPLErrorReset();
+                    ret = OGRERR_NONE;
+                }
             }
         }
 
+        OGRDestroyPreparedGeometry(x_prepared_geom);
         delete x;
     }
     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
@@ -2175,17 +2260,24 @@ done:
  * The recognized list of options is :
  * <ul>
  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
- *     feature could not be inserted.
+ *     feature could not be inserted or a GEOS call failed.
  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
  *     into MultiPolygons, or LineStrings to MultiLineStrings.
  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
  *     will be created from the fields of the input layer.
  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
  *     will be created from the fields of the method layer.
+ * <li>USE_PREPARED_GEOMETRIES=YES/NO. Set to NO to not use prepared
+ *     geometries to pretest intersection of features of method layer
+ *     with features of this layer.
+ * <li>PRETEST_CONTAINMENT=YES/NO. Set to YES to pretest the
+ *     containment of features of method layer within the features of
+ *     this layer. This will speed up the method significantly in some
+ *     cases. Requires that the prepared geometries are in effect.
  * </ul>
  *
  * This function is the same as the C++ method OGRLayer::Intersection().
- * 
+ *
  * @param pLayerInput the input layer. Should not be NULL.
  *
  * @param pLayerMethod the method layer. Should not be NULL.
@@ -2204,14 +2296,16 @@ done:
  * @return an error code if there was an error or the execution was
  * interrupted, OGRERR_NONE otherwise.
  *
+ * @note The first geometry field is always used.
+ *
  * @since OGR 1.10
  */
 
-OGRErr OGR_L_Intersection( OGRLayerH pLayerInput, 
-                           OGRLayerH pLayerMethod, 
-                           OGRLayerH pLayerResult, 
-                           char** papszOptions, 
-                           GDALProgressFunc pfnProgress, 
+OGRErr OGR_L_Intersection( OGRLayerH pLayerInput,
+                           OGRLayerH pLayerMethod,
+                           OGRLayerH pLayerResult,
+                           char** papszOptions,
+                           GDALProgressFunc pfnProgress,
                            void * pProgressArg )
 
 {
@@ -2252,17 +2346,20 @@ OGRErr OGR_L_Intersection( OGRLayerH pLayerInput,
  * The recognized list of options is :
  * <ul>
  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
- *     feature could not be inserted.
+ *     feature could not be inserted or a GEOS call failed.
  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
  *     into MultiPolygons, or LineStrings to MultiLineStrings.
  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
  *     will be created from the fields of the input layer.
  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
  *     will be created from the fields of the method layer.
+ * <li>USE_PREPARED_GEOMETRIES=YES/NO. Set to NO to not use prepared
+ *     geometries to pretest intersection of features of method layer
+ *     with features of this layer.
  * </ul>
  *
  * This method is the same as the C function OGR_L_Union().
- * 
+ *
  * @param pLayerMethod the method layer. Should not be NULL.
  *
  * @param pLayerResult the layer where the features resulting from the
@@ -2279,13 +2376,15 @@ OGRErr OGR_L_Intersection( OGRLayerH pLayerInput,
  * @return an error code if there was an error or the execution was
  * interrupted, OGRERR_NONE otherwise.
  *
+ * @note The first geometry field is always used.
+ *
  * @since OGR 1.10
  */
 
-OGRErr OGRLayer::Union( OGRLayer *pLayerMethod, 
-                        OGRLayer *pLayerResult, 
-                        char** papszOptions, 
-                        GDALProgressFunc pfnProgress, 
+OGRErr OGRLayer::Union( OGRLayer *pLayerMethod,
+                        OGRLayer *pLayerResult,
+                        char** papszOptions,
+                        GDALProgressFunc pfnProgress,
                         void * pProgressArg )
 {
     OGRErr ret = OGRERR_NONE;
@@ -2299,8 +2398,10 @@ OGRErr OGRLayer::Union( OGRLayer *pLayerMethod,
     double progress_max = (double) GetFeatureCount(0) + (double) pLayerMethod->GetFeatureCount(0);
     double progress_counter = 0;
     double progress_ticker = 0;
-    int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
-    int bPromoteToMulti = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
+    int bSkipFailures = CPLTestBool(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
+    int bPromoteToMulti = CPLTestBool(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
+    int bUsePreparedGeometries = CPLTestBool(CSLFetchNameValueDef(papszOptions, "USE_PREPARED_GEOMETRIES", "YES"));
+    if (bUsePreparedGeometries) bUsePreparedGeometries = OGRHasPreparedGeometrySupport();
 
     // check for GEOS
     if (!OGRGeometryFactory::haveGEOS()) {
@@ -2338,19 +2439,74 @@ OGRErr OGRLayer::Union( OGRLayer *pLayerMethod,
         }
 
         // set up the filter on method layer
+        CPLErrorReset();
         OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
+        if (CPLGetLastErrorType() != CE_None) {
+            if (!bSkipFailures) {
+                ret = OGRERR_FAILURE;
+                delete x;
+                goto done;
+            } else {
+                CPLErrorReset();
+                ret = OGRERR_NONE;
+            }
+        }
         if (!x_geom) {
-            delete x; 
+            delete x;
             continue;
         }
-        
+
+        OGRPreparedGeometry* x_prepared_geom = NULL;
+        if (bUsePreparedGeometries) {
+            x_prepared_geom = OGRCreatePreparedGeometry(x_geom);
+            if (!x_prepared_geom) {
+                delete x;
+                goto done;
+            }
+        }
+
         OGRGeometry *x_geom_diff = x_geom->clone(); // this will be the geometry of the result feature
         pLayerMethod->ResetReading();
         while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
             OGRGeometry *y_geom = y->GetGeometryRef();
             if (!y_geom) {delete y; continue;}
+
+            CPLErrorReset();
+            if (x_prepared_geom && !(OGRPreparedGeometryIntersects(x_prepared_geom, y_geom))) {
+                if (CPLGetLastErrorType() == CE_None) {
+                    delete y;
+                    continue;
+                }
+            }
+            if (CPLGetLastErrorType() != CE_None) {
+                if (!bSkipFailures) {
+                    ret = OGRERR_FAILURE;
+                    delete y;
+                    delete x;
+                    OGRDestroyPreparedGeometry(x_prepared_geom);
+                    goto done;
+                } else {
+                    CPLErrorReset();
+                    ret = OGRERR_NONE;
+                }
+            }
+
+            CPLErrorReset();
             OGRGeometry *poIntersection = x_geom->Intersection(y_geom);
-            if( poIntersection == NULL || poIntersection->IsEmpty() ||
+            if (CPLGetLastErrorType() != CE_None || poIntersection == NULL) {
+                delete y;
+                if (!bSkipFailures) {
+                    ret = OGRERR_FAILURE;
+                    delete x;
+                    OGRDestroyPreparedGeometry(x_prepared_geom);
+                    goto done;
+                } else {
+                    CPLErrorReset();
+                    ret = OGRERR_NONE;
+                    continue;
+                }
+            }
+            if( poIntersection->IsEmpty() ||
                 (x_geom->getDimension() == 2 &&
                 y_geom->getDimension() == 2 &&
                 poIntersection->getDimension() < 2) )
@@ -2366,9 +2522,28 @@ OGRErr OGRLayer::Union( OGRLayer *pLayerMethod,
                 if( bPromoteToMulti )
                     poIntersection = promote_to_multi(poIntersection);
                 z->SetGeometryDirectly(poIntersection);
-                OGRGeometry *x_geom_diff_new = x_geom_diff ? x_geom_diff->Difference(y_geom) : NULL;
-                if (x_geom_diff) delete x_geom_diff;
-                x_geom_diff = x_geom_diff_new;
+
+                if (x_geom_diff) {
+                    CPLErrorReset();
+                    OGRGeometry *x_geom_diff_new = x_geom_diff->Difference(y_geom);
+                    if (CPLGetLastErrorType() != CE_None || x_geom_diff_new == NULL) {
+                        if (!bSkipFailures) {
+                            ret = OGRERR_FAILURE;
+                            delete y;
+                            delete z;
+                            delete x;
+                            delete x_geom_diff;
+                            OGRDestroyPreparedGeometry(x_prepared_geom);
+                            goto done;
+                        } else {
+                            CPLErrorReset();
+                        }
+                    } else {
+                        delete x_geom_diff;
+                        x_geom_diff = x_geom_diff_new;
+                    }
+                }
+
                 delete y;
                 ret = pLayerResult->CreateFeature(z);
                 delete z;
@@ -2377,6 +2552,7 @@ OGRErr OGRLayer::Union( OGRLayer *pLayerMethod,
                         delete x;
                         if (x_geom_diff)
                             delete x_geom_diff;
+                        OGRDestroyPreparedGeometry(x_prepared_geom);
                         goto done;
                     } else {
                         CPLErrorReset();
@@ -2386,6 +2562,8 @@ OGRErr OGRLayer::Union( OGRLayer *pLayerMethod,
             }
         }
 
+        OGRDestroyPreparedGeometry(x_prepared_geom);
+
         if( x_geom_diff == NULL || x_geom_diff->IsEmpty() )
         {
             delete x_geom_diff;
@@ -2431,20 +2609,48 @@ OGRErr OGRLayer::Union( OGRLayer *pLayerMethod,
         }
 
         // set up the filter on input layer
+        CPLErrorReset();
         OGRGeometry *x_geom = set_filter_from(this, pGeometryInputFilter, x);
+        if (CPLGetLastErrorType() != CE_None) {
+            if (!bSkipFailures) {
+                ret = OGRERR_FAILURE;
+                delete x;
+                goto done;
+            } else {
+                CPLErrorReset();
+                ret = OGRERR_NONE;
+            }
+        }
         if (!x_geom) {
-            delete x; 
+            delete x;
             continue;
         }
-        
+
         OGRGeometry *x_geom_diff = x_geom->clone(); // this will be the geometry of the result feature
         ResetReading();
         while (OGRFeature *y = GetNextFeature()) {
             OGRGeometry *y_geom = y->GetGeometryRef();
             if (!y_geom) {delete y; continue;}
-            OGRGeometry *x_geom_diff_new = x_geom_diff ? x_geom_diff->Difference(y_geom) : NULL;
-            if (x_geom_diff) delete x_geom_diff;
-            x_geom_diff = x_geom_diff_new;
+            
+            if (x_geom_diff) {
+                CPLErrorReset();
+                OGRGeometry *x_geom_diff_new = x_geom_diff->Difference(y_geom);
+                if (CPLGetLastErrorType() != CE_None || x_geom_diff_new == NULL) {
+                    if (!bSkipFailures) {
+                        ret = OGRERR_FAILURE;
+                        delete x;
+                        delete y;
+                        delete x_geom_diff;
+                        goto done;
+                    } else {
+                        CPLErrorReset();
+                        ret = OGRERR_NONE;
+                    }
+                } else {
+                    delete x_geom_diff;
+                    x_geom_diff = x_geom_diff_new;
+                }
+            }
             delete y;
         }
 
@@ -2519,17 +2725,20 @@ done:
  * The recognized list of options is :
  * <ul>
  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
- *     feature could not be inserted.
+ *     feature could not be inserted or a GEOS call failed.
  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
  *     into MultiPolygons, or LineStrings to MultiLineStrings.
  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
  *     will be created from the fields of the input layer.
  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
  *     will be created from the fields of the method layer.
+ * <li>USE_PREPARED_GEOMETRIES=YES/NO. Set to NO to not use prepared
+ *     geometries to pretest intersection of features of method layer
+ *     with features of this layer.
  * </ul>
  *
  * This function is the same as the C++ method OGRLayer::Union().
- * 
+ *
  * @param pLayerInput the input layer. Should not be NULL.
  *
  * @param pLayerMethod the method layer. Should not be NULL.
@@ -2548,14 +2757,16 @@ done:
  * @return an error code if there was an error or the execution was
  * interrupted, OGRERR_NONE otherwise.
  *
- * @since OGR 1.10 
+ * @note The first geometry field is always used.
+ *
+ * @since OGR 1.10
  */
 
-OGRErr OGR_L_Union( OGRLayerH pLayerInput, 
-                    OGRLayerH pLayerMethod, 
-                    OGRLayerH pLayerResult, 
-                    char** papszOptions, 
-                    GDALProgressFunc pfnProgress, 
+OGRErr OGR_L_Union( OGRLayerH pLayerInput,
+                    OGRLayerH pLayerMethod,
+                    OGRLayerH pLayerResult,
+                    char** papszOptions,
+                    GDALProgressFunc pfnProgress,
                     void * pProgressArg )
 
 {
@@ -2596,7 +2807,7 @@ OGRErr OGR_L_Union( OGRLayerH pLayerInput,
  * The recognized list of options is :
  * <ul>
  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
- *     feature could not be inserted.
+ *     feature could not be inserted or a GEOS call failed.
  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
  *     into MultiPolygons, or LineStrings to MultiLineStrings.
  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
@@ -2606,7 +2817,7 @@ OGRErr OGR_L_Union( OGRLayerH pLayerInput,
  * </ul>
  *
  * This method is the same as the C function OGR_L_SymDifference().
- * 
+ *
  * @param pLayerMethod the method layer. Should not be NULL.
  *
  * @param pLayerResult the layer where the features resulting from the
@@ -2623,13 +2834,15 @@ OGRErr OGR_L_Union( OGRLayerH pLayerInput,
  * @return an error code if there was an error or the execution was
  * interrupted, OGRERR_NONE otherwise.
  *
+ * @note The first geometry field is always used.
+ *
  * @since OGR 1.10
  */
 
-OGRErr OGRLayer::SymDifference( OGRLayer *pLayerMethod, 
-                                OGRLayer *pLayerResult, 
-                                char** papszOptions, 
-                                GDALProgressFunc pfnProgress, 
+OGRErr OGRLayer::SymDifference( OGRLayer *pLayerMethod,
+                                OGRLayer *pLayerResult,
+                                char** papszOptions,
+                                GDALProgressFunc pfnProgress,
                                 void * pProgressArg )
 {
     OGRErr ret = OGRERR_NONE;
@@ -2643,8 +2856,8 @@ OGRErr OGRLayer::SymDifference( OGRLayer *pLayerMethod,
     double progress_max = (double) GetFeatureCount(0) + (double) pLayerMethod->GetFeatureCount(0);
     double progress_counter = 0;
     double progress_ticker = 0;
-    int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
-    int bPromoteToMulti = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
+    int bSkipFailures = CPLTestBool(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
+    int bPromoteToMulti = CPLTestBool(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
 
     // check for GEOS
     if (!OGRGeometryFactory::haveGEOS()) {
@@ -2682,20 +2895,47 @@ OGRErr OGRLayer::SymDifference( OGRLayer *pLayerMethod,
         }
 
         // set up the filter on method layer
+        CPLErrorReset();
         OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
+        if (CPLGetLastErrorType() != CE_None) {
+            if (!bSkipFailures) {
+                ret = OGRERR_FAILURE;
+                delete x;
+                goto done;
+            } else {
+                CPLErrorReset();
+                ret = OGRERR_NONE;
+            }
+        }
         if (!x_geom) {
-            delete x; 
+            delete x;
             continue;
         }
-        
+
         OGRGeometry *geom = x_geom->clone(); // this will be the geometry of the result feature
         pLayerMethod->ResetReading();
         while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
             OGRGeometry *y_geom = y->GetGeometryRef();
             if (!y_geom) {delete y; continue;}
-            OGRGeometry *geom_new = geom ? geom->Difference(y_geom) : NULL;
-            if (geom) delete geom;
-            geom = geom_new;
+            if (geom) {
+                CPLErrorReset();
+                OGRGeometry *geom_new = geom->Difference(y_geom);
+                if (CPLGetLastErrorType() != CE_None || geom_new == NULL) {
+                    if (!bSkipFailures) {
+                        ret = OGRERR_FAILURE;
+                        delete geom;
+                        delete y;
+                        delete x;
+                        goto done;
+                    } else {
+                        CPLErrorReset();
+                        ret = OGRERR_NONE;
+                    }
+                } else {
+                    delete geom;
+                    geom = geom_new;
+                }
+            }
             delete y;
             if (geom && geom->IsEmpty()) break;
         }
@@ -2744,20 +2984,47 @@ OGRErr OGRLayer::SymDifference( OGRLayer *pLayerMethod,
         }
 
         // set up the filter on input layer
+        CPLErrorReset();
         OGRGeometry *x_geom = set_filter_from(this, pGeometryInputFilter, x);
+        if (CPLGetLastErrorType() != CE_None) {
+            if (!bSkipFailures) {
+                ret = OGRERR_FAILURE;
+                delete x;
+                goto done;
+            } else {
+                CPLErrorReset();
+                ret = OGRERR_NONE;
+            }
+        }
         if (!x_geom) {
-            delete x; 
+            delete x;
             continue;
         }
-        
+
         OGRGeometry *geom = x_geom->clone(); // this will be the geometry of the result feature
         ResetReading();
         while (OGRFeature *y = GetNextFeature()) {
             OGRGeometry *y_geom = y->GetGeometryRef();
             if (!y_geom) {delete y; continue;}
-            OGRGeometry *geom_new = geom ? geom->Difference(y_geom) : NULL;
-            if (geom) delete geom;
-            geom = geom_new;
+            if (geom) {
+                CPLErrorReset();
+                OGRGeometry *geom_new = geom->Difference(y_geom);
+                if (CPLGetLastErrorType() != CE_None || geom_new == NULL) {
+                    if (!bSkipFailures) {
+                        ret = OGRERR_FAILURE;
+                        delete geom;
+                        delete y;
+                        delete x;
+                        goto done;
+                    } else {
+                        CPLErrorReset();
+                        ret = OGRERR_NONE;
+                    }
+                } else {
+                    delete geom;
+                    geom = geom_new;
+                }
+            }
             delete y;
             if (geom == NULL || geom->IsEmpty()) break;
         }
@@ -2832,7 +3099,7 @@ done:
  * The recognized list of options is :
  * <ul>
  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
- *     feature could not be inserted.
+ *     feature could not be inserted or a GEOS call failed.
  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
  *     into MultiPolygons, or LineStrings to MultiLineStrings.
  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
@@ -2861,14 +3128,16 @@ done:
  * @return an error code if there was an error or the execution was
  * interrupted, OGRERR_NONE otherwise.
  *
+ * @note The first geometry field is always used.
+ *
  * @since OGR 1.10
  */
 
-OGRErr OGR_L_SymDifference( OGRLayerH pLayerInput, 
-                            OGRLayerH pLayerMethod, 
-                            OGRLayerH pLayerResult, 
-                            char** papszOptions, 
-                            GDALProgressFunc pfnProgress, 
+OGRErr OGR_L_SymDifference( OGRLayerH pLayerInput,
+                            OGRLayerH pLayerMethod,
+                            OGRLayerH pLayerResult,
+                            char** papszOptions,
+                            GDALProgressFunc pfnProgress,
                             void * pProgressArg )
 
 {
@@ -2907,17 +3176,20 @@ OGRErr OGR_L_SymDifference( OGRLayerH pLayerInput,
  * The recognized list of options is :
  * <ul>
  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
- *     feature could not be inserted.
+ *     feature could not be inserted or a GEOS call failed.
  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
  *     into MultiPolygons, or LineStrings to MultiLineStrings.
  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
  *     will be created from the fields of the input layer.
  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
  *     will be created from the fields of the method layer.
+ * <li>USE_PREPARED_GEOMETRIES=YES/NO. Set to NO to not use prepared
+ *     geometries to pretest intersection of features of method layer
+ *     with features of this layer.
  * </ul>
  *
  * This method is the same as the C function OGR_L_Identity().
- * 
+ *
  * @param pLayerMethod the method layer. Should not be NULL.
  *
  * @param pLayerResult the layer where the features resulting from the
@@ -2934,13 +3206,15 @@ OGRErr OGR_L_SymDifference( OGRLayerH pLayerInput,
  * @return an error code if there was an error or the execution was
  * interrupted, OGRERR_NONE otherwise.
  *
+ * @note The first geometry field is always used.
+ *
  * @since OGR 1.10
  */
 
-OGRErr OGRLayer::Identity( OGRLayer *pLayerMethod, 
-                           OGRLayer *pLayerResult, 
-                           char** papszOptions, 
-                           GDALProgressFunc pfnProgress, 
+OGRErr OGRLayer::Identity( OGRLayer *pLayerMethod,
+                           OGRLayer *pLayerResult,
+                           char** papszOptions,
+                           GDALProgressFunc pfnProgress,
                            void * pProgressArg )
 {
     OGRErr ret = OGRERR_NONE;
@@ -2953,8 +3227,10 @@ OGRErr OGRLayer::Identity( OGRLayer *pLayerMethod,
     double progress_max = (double) GetFeatureCount(0);
     double progress_counter = 0;
     double progress_ticker = 0;
-    int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
-    int bPromoteToMulti = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
+    int bSkipFailures = CPLTestBool(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
+    int bPromoteToMulti = CPLTestBool(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
+    int bUsePreparedGeometries = CPLTestBool(CSLFetchNameValueDef(papszOptions, "USE_PREPARED_GEOMETRIES", "YES"));
+    if (bUsePreparedGeometries) bUsePreparedGeometries = OGRHasPreparedGeometrySupport();
 
     // check for GEOS
     if (!OGRGeometryFactory::haveGEOS()) {
@@ -2990,19 +3266,74 @@ OGRErr OGRLayer::Identity( OGRLayer *pLayerMethod,
         }
 
         // set up the filter on method layer
+        CPLErrorReset();
         OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
+        if (CPLGetLastErrorType() != CE_None) {
+            if (!bSkipFailures) {
+                ret = OGRERR_FAILURE;
+                delete x;
+                goto done;
+            } else {
+                CPLErrorReset();
+                ret = OGRERR_NONE;
+            }
+        }
         if (!x_geom) {
-            delete x; 
+            delete x;
             continue;
         }
-        
+
+        OGRPreparedGeometry* x_prepared_geom = NULL;
+        if (bUsePreparedGeometries) {
+            x_prepared_geom = OGRCreatePreparedGeometry(x_geom);
+            if (!x_prepared_geom) {
+                delete x;
+                goto done;
+            }
+        }
+
         OGRGeometry *x_geom_diff = x_geom->clone(); // this will be the geometry of the result feature
         pLayerMethod->ResetReading();
         while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
             OGRGeometry *y_geom = y->GetGeometryRef();
             if (!y_geom) {delete y; continue;}
+
+            CPLErrorReset();
+            if (x_prepared_geom && !(OGRPreparedGeometryIntersects(x_prepared_geom, y_geom))) {
+                if (CPLGetLastErrorType() == CE_None) {
+                    delete y;
+                    continue;
+                }
+            }
+            if (CPLGetLastErrorType() != CE_None) {
+                if (!bSkipFailures) {
+                    ret = OGRERR_FAILURE;
+                    delete x;
+                    delete x_geom_diff;
+                    OGRDestroyPreparedGeometry(x_prepared_geom);
+                    goto done;
+                } else {
+                    CPLErrorReset();
+                    ret = OGRERR_NONE;
+                }
+            }
+
+            CPLErrorReset();
             OGRGeometry* poIntersection = x_geom->Intersection(y_geom);
-            if( poIntersection == NULL || poIntersection->IsEmpty() ||
+            if (CPLGetLastErrorType() != CE_None || poIntersection == NULL) {
+                delete y;
+                if (!bSkipFailures) {
+                    ret = OGRERR_FAILURE;
+                    delete x;
+                    delete x_geom_diff;
+                    OGRDestroyPreparedGeometry(x_prepared_geom);
+                    goto done;
+                } else {
+                    CPLErrorReset();
+                    ret = OGRERR_NONE;
+                }
+            }
+            else if( poIntersection->IsEmpty() ||
                 (x_geom->getDimension() == 2 &&
                 y_geom->getDimension() == 2 &&
                 poIntersection->getDimension() < 2) )
@@ -3018,9 +3349,26 @@ OGRErr OGRLayer::Identity( OGRLayer *pLayerMethod,
                 if( bPromoteToMulti )
                     poIntersection = promote_to_multi(poIntersection);
                 z->SetGeometryDirectly(poIntersection);
-                OGRGeometry *x_geom_diff_new = x_geom_diff ? x_geom_diff->Difference(y_geom) : NULL;
-                if (x_geom_diff) delete x_geom_diff;
-                x_geom_diff = x_geom_diff_new;
+                if (x_geom_diff) {
+                    CPLErrorReset();
+                    OGRGeometry *x_geom_diff_new = x_geom_diff->Difference(y_geom);
+                    if (CPLGetLastErrorType() != CE_None || x_geom_diff_new == NULL) {
+                        if (!bSkipFailures) {
+                            ret = OGRERR_FAILURE;
+                            delete z;
+                            delete y;
+                            delete x;
+                            delete x_geom_diff;
+                            OGRDestroyPreparedGeometry(x_prepared_geom);
+                            goto done;
+                        } else {
+                            CPLErrorReset();
+                        }
+                    } else {
+                        delete x_geom_diff;
+                        x_geom_diff = x_geom_diff_new;
+                    }
+                }
                 delete y;
                 ret = pLayerResult->CreateFeature(z);
                 delete z;
@@ -3028,6 +3376,7 @@ OGRErr OGRLayer::Identity( OGRLayer *pLayerMethod,
                     if (!bSkipFailures) {
                         delete x;
                         delete x_geom_diff;
+                        OGRDestroyPreparedGeometry(x_prepared_geom);
                         goto done;
                     } else {
                         CPLErrorReset();
@@ -3037,6 +3386,8 @@ OGRErr OGRLayer::Identity( OGRLayer *pLayerMethod,
             }
         }
 
+        OGRDestroyPreparedGeometry(x_prepared_geom);
+
         if( x_geom_diff == NULL || x_geom_diff->IsEmpty() )
         {
             delete x_geom_diff;
@@ -3104,17 +3455,20 @@ done:
  * The recognized list of options is :
  * <ul>
  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
- *     feature could not be inserted.
+ *     feature could not be inserted or a GEOS call failed.
  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
  *     into MultiPolygons, or LineStrings to MultiLineStrings.
  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
  *     will be created from the fields of the input layer.
  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
  *     will be created from the fields of the method layer.
+ * <li>USE_PREPARED_GEOMETRIES=YES/NO. Set to NO to not use prepared
+ *     geometries to pretest intersection of features of method layer
+ *     with features of this layer.
  * </ul>
  *
  * This function is the same as the C++ method OGRLayer::Identity().
- * 
+ *
  * @param pLayerInput the input layer. Should not be NULL.
  *
  * @param pLayerMethod the method layer. Should not be NULL.
@@ -3133,14 +3487,16 @@ done:
  * @return an error code if there was an error or the execution was
  * interrupted, OGRERR_NONE otherwise.
  *
+ * @note The first geometry field is always used.
+ *
  * @since OGR 1.10
  */
 
-OGRErr OGR_L_Identity( OGRLayerH pLayerInput, 
-                       OGRLayerH pLayerMethod, 
-                       OGRLayerH pLayerResult, 
-                       char** papszOptions, 
-                       GDALProgressFunc pfnProgress, 
+OGRErr OGR_L_Identity( OGRLayerH pLayerInput,
+                       OGRLayerH pLayerMethod,
+                       OGRLayerH pLayerResult,
+                       char** papszOptions,
+                       GDALProgressFunc pfnProgress,
                        void * pProgressArg )
 
 {
@@ -3181,7 +3537,7 @@ OGRErr OGR_L_Identity( OGRLayerH pLayerInput,
  * The recognized list of options is :
  * <ul>
  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
- *     feature could not be inserted.
+ *     feature could not be inserted or a GEOS call failed.
  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
  *     into MultiPolygons, or LineStrings to MultiLineStrings.
  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
@@ -3191,7 +3547,7 @@ OGRErr OGR_L_Identity( OGRLayerH pLayerInput,
  * </ul>
  *
  * This method is the same as the C function OGR_L_Update().
- * 
+ *
  * @param pLayerMethod the method layer. Should not be NULL.
  *
  * @param pLayerResult the layer where the features resulting from the
@@ -3208,13 +3564,15 @@ OGRErr OGR_L_Identity( OGRLayerH pLayerInput,
  * @return an error code if there was an error or the execution was
  * interrupted, OGRERR_NONE otherwise.
  *
+ * @note The first geometry field is always used.
+ *
  * @since OGR 1.10
  */
 
-OGRErr OGRLayer::Update( OGRLayer *pLayerMethod, 
-                         OGRLayer *pLayerResult, 
-                         char** papszOptions, 
-                         GDALProgressFunc pfnProgress, 
+OGRErr OGRLayer::Update( OGRLayer *pLayerMethod,
+                         OGRLayer *pLayerResult,
+                         char** papszOptions,
+                         GDALProgressFunc pfnProgress,
                          void * pProgressArg )
 {
     OGRErr ret = OGRERR_NONE;
@@ -3227,8 +3585,8 @@ OGRErr OGRLayer::Update( OGRLayer *pLayerMethod,
     double progress_max = (double) GetFeatureCount(0) + (double) pLayerMethod->GetFeatureCount(0);
     double progress_counter = 0;
     double progress_ticker = 0;
-    int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
-    int bPromoteToMulti = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
+    int bSkipFailures = CPLTestBool(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
+    int bPromoteToMulti = CPLTestBool(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
 
     // check for GEOS
     if (!OGRGeometryFactory::haveGEOS()) {
@@ -3264,20 +3622,47 @@ OGRErr OGRLayer::Update( OGRLayer *pLayerMethod,
         }
 
         // set up the filter on method layer
+        CPLErrorReset();
         OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
+        if (CPLGetLastErrorType() != CE_None) {
+            if (!bSkipFailures) {
+                ret = OGRERR_FAILURE;
+                delete x;
+                goto done;
+            } else {
+                CPLErrorReset();
+                ret = OGRERR_NONE;
+            }
+        }
         if (!x_geom) {
-            delete x; 
+            delete x;
             continue;
         }
-        
+
         OGRGeometry *x_geom_diff = x_geom->clone(); //this will be the geometry of a result feature
         pLayerMethod->ResetReading();
         while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
             OGRGeometry *y_geom = y->GetGeometryRef();
             if (!y_geom) {delete y; continue;}
-            OGRGeometry *x_geom_diff_new = x_geom_diff ? x_geom_diff->Difference(y_geom) : NULL;
-            if (x_geom_diff) delete x_geom_diff;
-            x_geom_diff = x_geom_diff_new;
+            if (x_geom_diff) {
+                CPLErrorReset();
+                OGRGeometry *x_geom_diff_new = x_geom_diff->Difference(y_geom);
+                if (CPLGetLastErrorType() != CE_None || x_geom_diff_new == NULL) {
+                    if (!bSkipFailures) {
+                        ret = OGRERR_FAILURE;
+                        delete y;
+                        delete x;
+                        delete x_geom_diff;
+                        goto done;
+                    } else {
+                        CPLErrorReset();
+                        ret = OGRERR_NONE;
+                    }
+                } else {
+                    delete x_geom_diff;
+                    x_geom_diff = x_geom_diff_new;
+                }
+            }
             delete y;
         }
 
@@ -3386,7 +3771,7 @@ done:
  * The recognized list of options is :
  * <ul>
  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
- *     feature could not be inserted.
+ *     feature could not be inserted or a GEOS call failed.
  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
  *     into MultiPolygons, or LineStrings to MultiLineStrings.
  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
@@ -3396,7 +3781,7 @@ done:
  * </ul>
  *
  * This function is the same as the C++ method OGRLayer::Update().
- * 
+ *
  * @param pLayerInput the input layer. Should not be NULL.
  *
  * @param pLayerMethod the method layer. Should not be NULL.
@@ -3415,14 +3800,16 @@ done:
  * @return an error code if there was an error or the execution was
  * interrupted, OGRERR_NONE otherwise.
  *
+ * @note The first geometry field is always used.
+ *
  * @since OGR 1.10
  */
 
-OGRErr OGR_L_Update( OGRLayerH pLayerInput, 
-                     OGRLayerH pLayerMethod, 
-                     OGRLayerH pLayerResult, 
-                     char** papszOptions, 
-                     GDALProgressFunc pfnProgress, 
+OGRErr OGR_L_Update( OGRLayerH pLayerInput,
+                     OGRLayerH pLayerMethod,
+                     OGRLayerH pLayerResult,
+                     char** papszOptions,
+                     GDALProgressFunc pfnProgress,
                      void * pProgressArg )
 
 {
@@ -3456,7 +3843,7 @@ OGRErr OGR_L_Update( OGRLayerH pLayerInput,
  * The recognized list of options is :
  * <ul>
  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
- *     feature could not be inserted.
+ *     feature could not be inserted or a GEOS call failed.
  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
  *     into MultiPolygons, or LineStrings to MultiLineStrings.
  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
@@ -3466,7 +3853,7 @@ OGRErr OGR_L_Update( OGRLayerH pLayerInput,
  * </ul>
  *
  * This method is the same as the C function OGR_L_Clip().
- * 
+ *
  * @param pLayerMethod the method layer. Should not be NULL.
  *
  * @param pLayerResult the layer where the features resulting from the
@@ -3483,13 +3870,15 @@ OGRErr OGR_L_Update( OGRLayerH pLayerInput,
  * @return an error code if there was an error or the execution was
  * interrupted, OGRERR_NONE otherwise.
  *
+ * @note The first geometry field is always used.
+ *
  * @since OGR 1.10
  */
 
-OGRErr OGRLayer::Clip( OGRLayer *pLayerMethod, 
-                       OGRLayer *pLayerResult, 
-                       char** papszOptions, 
-                       GDALProgressFunc pfnProgress, 
+OGRErr OGRLayer::Clip( OGRLayer *pLayerMethod,
+                       OGRLayer *pLayerResult,
+                       char** papszOptions,
+                       GDALProgressFunc pfnProgress,
                        void * pProgressArg )
 {
     OGRErr ret = OGRERR_NONE;
@@ -3500,8 +3889,8 @@ OGRErr OGRLayer::Clip( OGRLayer *pLayerMethod,
     double progress_max = (double) GetFeatureCount(0);
     double progress_counter = 0;
     double progress_ticker = 0;
-    int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
-    int bPromoteToMulti = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
+    int bSkipFailures = CPLTestBool(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
+    int bPromoteToMulti = CPLTestBool(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
 
     // check for GEOS
     if (!OGRGeometryFactory::haveGEOS()) {
@@ -3514,7 +3903,7 @@ OGRErr OGRLayer::Clip( OGRLayer *pLayerMethod,
     if (ret != OGRERR_NONE) goto done;
     ret = set_result_schema(pLayerResult, poDefnInput, NULL, mapInput, NULL, 0, papszOptions);
     if (ret != OGRERR_NONE) goto done;
-    
+
     poDefnResult = pLayerResult->GetLayerDefn();
     ResetReading();
     while (OGRFeature *x = GetNextFeature()) {
@@ -3533,13 +3922,24 @@ OGRErr OGRLayer::Clip( OGRLayer *pLayerMethod,
         }
 
         // set up the filter on method layer
+        CPLErrorReset();
         OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
+        if (CPLGetLastErrorType() != CE_None) {
+            if (!bSkipFailures) {
+                ret = OGRERR_FAILURE;
+                delete x;
+                goto done;
+            } else {
+                CPLErrorReset();
+                ret = OGRERR_NONE;
+            }
+        }
         if (!x_geom) {
-            delete x; 
+            delete x;
             continue;
         }
-        
-        OGRGeometry *geom = NULL; // this will be the geometry of the result feature 
+
+        OGRGeometry *geom = NULL; // this will be the geometry of the result feature
         pLayerMethod->ResetReading();
         // incrementally add area from y to geom
         while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
@@ -3548,43 +3948,65 @@ OGRErr OGRLayer::Clip( OGRLayer *pLayerMethod,
             if (!geom) {
                 geom = y_geom->clone();
             } else {
+                CPLErrorReset();
                 OGRGeometry *geom_new = geom->Union(y_geom);
-                delete geom;
-                geom = geom_new;
+                if (CPLGetLastErrorType() != CE_None || geom_new == NULL) {
+                    if (!bSkipFailures) {
+                        ret = OGRERR_FAILURE;
+                        delete y;
+                        delete x;
+                        delete geom;
+                        goto done;
+                    } else {
+                        CPLErrorReset();
+                        ret = OGRERR_NONE;
+                    }
+                } else {
+                    delete geom;
+                    geom = geom_new;
+                }
             }
             delete y;
         }
 
         // possibly add a new feature with area x intersection sum of y
-        OGRFeature *z = NULL;
         if (geom) {
+            CPLErrorReset();
             OGRGeometry* poIntersection = x_geom->Intersection(geom);
-            if( poIntersection != NULL && !poIntersection->IsEmpty() )
+            if (CPLGetLastErrorType() != CE_None || poIntersection == NULL) {
+                if (!bSkipFailures) {
+                    ret = OGRERR_FAILURE;
+                    delete geom;
+                    delete x;
+                    goto done;
+                } else {
+                    CPLErrorReset();
+                    ret = OGRERR_NONE;
+                }
+            }
+            else if( !poIntersection->IsEmpty() )
             {
-                z = new OGRFeature(poDefnResult);
+                OGRFeature *z = new OGRFeature(poDefnResult);
                 z->SetFieldsFrom(x, mapInput);
                 if( bPromoteToMulti )
                     poIntersection = promote_to_multi(poIntersection);
                 z->SetGeometryDirectly(poIntersection);
+                ret = pLayerResult->CreateFeature(z);
+                delete z;
+                if (ret != OGRERR_NONE) {
+                    if (!bSkipFailures) {
+                        goto done;
+                    } else {
+                        CPLErrorReset();
+                        ret = OGRERR_NONE;
+                    }
+                }
             }
             else
                 delete poIntersection;
             delete geom;
         }
         delete x;
-        if (z) {
-            if (z->GetGeometryRef() != NULL && !z->GetGeometryRef()->IsEmpty())
-                ret = pLayerResult->CreateFeature(z);
-            delete z;
-            if (ret != OGRERR_NONE) {
-                if (!bSkipFailures) {
-                    goto done;
-                } else {
-                    CPLErrorReset();
-                    ret = OGRERR_NONE;
-                }
-            }
-        }
     }
     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
       CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
@@ -3622,7 +4044,7 @@ done:
  * The recognized list of options is :
  * <ul>
  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
- *     feature could not be inserted.
+ *     feature could not be inserted or a GEOS call failed.
  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
  *     into MultiPolygons, or LineStrings to MultiLineStrings.
  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
@@ -3632,7 +4054,7 @@ done:
  * </ul>
  *
  * This function is the same as the C++ method OGRLayer::Clip().
- * 
+ *
  * @param pLayerInput the input layer. Should not be NULL.
  *
  * @param pLayerMethod the method layer. Should not be NULL.
@@ -3651,14 +4073,16 @@ done:
  * @return an error code if there was an error or the execution was
  * interrupted, OGRERR_NONE otherwise.
  *
+ * @note The first geometry field is always used.
+ *
  * @since OGR 1.10
  */
 
-OGRErr OGR_L_Clip( OGRLayerH pLayerInput, 
-                   OGRLayerH pLayerMethod, 
-                   OGRLayerH pLayerResult, 
-                   char** papszOptions, 
-                   GDALProgressFunc pfnProgress, 
+OGRErr OGR_L_Clip( OGRLayerH pLayerInput,
+                   OGRLayerH pLayerMethod,
+                   OGRLayerH pLayerResult,
+                   char** papszOptions,
+                   GDALProgressFunc pfnProgress,
                    void * pProgressArg )
 
 {
@@ -3692,7 +4116,7 @@ OGRErr OGR_L_Clip( OGRLayerH pLayerInput,
  * The recognized list of options is :
  * <ul>
  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
- *     feature could not be inserted.
+ *     feature could not be inserted or a GEOS call failed.
  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
  *     into MultiPolygons, or LineStrings to MultiLineStrings.
  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
@@ -3719,13 +4143,15 @@ OGRErr OGR_L_Clip( OGRLayerH pLayerInput,
  * @return an error code if there was an error or the execution was
  * interrupted, OGRERR_NONE otherwise.
  *
+ * @note The first geometry field is always used.
+ *
  * @since OGR 1.10
  */
 
-OGRErr OGRLayer::Erase( OGRLayer *pLayerMethod, 
-                        OGRLayer *pLayerResult, 
-                        char** papszOptions, 
-                        GDALProgressFunc pfnProgress, 
+OGRErr OGRLayer::Erase( OGRLayer *pLayerMethod,
+                        OGRLayer *pLayerResult,
+                        char** papszOptions,
+                        GDALProgressFunc pfnProgress,
                         void * pProgressArg )
 {
     OGRErr ret = OGRERR_NONE;
@@ -3736,8 +4162,8 @@ OGRErr OGRLayer::Erase( OGRLayer *pLayerMethod,
     double progress_max = (double) GetFeatureCount(0);
     double progress_counter = 0;
     double progress_ticker = 0;
-    int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
-    int bPromoteToMulti = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
+    int bSkipFailures = CPLTestBool(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
+    int bPromoteToMulti = CPLTestBool(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
 
     // check for GEOS
     if (!OGRGeometryFactory::haveGEOS()) {
@@ -3770,60 +4196,62 @@ OGRErr OGRLayer::Erase( OGRLayer *pLayerMethod,
         }
 
         // set up the filter on the method layer
+        CPLErrorReset();
         OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
+        if (CPLGetLastErrorType() != CE_None) {
+            if (!bSkipFailures) {
+                ret = OGRERR_FAILURE;
+                delete x;
+                goto done;
+            } else {
+                CPLErrorReset();
+                ret = OGRERR_NONE;
+            }
+        }
         if (!x_geom) {
-            delete x; 
+            delete x;
             continue;
         }
 
-        OGRGeometry *geom = NULL; // this will be the geometry of the result feature
+        OGRGeometry *geom = x_geom->clone(); // this will be the geometry of the result feature
         pLayerMethod->ResetReading();
-        // incrementally add area from y to geom
+        // incrementally erase y from geom
         while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
             OGRGeometry *y_geom = y->GetGeometryRef();
             if (!y_geom) {delete y; continue;}
-            if (!geom) {
-                geom = y_geom->clone();
+            CPLErrorReset();
+            OGRGeometry *geom_new = geom->Difference(y_geom);
+            if (CPLGetLastErrorType() != CE_None || geom_new == NULL) {
+                if (!bSkipFailures) {
+                    ret = OGRERR_FAILURE;
+                    delete x;
+                    delete y;
+                    goto done;
+                } else {
+                    CPLErrorReset();
+                    ret = OGRERR_NONE;
+                }
             } else {
-                OGRGeometry *geom_new = geom->Union(y_geom);
                 delete geom;
                 geom = geom_new;
+                if (geom->IsEmpty())
+                    break;
             }
             delete y;
         }
 
-        // possibly add a new feature with area x minus sum of y
-        OGRFeature *z = NULL;
-        if (geom) {
-            OGRGeometry* x_geom_diff = x_geom->Difference(geom);
-            if( x_geom_diff != NULL && !x_geom_diff->IsEmpty() )
-            {
-                z = new OGRFeature(poDefnResult);
-                z->SetFieldsFrom(x, mapInput);
-                if( bPromoteToMulti )
-                    x_geom_diff = promote_to_multi(x_geom_diff);
-                z->SetGeometryDirectly(x_geom_diff);
-            }
-            else
-                delete x_geom_diff;
-            delete geom;
-        }
-        else
-        {
-            z = new OGRFeature(poDefnResult);
+        // add a new feature if there is remaining area
+        if (!geom->IsEmpty()) {
+            OGRFeature *z = new OGRFeature(poDefnResult);
             z->SetFieldsFrom(x, mapInput);
-            OGRGeometry* x_geom_diff = x_geom->clone();
             if( bPromoteToMulti )
-                x_geom_diff = promote_to_multi(x_geom_diff);
-            z->SetGeometryDirectly(x_geom_diff);
-        }
-        delete x;
-        if (z) {
-            if (z->GetGeometryRef() != NULL && !z->GetGeometryRef()->IsEmpty())
-                ret = pLayerResult->CreateFeature(z);
+                geom = promote_to_multi(geom);
+            z->SetGeometryDirectly(geom);
+            ret = pLayerResult->CreateFeature(z);
             delete z;
             if (ret != OGRERR_NONE) {
                 if (!bSkipFailures) {
+                    delete x;
                     goto done;
                 } else {
                     CPLErrorReset();
@@ -3831,6 +4259,7 @@ OGRErr OGRLayer::Erase( OGRLayer *pLayerMethod,
                 }
             }
         }
+        delete x;
     }
     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
       CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
@@ -3868,7 +4297,7 @@ done:
  * The recognized list of options is :
  * <ul>
  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
- *     feature could not be inserted.
+ *     feature could not be inserted or a GEOS call failed.
  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
  *     into MultiPolygons, or LineStrings to MultiLineStrings.
  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
@@ -3878,7 +4307,7 @@ done:
  * </ul>
  *
  * This function is the same as the C++ method OGRLayer::Erase().
- * 
+ *
  * @param pLayerInput the input layer. Should not be NULL.
  *
  * @param pLayerMethod the method layer. Should not be NULL.
@@ -3897,14 +4326,16 @@ done:
  * @return an error code if there was an error or the execution was
  * interrupted, OGRERR_NONE otherwise.
  *
+ * @note The first geometry field is always used.
+ *
  * @since OGR 1.10
  */
 
-OGRErr OGR_L_Erase( OGRLayerH pLayerInput, 
-                    OGRLayerH pLayerMethod, 
-                    OGRLayerH pLayerResult, 
-                    char** papszOptions, 
-                    GDALProgressFunc pfnProgress, 
+OGRErr OGR_L_Erase( OGRLayerH pLayerInput,
+                    OGRLayerH pLayerMethod,
+                    OGRLayerH pLayerResult,
+                    char** papszOptions,
+                    GDALProgressFunc pfnProgress,
                     void * pProgressArg )
 
 {
diff --git a/ogr/ogrsf_frmts/generic/ogrlayerdecorator.cpp b/ogr/ogrsf_frmts/generic/ogrlayerdecorator.cpp
index b697b32..298124a 100644
--- a/ogr/ogrsf_frmts/generic/ogrlayerdecorator.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrlayerdecorator.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrlayerdecorator.cpp 28601 2015-03-03 11:06:40Z rouault $
+ * $Id: ogrlayerdecorator.cpp 32467 2015-12-26 10:54:09Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRLayerDecorator class
@@ -29,15 +29,15 @@
 
 #include "ogrlayerdecorator.h"
 
-CPL_CVSID("$Id: ogrlayerdecorator.cpp 28601 2015-03-03 11:06:40Z rouault $");
+CPL_CVSID("$Id: ogrlayerdecorator.cpp 32467 2015-12-26 10:54:09Z rouault $");
 
 OGRLayerDecorator::OGRLayerDecorator(OGRLayer* poDecoratedLayer,
                                      int bTakeOwnership) :
                                         m_poDecoratedLayer(poDecoratedLayer),
                                         m_bHasOwnership(bTakeOwnership)
 {
-    SetDescription( poDecoratedLayer->GetDescription() );
     CPLAssert(poDecoratedLayer != NULL);
+    SetDescription( poDecoratedLayer->GetDescription() );
 }
 
 OGRLayerDecorator::~OGRLayerDecorator()
@@ -194,10 +194,17 @@ OGRErr      OGRLayerDecorator::ReorderFields( int* panMap )
     return m_poDecoratedLayer->ReorderFields(panMap);
 }
 
-OGRErr      OGRLayerDecorator::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags )
+OGRErr      OGRLayerDecorator::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlagsIn )
+{
+    if( !m_poDecoratedLayer ) return OGRERR_FAILURE;
+    return m_poDecoratedLayer->AlterFieldDefn(iField, poNewFieldDefn, nFlagsIn);
+}
+
+OGRErr      OGRLayerDecorator::CreateGeomField( OGRGeomFieldDefn *poField,
+                                            int bApproxOK )
 {
     if( !m_poDecoratedLayer ) return OGRERR_FAILURE;
-    return m_poDecoratedLayer->AlterFieldDefn(iField, poNewFieldDefn, nFlags);
+    return m_poDecoratedLayer->CreateGeomField(poField, bApproxOK);
 }
 
 OGRErr      OGRLayerDecorator::SyncToDisk()
diff --git a/ogr/ogrsf_frmts/generic/ogrlayerdecorator.h b/ogr/ogrsf_frmts/generic/ogrlayerdecorator.h
index 535bfcd..34abc10 100644
--- a/ogr/ogrsf_frmts/generic/ogrlayerdecorator.h
+++ b/ogr/ogrsf_frmts/generic/ogrlayerdecorator.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrlayerdecorator.h 28601 2015-03-03 11:06:40Z rouault $
+ * $Id: ogrlayerdecorator.h 32467 2015-12-26 10:54:09Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines OGRLayerDecorator class
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGRLAYERDECORATOR_H_INCLUDED
-#define _OGRLAYERDECORATOR_H_INCLUDED
+#ifndef OGRLAYERDECORATOR_H_INCLUDED
+#define OGRLAYERDECORATOR_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 
@@ -80,6 +80,9 @@ class CPL_DLL OGRLayerDecorator : public OGRLayer
     virtual OGRErr      ReorderFields( int* panMap );
     virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags );
 
+    virtual OGRErr      CreateGeomField( OGRGeomFieldDefn *poField,
+                                         int bApproxOK = TRUE );
+
     virtual OGRErr      SyncToDisk();
 
     virtual OGRStyleTable *GetStyleTable();
@@ -108,4 +111,4 @@ class CPL_DLL OGRLayerDecorator : public OGRLayer
     OGRLayer* GetBaseLayer()    { return m_poDecoratedLayer; }
 };
 
-#endif // _OGRLAYERDECORATOR_H_INCLUDED
+#endif // OGRLAYERDECORATOR_H_INCLUDED
diff --git a/ogr/ogrsf_frmts/generic/ogrlayerpool.cpp b/ogr/ogrsf_frmts/generic/ogrlayerpool.cpp
index 8dd789b..1418ad5 100644
--- a/ogr/ogrsf_frmts/generic/ogrlayerpool.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrlayerpool.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrlayerpool.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrlayerpool.cpp 31925 2015-12-01 15:02:41Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines OGRLayerPool and OGRProxiedLayer class
@@ -29,18 +29,18 @@
 
 #include "ogrlayerpool.h"
 
-CPL_CVSID("$Id: ogrlayerpool.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrlayerpool.cpp 31925 2015-12-01 15:02:41Z rouault $");
 
 /************************************************************************/
 /*                      OGRAbstractProxiedLayer()                       */
 /************************************************************************/
 
-OGRAbstractProxiedLayer::OGRAbstractProxiedLayer(OGRLayerPool* poPool)
+OGRAbstractProxiedLayer::OGRAbstractProxiedLayer(OGRLayerPool* poPoolIn) :
+    poPrevLayer(NULL),
+    poNextLayer(NULL)
 {
-    CPLAssert(poPool != NULL);
-    this->poPool = poPool;
-    poPrevLayer = NULL;
-    poNextLayer = NULL;
+    CPLAssert(poPoolIn != NULL);
+    poPool = poPoolIn;
 }
 
 /************************************************************************/
@@ -59,12 +59,12 @@ OGRAbstractProxiedLayer::~OGRAbstractProxiedLayer()
 /*                            OGRLayerPool()                            */
 /************************************************************************/
 
-OGRLayerPool::OGRLayerPool(int nMaxSimultaneouslyOpened)
+OGRLayerPool::OGRLayerPool(int nMaxSimultaneouslyOpenedIn) :
+    poMRULayer(NULL),
+    poLRULayer(NULL),
+    nMRUListSize(0)
 {
-    poMRULayer = NULL;
-    poLRULayer = NULL;
-    nMRUListSize = 0;
-    this->nMaxSimultaneouslyOpened = nMaxSimultaneouslyOpened;
+    nMaxSimultaneouslyOpened = nMaxSimultaneouslyOpenedIn;
 }
 
 /************************************************************************/
@@ -154,16 +154,16 @@ void OGRLayerPool::UnchainLayer(OGRAbstractProxiedLayer* poLayer)
 /*                          OGRProxiedLayer()                           */
 /************************************************************************/
 
-OGRProxiedLayer::OGRProxiedLayer(OGRLayerPool* poPool,
-                                 OpenLayerFunc pfnOpenLayer,
-                                 FreeUserDataFunc pfnFreeUserData,
-                                 void* pUserData) : OGRAbstractProxiedLayer(poPool)
+OGRProxiedLayer::OGRProxiedLayer(OGRLayerPool* poPoolIn,
+                                 OpenLayerFunc pfnOpenLayerIn,
+                                 FreeUserDataFunc pfnFreeUserDataIn,
+                                 void* pUserDataIn) : OGRAbstractProxiedLayer(poPoolIn)
 {
-    CPLAssert(pfnOpenLayer != NULL);
+    CPLAssert(pfnOpenLayerIn != NULL);
 
-    this->pfnOpenLayer = pfnOpenLayer;
-    this->pfnFreeUserData = pfnFreeUserData;
-    this->pUserData = pUserData;
+    pfnOpenLayer = pfnOpenLayerIn;
+    pfnFreeUserData = pfnFreeUserDataIn;
+    pUserData = pUserDataIn;
     poUnderlyingLayer = NULL;
     poFeatureDefn = NULL;
     poSRS = NULL;
@@ -223,7 +223,12 @@ void OGRProxiedLayer::CloseUnderlyingLayer()
 OGRLayer* OGRProxiedLayer::GetUnderlyingLayer()
 {
     if( poUnderlyingLayer == NULL )
+    {
+        //  If the open fails, poUnderlyingLayer will still be a nullptr
+        // and the user will be warned by the open call.
+        // coverity[check_return]
         OpenUnderlyingLayer();
+    }
     return poUnderlyingLayer;
 }
 
@@ -472,10 +477,10 @@ OGRErr      OGRProxiedLayer::ReorderFields( int* panMap )
 /*                           AlterFieldDefn()                           */
 /************************************************************************/
 
-OGRErr      OGRProxiedLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags )
+OGRErr      OGRProxiedLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlagsIn )
 {
     if( poUnderlyingLayer == NULL && !OpenUnderlyingLayer() ) return OGRERR_FAILURE;
-    return poUnderlyingLayer->AlterFieldDefn(iField, poNewFieldDefn, nFlags);
+    return poUnderlyingLayer->AlterFieldDefn(iField, poNewFieldDefn, nFlagsIn);
 }
 
 /************************************************************************/
@@ -577,4 +582,3 @@ OGRErr      OGRProxiedLayer::SetIgnoredFields( const char **papszFields )
     if( poUnderlyingLayer == NULL && !OpenUnderlyingLayer() ) return OGRERR_FAILURE;
     return poUnderlyingLayer->SetIgnoredFields(papszFields);
 }
-
diff --git a/ogr/ogrsf_frmts/generic/ogrlayerpool.h b/ogr/ogrsf_frmts/generic/ogrlayerpool.h
index c6e013f..c2472a0 100644
--- a/ogr/ogrsf_frmts/generic/ogrlayerpool.h
+++ b/ogr/ogrsf_frmts/generic/ogrlayerpool.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrlayerpool.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrlayerpool.h 32177 2015-12-14 07:25:30Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines OGRLayerPool and OGRProxiedLayer class
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGRLAYERPOOL_H_INCLUDED
-#define _OGRLAYERPOOL_H_INCLUDED
+#ifndef OGRLAYERPOOL_H_INCLUDED
+#define OGRLAYERPOOL_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 
@@ -107,7 +107,7 @@ class OGRProxiedLayer : public OGRAbstractProxiedLayer
                                         FreeUserDataFunc pfnFreeUserData,
                                         void* pUserData);
     virtual            ~OGRProxiedLayer();
-    
+
     OGRLayer           *GetUnderlyingLayer();
 
     virtual OGRGeometry *GetSpatialFilter();
@@ -159,4 +159,4 @@ class OGRProxiedLayer : public OGRAbstractProxiedLayer
     virtual OGRErr      SetIgnoredFields( const char **papszFields );
 };
 
-#endif // _OGRLAYERPOOL_H_INCLUDED
+#endif // OGRLAYERPOOL_H_INCLUDED
diff --git a/ogr/ogrsf_frmts/generic/ogrmutexeddatasource.cpp b/ogr/ogrsf_frmts/generic/ogrmutexeddatasource.cpp
index f186424..80b573b 100644
--- a/ogr/ogrsf_frmts/generic/ogrmutexeddatasource.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrmutexeddatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmutexeddatasource.cpp 28602 2015-03-03 11:16:35Z rouault $
+ * $Id: ogrmutexeddatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMutexedDataSource class
@@ -30,7 +30,7 @@
 #include "ogrmutexeddatasource.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: ogrmutexeddatasource.cpp 28602 2015-03-03 11:16:35Z rouault $");
+CPL_CVSID("$Id: ogrmutexeddatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 OGRMutexedDataSource::OGRMutexedDataSource(OGRDataSource* poBaseDataSource,
                                            int bTakeOwnership,
@@ -74,10 +74,10 @@ OGRLayer* OGRMutexedDataSource::WrapLayerIfNecessary(OGRLayer* poLayer)
             poLayer = poWrappedLayer;
         else
         {
-            OGRMutexedLayer* poWrappedLayer = new OGRMutexedLayer(poLayer, FALSE, m_hGlobalMutex);
-            m_oMapLayers[poLayer] = poWrappedLayer;
-            m_oReverseMapLayers[poWrappedLayer] = poLayer;
-            poLayer = poWrappedLayer;
+            OGRMutexedLayer* poMutexedLayer = new OGRMutexedLayer(poLayer, FALSE, m_hGlobalMutex);
+            m_oMapLayers[poLayer] = poMutexedLayer;
+            m_oReverseMapLayers[poMutexedLayer] = poLayer;
+            poLayer = poMutexedLayer;
         }
     }
     return poLayer;
@@ -119,7 +119,7 @@ int         OGRMutexedDataSource::TestCapability( const char * pszCap )
     return m_poBaseDataSource->TestCapability(pszCap);
 }
 
-OGRLayer   *OGRMutexedDataSource::ICreateLayer( const char *pszName, 
+OGRLayer   *OGRMutexedDataSource::ICreateLayer( const char *pszName,
                                      OGRSpatialReference *poSpatialRef,
                                      OGRwkbGeometryType eGType,
                                      char ** papszOptions)
@@ -128,8 +128,8 @@ OGRLayer   *OGRMutexedDataSource::ICreateLayer( const char *pszName,
     return WrapLayerIfNecessary(m_poBaseDataSource->CreateLayer(pszName, poSpatialRef, eGType, papszOptions));
 }
 
-OGRLayer   *OGRMutexedDataSource::CopyLayer( OGRLayer *poSrcLayer, 
-                                   const char *pszNewName, 
+OGRLayer   *OGRMutexedDataSource::CopyLayer( OGRLayer *poSrcLayer,
+                                   const char *pszNewName,
                                    char **papszOptions )
 {
     CPLMutexHolderOptionalLockD(m_hGlobalMutex);
diff --git a/ogr/ogrsf_frmts/generic/ogrmutexeddatasource.h b/ogr/ogrsf_frmts/generic/ogrmutexeddatasource.h
index e3ab8e0..0f2e93a 100644
--- a/ogr/ogrsf_frmts/generic/ogrmutexeddatasource.h
+++ b/ogr/ogrsf_frmts/generic/ogrmutexeddatasource.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmutexeddatasource.h 28601 2015-03-03 11:06:40Z rouault $
+ * $Id: ogrmutexeddatasource.h 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines OGRLMutexedDataSource class
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGRMUTEXEDDATASOURCELAYER_H_INCLUDED
-#define _OGRMUTEXEDDATASOURCELAYER_H_INCLUDED
+#ifndef OGRMUTEXEDDATASOURCELAYER_H_INCLUDED
+#define OGRMUTEXEDDATASOURCELAYER_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "cpl_multiproc.h"
@@ -39,8 +39,8 @@
  *  with a mutex.
  *  If the passed mutex is NULL, then no locking will be done.
  *
- *  Note that the constructors and destructors are not explictely protected
- *  by the mutex*
+ *  Note that the constructors and destructors are not explicitly protected
+ *  by the mutex.
  */
 class CPL_DLL OGRMutexedDataSource : public OGRDataSource
 {
@@ -51,7 +51,7 @@ class CPL_DLL OGRMutexedDataSource : public OGRDataSource
     int            m_bWrapLayersInMutexedLayer;
     std::map<OGRLayer*, OGRMutexedLayer* > m_oMapLayers;
     std::map<OGRMutexedLayer*, OGRLayer* > m_oReverseMapLayers;
-    
+
     OGRLayer*           WrapLayerIfNecessary(OGRLayer* poLayer);
 
   public:
@@ -64,7 +64,7 @@ class CPL_DLL OGRMutexedDataSource : public OGRDataSource
 
     /* The destruction of the object isn't protected by the mutex */
     virtual     ~OGRMutexedDataSource();
-    
+
     OGRDataSource*      GetBaseDataSource() { return m_poBaseDataSource; }
 
     virtual const char  *GetName();
@@ -76,24 +76,24 @@ class CPL_DLL OGRMutexedDataSource : public OGRDataSource
 
     virtual int         TestCapability( const char * );
 
-    virtual OGRLayer   *ICreateLayer( const char *pszName, 
+    virtual OGRLayer   *ICreateLayer( const char *pszName,
                                      OGRSpatialReference *poSpatialRef = NULL,
                                      OGRwkbGeometryType eGType = wkbUnknown,
                                      char ** papszOptions = NULL );
-    virtual OGRLayer   *CopyLayer( OGRLayer *poSrcLayer, 
-                                   const char *pszNewName, 
+    virtual OGRLayer   *CopyLayer( OGRLayer *poSrcLayer,
+                                   const char *pszNewName,
                                    char **papszOptions = NULL );
 
     virtual OGRStyleTable *GetStyleTable();
     virtual void        SetStyleTableDirectly( OGRStyleTable *poStyleTable );
-                            
+
     virtual void        SetStyleTable(OGRStyleTable *poStyleTable);
 
     virtual OGRLayer *  ExecuteSQL( const char *pszStatement,
                                     OGRGeometry *poSpatialFilter,
                                     const char *pszDialect );
     virtual void        ReleaseResultSet( OGRLayer * poResultsSet );
-    
+
     virtual void        FlushCache();
 
     virtual OGRErr      StartTransaction(int bForce=FALSE);
@@ -110,4 +110,4 @@ class CPL_DLL OGRMutexedDataSource : public OGRDataSource
                                          const char * pszDomain = "" );
 };
 
-#endif // _OGRMUTEXEDDATASOURCELAYER_H_INCLUDED
+#endif // OGRMUTEXEDDATASOURCELAYER_H_INCLUDED
diff --git a/ogr/ogrsf_frmts/generic/ogrmutexedlayer.cpp b/ogr/ogrsf_frmts/generic/ogrmutexedlayer.cpp
index a127ce2..88055fa 100644
--- a/ogr/ogrsf_frmts/generic/ogrmutexedlayer.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrmutexedlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmutexedlayer.cpp 28601 2015-03-03 11:06:40Z rouault $
+ * $Id: ogrmutexedlayer.cpp 31705 2015-11-21 22:57:18Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMutexedLayer class
@@ -30,7 +30,7 @@
 #include "ogrmutexedlayer.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: ogrmutexedlayer.cpp 28601 2015-03-03 11:06:40Z rouault $");
+CPL_CVSID("$Id: ogrmutexedlayer.cpp 31705 2015-11-21 22:57:18Z rouault $");
 
 OGRMutexedLayer::OGRMutexedLayer(OGRLayer* poDecoratedLayer,
                                  int bTakeOwnership,
@@ -192,10 +192,10 @@ OGRErr      OGRMutexedLayer::ReorderFields( int* panMap )
     return OGRLayerDecorator::ReorderFields(panMap);
 }
 
-OGRErr      OGRMutexedLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags )
+OGRErr      OGRMutexedLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlagsIn )
 {
     CPLMutexHolderOptionalLockD(m_hMutex);
-    return OGRLayerDecorator::AlterFieldDefn(iField, poNewFieldDefn, nFlags);
+    return OGRLayerDecorator::AlterFieldDefn(iField, poNewFieldDefn, nFlagsIn);
 }
 
 OGRErr      OGRMutexedLayer::SyncToDisk()
diff --git a/ogr/ogrsf_frmts/generic/ogrmutexedlayer.h b/ogr/ogrsf_frmts/generic/ogrmutexedlayer.h
index 451e817..a294100 100644
--- a/ogr/ogrsf_frmts/generic/ogrmutexedlayer.h
+++ b/ogr/ogrsf_frmts/generic/ogrmutexedlayer.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmutexedlayer.h 28601 2015-03-03 11:06:40Z rouault $
+ * $Id: ogrmutexedlayer.h 31812 2015-11-28 22:37:37Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines OGRLMutexedLayer class
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGRMUTEXEDLAYER_H_INCLUDED
-#define _OGRMUTEXEDLAYER_H_INCLUDED
+#ifndef OGRMUTEXEDLAYER_H_INCLUDED
+#define OGRMUTEXEDLAYER_H_INCLUDED
 
 #include "ogrlayerdecorator.h"
 #include "cpl_multiproc.h"
@@ -37,7 +37,7 @@
  *
  *  If the passed mutex is NULL, then no locking will be done.
  *
- *  Note that the constructors and destructors are not explictely protected
+ *  Note that the constructors and destructors are not explicitly protected
  *  by the mutex.
  */
 class CPL_DLL OGRMutexedLayer : public OGRLayerDecorator
@@ -117,4 +117,4 @@ class CPL_DLL OGRMutexedLayer : public OGRLayerDecorator
                                          const char * pszDomain = "" );
 };
 
-#endif // _OGRMUTEXEDLAYER_H_INCLUDED
+#endif // OGRMUTEXEDLAYER_H_INCLUDED
diff --git a/ogr/ogrsf_frmts/generic/ogrregisterall.cpp b/ogr/ogrsf_frmts/generic/ogrregisterall.cpp
index e61cd1b..f97f8a0 100644
--- a/ogr/ogrsf_frmts/generic/ogrregisterall.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrregisterall.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrregisterall.cpp 29028 2015-04-26 21:19:29Z rouault $
+ * $Id: ogrregisterall.cpp 32427 2015-12-22 11:18:32Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Function to register all known OGR drivers.
@@ -30,7 +30,7 @@
 
 #include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: ogrregisterall.cpp 29028 2015-04-26 21:19:29Z rouault $");
+CPL_CVSID("$Id: ogrregisterall.cpp 32427 2015-12-22 11:18:32Z rouault $");
 
 /************************************************************************/
 /*                           OGRRegisterAll()                           */
@@ -43,7 +43,9 @@ void OGRRegisterAll()
 
 void OGRRegisterAllInternal()
 {
-
+#ifdef DB2_ENABLED
+    RegisterOGRDB2();
+#endif
 #ifdef SHAPE_ENABLED
     RegisterOGRShape();
 #endif
@@ -127,7 +129,7 @@ void OGRRegisterAllInternal()
 #endif
 #ifdef MSSQLSPATIAL_ENABLED
     RegisterOGRMSSQLSpatial();
-#endif 
+#endif
 #ifdef OGDI_ENABLED
     RegisterOGROGDI();
 #endif
@@ -205,8 +207,8 @@ void OGRRegisterAllInternal()
 #ifdef WFS_ENABLED
     RegisterOGRWFS();
 #endif
-#ifdef SOSI_ENABLED 
-    RegisterOGRSOSI(); 
+#ifdef SOSI_ENABLED
+    RegisterOGRSOSI();
 #endif
 #ifdef HTF_ENABLED
     RegisterOGRHTF();
@@ -223,9 +225,6 @@ void OGRRegisterAllInternal()
 #ifdef GFT_ENABLED
     RegisterOGRGFT();
 #endif
-#ifdef GME_ENABLED
-    RegisterOGRGME();
-#endif
 #ifdef SVG_ENABLED
     RegisterOGRSVG();
 #endif
@@ -265,6 +264,9 @@ void OGRRegisterAllInternal()
 #ifdef CARTODB_ENABLED
     RegisterOGRCartoDB();
 #endif
+#ifdef AMIGOCLOUD_ENABLED
+    RegisterOGRAmigoCloud();
+#endif
 #ifdef SXF_ENABLED
     RegisterOGRSXF();
 #endif
@@ -280,6 +282,12 @@ void OGRRegisterAllInternal()
 #ifdef CSW_ENABLED
     RegisterOGRCSW();
 #endif
+#ifdef MONGODB_ENABLED
+    RegisterOGRMongoDB();
+#endif
+#ifdef VDV_ENABLED
+    RegisterOGRVDV();
+#endif
 
 /* Put TIGER and AVCBIN at end since they need poOpenInfo->GetSiblingFiles() */
 #ifdef TIGER_ENABLED
diff --git a/ogr/ogrsf_frmts/generic/ogrsfdriver.cpp b/ogr/ogrsf_frmts/generic/ogrsfdriver.cpp
index 5d3275f..d8702b4 100644
--- a/ogr/ogrsf_frmts/generic/ogrsfdriver.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrsfdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsfdriver.cpp 27698 2014-09-20 11:59:07Z rouault $
+ * $Id: ogrsfdriver.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The generic portions of the OGRSFDriver class.
@@ -33,7 +33,7 @@
 #include "ogr_p.h"
 #include "ograpispy.h"
 
-CPL_CVSID("$Id: ogrsfdriver.cpp 27698 2014-09-20 11:59:07Z rouault $");
+CPL_CVSID("$Id: ogrsfdriver.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                            ~OGRSFDriver()                            */
@@ -53,7 +53,7 @@ OGRDataSource *OGRSFDriver::CreateDataSource( const char *, char ** )
 {
     CPLError( CE_Failure, CPLE_NotSupported,
               "CreateDataSource() not supported by this driver.\n" );
-              
+
     return NULL;
 }
 
@@ -62,7 +62,7 @@ OGRDataSource *OGRSFDriver::CreateDataSource( const char *, char ** )
 /************************************************************************/
 
 OGRDataSourceH OGR_Dr_CreateDataSource( OGRSFDriverH hDriver,
-                                        const char *pszName, 
+                                        const char *pszName,
                                         char ** papszOptions )
 
 {
@@ -93,7 +93,7 @@ OGRErr OGRSFDriver::DeleteDataSource( const char *pszDataSource )
     (void) pszDataSource;
     CPLError( CE_Failure, CPLE_NotSupported,
               "DeleteDataSource() not supported by this driver." );
-              
+
     return OGRERR_UNSUPPORTED_OPERATION;
 }
 
@@ -101,7 +101,7 @@ OGRErr OGRSFDriver::DeleteDataSource( const char *pszDataSource )
 /*                      OGR_Dr_DeleteDataSource()                       */
 /************************************************************************/
 
-OGRErr OGR_Dr_DeleteDataSource( OGRSFDriverH hDriver, 
+OGRErr OGR_Dr_DeleteDataSource( OGRSFDriverH hDriver,
                                 const char *pszDataSource )
 
 {
@@ -112,7 +112,11 @@ OGRErr OGR_Dr_DeleteDataSource( OGRSFDriverH hDriver,
     OGRAPISpyDeleteDataSource(hDriver, pszDataSource);
 #endif
 
-    return ((GDALDriver *) hDriver)->Delete( pszDataSource );
+    CPLErr eErr = ((GDALDriver *) hDriver)->Delete( pszDataSource );
+    if( eErr == CE_None )
+        return OGRERR_NONE;
+    else
+        return OGRERR_FAILURE;
 }
 
 /************************************************************************/
@@ -131,7 +135,7 @@ const char *OGR_Dr_GetName( OGRSFDriverH hDriver )
 /*                            OGR_Dr_Open()                             */
 /************************************************************************/
 
-OGRDataSourceH OGR_Dr_Open( OGRSFDriverH hDriver, const char *pszName, 
+OGRDataSourceH OGR_Dr_Open( OGRSFDriverH hDriver, const char *pszName,
                             int bUpdate )
 
 {
@@ -185,11 +189,11 @@ int OGR_Dr_TestCapability( OGRSFDriverH hDriver, const char *pszCap )
 /*                       OGR_Dr_CopyDataSource()                        */
 /************************************************************************/
 
-OGRDataSourceH OGR_Dr_CopyDataSource( OGRSFDriverH hDriver, 
-                                      OGRDataSourceH hSrcDS, 
+OGRDataSourceH OGR_Dr_CopyDataSource( OGRSFDriverH hDriver,
+                                      OGRDataSourceH hSrcDS,
                                       const char *pszNewName,
                                       char **papszOptions )
-                                      
+
 {
     VALIDATE_POINTER1( hDriver, "OGR_Dr_CopyDataSource", NULL );
     VALIDATE_POINTER1( hSrcDS, "OGR_Dr_CopyDataSource", NULL );
@@ -198,7 +202,7 @@ OGRDataSourceH OGR_Dr_CopyDataSource( OGRSFDriverH hDriver,
     GDALDriver* poDriver = (GDALDriver*)hDriver;
     if( !poDriver->GetMetadataItem( GDAL_DCAP_CREATE ) )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "%s driver does not support data source creation.",
                   poDriver->GetDescription() );
         return NULL;
@@ -221,10 +225,9 @@ OGRDataSourceH OGR_Dr_CopyDataSource( OGRSFDriverH hDriver,
         if( poLayer == NULL )
             continue;
 
-        poODS->CopyLayer( poLayer, poLayer->GetLayerDefn()->GetName(), 
+        poODS->CopyLayer( poLayer, poLayer->GetLayerDefn()->GetName(),
                           papszOptions );
     }
 
     return (OGRDataSourceH)poODS;
 }
-
diff --git a/ogr/ogrsf_frmts/generic/ogrsfdriverregistrar.cpp b/ogr/ogrsf_frmts/generic/ogrsfdriverregistrar.cpp
index 7173a24..f47d006 100644
--- a/ogr/ogrsf_frmts/generic/ogrsfdriverregistrar.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrsfdriverregistrar.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsfdriverregistrar.cpp 28806 2015-03-28 14:37:47Z rouault $
+ * $Id: ogrsfdriverregistrar.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRSFDriverRegistrar class implementation.
@@ -32,7 +32,7 @@
 #include "ogr_api.h"
 #include "ograpispy.h"
 
-CPL_CVSID("$Id: ogrsfdriverregistrar.cpp 28806 2015-03-28 14:37:47Z rouault $");
+CPL_CVSID("$Id: ogrsfdriverregistrar.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                         OGRSFDriverRegistrar                         */
@@ -41,15 +41,12 @@ CPL_CVSID("$Id: ogrsfdriverregistrar.cpp 28806 2015-03-28 14:37:47Z rouault $");
 /**
  * \brief Constructor
  *
- * Normally the driver registrar is constucted by the 
+ * Normally the driver registrar is constructed by the
  * OGRSFDriverRegistrar::GetRegistrar() accessor which ensures singleton
- * status.  
+ * status.
  */
 
-OGRSFDriverRegistrar::OGRSFDriverRegistrar()
-
-{
-}
+OGRSFDriverRegistrar::OGRSFDriverRegistrar() {}
 
 /************************************************************************/
 /*                       ~OGRSFDriverRegistrar()                        */
@@ -83,7 +80,7 @@ int OGRwillNeverBeTrue = FALSE;
 #endif
 
 /**
- * \brief Cleanup all OGR related resources. 
+ * \brief Cleanup all OGR related resources.
  *
  * FIXME
  */
@@ -163,7 +160,7 @@ OGRErr OGRReleaseDataSource( OGRDataSourceH hDS )
 
 #ifdef OGRAPISPY_ENABLED
     if( bOGRAPISpyEnabled )
-        OGRAPISpyPostClose(hDS);
+        OGRAPISpyPostClose();
 #endif
 
     return OGRERR_NONE;
@@ -304,7 +301,7 @@ void OGRRegisterDriver( OGRSFDriverH hDriver )
 
 {
     VALIDATE_POINTER0( hDriver, "OGRRegisterDriver" );
-    
+
     GetGDALDriverManager()->RegisterDriver( (GDALDriver*)hDriver );
 }
 
@@ -316,7 +313,7 @@ void OGRDeregisterDriver( OGRSFDriverH hDriver )
 
 {
     VALIDATE_POINTER0( hDriver, "OGRDeregisterDriver" );
-    
+
     GetGDALDriverManager()->DeregisterDriver( (GDALDriver*)hDriver );
 }
 
@@ -411,6 +408,6 @@ OGRSFDriverH OGRGetDriverByName( const char *pszName )
 {
     VALIDATE_POINTER1( pszName, "OGRGetDriverByName", NULL );
 
-    return (OGRSFDriverH) 
+    return (OGRSFDriverH)
         OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName( pszName );
 }
diff --git a/ogr/ogrsf_frmts/generic/ogrunionlayer.cpp b/ogr/ogrsf_frmts/generic/ogrunionlayer.cpp
index 5f1b199..a9d7e79 100644
--- a/ogr/ogrsf_frmts/generic/ogrunionlayer.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrunionlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrunionlayer.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrunionlayer.cpp 32177 2015-12-14 07:25:30Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRUnionLayer class
@@ -31,15 +31,15 @@
 #include "ogrwarpedlayer.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrunionlayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrunionlayer.cpp 32177 2015-12-14 07:25:30Z goatbar $");
 
 /************************************************************************/
 /*                      OGRUnionLayerGeomFieldDefn()                    */
 /************************************************************************/
 
-OGRUnionLayerGeomFieldDefn::OGRUnionLayerGeomFieldDefn(const char* pszName,
+OGRUnionLayerGeomFieldDefn::OGRUnionLayerGeomFieldDefn(const char* pszNameIn,
                                                        OGRwkbGeometryType eType) :
-        OGRGeomFieldDefn(pszName, eType), bGeomTypeSet(FALSE), bSRSSet(FALSE)
+        OGRGeomFieldDefn(pszNameIn, eType), bGeomTypeSet(FALSE), bSRSSet(FALSE)
 {
 }
 
@@ -83,38 +83,35 @@ OGRUnionLayerGeomFieldDefn::~OGRUnionLayerGeomFieldDefn()
 OGRUnionLayer::OGRUnionLayer( const char* pszName,
                               int nSrcLayersIn,
                               OGRLayer** papoSrcLayersIn,
-                              int bTakeLayerOwnership )
+                              int bTakeLayerOwnership ) :
+    osName(pszName),
+    nSrcLayers(nSrcLayersIn),
+    papoSrcLayers(papoSrcLayersIn),
+    bHasLayerOwnership(bTakeLayerOwnership),
+    poFeatureDefn(NULL),
+    nFields(0),
+    papoFields(NULL),
+    nGeomFields(0),
+    papoGeomFields(NULL),
+    eFieldStrategy(FIELD_UNION_ALL_LAYERS),
+    bPreserveSrcFID(FALSE),
+    nFeatureCount(-1),
+    iCurLayer(-1),
+    pszAttributeFilter(NULL),
+    nNextFID(0),
+    panMap(NULL),
+    papszIgnoredFields(NULL),
+    bAttrFilterPassThroughValue(-1),
+    poGlobalSRS(NULL)
 {
     CPLAssert(nSrcLayersIn > 0);
-    
-    SetDescription( pszName );
-
-    osName = pszName;
-    nSrcLayers = nSrcLayersIn;
-    papoSrcLayers = papoSrcLayersIn;
-    bHasLayerOwnership = bTakeLayerOwnership;
-
-    poFeatureDefn = NULL;
-    nFields = 0;
-    papoFields = NULL;
-    nGeomFields = 0;
-    papoGeomFields = NULL;
-    eFieldStrategy = FIELD_UNION_ALL_LAYERS;
-
-    bPreserveSrcFID = FALSE;
 
-    nFeatureCount = -1;
-
-    iCurLayer = -1;
-    pszAttributeFilter = NULL;
-    nNextFID = 0;
-    panMap = NULL;
-    papszIgnoredFields = NULL;
-    bAttrFilterPassThroughValue = -1;
-    poGlobalSRS = NULL;
+    SetDescription( pszName );
 
-    pabModifiedLayers = (int*)CPLCalloc(sizeof(int), nSrcLayers);
-    pabCheckIfAutoWrap = (int*)CPLCalloc(sizeof(int), nSrcLayers);
+    pabModifiedLayers
+        = reinterpret_cast<int*>(CPLCalloc(sizeof(int), nSrcLayers));
+    pabCheckIfAutoWrap
+        = reinterpret_cast<int*>(CPLCalloc(sizeof(int), nSrcLayers));
 }
 
 /************************************************************************/
@@ -123,19 +120,17 @@ OGRUnionLayer::OGRUnionLayer( const char* pszName,
 
 OGRUnionLayer::~OGRUnionLayer()
 {
-    int i;
-
     if( bHasLayerOwnership )
     {
-        for(i = 0; i < nSrcLayers; i++)
+        for(int i = 0; i < nSrcLayers; i++)
             delete papoSrcLayers[i];
     }
     CPLFree(papoSrcLayers);
 
-    for(i = 0; i < nFields; i++)
+    for(int i = 0; i < nFields; i++)
         delete papoFields[i];
     CPLFree(papoFields);
-    for(i = 0; i < nGeomFields; i++)
+    for(int i = 0; i < nGeomFields; i++)
         delete papoGeomFields[i];
     CPLFree(papoGeomFields);
 
@@ -418,12 +413,12 @@ OGRFeatureDefn *OGRUnionLayer::GetLayerDefn()
         /* Remove any field that is not found in the source layers */
         for(int iLayer = 1; iLayer < nSrcLayers; iLayer++)
         {
-            OGRFeatureDefn* poSrcFeatureDefn =
+            OGRFeatureDefn* l_poSrcFeatureDefn =
                                         papoSrcLayers[iLayer]->GetLayerDefn();
             for(i = iCompareFirstIndex; i < poFeatureDefn->GetFieldCount();)
             {
                 OGRFieldDefn* poFieldDefn = poFeatureDefn->GetFieldDefn(i);
-                int nSrcIndex = poSrcFeatureDefn->GetFieldIndex(
+                int nSrcIndex = l_poSrcFeatureDefn->GetFieldIndex(
                                                     poFieldDefn->GetNameRef());
                 if( nSrcIndex < 0 )
                 {
@@ -432,7 +427,7 @@ OGRFeatureDefn *OGRUnionLayer::GetLayerDefn()
                 else
                 {
                     OGRFieldDefn* poSrcFieldDefn =
-                        poSrcFeatureDefn->GetFieldDefn(nSrcIndex);
+                        l_poSrcFeatureDefn->GetFieldDefn(nSrcIndex);
                     MergeFieldDefn(poFieldDefn, poSrcFieldDefn);
 
                     i ++;
@@ -441,7 +436,7 @@ OGRFeatureDefn *OGRUnionLayer::GetLayerDefn()
             for(i = 0; i < poFeatureDefn->GetGeomFieldCount();)
             {
                 OGRGeomFieldDefn* poFieldDefn = poFeatureDefn->GetGeomFieldDefn(i);
-                int nSrcIndex = poSrcFeatureDefn->GetGeomFieldIndex(
+                int nSrcIndex = l_poSrcFeatureDefn->GetGeomFieldIndex(
                                                     poFieldDefn->GetNameRef());
                 if( nSrcIndex < 0 )
                 {
@@ -514,7 +509,7 @@ void OGRUnionLayer::ConfigureActiveLayer()
     papoSrcLayers[iCurLayer]->ResetReading();
 
     /* Establish map */
-    OGRFeatureDefn* poFeatureDefn = GetLayerDefn();
+    GetLayerDefn();
     OGRFeatureDefn* poSrcFeatureDefn = papoSrcLayers[iCurLayer]->GetLayerDefn();
     CPLFree(panMap);
     panMap = (int*) CPLMalloc(poSrcFeatureDefn->GetFieldCount() * sizeof(int));
@@ -660,9 +655,17 @@ void OGRUnionLayer::AutoWarpLayerIfNecessary(int iLayer)
                         OGRCreateCoordinateTransformation( poSRS2, poSRS );
                     OGRCoordinateTransformation* poReversedCT = (poCT != NULL) ?
                         OGRCreateCoordinateTransformation( poSRS, poSRS2 ) : NULL;
-                    if( poCT != NULL && poReversedCT != NULL )
+                    if( poReversedCT != NULL )
                         papoSrcLayers[iLayer] = new OGRWarpedLayer(
                                     papoSrcLayers[iLayer], iSrcGeomField, TRUE, poCT, poReversedCT);
+                    else
+                    {
+                        CPLError(CE_Warning, CPLE_AppDefined,
+                                 "AutoWarpLayerIfNecessary failed to create "
+                                 "poCT or poReversedCT.");
+                        if ( poCT != NULL )
+                            delete poCT;
+                    }
                 }
             }
 
@@ -685,7 +688,7 @@ OGRFeature *OGRUnionLayer::GetNextFeature()
     if( iCurLayer == nSrcLayers )
         return NULL;
 
-    while(TRUE)
+    while( true )
     {
         OGRFeature* poSrcFeature = papoSrcLayers[iCurLayer]->GetNextFeature();
         if( poSrcFeature == NULL )
@@ -1132,7 +1135,7 @@ OGRErr OGRUnionLayer::GetExtent(int iGeomField, OGREnvelope *psExtent, int bForc
         memcpy(psExtent, &papoGeomFields[iGeomField]->sStaticEnvelope, sizeof(OGREnvelope));
         return OGRERR_NONE;
     }
-    
+
     if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
diff --git a/ogr/ogrsf_frmts/generic/ogrunionlayer.h b/ogr/ogrsf_frmts/generic/ogrunionlayer.h
index 8d641b6..529ad07 100644
--- a/ogr/ogrsf_frmts/generic/ogrunionlayer.h
+++ b/ogr/ogrsf_frmts/generic/ogrunionlayer.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrunionlayer.h 29330 2015-06-14 12:11:11Z rouault $
+ * $Id: ogrunionlayer.h 31777 2015-11-26 14:14:41Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines OGRUnionLayer class
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGRUNIONLAYER_H_INCLUDED
-#define _OGRUNIONLAYER_H_INCLUDED
+#ifndef OGRUNIONLAYER_H_INCLUDED
+#define OGRUNIONLAYER_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 
@@ -150,4 +150,4 @@ class OGRUnionLayer : public OGRLayer
     virtual OGRErr      SyncToDisk();
 };
 
-#endif // _OGRUNIONLAYER_H_INCLUDED
+#endif // OGRUNIONLAYER_H_INCLUDED
diff --git a/ogr/ogrsf_frmts/generic/ogrwarpedlayer.cpp b/ogr/ogrsf_frmts/generic/ogrwarpedlayer.cpp
index a3f0e6b..c830a8d 100644
--- a/ogr/ogrsf_frmts/generic/ogrwarpedlayer.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrwarpedlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrwarpedlayer.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrwarpedlayer.cpp 32177 2015-12-14 07:25:30Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRWarpedLayer class
@@ -29,7 +29,7 @@
 
 #include "ogrwarpedlayer.h"
 
-CPL_CVSID("$Id: ogrwarpedlayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrwarpedlayer.cpp 32177 2015-12-14 07:25:30Z goatbar $");
 
 /************************************************************************/
 /*                          OGRWarpedLayer()                            */
@@ -221,7 +221,7 @@ OGRFeature *OGRWarpedLayer::WarpedFeatureToSrcFeature(OGRFeature* poFeature)
 
 OGRFeature *OGRWarpedLayer::GetNextFeature()
 {
-    while(TRUE)
+    while( true )
     {
         OGRFeature* poFeature = m_poDecoratedLayer->GetNextFeature();
         if( poFeature == NULL )
@@ -287,7 +287,7 @@ OGRErr      OGRWarpedLayer::ICreateFeature( OGRFeature *poFeature )
     OGRFeature* poFeatureNew = WarpedFeatureToSrcFeature(poFeature);
     if( poFeatureNew == NULL )
         return OGRERR_FAILURE;
-   
+
     eErr = m_poDecoratedLayer->CreateFeature(poFeatureNew);
 
     delete poFeatureNew;
@@ -439,9 +439,9 @@ int OGRWarpedLayer::ReprojectEnvelope( OGREnvelope* psEnvelope,
     double *padfX, *padfY;
     int* pabSuccess;
 
-    padfX = (double*) VSIMalloc((NSTEP + 1) * (NSTEP + 1) * sizeof(double));
-    padfY = (double*) VSIMalloc((NSTEP + 1) * (NSTEP + 1) * sizeof(double));
-    pabSuccess = (int*) VSIMalloc((NSTEP + 1) * (NSTEP + 1) * sizeof(int));
+    padfX = (double*) VSI_MALLOC_VERBOSE((NSTEP + 1) * (NSTEP + 1) * sizeof(double));
+    padfY = (double*) VSI_MALLOC_VERBOSE((NSTEP + 1) * (NSTEP + 1) * sizeof(double));
+    pabSuccess = (int*) VSI_MALLOC_VERBOSE((NSTEP + 1) * (NSTEP + 1) * sizeof(int));
     if( padfX == NULL || padfY == NULL || pabSuccess == NULL)
     {
         VSIFree(padfX);
diff --git a/ogr/ogrsf_frmts/generic/ogrwarpedlayer.h b/ogr/ogrsf_frmts/generic/ogrwarpedlayer.h
index 7619981..cade5e8 100644
--- a/ogr/ogrsf_frmts/generic/ogrwarpedlayer.h
+++ b/ogr/ogrsf_frmts/generic/ogrwarpedlayer.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrwarpedlayer.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrwarpedlayer.h 31777 2015-11-26 14:14:41Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines OGRWarpedLayer class
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGRWARPEDLAYER_H_INCLUDED
-#define _OGRWARPEDLAYER_H_INCLUDED
+#ifndef OGRWARPEDLAYER_H_INCLUDED
+#define OGRWARPEDLAYER_H_INCLUDED
 
 #include "ogrlayerdecorator.h"
 
@@ -88,4 +88,4 @@ class OGRWarpedLayer : public OGRLayerDecorator
     virtual int         TestCapability( const char * );
 };
 
-#endif //  _OGRWARPEDLAYER_H_INCLUDED
+#endif //  OGRWARPEDLAYER_H_INCLUDED
diff --git a/ogr/ogrsf_frmts/geoconcept/drv_geoconcept.html b/ogr/ogrsf_frmts/geoconcept/drv_geoconcept.html
index 2715419..34e89c2 100644
--- a/ogr/ogrsf_frmts/geoconcept/drv_geoconcept.html
+++ b/ogr/ogrsf_frmts/geoconcept/drv_geoconcept.html
@@ -18,7 +18,7 @@ points.<p>
 
 <h2>GeoConcept Text File Format (gxt)</h2>
 
-GeoConcept is a GIS developped by the Company GeoConcept SA. <p>
+GeoConcept is a GIS developed by the Company GeoConcept SA. <p>
 
 It's an object oriented GIS, where the features are named « objects »,
 and feature types are named « type/subtype » (class allowing inheritance).<p>
@@ -65,7 +65,7 @@ the GeoConcept model, but are not yet supported by the GeoConcept
 driver).</li>
 </ul>
 
-The OGR GeoConcept driver does not support deleting features. <p> 
+The OGR GeoConcept driver does not support deleting features. <p>
 
 <h3>Dataset Creation Options</h3>
 
@@ -138,7 +138,7 @@ may be declared.</li>
 </ul>
 
 When this option is not used, the driver manage types and sub-types name based on either
-the layer name or on the use of <code>-nln</code> option. 
+the layer name or on the use of <code>-nln</code> option.
 </li>
 
 </ul>
@@ -150,8 +150,8 @@ corresponds to one of the <code>Name</code> found in the GCT file for a type sec
 The <code>SUBTYPE</code> corresponds to one of the <code>Name</code> found in the GCT file for a
 sub-type section within the previous type section.<p>
 
-At the present moment, coordinates are written with 2 decimales for cartesian
-spatial reference systems (including height) or with 9 decimales for
+At the present moment, coordinates are written with 2 decimals for Cartesian
+spatial reference systems (including height) or with 9 decimals for
 geographical spatial reference systems.<p>
 
 <h3>Examples</h3>
diff --git a/ogr/ogrsf_frmts/geoconcept/geoconcept.c b/ogr/ogrsf_frmts/geoconcept/geoconcept.c
index 0273865..15b1ec6 100644
--- a/ogr/ogrsf_frmts/geoconcept/geoconcept.c
+++ b/ogr/ogrsf_frmts/geoconcept/geoconcept.c
@@ -42,7 +42,7 @@ CPL_CVSID("$Id: geoconcept.c,v 1.0.0 2007-11-03 20:58:19 drichard Exp $")
 #define kIdSize_GCIO         12
 #define UNDEFINEDID_GCIO 199901L
 
-static char* gkGCCharset[]=
+static const char* const gkGCCharset[]=
 {
 /* 0 */ "",
 /* 1 */ "ANSI",
@@ -50,7 +50,7 @@ static char* gkGCCharset[]=
 /* 3 */ "MAC"
 };
 
-static char* gkGCAccess[]=
+static const char* const gkGCAccess[]=
 {
 /* 0 */ "",
 /* 1 */ "NO",
@@ -59,14 +59,14 @@ static char* gkGCAccess[]=
 /* 4 */ "WRITE"
 };
 
-static char* gkGCStatus[]=
+static const char* const gkGCStatus[]=
 {
 /* 0 */ "NONE",
 /* 1 */ "MEMO",
 /* 2 */ "EOF"
 };
 
-static char* gk3D[]=
+static const char* const gk3D[]=
 {
 /* 0 */ "",
 /* 1 */ "2D",
@@ -74,7 +74,7 @@ static char* gk3D[]=
 /* 3 */ "3D"
 };
 
-static char* gkGCTypeKind[]=
+static const char* const gkGCTypeKind[]=
 {
 /* 0 */ "",
 /* 1 */ "POINT",
@@ -271,14 +271,18 @@ static long GCIOAPI_CALL _read_GCIO (
   while ((c= VSIFGetc(h))!=EOF)
   {
     c= (0x00FF & (unsigned char)(c));
-    switch (c) {
-    case 0X1A : continue ; /* PC end-of-file           */
-    case '\r' :            /* PC '\r\n' line, MAC '\r' */
+
+    if( c ==  '\r' )            /* PC '\r\n' line, MAC '\r' */
+    {
       if ((c= VSIFGetc(h))!='\n')
       {
         VSIUngetc(c,h);
         c= '\n';
       }
+    }
+
+    switch (c) {
+    case 0X1A : continue ; /* PC end-of-file           */
     case '\n' :
       SetGCCurrentLinenum_GCIO(hGXT,GetGCCurrentLinenum_GCIO(hGXT)+1L);
       if (nread==0L) continue;
@@ -317,7 +321,7 @@ static long GCIOAPI_CALL _get_GCIO (
   if (GetGCStatus_GCIO(hGXT)==vEof_GCIO)
   {
     SetGCCache_GCIO(hGXT,"");
-    SetGCWhatIs_GCIO(hGXT, vUnknownIO_ItemType_GCIO);
+    SetGCWhatIs_GCIO(hGXT, (GCTypeKind)vUnknownIO_ItemType_GCIO);
     return EOF;
   }
   if (GetGCStatus_GCIO(hGXT)==vMemoStatus_GCIO)
@@ -327,22 +331,22 @@ static long GCIOAPI_CALL _get_GCIO (
   }
   if (_read_GCIO(hGXT)==EOF)
   {
-    SetGCWhatIs_GCIO(hGXT, vUnknownIO_ItemType_GCIO);
+    SetGCWhatIs_GCIO(hGXT, (GCTypeKind)vUnknownIO_ItemType_GCIO);
     return EOF;
   }
-  SetGCWhatIs_GCIO(hGXT, vStdCol_GCIO);
+  SetGCWhatIs_GCIO(hGXT, (GCTypeKind)vStdCol_GCIO);
   if (strstr(GetGCCache_GCIO(hGXT),kCom_GCIO)==GetGCCache_GCIO(hGXT))
   { /* // */
-    SetGCWhatIs_GCIO(hGXT, vComType_GCIO);
+    SetGCWhatIs_GCIO(hGXT, (GCTypeKind)vComType_GCIO);
     if (strstr(GetGCCache_GCIO(hGXT),kHeader_GCIO)==GetGCCache_GCIO(hGXT))
     { /* //# */
-      SetGCWhatIs_GCIO(hGXT, vHeader_GCIO);
+      SetGCWhatIs_GCIO(hGXT, (GCTypeKind)vHeader_GCIO);
     }
     else
     {
       if (strstr(GetGCCache_GCIO(hGXT),kPragma_GCIO)==GetGCCache_GCIO(hGXT))
       { /* //$ */
-        SetGCWhatIs_GCIO(hGXT, vPragma_GCIO);
+        SetGCWhatIs_GCIO(hGXT, (GCTypeKind)vPragma_GCIO);
       }
     }
   }
@@ -370,11 +374,8 @@ GCExtent GCIOAPI_CALL1(*) CreateExtent_GCIO (
 {
   GCExtent* theExtent;
 
-  if( !(theExtent= CPLMalloc(sizeof(GCExtent))) )
+  if( !(theExtent= VSI_MALLOC_VERBOSE(sizeof(GCExtent))) )
   {
-    CPLError( CE_Failure, CPLE_OutOfMemory,
-              "failed to create a Geoconcept extent for '[%g %g,%g %g]'.\n",
-              Xmin, Ymin,Xmax, Ymax);
     return NULL;
   }
   _InitExtent_GCIO(theExtent);
@@ -489,11 +490,8 @@ static GCField GCIOAPI_CALL1(*) _CreateField_GCIO (
 {
   GCField* theField;
 
-  if( !(theField= CPLMalloc(sizeof(GCField))) )
+  if( !(theField= VSI_MALLOC_VERBOSE(sizeof(GCField))) )
   {
-    CPLError( CE_Failure, CPLE_OutOfMemory,
-              "failed to create a Geoconcept field for '%s'.\n",
-              name);
     return NULL;
   }
   _InitField_GCIO(theField);
@@ -612,11 +610,8 @@ static GCSubType GCIOAPI_CALL1(*) _CreateSubType_GCIO (
 {
   GCSubType* theSubType;
 
-  if( !(theSubType= CPLMalloc(sizeof(GCSubType))) )
+  if( !(theSubType= VSI_MALLOC_VERBOSE(sizeof(GCSubType))) )
   {
-    CPLError( CE_Failure, CPLE_OutOfMemory,
-              "failed to create a Geoconcept subtype for '%s'.\n",
-              subtypName);
     return NULL;
   }
   _InitSubType_GCIO(theSubType);
@@ -686,7 +681,7 @@ static int GCIOAPI_CALL _findSubTypeByName_GCIO (
 {
   GCSubType* theSubType;
 
-  if( GetTypeSubtypes_GCIO(theClass) )
+  if( theClass != NULL && GetTypeSubtypes_GCIO(theClass) )
   {
     CPLList* e;
     int n, i;
@@ -743,11 +738,8 @@ static GCType GCIOAPI_CALL1(*) _CreateType_GCIO (
 {
   GCType* theClass;
 
-  if( !(theClass= CPLMalloc(sizeof(GCType))) )
+  if( !(theClass= VSI_MALLOC_VERBOSE(sizeof(GCType))) )
   {
-    CPLError( CE_Failure, CPLE_OutOfMemory,
-              "failed to create a Geoconcept type for '%s#%ld'.\n",
-              typName, id);
     return NULL;
   }
   _InitType_GCIO(theClass);
@@ -889,14 +881,12 @@ static void GCIOAPI_CALL _InitHeader_GCIO (
 }/* _InitHeader_GCIO */
 
 /* -------------------------------------------------------------------- */
-GCExportFileMetadata GCIOAPI_CALL1(*) CreateHeader_GCIO ( )
+GCExportFileMetadata GCIOAPI_CALL1(*) CreateHeader_GCIO ( void )
 {
   GCExportFileMetadata* m;
 
-  if( !(m= CPLMalloc(sizeof(GCExportFileMetadata)) ) )
+  if( !(m= VSI_MALLOC_VERBOSE(sizeof(GCExportFileMetadata)) ) )
   {
-    CPLError( CE_Failure, CPLE_OutOfMemory,
-              "failed to create Geoconcept metadata.\n");
     return NULL;
   }
   _InitHeader_GCIO(m);
@@ -995,7 +985,7 @@ static void GCIOAPI_CALL _Init_GCIO (
   SetGCMeta_GCIO(H, NULL);
   SetGCMode_GCIO(H, vNoAccess_GCIO);
   SetGCStatus_GCIO(H, vNoStatus_GCIO);
-  SetGCWhatIs_GCIO(H, vUnknownIO_ItemType_GCIO);
+  SetGCWhatIs_GCIO(H, (GCTypeKind)vUnknownIO_ItemType_GCIO);
 }/* _Init_GCIO */
 
 /* -------------------------------------------------------------------- */
@@ -1008,11 +998,8 @@ static GCExportFileH GCIOAPI_CALL1(*) _Create_GCIO (
   GCExportFileH* hGXT;
 
   CPLDebug("GEOCONCEPT","allocating %d bytes for GCExportFileH", (int)sizeof(GCExportFileH));
-  if( !(hGXT= CPLMalloc(sizeof(GCExportFileH)) ) )
+  if( !(hGXT= VSI_MALLOC_VERBOSE(sizeof(GCExportFileH)) ) )
   {
-    CPLError( CE_Failure, CPLE_OutOfMemory,
-              "failed to create a Geoconcept handle for '%s' (%s).\n",
-              pszGeoconceptFile, mode);
     return NULL;
   }
 
@@ -1795,7 +1782,7 @@ static OGRGeometryH GCIOAPI_CALL _buildOGRGeometry_GCIO (
   {
     buildGeom= FALSE;
   }
-  x= y= z= 0.0;
+  z= 0.0;
   switch( GetSubTypeKind_GCIO(theSubType) )
   {
     case vPoint_GCIO :
@@ -2002,7 +1989,7 @@ static OGRGeometryH GCIOAPI_CALL _buildOGRGeometry_GCIO (
       {
         CPLError( CE_Failure, CPLE_OutOfMemory,
                   "failed to add a polygon to subtype '%s.%s'.\n",
-                  GetTypeName_GCIO(GetSubTypeType_GCIO(theSubType)), 
+                  GetTypeName_GCIO(GetSubTypeType_GCIO(theSubType)),
                   GetSubTypeName_GCIO(theSubType) );
         OGR_G_DestroyGeometry(outer);
         goto onError;
@@ -2249,6 +2236,11 @@ static OGRFeatureH GCIOAPI_CALL _buildOGRFeature_GCIO (
     return NULL;
   }
   theClass= _getType_GCIO(H,whereClass);
+  if( theClass == NULL )
+  {
+      CSLDestroy(pszFields);
+      return NULL;
+  }
   if( *theSubType )
   {
     /* reading ... */
@@ -2269,7 +2261,9 @@ static OGRFeatureH GCIOAPI_CALL _buildOGRFeature_GCIO (
   }
   if( *theSubType )
   {
-    if( !EQUAL(GetSubTypeName_GCIO(_getSubType_GCIO(theClass,whereSubType)),GetSubTypeName_GCIO(*theSubType)) )
+    GCSubType* psSubType = _getSubType_GCIO(theClass,whereSubType);
+    if( psSubType == NULL ||
+        !EQUAL(GetSubTypeName_GCIO(psSubType),GetSubTypeName_GCIO(*theSubType)) )
     {
       CSLDestroy(pszFields);
       return NULL;
@@ -2278,6 +2272,7 @@ static OGRFeatureH GCIOAPI_CALL _buildOGRFeature_GCIO (
   else
   {
     *theSubType= _getSubType_GCIO(theClass,whereSubType);
+    CPLAssert(*theSubType != NULL);
   }
   snprintf(tdst, kItemSize_GCIO-1, "%s.%s", GetTypeName_GCIO(theClass), GetSubTypeName_GCIO(*theSubType));
   tdst[kItemSize_GCIO-1]= '\0';
@@ -2414,7 +2409,7 @@ static OGRFeatureH GCIOAPI_CALL _buildOGRFeature_GCIO (
     }
     for( i= 1 + nbf, j= 0; i<1 + nbf + nbstf; i++, j++ )
     {
-      theField= GetSubTypeField_GCIO(*theSubType,i);
+      /*theField= GetSubTypeField_GCIO(*theSubType,i); */ /* FIXME?*/
       if( pszFields[i][0]=='\0' )
         OGR_F_UnsetField(f,j);
       else
@@ -2490,6 +2485,7 @@ reloop:
     goto reloop;
   }
   /* analyze the line according to schema : */
+  /* coverity[mixed_enums] */ /* FIXME ? */
   if( (enum _tIO_MetadataType_GCIO)GetGCWhatIs_GCIO(H) == vPragma_GCIO )
   {
     if( strstr(GetGCCache_GCIO(H),k3DOBJECTMONO_GCIO) )
@@ -2548,6 +2544,8 @@ reloop:
   SetExtentLROrdinate_GCIO(GetSubTypeExtent_GCIO(theSubType),pszBbox->MinY);
   if( d==vUnknown3D_GCIO && GetSubTypeDim_GCIO(theSubType)==vUnknown3D_GCIO )
   {
+    /* FIXME ? */
+#ifdef notdef
     switch( d )
     {
       case v3DM_GCIO :
@@ -2555,11 +2553,14 @@ reloop:
         SetSubTypeDim_GCIO(theSubType,v3D_GCIO);
         break;
       default        :
+#endif
         SetSubTypeDim_GCIO(theSubType,v2D_GCIO);
+#ifdef notdef
         break;
     }
+#endif
   }
-  d= vUnknown3D_GCIO;
+  /*d= vUnknown3D_GCIO;*/
   theSubType= NULL;
 
   return Meta;
@@ -2576,9 +2577,9 @@ GCExportFileH GCIOAPI_CALL1(*) Open_GCIO (
   GCExportFileH* hGXT;
 
   CPLDebug( "GEOCONCEPT", "filename '%s' - '%s' - mode '%s' - config path '%s'",
-                          pszGeoconceptFile? pszGeoconceptFile:"???",
+                          pszGeoconceptFile,
                           ext? ext:"gxt",
-                          mode? mode:"???",
+                          mode,
                           gctPath? gctPath:"???" );
 
   if( !(hGXT= _Create_GCIO(pszGeoconceptFile,ext,mode)) )
@@ -2596,6 +2597,7 @@ GCExportFileH GCIOAPI_CALL1(*) Open_GCIO (
       _Destroy_GCIO(&hGXT,FALSE);
       return NULL;
     }
+    VSIFClose(h);
   }
 
   SetGCHandle_GCIO(hGXT, VSIFOpen(CPLFormFilename(GetGCPath_GCIO(hGXT),GetGCBasename_GCIO(hGXT),GetGCExtension_GCIO(hGXT)), mode));
@@ -2695,8 +2697,8 @@ GCExportFileH GCIOAPI_CALL1(*) Rewind_GCIO (
       }
       else
       {
-        VSIFSeek(GetGCHandle_GCIO(hGXT), GetSubTypeBOF_GCIO(theSubType), SEEK_SET);
-        SetGCCurrentLinenum_GCIO(hGXT, GetSubTypeBOFLinenum_GCIO(theSubType));
+        if( VSIFSeek(GetGCHandle_GCIO(hGXT), GetSubTypeBOF_GCIO(theSubType), SEEK_SET) == 0 )
+            SetGCCurrentLinenum_GCIO(hGXT, GetSubTypeBOFLinenum_GCIO(theSubType));
       }
       SetGCStatus_GCIO(hGXT,vNoStatus_GCIO);
     }
@@ -2719,6 +2721,7 @@ GCExportFileH GCIOAPI_CALL1(*) FFlush_GCIO (
   return hGXT;
 }/* FFlush_GCIO */
 
+#ifdef unused
 /* -------------------------------------------------------------------- */
 GCAccessMode GCIOAPI_CALL GetMode_GCIO (
                                          GCExportFileH* hGXT
@@ -2726,6 +2729,7 @@ GCAccessMode GCIOAPI_CALL GetMode_GCIO (
 {
   return hGXT? GetGCMode_GCIO(hGXT):vUnknownAccessMode_GCIO;
 }/* GetMode_GCIO */
+#endif
 
 /* -------------------------------------------------------------------- */
 GCSubType GCIOAPI_CALL1(*) AddSubType_GCIO (
@@ -2751,6 +2755,8 @@ GCSubType GCIOAPI_CALL1(*) AddSubType_GCIO (
   }
 
   theClass= _getType_GCIO(H,whereClass);
+  if( theClass == NULL )
+      return NULL;
   if( GetTypeSubtypes_GCIO(theClass) )
   {
     if( _findSubTypeByName_GCIO(theClass,subtypName)!=-1 )
@@ -3012,7 +3018,7 @@ static OGRErr GCIOAPI_CALL _readConfigField_GCIO (
                                                    GCExportFileH* hGCT
                                                  )
 {
-  int eof, res;
+  int bEOF;
   char *k, n[kItemSize_GCIO], x[kExtraSize_GCIO], e[kExtraSize_GCIO];
   const char* normName;
   long id;
@@ -3020,7 +3026,7 @@ static OGRErr GCIOAPI_CALL _readConfigField_GCIO (
   CPLList* L;
   GCField* theField;
 
-  eof= 0;
+  bEOF= 0;
   n[0]= '\0';
   x[0]= '\0';
   e[0]= '\0';
@@ -3033,17 +3039,17 @@ static OGRErr GCIOAPI_CALL _readConfigField_GCIO (
     {
       continue;
     }
+    /* coverity[mixed_enums] */ /* FIXME ? */
     if( (enum _tIO_MetadataType_GCIO)GetGCWhatIs_GCIO(hGCT) == vHeader_GCIO )
     {
       if( strstr(GetGCCache_GCIO(hGCT),kConfigEndField_GCIO)!=NULL)
       {
-        eof= 1;
+        bEOF= 1;
         if( n[0]=='\0' || id==UNDEFINEDID_GCIO || knd==vUnknownItemType_GCIO )
         {
           CPLError( CE_Failure, CPLE_AppDefined,
                     "Missing %s.\n",
                     n[0]=='\0'? "Name": id==UNDEFINEDID_GCIO? "ID": "Kind");
-          res= OGRERR_CORRUPT_DATA;
           goto onError;
         }
         normName= _NormalizeFieldName_GCIO(n);
@@ -3052,12 +3058,10 @@ static OGRErr GCIOAPI_CALL _readConfigField_GCIO (
           CPLError( CE_Failure, CPLE_AppDefined,
                     "field '@%s#%ld' already exists.\n",
                     n, id);
-          res= OGRERR_CORRUPT_DATA;
           goto onError;
         }
         if( !(theField= _CreateField_GCIO(normName,id,knd,x,e)) )
         {
-          res= OGRERR_CORRUPT_DATA;
           goto onError;
         }
         if( (L= CPLListAppend(GetMetaFields_GCIO(GetGCMeta_GCIO(hGCT)),theField))==NULL )
@@ -3066,13 +3070,12 @@ static OGRErr GCIOAPI_CALL _readConfigField_GCIO (
           CPLError( CE_Failure, CPLE_OutOfMemory,
                     "failed to add a Geoconcept field for '@%s#%ld'.\n",
                     n, id);
-          res= OGRERR_CORRUPT_DATA;
           goto onError;
         }
         SetMetaFields_GCIO(GetGCMeta_GCIO(hGCT), L);
         break;
       }
-      res= OGRERR_NONE;
+
       if( (k= strstr(GetGCCache_GCIO(hGCT),kConfigName_GCIO))!=NULL )
       {
         if( n[0]!='\0' )
@@ -3080,7 +3083,6 @@ static OGRErr GCIOAPI_CALL _readConfigField_GCIO (
           CPLError( CE_Failure, CPLE_AppDefined,
                     "Duplicate Name found : '%s'.\n",
                     GetGCCache_GCIO(hGCT));
-          res= OGRERR_CORRUPT_DATA;
           goto onError;
         }
         if( (k= _getHeaderValue_GCIO(k))==NULL )
@@ -3088,7 +3090,6 @@ static OGRErr GCIOAPI_CALL _readConfigField_GCIO (
           CPLError( CE_Failure, CPLE_AppDefined,
                     "Invalid Name found : '%s'.\n",
                     GetGCCache_GCIO(hGCT));
-          res= OGRERR_CORRUPT_DATA;
           goto onError;
         }
         strncpy(n,k,kItemSize_GCIO-1), n[kItemSize_GCIO-1]= '\0';
@@ -3101,7 +3102,6 @@ static OGRErr GCIOAPI_CALL _readConfigField_GCIO (
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Duplicate ID found : '%s'.\n",
                       GetGCCache_GCIO(hGCT));
-            res= OGRERR_CORRUPT_DATA;
             goto onError;
           }
           if( (k= _getHeaderValue_GCIO(k))==NULL )
@@ -3109,7 +3109,6 @@ static OGRErr GCIOAPI_CALL _readConfigField_GCIO (
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Invalid ID found : '%s'.\n",
                       GetGCCache_GCIO(hGCT));
-            res= OGRERR_CORRUPT_DATA;
             goto onError;
           }
           if( sscanf(k,"%ld", &id)!=1 )
@@ -3117,7 +3116,6 @@ static OGRErr GCIOAPI_CALL _readConfigField_GCIO (
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Invalid ID found : '%s'.\n",
                       GetGCCache_GCIO(hGCT));
-            res= OGRERR_CORRUPT_DATA;
             goto onError;
           }
         }
@@ -3129,7 +3127,6 @@ static OGRErr GCIOAPI_CALL _readConfigField_GCIO (
               CPLError( CE_Failure, CPLE_AppDefined,
                         "Duplicate Kind found : '%s'.\n",
                         GetGCCache_GCIO(hGCT));
-              res= OGRERR_CORRUPT_DATA;
               goto onError;
             }
             if( (k= _getHeaderValue_GCIO(k))==NULL )
@@ -3137,7 +3134,6 @@ static OGRErr GCIOAPI_CALL _readConfigField_GCIO (
               CPLError( CE_Failure, CPLE_AppDefined,
                         "Invalid Kind found : '%s'.\n",
                         GetGCCache_GCIO(hGCT));
-              res= OGRERR_CORRUPT_DATA;
               goto onError;
             }
             if( (knd= str2GCTypeKind_GCIO(k))==vUnknownItemType_GCIO )
@@ -3145,7 +3141,6 @@ static OGRErr GCIOAPI_CALL _readConfigField_GCIO (
               CPLError( CE_Failure, CPLE_AppDefined,
                         "Not supported Kind found : '%s'.\n",
                         GetGCCache_GCIO(hGCT));
-              res= OGRERR_CORRUPT_DATA;
               goto onError;
             }
           }
@@ -3158,7 +3153,6 @@ static OGRErr GCIOAPI_CALL _readConfigField_GCIO (
                 CPLError( CE_Failure, CPLE_AppDefined,
                           "Duplicate Extra information found : '%s'.\n",
                           GetGCCache_GCIO(hGCT));
-                res= OGRERR_CORRUPT_DATA;
                 goto onError;
               }
               if( (k= _getHeaderValue_GCIO(k))==NULL )
@@ -3166,7 +3160,6 @@ static OGRErr GCIOAPI_CALL _readConfigField_GCIO (
                 CPLError( CE_Failure, CPLE_AppDefined,
                           "Invalid Extra information found : '%s'.\n",
                           GetGCCache_GCIO(hGCT));
-                res= OGRERR_CORRUPT_DATA;
                 goto onError;
               }
               strncpy(x,k,kExtraSize_GCIO-1), x[kExtraSize_GCIO-1]= '\0';
@@ -3179,7 +3172,6 @@ static OGRErr GCIOAPI_CALL _readConfigField_GCIO (
                   CPLError( CE_Failure, CPLE_AppDefined,
                             "Duplicate List found : '%s'.\n",
                             GetGCCache_GCIO(hGCT));
-                  res= OGRERR_CORRUPT_DATA;
                   goto onError;
                 }
                 if( (k= _getHeaderValue_GCIO(k))==NULL )
@@ -3187,25 +3179,20 @@ static OGRErr GCIOAPI_CALL _readConfigField_GCIO (
                   CPLError( CE_Failure, CPLE_AppDefined,
                             "Invalid List found : '%s'.\n",
                             GetGCCache_GCIO(hGCT));
-                  res= OGRERR_CORRUPT_DATA;
                   goto onError;
                 }
                 strncpy(e,k,kExtraSize_GCIO-1), e[kExtraSize_GCIO-1]= '\0';
               }
               else
               { /* Skipping ... */
-                res= OGRERR_NONE;
               }
-      if( res != OGRERR_NONE )
-      {
-        goto onError;
-      }
+
       continue;
     }
 onError:
     return OGRERR_CORRUPT_DATA;
   }
-  if (eof!=1)
+  if (bEOF!=1)
   {
     CPLError( CE_Failure, CPLE_AppDefined,
               "Geoconcept config field end block %s not found.\n",
@@ -3222,13 +3209,13 @@ static OGRErr GCIOAPI_CALL _readConfigFieldType_GCIO (
                                                        GCType* theClass
                                                      )
 {
-  int eof, res;
+  int bEOF;
   char *k, n[kItemSize_GCIO], x[kExtraSize_GCIO], e[kExtraSize_GCIO];
   long id;
   GCTypeKind knd;
   GCField* theField;
 
-  eof= 0;
+  bEOF= 0;
   n[0]= '\0';
   x[0]= '\0';
   e[0]= '\0';
@@ -3241,27 +3228,26 @@ static OGRErr GCIOAPI_CALL _readConfigFieldType_GCIO (
     {
       continue;
     }
+    /* coverity[mixed_enums] */ /* FIXME ? */
     if( (enum _tIO_MetadataType_GCIO)GetGCWhatIs_GCIO(hGCT) == vHeader_GCIO )
     {
       if( strstr(GetGCCache_GCIO(hGCT),kConfigEndField_GCIO)!=NULL)
       {
-        eof= 1;
+        bEOF= 1;
         if( n[0]=='\0' || id==UNDEFINEDID_GCIO || knd==vUnknownItemType_GCIO )
         {
           CPLError( CE_Failure, CPLE_AppDefined,
                     "Missing %s.\n",
                     n[0]=='\0'? "Name": id==UNDEFINEDID_GCIO? "ID": "Kind");
-          res= OGRERR_CORRUPT_DATA;
           goto onError;
         }
         if( (theField= AddTypeField_GCIO(hGCT,GetTypeName_GCIO(theClass),-1,n,id,knd,x,e))==NULL )
         {
-          res= OGRERR_CORRUPT_DATA;
           goto onError;
         }
         break;
       }
-      res= OGRERR_NONE;
+
       if( (k= strstr(GetGCCache_GCIO(hGCT),kConfigName_GCIO))!=NULL )
       {
         if( n[0]!='\0' )
@@ -3269,7 +3255,6 @@ static OGRErr GCIOAPI_CALL _readConfigFieldType_GCIO (
           CPLError( CE_Failure, CPLE_AppDefined,
                     "Duplicate Name found : '%s'.\n",
                     GetGCCache_GCIO(hGCT));
-          res= OGRERR_CORRUPT_DATA;
           goto onError;
         }
         if( (k= _getHeaderValue_GCIO(k))==NULL )
@@ -3277,7 +3262,6 @@ static OGRErr GCIOAPI_CALL _readConfigFieldType_GCIO (
           CPLError( CE_Failure, CPLE_AppDefined,
                     "Invalid Name found : '%s'.\n",
                     GetGCCache_GCIO(hGCT));
-          res= OGRERR_CORRUPT_DATA;
           goto onError;
         }
         strncpy(n,k,kItemSize_GCIO-1), n[kItemSize_GCIO-1]= '\0';
@@ -3290,7 +3274,6 @@ static OGRErr GCIOAPI_CALL _readConfigFieldType_GCIO (
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Duplicate ID found : '%s'.\n",
                       GetGCCache_GCIO(hGCT));
-            res= OGRERR_CORRUPT_DATA;
             goto onError;
           }
           if( (k= _getHeaderValue_GCIO(k))==NULL )
@@ -3298,7 +3281,6 @@ static OGRErr GCIOAPI_CALL _readConfigFieldType_GCIO (
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Invalid ID found : '%s'.\n",
                       GetGCCache_GCIO(hGCT));
-            res= OGRERR_CORRUPT_DATA;
             goto onError;
           }
           if( sscanf(k,"%ld", &id)!=1 )
@@ -3306,7 +3288,6 @@ static OGRErr GCIOAPI_CALL _readConfigFieldType_GCIO (
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Invalid ID found : '%s'.\n",
                       GetGCCache_GCIO(hGCT));
-            res= OGRERR_CORRUPT_DATA;
             goto onError;
           }
         }
@@ -3318,7 +3299,6 @@ static OGRErr GCIOAPI_CALL _readConfigFieldType_GCIO (
               CPLError( CE_Failure, CPLE_AppDefined,
                         "Duplicate Kind found : '%s'.\n",
                         GetGCCache_GCIO(hGCT));
-              res= OGRERR_CORRUPT_DATA;
               goto onError;
             }
             if( (k= _getHeaderValue_GCIO(k))==NULL )
@@ -3326,7 +3306,6 @@ static OGRErr GCIOAPI_CALL _readConfigFieldType_GCIO (
               CPLError( CE_Failure, CPLE_AppDefined,
                         "Invalid Kind found : '%s'.\n",
                         GetGCCache_GCIO(hGCT));
-              res= OGRERR_CORRUPT_DATA;
               goto onError;
             }
             if( (knd= str2GCTypeKind_GCIO(k))==vUnknownItemType_GCIO )
@@ -3334,7 +3313,6 @@ static OGRErr GCIOAPI_CALL _readConfigFieldType_GCIO (
               CPLError( CE_Failure, CPLE_AppDefined,
                         "Not supported Kind found : '%s'.\n",
                         GetGCCache_GCIO(hGCT));
-              res= OGRERR_CORRUPT_DATA;
               goto onError;
             }
           }
@@ -3347,7 +3325,6 @@ static OGRErr GCIOAPI_CALL _readConfigFieldType_GCIO (
                 CPLError( CE_Failure, CPLE_AppDefined,
                           "Duplicate Extra information found : '%s'.\n",
                           GetGCCache_GCIO(hGCT));
-                res= OGRERR_CORRUPT_DATA;
                 goto onError;
               }
               if( (k= _getHeaderValue_GCIO(k))==NULL )
@@ -3355,7 +3332,6 @@ static OGRErr GCIOAPI_CALL _readConfigFieldType_GCIO (
                 CPLError( CE_Failure, CPLE_AppDefined,
                           "Invalid extra information found : '%s'.\n",
                           GetGCCache_GCIO(hGCT));
-                res= OGRERR_CORRUPT_DATA;
                 goto onError;
               }
               strncpy(x,k,kExtraSize_GCIO-1), x[kExtraSize_GCIO-1]= '\0';
@@ -3368,7 +3344,6 @@ static OGRErr GCIOAPI_CALL _readConfigFieldType_GCIO (
                   CPLError( CE_Failure, CPLE_AppDefined,
                             "Duplicate List found : '%s'.\n",
                             GetGCCache_GCIO(hGCT));
-                  res= OGRERR_CORRUPT_DATA;
                   goto onError;
                 }
                 if( (k= _getHeaderValue_GCIO(k))==NULL )
@@ -3376,25 +3351,20 @@ static OGRErr GCIOAPI_CALL _readConfigFieldType_GCIO (
                   CPLError( CE_Failure, CPLE_AppDefined,
                             "Invalid List found : '%s'.\n",
                             GetGCCache_GCIO(hGCT));
-                  res= OGRERR_CORRUPT_DATA;
                   goto onError;
                 }
                 strncpy(e,k,kExtraSize_GCIO-1), e[kExtraSize_GCIO-1]= '\0';
               }
               else
               { /* Skipping ... */
-                res= OGRERR_NONE;
               }
-      if( res != OGRERR_NONE )
-      {
-        goto onError;
-      }
+
       continue;
     }
 onError:
     return OGRERR_CORRUPT_DATA;
   }
-  if (eof!=1)
+  if (bEOF!=1)
   {
     CPLError( CE_Failure, CPLE_AppDefined,
               "Geoconcept config field end block %s not found.\n",
@@ -3412,13 +3382,13 @@ static OGRErr GCIOAPI_CALL _readConfigFieldSubType_GCIO (
                                                           GCSubType* theSubType
                                                         )
 {
-  int eof, res;
+  int bEOF;
   char *k, n[kItemSize_GCIO], x[kExtraSize_GCIO], e[kExtraSize_GCIO];
   long id;
   GCTypeKind knd;
   GCField* theField;
 
-  eof= 0;
+  bEOF= 0;
   n[0]= '\0';
   x[0]= '\0';
   e[0]= '\0';
@@ -3430,27 +3400,26 @@ static OGRErr GCIOAPI_CALL _readConfigFieldSubType_GCIO (
     {
       continue;
     }
+    /* coverity[mixed_enums] */ /* FIXME ? */
     if( (enum _tIO_MetadataType_GCIO)GetGCWhatIs_GCIO(hGCT) == vHeader_GCIO )
     {
       if( strstr(GetGCCache_GCIO(hGCT),kConfigEndField_GCIO)!=NULL)
       {
-        eof= 1;
+        bEOF= 1;
         if( n[0]=='\0' || id==UNDEFINEDID_GCIO || knd==vUnknownItemType_GCIO )
         {
           CPLError( CE_Failure, CPLE_AppDefined,
                     "Missing %s.\n",
                     n[0]=='\0'? "Name": id==UNDEFINEDID_GCIO? "ID": "Kind");
-          res= OGRERR_CORRUPT_DATA;
           goto onError;
         }
         if( (theField= AddSubTypeField_GCIO(hGCT,GetTypeName_GCIO(theClass),GetSubTypeName_GCIO(theSubType),-1,n,id,knd,x,e))==NULL )
         {
-          res= OGRERR_CORRUPT_DATA;
           goto onError;
         }
         break;
       }
-      res= OGRERR_NONE;
+
       if( (k= strstr(GetGCCache_GCIO(hGCT),kConfigName_GCIO))!=NULL )
       {
         if( n[0]!='\0' )
@@ -3458,7 +3427,6 @@ static OGRErr GCIOAPI_CALL _readConfigFieldSubType_GCIO (
           CPLError( CE_Failure, CPLE_AppDefined,
                     "Duplicate Name found : '%s'.\n",
                     GetGCCache_GCIO(hGCT));
-          res= OGRERR_CORRUPT_DATA;
           goto onError;
         }
         if( (k= _getHeaderValue_GCIO(k))==NULL )
@@ -3466,7 +3434,6 @@ static OGRErr GCIOAPI_CALL _readConfigFieldSubType_GCIO (
           CPLError( CE_Failure, CPLE_AppDefined,
                     "Invalid Name found : '%s'.\n",
                     GetGCCache_GCIO(hGCT));
-          res= OGRERR_CORRUPT_DATA;
           goto onError;
         }
         strncpy(n,k,kItemSize_GCIO-1), n[kItemSize_GCIO-1]= '\0';
@@ -3479,7 +3446,6 @@ static OGRErr GCIOAPI_CALL _readConfigFieldSubType_GCIO (
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Duplicate ID found : '%s'.\n",
                       GetGCCache_GCIO(hGCT));
-            res= OGRERR_CORRUPT_DATA;
             goto onError;
           }
           if( (k= _getHeaderValue_GCIO(k))==NULL )
@@ -3487,7 +3453,6 @@ static OGRErr GCIOAPI_CALL _readConfigFieldSubType_GCIO (
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Invalid ID found : '%s'.\n",
                       GetGCCache_GCIO(hGCT));
-            res= OGRERR_CORRUPT_DATA;
             goto onError;
           }
           if( sscanf(k,"%ld", &id)!=1 )
@@ -3495,7 +3460,6 @@ static OGRErr GCIOAPI_CALL _readConfigFieldSubType_GCIO (
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Invalid ID found : '%s'.\n",
                       GetGCCache_GCIO(hGCT));
-            res= OGRERR_CORRUPT_DATA;
             goto onError;
           }
         }
@@ -3507,7 +3471,6 @@ static OGRErr GCIOAPI_CALL _readConfigFieldSubType_GCIO (
               CPLError( CE_Failure, CPLE_AppDefined,
                         "Duplicate Kind found : '%s'.\n",
                         GetGCCache_GCIO(hGCT));
-              res= OGRERR_CORRUPT_DATA;
               goto onError;
             }
             if( (k= _getHeaderValue_GCIO(k))==NULL )
@@ -3515,7 +3478,6 @@ static OGRErr GCIOAPI_CALL _readConfigFieldSubType_GCIO (
               CPLError( CE_Failure, CPLE_AppDefined,
                         "Invalid Kind found : '%s'.\n",
                         GetGCCache_GCIO(hGCT));
-              res= OGRERR_CORRUPT_DATA;
               goto onError;
             }
             if( (knd= str2GCTypeKind_GCIO(k))==vUnknownItemType_GCIO )
@@ -3523,7 +3485,6 @@ static OGRErr GCIOAPI_CALL _readConfigFieldSubType_GCIO (
               CPLError( CE_Failure, CPLE_AppDefined,
                         "Not supported Kind found : '%s'.\n",
                         GetGCCache_GCIO(hGCT));
-              res= OGRERR_CORRUPT_DATA;
               goto onError;
             }
           }
@@ -3536,7 +3497,6 @@ static OGRErr GCIOAPI_CALL _readConfigFieldSubType_GCIO (
                 CPLError( CE_Failure, CPLE_AppDefined,
                           "Duplicate Extra information found : '%s'.\n",
                           GetGCCache_GCIO(hGCT));
-                res= OGRERR_CORRUPT_DATA;
                 goto onError;
               }
               if( (k= _getHeaderValue_GCIO(k))==NULL )
@@ -3544,7 +3504,6 @@ static OGRErr GCIOAPI_CALL _readConfigFieldSubType_GCIO (
                 CPLError( CE_Failure, CPLE_AppDefined,
                           "Invalid extra information found : '%s'.\n",
                           GetGCCache_GCIO(hGCT));
-                res= OGRERR_CORRUPT_DATA;
                 goto onError;
               }
               strncpy(x,k,kExtraSize_GCIO-1), x[kExtraSize_GCIO-1]= '\0';
@@ -3557,7 +3516,6 @@ static OGRErr GCIOAPI_CALL _readConfigFieldSubType_GCIO (
                   CPLError( CE_Failure, CPLE_AppDefined,
                             "Duplicate List found : '%s'.\n",
                             GetGCCache_GCIO(hGCT));
-                  res= OGRERR_CORRUPT_DATA;
                   goto onError;
                 }
                 if( (k= _getHeaderValue_GCIO(k))==NULL )
@@ -3565,25 +3523,20 @@ static OGRErr GCIOAPI_CALL _readConfigFieldSubType_GCIO (
                   CPLError( CE_Failure, CPLE_AppDefined,
                             "Invalid List found : '%s'.\n",
                             GetGCCache_GCIO(hGCT));
-                  res= OGRERR_CORRUPT_DATA;
                   goto onError;
                 }
                 strncpy(e,k,kExtraSize_GCIO-1), e[kExtraSize_GCIO-1]= '\0';
               }
               else
               { /* Skipping ... */
-                res= OGRERR_NONE;
               }
-      if( res != OGRERR_NONE )
-      {
-        goto onError;
-      }
+
       continue;
     }
 onError:
     return OGRERR_CORRUPT_DATA;
   }
-  if (eof!=1)
+  if (bEOF!=1)
   {
     CPLError( CE_Failure, CPLE_AppDefined,
               "Geoconcept config field end block %s not found.\n",
@@ -3618,6 +3571,7 @@ static OGRErr GCIOAPI_CALL _readConfigSubTypeType_GCIO (
     {
       continue;
     }
+    /* coverity[mixed_enums] */ /* FIXME ? */
     if( (enum _tIO_MetadataType_GCIO)GetGCWhatIs_GCIO(hGCT) == vHeader_GCIO )
     {
       if( strstr(GetGCCache_GCIO(hGCT),kConfigEndSubType_GCIO)!=NULL)
@@ -3633,7 +3587,6 @@ static OGRErr GCIOAPI_CALL _readConfigSubTypeType_GCIO (
           CPLError( CE_Failure, CPLE_AppDefined,
                     "Duplicate Name found : '%s'.\n",
                     GetGCCache_GCIO(hGCT));
-          res= OGRERR_CORRUPT_DATA;
           goto onError;
         }
         if( (k= _getHeaderValue_GCIO(k))==NULL )
@@ -3641,7 +3594,6 @@ static OGRErr GCIOAPI_CALL _readConfigSubTypeType_GCIO (
           CPLError( CE_Failure, CPLE_AppDefined,
                     "Invalid Name found : '%s'.\n",
                     GetGCCache_GCIO(hGCT));
-          res= OGRERR_CORRUPT_DATA;
           goto onError;
         }
         strncpy(n,k,kItemSize_GCIO-1), n[kItemSize_GCIO-1]= '\0';
@@ -3654,7 +3606,6 @@ static OGRErr GCIOAPI_CALL _readConfigSubTypeType_GCIO (
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Duplicate ID found : '%s'.\n",
                       GetGCCache_GCIO(hGCT));
-            res= OGRERR_CORRUPT_DATA;
             goto onError;
           }
           if( (k= _getHeaderValue_GCIO(k))==NULL )
@@ -3662,7 +3613,6 @@ static OGRErr GCIOAPI_CALL _readConfigSubTypeType_GCIO (
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Invalid ID found : '%s'.\n",
                       GetGCCache_GCIO(hGCT));
-            res= OGRERR_CORRUPT_DATA;
             goto onError;
           }
           if( sscanf(k,"%ld", &id)!=1 )
@@ -3670,7 +3620,6 @@ static OGRErr GCIOAPI_CALL _readConfigSubTypeType_GCIO (
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Invalid ID found : '%s'.\n",
                       GetGCCache_GCIO(hGCT));
-            res= OGRERR_CORRUPT_DATA;
             goto onError;
           }
         }
@@ -3682,7 +3631,6 @@ static OGRErr GCIOAPI_CALL _readConfigSubTypeType_GCIO (
               CPLError( CE_Failure, CPLE_AppDefined,
                         "Duplicate Kind found : '%s'.\n",
                         GetGCCache_GCIO(hGCT));
-              res= OGRERR_CORRUPT_DATA;
               goto onError;
             }
             if( (k= _getHeaderValue_GCIO(k))==NULL )
@@ -3690,7 +3638,6 @@ static OGRErr GCIOAPI_CALL _readConfigSubTypeType_GCIO (
               CPLError( CE_Failure, CPLE_AppDefined,
                         "Invalid Kind found : '%s'.\n",
                         GetGCCache_GCIO(hGCT));
-              res= OGRERR_CORRUPT_DATA;
               goto onError;
             }
             if( (knd= str2GCTypeKind_GCIO(k))==vUnknownItemType_GCIO )
@@ -3698,7 +3645,6 @@ static OGRErr GCIOAPI_CALL _readConfigSubTypeType_GCIO (
               CPLError( CE_Failure, CPLE_AppDefined,
                         "Not supported Kind found : '%s'.\n",
                         GetGCCache_GCIO(hGCT));
-              res= OGRERR_CORRUPT_DATA;
               goto onError;
             }
           }
@@ -3710,7 +3656,6 @@ static OGRErr GCIOAPI_CALL _readConfigSubTypeType_GCIO (
                 CPLError( CE_Failure, CPLE_AppDefined,
                           "Duplicate Dimension found : '%s'.\n",
                           GetGCCache_GCIO(hGCT));
-                res= OGRERR_CORRUPT_DATA;
                 goto onError;
               }
               if( (k= _getHeaderValue_GCIO(k))==NULL )
@@ -3718,7 +3663,6 @@ static OGRErr GCIOAPI_CALL _readConfigSubTypeType_GCIO (
                 CPLError( CE_Failure, CPLE_AppDefined,
                           "Invalid Dimension found : '%s'.\n",
                           GetGCCache_GCIO(hGCT));
-                res= OGRERR_CORRUPT_DATA;
                 goto onError;
               }
               if( (sys= str2GCDim(k))==vUnknown3D_GCIO )
@@ -3726,7 +3670,6 @@ static OGRErr GCIOAPI_CALL _readConfigSubTypeType_GCIO (
                 CPLError( CE_Failure, CPLE_AppDefined,
                           "Not supported Dimension found : '%s'.\n",
                           GetGCCache_GCIO(hGCT));
-                res= OGRERR_CORRUPT_DATA;
                 goto onError;
               }
             }
@@ -3740,12 +3683,10 @@ static OGRErr GCIOAPI_CALL _readConfigSubTypeType_GCIO (
                     CPLError( CE_Failure, CPLE_AppDefined,
                               "Missing %s.\n",
                               n[0]=='\0'? "Name": id==UNDEFINEDID_GCIO? "ID": knd==vUnknownItemType_GCIO? "Kind": "3D");
-                    res= OGRERR_CORRUPT_DATA;
                     goto onError;
                   }
                   if( (theSubType= AddSubType_GCIO(hGCT,GetTypeName_GCIO(theClass),n,id,knd,sys))==NULL )
                   {
-                    res= OGRERR_CORRUPT_DATA;
                     goto onError;
                   }
                 }
@@ -3802,6 +3743,7 @@ static OGRErr GCIOAPI_CALL _readConfigType_GCIO (
     {
       continue;
     }
+    /* coverity[mixed_enums] */ /* FIXME ? */
     if( (enum _tIO_MetadataType_GCIO)GetGCWhatIs_GCIO(hGCT) == vHeader_GCIO )
     {
       if( strstr(GetGCCache_GCIO(hGCT),kConfigEndType_GCIO)!=NULL )
@@ -3817,7 +3759,6 @@ static OGRErr GCIOAPI_CALL _readConfigType_GCIO (
           CPLError( CE_Failure, CPLE_AppDefined,
                     "Duplicate Name found : '%s'.\n",
                     GetGCCache_GCIO(hGCT));
-          res= OGRERR_CORRUPT_DATA;
           goto onError;
         }
         if( (k= _getHeaderValue_GCIO(k))==NULL )
@@ -3825,7 +3766,6 @@ static OGRErr GCIOAPI_CALL _readConfigType_GCIO (
           CPLError( CE_Failure, CPLE_AppDefined,
                     "Invalid Name found : '%s'.\n",
                     GetGCCache_GCIO(hGCT));
-          res= OGRERR_CORRUPT_DATA;
           goto onError;
         }
         strncpy(n,k,kItemSize_GCIO-1), n[kItemSize_GCIO-1]= '\0';
@@ -3838,7 +3778,6 @@ static OGRErr GCIOAPI_CALL _readConfigType_GCIO (
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Duplicate ID found : '%s'.\n",
                       GetGCCache_GCIO(hGCT));
-            res= OGRERR_CORRUPT_DATA;
             goto onError;
           }
           if( (k= _getHeaderValue_GCIO(k))==NULL )
@@ -3846,7 +3785,6 @@ static OGRErr GCIOAPI_CALL _readConfigType_GCIO (
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Invalid ID found : '%s'.\n",
                       GetGCCache_GCIO(hGCT));
-            res= OGRERR_CORRUPT_DATA;
             goto onError;
           }
           if( sscanf(k,"%ld", &id)!=1 )
@@ -3854,7 +3792,6 @@ static OGRErr GCIOAPI_CALL _readConfigType_GCIO (
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Not supported ID found : '%s'.\n",
                       GetGCCache_GCIO(hGCT));
-            res= OGRERR_CORRUPT_DATA;
             goto onError;
           }
         }
@@ -3865,7 +3802,6 @@ static OGRErr GCIOAPI_CALL _readConfigType_GCIO (
             {
               if( n[0]=='\0' || id==UNDEFINEDID_GCIO || (theClass= AddType_GCIO(hGCT,n,id))==NULL )
               {
-                res= OGRERR_CORRUPT_DATA;
                 goto onError;
               }
             }
@@ -3878,7 +3814,6 @@ static OGRErr GCIOAPI_CALL _readConfigType_GCIO (
               {
                 if( n[0]=='\0' || id==UNDEFINEDID_GCIO || (theClass= AddType_GCIO(hGCT,n,id))==NULL )
                 {
-                  res= OGRERR_CORRUPT_DATA;
                   goto onError;
                 }
               }
@@ -3921,7 +3856,7 @@ static OGRErr GCIOAPI_CALL _readConfigMap_GCIO (
                                                  GCExportFileH* hGCT
                                                )
 {
-  int eom, res;
+  int eom;
   char* k;
 
   eom= 0;
@@ -3930,6 +3865,7 @@ static OGRErr GCIOAPI_CALL _readConfigMap_GCIO (
     {
       continue;
     }
+    /* coverity[mixed_enums] */ /* FIXME ? */
     if( (enum _tIO_MetadataType_GCIO)GetGCWhatIs_GCIO(hGCT) == vHeader_GCIO )
     {
       if( strstr(GetGCCache_GCIO(hGCT),kConfigEndMap_GCIO)!=NULL )
@@ -3937,7 +3873,7 @@ static OGRErr GCIOAPI_CALL _readConfigMap_GCIO (
         eom= 1;
         break;
       }
-      res= OGRERR_NONE;
+
       if( (k= strstr(GetGCCache_GCIO(hGCT),kConfigUnit_GCIO))!=NULL &&
           strstr(GetGCCache_GCIO(hGCT),kConfigZUnit_GCIO)==NULL )
       {
@@ -3946,7 +3882,6 @@ static OGRErr GCIOAPI_CALL _readConfigMap_GCIO (
           CPLError( CE_Failure, CPLE_AppDefined,
                     "Invalid Unit found : '%s'.\n",
                     GetGCCache_GCIO(hGCT));
-          res= OGRERR_CORRUPT_DATA;
           goto onError;
         }
         SetMetaUnit_GCIO(GetGCMeta_GCIO(hGCT),k);
@@ -3961,7 +3896,6 @@ static OGRErr GCIOAPI_CALL _readConfigMap_GCIO (
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Invalid Precision found : '%s'.\n",
                       GetGCCache_GCIO(hGCT));
-            res= OGRERR_CORRUPT_DATA;
             goto onError;
           }
           if( CPLsscanf(k,"%lf", &r)!=1 )
@@ -3969,19 +3903,14 @@ static OGRErr GCIOAPI_CALL _readConfigMap_GCIO (
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Invalid Precision found : '%s'.\n",
                       GetGCCache_GCIO(hGCT));
-            res= OGRERR_CORRUPT_DATA;
             goto onError;
           }
           SetMetaResolution_GCIO(GetGCMeta_GCIO(hGCT),r);
         }
         else
         { /* Skipping ... */
-          res= OGRERR_NONE;
         }
-      if( res != OGRERR_NONE )
-      {
-        goto onError;
-      }
+
       continue;
     }
 onError:
@@ -4038,6 +3967,7 @@ GCExportFileMetadata GCIOAPI_CALL1(*) ReadConfig_GCIO (
     {
       continue;
     }
+    /* coverity[mixed_enums] */ /* FIXME ? */
     if( (enum _tIO_MetadataType_GCIO)GetGCWhatIs_GCIO(hGCT) == vHeader_GCIO )
     {
       if( strstr(GetGCCache_GCIO(hGCT),kConfigEndConfig_GCIO)!=NULL )
@@ -4045,25 +3975,25 @@ GCExportFileMetadata GCIOAPI_CALL1(*) ReadConfig_GCIO (
         eoc= 1;
         break;
       }
-      res= OGRERR_NONE;
+
       if( strstr(GetGCCache_GCIO(hGCT),kConfigBeginMap_GCIO)!=NULL )
       {
         res= _readConfigMap_GCIO(hGCT);
       }
       else
-        if( strstr(GetGCCache_GCIO(hGCT),kConfigBeginType_GCIO)!=NULL )
-        {
-          res= _readConfigType_GCIO(hGCT);
-        }
-        else
-          if( strstr(GetGCCache_GCIO(hGCT),kConfigBeginField_GCIO)!=NULL )
-          {
-            res= _readConfigField_GCIO(hGCT);
-          }
-          else
-          { /* Skipping : Version, Origin, ... */
-            res= OGRERR_NONE;
-          }
+      if( strstr(GetGCCache_GCIO(hGCT),kConfigBeginType_GCIO)!=NULL )
+      {
+        res= _readConfigType_GCIO(hGCT);
+      }
+      else
+      if( strstr(GetGCCache_GCIO(hGCT),kConfigBeginField_GCIO)!=NULL )
+      {
+        res= _readConfigField_GCIO(hGCT);
+      }
+      else
+      { /* Skipping : Version, Origin, ... */
+        res= OGRERR_NONE;
+      }
       if( res != OGRERR_NONE )
       {
         goto onError;
@@ -4112,7 +4042,7 @@ onError:
               {
                 v= CSLGetField(GetFieldList_GCIO(theField),il);
                 snprintf(l+ll,kExtraSize_GCIO-ll-1,"%s;", v), l[kExtraSize_GCIO-1]= '\0';
-                ll+= strlen(v);
+                ll+= (int)strlen(v);
               }
             }
             for (it= 0; it<nt; it++)
@@ -4206,7 +4136,7 @@ onError:
                         {
                           v= CSLGetField(GetFieldList_GCIO(theField),il);
                           snprintf(l+ll,kExtraSize_GCIO-ll-1,"%s;", v), l[kExtraSize_GCIO-1]= '\0';
-                          ll+= strlen(v);
+                          ll+= (int)strlen(v);
                         }
                       }
                       if( AddSubTypeField_GCIO(hGCT,GetTypeName_GCIO(theClass),
@@ -4603,6 +4533,7 @@ GCExportFileMetadata GCIOAPI_CALL1(*) ReadHeader_GCIO (
     {
       continue;
     }
+    /* coverity[mixed_enums] */ /* FIXME ? */
     if( (enum _tIO_MetadataType_GCIO)GetGCWhatIs_GCIO(hGXT)==vPragma_GCIO )
     {
       /* try config header first ... */
@@ -4658,7 +4589,7 @@ GCExportFileMetadata GCIOAPI_CALL1(*) ReadHeader_GCIO (
 }/* ReadHeader_GCIO */
 
 /* -------------------------------------------------------------------- */
-GCSubType GCIOAPI_CALL1(*) FindFeature_GCIO ( 
+GCSubType GCIOAPI_CALL1(*) FindFeature_GCIO (
                                               GCExportFileH* hGCT,
                                               const char* typDOTsubtypName
                                             )
@@ -4727,7 +4658,7 @@ static char GCIOAPI_CALL1(*) _escapeString_GCIO (
   int l, i, o;
   char *res;
   if( !theString ||
-      (l= strlen(theString))==0 )
+      (l= (int)strlen(theString))==0 )
   {
     res= CPLStrdup(theString);
     return res;
@@ -4768,7 +4699,8 @@ static int GCIOAPI_CALL _findNextFeatureFieldToWrite_GCIO (
   FILE *h;
   int n, i;
   GCField* theField;
-  char* fieldName, *quotes, *escapedValue, delim;
+  char* fieldName, *escapedValue, delim;
+  const char *quotes;
 
   if( (n= CountSubTypeFields_GCIO(theSubType))==0 )
   {
@@ -4850,6 +4782,7 @@ static int GCIOAPI_CALL _findNextFeatureFieldToWrite_GCIO (
       if( VSIFPrintf(h,"%s%s%s", quotes, escapedValue, quotes)<=0 )
       {
         CPLError( CE_Failure, CPLE_AppDefined, "Write failed.\n");
+        CPLFree(escapedValue);
         return WRITEERROR_GCIO;
       }
       CPLFree(escapedValue);
@@ -4863,6 +4796,7 @@ static int GCIOAPI_CALL _findNextFeatureFieldToWrite_GCIO (
       if( VSIFPrintf(h,"%s%s%s", quotes, escapedValue, quotes)<=0 )
       {
         CPLError( CE_Failure, CPLE_AppDefined, "Write failed.\n");
+        CPLFree(escapedValue);
         return WRITEERROR_GCIO;
       }
       CPLFree(escapedValue);
@@ -4876,6 +4810,7 @@ static int GCIOAPI_CALL _findNextFeatureFieldToWrite_GCIO (
       if( VSIFPrintf(h,"%s%s%s", quotes, escapedValue, quotes)<=0 )
       {
         CPLError( CE_Failure, CPLE_AppDefined, "Write failed.\n");
+        CPLFree(escapedValue);
         return WRITEERROR_GCIO;
       }
       CPLFree(escapedValue);
@@ -5130,13 +5065,13 @@ int GCIOAPI_CALL WriteFeatureGeometry_GCIO (
   GCExportFileH* H;
   FILE *h;
   int n, i, iAn, pCS, hCS;
-  char *quotes, delim;
+  const char *quotes;
+  char delim;
 
   H= GetSubTypeGCHandle_GCIO(theSubType);
   h= GetGCHandle_GCIO(H);
   n= CountSubTypeFields_GCIO(theSubType);
   iAn= -1;
-  pCS= hCS= 0;
   if( (i= _findFieldByName_GCIO(GetSubTypeFields_GCIO(theSubType),kGraphics_GCIO))==-1 )
   {
     if( (i= _findFieldByName_GCIO(GetSubTypeFields_GCIO(theSubType),kAngle_GCIO))==-1 )
@@ -5172,6 +5107,7 @@ int GCIOAPI_CALL WriteFeatureGeometry_GCIO (
     SetMetaPlanarFormat_GCIO(GetGCMeta_GCIO(H), pCS);
   }
 
+  hCS= 0;
   if (GetSubTypeDim_GCIO(theSubType)==v3D_GCIO &&
       (hCS= GetMetaHeightFormat_GCIO(GetGCMeta_GCIO(H)))==0 )
   {
@@ -5268,7 +5204,8 @@ int GCIOAPI_CALL WriteFeatureFieldAsString_GCIO (
   GCExportFileH* H;
   FILE *h;
   int n;
-  char *quotes, *escapedValue, delim;
+  const char *quotes;
+  char *escapedValue, delim;
   GCField* theField;
 
   H= GetSubTypeGCHandle_GCIO(theSubType);
@@ -5302,6 +5239,7 @@ int GCIOAPI_CALL WriteFeatureFieldAsString_GCIO (
     if( *quotes!='\0' || *escapedValue!='\0')
     {
       CPLError( CE_Failure, CPLE_AppDefined, "Write failed.\n");
+      CPLFree(escapedValue);
       return WRITEERROR_GCIO;
     }
   }
@@ -5310,6 +5248,7 @@ int GCIOAPI_CALL WriteFeatureFieldAsString_GCIO (
     if( VSIFPrintf(h,"%c", delim)<=0 )
     {
       CPLError( CE_Failure, CPLE_AppDefined, "Write failed.\n");
+      CPLFree(escapedValue);
       return WRITEERROR_GCIO;
     }
   }
@@ -5359,6 +5298,7 @@ OGRFeatureH GCIOAPI_CALL ReadNextFeature_GCIO (
       continue;
     }
     /* analyze the line according to schema : */
+    /* coverity[mixed_enums] */ /* FIXME ? */
     if( (enum _tIO_MetadataType_GCIO)GetGCWhatIs_GCIO(H) == vPragma_GCIO )
     {
       if( strstr(GetGCCache_GCIO(H),k3DOBJECTMONO_GCIO) )
diff --git a/ogr/ogrsf_frmts/geoconcept/geoconcept.h b/ogr/ogrsf_frmts/geoconcept/geoconcept.h
index 07153e7..f26941b 100644
--- a/ogr/ogrsf_frmts/geoconcept/geoconcept.h
+++ b/ogr/ogrsf_frmts/geoconcept/geoconcept.h
@@ -28,8 +28,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************/
-#ifndef _GEOCONCEPT_H_INCLUDED
-#define _GEOCONCEPT_H_INCLUDED
+#ifndef GEOCONCEPT_H_INCLUDED
+#define GEOCONCEPT_H_INCLUDED
 
 #include "cpl_port.h"
 #include "cpl_list.h"
@@ -335,7 +335,7 @@ GCField GCIOAPI_CALL1(*) AddTypeField_GCIO ( GCExportFileH* H, const char* typNa
 GCField GCIOAPI_CALL1(*) AddSubTypeField_GCIO ( GCExportFileH* H, const char* typName, const char* subtypName, int where, const char* name, long id, GCTypeKind knd, const char* extra, const char* enums );
 GCExportFileMetadata GCIOAPI_CALL1(*) ReadConfig_GCIO ( GCExportFileH* H );
 GCExportFileH GCIOAPI_CALL1(*) WriteHeader_GCIO ( GCExportFileH* H );
-GCExportFileMetadata GCIOAPI_CALL1(*) CreateHeader_GCIO ( );
+GCExportFileMetadata GCIOAPI_CALL1(*) CreateHeader_GCIO ( void );
 void GCIOAPI_CALL DestroyHeader_GCIO ( GCExportFileMetadata** m );
 GCExtent GCIOAPI_CALL1(*) CreateExtent_GCIO ( double Xmin, double Ymin, double Xmax, double Ymax );
 void GCIOAPI_CALL DestroyExtent_GCIO ( GCExtent** theExtent );
@@ -497,4 +497,4 @@ OGRFeatureH GCIOAPI_CALL ReadNextFeature_GCIO ( GCSubType* theSubType );
 #endif
 
 
-#endif /* ndef _GEOCONCEPT_H_INCLUDED */
+#endif /* ndef GEOCONCEPT_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/geoconcept/geoconcept_syscoord.c b/ogr/ogrsf_frmts/geoconcept/geoconcept_syscoord.c
index c749ac9..4ada5d0 100644
--- a/ogr/ogrsf_frmts/geoconcept/geoconcept_syscoord.c
+++ b/ogr/ogrsf_frmts/geoconcept/geoconcept_syscoord.c
@@ -35,11 +35,6 @@
 
 CPL_CVSID("$Id: geoconcept_syscoord.c,v 1.0.0 2007-12-24 15:40:28 drichard Exp $")
 
-#ifndef PI
-#define PI 3.14159265358979323846
-#endif
-
-
 /* -------------------------------------------------------------------- */
 /*      GCSRS globals                                                   */
 /* -------------------------------------------------------------------- */
@@ -51,7 +46,7 @@ CPL_CVSID("$Id: geoconcept_syscoord.c,v 1.0.0 2007-12-24 15:40:28 drichard Exp $
  * noticed as FIXME in the source.
  */
 
-static GCSysCoord gk_asSysCoordList[]=
+static const GCSysCoord gk_asSysCoordList[]=
 /*
  * pszSysCoordName, pszUnit, dfPM, dfLambda0, dfPhi0, dfk0, dfX0, dfY0, dfPhi1, dfPhi2, nDatumID, nProjID, coordSystemID, timeZoneValue
  *
@@ -67,13 +62,13 @@ static GCSysCoord gk_asSysCoordList[]=
 {"Lambert 4",                       NULL,  2.337229166667,   0.000000000, 42.16500000,0.99994471000,    234.358,  185861.369,  0.0,  0.0,  13,   2,    5,-1},
 {"Bonne NTF",                       NULL,  2.337222222222,   0.000000000, 48.86000000,1.00000000000,      0.000,       0.000,  0.0,  0.0,   1,   3,   11,-1},
 {"UTM Nord - ED50",                 NULL,  0.000000000000,   0.000000000,  0.00000000,0.99960000000, 500000.000,       0.000,  0.0,  0.0,  14,   1,   12, 0},
-{"Plate carr�e",                    NULL,  0.000000000000,   0.000000000,  0.00000000,0.00000000000,      0.000,       0.000,  0.0,  0.0,  11,   4,   13,-1},
+{"Plate carr""\xe9""e",                    NULL,  0.000000000000,   0.000000000,  0.00000000,0.00000000000,      0.000,       0.000,  0.0,  0.0,  11,   4,   13,-1},
 {"MGRS (Military UTM)",             NULL,  0.000000000000,   0.000000000,  0.00000000,0.99960000000,      0.000,       0.000,  0.0,  0.0,   4,  11,   14,-1},
 {"UTM Sud - WGS84",                 NULL,  0.000000000000,   0.000000000,  0.00000000,0.99960000000, 500000.000,10000000.000,  0.0,  0.0,   4,   1,   15, 0},
 {"National GB projection",          NULL,  0.000000000000,  -2.000000000, 49.00000000,0.99960127170, 400000.000, -100000.000,  0.0,  0.0,  12,  12,   16,-1},
 {"UTM Nord - WGS84",                NULL,  0.000000000000,   0.000000000,  0.00000000,0.99960000000, 500000.000,       0.000,  0.0,  0.0,   4,   1,   17, 0},
 {"UTM Nord - WGS84",                NULL,  0.000000000000,   0.000000000,  0.00000000,0.99960000000, 500000.000,       0.000,  0.0,  0.0,9990,   1,   17, 0},
-{"Lambert 2 �tendu - sans grille",  NULL,  2.337229166667,   0.000000000, 46.80000000,0.99987742000, 600000.000, 2200000.000,  0.0,  0.0,   1,   2,   91,-1},
+{"Lambert 2 ""\xe9""tendu - sans grille",  NULL,  2.337229166667,   0.000000000, 46.80000000,0.99987742000, 600000.000, 2200000.000,  0.0,  0.0,   1,   2,   91,-1},
 {"Lambert 1 - sans grille",         NULL,  2.337229166667,   0.000000000, 49.50000000,0.99987734000, 600000.000,  200000.000,  0.0,  0.0,   1,   2,   92,-1},
 {"Lambert 2 - sans grille",         NULL,  2.337229166667,   0.000000000, 46.80000000,0.99987742000, 600000.000,  200000.000,  0.0,  0.0,   1,   2,   93,-1},
 {"Lambert 3 - sans grille",         NULL,  2.337229166667,   0.000000000, 44.10000000,0.99987750000, 600000.000,  200000.000,  0.0,  0.0,   1,   2,   94,-1},
@@ -123,7 +118,7 @@ static GCSysCoord gk_asSysCoordList[]=
 {"Geoportail Nouvelle Caledonie",   NULL,  0.000000000000,   0.000000000,  0.00000000,0.92718385456,      0.000,       0.000,-22.0,  0.0,9984,  26, 2021,-1},
 {"Geoportail Wallis",               NULL,  0.000000000000,   0.000000000,  0.00000000,0.97029572627,      0.000,       0.000,-14.0,  0.0,9984,  26, 2022,-1},
 {"Geoportail Polynesie",            NULL,  0.000000000000,   0.000000000,  0.00000000,0.96592582628,      0.000,       0.000,-15.0,  0.0,9984,  26, 2023,-1},
-{"Mercator sur sph�re WGS84",       NULL,  0.000000000000,   0.000000000,  0.00000000,1.00000000000,      0.000,       0.000,  0.0,  0.0,2015,  21, 2027,-1},
+{"Mercator sur sph""\xe8""re WGS84",       NULL,  0.000000000000,   0.000000000,  0.00000000,1.00000000000,      0.000,       0.000,  0.0,  0.0,2015,  21, 2027,-1},
 {"(Long/Lat) RGF 93",                "d",  0.000000000000,   0.000000000,  0.00000000,0.00000000000,      0.000,       0.000,  0.0,  0.0,  13,   0, 2028,-1},
 {"(Long/Lat) ITRS-89",               "d",  0.000000000000,   0.000000000,  0.00000000,0.00000000000,      0.000,       0.000,  0.0,  0.0,9984,   0, 2028,-1},
 {"Geoportail Crozet",               NULL,  0.000000000000,   0.000000000,  0.00000000,0.69465837046,      0.000,       0.000,-46.0,  0.0,9984,  26, 2040,-1},/* FIXME : wrong scale factor was 0.69088241108 */
@@ -151,7 +146,7 @@ static GCSysCoord gk_asSysCoordList[]=
 {NULL,                              NULL,  0.000000000000,   0.000000000,  0.00000000,0.00000000000,      0.000,       0.000,  0.0,  0.0,  -1,  -1,   -1,-1}
 };
 
-static GCProjectionInfo gk_asProjList[]=
+static const GCProjectionInfo gk_asProjList[]=
 /*
  * pszProjName, nSphere, nProjID
  */
@@ -160,7 +155,7 @@ static GCProjectionInfo gk_asProjList[]=
 {"UTM",                     0,    1},
 {"Lambert Conform Conic",   0,    2},
 {"Bonne",                   0,    3},
-{"Plate carr�e",            0,    4},
+{"Plate carr""\xe9""e",            0,    4},
 {"MGRS (Military UTM)",     0,   11},
 {"Transversal Mercator",    0,   12},
 {"Lambert secant",          0,   18},
@@ -175,7 +170,7 @@ static GCProjectionInfo gk_asProjList[]=
 {NULL,                      0,   -1}
 };
 
-static GCDatumInfo gk_asDatumList[]=
+static const GCDatumInfo gk_asDatumList[]=
   /*
    * pszDatumName, dfShiftX, dfShiftY, dfShiftZ, dfRotX, dfRotY, dfRotZ, dfScaleFactor, dfFA, dfFlattening, nEllipsoidID, nDatumID
    */
@@ -229,7 +224,7 @@ static GCDatumInfo gk_asDatumList[]=
 {NULL,                                 0.0000,   0.0000,   0.0000, 0.00000, 0.00000,  0.00000,  0.0,          0.000,  0.0,            -1,  -1}
 };
 
-static GCSpheroidInfo gk_asSpheroidList[]=
+static const GCSpheroidInfo gk_asSpheroidList[]=
   /*
    * pszSpheroidName, dfA, dfE, nEllipsoidID
    *
@@ -238,8 +233,8 @@ static GCSpheroidInfo gk_asSpheroidList[]=
 {
 {"Sphere",                     6378137.0000, 0.00000000000000,   1},
 {"Clarke 1866",                6378206.4000, 0.08227185423947,   2},/* Wrong, semi-major was 6378249.4000     */
-{"Clarke 1880",                6378249.2000, 0.08248325676300,   3},/* Wrong, excentricity was 0.082483256945 */
-{"GRS 80",                     6378137.0000, 0.08181919104300,   4},/* Wrong, excentricity was 0.081819191060 */
+{"Clarke 1880",                6378249.2000, 0.08248325676300,   3},/* Wrong, eccentricity was 0.082483256945 */
+{"GRS 80",                     6378137.0000, 0.08181919104300,   4},/* Wrong, eccentricity was 0.081819191060 */
 {"International 1909",         6378388.0000, 0.08199188997900,   5},
 {"WGS 72",                     6378135.0000, 0.08181881201777,   6},
 {"Australian National",        6378160.0000, 0.08182017998700,   7},
@@ -257,7 +252,7 @@ static GCSpheroidInfo gk_asSpheroidList[]=
 static int GCSRSAPI_CALL _areCompatibleSpheroids_GCSRS ( int id1, int id2 )
 {
   if( id1==id2 ) return TRUE;
- 
+
   switch( id1 )
   {
     case    4 :
@@ -282,7 +277,7 @@ static int GCSRSAPI_CALL _areCompatibleSpheroids_GCSRS ( int id1, int id2 )
 static int GCSRSAPI_CALL _areCompatibleDatums_GCSRS ( int id1, int id2 )
 {
   if( id1==id2 ) return TRUE;
- 
+
   switch( id1 )
   {
     case    1 : /* NTF */
@@ -363,17 +358,17 @@ static int GCSRSAPI_CALL _areCompatibleDatums_GCSRS ( int id1, int id2 )
   return FALSE;
 }/* _areCompatibleDatums_GCSRS */
 
-#define _CPLDebugSpheroid_GCSRS(e) \
-CPLDebug( "GEOCONCEPT", "SemiMajor:%.4f;Excentricity:%.10f;",\
+#define CPLDebugSpheroid_GCSRS(e) \
+CPLDebug( "GEOCONCEPT", "SemiMajor:%.4f;Eccentricity:%.10f;",\
           GetInfoSpheroidSemiMajor_GCSRS(e),\
           GetInfoSpheroidExcentricity_GCSRS(e)\
 );
 
 /* -------------------------------------------------------------------- */
-static GCSpheroidInfo GCSRSAPI_CALL1(*) _findSpheroid_GCSRS ( double a, double rf )
+static const GCSpheroidInfo GCSRSAPI_CALL1(*) _findSpheroid_GCSRS ( double a, double rf )
 {
   int iSpheroid, iResol= 0, nResol= 2;
-  GCSpheroidInfo* ell;
+  const GCSpheroidInfo* ell;
   double e, p[]= {1e-10, 1e-8};
 
   /* f = 1 - sqrt(1 - e^2) */
@@ -397,7 +392,7 @@ ell_relax:
   return ell;
 }/* _findSpheroid_GCSRS */
 
-#define _CPLDebugDatum_GCSRS(d) \
+#define CPLDebugDatum_GCSRS(d) \
 CPLDebug( "GEOCONCEPT", "ID:%d;ShiftX:%.4f;ShiftY:%.4f;ShiftZ:%.4f;DiffA:%.4f;DiffFlattening:%.7f;",\
   GetInfoDatumID_GCSRS((d)),\
   GetInfoDatumShiftX_GCSRS((d)),\
@@ -408,14 +403,14 @@ CPLDebug( "GEOCONCEPT", "ID:%d;ShiftX:%.4f;ShiftY:%.4f;ShiftZ:%.4f;DiffA:%.4f;Di
 );
 
 /* -------------------------------------------------------------------- */
-static GCDatumInfo GCSRSAPI_CALL1(*) _findDatum_GCSRS ( double dx,
+static const GCDatumInfo GCSRSAPI_CALL1(*) _findDatum_GCSRS ( double dx,
                                                         double dy,
                                                         double dz,
                                                         double a,
                                                         double f )
 {
   int iDatum, bRelax= FALSE;
-  GCDatumInfo* datum;
+  const GCDatumInfo* datum;
 
 datum_relax:
   for( iDatum= 0, datum= &(gk_asDatumList[0]);
@@ -436,7 +431,7 @@ datum_relax:
   {
     /*
      * FIXME : when both nadgrids and towgs84 are defined, bursa-wolf parameters are lost !
-     *         if the projection and the ellipsoid are known, one can retrieve the datum 
+     *         if the projection and the ellipsoid are known, one can retrieve the datum
      *         Try relaxed search ...
      */
     bRelax= TRUE;
@@ -447,10 +442,10 @@ datum_relax:
 }/* _findDatum_GCSRS */
 
 /* -------------------------------------------------------------------- */
-static GCProjectionInfo GCSRSAPI_CALL1(*) _findProjection_GCSRS ( const char* p, double lat_ts )
+static const GCProjectionInfo GCSRSAPI_CALL1(*) _findProjection_GCSRS ( const char* p, double lat_ts )
 {
   int iProj;
-  GCProjectionInfo* proj;
+  const GCProjectionInfo* proj;
 
   for( iProj= 0, proj= &(gk_asProjList[0]);
        GetInfoProjID_GCSRS(proj)!=-1;
@@ -458,7 +453,7 @@ static GCProjectionInfo GCSRSAPI_CALL1(*) _findProjection_GCSRS ( const char* p,
   {
     if( iProj==0 && p==NULL)
       break;
-    if( iProj==1 && 
+    if( iProj==1 &&
         ( EQUAL(p,SRS_PT_TRANSVERSE_MERCATOR)               ||
           EQUAL(p,SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED) ) )
       break;
@@ -512,7 +507,7 @@ static GCProjectionInfo GCSRSAPI_CALL1(*) _findProjection_GCSRS ( const char* p,
   return proj;
 }/* _findProjection_GCSRS */
 
-#define _CPLDebugSysCoord_GCSRS(m,s) \
+#define CPLDebugSysCoord_GCSRS(m,s) \
 CPLDebug( "GEOCONCEPT", "[%s]ID=%d;Zone=%d;DatumID=%d;ProjID=%d;PrimeMeridian=%.10f;CentralMeridian=%.10f;LatitudeOfOrigin=%.10f;StandardParallel1=%.10f;StandardParallel2=%.10f;ScaleFactor=%.10f;FalseEasting=%.10f;FalseNorthing=%.10f;",\
           (m)? (m):"",\
           GetSysCoordSystemID_GCSRS((s)),\
@@ -533,13 +528,13 @@ CPLDebug( "GEOCONCEPT", "[%s]ID=%d;Zone=%d;DatumID=%d;ProjID=%d;PrimeMeridian=%.
 static GCSysCoord GCSRSAPI_CALL1(*) _findSysCoord_GCSRS ( GCSysCoord* theSysCoord )
 {
   int iSysCoord, bestSysCoord= -1;
-  GCSysCoord* gcsc;
+  const GCSysCoord* gcsc;
 
   if( !theSysCoord) return NULL;
 
   SetSysCoordSystemID_GCSRS(theSysCoord, -1);
   SetSysCoordTimeZone_GCSRS(theSysCoord, -1);
-  _CPLDebugSysCoord_GCSRS(NULL,theSysCoord);
+  CPLDebugSysCoord_GCSRS(NULL,theSysCoord);
   for( iSysCoord= 0, gcsc= &(gk_asSysCoordList[0]);
        GetSysCoordSystemID_GCSRS(gcsc)!=-1;
        iSysCoord++, gcsc= &(gk_asSysCoordList[iSysCoord]) )
@@ -554,7 +549,7 @@ static GCSysCoord GCSRSAPI_CALL1(*) _findSysCoord_GCSRS ( GCSysCoord* theSysCoor
     {
       switch( GetSysCoordProjID_GCSRS(gcsc) )
       {
-        case    1 :/* UTM familly : central meridian is the 6* zone - 183 (in degrees) */
+        case    1 : /* UTM family: central meridian is the 6* zone - 183 (in degrees) */
           if( GetSysCoordCentralMeridian_GCSRS(gcsc)==0.0 ) /* generic UTM definition */
           {
             break;
@@ -589,7 +584,7 @@ static GCSysCoord GCSRSAPI_CALL1(*) _findSysCoord_GCSRS ( GCSysCoord* theSysCoor
             bestSysCoord= iSysCoord;
           }
           break;
-        case    1:/* UTM familly : central meridian is the 6* zone - 183 (in degrees) */
+        case    1: /* UTM family: central meridian is the 6* zone - 183 (in degrees) */
           if( GetSysCoordCentralMeridian_GCSRS(gcsc)!=0.0 &&
               GetSysCoordDatumID_GCSRS(gcsc)==GetSysCoordDatumID_GCSRS(theSysCoord) &&
               GetSysCoordDatumID_GCSRS(&(gk_asSysCoordList[bestSysCoord]))!=GetSysCoordDatumID_GCSRS(theSysCoord)) /* exact match */
@@ -617,9 +612,9 @@ static GCSysCoord GCSRSAPI_CALL1(*) _findSysCoord_GCSRS ( GCSysCoord* theSysCoor
     }
     SetSysCoordTimeZone_GCSRS(theSysCoord, GetSysCoordTimeZone_GCSRS(gcsc));
     if( GetSysCoordName_GCSRS(gcsc) )
-      SetSysCoordName_GCSRS(theSysCoord, CPLStrdup(GetSysCoordName_GCSRS(gcsc)));
+      SetSysCoordName_GCSRS(theSysCoord, GetSysCoordName_GCSRS(gcsc));
     if( GetSysCoordUnit_GCSRS(gcsc) )
-      SetSysCoordUnit_GCSRS(theSysCoord, CPLStrdup(GetSysCoordUnit_GCSRS(gcsc)));
+      SetSysCoordUnit_GCSRS(theSysCoord, GetSysCoordUnit_GCSRS(gcsc));
   }
 
   return theSysCoord;
@@ -649,17 +644,15 @@ static void GCSRSAPI_CALL _InitSysCoord_GCSRS (
 /* -------------------------------------------------------------------- */
 GCSysCoord GCSRSAPI_CALL1(*) CreateSysCoord_GCSRS (
                                                     int srsid,
-                                                    int timezone
+                                                    int nTimezone
                                                   )
 {
   int iSysCoord;
-  GCSysCoord* theSysCoord, *gcsc;
+  GCSysCoord* theSysCoord;
+  const GCSysCoord* gcsc;
 
-  if( !(theSysCoord= CPLMalloc(sizeof(GCSysCoord))) )
+  if( !(theSysCoord= VSI_MALLOC_VERBOSE(sizeof(GCSysCoord))) )
   {
-    CPLError( CE_Failure, CPLE_OutOfMemory,
-              "failed to create a Geoconcept coordinate system.\n"
-              );
     return NULL;
   }
   _InitSysCoord_GCSRS(theSysCoord);
@@ -672,11 +665,11 @@ GCSysCoord GCSRSAPI_CALL1(*) CreateSysCoord_GCSRS (
       if( srsid==GetSysCoordSystemID_GCSRS(gcsc) )
       {
         SetSysCoordSystemID_GCSRS(theSysCoord, srsid);
-        SetSysCoordTimeZone_GCSRS(theSysCoord, timezone);
+        SetSysCoordTimeZone_GCSRS(theSysCoord, nTimezone);
         if( GetSysCoordName_GCSRS(gcsc) )
-          SetSysCoordName_GCSRS(theSysCoord, CPLStrdup(GetSysCoordName_GCSRS(gcsc)));
+          SetSysCoordName_GCSRS(theSysCoord, GetSysCoordName_GCSRS(gcsc));
         if( GetSysCoordUnit_GCSRS(gcsc) )
-          SetSysCoordUnit_GCSRS(theSysCoord, CPLStrdup(GetSysCoordUnit_GCSRS(gcsc)));
+          SetSysCoordUnit_GCSRS(theSysCoord, GetSysCoordUnit_GCSRS(gcsc));
         SetSysCoordCentralMeridian_GCSRS(theSysCoord, GetSysCoordCentralMeridian_GCSRS(gcsc));
         SetSysCoordLatitudeOfOrigin_GCSRS(theSysCoord, GetSysCoordLatitudeOfOrigin_GCSRS(gcsc));
         SetSysCoordStandardParallel1_GCSRS(theSysCoord, GetSysCoordStandardParallel1_GCSRS(gcsc));
@@ -699,14 +692,6 @@ static void GCSRSAPI_CALL _ReInitSysCoord_GCSRS (
                                                   GCSysCoord* theSysCoord
                                                 )
 {
-  if( GetSysCoordName_GCSRS(theSysCoord) )
-  {
-    CPLFree(GetSysCoordName_GCSRS(theSysCoord));
-  }
-  if( GetSysCoordUnit_GCSRS(theSysCoord) )
-  {
-    CPLFree(GetSysCoordUnit_GCSRS(theSysCoord));
-  }
   _InitSysCoord_GCSRS(theSysCoord);
 }/* _ReInitSysCoord_GCSRS */
 
@@ -724,9 +709,9 @@ void GCSRSAPI_CALL DestroySysCoord_GCSRS (
 GCSysCoord GCSRSAPI_CALL1(*) OGRSpatialReference2SysCoord_GCSRS ( OGRSpatialReferenceH poSR )
 {
   char* pszProj4= NULL;
-  GCSpheroidInfo* ell= NULL;
-  GCDatumInfo* datum= NULL;
-  GCProjectionInfo* gcproj= NULL;
+  const GCSpheroidInfo* ell= NULL;
+  const GCDatumInfo* datum= NULL;
+  const GCProjectionInfo* gcproj= NULL;
   double a, rf, f, p[7];
   GCSysCoord* syscoord= NULL;
 
@@ -809,7 +794,7 @@ GCSysCoord GCSRSAPI_CALL1(*) OGRSpatialReference2SysCoord_GCSRS ( OGRSpatialRefe
     if( (v= OSRGetProjParm(poSR,SRS_PP_PSEUDO_STD_PARALLEL_1,0.0,NULL))!= 0.0 )
     {
       /* should be SRS_PT_EQUIRECTANGULAR : */
-      SetSysCoordScaleFactor_GCSRS(syscoord, cos(v*PI/180.0));
+      SetSysCoordScaleFactor_GCSRS(syscoord, cos(v*M_PI/180.0));
       SetSysCoordStandardParallel1_GCSRS(syscoord, v);/* allow keeping lat_ts sign */
     }
   }
@@ -861,8 +846,8 @@ onError:
 OGRSpatialReferenceH GCSRSAPI_CALL SysCoord2OGRSpatialReference_GCSRS ( GCSysCoord* syscoord )
 {
   OGRSpatialReferenceH poSR;
-  GCDatumInfo* datum= NULL;
-  GCSpheroidInfo* ell= NULL;
+  const GCDatumInfo* datum= NULL;
+  const GCSpheroidInfo* ell= NULL;
   int i;
   double f;
 
@@ -1013,8 +998,8 @@ OGRSpatialReferenceH GCSRSAPI_CALL SysCoord2OGRSpatialReference_GCSRS ( GCSysCoo
     {
         CPLDebug( "GEOCONCEPT",
                   "This SysCoord value: %d:%d was translated to : %s",
-                  GetSysCoordSystemID_GCSRS(syscoord),
-                  GetSysCoordTimeZone_GCSRS(syscoord),
+                  syscoord ? GetSysCoordSystemID_GCSRS(syscoord) : -1,
+                  syscoord ? GetSysCoordTimeZone_GCSRS(syscoord) : -1,
                   pszWKT );
         CPLFree( pszWKT );
     }
diff --git a/ogr/ogrsf_frmts/geoconcept/geoconcept_syscoord.h b/ogr/ogrsf_frmts/geoconcept/geoconcept_syscoord.h
index a4600c5..ec783b4 100644
--- a/ogr/ogrsf_frmts/geoconcept/geoconcept_syscoord.h
+++ b/ogr/ogrsf_frmts/geoconcept/geoconcept_syscoord.h
@@ -29,8 +29,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************/
-#ifndef _GEOCONCEPT_SYSCOORD_H_INCLUDED
-#define _GEOCONCEPT_SYSCOORD_H_INCLUDED
+#ifndef GEOCONCEPT_SYSCOORD_H_INCLUDED
+#define GEOCONCEPT_SYSCOORD_H_INCLUDED
 
 #include "ogr_srs_api.h"
 
@@ -62,7 +62,7 @@ typedef struct _tSysCoord_GCSRS GCSysCoord;
 struct _tSpheroidInfo_GCSRS {
   const char *pszSpheroidName;
   double      dfA; /* semi major axis in meters */
-  double      dfE; /* excentricity */
+  double      dfE; /* eccentricity */
   int         nEllipsoidID;
 };
 
@@ -88,6 +88,7 @@ struct _tDatumInfo_GCSRS {
 
 struct _tProjectionInfo_GCSRS {
   const char *pszProjName;
+  /* TODO: Translate to English. */
   int         nSphere;/*
                        * 1 = sphere de courbure
                        * 2 = sphere equatoriale
@@ -100,8 +101,8 @@ struct _tProjectionInfo_GCSRS {
 };
 
 struct _tSysCoord_GCSRS {
-  char   *pszSysCoordName;
-  char   *pszUnit;
+  const char   *pszSysCoordName;
+  const char   *pszUnit;
 
   double  dfPM;
   /* inherited : */
@@ -185,4 +186,4 @@ OGRSpatialReferenceH GCSRSAPI_CALL SysCoord2OGRSpatialReference_GCSRS ( GCSysCoo
 #endif
 
 
-#endif /* ndef _GEOCONCEPT_SYSCOORD_H_INCLUDED */
+#endif /* ndef GEOCONCEPT_SYSCOORD_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdatasource.cpp b/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdatasource.cpp
index 98cb67f..9f27ba8 100644
--- a/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdatasource.cpp
+++ b/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdatasource.cpp
@@ -29,10 +29,10 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogrgeoconceptlayer.h"
-#include "ogrgeoconceptdatasource.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "ogrgeoconceptdatasource.h"
+#include "ogrgeoconceptlayer.h"
 
 CPL_CVSID("$Id: ogrgeoconceptdatasource.cpp 00000 2007-11-03 11:49:22Z drichard $");
 
@@ -40,22 +40,18 @@ CPL_CVSID("$Id: ogrgeoconceptdatasource.cpp 00000 2007-11-03 11:49:22Z drichard
 /*                         OGRGeoconceptDataSource()                    */
 /************************************************************************/
 
-OGRGeoconceptDataSource::OGRGeoconceptDataSource()
-
-{
-    _papoLayers = NULL;
-    _nLayers = 0;
-
-    _pszGCT = NULL;
-    _pszName = NULL;
-    _pszDirectory = NULL;
-    _pszExt = NULL;
-    _papszOptions = NULL;
-
-    _bSingleNewFile = FALSE;
-    _bUpdate = FALSE;
-    _hGXT = NULL;
-}
+OGRGeoconceptDataSource::OGRGeoconceptDataSource() :
+    _papoLayers(NULL),
+    _nLayers(0),
+    _pszGCT(NULL),
+    _pszName(NULL),
+    _pszDirectory(NULL),
+    _pszExt(NULL),
+    _papszOptions(NULL),
+    _bSingleNewFile(false),
+    _bUpdate(false),
+    _hGXT(NULL)
+{}
 
 /************************************************************************/
 /*                        ~OGRGeoconceptDataSource()                    */
@@ -64,42 +60,21 @@ OGRGeoconceptDataSource::OGRGeoconceptDataSource()
 OGRGeoconceptDataSource::~OGRGeoconceptDataSource()
 
 {
-    if ( _pszGCT )
-    {
-      CPLFree( _pszGCT );
-    }
-    if ( _pszName )
+    for( int i = 0; i < _nLayers; i++ )
     {
-      CPLFree( _pszName );
-    }
-    if ( _pszDirectory )
-    {
-      CPLFree( _pszDirectory );
-    }
-    if ( _pszExt )
-    {
-      CPLFree( _pszExt );
-    }
-
-    if ( _papoLayers )
-    {
-      for( int i = 0; i < _nLayers; i++ )
-      {
         delete _papoLayers[i];
-      }
-
-      CPLFree( _papoLayers );
     }
+    CPLFree( _papoLayers );
+    CPLFree( _pszGCT );
+    CPLFree( _pszName );
+    CPLFree( _pszDirectory );
+    CPLFree( _pszExt );
+    CSLDestroy( _papszOptions );
 
     if( _hGXT )
     {
       Close_GCIO(&_hGXT);
     }
-
-    if ( _papszOptions )
-    {
-      CSLDestroy( _papszOptions );
-    }
 }
 
 /************************************************************************/
@@ -108,7 +83,8 @@ OGRGeoconceptDataSource::~OGRGeoconceptDataSource()
 /*      Open an existing file.                                          */
 /************************************************************************/
 
-int OGRGeoconceptDataSource::Open( const char* pszName, int bTestOpen, int bUpdate )
+int OGRGeoconceptDataSource::Open( const char* pszName, bool bTestOpen,
+                                   bool bUpdate )
 
 {
 /* -------------------------------------------------------------------- */
@@ -122,8 +98,9 @@ int OGRGeoconceptDataSource::Open( const char* pszName, int bTestOpen, int bUpda
         if( !bTestOpen )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                    "%s is neither a file or directory, Geoconcept access failed.",
-                    pszName );
+                      "%s is neither a file or directory, "
+                      "Geoconcept access failed.",
+                      pszName );
         }
 
         return FALSE;
@@ -140,10 +117,10 @@ int OGRGeoconceptDataSource::Open( const char* pszName, int bTestOpen, int bUpda
 
     if( VSI_ISREG(stat.st_mode) )
     {
-        _bSingleNewFile= FALSE;
-        _bUpdate= bUpdate;
-        _pszName= CPLStrdup( pszName );
-        if( !LoadFile( _bUpdate? "a+t":"rt" ) )
+        _bSingleNewFile = false;
+        _bUpdate = bUpdate;
+        _pszName = CPLStrdup( pszName );
+        if( !LoadFile( _bUpdate ? "a+t":"rt" ) )
         {
             CPLDebug( "GEOCONCEPT",
                       "Failed to open Geoconcept %s."
@@ -166,8 +143,6 @@ int OGRGeoconceptDataSource::Open( const char* pszName, int bTestOpen, int bUpda
 int OGRGeoconceptDataSource::LoadFile( const char *pszMode )
 
 {
-    OGRGeoconceptLayer *poFile;
-
     if( _pszExt == NULL)
     {
       const char* pszExtension = CPLGetExtension(_pszName);
@@ -187,24 +162,24 @@ int OGRGeoconceptDataSource::LoadFile( const char *pszMode )
     GCExportFileMetadata* Meta= GetGCMeta_GCIO(_hGXT);
     if( Meta )
     {
-      int nC, iC, nS, iS;
+      const int nC = CountMetaTypes_GCIO(Meta);
 
-      if( (nC= CountMetaTypes_GCIO(Meta))>0 )
+      if( nC > 0 )
       {
-        GCType* aClass;
-        GCSubType* aSubclass;
-
-        for( iC= 0; iC<nC; iC++ )
+        for( int iC= 0; iC<nC; iC++ )
         {
-          if( (aClass= GetMetaType_GCIO(Meta,iC)) )
+          GCType* aClass = GetMetaType_GCIO(Meta,iC);
+          if( aClass )
           {
-            if( (nS= CountTypeSubtypes_GCIO(aClass)) )
+            const int nS = CountTypeSubtypes_GCIO(aClass);
+            if( nS )
             {
-              for( iS= 0; iS<nS; iS++ )
+              for( int iS = 0; iS<nS; iS++ )
               {
-                if( (aSubclass= GetTypeSubtype_GCIO(aClass,iS)) )
+                GCSubType *aSubclass = GetTypeSubtype_GCIO(aClass,iS);
+                if( aSubclass )
                 {
-                  poFile = new OGRGeoconceptLayer;
+                  OGRGeoconceptLayer *poFile = new OGRGeoconceptLayer;
                   if( poFile->Open(aSubclass) != OGRERR_NONE )
                   {
                     delete poFile;
@@ -212,13 +187,15 @@ int OGRGeoconceptDataSource::LoadFile( const char *pszMode )
                   }
 
                   /* Add layer to data source layers list */
-                  _papoLayers = (OGRGeoconceptLayer **)
-                      CPLRealloc( _papoLayers,  sizeof(OGRGeoconceptLayer *) * (_nLayers+1) );
+                  _papoLayers = static_cast<OGRGeoconceptLayer **>(
+                      CPLRealloc( _papoLayers,
+                                  sizeof(OGRGeoconceptLayer *)
+                                  * (_nLayers+1) ) );
                   _papoLayers[_nLayers++] = poFile;
 
-                  CPLDebug("GEOCONCEPT",
-                           "nLayers=%d - last=[%s]",
-                           _nLayers, poFile->GetLayerDefn()->GetName());
+                  CPLDebug( "GEOCONCEPT",
+                            "nLayers=%d - last=[%s]",
+                            _nLayers, poFile->GetLayerDefn()->GetName());
                 }
               }
             }
@@ -243,20 +220,17 @@ int OGRGeoconceptDataSource::LoadFile( const char *pszMode )
 int OGRGeoconceptDataSource::Create( const char *pszName, char** papszOptions )
 
 {
-    const char *pszConf;
-    const char *pszExtension;
-
-    if( _pszName ) CPLFree(_pszName);
+    CPLFree( _pszName );
     _papszOptions = CSLDuplicate( papszOptions );
 
-    pszConf= CSLFetchNameValue(papszOptions,"CONFIG");
+    const char *pszConf = CSLFetchNameValue(papszOptions,"CONFIG");
     if( pszConf != NULL )
     {
       _pszGCT = CPLStrdup(pszConf);
     }
 
     _pszExt = (char *)CSLFetchNameValue(papszOptions,"EXTENSION");
-    pszExtension = CSLFetchNameValue(papszOptions,"EXTENSION");
+    const char *pszExtension = CSLFetchNameValue( papszOptions, "EXTENSION" );
     if( pszExtension == NULL )
     {
         _pszExt = CPLStrdup(CPLGetExtension(pszName));
@@ -302,7 +276,7 @@ int OGRGeoconceptDataSource::Create( const char *pszName, char** papszOptions )
 /*      Create a new single file.                                       */
 /*      OGRGeoconceptDriver::ICreateLayer() will do the job.             */
 /* -------------------------------------------------------------------- */
-    _bSingleNewFile = TRUE;
+    _bSingleNewFile = true;
 
     if( !LoadFile( "wt" ) )
     {
@@ -329,14 +303,6 @@ OGRLayer *OGRGeoconceptDataSource::ICreateLayer( const char * pszLayerName,
                                                 char ** papszOptions /* = NULL */ )
 
 {
-    GCTypeKind gcioFeaType;
-    GCDim gcioDim;
-    OGRGeoconceptLayer *poFile= NULL;
-    const char *pszFeatureType; 
-    char **ft;
-    int iLayer;
-    char pszln[512];
-
     if( _hGXT == NULL )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
@@ -356,6 +322,9 @@ OGRLayer *OGRGeoconceptDataSource::ICreateLayer( const char * pszLayerName,
     /*
      * pszLayerName Class.Subclass if -nln option used, otherwise file name
      */
+    const char *pszFeatureType;
+    char pszln[512];
+
     if( !(pszFeatureType = CSLFetchNameValue(papszOptions,"FEATURETYPE")) )
     {
       if( !pszLayerName || !strchr(pszLayerName,'.') )
@@ -369,6 +338,7 @@ OGRLayer *OGRGeoconceptDataSource::ICreateLayer( const char * pszLayerName,
         pszFeatureType= pszLayerName;
     }
 
+    char **ft;
     if( !(ft= CSLTokenizeString2(pszFeatureType,".",0)) ||
         CSLCount(ft)!=2 )
     {
@@ -383,7 +353,9 @@ OGRLayer *OGRGeoconceptDataSource::ICreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
 /*      Figure out what type of layer we need.                          */
 /* -------------------------------------------------------------------- */
-    gcioDim= v2D_GCIO;
+    GCTypeKind gcioFeaType;
+    GCDim gcioDim = v2D_GCIO;
+
     if( eType == wkbUnknown )
         gcioFeaType = vUnknownItemType_GCIO;
     else if( eType == wkbPoint )
@@ -442,11 +414,13 @@ OGRLayer *OGRGeoconceptDataSource::ICreateLayer( const char * pszLayerName,
      * layer name to exist in the CONFIG as "Class.Subclass".
      * Removing the CONFIG, implies on-the-fly-creation of layers...
      */
+    OGRGeoconceptLayer *poFile= NULL;
+
     if( _nLayers > 0 )
-      for( iLayer= 0; iLayer<_nLayers; iLayer++)
+      for( int iLayer= 0; iLayer<_nLayers; iLayer++)
       {
-        poFile= (OGRGeoconceptLayer*)GetLayer(iLayer);
-        if( EQUAL(poFile->GetLayerDefn()->GetName(),pszFeatureType) )
+        poFile= reinterpret_cast<OGRGeoconceptLayer *>( GetLayer(iLayer) );
+        if( poFile != NULL && EQUAL(poFile->GetLayerDefn()->GetName(),pszFeatureType) )
         {
           break;
         }
@@ -524,8 +498,9 @@ OGRLayer *OGRGeoconceptDataSource::ICreateLayer( const char * pszLayerName,
         return NULL;
       }
 
-      _papoLayers = (OGRGeoconceptLayer **)
-                      CPLRealloc( _papoLayers,  sizeof(OGRGeoconceptLayer *) * (_nLayers+1) );
+      _papoLayers = static_cast<OGRGeoconceptLayer **>(
+          CPLRealloc( _papoLayers,
+                      sizeof(OGRGeoconceptLayer *) * (_nLayers+1) ) );
       _papoLayers[_nLayers++] = poFile;
 
       CPLDebug("GEOCONCEPT",
@@ -552,8 +527,8 @@ int OGRGeoconceptDataSource::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,ODsCCreateLayer) )
         return TRUE;
-    else
-        return FALSE;
+
+    return FALSE;
 }
 
 /************************************************************************/
@@ -563,10 +538,9 @@ int OGRGeoconceptDataSource::TestCapability( const char * pszCap )
 OGRLayer *OGRGeoconceptDataSource::GetLayer( int iLayer )
 
 {
-    OGRLayer *poFile;
     if( iLayer < 0 || iLayer >= GetLayerCount() )
-        poFile= NULL;
-    else
-        poFile= _papoLayers[iLayer];
+      return NULL;
+
+    OGRLayer *poFile = _papoLayers[iLayer];
     return poFile;
 }
diff --git a/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdatasource.h b/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdatasource.h
index bb166bf..9f4ca4c 100644
--- a/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdatasource.h
+++ b/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdatasource.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: ogrgeoconceptdatasource.h 
+ * $Id: ogrgeoconceptdatasource.h
  *
  * Name:     ogrgeoconceptdatasource.h
  * Project:  OpenGIS Simple Features Reference Implementation
@@ -15,24 +15,24 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************/
 
 #include "ogrsf_frmts.h"
 #include "ogrgeoconceptlayer.h"
 
-#ifndef _GEOCONCEPT_OGR_DATASOURCE_H_INCLUDED_
-#define _GEOCONCEPT_OGR_DATASOURCE_H_INCLUDED_
+#ifndef GEOCONCEPT_OGR_DATASOURCE_H_INCLUDED_
+#define GEOCONCEPT_OGR_DATASOURCE_H_INCLUDED_
 
 /**********************************************************************/
 /*            OGCGeoconceptDataSource Class                           */
@@ -48,15 +48,15 @@ class OGRGeoconceptDataSource : public OGRDataSource
     char                *_pszDirectory;
     char                *_pszExt;
     char               **_papszOptions;
-    int                  _bSingleNewFile;
-    int                  _bUpdate;
+    bool                 _bSingleNewFile;
+    bool                 _bUpdate;
     GCExportFileH       *_hGXT;
 
   public:
                    OGRGeoconceptDataSource();
                   ~OGRGeoconceptDataSource();
 
-    int            Open( const char* pszName, int bTestOpen, int bUpdate );
+    int            Open( const char* pszName, bool bTestOpen, bool bUpdate );
     int            Create( const char* pszName, char** papszOptions );
 
     const char*    GetName() { return _pszName; }
@@ -65,7 +65,7 @@ class OGRGeoconceptDataSource : public OGRDataSource
 //    OGRErr         DeleteLayer( int iLayer );
     int            TestCapability( const char* pszCap );
 
-    OGRLayer*      ICreateLayer( const char* pszName, 
+    OGRLayer*      ICreateLayer( const char* pszName,
                                 OGRSpatialReference* poSpatialRef = NULL,
                                 OGRwkbGeometryType eGType = wkbUnknown,
                                 char** papszOptions = NULL );
@@ -73,4 +73,4 @@ class OGRGeoconceptDataSource : public OGRDataSource
     int            LoadFile( const char * );
 };
 
-#endif /* _GEOCONCEPT_OGR_DATASOURCE_H_INCLUDED_ */
+#endif /* GEOCONCEPT_OGR_DATASOURCE_H_INCLUDED_ */
diff --git a/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdriver.cpp b/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdriver.cpp
index 32c5f7a..16c3c45 100644
--- a/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdriver.cpp
+++ b/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeoconceptdriver.cpp 
+ * $Id: ogrgeoconceptdriver.cpp
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGeoconceptDriver class.
@@ -28,10 +28,10 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogrgeoconceptdatasource.h"
-#include "ogrgeoconceptdriver.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "ogrgeoconceptdatasource.h"
+#include "ogrgeoconceptdriver.h"
 
 CPL_CVSID("$Id: ogrgeoconceptdriver.cpp 00000 2007-11-03 10:42:48Z drichard $");
 
@@ -39,10 +39,7 @@ CPL_CVSID("$Id: ogrgeoconceptdriver.cpp 00000 2007-11-03 10:42:48Z drichard $");
 /*                          ~OGRGeoconceptDriver()                      */
 /************************************************************************/
 
-OGRGeoconceptDriver::~OGRGeoconceptDriver()
-
-{
-}
+OGRGeoconceptDriver::~OGRGeoconceptDriver() {}
 
 /************************************************************************/
 /*                              GetName()                               */
@@ -62,8 +59,6 @@ OGRDataSource *OGRGeoconceptDriver::Open( const char* pszFilename,
                                           int bUpdate )
 
 {
-    OGRGeoconceptDataSource  *poDS;
-
 /* -------------------------------------------------------------------- */
 /*      We will only consider .gxt and .txt files.                      */
 /* -------------------------------------------------------------------- */
@@ -73,9 +68,9 @@ OGRDataSource *OGRGeoconceptDriver::Open( const char* pszFilename,
         return NULL;
     }
 
-    poDS = new OGRGeoconceptDataSource();
+    OGRGeoconceptDataSource  *poDS = new OGRGeoconceptDataSource();
 
-    if( !poDS->Open( pszFilename, TRUE, bUpdate ) )
+    if( !poDS->Open( pszFilename, true, CPL_TO_BOOL(bUpdate) ) )
     {
         delete poDS;
         return NULL;
@@ -150,9 +145,7 @@ OGRDataSource *OGRGeoconceptDriver::CreateDataSource( const char* pszName,
 /* -------------------------------------------------------------------- */
 /*      Return a new OGRDataSource()                                    */
 /* -------------------------------------------------------------------- */
-    OGRGeoconceptDataSource  *poDS = NULL;
-
-    poDS = new OGRGeoconceptDataSource();
+    OGRGeoconceptDataSource  *poDS = new OGRGeoconceptDataSource();
     if( !poDS->Create( pszName, papszOptions ) )
     {
         delete poDS;
@@ -168,9 +161,8 @@ OGRDataSource *OGRGeoconceptDriver::CreateDataSource( const char* pszName,
 OGRErr OGRGeoconceptDriver::DeleteDataSource( const char *pszDataSource )
 
 {
-    int iExt;
     VSIStatBuf sStatBuf;
-    static const char *apszExtensions[] = 
+    static const char * const apszExtensions[] =
         { "gxt", "txt", "gct", "gcm", "gcr", NULL };
 
     if( VSIStat( pszDataSource, &sStatBuf ) != 0 )
@@ -182,13 +174,13 @@ OGRErr OGRGeoconceptDriver::DeleteDataSource( const char *pszDataSource )
         return OGRERR_FAILURE;
     }
 
-    if( VSI_ISREG(sStatBuf.st_mode) 
+    if( VSI_ISREG(sStatBuf.st_mode)
         && (
             EQUAL(CPLGetExtension(pszDataSource),"gxt") ||
             EQUAL(CPLGetExtension(pszDataSource),"txt")
            ) )
     {
-        for( iExt=0; apszExtensions[iExt] != NULL; iExt++ )
+        for( int iExt=0; apszExtensions[iExt] != NULL; iExt++ )
         {
             const char *pszFile = CPLResetExtension(pszDataSource,
                                                     apszExtensions[iExt] );
@@ -198,18 +190,17 @@ OGRErr OGRGeoconceptDriver::DeleteDataSource( const char *pszDataSource )
     }
     else if( VSI_ISDIR(sStatBuf.st_mode) )
     {
-        char **papszDirEntries = CPLReadDir( pszDataSource );
-        int  iFile;
+        char **papszDirEntries = VSIReadDir( pszDataSource );
 
-        for( iFile = 0; 
+        for( int iFile = 0;
              papszDirEntries != NULL && papszDirEntries[iFile] != NULL;
              iFile++ )
         {
-            if( CSLFindString( (char **) apszExtensions, 
+            if( CSLFindString( const_cast<char **>( apszExtensions ),
                                CPLGetExtension(papszDirEntries[iFile])) != -1)
             {
-                VSIUnlink( CPLFormFilename( pszDataSource, 
-                                            papszDirEntries[iFile], 
+                VSIUnlink( CPLFormFilename( pszDataSource,
+                                            papszDirEntries[iFile],
                                             NULL ) );
             }
         }
@@ -232,10 +223,11 @@ int OGRGeoconceptDriver::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,ODrCCreateDataSource) )
         return TRUE;
-    else if( EQUAL(pszCap,ODrCDeleteDataSource) )
+
+    if( EQUAL(pszCap,ODrCDeleteDataSource) )
         return TRUE;
-    else
-        return FALSE;
+
+    return FALSE;
 }
 
 /************************************************************************/
@@ -250,17 +242,24 @@ void RegisterOGRGeoconcept()
 
     poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
-"  <Option name='EXTENSION' type='string-select' description='indicates the GeoConcept export file extension. TXT was used by earlier releases of GeoConcept. GXT is currently used.' default='GXT'>"
+"  <Option name='EXTENSION' type='string-select' description='indicates the "
+"GeoConcept export file extension. TXT was used by earlier releases of "
+"GeoConcept. GXT is currently used.' default='GXT'>"
 "    <Value>GXT</Value>"
 "    <Value>TXT</Value>"
 "  </Option>"
-"  <Option name='CONFIG' type='string' description='path to the GCT file that describes the GeoConcept types definitions.'/>"
+"  <Option name='CONFIG' type='string' description='path to the GCT file that "
+"describes the GeoConcept types definitions.'/>"
 "</CreationOptionList>");
 
-        poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
 "<LayerCreationOptionList>"
-"  <Option name='FEATURETYPE' type='string' description='TYPE.SUBTYPE : defines the feature to be created. The TYPE corresponds to one of the Name found in the GCT file for a type section. The SUBTYPE corresponds to one of the Name found in the GCT file for a sub-type section within the previous type section'/>"
-"</LayerCreationOptionList>");
+"  <Option name='FEATURETYPE' type='string' description='TYPE.SUBTYPE : "
+"defines the feature to be created. The TYPE corresponds to one of the Name "
+"found in the GCT file for a type section. The SUBTYPE corresponds to one of "
+"the Name found in the GCT file for a sub-type section within the previous "
+"type section'/>"
+"</LayerCreationOptionList>" );
 
     OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdriver.h b/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdriver.h
index 8bd21b5..c34bf49 100644
--- a/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdriver.h
+++ b/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdriver.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: ogrgeoconceptdriver.h 
+ * $Id: ogrgeoconceptdriver.h
  *
  * Name:     ogrgeoconceptdriver.h
  * Project:  OpenGIS Simple Features Reference Implementation
@@ -15,23 +15,23 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************/
 
 #include "ogrsf_frmts.h"
 
-#ifndef _GEOCONCEPT_OGR_DRIVER_H_INCLUDED_
-#define _GEOCONCEPT_OGR_DRIVER_H_INCLUDED_
+#ifndef GEOCONCEPT_OGR_DRIVER_H_INCLUDED_
+#define GEOCONCEPT_OGR_DRIVER_H_INCLUDED_
 
 /************************************************************************/
 /*                             OGRGeoconceptDriver                      */
@@ -49,4 +49,4 @@ public:
     OGRErr         DeleteDataSource( const char* pszName );
 };
 
-#endif /* _GEOCONCEPT_OGR_DRIVER_H_INCLUDED_ */
+#endif /* GEOCONCEPT_OGR_DRIVER_H_INCLUDED_ */
diff --git a/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptlayer.cpp b/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptlayer.cpp
index ed22dc2..a68bbea 100644
--- a/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptlayer.cpp
+++ b/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeoconceptlayer.cpp 
+ * $Id: ogrgeoconceptlayer.cpp
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGeoconceptLayer class.
@@ -29,9 +29,9 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogrgeoconceptlayer.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "ogrgeoconceptlayer.h"
 
 CPL_CVSID("$Id: ogrgeoconceptlayer.cpp 00000 2007-11-03 16:08:14Z drichard $");
 
@@ -39,11 +39,10 @@ CPL_CVSID("$Id: ogrgeoconceptlayer.cpp 00000 2007-11-03 16:08:14Z drichard $");
 /*                         OGRGeoconceptLayer()                         */
 /************************************************************************/
 
-OGRGeoconceptLayer::OGRGeoconceptLayer()
-{
-    _poFeatureDefn = NULL;
-    _gcFeature = NULL;
-}
+OGRGeoconceptLayer::OGRGeoconceptLayer() :
+    _poFeatureDefn(NULL),
+    _gcFeature(NULL)
+{}
 
 /************************************************************************/
 /*                          ~OGRGeoconceptLayer()                      */
@@ -52,13 +51,13 @@ OGRGeoconceptLayer::OGRGeoconceptLayer()
 OGRGeoconceptLayer::~OGRGeoconceptLayer()
 
 {
-  CPLDebug( "GEOCONCEPT",
-            "%ld features on layer %s.",
-            GetSubTypeNbFeatures_GCIO(_gcFeature),
-            _poFeatureDefn->GetName());
-
   if( _poFeatureDefn )
   {
+    CPLDebug( "GEOCONCEPT",
+              "%ld features on layer %s.",
+              GetSubTypeNbFeatures_GCIO(_gcFeature),
+              _poFeatureDefn->GetName() );
+
     _poFeatureDefn->Release();
   }
 
@@ -75,14 +74,13 @@ OGRErr OGRGeoconceptLayer::Open( GCSubType* Subclass )
     _gcFeature= Subclass;
     if( GetSubTypeFeatureDefn_GCIO(_gcFeature) )
     {
-      _poFeatureDefn = (OGRFeatureDefn *)GetSubTypeFeatureDefn_GCIO(_gcFeature);
+      _poFeatureDefn = reinterpret_cast<OGRFeatureDefn *>(
+          GetSubTypeFeatureDefn_GCIO(_gcFeature) );
       _poFeatureDefn->Reference();
     }
     else
     {
       char pszln[512];
-      int n, i;
-
       snprintf(pszln, 511, "%s.%s", GetSubTypeName_GCIO(_gcFeature),
                                     GetTypeName_GCIO(GetSubTypeType_GCIO(_gcFeature)));
       pszln[511]='\0';
@@ -92,13 +90,14 @@ OGRErr OGRGeoconceptLayer::Open( GCSubType* Subclass )
       _poFeatureDefn->Reference();
       _poFeatureDefn->SetGeomType(wkbUnknown);
 
-      if( (n= CountSubTypeFields_GCIO(_gcFeature))>0 )
+      const int n = CountSubTypeFields_GCIO(_gcFeature);
+      if( n>0 )
       {
-        GCField* aField= NULL;
         OGRFieldType oft;
-        for( i= 0; i<n; i++ )
+        for( int i= 0; i<n; i++ )
         {
-          if( (aField= GetSubTypeField_GCIO(_gcFeature,i)) )
+          GCField* aField = GetSubTypeField_GCIO(_gcFeature,i);
+          if( aField )
           {
             if( IsPrivateField_GCIO(aField) ) continue;
             switch(GetFieldKind_GCIO(aField)) {
@@ -133,6 +132,9 @@ OGRErr OGRGeoconceptLayer::Open( GCSubType* Subclass )
       _poFeatureDefn->Reference();
     }
 
+    if( _poFeatureDefn->GetGeomFieldCount() > 0 )
+        _poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(GetSpatialRef());
+
     return OGRERR_NONE;
 }
 
@@ -165,7 +167,7 @@ OGRFeature *OGRGeoconceptLayer::GetNextFeature()
          * the reader would allow reading other features :
          * ogrinfo -ro export.gxt FT1 FT2 ...
          * will be all features for all features types !
-         */ 
+         */
         Rewind_GCIO(GetSubTypeGCHandle_GCIO(_gcFeature),NULL);
         break;
       }
@@ -195,8 +197,7 @@ OGRFeature *OGRGeoconceptLayer::GetNextFeature()
 static char* OGRGeoconceptLayer_GetCompatibleFieldName(const char* pszName)
 {
     char* pszCompatibleName = CPLStrdup(pszName);
-    int i;
-    for(i=0;pszCompatibleName[i] != 0;i++)
+    for( int i=0; pszCompatibleName[i] != 0; i++ )
     {
         if (pszCompatibleName[i] == ' ')
             pszCompatibleName[i] = '_';
@@ -211,11 +212,7 @@ static char* OGRGeoconceptLayer_GetCompatibleFieldName(const char* pszName)
 OGRErr OGRGeoconceptLayer::ICreateFeature( OGRFeature* poFeature )
 
 {
-    OGRwkbGeometryType eGt;
-    OGRGeometry* poGeom;
-    int nextField, iGeom, nbGeom, isSingle;
-
-    poGeom= poFeature->GetGeometryRef();
+    OGRGeometry* poGeom = poFeature->GetGeometryRef();
 
     if (poGeom == NULL)
     {
@@ -224,7 +221,7 @@ OGRErr OGRGeoconceptLayer::ICreateFeature( OGRFeature* poFeature )
         return OGRERR_NONE;
     }
 
-    eGt= poGeom->getGeometryType();
+    OGRwkbGeometryType eGt = poGeom->getGeometryType();
     switch( eGt ) {
     case wkbPoint                 :
     case wkbPoint25D              :
@@ -253,7 +250,8 @@ OGRErr OGRGeoconceptLayer::ICreateFeature( OGRFeature* poFeature )
       else if( GetSubTypeKind_GCIO(_gcFeature)!=vLine_GCIO )
       {
         CPLError( CE_Failure, CPLE_NotSupported,
-                  "Can't write non linear feature in a linear Geoconcept layer %s.\n",
+                  "Can't write non linear feature in a linear Geoconcept "
+                  "layer %s.\n",
                   _poFeatureDefn->GetName());
         return OGRERR_FAILURE;
       }
@@ -269,7 +267,8 @@ OGRErr OGRGeoconceptLayer::ICreateFeature( OGRFeature* poFeature )
       else if( GetSubTypeKind_GCIO(_gcFeature)!=vPoly_GCIO )
       {
         CPLError( CE_Failure, CPLE_NotSupported,
-                  "Can't write non polygonal feature in a polygonal Geoconcept layer %s.\n",
+                  "Can't write non polygonal feature in a polygonal "
+                  "Geoconcept layer %s.\n",
                   _poFeatureDefn->GetName());
         return OGRERR_FAILURE;
       }
@@ -281,7 +280,8 @@ OGRErr OGRGeoconceptLayer::ICreateFeature( OGRFeature* poFeature )
     case wkbLinearRing            :
     default                       :
       CPLError( CE_Warning, CPLE_AppDefined,
-                "Geometry type %s not supported in Geoconcept, feature skipped.\n",
+                "Geometry type %s not supported in Geoconcept, "
+                "feature skipped.\n",
                 OGRGeometryTypeToName(eGt) );
       return OGRERR_NONE;
     }
@@ -297,6 +297,9 @@ OGRErr OGRGeoconceptLayer::ICreateFeature( OGRFeature* poFeature )
       }
     }
 
+    int nbGeom;
+    int isSingle;
+
     switch( eGt ) {
     case wkbPoint                 :
     case wkbPoint25D              :
@@ -328,11 +331,6 @@ OGRErr OGRGeoconceptLayer::ICreateFeature( OGRFeature* poFeature )
       nbGeom= ((OGRGeometryCollection*)poGeom)->getNumGeometries();
       isSingle= FALSE;
       break;
-    case wkbUnknown               :
-    case wkbGeometryCollection    :
-    case wkbGeometryCollection25D :
-    case wkbNone                  :
-    case wkbLinearRing            :
     default                       :
       nbGeom= 0;
       isSingle= FALSE;
@@ -349,11 +347,13 @@ OGRErr OGRGeoconceptLayer::ICreateFeature( OGRFeature* poFeature )
 
     if( nbGeom>0 )
     {
-      for( iGeom= 0; iGeom<nbGeom; iGeom++ )
+      for( int iGeom = 0; iGeom<nbGeom; iGeom++ )
       {
-        nextField= StartWritingFeature_GCIO(_gcFeature,
-                                            isSingle? (int)poFeature->GetFID():OGRNullFID);
-        while (nextField!=WRITECOMPLETED_GCIO)
+        int nextField
+            = StartWritingFeature_GCIO(
+                _gcFeature,
+                isSingle ? static_cast<int>(poFeature->GetFID()) : OGRNullFID );
+        while( nextField != WRITECOMPLETED_GCIO )
         {
           if( nextField==WRITEERROR_GCIO )
           {
@@ -368,34 +368,36 @@ OGRErr OGRGeoconceptLayer::ICreateFeature( OGRFeature* poFeature )
           }
           else
           {
-            int iF, nF;
-            OGRFieldDefn *poField;
             GCField* theField= GetSubTypeField_GCIO(_gcFeature,nextField);
             /* for each field, find out its mapping ... */
-            if( (nF= poFeature->GetFieldCount())>0 )
+            int nF = poFeature->GetFieldCount();
+            if( nF > 0 )
             {
-              for( iF= 0; iF<nF; iF++ )
+              int iF = 0;
+              for( ; iF<nF; iF++ )
               {
-                poField= poFeature->GetFieldDefnRef(iF);
-                char* pszName = OGRGeoconceptLayer_GetCompatibleFieldName(poField->GetNameRef());
+                OGRFieldDefn *poField = poFeature->GetFieldDefnRef(iF);
+                char* pszName = OGRGeoconceptLayer_GetCompatibleFieldName(
+                    poField->GetNameRef());
                 if( EQUAL(pszName, GetFieldName_GCIO(theField)) )
                 {
                   CPLFree(pszName);
-                  nextField= WriteFeatureFieldAsString_GCIO(_gcFeature,
-                                                            nextField,
-                                                            poFeature->IsFieldSet(iF)?
-                                                              poFeature->GetFieldAsString(iF)
-                                                            :
-                                                              NULL);
+                  nextField = WriteFeatureFieldAsString_GCIO(
+                      _gcFeature,
+                      nextField,
+                      poFeature->IsFieldSet(iF)?
+                      poFeature->GetFieldAsString(iF) : NULL);
                   break;
                 }
                 CPLFree(pszName);
               }
-              if( iF==nF )
+              if( iF == nF )
               {
                 CPLError( CE_Failure, CPLE_AppDefined,
-                          "Can't find a field attached to %s on Geoconcept layer %s.\n",
-                          GetFieldName_GCIO(theField), _poFeatureDefn->GetName());
+                          "Can't find a field attached to %s on "
+                          "Geoconcept layer %s.\n",
+                          GetFieldName_GCIO(theField),
+                          _poFeatureDefn->GetName() );
                 return OGRERR_FAILURE;
               }
             }
@@ -438,8 +440,8 @@ GIntBig OGRGeoconceptLayer::GetFeatureCount( int bForce )
 {
     if( m_poFilterGeom != NULL || m_poAttrQuery != NULL )
         return OGRLayer::GetFeatureCount( bForce );
-    else
-        return GetSubTypeNbFeatures_GCIO(_gcFeature);
+
+    return GetSubTypeNbFeatures_GCIO(_gcFeature);
 }
 
 /************************************************************************/
@@ -449,9 +451,7 @@ GIntBig OGRGeoconceptLayer::GetFeatureCount( int bForce )
 OGRErr OGRGeoconceptLayer::GetExtent( OGREnvelope* psExtent,
                                       CPL_UNUSED int bForce )
 {
-    GCExtent* theExtent;
-
-    theExtent= GetSubTypeExtent_GCIO( _gcFeature );
+    GCExtent* theExtent = GetSubTypeExtent_GCIO( _gcFeature );
     psExtent->MinX= GetExtentULAbscissa_GCIO(theExtent);
     psExtent->MinY= GetExtentLROrdinate_GCIO(theExtent);
     psExtent->MaxX= GetExtentLRAbscissa_GCIO(theExtent);
@@ -494,8 +494,7 @@ int OGRGeoconceptLayer::TestCapability( const char* pszCap )
     else if( EQUAL(pszCap,OLCCreateField) )
         return TRUE;
 
-    else
-        return FALSE;
+    return FALSE;
 }
 
 /************************************************************************/
@@ -540,7 +539,7 @@ OGRErr OGRGeoconceptLayer::CreateField( OGRFieldDefn *poField,
                                              GetTypeName_GCIO(GetSubTypeType_GCIO(_gcFeature)),
                                              GetSubTypeName_GCIO(_gcFeature),
                                              FindFeatureFieldIndex_GCIO(_gcFeature,kNbFields_GCIO)
-                                            +GetSubTypeNbFields_GCIO(_gcFeature)+1L,
+                                            +GetSubTypeNbFields_GCIO(_gcFeature)+1,
                                              pszName,
                                              GetSubTypeNbFields_GCIO(_gcFeature)-999L,
                                              vUnknownItemType_GCIO, NULL, NULL)) )
@@ -554,7 +553,7 @@ OGRErr OGRGeoconceptLayer::CreateField( OGRFieldDefn *poField,
           CPLFree(pszName);
           return OGRERR_FAILURE;
         }
-        SetSubTypeNbFields_GCIO(_gcFeature, GetSubTypeNbFields_GCIO(_gcFeature)+1L);
+        SetSubTypeNbFields_GCIO(_gcFeature, GetSubTypeNbFields_GCIO(_gcFeature)+1);
         _poFeatureDefn->AddFieldDefn(poField);
       }
       else
@@ -630,10 +629,7 @@ OGRErr OGRGeoconceptLayer::SyncToDisk()
 void OGRGeoconceptLayer::SetSpatialRef( OGRSpatialReference *poSpatialRef )
 
 {
-    GCSysCoord* os, *ns;
     OGRSpatialReference* poSRS= GetSpatialRef();
-    GCExportFileH* hGXT;
-    GCExportFileMetadata* Meta;
     /*-----------------------------------------------------------------
      * Keep a copy of the OGRSpatialReference...
      * Note: we have to take the reference count into account...
@@ -642,11 +638,22 @@ void OGRGeoconceptLayer::SetSpatialRef( OGRSpatialReference *poSpatialRef )
 
     if( !poSpatialRef ) return;
 
-    poSRS= poSpatialRef->Clone();
-    if( !(hGXT= GetSubTypeGCHandle_GCIO(_gcFeature)) ) return;
-    if( !(Meta= GetGCMeta_GCIO(hGXT)) ) return;
-    os= GetMetaSysCoord_GCIO(Meta);
-    ns= OGRSpatialReference2SysCoord_GCSRS((OGRSpatialReferenceH)poSRS);
+    poSRS = poSpatialRef->Clone();
+    GCExportFileH* hGXT = GetSubTypeGCHandle_GCIO(_gcFeature);
+    if( !hGXT )
+    {
+        delete poSRS;
+        return;
+    }
+    GCExportFileMetadata* Meta = GetGCMeta_GCIO(hGXT);
+    if( !Meta )
+    {
+        delete poSRS;
+        return;
+    }
+    GCSysCoord* os = GetMetaSysCoord_GCIO(Meta);
+    GCSysCoord* ns = OGRSpatialReference2SysCoord_GCSRS(
+        reinterpret_cast<OGRSpatialReferenceH>(poSRS) );
 
     if( os && ns &&
         GetSysCoordSystemID_GCSRS(os)!=-1 &&
@@ -658,6 +665,8 @@ void OGRGeoconceptLayer::SetSpatialRef( OGRSpatialReference *poSpatialRef )
     {
       CPLError( CE_Warning, CPLE_AppDefined,
                 "Can't change SRS on Geoconcept layers.\n" );
+      DestroySysCoord_GCSRS( &ns );
+      delete poSRS;
       return;
     }
 
diff --git a/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptlayer.h b/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptlayer.h
index 72b2f2e..3971446 100644
--- a/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptlayer.h
+++ b/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptlayer.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: ogrgeoconceptlayer.h 
+ * $Id: ogrgeoconceptlayer.h
  *
  * Name:     ogrgeoconceptlayer.h
  * Project:  OpenGIS Simple Features Reference Implementation
@@ -15,24 +15,24 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************/
 
 #include "ogrsf_frmts.h"
 #include "geoconcept.h"
 
-#ifndef _GEOCONCEPT_OGR_LAYER_H_INCLUDED_
-#define _GEOCONCEPT_OGR_LAYER_H_INCLUDED_
+#ifndef GEOCONCEPT_OGR_LAYER_H_INCLUDED_
+#define GEOCONCEPT_OGR_LAYER_H_INCLUDED_
 
 /**********************************************************************/
 /*            OGCGeoconceptLayer Class                           */
@@ -66,6 +66,8 @@ class OGRGeoconceptLayer : public OGRLayer
     OGRSpatialReference* GetSpatialRef( );
     GIntBig              GetFeatureCount( int bForce = TRUE );
     OGRErr               GetExtent( OGREnvelope *psExtent, int bForce = TRUE );
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
     int                  TestCapability( const char* pszCap );
 //    const char*          GetInfo( const char* pszTag );
     OGRErr               CreateField( OGRFieldDefn* poField, int bApproxOK = TRUE );
@@ -79,4 +81,4 @@ class OGRGeoconceptLayer : public OGRLayer
     void                   SetSpatialRef( OGRSpatialReference *poSpatialRef );
 };
 
-#endif /* _GEOCONCEPT_OGR_LAYER_H_INCLUDED_ */
+#endif /* GEOCONCEPT_OGR_LAYER_H_INCLUDED_ */
diff --git a/ogr/ogrsf_frmts/geojson/drv_geojson.html b/ogr/ogrsf_frmts/geojson/drv_geojson.html
index e7fbb8f..309b9ec 100644
--- a/ogr/ogrsf_frmts/geojson/drv_geojson.html
+++ b/ogr/ogrsf_frmts/geojson/drv_geojson.html
@@ -7,24 +7,24 @@
 
 <h1>GeoJSON</h1>
 
-<p>This driver implements read/write support for access to features encoded in  
-<a href="http://geojson.org/">GeoJSON</a> format. The GeoJSON is a dialect based on the 
-<a href="http://json.org/">JavaScript Object Notation (JSON)</a>. The JSON is a lightweight 
+<p>This driver implements read/write support for access to features encoded in
+<a href="http://geojson.org/">GeoJSON</a> format. GeoJSON is a dialect based on the
+<a href="http://json.org/">JavaScript Object Notation (JSON)</a>. JSON is a lightweight
 plain text format for data interchange and GeoJSON is nothing other than its specialization for geographic content.</p>
 
-<p>GeoJSON is supported as output format of a number of services :
+<p>GeoJSON is supported as an output format of a number of services:
 <a href="http://featureserver.org/">FeatureServer</a>,
-<a href="http://docs.geoserver.org/2.6.x/en/user/services/wfs/outputformats.html">GeoServer</a> ,
-<a href="http://exportgge.sourceforge.net/kml/">CartoWeb</a>, etc...</p>
+<a href="http://docs.geoserver.org/2.6.x/en/user/services/wfs/outputformats.html">GeoServer</a>,
+<a href="http://exportgge.sourceforge.net/kml/">CartoWeb</a>, etc.</p>
 
-<p>The OGR GeoJSON driver translates a GeoJSON encoded data to objects of <a href="/ogr/ogr_arch.html">OGR Simple Features model</a>: 
-Datasource, Layer, Feature, Geometry. 
+<p>The OGR GeoJSON driver translates GeoJSON encoded data to objects of the <a href="ogr_arch.html">OGR Simple Features model</a>:
+Datasource, Layer, Feature, Geometry.
 The implementation is based on <a href="http://geojson.org/geojson-spec.html">GeoJSON Specification, v1.0</a>.</p>
 
-<p>Starting with OGR 1.8.0, the GeoJSON driver can read the JSON output of Feature Service request following the
-<a href="http://www.esri.com/industries/landing-pages/geoservices/geoservices.html">GeoServices REST Specification<a/>, like
+<p>Starting with OGR 1.8.0, the GeoJSON driver can read the JSON output of Feature Service requests following the
+<a href="http://www.esri.com/industries/landing-pages/geoservices/geoservices.html">GeoServices REST Specification</a>, like
 implemented by <a href="http://help.arcgis.com/en/arcgisserver/10.0/apis/rest/index.html">ArcGIS Server REST API</a>.
-And starting with OGR 2.0, the GeoJSON driver can scroll through such result sets that
+Starting with OGR 2.0, the GeoJSON driver can scroll through such result sets that
 are spread over multiple pages (for ArcGIS servers >= 10.3). This is automatically enabled
 if URL does not contain an explicit <i>resultOffset</i> parameter. If it contains
 this parameter and scrolling is still desired, the FEATURE_SERVER_PAGING open option must be set to YES.
@@ -34,12 +34,16 @@ value allowed by the server.</p>
 
 <p>Starting with OGR 1.11, the GeoJSON driver can read the <a href="https://github.com/mbostock/topojson/wiki/Specification">TopoJSON format</a></p>
 
+<p>Starting with GDAL 2.1.0, the GeoJSON driver supports updating existing
+GeoJSON files. In that case, the default value for the NATIVE_DATA open option
+will be YES.</p>
+
 <h2>Datasource</h2>
 
-<p>The OGR GeoJSON driver accepts three types of sources of data:
+<p>The OGR GeoJSON driver accepts three types of sources of data:</p>
 <ul>
-<li>Uniform Resource Locator (<a href="http://en.wikipedia.org/wiki/URL">URL</a>) - a Web address to 
-    perform <a href="http://en.wikipedia.org/wiki/HTTP">HTTP</a> request</li>
+<li>Uniform Resource Locator (<a href="http://en.wikipedia.org/wiki/URL">URL</a>) - a Web address to
+perform <a href="http://en.wikipedia.org/wiki/HTTP">HTTP</a> request</li>
 <li>Plain text file with GeoJSON data - identified from the file extension .geojson or .json</li>
 <li>Text passed directly and encoded in GeoJSON</li>
 </ul>
@@ -52,44 +56,57 @@ ogrinfo -ro http://featureserver/data/.geojson OGRGeoJSON
 It's also valid to assume that OGRDataSource::GetLayerCount() for GeoJSON datasource always returns 1.
 </p>
 
-<p>Accessing Web Service as a datasource (ie. FeatureServer), each request will produce new layer.
+<p>Accessing Web Service as a datasource (i.e. FeatureServer), each request will produce new layer.
 This behavior conforms to stateless nature of HTTP transaction and is similar to how Web browsers operate:
 single request == single page.</p>
 
 <p>If a top-level member of GeoJSON data is of any other type than <em>FeatureCollection</em>, the driver will
 produce a layer with only one feature. Otherwise, a layer will consists of a set of features.</p>
 
+<p>If the NATIVE_DATA open option is set to YES, members at the level of the FeatureCollection will be
+stored as a serialized JSon object in the NATIVE_DATA item of the NATIVE_DATA metadata domain of the
+layer object (and "application/vnd.geo+json" in the NATIVE_MEDIA_TYPE of the NATIVE_DATA metadata domain).</p>
+
 <h2>Feature</h2>
 
 <p>The OGR GeoJSON driver maps each object of following types to new <em>OGRFeature</em> object:
 Point, LineString, Polygon, GeometryCollection, Feature.</p>
 
-<p>According to the <em>GeoJSON Specification</em>, only the <em>Feature</em> object must have a member with 
-name <em>properties</em>. Each and every member of <em>properties</em> is translated to OGR object of type of 
+<p>According to the <em>GeoJSON Specification</em>, only the <em>Feature</em> object must have a member with
+name <em>properties</em>. Each and every member of <em>properties</em> is translated to OGR object of type of
 OGRField and added to corresponding OGRFeature object.</p>
 
-<p>The <em>GeoJSON Specification</em> does not require all <em>Feature</em> objects in a collection must 
-have the same schema of properties. If <em>Feature</em> objects in a set defined by <em>FeatureCollection</em> 
-object have different schema of properties, then resulting schema of fields in OGRFeatureDefn is generated as 
+<p>The <em>GeoJSON Specification</em> does not require all <em>Feature</em> objects in a collection to
+have the same schema of properties. If <em>Feature</em> objects in a set defined by <em>FeatureCollection</em>
+object have different schema of properties, then resulting schema of fields in OGRFeatureDefn is generated as
 <a href="http://en.wikipedia.org/wiki/Union_(set_theory)">union</a> of all <em>Feature</em> properties.</p>
 
 <p>Schema detection will recognized fields of type String, Integer, Real, StringList, IntegerList and RealList.
 Starting with GDAL 2.0, Integer(Boolean), Date, Time and DateTime fields are also recognized.</p>
 
-<p>It is possible to tell the driver to not to process attributes by setting environment variable 
-<strong>ATTRIBUTES_SKIP=YES</strong>. Default behavior is to preserve all attributes (as an union, see previous paragraph), 
+<p>It is possible to tell the driver to not to process attributes by setting environment variable
+<strong>ATTRIBUTES_SKIP=YES</strong>. Default behavior is to preserve all attributes (as an union, see previous paragraph),
 what is equal to setting <strong>ATTRIBUTES_SKIP=NO</strong>.</p>
 
+<p>If the NATIVE_DATA open option is set to YES, the Feature JSon object will be
+stored as a serialized JSon object in the NativeData property of the OGRFeature object
+(and "application/vnd.geo+json" in the NativeMediaType property). On write, if
+a OGRFeature to be written has its NativeMediaType property set to "application/vnd.geo+json"
+and its NativeData property set to a string that is a serialized JSon object, then
+extra members of this object (i.e. not the "property" dictionary, nor the first 3
+dimensions of geometry coordinates) will be used to enhance the created JSon object from
+the OGRFeature. See <a href="https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr">RFC 60</a> for more details.</p>
+
 <h2>Geometry</h2>
 
-<p>Similarly to the issue with mixed-properties features, the <em>GeoJSON Specification</em> draft does not require 
-all <em>Feature</em> objects in a collection must have geometry of the same type. Fortunately, OGR objects model does 
-allow to have geometries of different types in single layer - a heterogeneous layer. By default, the GeoJSON driver 
+<p>Similarly to the issue with mixed-properties features, the <em>GeoJSON Specification</em> draft does not require
+all <em>Feature</em> objects in a collection must have geometry of the same type. Fortunately, OGR objects model does
+allow to have geometries of different types in single layer - a heterogeneous layer. By default, the GeoJSON driver
 preserves type of geometries.</p>
 
-<p>However, sometimes there is a need to generate homogeneous layer from a set of heterogeneous features. 
+<p>However, sometimes there is a need to generate a homogeneous layer from a set of heterogeneous features.
 For this purpose, it's possible to tell the driver to wrap all geometries with OGRGeometryCollection type as a common denominator.
-This behavior may be controlled by setting environment variable <strong>GEOMETRY_AS_COLLECTION=YES</strong> (default is <strong>NO</strong>).</p>
+This behavior may be controlled by setting <strong>GEOMETRY_AS_COLLECTION=YES</strong> in the environment (default is <strong>NO</strong>).</p>
 
 <h2>Environment variables</h2>
 
@@ -103,32 +120,39 @@ This behavior may be controlled by setting environment variable <strong>GEOMETRY
 <p>(GDAL >= 2.0)</p>
 
 <ul>
-<li><b>FLATTEN_NESTED_ATTRIBUTES</b> = YES/NO : Whether to
+<li><b>FLATTEN_NESTED_ATTRIBUTES</b> = YES/NO: Whether to
 recursively explore nested objects and produce flatten OGR attributes. Defaults to NO.</li>
-<li><b>NESTED_ATTRIBUTE_SEPARATOR</b> = character : Separator between components
+<li><b>NESTED_ATTRIBUTE_SEPARATOR</b> = character: Separator between components
 of nested attributes. Defaults to '_'</li>
 <li><b>FEATURE_SERVER_PAGING</b> = YES/NO: Whether to automatically scroll through
 results with a ArcGIS Feature Service endpoint.</li>
+<li><b>NATIVE_DATA</b> = YES/NO: (GDAL >= 2.1) Whether to store the native JSon representation at FeatureCollection and Feature level.
+Defaults to NO. This option can be used to improve round-tripping from GeoJSON to GeoJSON by preserving some extra
+JSon objects that would otherwise be ignored by the OGR abstraction. Note that
+ogr2ogr by default enable this option, unless you specify its -noNativeData switch.</li>
+<li><b>ARRAY_AS_STRING</b> = YES/NO: (GDAL >= 2.1) Whether to expose JSon arrays
+of strings, integers or reals as a OGR String. Default is NO. Can also be set with
+the OGR_GEOJSON_ARRAY_AS_STRING configuration option.</li>
 </ul>
 
-<p>To explain FLATTEN_NESTED_ATTRIBUTES, consider the following GeoJSON fragment :</p>
+<p>To explain FLATTEN_NESTED_ATTRIBUTES, consider the following GeoJSON fragment:</p>
 
 <pre>
 {
   "type": "FeatureCollection",
-  "features" :
+  "features":
   [
     {
       "type": "Feature",
       "geometry": {
         "type": "Point",
         "coordinates": [ 2, 49 ]
-      }, 
+      },
       "properties": {
-        "a_property": "foo", 
+        "a_property": "foo",
         "some_object": {
-          "a_property": 1, 
-          "another_property": 2 
+          "a_property": 1,
+          "another_property": 2
         }
       }
     }
@@ -136,7 +160,7 @@ results with a ArcGIS Feature Service endpoint.</li>
 }
 </pre>
 
-<p> "ogrinfo test.json -al -oo FLATTEN_NESTED_ATTRIBUTES=yes" reports :</p>
+<p>"ogrinfo test.json -al -oo FLATTEN_NESTED_ATTRIBUTES=yes" reports:</p>
 
 <pre>
 OGRFeature(OGRGeoJSON):0
@@ -146,23 +170,65 @@ OGRFeature(OGRGeoJSON):0
   POINT (2 49)
 </pre>
 
-<h2>Layer creation option</h2>
+<h2>Layer creation options</h2>
 
 <ul>
-<li><b>WRITE_BBOX</b> = YES/NO : (OGR >= 1.9.0) Set to YES to write a bbox property with the bounding box of the geometries at the feature and feature
+<li><b>WRITE_BBOX</b> = YES/NO: (OGR >= 1.9.0) Set to YES to write a bbox property with the bounding box of the geometries at the feature and feature
 collection level. Defaults to NO.</li>
-<li><b>COORDINATE_PRECISION</b> = int_number : (OGR >= 1.9.0) Maximum number of figures after decimal separator to write in coordinates.
+<li><b>COORDINATE_PRECISION</b> = int_number: (OGR >= 1.9.0) Maximum number of figures after decimal separator to write in coordinates.
 Default to 15. "Smart" truncation will occur to remove trailing zeros.</li>
+<li><b>SIGNIFICANT_FIGURES</b> = int_number: (OGR >= 2.1) Maximum number of significant figures when writing floating-point numbers.
+Default to 17. If explicitly specified, and COORDINATE_PRECISION is not, this will also apply to coordinates.</li>
+<li><b>NATIVE_DATA</b>=string. (OGR >= 2.1) Serialized JSon object that contains extra properties to store at FeatureCollection level.</li>
+<li><b>NATIVE_MEDIA_TYPE</b>=string. (OGR >= 2.1) Format of NATIVE_DATA. Must be "application/vnd.geo+json", otherwise NATIVE_DATA will be ignored.</li>
 </ul>
 
 <h2>VSI Virtual File System API support</h2>
 
-(Some features below might require OGR >= 1.9.0)<p>
+<p>Some features below require OGR >= 1.9.0.</p>
+
+<p>The driver supports reading and writing to files managed by VSI Virtual File System API, which includes
+"regular" files, as well as files in the /vsizip/ (read-write), /vsigzip/ (read-write), /vsicurl/ (read-only) domains.</p>
+
+<p>Writing to /dev/stdout or /vsistdout/ is also supported.</p>
+
+<h2>Round-tripping of extra JSon members</h2>
 
-The driver supports reading and writing to files managed by VSI Virtual File System API, which include
-"regular" files, as well as files in the /vsizip/ (read-write) , /vsigzip/ (read-write) , /vsicurl/ (read-only) domains.<p>
+<p>See <a href="https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr">RFC 60</a> for more details.</p>
 
-Writing to /dev/stdout or /vsistdout/ is also supported.<p>
+<p>Starting with GDAL 2.1, extra JSon members at the FeatureCollection, Feature or
+geometry levels that are not normally reflected in the OGR abstraction,
+such as the ones called "extra_XXXXX_member" in the below
+snippet, are by default preserved when executing ogr2ogr with GeoJSON both at the
+source and destination. This also applies to extra values in position tuples
+of geometries, beyond the 3rd dimension (100, 101 in the below example), if the
+transformation preserves the geometry structure (for example, reprojection is allowed, but not
+change in the number of coordinates).</p>
+
+<pre>
+{
+  "type": "FeatureCollection",
+  <b>"extra_fc_member": "foo",</b>
+  "features":
+  [
+    {
+      "type": "Feature",
+      <b>"extra_feat_member": "bar",</b>
+      "geometry": {
+        "type": "Point",
+        <b>"extra_geom_member": "baz",</b>
+        "coordinates": [ 2, 49, 3, <b>100, 101</b> ]
+      },
+      "properties": {
+        "a_property": "foo",
+      }
+    }
+  ]
+}
+</pre>
+
+<p>This behaviour can be turned off by specifying the <b>-noNativeData</b> switch
+of the ogr2ogr utility.</p>
 
 <h2>Example</h2>
 
@@ -198,10 +264,9 @@ ogrinfo -ro -al "http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/Hydr
 <li><a href="http://json.org/">JSON</a> - JavaScript Object Notation</li>
 <li><a href="http://oss.metaparadigm.com/json-c/">JSON-C</a> - A JSON implementation in C</li>
 <li><a href="http://lists.osgeo.org/pipermail/gdal-dev/2007-November/014746.html">[Gdal-dev] OGR GeoJSON Driver</a> - driver announcement</li>
-<li><a href="http://www.esri.com/industries/landing-pages/geoservices/geoservices.html">GeoServices REST Specification<a/></li>
+<li><a href="http://www.esri.com/industries/landing-pages/geoservices/geoservices.html">GeoServices REST Specification</a></li>
 </ul>
 </p>
 
 </body>
 </html>
-
diff --git a/ogr/ogrsf_frmts/geojson/libjson/ChangeLog b/ogr/ogrsf_frmts/geojson/libjson/ChangeLog
index 4e74c90..4f63f31 100644
--- a/ogr/ogrsf_frmts/geojson/libjson/ChangeLog
+++ b/ogr/ogrsf_frmts/geojson/libjson/ChangeLog
@@ -31,8 +31,8 @@
   * Add an alternative iterator implementation, see json_object_iterator.h
   * Make json_object_iter public to enable external use of the
      json_object_object_foreachC macro.
-  * Add a printbuf_memset() function to provide an effecient way to set and
-     append things like whitespace indentation.
+  * Add a printbuf_memset() function to provide an efficient way to set and
+     append things like white-space indentation.
   * Adjust json_object_is_type and json_object_get_type so they return
       json_type_null for NULL objects and handle NULL passed to
       json_objct_object_get().
@@ -95,7 +95,7 @@
     to not return TRUE for zero length string. Remove redundant includes.
     Erik Hovland, erik at hovland dot org
   * Fixed warning reported by adding -Wstrict-prototypes
-    -Wold-style-definition to the compilatin flags.
+    -Wold-style-definition to the compilation flags.
     Dotan Barak, dotanba at gmail dot com
   * Add const correctness to public interfaces
     Gerard Krol, g dot c dot krol at student dot tudelft dot nl
@@ -113,14 +113,14 @@
     Geoffrey Young, geoff at modperlcookbook dot org
 
 0.7
-  * Add escaping of backslash to json output
-  * Add escaping of foward slash on tokenizing and output
+  * Add escaping of backslash to JSON output
+  * Add escaping of forward slash on tokenizing and output
   * Changes to internal tokenizer from using recursion to
     using a depth state structure to allow incremental parsing
 
 0.6
   * Fix bug in escaping of control characters
-    Johan Bj�rklund, johbjo09 at kth dot se
+    Johan Björklund, johbjo09 at kth dot se
   * Remove include "config.h" from headers (should only
     be included from .c files)
     Michael Clark <michael at metaparadigm.com>
@@ -166,7 +166,7 @@
     Added cast and mask to suffice size_t v. unsigned int conversion
     correctness 
   * json_tokener.c - sign reversal issue on error info for nested object parse
-    spotted by Johan Bj�rklund (johbjo09 at kth.se)
+    spotted by Johan Björklund (johbjo09 at kth.se)
   * json_object.c - escape " in json_escape_str
   * Change to automake and libtool to build shared and static library
     Michael Clark <michael at metaparadigm.com>
diff --git a/ogr/ogrsf_frmts/geojson/libjson/GNUmakefile b/ogr/ogrsf_frmts/geojson/libjson/GNUmakefile
index 3aaf445..2ee2cc0 100644
--- a/ogr/ogrsf_frmts/geojson/libjson/GNUmakefile
+++ b/ogr/ogrsf_frmts/geojson/libjson/GNUmakefile
@@ -1,6 +1,6 @@
 # $Id$
 #
-# Makefile building jcon-c library (http://oss.metaparadigm.com/json-c/)
+# Makefile building json-c library (http://oss.metaparadigm.com/json-c/)
 # 
 include ../../../../GDALmake.opt
 
@@ -22,8 +22,10 @@ CPPFLAGS := $(CPPFLAGS)
 default:	$(O_OBJ:.o=.$(OBJ_EXT))
 
 # -D_XOPEN_SOURCE=500 to enable strdup() definition in C11 mode
+CPPFLAGS := -D_XOPEN_SOURCE=500 $(CPPFLAGS)
+
 ../../o/%.$(OBJ_EXT):	%.c
-	$(CC) $(CFLAGS) $(CPPFLAGS) -D_XOPEN_SOURCE=500 -c -o $@ $<
+	$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
 
 clean:
 	rm -f *.o $(O_OBJ)
diff --git a/ogr/ogrsf_frmts/geojson/libjson/README.html b/ogr/ogrsf_frmts/geojson/libjson/README.html
index 7c2f9f4..cc309b1 100644
--- a/ogr/ogrsf_frmts/geojson/libjson/README.html
+++ b/ogr/ogrsf_frmts/geojson/libjson/README.html
@@ -1,34 +1,34 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-	<head>
-		<title>JSON-C - A JSON implementation in C</title>
-		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
-	</head>
-	<body>
-		<h2>JSON-C - A JSON implementation in C</h2>
-
-		<h3>Overview</h3>
-		<p>JSON-C implements a reference counting object model that allows you to easily 
-		construct JSON objects in C, output them as JSON formatted strings and parse 
-		JSON formatted strings back into the C representation of JSON objects.</p>
-
-		<h3>Building</h3>
-		<p>To setup JSON-C to build on your system please run <tt>configure</tt> and <tt>make</tt>.</p>
-		<p>If you are on Win32 and are not using the VS project file, be sure 
-		to rename <tt>config.h.win32</tt> to <tt>config.h</tt> before building.</p>
-
-		<h3>Documentation</h3>
-		<P>Doxygen generated documentation exists <a href="doc/html/json__object_8h.html">here</a>
-		and Win32 specific notes can be found <a href="README-WIN32.html">here</a>.</P>
-
-		<h3><a href="https://github.com/json-c/json-c">GIT Reposository</a></h3>
-		<p><strong><code>git clone https://github.com/json-c/json-c.git</code></strong></p>
-
-		<h3><a href="http://groups.google.com/group/json-c">Mailing List</a></h3>
-                <pi>Send email to <strong><code>json-c <i><at></i> googlegroups <i><dot></i> com</code></strong></p>
-
-		<h3><a href="COPYING">License</a></h3>
-		<p>This program is free software; you can redistribute it and/or modify it under the terms of the MIT License..</p>
-		<hr/>
-	</body>
-</html>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+	<head>
+		<title>JSON-C - A JSON implementation in C</title>
+		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	</head>
+	<body>
+		<h2>JSON-C - A JSON implementation in C</h2>
+
+		<h3>Overview</h3>
+		<p>JSON-C implements a reference counting object model that allows you to easily
+		construct JSON objects in C, output them as JSON formatted strings and parse
+		JSON formatted strings back into the C representation of JSON objects.</p>
+
+		<h3>Building</h3>
+		<p>To setup JSON-C to build on your system please run <tt>configure</tt> and <tt>make</tt>.</p>
+		<p>If you are on Win32 and are not using the VS project file, be sure
+		to rename <tt>config.h.win32</tt> to <tt>config.h</tt> before building.</p>
+
+		<h3>Documentation</h3>
+		<P>Doxygen generated documentation exists <a href="doc/html/json__object_8h.html">here</a>
+		and Win32 specific notes can be found <a href="README-WIN32.html">here</a>.</P>
+
+		<h3><a href="https://github.com/json-c/json-c">GIT Reposository</a></h3>
+		<p><strong><code>git clone https://github.com/json-c/json-c.git</code></strong></p>
+
+		<h3><a href="http://groups.google.com/group/json-c">Mailing List</a></h3>
+                <pi>Send email to <strong><code>json-c <i><at></i> googlegroups <i><dot></i> com</code></strong></p>
+
+		<h3><a href="COPYING">License</a></h3>
+		<p>This program is free software; you can redistribute it and/or modify it under the terms of the MIT License..</p>
+		<hr/>
+	</body>
+</html>
diff --git a/ogr/ogrsf_frmts/geojson/libjson/arraylist.c b/ogr/ogrsf_frmts/geojson/libjson/arraylist.c
index 81b6fa2..72cbb2b 100644
--- a/ogr/ogrsf_frmts/geojson/libjson/arraylist.c
+++ b/ogr/ogrsf_frmts/geojson/libjson/arraylist.c
@@ -63,7 +63,12 @@ static int array_list_expand_internal(struct array_list *arr, int max)
   int new_size;
 
   if(max < arr->size) return 0;
-  new_size = json_max(arr->size << 1, max);
+  if( arr->size < 0x7FFFFFFF / 2 )
+    new_size = json_max(arr->size << 1, max);
+  else
+    new_size = max;
+  if( (size_t)new_size > (~(size_t)0) / sizeof(void*) )
+      return -1;
   if(!(t = realloc(arr->array, new_size*sizeof(void*)))) return -1;
   arr->array = (void**)t;
   (void)memset(arr->array + arr->size, 0, (new_size-arr->size)*sizeof(void*));
@@ -74,6 +79,7 @@ static int array_list_expand_internal(struct array_list *arr, int max)
 int
 array_list_put_idx(struct array_list *arr, int idx, void *data)
 {
+  if( idx > 0x7FFFFFFF - 1 ) return -1;
   if(array_list_expand_internal(arr, idx+1)) return -1;
   if(arr->array[idx]) arr->free_fn(arr->array[idx]);
   arr->array[idx] = data;
diff --git a/ogr/ogrsf_frmts/geojson/libjson/arraylist.h b/ogr/ogrsf_frmts/geojson/libjson/arraylist.h
index 4f3113c..9193b6e 100644
--- a/ogr/ogrsf_frmts/geojson/libjson/arraylist.h
+++ b/ogr/ogrsf_frmts/geojson/libjson/arraylist.h
@@ -9,8 +9,8 @@
  *
  */
 
-#ifndef _arraylist_h_
-#define _arraylist_h_
+#ifndef arraylist_h_
+#define arraylist_h_
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/ogr/ogrsf_frmts/geojson/libjson/bits.h b/ogr/ogrsf_frmts/geojson/libjson/bits.h
index c8cbbc8..1e27e6b 100644
--- a/ogr/ogrsf_frmts/geojson/libjson/bits.h
+++ b/ogr/ogrsf_frmts/geojson/libjson/bits.h
@@ -9,8 +9,8 @@
  *
  */
 
-#ifndef _bits_h_
-#define _bits_h_
+#ifndef bits_h_
+#define bits_h_
 
 #ifndef json_min
 #define json_min(a,b) ((a) < (b) ? (a) : (b))
diff --git a/ogr/ogrsf_frmts/geojson/libjson/debug.c b/ogr/ogrsf_frmts/geojson/libjson/debug.c
index e0294ca..2480523 100644
--- a/ogr/ogrsf_frmts/geojson/libjson/debug.c
+++ b/ogr/ogrsf_frmts/geojson/libjson/debug.c
@@ -91,7 +91,7 @@ void mc_info(const char *msg, ...)
 #if HAVE_VSYSLOG
     if(_syslog) {
 		vsyslog(LOG_INFO, msg, ap);
-	} else 
+	} else
 #endif
 		vfprintf(stderr, msg, ap);
   va_end(ap);
diff --git a/ogr/ogrsf_frmts/geojson/libjson/debug.h b/ogr/ogrsf_frmts/geojson/libjson/debug.h
index 9a59574..26db0ce 100644
--- a/ogr/ogrsf_frmts/geojson/libjson/debug.h
+++ b/ogr/ogrsf_frmts/geojson/libjson/debug.h
@@ -10,8 +10,8 @@
  *
  */
 
-#ifndef _DEBUG_H_
-#define _DEBUG_H_
+#ifndef DEBUG_H_
+#define DEBUG_H_
 
 #include <stdlib.h>
 
diff --git a/ogr/ogrsf_frmts/geojson/libjson/json.h b/ogr/ogrsf_frmts/geojson/libjson/json.h
index 4339b20..730bf8d 100644
--- a/ogr/ogrsf_frmts/geojson/libjson/json.h
+++ b/ogr/ogrsf_frmts/geojson/libjson/json.h
@@ -10,8 +10,8 @@
  *
  */
 
-#ifndef _json_h_
-#define _json_h_
+#ifndef json_h_
+#define json_h_
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/ogr/ogrsf_frmts/geojson/libjson/json_c_version.h b/ogr/ogrsf_frmts/geojson/libjson/json_c_version.h
index ff20f95..5f65fa5 100644
--- a/ogr/ogrsf_frmts/geojson/libjson/json_c_version.h
+++ b/ogr/ogrsf_frmts/geojson/libjson/json_c_version.h
@@ -5,8 +5,8 @@
  * it under the terms of the MIT license. See COPYING for details.
  */
 
-#ifndef _json_c_version_h_
-#define _json_c_version_h_
+#ifndef json_c_version_h_
+#define json_c_version_h_
 
 #define JSON_C_MAJOR_VERSION 0
 #define JSON_C_MINOR_VERSION 11
diff --git a/ogr/ogrsf_frmts/geojson/libjson/json_inttypes.h b/ogr/ogrsf_frmts/geojson/libjson/json_inttypes.h
index 9de8d24..be01bd4 100644
--- a/ogr/ogrsf_frmts/geojson/libjson/json_inttypes.h
+++ b/ogr/ogrsf_frmts/geojson/libjson/json_inttypes.h
@@ -1,6 +1,6 @@
 
-#ifndef _json_inttypes_h_
-#define _json_inttypes_h_
+#ifndef json_inttypes_h_
+#define json_inttypes_h_
 
 #include "json_config.h"
 
@@ -20,9 +20,26 @@ typedef __int64 int64_t;
 
 #ifdef JSON_C_HAVE_INTTYPES_H
 #include <inttypes.h>
+#if defined(__MSVCRT__)
+#  undef PRId64
+#  define PRId64 "I64d"
+#endif
 #endif
 /* inttypes.h includes stdint.h */
 
+#ifndef PRId64
+#define PRId64 "lld"
+#endif
+#ifndef SCNd64
+#define SCNd64 "lld"
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
+#ifndef INT64_MIN
+#define INT64_MIN (-9223372036854775807LL-1)
+#endif
+
 #endif
 
 #endif
diff --git a/ogr/ogrsf_frmts/geojson/libjson/json_object.c b/ogr/ogrsf_frmts/geojson/libjson/json_object.c
index 867754e..26758f2 100644
--- a/ogr/ogrsf_frmts/geojson/libjson/json_object.c
+++ b/ogr/ogrsf_frmts/geojson/libjson/json_object.c
@@ -10,7 +10,7 @@
  *
  */
 
-#include "cpl_conv.h"
+#include "cpl_string.h"
 
 #include "config.h"
 
@@ -28,6 +28,9 @@
 #include "json_object_private.h"
 #include "json_util.h"
 
+#undef snprintf
+#define snprintf CPLsnprintf
+
 #if !defined(HAVE_STRDUP) && defined(_MSC_VER)
   /* MSC has the version as _strdup */
 # define strdup _strdup
@@ -299,7 +302,8 @@ static int json_object_object_to_json_string(struct json_object* jso,
 	sprintbuf(pb, "{" /*}*/);
 	if (flags & JSON_C_TO_STRING_PRETTY)
 		sprintbuf(pb, "\n");
-	json_object_object_foreachC(jso, iter)
+        /* the if() is to make gcc 6 -Wnull-dereference happy */
+	if( jso->o_type == json_type_object) json_object_object_foreachC(jso, iter)
 	{
 		if (had_children)
 		{
@@ -312,7 +316,7 @@ static int json_object_object_to_json_string(struct json_object* jso,
 			sprintbuf(pb, " ");
 		indent(pb, level+1, flags);
 		sprintbuf(pb, "\"");
-		json_escape_str(pb, iter.key, strlen(iter.key));
+		json_escape_str(pb, iter.key, (int)strlen(iter.key));
 		if (flags & JSON_C_TO_STRING_SPACED)
 			sprintbuf(pb, "\": ");
 		else
@@ -575,7 +579,7 @@ static int json_object_double_to_json_string(struct json_object* jso,
     }
     /* drop trailing zeroes */
     *(++p) = 0;
-    size = p-buf;
+    size = (int)(p-buf);
   }
   printbuf_memappend(pb, buf, size);
   return size;
@@ -634,7 +638,7 @@ struct json_object* json_object_new_string(const char *s)
   jso->_delete = &json_object_string_delete;
   jso->_to_json_string = &json_object_string_to_json_string;
   jso->o.c_string.str = strdup(s);
-  jso->o.c_string.len = strlen(s);
+  jso->o.c_string.len = (int)strlen(s);
   return jso;
 }
 
@@ -735,6 +739,11 @@ struct json_object* json_object_new_array(void)
   jso->_delete = &json_object_array_delete;
   jso->_to_json_string = &json_object_array_to_json_string;
   jso->o.c_array = array_list_new(&json_object_array_entry_free);
+  if( jso->o.c_array == NULL )
+  {
+      free(jso);
+      jso = NULL;
+  }
   return jso;
 }
 
diff --git a/ogr/ogrsf_frmts/geojson/libjson/json_object.h b/ogr/ogrsf_frmts/geojson/libjson/json_object.h
index 3875805..27ef4fa 100644
--- a/ogr/ogrsf_frmts/geojson/libjson/json_object.h
+++ b/ogr/ogrsf_frmts/geojson/libjson/json_object.h
@@ -10,8 +10,8 @@
  *
  */
 
-#ifndef _json_object_h_
-#define _json_object_h_
+#ifndef json_object_h_
+#define json_object_h_
 
 #include "symbol_renames.h"
 #include "cpl_port.h"
@@ -106,7 +106,7 @@ typedef enum json_type {
 /* reference counting functions */
 
 /**
- * Increment the reference count of json_object, thereby grabbing shared 
+ * Increment the reference count of json_object, thereby grabbing shared
  * ownership of obj.
  *
  * @param obj the json_object instance
@@ -173,7 +173,7 @@ flags);
  * Set a custom serialization function to be used when this particular object
  * is converted to a string by json_object_to_json_string.
  *
- * If a custom serializer is already set on this object, any existing 
+ * If a custom serializer is already set on this object, any existing
  * user_delete function is called before the new one is set.
  *
  * If to_string_func is NULL, the other parameters are ignored
@@ -265,9 +265,9 @@ extern void CPL_DLL json_object_object_add(struct json_object* obj, const char *
 extern struct json_object* json_object_object_get(struct json_object* obj,
 						  const char *key);
 
-/** Get the json_object associated with a given object field.  
+/** Get the json_object associated with a given object field.
  *
- * This returns true if the key is found, false in all other cases (including 
+ * This returns true if the key is found, false in all other cases (including
  * if obj isn't a json_type_object).
  *
  * *No* reference counts will be changed.  There is no need to manually adjust
@@ -277,7 +277,7 @@ extern struct json_object* json_object_object_get(struct json_object* obj,
  *
  * @param obj the json_object instance
  * @param key the object field name
- * @param value a pointer where to store a reference to the json_object 
+ * @param value a pointer where to store a reference to the json_object
  *              associated with the given field name.
  *
  *              It is safe to pass a NULL value.
@@ -346,7 +346,7 @@ extern void json_object_object_del(struct json_object* obj, const char *key);
  * @param iter the object iterator
  */
 #define json_object_object_foreachC(obj,iter) \
- for(iter.entry = json_object_get_object(obj)->head; (iter.entry ? (iter.key = (char*)iter.entry->k, iter.val = (struct json_object*)iter.entry->v, iter.entry) : 0); iter.entry = iter.entry->next)
+ for(iter.entry = json_object_get_object(obj)->head; (iter.entry ? (iter.key = (char*)iter.entry->k, iter.val = (struct json_object*)iter.entry->v, 1) : 0); iter.entry = iter.entry->next)
 
 /* Array type methods */
 
@@ -407,7 +407,7 @@ extern int CPL_DLL json_object_array_add(struct json_object *obj,
 extern int json_object_array_put_idx(struct json_object *obj, int idx,
 				     struct json_object *val);
 
-/** Get the element at specificed index of the array (a json_object of type json_type_array)
+/** Get the element at specified index of the array (a json_object of type json_type_array)
  * @param obj the json_object instance
  * @param idx the index to get the element at
  * @returns the json_object at the specified index (or NULL)
diff --git a/ogr/ogrsf_frmts/geojson/libjson/json_object_private.h b/ogr/ogrsf_frmts/geojson/libjson/json_object_private.h
index 5ed791b..3d838d8 100644
--- a/ogr/ogrsf_frmts/geojson/libjson/json_object_private.h
+++ b/ogr/ogrsf_frmts/geojson/libjson/json_object_private.h
@@ -9,8 +9,8 @@
  *
  */
 
-#ifndef _json_object_private_h_
-#define _json_object_private_h_
+#ifndef json_object_private_h_
+#define json_object_private_h_
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/ogr/ogrsf_frmts/geojson/libjson/json_tokener.c b/ogr/ogrsf_frmts/geojson/libjson/json_tokener.c
index 1e28257..42c1a45 100644
--- a/ogr/ogrsf_frmts/geojson/libjson/json_tokener.c
+++ b/ogr/ogrsf_frmts/geojson/libjson/json_tokener.c
@@ -76,7 +76,7 @@ const char* json_tokener_errors[] = {
 const char *json_tokener_error_desc(enum json_tokener_error jerr)
 {
 	int jerr_int = (int)jerr;
-	if (jerr_int < 0 || jerr_int > (int)sizeof(json_tokener_errors))
+	if (jerr_int < 0 || jerr_int >= (int)(sizeof(json_tokener_errors) / sizeof(json_tokener_errors[0])))
 		return "Unknown error, invalid json_tokener_error value passed to json_tokener_error_desc()";
 	return json_tokener_errors[jerr];
 }
@@ -260,11 +260,15 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
 	state = json_tokener_state_eatws;
 	saved_state = json_tokener_state_object_field_start;
 	current = json_object_new_object();
+        if( current == NULL )
+            goto out;
 	break;
       case '[':
 	state = json_tokener_state_eatws;
 	saved_state = json_tokener_state_array;
 	current = json_object_new_array();
+        if( current == NULL )
+            goto out;
 	break;
       case 'N':
       case 'n':
@@ -396,6 +400,8 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
 	  if(c == tok->quote_char) {
 	    printbuf_memappend_fast(tok->pb, case_start, str-case_start);
 	    current = json_object_new_string_len(tok->pb->buf, tok->pb->bpos);
+            if( current == NULL )
+                goto out;
 	    saved_state = json_tokener_state_finish;
 	    state = json_tokener_state_eatws;
 	    break;
@@ -457,14 +463,14 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
 
                 if (got_hi_surrogate) {
 		  if (IS_LOW_SURROGATE(tok->ucs_char)) {
-                    /* Recalculate the ucs_char, then fall thru to process normally */
+                    /* Recalculate the ucs_char, then fall through to process normally */
                     tok->ucs_char = DECODE_SURROGATE_PAIR(got_hi_surrogate, tok->ucs_char);
                   } else {
                     /* Hi surrogate was not followed by a low surrogate */
                     /* Replace the hi and process the rest normally */
 		    printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
                   }
-                  got_hi_surrogate = 0;
+                  /*got_hi_surrogate = 0;*/
                 }
 
 		if (tok->ucs_char < 0x80) {
@@ -550,6 +556,8 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
 		     json_min(tok->st_pos+1, (int)strlen(json_true_str))) == 0) {
 	if(tok->st_pos == (int)strlen(json_true_str)) {
 	  current = json_object_new_boolean(1);
+          if( current == NULL )
+              goto out;
 	  saved_state = json_tokener_state_finish;
 	  state = json_tokener_state_eatws;
 	  goto redo_char;
@@ -558,6 +566,8 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
 			    json_min(tok->st_pos+1, (int)strlen(json_false_str))) == 0) {
 	if(tok->st_pos == (int)strlen(json_false_str)) {
 	  current = json_object_new_boolean(0);
+          if( current == NULL )
+              goto out;
 	  saved_state = json_tokener_state_finish;
 	  state = json_tokener_state_eatws;
 	  goto redo_char;
@@ -590,9 +600,13 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
 	int64_t num64;
 	double  numd;
 	if (!tok->is_double && json_parse_int64(tok->pb->buf, &num64) == 0) {
-		current = json_object_new_int64(num64);
+            current = json_object_new_int64(num64);
+            if( current == NULL )
+              goto out;
 	} else if(tok->is_double && json_parse_double(tok->pb->buf, &numd) == 0) {
           current = json_object_new_double(numd);
+          if( current == NULL )
+              goto out;
         } else {
           tok->err = json_tokener_error_parse_number;
           goto out;
@@ -627,7 +641,10 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
       break;
 
     case json_tokener_state_array_add:
-      json_object_array_add(current, obj);
+      if( json_object_array_add(current, obj) != 0 )
+      {
+          goto out;
+      }
       saved_state = json_tokener_state_array_sep;
       state = json_tokener_state_eatws;
       goto redo_char;
diff --git a/ogr/ogrsf_frmts/geojson/libjson/json_tokener.h b/ogr/ogrsf_frmts/geojson/libjson/json_tokener.h
index 08e5ff7..247ae01 100644
--- a/ogr/ogrsf_frmts/geojson/libjson/json_tokener.h
+++ b/ogr/ogrsf_frmts/geojson/libjson/json_tokener.h
@@ -9,8 +9,8 @@
  *
  */
 
-#ifndef _json_tokener_h_
-#define _json_tokener_h_
+#ifndef json_tokener_h_
+#define json_tokener_h_
 
 #include <stddef.h>
 #include "json_object.h"
@@ -105,8 +105,8 @@ struct json_tokener
  */
 const char *json_tokener_error_desc(enum json_tokener_error jerr);
 
-/** 
- * @b XXX do not use json_tokener_errors directly.  
+/**
+ * @b XXX do not use json_tokener_errors directly.
  * After v0.10 this will be removed.
  *
  * See json_tokener_error_desc() instead.
@@ -136,16 +136,16 @@ extern struct json_object* json_tokener_parse_verbose(const char *str, enum json
  */
 extern void json_tokener_set_flags(struct json_tokener *tok, int flags);
 
-/** 
+/**
  * Parse a string and return a non-NULL json_object if a valid JSON value
  * is found.  The string does not need to be a JSON object or array;
  * it can also be a string, number or boolean value.
  *
  * A partial JSON string can be parsed.  If the parsing is incomplete,
- * NULL will be returned and json_tokener_get_error() will be return 
+ * NULL will be returned and json_tokener_get_error() will be return
  * json_tokener_continue.
  * json_tokener_parse_ex() can then be called with additional bytes in str
- * to continue the parsing.  
+ * to continue the parsing.
  *
  * If json_tokener_parse_ex() returns NULL and the error anything other than
  * json_tokener_continue, a fatal error has occurred and parsing must be
@@ -157,11 +157,11 @@ extern void json_tokener_set_flags(struct json_tokener *tok, int flags);
  * Be sure to check the type with json_object_is_type() or
  * json_object_get_type() before using the object.
  *
- * @b XXX this shouldn't use internal fields:
- * Trailing characters after the parsed value do not automatically cause an 
+ * @b XXX this should not use internal fields:
+ * Trailing characters after the parsed value do not automatically cause an
  * error.  It is up to the caller to decide whether to treat this as an
  * error or to handle the additional characters, perhaps by parsing another
- * json value starting from that point.
+ * JSON value starting from that point.
  *
  * Extra characters can be detected by comparing the tok->char_offset against
  * the length of the last len parameter passed in.
diff --git a/ogr/ogrsf_frmts/geojson/libjson/json_util.c b/ogr/ogrsf_frmts/geojson/libjson/json_util.c
index bd1e0ca..e6f7477 100644
--- a/ogr/ogrsf_frmts/geojson/libjson/json_util.c
+++ b/ogr/ogrsf_frmts/geojson/libjson/json_util.c
@@ -46,13 +46,6 @@
 # define open _open
 #endif
 
-#if !defined(HAVE_SNPRINTF) && defined(_MSC_VER)
-  /* MSC has the version as _snprintf */
-# define snprintf _snprintf
-#elif !defined(HAVE_SNPRINTF)
-# error You do not have snprintf on your system.
-#endif /* HAVE_SNPRINTF */
-
 #include "bits.h"
 #include "debug.h"
 #include "printbuf.h"
@@ -61,7 +54,10 @@
 #include "json_tokener.h"
 #include "json_util.h"
 
-#include "cpl_conv.h"
+#include "cpl_string.h"
+#undef snprintf
+#define snprintf CPLsnprintf
+
 static int sscanf_is_broken = 0;
 static int sscanf_is_broken_testdone = 0;
 static void sscanf_is_broken_test(void);
@@ -83,7 +79,7 @@ struct json_object* json_object_from_file(const char *filename)
     MC_ERROR("json_object_from_file: printbuf_new failed\n");
     return NULL;
   }
-  while((ret = read(fd, buf, JSON_FILE_BUF_SIZE)) > 0) {
+  while((ret = (int)read(fd, buf, JSON_FILE_BUF_SIZE)) > 0) {
     printbuf_memappend(pb, buf, ret);
   }
   close(fd);
@@ -125,7 +121,7 @@ int json_object_to_file_ext(char *filename, struct json_object *obj, int flags)
   wsize = (unsigned int)(strlen(json_str) & UINT_MAX); /* CAW: probably unnecessary, but the most 64bit safe */
   wpos = 0;
   while(wpos < wsize) {
-    if((ret = write(fd, json_str + wpos, wsize-wpos)) < 0) {
+    if((ret = (int)write(fd, json_str + wpos, wsize-wpos)) < 0) {
       close(fd);
       MC_ERROR("json_object_to_file: error writing file %s: %s\n",
 	     filename, strerror(errno));
@@ -237,7 +233,7 @@ int json_parse_int64(const char *buf, int64_t *retval)
 		}
 		// No need to skip leading spaces or zeros here.
 
-		buf_cmp_len = strlen(buf_cmp_start);
+		buf_cmp_len = (int)strlen(buf_cmp_start);
 		/**
 		 * If the sign is different, or
 		 * some of the digits are different, or
diff --git a/ogr/ogrsf_frmts/geojson/libjson/json_util.h b/ogr/ogrsf_frmts/geojson/libjson/json_util.h
index b9a69c8..61ce826 100644
--- a/ogr/ogrsf_frmts/geojson/libjson/json_util.h
+++ b/ogr/ogrsf_frmts/geojson/libjson/json_util.h
@@ -9,8 +9,8 @@
  *
  */
 
-#ifndef _json_util_h_
-#define _json_util_h_
+#ifndef json_util_h_
+#define json_util_h_
 
 #include "json_object.h"
 
diff --git a/ogr/ogrsf_frmts/geojson/libjson/linkhash.c b/ogr/ogrsf_frmts/geojson/libjson/linkhash.c
index 5043148..c008531 100644
--- a/ogr/ogrsf_frmts/geojson/libjson/linkhash.c
+++ b/ogr/ogrsf_frmts/geojson/libjson/linkhash.c
@@ -43,7 +43,7 @@ unsigned long lh_char_hash(const void *k)
 {
 	unsigned int h = 0;
 	const char* data = (const char*)k;
- 
+
 	while( *data!=0 ) h = h*129 + (unsigned int)(*data++) + LH_PRIME;
 
 	return h;
diff --git a/ogr/ogrsf_frmts/geojson/libjson/linkhash.h b/ogr/ogrsf_frmts/geojson/libjson/linkhash.h
index 378de0b..9e08567 100644
--- a/ogr/ogrsf_frmts/geojson/libjson/linkhash.h
+++ b/ogr/ogrsf_frmts/geojson/libjson/linkhash.h
@@ -9,9 +9,9 @@
  * it under the terms of the MIT license. See COPYING for details.
  *
  */
- 
-#ifndef _linkhash_h_
-#define _linkhash_h_
+
+#ifndef linkhash_h_
+#define linkhash_h_
 
 #include "json_object.h"
 
@@ -26,7 +26,7 @@ extern "C" {
 
 /**
  * The fraction of filled hash buckets until an insert will cause the table
- * to be resized.  
+ * to be resized.
  * This can range from just above 0 up to 1.0.
  */
 #define LH_LOAD_FACTOR 0.66
@@ -282,7 +282,7 @@ extern int lh_table_delete(struct lh_table *t, const void *k);
 
 extern int lh_table_length(struct lh_table *t);
 
-void lh_abort(const char *msg, ...);
+void lh_abort(const char *msg, ...) CPL_NO_RETURN;
 void lh_table_resize(struct lh_table *t, int new_size);
 
 #ifdef __cplusplus
diff --git a/ogr/ogrsf_frmts/geojson/libjson/makefile.vc b/ogr/ogrsf_frmts/geojson/libjson/makefile.vc
index 17ae024..e15e4bf 100644
--- a/ogr/ogrsf_frmts/geojson/libjson/makefile.vc
+++ b/ogr/ogrsf_frmts/geojson/libjson/makefile.vc
@@ -1,6 +1,6 @@
 # $Id$
 #
-# Makefile building jcon-c library (http://oss.metaparadigm.com/json-c/)
+# Makefile building json-c library (http://oss.metaparadigm.com/json-c/)
 # 
 
 OBJ = \
@@ -18,7 +18,8 @@ GDAL_ROOT	=	..\..\..\..
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
-EXTRAFLAGS =	-I.. -I..\.. -I..\..\.. $(SOFTWARNFLAGS)
+# disable warning C4306: 'type cast' : conversion from 'int' to 'void *' of greater size
+EXTRAFLAGS =	-I.. -I..\.. -I..\..\.. $(SOFTWARNFLAGS) /wd4306
 
 default:	$(OBJ)
 
diff --git a/ogr/ogrsf_frmts/geojson/libjson/printbuf.c b/ogr/ogrsf_frmts/geojson/libjson/printbuf.c
index 6ec9533..fd83aab 100644
--- a/ogr/ogrsf_frmts/geojson/libjson/printbuf.c
+++ b/ogr/ogrsf_frmts/geojson/libjson/printbuf.c
@@ -19,7 +19,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include "cpl_string.h" 
+#include "cpl_string.h"
 
 #if HAVE_STDARG_H
 # include <stdarg.h>
@@ -114,20 +114,20 @@ int sprintbuf(struct printbuf *p, const char *msg, ...)
 {
   va_list ap;
   char *t;
-  int size, ret; 
+  int size, ret;
 
   /* user stack buffer first */
   va_start(ap, msg);
-  if((size = CPLVASPrintf(&t, msg, ap)) == -1) return -1; 
+  if((size = CPLVASPrintf(&t, msg, ap)) == -1) return -1;
   va_end(ap);
-  
+
   if (strcmp(msg, "%f") == 0)
   {
       char* pszComma = strchr(t, ',');
       if (pszComma)
           *pszComma = '.';
   }
-  
+
   ret = printbuf_memappend(p, t, size);
   CPLFree(t);
   return ret;
diff --git a/ogr/ogrsf_frmts/geojson/libjson/printbuf.h b/ogr/ogrsf_frmts/geojson/libjson/printbuf.h
index b1bde7f..269e7c7 100644
--- a/ogr/ogrsf_frmts/geojson/libjson/printbuf.h
+++ b/ogr/ogrsf_frmts/geojson/libjson/printbuf.h
@@ -13,8 +13,8 @@
  * (http://www.opensource.org/licenses/mit-license.php)
  */
 
-#ifndef _printbuf_h_
-#define _printbuf_h_
+#ifndef printbuf_h_
+#define printbuf_h_
 
 #ifdef __cplusplus
 extern "C" {
@@ -45,7 +45,7 @@ do {                                                         \
     memcpy(p->buf + p->bpos, (bufptr), bufsize);             \
     p->bpos += bufsize;                                      \
     p->buf[p->bpos]= '\0';                                   \
-  } else {  printbuf_memappend(p, (bufptr), bufsize); }      \
+  } else {  printbuf_memappend(p, (bufptr), (int)(bufsize)); }      \
 } while (0)
 
 #define printbuf_length(p) ((p)->bpos)
diff --git a/ogr/ogrsf_frmts/geojson/ogr_geojson.h b/ogr/ogrsf_frmts/geojson/ogr_geojson.h
index d4ed5a0..a29153a 100644
--- a/ogr/ogrsf_frmts/geojson/ogr_geojson.h
+++ b/ogr/ogrsf_frmts/geojson/ogr_geojson.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_geojson.h 32121 2015-12-11 10:25:38Z rouault $
+ * $Id: ogr_geojson.h 33138 2016-01-24 11:18:11Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Definitions of OGR OGRGeoJSON driver types.
@@ -32,6 +32,7 @@
 
 #include "cpl_port.h"
 #include <ogrsf_frmts.h>
+#include "../mem/ogr_mem.h"
 
 #include <cstdio>
 #include <vector> // used by OGRGeoJSONLayer
@@ -45,14 +46,15 @@ class OGRGeoJSONDataSource;
 /*                           OGRGeoJSONLayer                            */
 /************************************************************************/
 
-class OGRGeoJSONLayer : public OGRLayer
+class OGRGeoJSONLayer : public OGRMemLayer
 {
+    friend class OGRGeoJSONDataSource;
 public:
 
     static const char* const DefaultName;
     static const char* const DefaultFIDColumn;
     static const OGRwkbGeometryType DefaultGeometryType;
- 
+
     OGRGeoJSONLayer( const char* pszName,
                      OGRSpatialReference* poSRS,
                      OGRwkbGeometryType eGType,
@@ -62,31 +64,22 @@ public:
     //
     // OGRLayer Interface
     //
-    OGRFeatureDefn* GetLayerDefn();
-    
-    GIntBig GetFeatureCount( int bForce = TRUE );
-    void ResetReading();
-    OGRFeature* GetNextFeature();
-    int TestCapability( const char* pszCap );
-    const char* GetFIDColumn();
-    void SetFIDColumn( const char* pszFIDColumn );
-    
+    virtual const char* GetFIDColumn();
+    virtual int         TestCapability( const char * pszCap );
+
+    virtual OGRErr      SyncToDisk();
     //
     // OGRGeoJSONLayer Interface
     //
+    void SetFIDColumn( const char* pszFIDColumn );
     void AddFeature( OGRFeature* poFeature );
     void DetectGeometryType();
 
 private:
 
-    typedef std::vector<OGRFeature*> FeaturesSeq;
-    FeaturesSeq seqFeatures_;
-    FeaturesSeq::iterator iterCurrent_;
-
-
-    // CPL_UNUSED OGRGeoJSONDataSource* poDS_;
-    OGRFeatureDefn* poFeatureDefn_;
+    OGRGeoJSONDataSource* poDS_;
     CPLString sFIDColumn_;
+    bool bUpdated_;
 };
 
 /************************************************************************/
@@ -97,9 +90,10 @@ class OGRGeoJSONWriteLayer : public OGRLayer
 {
 public:
     OGRGeoJSONWriteLayer( const char* pszName,
-                     OGRwkbGeometryType eGType,
-                     char** papszOptions,
-                     OGRGeoJSONDataSource* poDS );
+                          OGRwkbGeometryType eGType,
+                          char** papszOptions,
+                          bool bWriteFC_BBOXIn,
+                          OGRGeoJSONDataSource* poDS );
     ~OGRGeoJSONWriteLayer();
 
     //
@@ -120,11 +114,13 @@ private:
     OGRFeatureDefn* poFeatureDefn_;
     int nOutCounter_;
 
-    int bWriteBBOX;
-    int bBBOX3D;
+    bool bWriteBBOX;
+    bool bBBOX3D;
+    bool bWriteFC_BBOX;
     OGREnvelope3D sEnvelopeLayer;
 
-    int nCoordPrecision;
+    int nCoordPrecision_;
+    int nSignificantFigures_;
 };
 
 /************************************************************************/
@@ -151,7 +147,7 @@ public:
                            OGRwkbGeometryType eGType = wkbUnknown,
                            char** papszOptions = NULL );
     int TestCapability( const char* pszCap );
-    
+
     void AddLayer( OGRGeoJSONLayer* poLayer );
 
     //
@@ -165,13 +161,13 @@ public:
         eGeometryPreserve,
         eGeometryAsCollection,
     };
-    
+
     void SetGeometryTranslation( GeometryTranslation type );
 
     enum AttributesTranslation
     {
-        eAtributesPreserve,
-        eAtributesSkip
+        eAttributesPreserve,
+        eAttributesSkip
     };
 
     void SetAttributesTranslation( AttributesTranslation type );
@@ -179,31 +175,36 @@ public:
     int  GetFpOutputIsSeekable() const { return bFpOutputIsSeekable_; }
     int  GetBBOXInsertLocation() const { return nBBOXInsertLocation_; }
     int  HasOtherPages() const { return bOtherPages_; }
+    bool IsUpdatable() const { return bUpdatable_; }
 
-private:
+    virtual void        FlushCache();
 
+private:
     //
     // Private data members
     //
     char* pszName_;
     char* pszGeoData_;
     vsi_l_offset nGeoDataLen_;
-    OGRLayer** papoLayers_;
+    OGRGeoJSONLayer** papoLayers_;
+    OGRGeoJSONWriteLayer** papoLayersWriter_;
     int nLayers_;
     VSILFILE* fpOut_;
-    
+
     //
     // Translation/Creation control flags
-    // 
+    //
     GeometryTranslation flTransGeom_;
     AttributesTranslation flTransAttrs_;
-    int bOtherPages_; /* ERSI Feature Service specific */
+    bool bOtherPages_;  // ESRI Feature Service specific.
 
-    int bFpOutputIsSeekable_;
+    bool bFpOutputIsSeekable_;
     int nBBOXInsertLocation_;
 
+    bool bUpdatable_;
+
     //
-    // Priavte utility functions
+    // Private utility functions
     //
     void Clear();
     int ReadFromFile( GDALOpenInfo* poOpenInfo );
diff --git a/ogr/ogrsf_frmts/geojson/ogresrijsonreader.cpp b/ogr/ogrsf_frmts/geojson/ogresrijsonreader.cpp
index 63eed04..ad92698 100644
--- a/ogr/ogrsf_frmts/geojson/ogresrijsonreader.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogresrijsonreader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogresrijsonreader.cpp 29120 2015-05-02 22:25:02Z rouault $
+ * $Id: ogresrijsonreader.cpp 32460 2015-12-26 00:06:24Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of OGRESRIJSONReader class (OGR ESRIJSON Driver)
@@ -42,9 +42,7 @@
 
 OGRESRIJSONReader::OGRESRIJSONReader()
     : poGJObject_( NULL ), poLayer_( NULL )
-{
-    // Take a deep breath and get to work.
-}
+{}
 
 /************************************************************************/
 /*                         ~OGRESRIJSONReader()                         */
@@ -69,17 +67,14 @@ OGRErr OGRESRIJSONReader::Parse( const char* pszText )
 {
     if( NULL != pszText )
     {
-        json_tokener* jstok = NULL;
-        json_object* jsobj = NULL;
-
-        jstok = json_tokener_new();
-        jsobj = json_tokener_parse_ex(jstok, pszText, -1);
+        json_tokener* jstok = json_tokener_new();
+        json_object* jsobj = json_tokener_parse_ex(jstok, pszText, -1);
         if( jstok->err != json_tokener_success)
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "ESRIJSON parsing error: %s (at offset %d)",
-            	      json_tokener_error_desc(jstok->err), jstok->char_offset);
-            
+                      json_tokener_error_desc(jstok->err), jstok->char_offset);
+
             json_tokener_free(jstok);
             return OGRERR_CORRUPT_DATA;
         }
@@ -105,12 +100,12 @@ void OGRESRIJSONReader::ReadLayers( OGRGeoJSONDataSource* poDS )
     if( NULL == poGJObject_ )
     {
         CPLDebug( "ESRIJSON",
-                  "Missing parset ESRIJSON data. Forgot to call Parse()?" );
+                  "Missing parsed ESRIJSON data. Forgot to call Parse()?" );
         return;
     }
 
-    OGRSpatialReference* poSRS = NULL;
-    poSRS = OGRESRIJSONReadSpatialReference( poGJObject_ );
+    OGRSpatialReference* poSRS
+        = OGRESRIJSONReadSpatialReference( poGJObject_ );
 
     poLayer_ = new OGRGeoJSONLayer( OGRGeoJSONLayer::DefaultName, poSRS,
                                     OGRESRIJSONGetGeometryType(poGJObject_),
@@ -127,8 +122,7 @@ void OGRESRIJSONReader::ReadLayers( OGRGeoJSONDataSource* poDS )
         return;
     }
 
-    OGRGeoJSONLayer* poThisLayer = NULL;
-    poThisLayer = ReadFeatureCollection( poGJObject_ );
+    OGRGeoJSONLayer *poThisLayer = ReadFeatureCollection( poGJObject_ );
     if (poThisLayer == NULL)
     {
         delete poLayer_;
@@ -153,18 +147,18 @@ bool OGRESRIJSONReader::GenerateLayerDefn()
     bool bSuccess = true;
 
 /* -------------------------------------------------------------------- */
-/*      Scan all features and generate layer definition.				*/
+/*      Scan all features and generate layer definition.                */
 /* -------------------------------------------------------------------- */
-    json_object* poObjFeatures = NULL;
-
-    poObjFeatures = OGRGeoJSONFindMemberByName( poGJObject_, "fields" );
-    if( NULL != poObjFeatures && json_type_array == json_object_get_type( poObjFeatures ) )
+    json_object* poObjFeatures
+        = OGRGeoJSONFindMemberByName( poGJObject_, "fields" );
+    if( NULL != poObjFeatures
+        && json_type_array == json_object_get_type( poObjFeatures ) )
     {
-        json_object* poObjFeature = NULL;
         const int nFeatures = json_object_array_length( poObjFeatures );
         for( int i = 0; i < nFeatures; ++i )
         {
-            poObjFeature = json_object_array_get_idx( poObjFeatures, i );
+            json_object* poObjFeature
+                = json_object_array_get_idx( poObjFeatures, i );
             if( !GenerateFeatureDefn( poObjFeature ) )
             {
                 CPLDebug( "GeoJSON", "Create feature schema failure." );
@@ -174,7 +168,8 @@ bool OGRESRIJSONReader::GenerateLayerDefn()
     }
     else
     {
-        poObjFeatures = OGRGeoJSONFindMemberByName( poGJObject_, "fieldAliases" );
+        poObjFeatures = OGRGeoJSONFindMemberByName(
+            poGJObject_, "fieldAliases" );
         if( NULL != poObjFeatures &&
             json_object_get_type(poObjFeatures) == json_type_object )
         {
@@ -213,7 +208,7 @@ bool OGRESRIJSONReader::GenerateFeatureDefn( json_object* poObj )
     bool bSuccess = false;
 
 /* -------------------------------------------------------------------- */
-/*      Read collection of properties.									*/
+/*      Read collection of properties.                                  */
 /* -------------------------------------------------------------------- */
     json_object* poObjName = OGRGeoJSONFindMemberByName( poObj, "name" );
     json_object* poObjType = OGRGeoJSONFindMemberByName( poObj, "type" );
@@ -256,16 +251,13 @@ bool OGRESRIJSONReader::GenerateFeatureDefn( json_object* poObj )
 
 bool OGRESRIJSONReader::AddFeature( OGRFeature* poFeature )
 {
-    bool bAdded = false;
-  
-    if( NULL != poFeature )
-    {
-        poLayer_->AddFeature( poFeature );
-        bAdded = true;
-        delete poFeature;
-    }
+    if( NULL == poFeature )
+        return false;
 
-    return bAdded;
+    poLayer_->AddFeature( poFeature );
+    delete poFeature;
+
+    return true;
 }
 
 /************************************************************************/
@@ -276,7 +268,7 @@ OGRGeometry* OGRESRIJSONReader::ReadGeometry( json_object* poObj )
 {
     OGRGeometry* poGeometry = NULL;
 
-    OGRwkbGeometryType eType = poLayer_->GetGeomType();
+    const OGRwkbGeometryType eType = poLayer_->GetGeomType();
     if (eType == wkbPoint)
         poGeometry = OGRESRIJSONReadPoint( poObj );
     else if (eType == wkbLineString)
@@ -298,8 +290,8 @@ OGRFeature* OGRESRIJSONReader::ReadFeature( json_object* poObj )
     CPLAssert( NULL != poObj );
     CPLAssert( NULL != poLayer_ );
 
-    OGRFeature* poFeature = NULL;
-    poFeature = new OGRFeature( poLayer_->GetLayerDefn() );
+    OGRFeature* poFeature
+        = new OGRFeature( poLayer_->GetLayerDefn() );
 
 /* -------------------------------------------------------------------- */
 /*      Translate ESRIJSON "attributes" object to feature attributes.   */
@@ -311,7 +303,6 @@ OGRFeature* OGRESRIJSONReader::ReadFeature( json_object* poObj )
     if( NULL != poObjProps &&
         json_object_get_type(poObjProps) == json_type_object )
     {
-        int nField = -1;
         OGRFieldDefn* poFieldDefn = NULL;
         json_object_iter it;
         it.key = NULL;
@@ -319,7 +310,8 @@ OGRFeature* OGRESRIJSONReader::ReadFeature( json_object* poObj )
         it.entry = NULL;
         json_object_object_foreachC( poObjProps, it )
         {
-            nField = poFeature->GetFieldIndex(it.key);
+            const int nField
+                = poFeature->GetFieldIndex(it.key);
             if( nField >= 0 )
             {
                 poFieldDefn = poFeature->GetFieldDefnRef(nField);
@@ -361,7 +353,7 @@ OGRFeature* OGRESRIJSONReader::ReadFeature( json_object* poObj )
                 return poFeature;
         }
     }
-    
+
     if( NULL != poObjGeom )
     {
         OGRGeometry* poGeometry = ReadGeometry( poObjGeom );
@@ -391,8 +383,8 @@ OGRESRIJSONReader::ReadFeatureCollection( json_object* poObj )
 {
     CPLAssert( NULL != poLayer_ );
 
-    json_object* poObjFeatures = NULL;
-    poObjFeatures = OGRGeoJSONFindMemberByName( poObj, "features" );
+    json_object* poObjFeatures
+        = OGRGeoJSONFindMemberByName( poObj, "features" );
     if( NULL == poObjFeatures )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -404,17 +396,17 @@ OGRESRIJSONReader::ReadFeatureCollection( json_object* poObj )
     if( json_type_array == json_object_get_type( poObjFeatures ) )
     {
         /* bool bAdded = false; */
-        OGRFeature* poFeature = NULL;
-        json_object* poObjFeature = NULL;
 
         const int nFeatures = json_object_array_length( poObjFeatures );
         for( int i = 0; i < nFeatures; ++i )
         {
-            poObjFeature = json_object_array_get_idx( poObjFeatures, i );
+            json_object* poObjFeature
+                = json_object_array_get_idx( poObjFeatures, i );
             if (poObjFeature != NULL &&
                 json_object_get_type(poObjFeature) == json_type_object)
             {
-                poFeature = OGRESRIJSONReader::ReadFeature( poObjFeature );
+                OGRFeature* poFeature
+                    = OGRESRIJSONReader::ReadFeature( poObjFeature );
                 /* bAdded = */ AddFeature( poFeature );
             }
             //CPLAssert( bAdded );
@@ -437,8 +429,8 @@ OGRwkbGeometryType OGRESRIJSONGetGeometryType( json_object* poObj )
     if( NULL == poObj )
         return wkbUnknown;
 
-    json_object* poObjType = NULL;
-    poObjType = OGRGeoJSONFindMemberByName( poObj, "geometryType" );
+    json_object* poObjType
+        = OGRGeoJSONFindMemberByName( poObj, "geometryType" );
     if( NULL == poObjType )
     {
         return wkbNone;
@@ -474,7 +466,7 @@ OGRPoint* OGRESRIJSONReadPoint( json_object* poObj)
         return NULL;
     }
 
-    int iTypeX = json_object_get_type(poObjX);
+    const int iTypeX = json_object_get_type(poObjX);
     if ( (json_type_double != iTypeX) && (json_type_int != iTypeX) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -492,7 +484,7 @@ OGRPoint* OGRESRIJSONReadPoint( json_object* poObj)
         return NULL;
     }
 
-    int iTypeY = json_object_get_type(poObjY);
+    const int iTypeY = json_object_get_type(poObjY);
     if ( (json_type_double != iTypeY) && (json_type_int != iTypeY) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -501,36 +493,24 @@ OGRPoint* OGRESRIJSONReadPoint( json_object* poObj)
         return NULL;
     }
 
-    double dfX, dfY;
-    dfX = json_object_get_double( poObjX );
-    dfY = json_object_get_double( poObjY );
-
-    bool is3d = false;
-    double dfZ = 0.0;
+    const double dfX = json_object_get_double( poObjX );
+    const double dfY = json_object_get_double( poObjY );
 
     json_object* poObjZ = OGRGeoJSONFindMemberByName( poObj, "z" );
-    if( NULL != poObjZ )
-    {
-        int iTypeZ = json_object_get_type(poObjZ);
-        if ( (json_type_double != iTypeZ) && (json_type_int != iTypeZ) )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                    "Invalid Z coordinate. Type is not double or integer for \'%s\'.",
-                    json_object_to_json_string(poObjZ) );
-            return NULL;
-        }
-        is3d = true;
-        dfZ = json_object_get_double( poObjZ );
-    }
+    if( NULL == poObjZ )
+        return new OGRPoint(dfX, dfY);
 
-    if(is3d)
-    {
-        return new OGRPoint(dfX, dfY, dfZ);
-    }
-    else
+    const int iTypeZ = json_object_get_type(poObjZ);
+    if ( (json_type_double != iTypeZ) && (json_type_int != iTypeZ) )
     {
-       return new OGRPoint(dfX, dfY);
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Invalid Z coordinate. Type is not double or integer "
+                  "for \'%s\'.",
+                  json_object_to_json_string(poObjZ) );
+        return NULL;
     }
+    const double dfZ = json_object_get_double( poObjZ );
+    return new OGRPoint(dfX, dfY, dfZ);
 }
 
 /************************************************************************/
@@ -542,12 +522,12 @@ static int OGRESRIJSONReaderParseZM( json_object* poObj, int *bHasZ,
 {
     CPLAssert( NULL != poObj );
     /*
-    ** The esri geojson spec states that geometries other than point can
+    ** The ESRI geojson spec states that geometries other than point can
     ** have the attributes hasZ and hasM.  A geometry that has a z value
     ** implies the 3rd number in the tuple is z.  if hasM is true, but hasZ
     ** is not, it is the M value, and is not supported in OGR.
     */
-    int bZ, bM;
+    int bZ;
     json_object* poObjHasZ = OGRGeoJSONFindMemberByName( poObj, "hasZ" );
     if( poObjHasZ == NULL )
     {
@@ -565,6 +545,7 @@ static int OGRESRIJSONReaderParseZM( json_object* poObj, int *bHasZ,
         }
     }
 
+    int bM;
     json_object* poObjHasM = OGRGeoJSONFindMemberByName( poObj, "hasM" );
     if( poObjHasM == NULL )
     {
@@ -617,32 +598,31 @@ static int OGRESRIJSONReaderParseXYZMArray (json_object* poObjCoords,
     if(coordDimension < 2 || coordDimension > 4)
     {
         CPLDebug( "ESRIJSON",
-                "OGRESRIJSONReaderParseXYZMArray: got an unexpected array object." );
+                  "OGRESRIJSONReaderParseXYZMArray: got an unexpected "
+                  "array object." );
         return FALSE;
     }
 
-    json_object* poObjCoord;
-    int iType;
-    double dfX, dfY, dfZ = 0.0;
-
     // Read X coordinate
-    poObjCoord = json_object_array_get_idx( poObjCoords, 0 );
+    json_object* poObjCoord = json_object_array_get_idx( poObjCoords, 0 );
     if (poObjCoord == NULL)
     {
-        CPLDebug( "ESRIJSON", "OGRESRIJSONReaderParseXYZMArray: got null object." );
+        CPLDebug( "ESRIJSON",
+                  "OGRESRIJSONReaderParseXYZMArray: got null object." );
         return FALSE;
     }
 
-    iType = json_object_get_type(poObjCoord);
+    int iType = json_object_get_type(poObjCoord);
     if ( (json_type_double != iType) && (json_type_int != iType) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                "Invalid X coordinate. Type is not double or integer for \'%s\'.",
+                  "Invalid X coordinate. Type is not double or integer "
+                  "for \'%s\'.",
                 json_object_to_json_string(poObjCoord) );
         return FALSE;
     }
 
-    dfX = json_object_get_double( poObjCoord );
+    const double dfX = json_object_get_double( poObjCoord );
 
     // Read Y coordinate
     poObjCoord = json_object_array_get_idx( poObjCoords, 1 );
@@ -661,7 +641,7 @@ static int OGRESRIJSONReaderParseXYZMArray (json_object* poObjCoords,
         return FALSE;
     }
 
-    dfY = json_object_get_double( poObjCoord );
+    const double dfY = json_object_get_double( poObjCoord );
 
     // Read Z coordinate
     if(coordDimension > 2)
@@ -669,7 +649,8 @@ static int OGRESRIJSONReaderParseXYZMArray (json_object* poObjCoords,
         poObjCoord = json_object_array_get_idx( poObjCoords, 2 );
         if (poObjCoord == NULL)
         {
-            CPLDebug( "ESRIJSON", "OGRESRIJSONReaderParseXYZMArray: got null object." );
+            CPLDebug( "ESRIJSON",
+                      "OGRESRIJSONReaderParseXYZMArray: got null object." );
             return FALSE;
         }
 
@@ -677,11 +658,19 @@ static int OGRESRIJSONReaderParseXYZMArray (json_object* poObjCoords,
         if ( (json_type_double != iType) && (json_type_int != iType) )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                    "Invalid Z coordinate. Type is not double or integer for \'%s\'.",
+                      "Invalid Z coordinate. Type is not double or integer "
+                      "for \'%s\'.",
                     json_object_to_json_string(poObjCoord) );
             return FALSE;
         }
-        dfZ = json_object_get_double( poObjCoord );
+        const double dfZ = json_object_get_double( poObjCoord );
+        if( pdfZ != NULL )
+            *pdfZ = dfZ;
+    }
+    else
+    {
+        if( pdfZ != NULL )
+            *pdfZ = 0.0;
     }
 
     if( pnNumCoords != NULL )
@@ -690,8 +679,6 @@ static int OGRESRIJSONReaderParseXYZMArray (json_object* poObjCoords,
         *pdfX = dfX;
     if( pdfY != NULL )
         *pdfY = dfY;
-    if( pdfZ != NULL )
-        *pdfZ = dfZ;
 
     return TRUE;
 }
@@ -713,26 +700,25 @@ OGRLineString* OGRESRIJSONReadLineString( json_object* poObj)
                   "Failed to parse hasZ and/or hasM from geometry" );
     }
 
-    OGRLineString* poLine = NULL;
-    
     json_object* poObjPaths = OGRGeoJSONFindMemberByName( poObj, "paths" );
     if( NULL == poObjPaths )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-            "Invalid LineString object. "
-            "Missing \'paths\' member." );
+                  "Invalid LineString object. "
+                  "Missing \'paths\' member." );
         return NULL;
     }
 
     if( json_type_array != json_object_get_type( poObjPaths ) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-            "Invalid LineString object. "
-            "Invalid \'paths\' member." );
+                  "Invalid LineString object. "
+                  "Invalid \'paths\' member." );
         return NULL;
     }
-    
-    poLine = new OGRLineString();
+
+    OGRLineString* poLine
+        = new OGRLineString();
     const int nPaths = json_object_array_length( poObjPaths );
     for(int iPath = 0; iPath < nPaths; iPath ++)
     {
@@ -749,12 +735,12 @@ OGRLineString* OGRESRIJSONReadLineString( json_object* poObj)
         const int nPoints = json_object_array_length( poObjPath );
         for(int i = 0; i < nPoints; i++)
         {
-            double dfX, dfY, dfZ;
             int nNumCoords = 2;
-            json_object* poObjCoords = NULL;
-
-            poObjCoords = json_object_array_get_idx( poObjPath, i );
-            if( !OGRESRIJSONReaderParseXYZMArray (poObjCoords, &dfX, &dfY, &dfZ, &nNumCoords) )
+            json_object* poObjCoords
+                = json_object_array_get_idx( poObjPath, i );
+            double dfX, dfY, dfZ;
+            if( !OGRESRIJSONReaderParseXYZMArray (
+                    poObjCoords, &dfX, &dfY, &dfZ, &nNumCoords) )
             {
                 delete poLine;
                 return NULL;
@@ -782,7 +768,6 @@ OGRGeometry* OGRESRIJSONReadPolygon( json_object* poObj)
 {
     CPLAssert( NULL != poObj );
 
-
     int bHasZ = FALSE;
     int bHasM = FALSE;
 
@@ -834,11 +819,11 @@ OGRGeometry* OGRESRIJSONReadPolygon( json_object* poObj)
         for(int i = 0; i < nPoints; i++)
         {
             int nNumCoords = 2;
+            json_object* poObjCoords
+                = json_object_array_get_idx( poObjRing, i );
             double dfX, dfY, dfZ;
-            json_object* poObjCoords = NULL;
-
-            poObjCoords = json_object_array_get_idx( poObjRing, i );
-            if( !OGRESRIJSONReaderParseXYZMArray (poObjCoords, &dfX, &dfY, &dfZ, &nNumCoords) )
+            if( !OGRESRIJSONReaderParseXYZMArray (
+                    poObjCoords, &dfX, &dfY, &dfZ, &nNumCoords) )
             {
                 for(int j=0;j<=iRing;j++)
                     delete papoGeoms[j];
@@ -856,7 +841,7 @@ OGRGeometry* OGRESRIJSONReadPolygon( json_object* poObj)
             }
         }
     }
-    
+
     OGRGeometry* poRet = OGRGeometryFactory::organizePolygons( papoGeoms,
                                                                nRings,
                                                                NULL,
@@ -883,8 +868,6 @@ OGRMultiPoint* OGRESRIJSONReadMultiPoint( json_object* poObj)
                   "Failed to parse hasZ and/or hasM from geometry" );
     }
 
-    OGRMultiPoint* poMulti = NULL;
-
     json_object* poObjPoints = OGRGeoJSONFindMemberByName( poObj, "points" );
     if( NULL == poObjPoints )
     {
@@ -902,17 +885,17 @@ OGRMultiPoint* OGRESRIJSONReadMultiPoint( json_object* poObj)
         return NULL;
     }
 
-    poMulti = new OGRMultiPoint();
+    OGRMultiPoint* poMulti = new OGRMultiPoint();
 
     const int nPoints = json_object_array_length( poObjPoints );
     for(int i = 0; i < nPoints; i++)
     {
-        double dfX, dfY, dfZ;
         int nNumCoords = 2;
-        json_object* poObjCoords = NULL;
-
-        poObjCoords = json_object_array_get_idx( poObjPoints, i );
-        if( !OGRESRIJSONReaderParseXYZMArray (poObjCoords, &dfX, &dfY, &dfZ, &nNumCoords) )
+        json_object* poObjCoords
+            = json_object_array_get_idx( poObjPoints, i );
+        double dfX, dfY, dfZ;
+        if( !OGRESRIJSONReaderParseXYZMArray (
+                poObjCoords, &dfX, &dfY, &dfZ, &nNumCoords) )
         {
             delete poMulti;
             return NULL;
@@ -942,17 +925,20 @@ OGRSpatialReference* OGRESRIJSONReadSpatialReference( json_object* poObj )
 /* -------------------------------------------------------------------- */
     OGRSpatialReference* poSRS = NULL;
 
-    json_object* poObjSrs = OGRGeoJSONFindMemberByName( poObj, "spatialReference" );
+    json_object* poObjSrs
+        = OGRGeoJSONFindMemberByName( poObj, "spatialReference" );
     if( NULL != poObjSrs )
     {
         json_object* poObjWkid = OGRGeoJSONFindMemberByName( poObjSrs, "wkid" );
         if (poObjWkid == NULL)
         {
-            json_object* poObjWkt = OGRGeoJSONFindMemberByName( poObjSrs, "wkt" );
+            json_object* poObjWkt
+                = OGRGeoJSONFindMemberByName( poObjSrs, "wkt" );
             if (poObjWkt == NULL)
                 return NULL;
 
-            char* pszWKT = (char*) json_object_get_string( poObjWkt );
+            char* pszWKT
+                = const_cast<char*>(json_object_get_string( poObjWkt ));
             poSRS = new OGRSpatialReference();
             if( OGRERR_NONE != poSRS->importFromWkt( &pszWKT ) ||
                 poSRS->morphFromESRI() != OGRERR_NONE )
@@ -964,7 +950,7 @@ OGRSpatialReference* OGRESRIJSONReadSpatialReference( json_object* poObj )
             return poSRS;
         }
 
-        int nEPSG = json_object_get_int( poObjWkid );
+        const int nEPSG = json_object_get_int( poObjWkid );
 
         poSRS = new OGRSpatialReference();
         if( OGRERR_NONE != poSRS->importFromEPSG( nEPSG ) )
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsondatasource.cpp b/ogr/ogrsf_frmts/geojson/ogrgeojsondatasource.cpp
index 3a2087e..7ad08f9 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsondatasource.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsondatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsondatasource.cpp 29120 2015-05-02 22:25:02Z rouault $
+ * $Id: ogrgeojsondatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of OGRGeoJSONDataSource class (OGR GeoJSON Driver).
@@ -30,8 +30,10 @@
 #include "ogr_geojson.h"
 #include "ogrgeojsonutils.h"
 #include "ogrgeojsonreader.h"
+#include "gdal_utils.h"
 #include <cpl_http.h>
 #include <json.h> // JSON-C
+#include "ogrgeojsonwriter.h"
 #include <cstddef>
 #include <cstdlib>
 using namespace std;
@@ -42,15 +44,14 @@ using namespace std;
 
 OGRGeoJSONDataSource::OGRGeoJSONDataSource()
     : pszName_(NULL), pszGeoData_(NULL), nGeoDataLen_(0),
-        papoLayers_(NULL), nLayers_(0), fpOut_(NULL),
+        papoLayers_(NULL), papoLayersWriter_(NULL), nLayers_(0), fpOut_(NULL),
         flTransGeom_( OGRGeoJSONDataSource::eGeometryPreserve ),
-        flTransAttrs_( OGRGeoJSONDataSource::eAtributesPreserve ),
-        bOtherPages_(FALSE),
-        bFpOutputIsSeekable_( FALSE ),
-        nBBOXInsertLocation_(0)
-{
-    // I've got constructed. Lunch time!
-}
+        flTransAttrs_( OGRGeoJSONDataSource::eAttributesPreserve ),
+        bOtherPages_(false),
+        bFpOutputIsSeekable_( false ),
+        nBBOXInsertLocation_(0),
+        bUpdatable_( false )
+{ }
 
 /************************************************************************/
 /*                           ~OGRGeoJSONDataSource()                    */
@@ -58,13 +59,8 @@ OGRGeoJSONDataSource::OGRGeoJSONDataSource()
 
 OGRGeoJSONDataSource::~OGRGeoJSONDataSource()
 {
+    FlushCache();
     Clear();
-    
-    if( NULL != fpOut_ )
-    {
-        VSIFCloseL( fpOut_ );
-        fpOut_ = NULL;
-    }
 }
 
 /************************************************************************/
@@ -78,6 +74,12 @@ int OGRGeoJSONDataSource::Open( GDALOpenInfo* poOpenInfo,
     {
         if( !ReadFromService( poOpenInfo->pszFilename ) )
             return FALSE;
+        if( poOpenInfo->eAccess == GA_Update )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Update from remote service not supported");
+            return FALSE;
+        }
     }
     else if( eGeoJSONSourceText == nSrcType )
     {
@@ -99,10 +101,10 @@ int OGRGeoJSONDataSource::Open( GDALOpenInfo* poOpenInfo,
 /*      GeoJSON text tree.                                              */
 /* -------------------------------------------------------------------- */
     if( NULL == pszGeoData_ ||
-        strncmp(pszGeoData_, "{\"couchdb\":\"Welcome\"", strlen("{\"couchdb\":\"Welcome\"")) == 0 ||
-        strncmp(pszGeoData_, "{\"db_name\":\"", strlen("{\"db_name\":\"")) == 0 ||
-        strncmp(pszGeoData_, "{\"total_rows\":", strlen("{\"total_rows\":")) == 0 ||
-        strncmp(pszGeoData_, "{\"rows\":[", strlen("{\"rows\":[")) == 0)
+        STARTS_WITH(pszGeoData_, "{\"couchdb\":\"Welcome\"") ||
+        STARTS_WITH(pszGeoData_, "{\"db_name\":\"") ||
+        STARTS_WITH(pszGeoData_, "{\"total_rows\":") ||
+        STARTS_WITH(pszGeoData_, "{\"rows\":["))
     {
         Clear();
         return FALSE;
@@ -111,30 +113,37 @@ int OGRGeoJSONDataSource::Open( GDALOpenInfo* poOpenInfo,
     LoadLayers(poOpenInfo->papszOpenOptions);
     if( nLayers_ == 0 )
     {
-        int bEmitError = TRUE;
+        bool bEmitError = true;
         if( eGeoJSONSourceService == nSrcType )
         {
             CPLString osTmpFilename = CPLSPrintf("/vsimem/%p/%s", this,
                                         CPLGetFilename(poOpenInfo->pszFilename));
             VSIFCloseL(VSIFileFromMemBuffer( osTmpFilename,
                                              (GByte*)pszGeoData_,
-                                             nGeoDataLen_, 
+                                             nGeoDataLen_,
                                              TRUE ));
             pszGeoData_ = NULL;
             if( GDALIdentifyDriver(osTmpFilename, NULL) )
-                bEmitError = FALSE;
+                bEmitError = false;
             VSIUnlink(osTmpFilename);
         }
         Clear();
 
         if( bEmitError )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
+            CPLError( CE_Failure, CPLE_OpenFailed,
                     "Failed to read GeoJSON data" );
         }
         return FALSE;
     }
 
+    if( eGeoJSONSourceText == nSrcType && poOpenInfo->eAccess == GA_Update )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                    "Update from inline definition not supported");
+        return FALSE;
+    }
+
     return TRUE;
 }
 
@@ -164,7 +173,10 @@ OGRLayer* OGRGeoJSONDataSource::GetLayer( int nLayer )
 {
     if( 0 <= nLayer && nLayer < nLayers_ )
     {
-        return papoLayers_[nLayer];
+        if( papoLayers_ )
+            return papoLayers_[nLayer];
+        else
+            return papoLayersWriter_[nLayer];
     }
 
     return NULL;
@@ -174,7 +186,7 @@ OGRLayer* OGRGeoJSONDataSource::GetLayer( int nLayer )
 /*                           ICreateLayer()                             */
 /************************************************************************/
 
-OGRLayer* OGRGeoJSONDataSource::ICreateLayer( const char* pszName_,
+OGRLayer* OGRGeoJSONDataSource::ICreateLayer( const char* pszNameIn,
                                              OGRSpatialReference* poSRS,
                                              OGRwkbGeometryType eGType,
                                              char** papszOptions )
@@ -193,26 +205,60 @@ OGRLayer* OGRGeoJSONDataSource::ICreateLayer( const char* pszName_,
         return NULL;
     }
 
-    OGRGeoJSONWriteLayer* poLayer = NULL;
-    poLayer = new OGRGeoJSONWriteLayer( pszName_, eGType, papszOptions, this );
-
-/* -------------------------------------------------------------------- */
-/*      Add layer to data source layer list.                            */
-/* -------------------------------------------------------------------- */
-    
-    papoLayers_ = (OGRLayer **)
-        CPLRealloc( papoLayers_,  sizeof(OGRLayer*) * (nLayers_ + 1) );
+    VSIFPrintfL( fpOut_, "{\n\"type\": \"FeatureCollection\",\n" );
 
-    papoLayers_[nLayers_++] = poLayer;
+    bool bWriteFC_BBOX =
+        CPLTestBool(CSLFetchNameValueDef(papszOptions, "WRITE_BBOX", "FALSE"));
 
-    VSIFPrintfL( fpOut_, "{\n\"type\": \"FeatureCollection\",\n" );
+    const char* pszNativeData = CSLFetchNameValue(papszOptions, "NATIVE_DATA");
+    const char* pszNativeMediaType = CSLFetchNameValue(papszOptions, "NATIVE_MEDIA_TYPE");
+    bool bWriteCRSIfWGS84 = true;
+    if( pszNativeMediaType && EQUAL(pszNativeMediaType, "application/vnd.geo+json") )
+    {
+        json_object *poObj = NULL;
+        if( OGRJSonParse(pszNativeData, &poObj) &&
+            json_object_get_type(poObj) == json_type_object )
+        {
+            json_object_iter it;
+            it.key = NULL;
+            it.val = NULL;
+            it.entry = NULL;
+            CPLString osNativeData;
+            bWriteCRSIfWGS84 = false;
+            json_object_object_foreachC(poObj, it)
+            {
+                if( strcmp(it.key, "type") == 0 ||
+                    strcmp(it.key, "features") == 0  )
+                {
+                    continue;
+                }
+                if( strcmp(it.key, "bbox") == 0 )
+                {
+                    if( CSLFetchNameValue(papszOptions, "WRITE_BBOX") == NULL )
+                        bWriteFC_BBOX = true;
+                    continue;
+                }
+                if( strcmp(it.key, "crs") == 0 )
+                {
+                    bWriteCRSIfWGS84 = true;
+                    continue;
+                }
+                json_object* poKey = json_object_new_string(it.key);
+                VSIFPrintfL( fpOut_, "%s: ", json_object_to_json_string(poKey) );
+                json_object_put(poKey);
+                VSIFPrintfL( fpOut_, "%s,\n", json_object_to_json_string(it.val) );
+            }
+            json_object_put(poObj);
+        }
+    }
 
     if (poSRS)
     {
         const char* pszAuthority = poSRS->GetAuthorityName(NULL);
         const char* pszAuthorityCode = poSRS->GetAuthorityCode(NULL);
         if (pszAuthority != NULL && pszAuthorityCode != NULL &&
-            EQUAL(pszAuthority, "EPSG"))
+            EQUAL(pszAuthority, "EPSG") &&
+            (bWriteCRSIfWGS84 || !EQUAL(pszAuthorityCode, "4326")) )
         {
             json_object* poObjCRS = json_object_new_object();
             json_object_object_add(poObjCRS, "type",
@@ -238,7 +284,7 @@ OGRLayer* OGRGeoJSONDataSource::ICreateLayer( const char* pszName_,
         }
     }
 
-    if (bFpOutputIsSeekable_)
+    if (bFpOutputIsSeekable_ && bWriteFC_BBOX)
     {
         nBBOXInsertLocation_ = (int) VSIFTellL( fpOut_ );
 
@@ -250,6 +296,18 @@ OGRLayer* OGRGeoJSONDataSource::ICreateLayer( const char* pszName_,
 
     VSIFPrintfL( fpOut_, "\"features\": [\n" );
 
+    OGRGeoJSONWriteLayer* poLayer
+        = new OGRGeoJSONWriteLayer( pszNameIn, eGType, papszOptions, bWriteFC_BBOX, this );
+
+/* -------------------------------------------------------------------- */
+/*      Add layer to data source layer list.                            */
+/* -------------------------------------------------------------------- */
+    CPLAssert(papoLayers_ == NULL);
+    papoLayersWriter_ = (OGRGeoJSONWriteLayer **)
+        CPLRealloc( papoLayers_,  sizeof(OGRGeoJSONWriteLayer*) * (nLayers_ + 1) );
+
+    papoLayersWriter_[nLayers_++] = poLayer;
+
     return poLayer;
 }
 
@@ -261,28 +319,28 @@ int OGRGeoJSONDataSource::TestCapability( const char* pszCap )
 {
     if( EQUAL( pszCap, ODsCCreateLayer ) )
         return fpOut_ != NULL && nLayers_ == 0;
-    else if( EQUAL( pszCap, ODsCDeleteLayer ) )
-        return FALSE;
-    else
-        return FALSE;
+
+    // if( EQUAL( pszCap, ODsCDeleteLayer ) )
+    //     return FALSE;
+
+    return FALSE;
 }
 
 /************************************************************************/
 /*                              Create()                                */
 /************************************************************************/
 
-int OGRGeoJSONDataSource::Create( const char* pszName, char** papszOptions )
+int OGRGeoJSONDataSource::Create( const char* pszName,
+                                  char** /* papszOptions */ )
 {
-    UNREFERENCED_PARAM(papszOptions);
-
     CPLAssert( NULL == fpOut_ );
 
     if (strcmp(pszName, "/dev/stdout") == 0)
         pszName = "/vsistdout/";
 
     bFpOutputIsSeekable_ =  !(strcmp(pszName,"/vsistdout/") == 0 ||
-                              strncmp(pszName,"/vsigzip/", 9) == 0 ||
-                              strncmp(pszName,"/vsizip/", 8) == 0);
+                              STARTS_WITH(pszName, "/vsigzip/") ||
+                              STARTS_WITH(pszName, "/vsizip/"));
 
 /* -------------------------------------------------------------------- */
 /*     File overwrite not supported.                                    */
@@ -294,15 +352,15 @@ int OGRGeoJSONDataSource::Create( const char* pszName, char** papszOptions )
                   "The GeoJSON driver does not overwrite existing files." );
         return FALSE;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create the output file.                                         */
 /* -------------------------------------------------------------------- */
     fpOut_ = VSIFOpenL( pszName, "w" );
     if( NULL == fpOut_)
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Failed to create GeoJSON datasource: %s.", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to create GeoJSON datasource: %s.",
                   pszName );
         return FALSE;
     }
@@ -339,12 +397,16 @@ void OGRGeoJSONDataSource::Clear()
 {
     for( int i = 0; i < nLayers_; i++ )
     {
-        CPLAssert( NULL != papoLayers_ );
-        delete papoLayers_[i];
+        if( papoLayers_ != NULL )
+            delete papoLayers_[i];
+        else
+            delete papoLayersWriter_[i];
     }
 
     CPLFree( papoLayers_ );
     papoLayers_ = NULL;
+    CPLFree( papoLayersWriter_ );
+    papoLayersWriter_ = NULL;
     nLayers_ = 0;
 
     CPLFree( pszName_ );
@@ -354,11 +416,11 @@ void OGRGeoJSONDataSource::Clear()
     pszGeoData_ = NULL;
     nGeoDataLen_ = 0;
 
-    if( NULL != fpOut_ )
+    if( fpOut_ )
     {
         VSIFCloseL( fpOut_ );
+        fpOut_ = NULL;
     }
-    fpOut_ = NULL;
 }
 
 /************************************************************************/
@@ -381,6 +443,23 @@ int OGRGeoJSONDataSource::ReadFromFile( GDALOpenInfo* poOpenInfo )
     pszName_ = CPLStrdup( poOpenInfo->pszFilename );
 
     CPLAssert( NULL != pszGeoData_ );
+
+    if( poOpenInfo->eAccess == GA_Update )
+    {
+        VSILFILE* fp = VSIFOpenL(poOpenInfo->pszFilename, "rb+");
+        if( fp == NULL )
+        {
+            CPLError(CE_Failure, CPLE_FileIO,
+                     "Update not supported because file is not writable");
+            return FALSE;
+        }
+        else
+        {
+            bUpdatable_ = true;
+        }
+        VSIFCloseL(fp);
+    }
+
     return TRUE;
 }
 
@@ -404,10 +483,10 @@ int OGRGeoJSONDataSource::ReadFromService( const char* pszSource )
 /* -------------------------------------------------------------------- */
     CPLErrorReset();
 
-    CPLHTTPResult* pResult = NULL;
     char* papsOptions[] = { (char*) "HEADERS=Accept: text/plain, application/json", NULL };
 
-    pResult = CPLHTTPFetch( pszSource, papsOptions );
+    CPLHTTPResult* pResult
+        = CPLHTTPFetch( pszSource, papsOptions );
 
 /* -------------------------------------------------------------------- */
 /*      Try to handle CURL/HTTP errors.                                 */
@@ -421,7 +500,7 @@ int OGRGeoJSONDataSource::ReadFromService( const char* pszSource )
 
    if( 0 != pResult->nStatus )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Curl reports error: %d: %s",
                   pResult->nStatus, pResult->pszErrBuf );
         CPLHTTPDestroyResult( pResult );
@@ -435,7 +514,7 @@ int OGRGeoJSONDataSource::ReadFromService( const char* pszSource )
 
     if ( eGeoJSONProtocolUnknown != GeoJSONGetProtocolType( pszData ) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
             "The data that was downloaded also starts with "
             "protocol prefix (http://, https:// or ftp://) "
             "and cannot be processed as GeoJSON data.");
@@ -464,7 +543,7 @@ int OGRGeoJSONDataSource::ReadFromService( const char* pszSource )
 /*                           LoadLayers()                               */
 /************************************************************************/
 
-void OGRGeoJSONDataSource::LoadLayers(char** papszOpenOptions)
+void OGRGeoJSONDataSource::LoadLayers(char** papszOpenOptionsIn)
 {
     if( NULL == pszGeoData_ )
     {
@@ -472,7 +551,7 @@ void OGRGeoJSONDataSource::LoadLayers(char** papszOpenOptions)
                   "GeoJSON data buffer empty" );
         return;
     }
-    
+
     const char* const apszPrefix[] = { "loadGeoJSON(", "jsonp(" };
     for(size_t iP = 0; iP < sizeof(apszPrefix) / sizeof(apszPrefix[0]); iP++ )
     {
@@ -498,8 +577,6 @@ void OGRGeoJSONDataSource::LoadLayers(char** papszOpenOptions)
         return;
     }
 
-    OGRErr err = OGRERR_NONE;
-
 /* -------------------------------------------------------------------- */
 /*      Is it ESRI Feature Service data ?                               */
 /* -------------------------------------------------------------------- */
@@ -507,7 +584,7 @@ void OGRGeoJSONDataSource::LoadLayers(char** papszOpenOptions)
          strstr(pszGeoData_, "esriFieldType") )
     {
         OGRESRIJSONReader reader;
-        err = reader.Parse( pszGeoData_ );
+        OGRErr err = reader.Parse( pszGeoData_ );
         if( OGRERR_NONE == err )
         {
             json_object* poObj = reader.GetJSonObject();
@@ -516,7 +593,8 @@ void OGRGeoJSONDataSource::LoadLayers(char** papszOpenOptions)
                 json_object* poExceededTransferLimit =
                     json_object_object_get(poObj, "exceededTransferLimit");
                 if( poExceededTransferLimit && json_object_get_type(poExceededTransferLimit) == json_type_boolean )
-                    bOtherPages_ = json_object_get_boolean(poExceededTransferLimit);
+                    bOtherPages_ = CPL_TO_BOOL(
+                        json_object_get_boolean(poExceededTransferLimit) );
             }
             reader.ReadLayers( this );
         }
@@ -530,7 +608,7 @@ void OGRGeoJSONDataSource::LoadLayers(char** papszOpenOptions)
          strstr(pszGeoData_, "\"Topology\"")  )
     {
         OGRTopoJSONReader reader;
-        err = reader.Parse( pszGeoData_ );
+        OGRErr err = reader.Parse( pszGeoData_ );
         if( OGRERR_NONE == err )
         {
             reader.ReadLayers( this );
@@ -548,21 +626,29 @@ void OGRGeoJSONDataSource::LoadLayers(char** papszOpenOptions)
         reader.SetPreserveGeometryType( false );
         CPLDebug( "GeoJSON", "Geometry as OGRGeometryCollection type." );
     }
-    
-    if( eAtributesSkip == flTransAttrs_ )
+
+    if( eAttributesSkip == flTransAttrs_ )
     {
         reader.SetSkipAttributes( true );
         CPLDebug( "GeoJSON", "Skip all attributes." );
     }
-    
+
     reader.SetFlattenNestedAttributes(
-        (bool)CSLFetchBoolean(papszOpenOptions, "FLATTEN_NESTED_ATTRIBUTES", FALSE),
-        CSLFetchNameValueDef(papszOpenOptions, "NESTED_ATTRIBUTE_SEPARATOR", "_")[0]);
+        CPL_TO_BOOL(CSLFetchBoolean(papszOpenOptionsIn, "FLATTEN_NESTED_ATTRIBUTES", FALSE)),
+        CSLFetchNameValueDef(papszOpenOptionsIn, "NESTED_ATTRIBUTE_SEPARATOR", "_")[0]);
+
+    const int bDefaultNativeData = bUpdatable_ ? TRUE : FALSE ;
+    reader.SetStoreNativeData(
+        CPL_TO_BOOL(CSLFetchBoolean(papszOpenOptionsIn, "NATIVE_DATA", bDefaultNativeData)));
+
+    reader.SetArrayAsString(
+        CPLTestBool(CSLFetchNameValueDef(papszOpenOptionsIn, "ARRAY_AS_STRING",
+                CPLGetConfigOption("OGR_GEOJSON_ARRAY_AS_STRING", "NO"))));
 
 /* -------------------------------------------------------------------- */
 /*      Parse GeoJSON and build valid OGRLayer instance.                */
 /* -------------------------------------------------------------------- */
-    err = reader.Parse( pszGeoData_ );
+    OGRErr err = reader.Parse( pszGeoData_ );
     if( OGRERR_NONE == err )
     {
         json_object* poObj = reader.GetJSonObject();
@@ -574,7 +660,8 @@ void OGRGeoJSONDataSource::LoadLayers(char** papszOpenOptions)
                 json_object* poExceededTransferLimit =
                     json_object_object_get(poProperties, "exceededTransferLimit");
                 if( poExceededTransferLimit && json_object_get_type(poExceededTransferLimit) == json_type_boolean )
-                    bOtherPages_ = json_object_get_boolean(poExceededTransferLimit);
+                  bOtherPages_ = CPL_TO_BOOL(
+                      json_object_get_boolean(poExceededTransferLimit) );
             }
         }
 
@@ -590,13 +677,114 @@ void OGRGeoJSONDataSource::LoadLayers(char** papszOpenOptions)
 
 void OGRGeoJSONDataSource::AddLayer( OGRGeoJSONLayer* poLayer )
 {
+    CPLAssert(papoLayersWriter_ == NULL);
 
     poLayer->DetectGeometryType();
 
     /* Return layer in readable state. */
     poLayer->ResetReading();
 
-    papoLayers_ = (OGRLayer**)CPLRealloc( papoLayers_, sizeof(OGRLayer*) * (nLayers_ + 1));
-    papoLayers_[nLayers_] = poLayer; 
+    papoLayers_ = (OGRGeoJSONLayer**)CPLRealloc( papoLayers_, sizeof(OGRGeoJSONLayer*) * (nLayers_ + 1));
+    papoLayers_[nLayers_] = poLayer;
     nLayers_ ++;
 }
+
+/************************************************************************/
+/*                            FlushCache()                              */
+/************************************************************************/
+
+void OGRGeoJSONDataSource::FlushCache()
+{
+    if( papoLayersWriter_ != NULL )
+        return;
+
+    for( int i=0; i < nLayers_; i++ )
+    {
+        if( papoLayers_[i]->HasBeenUpdated() )
+        {
+            papoLayers_[i]->SetUpdated(false);
+
+            CPLString osBackup(pszName_);
+            osBackup += ".bak";
+            if( VSIRename(pszName_, osBackup) < 0 )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Cannot create backup copy");
+                return;
+            }
+
+            bool bOK = false;
+
+            // Disable all filters
+            OGRFeatureQuery *poAttrQueryBak = papoLayers_[i]->m_poAttrQuery;
+            papoLayers_[i]->m_poAttrQuery = NULL;
+            OGRGeometry* poFilterGeomBak = papoLayers_[i]->m_poFilterGeom;
+            papoLayers_[i]->m_poFilterGeom = NULL;
+
+            // If the source data only contained one single feature and
+            // that's still the case, then do not use a FeatureCollection
+            // on writing
+            bool bAlreadyDone = false;
+            if( papoLayers_[i]->GetFeatureCount(TRUE) == 1 &&
+                papoLayers_[i]->GetMetadata("NATIVE_DATA") == NULL )
+            {
+                papoLayers_[i]->ResetReading();
+                OGRFeature* poFeature = papoLayers_[i]->GetNextFeature();
+                if( poFeature != NULL )
+                {
+                    if( poFeature->GetNativeData() != NULL )
+                    {
+                        bAlreadyDone = true;
+                        json_object* poObj = OGRGeoJSONWriteFeature( poFeature,
+                                                                     FALSE/* bWriteBBOX */,
+                                                                     -1 /*nCoordPrecision*/,
+                                                                     -1 /* nSignificatnFigures*/);
+                        VSILFILE* fp = VSIFOpenL(pszName_, "wb");
+                        if( fp != NULL )
+                        {
+                            bOK = VSIFPrintfL( fp, "%s", json_object_to_json_string( poObj ) ) > 0;
+                            VSIFCloseL( fp );
+                        }
+                        json_object_put( poObj );
+                    }
+                    delete poFeature;
+                }
+            }
+
+            // Otherwise do layer translation
+            if( !bAlreadyDone )
+            {
+                char** papszOptions = NULL;
+                papszOptions = CSLAddString(papszOptions, "-f");
+                papszOptions = CSLAddString(papszOptions, "GeoJSON");
+                GDALVectorTranslateOptions* psOptions =
+                    GDALVectorTranslateOptionsNew(papszOptions, NULL);
+                CSLDestroy(papszOptions);
+                GDALDatasetH hSrcDS = this;
+                GDALDatasetH hOutDS =
+                    GDALVectorTranslate(pszName_, NULL, 1, &hSrcDS, psOptions, NULL);
+                GDALVectorTranslateOptionsFree(psOptions);
+
+                if( hOutDS != NULL )
+                {
+                    CPLErrorReset();
+                    GDALClose(hOutDS);
+                    bOK = (CPLGetLastErrorType() == CE_None);
+                }
+            }
+
+            // Restore filters
+            papoLayers_[i]->m_poAttrQuery = poAttrQueryBak;
+            papoLayers_[i]->m_poFilterGeom = poFilterGeomBak;
+
+            if( bOK )
+            {
+                VSIUnlink(osBackup);
+            }
+            else
+            {
+                VSIRename(osBackup, pszName_);
+            }
+        }
+    }
+}
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsondriver.cpp b/ogr/ogrsf_frmts/geojson/ogrgeojsondriver.cpp
index 21c7f27..c36f113 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsondriver.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsondriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsondriver.cpp 29134 2015-05-03 18:17:46Z rouault $
+ * $Id: ogrgeojsondriver.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of OGRGeoJSONDriver class (OGR GeoJSON Driver).
@@ -26,9 +26,10 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#include "ogr_geojson.h"
+
 #include <cpl_conv.h>
-#include "cpl_http.h"
+#include <cpl_http.h>
+#include "ogr_geojson.h"
 
 class OGRESRIFeatureServiceDataset;
 
@@ -42,8 +43,8 @@ class OGRESRIFeatureServiceLayer: public OGRLayer
         OGRFeatureDefn* poFeatureDefn;
         GIntBig         nFeaturesRead;
         GIntBig         nLastFID;
-        int             bOtherPage;
-        int             bUseSequentialFID;
+        bool            bOtherPage;
+        bool            bUseSequentialFID;
 
     public:
         OGRESRIFeatureServiceLayer(OGRESRIFeatureServiceDataset* poDS);
@@ -53,6 +54,9 @@ class OGRESRIFeatureServiceLayer: public OGRLayer
         OGRFeature* GetNextFeature();
         GIntBig GetFeatureCount( int bForce = TRUE );
         OGRErr              GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+        virtual OGRErr      GetExtent( int iGeomField, OGREnvelope *psExtent,
+                                       int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
         int TestCapability( const char* pszCap );
         OGRFeatureDefn* GetLayerDefn() { return poFeatureDefn; }
 };
@@ -67,7 +71,7 @@ class OGRESRIFeatureServiceDataset: public GDALDataset
         GIntBig                nFirstOffset, nLastOffset;
         OGRGeoJSONDataSource* poCurrent;
         OGRESRIFeatureServiceLayer* poLayer;
-        
+
         int                     LoadPage();
 
     public:
@@ -77,12 +81,12 @@ class OGRESRIFeatureServiceDataset: public GDALDataset
 
         int GetLayerCount() { return 1; }
         OGRLayer* GetLayer( int nLayer ) { return (nLayer == 0) ? poLayer : NULL; }
-        
+
         OGRLayer* GetUnderlyingLayer() { return poCurrent->GetLayer(0); }
 
         int ResetReading();
         int LoadNextPage();
-        
+
         const CPLString&                GetURL() { return osURL; }
 };
 
@@ -90,9 +94,14 @@ class OGRESRIFeatureServiceDataset: public GDALDataset
 /*                       OGRESRIFeatureServiceLayer()                   */
 /************************************************************************/
 
-OGRESRIFeatureServiceLayer::OGRESRIFeatureServiceLayer(OGRESRIFeatureServiceDataset* poDS)
+OGRESRIFeatureServiceLayer::OGRESRIFeatureServiceLayer(
+    OGRESRIFeatureServiceDataset* poDSIn) :
+    poDS(poDSIn),
+    nFeaturesRead(0),
+    nLastFID(0),
+    bOtherPage(false),
+    bUseSequentialFID(false)
 {
-    this->poDS = poDS;
     OGRFeatureDefn* poSrcFeatDefn = poDS->GetUnderlyingLayer()->GetLayerDefn();
     poFeatureDefn = new OGRFeatureDefn(poSrcFeatDefn->GetName());
     SetDescription(poFeatureDefn->GetName());
@@ -102,10 +111,6 @@ OGRESRIFeatureServiceLayer::OGRESRIFeatureServiceLayer(OGRESRIFeatureServiceData
         poFeatureDefn->AddFieldDefn(poSrcFeatDefn->GetFieldDefn(i));
     for(int i=0;i<poSrcFeatDefn->GetGeomFieldCount();i++)
         poFeatureDefn->AddGeomFieldDefn(poSrcFeatDefn->GetGeomFieldDefn(i));
-    nFeaturesRead = 0;
-    nLastFID = 0;
-    bOtherPage = FALSE;
-    bUseSequentialFID = FALSE;
 }
 
 /************************************************************************/
@@ -126,8 +131,8 @@ void OGRESRIFeatureServiceLayer::ResetReading()
     poDS->ResetReading();
     nFeaturesRead = 0;
     nLastFID = 0;
-    bOtherPage = FALSE;
-    bUseSequentialFID = FALSE;
+    bOtherPage = false;
+    bUseSequentialFID = false;
 }
 
 /************************************************************************/
@@ -136,9 +141,9 @@ void OGRESRIFeatureServiceLayer::ResetReading()
 
 OGRFeature* OGRESRIFeatureServiceLayer::GetNextFeature()
 {
-    while( TRUE )
+    while( true )
     {
-        int bWasInFirstPage = !bOtherPage;
+        const bool bWasInFirstPage = !bOtherPage;
         OGRFeature* poSrcFeat = poDS->GetUnderlyingLayer()->GetNextFeature();
         if( poSrcFeat == NULL )
         {
@@ -147,12 +152,12 @@ OGRFeature* OGRESRIFeatureServiceLayer::GetNextFeature()
             poSrcFeat = poDS->GetUnderlyingLayer()->GetNextFeature();
             if( poSrcFeat == NULL )
                 return NULL;
-            bOtherPage = TRUE;
+            bOtherPage = true;
         }
         if( bOtherPage && bWasInFirstPage && poSrcFeat->GetFID() == 0 &&
             nLastFID == nFeaturesRead - 1 )
         {
-            bUseSequentialFID = TRUE;
+            bUseSequentialFID = true;
         }
 
         OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
@@ -164,7 +169,7 @@ OGRFeature* OGRESRIFeatureServiceLayer::GetNextFeature()
         nLastFID = poFeature->GetFID();
         nFeaturesRead ++;
         delete poSrcFeat;
-        
+
         if((m_poFilterGeom == NULL
             || FilterGeometry( poFeature->GetGeometryRef() ) )
         && (m_poAttrQuery == NULL
@@ -196,7 +201,7 @@ int OGRESRIFeatureServiceLayer::TestCapability( const char* pszCap )
 GIntBig OGRESRIFeatureServiceLayer::GetFeatureCount( int bForce )
 {
     GIntBig nFeatureCount = -1;
-    if( m_poAttrQuery == NULL && m_poFilterGeom == NULL ) 
+    if( m_poAttrQuery == NULL && m_poFilterGeom == NULL )
     {
         CPLString osNewURL = CPLURLAddKVP(poDS->GetURL(), "returnCountOnly", "true");
         CPLHTTPResult* pResult = NULL;
@@ -232,9 +237,8 @@ OGRErr OGRESRIFeatureServiceLayer::GetExtent(OGREnvelope *psExtent, int bForce)
     OGRErr eErr = OGRERR_FAILURE;
     CPLString osNewURL = CPLURLAddKVP(poDS->GetURL(), "returnExtentOnly", "true");
     osNewURL = CPLURLAddKVP(osNewURL, "f", "geojson");
-    CPLHTTPResult* pResult = NULL;
     CPLErrorReset();
-    pResult = CPLHTTPFetch( osNewURL, NULL );
+    CPLHTTPResult* pResult = CPLHTTPFetch( osNewURL, NULL );
     if( pResult != NULL && pResult->nDataLen != 0 && CPLGetLastErrorNo() == 0 &&
         pResult->nStatus == 0 )
     {
@@ -268,12 +272,12 @@ OGRErr OGRESRIFeatureServiceLayer::GetExtent(OGREnvelope *psExtent, int bForce)
 /*                      OGRESRIFeatureServiceDataset()                  */
 /************************************************************************/
 
-OGRESRIFeatureServiceDataset::OGRESRIFeatureServiceDataset(const CPLString &osURL,
-                                                           OGRGeoJSONDataSource* poFirst)
+OGRESRIFeatureServiceDataset::OGRESRIFeatureServiceDataset(const CPLString &osURLIn,
+                                                           OGRGeoJSONDataSource* poFirst) :
+    poCurrent(poFirst)
 {
-    poCurrent = poFirst;
     poLayer = new OGRESRIFeatureServiceLayer(this);
-    this->osURL = osURL;
+    this->osURL = osURLIn;
     if( CPLURLGetValue(this->osURL, "resultRecordCount").size() == 0 )
     {
         // We assume that if the server sets the exceededTransferLimit, the
@@ -318,11 +322,9 @@ int OGRESRIFeatureServiceDataset::ResetReading()
         nLastOffset = nFirstOffset;
         return LoadPage();
     }
-    else
-    {
-        poCurrent->GetLayer(0)->ResetReading();
-        return TRUE;
-    }
+
+    poCurrent->GetLayer(0)->ResetReading();
+    return TRUE;
 }
 
 /************************************************************************/
@@ -345,21 +347,20 @@ int OGRESRIFeatureServiceDataset::LoadPage()
 {
     CPLString osNewURL = CPLURLAddKVP(osURL, "resultOffset",
                                         CPLSPrintf(CPL_FRMT_GIB, nLastOffset));
-    OGRGeoJSONDataSource* poDS = NULL;
-    poDS = new OGRGeoJSONDataSource();
+    OGRGeoJSONDataSource* poDS
+        = new OGRGeoJSONDataSource();
     GDALOpenInfo oOpenInfo(osNewURL, GA_ReadOnly);
     if( !poDS->Open( &oOpenInfo, GeoJSONGetSourceType( &oOpenInfo ) ) ||
         poDS->GetLayerCount() == 0 )
     {
         delete poDS;
-        poDS= NULL;
+        poDS = NULL;
         return FALSE;
     }
     delete poCurrent;
     poCurrent = poDS;
     return TRUE;
 }
-    
 
 /************************************************************************/
 /*                        OGRGeoJSONDriverIdentify()                    */
@@ -401,8 +402,8 @@ static GDALDataset* OGRGeoJSONDriverOpen( GDALOpenInfo* poOpenInfo )
     if( OGRGeoJSONDriverIdentifyInternal(poOpenInfo, nSrcType) == FALSE )
         return NULL;
 
-    OGRGeoJSONDataSource* poDS = NULL;
-    poDS = new OGRGeoJSONDataSource();
+    OGRGeoJSONDataSource* poDS
+        = new OGRGeoJSONDataSource();
 
 /* -------------------------------------------------------------------- */
 /*      Processing configuration options.                               */
@@ -414,44 +415,37 @@ static GDALDataset* OGRGeoJSONDriverOpen( GDALOpenInfo* poOpenInfo )
 
     poDS->SetGeometryTranslation( OGRGeoJSONDataSource::eGeometryPreserve );
     const char* pszOpt = CPLGetConfigOption("GEOMETRY_AS_COLLECTION", NULL);
-    if( NULL != pszOpt && EQUALN(pszOpt, "YES", 3) )
+    if( NULL != pszOpt && STARTS_WITH_CI(pszOpt, "YES") )
     {
             poDS->SetGeometryTranslation(
                 OGRGeoJSONDataSource::eGeometryAsCollection );
     }
 
-    poDS->SetAttributesTranslation( OGRGeoJSONDataSource::eAtributesPreserve );
+    poDS->SetAttributesTranslation( OGRGeoJSONDataSource::eAttributesPreserve );
     pszOpt = CPLGetConfigOption("ATTRIBUTES_SKIP", NULL);
-    if( NULL != pszOpt && EQUALN(pszOpt, "YES", 3) )
+    if( NULL != pszOpt && STARTS_WITH_CI(pszOpt, "YES") )
     {
-        poDS->SetAttributesTranslation( 
-            OGRGeoJSONDataSource::eAtributesSkip );
+        poDS->SetAttributesTranslation(
+            OGRGeoJSONDataSource::eAttributesSkip );
     }
 
 /* -------------------------------------------------------------------- */
-/*      Open and start processing GeoJSON datasoruce to OGR objects.    */
+/*      Open and start processing GeoJSON datasource to OGR objects.    */
 /* -------------------------------------------------------------------- */
     if( !poDS->Open( poOpenInfo, nSrcType ) )
     {
         delete poDS;
-        poDS= NULL;
+        poDS = NULL;
     }
 
-    if( NULL != poDS && poOpenInfo->eAccess == GA_Update )
-    {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "GeoJSON Driver doesn't support update." );
-        delete poDS;
-        return NULL;
-    }
-    
     if( poDS != NULL && poDS->HasOtherPages() )
     {
         const char* pszFSP = CSLFetchNameValue(poOpenInfo->papszOpenOptions,
                                                "FEATURE_SERVER_PAGING");
-        int bHasResultOffset = CPLURLGetValue(poOpenInfo->pszFilename, "resultOffset").size() > 0;
-        if( (!bHasResultOffset && (pszFSP == NULL || CSLTestBoolean(pszFSP))) ||
-            (bHasResultOffset && pszFSP != NULL && CSLTestBoolean(pszFSP)) )
+        bool bHasResultOffset = CPLURLGetValue( poOpenInfo->pszFilename,
+                                                "resultOffset").size() > 0;
+        if( (!bHasResultOffset && (pszFSP == NULL || CPLTestBool(pszFSP))) ||
+            (bHasResultOffset && pszFSP != NULL && CPLTestBool(pszFSP)) )
         {
             return new OGRESRIFeatureServiceDataset(poOpenInfo->pszFilename,
                                                     poDS);
@@ -493,7 +487,7 @@ static CPLErr OGRGeoJSONDriverDelete( const char *pszFilename )
     {
         return CE_None;
     }
-    
+
     CPLDebug( "GeoJSON", "Failed to delete \'%s\'", pszFilename);
 
     return CE_Failure;
@@ -508,44 +502,47 @@ void RegisterOGRGeoJSON()
     if( !GDAL_CHECK_VERSION("OGR/GeoJSON driver") )
         return;
 
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "GeoJSON" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "GeoJSON" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "GeoJSON" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "GeoJSON" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "json geojson topojson" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_geojson.html" );
+    poDriver->SetDescription( "GeoJSON" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "GeoJSON" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "json geojson topojson" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_geojson.html" );
 
-        poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
 "<OpenOptionList>"
 "  <Option name='FLATTEN_NESTED_ATTRIBUTES' type='boolean' description='Whether to recursively explore nested objects and produce flatten OGR attributes' default='NO'/>"
 "  <Option name='NESTED_ATTRIBUTE_SEPARATOR' type='string' description='Separator between components of nested attributes' default='_'/>"
 "  <Option name='FEATURE_SERVER_PAGING' type='boolean' description='Whether to automatically scroll through results with a ArcGIS Feature Service endpoint'/>"
+"  <Option name='NATIVE_DATA' type='boolean' description='Whether to store the native JSon representation at FeatureCollection and Feature level' default='NO'/>"
+"  <Option name='ARRAY_AS_STRING' type='boolean' description='Whether to expose JSon arrays of strings, integers or reals as a OGR String' default='NO'/>"
 "</OpenOptionList>");
 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, "<CreationOptionList/>");
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+                               "<CreationOptionList/>");
 
-        poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
 "<LayerCreationOptionList>"
 "  <Option name='WRITE_BBOX' type='boolean' description='whether to write a bbox property with the bounding box of the geometries at the feature and feature collection level' default='NO'/>"
-"  <Option name='COORDINATE_PRECISION' type='int' description='Number of decimal for coordinates' default='10'/>"
+"  <Option name='COORDINATE_PRECISION' type='int' description='Number of decimal for coordinates' default='15'/>"
+"  <Option name='SIGNIFICANT_FIGURES' type='int' description='Number of significant figures for floating-point values' default='17'/>"
+"  <Option name='NATIVE_DATA' type='string' description='FeatureCollection level elements.'/>"
+"  <Option name='NATIVE_MEDIA_TYPE' type='string' description='Format of NATIVE_DATA. Must be \"application/vnd.geo+json\", otherwise NATIVE_DATA will be ignored.'/>"
 "</LayerCreationOptionList>");
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-        
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES, "Integer Integer64 Real String IntegerList Integer64List RealList StringList" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
+                               "Integer Integer64 Real String IntegerList "
+                               "Integer64List RealList StringList" );
 
-        poDriver->pfnOpen = OGRGeoJSONDriverOpen;
-        poDriver->pfnIdentify = OGRGeoJSONDriverIdentify;
-        poDriver->pfnCreate = OGRGeoJSONDriverCreate;
-        poDriver->pfnDelete = OGRGeoJSONDriverDelete;
+    poDriver->pfnOpen = OGRGeoJSONDriverOpen;
+    poDriver->pfnIdentify = OGRGeoJSONDriverIdentify;
+    poDriver->pfnCreate = OGRGeoJSONDriverCreate;
+    poDriver->pfnDelete = OGRGeoJSONDriverDelete;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonlayer.cpp b/ogr/ogrsf_frmts/geojson/ogrgeojsonlayer.cpp
index 6a1e073..b0ed7e2 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonlayer.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsonlayer.cpp 29111 2015-05-02 18:06:16Z rouault $
+ * $Id: ogrgeojsonlayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of OGRGeoJSONLayer class (OGR GeoJSON Driver).
@@ -51,17 +51,11 @@ const OGRwkbGeometryType OGRGeoJSONLayer::DefaultGeometryType = wkbUnknown;
 OGRGeoJSONLayer::OGRGeoJSONLayer( const char* pszName,
                                   OGRSpatialReference* poSRSIn,
                                   OGRwkbGeometryType eGType,
-                                  CPL_UNUSED OGRGeoJSONDataSource* poDS )
-  : iterCurrent_( seqFeatures_.end() ), /* poDS_( poDS ), */ poFeatureDefn_(new OGRFeatureDefn( pszName ) )
+                                  OGRGeoJSONDataSource* poDS )
+  : OGRMemLayer( pszName, poSRSIn, eGType), poDS_(poDS), bUpdated_(false)
 {
-    /* CPLAssert( NULL != poDS_ ); */
-    CPLAssert( NULL != poFeatureDefn_ );
-    
-    poFeatureDefn_->Reference();
-    poFeatureDefn_->SetGeomType( eGType );
-    if( poFeatureDefn_->GetGeomFieldCount() != 0 )
-        poFeatureDefn_->GetGeomFieldDefn(0)->SetSpatialRef(poSRSIn);
-    SetDescription( poFeatureDefn_->GetName() );
+    SetAdvertizeUTF8(true);
+    SetUpdatable( poDS->IsUpdatable() );
 }
 
 /************************************************************************/
@@ -70,109 +64,46 @@ OGRGeoJSONLayer::OGRGeoJSONLayer( const char* pszName,
 
 OGRGeoJSONLayer::~OGRGeoJSONLayer()
 {
-    std::for_each(seqFeatures_.begin(), seqFeatures_.end(),
-                  OGRFeature::DestroyFeature);
-
-    if( NULL != poFeatureDefn_ )
-    {
-        poFeatureDefn_->Release();
-    }
-}
-
-/************************************************************************/
-/*                           GetLayerDefn                               */
-/************************************************************************/
-
-OGRFeatureDefn* OGRGeoJSONLayer::GetLayerDefn()
-{
-    return poFeatureDefn_;
-}
-
-/************************************************************************/
-/*                           GetFeatureCount                            */
-/************************************************************************/
-
-GIntBig OGRGeoJSONLayer::GetFeatureCount( int bForce )
-{
-    if (m_poFilterGeom == NULL && m_poAttrQuery == NULL)
-        return static_cast<int>( seqFeatures_.size() );
-    else
-        return OGRLayer::GetFeatureCount(bForce);
 }
 
 /************************************************************************/
-/*                           ResetReading                               */
+/*                           GetFIDColumn                               */
 /************************************************************************/
 
-void OGRGeoJSONLayer::ResetReading()
+const char* OGRGeoJSONLayer::GetFIDColumn()
 {
-    iterCurrent_ = seqFeatures_.begin();
+	return sFIDColumn_.c_str();
 }
 
 /************************************************************************/
-/*                           GetNextFeature                             */
+/*                           SetFIDColumn                               */
 /************************************************************************/
 
-OGRFeature* OGRGeoJSONLayer::GetNextFeature()
+void OGRGeoJSONLayer::SetFIDColumn( const char* pszFIDColumn )
 {
-    while ( iterCurrent_ != seqFeatures_.end() )
-    {
-        OGRFeature* poFeature = (*iterCurrent_);
-        CPLAssert( NULL != poFeature );
-        ++iterCurrent_;
-        
-        if((m_poFilterGeom == NULL
-            || FilterGeometry( poFeature->GetGeometryRef() ) )
-        && (m_poAttrQuery == NULL
-            || m_poAttrQuery->Evaluate( poFeature )) )
-        {
-            OGRFeature* poFeatureCopy = poFeature->Clone();
-            CPLAssert( NULL != poFeatureCopy );
-
-            if (poFeatureCopy->GetGeometryRef() != NULL && GetSpatialRef() != NULL)
-            {
-                poFeatureCopy->GetGeometryRef()->assignSpatialReference( GetSpatialRef() );
-            }
-
-            return poFeatureCopy;
-        }
-    }
-
-    return NULL;
+	sFIDColumn_ = pszFIDColumn;
 }
 
 /************************************************************************/
-/*                           TestCapability                             */
+/*                           TestCapability()                           */
 /************************************************************************/
 
-int OGRGeoJSONLayer::TestCapability( const char* pszCap )
-{
-    if( EQUAL(pszCap, OLCFastFeatureCount) ||
-        EQUAL(pszCap, OLCFastGetExtent) ||
-        EQUAL(pszCap, OLCStringsAsUTF8) )
-    {
-        return TRUE;
-    }
+int OGRGeoJSONLayer::TestCapability( const char * pszCap )
 
-    return FALSE;
-}
-
-/************************************************************************/
-/*                           GetFIDColumn                               */
-/************************************************************************/
-	
-const char* OGRGeoJSONLayer::GetFIDColumn()
 {
-	return sFIDColumn_.c_str();
+    if( EQUAL(pszCap, OLCCurveGeometries) )
+        return FALSE;
+    return OGRMemLayer::TestCapability(pszCap);
 }
 
 /************************************************************************/
-/*                           SetFIDColumn                               */
+/*                           SyncToDisk()                               */
 /************************************************************************/
 
-void OGRGeoJSONLayer::SetFIDColumn( const char* pszFIDColumn )
+OGRErr OGRGeoJSONLayer::SyncToDisk()
 {
-	sFIDColumn_ = pszFIDColumn;
+    poDS_->FlushCache();
+    return OGRERR_NONE;
 }
 
 /************************************************************************/
@@ -181,36 +112,29 @@ void OGRGeoJSONLayer::SetFIDColumn( const char* pszFIDColumn )
 
 void OGRGeoJSONLayer::AddFeature( OGRFeature* poFeature )
 {
-    CPLAssert( NULL != poFeature );
-
-    // NOTE - mloskot:
-    // Features may not be sorted according to FID values.
-
-    // TODO: Should we check if feature already exists?
-    // TODO: Think about sync operation, upload, etc.
-
-    OGRFeature* poNewFeature = NULL;
-    poNewFeature = poFeature->Clone();
-
-
-    if( -1 == poNewFeature->GetFID() )
+    if( -1 == poFeature->GetFID() )
     {
-        int nFID = static_cast<int>(seqFeatures_.size());
-        poNewFeature->SetFID( nFID );
-
-        // TODO - mlokot: We need to redesign creation of FID column
-        int nField = poNewFeature->GetFieldIndex( DefaultFIDColumn );
-        if( -1 != nField && GetLayerDefn()->GetFieldDefn(nField)->GetType() == OFTInteger )
+        GIntBig nFID = GetFeatureCount(FALSE);
+        poFeature->SetFID( nFID );
+
+        // TODO - mloskot: We need to redesign creation of FID column
+        int nField = poFeature->GetFieldIndex( DefaultFIDColumn );
+        if( -1 != nField &&
+            (GetLayerDefn()->GetFieldDefn(nField)->GetType() == OFTInteger ||
+             GetLayerDefn()->GetFieldDefn(nField)->GetType() == OFTInteger64 ))
         {
-            poNewFeature->SetField( nField, nFID );
+            poFeature->SetField( nField, nFID );
         }
     }
-    
-        
-    if( (GIntBig)(int)poNewFeature->GetFID() != poNewFeature->GetFID() )
+
+    GIntBig nFID = poFeature->GetFID();
+    if( !CPL_INT64_FITS_ON_INT32(nFID) )
         SetMetadataItem(OLMD_FID64, "YES");
 
-    seqFeatures_.push_back( poNewFeature );
+    SetUpdatable( true ); /* temporary toggle on updatable flag */
+    CPL_IGNORE_RET_VAL(OGRMemLayer::SetFeature(poFeature));
+    SetUpdatable( poDS_->IsUpdatable() );
+    SetUpdated( false );
 }
 
 /************************************************************************/
@@ -219,42 +143,36 @@ void OGRGeoJSONLayer::AddFeature( OGRFeature* poFeature )
 
 void OGRGeoJSONLayer::DetectGeometryType()
 {
-    if (poFeatureDefn_->GetGeomType() != wkbUnknown)
+    if (GetLayerDefn()->GetGeomType() != wkbUnknown)
         return;
 
-    OGRwkbGeometryType featType = wkbUnknown;
-    OGRGeometry* poGeometry = NULL;
-    FeaturesSeq::const_iterator it = seqFeatures_.begin();
-    FeaturesSeq::const_iterator end = seqFeatures_.end();
-    
-    if( it != end )
+    ResetReading();
+    bool bFirstGeometry = true;
+    OGRwkbGeometryType eLayerGeomType = wkbUnknown;
+    OGRFeature* poFeature;
+    while( (poFeature = GetNextFeature()) != NULL )
     {
-        poGeometry = (*it)->GetGeometryRef();
+        OGRGeometry* poGeometry = poFeature->GetGeometryRef();
         if( NULL != poGeometry )
         {
-            featType = poGeometry->getGeometryType();
-            if( featType != poFeatureDefn_->GetGeomType() )
+            OGRwkbGeometryType eGeomType = poGeometry->getGeometryType();
+            if( bFirstGeometry )
             {
-                poFeatureDefn_->SetGeomType( featType );
+                eLayerGeomType = eGeomType;
+                GetLayerDefn()->SetGeomType( eGeomType );
+                bFirstGeometry = false;
             }
-        }
-        ++it;
-    }
-
-    while( it != end )
-    {
-        poGeometry = (*it)->GetGeometryRef();
-        if( NULL != poGeometry )
-        {
-            featType = poGeometry->getGeometryType();
-            if( featType != poFeatureDefn_->GetGeomType() )
+            else if( eGeomType != eLayerGeomType )
             {
                 CPLDebug( "GeoJSON",
                     "Detected layer of mixed-geometry type features." );
-                poFeatureDefn_->SetGeomType( DefaultGeometryType );
+                GetLayerDefn()->SetGeomType( DefaultGeometryType );
+                delete poFeature;
                 break;
             }
         }
-        ++it;
+        delete poFeature;
     }
+
+    ResetReading();
 }
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.cpp b/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.cpp
index e2f53a5..990d56a 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsonreader.cpp 31112 2015-10-23 20:28:27Z rouault $
+ * $Id: ogrgeojsonreader.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of OGRGeoJSONReader class (OGR GeoJSON Driver).
@@ -37,16 +37,20 @@
 /*                           OGRGeoJSONReader                           */
 /************************************************************************/
 
-OGRGeoJSONReader::OGRGeoJSONReader()
-    : poGJObject_( NULL ),
-        bGeometryPreserve_( true ),
-        bAttributesSkip_( false ),
-        bFlattenNestedAttributes_ (false),
-        chNestedAttributeSeparator_ (0),
-        bFlattenGeocouchSpatiallistFormat (-1), bFoundId (false), bFoundRev(false), bFoundTypeFeature(false), bIsGeocouchSpatiallistFormat(false)
-{
-    // Take a deep breath and get to work.
-}
+OGRGeoJSONReader::OGRGeoJSONReader() :
+    poGJObject_(NULL),
+    bGeometryPreserve_(true),
+    bAttributesSkip_(false),
+    bFlattenNestedAttributes_(false),
+    chNestedAttributeSeparator_(0),
+    bStoreNativeData_(false),
+    bArrayAsString_(false),
+    bFlattenGeocouchSpatiallistFormat(-1),
+    bFoundId(false),
+    bFoundRev(false),
+    bFoundTypeFeature(false),
+    bIsGeocouchSpatiallistFormat(false)
+{ }
 
 /************************************************************************/
 /*                          ~OGRGeoJSONReader                           */
@@ -70,9 +74,6 @@ OGRErr OGRGeoJSONReader::Parse( const char* pszText )
 {
     if( NULL != pszText )
     {
-        json_tokener* jstok = NULL;
-        json_object* jsobj = NULL;
-
         /* Skip UTF-8 BOM (#5630) */
         const GByte* pabyData = (const GByte*)pszText;
         if( pabyData[0] == 0xEF && pabyData[1] == 0xBB && pabyData[2] == 0xBF )
@@ -81,23 +82,11 @@ OGRErr OGRGeoJSONReader::Parse( const char* pszText )
             pszText += 3;
         }
 
-        jstok = json_tokener_new();
-        jsobj = json_tokener_parse_ex(jstok, pszText, -1);
-        if( jstok->err != json_tokener_success)
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "GeoJSON parsing error: %s (at offset %d)",
-            	      json_tokener_error_desc(jstok->err), jstok->char_offset);
-            
-            json_tokener_free(jstok);
-            return OGRERR_CORRUPT_DATA;
-        }
-        json_tokener_free(jstok);
-
         /* JSON tree is shared for while lifetime of the reader object
          * and will be released in the destructor.
          */
-        poGJObject_ = jsobj;
+        if( !OGRJSonParse(pszText, &poGJObject_) )
+            return OGRERR_CORRUPT_DATA;
     }
 
     return OGRERR_NONE;
@@ -112,7 +101,7 @@ void OGRGeoJSONReader::ReadLayers( OGRGeoJSONDataSource* poDS )
     if( NULL == poGJObject_ )
     {
         CPLDebug( "GeoJSON",
-                  "Missing parset GeoJSON data. Forgot to call Parse()?" );
+                  "Missing parsed GeoJSON data. Forgot to call Parse()?" );
         return;
     }
 
@@ -153,8 +142,8 @@ void OGRGeoJSONReader::ReadLayer( OGRGeoJSONDataSource* poDS,
         return;
     }
 
-    OGRSpatialReference* poSRS = NULL;
-    poSRS = OGRGeoJSONReadSpatialReference( poObj );
+    OGRSpatialReference* poSRS
+        = OGRGeoJSONReadSpatialReference( poObj );
     if (poSRS == NULL ) {
         // If there is none defined, we use 4326
         poSRS = new OGRSpatialReference();
@@ -192,8 +181,7 @@ void OGRGeoJSONReader::ReadLayer( OGRGeoJSONDataSource* poDS,
         || GeoJSONObject::eMultiPolygon == objType
         || GeoJSONObject::eGeometryCollection == objType )
     {
-        OGRGeometry* poGeometry = NULL;
-        poGeometry = ReadGeometry( poObj );
+        OGRGeometry* poGeometry = ReadGeometry( poObj );
         if( !AddFeature( poLayer, poGeometry ) )
         {
             CPLDebug( "GeoJSON",
@@ -207,8 +195,7 @@ void OGRGeoJSONReader::ReadLayer( OGRGeoJSONDataSource* poDS,
 /* -------------------------------------------------------------------- */
     else if( GeoJSONObject::eFeature == objType )
     {
-        OGRFeature* poFeature = NULL;
-        poFeature = ReadFeature( poLayer, poObj );
+        OGRFeature* poFeature = ReadFeature( poLayer, poObj );
         if( !AddFeature( poLayer, poFeature ) )
         {
             CPLDebug( "GeoJSON",
@@ -236,7 +223,7 @@ void OGRGeoJSONReader::ReadLayer( OGRGeoJSONDataSource* poDS,
 /************************************************************************/
 
 OGRSpatialReference* OGRGeoJSONReadSpatialReference( json_object* poObj) {
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read spatial reference definition.                              */
 /* -------------------------------------------------------------------- */
@@ -252,7 +239,7 @@ OGRSpatialReference* OGRGeoJSONReadSpatialReference( json_object* poObj) {
         const char* pszSrsType = json_object_get_string( poObjSrsType );
 
         // TODO: Add URL and URN types support
-        if( EQUALN( pszSrsType, "NAME", 4 ) )
+        if( STARTS_WITH_CI(pszSrsType, "NAME") )
         {
             json_object* poObjSrsProps = OGRGeoJSONFindMemberByName( poObjSrs, "properties" );
             if (poObjSrsProps == NULL)
@@ -272,7 +259,7 @@ OGRSpatialReference* OGRGeoJSONReadSpatialReference( json_object* poObj) {
             }
         }
 
-        if( EQUALN( pszSrsType, "EPSG", 4 ) )
+        if( STARTS_WITH_CI(pszSrsType, "EPSG") )
         {
             json_object* poObjSrsProps = OGRGeoJSONFindMemberByName( poObjSrs, "properties" );
             if (poObjSrsProps == NULL)
@@ -292,14 +279,14 @@ OGRSpatialReference* OGRGeoJSONReadSpatialReference( json_object* poObj) {
             }
         }
 
-        if( EQUALN( pszSrsType, "URL", 3 ) || EQUALN( pszSrsType, "LINK", 4 )  )
+        if( STARTS_WITH_CI(pszSrsType, "URL") || STARTS_WITH_CI(pszSrsType, "LINK")  )
         {
             json_object* poObjSrsProps = OGRGeoJSONFindMemberByName( poObjSrs, "properties" );
             if (poObjSrsProps == NULL)
                 return NULL;
 
             json_object* poObjURL = OGRGeoJSONFindMemberByName( poObjSrsProps, "url" );
-            
+
             if (NULL == poObjURL) {
                 poObjURL = OGRGeoJSONFindMemberByName( poObjSrsProps, "href" );
             }
@@ -313,11 +300,9 @@ OGRSpatialReference* OGRGeoJSONReadSpatialReference( json_object* poObj) {
             {
                 delete poSRS;
                 poSRS = NULL;
-
             }
         }
 
-
         if( EQUAL( pszSrsType, "OGC" ) )
         {
             json_object* poObjSrsProps = OGRGeoJSONFindMemberByName( poObjSrs, "properties" );
@@ -349,6 +334,7 @@ OGRSpatialReference* OGRGeoJSONReadSpatialReference( json_object* poObj) {
 
     return poSRS;
 }
+
 /************************************************************************/
 /*                           SetPreserveGeometryType                    */
 /************************************************************************/
@@ -368,7 +354,7 @@ void OGRGeoJSONReader::SetSkipAttributes( bool bSkip )
 }
 
 /************************************************************************/
-/*                           SetSkipAttributes                          */
+/*                         SetFlattenNestedAttributes                   */
 /************************************************************************/
 
 void OGRGeoJSONReader::SetFlattenNestedAttributes( bool bFlatten, char chSeparator )
@@ -378,6 +364,24 @@ void OGRGeoJSONReader::SetFlattenNestedAttributes( bool bFlatten, char chSeparat
 }
 
 /************************************************************************/
+/*                           SetStoreNativeData                         */
+/************************************************************************/
+
+void OGRGeoJSONReader::SetStoreNativeData( bool bStoreNativeData )
+{
+    bStoreNativeData_ = bStoreNativeData;
+}
+
+/************************************************************************/
+/*                           SetArrayAsString                           */
+/************************************************************************/
+
+void OGRGeoJSONReader::SetArrayAsString( bool bArrayAsString )
+{
+    bArrayAsString_ = bArrayAsString;
+}
+
+/************************************************************************/
 /*                         GenerateLayerDefn()                          */
 /************************************************************************/
 
@@ -387,14 +391,14 @@ bool OGRGeoJSONReader::GenerateLayerDefn( OGRGeoJSONLayer* poLayer, json_object*
     CPLAssert( NULL != poLayer->GetLayerDefn() );
     CPLAssert( 0 == poLayer->GetLayerDefn()->GetFieldCount() );
 
-    bool bSuccess = true;
-
     if( bAttributesSkip_ )
         return true;
 
 /* -------------------------------------------------------------------- */
 /*      Scan all features and generate layer definition.                */
 /* -------------------------------------------------------------------- */
+    bool bSuccess = true;
+
     GeoJSONObject::Type objType = OGRGeoJSONGetType( poGJObject );
     if( GeoJSONObject::eFeature == objType )
     {
@@ -402,16 +406,16 @@ bool OGRGeoJSONReader::GenerateLayerDefn( OGRGeoJSONLayer* poLayer, json_object*
     }
     else if( GeoJSONObject::eFeatureCollection == objType )
     {
-        json_object* poObjFeatures = NULL;
-        poObjFeatures = OGRGeoJSONFindMemberByName( poGJObject, "features" );
+        json_object* poObjFeatures
+            = OGRGeoJSONFindMemberByName( poGJObject, "features" );
         if( NULL != poObjFeatures
             && json_type_array == json_object_get_type( poObjFeatures ) )
         {
-            json_object* poObjFeature = NULL;
             const int nFeatures = json_object_array_length( poObjFeatures );
             for( int i = 0; i < nFeatures; ++i )
             {
-                poObjFeature = json_object_array_get_idx( poObjFeatures, i );
+                json_object* poObjFeature
+                    = json_object_array_get_idx( poObjFeatures, i );
                 if( !GenerateFeatureDefn( poLayer, poObjFeature ) )
                 {
                     CPLDebug( "GeoJSON", "Create feature schema failure." );
@@ -471,7 +475,8 @@ void OGRGeoJSONReaderAddOrUpdateField(OGRFeatureDefn* poDefn,
                                       const char* pszKey,
                                       json_object* poVal,
                                       bool bFlattenNestedAttributes,
-                                      char chNestedAttributeSeparator)
+                                      char chNestedAttributeSeparator,
+                                      bool bArrayAsString)
 {
     if( bFlattenNestedAttributes &&
         poVal != NULL && json_object_get_type(poVal) == json_type_object )
@@ -490,11 +495,13 @@ void OGRGeoJSONReaderAddOrUpdateField(OGRFeatureDefn* poDefn,
             if( it.val != NULL && json_object_get_type(it.val) == json_type_object )
             {
                 OGRGeoJSONReaderAddOrUpdateField(poDefn, osAttrName, it.val,
-                                                 TRUE, chNestedAttributeSeparator);
+                                                 true, chNestedAttributeSeparator,
+                                                 bArrayAsString);
             }
             else
             {
-                OGRGeoJSONReaderAddOrUpdateField(poDefn, osAttrName, it.val, FALSE, 0);
+                OGRGeoJSONReaderAddOrUpdateField(poDefn, osAttrName, it.val, false, 0,
+                                                 bArrayAsString);
             }
         }
         return;
@@ -504,8 +511,8 @@ void OGRGeoJSONReaderAddOrUpdateField(OGRFeatureDefn* poDefn,
     if( nIndex < 0 )
     {
         OGRFieldSubType eSubType;
-        OGRFieldDefn fldDefn( pszKey,
-                                GeoJSONPropertyToFieldType( poVal, eSubType ) );
+        OGRFieldType eType = GeoJSONPropertyToFieldType( poVal, eSubType, bArrayAsString );
+        OGRFieldDefn fldDefn( pszKey, eType );
         fldDefn.SetSubType(eSubType);
         if( eSubType == OFSTBoolean )
             fldDefn.SetWidth(1);
@@ -515,14 +522,14 @@ void OGRGeoJSONReaderAddOrUpdateField(OGRFeatureDefn* poDefn,
         }
         poDefn->AddFieldDefn( &fldDefn );
     }
-    else
+    else if ( poVal ) // If there is a null value: do not update field definition
     {
         OGRFieldDefn* poFDefn = poDefn->GetFieldDefn(nIndex);
         OGRFieldType eType = poFDefn->GetType();
         if( eType == OFTInteger )
         {
             OGRFieldSubType eSubType;
-            OGRFieldType eNewType = GeoJSONPropertyToFieldType( poVal, eSubType );
+            OGRFieldType eNewType = GeoJSONPropertyToFieldType( poVal, eSubType, bArrayAsString );
             if( eNewType == OFTInteger &&
                 poFDefn->GetSubType() == OFSTBoolean && eSubType != OFSTBoolean )
             {
@@ -537,7 +544,7 @@ void OGRGeoJSONReaderAddOrUpdateField(OGRFeatureDefn* poDefn,
         else if( eType == OFTInteger64 )
         {
             OGRFieldSubType eSubType;
-            OGRFieldType eNewType = GeoJSONPropertyToFieldType( poVal, eSubType );
+            OGRFieldType eNewType = GeoJSONPropertyToFieldType( poVal, eSubType, bArrayAsString );
             if( eNewType == OFTReal || eNewType == OFTString )
             {
                 poFDefn->SetType(eNewType);
@@ -547,21 +554,21 @@ void OGRGeoJSONReaderAddOrUpdateField(OGRFeatureDefn* poDefn,
         else if( eType == OFTIntegerList || eType == OFTInteger64List )
         {
             OGRFieldSubType eSubType;
-            OGRFieldType eNewType = GeoJSONPropertyToFieldType( poVal, eSubType );
+            OGRFieldType eNewType = GeoJSONPropertyToFieldType( poVal, eSubType, bArrayAsString );
             if( eNewType == OFTInteger64List || eNewType == OFTRealList || eNewType == OFTStringList )
                 poFDefn->SetType(eNewType);
         }
         else if( eType == OFTRealList )
         {
             OGRFieldSubType eSubType;
-            OGRFieldType eNewType = GeoJSONPropertyToFieldType( poVal, eSubType );
+            OGRFieldType eNewType = GeoJSONPropertyToFieldType( poVal, eSubType, bArrayAsString );
             if( eNewType == OFTStringList )
                 poFDefn->SetType(eNewType);
         }
         else if( eType == OFTDate || eType == OFTTime || eType == OFTDateTime )
         {
             OGRFieldSubType eSubType;
-            OGRFieldType eNewType = GeoJSONPropertyToFieldType( poVal, eSubType );
+            OGRFieldType eNewType = GeoJSONPropertyToFieldType( poVal, eSubType, bArrayAsString );
             if( eNewType == OFTString )
                 eNewType = GeoJSONStringPropertyToFieldType( poVal );
             if( eType != eNewType )
@@ -587,13 +594,10 @@ bool OGRGeoJSONReader::GenerateFeatureDefn( OGRGeoJSONLayer* poLayer, json_objec
     OGRFeatureDefn* poDefn = poLayer->GetLayerDefn();
     CPLAssert( NULL != poDefn );
 
-    bool bSuccess = false;
-
 /* -------------------------------------------------------------------- */
 /*      Read collection of properties.                                  */
 /* -------------------------------------------------------------------- */
-    json_object* poObjProps = NULL;
-    poObjProps = OGRGeoJSONFindMemberByName( poObj, "properties" );
+    json_object* poObjProps = OGRGeoJSONFindMemberByName( poObj, "properties" );
 
     // If there's a top-level id of type string, and no properties.id, then
     // declare a id field
@@ -602,7 +606,7 @@ bool OGRGeoJSONReader::GenerateFeatureDefn( OGRGeoJSONLayer* poLayer, json_objec
         json_object* poObjId = OGRGeoJSONFindMemberByName( poObj, "id" );
         if( poObjId && json_object_get_type(poObjId) == json_type_string )
         {
-            int bHasRegularIdProp = FALSE;
+            bool bHasRegularIdProp = false;
             if( NULL != poObjProps &&
                 json_object_get_type(poObjProps) == json_type_object )
             {
@@ -616,6 +620,8 @@ bool OGRGeoJSONReader::GenerateFeatureDefn( OGRGeoJSONLayer* poLayer, json_objec
         }
     }
 
+    bool bSuccess = false;
+
     if( NULL != poObjProps &&
         json_object_get_type(poObjProps) == json_type_object )
     {
@@ -652,7 +658,7 @@ bool OGRGeoJSONReader::GenerateFeatureDefn( OGRGeoJSONLayer* poLayer, json_objec
                          it.val != NULL && json_object_get_type(it.val) == json_type_object)
                 {
                     if (bFlattenGeocouchSpatiallistFormat < 0)
-                        bFlattenGeocouchSpatiallistFormat = CSLTestBoolean(
+                        bFlattenGeocouchSpatiallistFormat = CPLTestBool(
                             CPLGetConfigOption("GEOJSON_FLATTEN_GEOCOUCH", "TRUE"));
                     if (bFlattenGeocouchSpatiallistFormat)
                     {
@@ -663,9 +669,11 @@ bool OGRGeoJSONReader::GenerateFeatureDefn( OGRGeoJSONLayer* poLayer, json_objec
                 }
 
             }
+
             OGRGeoJSONReaderAddOrUpdateField(poDefn, it.key, it.val,
                                              bFlattenNestedAttributes_,
-                                             chNestedAttributeSeparator_);
+                                             chNestedAttributeSeparator_,
+                                             bArrayAsString_);
         }
 
         bSuccess = true; // SUCCESS
@@ -710,7 +718,7 @@ bool OGRGeoJSONReader::AddFeature( OGRGeoJSONLayer* poLayer, OGRGeometry* poGeom
 {
     bool bAdded = false;
 
-    // TODO: Should we check if geometry is of type of 
+    // TODO: Should we check if geometry is of type of
     //       wkbGeometryCollection ?
 
     if( NULL != poGeometry )
@@ -721,7 +729,7 @@ bool OGRGeoJSONReader::AddFeature( OGRGeoJSONLayer* poLayer, OGRGeometry* poGeom
 
         bAdded = AddFeature( poLayer, poFeature );
     }
-    
+
     return bAdded;
 }
 
@@ -731,16 +739,13 @@ bool OGRGeoJSONReader::AddFeature( OGRGeoJSONLayer* poLayer, OGRGeometry* poGeom
 
 bool OGRGeoJSONReader::AddFeature( OGRGeoJSONLayer* poLayer, OGRFeature* poFeature )
 {
-    bool bAdded = false;
-  
-    if( NULL != poFeature )
-    {
-        poLayer->AddFeature( poFeature );
-        bAdded = true;
-        delete poFeature;
-    }
+    if( poFeature == NULL )
+        return false;
 
-    return bAdded;
+    poLayer->AddFeature( poFeature );
+    delete poFeature;
+
+    return true;
 }
 
 /************************************************************************/
@@ -749,9 +754,8 @@ bool OGRGeoJSONReader::AddFeature( OGRGeoJSONLayer* poLayer, OGRFeature* poFeatu
 
 OGRGeometry* OGRGeoJSONReader::ReadGeometry( json_object* poObj )
 {
-    OGRGeometry* poGeometry = NULL;
-
-    poGeometry = OGRGeoJSONReadGeometry( poObj );
+    OGRGeometry* poGeometry
+        = OGRGeoJSONReadGeometry( poObj );
 
 /* -------------------------------------------------------------------- */
 /*      Wrap geometry with GeometryCollection as a common denominator.  */
@@ -762,7 +766,7 @@ OGRGeometry* OGRGeoJSONReader::ReadGeometry( json_object* poObj )
 /* -------------------------------------------------------------------- */
     if( NULL != poGeometry )
     {
-        if( !bGeometryPreserve_ 
+        if( !bGeometryPreserve_
             && wkbGeometryCollection != poGeometry->getGeometryType() )
         {
             OGRGeometryCollection* poMetaGeometry = NULL;
@@ -806,7 +810,7 @@ static void OGRGeoJSONReaderSetFieldNestedAttribute(OGRLayer* poLayer,
         {
             int nField = poFeature->GetFieldIndex(osAttrName);
             OGRGeoJSONReaderSetField(poLayer, poFeature, nField,
-                                     osAttrName, it.val, FALSE, 0);
+                                     osAttrName, it.val, false, 0);
         }
     }
 }
@@ -823,7 +827,7 @@ void OGRGeoJSONReaderSetField(OGRLayer* poLayer,
                               bool bFlattenNestedAttributes,
                               char chNestedAttributeSeparator)
 {
-    if( bFlattenNestedAttributes && 
+    if( bFlattenNestedAttributes &&
         poVal != NULL && json_object_get_type(poVal) == json_type_object )
     {
         OGRGeoJSONReaderSetFieldNestedAttribute(poLayer,
@@ -831,9 +835,9 @@ void OGRGeoJSONReaderSetField(OGRLayer* poLayer,
                                                 pszAttrPrefix,
                                                 chNestedAttributeSeparator,
                                                 poVal);
-        return ;
+        return;
     }
-    
+
     OGRFieldDefn* poFieldDefn = poFeature->GetFieldDefnRef(nField);
     CPLAssert( NULL != poFieldDefn );
     OGRFieldType eType = poFieldDefn->GetType();
@@ -845,7 +849,7 @@ void OGRGeoJSONReaderSetField(OGRLayer* poLayer,
     else if( OFTInteger == eType )
     {
         poFeature->SetField( nField, json_object_get_int(poVal) );
-                        
+
         /* Check if FID available and set correct value. */
         if( EQUAL( poFieldDefn->GetNameRef(), poLayer->GetFIDColumn() ) )
             poFeature->SetFID( json_object_get_int(poVal) );
@@ -853,7 +857,7 @@ void OGRGeoJSONReaderSetField(OGRLayer* poLayer,
     else if( OFTInteger64 == eType )
     {
         poFeature->SetField( nField, (GIntBig)json_object_get_int64(poVal) );
-        
+
         /* Check if FID available and set correct value. */
         if( EQUAL( poFieldDefn->GetNameRef(), poLayer->GetFIDColumn() ) )
             poFeature->SetFID( (GIntBig)json_object_get_int64(poVal) );
@@ -913,8 +917,8 @@ void OGRGeoJSONReaderSetField(OGRLayer* poLayer,
         {
             int nLength = json_object_array_length(poVal);
             char** papszVal = (char**)CPLMalloc(sizeof(char*) * (nLength+1));
-            int i;
-            for(i=0;i<nLength;i++)
+            int i = 0;
+            for( ;i<nLength;i++)
             {
                 json_object* poRow = json_object_array_get_idx(poVal, i);
                 const char* pszVal = json_object_get_string(poRow);
@@ -944,6 +948,12 @@ OGRFeature* OGRGeoJSONReader::ReadFeature( OGRGeoJSONLayer* poLayer, json_object
     OGRFeature* poFeature = NULL;
     poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
+    if( bStoreNativeData_ )
+    {
+        poFeature->SetNativeData( json_object_to_json_string( poObj ) );
+        poFeature->SetNativeMediaType( "application/vnd.geo+json" );
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Translate GeoJSON "properties" object to feature attributes.    */
 /* -------------------------------------------------------------------- */
@@ -972,14 +982,14 @@ OGRFeature* OGRGeoJSONReader::ReadFeature( OGRGeoJSONLayer* poLayer, json_object
             }
         }
 
-        int nField = -1;
         json_object_iter it;
         it.key = NULL;
         it.val = NULL;
         it.entry = NULL;
         json_object_object_foreachC( poObjProps, it )
         {
-            nField = poFeature->GetFieldIndex(it.key);
+            const int nField
+                = poFeature->GetFieldIndex(it.key);
             OGRGeoJSONReaderSetField(poLayer, poFeature, nField, it.key, it.val,
                                      bFlattenNestedAttributes_,
                                      chNestedAttributeSeparator_);
@@ -1044,7 +1054,7 @@ OGRFeature* OGRGeoJSONReader::ReadFeature( OGRGeoJSONLayer* poLayer, json_object
     json_object_iter it;
     it.key = NULL;
     it.val = NULL;
-    it.entry = NULL;    
+    it.entry = NULL;
     json_object_object_foreachC(poTmp, it)
     {
         if( EQUAL( it.key, "geometry" ) ) {
@@ -1055,7 +1065,7 @@ OGRFeature* OGRGeoJSONReader::ReadFeature( OGRGeoJSONLayer* poLayer, json_object
                 return poFeature;
         }
     }
-    
+
     if( NULL != poObjGeom )
     {
         // NOTE: If geometry can not be parsed or read correctly
@@ -1069,10 +1079,10 @@ OGRFeature* OGRGeoJSONReader::ReadFeature( OGRGeoJSONLayer* poLayer, json_object
     }
     else
     {
-        static int bWarned = FALSE;
+        static bool bWarned = false;
         if( !bWarned )
         {
-            bWarned = TRUE;
+            bWarned = true;
             CPLDebug("GeoJSON", "Non conformant Feature object. Missing \'geometry\' member." );
         }
     }
@@ -1087,8 +1097,8 @@ OGRFeature* OGRGeoJSONReader::ReadFeature( OGRGeoJSONLayer* poLayer, json_object
 void
 OGRGeoJSONReader::ReadFeatureCollection( OGRGeoJSONLayer* poLayer, json_object* poObj )
 {
-    json_object* poObjFeatures = NULL;
-    poObjFeatures = OGRGeoJSONFindMemberByName( poObj, "features" );
+    json_object* poObjFeatures
+        = OGRGeoJSONFindMemberByName( poObj, "features" );
     if( NULL == poObjFeatures )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -1100,19 +1110,58 @@ OGRGeoJSONReader::ReadFeatureCollection( OGRGeoJSONLayer* poLayer, json_object*
     if( json_type_array == json_object_get_type( poObjFeatures ) )
     {
         /* bool bAdded = false; */
-        OGRFeature* poFeature = NULL;
-        json_object* poObjFeature = NULL;
-
         const int nFeatures = json_object_array_length( poObjFeatures );
         for( int i = 0; i < nFeatures; ++i )
         {
-            poObjFeature = json_object_array_get_idx( poObjFeatures, i );
-            poFeature = ReadFeature( poLayer, poObjFeature );
+            json_object* poObjFeature
+                = json_object_array_get_idx( poObjFeatures, i );
+            OGRFeature* poFeature = ReadFeature( poLayer, poObjFeature );
             /* bAdded = */ AddFeature( poLayer, poFeature );
             //CPLAssert( bAdded );
         }
         //CPLAssert( nFeatures == poLayer_->GetFeatureCount() );
     }
+
+    // Collect top objects except 'type' and the 'features' array
+    if( bStoreNativeData_ )
+    {
+        json_object_iter it;
+        it.key = NULL;
+        it.val = NULL;
+        it.entry = NULL;
+        CPLString osNativeData;
+        json_object_object_foreachC(poObj, it)
+        {
+            if( strcmp(it.key, "type") == 0 ||
+                strcmp(it.key, "features") == 0 )
+            {
+                continue;
+            }
+            if( osNativeData.size() == 0 )
+                osNativeData = "{ ";
+            else
+                osNativeData += ", ";
+            json_object* poKey = json_object_new_string(it.key);
+            osNativeData += json_object_to_json_string(poKey);
+            json_object_put(poKey);
+            osNativeData += ": ";
+            osNativeData += json_object_to_json_string(it.val);
+        }
+        if( osNativeData.size() == 0 )
+        {
+            osNativeData = "{ ";
+        }
+        osNativeData += " }";
+
+        osNativeData = "NATIVE_DATA=" + osNativeData;
+
+        char* apszMetadata[3];
+        apszMetadata[0] = (char*) osNativeData.c_str();
+        apszMetadata[1] = (char*) "NATIVE_MEDIA_TYPE=application/vnd.geo+json";
+        apszMetadata[2] = NULL;
+
+        poLayer->SetMetadata( apszMetadata, "NATIVE_DATA" );
+    }
 }
 
 /************************************************************************/
@@ -1137,7 +1186,7 @@ json_object* OGRGeoJSONFindMemberByName( json_object* poObj,
         for( it.entry = json_object_get_object(poTmp)->head;
              ( it.entry ?
                ( it.key = (char*)it.entry->k,
-                 it.val = (json_object*)it.entry->v, it.entry) : 0);
+                 it.val = (json_object*)it.entry->v, 1) : 0);
              it.entry = it.entry->next)
         {
             if( EQUAL( it.key, pszName ) )
@@ -1157,8 +1206,8 @@ GeoJSONObject::Type OGRGeoJSONGetType( json_object* poObj )
     if( NULL == poObj )
         return GeoJSONObject::eUnknown;
 
-    json_object* poObjType = NULL;
-    poObjType = OGRGeoJSONFindMemberByName( poObj, "type" );
+    json_object* poObjType
+        = OGRGeoJSONFindMemberByName( poObj, "type" );
     if( NULL == poObjType )
         return GeoJSONObject::eUnknown;
 
@@ -1214,9 +1263,9 @@ OGRGeometry* OGRGeoJSONReadGeometry( json_object* poObj )
                   "Unsupported geometry type detected. "
                   "Feature gets NULL geometry assigned." );
     }
-    // If we have a crs object in the current object, let's try and 
+    // If we have a crs object in the current object, let's try and
     // set it too.
-    
+
     json_object* poObjSrs = OGRGeoJSONFindMemberByName( poObj, "crs" );
     if (poGeometry != NULL && poObjSrs != NULL) {
         OGRSpatialReference* poSRS = OGRGeoJSONReadSpatialReference(poObj);
@@ -1236,30 +1285,26 @@ bool OGRGeoJSONReadRawPoint( json_object* poObj, OGRPoint& point )
 {
     CPLAssert( NULL != poObj );
 
-    if( json_type_array == json_object_get_type( poObj ) ) 
+    if( json_type_array == json_object_get_type( poObj ) )
     {
         const int nSize = json_object_array_length( poObj );
-        int iType = 0;
 
-        if( nSize != GeoJSONObject::eMinCoordinateDimension
-            && nSize != GeoJSONObject::eMaxCoordinateDimension )
+        if( nSize < GeoJSONObject::eMinCoordinateDimension )
         {
             CPLDebug( "GeoJSON",
-                      "Invalid coord dimension. Only 2D and 3D supported." );
+                      "Invalid coord dimension. At least 2 dimensions must be present." );
             return false;
         }
 
-        json_object* poObjCoord = NULL;
-
         // Read X coordinate
-        poObjCoord = json_object_array_get_idx( poObj, 0 );
+        json_object* poObjCoord = json_object_array_get_idx( poObj, 0 );
         if (poObjCoord == NULL)
         {
             CPLDebug( "GeoJSON", "Point: got null object." );
             return false;
         }
-        
-        iType = json_object_get_type(poObjCoord);
+
+        int iType = json_object_get_type(poObjCoord);
         if ( (json_type_double != iType) && (json_type_int != iType) )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -1267,12 +1312,12 @@ bool OGRGeoJSONReadRawPoint( json_object* poObj, OGRPoint& point )
                       json_object_to_json_string(poObj) );
             return false;
         }
-        
+
         if (iType == json_type_double)
             point.setX(json_object_get_double( poObjCoord ));
         else
             point.setX(json_object_get_int( poObjCoord ));
-        
+
         // Read Y coordiante
         poObjCoord = json_object_array_get_idx( poObj, 1 );
         if (poObjCoord == NULL)
@@ -1280,7 +1325,7 @@ bool OGRGeoJSONReadRawPoint( json_object* poObj, OGRPoint& point )
             CPLDebug( "GeoJSON", "Point: got null object." );
             return false;
         }
-        
+
         iType = json_object_get_type(poObjCoord);
         if ( (json_type_double != iType) && (json_type_int != iType) )
         {
@@ -1294,11 +1339,11 @@ bool OGRGeoJSONReadRawPoint( json_object* poObj, OGRPoint& point )
             point.setY(json_object_get_double( poObjCoord ));
         else
             point.setY(json_object_get_int( poObjCoord ));
-        
+
         // Read Z coordinate
-        if( nSize == GeoJSONObject::eMaxCoordinateDimension )
+        if( nSize >= GeoJSONObject::eMaxCoordinateDimension )
         {
-            // Don't *expect* mixed-dimension geometries, although the 
+            // Don't *expect* mixed-dimension geometries, although the
             // spec doesn't explicitly forbid this.
             poObjCoord = json_object_array_get_idx( poObj, 2 );
             if (poObjCoord == NULL)
@@ -1306,7 +1351,7 @@ bool OGRGeoJSONReadRawPoint( json_object* poObj, OGRPoint& point )
                 CPLDebug( "GeoJSON", "Point: got null object." );
                 return false;
             }
-            
+
             iType = json_object_get_type(poObjCoord);
             if ( (json_type_double != iType) && (json_type_int != iType) )
             {
@@ -1327,7 +1372,7 @@ bool OGRGeoJSONReadRawPoint( json_object* poObj, OGRPoint& point )
         }
         return true;
     }
-    
+
     return false;
 }
 
@@ -1339,8 +1384,8 @@ OGRPoint* OGRGeoJSONReadPoint( json_object* poObj )
 {
     CPLAssert( NULL != poObj );
 
-    json_object* poObjCoords = NULL;
-    poObjCoords = OGRGeoJSONFindMemberByName( poObj, "coordinates" );
+    json_object* poObjCoords
+        = OGRGeoJSONFindMemberByName( poObj, "coordinates" );
     if( NULL == poObjCoords )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -1367,10 +1412,8 @@ OGRMultiPoint* OGRGeoJSONReadMultiPoint( json_object* poObj )
 {
     CPLAssert( NULL != poObj );
 
-    OGRMultiPoint* poMultiPoint = NULL;
-
-    json_object* poObjPoints = NULL;
-    poObjPoints = OGRGeoJSONFindMemberByName( poObj, "coordinates" );
+    json_object* poObjPoints
+        = OGRGeoJSONFindMemberByName( poObj, "coordinates" );
     if( NULL == poObjPoints )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -1379,6 +1422,7 @@ OGRMultiPoint* OGRGeoJSONReadMultiPoint( json_object* poObj )
         return NULL;
     }
 
+    OGRMultiPoint* poMultiPoint = NULL;
     if( json_type_array == json_object_get_type( poObjPoints ) )
     {
         const int nPoints = json_object_array_length( poObjPoints );
@@ -1413,9 +1457,8 @@ OGRLineString* OGRGeoJSONReadLineString( json_object* poObj , bool bRaw)
 {
     CPLAssert( NULL != poObj );
 
-    OGRLineString* poLine = NULL;
     json_object* poObjPoints = NULL;
-    
+
     if( !bRaw )
     {
         poObjPoints = OGRGeoJSONFindMemberByName( poObj, "coordinates" );
@@ -1432,6 +1475,8 @@ OGRLineString* OGRGeoJSONReadLineString( json_object* poObj , bool bRaw)
         poObjPoints = poObj;
     }
 
+    OGRLineString* poLine = NULL;
+
     if( json_type_array == json_object_get_type( poObjPoints ) )
     {
         const int nPoints = json_object_array_length( poObjPoints );
@@ -1441,8 +1486,8 @@ OGRLineString* OGRGeoJSONReadLineString( json_object* poObj , bool bRaw)
 
         for( int i = 0; i < nPoints; ++i)
         {
-            json_object* poObjCoords = NULL;
-            poObjCoords = json_object_array_get_idx( poObjPoints, i );
+            json_object* poObjCoords
+                = json_object_array_get_idx( poObjPoints, i );
             if (poObjCoords == NULL)
             {
                 delete poLine;
@@ -1450,7 +1495,7 @@ OGRLineString* OGRGeoJSONReadLineString( json_object* poObj , bool bRaw)
                           "LineString: got null object." );
                 return NULL;
             }
-            
+
             OGRPoint pt;
             if( !OGRGeoJSONReadRawPoint( poObjCoords, pt ) )
             {
@@ -1464,7 +1509,7 @@ OGRLineString* OGRGeoJSONReadLineString( json_object* poObj , bool bRaw)
             } else {
                 poLine->setPoint( i, pt.getX(), pt.getY(), pt.getZ() );
             }
-            
+
         }
     }
 
@@ -1479,10 +1524,8 @@ OGRMultiLineString* OGRGeoJSONReadMultiLineString( json_object* poObj )
 {
     CPLAssert( NULL != poObj );
 
-    OGRMultiLineString* poMultiLine = NULL;
-
-    json_object* poObjLines = NULL;
-    poObjLines = OGRGeoJSONFindMemberByName( poObj, "coordinates" );
+    json_object* poObjLines
+        = OGRGeoJSONFindMemberByName( poObj, "coordinates" );
     if( NULL == poObjLines )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -1491,6 +1534,8 @@ OGRMultiLineString* OGRGeoJSONReadMultiLineString( json_object* poObj )
         return NULL;
     }
 
+    OGRMultiLineString* poMultiLine = NULL;
+
     if( json_type_array == json_object_get_type( poObjLines ) )
     {
         const int nLines = json_object_array_length( poObjLines );
@@ -1537,8 +1582,8 @@ OGRLinearRing* OGRGeoJSONReadLinearRing( json_object* poObj )
 
         for( int i = 0; i < nPoints; ++i)
         {
-            json_object* poObjCoords = NULL;
-            poObjCoords = json_object_array_get_idx( poObj, i );
+            json_object* poObjCoords
+                = json_object_array_get_idx( poObj, i );
             if (poObjCoords == NULL)
             {
                 delete poRing;
@@ -1555,7 +1600,7 @@ OGRLinearRing* OGRGeoJSONReadLinearRing( json_object* poObj )
                           "LinearRing: raw point parsing failure." );
                 return NULL;
             }
-            
+
             if( 2 == pt.getCoordinateDimension() )
                 poRing->setPoint( i, pt.getX(), pt.getY());
             else
@@ -1574,10 +1619,8 @@ OGRPolygon* OGRGeoJSONReadPolygon( json_object* poObj , bool bRaw )
 {
     CPLAssert( NULL != poObj );
 
-    OGRPolygon* poPolygon = NULL;
-
     json_object* poObjRings = NULL;
-    
+
     if( !bRaw )
     {
         poObjRings = OGRGeoJSONFindMemberByName( poObj, "coordinates" );
@@ -1593,14 +1636,16 @@ OGRPolygon* OGRGeoJSONReadPolygon( json_object* poObj , bool bRaw )
     {
         poObjRings = poObj;
     }
-    
+
+    OGRPolygon* poPolygon = NULL;
+
     if( json_type_array == json_object_get_type( poObjRings ) )
     {
         const int nRings = json_object_array_length( poObjRings );
         if( nRings > 0 )
         {
-            json_object* poObjPoints = NULL;
-            poObjPoints = json_object_array_get_idx( poObjRings, 0 );
+            json_object* poObjPoints
+                = json_object_array_get_idx( poObjRings, 0 );
             if (poObjPoints == NULL)
             {
                 poPolygon = new OGRPolygon();
@@ -1646,8 +1691,6 @@ OGRMultiPolygon* OGRGeoJSONReadMultiPolygon( json_object* poObj )
 {
     CPLAssert( NULL != poObj );
 
-    OGRMultiPolygon* poMultiPoly = NULL;
-
     json_object* poObjPolys = NULL;
     poObjPolys = OGRGeoJSONFindMemberByName( poObj, "coordinates" );
     if( NULL == poObjPolys )
@@ -1658,6 +1701,8 @@ OGRMultiPolygon* OGRGeoJSONReadMultiPolygon( json_object* poObj )
         return NULL;
     }
 
+    OGRMultiPolygon* poMultiPoly = NULL;
+
     if( json_type_array == json_object_get_type( poObjPolys ) )
     {
         const int nPolys = json_object_array_length( poObjPolys );
@@ -1667,8 +1712,8 @@ OGRMultiPolygon* OGRGeoJSONReadMultiPolygon( json_object* poObj )
         for( int i = 0; i < nPolys; ++i)
         {
 
-            json_object* poObjPoly = NULL;
-            poObjPoly = json_object_array_get_idx( poObjPolys, i );
+            json_object* poObjPoly
+                = json_object_array_get_idx( poObjPolys, i );
             if (poObjPoly == NULL)
             {
                 poMultiPoly->addGeometryDirectly( new OGRPolygon() );
@@ -1694,8 +1739,6 @@ OGRGeometryCollection* OGRGeoJSONReadGeometryCollection( json_object* poObj )
 {
     CPLAssert( NULL != poObj );
 
-    OGRGeometry* poGeometry = NULL;
-    OGRGeometryCollection* poCollection = NULL;
 
     json_object* poObjGeoms = NULL;
     poObjGeoms = OGRGeoJSONFindMemberByName( poObj, "geometries" );
@@ -1707,6 +1750,8 @@ OGRGeometryCollection* OGRGeoJSONReadGeometryCollection( json_object* poObj )
         return NULL;
     }
 
+    OGRGeometryCollection* poCollection = NULL;
+
     if( json_type_array == json_object_get_type( poObjGeoms ) )
     {
         const int nGeoms = json_object_array_length( poObjGeoms );
@@ -1715,17 +1760,18 @@ OGRGeometryCollection* OGRGeoJSONReadGeometryCollection( json_object* poObj )
             poCollection = new OGRGeometryCollection();
         }
 
-        json_object* poObjGeom = NULL;
         for( int i = 0; i < nGeoms; ++i )
         {
-            poObjGeom = json_object_array_get_idx( poObjGeoms, i );
+            json_object* poObjGeom
+                = json_object_array_get_idx( poObjGeoms, i );
             if (poObjGeom == NULL)
             {
                 CPLDebug( "GeoJSON", "Skipping null sub-geometry");
                 continue;
             }
 
-            poGeometry = OGRGeoJSONReadGeometry( poObjGeom );
+            OGRGeometry* poGeometry
+                = OGRGeoJSONReadGeometry( poObjGeom );
             if( NULL != poGeometry )
             {
                 poCollection->addGeometryDirectly( poGeometry );
@@ -1742,40 +1788,76 @@ OGRGeometryCollection* OGRGeoJSONReadGeometryCollection( json_object* poObj )
 
 OGRGeometryH OGR_G_CreateGeometryFromJson( const char* pszJson )
 {
-    VALIDATE_POINTER1( pszJson, "OGR_G_CreateGeometryFromJson", NULL );
+    if( NULL == pszJson )
+    {
+        /* Translation failed */
+        return NULL;
+    }
+
+    json_object *poObj = NULL;
+    if( !OGRJSonParse(pszJson, &poObj) )
+        return NULL;
+
+    OGRGeometry* poGeometry
+        = OGRGeoJSONReadGeometry( poObj );
 
-    if( NULL != pszJson )
+    /* Assign WGS84 if no CRS defined on geometry */
+    if( poGeometry && poGeometry->getSpatialReference() == NULL )
     {
-        json_tokener* jstok = NULL;
-        json_object* poObj = NULL;
+        poGeometry->assignSpatialReference(OGRSpatialReference::GetWGS84SRS());
+    }
 
-        jstok = json_tokener_new();
-        poObj = json_tokener_parse_ex(jstok, pszJson, -1);
-        if( jstok->err != json_tokener_success)
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "GeoJSON parsing error: %s (at offset %d)",
-                      json_tokener_error_desc(jstok->err), jstok->char_offset);
-            json_tokener_free(jstok);
-            return NULL;
-        }
-        json_tokener_free(jstok);
+    /* Release JSON tree. */
+    json_object_put( poObj );
 
-        OGRGeometry* poGeometry = NULL;
-        poGeometry = OGRGeoJSONReadGeometry( poObj );
+    return (OGRGeometryH)poGeometry;
+}
 
-        /* Assign WGS84 if no CRS defined on geometry */
-        if( poGeometry && poGeometry->getSpatialReference() == NULL )
+/************************************************************************/
+/*                       json_ex_get_object_by_path()                   */
+/************************************************************************/
+
+json_object* json_ex_get_object_by_path(json_object* poObj, const char* pszPath )
+{
+    if( poObj == NULL || json_object_get_type(poObj) != json_type_object ||
+        pszPath == NULL || *pszPath == '\0' )
+    {
+        return poObj;
+    }
+    char** papszTokens = CSLTokenizeString2( pszPath, ".", 0 );
+    for( int i = 0; papszTokens[i] != NULL; i++ )
+    {
+        poObj = json_object_object_get(poObj, papszTokens[i]);
+        if( poObj == NULL || json_object_get_type(poObj) != json_type_object )
+            break;
+    }
+    CSLDestroy(papszTokens);
+    return poObj;
+}
+
+/************************************************************************/
+/*                             OGRJSonParse()                           */
+/************************************************************************/
+
+bool OGRJSonParse(const char* pszText, json_object** ppoObj, bool bVerboseError)
+{
+    if( ppoObj == NULL )
+        return false;
+    json_tokener* jstok = json_tokener_new();
+    *ppoObj = json_tokener_parse_ex(jstok, pszText, -1);
+    if( jstok->err != json_tokener_success)
+    {
+        if( bVerboseError )
         {
-            poGeometry->assignSpatialReference(OGRSpatialReference::GetWGS84SRS());
+            CPLError( CE_Failure, CPLE_AppDefined,
+                        "GeoJSON parsing error: %s (at offset %d)",
+                        json_tokener_error_desc(jstok->err), jstok->char_offset);
         }
-        
-        /* Release JSON tree. */
-        json_object_put( poObj );
 
-        return (OGRGeometryH)poGeometry;
+        json_tokener_free(jstok);
+        *ppoObj = NULL;
+        return false;
     }
-
-    /* Translation failed */
-    return NULL;
+    json_tokener_free(jstok);
+    return true;
 }
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.h b/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.h
index d1debd3..2779a3e 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.h
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsonreader.h 29111 2015-05-02 18:06:16Z rouault $
+ * $Id: ogrgeojsonreader.h 32461 2015-12-26 03:46:04Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines GeoJSON reader within OGR OGRGeoJSON Driver.
@@ -31,6 +31,7 @@
 #define OGR_GEOJSONREADER_H_INCLUDED
 
 #include <ogr_core.h>
+#include "cpl_string.h"
 #include "ogrsf_frmts.h"
 #include <json.h> // JSON-C
 
@@ -71,7 +72,7 @@ struct GeoJSONObject
         eFeature,
         eFeatureCollection
     };
-    
+
     enum CoordinateDimension
     {
         eMinCoordinateDimension = 2,
@@ -95,6 +96,8 @@ public:
     void SetPreserveGeometryType( bool bPreserve );
     void SetSkipAttributes( bool bSkip );
     void SetFlattenNestedAttributes( bool bFlatten, char chSeparator );
+    void SetStoreNativeData( bool bStoreNativeData );
+    void SetArrayAsString( bool bArrayAsString );
 
     OGRErr Parse( const char* pszText );
     void ReadLayers( OGRGeoJSONDataSource* poDS );
@@ -112,9 +115,16 @@ private:
     bool bAttributesSkip_;
     bool bFlattenNestedAttributes_;
     char chNestedAttributeSeparator_;
+    bool bStoreNativeData_;
+    bool bArrayAsString_;
 
+    // bFlatten... is a tri-state boolean with -1 being unset.
     int bFlattenGeocouchSpatiallistFormat;
-    bool bFoundId, bFoundRev, bFoundTypeFeature, bIsGeocouchSpatiallistFormat;
+
+    bool bFoundId;
+    bool bFoundRev;
+    bool bFoundTypeFeature;
+    bool bIsGeocouchSpatiallistFormat;
 
     //
     // Copy operations not supported.
@@ -146,7 +156,8 @@ void OGRGeoJSONReaderAddOrUpdateField(OGRFeatureDefn* poDefn,
                                       const char* pszKey,
                                       json_object* poVal,
                                       bool bFlattenNestedAttributes,
-                                      char chNestedAttributeSeparator);
+                                      char chNestedAttributeSeparator,
+                                      bool bArrayAsString = false);
 
 /************************************************************************/
 /*                 GeoJSON Parsing Utilities                            */
@@ -155,6 +166,10 @@ void OGRGeoJSONReaderAddOrUpdateField(OGRFeatureDefn* poDefn,
 json_object* OGRGeoJSONFindMemberByName(json_object* poObj,  const char* pszName );
 GeoJSONObject::Type OGRGeoJSONGetType( json_object* poObj );
 
+json_object* json_ex_get_object_by_path(json_object* poObj, const char* pszPath );
+
+bool OGRJSonParse(const char* pszText, json_object** ppoObj, bool bVerboseError = true);
+
 /************************************************************************/
 /*                 GeoJSON Geometry Translators                         */
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.cpp b/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.cpp
index d0582dc..f719ee4 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsonutils.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrgeojsonutils.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of private utilities used within OGR GeoJSON Driver.
@@ -67,7 +67,7 @@ int GeoJSONIsObject( const char* pszText )
         return FALSE;
 
     return ((strstr(pszText, "\"type\"") != NULL && strstr(pszText, "\"coordinates\"") != NULL)
-        || (strstr(pszText, "\"type\"") != NULL && strstr(pszText, "\"Topology\"") != NULL) 
+        || (strstr(pszText, "\"type\"") != NULL && strstr(pszText, "\"Topology\"") != NULL)
         || strstr(pszText, "\"FeatureCollection\"") != NULL
         || strstr(pszText, "\"Feature\"") != NULL
         || (strstr(pszText, "\"geometryType\"") != NULL && strstr(pszText, "\"esriGeometry") != NULL));
@@ -78,25 +78,25 @@ int GeoJSONIsObject( const char* pszText )
 /************************************************************************/
 
 static
-int GeoJSONFileIsObject( GDALOpenInfo* poOpenInfo ) 
-{ 
-    // by default read first 6000 bytes 
-    // 6000 was chosen as enough bytes to  
-    // enable all current tests to pass 
+bool GeoJSONFileIsObject( GDALOpenInfo* poOpenInfo )
+{
+    // by default read first 6000 bytes
+    // 6000 was chosen as enough bytes to
+    // enable all current tests to pass
 
     if( poOpenInfo->fpL == NULL ||
-        !poOpenInfo->TryToIngest(6000) ) 
-    { 
-        return FALSE; 
-    } 
+        !poOpenInfo->TryToIngest(6000) )
+    {
+        return false;
+    }
 
     if( !GeoJSONIsObject((const char*)poOpenInfo->pabyHeader) )
     {
-        return FALSE;
+        return false;
     }
 
-    return TRUE; 
-} 
+    return true;
+}
 
 /************************************************************************/
 /*                           GeoJSONGetSourceType()                     */
@@ -121,7 +121,7 @@ GeoJSONSourceType GeoJSONGetSourceType( GDALOpenInfo* poOpenInfo )
     else if( EQUAL( CPLGetExtension( poOpenInfo->pszFilename ), "geojson" )
              || EQUAL( CPLGetExtension( poOpenInfo->pszFilename ), "json" )
              || EQUAL( CPLGetExtension( poOpenInfo->pszFilename ), "topojson" )
-             || ((EQUALN( poOpenInfo->pszFilename, "/vsigzip/", 9) || EQUALN( poOpenInfo->pszFilename, "/vsizip/", 8)) &&
+             || ((STARTS_WITH_CI(poOpenInfo->pszFilename, "/vsigzip/") || STARTS_WITH_CI(poOpenInfo->pszFilename, "/vsizip/")) &&
                  (strstr( poOpenInfo->pszFilename, ".json") || strstr( poOpenInfo->pszFilename, ".JSON") ||
                   strstr( poOpenInfo->pszFilename, ".geojson") || strstr( poOpenInfo->pszFilename, ".GEOJSON")) ))
     {
@@ -148,11 +148,11 @@ GeoJSONProtocolType GeoJSONGetProtocolType( const char* pszSource )
 {
     GeoJSONProtocolType ptclType = eGeoJSONProtocolUnknown;
 
-    if( EQUALN( pszSource, "http:", 5 ) )
+    if( STARTS_WITH_CI(pszSource, "http:") )
         ptclType = eGeoJSONProtocolHTTP;
-    else if( EQUALN( pszSource, "https:", 6 ) )
+    else if( STARTS_WITH_CI(pszSource, "https:") )
         ptclType = eGeoJSONProtocolHTTPS;
-    else if( EQUALN( pszSource, "ftp:", 4 ) )
+    else if( STARTS_WITH_CI(pszSource, "ftp:") )
         ptclType = eGeoJSONProtocolFTP;
 
     return ptclType;
@@ -166,7 +166,8 @@ GeoJSONProtocolType GeoJSONGetProtocolType( const char* pszSource )
 #define MY_INT64_MIN ((((GIntBig)0x80000000) << 32))
 
 OGRFieldType GeoJSONPropertyToFieldType( json_object* poObject,
-                                         OGRFieldSubType& eSubType )
+                                         OGRFieldSubType& eSubType,
+                                         bool bArrayAsString )
 {
     eSubType = OFSTNone;
 
@@ -184,14 +185,14 @@ OGRFieldType GeoJSONPropertyToFieldType( json_object* poObject,
     else if( json_type_int == type )
     {
         GIntBig nVal = json_object_get_int64(poObject);
-        if( nVal != (GIntBig)(int) nVal )
+        if( !CPL_INT64_FITS_ON_INT32(nVal) )
         {
             if( nVal == MY_INT64_MIN || nVal == MY_INT64_MAX )
             {
-                static int bWarned = FALSE;
+                static bool bWarned = false;
                 if( !bWarned )
                 {
-                    bWarned = TRUE;
+                    bWarned = true;
                     CPLError(CE_Warning, CPLE_AppDefined,
                              "Integer values probably ranging out of 64bit integer range "
                              "have been found. Will be clamped to INT64_MIN/INT64_MAX");
@@ -208,6 +209,8 @@ OGRFieldType GeoJSONPropertyToFieldType( json_object* poObject,
         return OFTString;
     else if( json_type_array == type )
     {
+        if( bArrayAsString )
+            return OFTString;
         int nSize = json_object_array_length(poObject);
         if (nSize == 0)
             return OFTStringList; /* we don't know, so let's assume it's a string list */
@@ -228,7 +231,7 @@ OGRFieldType GeoJSONPropertyToFieldType( json_object* poObject,
                          type == json_type_int)
                 {
                     GIntBig nVal = json_object_get_int64(poRow);
-                    if( nVal != (GIntBig)(int)nVal )
+                    if( !CPL_INT64_FITS_ON_INT32(nVal) )
                         eType = OFTInteger64List;
                 }
                 else if (type != json_type_int &&
@@ -255,20 +258,21 @@ OGRFieldType GeoJSONStringPropertyToFieldType( json_object* poObject )
 
     OGRField sWrkField;
     CPLPushErrorHandler(CPLQuietErrorHandler);
-    int bSuccess = OGRParseDate( pszStr, &sWrkField, 0 );
+    const bool bSuccess = CPL_TO_BOOL(OGRParseDate( pszStr, &sWrkField, 0 ));
     CPLPopErrorHandler();
     CPLErrorReset();
     if( bSuccess )
     {
-        int bHasDate = strchr( pszStr, '/' ) != NULL ||
-                        strchr( pszStr, '-' ) != NULL;
-        int bHasTime = strchr( pszStr, ':' ) != NULL;
+        const bool bHasDate = strchr( pszStr, '/' ) != NULL ||
+            strchr( pszStr, '-' ) != NULL;
+        const bool  bHasTime = strchr( pszStr, ':' ) != NULL;
         if( bHasDate && bHasTime )
             return OFTDateTime;
         else if( bHasDate )
             return OFTDate;
         else
             return OFTTime;
+        // TODO: What if both are false?
     }
     return OFTString;
 }
@@ -280,8 +284,8 @@ OGRFieldType GeoJSONStringPropertyToFieldType( json_object* poObject )
 const char* OGRGeoJSONGetGeometryName( OGRGeometry const* poGeometry )
 {
     CPLAssert( NULL != poGeometry );
-    
-    OGRwkbGeometryType eType = poGeometry->getGeometryType();
+
+    const OGRwkbGeometryType eType = poGeometry->getGeometryType();
 
     if( wkbPoint == eType || wkbPoint25D == eType )
         return "Point";
@@ -297,7 +301,6 @@ const char* OGRGeoJSONGetGeometryName( OGRGeometry const* poGeometry )
         return "MultiPolygon";
     else if( wkbGeometryCollection == eType || wkbGeometryCollection25D == eType )
         return "GeometryCollection";
-    else
-        return "Unknown";
-}
 
+    return "Unknown";
+}
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.h b/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.h
index 0631ddb..8336bb5 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.h
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsonutils.h 28009 2014-11-26 12:50:04Z rouault $
+ * $Id: ogrgeojsonutils.h 32181 2015-12-15 10:41:07Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private utilities within OGR OGRGeoJSON Driver.
@@ -75,7 +75,8 @@ int GeoJSONIsObject( const char* pszText );
 /************************************************************************/
 
 OGRFieldType GeoJSONPropertyToFieldType( json_object* poObject,
-                                         OGRFieldSubType& eSubType );
+                                         OGRFieldSubType& eSubType,
+                                         bool bArrayAsString = false );
 
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonwritelayer.cpp b/ogr/ogrsf_frmts/geojson/ogrgeojsonwritelayer.cpp
index 8405d65..ba47ac2 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonwritelayer.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonwritelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsonwritelayer.cpp 32121 2015-12-11 10:25:38Z rouault $
+ * $Id: ogrgeojsonwritelayer.cpp 32981 2016-01-14 15:06:42Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of OGRGeoJSONWriteLayer class (OGR GeoJSON Driver).
@@ -40,19 +40,23 @@
 /************************************************************************/
 
 OGRGeoJSONWriteLayer::OGRGeoJSONWriteLayer( const char* pszName,
-                                  OGRwkbGeometryType eGType,
-                                  char** papszOptions,
-                                  OGRGeoJSONDataSource* poDS )
+                                            OGRwkbGeometryType eGType,
+                                            char** papszOptions,
+                                            bool bWriteFC_BBOXIn,
+                                           OGRGeoJSONDataSource* poDS )
     : poDS_( poDS ), poFeatureDefn_(new OGRFeatureDefn( pszName ) ), nOutCounter_( 0 )
 {
-    bWriteBBOX = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "WRITE_BBOX", "FALSE"));
-    bBBOX3D = FALSE;
+    bWriteBBOX = CPLTestBool(CSLFetchNameValueDef(
+        papszOptions, "WRITE_BBOX", "FALSE"));
+    bBBOX3D = false;
+    bWriteFC_BBOX = bWriteFC_BBOXIn;
 
     poFeatureDefn_->Reference();
     poFeatureDefn_->SetGeomType( eGType );
     SetDescription( poFeatureDefn_->GetName() );
 
-    nCoordPrecision = atoi(CSLFetchNameValueDef(papszOptions, "COORDINATE_PRECISION", "-1"));
+    nCoordPrecision_ = atoi(CSLFetchNameValueDef(papszOptions, "COORDINATE_PRECISION", "-1"));
+    nSignificantFigures_ = atoi(CSLFetchNameValueDef(papszOptions, "SIGNIFICANT_FIGURES", "-1"));
 }
 
 /************************************************************************/
@@ -65,7 +69,7 @@ OGRGeoJSONWriteLayer::~OGRGeoJSONWriteLayer()
 
     VSIFPrintfL( fp, "\n]" );
 
-    if( bWriteBBOX && sEnvelopeLayer.IsInit() )
+    if( bWriteFC_BBOX && sEnvelopeLayer.IsInit() )
     {
         CPLString osBBOX = "[ ";
         osBBOX += CPLSPrintf("%.15g, ", sEnvelopeLayer.MinX);
@@ -112,7 +116,8 @@ OGRErr OGRGeoJSONWriteLayer::ICreateFeature( OGRFeature* poFeature )
         return OGRERR_INVALID_HANDLE;
     }
 
-    json_object* poObj = OGRGeoJSONWriteFeature( poFeature, bWriteBBOX, nCoordPrecision );
+    json_object* poObj = OGRGeoJSONWriteFeature( poFeature, bWriteBBOX,
+                                                 nCoordPrecision_, nSignificantFigures_ );
     CPLAssert( NULL != poObj );
 
     if( nOutCounter_ > 0 )
@@ -127,13 +132,13 @@ OGRErr OGRGeoJSONWriteLayer::ICreateFeature( OGRFeature* poFeature )
     ++nOutCounter_;
 
     OGRGeometry* poGeometry = poFeature->GetGeometryRef();
-    if ( bWriteBBOX && !poGeometry->IsEmpty() )
+    if ( (bWriteBBOX || bWriteFC_BBOX) && !poGeometry->IsEmpty() )
     {
         OGREnvelope3D sEnvelope;
         poGeometry->getEnvelope(&sEnvelope);
 
         if( poGeometry->getCoordinateDimension() == 3 )
-            bBBOX3D = TRUE;
+            bBBOX3D = true;
 
         sEnvelopeLayer.Merge(sEnvelope);
     }
@@ -158,7 +163,7 @@ OGRErr OGRGeoJSONWriteLayer::CreateField(OGRFieldDefn* poField, int bApproxOK)
         {
             CPLDebug( "GeoJSON", "Field '%s' already present in schema",
                       poField->GetNameRef() );
-            
+
             // TODO - mloskot: Is this return code correct?
             return OGRERR_NONE;
         }
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.cpp b/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.cpp
index 0e6d364..b0a796a 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsonwriter.cpp 28382 2015-01-30 15:29:41Z rouault $
+ * $Id: ogrgeojsonwriter.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of GeoJSON writer utilities (OGR GeoJSON Driver).
@@ -30,17 +30,248 @@
 #include "ogrgeojsonwriter.h"
 #include "ogrgeojsonutils.h"
 #include "ogr_geojson.h"
+#include "ogrgeojsonreader.h"
 #include <json.h> // JSON-C
 #include <json_object_private.h>
 #include <printbuf.h>
 #include <ogr_api.h>
 #include <ogr_p.h>
 
+
+static json_object* json_object_new_coord(double dfVal, int nCoordPrecision, int nSignificantFigures)
+{
+    // If coordinate precision is specified, or significant figures is not
+    // then use the '%f' formatting
+    if( nCoordPrecision >= 0 || nSignificantFigures < 0 )
+        return json_object_new_double_with_precision(dfVal, nCoordPrecision);
+    return json_object_new_double_with_significant_figures(dfVal, nSignificantFigures);
+}
+
+/************************************************************************/
+/*                     OGRGeoJSONIsPatchablePosition()                  */
+/************************************************************************/
+
+static bool OGRGeoJSONIsPatchablePosition( json_object* poJSonCoordinates,
+                                           json_object* poNativeCoordinates )
+{
+    return json_object_get_type(poJSonCoordinates) == json_type_array &&
+           json_object_get_type(poNativeCoordinates) == json_type_array &&
+           json_object_array_length(poJSonCoordinates) == 3 &&
+           json_object_array_length(poNativeCoordinates) >= 4 &&
+           json_object_get_type(
+            json_object_array_get_idx(poJSonCoordinates, 0)) != json_type_array &&
+           json_object_get_type(
+            json_object_array_get_idx(poNativeCoordinates, 0)) != json_type_array;
+}
+
+/************************************************************************/
+/*                       OGRGeoJSONPatchPosition()                      */
+/************************************************************************/
+
+static void OGRGeoJSONPatchPosition( json_object* poJSonCoordinates,
+                                     json_object* poNativeCoordinates )
+{
+    int nLength = json_object_array_length(poNativeCoordinates);
+    for(int i=3; i<nLength;i++)
+    {
+        json_object_array_add(poJSonCoordinates,
+            json_object_get(
+                json_object_array_get_idx(poNativeCoordinates, i)));
+    }
+}
+
+/************************************************************************/
+/*                      OGRGeoJSONIsPatchableArray()                    */
+/************************************************************************/
+
+static bool OGRGeoJSONIsPatchableArray( json_object* poJSonArray,
+                                        json_object* poNativeArray,
+                                        int nDepth,
+                                        bool bLightCheck )
+{
+    if( nDepth == 0 )
+        return OGRGeoJSONIsPatchablePosition(poJSonArray, poNativeArray);
+
+    int nLength;
+    if( json_object_get_type(poJSonArray) == json_type_array &&
+        json_object_get_type(poNativeArray) == json_type_array &&
+        (nLength = json_object_array_length(poJSonArray)) ==
+                            json_object_array_length(poNativeArray) )
+    {
+        for( int i=0; i < nLength; i++ )
+        {
+            json_object* poJSonChild =
+                json_object_array_get_idx(poJSonArray, i);
+            json_object* poNativeChild =
+                json_object_array_get_idx(poNativeArray, i);
+            if( !OGRGeoJSONIsPatchableArray(poJSonChild, poNativeChild,
+                                            nDepth - 1, bLightCheck) )
+            {
+                return false;
+            }
+            if( bLightCheck )
+                break;
+        }
+        return true;
+    }
+    return false;
+}
+
+/************************************************************************/
+/*                        OGRGeoJSONPatchArray()                        */
+/************************************************************************/
+
+static void OGRGeoJSONPatchArray( json_object* poJSonArray,
+                                  json_object* poNativeArray,
+                                  int nDepth )
+{
+    if( nDepth == 0 )
+    {
+        OGRGeoJSONPatchPosition(poJSonArray, poNativeArray);
+        return;
+    }
+    int nLength = json_object_array_length(poJSonArray);
+    for(int i=0; i<nLength;i++)
+    {
+        json_object* poJSonChild = json_object_array_get_idx(poJSonArray, i);
+        json_object* poNativeChild = json_object_array_get_idx(poNativeArray, i);
+        OGRGeoJSONPatchArray(poJSonChild, poNativeChild,nDepth-1);
+    }
+}
+
+/************************************************************************/
+/*                        OGRGeoJSONIsPatchableGeometry()                */
+/************************************************************************/
+
+static bool OGRGeoJSONIsPatchableGeometry( json_object* poJSonGeometry,
+                                           json_object* poNativeGeometry )
+{
+    if( json_object_get_type(poJSonGeometry) != json_type_object ||
+        json_object_get_type(poNativeGeometry) != json_type_object )
+    {
+        return false;
+    }
+
+    json_object_iter it;
+    it.key = NULL;
+    it.val = NULL;
+    it.entry = NULL;
+    json_object_object_foreachC(poNativeGeometry, it)
+    {
+        if( strcmp(it.key, "coordinates") == 0 )
+        {
+            json_object* poJSonCoordinates =
+                    json_object_object_get(poJSonGeometry, "coordinates");
+            json_object* poNativeCoordinates = it.val;
+            // 0 = Point
+            // 1 = LineString or MultiPoint
+            // 2 = MultiLineString or Polygon
+            // 3 = MultiPolygon
+            for(int i=0;i<=3;i++)
+            {
+                if( OGRGeoJSONIsPatchableArray(poJSonCoordinates,
+                                               poNativeCoordinates, i, false) )
+                {
+                    return true;
+                }
+            }
+            return false;
+        }
+        if( strcmp(it.key, "geometries") == 0 )
+        {
+            json_object* poJSonGeometries =
+                    json_object_object_get(poJSonGeometry, "geometries");
+            json_object* poNativeGeometries = it.val;
+            int nLength;
+            if( json_object_get_type(poJSonGeometries) == json_type_array &&
+                json_object_get_type(poNativeGeometries) == json_type_array &&
+                (nLength = json_object_array_length(poJSonGeometries)) ==
+                    json_object_array_length(poNativeGeometries) )
+            {
+                for( int i=0; i < nLength; i++ )
+                {
+                    json_object* poJSonChild =
+                        json_object_array_get_idx(poJSonGeometries, i);
+                    json_object* poNativeChild =
+                        json_object_array_get_idx(poNativeGeometries, i);
+                    if( !OGRGeoJSONIsPatchableGeometry(poJSonChild, poNativeChild) )
+                    {
+                        return false;
+                    }
+                }
+                return true;
+            }
+            return false;
+        }
+    }
+    return false;
+}
+
+/************************************************************************/
+/*                        OGRGeoJSONPatchGeometry()                     */
+/************************************************************************/
+
+static void OGRGeoJSONPatchGeometry( json_object* poJSonGeometry,
+                                     json_object* poNativeGeometry )
+{
+    json_object_iter it;
+    it.key = NULL;
+    it.val = NULL;
+    it.entry = NULL;
+    json_object_object_foreachC(poNativeGeometry, it)
+    {
+        if( strcmp(it.key, "type") == 0 ||
+            strcmp(it.key, "bbox") == 0 )
+        {
+            continue;
+        }
+        if( strcmp(it.key, "coordinates") == 0 )
+        {
+            json_object* poJSonCoordinates =
+                json_object_object_get(poJSonGeometry, "coordinates");
+            json_object* poNativeCoordinates = it.val;
+            for(int i=0;i<=3;i++)
+            {
+                if( OGRGeoJSONIsPatchableArray(poJSonCoordinates,
+                                               poNativeCoordinates, i, true) )
+                {
+                    OGRGeoJSONPatchArray(poJSonCoordinates,
+                                         poNativeCoordinates, i);
+                    break;
+                }
+            }
+
+            continue;
+        }
+        if( strcmp(it.key, "geometries") == 0 )
+        {
+            json_object* poJSonGeometries =
+                json_object_object_get(poJSonGeometry, "geometries");
+            json_object* poNativeGeometries = it.val;
+            int nLength = json_object_array_length(poJSonGeometries);
+            for( int i=0; i < nLength; i++ )
+            {
+                json_object* poJSonChild =
+                    json_object_array_get_idx(poJSonGeometries, i);
+                json_object* poNativeChild =
+                    json_object_array_get_idx(poNativeGeometries, i);
+                OGRGeoJSONPatchGeometry(poJSonChild, poNativeChild);
+            }
+
+            continue;
+        }
+
+        json_object_object_add( poJSonGeometry, it.key,
+                                json_object_get(it.val) );
+    }
+}
+
 /************************************************************************/
 /*                           OGRGeoJSONWriteFeature                     */
 /************************************************************************/
 
-json_object* OGRGeoJSONWriteFeature( OGRFeature* poFeature, int bWriteBBOX, int nCoordPrecision )
+json_object* OGRGeoJSONWriteFeature( OGRFeature* poFeature, int bWriteBBOX,
+                                     int nCoordPrecision, int nSignificantFigures )
 {
     CPLAssert( NULL != poFeature );
 
@@ -51,9 +282,53 @@ json_object* OGRGeoJSONWriteFeature( OGRFeature* poFeature, int bWriteBBOX, int
                             json_object_new_string("Feature") );
 
 /* -------------------------------------------------------------------- */
+/*      Write native JSon data.                                         */
+/* -------------------------------------------------------------------- */
+    bool bIdAlreadyWritten = false;
+    const char* pszNativeMediaType = poFeature->GetNativeMediaType();
+    json_object* poNativeGeom = NULL;
+    if( pszNativeMediaType && EQUAL(pszNativeMediaType, "application/vnd.geo+json") )
+    {
+        const char* pszNativeData = poFeature->GetNativeData();
+        json_object* poNativeJSon = NULL;
+        if( pszNativeData && OGRJSonParse(pszNativeData, &poNativeJSon) &&
+            json_object_get_type(poNativeJSon) == json_type_object )
+        {
+            json_object_iter it;
+            it.key = NULL;
+            it.val = NULL;
+            it.entry = NULL;
+            CPLString osNativeData;
+            json_object_object_foreachC(poNativeJSon, it)
+            {
+                if( strcmp(it.key, "type") == 0 ||
+                    strcmp(it.key, "properties") == 0 )
+                {
+                    continue;
+                }
+                if( strcmp(it.key, "bbox") == 0 )
+                {
+                    bWriteBBOX = true;
+                    continue;
+                }
+                if( strcmp(it.key, "geometry") == 0 )
+                {
+                    poNativeGeom = json_object_get(it.val);
+                    continue;
+                }
+                if( strcmp(it.key, "id") == 0 )
+                    bIdAlreadyWritten = true;
+                json_object_object_add( poObj, it.key,
+                                        json_object_get(it.val) );
+            }
+            json_object_put(poNativeJSon);
+        }
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Write FID if available                                          */
 /* -------------------------------------------------------------------- */
-    if ( poFeature->GetFID() != OGRNullFID )
+    if ( poFeature->GetFID() != OGRNullFID && !bIdAlreadyWritten )
     {
         json_object_object_add( poObj, "id",
                                 json_object_new_int64(poFeature->GetFID()) );
@@ -62,9 +337,8 @@ json_object* OGRGeoJSONWriteFeature( OGRFeature* poFeature, int bWriteBBOX, int
 /* -------------------------------------------------------------------- */
 /*      Write feature attributes to GeoJSON "properties" object.        */
 /* -------------------------------------------------------------------- */
-    json_object* poObjProps = NULL;
-
-    poObjProps = OGRGeoJSONWriteAttributes( poFeature );
+    json_object* poObjProps
+        = OGRGeoJSONWriteAttributes( poFeature, nSignificantFigures );
     json_object_object_add( poObj, "properties", poObjProps );
 
 /* -------------------------------------------------------------------- */
@@ -76,7 +350,7 @@ json_object* OGRGeoJSONWriteFeature( OGRFeature* poFeature, int bWriteBBOX, int
     OGRGeometry* poGeometry = poFeature->GetGeometryRef();
     if ( NULL != poGeometry )
     {
-        poObjGeom = OGRGeoJSONWriteGeometry( poGeometry, nCoordPrecision );
+        poObjGeom = OGRGeoJSONWriteGeometry( poGeometry, nCoordPrecision, nSignificantFigures );
 
         if ( bWriteBBOX && !poGeometry->IsEmpty() )
         {
@@ -85,26 +359,34 @@ json_object* OGRGeoJSONWriteFeature( OGRFeature* poFeature, int bWriteBBOX, int
 
             json_object* poObjBBOX = json_object_new_array();
             json_object_array_add(poObjBBOX,
-                            json_object_new_double_with_precision(sEnvelope.MinX, nCoordPrecision));
+                            json_object_new_coord(sEnvelope.MinX, nCoordPrecision, nSignificantFigures));
             json_object_array_add(poObjBBOX,
-                            json_object_new_double_with_precision(sEnvelope.MinY, nCoordPrecision));
+                            json_object_new_coord(sEnvelope.MinY, nCoordPrecision, nSignificantFigures));
             if (poGeometry->getCoordinateDimension() == 3)
                 json_object_array_add(poObjBBOX,
-                            json_object_new_double_with_precision(sEnvelope.MinZ, nCoordPrecision));
+                            json_object_new_coord(sEnvelope.MinZ, nCoordPrecision, nSignificantFigures));
             json_object_array_add(poObjBBOX,
-                            json_object_new_double_with_precision(sEnvelope.MaxX, nCoordPrecision));
+                            json_object_new_coord(sEnvelope.MaxX, nCoordPrecision, nSignificantFigures));
             json_object_array_add(poObjBBOX,
-                            json_object_new_double_with_precision(sEnvelope.MaxY, nCoordPrecision));
+                            json_object_new_coord(sEnvelope.MaxY, nCoordPrecision, nSignificantFigures));
             if (poGeometry->getCoordinateDimension() == 3)
                 json_object_array_add(poObjBBOX,
-                            json_object_new_double_with_precision(sEnvelope.MaxZ, nCoordPrecision));
+                            json_object_new_coord(sEnvelope.MaxZ, nCoordPrecision, nSignificantFigures));
 
             json_object_object_add( poObj, "bbox", poObjBBOX );
         }
+
+        if( OGRGeoJSONIsPatchableGeometry( poObjGeom, poNativeGeom ) )
+        {
+            OGRGeoJSONPatchGeometry( poObjGeom, poNativeGeom );
+        }
     }
-    
+
     json_object_object_add( poObj, "geometry", poObjGeom );
 
+    if( poNativeGeom != NULL )
+        json_object_put(poNativeGeom);
+
     return poObj;
 }
 
@@ -112,7 +394,7 @@ json_object* OGRGeoJSONWriteFeature( OGRFeature* poFeature, int bWriteBBOX, int
 /*                           OGRGeoJSONWriteGeometry                    */
 /************************************************************************/
 
-json_object* OGRGeoJSONWriteAttributes( OGRFeature* poFeature )
+json_object* OGRGeoJSONWriteAttributes( OGRFeature* poFeature, int nSignificantFigures )
 {
     CPLAssert( NULL != poFeature );
 
@@ -122,12 +404,13 @@ json_object* OGRGeoJSONWriteAttributes( OGRFeature* poFeature )
     OGRFeatureDefn* poDefn = poFeature->GetDefnRef();
     for( int nField = 0; nField < poDefn->GetFieldCount(); ++nField )
     {
-        json_object* poObjProp;
         OGRFieldDefn* poFieldDefn = poDefn->GetFieldDefn( nField );
         CPLAssert( NULL != poFieldDefn );
         OGRFieldType eType = poFieldDefn->GetType();
         OGRFieldSubType eSubType = poFieldDefn->GetSubType();
 
+        json_object* poObjProp;
+
         if( !poFeature->IsFieldSet(nField) )
         {
             poObjProp = NULL;
@@ -135,30 +418,38 @@ json_object* OGRGeoJSONWriteAttributes( OGRFeature* poFeature )
         else if( OFTInteger == eType )
         {
             if( eSubType == OFSTBoolean )
-                poObjProp = json_object_new_boolean( 
+                poObjProp = json_object_new_boolean(
                     poFeature->GetFieldAsInteger( nField ) );
             else
-                poObjProp = json_object_new_int( 
+                poObjProp = json_object_new_int(
                     poFeature->GetFieldAsInteger( nField ) );
         }
         else if( OFTInteger64 == eType )
         {
             if( eSubType == OFSTBoolean )
-                poObjProp = json_object_new_boolean( 
+                poObjProp = json_object_new_boolean(
                     (json_bool)poFeature->GetFieldAsInteger64( nField ) );
             else
-                poObjProp = json_object_new_int64( 
+                poObjProp = json_object_new_int64(
                     poFeature->GetFieldAsInteger64( nField ) );
         }
         else if( OFTReal == eType )
         {
-            poObjProp = json_object_new_double( 
-                poFeature->GetFieldAsDouble(nField) );
+            poObjProp = json_object_new_double_with_significant_figures(
+                poFeature->GetFieldAsDouble(nField), nSignificantFigures );
         }
         else if( OFTString == eType )
         {
-            poObjProp = json_object_new_string( 
-                poFeature->GetFieldAsString(nField) );
+            const char* pszStr = poFeature->GetFieldAsString(nField);
+            const size_t nLen = strlen(pszStr);
+            poObjProp = NULL;
+            if( (pszStr[0] == '{' && pszStr[nLen-1] == '}') ||
+                (pszStr[0] == '[' && pszStr[nLen-1] == ']') )
+            {
+                OGRJSonParse(pszStr, &poObjProp, false);
+            }
+            if( poObjProp == NULL )
+                poObjProp = json_object_new_string( pszStr );
         }
         else if( OFTIntegerList == eType )
         {
@@ -198,7 +489,7 @@ json_object* OGRGeoJSONWriteAttributes( OGRFeature* poFeature )
             for(int i=0;i<nSize;i++)
             {
                 json_object_array_add(poObjProp,
-                            json_object_new_double(padfList[i]));
+                            json_object_new_double_with_significant_figures(padfList[i], nSignificantFigures));
             }
         }
         else if( OFTStringList == eType )
@@ -213,7 +504,7 @@ json_object* OGRGeoJSONWriteAttributes( OGRFeature* poFeature )
         }
         else
         {
-            poObjProp = json_object_new_string( 
+            poObjProp = json_object_new_string(
                  poFeature->GetFieldAsString(nField) );
         }
 
@@ -229,17 +520,28 @@ json_object* OGRGeoJSONWriteAttributes( OGRFeature* poFeature )
 /*                           OGRGeoJSONWriteGeometry                    */
 /************************************************************************/
 
-json_object* OGRGeoJSONWriteGeometry( OGRGeometry* poGeometry, int nCoordPrecision )
+json_object* OGRGeoJSONWriteGeometry( OGRGeometry* poGeometry,
+                                      int nCoordPrecision,
+                                      int nSignificantFigures )
 {
     CPLAssert( NULL != poGeometry );
 
+    OGRwkbGeometryType eType = poGeometry->getGeometryType();
+    /* For point empty, return a null geometry. For other empty geometry types, */
+    /* we will generate an empty coordinate array, which is propably also */
+    /* borderline. */
+    if( (wkbPoint == eType || wkbPoint25D == eType) && poGeometry->IsEmpty() )
+    {
+        return NULL;
+    }
+
     json_object* poObj = json_object_new_object();
     CPLAssert( NULL != poObj );
 
 /* -------------------------------------------------------------------- */
 /*      Build "type" member of GeoJSOn "geometry" object.               */
 /* -------------------------------------------------------------------- */
-    
+
     // XXX - mloskot: workaround hack for pure JSON-C API design.
     char* pszName = const_cast<char*>(OGRGeoJSONGetGeometryName( poGeometry ));
     json_object_object_add( poObj, "type", json_object_new_string(pszName) );
@@ -249,26 +551,25 @@ json_object* OGRGeoJSONWriteGeometry( OGRGeometry* poGeometry, int nCoordPrecisi
 /* -------------------------------------------------------------------- */
     json_object* poObjGeom = NULL;
 
-    OGRwkbGeometryType eType = poGeometry->getGeometryType();
     if( wkbGeometryCollection == eType || wkbGeometryCollection25D == eType )
     {
-        poObjGeom = OGRGeoJSONWriteGeometryCollection( static_cast<OGRGeometryCollection*>(poGeometry), nCoordPrecision );
+        poObjGeom = OGRGeoJSONWriteGeometryCollection( static_cast<OGRGeometryCollection*>(poGeometry), nCoordPrecision, nSignificantFigures );
         json_object_object_add( poObj, "geometries", poObjGeom);
     }
     else
     {
         if( wkbPoint == eType || wkbPoint25D == eType )
-            poObjGeom = OGRGeoJSONWritePoint( static_cast<OGRPoint*>(poGeometry), nCoordPrecision );
+            poObjGeom = OGRGeoJSONWritePoint( static_cast<OGRPoint*>(poGeometry), nCoordPrecision, nSignificantFigures );
         else if( wkbLineString == eType || wkbLineString25D == eType )
-            poObjGeom = OGRGeoJSONWriteLineString( static_cast<OGRLineString*>(poGeometry), nCoordPrecision );
+            poObjGeom = OGRGeoJSONWriteLineString( static_cast<OGRLineString*>(poGeometry), nCoordPrecision, nSignificantFigures );
         else if( wkbPolygon == eType || wkbPolygon25D == eType )
-            poObjGeom = OGRGeoJSONWritePolygon( static_cast<OGRPolygon*>(poGeometry), nCoordPrecision );
+            poObjGeom = OGRGeoJSONWritePolygon( static_cast<OGRPolygon*>(poGeometry), nCoordPrecision, nSignificantFigures );
         else if( wkbMultiPoint == eType || wkbMultiPoint25D == eType )
-            poObjGeom = OGRGeoJSONWriteMultiPoint( static_cast<OGRMultiPoint*>(poGeometry), nCoordPrecision );
+            poObjGeom = OGRGeoJSONWriteMultiPoint( static_cast<OGRMultiPoint*>(poGeometry), nCoordPrecision, nSignificantFigures );
         else if( wkbMultiLineString == eType || wkbMultiLineString25D == eType )
-            poObjGeom = OGRGeoJSONWriteMultiLineString( static_cast<OGRMultiLineString*>(poGeometry), nCoordPrecision );
+            poObjGeom = OGRGeoJSONWriteMultiLineString( static_cast<OGRMultiLineString*>(poGeometry), nCoordPrecision, nSignificantFigures );
         else if( wkbMultiPolygon == eType || wkbMultiPolygon25D == eType )
-            poObjGeom = OGRGeoJSONWriteMultiPolygon( static_cast<OGRMultiPolygon*>(poGeometry), nCoordPrecision );
+            poObjGeom = OGRGeoJSONWriteMultiPolygon( static_cast<OGRMultiPolygon*>(poGeometry), nCoordPrecision, nSignificantFigures );
         else
         {
             CPLDebug( "GeoJSON",
@@ -286,7 +587,7 @@ json_object* OGRGeoJSONWriteGeometry( OGRGeometry* poGeometry, int nCoordPrecisi
 /*                           OGRGeoJSONWritePoint                       */
 /************************************************************************/
 
-json_object* OGRGeoJSONWritePoint( OGRPoint* poPoint, int nCoordPrecision )
+json_object* OGRGeoJSONWritePoint( OGRPoint* poPoint, int nCoordPrecision, int nSignificantFigures )
 {
     CPLAssert( NULL != poPoint );
 
@@ -298,17 +599,13 @@ json_object* OGRGeoJSONWritePoint( OGRPoint* poPoint, int nCoordPrecision )
         poObj = OGRGeoJSONWriteCoords( poPoint->getX(),
                                        poPoint->getY(),
                                        poPoint->getZ(),
-                                       nCoordPrecision );
+                                       nCoordPrecision, nSignificantFigures );
     }
     else if( 2 == poPoint->getCoordinateDimension() )
     {
         poObj = OGRGeoJSONWriteCoords( poPoint->getX(),
                                        poPoint->getY(),
-                                       nCoordPrecision );
-    }
-    else
-    {
-        /* We can get here with POINT EMPTY geometries */
+                                       nCoordPrecision, nSignificantFigures );
     }
 
     return poObj;
@@ -318,13 +615,14 @@ json_object* OGRGeoJSONWritePoint( OGRPoint* poPoint, int nCoordPrecision )
 /*                           OGRGeoJSONWriteLineString                  */
 /************************************************************************/
 
-json_object* OGRGeoJSONWriteLineString( OGRLineString* poLine, int nCoordPrecision )
+json_object* OGRGeoJSONWriteLineString( OGRLineString* poLine,
+                                        int nCoordPrecision, int nSignificantFigures )
 {
     CPLAssert( NULL != poLine );
 
     /* Generate "coordinates" object for 2D or 3D dimension. */
     json_object* poObj = NULL;
-    poObj = OGRGeoJSONWriteLineCoords( poLine, nCoordPrecision );
+    poObj = OGRGeoJSONWriteLineCoords( poLine, nCoordPrecision, nSignificantFigures );
 
     return poObj;
 }
@@ -333,21 +631,21 @@ json_object* OGRGeoJSONWriteLineString( OGRLineString* poLine, int nCoordPrecisi
 /*                           OGRGeoJSONWritePolygon                     */
 /************************************************************************/
 
-json_object* OGRGeoJSONWritePolygon( OGRPolygon* poPolygon, int nCoordPrecision )
+json_object* OGRGeoJSONWritePolygon( OGRPolygon* poPolygon,
+                                     int nCoordPrecision, int nSignificantFigures )
 {
     CPLAssert( NULL != poPolygon );
 
     /* Generate "coordinates" array object. */
-    json_object* poObj = NULL;
-    poObj = json_object_new_array();
-    
+    json_object* poObj = json_object_new_array();
+
     /* Exterior ring. */
     OGRLinearRing* poRing = poPolygon->getExteriorRing();
     if (poRing == NULL)
         return poObj;
-    
-    json_object* poObjRing = NULL;
-    poObjRing = OGRGeoJSONWriteLineCoords( poRing, nCoordPrecision );
+
+    json_object* poObjRing
+        = OGRGeoJSONWriteLineCoords( poRing, nCoordPrecision, nSignificantFigures );
     if( poObjRing == NULL )
     {
         json_object_put(poObj);
@@ -363,7 +661,7 @@ json_object* OGRGeoJSONWritePolygon( OGRPolygon* poPolygon, int nCoordPrecision
         if (poRing == NULL)
             continue;
 
-        poObjRing = OGRGeoJSONWriteLineCoords( poRing, nCoordPrecision );
+        poObjRing = OGRGeoJSONWriteLineCoords( poRing, nCoordPrecision, nSignificantFigures );
         if( poObjRing == NULL )
         {
             json_object_put(poObj);
@@ -380,13 +678,14 @@ json_object* OGRGeoJSONWritePolygon( OGRPolygon* poPolygon, int nCoordPrecision
 /*                           OGRGeoJSONWriteMultiPoint                  */
 /************************************************************************/
 
-json_object* OGRGeoJSONWriteMultiPoint( OGRMultiPoint* poGeometry, int nCoordPrecision )
+json_object* OGRGeoJSONWriteMultiPoint( OGRMultiPoint* poGeometry,
+                                        int nCoordPrecision, int nSignificantFigures )
 {
     CPLAssert( NULL != poGeometry );
 
     /* Generate "coordinates" object for 2D or 3D dimension. */
-    json_object* poObj = NULL;
-    poObj = json_object_new_array();
+    json_object* poObj
+        = json_object_new_array();
 
     for( int i = 0; i < poGeometry->getNumGeometries(); ++i )
     {
@@ -394,8 +693,8 @@ json_object* OGRGeoJSONWriteMultiPoint( OGRMultiPoint* poGeometry, int nCoordPre
         CPLAssert( NULL != poGeom );
         OGRPoint* poPoint = static_cast<OGRPoint*>(poGeom);
 
-        json_object* poObjPoint = NULL;
-        poObjPoint = OGRGeoJSONWritePoint( poPoint, nCoordPrecision );
+        json_object* poObjPoint
+            = OGRGeoJSONWritePoint( poPoint, nCoordPrecision, nSignificantFigures );
         if( poObjPoint == NULL )
         {
             json_object_put(poObj);
@@ -412,13 +711,13 @@ json_object* OGRGeoJSONWriteMultiPoint( OGRMultiPoint* poGeometry, int nCoordPre
 /*                           OGRGeoJSONWriteMultiLineString             */
 /************************************************************************/
 
-json_object* OGRGeoJSONWriteMultiLineString( OGRMultiLineString* poGeometry, int nCoordPrecision )
+json_object* OGRGeoJSONWriteMultiLineString( OGRMultiLineString* poGeometry,
+                                             int nCoordPrecision, int nSignificantFigures )
 {
     CPLAssert( NULL != poGeometry );
 
     /* Generate "coordinates" object for 2D or 3D dimension. */
-    json_object* poObj = NULL;
-    poObj = json_object_new_array();
+    json_object* poObj = json_object_new_array();
 
     for( int i = 0; i < poGeometry->getNumGeometries(); ++i )
     {
@@ -427,13 +726,13 @@ json_object* OGRGeoJSONWriteMultiLineString( OGRMultiLineString* poGeometry, int
         OGRLineString* poLine = static_cast<OGRLineString*>(poGeom);
 
         json_object* poObjLine = NULL;
-        poObjLine = OGRGeoJSONWriteLineString( poLine, nCoordPrecision );
+        poObjLine = OGRGeoJSONWriteLineString( poLine, nCoordPrecision, nSignificantFigures );
         if( poObjLine == NULL )
         {
             json_object_put(poObj);
             return NULL;
         }
-        
+
         json_object_array_add( poObj, poObjLine );
     }
 
@@ -444,13 +743,13 @@ json_object* OGRGeoJSONWriteMultiLineString( OGRMultiLineString* poGeometry, int
 /*                           OGRGeoJSONWriteMultiPolygon                */
 /************************************************************************/
 
-json_object* OGRGeoJSONWriteMultiPolygon( OGRMultiPolygon* poGeometry, int nCoordPrecision )
+json_object* OGRGeoJSONWriteMultiPolygon( OGRMultiPolygon* poGeometry,
+                                          int nCoordPrecision, int nSignificantFigures )
 {
     CPLAssert( NULL != poGeometry );
 
     /* Generate "coordinates" object for 2D or 3D dimension. */
-    json_object* poObj = NULL;
-    poObj = json_object_new_array();
+    json_object* poObj = json_object_new_array();
 
     for( int i = 0; i < poGeometry->getNumGeometries(); ++i )
     {
@@ -458,14 +757,14 @@ json_object* OGRGeoJSONWriteMultiPolygon( OGRMultiPolygon* poGeometry, int nCoor
         CPLAssert( NULL != poGeom );
         OGRPolygon* poPoly = static_cast<OGRPolygon*>(poGeom);
 
-        json_object* poObjPoly = NULL;
-        poObjPoly = OGRGeoJSONWritePolygon( poPoly, nCoordPrecision );
+        json_object* poObjPoly
+            = OGRGeoJSONWritePolygon( poPoly, nCoordPrecision, nSignificantFigures );
         if( poObjPoly == NULL )
         {
             json_object_put(poObj);
             return NULL;
         }
-        
+
         json_object_array_add( poObj, poObjPoly );
     }
 
@@ -476,27 +775,27 @@ json_object* OGRGeoJSONWriteMultiPolygon( OGRMultiPolygon* poGeometry, int nCoor
 /*                           OGRGeoJSONWriteGeometryCollection          */
 /************************************************************************/
 
-json_object* OGRGeoJSONWriteGeometryCollection( OGRGeometryCollection* poGeometry, int nCoordPrecision )
+json_object* OGRGeoJSONWriteGeometryCollection( OGRGeometryCollection* poGeometry,
+                                                int nCoordPrecision, int nSignificantFigures )
 {
     CPLAssert( NULL != poGeometry );
 
     /* Generate "geometries" object. */
-    json_object* poObj = NULL;
-    poObj = json_object_new_array();
+    json_object* poObj = json_object_new_array();
 
     for( int i = 0; i < poGeometry->getNumGeometries(); ++i )
     {
         OGRGeometry* poGeom = poGeometry->getGeometryRef( i );
         CPLAssert( NULL != poGeom );
-        
-        json_object* poObjGeom = NULL;
-        poObjGeom = OGRGeoJSONWriteGeometry( poGeom, nCoordPrecision );
+
+        json_object* poObjGeom
+            = OGRGeoJSONWriteGeometry( poGeom, nCoordPrecision, nSignificantFigures );
         if( poGeom == NULL )
         {
             json_object_put(poObj);
             return NULL;
         }
-        
+
         json_object_array_add( poObj, poObjGeom );
     }
 
@@ -506,7 +805,8 @@ json_object* OGRGeoJSONWriteGeometryCollection( OGRGeometryCollection* poGeometr
 /*                           OGRGeoJSONWriteCoords                      */
 /************************************************************************/
 
-json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY, int nCoordPrecision )
+json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY,
+                                    int nCoordPrecision, int nSignificantFigures )
 {
     json_object* poObjCoords = NULL;
     if( CPLIsInf(fX) || CPLIsInf(fY) ||
@@ -516,13 +816,14 @@ json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY, int nCoo
         return NULL;
     }
     poObjCoords = json_object_new_array();
-    json_object_array_add( poObjCoords, json_object_new_double_with_precision( fX, nCoordPrecision ) );
-    json_object_array_add( poObjCoords, json_object_new_double_with_precision( fY, nCoordPrecision ) );
+    json_object_array_add( poObjCoords, json_object_new_coord( fX, nCoordPrecision, nSignificantFigures ) );
+    json_object_array_add( poObjCoords, json_object_new_coord( fY, nCoordPrecision, nSignificantFigures ) );
 
     return poObjCoords;
 }
 
-json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY, double const& fZ, int nCoordPrecision )
+json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY, double const& fZ,
+                                    int nCoordPrecision, int nSignificantFigures )
 {
     json_object* poObjCoords = NULL;
     if( CPLIsInf(fX) || CPLIsInf(fY) || CPLIsInf(fZ) ||
@@ -532,9 +833,9 @@ json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY, double c
         return NULL;
     }
     poObjCoords = json_object_new_array();
-    json_object_array_add( poObjCoords, json_object_new_double_with_precision( fX, nCoordPrecision ) );
-    json_object_array_add( poObjCoords, json_object_new_double_with_precision( fY, nCoordPrecision ) );
-    json_object_array_add( poObjCoords, json_object_new_double_with_precision( fZ, nCoordPrecision ) );
+    json_object_array_add( poObjCoords, json_object_new_coord( fX, nCoordPrecision, nSignificantFigures ) );
+    json_object_array_add( poObjCoords, json_object_new_coord( fY, nCoordPrecision, nSignificantFigures ) );
+    json_object_array_add( poObjCoords, json_object_new_coord( fZ, nCoordPrecision, nSignificantFigures ) );
 
     return poObjCoords;
 }
@@ -543,7 +844,9 @@ json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY, double c
 /*                           OGRGeoJSONWriteLineCoords                  */
 /************************************************************************/
 
-json_object* OGRGeoJSONWriteLineCoords( OGRLineString* poLine, int nCoordPrecision )
+json_object* OGRGeoJSONWriteLineCoords( OGRLineString* poLine,
+                                        int nCoordPrecision,
+                                        int nSignificantFigures )
 {
     json_object* poObjPoint = NULL;
     json_object* poObjCoords = json_object_new_array();
@@ -552,9 +855,11 @@ json_object* OGRGeoJSONWriteLineCoords( OGRLineString* poLine, int nCoordPrecisi
     for( int i = 0; i < nCount; ++i )
     {
         if( poLine->getCoordinateDimension() == 2 )
-            poObjPoint = OGRGeoJSONWriteCoords( poLine->getX(i), poLine->getY(i), nCoordPrecision );
+            poObjPoint = OGRGeoJSONWriteCoords( poLine->getX(i), poLine->getY(i),
+                                                nCoordPrecision, nSignificantFigures );
         else
-            poObjPoint = OGRGeoJSONWriteCoords( poLine->getX(i), poLine->getY(i), poLine->getZ(i), nCoordPrecision );
+            poObjPoint = OGRGeoJSONWriteCoords( poLine->getX(i), poLine->getY(i), poLine->getZ(i),
+                                                nCoordPrecision, nSignificantFigures );
         if( poObjPoint == NULL )
         {
             json_object_put(poObjCoords);
@@ -562,7 +867,7 @@ json_object* OGRGeoJSONWriteLineCoords( OGRLineString* poLine, int nCoordPrecisi
         }
         json_object_array_add( poObjCoords, poObjPoint );
     }
-    
+
     return poObjCoords;
 }
 
@@ -595,11 +900,20 @@ char* OGR_G_ExportToJson( OGRGeometryH hGeometry )
  *
  * The returned string should be freed with CPLFree() when no longer required.
  *
+ * The following options are supported :
+ * <ul>
+ * <li>COORDINATE_PRECISION=number: maximum number of figures after decimal separator to write in coordinates.</li>
+ * <li>SIGNIFICANT_FIGURES=number: maximum number of significant figures (GDAL >= 2.1).</li>
+ * </ul>
+ *
+ * If COORDINATE_PRECISION is defined, SIGNIFICANT_FIGURES will be ignored if
+ * specified.
+ * When none are defined, the default is COORDINATE_PRECISION=15.
+ *
  * This method is the same as the C++ method OGRGeometry::exportToJson().
  *
  * @param hGeometry handle to the geometry.
- * @param papszOptions a null terminated list of options. For now, only COORDINATE_PRECISION=int_number
- *                     where int_number is the maximum number of figures after decimal separator to write in coordinates.
+ * @param papszOptions a null terminated list of options.
  * @return A GeoJSON fragment or NULL in case of error.
  *
  * @since OGR 1.9.0
@@ -609,12 +923,16 @@ char* OGR_G_ExportToJsonEx( OGRGeometryH hGeometry, char** papszOptions )
 {
     VALIDATE_POINTER1( hGeometry, "OGR_G_ExportToJson", NULL );
 
-    OGRGeometry* poGeometry = (OGRGeometry*) (hGeometry);
+    OGRGeometry* poGeometry = reinterpret_cast<OGRGeometry *>( hGeometry );
 
-    int nCoordPrecision = atoi(CSLFetchNameValueDef(papszOptions, "COORDINATE_PRECISION", "-1"));
+    const int nCoordPrecision
+        = atoi(CSLFetchNameValueDef(papszOptions, "COORDINATE_PRECISION", "-1"));
 
-    json_object* poObj = NULL;
-    poObj = OGRGeoJSONWriteGeometry( poGeometry, nCoordPrecision );
+    const int nSignificantFigures
+        = atoi(CSLFetchNameValueDef(papszOptions, "SIGNIFICANT_FIGURES", "-1"));
+
+    json_object* poObj
+        = OGRGeoJSONWriteGeometry( poGeometry, nCoordPrecision, nSignificantFigures );
 
     if( NULL != poObj )
     {
@@ -640,14 +958,14 @@ static int OGR_json_double_with_precision_to_string(struct json_object *jso,
                                                     CPL_UNUSED int flags)
 {
     char szBuffer[75];
-    int nPrecision = (int) (size_t) jso->_userdata;
+    const int nPrecision = (int) (size_t) jso->_userdata;
     OGRFormatDouble( szBuffer, sizeof(szBuffer), jso->o.c_double, '.',
                      (nPrecision < 0) ? 15 : nPrecision );
     if( szBuffer[0] == 't' /*oobig */ )
     {
         CPLsnprintf(szBuffer, sizeof(szBuffer), "%.18g", jso->o.c_double);
     }
-    return printbuf_memappend(pb, szBuffer, strlen(szBuffer)); 
+    return printbuf_memappend(pb, szBuffer, static_cast<int>(strlen(szBuffer)));
 }
 
 /************************************************************************/
@@ -662,3 +980,81 @@ json_object* json_object_new_double_with_precision(double dfVal,
                                (void*)(size_t)nCoordPrecision, NULL );
     return jso;
 }
+
+/************************************************************************/
+/*             OGR_json_double_with_significant_figures_to_string()     */
+/************************************************************************/
+
+static int OGR_json_double_with_significant_figures_to_string(struct json_object *jso,
+                                                    struct printbuf *pb,
+                                                    CPL_UNUSED int level,
+                                                    CPL_UNUSED int flags)
+{
+    char szBuffer[75];
+    int nSize;
+    if( CPLIsNan(jso->o.c_double))
+        nSize = CPLsnprintf(szBuffer, sizeof(szBuffer), "NaN");
+    else if(CPLIsInf(jso->o.c_double))
+    {
+        if(jso->o.c_double > 0)
+            nSize = CPLsnprintf(szBuffer, sizeof(szBuffer), "Infinity");
+        else
+            nSize = CPLsnprintf(szBuffer, sizeof(szBuffer), "-Infinity");
+    }
+    else
+    {
+        char szFormatting[32];
+        const int nSignificantFigures = (int) (size_t) jso->_userdata;
+        const int nInitialSignificantFigures = nSignificantFigures >= 0 ? nSignificantFigures : 17;
+        CPLsnprintf(szFormatting, sizeof(szFormatting), "%%.%dg", nInitialSignificantFigures);
+        nSize = CPLsnprintf(szBuffer, sizeof(szBuffer), szFormatting, jso->o.c_double);
+        const char* pszDot = NULL;
+        if( nSize+2 < (int)sizeof(szBuffer) && (pszDot = strchr(szBuffer, '.')) == NULL )
+        {
+            nSize += CPLsnprintf(szBuffer + nSize, sizeof(szBuffer) - nSize, ".0");
+        }
+
+        // Try to avoid .xxxx999999y or .xxxx000000y rounding issues by decreasing a bit precision
+        if( nInitialSignificantFigures > 10 && pszDot != NULL &&
+            (strstr(pszDot, "999999") != NULL || strstr(pszDot, "000000") != NULL) )
+        {
+            bool bOK = false;
+            for(int i=1; i<=3; i++)
+            {
+                CPLsnprintf(szFormatting, sizeof(szFormatting), "%%.%dg", nInitialSignificantFigures- i);
+                nSize = CPLsnprintf(szBuffer, sizeof(szBuffer), szFormatting, jso->o.c_double);
+                pszDot = strchr(szBuffer, '.');
+                if( pszDot != NULL &&
+                    strstr(pszDot, "999999") == NULL && strstr(pszDot, "000000") == NULL )
+                {
+                    bOK = true;
+                    break;
+                }
+            }
+            if( !bOK )
+            {
+                CPLsnprintf(szFormatting, sizeof(szFormatting), "%%.%dg", nInitialSignificantFigures);
+                nSize = CPLsnprintf(szBuffer, sizeof(szBuffer), szFormatting, jso->o.c_double);
+                if( nSize+2 < (int)sizeof(szBuffer) && (pszDot = strchr(szBuffer, '.')) == NULL )
+                {
+                    nSize += CPLsnprintf(szBuffer + nSize, sizeof(szBuffer) - nSize, ".0");
+                }
+            }
+        }
+    }
+
+    return printbuf_memappend(pb, szBuffer, nSize);
+}
+
+/************************************************************************/
+/*              json_object_new_double_with_significant_figures()       */
+/************************************************************************/
+
+json_object* json_object_new_double_with_significant_figures(double dfVal,
+                                                   int nSignificantFigures)
+{
+    json_object* jso = json_object_new_double(dfVal);
+    json_object_set_serializer(jso, OGR_json_double_with_significant_figures_to_string,
+                               (void*)(size_t)nSignificantFigures, NULL );
+    return jso;
+}
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.h b/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.h
index 93ae2bc..8fa67f1 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.h
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsonwriter.h 29243 2015-05-24 15:53:26Z rouault $
+ * $Id: ogrgeojsonwriter.h 32952 2016-01-12 12:24:52Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines GeoJSON reader within OGR OGRGeoJSON Driver.
@@ -50,27 +50,32 @@ class OGRGeometryCollection;
 #endif
 
 CPL_C_START
+/* %.XXXf formatting */
 json_object CPL_DLL *json_object_new_double_with_precision(double dfVal, int nCoordPrecision);
+
+/* %.XXXg formatting */
+json_object CPL_DLL* json_object_new_double_with_significant_figures(double dfVal,
+                                                                     int nSignificantFigures);
 CPL_C_END
 
 /************************************************************************/
 /*                 GeoJSON Geometry Translators                         */
 /************************************************************************/
 #ifdef __cplusplus
-json_object* OGRGeoJSONWriteFeature( OGRFeature* poFeature, int bWriteBBOX, int nCoordPrecision );
-json_object* OGRGeoJSONWriteAttributes( OGRFeature* poFeature );
-json_object* OGRGeoJSONWriteGeometry( OGRGeometry* poGeometry, int nCoordPrecision );
-json_object* OGRGeoJSONWritePoint( OGRPoint* poPoint, int nCoordPrecision );
-json_object* OGRGeoJSONWriteLineString( OGRLineString* poLine, int nCoordPrecision );
-json_object* OGRGeoJSONWritePolygon( OGRPolygon* poPolygon, int nCoordPrecision );
-json_object* OGRGeoJSONWriteMultiPoint( OGRMultiPoint* poGeometry, int nCoordPrecision );
-json_object* OGRGeoJSONWriteMultiLineString( OGRMultiLineString* poGeometry, int nCoordPrecision );
-json_object* OGRGeoJSONWriteMultiPolygon( OGRMultiPolygon* poGeometry, int nCoordPrecision );
-json_object* OGRGeoJSONWriteGeometryCollection( OGRGeometryCollection* poGeometry, int nCoordPrecision );
+json_object* OGRGeoJSONWriteFeature( OGRFeature* poFeature, int bWriteBBOX, int nCoordPrecision, int nSignificantFigures );
+json_object* OGRGeoJSONWriteAttributes( OGRFeature* poFeature, int nSignificantFigures );
+json_object* OGRGeoJSONWriteGeometry( OGRGeometry* poGeometry, int nCoordPrecision, int nSignificantFigures );
+json_object* OGRGeoJSONWritePoint( OGRPoint* poPoint, int nCoordPrecision, int nSignificantFigures );
+json_object* OGRGeoJSONWriteLineString( OGRLineString* poLine, int nCoordPrecision, int nSignificantFigures );
+json_object* OGRGeoJSONWritePolygon( OGRPolygon* poPolygon, int nCoordPrecision, int nSignificantFigures );
+json_object* OGRGeoJSONWriteMultiPoint( OGRMultiPoint* poGeometry, int nCoordPrecision, int nSignificantFigures );
+json_object* OGRGeoJSONWriteMultiLineString( OGRMultiLineString* poGeometry, int nCoordPrecision, int nSignificantFigures );
+json_object* OGRGeoJSONWriteMultiPolygon( OGRMultiPolygon* poGeometry, int nCoordPrecision, int nSignificantFigures );
+json_object* OGRGeoJSONWriteGeometryCollection( OGRGeometryCollection* poGeometry, int nCoordPrecision, int nSignificantFigures );
 
-json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY, int nCoordPrecision );
-json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY, double const& fZ, int nCoordPrecision );
-json_object* OGRGeoJSONWriteLineCoords( OGRLineString* poLine, int nCoordPrecision );
+json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY, int nCoordPrecision, int nSignificantFigures );
+json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY, double const& fZ, int nCoordPrecision, int nSignificantFigures );
+json_object* OGRGeoJSONWriteLineCoords( OGRLineString* poLine, int nCoordPrecision, int nSignificantFigures );
 #endif
 
 #endif /* OGR_GEOJSONWRITER_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/geojson/ogrtopojsonreader.cpp b/ogr/ogrsf_frmts/geojson/ogrtopojsonreader.cpp
index 5daeaa5..6d51bd2 100644
--- a/ogr/ogrsf_frmts/geojson/ogrtopojsonreader.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrtopojsonreader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrtopojsonreader.cpp 28886 2015-04-12 23:09:13Z rouault $
+ * $Id: ogrtopojsonreader.cpp 33093 2016-01-22 17:38:07Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of OGRTopoJSONReader class
@@ -65,17 +65,14 @@ OGRErr OGRTopoJSONReader::Parse( const char* pszText )
 {
     if( NULL != pszText )
     {
-        json_tokener* jstok = NULL;
-        json_object* jsobj = NULL;
-
-        jstok = json_tokener_new();
-        jsobj = json_tokener_parse_ex(jstok, pszText, -1);
+        json_tokener *jstok = json_tokener_new();
+        json_object *jsobj = json_tokener_parse_ex(jstok, pszText, -1);
         if( jstok->err != json_tokener_success)
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "TopoJSON parsing error: %s (at offset %d)",
             	      json_tokener_error_desc(jstok->err), jstok->char_offset);
-            
+
             json_tokener_free(jstok);
             return OGRERR_CORRUPT_DATA;
         }
@@ -100,7 +97,7 @@ typedef struct
 /*                            ParsePoint()                              */
 /************************************************************************/
 
-static int ParsePoint(json_object* poPoint, double* pdfX, double* pdfY)
+static bool ParsePoint(json_object* poPoint, double* pdfX, double* pdfY)
 {
     if( poPoint != NULL && json_type_array == json_object_get_type(poPoint) &&
         json_object_array_length(poPoint) == 2 )
@@ -116,18 +113,18 @@ static int ParsePoint(json_object* poPoint, double* pdfX, double* pdfY)
         {
             *pdfX = json_object_get_double(poX);
             *pdfY = json_object_get_double(poY);
-            return TRUE;
+            return true;
         }
     }
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
 /*                             ParseArc()                               */
 /************************************************************************/
 
-static void ParseArc(OGRLineString* poLS, json_object* poArcsDB, int nArcID,
-                     int bReverse, ScalingParams* psParams)
+static void ParseArc( OGRLineString* poLS, json_object* poArcsDB, int nArcID,
+                      int bReverse, ScalingParams* psParams)
 {
     json_object* poArcDB = json_object_array_get_idx(poArcsDB, nArcID);
     if( poArcDB == NULL || json_type_array != json_object_get_type(poArcDB) )
@@ -143,8 +140,8 @@ static void ParseArc(OGRLineString* poLS, json_object* poArcsDB, int nArcID,
         {
             dfAccX += dfX;
             dfAccY += dfY;
-            double dfX = dfAccX * psParams->dfScale0 + psParams->dfTranslate0;
-            double dfY = dfAccY * psParams->dfScale1 + psParams->dfTranslate1;
+            dfX = dfAccX * psParams->dfScale0 + psParams->dfTranslate0;
+            dfY = dfAccY * psParams->dfScale1 + psParams->dfTranslate1;
             if( i == 0 )
             {
                 if( !bReverse && poLS->getNumPoints() > 0 )
@@ -309,15 +306,15 @@ static void ParseObject(const char* pszId,
     json_object* poProperties = OGRGeoJSONFindMemberByName(poObj, "properties");
     if( poProperties != NULL && json_type_object == json_object_get_type(poProperties) )
     {
-        int nField = -1;
         json_object_iter it;
         it.key = NULL;
         it.val = NULL;
         it.entry = NULL;
         json_object_object_foreachC( poProperties, it )
         {
-            nField = poFeature->GetFieldIndex(it.key);
-            OGRGeoJSONReaderSetField(poLayer, poFeature, nField, it.key, it.val, FALSE, 0);
+            const int nField
+                = poFeature->GetFieldIndex(it.key);
+            OGRGeoJSONReaderSetField(poLayer, poFeature, nField, it.key, it.val, false, 0);
         }
     }
 
@@ -375,7 +372,7 @@ static void ParseObject(const char* pszId,
         poGeom = poMultiPoly;
         ParseMultiPolygon(poMultiPoly, poArcsObj, poArcsDB, psParams);
     }
-    
+
     if( poGeom != NULL )
         poFeature->SetGeometryDirectly(poGeom);
     poLayer->AddFeature(poFeature);
@@ -400,7 +397,7 @@ static void EstablishLayerDefn(OGRFeatureDefn* poDefn,
         it.entry = NULL;
         json_object_object_foreachC( poObjProps, it )
         {
-            OGRGeoJSONReaderAddOrUpdateField(poDefn, it.key, it.val, FALSE, 0);
+            OGRGeoJSONReaderAddOrUpdateField(poDefn, it.key, it.val, false, 0);
         }
     }
 }
@@ -409,14 +406,14 @@ static void EstablishLayerDefn(OGRFeatureDefn* poDefn,
 /*                        ParseObjectMain()                             */
 /************************************************************************/
 
-static int  ParseObjectMain(const char* pszId, json_object* poObj,
-                            OGRGeoJSONDataSource* poDS,
-                            OGRGeoJSONLayer **ppoMainLayer,
-                            json_object* poArcs,
-                            ScalingParams* psParams,
-                            int nPassNumber)
+static bool ParseObjectMain( const char* pszId, json_object* poObj,
+                             OGRGeoJSONDataSource* poDS,
+                             OGRGeoJSONLayer **ppoMainLayer,
+                             json_object* poArcs,
+                             ScalingParams* psParams,
+                             int nPassNumber )
 {
-    int bNeedSecondPass = FALSE;
+    bool bNeedSecondPass = false;
 
     if( poObj != NULL && json_type_object == json_object_get_type( poObj ) )
     {
@@ -498,7 +495,7 @@ static int  ParseObjectMain(const char* pszId, json_object* poObj,
                     }
                     OGRFeatureDefn* poDefn = (*ppoMainLayer)->GetLayerDefn();
                     EstablishLayerDefn(poDefn, poObj);
-                    bNeedSecondPass = TRUE;
+                    bNeedSecondPass = true;
                 }
                 else
                     ParseObject(pszId, poObj, *ppoMainLayer, poArcs, psParams);
@@ -517,7 +514,7 @@ void OGRTopoJSONReader::ReadLayers( OGRGeoJSONDataSource* poDS )
     if( NULL == poGJObject_ )
     {
         CPLDebug( "TopoJSON",
-                  "Missing parset TopoJSON data. Forgot to call Parse()?" );
+                  "Missing parsed TopoJSON data. Forgot to call Parse()?" );
         return;
     }
 
@@ -582,11 +579,13 @@ void OGRTopoJSONReader::ReadLayers( OGRGeoJSONDataSource* poDS )
         it.key = NULL;
         it.val = NULL;
         it.entry = NULL;
-        int bNeedSecondPass = FALSE;
+        bool bNeedSecondPass = false;
         json_object_object_foreachC( poObjects, it )
         {
             json_object* poObj = it.val;
-            bNeedSecondPass |= ParseObjectMain(it.key, poObj, poDS, &poMainLayer, poArcs, &sParams, 1);
+            bNeedSecondPass |= ParseObjectMain( it.key, poObj, poDS,
+                                                &poMainLayer, poArcs, &sParams,
+                                                1);
         }
         if( bNeedSecondPass )
         {
@@ -602,8 +601,8 @@ void OGRTopoJSONReader::ReadLayers( OGRGeoJSONDataSource* poDS )
     }
     else if( json_type_array == json_object_get_type( poObjects ) )
     {
-        int nObjects = json_object_array_length(poObjects);
-        int bNeedSecondPass = FALSE;
+        const int nObjects = json_object_array_length(poObjects);
+        bool bNeedSecondPass = false;
         for(int i=0; i<nObjects; i++)
         {
             json_object* poObj = json_object_array_get_idx(poObjects, i);
diff --git a/ogr/ogrsf_frmts/geomedia/drv_geomedia.html b/ogr/ogrsf_frmts/geomedia/drv_geomedia.html
index 557237b..a774532 100644
--- a/ogr/ogrsf_frmts/geomedia/drv_geomedia.html
+++ b/ogr/ogrsf_frmts/geomedia/drv_geomedia.html
@@ -21,18 +21,18 @@
   <p>Geomedia .mdb are accessed by passing the file name of
   the .mdb file to be accessed as the data source name. On Windows,
   no ODBC DSN is required. On Linux, there are problems with DSN-less
-  connection due to incomplete or buggy implementation of this feature 
+  connection due to incomplete or buggy implementation of this feature
   in the <a href="http://mdbtools.sourceforge.net/">MDB Tools</a> package,
   So, it is required to configure Data Source Name (DSN) if the MDB
   Tools driver is used (check instructions below).</p>
-  
-  <p>In order to facilitate compatibility with different configurations, 
+
+  <p>In order to facilitate compatibility with different configurations,
   the GEOMEDIA_DRIVER_TEMPLATE Config Option was added to provide a way to
-  programmatically set the DSN programmatically with the filename as 
+  programmatically set the DSN programmatically with the filename as
   an argument.   In cases where the driver name is known, this allows for
   the construction of the DSN based on that information in a manner similar
   to the default (used for Windows access to the Microsoft Access Driver).</p>
-  
+
   <p>OGR treats all feature tables as layers. Most geometry types
   should be supported (arcs are not yet). Coordinate system information
   is not currently supported.</p>
@@ -41,9 +41,9 @@
   advantage of spatial indexes for fast spatial queries.</p>
 
 <p>By default, SQL statements are passed directly to the MDB database engine.
-It's also possible to request the driver to handle SQL commands 
-with <a href="/ogr/ogr_sql.html">OGR SQL</a> engine, 
-by passing <strong>"OGRSQL"</strong> string to the ExecuteSQL() 
+It's also possible to request the driver to handle SQL commands
+with <a href="ogr_sql.html">OGR SQL</a> engine,
+by passing <strong>"OGRSQL"</strong> string to the ExecuteSQL()
 method, as name of the SQL dialect.</p>
 
   <h2>How to use Geomedia driver with unixODBC and MDB Tools (on Unix and Linux)</h2>
diff --git a/ogr/ogrsf_frmts/geomedia/ogr_geomedia.h b/ogr/ogrsf_frmts/geomedia/ogr_geomedia.h
index 091423e..a02b4dd 100644
--- a/ogr/ogrsf_frmts/geomedia/ogr_geomedia.h
+++ b/ogr/ogrsf_frmts/geomedia/ogr_geomedia.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_geomedia.h 28382 2015-01-30 15:29:41Z rouault $
+ * $Id: ogr_geomedia.h 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for Geomedia MDB driver.
@@ -28,8 +28,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_GEOMEDIA_H_INCLUDED
-#define _OGR_GEOMEDIA_H_INCLUDED
+#ifndef OGR_GEOMEDIA_H_INCLUDED
+#define OGR_GEOMEDIA_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "cpl_odbc.h"
@@ -41,7 +41,7 @@
 /************************************************************************/
 
 class OGRGeomediaDataSource;
-    
+
 class OGRGeomediaLayer : public OGRLayer
 {
   protected:
@@ -78,9 +78,9 @@ class OGRGeomediaLayer : public OGRLayer
     virtual OGRFeature *GetNextFeature();
 
     virtual OGRFeature *GetFeature( GIntBig nFeatureId );
-    
+
     OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
-    
+
     virtual int         TestCapability( const char * );
 
     virtual const char *GetFIDColumn();
@@ -106,7 +106,7 @@ class OGRGeomediaTableLayer : public OGRGeomediaLayer
                         OGRGeomediaTableLayer( OGRGeomediaDataSource * );
                         ~OGRGeomediaTableLayer();
 
-    CPLErr              Initialize( const char *pszTableName, 
+    CPLErr              Initialize( const char *pszTableName,
                                     const char *pszGeomCol,
                                     OGRSpatialReference* poSRS );
 
@@ -115,7 +115,7 @@ class OGRGeomediaTableLayer : public OGRGeomediaLayer
 
     virtual OGRErr      SetAttributeFilter( const char * );
     virtual OGRFeature *GetFeature( GIntBig nFeatureId );
-    
+
     virtual int         TestCapability( const char * );
 };
 
@@ -141,7 +141,7 @@ class OGRGeomediaSelectLayer : public OGRGeomediaLayer
     virtual GIntBig     GetFeatureCount( int );
 
     virtual OGRFeature *GetFeature( GIntBig nFeatureId );
-    
+
     virtual int         TestCapability( const char * );
 };
 
@@ -171,7 +171,7 @@ class OGRGeomediaDataSource : public OGRDataSource
                         ~OGRGeomediaDataSource();
 
     int                 Open( const char *, int bUpdate, int bTestOpen );
-    int                 OpenTable( const char *pszTableName, 
+    int                 OpenTable( const char *pszTableName,
                                    const char *pszGeomCol,
                                    int bUpdate );
 
@@ -199,7 +199,7 @@ class OGRGeomediaDriver : public OGRODBCMDBDriver
 {
   public:
                 ~OGRGeomediaDriver();
-                
+
     const char  *GetName();
     OGRDataSource *Open( const char *, int );
 
diff --git a/ogr/ogrsf_frmts/geomedia/ogrgeomediadatasource.cpp b/ogr/ogrsf_frmts/geomedia/ogrgeomediadatasource.cpp
index acaaeb4..fce1ce3 100644
--- a/ogr/ogrsf_frmts/geomedia/ogrgeomediadatasource.cpp
+++ b/ogr/ogrsf_frmts/geomedia/ogrgeomediadatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeomediadatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogrgeomediadatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGeomediaDataSource class.
@@ -34,7 +34,7 @@
 #include "cpl_string.h"
 #include <vector>
 
-CPL_CVSID("$Id: ogrgeomediadatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogrgeomediadatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                       OGRGeomediaDataSource()                        */
@@ -48,6 +48,7 @@ OGRGeomediaDataSource::OGRGeomediaDataSource()
     papoLayersInvisible = NULL;
     nLayers = 0;
     nLayersWithInvisible = 0;
+    bDSUpdate = FALSE;
 }
 
 /************************************************************************/
@@ -116,7 +117,7 @@ int OGRGeomediaDataSource::Open( const char * pszNewName, int bUpdate,
 /*                                                                      */
 /* -------------------------------------------------------------------- */
     char *pszDSN;
-    if( EQUALN(pszNewName,"GEOMEDIA:",9) )
+    if( STARTS_WITH_CI(pszNewName, "GEOMEDIA:") )
         pszDSN = CPLStrdup( pszNewName + 9 );
     else
     {
@@ -129,7 +130,10 @@ int OGRGeomediaDataSource::Open( const char * pszNewName, int bUpdate,
             return FALSE;
         }
         pszDSN = (char *) CPLMalloc(strlen(pszNewName)+strlen(pszDSNStringTemplate)+100);
-        sprintf( pszDSN, pszDSNStringTemplate,  pszNewName );
+        /* coverity[tainted_string] */
+        snprintf( pszDSN,
+                  strlen(pszNewName)+strlen(pszDSNStringTemplate)+100,
+                  pszDSNStringTemplate,  pszNewName );
     }
 
 /* -------------------------------------------------------------------- */
@@ -139,7 +143,7 @@ int OGRGeomediaDataSource::Open( const char * pszNewName, int bUpdate,
 
     if( !oSession.EstablishSession( pszDSN, NULL, NULL ) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to initialize ODBC connection to DSN for %s,\n"
                   "%s", pszDSN, oSession.GetLastError() );
         CPLFree( pszDSN );
@@ -149,7 +153,7 @@ int OGRGeomediaDataSource::Open( const char * pszNewName, int bUpdate,
     CPLFree( pszDSN );
 
     pszName = CPLStrdup( pszNewName );
-    
+
     bDSUpdate = bUpdate;
 
 /* -------------------------------------------------------------------- */
@@ -179,7 +183,7 @@ int OGRGeomediaDataSource::Open( const char * pszNewName, int bUpdate,
 
         while( oStmt.Fetch() )
         {
-            int i, iNew = apapszGeomColumns.size();
+            int i, iNew = static_cast<int>(apapszGeomColumns.size());
             char **papszRecord = NULL;
             for( i = 0; i < 2; i++ )
                 papszRecord = CSLAddString( papszRecord,
@@ -345,12 +349,12 @@ OGRLayer *OGRGeomediaDataSource::GetLayer( int iLayer )
 /*                          GetLayerByName()                            */
 /************************************************************************/
 
-OGRLayer *OGRGeomediaDataSource::GetLayerByName( const char* pszName )
+OGRLayer *OGRGeomediaDataSource::GetLayerByName( const char* pszNameIn )
 
 {
-    if (pszName == NULL)
+    if (pszNameIn == NULL)
         return NULL;
-    OGRLayer* poLayer = OGRDataSource::GetLayerByName(pszName);
+    OGRLayer* poLayer = OGRDataSource::GetLayerByName(pszNameIn);
     if (poLayer)
         return poLayer;
 
@@ -358,7 +362,7 @@ OGRLayer *OGRGeomediaDataSource::GetLayerByName( const char* pszName )
     {
         poLayer = papoLayersInvisible[i];
 
-        if( strcmp( pszName, poLayer->GetName() ) == 0 )
+        if( strcmp( pszNameIn, poLayer->GetName() ) == 0 )
             return poLayer;
     }
 
@@ -366,7 +370,7 @@ OGRLayer *OGRGeomediaDataSource::GetLayerByName( const char* pszName )
 
     poGeomediaLayer = new OGRGeomediaTableLayer( this );
 
-    if( poGeomediaLayer->Initialize(pszName, NULL, NULL) != CE_None )
+    if( poGeomediaLayer->Initialize(pszNameIn, NULL, NULL) != CE_None )
     {
         delete poGeomediaLayer;
         return NULL;
@@ -392,8 +396,8 @@ OGRLayer * OGRGeomediaDataSource::ExecuteSQL( const char *pszSQLCommand,
 /*      Use generic implementation for recognized dialects              */
 /* -------------------------------------------------------------------- */
     if( IsGenericSQLDialect(pszDialect) )
-        return OGRDataSource::ExecuteSQL( pszSQLCommand, 
-                                          poSpatialFilter, 
+        return OGRDataSource::ExecuteSQL( pszSQLCommand,
+                                          poSpatialFilter,
                                           pszDialect );
 
 /* -------------------------------------------------------------------- */
@@ -404,8 +408,9 @@ OGRLayer * OGRGeomediaDataSource::ExecuteSQL( const char *pszSQLCommand,
     poStmt->Append( pszSQLCommand );
     if( !poStmt->ExecuteSQL() )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", oSession.GetLastError() );
+        delete poStmt;
         return NULL;
     }
 
@@ -424,12 +429,12 @@ OGRLayer * OGRGeomediaDataSource::ExecuteSQL( const char *pszSQLCommand,
 /*      statement.                                                      */
 /* -------------------------------------------------------------------- */
     OGRGeomediaSelectLayer *poLayer = NULL;
-        
+
     poLayer = new OGRGeomediaSelectLayer( this, poStmt );
 
     if( poSpatialFilter != NULL )
         poLayer->SetSpatialFilter( poSpatialFilter );
-    
+
     return poLayer;
 }
 
diff --git a/ogr/ogrsf_frmts/geomedia/ogrgeomediadriver.cpp b/ogr/ogrsf_frmts/geomedia/ogrgeomediadriver.cpp
index 14ea075..a588460 100644
--- a/ogr/ogrsf_frmts/geomedia/ogrgeomediadriver.cpp
+++ b/ogr/ogrsf_frmts/geomedia/ogrgeomediadriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeomediadriver.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogrgeomediadriver.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements Personal Geodatabase driver.
@@ -31,7 +31,7 @@
 #include "ogr_geomedia.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrgeomediadriver.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogrgeomediadriver.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                          ~OGRODBCDriver()                            */
@@ -62,20 +62,20 @@ OGRDataSource *OGRGeomediaDriver::Open( const char * pszFilename,
 {
     OGRGeomediaDataSource     *poDS;
 
-    if( EQUALN(pszFilename, "WALK:", strlen("WALK:")) )
+    if( STARTS_WITH_CI(pszFilename, "WALK:") )
         return NULL;
 
-    if( EQUALN(pszFilename, "PGEO:", strlen("PGEO:")) )
+    if( STARTS_WITH_CI(pszFilename, "PGEO:") )
         return NULL;
 
-    if( !EQUALN(pszFilename,"GEOMEDIA:",9) 
+    if( !STARTS_WITH_CI(pszFilename, "GEOMEDIA:")
         && !EQUAL(CPLGetExtension(pszFilename),"mdb") )
         return NULL;
 
     /* Disabling the attempt to guess if a MDB file is a Geomedia database */
     /* or not. See similar fix in PGeo driver for rationale. */
 #if 0
-    if( !EQUALN(pszFilename,"GEOMEDIA:",9) &&
+    if( !STARTS_WITH_CI(pszFilename, "GEOMEDIA:") &&
         EQUAL(CPLGetExtension(pszFilename),"mdb") )
     {
         VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
@@ -117,7 +117,7 @@ OGRDataSource *OGRGeomediaDriver::Open( const char * pszFilename,
     //
     if ( !InstallMdbDriver() )
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "Unable to install MDB driver for ODBC, MDB access may not supported.\n" );
     }
     else
@@ -154,10 +154,8 @@ void RegisterOGRGeomedia()
 
 {
     OGRSFDriver* poDriver = new OGRGeomediaDriver;
-    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                "Geomedia .mdb" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Geomedia .mdb" );
     poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "mdb" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                "drv_geomedia.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_geomedia.html" );
     OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver(poDriver);
 }
diff --git a/ogr/ogrsf_frmts/geomedia/ogrgeomedialayer.cpp b/ogr/ogrsf_frmts/geomedia/ogrgeomedialayer.cpp
index ad8fc20..a0ef066 100644
--- a/ogr/ogrsf_frmts/geomedia/ogrgeomedialayer.cpp
+++ b/ogr/ogrsf_frmts/geomedia/ogrgeomedialayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeomedialayer.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrgeomedialayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGeomediaLayer class, code shared between
@@ -34,7 +34,7 @@
 #include "cpl_string.h"
 #include "ogrgeomediageometry.h"
 
-CPL_CVSID("$Id: ogrgeomedialayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrgeomedialayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                          OGRGeomediaLayer()                          */
@@ -53,7 +53,9 @@ OGRGeomediaLayer::OGRGeomediaLayer()
     iNextShapeId = 0;
 
     poSRS = NULL;
-    nSRSId = -2; // we haven't even queried the database for it yet. 
+    nSRSId = -2; // we haven't even queried the database for it yet.
+    poFeatureDefn = NULL;
+    panFieldOrdinals = NULL;
 }
 
 /************************************************************************/
@@ -66,7 +68,7 @@ OGRGeomediaLayer::~OGRGeomediaLayer()
     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     {
         CPLDebug( "Geomedia", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
+                  (int) m_nFeaturesRead,
                   poFeatureDefn->GetName() );
     }
 
@@ -83,7 +85,7 @@ OGRGeomediaLayer::~OGRGeomediaLayer()
     }
 
     CPLFree( pszGeomColumn );
-    CPLFree( panFieldOrdinals ); 
+    CPLFree( panFieldOrdinals );
     CPLFree( pszFIDColumn );
 
     if( poSRS != NULL )
@@ -101,12 +103,12 @@ OGRGeomediaLayer::~OGRGeomediaLayer()
 /************************************************************************/
 
 CPLErr OGRGeomediaLayer::BuildFeatureDefn( const char *pszLayerName,
-                                       CPLODBCStatement *poStmt )
+                                       CPLODBCStatement *poStmtIn )
 
 {
     poFeatureDefn = new OGRFeatureDefn( pszLayerName );
     SetDescription( poFeatureDefn->GetName() );
-    int    nRawColumns = poStmt->GetColCount();
+    int    nRawColumns = poStmtIn->GetColCount();
 
     poFeatureDefn->Reference();
     poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
@@ -115,25 +117,25 @@ CPLErr OGRGeomediaLayer::BuildFeatureDefn( const char *pszLayerName,
 
     for( int iCol = 0; iCol < nRawColumns; iCol++ )
     {
-        OGRFieldDefn    oField( poStmt->GetColName(iCol), OFTString );
+        OGRFieldDefn    oField( poStmtIn->GetColName(iCol), OFTString );
 
-        oField.SetWidth( MAX(0,poStmt->GetColSize( iCol )) );
+        oField.SetWidth( MAX(0,poStmtIn->GetColSize( iCol )) );
 
-        if( pszGeomColumn != NULL 
-            && EQUAL(poStmt->GetColName(iCol),pszGeomColumn) )
+        if( pszGeomColumn != NULL
+            && EQUAL(poStmtIn->GetColName(iCol),pszGeomColumn) )
             continue;
 
-        if( pszGeomColumn == NULL 
-            && EQUAL(poStmt->GetColName(iCol),"Geometry")
-			&& (poStmt->GetColType(iCol) == SQL_BINARY ||
-			    poStmt->GetColType(iCol) == SQL_VARBINARY ||
-				poStmt->GetColType(iCol) == SQL_LONGVARBINARY) )
+        if( pszGeomColumn == NULL
+            && EQUAL(poStmtIn->GetColName(iCol),"Geometry")
+			&& (poStmtIn->GetColType(iCol) == SQL_BINARY ||
+			    poStmtIn->GetColType(iCol) == SQL_VARBINARY ||
+				poStmtIn->GetColType(iCol) == SQL_LONGVARBINARY) )
         {
-            pszGeomColumn = CPLStrdup(poStmt->GetColName(iCol));
+            pszGeomColumn = CPLStrdup(poStmtIn->GetColName(iCol));
             continue;
         }
-        
-        switch( poStmt->GetColType(iCol) )
+
+        switch( poStmtIn->GetColType(iCol) )
         {
           case SQL_INTEGER:
           case SQL_SMALLINT:
@@ -148,7 +150,7 @@ CPLErr OGRGeomediaLayer::BuildFeatureDefn( const char *pszLayerName,
 
           case SQL_DECIMAL:
             oField.SetType( OFTReal );
-            oField.SetPrecision( poStmt->GetColPrecision(iCol) );
+            oField.SetPrecision( poStmtIn->GetColPrecision(iCol) );
             break;
 
           case SQL_FLOAT:
@@ -199,7 +201,7 @@ void OGRGeomediaLayer::ResetReading()
 OGRFeature *OGRGeomediaLayer::GetNextFeature()
 
 {
-    for( ; TRUE; )
+    while( true )
     {
         OGRFeature      *poFeature;
 
@@ -242,11 +244,10 @@ OGRFeature *OGRGeomediaLayer::GetNextRawFeature()
 /* -------------------------------------------------------------------- */
 /*      Create a feature from the current result.                       */
 /* -------------------------------------------------------------------- */
-    int         iField;
     OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
 
     if( pszFIDColumn != NULL && poStmt->GetColId(pszFIDColumn) > -1 )
-        poFeature->SetFID( 
+        poFeature->SetFID(
             atoi(poStmt->GetColData(poStmt->GetColId(pszFIDColumn))) );
     else
         poFeature->SetFID( iNextShapeId );
@@ -257,7 +258,7 @@ OGRFeature *OGRGeomediaLayer::GetNextRawFeature()
 /* -------------------------------------------------------------------- */
 /*      Set the fields.                                                 */
 /* -------------------------------------------------------------------- */
-    for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
+    for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     {
         int iSrcField = panFieldOrdinals[iField]-1;
         const char *pszValue = poStmt->GetColData( iSrcField );
@@ -265,7 +266,7 @@ OGRFeature *OGRGeomediaLayer::GetNextRawFeature()
         if( pszValue == NULL )
             /* no value */;
         else if( poFeature->GetFieldDefnRef(iField)->GetType() == OFTBinary )
-            poFeature->SetField( iField, 
+            poFeature->SetField( iField,
                                  poStmt->GetColDataLength(iSrcField),
                                  (GByte *) pszValue );
         else
diff --git a/ogr/ogrsf_frmts/geomedia/ogrgeomediatablelayer.cpp b/ogr/ogrsf_frmts/geomedia/ogrgeomediatablelayer.cpp
index 0cedd22..16be49d 100644
--- a/ogr/ogrsf_frmts/geomedia/ogrgeomediatablelayer.cpp
+++ b/ogr/ogrsf_frmts/geomedia/ogrgeomediatablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeomediatablelayer.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrgeomediatablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGeomediaTableLayer class, access to an existing table.
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "ogr_geomedia.h"
 
-CPL_CVSID("$Id: ogrgeomediatablelayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrgeomediatablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                          OGRGeomediaTableLayer()                     */
@@ -65,7 +65,7 @@ OGRGeomediaTableLayer::~OGRGeomediaTableLayer()
 
 CPLErr OGRGeomediaTableLayer::Initialize( const char *pszTableName,
                                           const char *pszGeomCol,
-                                          OGRSpatialReference* poSRS )
+                                          OGRSpatialReference* poSRSIn )
 
 
 {
@@ -80,19 +80,19 @@ CPLErr OGRGeomediaTableLayer::Initialize( const char *pszTableName,
     CPLFree( pszFIDColumn );
     pszFIDColumn = NULL;
 
-    this->poSRS = poSRS;
+    this->poSRS = poSRSIn;
 
 /* -------------------------------------------------------------------- */
 /*      Do we have a simple primary key?                                */
 /* -------------------------------------------------------------------- */
     {
     CPLODBCStatement oGetKey( poSession );
-    
+
     if( oGetKey.GetPrimaryKeys( pszTableName ) && oGetKey.Fetch() )
     {
         pszFIDColumn = CPLStrdup(oGetKey.GetColData( 3 ));
-        
-        if( oGetKey.Fetch() ) // more than one field in key! 
+
+        if( oGetKey.Fetch() ) // more than one field in key!
         {
             CPLFree( pszFIDColumn );
             pszFIDColumn = NULL;
@@ -115,7 +115,7 @@ CPLErr OGRGeomediaTableLayer::Initialize( const char *pszTableName,
 
     if( !oGetCol.GetColumns( pszTableName ) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "GetColumns() failed on %s.\n%s",
                   pszTableName, poSession->GetLastError() );
         return CE_Failure;
@@ -127,8 +127,8 @@ CPLErr OGRGeomediaTableLayer::Initialize( const char *pszTableName,
 
     if( poFeatureDefn->GetFieldCount() == 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "No column definitions found for table '%s', layer not usable.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "No column definitions found for table '%s', layer not usable.",
                   pszTableName );
         return CE_Failure;
     }
@@ -234,16 +234,16 @@ OGRFeature *OGRGeomediaTableLayer::GetFeature( GIntBig nFeatureId )
 /*                         SetAttributeFilter()                         */
 /************************************************************************/
 
-OGRErr OGRGeomediaTableLayer::SetAttributeFilter( const char *pszQuery )
+OGRErr OGRGeomediaTableLayer::SetAttributeFilter( const char *pszQueryIn )
 
 {
-    if( (pszQuery == NULL && this->pszQuery == NULL)
-        || (pszQuery != NULL && this->pszQuery != NULL 
-            && EQUAL(pszQuery,this->pszQuery)) )
+    if( (pszQueryIn == NULL && this->pszQuery == NULL)
+        || (pszQueryIn != NULL && this->pszQuery != NULL
+            && EQUAL(pszQueryIn,this->pszQuery)) )
         return OGRERR_NONE;
 
     CPLFree( this->pszQuery );
-    this->pszQuery = pszQuery ? CPLStrdup( pszQuery ) : NULL; 
+    this->pszQuery = pszQueryIn ? CPLStrdup( pszQueryIn ) : NULL;
 
     ClearStatement();
 
@@ -267,7 +267,7 @@ int OGRGeomediaTableLayer::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCFastSpatialFilter) )
         return FALSE;
 
-    else 
+    else
         return OGRGeomediaLayer::TestCapability( pszCap );
 }
 
@@ -295,7 +295,7 @@ GIntBig OGRGeomediaTableLayer::GetFeatureCount( int bForce )
 
     if( !oStmt.ExecuteSQL() || !oStmt.Fetch() )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "GetFeatureCount() failed on query %s.\n%s",
                   oStmt.GetCommand(), poDS->GetSession()->GetLastError() );
         return OGRGeomediaLayer::GetFeatureCount(bForce);
diff --git a/ogr/ogrsf_frmts/georss/drv_georss.html b/ogr/ogrsf_frmts/georss/drv_georss.html
index 6d61669..3611d73 100644
--- a/ogr/ogrsf_frmts/georss/drv_georss.html
+++ b/ogr/ogrsf_frmts/georss/drv_georss.html
@@ -20,7 +20,14 @@ GeoRSS simple, GeoRSS GML and W3C Geo (the later being deprecated).<p>
 
 The driver can read and write documents without location information as well.<p>
 
-The default datum for GeoRSS document is the WGS84 datum (EPSG:4326). Although that GeoRSS locations are encoded in latitude-longitude order in the XML file, all coordinates reported or expected by the driver are in longitude-latitude order. The longitude/latitude order used by OGR is meant for compatibily with most of the rest of OGR drivers and utilities. For locations encoded in GML, the driver will support the srsName attribute for describing other SRS.<p>
+The default datum for GeoRSS document is the WGS84 datum
+(EPSG:4326). Although that GeoRSS locations are encoded in
+latitude-longitude order in the XML file, all coordinates reported or
+expected by the driver are in longitude-latitude order. The
+longitude/latitude order used by OGR is meant for compatibility with
+most of the rest of OGR drivers and utilities. For locations encoded
+in GML, the driver will support the srsName attribute for describing
+other SRS.<p>
 
 Simple and GML encoding support the notion of a <i>box</i> as a geometry. This will be decoded as a rectangle (Polygon geometry) in OGR Simple Feature model.<p>
 
@@ -38,10 +45,10 @@ Expat library supports reading the following built-in encodings :
 </ul>
 
 OGR 1.8.0 adds supports for Windows-1252 encoding (for previous versions, altering the encoding
-mentionned in the XML header to ISO-8859-1 might work in some cases).<p>
+mentioned in the XML header to ISO-8859-1 might work in some cases).<p>
 
 The content returned by OGR will be encoded in UTF-8, after the conversion from the
-encoding mentionned in the file header is.<p>
+encoding mentioned in the file header is.<p>
 
 If your GeoRSS file is not encoded in one of the previous encodings, it will not be parsed by the
 GeoRSS driver. You may convert it into one of the supported encoding with the <i>iconv</i> utility
@@ -69,7 +76,7 @@ The following content :
     <item>
         <title>My tile</title>
         <link>http://www.mylink.org</link>
-        <description>Cool descriprion !</description>
+        <description>Cool description !</description>
         <pubDate>Wed, 11 Jul 2007 15:39:21 GMT</pubDate>
         <guid>http://www.mylink.org/2007/07/11</guid>
         <category>Computer Science</category>
@@ -85,7 +92,7 @@ will be interpreted in the OGR SF model as :
 <pre>
   title (String) = My title
   link (String) = http://www.mylink.org
-  description (String) = Cool descriprion !
+  description (String) = Cool description !
   pubDate (DateTime) = 2007/07/11 15:39:21+00
   guid (String) = http://www.mylink.org/2007/07/11
   category (String) = Computer Science
@@ -95,7 +102,7 @@ will be interpreted in the OGR SF model as :
   myns_complexcontent (String) = <myns:subelement>Subelement</myns:subelement>
   POINT (2 49)
 </pre>
-<p> 
+<p>
 
 <h2>Creation Issues</h2>
 
@@ -134,7 +141,7 @@ will overload the following options.<p>
 <p>
 
 <p>
-When translating from a source dataset, it may be necessary to rename the field names from the source dataset to the expected RSS or ATOM attribute names, such as <title>, <description>, etc... 
+When translating from a source dataset, it may be necessary to rename the field names from the source dataset to the expected RSS or ATOM attribute names, such as <title>, <description>, etc...
 This can be done with a <a href="drv_vrt.html">OGR VRT</a> dataset, or by using the "-sql" option of the ogr2ogr utility (see <a href="http://trac.osgeo.org/gdal/wiki/rfc21_ogrsqlcast">RFC21: OGR SQL type cast and field name alias</a>)
 
 </li>
@@ -161,7 +168,7 @@ ogrinfo -ro -al input.xml
 <li>The ogr2ogr utility can be used to do GeoRSS to GeoRSS translation. For example, to translate a Atom document into a RSS document
 
 <pre>
-ogr2ogr -f GeoRSS output.xml input.xml "select link_href as link, title, content as description, author_name as author, id as guid from georss" 
+ogr2ogr -f GeoRSS output.xml input.xml "select link_href as link, title, content as description, author_name as author, id as guid from georss"
 </pre>
 <br>
 Note : in this example we map equivalent fields, from the source name to the expected name of the destination format.
diff --git a/ogr/ogrsf_frmts/georss/ogr_georss.h b/ogr/ogrsf_frmts/georss/ogr_georss.h
index bb7bb8f..ecb0095 100644
--- a/ogr/ogrsf_frmts/georss/ogr_georss.h
+++ b/ogr/ogrsf_frmts/georss/ogr_georss.h
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_GEORSS_H_INCLUDED
-#define _OGR_GEORSS_H_INCLUDED
+#ifndef OGR_GEORSS_H_INCLUDED
+#define OGR_GEORSS_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "ogr_p.h"
@@ -123,7 +123,7 @@ class OGRGeoRSSLayer : public OGRLayer
     void               AddStrToSubElementValue(const char* pszStr);
 #endif
     int                IsStandardField(const char* pszName);
-    
+
   public:
                         OGRGeoRSSLayer(const char *pszFilename,
                                     const char* layerName,
@@ -134,14 +134,14 @@ class OGRGeoRSSLayer : public OGRLayer
 
     void                ResetReading();
     OGRFeature *        GetNextFeature();
-    
+
     OGRErr              ICreateFeature( OGRFeature *poFeature );
     OGRErr              CreateField( OGRFieldDefn *poField, int bApproxOK );
 
     OGRFeatureDefn *    GetLayerDefn();
-    
+
     int                 TestCapability( const char * );
-    
+
     GIntBig             GetFeatureCount( int bForce );
 
     void                LoadSchema();
@@ -177,7 +177,7 @@ class OGRGeoRSSDataSource : public OGRDataSource
 
     /*  Export related */
     VSILFILE           *fpOutput; /* Virtual file API */
-    
+
 #ifdef HAVE_EXPAT
     OGRGeoRSSValidity   validity;
 #endif
@@ -196,27 +196,27 @@ class OGRGeoRSSDataSource : public OGRDataSource
 
     int                 Open( const char * pszFilename,
                               int bUpdate );
-    
-    int                 Create( const char *pszFilename, 
+
+    int                 Create( const char *pszFilename,
                               char **papszOptions );
-    
+
     const char*         GetName() { return pszName; }
 
     int                 GetLayerCount() { return nLayers; }
     OGRLayer*           GetLayer( int );
-    
+
     OGRLayer *          ICreateLayer( const char * pszLayerName,
                                     OGRSpatialReference *poSRS,
                                     OGRwkbGeometryType eType,
                                     char ** papszOptions );
 
     int                 TestCapability( const char * );
-    
+
     VSILFILE *          GetOutputFP() { return fpOutput; }
     OGRGeoRSSFormat     GetFormat() { return eFormat; }
     OGRGeoRSSGeomDialect GetGeomDialect() { return eGeomDialect; }
     int                 GetUseExtensions() { return bUseExtensions; }
-    
+
 #ifdef HAVE_EXPAT
     void                startElementValidateCbk(const char *pszName, const char **ppszAttr);
     void                dataHandlerValidateCbk(const char *data, int nLen);
diff --git a/ogr/ogrsf_frmts/georss/ogrgeorssdatasource.cpp b/ogr/ogrsf_frmts/georss/ogrgeorssdatasource.cpp
index 209dde9..695a7a6 100644
--- a/ogr/ogrsf_frmts/georss/ogrgeorssdatasource.cpp
+++ b/ogr/ogrsf_frmts/georss/ogrgeorssdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeorssdatasource.cpp 28636 2015-03-06 19:18:43Z rouault $
+ * $Id: ogrgeorssdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  GeoRSS Translator
  * Purpose:  Implements OGRGeoRSSDataSource class
@@ -32,27 +32,30 @@
 #include "cpl_string.h"
 #include "cpl_csv.h"
 
-CPL_CVSID("$Id: ogrgeorssdatasource.cpp 28636 2015-03-06 19:18:43Z rouault $");
+CPL_CVSID("$Id: ogrgeorssdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                          OGRGeoRSSDataSource()                          */
 /************************************************************************/
 
-OGRGeoRSSDataSource::OGRGeoRSSDataSource()
-
-{
-    papoLayers = NULL;
-    nLayers = 0;
-
-    fpOutput = NULL;
-
-    pszName = NULL;
-
-    eFormat = GEORSS_RSS;
-    eGeomDialect = GEORSS_SIMPLE;
-    bUseExtensions = FALSE;
-    bWriteHeaderAndFooter = TRUE;
-}
+OGRGeoRSSDataSource::OGRGeoRSSDataSource() :
+    pszName(NULL),
+    papoLayers(NULL),
+    nLayers(0),
+    fpOutput(NULL),
+#ifdef HAVE_EXPAT
+    validity(GEORSS_VALIDITY_UNKNOWN),
+#endif
+    eFormat(GEORSS_RSS),
+    eGeomDialect(GEORSS_SIMPLE),
+    bUseExtensions(FALSE),
+    bWriteHeaderAndFooter(TRUE)
+#ifdef HAVE_EXPAT
+    ,
+    oCurrentParser(NULL),
+    nDataHandlerCounter(0)
+#endif
+{ }
 
 /************************************************************************/
 /*                         ~OGRGeoRSSDataSource()                          */
@@ -139,7 +142,7 @@ OGRLayer * OGRGeoRSSDataSource::ICreateLayer( const char * pszLayerName,
     nLayers++;
     papoLayers = (OGRGeoRSSLayer **) CPLRealloc(papoLayers, nLayers * sizeof(OGRGeoRSSLayer*));
     papoLayers[nLayers-1] = new OGRGeoRSSLayer( pszName, pszLayerName, this, poSRS, TRUE );
-    
+
     return papoLayers[nLayers-1];
 }
 
@@ -148,22 +151,22 @@ OGRLayer * OGRGeoRSSDataSource::ICreateLayer( const char * pszLayerName,
 /*                startElementValidateCbk()                             */
 /************************************************************************/
 
-void OGRGeoRSSDataSource::startElementValidateCbk(const char *pszName, const char **ppszAttr)
+void OGRGeoRSSDataSource::startElementValidateCbk(const char *pszNameIn, const char **ppszAttr)
 {
     if (validity == GEORSS_VALIDITY_UNKNOWN)
     {
-        if (strcmp(pszName, "rss") == 0)
+        if (strcmp(pszNameIn, "rss") == 0)
         {
             validity = GEORSS_VALIDITY_VALID;
             eFormat = GEORSS_RSS;
         }
-        else if (strcmp(pszName, "feed") == 0 ||
-                 strcmp(pszName, "atom:feed") == 0)
+        else if (strcmp(pszNameIn, "feed") == 0 ||
+                 strcmp(pszNameIn, "atom:feed") == 0)
         {
             validity = GEORSS_VALIDITY_VALID;
             eFormat = GEORSS_ATOM;
         }
-        else if (strcmp(pszName, "rdf:RDF") == 0)
+        else if (strcmp(pszNameIn, "rdf:RDF") == 0)
         {
             const char** ppszIter = ppszAttr;
             while(*ppszIter)
@@ -235,20 +238,20 @@ int OGRGeoRSSDataSource::Open( const char * pszFilename, int bUpdateIn)
     VSILFILE* fp = VSIFOpenL(pszFilename, "r");
     if (fp == NULL)
         return FALSE;
-    
+
     validity = GEORSS_VALIDITY_UNKNOWN;
-    
+
     XML_Parser oParser = OGRCreateExpatXMLParser();
     XML_SetUserData(oParser, this);
     XML_SetElementHandler(oParser, ::startElementValidateCbk, NULL);
     XML_SetCharacterDataHandler(oParser, ::dataHandlerValidateCbk);
     oCurrentParser = oParser;
-    
+
     char aBuf[BUFSIZ];
     int nDone;
     unsigned int nLen;
     int nCount = 0;
-    
+
     /* Begin to parse the file and look for the <rss> or <feed> element */
     /* It *MUST* be the first element of an XML file */
     /* So once we have read the first element, we know if we can */
@@ -292,11 +295,11 @@ int OGRGeoRSSDataSource::Open( const char * pszFilename, int bUpdateIn)
                 break;
         }
     } while (!nDone && nLen > 0 );
-    
+
     XML_ParserFree(oParser);
-    
+
     VSIFCloseL(fp);
-    
+
     if (validity == GEORSS_VALIDITY_VALID)
     {
         CPLDebug("GeoRSS", "%s seems to be a GeoRSS file.", pszFilename);
@@ -330,7 +333,7 @@ int OGRGeoRSSDataSource::Open( const char * pszFilename, int bUpdateIn)
 /*                               Create()                               */
 /************************************************************************/
 
-int OGRGeoRSSDataSource::Create( const char *pszFilename, 
+int OGRGeoRSSDataSource::Create( const char *pszFilename,
                                  char **papszOptions )
 {
     if( fpOutput != NULL)
@@ -354,7 +357,7 @@ int OGRGeoRSSDataSource::Create( const char *pszFilename,
                  pszFilename);
         return FALSE;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create the output file.                                         */
 /* -------------------------------------------------------------------- */
@@ -363,8 +366,8 @@ int OGRGeoRSSDataSource::Create( const char *pszFilename,
     fpOutput = VSIFOpenL( pszFilename, "w" );
     if( fpOutput == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Failed to create GeoRSS file %s.", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to create GeoRSS file %s.",
                   pszFilename );
         return FALSE;
     }
@@ -400,7 +403,7 @@ int OGRGeoRSSDataSource::Create( const char *pszFilename,
     }
 
     const char* pszWriteHeaderAndFooter = CSLFetchNameValue(papszOptions, "WRITE_HEADER_AND_FOOTER");
-    if (pszWriteHeaderAndFooter && CSLTestBoolean(pszWriteHeaderAndFooter) == FALSE)
+    if (pszWriteHeaderAndFooter && CPLTestBool(pszWriteHeaderAndFooter) == FALSE)
     {
         bWriteHeaderAndFooter = FALSE;
         return TRUE;
@@ -451,7 +454,7 @@ int OGRGeoRSSDataSource::Create( const char *pszFilename,
     }
 
     const char* pszUseExtensions = CSLFetchNameValue( papszOptions, "USE_EXTENSIONS");
-    bUseExtensions =  (pszUseExtensions && CSLTestBoolean(pszUseExtensions));
+    bUseExtensions = pszUseExtensions && CPLTestBool(pszUseExtensions);
 
 /* -------------------------------------------------------------------- */
 /*     Output header of GeoRSS file.                                       */
diff --git a/ogr/ogrsf_frmts/georss/ogrgeorssdriver.cpp b/ogr/ogrsf_frmts/georss/ogrgeorssdriver.cpp
index a661123..de36da8 100644
--- a/ogr/ogrsf_frmts/georss/ogrgeorssdriver.cpp
+++ b/ogr/ogrsf_frmts/georss/ogrgeorssdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeorssdriver.cpp 28636 2015-03-06 19:18:43Z rouault $
+ * $Id: ogrgeorssdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  GeoRSS Translator
  * Purpose:  Implements OGRGeoRSSDriver.
@@ -30,7 +30,7 @@
 #include "ogr_georss.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrgeorssdriver.cpp 28636 2015-03-06 19:18:43Z rouault $");
+CPL_CVSID("$Id: ogrgeorssdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
 
 /************************************************************************/
 /*                                Open()                                */
@@ -102,20 +102,18 @@ void RegisterOGRGeoRSS()
 {
     if (! GDAL_CHECK_VERSION("OGR/GeoRSS driver"))
         return;
-    GDALDriver  *poDriver;
 
-    if( GDALGetDriverByName( "GeoRSS" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    if( GDALGetDriverByName( "GeoRSS" ) != NULL )
+        return;
+
+    GDALDriver  *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "GeoRSS" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "GeoRSS" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_georss.html" );
+    poDriver->SetDescription( "GeoRSS" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "GeoRSS" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_georss.html" );
 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "  <Option name='FORMAT' type='string-select' description='whether the document must be in RSS 2.0 or Atom 1.0 format' default='RSS'>"
 "    <Value>RSS</Value>"
@@ -136,14 +134,13 @@ void RegisterOGRGeoRSS()
 "  <Option name='AUTHOR_NAME' type='string' description='(ATOM only) value put inside the <author><name> element in the header'/>"
 "  <Option name='ID' type='string' description='(ATOM only) value put inside the <id> element in the header.'/>"
 "</CreationOptionList>");
-        poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST, "<LayerCreationOptionList/>");
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+                               "<LayerCreationOptionList/>");
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->pfnOpen = OGRGeoRSSDriverOpen;
+    poDriver->pfnCreate = OGRGeoRSSDriverCreate;
+    poDriver->pfnDelete = OGRGeoRSSDriverDelete;
 
-        poDriver->pfnOpen = OGRGeoRSSDriverOpen;
-        poDriver->pfnCreate = OGRGeoRSSDriverCreate;
-        poDriver->pfnDelete = OGRGeoRSSDriverDelete;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/georss/ogrgeorsslayer.cpp b/ogr/ogrsf_frmts/georss/ogrgeorsslayer.cpp
index 66818c4..40a60ea 100644
--- a/ogr/ogrsf_frmts/georss/ogrgeorsslayer.cpp
+++ b/ogr/ogrsf_frmts/georss/ogrgeorsslayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeorsslayer.cpp 28900 2015-04-14 09:40:34Z rouault $
+ * $Id: ogrgeorsslayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  GeoRSS Translator
  * Purpose:  Implements OGRGeoRSSLayer class.
@@ -27,52 +27,55 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_georss.h"
 #include "cpl_conv.h"
 #include "cpl_minixml.h"
 #include "ogr_api.h"
+#include "ogr_georss.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrgeorsslayer.cpp 28900 2015-04-14 09:40:34Z rouault $");
+CPL_CVSID("$Id: ogrgeorsslayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
-static const char* apszAllowedATOMFieldNamesWithSubElements[] = { "author", "contributor", NULL };
+static const char* const apszAllowedATOMFieldNamesWithSubElements[] =
+    { "author", "contributor", NULL };
 
 static
-const char* apszAllowedRSSFieldNames[] = {  "title", "link", "description", "author",
-                                            "category", "category_domain",
-                                            "comments",
-                                            "enclosure_url", "enclosure_length", "enclosure_type",
-                                            "guid", "guid_isPermaLink",
-                                            "pubDate",
-                                            "source", "source_url", NULL};
+const char* const apszAllowedRSSFieldNames[] =
+    {  "title", "link", "description", "author",
+       "category", "category_domain",
+       "comments",
+       "enclosure_url", "enclosure_length", "enclosure_type",
+       "guid", "guid_isPermaLink",
+       "pubDate",
+       "source", "source_url", NULL};
 
 static
-const char* apszAllowedATOMFieldNames[] = { "category_term", "category_scheme", "category_label",
-                                            "content", "content_type", "content_xml_lang", "content_xml_base",
-                                            "summary", "summary_type", "summary_xml_lang", "summary_xml_base",
-                                            "author_name", "author_uri", "author_email",
-                                            "contributor_name", "contributor_uri", "contributor_email",
-                                            "link_href", "link_rel", "link_type", "link_length",
-                                            "id", "published", "rights", "source",
-                                            "title", "updated", NULL };
-
-#define IS_LAT_ELEMENT(pszName) (strncmp(pszName, "geo:lat", strlen("geo:lat")) == 0 || \
-                                 strncmp(pszName, "icbm:lat", strlen("icbm:lat")) == 0 || \
-                                 strncmp(pszName, "geourl:lat", strlen("geourl:lat")) == 0)
-
-#define IS_LON_ELEMENT(pszName) (strncmp(pszName, "geo:lon", strlen("geo:lon")) == 0 || \
-                                 strncmp(pszName, "icbm:lon", strlen("icbm:lon")) == 0 || \
-                                 strncmp(pszName, "geourl:lon", strlen("geourl:lon")) == 0)
+const char* const apszAllowedATOMFieldNames[] =
+    { "category_term", "category_scheme", "category_label",
+      "content", "content_type", "content_xml_lang", "content_xml_base",
+      "summary", "summary_type", "summary_xml_lang", "summary_xml_base",
+      "author_name", "author_uri", "author_email",
+      "contributor_name", "contributor_uri", "contributor_email",
+      "link_href", "link_rel", "link_type", "link_length",
+      "id", "published", "rights", "source",
+      "title", "updated", NULL };
+
+#define IS_LAT_ELEMENT(pszName) (STARTS_WITH(pszName, "geo:lat") || \
+                                 STARTS_WITH(pszName, "icbm:lat") || \
+                                 STARTS_WITH(pszName, "geourl:lat"))
+
+#define IS_LON_ELEMENT(pszName) (STARTS_WITH(pszName, "geo:lon") || \
+                                 STARTS_WITH(pszName, "icbm:lon") || \
+                                 STARTS_WITH(pszName, "geourl:lon"))
 
 #define IS_GEO_ELEMENT(pszName) (strcmp(pszName, "georss:point") == 0 || \
                                  strcmp(pszName, "georss:line") == 0 || \
                                  strcmp(pszName, "georss:box") == 0 || \
                                  strcmp(pszName, "georss:polygon") == 0 || \
                                  strcmp(pszName, "georss:where") == 0 || \
-                                 strncmp(pszName, "gml:", strlen("gml:")) == 0 || \
-                                 strncmp(pszName, "geo:", strlen("geo:")) == 0 || \
-                                 strncmp(pszName, "icbm:", strlen("icbm:")) == 0 || \
-                                 strncmp(pszName, "geourl:", strlen("geourl:")) == 0)
+                                 STARTS_WITH(pszName, "gml:") || \
+                                 STARTS_WITH(pszName, "geo:") || \
+                                 STARTS_WITH(pszName, "icbm:") || \
+                                 STARTS_WITH(pszName, "geourl:"))
 
 /************************************************************************/
 /*                            OGRGeoRSSLayer()                          */
@@ -80,54 +83,50 @@ const char* apszAllowedATOMFieldNames[] = { "category_term", "category_scheme",
 
 OGRGeoRSSLayer::OGRGeoRSSLayer( const char* pszFilename,
                                 const char* pszLayerName,
-                                OGRGeoRSSDataSource* poDS,
+                                OGRGeoRSSDataSource* poDS_,
                                 OGRSpatialReference *poSRSIn,
-                                int bWriteMode)
-
+                                int bWriteMode_) :
+    poFeatureDefn(NULL), poSRS(poSRSIn), poDS(poDS_), eFormat(GEORSS_ATOM),
+    bWriteMode(bWriteMode_), nTotalFeatureCount(0), eof(FALSE), nNextFID(0),
+    fpGeoRSS(NULL), bHasReadSchema(FALSE),
+#ifdef HAVE_EXPAT
+    oParser(NULL), oSchemaParser(NULL),
+#endif
+    poGlobalGeom(NULL), bStopParsing(FALSE), bInFeature(FALSE),
+    hasFoundLat(FALSE), hasFoundLon(FALSE),
+#ifdef HAVE_EXPAT
+    latVal(0.0), lonVal(0.0),
+#endif
+    pszSubElementName(NULL), pszSubElementValue(NULL), nSubElementValueLen(0),
+#ifdef HAVE_EXPAT
+    iCurrentField(0),
+#endif
+    bInSimpleGeometry(FALSE), bInGMLGeometry(FALSE), bInGeoLat(FALSE),
+    bInGeoLong(FALSE),
+#ifdef HAVE_EXPAT
+    bFoundGeom(FALSE), bSameSRS(FALSE),
+#endif
+    eGeomType(wkbUnknown), pszGMLSRSName(NULL), bInTagWithSubTag(0),
+    pszTagWithSubTag(NULL), currentDepth(0), featureDepth(0), geometryDepth(0),
+#ifdef HAVE_EXPAT
+    currentFieldDefn(NULL), nWithoutEventCounter(0), nDataHandlerCounter(0),
+#endif
+    setOfFoundFields(NULL), poFeature(NULL),
+    ppoFeatureTab(NULL), nFeatureTabLength(0), nFeatureTabIndex(0)
 {
-    eof = FALSE;
-    nNextFID = 0;
-
-    this->poDS = poDS;
-    this->bWriteMode = bWriteMode;
-
     eFormat = poDS->GetFormat();
 
     poFeatureDefn = new OGRFeatureDefn( pszLayerName );
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
 
-    poSRS = poSRSIn;
     if (poSRS)
     {
         poSRS->Reference();
         poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
     }
 
-    nTotalFeatureCount = 0;
-
-    ppoFeatureTab = NULL;
-    nFeatureTabIndex = 0;
-    nFeatureTabLength = 0;
-    pszSubElementName = NULL;
-    pszSubElementValue = NULL;
-    nSubElementValueLen = 0;
-    pszGMLSRSName = NULL;
-    pszTagWithSubTag = NULL;
-    bStopParsing = FALSE;
-    bHasReadSchema = FALSE;
-    setOfFoundFields = NULL;
-    poGlobalGeom = NULL;
-    hasFoundLat = FALSE;
-    hasFoundLon = FALSE;
-
-    poFeature = NULL;
-
-#ifdef HAVE_EXPAT
-    oParser = NULL;
-#endif
-
-    if (bWriteMode == FALSE)
+    if (!bWriteMode)
     {
         fpGeoRSS = VSIFOpenL( pszFilename, "r" );
         if( fpGeoRSS == NULL )
@@ -136,8 +135,6 @@ OGRGeoRSSLayer::OGRGeoRSSLayer( const char* pszFilename,
             return;
         }
     }
-    else
-        fpGeoRSS = NULL;
 
     ResetReading();
 }
@@ -154,8 +151,8 @@ OGRGeoRSSLayer::~OGRGeoRSSLayer()
         XML_ParserFree(oParser);
 #endif
     poFeatureDefn->Release();
-    
-    if( poSRS != NULL )
+
+    if(poSRS)
         poSRS->Release();
 
     CPLFree(pszSubElementName);
@@ -167,8 +164,7 @@ OGRGeoRSSLayer::~OGRGeoRSSLayer()
     if (poGlobalGeom)
         delete poGlobalGeom;
 
-    int i;
-    for(i=nFeatureTabIndex;i<nFeatureTabLength;i++)
+    for(int i=nFeatureTabIndex;i<nFeatureTabLength;i++)
         delete ppoFeatureTab[i];
     CPLFree(ppoFeatureTab);
 
@@ -232,7 +228,7 @@ void OGRGeoRSSLayer::ResetReading()
 #ifdef HAVE_EXPAT
         if (oParser)
             XML_ParserFree(oParser);
-        
+
         oParser = OGRCreateExpatXMLParser();
         XML_SetElementHandler(oParser, ::startElementCbk, ::endElementCbk);
         XML_SetCharacterDataHandler(oParser, ::dataHandlerCbk);
@@ -259,8 +255,7 @@ void OGRGeoRSSLayer::ResetReading()
         CPLHashSetDestroy(setOfFoundFields);
     setOfFoundFields = NULL;
 
-    int i;
-    for(i=nFeatureTabIndex;i<nFeatureTabLength;i++)
+    for( int i=nFeatureTabIndex; i < nFeatureTabLength; i++ )
         delete ppoFeatureTab[i];
     CPLFree(ppoFeatureTab);
     nFeatureTabIndex = 0;
@@ -286,12 +281,11 @@ void OGRGeoRSSLayer::ResetReading()
 
 void OGRGeoRSSLayer::AddStrToSubElementValue(const char* pszStr)
 {
-    int len = strlen(pszStr);
+    int len = static_cast<int>(strlen(pszStr));
     char* pszNewSubElementValue = (char*)
-            VSIRealloc(pszSubElementValue, nSubElementValueLen + len + 1);
+            VSI_REALLOC_VERBOSE(pszSubElementValue, nSubElementValueLen + len + 1);
     if (pszNewSubElementValue == NULL)
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
         XML_StopParser(oParser, XML_FALSE);
         bStopParsing = TRUE;
         return;
@@ -310,8 +304,7 @@ void OGRGeoRSSLayer::AddStrToSubElementValue(const char* pszStr)
 static char* OGRGeoRSS_GetOGRCompatibleTagName(const char* pszName)
 {
     char* pszModName = CPLStrdup(pszName);
-    int i;
-    for(i=0;pszModName[i] != 0;i++)
+    for( int i=0; pszModName[i] != 0; i++ )
     {
         if (pszModName[i] == ':')
             pszModName[i] = '_';
@@ -325,8 +318,9 @@ static char* OGRGeoRSS_GetOGRCompatibleTagName(const char* pszName)
 
 static int OGRGeoRSSLayerATOMTagHasSubElement(const char* pszName)
 {
-    unsigned int i;
-    for(i=0;apszAllowedATOMFieldNamesWithSubElements[i] != NULL;i++)
+    for( unsigned int i=0;
+         apszAllowedATOMFieldNamesWithSubElements[i] != NULL;
+         i++ )
     {
         if (strcmp(pszName, apszAllowedATOMFieldNamesWithSubElements[i]) == 0)
             return TRUE;
@@ -414,7 +408,7 @@ void OGRGeoRSSLayer::startElementCbk(const char *pszName, const char **ppszAttr)
     }
     else if (bInSimpleGeometry || bInGeoLat || bInGeoLong)
     {
-        /* Shouldn't happen for a valid document */
+        /* Should not happen for a valid document. */
     }
     else if (IS_LAT_ELEMENT(pszName))
     {
@@ -482,7 +476,7 @@ void OGRGeoRSSLayer::startElementCbk(const char *pszName, const char **ppszAttr)
         nSubElementValueLen = 0;
         iCurrentField = -1;
 
-        if( pszName != pszNoNSName && strncmp(pszName, "atom:", 5) == 0 )
+        if( pszName != pszNoNSName && STARTS_WITH(pszName, "atom:") )
             pszName = pszNoNSName;
 
         pszSubElementName = CPLStrdup(pszName);
@@ -553,17 +547,15 @@ void OGRGeoRSSLayer::startElementCbk(const char *pszName, const char **ppszAttr)
 
 static void OGRGeoRSSLayerTrimLeadingAndTrailingSpaces(char* pszStr)
 {
-    int i;
-
     /* Trim leading spaces, tabs and newlines */
-    i = 0;
+    int i = 0;
     while(pszStr[i] != '\0' &&
           (pszStr[i] == ' ' || pszStr[i] == '\t' || pszStr[i] == '\n'))
         i ++;
     memmove(pszStr, pszStr + i, strlen(pszStr + i) + 1);
 
     /* Trim trailing spaces, tabs and newlines */
-    i = strlen(pszStr) - 1;
+    i = static_cast<int>(strlen(pszStr)) - 1;
     while(i >= 0 &&
           (pszStr[i] == ' ' || pszStr[i] == '\t' || pszStr[i] == '\n'))
     {
@@ -664,7 +656,7 @@ void OGRGeoRSSLayer::endElementCbk(const char *pszName)
         else
         {
             pszSubElementValue[nSubElementValueLen] = 0;
-            CPLAssert(strncmp(pszName, "gml:", 4) == 0);
+            CPLAssert(STARTS_WITH(pszName, "gml:"));
             poGeom = (OGRGeometry*) OGR_G_CreateFromGML(pszSubElementValue);
 
             if (poGeom != NULL && !poGeom->IsEmpty() )
@@ -692,7 +684,7 @@ void OGRGeoRSSLayer::endElementCbk(const char *pszName)
     {
         if (currentDepth > geometryDepth)
         {
-            /* Shouldn't happen for a valid document */
+            /* Should not happen for a valid document */
         }
         else
         {
@@ -728,8 +720,7 @@ void OGRGeoRSSLayer::endElementCbk(const char *pszName)
                 {
                     OGRLineString* poLineString = new OGRLineString ();
                     poGeom = poLineString;
-                    int i;
-                    for(i=0;i<nTokens;i+=2)
+                    for( int i = 0; i<nTokens; i+=2 )
                     {
                         poLineString->addPoint( CPLAtof(papszTokens[i+1]),
                                               CPLAtof(papszTokens[i]) );
@@ -743,8 +734,7 @@ void OGRGeoRSSLayer::endElementCbk(const char *pszName)
                     poPolygon->addRingDirectly(poLinearRing);
                     if (strcmp(pszName, "georss:polygon") == 0)
                     {
-                        int i;
-                        for(i=0;i<nTokens;i+=2)
+                        for( int i=0; i < nTokens; i+=2 )
                         {
                             poLinearRing->addPoint( CPLAtof(papszTokens[i+1]),
                                                     CPLAtof(papszTokens[i]) );
@@ -870,11 +860,10 @@ void OGRGeoRSSLayer::dataHandlerCbk(const char *data, int nLen)
         bInGeoLat == TRUE || bInGeoLong == TRUE ||
         pszSubElementName != NULL)
     {
-        char* pszNewSubElementValue = (char*) VSIRealloc(pszSubElementValue,
+        char* pszNewSubElementValue = (char*) VSI_REALLOC_VERBOSE(pszSubElementValue,
                                                nSubElementValueLen + nLen + 1);
         if (pszNewSubElementValue == NULL)
         {
-            CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
             XML_StopParser(oSchemaParser, XML_FALSE);
             bStopParsing = TRUE;
             return;
@@ -913,12 +902,12 @@ OGRFeature *OGRGeoRSSLayer::GetNextFeature()
     {
         return ppoFeatureTab[nFeatureTabIndex++];
     }
-    
+
     if (VSIFEofL(fpGeoRSS))
         return NULL;
-    
+
     char aBuf[BUFSIZ];
-    
+
     CPLFree(ppoFeatureTab);
     ppoFeatureTab = NULL;
     nFeatureTabLength = 0;
@@ -941,7 +930,7 @@ OGRFeature *OGRGeoRSSLayer::GetNextFeature()
             bStopParsing = TRUE;
         }
     } while (!nDone && !bStopParsing && nFeatureTabLength == 0);
-    
+
     return (nFeatureTabLength) ? ppoFeatureTab[nFeatureTabIndex++] : NULL;
 #else
     return NULL;
@@ -953,10 +942,9 @@ OGRFeature *OGRGeoRSSLayer::GetNextFeature()
 /************************************************************************/
 
 static int OGRGeoRSSLayerIsStandardFieldInternal(const char* pszName,
-                                                 const char** papszNames)
+                                                 const char* const * papszNames)
 {
-    unsigned int i;
-    for( i = 0; papszNames[i] != NULL; i++)
+    for( unsigned int i = 0; papszNames[i] != NULL; i++)
     {
         if (strcmp(pszName, papszNames[i]) == 0)
         {
@@ -966,10 +954,10 @@ static int OGRGeoRSSLayerIsStandardFieldInternal(const char* pszName,
         const char* pszUnderscore = strchr(papszNames[i], '_');
         if (pszUnderscore == NULL)
         {
-            int nLen = strlen(papszNames[i]);
+            size_t nLen = strlen(papszNames[i]);
             if (strncmp(pszName, papszNames[i], nLen) == 0)
             {
-                int k = nLen;
+                size_t k = nLen;
                 while(pszName[k] >= '0' && pszName[k] <= '9')
                     k++;
                 if (pszName[k] == '\0')
@@ -978,10 +966,10 @@ static int OGRGeoRSSLayerIsStandardFieldInternal(const char* pszName,
         }
         else
         {
-            int nLen = pszUnderscore - papszNames[i];
+            size_t nLen = static_cast<size_t>(pszUnderscore - papszNames[i]);
             if (strncmp(pszName, papszNames[i], nLen) == 0)
             {
-                int k = nLen;
+                size_t k = nLen;
                 while(pszName[k] >= '0' && pszName[k] <= '9')
                     k++;
                 if (pszName[k] == '_' && strcmp(pszName + k, pszUnderscore) == 0)
@@ -1065,7 +1053,7 @@ static void OGRGeoRSSLayerSplitComposedField(const char* pszName,
 static void OGRGeoRSSLayerWriteSimpleElement(VSILFILE* fp,
                                              const char* pszElementName,
                                              const char* pszNumber,
-                                             const char** papszNames,
+                                             const char* const * papszNames,
                                              OGRFeatureDefn* poFeatureDefn,
                                              OGRFeature* poFeature)
 {
@@ -1115,12 +1103,12 @@ static void OGRGeoRSSLayerWriteSimpleElement(VSILFILE* fp,
 /*                           ICreateFeature()                            */
 /************************************************************************/
 
-OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeature )
+OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeatureIn )
 
 {
     VSILFILE* fp = poDS->GetOutputFP();
     if (fp == NULL)
-        return CE_Failure;
+        return OGRERR_FAILURE;
 
     nNextFID ++;
 
@@ -1132,8 +1120,8 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeature )
 
         VSIFPrintfL(fp, "    <item>\n");
 
-        if ((iFieldTitle == -1 || poFeature->IsFieldSet( iFieldTitle ) == FALSE) &&
-            (iFieldDescription == -1 || poFeature->IsFieldSet( iFieldDescription ) == FALSE))
+        if ((iFieldTitle == -1 || poFeatureIn->IsFieldSet( iFieldTitle ) == FALSE) &&
+            (iFieldDescription == -1 || poFeatureIn->IsFieldSet( iFieldDescription ) == FALSE))
         {
             VSIFPrintfL(fp, "      <title>Feature %d</title>\n", nNextFID);
         }
@@ -1146,17 +1134,17 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeature )
         int iFieldTitle = poFeatureDefn->GetFieldIndex( "title" );
         int iFieldUpdated = poFeatureDefn->GetFieldIndex( "updated" );
 
-        if (iFieldId == -1 || poFeature->IsFieldSet( iFieldId ) == FALSE)
+        if (iFieldId == -1 || poFeatureIn->IsFieldSet( iFieldId ) == FALSE)
         {
             VSIFPrintfL(fp, "      <id>Feature %d</id>\n", nNextFID);
         }
 
-        if (iFieldTitle == -1 || poFeature->IsFieldSet( iFieldTitle ) == FALSE)
+        if (iFieldTitle == -1 || poFeatureIn->IsFieldSet( iFieldTitle ) == FALSE)
         {
             VSIFPrintfL(fp, "      <title>Title for feature %d</title>\n", nNextFID);
         }
 
-        if (iFieldUpdated == -1 || poFeature->IsFieldSet(iFieldUpdated ) == FALSE)
+        if (iFieldUpdated == -1 || poFeatureIn->IsFieldSet(iFieldUpdated ) == FALSE)
         {
             VSIFPrintfL(fp, "      <updated>2009-01-01T00:00:00Z</updated>\n");
         }
@@ -1170,7 +1158,7 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeature )
         OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( i );
         const char* pszName = poFieldDefn->GetNameRef();
 
-        if ( ! poFeature->IsFieldSet( i ) )
+        if ( ! poFeatureIn->IsFieldSet( i ) )
             continue;
 
         char* pszElementName;
@@ -1183,8 +1171,9 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeature )
         /* <author><name>...</name><uri>...</uri></author */
         if (eFormat == GEORSS_ATOM)
         {
-            unsigned int k;
-            for (k=0;apszAllowedATOMFieldNamesWithSubElements[k] != NULL;k++)
+            for( unsigned int k=0;
+                 apszAllowedATOMFieldNamesWithSubElements[k] != NULL;
+                 k++ )
             {
                 if (strcmp(pszElementName, apszAllowedATOMFieldNamesWithSubElements[k]) == 0 &&
                     pszAttributeName != NULL)
@@ -1195,11 +1184,10 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeature )
 
                     VSIFPrintfL(fp, "      <%s>\n", pszElementName);
 
-                    int j;
-                    for(j = i; j < nFieldCount; j ++)
+                    for( int j = i; j < nFieldCount; j++ )
                     {
                         poFieldDefn = poFeatureDefn->GetFieldDefn( j );
-                        if ( ! poFeature->IsFieldSet( j ) )
+                        if ( ! poFeatureIn->IsFieldSet( j ) )
                             continue;
 
                         char* pszElementName2;
@@ -1214,7 +1202,7 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeature )
                             pbUsed[j] = TRUE;
 
                             char* pszValue =
-                                    OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( j ));
+                                    OGRGetXML_UTF8_EscapedString(poFeatureIn->GetFieldAsString( j ));
                             VSIFPrintfL(fp, "        <%s>%s</%s>\n", pszAttributeName2, pszValue, pszAttributeName2);
                             CPLFree(pszValue);
                         }
@@ -1237,7 +1225,7 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeature )
         else if (eFormat == GEORSS_RSS &&
             strcmp(pszName, "pubDate") == 0)
         {
-            const OGRField* psField = poFeature->GetRawFieldRef(i);
+            const OGRField* psField = poFeatureIn->GetRawFieldRef(i);
             char* pszDate = OGRGetRFC822DateTime(psField);
             VSIFPrintfL(fp, "      <%s>%s</%s>\n",
                     pszName, pszDate, pszName);
@@ -1246,7 +1234,7 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeature )
         else if (eFormat == GEORSS_ATOM &&
                  (strcmp(pszName, "updated") == 0 || strcmp(pszName, "published") == 0))
         {
-            const OGRField* psField = poFeature->GetRawFieldRef(i);
+            const OGRField* psField = poFeatureIn->GetRawFieldRef(i);
             char* pszDate = OGRGetXMLDateTime(psField);
             VSIFPrintfL(fp, "      <%s>%s</%s>\n",
                     pszName, pszDate, pszName);
@@ -1254,7 +1242,7 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeature )
         }
         else if (strcmp(pszName, "dc_date") == 0)
         {
-            const OGRField* psField = poFeature->GetRawFieldRef(i);
+            const OGRField* psField = poFeatureIn->GetRawFieldRef(i);
             char* pszDate = OGRGetXMLDateTime(psField);
             VSIFPrintfL(fp, "      <%s>%s</%s>\n",
                     "dc:date", pszDate, "dc:date");
@@ -1269,7 +1257,7 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeature )
             if (pszAttributeName == NULL)
             {
                 OGRGeoRSSLayerWriteSimpleElement(fp, pszElementName, pszNumber,
-                                       apszAllowedRSSFieldNames, poFeatureDefn, poFeature);
+                                       apszAllowedRSSFieldNames, poFeatureDefn, poFeatureIn);
             }
         }
         /* RSS field with attribute only */
@@ -1279,7 +1267,7 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeature )
             if (pszAttributeName != NULL && strcmp(pszAttributeName, "url") == 0)
             {
                 OGRGeoRSSLayerWriteSimpleElement(fp, pszElementName, pszNumber,
-                                       apszAllowedRSSFieldNames, poFeatureDefn, poFeature);
+                                       apszAllowedRSSFieldNames, poFeatureDefn, poFeatureIn);
             }
         }
         /* ATOM fields with attribute only */
@@ -1291,12 +1279,12 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeature )
                  (strcmp(pszElementName, "link") == 0 && strcmp(pszAttributeName, "href") == 0)))
             {
                 OGRGeoRSSLayerWriteSimpleElement(fp, pszElementName, pszNumber,
-                                       apszAllowedATOMFieldNames, poFeatureDefn, poFeature);
+                                       apszAllowedATOMFieldNames, poFeatureDefn, poFeatureIn);
             }
         }
         else if (eFormat == GEORSS_ATOM &&
-                 (strncmp(pszName, "content", strlen("content")) == 0 ||
-                  strncmp(pszName, "summary", strlen("summary")) == 0))
+                 (STARTS_WITH(pszName, "content") ||
+                  STARTS_WITH(pszName, "summary")))
         {
             char* pszFieldName;
             int iIndex;
@@ -1307,11 +1295,11 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeature )
                 int bIsXHTML = FALSE;
                 pszFieldName = CPLStrdup(CPLSPrintf("%s_%s", pszName, "type"));
                 iIndex = poFeatureDefn->GetFieldIndex(pszFieldName);
-                if (iIndex != -1 && poFeature->IsFieldSet( iIndex ))
+                if (iIndex != -1 && poFeatureIn->IsFieldSet( iIndex ))
                 {
-                    bIsXHTML = strcmp(poFeature->GetFieldAsString( iIndex ), "xhtml") == 0;
+                    bIsXHTML = strcmp(poFeatureIn->GetFieldAsString( iIndex ), "xhtml") == 0;
                     char* pszValue =
-                            OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( iIndex ));
+                            OGRGetXML_UTF8_EscapedString(poFeatureIn->GetFieldAsString( iIndex ));
                     VSIFPrintfL(fp, " %s=\"%s\"", "type", pszValue);
                     CPLFree(pszValue);
                 }
@@ -1319,10 +1307,10 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeature )
 
                 pszFieldName = CPLStrdup(CPLSPrintf("%s_%s", pszName, "xml_lang"));
                 iIndex = poFeatureDefn->GetFieldIndex(pszFieldName);
-                if (iIndex != -1 && poFeature->IsFieldSet( iIndex ))
+                if (iIndex != -1 && poFeatureIn->IsFieldSet( iIndex ))
                 {
                     char* pszValue =
-                            OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( iIndex ));
+                            OGRGetXML_UTF8_EscapedString(poFeatureIn->GetFieldAsString( iIndex ));
                     VSIFPrintfL(fp, " %s=\"%s\"", "xml:lang", pszValue);
                     CPLFree(pszValue);
                 }
@@ -1330,10 +1318,10 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeature )
 
                 pszFieldName = CPLStrdup(CPLSPrintf("%s_%s", pszName, "xml_base"));
                 iIndex = poFeatureDefn->GetFieldIndex(pszFieldName);
-                if (iIndex != -1 && poFeature->IsFieldSet( iIndex ))
+                if (iIndex != -1 && poFeatureIn->IsFieldSet( iIndex ))
                 {
                     char* pszValue =
-                            OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( iIndex ));
+                            OGRGetXML_UTF8_EscapedString(poFeatureIn->GetFieldAsString( iIndex ));
                     VSIFPrintfL(fp, " %s=\"%s\"", "xml:base", pszValue);
                     CPLFree(pszValue);
                 }
@@ -1341,18 +1329,18 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeature )
 
                 VSIFPrintfL(fp, ">");
                 if (bIsXHTML)
-                    VSIFPrintfL(fp, "%s", poFeature->GetFieldAsString(i));
+                    VSIFPrintfL(fp, "%s", poFeatureIn->GetFieldAsString(i));
                 else
                 {
                     char* pszValue =
-                            OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( i ));
+                            OGRGetXML_UTF8_EscapedString(poFeatureIn->GetFieldAsString( i ));
                     VSIFPrintfL(fp, "%s", pszValue);
                     CPLFree(pszValue);
                 }
                 VSIFPrintfL(fp, "      </%s>\n", pszName);
             }
         }
-        else if (strncmp(pszName, "dc_subject", strlen("dc_subject")) == 0)
+        else if (STARTS_WITH(pszName, "dc_subject"))
         {
             char* pszFieldName;
             int iIndex;
@@ -1362,17 +1350,17 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeature )
 
                 pszFieldName = CPLStrdup(CPLSPrintf("%s_%s", pszName, "xml_lang"));
                 iIndex = poFeatureDefn->GetFieldIndex(pszFieldName);
-                if (iIndex != -1 && poFeature->IsFieldSet( iIndex ))
+                if (iIndex != -1 && poFeatureIn->IsFieldSet( iIndex ))
                 {
                     char* pszValue =
-                            OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( iIndex ));
+                            OGRGetXML_UTF8_EscapedString(poFeatureIn->GetFieldAsString( iIndex ));
                     VSIFPrintfL(fp, " %s=\"%s\"", "xml:lang", pszValue);
                     CPLFree(pszValue);
                 }
                 CPLFree(pszFieldName);
 
                 char* pszValue =
-                        OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( i ));
+                        OGRGetXML_UTF8_EscapedString(poFeatureIn->GetFieldAsString( i ));
                 VSIFPrintfL(fp, ">%s</%s>\n", pszValue, "dc:subject");
                 CPLFree(pszValue);
             }
@@ -1382,9 +1370,8 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeature )
             char* pszTagName = CPLStrdup(pszName);
             if (IsStandardField(pszName) == FALSE)
             {
-                int j;
                 int nCountUnderscore = 0;
-                for(j=0;pszTagName[j] != 0;j++)
+                for( int j=0; pszTagName[j] != 0; j++ )
                 {
                     if (pszTagName[j] == '_')
                     {
@@ -1403,7 +1390,7 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeature )
                 }
             }
             char* pszValue =
-                        OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( i ));
+                        OGRGetXML_UTF8_EscapedString(poFeatureIn->GetFieldAsString( i ));
             VSIFPrintfL(fp, "      <%s>%s</%s>\n", pszTagName, pszValue, pszTagName);
             CPLFree(pszValue);
             CPLFree(pszTagName);
@@ -1417,7 +1404,7 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeature )
     CPLFree(pbUsed);
 
     OGRGeoRSSGeomDialect eGeomDialect = poDS->GetGeomDialect();
-    OGRGeometry* poGeom = poFeature->GetGeometryRef();
+    OGRGeometry* poGeom = poFeatureIn->GetGeometryRef();
     if ( poGeom != NULL && !poGeom->IsEmpty() )
     {
         char* pszURN = NULL;
@@ -1432,13 +1419,16 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeature )
                     pszAuthorityCode != NULL)
                 {
                     if (!EQUAL(pszAuthorityCode, "4326"))
-                        pszURN = CPLStrdup(CPLSPrintf("urn:ogc:def:crs:EPSG::%s", pszAuthorityCode));
+                        pszURN = CPLStrdup(
+                            CPLSPrintf( "urn:ogc:def:crs:EPSG::%s",
+                                        pszAuthorityCode ) );
 
-                    /* In case the SRS is a geographic SRS and that we have no axis */
-                    /* defintion, we assume that the order is lon/lat */
+                    /* In case the SRS is a geographic SRS and that we have */
+                    /* no axis definition, we assume that the order is */
+                    /* lon/lat. */
                     const char* pszAxisName = poSRS->GetAxis(NULL, 0, NULL);
                     if (poSRS->IsGeographic() &&
-                        (pszAxisName == NULL || EQUALN(pszAxisName, "Lon", 3)))
+                        (pszAxisName == NULL || STARTS_WITH_CI(pszAxisName, "Lon")))
                     {
                         bSwapCoordinates = TRUE;
                     }
@@ -1774,12 +1764,10 @@ void OGRGeoRSSLayer::LoadSchema()
 
 static int OGRGeoRSSIsInt(const char* pszStr)
 {
-    int i;
-
     while(*pszStr == ' ')
         pszStr++;
 
-    for(i=0;pszStr[i];i++)
+    for( int i=0; pszStr[i]; i++ )
     {
         if (pszStr[i] == '+' || pszStr[i] == '-')
         {
@@ -1862,7 +1850,7 @@ void OGRGeoRSSLayer::startElementLoadSchemaCbk(const char *pszName, const char *
     }
     else if (bInFeature && currentDepth == featureDepth + 1 && !IS_GEO_ELEMENT(pszName))
     {
-        if( pszName != pszNoNSName && strncmp(pszName, "atom:", 5) == 0 )
+        if( pszName != pszNoNSName && STARTS_WITH(pszName, "atom:") )
             pszName = pszNoNSName;
 
         CPLFree(pszSubElementName);
@@ -2009,7 +1997,7 @@ void OGRGeoRSSLayer::startElementLoadSchemaCbk(const char *pszName, const char *
     if (!bInFeature || currentDepth >= featureDepth + 1)
     {
         int nDimension = 2;
-        for(int i = 0; ppszAttr[i] != NULL; i+=2)
+        for(int i = 0; ppszAttr[i] != NULL && ppszAttr[i+1] != NULL; i+=2)
         {
             if (strcmp(ppszAttr[i], "srsDimension") == 0)
             {
@@ -2160,10 +2148,9 @@ void OGRGeoRSSLayer::dataHandlerLoadSchemaCbk(const char *data, int nLen)
 
     if (pszSubElementName)
     {
-        char* pszNewSubElementValue = (char*) VSIRealloc(pszSubElementValue, nSubElementValueLen + nLen + 1);
+        char* pszNewSubElementValue = (char*) VSI_REALLOC_VERBOSE(pszSubElementValue, nSubElementValueLen + nLen + 1);
         if (pszNewSubElementValue == NULL)
         {
-            CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
             XML_StopParser(oSchemaParser, XML_FALSE);
             bStopParsing = TRUE;
             return;
@@ -2204,7 +2191,7 @@ int OGRGeoRSSLayer::TestCapability( const char * pszCap )
         return bWriteMode;
     else if( EQUAL(pszCap,OLCCreateField) )
         return bWriteMode;
-    else 
+    else
         return FALSE;
 }
 
diff --git a/ogr/ogrsf_frmts/gft/drv_gft.html b/ogr/ogrsf_frmts/gft/drv_gft.html
index b6758f8..25dde47 100644
--- a/ogr/ogrsf_frmts/gft/drv_gft.html
+++ b/ogr/ogrsf_frmts/gft/drv_gft.html
@@ -35,41 +35,41 @@ If several parameters are specified, they must be separated by a space.
 
 <h2>Authentication</h2>
 
-Most operations, in particular write operations, require a valid Google 
-account to provide authentication information to the driver. The only 
+Most operations, in particular write operations, require a valid Google
+account to provide authentication information to the driver. The only
 exception is read-only access to public tables.<p>
 
-In order to create an authorization key, it is necessary to 
+In order to create an authorization key, it is necessary to
 <a href="https://www.google.com/url?q=https%3A%2F%2Faccounts.google.com%2Fo%2Foauth2%2Fauth%3Fscope%3Dhttps%253A%252F%252Fwww.googleapis.com%252Fauth%252Ffusiontables%26state%3D%252Fprofile%26redirect_uri%3Durn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob%26response_type%3Dcode%26client_id%3D265656308688.apps.googleusercontent.com">
-login and authorize</a> access to fusion tables for a google (ie. gmail) 
-account.  The resulting authorization key can be turned into a refresh 
-token for use OGR using the gdal/swig/python/scripts/gdal_auth.py script 
-distributed with GDAL (available in GDAL/OGR >= 1.10.0).  Note that auth 
-tokens can only be used once, while the resulting refresh token lasts 
-indefinately.<p>
+login and authorize</a> access to fusion tables for a Google (i.e. GMail)
+account.  The resulting authorization key can be turned into a refresh
+token for use OGR using the gdal/swig/python/scripts/gdal_auth.py script
+distributed with GDAL (available in GDAL/OGR >= 1.10.0).  Note that auth
+tokens can only be used once, while the resulting refresh token lasts
+indefinitely.<p>
 
 <pre>
   gdal_auth.py auth2refresh <i>auth_token</i>
 </pre>
 
-This refresh token can then be either set as a configuration option 
-(GFT_REFRESH_TOKEN) or included in the connection string 
-(ie. GFT:refresh=<i>refresh_token</i>). <p>
+This refresh token can then be either set as a configuration option
+(GFT_REFRESH_TOKEN) or included in the connection string
+(i.e. GFT:refresh=<i>refresh_token</i>). <p>
 
 Generally OAuth2 credentials can be provided via these mechanisms:<p>
 
 <ul>
-<li> Specifying an <i>access token</i> via the <tt>GFT_ACCESS_TOKEN</tt> 
+<li> Specifying an <i>access token</i> via the <tt>GFT_ACCESS_TOKEN</tt>
 configuration/environment variable.<p>
-<li> Specifying an <i>access token</i> via the <tt>access=</tt> 
+<li> Specifying an <i>access token</i> via the <tt>access=</tt>
 clause in the GFT: connection string.
-<li> Specifying a <i>refresh token</i> via the <tt>GFT_REFRESH_TOKEN</tt> 
+<li> Specifying a <i>refresh token</i> via the <tt>GFT_REFRESH_TOKEN</tt>
 configuration/environment variable.<p>
-<li> Specifying an <i>refresh token</i> via the <tt>refresh=</tt> 
+<li> Specifying an <i>refresh token</i> via the <tt>refresh=</tt>
 clause in the GFT: connection string.
-<li> Specifying a <i>auth key</i> via the <tt>GFT_AUTH</tt> 
+<li> Specifying a <i>auth key</i> via the <tt>GFT_AUTH</tt>
 configuration/environment variable.<p>
-<li> Specifying an <i>auth key</i> via the <tt>auth=</tt> 
+<li> Specifying an <i>auth key</i> via the <tt>auth=</tt>
 clause in the GFT: connection string.
 </ul>
 
@@ -124,9 +124,11 @@ geodetic WGS84 SRS if needed (provided that the original SRS is attached to the
 The above operations are by default issued to the server synchronously with the OGR API call. This however
 can cause performance penalties when issuing a lot of commands due to many client/server exchanges.<p>
 
-It is possible to surround the CreateFeature() oepration between OGRLayer::StartTransaction() and OGRLayer::CommitTransaction().
-The operations will be stored into memory and only executed at the time CommitTransaction() is called. Note that
-the GFT service only supports up to 500 INSERTs and up to 1MB of content per transaction.<p>
+It is possible to surround the CreateFeature() operation between
+OGRLayer::StartTransaction() and OGRLayer::CommitTransaction().  The
+operations will be stored into memory and only executed at the time
+CommitTransaction() is called. Note that the GFT service only supports
+up to 500 INSERTs and up to 1MB of content per transaction.<p>
 
 Note : only CreateFeature() makes use of OGR transaction mechanism. SetFeature() and DeleteFeature()
 will still be issued immediately.<p>
@@ -136,8 +138,10 @@ will still be issued immediately.<p>
 SQL commands provided to the OGRDataSource::ExecuteSQL() call are executed on the server side, unless the OGRSQL
 dialect is specified. The subset of SQL supported by the GFT service is described in the links at the end of this page.<p>
 
-The SQL supported by the server understands only natively table id, and not the table names returned by OGR.
-For conveniency, OGR will "patch" your SQL command to replace the table name by the table id however.<p>
+The SQL supported by the server understands only native table id, and
+not the table names returned by OGR.  For convenience, OGR will
+"patch" your SQL command to replace the table name by the table id
+however.<p>
 
 <h2>Examples</h2>
 
@@ -156,7 +160,7 @@ ogr2ogr -f GFT "GFT:email=john.doe at example.com password=secret_password" shapefi
 <p>
 
 <li>
-Displaying the content of a public table with a spatial and attribue filters:
+Displaying the content of a public table with a spatial and attribute filters:
 <pre>
 ogrinfo -ro "GFT:tables=224453" -al -spat 67 31.5 67.5 32 -where "'Attack on' = 'ENEMY'"
 </pre>
diff --git a/ogr/ogrsf_frmts/gft/ogr_gft.h b/ogr/ogrsf_frmts/gft/ogr_gft.h
index 6bb6b21..01e6084 100644
--- a/ogr/ogrsf_frmts/gft/ogr_gft.h
+++ b/ogr/ogrsf_frmts/gft/ogr_gft.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_gft.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogr_gft.h 33138 2016-01-24 11:18:11Z rouault $
  *
  * Project:  GFT Translator
  * Purpose:  Definition of classes for OGR Google Fusion Tables driver.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_GFT_H_INCLUDED
-#define _OGR_GFT_H_INCLUDED
+#ifndef OGR_GFT_H_INCLUDED
+#define OGR_GFT_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "cpl_http.h"
@@ -142,6 +142,9 @@ class OGRGFTTableLayer : public OGRGFTLayer
     virtual OGRFeature *        GetFeature( GIntBig nFID );
 
     virtual void        SetSpatialFilter( OGRGeometry * );
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+                { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
+
     virtual OGRErr      SetAttributeFilter( const char * );
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
@@ -204,7 +207,7 @@ class OGRGFTDataSource : public OGRDataSource
 
     void                DeleteLayer( const char *pszLayerName );
 
-    int                 bMustCleanPersistant;
+    int                 bMustCleanPersistent;
 
     static CPLStringList ParseSimpleJson(const char *pszJSon);
 
@@ -260,4 +263,4 @@ class OGRGFTDriver : public OGRSFDriver
 char **OGRGFTCSVSplitLine( const char *pszString, char chDelimiter );
 char* OGRGFTGotoNextLine(char* pszData);
 
-#endif /* ndef _OGR_GFT_H_INCLUDED */
+#endif /* ndef OGR_GFT_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/gft/ogrgftdatasource.cpp b/ogr/ogrsf_frmts/gft/ogrgftdatasource.cpp
index c0ede5f..322c922 100644
--- a/ogr/ogrsf_frmts/gft/ogrgftdatasource.cpp
+++ b/ogr/ogrsf_frmts/gft/ogrgftdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgftdatasource.cpp 28939 2015-04-17 19:01:24Z rouault $
+ * $Id: ogrgftdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Google Fusion Table Translator
  * Purpose:  Implements OGRGFTDataSource class
@@ -29,7 +29,7 @@
 
 #include "ogr_gft.h"
 
-CPL_CVSID("$Id: ogrgftdatasource.cpp 28939 2015-04-17 19:01:24Z rouault $");
+CPL_CVSID("$Id: ogrgftdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 #define GDAL_API_KEY "AIzaSyA_2h1_wXMOLHNSVeo-jf1ACME-M1XMgP0"
 #define FUSION_TABLE_SCOPE "https://www.googleapis.com/Fauth/fusiontables"
@@ -49,7 +49,7 @@ OGRGFTDataSource::OGRGFTDataSource()
     bReadWrite = FALSE;
     bUseHTTPS = FALSE;
 
-    bMustCleanPersistant = FALSE;
+    bMustCleanPersistent = FALSE;
 }
 
 /************************************************************************/
@@ -63,11 +63,11 @@ OGRGFTDataSource::~OGRGFTDataSource()
         delete papoLayers[i];
     CPLFree( papoLayers );
 
-    if (bMustCleanPersistant)
+    if (bMustCleanPersistent)
     {
         char** papszOptions = NULL;
         papszOptions = CSLSetNameValue(papszOptions, "CLOSE_PERSISTENT", CPLSPrintf("GFT:%p", this));
-        CPLHTTPFetch( GetAPIURL(), papszOptions);
+        CPLHTTPDestroyResult( CPLHTTPFetch( GetAPIURL(), papszOptions) );
         CSLDestroy(papszOptions);
     }
 
@@ -111,23 +111,23 @@ OGRLayer *OGRGFTDataSource::GetLayerByName(const char * pszLayerName)
     OGRLayer* poLayer = OGRDataSource::GetLayerByName(pszLayerName);
     if (poLayer)
         return poLayer;
-        
+
     char* pszGeomColumnName = NULL;
-    char* pszName = CPLStrdup(pszLayerName);
-    char *pszLeftParenthesis = strchr(pszName, '(');
+    char* l_pszName = CPLStrdup(pszLayerName);
+    char *pszLeftParenthesis = strchr(l_pszName, '(');
     if( pszLeftParenthesis != NULL )
     {
         *pszLeftParenthesis = '\0';
         pszGeomColumnName = CPLStrdup(pszLeftParenthesis+1);
-        int len = strlen(pszGeomColumnName);
+        int len = static_cast<int>(strlen(pszGeomColumnName));
         if (len > 0 && pszGeomColumnName[len - 1] == ')')
             pszGeomColumnName[len - 1] = '\0';
     }
-    
-    CPLString osTableId(pszName);
+
+    CPLString osTableId(l_pszName);
     for(int i=0;i<nLayers;i++)
     {
-        if( strcmp(papoLayers[i]->GetName(), pszName) == 0)
+        if( strcmp(papoLayers[i]->GetName(), l_pszName) == 0)
         {
             osTableId = ((OGRGFTTableLayer*)papoLayers[i])->GetTableId();
             break;
@@ -136,7 +136,7 @@ OGRLayer *OGRGFTDataSource::GetLayerByName(const char * pszLayerName)
 
     poLayer = new OGRGFTTableLayer(this, pszLayerName, osTableId,
                                    pszGeomColumnName);
-    CPLFree(pszName);
+    CPLFree(l_pszName);
     CPLFree(pszGeomColumnName);
     if (poLayer->GetLayerDefn()->GetFieldCount() == 0)
     {
@@ -152,7 +152,7 @@ OGRLayer *OGRGFTDataSource::GetLayerByName(const char * pszLayerName)
 /*                      OGRGFTGetOptionValue()                          */
 /************************************************************************/
 
-CPLString OGRGFTGetOptionValue(const char* pszFilename,
+static CPLString OGRGFTGetOptionValue(const char* pszFilename,
                                const char* pszOptionName)
 {
     CPLString osOptionName(pszOptionName);
@@ -196,14 +196,14 @@ int OGRGFTDataSource::Open( const char * pszFilename, int bUpdateIn)
     osAccessToken = OGRGFTGetOptionValue(pszFilename, "access");
     if (osAccessToken.size() == 0)
         osAccessToken = CPLGetConfigOption("GFT_ACCESS_TOKEN","");
-    if (osAccessToken.size() == 0 && osRefreshToken.size() > 0) 
+    if (osAccessToken.size() == 0 && osRefreshToken.size() > 0)
     {
         osAccessToken.Seize(GOA2GetAccessToken(osRefreshToken,
                                                FUSION_TABLE_SCOPE));
         if (osAccessToken.size() == 0)
             return FALSE;
     }
-
+    /* coverity[copy_paste_error] */
     if (osAccessToken.size() == 0 && osAuth.size() > 0)
     {
         osRefreshToken.Seize(GOA2GetRefreshToken(osAuth, FUSION_TABLE_SCOPE));
@@ -242,7 +242,7 @@ int OGRGFTDataSource::Open( const char * pszFilename, int bUpdateIn)
     char* pszLine = (char*) psResult->pabyData;
     if (pszLine == NULL ||
         psResult->pszErrBuf != NULL ||
-        strncmp(pszLine, "table id,name", strlen("table id,name")) != 0)
+        !STARTS_WITH(pszLine, "table id,name"))
     {
         CPLHTTPDestroyResult(psResult);
         return FALSE;
@@ -302,7 +302,7 @@ const char*  OGRGFTDataSource::GetAPIURL() const
 /*                          ICreateLayer()                              */
 /************************************************************************/
 
-OGRLayer   *OGRGFTDataSource::ICreateLayer( const char *pszName,
+OGRLayer   *OGRGFTDataSource::ICreateLayer( const char *pszNameIn,
                                             CPL_UNUSED OGRSpatialReference *poSpatialRef,
                                             OGRwkbGeometryType eGType,
                                             char ** papszOptions )
@@ -327,12 +327,12 @@ OGRLayer   *OGRGFTDataSource::ICreateLayer( const char *pszName,
 
     for( iLayer = 0; iLayer < nLayers; iLayer++ )
     {
-        if( EQUAL(pszName,papoLayers[iLayer]->GetName()) )
+        if( EQUAL(pszNameIn,papoLayers[iLayer]->GetName()) )
         {
             if( CSLFetchNameValue( papszOptions, "OVERWRITE" ) != NULL
                 && !EQUAL(CSLFetchNameValue(papszOptions,"OVERWRITE"),"NO") )
             {
-                DeleteLayer( pszName );
+                DeleteLayer( pszNameIn );
                 break;
             }
             else
@@ -341,13 +341,13 @@ OGRLayer   *OGRGFTDataSource::ICreateLayer( const char *pszName,
                           "Layer %s already exists, CreateLayer failed.\n"
                           "Use the layer creation option OVERWRITE=YES to "
                           "replace it.",
-                          pszName );
+                          pszNameIn );
                 return NULL;
             }
         }
     }
 
-    OGRGFTTableLayer* poLayer = new OGRGFTTableLayer(this, pszName);
+    OGRGFTTableLayer* poLayer = new OGRGFTTableLayer(this, pszNameIn);
     poLayer->SetGeometryType(eGType);
     papoLayers = (OGRLayer**) CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
     papoLayers[nLayers ++] = poLayer;
@@ -452,11 +452,11 @@ OGRErr OGRGFTDataSource::DeleteLayer(int iLayer)
 
 char** OGRGFTDataSource::AddHTTPOptions(char** papszOptions)
 {
-    bMustCleanPersistant = TRUE;
+    bMustCleanPersistent = TRUE;
 
     if (strlen(osAccessToken) > 0)
       papszOptions = CSLAddString(papszOptions,
-        CPLSPrintf("HEADERS=Authorization: Bearer %s", 
+        CPLSPrintf("HEADERS=Authorization: Bearer %s",
                    osAccessToken.c_str()));
 
     return CSLAddString(papszOptions, CPLSPrintf("PERSISTENT=GFT:%p", this));
@@ -504,19 +504,19 @@ CPLHTTPResult * OGRGFTDataSource::RunSQL(const char* pszUnescapedSQL)
 /*      are transformed info failure.                                   */
 /* -------------------------------------------------------------------- */
     if (psResult && psResult->pszContentType &&
-        strncmp(psResult->pszContentType, "text/html", 9) == 0)
+        STARTS_WITH(psResult->pszContentType, "text/html"))
     {
         CPLDebug( "GFT", "RunSQL HTML Response:%s", psResult->pabyData );
-        CPLError(CE_Failure, CPLE_AppDefined, 
+        CPLError(CE_Failure, CPLE_AppDefined,
                  "HTML error page returned by server");
         CPLHTTPDestroyResult(psResult);
         psResult = NULL;
     }
-    if (psResult && psResult->pszErrBuf != NULL) 
+    if (psResult && psResult->pszErrBuf != NULL)
     {
         CPLDebug( "GFT", "RunSQL Error Message:%s", psResult->pszErrBuf );
     }
-    else if (psResult && psResult->nStatus != 0) 
+    else if (psResult && psResult->nStatus != 0)
     {
         CPLDebug( "GFT", "RunSQL Error Status:%d", psResult->nStatus );
     }
@@ -544,7 +544,7 @@ OGRLayer * OGRGFTDataSource::ExecuteSQL( const char *pszSQLCommand,
 /* -------------------------------------------------------------------- */
 /*      Special case DELLAYER: command.                                 */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszSQLCommand,"DELLAYER:",9) )
+    if( STARTS_WITH_CI(pszSQLCommand, "DELLAYER:") )
     {
         const char *pszLayerName = pszSQLCommand + 9;
 
diff --git a/ogr/ogrsf_frmts/gft/ogrgftdriver.cpp b/ogr/ogrsf_frmts/gft/ogrgftdriver.cpp
index 43b7b4a..676795d 100644
--- a/ogr/ogrsf_frmts/gft/ogrgftdriver.cpp
+++ b/ogr/ogrsf_frmts/gft/ogrgftdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgftdriver.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogrgftdriver.cpp 33105 2016-01-23 15:27:32Z rouault $
  *
  * Project:  GFT Translator
  * Purpose:  Implements OGRGFTDriver.
@@ -33,7 +33,7 @@
 
 /* http://code.google.com/intl/fr/apis/fusiontables/docs/developers_reference.html */
 
-CPL_CVSID("$Id: ogrgftdriver.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogrgftdriver.cpp 33105 2016-01-23 15:27:32Z rouault $");
 
 extern "C" void RegisterOGRGFT();
 
@@ -63,8 +63,8 @@ const char *OGRGFTDriver::GetName()
 OGRDataSource *OGRGFTDriver::Open( const char * pszFilename, int bUpdate )
 
 {
-    if (!EQUALN(pszFilename, "GFT:", 4))
-        return FALSE;
+    if (!STARTS_WITH_CI(pszFilename, "GFT:"))
+        return NULL;
 
     OGRGFTDataSource   *poDS = new OGRGFTDataSource();
 
@@ -117,9 +117,7 @@ void RegisterOGRGFT()
 
 {
     OGRSFDriver* poDriver = new OGRGFTDriver;
-    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Google Fusion Tables" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_gft.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Google Fusion Tables" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_gft.html" );
     OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver(poDriver);
 }
diff --git a/ogr/ogrsf_frmts/gft/ogrgftlayer.cpp b/ogr/ogrsf_frmts/gft/ogrgftlayer.cpp
index 5338c1e..7e930a2 100644
--- a/ogr/ogrsf_frmts/gft/ogrgftlayer.cpp
+++ b/ogr/ogrsf_frmts/gft/ogrgftlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgftlayer.cpp 28382 2015-01-30 15:29:41Z rouault $
+ * $Id: ogrgftlayer.cpp 32370 2015-12-20 19:40:13Z rouault $
  *
  * Project:  GFT Translator
  * Purpose:  Implements OGRGFTLayer class.
@@ -30,16 +30,16 @@
 #include "ogr_gft.h"
 #include "cpl_minixml.h"
 
-CPL_CVSID("$Id: ogrgftlayer.cpp 28382 2015-01-30 15:29:41Z rouault $");
+CPL_CVSID("$Id: ogrgftlayer.cpp 32370 2015-12-20 19:40:13Z rouault $");
 
 /************************************************************************/
 /*                            OGRGFTLayer()                             */
 /************************************************************************/
 
-OGRGFTLayer::OGRGFTLayer(OGRGFTDataSource* poDS)
+OGRGFTLayer::OGRGFTLayer(OGRGFTDataSource* poDSIn)
 
 {
-    this->poDS = poDS;
+    this->poDS = poDSIn;
 
     nNextInSeq = 0;
 
@@ -103,15 +103,15 @@ OGRFeature *OGRGFTLayer::GetNextFeature()
 
     GetLayerDefn();
 
-    while(TRUE)
+    while( true )
     {
         if (nNextInSeq < nOffset ||
-            nNextInSeq >= nOffset + (int)aosRows.size())
+            nNextInSeq >= nOffset + static_cast<int>(aosRows.size()))
         {
             if (bEOF)
                 return NULL;
 
-            nOffset += aosRows.size();
+            nOffset += static_cast<int>(aosRows.size());
             if (!FetchNextRows())
                 return NULL;
         }
@@ -157,11 +157,11 @@ char **OGRGFTCSVSplitLine( const char *pszString, char chDelimiter )
 
         nTokenLen = 0;
 
-        /* Try to find the next delimeter, marking end of token */
+        /* Try to find the next delimiter, marking end of token */
         for( ; *pszString != '\0'; pszString++ )
         {
 
-            /* End if this is a delimeter skip it and break. */
+            /* End if this is a delimiter skip it and break. */
             if( !bInString && *pszString == chDelimiter )
             {
                 pszString++;
@@ -287,8 +287,8 @@ static OGRGeometry* ParseKMLGeometry(/* const */ CPLXMLNode* psXML)
                     if (psIter->eType == CXT_Element &&
                         strcmp(psIter->pszValue, "innerBoundaryIs") == 0)
                     {
-                        CPLXMLNode* psLinearRing = CPLGetXMLNode(psIter, "LinearRing");
-                        const char* pszCoordinates = CPLGetXMLValue(
+                        psLinearRing = CPLGetXMLNode(psIter, "LinearRing");
+                        pszCoordinates = CPLGetXMLValue(
                             psLinearRing ? psLinearRing : psIter, "coordinates", NULL);
                         if (pszCoordinates)
                         {
@@ -344,7 +344,6 @@ static OGRGeometry* ParseKMLGeometry(/* const */ CPLXMLNode* psXML)
             CPLAssert(0);
         }
 
-        psIter = psXML->psChild;
         for(psIter = psXML->psChild; psIter; psIter = psIter->psNext)
         {
             if (psIter->eType == CXT_Element)
@@ -608,7 +607,7 @@ CPLString OGRGFTLayer::PatchSQL(const char* pszSQL)
 
     while(*pszSQL)
     {
-        if (EQUALN(pszSQL, "COUNT(", 5) && strchr(pszSQL, ')'))
+        if (STARTS_WITH_CI(pszSQL, "COUNT(") && strchr(pszSQL, ')'))
         {
             const char* pszNext = strchr(pszSQL, ')');
             osSQL += "COUNT()";
diff --git a/ogr/ogrsf_frmts/gft/ogrgftresultlayer.cpp b/ogr/ogrsf_frmts/gft/ogrgftresultlayer.cpp
index 37b2929..aa54a5d 100644
--- a/ogr/ogrsf_frmts/gft/ogrgftresultlayer.cpp
+++ b/ogr/ogrsf_frmts/gft/ogrgftresultlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgftresultlayer.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogrgftresultlayer.cpp 32177 2015-12-14 07:25:30Z goatbar $
  *
  * Project:  GFT Translator
  * Purpose:  Implements OGRGFTResultLayer class.
@@ -29,14 +29,14 @@
 
 #include "ogr_gft.h"
 
-CPL_CVSID("$Id: ogrgftresultlayer.cpp 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: ogrgftresultlayer.cpp 32177 2015-12-14 07:25:30Z goatbar $");
 
 /************************************************************************/
 /*                        OGRGFTResultLayer()                           */
 /************************************************************************/
 
-OGRGFTResultLayer::OGRGFTResultLayer(OGRGFTDataSource* poDS,
-                                     const char* pszSQL) : OGRGFTLayer(poDS)
+OGRGFTResultLayer::OGRGFTResultLayer(OGRGFTDataSource* poDSIn,
+                                     const char* pszSQL) : OGRGFTLayer(poDSIn)
 
 {
     osSQL = PatchSQL(pszSQL);
@@ -47,7 +47,7 @@ OGRGFTResultLayer::OGRGFTResultLayer(OGRGFTDataSource* poDS,
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbUnknown );
     poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
-    
+
     SetDescription( poFeatureDefn->GetName() );
 }
 
@@ -82,7 +82,7 @@ void OGRGFTResultLayer::ResetReading()
 
 int OGRGFTResultLayer::FetchNextRows()
 {
-    if (!EQUALN(osSQL.c_str(), "SELECT", 6))
+    if (!STARTS_WITH_CI(osSQL.c_str(), "SELECT"))
         return FALSE;
 
     aosRows.resize(0);
@@ -181,7 +181,7 @@ int OGRGFTResultLayer::RunSQL()
     OGRGFTTableLayer* poTableLayer = NULL;
     OGRFeatureDefn* poTableDefn = NULL;
     CPLString osTableId;
-    if (EQUALN(osSQL.c_str(), "SELECT", 6))
+    if (STARTS_WITH_CI(osSQL.c_str(), "SELECT"))
     {
         size_t nPosFROM = osSQL.ifind(" FROM ");
         if (nPosFROM == std::string::npos)
@@ -239,9 +239,9 @@ int OGRGFTResultLayer::RunSQL()
         return FALSE;
     }
 
-    if (EQUALN(osSQL.c_str(), "SELECT", 6) ||
+    if (STARTS_WITH_CI(osSQL.c_str(), "SELECT") ||
         EQUAL(osSQL.c_str(), "SHOW TABLES") ||
-        EQUALN(osSQL.c_str(), "DESCRIBE", 8))
+        STARTS_WITH_CI(osSQL.c_str(), "DESCRIBE"))
     {
         ParseCSVResponse(pszLine, aosRows);
         if (aosRows.size() > 0)
diff --git a/ogr/ogrsf_frmts/gft/ogrgfttablelayer.cpp b/ogr/ogrsf_frmts/gft/ogrgfttablelayer.cpp
index 054b8e9..fc5704e 100644
--- a/ogr/ogrsf_frmts/gft/ogrgfttablelayer.cpp
+++ b/ogr/ogrsf_frmts/gft/ogrgfttablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgfttablelayer.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrgfttablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  GFT Translator
  * Purpose:  Implements OGRGFTTableLayer class.
@@ -29,16 +29,16 @@
 
 #include "ogr_gft.h"
 
-CPL_CVSID("$Id: ogrgfttablelayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrgfttablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                         OGRGFTTableLayer()                           */
 /************************************************************************/
 
-OGRGFTTableLayer::OGRGFTTableLayer(OGRGFTDataSource* poDS,
+OGRGFTTableLayer::OGRGFTTableLayer(OGRGFTDataSource* poDSIn,
                          const char* pszTableName,
                          const char* pszTableId,
-                         const char* pszGeomColumnName) : OGRGFTLayer(poDS)
+                         const char* pszGeomColumnName) : OGRGFTLayer(poDSIn)
 
 {
     osTableName = pszTableName;
@@ -132,9 +132,7 @@ int OGRGFTTableLayer::FetchDescribe()
         char* pszLine = (char*) psResult->pabyData;
         if (pszLine == NULL ||
             psResult->pszErrBuf != NULL ||
-            strncmp(pszLine, "column id,name,type",
-                    strlen("column id,name,type")) != 0)
-        {
+            !STARTS_WITH(pszLine, "column id,name,type"))        {
             CPLHTTPDestroyResult(psResult);
             return FALSE;
         }
@@ -210,7 +208,7 @@ int OGRGFTTableLayer::FetchDescribe()
 
         CPLHTTPDestroyResult(psResult);
     }
-    
+
     if (osGeomColumnName.size() > 0)
     {
         iGeometryField = poFeatureDefn->GetFieldIndex(osGeomColumnName);
@@ -244,8 +242,8 @@ int OGRGFTTableLayer::FetchDescribe()
     {
         iLatitudeField = iLongitudeField = -1;
 
-        /* In the unauthentified case, we try to parse the first record to */
-        /* autodetect the geometry field */
+        /* In the unauthenticated case, we try to parse the first record to */
+        /* auto-detect the geometry field. */
         OGRwkbGeometryType eType = wkbUnknown;
         if (aosHeaderAndFirstDataLine.size() == 2)
         {
@@ -256,10 +254,10 @@ int OGRGFTTableLayer::FetchDescribe()
                 {
                     const char* pszVal = papszTokens[i];
                     if (pszVal != NULL &&
-                        (strncmp(pszVal, "<Point>", 7) == 0 ||
-                         strncmp(pszVal, "<LineString>", 12) == 0 ||
-                         strncmp(pszVal, "<Polygon>", 9) == 0 ||
-                         strncmp(pszVal, "<MultiGeometry>", 15) == 0))
+                        (STARTS_WITH(pszVal, "<Point>") ||
+                         STARTS_WITH(pszVal, "<LineString>") ||
+                         STARTS_WITH(pszVal, "<Polygon>") ||
+                         STARTS_WITH(pszVal, "<MultiGeometry>")))
                     {
                         if (iGeometryField < 0)
                         {
@@ -298,7 +296,7 @@ int OGRGFTTableLayer::FetchDescribe()
             }
             CSLDestroy(papszTokens);
         }
-        
+
         if (iGeometryField < 0)
             poFeatureDefn->SetGeomType( wkbNone );
         else
@@ -500,7 +498,7 @@ GIntBig OGRGFTTableLayer::GetFeatureCount(CPL_UNUSED int bForce)
 
     char* pszLine = (char*) psResult->pabyData;
     if (pszLine == NULL ||
-        strncmp(pszLine, "count()", 7) != 0 ||
+        !STARTS_WITH(pszLine, "count()") ||
         psResult->pszErrBuf != NULL)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "GetFeatureCount() failed");
@@ -575,11 +573,9 @@ void OGRGFTTableLayer::CreateTableIfNecessary()
     osSQL += osTableName;
     osSQL += "' (";
 
-    int i;
-
     /* If there are longitude and latitude fields, use the latitude */
     /* field as the LOCATION field */
-    for(i=0;i<poFeatureDefn->GetFieldCount();i++)
+    for( int i=0; i < poFeatureDefn->GetFieldCount(); i++ )
     {
         const char* pszName = poFeatureDefn->GetFieldDefn(i)->GetNameRef();
         if (EQUAL(pszName, "latitude") || EQUAL(pszName, "lat") ||
@@ -609,7 +605,8 @@ void OGRGFTTableLayer::CreateTableIfNecessary()
         poFeatureDefn->SetGeomType( eGTypeForCreation );
     }
 
-    for(i=0;i<poFeatureDefn->GetFieldCount();i++)
+    int i = 0;
+    for( ; i < poFeatureDefn->GetFieldCount(); i++ )
     {
         if (i > 0)
             osSQL += ", ";
@@ -664,7 +661,7 @@ void OGRGFTTableLayer::CreateTableIfNecessary()
 
     char* pszLine = (char*) psResult->pabyData;
     if (pszLine == NULL ||
-        strncmp(pszLine, "tableid", 7) != 0 ||
+        !STARTS_WITH(pszLine, "tableid") ||
         psResult->pszErrBuf != NULL)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Table creation failed");
@@ -844,7 +841,7 @@ OGRErr OGRGFTTableLayer::ICreateFeature( OGRFeature *poFeature )
 
     char* pszLine = (char*) psResult->pabyData;
     if (pszLine == NULL ||
-        strncmp(pszLine, "rowid", 5) != 0 ||
+        !STARTS_WITH(pszLine, "rowid") ||
         psResult->pszErrBuf != NULL)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Feature creation failed");
@@ -1022,11 +1019,11 @@ OGRErr      OGRGFTTableLayer::ISetFeature( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
     char* pszLine = (char*) psResult->pabyData;
     if (pszLine == NULL ||
-        strncmp(pszLine, "affected_rows\n1\n", 16) != 0 ||
+        !STARTS_WITH(pszLine, "affected_rows\n1\n") ||
         psResult->pszErrBuf != NULL)
     {
-        CPLDebug( "GFT", "%s/%s", 
-                  pszLine ? pszLine : "null", 
+        CPLDebug( "GFT", "%s/%s",
+                  pszLine ? pszLine : "null",
                   psResult->pszErrBuf ? psResult->pszErrBuf : "null");
         CPLError(CE_Failure, CPLE_AppDefined, "Feature update failed (2)");
         CPLHTTPDestroyResult(psResult);
@@ -1089,11 +1086,11 @@ OGRErr OGRGFTTableLayer::DeleteFeature( GIntBig nFID )
 /* -------------------------------------------------------------------- */
     char* pszLine = (char*) psResult->pabyData;
     if (pszLine == NULL ||
-        strncmp(pszLine, "affected_rows\n1\n", 16) != 0 ||
+        !STARTS_WITH(pszLine, "affected_rows\n1\n") ||
         psResult->pszErrBuf != NULL)
     {
-        CPLDebug( "GFT", "%s/%s", 
-                  pszLine ? pszLine : "null", 
+        CPLDebug( "GFT", "%s/%s",
+                  pszLine ? pszLine : "null",
                   psResult->pszErrBuf ? psResult->pszErrBuf : "null");
         CPLError(CE_Failure, CPLE_AppDefined, "Feature deletion failed (2)");
         CPLHTTPDestroyResult(psResult);
@@ -1184,7 +1181,7 @@ OGRErr OGRGFTTableLayer::CommitTransaction()
 
         char* pszLine = (char*) psResult->pabyData;
         if (pszLine == NULL ||
-            strncmp(pszLine, "rowid", 5) != 0 ||
+            !STARTS_WITH(pszLine, "rowid") ||
             psResult->pszErrBuf != NULL)
         {
             CPLError(CE_Failure, CPLE_AppDefined, "CommitTransaction failed : %s",
diff --git a/ogr/ogrsf_frmts/gme/GNUmakefile b/ogr/ogrsf_frmts/gme/GNUmakefile
deleted file mode 100644
index e1dada6..0000000
--- a/ogr/ogrsf_frmts/gme/GNUmakefile
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-include ../../../GDALmake.opt
-
-OBJ	=	\
-	ogrgmedriver.o ogrgmedatasource.o ogrgmelayer.o ogrgmejson.o
-
-CPPFLAGS	:=	$(JSON_INCLUDE) -I../geojson -I.. -I../.. \
-	 $(CPPFLAGS)
-
-default:	$(O_OBJ:.o=.$(OBJ_EXT))
-
-clean:
-	rm -f *.o $(O_OBJ)
-
-$(O_OBJ):	ogr_gme.h
\ No newline at end of file
diff --git a/ogr/ogrsf_frmts/gme/makefile.vc b/ogr/ogrsf_frmts/gme/makefile.vc
deleted file mode 100644
index d790593..0000000
--- a/ogr/ogrsf_frmts/gme/makefile.vc
+++ /dev/null
@@ -1,15 +0,0 @@
-
-OBJ	=	ogrgmedriver.obj ogrgmedatasource.obj ogrgmelayer.obj ogrgmejson.obj
-EXTRAFLAGS =	-I.. -I..\.. -I..\geojson -I..\geojson\libjson
-
-GDAL_ROOT	=	..\..\..
-
-!INCLUDE $(GDAL_ROOT)\nmake.opt
-
-default:	$(OBJ)
-
-clean:
-	-del *.obj *.pdb
-
-
-
diff --git a/ogr/ogrsf_frmts/gme/ogr_gme.h b/ogr/ogrsf_frmts/gme/ogr_gme.h
deleted file mode 100644
index 8fbdcc6..0000000
--- a/ogr/ogrsf_frmts/gme/ogr_gme.h
+++ /dev/null
@@ -1,213 +0,0 @@
-/******************************************************************************
- * $Id: ogr_gft.h 25483 2013-01-10 17:06:59Z warmerdam $
- *
- * Project:  Google Maps Engine (GME) API Driver
- * Purpose:  GME driver declarations
- * Author:   Frank Warmerdam <warmerdam at pobox.com>
- *           (derived from GFT driver by Even)
- *
- ******************************************************************************
- * Copyright (c) 2013, Frank Warmerdam <warmerdam at pobox.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#ifndef _OGR_GME_H_INCLUDED
-#define _OGR_GME_H_INCLUDED
-
-#include "ogrsf_frmts.h"
-#include "ogrgeojsonreader.h"
-#include "cpl_http.h"
-
-#include <map>
-#include <vector>
-
-#include <json.h>
-
-/************************************************************************/
-/*                             OGRGMELayer                              */
-/************************************************************************/
-class OGRGMEDataSource;
-
-class OGRGMELayer : public OGRLayer
-{
-    OGRGMEDataSource* poDS;
-
-    OGRFeatureDefn*    poFeatureDefn;
-    OGRSpatialReference* poSRS;
-
-    int                iGeometryField;
-    int                iGxIdField;
-
-    CPLString          osTableName;
-    CPLString          osTableId;
-    std::map<int, CPLString> omnosIdToGMEKey;
-    std::map<int, OGRFeature *> omnpoUpdatedFeatures;
-    std::map<int, OGRFeature *> omnpoInsertedFeatures;
-    std::vector<GIntBig> oListOfDeletedFeatures;
-    CPLString          osGeomColumnName;
-
-    CPLString          osWhere;
-    CPLString          osSelect;
-    CPLString          osIntersects;
-
-    json_object*       current_feature_page;
-    json_object*       current_features_array;
-    int                index_in_page;
-
-    bool               bDirty;
-    bool               bCreateTablePending;
-    bool               bInTransaction;
-    unsigned int       iBatchPatchSize;
-    OGRwkbGeometryType eGTypeForCreation;
-    CPLString          osProjectId;
-    CPLString          osDraftACL;
-    CPLString          osPublishedACL;
-
-    void               GetPageOfFeatures();
-
-    void               BuildWhere(void);
-
-    int                FetchDescribe();
-
-    OGRFeature        *GetNextRawFeature();
-    void               GetPageOfFEatures();
-    OGRErr             BatchPatch();
-    OGRErr             BatchInsert();
-    OGRErr             BatchDelete();
-    OGRErr             BatchRequest(const char *osMethod, std::map<int, OGRFeature *> &omnpoFeatures);
-    unsigned int       GetBatchPatchSize();
-    bool               CreateTableIfNotCreated();
-    static OGRPolygon  *WindPolygonCCW( OGRPolygon *poPolygon );
-
-  public:
-    OGRGMELayer(OGRGMEDataSource* poDS, const char* pszTableId);
-    OGRGMELayer(OGRGMEDataSource* poDS, const char* pszTableName, char ** papszOptions);
-    ~OGRGMELayer();
-
-    virtual void       ResetReading();
-    void               SetBatchPatchSize(unsigned int iSize);
-
-    virtual OGRFeatureDefn *    GetLayerDefn();
-
-    virtual const char *GetName() { return osTableName.c_str(); }
-
-    virtual OGRFeature *GetNextFeature();
-
-    virtual const char *GetGeometryColumn() { return osGeomColumnName; }
-
-    virtual int         TestCapability( const char * );
-
-    virtual void        SetSpatialFilter( OGRGeometry * );
-
-    virtual OGRErr      SetAttributeFilter( const char * pszWhere );
-
-    virtual OGRErr      SetIgnoredFields(const char ** papszFields );
-
-    virtual OGRErr      SyncToDisk();
-
-    virtual OGRErr      ISetFeature( OGRFeature *poFeature );
-    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
-    virtual OGRErr      DeleteFeature(GIntBig);
-    virtual OGRErr      CreateField( OGRFieldDefn *poField, int bApproxOK = TRUE );
-
-    virtual OGRErr      StartTransaction();
-    virtual OGRErr      CommitTransaction();
-    virtual OGRErr      RollbackTransaction();
-
-    void                SetGeometryType(OGRwkbGeometryType eGType);
-};
-
-/************************************************************************/
-/*                           OGRGMEDataSource                           */
-/************************************************************************/
-
-class OGRGMEDataSource : public OGRDataSource
-{
-    char*               pszName;
-
-    OGRLayer**          papoLayers;
-    int                 nLayers;
-
-    int                 bReadWrite;
-
-    int                 bUseHTTPS;
-
-    CPLString           osAuth;
-    CPLString           osAccessToken;
-    CPLString           osRefreshToken;
-    CPLString           osTraceToken;
-    CPLString           osAPIKey;
-    CPLString           osSelect;
-    CPLString           osWhere;
-    CPLString           osProjectId;
-
-    void                DeleteLayer( const char *pszLayerName );
-
-    int                 bMustCleanPersistant;
-    int                 nRetries;
-
-  public:
-                        OGRGMEDataSource();
-                        ~OGRGMEDataSource();
-
-    int                 Open( const char * pszFilename,
-                              int bUpdate );
-
-    virtual const char* GetName() { return pszName; }
-
-    virtual int         GetLayerCount() { return nLayers; }
-    virtual OGRLayer*   GetLayer( int );
-
-    virtual OGRLayer   *ICreateLayer( const char *pszName,
-                                     OGRSpatialReference *poSpatialRef = NULL,
-                                     OGRwkbGeometryType eGType = wkbUnknown,
-                                     char ** papszOptions = NULL );
-
-    virtual int         TestCapability( const char * );
-
-    CPLHTTPResult*      MakeRequest(const char *pszRequest,
-                                    const char *pszMoreOptions = NULL);
-    CPLHTTPResult*      PostRequest(const char *pszRequest,
-                                    const char *pszBody);
-    const CPLString&    GetAccessToken() const { return osAccessToken;}
-    const char*         GetAPIURL() const;
-    int                 IsReadWrite() const { return bReadWrite; }
-    void                AddHTTPOptions(CPLStringList &oOptions);
-    void                AddHTTPPostOptions(CPLStringList &oOptions);
-
-};
-
-/************************************************************************/
-/*                             OGRGMEDriver                             */
-/************************************************************************/
-
-class OGRGMEDriver : public OGRSFDriver
-{
-  public:
-                ~OGRGMEDriver();
-
-    virtual const char*         GetName();
-    virtual OGRDataSource*      Open( const char *, int );
-    virtual OGRDataSource*      CreateDataSource( const char * pszName,
-                                                  char **papszOptions );
-    virtual int                 TestCapability( const char * );
-};
-
-#endif /* ndef _OGR_GME_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/gme/ogrgmedatasource.cpp b/ogr/ogrsf_frmts/gme/ogrgmedatasource.cpp
deleted file mode 100644
index cf9b8a4..0000000
--- a/ogr/ogrsf_frmts/gme/ogrgmedatasource.cpp
+++ /dev/null
@@ -1,598 +0,0 @@
-/******************************************************************************
- * $Id$
- *
- * Project:  Google Maps Engine API Driver
- * Purpose:  OGRGMEDataSource Implementation.
- * Author:   Frank Warmerdam <warmerdam at pobox.com>
- *           (derived from GFT driver by Even)
- *
- ******************************************************************************
- * Copyright (c) 2013, Frank Warmerdam <warmerdam at pobox.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "ogr_gme.h"
-#include "ogrgmejson.h"
-#include "cpl_multiproc.h"
-
-CPL_CVSID("$Id$");
-
-#define GDAL_API_KEY "AIzaSyA_2h1_wXMOLHNSVeo-jf1ACME-M1XMgP0"
-#define GME_TABLE_SCOPE_RO "https://www.googleapis.com/auth/mapsengine.readonly"
-#define GME_TABLE_SCOPE "https://www.googleapis.com/auth/mapsengine"
-
-/************************************************************************/
-/*                          OGRGMEDataSource()                          */
-/************************************************************************/
-
-OGRGMEDataSource::OGRGMEDataSource()
-
-{
-    papoLayers = NULL;
-    nLayers = 0;
-
-    pszName = NULL;
-
-    bReadWrite = FALSE;
-    bUseHTTPS = FALSE;
-
-    bMustCleanPersistant = FALSE;
-    nRetries = 0;
-}
-
-/************************************************************************/
-/*                         ~OGRGMEDataSource()                          */
-/************************************************************************/
-
-OGRGMEDataSource::~OGRGMEDataSource()
-
-{
-    for( int i = 0; i < nLayers; i++ )
-        delete papoLayers[i];
-    CPLFree( papoLayers );
-
-    if (bMustCleanPersistant)
-    {
-        char** papszOptions = NULL;
-        papszOptions = CSLSetNameValue(papszOptions, "CLOSE_PERSISTENT", CPLSPrintf("GME:%p", this));
-        CPLHTTPFetch( GetAPIURL(), papszOptions);
-        CSLDestroy(papszOptions);
-    }
-
-    CPLFree( pszName );
-}
-
-/************************************************************************/
-/*                           TestCapability()                           */
-/************************************************************************/
-
-int OGRGMEDataSource::TestCapability( const char * pszCap )
-
-{
-    if( EQUAL(pszCap,ODsCCreateLayer) )
-        return TRUE;
-    //else if( bReadWrite && EQUAL(pszCap,ODsCDeleteLayer) )
-    //    return TRUE;
-    //else
-    return FALSE;
-}
-
-/************************************************************************/
-/*                              GetLayer()                              */
-/************************************************************************/
-
-OGRLayer *OGRGMEDataSource::GetLayer( int iLayer )
-
-{
-    if( iLayer < 0 || iLayer >= nLayers )
-        return NULL;
-    else
-        return papoLayers[iLayer];
-}
-
-/************************************************************************/
-/*                      OGRGMEGetOptionValue()                          */
-/************************************************************************/
-
-CPLString OGRGMEGetOptionValue(const char* pszFilename,
-                               const char* pszOptionName)
-{
-    CPLString osOptionName(pszOptionName);
-    osOptionName += "=";
-    const char* pszOptionValue = strstr(pszFilename, osOptionName);
-    if (!pszOptionValue)
-        return "";
-
-    CPLString osOptionValue(pszOptionValue + strlen(osOptionName));
-    const char* pszSpace = strchr(osOptionValue.c_str(), ' ');
-    if (pszSpace)
-        osOptionValue.resize(pszSpace - osOptionValue.c_str());
-    return osOptionValue;
-}
-
-/************************************************************************/
-/*                                Open()                                */
-/************************************************************************/
-
-int OGRGMEDataSource::Open( const char * pszFilename, int bUpdateIn)
-
-{
-    bReadWrite = bUpdateIn;
-
-    pszName = CPLStrdup( pszFilename );
-
-    osAuth = OGRGMEGetOptionValue(pszFilename, "auth");
-    if (osAuth.size() == 0)
-        osAuth = CPLGetConfigOption("GME_AUTH", "");
-
-    osRefreshToken = OGRGMEGetOptionValue(pszFilename, "refresh");
-    if (osRefreshToken.size() == 0)
-        osRefreshToken = CPLGetConfigOption("GME_REFRESH_TOKEN", "");
-
-    osAPIKey = CPLGetConfigOption("GME_APIKEY", GDAL_API_KEY);
-
-    CPLString osTables = OGRGMEGetOptionValue(pszFilename, "tables");
-
-    osProjectId = OGRGMEGetOptionValue(pszFilename, "projectId");
-
-    osSelect = OGRGMEGetOptionValue(pszFilename, "select");
-    osWhere = OGRGMEGetOptionValue(pszFilename, "where");
-
-    CPLString osBatchPatchSize;
-    osBatchPatchSize = OGRGMEGetOptionValue(pszFilename, "batchpatchsize");
-    if (osBatchPatchSize.size() == 0) {
-        osBatchPatchSize = CPLGetConfigOption("GME_BATCH_PATCH_SIZE","50");
-    }
-    int iBatchPatchSize = atoi( osBatchPatchSize.c_str() );
-
-    bUseHTTPS = TRUE;
-
-    osAccessToken = OGRGMEGetOptionValue(pszFilename, "access");
-    if (osAccessToken.size() == 0)
-        osAccessToken = CPLGetConfigOption("GME_ACCESS_TOKEN","");
-    if (osAccessToken.size() == 0 && osRefreshToken.size() > 0)
-    {
-        osAccessToken.Seize(GOA2GetAccessToken(osRefreshToken,
-                                               GME_TABLE_SCOPE)); // TODO
-        if (osAccessToken.size() == 0) {
-            CPLDebug( "GME", "Cannot get access token");
-            return FALSE;
-        }
-    }
-
-    if (osAccessToken.size() == 0 && osAuth.size() > 0)
-    {
-        osRefreshToken.Seize(GOA2GetRefreshToken(osAuth, GME_TABLE_SCOPE)); // TODO
-        if (osRefreshToken.size() == 0)
-            CPLDebug( "GME", "Cannot get refresh token");
-            return FALSE;
-    }
-
-    if ((osAccessToken.size() ==0) && (osTables.size() == 0))
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Unauthenticated access requires explicit tables= parameter");
-        return FALSE;
-    }
-
-    osTraceToken = OGRGMEGetOptionValue(pszFilename, "trace");
-    if (osTraceToken.size() == 0) {
-        CPLDebug("GME", "Looking for GME_TRACE_TOKEN");
-        osTraceToken = CPLGetConfigOption("GME_TRACE_TOKEN", "");
-    }
-    if (osTraceToken.size() != 0) {
-      CPLDebug("GME", "Found trace token %s", osTraceToken.c_str());
-    }
-
-    if (osTables.size() != 0)
-    {
-        char** papszTables = CSLTokenizeString2(osTables, ",", 0);
-        for(int i=0;papszTables && papszTables[i];i++)
-        {
-            papoLayers = (OGRLayer**) CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
-            OGRGMELayer *poGMELayer = new OGRGMELayer(this, papszTables[i]);
-            poGMELayer->SetBatchPatchSize(iBatchPatchSize);
-            if (poGMELayer->GetLayerDefn()) {
-                papoLayers[nLayers ++] = poGMELayer;
-            }
-            else {
-                delete poGMELayer;
-            }
-        }
-        CSLDestroy(papszTables);
-        if ( nLayers == 0 ) {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "Could not find any tables.");
-            return FALSE;
-        }
-        CPLDebug("GME", "Found %d layers", nLayers);
-        return TRUE;
-    }
-    else if (osProjectId.size() != 0) {
-        CPLDebug("GME", "We have a projectId: %s. UseICreateLayer to create tables.",
-                 osProjectId.c_str());
-        return TRUE;
-    }
-    CPLDebug("GME", "No table no project, giving up!");
-    return FALSE;
-}
-
-/************************************************************************/
-/*                          ICreateLayer()                              */
-/************************************************************************/
-
-OGRLayer   *OGRGMEDataSource::ICreateLayer( const char *pszName,
-                                            CPL_UNUSED OGRSpatialReference *poSpatialRef,
-                                            OGRwkbGeometryType eGType,
-                                            char ** papszOptions )
-{
-    if (!bReadWrite)
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "Operation not available in read-only mode");
-        return NULL;
-    }
-
-    if (osAccessToken.size() == 0)
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "Operation not available in unauthenticated mode");
-        return NULL;
-    }
-
-    if ((CSLFetchNameValue( papszOptions, "projectId" ) == NULL) && (osProjectId.size() != 0)) {
-        papszOptions = CSLAddNameValue( papszOptions, "projectId", osProjectId.c_str() );
-    }
-
-    osTraceToken = OGRGMEGetOptionValue(pszName, "trace");
-    if (osTraceToken.size() == 0) {
-      osTraceToken = CPLGetConfigOption("GME_TRACE_TOKEN", "");
-    }
-    if (osTraceToken.size() != 0) {
-      CPLDebug("GME", "Found trace token %s", osTraceToken.c_str());
-    }
-
-    OGRGMELayer* poLayer = new OGRGMELayer(this, pszName, papszOptions);
-    poLayer->SetGeometryType(eGType);
-    papoLayers = (OGRLayer**) CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
-    papoLayers[nLayers ++] = poLayer;
-    return poLayer;
-}
-
-/************************************************************************/
-/*                            GetAPIURL()                               */
-/************************************************************************/
-
-const char*  OGRGMEDataSource::GetAPIURL() const
-{
-    const char* pszAPIURL = CPLGetConfigOption("GME_API_URL", NULL);
-    if (pszAPIURL)
-        return pszAPIURL;
-    else if (bUseHTTPS)
-        return "https://www.googleapis.com/mapsengine/v1";
-    else
-        return "http://www.googleapis.com/mapsengine/v1";
-}
-
-/************************************************************************/
-/*                          AddHTTPOptions()                            */
-/************************************************************************/
-
-void OGRGMEDataSource::AddHTTPOptions(CPLStringList &oOptions)
-{
-    bMustCleanPersistant = TRUE;
-
-    if (strlen(osAccessToken) > 0)
-        oOptions.AddString(
-            CPLSPrintf("HEADERS=Authorization: Bearer %s",
-                       osAccessToken.c_str()));
-
-    oOptions.AddString(CPLSPrintf("PERSISTENT=GME:%p", this));
-}
-
-/************************************************************************/
-/*                            MakeRequest()                             */
-/************************************************************************/
-
-CPLHTTPResult * OGRGMEDataSource::MakeRequest(const char *pszRequest,
-                                              const char *pszMoreOptions)
-{
-/* -------------------------------------------------------------------- */
-/*      Provide the API Key - used to rate limit access (see            */
-/*      GME_APIKEY config)                                              */
-/* -------------------------------------------------------------------- */
-    CPLString osQueryFields;
-
-    osQueryFields += "key=";
-    osQueryFields += osAPIKey;
-
-    if (pszMoreOptions)
-        osQueryFields += pszMoreOptions;
-
-/* -------------------------------------------------------------------- */
-/*      Collect the header options.                                     */
-/* -------------------------------------------------------------------- */
-    CPLStringList oOptions;
-    oOptions.AddString("CUSTOMREQUEST=GET");
-    AddHTTPOptions(oOptions);
-
-/* -------------------------------------------------------------------- */
-/*      Build URL                                                       */
-/* -------------------------------------------------------------------- */
-    CPLString osURL = GetAPIURL();
-    osURL += "/";
-    osURL += pszRequest;
-
-    if (osURL.find("?") == std::string::npos) {
-        osURL += "?";
-    } else {
-        osURL += "?";
-    }
-    osURL += osQueryFields;
-
-    // Trace the request if we have a tracing token
-    if (osTraceToken.size() != 0) {
-      CPLDebug("GME", "Using trace token %s", osTraceToken.c_str());
-      osURL += "&trace=";
-      osURL += osTraceToken;
-    }
-
-    CPLDebug( "GME", "Sleep for 1s to try and avoid qps limiting errors.");
-    CPLSleep( 1.0 );
-
-    CPLHTTPResult * psResult = CPLHTTPFetch(osURL, oOptions);
-
-/* -------------------------------------------------------------------- */
-/*      Check for some error conditions and report.  HTML Messages      */
-/*      are transformed info failure.                                   */
-/* -------------------------------------------------------------------- */
-    if (psResult && psResult->pszContentType &&
-        strncmp(psResult->pszContentType, "text/html", 9) == 0)
-    {
-        CPLDebug( "GME", "MakeRequest HTML Response: %s", psResult->pabyData );
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "HTML error page returned by server");
-        if (nRetries < 5) {
-            CPLDebug("GME", "Sleeping 30s and retrying");
-            nRetries ++;
-            CPLSleep( 30.0 );
-            psResult = MakeRequest(pszRequest, pszMoreOptions);
-            if (psResult)
-                CPLDebug( "GME", "Got a result after %d retries", nRetries );
-            else
-                CPLDebug( "GME", "Didn't get a result after %d retries", nRetries );
-            nRetries--;
-        } else {
-            CPLDebug("GME", "I've waited too long on GME. Giving up!");
-            CPLHTTPDestroyResult(psResult);
-            psResult = NULL;
-        }
-        return psResult;
-    }
-    if (psResult && psResult->pszErrBuf != NULL)
-    {
-        CPLDebug( "GME", "MakeRequest Error Message: %s", psResult->pszErrBuf );
-        CPLDebug( "GME", "error doc:\n%s\n", psResult->pabyData ? (const char*)psResult->pabyData : "null");
-        json_object *error_response = OGRGMEParseJSON((const char *) psResult->pabyData);
-        CPLHTTPDestroyResult(psResult);
-        psResult = NULL;
-        if( error_response != NULL )
-        {
-            json_object *error_doc = json_object_object_get(error_response, "error");
-            json_object *errors_doc = json_object_object_get(error_doc, "errors");
-            array_list *errors_array = json_object_get_array(errors_doc);
-            int nErrors = array_list_length(errors_array);
-            for (int i = 0; i < nErrors; i++) {
-                json_object *error_obj = (json_object *)array_list_get_idx(errors_array, i);
-                const char* reason = OGRGMEGetJSONString(error_obj, "reason", "");
-                const char* domain = OGRGMEGetJSONString(error_obj, "domain", "");
-                const char* message = OGRGMEGetJSONString(error_obj, "message", "");
-                const char* locationType = OGRGMEGetJSONString(error_obj, "locationType", "");
-                const char* location = OGRGMEGetJSONString(error_obj, "location", "");
-                if ((nRetries < 10) && EQUAL(reason, "rateLimitExceeded")) {
-                    // Sleep nRetries * 1.0s and retry
-                    nRetries ++;
-                    CPLDebug( "GME", "Got a %s (%d) times.", reason, nRetries );
-                    CPLDebug( "GME", "Sleep for %2.2f to try and avoid qps limiting errors.", 1.0 * nRetries );
-                    CPLSleep( 1.0 * nRetries );
-                    psResult = MakeRequest(pszRequest, pszMoreOptions);
-                    if (psResult)
-                        CPLDebug( "GME", "Got a result after %d retries", nRetries );
-                    else
-                        CPLDebug( "GME", "Didn't get a result after %d retries", nRetries );
-                    nRetries = 0;
-                }
-                else if (EQUAL(reason, "authError")) {
-                        CPLDebug( "GME", "Failed to GET %s: %s", pszRequest, message );
-                        CPLError( CE_Failure, CPLE_OpenFailed, "GME: %s", message);
-                }
-                else if (EQUAL(reason, "backendError")) {
-                        CPLDebug( "GME", "Backend error retrying: GET %s: %s", pszRequest, message );
-                        psResult = MakeRequest(pszRequest, pszMoreOptions);
-                }
-                else {
-                    int code = 444;
-                    json_object *code_child = json_object_object_get(error_doc, "code");
-                    if (code_child != NULL )
-                        code = json_object_get_int(code_child);
-
-                    CPLDebug( "GME", "MakeRequest Error for %s: %s:%d", pszRequest, reason, code);
-                    CPLError( CE_Failure, CPLE_AppDefined, "GME: %s %s %s: %s - %s",
-                            domain, reason, locationType, location, message );
-                }
-            }
-            json_object_put(error_response);
-        }
-        return psResult;
-    }
-    else if (psResult && psResult->nStatus != 0)
-    {
-        CPLDebug( "GME", "MakeRequest Error Status:%d", psResult->nStatus );
-    }
-    return psResult;
-}
-
-/************************************************************************/
-/*                        AddHTTPPostOptions()                          */
-/************************************************************************/
-
-void OGRGMEDataSource::AddHTTPPostOptions(CPLStringList &oOptions)
-{
-    bMustCleanPersistant = TRUE;
-
-    if (strlen(osAccessToken) > 0)
-        oOptions.AddString(
-            CPLSPrintf("HEADERS=Content-type: application/json\n"
-                       "Authorization: Bearer %s",
-                       osAccessToken.c_str()));
-
-    oOptions.AddString(CPLSPrintf("PERSISTENT=GME:%p", this));
-}
-
-/************************************************************************/
-/*                            PostRequest()                             */
-/************************************************************************/
-
-CPLHTTPResult * OGRGMEDataSource::PostRequest(const char *pszRequest,
-                                              const char *pszBody)
-{
-/* -------------------------------------------------------------------- */
-/*      Provide the API Key - used to rate limit access (see            */
-/*      GME_APIKEY config)                                              */
-/* -------------------------------------------------------------------- */
-    CPLString osQueryFields;
-
-    osQueryFields += "key=";
-    osQueryFields += osAPIKey;
-
-/* -------------------------------------------------------------------- */
-/*      Collect the header options.                                     */
-/* -------------------------------------------------------------------- */
-    CPLStringList oOptions;
-    oOptions.AddString("CUSTOMREQUEST=POST");
-    CPLString osPostFields = "POSTFIELDS=";
-    osPostFields += pszBody;
-    oOptions.AddString(osPostFields);
-
-    AddHTTPPostOptions(oOptions);
-
-/* -------------------------------------------------------------------- */
-/*      Build URL                                                       */
-/* -------------------------------------------------------------------- */
-    CPLString osURL = GetAPIURL();
-    osURL += "/";
-    osURL += pszRequest;
-
-    if (osURL.find("?") == std::string::npos) {
-        osURL += "?";
-    } else {
-        osURL += "?";
-    }
-    osURL += osQueryFields;
-
-    // Trace the request if we have a tracing token
-    if (osTraceToken.size() != 0) {
-      CPLDebug("GME", "Using trace token %s", osTraceToken.c_str());
-      osURL += "&trace=";
-      osURL += osTraceToken;
-    }
-
-    CPLDebug( "GME", "Sleep for 1s to try and avoid qps limiting errors.");
-    CPLSleep( 1.0 );
-
-    CPLDebug( "GME", "Posting to %s.", osURL.c_str());
-    CPLHTTPResult * psResult = CPLHTTPFetch(osURL, oOptions);
-
-/* -------------------------------------------------------------------- */
-/*      Check for some error conditions and report.  HTML Messages      */
-/*      are transformed info failure.                                   */
-/* -------------------------------------------------------------------- */
-    if (psResult && psResult->pszContentType &&
-        strncmp(psResult->pszContentType, "text/html", 9) == 0)
-    {
-        CPLDebug( "GME", "PostRequest HTML Response:%s", psResult->pabyData );
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "HTML error page returned by server");
-        CPLHTTPDestroyResult(psResult);
-        psResult = NULL;
-    }
-    if (psResult && psResult->pszErrBuf != NULL)
-    {
-        CPLDebug( "GME", "PostRequest Error Message: %s", psResult->pszErrBuf );
-        CPLDebug( "GME", "error doc:\n%s\n", psResult->pabyData);
-        json_object *error_response = OGRGMEParseJSON((const char *) psResult->pabyData);
-        CPLHTTPDestroyResult(psResult);
-        psResult = NULL;
-        json_object *error_doc = json_object_object_get(error_response, "error");
-        json_object *errors_doc = json_object_object_get(error_doc, "errors");
-        array_list *errors_array = json_object_get_array(errors_doc);
-        int nErrors = array_list_length(errors_array);
-        for (int i = 0; i < nErrors; i++) {
-            json_object *error_obj = (json_object *)array_list_get_idx(errors_array, i);
-            const char* reason = OGRGMEGetJSONString(error_obj, "reason", "");
-            const char* domain = OGRGMEGetJSONString(error_obj, "domain", "");
-            const char* message = OGRGMEGetJSONString(error_obj, "message", "");
-            const char* locationType = OGRGMEGetJSONString(error_obj, "locationType", "");
-            const char* location = OGRGMEGetJSONString(error_obj, "location", "");
-            if ((nRetries < 10) && EQUAL(reason, "rateLimitExceeded")) {
-                // Sleep nRetries * 1.0s and retry
-                nRetries ++;
-                CPLDebug( "GME", "Got a %s (%d) times.", reason, nRetries );
-                CPLDebug( "GME", "Sleep for %2.2f to try and avoid qps limiting errors.", 1.0 * nRetries );
-                CPLSleep( 1.0 * nRetries );
-                psResult = PostRequest(pszRequest, pszBody);
-                if (psResult)
-                    CPLDebug( "GME", "Got a result after %d retries", nRetries );
-                else
-                    CPLDebug( "GME", "Didn't get a result after %d retries", nRetries );
-                nRetries = 0;
-            }
-	    else if (EQUAL(reason, "authError")) {
-                CPLDebug( "GME", "Failed to GET %s: %s", pszRequest, message );
-                CPLError( CE_Failure, CPLE_OpenFailed, "GME: %s", message);
-	    }
-	    else if (EQUAL(reason, "backendError")) {
-                CPLDebug( "GME", "Backend error retrying: GET %s: %s", pszRequest, message );
-                psResult = PostRequest(pszRequest, pszBody);
-	    }
-            else {
-                int code = 444;
-                json_object *code_child = json_object_object_get(error_doc, "code");
-                if (code_child != NULL )
-                    code = json_object_get_int(code_child);
-
-                CPLError( CE_Failure, CPLE_AppDefined, "GME: %s %s %s: %s - %s",
-                          domain, reason, locationType, location, message );
-                if ((code == 400) && (EQUAL(reason, "invalid")) && (EQUAL(location, "id"))) {
-                  CPLDebug("GME", "Got the notorious 400 - invalid id, retrying in 10s");
-                  CPLSleep( 10.0 );
-                  psResult = PostRequest(pszRequest, pszBody);
-                }
-                else {
-                    CPLDebug( "GME", "PostRequest Error for %s: %s:%d", pszRequest, reason, code);
-                }
-            }
-        }
-        return psResult;
-    }
-    else if (psResult && psResult->nStatus != 0)
-    {
-        CPLDebug( "GME", "PostRequest Error Status:%d", psResult->nStatus );
-    }
-    return psResult;
-}
diff --git a/ogr/ogrsf_frmts/gme/ogrgmedriver.cpp b/ogr/ogrsf_frmts/gme/ogrgmedriver.cpp
deleted file mode 100644
index faeb50e..0000000
--- a/ogr/ogrsf_frmts/gme/ogrgmedriver.cpp
+++ /dev/null
@@ -1,122 +0,0 @@
-/******************************************************************************
- * $Id$
- *
- * Project:  Google Maps Engine API Driver
- * Purpose:  OGRGMEDriver Implementation.
- * Author:   Frank Warmerdam <warmerdam at pobox.com>
- *           (derived from GFT driver by Even)
- *
- ******************************************************************************
- * Copyright (c) 2013, Frank Warmerdam <warmerdam at pobox.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "ogr_gme.h"
-
-CPL_CVSID("$Id$");
-
-extern "C" void RegisterOGRGME();
-
-/************************************************************************/
-/*                           ~OGRGMEDriver()                            */
-/************************************************************************/
-
-OGRGMEDriver::~OGRGMEDriver()
-
-{
-}
-
-/************************************************************************/
-/*                              GetName()                               */
-/************************************************************************/
-
-const char *OGRGMEDriver::GetName()
-
-{
-    return "GME";
-}
-
-/************************************************************************/
-/*                                Open()                                */
-/************************************************************************/
-
-OGRDataSource *OGRGMEDriver::Open( const char * pszFilename, int bUpdate )
-
-{
-    if (!EQUALN(pszFilename, "GME:", 4))
-        return NULL;
-
-    OGRGMEDataSource   *poDS = new OGRGMEDataSource();
-
-    if( !poDS->Open( pszFilename, bUpdate ) )
-    {
-        delete poDS;
-        poDS = NULL;
-    }
-
-    return poDS;
-}
-
-
-/************************************************************************/
-/*                          CreateDataSource()                          */
-/************************************************************************/
-
-OGRDataSource *OGRGMEDriver::CreateDataSource( const char * pszName,
-                                               CPL_UNUSED char **papszOptions )
-{
-    OGRGMEDataSource   *poDS = new OGRGMEDataSource();
-
-    if( !poDS->Open( pszName, TRUE ) )
-    {
-        delete poDS;
-        poDS = NULL;
-    }
-
-    return poDS;
-}
-
-/************************************************************************/
-/*                           TestCapability()                           */
-/************************************************************************/
-
-int OGRGMEDriver::TestCapability( const char * pszCap )
-
-{
-    if (EQUAL(pszCap, ODrCCreateDataSource))
-        return TRUE;
-
-    return FALSE;
-}
-
-/************************************************************************/
-/*                           RegisterOGRGME()                           */
-/************************************************************************/
-
-void RegisterOGRGME()
-
-{
-    OGRSFDriver* poDriver = new OGRGMEDriver;
-    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Google Maps Engine" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "http://trac.osgeo.org/gdal/wiki/GMEDriver" );
-    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver(poDriver);
-}
diff --git a/ogr/ogrsf_frmts/gme/ogrgmejson.cpp b/ogr/ogrsf_frmts/gme/ogrgmejson.cpp
deleted file mode 100644
index c54ea49..0000000
--- a/ogr/ogrsf_frmts/gme/ogrgmejson.cpp
+++ /dev/null
@@ -1,550 +0,0 @@
-/******************************************************************************
- * $Id$
- *
- * Project:  Google Maps Engine API Driver
- * Purpose:  GME GeoJSON helpper function Implementations.
- * Author:   Wolf Beregnheim <wolf+grass at bergenheim.net>
- *           (derived from Geo JSON driver by Mateusz)
- *
- ******************************************************************************
- * Copyright (c) 2013, Frank Warmerdam <warmerdam at pobox.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "ogrgmejson.h"
-#include <printbuf.h>
-
-static int json_gme_double_to_string(json_object *jso,
-                                     printbuf *pb,
-                                     int level,
-                                     int flags);
-
-/************************************************************************/
-/*                      OGRGMEFeatureToGeoJSON()                        */
-/************************************************************************/
-json_object* OGRGMEFeatureToGeoJSON(OGRFeature* poFeature)
-
-{
-    if( NULL == poFeature )
-        return NULL;
-
-    json_object* pjoFeature = json_object_new_object();
-    CPLAssert( NULL != pjoFeature );
-
-    json_object_object_add( pjoFeature, "type",
-                            json_object_new_string("Feature") );
-
-    /* -------------------------------------------------------------------- */
-    /*      Write feature geometry to GeoJSON "geometry" object.            */
-    /* -------------------------------------------------------------------- */
-    json_object* pjoGeometry = NULL;
-    OGRGeometry* poGeometry = poFeature->GetGeometryRef();
-
-    pjoGeometry = OGRGMEGeometryToGeoJSON(poGeometry);
-    if ( NULL == pjoGeometry ) {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "GME: NULL Geometry detected in feature " CPL_FRMT_GIB ". Ignoring feature.",
-                  poFeature->GetFID() );
-        json_object_put( pjoFeature );
-        return NULL;
-    }
-    json_object_object_add( pjoFeature, "geometry", pjoGeometry );
-
-    /* -------------------------------------------------------------------- */
-    /*      Write feature attributes to GeoJSON "properties" object.        */
-    /* -------------------------------------------------------------------- */
-    json_object* pjoProps = NULL;
-
-    pjoProps = OGRGMEAttributesToGeoJSON( poFeature );
-    if ( pjoProps )
-        json_object_object_add( pjoFeature, "properties", pjoProps );
-
-    return pjoFeature;
-}
-
-/************************************************************************/
-/*                        OGRGMEGeometryToGeoJSON()                     */
-/************************************************************************/
-json_object* OGRGMEGeometryToGeoJSON(OGRGeometry* poGeometry)
-
-{
-    if ( NULL == poGeometry )
-        return NULL;
-
-    json_object* pjoGeometry = json_object_new_object();
-    CPLAssert( NULL != pjoGeometry );
-
-    /* -------------------------------------------------------------------- */
-    /*      Build "type" member of GeoJSOn "geometry" object                */
-    /*      and "coordinates" member of GeoJSOn "geometry" object.          */
-    /* -------------------------------------------------------------------- */
-    const char* pszType = NULL;
-    OGRwkbGeometryType eType = poGeometry->getGeometryType();
-    json_object* pjoCoordinates = NULL;
-    if( wkbGeometryCollection == eType || wkbGeometryCollection25D == eType )
-    {
-        pszType = "GeometryCollection";
-        json_object *pjoGeometries =
-            OGRGMEGeometryCollectionToGeoJSON(static_cast<OGRGeometryCollection*>(poGeometry));
-        if ( pjoGeometries ) {
-            json_object *pjoType = json_object_new_string(pszType);
-            json_object_object_add( pjoGeometry, "type", pjoType );
-            json_object_object_add( pjoGeometry, "geometries", pjoGeometries );
-        }
-        else {
-            json_object_put(pjoGeometry);
-            pjoGeometry = NULL;
-        }            
-    }
-    else 
-    {
-        if( wkbPoint == eType || wkbPoint25D == eType ) {
-            pszType = "Point";
-            pjoCoordinates = OGRGMEPointToGeoJSON( static_cast<OGRPoint*>(poGeometry) );
-        }
-        if( wkbMultiPoint == eType || wkbMultiPoint25D == eType ) {
-            pszType = "MultiPoint";
-            pjoCoordinates = OGRGMEMultiPointToGeoJSON( static_cast<OGRMultiPoint*>(poGeometry) );
-        }
-        else if( wkbLineString == eType || wkbLineString25D == eType ) {
-            pszType = "LineString";
-            pjoCoordinates = OGRGMELineStringToGeoJSON( static_cast<OGRLineString*>(poGeometry) );
-        }
-        else if( wkbMultiLineString == eType || wkbMultiLineString25D == eType ) {
-            pszType = "MultiLineString";
-            pjoCoordinates = OGRGMEMultiLineStringToGeoJSON( static_cast<OGRMultiLineString*>(poGeometry) );
-        }
-        else if( wkbPolygon == eType || wkbPolygon25D == eType ) {
-            pszType = "Polygon";
-            pjoCoordinates = OGRGMEPolygonToGeoJSON( static_cast<OGRPolygon*>(poGeometry) );
-        }
-        else if( wkbMultiPolygon == eType || wkbMultiPolygon25D == eType ) {
-            pszType = "MultiPolygon";
-            pjoCoordinates = OGRGMEMultiPolygonToGeoJSON( static_cast<OGRMultiPolygon*>(poGeometry) );
-        }
-        else {
-            CPLDebug( "GME", "Unsupported geometry type detected. Geometry is IGNORED." );
-        }
-
-        if ( pjoCoordinates && pszType ) {
-            json_object *pjoType = json_object_new_string(pszType);
-            json_object_object_add( pjoGeometry, "type", pjoType );
-            json_object_object_add( pjoGeometry, "coordinates", pjoCoordinates);
-        }
-        else {
-            json_object_put(pjoGeometry);
-            pjoGeometry = NULL;
-        }
-    }
-    return pjoGeometry;
-}
-
-/************************************************************************/
-/*                  OGRGMEGeometryCollectionToGeoJSON()                 */
-/************************************************************************/
-json_object* OGRGMEGeometryCollectionToGeoJSON(OGRGeometryCollection* poGeometryCollection)
-
-{
-    if ( NULL == poGeometryCollection )
-        return NULL;
-
-    /* Generate "geometries" object. */
-    json_object* pjoGeometries = NULL;
-    pjoGeometries = json_object_new_array();
-
-    for( int i = 0; i < poGeometryCollection->getNumGeometries(); ++i ) {
-        OGRGeometry* poGeometry = poGeometryCollection->getGeometryRef( i );
-        json_object* pjoGeometry = NULL;
-        pjoGeometry = OGRGMEGeometryToGeoJSON( poGeometry );
-        if ( NULL != poGeometry )
-            json_object_array_add( pjoGeometries, pjoGeometry );
-        else
-            CPLError( CE_Failure, CPLE_AppDefined, "GME: Ignoring NULL geometry" );
-    }
-    return pjoGeometries;
-}
-
-/************************************************************************/
-/*                           OGRGMEPointToGeoJSON                       */
-/************************************************************************/
-
-json_object* OGRGMEPointToGeoJSON( OGRPoint* poPoint )
-{
-    if( NULL == poPoint )
-        return NULL;
-
-    json_object* pjoCoordinates = NULL;
-
-    /* Generate "coordinates" object for 2D or 3D dimension. */
-    if( 3 == poPoint->getCoordinateDimension() ) {
-        pjoCoordinates = OGRGMECoordsToGeoJSON( poPoint->getX(),
-                                                poPoint->getY(),
-                                                poPoint->getZ() );
-    }
-    else if( 2 == poPoint->getCoordinateDimension() ) {
-        pjoCoordinates = OGRGMECoordsToGeoJSON( poPoint->getX(),
-                                                poPoint->getY() );
-    }
-    else {
-        CPLError( CE_Failure, CPLE_AppDefined, "GME: Found EMPTY point, ignoring" );
-    }
-
-    return pjoCoordinates;
-}
-
-/************************************************************************/
-/*                           OGRGMEMultiPointToGeoJSON                  */
-/************************************************************************/
-
-json_object* OGRGMEMultiPointToGeoJSON( OGRMultiPoint* poGeometry )
-{
-    if( NULL == poGeometry )
-        return NULL;
-
-    /* Generate "coordinates" object for 2D or 3D dimension. */
-    json_object* pjoMultiPoint = NULL;
-    pjoMultiPoint = json_object_new_array();
-
-    for( int i = 0; i < poGeometry->getNumGeometries(); ++i )
-        {
-            OGRGeometry* poGeom = poGeometry->getGeometryRef( i );
-            CPLAssert( NULL != poGeom );
-            OGRPoint* poPoint = static_cast<OGRPoint*>(poGeom);
-
-            json_object* pjoPoint = NULL;
-            pjoPoint = OGRGMEPointToGeoJSON( poPoint );
-            if ( pjoPoint )
-                json_object_array_add( pjoMultiPoint, pjoPoint );
-        }
-
-    return pjoMultiPoint;
-}
-
-/************************************************************************/
-/*                           OGRGMELineStringToGeoJSON                  */
-/************************************************************************/
-
-json_object* OGRGMELineStringToGeoJSON( OGRLineString* poLine )
-{
-    if( NULL == poLine )
-        return NULL;
-
-    /* Generate "coordinates" object for 2D or 3D dimension. */
-    json_object* pjoLineString = NULL;
-    pjoLineString = OGRGMELineCoordsToGeoJSON( poLine );
-
-    return pjoLineString;
-}
-
-/************************************************************************/
-/*                           OGRGMEMultiLineStringToGeoJSON             */
-/************************************************************************/
-
-json_object* OGRGMEMultiLineStringToGeoJSON( OGRMultiLineString* poGeometry )
-{
-    CPLAssert( NULL != poGeometry );
-
-    /* Generate "coordinates" object for 2D or 3D dimension. */
-    json_object* pjoCoordinates = NULL;
-    pjoCoordinates = json_object_new_array();
-
-    for( int i = 0; i < poGeometry->getNumGeometries(); ++i )
-    {
-        OGRGeometry* poGeom = poGeometry->getGeometryRef( i );
-        CPLAssert( NULL != poGeom );
-        OGRLineString* poLine = static_cast<OGRLineString*>(poGeom);
-
-        json_object* pjoLine = NULL;
-        pjoLine = OGRGMELineStringToGeoJSON( poLine );
-
-        json_object_array_add( pjoCoordinates, pjoLine );
-    }
-
-    return pjoCoordinates;
-}
-
-/************************************************************************/
-/*                           OGRGMEPolygonToGeoJSON                     */
-/************************************************************************/
-
-json_object* OGRGMEPolygonToGeoJSON( OGRPolygon* poPolygon )
-{
-    CPLAssert( NULL != poPolygon );
-
-    /* Generate "coordinates" array object. */
-    json_object* pjoCoordinates = NULL;
-    pjoCoordinates = json_object_new_array();
-
-    /* Exterior ring. */
-    OGRLinearRing* poRing = poPolygon->getExteriorRing();
-    if (poRing == NULL) {
-        json_object_put(pjoCoordinates);
-        return NULL;
-    }
-
-    json_object* pjoRing = NULL;
-    // If the linear ring is CW re-wind it CCW
-    if (poRing->isClockwise() ) {
-      poRing->reverseWindingOrder();
-    }
-
-    pjoRing = OGRGMELineCoordsToGeoJSON( poRing );
-    json_object_array_add( pjoCoordinates, pjoRing );
-
-    /* Interior rings. */
-    const int nCount = poPolygon->getNumInteriorRings();
-    for( int i = 0; i < nCount; ++i ) {
-        poRing = poPolygon->getInteriorRing( i );
-        if (poRing == NULL)
-            continue;
-        // If the linear ring is CW re-wind it CCW
-        if (poRing->isClockwise() ) {
-            poRing->reverseWindingOrder();
-        }
-        pjoRing = OGRGMELineCoordsToGeoJSON( poRing );
-        json_object_array_add( pjoCoordinates, pjoRing );
-    }
-
-    return pjoCoordinates;
-}
-
-/************************************************************************/
-/*                           OGRGMEMultiPolygonToGeoJSON                */
-/************************************************************************/
-
-json_object* OGRGMEMultiPolygonToGeoJSON( OGRMultiPolygon* poGeometry )
-{
-    CPLAssert( NULL != poGeometry );
-
-    /* Generate "coordinates" object for 2D or 3D dimension. */
-    json_object* pjoCoordinates = NULL;
-    pjoCoordinates = json_object_new_array();
-
-    for( int i = 0; i < poGeometry->getNumGeometries(); ++i )
-    {
-        OGRGeometry* poGeom = poGeometry->getGeometryRef( i );
-        CPLAssert( NULL != poGeom );
-        OGRPolygon* poPoly = static_cast<OGRPolygon*>(poGeom);
-
-        json_object* pjoPoly = NULL;
-        pjoPoly = OGRGMEPolygonToGeoJSON( poPoly );
-
-        json_object_array_add( pjoCoordinates, pjoPoly );
-    }
-
-    return pjoCoordinates;
-}
-
-/************************************************************************/
-/*                           OGRGMECoordsToGeoJSON                      */
-/************************************************************************/
-
-json_object* OGRGMECoordsToGeoJSON( double const& fX, double const& fY )
-{
-    json_object* pjoCoords = NULL;
-    pjoCoords = json_object_new_array();
-    json_object_array_add( pjoCoords, json_object_new_gme_double( fX ) );
-    json_object_array_add( pjoCoords, json_object_new_gme_double( fY ) );
-
-    return pjoCoords;
-}
-
-json_object* OGRGMECoordsToGeoJSON( double const& fX, double const& fY, double const& fZ )
-{
-    json_object* pjoCoords = NULL;
-    pjoCoords = json_object_new_array();
-    json_object_array_add( pjoCoords, json_object_new_gme_double( fX ) );
-    json_object_array_add( pjoCoords, json_object_new_gme_double( fY ) );
-    json_object_array_add( pjoCoords, json_object_new_gme_double( fZ ) );
-
-    return pjoCoords;
-}
-
-/************************************************************************/
-/*                           OGRGMELineCoordsToGeoJSON                  */
-/************************************************************************/
-
-json_object* OGRGMELineCoordsToGeoJSON( OGRLineString* poLine )
-{
-    json_object* pjoCoords = json_object_new_array();
-
-    const int nCount = poLine->getNumPoints();
-    for( int i = 0; i < nCount; ++i )
-    {
-        json_object* pjoPoint = NULL;
-        if( poLine->getCoordinateDimension() == 2 )
-            pjoPoint = OGRGMECoordsToGeoJSON( poLine->getX(i), poLine->getY(i) );
-        else
-            pjoPoint = OGRGMECoordsToGeoJSON( poLine->getX(i), poLine->getY(i), poLine->getZ(i) );
-        json_object_array_add( pjoCoords, pjoPoint );
-    }
-
-    return pjoCoords;
-}
-
-/************************************************************************/
-/*                          OGRGMEAttributesToGeoJSON                   */
-/************************************************************************/
-
-json_object* OGRGMEAttributesToGeoJSON( OGRFeature* poFeature )
-{
-    if ( NULL == poFeature )
-        return NULL;
-    json_object* pjoProperties = json_object_new_object();
-    CPLAssert( NULL != pjoProperties );
-
-    OGRFeatureDefn* poDefn = poFeature->GetDefnRef();
-    for( int nField = 0; nField < poDefn->GetFieldCount(); ++nField ) {
-        json_object* pjoProperty = NULL;
-        OGRFieldDefn* poFieldDefn = poDefn->GetFieldDefn( nField );
-        if ( NULL == poFieldDefn )
-            continue;
-        OGRFieldType eType = poFieldDefn->GetType();
-
-        if( !poFeature->IsFieldSet(nField) )
-            pjoProperty = NULL;
-
-        // In GME integers are encoded as strings.
-        else if( OFTInteger == eType )
-            pjoProperty = json_object_new_string( poFeature->GetFieldAsString( nField ) );
-
-        else if( OFTReal == eType )
-            pjoProperty = json_object_new_gme_double( poFeature->GetFieldAsDouble(nField) );
-
-        // Supported types are integer, double and string. So treating everything else as strings
-        else
-            pjoProperty = json_object_new_string( poFeature->GetFieldAsString(nField) );
-
-        json_object_object_add( pjoProperties, poFieldDefn->GetNameRef(), pjoProperty );
-    }
-    int nGxId = poFeature->GetFieldIndex("gx_id");
-    if (nGxId < 0) {
-        json_object* pjoProperty = NULL;
-        GIntBig nFID = poFeature->GetFID();
-
-        char acGxId[128];
-        snprintf(acGxId, 128, "GDAL-" CPL_FRMT_GIB, nFID);
-        CPLDebug("GME", "gx_id is not set, so adding \"gx_id\": \"%s\" field.",
-                 acGxId);
-
-        pjoProperty = json_object_new_string( acGxId );
-        json_object_object_add( pjoProperties, "gx_id", pjoProperty);
-    }
-
-    return pjoProperties;
-}
-
-/************************************************************************/
-/*                        json_object_new_gme_double()                  */
-/************************************************************************/
-
-json_object* json_object_new_gme_double(double dfVal)
-
-{
-    json_object* pjoD = json_object_new_double(dfVal);
-    json_object_set_serializer(pjoD, json_gme_double_to_string, NULL, NULL );
-
-    return pjoD;
-}
-
-/************************************************************************/
-/*                        json_gme_double_to_string()                   */
-/************************************************************************/
-
-static int json_gme_double_to_string(json_object *pjo,
-                                     printbuf *pb,
-                                     CPL_UNUSED int level,
-                                     CPL_UNUSED int flags)
-{
-  char buf[128], *p, *q;
-  int size;
-
-  size = CPLsnprintf(buf, 128, "%.8f", json_object_get_double(pjo));
-  p = strchr(buf, ',');
-  if (p) {
-    *p = '.';
-  } else {
-    p = strchr(buf, '.');
-  }
-  if (p) {
-    /* last useful digit, always keep 1 zero */
-    p++;
-    for (q=p ; *q ; q++) {
-      if (*q!='0') p=q;
-    }
-    /* drop trailing zeroes */
-    *(++p) = 0;
-    size = p-buf;
-  }
-  printbuf_memappend(pb, buf, size);
-  return size;
-}
-
-/************************************************************************/
-/*                       OGRGMEParseJSON()                              */
-/************************************************************************/
-
-json_object *OGRGMEParseJSON( const char* pszText )
-{
-    if( NULL != pszText )
-    {
-        json_tokener* jstok = NULL;
-        json_object* jsobj = NULL;
-
-        jstok = json_tokener_new();
-        jsobj = json_tokener_parse_ex(jstok, pszText, -1);
-        if( jstok->err != json_tokener_success)
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "JSON parsing error: %s (at offset %d)",
-                          json_tokener_error_desc(jstok->err), jstok->char_offset);
-
-            json_tokener_free(jstok);
-            return NULL;
-        }
-        json_tokener_free(jstok);
-
-        /* JSON tree is shared for while lifetime of the reader object
-         * and will be released in the destructor.
-         */
-        return jsobj;
-    }
-
-    return NULL;
-}
-
-
-/************************************************************************/
-/*                        OGRGMEGetJSONString()                         */
-/*                                                                      */
-/*      Fetch a string field from a json_object (only an immediate      */
-/*      child).                                                         */
-/************************************************************************/
-
-const char *OGRGMEGetJSONString(json_object *parent,
-                               const char *field,
-                               const char *default_value)
-{
-    json_object *child = json_object_object_get(parent, field);
-    if (child == NULL )
-        return default_value;
-
-    return json_object_get_string(child);
-}
diff --git a/ogr/ogrsf_frmts/gme/ogrgmejson.h b/ogr/ogrsf_frmts/gme/ogrgmejson.h
deleted file mode 100644
index 7799f64..0000000
--- a/ogr/ogrsf_frmts/gme/ogrgmejson.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/******************************************************************************
- * $Id$
- *
- * Project:  Google Maps Engine (GME) API Driver
- * Purpose:  GME Geo JSON helper functions.
- * Author:   Wolf Bergenheim <wolf+grass at bergenheim.net>
- *           (derived from the GeoJSON driver by Mateusz)
- *
- ******************************************************************************
- * Copyright (c) 2013, Frank Warmerdam <warmerdam at pobox.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#ifndef _OGR_GME_JSON_H_INCLUDED
-#define _OGR_GME_JSON_H_INCLUDED
-
-#include "ogr_feature.h"
-#include "ogr_geometry.h"
-#include <json.h>
-
-json_object* OGRGMEFeatureToGeoJSON(OGRFeature* poFeature);
-json_object* OGRGMEGeometryToGeoJSON(OGRGeometry* poGeometry);
-json_object* OGRGMEGeometryCollectionToGeoJSON(OGRGeometryCollection* poGeometryCollection);
-json_object* OGRGMEPointToGeoJSON( OGRPoint* poPoint );
-json_object* OGRGMEMultiPointToGeoJSON( OGRMultiPoint* poGeometry );
-json_object* OGRGMELineStringToGeoJSON( OGRLineString* poLine );
-json_object* OGRGMEMultiLineStringToGeoJSON( OGRMultiLineString* poGeometry );
-json_object* OGRGMEPolygonToGeoJSON( OGRPolygon* poPolygon );
-json_object* OGRGMEMultiPolygonToGeoJSON( OGRMultiPolygon* poGeometry );
-json_object* OGRGMECoordsToGeoJSON( double const& fX, double const& fY );
-json_object* OGRGMECoordsToGeoJSON( double const& fX, double const& fY, double const& fZ );
-json_object* OGRGMELineCoordsToGeoJSON( OGRLineString* poLine );
-json_object* OGRGMEAttributesToGeoJSON( OGRFeature* poFeature );
-
-json_object* json_object_new_gme_double(double dfVal);
-
-json_object* OGRGMEParseJSON( const char* pszText );
-const char*  OGRGMEGetJSONString(json_object *parent,
-                                 const char *field_name,
-                                 const char *default_value = NULL);
-
-#endif /* ndef _OGR_GME_JSON_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/gme/ogrgmelayer.cpp b/ogr/ogrsf_frmts/gme/ogrgmelayer.cpp
deleted file mode 100644
index ecea24f..0000000
--- a/ogr/ogrsf_frmts/gme/ogrgmelayer.cpp
+++ /dev/null
@@ -1,1074 +0,0 @@
-/******************************************************************************
- * $Id$
- *
- * Project:  Google Maps Engine API Driver
- * Purpose:  OGRGMELayer Implementation.
- * Author:   Wolf Beregnheim <wolf+grass at bergenheim.net>
- *           Frank Warmerdam <warmerdam at pobox.com>
- *           (derived from GFT driver by Even)
- *
- ******************************************************************************
- * Copyright (c) 2013, Frank Warmerdam <warmerdam at pobox.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "ogr_gme.h"
-#include "ogrgmejson.h"
-
-#include "cpl_multiproc.h"
-
-CPL_CVSID("$Id: ogrgmetablelayer.cpp 25475 2013-01-09 09:09:59Z warmerdam $");
-
-/************************************************************************/
-/*                            OGRGMELayer()                             */
-/************************************************************************/
-
-OGRGMELayer::OGRGMELayer(OGRGMEDataSource* poDS,
-                         const char* pszTableId)
-
-{
-    CPLDebug("GME", "Opening existing layer %s", pszTableId);
-    this->poDS = poDS;
-    poSRS = new OGRSpatialReference(SRS_WKT_WGS84);
-    poFeatureDefn = NULL;
-    current_feature_page = NULL;
-    bDirty = false;
-    iBatchPatchSize = 50;
-    bCreateTablePending = false;
-    osTableId = pszTableId;
-    bInTransaction = false;
-    m_poFilterGeom = NULL;
-    iGxIdField = -1;
-    SetDescription( pszTableId );
-}
-
-
-OGRGMELayer::OGRGMELayer(OGRGMEDataSource* poDS,
-                         const char* pszTableName,
-                         char ** papszOptions)
-
-{
-    CPLDebug("GME", "Creating new layer %s", pszTableName);
-    this->poDS = poDS;
-    poSRS = new OGRSpatialReference(SRS_WKT_WGS84);
-    poFeatureDefn = NULL;
-    current_feature_page = NULL;
-    bDirty = false;
-    iBatchPatchSize = 50;
-    bCreateTablePending = true;
-    osTableName = pszTableName;
-    osProjectId = CSLFetchNameValue( papszOptions, "projectId" );
-    osDraftACL = CSLFetchNameValueDef( papszOptions, "draftAccessList", "Map Editors" );
-    osPublishedACL = CSLFetchNameValueDef( papszOptions, "publishedAccessList", "Map Viewers" );
-    iGxIdField = -1;
-    SetDescription( pszTableName );
-    // TODO: support tags and description
-}
-
-/************************************************************************/
-/*                            ~OGRGMELayer()                            */
-/************************************************************************/
-
-OGRGMELayer::~OGRGMELayer()
-
-{
-    SyncToDisk();
-    ResetReading();
-    if( poSRS )
-        poSRS->Release();
-    if( poFeatureDefn )
-        poFeatureDefn->Release();
-}
-
-/************************************************************************/
-/*                            ResetReading()                            */
-/************************************************************************/
-
-void OGRGMELayer::ResetReading()
-
-{
-    if (current_feature_page != NULL)
-    {
-        json_object_put(current_feature_page);
-        current_feature_page = NULL;
-        m_nFeaturesRead = 0;
-
-        // TODO - clear current page.
-    }
-}
-
-/************************************************************************/
-/*                           TestCapability()                           */
-/************************************************************************/
-
-int OGRGMELayer::TestCapability( const char * pszCap )
-
-{
-    if(EQUAL(pszCap,OLCStringsAsUTF8))
-        return TRUE;
-    else if(EQUAL(pszCap,OLCIgnoreFields))
-        return TRUE;
-    else if(EQUAL(pszCap,OLCFastSpatialFilter))
-        return TRUE;
-    else if(EQUAL(pszCap,OLCSequentialWrite))
-        return TRUE;
-    else if(EQUAL(pszCap,OLCRandomWrite))
-        return TRUE;
-    else if(EQUAL(pszCap,OLCDeleteFeature))
-        return TRUE;
-    else if(EQUAL(pszCap,OLCTransactions))
-        return TRUE;
-    return FALSE;
-}
-
-/************************************************************************/
-/*                             SyncToDisk()                             */
-/************************************************************************/
-
-OGRErr OGRGMELayer::SyncToDisk()
-
-{
-    CPLDebug("GME", "SyncToDisk()");
-    if (bDirty) {
-        if (omnpoInsertedFeatures.size() > 0) {
-            BatchInsert();
-        }
-        if (omnpoUpdatedFeatures.size() > 0) {
-            BatchPatch();
-        }
-        if (oListOfDeletedFeatures.size() > 0) {
-            BatchDelete();
-        }
-        bDirty = false;
-    }
-    return OGRERR_NONE;
-}
-
-/************************************************************************/
-/*                           FetchDescribe()                            */
-/************************************************************************/
-
-int OGRGMELayer::FetchDescribe()
-{
-    CPLString osRequest = "tables/" + osTableId;
-
-    CPLHTTPResult *psDescribe = poDS->MakeRequest(osRequest);
-    if (psDescribe == NULL)
-        return FALSE;
-
-    CPLDebug("GME", "table doc = %s\n", psDescribe->pabyData);
-
-    json_object *table_doc =
-        OGRGMEParseJSON((const char *) psDescribe->pabyData);
-
-    CPLHTTPDestroyResult(psDescribe);
-
-    osTableName = OGRGMEGetJSONString(table_doc, "name");
-
-    poFeatureDefn = new OGRFeatureDefn(osTableName);
-    poFeatureDefn->Reference();
-
-    json_object *schema_doc = json_object_object_get(table_doc, "schema");
-    json_object *columns_doc = json_object_object_get(schema_doc, "columns");
-    array_list *column_list = json_object_get_array(columns_doc);
-
-    CPLString osLastGeomColumn;
-
-    int field_count = array_list_length(column_list);
-    for( int i = 0; i < field_count; i++ )
-    {
-        OGRwkbGeometryType eFieldGeomType = wkbNone;
-
-        json_object *field_obj = (json_object*)
-            array_list_get_idx(column_list, i);
-
-	const char* name = OGRGMEGetJSONString(field_obj, "name");
-        OGRFieldDefn oFieldDefn(name, OFTString);
-        const char *type = OGRGMEGetJSONString(field_obj, "type");
-
-        if (EQUAL(type, "integer"))
-            oFieldDefn.SetType(OFTInteger);
-        else if (EQUAL(type, "double"))
-            oFieldDefn.SetType(OFTReal);
-        else if (EQUAL(type, "boolean"))
-            oFieldDefn.SetType(OFTInteger);
-        else if (EQUAL(type, "string"))
-            oFieldDefn.SetType(OFTString);
-        else if (EQUAL(type, "string")) {
-            if (EQUAL(name, "gx_id")) {
-                iGxIdField = i;
-            }
-            oFieldDefn.SetType(OFTString);
-        }
-        else if (EQUAL(type, "points"))
-            eFieldGeomType = wkbPoint;
-        else if (EQUAL(type, "linestrings"))
-            eFieldGeomType = wkbLineString;
-        else if (EQUAL(type, "polygons"))
-            eFieldGeomType = wkbPolygon;
-        else if (EQUAL(type, "mixedGeometry"))
-            eFieldGeomType = wkbGeometryCollection;
-
-        if (eFieldGeomType == wkbNone)
-        {
-            poFeatureDefn->AddFieldDefn(&oFieldDefn);
-        }
-        else
-        {
-            CPLAssert(EQUAL(osGeomColumnName,""));
-            osGeomColumnName = oFieldDefn.GetNameRef();
-            poFeatureDefn->SetGeomType(eFieldGeomType);
-            poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
-        }
-    }
-
-    json_object_put(table_doc);
-    return TRUE;
-}
-
-/************************************************************************/
-/*                         GetPageOfFeatures()                          */
-/************************************************************************/
-
-void OGRGMELayer::GetPageOfFeatures()
-{
-    CPLString osNextPageToken;
-
-    if (current_feature_page != NULL)
-    {
-        osNextPageToken = OGRGMEGetJSONString(current_feature_page,
-                                              "nextPageToken", "");
-        json_object_put(current_feature_page);
-        current_feature_page = NULL;
-
-        // End of query results?
-        if (EQUAL(osNextPageToken,""))
-            return;
-    }
-
-    index_in_page = 0;
-    current_features_array = NULL;
-
-/* -------------------------------------------------------------------- */
-/*      Fetch features.                                                 */
-/* -------------------------------------------------------------------- */
-    CPLString osRequest = "tables/" + osTableId + "/features";
-    CPLString osMoreOptions = "&maxResults=1000";
-
-    if (!EQUAL(osNextPageToken,""))
-    {
-        osMoreOptions += "&pageToken=";
-        osMoreOptions += osNextPageToken;
-    }
-    if (!osSelect.empty()) {
-        CPLDebug( "GME", "found select=%s", osSelect.c_str());
-        osMoreOptions += "&select=";
-        osMoreOptions += osSelect;
-    }
-    if (!osWhere.empty()) {
-        CPLDebug( "GME Layer", "found where=%s", osWhere.c_str());
-        osMoreOptions += "&where=";
-        osMoreOptions += osWhere;
-    }
-
-    if (!osIntersects.empty()) {
-        CPLDebug( "GME Layer", "found intersects=%s", osIntersects.c_str());
-        osMoreOptions += "&intersects=";
-        osMoreOptions += osIntersects;
-    }
-
-    CPLHTTPResult *psFeaturesResult =
-        poDS->MakeRequest(osRequest, osMoreOptions);
-
-    if (psFeaturesResult == NULL) {
-        CPLDebug("GME", "Got NULL from MakeRequest. Something went wrong. You figure it out!");
-        current_feature_page = NULL;
-        return;
-    }
-    CPLDebug("GME",
-             "features doc = %s...",
-             psFeaturesResult->pabyData);
-
-/* -------------------------------------------------------------------- */
-/*      Parse result.                                                   */
-/* -------------------------------------------------------------------- */
-
-    current_feature_page =
-        OGRGMEParseJSON((const char *) psFeaturesResult->pabyData);
-    CPLHTTPDestroyResult(psFeaturesResult);
-
-    current_features_array =
-        json_object_object_get(current_feature_page, "features");
-}
-
-/************************************************************************/
-/*                         GetNextRawFeature()                          */
-/************************************************************************/
-
-OGRFeature *OGRGMELayer::GetNextRawFeature()
-
-{
-/* -------------------------------------------------------------------- */
-/*      Fetch a new page of features if needed.                         */
-/* -------------------------------------------------------------------- */
-    if (current_feature_page == NULL
-        || index_in_page >= json_object_array_length(current_features_array))
-    {
-        GetPageOfFeatures();
-    }
-
-    if (current_feature_page == NULL)
-    {
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Identify our json feature.                                      */
-/* -------------------------------------------------------------------- */
-    json_object *feature_obj =
-        json_object_array_get_idx(current_features_array, index_in_page++);
-    if (feature_obj == NULL) 
-        return NULL;
-
-    OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
-
-/* -------------------------------------------------------------------- */
-/*      Handle properties.                                              */
-/* -------------------------------------------------------------------- */
-    json_object *properties_obj =
-        json_object_object_get(feature_obj, "properties");
-    for (int iOGRField = 0;
-         iOGRField < poFeatureDefn->GetFieldCount(); 
-         iOGRField++ ) 
-    {
-        const char *pszValue = 
-            OGRGMEGetJSONString(
-                properties_obj, 
-                poFeatureDefn->GetFieldDefn(iOGRField)->GetNameRef(),
-                NULL);
-        if (pszValue != NULL) {
-            poFeature->SetField(iOGRField, pszValue);
-	}
-    }
-/* -------------------------------------------------------------------- */
-/*      Handle gx_id.                                                   */
-/* -------------------------------------------------------------------- */
-    const char *gx_id = OGRGMEGetJSONString(properties_obj, "gx_id");
-    if (gx_id) {
-        CPLString gmeId(gx_id);
-        omnosIdToGMEKey[(int)(++m_nFeaturesRead)] = gmeId;
-        poFeature->SetFID(m_nFeaturesRead);
-        CPLDebug("GME", "Mapping ids: \"%s\" to %d", gx_id, (int)m_nFeaturesRead);
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Handle geometry.                                                */
-/* -------------------------------------------------------------------- */
-    json_object *geometry_obj =
-        json_object_object_get(feature_obj, "geometry");
-    OGRGeometry *poGeometry = NULL;
-
-    if (geometry_obj != NULL) 
-    {
-        poGeometry = OGRGeoJSONReadGeometry(geometry_obj);
-    }
-
-    if (poGeometry != NULL) 
-    {
-        poGeometry->assignSpatialReference(poSRS);
-        poFeature->SetGeometryDirectly(poGeometry);
-    }
-
-    return poFeature;
-}
-
-/************************************************************************/
-/*                           GetNextFeature()                           */
-/************************************************************************/
-
-OGRFeature *OGRGMELayer::GetNextFeature()
-{
-    OGRFeature *poFeature = NULL;
-    
-    while( TRUE )
-    {
-        poFeature = GetNextRawFeature();
-        if( poFeature == NULL )
-            break;
-
-        // incremeted in GetNextRawFeature()
-        // m_nFeaturesRead++;
-
-        if( (m_poFilterGeom == NULL
-             || poFeature->GetGeometryRef() == NULL 
-             || FilterGeometry( poFeature->GetGeometryRef() ) )
-            && (m_poAttrQuery == NULL
-                || m_poAttrQuery->Evaluate( poFeature )) )
-            break;
-
-        delete poFeature;
-    }
-
-    return poFeature;
-}
-
-/************************************************************************/
-/*                           GetLayerDefn()                             */
-/************************************************************************/
-
-OGRFeatureDefn * OGRGMELayer::GetLayerDefn()
-{
-    if (poFeatureDefn == NULL)
-    {
-        if (osTableId.size() == 0)
-            return NULL;
-        if (!FetchDescribe())
-	    return NULL;
-    }
-
-    return poFeatureDefn;
-}
-
-
-/************************************************************************/
-/*                        SetAttributeFilter()                          */
-/************************************************************************/
-
-OGRErr OGRGMELayer::SetAttributeFilter( const char *pszWhere )
-{
-    OGRErr eErr;
-    eErr = OGRLayer::SetAttributeFilter(pszWhere);
-    if( eErr == OGRERR_NONE ) {
-        if ( pszWhere ) {
-            char * pszEscaped = CPLEscapeString(pszWhere, -1, CPLES_URL);
-            osWhere = CPLString(pszEscaped);
-            CPLFree(pszEscaped);
-        }
-        else {
-            osWhere = "";
-        }
-    }
-    return eErr;
-}
-
-/************************************************************************/
-/*                       SetIgnoredFields()                             */
-/************************************************************************/
-
-OGRErr OGRGMELayer::SetIgnoredFields(const char ** papszFields )
-{
-    osSelect = "geometry";
-    OGRErr eErr;
-    eErr = OGRLayer::SetIgnoredFields(papszFields);
-
-    if( eErr == OGRERR_NONE ) {
-        for ( int iOGRField = 0; iOGRField < poFeatureDefn->GetFieldCount(); iOGRField++ )
-        {
-            if (!poFeatureDefn->GetFieldDefn(iOGRField)->IsIgnored()) {
-                osSelect += ",";
-                osSelect += poFeatureDefn->GetFieldDefn(iOGRField)->GetNameRef();
-            }
-        }
-    }
-    return eErr;
-}
-
-/************************************************************************/
-/*                       SetSpatialFilter()                             */
-/************************************************************************/
-
-void OGRGMELayer::SetSpatialFilter( OGRGeometry *poGeomIn)
-{
-    if (poGeomIn == NULL) {
-        osIntersects.clear();
-        OGRLayer::SetSpatialFilter( poGeomIn );
-        return;
-    }
-    switch( poGeomIn->getGeometryType() )
-    {
-      case wkbPolygon:
-        WindPolygonCCW((OGRPolygon *) poGeomIn);
-      case wkbPoint:
-      case wkbLineString:
-        if( poGeomIn == NULL ) {
-          osIntersects = "";
-        }
-        else {
-            char * pszWkt;
-            poGeomIn->exportToWkt(&pszWkt);
-            char * pszEscaped = CPLEscapeString(pszWkt, -1, CPLES_URL);
-            osIntersects = CPLString(pszEscaped);
-            CPLFree(pszEscaped);
-            CPLFree(pszWkt);
-        }
-        ResetReading();
-        break;
-      default:
-        m_iGeomFieldFilter = 0;
-        if( InstallFilter( poGeomIn ) )
-            ResetReading();
-        break;
-    }
-}
-
-/************************************************************************/
-/*                          WindPolygonCCW()                            */
-/************************************************************************/
-
-OGRPolygon* OGRGMELayer::WindPolygonCCW( OGRPolygon *poPolygon )
-{
-    CPLAssert( NULL != poPolygon );
-
-    OGRLinearRing* poRing = poPolygon->getExteriorRing();
-    if (poRing == NULL) {
-        return poPolygon;
-    }
-
-    // If the linear ring is CW re-wind it CCW
-    if (poRing->isClockwise() ) {
-      poRing->reverseWindingOrder();
-    }
-
-    /* Interior rings. */
-    const int nCount = poPolygon->getNumInteriorRings();
-    for( int i = 0; i < nCount; ++i ) {
-        poRing = poPolygon->getInteriorRing( i );
-        if (poRing == NULL)
-            continue;
-        // If the linear ring is CW re-wind it CCW
-
-        if (poRing->isClockwise() ) {
-            poRing->reverseWindingOrder();
-        }
-    }
-
-    return poPolygon;
-}
-
-
-/************************************************************************/
-/*                            BatchPatch()                              */
-/************************************************************************/
-
-OGRErr OGRGMELayer::BatchPatch()
-{
-    CPLDebug("GME", "BatchPatch() - <%d>", (int)oListOfDeletedFeatures.size() );
-    return BatchRequest("batchPatch", omnpoUpdatedFeatures);
-}
-
-/************************************************************************/
-/*                            BatchInsert()                             */
-/************************************************************************/
-
-OGRErr OGRGMELayer::BatchInsert()
-{
-    CPLDebug("GME", "BatchInsert() - <%d>", (int)oListOfDeletedFeatures.size() );
-    return BatchRequest("batchInsert", omnpoInsertedFeatures);
-}
-
-/************************************************************************/
-/*                            BatchDelete()                             */
-/************************************************************************/
-
-OGRErr OGRGMELayer::BatchDelete()
-{
-    json_object *pjoBatchDelete = json_object_new_object();
-    json_object *pjoGxIds = json_object_new_array();
-    std::vector<GIntBig>::const_iterator fit;
-    CPLDebug("GME", "BatchDelete() - <%d>", (int)oListOfDeletedFeatures.size() );
-    if (oListOfDeletedFeatures.size() == 0) {
-        CPLDebug("GME", "Empty list, not doing BatchDelete");
-        return OGRERR_NONE;
-    }
-    for ( fit = oListOfDeletedFeatures.begin(); fit != oListOfDeletedFeatures.end(); fit++)
-    {
-        GIntBig nFID = *fit;
-        if (nFID > 0) {
-            CPLString osGxId(omnosIdToGMEKey[(int)nFID]);
-            CPLDebug("GME", "Deleting feature " CPL_FRMT_GIB " -> '%s'", nFID, osGxId.c_str());
-            json_object *pjoGxId = json_object_new_string(osGxId.c_str());
-            omnosIdToGMEKey.erase((int)nFID);
-            json_object_array_add( pjoGxIds, pjoGxId );
-        }
-    }
-    oListOfDeletedFeatures.clear();
-    if (json_object_array_length(pjoGxIds) == 0)
-        return OGRERR_FAILURE;
-    json_object_object_add( pjoBatchDelete, "gx_ids", pjoGxIds );
-    const char *body =
-        json_object_to_json_string_ext(pjoBatchDelete,
-                                       JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY);
-
-/* -------------------------------------------------------------------- */
-/*      POST changes                                                    */
-/* -------------------------------------------------------------------- */
-    CPLString osRequest = "tables/" + osTableId + "/features/batchDelete";
-    CPLHTTPResult *poBatchDeleteResult = poDS->PostRequest(osRequest, body);
-    if (poBatchDeleteResult) {
-        CPLDebug("GME", "batchDelete returned %d", poBatchDeleteResult->nStatus);
-        return OGRERR_NONE;
-    }
-    else {
-        CPLDebug("GME", "batchPatch failed, NULL was returned.");
-        CPLError(CE_Failure, CPLE_AppDefined, "Server error for batchDelete");
-        return OGRERR_FAILURE;
-    }
-}
-
-/************************************************************************/
-/*                            BatchRequest()                            */
-/************************************************************************/
-
-OGRErr OGRGMELayer::BatchRequest(const char *pszMethod, std::map<int, OGRFeature *> &omnpoFeatures)
-{
-    json_object *pjoBatchDoc = json_object_new_object();
-    json_object *pjoFeatures = json_object_new_array();
-    std::map<int, OGRFeature *>::const_iterator fit;
-    CPLDebug("GME", "BatchRequest('%s', <%d>)", pszMethod, (int)omnpoFeatures.size() );
-    if (omnpoFeatures.size() == 0) {
-        CPLDebug("GME", "Empty map, not doing '%s'", pszMethod);
-        return OGRERR_NONE;
-    }
-    for ( fit = omnpoFeatures.begin(); fit != omnpoFeatures.end(); fit++)
-    {
-        GIntBig nFID = fit->first;
-        OGRFeature *poFeature = fit->second;
-        CPLDebug("GME", "Processing feature: " CPL_FRMT_GIB, nFID );
-        json_object *pjoFeature = OGRGMEFeatureToGeoJSON(poFeature);
-
-        if (pjoFeature != NULL)
-            json_object_array_add( pjoFeatures, pjoFeature );
-        delete poFeature;
-    }
-    omnpoFeatures.clear();
-    if (json_object_array_length(pjoFeatures) == 0)
-        return OGRERR_FAILURE;
-    json_object_object_add( pjoBatchDoc, "features", pjoFeatures );
-    const char *body =
-        json_object_to_json_string_ext(pjoBatchDoc,
-                                       JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY);
-
-/* -------------------------------------------------------------------- */
-/*      POST changes                                                    */
-/* -------------------------------------------------------------------- */
-    CPLString osRequest = "tables/" + osTableId + "/features/" + pszMethod;
-    CPLHTTPResult *psBatchResult = poDS->PostRequest(osRequest, body);
-    if (psBatchResult) {
-        CPLDebug("GME", "%s returned %d", pszMethod, psBatchResult->nStatus);
-        return OGRERR_NONE;
-    }
-    else {
-        CPLDebug("GME", "%s failed, NULL was returned.", pszMethod );
-        CPLError(CE_Failure, CPLE_AppDefined, "Server error for %s", pszMethod);
-        return OGRERR_FAILURE;
-    }
-}
-
-/************************************************************************/
-/*                         SetBatchPatchSize()                          */
-/************************************************************************/
-
-void OGRGMELayer::SetBatchPatchSize(unsigned int iSize)
-
-{
-    iBatchPatchSize = iSize;
-}
-
-/************************************************************************/
-/*                         GetBatchPatchSize()                          */
-/************************************************************************/
-
-unsigned int OGRGMELayer::GetBatchPatchSize()
-
-{
-    CPLString osBatchPatchSize;
-    osBatchPatchSize = CPLGetConfigOption("GME_BATCH_PATCH_SIZE","0");
-    int iSize = atoi( osBatchPatchSize.c_str() );
-    if (iSize < 1)
-        return iBatchPatchSize;
-    else {
-        iBatchPatchSize = iSize;
-        return (unsigned int) iSize;
-    }
-}
-
-/************************************************************************/
-/*                           ICreateFeature()                            */
-/************************************************************************/
-
-OGRErr OGRGMELayer::ICreateFeature( OGRFeature *poFeature )
-
-{
-    if (!poFeature)
-        return OGRERR_FAILURE;
-    if (!CreateTableIfNotCreated()) {
-        return OGRERR_FAILURE;
-    }
-
-    GIntBig nFID = ++m_nFeaturesRead;
-    poFeature->SetFID(nFID);
-
-    int nGxId = poFeature->GetFieldIndex("gx_id");
-    CPLDebug("GME", "gx_id is field %d", iGxIdField);
-    CPLString osGxId;
-    CPLDebug("GME", "Inserting feature " CPL_FRMT_GIB " as %s", poFeature->GetFID(), osGxId.c_str());
-    if (nGxId >= 0) {
-        iGxIdField = nGxId;
-        if(poFeature->IsFieldSet(iGxIdField)) {
-          osGxId = poFeature->GetFieldAsString(iGxIdField);
-          CPLDebug("GME", "Feature already has " CPL_FRMT_GIB " gx_id='%s'", poFeature->GetFID(),
-                   osGxId.c_str());
-        }
-        else {
-            osGxId = CPLSPrintf("GDAL-" CPL_FRMT_GIB "", nFID);
-            CPLDebug("GME", "Setting field %d as %s", iGxIdField, osGxId.c_str() );
-            poFeature->SetField( iGxIdField, osGxId.c_str() );
-        }
-    }
-
-    if (bInTransaction) {
-        unsigned int iBatchSize = GetBatchPatchSize();
-        if (omnpoInsertedFeatures.size() >= iBatchSize) {
-            CPLDebug("GME", "BatchInsert, reached BatchSize of %d", iBatchSize);
-            OGRErr iBatchInsertResult = BatchInsert();
-            if (iBatchInsertResult != OGRERR_NONE) {
-                return iBatchInsertResult;
-            }
-        }
-        omnosIdToGMEKey[(int)poFeature->GetFID()] = osGxId;
-        omnpoInsertedFeatures[(int)nFID] = poFeature->Clone();
-        CPLDebug("GME", "In Transaction, added feature to memory only");
-        bDirty = true;
-        return OGRERR_NONE;
-    }
-    else {
-        CPLDebug("GME", "Not in Transaction, BatchInsert()");
-        return BatchInsert();
-    }
-}
-
-/************************************************************************/
-/*                           ISetFeature()                               */
-/************************************************************************/
-
-OGRErr OGRGMELayer::ISetFeature( OGRFeature *poFeature )
-
-{
-    if (!poFeature)
-        return OGRERR_FAILURE;
-    GIntBig nFID = poFeature->GetFID();
-    if(bInTransaction) {
-        std::map<int, OGRFeature *>::const_iterator fit;
-        fit = omnpoInsertedFeatures.find((int)nFID);
-        if (fit != omnpoInsertedFeatures.end()) {
-            omnpoInsertedFeatures[(int)nFID] = poFeature->Clone();
-            CPLDebug("GME", "Updated Feature " CPL_FRMT_GIB " in Transaction", nFID);
-        }
-        else {
-            unsigned int iBatchSize = GetBatchPatchSize();
-            if (omnpoUpdatedFeatures.size() >= iBatchSize) {
-                CPLDebug("GME", "BatchPatch, reached BatchSize of %d", iBatchSize);
-                OGRErr iBatchInsertResult = BatchPatch();
-                if (iBatchInsertResult != OGRERR_NONE) {
-                    return iBatchInsertResult;
-                }
-            }
-            CPLDebug("GME", "In Transaction, add update to Transaction");
-            bDirty = true;
-            omnpoUpdatedFeatures[(int)nFID] = poFeature->Clone();
-        }
-        return OGRERR_NONE;
-    }
-    else {
-        omnpoUpdatedFeatures[(int)nFID] = poFeature->Clone();
-        CPLDebug("GME", "Not in Transaction, BatchPatch()");
-        return BatchPatch();
-    }
-}
-
-/************************************************************************/
-/*                           DeleteteFeature()                          */
-/************************************************************************/
-
-OGRErr OGRGMELayer::DeleteFeature( GIntBig nFID )
-{
-    if(bInTransaction) {
-        std::map<int, OGRFeature *>::iterator fit;
-        fit = omnpoInsertedFeatures.find((int)nFID);
-        if (fit != omnpoInsertedFeatures.end()) {
-            omnpoInsertedFeatures.erase(fit);
-            CPLDebug("GME", "Found " CPL_FRMT_GIB " in omnpoInsertedFeatures", nFID);
-        }
-        else {
-            unsigned int iBatchSize = GetBatchPatchSize();
-            if (oListOfDeletedFeatures.size() >= iBatchSize) {
-                CPLDebug("GME", "BatchDelete, reached BatchSize of %d", iBatchSize);
-                OGRErr iBatchResult = BatchDelete();
-                if (iBatchResult != OGRERR_NONE) {
-                    return iBatchResult;
-                }
-            }
-            CPLDebug("GME", "In Transaction, adding feature to List");
-            bDirty = true;
-            oListOfDeletedFeatures.push_back(nFID); 
-        }
-        return OGRERR_NONE;
-    }
-    else {
-        CPLDebug("GME", "Not in Transaction, BatchDelete()");
-        return BatchDelete();
-    }
-}
-
-/************************************************************************/
-/*                            CreateField()                             */
-/************************************************************************/
-
-OGRErr OGRGMELayer::CreateField( OGRFieldDefn *poField,
-                                 CPL_UNUSED int bApproxOK )
-{
-    CPLDebug("GME", "create field %s of type %s, pending = %d",
-             poField->GetNameRef(), OGRFieldDefn::GetFieldTypeName(poField->GetType()),
-             bCreateTablePending);
-    if (!bCreateTablePending) {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Cannot add field to table after schema is defined.");
-        return OGRERR_FAILURE;
-    }
-
-    if (poFeatureDefn == NULL) {
-        poFeatureDefn = new OGRFeatureDefn( osTableName );
-
-        poFeatureDefn->Reference();
-        poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
-        poFeatureDefn->GetGeomFieldDefn(0)->SetName("geometry");
-    }
-    poFeatureDefn->AddFieldDefn(poField);
-    return OGRERR_NONE;
-}
-
-/************************************************************************/
-/*                      CreateTableIfNotCreated()                       */
-/************************************************************************/
-
-bool OGRGMELayer::CreateTableIfNotCreated()
-{
-    if (!bCreateTablePending || (osTableId.size() != 0)) {
-        CPLDebug("GME", "Not creating table since already created");
-        CPLDebug("GME", "bCreateTablePending = %d osTableId ='%s'",
-                 bCreateTablePending, osTableId.c_str());
-        return true;
-    }
-    CPLDebug("GME", "Creating table...");
-
-    json_object *pjoCreateDoc = json_object_new_object();
-    json_object *pjoProjectId = json_object_new_string( osProjectId.c_str() );
-    json_object_object_add( pjoCreateDoc, "projectId", pjoProjectId );
-    json_object *pjoName = json_object_new_string( osTableName.c_str() );
-    json_object_object_add( pjoCreateDoc, "name",  pjoName );
-    json_object *pjoDraftACL = json_object_new_string( osDraftACL.c_str() );
-    json_object_object_add( pjoCreateDoc, "draftAccessList", pjoDraftACL );
-    json_object *pjoPublishedACL = json_object_new_string( osPublishedACL.c_str() );
-    json_object_object_add( pjoCreateDoc, "publishedAccessList", pjoPublishedACL );
-    json_object *pjoSchema = json_object_new_object();
-
-    json_object *pjoColumns = json_object_new_array();
-
-    poFeatureDefn->SetGeomType( eGTypeForCreation );
-
-    json_object *pjoGeometryColumn = json_object_new_object();
-    json_object *pjoGeometryName = json_object_new_string( "geometry" );
-    json_object *pjoGeometryType;
-    switch(eGTypeForCreation) {
-    case wkbPoint:
-    case wkbPoint25D:
-    case wkbMultiPoint:
-    case wkbMultiPoint25D:
-        pjoGeometryType = json_object_new_string( "points" );
-        break;
-    case wkbLineString:
-    case wkbLineString25D:
-    case wkbMultiLineString:
-    case wkbLinearRing:
-    case wkbMultiLineString25D:
-        pjoGeometryType = json_object_new_string( "lineStrings" );
-        break;
-    case wkbPolygon:
-    case wkbPolygon25D:
-    case wkbMultiPolygon:
-    case wkbGeometryCollection:
-    case wkbMultiPolygon25D:
-        pjoGeometryType = json_object_new_string( "polygons" );
-        break;
-    case wkbGeometryCollection25D:
-        pjoGeometryType = json_object_new_string( "mixedGeometry" );
-        break;
-    default:
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Unsupported Geometry type. Defaulting to Points");
-        pjoGeometryType = json_object_new_string( "points" );
-        poFeatureDefn->SetGeomType( wkbPoint );
-    }
-    json_object_object_add( pjoGeometryColumn, "name", pjoGeometryName );
-    json_object_object_add( pjoGeometryColumn, "type", pjoGeometryType );
-    json_object_array_add( pjoColumns, pjoGeometryColumn );
-
-    for (int iOGRField = 0; iOGRField < poFeatureDefn->GetFieldCount(); iOGRField++ )
-    {
-        if ((iOGRField == iGxIdField) && (iGxIdField >= 0))
-            continue; // don't create the gx_id field.
-        const char *pszFieldName = poFeatureDefn->GetFieldDefn(iOGRField)->GetNameRef();
-        if (EQUAL(pszFieldName, "gx_id")) {
-            iGxIdField = iOGRField;
-            continue;
-        }
-        json_object *pjoColumn = json_object_new_object();
-        json_object *pjoFieldName =
-            json_object_new_string( pszFieldName );
-        json_object *pjoFieldType;
-
-        switch(poFeatureDefn->GetFieldDefn(iOGRField)->GetType()) {
-        case OFTInteger:
-            pjoFieldType = json_object_new_string( "integer" );
-            break;
-        case OFTReal:
-            pjoFieldType = json_object_new_string( "double" );
-            break;
-        default:
-            pjoFieldType = json_object_new_string( "string" );
-        }
-        json_object_object_add( pjoColumn, "name", pjoFieldName );
-        json_object_object_add( pjoColumn, "type", pjoFieldType );
-        json_object_array_add( pjoColumns, pjoColumn );
-    }
-
-    json_object_object_add( pjoSchema, "columns", pjoColumns );
-    json_object_object_add( pjoCreateDoc, "schema", pjoSchema );
-    const char *body =
-        json_object_to_json_string_ext(pjoCreateDoc,
-                                       JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY);
-
-    CPLDebug("GME", "Create Table Doc:\n%s", body);
-
-/* -------------------------------------------------------------------- */
-/*      POST changes                                                    */
-/* -------------------------------------------------------------------- */
-    CPLString osRequest = "tables";
-    CPLHTTPResult *poCreateResult = poDS->PostRequest(osRequest, body);
-    if( poCreateResult == NULL || poCreateResult->pabyData == NULL )
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Table creation failed.");
-        if( poCreateResult )
-            CPLHTTPDestroyResult(poCreateResult);
-        return false;
-    }
-    CPLDebug("GME", "CreateTable returned %d\n%s", poCreateResult->nStatus,
-             poCreateResult->pabyData);
-
-    json_object *pjoResponseDoc = OGRGMEParseJSON((const char *) poCreateResult->pabyData);
-
-    osTableId = OGRGMEGetJSONString(pjoResponseDoc, "id", "");
-    CPLHTTPDestroyResult(poCreateResult);
-    if (osTableId.size() == 0) {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Table creation failed, or could not find table id.");
-        return false;
-    }
-
-    /*
-    OGRFieldDefn *poGxIdField = new OGRFieldDefn("gx_id", OFTString);
-
-    poFeatureDefn->AddFieldDefn(poGxIdField);
-    iGxIdField = poFeatureDefn->GetFieldCount() - 1;
-    CPLDebug("GME", "create field %s(%d) of type %s",
-             "gx_id", iGxIdField, OGRFieldDefn::GetFieldTypeName(OFTString));
-    */
-    bCreateTablePending = false;
-    CPLDebug("GME", "sleeping 3s to give GME time to create the table...");
-    CPLSleep( 3.0 );
-    return true;
-}
-
-/************************************************************************/
-/*                          SetGeometryType()                           */
-/************************************************************************/
-
-void OGRGMELayer::SetGeometryType(OGRwkbGeometryType eGType)
-{
-    eGTypeForCreation = eGType;
-}
-
-/************************************************************************/
-/*                         StartTransaction()                           */
-/************************************************************************/
-
-OGRErr OGRGMELayer::StartTransaction()
-{
-    if (bInTransaction)
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "Already in transaction");
-        return OGRERR_FAILURE;
-    }
-
-    if (!poDS->IsReadWrite())
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Operation not available in read-only mode");
-        return OGRERR_FAILURE;
-    }
-
-    bInTransaction = TRUE;
-
-    return OGRERR_NONE;
-}
-
-/************************************************************************/
-/*                         CommitTransaction()                          */
-/************************************************************************/
-
-OGRErr OGRGMELayer::CommitTransaction()
-{
-    if (!bInTransaction)
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "Cannot commit, not in transaction");
-        return OGRERR_FAILURE;
-    }
-    bInTransaction = FALSE;
-    return SyncToDisk();
-}
-
-/************************************************************************/
-/*                        RollbackTransaction()                         */
-/************************************************************************/
-
-OGRErr OGRGMELayer::RollbackTransaction()
-{
-    if (!bInTransaction)
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "Cannot rollback, not in transaction.");
-        return OGRERR_FAILURE;
-    }
-    bInTransaction = FALSE;
-    omnpoUpdatedFeatures.clear();
-    omnpoInsertedFeatures.clear();
-    oListOfDeletedFeatures.clear();
-    return OGRERR_NONE;
-}
diff --git a/ogr/ogrsf_frmts/gml/drv_gml.html b/ogr/ogrsf_frmts/gml/drv_gml.html
index 514d0f7..de85634 100644
--- a/ogr/ogrsf_frmts/gml/drv_gml.html
+++ b/ogr/ogrsf_frmts/gml/drv_gml.html
@@ -32,7 +32,7 @@ GML writing is always supported, even without Xerces or Expat.<p>
 Note: starting with OGR 1.9.0, if both Xerces and Expat are available at build time,
 the GML driver will preferentially select at runtime the Expat parser for cases where it is possible
 (GML file in a compatible encoding), and default back to Xerces parser in other cases.
-However, the choice of the parser can be overriden by specifying the <b>GML_PARSER</b>
+However, the choice of the parser can be overridden by specifying the <b>GML_PARSER</b>
 configuration option to <b>EXPAT</b> or <b>XERCES</b>.<p>
 
 <h2>CRS support</h2>
@@ -101,7 +101,7 @@ environment variables.<p>
 OGR 1.8.0 adds support for detecting feature attributes in nested GML elements
 (non-flat attribute hierarchy) that can be found in some GML profiles
 such as UK Ordnance Survey MasterMap. OGR 1.8.0 also brings support for reading
-IntegerList, RealList and StringList field types when a GML element has several occurences.<p>
+IntegerList, RealList and StringList field types when a GML element has several occurrences.<p>
 
 Since OGR 1.8.0, a specialized GML driver - the <a href="drv_nas.html">NAS</a> driver - is available to read
 German AAA GML Exchange Format (NAS/ALKIS).<p>
@@ -129,15 +129,13 @@ several geometry fields, or the .gfs file declares several geometry fields, mult
 fields will be reported by the GML driver according to
 <a href="http://trac.osgeo.org/gdal/wiki/rfc41_multiple_geometry_fields">RFC 41</a>.<p>
 
-Starting with OGR 1.10, in case of multiple geometry occurences, if a geometry is in a <geometry> element,
+Starting with OGR 1.10, in case of multiple geometry occurrences, if a geometry is in a <geometry> element,
 this will be the one selected. This will make default behaviour consistent with Inspire objects.<p>
 
-
 Starting with OGR 1.8.0, the user can change the .gfs file to select the appropriate
 geometry by specifying its path with the <GeometryElementPath> element. See the
 description of the .gfs syntax below.<p>
 
-
 <!-- Voluntary commented : a bit experimental for now and perhaps a better solution
      will emerge later -->
 <!--
@@ -181,26 +179,26 @@ doesn't exist already.  This behaviour can be changed using the configuration
 option <b>GML_SAVE_RESOLVED_TO</b>.  Set it to <b>SAME</b> to overwrite the
 original file.  Set it to a <b>filename ending with .gml</b> to save it to that
 location.  Any other values are ignored.  If the resolver cannot write to the
-file for any reason, it will try to save it to a temperary file generated using
+file for any reason, it will try to save it to a temporary file generated using
 CPLGenerateTempFilename("ResolvedGML"); if it cannot, resolution fails.<p>
 
-Note that the resolution algorithm is not optimised for large files.  For files
+Note that the resolution algorithm is not optimized for large files.  For files
 with more than a couple of thousand xlink:href tags, the process can go beyond
 a few minutes.  A rough progress is displayed through CPLDebug() for every
 256 links.  It can be seen by setting the environment variable CPL_DEBUG.
 The resolution time can be reduced if you know any elements that
-won't be needed.  Mention a comma seperated list of names of such elements with
+will not be needed.  Mention a comma separated list of names of such elements with
 the configuration option <b>GML_SKIP_RESOLVE_ELEMS</b>.  Set it to <b>ALL</b>
 to skip resolving altogether (default action).  Set it to <b>NONE</b> to
 resolve all the xlinks.<p>
 
 Starting since OGR 1.9.0 an alternative resolution method is available.
 This alternative method will be activated using the configuration option
-<b>GML_SKIP_RESOLVE_ELEMS HUGE</b>. In this case any gml:xlink will be 
+<b>GML_SKIP_RESOLVE_ELEMS HUGE</b>. In this case any gml:xlink will be
 resolved using a temporary SQLite DB so to identify any corresponding
 gml:id relation. At the end of this SQL-based process, a resolved file
-will be generated exactly as in the <b>NONE</b> case but without their limits. 
-The main advantages in using an external (temporary) DBMS so to resolve 
+will be generated exactly as in the <b>NONE</b> case but without their limits.
+The main advantages in using an external (temporary) DBMS so to resolve
 gml:xlink and gml:id relations are the followings:<ul>
 	<li>no memory size constraints. The <b>NONE</b> method stores the whole
 	   GML node-tree in-memory; and this practically means that no GML
@@ -208,18 +206,18 @@ gml:xlink and gml:id relations are the followings:<ul>
 	   platform, due to memory allocation limits. Using a file-system
 	   based DBMS avoids at all this issue.</li>
 	<li>by far better efficiency, most notably when huge GML files containing
-	   many thousands (or even millions) of xlink:href / gml:id relational 
+	   many thousands (or even millions) of xlink:href / gml:id relational
 	   pairs.</li>
-	<li>using the <b>GML_SKIP_RESOLVE_ELEMS HUGE</b> method realistically allows 
-	   to succesfully resolve some really huge GML file (3GB+) containing many 
+	<li>using the <b>GML_SKIP_RESOLVE_ELEMS HUGE</b> method realistically allows
+	   to successfully resolve some really huge GML file (3GB+) containing many
 	   millions xlink:href / gml:id in a reasonable time (about an hour or so on).</li>
-	<li>The <b>GML_SKIP_RESOLVE_ELEMS HUGE</b> method supports the followind further
+	<li>The <b>GML_SKIP_RESOLVE_ELEMS HUGE</b> method supports the following further
 	   configuration option:<ul>
 		<li>you can use <b>GML_GFS_TEMPLATE</b> <b><i>path_to_template.gfs</i></b>
 		   in order to unconditionally use a predefined GFS file. This option is really useful
-		   when you are planning to import many distinct GML files in subsequent steps [<b>-append</b>] 
+		   when you are planning to import many distinct GML files in subsequent steps [<b>-append</b>]
 		   and you absolutely want to preserve a fully consistent data layout for the whole GML set.
-		   Please, pay attention not to use the <b>-lco LAUNDER=yes</b> setting when using <b>GML_GFS_TEMPLATE</b>; 
+		   Please, pay attention not to use the <b>-lco LAUNDER=yes</b> setting when using <b>GML_GFS_TEMPLATE</b>;
 		   this should break the correct recognition of attribute names between subsequent GML import runs.
 </li>
 	</ul></li>
@@ -236,7 +234,7 @@ rules for TopoSurface when a polygon contains any internal hole:
 		<li><i>positive</i> Faces [i.e. declaring <b>orientation="+"</b>] are assumed to
 		    represent the Exterior Ring of some Polygon.</li>
 		<li><i>negative</i> Faces [i.e. declaring <b>orientation="-"</b>] are assumed to
-		    represent an Interior Ring (aka <i>hole</i>) belonging to the latest declared 
+		    represent an Interior Ring (aka <i>hole</i>) belonging to the latest declared
 			Exterior Ring.</li>
 		<li>ordering any Edge used to represent each Ring is important: each Edge is expected
 			to be exactly adjacent to the next one.</li>
@@ -244,12 +242,12 @@ rules for TopoSurface when a polygon contains any internal hole:
 	<li>the new interpretation rule now assumes that:<ul>
 		<li>each TopoSurface may be represented as a collection of many Faces</li>
 		<li>the declared <b>orientation</b> for any Face has nothing to deal with Exterior/Interior Rings</li>
-		<li>each Face is now intended to represent a complete Polygon, eventually including any possible Interior 
+		<li>each Face is now intended to represent a complete Polygon, eventually including any possible Interior
 			Ring (<i>holes</i>)</li>
-		<li>the relative ordering of any Edge composing the same Face is completely not relevant</li> 
+		<li>the relative ordering of any Edge composing the same Face is completely not relevant</li>
 	</li></ul>
 </ul>
-		
+
 The newest interpretation seems to fully match GML 3 standard recommendations; so this latest
 is now assumed to be the default interpretation supported by OGR.</p>
 
@@ -276,11 +274,11 @@ Expat library supports reading the following built-in encodings :
 </ul>
 
 When used with Expat library, OGR 1.8.0 adds supports for Windows-1252 encoding (
-for previous versions, altering the encoding mentionned in the XML header to
+for previous versions, altering the encoding mentioned in the XML header to
 ISO-8859-1 might work in some cases).<p>
 
 The content returned by OGR will be encoded in UTF-8, after the conversion from the
-encoding mentionned in the file header is.<p>
+encoding mentioned in the file header is.<p>
 
 If the GML file is not encoded in one of the previous encodings and the only parser available
 is Expat, it will not be parsed by the GML driver. You may convert it into one of the supported
@@ -304,7 +302,7 @@ write the content of the gml:id attribute of the created feature.<p>
 Starting with OGR 1.9.0, the driver autodetects the presence of a fid (GML2)
 (resp. gml:id (GML3)) attribute at the beginning of the file, and, if found,
 exposes it by default as a <i>fid</i> (resp. <i>gml_id</i>) field. The autodetection
-can be overriden by specifying the <b>GML_EXPOSE_FID</b> or <b>GML_EXPOSE_GML_ID</b> configuration
+can be overridden by specifying the <b>GML_EXPOSE_FID</b> or <b>GML_EXPOSE_GML_ID</b> configuration
 option to <b>YES</b> or <b>NO</b>.<p>
 
 Starting with OGR 1.9.0, when creating a GML2 document, if a field is called
@@ -392,7 +390,7 @@ Filename of the registry with application schemas. Defaults to {GDAL_DATA}/gml_r
 
 On export all layers are written to a single GML file all in a single
 feature collection.  Each layer's name is used as the element name for
-objects from that layer.  Geometries are always written as the 
+objects from that layer.  Geometries are always written as the
 ogr:geometryProperty element on the feature.<p>
 
 The GML writer supports the following dataset creation options:
@@ -400,7 +398,7 @@ The GML writer supports the following dataset creation options:
 <ul>
 <li> <B>XSISCHEMAURI</B>: If provided, this URI will be inserted as the
 schema location.  Note that the schema file isn't actually accessed by OGR, so
-it is up to the user to ensure it will match the schema of the OGR produced 
+it is up to the user to ensure it will match the schema of the OGR produced
 GML data file.<p>
 
 <li> <B>XSISCHEMA</B>: This can be EXTERNAL, INTERNAL or OFF and defaults to
@@ -579,7 +577,7 @@ OGRFeature(LAYER):0
 
 <h2>Advanced .gfs syntax (OGR >= 1.11)</h2>
 
-<h3>Specifying ElementPath to find objets embedded into top level objects</h3>
+<h3>Specifying ElementPath to find objects embedded into top level objects</h3>
 
 Let's consider the following test.gml file :
 <pre>
@@ -894,7 +892,7 @@ Such datasets typically look like:
     xmlns:gml="http://www.opengis.net/gml/3.2"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     numberMatched="unknown" numberReturned="2" timeStamp="2015-01-01T00:00:00.000Z"
-    xsi:schemaLocation="http://www.opengis.net/gml/3.2 http://schemas.opengis.net/gml/3.2.1/gml.xsd 
+    xsi:schemaLocation="http://www.opengis.net/gml/3.2 http://schemas.opengis.net/gml/3.2.1/gml.xsd
                         http://www.opengis.net/wfs/2.0 http://schemas.opengis.net/wfs/2.0/wfs.xsd">
   <wfs:member>
     <wfs:Tuple>
diff --git a/ogr/ogrsf_frmts/gml/gfstemplate.cpp b/ogr/ogrsf_frmts/gml/gfstemplate.cpp
index 3a12ee4..ab2942e 100644
--- a/ogr/ogrsf_frmts/gml/gfstemplate.cpp
+++ b/ogr/ogrsf_frmts/gml/gfstemplate.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gfstemplate.cpp 28481 2015-02-13 17:11:15Z rouault $
+ * $Id: gfstemplate.cpp 32099 2015-12-09 00:24:06Z goatbar $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GML GFS template management
@@ -36,7 +36,7 @@
 #include "gmlreaderp.h"
 #include "ogr_gml.h"
 
-CPL_CVSID("$Id: gfstemplate.cpp 28481 2015-02-13 17:11:15Z rouault $");
+CPL_CVSID("$Id: gfstemplate.cpp 32099 2015-12-09 00:24:06Z goatbar $");
 
 /************************************************************************/
 /*                        GFSTemplateItem                               */
@@ -76,7 +76,7 @@ public:
         if (poClass != NULL)
             poClass->SetFeatureCount( 0 );
     }
-    int m_bValid = FALSE;
+    bool bValid = false;
     GFSTemplateItem *pItem = pCC->GetFirst();
     while ( pItem != NULL )
     {
@@ -86,12 +86,12 @@ public:
         {
             poClass->SetFeatureCount( pItem->GetCount() );
             if ( pItem->GetGeomCount() != 0 && poClass->GetGeometryPropertyCount() == 0 )
-                poClass->AddGeometryProperty( new GMLGeometryPropertyDefn( "", "", wkbUnknown, -1, TRUE ) );
-            m_bValid = TRUE;
+                poClass->AddGeometryProperty( new GMLGeometryPropertyDefn( "", "", wkbUnknown, -1, true ) );
+            bValid = true;
         }
         pItem = pItem->GetNext();
     }
-    if ( m_bValid == TRUE && pCC->HaveSequentialLayers() == TRUE )
+    if ( bValid && pCC->HaveSequentialLayers() )
         *pbSequentialLayers = TRUE;
 }
 
@@ -99,7 +99,7 @@ public:
 /*       GMLReader::ReArrangeTemplateClasses()     */
 /***************************************************/
 
-int GMLReader::ReArrangeTemplateClasses ( GFSTemplateList *pCC )
+bool GMLReader::ReArrangeTemplateClasses ( GFSTemplateList *pCC )
 {
 /* rearranging the final FeatureClass list [SEQUENTIAL] */
     int m_nSavedClassCount = GetClassCount();
@@ -110,12 +110,12 @@ int GMLReader::ReArrangeTemplateClasses ( GFSTemplateList *pCC )
     int clIdx;
     for (clIdx = 0; clIdx < GetClassCount(); clIdx++)
     {
-    /* tranferring any previous FeatureClass */
+    /* Transferring any previous FeatureClass */
         m_papoSavedClass[clIdx] = m_papoClass[clIdx];
     }
 
 /* cleaning the previous FeatureClass list */
-    SetClassListLocked( FALSE );
+    SetClassListLocked( false );
     CPLFree( m_papoClass );
     m_nClassCount = 0;
     m_papoClass = NULL;
@@ -144,37 +144,36 @@ int GMLReader::ReArrangeTemplateClasses ( GFSTemplateList *pCC )
         }
         pItem = pItem->GetNext();
     }
-    SetClassListLocked( TRUE );
+    SetClassListLocked( true );
 
 /* destroying the saved List and any unused FeatureClass */
     for( int iClass = 0; iClass < m_nSavedClassCount; iClass++ )
     {
-        int bUnused = TRUE;
+        bool bUnused = true;
         GMLFeatureClass* poClass = m_papoSavedClass[iClass];
         for( int iClass2 = 0; iClass2 < m_nClassCount; iClass2++ )
         {
             if (m_papoClass[iClass2] == poClass)
             {
-                bUnused = FALSE;
+                bUnused = false;
                 break;
             }
         }
-        if ( bUnused == TRUE )
+        if ( bUnused )
             delete poClass;
     }
     CPLFree( m_papoSavedClass );
-    return 1;
+    return true;
 }
 
 /***************************************************/
 /*       GMLReader::PrescanForTemplate()           */
 /***************************************************/
 
-int GMLReader::PrescanForTemplate ()
+bool GMLReader::PrescanForTemplate ()
 {
     int iCount = 0;
     GMLFeature      *poFeature;
-    //int bSequentialLayers = TRUE;
     GFSTemplateList *pCC = new GFSTemplateList();
 
     /* processing GML features */
@@ -182,7 +181,7 @@ int GMLReader::PrescanForTemplate ()
     {
         GMLFeatureClass *poClass = poFeature->GetClass();
         const CPLXMLNode* const * papsGeomList = poFeature->GetGeometryList();
-        int b_has_geom = FALSE;
+        bool b_has_geom = false;
 
         if( papsGeomList != NULL )
         {
@@ -190,7 +189,7 @@ int GMLReader::PrescanForTemplate ()
             const CPLXMLNode *psNode = papsGeomList[i];
             while( psNode != NULL )
             {
-                b_has_geom = TRUE;
+                b_has_geom = true;
                 i++;
                 psNode = papsGeomList[i];
             }
@@ -200,8 +199,8 @@ int GMLReader::PrescanForTemplate ()
         delete poFeature;
     }
 
-    gmlUpdateFeatureClasses( pCC, this, &m_bSequentialLayers );
-    if ( m_bSequentialLayers == TRUE )
+    gmlUpdateFeatureClasses( pCC, this, &m_nHasSequentialLayers );
+    if ( m_nHasSequentialLayers == TRUE )
         ReArrangeTemplateClasses( pCC );
     iCount = pCC->GetClassCount();
     delete pCC;
@@ -216,7 +215,7 @@ int GMLReader::PrescanForTemplate ()
 
 GFSTemplateList::GFSTemplateList( void )
 {
-    m_bSequentialLayers = TRUE;
+    m_bSequentialLayers = true;
     pFirst = NULL;
     pLast = NULL;
 }
@@ -283,7 +282,7 @@ void GFSTemplateList::Update( const char *pszName, int bHasGeom )
         if( EQUAL(pszName, pItem->GetName() ))
         {
         /* Class Item previously declared: NOT SEQUENTIAL */
-            m_bSequentialLayers = FALSE;
+            m_bSequentialLayers = false;
             pItem->Update( bHasGeom );
             return;
         }
diff --git a/ogr/ogrsf_frmts/gml/gmlfeature.cpp b/ogr/ogrsf_frmts/gml/gmlfeature.cpp
index e6356db..cac8f9b 100644
--- a/ogr/ogrsf_frmts/gml/gmlfeature.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlfeature.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: gmlfeature.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: gmlfeature.cpp 33702 2016-03-11 06:20:16Z goatbar $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLFeature.
@@ -15,16 +15,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
@@ -41,7 +41,7 @@ GMLFeature::GMLFeature( GMLFeatureClass *poClass )
 {
     m_poClass = poClass;
     m_pszFID = NULL;
-    
+
     m_nPropertyCount = 0;
     m_pasProperties = NULL;
 
@@ -49,7 +49,7 @@ GMLFeature::GMLFeature( GMLFeatureClass *poClass )
     m_papsGeometry = m_apsGeometry;
     m_apsGeometry[0] = NULL;
     m_apsGeometry[1] = NULL;
-    
+
     m_papszOBProperties = NULL;
 }
 
@@ -62,8 +62,7 @@ GMLFeature::~GMLFeature()
 {
     CPLFree( m_pszFID );
 
-    int i;
-    for( i = 0; i < m_nPropertyCount; i++ )
+    for( int i = 0; i < m_nPropertyCount; i++ )
     {
         int nSubProperties = m_pasProperties[i].nSubProperties;
         if (nSubProperties == 1)
@@ -82,7 +81,7 @@ GMLFeature::~GMLFeature()
     }
     else if (m_nGeometryCount > 1)
     {
-        for(i=0;i<m_nGeometryCount;i++)
+        for( int i=0; i < m_nGeometryCount; i++ )
             CPLDestroyXMLNode(m_papsGeometry[i]);
         CPLFree(m_papsGeometry);
     }
@@ -119,15 +118,14 @@ void GMLFeature::SetPropertyDirectly( int iIndex, char *pszValue )
         m_pasProperties = (GMLProperty*)
             CPLRealloc( m_pasProperties,
                         sizeof(GMLProperty) * nClassPropertyCount );
-        int i;
-        for( i = 0; i < m_nPropertyCount; i ++ )
+        for( int i = 0; i < m_nPropertyCount; i++ )
         {
             /* Make sure papszSubProperties point to the right address in case */
             /* m_pasProperties has been relocated */
             if (m_pasProperties[i].nSubProperties <= 1)
                 m_pasProperties[i].papszSubProperties = m_pasProperties[i].aszSubProperties;
         }
-        for( i = m_nPropertyCount; i < nClassPropertyCount; i++ )
+        for( int i = m_nPropertyCount; i < nClassPropertyCount; i++ )
         {
             m_pasProperties[i].nSubProperties = 0;
             m_pasProperties[i].papszSubProperties = m_pasProperties[i].aszSubProperties;
@@ -172,8 +170,7 @@ void GMLFeature::Dump( CPL_UNUSED FILE * fp )
     if( m_pszFID != NULL )
         printf( "  FID = %s\n", m_pszFID );
 
-    int i;
-    for( i = 0; i < m_nPropertyCount; i++ )
+    for( int i = 0; i < m_nPropertyCount; i++ )
     {
         const GMLProperty * psGMLProperty = GetProperty( i );
         printf( "  %s = ", m_poClass->GetProperty( i )->GetName());
@@ -185,7 +182,7 @@ void GMLFeature::Dump( CPL_UNUSED FILE * fp )
         printf("\n");
     }
 
-    for(i=0;i<m_nGeometryCount;i++)
+    for( int i=0; i < m_nGeometryCount; i++ )
     {
         char* pszXML = CPLSerializeXMLTree(m_papsGeometry[i]);
         printf( "  %s\n", pszXML );
@@ -287,7 +284,7 @@ void GMLFeature::AddGeometry( CPLXMLNode* psGeom )
 void GMLFeature::AddOBProperty( const char *pszName, const char *pszValue )
 
 {
-    m_papszOBProperties = 
+    m_papszOBProperties =
         CSLAddNameValue( m_papszOBProperties, pszName, pszValue );
 }
 
diff --git a/ogr/ogrsf_frmts/gml/gmlfeatureclass.cpp b/ogr/ogrsf_frmts/gml/gmlfeatureclass.cpp
index 9101792..b36313f 100644
--- a/ogr/ogrsf_frmts/gml/gmlfeatureclass.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlfeatureclass.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: gmlfeatureclass.cpp 28909 2015-04-15 12:52:53Z rouault $
+ * $Id: gmlfeatureclass.cpp 33702 2016-03-11 06:20:16Z goatbar $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLFeatureClass.
@@ -15,16 +15,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
@@ -39,25 +39,28 @@
 /*                          GMLFeatureClass()                           */
 /************************************************************************/
 
-GMLFeatureClass::GMLFeatureClass( const char *pszName )
-
+GMLFeatureClass::GMLFeatureClass( const char *pszName ) :
+    m_pszName(NULL),
+    m_pszElementName(NULL),
+    n_nNameLen(0),
+    n_nElementNameLen(0),
+    m_nPropertyCount(0),
+    m_papoProperty(NULL),
+    m_nGeometryPropertyCount(0),
+    m_papoGeometryProperty(NULL),
+    m_bSchemaLocked(false),
+    m_nFeatureCount(-1), // unknown
+    m_pszExtraInfo(NULL),
+    m_bHaveExtents(false),
+    m_dfXMin(0.0),
+    m_dfXMax(0.0),
+    m_dfYMin(0.0),
+    m_dfYMax(0.0),
+    m_pszSRSName(NULL),
+    m_bSRSNameConsistent(true)
 {
     m_pszName = CPLStrdup( pszName );
-    n_nNameLen = strlen( m_pszName );
-    m_pszElementName = NULL;
-    n_nElementNameLen = 0;
-    m_nPropertyCount = 0;
-    m_papoProperty = NULL;
-    m_nGeometryPropertyCount = 0;
-    m_papoGeometryProperty = NULL;
-    m_bSchemaLocked = FALSE;
-
-    m_pszExtraInfo = NULL;
-    m_bHaveExtents = FALSE;
-    m_nFeatureCount = -1; // unknown
-
-    m_pszSRSName = NULL;
-    m_bSRSNameConsistent = TRUE;
+    n_nNameLen = static_cast<int>(strlen( m_pszName ));
 }
 
 /************************************************************************/
@@ -244,15 +247,15 @@ void GMLFeatureClass::ClearGeometryProperties()
 /*                         HasFeatureProperties()                       */
 /************************************************************************/
 
-int GMLFeatureClass::HasFeatureProperties()
+bool GMLFeatureClass::HasFeatureProperties()
 {
     for( int i = 0; i < m_nPropertyCount; i++ )
     {
         if( m_papoProperty[i]->GetType() == GMLPT_FeatureProperty ||
             m_papoProperty[i]->GetType() == GMLPT_FeaturePropertyList )
-            return TRUE;
+            return true;
     }
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
@@ -264,7 +267,7 @@ void GMLFeatureClass::SetElementName( const char *pszElementName )
 {
     CPLFree( m_pszElementName );
     m_pszElementName = CPLStrdup( pszElementName );
-    n_nElementNameLen = strlen(pszElementName);
+    n_nElementNameLen = static_cast<int>(strlen(pszElementName));
 }
 
 /************************************************************************/
@@ -341,7 +344,7 @@ void GMLFeatureClass::SetExtraInfo( const char *pszExtraInfo )
 /*                             SetExtents()                             */
 /************************************************************************/
 
-void GMLFeatureClass::SetExtents( double dfXMin, double dfXMax, 
+void GMLFeatureClass::SetExtents( double dfXMin, double dfXMax,
                                   double dfYMin, double dfYMax )
 
 {
@@ -350,14 +353,14 @@ void GMLFeatureClass::SetExtents( double dfXMin, double dfXMax,
     m_dfYMin = dfYMin;
     m_dfYMax = dfYMax;
 
-    m_bHaveExtents = TRUE;
+    m_bHaveExtents = true;
 }
 
 /************************************************************************/
 /*                             GetExtents()                             */
 /************************************************************************/
 
-int GMLFeatureClass::GetExtents( double *pdfXMin, double *pdfXMax, 
+bool GMLFeatureClass::GetExtents( double *pdfXMin, double *pdfXMax,
                                  double *pdfYMin, double *pdfYMax )
 
 {
@@ -379,7 +382,7 @@ int GMLFeatureClass::GetExtents( double *pdfXMin, double *pdfXMax,
 void GMLFeatureClass::SetSRSName( const char* pszSRSName )
 
 {
-    m_bSRSNameConsistent = TRUE;
+    m_bSRSNameConsistent = true;
     CPLFree(m_pszSRSName);
     m_pszSRSName = (pszSRSName) ? CPLStrdup(pszSRSName) : NULL;
 }
@@ -415,28 +418,28 @@ void GMLFeatureClass::MergeSRSName( const char* pszSRSName )
 /*                         InitializeFromXML()                          */
 /************************************************************************/
 
-int GMLFeatureClass::InitializeFromXML( CPLXMLNode *psRoot )
+bool GMLFeatureClass::InitializeFromXML( CPLXMLNode *psRoot )
 
 {
 /* -------------------------------------------------------------------- */
 /*      Do some rudimentary checking that this is a well formed         */
 /*      node.                                                           */
 /* -------------------------------------------------------------------- */
-    if( psRoot == NULL 
-        || psRoot->eType != CXT_Element 
+    if( psRoot == NULL
+        || psRoot->eType != CXT_Element
         || !EQUAL(psRoot->pszValue,"GMLFeatureClass") )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "GMLFeatureClass::InitializeFromXML() called on %s node!",
                   psRoot->pszValue );
-        return FALSE;
+        return false;
     }
 
     if( CPLGetXMLValue( psRoot, "Name", NULL ) == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "GMLFeatureClass has no <Name> element." );
-        return FALSE;
+        return false;
     }
 
 /* -------------------------------------------------------------------- */
@@ -444,7 +447,7 @@ int GMLFeatureClass::InitializeFromXML( CPLXMLNode *psRoot )
 /* -------------------------------------------------------------------- */
     CPLFree( m_pszName );
     m_pszName = CPLStrdup( CPLGetXMLValue( psRoot, "Name", NULL ) );
-    n_nNameLen = strlen(m_pszName);
+    n_nNameLen = static_cast<int>(strlen(m_pszName));
 
     SetElementName( CPLGetXMLValue( psRoot, "ElementPath", m_pszName ) );
 
@@ -453,10 +456,10 @@ int GMLFeatureClass::InitializeFromXML( CPLXMLNode *psRoot )
 /* -------------------------------------------------------------------- */
     CPLXMLNode *psThis;
 
-    int bHasValidGeometryName = FALSE;
-    int bHasValidGeometryElementPath = FALSE;
-    int bHasFoundGeomType = FALSE;
-    int bHasFoundGeomElements = FALSE;
+    bool bHasValidGeometryName = false;
+    bool bHasValidGeometryElementPath = false;
+    bool bHasFoundGeomType = false;
+    bool bHasFoundGeomElements = false;
     const char* pszGName = "";
     const char* pszGPath = "";
     int nGeomType = wkbUnknown;
@@ -469,7 +472,7 @@ int GMLFeatureClass::InitializeFromXML( CPLXMLNode *psRoot )
             const char *pszName = CPLGetXMLValue( psThis, "Name", "" );
             const char *pszElementPath = CPLGetXMLValue( psThis, "ElementPath", "" );
             const char *pszType = CPLGetXMLValue( psThis, "Type", NULL );
-            int bNullable = CSLTestBoolean(CPLGetXMLValue( psThis, "Nullable", "true") );
+            bool bNullable = CPLTestBool(CPLGetXMLValue( psThis, "Nullable", "true") );
             nGeomType = wkbUnknown;
             if( pszType != NULL && !EQUAL(pszType, "0") )
             {
@@ -478,68 +481,66 @@ int GMLFeatureClass::InitializeFromXML( CPLXMLNode *psRoot )
                 if( nGeomType != 0 && !(nFlattenGeomType >= wkbPoint && nFlattenGeomType <= wkbMultiSurface) )
                 {
                     nGeomType = wkbUnknown;
-                    CPLError(CE_Warning, CPLE_AppDefined, "Unrecognised geometry type : %s",
-                            pszType);
+                    CPLError( CE_Warning, CPLE_AppDefined,
+                              "Unrecognized geometry type : %s",
+                              pszType);
                 }
                 else if( nGeomType == 0 )
                     nGeomType = OGRFromOGCGeomType(pszType);
             }
-            bHasFoundGeomElements = TRUE;
+            bHasFoundGeomElements = true;
             AddGeometryProperty( new GMLGeometryPropertyDefn( pszName, pszElementPath, nGeomType, -1, bNullable ) );
-            bHasValidGeometryName = FALSE;
-            bHasValidGeometryElementPath = FALSE;
-            bHasFoundGeomType = FALSE;
+            bHasValidGeometryName = false;
+            bHasValidGeometryElementPath = false;
+            bHasFoundGeomType = false;
         }
         else if( psThis->eType == CXT_Element &&
             strcmp(psThis->pszValue, "GeometryName") == 0 )
         {
-            bHasFoundGeomElements = TRUE;
+            bHasFoundGeomElements = true;
 
             if( bHasValidGeometryName )
             {
-                AddGeometryProperty( new GMLGeometryPropertyDefn( pszGName, pszGPath, nGeomType, -1, TRUE ) );
-                bHasValidGeometryName = FALSE;
-                bHasValidGeometryElementPath = FALSE;
-                bHasFoundGeomType = FALSE;
-                pszGName = "";
+                AddGeometryProperty( new GMLGeometryPropertyDefn( pszGName, pszGPath, nGeomType, -1, true ) );
+                /*bHasValidGeometryName = false;*/
+                bHasValidGeometryElementPath = false;
+                bHasFoundGeomType = false;
                 pszGPath = "";
                 nGeomType = wkbUnknown;
             }
             pszGName = CPLGetXMLValue( psThis, NULL, "" );
-            bHasValidGeometryName = TRUE;
+            bHasValidGeometryName = true;
         }
         else if( psThis->eType == CXT_Element &&
             strcmp(psThis->pszValue, "GeometryElementPath") == 0 )
         {
-            bHasFoundGeomElements = TRUE;
+            bHasFoundGeomElements = true;
 
             if( bHasValidGeometryElementPath )
             {
-                AddGeometryProperty( new GMLGeometryPropertyDefn( pszGName, pszGPath, nGeomType, -1, TRUE ) );
-                bHasValidGeometryName = FALSE;
-                bHasValidGeometryElementPath = FALSE;
-                bHasFoundGeomType = FALSE;
+                AddGeometryProperty( new GMLGeometryPropertyDefn( pszGName, pszGPath, nGeomType, -1, true ) );
+                bHasValidGeometryName = false;
+                /*bHasValidGeometryElementPath = false;*/
+                bHasFoundGeomType = false;
                 pszGName = "";
-                pszGPath = "";
                 nGeomType = wkbUnknown;
             }
             pszGPath = CPLGetXMLValue( psThis, NULL, "" );
-            bHasValidGeometryElementPath = TRUE;
+            bHasValidGeometryElementPath = true;
         }
         else if( psThis->eType == CXT_Element &&
                  strcmp(psThis->pszValue, "GeometryType") == 0 )
         {
-            bHasFoundGeomElements = TRUE;
+            bHasFoundGeomElements = true;
 
             if( bHasFoundGeomType )
             {
-                AddGeometryProperty( new GMLGeometryPropertyDefn( pszGName, pszGPath, nGeomType, -1, TRUE ) );
-                bHasValidGeometryName = FALSE;
-                bHasValidGeometryElementPath = FALSE;
-                bHasFoundGeomType = FALSE;
+                AddGeometryProperty( new GMLGeometryPropertyDefn( pszGName, pszGPath, nGeomType, -1, true ) );
+                bHasValidGeometryName = false;
+                bHasValidGeometryElementPath = false;
+                /*bHasFoundGeomType = false;*/
                 pszGName = "";
                 pszGPath = "";
-                nGeomType = wkbUnknown;
             }
             const char* pszGeometryType = CPLGetXMLValue( psThis, NULL, NULL );
             nGeomType = wkbUnknown;
@@ -549,20 +550,21 @@ int GMLFeatureClass::InitializeFromXML( CPLXMLNode *psRoot )
                 OGRwkbGeometryType nFlattenGeomType = wkbFlatten(nGeomType);
                 if( nGeomType == 100 || EQUAL(pszGeometryType, "NONE") )
                 {
-                    bHasValidGeometryElementPath = FALSE;
-                    bHasFoundGeomType = FALSE;
+                    bHasValidGeometryElementPath = false;
+                    bHasFoundGeomType = false;
                     break;
                 }
                 else if( nGeomType != 0 && !(nFlattenGeomType >= wkbPoint && nFlattenGeomType <= wkbMultiSurface) )
                 {
                     nGeomType = wkbUnknown;
-                    CPLError(CE_Warning, CPLE_AppDefined, "Unrecognised geometry type : %s",
-                            pszGeometryType);
+                    CPLError( CE_Warning, CPLE_AppDefined,
+                              "Unrecognized geometry type : %s",
+                              pszGeometryType);
                 }
                 else if( nGeomType == 0 )
                     nGeomType = OGRFromOGCGeomType(pszGeometryType);
             }
-            bHasFoundGeomType = TRUE;
+            bHasFoundGeomType = true;
         }
     }
 
@@ -571,7 +573,7 @@ int GMLFeatureClass::InitializeFromXML( CPLXMLNode *psRoot )
     /* a geometry field */
     if( bHasValidGeometryElementPath || bHasFoundGeomType || !bHasFoundGeomElements )
     {
-        AddGeometryProperty( new GMLGeometryPropertyDefn( pszGName, pszGPath, nGeomType, -1, TRUE ) );
+        AddGeometryProperty( new GMLGeometryPropertyDefn( pszGName, pszGPath, nGeomType, -1, true ) );
     }
 
     SetSRSName( CPLGetXMLValue( psRoot, "SRSName", NULL ) );
@@ -593,7 +595,7 @@ int GMLFeatureClass::InitializeFromXML( CPLXMLNode *psRoot )
         if( pszValue != NULL )
             SetExtraInfo( pszValue );
 
-        if( CPLGetXMLValue( psDSI, "ExtentXMin", NULL ) != NULL 
+        if( CPLGetXMLValue( psDSI, "ExtentXMin", NULL ) != NULL
             && CPLGetXMLValue( psDSI, "ExtentXMax", NULL ) != NULL
             && CPLGetXMLValue( psDSI, "ExtentYMin", NULL ) != NULL
             && CPLGetXMLValue( psDSI, "ExtentYMax", NULL ) != NULL )
@@ -604,7 +606,7 @@ int GMLFeatureClass::InitializeFromXML( CPLXMLNode *psRoot )
                         CPLAtof(CPLGetXMLValue( psDSI, "ExtentYMax", "0.0" )) );
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Collect property definitions.                                   */
 /* -------------------------------------------------------------------- */
@@ -617,24 +619,24 @@ int GMLFeatureClass::InitializeFromXML( CPLXMLNode *psRoot )
             const char *pszType = CPLGetXMLValue( psThis, "Type", "Untyped" );
             const char *pszSubType = CPLGetXMLValue( psThis, "Subtype", "" );
             const char *pszCondition = CPLGetXMLValue( psThis, "Condition", NULL );
-            int bNullable = CSLTestBoolean(CPLGetXMLValue( psThis, "Nullable", "true") );
+            bool bNullable = CPLTestBool(CPLGetXMLValue( psThis, "Nullable", "true") );
             GMLPropertyDefn *poPDefn;
 
             if( pszName == NULL )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "GMLFeatureClass %s has a PropertyDefn without a <Name>..",
                           m_pszName );
-                return FALSE;
+                return false;
             }
 
-            poPDefn = new GMLPropertyDefn( 
+            poPDefn = new GMLPropertyDefn(
                 pszName, CPLGetXMLValue( psThis, "ElementPath", NULL ) );
-            
+
             poPDefn->SetNullable(bNullable);
             if( EQUAL(pszType,"Untyped") )
                 poPDefn->SetType( GMLPT_Untyped );
-            else if( EQUAL(pszType,"String") ) 
+            else if( EQUAL(pszType,"String") )
             {
                 if( EQUAL(pszSubType, "Boolean") )
                 {
@@ -676,7 +678,7 @@ int GMLFeatureClass::InitializeFromXML( CPLXMLNode *psRoot )
                 poPDefn->SetWidth( atoi( CPLGetXMLValue( psThis, "Width", "0" ) ) );
                 poPDefn->SetPrecision( atoi( CPLGetXMLValue( psThis, "Precision", "0" ) ) );
             }
-            else if( EQUAL(pszType,"StringList") ) 
+            else if( EQUAL(pszType,"StringList") )
             {
                 if( EQUAL(pszSubType, "Boolean") )
                     poPDefn->SetType( GMLPT_BooleanList );
@@ -700,20 +702,21 @@ int GMLFeatureClass::InitializeFromXML( CPLXMLNode *psRoot )
                 poPDefn->SetType( GMLPT_FeaturePropertyList );
             else
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                          "Unrecognised property type %s.", 
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Unrecognized property type %s.",
                           pszType );
                 delete poPDefn;
-                return FALSE;
+                return false;
             }
             if( pszCondition != NULL )
                 poPDefn->SetCondition(pszCondition);
 
-            AddProperty( poPDefn );
+            if( AddProperty( poPDefn ) < 0 )
+                delete poPDefn;
         }
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -733,7 +736,7 @@ CPLXMLNode *GMLFeatureClass::SerializeToXML()
 
     CPLCreateXMLElementAndValue( psRoot, "Name", GetName() );
     CPLCreateXMLElementAndValue( psRoot, "ElementPath", GetElementName() );
-    
+
     if( m_nGeometryPropertyCount > 1 )
     {
         for(int i=0; i < m_nGeometryPropertyCount; i++)
@@ -743,12 +746,12 @@ CPLXMLNode *GMLFeatureClass::SerializeToXML()
             CPLXMLNode *psPDefnNode;
             psPDefnNode = CPLCreateXMLNode( psRoot, CXT_Element, "GeomPropertyDefn" );
             if( strlen(poGeomFDefn->GetName()) > 0 )
-                CPLCreateXMLElementAndValue( psPDefnNode, "Name", 
+                CPLCreateXMLElementAndValue( psPDefnNode, "Name",
                                              poGeomFDefn->GetName() );
             if( poGeomFDefn->GetSrcElement() != NULL && strlen(poGeomFDefn->GetSrcElement()) > 0 )
-                CPLCreateXMLElementAndValue( psPDefnNode, "ElementPath", 
+                CPLCreateXMLElementAndValue( psPDefnNode, "ElementPath",
                                              poGeomFDefn->GetSrcElement() );
-            
+
             if( poGeomFDefn->GetType() != 0 /* wkbUnknown */ )
             {
                 char szValue[128];
@@ -759,7 +762,7 @@ CPLXMLNode *GMLFeatureClass::SerializeToXML()
                 if( wkbHasZ(eType) ) osStr += "Z";
                 CPLCreateXMLNode( psPDefnNode, CXT_Comment, osStr.c_str() );
 
-                sprintf( szValue, "%d", eType );
+                snprintf( szValue, sizeof(szValue), "%d", eType );
                 CPLCreateXMLElementAndValue( psPDefnNode, "Type", szValue );
             }
         }
@@ -767,15 +770,15 @@ CPLXMLNode *GMLFeatureClass::SerializeToXML()
     else if( m_nGeometryPropertyCount == 1 )
     {
         GMLGeometryPropertyDefn* poGeomFDefn = m_papoGeometryProperty[0];
-        
+
         if( strlen(poGeomFDefn->GetName()) > 0 )
-            CPLCreateXMLElementAndValue( psRoot, "GeometryName", 
+            CPLCreateXMLElementAndValue( psRoot, "GeometryName",
                                          poGeomFDefn->GetName() );
 
         if( poGeomFDefn->GetSrcElement() != NULL && strlen(poGeomFDefn->GetSrcElement()) > 0 )
-            CPLCreateXMLElementAndValue( psRoot, "GeometryElementPath", 
+            CPLCreateXMLElementAndValue( psRoot, "GeometryElementPath",
                                          poGeomFDefn->GetSrcElement() );
-        
+
         if( poGeomFDefn->GetType() != 0 /* wkbUnknown */ )
         {
             char szValue[128];
@@ -786,7 +789,7 @@ CPLXMLNode *GMLFeatureClass::SerializeToXML()
             if( wkbHasZ(eType) ) osStr += "Z";
             CPLCreateXMLNode( psRoot, CXT_Comment, osStr.c_str() );
 
-            sprintf( szValue, "%d", eType );
+            snprintf( szValue, sizeof(szValue), "%d", eType );
             CPLCreateXMLElementAndValue( psRoot, "GeometryType", szValue );
         }
     }
@@ -814,7 +817,7 @@ CPLXMLNode *GMLFeatureClass::SerializeToXML()
         {
             char szValue[128];
 
-            sprintf( szValue, CPL_FRMT_GIB, m_nFeatureCount );
+            snprintf( szValue, sizeof(szValue), CPL_FRMT_GIB, m_nFeatureCount );
             CPLCreateXMLElementAndValue( psDSI, "FeatureCount", szValue );
         }
 
@@ -842,7 +845,7 @@ CPLXMLNode *GMLFeatureClass::SerializeToXML()
         if( m_pszExtraInfo )
             CPLCreateXMLElementAndValue( psDSI, "ExtraInfo", m_pszExtraInfo );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      emit property information.                                      */
 /* -------------------------------------------------------------------- */
@@ -853,32 +856,32 @@ CPLXMLNode *GMLFeatureClass::SerializeToXML()
         const char *pszTypeName = "Unknown";
 
         psPDefnNode = CPLCreateXMLNode( psRoot, CXT_Element, "PropertyDefn" );
-        CPLCreateXMLElementAndValue( psPDefnNode, "Name", 
+        CPLCreateXMLElementAndValue( psPDefnNode, "Name",
                                      poPDefn->GetName() );
-        CPLCreateXMLElementAndValue( psPDefnNode, "ElementPath", 
+        CPLCreateXMLElementAndValue( psPDefnNode, "ElementPath",
                                      poPDefn->GetSrcElement() );
         switch( poPDefn->GetType() )
         {
           case GMLPT_Untyped:
             pszTypeName = "Untyped";
             break;
-            
+
           case GMLPT_String:
           case GMLPT_Boolean:
             pszTypeName = "String";
             break;
-            
+
           case GMLPT_Integer:
           case GMLPT_Short:
           case GMLPT_Integer64:
             pszTypeName = "Integer";
             break;
-            
+
           case GMLPT_Real:
           case GMLPT_Float:
             pszTypeName = "Real";
             break;
-            
+
           case GMLPT_Complex:
             pszTypeName = "Complex";
             break;
@@ -897,13 +900,13 @@ CPLXMLNode *GMLFeatureClass::SerializeToXML()
             pszTypeName = "StringList";
             break;
 
-          /* should not happen in practise for now because this is not */
+          /* should not happen in practice for now because this is not */
           /* autodetected */
           case GMLPT_FeatureProperty:
             pszTypeName = "FeatureProperty";
             break;
 
-          /* should not happen in practise for now because this is not */
+          /* should not happen in practice for now because this is not */
           /* autodetected */
           case GMLPT_FeaturePropertyList:
             pszTypeName = "FeaturePropertyList";
@@ -923,26 +926,25 @@ CPLXMLNode *GMLFeatureClass::SerializeToXML()
         if( EQUAL(pszTypeName,"String") )
         {
             char szMaxLength[48];
-            sprintf(szMaxLength, "%d", poPDefn->GetWidth());
+            snprintf(szMaxLength, sizeof(szMaxLength), "%d", poPDefn->GetWidth());
             CPLCreateXMLElementAndValue ( psPDefnNode, "Width", szMaxLength );
         }
         if( poPDefn->GetWidth() > 0 && EQUAL(pszTypeName,"Integer") )
         {
             char szLength[48];
-            sprintf(szLength, "%d", poPDefn->GetWidth());
+            snprintf(szLength, sizeof(szLength), "%d", poPDefn->GetWidth());
             CPLCreateXMLElementAndValue ( psPDefnNode, "Width", szLength );
         }
         if( poPDefn->GetWidth() > 0 && EQUAL(pszTypeName,"Real") )
         {
             char szLength[48];
-            sprintf(szLength, "%d", poPDefn->GetWidth());
+            snprintf(szLength, sizeof(szLength), "%d", poPDefn->GetWidth());
             CPLCreateXMLElementAndValue ( psPDefnNode, "Width", szLength );
             char szPrecision[48];
-            sprintf(szPrecision, "%d", poPDefn->GetPrecision());
+            snprintf(szPrecision, sizeof(szPrecision), "%d", poPDefn->GetPrecision());
             CPLCreateXMLElementAndValue ( psPDefnNode, "Precision", szPrecision );
         }
     }
 
     return psRoot;
 }
-
diff --git a/ogr/ogrsf_frmts/gml/gmlhandler.cpp b/ogr/ogrsf_frmts/gml/gmlhandler.cpp
index c08f481..08c0661 100644
--- a/ogr/ogrsf_frmts/gml/gmlhandler.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlhandler.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: gmlhandler.cpp 31860 2015-11-30 19:23:09Z rouault $
+ * $Id: gmlhandler.cpp 33702 2016-03-11 06:20:16Z goatbar $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLHandler class.
@@ -15,16 +15,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
@@ -64,7 +64,7 @@ void GMLXercesHandler::startElement(CPL_UNUSED const XMLCh* const uri,
     /* A XMLCh character can expand to 4 bytes in UTF-8 */
     if (4 * tr_strlen( localname ) >= MAX_TOKEN_SIZE)
     {
-        static int bWarnOnce = FALSE;
+        static bool bWarnOnce = false;
         XMLCh* tempBuffer = (XMLCh*) CPLMalloc(sizeof(XMLCh) * (MAX_TOKEN_SIZE / 4 + 1));
         memcpy(tempBuffer, localname, sizeof(XMLCh) * (MAX_TOKEN_SIZE / 4));
         tempBuffer[MAX_TOKEN_SIZE / 4] = 0;
@@ -72,14 +72,14 @@ void GMLXercesHandler::startElement(CPL_UNUSED const XMLCh* const uri,
         CPLFree(tempBuffer);
         if (!bWarnOnce)
         {
-            bWarnOnce = TRUE;
+            bWarnOnce = true;
             CPLError(CE_Warning, CPLE_AppDefined, "A too big element name has been truncated");
         }
     }
     else
         tr_strcpy( szElementName, localname );
 
-    if (GMLHandler::startElement(szElementName, strlen(szElementName), (void*) &attrs) == OGRERR_NOT_ENOUGH_MEMORY)
+    if (GMLHandler::startElement(szElementName, (int)strlen(szElementName), (void*) &attrs) == OGRERR_NOT_ENOUGH_MEMORY)
     {
         throw SAXNotSupportedException("Out of memory");
     }
@@ -115,7 +115,7 @@ void GMLXercesHandler::characters(const XMLCh* const chars_in,
 
 {
     char* utf8String = tr_strdup(chars_in);
-    int nLen = strlen(utf8String);
+    int nLen = (int)strlen(utf8String);
     OGRErr eErr = GMLHandler::dataHandler(utf8String, nLen);
     CPLFree(utf8String);
     if (eErr == OGRERR_NOT_ENOUGH_MEMORY)
@@ -134,8 +134,8 @@ void GMLXercesHandler::fatalError( const SAXParseException &exception)
     char *pszErrorMessage;
 
     pszErrorMessage = tr_strdup( exception.getMessage() );
-    CPLError( CE_Failure, CPLE_AppDefined, 
-              "XML Parsing Error: %s at line %d, column %d\n", 
+    CPLError( CE_Failure, CPLE_AppDefined,
+              "XML Parsing Error: %s at line %d, column %d\n",
               pszErrorMessage, (int)exception.getLineNumber(), (int)exception.getColumnNumber() );
 
     CPLFree( pszErrorMessage );
@@ -269,7 +269,7 @@ GMLExpatHandler::GMLExpatHandler( GMLReader *poReader, XML_Parser oParser ) : GM
 
 {
     m_oParser = oParser;
-    m_bStopParsing = FALSE;
+    m_bStopParsing = false;
     m_nDataHandlerCounter = 0;
 }
 
@@ -297,7 +297,7 @@ void XMLCALL GMLExpatHandler::startElementCbk(void *pUserData, const char *pszNa
     if (pThis->GMLHandler::startElement(pszName, (int)(pszIter - pszName), ppszAttr) == OGRERR_NOT_ENOUGH_MEMORY)
     {
         CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
-        pThis->m_bStopParsing = TRUE;
+        pThis->m_bStopParsing = true;
         XML_StopParser(pThis->m_oParser, XML_FALSE);
     }
 
@@ -316,7 +316,7 @@ void XMLCALL GMLExpatHandler::endElementCbk(void *pUserData,
     if (pThis->GMLHandler::endElement() == OGRERR_NOT_ENOUGH_MEMORY)
     {
         CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
-        pThis->m_bStopParsing = TRUE;
+        pThis->m_bStopParsing = true;
         XML_StopParser(pThis->m_oParser, XML_FALSE);
     }
 }
@@ -343,7 +343,7 @@ void XMLCALL GMLExpatHandler::dataHandlerCbk(void *pUserData, const char *data,
     if (pThis->m_nDataHandlerCounter >= PARSER_BUF_SIZE)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "File probably corrupted (million laugh pattern)");
-        pThis->m_bStopParsing = TRUE;
+        pThis->m_bStopParsing = true;
         XML_StopParser(pThis->m_oParser, XML_FALSE);
         return;
     }
@@ -351,7 +351,7 @@ void XMLCALL GMLExpatHandler::dataHandlerCbk(void *pUserData, const char *data,
     if (pThis->GMLHandler::dataHandler(data, nLen) == OGRERR_NOT_ENOUGH_MEMORY)
     {
         CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
-        pThis->m_bStopParsing = TRUE;
+        pThis->m_bStopParsing = true;
         XML_StopParser(pThis->m_oParser, XML_FALSE);
         return;
     }
@@ -500,7 +500,7 @@ GMLHandler::GMLHandler( GMLReader *poReader )
 
 {
     m_poReader = poReader;
-    m_bInCurField = FALSE;
+    m_bInCurField = false;
     m_nCurFieldAlloc = 0;
     m_nCurFieldLen = 0;
     m_pszCurField = NULL;
@@ -511,7 +511,7 @@ GMLHandler::GMLHandler( GMLReader *poReader )
     m_nGeomAlloc = 0;
     m_nGeomLen = 0;
     m_nGeometryDepth = 0;
-    m_bAlreadyFoundGeometry = FALSE;
+    m_bAlreadyFoundGeometry = false;
     m_nGeometryPropertyIndex = 0;
 
     m_nDepthFeature = m_nDepth = 0;
@@ -522,7 +522,7 @@ GMLHandler::GMLHandler( GMLReader *poReader )
     m_pszCityGMLGenericAttrName = NULL;
     m_inCityGMLGenericAttrDepth = 0;
 
-    m_bReportHref = FALSE;
+    m_bReportHref = false;
     m_pszHref = NULL;
     m_pszUom = NULL;
     m_pszValue = NULL;
@@ -743,7 +743,7 @@ OGRErr GMLHandler::startElementCityGMLGenericAttr(const char *pszName,
             m_pszCurField = NULL;
             m_nCurFieldLen = m_nCurFieldAlloc = 0;
         }
-        m_bInCurField = TRUE;
+        m_bInCurField = true;
     }
 
     return OGRERR_NONE;
@@ -758,7 +758,7 @@ void GMLHandler::DealWithAttributes(const char *pszName, int nLenName, void* att
     GMLReadState *poState = m_poReader->GetState();
     GMLFeatureClass *poClass = poState->m_poFeature->GetClass();
 
-    for(unsigned int idx=0; TRUE ;idx++)
+    for(unsigned int idx=0; true ;idx++)
     {
         char* pszAttrKey = NULL;
         char* pszAttrVal = NULL;
@@ -888,19 +888,19 @@ void GMLHandler::DealWithAttributes(const char *pszName, int nLenName, void* att
 /* FIXME! 'and' / 'or' operators are evaluated left to right, without */
 /* and precedence rules between them ! */
 
-int GMLHandler::IsConditionMatched(const char* pszCondition, void* attr)
+bool GMLHandler::IsConditionMatched(const char* pszCondition, void* attr)
 {
     if( pszCondition == NULL )
-        return TRUE;
+        return true;
 
-    int bSyntaxError = FALSE;
+    bool bSyntaxError = false;
     CPLString osCondAttr, osCondVal;
     const char* pszIter = pszCondition;
-    int bOpEqual = TRUE;
+    bool bOpEqual = true;
     while( *pszIter == ' ' )
         pszIter ++;
     if( *pszIter != '@' )
-        bSyntaxError = TRUE;
+        bSyntaxError = true;
     else
     {
         pszIter++;
@@ -917,19 +917,19 @@ int GMLHandler::IsConditionMatched(const char* pszCondition, void* attr)
 
         if( *pszIter == '!' )
         {
-            bOpEqual = FALSE;
+            bOpEqual = false;
             pszIter ++;
         }
 
         if( *pszIter != '=' )
-            bSyntaxError = TRUE;
+            bSyntaxError = true;
         else
         {
             pszIter ++;
             while( *pszIter == ' ' )
                 pszIter ++;
             if( *pszIter != '\'' )
-                bSyntaxError = TRUE;
+                bSyntaxError = true;
             else
             {
                 pszIter ++;
@@ -940,7 +940,7 @@ int GMLHandler::IsConditionMatched(const char* pszCondition, void* attr)
                     pszIter++;
                 }
                 if( *pszIter != '\'' )
-                    bSyntaxError = TRUE;
+                    bSyntaxError = true;
                 else
                 {
                     pszIter ++;
@@ -956,38 +956,38 @@ int GMLHandler::IsConditionMatched(const char* pszCondition, void* attr)
         CPLError(CE_Failure, CPLE_NotSupported,
                  "Invalid condition : %s. Must be of the form @attrname[!]='attrvalue' [and|or other_cond]*. 'and' and 'or' operators cannot be mixed",
                  pszCondition);
-        return FALSE;
+        return false;
     }
 
     char* pszVal = GetAttributeValue(attr, osCondAttr);
     if( pszVal == NULL )
         pszVal = CPLStrdup("");
-    int bCondMet = ((bOpEqual && strcmp(pszVal, osCondVal) == 0 ) ||
+    bool bCondMet = ((bOpEqual && strcmp(pszVal, osCondVal) == 0 ) ||
                     (!bOpEqual && strcmp(pszVal, osCondVal) != 0 ));
     CPLFree(pszVal);
     if( *pszIter == '\0' )
         return bCondMet;
 
-    if( strncmp(pszIter, "and", 3) == 0 )
+    if( STARTS_WITH(pszIter, "and") )
     {
         pszIter += 3;
         if( !bCondMet )
-            return FALSE;
+            return false;
         return IsConditionMatched(pszIter, attr);
     }
 
-    if( strncmp(pszIter, "or", 2) == 0 )
+    if( STARTS_WITH(pszIter, "or") )
     {
         pszIter += 2;
         if( bCondMet )
-            return TRUE;
+            return true;
         return IsConditionMatched(pszIter, attr);
     }
 
     CPLError(CE_Failure, CPLE_NotSupported,
                 "Invalid condition : %s. Must be of the form @attrname[!]='attrvalue' [and|or other_cond]*. 'and' and 'or' operators cannot be mixed",
                 pszCondition);
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
@@ -1031,7 +1031,7 @@ int GMLHandler::FindRealPropertyByCheckingConditions(int nIdx, void* attr)
 OGRErr GMLHandler::startElementFeatureAttribute(const char *pszName, int nLenName, void* attr )
 {
     /* Reset flag */
-    m_bInCurField = FALSE;
+    m_bInCurField = false;
 
     GMLReadState *poState = m_poReader->GetState();
 
@@ -1041,7 +1041,7 @@ OGRErr GMLHandler::startElementFeatureAttribute(const char *pszName, int nLenNam
 /* -------------------------------------------------------------------- */
     if( IsGeometryElement( pszName ) )
     {
-        int bReadGeometry;
+        bool bReadGeometry;
 
         /* If the <GeometryElementPath> is defined in the .gfs, use it */
         /* to read the appropriate geometry element */
@@ -1050,13 +1050,13 @@ OGRErr GMLHandler::startElementFeatureAttribute(const char *pszName, int nLenNam
         if( poClass->IsSchemaLocked() &&
             poClass->GetGeometryPropertyCount() == 0 )
         {
-            bReadGeometry = FALSE;
+            bReadGeometry = false;
         }
         else if( poClass->IsSchemaLocked() &&
                  poClass->GetGeometryPropertyCount() == 1 &&
                  poClass->GetGeometryProperty(0)->GetSrcElement()[0] == '\0' )
         {
-            bReadGeometry = TRUE;
+            bReadGeometry = true;
         }
         else if( poClass->IsSchemaLocked() &&
                  poClass->GetGeometryPropertyCount() > 0 )
@@ -1066,7 +1066,7 @@ OGRErr GMLHandler::startElementFeatureAttribute(const char *pszName, int nLenNam
         }
         else if( m_poReader->FetchAllGeometries() )
         {
-            bReadGeometry = TRUE;
+            bReadGeometry = true;
         }
         else if( !poClass->IsSchemaLocked() && m_poReader->IsWFSJointLayer() )
         {
@@ -1076,7 +1076,7 @@ OGRErr GMLHandler::startElementFeatureAttribute(const char *pszName, int nLenNam
                 const char* pszElement = poState->osPath.c_str();
                 CPLString osFieldName;
                 /* Strip member| prefix. Should always be true normally */
-                if( strncmp(pszElement, "member|", strlen("member|")) == 0 )
+                if( STARTS_WITH(pszElement, "member|") )
                     osFieldName = pszElement + strlen("member|");
 
                 /* Replace layer|property by layer_property */
@@ -1085,10 +1085,10 @@ OGRErr GMLHandler::startElementFeatureAttribute(const char *pszName, int nLenNam
                     osFieldName[iPos] = '.';
 
                 poClass->AddGeometryProperty( new GMLGeometryPropertyDefn(
-                        osFieldName, poState->osPath.c_str(), wkbUnknown, -1, TRUE ) );
+                        osFieldName, poState->osPath.c_str(), wkbUnknown, -1, true ) );
                 m_nGeometryPropertyIndex = poClass->GetGeometryPropertyCount();
             }
-            bReadGeometry = TRUE;
+            bReadGeometry = true;
         }
         else
         {
@@ -1100,22 +1100,22 @@ OGRErr GMLHandler::startElementFeatureAttribute(const char *pszName, int nLenNam
 
             /* For Inspire objects : the "main" geometry is in a <geometry> element */
             else if (m_bAlreadyFoundGeometry)
-                bReadGeometry = FALSE;
+                bReadGeometry = false;
             else if (strcmp( poState->osPath.c_str(), "geometry") == 0)
             {
-                m_bAlreadyFoundGeometry = TRUE;
-                bReadGeometry = TRUE;
+                m_bAlreadyFoundGeometry = true;
+                bReadGeometry = true;
                 m_nGeometryPropertyIndex = poClass->GetGeometryPropertyIndexBySrcElement( poState->osPath.c_str() );
                 if( m_nGeometryPropertyIndex < 0 )
                 {
                     poClass->AddGeometryProperty( new GMLGeometryPropertyDefn(
-                            "geometry", poState->osPath.c_str(), wkbUnknown, -1, TRUE ) );
+                            "geometry", poState->osPath.c_str(), wkbUnknown, -1, true ) );
                     m_nGeometryPropertyIndex = poClass->GetGeometryPropertyCount();
                 }
             }
 
             else
-                bReadGeometry = TRUE;
+                bReadGeometry = true;
         }
         if (bReadGeometry)
         {
@@ -1158,7 +1158,7 @@ OGRErr GMLHandler::startElementFeatureAttribute(const char *pszName, int nLenNam
 
         return OGRERR_NONE;
     }
-    
+
     else if( m_poReader->IsWFSJointLayer() && m_nDepth == m_nDepthFeature + 1 )
     {
     }
@@ -1206,7 +1206,7 @@ OGRErr GMLHandler::startElementFeatureAttribute(const char *pszName, int nLenNam
                     m_pszCurField = NULL;
                     m_nCurFieldLen = m_nCurFieldAlloc = 0;
                 }
-                m_bInCurField = TRUE;
+                m_bInCurField = true;
 
                 DealWithAttributes(pszName, nLenName, attr);
 
@@ -1248,7 +1248,7 @@ OGRErr GMLHandler::startElementTop(const char *pszName,
     else if (strcmp(pszName, "AIXMBasicMessage") == 0)
     {
         eAppSchemaType = APPSCHEMA_AIXM;
-        m_bReportHref = TRUE;
+        m_bReportHref = true;
     }
     else if (strcmp(pszName, "Maastotiedot") == 0)
     {
@@ -1258,10 +1258,10 @@ OGRErr GMLHandler::startElementTop(const char *pszName,
         m_poReader->SetGlobalSRSName(pszSRSName);
         CPLFree(pszSRSName);
 
-        m_bReportHref = TRUE;
+        m_bReportHref = true;
 
         /* the schemas of MTKGML don't have (string) width, so don't set it */
-        m_poReader->SetWidthFlag(FALSE);
+        m_poReader->SetWidthFlag(false);
     }
 
     stateStack[0] = STATE_DEFAULT;
@@ -1309,11 +1309,11 @@ OGRErr GMLHandler::startElementDefault(const char *pszName, int nLenName, void*
     /* WFS 2.0 GetFeature documents have a wfs:FeatureCollection */
     /* as a wfs:member of the top wfs:FeatureCollection. We don't want this */
     /* wfs:FeatureCollection to be recognized as a feature */
-    else if( (!(nLenName == strlen("FeatureCollection") &&
+    else if( (!(nLenName == (int)strlen("FeatureCollection") &&
                 strcmp(pszName, "FeatureCollection") == 0)) &&
              (nClassIndex = m_poReader->GetFeatureElementIndex( pszName, nLenName, eAppSchemaType )) != -1 )
     {
-        m_bAlreadyFoundGeometry = FALSE;
+        m_bAlreadyFoundGeometry = false;
 
         pszFilteredClassName = m_poReader->GetFilteredClassName();
         if ( pszFilteredClassName != NULL &&
@@ -1490,7 +1490,7 @@ OGRErr GMLHandler::endElementGeometry()
 
         /* AIXM ElevatedPoint. We want to parse this */
         /* a bit specially because ElevatedPoint is aixm: stuff and */
-        /* the srsDimension of the <gml:pos> can be set to TRUE although */
+        /* the srsDimension of the <gml:pos> can be set to true although */
         /* they are only 2 coordinates in practice */
         if ( eAppSchemaType == APPSCHEMA_AIXM && psInterestNode != NULL &&
             strcmp(psInterestNode->pszValue, "ElevatedPoint") == 0 )
@@ -1574,7 +1574,7 @@ OGRErr GMLHandler::endElementCityGMLGenericAttr()
         }
         m_pszCurField = NULL;
         m_nCurFieldLen = m_nCurFieldAlloc = 0;
-        m_bInCurField = FALSE;
+        m_bInCurField = false;
         CPLFree(m_pszCityGMLGenericAttrName);
         m_pszCityGMLGenericAttrName = NULL;
     }
@@ -1636,7 +1636,7 @@ OGRErr GMLHandler::endElementAttribute()
         }
 
         m_nCurFieldLen = m_nCurFieldAlloc = 0;
-        m_bInCurField = FALSE;
+        m_bInCurField = false;
         m_nAttributeIndex = -1;
 
         CPLFree( m_pszValue );
@@ -1759,11 +1759,20 @@ OGRErr GMLHandler::dataHandlerAttribute(const char *data, int nLen)
 
         int nCharsLen = nLen - nIter;
 
+        if( nCharsLen > INT_MAX - static_cast<int>(m_nCurFieldLen) - 1 )
+        {
+            CPLError(CE_Failure, CPLE_OutOfMemory,
+                    "Too much data in a single element");
+            return OGRERR_NOT_ENOUGH_MEMORY;
+        }
         if (m_nCurFieldLen + nCharsLen + 1 > m_nCurFieldAlloc)
         {
-            m_nCurFieldAlloc = m_nCurFieldAlloc * 4 / 3 + nCharsLen + 1;
+            if( m_nCurFieldAlloc < INT_MAX - m_nCurFieldAlloc / 3 - nCharsLen - 1 )
+                m_nCurFieldAlloc = m_nCurFieldAlloc + m_nCurFieldAlloc / 3 + nCharsLen + 1;
+            else
+                m_nCurFieldAlloc = m_nCurFieldLen + nCharsLen + 1;
             char *pszNewCurField = (char *)
-                VSIRealloc( m_pszCurField, m_nCurFieldAlloc );
+                VSI_REALLOC_VERBOSE( m_pszCurField, m_nCurFieldAlloc );
             if (pszNewCurField == NULL)
             {
                 return OGRERR_NOT_ENOUGH_MEMORY;
@@ -1802,11 +1811,20 @@ OGRErr GMLHandler::dataHandlerGeometry(const char *data, int nLen)
     int nCharsLen = nLen - nIter;
     if (nCharsLen)
     {
+        if( nCharsLen > INT_MAX - static_cast<int>(m_nGeomLen) - 1 )
+        {
+            CPLError(CE_Failure, CPLE_OutOfMemory,
+                    "Too much data in a single element");
+            return OGRERR_NOT_ENOUGH_MEMORY;
+        }
         if( m_nGeomLen + nCharsLen + 1 > m_nGeomAlloc )
         {
-            m_nGeomAlloc = m_nGeomAlloc * 4 / 3 + nCharsLen + 1;
+            if( m_nGeomAlloc < INT_MAX - m_nGeomAlloc / 3 - nCharsLen - 1 )
+                m_nGeomAlloc = m_nGeomAlloc + m_nGeomAlloc / 3 + nCharsLen + 1;
+            else
+                m_nGeomAlloc = m_nGeomAlloc + nCharsLen + 1;
             char* pszNewGeometry = (char *)
-                VSIRealloc( m_pszGeometry, m_nGeomAlloc);
+                VSI_REALLOC_VERBOSE( m_pszGeometry, m_nGeomAlloc);
             if (pszNewGeometry == NULL)
             {
                 return OGRERR_NOT_ENOUGH_MEMORY;
@@ -1826,7 +1844,7 @@ OGRErr GMLHandler::dataHandlerGeometry(const char *data, int nLen)
 /*                         IsGeometryElement()                          */
 /************************************************************************/
 
-int GMLHandler::IsGeometryElement( const char *pszElement )
+bool GMLHandler::IsGeometryElement( const char *pszElement )
 
 {
     int nFirst = 0;
@@ -1845,13 +1863,13 @@ int GMLHandler::IsGeometryElement( const char *pszElement )
 
     if (eAppSchemaType == APPSCHEMA_AIXM &&
         strcmp( pszElement, "ElevatedPoint") == 0)
-        return TRUE;
+        return true;
 
     if( eAppSchemaType == APPSCHEMA_MTKGML &&
         ( strcmp( pszElement, "Piste") == 0 ||
           strcmp( pszElement, "Alue") == 0  ||
           strcmp( pszElement, "Murtoviiva") == 0 ) )
-        return TRUE;
+        return true;
 
-    return FALSE;
+    return false;
 }
diff --git a/ogr/ogrsf_frmts/gml/gmlpropertydefn.cpp b/ogr/ogrsf_frmts/gml/gmlpropertydefn.cpp
index 6eaa094..e55a480 100644
--- a/ogr/ogrsf_frmts/gml/gmlpropertydefn.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlpropertydefn.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: gmlpropertydefn.cpp 28481 2015-02-13 17:11:15Z rouault $
+ * $Id: gmlpropertydefn.cpp 33702 2016-03-11 06:20:16Z goatbar $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLPropertyDefn
@@ -15,16 +15,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
@@ -36,7 +36,7 @@
 /*                           GMLPropertyDefn                            */
 /************************************************************************/
 
-GMLPropertyDefn::GMLPropertyDefn( const char *pszName, 
+GMLPropertyDefn::GMLPropertyDefn( const char *pszName,
                                   const char *pszSrcElement )
 
 {
@@ -52,10 +52,10 @@ GMLPropertyDefn::GMLPropertyDefn( const char *pszName,
         m_pszSrcElement = NULL;
     }
     m_eType = GMLPT_Untyped;
-    m_nWidth = 0; 
+    m_nWidth = 0;
     m_nPrecision = 0;
     m_pszCondition = NULL;
-    m_bNullable = TRUE;
+    m_bNullable = true;
 }
 
 /************************************************************************/
@@ -108,16 +108,15 @@ void GMLPropertyDefn::SetCondition( const char *pszCondition )
 /************************************************************************/
 
 void GMLPropertyDefn::AnalysePropertyValue( const GMLProperty* psGMLProperty,
-                                            int bSetWidth )
+                                            bool bSetWidth )
 
 {
 /* -------------------------------------------------------------------- */
 /*      Does the string consist entirely of numeric values?             */
 /* -------------------------------------------------------------------- */
-    int bIsReal = FALSE;
+    bool bIsReal = false;
 
-    int j;
-    for(j=0;j<psGMLProperty->nSubProperties;j++)
+    for( int j=0; j < psGMLProperty->nSubProperties; j++ )
     {
         if (j > 0)
         {
@@ -146,7 +145,7 @@ void GMLPropertyDefn::AnalysePropertyValue( const GMLProperty* psGMLProperty,
         CPLValueType valueType = CPLGetValueType(pszValue);
 
         if (valueType == CPL_VALUE_STRING
-            && m_eType != GMLPT_String 
+            && m_eType != GMLPT_String
             && m_eType != GMLPT_StringList )
         {
             if( (m_eType == GMLPT_Untyped || m_eType == GMLPT_Boolean) &&
@@ -168,15 +167,15 @@ void GMLPropertyDefn::AnalysePropertyValue( const GMLProperty* psGMLProperty,
         }
         else
             bIsReal = (valueType == CPL_VALUE_REAL);
-    
+
         if( m_eType == GMLPT_String )
         {
             if( bSetWidth )
             {
                 /* grow the Width to the length of the string passed in */
                 int nWidth;
-                nWidth = strlen(pszValue);
-                if ( m_nWidth < nWidth ) 
+                nWidth = static_cast<int>(strlen(pszValue));
+                if ( m_nWidth < nWidth )
                     SetWidth( nWidth );
             }
         }
@@ -188,7 +187,7 @@ void GMLPropertyDefn::AnalysePropertyValue( const GMLProperty* psGMLProperty,
             else if( m_eType != GMLPT_Integer64 )
             {
                 GIntBig nVal = CPLAtoGIntBig(pszValue);
-                if( (GIntBig)(int)nVal != nVal )
+                if( !CPL_INT64_FITS_ON_INT32(nVal) )
                     m_eType = GMLPT_Integer64;
                 else
                     m_eType = GMLPT_Integer;
@@ -202,7 +201,7 @@ void GMLPropertyDefn::AnalysePropertyValue( const GMLProperty* psGMLProperty,
         else if( m_eType == GMLPT_IntegerList && valueType == CPL_VALUE_INTEGER )
         {
             GIntBig nVal = CPLAtoGIntBig(pszValue);
-            if( (GIntBig)(int)nVal != nVal )
+            if( !CPL_INT64_FITS_ON_INT32(nVal) )
                 m_eType = GMLPT_Integer64List;
         }
     }
@@ -216,7 +215,7 @@ GMLGeometryPropertyDefn::GMLGeometryPropertyDefn( const char *pszName,
                                                   const char *pszSrcElement,
                                                   int nType,
                                                   int nAttributeIndex,
-                                                  int bNullable )
+                                                  bool bNullable )
 {
     m_pszName = (pszName == NULL || pszName[0] == '\0') ?
                         CPLStrdup(pszSrcElement) : CPLStrdup(pszName);
diff --git a/ogr/ogrsf_frmts/gml/gmlreader.cpp b/ogr/ogrsf_frmts/gml/gmlreader.cpp
index e2ef1b3..0651a84 100644
--- a/ogr/ogrsf_frmts/gml/gmlreader.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlreader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmlreader.cpp 29217 2015-05-21 09:08:48Z rouault $
+ * $Id: gmlreader.cpp 33702 2016-03-11 06:20:16Z goatbar $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLReader class.
@@ -15,24 +15,24 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "gmlreaderp.h"
 #include "gmlreader.h"
 #include "cpl_error.h"
 #include "cpl_string.h"
 #include "gmlutils.h"
-#include "gmlreaderp.h"
 #include "cpl_conv.h"
 #include <map>
 #include "cpl_multiproc.h"
@@ -63,10 +63,10 @@ IGMLReader::~IGMLReader()
 /*                          CreateGMLReader()                           */
 /************************************************************************/
 
-IGMLReader *CreateGMLReader(CPL_UNUSED int bUseExpatParserPreferably,
-                            CPL_UNUSED int bInvertAxisOrderIfLatLong,
-                            CPL_UNUSED int bConsiderEPSGAsURN,
-                            CPL_UNUSED int bGetSecondaryGeometryOption)
+IGMLReader *CreateGMLReader(bool /*bUseExpatParserPreferably*/,
+                            bool /*bInvertAxisOrderIfLatLong*/,
+                            bool /*bConsiderEPSGAsURN*/,
+                            bool /*bGetSecondaryGeometryOption*/)
 {
     CPLError( CE_Failure, CPLE_AppDefined,
               "Unable to create Xerces C++ or Expat based GML reader, Xerces or Expat support\n"
@@ -85,10 +85,10 @@ IGMLReader *CreateGMLReader(CPL_UNUSED int bUseExpatParserPreferably,
 /*                          CreateGMLReader()                           */
 /************************************************************************/
 
-IGMLReader *CreateGMLReader(int bUseExpatParserPreferably,
-                            int bInvertAxisOrderIfLatLong,
-                            int bConsiderEPSGAsURN,
-                            int bGetSecondaryGeometryOption)
+IGMLReader *CreateGMLReader(bool bUseExpatParserPreferably,
+                            bool bInvertAxisOrderIfLatLong,
+                            bool bConsiderEPSGAsURN,
+                            bool bGetSecondaryGeometryOption)
 
 {
     return new GMLReader(bUseExpatParserPreferably,
@@ -108,21 +108,21 @@ CPLMutex *GMLReader::hMutex = NULL;
 /************************************************************************/
 
 GMLReader::GMLReader(
-#ifndef HAVE_EXPAT
+#if !defined(HAVE_EXPAT) || !defined(HAVE_XERCES)
 CPL_UNUSED
 #endif
-                     int bUseExpatParserPreferably,
-                     int bInvertAxisOrderIfLatLong,
-                     int bConsiderEPSGAsURN,
-                     int bGetSecondaryGeometryOption)
+                     bool bUseExpatParserPreferably,
+                     bool bInvertAxisOrderIfLatLong,
+                     bool bConsiderEPSGAsURN,
+                     bool bGetSecondaryGeometryOption)
 {
 #ifndef HAVE_XERCES
-    bUseExpatReader = TRUE;
+    bUseExpatReader = true;
 #else
-    bUseExpatReader = FALSE;
+    bUseExpatReader = false;
 #ifdef HAVE_EXPAT
     if(bUseExpatParserPreferably)
-        bUseExpatReader = TRUE;
+        bUseExpatReader = true;
 #endif
 #endif
 
@@ -135,16 +135,16 @@ CPL_UNUSED
 
     m_nClassCount = 0;
     m_papoClass = NULL;
-    m_bLookForClassAtAnyLevel = FALSE;
+    m_bLookForClassAtAnyLevel = false;
 
-    m_bClassListLocked = FALSE;
+    m_bClassListLocked = false;
 
     m_poGMLHandler = NULL;
 #ifdef HAVE_XERCES
     m_poSAXReader = NULL;
     m_poCompleteFeature = NULL;
     m_GMLInputSource = NULL;
-    m_bEOF = FALSE;
+    m_bEOF = false;
 #endif
 #ifdef HAVE_EXPAT
     oParser = NULL;
@@ -155,39 +155,39 @@ CPL_UNUSED
     pabyBuf = NULL;
 #endif
     fpGML = NULL;
-    m_bReadStarted = FALSE;
-    
+    m_bReadStarted = false;
+
     m_poState = NULL;
     m_poRecycledState = NULL;
 
     m_pszFilename = NULL;
 
-    m_bStopParsing = FALSE;
+    m_bStopParsing = false;
 
     /* A bit experimental. Not publicly advertized. See commented doc in drv_gml.html */
-    m_bFetchAllGeometries = CSLTestBoolean(CPLGetConfigOption("GML_FETCH_ALL_GEOMETRIES", "NO"));
+    m_bFetchAllGeometries = CPLTestBool(CPLGetConfigOption("GML_FETCH_ALL_GEOMETRIES", "NO"));
 
     m_bInvertAxisOrderIfLatLong = bInvertAxisOrderIfLatLong;
     m_bConsiderEPSGAsURN = bConsiderEPSGAsURN;
     m_bGetSecondaryGeometryOption = bGetSecondaryGeometryOption;
 
     m_pszGlobalSRSName = NULL;
-    m_bCanUseGlobalSRSName = FALSE;
+    m_bCanUseGlobalSRSName = false;
 
     m_pszFilteredClassName = NULL;
     m_nFilteredClassIndex = -1;
 
-    m_bSequentialLayers = -1;
-	
+    m_nHasSequentialLayers = -1;
+
     /* Must be in synced in OGR_G_CreateFromGML(), OGRGMLLayer::OGRGMLLayer() and GMLReader::GMLReader() */
-    m_bFaceHoleNegative = CSLTestBoolean(CPLGetConfigOption("GML_FACE_HOLE_NEGATIVE", "NO"));
+    m_bFaceHoleNegative = CPLTestBool(CPLGetConfigOption("GML_FACE_HOLE_NEGATIVE", "NO"));
 
-    m_bSetWidthFlag = TRUE;
+    m_bSetWidthFlag = true;
 
-    m_bReportAllAttributes = FALSE;
+    m_bReportAllAttributes = false;
 
-    m_bIsWFSJointLayer = FALSE;
-    m_bEmptyAsNull = TRUE;
+    m_bIsWFSJointLayer = false;
+    m_bEmptyAsNull = true;
 }
 
 /************************************************************************/
@@ -263,7 +263,7 @@ void GMLReader::SetFP( VSILFILE* fp )
 /*                            SetupParser()                             */
 /************************************************************************/
 
-int GMLReader::SetupParser()
+bool GMLReader::SetupParser()
 
 {
     if (fpGML == NULL)
@@ -283,20 +283,21 @@ int GMLReader::SetupParser()
 #endif
     if (bRet < 0)
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "SetupParser(): shouldn't happen");
-        return FALSE;
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "SetupParser(): should not happen");
+        return false;
     }
 
     if (!bRet)
-        return FALSE;
+        return false;
 
-    m_bReadStarted = FALSE;
+    m_bReadStarted = false;
 
     // Push an empty state.
     PushState( m_poRecycledState ? m_poRecycledState : new GMLReadState() );
     m_poRecycledState = NULL;
 
-    return TRUE;
+    return true;
 }
 
 #ifdef HAVE_XERCES
@@ -304,7 +305,7 @@ int GMLReader::SetupParser()
 /*                        SetupParserXerces()                           */
 /************************************************************************/
 
-int GMLReader::SetupParserXerces()
+bool GMLReader::SetupParserXerces()
 {
     {
     CPLMutexHolderD(&hMutex);
@@ -315,19 +316,19 @@ int GMLReader::SetupParserXerces()
         {
             XMLPlatformUtils::Initialize();
         }
-        
+
         catch (const XMLException& toCatch)
         {
             CPLError( CE_Warning, CPLE_AppDefined,
-                      "Exception initializing Xerces based GML reader.\n%s", 
+                      "Exception initializing Xerces based GML reader.\n%s",
                       tr_strdup(toCatch.getMessage()) );
             m_eXercesInitState = OGRGML_XERCES_INIT_FAILED;
-            return FALSE;
+            return false;
         }
         m_eXercesInitState = OGRGML_XERCES_INIT_SUCCESSFUL;
     }
     if( m_eXercesInitState != OGRGML_XERCES_INIT_SUCCESSFUL )
-        return FALSE;
+        return false;
     }
 
     // Cleanup any old parser.
@@ -340,7 +341,7 @@ int GMLReader::SetupParserXerces()
 
     try{
         m_poSAXReader = XMLReaderFactory::createXMLReader();
-    
+
         GMLXercesHandler* poXercesHandler = new GMLXercesHandler( this );
         m_poGMLHandler = poXercesHandler;
 
@@ -382,13 +383,13 @@ int GMLReader::SetupParserXerces()
 
         CPLError( CE_Warning, CPLE_AppDefined,
                   "Exception initializing Xerces based GML reader.\n" );
-        return FALSE;
+        return false;
     }
 
     if (m_GMLInputSource == NULL && fpGML != NULL)
         m_GMLInputSource = new GMLInputSource(fpGML);
 
-    return TRUE;
+    return true;
 }
 #endif
 
@@ -397,7 +398,7 @@ int GMLReader::SetupParserXerces()
 /************************************************************************/
 
 #ifdef HAVE_EXPAT
-int GMLReader::SetupParserExpat()
+bool GMLReader::SetupParserExpat()
 {
     // Cleanup any old parser.
     if( oParser != NULL )
@@ -411,11 +412,11 @@ int GMLReader::SetupParserExpat()
     XML_SetUserData(oParser, m_poGMLHandler);
 
     if (pabyBuf == NULL)
-        pabyBuf = (char*)VSIMalloc(PARSER_BUF_SIZE);
+        pabyBuf = (char*)VSI_MALLOC_VERBOSE(PARSER_BUF_SIZE);
     if (pabyBuf == NULL)
-        return FALSE;
+        return false;
 
-    return TRUE;
+    return true;
 }
 #endif
 
@@ -446,7 +447,7 @@ void GMLReader::CleanupParser()
     m_GMLInputSource = NULL;
     delete m_poCompleteFeature;
     m_poCompleteFeature = NULL;
-    m_bEOF = FALSE;
+    m_bEOF = false;
 #endif
 
 #ifdef HAVE_EXPAT
@@ -454,8 +455,7 @@ void GMLReader::CleanupParser()
         XML_ParserFree(oParser);
     oParser = NULL;
 
-    int i;
-    for(i=nFeatureTabIndex;i<nFeatureTabLength;i++)
+    for( int i=nFeatureTabIndex; i < nFeatureTabLength; i++ )
         delete ppoFeatureTab[i];
     CPLFree(ppoFeatureTab);
     nFeatureTabIndex = 0;
@@ -468,14 +468,14 @@ void GMLReader::CleanupParser()
     delete m_poGMLHandler;
     m_poGMLHandler = NULL;
 
-    m_bReadStarted = FALSE;
+    m_bReadStarted = false;
 }
 
 #ifdef HAVE_XERCES
 
-GMLBinInputStream::GMLBinInputStream(VSILFILE* fp)
+GMLBinInputStream::GMLBinInputStream(VSILFILE* fpIn)
 {
-    this->fp = fp;
+    this->fp = fpIn;
     emptyString = 0;
 }
 
@@ -546,21 +546,21 @@ GMLFeature *GMLReader::NextFeatureXerces()
             if( m_poSAXReader == NULL )
                 SetupParser();
 
-            m_bReadStarted = TRUE;
+            m_bReadStarted = true;
 
-            if (m_GMLInputSource == NULL)
+            if (m_poSAXReader == NULL || m_GMLInputSource == NULL)
                 return NULL;
 
             if( !m_poSAXReader->parseFirst( *m_GMLInputSource, m_oToFill ) )
                 return NULL;
         }
 
-        while( m_poCompleteFeature == NULL 
+        while( m_poCompleteFeature == NULL
                && !m_bStopParsing
                && m_poSAXReader->parseNext( m_oToFill ) ) {}
 
         if (m_poCompleteFeature == NULL)
-            m_bEOF = TRUE;
+            m_bEOF = true;
 
         poReturn = m_poCompleteFeature;
         m_poCompleteFeature = NULL;
@@ -569,18 +569,18 @@ GMLFeature *GMLReader::NextFeatureXerces()
     catch (const XMLException& toCatch)
     {
         char *pszErrorMessage = tr_strdup( toCatch.getMessage() );
-        CPLDebug( "GML", 
-                  "Error during NextFeature()! Message:\n%s", 
+        CPLDebug( "GML",
+                  "Error during NextFeature()! Message:\n%s",
                   pszErrorMessage );
         CPLFree(pszErrorMessage);
-        m_bStopParsing = TRUE;
+        m_bStopParsing = true;
     }
     catch (const SAXException& toCatch)
     {
         char *pszErrorMessage = tr_strdup( toCatch.getMessage() );
         CPLError(CE_Failure, CPLE_AppDefined, "%s", pszErrorMessage);
         CPLFree(pszErrorMessage);
-        m_bStopParsing = TRUE;
+        m_bStopParsing = true;
     }
 
     return poReturn;
@@ -596,7 +596,7 @@ GMLFeature *GMLReader::NextFeatureExpat()
         if (oParser == NULL)
             SetupParser();
 
-        m_bReadStarted = TRUE;
+        m_bReadStarted = true;
     }
 
     if (fpGML == NULL || m_bStopParsing)
@@ -637,7 +637,7 @@ GMLFeature *GMLReader::NextFeatureExpat()
                      XML_ErrorString(XML_GetErrorCode(oParser)),
                      (int)XML_GetCurrentLineNumber(oParser),
                      (int)XML_GetCurrentColumnNumber(oParser));
-            m_bStopParsing = TRUE;
+            m_bStopParsing = true;
         }
         if (!m_bStopParsing)
             m_bStopParsing = ((GMLExpatHandler*)m_poGMLHandler)->HasStoppedParsing();
@@ -674,7 +674,7 @@ GMLFeature *GMLReader::NextFeature()
 /*      pushed onto the readstate stack.                                */
 /************************************************************************/
 
-void GMLReader::PushFeature( const char *pszElement, 
+void GMLReader::PushFeature( const char *pszElement,
                              const char *pszFID,
                              int nClassIndex )
 
@@ -791,20 +791,20 @@ int GMLReader::GetFeatureElementIndex( const char *pszElement, int nElementLengt
         }
 
         /* Begin of CSW SearchResults */
-        else if (nElementLength == strlen("BriefRecord") &&
-                 nLenLast == strlen("SearchResults") &&
+        else if (nElementLength == (int)strlen("BriefRecord") &&
+                 nLenLast == (int)strlen("SearchResults") &&
                  strcmp(pszElement, "BriefRecord") == 0 &&
                  strcmp(pszLast, "SearchResults") == 0)
         {
         }
-        else if (nElementLength == strlen("SummaryRecord") &&
-                 nLenLast == strlen("SearchResults") &&
+        else if (nElementLength == (int)strlen("SummaryRecord") &&
+                 nLenLast == (int)strlen("SearchResults") &&
                  strcmp(pszElement, "SummaryRecord") == 0 &&
                  strcmp(pszLast, "SearchResults") == 0)
         {
         }
-        else if (nElementLength == strlen("Record") &&
-                 nLenLast == strlen("SearchResults") &&
+        else if (nElementLength == (int)strlen("Record") &&
+                 nLenLast == (int)strlen("SearchResults") &&
                  strcmp(pszElement, "Record") == 0 &&
                  strcmp(pszLast, "SearchResults") == 0)
         {
@@ -831,7 +831,7 @@ int GMLReader::GetFeatureElementIndex( const char *pszElement, int nElementLengt
     }
 
     // If the class list isn't locked, any element that is a featureMember
-    // will do. 
+    // will do.
     if( !m_bClassListLocked )
         return INT_MAX;
 
@@ -850,17 +850,17 @@ int GMLReader::GetFeatureElementIndex( const char *pszElement, int nElementLengt
 /*                IsCityGMLGenericAttributeElement()                    */
 /************************************************************************/
 
-int GMLReader::IsCityGMLGenericAttributeElement( const char *pszElement, void* attr )
+bool GMLReader::IsCityGMLGenericAttributeElement( const char *pszElement, void* attr )
 
 {
     if( strcmp(pszElement, "stringAttribute") != 0 &&
         strcmp(pszElement, "intAttribute") != 0 &&
         strcmp(pszElement, "doubleAttribute") != 0 )
-        return FALSE;
+        return false;
 
     char* pszVal = m_poGMLHandler->GetAttributeValue(attr, "name");
     if (pszVal == NULL)
-        return FALSE;
+        return false;
 
     GMLFeatureClass *poClass = m_poState->m_poFeature->GetClass();
 
@@ -869,7 +869,7 @@ int GMLReader::IsCityGMLGenericAttributeElement( const char *pszElement, void* a
     if( !poClass->IsSchemaLocked() )
     {
         CPLFree(pszVal);
-        return TRUE;
+        return true;
     }
 
     for( int i = 0; i < poClass->GetPropertyCount(); i++ )
@@ -877,12 +877,12 @@ int GMLReader::IsCityGMLGenericAttributeElement( const char *pszElement, void* a
         if( strcmp(poClass->GetProperty(i)->GetSrcElement(),pszVal) == 0 )
         {
             CPLFree(pszVal);
-            return TRUE;
+            return true;
         }
     }
 
     CPLFree(pszVal);
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
@@ -908,7 +908,7 @@ int GMLReader::GetAttributeElementIndex( const char *pszElement, int nLen,
             return poClass->GetPropertyIndexBySrcElement(pszElement, nLen);
         else
         {
-            int nFullLen = nLen + 1 + strlen(pszAttrKey);
+            int nFullLen = nLen + 1 + static_cast<int>(strlen(pszAttrKey));
             osElemPath.reserve(nFullLen);
             osElemPath.assign(pszElement, nLen);
             osElemPath.append(1, '@');
@@ -918,9 +918,9 @@ int GMLReader::GetAttributeElementIndex( const char *pszElement, int nLen,
     }
     else
     {
-        int nFullLen = nLen + m_poState->osPath.size() + 1;
+        int nFullLen = nLen + static_cast<int>(m_poState->osPath.size()) + 1;
         if( pszAttrKey != NULL )
-            nFullLen += 1 + strlen(pszAttrKey);
+            nFullLen += 1 + static_cast<int>(strlen(pszAttrKey));
         osElemPath.reserve(nFullLen);
         osElemPath.assign(m_poState->osPath);
         osElemPath.append(1, '|');
@@ -972,7 +972,7 @@ void GMLReader::PopState()
         GMLReadState *poParent;
 
         poParent = m_poState->m_poParentState;
-        
+
         delete m_poRecycledState;
         m_poRecycledState = m_poState;
         m_poRecycledState->Reset();
@@ -1030,12 +1030,12 @@ int GMLReader::AddClass( GMLFeatureClass *poNewClass )
     CPLAssert( GetClass( poNewClass->GetName() ) == NULL );
 
     m_nClassCount++;
-    m_papoClass = (GMLFeatureClass **) 
+    m_papoClass = (GMLFeatureClass **)
         CPLRealloc( m_papoClass, sizeof(void*) * m_nClassCount );
     m_papoClass[m_nClassCount-1] = poNewClass;
 
     if( poNewClass->HasFeatureProperties() )
-        m_bLookForClassAtAnyLevel = TRUE;
+        m_bLookForClassAtAnyLevel = true;
 
     return m_nClassCount-1;
 }
@@ -1053,7 +1053,7 @@ void GMLReader::ClearClasses()
 
     m_nClassCount = 0;
     m_papoClass = NULL;
-    m_bLookForClassAtAnyLevel = FALSE;
+    m_bLookForClassAtAnyLevel = false;
 }
 
 /************************************************************************/
@@ -1064,7 +1064,7 @@ void GMLReader::ClearClasses()
 /*      The pszValue ownership is passed to this function.              */
 /************************************************************************/
 
-void GMLReader::SetFeaturePropertyDirectly( const char *pszElement, 
+void GMLReader::SetFeaturePropertyDirectly( const char *pszElement,
                                             char *pszValue,
                                             int iPropertyIn,
                                             GMLPropertyType eType )
@@ -1112,7 +1112,7 @@ void GMLReader::SetFeaturePropertyDirectly( const char *pszElement,
                 /* At that point the element path should be member|layer|property */
 
                 /* Strip member| prefix. Should always be true normally */
-                if( strncmp(pszElement, "member|", strlen("member|")) == 0 )
+                if( STARTS_WITH(pszElement, "member|") )
                     osFieldName = pszElement + strlen("member|");
 
                 /* Replace layer|property by layer_property */
@@ -1182,12 +1182,12 @@ void GMLReader::SetFeaturePropertyDirectly( const char *pszElement,
 /*                            LoadClasses()                             */
 /************************************************************************/
 
-int GMLReader::LoadClasses( const char *pszFile )
+bool GMLReader::LoadClasses( const char *pszFile )
 
 {
-    // Add logic later to determine reasonable default schema file. 
+    // Add logic later to determine reasonable default schema file.
     if( pszFile == NULL )
-        return FALSE;
+        return false;
 
 /* -------------------------------------------------------------------- */
 /*      Load the raw XML file.                                          */
@@ -1200,9 +1200,9 @@ int GMLReader::LoadClasses( const char *pszFile )
 
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "Failed to open file %s.", pszFile );
-        return FALSE;
+        return false;
     }
 
     VSIFSeekL( fp, 0, SEEK_END );
@@ -1212,21 +1212,21 @@ int GMLReader::LoadClasses( const char *pszFile )
     pszWholeText = (char *) VSIMalloc(nLength+1);
     if( pszWholeText == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Failed to allocate %d byte buffer for %s,\n"
                   "is this really a GMLFeatureClassList file?",
                   nLength, pszFile );
         VSIFCloseL( fp );
-        return FALSE;
+        return false;
     }
-    
+
     if( VSIFReadL( pszWholeText, nLength, 1, fp ) != 1 )
     {
         VSIFree( pszWholeText );
         VSIFCloseL( fp );
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Read failed on %s.", pszFile );
-        return FALSE;
+        return false;
     }
     pszWholeText[nLength] = '\0';
 
@@ -1235,10 +1235,10 @@ int GMLReader::LoadClasses( const char *pszFile )
     if( strstr( pszWholeText, "<GMLFeatureClassList" ) == NULL )
     {
         VSIFree( pszWholeText );
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "File %s does not contain a GMLFeatureClassList tree.",
                   pszFile );
-        return FALSE;
+        return false;
     }
 
 /* -------------------------------------------------------------------- */
@@ -1251,21 +1251,21 @@ int GMLReader::LoadClasses( const char *pszFile )
 
     // We assume parser will report errors via CPL.
     if( psRoot == NULL )
-        return FALSE;
+        return false;
 
-    if( psRoot->eType != CXT_Element 
+    if( psRoot->eType != CXT_Element
         || !EQUAL(psRoot->pszValue,"GMLFeatureClassList") )
     {
         CPLDestroyXMLNode(psRoot);
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "File %s is not a GMLFeatureClassList document.",
                   pszFile );
-        return FALSE;
+        return false;
     }
 
     const char* pszSequentialLayers = CPLGetXMLValue(psRoot, "SequentialLayers", NULL);
     if (pszSequentialLayers)
-        m_bSequentialLayers = CSLTestBoolean(pszSequentialLayers);
+        m_nHasSequentialLayers = CPLTestBool(pszSequentialLayers);
 
 /* -------------------------------------------------------------------- */
 /*      Extract feature classes for all definitions found.              */
@@ -1274,7 +1274,7 @@ int GMLReader::LoadClasses( const char *pszFile )
 
     for( psThis = psRoot->psChild; psThis != NULL; psThis = psThis->psNext )
     {
-        if( psThis->eType == CXT_Element 
+        if( psThis->eType == CXT_Element
             && EQUAL(psThis->pszValue,"GMLFeatureClass") )
         {
             GMLFeatureClass   *poClass;
@@ -1285,32 +1285,32 @@ int GMLReader::LoadClasses( const char *pszFile )
             {
                 delete poClass;
                 CPLDestroyXMLNode( psRoot );
-                return FALSE;
+                return false;
             }
 
-            poClass->SetSchemaLocked( TRUE );
+            poClass->SetSchemaLocked( true );
 
             AddClass( poClass );
         }
     }
 
     CPLDestroyXMLNode( psRoot );
-    
-    SetClassListLocked( TRUE );
 
-    return TRUE;
+    SetClassListLocked( true );
+
+    return true;
 }
 
 /************************************************************************/
 /*                            SaveClasses()                             */
 /************************************************************************/
 
-int GMLReader::SaveClasses( const char *pszFile )
+bool GMLReader::SaveClasses( const char *pszFile )
 
 {
-    // Add logic later to determine reasonable default schema file. 
+    // Add logic later to determine reasonable default schema file.
     if( pszFile == NULL )
-        return FALSE;
+        return false;
 
 /* -------------------------------------------------------------------- */
 /*      Create in memory schema tree.                                   */
@@ -1319,10 +1319,10 @@ int GMLReader::SaveClasses( const char *pszFile )
 
     psRoot = CPLCreateXMLNode( NULL, CXT_Element, "GMLFeatureClassList" );
 
-    if (m_bSequentialLayers != -1 && m_nClassCount > 1)
+    if (m_nHasSequentialLayers != -1 && m_nClassCount > 1)
     {
         CPLCreateXMLElementAndValue( psRoot, "SequentialLayers",
-                                     m_bSequentialLayers ? "true" : "false" );
+                                     m_nHasSequentialLayers ? "true" : "false" );
     }
 
     for( int iClass = 0; iClass < m_nClassCount; iClass++ )
@@ -1334,17 +1334,17 @@ int GMLReader::SaveClasses( const char *pszFile )
 /*      Serialize to disk.                                              */
 /* -------------------------------------------------------------------- */
     VSILFILE        *fp;
-    int         bSuccess = TRUE;
+    bool         bSuccess = true;
     char        *pszWholeText = CPLSerializeXMLTree( psRoot );
-    
+
     CPLDestroyXMLNode( psRoot );
- 
+
     fp = VSIFOpenL( pszFile, "wb" );
-    
+
     if( fp == NULL )
-        bSuccess = FALSE;
+        bSuccess = false;
     else if( VSIFWriteL( pszWholeText, strlen(pszWholeText), 1, fp ) != 1 )
-        bSuccess = FALSE;
+        bSuccess = false;
     else
         VSIFCloseL( fp );
 
@@ -1362,30 +1362,30 @@ int GMLReader::SaveClasses( const char *pszFile )
 /*      looking for schema information.                                 */
 /************************************************************************/
 
-int GMLReader::PrescanForSchema( int bGetExtents,
-                                 int bAnalyzeSRSPerFeature,
-                                 int bOnlyDetectSRS )
+bool GMLReader::PrescanForSchema( bool bGetExtents,
+                                 bool bAnalyzeSRSPerFeature,
+                                 bool bOnlyDetectSRS )
 
 {
     GMLFeature  *poFeature;
 
     if( m_pszFilename == NULL )
-        return FALSE;
+        return false;
 
     if( !bOnlyDetectSRS )
     {
-        SetClassListLocked( FALSE );
+        SetClassListLocked( false );
         ClearClasses();
     }
 
     if( !SetupParser() )
-        return FALSE;
+        return false;
 
-    m_bCanUseGlobalSRSName = TRUE;
+    m_bCanUseGlobalSRSName = true;
 
     GMLFeatureClass *poLastClass = NULL;
 
-    m_bSequentialLayers = TRUE;
+    m_nHasSequentialLayers = TRUE;
 
     void* hCacheSRS = GML_BuildOGRGeometryFromList_CreateCache();
 
@@ -1397,7 +1397,7 @@ int GMLReader::PrescanForSchema( int bGetExtents,
 
         if (poLastClass != NULL && poClass != poLastClass &&
             poClass->GetFeatureCount() != -1)
-            m_bSequentialLayers = FALSE;
+            m_nHasSequentialLayers = false;
         poLastClass = poClass;
 
         if( poClass->GetFeatureCount() == -1 )
@@ -1409,15 +1409,15 @@ int GMLReader::PrescanForSchema( int bGetExtents,
         if( !bOnlyDetectSRS && papsGeometry != NULL && papsGeometry[0] != NULL )
         {
             if( poClass->GetGeometryPropertyCount() == 0 )
-                poClass->AddGeometryProperty( new GMLGeometryPropertyDefn( "", "", wkbUnknown, -1, TRUE ) );
+                poClass->AddGeometryProperty( new GMLGeometryPropertyDefn( "", "", wkbUnknown, -1, true ) );
         }
 
 #ifdef SUPPORT_GEOMETRY
         if( bGetExtents && papsGeometry != NULL )
         {
             OGRGeometry *poGeometry = GML_BuildOGRGeometryFromList(
-                papsGeometry, TRUE, m_bInvertAxisOrderIfLatLong,
-                NULL, m_bConsiderEPSGAsURN, m_bGetSecondaryGeometryOption, 
+                papsGeometry, true, m_bInvertAxisOrderIfLatLong,
+                NULL, m_bConsiderEPSGAsURN, m_bGetSecondaryGeometryOption,
                 hCacheSRS, m_bFaceHoleNegative );
 
             if( poGeometry != NULL && poClass->GetGeometryPropertyCount() > 0 )
@@ -1425,7 +1425,7 @@ int GMLReader::PrescanForSchema( int bGetExtents,
                 double  dfXMin, dfXMax, dfYMin, dfYMax;
                 OGREnvelope sEnvelope;
 
-                OGRwkbGeometryType eGType = (OGRwkbGeometryType) 
+                OGRwkbGeometryType eGType = (OGRwkbGeometryType)
                     poClass->GetGeometryProperty(0)->GetType();
 
                 if( bAnalyzeSRSPerFeature )
@@ -1434,7 +1434,7 @@ int GMLReader::PrescanForSchema( int bGetExtents,
                                                                             osWork,
                                                                             m_bConsiderEPSGAsURN);
                     if (pszSRSName != NULL)
-                        m_bCanUseGlobalSRSName = FALSE;
+                        m_bCanUseGlobalSRSName = false;
                     poClass->MergeSRSName(pszSRSName);
                 }
 
@@ -1442,9 +1442,9 @@ int GMLReader::PrescanForSchema( int bGetExtents,
                 if( poClass->GetFeatureCount() == 1 && eGType == wkbUnknown )
                     eGType = wkbNone;
 
-                poClass->GetGeometryProperty(0)->SetType( 
+                poClass->GetGeometryProperty(0)->SetType(
                     (int) OGRMergeGeometryTypesEx(
-                        eGType, poGeometry->getGeometryType(), TRUE ) );
+                        eGType, poGeometry->getGeometryType(), true ) );
 
                 // merge extents.
                 if (!poGeometry->IsEmpty())
@@ -1472,7 +1472,7 @@ int GMLReader::PrescanForSchema( int bGetExtents,
             }
 #endif /* def SUPPORT_GEOMETRY */
         }
-        
+
         delete poFeature;
     }
 
@@ -1527,7 +1527,7 @@ int GMLReader::PrescanForSchema( int bGetExtents,
 
     CleanupParser();
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -1550,14 +1550,14 @@ void GMLReader::SetGlobalSRSName( const char* pszGlobalSRSName )
     if (m_pszGlobalSRSName == NULL && pszGlobalSRSName != NULL)
     {
         const char* pszVertCS_EPSG;
-        if( strncmp(pszGlobalSRSName, "EPSG:", 5) == 0 &&
+        if( STARTS_WITH(pszGlobalSRSName, "EPSG:") &&
             (pszVertCS_EPSG = strstr(pszGlobalSRSName, ", EPSG:")) != NULL )
         {
             m_pszGlobalSRSName = CPLStrdup(CPLSPrintf("EPSG:%d+%d",
                     atoi(pszGlobalSRSName + 5),
                     atoi(pszVertCS_EPSG + 7)));
         }
-        else if (strncmp(pszGlobalSRSName, "EPSG:", 5) == 0 &&
+        else if (STARTS_WITH(pszGlobalSRSName, "EPSG:") &&
             m_bConsiderEPSGAsURN)
         {
             m_pszGlobalSRSName = CPLStrdup(CPLSPrintf("urn:ogc:def:crs:EPSG::%s",
@@ -1574,7 +1574,7 @@ void GMLReader::SetGlobalSRSName( const char* pszGlobalSRSName )
 /*                       SetFilteredClassName()                         */
 /************************************************************************/
 
-int GMLReader::SetFilteredClassName(const char* pszClassName)
+bool GMLReader::SetFilteredClassName(const char* pszClassName)
 {
     CPLFree(m_pszFilteredClassName);
     m_pszFilteredClassName = (pszClassName) ? CPLStrdup(pszClassName) : NULL;
@@ -1592,5 +1592,5 @@ int GMLReader::SetFilteredClassName(const char* pszClassName)
         }
     }
 
-    return TRUE;
+    return true;
 }
diff --git a/ogr/ogrsf_frmts/gml/gmlreader.h b/ogr/ogrsf_frmts/gml/gmlreader.h
index 667c2ab..ea96e07 100644
--- a/ogr/ogrsf_frmts/gml/gmlreader.h
+++ b/ogr/ogrsf_frmts/gml/gmlreader.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmlreader.h 29051 2015-04-29 17:18:37Z rouault $
+ * $Id: gmlreader.h 33702 2016-03-11 06:20:16Z goatbar $
  *
  * Project:  GML Reader
  * Purpose:  Public Declarations for OGR free GML Reader code.
@@ -15,21 +15,21 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _GMLREADER_H_INCLUDED
-#define _GMLREADER_H_INCLUDED
+#ifndef GMLREADER_H_INCLUDED
+#define GMLREADER_H_INCLUDED
 
 #include "cpl_port.h"
 #include "cpl_vsi.h"
@@ -44,7 +44,7 @@ typedef enum {
     GMLPT_Real = 3,
     GMLPT_Complex = 4,
     GMLPT_StringList = 5,
-    GMLPT_IntegerList = 6, 
+    GMLPT_IntegerList = 6,
     GMLPT_RealList = 7,
     GMLPT_FeatureProperty = 8,
     GMLPT_FeaturePropertyList = 9,
@@ -76,16 +76,16 @@ class CPL_DLL GMLPropertyDefn
     char             *m_pszSrcElement;
     size_t            m_nSrcElementLen;
     char             *m_pszCondition;
-    int               m_bNullable;
+    bool              m_bNullable;
 
 public:
-    
+
         GMLPropertyDefn( const char *pszName, const char *pszSrcElement=NULL );
        ~GMLPropertyDefn();
 
-    const char *GetName() const { return m_pszName; } 
+    const char *GetName() const { return m_pszName; }
 
-    GMLPropertyType GetType() const { return m_eType; } 
+    GMLPropertyType GetType() const { return m_eType; }
     void        SetType( GMLPropertyType eType ) { m_eType = eType; }
     void        SetWidth( int nWidth) { m_nWidth = nWidth; }
     int         GetWidth() const { return m_nWidth; }
@@ -97,12 +97,12 @@ public:
 
     void        SetCondition( const char *pszCondition );
     const char *GetCondition() const { return m_pszCondition; }
-    
-    void        SetNullable( int bNullable ) { m_bNullable = bNullable; }
-    int         IsNullable() const { return m_bNullable; }
+
+    void        SetNullable( bool bNullable ) { m_bNullable = bNullable; }
+    bool        IsNullable() const { return m_bNullable; }
 
     void        AnalysePropertyValue( const GMLProperty* psGMLProperty,
-                                      int bSetWidth = TRUE );
+                                      bool bSetWidth = true );
 
     static bool IsSimpleType( GMLPropertyType eType )
     { return eType == GMLPT_String || eType == GMLPT_Integer || eType == GMLPT_Real; }
@@ -118,23 +118,23 @@ class CPL_DLL GMLGeometryPropertyDefn
     char       *m_pszSrcElement;
     int         m_nGeometryType;
     int         m_nAttributeIndex;
-    int         m_bNullable;
-    
+    bool        m_bNullable;
+
 public:
         GMLGeometryPropertyDefn( const char *pszName, const char *pszSrcElement,
                                  int nType, int nAttributeIndex,
-                                 int bNullable );
+                                 bool bNullable );
        ~GMLGeometryPropertyDefn();
 
-        const char *GetName() const { return m_pszName; } 
+        const char *GetName() const { return m_pszName; }
 
         int GetType() const { return m_nGeometryType; }
         void SetType(int nType) { m_nGeometryType = nType; }
         const char *GetSrcElement() const { return m_pszSrcElement; }
-        
+
         int GetAttributeIndex() const { return m_nAttributeIndex; }
 
-        int IsNullable() const { return m_bNullable; }
+        bool IsNullable() const { return m_bNullable; }
 };
 
 /************************************************************************/
@@ -148,24 +148,24 @@ class CPL_DLL GMLFeatureClass
     int          n_nElementNameLen;
     int         m_nPropertyCount;
     GMLPropertyDefn **m_papoProperty;
-    
+
     int         m_nGeometryPropertyCount;
     GMLGeometryPropertyDefn **m_papoGeometryProperty;
 
-    int         m_bSchemaLocked;
+    bool        m_bSchemaLocked;
 
     GIntBig     m_nFeatureCount;
 
     char        *m_pszExtraInfo;
 
-    int         m_bHaveExtents;
+    bool        m_bHaveExtents;
     double      m_dfXMin;
     double      m_dfXMax;
     double      m_dfYMin;
     double      m_dfYMax;
 
     char       *m_pszSRSName;
-    int         m_bSRSNameConsistent;
+    bool        m_bSRSNameConsistent;
 
 public:
             GMLFeatureClass( const char *pszName = "" );
@@ -180,7 +180,7 @@ public:
     int         GetPropertyCount() const { return m_nPropertyCount; }
     GMLPropertyDefn *GetProperty( int iIndex ) const;
     int GetPropertyIndex( const char *pszName ) const;
-    GMLPropertyDefn *GetProperty( const char *pszName ) const 
+    GMLPropertyDefn *GetProperty( const char *pszName ) const
         { return GetProperty( GetPropertyIndex(pszName) ); }
     int         GetPropertyIndexBySrcElement( const char *pszElement, int nLen ) const;
     void        StealProperties();
@@ -190,14 +190,14 @@ public:
     int         GetGeometryPropertyIndexBySrcElement( const char *pszElement ) const;
     void        StealGeometryProperties();
 
-    int         HasFeatureProperties();
+    bool        HasFeatureProperties();
 
     int         AddProperty( GMLPropertyDefn * );
     int         AddGeometryProperty( GMLGeometryPropertyDefn * );
     void        ClearGeometryProperties();
 
-    int         IsSchemaLocked() const { return m_bSchemaLocked; }
-    void        SetSchemaLocked( int bLock ) { m_bSchemaLocked = bLock; }
+    bool        IsSchemaLocked() const { return m_bSchemaLocked; }
+    void        SetSchemaLocked( bool bLock ) { m_bSchemaLocked = bLock; }
 
     const char  *GetExtraInfo();
     void        SetExtraInfo( const char * );
@@ -205,10 +205,10 @@ public:
     GIntBig     GetFeatureCount();
     void        SetFeatureCount( GIntBig );
 
-    int         HasExtents() const { return m_bHaveExtents; }
-    void        SetExtents( double dfXMin, double dfXMax, 
+    bool        HasExtents() const { return m_bHaveExtents; }
+    void        SetExtents( double dfXMin, double dfXMax,
                             double dFYMin, double dfYMax );
-    int         GetExtents( double *pdfXMin, double *pdfXMax, 
+    bool        GetExtents( double *pdfXMin, double *pdfXMax,
                             double *pdFYMin, double *pdfYMax );
 
     void        SetSRSName( const char* pszSRSName );
@@ -216,7 +216,7 @@ public:
     const char *GetSRSName() { return m_pszSRSName; }
 
     CPLXMLNode *SerializeToXML();
-    int         InitializeFromXML( CPLXMLNode * );
+    bool        InitializeFromXML( CPLXMLNode * );
 };
 
 /************************************************************************/
@@ -273,8 +273,8 @@ class CPL_DLL IGMLReader
 public:
     virtual     ~IGMLReader();
 
-    virtual int  IsClassListLocked() const = 0;
-    virtual void SetClassListLocked( int bFlag ) = 0;
+    virtual bool IsClassListLocked() const = 0;
+    virtual void SetClassListLocked( bool bFlag ) = 0;
 
     virtual void SetSourceFile( const char *pszFilename ) = 0;
     virtual void SetFP( CPL_UNUSED VSILFILE* fp ) {}
@@ -290,39 +290,39 @@ public:
     virtual GMLFeature *NextFeature() = 0;
     virtual void       ResetReading() = 0;
 
-    virtual int  LoadClasses( const char *pszFile = NULL ) = 0;
-    virtual int  SaveClasses( const char *pszFile = NULL ) = 0;
+    virtual bool LoadClasses( const char *pszFile = NULL ) = 0;
+    virtual bool SaveClasses( const char *pszFile = NULL ) = 0;
 
-    virtual int  ResolveXlinks( const char *pszFile,
-                                int* pbOutIsTempFile,
+    virtual bool ResolveXlinks( const char *pszFile,
+                                bool* pbOutIsTempFile,
                                 char **papszSkip = NULL,
-                                const int bStrict = FALSE ) = 0;
+                                const bool bStrict = false ) = 0;
 
-    virtual int  HugeFileResolver( const char *pszFile,
-                                   int pbSqlitIsTempFile,
+    virtual bool HugeFileResolver( const char *pszFile,
+                                   bool bSqliteIsTempFile,
                                    int iSqliteCacheMB ) = 0;
 
-    virtual int PrescanForSchema( int bGetExtents = TRUE,
-                                  int bAnalyzeSRSPerFeature = TRUE,
-                                  int bOnlyDetectSRS = FALSE ) = 0;
-    virtual int PrescanForTemplate( void ) = 0;
+    virtual bool PrescanForSchema( bool bGetExtents = true,
+                                  bool bAnalyzeSRSPerFeature = true,
+                                  bool bOnlyDetectSRS = false ) = 0;
+    virtual bool PrescanForTemplate( void ) = 0;
 
-    virtual int HasStoppedParsing() = 0;
+    virtual bool HasStoppedParsing() = 0;
 
     virtual void  SetGlobalSRSName( CPL_UNUSED const char* pszGlobalSRSName ) {}
     virtual const char* GetGlobalSRSName() = 0;
-    virtual int CanUseGlobalSRSName() = 0;
+    virtual bool CanUseGlobalSRSName() = 0;
 
-    virtual int SetFilteredClassName(const char* pszClassName) = 0;
+    virtual bool SetFilteredClassName(const char* pszClassName) = 0;
     virtual const char* GetFilteredClassName() = 0;
 
-    virtual int IsSequentialLayers() const { return FALSE; }
+    virtual bool IsSequentialLayers() const { return false; }
 };
 
-IGMLReader *CreateGMLReader(int bUseExpatParserPreferably,
-                            int bInvertAxisOrderIfLatLong,
-                            int bConsiderEPSGAsURN,
-                            int bGetSecondaryGeometryOption);
+IGMLReader *CreateGMLReader(bool bUseExpatParserPreferably,
+                            bool bInvertAxisOrderIfLatLong,
+                            bool bConsiderEPSGAsURN,
+                            bool bGetSecondaryGeometryOption);
 
 
-#endif /* _GMLREADER_H_INCLUDED */
+#endif /* GMLREADER_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/gml/gmlreaderp.h b/ogr/ogrsf_frmts/gml/gmlreaderp.h
index 202b573..bd731d9 100644
--- a/ogr/ogrsf_frmts/gml/gmlreaderp.h
+++ b/ogr/ogrsf_frmts/gml/gmlreaderp.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmlreaderp.h 29217 2015-05-21 09:08:48Z rouault $
+ * $Id: gmlreaderp.h 33702 2016-03-11 06:20:16Z goatbar $
  *
  * Project:  GML Reader
  * Purpose:  Private Declarations for OGR free GML Reader code.
@@ -15,21 +15,27 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _CPL_GMLREADERP_H_INCLUDED
-#define _CPL_GMLREADERP_H_INCLUDED
+#ifndef CPL_GMLREADERP_H_INCLUDED
+#define CPL_GMLREADERP_H_INCLUDED
+
+#if defined(HAVE_XERCES)
+
+#include "xercesc_headers.h"
+
+#endif /* HAVE_XERCES */
 
 #include "gmlreader.h"
 #include "ogr_api.h"
@@ -54,7 +60,7 @@ class GFSTemplateItem;
 class GFSTemplateList
 {
 private:
-    int             m_bSequentialLayers;
+    bool            m_bSequentialLayers;
     GFSTemplateItem *pFirst;
     GFSTemplateItem *pLast;
     GFSTemplateItem *Insert( const char *pszName );
@@ -63,13 +69,13 @@ public:
                     ~GFSTemplateList();
     void            Update( const char *pszName, int bHasGeom );
     GFSTemplateItem *GetFirst() { return pFirst; }
-    int             HaveSequentialLayers() { return m_bSequentialLayers; }
+    bool            HaveSequentialLayers() { return m_bSequentialLayers; }
     int             GetClassCount();
 };
 
 void gmlUpdateFeatureClasses ( GFSTemplateList *pCC,
                                GMLReader *pReader,
-                               int *pbSequentialLayers );
+                               int *pnHasSequentialLayers );
 
 /************************************************************************/
 /*                              GMLHandler                              */
@@ -108,18 +114,18 @@ typedef enum
 class GMLHandler
 {
     char      *m_pszCurField;
-    size_t     m_nCurFieldAlloc;
-    size_t     m_nCurFieldLen;
-    int        m_bInCurField;
+    unsigned int m_nCurFieldAlloc;
+    unsigned int m_nCurFieldLen;
+    bool       m_bInCurField;
     int        m_nAttributeIndex;
     int        m_nAttributeDepth;
 
 
     char      *m_pszGeometry;
-    int        m_nGeomAlloc;
-    int        m_nGeomLen;
+    unsigned int m_nGeomAlloc;
+    unsigned int m_nGeomLen;
     int        m_nGeometryDepth;
-    int        m_bAlreadyFoundGeometry;
+    bool       m_bAlreadyFoundGeometry;
     int        m_nGeometryPropertyIndex;
 
     int        m_nDepth;
@@ -130,7 +136,7 @@ class GMLHandler
     char      *m_pszCityGMLGenericAttrName;
     int        m_inCityGMLGenericAttrDepth;
 
-    int        m_bReportHref;
+    bool       m_bReportHref;
     char      *m_pszHref;
     char      *m_pszUom;
     char      *m_pszValue;
@@ -166,9 +172,9 @@ class GMLHandler
 
     OGRErr     startElementFeatureProperty(const char *pszName, int nLenName, void* attr);
     OGRErr     endElementFeatureProperty();
-    
+
     void       DealWithAttributes(const char *pszName, int nLenName, void* attr );
-    int        IsConditionMatched(const char* pszCondition, void* attr);
+    bool       IsConditionMatched(const char* pszCondition, void* attr);
     int        FindRealPropertyByCheckingConditions(int nIdx, void* attr);
 
 protected:
@@ -187,7 +193,7 @@ protected:
     OGRErr      endElement();
     OGRErr      dataHandler(const char *data, int nLen);
 
-    int         IsGeometryElement( const char *pszElement );
+    bool       IsGeometryElement( const char *pszElement );
 
 public:
     GMLHandler( GMLReader *poReader );
@@ -200,25 +206,6 @@ public:
 
 #if defined(HAVE_XERCES)
 
-// This works around problems with math.h on some platforms #defining INFINITY
-#ifdef INFINITY
-#undef  INFINITY
-#define INFINITY INFINITY_XERCES
-#endif
-
-#include <util/PlatformUtils.hpp>
-#include <sax2/DefaultHandler.hpp>
-#include <sax2/ContentHandler.hpp>
-#include <sax2/SAX2XMLReader.hpp>
-#include <sax2/XMLReaderFactory.hpp>
-#include <sax2/Attributes.hpp>
-#include <sax/InputSource.hpp>
-#include <util/BinInputStream.hpp>
-
-#ifdef XERCES_CPP_NAMESPACE_USE
-XERCES_CPP_NAMESPACE_USE
-#endif
-
 /************************************************************************/
 /*                        GMLBinInputStream                             */
 /************************************************************************/
@@ -277,7 +264,7 @@ class GMLXercesHandler : public DefaultHandler, public GMLHandler
 
 public:
     GMLXercesHandler( GMLReader *poReader );
-    
+
     void startElement(
         const   XMLCh* const    uri,
         const   XMLCh* const    localname,
@@ -320,13 +307,13 @@ public:
 class GMLExpatHandler : public GMLHandler
 {
     XML_Parser m_oParser;
-    int        m_bStopParsing;
+    bool       m_bStopParsing;
     int        m_nDataHandlerCounter;
 
 public:
     GMLExpatHandler( GMLReader *poReader, XML_Parser oParser );
 
-    int         HasStoppedParsing() { return m_bStopParsing; }
+    bool        HasStoppedParsing() { return m_bStopParsing; }
 
     void        ResetDataHandlerCounter() { m_nDataHandlerCounter = 0; }
 
@@ -389,20 +376,20 @@ typedef enum
     OGRGML_XERCES_INIT_SUCCESSFUL
 } OGRGMLXercesState;
 
-class GMLReader : public IGMLReader 
+class GMLReader : public IGMLReader
 {
 private:
     static OGRGMLXercesState    m_eXercesInitState;
     static int    m_nInstanceCount;
-    int           m_bClassListLocked;
+    bool          m_bClassListLocked;
 
     int         m_nClassCount;
     GMLFeatureClass **m_papoClass;
-    int           m_bLookForClassAtAnyLevel;
+    bool          m_bLookForClassAtAnyLevel;
 
     char          *m_pszFilename;
 
-    int            bUseExpatReader;
+    bool           bUseExpatReader;
 
     GMLHandler    *m_poGMLHandler;
 
@@ -411,8 +398,8 @@ private:
     XMLPScanToken m_oToFill;
     GMLFeature   *m_poCompleteFeature;
     GMLInputSource *m_GMLInputSource;
-    int           m_bEOF;
-    int           SetupParserXerces();
+    bool          m_bEOF;
+    bool          SetupParserXerces();
     GMLFeature   *NextFeatureXerces();
 #endif
 
@@ -422,64 +409,63 @@ private:
     int           nFeatureTabLength;
     int           nFeatureTabIndex;
     int           nFeatureTabAlloc;
-    int           SetupParserExpat();
+    bool          SetupParserExpat();
     GMLFeature   *NextFeatureExpat();
     char         *pabyBuf;
 #endif
 
     VSILFILE*     fpGML;
-    int           m_bReadStarted;
+    bool          m_bReadStarted;
 
     GMLReadState *m_poState;
     GMLReadState *m_poRecycledState;
 
-    int           m_bStopParsing;
+    bool          m_bStopParsing;
 
-    int           SetupParser();
+    bool          SetupParser();
     void          CleanupParser();
 
-    int           m_bFetchAllGeometries;
+    bool          m_bFetchAllGeometries;
 
-    int           m_bInvertAxisOrderIfLatLong;
-    int           m_bConsiderEPSGAsURN;
-    int           m_bGetSecondaryGeometryOption;
+    bool          m_bInvertAxisOrderIfLatLong;
+    bool          m_bConsiderEPSGAsURN;
+    bool          m_bGetSecondaryGeometryOption;
 
     int           ParseFeatureType(CPLXMLNode *psSchemaNode,
                                 const char* pszName,
                                 const char *pszType);
 
     char         *m_pszGlobalSRSName;
-    int           m_bCanUseGlobalSRSName;
+    bool          m_bCanUseGlobalSRSName;
 
     char         *m_pszFilteredClassName;
     int           m_nFilteredClassIndex;
 
-    int           m_bSequentialLayers;
+    int           m_nHasSequentialLayers;
 
     std::string   osElemPath;
 
-    int           m_bFaceHoleNegative;
-    
-    int           m_bSetWidthFlag;
-    
-    int           m_bReportAllAttributes;
-    
-    int           m_bIsWFSJointLayer;
-    
-    int           m_bEmptyAsNull;
-
-    int           ParseXMLHugeFile( const char *pszOutputFilename, 
-                                    const int bSqliteIsTempFile,
+    bool          m_bFaceHoleNegative;
+
+    bool          m_bSetWidthFlag;
+
+    bool          m_bReportAllAttributes;
+
+    bool          m_bIsWFSJointLayer;
+
+    bool          m_bEmptyAsNull;
+
+    bool          ParseXMLHugeFile( const char *pszOutputFilename,
+                                    const bool bSqliteIsTempFile,
                                     const int iSqliteCacheMB );
-                               
 
 public:
-                GMLReader(int bExpatReader, int bInvertAxisOrderIfLatLong,
-                          int bConsiderEPSGAsURN, int bGetSecondaryGeometryOption);
+                GMLReader(bool bExpatReader, bool bInvertAxisOrderIfLatLong,
+                          bool bConsiderEPSGAsURN, bool bGetSecondaryGeometryOption);
     virtual     ~GMLReader();
 
-    int              IsClassListLocked() const { return m_bClassListLocked; }
-    void             SetClassListLocked( int bFlag )
+    bool             IsClassListLocked() const { return m_bClassListLocked; }
+    void             SetClassListLocked( bool bFlag )
         { m_bClassListLocked = bFlag; }
 
     void             SetSourceFile( const char *pszFilename );
@@ -495,38 +481,38 @@ public:
 
     GMLFeature       *NextFeature();
 
-    int              LoadClasses( const char *pszFile = NULL );
-    int              SaveClasses( const char *pszFile = NULL );
+    bool             LoadClasses( const char *pszFile = NULL );
+    bool             SaveClasses( const char *pszFile = NULL );
 
-    int              ResolveXlinks( const char *pszFile,
-                                    int* pbOutIsTempFile,
+    bool             ResolveXlinks( const char *pszFile,
+                                    bool* pbOutIsTempFile,
                                     char **papszSkip = NULL,
-                                    const int bStrict = FALSE );
- 
-    int              HugeFileResolver( const char *pszFile,
-                                       int pbSqliteIsTempFile,
+                                    const bool bStrict = false );
+
+    bool             HugeFileResolver( const char *pszFile,
+                                       bool bSqliteIsTempFile,
                                        int iSqliteCacheMB );
 
-    int              PrescanForSchema(int bGetExtents = TRUE,
-                                      int bAnalyzeSRSPerFeature = TRUE,
-                                      int bOnlyDetectSRS = FALSE );
-    int              PrescanForTemplate( void );
-    int              ReArrangeTemplateClasses( GFSTemplateList *pCC );
+    bool             PrescanForSchema(bool bGetExtents = true,
+                                      bool bAnalyzeSRSPerFeature = true,
+                                      bool bOnlyDetectSRS = false );
+    bool             PrescanForTemplate( void );
+    bool             ReArrangeTemplateClasses( GFSTemplateList *pCC );
     void             ResetReading();
 
-// --- 
+// ---
 
     GMLReadState     *GetState() const { return m_poState; }
     void             PopState();
     void             PushState( GMLReadState * );
 
-    int              ShouldLookForClassAtAnyLevel() { return m_bLookForClassAtAnyLevel; }
+    bool             ShouldLookForClassAtAnyLevel() { return m_bLookForClassAtAnyLevel; }
 
     int         GetFeatureElementIndex( const char *pszElement, int nLen, GMLAppSchemaType eAppSchemaType );
     int         GetAttributeElementIndex( const char *pszElement, int nLen, const char* pszAttrKey = NULL );
-    int         IsCityGMLGenericAttributeElement( const char *pszElement, void* attr );
+    bool        IsCityGMLGenericAttributeElement( const char *pszElement, void* attr );
 
-    void        PushFeature( const char *pszElement, 
+    void        PushFeature( const char *pszElement,
                              const char *pszFID,
                              int nClassIndex );
 
@@ -535,33 +521,33 @@ public:
                                             int iPropertyIn,
                                             GMLPropertyType eType = GMLPT_Untyped );
 
-    void        SetWidthFlag(int bFlag) { m_bSetWidthFlag = bFlag; }
+    void        SetWidthFlag(bool bFlag) { m_bSetWidthFlag = bFlag; }
 
-    int         HasStoppedParsing() { return m_bStopParsing; }
+    bool        HasStoppedParsing() { return m_bStopParsing; }
 
-    int         FetchAllGeometries() { return m_bFetchAllGeometries; }
+    bool       FetchAllGeometries() { return m_bFetchAllGeometries; }
 
     void        SetGlobalSRSName( const char* pszGlobalSRSName ) ;
     const char* GetGlobalSRSName() { return m_pszGlobalSRSName; }
 
-    int         CanUseGlobalSRSName() { return m_bCanUseGlobalSRSName; }
+    bool        CanUseGlobalSRSName() { return m_bCanUseGlobalSRSName; }
 
-    int         SetFilteredClassName(const char* pszClassName);
+    bool        SetFilteredClassName(const char* pszClassName);
     const char* GetFilteredClassName() { return m_pszFilteredClassName; }
     int         GetFilteredClassIndex() { return m_nFilteredClassIndex; }
 
-    int         IsSequentialLayers() const { return m_bSequentialLayers == TRUE; }
-    
-    void        SetReportAllAttributes(int bFlag) { m_bReportAllAttributes = bFlag; }
-    int         ReportAllAttributes() const { return m_bReportAllAttributes; }
-    
-    void             SetIsWFSJointLayer( int bFlag ) { m_bIsWFSJointLayer = bFlag; }
-    int              IsWFSJointLayer() const { return m_bIsWFSJointLayer; }
-    
-    void             SetEmptyAsNull( int bFlag ) { m_bEmptyAsNull = bFlag; }
-    int              IsEmptyAsNull() const { return m_bEmptyAsNull; }
+    bool        IsSequentialLayers() const { return m_nHasSequentialLayers == TRUE; }
+
+    void        SetReportAllAttributes(bool bFlag) { m_bReportAllAttributes = bFlag; }
+    bool        ReportAllAttributes() const { return m_bReportAllAttributes; }
+
+    void             SetIsWFSJointLayer( bool bFlag ) { m_bIsWFSJointLayer = bFlag; }
+    bool             IsWFSJointLayer() const { return m_bIsWFSJointLayer; }
+
+    void             SetEmptyAsNull( bool bFlag ) { m_bEmptyAsNull = bFlag; }
+    bool             IsEmptyAsNull() const { return m_bEmptyAsNull; }
 
     static CPLMutex* hMutex;
 };
 
-#endif /* _CPL_GMLREADERP_H_INCLUDED */
+#endif /* CPL_GMLREADERP_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/gml/gmlreadstate.cpp b/ogr/ogrsf_frmts/gml/gmlreadstate.cpp
index fa662b1..3ec5c79 100644
--- a/ogr/ogrsf_frmts/gml/gmlreadstate.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlreadstate.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: gmlreadstate.cpp 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: gmlreadstate.cpp 33702 2016-03-11 06:20:16Z goatbar $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLReadState class.
@@ -15,16 +15,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
diff --git a/ogr/ogrsf_frmts/gml/gmlregistry.cpp b/ogr/ogrsf_frmts/gml/gmlregistry.cpp
index ca20a26..aa84061 100644
--- a/ogr/ogrsf_frmts/gml/gmlregistry.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlregistry.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmlregistry.cpp 29240 2015-05-24 10:58:38Z rouault $
+ * $Id: gmlregistry.cpp 33702 2016-03-11 06:20:16Z goatbar $
  *
  * Project:  GML registry
  * Purpose:  GML reader
@@ -14,16 +14,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
@@ -119,8 +119,8 @@ int GMLRegistryFeatureType::Parse(const char* pszRegistryFilename, CPLXMLNode* p
 
     if( pszSchemaLocation != NULL )
     {
-        if( strncmp(pszSchemaLocation, "http://", 7) != 0 &&
-            strncmp(pszSchemaLocation, "https://", 8) != 0 &&
+        if( !STARTS_WITH(pszSchemaLocation, "http://") &&
+            !STARTS_WITH(pszSchemaLocation, "https://") &&
             CPLIsFilenameRelative(pszSchemaLocation ) )
         {
             pszSchemaLocation = CPLFormFilename(
@@ -130,8 +130,8 @@ int GMLRegistryFeatureType::Parse(const char* pszRegistryFilename, CPLXMLNode* p
     }
     else if( pszGFSSchemaLocation != NULL )
     {
-        if( strncmp(pszGFSSchemaLocation, "http://", 7) != 0 &&
-            strncmp(pszGFSSchemaLocation, "https://", 8) != 0 &&
+        if( !STARTS_WITH(pszGFSSchemaLocation, "http://") &&
+            !STARTS_WITH(pszGFSSchemaLocation, "https://") &&
             CPLIsFilenameRelative(pszGFSSchemaLocation ) )
         {
             pszGFSSchemaLocation = CPLFormFilename(
@@ -142,7 +142,7 @@ int GMLRegistryFeatureType::Parse(const char* pszRegistryFilename, CPLXMLNode* p
 
     if ( pszElementValue != NULL )
     {
-        osElementValue = pszElementValue; 
+        osElementValue = pszElementValue;
     }
 
     return TRUE;
diff --git a/ogr/ogrsf_frmts/gml/gmlregistry.h b/ogr/ogrsf_frmts/gml/gmlregistry.h
index 837512c..9c2e861 100644
--- a/ogr/ogrsf_frmts/gml/gmlregistry.h
+++ b/ogr/ogrsf_frmts/gml/gmlregistry.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmlregistry.h 29240 2015-05-24 10:58:38Z rouault $
+ * $Id: gmlregistry.h 33702 2016-03-11 06:20:16Z goatbar $
  *
  * Project:  GML registry
  * Purpose:  GML reader
@@ -14,21 +14,21 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _GMLREGISTRY_H_INCLUDED
-#define _GMLREGISTRY_H_INCLUDED
+#ifndef GMLREGISTRY_H_INCLUDED
+#define GMLREGISTRY_H_INCLUDED
 
 #include "cpl_string.h"
 #include "cpl_minixml.h"
@@ -66,8 +66,8 @@ class GMLRegistry
     public:
         std::vector<GMLRegistryNamespace> aoNamespaces;
 
-        GMLRegistry(const CPLString& osRegistryPath) : osRegistryPath(osRegistryPath) {}
+        GMLRegistry(const CPLString& osRegistryPathIn) : osRegistryPath(osRegistryPathIn) {}
         int Parse();
 };
 
-#endif /* _GMLREGISTRY_H_INCLUDED */
+#endif /* GMLREGISTRY_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/gml/gmlutils.cpp b/ogr/ogrsf_frmts/gml/gmlutils.cpp
index 3236b77..e392311 100644
--- a/ogr/ogrsf_frmts/gml/gmlutils.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlutils.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmlutils.cpp 27576 2014-08-06 22:23:51Z rouault $
+ * $Id: gmlutils.cpp 33702 2016-03-11 06:20:16Z goatbar $
  *
  * Project:  GML Utils
  * Purpose:  GML reader
@@ -14,16 +14,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
@@ -41,16 +41,16 @@
 
 const char* GML_ExtractSrsNameFromGeometry(const CPLXMLNode* const * papsGeometry,
                                      std::string& osWork,
-                                     int bConsiderEPSGAsURN)
+                                     bool bConsiderEPSGAsURN)
 {
     if (papsGeometry[0] != NULL && papsGeometry[1] == NULL)
     {
         const char* pszSRSName = CPLGetXMLValue((CPLXMLNode*)papsGeometry[0], "srsName", NULL);
         if (pszSRSName)
         {
-            int nLen = strlen(pszSRSName);
+            int nLen = static_cast<int>(strlen(pszSRSName));
 
-            if (strncmp(pszSRSName, "EPSG:", 5) == 0 &&
+            if (STARTS_WITH(pszSRSName, "EPSG:") &&
                 bConsiderEPSGAsURN)
             {
                 osWork.reserve(22 + nLen-5);
@@ -58,7 +58,7 @@ const char* GML_ExtractSrsNameFromGeometry(const CPLXMLNode* const * papsGeometr
                 osWork.append(pszSRSName+5, nLen-5);
                 return osWork.c_str();
             }
-            else if (strncmp(pszSRSName, "http://www.opengis.net/gml/srs/epsg.xml#", 40) == 0)
+            else if (STARTS_WITH(pszSRSName, "http://www.opengis.net/gml/srs/epsg.xml#"))
             {
                 osWork.reserve(5 + nLen-40 );
                 osWork.assign("EPSG:", 5);
@@ -78,17 +78,17 @@ const char* GML_ExtractSrsNameFromGeometry(const CPLXMLNode* const * papsGeometr
 /*                       GML_IsSRSLatLongOrder()                        */
 /************************************************************************/
 
-int GML_IsSRSLatLongOrder(const char* pszSRSName)
+bool GML_IsSRSLatLongOrder(const char* pszSRSName)
 {
     if (pszSRSName == NULL)
-        return FALSE;
+        return false;
 
-    if (strncmp(pszSRSName, "urn:", 4) == 0)
+    if (STARTS_WITH(pszSRSName, "urn:"))
     {
         if (strstr(pszSRSName, ":4326") != NULL)
         {
             /* Shortcut ... */
-            return TRUE;
+            return true;
         }
         else
         {
@@ -96,11 +96,11 @@ int GML_IsSRSLatLongOrder(const char* pszSRSName)
             if (oSRS.importFromURN(pszSRSName) == OGRERR_NONE)
             {
                 if (oSRS.EPSGTreatsAsLatLong() || oSRS.EPSGTreatsAsNorthingEasting())
-                    return TRUE;
+                    return true;
             }
         }
     }
-    return FALSE;
+    return false;
 }
 
 
@@ -112,10 +112,10 @@ class SRSDesc
 {
 public:
     std::string          osSRSName;
-    int                  bAxisInvert;
+    bool                 bAxisInvert;
     OGRSpatialReference* poSRS;
 
-    SRSDesc() : bAxisInvert(FALSE), poSRS(NULL)
+    SRSDesc() : bAxisInvert(false), poSRS(NULL)
     {
     }
 };
@@ -185,22 +185,21 @@ void GML_BuildOGRGeometryFromList_DestroyCache(void* hCacheSRS)
 /************************************************************************/
 
 OGRGeometry* GML_BuildOGRGeometryFromList(const CPLXMLNode* const * papsGeometry,
-                                          int bTryToMakeMultipolygons,
-                                          int bInvertAxisOrderIfLatLong,
+                                          bool bTryToMakeMultipolygons,
+                                          bool bInvertAxisOrderIfLatLong,
                                           const char* pszDefaultSRSName,
-                                          int bConsiderEPSGAsURN,
-                                          int bGetSecondaryGeometryOption,
+                                          bool bConsiderEPSGAsURN,
+                                          int nPseudoBoolGetSecondaryGeometryOption,
                                           void* hCacheSRS,
-                                          int bFaceHoleNegative)
+                                          bool bFaceHoleNegative)
 {
     OGRGeometry* poGeom = NULL;
-    int i;
     OGRGeometryCollection* poCollection = NULL;
-    for(i=0;papsGeometry[i] != NULL;i++)
+    for( int i=0; papsGeometry[i] != NULL; i++ )
     {
         OGRGeometry* poSubGeom = GML2OGRGeometry_XMLNode( papsGeometry[i],
-                                                          bGetSecondaryGeometryOption,
-                                                          0, 0, FALSE, TRUE,
+                                                          nPseudoBoolGetSecondaryGeometryOption,
+                                                          0, 0, false, true,
                                                           bFaceHoleNegative );
         if (poSubGeom)
         {
@@ -233,10 +232,9 @@ OGRGeometry* GML_BuildOGRGeometryFromList(const CPLXMLNode* const * papsGeometry
                         OGRGeometryCollection* poGeomColl = (OGRGeometryCollection* )poGeom;
                         OGRGeometryCollection* poGeomColl2 = (OGRGeometryCollection* )poSubGeom;
                         int nCount = poGeomColl2->getNumGeometries();
-                        int i;
-                        for(i=0;i<nCount;i++)
+                        for(int j=0;j<nCount;j++)
                         {
-                            poGeomColl->addGeometry(poGeomColl2->getGeometryRef(i));
+                            poGeomColl->addGeometry(poGeomColl2->getGeometryRef(j));
                         }
                         delete poSubGeom;
                     }
@@ -245,11 +243,11 @@ OGRGeometry* GML_BuildOGRGeometryFromList(const CPLXMLNode* const * papsGeometry
                     {
                         delete poGeom;
                         delete poSubGeom;
-                        return GML_BuildOGRGeometryFromList(papsGeometry, FALSE,
+                        return GML_BuildOGRGeometryFromList(papsGeometry, false,
                                                             bInvertAxisOrderIfLatLong,
                                                             pszDefaultSRSName,
                                                             bConsiderEPSGAsURN,
-                                                            bGetSecondaryGeometryOption,
+                                                            nPseudoBoolGetSecondaryGeometryOption,
                                                             hCacheSRS);
                     }
                     else
@@ -266,7 +264,7 @@ OGRGeometry* GML_BuildOGRGeometryFromList(const CPLXMLNode* const * papsGeometry
             }
         }
     }
-    
+
     if( poGeom == NULL )
         return NULL;
 
@@ -293,9 +291,9 @@ OGRGeometry* GML_BuildOGRGeometryFromList(const CPLXMLNode* const * papsGeometry
 /*                           GML_GetSRSName()                           */
 /************************************************************************/
 
-char* GML_GetSRSName(const OGRSpatialReference* poSRS, int bLongSRS, int *pbCoordSwap)
+char* GML_GetSRSName(const OGRSpatialReference* poSRS, bool bLongSRS, bool *pbCoordSwap)
 {
-    *pbCoordSwap = FALSE;
+    *pbCoordSwap = false;
     if (poSRS == NULL)
         return CPLStrdup("");
 
@@ -326,18 +324,18 @@ char* GML_GetSRSName(const OGRSpatialReference* poSRS, int bLongSRS, int *pbCoor
                     if (oSRS.importFromEPSGA(atoi(pszAuthCode)) == OGRERR_NONE)
                     {
                         if (oSRS.EPSGTreatsAsLatLong() || oSRS.EPSGTreatsAsNorthingEasting())
-                            *pbCoordSwap = TRUE;
+                            *pbCoordSwap = true;
                     }
                 }
 
                 if (bLongSRS)
                 {
-                    sprintf( szSrsName, " srsName=\"urn:ogc:def:crs:%s::%s\"",
+                    snprintf( szSrsName, sizeof(szSrsName), " srsName=\"urn:ogc:def:crs:%s::%s\"",
                         pszAuthName, pszAuthCode );
                 }
                 else
                 {
-                    sprintf( szSrsName, " srsName=\"%s:%s\"",
+                    snprintf( szSrsName, sizeof(szSrsName), " srsName=\"%s:%s\"",
                             pszAuthName, pszAuthCode );
                 }
             }
diff --git a/ogr/ogrsf_frmts/gml/gmlutils.h b/ogr/ogrsf_frmts/gml/gmlutils.h
index d8466d6..e799483 100644
--- a/ogr/ogrsf_frmts/gml/gmlutils.h
+++ b/ogr/ogrsf_frmts/gml/gmlutils.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmlutils.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: gmlutils.h 33702 2016-03-11 06:20:16Z goatbar $
  *
  * Project:  GML Utils
  * Purpose:  GML reader
@@ -14,21 +14,21 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _CPL_GMLUTILS_H_INCLUDED
-#define _CPL_GMLUTILS_H_INCLUDED
+#ifndef CPL_GMLUTILS_H_INCLUDED
+#define CPL_GMLUTILS_H_INCLUDED
 
 #include <vector>
 #include <string>
@@ -38,22 +38,22 @@
 
 const char* GML_ExtractSrsNameFromGeometry(const CPLXMLNode* const * papsGeometry,
                                      std::string& osWork,
-                                     int bConsiderEPSGAsURN);
+                                     bool bConsiderEPSGAsURN);
 
-int GML_IsSRSLatLongOrder(const char* pszSRSName);
+bool GML_IsSRSLatLongOrder(const char* pszSRSName);
 
 void* GML_BuildOGRGeometryFromList_CreateCache();
 void GML_BuildOGRGeometryFromList_DestroyCache(void* hCacheSRS);
 
 OGRGeometry* GML_BuildOGRGeometryFromList(const CPLXMLNode* const * papsGeometry,
-                                          int bTryToMakeMultipolygons,
-                                          int bInvertAxisOrderIfLatLong,
+                                          bool bTryToMakeMultipolygons,
+                                          bool bInvertAxisOrderIfLatLong,
                                           const char* pszDefaultSRSName,
-                                          int bConsiderEPSGAsURN,
-                                          int bGetSecondaryGeometryOption,
+                                          bool bConsiderEPSGAsURN,
+                                          int nPseudoBoolGetSecondaryGeometryOption,
                                           void* hCacheSRS,
-                                          int bFaceHoleNegative = FALSE );
+                                          bool bFaceHoleNegative = false );
 
-char* GML_GetSRSName(const OGRSpatialReference* poSRS, int bLongSRS, int *pbCoordSwap);
+char* GML_GetSRSName(const OGRSpatialReference* poSRS, bool bLongSRS, bool *pbCoordSwap);
 
 #endif /* _CPL_GMLREADERP_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/gml/hugefileresolver.cpp b/ogr/ogrsf_frmts/gml/hugefileresolver.cpp
index 2c3c50b..568c575 100644
--- a/ogr/ogrsf_frmts/gml/hugefileresolver.cpp
+++ b/ogr/ogrsf_frmts/gml/hugefileresolver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hugefileresolver.cpp 27766 2014-09-28 20:13:12Z goatbar $
+ * $Id: hugefileresolver.cpp 33702 2016-03-11 06:20:16Z goatbar $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLReader::HugeFileResolver() method.
@@ -15,22 +15,22 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *
  ******************************************************************************
  * Contributor: Alessandro Furieri, a.furieri at lqt.it
- * This module implents GML_SKIP_RESOLVE_ELEMS HUGE
- * Developed for Faunalia ( http://www.faunalia.it) with funding from 
+ * This module implements GML_SKIP_RESOLVE_ELEMS HUGE
+ * Developed for Faunalia ( http://www.faunalia.it) with funding from
  * Regione Toscana - Settore SISTEMA INFORMATIVO TERRITORIALE ED AMBIENTALE
  *
  ****************************************************************************/
@@ -47,7 +47,7 @@
 
 #include <stack>
 
-CPL_CVSID("$Id: hugefileresolver.cpp 27766 2014-09-28 20:13:12Z goatbar $");
+CPL_CVSID("$Id: hugefileresolver.cpp 33702 2016-03-11 06:20:16Z goatbar $");
 
 /****************************************************/
 /*      SQLite is absolutely required in order to   */
@@ -69,10 +69,10 @@ struct huge_tag
     CPLString           *gmlId;
     CPLString           *gmlNodeFrom;
     CPLString           *gmlNodeTo;
-    int	                bIsNodeFromHref;
-    int                 bIsNodeToHref;
-    int                 bHasCoords;
-    int                 bHasZ;
+    bool                bIsNodeFromHref;
+    bool                bIsNodeToHref;
+    bool                bHasCoords;
+    bool                bHasZ;
     double              xNodeFrom;
     double              yNodeFrom;
     double              zNodeFrom;
@@ -89,12 +89,12 @@ struct huge_href
     CPLString           *gmlText;
     const CPLXMLNode    *psParent;
     const CPLXMLNode    *psNode;
-    int                 bIsDirectedEdge;
+    bool                bIsDirectedEdge;
     char                cOrientation;
     struct huge_href    *pNext;
 };
 
-/* an internal helper struct supporying GML rewriting */
+/* an internal helper struct supporting GML rewriting */
 struct huge_child
 {
     CPLXMLNode          *psChild;
@@ -112,7 +112,7 @@ struct huge_parent
 };
 
 /*
-/ an internal helper struct supporting GML 
+/ an internal helper struct supporting GML
 / resolver for Huge Files (based on SQLite)
 */
 struct huge_helper
@@ -129,7 +129,7 @@ struct huge_helper
     struct huge_parent  *pLastParent;
 };
 
-static int gmlHugeFileSQLiteInit( struct huge_helper *helper )
+static bool gmlHugeFileSQLiteInit( struct huge_helper *helper )
 {
 /* attempting to create SQLite tables */
     const char          *osCommand;
@@ -147,11 +147,11 @@ static int gmlHugeFileSQLiteInit( struct huge_helper *helper )
     rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to create table nodes: %s",
                   pszErrMsg );
         sqlite3_free( pszErrMsg );
-        return FALSE;
+        return false;
     }
 
     /* DB table: GML_EDGES */
@@ -170,11 +170,11 @@ static int gmlHugeFileSQLiteInit( struct huge_helper *helper )
     rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to create table gml_edges: %s",
                   pszErrMsg );
         sqlite3_free( pszErrMsg );
-        return FALSE;
+        return false;
     }
 
     /* DB table: NODES / Insert cursor */
@@ -183,9 +183,9 @@ static int gmlHugeFileSQLiteInit( struct huge_helper *helper )
     rc = sqlite3_prepare_v2( hDB, osCommand, -1, &hStmt, NULL );
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to create INSERT stmt for: nodes" );
-        return FALSE;
+        return false;
     }
     helper->hNodes = hStmt;
 
@@ -199,9 +199,9 @@ static int gmlHugeFileSQLiteInit( struct huge_helper *helper )
     rc = sqlite3_prepare_v2( hDB, osCommand, -1, &hStmt, NULL );
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to create INSERT stmt for: gml_edges" );
-        return FALSE;
+        return false;
     }
     helper->hEdges = hStmt;
 
@@ -209,17 +209,17 @@ static int gmlHugeFileSQLiteInit( struct huge_helper *helper )
     rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, &pszErrMsg );
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to perform BEGIN TRANSACTION: %s",
                   pszErrMsg );
         sqlite3_free( pszErrMsg );
-        return FALSE;
-    }	
+        return false;
+    }
 
-    return TRUE;
+    return true;
 }
 
-static int gmlHugeResolveEdgeNodes( const CPLXMLNode *psNode,
+static bool gmlHugeResolveEdgeNodes( const CPLXMLNode *psNode,
                                     const char *pszFromId,
                                     const char *pszToId )
 {
@@ -235,7 +235,7 @@ static int gmlHugeResolveEdgeNodes( const CPLXMLNode *psNode,
     if( psNode->eType == CXT_Element && EQUAL( psNode->pszValue, "Edge" ) )
         ;
     else
-        return FALSE;
+        return false;
 
     CPLXMLNode *psChild = psNode->psChild;
     while( psChild != NULL )
@@ -317,11 +317,11 @@ static int gmlHugeResolveEdgeNodes( const CPLXMLNode *psNode,
         }
     }
     if( iToBeReplaced != iReplaced )
-        return FALSE;
-return TRUE;
+        return false;
+    return true;
 }
 
-static int gmlHugeFileResolveEdges( struct huge_helper *helper )
+static bool gmlHugeFileResolveEdges( struct huge_helper *helper )
 {
 /* identifying any not yet resolved <Edge> GML string */
     const char          *osCommand;
@@ -331,7 +331,7 @@ static int gmlHugeFileResolveEdges( struct huge_helper *helper )
     sqlite3_stmt        *hQueryStmt;
     sqlite3_stmt        *hUpdateStmt;
     int                 iCount = 0;
-    int                 bError = FALSE;
+    bool                bError = false;
 
     /* query cursor */
     osCommand = "SELECT e.gml_id, e.gml_string, e.node_from_id, "
@@ -345,9 +345,9 @@ static int gmlHugeFileResolveEdges( struct huge_helper *helper )
     rc = sqlite3_prepare_v2( hDB, osCommand, -1, &hQueryStmt, NULL );
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to create QUERY stmt for Edge resolver" );
-        return FALSE;
+        return false;
     }
 
     /* update cursor */
@@ -358,27 +358,27 @@ static int gmlHugeFileResolveEdges( struct huge_helper *helper )
     rc = sqlite3_prepare_v2( hDB, osCommand, -1, &hUpdateStmt, NULL );
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to create UPDATE stmt for resolved Edges" );
         sqlite3_finalize ( hQueryStmt );
-        return FALSE;
+        return false;
     }
 
     /* starting a TRANSACTION */
     rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, &pszErrMsg );
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to perform BEGIN TRANSACTION: %s",
                   pszErrMsg );
         sqlite3_free( pszErrMsg );
         sqlite3_finalize ( hQueryStmt );
         sqlite3_finalize ( hUpdateStmt );
-        return FALSE;
+        return false;
     }
 
     /* looping on the QUERY result-set */
-    while ( TRUE )
+    while( true )
     {
         const char      *pszGmlId;
         const char      *pszGmlString = NULL;
@@ -400,277 +400,276 @@ static int gmlHugeFileResolveEdges( struct huge_helper *helper )
         double          zNodeFrom = 0.0;
         int             bIsZNodeFromNull;
         const char      *pszToId = NULL;
-        int             bIsToIdNull;
+        bool            bIsToIdNull;
         double          xTo = 0.0;
-        int             bIsXToNull;
+        bool            bIsXToNull;
         double          yTo = 0.0;
-        int             bIsYToNull;
+        bool            bIsYToNull;
         double          zTo = 0.0;
-        int             bIsZToNull;
+        bool            bIsZToNull;
         /* const char      *pszNodeToId = NULL; */
-        int             bIsNodeToIdNull;
+        bool            bIsNodeToIdNull;
         double          xNodeTo = 0.0;
-        int             bIsXNodeToNull;
+        bool            bIsXNodeToNull;
         double          yNodeTo = 0.0;
-        int             bIsYNodeToNull;
+        bool            bIsYNodeToNull;
         double          zNodeTo = 0.0;
-        int             bIsZNodeToNull;
+        bool            bIsZNodeToNull;
 
         rc = sqlite3_step( hQueryStmt );
         if( rc == SQLITE_DONE )
             break;
         else if( rc == SQLITE_ROW )
         {
-            bError = FALSE;
+            bError = false;
             pszGmlId = (const char *) sqlite3_column_text( hQueryStmt, 0 );
             if( sqlite3_column_type( hQueryStmt, 1 ) == SQLITE_NULL )
-                bIsGmlStringNull = TRUE;
+                bIsGmlStringNull = true;
             else
             {
                 pszGmlString = (const char *) sqlite3_column_blob( hQueryStmt, 1 );
-                bIsGmlStringNull = FALSE;
+                bIsGmlStringNull = false;
             }
             if( sqlite3_column_type( hQueryStmt, 2 ) == SQLITE_NULL )
-                bIsFromIdNull = TRUE;
+                bIsFromIdNull = true;
             else
             {
                 pszFromId = (const char *) sqlite3_column_text( hQueryStmt, 2 );
-                bIsFromIdNull = FALSE;
+                bIsFromIdNull = false;
             }
             if( sqlite3_column_type( hQueryStmt, 3 ) == SQLITE_NULL )
-                bIsXFromNull = TRUE;
+                bIsXFromNull = true;
             else
             {
                 xFrom = sqlite3_column_double( hQueryStmt, 3 );
-                bIsXFromNull = FALSE;
+                bIsXFromNull = false;
             }
             if( sqlite3_column_type( hQueryStmt, 4 ) == SQLITE_NULL )
-                bIsYFromNull = TRUE;
+                bIsYFromNull = true;
             else
             {
                 yFrom = sqlite3_column_double( hQueryStmt, 4 );
-                bIsYFromNull = FALSE;
+                bIsYFromNull = false;
             }
             if( sqlite3_column_type( hQueryStmt, 5 ) == SQLITE_NULL )
-                bIsZFromNull = TRUE;
+                bIsZFromNull = true;
             else
             {
                 zFrom = sqlite3_column_double( hQueryStmt, 5 );
-                bIsZFromNull = FALSE;
+                bIsZFromNull = false;
             }
             if( sqlite3_column_type( hQueryStmt, 6 ) == SQLITE_NULL )
-                bIsNodeFromIdNull = TRUE;
+                bIsNodeFromIdNull = true;
             else
             {
                 /* TODO: Can sqlite3_column_text be removed? */
                 /* pszNodeFromId = (const char *) */ sqlite3_column_text( hQueryStmt, 6 );
-                bIsNodeFromIdNull = FALSE;
+                bIsNodeFromIdNull = false;
             }
             if( sqlite3_column_type( hQueryStmt, 7 ) == SQLITE_NULL )
-                bIsXNodeFromNull = TRUE;
+                bIsXNodeFromNull = true;
             else
             {
                 xNodeFrom = sqlite3_column_double( hQueryStmt, 7 );
-                bIsXNodeFromNull = FALSE;
+                bIsXNodeFromNull = false;
             }
             if( sqlite3_column_type( hQueryStmt, 8 ) == SQLITE_NULL )
-                bIsYNodeFromNull = TRUE;
+                bIsYNodeFromNull = true;
             else
             {
                 yNodeFrom = sqlite3_column_double( hQueryStmt, 8 );
-                bIsYNodeFromNull = FALSE;
+                bIsYNodeFromNull = false;
             }
             if( sqlite3_column_type( hQueryStmt, 9 ) == SQLITE_NULL )
-                bIsZNodeFromNull = TRUE;
+                bIsZNodeFromNull = true;
             else
             {
                 zNodeFrom = sqlite3_column_double( hQueryStmt, 9 );
-                bIsZNodeFromNull = FALSE;
+                bIsZNodeFromNull = false;
             }
             if( sqlite3_column_type( hQueryStmt, 10 ) == SQLITE_NULL )
-                bIsToIdNull = TRUE;
+                bIsToIdNull = true;
             else
             {
                 pszToId = (const char *) sqlite3_column_text( hQueryStmt, 10 );
-                bIsToIdNull = FALSE;
+                bIsToIdNull = false;
             }
             if( sqlite3_column_type( hQueryStmt, 11 ) == SQLITE_NULL )
-                bIsXToNull = TRUE;
+                bIsXToNull = true;
             else
             {
                 xTo = sqlite3_column_double( hQueryStmt, 11 );
-                bIsXToNull = FALSE;
+                bIsXToNull = false;
             }
             if( sqlite3_column_type( hQueryStmt, 12 ) == SQLITE_NULL )
-                bIsYToNull = TRUE;
+                bIsYToNull = true;
             else
             {
                 yTo = sqlite3_column_double( hQueryStmt, 12 );
-                bIsYToNull = FALSE;
+                bIsYToNull = false;
             }
             if( sqlite3_column_type( hQueryStmt, 13 ) == SQLITE_NULL )
-                bIsZToNull = TRUE;
+                bIsZToNull = true;
             else
             {
                 zTo = sqlite3_column_double( hQueryStmt, 13 );
-                bIsZToNull = FALSE;
+                bIsZToNull = false;
             }
             if( sqlite3_column_type( hQueryStmt, 14 ) == SQLITE_NULL )
-                bIsNodeToIdNull = TRUE;
+                bIsNodeToIdNull = true;
             else
             {
                 /* TODO: Can sqlite3_column_text be removed? */
                 /* pszNodeToId = (const char *) */ sqlite3_column_text( hQueryStmt, 14 );
-                bIsNodeToIdNull = FALSE;
+                bIsNodeToIdNull = false;
             }
             if( sqlite3_column_type( hQueryStmt, 15 ) == SQLITE_NULL )
-                bIsXNodeToNull = TRUE;
+                bIsXNodeToNull = true;
             else
             {
                 xNodeTo = sqlite3_column_double( hQueryStmt, 15 );
-                bIsXNodeToNull = FALSE;
+                bIsXNodeToNull = false;
             }
             if( sqlite3_column_type( hQueryStmt, 16 ) == SQLITE_NULL )
-                bIsYNodeToNull = TRUE;
+                bIsYNodeToNull = true;
             else
             {
                 yNodeTo = sqlite3_column_double( hQueryStmt, 16 );
-                bIsYNodeToNull = FALSE;
+                bIsYNodeToNull = false;
             }
             if( sqlite3_column_type( hQueryStmt, 17 ) == SQLITE_NULL )
-                bIsZNodeToNull = TRUE;
+                bIsZNodeToNull = true;
             else
             {
                 zNodeTo = sqlite3_column_double( hQueryStmt, 17 );
-                bIsZNodeToNull = FALSE;
+                bIsZNodeToNull = false;
             }
 
             /* checking for consistency */
-            if( bIsFromIdNull == TRUE || bIsXFromNull == TRUE ||
-                bIsYFromNull == TRUE )
+            if( bIsFromIdNull || bIsXFromNull  || bIsYFromNull  )
             {
-                bError = TRUE;
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                          "Edge gml:id=\"%s\": invalid Node-from", 
+                bError = true;
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Edge gml:id=\"%s\": invalid Node-from",
                           pszGmlId );
             }
             else
             {
-                if( bIsNodeFromIdNull == TRUE )
+                if( bIsNodeFromIdNull )
                 {
-                    bError = TRUE;
-                    CPLError( CE_Failure, CPLE_AppDefined, 
-                              "Edge gml:id=\"%s\": undeclared Node gml:id=\"%s\"", 
+                    bError = true;
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                              "Edge gml:id=\"%s\": undeclared Node gml:id=\"%s\"",
                               pszGmlId, pszFromId );
                 }
-                else if( bIsXNodeFromNull == TRUE || bIsYNodeFromNull == TRUE )
+                else if( bIsXNodeFromNull || bIsYNodeFromNull )
                 {
-                    bError = TRUE;
-                    CPLError( CE_Failure, CPLE_AppDefined, 
-                              "Edge gml:id=\"%s\": unknown coords for Node gml:id=\"%s\"", 
+                    bError = true;
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                              "Edge gml:id=\"%s\": unknown coords for Node gml:id=\"%s\"",
                               pszGmlId, pszFromId );
                 }
                 else if( xFrom != xNodeFrom || yFrom != yNodeFrom )
                 {
-                    bError = TRUE;
-                    CPLError( CE_Failure, CPLE_AppDefined, 
-                              "Edge gml:id=\"%s\": mismatching coords for Node gml:id=\"%s\"", 
+                    bError = true;
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                              "Edge gml:id=\"%s\": mismatching coords for Node gml:id=\"%s\"",
                               pszGmlId, pszFromId );
                 }
                 else
                 {
-                    if( bIsZFromNull == TRUE && bIsZNodeFromNull == TRUE )
+                    if( bIsZFromNull && bIsZNodeFromNull )
 ;
-                    else if(  bIsZFromNull == TRUE || bIsZNodeFromNull == TRUE )
+                    else if( bIsZFromNull || bIsZNodeFromNull  )
                     {
-                        bError = TRUE;
-                        CPLError( CE_Failure, CPLE_AppDefined, 
-                                  "Edge gml:id=\"%s\": mismatching 2D/3D for Node gml:id=\"%s\"", 
+                        bError = true;
+                        CPLError( CE_Failure, CPLE_AppDefined,
+                                  "Edge gml:id=\"%s\": mismatching 2D/3D for Node gml:id=\"%s\"",
                                   pszGmlId, pszFromId );
                     }
-                    else if( zFrom != zNodeFrom ) 
+                    else if( zFrom != zNodeFrom )
                     {
-                        bError = TRUE;
-                        CPLError( CE_Failure, CPLE_AppDefined, 
-                                  "Edge gml:id=\"%s\": mismatching Z coord for Node gml:id=\"%s\"", 
+                        bError = true;
+                        CPLError( CE_Failure, CPLE_AppDefined,
+                                  "Edge gml:id=\"%s\": mismatching Z coord for Node gml:id=\"%s\"",
                                   pszGmlId, pszFromId );
                     }
                 }
             }
-            if( bIsToIdNull == TRUE || bIsXToNull == TRUE ||
-                bIsYToNull == TRUE )
+            if( bIsToIdNull || bIsXToNull || bIsYToNull )
             {
-                bError = TRUE;
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                          "Edge gml:id=\"%s\": invalid Node-to", 
+                bError = true;
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Edge gml:id=\"%s\": invalid Node-to",
                           pszGmlId );
             }
             else
             {
-                if( bIsNodeToIdNull == TRUE )
+                if( bIsNodeToIdNull )
                 {
-                    bError = TRUE;
-                    CPLError( CE_Failure, CPLE_AppDefined, 
-                              "Edge gml:id=\"%s\": undeclared Node gml:id=\"%s\"", 
+                    bError = true;
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                              "Edge gml:id=\"%s\": undeclared Node gml:id=\"%s\"",
                               pszGmlId, pszToId );
                 }
-                else if( bIsXNodeToNull == TRUE || bIsYNodeToNull == TRUE )
+                else if( bIsXNodeToNull  || bIsYNodeToNull )
                 {
-                    bError = TRUE;
-                    CPLError( CE_Failure, CPLE_AppDefined, 
-                              "Edge gml:id=\"%s\": unknown coords for Node gml:id=\"%s\"", 
+                    bError = true;
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                              "Edge gml:id=\"%s\": unknown coords for Node gml:id=\"%s\"",
                               pszGmlId, pszToId );
                 }
                 else if( xTo != xNodeTo || yTo != yNodeTo )
                 {
-                    bError = TRUE;
-                    CPLError( CE_Failure, CPLE_AppDefined, 
-                              "Edge gml:id=\"%s\": mismatching coords for Node gml:id=\"%s\"", 
+                    bError = true;
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                              "Edge gml:id=\"%s\": mismatching coords for Node gml:id=\"%s\"",
                               pszGmlId, pszToId );
                 }
                 else
                 {
-                    if( bIsZToNull == TRUE && bIsZNodeToNull == TRUE )
+                    if( bIsZToNull && bIsZNodeToNull )
 ;
-                    else if(  bIsZToNull == TRUE || bIsZNodeToNull == TRUE )
+                    else if(  bIsZToNull || bIsZNodeToNull )
                     {
-                        bError = TRUE;
-                        CPLError( CE_Failure, CPLE_AppDefined, 
-                                  "Edge gml:id=\"%s\": mismatching 2D/3D for Node gml:id=\"%s\"", 
+                        bError = true;
+                        CPLError( CE_Failure, CPLE_AppDefined,
+                                  "Edge gml:id=\"%s\": mismatching 2D/3D for Node gml:id=\"%s\"",
                                   pszGmlId, pszToId );
                     }
-                    else if( zTo != zNodeTo ) 
+                    else if( zTo != zNodeTo )
                     {
-                        bError = TRUE;
-                        CPLError( CE_Failure, CPLE_AppDefined, 
-                                  "Edge gml:id=\"%s\": mismatching Z coord for Node gml:id=\"%s\"", 
+                        bError = true;
+                        CPLError( CE_Failure, CPLE_AppDefined,
+                                  "Edge gml:id=\"%s\": mismatching Z coord for Node gml:id=\"%s\"",
                                   pszGmlId, pszToId );
                     }
                 }
             }
 
             /* updating the resolved Node */
-            if( bError == FALSE && bIsGmlStringNull == FALSE &&
-                bIsFromIdNull == FALSE && bIsToIdNull == FALSE )
+            if( bError == false && bIsGmlStringNull == false &&
+                bIsFromIdNull == false && bIsToIdNull == false )
             {
                 CPLXMLNode *psNode = CPLParseXMLString( pszGmlString );
                 if( psNode != NULL )
                 {
                     if( gmlHugeResolveEdgeNodes( psNode, pszFromId,
-                                                 pszToId ) == TRUE )
+                                                 pszToId ) )
                     {
                         char * gmlText = CPLSerializeXMLTree(psNode);
                         sqlite3_reset ( hUpdateStmt );
                         sqlite3_clear_bindings ( hUpdateStmt );
                         sqlite3_bind_blob( hUpdateStmt, 1, gmlText,
-                                           strlen(gmlText), SQLITE_STATIC );
+                                           (int)strlen(gmlText), SQLITE_STATIC );
                         sqlite3_bind_text( hUpdateStmt, 2, pszGmlId, -1,
                                            SQLITE_STATIC );
                         rc = sqlite3_step( hUpdateStmt );
                         if( rc != SQLITE_OK && rc != SQLITE_DONE )
                         {
                             CPLError( CE_Failure, CPLE_AppDefined,
-                                      "UPDATE resoved Edge \"%s\" sqlite3_step() failed:\n  %s",
+                                      "UPDATE resolved Edge \"%s\" "
+                                      "sqlite3_step() failed:\n  %s",
                                       pszGmlId, sqlite3_errmsg(hDB) );
                         }
                         CPLFree( gmlText );
@@ -682,23 +681,23 @@ static int gmlHugeFileResolveEdges( struct huge_helper *helper )
                                                &pszErrMsg );
                             if( rc != SQLITE_OK )
                             {
-                                CPLError( CE_Failure, CPLE_AppDefined, 
+                                CPLError( CE_Failure, CPLE_AppDefined,
                                           "Unable to perform COMMIT TRANSACTION: %s",
                                           pszErrMsg );
                                 sqlite3_free( pszErrMsg );
-                                return FALSE;
+                                return false;
                             }
                             /* restarting a new TRANSACTION */
                             rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, &pszErrMsg );
                             if( rc != SQLITE_OK )
                             {
-                                CPLError( CE_Failure, CPLE_AppDefined, 
+                                CPLError( CE_Failure, CPLE_AppDefined,
                                           "Unable to perform BEGIN TRANSACTION: %s",
                                           pszErrMsg );
                                 sqlite3_free( pszErrMsg );
                                 sqlite3_finalize ( hQueryStmt );
                                 sqlite3_finalize ( hUpdateStmt );
-                                return FALSE;
+                                return false;
                             }
                         }
                     }
@@ -708,12 +707,12 @@ static int gmlHugeFileResolveEdges( struct huge_helper *helper )
         }
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Edge resolver QUERY: sqlite3_step(%s)", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Edge resolver QUERY: sqlite3_step(%s)",
                       sqlite3_errmsg(hDB) );
             sqlite3_finalize ( hQueryStmt );
             sqlite3_finalize ( hUpdateStmt );
-            return FALSE;
+            return false;
         }
     }
     sqlite3_finalize ( hQueryStmt );
@@ -723,15 +722,15 @@ static int gmlHugeFileResolveEdges( struct huge_helper *helper )
     rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL, &pszErrMsg );
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to perform COMMIT TRANSACTION: %s",
                   pszErrMsg );
         sqlite3_free( pszErrMsg );
-        return FALSE;
+        return false;
     }
-    if( bError == TRUE )
-        return FALSE;
-    return TRUE;
+    if( bError )
+        return false;
+    return true;
 }
 
 static int gmlHugeFileSQLiteInsert( struct huge_helper *helper )
@@ -744,7 +743,7 @@ static int gmlHugeFileSQLiteInsert( struct huge_helper *helper )
     pItem = helper->pFirst;
     while ( pItem != NULL )
     {
-        if( pItem->bHasCoords == TRUE )
+        if( pItem->bHasCoords )
         {
             if( pItem->gmlNodeFrom != NULL )
             {
@@ -755,16 +754,16 @@ static int gmlHugeFileSQLiteInsert( struct huge_helper *helper )
                                    SQLITE_STATIC );
                 sqlite3_bind_double ( helper->hNodes, 2, pItem->xNodeFrom );
                 sqlite3_bind_double ( helper->hNodes, 3, pItem->yNodeFrom );
-                if( pItem->bHasZ == TRUE )
+                if( pItem->bHasZ )
                     sqlite3_bind_double ( helper->hNodes, 4, pItem->zNodeFrom );
                 sqlite3_bind_null ( helper->hNodes, 5 );
                 rc = sqlite3_step( helper->hNodes );
                 if( rc != SQLITE_OK && rc != SQLITE_DONE )
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined, 
-                              "sqlite3_step() failed:\n  %s (gmlNodeFrom id=%s)", 
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                              "sqlite3_step() failed:\n  %s (gmlNodeFrom id=%s)",
                               sqlite3_errmsg(helper->hDB), pItem->gmlNodeFrom->c_str() );
-                    return FALSE;
+                    return false;
                 }
             }
             if( pItem->gmlNodeTo != NULL )
@@ -775,16 +774,16 @@ static int gmlHugeFileSQLiteInsert( struct huge_helper *helper )
                                    -1, SQLITE_STATIC );
                 sqlite3_bind_double ( helper->hNodes, 2, pItem->xNodeTo );
                 sqlite3_bind_double ( helper->hNodes, 3, pItem->yNodeTo );
-                if ( pItem->bHasZ == TRUE )
+                if ( pItem->bHasZ )
                     sqlite3_bind_double ( helper->hNodes, 4, pItem->zNodeTo );
                 sqlite3_bind_null ( helper->hNodes, 5 );
                 rc = sqlite3_step( helper->hNodes );
                 if( rc != SQLITE_OK && rc != SQLITE_DONE )
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined, 
-                              "sqlite3_step() failed:\n  %s (gmlNodeTo id=%s)", 
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                              "sqlite3_step() failed:\n  %s (gmlNodeTo id=%s)",
                               sqlite3_errmsg(helper->hDB), pItem->gmlNodeTo->c_str() );
-                    return FALSE;
+                    return false;
                 }
             }
         }
@@ -794,17 +793,17 @@ static int gmlHugeFileSQLiteInsert( struct huge_helper *helper )
         sqlite3_clear_bindings( helper->hEdges );
         sqlite3_bind_text( helper->hEdges, 1, pItem->gmlId->c_str(), -1,
                            SQLITE_STATIC );
-        if( pItem->bIsNodeFromHref == FALSE && pItem->bIsNodeToHref == FALSE )
+        if( pItem->bIsNodeFromHref == false && pItem->bIsNodeToHref == false )
         {
             sqlite3_bind_null( helper->hEdges, 2 );
             sqlite3_bind_blob( helper->hEdges, 3, pItem->gmlTagValue->c_str(),
-                               strlen( pItem->gmlTagValue->c_str() ),
+                               (int)strlen( pItem->gmlTagValue->c_str() ),
                                SQLITE_STATIC );
         }
         else
         {
             sqlite3_bind_blob( helper->hEdges, 2, pItem->gmlTagValue->c_str(),
-                               strlen( pItem->gmlTagValue->c_str() ),
+                               (int)strlen( pItem->gmlTagValue->c_str() ),
                                SQLITE_STATIC );
             sqlite3_bind_null( helper->hEdges, 3 );
         }
@@ -813,11 +812,11 @@ static int gmlHugeFileSQLiteInsert( struct huge_helper *helper )
                                -1, SQLITE_STATIC );
         else
             sqlite3_bind_null( helper->hEdges, 4 );
-        if( pItem->bHasCoords == TRUE )
+        if( pItem->bHasCoords )
         {
             sqlite3_bind_double( helper->hEdges, 5, pItem->xNodeFrom );
             sqlite3_bind_double( helper->hEdges, 6, pItem->yNodeFrom );
-            if( pItem->bHasZ == TRUE )
+            if( pItem->bHasZ )
                 sqlite3_bind_double( helper->hEdges, 7, pItem->zNodeFrom );
             else
                 sqlite3_bind_null( helper->hEdges, 7 );
@@ -833,11 +832,11 @@ static int gmlHugeFileSQLiteInsert( struct huge_helper *helper )
                                -1, SQLITE_STATIC );
         else
             sqlite3_bind_null( helper->hEdges, 8 );
-        if( pItem->bHasCoords == TRUE )
+        if( pItem->bHasCoords )
         {
             sqlite3_bind_double( helper->hEdges, 9, pItem->xNodeTo );
             sqlite3_bind_double( helper->hEdges, 10, pItem->yNodeTo );
-            if( pItem->bHasZ == TRUE )
+            if( pItem->bHasZ )
                 sqlite3_bind_double( helper->hEdges, 11, pItem->zNodeTo );
             else
                 sqlite3_bind_null( helper->hEdges, 11 );
@@ -851,14 +850,14 @@ static int gmlHugeFileSQLiteInsert( struct huge_helper *helper )
         rc = sqlite3_step( helper->hEdges );
         if( rc != SQLITE_OK && rc != SQLITE_DONE )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "sqlite3_step() failed:\n  %s (edge gml:id=%s)", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "sqlite3_step() failed:\n  %s (edge gml:id=%s)",
                       sqlite3_errmsg(helper->hDB), pItem->gmlId->c_str() );
-            return FALSE;
+            return false;
         }
         pItem = pItem->pNext;
     }
-    return TRUE;
+    return true;
 }
 
 static void gmlHugeFileReset( struct huge_helper *helper )
@@ -910,22 +909,22 @@ static void gmlHugeFileHrefReset( struct huge_helper *helper )
 static int gmlHugeFileHrefCheck( struct huge_helper *helper )
 {
 /* testing for unresolved items */
-    int bError = FALSE;
+    int bError = false;
 	struct huge_href *p = helper->pFirstHref;
 	while( p != NULL )
     {
 		if( p->gmlText == NULL)
 		{
-			bError = TRUE;
-			CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Edge xlink:href\"%s\": unresolved match", 
+			bError = true;
+			CPLError( CE_Failure, CPLE_AppDefined,
+                      "Edge xlink:href\"%s\": unresolved match",
                       p->gmlId->c_str() );
 		}
         p = p->pNext;
     }
-	if( bError == TRUE )
-		return FALSE;
-	return TRUE;
+	if( bError )
+		return false;
+	return true;
 }
 
 static void gmlHugeFileRewiterReset( struct huge_helper *helper )
@@ -967,17 +966,17 @@ static struct huge_tag *gmlHugeAddToHelper( struct huge_helper *helper,
         if( EQUAL( pItem->gmlId->c_str(), gmlId->c_str() ) )
             return NULL;
         pItem = pItem->pNext;
-    }	
+    }
 
     pItem = new struct huge_tag;
     pItem->gmlId = gmlId;
     pItem->gmlTagValue = gmlFragment;
     pItem->gmlNodeFrom = NULL;
     pItem->gmlNodeTo = NULL;
-    pItem->bIsNodeFromHref = FALSE;
-    pItem->bIsNodeToHref = FALSE;
-    pItem->bHasCoords = FALSE;
-    pItem->bHasZ = FALSE;
+    pItem->bIsNodeFromHref = false;
+    pItem->bIsNodeToHref = false;
+    pItem->bHasCoords = false;
+    pItem->bHasZ = false;
     pItem->pNext = NULL;
 
     /* appending the item to the linked list */
@@ -993,7 +992,7 @@ static void gmlHugeAddPendingToHelper( struct huge_helper *helper,
                                        CPLString *gmlId,
                                        const CPLXMLNode *psParent,
                                        const CPLXMLNode *psNode,
-                                       int bIsDirectedEdge,
+                                       bool bIsDirectedEdge,
                                        char cOrientation )
 {
 /* inserting an item into the linked list */
@@ -1004,8 +1003,8 @@ static void gmlHugeAddPendingToHelper( struct huge_helper *helper,
     while( pItem != NULL )
     {
         if( EQUAL( pItem->gmlId->c_str(), gmlId->c_str() ) &&
-            pItem->psParent == psParent  && 
-            pItem->psNode == psNode && 
+            pItem->psParent == psParent  &&
+            pItem->psNode == psNode &&
             pItem->cOrientation == cOrientation &&
             pItem->bIsDirectedEdge == bIsDirectedEdge )
             {
@@ -1013,7 +1012,7 @@ static void gmlHugeAddPendingToHelper( struct huge_helper *helper,
                 return;
             }
             pItem = pItem->pNext;
-    }	
+    }
 
     pItem = new struct huge_href;
     pItem->gmlId = gmlId;
@@ -1048,20 +1047,20 @@ static int gmlHugeFindGmlId( const CPLXMLNode *psNode, CPLString **gmlId )
                 if( psIdValue->eType == CXT_Text )
                 {
                     *gmlId = new CPLString(psIdValue->pszValue);
-                    return TRUE;
+                    return true;
                 }
             }
         }
         psChild = psChild->psNext;
     }
-    return FALSE;
+    return false;
 }
 
 static void gmlHugeFileNodeCoords( struct huge_tag *pItem,
                                    const CPLXMLNode * psNode,
                                    CPL_UNUSED CPLString **nodeSrs )
 {
-/* 
+/*
 / this function attempts to set coordinates for <Node> items
 / when required (an <Edge> is expected to be processed)
 */
@@ -1087,7 +1086,7 @@ static void gmlHugeFileNodeCoords( struct huge_tag *pItem,
                 int iPoints =  poLine->getNumPoints();
                 if( iPoints >= 2 )
                 {
-                    pItem->bHasCoords = TRUE;
+                    pItem->bHasCoords = true;
                     pItem->xNodeFrom = poLine->getX( 0 );
                     pItem->yNodeFrom = poLine->getY( 0 );
                     pItem->xNodeTo = poLine->getX( iPoints - 1 );
@@ -1096,16 +1095,16 @@ static void gmlHugeFileNodeCoords( struct huge_tag *pItem,
                     {
                         pItem->zNodeFrom = poLine->getZ( 0 );
                         pItem->zNodeTo = poLine->getZ( iPoints - 1 );
-                        pItem->bHasZ = TRUE;
+                        pItem->bHasZ = true;
                     }
                     else
-                        pItem->bHasZ = FALSE;
+                        pItem->bHasZ = false;
                 }
             }
         }
         delete poColl;
     }
-	
+
     /* searching the <directedNode> sub-tags */
     const CPLXMLNode *psChild = psNode->psChild;
     while( psChild != NULL )
@@ -1115,7 +1114,7 @@ static void gmlHugeFileNodeCoords( struct huge_tag *pItem,
         {
             char cOrientation = '+';
             const char *pszGmlId = NULL;
-            int bIsHref = FALSE;
+            bool bIsHref = false;
             const CPLXMLNode *psAttr = psChild->psChild;
             while( psAttr != NULL )
             {
@@ -1128,7 +1127,7 @@ static void gmlHugeFileNodeCoords( struct huge_tag *pItem,
                         if( psHref->eType == CXT_Text )
                         {
                             pszGmlId = psHref->pszValue;
-                            bIsHref = TRUE;
+                            bIsHref = true;
                         }
                     }
                 }
@@ -1149,7 +1148,7 @@ static void gmlHugeFileNodeCoords( struct huge_tag *pItem,
                 {
                     const CPLXMLNode *psId = psAttr->psChild;
                     while( psId != NULL )
-                    {		
+                    {
                         if( psId->eType == CXT_Attribute &&
                             EQUAL( psId->pszValue, "gml:id" ) )
                         {
@@ -1159,7 +1158,7 @@ static void gmlHugeFileNodeCoords( struct huge_tag *pItem,
                                 if( psIdGml->eType == CXT_Text )
                                 {
                                     pszGmlId = psIdGml->pszValue;
-                                    bIsHref = FALSE;
+                                    bIsHref = false;
                                 }
                             }
                         }
@@ -1171,7 +1170,7 @@ static void gmlHugeFileNodeCoords( struct huge_tag *pItem,
             if( pszGmlId != NULL )
             {
                 CPLString* posNode;
-                if( bIsHref == TRUE )
+                if( bIsHref )
                 {
                     if (pszGmlId[0] != '#')
                     {
@@ -1193,25 +1192,25 @@ static void gmlHugeFileNodeCoords( struct huge_tag *pItem,
                     pItem->gmlNodeTo = posNode;
                     pItem->bIsNodeToHref = bIsHref;
                 }
-                pszGmlId = NULL;
-                bIsHref = FALSE;
-                cOrientation = '+';
+                /*pszGmlId = NULL;*/
+                /*bIsHref = false; */
+                /*cOrientation = '+';*/
             }
         }
         psChild = psChild->psNext;
     }
 }
 
-static void gmlHugeFileCheckXrefs( struct huge_helper *helper, 
+static void gmlHugeFileCheckXrefs( struct huge_helper *helper,
                                    const CPLXMLNode *psNode )
 {
 /* identifying <Edge> GML nodes */
     if( psNode->eType == CXT_Element )
     {
-        if( EQUAL(psNode->pszValue, "Edge") == TRUE )
+        if( EQUAL(psNode->pszValue, "Edge") )
         {
             CPLString *gmlId = NULL;
-            if( gmlHugeFindGmlId( psNode, &gmlId ) == TRUE )
+            if( gmlHugeFindGmlId( psNode, &gmlId ) )
             {
                 char * gmlText = CPLSerializeXMLTree((CPLXMLNode *)psNode);
                 CPLString *gmlValue = new CPLString(gmlText);
@@ -1235,18 +1234,18 @@ static void gmlHugeFileCheckXrefs( struct huge_helper *helper,
     {
         if( psChild->eType == CXT_Element )
         {
-            if( EQUAL(psChild->pszValue, "Edge") == TRUE ||
-                EQUAL(psChild->pszValue, "directedEdge") == TRUE )
+            if( EQUAL(psChild->pszValue, "Edge") ||
+                EQUAL(psChild->pszValue, "directedEdge") )
             {
                 gmlHugeFileCheckXrefs( helper, psChild );
             }
-            if( EQUAL(psChild->pszValue, "directedFace") == TRUE )
+            if( EQUAL(psChild->pszValue, "directedFace") )
             {
                 const CPLXMLNode *psFace = psChild->psChild;
                 if( psFace != NULL )
                 {
                     if( psFace->eType == CXT_Element &&
-                        EQUAL(psFace->pszValue, "Face") == TRUE)
+                        EQUAL(psFace->pszValue, "Face") )
                     {
                         const CPLXMLNode *psDirEdge = psFace->psChild;
                         while (psDirEdge != NULL)
@@ -1255,7 +1254,7 @@ static void gmlHugeFileCheckXrefs( struct huge_helper *helper,
                             while( psEdge != NULL)
                             {
                                 if( psEdge->eType == CXT_Element &&
-                                    EQUAL(psEdge->pszValue, "Edge") == TRUE)
+                                    EQUAL(psEdge->pszValue, "Edge") )
                                     gmlHugeFileCheckXrefs( helper, psEdge );
                                 psEdge = psEdge->psNext;
                             }
@@ -1274,8 +1273,8 @@ static void gmlHugeFileCheckXrefs( struct huge_helper *helper,
     {
         if( psNext->eType == CXT_Element )
         {
-            if( EQUAL(psNext->pszValue, "Edge") == TRUE ||
-                EQUAL(psNext->pszValue, "directedEdge") == TRUE )
+            if( EQUAL(psNext->pszValue, "Edge") ||
+                EQUAL(psNext->pszValue, "directedEdge") )
             {
                 gmlHugeFileCheckXrefs( helper, psNext );
             }
@@ -1284,7 +1283,7 @@ static void gmlHugeFileCheckXrefs( struct huge_helper *helper,
     }
 }
 
-static void gmlHugeFileCleanUp ( struct huge_helper *helper ) 
+static void gmlHugeFileCleanUp ( struct huge_helper *helper )
 {
 /* cleaning up any SQLite handle */
     if( helper->hNodes != NULL )
@@ -1304,7 +1303,7 @@ static void gmlHugeFileCheckPendingHrefs( struct huge_helper *helper,
 /* identifying any xlink:href to be replaced */
     if( psNode->eType == CXT_Element )
     {
-        if( EQUAL(psNode->pszValue, "directedEdge") == TRUE )
+        if( EQUAL(psNode->pszValue, "directedEdge") )
         {
             char cOrientation = '+';
             CPLXMLNode *psAttr = psNode->psChild;
@@ -1341,7 +1340,7 @@ static void gmlHugeFileCheckPendingHrefs( struct huge_helper *helper,
                             }
                             CPLString *gmlId = new CPLString(pszHref->pszValue+1);
                             gmlHugeAddPendingToHelper( helper, gmlId, psParent,
-                                                       psNode, TRUE, cOrientation );
+                                                       psNode, true, cOrientation );
                         }
                     }
                 }
@@ -1356,9 +1355,9 @@ static void gmlHugeFileCheckPendingHrefs( struct huge_helper *helper,
     {
         if( psChild->eType == CXT_Element )
         {
-            if( EQUAL(psChild->pszValue, "directedEdge") == TRUE ||
-                EQUAL(psChild->pszValue, "directedFace") == TRUE ||
-                EQUAL(psChild->pszValue, "Face") == TRUE)
+            if( EQUAL(psChild->pszValue, "directedEdge") ||
+                EQUAL(psChild->pszValue, "directedFace") ||
+                EQUAL(psChild->pszValue, "Face") )
             {
                 gmlHugeFileCheckPendingHrefs( helper, psNode, psChild );
             }
@@ -1372,7 +1371,7 @@ static void gmlHugeFileCheckPendingHrefs( struct huge_helper *helper,
     {
         if( psNext->eType == CXT_Element )
         {
-            if( EQUAL(psNext->pszValue, "Face") == TRUE )
+            if( EQUAL(psNext->pszValue, "Face") )
             {
                 gmlHugeFileCheckPendingHrefs( helper, psParent, psNext );
             }
@@ -1389,7 +1388,7 @@ static void gmlHugeSetHrefGmlText( struct huge_helper *helper,
     struct huge_href *pItem = helper->pFirstHref;
     while( pItem != NULL )
     {
-        if( EQUAL( pItem->gmlId->c_str(), pszGmlId ) == TRUE )
+        if( EQUAL( pItem->gmlId->c_str(), pszGmlId ) )
         {
             if( pItem->gmlText != NULL)
                 delete pItem->gmlText;
@@ -1403,7 +1402,7 @@ static void gmlHugeSetHrefGmlText( struct huge_helper *helper,
 static struct huge_parent *gmlHugeFindParent( struct huge_helper *helper,
                                               CPLXMLNode *psParent )
 {
-/* inserting a GML Node (parent) to be rewritted */
+    /* Inserting a GML Node (parent) to be rewritten */
     struct huge_parent *pItem = helper->pFirstParent;
 
     /* checking if already exists */
@@ -1448,18 +1447,18 @@ static struct huge_parent *gmlHugeFindParent( struct huge_helper *helper,
 static int gmlHugeSetChild( struct huge_parent *pParent,
                             struct huge_href *pItem )
 {
-/* setting a Child Node to be rewritted */
+    /* Setting a Child Node to be rewritten. */
     struct huge_child *pChild = pParent->pFirst;
     while( pChild != NULL )
     {
          if( pChild->psChild == pItem->psNode )
          {
             pChild->pItem = pItem;
-            return TRUE;
+            return true;
          }
          pChild = pChild->pNext;
     }
-    return FALSE;
+    return false;
 }
 
 static int gmlHugeResolveEdges( CPL_UNUSED struct huge_helper *helper,
@@ -1470,8 +1469,8 @@ static int gmlHugeResolveEdges( CPL_UNUSED struct huge_helper *helper,
     CPLString      osCommand;
     sqlite3_stmt   *hStmtEdges;
     int            rc;
-    int            bIsComma = FALSE;
-    int            bError = FALSE;
+    bool           bIsComma = false;
+    bool           bError = false;
     struct huge_href *pItem;
     struct huge_parent *pParent;
 
@@ -1482,10 +1481,10 @@ static int gmlHugeResolveEdges( CPL_UNUSED struct huge_helper *helper,
     pItem = helper->pFirstHref;
     while( pItem != NULL )
     {
-        if( bIsComma == TRUE )
+        if( bIsComma )
             osCommand += ", ";
         else
-            bIsComma = TRUE;
+            bIsComma = true;
         osCommand += "'";
         osCommand += pItem->gmlId->c_str();
         osCommand += "'";
@@ -1495,11 +1494,11 @@ static int gmlHugeResolveEdges( CPL_UNUSED struct huge_helper *helper,
     rc = sqlite3_prepare_v2( hDB, osCommand.c_str(), -1, &hStmtEdges, NULL );
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to create QUERY stmt for EDGES" );
-        return FALSE;
+        return false;
     }
-    while ( TRUE )
+    while( true )
     {
         rc = sqlite3_step( hStmtEdges );
         if( rc == SQLITE_DONE )
@@ -1517,37 +1516,37 @@ static int gmlHugeResolveEdges( CPL_UNUSED struct huge_helper *helper,
         }
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Edge xlink:href QUERY: sqlite3_step(%s)", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Edge xlink:href QUERY: sqlite3_step(%s)",
                       sqlite3_errmsg(hDB) );
-            bError = TRUE;
+            bError = true;
             break;
         }
     }
     sqlite3_finalize ( hStmtEdges );
-    if( bError == TRUE )
-        return FALSE;
+    if( bError )
+        return false;
 
-    /* indentifying any GML node to be rewritten */
+    /* Identifying any GML node to be rewritten. */
     pItem = helper->pFirstHref;
     while( pItem != NULL )
     {
         if( pItem->gmlText == NULL || pItem->psParent == NULL ||
             pItem->psNode == NULL )
         {
-            bError = TRUE;
+            bError = true;
             break;
         }
         pParent = gmlHugeFindParent( helper, (CPLXMLNode *)pItem->psParent );
-        if( gmlHugeSetChild( pParent, pItem ) == FALSE )
+        if( gmlHugeSetChild( pParent, pItem ) == false )
         {
-            bError = TRUE;
+            bError = true;
             break;
         }
         pItem = pItem->pNext;
     }
 
-    if( bError == FALSE )
+    if( bError == false )
     {
     /* rewriting GML nodes */
         pParent = helper->pFirstParent;
@@ -1561,7 +1560,7 @@ static int gmlHugeResolveEdges( CPL_UNUSED struct huge_helper *helper,
             {
                 CPLRemoveXMLChild( pParent->psParent, pChild->psChild );
 
-                /* destroyng any Child Node to be rewritten */
+                /* Destroying any Child Node to be rewritten */
                 if( pChild->pItem != NULL )
                     CPLDestroyXMLNode( pChild->psChild );
                 pChild = pChild->pNext;
@@ -1586,7 +1585,8 @@ static int gmlHugeResolveEdges( CPL_UNUSED struct huge_helper *helper,
                         CPLCreateXMLNode(psOrientationNode, CXT_Text, "-");
                     }
                     CPLXMLNode *psEdge = CPLParseXMLString(pChild->pItem->gmlText->c_str());
-                    CPLAddXMLChild( psNewNode, psEdge );
+                    if( psEdge != NULL )
+                        CPLAddXMLChild( psNewNode, psEdge );
                     CPLAddXMLChild( pParent->psParent, psNewNode );
                 }
                 pChild = pChild->pNext;
@@ -1597,15 +1597,15 @@ static int gmlHugeResolveEdges( CPL_UNUSED struct huge_helper *helper,
 
     /* resetting the Rewrite Helper to an empty state */
     gmlHugeFileRewiterReset( helper );
-    if( bError == TRUE )
-        return FALSE;
-    return TRUE;
+    if( bError )
+        return false;
+    return true;
 }
 
-static int gmlHugeFileWriteResolved ( struct huge_helper *helper, 
-                                      const char *pszOutputFilename, 
+static bool gmlHugeFileWriteResolved ( struct huge_helper *helper,
+                                      const char *pszOutputFilename,
                                       GMLReader *pReader,
-                                      int *m_bSequentialLayers ) 
+                                      int *m_nHasSequentialLayers )
 {
 /* writing the resolved GML file */
     VSILFILE       *fp;
@@ -1614,7 +1614,7 @@ static int gmlHugeFileWriteResolved ( struct huge_helper *helper,
     int            rc;
     sqlite3        *hDB = helper->hDB;
     sqlite3_stmt   *hStmtNodes;
-    int            bError = FALSE;
+    bool           bError = false;
     int            iOutCount = 0;
 
 /* -------------------------------------------------------------------- */
@@ -1623,9 +1623,9 @@ static int gmlHugeFileWriteResolved ( struct huge_helper *helper,
     fp = VSIFOpenL( pszOutputFilename, "w" );
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "Failed to open %.500s to write.", pszOutputFilename );
-        return FALSE;
+        return false;
     }
 
     /* query cursor [Nodes] */
@@ -1634,19 +1634,19 @@ static int gmlHugeFileWriteResolved ( struct huge_helper *helper,
     rc = sqlite3_prepare_v2( hDB, osCommand, -1, &hStmtNodes, NULL );
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to create QUERY stmt for NODES" );
         VSIFCloseL( fp );
-        return FALSE;
+        return false;
     }
 
-    VSIFPrintfL ( fp, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" ); 
+    VSIFPrintfL ( fp, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" );
     VSIFPrintfL ( fp, "<ResolvedTopoFeatureCollection  "
-                      "xmlns:gml=\"http://www.opengis.net/gml\">\n" );		
+                      "xmlns:gml=\"http://www.opengis.net/gml\">\n" );
     VSIFPrintfL ( fp, "  <ResolvedTopoFeatureMembers>\n" );
     /* exporting Nodes */
     GFSTemplateList *pCC = new GFSTemplateList();
-    while ( TRUE )
+    while( true )
     {
         rc = sqlite3_step( hStmtNodes );
         if( rc == SQLITE_DONE )
@@ -1658,18 +1658,18 @@ static int gmlHugeFileWriteResolved ( struct huge_helper *helper,
             double x;
             double y;
             double z = 0.0;
-            int bHasZ = FALSE;
+            bool bHasZ = false;
             pszGmlId = (const char *)sqlite3_column_text ( hStmtNodes, 0 );
             x = sqlite3_column_double ( hStmtNodes, 1 );
             y = sqlite3_column_double ( hStmtNodes, 2 );
             if ( sqlite3_column_type( hStmtNodes, 3 ) == SQLITE_FLOAT )
             {
                 z = sqlite3_column_double ( hStmtNodes, 3 );
-                bHasZ = TRUE;
+                bHasZ = true;
             }
 
             /* inserting a node into the resolved GML file */
-            pCC->Update( "ResolvedNodes", TRUE );
+            pCC->Update( "ResolvedNodes", true );
             VSIFPrintfL ( fp, "    <ResolvedNodes>\n" );
             pszEscaped = CPLEscapeString( pszGmlId, -1, CPLES_XML );
             VSIFPrintfL ( fp, "      <NodeGmlId>%s</NodeGmlId>\n", pszEscaped );
@@ -1677,17 +1677,17 @@ static int gmlHugeFileWriteResolved ( struct huge_helper *helper,
             VSIFPrintfL ( fp, "      <ResolvedGeometry> \n" );
             if ( helper->nodeSrs == NULL )
                 VSIFPrintfL ( fp, "        <gml:Point srsDimension=\"%d\">",
-                              ( bHasZ == TRUE ) ? 3 : 2 );
+                              ( bHasZ ) ? 3 : 2 );
             else
             {
                 pszEscaped = CPLEscapeString( helper->nodeSrs->c_str(), -1, CPLES_XML );
                 VSIFPrintfL ( fp, "        <gml:Point srsDimension=\"%d\""
                                   " srsName=\"%s\">",
-                                  ( bHasZ == TRUE ) ? 3 : 2,
+                                  ( bHasZ ) ? 3 : 2,
                               pszEscaped );
                 CPLFree(pszEscaped);
             }
-            if ( bHasZ == TRUE )
+            if ( bHasZ )
                 VSIFPrintfL ( fp, "<gml:pos>%1.8f %1.8f %1.8f</gml:pos>"
                                   "</gml:Point>\n",
                               x, y, z );
@@ -1701,11 +1701,12 @@ static int gmlHugeFileWriteResolved ( struct huge_helper *helper,
         }
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "ResolvedNodes QUERY: sqlite3_step(%s)", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "ResolvedNodes QUERY: sqlite3_step(%s)",
             sqlite3_errmsg(hDB) );
             sqlite3_finalize ( hStmtNodes );
-            return FALSE;
+            delete pCC;
+            return false;
         }
     }
     sqlite3_finalize ( hStmtNodes );
@@ -1716,9 +1717,9 @@ static int gmlHugeFileWriteResolved ( struct huge_helper *helper,
         GMLFeatureClass *poClass = poFeature->GetClass();
         const CPLXMLNode* const * papsGeomList = poFeature->GetGeometryList();
         int iPropCount = poClass->GetPropertyCount();
-		
-        int b_has_geom = FALSE;
-        VSIFPrintfL ( fp, "    <%s>\n", poClass->GetElementName() ); 
+
+        bool b_has_geom = false;
+        VSIFPrintfL ( fp, "    <%s>\n", poClass->GetElementName() );
 
         for( int iProp = 0; iProp < iPropCount; iProp++ )
         {
@@ -1733,8 +1734,8 @@ static int gmlHugeFileWriteResolved ( struct huge_helper *helper,
                     char *gmlText = CPLEscapeString( poProp->papszSubProperties[iSub],
                                                     -1,
                                                     CPLES_XML );
-                    VSIFPrintfL ( fp, "      <%s>%s</%s>\n", 
-                                  pszPropName, gmlText, pszPropName ); 
+                    VSIFPrintfL ( fp, "      <%s>%s</%s>\n",
+                                  pszPropName, gmlText, pszPropName );
                     CPLFree( gmlText );
                 }
             }
@@ -1747,25 +1748,25 @@ static int gmlHugeFileWriteResolved ( struct huge_helper *helper,
             while( psNode != NULL )
             {
                 char *pszResolved = NULL;
-                int bNotToBeResolved;
+                bool bNotToBeResolved;
                 if( psNode->eType != CXT_Element )
-                    bNotToBeResolved = TRUE;
+                    bNotToBeResolved = true;
                 else
                 {
-                    if( EQUAL(psNode->pszValue, "TopoCurve") == TRUE ||
-                        EQUAL(psNode->pszValue, "TopoSurface") == TRUE )
-                        bNotToBeResolved = FALSE;
+                    if( EQUAL(psNode->pszValue, "TopoCurve") ||
+                        EQUAL(psNode->pszValue, "TopoSurface") )
+                        bNotToBeResolved = false;
                     else
-                        bNotToBeResolved = TRUE;
+                        bNotToBeResolved = true;
                 }
-                if( bNotToBeResolved == TRUE )
+                if( bNotToBeResolved )
                 {
                     VSIFPrintfL ( fp, "      <ResolvedGeometry> \n" );
                     pszResolved = CPLSerializeXMLTree((CPLXMLNode *)psNode);
                     VSIFPrintfL ( fp, "        %s\n", pszResolved );
                     CPLFree( pszResolved );
                     VSIFPrintfL ( fp, "      </ResolvedGeometry>\n" );
-                    b_has_geom = TRUE;
+                    b_has_geom = true;
                 }
                 else
                 {
@@ -1777,21 +1778,21 @@ static int gmlHugeFileWriteResolved ( struct huge_helper *helper,
                         VSIFPrintfL ( fp, "        %s\n", pszResolved );
                         CPLFree( pszResolved );
                         VSIFPrintfL ( fp, "      </ResolvedGeometry>\n" );
-                        b_has_geom = TRUE;
+                        b_has_geom = true;
                     }
                     else
                     {
                         if( gmlHugeResolveEdges( helper, (CPLXMLNode *)psNode,
-                                                         hDB ) == FALSE)
-                            bError = TRUE;
-                        if( gmlHugeFileHrefCheck( helper ) == FALSE )
-							bError = TRUE;
+                                                         hDB ) == false)
+                            bError = true;
+                        if( gmlHugeFileHrefCheck( helper ) == false )
+                            bError = true;
                         VSIFPrintfL ( fp, "      <ResolvedGeometry> \n" );
                         pszResolved = CPLSerializeXMLTree((CPLXMLNode *)psNode);
                         VSIFPrintfL ( fp, "        %s\n", pszResolved );
                         CPLFree( pszResolved );
                         VSIFPrintfL ( fp, "      </ResolvedGeometry>\n" );
-                        b_has_geom = TRUE;
+                        b_has_geom = true;
                         gmlHugeFileHrefReset( helper );
                     }
                 }
@@ -1801,36 +1802,36 @@ static int gmlHugeFileWriteResolved ( struct huge_helper *helper,
         }
         pCC->Update( poClass->GetElementName(), b_has_geom );
 
-        VSIFPrintfL ( fp, "    </%s>\n", poClass->GetElementName() ); 
+        VSIFPrintfL ( fp, "    </%s>\n", poClass->GetElementName() );
 
         delete poFeature;
         iOutCount++;
     }
 
-    VSIFPrintfL ( fp, "  </ResolvedTopoFeatureMembers>\n" ); 
-    VSIFPrintfL ( fp, "</ResolvedTopoFeatureCollection>\n" ); 
+    VSIFPrintfL ( fp, "  </ResolvedTopoFeatureMembers>\n" );
+    VSIFPrintfL ( fp, "</ResolvedTopoFeatureCollection>\n" );
 
     VSIFCloseL( fp );
-		
-    gmlUpdateFeatureClasses( pCC, pReader, m_bSequentialLayers );
-    if ( *m_bSequentialLayers == TRUE )
+
+    gmlUpdateFeatureClasses( pCC, pReader, m_nHasSequentialLayers );
+    if ( *m_nHasSequentialLayers )
         pReader->ReArrangeTemplateClasses( pCC );
     delete pCC;
-    if( bError == TRUE || iOutCount == 0 )
-        return FALSE;
-    return TRUE;
+    if( bError || iOutCount == 0 )
+        return false;
+    return true;
 }
 
 /**************************************************************/
 /*                                                            */
 /* private member(s):                                         */
-/* any other funtion is implemented as "internal" static,     */
+/* any other function is implemented as "internal" static,    */
 /* so to make all the SQLite own stuff nicely "invisible"     */
 /*                                                            */
 /**************************************************************/
 
-int GMLReader::ParseXMLHugeFile( const char *pszOutputFilename,
-                                 const int bSqliteIsTempFile,
+bool GMLReader::ParseXMLHugeFile( const char *pszOutputFilename,
+                                 const bool bSqliteIsTempFile,
                                  const int iSqliteCacheMB )
 
 {
@@ -1854,7 +1855,7 @@ int GMLReader::ParseXMLHugeFile( const char *pszOutputFilename,
     helper.pLastHref = NULL;
     helper.pFirstParent = NULL;
     helper.pLastParent = NULL;
-	
+
 /* -------------------------------------------------------------------- */
 /*      Creating/Opening the SQLite DB file                             */
 /* -------------------------------------------------------------------- */
@@ -1864,23 +1865,23 @@ int GMLReader::ParseXMLHugeFile( const char *pszOutputFilename,
     VSIStatBufL statBufL;
     if ( VSIStatExL ( pszSQLiteFilename, &statBufL, VSI_STAT_EXISTS_FLAG) == 0)
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "sqlite3_open(%s) failed:\n\tDB-file already exists", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "sqlite3_open(%s) failed:\n\tDB-file already exists",
                   pszSQLiteFilename );
-        return FALSE;
+        return false;
     }
 
     rc = sqlite3_open( pszSQLiteFilename, &hDB );
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "sqlite3_open(%s) failed: %s", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "sqlite3_open(%s) failed: %s",
                   pszSQLiteFilename, sqlite3_errmsg( hDB ) );
-        return FALSE;
+        return false;
     }
     helper.hDB = hDB;
-	
-/* 
+
+/*
 * setting SQLite for max speed; this is intrinsically unsafe,
 * and the DB file could be potentially damaged (power failure ...]
 *
@@ -1914,7 +1915,7 @@ int GMLReader::ParseXMLHugeFile( const char *pszOutputFilename,
                   pszErrMsg );
         sqlite3_free( pszErrMsg );
     }
-    
+
     /* setting the SQLite cache */
     if( iSqliteCacheMB > 0 )
     {
@@ -1923,8 +1924,8 @@ int GMLReader::ParseXMLHugeFile( const char *pszOutputFilename,
         /* refusing to allocate more than 1GB */
         if( cache_size > 1024 * 1024 )
             cache_size = 1024 * 1024;
-        char sqlPragma[1024];
-        sprintf( sqlPragma, "PRAGMA cache_size = %d", cache_size );
+        char sqlPragma[64];
+        snprintf( sqlPragma, sizeof(sqlPragma), "PRAGMA cache_size = %d", cache_size );
         rc = sqlite3_exec( hDB, sqlPragma, NULL, NULL, &pszErrMsg );
         if( rc != SQLITE_OK )
         {
@@ -1933,18 +1934,18 @@ int GMLReader::ParseXMLHugeFile( const char *pszOutputFilename,
             sqlite3_free( pszErrMsg );
         }
     }
-	
+
     if( !SetupParser() )
     {
         gmlHugeFileCleanUp ( &helper );
-        return FALSE;
+        return false;
     }
 
     /* creating SQLite tables and Insert cursors */
-    if( gmlHugeFileSQLiteInit( &helper ) == FALSE )
+    if( gmlHugeFileSQLiteInit( &helper ) == false )
     {
         gmlHugeFileCleanUp ( &helper );
-        return FALSE;
+        return false;
     }
 
     /* processing GML features */
@@ -1982,39 +1983,39 @@ int GMLReader::ParseXMLHugeFile( const char *pszOutputFilename,
     rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL, &pszErrMsg );
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to perform COMMIT TRANSACTION: %s",
                   pszErrMsg );
         sqlite3_free( pszErrMsg );
-        return FALSE;
+        return false;
     }
 
 /* attempting to resolve GML strings */
-    if( gmlHugeFileResolveEdges( &helper ) == FALSE )
+    if( gmlHugeFileResolveEdges( &helper ) == false )
     {
         gmlHugeFileCleanUp ( &helper );
-        return FALSE;
+        return false;
     }
-	
+
     /* restarting the GML parser */
     if( !SetupParser() )
     {
         gmlHugeFileCleanUp ( &helper );
-        return FALSE;
+        return false;
     }
 
     /* output: writing the revolved GML file */
-    if ( gmlHugeFileWriteResolved( &helper, pszOutputFilename, this, 
-                                   &m_bSequentialLayers ) == FALSE)
+    if ( gmlHugeFileWriteResolved( &helper, pszOutputFilename, this,
+                                   &m_nHasSequentialLayers ) == false)
     {
         gmlHugeFileCleanUp ( &helper );
-        return FALSE;
+        return false;
     }
 
     gmlHugeFileCleanUp ( &helper );
-    if ( bSqliteIsTempFile == TRUE )
+    if ( bSqliteIsTempFile )
         VSIUnlink( pszSQLiteFilename );
-    return TRUE;
+    return true;
 }
 
 /**************************************************************/
@@ -2022,9 +2023,9 @@ int GMLReader::ParseXMLHugeFile( const char *pszOutputFilename,
 /* an alternative <xlink:href> resolver based on SQLite       */
 /*                                                            */
 /**************************************************************/
-int GMLReader::HugeFileResolver( const char *pszFile,
-                                 int bSqliteIsTempFile,
-                                 int iSqliteCacheMB )
+bool GMLReader::HugeFileResolver( const char *pszFile,
+                                  bool bSqliteIsTempFile,
+                                  int iSqliteCacheMB )
 
 {
     // Check if the original source file is set.
@@ -2033,10 +2034,10 @@ int GMLReader::HugeFileResolver( const char *pszFile,
         CPLError( CE_Failure, CPLE_NotSupported,
         "GML source file needs to be set first with "
         "GMLReader::SetSourceFile()." );
-        return FALSE;
+        return false;
     }
-    if ( ParseXMLHugeFile( pszFile, bSqliteIsTempFile, iSqliteCacheMB ) == FALSE )
-        return FALSE;
+    if ( ParseXMLHugeFile( pszFile, bSqliteIsTempFile, iSqliteCacheMB ) == false )
+        return false;
 
     //set the source file to the resolved file
     CleanupParser();
@@ -2045,7 +2046,7 @@ int GMLReader::HugeFileResolver( const char *pszFile,
     fpGML = NULL;
     CPLFree( m_pszFilename );
     m_pszFilename = CPLStrdup( pszFile );
-    return TRUE;
+    return true;
 }
 
 #else  // HAVE_SQLITE
@@ -2055,25 +2056,25 @@ int GMLReader::HugeFileResolver( const char *pszFile,
 /*    simply output an error message              */
 /**************************************************/
 
-int GMLReader::HugeFileResolver( CPL_UNUSED const char *pszFile,
-                                 CPL_UNUSED int bSqliteIsTempFile,
+bool GMLReader::HugeFileResolver( CPL_UNUSED const char *pszFile,
+                                 CPL_UNUSED bool bSqliteIsTempFile,
                                  CPL_UNUSED int iSqliteCacheMB )
 
 {
     CPLError( CE_Failure, CPLE_NotSupported,
               "OGR was built without SQLite3 support\n"
               "... sorry, the HUGE GML resolver is unsupported\n" );
-    return FALSE;
+    return false;
 }
 
-int GMLReader::ParseXMLHugeFile( CPL_UNUSED const char *pszOutputFilename,
-                                 CPL_UNUSED const int bSqliteIsTempFile,
+bool GMLReader::ParseXMLHugeFile( CPL_UNUSED const char *pszOutputFilename,
+                                 CPL_UNUSED const bool bSqliteIsTempFile,
                                  CPL_UNUSED const int iSqliteCacheMB )
 {
     CPLError( CE_Failure, CPLE_NotSupported,
               "OGR was built without SQLite3 support\n"
               "... sorry, the HUGE GML resolver is unsupported\n" );
-    return FALSE;
+    return false;
 }
 
 #endif // HAVE_SQLITE
diff --git a/ogr/ogrsf_frmts/gml/ogr_gml.h b/ogr/ogrsf_frmts/gml/ogr_gml.h
index 5adc217..aa252d9 100644
--- a/ogr/ogrsf_frmts/gml/ogr_gml.h
+++ b/ogr/ogrsf_frmts/gml/ogr_gml.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_gml.h 29214 2015-05-20 13:47:29Z rouault $
+ * $Id: ogr_gml.h 33702 2016-03-11 06:20:16Z goatbar $
  *
  * Project:  GML Reader
  * Purpose:  Declarations for OGR wrapper classes for GML, and GML<->OGR
@@ -16,21 +16,21 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_GML_H_INCLUDED
-#define _OGR_GML_H_INCLUDED
+#ifndef OGR_GML_H_INCLUDED
+#define OGR_GML_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "gmlreader.h"
@@ -54,11 +54,11 @@ class OGRGMLLayer : public OGRLayer
 
     GIntBig             iNextGMLId;
     int                 nTotalGMLCount;
-    int                 bInvalidFIDFound;
+    bool                bInvalidFIDFound;
     char                *pszFIDPrefix;
 
-    int                 bWriter;
-    int                 bSameSRS;
+    bool                bWriter;
+    bool                bSameSRS;
 
     OGRGMLDataSource    *poDS;
 
@@ -66,13 +66,13 @@ class OGRGMLLayer : public OGRLayer
 
     void                *hCacheSRS;
 
-    int                 bUseOldFIDFormat;
+    bool                bUseOldFIDFormat;
 
-    int                 bFaceHoleNegative;
+    bool                bFaceHoleNegative;
 
   public:
-                        OGRGMLLayer( const char * pszName, 
-                                     int bWriter,
+                        OGRGMLLayer( const char * pszName,
+                                     bool bWriter,
                                      OGRGMLDataSource *poDS );
 
                         ~OGRGMLLayer();
@@ -82,9 +82,11 @@ class OGRGMLLayer : public OGRLayer
 
     GIntBig             GetFeatureCount( int bForce = TRUE );
     OGRErr              GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
     OGRErr              ICreateFeature( OGRFeature *poFeature );
-    
+
     OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
@@ -103,76 +105,76 @@ class OGRGMLDataSource : public OGRDataSource
 {
     OGRGMLLayer     **papoLayers;
     int                 nLayers;
-    
+
     char                *pszName;
-    
+
     OGRGMLLayer         *TranslateGMLSchema( GMLFeatureClass * );
 
     char               **papszCreateOptions;
 
-    // output related parameters 
+    // output related parameters
     VSILFILE           *fpOutput;
-    int                 bFpOutputIsNonSeekable;
-    int                 bFpOutputSingleFile;
+    bool                bFpOutputIsNonSeekable;
+    bool                bFpOutputSingleFile;
     OGREnvelope3D       sBoundingRect;
-    int                 bBBOX3D;
+    bool                bBBOX3D;
     int                 nBoundedByLocation;
-    
+
     int                 nSchemaInsertLocation;
-    int                 bIsOutputGML3;
-    int                 bIsOutputGML3Deegree; /* if TRUE, then bIsOutputGML3 is also TRUE */
-    int                 bIsOutputGML32; /* if TRUE, then bIsOutputGML3 is also TRUE */
-    int                 bIsLongSRSRequired;
-    int                 bWriteSpaceIndentation;
+    bool                bIsOutputGML3;
+    bool                bIsOutputGML3Deegree; /* if TRUE, then bIsOutputGML3 is also TRUE */
+    bool                bIsOutputGML32; /* if TRUE, then bIsOutputGML3 is also TRUE */
+    bool                bIsLongSRSRequired;
+    bool                bWriteSpaceIndentation;
 
     OGRSpatialReference* poWriteGlobalSRS;
-    int                 bWriteGlobalSRS;
+    bool                bWriteGlobalSRS;
 
     // input related parameters.
     CPLString           osFilename;
     CPLString           osXSDFilename;
 
     IGMLReader          *poReader;
-    int                 bOutIsTempFile;
+    bool                bOutIsTempFile;
 
     void                InsertHeader();
 
-    int                 bExposeGMLId;
-    int                 bExposeFid;
-    int                 bIsWFS;
+    bool                bExposeGMLId;
+    bool                bExposeFid;
+    bool                bIsWFS;
 
-    int                 bUseGlobalSRSName;
+    bool                bUseGlobalSRSName;
 
-    int                 m_bInvertAxisOrderIfLatLong;
-    int                 m_bConsiderEPSGAsURN;
-    int                 m_bGetSecondaryGeometryOption;
+    bool                m_bInvertAxisOrderIfLatLong;
+    bool                m_bConsiderEPSGAsURN;
+    bool                m_bGetSecondaryGeometryOption;
 
     ReadMode            eReadMode;
     GMLFeature         *poStoredGMLFeature;
     OGRGMLLayer        *poLastReadLayer;
-    
-    int                 bEmptyAsNull;
+
+    bool                bEmptyAsNull;
 
     void                FindAndParseTopElements(VSILFILE* fp);
     void                SetExtents(double dfMinX, double dfMinY, double dfMaxX, double dfMaxY);
-    
+
     void                BuildJointClassFromXSD();
     void                BuildJointClassFromScannedSchema();
-    
+
     void                WriteTopElements();
 
   public:
                         OGRGMLDataSource();
                         ~OGRGMLDataSource();
 
-    int                 Open( GDALOpenInfo* poOpenInfo );
-    int                 Create( const char *pszFile, char **papszOptions );
+    bool                Open( GDALOpenInfo* poOpenInfo );
+    bool                Create( const char *pszFile, char **papszOptions );
 
     const char          *GetName() { return pszName; }
     int                 GetLayerCount() { return nLayers; }
     OGRLayer            *GetLayer( int );
 
-    virtual OGRLayer    *ICreateLayer( const char *, 
+    virtual OGRLayer    *ICreateLayer( const char *,
                                       OGRSpatialReference * = NULL,
                                       OGRwkbGeometryType = wkbUnknown,
                                       char ** = NULL );
@@ -188,16 +190,16 @@ class OGRGMLDataSource : public OGRDataSource
 
     static void         PrintLine(VSILFILE* fp, const char *fmt, ...) CPL_PRINT_FUNC_FORMAT (2, 3);
 
-    int                 IsGML3Output() const { return bIsOutputGML3; }
-    int                 IsGML3DeegreeOutput() const { return bIsOutputGML3Deegree; }
-    int                 IsGML32Output() const { return bIsOutputGML32; }
-    int                 IsLongSRSRequired() const { return bIsLongSRSRequired; }
+    bool                IsGML3Output() const { return bIsOutputGML3; }
+    bool                IsGML3DeegreeOutput() const { return bIsOutputGML3Deegree; }
+    bool                IsGML32Output() const { return bIsOutputGML32; }
+    bool                IsLongSRSRequired() const { return bIsLongSRSRequired; }
     int                 WriteSpaceIndentation() const { return bWriteSpaceIndentation; }
     const char         *GetGlobalSRSName();
 
-    int                 GetInvertAxisOrderIfLatLong() const { return m_bInvertAxisOrderIfLatLong; }
-    int                 GetConsiderEPSGAsURN() const { return m_bConsiderEPSGAsURN; }
-    int                 GetSecondaryGeometryOption() const { return m_bGetSecondaryGeometryOption; }
+    bool                GetInvertAxisOrderIfLatLong() const { return m_bInvertAxisOrderIfLatLong; }
+    bool                GetConsiderEPSGAsURN() const { return m_bConsiderEPSGAsURN; }
+    bool                GetSecondaryGeometryOption() const { return m_bGetSecondaryGeometryOption; }
 
     ReadMode            GetReadMode() const { return eReadMode; }
     void                SetStoredGMLFeature(GMLFeature* poStoredGMLFeatureIn) { poStoredGMLFeature = poStoredGMLFeatureIn; }
@@ -207,16 +209,16 @@ class OGRGMLDataSource : public OGRDataSource
     void                SetLastReadLayer(OGRGMLLayer* poLayer) { poLastReadLayer = poLayer; }
 
     const char         *GetAppPrefix();
-    int                 RemoveAppPrefix();
-    int                 WriteFeatureBoundedBy();
+    bool                RemoveAppPrefix();
+    bool                WriteFeatureBoundedBy();
     const char         *GetSRSDimensionLoc();
 
     virtual OGRLayer *          ExecuteSQL( const char *pszSQLCommand,
                                             OGRGeometry *poSpatialFilter,
                                             const char *pszDialect );
     virtual void                ReleaseResultSet( OGRLayer * poResultsSet );
-    
-    static int          CheckHeader(const char* pszStr);
+
+    static bool          CheckHeader(const char* pszStr);
 };
 
-#endif /* _OGR_GML_H_INCLUDED */
+#endif /* OGR_GML_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp b/ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp
index 674fc01..9932107 100644
--- a/ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp
+++ b/ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgmldatasource.cpp 32902 2016-01-10 17:54:15Z rouault $
+ * $Id: ogrgmldatasource.cpp 33702 2016-03-11 06:20:16Z goatbar $
  *
  * Project:  OGR
  * Purpose:  Implements OGRGMLDataSource class.
@@ -29,8 +29,8 @@
  *
  ******************************************************************************
  * Contributor: Alessandro Furieri, a.furieri at lqt.it
- * Portions of this module implenting GML_SKIP_RESOLVE_ELEMS HUGE
- * Developed for Faunalia ( http://www.faunalia.it) with funding from 
+ * Portions of this module implementing GML_SKIP_RESOLVE_ELEMS HUGE
+ * Developed for Faunalia ( http://www.faunalia.it) with funding from
  * Regione Toscana - Settore SISTEMA INFORMATIVO TERRITORIALE ED AMBIENTALE
  *
  ****************************************************************************/
@@ -47,10 +47,10 @@
 
 #include <vector>
 
-CPL_CVSID("$Id: ogrgmldatasource.cpp 32902 2016-01-10 17:54:15Z rouault $");
+CPL_CVSID("$Id: ogrgmldatasource.cpp 33702 2016-03-11 06:20:16Z goatbar $");
 
-static int ExtractSRSName(const char* pszXML, char* szSRSName,
-                          size_t sizeof_szSRSName);
+static bool ExtractSRSName(const char* pszXML, char* szSRSName,
+                           size_t sizeof_szSRSName);
 
 /************************************************************************/
 /*                   ReplaceSpaceByPct20IfNeeded()                      */
@@ -88,36 +88,36 @@ OGRGMLDataSource::OGRGMLDataSource()
 
     poReader = NULL;
     fpOutput = NULL;
-    bFpOutputIsNonSeekable = FALSE;
-    bFpOutputSingleFile = FALSE;
-    bIsOutputGML3 = FALSE;
-    bIsOutputGML3Deegree = FALSE;
-    bIsOutputGML32 = FALSE;
-    bIsLongSRSRequired = FALSE;
-    bWriteSpaceIndentation = TRUE;
+    bFpOutputIsNonSeekable = false;
+    bFpOutputSingleFile = false;
+    bIsOutputGML3 = false;
+    bIsOutputGML3Deegree = false;
+    bIsOutputGML32 = false;
+    bIsLongSRSRequired = false;
+    bWriteSpaceIndentation = true;
 
     papszCreateOptions = NULL;
-    bOutIsTempFile = FALSE;
+    bOutIsTempFile = false;
 
-    bExposeGMLId = FALSE;
-    bExposeFid = FALSE;
+    bExposeGMLId = false;
+    bExposeFid = false;
     nSchemaInsertLocation = -1;
     nBoundedByLocation = -1;
-    bBBOX3D = FALSE;
+    bBBOX3D = false;
 
     poWriteGlobalSRS = NULL;
-    bWriteGlobalSRS = FALSE;
-    bUseGlobalSRSName = FALSE;
-    bIsWFS = FALSE;
+    bWriteGlobalSRS = false;
+    bUseGlobalSRSName = false;
+    bIsWFS = false;
 
     eReadMode = STANDARD;
     poStoredGMLFeature = NULL;
     poLastReadLayer = NULL;
 
-    m_bInvertAxisOrderIfLatLong = FALSE;
-    m_bConsiderEPSGAsURN = FALSE;
-    m_bGetSecondaryGeometryOption = FALSE;
-    bEmptyAsNull = TRUE;
+    m_bInvertAxisOrderIfLatLong = false;
+    m_bConsiderEPSGAsURN = false;
+    m_bGetSecondaryGeometryOption = false;
+    bEmptyAsNull = true;
 }
 
 /************************************************************************/
@@ -153,7 +153,7 @@ OGRGMLDataSource::~OGRGMLDataSource()
         {
             if (bWriteGlobalSRS && sBoundingRect.IsInit()  && IsGML3Output())
             {
-                int bCoordSwap = FALSE;
+                bool bCoordSwap = false;
                 char* pszSRSName;
                 if (poWriteGlobalSRS)
                     pszSRSName = GML_GetSRSName(poWriteGlobalSRS, IsLongSRSRequired(), &bCoordSwap);
@@ -231,7 +231,7 @@ OGRGMLDataSource::~OGRGMLDataSource()
 
     for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
-    
+
     CPLFree( papoLayers );
 
     if( poReader )
@@ -253,12 +253,12 @@ OGRGMLDataSource::~OGRGMLDataSource()
 /*                            CheckHeader()                             */
 /************************************************************************/
 
-int OGRGMLDataSource::CheckHeader(const char* pszStr)
+bool OGRGMLDataSource::CheckHeader(const char* pszStr)
 {
     if( strstr(pszStr,"opengis.net/gml") == NULL &&
         strstr(pszStr,"<csw:GetRecordsResponse") == NULL )
     {
-        return FALSE;
+        return false;
     }
 
     /* Ignore .xsd schemas */
@@ -266,42 +266,42 @@ int OGRGMLDataSource::CheckHeader(const char* pszStr)
         || strstr(pszStr, "<xs:schema") != NULL
         || strstr(pszStr, "<xsd:schema") != NULL )
     {
-        return FALSE;
+        return false;
     }
 
     /* Ignore GeoRSS documents. They will be recognized by the GeoRSS driver */
     if( strstr(pszStr, "<rss") != NULL && strstr(pszStr, "xmlns:georss") != NULL )
     {
-        return FALSE;
+        return false;
     }
 
     /* Ignore OpenJUMP .jml documents. They will be recognized by the OpenJUMP driver */
     if( strstr(pszStr, "<JCSDataFile") != NULL )
     {
-        return FALSE;
+        return false;
     }
 
     /* Ignore OGR WFS xml description files, or WFS Capabilities results */
     if( strstr(pszStr, "<OGRWFSDataSource>") != NULL ||
         strstr(pszStr, "<wfs:WFS_Capabilities") != NULL )
     {
-        return FALSE;
+        return false;
     }
 
     /* Ignore WMTS capabilities results */
     if( strstr(pszStr, "http://www.opengis.net/wmts/1.0") != NULL )
     {
-        return FALSE;
+        return false;
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
 
-int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
+bool OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
 
 {
     VSILFILE   *fp;
@@ -309,10 +309,10 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
     GIntBig     nNumberOfFeatures = 0;
     CPLString   osWithVsiGzip;
     const char *pszSchemaLocation = NULL;
-    int bCheckAuxFile = TRUE;
+    bool bCheckAuxFile = true;
 
 /* -------------------------------------------------------------------- */
-/*      Extract xsd filename from connexion string if present.          */
+/*      Extract XSD filename from connection string if present.          */
 /* -------------------------------------------------------------------- */
     osFilename = poOpenInfo->pszFilename;
     const char *pszXSDFilenameTmp = strstr(poOpenInfo->pszFilename, ",xsd=");
@@ -341,13 +341,13 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
     {
         fpToClose = fp = VSIFOpenL( pszFilename, "r" );
         if( fp == NULL )
-            return FALSE;
+            return false;
     }
 
-    int bExpatCompatibleEncoding = FALSE;
-    int bHas3D = FALSE;
-    int bHintConsiderEPSGAsURN = FALSE;
-    int bAnalyzeSRSPerFeature = TRUE;
+    bool bExpatCompatibleEncoding = false;
+    bool bHas3D = false;
+    bool bHintConsiderEPSGAsURN = false;
+    bool bAnalyzeSRSPerFeature = true;
 
     char szSRSName[128];
     szSRSName[0] = '\0';
@@ -361,7 +361,7 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
     {
         if( fpToClose )
             VSIFCloseL( fpToClose );
-        return FALSE;
+        return false;
     }
     szHeader[nRead] = '\0';
 
@@ -369,7 +369,7 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
     /* it transparently with /vsigzip/ */
     if ( ((GByte*)szHeader)[0] == 0x1f && ((GByte*)szHeader)[1] == 0x8b &&
             EQUAL(CPLGetExtension(pszFilename), "gz") &&
-            strncmp(pszFilename, "/vsigzip/", strlen("/vsigzip/")) != 0 )
+            !STARTS_WITH(pszFilename, "/vsigzip/") )
     {
         if( fpToClose )
             VSIFCloseL( fpToClose );
@@ -381,13 +381,13 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
 
         fp = fpToClose = VSIFOpenL( pszFilename, "r" );
         if( fp == NULL )
-            return FALSE;
+            return false;
 
         nRead = VSIFReadL( szHeader, 1, sizeof(szHeader) - 1, fp );
         if (nRead <= 0)
         {
             VSIFCloseL( fpToClose );
-            return FALSE;
+            return false;
         }
         szHeader[nRead] = '\0';
     }
@@ -395,7 +395,7 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Check for a UTF-8 BOM and skip if found                         */
 /*                                                                      */
-/*      TODO: BOM is variable-lenght parameter and depends on encoding. */
+/*      TODO: BOM is variable-length parameter and depends on encoding. */
 /*            Add BOM detection for other encodings.                    */
 /* -------------------------------------------------------------------- */
 
@@ -412,12 +412,12 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
     const char* pszEncoding = strstr(szPtr, "encoding=");
     if (pszEncoding)
         bExpatCompatibleEncoding = (pszEncoding[9] == '\'' || pszEncoding[9] == '"') &&
-                                    (EQUALN(pszEncoding + 10, "UTF-8", 5) ||
-                                    EQUALN(pszEncoding + 10, "ISO-8859-15", 11) ||
-                                    (EQUALN(pszEncoding + 10, "ISO-8859-1", 10) &&
+                                    (STARTS_WITH_CI(pszEncoding + 10, "UTF-8") ||
+                                    STARTS_WITH_CI(pszEncoding + 10, "ISO-8859-15") ||
+                                    (STARTS_WITH_CI(pszEncoding + 10, "ISO-8859-1") &&
                                         pszEncoding[20] == pszEncoding[9])) ;
     else
-        bExpatCompatibleEncoding = TRUE; /* utf-8 is the default */
+        bExpatCompatibleEncoding = true; /* utf-8 is the default */
 
     bHas3D = strstr(szPtr, "srsDimension=\"3\"") != NULL || strstr(szPtr, "<gml:Z>") != NULL;
 
@@ -428,7 +428,7 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
     {
         if( fpToClose )
             VSIFCloseL( fpToClose );
-        return FALSE;
+        return false;
     }
 
     /* Now we definitely own the file descriptor */
@@ -449,8 +449,8 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
     }
     if (pszFeatureCollection)
     {
-        bExposeGMLId = TRUE;
-        bIsWFS = TRUE;
+        bExposeGMLId = true;
+        bIsWFS = true;
         const char* pszNumberOfFeatures = strstr(szPtr, "numberOfFeatures=");
         if (pszNumberOfFeatures)
         {
@@ -474,13 +474,13 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
             }
         }
     }
-    else if (strncmp(pszFilename, "/vsimem/tempwfs_", strlen("/vsimem/tempwfs_")) == 0)
+    else if (STARTS_WITH(pszFilename, "/vsimem/tempwfs_"))
     {
         /* http://regis.intergraph.com/wfs/dcmetro/request.asp? returns a <G:FeatureCollection> */
         /* Who knows what servers can return ? Ok, so when in the context of the WFS driver */
         /* always expose the gml:id to avoid later crashes */
-        bExposeGMLId = TRUE;
-        bIsWFS = TRUE;
+        bExposeGMLId = true;
+        bIsWFS = true;
     }
     else
     {
@@ -493,12 +493,12 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
     const char* pszExposeGMLId = CSLFetchNameValueDef(poOpenInfo->papszOpenOptions,
         "EXPOSE_GML_ID", CPLGetConfigOption("GML_EXPOSE_GML_ID", NULL));
     if (pszExposeGMLId)
-        bExposeGMLId = CSLTestBoolean(pszExposeGMLId);
+        bExposeGMLId = CPLTestBool(pszExposeGMLId);
 
     const char* pszExposeFid = CSLFetchNameValueDef(poOpenInfo->papszOpenOptions,
         "EXPOSE_FID", CPLGetConfigOption("GML_EXPOSE_FID", NULL));
     if (pszExposeFid)
-        bExposeFid = CSLTestBoolean(pszExposeFid);
+        bExposeFid = CPLTestBool(pszExposeFid);
 
     bHintConsiderEPSGAsURN = strstr(szPtr, "xmlns:fme=\"http://www.safe.com/gml/fme\"") != NULL;
 
@@ -507,8 +507,8 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
     {
         if( strstr(szPtr, "http://xml.nls.fi/XML/Namespace/Maastotietojarjestelma/SiirtotiedostonMalli/2011-02") == NULL )
             CPLDebug("GML", "Warning: a MTKGML file was detected, but its namespace is unknown");
-        bAnalyzeSRSPerFeature = FALSE;
-        bUseGlobalSRSName = TRUE;
+        bAnalyzeSRSPerFeature = false;
+        bUseGlobalSRSName = true;
         if( !ExtractSRSName(szPtr, szSRSName, sizeof(szSRSName)) )
             strcpy(szSRSName, "EPSG:3067");
     }
@@ -517,15 +517,15 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
     if (pszSchemaLocation)
         pszSchemaLocation += strlen("schemaLocation=");
 
-    if (strncmp(pszFilename, "/vsicurl_streaming/", strlen("/vsicurl_streaming/")) == 0)
-        bCheckAuxFile = FALSE;
-    else if (strncmp(pszFilename, "/vsicurl/", strlen("/vsicurl/")) == 0 &&
+    if (STARTS_WITH(pszFilename, "/vsicurl_streaming/"))
+        bCheckAuxFile = false;
+    else if (STARTS_WITH(pszFilename, "/vsicurl/") &&
              (strstr(pszFilename, "?SERVICE=") || strstr(pszFilename, "&SERVICE=")) )
-        bCheckAuxFile = FALSE;
+        bCheckAuxFile = false;
 
-    int bIsWFSJointLayer = bIsWFS && strstr(szPtr, "<wfs:Tuple>");
+    bool bIsWFSJointLayer = bIsWFS && strstr(szPtr, "<wfs:Tuple>");
     if( bIsWFSJointLayer )
-        bExposeGMLId = FALSE;
+        bExposeGMLId = false;
 
 /* -------------------------------------------------------------------- */
 /*      We assume now that it is GML.  Instantiate a GMLReader on it.   */
@@ -547,8 +547,8 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
         CPLDebug("GML", "Unrecognized value for GML_READ_MODE configuration option.");
     }
 
-    m_bInvertAxisOrderIfLatLong = 
-        CSLTestBoolean(CSLFetchNameValueDef(poOpenInfo->papszOpenOptions,
+    m_bInvertAxisOrderIfLatLong =
+        CPLTestBool(CSLFetchNameValueDef(poOpenInfo->papszOpenOptions,
             "INVERT_AXIS_ORDER_IF_LAT_LONG",
             CPLGetConfigOption("GML_INVERT_AXIS_ORDER_IF_LAT_LONG", "YES")));
 
@@ -557,31 +557,31 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
             "CONSIDER_EPSG_AS_URN",
             CPLGetConfigOption("GML_CONSIDER_EPSG_AS_URN", "AUTO"));
     if( !EQUAL(pszConsiderEPSGAsURN, "AUTO") )
-        m_bConsiderEPSGAsURN = CSLTestBoolean(pszConsiderEPSGAsURN);
+        m_bConsiderEPSGAsURN = CPLTestBool(pszConsiderEPSGAsURN);
     else if (bHintConsiderEPSGAsURN)
     {
         /* GML produced by FME (at least CanVec GML) seem to honour EPSG axis ordering */
         CPLDebug("GML", "FME-produced GML --> consider that GML_CONSIDER_EPSG_AS_URN is set to YES");
-        m_bConsiderEPSGAsURN = TRUE;
+        m_bConsiderEPSGAsURN = true;
     }
     else
-        m_bConsiderEPSGAsURN = FALSE;
+        m_bConsiderEPSGAsURN = false;
 
-    m_bGetSecondaryGeometryOption = CSLTestBoolean(CPLGetConfigOption("GML_GET_SECONDARY_GEOM", "NO"));
+    m_bGetSecondaryGeometryOption = CPLTestBool(CPLGetConfigOption("GML_GET_SECONDARY_GEOM", "NO"));
 
     /* EXPAT is faster than Xerces, so when it is safe to use it, use it ! */
     /* The only interest of Xerces is for rare encodings that Expat doesn't handle */
     /* but UTF-8 is well handled by Expat */
-    int bUseExpatParserPreferably = bExpatCompatibleEncoding;
+    bool bUseExpatParserPreferably = bExpatCompatibleEncoding;
 
     /* Override default choice */
     const char* pszGMLParser = CPLGetConfigOption("GML_PARSER", NULL);
     if (pszGMLParser)
     {
         if (EQUAL(pszGMLParser, "EXPAT"))
-            bUseExpatParserPreferably = TRUE;
+            bUseExpatParserPreferably = true;
         else if (EQUAL(pszGMLParser, "XERCES"))
-            bUseExpatParserPreferably = FALSE;
+            bUseExpatParserPreferably = false;
     }
 
     poReader = CreateGMLReader( bUseExpatParserPreferably,
@@ -590,22 +590,22 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
                                 m_bGetSecondaryGeometryOption );
     if( poReader == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "File %s appears to be GML but the GML reader can't\n"
-                  "be instantiated, likely because Xerces or Expat support wasn't\n"
-                  "configured in.", 
+                  "be instantiated, likely because Xerces or Expat support was\n"
+                  "not configured in.",
                   pszFilename );
         VSIFCloseL( fp );
-        return FALSE;
+        return false;
     }
 
     poReader->SetSourceFile( pszFilename );
     ((GMLReader*)poReader)->SetIsWFSJointLayer(bIsWFSJointLayer);
-    bEmptyAsNull = CSLFetchBoolean(poOpenInfo->papszOpenOptions, "EMPTY_AS_NULL", TRUE);
+    bEmptyAsNull = CPL_TO_BOOL(CSLFetchBoolean(poOpenInfo->papszOpenOptions, "EMPTY_AS_NULL", TRUE));
     ((GMLReader*)poReader)->SetEmptyAsNull(bEmptyAsNull);
     ((GMLReader*)poReader)->SetReportAllAttributes(
-        CSLFetchBoolean(poOpenInfo->papszOpenOptions, "GML_ATTRIBUTES_TO_OGR_FIELDS",
-            CSLTestBoolean(CPLGetConfigOption("GML_ATTRIBUTES_TO_OGR_FIELDS", "NO"))));
+        CPL_TO_BOOL(CSLFetchBoolean(poOpenInfo->papszOpenOptions, "GML_ATTRIBUTES_TO_OGR_FIELDS",
+            CPLTestBool(CPLGetConfigOption("GML_ATTRIBUTES_TO_OGR_FIELDS", "NO")))));
 
 /* -------------------------------------------------------------------- */
 /*      Find <gml:description>, <gml:name> and <gml:boundedBy>          */
@@ -623,16 +623,16 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
 
     char *pszXlinkResolvedFilename = NULL;
     const char *pszOption = CPLGetConfigOption("GML_SAVE_RESOLVED_TO", NULL);
-    int bResolve = TRUE;
-    int bHugeFile = FALSE;
-    if( pszOption != NULL && EQUALN( pszOption, "SAME", 4 ) )
+    bool bResolve = true;
+    bool bHugeFile = false;
+    if( pszOption != NULL && STARTS_WITH_CI(pszOption, "SAME") )
     {
         // "SAME" will overwrite the existing gml file
         pszXlinkResolvedFilename = CPLStrdup( pszFilename );
     }
     else if( pszOption != NULL &&
              CPLStrnlen( pszOption, 5 ) >= 5 &&
-             EQUALN( pszOption - 4 + strlen( pszOption ), ".gml", 4 ) )
+             STARTS_WITH_CI(pszOption - 4 + strlen( pszOption ), ".gml") )
     {
         // Any string ending with ".gml" will try and write to it
         pszXlinkResolvedFilename = CPLStrdup( pszOption );
@@ -648,18 +648,18 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
         VSIStatBufL sResStatBuf, sGMLStatBuf;
         if( bCheckAuxFile && VSIStatL( pszXlinkResolvedFilename, &sResStatBuf ) == 0 )
         {
-            VSIStatL( pszFilename, &sGMLStatBuf );
-            if( sGMLStatBuf.st_mtime > sResStatBuf.st_mtime )
+            if( VSIStatL( pszFilename, &sGMLStatBuf ) == 0 &&
+                sGMLStatBuf.st_mtime > sResStatBuf.st_mtime )
             {
-                CPLDebug( "GML", 
+                CPLDebug( "GML",
                           "Found %s but ignoring because it appears\n"
-                          "be older than the associated GML file.", 
+                          "be older than the associated GML file.",
                           pszXlinkResolvedFilename );
             }
             else
             {
                 poReader->SetSourceFile( pszXlinkResolvedFilename );
-                bResolve = FALSE;
+                bResolve = false;
             }
         }
     }
@@ -668,44 +668,44 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
                                                     "ALL");
     char **papszSkip = NULL;
     if( EQUAL( pszSkipOption, "ALL" ) )
-        bResolve = FALSE;
+        bResolve = false;
     else if( EQUAL( pszSkipOption, "HUGE" ) )//exactly as NONE, but intended for HUGE files
-        bHugeFile = TRUE;
+        bHugeFile = true;
     else if( !EQUAL( pszSkipOption, "NONE" ) )//use this to resolve everything
         papszSkip = CSLTokenizeString2( pszSkipOption, ",",
                                            CSLT_STRIPLEADSPACES |
                                            CSLT_STRIPENDSPACES );
-    int         bHaveSchema = FALSE;
-    int         bSchemaDone = FALSE;
- 
+    bool        bHaveSchema = false;
+    bool        bSchemaDone = false;
+
 /* -------------------------------------------------------------------- */
 /*      Is some GML Feature Schema (.gfs) TEMPLATE required ?           */
 /* -------------------------------------------------------------------- */
-    const char *pszGFSTemplateName = 
+    const char *pszGFSTemplateName =
         CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "GFS_TEMPLATE",
                 CPLGetConfigOption( "GML_GFS_TEMPLATE", NULL));
     if( pszGFSTemplateName != NULL )
     {
         /* attempting to load the GFS TEMPLATE */
         bHaveSchema = poReader->LoadClasses( pszGFSTemplateName );
-    }	
+    }
 
     if( bResolve )
     {
         if ( bHugeFile )
         {
-            bSchemaDone = TRUE;
-            int bSqliteIsTempFile =
-                CSLTestBoolean(CPLGetConfigOption( "GML_HUGE_TEMPFILE", "YES"));
+            bSchemaDone = true;
+            bool bSqliteIsTempFile =
+                CPLTestBool(CPLGetConfigOption( "GML_HUGE_TEMPFILE", "YES"));
             int iSqliteCacheMB = atoi(CPLGetConfigOption( "OGR_SQLITE_CACHE", "0"));
             if( poReader->HugeFileResolver( pszXlinkResolvedFilename,
-                                            bSqliteIsTempFile, 
-                                            iSqliteCacheMB ) == FALSE )
+                                            bSqliteIsTempFile,
+                                            iSqliteCacheMB ) == false )
             {
                 // we assume an errors have been reported.
                 VSIFCloseL(fp);
                 CPLFree( pszXlinkResolvedFilename );
-                return FALSE;
+                return false;
             }
         }
         else
@@ -737,12 +737,12 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
         if( !poReader->PrescanForTemplate() )
         {
             // we assume an errors have been reported.
-            return FALSE;
+            return false;
         }
     }
 
     CPLString osGFSFilename = CPLResetExtension( pszFilename, "gfs" );
-    if (strncmp(osGFSFilename, "/vsigzip/", strlen("/vsigzip/")) == 0)
+    if (STARTS_WITH(osGFSFilename, "/vsigzip/"))
         osGFSFilename = osGFSFilename.substr(strlen("/vsigzip/"));
 
 /* -------------------------------------------------------------------- */
@@ -754,12 +754,12 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
         if( bCheckAuxFile && VSIStatL( osGFSFilename, &sGFSStatBuf ) == 0 )
         {
             VSIStatBufL sGMLStatBuf;
-            VSIStatL( pszFilename, &sGMLStatBuf );
-            if( sGMLStatBuf.st_mtime > sGFSStatBuf.st_mtime )
+            if( VSIStatL( pszFilename, &sGMLStatBuf ) == 0 &&
+                sGMLStatBuf.st_mtime > sGFSStatBuf.st_mtime )
             {
-                CPLDebug( "GML", 
+                CPLDebug( "GML",
                           "Found %s but ignoring because it appears\n"
-                          "be older than the associated GML file.", 
+                          "be older than the associated GML file.",
                           osGFSFilename.c_str() );
             }
             else
@@ -767,7 +767,6 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
                 bHaveSchema = poReader->LoadClasses( osGFSFilename );
                 if (bHaveSchema)
                 {
-                    const char *pszXSDFilenameTmp;
                     pszXSDFilenameTmp = CPLResetExtension( pszFilename, "xsd" );
                     if( VSIStatExL( pszXSDFilenameTmp, &sGMLStatBuf,
                                     VSI_STAT_EXISTS_FLAG ) == 0 )
@@ -786,7 +785,7 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
 /*      schemaLocation in the GML feature collection but for now we     */
 /*      just hopes it is in the same director with the same name.       */
 /* -------------------------------------------------------------------- */
-    int bHasFoundXSD = FALSE;
+    bool bHasFoundXSD = false;
 
     if( !bHaveSchema )
     {
@@ -798,16 +797,16 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
             osXSDFilename = CPLResetExtension( pszFilename, "xsd" );
             if( bCheckAuxFile && VSIStatExL( osXSDFilename, &sXSDStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 )
             {
-                bHasFoundXSD = TRUE;
+                bHasFoundXSD = true;
             }
         }
         else
         {
-            if ( strncmp(osXSDFilename, "http://", 7) == 0 ||
-                 strncmp(osXSDFilename, "https://", 8) == 0 ||
+            if ( STARTS_WITH(osXSDFilename, "http://") ||
+                 STARTS_WITH(osXSDFilename, "https://") ||
                  VSIStatExL( osXSDFilename, &sXSDStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 )
             {
-                bHasFoundXSD = TRUE;
+                bHasFoundXSD = true;
             }
         }
 
@@ -834,18 +833,18 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
                         strstr(szHeader, pszURIToFind) != NULL )
                     {
                         if( oNamespace.bUseGlobalSRSName )
-                            bUseGlobalSRSName = TRUE;
-                        
+                            bUseGlobalSRSName = true;
+
                         for( size_t iTypename = 0;
                                     iTypename < oNamespace.aoFeatureTypes.size();
                                     iTypename ++ )
                         {
                             const char* pszElementToFind = NULL;
-                            
+
                             GMLRegistryFeatureType& oFeatureType =
                                         oNamespace.aoFeatureTypes[iTypename];
-                            
-                            if ( oFeatureType.osElementValue.size() ) 
+
+                            if ( oFeatureType.osElementValue.size() )
                                 pszElementToFind = CPLSPrintf("%s:%s>%s",
                                                               oNamespace.osPrefix.c_str(),
                                                               oFeatureType.osElementName.c_str(),
@@ -863,15 +862,15 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
                                 if( oFeatureType.osSchemaLocation.size() )
                                 {
                                     osXSDFilename = oFeatureType.osSchemaLocation;
-                                    if( strncmp(osXSDFilename, "http://", 7) == 0 ||
-                                        strncmp(osXSDFilename, "https://", 8) == 0 ||
+                                    if( STARTS_WITH(osXSDFilename, "http://") ||
+                                        STARTS_WITH(osXSDFilename, "https://") ||
                                         VSIStatExL( osXSDFilename, &sXSDStatBuf,
                                                     VSI_STAT_EXISTS_FLAG ) == 0 )
                                     {
-                                        bHasFoundXSD = TRUE;
-                                        bHaveSchema = TRUE;
+                                        bHasFoundXSD = true;
+                                        bHaveSchema = true;
                                         CPLDebug("GML", "Found %s for %s:%s in registry",
-                                                osXSDFilename.c_str(), 
+                                                osXSDFilename.c_str(),
                                                 oNamespace.osPrefix.c_str(),
                                                 oFeatureType.osElementName.c_str());
                                     }
@@ -887,7 +886,7 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
                                     if( bHaveSchema )
                                     {
                                         CPLDebug("GML", "Found %s for %s:%s in registry",
-                                                oFeatureType.osGFSSchemaLocation.c_str(), 
+                                                oFeatureType.osGFSSchemaLocation.c_str(),
                                                 oNamespace.osPrefix.c_str(),
                                                 oFeatureType.osElementName.c_str());
                                     }
@@ -902,7 +901,7 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
         }
 
         /* For WFS, try to fetch the application schema */
-        if( bIsWFS && !bHaveSchema && pszSchemaLocation != NULL && 
+        if( bIsWFS && !bHaveSchema && pszSchemaLocation != NULL &&
             (pszSchemaLocation[0] == '\'' || pszSchemaLocation[0] == '"') &&
              strchr(pszSchemaLocation + 1, pszSchemaLocation[0]) != NULL )
         {
@@ -939,14 +938,14 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
                             if (!bHasFoundXSD && CPLHTTPEnabled() &&
                                 CSLFetchBoolean(poOpenInfo->papszOpenOptions,
                                     "DOWNLOAD_SCHEMA",
-                                    CSLTestBoolean(CPLGetConfigOption("GML_DOWNLOAD_WFS_SCHEMA", "YES"))) )
+                                    CPLTestBool(CPLGetConfigOption("GML_DOWNLOAD_WFS_SCHEMA", "YES"))) )
                             {
                                 CPLHTTPResult* psResult = CPLHTTPFetch(pszEscapedURL, NULL);
                                 if (psResult)
                                 {
                                     if (psResult->nStatus == 0 && psResult->pabyData != NULL)
                                     {
-                                        bHasFoundXSD = TRUE;
+                                        bHasFoundXSD = true;
                                         osXSDFilename =
                                             CPLSPrintf("/vsimem/tmp_gml_xsd_%p.xsd", this);
                                         VSILFILE* fpMem = VSIFileFromMemBuffer(
@@ -968,52 +967,52 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
             CPLFree(pszSchemaLocationTmp1);
         }
 
-        int bHasFeatureProperties = FALSE;
+        bool bHasFeatureProperties = false;
         if( bHasFoundXSD )
         {
             std::vector<GMLFeatureClass*> aosClasses;
-            int bFullyUnderstood = FALSE;
+            bool bFullyUnderstood = false;
             bHaveSchema = GMLParseXSD( osXSDFilename, aosClasses, bFullyUnderstood );
-            
+
             if( bHaveSchema && !bFullyUnderstood && bIsWFSJointLayer )
             {
                 CPLDebug("GML", "Schema found, but only partially understood. Cannot be used in a WFS join context");
 
-                std::vector<GMLFeatureClass*>::const_iterator iter = aosClasses.begin();
-                std::vector<GMLFeatureClass*>::const_iterator eiter = aosClasses.end();
-                while (iter != eiter)
+                std::vector<GMLFeatureClass*>::const_iterator oIter = aosClasses.begin();
+                std::vector<GMLFeatureClass*>::const_iterator oEndIter = aosClasses.end();
+                while (oIter != oEndIter)
                 {
-                    GMLFeatureClass* poClass = *iter;
+                    GMLFeatureClass* poClass = *oIter;
 
                     delete poClass;
-                    iter ++;
+                    oIter ++;
                 }
                 aosClasses.resize(0);
-                bHaveSchema = FALSE;
+                bHaveSchema = false;
             }
 
             if( bHaveSchema )
             {
                 CPLDebug("GML", "Using %s", osXSDFilename.c_str());
-                std::vector<GMLFeatureClass*>::const_iterator iter = aosClasses.begin();
-                std::vector<GMLFeatureClass*>::const_iterator eiter = aosClasses.end();
-                while (iter != eiter)
+                std::vector<GMLFeatureClass*>::const_iterator oIter = aosClasses.begin();
+                std::vector<GMLFeatureClass*>::const_iterator oEndIter = aosClasses.end();
+                while (oIter != oEndIter)
                 {
-                    GMLFeatureClass* poClass = *iter;
+                    GMLFeatureClass* poClass = *oIter;
 
                     if( poClass->HasFeatureProperties() )
                     {
-                        bHasFeatureProperties = TRUE;
+                        bHasFeatureProperties = true;
                         break;
                     }
-                    iter ++;
+                    oIter ++;
                 }
 
-                iter = aosClasses.begin();
-                while (iter != eiter)
+                oIter = aosClasses.begin();
+                while (oIter != oEndIter)
                 {
-                    GMLFeatureClass* poClass = *iter;
-                    iter ++;
+                    GMLFeatureClass* poClass = *oIter;
+                    oIter ++;
 
                     /* We have no way of knowing if the geometry type is 25D */
                     /* when examining the xsd only, so if there was a hint */
@@ -1024,20 +1023,20 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
                             wkbSetZ((OGRwkbGeometryType)poClass->GetGeometryProperty(0)->GetType()));
                     }
 
-                    int bAddClass = TRUE;
+                    bool bAddClass = true;
                     /* If typenames are declared, only register the matching classes, in case */
                     /* the XSD contains more layers, but not if feature classes contain */
                     /* feature properties, in which case we will have embedded features that */
                     /* will be reported as top-level features */
                     if( papszTypeNames != NULL && !bHasFeatureProperties )
                     {
-                        bAddClass = FALSE;
+                        bAddClass = false;
                         char** papszIter = papszTypeNames;
                         while (*papszIter && !bAddClass)
                         {
                             const char* pszTypeName = *papszIter;
                             if (strcmp(pszTypeName, poClass->GetName()) == 0)
-                                bAddClass = TRUE;
+                                bAddClass = true;
                             papszIter ++;
                         }
 
@@ -1055,7 +1054,7 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
                                     if (strcmp(pszTypeName, poClass->GetName()) == 0)
                                     {
                                         poClass->SetName(pszTypeName);
-                                        bAddClass = TRUE;
+                                        bAddClass = true;
                                     }
                                 }
                                 papszIter ++;
@@ -1070,7 +1069,7 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
                         delete poClass;
                 }
 
-                poReader->SetClassListLocked( TRUE );
+                poReader->SetClassListLocked( true );
             }
         }
 
@@ -1091,7 +1090,7 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
             /* Sometimes the returned schema contains only <xs:include> that we don't resolve */
             /* so ignore it */
             else if (poReader->GetClassCount() == 0)
-                bHaveSchema = FALSE;
+                bHaveSchema = false;
         }
 
         CSLDestroy(papszTypeNames);
@@ -1105,12 +1104,12 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
     if( !bHaveSchema ||
         CSLFetchBoolean(poOpenInfo->papszOpenOptions, "FORCE_SRS_DETECTION", FALSE) )
     {
-        int bOnlyDetectSRS = bHaveSchema;
-        if( !poReader->PrescanForSchema( TRUE, bAnalyzeSRSPerFeature,
+        bool bOnlyDetectSRS = bHaveSchema;
+        if( !poReader->PrescanForSchema( true, bAnalyzeSRSPerFeature,
                                          bOnlyDetectSRS ) )
         {
             // we assume an errors have been reported.
-            return FALSE;
+            return false;
         }
         if( !bHaveSchema )
         {
@@ -1139,25 +1138,25 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
 /*      can't ... could be read-only directory or something.            */
 /* -------------------------------------------------------------------- */
     if( !bHaveSchema && !poReader->HasStoppedParsing() &&
-        !EQUALN(pszFilename, "/vsitar/", strlen("/vsitar/")) &&
-        !EQUALN(pszFilename, "/vsizip/", strlen("/vsizip/")) &&
-        !EQUALN(pszFilename, "/vsigzip/vsi", strlen("/vsigzip/vsi")) &&
-        !EQUALN(pszFilename, "/vsigzip//vsi", strlen("/vsigzip//vsi")) &&
-        !EQUALN(pszFilename, "/vsicurl/", strlen("/vsicurl/")) &&
-        !EQUALN(pszFilename, "/vsicurl_streaming/", strlen("/vsicurl_streaming/")))
+        !STARTS_WITH_CI(pszFilename, "/vsitar/") &&
+        !STARTS_WITH_CI(pszFilename, "/vsizip/") &&
+        !STARTS_WITH_CI(pszFilename, "/vsigzip/vsi") &&
+        !STARTS_WITH_CI(pszFilename, "/vsigzip//vsi") &&
+        !STARTS_WITH_CI(pszFilename, "/vsicurl/") &&
+        !STARTS_WITH_CI(pszFilename, "/vsicurl_streaming/"))
     {
-        VSILFILE    *fp = NULL;
+        VSILFILE    *l_fp = NULL;
 
         VSIStatBufL sGFSStatBuf;
         if( VSIStatExL( osGFSFilename, &sGFSStatBuf, VSI_STAT_EXISTS_FLAG ) != 0
-            && (fp = VSIFOpenL( osGFSFilename, "wt" )) != NULL )
+            && (l_fp = VSIFOpenL( osGFSFilename, "wt" )) != NULL )
         {
-            VSIFCloseL( fp );
+            VSIFCloseL( l_fp );
             poReader->SaveClasses( osGFSFilename );
         }
         else
         {
-            CPLDebug("GML", 
+            CPLDebug("GML",
                      "Not saving %s files already exists or can't be created.",
                      osGFSFilename.c_str() );
         }
@@ -1185,17 +1184,17 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
     }
 
     if (bIsWFS && poReader->GetClassCount() == 1)
-        bUseGlobalSRSName = TRUE;
+        bUseGlobalSRSName = true;
 
     while( nLayers < poReader->GetClassCount() )
     {
         papoLayers[nLayers] = TranslateGMLSchema(poReader->GetClass(nLayers));
         nLayers++;
     }
-    
 
-    
-    return TRUE;
+
+
+    return true;
 }
 
 /************************************************************************/
@@ -1216,6 +1215,7 @@ void OGRGMLDataSource::BuildJointClassFromXSD()
     {
         GMLFeatureClass* poClass = poReader->GetClass(i);
 
+        {
         CPLString osPropertyName;
         osPropertyName.Printf("%s.%s", poClass->GetName(), "gml_id");
         GMLPropertyDefn* poNewProperty = new GMLPropertyDefn( osPropertyName );
@@ -1225,6 +1225,7 @@ void OGRGMLDataSource::BuildJointClassFromXSD()
         poNewProperty->SetSrcElement(osSrcElement);
         poNewProperty->SetType(GMLPT_String);
         poJointClass->AddProperty(poNewProperty);
+        }
 
         int iField;
         for( iField = 0; iField < poClass->GetPropertyCount(); iField++ )
@@ -1261,7 +1262,7 @@ void OGRGMLDataSource::BuildJointClassFromXSD()
             poJointClass->AddGeometryProperty(poNewProperty);
         }
     }
-    poJointClass->SetSchemaLocked(TRUE);
+    poJointClass->SetSchemaLocked(true);
 
     poReader->ClearClasses();
     poReader->AddClass( poJointClass );
@@ -1279,18 +1280,18 @@ void OGRGMLDataSource::BuildJointClassFromScannedSchema()
     GMLFeatureClass *poClass = poReader->GetClass(0);
     CPLString osJointClassName = "join";
 
-    int iField, iSubClass;
-    for( iField = 0; iField < poClass->GetPropertyCount(); iField ++ )
+    for( int iField = 0; iField < poClass->GetPropertyCount(); iField ++ )
     {
         GMLPropertyDefn* poProp = poClass->GetProperty(iField);
         CPLString osPrefix(poProp->GetName());
         size_t iPos = osPrefix.find('.');
         if( iPos != std::string::npos )
             osPrefix.resize(iPos);
+        int iSubClass;
         for( iSubClass = 0; iSubClass < (int)aapoProps.size(); iSubClass ++ )
         {
             CPLString osPrefixClass(aapoProps[iSubClass][0]->GetName());
-            size_t iPos = osPrefixClass.find('.');
+            iPos = osPrefixClass.find('.');
             if( iPos != std::string::npos )
                 osPrefixClass.resize(iPos);
             if( osPrefix == osPrefixClass )
@@ -1309,13 +1310,13 @@ void OGRGMLDataSource::BuildJointClassFromScannedSchema()
 
     poClass->StealProperties();
     std::vector< std::pair< CPLString, std::vector<GMLGeometryPropertyDefn*> > > aapoGeomProps;
-    for( iSubClass = 0; iSubClass < (int)aapoProps.size(); iSubClass ++ )
+    for( int iSubClass = 0; iSubClass < (int)aapoProps.size(); iSubClass ++ )
     {
         CPLString osPrefixClass(aapoProps[iSubClass][0]->GetName());
         size_t iPos = osPrefixClass.find('.');
         if( iPos != std::string::npos )
             osPrefixClass.resize(iPos);
-        aapoGeomProps.push_back( std::pair< CPLString, std::vector<GMLGeometryPropertyDefn*> > 
+        aapoGeomProps.push_back( std::pair< CPLString, std::vector<GMLGeometryPropertyDefn*> >
                 (osPrefixClass, std::vector<GMLGeometryPropertyDefn*>()) );
         for( int iField = 0; iField < (int)aapoProps[iSubClass].size(); iField ++ )
         {
@@ -1325,7 +1326,7 @@ void OGRGMLDataSource::BuildJointClassFromScannedSchema()
     aapoProps.resize(0);
 
     // Reorder geometry fields too
-    for( iField = 0; iField < poClass->GetGeometryPropertyCount(); iField ++ )
+    for( int iField = 0; iField < poClass->GetGeometryPropertyCount(); iField ++ )
     {
         GMLGeometryPropertyDefn* poProp = poClass->GetGeometryProperty(iField);
         CPLString osPrefix(poProp->GetName());
@@ -1344,9 +1345,9 @@ void OGRGMLDataSource::BuildJointClassFromScannedSchema()
         aapoGeomProps[iSubClass].second.push_back(poProp);
     }
     poClass->StealGeometryProperties();
-    for( iSubClass = 0; iSubClass < (int)aapoGeomProps.size(); iSubClass ++ )
+    for( int iSubClass = 0; iSubClass < (int)aapoGeomProps.size(); iSubClass ++ )
     {
-        for( iField = 0; iField < (int)aapoGeomProps[iSubClass].second.size(); iField ++ )
+        for( int iField = 0; iField < (int)aapoGeomProps[iSubClass].second.size(); iField ++ )
         {
             poClass->AddGeometryProperty(aapoGeomProps[iSubClass].second[iField]);
         }
@@ -1423,7 +1424,7 @@ OGRGMLLayer *OGRGMLDataSource::TranslateGMLSchema( GMLFeatureClass *poClass )
 
     /* Report a COMPD_CS only if GML_REPORT_COMPD_CS is explicitly set to TRUE */
     if( poSRS != NULL &&
-        !CSLTestBoolean(CPLGetConfigOption("GML_REPORT_COMPD_CS", "FALSE")) )
+        !CPLTestBool(CPLGetConfigOption("GML_REPORT_COMPD_CS", "FALSE")) )
     {
         OGR_SRSNode *poCOMPD_CS = poSRS->GetAttrNode( "COMPD_CS" );
         if( poCOMPD_CS != NULL )
@@ -1439,7 +1440,7 @@ OGRGMLLayer *OGRGMLDataSource::TranslateGMLSchema( GMLFeatureClass *poClass )
     }
 
 
-    poLayer = new OGRGMLLayer( poClass->GetName(), FALSE, this );
+    poLayer = new OGRGMLLayer( poClass->GetName(), false, this );
 
 /* -------------------------------------------------------------------- */
 /*      Added attributes (properties).                                  */
@@ -1502,9 +1503,9 @@ OGRGMLLayer *OGRGMLDataSource::TranslateGMLSchema( GMLFeatureClass *poClass )
             eFType = OFTStringList;
         else
             eFType = OFTString;
-        
+
         OGRFieldDefn oField( poProperty->GetName(), eFType );
-        if ( EQUALN(oField.GetNameRef(), "ogr:", 4) )
+        if ( STARTS_WITH_CI(oField.GetNameRef(), "ogr:") )
           oField.SetName(poProperty->GetName()+4);
         if( poProperty->GetWidth() > 0 )
             oField.SetWidth( poProperty->GetWidth() );
@@ -1513,9 +1514,9 @@ OGRGMLLayer *OGRGMLDataSource::TranslateGMLSchema( GMLFeatureClass *poClass )
         if( poProperty->GetType() == GMLPT_Boolean ||
             poProperty->GetType() == GMLPT_BooleanList )
             oField.SetSubType(OFSTBoolean);
-        else if( poProperty->GetType() == GMLPT_Short) 
+        else if( poProperty->GetType() == GMLPT_Short)
             oField.SetSubType(OFSTInt16);
-        else if( poProperty->GetType() == GMLPT_Float) 
+        else if( poProperty->GetType() == GMLPT_Float)
             oField.SetSubType(OFSTFloat32);
         if( !bEmptyAsNull )
             oField.SetNullable(poProperty->IsNullable() );
@@ -1545,14 +1546,14 @@ const char *OGRGMLDataSource::GetGlobalSRSName()
 /*                               Create()                               */
 /************************************************************************/
 
-int OGRGMLDataSource::Create( const char *pszFilename, 
+bool OGRGMLDataSource::Create( const char *pszFilename,
                               char **papszOptions )
 
 {
     if( fpOutput != NULL || poReader != NULL )
     {
-        CPLAssert( FALSE );
-        return FALSE;
+        CPLAssert( false );
+        return false;
     }
 
     if( strcmp(pszFilename,"/dev/stdout") == 0 )
@@ -1570,13 +1571,13 @@ int OGRGMLDataSource::Create( const char *pszFilename,
     bIsOutputGML3Deegree = pszFormat && EQUAL(pszFormat, "GML3Deegree");
     bIsOutputGML32 = pszFormat && EQUAL(pszFormat, "GML3.2");
     if (bIsOutputGML3Deegree || bIsOutputGML32)
-        bIsOutputGML3 = TRUE;
+        bIsOutputGML3 = true;
 
     bIsLongSRSRequired =
-        CSLTestBoolean(CSLFetchNameValueDef(papszCreateOptions, "GML3_LONGSRS", "YES"));
+        CPLTestBool(CSLFetchNameValueDef(papszCreateOptions, "GML3_LONGSRS", "YES"));
 
     bWriteSpaceIndentation =
-        CSLTestBoolean(CSLFetchNameValueDef(papszCreateOptions, "SPACE_INDENTATION", "YES"));
+        CPLTestBool(CSLFetchNameValueDef(papszCreateOptions, "SPACE_INDENTATION", "YES"));
 
 /* -------------------------------------------------------------------- */
 /*      Create the output file.                                         */
@@ -1585,13 +1586,13 @@ int OGRGMLDataSource::Create( const char *pszFilename,
     osFilename = pszName;
 
     if( strcmp(pszFilename,"/vsistdout/") == 0 ||
-        strncmp(pszFilename,"/vsigzip/", 9) == 0 )
+        STARTS_WITH(pszFilename, "/vsigzip/") )
     {
         fpOutput = VSIFOpenL(pszFilename, "wb");
-        bFpOutputIsNonSeekable = TRUE;
-        bFpOutputSingleFile = TRUE;
+        bFpOutputIsNonSeekable = true;
+        bFpOutputSingleFile = true;
     }
-    else if ( strncmp(pszFilename,"/vsizip/", 8) == 0)
+    else if ( STARTS_WITH(pszFilename, "/vsizip/"))
     {
         if (EQUAL(CPLGetExtension(pszFilename), "zip"))
         {
@@ -1600,22 +1601,22 @@ int OGRGMLDataSource::Create( const char *pszFilename,
         }
 
         fpOutput = VSIFOpenL(pszName, "wb");
-        bFpOutputIsNonSeekable = TRUE;
+        bFpOutputIsNonSeekable = true;
     }
     else
         fpOutput = VSIFOpenL( pszFilename, "wb+" );
     if( fpOutput == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Failed to create GML file %s.", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to create GML file %s.",
                   pszFilename );
-        return FALSE;
+        return false;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Write out "standard" header.                                    */
 /* -------------------------------------------------------------------- */
-    PrintLine( fpOutput, "%s", 
+    PrintLine( fpOutput, "%s",
                 "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" );
 
     if (!bFpOutputIsNonSeekable)
@@ -1645,19 +1646,19 @@ int OGRGMLDataSource::Create( const char *pszFilename,
 
     if( pszSchemaURI != NULL )
     {
-        PrintLine( fpOutput, 
+        PrintLine( fpOutput,
               "     xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
-        PrintLine( fpOutput, 
-              "     xsi:schemaLocation=\"%s\"", 
+        PrintLine( fpOutput,
+              "     xsi:schemaLocation=\"%s\"",
                     pszSchemaURI );
     }
     else if( pszSchemaOpt == NULL || EQUAL(pszSchemaOpt,"EXTERNAL") )
     {
         char *pszBasename = CPLStrdup(CPLGetBasename( pszName ));
 
-        PrintLine( fpOutput, 
+        PrintLine( fpOutput,
               "     xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
-        PrintLine( fpOutput, 
+        PrintLine( fpOutput,
               "     xsi:schemaLocation=\"%s %s\"",
                     pszTargetNameSpace,
                     CPLResetExtension( pszBasename, "xsd" ) );
@@ -1678,7 +1679,7 @@ int OGRGMLDataSource::Create( const char *pszFilename,
         PrintLine( fpOutput, "%s",
                     "     xmlns:gml=\"http://www.opengis.net/gml\">" );
 
-    return TRUE;
+    return true;
 }
 
 
@@ -1699,13 +1700,13 @@ void OGRGMLDataSource::WriteTopElements()
         CPLFree(pszTmp);
     }
 
-    const char* pszName = CSLFetchNameValueDef(papszCreateOptions,
+    const char* l_pszName = CSLFetchNameValueDef(papszCreateOptions,
         "NAME", GetMetadataItem("NAME"));
-    if( pszName != NULL )
+    if( l_pszName != NULL )
     {
         if (bWriteSpaceIndentation)
             VSIFPrintfL( fpOutput, "  ");
-        char* pszTmp = CPLEscapeString(pszName, -1, CPLES_XML);
+        char* pszTmp = CPLEscapeString(l_pszName, -1, CPLES_XML);
         PrintLine( fpOutput, "<gml:name>%s</gml:name>", pszTmp );
         CPLFree(pszTmp);
     }
@@ -1767,7 +1768,7 @@ OGRGMLDataSource::ICreateLayer( const char * pszLayerName,
     CPLCleanXMLElementName( pszCleanLayerName );
     if( strcmp(pszCleanLayerName,pszLayerName) != 0 )
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "Layer name '%s' adjusted to '%s' for XML validity.",
                   pszLayerName, pszCleanLayerName );
     }
@@ -1780,7 +1781,7 @@ OGRGMLDataSource::ICreateLayer( const char * pszLayerName,
         WriteTopElements();
         if (poSRS)
             poWriteGlobalSRS = poSRS->Clone();
-        bWriteGlobalSRS = TRUE;
+        bWriteGlobalSRS = true;
     }
     else if( bWriteGlobalSRS )
     {
@@ -1790,13 +1791,13 @@ OGRGMLDataSource::ICreateLayer( const char * pszLayerName,
             {
                 delete poWriteGlobalSRS;
                 poWriteGlobalSRS = NULL;
-                bWriteGlobalSRS = FALSE;
+                bWriteGlobalSRS = false;
             }
         }
         else
         {
             if( poSRS != NULL )
-                bWriteGlobalSRS = FALSE;
+                bWriteGlobalSRS = false;
         }
     }
 
@@ -1805,7 +1806,7 @@ OGRGMLDataSource::ICreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
     OGRGMLLayer *poLayer;
 
-    poLayer = new OGRGMLLayer( pszCleanLayerName, TRUE, this );
+    poLayer = new OGRGMLLayer( pszCleanLayerName, true, this );
     poLayer->GetLayerDefn()->SetGeomType(eType);
     if( eType != wkbNone )
     {
@@ -1813,7 +1814,7 @@ OGRGMLDataSource::ICreateLayer( const char * pszLayerName,
         if( poSRS != NULL )
         {
             /* Clone it since mapogroutput assumes that it can destroys */
-            /* the SRS it has passed to use, instead of deferencing it */
+            /* the SRS it has passed to use, instead of dereferencing it. */
             poSRS = poSRS->Clone();
             poLayer->GetLayerDefn()->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
             poSRS->Dereference();
@@ -1827,7 +1828,7 @@ OGRGMLDataSource::ICreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
     papoLayers = (OGRGMLLayer **)
         CPLRealloc( papoLayers,  sizeof(OGRGMLLayer *) * (nLayers+1) );
-    
+
     papoLayers[nLayers++] = poLayer;
 
     return poLayer;
@@ -1872,7 +1873,7 @@ void OGRGMLDataSource::GrowExtents( OGREnvelope3D *psGeomBounds, int nCoordDimen
 {
     sBoundingRect.Merge( *psGeomBounds );
     if (nCoordDimension == 3)
-        bBBOX3D = TRUE;
+        bBBOX3D = true;
 }
 
 /************************************************************************/
@@ -1898,7 +1899,7 @@ void OGRGMLDataSource::InsertHeader()
 /* -------------------------------------------------------------------- */
     const char *pszSchemaURI = CSLFetchNameValue(papszCreateOptions,
                                                  "XSISCHEMAURI");
-    const char *pszSchemaOpt = CSLFetchNameValue( papszCreateOptions, 
+    const char *pszSchemaOpt = CSLFetchNameValue( papszCreateOptions,
                                                   "XSISCHEMA" );
 
     if( pszSchemaURI != NULL )
@@ -1911,8 +1912,8 @@ void OGRGMLDataSource::InsertHeader()
         fpSchema = VSIFOpenL( pszXSDFilename, "wt" );
         if( fpSchema == NULL )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
-                      "Failed to open file %.500s for schema output.", 
+            CPLError( CE_Failure, CPLE_OpenFailed,
+                      "Failed to open file %.500s for schema output.",
                       pszXSDFilename );
             return;
         }
@@ -1925,7 +1926,7 @@ void OGRGMLDataSource::InsertHeader()
         nSchemaStart = (int) VSIFTellL( fpOutput );
         fpSchema = fpOutput;
     }
-    else                                                               
+    else
         return;
 
 /* ==================================================================== */
@@ -1938,11 +1939,11 @@ void OGRGMLDataSource::InsertHeader()
 /*      Detect if there are fields of List types.                       */
 /* ==================================================================== */
     int iLayer;
-    int bHasListFields = FALSE;
+    bool bHasListFields = false;
 
     for( iLayer = 0; !bHasListFields && iLayer < GetLayerCount(); iLayer++ )
     {
-        OGRFeatureDefn *poFDefn = GetLayer(iLayer)->GetLayerDefn();
+        OGRFeatureDefn *poFDefn = papoLayers[iLayer]->GetLayerDefn();
         for( int iField = 0; !bHasListFields && iField < poFDefn->GetFieldCount(); iField++ )
         {
             OGRFieldDefn *poFieldDefn = poFDefn->GetFieldDefn(iField);
@@ -1952,7 +1953,7 @@ void OGRGMLDataSource::InsertHeader()
                 poFieldDefn->GetType() == OFTRealList ||
                 poFieldDefn->GetType() == OFTStringList )
             {
-                bHasListFields = TRUE;
+                bHasListFields = true;
             }
         } /* next field */
     } /* next layer */
@@ -2137,8 +2138,8 @@ void OGRGMLDataSource::InsertHeader()
 
     for( iLayer = 0; iLayer < GetLayerCount(); iLayer++ )
     {
-        OGRFeatureDefn *poFDefn = GetLayer(iLayer)->GetLayerDefn();
-        
+        OGRFeatureDefn *poFDefn = papoLayers[iLayer]->GetLayerDefn();
+
 /* -------------------------------------------------------------------- */
 /*      Emit initial stuff for a feature type.                          */
 /* -------------------------------------------------------------------- */
@@ -2354,7 +2355,7 @@ void OGRGMLDataSource::InsertHeader()
             else if( poFieldDefn->GetType() == OFTString ||
                      poFieldDefn->GetType() == OFTStringList )
             {
-                PrintLine( fpSchema, "        <xs:element name=\"%s\" nillable=\"true\" minOccurs=\"%d\" maxOccurs=\"%s\">", 
+                PrintLine( fpSchema, "        <xs:element name=\"%s\" nillable=\"true\" minOccurs=\"%d\" maxOccurs=\"%s\">",
                            poFieldDefn->GetNameRef(),
                            nMinOccurs,
                            poFieldDefn->GetType() == OFTStringList ? "unbounded": "1" );
@@ -2370,7 +2371,7 @@ void OGRGMLDataSource::InsertHeader()
             }
             else if( poFieldDefn->GetType() == OFTDate || poFieldDefn->GetType() == OFTDateTime )
             {
-                PrintLine( fpSchema, "        <xs:element name=\"%s\" nillable=\"true\" minOccurs=\"%d\" maxOccurs=\"1\">", 
+                PrintLine( fpSchema, "        <xs:element name=\"%s\" nillable=\"true\" minOccurs=\"%d\" maxOccurs=\"1\">",
                            poFieldDefn->GetNameRef(),
                            nMinOccurs );
                 PrintLine( fpSchema, "          <xs:simpleType>");
@@ -2406,12 +2407,12 @@ void OGRGMLDataSource::InsertHeader()
 /* -------------------------------------------------------------------- */
         int nSchemaSize = (int) VSIFTellL( fpOutput ) - nSchemaStart;
         char *pszSchema = (char *) CPLMalloc(nSchemaSize+1);
-    
+
         VSIFSeekL( fpOutput, nSchemaStart, SEEK_SET );
 
         VSIFReadL( pszSchema, 1, nSchemaSize, fpOutput );
         pszSchema[nSchemaSize] = '\0';
-    
+
 /* -------------------------------------------------------------------- */
 /*      Move file data down by "schema size" bytes from after <?xml>    */
 /*      header so we have room insert the schema.  Move in pretty       */
@@ -2419,20 +2420,19 @@ void OGRGMLDataSource::InsertHeader()
 /* -------------------------------------------------------------------- */
         int nChunkSize = MIN(nSchemaStart-nSchemaInsertLocation,250000);
         char *pszChunk = (char *) CPLMalloc(nChunkSize);
-        int nEndOfUnmovedData = nSchemaStart;
 
-        for( nEndOfUnmovedData = nSchemaStart;
+        for( int nEndOfUnmovedData = nSchemaStart;
              nEndOfUnmovedData > nSchemaInsertLocation; )
         {
-            int nBytesToMove = 
+            int nBytesToMove =
                 MIN(nChunkSize, nEndOfUnmovedData - nSchemaInsertLocation );
 
             VSIFSeekL( fpOutput, nEndOfUnmovedData - nBytesToMove, SEEK_SET );
             VSIFReadL( pszChunk, 1, nBytesToMove, fpOutput );
-            VSIFSeekL( fpOutput, nEndOfUnmovedData - nBytesToMove + nSchemaSize, 
+            VSIFSeekL( fpOutput, nEndOfUnmovedData - nBytesToMove + nSchemaSize,
                       SEEK_SET );
             VSIFWriteL( pszChunk, 1, nBytesToMove, fpOutput );
-        
+
             nEndOfUnmovedData -= nBytesToMove;
         }
 
@@ -2506,14 +2506,14 @@ class OGRGMLSingleFeatureLayer : public OGRLayer
 /*                      OGRGMLSingleFeatureLayer()                      */
 /************************************************************************/
 
-OGRGMLSingleFeatureLayer::OGRGMLSingleFeatureLayer( int nVal )
+OGRGMLSingleFeatureLayer::OGRGMLSingleFeatureLayer( int nValIn )
 {
     poFeatureDefn = new OGRFeatureDefn( "SELECT" );
     poFeatureDefn->Reference();
     OGRFieldDefn oField( "Validates", OFTInteger );
     poFeatureDefn->AddFieldDefn( &oField );
 
-    this->nVal = nVal;
+    this->nVal = nValIn;
     iNextShapeId = 0;
 }
 
@@ -2542,11 +2542,11 @@ OGRLayer * OGRGMLDataSource::ExecuteSQL( const char *pszSQLCommand,
 {
     if (poReader != NULL && EQUAL(pszSQLCommand, "SELECT ValidateSchema()"))
     {
-        int bIsValid = FALSE;
+        bool bIsValid = false;
         if (osXSDFilename.size())
         {
             CPLErrorReset();
-            bIsValid = CPLValidateXML(osFilename, osXSDFilename, NULL);
+            bIsValid = CPL_TO_BOOL(CPLValidateXML(osFilename, osXSDFilename, NULL));
         }
         return new OGRGMLSingleFeatureLayer(bIsValid);
     }
@@ -2567,8 +2567,8 @@ void OGRGMLDataSource::ReleaseResultSet( OGRLayer * poResultsSet )
 /*                          ExtractSRSName()                            */
 /************************************************************************/
 
-static int ExtractSRSName(const char* pszXML, char* szSRSName,
-                          size_t sizeof_szSRSName)
+static bool ExtractSRSName(const char* pszXML, char* szSRSName,
+                           size_t sizeof_szSRSName)
 {
     szSRSName[0] = '\0';
 
@@ -2582,10 +2582,10 @@ static int ExtractSRSName(const char* pszXML, char* szSRSName,
         {
             memcpy(szSRSName, pszSRSName, pszEndQuote - pszSRSName);
             szSRSName[pszEndQuote - pszSRSName] = '\0';
-            return TRUE;
+            return true;
         }
     }
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
@@ -2640,17 +2640,17 @@ void OGRGMLDataSource::FindAndParseTopElements(VSILFILE* fp)
         }
     }
 
-    const char* pszName = strstr(pszXML, "<gml:name");
-    if( pszName )
-        pszName = strchr(pszName, '>');
-    if( pszName )
+    const char* l_pszName = strstr(pszXML, "<gml:name");
+    if( l_pszName )
+        l_pszName = strchr(l_pszName, '>');
+    if( l_pszName )
     {
-        pszName ++;
-        const char* pszEndName = strstr(pszName, "</gml:name>");
+        l_pszName ++;
+        const char* pszEndName = strstr(l_pszName, "</gml:name>");
         if( pszEndName )
         {
-            CPLString osTmp(pszName);
-            osTmp.resize(pszEndName-pszName);
+            CPLString osTmp(l_pszName);
+            osTmp.resize(pszEndName-l_pszName);
             char* pszTmp = CPLUnescapeString(osTmp, NULL, CPLES_XML);
             if( pszTmp )
                 SetMetadataItem("NAME", pszTmp);
@@ -2659,9 +2659,9 @@ void OGRGMLDataSource::FindAndParseTopElements(VSILFILE* fp)
     }
 
     char* pszEndBoundedBy = strstr(pszXML, "</wfs:boundedBy>");
-    int bWFSBoundedBy = FALSE;
+    bool bWFSBoundedBy = false;
     if (pszEndBoundedBy != NULL)
-        bWFSBoundedBy = TRUE;
+        bWFSBoundedBy = true;
     else
         pszEndBoundedBy = strstr(pszXML, "</gml:boundedBy>");
     if (pszStartTag != NULL && pszEndBoundedBy != NULL)
@@ -2729,7 +2729,7 @@ void OGRGMLDataSource::FindAndParseTopElements(VSILFILE* fp)
                 {
                     CPLDebug("GML", "Global SRS = %s", pszSRSName);
 
-                    if (strncmp(pszSRSName, "http://www.opengis.net/gml/srs/epsg.xml#", 40) == 0)
+                    if (STARTS_WITH(pszSRSName, "http://www.opengis.net/gml/srs/epsg.xml#"))
                     {
                         std::string osWork;
                         osWork.assign("EPSG:", 5);
@@ -2782,11 +2782,11 @@ const char* OGRGMLDataSource::GetAppPrefix()
 /*                            RemoveAppPrefix()                         */
 /************************************************************************/
 
-int OGRGMLDataSource::RemoveAppPrefix()
+bool OGRGMLDataSource::RemoveAppPrefix()
 {
-    if( CSLTestBoolean(CSLFetchNameValueDef(
+    if( CPLTestBool(CSLFetchNameValueDef(
             papszCreateOptions, "STRIP_PREFIX", "FALSE")) )
-        return TRUE;
+        return true;
     const char* pszPrefix = GetAppPrefix();
     return( pszPrefix[0] == '\0' );
 }
@@ -2795,10 +2795,10 @@ int OGRGMLDataSource::RemoveAppPrefix()
 /*                        WriteFeatureBoundedBy()                       */
 /************************************************************************/
 
-int OGRGMLDataSource::WriteFeatureBoundedBy()
+bool OGRGMLDataSource::WriteFeatureBoundedBy()
 {
-    return CSLTestBoolean(CSLFetchNameValueDef(
-                    papszCreateOptions, "WRITE_FEATURE_BOUNDED_BY", "TRUE"));
+    return CPLTestBool(CSLFetchNameValueDef(
+        papszCreateOptions, "WRITE_FEATURE_BOUNDED_BY", "TRUE"));
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/gml/ogrgmldriver.cpp b/ogr/ogrsf_frmts/gml/ogrgmldriver.cpp
index f8e4a8d..4ef133c 100644
--- a/ogr/ogrsf_frmts/gml/ogrgmldriver.cpp
+++ b/ogr/ogrsf_frmts/gml/ogrgmldriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgmldriver.cpp 29240 2015-05-24 10:58:38Z rouault $
+ * $Id: ogrgmldriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  OGR
  * Purpose:  OGRGMLDriver implementation
@@ -32,7 +32,7 @@
 #include "cpl_multiproc.h"
 #include "gmlreaderp.h"
 
-CPL_CVSID("$Id: ogrgmldriver.cpp 29240 2015-05-24 10:58:38Z rouault $");
+CPL_CVSID("$Id: ogrgmldriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
 
 /************************************************************************/
 /*                        OGRGMLDriverUnload()                          */
@@ -63,7 +63,7 @@ static int OGRGMLDriverIdentify( GDALOpenInfo* poOpenInfo )
     else
     if ( poOpenInfo->pabyHeader[0] == 0x1f && poOpenInfo->pabyHeader[1] == 0x8b &&
          EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "gz") &&
-         strncmp(poOpenInfo->pszFilename, "/vsigzip/", strlen("/vsigzip/")) != 0 )
+         !STARTS_WITH(poOpenInfo->pszFilename, "/vsigzip/") )
     {
         return -1; /* must be later checked */
     }
@@ -145,22 +145,20 @@ static GDALDataset *OGRGMLDriverCreate( const char * pszName,
 void RegisterOGRGML()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "GML" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "GML" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-
-        poDriver->SetDescription( "GML" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Geography Markup Language (GML)" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gml" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "gml xml" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_gml.html" );
-
-        poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+    GDALDriver  *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "GML" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Geography Markup Language (GML)" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gml" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "gml xml" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_gml.html" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
 "<OpenOptionList>"
 "  <Option name='XSD' type='string' description='Name of the related application schema file (.xsd).'/>"
 "  <Option name='GFS_TEMPLATE' type='string' description='Filename of a .gfs template file to appli.'/>"
@@ -193,7 +191,7 @@ void RegisterOGRGML()
 "  <Option name='REGISTRY' type='string' description='Filename of the registry with application schemas.'/>"
 "</OpenOptionList>" );
 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "  <Option name='XSISCHEMAURI' type='string' description='URI to be inserted as the schema location.'/>"
 "  <Option name='XSISCHEMA' type='string-select' description='where to write a .xsd application schema. INTERNAL should not normally be used' default='EXTERNAL'>"
@@ -212,7 +210,7 @@ void RegisterOGRGML()
 "  </Option>"
 "  <Option name='GML3_LONGSRS' type='boolean' description='Whether to write SRS with \"urn:ogc:def:crs:EPSG::\" prefix with GML3* versions' default='YES'/>"
 "  <Option name='WRITE_FEATURE_BOUNDED_BY' type='boolean' description='Whether to write <gml:boundedBy> element for each feature with GML3* versions' default='YES'/>"
-"  <Option name='SPACE_INDENTATION' type='boolean' description='Whether to indentate the output for readability' default='YES'/>"
+"  <Option name='SPACE_INDENTATION' type='boolean' description='Whether to indent the output for readability' default='YES'/>"
 "  <Option name='SRSDIMENSION_LOC' type='string-select' description='(only valid for FORMAT=GML3xx) Location where to put srsDimension attribute' default='POSLIST'>"
 "    <Value>POSLIST</Value>"
 "    <Value>GEOMETRY</Value>"
@@ -223,19 +221,16 @@ void RegisterOGRGML()
 "  <Option name='DESCRIPTION' type='string' description='Content of GML description element'/>"
 "</CreationOptionList>");
 
-        poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST, "<LayerCreationOptionList/>");
-        
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES, "Integer Integer64 Real String Date DateTime IntegerList Integer64List RealList StringList" );
-        poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_FIELDS, "YES" );
-        poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_GEOMFIELDS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST, "<LayerCreationOptionList/>");
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES, "Integer Integer64 Real String Date DateTime IntegerList Integer64List RealList StringList" );
+    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_FIELDS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_GEOMFIELDS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-        
-        poDriver->pfnOpen = OGRGMLDriverOpen;
-        poDriver->pfnIdentify = OGRGMLDriverIdentify;
-        poDriver->pfnCreate = OGRGMLDriverCreate;
-        poDriver->pfnUnloadDriver = OGRGMLDriverUnload;
+    poDriver->pfnOpen = OGRGMLDriverOpen;
+    poDriver->pfnIdentify = OGRGMLDriverIdentify;
+    poDriver->pfnCreate = OGRGMLDriverCreate;
+    poDriver->pfnUnloadDriver = OGRGMLDriverUnload;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/gml/ogrgmllayer.cpp b/ogr/ogrsf_frmts/gml/ogrgmllayer.cpp
index e757f61..afbd73a 100644
--- a/ogr/ogrsf_frmts/gml/ogrgmllayer.cpp
+++ b/ogr/ogrsf_frmts/gml/ogrgmllayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgmllayer.cpp 28481 2015-02-13 17:11:15Z rouault $
+ * $Id: ogrgmllayer.cpp 33702 2016-03-11 06:20:16Z goatbar $
  *
  * Project:  OGR
  * Purpose:  Implements OGRGMLLayer class.
@@ -36,26 +36,26 @@
 #include "ogr_p.h"
 #include "ogr_api.h"
 
-CPL_CVSID("$Id: ogrgmllayer.cpp 28481 2015-02-13 17:11:15Z rouault $");
+CPL_CVSID("$Id: ogrgmllayer.cpp 33702 2016-03-11 06:20:16Z goatbar $");
 
 /************************************************************************/
 /*                           OGRGMLLayer()                              */
 /************************************************************************/
 
 OGRGMLLayer::OGRGMLLayer( const char * pszName,
-                          int bWriterIn,
+                          bool bWriterIn,
                           OGRGMLDataSource *poDSIn )
 
 {
     iNextGMLId = 0;
     nTotalGMLCount = -1;
-    bInvalidFIDFound = FALSE;
+    bInvalidFIDFound = false;
     pszFIDPrefix = NULL;
-    bFaceHoleNegative = FALSE;
-        
+    bFaceHoleNegative = false;
+
     poDS = poDSIn;
 
-    if ( EQUALN(pszName, "ogr:", 4) )
+    if ( STARTS_WITH_CI(pszName, "ogr:") )
       poFeatureDefn = new OGRFeatureDefn( pszName+4 );
     else
       poFeatureDefn = new OGRFeatureDefn( pszName );
@@ -64,7 +64,7 @@ OGRGMLLayer::OGRGMLLayer( const char * pszName,
     poFeatureDefn->SetGeomType( wkbNone );
 
     bWriter = bWriterIn;
-    bSameSRS = FALSE;
+    bSameSRS = false;
 
 /* -------------------------------------------------------------------- */
 /*      Reader's should get the corresponding GMLFeatureClass and       */
@@ -79,10 +79,10 @@ OGRGMLLayer::OGRGMLLayer( const char * pszName,
 
     /* Compatibility option. Not advertized, because hopefully won't be needed */
     /* Just put here in provision... */
-    bUseOldFIDFormat = CSLTestBoolean(CPLGetConfigOption("GML_USE_OLD_FID_FORMAT", "FALSE"));
+    bUseOldFIDFormat = CPLTestBool(CPLGetConfigOption("GML_USE_OLD_FID_FORMAT", "FALSE"));
 
     /* Must be in synced in OGR_G_CreateFromGML(), OGRGMLLayer::OGRGMLLayer() and GMLReader::GMLReader() */
-    bFaceHoleNegative = CSLTestBoolean(CPLGetConfigOption("GML_FACE_HOLE_NEGATIVE", "NO"));
+    bFaceHoleNegative = CPLTestBool(CPLGetConfigOption("GML_FACE_HOLE_NEGATIVE", "NO"));
 
 }
 
@@ -144,8 +144,6 @@ void OGRGMLLayer::ResetReading()
 OGRFeature *OGRGMLLayer::GetNextFeature()
 
 {
-    int i;
-
     if (bWriter)
     {
         CPLError(CE_Failure, CPLE_NotSupported,
@@ -164,7 +162,7 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
 /*      Loop till we find and translate a feature meeting all our       */
 /*      requirements.                                                   */
 /* ==================================================================== */
-    while( TRUE )
+    while( true )
     {
         GMLFeature  *poGMLFeature = NULL;
         OGRGeometry *poGeom = NULL;
@@ -220,13 +218,13 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
         }
         else if( pszGML_FID == NULL )
         {
-            bInvalidFIDFound = TRUE;
+            bInvalidFIDFound = true;
             nFID = iNextGMLId++;
         }
         else if( iNextGMLId == 0 )
         {
             int j = 0;
-            i = strlen( pszGML_FID )-1;
+            int i = static_cast<int>(strlen( pszGML_FID ))-1;
             while( i >= 0 && pszGML_FID[i] >= '0'
                           && pszGML_FID[i] <= '9' && j<20)
                 i--, j++;
@@ -245,7 +243,7 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
             }
             else
             {
-                bInvalidFIDFound = TRUE;
+                bInvalidFIDFound = true;
                 nFID = iNextGMLId++;
             }
         }
@@ -253,7 +251,7 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
         {
             const char* pszFIDPrefix_notnull = pszFIDPrefix;
             if (pszFIDPrefix_notnull == NULL) pszFIDPrefix_notnull = "";
-            int nLenPrefix = strlen(pszFIDPrefix_notnull);
+            int nLenPrefix = static_cast<int>(strlen(pszFIDPrefix_notnull));
 
             if(  strncmp(pszGML_FID, pszFIDPrefix_notnull, nLenPrefix) == 0 &&
                  strlen(pszGML_FID+nLenPrefix) < 20 &&
@@ -264,7 +262,7 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
             }
             else
             { /* fid without the aforementioned prefix or a valid numerical part */
-                bInvalidFIDFound = TRUE;
+                bInvalidFIDFound = true;
                 nFID = iNextGMLId++;
             }
         }
@@ -281,7 +279,7 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
             papoGeometries = (OGRGeometry**)
                 CPLCalloc( poFeatureDefn->GetGeomFieldCount(), sizeof(OGRGeometry*) );
             const char* pszSRSName = poDS->GetGlobalSRSName();
-            for( i=0; i < poFeatureDefn->GetGeomFieldCount(); i++)
+            for( int i=0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
             {
                 const CPLXMLNode* psGeom = poGMLFeature->GetGeometryRef(i);
                 if( psGeom != NULL )
@@ -289,7 +287,7 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
                     const CPLXMLNode* myGeometryList[2];
                     myGeometryList[0] = psGeom;
                     myGeometryList[1] = NULL;
-                    poGeom = GML_BuildOGRGeometryFromList(myGeometryList, TRUE,
+                    poGeom = GML_BuildOGRGeometryFromList(myGeometryList, true,
                                                   poDS->GetInvertAxisOrderIfLatLong(),
                                                   pszSRSName,
                                                   poDS->GetConsiderEPSGAsURN(),
@@ -325,7 +323,7 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
                 papoGeometries[m_iGeomFieldFilter] &&
                 !FilterGeometry( papoGeometries[m_iGeomFieldFilter] ) )
             {
-                for( i=0; i < poFeatureDefn->GetGeomFieldCount(); i++)
+                for( int i=0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
                 {
                     delete papoGeometries[i];
                 }
@@ -337,7 +335,7 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
         else if (papsGeometry[0] != NULL)
         {
             const char* pszSRSName = poDS->GetGlobalSRSName();
-            poGeom = GML_BuildOGRGeometryFromList(papsGeometry, TRUE,
+            poGeom = GML_BuildOGRGeometryFromList(papsGeometry, true,
                                                   poDS->GetInvertAxisOrderIfLatLong(),
                                                   pszSRSName,
                                                   poDS->GetConsiderEPSGAsURN(),
@@ -366,7 +364,6 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
             }
         }
 
-        
 /* -------------------------------------------------------------------- */
 /*      Convert the whole feature into an OGRFeature.                   */
 /* -------------------------------------------------------------------- */
@@ -402,8 +399,9 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
                   int nCount = psGMLProperty->nSubProperties;
                   int *panIntList = (int *) CPLMalloc(sizeof(int) * nCount );
 
-                  for( i = 0; i < nCount; i++ )
-                      panIntList[i] = atoi(psGMLProperty->papszSubProperties[i]);
+                  for( int i = 0; i < nCount; i++ )
+                      panIntList[i]
+                          = atoi(psGMLProperty->papszSubProperties[i]);
 
                   poOGRFeature->SetField( iDstField, nCount, panIntList );
                   CPLFree( panIntList );
@@ -415,8 +413,9 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
                   int nCount = psGMLProperty->nSubProperties;
                   GIntBig *panIntList = (GIntBig *) CPLMalloc(sizeof(GIntBig) * nCount );
 
-                  for( i = 0; i < nCount; i++ )
-                      panIntList[i] = CPLAtoGIntBig(psGMLProperty->papszSubProperties[i]);
+                  for( int i = 0; i < nCount; i++ )
+                      panIntList[i]
+                          = CPLAtoGIntBig(psGMLProperty->papszSubProperties[i]);
 
                   poOGRFeature->SetField( iDstField, nCount, panIntList );
                   CPLFree( panIntList );
@@ -428,8 +427,9 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
                   int nCount = psGMLProperty->nSubProperties;
                   double *padfList = (double *)CPLMalloc(sizeof(double)*nCount);
 
-                  for( i = 0; i < nCount; i++ )
-                      padfList[i] = CPLAtof(psGMLProperty->papszSubProperties[i]);
+                  for( int i = 0; i < nCount; i++ )
+                      padfList[i]
+                          = CPLAtof(psGMLProperty->papszSubProperties[i]);
 
                   poOGRFeature->SetField( iDstField, nCount, padfList );
                   CPLFree( padfList );
@@ -465,10 +465,13 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
                   int nCount = psGMLProperty->nSubProperties;
                   int *panIntList = (int *) CPLMalloc(sizeof(int) * nCount );
 
-                  for( i = 0; i < nCount; i++ )
+                  for( int i = 0; i < nCount; i++ )
                   {
-                      panIntList[i] = ( strcmp(psGMLProperty->papszSubProperties[i], "true") == 0 ||
-                                        strcmp(psGMLProperty->papszSubProperties[i], "1") == 0 );
+                      panIntList[i] = (
+                          strcmp(psGMLProperty->papszSubProperties[i],
+                                 "true") == 0 ||
+                          strcmp(psGMLProperty->papszSubProperties[i],
+                                 "1") == 0 );
                   }
 
                   poOGRFeature->SetField( iDstField, nCount, panIntList );
@@ -489,7 +492,7 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
         /* the attribute filter may use a special field like OGR_GEOMETRY */
         if( papoGeometries != NULL )
         {
-            for( i=0; i < poFeatureDefn->GetGeomFieldCount(); i++)
+            for( int i=0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
             {
                 poOGRFeature->SetGeomFieldDirectly( i, papoGeometries[i] );
             }
@@ -500,17 +503,18 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
             poOGRFeature->SetGeometryDirectly( poGeom );
 
         /* Assign SRS */
-        for( i=0; i < poFeatureDefn->GetGeomFieldCount(); i++)
+        for( int i=0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
         {
             poGeom = poOGRFeature->GetGeomFieldRef(i);
             if( poGeom != NULL )
             {
-                OGRSpatialReference* poSRS = poFeatureDefn->GetGeomFieldDefn(i)->GetSpatialRef();
+                OGRSpatialReference* poSRS
+                    = poFeatureDefn->GetGeomFieldDefn(i)->GetSpatialRef();
                 if (poSRS != NULL)
                     poGeom->assignSpatialReference(poSRS);
             }
         }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Test against the attribute query.                               */
 /* -------------------------------------------------------------------- */
@@ -569,7 +573,7 @@ OGRErr OGRGMLLayer::GetExtent(OGREnvelope *psExtent, int bForce )
     if( GetGeomType() == wkbNone )
         return OGRERR_FAILURE;
 
-    if( poFClass != NULL && 
+    if( poFClass != NULL &&
         poFClass->GetExtents( &dfXMin, &dfXMax, &dfYMin, &dfYMax ) )
     {
         psExtent->MinX = dfXMin;
@@ -579,7 +583,7 @@ OGRErr OGRGMLLayer::GetExtent(OGREnvelope *psExtent, int bForce )
 
         return OGRERR_NONE;
     }
-    else 
+    else
         return OGRLayer::GetExtent( psExtent, bForce );
 }
 
@@ -642,7 +646,7 @@ OGRErr OGRGMLLayer::ICreateFeature( OGRFeature *poFeature )
         VSIFPrintfL(fp, "  ");
     if (bIsGML3Output)
     {
-        if( bRemoveAppPrefix ) 
+        if( bRemoveAppPrefix )
             poDS->PrintLine( fp, "<featureMember>" );
         else
             poDS->PrintLine( fp, "<%s:featureMember>", pszPrefix );
@@ -652,7 +656,7 @@ OGRErr OGRGMLLayer::ICreateFeature( OGRFeature *poFeature )
 
     if( iNextGMLId == 0 )
     {
-        bSameSRS = TRUE;
+        bSameSRS = true;
         for( int iGeomField = 1; iGeomField < poFeatureDefn->GetGeomFieldCount(); iGeomField++ )
         {
             OGRGeomFieldDefn *poFieldDefn0 = poFeatureDefn->GetGeomFieldDefn(0);
@@ -660,13 +664,13 @@ OGRErr OGRGMLLayer::ICreateFeature( OGRFeature *poFeature )
             OGRSpatialReference* poSRS0 = poFieldDefn0->GetSpatialRef();
             OGRSpatialReference* poSRS = poFieldDefn->GetSpatialRef();
             if( poSRS0 != NULL && poSRS == NULL )
-                bSameSRS = FALSE;
+                bSameSRS = false;
             else if( poSRS0 == NULL && poSRS != NULL )
-                bSameSRS = FALSE;
+                bSameSRS = false;
             else if( poSRS0 != NULL && poSRS != NULL &&
                      poSRS0 != poSRS && !poSRS0->IsSame(poSRS) )
             {
-                bSameSRS = FALSE;
+                bSameSRS = false;
             }
         }
     }
@@ -678,7 +682,7 @@ OGRErr OGRGMLLayer::ICreateFeature( OGRFeature *poFeature )
     if (bWriteSpaceIndentation)
         VSIFPrintfL(fp, "    ");
     VSIFPrintfL(fp, "<");
-    if( !bRemoveAppPrefix ) 
+    if( !bRemoveAppPrefix )
         VSIFPrintfL(fp, "%s:", pszPrefix);
     if (bIsGML3Output)
     {
@@ -741,7 +745,7 @@ OGRErr OGRGMLLayer::ICreateFeature( OGRFeature *poFeature )
 
             if (bIsGML3Output && poDS->WriteFeatureBoundedBy())
             {
-                int bCoordSwap;
+                bool bCoordSwap;
 
                 char* pszSRSName = GML_GetSRSName(poGeom->getSpatialReference(), poDS->IsLongSRSRequired(), &bCoordSwap);
                 char szLowerCorner[75], szUpperCorner[75];
@@ -807,10 +811,10 @@ OGRErr OGRGMLLayer::ICreateFeature( OGRFeature *poFeature )
         }
     }
 
-    // Write all "set" fields. 
+    // Write all "set" fields.
     for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     {
-        
+
         OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( iField );
 
         if( poFeature->IsFieldSet( iField ) && iField != nGMLIdIndex )
@@ -959,8 +963,8 @@ int OGRGMLLayer::TestCapability( const char * pszCap )
 
     else if( EQUAL(pszCap,OLCFastFeatureCount) )
     {
-        if( poFClass == NULL 
-            || m_poFilterGeom != NULL 
+        if( poFClass == NULL
+            || m_poFilterGeom != NULL
             || m_poAttrQuery != NULL )
             return FALSE;
 
@@ -973,7 +977,7 @@ int OGRGMLLayer::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCCurveGeometries) )
         return poDS->IsGML3Output();
 
-    else 
+    else
         return FALSE;
 }
 
@@ -993,13 +997,13 @@ OGRErr OGRGMLLayer::CreateField( OGRFieldDefn *poField, int bApproxOK )
     OGRFieldDefn oCleanCopy( poField );
     char *pszName = CPLStrdup( poField->GetNameRef() );
     CPLCleanXMLElementName( pszName );
-    
+
     if( strcmp(pszName,poField->GetNameRef()) != 0 )
     {
         if( !bApproxOK )
         {
             CPLFree( pszName );
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Unable to create field with name '%s', it would not\n"
                       "be valid as an XML element name.",
                       poField->GetNameRef() );
@@ -1007,7 +1011,7 @@ OGRErr OGRGMLLayer::CreateField( OGRFieldDefn *poField, int bApproxOK )
         }
 
         oCleanCopy.SetName( pszName );
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "Field name '%s' adjusted to '%s' to be a valid\n"
                   "XML element name.",
                   poField->GetNameRef(), pszName );
@@ -1015,7 +1019,7 @@ OGRErr OGRGMLLayer::CreateField( OGRFieldDefn *poField, int bApproxOK )
 
     CPLFree( pszName );
 
-    
+
     poFeatureDefn->AddFieldDefn( &oCleanCopy );
 
     return OGRERR_NONE;
@@ -1037,13 +1041,13 @@ OGRErr OGRGMLLayer::CreateGeomField( OGRGeomFieldDefn *poField, int bApproxOK )
     OGRGeomFieldDefn oCleanCopy( poField );
     char *pszName = CPLStrdup( poField->GetNameRef() );
     CPLCleanXMLElementName( pszName );
-    
+
     if( strcmp(pszName,poField->GetNameRef()) != 0 )
     {
         if( !bApproxOK )
         {
             CPLFree( pszName );
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Unable to create field with name '%s', it would not\n"
                       "be valid as an XML element name.",
                       poField->GetNameRef() );
@@ -1051,7 +1055,7 @@ OGRErr OGRGMLLayer::CreateGeomField( OGRGeomFieldDefn *poField, int bApproxOK )
         }
 
         oCleanCopy.SetName( pszName );
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "Field name '%s' adjusted to '%s' to be a valid\n"
                   "XML element name.",
                   poField->GetNameRef(), pszName );
@@ -1059,7 +1063,7 @@ OGRErr OGRGMLLayer::CreateGeomField( OGRGeomFieldDefn *poField, int bApproxOK )
 
     CPLFree( pszName );
 
-    
+
     poFeatureDefn->AddGeomFieldDefn( &oCleanCopy );
 
     return OGRERR_NONE;
diff --git a/ogr/ogrsf_frmts/gml/parsexsd.cpp b/ogr/ogrsf_frmts/gml/parsexsd.cpp
index 71c6560..5420437 100644
--- a/ogr/ogrsf_frmts/gml/parsexsd.cpp
+++ b/ogr/ogrsf_frmts/gml/parsexsd.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: parsexsd.cpp 28909 2015-04-15 12:52:53Z rouault $
+ * $Id: parsexsd.cpp 33702 2016-03-11 06:20:16Z goatbar $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLParseXSD()
@@ -15,16 +15,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
@@ -43,7 +43,7 @@
 /*      stripped off if there is one.  Returns pointer into             */
 /*      original string.                                                */
 /************************************************************************/
-
+static
 const char *StripNS( const char *pszFullValue )
 
 {
@@ -59,7 +59,7 @@ const char *StripNS( const char *pszFullValue )
 /************************************************************************/
 
 static
-int GetSimpleTypeProperties(CPLXMLNode *psTypeNode,
+bool GetSimpleTypeProperties(CPLXMLNode *psTypeNode,
                             GMLPropertyType *pGMLType,
                             int *pnWidth,
                             int *pnPrecision)
@@ -79,19 +79,19 @@ int GetSimpleTypeProperties(CPLXMLNode *psTypeNode,
                         "restriction.fractionDigits.value", "0" );
         *pnWidth = atoi(pszWidth);
         *pnPrecision = atoi(pszPrecision);
-        return TRUE;
+        return true;
     }
-    
+
      else if( EQUAL(pszBase,"float") )
     {
         *pGMLType = GMLPT_Float;
-        return TRUE;
+        return true;
     }
 
     else if( EQUAL(pszBase,"double") )
     {
         *pGMLType = GMLPT_Real;
-        return TRUE;
+        return true;
     }
 
     else if( EQUAL(pszBase,"integer") )
@@ -101,7 +101,7 @@ int GetSimpleTypeProperties(CPLXMLNode *psTypeNode,
             CPLGetXMLValue( psTypeNode,
                         "restriction.totalDigits.value", "0" );
         *pnWidth = atoi(pszWidth);
-        return TRUE;
+        return true;
     }
 
     else if( EQUAL(pszBase,"long") )
@@ -111,7 +111,7 @@ int GetSimpleTypeProperties(CPLXMLNode *psTypeNode,
             CPLGetXMLValue( psTypeNode,
                         "restriction.totalDigits.value", "0" );
         *pnWidth = atoi(pszWidth);
-        return TRUE;
+        return true;
     }
 
     else if( EQUAL(pszBase,"long") )
@@ -121,7 +121,7 @@ int GetSimpleTypeProperties(CPLXMLNode *psTypeNode,
             CPLGetXMLValue( psTypeNode,
                         "restriction.totalDigits.value", "0" );
         *pnWidth = atoi(pszWidth);
-        return TRUE;
+        return true;
     }
 
     else if( EQUAL(pszBase,"string") )
@@ -131,7 +131,7 @@ int GetSimpleTypeProperties(CPLXMLNode *psTypeNode,
             CPLGetXMLValue( psTypeNode,
                         "restriction.maxLength.value", "0" );
         *pnWidth = atoi(pszWidth);
-        return TRUE;
+        return true;
     }
 
     /* TODO: Would be nice to have a proper date type */
@@ -139,22 +139,22 @@ int GetSimpleTypeProperties(CPLXMLNode *psTypeNode,
              EQUAL(pszBase,"dateTime") )
     {
         *pGMLType = GMLPT_String;
-        return TRUE;
+        return true;
     }
 
     else if( EQUAL(pszBase,"boolean") )
     {
         *pGMLType = GMLPT_Boolean;
-        return TRUE;
+        return true;
     }
 
     else if( EQUAL(pszBase,"short") )
     {
         *pGMLType = GMLPT_Short;
-        return TRUE;
+        return true;
     }
 
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
@@ -162,7 +162,7 @@ int GetSimpleTypeProperties(CPLXMLNode *psTypeNode,
 /************************************************************************/
 
 static
-int LookForSimpleType(CPLXMLNode *psSchemaNode,
+bool LookForSimpleType(CPLXMLNode *psSchemaNode,
                       const char* pszStrippedNSType,
                       GMLPropertyType *pGMLType,
                       int *pnWidth,
@@ -180,7 +180,7 @@ int LookForSimpleType(CPLXMLNode *psSchemaNode,
         }
     }
     if (psThis == NULL)
-        return FALSE;
+        return false;
 
     return GetSimpleTypeProperties(psThis, pGMLType, pnWidth, pnPrecision);
 }
@@ -352,7 +352,7 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
     CPLXMLNode *psAttrDef;
     int nAttributeIndex = 0;
 
-    int bGotUnrecognizedType = FALSE;
+    bool bGotUnrecognizedType = false;
 
     for( psAttrDef = psAttrSeq->psChild;
             psAttrDef != NULL;
@@ -364,7 +364,7 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
             delete poClass;
             return NULL;
         }
-        
+
         /* Parse stuff like :
         <xs:choice>
             <xs:element ref="gml:polygonProperty"/>
@@ -375,8 +375,8 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
         if( strcmp(psAttrDef->pszValue,"choice") == 0 )
         {
             CPLXMLNode* psChild = psAttrDef->psChild;
-            int bPolygon = FALSE;
-            int bMultiPolygon = FALSE;
+            bool bPolygon = false;
+            bool bMultiPolygon = false;
             for( ; psChild; psChild = psChild->psNext )
             {
                 if( psChild->eType != CXT_Element )
@@ -387,9 +387,9 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
                     if( pszRef != NULL )
                     {
                         if( strcmp(pszRef, "gml:polygonProperty") == 0 )
-                            bPolygon = TRUE;
+                            bPolygon = true;
                         else if( strcmp(pszRef, "gml:multiPolygonProperty") == 0 )
-                            bMultiPolygon = TRUE;
+                            bMultiPolygon = true;
                         else
                         {
                             delete poClass;
@@ -406,7 +406,7 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
             if( bPolygon && bMultiPolygon )
             {
                 poClass->AddGeometryProperty( new GMLGeometryPropertyDefn(
-                    "", "", wkbMultiPolygon, nAttributeIndex, TRUE ) );
+                    "", "", wkbMultiPolygon, nAttributeIndex, true ) );
 
                 nAttributeIndex ++;
             }
@@ -420,7 +420,7 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
         /* not as a simpleType definition */
         const char* pszType = CPLGetXMLValue( psAttrDef, "type", NULL );
         const char* pszElementName = CPLGetXMLValue( psAttrDef, "name", NULL );
-        int bNullable = EQUAL(CPLGetXMLValue( psAttrDef, "minOccurs", "1" ), "0");
+        bool bNullable = EQUAL(CPLGetXMLValue( psAttrDef, "minOccurs", "1" ), "0");
         const char* pszMaxOccurs = CPLGetXMLValue( psAttrDef, "maxOccurs", NULL );
         if (pszType != NULL)
         {
@@ -454,7 +454,7 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
             {
                 gmlType = GMLPT_FeatureProperty;
             }
-            else if (strncmp(pszType, "gml:", 4) == 0)
+            else if (STARTS_WITH(pszType, "gml:"))
             {
                 const AssocNameType* psIter = apsPropertyTypes;
                 while(psIter->pszName)
@@ -496,7 +496,7 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
                 }
 
                 if (poClass->GetGeometryPropertyCount() == 0)
-                    bGotUnrecognizedType = TRUE;
+                    bGotUnrecognizedType = true;
 
                 continue;
             }
@@ -590,7 +590,7 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
             const char* pszRef = CPLGetXMLValue( psAttrDef, "ref", NULL );
 
             /* FME .xsd */
-            if (pszRef != NULL && strncmp(pszRef, "gml:", 4) == 0)
+            if (pszRef != NULL && STARTS_WITH(pszRef, "gml:"))
             {
                 const AssocNameType* psIter = apsRefTypes;
                 while(psIter->pszName)
@@ -615,7 +615,7 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
                         else
                         {
                             poClass->AddGeometryProperty( new GMLGeometryPropertyDefn(
-                                pszElementName, pszElementName, psIter->eType, nAttributeIndex, TRUE ) );
+                                pszElementName, pszElementName, psIter->eType, nAttributeIndex, true ) );
 
                             nAttributeIndex ++;
                         }
@@ -635,7 +635,7 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
                 }
 
                 if (poClass->GetGeometryPropertyCount() == 0)
-                    bGotUnrecognizedType = TRUE;
+                    bGotUnrecognizedType = true;
 
                 continue;
             }
@@ -649,8 +649,8 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
                 </xs:complexType>
             </xs:element>
             */
-            CPLXMLNode* psComplexType = GetSingleChildElement( psAttrDef, "complexType" );
-            CPLXMLNode* psComplexTypeSequence = GetSingleChildElement( psComplexType, "sequence" );
+            CPLXMLNode* l_psComplexType = GetSingleChildElement( psAttrDef, "complexType" );
+            CPLXMLNode* psComplexTypeSequence = GetSingleChildElement( l_psComplexType, "sequence" );
             CPLXMLNode* psComplexTypeSequenceElement = GetSingleChildElement( psComplexTypeSequence, "element" );
 
             if( pszElementName != NULL &&
@@ -702,13 +702,13 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
     if( poClass->GetGeometryPropertyCount() == 0 &&
         bGotUnrecognizedType )
     {
-        poClass->AddGeometryProperty( new GMLGeometryPropertyDefn( "", "", wkbUnknown, -1, TRUE ) );
+        poClass->AddGeometryProperty( new GMLGeometryPropertyDefn( "", "", wkbUnknown, -1, true ) );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Class complete, add to reader class list.                       */
 /* -------------------------------------------------------------------- */
-    poClass->SetSchemaLocked( TRUE );
+    poClass->SetSchemaLocked( true );
 
     return poClass;
 }
@@ -720,8 +720,8 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
 static
 CPLXMLNode* GMLParseXMLFile(const char* pszFilename)
 {
-    if( strncmp(pszFilename, "http://", 7) == 0 ||
-        strncmp(pszFilename, "https://", 8) == 0 )
+    if( STARTS_WITH(pszFilename, "http://") ||
+        STARTS_WITH(pszFilename, "https://") )
     {
         CPLXMLNode* psRet = NULL;
         CPLHTTPResult* psResult = CPLHTTPFetch( pszFilename, NULL );
@@ -767,8 +767,6 @@ CPLXMLNode* CPLGetFirstChildNode( CPLXMLNode* psNode )
 static
 CPLXMLNode* CPLGetLastNode( CPLXMLNode* psNode )
 {
-    if( psNode == NULL )
-        return NULL;
     CPLXMLNode* psIter = psNode;
     while( psIter->psNext != NULL )
         psIter = psIter->psNext;
@@ -785,28 +783,28 @@ void CPLXMLSchemaResolveInclude( const char* pszMainSchemaLocation,
 {
     std::set<CPLString> osAlreadyIncluded;
 
-    int bTryAgain;
+    bool bTryAgain;
     do
     {
         CPLXMLNode *psThis;
         CPLXMLNode *psLast = NULL;
-        bTryAgain = FALSE;
+        bTryAgain = false;
 
-        for( psThis = psSchemaNode->psChild; 
+        for( psThis = psSchemaNode->psChild;
             psThis != NULL; psThis = psThis->psNext )
         {
             if( psThis->eType == CXT_Element &&
                 EQUAL(psThis->pszValue,"include") )
             {
-                const char* pszSchemaLocation = 
+                const char* pszSchemaLocation =
                         CPLGetXMLValue(psThis, "schemaLocation", NULL);
                 if( pszSchemaLocation != NULL &&
                     osAlreadyIncluded.count( pszSchemaLocation) == 0 )
                 {
                     osAlreadyIncluded.insert( pszSchemaLocation );
 
-                    if( strncmp(pszSchemaLocation, "http://", 7) != 0 &&
-                        strncmp(pszSchemaLocation, "https://", 8) != 0 &&
+                    if( !STARTS_WITH(pszSchemaLocation, "http://") &&
+                        !STARTS_WITH(pszSchemaLocation, "https://") &&
                         CPLIsFilenameRelative(pszSchemaLocation ) )
                     {
                         pszSchemaLocation = CPLFormFilename(
@@ -840,7 +838,7 @@ void CPLXMLSchemaResolveInclude( const char* pszMainSchemaLocation,
 
                                 /* In case the included schema also contains */
                                 /* includes */
-                                bTryAgain = TRUE;
+                                bTryAgain = true;
                             }
 
                         }
@@ -865,23 +863,23 @@ void CPLXMLSchemaResolveInclude( const char* pszMainSchemaLocation,
 /*                          GMLParseXSD()                               */
 /************************************************************************/
 
-int GMLParseXSD( const char *pszFile,
+bool GMLParseXSD( const char *pszFile,
                  std::vector<GMLFeatureClass*> & aosClasses,
-                 int& bFullyUnderstood)
+                 bool& bFullyUnderstood)
 
 {
-    bFullyUnderstood = FALSE;
+    bFullyUnderstood = false;
 
     if( pszFile == NULL )
-        return FALSE;
+        return false;
 
 /* -------------------------------------------------------------------- */
 /*      Load the raw XML file.                                          */
 /* -------------------------------------------------------------------- */
     CPLXMLNode *psXSDTree = GMLParseXMLFile( pszFile );
-    
+
     if( psXSDTree == NULL )
-        return FALSE;
+        return false;
 
 /* -------------------------------------------------------------------- */
 /*      Strip off any namespace qualifiers.                             */
@@ -895,7 +893,7 @@ int GMLParseXSD( const char *pszFile,
     if( psSchemaNode == NULL )
     {
         CPLDestroyXMLNode( psXSDTree );
-        return FALSE;
+        return false;
     }
 
 /* ==================================================================== */
@@ -905,27 +903,27 @@ int GMLParseXSD( const char *pszFile,
 
     //CPLSerializeXMLTreeToFile(psSchemaNode, "/vsistdout/");
 
-    bFullyUnderstood = TRUE;
+    bFullyUnderstood = true;
 
 /* ==================================================================== */
 /*      Process each feature class definition.                          */
 /* ==================================================================== */
     CPLXMLNode *psThis;
 
-    for( psThis = psSchemaNode->psChild; 
+    for( psThis = psSchemaNode->psChild;
          psThis != NULL; psThis = psThis->psNext )
     {
 /* -------------------------------------------------------------------- */
 /*      Check for <xs:element> node.                                    */
 /* -------------------------------------------------------------------- */
-        if( psThis->eType != CXT_Element 
+        if( psThis->eType != CXT_Element
             || !EQUAL(psThis->pszValue,"element") )
             continue;
 
 /* -------------------------------------------------------------------- */
 /*      Check the substitution group.                                   */
 /* -------------------------------------------------------------------- */
-        const char *pszSubGroup = 
+        const char *pszSubGroup =
             StripNS(CPLGetXMLValue(psThis,"substitutionGroup",""));
 
         // Old OGR produced elements for the feature collection.
@@ -937,7 +935,7 @@ int GMLParseXSD( const char *pszFile,
         {
             continue;
         }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Get name                                                        */
 /* -------------------------------------------------------------------- */
@@ -965,7 +963,7 @@ int GMLParseXSD( const char *pszFile,
                 if (poClass)
                     aosClasses.push_back(poClass);
                 else
-                    bFullyUnderstood = FALSE;
+                    bFullyUnderstood = false;
             }
             continue;
         }
@@ -984,8 +982,7 @@ int GMLParseXSD( const char *pszFile,
                   strlen(pszName) > strlen(pszType) - 4 &&
                   strncmp(pszName + strlen(pszName) - (strlen(pszType) - 4),
                           pszType,
-                          strlen(pszType) - 4) == 0 )
-        {
+                          strlen(pszType) - 4) == 0 )        {
         }
 
         else if( !EQUALN(pszType,pszName,strlen(pszName))
@@ -996,9 +993,9 @@ int GMLParseXSD( const char *pszFile,
         }
 
         /* CanVec .xsd contains weird types that are not used in the related GML */
-        if (strncmp(pszName, "XyZz", 4) == 0 ||
-            strncmp(pszName, "XyZ1", 4) == 0 ||
-            strncmp(pszName, "XyZ2", 4) == 0)
+        if (STARTS_WITH(pszName, "XyZz") ||
+            STARTS_WITH(pszName, "XyZ1") ||
+            STARTS_WITH(pszName, "XyZ2"))
             continue;
 
         GMLFeatureClass* poClass =
@@ -1006,15 +1003,15 @@ int GMLParseXSD( const char *pszFile,
         if (poClass)
             aosClasses.push_back(poClass);
         else
-            bFullyUnderstood = FALSE;
+            bFullyUnderstood = false;
     }
 
     CPLDestroyXMLNode( psXSDTree );
 
     if( aosClasses.size() > 0 )
     {
-        return TRUE;
+        return true;
     }
     else
-        return FALSE;
+        return false;
 }
diff --git a/ogr/ogrsf_frmts/gml/parsexsd.h b/ogr/ogrsf_frmts/gml/parsexsd.h
index 125d64a..d03c51c 100644
--- a/ogr/ogrsf_frmts/gml/parsexsd.h
+++ b/ogr/ogrsf_frmts/gml/parsexsd.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: parsexsd.h 28909 2015-04-15 12:52:53Z rouault $
+ * $Id: parsexsd.h 31777 2015-11-26 14:14:41Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLParseXSD()
@@ -28,14 +28,14 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _PARSEXSD_H_INCLUDED
-#define _PARSEXSD_H_INCLUDED
+#ifndef PARSEXSD_H_INCLUDED
+#define PARSEXSD_H_INCLUDED
 
 #include <vector>
 #include "gmlreader.h"
 
-int GMLParseXSD( const char *pszFile,
+bool GMLParseXSD( const char *pszFile,
                  std::vector<GMLFeatureClass*> & aosClasses,
-                 int& bFullyUnderstood );
+                 bool& bFullyUnderstood );
 
-#endif // _PARSEXSD_H_INCLUDED
+#endif // PARSEXSD_H_INCLUDED
diff --git a/ogr/ogrsf_frmts/gml/resolvexlinks.cpp b/ogr/ogrsf_frmts/gml/resolvexlinks.cpp
index 984bb9b..50ee28e 100644
--- a/ogr/ogrsf_frmts/gml/resolvexlinks.cpp
+++ b/ogr/ogrsf_frmts/gml/resolvexlinks.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: resolvexlinks.cpp 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: resolvexlinks.cpp 32177 2015-12-14 07:25:30Z goatbar $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLReader::ResolveXlinks() method.
@@ -15,23 +15,23 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
 #include "gmlreader.h"
 #include "cpl_error.h"
 
-CPL_CVSID("$Id: resolvexlinks.cpp 27044 2014-03-16 23:41:27Z rouault $");
+CPL_CVSID("$Id: resolvexlinks.cpp 32177 2015-12-14 07:25:30Z goatbar $");
 
 #include "gmlreaderp.h"
 #include "cpl_conv.h"
@@ -175,15 +175,15 @@ static void RemoveIDs( CPLXMLNode * psRoot )
 /************************************************************************/
 /*                          TrimTree()                                  */
 /*                                                                      */
-/*      Remove all nodes without a gml:id node in the descendents.      */
-/*      Returns TRUE if there is a gml:id node in the descendents.      */
+/*      Remove all nodes without a gml:id node in the descendants.      */
+/*      Returns TRUE if there is a gml:id node in the descendants.      */
 /************************************************************************/
 
-static int TrimTree( CPLXMLNode * psRoot )
+static bool TrimTree( CPLXMLNode * psRoot )
 
 {
     if( psRoot == NULL )
-        return FALSE;
+        return false;
 
     CPLXMLNode *psChild = psRoot->psChild;
 
@@ -192,10 +192,10 @@ static int TrimTree( CPLXMLNode * psRoot )
         psChild = psChild->psNext;
 
     if( psChild != NULL )
-        return TRUE;
+        return true;
 
 // search the child elements of psRoot
-    int bReturn = FALSE, bRemove;
+    bool bReturn = false, bRemove;
     for( psChild = psRoot->psChild; psChild != NULL;)
     {
         CPLXMLNode* psNextChild = psChild->psNext;
@@ -275,7 +275,7 @@ static void CorrectURLs( CPLXMLNode * psRoot, const char *pszURL )
                 strncmp( pszURL, psChild->psChild->pszValue, nPathLen ) != 0 )
             {
             //different path
-                int nURLLen = pszDash - psChild->psChild->pszValue;
+                int nURLLen = static_cast<int>(pszDash - psChild->psChild->pszValue);
                 char *pszURLWithoutID = (char *)CPLMalloc( (nURLLen+1) * sizeof(char));
                 strncpy( pszURLWithoutID, psChild->psChild->pszValue, nURLLen );
                 pszURLWithoutID[nURLLen] = '\0';
@@ -403,7 +403,7 @@ static CPLErr Resolve( CPLXMLNode * psNode,
     CPLXMLNode *psResource = NULL;
     CPLXMLNode *psTarget = NULL;
     CPLErr eReturn = CE_None, eReturned;
-    
+
     for( psSibling = psNode; psSibling != NULL; psSibling = psSibling->psNext )
     {
         if( psSibling->eType != CXT_Element )
@@ -527,13 +527,13 @@ static CPLErr Resolve( CPLXMLNode * psNode,
 /*      saved to.                                                       */
 /************************************************************************/
 
-int GMLReader::ResolveXlinks( const char *pszFile,
-                              int* pbOutIsTempFile,
+bool GMLReader::ResolveXlinks( const char *pszFile,
+                              bool* pbOutIsTempFile,
                               char **papszSkip,
-                              const int bStrict)
+                              const bool bStrict)
 
 {
-    *pbOutIsTempFile = FALSE;
+    *pbOutIsTempFile = false;
 
 // Check if the original source file is set.
     if( m_pszFilename == NULL )
@@ -541,7 +541,7 @@ int GMLReader::ResolveXlinks( const char *pszFile,
         CPLError( CE_Failure, CPLE_NotSupported,
                   "GML source file needs to be set first with "
                   "GMLReader::SetSourceFile()." );
-        return FALSE;
+        return false;
     }
 
 /* -------------------------------------------------------------------- */
@@ -554,7 +554,7 @@ int GMLReader::ResolveXlinks( const char *pszFile,
     if( papsSrcTree[0] == NULL )
     {
         CPLFree(papsSrcTree);
-        return FALSE;
+        return false;
     }
 
     //make all the URLs absolute
@@ -571,23 +571,23 @@ int GMLReader::ResolveXlinks( const char *pszFile,
     CPLErr eReturned = CE_None;
     eReturned = Resolve( papsSrcTree[0], &papsSrcTree, &papszResourceHREF, papszSkip, bStrict );
 
-    int bReturn = TRUE;
+    bool bReturn = true;
     if( eReturned != CE_Failure )
     {
         char *pszTmpName = NULL;
-        int bTryWithTempFile = FALSE;
-        if( EQUALN(pszFile, "/vsitar/", strlen("/vsitar/")) ||
-            EQUALN(pszFile, "/vsigzip/", strlen("/vsigzip/")) ||
-            EQUALN(pszFile, "/vsizip/", strlen("/vsizip/")) )
+        bool bTryWithTempFile = false;
+        if( STARTS_WITH_CI(pszFile, "/vsitar/") ||
+            STARTS_WITH_CI(pszFile, "/vsigzip/") ||
+            STARTS_WITH_CI(pszFile, "/vsizip/") )
         {
-            bTryWithTempFile = TRUE;
+            bTryWithTempFile = true;
         }
         else if( !CPLSerializeXMLTreeToFile( papsSrcTree[0], pszFile ) )
         {
             CPLError( CE_Failure, CPLE_FileIO,
                       "Cannot serialize resolved file %s to %s.",
                       m_pszFilename, pszFile );
-            bTryWithTempFile = TRUE;
+            bTryWithTempFile = true;
         }
 
         if (bTryWithTempFile)
@@ -599,14 +599,14 @@ int GMLReader::ResolveXlinks( const char *pszFile,
                           "Cannot serialize resolved file %s to %s either.",
                           m_pszFilename, pszTmpName );
                 CPLFree( pszTmpName );
-                bReturn = FALSE;
+                bReturn = false;
             }
             else
             {
             //set the source file to the resolved file
                 CPLFree( m_pszFilename );
                 m_pszFilename = pszTmpName;
-                *pbOutIsTempFile = TRUE;
+                *pbOutIsTempFile = true;
             }
         }
         else
@@ -618,7 +618,7 @@ int GMLReader::ResolveXlinks( const char *pszFile,
     }
     else
     {
-        bReturn = FALSE;
+        bReturn = false;
     }
 
     int nItems = CSLCount( papszResourceHREF );
diff --git a/ogr/ogrsf_frmts/gml/trstring.cpp b/ogr/ogrsf_frmts/gml/trstring.cpp
index def831c..ddc8d7c 100644
--- a/ogr/ogrsf_frmts/gml/trstring.cpp
+++ b/ogr/ogrsf_frmts/gml/trstring.cpp
@@ -1,9 +1,9 @@
 /******************************************************************************
- * $Id: trstring.cpp 22205 2011-04-18 21:17:30Z rouault $
+ * $Id: trstring.cpp 33702 2016-03-11 06:20:16Z goatbar $
  *
  * Project:  GML Reader
  * Purpose:  Functions for translating back and forth between XMLCh and char.
- *           We assume that XMLCh is a simple numeric type that we can 
+ *           We assume that XMLCh is a simple numeric type that we can
  *           correspond 1:1 with char values, but that it likely is larger
  *           than a char.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
@@ -17,16 +17,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
@@ -51,7 +51,7 @@ static int tr_isascii( const char * pszCString )
 
         pszCString++;
     }
-    
+
     return TRUE;
 }
 
@@ -69,9 +69,9 @@ int tr_strcmp( const char *pszCString, const XMLCh *panXMLString )
 /* -------------------------------------------------------------------- */
     if( tr_isascii( pszCString ) )
     {
-        while( pszCString[i] != 0 && panXMLString[i] != 0 
+        while( pszCString[i] != 0 && panXMLString[i] != 0
                && pszCString[i] == panXMLString[i] ) {}
-        
+
         if( pszCString[i] == 0 && panXMLString[i] == 0 )
             return 0;
         else if( pszCString[i] < panXMLString[i] )
@@ -84,12 +84,12 @@ int tr_strcmp( const char *pszCString, const XMLCh *panXMLString )
 /*      Translated UTF8 to XMLCh for comparison.                        */
 /* -------------------------------------------------------------------- */
     XMLCh *panFirst = (XMLCh *) CPLCalloc(strlen(pszCString)+1,sizeof(XMLCh));
-    
+
     tr_strcpy( panFirst, pszCString );
-    
-    while( panFirst[i] != 0 && panXMLString[i] != 0 
+
+    while( panFirst[i] != 0 && panXMLString[i] != 0
            && panFirst[i] == panXMLString[i] ) {}
-        
+
     if( panFirst[i] == 0 && panXMLString[i] == 0 )
     {
         CPLFree( panFirst );
@@ -128,12 +128,12 @@ void tr_strcpy( XMLCh *panXMLString, const char *pszCString )
 /* -------------------------------------------------------------------- */
 /*      Otherwise we need to do a full UTC2 to UTF-8 conversion.        */
 /* -------------------------------------------------------------------- */
-    int i;
     wchar_t *pwszUTF16;
 
     pwszUTF16 = CPLRecodeToWChar( pszCString, CPL_ENC_UTF8, "WCHAR_T" );
-    
-    for( i = 0; pwszUTF16[i] != 0; i++ )
+
+    int i = 0;
+    for( ; pwszUTF16[i] != 0; i++ )
         panXMLString[i] = pwszUTF16[i];
 
     panXMLString[i] = 0;
@@ -172,16 +172,16 @@ void tr_strcpy( char *pszCString, const XMLCh *panXMLString )
 /*      all simple ASCII characters.  Redo using the more expensive     */
 /*      recoding API.                                                   */
 /* -------------------------------------------------------------------- */
-    int i;
     wchar_t *pwszSource = (wchar_t *) CPLCalloc(sizeof(wchar_t),
                                                 tr_strlen(panXMLStringOriginal)+1 );
-    for( i = 0; panXMLString[i] != 0; i++ )
+    int i = 0;
+    for( ; panXMLString[i] != 0; i++ )
         pwszSource[i] = panXMLString[i];
     pwszSource[i] = 0;
-    
-    char *pszResult = CPLRecodeFromWChar( pwszSource, 
+
+    char *pszResult = CPLRecodeFromWChar( pwszSource,
                                           "WCHAR_T", CPL_ENC_UTF8 );
-    
+
     strcpy( pszCString, pszResult );
 
     CPLFree( pwszSource );
@@ -196,7 +196,7 @@ int tr_strlen( const XMLCh *panXMLString )
 
 {
     int nLength = 0;
-    
+
     while( *(panXMLString++) != 0 )
         nLength++;
 
diff --git a/ogr/ogrsf_frmts/gml/xercesc_headers.h b/ogr/ogrsf_frmts/gml/xercesc_headers.h
new file mode 100644
index 0000000..7920072
--- /dev/null
+++ b/ogr/ogrsf_frmts/gml/xercesc_headers.h
@@ -0,0 +1,55 @@
+/******************************************************************************
+ *
+ * Project:  GDAL
+ * Purpose:  Includes Xerces-C headers
+ * Author:   Even Rouault <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+#ifndef XERCESC_HEADERS_H
+#define XERCESC_HEADERS_H
+
+#if ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) && !defined(_MSC_VER))
+#pragma GCC system_header
+#endif
+
+// This works around problems with math.h on some platforms #defining INFINITY
+#ifdef INFINITY
+#undef  INFINITY
+#define INFINITY INFINITY_XERCES
+#endif
+
+#include <util/PlatformUtils.hpp>
+#include <sax2/DefaultHandler.hpp>
+#include <sax2/ContentHandler.hpp>
+#include <sax2/SAX2XMLReader.hpp>
+#include <sax2/XMLReaderFactory.hpp>
+#include <sax2/Attributes.hpp>
+#include <sax/InputSource.hpp>
+#include <util/BinInputStream.hpp>
+
+#ifdef XERCES_CPP_NAMESPACE_USE
+XERCES_CPP_NAMESPACE_USE
+#endif
+
+#endif /* XERCESC_HEADERS_H */
diff --git a/ogr/ogrsf_frmts/gmt/drv_gmt.html b/ogr/ogrsf_frmts/gmt/drv_gmt.html
index e2bcede..c8b67f5 100644
--- a/ogr/ogrsf_frmts/gmt/drv_gmt.html
+++ b/ogr/ogrsf_frmts/gmt/drv_gmt.html
@@ -8,21 +8,21 @@
 <h1>GMT ASCII Vectors (.gmt)</h1>
 
 OGR supports reading and writing GMT ASCII vector format.  This is the
-format used by the Generic Mapping Tools (GMT) package, and includes 
+format used by the Generic Mapping Tools (GMT) package, and includes
 recent additions to the format to handle more geometry types, and attributes.
-Currently GMT files are only supported if they have the extension ".gmt". 
+Currently GMT files are only supported if they have the extension ".gmt".
 
 Old (simple) GMT files are treated as either point, or linestring files
-depending on whether a ">" line is encountered before the first vertex. 
+depending on whether a ">" line is encountered before the first vertex.
 New style files have a variety of auxiliary information including geometry
 type, layer extents, coordinate system and attribute field declarations in
-comments in the header, and for each feature can have attributes. 
+comments in the header, and for each feature can have attributes.
 
 <h2>Creation Issues</h2>
 
 The driver supports creating new GMT files, and appending additional features
 to existing files, but update of existing features is not supported.  Each
-layer is created as a seperate .gmt file.
+layer is created as a separate .gmt file.
 
 If a name that ends with .gmt is not given, then the GMT driver will take
 the layer name and add the ".gmt" extension.
diff --git a/ogr/ogrsf_frmts/gmt/ogr_gmt.h b/ogr/ogrsf_frmts/gmt/ogr_gmt.h
index a5b61b3..0b45abf 100644
--- a/ogr/ogrsf_frmts/gmt/ogr_gmt.h
+++ b/ogr/ogrsf_frmts/gmt/ogr_gmt.h
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGRGMT_H_INCLUDED
-#define _OGRGMT_H_INCLUDED
+#ifndef OGRGMT_H_INCLUDED
+#define OGRGMT_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "ogr_api.h"
@@ -42,15 +42,13 @@ class OGRGmtLayer : public OGRLayer
 {
     OGRSpatialReference *poSRS;
     OGRFeatureDefn     *poFeatureDefn;
-    
-    int                 iNextFID;
 
-    OGRwkbGeometryType  eWkbType;
+    int                 iNextFID;
 
-    int                 bUpdate;
-    int                 bHeaderComplete;
+    bool                bUpdate;
+    bool                bHeaderComplete;
 
-    int                 bRegionComplete;
+    bool                bRegionComplete;
     OGREnvelope         sRegion;
     vsi_l_offset        nRegionOffset;
 
@@ -80,9 +78,11 @@ class OGRGmtLayer : public OGRLayer
     OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
 
     OGRErr              GetExtent(OGREnvelope *psExtent, int bForce);
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
     OGRErr              ICreateFeature( OGRFeature *poFeature );
-    
+
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
                                      int bApproxOK = TRUE );
 
@@ -97,10 +97,10 @@ class OGRGmtDataSource : public OGRDataSource
 {
     OGRGmtLayer       **papoLayers;
     int                 nLayers;
-    
+
     char                *pszName;
 
-    int                 bUpdate;
+    bool                bUpdate;
 
   public:
                         OGRGmtDataSource();
@@ -113,7 +113,7 @@ class OGRGmtDataSource : public OGRDataSource
     int                 GetLayerCount() { return nLayers; }
     OGRLayer            *GetLayer( int );
 
-    virtual OGRLayer    *ICreateLayer( const char *, 
+    virtual OGRLayer    *ICreateLayer( const char *,
                                       OGRSpatialReference * = NULL,
                                       OGRwkbGeometryType = wkbUnknown,
                                       char ** = NULL );
@@ -128,16 +128,15 @@ class OGRGmtDriver : public OGRSFDriver
 {
   public:
                 ~OGRGmtDriver();
-                
+
     const char *GetName();
     OGRDataSource *Open( const char *, int );
 
     virtual OGRDataSource *CreateDataSource( const char *pszName,
                                              char ** = NULL );
-    
+
     int                 TestCapability( const char * );
 };
 
 
-#endif /* ndef _OGRGMT_H_INCLUDED */
-
+#endif /* ndef OGRGMT_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/gmt/ogrgmtdatasource.cpp b/ogr/ogrsf_frmts/gmt/ogrgmtdatasource.cpp
index ffd25e0..9bf9db7 100644
--- a/ogr/ogrsf_frmts/gmt/ogrgmtdatasource.cpp
+++ b/ogr/ogrsf_frmts/gmt/ogrgmtdatasource.cpp
@@ -27,9 +27,9 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_gmt.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "ogr_gmt.h"
 
 CPL_CVSID("$Id: ogrgmtdatasource.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
 
@@ -37,15 +37,12 @@ CPL_CVSID("$Id: ogrgmtdatasource.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
 /*                          OGRGmtDataSource()                          */
 /************************************************************************/
 
-OGRGmtDataSource::OGRGmtDataSource()
-
-{
-    pszName = NULL;
-    papoLayers = NULL;
-    nLayers = 0;
-
-    bUpdate = FALSE;
-}
+OGRGmtDataSource::OGRGmtDataSource() :
+    papoLayers(NULL),
+    nLayers(0),
+    pszName(NULL),
+    bUpdate(false)
+{}
 
 /************************************************************************/
 /*                         ~OGRGmtDataSource()                          */
@@ -54,22 +51,20 @@ OGRGmtDataSource::OGRGmtDataSource()
 OGRGmtDataSource::~OGRGmtDataSource()
 
 {
-    CPLFree( pszName );
-
     for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
-    
     CPLFree( papoLayers );
+    CPLFree( pszName );
 }
 
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
 
-int OGRGmtDataSource::Open( const char *pszFilename, int bUpdate )
+int OGRGmtDataSource::Open( const char *pszFilename, int bUpdateIn )
 
 {
-    this->bUpdate = bUpdate;
+    bUpdate = CPL_TO_BOOL( bUpdateIn );
 
     OGRGmtLayer *poLayer = new OGRGmtLayer( pszFilename, bUpdate );
     if( !poLayer->bValidFile )
@@ -79,7 +74,7 @@ int OGRGmtDataSource::Open( const char *pszFilename, int bUpdate )
     }
 
     nLayers = 1;
-    papoLayers = (OGRGmtLayer **) CPLMalloc(sizeof(void*));
+    papoLayers = static_cast<OGRGmtLayer **>( CPLMalloc(sizeof(void*)) );
     papoLayers[0] = poLayer;
 
     CPLFree (pszName);
@@ -91,15 +86,13 @@ int OGRGmtDataSource::Open( const char *pszFilename, int bUpdate )
 /************************************************************************/
 /*                               Create()                               */
 /*                                                                      */
-/*      Create a new datasource.  This doesn't really do anything       */
+/*      Create a new datasource.  This does not really do anything      */
 /*      currently but save the name.                                    */
 /************************************************************************/
 
-int OGRGmtDataSource::Create( const char *pszDSName, char **papszOptions )
+int OGRGmtDataSource::Create( const char *pszDSName, char ** /* papszOptions */)
 
 {
-    (void) papszOptions;
-
     pszName = CPLStrdup( pszDSName );
 
     return TRUE;
@@ -164,8 +157,8 @@ OGRGmtDataSource::ICreateLayer( const char * pszLayerName,
     VSILFILE *fp = VSIFOpenL( osFilename, "w" );
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "open(%s) failed: %s", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "open(%s) failed: %s",
                   osFilename.c_str(), VSIStrerror(errno) );
         return NULL;
     }
@@ -174,30 +167,30 @@ OGRGmtDataSource::ICreateLayer( const char * pszLayerName,
 /*      Write out header.                                               */
 /* -------------------------------------------------------------------- */
     VSIFPrintfL( fp, "# @VGMT1.0%s\n", pszGeom );
-    VSIFPrintfL( fp, "# REGION_STUB                                                             \n" );
+    VSIFPrintfL( fp, "# REGION_STUB                                      "
+                 "                       \n" );
 
 /* -------------------------------------------------------------------- */
 /*      Write the projection, if possible.                              */
 /* -------------------------------------------------------------------- */
     if( poSRS != NULL )
     {
-        char *pszValue = NULL;
-
-        if( poSRS->IsProjected() 
+        if( poSRS->IsProjected()
             && poSRS->GetAuthorityName("PROJCS")
             && EQUAL(poSRS->GetAuthorityName("PROJCS"),"EPSG") )
         {
-            VSIFPrintfL( fp, "# @Je%s\n", 
+            VSIFPrintfL( fp, "# @Je%s\n",
                          poSRS->GetAuthorityCode("PROJCS") );
         }
-        else if( poSRS->IsGeographic() 
+        else if( poSRS->IsGeographic()
                  && poSRS->GetAuthorityName("GEOGCS")
                  && EQUAL(poSRS->GetAuthorityName("GEOGCS"),"EPSG") )
         {
-            VSIFPrintfL( fp, "# @Je%s\n", 
+            VSIFPrintfL( fp, "# @Je%s\n",
                          poSRS->GetAuthorityCode("GEOGCS") );
         }
 
+        char *pszValue = NULL;
         if( poSRS->exportToProj4( &pszValue ) == OGRERR_NONE )
         {
             VSIFPrintfL( fp, "# @Jp\"%s\"\n", pszValue );
@@ -209,7 +202,7 @@ OGRGmtDataSource::ICreateLayer( const char * pszLayerName,
         {
             char *pszEscapedWkt = CPLEscapeString( pszValue, -1,
                                                    CPLES_BackslashQuotable );
-                                                   
+
             VSIFPrintfL( fp, "# @Jw\"%s\"\n", pszEscapedWkt );
             CPLFree( pszValue );
             CPLFree( pszEscapedWkt );
@@ -227,8 +220,8 @@ OGRGmtDataSource::ICreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
     if( Open( osFilename, TRUE ) )
         return papoLayers[nLayers-1];
-    else
-        return NULL;
+
+    return NULL;
 }
 
 /************************************************************************/
@@ -240,8 +233,8 @@ int OGRGmtDataSource::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,ODsCCreateLayer) )
         return TRUE;
-    else
-        return FALSE;
+
+    return FALSE;
 }
 
 /************************************************************************/
@@ -253,6 +246,6 @@ OGRLayer *OGRGmtDataSource::GetLayer( int iLayer )
 {
     if( iLayer < 0 || iLayer >= nLayers )
         return NULL;
-    else
-        return papoLayers[iLayer];
+
+    return papoLayers[iLayer];
 }
diff --git a/ogr/ogrsf_frmts/gmt/ogrgmtdriver.cpp b/ogr/ogrsf_frmts/gmt/ogrgmtdriver.cpp
index f9b4c95..1d0fd90 100644
--- a/ogr/ogrsf_frmts/gmt/ogrgmtdriver.cpp
+++ b/ogr/ogrsf_frmts/gmt/ogrgmtdriver.cpp
@@ -37,10 +37,7 @@ CPL_CVSID("$Id: ogrmemdriver.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
 /*                          ~OGRGmtDriver()                           */
 /************************************************************************/
 
-OGRGmtDriver::~OGRGmtDriver()
-
-{
-}
+OGRGmtDriver::~OGRGmtDriver() {}
 
 /************************************************************************/
 /*                              GetName()                               */
@@ -69,8 +66,8 @@ OGRDataSource *OGRGmtDriver::Open( const char * pszFilename, int bUpdate )
         delete poDS;
         return NULL;
     }
-    else
-        return poDS;
+
+    return poDS;
 }
 
 /************************************************************************/
@@ -85,11 +82,10 @@ OGRDataSource *OGRGmtDriver::CreateDataSource( const char * pszName,
 
     if( poDS->Create( pszName, papszOptions ) )
         return poDS;
-    else
-    {
-        delete poDS;
-        return NULL;
-    }
+
+
+    delete poDS;
+    return NULL;
 }
 
 /************************************************************************/
@@ -101,8 +97,8 @@ int OGRGmtDriver::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,ODrCCreateDataSource) )
         return TRUE;
-    else
-        return FALSE;
+
+    return FALSE;
 }
 
 /************************************************************************/
@@ -113,11 +109,8 @@ void RegisterOGRGMT()
 
 {
     OGRSFDriver* poDriver = new OGRGmtDriver;
-    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                "GMT ASCII Vectors (.gmt)" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "GMT ASCII Vectors (.gmt)" );
     poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gmt" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                "drv_gmt.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_gmt.html" );
     OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver(poDriver);
 }
-
diff --git a/ogr/ogrsf_frmts/gmt/ogrgmtlayer.cpp b/ogr/ogrsf_frmts/gmt/ogrgmtlayer.cpp
index e8ca183..d547eb0 100644
--- a/ogr/ogrsf_frmts/gmt/ogrgmtlayer.cpp
+++ b/ogr/ogrsf_frmts/gmt/ogrgmtlayer.cpp
@@ -37,22 +37,18 @@ CPL_CVSID("$Id: ogrgmtlayer.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
 /*                            OGRGmtLayer()                             */
 /************************************************************************/
 
-OGRGmtLayer::OGRGmtLayer( const char * pszFilename, int bUpdate )
-
+OGRGmtLayer::OGRGmtLayer( const char * pszFilename, int bUpdateIn ) :
+    poSRS(NULL),
+    poFeatureDefn(NULL),
+    iNextFID(0),
+    bUpdate(CPL_TO_BOOL(bUpdateIn)),
+    // Assume header complete in readonly mode.
+    bHeaderComplete(CPL_TO_BOOL(!bUpdate)),
+    bRegionComplete(false),
+    nRegionOffset(0),
+    papszKeyedValues(NULL),
+    bValidFile(FALSE)
 {
-    poSRS = NULL;
-    
-    iNextFID = 0;
-    bValidFile = FALSE;
-    bHeaderComplete = !bUpdate; // assume header complete in readonly mode.
-    eWkbType = wkbUnknown;
-    poFeatureDefn = NULL;
-    papszKeyedValues = NULL;
-
-    this->bUpdate = bUpdate;
-
-    bRegionComplete = FALSE;
-    nRegionOffset = 0;
 
 /* -------------------------------------------------------------------- */
 /*      Open file.                                                      */
@@ -61,21 +57,24 @@ OGRGmtLayer::OGRGmtLayer( const char * pszFilename, int bUpdate )
         fp = VSIFOpenL( pszFilename, "r+" );
     else
         fp = VSIFOpenL( pszFilename, "r" );
-    
+
     if( fp == NULL )
         return;
 
 /* -------------------------------------------------------------------- */
 /*      Read the header.                                                */
 /* -------------------------------------------------------------------- */
-    CPLString osFieldNames, osFieldTypes, osGeometryType, osRegion;
-    CPLString osWKT, osProj4, osEPSG;
+    CPLString osFieldNames;
+    CPLString osFieldTypes;
+    CPLString osGeometryType;
+    CPLString osRegion;
+    CPLString osWKT;
+    CPLString osProj4;
+    CPLString osEPSG;
     vsi_l_offset nStartOfLine = VSIFTellL(fp);
-    
+
     while( ReadLine() && osLine[0] == '#' )
     {
-        int iKey;
-
         if( strstr( osLine, "FEATURE_DATA" ) )
         {
             bHeaderComplete = TRUE;
@@ -83,11 +82,11 @@ OGRGmtLayer::OGRGmtLayer( const char * pszFilename, int bUpdate )
             break;
         }
 
-        if( EQUALN( osLine, "# REGION_STUB ", 14 ) )
+        if( STARTS_WITH_CI(osLine, "# REGION_STUB ") )
             nRegionOffset = nStartOfLine;
 
-        for( iKey = 0; 
-             papszKeyedValues != NULL && papszKeyedValues[iKey] != NULL; 
+        for( int iKey = 0;
+             papszKeyedValues != NULL && papszKeyedValues[iKey] != NULL;
              iKey++ )
         {
             if( papszKeyedValues[iKey][0] == 'N' )
@@ -109,7 +108,7 @@ OGRGmtLayer::OGRGmtLayer( const char * pszFilename, int bUpdate )
                     osArg = pszArg;
                     CPLFree( pszArg );
                 }
-                    
+
                 if( papszKeyedValues[iKey][1] == 'e' )
                     osEPSG = osArg;
                 if( papszKeyedValues[iKey][1] == 'p' )
@@ -184,7 +183,7 @@ OGRGmtLayer::OGRGmtLayer( const char * pszFilename, int bUpdate )
     {
         char **papszTokens = CSLTokenizeStringComplex( osRegion.c_str(),
                                                        "/", FALSE, FALSE );
-        
+
         if( CSLCount(papszTokens) == 4 )
         {
             sRegion.MinX = CPLAtofM(papszTokens[0]);
@@ -203,14 +202,13 @@ OGRGmtLayer::OGRGmtLayer( const char * pszFilename, int bUpdate )
 /* -------------------------------------------------------------------- */
     if( osFieldNames.length() || osFieldTypes.length() )
     {
-        char **papszFN = CSLTokenizeStringComplex( osFieldNames, "|", 
+        char **papszFN = CSLTokenizeStringComplex( osFieldNames, "|",
                                                    TRUE, TRUE );
-        char **papszFT = CSLTokenizeStringComplex( osFieldTypes, "|", 
+        char **papszFT = CSLTokenizeStringComplex( osFieldTypes, "|",
                                                    TRUE, TRUE );
-        int nFieldCount = MAX(CSLCount(papszFN),CSLCount(papszFT));
-        int iField;
+        const int nFieldCount = MAX(CSLCount(papszFN),CSLCount(papszFT));
 
-        for( iField = 0; iField < nFieldCount; iField++ )
+        for( int iField = 0; iField < nFieldCount; iField++ )
         {
             OGRFieldDefn oField("", OFTString );
 
@@ -249,7 +247,7 @@ OGRGmtLayer::~OGRGmtLayer()
     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     {
         CPLDebug( "Gmt", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
+                  (int) m_nFeaturesRead,
                   poFeatureDefn->GetName() );
     }
 
@@ -260,13 +258,13 @@ OGRGmtLayer::~OGRGmtLayer()
     if( nRegionOffset != 0 && bUpdate )
     {
         VSIFSeekL( fp, nRegionOffset, SEEK_SET );
-        VSIFPrintfL( fp, "# @R%.12g/%.12g/%.12g/%.12g", 
-                     sRegion.MinX, 
+        VSIFPrintfL( fp, "# @R%.12g/%.12g/%.12g/%.12g",
+                     sRegion.MinX,
                      sRegion.MaxX,
                      sRegion.MinY,
                      sRegion.MaxY );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Clean up.                                                       */
 /* -------------------------------------------------------------------- */
@@ -302,7 +300,7 @@ int OGRGmtLayer::ReadLine()
         CSLDestroy( papszKeyedValues );
         papszKeyedValues = NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read newline.                                                   */
 /* -------------------------------------------------------------------- */
@@ -315,25 +313,25 @@ int OGRGmtLayer::ReadLine()
 /* -------------------------------------------------------------------- */
 /*      If this is a comment line with keyed values, parse them.        */
 /* -------------------------------------------------------------------- */
-    size_t i;
 
     if( osLine[0] != '#' || osLine.find_first_of('@') == std::string::npos )
         return TRUE;
 
-    for( i = 0; i < osLine.length(); i++ )
+    for( size_t i = 0; i < osLine.length(); i++ )
     {
         if( osLine[i] == '@' )
         {
-            size_t iValEnd;
-            int bInQuotes = FALSE;
+            bool bInQuotes = false;
 
+            size_t iValEnd;
             for( iValEnd = i+2; iValEnd < osLine.length(); iValEnd++ )
             {
                 if( !bInQuotes && isspace((unsigned char)osLine[iValEnd]) )
                     break;
 
-                if( bInQuotes && osLine[iValEnd] == '\\' 
-                    && iValEnd < osLine.length()-1 )
+                if( bInQuotes
+                    && iValEnd < osLine.length()-1
+                    && osLine[iValEnd] == '\\' )
                 {
                     iValEnd++;
                 }
@@ -341,12 +339,12 @@ int OGRGmtLayer::ReadLine()
                     bInQuotes = !bInQuotes;
             }
 
-            CPLString osValue = osLine.substr(i+2,iValEnd-i-2);
+            const CPLString osValue = osLine.substr(i+2,iValEnd-i-2);
 
             // Unecape contents
-            char *pszUEValue = CPLUnescapeString( osValue, NULL, 
+            char *pszUEValue = CPLUnescapeString( osValue, NULL,
                                                   CPLES_BackslashQuotable );
-            
+
             CPLString osKeyValue = osLine.substr(i+1,1);
             osKeyValue += pszUEValue;
             CPLFree( pszUEValue );
@@ -366,12 +364,12 @@ int OGRGmtLayer::ReadLine()
 void OGRGmtLayer::ResetReading()
 
 {
-    if( iNextFID != 0 )
-    {
-        iNextFID = 0;
-        VSIFSeekL( fp, 0, SEEK_SET );
-        ReadLine();
-    }
+    if( iNextFID == 0 )
+        return;
+
+    iNextFID = 0;
+    VSIFSeekL( fp, 0, SEEK_SET );
+    ReadLine();
 }
 
 /************************************************************************/
@@ -385,8 +383,8 @@ void OGRGmtLayer::ResetReading()
 int OGRGmtLayer::ScanAheadForHole()
 
 {
-    CPLString osSavedLine = osLine;
-    vsi_l_offset nSavedLocation = VSIFTellL( fp );
+    const CPLString osSavedLine = osLine;
+    const vsi_l_offset nSavedLocation = VSIFTellL( fp );
 
     while( ReadLine() && osLine[0] == '#' )
     {
@@ -397,8 +395,8 @@ int OGRGmtLayer::ScanAheadForHole()
     VSIFSeekL( fp, nSavedLocation, SEEK_SET );
     osLine = osSavedLine;
 
-    // We don't actually restore papszKeyedValues, but we 
-    // assume it doesn't matter since this method is only called
+    // We do not actually restore papszKeyedValues, but we
+    // assume it does not matter since this method is only called
     // when processing the '>' line.
 
     return FALSE;
@@ -415,20 +413,20 @@ int OGRGmtLayer::ScanAheadForHole()
 int OGRGmtLayer::NextIsFeature()
 
 {
-    CPLString osSavedLine = osLine;
-    vsi_l_offset nSavedLocation = VSIFTellL( fp );
-    int bReturn = FALSE;
+    const CPLString osSavedLine = osLine;
+    const vsi_l_offset nSavedLocation = VSIFTellL( fp );
+    bool bReturn = false;
 
     ReadLine();
 
     if( osLine[0] == '#' && strstr(osLine,"@D") != NULL )
-        bReturn = TRUE;
+        bReturn = true;
 
     VSIFSeekL( fp, nSavedLocation, SEEK_SET );
     osLine = osSavedLine;
 
-    // We don't actually restore papszKeyedValues, but we 
-    // assume it doesn't matter since this method is only called
+    // We do not actually restore papszKeyedValues, but we
+    // assume it does not matter since this method is only called
     // when processing the '>' line.
 
     return bReturn;
@@ -442,7 +440,7 @@ OGRFeature *OGRGmtLayer::GetNextRawFeature()
 
 {
 #if 0
-    int  bMultiVertex =
+    int bMultiVertex =
         poFeatureDefn->GetGeomType() != wkbPoint
         && poFeatureDefn->GetGeomType() != wkbUnknown;
 #endif
@@ -452,14 +450,14 @@ OGRFeature *OGRGmtLayer::GetNextRawFeature()
 /* -------------------------------------------------------------------- */
 /*      Read lines associated with this feature.                        */
 /* -------------------------------------------------------------------- */
-    for( ; TRUE; ReadLine() )
+    for( ; true; ReadLine() )
     {
         if( osLine.length() == 0 )
             break;
 
         if( osLine[0] == '>' )
         {
-            if( poGeom != NULL 
+            if( poGeom != NULL
                 && wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon )
             {
                 OGRMultiPolygon *poMP = (OGRMultiPolygon *) poGeom;
@@ -473,7 +471,7 @@ OGRFeature *OGRGmtLayer::GetNextRawFeature()
                 else if( !NextIsFeature() )
                 {
                     OGRPolygon *poPoly = new OGRPolygon();
-                    
+
                     poPoly->addRingDirectly( new OGRLinearRing() );
 
                     poMP->addGeometryDirectly( poPoly );
@@ -481,7 +479,7 @@ OGRFeature *OGRGmtLayer::GetNextRawFeature()
                 else
                     break; /* done geometry */
             }
-            else if( poGeom != NULL 
+            else if( poGeom != NULL
                      && wkbFlatten(poGeom->getGeometryType()) == wkbPolygon)
             {
                 if( ScanAheadForHole() )
@@ -490,8 +488,8 @@ OGRFeature *OGRGmtLayer::GetNextRawFeature()
                 else
                     break; /* done geometry */
             }
-            else if( poGeom != NULL 
-                     && (wkbFlatten(poGeom->getGeometryType()) 
+            else if( poGeom != NULL
+                     && (wkbFlatten(poGeom->getGeometryType())
                          == wkbMultiLineString)
                      && !NextIsFeature() )
             {
@@ -510,9 +508,8 @@ OGRFeature *OGRGmtLayer::GetNextRawFeature()
         }
         else if( osLine[0] == '#' )
         {
-            int i;
-            for( i = 0;
-                 papszKeyedValues != NULL && papszKeyedValues[i] != NULL; 
+            for( int i = 0;
+                 papszKeyedValues != NULL && papszKeyedValues[i] != NULL;
                  i++ )
             {
                 if( papszKeyedValues[i][0] == 'D' )
@@ -521,10 +518,13 @@ OGRFeature *OGRGmtLayer::GetNextRawFeature()
         }
         else
         {
-            // Parse point line. 
-            double dfX, dfY, dfZ = 0.0;
-            int nDim = CPLsscanf( osLine, "%lf %lf %lf", &dfX, &dfY, &dfZ );
-                
+            // Parse point line.
+            double dfX;
+            double dfY;
+            double dfZ = 0.0;
+            const int nDim
+                = CPLsscanf( osLine, "%lf %lf %lf", &dfX, &dfY, &dfZ );
+
             if( nDim >= 2 )
             {
                 if( poGeom == NULL )
@@ -534,32 +534,32 @@ OGRFeature *OGRGmtLayer::GetNextRawFeature()
                       case wkbLineString:
                         poGeom = new OGRLineString();
                         break;
-                    
+
                       case wkbPolygon:
                         poGeom = new OGRPolygon();
-                        ((OGRPolygon *) poGeom)->addRingDirectly(
+                        reinterpret_cast<OGRPolygon *>(poGeom)->addRingDirectly(
                             new OGRLinearRing() );
                         break;
-                    
+
                       case wkbMultiPolygon:
                       {
                           OGRPolygon *poPoly = new OGRPolygon();
                           poPoly->addRingDirectly( new OGRLinearRing() );
 
                           poGeom = new OGRMultiPolygon();
-                          ((OGRMultiPolygon *) poGeom)->
+                          reinterpret_cast<OGRMultiPolygon *>(poGeom)->
                               addGeometryDirectly( poPoly );
                       }
                       break;
-                    
+
                       case wkbMultiPoint:
                         poGeom = new OGRMultiPoint();
                         break;
 
                       case wkbMultiLineString:
                         poGeom = new OGRMultiLineString();
-                        ((OGRMultiLineString *) poGeom)->addGeometryDirectly(
-                            new OGRLineString() );
+                        reinterpret_cast<OGRMultiLineString *>(poGeom)->
+                            addGeometryDirectly(new OGRLineString() );
                         break;
 
                       case wkbPoint:
@@ -574,26 +574,27 @@ OGRFeature *OGRGmtLayer::GetNextRawFeature()
                 switch( wkbFlatten(poGeom->getGeometryType()) )
                 {
                   case wkbPoint:
-                    ((OGRPoint *) poGeom)->setX( dfX );
-                    ((OGRPoint *) poGeom)->setY( dfY );
+                    reinterpret_cast<OGRPoint *>(poGeom)->setX( dfX );
+                    reinterpret_cast<OGRPoint *>(poGeom)->setY( dfY );
                     if( nDim == 3 )
-                        ((OGRPoint *) poGeom)->setZ( dfZ );
+                        reinterpret_cast<OGRPoint *>(poGeom)->setZ( dfZ );
                     break;
 
                   case wkbLineString:
                     if( nDim == 3 )
-                        ((OGRLineString *)poGeom)->addPoint(dfX,dfY,dfZ);
+                        reinterpret_cast<OGRLineString *>(poGeom)->
+                            addPoint( dfX, dfY, dfZ);
                     else
-                        ((OGRLineString *)poGeom)->addPoint(dfX,dfY);
+                        reinterpret_cast<OGRLineString *>(poGeom)->
+                            addPoint( dfX, dfY );
                     break;
 
                   case wkbPolygon:
                   case wkbMultiPolygon:
                   {
-                      OGRPolygon *poPoly;
-                      OGRLinearRing *poRing;
+                      OGRPolygon *poPoly = NULL;
 
-                      if( wkbFlatten(poGeom->getGeometryType()) 
+                      if( wkbFlatten(poGeom->getGeometryType())
                           == wkbMultiPolygon )
                       {
                           OGRMultiPolygon *poMP = (OGRMultiPolygon *) poGeom;
@@ -601,33 +602,32 @@ OGRFeature *OGRGmtLayer::GetNextRawFeature()
                               poMP->getNumGeometries() - 1 );
                       }
                       else
-                          poPoly = (OGRPolygon *) poGeom;
+                          poPoly = reinterpret_cast<OGRPolygon *>(poGeom);
 
+                      OGRLinearRing *poRing = NULL;
                       if( poPoly->getNumInteriorRings() == 0 )
                           poRing = poPoly->getExteriorRing();
                       else
                           poRing = poPoly->getInteriorRing(
                               poPoly->getNumInteriorRings()-1 );
-                      
+
                       if( nDim == 3 )
-                        poRing->addPoint(dfX,dfY,dfZ);
+                          poRing->addPoint( dfX, dfY, dfZ );
                       else
-                        poRing->addPoint(dfX,dfY);
+                          poRing->addPoint( dfX, dfY );
                   }
                   break;
 
                   case wkbMultiLineString:
                   {
                       OGRMultiLineString *poML = (OGRMultiLineString *) poGeom;
-                      OGRLineString *poLine;
+                      OGRLineString *poLine = reinterpret_cast<OGRLineString *>(
+                          poML->getGeometryRef( poML->getNumGeometries() -1 ) );
 
-                      poLine = (OGRLineString *) 
-                          poML->getGeometryRef( poML->getNumGeometries()-1 );
-                      
                       if( nDim == 3 )
-                        poLine->addPoint(dfX,dfY,dfZ);
+                          poLine->addPoint( dfX, dfY, dfZ );
                       else
-                        poLine->addPoint(dfX,dfY);
+                          poLine->addPoint( dfX, dfY );
                   }
                   break;
 
@@ -659,9 +659,8 @@ OGRFeature *OGRGmtLayer::GetNextRawFeature()
 /*      Process field values.                                           */
 /* -------------------------------------------------------------------- */
     char **papszFD = CSLTokenizeStringComplex( osFieldData, "|", TRUE, TRUE );
-    int iField; 
 
-    for( iField = 0; papszFD != NULL && papszFD[iField] != NULL; iField++ )
+    for( int iField = 0; papszFD != NULL && papszFD[iField] != NULL; iField++ )
     {
         if( iField >= poFeatureDefn->GetFieldCount() )
             break;
@@ -683,7 +682,7 @@ OGRFeature *OGRGmtLayer::GetNextRawFeature()
 OGRFeature *OGRGmtLayer::GetNextFeature()
 
 {
-    while( TRUE )
+    while( true )
     {
         OGRFeature *poFeature = GetNextRawFeature();
 
@@ -697,10 +696,8 @@ OGRFeature *OGRGmtLayer::GetNextFeature()
         {
             return poFeature;
         }
-        else
-        {
-            delete poFeature;
-        }
+
+        delete poFeature;
     }
 
     return NULL;
@@ -717,16 +714,15 @@ OGRErr OGRGmtLayer::CompleteHeader( OGRGeometry *poThisGeom )
 
 {
 /* -------------------------------------------------------------------- */
-/*      If we don't already have a geometry type, try to work one       */
+/*      If we do not already have a geometry type, try to work one      */
 /*      out and write it now.                                           */
 /* -------------------------------------------------------------------- */
-    if( poFeatureDefn->GetGeomType() == wkbUnknown 
+    if( poFeatureDefn->GetGeomType() == wkbUnknown
         && poThisGeom != NULL )
     {
-        const char *pszGeom;
-
         poFeatureDefn->SetGeomType(wkbFlatten(poThisGeom->getGeometryType()));
 
+        const char *pszGeom = NULL;
         switch( wkbFlatten(poFeatureDefn->GetGeomType()) )
         {
           case wkbPoint:
@@ -751,18 +747,17 @@ OGRErr OGRGmtLayer::CompleteHeader( OGRGeometry *poThisGeom )
             pszGeom = "";
             break;
         }
-        
+
         VSIFPrintfL( fp, "#%s\n", pszGeom );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Prepare and write the field names and types.                    */
 /* -------------------------------------------------------------------- */
-    CPLString osFieldNames, osFieldTypes;
-        
-    int iField;
+    CPLString osFieldNames;
+    CPLString osFieldTypes;
 
-    for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
+    for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     {
         if( iField > 0 )
         {
@@ -776,15 +771,15 @@ OGRErr OGRGmtLayer::CompleteHeader( OGRGeometry *poThisGeom )
           case OFTInteger:
             osFieldTypes += "integer";
             break;
-                
+
           case OFTReal:
             osFieldTypes += "double";
             break;
-                
+
           case OFTDateTime:
             osFieldTypes += "datetime";
             break;
-                
+
           default:
             osFieldTypes += "string";
             break;
@@ -817,8 +812,8 @@ OGRErr OGRGmtLayer::ICreateFeature( OGRFeature *poFeature )
 {
     if( !bUpdate )
     {
-        CPLError( CE_Failure, CPLE_NoWriteAccess, 
-                  "Can't create features on read-only dataset." );
+        CPLError( CE_Failure, CPLE_NoWriteAccess,
+                  "Cannot create features on read-only dataset." );
         return OGRERR_FAILURE;
     }
 
@@ -837,10 +832,10 @@ OGRErr OGRGmtLayer::ICreateFeature( OGRFeature *poFeature )
 /*      Write out the feature                                           */
 /* -------------------------------------------------------------------- */
     OGRGeometry *poGeom = poFeature->GetGeometryRef();
-    
+
     if( poGeom == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Features without geometry not supported by GMT writer." );
         return OGRERR_FAILURE;
     }
@@ -848,7 +843,7 @@ OGRErr OGRGmtLayer::ICreateFeature( OGRFeature *poFeature )
     if( poFeatureDefn->GetGeomType() == wkbUnknown )
         poFeatureDefn->SetGeomType(wkbFlatten(poGeom->getGeometryType()));
 
-    // Do we need a vertex collection marker grouping vertices. 
+    // Do we need a vertex collection marker grouping vertices.
     if( poFeatureDefn->GetGeomType() != wkbPoint )
         VSIFPrintfL( fp, ">\n" );
 
@@ -857,34 +852,33 @@ OGRErr OGRGmtLayer::ICreateFeature( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
     if( poFeatureDefn->GetFieldCount() > 0 )
     {
-        int iField;
         CPLString osFieldData;
 
-        for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
+        for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
         {
             OGRFieldType eFType=poFeatureDefn->GetFieldDefn(iField)->GetType();
             const char *pszRawValue = poFeature->GetFieldAsString(iField);
-            char *pszEscapedVal;
 
             if( iField > 0 )
                 osFieldData += "|";
 
-            // We don't want prefix spaces for numeric values.
+            // We do not want prefix spaces for numeric values.
             if( eFType == OFTInteger || eFType == OFTReal )
                 while( *pszRawValue == ' ' )
                     pszRawValue++;
 
-            if( strchr(pszRawValue,' ') || strchr(pszRawValue,'|') 
+            if( strchr(pszRawValue,' ') || strchr(pszRawValue,'|')
                 || strchr(pszRawValue, '\t') || strchr(pszRawValue, '\n') )
             {
-                pszEscapedVal = 
-                    CPLEscapeString( pszRawValue, 
-                                     -1, CPLES_BackslashQuotable );
-                
                 osFieldData += "\"";
+
+                char *pszEscapedVal
+                    = CPLEscapeString( pszRawValue,
+                                       -1, CPLES_BackslashQuotable );
                 osFieldData += pszEscapedVal;
-                osFieldData += "\"";
                 CPLFree( pszEscapedVal );
+
+                osFieldData += "\"";
             }
             else
                 osFieldData += pszRawValue;
@@ -896,14 +890,14 @@ OGRErr OGRGmtLayer::ICreateFeature( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
 /*      Write Geometry                                                  */
 /* -------------------------------------------------------------------- */
-    return WriteGeometry( (OGRGeometryH) poGeom, TRUE );
+    return WriteGeometry( reinterpret_cast<OGRGeometryH>(poGeom), TRUE );
 }
 
 /************************************************************************/
 /*                           WriteGeometry()                            */
 /*                                                                      */
 /*      Write a geometry to the file.  If bHaveAngle is TRUE it         */
-/*      means the angle bracket preceeding the point stream has         */
+/*      means the angle bracket preceding the point stream has          */
 /*      already been written out.                                       */
 /*                                                                      */
 /*      We use the C API for geometry access because of it's            */
@@ -918,16 +912,15 @@ OGRErr OGRGmtLayer::WriteGeometry( OGRGeometryH hGeom, int bHaveAngle )
 /* -------------------------------------------------------------------- */
     if( OGR_G_GetGeometryCount( hGeom ) > 0 )
     {
-        int iGeom;
         OGRErr eErr = OGRERR_NONE;
-        
-        for( iGeom = 0; 
+
+        for( int iGeom = 0;
              iGeom < OGR_G_GetGeometryCount(hGeom) && eErr == OGRERR_NONE;
              iGeom++ )
         {
             // We need to emit polygon @P and @H items while we still
             // know this is a polygon and which is the outer and inner
-            // ring. 
+            // ring.
             if( wkbFlatten(OGR_G_GetGeometryType(hGeom)) == wkbPolygon )
             {
                 if( !bHaveAngle )
@@ -941,7 +934,7 @@ OGRErr OGRGmtLayer::WriteGeometry( OGRGeometryH hGeom, int bHaveAngle )
                     VSIFPrintfL( fp, "# @H\n" );
             }
 
-            eErr = WriteGeometry( OGR_G_GetGeometryRef( hGeom, iGeom ), 
+            eErr = WriteGeometry( OGR_G_GetGeometryRef( hGeom, iGeom ),
                                   bHaveAngle );
             bHaveAngle = FALSE;
         }
@@ -952,29 +945,29 @@ OGRErr OGRGmtLayer::WriteGeometry( OGRGeometryH hGeom, int bHaveAngle )
 /*      If this is not a point we need to have an angle bracket to      */
 /*      mark the vertex list.                                           */
 /* -------------------------------------------------------------------- */
-    if( wkbFlatten(OGR_G_GetGeometryType(hGeom)) != wkbPoint 
+    if( wkbFlatten(OGR_G_GetGeometryType(hGeom)) != wkbPoint
         && !bHaveAngle )
         VSIFPrintfL( fp, ">\n" );
 
 /* -------------------------------------------------------------------- */
 /*      Dump vertices.                                                  */
 /* -------------------------------------------------------------------- */
-    int iPoint, nPointCount = OGR_G_GetPointCount(hGeom);
-    int nDim = OGR_G_GetCoordinateDimension(hGeom);
+    const int nPointCount = OGR_G_GetPointCount(hGeom);
+    const int nDim = OGR_G_GetCoordinateDimension(hGeom);
 
-    for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+    for( int iPoint = 0; iPoint < nPointCount; iPoint++ )
     {
-        char   szLine[128];
-        double dfX = OGR_G_GetX( hGeom, iPoint );
-        double dfY = OGR_G_GetY( hGeom, iPoint );
-        double dfZ = OGR_G_GetZ( hGeom, iPoint );
+        const double dfX = OGR_G_GetX( hGeom, iPoint );
+        const double dfY = OGR_G_GetY( hGeom, iPoint );
+        const double dfZ = OGR_G_GetZ( hGeom, iPoint );
 
         sRegion.Merge( dfX, dfY );
+        char szLine[128];
         OGRMakeWktCoordinate( szLine, dfX, dfY, dfZ, nDim );
         if( VSIFPrintfL( fp, "%s\n", szLine ) < 1 )
         {
-            CPLError( CE_Failure, CPLE_FileIO, 
-                      "Gmt write failure: %s", 
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Gmt write failure: %s",
                       VSIStrerror( errno ) );
             return OGRERR_FAILURE;
         }
@@ -1015,20 +1008,19 @@ int OGRGmtLayer::TestCapability( const char * pszCap )
     if( EQUAL(pszCap,OLCRandomRead) )
         return FALSE;
 
-    else if( EQUAL(pszCap,OLCSequentialWrite) )
+    if( EQUAL(pszCap,OLCSequentialWrite) )
         return TRUE;
 
-    else if( EQUAL(pszCap,OLCFastSpatialFilter) )
+    if( EQUAL(pszCap,OLCFastSpatialFilter) )
         return FALSE;
 
-    else if( EQUAL(pszCap,OLCFastGetExtent) )
+    if( EQUAL(pszCap,OLCFastGetExtent) )
         return bRegionComplete;
 
-    else if( EQUAL(pszCap,OLCCreateField) )
+    if( EQUAL(pszCap,OLCCreateField) )
         return TRUE;
 
-    else 
-        return FALSE;
+    return FALSE;
 }
 
 /************************************************************************/
@@ -1040,14 +1032,14 @@ OGRErr OGRGmtLayer::CreateField( OGRFieldDefn *poField, int bApproxOK )
 {
     if( !bUpdate )
     {
-        CPLError( CE_Failure, CPLE_NoWriteAccess, 
-                  "Can't create fields on read-only dataset." );
+        CPLError( CE_Failure, CPLE_NoWriteAccess,
+                  "Cannot create fields on read-only dataset." );
         return OGRERR_FAILURE;
     }
 
     if( bHeaderComplete )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to create fields after features have been created.");
         return OGRERR_FAILURE;
     }
@@ -1067,13 +1059,13 @@ OGRErr OGRGmtLayer::CreateField( OGRFieldDefn *poField, int bApproxOK )
       default:
         if( !bApproxOK )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Field %s is of unsupported type %s.", 
-                      poField->GetNameRef(), 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Field %s is of unsupported type %s.",
+                      poField->GetNameRef(),
                       poField->GetFieldTypeName( poField->GetType() ) );
             return OGRERR_FAILURE;
-        } 
-        else if( poField->GetType() == OFTDate 
+        }
+        else if( poField->GetType() == OFTDate
                  || poField->GetType() == OFTTime )
         {
             OGRFieldDefn oModDef( poField );
@@ -1081,7 +1073,7 @@ OGRErr OGRGmtLayer::CreateField( OGRFieldDefn *poField, int bApproxOK )
             poFeatureDefn->AddFieldDefn( poField );
             return OGRERR_NONE;
         }
-        else 
+        else
         {
             OGRFieldDefn oModDef( poField );
             oModDef.SetType( OFTString );
diff --git a/ogr/ogrsf_frmts/gpkg/GNUmakefile b/ogr/ogrsf_frmts/gpkg/GNUmakefile
index d7eac6f..0cfc8c0 100644
--- a/ogr/ogrsf_frmts/gpkg/GNUmakefile
+++ b/ogr/ogrsf_frmts/gpkg/GNUmakefile
@@ -21,6 +21,6 @@ default: $(O_OBJ:.o=.$(OBJ_EXT))
 clean:
 	rm -f *.o $(O_OBJ)
 
-$(O_OBJ): ogr_geopackage.h ogrgeopackageutility.h ../sqlite/ogr_sqlite.h
+$(O_OBJ): ogr_geopackage.h ogrgeopackageutility.h gpkgmbtilescommon.h ../sqlite/ogr_sqlite.h
 
 
diff --git a/ogr/ogrsf_frmts/gpkg/drv_geopackage.html b/ogr/ogrsf_frmts/gpkg/drv_geopackage.html
index a888b46..8241415 100644
--- a/ogr/ogrsf_frmts/gpkg/drv_geopackage.html
+++ b/ogr/ogrsf_frmts/gpkg/drv_geopackage.html
@@ -7,7 +7,7 @@
 
 <h1>GeoPackage vector</h1>
 
-<p>This driver implements support for access to spatial tables in the 
+<p>This driver implements support for access to spatial tables in the
 <a href="http://www.geopackage.org/spec/">OGC GeoPackage format standard</a>.
 The GeoPackage standard uses a SQLite database file as a generic container, and the standard defines:
 </p>
@@ -96,7 +96,7 @@ The driver implements transactions at the database level, per
 <h2>Creation Issues</h2>
 
 <p>When creating a new GeoPackage file, the driver will attempt to
-  force the database into a UTF-8 mode for text handling, satisfying 
+  force the database into a UTF-8 mode for text handling, satisfying
   the OGR strict UTF-8 capability. For pre-existing files, the driver
   will work with whatever it's given.</p>
 
@@ -153,7 +153,7 @@ the gpkg_contents table.</p>
 <ul>
 <li>
 Simple translation of a single shapefile into GeoPackage.  The table 'abc' will
-be created with the features from abc.shp and attributes from abc.dbf. 
+be created with the features from abc.shp and attributes from abc.dbf.
 The file <code>filename.gpkg</code> must <strong>not</strong> already exist, as it will be created.
 <pre>
 % ogr2ogr -f GPKG filename.gpkg abc.shp
diff --git a/ogr/ogrsf_frmts/gpkg/drv_geopackage_raster.html b/ogr/ogrsf_frmts/gpkg/drv_geopackage_raster.html
index 09763c1..586ca52 100644
--- a/ogr/ogrsf_frmts/gpkg/drv_geopackage_raster.html
+++ b/ogr/ogrsf_frmts/gpkg/drv_geopackage_raster.html
@@ -9,7 +9,7 @@
 <h1>GeoPackage raster</h1>
 
 <p>Starting with GDAL 2.0, this driver implements full read/creation/update of
-tables containing raster tiles in the 
+tables containing raster tiles in the
 <a href="http://www.geopackage.org/spec/">OGC GeoPackage format standard</a>.
 The GeoPackage standard uses a SQLite database file as a generic container, and the standard defines:
 </p>
@@ -249,7 +249,7 @@ See <a href="#tiling_schemes">Tiling schemes</a> section. Defaults to CUSTOM.</l
 <li><b>ZOOM_LEVEL_STRATEGY</b>=AUTO/LOWER/UPPER. Strategy to determine zoom level.
 Only used for TILING_SCHEME is different from CUSTOM. LOWER will select the
 zoom level immediately below the theoretical computed non-integral zoom level,
-leading to subsampling. On the contrary, UPPER will select the immedately above
+leading to subsampling. On the contrary, UPPER will select the immediately above
 zoom level, leading to oversampling. Defaults to AUTO which selects the closest
 zoom level.</li>
 <li><b>RESAMPLING</b>=NEAREST/BILINEAR/CUBIC/CUBICSPLINE/LANCZOS/MODE/AVERAGE.
diff --git a/ogr/ogrsf_frmts/gpkg/gdalgeopackagerasterband.cpp b/ogr/ogrsf_frmts/gpkg/gdalgeopackagerasterband.cpp
index ab6dd32..5eb7524 100644
--- a/ogr/ogrsf_frmts/gpkg/gdalgeopackagerasterband.cpp
+++ b/ogr/ogrsf_frmts/gpkg/gdalgeopackagerasterband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalgeopackagerasterband.cpp 33002 2016-01-15 15:11:34Z rouault $
+ * $Id: gdalgeopackagerasterband.cpp 33830 2016-03-31 16:22:35Z rouault $
  *
  * Project:  GeoPackage Translator
  * Purpose:  Implements GDALGeoPackageRasterBand class
@@ -24,7 +24,7 @@
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFpszFileNameTWARE.
+ * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
 #include "ogr_geopackage.h"
@@ -36,15 +36,81 @@
 #endif
 
 /************************************************************************/
-/*                      GDALGeoPackageRasterBand()                      */
+/*                    GDALGPKGMBTilesLikePseudoDataset()                */
+/************************************************************************/
+
+GDALGPKGMBTilesLikePseudoDataset::GDALGPKGMBTilesLikePseudoDataset() :
+    m_bNew(false),
+    m_nZoomLevel(-1),
+    m_pabyCachedTiles(NULL),
+    m_nShiftXTiles(0),
+    m_nShiftXPixelsMod(0),
+    m_nShiftYTiles(0),
+    m_nShiftYPixelsMod(0),
+    m_nTileMatrixWidth(0),
+    m_nTileMatrixHeight(0),
+    m_eTF(GPKG_TF_PNG_JPEG),
+    m_bPNGSupports2Bands(true),
+    m_bPNGSupportsCT(true),
+    m_nZLevel(6),
+    m_nQuality(75),
+    m_bDither(false),
+    m_poParentDS(NULL)
+{
+    for(int i=0;i<4;i++)
+    {
+        m_asCachedTilesDesc[i].nRow = -1;
+        m_asCachedTilesDesc[i].nCol = -1;
+        m_asCachedTilesDesc[i].nIdxWithinTileData = -1;
+        m_asCachedTilesDesc[i].abBandDirty[0] = FALSE;
+        m_asCachedTilesDesc[i].abBandDirty[1] = FALSE;
+        m_asCachedTilesDesc[i].abBandDirty[2] = FALSE;
+        m_asCachedTilesDesc[i].abBandDirty[3] = FALSE;
+    }
+    m_bTriedEstablishingCT = false;
+    m_pabyHugeColorArray = NULL;
+    m_poCT = NULL;
+    m_bInWriteTile = false;
+#ifdef HAVE_SQLITE_VFS
+    m_pMyVFS = NULL;
+#endif
+    m_hTempDB = NULL;
+    m_nTileInsertionCount = 0;
+}
+
+/************************************************************************/
+/*                 ~GDALGPKGMBTilesLikePseudoDataset()                  */
 /************************************************************************/
 
-GDALGeoPackageRasterBand::GDALGeoPackageRasterBand(GDALGeoPackageDataset* poDS,
-                                                   int nBand,
-                                                   int nTileWidth, int nTileHeight)
+GDALGPKGMBTilesLikePseudoDataset::~GDALGPKGMBTilesLikePseudoDataset()
+{
+    if( m_poParentDS == NULL && m_hTempDB != NULL )
+    {
+        sqlite3_close(m_hTempDB);
+        m_hTempDB = NULL;
+        VSIUnlink(m_osTempDBFilename);
+#ifdef HAVE_SQLITE_VFS
+        if (m_pMyVFS)
+        {
+            sqlite3_vfs_unregister(m_pMyVFS);
+            CPLFree(m_pMyVFS->pAppData);
+            CPLFree(m_pMyVFS);
+        }
+#endif
+    }
+    CPLFree(m_pabyCachedTiles);
+    delete m_poCT;
+    CPLFree(m_pabyHugeColorArray);
+}
+
+/************************************************************************/
+/*                      GDALGPKGMBTilesLikeRasterBand()                 */
+/************************************************************************/
+
+GDALGPKGMBTilesLikeRasterBand::GDALGPKGMBTilesLikeRasterBand(
+    GDALGPKGMBTilesLikePseudoDataset* poTPD, int nTileWidth, int nTileHeight)
+    : m_poTPD(poTPD)
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
     eDataType = GDT_Byte;
     nBlockXSize = nTileWidth;
     nBlockYSize = nTileHeight;
@@ -54,64 +120,96 @@ GDALGeoPackageRasterBand::GDALGeoPackageRasterBand(GDALGeoPackageDataset* poDS,
 /*                              FlushCache()                            */
 /************************************************************************/
 
-CPLErr GDALGeoPackageRasterBand::FlushCache()
+CPLErr GDALGPKGMBTilesLikeRasterBand::FlushCache()
 {
-    GDALGeoPackageDataset* poGDS = (GDALGeoPackageDataset* )poDS;
     if( GDALPamRasterBand::FlushCache() != CE_None )
         return CE_Failure;
-    return poGDS->FlushCacheWithErrCode();
+    return m_poTPD->IFlushCacheWithErrCode();
+}
+
+/************************************************************************/
+/*                              FlushTiles()                            */
+/************************************************************************/
+
+CPLErr GDALGPKGMBTilesLikePseudoDataset::FlushTiles()
+{
+    CPLErr eErr = CE_None;
+    if( IGetUpdate() )
+    {
+        if( m_nShiftXPixelsMod || m_nShiftYPixelsMod )
+        {
+            eErr = FlushRemainingShiftedTiles();
+        }
+        else
+        {
+            eErr = WriteTile();
+        }
+    }
+
+    GDALGPKGMBTilesLikePseudoDataset* poMainDS = m_poParentDS ? m_poParentDS : this;
+    if( poMainDS->m_nTileInsertionCount )
+    {
+        poMainDS->ICommitTransaction();
+        poMainDS->m_nTileInsertionCount = 0;
+    }
+    return eErr;
 }
 
 /************************************************************************/
 /*                             GetColorTable()                          */
 /************************************************************************/
 
-GDALColorTable* GDALGeoPackageRasterBand::GetColorTable()
+GDALColorTable* GDALGPKGMBTilesLikeRasterBand::GetColorTable()
 {
-    GDALGeoPackageDataset* poGDS = (GDALGeoPackageDataset* )poDS;
-    if( poGDS->nBands == 1 )
+    if( poDS->GetRasterCount() == 1 )
     {
-        if( !poGDS->m_bTriedEstablishingCT )
+        if( !m_poTPD->m_bTriedEstablishingCT )
         {
-            poGDS->m_bTriedEstablishingCT = TRUE;
-            if( poGDS->m_poParentDS != NULL )
+            m_poTPD->m_bTriedEstablishingCT = true;
+            if( m_poTPD->m_poParentDS != NULL )
             {
-                poGDS->m_poCT = poGDS->m_poParentDS->GetRasterBand(1)->GetColorTable();
-                if( poGDS->m_poCT )
-                    poGDS->m_poCT = poGDS->m_poCT->Clone();
-                return poGDS->m_poCT;
+                m_poTPD->m_poCT
+                    = m_poTPD->m_poParentDS->IGetRasterBand(1)->GetColorTable();
+                if( m_poTPD->m_poCT )
+                    m_poTPD->m_poCT = m_poTPD->m_poCT->Clone();
+                return m_poTPD->m_poCT;
             }
 
             char* pszSQL = sqlite3_mprintf("SELECT tile_data FROM '%q' "
                 "WHERE zoom_level = %d LIMIT 1",
-                poGDS->m_osRasterTable.c_str(), poGDS->m_nZoomLevel);
+                m_poTPD->m_osRasterTable.c_str(), m_poTPD->m_nZoomLevel);
             sqlite3_stmt* hStmt = NULL;
-            int rc = sqlite3_prepare(poGDS->GetDB(), pszSQL, -1, &hStmt, NULL);
+            int rc = sqlite3_prepare(m_poTPD->IGetDB(), pszSQL, -1, &hStmt, NULL);
             if ( rc == SQLITE_OK )
             {
                 rc = sqlite3_step( hStmt );
-                if( rc == SQLITE_ROW && sqlite3_column_type( hStmt, 0 ) == SQLITE_BLOB )
+                if( rc == SQLITE_ROW
+                    && sqlite3_column_type( hStmt, 0 ) == SQLITE_BLOB )
                 {
                     const int nBytes = sqlite3_column_bytes( hStmt, 0 );
-                    GByte* pabyRawData = (GByte*)sqlite3_column_blob( hStmt, 0 );
+                    GByte* pabyRawData = reinterpret_cast<GByte *>(
+                        const_cast<void *>( sqlite3_column_blob( hStmt, 0 ) ) );
                     CPLString osMemFileName;
                     osMemFileName.Printf("/vsimem/gpkg_read_tile_%p", this);
-                    VSILFILE * fp = VSIFileFromMemBuffer( osMemFileName.c_str(), pabyRawData,
-                                                            nBytes, FALSE);
+                    VSILFILE *fp = VSIFileFromMemBuffer( osMemFileName.c_str(),
+                                                         pabyRawData,
+                                                         nBytes, FALSE);
                     VSIFCloseL(fp);
 
-                    /* Only PNG can have color table */
+                    /* Only PNG can have color table. */
                     const char* apszDrivers[] = { "PNG", NULL };
-                    GDALDataset* poDSTile = (GDALDataset*)GDALOpenEx(osMemFileName.c_str(),
-                                                                GDAL_OF_RASTER | GDAL_OF_INTERNAL,
-                                                                apszDrivers, NULL, NULL);
+                    GDALDataset* poDSTile = reinterpret_cast<GDALDataset *>(
+                        GDALOpenEx( osMemFileName.c_str(),
+                                    GDAL_OF_RASTER | GDAL_OF_INTERNAL,
+                                    apszDrivers, NULL, NULL ) );
                     if( poDSTile != NULL )
                     {
                         if( poDSTile->GetRasterCount() == 1 )
                         {
-                            poGDS->m_poCT = poDSTile->GetRasterBand(1)->GetColorTable();
-                            if( poGDS->m_poCT != NULL )
-                                poGDS->m_poCT = poGDS->m_poCT->Clone();
+                            m_poTPD->m_poCT
+                                = poDSTile->GetRasterBand(1)->GetColorTable();
+                            if( m_poTPD->m_poCT != NULL )
+                                m_poTPD->m_poCT = m_poTPD->m_poCT->Clone();
                         }
                         GDALClose( poDSTile );
                     }
@@ -123,38 +221,37 @@ GDALColorTable* GDALGeoPackageRasterBand::GetColorTable()
             sqlite3_finalize(hStmt);
         }
 
-        return poGDS->m_poCT;
+        return m_poTPD->m_poCT;
     }
-    else
-        return NULL;
+
+    return NULL;
 }
 
 /************************************************************************/
 /*                             SetColorTable()                          */
 /************************************************************************/
 
-CPLErr GDALGeoPackageRasterBand::SetColorTable(GDALColorTable* poCT)
+CPLErr GDALGPKGMBTilesLikeRasterBand::SetColorTable(GDALColorTable* poCT)
 {
-    GDALGeoPackageDataset* poGDS = (GDALGeoPackageDataset* )poDS;
-    if( poGDS->nBands != 1 )
+    if( poDS->GetRasterCount() != 1 )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "SetColorTable() only supported for a single band dataset");
         return CE_Failure;
     }
-    if( !poGDS->m_bNew || poGDS->m_bTriedEstablishingCT )
+    if( !m_poTPD->m_bNew || m_poTPD->m_bTriedEstablishingCT )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "SetColorTable() only supported on a newly created dataset");
         return CE_Failure;
     }
 
-    poGDS->m_bTriedEstablishingCT = TRUE;
-    delete poGDS->m_poCT;
+    m_poTPD->m_bTriedEstablishingCT = true;
+    delete m_poTPD->m_poCT;
     if( poCT != NULL )
-        poGDS->m_poCT = poCT->Clone();
+        m_poTPD->m_poCT = poCT->Clone();
     else
-        poGDS->m_poCT = NULL;
+        m_poTPD->m_poCT = NULL;
     return CE_None;
 }
 
@@ -162,12 +259,11 @@ CPLErr GDALGeoPackageRasterBand::SetColorTable(GDALColorTable* poCT)
 /*                        GetColorInterpretation()                      */
 /************************************************************************/
 
-GDALColorInterp GDALGeoPackageRasterBand::GetColorInterpretation()
+GDALColorInterp GDALGPKGMBTilesLikeRasterBand::GetColorInterpretation()
 {
-    GDALGeoPackageDataset* poGDS = (GDALGeoPackageDataset* )poDS;
-    if( poGDS->nBands == 1 )
+    if( poDS->GetRasterCount() == 1 )
         return GetColorTable() ? GCI_PaletteIndex : GCI_GrayIndex;
-    else if( poGDS->nBands == 2 )
+    else if( poDS->GetRasterCount() == 2 )
         return (nBand == 1) ? GCI_GrayIndex : GCI_AlphaBand;
     else
         return (GDALColorInterp) (GCI_RedBand + (nBand - 1));
@@ -177,19 +273,23 @@ GDALColorInterp GDALGeoPackageRasterBand::GetColorInterpretation()
 /*                        SetColorInterpretation()                      */
 /************************************************************************/
 
-CPLErr GDALGeoPackageRasterBand::SetColorInterpretation( GDALColorInterp eInterp )
+CPLErr GDALGPKGMBTilesLikeRasterBand::SetColorInterpretation(
+    GDALColorInterp eInterp )
 {
-    GDALGeoPackageDataset* poGDS = (GDALGeoPackageDataset* )poDS;
     if( eInterp == GCI_Undefined )
         return CE_None;
-    if( poGDS->nBands == 1 && (eInterp == GCI_GrayIndex || eInterp == GCI_PaletteIndex) )
+    if( poDS->GetRasterCount() == 1
+        && (eInterp == GCI_GrayIndex || eInterp == GCI_PaletteIndex) )
         return CE_None;
-    if( poGDS->nBands == 2 &&
-        ((nBand == 1 && eInterp == GCI_GrayIndex) || (nBand == 2 && eInterp == GCI_AlphaBand)) )
+    if( poDS->GetRasterCount() == 2 &&
+        ((nBand == 1
+          && eInterp == GCI_GrayIndex)
+         || (nBand == 2 && eInterp == GCI_AlphaBand)) )
         return CE_None;
-    if( poGDS->nBands >= 3 && eInterp == GCI_RedBand + nBand - 1 )
+    if( poDS->GetRasterCount() >= 3 && eInterp == GCI_RedBand + nBand - 1 )
         return CE_None;
-    CPLError(CE_Warning, CPLE_NotSupported, "%s color interpretation not supported. Will be ignored",
+    CPLError(CE_Warning, CPLE_NotSupported,
+             "%s color interpretation not supported. Will be ignored",
              GDALGetColorInterpretationName(eInterp));
     return CE_Warning;
 }
@@ -202,7 +302,7 @@ static int GPKGFindBestEntry(GDALColorTable* poCT,
                              GByte c1, GByte c2, GByte c3, GByte c4,
                              int nTileBandCount)
 {
-    int nEntries = MIN(256, poCT->GetColorEntryCount());
+    const int nEntries = MIN(256, poCT->GetColorEntryCount());
     int iBestIdx = 0;
     int nBestDistance = 4 * 256 * 256;
     for(int i=0;i<nEntries;i++)
@@ -226,16 +326,18 @@ static int GPKGFindBestEntry(GDALColorTable* poCT,
 /*                           ReadTile()                                 */
 /************************************************************************/
 
-CPLErr GDALGeoPackageDataset::ReadTile(const CPLString& osMemFileName,
+CPLErr GDALGPKGMBTilesLikePseudoDataset::ReadTile(const CPLString& osMemFileName,
                                        GByte* pabyTileData,
-                                       int* pbIsLossyFormat)
+                                       bool* pbIsLossyFormat)
 {
     const char* apszDrivers[] = { "JPEG", "PNG", "WEBP", NULL };
     int nBlockXSize, nBlockYSize;
-    GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
-    GDALDataset* poDSTile = (GDALDataset*)GDALOpenEx(osMemFileName.c_str(),
-                                                     GDAL_OF_RASTER | GDAL_OF_INTERNAL,
-                                                     apszDrivers, NULL, NULL);
+    IGetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
+    const int nBands = IGetRasterCount();
+    GDALDataset* poDSTile = reinterpret_cast<GDALDataset*>(
+        GDALOpenEx( osMemFileName.c_str(),
+                    GDAL_OF_RASTER | GDAL_OF_INTERNAL,
+                    apszDrivers, NULL, NULL ) );
     if( poDSTile == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -244,14 +346,14 @@ CPLErr GDALGeoPackageDataset::ReadTile(const CPLString& osMemFileName,
         return CE_Failure;
     }
 
-    int nTileBandCount = poDSTile->GetRasterCount();
+    const int nTileBandCount = poDSTile->GetRasterCount();
 
     if( !(poDSTile->GetRasterXSize() == nBlockXSize &&
           poDSTile->GetRasterYSize() == nBlockYSize &&
           (nTileBandCount >= 1 && nTileBandCount <= 4)) )
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Inconsistent tiles characteristics");
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Inconsistent tiles characteristics" );
         GDALClose(poDSTile);
         memset(pabyTileData, 0, nBands * nBlockXSize * nBlockYSize );
         return CE_Failure;
@@ -273,12 +375,13 @@ CPLErr GDALGeoPackageDataset::ReadTile(const CPLString& osMemFileName,
     if( nBands == 1 || nTileBandCount == 1 )
     {
         poCT = poDSTile->GetRasterBand(1)->GetColorTable();
-        GetRasterBand(1)->GetColorTable();
+        IGetRasterBand(1)->GetColorTable();
     }
 
     if( pbIsLossyFormat )
-        *pbIsLossyFormat = !EQUAL(poDSTile->GetDriver()->GetDescription(), "PNG") ||
-                           (poCT != NULL && poCT->GetColorEntryCount() == 256) /* PNG8 */;
+        *pbIsLossyFormat
+            = !EQUAL(poDSTile->GetDriver()->GetDescription(), "PNG") ||
+              (poCT != NULL && poCT->GetColorEntryCount() == 256) /* PNG8 */;
 
     /* Map RGB(A) tile to single-band color indexed */
     if( nBands == 1 && m_poCT != NULL && nTileBandCount != 1 )
@@ -298,36 +401,44 @@ CPLErr GDALGeoPackageDataset::ReadTile(const CPLString& osMemFileName,
         int iBestEntryFor0 = GPKGFindBestEntry(m_poCT, 0, 0, 0, 0, nTileBandCount);
         for(int i=0;i<nBlockXSize*nBlockYSize;i++)
         {
-            GByte c1 = pabyTileData[i];
-            GByte c2 = pabyTileData[i + nBlockXSize * nBlockYSize];
-            GByte c3 = pabyTileData[i + 2 * nBlockXSize * nBlockYSize];
-            GByte c4 = pabyTileData[i + 3 * nBlockXSize * nBlockYSize];
+            const GByte c1 = pabyTileData[i];
+            const GByte c2 = pabyTileData[i + nBlockXSize * nBlockYSize];
+            const GByte c3 = pabyTileData[i + 2 * nBlockXSize * nBlockYSize];
+            const GByte c4 = pabyTileData[i + 3 * nBlockXSize * nBlockYSize];
             GUInt32 nVal = c1 + (c2 << 8) + (c3 << 16);
             if( nTileBandCount == 4 ) nVal += (c4 << 24);
-            if( nVal == 0 ) /* In most cases we will reach that point at partial tiles */
-                pabyTileData[i] = (GByte) iBestEntryFor0;
+            if( nVal == 0 )
+                // In most cases we will reach that point at partial tiles.
+                pabyTileData[i] = static_cast<GByte>( iBestEntryFor0 );
             else
             {
-                std::map< GUInt32, int >::iterator oMapEntryToIndexIter = oMapEntryToIndex.find(nVal);
+                std::map< GUInt32, int >::iterator oMapEntryToIndexIter
+                    = oMapEntryToIndex.find(nVal);
                 if( oMapEntryToIndexIter == oMapEntryToIndex.end() )
                     /* Could happen with JPEG tiles */
-                    pabyTileData[i] = (GByte) GPKGFindBestEntry(m_poCT, c1, c2, c3, c4, nTileBandCount);
+                  pabyTileData[i] = static_cast<GByte>(
+                      GPKGFindBestEntry(m_poCT, c1, c2, c3, c4,
+                                        nTileBandCount) );
                 else
-                    pabyTileData[i] = (GByte) oMapEntryToIndexIter->second;
+                    pabyTileData[i] = static_cast<GByte>(
+                        oMapEntryToIndexIter->second );
             }
         }
         GDALClose( poDSTile );
         return CE_None;
     }
-    
+
     if( nBands == 1 && nTileBandCount == 1 && poCT != NULL && m_poCT != NULL &&
              !poCT->IsSame(m_poCT) )
     {
-        CPLError(CE_Warning, CPLE_NotSupported, "Different color tables. Unhandled for now");
+        CPLError( CE_Warning, CPLE_NotSupported,
+                  "Different color tables. Unhandled for now" );
     }
     else if( (nBands == 1 && nTileBandCount >= 3) ||
-             (nBands == 1 && nTileBandCount == 1 && m_poCT != NULL && poCT == NULL) ||
-             ((nBands == 1 || nBands == 2) && nTileBandCount == 1 && m_poCT == NULL && poCT != NULL) )
+             (nBands == 1 && nTileBandCount == 1 && m_poCT != NULL
+              && poCT == NULL) ||
+             ((nBands == 1 || nBands == 2) && nTileBandCount == 1
+              && m_poCT == NULL && poCT != NULL) )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Inconsistent dataset and tiles band characteristics");
@@ -335,7 +446,8 @@ CPLErr GDALGeoPackageDataset::ReadTile(const CPLString& osMemFileName,
 
     if( nBands == 2 )
     {
-        if( nTileBandCount == 1 || nTileBandCount == 3 /* assuming that the RGB is Grey,Grey,Grey */ )
+        // assuming that the RGB is Grey,Grey,Grey
+        if( nTileBandCount == 1 || nTileBandCount == 3 )
         {
             /* Create fully opaque alpha */
             memset(pabyTileData + 1 * nBlockXSize * nBlockYSize,
@@ -365,10 +477,9 @@ CPLErr GDALGeoPackageDataset::ReadTile(const CPLString& osMemFileName,
         /* Expand color indexed to RGB(A) */
         if( poCT != NULL )
         {
-            int i;
             GByte abyCT[4*256];
             int nEntries = MIN(256, poCT->GetColorEntryCount());
-            for(i=0;i<nEntries;i++)
+            for( int i = 0; i < nEntries; i++ )
             {
                 const GDALColorEntry* psEntry = poCT->GetColorEntry(i);
                 abyCT[4*i] = (GByte)psEntry->c1;
@@ -376,16 +487,16 @@ CPLErr GDALGeoPackageDataset::ReadTile(const CPLString& osMemFileName,
                 abyCT[4*i+2] = (GByte)psEntry->c3;
                 abyCT[4*i+3] = (GByte)psEntry->c4;
             }
-            for(;i<256;i++)
+            for( int i = nEntries; i < 256; i++ )
             {
                 abyCT[4*i] = 0;
                 abyCT[4*i+1] = 0;
                 abyCT[4*i+2] = 0;
                 abyCT[4*i+3] = 0;
             }
-            for(i=0;i<nBlockXSize * nBlockYSize;i++)
+            for( int i = 0; i < nBlockXSize * nBlockYSize; i++ )
             {
-                GByte byVal = pabyTileData[i];
+                const GByte byVal = pabyTileData[i];
                 pabyTileData[i] = abyCT[4*byVal];
                 pabyTileData[i + 1 * nBlockXSize * nBlockYSize] = abyCT[4*byVal+1];
                 pabyTileData[i + 2 * nBlockXSize * nBlockYSize] = abyCT[4*byVal+2];
@@ -413,7 +524,7 @@ CPLErr GDALGeoPackageDataset::ReadTile(const CPLString& osMemFileName,
     }
 
     GDALClose( poDSTile );
-    
+
     return CE_None;
 }
 
@@ -421,10 +532,11 @@ CPLErr GDALGeoPackageDataset::ReadTile(const CPLString& osMemFileName,
 /*                           ReadTile()                                 */
 /************************************************************************/
 
-GByte* GDALGeoPackageDataset::ReadTile(int nRow, int nCol)
+GByte* GDALGPKGMBTilesLikePseudoDataset::ReadTile(int nRow, int nCol)
 {
     int nBlockXSize, nBlockYSize;
-    GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
+    IGetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
+    const int nBands = IGetRasterCount();
     if( m_nShiftXPixelsMod || m_nShiftYPixelsMod )
     {
         GByte* pabyData = NULL;
@@ -466,11 +578,11 @@ GByte* GDALGeoPackageDataset::ReadTile(int nRow, int nCol)
     else
     {
         GByte* pabyDest = m_pabyCachedTiles + 8 * nBlockXSize * nBlockYSize;
-        int bAllNonDirty = TRUE;
+        bool bAllNonDirty = true;
         for( int i = 0; i < nBands; i++ )
         {
             if( m_asCachedTilesDesc[0].abBandDirty[i] )
-                bAllNonDirty = FALSE;
+                bAllNonDirty = false;
         }
         if( bAllNonDirty )
         {
@@ -506,50 +618,57 @@ GByte* GDALGeoPackageDataset::ReadTile(int nRow, int nCol)
 /*                           ReadTile()                                 */
 /************************************************************************/
 
-GByte* GDALGeoPackageDataset::ReadTile(int nRow, int nCol, GByte* pabyData,
-                                       int* pbIsLossyFormat)
+GByte* GDALGPKGMBTilesLikePseudoDataset::ReadTile( int nRow, int nCol, GByte *pabyData,
+                                        bool *pbIsLossyFormat)
 {
-    int rc;
-    int nBlockXSize, nBlockYSize;
-    GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
-    
-    if( pbIsLossyFormat ) *pbIsLossyFormat = FALSE;
+    int nBlockXSize;
+    int nBlockYSize;
+    IGetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
+    const int nBands = IGetRasterCount();
+
+    if( pbIsLossyFormat ) *pbIsLossyFormat = false;
 
     if( nRow < 0 || nCol < 0 || nRow >= m_nTileMatrixHeight ||
         nCol >= m_nTileMatrixWidth )
     {
-        memset(pabyData, 0, nBands * nBlockXSize * nBlockYSize );
+        memset( pabyData, 0, nBands * nBlockXSize * nBlockYSize );
         return pabyData;
     }
 
-    //CPLDebug("GPKG", "For block (blocky=%d, blockx=%d) request tile (row=%d, col=%d)",
-    //         nBlockYOff, nBlockXOff, nRow, nCol);
-    char* pszSQL = sqlite3_mprintf("SELECT tile_data FROM '%q' "
+#ifdef DEBUG_VERBOSE
+    CPLDebug( "GPKG", "ReadTile(row=%d, col=%d)", nRow, nCol );
+#endif
+
+    char *pszSQL = sqlite3_mprintf( "SELECT tile_data FROM '%q' "
         "WHERE zoom_level = %d AND tile_row = %d AND tile_column = %d%s",
-        m_osRasterTable.c_str(), m_nZoomLevel, nRow, nCol,
+        m_osRasterTable.c_str(), m_nZoomLevel, GetRowFromIntoTopConvention(nRow), nCol,
         m_osWHERE.size() ? CPLSPrintf(" AND (%s)", m_osWHERE.c_str()): "");
+
 #ifdef DEBUG_VERBOSE
     CPLDebug("GPKG", "%s", pszSQL);
 #endif
-    sqlite3_stmt* hStmt = NULL;
-    rc = sqlite3_prepare(GetDB(), pszSQL, -1, &hStmt, NULL);
+
+    sqlite3_stmt *hStmt = NULL;
+    int rc = sqlite3_prepare( IGetDB(), pszSQL, -1, &hStmt, NULL );
     if ( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, "failed to prepare SQL: %s", pszSQL);
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "failed to prepare SQL: %s", pszSQL );
         sqlite3_free(pszSQL);
         return NULL;
     }
-    sqlite3_free(pszSQL);
+    sqlite3_free( pszSQL );
     rc = sqlite3_step( hStmt );
 
     if( rc == SQLITE_ROW && sqlite3_column_type( hStmt, 0 ) == SQLITE_BLOB )
     {
         const int nBytes = sqlite3_column_bytes( hStmt, 0 );
-        GByte* pabyRawData = (GByte*)sqlite3_column_blob( hStmt, 0 );
+        GByte* pabyRawData = static_cast<GByte *>( const_cast<void *>(
+            sqlite3_column_blob( hStmt, 0 ) ) );
         CPLString osMemFileName;
         osMemFileName.Printf("/vsimem/gpkg_read_tile_%p", this);
-        VSILFILE * fp = VSIFileFromMemBuffer( osMemFileName.c_str(), pabyRawData,
-                                                nBytes, FALSE);
+        VSILFILE * fp = VSIFileFromMemBuffer(
+            osMemFileName.c_str(), pabyRawData, nBytes, FALSE );
         VSIFCloseL(fp);
 
         ReadTile(osMemFileName, pabyData, pbIsLossyFormat);
@@ -558,7 +677,7 @@ GByte* GDALGeoPackageDataset::ReadTile(int nRow, int nCol, GByte* pabyData,
     }
     else
     {
-        sqlite3_finalize(hStmt);
+        sqlite3_finalize( hStmt );
         hStmt = NULL;
 
         if( m_hTempDB && (m_nShiftXPixelsMod || m_nShiftYPixelsMod) )
@@ -568,28 +687,33 @@ GByte* GDALGeoPackageDataset::ReadTile(int nRow, int nCol, GByte* pabyData,
                 "tile_data_band_3, tile_data_band_4 FROM partial_tiles WHERE "
                 "zoom_level = %d AND tile_row = %d AND tile_column = %d",
                 m_nZoomLevel, nRow, nCol);
+
 #ifdef DEBUG_VERBOSE
             CPLDebug("GPKG", "%s", pszSQLNew);
 #endif
-            rc = sqlite3_prepare_v2(m_hTempDB, pszSQLNew, strlen(pszSQLNew), &hStmt, NULL);
+
+            rc = sqlite3_prepare_v2(m_hTempDB, pszSQLNew, -1, &hStmt, NULL);
             if ( rc != SQLITE_OK )
             {
                 memset(pabyData, 0, nBands * nBlockXSize * nBlockYSize );
-                CPLError( CE_Failure, CPLE_AppDefined, "sqlite3_prepare(%s) failed: %s",
-                        pszSQLNew, sqlite3_errmsg( m_hTempDB ) );
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "sqlite3_prepare(%s) failed: %s",
+                          pszSQLNew, sqlite3_errmsg( m_hTempDB ) );
                 return pabyData;
             }
 
             rc = sqlite3_step(hStmt);
             if ( rc == SQLITE_ROW )
             {
-                int nPartialFlag = sqlite3_column_int(hStmt, 0);
+                const int nPartialFlag = sqlite3_column_int(hStmt, 0);
                 for(int iBand = 1; iBand <= nBands; iBand ++ )
                 {
-                    GByte* pabyDestBand = pabyData + (iBand - 1) * nBlockXSize * nBlockYSize;
+                    GByte* pabyDestBand
+                        = pabyData + (iBand - 1) * nBlockXSize * nBlockYSize;
                     if( nPartialFlag & (((1 << 4)-1) << (4 * (iBand - 1))) )
                     {
-                        CPLAssert( sqlite3_column_bytes(hStmt, iBand) == nBlockXSize * nBlockYSize );
+                        CPLAssert( sqlite3_column_bytes(hStmt, iBand)
+                                   == nBlockXSize * nBlockYSize );
                         memcpy( pabyDestBand,
                                 sqlite3_column_blob(hStmt, iBand),
                                 nBlockXSize * nBlockYSize );
@@ -619,61 +743,62 @@ GByte* GDALGeoPackageDataset::ReadTile(int nRow, int nCol, GByte* pabyData,
 /*                         IReadBlock()                                 */
 /************************************************************************/
 
-CPLErr GDALGeoPackageRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff,
+CPLErr GDALGPKGMBTilesLikeRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff,
                                             void* pData)
 {
-    GDALGeoPackageDataset* poGDS = (GDALGeoPackageDataset* )poDS;
-
 #ifdef DEBUG_VERBOSE
     CPLDebug( "GPKG", "IReadBlock(nBand=%d,nBlockXOff=%d,nBlockYOff=%d,m_nZoomLevel=%d)",
-              nBand,nBlockXOff,nBlockYOff,poGDS->m_nZoomLevel);
+              nBand,nBlockXOff,nBlockYOff,m_poTPD->m_nZoomLevel);
 #endif
 
-    const int nRowMin = nBlockYOff + poGDS->m_nShiftYTiles;
+    const int nRowMin = nBlockYOff + m_poTPD->m_nShiftYTiles;
     int nRowMax = nRowMin;
-    if( poGDS->m_nShiftYPixelsMod )
+    if( m_poTPD->m_nShiftYPixelsMod )
         nRowMax ++;
 
-    const int nColMin = nBlockXOff + poGDS->m_nShiftXTiles;
+    const int nColMin = nBlockXOff + m_poTPD->m_nShiftXTiles;
     int nColMax = nColMin;
-    if( poGDS->m_nShiftXPixelsMod )
+    if( m_poTPD->m_nShiftXPixelsMod )
         nColMax ++;
 
+retry:
     /* Optimize for left to right reading at constant row */
-    if( poGDS->m_nShiftXPixelsMod || poGDS->m_nShiftYPixelsMod )
+    if( m_poTPD->m_nShiftXPixelsMod || m_poTPD->m_nShiftYPixelsMod )
     {
-        if( nRowMin == poGDS->m_asCachedTilesDesc[0].nRow &&
-            nColMin == poGDS->m_asCachedTilesDesc[0].nCol + 1 &&
-            poGDS->m_asCachedTilesDesc[0].nIdxWithinTileData >= 0 )
+        if( nRowMin == m_poTPD->m_asCachedTilesDesc[0].nRow &&
+            nColMin == m_poTPD->m_asCachedTilesDesc[0].nCol + 1 &&
+            m_poTPD->m_asCachedTilesDesc[0].nIdxWithinTileData >= 0 )
         {
-            CPLAssert(nRowMin == poGDS->m_asCachedTilesDesc[1].nRow);
-            CPLAssert(nColMin == poGDS->m_asCachedTilesDesc[1].nCol);
-            CPLAssert(poGDS->m_asCachedTilesDesc[0].nIdxWithinTileData == 0 ||
-                      poGDS->m_asCachedTilesDesc[0].nIdxWithinTileData == 1);
+            CPLAssert(nRowMin == m_poTPD->m_asCachedTilesDesc[1].nRow);
+            CPLAssert(nColMin == m_poTPD->m_asCachedTilesDesc[1].nCol);
+            CPLAssert(m_poTPD->m_asCachedTilesDesc[0].nIdxWithinTileData == 0 ||
+                      m_poTPD->m_asCachedTilesDesc[0].nIdxWithinTileData == 1);
 
             /* 0 1  --> 1 -1 */
             /* 2 3      3 -1 */
             /* or */
             /* 1 0  --> 0 -1 */
             /* 3 2      2 -1 */
-            poGDS->m_asCachedTilesDesc[0].nIdxWithinTileData = poGDS->m_asCachedTilesDesc[1].nIdxWithinTileData;
-            poGDS->m_asCachedTilesDesc[2].nIdxWithinTileData = poGDS->m_asCachedTilesDesc[3].nIdxWithinTileData;
+            m_poTPD->m_asCachedTilesDesc[0].nIdxWithinTileData
+                = m_poTPD->m_asCachedTilesDesc[1].nIdxWithinTileData;
+            m_poTPD->m_asCachedTilesDesc[2].nIdxWithinTileData
+                = m_poTPD->m_asCachedTilesDesc[3].nIdxWithinTileData;
         }
         else
         {
-            poGDS->m_asCachedTilesDesc[0].nIdxWithinTileData = -1;
-            poGDS->m_asCachedTilesDesc[2].nIdxWithinTileData = -1;
+            m_poTPD->m_asCachedTilesDesc[0].nIdxWithinTileData = -1;
+            m_poTPD->m_asCachedTilesDesc[2].nIdxWithinTileData = -1;
         }
-        poGDS->m_asCachedTilesDesc[0].nRow = nRowMin;
-        poGDS->m_asCachedTilesDesc[0].nCol = nColMin;
-        poGDS->m_asCachedTilesDesc[1].nRow = nRowMin;
-        poGDS->m_asCachedTilesDesc[1].nCol = nColMin + 1;
-        poGDS->m_asCachedTilesDesc[2].nRow = nRowMin + 1;
-        poGDS->m_asCachedTilesDesc[2].nCol = nColMin;
-        poGDS->m_asCachedTilesDesc[3].nRow = nRowMin + 1;
-        poGDS->m_asCachedTilesDesc[3].nCol = nColMin + 1;
-        poGDS->m_asCachedTilesDesc[1].nIdxWithinTileData = -1;
-        poGDS->m_asCachedTilesDesc[3].nIdxWithinTileData = -1;
+        m_poTPD->m_asCachedTilesDesc[0].nRow = nRowMin;
+        m_poTPD->m_asCachedTilesDesc[0].nCol = nColMin;
+        m_poTPD->m_asCachedTilesDesc[1].nRow = nRowMin;
+        m_poTPD->m_asCachedTilesDesc[1].nCol = nColMin + 1;
+        m_poTPD->m_asCachedTilesDesc[2].nRow = nRowMin + 1;
+        m_poTPD->m_asCachedTilesDesc[2].nCol = nColMin;
+        m_poTPD->m_asCachedTilesDesc[3].nRow = nRowMin + 1;
+        m_poTPD->m_asCachedTilesDesc[3].nCol = nColMin + 1;
+        m_poTPD->m_asCachedTilesDesc[1].nIdxWithinTileData = -1;
+        m_poTPD->m_asCachedTilesDesc[3].nIdxWithinTileData = -1;
 
     }
 
@@ -681,22 +806,22 @@ CPLErr GDALGeoPackageRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff,
     {
         for(int nCol = nColMin; nCol <= nColMax; nCol++ )
         {
-            if( poGDS->m_nShiftXPixelsMod == 0 && poGDS->m_nShiftYPixelsMod == 0 )
+            if( m_poTPD->m_nShiftXPixelsMod == 0 && m_poTPD->m_nShiftYPixelsMod == 0 )
             {
-                if( !(nRow == poGDS->m_asCachedTilesDesc[0].nRow &&
-                      nCol == poGDS->m_asCachedTilesDesc[0].nCol &&
-                      poGDS->m_asCachedTilesDesc[0].nIdxWithinTileData == 0) )
+                if( !(nRow == m_poTPD->m_asCachedTilesDesc[0].nRow &&
+                      nCol == m_poTPD->m_asCachedTilesDesc[0].nCol &&
+                      m_poTPD->m_asCachedTilesDesc[0].nIdxWithinTileData == 0) )
                 {
-                    if( poGDS->WriteTile() != CE_None )
+                    if( m_poTPD->WriteTile() != CE_None )
                         return CE_Failure;
                 }
             }
 
-            GByte* pabyTileData = poGDS->ReadTile(nRow, nCol);
+            GByte* pabyTileData = m_poTPD->ReadTile(nRow, nCol);
             if( pabyTileData == NULL )
                 return CE_Failure;
 
-            for(int iBand=1;iBand<=poGDS->nBands;iBand++)
+            for(int iBand=1;iBand<=poDS->GetRasterCount();iBand++)
             {
                 GDALRasterBlock* poBlock = NULL;
                 GByte* pabyDest;
@@ -707,7 +832,8 @@ CPLErr GDALGeoPackageRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff,
                 else
                 {
                     poBlock =
-                        poGDS->GetRasterBand(iBand)->GetLockedBlockRef(nBlockXOff, nBlockYOff, TRUE);
+                        poDS->GetRasterBand(iBand)->GetLockedBlockRef(
+                            nBlockXOff, nBlockYOff, TRUE );
                     if( poBlock == NULL )
                         continue;
                     if( poBlock->GetDirty() )
@@ -715,12 +841,25 @@ CPLErr GDALGeoPackageRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff,
                         poBlock->DropLock();
                         continue;
                     }
+                    /* if we are short of GDAL cache max and there are dirty blocks */
+                    /* of our dataset, the above GetLockedBlockRef() might have reset */
+                    /* (at least part of) the 4 tiles we want to cache and have */
+                    /* already read */
+                    // FIXME this is way too fragile.
+                    if( (m_poTPD->m_nShiftXPixelsMod != 0 ||
+                         m_poTPD->m_nShiftYPixelsMod != 0) &&
+                        (m_poTPD->m_asCachedTilesDesc[0].nRow != nRowMin ||
+                         m_poTPD->m_asCachedTilesDesc[0].nCol != nColMin) )
+                    {
+                        poBlock->DropLock();
+                        goto retry;
+                    }
                     pabyDest = (GByte*) poBlock->GetDataRef();
                 }
 
                 // Composite tile data into block data
-                if( poGDS->m_nShiftXPixelsMod == 0
-                    && poGDS->m_nShiftYPixelsMod == 0 )
+                if( m_poTPD->m_nShiftXPixelsMod == 0
+                    && m_poTPD->m_nShiftYPixelsMod == 0 )
                 {
                     memcpy( pabyDest,
                             pabyTileData +
@@ -738,7 +877,7 @@ CPLErr GDALGeoPackageRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff,
                                 if( pabyDest[y*nBlockXSize+x] != 0 && !bFoundNonZero )
                                 {
                                     CPLDebug("GPKG", "IReadBlock(): Found non-zero content in ghost part of tile(nBand=%d,nBlockXOff=%d,nBlockYOff=%d,m_nZoomLevel=%d)\n",
-                                            iBand,nBlockXOff,nBlockYOff,poGDS->m_nZoomLevel);
+                                            iBand,nBlockXOff,nBlockYOff,m_poTPD->m_nZoomLevel);
                                     bFoundNonZero = true;
                                 }
                             }
@@ -749,39 +888,53 @@ CPLErr GDALGeoPackageRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff,
                 }
                 else
                 {
-                    int nSrcXOffset, nSrcXSize, nSrcYOffset, nSrcYSize;
-                    int nDstXOffset, nDstYOffset;
+                    int nSrcXOffset;
+                    int nSrcXSize;
+                    int nSrcYOffset;
+                    int nSrcYSize;
+                    int nDstXOffset;
+                    int nDstYOffset;
                     if( nCol == nColMin )
                     {
-                        nSrcXOffset = poGDS->m_nShiftXPixelsMod;
-                        nSrcXSize = nBlockXSize - poGDS->m_nShiftXPixelsMod;
+                        nSrcXOffset = m_poTPD->m_nShiftXPixelsMod;
+                        nSrcXSize = nBlockXSize - m_poTPD->m_nShiftXPixelsMod;
                         nDstXOffset = 0;
                     }
                     else
                     {
                         nSrcXOffset = 0;
-                        nSrcXSize = poGDS->m_nShiftXPixelsMod;
-                        nDstXOffset = nBlockXSize - poGDS->m_nShiftXPixelsMod;
+                        nSrcXSize = m_poTPD->m_nShiftXPixelsMod;
+                        nDstXOffset = nBlockXSize - m_poTPD->m_nShiftXPixelsMod;
                     }
                     if( nRow == nRowMin )
                     {
-                        nSrcYOffset = poGDS->m_nShiftYPixelsMod;
-                        nSrcYSize = nBlockYSize - poGDS->m_nShiftYPixelsMod;
+                        nSrcYOffset = m_poTPD->m_nShiftYPixelsMod;
+                        nSrcYSize = nBlockYSize - m_poTPD->m_nShiftYPixelsMod;
                         nDstYOffset = 0;
                     }
                     else
                     {
                         nSrcYOffset = 0;
-                        nSrcYSize = poGDS->m_nShiftYPixelsMod;
-                        nDstYOffset = nBlockYSize - poGDS->m_nShiftYPixelsMod;
+                        nSrcYSize = m_poTPD->m_nShiftYPixelsMod;
+                        nDstYOffset = nBlockYSize - m_poTPD->m_nShiftYPixelsMod;
                     }
-                    //CPLDebug("GPKG", "Copy source tile x=%d,w=%d,y=%d,h=%d into buffet at x=%d,y=%d",
-                    //         nSrcXOffset, nSrcXSize, nSrcYOffset, nSrcYSize, nDstXOffset, nDstYOffset);
+
+#ifdef DEBUG_VERBOSE
+                    CPLDebug( "GPKG",
+                              "Copy source tile x=%d,w=%d,y=%d,h=%d into "
+                              "buffer at x=%d,y=%d",
+                              nSrcXOffset, nSrcXSize, nSrcYOffset, nSrcYSize,
+                              nDstXOffset, nDstYOffset);
+#endif
+
                     for( int y=0; y<nSrcYSize; y++ )
                     {
-                        GByte* pSrc = pabyTileData + (iBand - 1) * nBlockXSize * nBlockYSize +
-                                        (y + nSrcYOffset) * nBlockXSize + nSrcXOffset;
-                        GByte* pDst = pabyDest + (y + nDstYOffset) * nBlockXSize + nDstXOffset;
+                        GByte *pSrc =
+                          pabyTileData + (iBand - 1) * nBlockXSize * nBlockYSize
+                          + (y + nSrcYOffset) * nBlockXSize + nSrcXOffset;
+                        GByte *pDst =
+                          pabyDest + (y + nDstYOffset) * nBlockXSize
+                          + nDstXOffset;
                         GDALCopyWords(pSrc, GDT_Byte, 1,
                                       pDst, GDT_Byte, 1,
                                       nSrcXSize);
@@ -802,14 +955,14 @@ CPLErr GDALGeoPackageRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff,
 /*                       WEBPSupports4Bands()                           */
 /************************************************************************/
 
-static int WEBPSupports4Bands()
+static bool WEBPSupports4Bands()
 {
     static int bRes = -1;
     if( bRes < 0 )
     {
         GDALDriver* poDrv = (GDALDriver*) GDALGetDriverByName("WEBP");
-        if( poDrv == NULL || CSLTestBoolean(CPLGetConfigOption("GPKG_SIMUL_WEBP_3BAND", "FALSE")) )
-            bRes = FALSE;
+        if( poDrv == NULL || CPLTestBool(CPLGetConfigOption("GPKG_SIMUL_WEBP_3BAND", "FALSE")) )
+            bRes = false;
         else
         {
             // LOSSLESS and RGBA support appeared in the same version
@@ -821,26 +974,26 @@ static int WEBPSupports4Bands()
                         "The version of WEBP available does not support 4-band RGBA");
         }
     }
-    return bRes;
+    return CPL_TO_BOOL(bRes);
 }
 
 /************************************************************************/
 /*                         WriteTile()                                  */
 /************************************************************************/
 
-CPLErr GDALGeoPackageDataset::WriteTile()
+CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteTile()
 {
     CPLAssert(!m_bInWriteTile);
-    m_bInWriteTile = TRUE;
+    m_bInWriteTile = true;
     CPLErr eErr = WriteTileInternal();
-    m_bInWriteTile = FALSE;
+    m_bInWriteTile = false;
     return eErr;
 }
 
 /* should only be called by WriteTile() */
-CPLErr GDALGeoPackageDataset::WriteTileInternal()
+CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteTileInternal()
 {
-    if( !(bUpdate && m_asCachedTilesDesc[0].nRow >= 0 &&
+    if( !(IGetUpdate() && m_asCachedTilesDesc[0].nRow >= 0 &&
           m_asCachedTilesDesc[0].nCol >= 0 &&
           m_asCachedTilesDesc[0].nIdxWithinTileData == 0) )
         return CE_None;
@@ -848,28 +1001,28 @@ CPLErr GDALGeoPackageDataset::WriteTileInternal()
     int nRow = m_asCachedTilesDesc[0].nRow;
     int nCol = m_asCachedTilesDesc[0].nCol;
 
-    int bAllDirty = TRUE;
-    int bAllNonDirty = TRUE;
-    int i;
-    for(i=0;i<nBands;i++)
+    bool bAllDirty = true;
+    bool bAllNonDirty = true;
+    const int nBands = IGetRasterCount();
+    for( int i = 0; i < nBands; i++ )
     {
         if( m_asCachedTilesDesc[0].abBandDirty[i] )
-            bAllNonDirty = FALSE;
+            bAllNonDirty = false;
         else
-            bAllDirty = FALSE;
+            bAllDirty = false;
     }
     if( bAllNonDirty )
         return CE_None;
 
     int nBlockXSize, nBlockYSize;
-    GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
+    IGetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
 
     /* If all bands for that block are not dirty/written, we need to */
     /* fetch the missing ones if the tile exists */
-    int bIsLossyFormat = FALSE;
+    bool bIsLossyFormat = false;
     if( !bAllDirty )
     {
-        for(i=1;i<=3;i++)
+        for( int i = 1; i <= 3; i++ )
         {
             m_asCachedTilesDesc[i].nRow = -1;
             m_asCachedTilesDesc[i].nCol = -1;
@@ -877,7 +1030,7 @@ CPLErr GDALGeoPackageDataset::WriteTileInternal()
         }
         ReadTile(nRow, nCol, m_pabyCachedTiles + 4 * nBlockXSize * nBlockYSize,
                  &bIsLossyFormat);
-        for(i=0;i<nBands;i++)
+        for( int i = 0; i < nBands; i++ )
         {
             if( !m_asCachedTilesDesc[0].abBandDirty[i] )
             {
@@ -889,13 +1042,15 @@ CPLErr GDALGeoPackageDataset::WriteTileInternal()
     }
 
     /* Compute origin of tile in GDAL raster space */
-    int nXOff = (nCol - m_nShiftXTiles) * nBlockXSize - m_nShiftXPixelsMod; 
+    int nXOff = (nCol - m_nShiftXTiles) * nBlockXSize - m_nShiftXPixelsMod;
     int nYOff = (nRow - m_nShiftYTiles) * nBlockYSize - m_nShiftYPixelsMod;
 
     /* Assert that the tile at least intersects some of the GDAL raster space */
     CPLAssert(nXOff + nBlockXSize > 0);
     CPLAssert(nYOff + nBlockYSize > 0);
     /* Can happen if the tile of the raster is less than the block size */
+    const int nRasterXSize = IGetRasterBand(1)->GetXSize();
+    const int nRasterYSize = IGetRasterBand(1)->GetYSize();
     if( nXOff >= nRasterXSize || nYOff >= nRasterYSize )
         return CE_None;
 
@@ -933,30 +1088,30 @@ CPLErr GDALGeoPackageDataset::WriteTileInternal()
     int iXCount = nBlockXSize;
     int iYCount = nBlockYSize;
 
-    int bPartialTile = FALSE;
+    bool bPartialTile = false;
     int nAlphaBand = (nBands == 2) ? 2 : (nBands == 4) ? 4 : 0;
     if( nAlphaBand == 0 )
     {
         if( nXOff < 0 )
         {
-            bPartialTile = TRUE;
+            bPartialTile = true;
             iXOff = -nXOff;
             iXCount += nXOff;
         }
         if( nXOff + nBlockXSize > nRasterXSize )
         {
-            bPartialTile = TRUE;
+            bPartialTile = true;
             iXCount -= nXOff + nBlockXSize - nRasterXSize;
         }
         if( nYOff < 0 )
         {
-            bPartialTile = TRUE;
+            bPartialTile = true;
             iYOff = -nYOff;
             iYCount += nYOff;
         }
         if( nYOff + nBlockYSize > nRasterYSize )
         {
-            bPartialTile = TRUE;
+            bPartialTile = true;
             iYCount -= nYOff + nBlockYSize - nRasterYSize;
         }
         CPLAssert(iXOff >= 0);
@@ -970,18 +1125,19 @@ CPLErr GDALGeoPackageDataset::WriteTileInternal()
     m_asCachedTilesDesc[0].nRow = -1;
     m_asCachedTilesDesc[0].nCol = -1;
     m_asCachedTilesDesc[0].nIdxWithinTileData = -1;
-    m_asCachedTilesDesc[0].abBandDirty[0] = FALSE;
-    m_asCachedTilesDesc[0].abBandDirty[1] = FALSE;
-    m_asCachedTilesDesc[0].abBandDirty[2] = FALSE;
-    m_asCachedTilesDesc[0].abBandDirty[3] = FALSE;
+    m_asCachedTilesDesc[0].abBandDirty[0] = false;
+    m_asCachedTilesDesc[0].abBandDirty[1] = false;
+    m_asCachedTilesDesc[0].abBandDirty[2] = false;
+    m_asCachedTilesDesc[0].abBandDirty[3] = false;
 
     CPLErr eErr = CE_Failure;
 
-    int bAllOpaque = TRUE;
+    bool bAllOpaque = true;
     if( m_poCT == NULL && nAlphaBand != 0 )
     {
         GByte byFirstAlphaVal =  m_pabyCachedTiles[(nAlphaBand-1) * nBlockXSize * nBlockYSize];
-        for(i=1;i<nBlockXSize * nBlockYSize;i++)
+        int i = 1;
+        for( ; i < nBlockXSize * nBlockYSize; i++ )
         {
             if( m_pabyCachedTiles[(nAlphaBand-1) * nBlockXSize * nBlockYSize + i] != byFirstAlphaVal )
                 break;
@@ -993,18 +1149,18 @@ CPLErr GDALGeoPackageDataset::WriteTileInternal()
             {
                 char* pszSQL = sqlite3_mprintf("DELETE FROM '%q' "
                     "WHERE zoom_level = %d AND tile_row = %d AND tile_column = %d",
-                    m_osRasterTable.c_str(), m_nZoomLevel, nRow, nCol);
+                    m_osRasterTable.c_str(), m_nZoomLevel, GetRowFromIntoTopConvention(nRow), nCol);
 #ifdef DEBUG_VERBOSE
                 CPLDebug("GPKG", "%s", pszSQL);
 #endif
                 char* pszErrMsg = NULL;
-                int rc = sqlite3_exec(GetDB(), pszSQL, NULL, NULL, &pszErrMsg);
-                if( rc == SQLITE_OK )
-                    eErr = CE_None;
-                else
+                int rc = sqlite3_exec(IGetDB(), pszSQL, NULL, NULL, &pszErrMsg);
+                if( rc != SQLITE_OK )
+                {
                     CPLError(CE_Failure, CPLE_AppDefined,
                             "Failure when deleting tile (row=%d,col=%d) at zoom_level=%d : %s",
-                            nRow, nCol, m_nZoomLevel, pszErrMsg ? pszErrMsg : "");
+                            GetRowFromIntoTopConvention(nRow), nCol, m_nZoomLevel, pszErrMsg ? pszErrMsg : "");
+                }
                 sqlite3_free(pszSQL);
                 sqlite3_free(pszErrMsg);
                 return CE_None;
@@ -1012,7 +1168,7 @@ CPLErr GDALGeoPackageDataset::WriteTileInternal()
             bAllOpaque = (byFirstAlphaVal == 255);
         }
         else
-            bAllOpaque = FALSE;
+            bAllOpaque = false;
     }
 
     if( bIsLossyFormat )
@@ -1025,23 +1181,23 @@ CPLErr GDALGeoPackageDataset::WriteTileInternal()
     CPLString osMemFileName;
     osMemFileName.Printf("/vsimem/gpkg_write_tile_%p", this);
     const char* pszDriverName = "PNG";
-    int bTileDriverSupports1Band = FALSE;
-    int bTileDriverSupports2Bands = FALSE;
-    int bTileDriverSupports4Bands = FALSE;
-    int bTileDriverSupportsCT = FALSE;
-    
+    bool bTileDriverSupports1Band = false;
+    bool bTileDriverSupports2Bands = false;
+    bool bTileDriverSupports4Bands = false;
+    bool bTileDriverSupportsCT = false;
+
     if( nBands == 1 )
-        GetRasterBand(1)->GetColorTable();
-    
+        IGetRasterBand(1)->GetColorTable();
+
     if( m_eTF == GPKG_TF_PNG_JPEG )
     {
-        bTileDriverSupports1Band = TRUE;
+        bTileDriverSupports1Band = true;
         if( bPartialTile || (nBands == 2 && !bAllOpaque) || (nBands == 4 && !bAllOpaque) || m_poCT != NULL )
         {
             pszDriverName = "PNG";
-            bTileDriverSupports2Bands = TRUE;
-            bTileDriverSupports4Bands = TRUE;
-            bTileDriverSupportsCT = TRUE;
+            bTileDriverSupports2Bands = m_bPNGSupports2Bands;
+            bTileDriverSupports4Bands = true;
+            bTileDriverSupportsCT = m_bPNGSupportsCT;
         }
         else
             pszDriverName = "JPEG";
@@ -1050,15 +1206,15 @@ CPLErr GDALGeoPackageDataset::WriteTileInternal()
              m_eTF == GPKG_TF_PNG8 )
     {
         pszDriverName = "PNG";
-        bTileDriverSupports1Band = TRUE;
-        bTileDriverSupports2Bands = TRUE;
-        bTileDriverSupports4Bands = TRUE;
-        bTileDriverSupportsCT = TRUE;
+        bTileDriverSupports1Band = true;
+        bTileDriverSupports2Bands = m_bPNGSupports2Bands;
+        bTileDriverSupports4Bands = true;
+        bTileDriverSupportsCT = m_bPNGSupportsCT;
     }
     else if( m_eTF == GPKG_TF_JPEG )
     {
         pszDriverName = "JPEG";
-        bTileDriverSupports1Band = TRUE;
+        bTileDriverSupports1Band = true;
     }
     else if( m_eTF == GPKG_TF_WEBP )
     {
@@ -1066,10 +1222,12 @@ CPLErr GDALGeoPackageDataset::WriteTileInternal()
         bTileDriverSupports4Bands = WEBPSupports4Bands();
     }
     else
+    {
         CPLAssert(0);
+    }
 
-    GDALDriver* poDriver = (GDALDriver*) GDALGetDriverByName(pszDriverName);
-    if( poDriver != NULL)
+    GDALDriver* l_poDriver = (GDALDriver*) GDALGetDriverByName(pszDriverName);
+    if( l_poDriver != NULL)
     {
         GDALDataset* poMEMDS = MEMDataset::Create("", nBlockXSize, nBlockYSize,
                                                   0, GDT_Byte, NULL);
@@ -1104,7 +1262,7 @@ CPLErr GDALGeoPackageDataset::WriteTileInternal()
             nTileBands = 3;
             if( bTileDriverSupports4Bands )
             {
-                for(i=0;i<m_poCT->GetColorEntryCount();i++)
+                for( int i = 0; i < m_poCT->GetColorEntryCount(); i++ )
                 {
                     const GDALColorEntry* psEntry = m_poCT->GetColorEntry(i);
                     if( psEntry->c4 == 0 )
@@ -1130,7 +1288,7 @@ CPLErr GDALGeoPackageDataset::WriteTileInternal()
             }
         }
 
-        for(i=0;i<nTileBands;i++)
+        for( int i = 0; i < nTileBands; i++ )
         {
             char** papszOptions = NULL;
             char szDataPointer[32];
@@ -1156,7 +1314,7 @@ CPLErr GDALGeoPackageDataset::WriteTileInternal()
         {
             GDALDataset* poMEM_RGB_DS = MEMDataset::Create("", nBlockXSize, nBlockYSize,
                                                   0, GDT_Byte, NULL);
-            for(i=0;i<3;i++)
+            for( int i = 0; i < 3; i++ )
             {
                 char** papszOptions = NULL;
                 char szDataPointer[32];
@@ -1168,13 +1326,13 @@ CPLErr GDALGeoPackageDataset::WriteTileInternal()
                 poMEM_RGB_DS->AddBand(GDT_Byte, papszOptions);
                 CSLDestroy(papszOptions);
             }
-            
+
             if( m_pabyHugeColorArray == NULL )
             {
-                if( nBlockXSize * nBlockYSize <= 65536 )
+                if( nBlockXSize <= 65536 / nBlockYSize )
                     m_pabyHugeColorArray = (GByte*) VSIMalloc(MEDIAN_CUT_AND_DITHER_BUFFER_SIZE_65536);
                 else
-                    m_pabyHugeColorArray = (GByte*) VSIMalloc2(256 * 256 * 256, sizeof(int));
+                    m_pabyHugeColorArray = (GByte*) VSIMalloc2(256 * 256 * 256, sizeof(GUInt32));
             }
 
             GDALColorTable* poCT = new GDALColorTable();
@@ -1188,14 +1346,14 @@ CPLErr GDALGeoPackageDataset::WriteTileInternal()
                                        NULL,
                                        256, /* max colors */
                                        8, /* bit depth */
-                                       (int*)m_pabyHugeColorArray, /* preallocated histogram */
+                                       (GUInt32*)m_pabyHugeColorArray, /* preallocated histogram */
                                        poCT,
                                        NULL, NULL );
 
             GDALDitherRGB2PCTInternal( poMEM_RGB_DS->GetRasterBand(1),
                                poMEM_RGB_DS->GetRasterBand(2),
                                poMEM_RGB_DS->GetRasterBand(3),
-                               poMEMDS->GetRasterBand(1), 
+                               poMEMDS->GetRasterBand(1),
                                poCT,
                                8, /* bit depth */
                                (GInt16*)m_pabyHugeColorArray, /* pasDynamicColorMap */
@@ -1209,7 +1367,7 @@ CPLErr GDALGeoPackageDataset::WriteTileInternal()
         {
             GByte abyCT[4*256];
             int nEntries = MIN(256, m_poCT->GetColorEntryCount());
-            for(i=0;i<nEntries;i++)
+            for( int i = 0; i < nEntries; i++ )
             {
                 const GDALColorEntry* psEntry = m_poCT->GetColorEntry(i);
                 abyCT[4*i] = (GByte)psEntry->c1;
@@ -1217,7 +1375,7 @@ CPLErr GDALGeoPackageDataset::WriteTileInternal()
                 abyCT[4*i+2] = (GByte)psEntry->c3;
                 abyCT[4*i+3] = (GByte)psEntry->c4;
             }
-            for(;i<256;i++)
+            for( int i = nEntries; i<256 ;i++ )
             {
                 abyCT[4*i] = 0;
                 abyCT[4*i+1] = 0;
@@ -1231,6 +1389,7 @@ CPLErr GDALGeoPackageDataset::WriteTileInternal()
                 memset(m_pabyCachedTiles + 2 * nBlockXSize * nBlockYSize, 0, nBlockXSize * iYOff);
                 memset(m_pabyCachedTiles + 3 * nBlockXSize * nBlockYSize, 0, nBlockXSize * iYOff);
             }
+            int i;  // TODO: Rename the variable to make it clean what it is.
             for(int iY = iYOff; iY < iYOff + iYCount; iY ++)
             {
                 if( iXOff > 0 )
@@ -1284,7 +1443,7 @@ CPLErr GDALGeoPackageDataset::WriteTileInternal()
         VSIStatBufL sStat;
         CPLAssert(VSIStatL(osMemFileName, &sStat) != 0);
 #endif
-        GDALDataset* poOutDS = poDriver->CreateCopy(osMemFileName, poMEMDS,
+        GDALDataset* poOutDS = l_poDriver->CreateCopy(osMemFileName, poMEMDS,
                                                     FALSE, papszDriverOptions, NULL, NULL);
         CSLDestroy( papszDriverOptions );
         if( poOutDS )
@@ -1294,31 +1453,31 @@ CPLErr GDALGeoPackageDataset::WriteTileInternal()
             GByte* pabyBlob = VSIGetMemFileBuffer(osMemFileName, &nBlobSize, TRUE);
 
             /* Create or commit and recreate transaction */
-            GDALGeoPackageDataset* poMainDS = m_poParentDS ? m_poParentDS : this;
+            GDALGPKGMBTilesLikePseudoDataset* poMainDS = m_poParentDS ? m_poParentDS : this;
             if( poMainDS->m_nTileInsertionCount == 0 )
             {
-                poMainDS->SoftStartTransaction();
+                poMainDS->IStartTransaction();
             }
             else if( poMainDS->m_nTileInsertionCount == 1000 )
             {
-                poMainDS->SoftCommitTransaction();
-                poMainDS->SoftStartTransaction();
+                poMainDS->ICommitTransaction();
+                poMainDS->IStartTransaction();
                 poMainDS->m_nTileInsertionCount = 0;
             }
             poMainDS->m_nTileInsertionCount ++;
 
             char* pszSQL = sqlite3_mprintf("INSERT OR REPLACE INTO '%q' "
                 "(zoom_level, tile_row, tile_column, tile_data) VALUES (%d, %d, %d, ?)",
-                m_osRasterTable.c_str(), m_nZoomLevel, nRow, nCol);
+                m_osRasterTable.c_str(), m_nZoomLevel, GetRowFromIntoTopConvention(nRow), nCol);
 #ifdef DEBUG_VERBOSE
             CPLDebug("GPKG", "%s", pszSQL);
 #endif
             sqlite3_stmt* hStmt = NULL;
-            int rc = sqlite3_prepare(GetDB(), pszSQL, -1, &hStmt, NULL);
+            int rc = sqlite3_prepare(IGetDB(), pszSQL, -1, &hStmt, NULL);
             if ( rc != SQLITE_OK )
             {
                 CPLError( CE_Failure, CPLE_AppDefined, "failed to prepare SQL %s: %s",
-                          pszSQL, sqlite3_errmsg(hDB) );
+                          pszSQL, sqlite3_errmsg(IGetDB()) );
                 CPLFree(pabyBlob);
             }
             else
@@ -1331,7 +1490,7 @@ CPLErr GDALGeoPackageDataset::WriteTileInternal()
                 {
                     CPLError(CE_Failure, CPLE_AppDefined,
                              "Failure when inserting tile (row=%d,col=%d) at zoom_level=%d : %s",
-                             nRow, nCol, m_nZoomLevel, sqlite3_errmsg(GetDB()));
+                             GetRowFromIntoTopConvention(nRow), nCol, m_nZoomLevel, sqlite3_errmsg(IGetDB()));
                 }
             }
             sqlite3_finalize(hStmt);
@@ -1354,7 +1513,7 @@ CPLErr GDALGeoPackageDataset::WriteTileInternal()
 /*                     FlushRemainingShiftedTiles()                     */
 /************************************************************************/
 
-CPLErr GDALGeoPackageDataset::FlushRemainingShiftedTiles()
+CPLErr GDALGPKGMBTilesLikePseudoDataset::FlushRemainingShiftedTiles()
 {
     if( m_hTempDB == NULL )
         return CE_None;
@@ -1367,7 +1526,8 @@ CPLErr GDALGeoPackageDataset::FlushRemainingShiftedTiles()
     }
 
     int nBlockXSize, nBlockYSize;
-    GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
+    IGetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
+    const int nBands = IGetRasterCount();
 
     CPLString osSQL = "SELECT tile_row, tile_column, partial_flag";
     for(int nBand = 1; nBand <= nBands; nBand++ )
@@ -1383,7 +1543,7 @@ CPLErr GDALGeoPackageDataset::FlushRemainingShiftedTiles()
     CPLDebug("GPKG", "%s", pszSQL);
 #endif
     sqlite3_stmt* hStmt = NULL;
-    int rc = sqlite3_prepare_v2(m_hTempDB, pszSQL, strlen(pszSQL), &hStmt, NULL);
+    int rc = sqlite3_prepare_v2(m_hTempDB, pszSQL, -1, &hStmt, NULL);
     if ( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined, "sqlite3_prepare(%s) failed: %s",
@@ -1392,13 +1552,13 @@ CPLErr GDALGeoPackageDataset::FlushRemainingShiftedTiles()
     }
 
     CPLErr eErr = CE_None;
-    int bGotPartialTiles = FALSE;
+    bool bGotPartialTiles = false;
     do
     {
-        int rc = sqlite3_step(hStmt);
+        rc = sqlite3_step(hStmt);
         if ( rc == SQLITE_ROW )
         {
-            bGotPartialTiles = TRUE;
+            bGotPartialTiles = true;
 
             int nRow = sqlite3_column_int(hStmt, 0);
             int nCol = sqlite3_column_int(hStmt, 1);
@@ -1430,13 +1590,13 @@ CPLErr GDALGeoPackageDataset::FlushRemainingShiftedTiles()
             {
                 char* pszNewSQL = sqlite3_mprintf("SELECT tile_data FROM '%q' "
                         "WHERE zoom_level = %d AND tile_row = %d AND tile_column = %d%s",
-                        m_osRasterTable.c_str(), m_nZoomLevel, nRow, nCol,
+                        m_osRasterTable.c_str(), m_nZoomLevel, GetRowFromIntoTopConvention(nRow), nCol,
                         m_osWHERE.size() ? CPLSPrintf(" AND (%s)", m_osWHERE.c_str()): "");
 #ifdef DEBUG_VERBOSE
                 CPLDebug("GPKG", "%s", pszNewSQL);
 #endif
                 sqlite3_stmt* hNewStmt = NULL;
-                rc = sqlite3_prepare(GetDB(), pszNewSQL, -1, &hNewStmt, NULL);
+                rc = sqlite3_prepare(IGetDB(), pszNewSQL, -1, &hNewStmt, NULL);
                 if ( rc == SQLITE_OK )
                 {
                     rc = sqlite3_step( hNewStmt );
@@ -1450,10 +1610,8 @@ CPLErr GDALGeoPackageDataset::FlushRemainingShiftedTiles()
                                                               nBytes, FALSE);
                         VSIFCloseL(fp);
 
-                        int bIsLossyFormat;
                         ReadTile(osMemFileName,
-                                 m_pabyCachedTiles + 4 * nBlockXSize * nBlockYSize,
-                                 &bIsLossyFormat);
+                                 m_pabyCachedTiles + 4 * nBlockXSize * nBlockYSize);
                         VSIUnlink(osMemFileName);
 
                         int iYQuadrantMax = ( m_nShiftYPixelsMod ) ? 1 : 0;
@@ -1508,23 +1666,40 @@ CPLErr GDALGeoPackageDataset::FlushRemainingShiftedTiles()
                             }
                         }
                     }
+                    else if( rc != SQLITE_DONE )
+                    {
+                        CPLError( CE_Failure, CPLE_AppDefined, "sqlite3_step(%s) failed: %s",
+                                  pszNewSQL, sqlite3_errmsg( m_hTempDB ) );
+                    }
                     sqlite3_finalize(hNewStmt);
                 }
+                else
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined, "sqlite3_prepare(%s) failed: %s",
+                              pszNewSQL, sqlite3_errmsg( m_hTempDB ) );
+                }
                 sqlite3_free(pszNewSQL);
             }
 
             m_asCachedTilesDesc[0].nRow = nRow;
             m_asCachedTilesDesc[0].nCol = nCol;
             m_asCachedTilesDesc[0].nIdxWithinTileData = 0;
-            m_asCachedTilesDesc[0].abBandDirty[0] = TRUE;
-            m_asCachedTilesDesc[0].abBandDirty[1] = TRUE;
-            m_asCachedTilesDesc[0].abBandDirty[2] = TRUE;
-            m_asCachedTilesDesc[0].abBandDirty[3] = TRUE;
+            m_asCachedTilesDesc[0].abBandDirty[0] = true;
+            m_asCachedTilesDesc[0].abBandDirty[1] = true;
+            m_asCachedTilesDesc[0].abBandDirty[2] = true;
+            m_asCachedTilesDesc[0].abBandDirty[3] = true;
 
             eErr = WriteTile();
         }
         else
+        {
+            if( rc != SQLITE_DONE )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined, "sqlite3_step(%s) failed: %s",
+                          pszSQL, sqlite3_errmsg( m_hTempDB ) );
+            }
             break;
+        }
     }
     while( eErr == CE_None);
 
@@ -1532,6 +1707,23 @@ CPLErr GDALGeoPackageDataset::FlushRemainingShiftedTiles()
 
     if( bGotPartialTiles )
     {
+#ifdef DEBUG_VERBOSE
+        pszSQL = CPLSPrintf("SELECT p1.id, p1.tile_row, p1.tile_column FROM partial_tiles p1, partial_tiles p2 "
+                            "WHERE p1.zoom_level = %d AND p2.zoom_level = %d AND p1.tile_row = p2.tile_row AND p1.tile_column = p2.tile_column AND p2.partial_flag != 0",
+                            -1-m_nZoomLevel, m_nZoomLevel);
+        rc = sqlite3_prepare_v2(m_hTempDB, pszSQL, -1, &hStmt, NULL);
+        CPLAssert( rc == SQLITE_OK );
+        while( (rc = sqlite3_step(hStmt)) == SQLITE_ROW )
+        {
+            CPLDebug("GPKG", "Conflict: existing id = %d, tile_row = %d, tile_column = %d, zoom_level = %d",
+                     sqlite3_column_int(hStmt, 0),
+                     sqlite3_column_int(hStmt, 1),
+                     sqlite3_column_int(hStmt, 2),
+                     m_nZoomLevel);
+        }
+        sqlite3_finalize(hStmt);
+#endif
+
         pszSQL = CPLSPrintf("UPDATE partial_tiles SET zoom_level = %d, "
                             "partial_flag = 0 WHERE zoom_level = %d AND partial_flag != 0",
                             -1-m_nZoomLevel, m_nZoomLevel);
@@ -1548,7 +1740,7 @@ CPLErr GDALGeoPackageDataset::FlushRemainingShiftedTiles()
 /*                         WriteShiftedTile()                           */
 /************************************************************************/
 
-CPLErr GDALGeoPackageDataset::WriteShiftedTile(int nRow, int nCol, int nBand,
+CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteShiftedTile(int nRow, int nCol, int nBand,
                                                int nDstXOffset, int nDstYOffset,
                                                int nDstXSize, int nDstYSize)
 {
@@ -1562,14 +1754,27 @@ CPLErr GDALGeoPackageDataset::WriteShiftedTile(int nRow, int nCol, int nBand,
         (m_poParentDS == NULL || m_poParentDS->m_hTempDB == NULL) )
     {
         const char* pszBaseFilename = m_poParentDS ?
-                m_poParentDS->m_pszFilename : m_pszFilename;
-        m_osTempDBFilename = CPLResetExtension(pszBaseFilename, "gpkg.tmp");
+                m_poParentDS->IGetFilename() : IGetFilename();
+        m_osTempDBFilename = CPLResetExtension(pszBaseFilename, "partial_tiles.db");
         CPLPushErrorHandler(CPLQuietErrorHandler);
         VSIUnlink(m_osTempDBFilename);
         CPLPopErrorHandler();
         m_hTempDB = NULL;
-        sqlite3_open(m_osTempDBFilename, &m_hTempDB);
-        if( m_hTempDB == NULL )
+        int rc;
+#ifdef HAVE_SQLITE_VFS
+        if (STARTS_WITH(m_osTempDBFilename, "/vsi"))
+        {
+            m_pMyVFS = OGRSQLiteCreateVFS(NULL, NULL);
+            sqlite3_vfs_register(m_pMyVFS, 0);
+            rc = sqlite3_open_v2( m_osTempDBFilename, &m_hTempDB,
+                             SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, m_pMyVFS->zName );
+        }
+        else
+#endif
+        {
+            rc = sqlite3_open(m_osTempDBFilename, &m_hTempDB);
+        }
+        if( rc != SQLITE_OK || m_hTempDB == NULL )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
                         "Cannot create temporary database %s",
@@ -1602,7 +1807,8 @@ CPLErr GDALGeoPackageDataset::WriteShiftedTile(int nRow, int nCol, int nBand,
         m_hTempDB = m_poParentDS->m_hTempDB;
 
     int nBlockXSize, nBlockYSize;
-    GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
+    IGetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
+    const int nBands = IGetRasterCount();
 
     int iQuadrantFlag = 0;
     if( nDstXOffset == 0 && nDstYOffset == 0 )
@@ -1613,7 +1819,7 @@ CPLErr GDALGeoPackageDataset::WriteShiftedTile(int nRow, int nCol, int nBand,
         iQuadrantFlag |= (1 << 2);
     if( nDstXOffset + nDstXSize == nBlockXSize && nDstYOffset + nDstYSize == nBlockYSize )
         iQuadrantFlag |= (1 << 3);
-    int nFlags = iQuadrantFlag << (4 * (nBand - 1));
+    int l_nFlags = iQuadrantFlag << (4 * (nBand - 1));
     int nFullFlags = (1 << (4 * nBands)) - 1;
     int nOldFlags = 0;
 
@@ -1632,7 +1838,7 @@ CPLErr GDALGeoPackageDataset::WriteShiftedTile(int nRow, int nCol, int nBand,
     CPLDebug("GPKG", "%s", pszSQL);
 #endif
     sqlite3_stmt* hStmt = NULL;
-    int rc = sqlite3_prepare_v2(m_hTempDB, pszSQL, strlen(pszSQL), &hStmt, NULL);
+    int rc = sqlite3_prepare_v2(m_hTempDB, pszSQL, -1, &hStmt, NULL);
     if ( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined, "sqlite3_prepare(%s) failed: %s",
@@ -1696,22 +1902,22 @@ CPLErr GDALGeoPackageDataset::WriteShiftedTile(int nRow, int nCol, int nBand,
     GDALClose(poLogDS);
 #endif
 
-    if( (nOldFlags & nFlags) != 0 )
+    if( (nOldFlags & l_nFlags) != 0 )
     {
         CPLDebug("GPKG",
                  "Rewriting quadrant %d of band %d of tile (row=%d,col=%d)",
                  iQuadrantFlag, nBand, nRow, nCol);
     }
 
-    nFlags |= nOldFlags;
-    if( nFlags == nFullFlags )
+    l_nFlags |= nOldFlags;
+    if( l_nFlags == nFullFlags )
     {
 #ifdef DEBUG_VERBOSE
         CPLDebug("GPKG", "Got all quadrants for that tile");
 #endif
         for( int iBand = 1; iBand <= nBands; iBand ++ )
         {
-            if( iBand != nBand && nExistingId )
+            if( iBand != nBand )
             {
                 pszSQL = CPLSPrintf("SELECT tile_data_band_%d FROM partial_tiles WHERE "
                                     "id = %d", iBand, nExistingId);
@@ -1719,7 +1925,7 @@ CPLErr GDALGeoPackageDataset::WriteShiftedTile(int nRow, int nCol, int nBand,
                 CPLDebug("GPKG", "%s", pszSQL);
 #endif
                 hStmt = NULL;
-                rc = sqlite3_prepare_v2(m_hTempDB, pszSQL, strlen(pszSQL), &hStmt, NULL);
+                rc = sqlite3_prepare_v2(m_hTempDB, pszSQL, -1, &hStmt, NULL);
                 if ( rc != SQLITE_OK )
                 {
                     CPLError( CE_Failure, CPLE_AppDefined, "sqlite3_prepare(%s) failed: %s",
@@ -1749,10 +1955,10 @@ CPLErr GDALGeoPackageDataset::WriteShiftedTile(int nRow, int nCol, int nBand,
         m_asCachedTilesDesc[0].nRow = nRow;
         m_asCachedTilesDesc[0].nCol = nCol;
         m_asCachedTilesDesc[0].nIdxWithinTileData = 0;
-        m_asCachedTilesDesc[0].abBandDirty[0] = TRUE;
-        m_asCachedTilesDesc[0].abBandDirty[1] = TRUE;
-        m_asCachedTilesDesc[0].abBandDirty[2] = TRUE;
-        m_asCachedTilesDesc[0].abBandDirty[3] = TRUE;
+        m_asCachedTilesDesc[0].abBandDirty[0] = true;
+        m_asCachedTilesDesc[0].abBandDirty[1] = true;
+        m_asCachedTilesDesc[0].abBandDirty[2] = true;
+        m_asCachedTilesDesc[0].abBandDirty[3] = true;
 
         pszSQL = CPLSPrintf("UPDATE partial_tiles SET zoom_level = %d, "
                             "partial_flag = 0 WHERE id = %d",
@@ -1769,7 +1975,7 @@ CPLErr GDALGeoPackageDataset::WriteShiftedTile(int nRow, int nCol, int nBand,
         OGRErr err;
         pszSQL = CPLSPrintf("SELECT id FROM partial_tiles WHERE "
                             "partial_flag = 0 AND zoom_level = %d "
-                            "AND tile_column = %d AND tile_row = %d",
+                            "AND tile_row = %d AND tile_column = %d",
                             -1-m_nZoomLevel, nRow, nCol);
 #ifdef DEBUG_VERBOSE
         CPLDebug("GPKG", "%s", pszSQL);
@@ -1789,14 +1995,14 @@ CPLErr GDALGeoPackageDataset::WriteShiftedTile(int nRow, int nCol, int nBand,
     {
         pszSQL = CPLSPrintf("INSERT INTO partial_tiles "
                 "(zoom_level, tile_row, tile_column, tile_data_band_%d, partial_flag) VALUES (%d, %d, %d, ?, %d)",
-                nBand, m_nZoomLevel, nRow, nCol, nFlags);
+                nBand, m_nZoomLevel, nRow, nCol, l_nFlags);
     }
     else
     {
         pszSQL = CPLSPrintf("UPDATE partial_tiles SET zoom_level = %d, "
                             "tile_row = %d, tile_column = %d, "
                             "tile_data_band_%d = ?, partial_flag = %d WHERE id = %d",
-                            m_nZoomLevel, nRow, nCol, nBand, nFlags, nExistingId);
+                            m_nZoomLevel, nRow, nCol, nBand, l_nFlags, nExistingId);
     }
 #ifdef DEBUG_VERBOSE
     CPLDebug("GPKG", "%s", pszSQL);
@@ -1835,41 +2041,30 @@ CPLErr GDALGeoPackageDataset::WriteShiftedTile(int nRow, int nCol, int nBand,
 /*                         IWriteBlock()                                */
 /************************************************************************/
 
-CPLErr GDALGeoPackageRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff,
+CPLErr GDALGPKGMBTilesLikeRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff,
                                              void* pData)
 {
-    GDALGeoPackageDataset* poGDS = (GDALGeoPackageDataset* )poDS;
-
 #ifdef DEBUG_VERBOSE
     CPLDebug("GPKG", "IWriteBlock(nBand=%d,nBlockXOff=%d,nBlockYOff=%d,m_nZoomLevel=%d)",
-             nBand,nBlockXOff,nBlockYOff,poGDS->m_nZoomLevel);
+             nBand,nBlockXOff,nBlockYOff,m_poTPD->m_nZoomLevel);
 #endif
 
-    if( !poGDS->bUpdate )
-    {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "IWriteBlock() not supported on dataset opened in read-only mode");
-        return CE_Failure;
-    }
-
-    if( !poGDS->m_bGeoTransformValid || poGDS->m_nSRID == UNKNOWN_SRID )
+    if( !m_poTPD->ICanIWriteBlock() )
     {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "IWriteBlock() not supported if georeferencing not set");
         return CE_Failure;
     }
 
-    int nRow = nBlockYOff + poGDS->m_nShiftYTiles;
-    int nCol = nBlockXOff + poGDS->m_nShiftXTiles;
+    int nRow = nBlockYOff + m_poTPD->m_nShiftYTiles;
+    int nCol = nBlockXOff + m_poTPD->m_nShiftXTiles;
 
     int nRowMin = nRow;
     int nRowMax = nRowMin;
-    if( poGDS->m_nShiftYPixelsMod )
+    if( m_poTPD->m_nShiftYPixelsMod )
         nRowMax ++;
 
     int nColMin = nCol;
     int nColMax = nColMin;
-    if( poGDS->m_nShiftXPixelsMod )
+    if( m_poTPD->m_nShiftXPixelsMod )
         nColMax ++;
 
     CPLErr eErr = CE_None;
@@ -1878,30 +2073,30 @@ CPLErr GDALGeoPackageRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff,
     {
         for(nCol = nColMin; eErr == CE_None && nCol <= nColMax; nCol++ )
         {
-            if( nRow < 0 || nCol < 0 || nRow >= poGDS->m_nTileMatrixHeight ||
-                nCol >= poGDS->m_nTileMatrixWidth )
+            if( nRow < 0 || nCol < 0 || nRow >= m_poTPD->m_nTileMatrixHeight ||
+                nCol >= m_poTPD->m_nTileMatrixWidth )
             {
                 continue;
             }
 
-            if( poGDS->m_nShiftXPixelsMod == 0 && poGDS->m_nShiftYPixelsMod == 0 )
+            if( m_poTPD->m_nShiftXPixelsMod == 0 && m_poTPD->m_nShiftYPixelsMod == 0 )
             {
-                if( !(nRow == poGDS->m_asCachedTilesDesc[0].nRow &&
-                    nCol == poGDS->m_asCachedTilesDesc[0].nCol &&
-                    poGDS->m_asCachedTilesDesc[0].nIdxWithinTileData == 0) )
+                if( !(nRow == m_poTPD->m_asCachedTilesDesc[0].nRow &&
+                    nCol == m_poTPD->m_asCachedTilesDesc[0].nCol &&
+                    m_poTPD->m_asCachedTilesDesc[0].nIdxWithinTileData == 0) )
                 {
-                    eErr = poGDS->WriteTile();
+                    eErr = m_poTPD->WriteTile();
 
-                    poGDS->m_asCachedTilesDesc[0].nRow = nRow;
-                    poGDS->m_asCachedTilesDesc[0].nCol = nCol;
-                    poGDS->m_asCachedTilesDesc[0].nIdxWithinTileData = 0;
+                    m_poTPD->m_asCachedTilesDesc[0].nRow = nRow;
+                    m_poTPD->m_asCachedTilesDesc[0].nCol = nCol;
+                    m_poTPD->m_asCachedTilesDesc[0].nIdxWithinTileData = 0;
                 }
             }
 
             // Composite block data into tile, and check if all bands for this block
             // are dirty, and if so write the tile
-            int bAllDirty = TRUE;
-            for(int iBand=1;iBand<=poGDS->nBands;iBand++)
+            bool bAllDirty = true;
+            for(int iBand=1;iBand<=poDS->GetRasterCount();iBand++)
             {
                 GDALRasterBlock* poBlock = NULL;
                 GByte* pabySrc;
@@ -1911,16 +2106,16 @@ CPLErr GDALGeoPackageRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff,
                 }
                 else
                 {
-                    if( !(poGDS->m_nShiftXPixelsMod == 0 && poGDS->m_nShiftYPixelsMod == 0) )
+                    if( !(m_poTPD->m_nShiftXPixelsMod == 0 && m_poTPD->m_nShiftYPixelsMod == 0) )
                         continue;
 
                     // If the block for this band is not dirty, it might be dirty in cache
-                    if( poGDS->m_asCachedTilesDesc[0].abBandDirty[iBand-1] )
+                    if( m_poTPD->m_asCachedTilesDesc[0].abBandDirty[iBand-1] )
                         continue;
                     else
                     {
                         poBlock =
-                            ((GDALGeoPackageRasterBand*)poGDS->GetRasterBand(iBand))->
+                            ((GDALGPKGMBTilesLikeRasterBand*)poDS->GetRasterBand(iBand))->
                                         TryGetLockedBlockRef(nBlockXOff, nBlockYOff);
                         if( poBlock && poBlock->GetDirty() )
                         {
@@ -1931,20 +2126,20 @@ CPLErr GDALGeoPackageRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff,
                         {
                             if( poBlock )
                                 poBlock->DropLock();
-                            bAllDirty = FALSE;
+                            bAllDirty = false;
                             continue;
                         }
                     }
                 }
 
-                if( poGDS->m_nShiftXPixelsMod == 0 && poGDS->m_nShiftYPixelsMod == 0 )
-                    poGDS->m_asCachedTilesDesc[0].abBandDirty[iBand - 1] = TRUE;
+                if( m_poTPD->m_nShiftXPixelsMod == 0 && m_poTPD->m_nShiftYPixelsMod == 0 )
+                    m_poTPD->m_asCachedTilesDesc[0].abBandDirty[iBand - 1] = true;
 
                 int nDstXOffset = 0, nDstXSize = nBlockXSize,
                     nDstYOffset = 0, nDstYSize = nBlockYSize;
                 int nSrcXOffset = 0, nSrcYOffset = 0;
                 // Composite block data into tile data
-                if( poGDS->m_nShiftXPixelsMod == 0 && poGDS->m_nShiftYPixelsMod == 0 )
+                if( m_poTPD->m_nShiftXPixelsMod == 0 && m_poTPD->m_nShiftYPixelsMod == 0 )
                 {
 
 #ifdef DEBUG_VERBOSE
@@ -1959,7 +2154,7 @@ CPLErr GDALGeoPackageRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff,
                                 if( pabySrc[y*nBlockXSize+x] != 0 && !bFoundNonZero )
                                 {
                                     CPLDebug("GPKG", "IWriteBlock(): Found non-zero content in ghost part of tile(nBand=%d,nBlockXOff=%d,nBlockYOff=%d,m_nZoomLevel=%d)\n",
-                                            iBand,nBlockXOff,nBlockYOff,poGDS->m_nZoomLevel);
+                                            iBand,nBlockXOff,nBlockYOff,m_poTPD->m_nZoomLevel);
                                     bFoundNonZero = true;
                                 }
                             }
@@ -1967,7 +2162,7 @@ CPLErr GDALGeoPackageRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff,
                     }
 #endif
 
-                    memcpy( poGDS->m_pabyCachedTiles + (iBand - 1) * nBlockXSize * nBlockYSize,
+                    memcpy( m_poTPD->m_pabyCachedTiles + (iBand - 1) * nBlockXSize * nBlockYSize,
                             pabySrc, nBlockXSize * nBlockYSize );
 
                     // Make sure partial blocks are zero'ed outside of the validity area
@@ -1975,7 +2170,7 @@ CPLErr GDALGeoPackageRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff,
                     // avoid edge effects (although we should probably repeat last pixels
                     // if we really want to do that, but that only makes sense if readers
                     // only clip to the gpkg_contents extent). Well, ere on the safe side for now
-                    if( poGDS->m_eTF != GPKG_TF_JPEG &&
+                    if( m_poTPD->m_eTF != GPKG_TF_JPEG &&
                         ((nBlockXOff+1) * nBlockXSize >= nRasterXSize ||
                          (nBlockYOff+1) * nBlockYSize >= nRasterYSize) )
                     {
@@ -1989,14 +2184,14 @@ CPLErr GDALGeoPackageRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff,
                         {
                             for( int iY = 0; iY < nYEndValidity; iY++ )
                             {
-                                memset( poGDS->m_pabyCachedTiles + ((iBand - 1) * nBlockYSize + iY) * nBlockXSize + nXEndValidity,
+                                memset( m_poTPD->m_pabyCachedTiles + ((iBand - 1) * nBlockYSize + iY) * nBlockXSize + nXEndValidity,
                                         0,
                                         nBlockXSize - nXEndValidity );
                             }
                         }
                         if( nYEndValidity < nBlockYSize )
                         {
-                            memset( poGDS->m_pabyCachedTiles + ((iBand - 1) * nBlockYSize + nYEndValidity) * nBlockXSize,
+                            memset( m_poTPD->m_pabyCachedTiles + ((iBand - 1) * nBlockYSize + nYEndValidity) * nBlockXSize,
                                     0,
                                     (nBlockYSize - nYEndValidity) * nBlockXSize );
                         }
@@ -2007,35 +2202,46 @@ CPLErr GDALGeoPackageRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff,
                 {
                     if( nCol == nColMin )
                     {
-                        nDstXOffset = poGDS->m_nShiftXPixelsMod;
-                        nDstXSize = nBlockXSize - poGDS->m_nShiftXPixelsMod;
+                        nDstXOffset = m_poTPD->m_nShiftXPixelsMod;
+                        nDstXSize = nBlockXSize - m_poTPD->m_nShiftXPixelsMod;
                         nSrcXOffset = 0;
                     }
                     else
                     {
                         nDstXOffset = 0;
-                        nDstXSize = poGDS->m_nShiftXPixelsMod;
-                        nSrcXOffset = nBlockXSize - poGDS->m_nShiftXPixelsMod;
+                        nDstXSize = m_poTPD->m_nShiftXPixelsMod;
+                        nSrcXOffset = nBlockXSize - m_poTPD->m_nShiftXPixelsMod;
                     }
                     if( nRow == nRowMin )
                     {
-                        nDstYOffset = poGDS->m_nShiftYPixelsMod;
-                        nDstYSize = nBlockYSize - poGDS->m_nShiftYPixelsMod;
+                        nDstYOffset = m_poTPD->m_nShiftYPixelsMod;
+                        nDstYSize = nBlockYSize - m_poTPD->m_nShiftYPixelsMod;
                         nSrcYOffset = 0;
                     }
                     else
                     {
                         nDstYOffset = 0;
-                        nDstYSize = poGDS->m_nShiftYPixelsMod;
-                        nSrcYOffset = nBlockYSize - poGDS->m_nShiftYPixelsMod;
+                        nDstYSize = m_poTPD->m_nShiftYPixelsMod;
+                        nSrcYOffset = nBlockYSize - m_poTPD->m_nShiftYPixelsMod;
                     }
-                    //CPLDebug("GPKG", "Copy source tile x=%d,w=%d,y=%d,h=%d into buffet at x=%d,y=%d",
-                    //         nDstXOffset, nDstXSize, nDstYOffset, nDstYSize, nSrcXOffset, nSrcYOffset);
+
+#ifdef DEBUG_VERBOSE
+                    CPLDebug( "GPKG",
+                              "Copy source tile x=%d,w=%d,y=%d,h=%d into "
+                              "buffer at x=%d,y=%d",
+                              nDstXOffset, nDstXSize, nDstYOffset, nDstYSize,
+                              nSrcXOffset, nSrcYOffset);
+#endif
+
                     for( int y=0; y<nDstYSize; y++ )
                     {
-                        GByte* pDst = poGDS->m_pabyCachedTiles + (iBand - 1) * nBlockXSize * nBlockYSize +
-                                        (y + nDstYOffset) * nBlockXSize + nDstXOffset;
-                        GByte* pSrc = pabySrc + (y + nSrcYOffset) * nBlockXSize + nSrcXOffset;
+                        GByte* pDst =
+                          m_poTPD->m_pabyCachedTiles +
+                          (iBand - 1) * nBlockXSize * nBlockYSize +
+                          (y + nDstYOffset) * nBlockXSize + nDstXOffset;
+                        GByte* pSrc =
+                            pabySrc + (y + nSrcYOffset) * nBlockXSize +
+                            nSrcXOffset;
                         GDALCopyWords(pSrc, GDT_Byte, 1,
                                     pDst, GDT_Byte, 1,
                                     nDstXSize);
@@ -2045,22 +2251,24 @@ CPLErr GDALGeoPackageRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff,
                 if( poBlock )
                     poBlock->DropLock();
 
-                if( !(poGDS->m_nShiftXPixelsMod == 0 && poGDS->m_nShiftYPixelsMod == 0) )
+                if( !(m_poTPD->m_nShiftXPixelsMod == 0
+                      && m_poTPD->m_nShiftYPixelsMod == 0) )
                 {
-                    poGDS->m_asCachedTilesDesc[0].nRow = -1;
-                    poGDS->m_asCachedTilesDesc[0].nCol = -1;
-                    poGDS->m_asCachedTilesDesc[0].nIdxWithinTileData = -1;
-                    eErr = poGDS->WriteShiftedTile(nRow, nCol, iBand,
+                    m_poTPD->m_asCachedTilesDesc[0].nRow = -1;
+                    m_poTPD->m_asCachedTilesDesc[0].nCol = -1;
+                    m_poTPD->m_asCachedTilesDesc[0].nIdxWithinTileData = -1;
+                    eErr = m_poTPD->WriteShiftedTile(nRow, nCol, iBand,
                                                    nDstXOffset, nDstYOffset,
                                                    nDstXSize, nDstYSize);
                 }
             }
 
-            if( poGDS->m_nShiftXPixelsMod == 0 && poGDS->m_nShiftYPixelsMod == 0 )
+            if( m_poTPD->m_nShiftXPixelsMod == 0
+                && m_poTPD->m_nShiftYPixelsMod == 0 )
             {
-                if( bAllDirty ) 
+                if( bAllDirty )
                 {
-                    eErr = poGDS->WriteTile();
+                    eErr = m_poTPD->WriteTile();
                 }
             }
         }
@@ -2070,12 +2278,24 @@ CPLErr GDALGeoPackageRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff,
 }
 
 /************************************************************************/
+/*                      GDALGeoPackageRasterBand()                      */
+/************************************************************************/
+
+GDALGeoPackageRasterBand::GDALGeoPackageRasterBand(
+    GDALGeoPackageDataset* poDSIn, int nTileWidth, int nTileHeight) :
+          GDALGPKGMBTilesLikeRasterBand(poDSIn, nTileWidth, nTileHeight)
+{
+    poDS = poDSIn;
+}
+
+/************************************************************************/
 /*                         GetOverviewCount()                           */
 /************************************************************************/
 
 int GDALGeoPackageRasterBand::GetOverviewCount()
 {
-    GDALGeoPackageDataset* poGDS = (GDALGeoPackageDataset* )poDS;
+    GDALGeoPackageDataset *poGDS
+        = reinterpret_cast<GDALGeoPackageDataset *>( poDS );
     return poGDS->m_nOverviewCount;
 }
 
@@ -2085,7 +2305,8 @@ int GDALGeoPackageRasterBand::GetOverviewCount()
 
 GDALRasterBand* GDALGeoPackageRasterBand::GetOverview(int nIdx)
 {
-    GDALGeoPackageDataset* poGDS = (GDALGeoPackageDataset* )poDS;
+    GDALGeoPackageDataset *poGDS
+        = reinterpret_cast<GDALGeoPackageDataset *>( poDS );
     if( nIdx < 0 || nIdx >= poGDS->m_nOverviewCount )
         return NULL;
     return poGDS->m_papoOverviewDS[nIdx]->GetRasterBand(nBand);
diff --git a/ogr/ogrsf_frmts/gpkg/geopackage_aspatial.md b/ogr/ogrsf_frmts/gpkg/geopackage_aspatial.md
index e23c988..42b63a8 100644
--- a/ogr/ogrsf_frmts/gpkg/geopackage_aspatial.md
+++ b/ogr/ogrsf_frmts/gpkg/geopackage_aspatial.md
@@ -8,7 +8,8 @@ Aspatial Support
 
 ## Introduction
 
-Support for aspatial data (ie. SQLite tables/views without a geometry column), potentially with associated metadata.
+Support for aspatial data (i.e. SQLite tables/views without a geometry column),
+potentially with associated metadata.
 
 ## Extension Author
 
diff --git a/ogr/ogrsf_frmts/gpkg/gpkgmbtilescommon.h b/ogr/ogrsf_frmts/gpkg/gpkgmbtilescommon.h
new file mode 100644
index 0000000..ea8825e
--- /dev/null
+++ b/ogr/ogrsf_frmts/gpkg/gpkgmbtilescommon.h
@@ -0,0 +1,153 @@
+/******************************************************************************
+ * $Id: gpkgmbtilescommon.h 33820 2016-03-31 12:34:07Z rouault $
+ *
+ * Project:  GeoPackage/MBTiles Translator
+ * Purpose:  Definition of common classes for GeoPackage and MBTiles drivers.
+ * Author:   Even Rouault <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2014-2016, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef GPKGMBTILESCOMMON_H_INCLUDED
+#define GPKGMBTILESCOMMON_H_INCLUDED
+
+#include "cpl_string.h"
+#include "gdal_pam.h"
+#include "ogr_sqlite.h" // for sqlite3*
+
+typedef struct
+{
+    int     nRow;
+    int     nCol;
+    int     nIdxWithinTileData;
+    bool    abBandDirty[4];
+} CachedTileDesc;
+
+typedef enum
+{
+    GPKG_TF_PNG_JPEG,
+    GPKG_TF_PNG,
+    GPKG_TF_PNG8,
+    GPKG_TF_JPEG,
+    GPKG_TF_WEBP
+} GPKGTileFormat;
+
+GPKGTileFormat GDALGPKGMBTilesGetTileFormat(const char* pszTF );
+
+class GDALGPKGMBTilesLikePseudoDataset
+{
+    friend class GDALGPKGMBTilesLikeRasterBand;
+
+  protected:
+    bool                m_bNew;
+
+    CPLString           m_osRasterTable;
+    int                 m_nZoomLevel;
+    GByte              *m_pabyCachedTiles;
+    CachedTileDesc      m_asCachedTilesDesc[4];
+    int                 m_nShiftXTiles;
+    int                 m_nShiftXPixelsMod;
+    int                 m_nShiftYTiles;
+    int                 m_nShiftYPixelsMod;
+    int                 m_nTileMatrixWidth;
+    int                 m_nTileMatrixHeight;
+
+    GPKGTileFormat      m_eTF;
+    bool                m_bPNGSupports2Bands; // for test/debug purposes only. true is the nominal value
+    bool                m_bPNGSupportsCT; // for test/debug purposes only. true is the nominal value
+    int                 m_nZLevel;
+    int                 m_nQuality;
+    bool                m_bDither;
+
+    GDALColorTable*     m_poCT;
+    bool                m_bTriedEstablishingCT;
+    GByte*              m_pabyHugeColorArray;
+
+    CPLString           m_osWHERE;
+
+#ifdef HAVE_SQLITE_VFS
+    sqlite3_vfs*        m_pMyVFS;
+#endif
+    sqlite3            *m_hTempDB;
+    CPLString           m_osTempDBFilename;
+
+    int                 m_nTileInsertionCount;
+
+    GDALGPKGMBTilesLikePseudoDataset* m_poParentDS;
+
+        bool                    m_bInWriteTile;
+        CPLErr                  WriteTileInternal(); /* should only be called by WriteTile() */
+
+  public:
+                                GDALGPKGMBTilesLikePseudoDataset();
+        virtual                ~GDALGPKGMBTilesLikePseudoDataset();
+
+        CPLErr                  ReadTile(const CPLString& osMemFileName,
+                                         GByte* pabyTileData,
+                                         bool* pbIsLossyFormat = NULL);
+        GByte*                  ReadTile(int nRow, int nCol);
+        GByte*                  ReadTile(int nRow, int nCol, GByte* pabyData,
+                                         bool* pbIsLossyFormat = NULL);
+
+        CPLErr                  WriteTile();
+
+        CPLErr                  FlushTiles();
+        CPLErr                  FlushRemainingShiftedTiles();
+        CPLErr                  WriteShiftedTile(int nRow, int nCol, int iBand,
+                                                 int nDstXOffset, int nDstYOffset,
+                                                 int nDstXSize, int nDstYSize);
+
+        virtual CPLErr                  IFlushCacheWithErrCode() = 0;
+        virtual int                     IGetRasterCount() = 0;
+        virtual GDALRasterBand*         IGetRasterBand(int nBand) = 0;
+        virtual sqlite3                *IGetDB() = 0;
+        virtual bool                    IGetUpdate() = 0;
+        virtual bool                    ICanIWriteBlock() = 0;
+        virtual void                    IStartTransaction() = 0;
+        virtual void                    ICommitTransaction() = 0;
+        virtual const char             *IGetFilename() = 0;
+        virtual int                     GetRowFromIntoTopConvention(int nRow) = 0;
+};
+
+class GDALGPKGMBTilesLikeRasterBand: public GDALPamRasterBand
+{
+    GDALGPKGMBTilesLikePseudoDataset* m_poTPD;
+
+    public:
+                                GDALGPKGMBTilesLikeRasterBand(GDALGPKGMBTilesLikePseudoDataset* poTPD,
+                                                              int nTileWidth, int nTileHeight);
+
+        virtual CPLErr          IReadBlock(int nBlockXOff, int nBlockYOff,
+                                           void* pData);
+        virtual CPLErr          IWriteBlock(int nBlockXOff, int nBlockYOff,
+                                           void* pData);
+        virtual CPLErr          FlushCache();
+
+        virtual GDALColorTable* GetColorTable();
+        virtual CPLErr          SetColorTable(GDALColorTable* poCT);
+
+        virtual GDALColorInterp GetColorInterpretation();
+        virtual CPLErr          SetColorInterpretation( GDALColorInterp );
+
+};
+
+#endif // GPKGMBTILESCOMMON_H_INCLUDED
diff --git a/ogr/ogrsf_frmts/gpkg/ogr_geopackage.h b/ogr/ogrsf_frmts/gpkg/ogr_geopackage.h
index e86709b..b43920d 100644
--- a/ogr/ogrsf_frmts/gpkg/ogr_geopackage.h
+++ b/ogr/ogrsf_frmts/gpkg/ogr_geopackage.h
@@ -27,12 +27,13 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_GEOPACKAGE_H_INCLUDED
-#define _OGR_GEOPACKAGE_H_INCLUDED
+#ifndef OGR_GEOPACKAGE_H_INCLUDED
+#define OGR_GEOPACKAGE_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "ogr_sqlite.h"
 #include "ogrgeopackageutility.h"
+#include "gpkgmbtilescommon.h"
 
 #define UNKNOWN_SRID   -2
 #define DEFAULT_SRID    0
@@ -43,82 +44,36 @@
 
 class OGRGeoPackageTableLayer;
 
-typedef struct
-{
-    int     nRow;
-    int     nCol;
-    int     nIdxWithinTileData;
-    int     abBandDirty[4];
-} CachedTileDesc;
-
-typedef enum
-{
-    GPKG_TF_PNG_JPEG,
-    GPKG_TF_PNG,
-    GPKG_TF_PNG8,
-    GPKG_TF_JPEG,
-    GPKG_TF_WEBP
-} GPKGTileFormat;
-
-class GDALGeoPackageDataset : public OGRSQLiteBaseDataSource
+class GDALGeoPackageDataset CPL_FINAL : public OGRSQLiteBaseDataSource, public GDALGPKGMBTilesLikePseudoDataset
 {
     friend class GDALGeoPackageRasterBand;
     friend class OGRGeoPackageTableLayer;
 
     OGRGeoPackageTableLayer** m_papoLayers;
     int                 m_nLayers;
-    int                 m_bUtf8;
-    void                CheckUnknownExtensions(int bCheckRasterTable = FALSE);
-    
-    int                 m_bNew;
+    bool                m_bUtf8;
+    void                CheckUnknownExtensions(bool bCheckRasterTable = false);
 
-    CPLString           m_osRasterTable;
     CPLString           m_osIdentifier;
-    int                 m_bIdentifierAsCO;
+    bool                m_bIdentifierAsCO;
     CPLString           m_osDescription;
-    int                 m_bDescriptionAsCO;
-    int                 m_bHasReadMetadataFromStorage;
-    int                 m_bMetadataDirty;
+    bool                m_bDescriptionAsCO;
+    bool                m_bHasReadMetadataFromStorage;
+    bool                m_bMetadataDirty;
     char              **m_papszSubDatasets;
     char               *m_pszProjection;
-    int                 m_bRecordInsertedInGPKGContent;
-    int                 m_bGeoTransformValid;
+    bool                m_bRecordInsertedInGPKGContent;
+    bool                m_bGeoTransformValid;
     double              m_adfGeoTransform[6];
     int                 m_nSRID;
     double              m_dfTMSMinX;
     double              m_dfTMSMaxY;
-    int                 m_nZoomLevel;
-    GByte              *m_pabyCachedTiles;
-    CachedTileDesc      m_asCachedTilesDesc[4];
-    int                 m_nShiftXTiles;
-    int                 m_nShiftXPixelsMod;
-    int                 m_nShiftYTiles;
-    int                 m_nShiftYPixelsMod;
-    int                 m_nTileMatrixWidth;
-    int                 m_nTileMatrixHeight;
-
-    GPKGTileFormat      m_eTF;
-    int                 m_nZLevel;
-    int                 m_nQuality;
-    int                 m_bDither;
-
-    GDALColorTable*     m_poCT;
-    int                 m_bTriedEstablishingCT;
-    GByte*              m_pabyHugeColorArray;
-
-    GDALGeoPackageDataset* m_poParentDS;
+
     int                 m_nOverviewCount;
     GDALGeoPackageDataset** m_papoOverviewDS;
-    int                 m_bZoomOther;
-
-    CPLString           m_osWHERE;
+    bool                m_bZoomOther;
 
-    sqlite3            *m_hTempDB;
-    CPLString           m_osTempDBFilename;
-    
-    int                 m_bInFlushCache;
-    
-    int                 m_nTileInsertionCount;
+    bool                m_bInFlushCache;
 
     CPLString           m_osTilingScheme;
 
@@ -168,22 +123,6 @@ class GDALGeoPackageDataset : public OGRSQLiteBaseDataSource
                             char** papszOptions );
         CPLErr   FinalizeRasterRegistration();
 
-        CPLErr                  ReadTile(const CPLString& osMemFileName,
-                                         GByte* pabyTileData,
-                                         int* pbIsLossyFormat = NULL);
-        GByte*                  ReadTile(int nRow, int nCol);
-        GByte*                  ReadTile(int nRow, int nCol, GByte* pabyData,
-                                         int* pbIsLossyFormat = NULL);
-
-        int                     m_bInWriteTile;
-        CPLErr                  WriteTile();
-
-        CPLErr                  WriteTileInternal(); /* should only be called by WriteTile() */
-        CPLErr                  FlushRemainingShiftedTiles();
-        CPLErr                  WriteShiftedTile(int nRow, int nCol, int iBand,
-                                                 int nDstXOffset, int nDstYOffset,
-                                                 int nDstXSize, int nDstYSize);
-
         int                     RegisterWebPExtension();
         int                     RegisterZoomOtherExtension();
         void                    ParseCompressionOptions(char** papszOptions);
@@ -191,7 +130,7 @@ class GDALGeoPackageDataset : public OGRSQLiteBaseDataSource
         int                     HasMetadataTables();
         int                     CreateMetadataTables();
         const char*             CheckMetadataDomain( const char* pszDomain );
-        void                    WriteMetadata(CPLXMLNode* psXMLNode, /* will be destroyed by the method /*/
+        void                    WriteMetadata(CPLXMLNode* psXMLNode, /* will be destroyed by the method */
                                               const char* pszTableName);
         CPLErr                  FlushMetadata();
 
@@ -216,7 +155,6 @@ class GDALGeoPackageDataset : public OGRSQLiteBaseDataSource
         virtual CPLErr      SetGeoTransform( double* padfGeoTransform );
 
         virtual void        FlushCache();
-        CPLErr              FlushCacheWithErrCode();
         virtual CPLErr      IBuildOverviews( const char *, int, int *,
                                              int, int *, GDALProgressFunc, void * );
 
@@ -229,13 +167,13 @@ class GDALGeoPackageDataset : public OGRSQLiteBaseDataSource
                                     GDALDataType eDT,
                                     char **papszOptions );
         OGRLayer*           GetLayer( int iLayer );
-        int                 DeleteLayer( int iLayer );
+        OGRErr              DeleteLayer( int iLayer );
         OGRLayer*           ICreateLayer( const char * pszLayerName,
                                          OGRSpatialReference * poSpatialRef,
                                          OGRwkbGeometryType eGType,
                                          char **papszOptions );
         int                 TestCapability( const char * );
-        
+
         virtual std::pair<OGRLayer*, IOGRSQLiteGetSpatialWhere*> GetLayerWithGetSpatialWhereByName( const char* pszName );
 
         virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
@@ -249,51 +187,52 @@ class GDALGeoPackageDataset : public OGRSQLiteBaseDataSource
         int                 GetSrsId( const OGRSpatialReference * poSRS );
         const char*         GetSrsName( const OGRSpatialReference * poSRS );
         OGRSpatialReference* GetSpatialRef( int iSrsId );
-        virtual int         GetUTF8() { return m_bUtf8; }
+        bool                GetUTF8() { return m_bUtf8; }
         OGRErr              CreateExtensionsTableIfNecessary();
-        int                 HasExtensionsTable();
+        bool                HasExtensionsTable();
         OGRErr              CreateGDALAspatialExtension();
-        void                SetMetadataDirty() { m_bMetadataDirty = TRUE; }
+        void                SetMetadataDirty() { m_bMetadataDirty = true; }
 
         const char*         GetGeometryTypeString(OGRwkbGeometryType eType);
 
         static GDALDataset* CreateCopy( const char *pszFilename,
-                                                   GDALDataset *poSrcDS, 
+                                                   GDALDataset *poSrcDS,
                                                    int bStrict,
                                                    char ** papszOptions,
-                                                   GDALProgressFunc pfnProgress, 
+                                                   GDALProgressFunc pfnProgress,
                                                    void * pProgressData );
+
+    protected:
+        // Coming from GDALGPKGMBTilesLikePseudoDataset
+
+        virtual CPLErr                  IFlushCacheWithErrCode();
+        virtual int                     IGetRasterCount() { return nBands; }
+        virtual GDALRasterBand*         IGetRasterBand(int nBand) { return GetRasterBand(nBand); }
+        virtual sqlite3                *IGetDB() { return GetDB(); }
+        virtual bool                    IGetUpdate() { return bUpdate != FALSE; }
+        virtual bool                    ICanIWriteBlock();
+        virtual void                    IStartTransaction() { SoftStartTransaction(); }
+        virtual void                    ICommitTransaction() { SoftCommitTransaction(); }
+        virtual const char             *IGetFilename() { return m_pszFilename; }
+        virtual int                     GetRowFromIntoTopConvention(int nRow) { return nRow; }
+
     private:
-    
+
         OGRErr              PragmaCheck(const char * pszPragma, const char * pszExpected, int nRowsExpected);
         OGRErr              SetApplicationId();
         int                 OpenOrCreateDB(int flags);
-        int                 HasGDALAspatialExtension();
+        bool                HasGDALAspatialExtension();
 };
 
 /************************************************************************/
 /*                        GDALGeoPackageRasterBand                      */
 /************************************************************************/
 
-class GDALGeoPackageRasterBand: public GDALPamRasterBand
+class GDALGeoPackageRasterBand CPL_FINAL: public GDALGPKGMBTilesLikeRasterBand
 {
     public:
-
                                 GDALGeoPackageRasterBand(GDALGeoPackageDataset* poDS,
-                                                         int nBand,
                                                          int nTileWidth, int nTileHeight);
-        
-        virtual CPLErr          IReadBlock(int nBlockXOff, int nBlockYOff,
-                                           void* pData);
-        virtual CPLErr          IWriteBlock(int nBlockXOff, int nBlockYOff,
-                                           void* pData);
-        virtual CPLErr          FlushCache();
-
-        virtual GDALColorTable* GetColorTable();
-        virtual CPLErr          SetColorTable(GDALColorTable* poCT);
-
-        virtual GDALColorInterp GetColorInterpretation();
-        virtual CPLErr          SetColorInterpretation( GDALColorInterp );
 
         virtual int             GetOverviewCount();
         virtual GDALRasterBand* GetOverview(int nIdx);
@@ -322,7 +261,7 @@ class OGRGeoPackageLayer : public OGRLayer, public IOGRSQLiteGetSpatialWhere
 
     void                ClearStatement();
     virtual OGRErr      ResetStatement() = 0;
-    
+
     void                BuildFeatureDefn( const char *pszLayerName,
                                            sqlite3_stmt *hStmt );
 
@@ -341,9 +280,9 @@ class OGRGeoPackageLayer : public OGRLayer, public IOGRSQLiteGetSpatialWhere
     int                 TestCapability( const char * );
     OGRFeatureDefn*     GetLayerDefn() { return m_poFeatureDefn; }
 
-    virtual int          HasFastSpatialFilter(CPL_UNUSED int iGeomCol) { return FALSE; }
-    virtual CPLString    GetSpatialWhere(CPL_UNUSED int iGeomCol,
-                                         CPL_UNUSED OGRGeometry* poFilterGeom) { return ""; }
+    virtual int          HasFastSpatialFilter(int /*iGeomCol*/) { return FALSE; }
+    virtual CPLString    GetSpatialWhere(int /*iGeomCol*/,
+                                         OGRGeometry* /*poFilterGeom*/) { return ""; }
 
 };
 
@@ -351,7 +290,7 @@ class OGRGeoPackageLayer : public OGRLayer, public IOGRSQLiteGetSpatialWhere
 /*                        OGRGeoPackageTableLayer                       */
 /************************************************************************/
 
-class OGRGeoPackageTableLayer : public OGRGeoPackageLayer
+class OGRGeoPackageTableLayer CPL_FINAL : public OGRGeoPackageLayer
 {
     char*                       m_pszTableName;
     int                         m_iSrs;
@@ -359,37 +298,37 @@ class OGRGeoPackageTableLayer : public OGRGeoPackageLayer
     CPLString                   m_soColumns;
     CPLString                   m_soFilter;
     CPLString                   osQuery;
-    OGRBoolean                  m_bExtentChanged;
+    bool                        m_bExtentChanged;
     sqlite3_stmt*               m_poUpdateStatement;
-    int                         m_bInsertStatementWithFID;
+    bool                        m_bInsertStatementWithFID;
     sqlite3_stmt*               m_poInsertStatement;
-    int                         bDeferedSpatialIndexCreation;
+    bool                        m_bDeferredSpatialIndexCreation;
+    // m_bHasSpatialIndex cannot be bool.  -1 is unset.
     int                         m_bHasSpatialIndex;
-    int                         bDropRTreeTable;
-    int                         m_anHasGeometryExtension[wkbMultiSurface+1];
-    int                         m_bPreservePrecision;
-    int                         m_bTruncateFields;
-    int                         m_bDeferredCreation;
+    bool                        m_bDropRTreeTable;
+    bool                        m_abHasGeometryExtension[wkbTIN+1];
+    bool                        m_bPreservePrecision;
+    bool                        m_bTruncateFields;
+    bool                        m_bDeferredCreation;
     int                         m_iFIDAsRegularColumnIndex;
-    
+
     CPLString                   m_osIdentifierLCO;
     CPLString                   m_osDescriptionLCO;
-    int                         m_bHasReadMetadataFromStorage;
+    bool                        m_bHasReadMetadataFromStorage;
 
     virtual OGRErr      ResetStatement();
-    
+
     void                BuildWhere(void);
     OGRErr              RegisterGeometryColumn();
-    
+
     public:
-    
                         OGRGeoPackageTableLayer( GDALGeoPackageDataset *poDS,
                                             const char * pszTableName );
                         ~OGRGeoPackageTableLayer();
 
     /************************************************************************/
     /* OGR API methods */
-                        
+
     int                 TestCapability( const char * );
     OGRErr              CreateField( OGRFieldDefn *poField, int bApproxOK = TRUE );
     OGRErr              CreateGeomField( OGRGeomFieldDefn *poGeomFieldIn,
@@ -399,6 +338,9 @@ class OGRGeoPackageTableLayer : public OGRGeoPackageLayer
     OGRErr              ISetFeature( OGRFeature *poFeature );
     OGRErr              DeleteFeature(GIntBig nFID);
     virtual void        SetSpatialFilter( OGRGeometry * );
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+                { OGRGeoPackageLayer::SetSpatialFilter(iGeomField, poGeom); }
+
     OGRErr              SetAttributeFilter( const char *pszQuery );
     OGRErr              SyncToDisk();
     OGRFeature*         GetNextFeature();
@@ -408,8 +350,8 @@ class OGRGeoPackageTableLayer : public OGRGeoPackageLayer
     OGRErr              RollbackTransaction();
     GIntBig             GetFeatureCount( int );
     OGRErr              GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
-    
-    // void                SetSpatialFilter( int iGeomField, OGRGeometry * poGeomIn );
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRGeoPackageLayer::GetExtent(iGeomField, psExtent, bForce); }
 
     OGRErr              ReadTableDefinition(int bIsSpatial);
     void                SetCreationParameters( OGRwkbGeometryType eGType,
@@ -419,12 +361,12 @@ class OGRGeoPackageTableLayer : public OGRGeoPackageLayer
                                                const char* pszFIDColumnName,
                                                const char* pszIdentifier,
                                                const char* pszDescription );
-    void                SetDeferedSpatialIndexCreation( int bFlag )
-                                { bDeferedSpatialIndexCreation = bFlag; }
+    void                SetDeferredSpatialIndexCreation( bool bFlag )
+                                { m_bDeferredSpatialIndexCreation = bFlag; }
 
     void                CreateSpatialIndexIfNecessary();
-    int                 CreateSpatialIndex();
-    int                 DropSpatialIndex(int bCalledFromSQLFunction = FALSE);
+    bool                CreateSpatialIndex();
+    bool                DropSpatialIndex(bool bCalledFromSQLFunction = false);
 
     virtual char **     GetMetadata( const char *pszDomain = NULL );
     virtual const char *GetMetadataItem( const char * pszName,
@@ -443,44 +385,43 @@ class OGRGeoPackageTableLayer : public OGRGeoPackageLayer
     virtual CPLString    GetSpatialWhere(int iGeomCol,
                                          OGRGeometry* poFilterGeom);
 
-    int                 HasSpatialIndex();
+    bool                HasSpatialIndex();
     void                SetPrecisionFlag( int bFlag )
-                                { m_bPreservePrecision = bFlag; }
+                                { m_bPreservePrecision = CPL_TO_BOOL( bFlag ); }
     void                SetTruncateFieldsFlag( int bFlag )
-                                { m_bTruncateFields = bFlag; }
+                                { m_bTruncateFields = CPL_TO_BOOL( bFlag ); }
     OGRErr              RunDeferredCreationIfNecessary();
 
     /************************************************************************/
     /* GPKG methods */
-    
-    private:
-    
+
+  private:
     OGRErr              UpdateExtent( const OGREnvelope *poExtent );
     OGRErr              SaveExtent();
     OGRErr              BuildColumns();
     OGRBoolean          IsGeomFieldSet( OGRFeature *poFeature );
     CPLString           FeatureGenerateUpdateSQL( OGRFeature *poFeature );
-    CPLString           FeatureGenerateInsertSQL( OGRFeature *poFeature, int bAddFID, int bBindNullFields );
+    CPLString           FeatureGenerateInsertSQL( OGRFeature *poFeature, bool bAddFID, bool bBindNullFields );
     OGRErr              FeatureBindUpdateParameters( OGRFeature *poFeature, sqlite3_stmt *poStmt );
-    OGRErr              FeatureBindInsertParameters( OGRFeature *poFeature, sqlite3_stmt *poStmt, int bAddFID, int bBindNullFields );
-    OGRErr              FeatureBindParameters( OGRFeature *poFeature, sqlite3_stmt *poStmt, int *pnColCount, int bAddFID, int bBindNullFields );
+    OGRErr              FeatureBindInsertParameters( OGRFeature *poFeature, sqlite3_stmt *poStmt, bool bAddFID, bool bBindNullFields );
+    OGRErr              FeatureBindParameters( OGRFeature *poFeature, sqlite3_stmt *poStmt, int *pnColCount, bool bAddFID, bool bBindNullFields );
 
     void                CheckUnknownExtensions();
-    int                 CreateGeometryExtensionIfNecessary(OGRwkbGeometryType eGType);
+    bool                CreateGeometryExtensionIfNecessary(OGRwkbGeometryType eGType);
 };
 
 /************************************************************************/
 /*                         OGRGeoPackageSelectLayer                     */
 /************************************************************************/
 
-class OGRGeoPackageSelectLayer : public OGRGeoPackageLayer, public IOGRSQLiteSelectLayer
+class OGRGeoPackageSelectLayer CPL_FINAL : public OGRGeoPackageLayer, public IOGRSQLiteSelectLayer
 {
     OGRSQLiteSelectLayerCommonBehaviour* poBehaviour;
 
     virtual OGRErr      ResetStatement();
 
   public:
-                        OGRGeoPackageSelectLayer( GDALGeoPackageDataset *, 
+                        OGRGeoPackageSelectLayer( GDALGeoPackageDataset *,
                                               CPLString osSQL,
                                               sqlite3_stmt *,
                                               int bUseStatementForGetNextFeature,
@@ -519,4 +460,4 @@ class OGRGeoPackageSelectLayer : public OGRGeoPackageLayer, public IOGRSQLiteSel
 };
 
 
-#endif /* _OGR_GEOPACKAGE_H_INCLUDED */
+#endif /* OGR_GEOPACKAGE_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp b/ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp
index 3838a87..22a1a4e 100644
--- a/ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp
@@ -108,7 +108,7 @@ static const TilingSchemeDefinition asTilingShemes[] =
 /* via a PRAGMA statement, so we have to write directly into the */
 /* file header here. */
 /* We do this at the *end* of initialization so that there is */
-/* data to write down to a file, and we'll have a writeable file */
+/* data to write down to a file, and we will have a writable file */
 /* once we close the SQLite connection */
 OGRErr GDALGeoPackageDataset::SetApplicationId()
 {
@@ -147,52 +147,56 @@ OGRErr GDALGeoPackageDataset::SetApplicationId()
 
 
 /* Returns the first row of first column of SQL as integer */
-OGRErr GDALGeoPackageDataset::PragmaCheck(const char * pszPragma, const char * pszExpected, int nRowsExpected)
+OGRErr GDALGeoPackageDataset::PragmaCheck(
+    const char * pszPragma, const char * pszExpected, int nRowsExpected )
 {
     CPLAssert( pszPragma != NULL );
     CPLAssert( pszExpected != NULL );
     CPLAssert( nRowsExpected >= 0 );
-    
+
+    char **papszResult = NULL;
+    int nRowCount;
+    int nColCount;
     char *pszErrMsg = NULL;
-    int nRowCount, nColCount, rc;
-    char **papszResult;
 
-    rc = sqlite3_get_table(
+    int rc = sqlite3_get_table(
         hDB,
         CPLSPrintf("PRAGMA %s", pszPragma),
         &papszResult, &nRowCount, &nColCount, &pszErrMsg );
-    
+
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "unable to execute PRAGMA %s", pszPragma);
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Unable to execute PRAGMA %s", pszPragma);
         return OGRERR_FAILURE;
     }
-    
+
     if ( nRowCount != nRowsExpected )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "bad result for PRAGMA %s, got %d rows, expected %d", pszPragma, nRowCount, nRowsExpected);
-        return OGRERR_FAILURE;        
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "bad result for PRAGMA %s, got %d rows, expected %d",
+                  pszPragma, nRowCount, nRowsExpected );
+        return OGRERR_FAILURE;
     }
-    
+
     if ( nRowCount > 0 && ! EQUAL(papszResult[1], pszExpected) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, "invalid %s (expected '%s', got '%s')",
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "invalid %s (expected '%s', got '%s')",
                   pszPragma, pszExpected, papszResult[1]);
         return OGRERR_FAILURE;
     }
-    
+
     sqlite3_free_table(papszResult);
-    
-    return OGRERR_NONE; 
+
+    return OGRERR_NONE;
 }
 
 static OGRErr GDALGPKGImportFromEPSG(OGRSpatialReference *poSpatialRef,
                                      int nEPSGCode)
 {
     CPLPushErrorHandler(CPLQuietErrorHandler);
-    OGRErr eErr = poSpatialRef->importFromEPSG(nEPSGCode);
+    const OGRErr eErr = poSpatialRef->importFromEPSG(nEPSGCode);
     CPLPopErrorHandler();
     CPLErrorReset();
     return eErr;
@@ -201,46 +205,51 @@ static OGRErr GDALGPKGImportFromEPSG(OGRSpatialReference *poSpatialRef,
 
 OGRSpatialReference* GDALGeoPackageDataset::GetSpatialRef(int iSrsId)
 {
-    SQLResult oResult;
-    
     /* Should we do something special with undefined SRS ? */
     if( iSrsId == 0 || iSrsId == -1 )
     {
         return NULL;
     }
-    
+
     CPLString oSQL;
-    oSQL.Printf("SELECT definition, organization, organization_coordsys_id FROM gpkg_spatial_ref_sys WHERE srs_id = %d", iSrsId);
-    
+    oSQL.Printf( "SELECT definition, organization, organization_coordsys_id "
+                 "FROM gpkg_spatial_ref_sys WHERE srs_id = %d", iSrsId );
+
+    SQLResult oResult;
     OGRErr err = SQLQuery(hDB, oSQL.c_str(), &oResult);
 
     if ( err != OGRERR_NONE || oResult.nRowCount != 1 )
     {
         SQLResultFree(&oResult);
-        CPLError( CE_Warning, CPLE_AppDefined, "unable to read srs_id '%d' from gpkg_spatial_ref_sys",
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "unable to read srs_id '%d' from gpkg_spatial_ref_sys",
                   iSrsId);
         return NULL;
     }
-    
+
     const char *pszWkt = SQLResultGetValue(&oResult, 0, 0);
     if ( ! pszWkt )
     {
         SQLResultFree(&oResult);
-        CPLError( CE_Warning, CPLE_AppDefined, "null definition for srs_id '%d' in gpkg_spatial_ref_sys",
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "null definition for srs_id '%d' in gpkg_spatial_ref_sys",
                   iSrsId);
         return NULL;
     }
-    
+
     const char* pszOrganization = SQLResultGetValue(&oResult, 1, 0);
     const char* pszOrganizationCoordsysID = SQLResultGetValue(&oResult, 2, 0);
-    
+
     OGRSpatialReference *poSpatialRef = new OGRSpatialReference();
     // Try to import first from EPSG code, and then from WKT
-    if( !(pszOrganization && pszOrganizationCoordsysID && EQUAL(pszOrganization, "EPSG") &&
-          GDALGPKGImportFromEPSG(poSpatialRef, atoi(pszOrganizationCoordsysID)) == OGRERR_NONE) &&
+    if( !(pszOrganization && pszOrganizationCoordsysID
+          && EQUAL(pszOrganization, "EPSG") &&
+          GDALGPKGImportFromEPSG(poSpatialRef, atoi(pszOrganizationCoordsysID))
+          == OGRERR_NONE) &&
         poSpatialRef->SetFromUserInput(pszWkt) != OGRERR_NONE )
     {
-        CPLError( CE_Warning, CPLE_AppDefined, "unable to parse srs_id '%d' well-known text '%s'",
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Unable to parse srs_id '%d' well-known text '%s'",
                 iSrsId, pszWkt);
         SQLResultFree(&oResult);
         delete poSpatialRef;
@@ -251,47 +260,39 @@ OGRSpatialReference* GDALGeoPackageDataset::GetSpatialRef(int iSrsId)
     return poSpatialRef;
 }
 
-const char * GDALGeoPackageDataset::GetSrsName(const OGRSpatialReference * poSRS)
+const char * GDALGeoPackageDataset::GetSrsName(
+    const OGRSpatialReference *poSRS )
 {
-    const OGR_SRSNode *node;
-    
+    const OGR_SRSNode *node = poSRS->GetAttrNode("PROJCS");
+
     /* Projected coordinate system? */
-    if ( (node = poSRS->GetAttrNode("PROJCS")) )
+    if ( node != NULL )
     {
         return node->GetChild(0)->GetValue();
     }
+
     /* Geographic coordinate system? */
-    else if ( (node = poSRS->GetAttrNode("GEOGCS")) )
+    if ( (node = poSRS->GetAttrNode("GEOGCS")) != NULL )
     {
         return node->GetChild(0)->GetValue();
     }
-    /* Something odd! return empty. */
-    else
-    {
-        return "Unnamed SRS";
-    }
+
+    // Something odd.  Return empty.
+    return "Unnamed SRS";
 }
 
 int GDALGeoPackageDataset::GetSrsId(const OGRSpatialReference * cpoSRS)
 {
-    char *pszWKT = NULL;
-    char *pszSQL = NULL;
-    int nSRSId = DEFAULT_SRID;
-    const char* pszAuthorityName;
-    int nAuthorityCode = 0;
-    OGRErr err;
-    OGRBoolean bCanUseAuthorityCode = FALSE;
-
     if( cpoSRS == NULL )
         return DEFAULT_SRID;
 
     OGRSpatialReference *poSRS = cpoSRS->Clone();
 
-    pszAuthorityName = poSRS->GetAuthorityName(NULL);
+    const char* pszAuthorityName = poSRS->GetAuthorityName( NULL );
 
     if ( pszAuthorityName == NULL || strlen(pszAuthorityName) == 0 )
     {
-        // Try to force identify an EPSG code                                    
+        // Try to force identify an EPSG code.
         poSRS->AutoIdentifyEPSG();
 
         pszAuthorityName = poSRS->GetAuthorityName(NULL);
@@ -307,8 +308,14 @@ int GDALGeoPackageDataset::GetSrsId(const OGRSpatialReference * cpoSRS)
             }
         }
     }
+
     // Check whether the EPSG authority code is already mapped to a
-    // SRS ID.                                                         
+    // SRS ID.
+    char *pszSQL = NULL;
+    int nSRSId = DEFAULT_SRID;
+    int nAuthorityCode = 0;
+    OGRErr err = OGRERR_NONE;
+    bool bCanUseAuthorityCode = false;
     if ( pszAuthorityName != NULL && strlen(pszAuthorityName) > 0 )
     {
         // For the root authority name 'EPSG', the authority code
@@ -317,31 +324,33 @@ int GDALGeoPackageDataset::GetSrsId(const OGRSpatialReference * cpoSRS)
 
         pszSQL = sqlite3_mprintf(
                          "SELECT srs_id FROM gpkg_spatial_ref_sys WHERE "
-                         "upper(organization) = upper('%q') AND organization_coordsys_id = %d",
+                         "upper(organization) = upper('%q') AND "
+                         "organization_coordsys_id = %d",
                          pszAuthorityName, nAuthorityCode );
-        
+
         nSRSId = SQLGetInteger(hDB, pszSQL, &err);
         sqlite3_free(pszSQL);
-        
+
         // Got a match? Return it!
         if ( OGRERR_NONE == err )
         {
             delete poSRS;
             return nSRSId;
         }
-        
+
         // No match, but maybe we can use the nAuthorityCode as the nSRSId?
         pszSQL = sqlite3_mprintf(
                          "SELECT Count(*) FROM gpkg_spatial_ref_sys WHERE "
                          "srs_id = %d", nAuthorityCode );
-        
+
         // Yep, we can!
         if ( ! SQLGetInteger(hDB, pszSQL, &err) && err == OGRERR_NONE )
-            bCanUseAuthorityCode = TRUE;
+            bCanUseAuthorityCode = true;
         sqlite3_free(pszSQL);
     }
 
-    // Translate SRS to WKT.                                           
+    // Translate SRS to WKT.
+    char *pszWKT = NULL;
     if( poSRS->exportToWkt( &pszWKT ) != OGRERR_NONE )
     {
         delete poSRS;
@@ -357,46 +366,47 @@ int GDALGeoPackageDataset::GetSrsId(const OGRSpatialReference * cpoSRS)
     // Otherwise, generate a new SRS_ID number (max + 1)
     else
     {
-        // Get the current maximum srid in the srs table.                  
-        int nMaxSRSId = SQLGetInteger(hDB, "SELECT MAX(srs_id) FROM gpkg_spatial_ref_sys", &err);
+        // Get the current maximum srid in the srs table.
+        const int nMaxSRSId
+            = SQLGetInteger(
+                hDB, "SELECT MAX(srs_id) FROM gpkg_spatial_ref_sys", &err );
         if ( OGRERR_NONE != err )
         {
             CPLFree(pszWKT);
             delete poSRS;
-            return DEFAULT_SRID;        
+            return DEFAULT_SRID;
         }
 
         nSRSId = nMaxSRSId + 1;
     }
-    
-    // Add new SRS row to gpkg_spatial_ref_sys
+
+    // Add new SRS row to gpkg_spatial_ref_sys.
     if( pszAuthorityName != NULL && nAuthorityCode > 0 )
     {
         pszSQL = sqlite3_mprintf(
-                 "INSERT INTO gpkg_spatial_ref_sys "
-                 "(srs_name,srs_id,organization,organization_coordsys_id,definition) "
-                 "VALUES ('%q', %d, upper('%q'), %d, '%q')",
-                 GetSrsName(poSRS), nSRSId, pszAuthorityName, nAuthorityCode, pszWKT
-                 );
+            "INSERT INTO gpkg_spatial_ref_sys "
+            "(srs_name,srs_id,organization,organization_coordsys_id,"
+            "definition) VALUES ('%q', %d, upper('%q'), %d, '%q')",
+            GetSrsName(poSRS), nSRSId, pszAuthorityName, nAuthorityCode,
+            pszWKT );
     }
     else
     {
         pszSQL = sqlite3_mprintf(
-                 "INSERT INTO gpkg_spatial_ref_sys "
-                 "(srs_name,srs_id,organization,organization_coordsys_id,definition) "
-                 "VALUES ('%q', %d, upper('%q'), %d, '%q')",
-                 GetSrsName(poSRS), nSRSId, "NONE", nSRSId, pszWKT
-                 );
+            "INSERT INTO gpkg_spatial_ref_sys "
+            "(srs_name,srs_id,organization,organization_coordsys_id,"
+            "definition) VALUES ('%q', %d, upper('%q'), %d, '%q')",
+            GetSrsName(poSRS), nSRSId, "NONE", nSRSId, pszWKT );
     }
 
-    // Add new row to gpkg_spatial_ref_sys
+    // Add new row to gpkg_spatial_ref_sys.
     err = SQLCommand(hDB, pszSQL);
 
     // Free everything that was allocated.
-    CPLFree(pszWKT);    
+    CPLFree(pszWKT);
     sqlite3_free(pszSQL);
     delete poSRS;
-    
+
     return nSRSId;
 }
 
@@ -405,60 +415,32 @@ int GDALGeoPackageDataset::GetSrsId(const OGRSpatialReference * cpoSRS)
 /*                        GDALGeoPackageDataset()                       */
 /************************************************************************/
 
-GDALGeoPackageDataset::GDALGeoPackageDataset()
+GDALGeoPackageDataset::GDALGeoPackageDataset() :
+    m_papoLayers(NULL),
+    m_nLayers(0),
+    m_bUtf8(false),
+    m_bIdentifierAsCO(false),
+    m_bDescriptionAsCO(false),
+    m_bHasReadMetadataFromStorage(false),
+    m_bMetadataDirty(false),
+    m_papszSubDatasets(NULL),
+    m_pszProjection(NULL),
+    m_bRecordInsertedInGPKGContent(false),
+    m_bGeoTransformValid(false),
+    m_nSRID(-1),  // Unknown cartesian.
+    m_dfTMSMinX(0.0),
+    m_dfTMSMaxY(0.0),
+    m_nOverviewCount(0),
+    m_papoOverviewDS(NULL),
+    m_bZoomOther(false),
+    m_bInFlushCache(false)
 {
-    m_bNew = FALSE;
-    m_papoLayers = NULL;
-    m_nLayers = 0;
-    m_bUtf8 = FALSE;
-    m_bIdentifierAsCO = FALSE;
-    m_bDescriptionAsCO = FALSE;
-    m_bHasReadMetadataFromStorage = FALSE;
-    m_bMetadataDirty = FALSE;
-    m_papszSubDatasets = NULL;
-    m_pszProjection = NULL;
-    m_bRecordInsertedInGPKGContent = FALSE;
-    m_bGeoTransformValid = FALSE;
-    m_nSRID = -1; /* unknown cartesian */
     m_adfGeoTransform[0] = 0.0;
     m_adfGeoTransform[1] = 1.0;
     m_adfGeoTransform[2] = 0.0;
     m_adfGeoTransform[3] = 0.0;
     m_adfGeoTransform[4] = 0.0;
     m_adfGeoTransform[5] = 1.0;
-    m_nZoomLevel = -1;
-    m_pabyCachedTiles = NULL;
-    for(int i=0;i<4;i++)
-    {
-        m_asCachedTilesDesc[i].nRow = -1;
-        m_asCachedTilesDesc[i].nCol = -1;
-        m_asCachedTilesDesc[i].nIdxWithinTileData = -1;
-        m_asCachedTilesDesc[i].abBandDirty[0] = FALSE;
-        m_asCachedTilesDesc[i].abBandDirty[1] = FALSE;
-        m_asCachedTilesDesc[i].abBandDirty[2] = FALSE;
-        m_asCachedTilesDesc[i].abBandDirty[3] = FALSE;
-    }
-    m_nShiftXTiles = 0;
-    m_nShiftXPixelsMod = 0;
-    m_nShiftYTiles = 0;
-    m_nShiftYPixelsMod = 0;
-    m_eTF = GPKG_TF_PNG_JPEG;
-    m_nTileMatrixWidth = 0;
-    m_nTileMatrixHeight = 0;
-    m_nZLevel = 6;
-    m_nQuality = 75;
-    m_bDither = FALSE;
-    m_poParentDS = NULL;
-    m_nOverviewCount = 0;
-    m_papoOverviewDS = NULL;
-    m_bZoomOther = FALSE;
-    m_bTriedEstablishingCT = FALSE;
-    m_pabyHugeColorArray = NULL;
-    m_poCT = NULL;
-    m_bInWriteTile = FALSE;
-    m_hTempDB = NULL;
-    m_bInFlushCache = FALSE;
-    m_nTileInsertionCount = 0;
     m_osTilingScheme = "CUSTOM";
 }
 
@@ -468,19 +450,17 @@ GDALGeoPackageDataset::GDALGeoPackageDataset()
 
 GDALGeoPackageDataset::~GDALGeoPackageDataset()
 {
-    int i;
-    
     SetPamFlags(0);
 
     if( m_poParentDS == NULL && m_osRasterTable.size() &&
         !m_bGeoTransformValid )
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Raster table %s not correctly initialized due to missing call "
-                 "to SetGeoTransform()",
-                 m_osRasterTable.c_str());
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Raster table %s not correctly initialized due to missing "
+                  "call to SetGeoTransform()",
+                  m_osRasterTable.c_str());
     }
-    
+
     FlushCache();
     FlushMetadata();
 
@@ -493,23 +473,36 @@ GDALGeoPackageDataset::~GDALGeoPackageDataset()
     {
         hDB = NULL;
     }
-    else if( m_hTempDB != NULL )
-    {
-        sqlite3_close(m_hTempDB);
-        m_hTempDB = NULL;
-        VSIUnlink(m_osTempDBFilename);
-    }
 
-    for( i = 0; i < m_nLayers; i++ )
+    for( int i = 0; i < m_nLayers; i++ )
         delete m_papoLayers[i];
 
     CPLFree( m_papoLayers );
     CPLFree( m_papoOverviewDS );
     CSLDestroy( m_papszSubDatasets );
     CPLFree(m_pszProjection);
-    CPLFree(m_pabyCachedTiles);
-    delete m_poCT;
-    CPLFree(m_pabyHugeColorArray);
+}
+
+/************************************************************************/
+/*                         ICanIWriteBlock()                            */
+/************************************************************************/
+
+bool GDALGeoPackageDataset::ICanIWriteBlock()
+{
+    if( !bUpdate )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "IWriteBlock() not supported on dataset opened in read-only mode");
+        return false;
+    }
+
+    if( !m_bGeoTransformValid || m_nSRID == UNKNOWN_SRID )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "IWriteBlock() not supported if georeferencing not set");
+        return false;
+    }
+    return true;
 }
 
 /************************************************************************/
@@ -518,16 +511,15 @@ GDALGeoPackageDataset::~GDALGeoPackageDataset()
 
 int GDALGeoPackageDataset::Open( GDALOpenInfo* poOpenInfo )
 {
-    int i;
     OGRErr err;
 
     CPLAssert( m_nLayers == 0 );
     CPLAssert( hDB == NULL );
-    
+
     SetDescription( poOpenInfo->pszFilename );
     CPLString osFilename( poOpenInfo->pszFilename );
     CPLString osSubdatasetTableName;
-    if( EQUALN(poOpenInfo->pszFilename, "GPKG:", 5) )
+    if( STARTS_WITH_CI(poOpenInfo->pszFilename, "GPKG:") )
     {
         char** papszTokens = CSLTokenizeString2(poOpenInfo->pszFilename, ":", 0);
         if( CSLCount(papszTokens) != 3 )
@@ -553,32 +545,33 @@ int GDALGeoPackageDataset::Open( GDALOpenInfo* poOpenInfo )
     /* Requirement 6: The SQLite PRAGMA integrity_check SQL command SHALL return “ok” */
     /* http://opengis.github.io/geopackage/#_file_integrity */
     /* Disable integrity check by default, since it is expensive on big files */
-    if( CSLTestBoolean(CPLGetConfigOption("OGR_GPKG_INTEGRITY_CHECK", "NO")) &&
+    if( CPLTestBool(CPLGetConfigOption("OGR_GPKG_INTEGRITY_CHECK", "NO")) &&
         OGRERR_NONE != PragmaCheck("integrity_check", "ok", 1) )
     {
         CPLError( CE_Failure, CPLE_AppDefined, "pragma integrity_check on '%s' failed",
                   m_pszFilename);
         return FALSE;
     }
-    
+
     /* Requirement 7: The SQLite PRAGMA foreign_key_check() SQL with no */
     /* parameter value SHALL return an empty result set */
     /* http://opengis.github.io/geopackage/#_file_integrity */
-    if ( OGRERR_NONE != PragmaCheck("foreign_key_check", "", 0) ) 
+    if ( OGRERR_NONE != PragmaCheck("foreign_key_check", "", 0) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, "pragma foreign_key_check on '%s' failed",
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "pragma foreign_key_check on '%s' failed",
                   m_pszFilename);
-        return FALSE; 
+        return FALSE;
     }
 
     /* OGR UTF-8 capability, we'll advertise UTF-8 support if we have it */
-    if ( OGRERR_NONE == PragmaCheck("encoding", "UTF-8", 1) ) 
+    if ( OGRERR_NONE == PragmaCheck("encoding", "UTF-8", 1) )
     {
-        m_bUtf8 = TRUE;
+        m_bUtf8 = true;
     }
     else
     {
-        m_bUtf8 = FALSE;
+        m_bUtf8 = false;
     }
 
     /* Check for requirement metadata tables */
@@ -588,24 +581,26 @@ int GDALGeoPackageDataset::Open( GDALOpenInfo* poOpenInfo )
         "gpkg_spatial_ref_sys",
         "gpkg_contents"
     };
-    
-    for ( i = 0; i < (int)(sizeof(aosGpkgTables) / sizeof(aosGpkgTables[0])); i++ )
+
+    for ( int i = 0;
+          i < (int)(sizeof(aosGpkgTables) / sizeof(aosGpkgTables[0]));
+          i++ )
     {
         SQLResult oResult;
         char *pszSQL = sqlite3_mprintf("pragma table_info('%q')", aosGpkgTables[i].c_str());
         err = SQLQuery(hDB, pszSQL, &oResult);
         sqlite3_free(pszSQL);
-        
+
         if  ( err != OGRERR_NONE )
             return FALSE;
-            
+
         if ( oResult.nRowCount <= 0 )
         {
             CPLError( CE_Failure, CPLE_AppDefined, "required GeoPackage table '%s' is missing", aosGpkgTables[i].c_str());
             SQLResultFree(&oResult);
             return FALSE;
         }
-        
+
         SQLResultFree(&oResult);
     }
 
@@ -649,12 +644,12 @@ int GDALGeoPackageDataset::Open( GDALOpenInfo* poOpenInfo )
         {
             m_papoLayers = (OGRGeoPackageTableLayer**)CPLMalloc(sizeof(OGRGeoPackageTableLayer*) * oResult.nRowCount);
 
-            for ( i = 0; i < oResult.nRowCount; i++ )
+            for ( int i = 0; i < oResult.nRowCount; i++ )
             {
                 const char *pszTableName = SQLResultGetValue(&oResult, 0, i);
                 if ( ! pszTableName )
                 {
-                    CPLError(CE_Warning, CPLE_AppDefined, "unable to read table name for layer(%d)", i);            
+                    CPLError(CE_Warning, CPLE_AppDefined, "unable to read table name for layer(%d)", i);
                     continue;
                 }
                 int bIsSpatial = SQLResultGetValueAsInteger(&oResult, 2, i);
@@ -662,7 +657,7 @@ int GDALGeoPackageDataset::Open( GDALOpenInfo* poOpenInfo )
                 if( OGRERR_NONE != poLayer->ReadTableDefinition(bIsSpatial) )
                 {
                     delete poLayer;
-                    CPLError(CE_Warning, CPLE_AppDefined, "unable to read table definition for '%s'", pszTableName);            
+                    CPLError(CE_Warning, CPLE_AppDefined, "unable to read table definition for '%s'", pszTableName);
                     continue;
                 }
                 m_papoLayers[m_nLayers++] = poLayer;
@@ -672,7 +667,7 @@ int GDALGeoPackageDataset::Open( GDALOpenInfo* poOpenInfo )
         SQLResultFree(&oResult);
         bRet = TRUE;
     }
-    
+
     int bHasTileMatrixSet = FALSE;
     if( poOpenInfo->nOpenFlags & GDAL_OF_RASTER )
     {
@@ -738,9 +733,9 @@ int GDALGeoPackageDataset::Open( GDALOpenInfo* poOpenInfo )
         else if( oResult.nRowCount >= 1 )
         {
             bRet = TRUE;
-            
+
             int nSDSCount = 0;
-            for ( i = 0; i < oResult.nRowCount; i++ )
+            for ( int i = 0; i < oResult.nRowCount; i++ )
             {
                 const char *pszTableName = SQLResultGetValue(&oResult, 0, i);
                 const char *pszIdentifier = SQLResultGetValue(&oResult, 1, i);
@@ -782,7 +777,7 @@ int GDALGeoPackageDataset::InitRaster ( GDALGeoPackageDataset* poParentDS,
                                         const char* pszContentsMinY,
                                         const char* pszContentsMaxX,
                                         const char* pszContentsMaxY,
-                                        char** papszOpenOptions,
+                                        char** papszOpenOptionsIn,
                                         const SQLResult& oResult,
                                         int nIdxInResult )
 {
@@ -803,10 +798,10 @@ int GDALGeoPackageDataset::InitRaster ( GDALGeoPackageDataset* poParentDS,
     double dfGDALMinY = dfMinY;
     double dfGDALMaxX = dfMaxX;
     double dfGDALMaxY = dfMaxY;
-    pszContentsMinX = CSLFetchNameValueDef(papszOpenOptions, "MINX", pszContentsMinX);
-    pszContentsMinY = CSLFetchNameValueDef(papszOpenOptions, "MINY", pszContentsMinY);
-    pszContentsMaxX = CSLFetchNameValueDef(papszOpenOptions, "MAXX", pszContentsMaxX);
-    pszContentsMaxY = CSLFetchNameValueDef(papszOpenOptions, "MAXY", pszContentsMaxY);
+    pszContentsMinX = CSLFetchNameValueDef(papszOpenOptionsIn, "MINX", pszContentsMinX);
+    pszContentsMinY = CSLFetchNameValueDef(papszOpenOptionsIn, "MINY", pszContentsMinY);
+    pszContentsMaxX = CSLFetchNameValueDef(papszOpenOptionsIn, "MAXX", pszContentsMaxX);
+    pszContentsMaxY = CSLFetchNameValueDef(papszOpenOptionsIn, "MAXY", pszContentsMaxY);
     if( pszContentsMinX != NULL && pszContentsMinY != NULL &&
         pszContentsMaxX != NULL && pszContentsMaxY != NULL )
     {
@@ -820,7 +815,7 @@ int GDALGeoPackageDataset::InitRaster ( GDALGeoPackageDataset* poParentDS,
         return FALSE;
     }
 
-    int nBandCount = atoi(CSLFetchNameValueDef(papszOpenOptions, "BAND_COUNT", "4"));
+    int nBandCount = atoi(CSLFetchNameValueDef(papszOpenOptionsIn, "BAND_COUNT", "4"));
     if( nBandCount != 1 && nBandCount != 2 && nBandCount != 3 && nBandCount != 4 )
         nBandCount = 4;
 
@@ -877,7 +872,7 @@ int GDALGeoPackageDataset::InitRaster ( GDALGeoPackageDataset* poParentDS,
     m_nTileMatrixWidth = nTileMatrixWidth;
     m_nTileMatrixHeight = nTileMatrixHeight;
 
-    m_bGeoTransformValid = TRUE;
+    m_bGeoTransformValid = true;
     m_adfGeoTransform[0] = dfGDALMinX;
     m_adfGeoTransform[1] = dfPixelXSize;
     m_adfGeoTransform[3] = dfGDALMaxY;
@@ -889,14 +884,14 @@ int GDALGeoPackageDataset::InitRaster ( GDALGeoPackageDataset* poParentDS,
     nRasterXSize = (int)dfRasterXSize;
     nRasterYSize = (int)dfRasterYSize;
 
-    m_pabyCachedTiles = (GByte*) VSIMalloc3(4 * 4, nTileWidth, nTileHeight);
+    m_pabyCachedTiles = (GByte*) VSI_MALLOC3_VERBOSE(4 * 4, nTileWidth, nTileHeight);
     if( m_pabyCachedTiles == NULL )
     {
         return FALSE;
     }
 
     for(int i = 1; i <= nBandCount; i ++)
-        SetBand( i, new GDALGeoPackageRasterBand(this, i, nTileWidth, nTileHeight) );
+        SetBand( i, new GDALGeoPackageRasterBand(this, nTileWidth, nTileHeight) );
 
     ComputeTileAndPixelShifts();
 
@@ -923,10 +918,10 @@ int GDALGeoPackageDataset::InitRaster ( GDALGeoPackageDataset* poParentDS,
 }
 
 /************************************************************************/
-/*                         GetTileFormat()                              */
+/*                 GDALGPKGMBTilesGetTileFormat()                       */
 /************************************************************************/
 
-static GPKGTileFormat GetTileFormat(const char* pszTF )
+GPKGTileFormat GDALGPKGMBTilesGetTileFormat(const char* pszTF )
 {
     GPKGTileFormat eTF = GPKG_TF_PNG_JPEG;
     if( pszTF )
@@ -961,7 +956,7 @@ int GDALGeoPackageDataset::OpenRaster( const char* pszTableName,
                                        const char* pszContentsMinY,
                                        const char* pszContentsMaxX,
                                        const char* pszContentsMaxY,
-                                       char** papszOpenOptions )
+                                       char** papszOpenOptionsIn )
 {
     OGRErr err;
     SQLResult oResult;
@@ -969,7 +964,7 @@ int GDALGeoPackageDataset::OpenRaster( const char* pszTableName,
     if( dfMinX >= dfMaxX || dfMinY >= dfMaxY )
         return FALSE;
 
-    m_bRecordInsertedInGPKGContent = TRUE;
+    m_bRecordInsertedInGPKGContent = true;
     m_nSRID = nSRSId;
     if( nSRSId > 0 )
     {
@@ -992,7 +987,7 @@ int GDALGeoPackageDataset::OpenRaster( const char* pszTableName,
             "AND pixel_y_size > 0 AND tile_width > 0 AND tile_height > 0 AND matrix_width > 0 AND matrix_height > 0",
             osQuotedTableName.c_str());
     CPLString osSQL(pszSQL);
-    const char* pszZoomLevel =  CSLFetchNameValue(papszOpenOptions, "ZOOM_LEVEL");
+    const char* pszZoomLevel =  CSLFetchNameValue(papszOpenOptionsIn, "ZOOM_LEVEL");
     if( pszZoomLevel )
     {
         if( bUpdate )
@@ -1040,7 +1035,7 @@ int GDALGeoPackageDataset::OpenRaster( const char* pszTableName,
     // If USE_TILE_EXTENT=YES, then query the tile table to find which tiles
     // actually exist.
     CPLString osContentsMinX, osContentsMinY, osContentsMaxX, osContentsMaxY;
-    if( CSLTestBoolean(CSLFetchNameValueDef(papszOpenOptions, "USE_TILE_EXTENT", "NO")) )
+    if( CPLTestBool(CSLFetchNameValueDef(papszOpenOptionsIn, "USE_TILE_EXTENT", "NO")) )
     {
         pszSQL = sqlite3_mprintf(
             "SELECT MIN(tile_column), MIN(tile_row), MAX(tile_column), MAX(tile_row) FROM '%q' WHERE zoom_level = %d",
@@ -1068,20 +1063,20 @@ int GDALGeoPackageDataset::OpenRaster( const char* pszTableName,
         pszContentsMaxY = osContentsMaxY.c_str();
         SQLResultFree(&oResult2);
     }
-    
+
     if(! InitRaster ( NULL, pszTableName, dfMinX, dfMinY, dfMaxX, dfMaxY,
                  pszContentsMinX, pszContentsMinY, pszContentsMaxX, pszContentsMaxY,
-                 papszOpenOptions, oResult, 0) )
+                 papszOpenOptionsIn, oResult, 0) )
     {
         SQLResultFree(&oResult);
         return FALSE;
     }
 
-    CheckUnknownExtensions(TRUE);
+    CheckUnknownExtensions(true);
 
     // Do this after CheckUnknownExtensions() so that m_eTF is set to GPKG_TF_WEBP
     // if the table already registers the gpkg_webp extension
-    const char* pszTF = CSLFetchNameValue(papszOpenOptions, "TILE_FORMAT");
+    const char* pszTF = CSLFetchNameValue(papszOpenOptionsIn, "TILE_FORMAT");
     if( pszTF )
     {
         if( !bUpdate )
@@ -1091,7 +1086,7 @@ int GDALGeoPackageDataset::OpenRaster( const char* pszTableName,
         }
         else
         {
-            GPKGTileFormat eTF = GetTileFormat(pszTF);
+            GPKGTileFormat eTF = GDALGPKGMBTilesGetTileFormat(pszTF);
             if( eTF == GPKG_TF_WEBP && m_eTF != eTF )
             {
                 if( !RegisterWebPExtension() )
@@ -1101,9 +1096,9 @@ int GDALGeoPackageDataset::OpenRaster( const char* pszTableName,
         }
     }
 
-    ParseCompressionOptions(papszOpenOptions);
+    ParseCompressionOptions(papszOpenOptionsIn);
 
-    m_osWHERE = CSLFetchNameValueDef(papszOpenOptions, "WHERE", "");
+    m_osWHERE = CSLFetchNameValueDef(papszOpenOptionsIn, "WHERE", "");
 
     // Set metadata
     if( pszIdentifier && pszIdentifier[0] )
@@ -1117,7 +1112,7 @@ int GDALGeoPackageDataset::OpenRaster( const char* pszTableName,
         GDALGeoPackageDataset* poOvrDS = new GDALGeoPackageDataset();
         poOvrDS->InitRaster ( this, pszTableName, dfMinX, dfMinY, dfMaxX, dfMaxY,
                  pszContentsMinX, pszContentsMinY, pszContentsMaxX, pszContentsMaxY,
-                 papszOpenOptions, oResult, i);
+                 papszOpenOptionsIn, oResult, i);
 
         m_papoOverviewDS = (GDALGeoPackageDataset**) CPLRealloc(m_papoOverviewDS,
                         sizeof(GDALGeoPackageDataset*) * (m_nOverviewCount+1));
@@ -1295,7 +1290,7 @@ CPLErr GDALGeoPackageDataset::SetGeoTransform( double* padfGeoTransform )
     }
 
     memcpy(m_adfGeoTransform, padfGeoTransform, 6 * sizeof(double));
-    m_bGeoTransformValid = TRUE;
+    m_bGeoTransformValid = true;
 
     return FinalizeRasterRegistration();
 }
@@ -1324,7 +1319,7 @@ CPLErr GDALGeoPackageDataset::FinalizeRasterRegistration()
             (nRasterYSize >> m_nZoomLevel) > nTileHeight )
             m_nZoomLevel ++;
     }
-    
+
     double dfPixelXSizeZoomLevel0 = m_adfGeoTransform[1] * (1 << m_nZoomLevel);
     double dfPixelYSizeZoomLevel0 = fabs(m_adfGeoTransform[5]) * (1 << m_nZoomLevel);
     int nTileXCountZoomLevel0 = ((nRasterXSize >> m_nZoomLevel) + nTileWidth - 1) / nTileWidth;
@@ -1429,11 +1424,11 @@ CPLErr GDALGeoPackageDataset::FinalizeRasterRegistration()
             m_papoOverviewDS[m_nZoomLevel-1-i] = poOvrDS;
         }
     }
-    
+
     SoftCommitTransaction();
 
     m_nOverviewCount = m_nZoomLevel;
-    m_bRecordInsertedInGPKGContent = TRUE;
+    m_bRecordInsertedInGPKGContent = true;
 
     return CE_None;
 }
@@ -1444,45 +1439,27 @@ CPLErr GDALGeoPackageDataset::FinalizeRasterRegistration()
 
 void GDALGeoPackageDataset::FlushCache()
 {
-    FlushCacheWithErrCode();
+    IFlushCacheWithErrCode();
 }
 
-CPLErr GDALGeoPackageDataset::FlushCacheWithErrCode()
+CPLErr GDALGeoPackageDataset::IFlushCacheWithErrCode()
 
 {
     if( m_bInFlushCache )
         return CE_None;
-    m_bInFlushCache = TRUE;
+    m_bInFlushCache = true;
     // Short circuit GDALPamDataset to avoid serialization to .aux.xml
     GDALDataset::FlushCache();
-    
+
     for( int i = 0; i < m_nLayers; i++ )
     {
         m_papoLayers[i]->RunDeferredCreationIfNecessary();
         m_papoLayers[i]->CreateSpatialIndexIfNecessary();
     }
 
-    CPLErr eErr = CE_None;
-    if( bUpdate )
-    {
-        if( m_nShiftXPixelsMod || m_nShiftYPixelsMod )
-        {
-            eErr = FlushRemainingShiftedTiles();
-        }
-        else
-        {
-            eErr = WriteTile();
-        }
-    }
-
-    GDALGeoPackageDataset* poMainDS = m_poParentDS ? m_poParentDS : this;
-    if( poMainDS->m_nTileInsertionCount )
-    {
-        poMainDS->SoftCommitTransaction();
-        poMainDS->m_nTileInsertionCount = 0;
-    }
+    CPLErr eErr = FlushTiles();
 
-    m_bInFlushCache = FALSE;
+    m_bInFlushCache = false;
     return eErr;
 }
 
@@ -1500,8 +1477,8 @@ static int GetFloorPowerOfTwo(int n)
     return p2;
 }
 
-CPLErr GDALGeoPackageDataset::IBuildOverviews( 
-                        const char * pszResampling, 
+CPLErr GDALGeoPackageDataset::IBuildOverviews(
+                        const char * pszResampling,
                         int nOverviews, int * panOverviewList,
                         int nBandsIn, CPL_UNUSED int * panBandList,
                         GDALProgressFunc pfnProgress, void * pProgressData )
@@ -1518,7 +1495,7 @@ CPLErr GDALGeoPackageDataset::IBuildOverviews(
                  "Overview building not supported on overview dataset");
         return CE_Failure;
     }
-    
+
     if( nOverviews == 0 )
     {
         for(int i=0;i<m_nOverviewCount;i++)
@@ -1538,7 +1515,7 @@ CPLErr GDALGeoPackageDataset::IBuildOverviews(
         }
         return CE_None;
     }
-    
+
     if( nBandsIn != nBands )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
@@ -1571,11 +1548,11 @@ CPLErr GDALGeoPackageDataset::IBuildOverviews(
 
             GDALDataset* poODS = m_papoOverviewDS[j];
 
-            nOvFactor = (int) 
+            nOvFactor = (int)
                 (0.5 + GetRasterXSize() / (double) poODS->GetRasterXSize());
             nMaxOvFactor = nOvFactor;
 
-            if( nOvFactor == panOverviewList[i] 
+            if( nOvFactor == panOverviewList[i]
                 || nOvFactor == GDALOvLevelAdjust2( panOverviewList[i],
                                                     GetRasterXSize(),
                                                     GetRasterYSize() ) )
@@ -1591,7 +1568,7 @@ CPLErr GDALGeoPackageDataset::IBuildOverviews(
         if( !bFound )
         {
             /* Mostly for debug */
-            if( !CSLTestBoolean(CPLGetConfigOption("ALLOW_GPKG_ZOOM_OTHER_EXTENSION", "YES")) )
+            if( !CPLTestBool(CPLGetConfigOption("ALLOW_GPKG_ZOOM_OTHER_EXTENSION", "YES")) )
             {
                 CPLString osOvrList;
                 for(int j=0;j<m_nOverviewCount;j++)
@@ -1601,7 +1578,7 @@ CPLErr GDALGeoPackageDataset::IBuildOverviews(
                     GDALDataset* poODS = m_papoOverviewDS[j];
 
                     /* Compute overview factor */
-                    nOvFactor = (int) 
+                    nOvFactor = (int)
                         (0.5 + GetRasterXSize() / (double) poODS->GetRasterXSize());
                     int nODSXSize = (int)(0.5 + GetRasterXSize() / (double) nOvFactor);
                     if( nODSXSize != poODS->GetRasterXSize() )
@@ -1648,7 +1625,7 @@ CPLErr GDALGeoPackageDataset::IBuildOverviews(
                             "Use of overview factor %d cause gpkg_zoom_other extension to be needed",
                             nOvFactor);
                     RegisterZoomOtherExtension();
-                    m_bZoomOther = TRUE;
+                    m_bZoomOther = true;
                 }
 
                 SoftStartTransaction();
@@ -1739,7 +1716,7 @@ CPLErr GDALGeoPackageDataset::IBuildOverviews(
             }
         }
     }
-    
+
     GDALRasterBand*** papapoOverviewBands = (GDALRasterBand ***) CPLCalloc(sizeof(void*),nBands);
     for( int iBand = 0; iBand < nBands; iBand++ )
     {
@@ -1758,7 +1735,7 @@ CPLErr GDALGeoPackageDataset::IBuildOverviews(
                                                 poODS->GetRasterYSize(),
                                                 GetRasterYSize());
 
-                if( nOvFactor == panOverviewList[i] 
+                if( nOvFactor == panOverviewList[i]
                     || nOvFactor == GDALOvLevelAdjust2( panOverviewList[i],
                                                         GetRasterXSize(),
                                                         GetRasterYSize() ) )
@@ -1845,7 +1822,7 @@ char **GDALGeoPackageDataset::GetMetadata( const char *pszDomain )
     if( m_bHasReadMetadataFromStorage )
         return GDALPamDataset::GetMetadata( pszDomain );
 
-    m_bHasReadMetadataFromStorage = TRUE;
+    m_bHasReadMetadataFromStorage = true;
 
     if ( !HasMetadataTables() )
         return GDALPamDataset::GetMetadata( pszDomain );
@@ -1970,7 +1947,7 @@ char **GDALGeoPackageDataset::GetMetadata( const char *pszDomain )
 /*                            WriteMetadata()                           */
 /************************************************************************/
 
-void GDALGeoPackageDataset::WriteMetadata(CPLXMLNode* psXMLNode, /* will be destroyed by the method /*/
+void GDALGeoPackageDataset::WriteMetadata(CPLXMLNode* psXMLNode, /* will be destroyed by the method */
                                           const char* pszTableName)
 {
     int bIsEmpty = (psXMLNode == NULL);
@@ -2074,8 +2051,8 @@ void GDALGeoPackageDataset::WriteMetadata(CPLXMLNode* psXMLNode, /* will be dest
 
 int GDALGeoPackageDataset::CreateMetadataTables()
 {
-    int bCreateTriggers = CSLTestBoolean(CPLGetConfigOption("CREATE_TRIGGERS", "YES"));
-    
+    int bCreateTriggers = CPLTestBool(CPLGetConfigOption("CREATE_TRIGGERS", "YES"));
+
     /* From C.10. gpkg_metadata Table 35. gpkg_metadata Table Definition SQL  */
     const char* pszMetadata =
         "CREATE TABLE gpkg_metadata ("
@@ -2085,7 +2062,7 @@ int GDALGeoPackageDataset::CreateMetadataTables()
         "mime_type TEXT NOT NULL DEFAULT 'text/xml',"
         "metadata TEXT NOT NULL"
         ")";
-        
+
     if ( OGRERR_NONE != SQLCommand(hDB, pszMetadata) )
         return FALSE;
 
@@ -2137,7 +2114,7 @@ int GDALGeoPackageDataset::CreateMetadataTables()
         "CONSTRAINT crmr_mfi_fk FOREIGN KEY (md_file_id) REFERENCES gpkg_metadata(id),"
         "CONSTRAINT crmr_mpi_fk FOREIGN KEY (md_parent_id) REFERENCES gpkg_metadata(id)"
         ")";
-        
+
     if ( OGRERR_NONE != SQLCommand(hDB, pszMetadataReference) )
         return FALSE;
 
@@ -2156,7 +2133,7 @@ int GDALGeoPackageDataset::CreateMetadataTables()
         "BEFORE UPDATE OF 'reference_scope' ON 'gpkg_metadata_reference' "
         "FOR EACH ROW BEGIN "
         "SELECT RAISE(ABORT, 'update on table gpkg_metadata_reference "
-        "violates constraint: referrence_scope must be one of \"geopackage\", "
+        "violates constraint: reference_scope must be one of \"geopackage\", "
         "\"table\", \"column\", \"row\", \"row/col\"') "
         "WHERE NOT NEW.reference_scope IN "
         "('geopackage','table','column','row','row/col'); "
@@ -2260,11 +2237,11 @@ int GDALGeoPackageDataset::CreateMetadataTables()
 CPLErr GDALGeoPackageDataset::FlushMetadata()
 {
     if( !m_bMetadataDirty || m_poParentDS != NULL ||
-        !CSLTestBoolean(CPLGetConfigOption("CREATE_METADATA_TABLES", "YES")) )
+        !CPLTestBool(CPLGetConfigOption("CREATE_METADATA_TABLES", "YES")) )
         return CE_None;
     if( !HasMetadataTables() && !CreateMetadataTables() )
         return CE_Failure;
-    m_bMetadataDirty = FALSE;
+    m_bMetadataDirty = false;
 
     if( m_osRasterTable.size() )
     {
@@ -2295,13 +2272,13 @@ CPLErr GDALGeoPackageDataset::FlushMetadata()
     char** papszMDDup = NULL;
     for( char** papszIter = GetMetadata(); papszIter && *papszIter; ++papszIter )
     {
-        if( EQUALN(*papszIter, "IDENTIFIER=", strlen("IDENTIFIER=")) )
+        if( STARTS_WITH_CI(*papszIter, "IDENTIFIER=") )
             continue;
-        if( EQUALN(*papszIter, "DESCRIPTION=", strlen("DESCRIPTION=")) )
+        if( STARTS_WITH_CI(*papszIter, "DESCRIPTION=") )
             continue;
-        if( EQUALN(*papszIter, "ZOOM_LEVEL=", strlen("ZOOM_LEVEL=")) )
+        if( STARTS_WITH_CI(*papszIter, "ZOOM_LEVEL=") )
             continue;
-        if( EQUALN(*papszIter, "GPKG_METADATA_ITEM_", strlen("GPKG_METADATA_ITEM_")) )
+        if( STARTS_WITH_CI(*papszIter, "GPKG_METADATA_ITEM_") )
             continue;
         papszMDDup = CSLInsertString(papszMDDup, -1, *papszIter);
     }
@@ -2314,8 +2291,8 @@ CPLErr GDALGeoPackageDataset::FlushMetadata()
         oLocalMDMD.SetMetadata(papszMDDup);
         while( papszIter && *papszIter )
         {
-            if( !EQUAL(*papszIter, "") && 
-                !EQUAL(*papszIter, "IMAGE_STRUCTURE") && 
+            if( !EQUAL(*papszIter, "") &&
+                !EQUAL(*papszIter, "IMAGE_STRUCTURE") &&
                 !EQUAL(*papszIter, "GEOPACKAGE") )
                 oLocalMDMD.SetMetadata(oMDMD.GetMetadata(*papszIter), *papszIter);
             papszIter ++;
@@ -2332,7 +2309,7 @@ CPLErr GDALGeoPackageDataset::FlushMetadata()
     {
         char** papszGeopackageMD = GetMetadata("GEOPACKAGE");
 
-        char** papszMDDup = NULL;
+        papszMDDup = NULL;
         for( char** papszIter = papszGeopackageMD; papszIter && *papszIter; ++papszIter )
         {
             papszMDDup = CSLInsertString(papszMDDup, -1, *papszIter);
@@ -2368,19 +2345,18 @@ CPLErr GDALGeoPackageDataset::FlushMetadata()
             sqlite3_free(pszSQL);
         }
 
-        char** papszMDDup = NULL;
+        papszMDDup = NULL;
         for( char** papszIter = m_papoLayers[i]->GetMetadata(); papszIter && *papszIter; ++papszIter )
         {
-            if( EQUALN(*papszIter, "IDENTIFIER=", strlen("IDENTIFIER=")) )
+            if( STARTS_WITH_CI(*papszIter, "IDENTIFIER=") )
                 continue;
-            if( EQUALN(*papszIter, "DESCRIPTION=", strlen("DESCRIPTION=")) )
+            if( STARTS_WITH_CI(*papszIter, "DESCRIPTION=") )
                 continue;
-            if( EQUALN(*papszIter, "OLMD_FID64=", strlen("OLMD_FID64=")) )
+            if( STARTS_WITH_CI(*papszIter, "OLMD_FID64=") )
                 continue;
             papszMDDup = CSLInsertString(papszMDDup, -1, *papszIter);
         }
 
-        CPLXMLNode* psXMLNode;
         {
             GDALMultiDomainMetadata oLocalMDMD;
             char** papszDomainList = m_papoLayers[i]->GetMetadataDomainList();
@@ -2423,7 +2399,7 @@ const char *GDALGeoPackageDataset::GetMetadataItem( const char * pszName,
 CPLErr GDALGeoPackageDataset::SetMetadata( char ** papszMetadata, const char * pszDomain )
 {
     pszDomain = CheckMetadataDomain(pszDomain);
-    m_bMetadataDirty = TRUE;
+    m_bMetadataDirty = true;
     GetMetadata(); /* force loading from storage if needed */
     return GDALPamDataset::SetMetadata(papszMetadata, pszDomain);
 }
@@ -2437,7 +2413,7 @@ CPLErr GDALGeoPackageDataset::SetMetadataItem( const char * pszName,
                                                const char * pszDomain )
 {
     pszDomain = CheckMetadataDomain(pszDomain);
-    m_bMetadataDirty = TRUE;
+    m_bMetadataDirty = true;
     GetMetadata(); /* force loading from storage if needed */
     return GDALPamDataset::SetMetadataItem(pszName, pszValue, pszDomain);
 }
@@ -2449,7 +2425,7 @@ CPLErr GDALGeoPackageDataset::SetMetadataItem( const char * pszName,
 int GDALGeoPackageDataset::Create( const char * pszFilename,
                                    int nXSize,
                                    int nYSize,
-                                   int nBands,
+                                   int nBandsIn,
                                    GDALDataType eDT,
                                    char **papszOptions )
 {
@@ -2459,14 +2435,14 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
     /* First, ensure there isn't any such file yet. */
     VSIStatBufL sStatBuf;
 
-    if( nBands != 0 )
+    if( nBandsIn != 0 )
     {
         if( eDT != GDT_Byte )
         {
             CPLError(CE_Failure, CPLE_NotSupported, "Only Byte supported");
             return FALSE;
         }
-        if( nBands != 1 && nBands != 2 && nBands != 3 && nBands != 4 )
+        if( nBandsIn != 1 && nBandsIn != 2 && nBandsIn != 3 && nBandsIn != 4 )
         {
             CPLError(CE_Failure, CPLE_NotSupported,
                      "Only 1 (Grey/ColorTable), 2 (Grey+Alpha), 3 (RGB) or 4 (RGBA) band dataset supported");
@@ -2478,8 +2454,8 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
     if( VSIStatL( pszFilename, &sStatBuf ) == 0 )
     {
         bFileExists = TRUE;
-        if( nBands == 0 ||
-            !CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "APPEND_SUBDATASET", "NO")) )
+        if( nBandsIn == 0 ||
+            !CPLTestBool(CSLFetchNameValueDef(papszOptions, "APPEND_SUBDATASET", "NO")) )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                     "A file system object called '%s' already exists.",
@@ -2489,10 +2465,14 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
         }
     }
     m_pszFilename = CPLStrdup(pszFilename);
-    m_bNew = TRUE;
+    m_bNew = true;
     bUpdate = TRUE;
     eAccess = GA_Update; /* hum annoying duplication */
 
+    // for test/debug purposes only. true is the nominal value
+    m_bPNGSupports2Bands = CPLTestBool(CPLGetConfigOption("GPKG_PNG_SUPPORTS_2BANDS", "TRUE"));
+    m_bPNGSupportsCT = CPLTestBool(CPLGetConfigOption("GPKG_PNG_SUPPORTS_CT", "TRUE"));
+
     if (!OpenOrCreateDB(bFileExists ? SQLITE_OPEN_READWRITE : SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE))
         return FALSE;
 
@@ -2508,20 +2488,20 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
 
     SoftStartTransaction();
 
-    int bCreateTriggers = CSLTestBoolean(CPLGetConfigOption("CREATE_TRIGGERS", "YES"));
-    int bCreateGeometryColumns = CSLTestBoolean(CPLGetConfigOption("CREATE_GEOMETRY_COLUMNS", "YES"));
+    int bCreateTriggers = CPLTestBool(CPLGetConfigOption("CREATE_TRIGGERS", "YES"));
+    int bCreateGeometryColumns = CPLTestBool(CPLGetConfigOption("CREATE_GEOMETRY_COLUMNS", "YES"));
     if( !bFileExists )
     {
         /* Requirement 2: A GeoPackage SHALL contain 0x47503130 ("GP10" in ASCII) in the application id */
         /* http://opengis.github.io/geopackage/#_file_format */
         const char *pszPragma = CPLSPrintf("PRAGMA application_id = %d", GPKG_APPLICATION_ID);
-        
+
         if ( OGRERR_NONE != SQLCommand(hDB, pszPragma) )
             return FALSE;
-            
+
         /* Requirement 10: A GeoPackage SHALL include a gpkg_spatial_ref_sys table */
         /* http://opengis.github.io/geopackage/#spatial_ref_sys */
-        const char *pszSpatialRefSys = 
+        const char *pszSpatialRefSys =
             "CREATE TABLE gpkg_spatial_ref_sys ("
             "srs_name TEXT NOT NULL,"
             "srs_id INTEGER NOT NULL PRIMARY KEY,"
@@ -2530,22 +2510,22 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
             "definition  TEXT NOT NULL,"
             "description TEXT"
             ")";
-            
+
         if ( OGRERR_NONE != SQLCommand(hDB, pszSpatialRefSys) )
             return FALSE;
 
         /* Requirement 11: The gpkg_spatial_ref_sys table in a GeoPackage SHALL */
         /* contain a record for EPSG:4326, the geodetic WGS84 SRS */
         /* http://opengis.github.io/geopackage/#spatial_ref_sys */
-        pszSpatialRefSysRecord = 
+        pszSpatialRefSysRecord =
             "INSERT INTO gpkg_spatial_ref_sys ("
             "srs_name, srs_id, organization, organization_coordsys_id, definition, description"
             ") VALUES ("
             "'WGS 84 geodetic', 4326, 'EPSG', 4326, '"
             "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]]"
             "', 'longitude/latitude coordinates in decimal degrees on the WGS 84 spheroid'"
-            ")";  
-            
+            ")";
+
         if ( OGRERR_NONE != SQLCommand(hDB, pszSpatialRefSysRecord) )
             return FALSE;
 
@@ -2554,13 +2534,13 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
         /* an organization_coordsys_id of -1, and definition “undefined” */
         /* for undefined Cartesian coordinate reference systems */
         /* http://opengis.github.io/geopackage/#spatial_ref_sys */
-        pszSpatialRefSysRecord = 
+        pszSpatialRefSysRecord =
             "INSERT INTO gpkg_spatial_ref_sys ("
             "srs_name, srs_id, organization, organization_coordsys_id, definition, description"
             ") VALUES ("
             "'Undefined cartesian SRS', -1, 'NONE', -1, 'undefined', 'undefined cartesian coordinate reference system'"
-            ")"; 
-            
+            ")";
+
         if ( OGRERR_NONE != SQLCommand(hDB, pszSpatialRefSysRecord) )
             return FALSE;
 
@@ -2569,16 +2549,16 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
         /* an organization_coordsys_id of 0, and definition “undefined” */
         /* for undefined geographic coordinate reference systems */
         /* http://opengis.github.io/geopackage/#spatial_ref_sys */
-        pszSpatialRefSysRecord = 
+        pszSpatialRefSysRecord =
             "INSERT INTO gpkg_spatial_ref_sys ("
             "srs_name, srs_id, organization, organization_coordsys_id, definition, description"
             ") VALUES ("
             "'Undefined geographic SRS', 0, 'NONE', 0, 'undefined', 'undefined geographic coordinate reference system'"
-            ")"; 
-            
+            ")";
+
         if ( OGRERR_NONE != SQLCommand(hDB, pszSpatialRefSysRecord) )
             return FALSE;
-        
+
         /* Requirement 13: A GeoPackage file SHALL include a gpkg_contents table */
         /* http://opengis.github.io/geopackage/#_contents */
         const char *pszContents =
@@ -2593,14 +2573,14 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
             "srs_id INTEGER,"
             "CONSTRAINT fk_gc_r_srs_id FOREIGN KEY (srs_id) REFERENCES gpkg_spatial_ref_sys(srs_id)"
             ")";
-            
+
         if ( OGRERR_NONE != SQLCommand(hDB, pszContents) )
             return FALSE;
 
         /* Requirement 21: A GeoPackage with a gpkg_contents table row with a “features” */
         /* data_type SHALL contain a gpkg_geometry_columns table or updateable view */
         /* http://opengis.github.io/geopackage/#_geometry_columns */
-        const char *pszGeometryColumns =        
+        const char *pszGeometryColumns =
             "CREATE TABLE gpkg_geometry_columns ("
             "table_name TEXT NOT NULL,"
             "column_name TEXT NOT NULL,"
@@ -2613,7 +2593,7 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
             "CONSTRAINT fk_gc_tn FOREIGN KEY (table_name) REFERENCES gpkg_contents(table_name),"
             "CONSTRAINT fk_gc_srs FOREIGN KEY (srs_id) REFERENCES gpkg_spatial_ref_sys (srs_id)"
             ")";
-            
+
         if ( bCreateGeometryColumns && OGRERR_NONE != SQLCommand(hDB, pszGeometryColumns) )
             return FALSE;
 
@@ -2629,10 +2609,10 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
             "CONSTRAINT fk_gtms_table_name FOREIGN KEY (table_name) REFERENCES gpkg_contents(table_name),"
             "CONSTRAINT fk_gtms_srs FOREIGN KEY (srs_id) REFERENCES gpkg_spatial_ref_sys (srs_id)"
             ")";
-            
+
         if ( OGRERR_NONE != SQLCommand(hDB, pszTileMatrixSet) )
             return FALSE;
-        
+
         /* From C.6. gpkg_tile_matrix Table 29. gpkg_tile_matrix Table Creation SQL */
         const char *pszTileMatrix =
             "CREATE TABLE gpkg_tile_matrix ("
@@ -2647,7 +2627,7 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
             "CONSTRAINT pk_ttm PRIMARY KEY (table_name, zoom_level),"
             "CONSTRAINT fk_tmm_table_name FOREIGN KEY (table_name) REFERENCES gpkg_contents(table_name)"
             ")";
-            
+
         if ( OGRERR_NONE != SQLCommand(hDB, pszTileMatrix) )
             return FALSE;
 
@@ -2716,12 +2696,12 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
         if ( bCreateTriggers && OGRERR_NONE != SQLCommand(hDB, pszTileMatrixTrigger) )
             return FALSE;
 
-        if( CSLTestBoolean(CPLGetConfigOption("CREATE_METADATA_TABLES", "YES")) &&
+        if( CPLTestBool(CPLGetConfigOption("CREATE_METADATA_TABLES", "YES")) &&
             !CreateMetadataTables() )
             return FALSE;
     }
-    
-    if( nBands != 0 )
+
+    if( nBandsIn != 0 )
     {
         const char* pszTableName = CPLGetBasename(m_pszFilename);
         m_osRasterTable = CSLFetchNameValueDef(papszOptions, "RASTER_TABLE", pszTableName);
@@ -2835,21 +2815,21 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
         int nTileWidth = atoi(pszTileWidth);
         int nTileHeight = atoi(pszTileHeight);
         if( (nTileWidth < 8 || nTileWidth > 4096 || nTileHeight < 8 || nTileHeight > 4096) &&
-            !CSLTestBoolean(CPLGetConfigOption("GPKG_ALLOW_CRAZY_SETTINGS", "NO")) )
+            !CPLTestBool(CPLGetConfigOption("GPKG_ALLOW_CRAZY_SETTINGS", "NO")) )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Invalid block dimensions: %dx%d",
                      nTileWidth, nTileHeight);
             return FALSE;
         }
 
-        m_pabyCachedTiles = (GByte*) VSIMalloc3(4 * 4, nTileWidth, nTileHeight);
+        m_pabyCachedTiles = (GByte*) VSI_MALLOC3_VERBOSE(4 * 4, nTileWidth, nTileHeight);
         if( m_pabyCachedTiles == NULL )
         {
             return FALSE;
         }
 
-        for(int i = 1; i <= nBands; i ++)
-            SetBand( i, new GDALGeoPackageRasterBand(this, i, nTileWidth, nTileHeight) );
+        for(int i = 1; i <= nBandsIn; i ++)
+            SetBand( i, new GDALGeoPackageRasterBand(this, nTileWidth, nTileHeight) );
 
         GDALPamDataset::SetMetadataItem("INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE");
         GDALPamDataset::SetMetadataItem("IDENTIFIER", m_osIdentifier);
@@ -2858,7 +2838,7 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
 
         const char* pszTF = CSLFetchNameValue(papszOptions, "TILE_FORMAT");
         if( pszTF )
-            m_eTF = GetTileFormat(pszTF);
+            m_eTF = GDALGPKGMBTilesGetTileFormat(pszTF);
 
         ParseCompressionOptions(papszOptions);
 
@@ -2890,9 +2870,10 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
                         return FALSE;
                     }
 
-                    /* Implicitely sets SRS */
+                    // Implicitly sets SRS.
                     OGRSpatialReference oSRS;
-                    if( oSRS.importFromEPSG(asTilingShemes[iScheme].nEPSGCode) != OGRERR_NONE )
+                    if( oSRS.importFromEPSG(asTilingShemes[iScheme].nEPSGCode)
+                        != OGRERR_NONE )
                         return FALSE;
                     char* pszWKT = NULL;
                     oSRS.exportToWkt(&pszWKT);
@@ -2937,6 +2918,7 @@ typedef struct
 
 static const WarpResamplingAlg asResamplingAlg[] =
 {
+    { "NEAREST", GRA_NearestNeighbour },
     { "BILINEAR", GRA_Bilinear },
     { "CUBIC", GRA_Cubic },
     { "CUBICSPLINE", GRA_CubicSpline },
@@ -2946,17 +2928,17 @@ static const WarpResamplingAlg asResamplingAlg[] =
 };
 
 GDALDataset* GDALGeoPackageDataset::CreateCopy( const char *pszFilename,
-                                                   GDALDataset *poSrcDS, 
+                                                   GDALDataset *poSrcDS,
                                                    int bStrict,
                                                    char ** papszOptions,
-                                                   GDALProgressFunc pfnProgress, 
+                                                   GDALProgressFunc pfnProgress,
                                                    void * pProgressData )
 {
-    const char* pszTilingScheme = 
+    const char* pszTilingScheme =
             CSLFetchNameValueDef(papszOptions, "TILING_SCHEME", "CUSTOM");
 
     char** papszUpdatedOptions = CSLDuplicate(papszOptions);
-    if( CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "APPEND_SUBDATASET", "NO")) &&
+    if( CPLTestBool(CSLFetchNameValueDef(papszOptions, "APPEND_SUBDATASET", "NO")) &&
         CSLFetchNameValue(papszOptions, "RASTER_TABLE") == NULL )
     {
         papszUpdatedOptions = CSLSetNameValue(papszUpdatedOptions,
@@ -2973,12 +2955,12 @@ GDALDataset* GDALGeoPackageDataset::CreateCopy( const char *pszFilename,
             return NULL;
         }
         GDALDataset* poDS = poThisDriver->DefaultCreateCopy(
-                                    pszFilename, poSrcDS, bStrict, 
+                                    pszFilename, poSrcDS, bStrict,
                                     papszUpdatedOptions, pfnProgress, pProgressData );
         CSLDestroy(papszUpdatedOptions);
         return poDS;
     }
-    
+
     int nBands = poSrcDS->GetRasterCount();
     if( nBands != 1 && nBands != 2 && nBands != 3 && nBands != 4 )
     {
@@ -3017,7 +2999,7 @@ GDALDataset* GDALGeoPackageDataset::CreateCopy( const char *pszFilename,
     char* pszWKT = NULL;
     oSRS.exportToWkt(&pszWKT);
     char** papszTO = CSLSetNameValue( NULL, "DST_SRS", pszWKT );
-    void* hTransformArg = 
+    void* hTransformArg =
             GDALCreateGenImgProjTransformer2( poSrcDS, NULL, papszTO );
     if( hTransformArg == NULL )
     {
@@ -3032,10 +3014,10 @@ GDALDataset* GDALGeoPackageDataset::CreateCopy( const char *pszFilename,
     double adfExtent[4];
     int    nXSize, nYSize;
 
-    if ( GDALSuggestedWarpOutput2( poSrcDS, 
-                                  psInfo->pfnTransform, hTransformArg, 
-                                  adfGeoTransform, 
-                                  &nXSize, &nYSize, 
+    if ( GDALSuggestedWarpOutput2( poSrcDS,
+                                  psInfo->pfnTransform, hTransformArg,
+                                  adfGeoTransform,
+                                  &nXSize, &nYSize,
                                   adfExtent, 0 ) != CE_None )
     {
         CSLDestroy(papszUpdatedOptions);
@@ -3067,7 +3049,7 @@ GDALDataset* GDALGeoPackageDataset::CreateCopy( const char *pszFilename,
         CSLDestroy(papszTO);
         return NULL;
     }
-    
+
     const char* pszZoomLevelStrategy = CSLFetchNameValueDef(papszOptions,
                                                             "ZOOM_LEVEL_STRATEGY",
                                                             "AUTO");
@@ -3147,7 +3129,7 @@ GDALDataset* GDALGeoPackageDataset::CreateCopy( const char *pszFilename,
 /*      Warp the transformer with a linear approximator                 */
 /* -------------------------------------------------------------------- */
     hTransformArg =
-        GDALCreateApproxTransformer( GDALGenImgProjTransform, 
+        GDALCreateApproxTransformer( GDALGenImgProjTransform,
                                      hTransformArg, 0.125 );
     GDALApproxTransformerOwnsSubtransformer(hTransformArg, TRUE);
 
@@ -3158,7 +3140,7 @@ GDALDataset* GDALGeoPackageDataset::CreateCopy( const char *pszFilename,
 
     psWO->papszWarpOptions = NULL;
     psWO->eWorkingDataType = GDT_Byte;
-    
+
     GDALResampleAlg eResampleAlg = GRA_Bilinear;
     const char* pszResampling = CSLFetchNameValue(papszOptions, "RESAMPLING");
     if( pszResampling )
@@ -3251,7 +3233,7 @@ void GDALGeoPackageDataset::ParseCompressionOptions(char** papszOptions)
 
     const char* pszDither = CSLFetchNameValue(papszOptions, "DITHER");
     if( pszDither )
-        m_bDither = CSLTestBoolean(pszDither);
+        m_bDither = CPLTestBool(pszDither);
 }
 
 /************************************************************************/
@@ -3344,7 +3326,7 @@ OGRLayer* GDALGeoPackageDataset::ICreateLayer( const char * pszLayerName,
     if (pszGeomColumnName == NULL)
         pszGeomColumnName = "geom";
     int bGeomNullable = CSLFetchBoolean(papszOptions, "GEOMETRY_NULLABLE", TRUE);
-    
+
     /* Read FID option */
     const char* pszFIDColumnName = CSLFetchNameValue(papszOptions, "FID");
     if (pszFIDColumnName == NULL)
@@ -3353,21 +3335,21 @@ OGRLayer* GDALGeoPackageDataset::ICreateLayer( const char * pszLayerName,
     if ( strspn(pszFIDColumnName, "`~!@#$%^&*()+-={}|[]\\:\";'<>?,./") > 0 )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
-                 "The primary key (%s) name may not contain special characters or spaces", 
+                 "The primary key (%s) name may not contain special characters or spaces",
                  pszFIDColumnName);
         return NULL;
     }
 
     /* Avoiding gpkg prefixes is not an official requirement, but seems wise */
-    if (strncmp(pszLayerName, "gpkg", 4) == 0)
+    if (STARTS_WITH(pszLayerName, "gpkg"))
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "The layer name may not begin with 'gpkg' as it is a reserved geopackage prefix");
         return NULL;
     }
 
-    /* Pre-emptively try and avoid sqlite3 syntax errors due to  */
-    /* illegal characters */
+    /* Preemptively try and avoid sqlite3 syntax errors due to  */
+    /* illegal characters. */
     if ( strspn(pszLayerName, "`~!@#$%^&*()+-={}|[]\\:\";'<>?,./") > 0 )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -3381,7 +3363,7 @@ OGRLayer* GDALGeoPackageDataset::ICreateLayer( const char * pszLayerName,
         if( EQUAL(pszLayerName, m_papoLayers[iLayer]->GetName()) )
         {
             const char *pszOverwrite = CSLFetchNameValue(papszOptions,"OVERWRITE");
-            if( pszOverwrite != NULL && CSLTestBoolean(pszOverwrite) )
+            if( pszOverwrite != NULL && CPLTestBool(pszOverwrite) )
             {
                 DeleteLayer( iLayer );
             }
@@ -3409,10 +3391,10 @@ OGRLayer* GDALGeoPackageDataset::ICreateLayer( const char * pszLayerName,
 
     /* Should we create a spatial index ? */
     const char *pszSI = CSLFetchNameValue( papszOptions, "SPATIAL_INDEX" );
-    int bCreateSpatialIndex = ( pszSI == NULL || CSLTestBoolean(pszSI) );
+    int bCreateSpatialIndex = ( pszSI == NULL || CPLTestBool(pszSI) );
     if( eGType != wkbNone && bCreateSpatialIndex )
     {
-        poLayer->SetDeferedSpatialIndexCreation(TRUE);
+        poLayer->SetDeferredSpatialIndexCreation(true);
     }
 
     poLayer->SetPrecisionFlag( CSLFetchBoolean(papszOptions,"PRECISION",TRUE));
@@ -3428,7 +3410,7 @@ OGRLayer* GDALGeoPackageDataset::ICreateLayer( const char * pszLayerName,
 /*                            DeleteLayer()                             */
 /************************************************************************/
 
-int GDALGeoPackageDataset::DeleteLayer( int iLayer )
+OGRErr GDALGeoPackageDataset::DeleteLayer( int iLayer )
 {
     char *pszSQL;
 
@@ -3454,17 +3436,17 @@ int GDALGeoPackageDataset::DeleteLayer( int iLayer )
     pszSQL = sqlite3_mprintf(
             "DROP TABLE \"%s\"",
              osLayerName.c_str());
-    
+
     SQLCommand(hDB, pszSQL);
     sqlite3_free(pszSQL);
 
     pszSQL = sqlite3_mprintf(
             "DELETE FROM gpkg_geometry_columns WHERE table_name = '%q'",
              osLayerName.c_str());
-    
+
     SQLCommand(hDB, pszSQL);
     sqlite3_free(pszSQL);
-    
+
     pszSQL = sqlite3_mprintf(
              "DELETE FROM gpkg_contents WHERE table_name = '%q'",
               osLayerName.c_str());
@@ -3490,6 +3472,8 @@ int GDALGeoPackageDataset::TestCapability( const char * pszCap )
     }
     else if( EQUAL(pszCap,ODsCCurveGeometries) )
         return TRUE;
+    else if( EQUAL(pszCap,ODsCMeasuredGeometries) )
+        return TRUE;
     return OGRSQLiteBaseDataSource::TestCapability(pszCap);
 }
 
@@ -3497,7 +3481,7 @@ int GDALGeoPackageDataset::TestCapability( const char * pszCap )
 /*                             ExecuteSQL()                             */
 /************************************************************************/
 
-static const char* apszFuncsWithSideEffects[] =
+static const char* const apszFuncsWithSideEffects[] =
 {
     "CreateSpatialIndex",
     "DisableSpatialIndex",
@@ -3508,7 +3492,7 @@ OGRLayer * GDALGeoPackageDataset::ExecuteSQL( const char *pszSQLCommand,
                                           const char *pszDialect )
 
 {
-    m_bHasReadMetadataFromStorage = FALSE;
+    m_bHasReadMetadataFromStorage = false;
 
     FlushMetadata();
     for( int i = 0; i < m_nLayers; i++ )
@@ -3518,12 +3502,12 @@ OGRLayer * GDALGeoPackageDataset::ExecuteSQL( const char *pszSQLCommand,
     }
 
     if( pszDialect != NULL && EQUAL(pszDialect,"OGRSQL") )
-        return GDALDataset::ExecuteSQL( pszSQLCommand, 
-                                          poSpatialFilter, 
+        return GDALDataset::ExecuteSQL( pszSQLCommand,
+                                          poSpatialFilter,
                                           pszDialect );
     else if( pszDialect != NULL && EQUAL(pszDialect,"INDIRECT_SQLITE") )
-        return GDALDataset::ExecuteSQL( pszSQLCommand, 
-                                          poSpatialFilter, 
+        return GDALDataset::ExecuteSQL( pszSQLCommand,
+                                          poSpatialFilter,
                                           "SQLITE" );
 
 /* -------------------------------------------------------------------- */
@@ -3553,13 +3537,14 @@ OGRLayer * GDALGeoPackageDataset::ExecuteSQL( const char *pszSQLCommand,
         }
     }
 
-    rc = sqlite3_prepare( hDB, osSQLCommand.c_str(), osSQLCommand.size(),
+    rc = sqlite3_prepare( hDB, osSQLCommand.c_str(),
+                          static_cast<int>(osSQLCommand.size()),
                           &hSQLStmt, NULL );
 
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                "In ExecuteSQL(): sqlite3_prepare(%s):\n  %s", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                "In ExecuteSQL(): sqlite3_prepare(%s):\n  %s",
                 pszSQLCommand, sqlite3_errmsg(hDB) );
 
         if( hSQLStmt != NULL )
@@ -3578,14 +3563,14 @@ OGRLayer * GDALGeoPackageDataset::ExecuteSQL( const char *pszSQLCommand,
     {
         if ( rc != SQLITE_DONE )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                  "In ExecuteSQL(): sqlite3_step(%s):\n  %s", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                  "In ExecuteSQL(): sqlite3_step(%s):\n  %s",
                   pszSQLCommand, sqlite3_errmsg(hDB) );
 
             sqlite3_finalize( hSQLStmt );
             return NULL;
         }
-        
+
         if( EQUAL(pszSQLCommand, "VACUUM") )
         {
             sqlite3_finalize( hSQLStmt );
@@ -3593,8 +3578,8 @@ OGRLayer * GDALGeoPackageDataset::ExecuteSQL( const char *pszSQLCommand,
             SetApplicationId();
             return NULL;
         }
-        
-        if( EQUALN(pszSQLCommand, "ALTER TABLE ", strlen("ALTER TABLE ")) )
+
+        if( STARTS_WITH_CI(pszSQLCommand, "ALTER TABLE ") )
         {
             char **papszTokens = CSLTokenizeString( pszSQLCommand );
             /* ALTER TABLE src_table RENAME TO dst_table */
@@ -3612,7 +3597,7 @@ OGRLayer * GDALGeoPackageDataset::ExecuteSQL( const char *pszSQLCommand,
             CSLDestroy(papszTokens);
         }
 
-        if( !EQUALN(pszSQLCommand, "SELECT ", 7) )
+        if( !STARTS_WITH_CI(pszSQLCommand, "SELECT ") )
         {
             sqlite3_finalize( hSQLStmt );
             return NULL;
@@ -3621,16 +3606,15 @@ OGRLayer * GDALGeoPackageDataset::ExecuteSQL( const char *pszSQLCommand,
         bUseStatementForGetNextFeature = FALSE;
         bEmptyLayer = TRUE;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Special case for some functions which must be run               */
 /*      only once                                                       */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszSQLCommand,"SELECT ",7) )
+    if( STARTS_WITH_CI(pszSQLCommand, "SELECT ") )
     {
-        unsigned int i;
-        for(i=0;i<sizeof(apszFuncsWithSideEffects)/
-                  sizeof(apszFuncsWithSideEffects[0]);i++)
+        for( unsigned int i=0; i < sizeof(apszFuncsWithSideEffects) /
+               sizeof(apszFuncsWithSideEffects[0]); i++ )
         {
             if( EQUALN(apszFuncsWithSideEffects[i], pszSQLCommand + 7,
                        strlen(apszFuncsWithSideEffects[i])) )
@@ -3648,7 +3632,7 @@ OGRLayer * GDALGeoPackageDataset::ExecuteSQL( const char *pszSQLCommand,
             }
         }
     }
-    else if( EQUALN(pszSQLCommand,"PRAGMA ",7) )
+    else if( STARTS_WITH_CI(pszSQLCommand, "PRAGMA ") )
     {
         if (sqlite3_column_count( hSQLStmt ) == 1 &&
             sqlite3_column_type( hSQLStmt, 0 ) == SQLITE_INTEGER )
@@ -3703,13 +3687,13 @@ void GDALGeoPackageDataset::ReleaseResultSet( OGRLayer * poLayer )
 /*                         HasExtensionsTable()                         */
 /************************************************************************/
 
-int GDALGeoPackageDataset::HasExtensionsTable()
+bool GDALGeoPackageDataset::HasExtensionsTable()
 {
     SQLResult oResultTable;
     OGRErr err = SQLQuery(hDB,
         "SELECT * FROM sqlite_master WHERE name = 'gpkg_extensions' "
         "AND type IN ('table', 'view')", &oResultTable);
-    int bHasExtensionsTable = ( err == OGRERR_NONE && oResultTable.nRowCount == 1 );
+    bool bHasExtensionsTable = ( err == OGRERR_NONE && oResultTable.nRowCount == 1 );
     SQLResultFree(&oResultTable);
     return bHasExtensionsTable;
 }
@@ -3718,7 +3702,7 @@ int GDALGeoPackageDataset::HasExtensionsTable()
 /*                    CheckUnknownExtensions()                          */
 /************************************************************************/
 
-void GDALGeoPackageDataset::CheckUnknownExtensions(int bCheckRasterTable)
+void GDALGeoPackageDataset::CheckUnknownExtensions(bool bCheckRasterTable)
 {
     if( !HasExtensionsTable() )
         return;
@@ -3726,10 +3710,18 @@ void GDALGeoPackageDataset::CheckUnknownExtensions(int bCheckRasterTable)
     char* pszSQL;
     if( !bCheckRasterTable)
         pszSQL = sqlite3_mprintf(
-            "SELECT extension_name, definition, scope FROM gpkg_extensions WHERE table_name IS NULL AND extension_name != 'gdal_aspatial'");
+            "SELECT extension_name, definition, scope FROM gpkg_extensions WHERE (table_name IS NULL AND extension_name != 'gdal_aspatial')"
+#ifdef WORKAROUND_SQLITE3_BUGS
+            " OR 0"
+#endif
+        );
     else
         pszSQL = sqlite3_mprintf(
-            "SELECT extension_name, definition, scope FROM gpkg_extensions WHERE table_name = '%q'",
+            "SELECT extension_name, definition, scope FROM gpkg_extensions WHERE table_name = '%q'"
+#ifdef WORKAROUND_SQLITE3_BUGS
+            " OR 0"
+#endif
+            ,
             m_osRasterTable.c_str());
 
     SQLResult oResultTable;
@@ -3760,7 +3752,7 @@ void GDALGeoPackageDataset::CheckUnknownExtensions(int bCheckRasterTable)
             }
             if( EQUAL(pszExtName, "gpkg_zoom_other") )
             {
-                m_bZoomOther = TRUE;
+                m_bZoomOther = true;
                 continue;
             }
 
@@ -3797,18 +3789,22 @@ void GDALGeoPackageDataset::CheckUnknownExtensions(int bCheckRasterTable)
 /*                         HasGDALAspatialExtension()                       */
 /************************************************************************/
 
-int GDALGeoPackageDataset::HasGDALAspatialExtension()
+bool GDALGeoPackageDataset::HasGDALAspatialExtension()
 {
     if (!HasExtensionsTable())
-        return 0;
+        return false;
 
     SQLResult oResultTable;
     OGRErr err = SQLQuery(hDB,
         "SELECT * FROM gpkg_extensions "
-        "WHERE extension_name = 'gdal_aspatial' "
+        "WHERE (extension_name = 'gdal_aspatial' "
         "AND table_name IS NULL "
-        "AND column_name IS NULL", &oResultTable);
-    int bHasExtension = ( err == OGRERR_NONE && oResultTable.nRowCount == 1 );
+        "AND column_name IS NULL)"
+#ifdef WORKAROUND_SQLITE3_BUGS
+        " OR 0"
+#endif
+        , &oResultTable);
+    bool bHasExtension = ( err == OGRERR_NONE && oResultTable.nRowCount == 1 );
     SQLResultFree(&oResultTable);
     return bHasExtension;
 }
@@ -3847,7 +3843,7 @@ OGRErr GDALGeoPackageDataset::CreateExtensionsTableIfNecessary()
     /* in a corresponding row in the gpkg_extensions table. The absence of a */
     /* gpkg_extensions table or the absence of rows in gpkg_extensions table */
     /* SHALL both indicate the absence of extensions to a GeoPackage. */
-    const char* pszCreateGpkgExtensions = 
+    const char* pszCreateGpkgExtensions =
         "CREATE TABLE gpkg_extensions ("
         "table_name TEXT,"
         "column_name TEXT,"
@@ -3877,13 +3873,13 @@ static int OGRGeoPackageGetHeader(sqlite3_context* pContext,
     }
     int nBLOBLen = sqlite3_value_bytes (argv[0]);
     const GByte* pabyBLOB = (const GByte *) sqlite3_value_blob (argv[0]);
-    if( nBLOBLen < 4 ||
-        GPkgHeaderFromWKB(pabyBLOB, psHeader) != OGRERR_NONE )
+    if( nBLOBLen < 8 ||
+        GPkgHeaderFromWKB(pabyBLOB, nBLOBLen, psHeader) != OGRERR_NONE )
     {
         sqlite3_result_null(pContext);
         return FALSE;
     }
-    if( psHeader->iDims == 0 && bNeedExtent )
+    if( !(psHeader->bExtentHasXY) && bNeedExtent )
     {
         OGRGeometry *poGeom = GPkgGeometryToOGR(pabyBLOB, nBLOBLen, NULL);
         if( poGeom == NULL || poGeom->IsEmpty() )
@@ -3987,7 +3983,6 @@ void OGRGeoPackageSTGeometryType(sqlite3_context* pContext,
 
     int nBLOBLen = sqlite3_value_bytes (argv[0]);
     const GByte* pabyBLOB = (const GByte *) sqlite3_value_blob (argv[0]);
-    OGRBoolean bIs3D;
     OGRwkbGeometryType eGeometryType;
     if( nBLOBLen <= (int)sHeader.szHeader )
     {
@@ -3995,7 +3990,7 @@ void OGRGeoPackageSTGeometryType(sqlite3_context* pContext,
         return;
     }
     OGRErr err = OGRReadWKBGeometryType( (GByte*)pabyBLOB + sHeader.szHeader,
-                                         wkbVariantIso, &eGeometryType, &bIs3D );
+                                         wkbVariantIso, &eGeometryType );
     if( err != OGRERR_NONE )
         sqlite3_result_null( pContext );
     else
@@ -4058,7 +4053,7 @@ void OGRGeoPackageCreateSpatialIndex(sqlite3_context* pContext,
     const char* pszTableName = (const char*)sqlite3_value_text(argv[0]);
     const char* pszGeomName = (const char*)sqlite3_value_text(argv[1]);
     GDALGeoPackageDataset* poDS = (GDALGeoPackageDataset* )sqlite3_user_data(pContext);
-    
+
     OGRGeoPackageTableLayer* poLyr = (OGRGeoPackageTableLayer*)poDS->GetLayerByName(pszTableName);
     if( poLyr == NULL )
     {
@@ -4095,7 +4090,7 @@ void OGRGeoPackageDisableSpatialIndex(sqlite3_context* pContext,
     const char* pszTableName = (const char*)sqlite3_value_text(argv[0]);
     const char* pszGeomName = (const char*)sqlite3_value_text(argv[1]);
     GDALGeoPackageDataset* poDS = (GDALGeoPackageDataset* )sqlite3_user_data(pContext);
-    
+
     OGRGeoPackageTableLayer* poLyr = (OGRGeoPackageTableLayer*)poDS->GetLayerByName(pszTableName);
     if( poLyr == NULL )
     {
@@ -4110,7 +4105,7 @@ void OGRGeoPackageDisableSpatialIndex(sqlite3_context* pContext,
         return;
     }
 
-    sqlite3_result_int( pContext, poLyr->DropSpatialIndex(TRUE) );
+    sqlite3_result_int( pContext, poLyr->DropSpatialIndex(true) );
 }
 
 /************************************************************************/
@@ -4262,9 +4257,9 @@ int GDALGeoPackageDataset::OpenOrCreateDB(int flags)
 #ifdef SPATIALITE_412_OR_LATER
     InitNewSpatialite();
 
-    // Enable Spatialite 4.3 "amphibious" mode, i.e. that spatialite functions
-    // that take geometries will accept GPKG encoded gometries without
-    // explicit conversion
+    // Enable SpatiaLite 4.3 "amphibious" mode, i.e. that SpatiaLite functions
+    // that take geometries will accept GPKG encoded geometries without
+    // explicit conversion.
     sqlite3_exec(hDB, "SELECT EnableGpkgAmphibiousMode()", NULL, NULL, NULL);
 #endif
 
@@ -4299,9 +4294,9 @@ int GDALGeoPackageDataset::OpenOrCreateDB(int flags)
     // HSTORE functions
     sqlite3_create_function(hDB, "hstore_get_value", 2, SQLITE_ANY, NULL,
                             GPKG_hstore_get_value, NULL, NULL);
-    
+
     // Debug functions
-    if( CSLTestBoolean(CPLGetConfigOption("GPKG_DEBUG", "FALSE")) )
+    if( CPLTestBool(CPLGetConfigOption("GPKG_DEBUG", "FALSE")) )
     {
         sqlite3_create_function(hDB, "GDAL_GetMimeType", 1, SQLITE_ANY, NULL,
                                 GPKG_GDAL_GetMimeType, NULL, NULL);
@@ -4373,10 +4368,9 @@ const char* GDALGeoPackageDataset::GetGeometryTypeString(OGRwkbGeometryType eTyp
 {
     const char* pszGPKGGeomType = OGRToOGCGeomType(eType);
     if( EQUAL(pszGPKGGeomType, "GEOMETRYCOLLECTION") &&
-        CSLTestBoolean(CPLGetConfigOption("OGR_GPKG_GEOMCOLLECTION", "YES")) )
+        CPLTestBool(CPLGetConfigOption("OGR_GPKG_GEOMCOLLECTION", "YES")) )
     {
         pszGPKGGeomType = "GEOMCOLLECTION";
     }
     return pszGPKGGeomType;
 }
-
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackagedriver.cpp b/ogr/ogrsf_frmts/gpkg/ogrgeopackagedriver.cpp
index ac7a8ab..8ab5dc2 100644
--- a/ogr/ogrsf_frmts/gpkg/ogrgeopackagedriver.cpp
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackagedriver.cpp
@@ -29,7 +29,7 @@
 
 #include "ogr_geopackage.h"
 
-// g++ -g -Wall -fPIC -shared -o ogr_geopackage.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/gpkg ogr/ogrsf_frmts/gpkg/*.c* -L. -lgdal 
+// g++ -g -Wall -fPIC -shared -o ogr_geopackage.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/gpkg ogr/ogrsf_frmts/gpkg/*.c* -L. -lgdal
 
 
 /* "GP10" in ASCII bytes */
@@ -40,26 +40,29 @@ static const char aGpkgId[4] = {0x47, 0x50, 0x31, 0x30};
 /*                       OGRGeoPackageDriverIdentify()                  */
 /************************************************************************/
 
-static int OGRGeoPackageDriverIdentify( GDALOpenInfo* poOpenInfo )
+
+static int OGRGeoPackageDriverIdentify( GDALOpenInfo* poOpenInfo, bool bEmitWarning )
 {
-    if( EQUALN(poOpenInfo->pszFilename, "GPKG:", 5) )
+    if( STARTS_WITH_CI(poOpenInfo->pszFilename, "GPKG:") )
         return TRUE;
 
-    /* Requirement 3: File name has to end in "gpkg" */
-    /* http://opengis.github.io/geopackage/#_file_extension_name */
-    if( !EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "GPKG") )
-        return FALSE;
-
     /* Check that the filename exists and is a file */
     if( poOpenInfo->fpL == NULL)
         return FALSE;
 
     if ( poOpenInfo->nHeaderBytes < 16 ||
-        strncmp( (const char*)poOpenInfo->pabyHeader, "SQLite format 3", 15 ) != 0 )
+        !STARTS_WITH((const char*)poOpenInfo->pabyHeader, "SQLite format 3") )
     {
         return FALSE;
     }
 
+    /* Requirement 3: File name has to end in "gpkg" */
+    /* http://opengis.github.io/geopackage/#_file_extension_name */
+    /* But be tolerant, if the GPKG application id is found, because some */
+    /* producers don't necessarily honour that requirement (#6396) */
+    const char* pszExt = CPLGetExtension(poOpenInfo->pszFilename);
+    const bool bIsRecognizedExtension = EQUAL(pszExt, "GPKG") || EQUAL(pszExt, "GPKX");
+
     /* Requirement 2: A GeoPackage SHALL contain 0x47503130 ("GP10" in ASCII) */
     /* in the application id */
     /* http://opengis.github.io/geopackage/#_file_format */
@@ -67,20 +70,88 @@ static int OGRGeoPackageDriverIdentify( GDALOpenInfo* poOpenInfo )
     if( poOpenInfo->nHeaderBytes < 68 + 4 ||
         memcmp(poOpenInfo->pabyHeader + 68, aGpkgId, 4) != 0 )
     {
-        CPLError( CE_Warning, CPLE_AppDefined, "GPKG: bad application_id on '%s'",
-                  poOpenInfo->pszFilename);
+#ifdef DEBUG
+        if( EQUAL(CPLGetFilename(poOpenInfo->pszFilename), ".cur_input")  )
+        {
+            return FALSE;
+        }
+#endif
+        if( !bIsRecognizedExtension )
+            return FALSE;
+
+        if( bEmitWarning )
+        {
+            char szSignature[4+1];
+            memcpy(szSignature, poOpenInfo->pabyHeader + 68, 4);
+            szSignature[4] = '\0';
+
+            /* Is this a GPxx version ? */
+            const bool bWarn = CPLTestBool(CPLGetConfigOption("GPKG_WARN_UNRECOGNIZED_APPLICATION_ID", "YES"));
+            if( szSignature[0] == 'G' && szSignature[1] == 'P' &&
+                szSignature[2] >= '0' && szSignature[2] <= '9' &&
+                szSignature[3] >= '0' && szSignature[3] <= '9' )
+            {
+                if( bWarn )
+                {
+                    CPLError( CE_Warning, CPLE_AppDefined,
+                              "GPKG: '%s' has version '%s' with may be partially supported by this driver",
+                              poOpenInfo->pszFilename, szSignature );
+                }
+                else
+                {
+                    CPLDebug( "GPKG",
+                              "'%s' has version '%s' with may be partially supported by this driver",
+                              poOpenInfo->pszFilename, szSignature );
+                }
+            }
+            else
+            {
+                if( bWarn )
+                {
+                    CPLError( CE_Warning, CPLE_AppDefined,
+                              "GPKG: bad application_id 0x%02X%02X%02X%02X on '%s'",
+                              szSignature[0], szSignature[1], szSignature[2], szSignature[3],
+                              poOpenInfo->pszFilename );
+                }
+                else
+                {
+                    CPLDebug( "GPKG",
+                              "bad application_id 0x%02X%02X%02X%02X on '%s'",
+                              szSignature[0], szSignature[1], szSignature[2], szSignature[3],
+                              poOpenInfo->pszFilename );
+                }
+            }
+        }
+    }
+    else if( !bIsRecognizedExtension
+#ifdef DEBUG
+              && !EQUAL(CPLGetFilename(poOpenInfo->pszFilename), ".cur_input")
+#endif
+           )
+    {
+        if( bEmitWarning )
+        {
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "File %s has GPKG application_id, but non conformant file extension",
+                      poOpenInfo->pszFilename);
+        }
     }
 
     return TRUE;
 }
 
+static int OGRGeoPackageDriverIdentify( GDALOpenInfo* poOpenInfo )
+{
+    return OGRGeoPackageDriverIdentify(poOpenInfo, false);
+}
+
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
 
 static GDALDataset *OGRGeoPackageDriverOpen( GDALOpenInfo* poOpenInfo )
 {
-    if( !OGRGeoPackageDriverIdentify(poOpenInfo) )
+    if( !OGRGeoPackageDriverIdentify(poOpenInfo, true) )
         return NULL;
 
     GDALGeoPackageDataset   *poDS = new GDALGeoPackageDataset();
@@ -105,6 +176,16 @@ static GDALDataset* OGRGeoPackageDriverCreate( const char * pszFilename,
                                             GDALDataType eDT,
                                             char **papszOptions )
 {
+    const char* pszExt = CPLGetExtension(pszFilename);
+    const bool bIsRecognizedExtension = EQUAL(pszExt, "GPKG") || EQUAL(pszExt, "GPKX");
+    if( !bIsRecognizedExtension )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "The '%s' extension is not allowed by the GPKG specification, "
+                 "which may cause compatibility problems",
+                 pszExt);
+    }
+
     GDALGeoPackageDataset   *poDS = new GDALGeoPackageDataset();
 
     if( !poDS->Create( pszFilename, nXSize, nYSize,
@@ -136,23 +217,20 @@ static CPLErr OGRGeoPackageDriverDelete( const char *pszFilename )
 
 void RegisterOGRGeoPackage()
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "GPKG" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "GPKG" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "GPKG" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
+    poDriver->SetDescription( "GPKG" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
 
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "GeoPackage" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gpkg" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_geopackage.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "GeoPackage" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gpkg" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_geopackage.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte" );
 
 #define COMPRESSION_OPTIONS \
 "  <Option name='TILE_FORMAT' type='string-select' description='Format to use to create tiles' default='PNG_JPEG'>" \
@@ -166,7 +244,7 @@ void RegisterOGRGeoPackage()
 "  <Option name='ZLEVEL' type='int' min='1' max='9' description='DEFLATE compression level for PNG tiles' default='6'/>" \
 "  <Option name='DITHER' type='boolean' description='Whether to apply Floyd-Steinberg dithering (for TILE_FORMAT=PNG8)' default='NO'/>"
 
-        poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST, "<OpenOptionList>"
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST, "<OpenOptionList>"
 "  <Option name='TABLE' type='string' description='Name of tile user-table'/>"
 "  <Option name='ZOOM_LEVEL' type='integer' description='Zoom level of full resolution. If not specified, maximum non-empty zoom level'/>"
 "  <Option name='BAND_COUNT' type='int' min='1' max='4' description='Number of raster bands' default='4'/>"
@@ -179,7 +257,7 @@ void RegisterOGRGeoPackage()
 COMPRESSION_OPTIONS
 "</OpenOptionList>");
 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, "<CreationOptionList>"
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, "<CreationOptionList>"
 "  <Option name='RASTER_TABLE' type='string' description='Name of tile user table'/>"
 "  <Option name='APPEND_SUBDATASET' type='boolean' description='Set to YES to add a new tile user table to an existing GeoPackage instead of replacing it' default='NO'/>"
 "  <Option name='RASTER_IDENTIFIER' type='string' description='Human-readable identifier (e.g. short name)'/>"
@@ -212,7 +290,7 @@ COMPRESSION_OPTIONS
 "  </Option>"
 "</CreationOptionList>");
 
-        poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
 "<LayerCreationOptionList>"
 "  <Option name='GEOMETRY_NAME' type='string' description='Name of geometry column.' default='geom' deprecated_alias='GEOMETRY_COLUMN'/>"
 "  <Option name='GEOMETRY_NULLABLE' type='boolean' description='Whether the values of the geometry column can be NULL' default='YES'/>"
@@ -224,20 +302,21 @@ COMPRESSION_OPTIONS
 "  <Option name='IDENTIFIER' type='string' description='Identifier of the layer, as put in the contents table'/>"
 "  <Option name='DESCRIPTION' type='string' description='Description of the layer, as put in the contents table'/>"
 "</LayerCreationOptionList>");
-        
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES, "Integer Integer64 Real String Date DateTime Binary" );
-        poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_FIELDS, "YES" );
-        poDriver->SetMetadataItem( GDAL_DCAP_DEFAULT_FIELDS, "YES" );
-        poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_GEOMFIELDS, "YES" );
 
-        poDriver->pfnOpen = OGRGeoPackageDriverOpen;
-        poDriver->pfnIdentify = OGRGeoPackageDriverIdentify;
-        poDriver->pfnCreate = OGRGeoPackageDriverCreate;
-        poDriver->pfnCreateCopy = GDALGeoPackageDataset::CreateCopy;
-        poDriver->pfnDelete = OGRGeoPackageDriverDelete;
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
+                               "Integer Integer64 Real String Date DateTime "
+                               "Binary" );
+    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_FIELDS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_DEFAULT_FIELDS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_GEOMFIELDS, "YES" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->pfnOpen = OGRGeoPackageDriverOpen;
+    poDriver->pfnIdentify = OGRGeoPackageDriverIdentify;
+    poDriver->pfnCreate = OGRGeoPackageDriverCreate;
+    poDriver->pfnCreateCopy = GDALGeoPackageDataset::CreateCopy;
+    poDriver->pfnDelete = OGRGeoPackageDriverDelete;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackagelayer.cpp b/ogr/ogrsf_frmts/gpkg/ogrgeopackagelayer.cpp
index b76b882..a7c0657 100644
--- a/ogr/ogrsf_frmts/gpkg/ogrgeopackagelayer.cpp
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackagelayer.cpp
@@ -36,16 +36,17 @@
 /*                      OGRGeoPackageLayer()                            */
 /************************************************************************/
 
-OGRGeoPackageLayer::OGRGeoPackageLayer(GDALGeoPackageDataset *poDS) : m_poDS(poDS)
+OGRGeoPackageLayer::OGRGeoPackageLayer(GDALGeoPackageDataset *poDS) :
+    m_poDS(poDS),
+    m_poFeatureDefn(NULL),
+    iNextShapeId(0),
+    m_poQueryStatement(NULL),
+    bDoStep(TRUE),
+    m_pszFidColumn(NULL),
+    iFIDCol(-1),
+    iGeomCol(-1),
+    panFieldOrdinals(NULL)
 {
-    m_poFeatureDefn = NULL;
-    iNextShapeId = 0;
-    m_poQueryStatement = NULL;
-    bDoStep = TRUE;
-    m_pszFidColumn = NULL;
-    iFIDCol = -1;
-    iGeomCol = -1;
-    panFieldOrdinals = NULL;
 }
 
 /************************************************************************/
@@ -100,7 +101,7 @@ void OGRGeoPackageLayer::ClearStatement()
 OGRFeature *OGRGeoPackageLayer::GetNextFeature()
 
 {
-    for( ; TRUE; )
+    for( ; true; )
     {
         OGRFeature      *poFeature;
 
@@ -162,7 +163,6 @@ OGRFeature *OGRGeoPackageLayer::TranslateFeature( sqlite3_stmt* hStmt )
 /* -------------------------------------------------------------------- */
 /*      Create a feature from the current result.                       */
 /* -------------------------------------------------------------------- */
-    int         iField;
     OGRFeature *poFeature = new OGRFeature( m_poFeatureDefn );
 
 /* -------------------------------------------------------------------- */
@@ -202,17 +202,17 @@ OGRFeature *OGRGeoPackageLayer::TranslateFeature( sqlite3_stmt* hStmt )
             poFeature->SetGeometryDirectly( poGeom );
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      set the fields.                                                 */
 /* -------------------------------------------------------------------- */
-    for( iField = 0; iField < m_poFeatureDefn->GetFieldCount(); iField++ )
+    for( int iField = 0; iField < m_poFeatureDefn->GetFieldCount(); iField++ )
     {
         OGRFieldDefn *poFieldDefn = m_poFeatureDefn->GetFieldDefn( iField );
         if ( poFieldDefn->IsIgnored() )
             continue;
 
-        int iRawField = panFieldOrdinals[iField];
+        const int iRawField = panFieldOrdinals[iField];
 
         if( sqlite3_column_type( hStmt, iRawField ) == SQLITE_NULL )
             continue;
@@ -220,17 +220,17 @@ OGRFeature *OGRGeoPackageLayer::TranslateFeature( sqlite3_stmt* hStmt )
         switch( poFieldDefn->GetType() )
         {
             case OFTInteger:
-                poFeature->SetField( iField, 
+                poFeature->SetField( iField,
                     sqlite3_column_int( hStmt, iRawField ) );
                 break;
 
             case OFTInteger64:
-                poFeature->SetField( iField, 
+                poFeature->SetField( iField,
                     sqlite3_column_int64( hStmt, iRawField ) );
                 break;
 
             case OFTReal:
-                poFeature->SetField( iField, 
+                poFeature->SetField( iField,
                     sqlite3_column_double( hStmt, iRawField ) );
                 break;
 
@@ -262,7 +262,7 @@ OGRFeature *OGRGeoPackageLayer::TranslateFeature( sqlite3_stmt* hStmt )
             }
 
             case OFTString:
-                poFeature->SetField( iField, 
+                poFeature->SetField( iField,
                         (const char *) sqlite3_column_text( hStmt, iRawField ) );
                 break;
 
@@ -293,7 +293,7 @@ const char* OGRGeoPackageLayer::GetFIDColumn()
 int OGRGeoPackageLayer::TestCapability ( const char * pszCap )
 {
     if( EQUAL(pszCap,OLCIgnoreFields) )
-        return TRUE; 
+        return TRUE;
     else if ( EQUAL(pszCap, OLCStringsAsUTF8) )
         return m_poDS->GetUTF8();
     else
@@ -320,8 +320,7 @@ void OGRGeoPackageLayer::BuildFeatureDefn( const char *pszLayerName,
 
     panFieldOrdinals = (int *) CPLMalloc( sizeof(int) * nRawColumns );
 
-    int iCol;
-    for( iCol = 0; iCol < nRawColumns; iCol++ )
+    for( int iCol = 0; iCol < nRawColumns; iCol++ )
     {
         OGRFieldDefn    oField( OGRSQLiteParamsUnquote(sqlite3_column_name( hStmt, iCol )),
                                 OFTString );
@@ -360,14 +359,14 @@ void OGRGeoPackageLayer::BuildFeatureDefn( const char *pszLayerName,
         if( nColType == SQLITE_BLOB && m_poFeatureDefn->GetGeomFieldCount() == 0 )
         {
             const int nBytes = sqlite3_column_bytes( hStmt, iCol );
-            if( nBytes > 4 )
+            if( nBytes >= 8 )
             {
-                int iGpkgSize = sqlite3_column_bytes(hStmt, iCol);
                 const GByte* pabyGpkg = (const GByte*)sqlite3_column_blob( hStmt, iCol  );
                 GPkgHeader oHeader;
                 OGRGeometry* poGeom = NULL;
                 int nSRID;
-                if( GPkgHeaderFromWKB(pabyGpkg, &oHeader) == OGRERR_NONE )
+                if( GPkgHeaderFromWKB(pabyGpkg, nBytes, &oHeader) == OGRERR_NONE &&
+                    (poGeom = GPkgGeometryToOGR(pabyGpkg, nBytes, NULL)) != NULL )
                 {
                     OGRGeomFieldDefn oGeomField(oField.GetNameRef(), wkbUnknown);
 
@@ -382,10 +381,11 @@ void OGRGeoPackageLayer::BuildFeatureDefn( const char *pszLayerName,
                     OGRwkbGeometryType eGeomType = wkbUnknown;
                     if( pszDeclType != NULL )
                     {
-                        eGeomType = GPkgGeometryTypeToWKB(pszDeclType, (oHeader.iDims == 3));
-                        if( eGeomType != wkbNone )
-                            oGeomField.SetType( eGeomType );
+                        eGeomType = poGeom->getGeometryType();
+                        oGeomField.SetType( eGeomType );
                     }
+                    delete poGeom;
+                    poGeom = NULL;
 
 #ifdef SQLITE_HAS_COLUMN_METADATA
                     const char* pszTableName = sqlite3_column_table_name( hStmt, iCol );
@@ -406,7 +406,7 @@ void OGRGeoPackageLayer::BuildFeatureDefn( const char *pszLayerName,
                 }
 
                 // Try also spatialite geometry blobs
-                else if( OGRSQLiteLayer::ImportSpatiaLiteGeometry( pabyGpkg, iGpkgSize,
+                else if( OGRSQLiteLayer::ImportSpatiaLiteGeometry( pabyGpkg, nBytes,
                                                                    &poGeom, &nSRID ) == OGRERR_NONE )
                 {
                     OGRGeomFieldDefn oGeomField(oField.GetNameRef(), wkbUnknown);
@@ -419,23 +419,28 @@ void OGRGeoPackageLayer::BuildFeatureDefn( const char *pszLayerName,
                         poSRS->Dereference();
                     }
                     delete poGeom;
+                    poGeom = NULL;
 
                     m_poFeatureDefn->AddGeomFieldDefn(&oGeomField);
                     iGeomCol = iCol;
                     continue;
                 }
+                // Unlikely to have poGeom be valid, but just in case, check
+                // if we need to delete it.
+                if (poGeom != NULL)
+                    delete poGeom;
             }
         }
 
         switch( nColType )
         {
           case SQLITE_INTEGER:
-            if( CSLTestBoolean(CPLGetConfigOption("OGR_PROMOTE_TO_INTEGER64", "FALSE")) )
+            if( CPLTestBool(CPLGetConfigOption("OGR_PROMOTE_TO_INTEGER64", "FALSE")) )
                 oField.SetType( OFTInteger64 );
             else
             {
                 GIntBig nVal = sqlite3_column_int64(hStmt, iCol);
-                if( (GIntBig)(int)nVal == nVal )
+                if( CPL_INT64_FITS_ON_INT32(nVal) )
                     oField.SetType( OFTInteger );
                 else
                     oField.SetType( OFTInteger64 );
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackageselectlayer.cpp b/ogr/ogrsf_frmts/gpkg/ogrgeopackageselectlayer.cpp
index bdb2474..0f6d697 100644
--- a/ogr/ogrsf_frmts/gpkg/ogrgeopackageselectlayer.cpp
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackageselectlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeopackageselectlayer.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrgeopackageselectlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  GeoPackage Translator
  * Purpose:  Implements OGRGeoPackageSelectLayer class
@@ -106,7 +106,8 @@ OGRErr OGRGeoPackageSelectLayer::ResetStatement()
     CPLDebug( "OGR_GPKG", "prepare(%s)", poBehaviour->osSQLCurrent.c_str() );
 #endif
 
-    rc = sqlite3_prepare( m_poDS->GetDB(), poBehaviour->osSQLCurrent, poBehaviour->osSQLCurrent.size(),
+    rc = sqlite3_prepare( m_poDS->GetDB(), poBehaviour->osSQLCurrent,
+                          static_cast<int>(poBehaviour->osSQLCurrent.size()),
                           &m_poQueryStatement, NULL );
 
     if( rc == SQLITE_OK )
@@ -115,8 +116,8 @@ OGRErr OGRGeoPackageSelectLayer::ResetStatement()
     }
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "In ResetStatement(): sqlite3_prepare(%s):\n  %s", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "In ResetStatement(): sqlite3_prepare(%s):\n  %s",
                   poBehaviour->osSQLCurrent.c_str(), sqlite3_errmsg(m_poDS->GetDB()) );
         m_poQueryStatement = NULL;
         return OGRERR_FAILURE;
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackagetablelayer.cpp b/ogr/ogrsf_frmts/gpkg/ogrgeopackagetablelayer.cpp
index f161760..d206e2e 100644
--- a/ogr/ogrsf_frmts/gpkg/ogrgeopackagetablelayer.cpp
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackagetablelayer.cpp
@@ -35,13 +35,13 @@
 
 //----------------------------------------------------------------------
 // SaveExtent()
-// 
+//
 // Write the current contents of the layer envelope down to the
 // gpkg_contents metadata table.
 //
 OGRErr OGRGeoPackageTableLayer::SaveExtent()
 {
-    if ( !m_poDS->GetUpdate() || ! m_bExtentChanged || ! m_poExtent ) 
+    if ( !m_poDS->GetUpdate() || ! m_bExtentChanged || ! m_poExtent )
         return OGRERR_NONE;
 
     sqlite3* poDb = m_poDS->GetDB();
@@ -60,14 +60,14 @@ OGRErr OGRGeoPackageTableLayer::SaveExtent()
 
     OGRErr err = SQLCommand(poDb, pszSQL);
     sqlite3_free(pszSQL);
-    m_bExtentChanged = FALSE;
-    
+    m_bExtentChanged = false;
+
     return err;
 }
 
 //----------------------------------------------------------------------
 // UpdateExtent()
-// 
+//
 // Expand the layer envelope if necessary to reflect the bounds
 // of new features being added to the layer.
 //
@@ -78,13 +78,13 @@ OGRErr OGRGeoPackageTableLayer::UpdateExtent( const OGREnvelope *poExtent )
         m_poExtent = new OGREnvelope( *poExtent );
     }
     m_poExtent->Merge( *poExtent );
-    m_bExtentChanged = TRUE;
+    m_bExtentChanged = true;
     return OGRERR_NONE;
 }
 
 //----------------------------------------------------------------------
 // BuildColumns()
-// 
+//
 // Save a list of columns (fid, geometry, attributes) suitable
 // for use in a SELECT query that retrieves all fields.
 //
@@ -121,38 +121,36 @@ OGRErr OGRGeoPackageTableLayer::BuildColumns()
         panFieldOrdinals[i] = 1 + (iGeomCol >= 0) + i;
     }
 
-    m_soColumns = soColumns;    
-    return OGRERR_NONE;    
+    m_soColumns = soColumns;
+    return OGRERR_NONE;
 }
 
 //----------------------------------------------------------------------
 // IsGeomFieldSet()
-// 
+//
 // Utility method to determine if there is a non-Null geometry
 // in an OGRGeometry.
 //
 OGRBoolean OGRGeoPackageTableLayer::IsGeomFieldSet( OGRFeature *poFeature )
 {
-    if ( poFeature->GetDefnRef()->GetGeomFieldCount() && 
+    if ( poFeature->GetDefnRef()->GetGeomFieldCount() &&
          poFeature->GetGeomFieldRef(0) )
     {
-        return TRUE;        
-    }
-    else
-    {
-        return FALSE;
+        return TRUE;
     }
+
+    return FALSE;
 }
 
 OGRErr OGRGeoPackageTableLayer::FeatureBindParameters( OGRFeature *poFeature,
                                                        sqlite3_stmt *poStmt,
                                                        int *pnColCount,
-                                                       int bAddFID,
-                                                       int bBindNullFields )
+                                                       bool bAddFID,
+                                                       bool bBindNullFields )
 {
     int nColCount = 1;
     int err;
-    
+
     if ( ! (poFeature && poStmt && pnColCount) )
         return OGRERR_FAILURE;
 
@@ -161,6 +159,12 @@ OGRErr OGRGeoPackageTableLayer::FeatureBindParameters( OGRFeature *poFeature,
     if( bAddFID )
     {
         err = sqlite3_bind_int64(poStmt, nColCount++, poFeature->GetFID());
+        if ( err != SQLITE_OK )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "failed to bind FID to statement");
+            return OGRERR_FAILURE;
+        }
     }
 
     /* Bind data values to the statement, here bind the blob for geometry */
@@ -174,7 +178,8 @@ OGRErr OGRGeoPackageTableLayer::FeatureBindParameters( OGRFeature *poFeature,
         {
             size_t szWkb;
             pabyWkb = GPkgGeometryFromOGR(poGeom, m_iSrs, &szWkb);
-            err = sqlite3_bind_blob(poStmt, nColCount++, pabyWkb, szWkb, CPLFree);
+            err = sqlite3_bind_blob(poStmt, nColCount++, pabyWkb,
+                                    static_cast<int>(szWkb), CPLFree);
 
             // FIXME: in case the geometry is a GeometryCollection, we should
             // inspect its subgeometries to see if there's non-linear ones.
@@ -189,18 +194,19 @@ OGRErr OGRGeoPackageTableLayer::FeatureBindParameters( OGRFeature *poFeature,
         if ( err != SQLITE_OK )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "failed to bind geometry to statement");        
-            return OGRERR_FAILURE;            
+                      "failed to bind geometry to statement");
+            return OGRERR_FAILURE;
         }
     }
 
     /* Bind the attributes using appropriate SQLite data types */
-    for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
+    err = SQLITE_OK;
+    for( int i = 0; err == SQLITE_OK && i < poFeatureDefn->GetFieldCount(); i++ )
     {
         if( i == m_iFIDAsRegularColumnIndex )
             continue;
-        OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn(i); 
-        
+        OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn(i);
+
         if( poFeature->IsFieldSet(i) )
         {
             switch(SQLiteFieldFromOGR(poFieldDefn->GetType()))
@@ -298,8 +304,8 @@ OGRErr OGRGeoPackageTableLayer::FeatureBindParameters( OGRFeature *poFeature,
                     }
                     err = sqlite3_bind_text(poStmt, nColCount++, pszVal, nValLengthBytes, SQLITE_TRANSIENT);
                     break;
-                }            
-            }            
+                }
+            }
         }
         else
         {
@@ -307,16 +313,16 @@ OGRErr OGRGeoPackageTableLayer::FeatureBindParameters( OGRFeature *poFeature,
                 err = sqlite3_bind_null(poStmt, nColCount++);
         }
     }
-    
+
     *pnColCount = nColCount;
-    return OGRERR_NONE;
+    return (err == SQLITE_OK) ? OGRERR_NONE : OGRERR_FAILURE;
 }
 
 //----------------------------------------------------------------------
 // FeatureBindUpdateParameters()
-// 
-// Selectively bind the values of an OGRFeature to a prepared 
-// statement, prior to execution. Carefully binds exactly the 
+//
+// Selectively bind the values of an OGRFeature to a prepared
+// statement, prior to execution. Carefully binds exactly the
 // same parameters that have been set up by FeatureGenerateUpdateSQL()
 // as bindable.
 //
@@ -324,44 +330,44 @@ OGRErr OGRGeoPackageTableLayer::FeatureBindUpdateParameters( OGRFeature *poFeatu
 {
 
     int nColCount;
-    OGRErr err = FeatureBindParameters( poFeature, poStmt, &nColCount, FALSE, TRUE );
+    OGRErr err = FeatureBindParameters( poFeature, poStmt, &nColCount, false, true );
     if ( err != OGRERR_NONE )
         return err;
 
     /* Bind the FID to the "WHERE" clause */
-    err = sqlite3_bind_int64(poStmt, nColCount, poFeature->GetFID());    
-    if ( err != SQLITE_OK )
+    int sqlite_err = sqlite3_bind_int64(poStmt, nColCount, poFeature->GetFID());
+    if ( sqlite_err != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "failed to bind FID '" CPL_FRMT_GIB "' to statement", poFeature->GetFID());
-        return OGRERR_FAILURE;       
+        return OGRERR_FAILURE;
     }
-    
+
     return OGRERR_NONE;
 }
 
 
 //----------------------------------------------------------------------
 // FeatureBindInsertParameters()
-// 
-// Selectively bind the values of an OGRFeature to a prepared 
-// statement, prior to execution. Carefully binds exactly the 
+//
+// Selectively bind the values of an OGRFeature to a prepared
+// statement, prior to execution. Carefully binds exactly the
 // same parameters that have been set up by FeatureGenerateInsertSQL()
 // as bindable.
 //
 OGRErr OGRGeoPackageTableLayer::FeatureBindInsertParameters( OGRFeature *poFeature,
                                                              sqlite3_stmt *poStmt,
-                                                             int bAddFID,
-                                                             int bBindNullFields )
-{    
+                                                             bool bAddFID,
+                                                             bool bBindNullFields )
+{
     int nColCount;
     return FeatureBindParameters( poFeature, poStmt, &nColCount, bAddFID, bBindNullFields );
-}   
+}
 
 
 //----------------------------------------------------------------------
 // FeatureGenerateInsertSQL()
-// 
+//
 // Build a SQL INSERT statement that references all the columns in
 // the OGRFeatureDefn, then prepare it for repeated use in a prepared
 // statement. All statements start off with geometry (if it exists)
@@ -370,10 +376,10 @@ OGRErr OGRGeoPackageTableLayer::FeatureBindInsertParameters( OGRFeature *poFeatu
 // column ordering.
 //
 CPLString OGRGeoPackageTableLayer::FeatureGenerateInsertSQL( OGRFeature *poFeature,
-                                                             int bAddFID,
-                                                             int bBindNullFields )
+                                                             bool bAddFID,
+                                                             bool bBindNullFields )
 {
-    OGRBoolean bNeedComma = FALSE;
+    bool bNeedComma = false;
     OGRFeatureDefn *poFeatureDefn = poFeature->GetDefnRef();
 
     if( poFeatureDefn->GetFieldCount() == ((m_iFIDAsRegularColumnIndex >= 0) ? 1 : 0) &&
@@ -389,22 +395,18 @@ CPLString OGRGeoPackageTableLayer::FeatureGenerateInsertSQL( OGRFeature *poFeatu
     osSQLBack = ") VALUES (";
 
     CPLString osSQLColumn;
-    
+
     if( bAddFID )
     {
         osSQLColumn.Printf("\"%s\"", GetFIDColumn());
         osSQLFront += osSQLColumn;
         osSQLBack += "?";
-        bNeedComma = TRUE;
+        bNeedComma = true;
     }
-    
+
     if ( poFeatureDefn->GetGeomFieldCount() )
     {
-        if( !bNeedComma )
-        {
-            bNeedComma = TRUE;
-        }
-        else 
+        if( bNeedComma )
         {
             osSQLFront += ", ";
             osSQLBack += ", ";
@@ -413,7 +415,7 @@ CPLString OGRGeoPackageTableLayer::FeatureGenerateInsertSQL( OGRFeature *poFeatu
         osSQLColumn.Printf("\"%s\"", poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef());
         osSQLFront += osSQLColumn;
         osSQLBack += "?";
-        bNeedComma = TRUE;
+        bNeedComma = true;
     }
 
     /* Add attribute column names (except FID) to the SQL */
@@ -426,9 +428,9 @@ CPLString OGRGeoPackageTableLayer::FeatureGenerateInsertSQL( OGRFeature *poFeatu
 
         if( !bNeedComma )
         {
-            bNeedComma = TRUE;
+            bNeedComma = true;
         }
-        else 
+        else
         {
             osSQLFront += ", ";
             osSQLBack += ", ";
@@ -438,9 +440,9 @@ CPLString OGRGeoPackageTableLayer::FeatureGenerateInsertSQL( OGRFeature *poFeatu
         osSQLFront += osSQLColumn;
         osSQLBack += "?";
     }
-    
+
     osSQLBack += ")";
-    
+
     if( !bNeedComma )
         return CPLSPrintf("INSERT INTO \"%s\" DEFAULT VALUES", m_pszTableName);
 
@@ -450,7 +452,7 @@ CPLString OGRGeoPackageTableLayer::FeatureGenerateInsertSQL( OGRFeature *poFeatu
 
 //----------------------------------------------------------------------
 // FeatureGenerateUpdateSQL()
-// 
+//
 // Build a SQL UPDATE statement that references all the columns in
 // the OGRFeatureDefn, then prepare it for repeated use in a prepared
 // statement. All statements start off with geometry (if it exists)
@@ -461,7 +463,7 @@ CPLString OGRGeoPackageTableLayer::FeatureGenerateInsertSQL( OGRFeature *poFeatu
 //
 CPLString OGRGeoPackageTableLayer::FeatureGenerateUpdateSQL( OGRFeature *poFeature )
 {
-    OGRBoolean bNeedComma = FALSE;
+    bool bNeedComma = false;
     OGRFeatureDefn *poFeatureDefn = poFeature->GetDefnRef();
 
     /* Set up our SQL string basics */
@@ -469,13 +471,13 @@ CPLString OGRGeoPackageTableLayer::FeatureGenerateUpdateSQL( OGRFeature *poFeatu
     osUpdate.Printf("UPDATE \"%s\" SET ", m_pszTableName);
 
     CPLString osSQLColumn;
-    
+
     if ( poFeatureDefn->GetGeomFieldCount() > 0 )
     {
         osSQLColumn.Printf("\"%s\"", poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef());
         osUpdate += osSQLColumn;
         osUpdate += "=?";
-        bNeedComma = TRUE;
+        bNeedComma = true;
     }
 
     /* Add attribute column names (except FID) to the SQL */
@@ -484,15 +486,15 @@ CPLString OGRGeoPackageTableLayer::FeatureGenerateUpdateSQL( OGRFeature *poFeatu
         if( i == m_iFIDAsRegularColumnIndex )
             continue;
         if( !bNeedComma )
-            bNeedComma = TRUE;
-        else 
+            bNeedComma = true;
+        else
             osUpdate += ", ";
 
         osSQLColumn.Printf("\"%s\"", poFeatureDefn->GetFieldDefn(i)->GetNameRef());
         osUpdate += osSQLColumn;
         osUpdate += "=?";
     }
-    
+
     CPLString osWhere;
     osWhere.Printf(" WHERE \"%s\" = ?", m_pszFidColumn);
 
@@ -502,11 +504,11 @@ CPLString OGRGeoPackageTableLayer::FeatureGenerateUpdateSQL( OGRFeature *poFeatu
 
 //----------------------------------------------------------------------
 // ReadTableDefinition()
-// 
-// Initialization routine. Read all the metadata about a table, 
+//
+// Initialization routine. Read all the metadata about a table,
 // starting from just the table name. Reads information from GPKG
-// metadata tables and from SQLite table metadata. Uses it to 
-// populate OGRSpatialReference information and OGRFeatureDefn objects, 
+// metadata tables and from SQLite table metadata. Uses it to
+// populate OGRSpatialReference information and OGRFeatureDefn objects,
 // among others.
 //
 OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(int bIsSpatial)
@@ -514,40 +516,42 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(int bIsSpatial)
     OGRErr err;
     SQLResult oResultTable;
     char* pszSQL;
-    OGRBoolean bReadExtent = FALSE;
+    bool bReadExtent = false;
     sqlite3* poDb = m_poDS->GetDB();
     OGREnvelope oExtent;
     CPLString osGeomColumnName;
     CPLString osGeomColsType;
-    int bHasZ = FALSE;
+    bool bHasZ = false;
+    bool bHasM = false;
 
     /* Check that the table name is registered in gpkg_contents */
     pszSQL = sqlite3_mprintf(
                 "SELECT table_name, data_type, identifier, "
                 "description, min_x, min_y, max_x, max_y, srs_id "
                 "FROM gpkg_contents "
-                "WHERE table_name = '%q'",
-                m_pszTableName);
-                
+                "WHERE table_name = '%q'"
+#ifdef WORKAROUND_SQLITE3_BUGS
+                " OR 0"
+#endif
+                ,m_pszTableName);
+
     SQLResult oResultContents;
     err = SQLQuery(poDb, pszSQL, &oResultContents);
     sqlite3_free(pszSQL);
-    
+
     /* gpkg_contents query has to work */
     /* gpkg_contents.table_name is supposed to be unique */
     if ( err != OGRERR_NONE || oResultContents.nRowCount != 1 )
     {
         if ( err != OGRERR_NONE )
-            CPLError( CE_Failure, CPLE_AppDefined, "%s", oResultContents.pszErrMsg );
-        else if ( oResultContents.nRowCount != 1 )
+            CPLError( CE_Failure, CPLE_AppDefined, "%s", oResultContents.pszErrMsg ? oResultContents.pszErrMsg : "" );
+        else /* if ( oResultContents.nRowCount != 1 ) */
             CPLError( CE_Failure, CPLE_AppDefined, "layer '%s' is not registered in gpkg_contents", m_pszTableName );
-        else
-            CPLError( CE_Failure, CPLE_AppDefined, "error reading gpkg_contents" );
-            
+
         SQLResultFree(&oResultContents);
         return OGRERR_FAILURE;
     }
-    
+
     const char* pszIdentifier = SQLResultGetValue(&oResultContents, 2, 0);
     if( pszIdentifier && strcmp(pszIdentifier, m_pszTableName) != 0 )
         OGRLayer::SetMetadataItem("IDENTIFIER", pszIdentifier);
@@ -561,7 +565,7 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(int bIsSpatial)
         const char *pszMinY = SQLResultGetValue(&oResultContents, 5, 0);
         const char *pszMaxX = SQLResultGetValue(&oResultContents, 6, 0);
         const char *pszMaxY = SQLResultGetValue(&oResultContents, 7, 0);
-        
+
         /* All the extrema have to be non-NULL for this to make sense */
         if ( pszMinX && pszMinY && pszMaxX && pszMaxY )
         {
@@ -569,7 +573,7 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(int bIsSpatial)
             oExtent.MinY = CPLAtof(pszMinY);
             oExtent.MaxX = CPLAtof(pszMaxX);
             oExtent.MaxY = CPLAtof(pszMaxY);
-            bReadExtent = TRUE;
+            bReadExtent = true;
         }
 
         /* Done with info from gpkg_contents now */
@@ -578,10 +582,13 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(int bIsSpatial)
         /* Check that the table name is registered in gpkg_geometry_columns */
         pszSQL = sqlite3_mprintf(
                     "SELECT table_name, column_name, "
-                    "geometry_type_name, srs_id, z "
+                    "geometry_type_name, srs_id, z, m "
                     "FROM gpkg_geometry_columns "
-                    "WHERE table_name = '%q'",
-                    m_pszTableName);
+                    "WHERE table_name = '%q'"
+#ifdef WORKAROUND_SQLITE3_BUGS
+                    " OR 0"
+#endif
+                    ,m_pszTableName);
 
         SQLResult oResultGeomCols;
         err = SQLQuery(poDb, pszSQL, &oResultGeomCols);
@@ -591,7 +598,11 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(int bIsSpatial)
         /* gpkg_geometry_columns.table_name is supposed to be unique */
         if ( err != OGRERR_NONE || oResultGeomCols.nRowCount != 1 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, "%s", oResultGeomCols.pszErrMsg );
+            if ( err != OGRERR_NONE )
+                CPLError( CE_Failure, CPLE_AppDefined, "%s", oResultGeomCols.pszErrMsg ? oResultGeomCols.pszErrMsg : "" );
+            else /* if ( oResultContents.nRowCount != 1 ) */
+                CPLError( CE_Failure, CPLE_AppDefined, "layer '%s' is not registered in gpkg_geometry_columns", m_pszTableName );
+
             SQLResultFree(&oResultGeomCols);
             return OGRERR_FAILURE;
         }
@@ -603,7 +614,8 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(int bIsSpatial)
         if( pszGeomColsType != NULL )
             osGeomColsType = pszGeomColsType;
         m_iSrs = SQLResultGetValueAsInteger(&oResultGeomCols, 3, 0);
-        bHasZ = SQLResultGetValueAsInteger(&oResultGeomCols, 4, 0);
+        bHasZ = CPL_TO_BOOL(SQLResultGetValueAsInteger(&oResultGeomCols, 4, 0));
+        bHasM = CPL_TO_BOOL(SQLResultGetValueAsInteger(&oResultGeomCols, 5, 0));
 
         SQLResultFree(&oResultGeomCols);
     }
@@ -613,7 +625,7 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(int bIsSpatial)
     /* Use the "PRAGMA TABLE_INFO()" call to get table definition */
     /*  #|name|type|notnull|default|pk */
     /*  0|id|integer|0||1 */
-    /*  1|name|varchar|0||0 */    
+    /*  1|name|varchar|0||0 */
     pszSQL = sqlite3_mprintf("pragma table_info('%q')", m_pszTableName);
     err = SQLQuery(poDb, pszSQL, &oResultTable);
     sqlite3_free(pszSQL);
@@ -628,15 +640,15 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(int bIsSpatial)
         SQLResultFree(&oResultTable);
         return OGRERR_FAILURE;
     }
-    
+
     /* Populate feature definition from table description */
     m_poFeatureDefn = new OGRFeatureDefn( m_pszTableName );
     SetDescription( m_poFeatureDefn->GetName() );
     m_poFeatureDefn->SetGeomType(wkbNone);
     m_poFeatureDefn->Reference();
-    
+
     int iRecord;
-    OGRBoolean bFidFound = FALSE;
+    bool bFidFound = false;
 
     for ( iRecord = 0; iRecord < oResultTable.nRowCount; iRecord++ )
     {
@@ -655,19 +667,19 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(int bIsSpatial)
             /* Maybe it's a geometry type? */
             OGRwkbGeometryType oGeomType;
             if( oType > OFTMaxType )
-                oGeomType = GPkgGeometryTypeToWKB(pszType, bHasZ);
+                oGeomType = GPkgGeometryTypeToWKB(pszType, bHasZ, bHasM);
             else
                 oGeomType = wkbUnknown;
             if ( oGeomType != wkbNone )
             {
-                OGRwkbGeometryType oGeomTypeGeomCols = GPkgGeometryTypeToWKB(osGeomColsType.c_str(), bHasZ);
+                OGRwkbGeometryType oGeomTypeGeomCols = GPkgGeometryTypeToWKB(osGeomColsType.c_str(), bHasZ, bHasM);
                 /* Enforce consistency between table and metadata */
                 if( wkbFlatten(oGeomType) == wkbUnknown )
                     oGeomType = oGeomTypeGeomCols;
                 if ( oGeomType != oGeomTypeGeomCols )
                 {
-                    CPLError(CE_Warning, CPLE_AppDefined, 
-                             "geometry column type in '%s.%s' is not consistent with type in gpkg_geometry_columns", 
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "geometry column type in '%s.%s' is not consistent with type in gpkg_geometry_columns",
                              m_pszTableName, pszName);
                 }
 
@@ -688,8 +700,8 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(int bIsSpatial)
                 }
                 else
                 {
-                    CPLError(CE_Failure, CPLE_AppDefined, 
-                             "table '%s' has multiple geometry fields? not legal in gpkg", 
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "table '%s' has multiple geometry fields? not legal in gpkg",
                              m_pszTableName);
                     SQLResultFree(&oResultTable);
                     return OGRERR_FAILURE;
@@ -700,10 +712,10 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(int bIsSpatial)
             {
                 // CPLError( CE_Failure, CPLE_AppDefined, "invalid field type '%s'", pszType );
                 // SQLResultFree(&oResultTable);
-                CPLError(CE_Warning, CPLE_AppDefined, 
+                CPLError(CE_Warning, CPLE_AppDefined,
                          "geometry column '%s' of type '%s' ignored", pszName, pszType);
             }
-            
+
         }
         else
         {
@@ -717,7 +729,7 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(int bIsSpatial)
                 }
                 else
                 {
-                    bFidFound = TRUE;
+                    bFidFound = true;
                     m_pszFidColumn = CPLStrdup(pszName);
                 }
             }
@@ -734,7 +746,7 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(int bIsSpatial)
                     float fSecond;
                     if( oField.GetType() == OFTString &&
                         !EQUAL(pszDefault, "NULL") &&
-                        !EQUALN(pszDefault, "CURRENT_", strlen("CURRENT_")) &&
+                        !STARTS_WITH_CI(pszDefault, "CURRENT_") &&
                         pszDefault[0] != '(' &&
                         pszDefault[0] != '\'' &&
                         CPLGetValueType(pszDefault) == CPL_VALUE_STRING )
@@ -759,7 +771,7 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(int bIsSpatial)
                     }
                     else if( (oField.GetType() == OFTDate || oField.GetType() == OFTDateTime) &&
                              !EQUAL(pszDefault, "NULL") &&
-                             !EQUALN(pszDefault, "CURRENT_", strlen("CURRENT_")) &&
+                             !STARTS_WITH_CI(pszDefault, "CURRENT_") &&
                              pszDefault[0] != '(' &&
                              pszDefault[0] != '\'' &&
                              !(pszDefault[0] >= '0' && pszDefault[0] <= '9') &&
@@ -786,7 +798,7 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(int bIsSpatial)
     /* Wait, we didn't find a FID? Some operations will not be possible */
     if ( ! bFidFound )
     {
-        CPLDebug("GPKG", 
+        CPLDebug("GPKG",
                  "no integer primary key defined for table '%s'", m_pszTableName);
     }
     else
@@ -798,7 +810,7 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(int bIsSpatial)
                             OGRSQLiteEscape(m_pszFidColumn).c_str(),
                             m_pszTableName);
         sqlite3_stmt* hColStmt = NULL;
-        int rc = sqlite3_prepare( poDb, pszSQLStatic, strlen(pszSQLStatic), &hColStmt, NULL ); 
+        int rc = sqlite3_prepare( poDb, pszSQLStatic, -1, &hColStmt, NULL );
         if( rc == SQLITE_OK )
         {
             rc = sqlite3_step( hColStmt );
@@ -821,7 +833,7 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(int bIsSpatial)
 
     /* Update the columns string */
     BuildColumns();
-    
+
     CheckUnknownExtensions();
 
     return OGRERR_NONE;
@@ -839,22 +851,22 @@ OGRGeoPackageTableLayer::OGRGeoPackageTableLayer(
     m_pszTableName = CPLStrdup(pszTableName);
     m_iSrs = 0;
     m_poExtent = NULL;
-    m_bExtentChanged = FALSE;
+    m_bExtentChanged = false;
     m_poQueryStatement = NULL;
     m_poUpdateStatement = NULL;
-    m_bInsertStatementWithFID = FALSE;
+    m_bInsertStatementWithFID = false;
     m_poInsertStatement = NULL;
     m_soColumns = "";
     m_soFilter = "";
-    bDeferedSpatialIndexCreation = FALSE;
+    m_bDeferredSpatialIndexCreation = false;
     m_bHasSpatialIndex = -1;
-    bDropRTreeTable = FALSE;
-    memset(m_anHasGeometryExtension, 0, sizeof(m_anHasGeometryExtension));
-    m_bPreservePrecision = TRUE;
-    m_bTruncateFields = FALSE;
-    m_bDeferredCreation = FALSE;
+    m_bDropRTreeTable = false;
+    memset(m_abHasGeometryExtension, 0, sizeof(m_abHasGeometryExtension)); /* false */
+    m_bPreservePrecision = true;
+    m_bTruncateFields = false;
+    m_bDeferredCreation = false;
     m_iFIDAsRegularColumnIndex = -1;
-    m_bHasReadMetadataFromStorage = FALSE;
+    m_bHasReadMetadataFromStorage = false;
 }
 
 
@@ -867,7 +879,7 @@ OGRGeoPackageTableLayer::~OGRGeoPackageTableLayer()
     if( m_bDeferredCreation )
         RunDeferredCreationIfNecessary();
 
-    if( bDropRTreeTable )
+    if( m_bDropRTreeTable )
     {
         const char* pszT = m_pszTableName;
         const char* pszC =m_poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef();
@@ -911,14 +923,14 @@ OGRErr OGRGeoPackageTableLayer::CreateField( OGRFieldDefn *poField,
     {
         return OGRERR_FAILURE;
     }
-    
+
     int nMaxWidth = 0;
     if( m_bPreservePrecision && poField->GetType() == OFTString )
         nMaxWidth = poField->GetWidth();
     else
         oFieldDefn.SetWidth(0);
     oFieldDefn.SetPrecision(0);
-    
+
     if( m_pszFidColumn != NULL &&
         EQUAL( oFieldDefn.GetNameRef(), m_pszFidColumn ) &&
         oFieldDefn.GetType() != OFTInteger &&
@@ -926,14 +938,14 @@ OGRErr OGRGeoPackageTableLayer::CreateField( OGRFieldDefn *poField,
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Wrong field type for %s",
                  oFieldDefn.GetNameRef());
-        return CE_Failure;
+        return OGRERR_FAILURE;
     }
 
     if( !m_bDeferredCreation )
     {
         CPLString osCommand;
-    
-        osCommand.Printf("ALTER TABLE \"%s\" ADD COLUMN \"%s\" %s", 
+
+        osCommand.Printf("ALTER TABLE \"%s\" ADD COLUMN \"%s\" %s",
                                  m_pszTableName, poField->GetNameRef(),
                                  GPkgFieldFromOGR(poField->GetType(),
                                                   poField->GetSubType(),
@@ -1003,7 +1015,7 @@ OGRErr OGRGeoPackageTableLayer::CreateGeomField( OGRGeomFieldDefn *poGeomFieldIn
                  "Cannot create more than on geometry field in GeoPackage");
         return OGRERR_FAILURE;
     }
-    
+
     OGRwkbGeometryType eType = poGeomFieldIn->GetType();
     if( eType == wkbNone )
     {
@@ -1029,7 +1041,7 @@ OGRErr OGRGeoPackageTableLayer::CreateGeomField( OGRGeomFieldDefn *poGeomFieldIn
     {
         char *pszSQL;
 
-        pszSQL = sqlite3_mprintf("ALTER TABLE \"%s\" ADD COLUMN \"%s\" %s%s", 
+        pszSQL = sqlite3_mprintf("ALTER TABLE \"%s\" ADD COLUMN \"%s\" %s%s",
                                  m_pszTableName, oGeomField.GetNameRef(),
                                  m_poDS->GetGeometryTypeString(oGeomField.GetType()),
                                  !oGeomField.IsNullable() ? " NOT NULL DEFAULT ''" : "");
@@ -1048,12 +1060,12 @@ OGRErr OGRGeoPackageTableLayer::CreateGeomField( OGRGeomFieldDefn *poGeomFieldIn
         if ( err != OGRERR_NONE )
             return OGRERR_FAILURE;
 
-        int bHasASpatialLayers = FALSE;
+        bool bHasASpatialLayers = false;
         for(int i=0;i<m_poDS->GetLayerCount();i++)
         {
             if( m_poDS->GetLayer(i) != this &&
                 m_poDS->GetLayer(i)->GetLayerDefn()->GetGeomFieldCount() == 0 )
-                bHasASpatialLayers = TRUE;
+                bHasASpatialLayers = true;
         }
         if( !bHasASpatialLayers )
         {
@@ -1098,7 +1110,7 @@ OGRErr OGRGeoPackageTableLayer::ICreateFeature( OGRFeature *poFeature )
     /* Substitute default values for null Date/DateTime fields as the standard */
     /* format of SQLite is not the one mandated by GeoPackage */
     poFeature->FillUnsetWithDefault(FALSE, NULL);
-    int bHasDefaultValue = FALSE;
+    bool bHasDefaultValue = false;
     int iField;
     int nFieldCount = m_poFeatureDefn->GetFieldCount();
     for( iField = 0; iField < nFieldCount; iField++ )
@@ -1108,7 +1120,7 @@ OGRErr OGRGeoPackageTableLayer::ICreateFeature( OGRFeature *poFeature )
         const char* pszDefault = poFeature->GetFieldDefnRef(iField)->GetDefault();
         if( pszDefault != NULL )
         {
-            bHasDefaultValue = TRUE;
+            bHasDefaultValue = true;
             break;
         }
     }
@@ -1131,7 +1143,7 @@ OGRErr OGRGeoPackageTableLayer::ICreateFeature( OGRFeature *poFeature )
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
                             "Inconsistent values of FID and field of same name");
-                return CE_Failure;
+                return OGRERR_FAILURE;
             }
         }
     }
@@ -1143,15 +1155,15 @@ OGRErr OGRGeoPackageTableLayer::ICreateFeature( OGRFeature *poFeature )
         sqlite3_finalize(m_poInsertStatement);
         m_poInsertStatement = NULL;
     }
-    
-    if ( ! m_poInsertStatement ) 
+
+    if ( ! m_poInsertStatement )
     {
         /* Construct a SQL INSERT statement from the OGRFeature */
         /* Only work with fields that are set */
-        /* Do not stick values into SQL, use placeholder and bind values later */    
+        /* Do not stick values into SQL, use placeholder and bind values later */
         m_bInsertStatementWithFID = poFeature->GetFID() != OGRNullFID;
         CPLString osCommand = FeatureGenerateInsertSQL(poFeature, m_bInsertStatementWithFID, !bHasDefaultValue);
-        
+
         /* Prepare the SQL into a statement */
         sqlite3 *poDb = m_poDS->GetDB();
         int err = sqlite3_prepare_v2(poDb, osCommand, -1, &m_poInsertStatement, NULL);
@@ -1159,11 +1171,11 @@ OGRErr OGRGeoPackageTableLayer::ICreateFeature( OGRFeature *poFeature )
         {
             m_poInsertStatement = NULL;
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "failed to prepare SQL: %s", osCommand.c_str());        
+                      "failed to prepare SQL: %s", osCommand.c_str());
             return OGRERR_FAILURE;
-        }        
+        }
     }
-    
+
     /* Bind values onto the statement now */
     OGRErr errOgr = FeatureBindInsertParameters(poFeature, m_poInsertStatement,
                                                 m_bInsertStatementWithFID, !bHasDefaultValue);
@@ -1187,12 +1199,12 @@ OGRErr OGRGeoPackageTableLayer::ICreateFeature( OGRFeature *poFeature )
         sqlite3_clear_bindings(m_poInsertStatement);
         sqlite3_finalize(m_poInsertStatement);
         m_poInsertStatement = NULL;
-        return OGRERR_FAILURE; 
+        return OGRERR_FAILURE;
     }
 
     sqlite3_reset(m_poInsertStatement);
     sqlite3_clear_bindings(m_poInsertStatement);
-    
+
     if( bHasDefaultValue )
     {
         sqlite3_finalize(m_poInsertStatement);
@@ -1208,8 +1220,8 @@ OGRErr OGRGeoPackageTableLayer::ICreateFeature( OGRFeature *poFeature )
     }
 
     /* Read the latest FID value */
-    GIntBig nFID;
-    if ( (nFID = sqlite3_last_insert_rowid(m_poDS->GetDB())) )
+    GIntBig nFID = sqlite3_last_insert_rowid(m_poDS->GetDB());
+    if( nFID )
     {
         poFeature->SetFID(nFID);
         if( m_iFIDAsRegularColumnIndex >= 0 )
@@ -1219,7 +1231,7 @@ OGRErr OGRGeoPackageTableLayer::ICreateFeature( OGRFeature *poFeature )
     {
         poFeature->SetFID(OGRNullFID);
     }
-    
+
     /* All done! */
     return OGRERR_NONE;
 }
@@ -1252,7 +1264,7 @@ OGRErr OGRGeoPackageTableLayer::ISetFeature( OGRFeature *poFeature )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
                         "Inconsistent values of FID and field of same name");
-            return CE_Failure;
+            return OGRERR_FAILURE;
         }
     }
 
@@ -1267,15 +1279,15 @@ OGRErr OGRGeoPackageTableLayer::ISetFeature( OGRFeature *poFeature )
         {
             /* Construct a SQL INSERT statement from the OGRFeature */
             /* Only work with fields that are set */
-            /* Do not stick values into SQL, use placeholder and bind values later */    
-            CPLString osCommand = FeatureGenerateInsertSQL(poFeature, TRUE, TRUE);
+            /* Do not stick values into SQL, use placeholder and bind values later */
+            CPLString osCommand = FeatureGenerateInsertSQL(poFeature, true, true);
 
             /* Prepare the SQL into a statement */
             int err = sqlite3_prepare_v2(m_poDS->GetDB(), osCommand, -1, &m_poUpdateStatement, NULL);
             if ( err != SQLITE_OK )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
-                        "failed to prepare SQL: %s", osCommand.c_str());        
+                        "failed to prepare SQL: %s", osCommand.c_str());
                 return OGRERR_FAILURE;
             }
         }
@@ -1291,7 +1303,7 @@ OGRErr OGRGeoPackageTableLayer::ISetFeature( OGRFeature *poFeature )
             return errOgr;
 
         /* Bind values onto the statement now */
-        errOgr = FeatureBindInsertParameters(poFeature, m_poUpdateStatement, TRUE, TRUE);
+        errOgr = FeatureBindInsertParameters(poFeature, m_poUpdateStatement, true, true);
         if ( errOgr != OGRERR_NONE )
             return errOgr;
     }
@@ -1302,7 +1314,7 @@ OGRErr OGRGeoPackageTableLayer::ISetFeature( OGRFeature *poFeature )
         {
             /* Construct a SQL UPDATE statement from the OGRFeature */
             /* Only work with fields that are set */
-            /* Do not stick values into SQL, use placeholder and bind values later */    
+            /* Do not stick values into SQL, use placeholder and bind values later */
             CPLString osCommand = FeatureGenerateUpdateSQL(poFeature);
 
             /* Prepare the SQL into a statement */
@@ -1310,11 +1322,11 @@ OGRErr OGRGeoPackageTableLayer::ISetFeature( OGRFeature *poFeature )
             if ( err != SQLITE_OK )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
-                        "failed to prepare SQL: %s", osCommand.c_str());        
+                        "failed to prepare SQL: %s", osCommand.c_str());
                 return OGRERR_FAILURE;
             }
         }
-        
+
         /* Bind values onto the statement now */
         OGRErr errOgr = FeatureBindUpdateParameters(poFeature, m_poUpdateStatement);
         if ( errOgr != OGRERR_NONE )
@@ -1334,7 +1346,7 @@ OGRErr OGRGeoPackageTableLayer::ISetFeature( OGRFeature *poFeature )
                   sqlite3_errmsg( m_poDS->GetDB() ) );
         sqlite3_reset(m_poUpdateStatement);
         sqlite3_clear_bindings(m_poUpdateStatement);
-        return OGRERR_FAILURE;       
+        return OGRERR_FAILURE;
     }
 
     sqlite3_reset(m_poUpdateStatement);
@@ -1432,10 +1444,10 @@ OGRErr OGRGeoPackageTableLayer::ResetStatement()
     if ( err != SQLITE_OK )
     {
         m_poQueryStatement = NULL;
-        CPLError( CE_Failure, CPLE_AppDefined, "failed to prepare SQL: %s", soSQL.c_str());            
+        CPLError( CE_Failure, CPLE_AppDefined, "failed to prepare SQL: %s", soSQL.c_str());
         return OGRERR_FAILURE;
     }
-    
+
     return OGRERR_NONE;
 }
 
@@ -1472,7 +1484,7 @@ OGRFeature* OGRGeoPackageTableLayer::GetFeature(GIntBig nFID)
         return NULL;
 
     CreateSpatialIndexIfNecessary();
-    
+
     /* Clear out any existing query */
     ResetReading();
 
@@ -1485,13 +1497,13 @@ OGRFeature* OGRGeoPackageTableLayer::GetFeature(GIntBig nFID)
     if ( err != SQLITE_OK )
     {
         m_poQueryStatement = NULL;
-        CPLError( CE_Failure, CPLE_AppDefined, "failed to prepare SQL: %s", soSQL.c_str());            
+        CPLError( CE_Failure, CPLE_AppDefined, "failed to prepare SQL: %s", soSQL.c_str());
         return NULL;
     }
-    
+
     /* Should be only one or zero results */
     err = sqlite3_step(m_poQueryStatement);
-        
+
     /* Nothing left in statement? NULL return indicates to caller */
     /* that there are no features left */
     if ( err == SQLITE_DONE )
@@ -1507,7 +1519,7 @@ OGRFeature* OGRGeoPackageTableLayer::GetFeature(GIntBig nFID)
         }
         return poFeature;
     }
-    
+
     /* Error out on all other return codes */
     return NULL;
 }
@@ -1516,13 +1528,13 @@ OGRFeature* OGRGeoPackageTableLayer::GetFeature(GIntBig nFID)
 /*                        DeleteFeature()                               */
 /************************************************************************/
 
-OGRErr OGRGeoPackageTableLayer::DeleteFeature(GIntBig nFID) 
+OGRErr OGRGeoPackageTableLayer::DeleteFeature(GIntBig nFID)
 {
     if( !m_poDS->GetUpdate() || m_pszFidColumn == NULL )
     {
         return OGRERR_FAILURE;
     }
-    
+
     /* No FID, no answer. */
     if (nFID == OGRNullFID)
     {
@@ -1632,7 +1644,7 @@ OGRErr OGRGeoPackageTableLayer::GetExtent(OGREnvelope *psExtent, int bForce)
     {
         if ( psExtent )
         {
-            *psExtent = *m_poExtent;            
+            *psExtent = *m_poExtent;
         }
         return OGRERR_NONE;
     }
@@ -1648,7 +1660,7 @@ OGRErr OGRGeoPackageTableLayer::GetExtent(OGREnvelope *psExtent, int bForce)
         OGRErr err = OGRLayer::GetExtent(psExtent, bForce);
         if ( err != OGRERR_NONE )
             return err;
-    
+
         if ( ! m_poExtent )
             m_poExtent = new OGREnvelope( *psExtent );
         else
@@ -1692,6 +1704,8 @@ int OGRGeoPackageTableLayer::TestCapability ( const char * pszCap )
     }
     else if( EQUAL(pszCap,OLCCurveGeometries) )
         return TRUE;
+    else if( EQUAL(pszCap,OLCMeasuredGeometries) )
+        return TRUE;
     else
     {
         return OGRGeoPackageLayer::TestCapability(pszCap);
@@ -1704,7 +1718,7 @@ int OGRGeoPackageTableLayer::TestCapability ( const char * pszCap )
 
 void OGRGeoPackageTableLayer::CreateSpatialIndexIfNecessary()
 {
-    if( bDeferedSpatialIndexCreation )
+    if( m_bDeferredSpatialIndexCreation )
     {
         CreateSpatialIndex();
     }
@@ -1714,32 +1728,32 @@ void OGRGeoPackageTableLayer::CreateSpatialIndexIfNecessary()
 /*                       CreateSpatialIndex()                           */
 /************************************************************************/
 
-int OGRGeoPackageTableLayer::CreateSpatialIndex()
+bool OGRGeoPackageTableLayer::CreateSpatialIndex()
 {
     char* pszSQL;
     OGRErr err;
 
     if( m_bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
-        return FALSE;
+        return false;
+
+    m_bDeferredSpatialIndexCreation = false;
 
-    bDeferedSpatialIndexCreation = FALSE;
-    
     if( m_pszFidColumn == NULL )
-        return FALSE;
+        return false;
 
     if( HasSpatialIndex() )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Spatial index already existing");
-        return FALSE;
+        return false;
     }
 
     if( m_poFeatureDefn->GetGeomFieldCount() == 0 )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Spatial index already existing");
-        return FALSE;
+        return false;
     }
     if( m_poDS->CreateExtensionsTableIfNecessary() != OGRERR_NONE )
-        return FALSE;
+        return false;
 
     const char* pszT = m_pszTableName;
     const char* pszC = m_poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef();
@@ -1758,11 +1772,11 @@ int OGRGeoPackageTableLayer::CreateSpatialIndex()
     if( err != OGRERR_NONE )
     {
         m_poDS->SoftRollbackTransaction();
-        return FALSE;
+        return false;
     }
 
     /* Create virtual table */
-    if( !bDropRTreeTable )
+    if( !m_bDropRTreeTable )
     {
         pszSQL = sqlite3_mprintf(
                     "CREATE VIRTUAL TABLE \"rtree_%s_%s\" USING rtree(id, minx, maxx, miny, maxy)",
@@ -1772,10 +1786,10 @@ int OGRGeoPackageTableLayer::CreateSpatialIndex()
         if( err != OGRERR_NONE )
         {
             m_poDS->SoftRollbackTransaction();
-            return FALSE;
+            return false;
         }
     }
-    bDropRTreeTable = FALSE;
+    m_bDropRTreeTable = false;
 
     /* Populate the RTree */
     pszSQL = sqlite3_mprintf(
@@ -1787,7 +1801,7 @@ int OGRGeoPackageTableLayer::CreateSpatialIndex()
     if( err != OGRERR_NONE )
     {
         m_poDS->SoftRollbackTransaction();
-        return FALSE;
+        return false;
     }
 
     /* Define Triggers to Maintain Spatial Index Values */
@@ -1815,7 +1829,7 @@ int OGRGeoPackageTableLayer::CreateSpatialIndex()
     if( err != OGRERR_NONE )
     {
         m_poDS->SoftRollbackTransaction();
-        return FALSE;
+        return false;
     }
 
     /* Conditions: Update of geometry column to non-empty geometry
@@ -1844,7 +1858,7 @@ int OGRGeoPackageTableLayer::CreateSpatialIndex()
     if( err != OGRERR_NONE )
     {
         m_poDS->SoftRollbackTransaction();
-        return FALSE;
+        return false;
     }
 
     /* Conditions: Update of geometry column to empty geometry
@@ -1866,7 +1880,7 @@ int OGRGeoPackageTableLayer::CreateSpatialIndex()
     if( err != OGRERR_NONE )
     {
         m_poDS->SoftRollbackTransaction();
-        return FALSE;
+        return false;
     }
 
     /* Conditions: Update of any column
@@ -1899,7 +1913,7 @@ int OGRGeoPackageTableLayer::CreateSpatialIndex()
     if( err != OGRERR_NONE )
     {
         m_poDS->SoftRollbackTransaction();
-        return FALSE;
+        return false;
     }
 
     /* Conditions: Update of any column
@@ -1922,7 +1936,7 @@ int OGRGeoPackageTableLayer::CreateSpatialIndex()
     if( err != OGRERR_NONE )
     {
         m_poDS->SoftRollbackTransaction();
-        return FALSE;
+        return false;
     }
 
     /* Conditions: Row deleted
@@ -1941,14 +1955,14 @@ int OGRGeoPackageTableLayer::CreateSpatialIndex()
     if( err != OGRERR_NONE )
     {
         m_poDS->SoftRollbackTransaction();
-        return FALSE;
+        return false;
     }
 
     m_poDS->SoftCommitTransaction();
 
-    m_bHasSpatialIndex = TRUE;
+    m_bHasSpatialIndex = true;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -1969,18 +1983,25 @@ void OGRGeoPackageTableLayer::CheckUnknownExtensions()
     if( m_poFeatureDefn->GetGeomFieldCount() == 0 )
     {
         pszSQL = sqlite3_mprintf(
-                    "SELECT extension_name, definition, scope FROM gpkg_extensions WHERE table_name='%q'",
-                    pszT );
+                    "SELECT extension_name, definition, scope FROM gpkg_extensions WHERE table_name='%q'"
+#ifdef WORKAROUND_SQLITE3_BUGS
+                    " OR 0"
+#endif
+                    ,pszT );
     }
     else
     {
         pszSQL = sqlite3_mprintf(
-                    "SELECT extension_name, definition, scope FROM gpkg_extensions WHERE table_name='%q' "
-                    "AND column_name='%q' AND extension_name NOT LIKE 'gpkg_geom_%s' AND extension_name NOT IN "
-                    "('gpkg_rtree_index', 'gpkg_geometry_type_trigger', 'gpkg_srs_id_trigger')",
-                    pszT,
-                    m_poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef(),
-                    m_poDS->GetGeometryTypeString(m_poFeatureDefn->GetGeomFieldDefn(0)->GetType()) );
+                    "SELECT extension_name, definition, scope FROM gpkg_extensions WHERE (table_name='%q' "
+                    "AND column_name='%q' AND extension_name NOT IN ('gpkg_geom_CIRCULARSTRING', "
+                    "'gpkg_geom_COMPOUNDCURVE', 'gpkg_geom_CURVEPOLYGON', 'gpkg_geom_MULTICURVE', "
+                    "'gpkg_geom_MULTISURFACE', 'gpkg_geom_CURVE', 'gpkg_geom_SURFACE', "
+                    "'gpkg_rtree_index', 'gpkg_geometry_type_trigger', 'gpkg_srs_id_trigger'))"
+#ifdef WORKAROUND_SQLITE3_BUGS
+                    " OR 0"
+#endif
+                    ,pszT,
+                    m_poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef() );
     }
     SQLResult oResultTable;
     OGRErr err = SQLQuery(m_poDS->GetDB(), pszSQL, &oResultTable);
@@ -2028,79 +2049,94 @@ void OGRGeoPackageTableLayer::CheckUnknownExtensions()
 /*                     CreateGeometryExtensionIfNecessary()             */
 /************************************************************************/
 
-int OGRGeoPackageTableLayer::CreateGeometryExtensionIfNecessary(OGRwkbGeometryType eGType)
+bool OGRGeoPackageTableLayer::CreateGeometryExtensionIfNecessary(OGRwkbGeometryType eGType)
 {
     eGType = wkbFlatten(eGType);
-    CPLAssert(eGType <= wkbMultiSurface);
-    if( m_anHasGeometryExtension[eGType] )
-        return TRUE;
+    CPLAssert(eGType <= wkbTIN);
+    if( m_abHasGeometryExtension[eGType] )
+        return true;
 
     if( m_poDS->CreateExtensionsTableIfNecessary() != OGRERR_NONE )
-        return FALSE;
+        return false;
 
     const char* pszT = m_pszTableName;
     const char* pszC = m_poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef();
     const char *pszGeometryType = m_poDS->GetGeometryTypeString(eGType);
 
-    /* Register the table in gpkg_extensions */
+    // Check first if the extension isn't registered
     char* pszSQL = sqlite3_mprintf(
-                "INSERT INTO gpkg_extensions "
-                "(table_name,column_name,extension_name,definition,scope) "
-                "VALUES ('%q', '%q', 'gpkg_geom_%s', 'GeoPackage 1.0 Specification Annex J', 'write-only')",
-                pszT, pszC, pszGeometryType);
-    OGRErr err = SQLCommand(m_poDS->GetDB(), pszSQL);
+        "SELECT 1 FROM gpkg_extensions WHERE table_name = '%q' AND "
+        "column_name = '%q' AND extension_name = 'gpkg_geom_%s'",
+         pszT, pszC, pszGeometryType);
+    OGRErr err = OGRERR_NONE;
+    SQLGetInteger(m_poDS->GetDB(), pszSQL, &err);
     sqlite3_free(pszSQL);
-    if ( err != OGRERR_NONE )
-        return FALSE;
 
-    m_anHasGeometryExtension[eGType] = TRUE;
-    return TRUE;
+    if( err != OGRERR_NONE )
+    {
+        /* Register the table in gpkg_extensions */
+        pszSQL = sqlite3_mprintf(
+                    "INSERT INTO gpkg_extensions "
+                    "(table_name,column_name,extension_name,definition,scope) "
+                    "VALUES ('%q', '%q', 'gpkg_geom_%s', 'GeoPackage 1.0 Specification Annex J', 'read-write')",
+                    pszT, pszC, pszGeometryType);
+        err = SQLCommand(m_poDS->GetDB(), pszSQL);
+        sqlite3_free(pszSQL);
+        if ( err != OGRERR_NONE )
+            return false;
+    }
+
+    m_abHasGeometryExtension[eGType] = true;
+    return true;
 }
 
 /************************************************************************/
 /*                        HasSpatialIndex()                             */
 /************************************************************************/
 
-int OGRGeoPackageTableLayer::HasSpatialIndex()
+bool OGRGeoPackageTableLayer::HasSpatialIndex()
 {
     if( m_bHasSpatialIndex >= 0 )
-        return m_bHasSpatialIndex;
-    m_bHasSpatialIndex = FALSE;
+        return CPL_TO_BOOL(m_bHasSpatialIndex);
+    m_bHasSpatialIndex = false;
 
     if( m_poFeatureDefn->GetGeomFieldCount() == 0 ||
         !m_poDS->HasExtensionsTable() )
-        return FALSE;
+        return false;
 
     const char* pszT = m_pszTableName;
     const char* pszC = m_poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef();
 
     /* Check into gpkg_extensions */
     char* pszSQL = sqlite3_mprintf(
-                 "SELECT * FROM gpkg_extensions WHERE table_name='%q' "
-                 "AND column_name='%q' AND extension_name='gpkg_rtree_index'",
-                 pszT, pszC );
+                 "SELECT * FROM gpkg_extensions WHERE (table_name='%q' "
+                 "AND column_name='%q' AND extension_name='gpkg_rtree_index')"
+#ifdef WORKAROUND_SQLITE3_BUGS
+                " OR 0"
+#endif
+                 ,pszT, pszC );
     SQLResult oResultTable;
     OGRErr err = SQLQuery(m_poDS->GetDB(), pszSQL, &oResultTable);
     sqlite3_free(pszSQL);
     if ( err == OGRERR_NONE && oResultTable.nRowCount == 1 )
     {
-        m_bHasSpatialIndex = TRUE;
+        m_bHasSpatialIndex = true;
     }
     SQLResultFree(&oResultTable);
-    
-    return m_bHasSpatialIndex;
+
+    return CPL_TO_BOOL(m_bHasSpatialIndex);
 }
 
 /************************************************************************/
 /*                        DropSpatialIndex()                            */
 /************************************************************************/
 
-int OGRGeoPackageTableLayer::DropSpatialIndex(int bCalledFromSQLFunction)
+bool OGRGeoPackageTableLayer::DropSpatialIndex(bool bCalledFromSQLFunction)
 {
     if( !HasSpatialIndex() )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Spatial index not existing");
-        return FALSE;
+        return false;
     }
 
     const char* pszT = m_pszTableName;
@@ -2118,7 +2154,7 @@ int OGRGeoPackageTableLayer::DropSpatialIndex(int bCalledFromSQLFunction)
         /* We cannot drop a table from a SQLite function call, so we just */
         /* remove the content and memorize that we will have to delete the */
         /* table later */
-        bDropRTreeTable = TRUE;
+        m_bDropRTreeTable = true;
         pszSQL = sqlite3_mprintf("DELETE FROM \"rtree_%s_%s\"", pszT, pszC);
     }
     else
@@ -2152,8 +2188,8 @@ int OGRGeoPackageTableLayer::DropSpatialIndex(int bCalledFromSQLFunction)
     SQLCommand(m_poDS->GetDB(), pszSQL);
     sqlite3_free(pszSQL);
 
-    m_bHasSpatialIndex = FALSE;
-    return TRUE;
+    m_bHasSpatialIndex = false;
+    return true;
 }
 
 /************************************************************************/
@@ -2176,7 +2212,7 @@ void OGRGeoPackageTableLayer::RenameTo(const char* pszDstTableName)
             pszDstTableName, m_pszTableName);
     SQLCommand(m_poDS->GetDB(), pszSQL);
     sqlite3_free(pszSQL);
-    
+
     pszSQL = sqlite3_mprintf(
             "UPDATE gpkg_contents SET table_name = '%s' WHERE table_name = '%s'",
             pszDstTableName, m_pszTableName);
@@ -2211,9 +2247,9 @@ void OGRGeoPackageTableLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
 /*                        HasFastSpatialFilter()                        */
 /************************************************************************/
 
-int OGRGeoPackageTableLayer::HasFastSpatialFilter(int iGeomCol)
+int OGRGeoPackageTableLayer::HasFastSpatialFilter(int iGeomColIn)
 {
-    if( iGeomCol < 0 || iGeomCol >= m_poFeatureDefn->GetGeomFieldCount() )
+    if( iGeomColIn < 0 || iGeomColIn >= m_poFeatureDefn->GetGeomFieldCount() )
         return FALSE;
     return HasSpatialIndex();
 }
@@ -2222,23 +2258,23 @@ int OGRGeoPackageTableLayer::HasFastSpatialFilter(int iGeomCol)
 /*                           GetSpatialWhere()                          */
 /************************************************************************/
 
-CPLString OGRGeoPackageTableLayer::GetSpatialWhere(int iGeomCol,
+CPLString OGRGeoPackageTableLayer::GetSpatialWhere(int iGeomColIn,
                                                OGRGeometry* poFilterGeom)
 {
     CPLString osSpatialWHERE;
 
-    if( iGeomCol < 0 || iGeomCol >= m_poFeatureDefn->GetGeomFieldCount() )
+    if( iGeomColIn < 0 || iGeomColIn >= m_poFeatureDefn->GetGeomFieldCount() )
         return osSpatialWHERE;
 
     const char* pszT = m_pszTableName;
-    const char* pszC = m_poFeatureDefn->GetGeomFieldDefn(iGeomCol)->GetNameRef();
+    const char* pszC = m_poFeatureDefn->GetGeomFieldDefn(iGeomColIn)->GetNameRef();
 
     if( poFilterGeom != NULL )
     {
         OGREnvelope  sEnvelope;
 
         poFilterGeom->getEnvelope( &sEnvelope );
-        
+
         if( CPLIsInf(sEnvelope.MinX) || CPLIsInf(sEnvelope.MinY) ||
             CPLIsInf(sEnvelope.MaxX) || CPLIsInf(sEnvelope.MaxY) )
         {
@@ -2293,7 +2329,7 @@ void OGRGeoPackageTableLayer::BuildWhere()
         {
             m_soFilter += osQuery;
         }
-        else    
+        else
         {
             m_soFilter += " AND (";
             m_soFilter += osQuery;
@@ -2314,7 +2350,7 @@ void OGRGeoPackageTableLayer::SetCreationParameters( OGRwkbGeometryType eGType,
                                                      const char* pszIdentifier,
                                                      const char* pszDescription )
 {
-    m_bDeferredCreation = TRUE;
+    m_bDeferredCreation = true;
     m_pszFidColumn = CPLStrdup(pszFIDColumnName);
     m_poFeatureDefn = new OGRFeatureDefn( m_pszTableName );
     SetDescription( m_poFeatureDefn->GetName() );
@@ -2351,7 +2387,8 @@ OGRErr OGRGeoPackageTableLayer::RegisterGeometryColumn()
     const char *pszGeometryType = m_poDS->GetGeometryTypeString(eGType);
     /* Requirement 27: The z value in a gpkg_geometry_columns table row */
     /* SHALL be one of 0 (none), 1 (mandatory), or 2 (optional) */
-    int bGeometryTypeHasZ = wkbHasZ(eGType);
+    bool bGeometryTypeHasZ = CPL_TO_BOOL(wkbHasZ(eGType));
+    bool bGeometryTypeHasM = CPL_TO_BOOL(wkbHasM(eGType));
 
     /* Update gpkg_geometry_columns with the table info */
     char* pszSQL = sqlite3_mprintf(
@@ -2360,16 +2397,20 @@ OGRErr OGRGeoPackageTableLayer::RegisterGeometryColumn()
         " VALUES "
         "('%q','%q','%q',%d,%d,%d)",
         GetName(),GetGeometryColumn(),pszGeometryType,
-        m_iSrs,bGeometryTypeHasZ,0);
+        m_iSrs,static_cast<int>(bGeometryTypeHasZ),
+        static_cast<int>(bGeometryTypeHasM));
 
     OGRErr err = SQLCommand(m_poDS->GetDB(), pszSQL);
     sqlite3_free(pszSQL);
     if ( err != OGRERR_NONE )
         return OGRERR_FAILURE;
 
-    if( OGR_GT_IsNonLinear( eGType ) )
+    if( OGR_GT_IsNonLinear( eGType ) || wkbFlatten(eGType) == wkbCurve ||
+        wkbFlatten(eGType) == wkbSurface )
+    {
         CreateGeometryExtensionIfNecessary(eGType);
-    
+    }
+
     return OGRERR_NONE;
 }
 
@@ -2381,7 +2422,7 @@ OGRErr OGRGeoPackageTableLayer::RunDeferredCreationIfNecessary()
 {
     if( !m_bDeferredCreation )
         return OGRERR_NONE;
-    m_bDeferredCreation = FALSE;
+    m_bDeferredCreation = false;
 
     const char* pszLayerName = m_poFeatureDefn->GetName();
     OGRwkbGeometryType eGType = GetGeomType();
@@ -2403,7 +2444,7 @@ OGRErr OGRGeoPackageTableLayer::RunDeferredCreationIfNecessary()
             pszLayerName, m_pszFidColumn);
     osCommand += pszSQL;
     sqlite3_free(pszSQL);
-    
+
     if( GetGeomType() != wkbNone )
     {
         pszSQL = sqlite3_mprintf(", '%q' %s",
@@ -2436,8 +2477,8 @@ OGRErr OGRGeoPackageTableLayer::RunDeferredCreationIfNecessary()
         if( pszDefault != NULL &&
             (!poFieldDefn->IsDefaultDriverSpecific() ||
              (pszDefault[0] == '(' && pszDefault[strlen(pszDefault)-1] == ')' &&
-             (EQUALN(pszDefault+1, "strftime", strlen("strftime")) ||
-              EQUALN(pszDefault+1, " strftime", strlen(" strftime"))))) )
+             (STARTS_WITH_CI(pszDefault+1, "strftime") ||
+              STARTS_WITH_CI(pszDefault+1, " strftime")))) )
         {
             osCommand += " DEFAULT ";
             OGRField sField;
@@ -2512,7 +2553,7 @@ char **OGRGeoPackageTableLayer::GetMetadata( const char *pszDomain )
     if( m_bHasReadMetadataFromStorage )
         return OGRLayer::GetMetadata( pszDomain );
 
-    m_bHasReadMetadataFromStorage = TRUE;
+    m_bHasReadMetadataFromStorage = true;
 
     if ( !m_poDS->HasMetadataTables() )
         return OGRLayer::GetMetadata( pszDomain );
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.cpp b/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.cpp
index 175afbf..240e74e 100644
--- a/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.cpp
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.cpp
@@ -26,8 +26,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
- 
- 
+
 #include "ogrgeopackageutility.h"
 #include "ogr_p.h"
 
@@ -40,7 +39,7 @@ OGRErr SQLCommand(sqlite3 * poDb, const char * pszSQL)
     char *pszErrMsg = NULL;
     //CPLDebug("GPKG", "exec(%s)", pszSQL);
     int rc = sqlite3_exec(poDb, pszSQL, NULL, NULL, &pszErrMsg);
-    
+
     if ( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -49,7 +48,7 @@ OGRErr SQLCommand(sqlite3 * poDb, const char * pszSQL)
         sqlite3_free( pszErrMsg );
         return OGRERR_FAILURE;
     }
-    
+
     return OGRERR_NONE;
 }
 
@@ -75,14 +74,14 @@ OGRErr SQLQuery(sqlite3 * poDb, const char * pszSQL, SQLResult * poResult)
 
     poResult->rc = sqlite3_get_table(
         poDb, pszSQL,
-        &(poResult->papszResult), 
-        &(poResult->nRowCount), 
-        &(poResult->nColCount), 
+        &(poResult->papszResult),
+        &(poResult->nRowCount),
+        &(poResult->nColCount),
         &(poResult->pszErrMsg) );
-    
+
     if( poResult->rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "sqlite3_get_table(%s) failed: %s", pszSQL, poResult->pszErrMsg );
         return OGRERR_FAILURE;
     }
@@ -98,52 +97,52 @@ OGRErr SQLResultFree(SQLResult * poResult)
 
     if ( poResult->pszErrMsg )
         sqlite3_free(poResult->pszErrMsg);
-        
+
     return OGRERR_NONE;
 }
 
 const char* SQLResultGetColumn(const SQLResult * poResult, int iColNum)
 {
-    if ( ! poResult ) 
+    if ( ! poResult )
         return NULL;
-        
+
     if ( iColNum < 0 || iColNum >= poResult->nColCount )
         return NULL;
-    
+
     return poResult->papszResult[iColNum];
 }
 
 const char* SQLResultGetValue(const SQLResult * poResult, int iColNum, int iRowNum)
 {
-    if ( ! poResult ) 
+    if ( ! poResult )
         return NULL;
 
     int nCols = poResult->nColCount;
-    int nRows = poResult->nRowCount;    
-        
+    int nRows = poResult->nRowCount;
+
     if ( iColNum < 0 || iColNum >= nCols )
         return NULL;
 
     if ( iRowNum < 0 || iRowNum >= nRows )
         return NULL;
-        
+
     return poResult->papszResult[ nCols + iRowNum * nCols + iColNum ];
 }
 
 int SQLResultGetValueAsInteger(const SQLResult * poResult, int iColNum, int iRowNum)
 {
-    if ( ! poResult ) 
+    if ( ! poResult )
         return 0;
-        
+
     int nCols = poResult->nColCount;
     int nRows = poResult->nRowCount;
-    
+
     if ( iColNum < 0 || iColNum >= nCols )
         return 0;
 
     if ( iRowNum < 0 || iRowNum >= nRows )
         return 0;
-    
+
     char *pszValue = poResult->papszResult[ nCols + iRowNum * nCols + iColNum ];
     if ( ! pszValue )
         return 0;
@@ -155,13 +154,13 @@ int SQLResultGetValueAsInteger(const SQLResult * poResult, int iColNum, int iRow
 GIntBig SQLGetInteger64(sqlite3 * poDb, const char * pszSQL, OGRErr *err)
 {
     CPLAssert( poDb != NULL );
-    
+
     sqlite3_stmt *poStmt;
     int rc;
     GIntBig i;
-    
+
     /* Prepare the SQL */
-    rc = sqlite3_prepare_v2(poDb, pszSQL, strlen(pszSQL), &poStmt, NULL);
+    rc = sqlite3_prepare_v2(poDb, pszSQL, -1, &poStmt, NULL);
     if ( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined, "sqlite3_prepare_v2(%s) failed: %s",
@@ -169,7 +168,7 @@ GIntBig SQLGetInteger64(sqlite3 * poDb, const char * pszSQL, OGRErr *err)
         if ( err ) *err = OGRERR_FAILURE;
         return 0;
     }
-    
+
     /* Execute and fetch first row */
     rc = sqlite3_step(poStmt);
     if ( rc != SQLITE_ROW )
@@ -178,11 +177,11 @@ GIntBig SQLGetInteger64(sqlite3 * poDb, const char * pszSQL, OGRErr *err)
         sqlite3_finalize(poStmt);
         return 0;
     }
-    
+
     /* Read the integer from the row */
     i = sqlite3_column_int64(poStmt, 0);
     sqlite3_finalize(poStmt);
-    
+
     if ( err ) *err = OGRERR_NONE;
     return i;
 }
@@ -197,7 +196,7 @@ int SQLGetInteger(sqlite3 * poDb, const char * pszSQL, OGRErr *err)
 /* LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon, */
 /* GeomCollection) */
 /* http://opengis.github.io/geopackage/#geometry_types */
-OGRwkbGeometryType GPkgGeometryTypeToWKB(const char *pszGpkgType, int bHasZ)
+OGRwkbGeometryType GPkgGeometryTypeToWKB(const char *pszGpkgType, bool bHasZ, bool bHasM)
 {
     OGRwkbGeometryType oType;
 
@@ -218,6 +217,10 @@ OGRwkbGeometryType GPkgGeometryTypeToWKB(const char *pszGpkgType, int bHasZ)
     {
         oType = wkbSetZ(oType);
     }
+    if ( (oType != wkbNone) && bHasM )
+    {
+        oType = wkbSetM(oType);
+    }
 
     return oType;
 }
@@ -260,7 +263,7 @@ OGRFieldType GPkgFieldToOGR(const char *pszGpkgType, OGRFieldSubType& eSubType,
         return OFTReal;
     else if ( EQUAL("REAL", pszGpkgType) )
         return OFTReal;
-        
+
     /* String/binary types */
     else if ( STRNCASECMP("TEXT", pszGpkgType, 4) == 0 )
     {
@@ -268,10 +271,10 @@ OGRFieldType GPkgFieldToOGR(const char *pszGpkgType, OGRFieldSubType& eSubType,
             nMaxWidth = atoi(pszGpkgType+5);
         return OFTString;
     }
-        
+
     else if ( STRNCASECMP("BLOB", pszGpkgType, 4) == 0 )
         return OFTBinary;
-        
+
     /* Date types */
     else if ( EQUAL("DATE", pszGpkgType) )
         return OFTDate;
@@ -279,7 +282,7 @@ OGRFieldType GPkgFieldToOGR(const char *pszGpkgType, OGRFieldSubType& eSubType,
         return OFTDateTime;
 
     /* Illegal! */
-    else 
+    else
         return (OGRFieldType)(OFTMaxType + 1);
 }
 
@@ -353,24 +356,24 @@ int SQLiteFieldFromOGR(OGRFieldType nType)
 
 
 
-/* Requirement 19: A GeoPackage SHALL store feature table geometries 
-*  with or without optional elevation (Z) and/or measure (M) values in SQL 
-*  BLOBs using the Standard GeoPackageBinary format specified in table GeoPackage 
+/* Requirement 19: A GeoPackage SHALL store feature table geometries
+*  with or without optional elevation (Z) and/or measure (M) values in SQL
+*  BLOBs using the Standard GeoPackageBinary format specified in table GeoPackage
 *  SQL Geometry Binary Format and clause Geometry Encoding.
 *
 *  http://opengis.github.io/geopackage/#gpb_format
 *
 *   GeoPackageBinaryHeader {
-*     byte[2] magic = 0x4750; 
-*     byte version;           
-*     byte flags;             
+*     byte[2] magic = 0x4750;
+*     byte version;
+*     byte flags;
 *     int32 srs_id;
-*     double[] envelope;      
+*     double[] envelope;
 *    }
-* 
+*
 *   StandardGeoPackageBinary {
-*     GeoPackageBinaryHeader header; 
-*     WKBGeometry geometry;          
+*     GeoPackageBinaryHeader header;
+*     WKBGeometry geometry;
 *   }
 *
 *  Flags byte contents:
@@ -386,7 +389,7 @@ int SQLiteFieldFromOGR(OGRFieldType nType)
 GByte* GPkgGeometryFromOGR(const OGRGeometry *poGeometry, int iSrsId, size_t *pszWkb)
 {
     CPLAssert( poGeometry != NULL );
-    
+
     GByte *pabyPtr;
     GByte byFlags = 0;
     GByte byEnv = 1;
@@ -394,43 +397,45 @@ GByte* GPkgGeometryFromOGR(const OGRGeometry *poGeometry, int iSrsId, size_t *ps
     OGRErr err;
     OGRBoolean bPoint = (wkbFlatten(poGeometry->getGeometryType()) == wkbPoint);
     OGRBoolean bEmpty = poGeometry->IsEmpty();
+    /* We voluntarily use getCoordinateDimension() so as to get only 2 for XY/XYM */
+    /* and 3 for XYZ/XYZM as we currently don't write envelopes with M extent. */
     int iDims = poGeometry->getCoordinateDimension();
 
     /* Header has 8 bytes for sure, and optional extra space for bounds */
-    size_t szHeader = 2+1+1+4;    
+    size_t szHeader = 2+1+1+4;
     if ( ! bPoint && ! bEmpty )
     {
         szHeader += 8*2*iDims;
     }
-    
+
     /* Total BLOB size is header + WKB size */
     size_t szWkb = szHeader + poGeometry->WkbSize();
     GByte *pabyWkb = (GByte *)CPLMalloc(szWkb);
     if (pszWkb)
         *pszWkb = szWkb;
-    
+
     /* Header Magic */
     pabyWkb[0] = 0x47;
     pabyWkb[1] = 0x50;
 
     /* GPKG BLOB Version */
     pabyWkb[2] = 0;
-    
+
     /* Extended? No. */
 
     /* Envelope dimensionality? */
 
     /* Don't write envelope for point type */
     if ( bPoint )
-        byEnv = 0; 
+        byEnv = 0;
     else
-        /* 3D envelope for 3D data */      
+        /* 3D envelope for 3D data */
         if ( iDims == 3 )
             byEnv = 2;
-        /* 2D envelope otherwise */      
+        /* 2D envelope otherwise */
         else
             byEnv = 1;
-    
+
     /* Empty? No envelope then. */
     if ( bEmpty )
     {
@@ -438,7 +443,7 @@ GByte* GPkgGeometryFromOGR(const OGRGeometry *poGeometry, int iSrsId, size_t *ps
         /* Set empty flag */
         byFlags |= (1 << 4);
     }
-    
+
     /* Set envelope flags */
     byFlags |= (byEnv << 1);
 
@@ -448,10 +453,10 @@ GByte* GPkgGeometryFromOGR(const OGRGeometry *poGeometry, int iSrsId, size_t *ps
 
     /* Write flags byte */
     pabyWkb[3] = byFlags;
-    
+
     /* Write srs_id */
     memcpy(pabyWkb+4, &iSrsId, 4);
-    
+
     /* Write envelope */
     if ( ! bEmpty && ! bPoint )
     {
@@ -477,9 +482,9 @@ GByte* GPkgGeometryFromOGR(const OGRGeometry *poGeometry, int iSrsId, size_t *ps
             padPtr[3] = oEnv.MaxY;
         }
     }
-    
+
     pabyPtr = pabyWkb + szHeader;
-    
+
     /* Use the wkbVariantIso for ISO SQL/MM output (differs for 3d geometry) */
     err = poGeometry->exportToWkb(eByteOrder, pabyPtr, wkbVariantIso);
     if ( err != OGRERR_NONE )
@@ -487,18 +492,19 @@ GByte* GPkgGeometryFromOGR(const OGRGeometry *poGeometry, int iSrsId, size_t *ps
         CPLFree(pabyWkb);
         return NULL;
     }
-    
-    return pabyWkb; 
+
+    return pabyWkb;
 }
 
 
-OGRErr GPkgHeaderFromWKB(const GByte *pabyGpkg, GPkgHeader *poHeader)
+OGRErr GPkgHeaderFromWKB(const GByte *pabyGpkg, size_t szGpkg, GPkgHeader *poHeader)
 {
     CPLAssert( pabyGpkg != NULL );
     CPLAssert( poHeader != NULL );
 
     /* Magic (match required) */
-    if ( pabyGpkg[0] != 0x47 || 
+    if ( szGpkg < 8 ||
+         pabyGpkg[0] != 0x47 ||
          pabyGpkg[1] != 0x50 ||
          pabyGpkg[2] != 0 )  /* Version (only 0 supported at this time)*/
     {
@@ -510,29 +516,63 @@ OGRErr GPkgHeaderFromWKB(const GByte *pabyGpkg, GPkgHeader *poHeader)
     poHeader->bEmpty = (byFlags & (0x01 << 4)) >> 4;
     poHeader->bExtended = (byFlags & (0x01 << 5)) >> 5;
     poHeader->eByteOrder = (OGRwkbByteOrder)(byFlags & 0x01);
+    poHeader->bExtentHasXY = false;
+    poHeader->bExtentHasZ = false;
+#ifdef notdef
+    poHeader->bExtentHasM = false;
+#endif
     OGRBoolean bSwap = OGR_SWAP(poHeader->eByteOrder);
 
     /* Envelope */
     int iEnvelope = (byFlags & (0x07 << 1)) >> 1;
-    if ( iEnvelope == 1 )
-        poHeader->iDims = 2; /* 2D envelope */
-    else if ( iEnvelope == 2 )
-        poHeader->iDims = 3; /* 3D envelope */
-    else 
-        poHeader->iDims = 0; /* No envelope */
+    int nEnvelopeDim = 0;
+    if( iEnvelope )
+    {
+        poHeader->bExtentHasXY = true;
+        if( iEnvelope == 1 )
+        {
+            nEnvelopeDim = 2; /* 2D envelope */
+        }
+        else if ( iEnvelope == 2 )
+        {
+            poHeader->bExtentHasZ = true;
+            nEnvelopeDim = 3; /* 2D+Z envelope */
+        }
+        else if ( iEnvelope == 3 )
+        {
+#ifdef notdef
+            poHeader->bExtentHasM = true;
+#endif
+            nEnvelopeDim = 3; /* 2D+M envelope */
+        }
+        else if ( iEnvelope == 4 )
+        {
+            poHeader->bExtentHasZ = true;
+#ifdef notdef
+            poHeader->bExtentHasM = true;
+#endif
+            nEnvelopeDim = 4; /* 2D+ZM envelope */
+        }
+    }
 
     /* SrsId */
     int iSrsId;
-    memcpy(&iSrsId, pabyGpkg+4, 4);    
+    memcpy(&iSrsId, pabyGpkg+4, 4);
     if ( bSwap )
     {
         iSrsId = CPL_SWAP32(iSrsId);
     }
     poHeader->iSrsId = iSrsId;
-    
+
+    if( szGpkg < static_cast<size_t>(8 + 8*2*nEnvelopeDim) )
+    {
+        // Not enough bytes
+        return OGRERR_FAILURE;
+    }
+
     /* Envelope */
     double *padPtr = (double*)(pabyGpkg+8);
-    if ( poHeader->iDims >= 2 )
+    if ( poHeader->bExtentHasXY )
     {
         poHeader->MinX = padPtr[0];
         poHeader->MaxX = padPtr[1];
@@ -546,7 +586,7 @@ OGRErr GPkgHeaderFromWKB(const GByte *pabyGpkg, GPkgHeader *poHeader)
             CPL_SWAPDOUBLE(&(poHeader->MaxY));
         }
     }
-    if ( poHeader->iDims == 3 )
+    if ( poHeader->bExtentHasZ )
     {
         poHeader->MinZ = padPtr[4];
         poHeader->MaxZ = padPtr[5];
@@ -556,22 +596,34 @@ OGRErr GPkgHeaderFromWKB(const GByte *pabyGpkg, GPkgHeader *poHeader)
             CPL_SWAPDOUBLE(&(poHeader->MaxZ));
         }
     }
-    
+#ifdef notdef
+    if ( poHeader->bExtentHasM )
+    {
+        poHeader->MinM = padPtr[ ( poHeader->bExtentHasZ ) ? 6 : 4 ];
+        poHeader->MaxM = padPtr[ ( poHeader->bExtentHasZ ) ? 7 : 5 ];
+        if ( bSwap )
+        {
+            CPL_SWAPDOUBLE(&(poHeader->MinM));
+            CPL_SWAPDOUBLE(&(poHeader->MaxM));
+        }
+    }
+#endif
+
     /* Header size in byte stream */
-    poHeader->szHeader = 8 + 8*2*(poHeader->iDims);
-    
+    poHeader->szHeader = 8 + 8*2*nEnvelopeDim;
+
     return OGRERR_NONE;
 }
 
 OGRGeometry* GPkgGeometryToOGR(const GByte *pabyGpkg, size_t szGpkg, OGRSpatialReference *poSrs)
 {
     CPLAssert( pabyGpkg != NULL );
-    
+
     GPkgHeader oHeader;
     OGRGeometry *poGeom;
-    
+
     /* Read header */
-    OGRErr err = GPkgHeaderFromWKB(pabyGpkg, &oHeader);
+    OGRErr err = GPkgHeaderFromWKB(pabyGpkg, szGpkg, &oHeader);
     if ( err != OGRERR_NONE )
         return NULL;
 
@@ -580,7 +632,8 @@ OGRGeometry* GPkgGeometryToOGR(const GByte *pabyGpkg, size_t szGpkg, OGRSpatialR
     size_t szWkb = szGpkg - oHeader.szHeader;
 
     /* Parse WKB */
-    err = OGRGeometryFactory::createFromWkb((GByte*)pabyWkb, poSrs, &poGeom, szWkb);
+    err = OGRGeometryFactory::createFromWkb((GByte*)pabyWkb, poSrs, &poGeom,
+                                            static_cast<int>(szWkb));
     if ( err != OGRERR_NONE )
         return NULL;
 
@@ -589,7 +642,7 @@ OGRGeometry* GPkgGeometryToOGR(const GByte *pabyGpkg, size_t szGpkg, OGRSpatialR
 
 
 OGRErr GPkgEnvelopeToOGR(GByte *pabyGpkg,
-                         CPL_UNUSED size_t szGpkg,
+                         size_t szGpkg,
                          OGREnvelope *poEnv)
 {
     CPLAssert( poEnv != NULL );
@@ -598,25 +651,19 @@ OGRErr GPkgEnvelopeToOGR(GByte *pabyGpkg,
     GPkgHeader oHeader;
 
     /* Read header */
-    OGRErr err = GPkgHeaderFromWKB(pabyGpkg, &oHeader);
+    OGRErr err = GPkgHeaderFromWKB(pabyGpkg, szGpkg, &oHeader);
     if ( err != OGRERR_NONE )
         return err;
 
-    if ( oHeader.bEmpty || oHeader.iDims == 0 )
+    if ( oHeader.bEmpty || !oHeader.bExtentHasXY )
     {
         return OGRERR_FAILURE;
     }
-    
+
     poEnv->MinX = oHeader.MinX;
     poEnv->MaxX = oHeader.MaxX;
     poEnv->MinY = oHeader.MinY;
     poEnv->MaxY = oHeader.MaxY;
-    
-    // if ( oHeader.iDims == 3 )
-    // {
-    //     poEnv->MinZ = oHeader.MinZ;
-    //     poEnv->MaxZ = oHeader.MaxZ;
-    // }
-    
+
     return OGRERR_NONE;
 }
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.h b/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.h
index bad3894..93f9e76 100644
--- a/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.h
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.h
@@ -30,10 +30,10 @@
 #include "ogrsf_frmts.h"
 #include "sqlite3.h"
 
-#ifndef _OGR_GEOPACKAGEUTILITY_H_INCLUDED
-#define _OGR_GEOPACKAGEUTILITY_H_INCLUDED
+#ifndef OGR_GEOPACKAGEUTILITY_H_INCLUDED
+#define OGR_GEOPACKAGEUTILITY_H_INCLUDED
 
-typedef struct 
+typedef struct
 {
     char** papszResult;
     int nRowCount;
@@ -42,14 +42,21 @@ typedef struct
     int rc;
 } SQLResult;
 
-typedef struct 
+typedef struct
 {
     OGRBoolean bEmpty;
     OGRBoolean bExtended;
     OGRwkbByteOrder eByteOrder;
     int iSrsId;
-    int iDims;
+    bool bExtentHasXY;
+    bool bExtentHasZ;
+#ifdef notdef
+    bool bExtentHasM;
+#endif
     double MinX, MaxX, MinY, MaxY, MinZ, MaxZ;
+#ifdef notdef
+    double MinM, MaxM;
+#endif
     size_t szHeader;
 } GPkgHeader;
 
@@ -69,12 +76,12 @@ int                 SQLiteFieldFromOGR(OGRFieldType nType);
 
 OGRFieldType        GPkgFieldToOGR(const char *pszGpkgType, OGRFieldSubType& eSubType, int& nMaxWidth);
 const char*         GPkgFieldFromOGR(OGRFieldType nType, OGRFieldSubType eSubType, int nMaxWidth);
-OGRwkbGeometryType  GPkgGeometryTypeToWKB(const char *pszGpkgType, int bHasZ);
+OGRwkbGeometryType  GPkgGeometryTypeToWKB(const char *pszGpkgType, bool bHasZ, bool bHasM);
 
 GByte*              GPkgGeometryFromOGR(const OGRGeometry *poGeometry, int iSrsId, size_t *szWkb);
 OGRGeometry*        GPkgGeometryToOGR(const GByte *pabyGpkg, size_t szGpkg, OGRSpatialReference *poSrs);
 OGRErr              GPkgEnvelopeToOGR(GByte *pabyGpkg, size_t szGpkg, OGREnvelope *poEnv);
 
-OGRErr              GPkgHeaderFromWKB(const GByte *pabyGpkg, GPkgHeader *poHeader);
+OGRErr              GPkgHeaderFromWKB(const GByte *pabyGpkg, size_t szGpkg, GPkgHeader *poHeader);
 
-#endif
\ No newline at end of file
+#endif
diff --git a/ogr/ogrsf_frmts/gpsbabel/ogr_gpsbabel.h b/ogr/ogrsf_frmts/gpsbabel/ogr_gpsbabel.h
index 1db5306..45cca08 100644
--- a/ogr/ogrsf_frmts/gpsbabel/ogr_gpsbabel.h
+++ b/ogr/ogrsf_frmts/gpsbabel/ogr_gpsbabel.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_gpsbabel.h 29172 2015-05-07 22:15:24Z rouault $
+ * $Id: ogr_gpsbabel.h 32577 2015-12-31 06:39:56Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/GPSBabel driver.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_GPSBABEL_H_INCLUDED
-#define _OGR_GPSBABEL_H_INCLUDED
+#ifndef OGR_GPSBABEL_H_INCLUDED
+#define OGR_GPSBABEL_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "cpl_string.h"
@@ -100,5 +100,4 @@ class OGRGPSBabelWriteDataSource : public OGRDataSource
     int                 Create ( const char* pszFilename, char **papszOptions );
 };
 
-#endif /* ndef _OGR_GPSBABEL_H_INCLUDED */
-
+#endif /* ndef OGR_GPSBABEL_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldatasource.cpp b/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldatasource.cpp
index 7719727..95d0af9 100644
--- a/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldatasource.cpp
+++ b/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgpsbabeldatasource.cpp 29177 2015-05-09 19:29:02Z rouault $
+ * $Id: ogrgpsbabeldatasource.cpp 32982 2016-01-14 16:53:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGPSBabelDataSource class.
@@ -27,28 +27,31 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_gpsbabel.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
 #include "cpl_error.h"
 #include "cpl_spawn.h"
+#include "ogr_gpsbabel.h"
 
-#include <string.h>
+#include <cstring>
 
-CPL_CVSID("$Id: ogrgpsbabeldatasource.cpp 29177 2015-05-09 19:29:02Z rouault $");
+CPL_CVSID("$Id: ogrgpsbabeldatasource.cpp 32982 2016-01-14 16:53:57Z goatbar $");
 
 /************************************************************************/
 /*                      OGRGPSBabelDataSource()                         */
 /************************************************************************/
 
-OGRGPSBabelDataSource::OGRGPSBabelDataSource()
-
+OGRGPSBabelDataSource::OGRGPSBabelDataSource() :
+    nLayers(0),
+    pszName(NULL),
+    pszGPSBabelDriverName(NULL),
+    pszFilename(NULL),
+    poGPXDS(NULL)
 {
-    nLayers = 0;
-    pszName = NULL;
-    pszGPSBabelDriverName = NULL;
-    pszFilename = NULL;
-    poGPXDS = NULL;
+  for(int i=0; i<5; ++i)
+  {
+    apoLayers[i] = NULL;
+  }
 }
 
 /************************************************************************/
@@ -61,9 +64,9 @@ OGRGPSBabelDataSource::~OGRGPSBabelDataSource()
     CPLFree(pszName);
     CPLFree(pszGPSBabelDriverName);
     CPLFree(pszFilename);
-    
+
     CloseDependentDatasets();
-    
+
     if (osTmpFileName.size() > 0)
         VSIUnlink(osTmpFileName.c_str());
 }
@@ -74,26 +77,23 @@ OGRGPSBabelDataSource::~OGRGPSBabelDataSource()
 
 int OGRGPSBabelDataSource::CloseDependentDatasets()
 {
-    int bRet = FALSE;
-    if (poGPXDS)
-    {
-        bRet = TRUE;
-        GDALClose( (GDALDatasetH) poGPXDS );
-        poGPXDS = NULL;
-    }
-    return bRet;
+    if( poGPXDS == NULL )
+        return FALSE;
+
+    GDALClose( poGPXDS );
+    poGPXDS = NULL;
+    return TRUE;
 }
 
 /************************************************************************/
 /*                             GetArgv()                                */
 /************************************************************************/
 
-static char** GetArgv(int bExplicitFeatures, int bWaypoints, int bRoutes,
-                      int bTracks, const char* pszGPSBabelDriverName,
-                      const char* pszFilename)
+static char** GetArgv( int bExplicitFeatures, int bWaypoints, int bRoutes,
+                       int bTracks, const char* pszGPSBabelDriverName,
+                       const char* pszFilename )
 {
-    char** argv = NULL;
-    argv = CSLAddString(argv, "gpsbabel");
+    char** argv = CSLAddString(NULL, "gpsbabel");
     if (bExplicitFeatures)
     {
         if (bWaypoints) argv = CSLAddString(argv, "-w");
@@ -118,9 +118,9 @@ static char** GetArgv(int bExplicitFeatures, int bWaypoints, int bRoutes,
 
 int OGRGPSBabelDataSource::IsSpecialFile(const char* pszFilename)
 {
-    return (strncmp(pszFilename, "/dev/", 5) == 0 ||
-            strncmp(pszFilename, "usb:", 4) == 0 ||
-            (strncmp(pszFilename, "COM", 3) == 0  && atoi(pszFilename + 3) > 0));
+    return (STARTS_WITH(pszFilename, "/dev/") ||
+            STARTS_WITH(pszFilename, "usb:") ||
+            (STARTS_WITH(pszFilename, "COM")  && atoi(pszFilename + 3) > 0));
 }
 
 /************************************************************************/
@@ -129,15 +129,16 @@ int OGRGPSBabelDataSource::IsSpecialFile(const char* pszFilename)
 
 int OGRGPSBabelDataSource::IsValidDriverName(const char* pszGPSBabelDriverName)
 {
-    int i;
-    for(i=0;pszGPSBabelDriverName[i] != '\0';i++)
+    for( int i = 0; pszGPSBabelDriverName[i] != '\0'; i++ )
     {
         char ch = pszGPSBabelDriverName[i];
-        if (!((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') ||
-            (ch >= '0' && ch <= '9') || ch == '_' || ch == '=' || ch == '.'  || ch == ','))
+        if( !((ch >= 'A' && ch <= 'Z') ||
+              (ch >= 'a' && ch <= 'z') ||
+              (ch >= '0' && ch <= '9') ||
+              ch == '_' || ch == '=' || ch == '.'  || ch == ',') )
         {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                "Invalid GPSBabel driver name");
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Invalid GPSBabel driver name");
             return FALSE;
         }
     }
@@ -150,13 +151,10 @@ int OGRGPSBabelDataSource::IsValidDriverName(const char* pszGPSBabelDriverName)
 
 int OGRGPSBabelDataSource::Open( const char * pszDatasourceName,
                                  const char* pszGPSBabelDriverNameIn,
-                                 char** papszOpenOptions )
+                                 char** papszOpenOptionsIn )
 
 {
-    int bExplicitFeatures = FALSE;
-    int bWaypoints = TRUE, bTracks = TRUE, bRoutes = TRUE;
-
-    if (!EQUALN(pszDatasourceName, "GPSBABEL:", 9))
+    if (!STARTS_WITH_CI(pszDatasourceName, "GPSBABEL:"))
     {
         CPLAssert(pszGPSBabelDriverNameIn);
         pszGPSBabelDriverName = CPLStrdup(pszGPSBabelDriverNameIn);
@@ -164,11 +162,11 @@ int OGRGPSBabelDataSource::Open( const char * pszDatasourceName,
     }
     else
     {
-        if( CSLFetchNameValue(papszOpenOptions, "FILENAME") )
-            pszFilename = CPLStrdup(CSLFetchNameValue(papszOpenOptions,
+        if( CSLFetchNameValue(papszOpenOptionsIn, "FILENAME") )
+            pszFilename = CPLStrdup(CSLFetchNameValue(papszOpenOptionsIn,
                                                       "FILENAME"));
 
-        if( CSLFetchNameValue(papszOpenOptions, "GPSBABEL_DRIVER") )
+        if( CSLFetchNameValue(papszOpenOptionsIn, "GPSBABEL_DRIVER") )
         {
             if( pszFilename == NULL )
             {
@@ -176,8 +174,8 @@ int OGRGPSBabelDataSource::Open( const char * pszDatasourceName,
                 return FALSE;
             }
 
-            pszGPSBabelDriverName = CPLStrdup(CSLFetchNameValue(papszOpenOptions,
-                                                            "DRIVER"));
+            pszGPSBabelDriverName
+                = CPLStrdup(CSLFetchNameValue(papszOpenOptionsIn, "DRIVER"));
 
             /* A bit of validation to avoid command line injection */
             if (!IsValidDriverName(pszGPSBabelDriverName))
@@ -187,13 +185,18 @@ int OGRGPSBabelDataSource::Open( const char * pszDatasourceName,
 
     pszName = CPLStrdup( pszDatasourceName );
 
+    bool bExplicitFeatures = false;
+    bool bWaypoints = true;
+    bool bTracks = true;
+    bool bRoutes = true;
+
     if (pszGPSBabelDriverName == NULL)
     {
         const char* pszSep = strchr(pszDatasourceName + 9, ':');
         if (pszSep == NULL)
         {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                    "Wrong syntax. Expected GPSBabel:driver_name:file_name");
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Wrong syntax. Expected GPSBabel:driver_name:file_name");
             return FALSE;
         }
 
@@ -204,14 +207,16 @@ int OGRGPSBabelDataSource::Open( const char * pszDatasourceName,
         if (!IsValidDriverName(pszGPSBabelDriverName))
             return FALSE;
 
-        /* Parse optionnal features= option */
-        if (EQUALN(pszSep+1, "features=", 9))
+        /* Parse optional features= option */
+        if (STARTS_WITH_CI(pszSep+1, "features="))
         {
             const char* pszNextSep = strchr(pszSep+1, ':');
             if (pszNextSep == NULL)
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
-                        "Wrong syntax. Expected GPSBabel:driver_name[,options]*:[features=waypoints,tracks,routes:]file_name");
+                        "Wrong syntax. Expected "
+                         "GPSBabel:driver_name[,options]*:["
+                         "features=waypoints,tracks,routes:]file_name");
                 return FALSE;
             }
 
@@ -219,23 +224,26 @@ int OGRGPSBabelDataSource::Open( const char * pszDatasourceName,
             *strchr(pszFeatures, ':') = 0;
             char** papszTokens = CSLTokenizeString(pszFeatures);
             char** papszIter = papszTokens;
-            int bErr = FALSE;
-            bExplicitFeatures = TRUE;
-            bWaypoints = bTracks = bRoutes = FALSE;
+            bool bErr = false;
+            bExplicitFeatures = true;
+            bWaypoints = false;
+            bTracks = false;
+            bRoutes = false;
             while(papszIter && *papszIter)
             {
                 if (EQUAL(*papszIter, "waypoints"))
-                    bWaypoints = TRUE;
+                    bWaypoints = true;
                 else if (EQUAL(*papszIter, "tracks"))
-                    bTracks = TRUE;
+                    bTracks = true;
                 else if (EQUAL(*papszIter, "routes"))
-                    bRoutes = TRUE;
+                    bRoutes = true;
                 else
                 {
-                    CPLError(CE_Failure, CPLE_AppDefined, "Wrong value for 'features' options");
-                    bErr = TRUE;
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                              "Wrong value for 'features' options");
+                    bErr = true;
                 }
-                papszIter ++;
+                papszIter++;
             }
             CSLDestroy(papszTokens);
             CPLFree(pszFeatures);
@@ -251,12 +259,12 @@ int OGRGPSBabelDataSource::Open( const char * pszDatasourceName,
     }
 
     const char* pszOptionUseTempFile = CPLGetConfigOption("USE_TEMPFILE", NULL);
-    if (pszOptionUseTempFile && CSLTestBoolean(pszOptionUseTempFile))
+    if (pszOptionUseTempFile && CPLTestBool(pszOptionUseTempFile))
         osTmpFileName = CPLGenerateTempFilename(NULL);
     else
         osTmpFileName.Printf("/vsimem/ogrgpsbabeldatasource_%p", this);
 
-    int bRet = FALSE;
+    bool bRet = false;
     if (IsSpecialFile(pszFilename))
     {
         /* Special file : don't try to open it */
@@ -292,7 +300,7 @@ int OGRGPSBabelDataSource::Open( const char * pszDatasourceName,
         argv = NULL;
 
         CPLErr nLastErrorType = CPLGetLastErrorType();
-        int nLastErrorNo = CPLGetLastErrorNo();
+        CPLErrorNum nLastErrorNo = CPLGetLastErrorNo();
         CPLString osLastErrorMsg = CPLGetLastErrorMsg();
 
         VSIFCloseL(tmpfp);
@@ -303,17 +311,21 @@ int OGRGPSBabelDataSource::Open( const char * pszDatasourceName,
 
         if (!bRet)
         {
-            if (strstr(osLastErrorMsg.c_str(), "This format cannot be used in piped commands") == NULL)
+            if ( strstr(osLastErrorMsg.c_str(),
+                        "This format cannot be used in piped commands") == NULL)
             {
-                CPLError(nLastErrorType, nLastErrorNo, "%s", osLastErrorMsg.c_str());
+                CPLError( nLastErrorType, nLastErrorNo, "%s",
+                          osLastErrorMsg.c_str());
             }
             else
             {
                 VSIStatBuf sStatBuf;
                 if (VSIStat(pszFilename, &sStatBuf) != 0)
                 {
-                    CPLError(CE_Failure, CPLE_NotSupported,
-                            "Driver %s only supports real (non virtual) files", pszGPSBabelDriverName);
+                    CPLError( CE_Failure, CPLE_NotSupported,
+                              "Driver %s only supports real (non virtual) "
+                              "files",
+                              pszGPSBabelDriverName );
                     return FALSE;
                 }
 
@@ -334,22 +346,21 @@ int OGRGPSBabelDataSource::Open( const char * pszDatasourceName,
 
     if (bRet)
     {
-        poGPXDS = (GDALDataset*) GDALOpenEx(osTmpFileName.c_str(),
-                                            GDAL_OF_VECTOR, NULL, NULL, NULL);
+        poGPXDS = static_cast<GDALDataset *>(
+            GDALOpenEx( osTmpFileName.c_str(),
+                        GDAL_OF_VECTOR, NULL, NULL, NULL ) );
         if (poGPXDS)
         {
-            OGRLayer* poLayer;
-
             if (bWaypoints)
             {
-                poLayer = poGPXDS->GetLayerByName("waypoints");
+                OGRLayer* poLayer = poGPXDS->GetLayerByName("waypoints");
                 if (poLayer != NULL && poLayer->GetFeatureCount() != 0)
                     apoLayers[nLayers++] = poLayer;
             }
 
             if (bRoutes)
             {
-                poLayer = poGPXDS->GetLayerByName("routes");
+                OGRLayer* poLayer = poGPXDS->GetLayerByName("routes");
                 if (poLayer != NULL && poLayer->GetFeatureCount() != 0)
                     apoLayers[nLayers++] = poLayer;
                 poLayer = poGPXDS->GetLayerByName("route_points");
@@ -359,7 +370,7 @@ int OGRGPSBabelDataSource::Open( const char * pszDatasourceName,
 
             if (bTracks)
             {
-                poLayer = poGPXDS->GetLayerByName("tracks");
+                OGRLayer* poLayer = poGPXDS->GetLayerByName("tracks");
                 if (poLayer != NULL && poLayer->GetFeatureCount() != 0)
                     apoLayers[nLayers++] = poLayer;
                 poLayer = poGPXDS->GetLayerByName("track_points");
@@ -376,7 +387,7 @@ int OGRGPSBabelDataSource::Open( const char * pszDatasourceName,
 /*                           TestCapability()                           */
 /************************************************************************/
 
-int OGRGPSBabelDataSource::TestCapability( CPL_UNUSED const char * pszCap )
+int OGRGPSBabelDataSource::TestCapability( const char * /* pszCap */ )
 {
     return FALSE;
 }
@@ -390,6 +401,6 @@ OGRLayer *OGRGPSBabelDataSource::GetLayer( int iLayer )
 {
     if( iLayer < 0 || iLayer >= nLayers )
         return NULL;
-    else
-        return apoLayers[iLayer];
+
+    return apoLayers[iLayer];
 }
diff --git a/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldriver.cpp b/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldriver.cpp
index 8f6678c..5b7951e 100644
--- a/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldriver.cpp
+++ b/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldriver.cpp
@@ -27,11 +27,10 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_gpsbabel.h"
 #include "cpl_conv.h"
 #include "cpl_spawn.h"
 
-// g++ -g -Wall -fPIC  ogr/ogrsf_frmts/gpsbabel/*.cpp -shared -o ogr_GPSBabel.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/gpsbabel -L. -lgdal
+#include "ogr_gpsbabel.h"
 
 CPL_CVSID("$Id$");
 
@@ -39,30 +38,31 @@ CPL_CVSID("$Id$");
 /*                         OGRGPSBabelDriverIdentify()                  */
 /************************************************************************/
 
-static int OGRGPSBabelDriverIdentifyInternal( GDALOpenInfo* poOpenInfo,
-                                              const char** ppszGSPBabelDriverName )
+static bool OGRGPSBabelDriverIdentifyInternal(
+    GDALOpenInfo* poOpenInfo,
+    const char** ppszGSPBabelDriverName )
 {
-    if( EQUALN(poOpenInfo->pszFilename, "GPSBABEL:", strlen("GPSBABEL:")) )
-        return TRUE;
+    if( STARTS_WITH_CI(poOpenInfo->pszFilename, "GPSBABEL:") )
+        return true;
 
     const char* pszGPSBabelDriverName = NULL;
     if( poOpenInfo->fpL == NULL )
-            return FALSE;
+            return false;
 
     if (memcmp(poOpenInfo->pabyHeader, "MsRcd", 5) == 0)
         pszGPSBabelDriverName = "mapsource";
     else if (memcmp(poOpenInfo->pabyHeader, "MsRcf", 5) == 0)
         pszGPSBabelDriverName = "gdb";
-    else if (strstr((const char*)poOpenInfo->pabyHeader, "<osm") != NULL)
+    else if (strstr(reinterpret_cast<const char*>(poOpenInfo->pabyHeader), "<osm") != NULL)
         pszGPSBabelDriverName = "osm";
-    else if (strstr((const char*)poOpenInfo->pabyHeader, "$GPGSA") != NULL ||
-                strstr((const char*)poOpenInfo->pabyHeader, "$GPGGA") != NULL)
+    else if (strstr(reinterpret_cast<const char*>(poOpenInfo->pabyHeader), "$GPGSA") != NULL ||
+                strstr(reinterpret_cast<const char*>(poOpenInfo->pabyHeader), "$GPGGA") != NULL)
         pszGPSBabelDriverName = "nmea";
-    else if (EQUALN((const char*)poOpenInfo->pabyHeader, "OziExplorer",11))
+    else if (STARTS_WITH_CI((const char*)poOpenInfo->pabyHeader, "OziExplorer"))
         pszGPSBabelDriverName = "ozi";
-    else if (strstr((const char*)poOpenInfo->pabyHeader, "Grid") &&
-                strstr((const char*)poOpenInfo->pabyHeader, "Datum") &&
-                strstr((const char*)poOpenInfo->pabyHeader, "Header"))
+    else if (strstr(reinterpret_cast<const char*>(poOpenInfo->pabyHeader), "Grid") &&
+                strstr(reinterpret_cast<const char*>(poOpenInfo->pabyHeader), "Datum") &&
+                strstr(reinterpret_cast<const char*>(poOpenInfo->pabyHeader), "Header"))
         pszGPSBabelDriverName = "garmin_txt";
     else if (poOpenInfo->pabyHeader[0] == 13 && poOpenInfo->pabyHeader[10] == 'M' && poOpenInfo->pabyHeader[11] == 'S' &&
                 (poOpenInfo->pabyHeader[12] >= '0' && poOpenInfo->pabyHeader[12] <= '9') &&
@@ -71,8 +71,8 @@ static int OGRGPSBabelDriverIdentifyInternal( GDALOpenInfo* poOpenInfo,
                 (poOpenInfo->pabyHeader[14] == 1 || poOpenInfo->pabyHeader[14] == 2) && poOpenInfo->pabyHeader[15] == 0 &&
                 poOpenInfo->pabyHeader[16] == 0 && poOpenInfo->pabyHeader[17] == 0)
         pszGPSBabelDriverName = "mapsend";
-    else if (strstr((const char*)poOpenInfo->pabyHeader, "$PMGNWPL") != NULL ||
-                strstr((const char*)poOpenInfo->pabyHeader, "$PMGNRTE") != NULL)
+    else if (strstr(reinterpret_cast<const char*>(poOpenInfo->pabyHeader), "$PMGNWPL") != NULL ||
+                strstr(reinterpret_cast<const char*>(poOpenInfo->pabyHeader), "$PMGNRTE") != NULL)
         pszGPSBabelDriverName = "magellan";
     else if (poOpenInfo->pabyHeader[0] == 'A' &&
                 poOpenInfo->pabyHeader[1] >= 'A' && poOpenInfo->pabyHeader[1] <= 'Z' &&
@@ -101,15 +101,16 @@ static int OGRGPSBabelDriverIdentifyInternal( GDALOpenInfo* poOpenInfo,
 
     if( bGPSBabelFound )
         *ppszGSPBabelDriverName = pszGPSBabelDriverName;
-    return ( *ppszGSPBabelDriverName != NULL );
+    return *ppszGSPBabelDriverName != NULL;
 }
 
 static int OGRGPSBabelDriverIdentify( GDALOpenInfo* poOpenInfo )
 {
     const char* pszGPSBabelDriverName = NULL;
-    return OGRGPSBabelDriverIdentifyInternal(poOpenInfo, &pszGPSBabelDriverName);
+    return OGRGPSBabelDriverIdentifyInternal( poOpenInfo,
+                                              &pszGPSBabelDriverName );
 }
-    
+
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
@@ -122,7 +123,7 @@ static GDALDataset *OGRGPSBabelDriverOpen( GDALOpenInfo* poOpenInfo )
         !OGRGPSBabelDriverIdentifyInternal(poOpenInfo, &pszGPSBabelDriverName))
         return NULL;
 
-    OGRGPSBabelDataSource   *poDS = new OGRGPSBabelDataSource();
+    OGRGPSBabelDataSource *poDS = new OGRGPSBabelDataSource();
 
     if( !poDS->Open( poOpenInfo->pszFilename, pszGPSBabelDriverName,
                      poOpenInfo->papszOpenOptions ) )
@@ -139,13 +140,13 @@ static GDALDataset *OGRGPSBabelDriverOpen( GDALOpenInfo* poOpenInfo )
 /************************************************************************/
 
 static GDALDataset *OGRGPSBabelDriverCreate( const char * pszName,
-                                             CPL_UNUSED int nBands,
-                                             CPL_UNUSED int nXSize,
-                                             CPL_UNUSED int nYSize,
-                                             CPL_UNUSED GDALDataType eDT,
+                                             int /* nBands */,
+                                             int /* nXSize */,
+                                             int /* nYSize */,
+                                             GDALDataType /* eDT */,
                                              char **papszOptions )
 {
-    OGRGPSBabelWriteDataSource   *poDS = new OGRGPSBabelWriteDataSource();
+    OGRGPSBabelWriteDataSource *poDS = new OGRGPSBabelWriteDataSource();
 
     if( !poDS->Create( pszName, papszOptions ) )
     {
@@ -165,8 +166,8 @@ static CPLErr OGRGPSBabelDriverDelete( const char *pszFilename )
 {
     if( VSIUnlink( pszFilename ) == 0 )
         return CE_None;
-    else
-        return CE_Failure;
+
+    return CE_Failure;
 }
 
 /************************************************************************/
@@ -178,37 +179,33 @@ void RegisterOGRGPSBabel()
     if (! GDAL_CHECK_VERSION("OGR/GPSBabel driver"))
         return;
 
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "GPSBabel" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "GPSBabel" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "GPSBabel" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "GPSBabel" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_gpsbabel.html" );
+    poDriver->SetDescription( "GPSBabel" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "GPSBabel" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_gpsbabel.html" );
 
-        poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, "GPSBABEL:" );
+    poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, "GPSBABEL:" );
 
-        poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
 "<OpenOptionList>"
 "  <Option name='FILENAME' type='string' description='Filename to open'/>"
 "  <Option name='GPSBABEL_DRIVER' type='string' description='Name of the GPSBabel to use'/>"
 "</OpenOptionList>");
 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "  <Option name='GPSBABEL_DRIVER' type='string' description='Name of the GPSBabel to use'/>"
 "</CreationOptionList>");
 
-        poDriver->pfnOpen = OGRGPSBabelDriverOpen;
-        poDriver->pfnIdentify = OGRGPSBabelDriverIdentify;
-        poDriver->pfnCreate = OGRGPSBabelDriverCreate;
-        poDriver->pfnDelete = OGRGPSBabelDriverDelete;
+    poDriver->pfnOpen = OGRGPSBabelDriverOpen;
+    poDriver->pfnIdentify = OGRGPSBabelDriverIdentify;
+    poDriver->pfnCreate = OGRGPSBabelDriverCreate;
+    poDriver->pfnDelete = OGRGPSBabelDriverDelete;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabelwritedatasource.cpp b/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabelwritedatasource.cpp
index 745f47c..eff1a65 100644
--- a/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabelwritedatasource.cpp
+++ b/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabelwritedatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgpsbabelwritedatasource.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogrgpsbabelwritedatasource.cpp 32982 2016-01-14 16:53:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGPSBabelWriteDataSource class.
@@ -27,27 +27,26 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include <string.h>
-#include "ogr_gpsbabel.h"
+#include <cstring>
 #include "cpl_conv.h"
 #include "cpl_string.h"
 #include "cpl_error.h"
 #include "cpl_spawn.h"
 
-CPL_CVSID("$Id: ogrgpsbabelwritedatasource.cpp 27384 2014-05-24 12:28:12Z rouault $");
+#include "ogr_gpsbabel.h"
+
+CPL_CVSID("$Id: ogrgpsbabelwritedatasource.cpp 32982 2016-01-14 16:53:57Z goatbar $");
 
 /************************************************************************/
 /*                    OGRGPSBabelWriteDataSource()                      */
 /************************************************************************/
 
-OGRGPSBabelWriteDataSource::OGRGPSBabelWriteDataSource()
-
-{
-    pszName = NULL;
-    pszGPSBabelDriverName = NULL;
-    pszFilename = NULL;
-    poGPXDS = NULL;
-}
+OGRGPSBabelWriteDataSource::OGRGPSBabelWriteDataSource() :
+    pszName(NULL),
+    pszGPSBabelDriverName(NULL),
+    pszFilename(NULL),
+    poGPXDS(NULL)
+{}
 
 /************************************************************************/
 /*                  ~OGRGPSBabelWriteDataSource()                       */
@@ -57,7 +56,7 @@ OGRGPSBabelWriteDataSource::~OGRGPSBabelWriteDataSource()
 
 {
     if (poGPXDS)
-        GDALClose( (GDALDatasetH) poGPXDS );
+        GDALClose( poGPXDS );
 
     Convert();
 
@@ -73,16 +72,18 @@ OGRGPSBabelWriteDataSource::~OGRGPSBabelWriteDataSource()
 int OGRGPSBabelWriteDataSource::Convert()
 {
     int nRet = -1;
-    if (osTmpFileName.size() > 0 && pszFilename != NULL && pszGPSBabelDriverName != NULL)
+    if( osTmpFileName.size() > 0 && pszFilename != NULL &&
+         pszGPSBabelDriverName != NULL )
     {
         if (OGRGPSBabelDataSource::IsSpecialFile(pszFilename))
         {
             /* Special file : don't try to open it */
-            const char* const argv[] = { "gpsbabel", "-i", "gpx", "-f", "-",
-                                          "-o", pszGPSBabelDriverName, "-F", pszFilename, NULL };
             VSILFILE* tmpfp = VSIFOpenL(osTmpFileName.c_str(), "rb");
             if (tmpfp)
             {
+                const char* const argv[] = {
+                    "gpsbabel", "-i", "gpx", "-f", "-",
+                    "-o", pszGPSBabelDriverName, "-F", pszFilename, NULL };
                 nRet = CPLSpawn(argv, tmpfp, NULL, TRUE);
 
                 VSIFCloseL(tmpfp);
@@ -94,16 +95,17 @@ int OGRGPSBabelWriteDataSource::Convert()
             VSILFILE* fp = VSIFOpenL(pszFilename, "wb");
             if (fp == NULL)
             {
-                CPLError(CE_Failure, CPLE_AppDefined,
-                        "Cannot open file %s", pszFilename);
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Cannot open file %s", pszFilename );
             }
             else
             {
-                const char* const argv[] = { "gpsbabel", "-i", "gpx", "-f", "-",
-                                            "-o", pszGPSBabelDriverName, "-F", "-", NULL };
                 VSILFILE* tmpfp = VSIFOpenL(osTmpFileName.c_str(), "rb");
                 if (tmpfp)
                 {
+                    const char* const argv[] = {
+                        "gpsbabel", "-i", "gpx", "-f", "-",
+                        "-o", pszGPSBabelDriverName, "-F", "-", NULL };
                     nRet = CPLSpawn(argv, tmpfp, fp, TRUE);
 
                     VSIFCloseL(tmpfp);
@@ -126,17 +128,19 @@ int OGRGPSBabelWriteDataSource::Convert()
 /*                                 Create()                             */
 /************************************************************************/
 
-int OGRGPSBabelWriteDataSource::Create( const char * pszName,
+int OGRGPSBabelWriteDataSource::Create( const char * pszNameIn,
                                         char **papszOptions )
 {
-    GDALDriver* poGPXDriver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName("GPX");
+    GDALDriver* poGPXDriver
+        = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName("GPX");
     if (poGPXDriver == NULL)
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "GPX driver is necessary for GPSBabel write support");
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "GPX driver is necessary for GPSBabel write support" );
         return FALSE;
     }
 
-    if (!EQUALN(pszName, "GPSBABEL:", 9))
+    if (!STARTS_WITH_CI(pszNameIn, "GPSBABEL:"))
     {
         const char* pszOptionGPSBabelDriverName =
                 CSLFetchNameValue(papszOptions, "GPSBABEL_DRIVER");
@@ -144,23 +148,25 @@ int OGRGPSBabelWriteDataSource::Create( const char * pszName,
             pszGPSBabelDriverName = CPLStrdup(pszOptionGPSBabelDriverName);
         else
         {
-            CPLError(CE_Failure, CPLE_AppDefined, "GPSBABEL_DRIVER dataset creation option expected");
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "GPSBABEL_DRIVER dataset creation option expected" );
             return FALSE;
         }
 
-        pszFilename = CPLStrdup(pszName);
+        pszFilename = CPLStrdup(pszNameIn);
     }
     else
     {
-        const char* pszSep = strchr(pszName + 9, ':');
+        const char* pszSep = strchr(pszNameIn + 9, ':');
         if (pszSep == NULL)
         {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                    "Wrong syntax. Expected GPSBabel:driver_name[,options]*:file_name");
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Wrong syntax. Expected GPSBabel:driver_name[,options]*:"
+                      "file_name" );
             return FALSE;
         }
 
-        pszGPSBabelDriverName = CPLStrdup(pszName + 9);
+        pszGPSBabelDriverName = CPLStrdup(pszNameIn + 9);
         *(strchr(pszGPSBabelDriverName, ':')) = '\0';
 
         pszFilename = CPLStrdup(pszSep+1);
@@ -170,19 +176,21 @@ int OGRGPSBabelWriteDataSource::Create( const char * pszName,
     if (!OGRGPSBabelDataSource::IsValidDriverName(pszGPSBabelDriverName))
         return FALSE;
 
-    const char* pszOptionUseTempFile = CSLFetchNameValue(papszOptions, "USE_TEMPFILE");
+    const char* pszOptionUseTempFile
+        = CSLFetchNameValue(papszOptions, "USE_TEMPFILE");
     if (pszOptionUseTempFile == NULL)
         pszOptionUseTempFile = CPLGetConfigOption("USE_TEMPFILE", NULL);
-    if (pszOptionUseTempFile && CSLTestBoolean(pszOptionUseTempFile))
+    if (pszOptionUseTempFile && CPLTestBool(pszOptionUseTempFile))
         osTmpFileName = CPLGenerateTempFilename(NULL);
     else
         osTmpFileName.Printf("/vsimem/ogrgpsbabeldatasource_%p", this);
 
-    poGPXDS = poGPXDriver->Create(osTmpFileName.c_str(), 0, 0, 0, GDT_Unknown, papszOptions);
+    poGPXDS = poGPXDriver->Create( osTmpFileName.c_str(), 0, 0, 0,
+                                   GDT_Unknown, papszOptions);
     if (poGPXDS == NULL)
         return FALSE;
 
-    this->pszName = CPLStrdup(pszName);
+    this->pszName = CPLStrdup(pszNameIn);
 
     return TRUE;
 }
@@ -191,12 +199,12 @@ int OGRGPSBabelWriteDataSource::Create( const char * pszName,
 /*                           ICreateLayer()                             */
 /************************************************************************/
 
-OGRLayer * OGRGPSBabelWriteDataSource::ICreateLayer( const char * pszLayerName,
+OGRLayer *OGRGPSBabelWriteDataSource::ICreateLayer( const char * pszLayerName,
                                                     OGRSpatialReference *poSRS,
                                                     OGRwkbGeometryType eType,
                                                     char ** papszOptions )
 {
-    if (poGPXDS)
+    if( poGPXDS )
         return poGPXDS->CreateLayer(pszLayerName, poSRS, eType, papszOptions);
     return NULL;
 }
@@ -211,6 +219,7 @@ int OGRGPSBabelWriteDataSource::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,ODsCCreateLayer) )
         return TRUE;
+
     return FALSE;
 }
 
@@ -221,8 +230,9 @@ int OGRGPSBabelWriteDataSource::TestCapability( const char * pszCap )
 OGRLayer *OGRGPSBabelWriteDataSource::GetLayer( int iLayer )
 
 {
-    if (poGPXDS)
+    if( poGPXDS )
         return poGPXDS->GetLayer(iLayer);
+
     return NULL;
 }
 
@@ -233,7 +243,8 @@ OGRLayer *OGRGPSBabelWriteDataSource::GetLayer( int iLayer )
 int OGRGPSBabelWriteDataSource::GetLayerCount()
 
 {
-    if (poGPXDS)
+    if( poGPXDS )
         return poGPXDS->GetLayerCount();
+
     return 0;
 }
diff --git a/ogr/ogrsf_frmts/gpx/drv_gpx.html b/ogr/ogrsf_frmts/gpx/drv_gpx.html
index 4b3c80c..713406d 100644
--- a/ogr/ogrsf_frmts/gpx/drv_gpx.html
+++ b/ogr/ogrsf_frmts/gpx/drv_gpx.html
@@ -51,10 +51,10 @@ Expat library supports reading the following built-in encodings :
 </ul>
 
 OGR 1.8.0 adds supports for Windows-1252 encoding (for previous versions, altering the encoding
-mentionned in the XML header to ISO-8859-1 might work in some cases).<p>
+mentioned in the XML header to ISO-8859-1 might work in some cases).<p>
 
 The content returned by OGR will be encoded in UTF-8, after the conversion from the
-encoding mentionned in the file header is.<p>
+encoding mentioned in the file header is.<p>
 
 If your GPX file is not encoded in one of the previous encodings, it will not be parsed by the
 GPX driver. You may convert it into one of the supported encoding with the <i>iconv</i> utility
@@ -98,7 +98,7 @@ will be interpreted in the OGR SF model as :
 <p><br>
 Note : the GPX driver will output content of the extensions element only if it is found in the first records of the GPX file.
 If extensions appear later, you can force an explicit parsing of the whole file with the <b>GPX_USE_EXTENSIONS</b> environment variable.
-<p> 
+<p>
 
 <h2>Creation Issues</h2>
 
@@ -132,12 +132,12 @@ field can be set on the first track point to fill the <name> element of th
 The GPX writer supports the following <i>layer</i> creation options:
 <ul>
 <li> <b>FORCE_GPX_TRACK</b>:
-By default when writting a layer whose features are of type wkbLineString, the GPX driver
+By default when writing a layer whose features are of type wkbLineString, the GPX driver
 chooses to write them as routes.
 <br>If FORCE_GPX_TRACK=YES is specified, they will be written
 as tracks.</li><p>
 <li> <b>FORCE_GPX_ROUTE</b>:
-By default when writting a layer whose features are of type wkbMultiLineString, the GPX driver
+By default when writing a layer whose features are of type wkbMultiLineString, the GPX driver
 chooses to write them as tracks.
 <br>If FORCE_GPX_ROUTE=YES is specified, they will be written
 as routes, provided that the multilines are composed of only one single line.</li><p>
@@ -157,7 +157,7 @@ Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS is set.<br>
 The namespace URI. By default, "http://osgeo.org/gdal".</li><p>
 <li> <b>LINEFORMAT</b>: (GDAL/OGR >= 1.8.0)
 By default files are created with the line
-termination conventions of the local platform (CR/LF on win32 or 
+termination conventions of the local platform (CR/LF on win32 or
 LF on all other systems).  This may be overridden through use of the
 LINEFORMAT layer creation option which may have a value of <b>CRLF</b>
 (DOS format) or <b>LF</b> (Unix format).</li> <p>
@@ -167,7 +167,7 @@ LINEFORMAT layer creation option which may have a value of <b>CRLF</b>
 Waypoints, routes and tracks must be written into that order to be valid against the XML Schema.
 
 <p>
-When translating from a source dataset, it may be necessary to rename the field names from the source dataset to the expected GPX attribute names, such as <name>, <desc>, etc... 
+When translating from a source dataset, it may be necessary to rename the field names from the source dataset to the expected GPX attribute names, such as <name>, <desc>, etc...
 This can be done with a <a href="drv_vrt.html">OGR VRT</a> dataset, or by using the "-sql" option of the ogr2ogr utility.
 
 </li>
diff --git a/ogr/ogrsf_frmts/gpx/ogr_gpx.h b/ogr/ogrsf_frmts/gpx/ogr_gpx.h
index 586d2cb..c6f3a18 100644
--- a/ogr/ogrsf_frmts/gpx/ogr_gpx.h
+++ b/ogr/ogrsf_frmts/gpx/ogr_gpx.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_gpx.h 27959 2014-11-14 18:29:21Z rouault $
+ * $Id: ogr_gpx.h 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  GPX Translator
  * Purpose:  Definition of classes for OGR .gpx driver.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_GPX_H_INCLUDED
-#define _OGR_GPX_H_INCLUDED
+#ifndef OGR_GPX_H_INCLUDED
+#define OGR_GPX_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 
@@ -58,65 +58,70 @@ class OGRGPXLayer : public OGRLayer
     OGRFeatureDefn*    poFeatureDefn;
     OGRSpatialReference *poSRS;
     OGRGPXDataSource*  poDS;
-    
+
     GPXGeometryType    gpxGeomType;
 
     int                nGPXFields;
 
-    int                bWriteMode;
-    int                nFeatures;
-    int                eof;
+    bool               bWriteMode;
     int                nNextFID;
     VSILFILE*          fpGPX; /* Large file API */
-    const char*        pszElementToScan;
 #ifdef HAVE_EXPAT
     XML_Parser         oParser;
     XML_Parser         oSchemaParser;
 #endif
-    int                inInterestingElement;
-    int                hasFoundLat;
-    int                hasFoundLon;
+    bool               inInterestingElement;
+    bool               hasFoundLat;
+    bool               hasFoundLon;
+#ifdef HAVE_EXPAT
     double             latVal;
     double             lonVal;
+#endif
     char*              pszSubElementName;
     char*              pszSubElementValue;
     int                nSubElementValueLen;
+#ifdef HAVE_EXPAT
     int                iCurrentField;
+#endif
 
     OGRFeature*        poFeature;
     OGRFeature **      ppoFeatureTab;
     int                nFeatureTabLength;
     int                nFeatureTabIndex;
-    
+
     OGRMultiLineString* multiLineString;
     OGRLineString*      lineString;
-    
+
     int                depthLevel;
     int                interestingDepthLevel;
-    
+
+#ifdef HAVE_EXPAT
     OGRFieldDefn*      currentFieldDefn;
-    int                inExtensions;
+    bool               inExtensions;
     int                extensionsDepthLevel;
-    
-    int                inLink;
+
+    bool               inLink;
     int                iCountLink;
+#endif
     int                nMaxLinks;
-    
-    int                bEleAs25D;
-    
+
+    bool               bEleAs25D;
+
     int                trkFID;
     int                trkSegId;
     int                trkSegPtId;
-    
+
     int                rteFID;
     int                rtePtId;
-    
-    int                bStopParsing;
+
+#ifdef HAVE_EXPAT
+    bool               bStopParsing;
     int                nWithoutEventCounter;
     int                nDataHandlerCounter;
-    
+#endif
+
     int                iFirstGPXField;
-    
+
   private:
     void               WriteFeatureAttributes( OGRFeature *poFeature, int nIdentLevel = 1 );
     void               LoadExtensionsSchema();
@@ -136,19 +141,19 @@ class OGRGPXLayer : public OGRLayer
 
     void                ResetReading();
     OGRFeature *        GetNextFeature();
-    
+
     OGRErr              ICreateFeature( OGRFeature *poFeature );
     OGRErr              CreateField( OGRFieldDefn *poField, int bApproxOK );
 
     OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
-    
+
     int                 TestCapability( const char * );
-    
+
 #ifdef HAVE_EXPAT
     void                startElementCbk(const char *pszName, const char **ppszAttr);
     void                endElementCbk(const char *pszName);
     void                dataHandlerCbk(const char *data, int nLen);
-    
+
     void                startElementLoadSchemaCbk(const char *pszName, const char **ppszAttr);
     void                endElementLoadSchemaCbk(const char *pszName);
     void                dataHandlerLoadSchemaCbk(const char *data, int nLen);
@@ -177,20 +182,23 @@ class OGRGPXDataSource : public OGRDataSource
 
     /*  Export related */
     VSILFILE           *fpOutput; /* Large file API */
-    int                 bIsBackSeekable;
+    bool                bIsBackSeekable;
     const char         *pszEOL;
     int                 nOffsetBounds;
-    double              dfMinLat, dfMinLon, dfMaxLat, dfMaxLon;
-    
+    double              dfMinLat;
+    double              dfMinLon;
+    double              dfMaxLat;
+    double              dfMaxLon;
+
     GPXGeometryType     lastGPXGeomTypeWritten;
-    
-    int                 bUseExtensions;
+
+    bool                bUseExtensions;
     char*               pszExtensionsNS;
-    
+
+#ifdef HAVE_EXPAT
     OGRGPXValidity      validity;
     int                 nElementsRead;
     char*               pszVersion;
-#ifdef HAVE_EXPAT
     XML_Parser          oCurrentParser;
     int                 nDataHandlerCounter;
 #endif
@@ -205,40 +213,39 @@ class OGRGPXDataSource : public OGRDataSource
 
     int                 Open( const char * pszFilename,
                               int bUpdate );
-    
-    int                 Create( const char *pszFilename, 
+
+    int                 Create( const char *pszFilename,
                               char **papszOptions );
-    
+
     const char*         GetName() { return pszName; }
 
     int                 GetLayerCount() { return nLayers; }
     OGRLayer*           GetLayer( int );
-    
+
     OGRLayer *          ICreateLayer( const char * pszLayerName,
                                     OGRSpatialReference *poSRS,
                                     OGRwkbGeometryType eType,
                                     char ** papszOptions );
 
     int                 TestCapability( const char * );
-    
+
     VSILFILE *              GetOutputFP() { return fpOutput; }
     void                SetLastGPXGeomTypeWritten(GPXGeometryType gpxGeomType)
                             { lastGPXGeomTypeWritten = gpxGeomType; }
     GPXGeometryType     GetLastGPXGeomTypeWritten() { return lastGPXGeomTypeWritten; }
-    
+
     int                 GetUseExtensions() { return bUseExtensions; }
     const char*         GetExtensionsNS() { return pszExtensionsNS; }
-    
+
 #ifdef HAVE_EXPAT
     void                startElementValidateCbk(const char *pszName, const char **ppszAttr);
     void                dataHandlerValidateCbk(const char *data, int nLen);
+    const char*         GetVersion() { return pszVersion; }
 #endif
 
-    const char*         GetVersion() { return pszVersion; }
-    
     void                AddCoord(double dfLon, double dfLat);
-    
+
     void                PrintLine(const char *fmt, ...) CPL_PRINT_FUNC_FORMAT (2, 3);
 };
 
-#endif /* ndef _OGR_GPX_H_INCLUDED */
+#endif /* ndef OGR_GPX_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/gpx/ogrgpxdatasource.cpp b/ogr/ogrsf_frmts/gpx/ogrgpxdatasource.cpp
index 37d80de..714c5d6 100644
--- a/ogr/ogrsf_frmts/gpx/ogrgpxdatasource.cpp
+++ b/ogr/ogrsf_frmts/gpx/ogrgpxdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgpxdatasource.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: ogrgpxdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  GPX Translator
  * Purpose:  Implements OGRGPXDataSource class
@@ -27,46 +27,45 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_gpx.h"
 #include "cpl_conv.h"
-#include "cpl_string.h"
 #include "cpl_csv.h"
+#include "cpl_string.h"
+#include "ogr_gpx.h"
 
-CPL_CVSID("$Id: ogrgpxdatasource.cpp 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: ogrgpxdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
-#define SPACE_FOR_METADATA 160
+static const int SPACE_FOR_METADATA = 160;
 
 /************************************************************************/
 /*                          OGRGPXDataSource()                          */
 /************************************************************************/
 
-OGRGPXDataSource::OGRGPXDataSource()
-
-{
-    lastGPXGeomTypeWritten = GPX_NONE;
-    bUseExtensions = FALSE;
-    pszExtensionsNS = NULL;
-
-    papoLayers = NULL;
-    nLayers = 0;
-    
-    fpOutput = NULL;
-    nOffsetBounds = -1;
-    dfMinLat = 90;
-    dfMinLon = 180;
-    dfMaxLat = -90;
-    dfMaxLon = -180;
-
-    pszName = NULL;
-    pszVersion = NULL;
-
-    bIsBackSeekable = TRUE;
-    pszEOL = "\n";
-
-    nLastRteId = -1;
-    nLastTrkId = -1;
-    nLastTrkSegId = -1;
-}
+OGRGPXDataSource::OGRGPXDataSource() :
+    pszName(NULL),
+    papoLayers(NULL),
+    nLayers(0),
+    fpOutput(NULL),
+    bIsBackSeekable(true),
+    pszEOL("\n"),
+    nOffsetBounds(-1),
+    dfMinLat(90),
+    dfMinLon(180),
+    dfMaxLat(-90),
+    dfMaxLon(-180),
+    lastGPXGeomTypeWritten(GPX_NONE),
+    bUseExtensions(false),
+    pszExtensionsNS(NULL),
+#ifdef HAVE_EXPAT
+    validity(GPX_VALIDITY_UNKNOWN),
+    nElementsRead(0),
+    pszVersion(NULL),
+    oCurrentParser(NULL),
+    nDataHandlerCounter(0),
+#endif
+    nLastRteId(-1),
+    nLastTrkId(-1),
+    nLastTrkSegId(-1)
+{}
 
 /************************************************************************/
 /*                         ~OGRGPXDataSource()                          */
@@ -85,15 +84,17 @@ OGRGPXDataSource::~OGRGPXDataSource()
             PrintLine("</trk>");
         }
         PrintLine("</gpx>");
-        if ( bIsBackSeekable )
+        if( bIsBackSeekable )
         {
             /* Write the <bound> element in the reserved space */
             if (dfMinLon <= dfMaxLon)
             {
                 char szMetadata[SPACE_FOR_METADATA+1];
-                int nRet = CPLsnprintf(szMetadata, SPACE_FOR_METADATA,
-                         "<metadata><bounds minlat=\"%.15f\" minlon=\"%.15f\" maxlat=\"%.15f\" maxlon=\"%.15f\"/></metadata>",
-                        dfMinLat, dfMinLon, dfMaxLat, dfMaxLon);
+                int nRet = CPLsnprintf(
+                    szMetadata, SPACE_FOR_METADATA,
+                    "<metadata><bounds minlat=\"%.15f\" minlon=\"%.15f\""
+                    " maxlat=\"%.15f\" maxlon=\"%.15f\"/></metadata>",
+                    dfMinLat, dfMinLon, dfMaxLat, dfMaxLon);
                 if (nRet < SPACE_FOR_METADATA)
                 {
                     VSIFSeekL(fpOutput, nOffsetBounds, SEEK_SET);
@@ -109,7 +110,9 @@ OGRGPXDataSource::~OGRGPXDataSource()
     CPLFree( papoLayers );
     CPLFree( pszExtensionsNS );
     CPLFree( pszName );
+#ifdef HAVE_EXPAT
     CPLFree( pszVersion );
+#endif
 }
 
 /************************************************************************/
@@ -121,10 +124,10 @@ int OGRGPXDataSource::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,ODsCCreateLayer) )
         return TRUE;
-    else if( EQUAL(pszCap,ODsCDeleteLayer) )
-        return FALSE;
-    else
+    if( EQUAL(pszCap,ODsCDeleteLayer) )
         return FALSE;
+
+    return FALSE;
 }
 
 /************************************************************************/
@@ -136,8 +139,8 @@ OGRLayer *OGRGPXDataSource::GetLayer( int iLayer )
 {
     if( iLayer < 0 || iLayer >= nLayers )
         return NULL;
-    else
-        return papoLayers[iLayer];
+
+    return papoLayers[iLayer];
 }
 
 /************************************************************************/
@@ -145,7 +148,7 @@ OGRLayer *OGRGPXDataSource::GetLayer( int iLayer )
 /************************************************************************/
 
 OGRLayer * OGRGPXDataSource::ICreateLayer( const char * pszLayerName,
-                                           CPL_UNUSED OGRSpatialReference *poSRS,
+                                           OGRSpatialReference * /* poSRS */,
                                            OGRwkbGeometryType eType,
                                            char ** papszOptions )
 {
@@ -161,24 +164,27 @@ OGRLayer * OGRGPXDataSource::ICreateLayer( const char * pszLayerName,
     }
     else if (eType == wkbLineString || eType == wkbLineString25D)
     {
-        const char *pszForceGPXTrack = CSLFetchNameValue( papszOptions, "FORCE_GPX_TRACK");
-        if (pszForceGPXTrack && CSLTestBoolean(pszForceGPXTrack))
+        const char *pszForceGPXTrack
+            = CSLFetchNameValue( papszOptions, "FORCE_GPX_TRACK");
+        if (pszForceGPXTrack && CPLTestBool(pszForceGPXTrack))
             gpxGeomType = GPX_TRACK;
         else
             gpxGeomType = GPX_ROUTE;
     }
     else if (eType == wkbMultiLineString || eType == wkbMultiLineString25D)
     {
-        const char *pszForceGPXRoute = CSLFetchNameValue( papszOptions, "FORCE_GPX_ROUTE");
-        if (pszForceGPXRoute && CSLTestBoolean(pszForceGPXRoute))
+        const char *pszForceGPXRoute
+            = CSLFetchNameValue( papszOptions, "FORCE_GPX_ROUTE");
+        if (pszForceGPXRoute && CPLTestBool(pszForceGPXRoute))
             gpxGeomType = GPX_ROUTE;
         else
             gpxGeomType = GPX_TRACK;
     }
     else if (eType == wkbUnknown)
     {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "Cannot create GPX layer %s with unknown geometry type", pszLayerName);
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Cannot create GPX layer %s with unknown geometry type"
+                  , pszLayerName);
         return NULL;
     }
     else
@@ -189,9 +195,11 @@ OGRLayer * OGRGPXDataSource::ICreateLayer( const char * pszLayerName,
         return NULL;
     }
     nLayers++;
-    papoLayers = (OGRGPXLayer **) CPLRealloc(papoLayers, nLayers * sizeof(OGRGPXLayer*));
-    papoLayers[nLayers-1] = new OGRGPXLayer( pszName, pszLayerName, gpxGeomType, this, TRUE );
-    
+    papoLayers = static_cast<OGRGPXLayer **>(
+        CPLRealloc(papoLayers, nLayers * sizeof(OGRGPXLayer*)));
+    papoLayers[nLayers-1] = new OGRGPXLayer(
+        pszName, pszLayerName, gpxGeomType, this, TRUE );
+
     return papoLayers[nLayers-1];
 }
 
@@ -201,15 +209,15 @@ OGRLayer * OGRGPXDataSource::ICreateLayer( const char * pszLayerName,
 /*                startElementValidateCbk()                             */
 /************************************************************************/
 
-void OGRGPXDataSource::startElementValidateCbk(const char *pszName, const char **ppszAttr)
+void OGRGPXDataSource::startElementValidateCbk(
+    const char *pszNameIn, const char **ppszAttr)
 {
     if (validity == GPX_VALIDITY_UNKNOWN)
     {
-        if (strcmp(pszName, "gpx") == 0)
+        if (strcmp(pszNameIn, "gpx") == 0)
         {
-            int i;
             validity = GPX_VALIDITY_VALID;
-            for(i=0; ppszAttr[i] != NULL; i+= 2)
+            for( int i = 0; ppszAttr[i] != NULL; i += 2)
             {
                 if (strcmp(ppszAttr[i], "version") == 0)
                 {
@@ -225,9 +233,9 @@ void OGRGPXDataSource::startElementValidateCbk(const char *pszName, const char *
     }
     else if (validity == GPX_VALIDITY_VALID)
     {
-        if (strcmp(pszName, "extensions") == 0)
+        if (strcmp(pszNameIn, "extensions") == 0)
         {
-            bUseExtensions = TRUE;
+            bUseExtensions = true;
         }
         nElementsRead++;
     }
@@ -244,21 +252,24 @@ void OGRGPXDataSource::dataHandlerValidateCbk(CPL_UNUSED const char *data,
     nDataHandlerCounter ++;
     if (nDataHandlerCounter >= BUFSIZ)
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "File probably corrupted (million laugh pattern)");
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "File probably corrupted (million laugh pattern)");
         XML_StopParser(oCurrentParser, XML_FALSE);
     }
 }
 
 
-static void XMLCALL startElementValidateCbk(void *pUserData, const char *pszName, const char **ppszAttr)
+static void XMLCALL startElementValidateCbk(
+    void *pUserData, const char *pszName, const char **ppszAttr)
 {
-    OGRGPXDataSource* poDS = (OGRGPXDataSource*) pUserData;
+    OGRGPXDataSource* poDS = static_cast<OGRGPXDataSource *>(pUserData);
     poDS->startElementValidateCbk(pszName, ppszAttr);
 }
 
-static void XMLCALL dataHandlerValidateCbk(void *pUserData, const char *data, int nLen)
+static void XMLCALL dataHandlerValidateCbk(
+    void *pUserData, const char *data, int nLen)
 {
-    OGRGPXDataSource* poDS = (OGRGPXDataSource*) pUserData;
+    OGRGPXDataSource* poDS = static_cast<OGRGPXDataSource *>(pUserData);
     poDS->dataHandlerValidateCbk(data, nLen);
 }
 #endif
@@ -272,8 +283,9 @@ int OGRGPXDataSource::Open( const char * pszFilename, int bUpdateIn)
 {
     if (bUpdateIn)
     {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                    "OGR/GPX driver does not support opening a file in update mode");
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "OGR/GPX driver does not support opening a file in "
+                  "update mode");
         return FALSE;
     }
 #ifdef HAVE_EXPAT
@@ -285,24 +297,24 @@ int OGRGPXDataSource::Open( const char * pszFilename, int bUpdateIn)
     VSILFILE* fp = VSIFOpenL(pszFilename, "r");
     if (fp == NULL)
         return FALSE;
-    
+
     validity = GPX_VALIDITY_UNKNOWN;
     CPLFree(pszVersion);
     pszVersion = NULL;
-    bUseExtensions = FALSE;
+    bUseExtensions = false;
     nElementsRead = 0;
-    
+
     XML_Parser oParser = OGRCreateExpatXMLParser();
     oCurrentParser = oParser;
     XML_SetUserData(oParser, this);
     XML_SetElementHandler(oParser, ::startElementValidateCbk, NULL);
     XML_SetCharacterDataHandler(oParser, ::dataHandlerValidateCbk);
-    
+
     char aBuf[BUFSIZ];
     int nDone;
     unsigned int nLen;
     int nCount = 0;
-    
+
     /* Begin to parse the file and look for the <gpx> element */
     /* It *MUST* be the first element of an XML file */
     /* So once we have read the first element, we know if we can */
@@ -310,7 +322,8 @@ int OGRGPXDataSource::Open( const char * pszFilename, int bUpdateIn)
     do
     {
         nDataHandlerCounter = 0;
-        nLen = (unsigned int) VSIFReadL( aBuf, 1, sizeof(aBuf), fp );
+        nLen = static_cast<unsigned int>(
+            VSIFReadL( aBuf, 1, sizeof(aBuf), fp ) );
         nDone = VSIFEofL(fp);
         if (XML_Parse(oParser, aBuf, nLen, nDone) == XML_STATUS_ERROR)
         {
@@ -320,11 +333,12 @@ int OGRGPXDataSource::Open( const char * pszFilename, int bUpdateIn)
                 aBuf[BUFSIZ-1] = 0;
             if (strstr(aBuf, "<?xml") && strstr(aBuf, "<gpx"))
             {
-                CPLError(CE_Failure, CPLE_AppDefined,
-                        "XML parsing of GPX file failed : %s at line %d, column %d",
-                        XML_ErrorString(XML_GetErrorCode(oParser)),
-                        (int)XML_GetCurrentLineNumber(oParser),
-                        (int)XML_GetCurrentColumnNumber(oParser));
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "XML parsing of GPX file failed : %s at line %d, "
+                          "column %d",
+                          XML_ErrorString(XML_GetErrorCode(oParser)),
+                          static_cast<int>(XML_GetCurrentLineNumber(oParser)),
+                          static_cast<int>(XML_GetCurrentColumnNumber(oParser)));
             }
             validity = GPX_VALIDITY_INVALID;
             break;
@@ -338,29 +352,29 @@ int OGRGPXDataSource::Open( const char * pszFilename, int bUpdateIn)
             /* If we have recognized the <gpx> element, now we try */
             /* to recognize if they are <extensions> tags */
             /* But we stop to look for after an arbitrary number of tags */
-            if (bUseExtensions)
+            if( bUseExtensions )
                 break;
             else if (nElementsRead > 200)
                 break;
         }
         else
         {
-            /* After reading 50 * BUFSIZE bytes, and not finding whether the file */
-            /* is GPX or not, we give up and fail silently */
+            // After reading 50 * BUFSIZE bytes, and not finding whether the file
+            // is GPX or not, we give up and fail silently.
             nCount ++;
             if (nCount == 50)
                 break;
         }
     } while (!nDone && nLen > 0 );
-    
+
     XML_ParserFree(oParser);
-    
+
     VSIFCloseL(fp);
-    
+
     if (validity == GPX_VALIDITY_VALID)
     {
         CPLDebug("GPX", "%s seems to be a GPX file.", pszFilename);
-        if (bUseExtensions)
+        if( bUseExtensions )
             CPLDebug("GPX", "It uses <extensions>");
 
         if (pszVersion == NULL)
@@ -392,11 +406,11 @@ int OGRGPXDataSource::Open( const char * pszFilename, int bUpdateIn)
 
     return (validity == GPX_VALIDITY_VALID);
 #else
-    char aBuf[256];
     VSILFILE* fp = VSIFOpenL(pszFilename, "r");
     if (fp)
     {
-        unsigned int nLen = (unsigned int)VSIFReadL( aBuf, 1, 255, fp );
+        char aBuf[256];
+        unsigned int nLen = static_cast<unsigned int>(VSIFReadL( aBuf, 1, 255, fp ));
         aBuf[nLen] = 0;
         if (strstr(aBuf, "<?xml") && strstr(aBuf, "<gpx"))
         {
@@ -414,7 +428,7 @@ int OGRGPXDataSource::Open( const char * pszFilename, int bUpdateIn)
 /*                               Create()                               */
 /************************************************************************/
 
-int OGRGPXDataSource::Create( const char *pszFilename, 
+int OGRGPXDataSource::Create( const char *pszFilename,
                               char **papszOptions )
 {
     if( fpOutput != NULL)
@@ -438,7 +452,7 @@ int OGRGPXDataSource::Create( const char *pszFilename,
                  pszFilename);
         return FALSE;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create the output file.                                         */
 /* -------------------------------------------------------------------- */
@@ -447,15 +461,15 @@ int OGRGPXDataSource::Create( const char *pszFilename,
 
     if( strcmp(pszName, "/vsistdout/") == 0 )
     {
-        bIsBackSeekable = FALSE;
+        bIsBackSeekable = false;
         fpOutput = VSIFOpenL( pszFilename, "w" );
     }
     else
         fpOutput = VSIFOpenL( pszFilename, "w+" );
     if( fpOutput == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Failed to create GPX file %s.", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to create GPX file %s.",
                   pszFilename );
         return FALSE;
     }
@@ -465,43 +479,44 @@ int OGRGPXDataSource::Create( const char *pszFilename,
 /* -------------------------------------------------------------------- */
     const char *pszCRLFFormat = CSLFetchNameValue( papszOptions, "LINEFORMAT");
 
-    int bUseCRLF;
-    if( pszCRLFFormat == NULL )
-    {
+    bool bUseCRLF =
 #ifdef WIN32
-        bUseCRLF = TRUE;
+        true
 #else
-        bUseCRLF = FALSE;
+        false
 #endif
+    ;
+    if( pszCRLFFormat == NULL )
+    {
+        // Use default value for OS.
     }
     else if( EQUAL(pszCRLFFormat,"CRLF") )
-        bUseCRLF = TRUE;
+        bUseCRLF = true;
     else if( EQUAL(pszCRLFFormat,"LF") )
-        bUseCRLF = FALSE;
+        bUseCRLF = false;
     else
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "LINEFORMAT=%s not understood, use one of CRLF or LF.",
                   pszCRLFFormat );
-#ifdef WIN32
-        bUseCRLF = TRUE;
-#else
-        bUseCRLF = FALSE;
-#endif
+        // Use default value for OS.
     }
     pszEOL = (bUseCRLF) ? "\r\n" : "\n";
 
 /* -------------------------------------------------------------------- */
 /*      Look at use extensions options.                                 */
 /* -------------------------------------------------------------------- */
-    const char* pszUseExtensions = CSLFetchNameValue( papszOptions, "GPX_USE_EXTENSIONS");
+    const char* pszUseExtensions =
+        CSLFetchNameValue( papszOptions, "GPX_USE_EXTENSIONS");
     const char* pszExtensionsNSURL = NULL;
-    if (pszUseExtensions && CSLTestBoolean(pszUseExtensions))
+    if (pszUseExtensions && CPLTestBool(pszUseExtensions))
     {
-        bUseExtensions = TRUE;
+        bUseExtensions = true;
 
-        const char* pszExtensionsNSOption = CSLFetchNameValue( papszOptions, "GPX_EXTENSIONS_NS");
-        const char* pszExtensionsNSURLOption = CSLFetchNameValue( papszOptions, "GPX_EXTENSIONS_NS_URL");
+        const char* pszExtensionsNSOption =
+            CSLFetchNameValue( papszOptions, "GPX_EXTENSIONS_NS");
+        const char* pszExtensionsNSURLOption =
+            CSLFetchNameValue( papszOptions, "GPX_EXTENSIONS_NS_URL");
         if (pszExtensionsNSOption && pszExtensionsNSURLOption)
         {
             pszExtensionsNS = CPLStrdup(pszExtensionsNSOption);
@@ -513,24 +528,25 @@ int OGRGPXDataSource::Create( const char *pszFilename,
             pszExtensionsNSURL = "http://osgeo.org/gdal";
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*     Output header of GPX file.                                       */
 /* -------------------------------------------------------------------- */
     PrintLine("<?xml version=\"1.0\"?>");
     VSIFPrintfL(fpOutput, "<gpx version=\"1.1\" creator=\"GDAL " GDAL_RELEASE_NAME "\" ");
     VSIFPrintfL(fpOutput, "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ");
-    if (bUseExtensions)
-        VSIFPrintfL(fpOutput, "xmlns:%s=\"%s\" ", pszExtensionsNS, pszExtensionsNSURL);
+    if( bUseExtensions )
+        VSIFPrintfL( fpOutput, "xmlns:%s=\"%s\" ",
+                     pszExtensionsNS, pszExtensionsNSURL);
     VSIFPrintfL(fpOutput, "xmlns=\"http://www.topografix.com/GPX/1/1\" ");
     PrintLine("xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\">");
-    if (bIsBackSeekable)
+    if( bIsBackSeekable )
     {
       /* Reserve space for <metadata><bounds/></metadata> */
       char szMetadata[SPACE_FOR_METADATA+1];
       memset(szMetadata, ' ', SPACE_FOR_METADATA);
       szMetadata[SPACE_FOR_METADATA] = '\0';
-      nOffsetBounds = (int) VSIFTellL(fpOutput);
+      nOffsetBounds = static_cast<int>( VSIFTellL(fpOutput));
       PrintLine("%s", szMetadata);
     }
 
diff --git a/ogr/ogrsf_frmts/gpx/ogrgpxdriver.cpp b/ogr/ogrsf_frmts/gpx/ogrgpxdriver.cpp
index 3bd09a2..826f661 100644
--- a/ogr/ogrsf_frmts/gpx/ogrgpxdriver.cpp
+++ b/ogr/ogrsf_frmts/gpx/ogrgpxdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgpxdriver.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogrgpxdriver.cpp 32663 2016-01-02 03:39:54Z goatbar $
  *
  * Project:  GPX Translator
  * Purpose:  Implements OGRGPXDriver.
@@ -30,7 +30,7 @@
 #include "ogr_gpx.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrgpxdriver.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogrgpxdriver.cpp 32663 2016-01-02 03:39:54Z goatbar $");
 
 /************************************************************************/
 /*                                Open()                                */
@@ -42,7 +42,7 @@ static GDALDataset *OGRGPXDriverOpen( GDALOpenInfo* poOpenInfo )
     if( poOpenInfo->eAccess == GA_Update || poOpenInfo->fpL == NULL )
         return NULL;
 
-    if( strstr((const char*)poOpenInfo->pabyHeader, "<gpx") == NULL )
+    if( strstr(reinterpret_cast<const char*>(poOpenInfo->pabyHeader), "<gpx") == NULL )
         return NULL;
 
     OGRGPXDataSource   *poDS = new OGRGPXDataSource();
@@ -98,23 +98,21 @@ static CPLErr OGRGPXDriverDelete( const char *pszFilename )
 void RegisterOGRGPX()
 
 {
-    if (! GDAL_CHECK_VERSION("OGR/GPX driver"))
+    if( !GDAL_CHECK_VERSION("OGR/GPX driver") )
         return;
-    GDALDriver  *poDriver;
 
-    if( GDALGetDriverByName( "GPX" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    if( GDALGetDriverByName( "GPX" ) != NULL )
+        return;
 
-        poDriver->SetDescription( "GPX" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "GPX" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gpx" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_gpx.html" );
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    poDriver->SetDescription( "GPX" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "GPX" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gpx" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_gpx.html" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 #ifdef WIN32
 "  <Option name='LINEFORMAT' type='string-select' description='end-of-line sequence' default='CRLF'>"
@@ -129,18 +127,17 @@ void RegisterOGRGPX()
 "  <Option name='GPX_EXTENSIONS_NS_URL' type='string' description='Namespace URI' default='http://osgeo.org/gdal'/>"
 "</CreationOptionList>");
 
-        poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
 "<LayerCreationOptionList>"
 "  <Option name='FORCE_GPX_TRACK' type='boolean' description='Whether to force layers with geometries of type wkbLineString as tracks' default='NO'/>"
 "  <Option name='FORCE_GPX_ROUTE' type='boolean' description='Whether to force layers with geometries of type wkbMultiLineString (with single line string in them) as routes' default='NO'/>"
 "</LayerCreationOptionList>");
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = OGRGPXDriverOpen;
-        poDriver->pfnCreate = OGRGPXDriverCreate;
-        poDriver->pfnDelete = OGRGPXDriverDelete;
+    poDriver->pfnOpen = OGRGPXDriverOpen;
+    poDriver->pfnCreate = OGRGPXDriverCreate;
+    poDriver->pfnDelete = OGRGPXDriverDelete;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/gpx/ogrgpxlayer.cpp b/ogr/ogrsf_frmts/gpx/ogrgpxlayer.cpp
index 58509dc..0877447 100644
--- a/ogr/ogrsf_frmts/gpx/ogrgpxlayer.cpp
+++ b/ogr/ogrsf_frmts/gpx/ogrgpxlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgpxlayer.cpp 31752 2015-11-25 11:02:14Z rouault $
+ * $Id: ogrgpxlayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  GPX Translator
  * Purpose:  Implements OGRGPXLayer class.
@@ -29,20 +29,24 @@
 
 #include "ogr_gpx.h"
 #include "cpl_conv.h"
-#include "cpl_string.h"
 #include "cpl_minixml.h"
+#include "cpl_string.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrgpxlayer.cpp 31752 2015-11-25 11:02:14Z rouault $");
+CPL_CVSID("$Id: ogrgpxlayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
-#define FLD_TRACK_FID       0
-#define FLD_TRACK_SEG_ID    1
-#define FLD_TRACK_PT_ID     2
-#define FLD_TRACK_NAME      3
+static const int FLD_TRACK_FID = 0;
+static const int FLD_TRACK_SEG_ID = 1;
+#ifdef HAVE_EXPAT
+static const int FLD_TRACK_PT_ID = 2;
+#endif
+static const int FLD_TRACK_NAME = 3;
 
-#define FLD_ROUTE_FID       0
-#define FLD_ROUTE_PT_ID     1
-#define FLD_ROUTE_NAME      2
+static const int FLD_ROUTE_FID = 0;
+#ifdef HAVE_EXPAT
+static const int FLD_ROUTE_PT_ID = 1;
+#endif
+static const int FLD_ROUTE_NAME = 2;
 
 /************************************************************************/
 /*                            OGRGPXLayer()                             */
@@ -53,53 +57,82 @@ CPL_CVSID("$Id: ogrgpxlayer.cpp 31752 2015-11-25 11:02:14Z rouault $");
 
 OGRGPXLayer::OGRGPXLayer( const char* pszFilename,
                           const char* pszLayerName,
-                          GPXGeometryType gpxGeomType,
-                          OGRGPXDataSource* poDS,
-                          int bWriteMode)
-
+                          GPXGeometryType gpxGeomTypeIn,
+                          OGRGPXDataSource* poDSIn,
+                          int bWriteModeIn ) :
+    bWriteMode(CPL_TO_BOOL(bWriteModeIn)),
+    nNextFID(0),
+#ifdef HAVE_EXPAT
+    oSchemaParser(NULL),
+#endif
+    inInterestingElement(false),
+    hasFoundLat(false),
+    hasFoundLon(false),
+#ifdef HAVE_EXPAT
+    latVal(0.0),
+    lonVal(0.0),
+    iCurrentField(0),
+#endif
+    multiLineString(NULL),
+    lineString(NULL),
+    depthLevel(0),
+    interestingDepthLevel(0),
+#ifdef HAVE_EXPAT
+    currentFieldDefn(NULL),
+    inExtensions(false),
+    extensionsDepthLevel(0),
+    inLink(false),
+    iCountLink(0),
+#endif
+    trkFID(0),
+    trkSegId(0),
+    trkSegPtId(0),
+    rteFID(0),
+    rtePtId(0)
+#ifdef HAVE_EXPAT
+    ,
+    bStopParsing(false),
+    nWithoutEventCounter(0),
+    nDataHandlerCounter(0)
+#endif
 {
-    const char* gpxVersion = poDS->GetVersion();
-
-    int i;
+    poDS = poDSIn;
+    gpxGeomType = gpxGeomTypeIn;
 
-    eof = FALSE;
-    nNextFID = 0;
+#ifdef HAVE_EXPAT
+    const char* gpxVersion = poDS->GetVersion();
+#endif
 
-    this->poDS = poDS;
-    this->bWriteMode = bWriteMode;
-    this->gpxGeomType = gpxGeomType;
-    
-    pszElementToScan = pszLayerName;
-    
     nMaxLinks = atoi(CPLGetConfigOption("GPX_N_MAX_LINKS", "2"));
     if (nMaxLinks < 0)
         nMaxLinks = 2;
     if (nMaxLinks > 100)
         nMaxLinks = 100;
 
-    nFeatures = 0;
-    
-    bEleAs25D =  CSLTestBoolean(CPLGetConfigOption("GPX_ELE_AS_25D", "NO"));
-    
-    int bShortNames  = CSLTestBoolean(CPLGetConfigOption("GPX_SHORT_NAMES", "NO"));
-    
+    bEleAs25D = CPLTestBool( CPLGetConfigOption( "GPX_ELE_AS_25D", "NO" ) );
+
+    const bool bShortNames =
+        CPLTestBool( CPLGetConfigOption( "GPX_SHORT_NAMES", "NO" ) );
+
     poFeatureDefn = new OGRFeatureDefn( pszLayerName );
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
-    
+
     if (gpxGeomType == GPX_TRACK_POINT)
     {
         /* Don't move this code. This fields must be number 0, 1 and 2 */
         /* in order to make OGRGPXLayer::startElementCbk work */
         OGRFieldDefn oFieldTrackFID("track_fid", OFTInteger );
         poFeatureDefn->AddFieldDefn( &oFieldTrackFID );
-        
-        OGRFieldDefn oFieldTrackSegID((bShortNames) ? "trksegid" : "track_seg_id", OFTInteger );
+
+        OGRFieldDefn oFieldTrackSegID(
+            (bShortNames) ? "trksegid" : "track_seg_id", OFTInteger );
         poFeatureDefn->AddFieldDefn( &oFieldTrackSegID );
-        
-        OGRFieldDefn oFieldTrackSegPointID((bShortNames) ? "trksegptid" : "track_seg_point_id", OFTInteger );
+
+        OGRFieldDefn oFieldTrackSegPointID(
+            (bShortNames) ? "trksegptid" : "track_seg_point_id", OFTInteger );
         poFeatureDefn->AddFieldDefn( &oFieldTrackSegPointID );
-        
+
         if (bWriteMode)
         {
             OGRFieldDefn oFieldName("track_name", OFTString );
@@ -111,8 +144,9 @@ OGRGPXLayer::OGRGPXLayer( const char* pszFilename,
         /* Don't move this code. See above */
         OGRFieldDefn oFieldRouteFID("route_fid", OFTInteger );
         poFeatureDefn->AddFieldDefn( &oFieldRouteFID );
-        
-        OGRFieldDefn oFieldRoutePointID((bShortNames) ? "rteptid" : "route_point_id", OFTInteger );
+
+        OGRFieldDefn oFieldRoutePointID(
+            (bShortNames) ? "rteptid" : "route_point_id", OFTInteger );
         poFeatureDefn->AddFieldDefn( &oFieldRoutePointID );
 
         if (bWriteMode)
@@ -130,96 +164,100 @@ OGRGPXLayer::OGRGPXLayer( const char* pszFilename,
     {
         poFeatureDefn->SetGeomType((bEleAs25D) ? wkbPoint25D : wkbPoint);
         /* Position info */
-        
+
         OGRFieldDefn oFieldEle("ele", OFTReal );
         poFeatureDefn->AddFieldDefn( &oFieldEle );
-        
+
         OGRFieldDefn oFieldTime("time", OFTDateTime );
         poFeatureDefn->AddFieldDefn( &oFieldTime );
-        
+
+#ifdef HAVE_EXPAT
         if (gpxGeomType == GPX_TRACK_POINT &&
             gpxVersion && strcmp(gpxVersion, "1.0") == 0)
         {
             OGRFieldDefn oFieldCourse("course", OFTReal );
             poFeatureDefn->AddFieldDefn( &oFieldCourse );
-            
+
             OGRFieldDefn oFieldSpeed("speed", OFTReal );
             poFeatureDefn->AddFieldDefn( &oFieldSpeed );
         }
-        
+#endif
+
         OGRFieldDefn oFieldMagVar("magvar", OFTReal );
         poFeatureDefn->AddFieldDefn( &oFieldMagVar );
-    
+
         OGRFieldDefn oFieldGeoidHeight("geoidheight", OFTReal );
         poFeatureDefn->AddFieldDefn( &oFieldGeoidHeight );
-            
+
         /* Description info */
-        
+
         OGRFieldDefn oFieldName("name", OFTString );
         poFeatureDefn->AddFieldDefn( &oFieldName );
-        
+
         OGRFieldDefn oFieldCmt("cmt", OFTString );
         poFeatureDefn->AddFieldDefn( &oFieldCmt );
-        
+
         OGRFieldDefn oFieldDesc("desc", OFTString );
         poFeatureDefn->AddFieldDefn( &oFieldDesc );
-        
+
         OGRFieldDefn oFieldSrc("src", OFTString );
         poFeatureDefn->AddFieldDefn( &oFieldSrc );
-        
+
+#ifdef HAVE_EXPAT
         if (gpxVersion && strcmp(gpxVersion, "1.0") == 0)
         {
             OGRFieldDefn oFieldUrl("url", OFTString );
             poFeatureDefn->AddFieldDefn( &oFieldUrl );
-            
+
             OGRFieldDefn oFieldUrlName("urlname", OFTString );
             poFeatureDefn->AddFieldDefn( &oFieldUrlName );
         }
         else
+#endif
         {
-            for(i=1;i<=nMaxLinks;i++)
+            for(int i=1;i<=nMaxLinks;i++)
             {
                 char szFieldName[32];
-                sprintf(szFieldName, "link%d_href", i);
+                snprintf(szFieldName, sizeof(szFieldName), "link%d_href", i);
                 OGRFieldDefn oFieldLinkHref( szFieldName, OFTString );
                 poFeatureDefn->AddFieldDefn( &oFieldLinkHref );
-                
-                sprintf(szFieldName, "link%d_text", i);
+
+                snprintf(szFieldName, sizeof(szFieldName), "link%d_text", i);
                 OGRFieldDefn oFieldLinkText( szFieldName, OFTString );
                 poFeatureDefn->AddFieldDefn( &oFieldLinkText );
-                
-                sprintf(szFieldName, "link%d_type", i);
+
+                snprintf(szFieldName, sizeof(szFieldName), "link%d_type", i);
                 OGRFieldDefn oFieldLinkType( szFieldName, OFTString );
                 poFeatureDefn->AddFieldDefn( &oFieldLinkType );
             }
         }
-        
+
         OGRFieldDefn oFieldSym("sym", OFTString );
         poFeatureDefn->AddFieldDefn( &oFieldSym );
-        
+
         OGRFieldDefn oFieldType("type", OFTString );
         poFeatureDefn->AddFieldDefn( &oFieldType );
-    
+
         /* Accuracy info */
-        
+
         OGRFieldDefn oFieldFix("fix", OFTString );
         poFeatureDefn->AddFieldDefn( &oFieldFix );
-        
+
         OGRFieldDefn oFieldSat("sat", OFTInteger );
         poFeatureDefn->AddFieldDefn( &oFieldSat );
-        
+
         OGRFieldDefn oFieldHdop("hdop", OFTReal );
         poFeatureDefn->AddFieldDefn( &oFieldHdop );
-        
+
         OGRFieldDefn oFieldVdop("vdop", OFTReal );
         poFeatureDefn->AddFieldDefn( &oFieldVdop );
-        
+
         OGRFieldDefn oFieldPdop("pdop", OFTReal );
         poFeatureDefn->AddFieldDefn( &oFieldPdop );
-        
+
         OGRFieldDefn oFieldAgeofgpsdata("ageofdgpsdata", OFTReal );
         poFeatureDefn->AddFieldDefn( &oFieldAgeofgpsdata );
-        
+
         OGRFieldDefn oFieldDgpsid("dgpsid", OFTInteger );
         poFeatureDefn->AddFieldDefn( &oFieldDgpsid );
     }
@@ -229,52 +267,51 @@ OGRGPXLayer::OGRGPXLayer( const char* pszFilename,
             poFeatureDefn->SetGeomType((bEleAs25D) ? wkbMultiLineString25D : wkbMultiLineString);
         else
             poFeatureDefn->SetGeomType((bEleAs25D) ? wkbLineString25D : wkbLineString);
-        
+
         OGRFieldDefn oFieldName("name", OFTString );
         poFeatureDefn->AddFieldDefn( &oFieldName );
-        
+
         OGRFieldDefn oFieldCmt("cmt", OFTString );
         poFeatureDefn->AddFieldDefn( &oFieldCmt );
-        
+
         OGRFieldDefn oFieldDesc("desc", OFTString );
         poFeatureDefn->AddFieldDefn( &oFieldDesc );
-        
+
         OGRFieldDefn oFieldSrc("src", OFTString );
         poFeatureDefn->AddFieldDefn( &oFieldSrc );
-        
-        for(i=1;i<=nMaxLinks;i++)
+
+        for(int i=1;i<=nMaxLinks;i++)
         {
             char szFieldName[32];
-            sprintf(szFieldName, "link%d_href", i);
+            snprintf(szFieldName, sizeof(szFieldName), "link%d_href", i);
             OGRFieldDefn oFieldLinkHref( szFieldName, OFTString );
             poFeatureDefn->AddFieldDefn( &oFieldLinkHref );
-            
-            sprintf(szFieldName, "link%d_text", i);
+
+            snprintf(szFieldName, sizeof(szFieldName), "link%d_text", i);
             OGRFieldDefn oFieldLinkText( szFieldName, OFTString );
             poFeatureDefn->AddFieldDefn( &oFieldLinkText );
-            
-            sprintf(szFieldName, "link%d_type", i);
+
+            snprintf(szFieldName, sizeof(szFieldName), "link%d_type", i);
             OGRFieldDefn oFieldLinkType( szFieldName, OFTString );
             poFeatureDefn->AddFieldDefn( &oFieldLinkType );
         }
-        
+
         OGRFieldDefn oFieldNumber("number", OFTInteger );
         poFeatureDefn->AddFieldDefn( &oFieldNumber );
-        
+
         OGRFieldDefn oFieldType("type", OFTString );
         poFeatureDefn->AddFieldDefn( &oFieldType );
     }
-    
+
     /* Number of 'standard' GPX attributes */
     nGPXFields = poFeatureDefn->GetFieldCount();
-   
+
     ppoFeatureTab = NULL;
     nFeatureTabIndex = 0;
     nFeatureTabLength = 0;
     pszSubElementName = NULL;
     pszSubElementValue = NULL;
     nSubElementValueLen = 0;
-    bStopParsing = FALSE;
 
     poSRS = new OGRSpatialReference("GEOGCS[\"WGS 84\", "
         "   DATUM[\"WGS_1984\","
@@ -295,7 +332,7 @@ OGRGPXLayer::OGRGPXLayer( const char* pszFilename,
     oParser = NULL;
 #endif
 
-    if (bWriteMode == FALSE)
+    if( !bWriteMode )
     {
         fpGPX = VSIFOpenL( pszFilename, "r" );
         if( fpGPX == NULL )
@@ -305,7 +342,7 @@ OGRGPXLayer::OGRGPXLayer( const char* pszFilename,
         }
 
         if (poDS->GetUseExtensions() ||
-            CSLTestBoolean(CPLGetConfigOption("GPX_USE_EXTENSIONS", "FALSE")))
+            CPLTestBool(CPLGetConfigOption("GPX_USE_EXTENSIONS", "FALSE")))
         {
             LoadExtensionsSchema();
         }
@@ -328,15 +365,14 @@ OGRGPXLayer::~OGRGPXLayer()
         XML_ParserFree(oParser);
 #endif
     poFeatureDefn->Release();
-    
+
     if( poSRS != NULL )
         poSRS->Release();
 
     CPLFree(pszSubElementName);
     CPLFree(pszSubElementValue);
 
-    int i;
-    for(i=nFeatureTabIndex;i<nFeatureTabLength;i++)
+    for( int i = nFeatureTabIndex; i < nFeatureTabLength; i++ )
         delete ppoFeatureTab[i];
     CPLFree(ppoFeatureTab);
 
@@ -349,19 +385,20 @@ OGRGPXLayer::~OGRGPXLayer()
 
 #ifdef HAVE_EXPAT
 
-static void XMLCALL startElementCbk(void *pUserData, const char *pszName, const char **ppszAttr)
+static void XMLCALL startElementCbk(
+    void *pUserData, const char *pszName, const char **ppszAttr)
 {
-    ((OGRGPXLayer*)pUserData)->startElementCbk(pszName, ppszAttr);
+    static_cast<OGRGPXLayer *>(pUserData)->startElementCbk(pszName, ppszAttr);
 }
 
 static void XMLCALL endElementCbk(void *pUserData, const char *pszName)
 {
-    ((OGRGPXLayer*)pUserData)->endElementCbk(pszName);
+    static_cast<OGRGPXLayer *>(pUserData)->endElementCbk(pszName);
 }
 
 static void XMLCALL dataHandlerCbk(void *pUserData, const char *data, int nLen)
 {
-    ((OGRGPXLayer*)pUserData)->dataHandlerCbk(data, nLen);
+    static_cast<OGRGPXLayer *>(pUserData)->dataHandlerCbk(data, nLen);
 }
 
 #endif
@@ -373,7 +410,6 @@ static void XMLCALL dataHandlerCbk(void *pUserData, const char *data, int nLen)
 void OGRGPXLayer::ResetReading()
 
 {
-    eof = FALSE;
     nNextFID = 0;
     if (fpGPX)
     {
@@ -388,17 +424,16 @@ void OGRGPXLayer::ResetReading()
         XML_SetUserData(oParser, this);
 #endif
     }
-    hasFoundLat = FALSE;
-    hasFoundLon = FALSE;
-    inInterestingElement = FALSE;
+    hasFoundLat = false;
+    hasFoundLon = false;
+    inInterestingElement = false;
     CPLFree(pszSubElementName);
     pszSubElementName = NULL;
     CPLFree(pszSubElementValue);
     pszSubElementValue = NULL;
     nSubElementValueLen = 0;
-    
-    int i;
-    for(i=nFeatureTabIndex;i<nFeatureTabLength;i++)
+
+    for( int i = nFeatureTabIndex;i<nFeatureTabLength; i++ )
         delete ppoFeatureTab[i];
     CPLFree(ppoFeatureTab);
     nFeatureTabIndex = 0;
@@ -412,7 +447,7 @@ void OGRGPXLayer::ResetReading()
 
     depthLevel = 0;
     interestingDepthLevel = 0;
-    
+
     trkFID = trkSegId = trkSegPtId = 0;
     rteFID = rtePtId = 0;
 }
@@ -420,15 +455,14 @@ void OGRGPXLayer::ResetReading()
 #ifdef HAVE_EXPAT
 
 /************************************************************************/
-/*                        startElementCbk()                            */
+/*                        startElementCbk()                             */
 /************************************************************************/
 
 /** Replace ':' from XML NS element name by '_' more OGR friendly */
 static char* OGRGPX_GetOGRCompatibleTagName(const char* pszName)
 {
     char* pszModName = CPLStrdup(pszName);
-    int i;
-    for(i=0;pszModName[i] != 0;i++)
+    for( int i = 0; pszModName[i] != 0; i++ )
     {
         if (pszModName[i] == ':')
             pszModName[i] = '_';
@@ -438,14 +472,14 @@ static char* OGRGPX_GetOGRCompatibleTagName(const char* pszName)
 
 void OGRGPXLayer::AddStrToSubElementValue(const char* pszStr)
 {
-    int len = strlen(pszStr);
-    char* pszNewSubElementValue = (char*)
-            VSIRealloc(pszSubElementValue, nSubElementValueLen + len + 1);
+    int len = (int)strlen(pszStr);
+    char* pszNewSubElementValue = static_cast<char *>(
+            VSI_REALLOC_VERBOSE(
+                pszSubElementValue, nSubElementValueLen + len + 1) );
     if (pszNewSubElementValue == NULL)
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
         XML_StopParser(oParser, XML_FALSE);
-        bStopParsing = TRUE;
+        bStopParsing = true;
         return;
     }
     pszSubElementValue = pszNewSubElementValue;
@@ -455,8 +489,6 @@ void OGRGPXLayer::AddStrToSubElementValue(const char* pszStr)
 
 void OGRGPXLayer::startElementCbk(const char *pszName, const char **ppszAttr)
 {
-    int i;
-
     if (bStopParsing) return;
 
     nWithoutEventCounter = 0;
@@ -471,23 +503,23 @@ void OGRGPXLayer::startElementCbk(const char *pszName, const char **ppszAttr)
             delete poFeature;
 
         poFeature = new OGRFeature( poFeatureDefn );
-        inInterestingElement = TRUE;
-        hasFoundLat = FALSE;
-        hasFoundLon = FALSE;
-        inExtensions = FALSE;
-        inLink = FALSE;
+        inInterestingElement = true;
+        hasFoundLat = false;
+        hasFoundLon = false;
+        inExtensions = false;
+        inLink = false;
         iCountLink = 0;
 
-        for (i = 0; ppszAttr[i]; i += 2)
+        for (int i = 0; ppszAttr[i]; i += 2)
         {
             if (strcmp(ppszAttr[i], "lat") == 0)
             {
-                hasFoundLat = TRUE;
+                hasFoundLat = true;
                 latVal = CPLAtof(ppszAttr[i + 1]);
             }
             else if (strcmp(ppszAttr[i], "lon") == 0)
             {
-                hasFoundLon = TRUE;
+                hasFoundLon = true;
                 lonVal = CPLAtof(ppszAttr[i + 1]);
             }
         }
@@ -519,11 +551,11 @@ void OGRGPXLayer::startElementCbk(const char *pszName, const char **ppszAttr)
 
         if (poFeature)
             delete poFeature;
-        inExtensions = FALSE;
-        inLink = FALSE;
+        inExtensions = false;
+        inLink = false;
         iCountLink = 0;
         poFeature = new OGRFeature( poFeatureDefn );
-        inInterestingElement = TRUE;
+        inInterestingElement = true;
 
         multiLineString = new OGRMultiLineString ();
         lineString = NULL;
@@ -544,14 +576,14 @@ void OGRGPXLayer::startElementCbk(const char *pszName, const char **ppszAttr)
     else if (gpxGeomType == GPX_ROUTE && strcmp(pszName, "rte") == 0)
     {
         interestingDepthLevel = depthLevel;
-        
+
         if (poFeature)
             delete poFeature;
 
         poFeature = new OGRFeature( poFeatureDefn );
-        inInterestingElement = TRUE;
-        inExtensions = FALSE;
-        inLink = FALSE;
+        inInterestingElement = true;
+        inExtensions = false;
+        inLink = false;
         iCountLink = 0;
 
         lineString = new OGRLineString ();
@@ -579,18 +611,18 @@ void OGRGPXLayer::startElementCbk(const char *pszName, const char **ppszAttr)
         {
             if (lineString)
             {
-                hasFoundLat = FALSE;
-                hasFoundLon = FALSE;
-                for (i = 0; ppszAttr[i]; i += 2)
+                hasFoundLat = false;
+                hasFoundLon = false;
+                for (int i = 0; ppszAttr[i]; i += 2)
                 {
                     if (strcmp(ppszAttr[i], "lat") == 0)
                     {
-                        hasFoundLat = TRUE;
+                        hasFoundLat = true;
                         latVal = CPLAtof(ppszAttr[i + 1]);
                     }
                     else if (strcmp(ppszAttr[i], "lon") == 0)
                     {
-                        hasFoundLon = TRUE;
+                        hasFoundLon = true;
                         lonVal = CPLAtof(ppszAttr[i + 1]);
                     }
                 }
@@ -606,18 +638,18 @@ void OGRGPXLayer::startElementCbk(const char *pszName, const char **ppszAttr)
         {
             if (lineString)
             {
-                hasFoundLat = FALSE;
-                hasFoundLon = FALSE;
-                for (i = 0; ppszAttr[i]; i += 2)
+                hasFoundLat = false;
+                hasFoundLon = false;
+                for (int i = 0; ppszAttr[i]; i += 2)
                 {
                     if (strcmp(ppszAttr[i], "lat") == 0)
                     {
-                        hasFoundLat = TRUE;
+                        hasFoundLat = true;
                         latVal = CPLAtof(ppszAttr[i + 1]);
                     }
                     else if (strcmp(ppszAttr[i], "lon") == 0)
                     {
-                        hasFoundLon = TRUE;
+                        hasFoundLon = true;
                         lonVal = CPLAtof(ppszAttr[i + 1]);
                     }
                 }
@@ -642,7 +674,7 @@ void OGRGPXLayer::startElementCbk(const char *pszName, const char **ppszAttr)
         {
             if (poDS->GetUseExtensions())
             {
-                inExtensions = TRUE;
+                inExtensions = true;
             }
         }
         else if (depthLevel == interestingDepthLevel + 1 ||
@@ -651,7 +683,7 @@ void OGRGPXLayer::startElementCbk(const char *pszName, const char **ppszAttr)
             CPLFree(pszSubElementName);
             pszSubElementName = NULL;
             iCurrentField = -1;
-            
+
             if (strcmp(pszName, "link") == 0)
             {
                 iCountLink++;
@@ -661,7 +693,7 @@ void OGRGPXLayer::startElementCbk(const char *pszName, const char **ppszAttr)
                         strcmp(ppszAttr[0], "href") == 0)
                     {
                         char szFieldName[32];
-                        sprintf(szFieldName, "link%d_href", iCountLink);
+                        snprintf(szFieldName, sizeof(szFieldName), "link%d_href", iCountLink);
                         iCurrentField = poFeatureDefn->GetFieldIndex(szFieldName);
                         poFeature->SetField( iCurrentField, ppszAttr[1]);
                     }
@@ -678,7 +710,7 @@ void OGRGPXLayer::startElementCbk(const char *pszName, const char **ppszAttr)
                                  nMaxLinks);
                     }
                 }
-                inLink = TRUE;
+                inLink = true;
                 iCurrentField = -1;
             }
             else
@@ -696,7 +728,7 @@ void OGRGPXLayer::startElementCbk(const char *pszName, const char **ppszAttr)
                     else
                         bMatch = (strcmp(poFeatureDefn->GetFieldDefn(iField)->GetNameRef(),
                                         pszName ) == 0);
-    
+
                     if (bMatch)
                     {
                         iCurrentField = iField;
@@ -708,7 +740,6 @@ void OGRGPXLayer::startElementCbk(const char *pszName, const char **ppszAttr)
         }
         else if (depthLevel == interestingDepthLevel + 2 && inLink)
         {
-            char szFieldName[32];
             CPLFree(pszSubElementName);
             pszSubElementName = NULL;
             iCurrentField = -1;
@@ -716,13 +747,15 @@ void OGRGPXLayer::startElementCbk(const char *pszName, const char **ppszAttr)
             {
                 if (strcmp(pszName, "type") == 0)
                 {
-                    sprintf(szFieldName, "link%d_type", iCountLink);
+                    char szFieldName[32];
+                    snprintf(szFieldName, sizeof(szFieldName), "link%d_type", iCountLink);
                     iCurrentField = poFeatureDefn->GetFieldIndex(szFieldName);
                     pszSubElementName = CPLStrdup(pszName);
                 }
                 else if (strcmp(pszName, "text") == 0)
                 {
-                    sprintf(szFieldName, "link%d_text", iCountLink);
+                    char szFieldName[32];
+                    snprintf(szFieldName, sizeof(szFieldName), "link%d_text", iCountLink);
                     iCurrentField = poFeatureDefn->GetFieldIndex(szFieldName);
                     pszSubElementName = CPLStrdup(pszName);
                 }
@@ -733,8 +766,7 @@ void OGRGPXLayer::startElementCbk(const char *pszName, const char **ppszAttr)
             AddStrToSubElementValue(
                (ppszAttr[0] == NULL) ? CPLSPrintf("<%s>", pszName) :
                                     CPLSPrintf("<%s ", pszName));
-            int i;
-            for (i = 0; ppszAttr[i]; i += 2)
+            for( int i = 0; ppszAttr[i]; i += 2 )
             {
                 AddStrToSubElementValue(
                     CPLSPrintf("%s=\"%s\" ", ppszAttr[i], ppszAttr[i + 1]));
@@ -767,8 +799,8 @@ void OGRGPXLayer::endElementCbk(const char *pszName)
             (gpxGeomType == GPX_ROUTE_POINT && strcmp(pszName, "rtept") == 0) ||
             (gpxGeomType == GPX_TRACK_POINT && strcmp(pszName, "trkpt") == 0))
         {
-            int bIsValid = (hasFoundLat && hasFoundLon);
-            inInterestingElement = FALSE;
+            const bool bIsValid = (hasFoundLat && hasFoundLon);
+            inInterestingElement = false;
 
             if( bIsValid
                 &&  (m_poFilterGeom == NULL
@@ -798,9 +830,10 @@ void OGRGPXLayer::endElementCbk(const char *pszName)
                     }
                 }
 
-                ppoFeatureTab = (OGRFeature**)
-                        CPLRealloc(ppoFeatureTab,
-                                    sizeof(OGRFeature*) * (nFeatureTabLength + 1));
+                ppoFeatureTab = static_cast<OGRFeature **>(
+                    CPLRealloc(
+                        ppoFeatureTab,
+                        sizeof(OGRFeature*) * (nFeatureTabLength + 1) ) );
                 ppoFeatureTab[nFeatureTabLength] = poFeature;
                 nFeatureTabLength++;
             }
@@ -812,7 +845,7 @@ void OGRGPXLayer::endElementCbk(const char *pszName)
         }
         else if (gpxGeomType == GPX_TRACK && strcmp(pszName, "trk") == 0)
         {
-            inInterestingElement = FALSE;
+            inInterestingElement = false;
             if( (m_poFilterGeom == NULL
                     || FilterGeometry( poFeature->GetGeometryRef() ) )
                 && (m_poAttrQuery == NULL
@@ -820,12 +853,14 @@ void OGRGPXLayer::endElementCbk(const char *pszName)
             {
                 if( poFeature->GetGeometryRef() != NULL )
                 {
-                    poFeature->GetGeometryRef()->assignSpatialReference( poSRS );
+                    poFeature->GetGeometryRef()->
+                        assignSpatialReference( poSRS );
                 }
 
-                ppoFeatureTab = (OGRFeature**)
-                        CPLRealloc(ppoFeatureTab,
-                                    sizeof(OGRFeature*) * (nFeatureTabLength + 1));
+                ppoFeatureTab = static_cast<OGRFeature **>(
+                    CPLRealloc(
+                        ppoFeatureTab,
+                        sizeof(OGRFeature*) * (nFeatureTabLength + 1) ) );
                 ppoFeatureTab[nFeatureTabLength] = poFeature;
                 nFeatureTabLength++;
             }
@@ -844,7 +879,7 @@ void OGRGPXLayer::endElementCbk(const char *pszName)
         }
         else if (gpxGeomType == GPX_ROUTE && strcmp(pszName, "rte") == 0)
         {
-            inInterestingElement = FALSE;
+            inInterestingElement = false;
             if( (m_poFilterGeom == NULL
                     || FilterGeometry( poFeature->GetGeometryRef() ) )
                 && (m_poAttrQuery == NULL
@@ -871,19 +906,22 @@ void OGRGPXLayer::endElementCbk(const char *pszName)
         else if (bEleAs25D &&
                  strcmp(pszName, "ele") == 0 &&
                  lineString != NULL &&
-                 ((gpxGeomType == GPX_ROUTE && depthLevel == interestingDepthLevel + 2) ||
-                 (gpxGeomType == GPX_TRACK && depthLevel == interestingDepthLevel + 3)))
+                 ((gpxGeomType == GPX_ROUTE &&
+                   depthLevel == interestingDepthLevel + 2) ||
+                 (gpxGeomType == GPX_TRACK &&
+                  depthLevel == interestingDepthLevel + 3)))
         {
             poFeature->GetGeometryRef()->setCoordinateDimension(3);
 
             if (nSubElementValueLen)
             {
                 pszSubElementValue[nSubElementValueLen] = 0;
-    
+
                 double val = CPLAtof(pszSubElementValue);
                 int i = lineString->getNumPoints() - 1;
                 if (i >= 0)
-                    lineString->setPoint(i, lineString->getX(i), lineString->getY(i), val);
+                    lineString->setPoint(
+                        i, lineString->getX(i), lineString->getY(i), val);
             }
 
             CPLFree(pszSubElementName);
@@ -895,7 +933,7 @@ void OGRGPXLayer::endElementCbk(const char *pszName)
         else if (depthLevel == interestingDepthLevel + 1 &&
                  strcmp(pszName, "extensions") == 0)
         {
-            inExtensions = FALSE;
+            inExtensions = false;
         }
         else if ((depthLevel == interestingDepthLevel + 1 ||
                  (inExtensions && depthLevel == interestingDepthLevel + 2) ) &&
@@ -925,7 +963,7 @@ void OGRGPXLayer::endElementCbk(const char *pszName)
                 }
             }
             if (strcmp(pszName, "link") == 0)
-                inLink = FALSE;
+                inLink = false;
 
             CPLFree(pszSubElementName);
             pszSubElementName = NULL;
@@ -966,9 +1004,10 @@ void OGRGPXLayer::dataHandlerCbk(const char *data, int nLen)
     nDataHandlerCounter ++;
     if (nDataHandlerCounter >= BUFSIZ)
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "File probably corrupted (million laugh pattern)");
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "File probably corrupted (million laugh pattern)");
         XML_StopParser(oParser, XML_FALSE);
-        bStopParsing = TRUE;
+        bStopParsing = true;
         return;
     }
 
@@ -981,12 +1020,13 @@ void OGRGPXLayer::dataHandlerCbk(const char *data, int nLen)
             if (data[0] == '\n')
                 return;
         }
-        char* pszNewSubElementValue = (char*) VSIRealloc(pszSubElementValue, nSubElementValueLen + nLen + 1);
+        char* pszNewSubElementValue = static_cast<char*>(
+            VSI_REALLOC_VERBOSE(
+                pszSubElementValue, nSubElementValueLen + nLen + 1) );
         if (pszNewSubElementValue == NULL)
         {
-            CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
             XML_StopParser(oParser, XML_FALSE);
-            bStopParsing = TRUE;
+            bStopParsing = true;
             return;
         }
         pszSubElementValue = pszNewSubElementValue;
@@ -994,10 +1034,11 @@ void OGRGPXLayer::dataHandlerCbk(const char *data, int nLen)
         nSubElementValueLen += nLen;
         if (nSubElementValueLen > 100000)
         {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "Too much data inside one element. File probably corrupted");
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Too much data inside one element. "
+                      "File probably corrupted" );
             XML_StopParser(oParser, XML_FALSE);
-            bStopParsing = TRUE;
+            bStopParsing = true;
         }
     }
 }
@@ -1009,7 +1050,7 @@ void OGRGPXLayer::dataHandlerCbk(const char *data, int nLen)
 
 OGRFeature *OGRGPXLayer::GetNextFeature()
 {
-    if (bWriteMode)
+    if( bWriteMode )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "Cannot read features when writing a GPX file");
@@ -1019,20 +1060,21 @@ OGRFeature *OGRGPXLayer::GetNextFeature()
     if (fpGPX == NULL)
         return NULL;
 
+#ifdef HAVE_EXPAT
+
     if (bStopParsing)
         return NULL;
 
-#ifdef HAVE_EXPAT
     if (nFeatureTabIndex < nFeatureTabLength)
     {
         return ppoFeatureTab[nFeatureTabIndex++];
     }
-    
+
     if (VSIFEofL(fpGPX))
         return NULL;
-    
+
     char aBuf[BUFSIZ];
-    
+
     CPLFree(ppoFeatureTab);
     ppoFeatureTab = NULL;
     nFeatureTabLength = 0;
@@ -1043,26 +1085,29 @@ OGRFeature *OGRGPXLayer::GetNextFeature()
     do
     {
         nDataHandlerCounter = 0;
-        unsigned int nLen = (unsigned int)VSIFReadL( aBuf, 1, sizeof(aBuf), fpGPX );
+        unsigned int nLen = static_cast<unsigned int>(
+            VSIFReadL( aBuf, 1, sizeof(aBuf), fpGPX ) );
         nDone = VSIFEofL(fpGPX);
         if (XML_Parse(oParser, aBuf, nLen, nDone) == XML_STATUS_ERROR)
         {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "XML parsing of GPX file failed : %s at line %d, column %d",
-                     XML_ErrorString(XML_GetErrorCode(oParser)),
-                     (int)XML_GetCurrentLineNumber(oParser),
-                     (int)XML_GetCurrentColumnNumber(oParser));
-            bStopParsing = TRUE;
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "XML parsing of GPX file failed : "
+                      "%s at line %d, column %d",
+                      XML_ErrorString(XML_GetErrorCode(oParser)),
+                      static_cast<int>(XML_GetCurrentLineNumber(oParser)),
+                      static_cast<int>(XML_GetCurrentColumnNumber(oParser)) );
+            bStopParsing = true;
             break;
         }
         nWithoutEventCounter ++;
-    } while (!nDone && nFeatureTabLength == 0 && !bStopParsing && nWithoutEventCounter < 10);
+    } while (!nDone && nFeatureTabLength == 0 && !bStopParsing &&
+             nWithoutEventCounter < 10);
 
     if (nWithoutEventCounter == 10)
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Too much data inside one element. File probably corrupted");
-        bStopParsing = TRUE;
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Too much data inside one element. File probably corrupted" );
+        bStopParsing = true;
     }
 
     return (nFeatureTabLength) ? ppoFeatureTab[nFeatureTabIndex++] : NULL;
@@ -1086,8 +1131,7 @@ static char* OGRGPX_GetXMLCompatibleTagName(const char* pszExtensionsNS,
     }
 
     char* pszModName = CPLStrdup(pszName);
-    int i;
-    for(i=0;pszModName[i] != 0;i++)
+    for( int i = 0;pszModName[i] != 0; i++ )
     {
         if (pszModName[i] == ' ')
             pszModName[i] = '_';
@@ -1103,12 +1147,12 @@ static char* OGRGPX_GetUTF8String(const char* pszString)
 {
     char *pszEscaped;
     if (!CPLIsUTF8(pszString, -1) &&
-         CSLTestBoolean(CPLGetConfigOption("OGR_FORCE_ASCII", "YES")))
+         CPLTestBool(CPLGetConfigOption("OGR_FORCE_ASCII", "YES")))
     {
-        static int bFirstTime = TRUE;
+        static bool bFirstTime = true;
         if (bFirstTime)
         {
-            bFirstTime = FALSE;
+            bFirstTime = false;
             CPLError(CE_Warning, CPLE_AppDefined,
                     "%s is not a valid UTF-8 string. Forcing it to ASCII.\n"
                     "If you still want the original string and change the XML file encoding\n"
@@ -1148,19 +1192,19 @@ int OGRGPXLayer::OGRGPX_WriteXMLExtension(const char* pszTagName,
         /* If we detect a Garmin GPX extension, add its xmlns */
         if (strcmp(pszTagName, "gpxx_WaypointExtension") == 0)
             pszXMLNS = " xmlns:gpxx=\"http://www.garmin.com/xmlschemas/GpxExtensions/v3\"";
-            
+
         /* Don't XML escape here */
         char *pszUTF8 = OGRGPX_GetUTF8String( pszContent );
         poDS->PrintLine("    <%s%s>%s</%s>",
                    pszTagNameWithNS, (pszXMLNS) ? pszXMLNS : "", pszUTF8, pszTagNameWithNS);
         CPLFree(pszUTF8);
-        
+
         CPLFree(pszTagNameWithNS);
         CPLDestroyXMLNode(poXML);
-        
+
         return TRUE;
     }
-    
+
     return FALSE;
 }
 
@@ -1170,54 +1214,53 @@ int OGRGPXLayer::OGRGPX_WriteXMLExtension(const char* pszTagName,
 
 static void AddIdent(VSILFILE* fp, int nIdentLevel)
 {
-    int i;
-    for(i=0;i<nIdentLevel;i++)
+    for( int i=0;i < nIdentLevel ; i++)
         VSIFPrintfL(fp, "  ");
 }
 
-void OGRGPXLayer::WriteFeatureAttributes( OGRFeature *poFeature, int nIdentLevel )
+void OGRGPXLayer::WriteFeatureAttributes( OGRFeature *poFeatureIn, int nIdentLevel )
 {
     VSILFILE* fp = poDS->GetOutputFP();
-    int i;
-    
+
     /* Begin with standard GPX fields */
-    for(i=iFirstGPXField;i<nGPXFields;i++)
-    { 
+    int i = iFirstGPXField;
+    for( ; i < nGPXFields; i++ )
+    {
         OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( i );
-        if( poFeature->IsFieldSet( i ) )
+        if( poFeatureIn->IsFieldSet( i ) )
         {
             const char* pszName = poFieldDefn->GetNameRef();
             if (strcmp(pszName, "time") == 0)
             {
-                char* pszDate = OGRGetXMLDateTime(poFeature->GetRawFieldRef(i));
+                char* pszDate = OGRGetXMLDateTime(poFeatureIn->GetRawFieldRef(i));
                 AddIdent(fp, nIdentLevel);
                 poDS->PrintLine("<time>%s</time>", pszDate);
                 CPLFree(pszDate);
             }
-            else if (strncmp(pszName, "link", 4) == 0)
+            else if (STARTS_WITH(pszName, "link"))
             {
                 if (strstr(pszName, "href"))
                 {
                     AddIdent(fp, nIdentLevel);
-                    VSIFPrintfL(fp, "<link href=\"%s\">", poFeature->GetFieldAsString( i ));
-                    if( poFeature->IsFieldSet( i + 1 ) )
-                        VSIFPrintfL(fp, "<text>%s</text>", poFeature->GetFieldAsString( i + 1 ));
-                    if( poFeature->IsFieldSet( i + 2 ) )
-                        VSIFPrintfL(fp, "<type>%s</type>", poFeature->GetFieldAsString( i + 2 ));
+                    VSIFPrintfL(fp, "<link href=\"%s\">", poFeatureIn->GetFieldAsString( i ));
+                    if( poFeatureIn->IsFieldSet( i + 1 ) )
+                        VSIFPrintfL(fp, "<text>%s</text>", poFeatureIn->GetFieldAsString( i + 1 ));
+                    if( poFeatureIn->IsFieldSet( i + 2 ) )
+                        VSIFPrintfL(fp, "<type>%s</type>", poFeatureIn->GetFieldAsString( i + 2 ));
                     poDS->PrintLine("</link>");
                 }
             }
             else if (poFieldDefn->GetType() == OFTReal)
             {
                 char szValue[64];
-                OGRFormatDouble(szValue, sizeof(szValue), poFeature->GetFieldAsDouble(i), '.');
+                OGRFormatDouble(szValue, sizeof(szValue), poFeatureIn->GetFieldAsDouble(i), '.');
                 AddIdent(fp, nIdentLevel);
                 poDS->PrintLine("<%s>%s</%s>", pszName, szValue, pszName);
             }
             else
             {
                 char* pszValue =
-                        OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( i ));
+                        OGRGetXML_UTF8_EscapedString(poFeatureIn->GetFieldAsString( i ));
                 AddIdent(fp, nIdentLevel);
                 poDS->PrintLine("<%s>%s</%s>", pszName, pszValue, pszName);
                 CPLFree(pszValue);
@@ -1235,7 +1278,7 @@ void OGRGPXLayer::WriteFeatureAttributes( OGRFeature *poFeature, int nIdentLevel
         for(;i<n;i++)
         {
             OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( i );
-            if( poFeature->IsFieldSet( i ) )
+            if( poFeatureIn->IsFieldSet( i ) )
             {
                 char* compatibleName =
                         OGRGPX_GetXMLCompatibleTagName(pszExtensionsNS, poFieldDefn->GetNameRef());
@@ -1243,7 +1286,7 @@ void OGRGPXLayer::WriteFeatureAttributes( OGRFeature *poFeature, int nIdentLevel
                 if (poFieldDefn->GetType() == OFTReal)
                 {
                     char szValue[64];
-                    OGRFormatDouble(szValue, sizeof(szValue), poFeature->GetFieldAsDouble(i), '.');
+                    OGRFormatDouble(szValue, sizeof(szValue), poFeatureIn->GetFieldAsDouble(i), '.');
                     AddIdent(fp, nIdentLevel + 1);
                     poDS->PrintLine("<%s:%s>%s</%s:%s>",
                                 pszExtensionsNS,
@@ -1254,24 +1297,28 @@ void OGRGPXLayer::WriteFeatureAttributes( OGRFeature *poFeature, int nIdentLevel
                 }
                 else
                 {
-                    const char *pszRaw = poFeature->GetFieldAsString( i );
+                    const char *pszRaw = poFeatureIn->GetFieldAsString( i );
 
                     /* Try to detect XML content */
                     if (pszRaw[0] == '<' && pszRaw[strlen(pszRaw) - 1] == '>')
                     {
                         if (OGRGPX_WriteXMLExtension( compatibleName, pszRaw))
+                        {
+                            CPLFree(compatibleName);
                             continue;
+                        }
                     }
 
                     /* Try to detect XML escaped content */
-                    else if (strncmp(pszRaw, "<", 4) == 0 &&
-                            strncmp(pszRaw + strlen(pszRaw) - 4, ">", 4) == 0)
+                    else if (STARTS_WITH(pszRaw, "<") &&
+                            STARTS_WITH(pszRaw + strlen(pszRaw) - 4, ">"))
                     {
                         char* pszUnescapedContent = CPLUnescapeString( pszRaw, NULL, CPLES_XML );
 
                         if (OGRGPX_WriteXMLExtension(compatibleName, pszUnescapedContent))
                         {
                             CPLFree(pszUnescapedContent);
+                            CPLFree(compatibleName);
                             continue;
                         }
 
@@ -1311,56 +1358,59 @@ OGRErr OGRGPXLayer::CheckAndFixCoordinatesValidity( double* pdfLatitude, double*
 {
     if (pdfLatitude != NULL && (*pdfLatitude < -90 || *pdfLatitude > 90))
     {
-        static int bFirstWarning = TRUE;
+        static bool bFirstWarning = true;
         if (bFirstWarning)
         {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "Latitude %f is invalid. Valid range is [-90,90]. This warning will not be issued any more",
-                     *pdfLatitude);
-            bFirstWarning = FALSE;
+            bFirstWarning = false;
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Latitude %f is invalid. Valid range is [-90,90]. "
+                      "This warning will not be issued any more",
+                      *pdfLatitude );
         }
-        return CE_Failure;
+        return OGRERR_FAILURE;
     }
 
     if (pdfLongitude != NULL && (*pdfLongitude < -180 || *pdfLongitude > 180))
     {
-        static int bFirstWarning = TRUE;
+        static bool bFirstWarning = true;
         if (bFirstWarning)
         {
-            CPLError(CE_Warning, CPLE_AppDefined,
-                     "Longitude %f has been modified to fit into range [-180,180]. This warning will not be issued any more",
-                     *pdfLongitude);
-            bFirstWarning = FALSE;
+            bFirstWarning = false;
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Longitude %f has been modified to fit into "
+                      "range [-180,180]. This warning will not be "
+                      "issued any more",
+                      *pdfLongitude);
         }
 
         if (*pdfLongitude > 180)
-            *pdfLongitude -= ((int) ((*pdfLongitude+180)/360)*360);
+            *pdfLongitude -= (static_cast<int> ((*pdfLongitude+180)/360)*360);
         else if (*pdfLongitude < -180)
-            *pdfLongitude += ((int) (180 - *pdfLongitude)/360)*360;
+            *pdfLongitude += (static_cast<int> (180 - *pdfLongitude)/360)*360;
 
-        return CE_None;
+        return OGRERR_NONE;
     }
 
-    return CE_None;
+    return OGRERR_NONE;
 }
 
 /************************************************************************/
 /*                           ICreateFeature()                            */
 /************************************************************************/
 
-OGRErr OGRGPXLayer::ICreateFeature( OGRFeature *poFeature )
+OGRErr OGRGPXLayer::ICreateFeature( OGRFeature *poFeatureIn )
 
 {
     VSILFILE* fp = poDS->GetOutputFP();
     if (fp == NULL)
-        return CE_Failure;
-    
+        return OGRERR_FAILURE;
+
     char szLat[64];
     char szLon[64];
     char szAlt[64];
-    
-    OGRGeometry     *poGeom = poFeature->GetGeometryRef();
-    
+
+    OGRGeometry     *poGeom = poFeatureIn->GetGeometryRef();
+
     if (gpxGeomType == GPX_WPT)
     {
         if (poDS->GetLastGPXGeomTypeWritten() == GPX_ROUTE)
@@ -1376,24 +1426,24 @@ OGRErr OGRGPXLayer::ICreateFeature( OGRFeature *poFeature )
                         "Cannot write a 'wpt' element after a 'trk' element.\n");
             return OGRERR_FAILURE;
         }
-        
+
         poDS->SetLastGPXGeomTypeWritten(gpxGeomType);
 
         if ( poGeom == NULL || wkbFlatten(poGeom->getGeometryType()) != wkbPoint )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Features without geometry or with non-ponctual geometries not supported by GPX writer in waypoints layer." );
             return OGRERR_FAILURE;
         }
 
         if ( poGeom->getCoordinateDimension() == 0 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "POINT EMPTY geometries not supported by GPX writer." );
             return OGRERR_FAILURE;
         }
 
-        OGRPoint* point = (OGRPoint*)poGeom;
+        OGRPoint* point = reinterpret_cast<OGRPoint*>(poGeom);
         double lat = point->getY();
         double lon = point->getX();
         CheckAndFixCoordinatesValidity(&lat, &lon);
@@ -1401,7 +1451,7 @@ OGRErr OGRGPXLayer::ICreateFeature( OGRFeature *poFeature )
         OGRFormatDouble(szLat, sizeof(szLat), lat, '.');
         OGRFormatDouble(szLon, sizeof(szLon), lon, '.');
         poDS->PrintLine("<wpt lat=\"%s\" lon=\"%s\">", szLat, szLon);
-        WriteFeatureAttributes(poFeature);
+        WriteFeatureAttributes(poFeatureIn);
         poDS->PrintLine("</wpt>");
     }
     else if (gpxGeomType == GPX_ROUTE)
@@ -1427,7 +1477,7 @@ OGRErr OGRGPXLayer::ICreateFeature( OGRFeature *poFeature )
         if ( poGeom == NULL )
         {
             poDS->PrintLine("<rte>");
-            WriteFeatureAttributes(poFeature);
+            WriteFeatureAttributes(poFeatureIn);
             poDS->PrintLine("</rte>");
             return OGRERR_NONE;
         }
@@ -1437,26 +1487,30 @@ OGRErr OGRGPXLayer::ICreateFeature( OGRFeature *poFeature )
             case wkbLineString:
             case wkbLineString25D:
             {
-                line = (OGRLineString*)poGeom;
+                line = reinterpret_cast<OGRLineString *>(poGeom);
                 break;
             }
 
             case wkbMultiLineString:
             case wkbMultiLineString25D:
             {
-                int nGeometries = ((OGRGeometryCollection*)poGeom)->getNumGeometries ();
+                int nGeometries = reinterpret_cast<OGRGeometryCollection *>(
+                    poGeom)->getNumGeometries ();
                 if (nGeometries == 0)
                 {
                     line = NULL;
                 }
                 else if (nGeometries == 1)
                 {
-                    line = (OGRLineString*) ( ((OGRGeometryCollection*)poGeom)->getGeometryRef(0) );
+                    line = reinterpret_cast<OGRLineString *>(
+                        reinterpret_cast<OGRGeometryCollection*>(
+                            poGeom)->getGeometryRef(0) );
                 }
                 else
                 {
                     CPLError( CE_Failure, CPLE_NotSupported,
-                            "Multiline with more than one line is not supported for 'rte' element.\n");
+                              "Multiline with more than one line is not "
+                              "supported for 'rte' element." );
                     return OGRERR_FAILURE;
                 }
                 break;
@@ -1471,11 +1525,10 @@ OGRErr OGRGPXLayer::ICreateFeature( OGRFeature *poFeature )
             }
         }
 
-        int n = (line) ? line->getNumPoints() : 0;
-        int i;
+        const int n = (line) ? line->getNumPoints() : 0;
         poDS->PrintLine("<rte>");
-        WriteFeatureAttributes(poFeature);
-        for(i=0;i<n;i++)
+        WriteFeatureAttributes(poFeatureIn);
+        for( int i = 0; i < n; i++ )
         {
             double lat = line->getY(i);
             double lon = line->getX(i);
@@ -1514,7 +1567,7 @@ OGRErr OGRGPXLayer::ICreateFeature( OGRFeature *poFeature )
         if (poGeom == NULL)
         {
             poDS->PrintLine("<trk>");
-            WriteFeatureAttributes(poFeature);
+            WriteFeatureAttributes(poFeatureIn);
             poDS->PrintLine("</trk>");
             return OGRERR_NONE;
         }
@@ -1524,13 +1577,12 @@ OGRErr OGRGPXLayer::ICreateFeature( OGRFeature *poFeature )
             case wkbLineString:
             case wkbLineString25D:
             {
-                OGRLineString* line = (OGRLineString*)poGeom;
+                OGRLineString* line = reinterpret_cast<OGRLineString *>(poGeom);
                 int n = line->getNumPoints();
-                int i;
                 poDS->PrintLine("<trk>");
-                WriteFeatureAttributes(poFeature);
+                WriteFeatureAttributes(poFeatureIn);
                 poDS->PrintLine("  <trkseg>");
-                for(i=0;i<n;i++)
+                for( int  i = 0; i < n; i++ )
                 {
                     double lat = line->getY(i);
                     double lon = line->getX(i);
@@ -1538,10 +1590,12 @@ OGRErr OGRGPXLayer::ICreateFeature( OGRFeature *poFeature )
                     poDS->AddCoord(lon, lat);
                     OGRFormatDouble(szLat, sizeof(szLat), lat, '.');
                     OGRFormatDouble(szLon, sizeof(szLon), lon, '.');
-                    poDS->PrintLine("    <trkpt lat=\"%s\" lon=\"%s\">", szLat, szLon);
+                    poDS->PrintLine( "    <trkpt lat=\"%s\" lon=\"%s\">",
+                                     szLat, szLon );
                     if (line->getGeometryType() == wkbLineString25D)
                     {
-                        OGRFormatDouble(szAlt, sizeof(szAlt), line->getZ(i), '.');
+                        OGRFormatDouble( szAlt, sizeof(szAlt),
+                                         line->getZ(i), '.');
                         poDS->PrintLine("        <ele>%s</ele>", szAlt);
                     }
                     poDS->PrintLine("    </trkpt>");
@@ -1554,17 +1608,19 @@ OGRErr OGRGPXLayer::ICreateFeature( OGRFeature *poFeature )
             case wkbMultiLineString:
             case wkbMultiLineString25D:
             {
-                int nGeometries = ((OGRGeometryCollection*)poGeom)->getNumGeometries ();
+                const int nGeometries
+                    = static_cast<OGRGeometryCollection*>(poGeom)->
+                        getNumGeometries();
                 poDS->PrintLine("<trk>");
-                WriteFeatureAttributes(poFeature);
-                int j;
-                for(j=0;j<nGeometries;j++)
+                WriteFeatureAttributes(poFeatureIn);
+                for( int j = 0; j < nGeometries; j++ )
                 {
-                    OGRLineString* line = (OGRLineString*) ( ((OGRGeometryCollection*)poGeom)->getGeometryRef(j) );
-                    int n = (line) ? line->getNumPoints() : 0;
-                    int i;
+                    OGRLineString* line = reinterpret_cast<OGRLineString *>(
+                        reinterpret_cast<OGRGeometryCollection *>(
+                            poGeom)->getGeometryRef(j) );
+                    const int n = (line) ? line->getNumPoints() : 0;
                     poDS->PrintLine("  <trkseg>");
-                    for(i=0;i<n;i++)
+                    for( int i=0; i<n; i++ )
                     {
                         double lat = line->getY(i);
                         double lon = line->getX(i);
@@ -1572,10 +1628,12 @@ OGRErr OGRGPXLayer::ICreateFeature( OGRFeature *poFeature )
                         poDS->AddCoord(lon, lat);
                         OGRFormatDouble(szLat, sizeof(szLat), lat, '.');
                         OGRFormatDouble(szLon, sizeof(szLon), lon, '.');
-                        poDS->PrintLine("    <trkpt lat=\"%s\" lon=\"%s\">", szLat, szLon);
+                        poDS->PrintLine( "    <trkpt lat=\"%s\" lon=\"%s\">",
+                                         szLat, szLon);
                         if (line->getGeometryType() == wkbLineString25D)
                         {
-                            OGRFormatDouble(szAlt, sizeof(szAlt), line->getZ(i), '.');
+                            OGRFormatDouble(szAlt, sizeof(szAlt),
+                                            line->getZ(i), '.');
                             poDS->PrintLine("        <ele>%s</ele>", szAlt);
                         }
                         poDS->PrintLine("    </trkpt>");
@@ -1607,53 +1665,53 @@ OGRErr OGRGPXLayer::ICreateFeature( OGRFeature *poFeature )
 
         if ( poGeom == NULL || wkbFlatten(poGeom->getGeometryType()) != wkbPoint )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Features without geometry or with non-ponctual geometries not supported by GPX writer in route_points layer." );
             return OGRERR_FAILURE;
         }
 
         if ( poGeom->getCoordinateDimension() == 0 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "POINT EMPTY geometries not supported by GPX writer." );
             return OGRERR_FAILURE;
         }
 
-        if ( !poFeature->IsFieldSet(FLD_ROUTE_FID) )
+        if ( !poFeatureIn->IsFieldSet(FLD_ROUTE_FID) )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Field %s must be set.", poFeatureDefn->GetFieldDefn(FLD_ROUTE_FID)->GetNameRef() );
             return OGRERR_FAILURE;
         }
-        if ( poFeature->GetFieldAsInteger(FLD_ROUTE_FID) < 0 )
+        if ( poFeatureIn->GetFieldAsInteger(FLD_ROUTE_FID) < 0 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Invalid value for field %s.", poFeatureDefn->GetFieldDefn(FLD_ROUTE_FID)->GetNameRef() );
             return OGRERR_FAILURE;
         }
 
         poDS->SetLastGPXGeomTypeWritten(gpxGeomType);
 
-        if ( poDS->nLastRteId != poFeature->GetFieldAsInteger(FLD_ROUTE_FID))
+        if ( poDS->nLastRteId != poFeatureIn->GetFieldAsInteger(FLD_ROUTE_FID))
         {
             if (poDS->nLastRteId != -1)
             {
                 poDS->PrintLine("</rte>");
             }
             poDS->PrintLine("<rte>");
-            if ( poFeature->IsFieldSet(FLD_ROUTE_NAME) )
+            if ( poFeatureIn->IsFieldSet(FLD_ROUTE_NAME) )
             {
                 char* pszValue =
-                            OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( FLD_ROUTE_NAME ));
+                            OGRGetXML_UTF8_EscapedString(poFeatureIn->GetFieldAsString( FLD_ROUTE_NAME ));
                 poDS->PrintLine("  <%s>%s</%s>",
                         "name", pszValue, "name");
                 CPLFree(pszValue);
             }
         }
 
-        poDS->nLastRteId = poFeature->GetFieldAsInteger(FLD_ROUTE_FID);
+        poDS->nLastRteId = poFeatureIn->GetFieldAsInteger(FLD_ROUTE_FID);
 
-        OGRPoint* point = (OGRPoint*)poGeom;
+        OGRPoint* point = reinterpret_cast<OGRPoint *>(poGeom);
         double lat = point->getY();
         double lon = point->getX();
         CheckAndFixCoordinatesValidity(&lat, &lon);
@@ -1661,13 +1719,14 @@ OGRErr OGRGPXLayer::ICreateFeature( OGRFeature *poFeature )
         OGRFormatDouble(szLat, sizeof(szLat), lat, '.');
         OGRFormatDouble(szLon, sizeof(szLon), lon, '.');
         poDS->PrintLine("  <rtept lat=\"%s\" lon=\"%s\">", szLat, szLon);
-        WriteFeatureAttributes(poFeature, 2);
+        WriteFeatureAttributes(poFeatureIn, 2);
         poDS->PrintLine("  </rtept>");
 
     }
     else
     {
-        if (poDS->GetLastGPXGeomTypeWritten() == GPX_ROUTE_POINT && poDS->nLastRteId != -1)
+        if( poDS->GetLastGPXGeomTypeWritten() == GPX_ROUTE_POINT &&
+            poDS->nLastRteId != -1 )
         {
             poDS->PrintLine("</rte>");
             poDS->nLastRteId = -1;
@@ -1675,46 +1734,46 @@ OGRErr OGRGPXLayer::ICreateFeature( OGRFeature *poFeature )
 
         if ( poGeom == NULL || wkbFlatten(poGeom->getGeometryType()) != wkbPoint )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Features without geometry or with non-ponctual geometries not supported by GPX writer in track_points layer." );
             return OGRERR_FAILURE;
         }
 
         if ( poGeom->getCoordinateDimension() == 0 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "POINT EMPTY geometries not supported by GPX writer." );
             return OGRERR_FAILURE;
         }
 
-        if ( !poFeature->IsFieldSet(FLD_TRACK_FID) )
+        if ( !poFeatureIn->IsFieldSet(FLD_TRACK_FID) )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Field %s must be set.", poFeatureDefn->GetFieldDefn(FLD_TRACK_FID)->GetNameRef() );
             return OGRERR_FAILURE;
         }
-        if ( poFeature->GetFieldAsInteger(FLD_TRACK_FID) < 0 )
+        if ( poFeatureIn->GetFieldAsInteger(FLD_TRACK_FID) < 0 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Invalid value for field %s.", poFeatureDefn->GetFieldDefn(FLD_TRACK_FID)->GetNameRef() );
             return OGRERR_FAILURE;
         }
-        if ( !poFeature->IsFieldSet(FLD_TRACK_SEG_ID) )
+        if ( !poFeatureIn->IsFieldSet(FLD_TRACK_SEG_ID) )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Field %s must be set.", poFeatureDefn->GetFieldDefn(FLD_TRACK_SEG_ID)->GetNameRef() );
             return OGRERR_FAILURE;
         }
-        if ( poFeature->GetFieldAsInteger(FLD_TRACK_SEG_ID) < 0 )
+        if ( poFeatureIn->GetFieldAsInteger(FLD_TRACK_SEG_ID) < 0 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Invalid value for field %s.", poFeatureDefn->GetFieldDefn(FLD_TRACK_SEG_ID)->GetNameRef() );
             return OGRERR_FAILURE;
         }
 
         poDS->SetLastGPXGeomTypeWritten(gpxGeomType);
 
-        if ( poDS->nLastTrkId != poFeature->GetFieldAsInteger(FLD_TRACK_FID))
+        if ( poDS->nLastTrkId != poFeatureIn->GetFieldAsInteger(FLD_TRACK_FID))
         {
             if (poDS->nLastTrkId != -1)
             {
@@ -1723,10 +1782,10 @@ OGRErr OGRGPXLayer::ICreateFeature( OGRFeature *poFeature )
             }
             poDS->PrintLine("<trk>");
 
-            if ( poFeature->IsFieldSet(FLD_TRACK_NAME) )
+            if ( poFeatureIn->IsFieldSet(FLD_TRACK_NAME) )
             {
                 char* pszValue =
-                            OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( FLD_TRACK_NAME ));
+                            OGRGetXML_UTF8_EscapedString(poFeatureIn->GetFieldAsString( FLD_TRACK_NAME ));
                 poDS->PrintLine("  <%s>%s</%s>",
                         "name", pszValue, "name");
                 CPLFree(pszValue);
@@ -1734,16 +1793,16 @@ OGRErr OGRGPXLayer::ICreateFeature( OGRFeature *poFeature )
 
             poDS->PrintLine("  <trkseg>");
         }
-        else if (poDS->nLastTrkSegId != poFeature->GetFieldAsInteger(FLD_TRACK_SEG_ID))
+        else if (poDS->nLastTrkSegId != poFeatureIn->GetFieldAsInteger(FLD_TRACK_SEG_ID))
         {
             poDS->PrintLine("  </trkseg>");
             poDS->PrintLine("  <trkseg>");
         }
 
-        poDS->nLastTrkId = poFeature->GetFieldAsInteger(FLD_TRACK_FID);
-        poDS->nLastTrkSegId = poFeature->GetFieldAsInteger(FLD_TRACK_SEG_ID);
+        poDS->nLastTrkId = poFeatureIn->GetFieldAsInteger(FLD_TRACK_FID);
+        poDS->nLastTrkSegId = poFeatureIn->GetFieldAsInteger(FLD_TRACK_SEG_ID);
 
-        OGRPoint* point = (OGRPoint*)poGeom;
+        OGRPoint* point = reinterpret_cast<OGRPoint*>(poGeom);
         double lat = point->getY();
         double lon = point->getX();
         CheckAndFixCoordinatesValidity(&lat, &lon);
@@ -1751,7 +1810,7 @@ OGRErr OGRGPXLayer::ICreateFeature( OGRFeature *poFeature )
         OGRFormatDouble(szLat, sizeof(szLat), lat, '.');
         OGRFormatDouble(szLon, sizeof(szLon), lon, '.');
         poDS->PrintLine("    <trkpt lat=\"%s\" lon=\"%s\">", szLat, szLon);
-        WriteFeatureAttributes(poFeature, 3);
+        WriteFeatureAttributes(poFeatureIn, 3);
         poDS->PrintLine("    </trkpt>");
     }
 
@@ -1816,19 +1875,24 @@ int OGRGPXLayer::TestCapability( const char * pszCap )
 
 #ifdef HAVE_EXPAT
 
-static void XMLCALL startElementLoadSchemaCbk(void *pUserData, const char *pszName, const char **ppszAttr)
+static void XMLCALL startElementLoadSchemaCbk(
+    void *pUserData, const char *pszName, const char **ppszAttr )
 {
-    ((OGRGPXLayer*)pUserData)->startElementLoadSchemaCbk(pszName, ppszAttr);
+    static_cast<OGRGPXLayer *>(pUserData)->
+        startElementLoadSchemaCbk(pszName, ppszAttr);
 }
 
-static void XMLCALL endElementLoadSchemaCbk(void *pUserData, const char *pszName)
+static void XMLCALL endElementLoadSchemaCbk(
+    void *pUserData, const char *pszName )
 {
-    ((OGRGPXLayer*)pUserData)->endElementLoadSchemaCbk(pszName);
+    static_cast<OGRGPXLayer *>(pUserData)->
+        endElementLoadSchemaCbk(pszName);
 }
 
-static void XMLCALL dataHandlerLoadSchemaCbk(void *pUserData, const char *data, int nLen)
+static void XMLCALL dataHandlerLoadSchemaCbk(
+    void *pUserData, const char *data, int nLen )
 {
-    ((OGRGPXLayer*)pUserData)->dataHandlerLoadSchemaCbk(data, nLen);
+    static_cast<OGRGPXLayer *>(pUserData)->dataHandlerLoadSchemaCbk(data, nLen);
 }
 
 
@@ -1842,31 +1906,33 @@ void OGRGPXLayer::LoadExtensionsSchema()
 
     VSIFSeekL( fpGPX, 0, SEEK_SET );
 
-    inInterestingElement = FALSE;
-    inExtensions = FALSE;
+    inInterestingElement = false;
+    inExtensions = false;
     depthLevel = 0;
     currentFieldDefn = NULL;
     pszSubElementName = NULL;
     pszSubElementValue = NULL;
     nSubElementValueLen = 0;
     nWithoutEventCounter = 0;
-    bStopParsing = FALSE;
+    bStopParsing = false;
 
     char aBuf[BUFSIZ];
     int nDone;
     do
     {
         nDataHandlerCounter = 0;
-        unsigned int nLen = (unsigned int)VSIFReadL( aBuf, 1, sizeof(aBuf), fpGPX );
+        unsigned int nLen = static_cast<unsigned int>(
+            VSIFReadL( aBuf, 1, sizeof(aBuf), fpGPX ) );
         nDone = VSIFEofL(fpGPX);
         if (XML_Parse(oSchemaParser, aBuf, nLen, nDone) == XML_STATUS_ERROR)
         {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "XML parsing of GPX file failed : %s at line %d, column %d",
-                     XML_ErrorString(XML_GetErrorCode(oSchemaParser)),
-                     (int)XML_GetCurrentLineNumber(oSchemaParser),
-                     (int)XML_GetCurrentColumnNumber(oSchemaParser));
-            bStopParsing = TRUE;
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "XML parsing of GPX file failed : "
+                      "%s at line %d, column %d",
+                      XML_ErrorString(XML_GetErrorCode(oSchemaParser)),
+                      static_cast<int>(XML_GetCurrentLineNumber(oSchemaParser)),
+                      static_cast<int>(XML_GetCurrentColumnNumber(oSchemaParser)));
+            bStopParsing = true;
             break;
         }
         nWithoutEventCounter ++;
@@ -1874,9 +1940,9 @@ void OGRGPXLayer::LoadExtensionsSchema()
 
     if (nWithoutEventCounter == 10)
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Too much data inside one element. File probably corrupted");
-        bStopParsing = TRUE;
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Too much data inside one element. File probably corrupted" );
+        bStopParsing = true;
     }
 
     XML_ParserFree(oSchemaParser);
@@ -1900,32 +1966,32 @@ void OGRGPXLayer::startElementLoadSchemaCbk(const char *pszName,
 
     if (gpxGeomType == GPX_WPT && strcmp(pszName, "wpt") == 0)
     {
-        inInterestingElement = TRUE;
-        inExtensions = FALSE;
+        inInterestingElement = true;
+        inExtensions = false;
         interestingDepthLevel = depthLevel;
     }
     else if (gpxGeomType == GPX_TRACK && strcmp(pszName, "trk") == 0)
     {
-        inInterestingElement = TRUE;
-        inExtensions = FALSE;
+        inInterestingElement = true;
+        inExtensions = false;
         interestingDepthLevel = depthLevel;
     }
     else if (gpxGeomType == GPX_ROUTE && strcmp(pszName, "rte") == 0)
     {
-        inInterestingElement = TRUE;
-        inExtensions = FALSE;
+        inInterestingElement = true;
+        inExtensions = false;
         interestingDepthLevel = depthLevel;
     }
     else if (gpxGeomType == GPX_TRACK_POINT && strcmp(pszName, "trkpt") == 0)
     {
-        inInterestingElement = TRUE;
-        inExtensions = FALSE;
+        inInterestingElement = true;
+        inExtensions = false;
         interestingDepthLevel = depthLevel;
     }
     else if (gpxGeomType == GPX_ROUTE_POINT && strcmp(pszName, "rtept") == 0)
     {
-        inInterestingElement = TRUE;
-        inExtensions = FALSE;
+        inInterestingElement = true;
+        inExtensions = false;
         interestingDepthLevel = depthLevel;
     }
     else if (inInterestingElement)
@@ -1933,7 +1999,7 @@ void OGRGPXLayer::startElementLoadSchemaCbk(const char *pszName,
         if (depthLevel == interestingDepthLevel + 1 &&
             strcmp(pszName, "extensions") == 0)
         {
-            inExtensions = TRUE;
+            inExtensions = true;
             extensionsDepthLevel = depthLevel;
         }
         else if (inExtensions && depthLevel == extensionsDepthLevel + 1)
@@ -1953,7 +2019,7 @@ void OGRGPXLayer::startElementLoadSchemaCbk(const char *pszName,
                 }
                 else
                     bMatch = (strcmp(poFeatureDefn->GetFieldDefn(iField)->GetNameRef(), pszName ) == 0);
-                
+
                 if (bMatch)
                 {
                     currentFieldDefn = poFeatureDefn->GetFieldDefn(iField);
@@ -1965,7 +2031,7 @@ void OGRGPXLayer::startElementLoadSchemaCbk(const char *pszName,
                 char* pszCompatibleName = OGRGPX_GetOGRCompatibleTagName(pszName);
                 OGRFieldDefn newFieldDefn(pszCompatibleName, OFTInteger);
                 CPLFree(pszCompatibleName);
-                
+
                 poFeatureDefn->AddFieldDefn(&newFieldDefn);
                 currentFieldDefn = poFeatureDefn->GetFieldDefn(poFeatureDefn->GetFieldCount() - 1);
 
@@ -1974,7 +2040,7 @@ void OGRGPXLayer::startElementLoadSchemaCbk(const char *pszName,
                     CPLError(CE_Failure, CPLE_AppDefined,
                             "Too many fields. File probably corrupted");
                     XML_StopParser(oSchemaParser, XML_FALSE);
-                    bStopParsing = TRUE;
+                    bStopParsing = true;
                 }
             }
         }
@@ -1990,12 +2056,10 @@ void OGRGPXLayer::startElementLoadSchemaCbk(const char *pszName,
 
 static int OGRGPXIsInt(const char* pszStr)
 {
-    int i;
-
     while(*pszStr == ' ')
         pszStr++;
 
-    for(i=0;pszStr[i];i++)
+    for( int i = 0; pszStr[i]; i++ )
     {
         if (pszStr[i] == '+' || pszStr[i] == '-')
         {
@@ -2021,33 +2085,33 @@ void OGRGPXLayer::endElementLoadSchemaCbk(const char *pszName)
     {
         if (gpxGeomType == GPX_WPT && strcmp(pszName, "wpt") == 0)
         {
-            inInterestingElement = FALSE;
-            inExtensions = FALSE;
+            inInterestingElement = false;
+            inExtensions = false;
         }
         else if (gpxGeomType == GPX_TRACK && strcmp(pszName, "trk") == 0)
         {
-            inInterestingElement = FALSE;
-            inExtensions = FALSE;
+            inInterestingElement = false;
+            inExtensions = false;
         }
         else if (gpxGeomType == GPX_ROUTE && strcmp(pszName, "rte") == 0)
         {
-            inInterestingElement = FALSE;
-            inExtensions = FALSE;
+            inInterestingElement = false;
+            inExtensions = false;
         }
         else if (gpxGeomType == GPX_TRACK_POINT && strcmp(pszName, "trkpt") == 0)
         {
-            inInterestingElement = FALSE;
-            inExtensions = FALSE;
+            inInterestingElement = false;
+            inExtensions = false;
         }
         else if (gpxGeomType == GPX_ROUTE_POINT && strcmp(pszName, "rtept") == 0)
         {
-            inInterestingElement = FALSE;
-            inExtensions = FALSE;
+            inInterestingElement = false;
+            inExtensions = false;
         }
         else if (depthLevel == interestingDepthLevel + 1 &&
                  strcmp(pszName, "extensions") == 0)
         {
-            inExtensions = FALSE;
+            inExtensions = false;
         }
         else if (inExtensions && depthLevel == extensionsDepthLevel + 1 &&
                  pszSubElementName && strcmp(pszName, pszSubElementName) == 0)
@@ -2100,9 +2164,10 @@ void OGRGPXLayer::dataHandlerLoadSchemaCbk(const char *data, int nLen)
     nDataHandlerCounter ++;
     if (nDataHandlerCounter >= BUFSIZ)
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "File probably corrupted (million laugh pattern)");
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "File probably corrupted (million laugh pattern)" );
         XML_StopParser(oSchemaParser, XML_FALSE);
-        bStopParsing = TRUE;
+        bStopParsing = true;
         return;
     }
 
@@ -2110,12 +2175,13 @@ void OGRGPXLayer::dataHandlerLoadSchemaCbk(const char *data, int nLen)
 
     if (pszSubElementName)
     {
-        char* pszNewSubElementValue = (char*) VSIRealloc(pszSubElementValue, nSubElementValueLen + nLen + 1);
+        char* pszNewSubElementValue = static_cast<char*>(
+            VSI_REALLOC_VERBOSE(
+                pszSubElementValue, nSubElementValueLen + nLen + 1) );
         if (pszNewSubElementValue == NULL)
         {
-            CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
             XML_StopParser(oSchemaParser, XML_FALSE);
-            bStopParsing = TRUE;
+            bStopParsing = true;
             return;
         }
         pszSubElementValue = pszNewSubElementValue;
@@ -2123,15 +2189,14 @@ void OGRGPXLayer::dataHandlerLoadSchemaCbk(const char *data, int nLen)
         nSubElementValueLen += nLen;
         if (nSubElementValueLen > 100000)
         {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "Too much data inside one element. File probably corrupted");
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Too much data inside one element. "
+                      "File probably corrupted" );
             XML_StopParser(oSchemaParser, XML_FALSE);
-            bStopParsing = TRUE;
+            bStopParsing = true;
         }
     }
 }
 #else
-void OGRGPXLayer::LoadExtensionsSchema()
-{
-}
+void OGRGPXLayer::LoadExtensionsSchema() {}
 #endif
diff --git a/ogr/ogrsf_frmts/grass/drv_grass.html b/ogr/ogrsf_frmts/grass/drv_grass.html
index 3252428..5a2ccd5 100644
--- a/ogr/ogrsf_frmts/grass/drv_grass.html
+++ b/ogr/ogrsf_frmts/grass/drv_grass.html
@@ -28,7 +28,7 @@ Both 2D and 3D maps are supported.
 <h2>Datasource name</h2>
 
 Datasource name is full path to 'head' file in GRASS vector directory.
-Using names of GRASS enviroment variables it can be expressed:
+Using names of GRASS environment variables it can be expressed:
 <pre>
    $GISDBASE/$LOCATION_NAME/$MAPSET/vector/mymap/head
 </pre>
@@ -39,8 +39,8 @@ where 'mymap' is name of a vector map. For example:
 
 <h2>Layer names</h2>
 
-Usualy layer numbers are used as layer names. Layer number 0 is used
-for all features without any category. It is possible to optionaly
+Usually layer numbers are used as layer names. Layer number 0 is used
+for all features without any category. It is possible to optionally
 give names to GRASS layers linked to database however currently this
 is not supported by grass modules.  A layer name can be added in
 'dbln' vector file as '/name' after layer number, for example to
@@ -58,10 +58,10 @@ the layer 1 will be listed is layer 'rivers'.
 <h2>Attribute filter</h2>
 
 If a layer has attributes stored in a database, the query is passed to
-the underlaying database driver. That means, that SQL conditions which
+the underlying database driver. That means, that SQL conditions which
 can be used depend on the driver and database to which the layer is
 linked. For example, DBF driver has currently very limited set of SQL
-expressions and PostgreSQL offeres very rich set of SQL expressions.
+expressions and PostgreSQL offers very rich set of SQL expressions.
 
 <p>
 If a layer has no attributes linked and it has only categories, OGR
@@ -85,7 +85,7 @@ Evaluation is done once when the spatial filter is set.
 GISBASE is full path to the directory where GRASS is installed.  By
 default, GRASS driver is using the path given to gdal configure
 script.  A different directory can be forced by setting GISBASE
-enviroment variable.  GISBASE is used to find GRASS database drivers.
+environment variable.  GISBASE is used to find GRASS database drivers.
 
 <h2>Missing topology</h2>
 
@@ -101,7 +101,7 @@ layer with attributes, the reading of features can be quite slow. It
 is because the driver has to query attributes by category for each
 feature (to avoid using a lot of memory) and random access to database
 is usually slow. This can be improved on GRASS side optimizing/writing
-file based (DBF,SQLite) drivers.
+file based (DBF, SQLite) drivers.
 
 <h2>Known problem</h2>
 
@@ -124,7 +124,7 @@ that case kill() is not used.
 </ul>
 
 <hr>
-Development of this driver was financially supported by Faunalia 
+Development of this driver was financially supported by Faunalia
 (<a href="http://www.faunalia.it/">www.faunalia.it</a>).
 
 </body>
diff --git a/ogr/ogrsf_frmts/grass/ogrgrass.h b/ogr/ogrsf_frmts/grass/ogrgrass.h
index 5abed15..3cda766 100644
--- a/ogr/ogrsf_frmts/grass/ogrgrass.h
+++ b/ogr/ogrsf_frmts/grass/ogrgrass.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgrass.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrgrass.h 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/GRASS driver.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGRGRASS_H_INCLUDED
-#define _OGRGRASS_H_INCLUDED
+#ifndef OGRGRASS_H_INCLUDED
+#define OGRGRASS_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 
@@ -57,6 +57,8 @@ class OGRGRASSLayer : public OGRLayer
     OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
     GIntBig             GetFeatureCount( int );
     OGRErr              GetExtent(OGREnvelope *psExtent, int bForce);
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
     virtual OGRSpatialReference *GetSpatialRef();
     int                 TestCapability( const char * );
 
@@ -69,12 +71,14 @@ class OGRGRASSLayer : public OGRLayer
     // Filters
     virtual OGRErr 	SetAttributeFilter( const char *query );
     virtual void 	SetSpatialFilter( OGRGeometry * poGeomIn );
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+                { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
 
     // Write access, not supported:
     virtual OGRErr      CreateField( OGRFieldDefn *poField, int bApproxOK = TRUE );
     OGRErr              ISetFeature( OGRFeature *poFeature );
     OGRErr              ICreateFeature( OGRFeature *poFeature );
-    
+
   private:
     char		*pszName;
     OGRSpatialReference *poSRS;
@@ -83,7 +87,7 @@ class OGRGRASSLayer : public OGRLayer
 
     int			iNextId;
     int			nTotalCount;
-    int			iLayer;		// Layer number 
+    int			iLayer;		// Layer number
     int			iLayerIndex;	// Layer index (in GRASS category index)
     int			iCatField;	// Field where category (key) is stored
     int			nFields;
@@ -99,11 +103,11 @@ class OGRGRASSLayer : public OGRLayer
     dbString		*poDbString;
     dbDriver		*poDriver;
     dbCursor		*poCursor;
-    
+
     bool		bCursorOpened;	// Sequential database cursor opened
     int 		iCurrentCat;	// Current category in select cursor
 
-    struct line_pnts	*poPoints; 
+    struct line_pnts	*poPoints;
     struct line_cats	*poCats;
 
     bool		StartDbDriver ();
@@ -142,7 +146,7 @@ class OGRGRASSDataSource : public OGRDataSource
     int                 TestCapability( const char * );
 
     // Not implemented (returns NULL):
-    virtual OGRLayer    *ICreateLayer( const char *, 
+    virtual OGRLayer    *ICreateLayer( const char *,
                                       OGRSpatialReference * = NULL,
                                       OGRwkbGeometryType = wkbUnknown,
                                       char ** = NULL );
@@ -158,7 +162,7 @@ class OGRGRASSDataSource : public OGRDataSource
 
     struct Map_info 	map;
     int                 nLayers;
-    
+
     int                 bOpened;
 
     static bool SplitPath ( char *, char **, char **, char **, char ** );
@@ -171,16 +175,16 @@ class OGRGRASSDriver : public OGRSFDriver
 {
   public:
 			~OGRGRASSDriver();
-                
+
     const char 		*GetName();
     OGRDataSource 	*Open( const char *, int );
 
     int                 TestCapability( const char * );
 
     // Not implemented (return error/NULL):
-    virtual OGRDataSource *CreateDataSource( const char *pszName, 
+    virtual OGRDataSource *CreateDataSource( const char *pszName,
 	    				     char ** = NULL );
     OGRErr              DeleteDataSource( const char *pszDataSource );
 };
 
-#endif /* ndef _OGRGRASS_H_INCLUDED */
+#endif /* ndef OGRGRASS_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/grass/ogrgrassdatasource.cpp b/ogr/ogrsf_frmts/grass/ogrgrassdatasource.cpp
index 8677c47..e454f0a 100644
--- a/ogr/ogrsf_frmts/grass/ogrgrassdatasource.cpp
+++ b/ogr/ogrsf_frmts/grass/ogrgrassdatasource.cpp
@@ -1,9 +1,9 @@
 /******************************************************************************
- * $Id: ogrgrassdatasource.cpp 28534 2015-02-21 14:34:39Z rouault $
+ * $Id: ogrgrassdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGRASSDataSource class.
- * Author:   Radim Blazek, radim.blazek at gmail.com 
+ * Author:   Radim Blazek, radim.blazek at gmail.com
  *
  ******************************************************************************
  * Copyright (c) 2005, Radim Blazek <radim.blazek at gmail.com>
@@ -32,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrgrassdatasource.cpp 28534 2015-02-21 14:34:39Z rouault $");
+CPL_CVSID("$Id: ogrgrassdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 #if GRASS_VERSION_MAJOR  >= 7
 #define G__setenv                G_setenv_nogisrc
@@ -73,14 +73,14 @@ OGRGRASSDataSource::~OGRGRASSDataSource()
 {
     for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
-    
+
     if ( pszName ) CPLFree( pszName );
     if ( papoLayers ) CPLFree( papoLayers );
     if ( pszGisdbase ) G_free( pszGisdbase );
     if ( pszLocation ) G_free( pszLocation );
     if ( pszMapset ) G_free( pszMapset );
     if ( pszMap ) G_free( pszMap );
-    
+
     if (bOpened)
         Vect_close(&map);
 }
@@ -89,7 +89,7 @@ OGRGRASSDataSource::~OGRGRASSDataSource()
 /*                                Open()                                */
 /************************************************************************/
 
-#if (GRASS_VERSION_MAJOR  >= 6 && GRASS_VERSION_MINOR  >= 3) || GRASS_VERSION_MAJOR  >= 7 
+#if (GRASS_VERSION_MAJOR  >= 6 && GRASS_VERSION_MINOR  >= 3) || GRASS_VERSION_MAJOR  >= 7
 typedef int (*GrassErrorHandler)(const char *, int);
 #else
 typedef int (*GrassErrorHandler)(char *, int);
@@ -99,9 +99,9 @@ int OGRGRASSDataSource::Open( const char * pszNewName, int bUpdate,
                               int bTestOpen, int bSingleNewFileIn )
 {
     VSIStatBuf  stat;
-    
+
     CPLAssert( nLayers == 0 );
-    
+
     pszName = CPLStrdup( pszNewName ); // Released by destructor
 
 /* -------------------------------------------------------------------- */
@@ -116,7 +116,7 @@ int OGRGRASSDataSource::Open( const char * pszNewName, int bUpdate,
 	}
 	return FALSE;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Is the given a regular file?                                    */
 /* -------------------------------------------------------------------- */
@@ -134,18 +134,18 @@ int OGRGRASSDataSource::Open( const char * pszNewName, int bUpdate,
 /* -------------------------------------------------------------------- */
 /*      Parse datasource name                                           */
 /* -------------------------------------------------------------------- */
-    if ( !SplitPath(pszName, &pszGisdbase, &pszLocation, 
-		    &pszMapset, &pszMap) ) 
+    if ( !SplitPath(pszName, &pszGisdbase, &pszLocation,
+		    &pszMapset, &pszMap) )
     {
         if( !bTestOpen )
 	{
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "%s is not GRASS datasource name, access failed.\n", 
+                      "%s is not GRASS datasource name, access failed.\n",
 		      pszName );
 	}
 	return FALSE;
     }
-			
+
     CPLDebug ( "GRASS", "Gisdbase: %s", pszGisdbase );
     CPLDebug ( "GRASS", "Location: %s", pszLocation );
     CPLDebug ( "GRASS", "Mapset: %s", pszMapset );
@@ -170,13 +170,13 @@ int OGRGRASSDataSource::Open( const char * pszNewName, int bUpdate,
         putenv( gisbaseEnv );
     }
 
-    // Don't use GISRC file and read/write GRASS variables 
+    // Don't use GISRC file and read/write GRASS variables
     // (from location G_VAR_GISRC) to memory only.
     G_set_gisrc_mode ( G_GISRC_MODE_MEMORY );
 
-    // Init GRASS libraries (required). G_no_gisinit() doesn't check 
+    // Init GRASS libraries (required). G_no_gisinit() doesn't check
     // write permissions for mapset compare to G_gisinit()
-    G_no_gisinit();  
+    G_no_gisinit();
 
     // Set error function
     G_set_error_routine ( (GrassErrorHandler) Grass2OGRErrorHook );
@@ -186,7 +186,7 @@ int OGRGRASSDataSource::Open( const char * pszNewName, int bUpdate,
 /* -------------------------------------------------------------------- */
      G__setenv( "GISDBASE", pszGisdbase );
      G__setenv( "LOCATION_NAME", pszLocation );
-     G__setenv( "MAPSET", pszMapset); 
+     G__setenv( "MAPSET", pszMapset);
      G_reset_mapsets();
      G_add_mapset_to_search_path ( pszMapset );
 
@@ -206,7 +206,7 @@ int OGRGRASSDataSource::Open( const char * pszNewName, int bUpdate,
     }
 
     CPLDebug ( "GRASS", "Num lines = %d", Vect_get_num_lines(&map) );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Build a list of layers.                                         */
 /* -------------------------------------------------------------------- */
@@ -218,15 +218,15 @@ int OGRGRASSDataSource::Open( const char * pszNewName, int bUpdate,
 	OGRGRASSLayer       *poLayer;
 
         poLayer = new OGRGRASSLayer( i, &map );
-	
+
         // Add layer to data source layer list
 	papoLayers = (OGRGRASSLayer **)
 	    CPLRealloc( papoLayers,  sizeof(OGRGRASSLayer *) * (nLayers+1) );
 	papoLayers[nLayers++] = poLayer;
     }
-    
+
     bOpened = TRUE;
-    
+
     return TRUE;
 }
 
@@ -274,24 +274,24 @@ OGRLayer *OGRGRASSDataSource::GetLayer( int iLayer )
 /* Returns: true - OK                                                   */
 /*          false - failed                                              */
 /************************************************************************/
-bool OGRGRASSDataSource::SplitPath( char *path, char **gisdbase, 
+bool OGRGRASSDataSource::SplitPath( char *path, char **gisdbase,
 	                     char **location, char **mapset, char **map )
 {
     char *p, *ptr[5], *tmp;
     int  i = 0;
-    
+
     CPLDebug ( "GRASS", "OGRGRASSDataSource::SplitPath" );
-    
+
     *gisdbase = *location = *mapset = *map = NULL;
-    
-    if ( !path || strlen(path) == 0 ) 
+
+    if ( !path || strlen(path) == 0 )
 	return false;
 
     tmp = G_store ( path );
 
     while ( (p = strrchr(tmp,'/')) != NULL  && i < 5 ) {
 	*p = '\0';
-	
+
 	if ( strlen(p+1) == 0 ) /* repeated '/' */
 	    continue;
 
@@ -306,7 +306,7 @@ bool OGRGRASSDataSource::SplitPath( char *path, char **gisdbase,
 
     if ( strcmp(ptr[0],"head") != 0 || strcmp(ptr[2],"vector") != 0 ) {
        return false;
-    }       
+    }
 
     *gisdbase = G_store ( tmp );
     *location = G_store ( ptr[4] );
@@ -316,4 +316,3 @@ bool OGRGRASSDataSource::SplitPath( char *path, char **gisdbase,
     free ( tmp );
     return true;
 }
-
diff --git a/ogr/ogrsf_frmts/grass/ogrgrassdriver.cpp b/ogr/ogrsf_frmts/grass/ogrgrassdriver.cpp
index 999da00..f1a9521 100644
--- a/ogr/ogrsf_frmts/grass/ogrgrassdriver.cpp
+++ b/ogr/ogrsf_frmts/grass/ogrgrassdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgrassdriver.cpp 28290 2015-01-05 13:16:48Z martinl $
+ * $Id: ogrgrassdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGRASSDriver class.
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrgrassdriver.cpp 28290 2015-01-05 13:16:48Z martinl $");
+CPL_CVSID("$Id: ogrgrassdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
 
 /************************************************************************/
 /*                          ~OGRGRASSDriver()                           */
@@ -75,9 +75,9 @@ OGRDataSource *OGRGRASSDriver::Open( const char * pszFilename,
 OGRDataSource *OGRGRASSDriver::CreateDataSource( const char * pszName,
                                                  char **papszOptions )
 {
-    CPLError( CE_Failure, CPLE_AppDefined, 
-	      "CreateDataSource is not supported by GRASS driver.\n" );
-            
+    CPLError( CE_Failure, CPLE_AppDefined,
+              "CreateDataSource is not supported by GRASS driver.\n" );
+
     return NULL;
 }
 
@@ -87,7 +87,7 @@ OGRDataSource *OGRGRASSDriver::CreateDataSource( const char * pszName,
 OGRErr OGRGRASSDriver::DeleteDataSource( const char *pszDataSource )
 {
     CPLError( CE_Failure, CPLE_AppDefined,
-	      "DeleteDataSource is not supported by GRASS driver" );
+              "DeleteDataSource is not supported by GRASS driver" );
 
     return OGRERR_FAILURE;
 }
@@ -105,23 +105,19 @@ int OGRGRASSDriver::TestCapability( const char * pszCap )
 /************************************************************************/
 void RegisterOGRGRASS()
 {
-    OGRGRASSDriver	*poDriver;
-
     if (! GDAL_CHECK_VERSION("OGR/GRASS driver"))
         return;
 
-    if( GDALGetDriverByName( "OGR_GRASS" ) == NULL )
-    {
-        poDriver = new OGRGRASSDriver();
-        
-        poDriver->SetDescription( "GRASS" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "GRASS Vectors (5.7+)" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "drv_grass.html" );
-
-        OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( poDriver );
-    }
+    if( GDALGetDriverByName( "OGR_GRASS" ) != NULL )
+        return;
+
+    OGRGRASSDriver *poDriver = new OGRGRASSDriver();
+
+    poDriver->SetDescription( "GRASS" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "GRASS Vectors (5.7+)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_grass.html" );
+
+    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( poDriver );
 }
 
diff --git a/ogr/ogrsf_frmts/grass/ogrgrasslayer.cpp b/ogr/ogrsf_frmts/grass/ogrgrasslayer.cpp
index 41855b3..a2be8ea 100644
--- a/ogr/ogrsf_frmts/grass/ogrgrasslayer.cpp
+++ b/ogr/ogrsf_frmts/grass/ogrgrasslayer.cpp
@@ -1,9 +1,9 @@
 /******************************************************************************
- * $Id: ogrgrasslayer.cpp 28831 2015-04-01 16:46:05Z rouault $
+ * $Id: ogrgrasslayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGRASSLayer class.
- * Author:   Radim Blazek, radim.blazek at gmail.com 
+ * Author:   Radim Blazek, radim.blazek at gmail.com
  *
  ******************************************************************************
  * Copyright (c) 2005, Radim Blazek <radim.blazek at gmail.com>
@@ -32,7 +32,7 @@
 #include "ogrgrass.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrgrasslayer.cpp 28831 2015-04-01 16:46:05Z rouault $");
+CPL_CVSID("$Id: ogrgrasslayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                           OGRGRASSLayer()                            */
@@ -40,9 +40,9 @@ CPL_CVSID("$Id: ogrgrasslayer.cpp 28831 2015-04-01 16:46:05Z rouault $");
 OGRGRASSLayer::OGRGRASSLayer( int layerIndex,  struct Map_info * map )
 {
     CPLDebug ( "GRASS", "OGRGRASSLayer::OGRGRASSLayer layerIndex = %d", layerIndex );
-    
+
     iLayerIndex = layerIndex;
-    poMap = map; 
+    poMap = map;
     poSRS = NULL;
     iNextId = 0;
     poPoints = Vect_new_line_struct();
@@ -53,18 +53,18 @@ OGRGRASSLayer::OGRGRASSLayer( int layerIndex,  struct Map_info * map )
 
     iLayer = Vect_cidx_get_field_number ( poMap, iLayerIndex);
     CPLDebug ( "GRASS", "iLayer = %d", iLayer );
-    
+
     poLink = Vect_get_field ( poMap, iLayer ); // May be NULL if not defined
 
     // Layer name
     if ( poLink && poLink->name )
     {
-	pszName = CPLStrdup( poLink->name );	
+	pszName = CPLStrdup( poLink->name );
     }
     else
-    {	
-	char buf[20]; 
-	sprintf ( buf, "%d", iLayer ); 
+    {
+	char buf[20];
+	sprintf ( buf, "%d", iLayer );
 	pszName = CPLStrdup( buf );
     }
 
@@ -73,15 +73,15 @@ OGRGRASSLayer::OGRGRASSLayer( int layerIndex,  struct Map_info * map )
     nTotalCount = Vect_cidx_get_type_count(poMap,iLayer, GV_POINT|GV_LINES|GV_AREA);
     CPLDebug ( "GRASS", "nTotalCount = %d", nTotalCount );
     paFeatureIndex = (int *) CPLMalloc ( nTotalCount * sizeof(int) );
-    
+
     int n = Vect_cidx_get_type_count(poMap,iLayer, GV_POINTS|GV_LINES|GV_AREA);
     int cnt = 0;
-    for ( int i = 0; i < n; i++ ) 
+    for ( int i = 0; i < n; i++ )
     {
 	int cat,type, id;
-	
+
 	Vect_cidx_get_cat_by_index ( poMap, iLayerIndex, i, &cat, &type, &id );
-    
+
 	if ( !( type & (GV_POINT|GV_LINES|GV_AREA) ) ) continue;
 	paFeatureIndex[cnt++] = i;
     }
@@ -100,12 +100,12 @@ OGRGRASSLayer::OGRGRASSLayer( int layerIndex,  struct Map_info * map )
 	types |= type;
         CPLDebug ( "GRASS", "type = %d types = %d", type, types );
     }
-    
+
     OGRwkbGeometryType eGeomType = wkbUnknown;
-    if ( types == GV_LINE || types == GV_BOUNDARY || types == GV_LINES ) 
+    if ( types == GV_LINE || types == GV_BOUNDARY || types == GV_LINES )
     {
         eGeomType = wkbLineString;
-    } 
+    }
     else if ( types == GV_POINT )
     {
         eGeomType = wkbPoint;
@@ -129,9 +129,9 @@ OGRGRASSLayer::OGRGRASSLayer( int layerIndex,  struct Map_info * map )
     poDriver = NULL;
     bHaveAttributes = false;
     db_init_string ( poDbString );
-    if ( poLink ) 
+    if ( poLink )
     {
-	if ( StartDbDriver() ) 
+	if ( StartDbDriver() )
 	{
 	    db_set_string ( poDbString, poLink->table );
 	    dbTable *table;
@@ -139,30 +139,30 @@ OGRGRASSLayer::OGRGRASSLayer( int layerIndex,  struct Map_info * map )
 	    {
 		nFields = db_get_table_number_of_columns ( table );
 		iCatField = -1;
-		for ( int i = 0; i < nFields; i++) 
+		for ( int i = 0; i < nFields; i++)
 		{
 		    dbColumn *column = db_get_table_column ( table, i );
 		    int ctype = db_sqltype_to_Ctype ( db_get_column_sqltype(column) );
-    
+
 		    OGRFieldType ogrFtype = OFTInteger;
  	     	    switch ( ctype ) {
 			 case DB_C_TYPE_INT:
 			    ogrFtype = OFTInteger;
-			    break; 
+			    break;
 			 case DB_C_TYPE_DOUBLE:
 			    ogrFtype = OFTReal;
-			    break; 
+			    break;
 			 case DB_C_TYPE_STRING:
 			    ogrFtype = OFTString;
-			    break; 
+			    break;
 			 case DB_C_TYPE_DATETIME:
 			    ogrFtype = OFTDateTime;
-			    break; 
+			    break;
 		    }
 
-		    CPLDebug ( "GRASS", "column = %s type = %d", 
+		    CPLDebug ( "GRASS", "column = %s type = %d",
 			       db_get_column_name(column), ctype );
-		    
+
 		    OGRFieldDefn oField ( db_get_column_name(column), ogrFtype );
 		    poFeatureDefn->AddFieldDefn( &oField );
 
@@ -171,7 +171,7 @@ OGRGRASSLayer::OGRGRASSLayer( int layerIndex,  struct Map_info * map )
 			iCatField = i;
 		    }
 		}
-		if ( iCatField >= 0  ) 
+		if ( iCatField >= 0  )
 		{
     		    bHaveAttributes = true;
 		}
@@ -180,20 +180,20 @@ OGRGRASSLayer::OGRGRASSLayer( int layerIndex,  struct Map_info * map )
 		    CPLError( CE_Failure, CPLE_AppDefined, "Cannot find key field" );
 		    db_close_database_shutdown_driver ( poDriver );
 		    poDriver = NULL;
-		}
-	    }
+                }
+            }
 	    else
-	    {
-		CPLError( CE_Failure, CPLE_AppDefined, "Cannot describe table %s", 
+            {
+		CPLError( CE_Failure, CPLE_AppDefined, "Cannot describe table %s",
 			  poLink->table );
 
-	    }
+            }
 	    db_close_database_shutdown_driver ( poDriver );
 	    poDriver = NULL;
-	}
-    } 
-	
-    if ( !bHaveAttributes && iLayer > 0 ) // Because features in layer 0 have no cats  
+        }
+    }
+
+    if ( !bHaveAttributes && iLayer > 0 ) // Because features in layer 0 have no cats
     {
 	OGRFieldDefn oField("cat", OFTInteger);
 	poFeatureDefn->AddFieldDefn( &oField );
@@ -203,19 +203,19 @@ OGRGRASSLayer::OGRGRASSLayer( int layerIndex,  struct Map_info * map )
     {
         struct Key_Value *projinfo, *projunits;
 
-	// Note: we dont have to reset GISDBASE and LOCATION_NAME because 
-	// OGRGRASSLayer constructor is called from OGRGRASSDataSource::Open
-	// where those variables are set
+        // Note: we do not have to reset GISDBASE and LOCATION_NAME because
+        // OGRGRASSLayer constructor is called from OGRGRASSDataSource::Open
+        // where those variables are set
 
         projinfo = G_get_projinfo();
 	projunits = G_get_projunits();
 
 	char *srsWkt = GPJ_grass_to_wkt ( projinfo, projunits, 0, 0);
-	if ( srsWkt ) 
-	{
+        if ( srsWkt )
+        {
 	    poSRS = new OGRSpatialReference ( srsWkt );
 	    G_free ( srsWkt );
-	}
+        }
 
         G_free_key_value(projinfo);
         G_free_key_value(projunits);
@@ -227,16 +227,16 @@ OGRGRASSLayer::OGRGRASSLayer( int layerIndex,  struct Map_info * map )
 /************************************************************************/
 OGRGRASSLayer::~OGRGRASSLayer()
 {
-    if ( bCursorOpened ) 
+    if ( bCursorOpened )
     {
 	db_close_cursor ( poCursor);
     }
 
-    if ( poDriver ) 
+    if ( poDriver )
     {
 	StopDbDriver();
     }
-    
+
     if ( pszName ) CPLFree ( pszName );
     if ( poFeatureDefn )
         poFeatureDefn->Release();
@@ -244,11 +244,11 @@ OGRGRASSLayer::~OGRGRASSLayer()
         poSRS->Release();
 
     if ( pszQuery ) CPLFree ( pszQuery );
-    
+
     if ( paFeatureIndex ) CPLFree ( paFeatureIndex );
-    
+
     if ( poLink ) G_free ( poLink );
-    
+
     Vect_destroy_line_struct ( poPoints );
     Vect_destroy_cats_struct ( poCats );
 
@@ -265,23 +265,23 @@ OGRGRASSLayer::~OGRGRASSLayer()
 /************************************************************************/
 bool OGRGRASSLayer::StartDbDriver()
 {
-    CPLDebug ( "GRASS", "StartDbDriver()" ); 
+    CPLDebug ( "GRASS", "StartDbDriver()" );
 
     bCursorOpened = false;
-	    
-    if ( !poLink ) 
+
+    if ( !poLink )
     {
 	return false;
     }
     poDriver = db_start_driver_open_database ( poLink->driver, poLink->database );
-    
-    if ( poDriver == NULL) 
+
+    if ( poDriver == NULL)
     {
 	CPLError( CE_Failure, CPLE_AppDefined, "Cannot open database %s by driver %s, "
 		  "check if GISBASE environment variable is set, the driver is available "
 		  " and the database is accessible.", poLink->driver, poLink->database );
 	return false;
-    } 
+    }
     return true;
 }
 
@@ -290,32 +290,32 @@ bool OGRGRASSLayer::StartDbDriver()
 /************************************************************************/
 bool OGRGRASSLayer::StopDbDriver()
 {
-    if ( !poDriver ) 
+    if ( !poDriver )
     {
 	CPLError( CE_Failure, CPLE_AppDefined, "Driver is not started" );
 	return true; // I think that true is OK here
     }
 
-    // TODO!!!: Because of bug in GRASS library it is impossible 
-    // to stop drivers in FIFO order. Until this is fixed 
+    // TODO!!!: Because of bug in GRASS library it is impossible
+    // to stop drivers in FIFO order. Until this is fixed
     // we have to use kill
-    CPLDebug ( "GRASS", "driver PID = %d", poDriver->pid ); 
+    CPLDebug ( "GRASS", "driver PID = %d", poDriver->pid );
 
 #if defined(_WIN32) || defined(__WIN32__)
     db_close_database_shutdown_driver ( poDriver );
 #else
-    if ( kill (poDriver->pid, SIGINT) != 0 ) 
+    if ( kill (poDriver->pid, SIGINT) != 0 )
     {
-	if ( kill (poDriver->pid, SIGKILL) != 0 ) 
-	{
-	    CPLError( CE_Failure, CPLE_AppDefined, "Cannot stop database "
-		      "driver pid = %d", poDriver->pid );
-	}
+        if ( kill (poDriver->pid, SIGKILL) != 0 )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "Cannot stop database "
+                      "driver pid = %d", poDriver->pid );
+        }
     }
 #endif
-	    
+
     bCursorOpened = false;
-    
+
     return true;
 }
 
@@ -325,25 +325,25 @@ bool OGRGRASSLayer::StopDbDriver()
 void OGRGRASSLayer::ResetReading()
 {
     iNextId = 0;
-    
+
     if ( bCursorOpened ) {
-	ResetSequentialCursor();
+        ResetSequentialCursor();
     }
 }
 
 /************************************************************************/
 /*                           SetNextByIndex()                           */
 /*                                                                      */
-/*      If we already have an FID list, we can easily resposition       */
+/*      If we already have an FID list, we can easily reposition        */
 /*      ourselves in it.                                                */
 /************************************************************************/
 OGRErr OGRGRASSLayer::SetNextByIndex( GIntBig nIndex )
 {
-    if( m_poFilterGeom != NULL || m_poAttrQuery != NULL ) 
+    if( m_poFilterGeom != NULL || m_poAttrQuery != NULL )
     {
 	iNextId = 0;
 	int count = 0;
-	
+
 	while ( true ) {
 	    if( iNextId >= nTotalCount ) break;
 	    if ( count == nIndex ) break;
@@ -352,7 +352,7 @@ OGRErr OGRGRASSLayer::SetNextByIndex( GIntBig nIndex )
 	    if( pszQuery != NULL && !paQueryMatch[iNextId] ) {
 		iNextId++;
 		continue;
-	    }
+            }
 
 	    // Spatial
 	    if( m_poFilterGeom && !paSpatialMatch[iNextId] ) {
@@ -360,7 +360,7 @@ OGRErr OGRGRASSLayer::SetNextByIndex( GIntBig nIndex )
 		continue;
 	    }
 	    count++;
-	}
+        }
     }
 
     iNextId = nIndex;
@@ -396,16 +396,16 @@ OGRErr OGRGRASSLayer::SetAttributeFilter( const char *query )
 
     if ( bHaveAttributes ) {
 
-	if ( !poDriver ) 
+	if ( !poDriver )
 	{
 	    StartDbDriver();
 	}
 
-	if ( poDriver ) 
+	if ( poDriver )
 	{
 	    if ( bCursorOpened )
 	    {
-		db_close_cursor ( poCursor ); 
+		db_close_cursor ( poCursor );
 		bCursorOpened = false;
 	    }
 	    OpenSequentialCursor();
@@ -434,9 +434,9 @@ OGRErr OGRGRASSLayer::SetAttributeFilter( const char *query )
     else
     {
 	// Use OGR to evaluate category match
-	for ( int i = 0; i < nTotalCount; i++ ) 
+	for ( int i = 0; i < nTotalCount; i++ )
 	{
-	    OGRFeature *feature = GetFeature(i); 
+	    OGRFeature *feature = GetFeature(i);
 	    CPLDebug ( "GRASS", "i = %d eval = %d", i, m_poAttrQuery->Evaluate ( feature ) );
 	    if ( m_poAttrQuery->Evaluate ( feature ) )
 	    {
@@ -444,7 +444,7 @@ OGRErr OGRGRASSLayer::SetAttributeFilter( const char *query )
 	    }
 	}
     }
-    
+
     return OGRERR_NONE;
 }
 
@@ -457,7 +457,7 @@ bool OGRGRASSLayer::SetQueryMatch()
 
     // NOTE: we don't have to call ResetSequentialCursor() first because
     // this method is called immediately after OpenSequentialCursor()
-    
+
     if ( !bCursorOpened ) {
 	CPLError( CE_Failure, CPLE_AppDefined, "Cursor is not opened.");
 	return false;
@@ -470,7 +470,7 @@ bool OGRGRASSLayer::SetQueryMatch()
     int ncats = Vect_cidx_get_num_cats_by_index ( poMap, iLayerIndex );
     dbTable *table = db_get_cursor_table ( poCursor );
     while ( true ) {
-	if( db_fetch ( poCursor, DB_NEXT, &more) != DB_OK ) 
+	if( db_fetch ( poCursor, DB_NEXT, &more) != DB_OK )
 	{
 	    CPLError( CE_Failure, CPLE_AppDefined, "Cannot fetch attributes.");
 	    return false;
@@ -483,12 +483,12 @@ bool OGRGRASSLayer::SetQueryMatch()
 
 	// NOTE: because of bug in GRASS library it is impossible to use
 	//       Vect_cidx_find_next
-	
-	// Go through category index until first record of current category 
+
+	// Go through category index until first record of current category
 	// is found or a category > current is found
 	int cidxcat, type, id;
 	while ( cidx < ncats ) {
-	    Vect_cidx_get_cat_by_index ( poMap, iLayerIndex, cidx, 
+	    Vect_cidx_get_cat_by_index ( poMap, iLayerIndex, cidx,
 		                         &cidxcat, &type, &id );
 
 	    if ( cidxcat < cat ) {
@@ -496,7 +496,7 @@ bool OGRGRASSLayer::SetQueryMatch()
 		continue;
 	    }
 	    if ( cidxcat > cat ) break; // Not found
-	    
+
 	    // We have the category we want, check type
 	    if ( !(type & (GV_POINT|GV_LINES|GV_AREA)) )
 	    {
@@ -506,11 +506,11 @@ bool OGRGRASSLayer::SetQueryMatch()
 
 	    // Both category and type match -> find feature and set it on
 	    while ( true ) {
-		if ( fidx > nTotalCount || paFeatureIndex[fidx] > cidx ) { 
+		if ( fidx > nTotalCount || paFeatureIndex[fidx] > cidx ) {
 		    // should not happen
 		    break;
 		}
-		    
+
 		if ( paFeatureIndex[fidx] == cidx ) {
 		    paQueryMatch[fidx] = 1;
 		    fidx++;
@@ -526,7 +526,7 @@ bool OGRGRASSLayer::SetQueryMatch()
 
     return true;
 }
-    
+
 /************************************************************************/
 /*                           OpenSequentialCursor                       */
 /************************************************************************/
@@ -534,7 +534,7 @@ bool OGRGRASSLayer::OpenSequentialCursor()
 {
     CPLDebug ( "GRASS", "OpenSequentialCursor: %s", pszQuery  );
 
-    if ( !poDriver ) 
+    if ( !poDriver )
     {
 	CPLError( CE_Failure, CPLE_AppDefined, "Driver not opened.");
 	return false;
@@ -559,15 +559,15 @@ bool OGRGRASSLayer::OpenSequentialCursor()
     db_append_string ( poDbString, buf);
 
     CPLDebug ( "GRASS", "Query: %s", db_get_string(poDbString) );
-    
-    if ( db_open_select_cursor ( poDriver, poDbString, 
-		poCursor, DB_SCROLL) == DB_OK ) 
+
+    if ( db_open_select_cursor ( poDriver, poDbString,
+		poCursor, DB_SCROLL) == DB_OK )
     {
 	iCurrentCat = -1;
 	bCursorOpened = true;
 	CPLDebug ( "GRASS", "num rows = %d", db_get_num_rows ( poCursor ) );
-    } 
-    else 
+    }
+    else
     {
 	CPLError( CE_Failure, CPLE_AppDefined, "Cannot open cursor.");
 	return false;
@@ -583,12 +583,12 @@ bool OGRGRASSLayer::ResetSequentialCursor()
     CPLDebug ( "GRASS", "ResetSequentialCursor" );
 
     int more;
-    if( db_fetch ( poCursor, DB_FIRST, &more) != DB_OK ) 
+    if( db_fetch ( poCursor, DB_FIRST, &more) != DB_OK )
     {
 	CPLError( CE_Failure, CPLE_AppDefined, "Cannot reset cursor.");
 	return false;
     }
-    if( db_fetch ( poCursor, DB_PREVIOUS, &more) != DB_OK ) 
+    if( db_fetch ( poCursor, DB_PREVIOUS, &more) != DB_OK )
     {
 	CPLError( CE_Failure, CPLE_AppDefined, "Cannot reset cursor.");
 	return false;
@@ -624,13 +624,13 @@ bool OGRGRASSLayer::SetSpatialMatch()
 {
     CPLDebug ( "GRASS", "SetSpatialMatch" );
 
-    if ( !paSpatialMatch ) 
+    if ( !paSpatialMatch )
     {
 	paSpatialMatch = (char *) CPLMalloc ( nTotalCount );
     }
     memset ( paSpatialMatch, 0x0, nTotalCount );
 
-    OGRGeometry *geom; 
+    OGRGeometry *geom;
     OGRLineString *lstring = new OGRLineString();
     lstring->setNumPoints ( 5 );
     geom = lstring;
@@ -639,7 +639,7 @@ bool OGRGRASSLayer::SetSpatialMatch()
 	int cidx = paFeatureIndex[i];
 
 	int cat, type, id;
-	
+
 	Vect_cidx_get_cat_by_index ( poMap, iLayerIndex, cidx, &cat, &type, &id );
 
 #if GRASS_VERSION_MAJOR  >= 7
@@ -648,7 +648,7 @@ bool OGRGRASSLayer::SetSpatialMatch()
 	BOUND_BOX box;
 #endif
 
-	switch ( type ) 
+	switch ( type )
 	{
 	    case GV_POINT:
 	    case GV_LINE:
@@ -660,7 +660,7 @@ bool OGRGRASSLayer::SetSpatialMatch()
 		Vect_get_area_box ( poMap, id, &box );
 		break;
 	}
-		
+
 	lstring->setPoint( 0, box.W, box.N, 0. );
 	lstring->setPoint( 1, box.W, box.S, 0. );
 	lstring->setPoint( 2, box.E, box.S, 0. );
@@ -675,7 +675,7 @@ bool OGRGRASSLayer::SetSpatialMatch()
     delete lstring;
     return true;
 }
-    
+
 /************************************************************************/
 /*                           GetNextFeature()                           */
 /************************************************************************/
@@ -689,14 +689,14 @@ OGRFeature *OGRGRASSLayer::GetNextFeature()
     // Get next iNextId
     while ( true ) {
 	if( iNextId >= nTotalCount ) // No more features
-	{ 
-	    // Close cursor / driver if opened 
-	    if ( bCursorOpened ) 
+	{
+	    // Close cursor / driver if opened
+	    if ( bCursorOpened )
 	    {
 	    	db_close_cursor ( poCursor);
 	    	bCursorOpened = false;
 	    }
-	    if ( poDriver ) 
+	    if ( poDriver )
 	    {
     	    	db_close_database_shutdown_driver ( poDriver );
 		poDriver = NULL;
@@ -716,7 +716,7 @@ OGRFeature *OGRGRASSLayer::GetNextFeature()
 	    iNextId++;
 	    continue;
 	}
-	
+
 	break; // Attributes & spatial filter match
     }
 
@@ -726,30 +726,30 @@ OGRFeature *OGRGRASSLayer::GetNextFeature()
     poFeature->SetGeometryDirectly( poOGR );
     poFeature->SetFID ( iNextId );
     iNextId++;
-    
+
     // Get attributes
     CPLDebug ( "GRASS", "bHaveAttributes = %d", bHaveAttributes );
-    if ( bHaveAttributes ) 
+    if ( bHaveAttributes )
     {
-	if ( !poDriver ) 
+	if ( !poDriver )
 	{
 	    StartDbDriver();
 	}
 	if ( poDriver ) {
-	    if ( !bCursorOpened ) 
+	    if ( !bCursorOpened )
 	    {
 		OpenSequentialCursor();
 	    }
-	    if ( bCursorOpened ) 
+	    if ( bCursorOpened )
 	    {
 		dbTable  *table = db_get_cursor_table ( poCursor );
-		if ( iCurrentCat < cat ) 
+		if ( iCurrentCat < cat )
 		{
 		    while ( true ) {
 			int more;
-			if( db_fetch ( poCursor, DB_NEXT, &more) != DB_OK ) 
+			if( db_fetch ( poCursor, DB_NEXT, &more) != DB_OK )
 			{
-			    CPLError( CE_Failure, CPLE_AppDefined, 
+			    CPLError( CE_Failure, CPLE_AppDefined,
 				      "Cannot fetch attributes.");
 			    break;
 			}
@@ -765,19 +765,19 @@ OGRFeature *OGRGRASSLayer::GetNextFeature()
 		if ( cat == iCurrentCat )
 		{
 		    SetAttributes ( poFeature, table );
-		} 
-		else 
+		}
+		else
 		{
 		    CPLError( CE_Failure, CPLE_AppDefined, "Attributes not found.");
 		}
 	    }
 	}
-    } 
+    }
     else if ( iLayer > 0 ) // Add category
     {
 	poFeature->SetField( 0, cat );
-    }	
-    
+    }
+
     m_nFeaturesRead++;
     return poFeature;
 }
@@ -799,47 +799,47 @@ OGRFeature *OGRGRASSLayer::GetFeature( GIntBig nFeatureId )
     poFeature->SetFID ( nFeatureId );
 
     // Get attributes
-    if ( bHaveAttributes && !poDriver ) 
+    if ( bHaveAttributes && !poDriver )
     {
 	StartDbDriver();
     }
-    if ( poDriver ) 
+    if ( poDriver )
     {
-	if ( bCursorOpened ) 
+	if ( bCursorOpened )
 	{
 	    db_close_cursor ( poCursor);
 	    bCursorOpened = false;
 	}
 	CPLDebug ( "GRASS", "Open cursor for key = %d", cat );
 	char buf[2000];
-	sprintf ( buf, "SELECT * FROM %s WHERE %s = %d", 
+	sprintf ( buf, "SELECT * FROM %s WHERE %s = %d",
 		       poLink->table, poLink->key, cat );
 	db_set_string ( poDbString, buf);
-	if ( db_open_select_cursor ( poDriver, poDbString, 
-		    poCursor, DB_SEQUENTIAL) == DB_OK ) 
+	if ( db_open_select_cursor ( poDriver, poDbString,
+		    poCursor, DB_SEQUENTIAL) == DB_OK )
 	{
 	    iCurrentCat = cat; // Not important
 	    bCursorOpened = true;
-	} 
-	else 
+	}
+	else
 	{
 	    CPLError( CE_Failure, CPLE_AppDefined, "Cannot open cursor.");
 	}
 
-	if ( bCursorOpened ) 
+	if ( bCursorOpened )
 	{
 	    int more;
-	    if( db_fetch ( poCursor, DB_NEXT, &more) != DB_OK ) 
+	    if( db_fetch ( poCursor, DB_NEXT, &more) != DB_OK )
 	    {
 		CPLError( CE_Failure, CPLE_AppDefined, "Cannot fetch attributes.");
-	    } 
-	    else 
+	    }
+	    else
 	    {
-		if ( !more ) 
+		if ( !more )
 		{
 		    CPLError( CE_Failure, CPLE_AppDefined, "Attributes not found.");
-		} 
-		else 
+		}
+		else
 		{
 	    	    dbTable *table = db_get_cursor_table ( poCursor );
 		    SetAttributes ( poFeature, table );
@@ -848,12 +848,12 @@ OGRFeature *OGRGRASSLayer::GetFeature( GIntBig nFeatureId )
 	    db_close_cursor ( poCursor);
 	    bCursorOpened = false;
 	}
-    } 
+    }
     else if ( iLayer > 0 ) // Add category
     {
 	poFeature->SetField( 0, cat );
-    }	
-    
+    }
+
     m_nFeaturesRead++;
     return poFeature;
 }
@@ -885,17 +885,17 @@ OGRGeometry *OGRGRASSLayer::GetFeatureGeometry ( long nFeatureId, int *cat )
                 poOGR = new OGRPoint( poPoints->x[0], poPoints->y[0] );
         }
         break;
-	    
+
 	case GV_LINE:
 	case GV_BOUNDARY:
         {
 	    Vect_read_line ( poMap, poPoints, poCats, id);
 	    OGRLineString *poOGRLine = new OGRLineString();
             if (bIs3D)
-                poOGRLine->setPoints( poPoints->n_points, 
+                poOGRLine->setPoints( poPoints->n_points,
                                       poPoints->x, poPoints->y, poPoints->z );
             else
-                poOGRLine->setPoints( poPoints->n_points, 
+                poOGRLine->setPoints( poPoints->n_points,
                                       poPoints->x, poPoints->y );
 
             poOGR = poOGRLine;
@@ -905,7 +905,7 @@ OGRGeometry *OGRGRASSLayer::GetFeatureGeometry ( long nFeatureId, int *cat )
 	case GV_AREA:
         {
 	    Vect_get_area_points ( poMap, id, poPoints );
-	    
+
 	    OGRPolygon 		*poOGRPoly;
 	    poOGRPoly = new OGRPolygon();
 
@@ -916,7 +916,7 @@ OGRGeometry *OGRGRASSLayer::GetFeatureGeometry ( long nFeatureId, int *cat )
                                 poPoints->x, poPoints->y, poPoints->z );
             else
                 poRing->setPoints( poPoints->n_points,
-                                poPoints->x, poPoints->y ); 
+                                poPoints->x, poPoints->y );
 
 	    poOGRPoly->addRingDirectly( poRing );
 
@@ -936,9 +936,9 @@ OGRGeometry *OGRGRASSLayer::GetFeatureGeometry ( long nFeatureId, int *cat )
 
 		poOGRPoly->addRingDirectly( poRing );
 	    }
-	    
+
 	    poOGR = poOGRPoly;
-        }   
+        }
         break;
 
 	default: // Should not happen
@@ -947,7 +947,7 @@ OGRGeometry *OGRGRASSLayer::GetFeatureGeometry ( long nFeatureId, int *cat )
 	    return NULL;
         }
     }
-	    
+
     return poOGR;
 }
 
@@ -958,7 +958,7 @@ bool OGRGRASSLayer::SetAttributes ( OGRFeature *poFeature, dbTable *table )
 {
     CPLDebug ( "GRASS", "OGRGRASSLayer::SetAttributes" );
 
-    for ( int i = 0; i < nFields; i++) 
+    for ( int i = 0; i < nFields; i++)
     {
 	dbColumn *column = db_get_table_column ( table, i );
 	dbValue *value = db_get_column_value ( column );
@@ -970,20 +970,20 @@ bool OGRGRASSLayer::SetAttributes ( OGRFeature *poFeature, dbTable *table )
 	    switch ( ctype ) {
 		case DB_C_TYPE_INT:
 		    poFeature->SetField( i, db_get_value_int ( value ));
-		    break; 
+		    break;
 		case DB_C_TYPE_DOUBLE:
 		    poFeature->SetField( i, db_get_value_double ( value ));
-		    break; 
+		    break;
 		case DB_C_TYPE_STRING:
 		    poFeature->SetField( i, db_get_value_string ( value ));
-		    break; 
+		    break;
 		case DB_C_TYPE_DATETIME:
 		    db_convert_column_value_to_string ( column, poDbString );
 		    poFeature->SetField( i, db_get_string ( poDbString ));
-		    break; 
+		    break;
 	    }
 	}
-	
+
 	db_convert_column_value_to_string ( column, poDbString );
 	//CPLDebug ( "GRASS", "val = %s", db_get_string ( poDbString ));
     }
@@ -1018,7 +1018,7 @@ GIntBig OGRGRASSLayer::GetFeatureCount( int bForce )
 {
     if( m_poFilterGeom != NULL || m_poAttrQuery != NULL )
         return OGRLayer::GetFeatureCount( bForce );
-        
+
     return nTotalCount;
 }
 
@@ -1069,7 +1069,7 @@ int OGRGRASSLayer::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCFastSetNextByIndex) )
         return TRUE;
 
-    else 
+    else
         return FALSE;
 }
 
@@ -1080,7 +1080,7 @@ OGRErr OGRGRASSLayer::CreateField( OGRFieldDefn *poField, int bApproxOK )
 {
     CPLError( CE_Failure, CPLE_NotSupported,
                   "Can't create fields on a GRASS layer.\n");
-    
+
     return OGRERR_FAILURE;
 }
 
@@ -1091,4 +1091,3 @@ OGRSpatialReference *OGRGRASSLayer::GetSpatialRef()
 {
     return poSRS;
 }
-
diff --git a/ogr/ogrsf_frmts/gtm/drv_gtm.html b/ogr/ogrsf_frmts/gtm/drv_gtm.html
index f45de3b..7ac943b 100644
--- a/ogr/ogrsf_frmts/gtm/drv_gtm.html
+++ b/ogr/ogrsf_frmts/gtm/drv_gtm.html
@@ -53,7 +53,7 @@ ogr2ogr -f "GPSTrackMaker" output.gtm input.shp -sql "SELECT field1 AS name, fie
 <pre>
 ogr2ogr -f "GPSTrackMaker" output.gtm PG:"host=hostaddress user=username dbname=db password=mypassword" -sql "select filed1 as name, field2 as color, field3 as type, wkb_geometry from input" -nlt MULTILINESTRING
 </pre>
-<br> 
+<br>
 Note : You need to specify the layer type as POINT, LINESTRING, or MULTILINESTRING.
 </li>
 
diff --git a/ogr/ogrsf_frmts/gtm/gtm.cpp b/ogr/ogrsf_frmts/gtm/gtm.cpp
index b815e5a..8a8ba13 100644
--- a/ogr/ogrsf_frmts/gtm/gtm.cpp
+++ b/ogr/ogrsf_frmts/gtm/gtm.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gtm.cpp 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: gtm.cpp 32760 2016-01-05 17:50:33Z rouault $
  *
  * Project:  GTM Driver
  * Purpose:  Class for reading, parsing and handling a gtmfile.
@@ -27,6 +27,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
+
 #include "gtm.h"
 
 
@@ -41,13 +42,13 @@ void appendDouble(void* pBuffer, double val)
 
 void appendFloat(void* pBuffer, float val)
 {
-    CPL_LSBPTR32(&val)
+    CPL_LSBPTR32(&val);
     memcpy(pBuffer, &val, 4);
 }
 
 void appendInt(void* pBuffer, int val)
 {
-    CPL_LSBPTR32(&val)
+    CPL_LSBPTR32(&val);
     memcpy(pBuffer, &val, 4);
 }
 
@@ -58,7 +59,7 @@ void appendUChar(void* pBuffer, unsigned char val)
 
 void appendUShort(void* pBuffer, unsigned short val)
 {
-    CPL_LSBPTR16(&val)
+    CPL_LSBPTR16(&val);
     memcpy(pBuffer, &val, 2);
 }
 
@@ -69,7 +70,7 @@ void writeUChar(VSILFILE* fp, unsigned char val)
 
 void writeDouble(VSILFILE* fp, double val)
 {
-    CPL_LSBPTR64(&val)
+    CPL_LSBPTR64(&val);
     VSIFWriteL(&val, 1, 8, fp);
 }
 
@@ -77,7 +78,7 @@ static double readDouble(VSILFILE* fp)
 {
     double val;
     VSIFReadL( &val, 1, 8, fp );
-    CPL_LSBPTR64(&val)
+    CPL_LSBPTR64(&val);
     return val;
 }
 
@@ -85,7 +86,7 @@ static float readFloat(VSILFILE* fp)
 {
     float val;
     VSIFReadL( &val, 1, 4, fp );
-    CPL_LSBPTR32(&val)
+    CPL_LSBPTR32(&val);
     return val;
 }
 
@@ -93,7 +94,7 @@ static int readInt(VSILFILE* fp)
 {
     int val;
     VSIFReadL( &val, 1, 4, fp );
-    CPL_LSBPTR32(&val)
+    CPL_LSBPTR32(&val);
     return val;
 }
 
@@ -113,48 +114,46 @@ static unsigned short readUShort(VSILFILE* fp, int *pbSuccess = NULL)
         return 0;
     }
     if (pbSuccess) *pbSuccess = TRUE;
-    CPL_LSBPTR16(&val)
+    CPL_LSBPTR16(&val);
     return val;
 }
 
 void writeFloat(VSILFILE* fp, float val)
 {
-    CPL_LSBPTR32(&val)
+    CPL_LSBPTR32(&val);
     VSIFWriteL(&val, 1, 4, fp);
 }
 
 void writeInt(VSILFILE* fp, int val)
 {
-    CPL_LSBPTR32(&val)
+    CPL_LSBPTR32(&val);
     VSIFWriteL(&val, 1, 4, fp);
 }
 
 void writeUShort(VSILFILE* fp, unsigned short val)
 {
-    CPL_LSBPTR16(&val)
+    CPL_LSBPTR16(&val);
     VSIFWriteL(&val, 1, 2, fp);
 }
 
-
 /************************************************************************/
 /*             Implementation of Waypoint Function Members              */
 /************************************************************************/
-Waypoint::Waypoint(double latitude,
-                   double longitude,
-                   double altitude,
-                   const char* name,
-                   const char* comment,
-                   int icon,
-                   GIntBig wptdate)
-{
-    this->latitude = latitude;
-    this->longitude = longitude;
-    this->altitude = altitude;
-    this->name = CPLStrdup(name);
-    this->comment = CPLStrdup(comment);
-    this->icon = icon;
-    this->wptdate = wptdate;
-}
+Waypoint::Waypoint( double latitudeIn,
+                    double longitudeIn,
+                    double altitudeIn,
+                    const char* nameIn,
+                    const char* commentIn,
+                    int iconIn,
+                    GIntBig wptdateIn ) :
+    latitude(latitudeIn),
+    longitude(longitudeIn),
+    altitude(altitudeIn),
+    name(CPLStrdup(nameIn)),
+    comment(CPLStrdup(commentIn)),
+    icon(iconIn),
+    wptdate(wptdateIn)
+{}
 
 Waypoint::~Waypoint()
 {
@@ -162,37 +161,37 @@ Waypoint::~Waypoint()
     CPLFree(comment);
 }
 
-double Waypoint::getLatitude() 
+double Waypoint::getLatitude() const
 {
     return latitude;
 }
 
-double Waypoint::getLongitude()
+double Waypoint::getLongitude() const
 {
     return longitude;
 }
 
-double Waypoint::getAltitude()
+double Waypoint::getAltitude() const
 {
     return altitude;
 }
 
-const char* Waypoint::getName()
+const char* Waypoint::getName() const
 {
     return name;
 }
 
-const char* Waypoint::getComment()
+const char* Waypoint::getComment() const
 {
     return comment;
 }
 
-int Waypoint::getIcon()
+int Waypoint::getIcon() const
 {
     return icon;
 }
 
-GIntBig Waypoint::getDate()
+GIntBig Waypoint::getDate() const
 {
     return wptdate;
 }
@@ -200,16 +199,15 @@ GIntBig Waypoint::getDate()
 /************************************************************************/
 /*               Implementation of Track Function Members               */
 /************************************************************************/
-Track::Track(const char* pszName,
-             unsigned char type,
-             int color)
-{
-    this->pszName = CPLStrdup(pszName);
-    this->type = type;
-    this->color = color;
-    nPoints = 0;
-    pasTrackPoints = NULL;
-}
+Track::Track( const char* pszNameIn,
+              unsigned char typeIn,
+              int colorIn) :
+    pszName(CPLStrdup(pszNameIn)),
+    type(typeIn),
+    color(colorIn),
+    nPoints(0),
+    pasTrackPoints(NULL)
+{}
 
 Track::~Track()
 {
@@ -218,25 +216,26 @@ Track::~Track()
     CPLFree(pasTrackPoints);
 }
 
-const char* Track::getName() {
+const char* Track::getName() const
+{
     return pszName;
 }
 
-unsigned char Track::getType()
+unsigned char Track::getType() const
 {
     return type;
 }
 
 
-int Track::getColor()
+int Track::getColor() const
 {
     return color;
 }
 
 void Track::addPoint(double x, double y, GIntBig datetime, double altitude)
 {
-    pasTrackPoints = (TrackPoint*)
-        CPLRealloc(pasTrackPoints, (nPoints + 1) * sizeof(TrackPoint));
+    pasTrackPoints = static_cast<TrackPoint*>(
+        CPLRealloc(pasTrackPoints, (nPoints + 1) * sizeof(TrackPoint)) );
     pasTrackPoints[nPoints].x = x;
     pasTrackPoints[nPoints].y = y;
     pasTrackPoints[nPoints].datetime = datetime;
@@ -244,47 +243,42 @@ void Track::addPoint(double x, double y, GIntBig datetime, double altitude)
     nPoints ++;
 }
 
-int Track::getNumPoints()
+int Track::getNumPoints() const
 {
     return nPoints;
 }
 
-const TrackPoint* Track::getPoint(int pointNum)
+const TrackPoint* Track::getPoint(int pointNum) const
 {
     if (pointNum >=0 && pointNum < nPoints)
         return &pasTrackPoints[pointNum];
-    else
-        return NULL;
+
+    return NULL;
 }
 
 
 /************************************************************************/
 /*                Implementation of GTM Function Members                */
 /************************************************************************/
-GTM::GTM()
-{
-    pGTMFile = NULL;
-    pszFilename = NULL;
-
-    nwptstyles = 0;
-    nwpts = 0;
-    ntcks = 0;
-    n_tk = 0;
-    n_maps = 0;
-    headerSize = 0;
-
-    firstWaypointOffset = 0;
-    actualWaypointOffset = 0;
-    waypointFetched = 0;
-  
-    firstTrackpointOffset = 0;
-    actualTrackpointOffset = 0;
-    trackpointFetched = 0;
-
-    firstTrackOffset = 0;
-    actualTrackOffset = 0;
-    trackFetched = 0;
-}
+GTM::GTM() :
+    pGTMFile(NULL),
+    pszFilename(NULL),
+    nwptstyles(0),
+    nwpts(0),
+    ntcks(0),
+    n_tk(0),
+    n_maps(0),
+    headerSize(0),
+    firstWaypointOffset(0),
+    actualWaypointOffset(0),
+    waypointFetched(0),
+    firstTrackpointOffset(0),
+    actualTrackpointOffset(0),
+    trackpointFetched(0),
+    firstTrackOffset(0),
+    actualTrackOffset(0),
+    trackFetched(0)
+{}
 
 GTM::~GTM()
 {
@@ -296,56 +290,53 @@ GTM::~GTM()
     }
 }
 
-bool GTM::Open(const char* pszFilename)
+bool GTM::Open(const char* pszFilenameIn)
 {
 
     if (pGTMFile != NULL)
         VSIFCloseL(pGTMFile);
-        
-    CPLFree(this->pszFilename);
-    this->pszFilename = CPLStrdup(pszFilename);
+
+    CPLFree(pszFilename);
+    pszFilename = CPLStrdup(pszFilenameIn);
 
     pGTMFile = VSIFOpenL( pszFilename, "r" );
     if (pGTMFile == NULL)
     {
-        return FALSE;
+        return false;
     }
-    return TRUE;
+    return true;
 }
 
 
 bool GTM::isValid()
 {
-    //  2 bytes - version number
-    // 10 bytes - "TrackMaker" string
-    char buffer[13];
-
-    char* szHeader;
-    short version;
-
 /* -------------------------------------------------------------------- */
 /*      If we aren't sure it is GTM, load a header chunk and check      */
 /*      for signs it is GTM                                             */
 /* -------------------------------------------------------------------- */
-    size_t nRead = VSIFReadL( buffer, 1, sizeof(buffer)-1, pGTMFile );
-    if (nRead <= 0)
+    //  2 bytes - version number
+    // 10 bytes - "TrackMaker" string
+    char buffer[13];
+
+    const size_t nRead = VSIFReadL( buffer, 1, sizeof(buffer)-1, pGTMFile );
+    if (nRead == 0)
     {
         VSIFCloseL( pGTMFile );
         pGTMFile = NULL;
-        return FALSE;
+        return false;
     }
     buffer[12] = '\0';
-    
+
 /* -------------------------------------------------------------------- */
 /*      If it looks like a GZip header, this may be a .gtz file, so     */
 /*      try opening with the /vsigzip/ prefix                           */
 /* -------------------------------------------------------------------- */
     if (buffer[0] == 0x1f && ((unsigned char*)buffer)[1] == 0x8b &&
-        strncmp(pszFilename, "/vsigzip/", strlen("/vsigzip/")) != 0)
+        !STARTS_WITH(pszFilename, "/vsigzip/"))
     {
-        char* pszGZIPFileName = (char*)CPLMalloc(
-                           strlen("/vsigzip/") + strlen(pszFilename) + 1);
-        sprintf(pszGZIPFileName, "/vsigzip/%s", pszFilename);
+        const size_t nLen = strlen("/vsigzip/") + strlen(pszFilename) + 1;
+        char* pszGZIPFileName = static_cast<char *>(CPLMalloc(nLen));
+        snprintf(pszGZIPFileName, nLen, "/vsigzip/%s", pszFilename);
         VSILFILE* fp = VSIFOpenL(pszGZIPFileName, "rb");
         if (fp)
         {
@@ -355,7 +346,7 @@ bool GTM::isValid()
             {
                 VSIFCloseL(pGTMFileOri);
                 CPLFree(pszGZIPFileName);
-                return TRUE;
+                return true;
             }
             else
             {
@@ -366,23 +357,22 @@ bool GTM::isValid()
         }
         CPLFree(pszGZIPFileName);
     }
-    
-    version = CPL_LSBINT16PTR(buffer);
+
+    const short version = CPL_LSBINT16PTR(buffer);
     /*Skip string length */
-    szHeader = buffer + 2;
+    const char* szHeader = buffer + 2;
     if (version == 211 && strcmp(szHeader, "TrackMaker") == 0 )
     {
-        return TRUE;
+        return true;
     }
-    return FALSE;
+    return false;
 }
 
 bool GTM::readHeaderNumbers()
 {
     if (pGTMFile == NULL)
-        return FALSE;
+        return false;
 
-   
     /* I'm supposing that the user has already checked if the file is
        valid.  */
     /* Also, I'm ignoring some header parameters that are unnecessary
@@ -391,119 +381,118 @@ bool GTM::readHeaderNumbers()
     /* Read Number of Waypoint Styles*/
     /* Seek file */
     if (VSIFSeekL(pGTMFile, NWPTSTYLES_OFFSET, SEEK_SET) != 0)
-        return FALSE;
+        return false;
     /* Read nwptstyles */
     nwptstyles = readInt(pGTMFile);
     if (nwptstyles < 0)
-        return FALSE;
+        return false;
 
     /* Read Number of Waypoints */
     /* Seek file */
     if ( VSIFSeekL(pGTMFile, NWPTS_OFFSET, SEEK_SET) != 0)
-        return FALSE;
+        return false;
     /* Read nwpts */
     nwpts = readInt(pGTMFile);
     if (nwpts < 0)
-        return FALSE;
+        return false;
 
     /* Read Number of Trackpoints */
     ntcks = readInt(pGTMFile);
     if (ntcks < 0)
-        return FALSE;
+        return false;
 
     /* Read Number of images */
     /* Seek file */
     if ( VSIFSeekL(pGTMFile, NMAPS_OFFSET, SEEK_SET) != 0)
-        return FALSE;
+        return false;
     /* read n_maps */
     n_maps = readInt(pGTMFile);
     if (n_maps < 0)
-        return FALSE;
+        return false;
 
     /* Read Number of Tracks */
     n_tk = readInt(pGTMFile);
     if (n_tk < 0)
-        return FALSE;
+        return false;
 
     /* Figure out the header size */
     headerSize = 99; // Constant size plus size of strings
-    unsigned short stringSize;
 
     /* Read gradfont string size */
     if ( VSIFSeekL(pGTMFile, 99, SEEK_SET) != 0)
-        return FALSE;
-    stringSize = readUShort(pGTMFile);
+        return false;
+    unsigned short stringSize = readUShort(pGTMFile);
     headerSize += stringSize + 2; // String + size field
 
     /* Read labelfont string size */
     if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
-        return FALSE;
+        return false;
     stringSize = readUShort(pGTMFile);
     headerSize += stringSize + 2; // String + size field
 
 
     /* Read userfont string size */
     if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
-        return FALSE;
+        return false;
     stringSize = readUShort(pGTMFile);
     headerSize += stringSize + 2; // String + size field
 
     /* Read newdatum string size */
     if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
-        return FALSE;
+        return false;
     stringSize = readUShort(pGTMFile);
     headerSize += stringSize + 2; // String + size field
 
-
-
 /* -------------------------------------------------------------------- */
 /*                 Checks if it is using WGS84 datum                    */
 /* -------------------------------------------------------------------- */
     /* Read newdatum string size */
     if ( VSIFSeekL(pGTMFile, headerSize + 34, SEEK_SET) != 0)
-        return FALSE;
+        return false;
     if (readInt(pGTMFile) != 217)
     {
         CPLError( CE_Warning, CPLE_AppDefined,
-                  "You are attempting to open a file that is not using WGS84 datum.\n"
-                  "Coordinates will be returned as if they were WGS84, but no reprojection will be done.");
+                  "You are attempting to open a file that is not using "
+                  "WGS84 datum.\n"
+                  "Coordinates will be returned as if they were WGS84, "
+                  "but no reprojection will be done." );
     }
 
     /* Look for the offsets */
     /* Waypoints */
     firstWaypointOffset = findFirstWaypointOffset();
     if (firstWaypointOffset == 0)
-        return FALSE;
+        return false;
     actualWaypointOffset = firstWaypointOffset;
     /* Trackpoints */
     firstTrackpointOffset = findFirstTrackpointOffset();
     if (firstTrackpointOffset == 0)
-        return FALSE;
+        return false;
     actualTrackpointOffset = firstTrackpointOffset;
 
     /* Tracks */
     firstTrackOffset = findFirstTrackOffset();
     if (firstTrackOffset == 0)
-        return FALSE;
+        return false;
     actualTrackOffset = firstTrackOffset;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                        Waypoint control functions                    */
 /************************************************************************/
-int GTM::getNWpts()
+int GTM::getNWpts() const
 {
     return nwpts;
 }
 
-bool GTM::hasNextWaypoint()
+bool GTM::hasNextWaypoint() const
 {
     return waypointFetched < nwpts;
 }
 
-void GTM::rewindWaypoint() 
+void GTM::rewindWaypoint()
 {
     actualWaypointOffset = firstWaypointOffset;
     waypointFetched = 0;
@@ -511,41 +500,39 @@ void GTM::rewindWaypoint()
 
 Waypoint* GTM::fetchNextWaypoint()
 {
-    unsigned short stringSize;
-
-    double latitude, longitude;
-    char name[11];
-    char* comment;
-    unsigned short icon;
-    int i;
-    float altitude;
-    GIntBig wptdate;
-
     /* Point to the actual waypoint offset */
     if ( VSIFSeekL(pGTMFile, actualWaypointOffset, SEEK_SET) != 0)
         return NULL;
 
-    latitude = readDouble(pGTMFile);
-    longitude = readDouble(pGTMFile);
+    const double latitude = readDouble(pGTMFile);
+    const double longitude = readDouble(pGTMFile);
 
+    char name[11];
     if ( !readFile( name, 1, 10 ) )
         return NULL;
+
     /* Trim string name */
-    for (i = 9; i >= 0; --i)
     {
-        if (name[i] != ' ')
+    int i;
+        for (i = 9; i >= 0; --i)
         {
-            name[i+1] = '\0';
-            break;
+            if (name[i] != ' ')
+            {
+                name[i+1] = '\0';
+                break;
+            }
         }
+        if (i < 0)
+            name[0] = '\0';
     }
-    if (i < 0)
-        name[0] = '\0';
 
     /* Read String Length */
-    stringSize = readUShort(pGTMFile);
+    const unsigned short stringSize = readUShort(pGTMFile);
     /* Read Comment String */
-    comment = (char*) VSIMalloc2(sizeof(char), stringSize+1);
+    char* comment = static_cast<char *>(
+        VSI_MALLOC2_VERBOSE(sizeof(char), stringSize+1) );
+    if( comment == NULL )
+        return NULL;
     if ( stringSize != 0 && !readFile( comment, 1, sizeof(char)*stringSize ) )
     {
         CPLFree(comment);
@@ -554,23 +541,23 @@ Waypoint* GTM::fetchNextWaypoint()
     comment[stringSize] = '\0';
 
     /* Read Icon */
-    icon = readUShort(pGTMFile);
-    
+    const unsigned short icon = readUShort(pGTMFile);
+
     /* Display number */
     readUChar(pGTMFile);
-    
+
     /* Waypoint date */
-    
-    wptdate = readInt(pGTMFile);
+
+    GIntBig wptdate = readInt(pGTMFile);
     if (wptdate != 0)
         wptdate += GTM_EPOCH;
-    
+
     /* Rotation text angle */
     readUShort(pGTMFile);
-    
+
     /* Altitude */
-    altitude = readFloat(pGTMFile);
-  
+    const float altitude = readFloat(pGTMFile);
+
     Waypoint* poWaypoint = new Waypoint(latitude, longitude, altitude,
                                         name, comment, (int) icon, wptdate);
 
@@ -579,7 +566,8 @@ Waypoint* GTM::fetchNextWaypoint()
     ++waypointFetched;
     if (waypointFetched < nwpts)
     {
-        actualWaypointOffset += 8 + 8 + 10 + 2 + stringSize + 2 + 1 + 4 + 2 + 4 + 2;
+        actualWaypointOffset +=
+            8 + 8 + 10 + 2 + stringSize + 2 + 1 + 4 + 2 + 4 + 2;
     }
 
     CPLFree(comment);
@@ -590,17 +578,17 @@ Waypoint* GTM::fetchNextWaypoint()
 /************************************************************************/
 /*                        Track control functions                    */
 /************************************************************************/
-int GTM::getNTracks()
+int GTM::getNTracks() const
 {
     return n_tk;
 }
 
-bool GTM::hasNextTrack()
+bool GTM::hasNextTrack() const
 {
     return trackFetched < n_tk;
 }
 
-void GTM::rewindTrack() 
+void GTM::rewindTrack()
 {
     actualTrackpointOffset = firstTrackpointOffset;
     actualTrackOffset = firstTrackOffset;
@@ -615,7 +603,7 @@ Track* GTM::fetchNextTrack()
     char* pszName;
     unsigned char type;
     int color;
-  
+
 
     /* Point to the actual track offset */
     if ( VSIFSeekL(pGTMFile, actualTrackOffset, SEEK_SET) != 0)
@@ -625,7 +613,9 @@ Track* GTM::fetchNextTrack()
     /* Read string length */
     stringSize = readUShort(pGTMFile);
     /* Read name string */
-    pszName = (char*) VSIMalloc2(sizeof(char), stringSize+1);
+    pszName = (char*) VSI_MALLOC2_VERBOSE(sizeof(char), stringSize+1);
+    if( pszName == NULL )
+        return NULL;
     if ( stringSize != 0 && !readFile( pszName, 1, sizeof(char) * stringSize ) )
     {
         CPLFree(pszName);
@@ -635,10 +625,10 @@ Track* GTM::fetchNextTrack()
 
     /* Read type */
     type = readUChar(pGTMFile);
-  
+
     /* Read color */
     color = readInt(pGTMFile);
-    
+
     Track* poTrack = new Track(pszName, type, color);
 
     CPLFree(pszName);
@@ -665,7 +655,7 @@ Track* GTM::fetchNextTrack()
         return NULL;
     }
     poTrack->addPoint(longitude, latitude, datetime, altitude);
-  
+
     do
     {
         /* NOTE: Parameters are passed by reference */
@@ -698,13 +688,12 @@ vsi_l_offset GTM::findFirstWaypointOffset()
     /* Skip header and datum */
     if ( VSIFSeekL(pGTMFile, headerSize + DATUM_SIZE, SEEK_SET) != 0)
         return 0;
-  
+
     /* Skip images */
-    unsigned short stringSize;
     for (int i = 0; i < n_maps; ++i)
     {
         /* Read image name string size */
-        stringSize = readUShort(pGTMFile);
+        unsigned short stringSize = readUShort(pGTMFile);
 
         /* skip image name string */
         if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
@@ -716,7 +705,7 @@ vsi_l_offset GTM::findFirstWaypointOffset()
         /* skip image comment string */
         if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
             return 0;
-    
+
         /* skip the others image parameters */
         if ( VSIFSeekL(pGTMFile, 30, SEEK_CUR) != 0)
             return 0;
@@ -740,7 +729,7 @@ vsi_l_offset GTM::findFirstTrackpointOffset()
     /* Seek file to the first Waypoint */
     if (VSIFSeekL(pGTMFile, firstWaypointOffset, SEEK_SET) != 0)
         return 0;
-  
+
     unsigned short stringSize;
     int bSuccess;
     /* Skip waypoints */
@@ -751,12 +740,12 @@ vsi_l_offset GTM::findFirstTrackpointOffset()
             return 0;
         /* Read string comment size */
         stringSize = readUShort(pGTMFile, &bSuccess);
-    
+
         /* Skip to the next Waypoint */
         if (bSuccess == FALSE || VSIFSeekL(pGTMFile, stringSize + 15, SEEK_CUR) != 0)
             return 0;
     }
-  
+
     /* Skip waypoint styles */
     /* If we don't have waypoints, we don't have waypoint styles, even
        though the nwptstyles is telling the contrary. */
@@ -790,18 +779,20 @@ vsi_l_offset GTM::findFirstTrackOffset()
     }
     /* First track offset is the first trackpoint offset plus number of
        trackpoints time size of a trackpoint*/
-    return (vsi_l_offset) (firstTrackpointOffset + ntcks * 25);
+    return firstTrackpointOffset + static_cast<vsi_l_offset>(ntcks) * 25;
 }
 
-bool GTM::readTrackPoints(double& latitude, double& longitude, GIntBig& datetime,
-                          unsigned char& start, float& altitude) {
+bool GTM::readTrackPoints( double& latitude, double& longitude,
+                           GIntBig& datetime,
+                           unsigned char& start, float& altitude)
+{
     /* Point to the actual trackpoint offset */
     if ( VSIFSeekL(pGTMFile, actualTrackpointOffset, SEEK_SET) != 0)
-        return FALSE;
+        return false;
 
     /* Read latitude */
     latitude = readDouble(pGTMFile);
-  
+
     /* Read longitude */
     longitude = readDouble(pGTMFile);
 
@@ -809,11 +800,11 @@ bool GTM::readTrackPoints(double& latitude, double& longitude, GIntBig& datetime
     datetime = readInt(pGTMFile);
     if (datetime != 0)
         datetime += GTM_EPOCH;
-    
+
     /* Read start flag */
     if ( !readFile( &start, 1, 1 ) )
-        return FALSE;
-        
+        return false;
+
     /* Read altitude */
     altitude = readFloat(pGTMFile);
 
@@ -822,20 +813,19 @@ bool GTM::readTrackPoints(double& latitude, double& longitude, GIntBig& datetime
     {
         actualTrackpointOffset += 8 + 8 + 4 + 1 + 4;
     }
-    return TRUE;
+    return true;
 }
 
 bool GTM::readFile(void* pBuffer, size_t nSize, size_t nCount)
 {
-    size_t nRead;
-    nRead = VSIFReadL( pBuffer, nSize, nCount, pGTMFile );
-    if (nRead <= 0)
+    const size_t nRead = VSIFReadL( pBuffer, nSize, nCount, pGTMFile );
+    if (nRead == 0)
     {
         VSIFCloseL( pGTMFile );
         pGTMFile = NULL;
-        return FALSE;
+        return false;
     }
-    return TRUE;
+    return true;
 }
 
 
diff --git a/ogr/ogrsf_frmts/gtm/gtm.h b/ogr/ogrsf_frmts/gtm/gtm.h
index f8b57aa..662459f 100644
--- a/ogr/ogrsf_frmts/gtm/gtm.h
+++ b/ogr/ogrsf_frmts/gtm/gtm.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gtm.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: gtm.h 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  GTM Driver
  * Purpose:  Class for reading, parsing and handling a gtm file.
@@ -64,9 +64,8 @@
 
 /* GTM_EPOCH is defined as the unix time for the 31 dec 1989 00:00:00 */
 #define GTM_EPOCH 631065600
-    
-#endif
 
+#endif
 
 void appendDouble(void* pBuffer, double val);
 void appendFloat(void* pBuffer, float val);
@@ -90,16 +89,15 @@ public:
              const char* name,
              const char* comment,
              int icon,
-             GIntBig wptdate
-             );
+             GIntBig wptdate );
     ~Waypoint();
-    double getLatitude();
-    double getLongitude();
-    double getAltitude();
-    const char* getName();
-    const char* getComment();
-    int getIcon();
-    GIntBig getDate(); /* 0 if invalid */
+    double getLatitude() const;
+    double getLongitude() const;
+    double getAltitude() const;
+    const char* getName() const;
+    const char* getComment() const;
+    int getIcon() const;
+    GIntBig getDate() const; /* 0 if invalid */
 private:
     double latitude;
     double longitude;
@@ -125,16 +123,16 @@ public:
           unsigned char type,
           int color);
     ~Track();
-  
-    const char* getName();
-    unsigned char getType();
-    int getColor();
 
-    void addPoint(double x, double y, GIntBig datetime, double altitude);  
-    int getNumPoints();
-    const TrackPoint* getPoint(int pointNum);
+    const char* getName() const;
+    unsigned char getType() const;
+    int getColor() const;
 
-private: 
+    void addPoint(double x, double y, GIntBig datetime, double altitude);
+    int getNumPoints() const;
+    const TrackPoint* getPoint(int pointNum) const;
+
+private:
     char* pszName;
     unsigned char type;
     int color;
@@ -152,18 +150,18 @@ public:
     bool Open(const char* pszFilename);
 
 
-    // Check wheater it is a valid GTM file or not
+    // Check whether it is a valid GTM file or not.
     bool isValid();
     bool readHeaderNumbers();
 
     // Waypoint control functions
     Waypoint* fetchNextWaypoint();
-    int getNWpts();
-    bool hasNextWaypoint();
+    int getNWpts() const;
+    bool hasNextWaypoint() const;
     void rewindWaypoint();
 
-    int getNTracks();
-    bool hasNextTrack();
+    int getNTracks() const;
+    bool hasNextTrack() const;
     void rewindTrack();
     Track* fetchNextTrack();
 
diff --git a/ogr/ogrsf_frmts/gtm/gtmtracklayer.cpp b/ogr/ogrsf_frmts/gtm/gtmtracklayer.cpp
index 8d9a4f0..d906e51 100644
--- a/ogr/ogrsf_frmts/gtm/gtmtracklayer.cpp
+++ b/ogr/ogrsf_frmts/gtm/gtmtracklayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gtmtracklayer.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: gtmtracklayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  GTM Driver
  * Purpose:  Implementation of GTMTrackLayer class.
@@ -30,9 +30,9 @@
 #include "ogr_gtm.h"
 
 
-GTMTrackLayer::GTMTrackLayer( const char* pszName,
-                              OGRSpatialReference* poSRSIn,
-                              CPL_UNUSED int bWriterIn,
+GTMTrackLayer::GTMTrackLayer( const char* pszNameIn,
+                              OGRSpatialReference *poSRSIn,
+                              int /* bWriterIn */,
                               OGRGTMDataSource* poDSIn )
 {
     poCT = NULL;
@@ -41,7 +41,7 @@ GTMTrackLayer::GTMTrackLayer( const char* pszName,
        formats. */
     if( poSRSIn != NULL )
     {
-        poSRS = new OGRSpatialReference(NULL);   
+        poSRS = new OGRSpatialReference(NULL);
         poSRS->SetWellKnownGeogCS( "WGS84" );
         if (!poSRS->IsSame(poSRSIn))
         {
@@ -55,16 +55,19 @@ GTMTrackLayer::GTMTrackLayer( const char* pszName,
                 poSRSIn->exportToPrettyWkt( &pszWKT, FALSE );
 
                 CPLError( CE_Warning, CPLE_AppDefined,
-                          "Failed to create coordinate transformation between the\n"
-                          "input coordinate system and WGS84.  This may be because they\n"
-                          "are not transformable, or because projection services\n"
-                          "(PROJ.4 DLL/.so) could not be loaded.\n" 
+                          "Failed to create coordinate transformation between "
+                          "the\n"
+                          "input coordinate system and WGS84.  This may be "
+                          "because they\n"
+                          "are not transformable, or because projection "
+                          "services\n"
+                          "(PROJ.4 DLL/.so) could not be loaded.\n"
                           "This message will not be issued any more. \n"
-                          "\nSource:\n%s\n", 
+                          "\nSource:\n%s",
                           pszWKT );
 
                 CPLFree( pszWKT );
-                poDSIn->issuedFirstCTError(); 
+                poDSIn->issuedFirstCTError();
             }
         }
     }
@@ -78,6 +81,8 @@ GTMTrackLayer::GTMTrackLayer( const char* pszName,
     nNextFID = 0;
     nTotalFCount = poDS->getNTracks();
 
+    pszName = CPLStrdup(pszNameIn);
+
     poFeatureDefn = new OGRFeatureDefn( pszName );
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
@@ -95,14 +100,13 @@ GTMTrackLayer::GTMTrackLayer( const char* pszName,
 
     OGRFieldDefn oFieldColor( "color", OFTInteger );
     poFeatureDefn->AddFieldDefn( &oFieldColor );
-  
-    this->pszName = CPLStrdup(pszName);
+
 }
 
 GTMTrackLayer::~GTMTrackLayer()
 {
-    /* poDS, poSRS, poCT, pszName, and poFeatureDefn are released on
-       parent class*/
+    /* poDS, poSRS, poCT, pszName, and poFeatureDefn are released in
+       parent class */
 }
 
 
@@ -111,7 +115,6 @@ GTMTrackLayer::~GTMTrackLayer()
 /************************************************************************/
 void GTMTrackLayer::WriteFeatureAttributes( OGRFeature *poFeature )
 {
-    void* pBuffer = NULL;
     char* psztrackname = NULL;
     int type = 1;
     unsigned int color = 0;
@@ -120,14 +123,15 @@ void GTMTrackLayer::WriteFeatureAttributes( OGRFeature *poFeature )
         OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( i );
         if( poFeature->IsFieldSet( i ) )
         {
-            const char* pszName = poFieldDefn->GetNameRef();
+            const char* l_pszName = poFieldDefn->GetNameRef();
             /* track name */
-            if (strncmp(pszName, "name", 4) == 0)
+            if (STARTS_WITH(l_pszName, "name"))
             {
+                CPLFree(psztrackname);
                 psztrackname = CPLStrdup( poFeature->GetFieldAsString( i ) );
             }
             /* track type */
-            else if (strncmp(pszName, "type", 4) == 0)
+            else if (STARTS_WITH(l_pszName, "type"))
             {
                 type = poFeature->GetFieldAsInteger( i );
                 // Check if it is a valid type
@@ -135,7 +139,7 @@ void GTMTrackLayer::WriteFeatureAttributes( OGRFeature *poFeature )
                     type = 1;
             }
             /* track color */
-            else if (strncmp(pszName, "color", 5) == 0)
+            else if (STARTS_WITH(l_pszName, "color"))
             {
                 color = (unsigned int) poFeature->GetFieldAsInteger( i );
                 if (color > 0xFFFFFF)
@@ -147,12 +151,10 @@ void GTMTrackLayer::WriteFeatureAttributes( OGRFeature *poFeature )
     if (psztrackname == NULL)
         psztrackname = CPLStrdup( "" );
 
-    int trackNameLength = 0;
-    if (psztrackname != NULL)
-        trackNameLength = strlen(psztrackname);
+    const size_t trackNameLength = strlen(psztrackname);
 
-    int bufferSize = 14 + trackNameLength;
-    pBuffer = CPLMalloc(bufferSize);
+    const size_t bufferSize = 14 + trackNameLength;
+    void* pBuffer = CPLMalloc(bufferSize);
     void* pBufferAux = pBuffer;
     /* Write track string name size to buffer */
     appendUShort(pBufferAux, (unsigned short) trackNameLength);
@@ -165,11 +167,11 @@ void GTMTrackLayer::WriteFeatureAttributes( OGRFeature *poFeature )
     /* Write track type */
     appendUChar(pBufferAux, (unsigned char) type);
     pBufferAux = (char*)pBufferAux + 1;
-  
+
     /* Write track color */
     appendInt(pBufferAux, color);
     pBufferAux = (char*)pBufferAux + 4;
-  
+
     /* Write track scale */
     appendFloat(pBufferAux, 0);
     pBufferAux = (char*)pBufferAux + 4;
@@ -184,31 +186,31 @@ void GTMTrackLayer::WriteFeatureAttributes( OGRFeature *poFeature )
     VSIFWriteL(pBuffer, bufferSize, 1, poDS->getTmpTracksFP());
     poDS->incNumTracks();
 
-    if (psztrackname != NULL)
-        CPLFree(psztrackname);
+    CPLFree(psztrackname);
     CPLFree(pBuffer);
 }
 
 /************************************************************************/
 /*                          WriteTrackpoint()                           */
 /************************************************************************/
-inline void GTMTrackLayer::WriteTrackpoint( double lat, double lon, float altitude, bool start )
+inline void GTMTrackLayer::WriteTrackpoint( double lat, double lon,
+                                            float altitude, bool start )
 {
     void* pBuffer = CPLMalloc(25);
     void* pBufferAux = pBuffer;
-    //latitude
+    // latitude
     appendDouble(pBufferAux, lat);
-    pBufferAux = (char*)pBufferAux + 8; 
-    //longitude
+    pBufferAux = (char*)pBufferAux + 8;
+    // longitude
     appendDouble(pBufferAux, lon);
-    pBufferAux = (char*)pBufferAux + 8; 
-    //date
+    pBufferAux = (char*)pBufferAux + 8;
+    // date
     appendInt(pBufferAux, 0);
-    pBufferAux = (char*)pBufferAux + 4; 
-    //start
-    appendUChar(pBufferAux, start);
-    pBufferAux = (char*)pBufferAux + 1; 
-    //altitude
+    pBufferAux = (char*)pBufferAux + 4;
+    // start
+    appendUChar(pBufferAux, static_cast<int>(start));
+    pBufferAux = (char*)pBufferAux + 1;
+    // altitude
     appendFloat(pBufferAux, altitude);
     VSIFWriteL(pBuffer, 25, 1, poDS->getTmpTrackpointsFP());
     poDS->incNumTrackpoints();
@@ -223,33 +225,34 @@ OGRErr GTMTrackLayer::ICreateFeature (OGRFeature *poFeature)
 {
     VSILFILE* fpTmpTrackpoints = poDS->getTmpTrackpointsFP();
     if (fpTmpTrackpoints == NULL)
-        return CE_Failure;
+        return OGRERR_FAILURE;
 
     VSILFILE* fpTmpTracks = poDS->getTmpTracksFP();
     if (fpTmpTracks == NULL)
-        return CE_Failure;
+        return OGRERR_FAILURE;
 
     OGRGeometry *poGeom = poFeature->GetGeometryRef();
     if ( poGeom == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Features without geometry not supported by GTM writer in track layer." );
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Features without geometry not supported by GTM writer in "
+                  "track layer." );
         return OGRERR_FAILURE;
     }
-   
+
     if (NULL != poCT)
     {
         poGeom = poGeom->clone();
         poGeom->transform( poCT );
     }
-    
+
     switch( poGeom->getGeometryType() )
     {
     case wkbLineString:
     case wkbLineString25D:
     {
         WriteFeatureAttributes(poFeature);
-        OGRLineString* line = (OGRLineString*)poGeom;
+        OGRLineString* line = reinterpret_cast<OGRLineString *>(poGeom);
         for(int i = 0; i < line->getNumPoints(); ++i)
         {
             double lat = line->getY(i);
@@ -258,7 +261,7 @@ OGRErr GTMTrackLayer::ICreateFeature (OGRFeature *poFeature)
             CheckAndFixCoordinatesValidity(lat, lon);
             poDS->checkBounds((float)lat, (float)lon);
             if (line->getGeometryType() == wkbLineString25D)
-	      altitude = (float)line->getZ(i);
+                altitude = static_cast<float>(line->getZ(i));
             WriteTrackpoint( lat, lon, altitude, i==0 );
         }
         break;
@@ -280,13 +283,13 @@ OGRErr GTMTrackLayer::ICreateFeature (OGRFeature *poFeature)
                 float altitude = 0;
                 CheckAndFixCoordinatesValidity(lat, lon);
                 if (line->getGeometryType() == wkbLineString25D)
-		  altitude = (float) line->getZ(i);
+                    altitude = static_cast<float>(line->getZ(i));
                 WriteTrackpoint( lat, lon, altitude, i==0 );
             }
         }
         break;
     }
-    
+
     default:
     {
         CPLError( CE_Failure, CPLE_NotSupported,
@@ -297,7 +300,7 @@ OGRErr GTMTrackLayer::ICreateFeature (OGRFeature *poFeature)
         return OGRERR_FAILURE;
     }
     }
-    
+
     if (NULL != poCT)
         delete poGeom;
 
@@ -307,9 +310,9 @@ OGRErr GTMTrackLayer::ICreateFeature (OGRFeature *poFeature)
 
 OGRFeature* GTMTrackLayer::GetNextFeature()
 {
-    if (bError)
+    if( bError )
         return NULL;
-        
+
     while (poDS->hasNextTrack())
     {
         Track* poTrack = poDS->fetchNextTrack();
@@ -317,16 +320,16 @@ OGRFeature* GTMTrackLayer::GetNextFeature()
         {
             CPLError(CE_Failure, CPLE_AppDefined,
                      "Could not read track. File probably corrupted");
-            bError = TRUE;
+            bError = true;
             return NULL;
         }
         OGRFeature* poFeature = new OGRFeature( poFeatureDefn );
         OGRLineString* lineString = new OGRLineString ();
-    
+
         for (int i = 0; i < poTrack->getNumPoints(); ++i)
         {
             const TrackPoint* psTrackPoint = poTrack->getPoint(i);
-            lineString->addPoint(psTrackPoint->x, 
+            lineString->addPoint(psTrackPoint->x,
                                  psTrackPoint->y);
         }
         if (poSRS)
@@ -353,7 +356,7 @@ GIntBig GTMTrackLayer::GetFeatureCount(int bForce)
 {
     if (m_poFilterGeom == NULL && m_poAttrQuery == NULL)
         return poDS->getNTracks();
-        
+
     return OGRLayer::GetFeatureCount(bForce);
 }
 
diff --git a/ogr/ogrsf_frmts/gtm/gtmwaypointlayer.cpp b/ogr/ogrsf_frmts/gtm/gtmwaypointlayer.cpp
index 1966d3c..df82b7d 100644
--- a/ogr/ogrsf_frmts/gtm/gtmwaypointlayer.cpp
+++ b/ogr/ogrsf_frmts/gtm/gtmwaypointlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gtmwaypointlayer.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: gtmwaypointlayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  GTM Driver
  * Purpose:  Implementation of gtmwaypoint class.
@@ -31,7 +31,7 @@
 #include "ogr_gtm.h"
 #include "cpl_time.h"
 
-GTMWaypointLayer::GTMWaypointLayer( const char* pszName,
+GTMWaypointLayer::GTMWaypointLayer( const char* pszNameIn,
                                     OGRSpatialReference* poSRSIn,
                                     CPL_UNUSED int bWriterIn,
                                     OGRGTMDataSource* poDSIn )
@@ -42,7 +42,7 @@ GTMWaypointLayer::GTMWaypointLayer( const char* pszName,
        formats. */
     if( poSRSIn != NULL )
     {
-        poSRS = new OGRSpatialReference(NULL);   
+        poSRS = new OGRSpatialReference(NULL);
         poSRS->SetWellKnownGeogCS( "WGS84" );
         if (!poSRS->IsSame(poSRSIn))
         {
@@ -59,13 +59,13 @@ GTMWaypointLayer::GTMWaypointLayer( const char* pszName,
                           "Failed to create coordinate transformation between the\n"
                           "input coordinate system and WGS84.  This may be because they\n"
                           "are not transformable, or because projection services\n"
-                          "(PROJ.4 DLL/.so) could not be loaded.\n" 
+                          "(PROJ.4 DLL/.so) could not be loaded.\n"
                           "This message will not be issued any more. \n"
-                          "\nSource:\n%s\n", 
+                          "\nSource:\n%s\n",
                           pszWKT );
 
                 CPLFree( pszWKT );
-                poDSIn->issuedFirstCTError(); 
+                poDSIn->issuedFirstCTError();
             }
         }
     }
@@ -79,6 +79,8 @@ GTMWaypointLayer::GTMWaypointLayer( const char* pszName,
     nNextFID = 0;
     nTotalFCount = poDS->getNWpts();
 
+    this->pszName = CPLStrdup(pszNameIn);
+
     poFeatureDefn = new OGRFeatureDefn( pszName );
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
@@ -95,16 +97,14 @@ GTMWaypointLayer::GTMWaypointLayer( const char* pszName,
 
     OGRFieldDefn oFieldIcon( "icon", OFTInteger );
     poFeatureDefn->AddFieldDefn( &oFieldIcon );
-  
+
     OGRFieldDefn oFieldTime( "time", OFTDateTime );
     poFeatureDefn->AddFieldDefn( &oFieldTime );
-    
-    this->pszName = CPLStrdup(pszName);
 }
 
 GTMWaypointLayer::~GTMWaypointLayer()
 {
-  
+
 }
 
 
@@ -113,8 +113,6 @@ GTMWaypointLayer::~GTMWaypointLayer()
 /************************************************************************/
 void GTMWaypointLayer::WriteFeatureAttributes( OGRFeature *poFeature, float altitude )
 {
-    void* pBuffer = NULL;
-    void* pBufferAux = NULL;
     char psNameField[] = "          ";
     char* pszcomment = NULL;
     int icon = 48;
@@ -124,20 +122,21 @@ void GTMWaypointLayer::WriteFeatureAttributes( OGRFeature *poFeature, float alti
         OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( i );
         if( poFeature->IsFieldSet( i ) )
         {
-            const char* pszName = poFieldDefn->GetNameRef();
+            const char* l_pszName = poFieldDefn->GetNameRef();
             /* Waypoint name */
-            if (strncmp(pszName, "name", 4) == 0)
+            if (STARTS_WITH(l_pszName, "name"))
             {
                 strncpy (psNameField, poFeature->GetFieldAsString( i ), 10);
                 CPLStrlcat (psNameField, "          ", sizeof(psNameField));
             }
             /* Waypoint comment */
-            else if (strncmp(pszName, "comment", 7) == 0)
+            else if (STARTS_WITH(l_pszName, "comment"))
             {
+                CPLFree(pszcomment);
                 pszcomment = CPLStrdup( poFeature->GetFieldAsString( i ) );
             }
             /* Waypoint icon */
-            else if (strncmp(pszName, "icon", 4) == 0)
+            else if (STARTS_WITH(l_pszName, "icon"))
             {
                 icon = poFeature->GetFieldAsInteger( i );
                 // Check if it is a valid icon
@@ -145,7 +144,7 @@ void GTMWaypointLayer::WriteFeatureAttributes( OGRFeature *poFeature, float alti
                     icon = 48;
             }
             /* Waypoint date */
-            else if (EQUAL(pszName, "time"))
+            else if (EQUAL(l_pszName, "time"))
             {
                 struct tm brokendowndate;
                 int year, month, day, hour, min, sec, TZFlag;
@@ -178,13 +177,11 @@ void GTMWaypointLayer::WriteFeatureAttributes( OGRFeature *poFeature, float alti
     if (pszcomment == NULL)
         pszcomment = CPLStrdup( "" );
 
-    int commentLength = 0;
-    if (pszcomment != NULL)
-        commentLength = strlen(pszcomment);
+    const size_t commentLength = strlen(pszcomment);
 
-    int bufferSize = 27 + commentLength;
-    pBuffer = CPLMalloc(bufferSize);
-    pBufferAux = pBuffer;
+    const size_t bufferSize = 27 + commentLength;
+    void* pBuffer = CPLMalloc(bufferSize);
+    void* pBufferAux = pBuffer;
     /* Write waypoint name to buffer */
     strncpy((char*)pBufferAux, psNameField, 10);
 
@@ -222,8 +219,7 @@ void GTMWaypointLayer::WriteFeatureAttributes( OGRFeature *poFeature, float alti
     VSIFWriteL(pBuffer, bufferSize, 1, poDS->getOutputFP());
     poDS->incNumWaypoints();
 
-    if (pszcomment != NULL)
-        CPLFree(pszcomment);
+    CPLFree(pszcomment);
     CPLFree(pBuffer);
 }
 
@@ -234,16 +230,16 @@ OGRErr GTMWaypointLayer::ICreateFeature (OGRFeature *poFeature)
 {
     VSILFILE* fp = poDS->getOutputFP();
     if (fp == NULL)
-        return CE_Failure;
+        return OGRERR_FAILURE;
 
     OGRGeometry *poGeom = poFeature->GetGeometryRef();
     if ( poGeom == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Features without geometry not supported by GTM writer in waypoints layer." );
         return OGRERR_FAILURE;
     }
-    
+
     if (NULL != poCT)
     {
         poGeom = poGeom->clone();
@@ -270,7 +266,7 @@ OGRErr GTMWaypointLayer::ICreateFeature (OGRFeature *poFeature)
         WriteFeatureAttributes(poFeature, altitude);
         break;
     }
-            
+
     default:
     {
         CPLError( CE_Failure, CPLE_NotSupported,
@@ -279,10 +275,10 @@ OGRErr GTMWaypointLayer::ICreateFeature (OGRFeature *poFeature)
         return OGRERR_FAILURE;
     }
     }
-    
+
     if (NULL != poCT)
         delete poGeom;
-        
+
     return OGRERR_NONE;
 
 }
@@ -306,21 +302,21 @@ OGRFeature* GTMWaypointLayer::GetNextFeature()
         OGRFeature* poFeature = new OGRFeature( poFeatureDefn );
         double altitude = poWaypoint->getAltitude();
         if (altitude == 0.0)
-            poFeature->SetGeometryDirectly(new OGRPoint 
+            poFeature->SetGeometryDirectly(new OGRPoint
                                            (poWaypoint->getLongitude(),
                                             poWaypoint->getLatitude()));
         else
-            poFeature->SetGeometryDirectly(new OGRPoint 
+            poFeature->SetGeometryDirectly(new OGRPoint
                                            (poWaypoint->getLongitude(),
                                             poWaypoint->getLatitude(),
                                             altitude));
-                                            
+
         if (poSRS)
             poFeature->GetGeometryRef()->assignSpatialReference(poSRS);
         poFeature->SetField( NAME, poWaypoint->getName());
         poFeature->SetField( COMMENT, poWaypoint->getComment());
         poFeature->SetField( ICON, poWaypoint->getIcon());
-        
+
         GIntBig wptdate = poWaypoint->getDate();
         if (wptdate != 0)
         {
@@ -332,9 +328,9 @@ OGRFeature* GTMWaypointLayer::GetNextFeature()
                                  brokendownTime.tm_mday,
                                  brokendownTime.tm_hour,
                                  brokendownTime.tm_min,
-                                 brokendownTime.tm_sec);
+                                 static_cast<float>(brokendownTime.tm_sec));
         }
-        
+
         poFeature->SetFID( nNextFID++ );
         delete poWaypoint;
         if( (m_poFilterGeom == NULL
@@ -352,7 +348,7 @@ GIntBig GTMWaypointLayer::GetFeatureCount(int bForce)
 {
     if (m_poFilterGeom == NULL && m_poAttrQuery == NULL)
         return poDS->getNWpts();
-        
+
     return OGRLayer::GetFeatureCount(bForce);
 }
 
diff --git a/ogr/ogrsf_frmts/gtm/ogr_gtm.h b/ogr/ogrsf_frmts/gtm/ogr_gtm.h
index aac5796..cc5c84f 100644
--- a/ogr/ogrsf_frmts/gtm/ogr_gtm.h
+++ b/ogr/ogrsf_frmts/gtm/ogr_gtm.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_gtm.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogr_gtm.h 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  GTM Driver
  * Purpose:  Declarations for OGR wrapper classes for GTM, and OGR->GTM
@@ -97,7 +97,7 @@ public:
     virtual OGRErr ICreateFeature(OGRFeature *poFeature) = 0;
 
     int TestCapability( const char* pszCap );
-    
+
     OGRErr CreateField( OGRFieldDefn *poField, int bApproxOK );
 
 protected:
@@ -109,9 +109,9 @@ protected:
     OGRFeatureDefn* poFeatureDefn;
     int nNextFID;
     int nTotalFCount;
-    
-    int bError;
-    
+
+    bool bError;
+
     static OGRErr CheckAndFixCoordinatesValidity( double& pdfLatitude, double& pdfLongitude );
 
 };
@@ -181,9 +181,9 @@ public:
 
     OGRLayer* GetLayer( int );
 
-    OGRLayer* ICreateLayer(const char *pszName, 
-                           OGRSpatialReference *poSpatialRef=NULL, 
-                           OGRwkbGeometryType eGType=wkbUnknown, 
+    OGRLayer* ICreateLayer(const char *pszName,
+                           OGRSpatialReference *poSpatialRef=NULL,
+                           OGRwkbGeometryType eGType=wkbUnknown,
                            char **papszOptions=NULL);
     int TestCapability( const char * );
 
@@ -199,7 +199,7 @@ public:
     bool hasNextWaypoint();
     Waypoint* fetchNextWaypoint();
     void rewindWaypoint();
-  
+
     /* Functions to handle with tracks */
     int getNTracks();
     bool hasNextTrack();
@@ -215,21 +215,21 @@ public:
 
     void checkBounds(float newLat,
                      float newLon);
-    int getNumWaypoints() { return numWaypoints; } 
+    int getNumWaypoints() { return numWaypoints; }
     int getNumTrackpoints() { return numTrackpoints; }
     int getTracks() { return numTracks; };
 
-    int incNumWaypoints() { return ++numWaypoints; } 
+    int incNumWaypoints() { return ++numWaypoints; }
     int incNumTrackpoints() { return ++numTrackpoints; }
     int incNumTracks() { return ++numTracks; };
 private:
     VSILFILE* fpOutput;
-  
+
     /* GTM is not a contiguous file. We need two temporary files because
        trackpoints and tracks are stored separated and we don't know in
        advance how many trackpoints and tracks the new file will
-       have. So, we create temporary file and append the at the end of
-       the gtm file whe everything is done, that is, in the
+       have. So, we create temporary file and append at the end of
+       the gtm file when everything is done, that is, in the
        destructor. */
     VSILFILE* fpTmpTrackpoints;
     char* pszTmpTrackpoints;
@@ -239,10 +239,10 @@ private:
 
     GTM* poGTMFile;
     char* pszName;
-  
+
     OGRGTMLayer **papoLayers;
     int nLayers;
-  
+
     bool bIssuedCTError;
 
     /* Used for creating a new file */
diff --git a/ogr/ogrsf_frmts/gtm/ogrgtmdatasource.cpp b/ogr/ogrsf_frmts/gtm/ogrgtmdatasource.cpp
index 2ba2e45..67d17f6 100644
--- a/ogr/ogrsf_frmts/gtm/ogrgtmdatasource.cpp
+++ b/ogr/ogrsf_frmts/gtm/ogrgtmdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgtmdatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogrgtmdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  GTM Driver
  * Purpose:  Implementation of OGRGTMDataSource class.
@@ -33,29 +33,25 @@
 /*                         OGRGTMDataSource()                           */
 /************************************************************************/
 
-OGRGTMDataSource::OGRGTMDataSource()
-{
-    pszName = NULL;
-    papoLayers = NULL;
-    nLayers = 0;
-    bIssuedCTError = FALSE;
-    poGTMFile = NULL;
-    fpOutput = NULL;
-    fpTmpTrackpoints = NULL;
-    pszTmpTrackpoints = NULL;
-    fpTmpTracks = NULL;
-    pszTmpTracks = NULL;
-
-    minlat = 0;
-    maxlat = 0;
-    minlon = 0;
-    maxlon = 0;
-
-    numWaypoints = 0;
-    numTracks = 0;
-    numTrackpoints = 0;
-
-}
+OGRGTMDataSource::OGRGTMDataSource() :
+    fpOutput(NULL),
+    fpTmpTrackpoints(NULL),
+    pszTmpTrackpoints(NULL),
+    fpTmpTracks(NULL),
+    pszTmpTracks(NULL),
+    poGTMFile(NULL),
+    pszName(NULL),
+    papoLayers(NULL),
+    nLayers(0),
+    bIssuedCTError(false),
+    minlat(0),
+    maxlat(0),
+    minlon(0),
+    maxlon(0),
+    numWaypoints(0),
+    numTracks(0),
+    numTrackpoints(0)
+{}
 
 /************************************************************************/
 /*                       AppendTemporaryFiles()                         */
@@ -65,38 +61,37 @@ void OGRGTMDataSource::AppendTemporaryFiles()
     if( fpOutput == NULL )
         return;
 
-    if (numTrackpoints != 0 || numTracks != 0)
+    if (numTrackpoints == 0 && numTracks == 0)
+        return;
+
+    void* pBuffer = CPLMalloc(2048);
+
+    // Append Trackpoints to the output file
+    fpTmpTrackpoints = VSIFOpenL( pszTmpTrackpoints, "r" );
+    if (fpTmpTrackpoints != NULL)
     {
-        void* pBuffer = CPLMalloc(2048);
-        size_t bytes;
-
-        // Append Trackpoints to the output file
-        fpTmpTrackpoints = VSIFOpenL( pszTmpTrackpoints, "r" );
-        if (fpTmpTrackpoints != NULL)
-        { 
-            while ( !VSIFEofL(fpTmpTrackpoints) )
-            {
-                bytes = VSIFReadL(pBuffer, 1, 2048, fpTmpTrackpoints);
-                VSIFWriteL(pBuffer, bytes, 1, fpOutput);
-            }
-            VSIFCloseL( fpTmpTrackpoints );
-            fpTmpTrackpoints = NULL;
+        while ( !VSIFEofL(fpTmpTrackpoints) )
+        {
+            const size_t bytes = VSIFReadL(pBuffer, 1, 2048, fpTmpTrackpoints);
+            VSIFWriteL(pBuffer, bytes, 1, fpOutput);
         }
+        VSIFCloseL( fpTmpTrackpoints );
+        fpTmpTrackpoints = NULL;
+    }
 
-        // Append Tracks to the output file
-        fpTmpTracks = VSIFOpenL( pszTmpTracks, "r" );
-        if (fpTmpTracks != NULL)
+    // Append Tracks to the output file
+    fpTmpTracks = VSIFOpenL( pszTmpTracks, "r" );
+    if (fpTmpTracks != NULL)
+    {
+        while ( !VSIFEofL(fpTmpTracks) )
         {
-            while ( !VSIFEofL(fpTmpTracks) )
-            {
-                bytes = VSIFReadL(pBuffer, 1, 2048, fpTmpTracks);
-                VSIFWriteL(pBuffer, bytes, 1, fpOutput);
-            }
-            VSIFCloseL( fpTmpTracks );
-            fpTmpTracks = NULL;
+            const size_t bytes = VSIFReadL(pBuffer, 1, 2048, fpTmpTracks);
+            VSIFWriteL(pBuffer, bytes, 1, fpOutput);
         }
-        CPLFree(pBuffer);
+        VSIFCloseL( fpTmpTracks );
+        fpTmpTracks = NULL;
     }
+    CPLFree(pBuffer);
 }
 
 /************************************************************************/
@@ -119,10 +114,10 @@ void OGRGTMDataSource::WriteWaypointStyles()
                 pBufferAux = ((char*)pBufferAux) + 4;
                 // facename size
                 appendUShort(pBufferAux, 5);
-                pBufferAux = ((char*)pBufferAux) + 2; 
+                pBufferAux = ((char*)pBufferAux) + 2;
                 // facename
                 strncpy((char*)pBufferAux, "Arial", 5);
-                pBufferAux = ((char*)pBufferAux) + 5; 
+                pBufferAux = ((char*)pBufferAux) + 5;
                 // dspl
                 appendUChar(pBufferAux, (unsigned char) i);
                 pBufferAux = ((char*)pBufferAux) + 1;
@@ -140,7 +135,7 @@ void OGRGTMDataSource::WriteWaypointStyles()
                 pBufferAux = ((char*)pBufferAux) + 1;
                 // background
                 appendUShort(pBufferAux, (i != 3) ? 0 : 0xFF);
-                pBufferAux = ((char*)pBufferAux) + 2; 
+                pBufferAux = ((char*)pBufferAux) + 2;
                 // backcolor
                 appendInt(pBufferAux, (i != 3) ? 0 : 0xFFFF);
                 pBufferAux = ((char*)pBufferAux) + 4;
@@ -166,15 +161,15 @@ OGRGTMDataSource::~OGRGTMDataSource()
 {
     if (fpTmpTrackpoints != NULL)
         VSIFCloseL( fpTmpTrackpoints );
-       
+
     if (fpTmpTracks != NULL)
         VSIFCloseL( fpTmpTracks );
-       
+
     WriteWaypointStyles();
-    AppendTemporaryFiles();  
-  
+    AppendTemporaryFiles();
+
     if( fpOutput != NULL )
-    { 
+    {
         /* Adjust header counters */
         VSIFSeekL(fpOutput, NWPTS_OFFSET, SEEK_SET);
         writeInt(fpOutput, numWaypoints);
@@ -192,17 +187,12 @@ OGRGTMDataSource::~OGRGTMDataSource()
         VSIFCloseL( fpOutput );
     }
 
- 
-    if (papoLayers != NULL)
-    {
-        for( int i = 0; i < nLayers; i++ )
-            delete papoLayers[i];
-        CPLFree( papoLayers );
-    }
+    for( int i = 0; i < nLayers; i++ )
+        delete papoLayers[i];
+    CPLFree( papoLayers );
+
+    CPLFree( pszName );
 
-    if (pszName != NULL)
-        CPLFree( pszName );
-  
     if (pszTmpTracks != NULL)
     {
         VSIUnlink( pszTmpTracks );
@@ -228,7 +218,7 @@ OGRGTMDataSource::~OGRGTMDataSource()
 int OGRGTMDataSource::Open(const char* pszFilename, int bUpdate)
 {
     CPLAssert( pszFilename != NULL );
-    
+
     /* Should not happen as the driver already returned if bUpdate == NULL */
     if (bUpdate)
     {
@@ -236,7 +226,7 @@ int OGRGTMDataSource::Open(const char* pszFilename, int bUpdate)
                  "GTM driver does not support opening in update mode");
         return FALSE;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create a GTM object and open the source file.                   */
 /* -------------------------------------------------------------------- */
@@ -275,10 +265,9 @@ int OGRGTMDataSource::Open(const char* pszFilename, int bUpdate)
     /* We are going to create two layers, one for storing waypoints and
        another for storing tracks */
     papoLayers = (OGRGTMLayer **) CPLMalloc(sizeof(void*) * 2);
-  
 
     /* Create a spatial reference for WGS8*/
-    OGRSpatialReference* poSRS = new OGRSpatialReference(NULL);   
+    OGRSpatialReference* poSRS = new OGRSpatialReference(NULL);
     poSRS->SetWellKnownGeogCS( "WGS84" );
 
 
@@ -358,8 +347,8 @@ int OGRGTMDataSource::Create( const char* pszFilename,
     fpOutput = VSIFOpenL( pszFilename, "w" );
     if( fpOutput == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Failed to create GTM file %s.", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to create GTM file %s.",
                   pszFilename );
         return FALSE;
     }
@@ -370,8 +359,8 @@ int OGRGTMDataSource::Create( const char* pszFilename,
     fpTmpTrackpoints = VSIFOpenL(pszTmpName , "w" );
     if( fpTmpTrackpoints == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Failed to create temporary file %s.", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to create temporary file %s.",
                   pszTmpName );
         return FALSE;
     }
@@ -381,8 +370,8 @@ int OGRGTMDataSource::Create( const char* pszFilename,
     fpTmpTracks = VSIFOpenL(pszTmpName , "w" );
     if( fpTmpTracks == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Failed to create temporary file %s.", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to create temporary file %s.",
                   pszTmpName );
         return FALSE;
     }
@@ -391,7 +380,7 @@ int OGRGTMDataSource::Create( const char* pszFilename,
 /*     Output header of GTM file.                                       */
 /* -------------------------------------------------------------------- */
     char* pszBaseFileName = CPLStrdup( CPLGetBasename(pszFilename) );
-    int sizeBuffer = 175 + strlen(pszBaseFileName);
+    size_t sizeBuffer = 175 + strlen(pszBaseFileName);
     void* pBuffer = CPLCalloc(1, sizeBuffer);
     void* pCurrentPos = pBuffer;
 
@@ -422,8 +411,8 @@ int OGRGTMDataSource::Create( const char* pszFilename,
     pCurrentPos = ((char*)pCurrentPos) + 2;
     strcpy((char*)pCurrentPos, pszBaseFileName);
 
-    // write ndatum. We are implementing just WGS84, so write the
-    // correspondig value for WGS84
+    // Write ndatum. We are implementing just WGS84, so write the
+    // corresponding value for WGS84.
     pCurrentPos = ((char*) pBuffer) + 151 + strlen(pszBaseFileName);
     appendInt(pCurrentPos, 217);
 
@@ -438,12 +427,13 @@ int OGRGTMDataSource::Create( const char* pszFilename,
 /************************************************************************/
 /*                            GetLayer()                                */
 /************************************************************************/
+
 OGRLayer* OGRGTMDataSource::GetLayer( int iLayer )
 {
     if( iLayer < 0 || iLayer >= nLayers )
         return NULL;
-    else
-        return papoLayers[iLayer];
+
+    return papoLayers[iLayer];
 }
 
 
@@ -465,7 +455,7 @@ OGRLayer * OGRGTMDataSource::ICreateLayer( const char * pszLayerName,
         return papoLayers[nLayers-1];
 
     }
-    else if (eType == wkbLineString || eType == wkbLineString25D || 
+    else if (eType == wkbLineString || eType == wkbLineString25D ||
              eType == wkbMultiLineString || eType == wkbMultiLineString25D)
     {
         // Tracks
@@ -473,7 +463,7 @@ OGRLayer * OGRGTMDataSource::ICreateLayer( const char * pszLayerName,
         papoLayers = (OGRGTMLayer **) CPLRealloc(papoLayers, nLayers * sizeof(OGRGTMLayer*));
         papoLayers[nLayers-1] = new GTMTrackLayer( pszName, poSRS, TRUE, this );
         return papoLayers[nLayers-1];
-    } 
+    }
     else if (eType == wkbUnknown)
     {
         CPLError(CE_Failure, CPLE_NotSupported,
@@ -510,7 +500,7 @@ int OGRGTMDataSource::TestCapability( const char * pszCap )
 void OGRGTMDataSource::checkBounds(float newLat,
                                    float newLon)
 {
-    if (minlat == 0 && maxlat == 0 && 
+    if (minlat == 0 && maxlat == 0 &&
         minlon == 0 && maxlon == 0)
     {
         minlat = newLat;
diff --git a/ogr/ogrsf_frmts/gtm/ogrgtmdriver.cpp b/ogr/ogrsf_frmts/gtm/ogrgtmdriver.cpp
index 5881e5e..35d778f 100644
--- a/ogr/ogrsf_frmts/gtm/ogrgtmdriver.cpp
+++ b/ogr/ogrsf_frmts/gtm/ogrgtmdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgtmdriver.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogrgtmdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  GTM Driver
  * Purpose:  Implementation of OGRGTMDriver class.
@@ -46,7 +46,7 @@ static GDALDataset *OGRGTMDriverOpen( GDALOpenInfo* poOpenInfo )
 /*      try opening with the /vsigzip/ prefix                           */
 /* -------------------------------------------------------------------- */
     if (poOpenInfo->pabyHeader[0] == 0x1f && ((unsigned char*)poOpenInfo->pabyHeader)[1] == 0x8b &&
-        strncmp(poOpenInfo->pszFilename, "/vsigzip/", strlen("/vsigzip/")) != 0)
+        !STARTS_WITH(poOpenInfo->pszFilename, "/vsigzip/"))
     {
         /* ok */
     }
@@ -54,7 +54,7 @@ static GDALDataset *OGRGTMDriverOpen( GDALOpenInfo* poOpenInfo )
     {
         short version = CPL_LSBINT16PTR(poOpenInfo->pabyHeader);
         if (version != 211 ||
-            strncmp((const char*)poOpenInfo->pabyHeader + 2, "TrackMaker", strlen("TrackMaker")) != 0 )
+            !STARTS_WITH((const char*)poOpenInfo->pabyHeader + 2, "TrackMaker") )
         {
             return NULL;
         }
@@ -101,25 +101,20 @@ static GDALDataset *OGRGTMDriverCreate( const char * pszName,
 
 void RegisterOGRGTM()
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "GPSTrackMaker" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "GPSTrackMaker" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-
-        poDriver->SetDescription( "GPSTrackMaker" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "GPSTrackMaker" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "gtm gtz" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_gtm.html" );
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetDescription( "GPSTrackMaker" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "GPSTrackMaker" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "gtm gtz" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_gtm.html" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = OGRGTMDriverOpen;
-        poDriver->pfnCreate = OGRGTMDriverCreate;
+    poDriver->pfnOpen = OGRGTMDriverOpen;
+    poDriver->pfnCreate = OGRGTMDriverCreate;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/gtm/ogrgtmlayer.cpp b/ogr/ogrsf_frmts/gtm/ogrgtmlayer.cpp
index 93f3de1..db43078 100644
--- a/ogr/ogrsf_frmts/gtm/ogrgtmlayer.cpp
+++ b/ogr/ogrsf_frmts/gtm/ogrgtmlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgtmlayer.cpp 27884 2014-10-19 22:27:48Z rouault $
+ * $Id: ogrgtmlayer.cpp 32698 2016-01-03 18:07:36Z goatbar $
  *
  * Project:  GTM Driver
  * Purpose:  Implementation of OGRGTMLayer class.
@@ -29,17 +29,16 @@
 
 #include "ogr_gtm.h"
 
-OGRGTMLayer::OGRGTMLayer()
-{
-    poDS = NULL;
-    poSRS = NULL;
-    poCT = NULL;
-    pszName = NULL;
-    poFeatureDefn = NULL;
-    nNextFID = 0;
-    nTotalFCount = 0;
-    bError = FALSE;
-}
+OGRGTMLayer::OGRGTMLayer() :
+    poDS(NULL),
+    poSRS(NULL),
+    poCT(NULL),
+    pszName(NULL),
+    poFeatureDefn(NULL),
+    nNextFID(0),
+    nTotalFCount(0),
+    bError(false)
+{}
 
 OGRGTMLayer::~OGRGTMLayer()
 {
@@ -77,17 +76,19 @@ OGRFeatureDefn* OGRGTMLayer::GetLayerDefn()
 /*                           TestCapability()                           */
 /************************************************************************/
 
-int OGRGTMLayer::TestCapability( const char * pszCap ) 
+int OGRGTMLayer::TestCapability( const char * pszCap )
 {
     if (EQUAL(pszCap,OLCFastFeatureCount) &&
         m_poFilterGeom == NULL && m_poAttrQuery == NULL )
         return TRUE;
-    else if( EQUAL(pszCap,OLCCreateField) )
+
+    if( EQUAL(pszCap,OLCCreateField) )
         return poDS != NULL && poDS->getOutputFP() != NULL;
-    else if( EQUAL(pszCap,OLCSequentialWrite) )
+
+    if( EQUAL(pszCap,OLCSequentialWrite) )
         return poDS != NULL && poDS->getOutputFP() != NULL;
-    else
-        return FALSE;
+
+    return FALSE;
 }
 
 
@@ -107,7 +108,7 @@ OGRErr OGRGTMLayer::CheckAndFixCoordinatesValidity( double& pdfLatitude, double&
                      pdfLatitude);
             bFirstWarning = FALSE;
         }
-        return CE_Failure;
+        return OGRERR_FAILURE;
     }
 
     if (pdfLongitude < -180 || pdfLongitude > 180)
@@ -126,10 +127,10 @@ OGRErr OGRGTMLayer::CheckAndFixCoordinatesValidity( double& pdfLatitude, double&
         else if (pdfLongitude < -180)
             pdfLongitude += ((int) (180 - pdfLongitude)/360)*360;
 
-        return CE_None;
+        return OGRERR_NONE;
     }
 
-    return CE_None;
+    return OGRERR_NONE;
 }
 
 /************************************************************************/
@@ -137,7 +138,7 @@ OGRErr OGRGTMLayer::CheckAndFixCoordinatesValidity( double& pdfLatitude, double&
 /************************************************************************/
 
 OGRErr OGRGTMLayer::CreateField( OGRFieldDefn *poField,
-                                 CPL_UNUSED int bApproxOK )
+                                 int /* bApproxOK */ )
 {
     for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     {
diff --git a/ogr/ogrsf_frmts/htf/drv_htf.html b/ogr/ogrsf_frmts/htf/drv_htf.html
index 95c5f9a..fd1fea9 100644
--- a/ogr/ogrsf_frmts/htf/drv_htf.html
+++ b/ogr/ogrsf_frmts/htf/drv_htf.html
@@ -9,7 +9,7 @@
 
 (GDAL/OGR >= 1.8.0)<p>
 
-This driver reads files containg sounding data following the Hydrographic Transfer Format (HTF),
+This driver reads files containing sounding data following the Hydrographic Transfer Format (HTF),
 which is used by the Australian Hydrographic Office (AHO).<p>
 
 The driver has been developed based on HTF 2.02 specification.<p>
@@ -29,31 +29,31 @@ The "polygon" layer contains the following fields :
 <li><i>DESCRIPTION</i> : Defines the polygons of each region of similar survey criteria or theme.</li>
 <li><i>IDENTIFIER</i> : Unique polygon identifier for this transmittal.</li>
 <li><i>SEAFLOOR_COVERAGE</i> : All significant seafloor features detected (full ensonification/sweep) or full coverage not achieved and uncharted features may exist.</li>
-<li><i>POSITION_ACCURACY</i> : +/- NNN.n metres at 95% CI (2.45) with respect to the given datum.</li>
-<li><i>DEPTH_ACCURACY</i> : +/- NN.n metres at 95% CI (2.00) at critical depths.</li>
+<li><i>POSITION_ACCURACY</i> : +/- NNN.n meters at 95% CI (2.45) with respect to the given datum.</li>
+<li><i>DEPTH_ACCURACY</i> : +/- NN.n meters at 95% CI (2.00) at critical depths.</li>
 </ul>
 
 The "sounding" layer should contain - at minimum - the following 20 fields :
 <ul>
 <li><i>REJECTED_SOUNDING</i> : if 0 sounding is valid or if 1 the sounding has been rejected (flagged).</li>
-<li><i>LINE_NAME</i> : Survey line name/number as a unique identifer within the survey.</li>
+<li><i>LINE_NAME</i> : Survey line name/number as a unique identifier within the survey.</li>
 <li><i>FIX_NUMBER</i> : Sequential sounding fix number, unique within the survey.</li>
 <li><i>UTC_DATE</i> : UTC date for the sounding CCYYMMDD.</li>
 <li><i>UTC_TIME</i> : UTC time for the sounding HHMMSS.ss.</li>
 <li><i>LATITUDE</i> : Latitude position of the sounding +/-NN.nnnnnn (degrees of arc, south is negative).</li>
 <li><i>LONGITUDE</i> : Longitude position of the sounding +/-NNN.nnnnnn (degrees of arc, west is negative).</li>
-<li><i>EASTING</i> : Grid coordinate position of the sounding in metres NNNNNNN.n.</li>
-<li><i>NORTHING</i> : Grid coordinate position of the sounding in metres NNNNNNN.n.</li>
-<li><i>DEPTH</i> : Reduced sounding value in metres with corrections applied as indicated in the relevant fields, soundings are positive and drying heights are negative +/-NNNN.nn metres.</li>
+<li><i>EASTING</i> : Grid coordinate position of the sounding in meters NNNNNNN.n.</li>
+<li><i>NORTHING</i> : Grid coordinate position of the sounding in meters NNNNNNN.n.</li>
+<li><i>DEPTH</i> : Reduced sounding value in meters with corrections applied as indicated in the relevant fields, soundings are positive and drying heights are negative +/-NNNN.nn meters.</li>
 <li><i>POSITIONING_SENSOR</i> : Indicate position system number populated in the HTF header record.</li>
 <li><i>DEPTH_SENSOR</i> : Indicate depth sounder system number populated in the HTF header record.</li>
 <li><i>TPE_POSITION</i> : Total propagated error of the horizontal component for the sounding.</li>
 <li><i>TPE_DEPTH</i> : Total propagated error of the vertical component for the sounding.</li>
 <li><i>NBA FLAG</i> : No Bottom at Flag, if 0 not NBA depth or if 1 Depth is NBA, deeper water probably exists.</li>
-<li><i>TIDE</i> : Value of the tidal correction applied +/- NN.nn metres.</li>
-<li><i>DEEP_WATER_CORRECTION</i> : Value of the deep water sounding velocity applied +/- NN.nn metres.</li>
-<li><i>VERTICAL BIAS_CORRECTION</i> : Value of the vertical bias applied +/- NN.nn metres. eg transducer depth correction</li>
-<li><i>SOUND_VELOCITY</i> : Measured sound velocity used to process sounding in metres per second IIII.</li>
+<li><i>TIDE</i> : Value of the tidal correction applied +/- NN.nn meters.</li>
+<li><i>DEEP_WATER_CORRECTION</i> : Value of the deep water sounding velocity applied +/- NN.nn meters.</li>
+<li><i>VERTICAL BIAS_CORRECTION</i> : Value of the vertical bias applied +/- NN.nn meters. eg transducer depth correction</li>
+<li><i>SOUND_VELOCITY</i> : Measured sound velocity used to process sounding in meters per second IIII.</li>
 <li><i>PLOTTED_SOUNDING</i> : if 0 then the reduced depth did not appear on the original fairsheet or id 1 then the reduced depth appeared on the original fairsheet.</li>
 </ul>
 
diff --git a/ogr/ogrsf_frmts/htf/ogr_htf.h b/ogr/ogrsf_frmts/htf/ogr_htf.h
index 9f5017b..46fb1f6 100644
--- a/ogr/ogrsf_frmts/htf/ogr_htf.h
+++ b/ogr/ogrsf_frmts/htf/ogr_htf.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_htf.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogr_htf.h 32744 2016-01-04 22:26:42Z goatbar $
  *
  * Project:  HTF Translator
  * Purpose:  Definition of classes for OGR .htf driver.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_HTF_H_INCLUDED
-#define _OGR_HTF_H_INCLUDED
+#ifndef OGR_HTF_H_INCLUDED
+#define OGR_HTF_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 
@@ -45,13 +45,13 @@ protected:
     OGRSpatialReference *poSRS;
 
     VSILFILE*          fpHTF;
-    int                bEOF;
+    bool               bEOF;
 
     int                nNextFID;
 
     virtual OGRFeature *       GetNextRawFeature() = 0;
 
-    int                bHasExtent;
+    bool              bHasExtent;
     double             dfMinX;
     double             dfMinY;
     double             dfMaxX;
@@ -61,7 +61,6 @@ protected:
                         OGRHTFLayer(const char* pszFilename, int nZone, int bIsNorth);
                         ~OGRHTFLayer();
 
-
     virtual void                ResetReading();
     virtual OGRFeature *        GetNextFeature();
 
@@ -70,8 +69,9 @@ protected:
     virtual int                 TestCapability( const char * );
 
     virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
     void    SetExtent(double dfMinX, double dfMinY, double dfMaxX, double dfMaxY);
-
 };
 
 /************************************************************************/
@@ -96,10 +96,11 @@ protected:
 class OGRHTFSoundingLayer : public OGRHTFLayer
 {
 private:
-    int                        bHasFPK;
+    bool                       bHasFPK;
     int                        nFieldsPresent;
-    int                       *panFieldPresence;
-    int                        nEastingIndex, nNorthingIndex;
+    bool                      *panFieldPresence;
+    int                        nEastingIndex;
+    int                        nNorthingIndex;
     int                        nTotalSoundings;
 
 protected:
@@ -133,7 +134,6 @@ protected:
                         OGRHTFMetadataLayer(std::vector<CPLString> aosMD);
                         ~OGRHTFMetadataLayer();
 
-
     virtual void                ResetReading() { nNextFID = 0; }
     virtual OGRFeature *        GetNextFeature();
 
@@ -169,4 +169,4 @@ class OGRHTFDataSource : public OGRDataSource
     virtual int                 TestCapability( const char * );
 };
 
-#endif /* ndef _OGR_HTF_H_INCLUDED */
+#endif /* ndef OGR_HTF_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/htf/ogrhtfdatasource.cpp b/ogr/ogrsf_frmts/htf/ogrhtfdatasource.cpp
index 3aecce3..1b2e374 100644
--- a/ogr/ogrsf_frmts/htf/ogrhtfdatasource.cpp
+++ b/ogr/ogrsf_frmts/htf/ogrhtfdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrhtfdatasource.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: ogrhtfdatasource.cpp 32744 2016-01-04 22:26:42Z goatbar $
  *
  * Project:  HTF Translator
  * Purpose:  Implements OGRHTFDataSource class
@@ -27,25 +27,22 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_htf.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "ogr_htf.h"
 
-CPL_CVSID("$Id: ogrhtfdatasource.cpp 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: ogrhtfdatasource.cpp 32744 2016-01-04 22:26:42Z goatbar $");
 
 /************************************************************************/
 /*                          OGRHTFDataSource()                          */
 /************************************************************************/
 
-OGRHTFDataSource::OGRHTFDataSource()
-
-{
-    papoLayers = NULL;
-    nLayers = 0;
-    poMetadataLayer = NULL;
-
-    pszName = NULL;
-}
+OGRHTFDataSource::OGRHTFDataSource() :
+    pszName(NULL),
+    papoLayers(NULL),
+    nLayers(0),
+    poMetadataLayer(NULL)
+{}
 
 /************************************************************************/
 /*                         ~OGRHTFDataSource()                          */
@@ -66,7 +63,7 @@ OGRHTFDataSource::~OGRHTFDataSource()
 /*                           TestCapability()                           */
 /************************************************************************/
 
-int OGRHTFDataSource::TestCapability( CPL_UNUSED const char * pszCap )
+int OGRHTFDataSource::TestCapability( const char * /* pszCap */ )
 {
     return FALSE;
 }
@@ -80,8 +77,8 @@ OGRLayer *OGRHTFDataSource::GetLayer( int iLayer )
 {
     if( iLayer < 0 || iLayer >= nLayers )
         return NULL;
-    else
-        return papoLayers[iLayer];
+
+    return papoLayers[iLayer];
 }
 
 /************************************************************************/
@@ -110,7 +107,7 @@ int OGRHTFDataSource::Open( const char * pszFilename )
 {
     pszName = CPLStrdup( pszFilename );
 
-// -------------------------------------------------------------------- 
+// --------------------------------------------------------------------
 //      Does this appear to be a .htf file?
 // --------------------------------------------------------------------
 
@@ -119,14 +116,20 @@ int OGRHTFDataSource::Open( const char * pszFilename )
         return FALSE;
 
     const char* pszLine;
-    int bEndOfHTFHeader = FALSE;
-    int bIsSouth = FALSE;
-    int bGeodeticDatumIsWGS84 = FALSE;
-    int bIsUTM = FALSE;
+    bool bEndOfHTFHeader = false;
+    bool bIsSouth = false;
+    bool bGeodeticDatumIsWGS84 = false;
+    bool bIsUTM = false;
     int nZone = 0;
     int nLines = 0;
-    int bHasSWEasting = FALSE, bHasSWNorthing = FALSE, bHasNEEasting = FALSE, bHasNENorthing = FALSE;
-    double dfSWEasting = 0, dfSWNorthing = 0, dfNEEasting = 0, dfNENorthing = 0;
+    bool bHasSWEasting = false;
+    bool bHasSWNorthing = false;
+    bool bHasNEEasting = false;
+    bool bHasNENorthing = false;
+    double dfSWEasting = 0;
+    double dfSWNorthing = 0;
+    double dfNEEasting = 0;
+    double dfNENorthing = 0;
     std::vector<CPLString> aosMD;
     int nTotalSoundings = 0;
     while( (pszLine = CPLReadLine2L(fp, 1024, NULL)) != NULL)
@@ -141,17 +144,17 @@ int OGRHTFDataSource::Open( const char * pszFilename )
 
         if (strcmp(pszLine, "END OF HTF HEADER") == 0)
         {
-            bEndOfHTFHeader = TRUE;
+            bEndOfHTFHeader = true;
             break;
         }
 
         aosMD.push_back(pszLine);
 
-        if (strncmp(pszLine, "GEODETIC DATUM: ", 16) == 0)
+        if (STARTS_WITH(pszLine, "GEODETIC DATUM: "))
         {
             if (strcmp(pszLine + 16, "WG84") == 0 ||
                 strcmp(pszLine + 16, "WGS84") == 0)
-                bGeodeticDatumIsWGS84 = TRUE;
+                bGeodeticDatumIsWGS84 = true;
             else
             {
                 VSIFCloseL(fp);
@@ -160,45 +163,45 @@ int OGRHTFDataSource::Open( const char * pszFilename )
                 return FALSE;
             }
         }
-        else if (strncmp(pszLine, "NE LATITUDE: -", 14) == 0)
-            bIsSouth = TRUE;
-        else if (strncmp(pszLine, "GRID REFERENCE SYSTEM: ", 23) == 0)
+        else if (STARTS_WITH(pszLine, "NE LATITUDE: -"))
+            bIsSouth = true;
+        else if (STARTS_WITH(pszLine, "GRID REFERENCE SYSTEM: "))
         {
-            if (strncmp(pszLine + 23, "UTM", 3) == 0)
-                bIsUTM = TRUE;
+            if (STARTS_WITH(pszLine + 23, "UTM"))
+                bIsUTM = true;
             else
             {
                 VSIFCloseL(fp);
                 CPLError(CE_Failure, CPLE_NotSupported,
                          "Unsupported grid : %s", pszLine + 23);
-                return FALSE;
+                return false;
             }
         }
-        else if (strncmp(pszLine, "GRID ZONE: ", 11) == 0)
+        else if (STARTS_WITH(pszLine, "GRID ZONE: "))
         {
             nZone = atoi(pszLine + 11);
         }
-        else if (strncmp(pszLine, "SW GRID COORDINATE - EASTING: ", 30) == 0)
+        else if (STARTS_WITH(pszLine, "SW GRID COORDINATE - EASTING: "))
         {
-            bHasSWEasting = TRUE;
+            bHasSWEasting = true;
             dfSWEasting = CPLAtof(pszLine + 30);
         }
-        else if (strncmp(pszLine, "SW GRID COORDINATE - NORTHING: ", 31) == 0)
+        else if (STARTS_WITH(pszLine, "SW GRID COORDINATE - NORTHING: "))
         {
-            bHasSWNorthing = TRUE;
+            bHasSWNorthing = true;
             dfSWNorthing = CPLAtof(pszLine + 31);
         }
-        else if (strncmp(pszLine, "NE GRID COORDINATE - EASTING: ", 30) == 0)
+        else if (STARTS_WITH(pszLine, "NE GRID COORDINATE - EASTING: "))
         {
-            bHasNEEasting = TRUE;
+            bHasNEEasting = true;
             dfNEEasting = CPLAtof(pszLine + 30);
         }
-        else if (strncmp(pszLine, "NE GRID COORDINATE - NORTHING: ", 31) == 0)
+        else if (STARTS_WITH(pszLine, "NE GRID COORDINATE - NORTHING: "))
         {
-            bHasNENorthing = TRUE;
+            bHasNENorthing = true;
             dfNENorthing = CPLAtof(pszLine + 31);
         }
-        else if (strncmp(pszLine, "TOTAL SOUNDINGS: ", 17) == 0)
+        else if (STARTS_WITH(pszLine, "TOTAL SOUNDINGS: "))
         {
             nTotalSoundings = atoi(pszLine + 17);
         }
@@ -214,16 +217,20 @@ int OGRHTFDataSource::Open( const char * pszFilename )
         return FALSE;
     if (nZone == 0)
         return FALSE;
-  
+
     nLayers = 2;
-    papoLayers = (OGRHTFLayer**) CPLMalloc(sizeof(OGRHTFLayer*) * 2);
+    papoLayers = static_cast<OGRHTFLayer **>(
+        CPLMalloc(sizeof(OGRHTFLayer*) * 2) );
     papoLayers[0] = new OGRHTFPolygonLayer(pszFilename, nZone, !bIsSouth);
-    papoLayers[1] = new OGRHTFSoundingLayer(pszFilename, nZone, !bIsSouth, nTotalSoundings);
+    papoLayers[1] = new OGRHTFSoundingLayer(
+        pszFilename, nZone, !bIsSouth, nTotalSoundings);
 
     if (bHasSWEasting && bHasSWNorthing && bHasNEEasting && bHasNENorthing)
     {
-        papoLayers[0]->SetExtent(dfSWEasting, dfSWNorthing, dfNEEasting, dfNENorthing);
-        papoLayers[1]->SetExtent(dfSWEasting, dfSWNorthing, dfNEEasting, dfNENorthing);
+        papoLayers[0]->SetExtent(
+            dfSWEasting, dfSWNorthing, dfNEEasting, dfNENorthing);
+        papoLayers[1]->SetExtent(
+            dfSWEasting, dfSWNorthing, dfNEEasting, dfNENorthing);
     }
 
     poMetadataLayer = new OGRHTFMetadataLayer(aosMD);
diff --git a/ogr/ogrsf_frmts/htf/ogrhtfdriver.cpp b/ogr/ogrsf_frmts/htf/ogrhtfdriver.cpp
index a4ebf6e..4fff184 100644
--- a/ogr/ogrsf_frmts/htf/ogrhtfdriver.cpp
+++ b/ogr/ogrsf_frmts/htf/ogrhtfdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrhtfdriver.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogrhtfdriver.cpp 32744 2016-01-04 22:26:42Z goatbar $
  *
  * Project:  HTF Translator
  * Purpose:  Implements OGRHTFDriver.
@@ -27,12 +27,11 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_htf.h"
 #include "cpl_conv.h"
+#include "ogr_htf.h"
+#include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: ogrhtfdriver.cpp 27384 2014-05-24 12:28:12Z rouault $");
-
-extern "C" void RegisterOGRHTF();
+CPL_CVSID("$Id: ogrhtfdriver.cpp 32744 2016-01-04 22:26:42Z goatbar $");
 
 /************************************************************************/
 /*                                Open()                                */
@@ -45,10 +44,11 @@ static GDALDataset *OGRHTFDriverOpen( GDALOpenInfo* poOpenInfo )
         poOpenInfo->fpL == NULL )
         return NULL;
 
-    if( strncmp((const char*)poOpenInfo->pabyHeader,  "HTF HEADER", strlen("HTF HEADER")) != 0 )
+    if( !STARTS_WITH( reinterpret_cast<char *>(poOpenInfo->pabyHeader),
+                      "HTF HEADER") )
         return NULL;
 
-    OGRHTFDataSource   *poDS = new OGRHTFDataSource();
+    OGRHTFDataSource *poDS = new OGRHTFDataSource();
 
     if( !poDS->Open( poOpenInfo->pszFilename ) )
     {
@@ -66,24 +66,20 @@ static GDALDataset *OGRHTFDriverOpen( GDALOpenInfo* poOpenInfo )
 void RegisterOGRHTF()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "HTF" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "HTF" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "HTF" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+    poDriver->SetDescription( "HTF" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
                                    "Hydrographic Transfer Vector" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_htf.html" );
-
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_htf.html" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = OGRHTFDriverOpen;
+    poDriver->pfnOpen = OGRHTFDriverOpen;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
 
diff --git a/ogr/ogrsf_frmts/htf/ogrhtflayer.cpp b/ogr/ogrsf_frmts/htf/ogrhtflayer.cpp
index 295ac8a..9427ff9 100644
--- a/ogr/ogrsf_frmts/htf/ogrhtflayer.cpp
+++ b/ogr/ogrsf_frmts/htf/ogrhtflayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrhtflayer.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrhtflayer.cpp 33199 2016-01-29 15:48:41Z rouault $
  *
  * Project:  HTF Translator
  * Purpose:  Implements OGRHTFLayer class.
@@ -27,42 +27,41 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_htf.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "ogr_htf.h"
 #include "ogr_p.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ogrhtflayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrhtflayer.cpp 33199 2016-01-29 15:48:41Z rouault $");
 
 /************************************************************************/
 /*                            OGRHTFLayer()                             */
 /************************************************************************/
 
-OGRHTFLayer::OGRHTFLayer( const char* pszFilename, int nZone, int bIsNorth )
-
+OGRHTFLayer::OGRHTFLayer( const char* pszFilename, int nZone, int bIsNorth ) :
+    poFeatureDefn(NULL),
+    bEOF(false),
+    nNextFID(0),
+    bHasExtent(false),
+    dfMinX(0),
+    dfMinY(0),
+    dfMaxX(0),
+    dfMaxY(0)
 {
     fpHTF = VSIFOpenL(pszFilename, "rb");
-    nNextFID = 0;
-    bEOF = FALSE;
 
     poSRS = new OGRSpatialReference(SRS_WKT_WGS84);
     poSRS->SetUTM( nZone, bIsNorth );
-
-    bHasExtent = FALSE;
-    dfMinX = 0;
-    dfMinY = 0;
-    dfMaxX = 0;
-    dfMaxY = 0;
 }
 
 /************************************************************************/
 /*                         OGRHTFPolygonLayer()                         */
 /************************************************************************/
 
-OGRHTFPolygonLayer::OGRHTFPolygonLayer( const char* pszFilename, int nZone, int bIsNorth ) :
-                                     OGRHTFLayer(pszFilename, nZone, bIsNorth)
-
+OGRHTFPolygonLayer::OGRHTFPolygonLayer( const char* pszFilename, int nZone,
+                                        int bIsNorth ) :
+    OGRHTFLayer(pszFilename, nZone, bIsNorth)
 {
     poFeatureDefn = new OGRFeatureDefn( "polygon" );
     SetDescription( poFeatureDefn->GetName() );
@@ -88,9 +87,16 @@ OGRHTFPolygonLayer::OGRHTFPolygonLayer( const char* pszFilename, int nZone, int
 /*                        OGRHTFSoundingLayer()                         */
 /************************************************************************/
 
-OGRHTFSoundingLayer::OGRHTFSoundingLayer( const char* pszFilename, int nZone, int bIsNorth, int nTotalSoundings ) :
-                                        OGRHTFLayer(pszFilename, nZone, bIsNorth)
-
+OGRHTFSoundingLayer::OGRHTFSoundingLayer( const char* pszFilename, int nZone,
+                                          int bIsNorth,
+                                          int nTotalSoundingsIn ) :
+    OGRHTFLayer(pszFilename, nZone, bIsNorth),
+    bHasFPK(false),
+    nFieldsPresent(0),
+    panFieldPresence(NULL),
+    nEastingIndex(-1),
+    nNorthingIndex(-1),
+    nTotalSoundings(nTotalSoundingsIn)
 {
     poFeatureDefn = new OGRFeatureDefn( "sounding" );
     SetDescription( poFeatureDefn->GetName() );
@@ -98,20 +104,13 @@ OGRHTFSoundingLayer::OGRHTFSoundingLayer( const char* pszFilename, int nZone, in
     poFeatureDefn->SetGeomType( wkbPoint  );
     poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 
-    this->nTotalSoundings = nTotalSoundings;
-    bHasFPK = FALSE;
-    nFieldsPresent = 0;
-    panFieldPresence = NULL;
-    nEastingIndex = -1;
-    nNorthingIndex = -1;
-
     const char* pszLine;
-    int bSoundingHeader = FALSE;
+    bool bSoundingHeader = false;
     while( fpHTF != NULL &&
            (pszLine = CPLReadLine2L(fpHTF, 1024, NULL)) != NULL)
     {
-        if (strncmp(pszLine, "SOUNDING HEADER", strlen("SOUNDING HEADER")) == 0)
-            bSoundingHeader = TRUE;
+        if (STARTS_WITH(pszLine, "SOUNDING HEADER"))
+            bSoundingHeader = true;
         else if (bSoundingHeader && strlen(pszLine) > 10 &&
                  pszLine[0] == '[' && pszLine[3] == ']' &&
                  pszLine[4] == ' ' &&
@@ -151,7 +150,7 @@ OGRHTFSoundingLayer::OGRHTFSoundingLayer( const char* pszFilename, int nZone, in
         }
         else if (strcmp(pszLine, "END OF SOUNDING HEADER") == 0)
         {
-            bSoundingHeader = FALSE;
+            bSoundingHeader = false;
         }
         else if (strcmp(pszLine, "SOUNDING DATA") == 0)
         {
@@ -159,34 +158,32 @@ OGRHTFSoundingLayer::OGRHTFSoundingLayer( const char* pszFilename, int nZone, in
             if (pszLine == NULL)
                 break;
             if (pszLine[0] == '[' &&
-                (int)strlen(pszLine) == 2 + poFeatureDefn->GetFieldCount())
+                static_cast<int>(strlen(pszLine)) ==
+                2 + poFeatureDefn->GetFieldCount())
             {
-                bHasFPK = TRUE;
-                panFieldPresence = (int*)CPLMalloc(sizeof(int) *
-                                            poFeatureDefn->GetFieldCount());
-                int i;
-                for(i=0;i<poFeatureDefn->GetFieldCount();i++)
+                bHasFPK = true;
+                panFieldPresence = static_cast<bool *>(
+                    CPLMalloc(sizeof(int) * poFeatureDefn->GetFieldCount()) );
+                for( int i=0;i<poFeatureDefn->GetFieldCount();i++)
                 {
                     panFieldPresence[i] = pszLine[1 + i] != '0';
-                    nFieldsPresent += panFieldPresence[i];
+                    nFieldsPresent += panFieldPresence[i] ? 1 : 0;
                 }
             }
             break;
         }
     }
 
-    if (!bHasFPK)
+    if( !bHasFPK )
     {
-        panFieldPresence = (int*)CPLMalloc(sizeof(int) *
-                                           poFeatureDefn->GetFieldCount());
-        int i;
-        for(i=0;i<poFeatureDefn->GetFieldCount();i++)
-            panFieldPresence[i] = TRUE;
+        panFieldPresence = static_cast<bool *>(
+            CPLMalloc(sizeof(int) * poFeatureDefn->GetFieldCount()) );
+        for( int i=0; i < poFeatureDefn->GetFieldCount(); i++ )
+            panFieldPresence[i] = true;
         nFieldsPresent = poFeatureDefn->GetFieldCount();
     }
 
-    int nIndex;
-    nIndex = poFeatureDefn->GetFieldIndex("EASTING");
+    int nIndex = poFeatureDefn->GetFieldIndex("EASTING");
     if (nIndex < 0 || !panFieldPresence[nIndex])
     {
         CPLError(CE_Failure, CPLE_NotSupported, "Cannot find EASTING field");
@@ -243,7 +240,7 @@ void OGRHTFLayer::ResetReading()
 
 {
     nNextFID = 0;
-    bEOF = FALSE;
+    bEOF = false;
     if (fpHTF)
     {
         VSIFSeekL( fpHTF, 0, SEEK_SET );
@@ -270,7 +267,7 @@ void OGRHTFPolygonLayer::ResetReading()
             }
         }
         if (pszLine == NULL)
-            bEOF = TRUE;
+            bEOF = true;
     }
 }
 
@@ -296,7 +293,7 @@ void OGRHTFSoundingLayer::ResetReading()
             }
         }
         if (pszLine == NULL)
-            bEOF = TRUE;
+            bEOF = true;
     }
 }
 
@@ -306,14 +303,12 @@ void OGRHTFSoundingLayer::ResetReading()
 
 OGRFeature *OGRHTFLayer::GetNextFeature()
 {
-    OGRFeature  *poFeature;
-
     if (fpHTF == NULL || bEOF)
         return NULL;
 
     while(!bEOF)
     {
-        poFeature = GetNextRawFeature();
+        OGRFeature *poFeature = GetNextRawFeature();
         if (poFeature == NULL)
             return NULL;
 
@@ -324,8 +319,8 @@ OGRFeature *OGRHTFLayer::GetNextFeature()
         {
             return poFeature;
         }
-        else
-            delete poFeature;
+
+        delete poFeature;
     }
 
     return NULL;
@@ -342,10 +337,12 @@ OGRFeature *OGRHTFPolygonLayer::GetNextRawFeature()
     const char* pszLine;
 
     OGRLinearRing oLR;
-    int bHastFirstCoord = FALSE;
-    double dfFirstEasting = 0, dfFirstNorthing = 0;
-    double dfIslandEasting = 0, dfIslandNorthing = 0;
-    int bInIsland = FALSE;
+    bool bHasFirstCoord = false;
+    double dfFirstEasting = 0;
+    double dfFirstNorthing = 0;
+    double dfIslandEasting = 0;
+    double dfIslandNorthing = 0;
+    bool bInIsland = false;
     OGRPolygon* poPoly = new OGRPolygon();
 
     while( (pszLine = CPLReadLine2L(fpHTF, 1024, NULL)) != NULL)
@@ -359,32 +356,27 @@ OGRFeature *OGRHTFPolygonLayer::GetNextRawFeature()
             /* end of polygon is marked by a blank line */
             break;
         }
-        else if (strncmp(pszLine, "POLYGON DESCRIPTION: ",
-                         strlen("POLYGON DESCRIPTION: ")) == 0)
+        else if (STARTS_WITH(pszLine, "POLYGON DESCRIPTION: "))
         {
             poFeature->SetField(0, pszLine + strlen("POLYGON DESCRIPTION: "));
         }
-        else if (strncmp(pszLine, "POLYGON IDENTIFIER: ",
-                         strlen("POLYGON IDENTIFIER: ")) == 0)
+        else if (STARTS_WITH(pszLine, "POLYGON IDENTIFIER: "))
         {
             poFeature->SetField(1, pszLine + strlen("POLYGON IDENTIFIER: "));
         }
-        else if (strncmp(pszLine, "SEAFLOOR COVERAGE: ",
-                         strlen("SEAFLOOR COVERAGE:")) == 0)
+        else if (STARTS_WITH(pszLine, "SEAFLOOR COVERAGE: "))
         {
             const char* pszVal = pszLine + strlen("SEAFLOOR COVERAGE: ");
             if (*pszVal != '*')
                 poFeature->SetField(2, pszVal);
         }
-        else if (strncmp(pszLine, "POSITION ACCURACY: ",
-                         strlen("POSITION ACCURACY:")) == 0)
+        else if (STARTS_WITH(pszLine, "POSITION ACCURACY: "))
         {
             const char* pszVal = pszLine + strlen("POSITION ACCURACY: ");
             if (*pszVal != '*')
                 poFeature->SetField(3, pszVal);
         }
-        else if (strncmp(pszLine, "DEPTH ACCURACY: ",
-                         strlen("DEPTH ACCURACY:")) == 0)
+        else if (STARTS_WITH(pszLine, "DEPTH ACCURACY: "))
         {
             const char* pszVal = pszLine + strlen("DEPTH ACCURACY: ");
             if (*pszVal != '*')
@@ -392,7 +384,7 @@ OGRFeature *OGRHTFPolygonLayer::GetNextRawFeature()
         }
         else if (strcmp(pszLine, "END OF POLYGON DATA") == 0)
         {
-            bEOF = TRUE;
+            bEOF = true;
             break;
         }
         else
@@ -400,11 +392,11 @@ OGRFeature *OGRHTFPolygonLayer::GetNextRawFeature()
             char** papszTokens = CSLTokenizeString(pszLine);
             if (CSLCount(papszTokens) == 4)
             {
-                double dfEasting = CPLAtof(papszTokens[2]);
-                double dfNorthing = CPLAtof(papszTokens[3]);
-                if (!bHastFirstCoord)
+                const double dfEasting = CPLAtof(papszTokens[2]);
+                const double dfNorthing = CPLAtof(papszTokens[3]);
+                if (!bHasFirstCoord)
                 {
-                    bHastFirstCoord = TRUE;
+                    bHasFirstCoord = true;
                     dfFirstEasting = dfEasting;
                     dfFirstNorthing = dfNorthing;
                     oLR.addPoint(dfEasting, dfNorthing);
@@ -417,7 +409,7 @@ OGRFeature *OGRHTFPolygonLayer::GetNextRawFeature()
                         oLR.addPoint(dfEasting, dfNorthing);
                         poPoly->addRing(&oLR);
                         oLR.empty();
-                        bInIsland = TRUE;
+                        bInIsland = true;
                     }
                 }
                 else if (bInIsland && oLR.getNumPoints() == 0)
@@ -443,7 +435,7 @@ OGRFeature *OGRHTFPolygonLayer::GetNextRawFeature()
     }
 
     if (pszLine == NULL)
-        bEOF = TRUE;
+        bEOF = true;
 
     if (oLR.getNumPoints() >= 3)
     {
@@ -476,12 +468,12 @@ OGRFeature *OGRHTFSoundingLayer::GetNextRawFeature()
         }
         else if (pszLine[0] == 0)
         {
-            bEOF = TRUE;
+            bEOF = true;
             return NULL;
         }
         else if (strcmp(pszLine, "END OF SOUNDING DATA") == 0)
         {
-            bEOF = TRUE;
+            bEOF = true;
             return NULL;
         }
         else
@@ -489,15 +481,15 @@ OGRFeature *OGRHTFSoundingLayer::GetNextRawFeature()
     }
     if (pszLine == NULL)
     {
-        bEOF = TRUE;
+        bEOF = true;
         return NULL;
     }
 
-    int i;
-    double dfEasting = 0, dfNorthing = 0;
+    double dfEasting = 0;
+    double dfNorthing = 0;
     OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
-    char* pszStr = (char*)pszLine;
-    for(i=0;i<poFeatureDefn->GetFieldCount();i++)
+    char* pszStr = const_cast<char *>(pszLine);
+    for( int i=0; i < poFeatureDefn->GetFieldCount(); i++ )
     {
         if (!panFieldPresence[i])
             continue;
@@ -582,7 +574,8 @@ int OGRHTFSoundingLayer::TestCapability( const char * pszCap )
 
 {
     if (EQUAL(pszCap, OLCFastFeatureCount))
-        return m_poFilterGeom == NULL && m_poAttrQuery == NULL && nTotalSoundings != 0;
+        return m_poFilterGeom == NULL && m_poAttrQuery == NULL &&
+            nTotalSoundings != 0;
 
     return OGRHTFLayer::TestCapability(pszCap);
 }
@@ -608,13 +601,14 @@ OGRErr OGRHTFLayer::GetExtent(OGREnvelope *psExtent, int bForce)
 /*                             SetExtent()                              */
 /************************************************************************/
 
-void OGRHTFLayer::SetExtent(double dfMinX, double dfMinY, double dfMaxX, double dfMaxY)
+void OGRHTFLayer::SetExtent( double dfMinXIn, double dfMinYIn, double dfMaxXIn,
+                             double dfMaxYIn )
 {
-    bHasExtent = TRUE;
-    this->dfMinX = dfMinX;
-    this->dfMinY = dfMinY;
-    this->dfMaxX = dfMaxX;
-    this->dfMaxY = dfMaxY;
+    bHasExtent = true;
+    dfMinX = dfMinXIn;
+    dfMinY = dfMinYIn;
+    dfMaxX = dfMaxXIn;
+    dfMaxY = dfMaxYIn;
 }
 
 
@@ -622,21 +616,20 @@ void OGRHTFLayer::SetExtent(double dfMinX, double dfMinY, double dfMaxX, double
 /*                        OGRHTFMetadataLayer()                         */
 /************************************************************************/
 
-OGRHTFMetadataLayer::OGRHTFMetadataLayer(std::vector<CPLString> aosMD)
+OGRHTFMetadataLayer::OGRHTFMetadataLayer(std::vector<CPLString> aosMDIn) :
+    poFeatureDefn(new OGRFeatureDefn( "metadata" )),
+    aosMD(aosMDIn),
+    nNextFID(0)
 {
-    this->aosMD = aosMD;
-    nNextFID = 0;
-
-    poFeatureDefn = new OGRFeatureDefn( "metadata" );
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbNone  );
 
-    std::vector<CPLString>::const_iterator iter = aosMD.begin();
-    std::vector<CPLString>::const_iterator eiter = aosMD.end();
-    while(iter != eiter)
+    std::vector<CPLString>::const_iterator oIter = aosMD.begin();
+    std::vector<CPLString>::const_iterator oEndIter = aosMD.end();
+    while(oIter != oEndIter)
     {
-        const CPLString& osStr = *iter;
+        const CPLString& osStr = *oIter;
         char* pszStr = CPLStrdup(osStr.c_str());
         char* pszSep = strstr(pszStr, ": ");
         if (pszSep)
@@ -661,16 +654,16 @@ OGRHTFMetadataLayer::OGRHTFMetadataLayer(std::vector<CPLString> aosMD)
             poFeatureDefn->AddFieldDefn( &oField );
         }
         CPLFree(pszStr);
-        ++iter;
+        ++oIter;
     }
 
     poFeature = new OGRFeature(poFeatureDefn);
-    iter = aosMD.begin();
-    eiter = aosMD.end();
+    oIter = aosMD.begin();
+    oEndIter = aosMD.end();
     int nField = 0;
-    while(iter != eiter)
+    while(oIter != oEndIter)
     {
-        const CPLString& osStr = *iter;
+        const CPLString& osStr = *oIter;
         const char* pszStr = osStr.c_str();
         const char* pszSep = strstr(pszStr, ": ");
         if (pszSep)
@@ -680,7 +673,7 @@ OGRHTFMetadataLayer::OGRHTFMetadataLayer(std::vector<CPLString> aosMD)
 
             nField ++;
         }
-        ++iter;
+        ++oIter;
     }
 }
 
diff --git a/ogr/ogrsf_frmts/idb/drv_idb.html b/ogr/ogrsf_frmts/idb/drv_idb.html
index ef5f213..d905e8e 100644
--- a/ogr/ogrsf_frmts/idb/drv_idb.html
+++ b/ogr/ogrsf_frmts/idb/drv_idb.html
@@ -7,7 +7,7 @@
 
 <h1>IDB</h1>
 
-<p>This driver implements support for access to spatial tables in 
+<p>This driver implements support for access to spatial tables in
 IBM Informix extended with the DataBlade spatial module.
 
 <p>When opening a database, it's name should be specified in the form
@@ -22,7 +22,7 @@ will be treated as layers.
 
 <p>Regular (non-spatial) tables can be accessed, and will return features with
 attributes, but not geometry.  If the table has a "st_*" field, it will
-be treated as a spatial table. The type of the field is inspected to 
+be treated as a spatial table. The type of the field is inspected to
 determine how to read it.
 
 <p>Driver supports automatic FID detection.
diff --git a/ogr/ogrsf_frmts/idb/ogr_idb.h b/ogr/ogrsf_frmts/idb/ogr_idb.h
index 4fc8e82..6dd1b0a 100644
--- a/ogr/ogrsf_frmts/idb/ogr_idb.h
+++ b/ogr/ogrsf_frmts/idb/ogr_idb.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_idb.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogr_idb.h 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRIDBTableLayer class, access to an existing table
@@ -28,8 +28,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_IDB_H_INCLUDED_
-#define _OGR_IDB_H_INCLUDED_
+#ifndef OGR_IDB_H_INCLUDED_
+#define OGR_IDB_H_INCLUDED_
 
 #include "ogrsf_frmts.h"
 #include "cpl_error.h"
@@ -106,7 +106,7 @@ class OGRIDBTableLayer : public OGRIDBLayer
                         OGRIDBTableLayer( OGRIDBDataSource * );
                         ~OGRIDBTableLayer();
 
-    CPLErr              Initialize( const char *pszTableName, 
+    CPLErr              Initialize( const char *pszTableName,
                                     const char *pszGeomCol,
                                     int bUpdate
                                   );
@@ -121,7 +121,7 @@ class OGRIDBTableLayer : public OGRIDBLayer
 #if 0
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
                                      int bApproxOK = TRUE );
-#endif    
+#endif
     virtual OGRFeature *GetFeature( GIntBig nFeatureId );
 
     virtual OGRSpatialReference *GetSpatialRef();
@@ -153,6 +153,8 @@ class OGRIDBSelectLayer : public OGRIDBLayer
     virtual OGRFeature *GetFeature( GIntBig nFeatureId );
 
     virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
     virtual int         TestCapability( const char * );
 };
@@ -176,7 +178,7 @@ class OGRIDBDataSource : public OGRDataSource
                         ~OGRIDBDataSource();
 
     int                 Open( const char *, int bUpdate, int bTestOpen );
-    int                 OpenTable( const char *pszTableName, 
+    int                 OpenTable( const char *pszTableName,
                                    const char *pszGeomCol,
                                    int bUpdate );
 
@@ -216,5 +218,3 @@ ITCallbackResult
 IDBErrorHandler( const ITErrorManager &err, void * userdata, long errorlevel );
 
 #endif /* ndef _OGR_idb_H_INCLUDED_ */
-
-
diff --git a/ogr/ogrsf_frmts/idb/ogridbdatasource.cpp b/ogr/ogrsf_frmts/idb/ogridbdatasource.cpp
index 5b6e8d0..5e91708 100644
--- a/ogr/ogrsf_frmts/idb/ogridbdatasource.cpp
+++ b/ogr/ogrsf_frmts/idb/ogridbdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogridbdatasource.cpp 26506 2013-09-30 18:17:55Z rouault $
+ * $Id: ogridbdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRIDBDataSource class
@@ -32,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogridbdatasource.cpp 26506 2013-09-30 18:17:55Z rouault $");
+CPL_CVSID("$Id: ogridbdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 /************************************************************************/
 /*                         OGRIDBDataSource()                          */
 /************************************************************************/
@@ -88,19 +88,19 @@ int OGRIDBDataSource::Open( const char * pszNewName, int bUpdate,
 
     char ** papszTokens = CSLTokenizeString2(pszNewName + 4, " ", 0);
     char * pszToken = 0;
-    int i = 0; 
+    int i = 0;
 
     while ( pszToken = papszTokens[i++] )
     {
-        if ( EQUALN( pszToken, "dbname=", 7 ) )
+        if ( STARTS_WITH_CI(pszToken, "dbname=") )
             pszDbName = CPLStrdup( pszToken + 7 );
-        else if ( EQUALN( pszToken, "server=", 7 ) )
+        else if ( STARTS_WITH_CI(pszToken, "server=") )
             pszServer = CPLStrdup( pszToken + 7 );
-        else if ( EQUALN( pszToken, "user=", 5 ) )
+        else if ( STARTS_WITH_CI(pszToken, "user=") )
             pszUser = CPLStrdup( pszToken + 5 );
-        else if ( EQUALN( pszToken, "pass=", 5 ) )
+        else if ( STARTS_WITH_CI(pszToken, "pass=") )
             pszPass = CPLStrdup( pszToken + 5 );
-        else if ( EQUALN( pszToken, "table=", 6 ) )
+        else if ( STARTS_WITH_CI(pszToken, "table=") )
         {
             papszTables = CSLAddString( papszTables, pszToken + 6 );
             papszGeomCol = CSLAddString( papszGeomCol, "" );
@@ -129,7 +129,7 @@ int OGRIDBDataSource::Open( const char * pszNewName, int bUpdate,
 
     if( !poConn->Open() )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to initialize IDB connection to %s",
                   pszNewName+4);
         CSLDestroy( papszTables );
@@ -155,9 +155,9 @@ int OGRIDBDataSource::Open( const char * pszNewName, int bUpdate,
             ITRow * row = 0;
             while( (row = oCurr.NextRow()) )
             {
-                papszTables = 
+                papszTables =
                     CSLAddString( papszTables, row->Column(0)->Printable() );
-                papszGeomCol = 
+                papszGeomCol =
                     CSLAddString( papszGeomCol, row->Column(1)->Printable() );
                 row->Release();
             }
@@ -178,7 +178,7 @@ int OGRIDBDataSource::Open( const char * pszNewName, int bUpdate,
             ITRow * row = 0;
             while( (row = oTableList.NextRow()) )
             {
-                papszTables = 
+                papszTables =
                     CSLAddString( papszTables, row->Column(0)->Printable() );
                 papszGeomCol = CSLAddString(papszGeomCol,"");
                 row->Release();
@@ -194,8 +194,8 @@ int OGRIDBDataSource::Open( const char * pszNewName, int bUpdate,
 /*      If we have an explicit list of requested tables, use them       */
 /*      (non-spatial).                                                  */
 /* -------------------------------------------------------------------- */
-    for( int iTable = 0; 
-         papszTables != NULL && papszTables[iTable] != NULL; 
+    for( int iTable = 0;
+         papszTables != NULL && papszTables[iTable] != NULL;
          iTable++ )
     {
         char * pszGeomCol = NULL;
@@ -282,8 +282,8 @@ OGRLayer * OGRIDBDataSource::ExecuteSQL( const char *pszSQLCommand,
 /*      Use generic implementation for recognized dialects              */
 /* -------------------------------------------------------------------- */
     if( IsGenericSQLDialect(pszDialect) )
-        return OGRDataSource::ExecuteSQL( pszSQLCommand, 
-                                          poSpatialFilter, 
+        return OGRDataSource::ExecuteSQL( pszSQLCommand,
+                                          poSpatialFilter,
                                           pszDialect );
 
 /* -------------------------------------------------------------------- */
@@ -294,7 +294,7 @@ OGRLayer * OGRIDBDataSource::ExecuteSQL( const char *pszSQLCommand,
     poCurr->Prepare( pszSQLCommand );
     if( !poCurr->Open(ITCursor::ReadOnly) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Error execute SQL: %s", pszSQLCommand );
         return NULL;
     }
diff --git a/ogr/ogrsf_frmts/idb/ogridbdriver.cpp b/ogr/ogrsf_frmts/idb/ogridbdriver.cpp
index f6b1c8b..ff334e0 100644
--- a/ogr/ogrsf_frmts/idb/ogridbdriver.cpp
+++ b/ogr/ogrsf_frmts/idb/ogridbdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogridbdriver.cpp 12396 2007-10-13 10:02:17Z rouault $
+ * $Id: ogridbdriver.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRIDBDriver class.
@@ -31,7 +31,7 @@
 #include "ogr_idb.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogridbdriver.cpp 12396 2007-10-13 10:02:17Z rouault $");
+CPL_CVSID("$Id: ogridbdriver.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                            ~OGRIDBDriver()                            */
@@ -62,7 +62,7 @@ OGRDataSource *OGRIDBDriver::Open( const char * pszFilename,
 {
     OGRIDBDataSource     *poDS;
 
-    if( !EQUALN(pszFilename,"IDB:",4) )
+    if( !STARTS_WITH_CI(pszFilename, "IDB:") )
         return NULL;
 
     poDS = new OGRIDBDataSource();
@@ -86,7 +86,7 @@ OGRDataSource *OGRIDBDriver::CreateDataSource( const char * pszName,
 {
     OGRIDBDataSource     *poDS;
 
-    if( !EQUALN(pszName,"IDB:",4) )
+    if( !STARTS_WITH_CI(pszName, "IDB:") )
         return NULL;
 
     poDS = new OGRIDBDataSource();
@@ -94,7 +94,7 @@ OGRDataSource *OGRIDBDriver::CreateDataSource( const char * pszName,
     if( !poDS->Open( pszName, TRUE, TRUE ) )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
          "IDB driver doesn't currently support database creation.");
         return NULL;
     }
@@ -122,8 +122,7 @@ int OGRIDBDriver::TestCapability( const char * pszCap )
 void RegisterOGRIDB()
 
 {
-    if (! GDAL_CHECK_VERSION("IDB driver"))
+    if( !GDAL_CHECK_VERSION("IDB driver") )
         return;
     OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( new OGRIDBDriver );
 }
-
diff --git a/ogr/ogrsf_frmts/idb/ogridblayer.cpp b/ogr/ogrsf_frmts/idb/ogridblayer.cpp
index 1e4f6b2..0833945 100644
--- a/ogr/ogrsf_frmts/idb/ogridblayer.cpp
+++ b/ogr/ogrsf_frmts/idb/ogridblayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogridblayer.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogridblayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRIDBLayer class, code shared between
@@ -33,7 +33,7 @@
 #include "ogr_idb.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogridblayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogridblayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                            OGRIDBLayer()                            */
@@ -53,7 +53,7 @@ OGRIDBLayer::OGRIDBLayer()
     iNextShapeId = 0;
 
     poSRS = NULL;
-    nSRSId = -2; // we haven't even queried the database for it yet. 
+    nSRSId = -2; // we haven't even queried the database for it yet.
 }
 
 /************************************************************************/
@@ -93,7 +93,7 @@ OGRIDBLayer::~OGRIDBLayer()
 /*      set on a statement.  Sift out geometry and FID fields.          */
 /************************************************************************/
 
-CPLErr OGRIDBLayer::BuildFeatureDefn( const char *pszLayerName, 
+CPLErr OGRIDBLayer::BuildFeatureDefn( const char *pszLayerName,
                                     ITCursor *poCurr )
 
 {
@@ -117,7 +117,7 @@ CPLErr OGRIDBLayer::BuildFeatureDefn( const char *pszLayerName,
         if ( pszGeomColumn != NULL && EQUAL(pszColName,pszGeomColumn) )
             continue;
 
-        if ( EQUALN("st_", pszTypName, 3) && pszGeomColumn == NULL )
+        if ( STARTS_WITH_CI(pszTypName, "st_") && pszGeomColumn == NULL )
         {
             // We found spatial column!
             pszGeomColumn = CPLStrdup(pszColName);
@@ -143,17 +143,17 @@ CPLErr OGRIDBLayer::BuildFeatureDefn( const char *pszLayerName,
              EQUAL( pszTypName, "byte" ) ||
              EQUAL( pszTypName, "opaque" ) ||
              EQUAL( pszTypName, "text" ) ||
-             EQUALN( pszTypName, "list", 4 ) ||
-             EQUALN( pszTypName, "collection", 10 ) ||
-             EQUALN( pszTypName, "row", 3 ) ||
-             EQUALN( pszTypName, "set", 3 ) )
+             STARTS_WITH_CI(pszTypName, "list") ||
+             STARTS_WITH_CI(pszTypName, "collection") ||
+             STARTS_WITH_CI(pszTypName, "row") ||
+             STARTS_WITH_CI(pszTypName, "set") )
         {
             CPLDebug( "OGR_IDB", "'%s' column type not supported yet. Column '%s'",
                       pszTypName, pszColName );
             continue;
         }
 
-        if ( EQUALN( pszTypName, "st_", 3 ) )
+        if ( STARTS_WITH_CI(pszTypName, "st_") )
         {
             oField.SetType( OFTBinary );
         }
@@ -189,7 +189,7 @@ CPLErr OGRIDBLayer::BuildFeatureDefn( const char *pszLayerName,
         else
         {
             // leave as string:
-            // *char, character, character varing, *varchar
+            // *char, character, character varying, *varchar
             // interval. int8, serial8
         }
 
@@ -235,7 +235,7 @@ void OGRIDBLayer::ResetReading()
 OGRFeature *OGRIDBLayer::GetNextFeature()
 
 {
-    for( ; TRUE; )
+    while( true )
     {
         OGRFeature      *poFeature;
 
diff --git a/ogr/ogrsf_frmts/idb/ogridbtablelayer.cpp b/ogr/ogrsf_frmts/idb/ogridbtablelayer.cpp
index b67faae..2eda4e7 100644
--- a/ogr/ogrsf_frmts/idb/ogridbtablelayer.cpp
+++ b/ogr/ogrsf_frmts/idb/ogridbtablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogridbtablelayer.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogridbtablelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRIDBTableLayer class, access to an existing table
@@ -32,7 +32,7 @@
 #include "cpl_string.h"
 #include "ogr_idb.h"
 
-CPL_CVSID("$Id: ogridbtablelayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogridbtablelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 /************************************************************************/
 /*                          OGRIDBTableLayer()                         */
 /************************************************************************/
@@ -149,8 +149,8 @@ CPLErr OGRIDBTableLayer::Initialize( const char *pszTableName,
 
     if( poFeatureDefn->GetFieldCount() == 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "No column definitions found for table '%s', layer not usable.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "No column definitions found for table '%s', layer not usable.",
                   pszTableName );
         return CE_Failure;
     }
@@ -158,9 +158,9 @@ CPLErr OGRIDBTableLayer::Initialize( const char *pszTableName,
 /* -------------------------------------------------------------------- */
 /*      Do we have XMIN, YMIN, XMAX, YMAX extent fields?                */
 /* -------------------------------------------------------------------- */
-    if( poFeatureDefn->GetFieldIndex( "XMIN" ) != -1 
-        && poFeatureDefn->GetFieldIndex( "XMAX" ) != -1 
-        && poFeatureDefn->GetFieldIndex( "YMIN" ) != -1 
+    if( poFeatureDefn->GetFieldIndex( "XMIN" ) != -1
+        && poFeatureDefn->GetFieldIndex( "XMAX" ) != -1
+        && poFeatureDefn->GetFieldIndex( "YMIN" ) != -1
         && poFeatureDefn->GetFieldIndex( "YMAX" ) != -1 )
     {
         bHaveSpatialExtents = TRUE;
@@ -176,8 +176,8 @@ CPLErr OGRIDBTableLayer::Initialize( const char *pszTableName,
         int iColumn = oGetCol.RowType()->ColumnId( pszGeomColumn );
         if( iColumn < 0 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Column %s requested for geometry, but it does not exist.", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Column %s requested for geometry, but it does not exist.",
                       pszGeomColumn );
             CPLFree( pszGeomColumn );
             pszGeomColumn = NULL;
@@ -382,7 +382,7 @@ OGRErr OGRIDBTableLayer::SetAttributeFilter( const char *pszQuery )
     m_pszAttrQueryString = (pszQuery) ? CPLStrdup(pszQuery) : NULL;
 
     if( (pszQuery == NULL && this->pszQuery == NULL)
-        || (pszQuery != NULL && this->pszQuery != NULL 
+        || (pszQuery != NULL && this->pszQuery != NULL
             && EQUAL(pszQuery,this->pszQuery)) )
         return OGRERR_NONE;
 
diff --git a/ogr/ogrsf_frmts/idrisi/generate_test_files.c b/ogr/ogrsf_frmts/idrisi/generate_test_files.c
index 1f4ad26..24cdd5b 100644
--- a/ogr/ogrsf_frmts/idrisi/generate_test_files.c
+++ b/ogr/ogrsf_frmts/idrisi/generate_test_files.c
@@ -1,7 +1,7 @@
 /******************************************************************************
  * $Id$
  *
- * Project:  
+ * Project:
  * Purpose:  Generate sample .VCT files
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
@@ -200,8 +200,6 @@ int main(int argc, char* argv[])
     fwrite(&x, 1, sizeof(double), f);
     fwrite(&y, 1, sizeof(double), f);
 
-
-    
     id = 2;
     minx = 400000;
     miny = 4000000;
diff --git a/ogr/ogrsf_frmts/idrisi/ogr_idrisi.h b/ogr/ogrsf_frmts/idrisi/ogr_idrisi.h
index 5a0afe7..bcf2a8a 100644
--- a/ogr/ogrsf_frmts/idrisi/ogr_idrisi.h
+++ b/ogr/ogrsf_frmts/idrisi/ogr_idrisi.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_idrisi.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogr_idrisi.h 32745 2016-01-04 23:16:43Z goatbar $
  *
  * Project:  Idrisi Translator
  * Purpose:  Definition of classes for OGR Idrisi driver.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_IDRISI_H_INCLUDED
-#define _OGR_IDRISI_H_INCLUDED
+#ifndef OGR_IDRISI_H_INCLUDED
+#define OGR_IDRISI_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 
@@ -45,11 +45,11 @@ protected:
 
     VSILFILE*          fp;
     VSILFILE*          fpAVL;
-    int                bEOF;
+    bool               bEOF;
 
     int                nNextFID;
 
-    int                bExtentValid;
+    bool               bExtentValid;
     double             dfMinX;
     double             dfMinY;
     double             dfMaxX;
@@ -78,6 +78,8 @@ protected:
 
     void SetExtent(double dfMinX, double dfMinY, double dfMaxX, double dfMaxY);
     virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
     virtual GIntBig         GetFeatureCount( int bForce = TRUE );
 };
@@ -122,4 +124,4 @@ class OGRIdrisiDriver : public OGRSFDriver
 };
 
 
-#endif /* ndef _OGR_IDRISI_H_INCLUDED */
+#endif /* ndef OGR_IDRISI_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/idrisi/ogridrisidatasource.cpp b/ogr/ogrsf_frmts/idrisi/ogridrisidatasource.cpp
index 3b81a8c..220aa94 100644
--- a/ogr/ogrsf_frmts/idrisi/ogridrisidatasource.cpp
+++ b/ogr/ogrsf_frmts/idrisi/ogridrisidatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogridrisidatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogridrisidatasource.cpp 32745 2016-01-04 23:16:43Z goatbar $
  *
  * Project:  Idrisi Translator
  * Purpose:  Implements OGRIdrisiDataSource class
@@ -27,25 +27,22 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_idrisi.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
 #include "idrisi.h"
+#include "ogr_idrisi.h"
 
-CPL_CVSID("$Id: ogridrisidatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogridrisidatasource.cpp 32745 2016-01-04 23:16:43Z goatbar $");
 
 /************************************************************************/
 /*                        OGRIdrisiDataSource()                         */
 /************************************************************************/
 
-OGRIdrisiDataSource::OGRIdrisiDataSource()
-
-{
-    papoLayers = NULL;
-    nLayers = 0;
-
-    pszName = NULL;
-}
+OGRIdrisiDataSource::OGRIdrisiDataSource() :
+    pszName(NULL),
+    papoLayers(NULL),
+    nLayers(0)
+{}
 
 /************************************************************************/
 /*                       ~OGRIdrisiDataSource()                         */
@@ -54,18 +51,17 @@ OGRIdrisiDataSource::OGRIdrisiDataSource()
 OGRIdrisiDataSource::~OGRIdrisiDataSource()
 
 {
+    CPLFree( pszName );
     for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
     CPLFree( papoLayers );
-
-    CPLFree( pszName );
 }
 
 /************************************************************************/
 /*                           TestCapability()                           */
 /************************************************************************/
 
-int OGRIdrisiDataSource::TestCapability( CPL_UNUSED const char * pszCap )
+int OGRIdrisiDataSource::TestCapability( const char * /* pszCap */ )
 {
     return FALSE;
 }
@@ -79,8 +75,8 @@ OGRLayer *OGRIdrisiDataSource::GetLayer( int iLayer )
 {
     if( iLayer < 0 || iLayer >= nLayers )
         return NULL;
-    else
-        return papoLayers[iLayer];
+
+    return papoLayers[iLayer];
 }
 
 /************************************************************************/
@@ -136,11 +132,13 @@ int OGRIdrisiDataSource::Open( const char * pszFilename )
             return FALSE;
         }
 
-        const char *pszRefSystem  = CSLFetchNameValue( papszVDC, "ref. system " );
-        const char *pszRefUnits   = CSLFetchNameValue( papszVDC, "ref. units  " );
+        const char *pszRefSystem
+            = CSLFetchNameValue( papszVDC, "ref. system " );
+        const char *pszRefUnits = CSLFetchNameValue( papszVDC, "ref. units  " );
 
         if (pszRefSystem != NULL && pszRefUnits != NULL)
-            IdrisiGeoReference2Wkt( pszFilename, pszRefSystem, pszRefUnits, &pszWTKString);
+            IdrisiGeoReference2Wkt( pszFilename, pszRefSystem, pszRefUnits,
+                                    &pszWTKString);
     }
 
     GByte chType;
@@ -159,27 +157,30 @@ int OGRIdrisiDataSource::Open( const char * pszFilename )
         eType = wkbPolygon;
     else
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "Unsupport geometry type : %d",
-                    (int)chType);
+        CPLError( CE_Failure, CPLE_AppDefined, "Unsupport geometry type : %d",
+                  static_cast<int>(chType) );
         VSIFCloseL(fpVCT);
         CSLDestroy( papszVDC );
         return FALSE;
     }
 
-    const char *pszMinX       = CSLFetchNameValue( papszVDC, "min. X      " );
-    const char *pszMaxX       = CSLFetchNameValue( papszVDC, "max. X      " );
-    const char *pszMinY       = CSLFetchNameValue( papszVDC, "min. Y      " );
-    const char *pszMaxY       = CSLFetchNameValue( papszVDC, "max. Y      " );
+    const char *pszMinX = CSLFetchNameValue( papszVDC, "min. X      " );
+    const char *pszMaxX = CSLFetchNameValue( papszVDC, "max. X      " );
+    const char *pszMinY = CSLFetchNameValue( papszVDC, "min. Y      " );
+    const char *pszMaxY = CSLFetchNameValue( papszVDC, "max. Y      " );
 
     OGRIdrisiLayer* poLayer = new OGRIdrisiLayer(pszFilename,
                                                  CPLGetBasename(pszFilename),
                                                  fpVCT, eType, pszWTKString);
-    papoLayers = (OGRLayer**) CPLMalloc(sizeof(OGRLayer*));
+    papoLayers = static_cast<OGRLayer**>( CPLMalloc(sizeof(OGRLayer*)) );
     papoLayers[nLayers ++] = poLayer;
 
-    if (pszMinX != NULL && pszMaxX != NULL && pszMinY != NULL && pszMaxY != NULL)
+    if( pszMinX != NULL && pszMaxX != NULL && pszMinY != NULL &&
+        pszMaxY != NULL)
     {
-        poLayer->SetExtent(CPLAtof(pszMinX), CPLAtof(pszMinY), CPLAtof(pszMaxX), CPLAtof(pszMaxY));
+        poLayer->SetExtent(
+            CPLAtof(pszMinX), CPLAtof(pszMinY), CPLAtof(pszMaxX),
+            CPLAtof(pszMaxY) );
     }
 
     CPLFree(pszWTKString);
diff --git a/ogr/ogrsf_frmts/idrisi/ogridrisidriver.cpp b/ogr/ogrsf_frmts/idrisi/ogridrisidriver.cpp
index 62881c7..2e70ef7 100644
--- a/ogr/ogrsf_frmts/idrisi/ogridrisidriver.cpp
+++ b/ogr/ogrsf_frmts/idrisi/ogridrisidriver.cpp
@@ -27,23 +27,19 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_idrisi.h"
 #include "cpl_conv.h"
+#include "ogr_idrisi.h"
+#include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: ogridrisidriver.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogridrisidriver.cpp 32745 2016-01-04 23:16:43Z goatbar $");
 
 // g++ ogr/ogrsf_frmts/idrisi/*.cpp -Wall -g -fPIC -shared -o ogr_Idrisi.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts/idrisi -Iogr/ogrsf_frmts -Ifrmts/idrisi
 
-extern "C" void RegisterOGRIdrisi();
-
 /************************************************************************/
 /*                       ~OGRIdrisiDriver()                         */
 /************************************************************************/
 
-OGRIdrisiDriver::~OGRIdrisiDriver()
-
-{
-}
+OGRIdrisiDriver::~OGRIdrisiDriver() {}
 
 /************************************************************************/
 /*                              GetName()                               */
@@ -73,7 +69,7 @@ OGRDataSource *OGRIdrisiDriver::Open( const char * pszFilename, int bUpdate )
     if ( !EQUAL(CPLGetExtension(pszFilename), "vct") )
         return NULL;
 
-    OGRIdrisiDataSource   *poDS = new OGRIdrisiDataSource();
+    OGRIdrisiDataSource *poDS = new OGRIdrisiDataSource();
 
     if( !poDS->Open( pszFilename ) )
     {
@@ -88,7 +84,7 @@ OGRDataSource *OGRIdrisiDriver::Open( const char * pszFilename, int bUpdate )
 /*                           TestCapability()                           */
 /************************************************************************/
 
-int OGRIdrisiDriver::TestCapability( CPL_UNUSED const char * pszCap )
+int OGRIdrisiDriver::TestCapability( const char * /* pszCap */ )
 {
     return FALSE;
 }
@@ -101,8 +97,7 @@ void RegisterOGRIdrisi()
 
 {
     OGRSFDriver* poDriver = new OGRIdrisiDriver;
-    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Idrisi Vector (.vct)" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Idrisi Vector (.vct)" );
     poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "vct" );
     poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
     OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver(poDriver);
diff --git a/ogr/ogrsf_frmts/idrisi/ogridrisilayer.cpp b/ogr/ogrsf_frmts/idrisi/ogridrisilayer.cpp
index ee2455e..0b696ad 100644
--- a/ogr/ogrsf_frmts/idrisi/ogridrisilayer.cpp
+++ b/ogr/ogrsf_frmts/idrisi/ogridrisilayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogridrisilayer.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogridrisilayer.cpp 32745 2016-01-04 23:16:43Z goatbar $
  *
  * Project:  Idrisi Translator
  * Purpose:  Implements OGRIdrisiLayer class.
@@ -27,13 +27,13 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_idrisi.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "ogr_idrisi.h"
 #include "ogr_p.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ogridrisilayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogridrisilayer.cpp 32745 2016-01-04 23:16:43Z goatbar $");
 
 /************************************************************************/
 /*                         OGRIdrisiLayer()                             */
@@ -41,27 +41,30 @@ CPL_CVSID("$Id: ogridrisilayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
 
 OGRIdrisiLayer::OGRIdrisiLayer( const char* pszFilename,
                                 const char* pszLayerName,
-                                VSILFILE* fp,
-                                OGRwkbGeometryType eGeomType,
-                                const char* pszWTKString )
-
+                                VSILFILE* fpIn,
+                                OGRwkbGeometryType eGeomTypeIn,
+                                const char* pszWTKString ) :
+    poFeatureDefn(new OGRFeatureDefn( pszLayerName )),
+    poSRS(NULL),
+    eGeomType(eGeomTypeIn),
+    fp(fpIn),
+    fpAVL(NULL),
+    bEOF(false),
+    nNextFID(1),
+    bExtentValid(false),
+    dfMinX(0.0),
+    dfMinY(0.0),
+    dfMaxX(0.0),
+    dfMaxY(0.0),
+    nTotalFeatures(0)
 {
-    this->fp = fp;
-    this->eGeomType = eGeomType;
-    nNextFID = 1;
-    bEOF = FALSE;
-    fpAVL = NULL;
-
     if (pszWTKString)
     {
         poSRS = new OGRSpatialReference();
-        char* pszTmp = (char*)pszWTKString;
+        char* pszTmp = const_cast<char *>(pszWTKString);
         poSRS->importFromWkt(&pszTmp);
     }
-    else
-        poSRS = NULL;
 
-    poFeatureDefn = new OGRFeatureDefn( pszLayerName );
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
     poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
@@ -70,9 +73,6 @@ OGRIdrisiLayer::OGRIdrisiLayer( const char* pszFilename,
     OGRFieldDefn oFieldDefn("id", OFTReal);
     poFeatureDefn->AddFieldDefn( &oFieldDefn );
 
-    bExtentValid = FALSE;
-    dfMinX = dfMinY = dfMaxX = dfMaxY = 0.0;
-
     VSIFSeekL( fp, 1, SEEK_SET );
     if (VSIFReadL( &nTotalFeatures, sizeof(unsigned int), 1, fp ) != 1)
         nTotalFeatures = 0;
@@ -170,7 +170,8 @@ int OGRIdrisiLayer::Detect_AVL_ADC(const char* pszFilename)
     const char* pszFields = CSLFetchNameValue( papszADC, "fields      " );
     if( pszFields == NULL || atoi(pszFields) <= 1 )
     {
-        CPLDebug("IDRISI", ".adc file found, but 'fields' not found or invalid");
+        CPLDebug( "IDRISI",
+                  ".adc file found, but 'fields' not found or invalid" );
         CSLDestroy( papszADC );
         return FALSE;
     }
@@ -195,15 +196,13 @@ int OGRIdrisiLayer::Detect_AVL_ADC(const char* pszFilename)
 //      Build layer definition
 // --------------------------------------------------------------------
 
-    int iCurField;
     char szKey[32];
-
-    iCurField = 0;
-    sprintf(szKey, "field %d ", iCurField);
+    int iCurField = 0;
+    snprintf(szKey, sizeof(szKey), "field %d ", iCurField);
 
     char** papszIter = papszADC;
     const char* pszLine;
-    int bFieldFound = FALSE;
+    bool bFieldFound = false;
     CPLString osFieldName;
     while((pszLine = *papszIter) != NULL)
     {
@@ -214,11 +213,11 @@ int OGRIdrisiLayer::Detect_AVL_ADC(const char* pszFilename)
             if (pszColon)
             {
                 osFieldName = pszColon + 1;
-                bFieldFound = TRUE;
+                bFieldFound = true;
             }
         }
         else if (bFieldFound &&
-                 strncmp(pszLine, "data type   :", strlen("data type   :")) == 0)
+                 STARTS_WITH(pszLine, "data type   :"))
         {
             const char* pszFieldType = pszLine + strlen("data type   :");
 
@@ -236,7 +235,7 @@ int OGRIdrisiLayer::Detect_AVL_ADC(const char* pszFilename)
                 poFeatureDefn->AddFieldDefn( &oFieldDefn );
 
             iCurField ++;
-            sprintf(szKey, "field %d ", iCurField);
+            snprintf(szKey, sizeof(szKey), "field %d ", iCurField);
         }
 
         papszIter++;
@@ -255,7 +254,7 @@ void OGRIdrisiLayer::ResetReading()
 
 {
     nNextFID = 1;
-    bEOF = FALSE;
+    bEOF = false;
     VSIFSeekL( fp, 0x105, SEEK_SET );
     if( fpAVL != NULL )
         VSIFSeekL( fpAVL, 0, SEEK_SET );
@@ -267,17 +266,15 @@ void OGRIdrisiLayer::ResetReading()
 
 OGRFeature *OGRIdrisiLayer::GetNextFeature()
 {
-    OGRFeature  *poFeature;
-
-    while(TRUE)
+    while( true )
     {
-        if (bEOF)
+        if( bEOF )
             return NULL;
 
-        poFeature = GetNextRawFeature();
+        OGRFeature *poFeature = GetNextRawFeature();
         if (poFeature == NULL)
         {
-            bEOF = TRUE;
+            bEOF = true;
             return NULL;
         }
 
@@ -315,12 +312,13 @@ int OGRIdrisiLayer::TestCapability( const char * pszCap )
 
 OGRFeature *OGRIdrisiLayer::GetNextRawFeature()
 {
-    while(TRUE)
+    while( true )
     {
         if (eGeomType == wkbPoint)
         {
             double dfId;
-            double dfX, dfY;
+            double dfX;
+            double dfY;
             if (VSIFReadL(&dfId, sizeof(double), 1, fp) != 1 ||
                 VSIFReadL(&dfX, sizeof(double), 1, fp) != 1 ||
                 VSIFReadL(&dfY, sizeof(double), 1, fp) != 1)
@@ -337,7 +335,7 @@ OGRFeature *OGRIdrisiLayer::GetNextRawFeature()
                  dfY < m_sFilterEnvelope.MinY ||
                  dfY > m_sFilterEnvelope.MaxY))
             {
-                nNextFID ++;
+                nNextFID++;
                 continue;
             }
 
@@ -354,7 +352,10 @@ OGRFeature *OGRIdrisiLayer::GetNextRawFeature()
         else if (eGeomType == wkbLineString)
         {
             double dfId;
-            double dfMinXShape, dfMaxXShape, dfMinYShape, dfMaxYShape;
+            double dfMinXShape;
+            double dfMaxXShape;
+            double dfMinYShape;
+            double dfMaxYShape;
             unsigned int nNodes;
 
             if (VSIFReadL(&dfId, sizeof(double), 1, fp) != 1 ||
@@ -391,13 +392,15 @@ OGRFeature *OGRIdrisiLayer::GetNextRawFeature()
                 continue;
             }
 
-            OGRRawPoint* poRawPoints = (OGRRawPoint*)VSIMalloc2(sizeof(OGRRawPoint), nNodes);
+            OGRRawPoint* poRawPoints = static_cast<OGRRawPoint *>(
+                VSI_MALLOC2_VERBOSE(sizeof(OGRRawPoint), nNodes) );
             if (poRawPoints == NULL)
             {
                 return NULL;
             }
 
-            if ((unsigned int)VSIFReadL(poRawPoints, sizeof(OGRRawPoint), nNodes, fp) != nNodes)
+            if (static_cast<unsigned int>(VSIFReadL(
+                    poRawPoints, sizeof(OGRRawPoint), nNodes, fp)) != nNodes)
             {
                 VSIFree(poRawPoints);
                 return NULL;
@@ -428,7 +431,10 @@ OGRFeature *OGRIdrisiLayer::GetNextRawFeature()
         else /* if (eGeomType == wkbPolygon) */
         {
             double dfId;
-            double dfMinXShape, dfMaxXShape, dfMinYShape, dfMaxYShape;
+            double dfMinXShape;
+            double dfMaxXShape;
+            double dfMinYShape;
+            double dfMaxYShape;
             unsigned int nParts;
             unsigned int nTotalNodes;
 
@@ -462,12 +468,14 @@ OGRFeature *OGRIdrisiLayer::GetNextRawFeature()
                  dfMaxYShape < m_sFilterEnvelope.MinY ||
                  dfMinYShape > m_sFilterEnvelope.MaxY))
             {
-                VSIFSeekL(fp, sizeof(unsigned int) * nParts + sizeof(OGRRawPoint) * nTotalNodes, SEEK_CUR);
+                VSIFSeekL(fp, sizeof(unsigned int) * nParts
+                          + sizeof(OGRRawPoint) * nTotalNodes, SEEK_CUR);
                 nNextFID ++;
                 continue;
             }
 
-            OGRRawPoint* poRawPoints = (OGRRawPoint*)VSIMalloc2(sizeof(OGRRawPoint), nTotalNodes);
+            OGRRawPoint* poRawPoints = static_cast<OGRRawPoint *>(
+                VSI_MALLOC2_VERBOSE(sizeof(OGRRawPoint), nTotalNodes) );
             if (poRawPoints == NULL)
             {
                 return NULL;
@@ -475,8 +483,10 @@ OGRFeature *OGRIdrisiLayer::GetNextRawFeature()
             unsigned int* panNodesCount = NULL;
             if( nParts > 1 )
             {
-                panNodesCount = (unsigned int *)CPLMalloc(sizeof(unsigned int) * nParts);
-                if (VSIFReadL(panNodesCount, sizeof(unsigned int) * nParts, 1, fp) != 1)
+                panNodesCount = static_cast<unsigned int *>(
+                    CPLMalloc( sizeof(unsigned int) * nParts ) );
+                if (VSIFReadL(panNodesCount, sizeof(unsigned int) * nParts, 1,
+                              fp) != 1)
                 {
                     VSIFree(poRawPoints);
                     VSIFree(panNodesCount);
@@ -505,13 +515,15 @@ OGRFeature *OGRIdrisiLayer::GetNextRawFeature()
                 }
             }
 
-            unsigned int iPart;
             OGRPolygon* poGeom = new OGRPolygon();
-            for(iPart = 0; iPart < nParts; iPart ++)
+            for( unsigned int iPart = 0; iPart < nParts; iPart++ )
             {
-                unsigned int nNodes = (nParts > 1) ? panNodesCount[iPart] : nTotalNodes;
+                unsigned int nNodes
+                    = (nParts > 1) ? panNodesCount[iPart] : nTotalNodes;
                 if (nNodes > nTotalNodes ||
-                    (unsigned int)VSIFReadL(poRawPoints, sizeof(OGRRawPoint), nNodes, fp) != nNodes)
+                    static_cast<unsigned int>(
+                        VSIFReadL(poRawPoints, sizeof(OGRRawPoint), nNodes, fp))
+                    != nNodes)
                 {
                     VSIFree(poRawPoints);
                     VSIFree(panNodesCount);
@@ -563,11 +575,10 @@ void OGRIdrisiLayer::ReadAVLLine(OGRFeature* poFeature)
     char** papszTokens = CSLTokenizeStringComplex(pszLine, "\t", TRUE, TRUE);
     if (CSLCount(papszTokens) == poFeatureDefn->GetFieldCount())
     {
-        int nID = atoi(papszTokens[0]);
+        const int nID = atoi(papszTokens[0]);
         if (nID == poFeature->GetFID())
         {
-            int i;
-            for(i=1;i<poFeatureDefn->GetFieldCount();i++)
+            for(int i=1;i<poFeatureDefn->GetFieldCount();i++)
             {
                 poFeature->SetField(i, papszTokens[i]);
             }
@@ -580,13 +591,14 @@ void OGRIdrisiLayer::ReadAVLLine(OGRFeature* poFeature)
 /*                             SetExtent()                              */
 /************************************************************************/
 
-void OGRIdrisiLayer::SetExtent(double dfMinX, double dfMinY, double dfMaxX, double dfMaxY)
+void OGRIdrisiLayer::SetExtent( double dfMinXIn, double dfMinYIn,
+                                double dfMaxXIn, double dfMaxYIn )
 {
-    bExtentValid = TRUE;
-    this->dfMinX = dfMinX;
-    this->dfMinY = dfMinY;
-    this->dfMaxX = dfMaxX;
-    this->dfMaxY = dfMaxY;
+    bExtentValid = true;
+    this->dfMinX = dfMinXIn;
+    this->dfMinY = dfMinYIn;
+    this->dfMaxX = dfMaxXIn;
+    this->dfMaxY = dfMaxYIn;
 }
 
 /************************************************************************/
@@ -595,7 +607,7 @@ void OGRIdrisiLayer::SetExtent(double dfMinX, double dfMinY, double dfMaxX, doub
 
 OGRErr OGRIdrisiLayer::GetExtent(OGREnvelope *psExtent, int bForce)
 {
-    if (!bExtentValid)
+    if( !bExtentValid )
         return OGRLayer::GetExtent(psExtent, bForce);
 
     psExtent->MinX = dfMinX;
diff --git a/ogr/ogrsf_frmts/ili/drv_ili.html b/ogr/ogrsf_frmts/ili/drv_ili.html
index 6eb15b2..1b865fe 100644
--- a/ogr/ogrsf_frmts/ili/drv_ili.html
+++ b/ogr/ogrsf_frmts/ili/drv_ili.html
@@ -8,7 +8,7 @@
 <h1>INTERLIS</h1>
 
 OGR has support for INTERLIS reading and writing.<br>
-<a href="http://www.interlis.ch/">INTERLIS</a> is a standard which has been especially composed in order to fulfil the requirements of modelling and the integration of geodata into contemporary and future geographic information systems.
+<a href="http://www.interlis.ch/">INTERLIS</a> is a standard which has been especially composed in order to fulfill the requirements of modeling and the integration of geodata into contemporary and future geographic information systems.
 
 With the usage of unified, documented geodata and the flexible exchange possibilities the following advantage may occur:
 <ul>
@@ -22,10 +22,10 @@ With the usage of unified, documented geodata and the flexible exchange possibil
 
 OGR supports INTERLIS 1 and INTERLIS 2 (2.2 and 2.3) with the following limitations:
 <ul>
-<li>Curves in Interlis 1 areas are converted to line segments</li>
-<li>Embedded INTERLIS 2 structures are not supported</li>
-<li>Incremental transfer is not supported</li>
+<li>Curves in Interlis 1 area polygons are converted to line segments</li>
 <li>Interlis 1 Surface geometries with non-numeric IDENT field are not included in the attribute layer</li>
+<li>Embedded INTERLIS 2 structures and line attributes are not supported</li>
+<li>Incremental transfer is not supported</li>
 <li>Transfer id (TID) is used as feature id</li>
 </ul>
 
@@ -40,7 +40,7 @@ IlisMeta files can be be generated with the ili2c compiler. Command line example
 java -jar ili2c.jar --ilidirs '%ILI_DIR;http://models.interlis.ch/;%JAR_DIR' -oIMD --out models.imd model1.ili [model2.ili ...]
 </pre>
 
-Some possible transformations using <a href="http://www.gdal.org/ogr/ogr2ogr.html">ogr2ogr</a>.<p>
+Some possible transformations using <a href="http://www.gdal.org/ogr2ogr.html">ogr2ogr</a>.<p>
 <ul>
 <li>
 Interlis 1 -> Shape:
@@ -83,13 +83,13 @@ ogr2ogr -f PostgreSQL PG:dbname=warmerda av_fixpunkte_mit_LFPNachfuehrung.itf,av
 <p>
 
 <h3>Arc interpolation</h3>
-Converting INTERLIS arc geometries to line segements can be forced by setting the configuration
-variable OGR_STROKE_CURVE to TRUE.<br></br>
-The approximation of arcs as linestrings is done by splitting the arcs into subarcs of no more than a
-threshhold angle. This angle is the OGR_ARC_STEPSIZE. This defaults to
-one degree, but may be overridden by setting the configuration variable
-OGR_ARC_STEPSIZE.<br></br>
+Converting INTERLIS arc geometries to line segments can be forced by setting
+the configuration variable OGR_STROKE_CURVE to TRUE.<br></br>
 
+The approximation of arcs as linestrings is done by splitting the arcs into
+subarcs of no more than a threshold angle. This angle is the
+OGR_ARC_STEPSIZE. This defaults to one degree, but may be overridden by
+setting the configuration variable OGR_ARC_STEPSIZE.<br></br>
 
 <h3>OGR versions prior to 2.0</h3>
 
@@ -97,17 +97,17 @@ Arcs are always interpolated and the interpolation angle can be configured with
 
 <h3>OGR versions prior to 1.11</h3>
 
-For using the INTERLIS model (.ili) a Java interpreter is needed at runtime and ili2c.jar (included in the 
+For using the INTERLIS model (.ili) a Java interpreter is needed at runtime and ili2c.jar (included in the
 <a href="http://interlis.ch/interlis2/download23_e.php#outils">Compiler for INTERLIS 2</a>) must be in the Java path.<p>
 
 
 <h2>Other Notes</h2>
 <ul>
 <li><a href="https://github.com/sourcepole/ogrtools">ogrtools</a> library includes extensions for the OGR Interlis driver</li>
-<li>Development of the OGR INTERLIS driver was supported by 
-<a href="http://www.kogis.ch/">Swiss Federal Administration</a>,  
-<a href="http://www.sogis.ch/">Canton Solothurn</a> and 
-<a href="http://www.geoinformation.tg.ch/">Canton Thurgovia</a>.</li> 
+<li>Development of the OGR INTERLIS driver was supported by
+<a href="http://www.kogis.ch/">Swiss Federal Administration</a>,
+<a href="http://www.sogis.ch/">Canton Solothurn</a> and
+<a href="http://www.geoinformation.tg.ch/">Canton Thurgovia</a>.</li>
 </ul>
 
 </body>
diff --git a/ogr/ogrsf_frmts/ili/ili1reader.cpp b/ogr/ogrsf_frmts/ili/ili1reader.cpp
index 2d7ede8..8ada9db 100644
--- a/ogr/ogrsf_frmts/ili/ili1reader.cpp
+++ b/ogr/ogrsf_frmts/ili/ili1reader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ili1reader.cpp 33076 2016-01-22 09:45:53Z pka $
+ * $Id: ili1reader.cpp 33829 2016-03-31 16:21:01Z rouault $
  *
  * Project:  Interlis 1 Reader
  * Purpose:  Implementation of ILI1Reader class.
@@ -28,10 +28,10 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_ili1.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
 #include "ogr_api.h"
+#include "ogr_ili1.h"
 #include "ogr_geos.h"
 
 #include "ili1reader.h"
@@ -45,33 +45,32 @@
 
 #ifndef POLYGONIZE_AREAS
 #  if defined(__GNUC_PREREQ)
-#    warning Interlis 1 Area polygonizing disabled. Needs GEOS >= 3.1.0
+//#    warning Interlis 1 Area polygonizing disabled. Needs GEOS >= 3.1.0
 #  endif
 #endif
 
-CPL_CVSID("$Id: ili1reader.cpp 33076 2016-01-22 09:45:53Z pka $");
+CPL_CVSID("$Id: ili1reader.cpp 33829 2016-03-31 16:21:01Z rouault $");
 
 //
 // ILI1Reader
 //
-IILI1Reader::~IILI1Reader() {
-}
-
-ILI1Reader::ILI1Reader() {
-  fpItf = NULL;
-  nLayers = 0;
-  papoLayers = NULL;
-  curLayer = NULL;
-  codeBlank = '_';
-  codeUndefined = '@';
-  codeContinue = '\\';
-}
-
-ILI1Reader::~ILI1Reader() {
-  int i;
+IILI1Reader::~IILI1Reader() {}
+
+ILI1Reader::ILI1Reader() :
+  fpItf(NULL),
+  nLayers(0),
+  papoLayers(NULL),
+  curLayer(NULL),
+  codeBlank('_'),
+  codeUndefined('@'),
+  codeContinue('\\')
+{}
+
+ILI1Reader::~ILI1Reader()
+{
   if (fpItf) VSIFClose( fpItf );
 
-  for(i=0;i<nLayers;i++)
+  for( int i=0; i < nLayers; i++)
      delete papoLayers[i];
   CPLFree(papoLayers);
 }
@@ -79,7 +78,8 @@ ILI1Reader::~ILI1Reader() {
 /* -------------------------------------------------------------------- */
 /*      Open the source file.                                           */
 /* -------------------------------------------------------------------- */
-int ILI1Reader::OpenFile( const char *pszFilename ) {
+int ILI1Reader::OpenFile( const char *pszFilename )
+{
     fpItf = VSIFOpen( pszFilename, "r" );
     if( fpItf == NULL )
     {
@@ -92,31 +92,48 @@ int ILI1Reader::OpenFile( const char *pszFilename ) {
     return TRUE;
 }
 
-const char* ILI1Reader::GetLayerNameString(const char* topicname, const char* tablename) {
+const char* ILI1Reader::GetLayerNameString( const char* topicname,
+                                            const char* tablename)
+{
 
     return CPLSPrintf("%s__%s", topicname, tablename);
 }
 
-int ILI1Reader::ReadModel(ImdReader *poImdReader, const char *pszModelFilename, OGRILI1DataSource *poDS) {
+int ILI1Reader::ReadModel( ImdReader *poImdReader,
+                           const char *pszModelFilename,
+                           OGRILI1DataSource *poDS)
+{
 
   poImdReader->ReadModel(pszModelFilename);
   for (FeatureDefnInfos::const_iterator it = poImdReader->featureDefnInfos.begin(); it != poImdReader->featureDefnInfos.end(); ++it)
   {
-    //CPLDebug( "OGR_ILI", "Adding OGRILI1Layer with table '%s'", it->poTableDefn->GetName() );
-    OGRILI1Layer* layer = new OGRILI1Layer(it->poTableDefn, it->poGeomFieldInfos, poDS);
+#if DEBUG_VERBOSE
+    CPLDebug( "OGR_ILI", "Adding OGRILI1Layer with table '%s'",
+              it->poTableDefn->GetName() );
+#endif
+    OGRILI1Layer* layer = new OGRILI1Layer( it->GetTableDefnRef(),
+                                            it->poGeomFieldInfos, poDS);
     AddLayer(layer);
-    //Create additional layers for surface and area geometries
-    for (GeomFieldInfos::const_iterator it2 = it->poGeomFieldInfos.begin(); it2 != it->poGeomFieldInfos.end(); ++it2)
+    // Create additional layers for surface and area geometries.
+    for (GeomFieldInfos::const_iterator it2 = it->poGeomFieldInfos.begin();
+         it2 != it->poGeomFieldInfos.end();
+         ++it2)
     {
-      if (it2->second.geomTable)
+      if (it2->second.GetGeomTableDefnRef())
       {
-        OGRFeatureDefn* poGeomTableDefn = it2->second.geomTable;
-        OGRGeomFieldDefn* poOGRGeomFieldDefn = poGeomTableDefn->GetGeomFieldDefn(0);
+        OGRFeatureDefn* poGeomTableDefn = it2->second.GetGeomTableDefnRef();
+        OGRGeomFieldDefn* poOGRGeomFieldDefn
+            = poGeomTableDefn->GetGeomFieldDefn(0);
         GeomFieldInfos oGeomFieldInfos;
         // We add iliGeomType to recognize Ili1 geom tables
-        oGeomFieldInfos[poOGRGeomFieldDefn->GetNameRef()].iliGeomType = it2->second.iliGeomType;
-        //CPLDebug( "OGR_ILI", "Adding OGRILI1Layer with geometry table '%s'", it2->second.geomTable->GetName() );
-        OGRILI1Layer* geomlayer = new OGRILI1Layer(poGeomTableDefn, oGeomFieldInfos, poDS);
+        oGeomFieldInfos[poOGRGeomFieldDefn->GetNameRef()].iliGeomType
+            = it2->second.iliGeomType;
+#if DEBUG_VERBOSE
+        CPLDebug( "OGR_ILI", "Adding OGRILI1Layer with geometry table '%s'",
+                  it2->second.geomTable->GetName() );
+#endif
+        OGRILI1Layer* geomlayer
+            = new OGRILI1Layer(poGeomTableDefn, oGeomFieldInfos, poDS);
         AddLayer(geomlayer);
       }
     }
@@ -125,22 +142,23 @@ int ILI1Reader::ReadModel(ImdReader *poImdReader, const char *pszModelFilename,
   codeBlank = poImdReader->codeBlank;
   CPLDebug( "OGR_ILI", "Ili1Format blankCode '%c'", poImdReader->codeBlank );
   codeUndefined = poImdReader->codeUndefined;
-  CPLDebug( "OGR_ILI", "Ili1Format undefinedCode '%c'", poImdReader->codeUndefined );
+  CPLDebug( "OGR_ILI", "Ili1Format undefinedCode '%c'",
+            poImdReader->codeUndefined );
   codeContinue = poImdReader->codeContinue;
-  CPLDebug( "OGR_ILI", "Ili1Format continueCode '%c'", poImdReader->codeContinue );
+  CPLDebug( "OGR_ILI", "Ili1Format continueCode '%c'",
+            poImdReader->codeContinue );
   return 0;
 }
 
 int ILI1Reader::ReadFeatures() {
     char **tokens = NULL;
-    const char *firsttok = NULL;
-    const char *pszLine;
-    char *topic = NULL;
+    const char *pszLine = NULL;
+    char *topic = CPLStrdup("(null)");
     int ret = TRUE;
 
-    while (ret && (tokens = ReadParseLine()))
+    while (ret && (tokens = ReadParseLine()) != NULL)
     {
-      firsttok = tokens[0];
+      const char *firsttok = tokens[0];
       if (EQUAL(firsttok, "SCNT"))
       {
         //read description
@@ -148,7 +166,7 @@ int ILI1Reader::ReadFeatures() {
         {
           pszLine = CPLReadLine( fpItf );
         }
-        while (pszLine && !EQUALN(pszLine, "////", 4));
+        while (pszLine && !STARTS_WITH_CI(pszLine, "////"));
         ret = (pszLine != NULL);
       }
       else if (EQUAL(firsttok, "MOTR"))
@@ -158,7 +176,7 @@ int ILI1Reader::ReadFeatures() {
         {
           pszLine = CPLReadLine( fpItf );
         }
-        while (pszLine && !EQUALN(pszLine, "////", 4));
+        while (pszLine && !STARTS_WITH_CI(pszLine, "////"));
         ret = (pszLine != NULL);
       }
       else if (EQUAL(firsttok, "MTID"))
@@ -167,21 +185,25 @@ int ILI1Reader::ReadFeatures() {
       else if (EQUAL(firsttok, "MODL"))
       {
       }
-      else if (EQUAL(firsttok, "TOPI"))
+      else if (EQUAL(firsttok, "TOPI") && CSLCount(tokens) >= 2)
       {
         CPLFree(topic);
         topic = CPLStrdup(CSLGetField(tokens, 1));
       }
-      else if (EQUAL(firsttok, "TABL"))
+      else if (EQUAL(firsttok, "TABL") && CSLCount(tokens) >= 2)
       {
-        const char *layername = GetLayerNameString(topic, CSLGetField(tokens, 1));
+        const char *layername
+            = GetLayerNameString(topic, CSLGetField(tokens, 1));
         CPLDebug( "OGR_ILI", "Reading table '%s'", layername );
         curLayer = GetLayerByName(layername);
 
         if (curLayer == NULL) { //create one
-          CPLError(CE_Warning, CPLE_AppDefined,
-              "No model definition for table '%s' found, using default field names.", layername );
-          OGRFeatureDefn* poFeatureDefn = new OGRFeatureDefn(GetLayerNameString(topic, CSLGetField(tokens, 1)));
+          CPLError( CE_Warning, CPLE_AppDefined,
+                    "No model definition for table '%s' found, "
+                    "using default field names.", layername );
+          OGRFeatureDefn* poFeatureDefn
+            = new OGRFeatureDefn(
+                GetLayerNameString(topic, CSLGetField(tokens, 1)));
           poFeatureDefn->SetGeomType( wkbUnknown );
           GeomFieldInfos oGeomFieldInfos;
           curLayer = new OGRILI1Layer(poFeatureDefn, oGeomFieldInfos, NULL);
@@ -189,7 +211,8 @@ int ILI1Reader::ReadFeatures() {
         }
         if(curLayer != NULL) {
           for (int i=0; i < curLayer->GetLayerDefn()->GetFieldCount(); i++) {
-            CPLDebug( "OGR_ILI", "Field %d: %s", i,  curLayer->GetLayerDefn()->GetFieldDefn(i)->GetNameRef());
+            CPLDebug( "OGR_ILI", "Field %d: %s", i,
+                      curLayer->GetLayerDefn()->GetFieldDefn(i)->GetNameRef());
           }
         }
         ret = ReadTable(layername);
@@ -208,7 +231,8 @@ int ILI1Reader::ReadFeatures() {
       }
       else
       {
-        CPLError(CE_Warning, CPLE_AppDefined, "Unexpected token: %s", firsttok );
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Unexpected token: %s", firsttok );
       }
 
       CSLDestroy(tokens);
@@ -223,46 +247,56 @@ int ILI1Reader::ReadFeatures() {
 
 int ILI1Reader::ReadTable(CPL_UNUSED const char *layername) {
     char **tokens = NULL;
-    const char *firsttok = NULL;
     int ret = TRUE;
     int warned = FALSE;
-    int fIndex;
     int geomIdx = -1;
 
     OGRFeatureDefn *featureDef = curLayer->GetLayerDefn();
     OGRFeature *feature = NULL;
+    bool bFeatureAdded = false;
 
-    while (ret && (tokens = ReadParseLine()))
+    while (ret && (tokens = ReadParseLine()) != NULL)
     {
-      firsttok = CSLGetField(tokens, 0);
+      const char *firsttok = CSLGetField(tokens, 0);
       if (EQUAL(firsttok, "OBJE"))
       {
         if (featureDef->GetFieldCount() == 0)
         {
-          CPLError(CE_Warning, CPLE_AppDefined,
-              "No field definition found for table: %s", featureDef->GetName() );
-          //Model not read - use heuristics
-          for (fIndex=1; fIndex<CSLCount(tokens); fIndex++)
+          CPLError( CE_Warning, CPLE_AppDefined,
+                    "No field definition found for table: %s",
+                    featureDef->GetName() );
+          // Model not read - use heuristics.
+          for( int fIndex=1; fIndex<CSLCount(tokens); fIndex++ )
           {
             char szFieldName[32];
-            sprintf(szFieldName, "Field%02d", fIndex);
+            snprintf(szFieldName, sizeof(szFieldName), "Field%02d", fIndex);
             OGRFieldDefn oFieldDefn(szFieldName, OFTString);
             featureDef->AddFieldDefn(&oFieldDefn);
           }
         }
         //start new feature
+        if( !bFeatureAdded )
+            delete feature;
         feature = new OGRFeature(featureDef);
 
-        int fieldno = 0;
-        for (fIndex=1; fIndex<CSLCount(tokens) && fieldno < featureDef->GetFieldCount(); fIndex++, fieldno++)
+        for( int fIndex=1, fieldno = 0;
+             fIndex<CSLCount(tokens) && fieldno < featureDef->GetFieldCount();
+             fIndex++, fieldno++ )
         {
           if (!(tokens[fIndex][0] == codeUndefined && tokens[fIndex][1] == '\0')) {
-            //CPLDebug( "READ TABLE OGR_ILI", "Setting Field %d (Type %d): %s", fieldno, featureDef->GetFieldDefn(fieldno)->GetType(), tokens[fIndex]);
+#ifdef DEBUG_VERBOSE
+            CPLDebug( "READ TABLE OGR_ILI", "Setting Field %d (Type %d): %s",
+                      fieldno, featureDef->GetFieldDefn(fieldno)->GetType(),
+                      tokens[fIndex] );
+#endif
             if (featureDef->GetFieldDefn(fieldno)->GetType() == OFTString) {
-                //Interlis 1 encoding is ISO 8859-1 (Latin1) -> Recode to UTF-8
-                char* pszRecoded = CPLRecode(tokens[fIndex], CPL_ENC_ISO8859_1, CPL_ENC_UTF8);
-                //Replace space marks
-                for(char* pszString = pszRecoded; *pszString != '\0'; pszString++ ) {
+                // Interlis 1 encoding is ISO 8859-1 (Latin1) -> Recode to UTF-8
+                char* pszRecoded = CPLRecode(
+                    tokens[fIndex], CPL_ENC_ISO8859_1, CPL_ENC_UTF8);
+                // Replace space marks
+                for( char* pszString = pszRecoded;
+                     *pszString != '\0';
+                     pszString++ ) {
                     if (*pszString == codeBlank) *pszString = ' ';
                 }
                 feature->SetField(fieldno, pszRecoded);
@@ -273,31 +307,42 @@ int ILI1Reader::ReadTable(CPL_UNUSED const char *layername) {
             if (featureDef->GetFieldDefn(fieldno)->GetType() == OFTReal
                 && fieldno > 0
                 && featureDef->GetFieldDefn(fieldno-1)->GetType() == OFTReal) {
-              //check for Point geometry (Coord type)
-              // if there is no ili model read,
+              // Check for Point geometry (Coord type).
+              // If there is no ili model read,
               // we have no chance to detect the
-              // geometry column!!
-              CPLString geomfldname = featureDef->GetFieldDefn(fieldno)->GetNameRef();
-              //Check if name ends with _1
-              if (geomfldname.size() >= 2 && geomfldname[geomfldname.size()-2] == '_') {
+              // geometry column.
+              CPLString geomfldname
+                  = featureDef->GetFieldDefn(fieldno)->GetNameRef();
+              // Check if name ends with _1.
+              if (geomfldname.size() >= 2 && geomfldname[geomfldname.size()-2]
+                  == '_') {
                 geomfldname = geomfldname.substr(0, geomfldname.size()-2);
                 geomIdx = featureDef->GetGeomFieldIndex(geomfldname.c_str());
                 if (geomIdx == -1)
                 {
-                  CPLError(CE_Warning, CPLE_AppDefined,
-                      "No matching definition for field '%s' of table %s found", geomfldname.c_str(), featureDef->GetName());
+                  CPLError( CE_Warning, CPLE_AppDefined,
+                            "No matching definition for field '%s' of "
+                            "table %s found",
+                            geomfldname.c_str(), featureDef->GetName() );
                 }
               } else {
                 geomIdx = -1;
               }
               if (geomIdx >= 0) {
-                if (featureDef->GetGeomFieldDefn(geomIdx)->GetType() == wkbPoint) {
-                  //add Point geometry
-                  OGRPoint *ogrPoint = new OGRPoint(CPLAtof(tokens[fIndex-1]), CPLAtof(tokens[fIndex]));
+                if (featureDef->GetGeomFieldDefn(geomIdx)->GetType() ==
+                    wkbPoint) {
+                  // Add Point geometry.
+                  OGRPoint *ogrPoint = new OGRPoint(
+                      CPLAtof(tokens[fIndex-1]), CPLAtof(tokens[fIndex]));
                   feature->SetGeomFieldDirectly(geomIdx, ogrPoint);
-                } else if (featureDef->GetGeomFieldDefn(geomIdx)->GetType() == wkbPoint25D && fieldno > 1 && featureDef->GetFieldDefn(fieldno-2)->GetType() == OFTReal) {
-                  //add 3D Point geometry
-                  OGRPoint *ogrPoint = new OGRPoint(CPLAtof(tokens[fIndex-2]), CPLAtof(tokens[fIndex-1]), CPLAtof(tokens[fIndex]));
+                } else if (featureDef->GetGeomFieldDefn(geomIdx)->GetType() ==
+                           wkbPoint25D && fieldno > 1 &&
+                           featureDef->GetFieldDefn(fieldno-2)->GetType() ==
+                           OFTReal) {
+                  // Add 3D Point geometry.
+                  OGRPoint *ogrPoint = new OGRPoint(
+                      CPLAtof(tokens[fIndex-2]), CPLAtof(tokens[fIndex-1]),
+                      CPLAtof(tokens[fIndex]) );
                   feature->SetGeomFieldDirectly(geomIdx, ogrPoint);
                 }
               }
@@ -305,34 +350,47 @@ int ILI1Reader::ReadTable(CPL_UNUSED const char *layername) {
           }
         }
         if (!warned && featureDef->GetFieldCount() != CSLCount(tokens)-1) {
-          CPLError(CE_Warning, CPLE_AppDefined,
-              "Field count of table %s doesn't match. %d declared, %d found (e.g. ignored LINEATTR)", featureDef->GetName(), featureDef->GetFieldCount(), CSLCount(tokens)-1);
+          CPLError( CE_Warning, CPLE_AppDefined,
+                    "Field count of table %s doesn't match. %d declared, "
+                    "%d found (e.g. ignored LINEATTR)",
+                    featureDef->GetName(), featureDef->GetFieldCount(),
+                    CSLCount(tokens) - 1 );
           warned = TRUE;
         }
         if (feature->GetFieldCount() > 0) {
-          // USE _TID as FID. TODO: respect IDENT field from model
+          // USE _TID as FID. TODO: respect IDENT field from model.
           feature->SetFID(feature->GetFieldAsInteger64(0));
         }
         curLayer->AddFeature(feature);
+        bFeatureAdded = true;
         geomIdx = -1; //Reset
       }
-      else if (EQUAL(firsttok, "STPT"))
+      else if (EQUAL(firsttok, "STPT") && feature != NULL)
       {
         //Find next non-Point geometry
         if (geomIdx < 0) geomIdx = 0;
-        while (geomIdx < featureDef->GetGeomFieldCount() && featureDef->GetGeomFieldDefn(geomIdx)->GetType() == wkbPoint) { geomIdx++; }
-        OGRwkbGeometryType geomType = (geomIdx < featureDef->GetGeomFieldCount()) ? featureDef->GetGeomFieldDefn(geomIdx)->GetType() : wkbNone;
+        while (geomIdx < featureDef->GetGeomFieldCount() &&
+               featureDef->GetGeomFieldDefn(geomIdx)->GetType() == wkbPoint) {
+            geomIdx++;
+        }
+        OGRwkbGeometryType geomType
+            = (geomIdx < featureDef->GetGeomFieldCount()) ?
+               featureDef->GetGeomFieldDefn(geomIdx)->GetType() : wkbNone;
         ReadGeom(tokens, geomIdx, geomType, feature);
       }
       else if (EQUAL(firsttok, "ELIN"))
       {
-        //empty geom
+        // Empty geom.
       }
-      else if (EQUAL(firsttok, "EDGE"))
+      else if (EQUAL(firsttok, "EDGE") && feature != NULL)
       {
+        CSLDestroy(tokens);
         tokens = ReadParseLine(); //STPT
         //Find next non-Point geometry
-        do { geomIdx++; } while (geomIdx < featureDef->GetGeomFieldCount() && featureDef->GetGeomFieldDefn(geomIdx)->GetType() == wkbPoint);
+        do {
+            geomIdx++;
+        } while (geomIdx < featureDef->GetGeomFieldCount() &&
+                 featureDef->GetGeomFieldDefn(geomIdx)->GetType() == wkbPoint);
         ReadGeom(tokens, geomIdx, wkbMultiLineString, feature);
       }
       else if (EQUAL(firsttok, "PERI"))
@@ -340,41 +398,46 @@ int ILI1Reader::ReadTable(CPL_UNUSED const char *layername) {
       }
       else if (EQUAL(firsttok, "ETAB"))
       {
-        CPLDebug( "OGR_ILI", "Total features: " CPL_FRMT_GIB, curLayer->GetFeatureCount() );
+        CPLDebug( "OGR_ILI", "Total features: " CPL_FRMT_GIB,
+                  curLayer->GetFeatureCount() );
         CSLDestroy(tokens);
+        if( !bFeatureAdded )
+            delete feature;
         return TRUE;
       }
       else
       {
-        CPLError(CE_Warning, CPLE_AppDefined, "Unexpected token: %s", firsttok );
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Unexpected token: %s", firsttok );
       }
 
       CSLDestroy(tokens);
     }
 
+    if( !bFeatureAdded )
+        delete feature;
+
     return ret;
 }
 
-void ILI1Reader::ReadGeom(char **stgeom, int geomIdx, OGRwkbGeometryType eType, OGRFeature *feature) {
-    char **tokens = NULL;
-    const char *firsttok = NULL;
-    int end = FALSE;
-    OGRCompoundCurve *ogrCurve = NULL; //current compound curve
-    OGRLineString *ogrLine = NULL; //current line
-    OGRCircularString *arc = NULL; //current arc
-    OGRCurvePolygon *ogrPoly = NULL; //current polygon
-    OGRPoint ogrPoint; //current point
-    OGRMultiCurve *ogrMultiLine = NULL; //current multi line
-
-    //CPLDebug( "OGR_ILI", "ILI1Reader::ReadGeom geomIdx: %d OGRGeometryType: %s", geomIdx, OGRGeometryTypeToName(eType));
+void ILI1Reader::ReadGeom( char **stgeom, int geomIdx, OGRwkbGeometryType eType,
+                           OGRFeature *feature ) {
+#ifdef DEBUG_VERBOSE
+    CPLDebug( "OGR_ILI",
+              "ILI1Reader::ReadGeom geomIdx: %d OGRGeometryType: %s",
+              geomIdx, OGRGeometryTypeToName(eType) );
+#endif
     if (eType == wkbNone)
     {
-      CPLError(CE_Warning, CPLE_AppDefined, "Calling ILI1Reader::ReadGeom with wkbNone" );
+      CPLError( CE_Warning, CPLE_AppDefined,
+                "Calling ILI1Reader::ReadGeom with wkbNone" );
     }
 
-    //Initialize geometry
+    // Initialize geometry.
 
-    ogrCurve = new OGRCompoundCurve();
+    OGRCompoundCurve *ogrCurve = new OGRCompoundCurve();
+    OGRCurvePolygon *ogrPoly = NULL; //current polygon
+    OGRMultiCurve *ogrMultiLine = NULL; //current multi line
 
     if (eType == wkbMultiCurve || eType == wkbMultiLineString)
     {
@@ -385,15 +448,21 @@ void ILI1Reader::ReadGeom(char **stgeom, int geomIdx, OGRwkbGeometryType eType,
       ogrPoly = new OGRCurvePolygon();
     }
 
-    //tokens = ["STPT", "1111", "22222"]
+    OGRPoint ogrPoint; // Current point.
     ogrPoint.setX(CPLAtof(stgeom[1])); ogrPoint.setY(CPLAtof(stgeom[2]));
-    ogrLine = new OGRLineString();
+
+    OGRLineString *ogrLine = new OGRLineString();
     ogrLine->addPoint(&ogrPoint);
 
-    //Parse geometry
-    while (!end && (tokens = ReadParseLine()))
+    // Parse geometry.
+
+    char **tokens = NULL;
+    bool end = false;
+    OGRCircularString *arc = NULL; //current arc
+
+    while (!end && (tokens = ReadParseLine()) != NULL)
     {
-      firsttok = CSLGetField(tokens, 0);
+      const char *firsttok = CSLGetField(tokens, 0);
       if (EQUAL(firsttok, "LIPT"))
       {
         ogrPoint.setX(CPLAtof(tokens[1])); ogrPoint.setY(CPLAtof(tokens[2]));
@@ -431,6 +500,7 @@ void ILI1Reader::ReadGeom(char **stgeom, int geomIdx, OGRwkbGeometryType eType,
           if (error != OGRERR_NONE) {
             CPLError(CE_Warning, CPLE_AppDefined, "Added geometry: %s", ogrLine->exportToJson() );
           }
+          ogrLine = NULL;
         }
         if (!ogrCurve->IsEmpty()) {
           if (ogrMultiLine)
@@ -439,6 +509,7 @@ void ILI1Reader::ReadGeom(char **stgeom, int geomIdx, OGRwkbGeometryType eType,
             if (error != OGRERR_NONE) {
               CPLError(CE_Warning, CPLE_AppDefined, "Added geometry: %s", ogrCurve->exportToJson() );
             }
+            ogrCurve = NULL;
           }
           if (ogrPoly)
           {
@@ -446,13 +517,14 @@ void ILI1Reader::ReadGeom(char **stgeom, int geomIdx, OGRwkbGeometryType eType,
             if (error != OGRERR_NONE) {
               CPLError(CE_Warning, CPLE_AppDefined, "Added geometry: %s", ogrCurve->exportToJson() );
             }
+            ogrCurve = NULL;
           }
         }
-        end = TRUE;
+        end = true;
       }
       else if (EQUAL(firsttok, "EEDG"))
       {
-        end = TRUE;
+        end = true;
       }
       else if (EQUAL(firsttok, "LATT"))
       {
@@ -460,38 +532,45 @@ void ILI1Reader::ReadGeom(char **stgeom, int geomIdx, OGRwkbGeometryType eType,
       }
       else if (EQUAL(firsttok, "EFLA"))
       {
-        end = TRUE;
+        end = true;
       }
       else if (EQUAL(firsttok, "ETAB"))
       {
-        end = TRUE;
+        end = true;
       }
       else
       {
-        CPLError(CE_Warning, CPLE_AppDefined, "Unexpected token: %s", firsttok );
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Unexpected token: %s", firsttok );
       }
 
       CSLDestroy(tokens);
     }
 
+    delete ogrLine;
+
     //Set feature geometry
     if (eType == wkbMultiCurve)
     {
       feature->SetGeomFieldDirectly(geomIdx, ogrMultiLine);
+      delete ogrCurve;
     }
     else if (eType == wkbMultiLineString)
     {
       feature->SetGeomFieldDirectly(geomIdx, ogrMultiLine->getLinearGeometry());
       delete ogrMultiLine;
+      delete ogrCurve;
     }
     else if (eType == wkbCurvePolygon)
     {
       feature->SetGeomFieldDirectly(geomIdx, ogrPoly);
+      delete ogrCurve;
     }
     else if (eType == wkbPolygon)
     {
       feature->SetGeomFieldDirectly(geomIdx, ogrPoly->getLinearGeometry());
       delete ogrPoly;
+      delete ogrCurve;
     }
     else
     {
@@ -508,8 +587,8 @@ void ILI1Reader::AddLayer( OGRILI1Layer * poNewLayer )
 {
     nLayers++;
 
-    papoLayers = (OGRILI1Layer **)
-        CPLRealloc( papoLayers, sizeof(void*) * nLayers );
+    papoLayers = static_cast<OGRILI1Layer **>(
+        CPLRealloc( papoLayers, sizeof(void*) * nLayers ) );
 
     papoLayers[nLayers-1] = poNewLayer;
 }
@@ -523,8 +602,8 @@ OGRILI1Layer *ILI1Reader::GetLayer( int iLayer )
 {
     if( iLayer < 0 || iLayer >= nLayers )
         return NULL;
-    else
-        return papoLayers[iLayer];
+
+    return papoLayers[iLayer];
 }
 
 OGRILI1Layer *ILI1Reader::GetLayerByName( const char* pszLayerName )
@@ -556,23 +635,18 @@ int ILI1Reader::GetLayerCount()
 
 char ** ILI1Reader::ReadParseLine()
 {
-    const char  *pszLine;
-    char **tokens;
-    char **conttok;
-    char *token;
-
     CPLAssert( fpItf != NULL );
     if( fpItf == NULL )
         return( NULL );
 
-    pszLine = CPLReadLine( fpItf );
+    const char  *pszLine = CPLReadLine( fpItf );
     if( pszLine == NULL )
         return( NULL );
 
     if (strlen(pszLine) == 0) return NULL;
 
-    tokens = CSLTokenizeString2( pszLine, " ", CSLT_PRESERVEESCAPES );
-    token = tokens[CSLCount(tokens)-1];
+    char **tokens = CSLTokenizeString2( pszLine, " ", CSLT_PRESERVEESCAPES );
+    char *token = tokens[CSLCount(tokens)-1];
 
     //Append CONT lines
     while (strlen(pszLine) && token[0] == codeContinue && token[1] == '\0')
@@ -582,7 +656,11 @@ char ** ILI1Reader::ReadParseLine()
       tokens[CSLCount(tokens)-1] = NULL;
 
       pszLine = CPLReadLine( fpItf );
-      conttok = CSLTokenizeString2( pszLine, " ", CSLT_PRESERVEESCAPES );
+      if( pszLine == NULL )
+      {
+          break;
+      }
+      char **conttok = CSLTokenizeString2( pszLine, " ", CSLT_PRESERVEESCAPES );
       if (!conttok || !EQUAL(conttok[0], "CONT"))
       {
           CSLDestroy(conttok);
diff --git a/ogr/ogrsf_frmts/ili/ili1reader.h b/ogr/ogrsf_frmts/ili/ili1reader.h
index aa47aca..df58c9c 100644
--- a/ogr/ogrsf_frmts/ili/ili1reader.h
+++ b/ogr/ogrsf_frmts/ili/ili1reader.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ili1reader.h 29093 2015-05-01 18:50:08Z pka $
+ * $Id: ili1reader.h 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Interlis 1 Reader
  * Purpose:  Private Declarations for Reader code.
@@ -14,21 +14,21 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _CPL_ILI1READER_H_INCLUDED
-#define _CPL_ILI1READER_H_INCLUDED
+#ifndef CPL_ILI1READER_H_INCLUDED
+#define CPL_ILI1READER_H_INCLUDED
 
 #include "imdreader.h"
 
@@ -40,10 +40,10 @@ public:
     virtual     ~IILI1Reader();
 
     virtual int  OpenFile( const char *pszFilename ) = 0;
-    
+
     virtual int  ReadModel( ImdReader *poImdReader, const char *pszModelFilename, OGRILI1DataSource *poDS ) = 0;
-    virtual int  ReadFeatures() = 0;       
-    
+    virtual int  ReadFeatures() = 0;
+
     virtual OGRLayer *GetLayer( int ) = 0;
     virtual OGRLayer *GetLayerByName( const char* ) = 0;
     virtual int  GetLayerCount() = 0;
diff --git a/ogr/ogrsf_frmts/ili/ili1readerp.h b/ogr/ogrsf_frmts/ili/ili1readerp.h
index eb1a69b..77b97cd 100644
--- a/ogr/ogrsf_frmts/ili/ili1readerp.h
+++ b/ogr/ogrsf_frmts/ili/ili1readerp.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ili1readerp.h 29093 2015-05-01 18:50:08Z pka $
+ * $Id: ili1readerp.h 31777 2015-11-26 14:14:41Z rouault $
  *
  * Project:  Interlis 1 Reader
  * Purpose:  Private Declarations for Reader code.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _CPL_ILI1READERP_H_INCLUDED
-#define _CPL_ILI1READERP_H_INCLUDED
+#ifndef CPL_ILI1READERP_H_INCLUDED
+#define CPL_ILI1READERP_H_INCLUDED
 
 #include "ili1reader.h"
 #include "ogr_ili1.h"
diff --git a/ogr/ogrsf_frmts/ili/ili2handler.cpp b/ogr/ogrsf_frmts/ili/ili2handler.cpp
index d48dd62..0eaba04 100644
--- a/ogr/ogrsf_frmts/ili/ili2handler.cpp
+++ b/ogr/ogrsf_frmts/ili/ili2handler.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ili2handler.cpp 27794 2014-10-04 10:13:46Z rouault $
+ * $Id: ili2handler.cpp 33109 2016-01-23 16:25:42Z rouault $
  *
  * Project:  Interlis 2 Reader
  * Purpose:  Implementation of ILI2Handler class.
@@ -28,55 +28,56 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_ili2.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
 #include "ili2readerp.h"
+#include "ogr_ili2.h"
+
 #include <xercesc/sax2/Attributes.hpp>
 
-CPL_CVSID("$Id: ili2handler.cpp 27794 2014-10-04 10:13:46Z rouault $");
+CPL_CVSID("$Id: ili2handler.cpp 33109 2016-01-23 16:25:42Z rouault $");
 
-// 
+//
 // constants
-// 
-static const char* ILI2_DATASECTION = "DATASECTION";
+//
+static const char* const ILI2_DATASECTION = "DATASECTION";
 
 //
 // ILI2Handler
-// 
-ILI2Handler::ILI2Handler( ILI2Reader *poReader ) {
+//
+ILI2Handler::ILI2Handler( ILI2Reader *poReader ) :
+    level(0),
+    m_nEntityCounter(0)
+{
   m_poReader = poReader;
-  
+
   XMLCh *tmpCh = XMLString::transcode("CORE");
   DOMImplementation *impl = DOMImplementationRegistry::getDOMImplementation(tmpCh);
   XMLString::release(&tmpCh);
 
   // the root element
   tmpCh = XMLString::transcode("ROOT");
-  dom_doc = impl->createDocument(0,tmpCh,0);
+  dom_doc = impl->createDocument(NULL,tmpCh,NULL);
   XMLString::release(&tmpCh);
 
   // the first element is root
   dom_elem = dom_doc->getDocumentElement();
-
 }
 
 ILI2Handler::~ILI2Handler() {
-  
   // remove all elements
   DOMNode *tmpNode = dom_doc->getFirstChild();
   while (tmpNode != NULL) {
-    tmpNode = dom_doc->removeChild(tmpNode);
+    /*tmpNode = */dom_doc->removeChild(tmpNode);
     tmpNode = dom_doc->getFirstChild();
   }
-  
+
   // release the dom tree
   dom_doc->release();
-
 }
 
-    
+
 void ILI2Handler::startDocument() {
   // the level counter starts with DATASECTION
   level = -1;
@@ -88,24 +89,26 @@ void ILI2Handler::endDocument() {
 }
 
 void ILI2Handler::startElement(
-    CPL_UNUSED const XMLCh* const uri,
-    CPL_UNUSED const XMLCh* const localname,
+    const XMLCh* const /* uri */,
+    const XMLCh* const /* localname */,
     const XMLCh* const qname,
     const Attributes& attrs
     ) {
   // start to add the layers, features with the DATASECTION
   char *tmpC = NULL;
   m_nEntityCounter = 0;
-  if ((level >= 0) || (cmpStr(ILI2_DATASECTION, tmpC = XMLString::transcode(qname)) == 0)) {
+  if ((level >= 0) || (cmpStr(ILI2_DATASECTION,
+                              tmpC = XMLString::transcode(qname)) == 0)) {
     level++;
 
     if (level >= 2) {
 
       // create the dom tree
-      DOMElement *elem = (DOMElement*)dom_doc->createElement(qname);
-      
+      DOMElement *elem = reinterpret_cast<DOMElement *>(
+          dom_doc->createElement(qname) );
+
       // add all attributes
-      unsigned int len = attrs.getLength();
+      unsigned int len = static_cast<unsigned int>(attrs.getLength());
       for (unsigned int index = 0; index < len; index++)
         elem->setAttribute(attrs.getQName(index), attrs.getValue(index));
       dom_elem->appendChild(elem);
@@ -131,11 +134,11 @@ void ILI2Handler::endElement(
       m_poReader->AddFeature(childElem);
 
       // remove the child element
-      childElem = (DOMElement*)dom_elem->removeChild(childElem);
+      /*childElem = (DOMElement*)*/dom_elem->removeChild(childElem);
     } else if (level >= 3) {
 
       // go to the parent element
-      dom_elem = (DOMElement*)dom_elem->getParentNode();
+      dom_elem = reinterpret_cast<DOMElement *>( dom_elem->getParentNode() );
     }
     level--;
   }
@@ -167,11 +170,11 @@ void ILI2Handler::characters( const XMLCh *const chars,
 
 void ILI2Handler::characters( const XMLCh *const chars,
                      CPL_UNUSED const unsigned int length ) {
-  
+
   // add the text element
   if (level >= 3) {
     char *tmpC = XMLString::transcode(chars);
-    
+
     // only add the text if it is not empty
     if (trim(tmpC) != "")
       dom_elem->appendChild(dom_doc->createTextNode(chars));
@@ -186,7 +189,8 @@ void ILI2Handler::startEntity (CPL_UNUSED const XMLCh *const name)
     m_nEntityCounter++;
     if (m_nEntityCounter > 1000)
     {
-        throw SAXNotSupportedException ("File probably corrupted (million laugh pattern)");
+        throw SAXNotSupportedException (
+            "File probably corrupted (million laugh pattern)" );
     }
 }
 
diff --git a/ogr/ogrsf_frmts/ili/ili2reader.cpp b/ogr/ogrsf_frmts/ili/ili2reader.cpp
index 36fb7af..e5f873e 100644
--- a/ogr/ogrsf_frmts/ili/ili2reader.cpp
+++ b/ogr/ogrsf_frmts/ili/ili2reader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ili2reader.cpp 29140 2015-05-03 20:09:32Z pka $
+ * $Id: ili2reader.cpp 33123 2016-01-23 18:59:28Z rouault $
  *
  * Project:  Interlis 2 Reader
  * Purpose:  Implementation of ILI2Reader class.
@@ -28,25 +28,26 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "ili2readerp.h"
 #include "ogr_ili2.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
 #include "ili2reader.h"
-#include "ili2readerp.h"
+
 
 //from trstring.cpp/gmlreaderp.h
 char *tr_strdup( const XMLCh * );
 
 using namespace std;
 
-CPL_CVSID("$Id: ili2reader.cpp 29140 2015-05-03 20:09:32Z pka $");
+CPL_CVSID("$Id: ili2reader.cpp 33123 2016-01-23 18:59:28Z rouault $");
 
 //
 // constants
 //
-static const char *ILI2_TID = "TID";
-static const char *ILI2_REF = "REF";
+static const char * const ILI2_TID = "TID";
+static const char * const ILI2_REF = "REF";
 
 static const int ILI2_STRING_TYPE = 0;
 static const int ILI2_COORD_TYPE = 1;
@@ -56,12 +57,12 @@ static const int ILI2_BOUNDARY_TYPE = 8;
 static const int ILI2_AREA_TYPE = 16; // also SURFACE
 static const int ILI2_GEOMCOLL_TYPE = 32;
 
-static const char *ILI2_COORD = "COORD";
-static const char *ILI2_ARC = "ARC";
-static const char *ILI2_POLYLINE = "POLYLINE";
-static const char *ILI2_BOUNDARY = "BOUNDARY";
-static const char *ILI2_AREA = "AREA";
-static const char *ILI2_SURFACE = "SURFACE";
+static const char * const ILI2_COORD = "COORD";
+static const char * const ILI2_ARC = "ARC";
+static const char * const ILI2_POLYLINE = "POLYLINE";
+static const char * const ILI2_BOUNDARY = "BOUNDARY";
+static const char * const ILI2_AREA = "AREA";
+static const char * const ILI2_SURFACE = "SURFACE";
 
 
 //
@@ -91,7 +92,7 @@ string ltrim(string tmpstr) {
 
 string rtrim(string tmpstr) {
   if (tmpstr.length() == 0) return tmpstr;
-  unsigned int i = tmpstr.length() - 1;
+  unsigned int i = static_cast<unsigned int>(tmpstr.length()) - 1;
   while (tmpstr[i] == ' ' || tmpstr[i] == '\t' || tmpstr[i] == '\r' || tmpstr[i] == '\n') --i;
   return i < tmpstr.length() - 1 ? tmpstr.substr(0, i+1) : tmpstr;
 }
@@ -102,11 +103,11 @@ string trim(string tmpstr) {
   return tmpstr;
 }
 
-int getGeometryTypeOfElem(DOMElement* elem) {
+static int getGeometryTypeOfElem(DOMElement* elem) {
   int type = ILI2_STRING_TYPE;
   char* pszTagName = XMLString::transcode(elem->getTagName());
 
-  if (elem && elem->getNodeType() == DOMNode::ELEMENT_NODE) {
+  if (elem->getNodeType() == DOMNode::ELEMENT_NODE) {
     if (cmpStr(ILI2_COORD, pszTagName) == 0) {
       type = ILI2_COORD_TYPE;
     } else if (cmpStr(ILI2_ARC, pszTagName) == 0) {
@@ -125,26 +126,25 @@ int getGeometryTypeOfElem(DOMElement* elem) {
   return type;
 }
 
-char *getObjValue(DOMElement *elem) {
-  DOMElement *textElem = (DOMElement *)elem->getFirstChild();
-
-  if ((textElem != NULL) && (textElem->getNodeType() == DOMNode::TEXT_NODE))
+static char *getObjValue(DOMElement *elem) {
+  DOMNode* child = elem->getFirstChild();
+  if ((child != NULL) && (child->getNodeType() == DOMNode::TEXT_NODE))
   {
-    char* pszNodeValue = tr_strdup(textElem->getNodeValue());
+    char* pszNodeValue = tr_strdup(child->getNodeValue());
     return pszNodeValue;
   }
 
   return NULL;
 }
 
-char *getREFValue(DOMElement *elem) {
+static char *getREFValue(DOMElement *elem) {
   XMLCh* pszIli2_ref = XMLString::transcode(ILI2_REF);
   char* pszREFValue = tr_strdup(elem->getAttribute(pszIli2_ref));
   XMLString::release(&pszIli2_ref);
   return pszREFValue;
 }
 
-OGRPoint *getPoint(DOMElement *elem) {
+static OGRPoint *getPoint(DOMElement *elem) {
   // elem -> COORD (or ARC)
   OGRPoint *pt = new OGRPoint();
 
@@ -209,7 +209,7 @@ OGRCircularString *ILI2Reader::getArc(DOMElement *elem) {
   return arc;
 }
 
-OGRCompoundCurve *getPolyline(DOMElement *elem) {
+static OGRCompoundCurve *getPolyline(DOMElement *elem) {
   // elem -> POLYLINE
   OGRCompoundCurve *ogrCurve = new OGRCompoundCurve();
   OGRLineString *ls = new OGRLineString();
@@ -241,25 +241,25 @@ OGRCompoundCurve *getPolyline(DOMElement *elem) {
 
       DOMElement *arcElem = (DOMElement *)lineElem->getFirstChild();
       while (arcElem != NULL) {
-        char* pszTagName = XMLString::transcode(arcElem->getTagName());
+        char* pszTagName2 = XMLString::transcode(arcElem->getTagName());
         char* pszObjValue = getObjValue(arcElem);
-        if (cmpStr("C1", pszTagName) == 0)
+        if (cmpStr("C1", pszTagName2) == 0)
           ptEnd->setX(CPLAtof(pszObjValue));
-        else if (cmpStr("C2", pszTagName) == 0)
+        else if (cmpStr("C2", pszTagName2) == 0)
           ptEnd->setY(CPLAtof(pszObjValue));
-        else if (cmpStr("C3", pszTagName) == 0)
+        else if (cmpStr("C3", pszTagName2) == 0)
           ptEnd->setZ(CPLAtof(pszObjValue));
-        else if (cmpStr("A1", pszTagName) == 0)
+        else if (cmpStr("A1", pszTagName2) == 0)
           ptOnArc->setX(CPLAtof(pszObjValue));
-        else if (cmpStr("A2", pszTagName) == 0)
+        else if (cmpStr("A2", pszTagName2) == 0)
           ptOnArc->setY(CPLAtof(pszObjValue));
-        else if (cmpStr("A3", pszTagName) == 0)
+        else if (cmpStr("A3", pszTagName2) == 0)
           ptOnArc->setZ(CPLAtof(pszObjValue));
-        else if (cmpStr("R", pszTagName) == 0) {
+        else if (cmpStr("R", pszTagName2) == 0) {
           // radius = CPLAtof(pszObjValue);
         }
         CPLFree(pszObjValue);
-        XMLString::release(&pszTagName);
+        XMLString::release(&pszTagName2);
 
         arcElem = (DOMElement *)arcElem->getNextSibling();
       }
@@ -283,10 +283,13 @@ OGRCompoundCurve *getPolyline(DOMElement *elem) {
   if (ls->getNumPoints() > 1) {
     ogrCurve->addCurveDirectly(ls);
   }
+  else {
+    delete ls;
+  }
   return ogrCurve;
 }
 
-OGRCompoundCurve *getBoundary(DOMElement *elem) {
+static OGRCompoundCurve *getBoundary(DOMElement *elem) {
 
   DOMElement *lineElem = (DOMElement *)elem->getFirstChild();
   if (lineElem != NULL)
@@ -303,7 +306,7 @@ OGRCompoundCurve *getBoundary(DOMElement *elem) {
   return new OGRCompoundCurve();
 }
 
-OGRCurvePolygon *getPolygon(DOMElement *elem) {
+static OGRCurvePolygon *getPolygon(DOMElement *elem) {
   OGRCurvePolygon *pg = new OGRCurvePolygon();
 
   DOMElement *boundaryElem = (DOMElement *)elem->getFirstChild(); // outer boundary
@@ -387,14 +390,14 @@ int ILI2Reader::ReadModel(ImdReader *poImdReader, const char *modelFilename) {
   poImdReader->ReadModel(modelFilename);
   for (FeatureDefnInfos::const_iterator it = poImdReader->featureDefnInfos.begin(); it != poImdReader->featureDefnInfos.end(); ++it)
   {
-    OGRLayer* layer = new OGRILI2Layer(it->poTableDefn, it->poGeomFieldInfos, NULL);
+    OGRLayer* layer = new OGRILI2Layer(it->GetTableDefnRef(), it->poGeomFieldInfos, NULL);
     m_listLayer.push_back(layer);
   }
   return 0;
 }
 
 //Detect field name of value element
-char* fieldName(DOMElement* elem) {
+static char* fieldName(DOMElement* elem) {
   DOMNode *node = elem;
   if (getGeometryTypeOfElem(elem))
   {
@@ -404,6 +407,11 @@ char* fieldName(DOMElement* elem) {
     node = elem;
     for (int d = 0; d<depth-4; ++d) node = node->getParentNode();
   }
+  if( node == NULL )
+  {
+      CPLError(CE_Failure, CPLE_AssertionFailed, "node == NULL");
+      return CPLStrdup("***bug***");
+  }
   char* pszNodeName = tr_strdup(node->getNodeName());
   return pszNodeName;
 }
@@ -460,12 +468,13 @@ void ILI2Reader::SetFieldValues(OGRFeature *feature, DOMElement* elem) {
       char *fName = fieldName(childElem);
       int fIndex = feature->GetGeomFieldIndex(fName);
       OGRGeometry *geom = getGeometry(childElem, type);
-      if (fIndex == -1) { // Unkown model
+      if (fIndex == -1) { // Unknown model
         feature->SetGeometryDirectly(geom);
       } else {
         OGRwkbGeometryType geomType = feature->GetGeomFieldDefnRef(fIndex)->GetType();
         if (geomType == wkbMultiLineString || geomType == wkbPolygon) {
           feature->SetGeomFieldDirectly(fIndex, geom->getLinearGeometry());
+          delete geom;
         } else {
           feature->SetGeomFieldDirectly(fIndex, geom);
         }
@@ -631,7 +640,7 @@ list<OGRLayer *> ILI2Reader::GetLayers() {
 }
 
 int ILI2Reader::GetLayerCount() {
-  return m_listLayer.size();
+  return static_cast<int>(m_listLayer.size());
 }
 
 OGRLayer* ILI2Reader::GetLayer(const char* pszName) {
@@ -648,7 +657,7 @@ OGRLayer* ILI2Reader::GetLayer(const char* pszName) {
 
 int ILI2Reader::AddFeature(DOMElement *elem) {
   bool newLayer = true;
-  OGRLayer *curLayer = 0;
+  OGRLayer *curLayer = NULL;
   char *pszName = tr_strdup(elem->getTagName());
   //CPLDebug( "OGR_ILI", "Reading layer: %s", pszName );
 
@@ -692,8 +701,8 @@ int ILI2Reader::AddFeature(DOMElement *elem) {
   }
 
   SetFieldValues(feature, elem);
-  curLayer->SetFeature(feature);
-  
+  CPL_IGNORE_RET_VAL(curLayer->SetFeature(feature));
+
   CPLFree(pszName);
 
   return 0;
diff --git a/ogr/ogrsf_frmts/ili/ili2reader.h b/ogr/ogrsf_frmts/ili/ili2reader.h
index 91c9034..bd28bcf 100644
--- a/ogr/ogrsf_frmts/ili/ili2reader.h
+++ b/ogr/ogrsf_frmts/ili/ili2reader.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ili2reader.h 29140 2015-05-03 20:09:32Z pka $
+ * $Id: ili2reader.h 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Interlis 2 Reader
  * Purpose:  Public Declarations for Reader code.
@@ -14,21 +14,21 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _CPL_ILI2READER_H_INCLUDED
-#define _CPL_ILI2READER_H_INCLUDED
+#ifndef CPL_ILI2READER_H_INCLUDED
+#define CPL_ILI2READER_H_INCLUDED
 
 // This works around problems with math.h on some platforms #defining INFINITY
 #ifdef INFINITY
@@ -49,7 +49,7 @@ public:
 
     virtual int  ReadModel( ImdReader *poImdReader, const char *modelFilename ) = 0;
     virtual int  SaveClasses( const char *pszFilename ) = 0;
-    
+
     virtual std::list<OGRLayer *> GetLayers() = 0;
     virtual int GetLayerCount() = 0;
 };
diff --git a/ogr/ogrsf_frmts/ili/ili2readerp.h b/ogr/ogrsf_frmts/ili/ili2readerp.h
index f04e22b..51420fd 100644
--- a/ogr/ogrsf_frmts/ili/ili2readerp.h
+++ b/ogr/ogrsf_frmts/ili/ili2readerp.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ili2readerp.h 29140 2015-05-03 20:09:32Z pka $
+ * $Id: ili2readerp.h 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Interlis 2 Reader
  * Purpose:  Private Declarations for Reader code.
@@ -14,27 +14,23 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _CPL_ILI2READERP_H_INCLUDED
-#define _CPL_ILI2READERP_H_INCLUDED
+#ifndef CPL_ILI2READERP_H_INCLUDED
+#define CPL_ILI2READERP_H_INCLUDED
 
-// This works around problems with math.h on some platforms #defining INFINITY
-#ifdef INFINITY
-#undef  INFINITY
-#define INFINITY INFINITY_XERCES
-#endif
+#include "xercesc_headers.h"
 
 #include "ili2reader.h"
 #include "ogr_ili2.h"
@@ -42,22 +38,6 @@
 #include <string>
 #include <set>
 
-#include <util/PlatformUtils.hpp>
-#include <sax2/DefaultHandler.hpp>
-#include <sax2/ContentHandler.hpp>
-#include <sax2/SAX2XMLReader.hpp>
-#include <sax2/XMLReaderFactory.hpp>
-#include <dom/DOM.hpp>
-#include <util/XMLString.hpp>
-
-#if _XERCES_VERSION >= 30000
-# include <sax2/Attributes.hpp>
-#endif
-
-#ifdef XERCES_CPP_NAMESPACE_USE
-XERCES_CPP_NAMESPACE_USE
-#endif
-
 int cmpStr(std::string s1, std::string s2);
 
 std::string ltrim(std::string tmpstr);
@@ -70,24 +50,24 @@ class ILI2Reader;
 /************************************************************************/
 /*                            ILI2Handler                                */
 /************************************************************************/
-class ILI2Handler : public DefaultHandler 
+class ILI2Handler : public DefaultHandler
 {
     ILI2Reader  *m_poReader;
 
     int level;
-    
+
     DOMDocument *dom_doc;
     DOMElement *dom_elem;
-    
+
     int m_nEntityCounter;
 
 public:
     ILI2Handler( ILI2Reader *poReader );
     ~ILI2Handler();
-    
+
     void startDocument();
     void endDocument();
-    
+
     void startElement(
         const   XMLCh* const    uri,
         const   XMLCh* const    localname,
@@ -118,20 +98,19 @@ public:
 /************************************************************************/
 
 class ILI2Reader : public IILI2Reader
-{    
+{
 private:
     int      SetupParser();
     void     CleanupParser();
-    
+
     char    *m_pszFilename;
-    
+
     std::list<std::string> m_missAttrs;
 
     ILI2Handler *m_poILI2Handler;
     SAX2XMLReader *m_poSAXReader;
     int      m_bReadStarted;
-    double   arcIncr;
-    
+
     std::list<OGRLayer *> m_listLayer;
 
 public:
@@ -141,11 +120,11 @@ public:
     void     SetSourceFile( const char *pszFilename );
     int      ReadModel( ImdReader *poImdReader, const char *modelFilename );
     int      SaveClasses( const char *pszFile );
-    
+
     std::list<OGRLayer *> GetLayers();
     int      GetLayerCount();
     OGRLayer* GetLayer(const char* pszName);
-    
+
     int      AddFeature(DOMElement *elem);
     void     SetFieldValues(OGRFeature *feature, DOMElement* elem);
     const char* GetLayerName(/*IOM_BASKET model, IOM_OBJECT table*/);
diff --git a/ogr/ogrsf_frmts/ili/imdreader.cpp b/ogr/ogrsf_frmts/ili/imdreader.cpp
index 2ece5b0..e8a3a99 100644
--- a/ogr/ogrsf_frmts/ili/imdreader.cpp
+++ b/ogr/ogrsf_frmts/ili/imdreader.cpp
@@ -30,8 +30,9 @@
 // IlisMeta model: http://www.interlis.ch/models/core/IlisMeta07-20111222.ili
 
 
-#include "imdreader.h"
 #include "cpl_minixml.h"
+#include "imdreader.h"
+
 #include <set>
 #include <vector>
 #include <algorithm>
@@ -39,12 +40,12 @@
 
 CPL_CVSID("$Id$");
 
-
 typedef std::map<CPLString,CPLXMLNode*> StrNodeMap;
 typedef std::vector<CPLXMLNode*> NodeVector;
 typedef std::map<CPLXMLNode*,int> NodeCountMap;
 class IliClass;
-typedef std::map<CPLXMLNode*,IliClass*> ClassesMap; /* all classes with XML node for lookup */
+// All classes with XML node for lookup.
+typedef std::map<CPLXMLNode*,IliClass*> ClassesMap;
 
 /* Helper class for collection class infos */
 class IliClass
@@ -62,17 +63,21 @@ public:
     bool isAssocClass;
     bool hasDerivedClasses;
 
-    IliClass(CPLXMLNode* node_, int iliVersion_, StrNodeMap& oTidLookup_, ClassesMap& oClasses_, NodeCountMap& oAxisCount_) :
-        node(node_), iliVersion(iliVersion_), oTidLookup(oTidLookup_), oClasses(oClasses_), oAxisCount(oAxisCount_),
-        poGeomFieldInfos(), poStructFieldInfos(), oFields(), isAssocClass(false), hasDerivedClasses(false)
+    IliClass( CPLXMLNode* node_, int iliVersion_, StrNodeMap& oTidLookup_,
+              ClassesMap& oClasses_, NodeCountMap& oAxisCount_) :
+        node(node_), iliVersion(iliVersion_), oTidLookup(oTidLookup_),
+        oClasses(oClasses_), oAxisCount(oAxisCount_),
+        poGeomFieldInfos(), poStructFieldInfos(), oFields(),
+        isAssocClass(false), hasDerivedClasses(false)
     {
         char* layerName = LayerName();
         poTableDefn = new OGRFeatureDefn(layerName);
+        poTableDefn->Reference();
         CPLFree(layerName);
     };
     ~IliClass()
     {
-        delete poTableDefn;
+        poTableDefn->Release();
     };
     const char* GetName() {
         return poTableDefn->GetName();
@@ -96,35 +101,42 @@ public:
             }
             CSLDestroy( papszTokens );
             return CPLStrdup(layername);
-        } else {
-            return CPLStrdup(psClassTID);
         }
+
+        return CPLStrdup(psClassTID);
     };
-    void AddFieldNode(CPLXMLNode* node, int iOrderPos)
+    void AddFieldNode(CPLXMLNode* nodeIn, int iOrderPos)
     {
         if (iOrderPos >= (int)oFields.size())
             oFields.resize(iOrderPos+1);
-        //CPLDebug( "OGR_ILI", "Register field with OrderPos %d to Class %s", iOrderPos, GetName());
-        oFields[iOrderPos] = node;
+#ifdef DEBUG_VERBOSE
+        CPLDebug( "OGR_ILI", "Register field with OrderPos %d to Class %s",
+                  iOrderPos, GetName() );
+#endif
+        oFields[iOrderPos] = nodeIn;
     }
-    void AddRoleNode(CPLXMLNode* node, int iOrderPos)
+    void AddRoleNode(CPLXMLNode* nodeIn, int iOrderPos)
     {
         isAssocClass = true;
-        AddFieldNode(node, iOrderPos);
+        AddFieldNode(nodeIn, iOrderPos);
     }
     bool isEmbedded()
     {
         if (isAssocClass)
-            for (NodeVector::const_iterator it = oFields.begin(); it != oFields.end(); ++it)
+            for( NodeVector::const_iterator it = oFields.begin();
+                 it != oFields.end();
+                 ++it )
             {
                 if (*it == NULL) continue;
-                if (CSLTestBoolean(CPLGetXMLValue( *it, "EmbeddedTransfer", "FALSE" )))
+                if( CPLTestBool(
+                        CPLGetXMLValue( *it, "EmbeddedTransfer", "FALSE" ) ) )
                     return true;
             }
         return false;
     }
     // Add additional Geometry table for Interlis 1
-    void AddGeomTable(CPLString layerName, const char* psFieldName, OGRwkbGeometryType eType, bool bRefTIDField = false)
+    void AddGeomTable( CPLString layerName, const char* psFieldName,
+                       OGRwkbGeometryType eType, bool bRefTIDField = false )
     {
         OGRFeatureDefn* poGeomTableDefn = new OGRFeatureDefn(layerName);
         OGRFieldDefn fieldDef("_TID", OFTString);
@@ -137,8 +149,9 @@ public:
         poGeomTableDefn->DeleteGeomFieldDefn(0);
         OGRGeomFieldDefn fieldDefGeom(psFieldName, eType);
         poGeomTableDefn->AddGeomFieldDefn(&fieldDefGeom);
-        CPLDebug( "OGR_ILI", "Adding geometry table %s for field %s", poGeomTableDefn->GetName(), psFieldName);
-        poGeomFieldInfos[psFieldName].geomTable = poGeomTableDefn;
+        CPLDebug( "OGR_ILI", "Adding geometry table %s for field %s",
+                  poGeomTableDefn->GetName(), psFieldName);
+        poGeomFieldInfos[psFieldName].SetGeomTableDefn(poGeomTableDefn);
     }
     void AddField(const char* psName, OGRFieldType fieldType)
     {
@@ -151,7 +164,8 @@ public:
         OGRGeomFieldDefn fieldDef(psName, geomType);
         //oGFld.SetSpatialRef(geomlayer->GetSpatialRef());
         poTableDefn->AddGeomFieldDefn(&fieldDef);
-        CPLDebug( "OGR_ILI", "Adding geometry field '%s' to Class %s", psName, GetName());
+        CPLDebug( "OGR_ILI", "Adding geometry field '%s' to Class %s",
+                  psName, GetName());
     }
     void AddCoord(const char* psName, CPLXMLNode* psTypeNode)
     {
@@ -167,13 +181,13 @@ public:
         OGRwkbGeometryType geomType = (dim > 2) ? wkbPoint25D : wkbPoint;
         AddGeomField(psName, geomType);
     }
-    OGRFieldType GetFormattedType(CPLXMLNode* node)
+    OGRFieldType GetFormattedType(CPLXMLNode* nodeIn)
     {
-        const char* psRefSuper = CPLGetXMLValue( node, "Super.REF", NULL );
+        const char* psRefSuper = CPLGetXMLValue( nodeIn, "Super.REF", NULL );
         if (psRefSuper)
             return GetFormattedType(oTidLookup[psRefSuper]);
-        else
-            return OFTString; //TODO: Time, Date, etc. if possible
+
+        return OFTString; //TODO: Time, Date, etc. if possible
     }
     void InitFieldDefinitions()
     {
@@ -181,7 +195,10 @@ public:
         poTableDefn->DeleteGeomFieldDefn(0);
 
         const char* psKind = CPLGetXMLValue( node, "Kind", NULL );
-        //CPLDebug( "OGR_ILI", "InitFieldDefinitions of '%s' kind: %s", GetName(), psKind);
+#ifdef DEBUG_VERBOSE
+        CPLDebug( "OGR_ILI", "InitFieldDefinitions of '%s' kind: %s",
+                  GetName(), psKind );
+#endif
         if (EQUAL(psKind, "Structure"))
         {
             // add foreign_key field
@@ -195,12 +212,14 @@ public:
             OGRFieldDefn ofieldDefn(psTidColName, OFTString);
             poTableDefn->AddFieldDefn(&ofieldDefn);
         }
-        if (CSLTestBoolean(CPLGetXMLValue( node, "Abstract", "FALSE" )))
+        if (CPLTestBool(CPLGetXMLValue( node, "Abstract", "FALSE" )))
             hasDerivedClasses = true;
     }
     void AddFieldDefinitions(NodeVector oArcLineTypes)
     {
-        for (NodeVector::const_iterator it = oFields.begin(); it != oFields.end(); ++it)
+        for( NodeVector::const_iterator it = oFields.begin();
+             it != oFields.end();
+             ++it)
         {
             if (*it == NULL) continue;
             const char* psName = CPLGetXMLValue( *it, "Name", NULL );
@@ -260,7 +279,7 @@ public:
                     const char* psKind = CPLGetXMLValue( psElementNode, "Kind", NULL );
                     poGeomFieldInfos[psName].iliGeomType = psKind;
                     bool isLinearType = (std::find(oArcLineTypes.begin(), oArcLineTypes.end(), psElementNode) == oArcLineTypes.end());
-                    bool linearGeom = isLinearType || CSLTestBoolean(CPLGetConfigOption("OGR_STROKE_CURVE", "FALSE"));
+                    bool linearGeom = isLinearType || CPLTestBool(CPLGetConfigOption("OGR_STROKE_CURVE", "FALSE"));
                     OGRwkbGeometryType multiLineType = linearGeom ? wkbMultiLineString : wkbMultiCurve;
                     OGRwkbGeometryType polyType = linearGeom ? wkbPolygon : wkbCurvePolygon;
                     if (iliVersion == 1)
@@ -306,28 +325,31 @@ public:
     FeatureDefnInfo tableDefs()
     {
         FeatureDefnInfo poLayerInfo;
-        poLayerInfo.poTableDefn = NULL;
         if (!hasDerivedClasses && !isEmbedded())
         {
-            poLayerInfo.poTableDefn = poTableDefn;
+            poLayerInfo.SetTableDefn(poTableDefn);
             poLayerInfo.poGeomFieldInfos = poGeomFieldInfos;
         }
         return poLayerInfo;
     }
 
+  private:
+    CPL_DISALLOW_COPY_ASSIGN(IliClass);
 };
 
 
-ImdReader::ImdReader(int iliVersionIn) : iliVersion(iliVersionIn), modelInfos() {
-  mainModelName = "OGR";
-  mainTopicName = "OGR";
-  codeBlank = '_';
-  codeUndefined = '@';
-  codeContinue = '\\';
+ImdReader::ImdReader(int iliVersionIn) :
+    iliVersion(iliVersionIn),
+    modelInfos()
+{
+    mainModelName = "OGR";
+    mainTopicName = "OGR";
+    codeBlank = '_';
+    codeUndefined = '@';
+    codeContinue = '\\';
 }
 
-ImdReader::~ImdReader() {
-}
+ImdReader::~ImdReader() {}
 
 void ImdReader::ReadModel(const char *pszFilename) {
     CPLDebug( "OGR_ILI", "Reading model '%s'", pszFilename);
@@ -335,7 +357,8 @@ void ImdReader::ReadModel(const char *pszFilename) {
     CPLXMLNode* psRootNode = CPLParseXMLFile(pszFilename);
     if( psRootNode == NULL )
         return;
-    CPLXMLNode *psSectionNode = CPLGetXMLNode( psRootNode, "=TRANSFER.DATASECTION" );
+    CPLXMLNode *psSectionNode
+        = CPLGetXMLNode( psRootNode, "=TRANSFER.DATASECTION" );
     if( psSectionNode == NULL )
         return;
 
@@ -350,36 +373,48 @@ void ImdReader::ReadModel(const char *pszFilename) {
     while( psModel != NULL )
     {
         modelName = CPLGetXMLValue( psModel, "BID", NULL );
-        //CPLDebug( "OGR_ILI", "Model: '%s'", modelName);
+#ifdef DEBUG_VERBOSE
+        CPLDebug( "OGR_ILI", "Model: '%s'", modelName);
+#endif
 
         CPLXMLNode* psEntry = psModel->psChild;
         while( psEntry != NULL )
                 {
             if (psEntry->eType != CXT_Attribute) //ignore BID
             {
-                //CPLDebug( "OGR_ILI", "Node tag: '%s'", psEntry->pszValue);
+#ifdef DEBUG_VERBOSE
+                CPLDebug( "OGR_ILI", "Node tag: '%s'", psEntry->pszValue);
+#endif
                 const char* psTID = CPLGetXMLValue( psEntry, "TID", NULL );
                 if( psTID != NULL )
                     oTidLookup[psTID] = psEntry;
 
 
-                if( EQUAL(psEntry->pszValue, "IlisMeta07.ModelData.Model") && !EQUAL(modelName, "MODEL.INTERLIS"))
+                if( EQUAL(psEntry->pszValue, "IlisMeta07.ModelData.Model") &&
+                    !EQUAL(modelName, "MODEL.INTERLIS"))
                 {
                     IliModelInfo modelInfo;
                     modelInfo.name = CPLGetXMLValue( psEntry, "Name", "OGR" );
                     modelInfo.version = CPLGetXMLValue( psEntry, "Version", "" );
                     modelInfo.uri = CPLGetXMLValue( psEntry, "At", "" );
                     modelInfos.push_back(modelInfo);
-                    mainModelName = modelInfo.name; //FIXME: check model inheritance
+                    mainModelName = modelInfo.name; // FIXME: check model inheritance
                     //version = CPLGetXMLValue(psEntry, "iliVersion", "0"); //1 or 2.3
 
-                    CPLXMLNode *psFormatNode = CPLGetXMLNode( psEntry, "ili1Format" );
+                    CPLXMLNode *psFormatNode
+                        = CPLGetXMLNode( psEntry, "ili1Format" );
                     if (psFormatNode != NULL)
                     {
                         psFormatNode = psFormatNode->psChild;
-                        codeBlank = atoi(CPLGetXMLValue(psFormatNode, "blankCode", "95"));
-                        codeUndefined = atoi(CPLGetXMLValue(psFormatNode, "undefinedCode", "64"));
-                        codeContinue = atoi(CPLGetXMLValue(psFormatNode, "continueCode", "92"));
+                        codeBlank = static_cast<char>(
+                            atoi( CPLGetXMLValue(
+                                psFormatNode, "blankCode", "95")));
+                        codeUndefined = static_cast<char>(
+                            atoi( CPLGetXMLValue(
+                                psFormatNode, "undefinedCode", "64")));
+                        codeContinue = static_cast<char>(
+                            atoi( CPLGetXMLValue(
+                                psFormatNode, "continueCode", "92")));
                     }
                 }
                 else if( EQUAL(psEntry->pszValue, "IlisMeta07.ModelData.SubModel"))
@@ -390,7 +425,8 @@ void ImdReader::ReadModel(const char *pszFilename) {
                 else if( EQUAL(psEntry->pszValue, "IlisMeta07.ModelData.Class") )
                 {
                     CPLDebug( "OGR_ILI", "Class name: '%s'", psTID);
-                    oClasses[psEntry] = new IliClass(psEntry, iliVersion, oTidLookup, oClasses, oAxisCount);
+                    oClasses[psEntry] = new IliClass(
+                      psEntry, iliVersion, oTidLookup, oClasses, oAxisCount);
                 }
             }
             psEntry = psEntry->psNext;
@@ -402,45 +438,64 @@ void ImdReader::ReadModel(const char *pszFilename) {
         {
             if (psEntry->eType != CXT_Attribute) //ignore BID
             {
-                //CPLDebug( "OGR_ILI", "Node tag: '%s'", psEntry->pszValue);
-                if( iliVersion == 1 && EQUAL(psEntry->pszValue, "IlisMeta07.ModelData.Ili1TransferElement"))
+#ifdef DEBUG_VERBOSE
+                CPLDebug( "OGR_ILI", "Node tag: '%s'", psEntry->pszValue);
+#endif
+                if( iliVersion == 1 &&
+                    EQUAL( psEntry->pszValue,
+                           "IlisMeta07.ModelData.Ili1TransferElement"))
                 {
-                    const char* psClassRef = CPLGetXMLValue( psEntry, "Ili1TransferClass.REF", NULL );
-                    const char* psElementRef = CPLGetXMLValue( psEntry, "Ili1RefAttr.REF", NULL );
-                    int iOrderPos = atoi(CPLGetXMLValue( psEntry, "Ili1RefAttr.ORDER_POS", "0" ))-1;
+                    const char* psClassRef = CPLGetXMLValue(
+                      psEntry, "Ili1TransferClass.REF", NULL );
+                    const char* psElementRef
+                        = CPLGetXMLValue( psEntry, "Ili1RefAttr.REF", NULL );
+                    int iOrderPos = atoi(CPLGetXMLValue(
+                        psEntry, "Ili1RefAttr.ORDER_POS", "0" ))-1;
                     IliClass* psParentClass = oClasses[oTidLookup[psClassRef]];
                     CPLXMLNode* psElementNode = oTidLookup[psElementRef];
                     psParentClass->AddFieldNode(psElementNode, iOrderPos);
                 }
-                else if( EQUAL(psEntry->pszValue, "IlisMeta07.ModelData.TransferElement"))
+                else if( EQUAL( psEntry->pszValue,
+                                "IlisMeta07.ModelData.TransferElement"))
                 {
-                    const char* psClassRef = CPLGetXMLValue( psEntry, "TransferClass.REF", NULL );
-                    const char* psElementRef = CPLGetXMLValue( psEntry, "TransferElement.REF", NULL );
-                    int iOrderPos = atoi(CPLGetXMLValue( psEntry, "TransferElement.ORDER_POS", "0" ))-1;
+                    const char* psClassRef
+                        = CPLGetXMLValue( psEntry, "TransferClass.REF", NULL );
+                    const char* psElementRef = CPLGetXMLValue(
+                        psEntry, "TransferElement.REF", NULL );
+                    int iOrderPos = atoi(CPLGetXMLValue(
+                        psEntry, "TransferElement.ORDER_POS", "0" ))-1;
                     IliClass* psParentClass = oClasses[oTidLookup[psClassRef]];
                     CPLXMLNode* psElementNode = oTidLookup[psElementRef];
                     psParentClass->AddFieldNode(psElementNode, iOrderPos);
                 }
                 else if( EQUAL(psEntry->pszValue, "IlisMeta07.ModelData.Role"))
                 {
-                    const char* psRefParent = CPLGetXMLValue( psEntry, "Association.REF", NULL );
-                    int iOrderPos = atoi(CPLGetXMLValue( psEntry, "Association.ORDER_POS", "0" ))-1;
+                    const char* psRefParent
+                        = CPLGetXMLValue( psEntry, "Association.REF", NULL );
+                    int iOrderPos = atoi(
+                        CPLGetXMLValue( psEntry,
+                                        "Association.ORDER_POS", "0" ))-1;
                     IliClass* psParentClass = oClasses[oTidLookup[psRefParent]];
                     if (psParentClass)
                         psParentClass->AddRoleNode(psEntry, iOrderPos);
                 }
                 else if( EQUAL(psEntry->pszValue, "IlisMeta07.ModelData.AxisSpec"))
                 {
-                    const char* psClassRef = CPLGetXMLValue( psEntry, "CoordType.REF", NULL );
-                    //int iOrderPos = atoi(CPLGetXMLValue( psEntry, "Axis.ORDER_POS", "0" ))-1;
+                    const char* psClassRef
+                        = CPLGetXMLValue( psEntry, "CoordType.REF", NULL );
+                    // int iOrderPos = atoi(
+                    //     CPLGetXMLValue( psEntry, "Axis.ORDER_POS", "0" ))-1;
                     CPLXMLNode* psCoordTypeNode = oTidLookup[psClassRef];
                     oAxisCount[psCoordTypeNode] += 1;
                 }
-                else if( EQUAL(psEntry->pszValue, "IlisMeta07.ModelData.LinesForm"))
+                else if( EQUAL( psEntry->pszValue,
+                                "IlisMeta07.ModelData.LinesForm"))
                 {
-                    const char* psLineForm = CPLGetXMLValue( psEntry, "LineForm.REF", NULL );
+                    const char* psLineForm
+                        = CPLGetXMLValue( psEntry, "LineForm.REF", NULL );
                     if (EQUAL(psLineForm, "INTERLIS.ARCS")) {
-                        const char* psElementRef = CPLGetXMLValue( psEntry, "LineType.REF", NULL );
+                        const char* psElementRef
+                            = CPLGetXMLValue( psEntry, "LineType.REF", NULL );
                         CPLXMLNode* psElementNode = oTidLookup[psElementRef];
                         oArcLineTypes.push_back(psElementNode);
                     }
@@ -454,9 +509,13 @@ void ImdReader::ReadModel(const char *pszFilename) {
     }
 
     /* Analyze class inheritance & add fields to class table defn */
-    for (ClassesMap::const_iterator it = oClasses.begin(); it != oClasses.end(); ++it)
+    for( ClassesMap::const_iterator it = oClasses.begin();
+         it != oClasses.end();
+         ++it )
     {
-        //CPLDebug( "OGR_ILI", "Class: '%s'", it->second->GetName());
+#ifdef DEBUG_VERBOSE
+        CPLDebug( "OGR_ILI", "Class: '%s'", it->second->GetName());
+#endif
         const char* psRefSuper = CPLGetXMLValue( it->first, "Super.REF", NULL );
         if (psRefSuper) {
             if (oTidLookup.find(psRefSuper) != oTidLookup.end() &&
@@ -472,22 +531,32 @@ void ImdReader::ReadModel(const char *pszFilename) {
     }
 
     /* Filter relevant classes */
-    for (ClassesMap::const_iterator it = oClasses.begin(); it != oClasses.end(); ++it)
+    for( ClassesMap::const_iterator it = oClasses.begin();
+         it != oClasses.end();
+         ++it)
     {
         const char* className = it->second->GetIliName();
         FeatureDefnInfo oClassInfo = it->second->tableDefs();
-        if (!EQUALN(className, "INTERLIS.", 9) && oClassInfo.poTableDefn)
+        if (!STARTS_WITH_CI(className, "INTERLIS.") &&
+            oClassInfo.GetTableDefnRef())
             featureDefnInfos.push_back(oClassInfo);
     }
 
+    for (ClassesMap::iterator it = oClasses.begin(); it != oClasses.end(); ++it)
+    {
+        delete it->second;
+    }
+
     CPLDestroyXMLNode(psRootNode);
 }
 
 FeatureDefnInfo ImdReader::GetFeatureDefnInfo(const char *pszLayerName) {
     FeatureDefnInfo featureDefnInfo;
-    for (FeatureDefnInfos::const_iterator it = featureDefnInfos.begin(); it != featureDefnInfos.end(); ++it)
+    for( FeatureDefnInfos::const_iterator it = featureDefnInfos.begin();
+         it != featureDefnInfos.end();
+         ++it )
     {
-        OGRFeatureDefn* fdefn = it->poTableDefn;
+        OGRFeatureDefn* fdefn = it->GetTableDefnRef();
         if (EQUAL(fdefn->GetName(), pszLayerName)) featureDefnInfo = *it;
     }
     return featureDefnInfo;
diff --git a/ogr/ogrsf_frmts/ili/imdreader.h b/ogr/ogrsf_frmts/ili/imdreader.h
index d4316f2..39ad7a2 100644
--- a/ogr/ogrsf_frmts/ili/imdreader.h
+++ b/ogr/ogrsf_frmts/ili/imdreader.h
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _IMDREADER_H_INCLUDED
-#define _IMDREADER_H_INCLUDED
+#ifndef IMDREADER_H_INCLUDED
+#define IMDREADER_H_INCLUDED
 
 #include "cpl_vsi.h"
 #include "cpl_error.h"
@@ -39,10 +39,45 @@
 
 class GeomFieldInfo
 {
-public:
     OGRFeatureDefn* geomTable; /* separate geometry table for Ili 1 */
+public:
     CPLString       iliGeomType;
-    GeomFieldInfo() : geomTable(0) {};
+
+    GeomFieldInfo() : geomTable(NULL) {};
+    ~GeomFieldInfo() {
+       if( geomTable )
+           geomTable->Release();
+    }
+    GeomFieldInfo(const GeomFieldInfo& other)
+    {
+        geomTable = other.geomTable;
+        if( geomTable )
+            geomTable->Reference();
+        iliGeomType = other.iliGeomType;
+    }
+
+    GeomFieldInfo& operator= (const GeomFieldInfo& other)
+    {
+        if( this != &other )
+        {
+            if( geomTable )
+                geomTable->Release();
+            geomTable = other.geomTable;
+            if( geomTable )
+                geomTable->Reference();
+            iliGeomType = other.iliGeomType;
+        }
+        return *this;
+    }
+
+    OGRFeatureDefn* GetGeomTableDefnRef() const { return geomTable; }
+    void            SetGeomTableDefn(OGRFeatureDefn* geomTableIn)
+    {
+        CPLAssert(geomTable == NULL);
+        geomTable = geomTableIn;
+        if( geomTable )
+            geomTable->Reference();
+    }
 };
 
 typedef std::map<CPLString,GeomFieldInfo> GeomFieldInfos; /* key: geom field name, value: ILI geom field info */
@@ -50,11 +85,48 @@ typedef std::map<CPLString,CPLString> StructFieldInfos; /* key: struct field nam
 
 class FeatureDefnInfo
 {
-public:
     OGRFeatureDefn* poTableDefn;
+public:
     GeomFieldInfos  poGeomFieldInfos;
     StructFieldInfos poStructFieldInfos;
-    FeatureDefnInfo() : poTableDefn(0) {};
+
+    FeatureDefnInfo() : poTableDefn(NULL) {};
+    ~FeatureDefnInfo() {
+       if( poTableDefn )
+           poTableDefn->Release();
+    }
+    FeatureDefnInfo(const FeatureDefnInfo& other)
+    {
+        poTableDefn = other.poTableDefn;
+        if( poTableDefn )
+            poTableDefn->Reference();
+        poGeomFieldInfos = other.poGeomFieldInfos;
+        poStructFieldInfos = other.poStructFieldInfos;
+    }
+
+    FeatureDefnInfo& operator= (const FeatureDefnInfo& other)
+    {
+        if( this != &other )
+        {
+            if( poTableDefn )
+                poTableDefn->Release();
+            poTableDefn = other.poTableDefn;
+            if( poTableDefn )
+                poTableDefn->Reference();
+            poGeomFieldInfos = other.poGeomFieldInfos;
+            poStructFieldInfos = other.poStructFieldInfos;
+        }
+        return *this;
+    }
+
+    OGRFeatureDefn* GetTableDefnRef() const { return poTableDefn; }
+    void            SetTableDefn(OGRFeatureDefn* poTableDefnIn)
+    {
+        CPLAssert(poTableDefn == NULL);
+        poTableDefn= poTableDefnIn;
+        if( poTableDefn )
+            poTableDefn->Reference();
+    }
 };
 typedef std::list<FeatureDefnInfo> FeatureDefnInfos;
 
@@ -86,4 +158,4 @@ public:
     FeatureDefnInfo      GetFeatureDefnInfo(const char *pszLayerName);
 };
 
-#endif /* _IMDREADER_H_INCLUDED */
+#endif /* IMDREADER_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/ili/ogr_ili1.h b/ogr/ogrsf_frmts/ili/ogr_ili1.h
index ebb34f4..b0b4b7c 100644
--- a/ogr/ogrsf_frmts/ili/ogr_ili1.h
+++ b/ogr/ogrsf_frmts/ili/ogr_ili1.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_ili1.h 29109 2015-05-02 11:45:44Z rouault $
+ * $Id: ogr_ili1.h 33325 2016-02-02 14:30:48Z rouault $
  *
  * Project:  Interlis 1 Translator
  * Purpose:   Definition of classes for OGR Interlis 1 driver.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_ILI1_H_INCLUDED
-#define _OGR_ILI1_H_INCLUDED
+#ifndef OGR_ILI1_H_INCLUDED
+#define OGR_ILI1_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "ili1reader.h"
@@ -44,7 +44,7 @@ class OGRILI1DataSource;
 class OGRILI1Layer : public OGRLayer
 {
 private:
-#ifdef notused
+#if 0
     OGRSpatialReference *poSRS;
 #endif
     OGRFeatureDefn      *poFeatureDefn;
@@ -54,7 +54,7 @@ private:
     OGRFeature          **papoFeatures;
     int                 nFeatureIdx;
 
-    int                 bGeomsJoined;
+    bool                bGeomsJoined;
 
     OGRILI1DataSource   *poDS;
 
@@ -70,7 +70,8 @@ private:
     void                ResetReading();
     OGRFeature *        GetNextFeature();
     OGRFeature *        GetNextFeatureRef();
-    OGRFeature *        GetFeatureRef( long nFID );
+    OGRFeature *        GetFeatureRef( long nFid );
+    OGRFeature *        GetFeatureRef( const char* );
 
     GIntBig             GetFeatureCount( int bForce = TRUE );
 
@@ -128,4 +129,4 @@ class OGRILI1DataSource : public OGRDataSource
     int         TestCapability( const char * );
 };
 
-#endif /* _OGR_ILI1_H_INCLUDED */
+#endif /* OGR_ILI1_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/ili/ogr_ili2.h b/ogr/ogrsf_frmts/ili/ogr_ili2.h
index 1aa3676..9ec063b 100644
--- a/ogr/ogrsf_frmts/ili/ogr_ili2.h
+++ b/ogr/ogrsf_frmts/ili/ogr_ili2.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_ili2.h 29109 2015-05-02 11:45:44Z rouault $
+ * $Id: ogr_ili2.h 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Interlis 2 Translator
  * Purpose:   Definition of classes for OGR Interlis 2 driver.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_ILI2_H_INCLUDED
-#define _OGR_ILI2_H_INCLUDED
+#ifndef OGR_ILI2_H_INCLUDED
+#define OGR_ILI2_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "imdreader.h"
@@ -45,7 +45,7 @@ class OGRILI2DataSource;
 
 class OGRILI2Layer : public OGRLayer
 {
-private:
+  private:
     OGRFeatureDefn     *poFeatureDefn;
     GeomFieldInfos      oGeomFieldInfos;
     std::list<OGRFeature *>    listFeature;
@@ -61,20 +61,20 @@ private:
                        ~OGRILI2Layer();
 
     OGRErr              ISetFeature(OGRFeature *poFeature);
-    
+
     void                ResetReading();
     OGRFeature *        GetNextFeature();
 
     GIntBig             GetFeatureCount( int bForce = TRUE );
 
     OGRErr              ICreateFeature( OGRFeature *poFeature );
-    
+
     OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
 
     CPLString           GetIliGeomType( const char* cFieldName) { return oGeomFieldInfos[cFieldName].iliGeomType; };
 
     OGRErr              CreateField( OGRFieldDefn *poField, int bApproxOK = TRUE );
-    
+
     int                 TestCapability( const char * );
 };
 
@@ -86,7 +86,7 @@ class OGRILI2DataSource : public OGRDataSource
 {
   private:
     std::list<OGRLayer *> listLayer;
-    
+
     char        *pszName;
     ImdReader   *poImdReader;
     IILI2Reader *poReader;
@@ -103,10 +103,10 @@ class OGRILI2DataSource : public OGRDataSource
     int         Create( const char *pszFile, char **papszOptions );
 
     const char *GetName() { return pszName; }
-    int         GetLayerCount() { return listLayer.size(); }
+    int         GetLayerCount() { return static_cast<int>(listLayer.size()); }
     OGRLayer   *GetLayer( int );
 
-    virtual OGRLayer *ICreateLayer( const char *, 
+    virtual OGRLayer *ICreateLayer( const char *,
                                       OGRSpatialReference * = NULL,
                                       OGRwkbGeometryType = wkbUnknown,
                                       char ** = NULL );
@@ -115,4 +115,4 @@ class OGRILI2DataSource : public OGRDataSource
     int         TestCapability( const char * );
 };
 
-#endif /* _OGR_ILI2_H_INCLUDED */
+#endif /* OGR_ILI2_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/ili/ogrili1datasource.cpp b/ogr/ogrsf_frmts/ili/ogrili1datasource.cpp
index 66becbd..669fa84 100644
--- a/ogr/ogrsf_frmts/ili/ogrili1datasource.cpp
+++ b/ogr/ogrsf_frmts/ili/ogrili1datasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrili1datasource.cpp 29139 2015-05-03 20:09:20Z pka $
+ * $Id: ogrili1datasource.cpp 32746 2016-01-05 05:18:43Z goatbar $
  *
  * Project:  Interlis 1 Translator
  * Purpose:  Implements OGRILI1DataSource class.
@@ -28,31 +28,29 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_ili1.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
 #include "ili1reader.h"
+#include "ogr_ili1.h"
 
 #include <string>
 
-CPL_CVSID("$Id: ogrili1datasource.cpp 29139 2015-05-03 20:09:20Z pka $");
+CPL_CVSID("$Id: ogrili1datasource.cpp 32746 2016-01-05 05:18:43Z goatbar $");
 
 /************************************************************************/
 /*                         OGRILI1DataSource()                         */
 /************************************************************************/
 
-OGRILI1DataSource::OGRILI1DataSource()
-
-{
-    pszName = NULL;
-    poImdReader = new ImdReader(1);
-    poReader = NULL;
-    fpTransfer = NULL;
-    pszTopic = NULL;
-    nLayers = 0;
-    papoLayers = NULL;
-}
+OGRILI1DataSource::OGRILI1DataSource() :
+    pszName(NULL),
+    poImdReader(new ImdReader(1)),
+    poReader(NULL),
+    fpTransfer(NULL),
+    pszTopic(NULL),
+    nLayers(0),
+    papoLayers(NULL)
+{}
 
 /************************************************************************/
 /*                        ~OGRILI1DataSource()                         */
@@ -61,9 +59,7 @@ OGRILI1DataSource::OGRILI1DataSource()
 OGRILI1DataSource::~OGRILI1DataSource()
 
 {
-    int i;
-
-    for(i=0;i<nLayers;i++)
+    for( int i=0; i<nLayers; i++)
     {
         delete papoLayers[i];
     }
@@ -87,22 +83,21 @@ OGRILI1DataSource::~OGRILI1DataSource()
 /*                                Open()                                */
 /************************************************************************/
 
-int OGRILI1DataSource::Open( const char * pszNewName, char** papszOpenOptions, int bTestOpen )
+int OGRILI1DataSource::Open( const char * pszNewName,
+                             char** papszOpenOptionsIn, int bTestOpen )
 
 {
-    FILE        *fp;
-    char        szHeader[1000];
-    std::string osBasename, osModelFilename;
-
     if (strlen(pszNewName) == 0)
     {
         return FALSE;
     }
-    
-    if( CSLFetchNameValue(papszOpenOptions, "MODEL") != NULL )
+
+    std::string osBasename;
+    std::string osModelFilename;
+    if( CSLFetchNameValue(papszOpenOptionsIn, "MODEL") != NULL )
     {
         osBasename = pszNewName;
-        osModelFilename = CSLFetchNameValue(papszOpenOptions, "MODEL");
+        osModelFilename = CSLFetchNameValue(papszOpenOptionsIn, "MODEL");
     }
     else
     {
@@ -119,7 +114,7 @@ int OGRILI1DataSource::Open( const char * pszNewName, char** papszOpenOptions, i
 /* -------------------------------------------------------------------- */
 /*      Open the source file.                                           */
 /* -------------------------------------------------------------------- */
-    fp = VSIFOpen( osBasename.c_str(), "r" );
+    FILE *fp = VSIFOpen( osBasename.c_str(), "r" );
     if( fp == NULL )
     {
         if( !bTestOpen )
@@ -134,6 +129,8 @@ int OGRILI1DataSource::Open( const char * pszNewName, char** papszOpenOptions, i
 /*      If we aren't sure it is ILI1, load a header chunk and check      */
 /*      for signs it is ILI1                                             */
 /* -------------------------------------------------------------------- */
+    char szHeader[1000];
+
     if( bTestOpen )
     {
         int nLen = (int)VSIFRead( szHeader, 1, sizeof(szHeader), fp );
@@ -159,8 +156,8 @@ int OGRILI1DataSource::Open( const char * pszNewName, char** papszOpenOptions, i
     if( poReader == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "File %s appears to be ILI1 but the ILI1 reader can't\n"
-                  "be instantiated, likely because Xerces support wasn't\n"
+                  "File %s appears to be ILI1 but the ILI1 reader cannot\n"
+                  "be instantiated, likely because Xerces support was not\n"
                   "configured in.",
                   pszNewName );
         return FALSE;
@@ -180,9 +177,9 @@ int OGRILI1DataSource::Open( const char * pszNewName, char** papszOpenOptions, i
         CPLSetThreadLocalConfigOption("OGR_ARC_STEPSIZE", "0.96");
     }
 
-    //Parse model and read data - without surface join and area polygonizing
+    // Parse model and read data - without surface join and area polygonizing.
     poReader->ReadFeatures();
-    
+
     if( bResetConfigOption )
         CPLSetThreadLocalConfigOption("OGR_ARC_STEPSIZE", NULL);
 
@@ -194,13 +191,13 @@ int OGRILI1DataSource::Open( const char * pszNewName, char** papszOpenOptions, i
 /************************************************************************/
 
 int OGRILI1DataSource::Create( const char *pszFilename,
-                               CPL_UNUSED char **papszOptions )
+                               char ** /* papszOptions */)
 {
-    std::string osBasename, osModelFilename;
     char **filenames = CSLTokenizeString2( pszFilename, ",", 0 );
 
-    osBasename = filenames[0];
+    std::string osBasename = filenames[0];
 
+    std::string osModelFilename;
     if( CSLCount(filenames) > 1 )
         osModelFilename = filenames[1];
 
@@ -220,7 +217,6 @@ int OGRILI1DataSource::Create( const char *pszFilename,
         return FALSE;
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Parse model                                                     */
 /* -------------------------------------------------------------------- */
@@ -238,7 +234,8 @@ int OGRILI1DataSource::Create( const char *pszFilename,
 /*      Write headers                                                   */
 /* -------------------------------------------------------------------- */
     VSIFPrintf( fpTransfer, "SCNT\n" );
-    VSIFPrintf( fpTransfer, "OGR/GDAL %s, INTERLIS Driver\n", GDAL_RELEASE_NAME );
+    VSIFPrintf( fpTransfer, "OGR/GDAL %s, INTERLIS Driver\n",
+                GDAL_RELEASE_NAME );
     VSIFPrintf( fpTransfer, "////\n" );
     VSIFPrintf( fpTransfer, "MTID INTERLIS1\n" );
     const char* modelname = poImdReader->mainModelName.c_str();
@@ -251,7 +248,8 @@ static char *ExtractTopic(const char * pszLayerName)
 {
   const char *table = strchr(pszLayerName, '_');
   while (table && table[1] !=  '_') table = strchr(table+1, '_');
-  return (table) ? CPLScanString(pszLayerName, table-pszLayerName, FALSE, FALSE) : NULL;
+  return (table) ? CPLScanString(
+      pszLayerName, static_cast<int>(table-pszLayerName), FALSE, FALSE) : NULL;
 }
 
 /************************************************************************/
@@ -264,7 +262,8 @@ OGRILI1DataSource::ICreateLayer( const char * pszLayerName,
                                OGRwkbGeometryType eType,
                                CPL_UNUSED char ** papszOptions )
 {
-    FeatureDefnInfo featureDefnInfo = poImdReader->GetFeatureDefnInfo(pszLayerName);
+    FeatureDefnInfo featureDefnInfo
+        = poImdReader->GetFeatureDefnInfo(pszLayerName);
     const char *table = pszLayerName;
     char * topic = ExtractTopic(pszLayerName);
     if (nLayers) VSIFPrintf( fpTransfer, "ETAB\n" );
@@ -295,12 +294,15 @@ OGRILI1DataSource::ICreateLayer( const char * pszLayerName,
 
     OGRFeatureDefn* poFeatureDefn = new OGRFeatureDefn(table);
     poFeatureDefn->SetGeomType( eType );
-    OGRILI1Layer *poLayer = new OGRILI1Layer(poFeatureDefn, featureDefnInfo.poGeomFieldInfos, this);
+    OGRILI1Layer *poLayer
+        = new OGRILI1Layer(poFeatureDefn, featureDefnInfo.poGeomFieldInfos,
+                           this);
 
     nLayers ++;
-    papoLayers = (OGRILI1Layer**)CPLRealloc(papoLayers, sizeof(OGRILI1Layer*) * nLayers);
+    papoLayers = static_cast<OGRILI1Layer **>(
+        CPLRealloc(papoLayers, sizeof(OGRILI1Layer*) * nLayers) );
     papoLayers[nLayers-1] = poLayer;
-    
+
     return poLayer;
 }
 
@@ -313,10 +315,10 @@ int OGRILI1DataSource::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,ODsCCreateLayer) )
         return TRUE;
-    else if( EQUAL(pszCap,ODsCCurveGeometries) )
+    if( EQUAL(pszCap,ODsCCurveGeometries) )
         return TRUE;
-    else
-        return FALSE;
+
+    return FALSE;
 }
 
 /************************************************************************/
@@ -334,5 +336,6 @@ OGRLayer *OGRILI1DataSource::GetLayer( int iLayer )
 
 OGRILI1Layer *OGRILI1DataSource::GetLayerByName( const char* pszLayerName )
 {
-  return (OGRILI1Layer*)poReader->GetLayerByName( pszLayerName );
+  return reinterpret_cast<OGRILI1Layer *>(
+      poReader->GetLayerByName( pszLayerName ) );
 }
diff --git a/ogr/ogrsf_frmts/ili/ogrili1driver.cpp b/ogr/ogrsf_frmts/ili/ogrili1driver.cpp
index e508222..689a20c 100644
--- a/ogr/ogrsf_frmts/ili/ogrili1driver.cpp
+++ b/ogr/ogrsf_frmts/ili/ogrili1driver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrili1driver.cpp 29109 2015-05-02 11:45:44Z rouault $
+ * $Id: ogrili1driver.cpp 32746 2016-01-05 05:18:43Z goatbar $
  *
  * Project:  Interlis 1 Translator
  * Purpose:  Implements OGRILI1Layer class.
@@ -27,10 +27,11 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_ili1.h"
 #include "cpl_conv.h"
+#include "ogr_ili1.h"
+#include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: ogrili1driver.cpp 29109 2015-05-02 11:45:44Z rouault $");
+CPL_CVSID("$Id: ogrili1driver.cpp 32746 2016-01-05 05:18:43Z goatbar $");
 
 /************************************************************************/
 /*                                Open()                                */
@@ -39,8 +40,6 @@ CPL_CVSID("$Id: ogrili1driver.cpp 29109 2015-05-02 11:45:44Z rouault $");
 static GDALDataset *OGRILI1DriverOpen( GDALOpenInfo* poOpenInfo )
 
 {
-    OGRILI1DataSource    *poDS;
-
     if( poOpenInfo->eAccess == GA_Update ||
         (!poOpenInfo->bStatOK && strchr(poOpenInfo->pszFilename, ',') == NULL) )
         return NULL;
@@ -55,16 +54,17 @@ static GDALDataset *OGRILI1DriverOpen( GDALOpenInfo* poOpenInfo )
     else if( poOpenInfo->bIsDirectory )
         return NULL;
 
-    poDS = new OGRILI1DataSource();
+    OGRILI1DataSource *poDS = new OGRILI1DataSource();
 
-    if( !poDS->Open( poOpenInfo->pszFilename, poOpenInfo->papszOpenOptions, TRUE )
+    if( !poDS->Open( poOpenInfo->pszFilename, poOpenInfo->papszOpenOptions,
+                     TRUE )
         || poDS->GetLayerCount() == 0 )
     {
         delete poDS;
         return NULL;
     }
-    else
-        return poDS;
+
+    return poDS;
 }
 
 /************************************************************************/
@@ -72,21 +72,21 @@ static GDALDataset *OGRILI1DriverOpen( GDALOpenInfo* poOpenInfo )
 /************************************************************************/
 
 static GDALDataset *OGRILI1DriverCreate( const char * pszName,
-                                         CPL_UNUSED int nBands,
-                                         CPL_UNUSED int nXSize,
-                                         CPL_UNUSED int nYSize,
-                                         CPL_UNUSED GDALDataType eDT,
+                                         int /* nBands */,
+                                         int /* nXSize */,
+                                         int /* nYSize */,
+                                         GDALDataType /* eDT */,
                                          char **papszOptions )
 {
-    OGRILI1DataSource    *poDS = new OGRILI1DataSource();
+    OGRILI1DataSource *poDS = new OGRILI1DataSource();
 
     if( !poDS->Create( pszName, papszOptions ) )
     {
         delete poDS;
         return NULL;
     }
-    else
-        return poDS;
+
+    return poDS;
 }
 
 /************************************************************************/
@@ -94,28 +94,23 @@ static GDALDataset *OGRILI1DriverCreate( const char * pszName,
 /************************************************************************/
 
 void RegisterOGRILI1() {
-    GDALDriver  *poDriver;
-
-    if( GDALGetDriverByName( "Interlis 1" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    if( GDALGetDriverByName( "Interlis 1" ) != NULL )
+        return;
 
-        poDriver->SetDescription( "Interlis 1" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Interlis 1" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_ili.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "itf ili" );
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+    poDriver->SetDescription( "Interlis 1" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Interlis 1" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_ili.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "itf ili" );
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
 "<OpenOptionList>"
 "  <Option name='MODEL' type='string' description='Filename of the model in IlisMeta format (.imd)'/>"
 "</OpenOptionList>" );
 
-        poDriver->pfnOpen = OGRILI1DriverOpen;
-        poDriver->pfnCreate = OGRILI1DriverCreate;
+    poDriver->pfnOpen = OGRILI1DriverOpen;
+    poDriver->pfnCreate = OGRILI1DriverCreate;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/ili/ogrili1layer.cpp b/ogr/ogrsf_frmts/ili/ogrili1layer.cpp
index bebe707..dd93ff8 100644
--- a/ogr/ogrsf_frmts/ili/ogrili1layer.cpp
+++ b/ogr/ogrsf_frmts/ili/ogrili1layer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrili1layer.cpp 33156 2016-01-25 12:53:04Z rouault $
+ * $Id: ogrili1layer.cpp 33325 2016-02-02 14:30:48Z rouault $
  *
  * Project:  Interlis 1 Translator
  * Purpose:  Implements OGRILI1Layer class.
@@ -28,12 +28,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_ili1.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
 #include "ogr_geos.h"
+#include "ogr_ili1.h"
 
-CPL_CVSID("$Id: ogrili1layer.cpp 33156 2016-01-25 12:53:04Z rouault $");
+CPL_CVSID("$Id: ogrili1layer.cpp 33325 2016-02-02 14:30:48Z rouault $");
 
 /************************************************************************/
 /*                           OGRILI1Layer()                              */
@@ -41,21 +41,17 @@ CPL_CVSID("$Id: ogrili1layer.cpp 33156 2016-01-25 12:53:04Z rouault $");
 
 OGRILI1Layer::OGRILI1Layer( OGRFeatureDefn* poFeatureDefnIn,
                             GeomFieldInfos oGeomFieldInfosIn,
-                            OGRILI1DataSource *poDSIn )
-
+                            OGRILI1DataSource *poDSIn ) :
+    poFeatureDefn(poFeatureDefnIn),
+    oGeomFieldInfos(oGeomFieldInfosIn),
+    nFeatures(0),
+    papoFeatures(NULL),
+    nFeatureIdx(0),
+    bGeomsJoined(FALSE),
+    poDS(poDSIn)
 {
-    poDS = poDSIn;
-
-    poFeatureDefn = poFeatureDefnIn;
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
-    oGeomFieldInfos = oGeomFieldInfosIn;
-
-    nFeatures = 0;
-    papoFeatures = NULL;
-    nFeatureIdx = 0;
-
-    bGeomsJoined = FALSE;
 }
 
 /************************************************************************/
@@ -64,9 +60,7 @@ OGRILI1Layer::OGRILI1Layer( OGRFeatureDefn* poFeatureDefnIn,
 
 OGRILI1Layer::~OGRILI1Layer()
 {
-    int i;
-
-    for(i=0;i<nFeatures;i++)
+    for( int i=0; i < nFeatures; i++ )
     {
         delete papoFeatures[i];
     }
@@ -81,8 +75,8 @@ OGRErr OGRILI1Layer::AddFeature (OGRFeature *poFeature)
 {
     nFeatures++;
 
-    papoFeatures = (OGRFeature **)
-        CPLRealloc( papoFeatures, sizeof(void*) * nFeatures );
+    papoFeatures = static_cast<OGRFeature **>(
+        CPLRealloc( papoFeatures, sizeof(void*) * nFeatures ) );
 
     papoFeatures[nFeatures-1] = poFeature;
 
@@ -93,7 +87,8 @@ OGRErr OGRILI1Layer::AddFeature (OGRFeature *poFeature)
 /*                            ResetReading()                            */
 /************************************************************************/
 
-void OGRILI1Layer::ResetReading(){
+void OGRILI1Layer::ResetReading()
+{
     nFeatureIdx = 0;
 }
 
@@ -150,14 +145,29 @@ OGRFeature *OGRILI1Layer::GetFeatureRef( long nFID )
     return NULL;
 }
 
+OGRFeature *OGRILI1Layer::GetFeatureRef( const char *fid )
+
+{
+    OGRFeature *poFeature;
+
+    ResetReading();
+    while( (poFeature = GetNextFeatureRef()) != NULL )
+    {
+        if( !strcmp( poFeature->GetFieldAsString(0), fid ) )
+            return poFeature;
+    }
+
+    return NULL;
+}
+
 /************************************************************************/
 /*                          GetFeatureCount()                           */
 /************************************************************************/
 
 GIntBig OGRILI1Layer::GetFeatureCount( int bForce )
 {
-    if (m_poFilterGeom == NULL && m_poAttrQuery == NULL &&
-        1 /*poAreaLineLayer == NULL*/)
+    if (m_poFilterGeom == NULL && m_poAttrQuery == NULL
+        /* && poAreaLineLayer == NULL*/)
     {
         return nFeatures;
     }
@@ -167,37 +177,41 @@ GIntBig OGRILI1Layer::GetFeatureCount( int bForce )
     }
 }
 
-static char* d2str(double val)
+static const char* d2str(double val)
 {
-    static char strbuf[255];
-    if( val == (int) val )
-        sprintf( strbuf, "%d", (int) val );
-    else if( fabs(val) < 370 )
-        CPLsprintf( strbuf, "%.16g", val );
-    else if( fabs(val) > 100000000.0  )
-        CPLsprintf( strbuf, "%.16g", val );
-    else
-        CPLsprintf( strbuf, "%.3f", val );
-    return strbuf;
+    if( val == static_cast<int>(val) )
+        return CPLSPrintf("%d", static_cast<int>(val) );
+    if( fabs(val) < 370 )
+        return CPLSPrintf("%.16g", val );
+    if( fabs(val) > 100000000.0  )
+        return CPLSPrintf("%.16g", val );
+
+    return CPLSPrintf("%.3f", val );
 }
 
-static void AppendCoordinateList( OGRLineString *poLine, OGRILI1DataSource *poDS)
+static void AppendCoordinateList( OGRLineString *poLine,
+                                  OGRILI1DataSource *poDS )
 {
-    int         b3D = wkbHasZ(poLine->getGeometryType());
+    const bool b3D = CPL_TO_BOOL(wkbHasZ(poLine->getGeometryType()));
 
     for( int iPoint = 0; iPoint < poLine->getNumPoints(); iPoint++ )
     {
         if (iPoint == 0) VSIFPrintf( poDS->GetTransferFile(), "STPT" );
         else VSIFPrintf( poDS->GetTransferFile(), "LIPT" );
-        VSIFPrintf( poDS->GetTransferFile(), " %s", d2str(poLine->getX(iPoint)) );
-        VSIFPrintf( poDS->GetTransferFile(), " %s", d2str(poLine->getY(iPoint)) );
-        if (b3D) VSIFPrintf( poDS->GetTransferFile(), " %s", d2str(poLine->getZ(iPoint)) );
+        VSIFPrintf( poDS->GetTransferFile(), " %s",
+                    d2str(poLine->getX(iPoint)) );
+        VSIFPrintf( poDS->GetTransferFile(), " %s",
+                    d2str(poLine->getY(iPoint)) );
+        if( b3D )
+            VSIFPrintf( poDS->GetTransferFile(), " %s",
+                        d2str(poLine->getZ(iPoint)) );
         VSIFPrintf( poDS->GetTransferFile(), "\n" );
     }
     VSIFPrintf( poDS->GetTransferFile(), "ELIN\n" );
 }
 
-static void AppendCoumpoundCurve( OGRCompoundCurve *poCC, OGRILI1DataSource *poDS)
+static void AppendCoumpoundCurve( OGRCompoundCurve *poCC,
+                                  OGRILI1DataSource *poDS )
 {
     for( int iMember = 0; iMember < poCC->getNumCurves(); iMember++)
     {
@@ -225,7 +239,10 @@ static void AppendCoumpoundCurve( OGRCompoundCurve *poCC, OGRILI1DataSource *poD
 
 int OGRILI1Layer::GeometryAppend( OGRGeometry *poGeometry )
 {
-    //CPLDebug( "OGR_ILI", "OGRILI1Layer::GeometryAppend OGRGeometryType: %s", OGRGeometryTypeToName(poGeometry->getGeometryType()));
+#ifdef DEBUG_VERBOSE
+    CPLDebug( "OGR_ILI", "OGRILI1Layer::GeometryAppend OGRGeometryType: %s",
+              OGRGeometryTypeToName(poGeometry->getGeometryType()) );
+#endif
 /* -------------------------------------------------------------------- */
 /*      2D Point                                                        */
 /* -------------------------------------------------------------------- */
@@ -247,7 +264,8 @@ int OGRILI1Layer::GeometryAppend( OGRGeometry *poGeometry )
     else if( poGeometry->getGeometryType() == wkbLineString
              || poGeometry->getGeometryType() == wkbLineString25D )
     {
-        AppendCoordinateList( (OGRLineString *) poGeometry, poDS );
+        AppendCoordinateList( reinterpret_cast<OGRLineString *>(poGeometry),
+                              poDS );
     }
 
 /* -------------------------------------------------------------------- */
@@ -256,7 +274,7 @@ int OGRILI1Layer::GeometryAppend( OGRGeometry *poGeometry )
     else if( poGeometry->getGeometryType() == wkbPolygon
              || poGeometry->getGeometryType() == wkbPolygon25D )
     {
-        OGRPolygon      *poPolygon = (OGRPolygon *) poGeometry;
+        OGRPolygon *poPolygon = reinterpret_cast<OGRPolygon *>(poGeometry);
 
         if( poPolygon->getExteriorRing() != NULL )
         {
@@ -284,8 +302,9 @@ int OGRILI1Layer::GeometryAppend( OGRGeometry *poGeometry )
              || wkbFlatten(poGeometry->getGeometryType()) == wkbMultiCurveZ )
     {
         OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeometry;
-        int             iMember;
 
+#if 0
+        // TODO: Why this large NOP block?
         if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPolygon )
         {
         }
@@ -298,8 +317,9 @@ int OGRILI1Layer::GeometryAppend( OGRGeometry *poGeometry )
         else
         {
         }
+#endif
 
-        for( iMember = 0; iMember < poGC->getNumGeometries(); iMember++)
+        for( int iMember = 0; iMember < poGC->getNumGeometries(); iMember++ )
         {
             OGRGeometry *poMember = poGC->getGeometryRef( iMember );
             if( !GeometryAppend( poMember ) )
@@ -310,9 +330,12 @@ int OGRILI1Layer::GeometryAppend( OGRGeometry *poGeometry )
     else if( poGeometry->getGeometryType() == wkbCompoundCurve
              || poGeometry->getGeometryType() == wkbCompoundCurveZ )
     {
-        AppendCoumpoundCurve( ( OGRCompoundCurve *) poGeometry, poDS );
+        AppendCoumpoundCurve( reinterpret_cast<OGRCompoundCurve *>(poGeometry),
+                              poDS );
     } else {
-        CPLError(CE_Warning, CPLE_AppDefined, "Skipping unknown geometry type '%s'", OGRGeometryTypeToName(poGeometry->getGeometryType()));
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Skipping unknown geometry type '%s'",
+                  OGRGeometryTypeToName(poGeometry->getGeometryType()) );
         return FALSE;
     }
 
@@ -327,7 +350,8 @@ OGRErr OGRILI1Layer::ICreateFeature( OGRFeature *poFeature ) {
     static long tid = -1; //system generated TID (must be unique within table)
     VSIFPrintf( poDS->GetTransferFile(), "OBJE" );
 
-    if ( poFeatureDefn->GetFieldCount() && !EQUAL(poFeatureDefn->GetFieldDefn(0)->GetNameRef(), "TID") )
+    if ( poFeatureDefn->GetFieldCount() &&
+         !EQUAL(poFeatureDefn->GetFieldDefn(0)->GetNameRef(), "TID") )
     {
         //Input is not generated from an Interlis 1 source
         if (poFeature->GetFID() != OGRNullFID)
@@ -342,32 +366,38 @@ OGRErr OGRILI1Layer::ICreateFeature( OGRFeature *poFeature ) {
             // 2D Point
             if( poGeometry->getGeometryType() == wkbPoint )
             {
-                OGRPoint *poPoint = (OGRPoint *) poGeometry;
+                OGRPoint *poPoint = reinterpret_cast<OGRPoint *>(poGeometry);
 
-                VSIFPrintf( poDS->GetTransferFile(), " %s", d2str(poPoint->getX()) );
-                VSIFPrintf( poDS->GetTransferFile(), " %s", d2str(poPoint->getY()) );
+                VSIFPrintf( poDS->GetTransferFile(), " %s",
+                            d2str(poPoint->getX()) );
+                VSIFPrintf( poDS->GetTransferFile(), " %s",
+                            d2str(poPoint->getY()) );
             }
             // 3D Point
             else if( poGeometry->getGeometryType() == wkbPoint25D )
             {
-                OGRPoint *poPoint = (OGRPoint *) poGeometry;
-
-                VSIFPrintf( poDS->GetTransferFile(), " %s", d2str(poPoint->getX()) );
-                VSIFPrintf( poDS->GetTransferFile(), " %s", d2str(poPoint->getY()) );
-                VSIFPrintf( poDS->GetTransferFile(), " %s", d2str(poPoint->getZ()) );
+                OGRPoint *poPoint = reinterpret_cast<OGRPoint *>(poGeometry);
+
+                VSIFPrintf( poDS->GetTransferFile(), " %s",
+                            d2str(poPoint->getX()) );
+                VSIFPrintf( poDS->GetTransferFile(), " %s",
+                            d2str(poPoint->getY()) );
+                VSIFPrintf( poDS->GetTransferFile(), " %s",
+                            d2str(poPoint->getZ()) );
             }
         }
     }
 
     // Write all fields.
-    for(int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
+    for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     {
         if ( poFeature->IsFieldSet( iField ) )
         {
           const char *pszRaw = poFeature->GetFieldAsString( iField );
           if (poFeatureDefn->GetFieldDefn( iField )->GetType() == OFTString) {
               //Interlis 1 encoding is ISO 8859-1 (Latin1) -> Recode from UTF-8
-              char* pszString  = CPLRecode(pszRaw, CPL_ENC_UTF8, CPL_ENC_ISO8859_1);
+              char* pszString
+                  = CPLRecode( pszRaw, CPL_ENC_UTF8, CPL_ENC_ISO8859_1 );
               //Replace spaces
               for(size_t i=0; i<strlen(pszString); i++ ) {
                   if (pszString[i] == ' ') pszString[i] = '_';
@@ -401,15 +431,15 @@ OGRErr OGRILI1Layer::ICreateFeature( OGRFeature *poFeature ) {
 int OGRILI1Layer::TestCapability( CPL_UNUSED const char * pszCap ) {
     if( EQUAL(pszCap,OLCCurveGeometries) )
         return TRUE;
-    else
-        return FALSE;
+
+    return FALSE;
 }
 
 /************************************************************************/
 /*                            CreateField()                             */
 /************************************************************************/
 
-OGRErr OGRILI1Layer::CreateField( OGRFieldDefn *poField, CPL_UNUSED int bApproxOK ) {
+OGRErr OGRILI1Layer::CreateField( OGRFieldDefn *poField, int /* bApproxOK */ ) {
     poFeatureDefn->AddFieldDefn( poField );
 
     return OGRERR_NONE;
@@ -422,22 +452,27 @@ OGRErr OGRILI1Layer::CreateField( OGRFieldDefn *poField, CPL_UNUSED int bApproxO
 
 void OGRILI1Layer::JoinGeomLayers()
 {
-    bGeomsJoined = TRUE;
-    int bResetConfigOption = FALSE;
+    bGeomsJoined = true;
+    bool bResetConfigOption = false;
     if (EQUAL(CPLGetConfigOption("OGR_ARC_STEPSIZE", ""), ""))
     {
-        bResetConfigOption = TRUE;
+        bResetConfigOption = true;
         CPLSetThreadLocalConfigOption("OGR_ARC_STEPSIZE", "0.96");
     }
 
-    for (GeomFieldInfos::const_iterator it = oGeomFieldInfos.begin(); it != oGeomFieldInfos.end(); ++it)
+    for( GeomFieldInfos::const_iterator it = oGeomFieldInfos.begin();
+         it != oGeomFieldInfos.end();
+         ++it )
     {
-        OGRFeatureDefn* geomFeatureDefn = it->second.geomTable;
+        OGRFeatureDefn* geomFeatureDefn = it->second.GetGeomTableDefnRef();
         if (geomFeatureDefn)
         {
-            CPLDebug( "OGR_ILI", "Join geometry table %s of field '%s'", geomFeatureDefn->GetName(), it->first.c_str() );
-            OGRILI1Layer* poGeomLayer = poDS->GetLayerByName(geomFeatureDefn->GetName());
-            int nGeomFieldIndex = GetLayerDefn()->GetGeomFieldIndex(it->first.c_str());
+            CPLDebug( "OGR_ILI", "Join geometry table %s of field '%s'",
+                      geomFeatureDefn->GetName(), it->first.c_str() );
+            OGRILI1Layer* poGeomLayer
+                = poDS->GetLayerByName(geomFeatureDefn->GetName());
+            const int nGeomFieldIndex
+                = GetLayerDefn()->GetGeomFieldIndex(it->first.c_str());
             if (it->second.iliGeomType == "Surface")
             {
                 JoinSurfaceLayer(poGeomLayer, nGeomFieldIndex);
@@ -445,8 +480,10 @@ void OGRILI1Layer::JoinGeomLayers()
             else if (it->second.iliGeomType == "Area")
             {
                 CPLString pointField = it->first + "__Point";
-                int nPointFieldIndex = GetLayerDefn()->GetGeomFieldIndex(pointField.c_str());
-                PolygonizeAreaLayer(poGeomLayer, nGeomFieldIndex, nPointFieldIndex);
+                const int nPointFieldIndex
+                    = GetLayerDefn()->GetGeomFieldIndex( pointField.c_str() );
+                PolygonizeAreaLayer( poGeomLayer, nGeomFieldIndex,
+                                     nPointFieldIndex);
             }
         }
     }
@@ -456,36 +493,46 @@ void OGRILI1Layer::JoinGeomLayers()
 }
 
 
-void OGRILI1Layer::JoinSurfaceLayer( OGRILI1Layer* poSurfaceLineLayer, int nSurfaceFieldIndex )
+void OGRILI1Layer::JoinSurfaceLayer( OGRILI1Layer* poSurfaceLineLayer,
+                                     int nSurfaceFieldIndex )
 {
-    CPLDebug( "OGR_ILI", "Joining surface layer %s with geometries", GetLayerDefn()->GetName());
-    OGRwkbGeometryType geomType = GetLayerDefn()->GetGeomFieldDefn(nSurfaceFieldIndex)->GetType();
-    OGRCompoundCurve *surface_lines = 0; // collected lines of SURFACE polygon ring
+    CPLDebug( "OGR_ILI", "Joining surface layer %s with geometries",
+              GetLayerDefn()->GetName());
+    OGRwkbGeometryType geomType
+        = GetLayerDefn()->GetGeomFieldDefn(nSurfaceFieldIndex)->GetType();
+    OGRCompoundCurve *surface_lines = NULL; // collected lines of SURFACE polygon ring
     poSurfaceLineLayer->ResetReading();
     while (OGRFeature *linefeature = poSurfaceLineLayer->GetNextFeatureRef()) {
         //OBJE entries with same _RefTID are polygon rings of same feature
-        //TODO: non-numeric _RefTID/FID is not supported yet!
-        GIntBig reftid = linefeature->GetFieldAsInteger64(1); //_RefTID
-        OGRFeature *feature = GetFeatureRef((int)reftid);
+        OGRFeature *feature;
+        if (poFeatureDefn->GetFieldDefn(0)->GetType() == OFTString)
+        {
+          feature = GetFeatureRef(linefeature->GetFieldAsString(1));
+        }
+        else
+        {
+          GIntBig reftid = linefeature->GetFieldAsInteger64(1);
+          feature = GetFeatureRef((int)reftid);
+        }
         if (feature) {
-            OGRCurvePolygon *poly;
-            if (feature->GetGeomFieldRef(nSurfaceFieldIndex)) {
-                CPLDebug( "OGR_ILI", "Appending lines to FID " CPL_FRMT_GIB, reftid );
-                poly = (OGRCurvePolygon *)feature->GetGeomFieldRef(nSurfaceFieldIndex);
-            } else {
-                poly = (geomType == wkbPolygon) ? new OGRPolygon() : new OGRCurvePolygon();
-                feature->SetGeomFieldDirectly(nSurfaceFieldIndex, poly);
+            if (!feature->GetGeomFieldRef(nSurfaceFieldIndex)) {
+                OGRCurvePolygon *newpoly = (geomType == wkbPolygon) ?
+                    new OGRPolygon() : new OGRCurvePolygon();
+                feature->SetGeomFieldDirectly(nSurfaceFieldIndex, newpoly);
             }
-            OGRMultiCurve *lines = (OGRMultiCurve*)linefeature->GetGeomFieldRef(0);
+            OGRCurvePolygon *poly = reinterpret_cast<OGRCurvePolygon *>(
+                        feature->GetGeomFieldRef(nSurfaceFieldIndex) );
+            OGRMultiCurve *lines = reinterpret_cast<OGRMultiCurve *>(
+                linefeature->GetGeomFieldRef(0) );
             for( int i = 0; i < lines->getNumGeometries(); i++ ) {
-                OGRCurve *line = (OGRCurve*)lines->getGeometryRef(i);
-                OGRCurve *ring = 0;
+                OGRCurve *line = reinterpret_cast<OGRCurve*>(lines->getGeometryRef(i));
+                OGRCurve *ring = NULL;
                 if (surface_lines) {
                     //SURFACE polygon lines spread over multiple OBJECTs, so we collect curves
                     if (line->getGeometryType() == wkbCompoundCurve) {
-                        OGRCompoundCurve* ccurve = (OGRCompoundCurve*)line;
+                        OGRCompoundCurve* ccurve = reinterpret_cast<OGRCompoundCurve *>(line);
                         for (int j=0; j<ccurve->getNumCurves(); j++) {
-                            surface_lines->addCurveDirectly(ccurve->getCurve(j));
+                            surface_lines->addCurve(ccurve->getCurve(j));
                         }
                     } else { // wkbLineString (linearized)
                         surface_lines->addCurve(line);
@@ -494,23 +541,25 @@ void OGRILI1Layer::JoinSurfaceLayer( OGRILI1Layer* poSurfaceLineLayer, int nSurf
                 }
                 if (line->get_IsClosed()) {
                     if (geomType == wkbPolygon) {
-                        ring = OGRCurve::CastToLinearRing((OGRCurve*)line->clone());
+                        ring = OGRCurve::CastToLinearRing(reinterpret_cast<OGRCurve*>(
+                                 line->clone()));
                     } else { // wkbMultiCurve
-                        ring = (OGRCurve*)line->clone();
+                        ring = reinterpret_cast<OGRCurve*>(line->clone());
+                    }
+                    if( line == surface_lines ) {
+                        delete surface_lines;
+                        surface_lines = NULL;
+                        line = NULL; /* to make CLang Static Analyzer happy */
                     }
                 }
-                if (ring == 0 && surface_lines == 0) {
+                if (ring == NULL && surface_lines == NULL && line != NULL) {
                     //SURFACE polygon lines spread over multiple OBJECTs, so we collect curves
                     if (line->getGeometryType() == wkbCompoundCurve) {
-                        surface_lines = (OGRCompoundCurve*)line->clone();
+                        surface_lines = reinterpret_cast<OGRCompoundCurve *>(line->clone());
                     } else { // wkbLineString (linearized)
                         surface_lines = new OGRCompoundCurve();
                         surface_lines->addCurve(line);
                     }
-                    if( line == surface_lines ) {
-                        delete surface_lines;
-                        surface_lines = NULL;
-                    }
                 }
                 if (ring) {
                     OGRErr error = poly->addRingDirectly(ring);
@@ -520,23 +569,29 @@ void OGRILI1Layer::JoinSurfaceLayer( OGRILI1Layer* poSurfaceLineLayer, int nSurf
                 }
             }
         } else {
-            CPLError(CE_Warning, CPLE_AppDefined, "Couldn't join feature FID " CPL_FRMT_GIB, reftid );
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Couldn't join feature FID " CPL_FRMT_GIB, linefeature->GetFieldAsInteger64(1) );
         }
     }
 
     ResetReading();
-    poSurfaceLineLayer = 0;
+    poSurfaceLineLayer = NULL;
 }
 
-OGRMultiPolygon* OGRILI1Layer::Polygonize( OGRGeometryCollection* poLines, bool fix_crossing_lines )
+OGRMultiPolygon* OGRILI1Layer::Polygonize( OGRGeometryCollection* poLines,
+                                           bool
+                                           #if defined(HAVE_GEOS)
+                                            fix_crossing_lines
+                                           #endif
+                                           )
 {
-    OGRMultiPolygon *poPolygon = new OGRMultiPolygon();
-
-    if (poLines->getNumGeometries() == 0) return poPolygon;
+    if (poLines->getNumGeometries() == 0)
+    {
+        return new OGRMultiPolygon();
+    }
 
 #if defined(HAVE_GEOS)
     GEOSGeom *ahInGeoms = NULL;
-    int       i = 0;
     OGRGeometryCollection *poNoncrossingLines = poLines;
     GEOSGeom hResultGeom = NULL;
     OGRGeometry *poMP = NULL;
@@ -544,30 +599,50 @@ OGRMultiPolygon* OGRILI1Layer::Polygonize( OGRGeometryCollection* poLines, bool
     if (fix_crossing_lines && poLines->getNumGeometries() > 0)
     {
         CPLDebug( "OGR_ILI", "Fixing crossing lines");
-        //A union of the geometry collection with one line fixes invalid geometries
-        poNoncrossingLines = (OGRGeometryCollection*)poLines->Union(poLines->getGeometryRef(0));
-        CPLDebug( "OGR_ILI", "Fixed lines: %d", poNoncrossingLines->getNumGeometries()-poLines->getNumGeometries());
+        // A union of the geometry collection with one line fixes
+        // invalid geometries.
+        OGRGeometry* poUnion = poLines->Union(poLines->getGeometryRef(0));
+        if( poUnion != NULL )
+        {
+            if( wkbFlatten(poUnion->getGeometryType()) ==
+                wkbGeometryCollection ||
+                wkbFlatten(poUnion->getGeometryType()) == wkbMultiLineString )
+            {
+                poNoncrossingLines
+                    = dynamic_cast<OGRGeometryCollection*>(poUnion);
+                CPLDebug( "OGR_ILI", "Fixed lines: %d",
+                          poNoncrossingLines->getNumGeometries()-poLines->
+                          getNumGeometries());
+            }
+            else
+            {
+                delete poUnion;
+            }
+        }
     }
-    
+
     GEOSContextHandle_t hGEOSCtxt = OGRGeometry::createGEOSContext();
 
-    ahInGeoms = (GEOSGeom *) CPLCalloc(sizeof(void*),poNoncrossingLines->getNumGeometries());
-    for( i = 0; i < poNoncrossingLines->getNumGeometries(); i++ )
-          ahInGeoms[i] = poNoncrossingLines->getGeometryRef(i)->exportToGEOS(hGEOSCtxt);
+    ahInGeoms = static_cast<GEOSGeom *>(
+        CPLCalloc(sizeof(void*),poNoncrossingLines->getNumGeometries()) );
+    for( int i = 0; i < poNoncrossingLines->getNumGeometries(); i++ )
+          ahInGeoms[i] = poNoncrossingLines->getGeometryRef(i)->
+              exportToGEOS(hGEOSCtxt);
 
     hResultGeom = GEOSPolygonize_r( hGEOSCtxt,
                                     ahInGeoms,
-                                   poNoncrossingLines->getNumGeometries() );
+                                    poNoncrossingLines->getNumGeometries() );
 
-    for( i = 0; i < poNoncrossingLines->getNumGeometries(); i++ )
+    for( int i = 0; i < poNoncrossingLines->getNumGeometries(); i++ )
         GEOSGeom_destroy_r( hGEOSCtxt, ahInGeoms[i] );
     CPLFree( ahInGeoms );
-    if (poNoncrossingLines != poLines) delete poNoncrossingLines;
+    if (poNoncrossingLines != poLines)
+        delete poNoncrossingLines;
 
     if( hResultGeom == NULL )
     {
         OGRGeometry::freeGEOSContext( hGEOSCtxt );
-        return NULL;
+        return new OGRMultiPolygon();
     }
 
     poMP = OGRGeometryFactory::createFromGEOS( hGEOSCtxt, hResultGeom );
@@ -575,15 +650,29 @@ OGRMultiPolygon* OGRILI1Layer::Polygonize( OGRGeometryCollection* poLines, bool
     GEOSGeom_destroy_r( hGEOSCtxt, hResultGeom );
     OGRGeometry::freeGEOSContext( hGEOSCtxt );
 
-    return (OGRMultiPolygon *) poMP;
+    poMP = OGRGeometryFactory::forceToMultiPolygon( poMP );
+    if( poMP && wkbFlatten(poMP->getGeometryType()) == wkbMultiPolygon )
+        return dynamic_cast<OGRMultiPolygon *>(poMP);
 
-#endif
+    delete poMP;
+    return new OGRMultiPolygon();
 
-    return poPolygon;
+#else
+    return new OGRMultiPolygon();
+#endif
 }
 
 
-void OGRILI1Layer::PolygonizeAreaLayer( OGRILI1Layer* poAreaLineLayer, int nAreaFieldIndex, int nPointFieldIndex )
+void OGRILI1Layer::PolygonizeAreaLayer( OGRILI1Layer* poAreaLineLayer,
+                                        int
+#if defined(HAVE_GEOS)
+                                            nAreaFieldIndex
+#endif
+                                        , int
+#if defined(HAVE_GEOS)
+                                            nPointFieldIndex
+#endif
+                                        )
 {
     //add all lines from poAreaLineLayer to collection
     OGRGeometryCollection *gc = new OGRGeometryCollection();
@@ -592,30 +681,35 @@ void OGRILI1Layer::PolygonizeAreaLayer( OGRILI1Layer* poAreaLineLayer, int nArea
         gc->addGeometry(feature->GetGeometryRef());
 
     //polygonize lines
-    CPLDebug( "OGR_ILI", "Polygonizing layer %s with %d multilines", poAreaLineLayer->GetLayerDefn()->GetName(), gc->getNumGeometries());
-    poAreaLineLayer = 0;
+    CPLDebug( "OGR_ILI", "Polygonizing layer %s with %d multilines",
+              poAreaLineLayer->GetLayerDefn()->GetName(),
+              gc->getNumGeometries());
+    poAreaLineLayer = NULL;
     OGRMultiPolygon* polys = Polygonize( gc , false);
     CPLDebug( "OGR_ILI", "Resulting polygons: %d", polys->getNumGeometries());
     if (polys->getNumGeometries() != GetFeatureCount())
     {
-        CPLDebug( "OGR_ILI", "Feature count of layer %s: " CPL_FRMT_GIB, GetLayerDefn()->GetName(), GetFeatureCount());
+        CPLDebug( "OGR_ILI", "Feature count of layer %s: " CPL_FRMT_GIB,
+                  GetLayerDefn()->GetName(), GetFeatureCount());
         CPLDebug( "OGR_ILI", "Polygonizing again with crossing line fix");
         delete polys;
         polys = Polygonize( gc, true ); //try again with crossing line fix
-        CPLDebug( "OGR_ILI", "Resulting polygons: %d", polys->getNumGeometries());
+        CPLDebug( "OGR_ILI", "Resulting polygons: %d",
+                  polys->getNumGeometries());
     }
     delete gc;
 
     //associate polygon feature with data row according to centroid
 #if defined(HAVE_GEOS)
-    int i;
     OGRPolygon emptyPoly;
     GEOSGeom *ahInGeoms = NULL;
 
-    CPLDebug( "OGR_ILI", "Associating layer %s with area polygons", GetLayerDefn()->GetName());
-    ahInGeoms = (GEOSGeom *) CPLCalloc(sizeof(void*), polys->getNumGeometries());
+    CPLDebug( "OGR_ILI", "Associating layer %s with area polygons",
+              GetLayerDefn()->GetName());
+    ahInGeoms = static_cast<GEOSGeom *>(
+        CPLCalloc(sizeof(void*), polys->getNumGeometries() ) );
     GEOSContextHandle_t hGEOSCtxt = OGRGeometry::createGEOSContext();
-    for( i = 0; i < polys->getNumGeometries(); i++ )
+    for( int i = 0; i < polys->getNumGeometries(); i++ )
     {
         ahInGeoms[i] = polys->getGeometryRef(i)->exportToGEOS(hGEOSCtxt);
         if (!GEOSisValid_r(hGEOSCtxt, ahInGeoms[i])) ahInGeoms[i] = NULL;
@@ -628,12 +722,16 @@ void OGRILI1Layer::PolygonizeAreaLayer( OGRILI1Layer* poAreaLineLayer, int nArea
         {
             continue;
         }
-        GEOSGeom point = (GEOSGeom)(geomRef->exportToGEOS(hGEOSCtxt));
-        for (i = 0; i < polys->getNumGeometries(); i++ )
+        GEOSGeom point = reinterpret_cast<GEOSGeom>(
+            geomRef->exportToGEOS(hGEOSCtxt) );
+
+        int i = 0;
+        for ( ; i < polys->getNumGeometries(); i++ )
         {
             if (ahInGeoms[i] && GEOSWithin_r(hGEOSCtxt, point, ahInGeoms[i]))
             {
-                feature->SetGeomField(nAreaFieldIndex, polys->getGeometryRef(i));
+                feature->SetGeomField( nAreaFieldIndex,
+                                       polys->getGeometryRef(i));
                 break;
             }
         }
@@ -644,11 +742,11 @@ void OGRILI1Layer::PolygonizeAreaLayer( OGRILI1Layer* poAreaLineLayer, int nArea
         }
         GEOSGeom_destroy_r( hGEOSCtxt, point );
     }
-    for( i = 0; i < polys->getNumGeometries(); i++ )
+    for( int i = 0; i < polys->getNumGeometries(); i++ )
         GEOSGeom_destroy_r( hGEOSCtxt, ahInGeoms[i] );
     CPLFree( ahInGeoms );
     OGRGeometry::freeGEOSContext( hGEOSCtxt );
 #endif
-    poAreaLineLayer = 0;
+    poAreaLineLayer = NULL;
     delete polys;
 }
diff --git a/ogr/ogrsf_frmts/ili/ogrili2datasource.cpp b/ogr/ogrsf_frmts/ili/ogrili2datasource.cpp
index 8d89139..b35d6d5 100644
--- a/ogr/ogrsf_frmts/ili/ogrili2datasource.cpp
+++ b/ogr/ogrsf_frmts/ili/ogrili2datasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrili2datasource.cpp 29140 2015-05-03 20:09:32Z pka $
+ * $Id: ogrili2datasource.cpp 32797 2016-01-07 19:49:33Z rouault $
  *
  * Project:  Interlis 2 Translator
  * Purpose:  Implements OGRILI2DataSource class.
@@ -28,31 +28,30 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_ili2.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
 #include "ili2reader.h"
 
+#include "ogr_ili2.h"
+
 using namespace std;
 
 
-CPL_CVSID("$Id: ogrili2datasource.cpp 29140 2015-05-03 20:09:32Z pka $");
+CPL_CVSID("$Id: ogrili2datasource.cpp 32797 2016-01-07 19:49:33Z rouault $");
 
 /************************************************************************/
 /*                         OGRILI2DataSource()                         */
 /************************************************************************/
 
-OGRILI2DataSource::OGRILI2DataSource()
-
-{
-    pszName = NULL;
-    poImdReader = new ImdReader(2);
-    poReader = NULL;
-    fpOutput = NULL;
-    nLayers = 0;
-    papoLayers = NULL;
-}
+OGRILI2DataSource::OGRILI2DataSource() :
+    pszName(NULL),
+    poImdReader(new ImdReader(2)),
+    poReader(NULL),
+    fpOutput(NULL),
+    nLayers(0),
+    papoLayers(NULL)
+{}
 
 /************************************************************************/
 /*                        ~OGRILI2DataSource()                         */
@@ -61,9 +60,7 @@ OGRILI2DataSource::OGRILI2DataSource()
 OGRILI2DataSource::~OGRILI2DataSource()
 
 {
-    int i;
-
-    for(i=0;i<nLayers;i++)
+    for( int i=0; i<nLayers; i++ )
     {
         delete papoLayers[i];
     }
@@ -86,18 +83,17 @@ OGRILI2DataSource::~OGRILI2DataSource()
 /*                                Open()                                */
 /************************************************************************/
 
-int OGRILI2DataSource::Open( const char * pszNewName, char** papszOpenOptions, int bTestOpen )
+int OGRILI2DataSource::Open( const char * pszNewName,
+                             char** papszOpenOptionsIn, int bTestOpen )
 
 {
-    FILE        *fp;
-    char        szHeader[1000];
     CPLString   osBasename;
     CPLString   osModelFilename;
 
-    if( CSLFetchNameValue(papszOpenOptions, "MODEL") != NULL )
+    if( CSLFetchNameValue(papszOpenOptionsIn, "MODEL") != NULL )
     {
         osBasename = pszNewName;
-        osModelFilename = CSLFetchNameValue(papszOpenOptions, "MODEL");
+        osModelFilename = CSLFetchNameValue(papszOpenOptionsIn, "MODEL");
     }
     else
     {
@@ -116,7 +112,7 @@ int OGRILI2DataSource::Open( const char * pszNewName, char** papszOpenOptions, i
 /* -------------------------------------------------------------------- */
 /*      Open the source file.                                           */
 /* -------------------------------------------------------------------- */
-    fp = VSIFOpen( pszName, "r" );
+    FILE *fp = VSIFOpen( pszName, "r" );
     if( fp == NULL )
     {
         if( !bTestOpen )
@@ -128,38 +124,41 @@ int OGRILI2DataSource::Open( const char * pszNewName, char** papszOpenOptions, i
     }
 
 /* -------------------------------------------------------------------- */
-/*      If we aren't sure it is ILI2, load a header chunk and check      */
-/*      for signs it is ILI2                                             */
+/*      If we aren't sure it is ILI2, load a header chunk and check     */
+/*      for signs it is ILI2                                            */
 /* -------------------------------------------------------------------- */
+    char szHeader[1000];
     if( bTestOpen )
     {
-        int nLen = (int)VSIFRead( szHeader, 1, sizeof(szHeader), fp );
+        int nLen = static_cast<int>(
+            VSIFRead( szHeader, 1, sizeof(szHeader), fp ) );
         if (nLen == sizeof(szHeader))
             szHeader[sizeof(szHeader)-1] = '\0';
         else
             szHeader[nLen] = '\0';
 
-        if( szHeader[0] != '<' 
+        if( szHeader[0] != '<'
             || strstr(szHeader,"interlis.ch/INTERLIS2") == NULL )
-        { // "www.interlis.ch/INTERLIS2.3"
+        {
+            // "www.interlis.ch/INTERLIS2.3"
             VSIFClose( fp );
             return FALSE;
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
-/*      We assume now that it is ILI2.  Close and instantiate a          */
-/*      ILI2Reader on it.                                                */
+/*      We assume now that it is ILI2.  Close and instantiate a         */
+/*      ILI2Reader on it.                                               */
 /* -------------------------------------------------------------------- */
     VSIFClose( fp );
-    
+
     poReader = CreateILI2Reader();
     if( poReader == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "File %s appears to be ILI2 but the ILI2 reader can't\n"
-                  "be instantiated, likely because Xerces support wasn't\n"
-                  "configured in.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "File %s appears to be ILI2 but the ILI2 reader cannot\n"
+                  "be instantiated, likely because Xerces support was not\n"
+                  "configured in.",
                   pszNewName );
         return FALSE;
     }
@@ -207,16 +206,17 @@ int OGRILI2DataSource::Create( const char *pszFilename,
 /* -------------------------------------------------------------------- */
 
     if( strcmp(pszName,"/vsistdout/") == 0 ||
-        strncmp(pszName,"/vsigzip/", 9) == 0 )
+        STARTS_WITH(pszName, "/vsigzip/") )
     {
         fpOutput = VSIFOpenL(pszName, "wb");
     }
-    else if ( strncmp(pszName,"/vsizip/", 8) == 0)
+    else if ( STARTS_WITH(pszName, "/vsizip/"))
     {
         if (EQUAL(CPLGetExtension(pszName), "zip"))
         {
+            char* pszNewName = CPLStrdup(CPLFormFilename(pszName, "out.xtf", NULL));
             CPLFree(pszName);
-            pszName = CPLStrdup(CPLFormFilename(pszName, "out.xtf", NULL));
+            pszName = pszNewName;
         }
 
         fpOutput = VSIFOpenL(pszName, "wb");
@@ -242,13 +242,19 @@ int OGRILI2DataSource::Create( const char *pszFilename,
 /*      Write headers                                                   */
 /* -------------------------------------------------------------------- */
     VSIFPrintfL(fpOutput, "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
-    VSIFPrintfL(fpOutput, "<TRANSFER xmlns=\"http://www.interlis.ch/INTERLIS2.3\">\n");
-    VSIFPrintfL(fpOutput, "<HEADERSECTION SENDER=\"OGR/GDAL %s\" VERSION=\"2.3\">\n", GDAL_RELEASE_NAME);
+    VSIFPrintfL( fpOutput,
+                 "<TRANSFER xmlns=\"http://www.interlis.ch/INTERLIS2.3\">\n");
+    VSIFPrintfL( fpOutput,
+                 "<HEADERSECTION SENDER=\"OGR/GDAL %s\" VERSION=\"2.3\">\n",
+                 GDAL_RELEASE_NAME);
     VSIFPrintfL(fpOutput, "<MODELS>\n");
-    for (IliModelInfos::const_iterator it = poImdReader->modelInfos.begin(); it != poImdReader->modelInfos.end(); ++it)
+    for( IliModelInfos::const_iterator it = poImdReader->modelInfos.begin();
+         it != poImdReader->modelInfos.end();
+         ++it)
     {
-        VSIFPrintfL(fpOutput, "<MODEL NAME=\"%s\" URI=\"%s\" VERSION=\"%s\"/>\n",
-            it->name.c_str(), it->uri.c_str(), it->version.c_str());
+        VSIFPrintfL( fpOutput,
+                     "<MODEL NAME=\"%s\" URI=\"%s\" VERSION=\"%s\"/>\n",
+                     it->name.c_str(), it->uri.c_str(), it->version.c_str() );
     }
     VSIFPrintfL(fpOutput, "</MODELS>\n");
     VSIFPrintfL(fpOutput, "</HEADERSECTION>\n");
@@ -266,26 +272,30 @@ int OGRILI2DataSource::Create( const char *pszFilename,
 
 OGRLayer *
 OGRILI2DataSource::ICreateLayer( const char * pszLayerName,
-                                 CPL_UNUSED OGRSpatialReference *poSRS,
+                                 OGRSpatialReference * /* poSRS */,
                                  OGRwkbGeometryType eType,
-                                 CPL_UNUSED char ** papszOptions )
+                                 char ** /* papszOptions */ )
 {
     if (fpOutput == NULL)
         return NULL;
 
-    FeatureDefnInfo featureDefnInfo = poImdReader->GetFeatureDefnInfo(pszLayerName);
-    OGRFeatureDefn* poFeatureDefn = featureDefnInfo.poTableDefn;
+    FeatureDefnInfo featureDefnInfo
+        = poImdReader->GetFeatureDefnInfo(pszLayerName);
+    OGRFeatureDefn* poFeatureDefn = featureDefnInfo.GetTableDefnRef();
     if (poFeatureDefn == NULL)
     {
-        CPLError(CE_Warning, CPLE_AppDefined,
-                 "Layer '%s' not found in model definition. Creating adhoc layer", pszLayerName);
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Layer '%s' not found in model definition. "
+                  "Creating adhoc layer", pszLayerName );
         poFeatureDefn = new OGRFeatureDefn(pszLayerName);
         poFeatureDefn->SetGeomType( eType );
     }
-    OGRILI2Layer *poLayer = new OGRILI2Layer(poFeatureDefn, featureDefnInfo.poGeomFieldInfos, this);
+    OGRILI2Layer *poLayer = new OGRILI2Layer(
+        poFeatureDefn, featureDefnInfo.poGeomFieldInfos, this);
 
     nLayers++;
-    papoLayers = (OGRILI2Layer**)CPLRealloc(papoLayers, sizeof(OGRILI2Layer*) * nLayers);
+    papoLayers = static_cast<OGRILI2Layer **>(
+        CPLRealloc(papoLayers, sizeof(OGRILI2Layer*) * nLayers) );
     papoLayers[nLayers-1] = poLayer;
 
     return poLayer;
@@ -300,10 +310,10 @@ int OGRILI2DataSource::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,ODsCCreateLayer) )
         return TRUE;
-    else if( EQUAL(pszCap,ODsCCurveGeometries) )
+    if( EQUAL(pszCap,ODsCCurveGeometries) )
         return TRUE;
-    else
-        return FALSE;
+
+    return FALSE;
 }
 
 /************************************************************************/
@@ -313,16 +323,17 @@ int OGRILI2DataSource::TestCapability( const char * pszCap )
 OGRLayer *OGRILI2DataSource::GetLayer( int iLayer )
 
 {
-  list<OGRLayer *>::const_iterator layerIt = listLayer.begin();
-  int i = 0;
-  while (i < iLayer && layerIt != listLayer.end()) {
-    i++;
-    layerIt++;
-  }
-  
-  if (i == iLayer) {
-    OGRILI2Layer *tmpLayer = (OGRILI2Layer *)*layerIt;
-    return tmpLayer;
-  } else
+    list<OGRLayer *>::const_iterator layerIt = listLayer.begin();
+    int i = 0;
+    while (i < iLayer && layerIt != listLayer.end()) {
+        i++;
+        layerIt++;
+    }
+
+    if (i == iLayer) {
+        OGRILI2Layer *tmpLayer = reinterpret_cast<OGRILI2Layer *>(*layerIt);
+        return tmpLayer;
+    }
+
     return NULL;
 }
diff --git a/ogr/ogrsf_frmts/ili/ogrili2driver.cpp b/ogr/ogrsf_frmts/ili/ogrili2driver.cpp
index 28f65d7..76fb7a0 100644
--- a/ogr/ogrsf_frmts/ili/ogrili2driver.cpp
+++ b/ogr/ogrsf_frmts/ili/ogrili2driver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrili2driver.cpp 29109 2015-05-02 11:45:44Z rouault $
+ * $Id: ogrili2driver.cpp 33109 2016-01-23 16:25:42Z rouault $
  *
  * Project:  Interlis 2 Translator
  * Purpose:  Implements OGRILI2Layer class.
@@ -27,10 +27,14 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_ili2.h"
+#include "xercesc_headers.h"
+
 #include "cpl_conv.h"
+#include "ogr_ili2.h"
+#include "ogrsf_frmts.h"
+
+CPL_CVSID("$Id: ogrili2driver.cpp 33109 2016-01-23 16:25:42Z rouault $");
 
-CPL_CVSID("$Id: ogrili2driver.cpp 29109 2015-05-02 11:45:44Z rouault $");
 
 /************************************************************************/
 /*                                Open()                                */
@@ -39,15 +43,13 @@ CPL_CVSID("$Id: ogrili2driver.cpp 29109 2015-05-02 11:45:44Z rouault $");
 static GDALDataset *OGRILI2DriverOpen( GDALOpenInfo* poOpenInfo )
 
 {
-    OGRILI2DataSource    *poDS;
-
     if( poOpenInfo->eAccess == GA_Update ||
         (!poOpenInfo->bStatOK && strchr(poOpenInfo->pszFilename, ',') == NULL) )
         return NULL;
 
     if( poOpenInfo->fpL != NULL )
     {
-        if( poOpenInfo->pabyHeader[0] != '<' 
+        if( poOpenInfo->pabyHeader[0] != '<'
             || strstr((const char*)poOpenInfo->pabyHeader,"interlis.ch/INTERLIS2") == NULL )
         {
             return NULL;
@@ -56,16 +58,17 @@ static GDALDataset *OGRILI2DriverOpen( GDALOpenInfo* poOpenInfo )
     else if( poOpenInfo->bIsDirectory )
         return NULL;
 
-    poDS = new OGRILI2DataSource();
+    OGRILI2DataSource *poDS = new OGRILI2DataSource();
 
-    if( !poDS->Open( poOpenInfo->pszFilename, poOpenInfo->papszOpenOptions, TRUE )
+    if( !poDS->Open( poOpenInfo->pszFilename, poOpenInfo->papszOpenOptions,
+                     TRUE )
         || poDS->GetLayerCount() == 0 )
     {
         delete poDS;
         return NULL;
     }
-    else
-        return poDS;
+
+    return poDS;
 }
 
 /************************************************************************/
@@ -73,21 +76,31 @@ static GDALDataset *OGRILI2DriverOpen( GDALOpenInfo* poOpenInfo )
 /************************************************************************/
 
 static GDALDataset *OGRILI2DriverCreate( const char * pszName,
-                                         CPL_UNUSED int nBands,
-                                         CPL_UNUSED int nXSize,
-                                         CPL_UNUSED int nYSize,
-                                         CPL_UNUSED GDALDataType eDT,
+                                         int /* nBands */,
+                                         int /* nXSize */,
+                                         int /* nYSize */,
+                                         GDALDataType /* eDT */,
                                          char **papszOptions )
 {
-    OGRILI2DataSource    *poDS = new OGRILI2DataSource();
+    OGRILI2DataSource *poDS = new OGRILI2DataSource();
 
     if( !poDS->Create( pszName, papszOptions ) )
     {
         delete poDS;
         return NULL;
     }
-    else
-        return poDS;
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                         OGRILI2DriverUnload()                        */
+/************************************************************************/
+
+static void OGRILI2DriverUnload ( GDALDriver* )
+{
+    if( getenv("ILI2_TERMINATE_XERCES") )
+        XMLPlatformUtils::Terminate();
 }
 
 /************************************************************************/
@@ -95,28 +108,24 @@ static GDALDataset *OGRILI2DriverCreate( const char * pszName,
 /************************************************************************/
 
 void RegisterOGRILI2() {
-    GDALDriver  *poDriver;
-
-    if( GDALGetDriverByName( "Interlis 2" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    if( GDALGetDriverByName( "Interlis 2" ) != NULL )
+        return;
 
-        poDriver->SetDescription( "Interlis 2" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Interlis 2" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_ili.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "xtf xml ili" );
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+    poDriver->SetDescription( "Interlis 2" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Interlis 2" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_ili.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "xtf xml ili" );
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
 "<OpenOptionList>"
 "  <Option name='MODEL' type='string' description='Filename of the model in IlisMeta format (.imd)'/>"
 "</OpenOptionList>" );
 
-        poDriver->pfnOpen = OGRILI2DriverOpen;
-        poDriver->pfnCreate = OGRILI2DriverCreate;
+    poDriver->pfnOpen = OGRILI2DriverOpen;
+    poDriver->pfnCreate = OGRILI2DriverCreate;
+    poDriver->pfnUnloadDriver = OGRILI2DriverUnload;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/ili/ogrili2layer.cpp b/ogr/ogrsf_frmts/ili/ogrili2layer.cpp
index 4e0bb61..91194ba 100644
--- a/ogr/ogrsf_frmts/ili/ogrili2layer.cpp
+++ b/ogr/ogrsf_frmts/ili/ogrili2layer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrili2layer.cpp 29140 2015-05-03 20:09:32Z pka $
+ * $Id: ogrili2layer.cpp 32765 2016-01-05 19:27:15Z rouault $
  *
  * Project:  Interlis 2 Translator
  * Purpose:  Implements OGRILI2Layer class.
@@ -28,11 +28,11 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_ili2.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "ogr_ili2.h"
 
-CPL_CVSID("$Id: ogrili2layer.cpp 29140 2015-05-03 20:09:32Z pka $");
+CPL_CVSID("$Id: ogrili2layer.cpp 32765 2016-01-05 19:27:15Z rouault $");
 
 /************************************************************************/
 /*                           OGRILI2Layer()                              */
@@ -40,14 +40,13 @@ CPL_CVSID("$Id: ogrili2layer.cpp 29140 2015-05-03 20:09:32Z pka $");
 
 OGRILI2Layer::OGRILI2Layer( OGRFeatureDefn* poFeatureDefnIn,
                             GeomFieldInfos oGeomFieldInfosIn,
-                            OGRILI2DataSource *poDSIn )
+                            OGRILI2DataSource *poDSIn ) :
+    poFeatureDefn(poFeatureDefnIn),
+    oGeomFieldInfos(oGeomFieldInfosIn),
+    poDS(poDSIn)
 {
-    poFeatureDefn = poFeatureDefnIn;
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
-    oGeomFieldInfos = oGeomFieldInfosIn;
-
-    poDS = poDSIn;
 
     listFeatureIt = listFeature.begin();
 }
@@ -95,10 +94,9 @@ void OGRILI2Layer::ResetReading()
 
 OGRFeature *OGRILI2Layer::GetNextFeature()
 {
-    OGRFeature *poFeature = NULL;
     while (listFeatureIt != listFeature.end())
     {
-      poFeature = *(listFeatureIt++);
+      OGRFeature *poFeature = *(listFeatureIt++);
       //apply filters
       if( (m_poFilterGeom == NULL
            || FilterGeometry( poFeature->GetGeometryRef() ) )
@@ -125,43 +123,48 @@ GIntBig OGRILI2Layer::GetFeatureCount( int bForce )
     }
 }
 
-static char* d2str(double val)
+static const char* d2str(double val)
 {
-    static char strbuf[255];
     if( val == (int) val )
-        sprintf( strbuf, "%d", (int) val );
-    else if( fabs(val) < 370 )
-        CPLsprintf( strbuf, "%.16g", val );
-    else if( fabs(val) > 100000000.0  )
-        CPLsprintf( strbuf, "%.16g", val );
-    else
-        CPLsprintf( strbuf, "%.3f", val );
-    return strbuf;
+        return CPLSPrintf("%d", (int) val );
+    if( fabs(val) < 370 )
+        return CPLSPrintf("%.16g", val );
+    if( fabs(val) > 100000000.0  )
+        return CPLSPrintf("%.16g", val );
+
+    return CPLSPrintf("%.3f", val );
 }
 
 static void AppendCoordinateList( OGRLineString *poLine, VSILFILE* fp )
 {
-    int         b3D = wkbHasZ(poLine->getGeometryType());
+    const bool b3D = CPL_TO_BOOL(wkbHasZ(poLine->getGeometryType()));
 
     for( int iPoint = 0; iPoint < poLine->getNumPoints(); iPoint++ )
     {
         VSIFPrintfL(fp, "<COORD>");
         VSIFPrintfL(fp, "<C1>%s</C1>", d2str(poLine->getX(iPoint)));
         VSIFPrintfL(fp, "<C2>%s</C2>", d2str(poLine->getY(iPoint)));
-        if (b3D) VSIFPrintfL(fp, "<C3>%s</C3>", d2str(poLine->getZ(iPoint)));
+        if (b3D)
+            VSIFPrintfL(fp, "<C3>%s</C3>", d2str(poLine->getZ(iPoint)));
         VSIFPrintfL(fp, "</COORD>\n");
     }
 }
 
-static int OGR2ILIGeometryAppend( OGRGeometry *poGeometry, VSILFILE* fp, const char *attrname, CPLString iliGeomType )
+static int OGR2ILIGeometryAppend( OGRGeometry *poGeometry, VSILFILE* fp,
+                                  const char *attrname, CPLString iliGeomType )
 {
-    //CPLDebug( "OGR_ILI", "OGR2ILIGeometryAppend getGeometryType %s iliGeomType %s", poGeometry->getGeometryName(), iliGeomType.c_str());
+#ifdef DEBUG_VERBOSE
+    CPLDebug( "OGR_ILI",
+              "OGR2ILIGeometryAppend getGeometryType %s iliGeomType %s",
+              poGeometry->getGeometryName(), iliGeomType.c_str());
+#endif
 /* -------------------------------------------------------------------- */
 /*      2D/3D Point                                                     */
 /* -------------------------------------------------------------------- */
-    if( poGeometry->getGeometryType() == wkbPoint || poGeometry->getGeometryType() == wkbPoint25D )
+    if( poGeometry->getGeometryType() == wkbPoint ||
+        poGeometry->getGeometryType() == wkbPoint25D )
     {
-        OGRPoint *poPoint = (OGRPoint *) poGeometry;
+        OGRPoint *poPoint = reinterpret_cast<OGRPoint *>( poGeometry );
 
         VSIFPrintfL(fp, "<%s>\n", attrname);
         VSIFPrintfL(fp, "<COORD>");
@@ -207,7 +210,8 @@ static int OGR2ILIGeometryAppend( OGRGeometry *poGeometry, VSILFILE* fp, const c
 
         if( poPolygon->getExteriorRing() != NULL )
         {
-            if( !OGR2ILIGeometryAppend( poPolygon->getExteriorRing(), fp, NULL, "" ) )
+            if( !OGR2ILIGeometryAppend( poPolygon->getExteriorRing(), fp,
+                                        NULL, "" ) )
                 return FALSE;
         }
 
@@ -236,8 +240,9 @@ static int OGR2ILIGeometryAppend( OGRGeometry *poGeometry, VSILFILE* fp, const c
              || wkbFlatten(poGeometry->getGeometryType()) == wkbGeometryCollection )
     {
         OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeometry;
-        int             iMember;
 
+#if 0
+        // TODO: Why were these all blank?
         if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPolygon )
         {
         }
@@ -250,8 +255,8 @@ static int OGR2ILIGeometryAppend( OGRGeometry *poGeometry, VSILFILE* fp, const c
         else
         {
         }
-
-        for( iMember = 0; iMember < poGC->getNumGeometries(); iMember++)
+#endif
+        for( int iMember = 0; iMember < poGC->getNumGeometries(); iMember++)
         {
             OGRGeometry *poMember = poGC->getGeometryRef( iMember );
 
@@ -272,42 +277,48 @@ static int OGR2ILIGeometryAppend( OGRGeometry *poGeometry, VSILFILE* fp, const c
 /************************************************************************/
 
 OGRErr OGRILI2Layer::ICreateFeature( OGRFeature *poFeature ) {
-    static char         szTempBuffer[80];
+    char szTempBuffer[80];
     const char* tid;
     int iField = 0;
-    if (poFeatureDefn->GetFieldCount() && EQUAL(poFeatureDefn->GetFieldDefn(iField)->GetNameRef(), "TID"))
+    if( poFeatureDefn->GetFieldCount() &&
+        EQUAL(poFeatureDefn->GetFieldDefn(iField)->GetNameRef(), "TID") )
     {
         tid = poFeature->GetFieldAsString(0);
         ++iField;
     }
     else
     {
-        sprintf( szTempBuffer, CPL_FRMT_GIB, poFeature->GetFID() );
+        snprintf( szTempBuffer, sizeof(szTempBuffer), CPL_FRMT_GIB,
+                  poFeature->GetFID() );
         tid = szTempBuffer;
     }
 
     VSILFILE* fp = poDS->GetOutputFP();
     if (fp == NULL)
-        return CE_Failure;
+        return OGRERR_FAILURE;
 
     VSIFPrintfL(fp, "<%s TID=\"%s\">\n", poFeatureDefn->GetName(), tid);
 
     // Write out Geometries
-    for( int iGeomField = 0; iGeomField < poFeatureDefn->GetGeomFieldCount(); iGeomField++ )
+    for( int iGeomField = 0;
+         iGeomField < poFeatureDefn->GetGeomFieldCount();
+         iGeomField++ )
     {
-        OGRGeomFieldDefn *poFieldDefn = poFeatureDefn->GetGeomFieldDefn(iGeomField);
+        OGRGeomFieldDefn *poFieldDefn
+            = poFeatureDefn->GetGeomFieldDefn(iGeomField);
         OGRGeometry* poGeom = poFeature->GetGeomFieldRef(iGeomField);
         if( poGeom != NULL )
         {
             CPLString iliGeomType = GetIliGeomType(poFieldDefn->GetNameRef());
-            OGR2ILIGeometryAppend(poGeom, fp, poFieldDefn->GetNameRef(), iliGeomType);
+            OGR2ILIGeometryAppend( poGeom, fp, poFieldDefn->GetNameRef(),
+                                   iliGeomType );
         }
     }
 
-    // Write all "set" fields. 
+    // Write all "set" fields.
     for( ; iField < poFeatureDefn->GetFieldCount(); iField++ )
     {
-        
+
         OGRFieldDefn *poField = poFeatureDefn->GetFieldDefn( iField );
 
         if( poFeature->IsFieldSet( iField ) )
@@ -329,15 +340,15 @@ OGRErr OGRILI2Layer::ICreateFeature( OGRFeature *poFeature ) {
 int OGRILI2Layer::TestCapability( CPL_UNUSED const char * pszCap ) {
     if( EQUAL(pszCap,OLCCurveGeometries) )
         return TRUE;
-    else
-        return FALSE;
+
+    return FALSE;
 }
 
 /************************************************************************/
 /*                            CreateField()                             */
 /************************************************************************/
 
-OGRErr OGRILI2Layer::CreateField( OGRFieldDefn *poField, CPL_UNUSED int bApproxOK ) {
+OGRErr OGRILI2Layer::CreateField( OGRFieldDefn *poField, int /* bApproxOK */ ) {
     poFeatureDefn->AddFieldDefn( poField );
     return OGRERR_NONE;
 }
diff --git a/ogr/ogrsf_frmts/ili/xercesc_headers.h b/ogr/ogrsf_frmts/ili/xercesc_headers.h
new file mode 100644
index 0000000..12213ec
--- /dev/null
+++ b/ogr/ogrsf_frmts/ili/xercesc_headers.h
@@ -0,0 +1,58 @@
+/******************************************************************************
+ *
+ * Project:  GDAL
+ * Purpose:  Includes Xerces-C headers
+ * Author:   Even Rouault <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+#ifndef XERCESC_HEADERS_H
+#define XERCESC_HEADERS_H
+
+#if ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) && !defined(_MSC_VER))
+#pragma GCC system_header
+#endif
+
+// This works around problems with math.h on some platforms #defining INFINITY
+#ifdef INFINITY
+#undef  INFINITY
+#define INFINITY INFINITY_XERCES
+#endif
+
+#include <util/PlatformUtils.hpp>
+#include <sax2/DefaultHandler.hpp>
+#include <sax2/ContentHandler.hpp>
+#include <sax2/SAX2XMLReader.hpp>
+#include <sax2/XMLReaderFactory.hpp>
+#include <dom/DOM.hpp>
+#include <util/XMLString.hpp>
+
+#if _XERCES_VERSION >= 30000
+# include <sax2/Attributes.hpp>
+#endif
+
+#ifdef XERCES_CPP_NAMESPACE_USE
+XERCES_CPP_NAMESPACE_USE
+#endif
+
+#endif /* XERCESC_HEADERS_H */
diff --git a/ogr/ogrsf_frmts/ingres/drv_ingres.html b/ogr/ogrsf_frmts/ingres/drv_ingres.html
index 15f0ff4..b0752b5 100644
--- a/ogr/ogrsf_frmts/ingres/drv_ingres.html
+++ b/ogr/ogrsf_frmts/ingres/drv_ingres.html
@@ -14,7 +14,7 @@ functionality was introduced in GDAL/OGR 1.6.0. </p>
 <p>When opening a database, it's name should be specified in the form
 "@driver=ingres,[host=<i>host</i>, instance=<i>instance</i>],dbname=<i>[vnode::]dbname</i>
 [,options]". where the options can
-include comma seperated
+include comma separated
 items like "host=*ip_address*","instance=*instance*", "username=*userid*", "password=*password*",
 "effuser=*database_user*", "dbpwd=*database_passwd*", "timeout=*timeout*",
 "tables=table1/table2".</p>
@@ -26,7 +26,7 @@ is made to authenticate as the current OS user.</p>
 <p>If the host and instance options are both specified,
 the username and password *must* be supplied as it creates a temporary
 <a href=http://docs.actian.com/ingres/10.0/command-reference-guide/1207-dynamic-vnode-specificationconnect-to-remote-node>dynamic vnode connection</a>.
-The default protocal is TCP/IP. If any other protocal is expected to be used, a pre-built vnode is preferable.
+The default protocol is TCP/IP. If any other protocol is expected to be used, a pre-built vnode is preferable.
 If vnode and these two options are passed at the same time, an error will occur.
 </p>
 
@@ -36,17 +36,17 @@ username and password which are used for OS level authorization.</p>
 Examples:
 <pre>
   @driver=ingres,host=192.168.0.1, instance=II, dbname=test,userid=warmerda,password=test,effuser=frank, dbpwd=123, tables=usa/canada
-  
+
   @driver=ingres,host=192.168.0.1, instance=II, dbname=test,userid=warmerda,password=test,tables=usa/canada
-  
+
   @driver=ingres,dbname=test,userid=warmerda,password=test,tables=usa/canada
 
   @driver=ingres,dbname=test,userid=warmerda,password=test,tables=usa/canada
-  
+
   @driver=ingres,dbname=test,userid=warmerda,password=test,tables=usa/canada
-  
+
   @driver=ingres,dbname=server::mapping
-  
+
   @driver=ingres,dbname=mapping
 </pre>
 
@@ -64,7 +64,7 @@ on the spatial and attribute query filters in effect at a given time.</p>
 
 <p>By default, SQL statements are passed directly to the INGRES database
 engine. It's also possible to request the driver to handle SQL commands
-with <a href="/ogr/ogr_sql.html">OGR SQL</a> engine,
+with <a href="ogr_sql.html">OGR SQL</a> engine,
 by passing <strong>"OGRSQL"</strong> string to the ExecuteSQL()
 method, as name of the SQL dialect.</p>
 
@@ -72,7 +72,7 @@ method, as name of the SQL dialect.</p>
 The INGRES driver supports OGC SFSQL 1.1 compliant spatial types and functions,
 including types: POINT, LINESTRING, POLYGON, MULTI* versions, and GEOMETRYCOLLECTION.
 </p>
- 
+
 <h2>Caveats</h2>
 <ul>
 <li> No fast spatial index is used when reading, so spatial filters are
diff --git a/ogr/ogrsf_frmts/ingres/ogr_ingres.h b/ogr/ogrsf_frmts/ingres/ogr_ingres.h
index 6b2805e..554ecc0 100644
--- a/ogr/ogrsf_frmts/ingres/ogr_ingres.h
+++ b/ogr/ogrsf_frmts/ingres/ogr_ingres.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_ingres.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogr_ingres.h 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Declarations for Ingres OGR Driver Classes.
@@ -34,12 +34,12 @@
 #include "ogrsf_frmts.h"
 
 class OGRIngresDataSource;
-    
+
 /************************************************************************/
 /*                          OGRIngresStatement                          */
 /************************************************************************/
 
-class OGRIngresStatement 
+class OGRIngresStatement
 {
 public:
     II_PTR            hConn;
@@ -50,7 +50,7 @@ public:
     IIAPI_GETCOLPARM	getColParm;
     IIAPI_DATAVALUE	*pasDataBuffer;
     IIAPI_GETQINFOPARM  queryInfo;
-    
+
     GByte             *pabyWrkBuffer;
     char              **papszFields;
 
@@ -67,7 +67,7 @@ public:
     void addInputParameter( IIAPI_DT_ID eDType, int nLength, GByte *pabyData );
 
     int ExecuteSQL( const char * );
-    
+
     char **GetRow();
     void   DumpRow( FILE * );
     static void         ReportError( IIAPI_GENPARM *, const char * = NULL );
@@ -94,7 +94,7 @@ class OGRIngresLayer : public OGRLayer
     int                 iNextShapeId;
 
     OGRIngresDataSource    *poDS;
- 
+
     CPLString           osQueryStatement;
 
     int                 nResultOffset;
@@ -118,7 +118,7 @@ class OGRIngresLayer : public OGRLayer
     virtual OGRFeature *GetNextFeature();
 
     virtual OGRFeature *GetFeature( GIntBig nFeatureId );
-    
+
     OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
 
     virtual OGRSpatialReference *GetSpatialRef();
@@ -155,7 +155,7 @@ class OGRIngresTableLayer : public OGRIngresLayer
 
     OGRErr              PrepareOldStyleGeometry( OGRGeometry*, CPLString& );
     OGRErr              PrepareNewStyleGeometry( OGRGeometry*, CPLString& );
-    
+
   public:
                         OGRIngresTableLayer( OGRIngresDataSource *,
                                          const char * pszName,
@@ -163,12 +163,14 @@ class OGRIngresTableLayer : public OGRIngresLayer
                         ~OGRIngresTableLayer();
 
     OGRErr              Initialize(const char* pszTableName);
-    
+
 //    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
     virtual void        ResetReading();
 //    virtual GIntBig     GetFeatureCount( int );
 
     void                SetSpatialFilter( OGRGeometry * );
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+                { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
 
     virtual OGRErr      SetAttributeFilter( const char * );
 
@@ -182,10 +184,9 @@ class OGRIngresTableLayer : public OGRIngresLayer
     void                SetLaunderFlag( int bFlag )
                                 { bLaunderColumnNames = bFlag; }
     void                SetPrecisionFlag( int bFlag )
-                                { bPreservePrecision = bFlag; }    
+                                { bPreservePrecision = bFlag; }
 
     virtual int         TestCapability( const char * );
-//    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
 };
 
 /************************************************************************/
@@ -197,10 +198,10 @@ class OGRIngresResultLayer : public OGRIngresLayer
     void                BuildFullQueryStatement(void);
 
     char                *pszRawStatement;
-    
+
     // Layer srid.
     int                 nSRSId;
-    
+
     int                 nFeatureCount;
 
   public:
@@ -224,7 +225,7 @@ class OGRIngresDataSource : public OGRDataSource
 {
     OGRIngresLayer    **papoLayers;
     int                 nLayers;
-    
+
     char               *pszName;
 
     int                 bDSUpdate;
@@ -234,7 +235,7 @@ class OGRIngresDataSource : public OGRDataSource
     int                 DeleteLayer( int iLayer );
 
     // We maintain a list of known SRID to reduce the number of trips to
-    // the database to get SRSes. 
+    // the database to get SRSes.
     int                 nKnownSRID;
     int                *panSRID;
     OGRSpatialReference **papoSRS;
@@ -256,7 +257,7 @@ class OGRIngresDataSource : public OGRDataSource
 
     OGRErr              InitializeMetadataTables();
 
-    int                 Open( const char *pszFullName, 
+    int                 Open( const char *pszFullName,
                               char **papszOptions, int bUpdate );
     int                 OpenTable( const char *, int bUpdate );
 
@@ -264,8 +265,8 @@ class OGRIngresDataSource : public OGRDataSource
     int                 GetLayerCount() { return nLayers; }
     OGRLayer            *GetLayer( int );
 
-    virtual OGRLayer    *ICreateLayer( const char *, 
-                                      OGRSpatialReference * = NULL,
+    virtual OGRLayer    *ICreateLayer( const char *,
+                                       OGRSpatialReference * = NULL,
                                       OGRwkbGeometryType = wkbUnknown,
                                       char ** = NULL );
 
@@ -295,7 +296,7 @@ class OGRIngresDriver : public OGRSFDriver
 
   public:
                 ~OGRIngresDriver();
-                
+
     const char *GetName();
     OGRDataSource *Open( const char *, int );
     virtual OGRDataSource *CreateDataSource( const char *pszName,
@@ -305,5 +306,3 @@ class OGRIngresDriver : public OGRSFDriver
 
 
 #endif /* ndef OGR_PG_H_INCLUDED */
-
-
diff --git a/ogr/ogrsf_frmts/ingres/ogringresdatasource.cpp b/ogr/ogrsf_frmts/ingres/ogringresdatasource.cpp
index 2947908..8a06c7b 100644
--- a/ogr/ogrsf_frmts/ingres/ogringresdatasource.cpp
+++ b/ogr/ogrsf_frmts/ingres/ogringresdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogringresdatasource.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogringresdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRIngresDataSource class.
@@ -33,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogringresdatasource.cpp 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: ogringresdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                            SetConnParam()                            */
@@ -53,15 +53,15 @@ SetConnParam(II_PTR *connHandle,
     setconnParm.sc_connHandle = *connHandle;
     setconnParm.sc_paramID = paramID;
     setconnParm.sc_paramValue = paramValue;
-	
+
     IIapi_setConnectParam(&setconnParm);
-	
+
     while( setconnParm.sc_genParm.gp_completed == FALSE )
         IIapi_wait( &waitParm );
-	
+
     if (setconnParm.sc_genParm.gp_errorHandle)
     {
-        OGRIngresStatement::ReportError( &(setconnParm.sc_genParm), 
+        OGRIngresStatement::ReportError( &(setconnParm.sc_genParm),
                                          "Failed to set OpenAPI connection para." );
         return IIAPI_ST_FAILURE;
     }
@@ -70,7 +70,7 @@ SetConnParam(II_PTR *connHandle,
         /* save the handle   */
         *connHandle = setconnParm.sc_connHandle;
     }
-   
+
     return (setconnParm.sc_genParm.gp_status);
 }
 
@@ -105,7 +105,7 @@ OGRIngresDataSource::~OGRIngresDataSource()
 
     for( i = 0; i < nLayers; i++ )
         delete papoLayers[i];
-    
+
     CPLFree( papoLayers );
 
 #ifdef notdef
@@ -126,13 +126,13 @@ OGRIngresDataSource::~OGRIngresDataSource()
 /*                                Open()                                */
 /************************************************************************/
 
-int OGRIngresDataSource::Open( const char *pszFullName, 
+int OGRIngresDataSource::Open( const char *pszFullName,
                                char **papszOptions, int bUpdate )
 
 
 {
     CPLAssert( nLayers == 0 );
-  
+
  #define MAX_TARGET_STRING_LENGTH 512
     char pszDBTarget[MAX_TARGET_STRING_LENGTH];
 
@@ -156,7 +156,7 @@ int OGRIngresDataSource::Open( const char *pszFullName,
 
     if( pszTables != NULL )
         papszTableNames = CSLTokenizeStringComplex(pszTables,"/",TRUE,FALSE);
-   
+
 /* -------------------------------------------------------------------- */
 /*      Add support to dynamic vnode if passed                          */
 /* -------------------------------------------------------------------- */
@@ -170,44 +170,44 @@ int OGRIngresDataSource::Open( const char *pszFullName,
                   "instance name must be specified with host." );
             return FALSE;
         }
-        
-        /* 
+
+        /*
         ** make sure the user name and password are passed too,
         ** note it could not be zero length.
-        */ 
+        */
         const char *pszUsername = CSLFetchNameValue(papszOptions,"username");
         const char *pszPassword = CSLFetchNameValue(papszOptions,"password");
-        
+
         if (pszUsername == NULL || strlen(pszUsername) == 0)
         {
             CPLError( CE_Failure, CPLE_OpenFailed,
-                  "user name must be specified in dynamic vnode." );            
+                      "user name must be specified in dynamic vnode." );
             return FALSE;
         }
-        
+
         if (pszPassword == NULL || strlen(pszPassword) == 0)
         {
             CPLError( CE_Failure, CPLE_OpenFailed,
-                  "password must be specified in dynamic vnode." );            
+                      "password must be specified in dynamic vnode." );
             return FALSE;
         }
-        
-        /* 
-        ** construct the vnode string, like : 
-        ** @host,protocol,port[;attribute=value{;attribute=value}][[user,password]], 
-        ** visit for detail 
+
+        /*
+        ** construct the vnode string, like:
+        ** @host,protocol,port[;attribute=value{;attribute=value}][[user,password]],
+        ** visit for detail
         ** http://docs.actian.com/ingres/10.0/command-reference-guide/1207-dynamic-vnode-specificationconnect-to-remote-node
         */
-        sprintf(pszDBTarget, "@%s,%s,%s;%s[%s,%s]::%s ", 
+        sprintf(pszDBTarget, "@%s,%s,%s;%s[%s,%s]::%s ",
             pszHost,        /* host, compute name or IP address */
-            "TCP_IP",       /* protocal, default with TCP/IP */
+            "TCP_IP",       /* protocol, default with TCP/IP */
             pszInstance,    /* instance Name */
             "" ,            /* option, Null */
             pszUsername,    /* user name, could not be empty */
             pszPassword,    /* pwd */
             pszDBName       /* database name */
             );
-        
+
        CPLDebug("INGRES", pszDBTarget);
     }
     else
@@ -215,15 +215,15 @@ int OGRIngresDataSource::Open( const char *pszFullName,
         /* Remain the database name */
         strcpy(pszDBTarget, pszDBName);
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Initialize the Ingres API. Should we only do this once per      */
-/*      program run?  Really we should also try to terminate the api    */
+/*      program run?  Really we should also try to terminate the API    */
 /*      on program exit.                                                */
 /* -------------------------------------------------------------------- */
     IIAPI_INITPARM  initParm;
 
-    initParm.in_version = IIAPI_VERSION_1; 
+    initParm.in_version = IIAPI_VERSION_1;
     initParm.in_timeout = -1;
     IIapi_initialize( &initParm );
 
@@ -233,35 +233,35 @@ int OGRIngresDataSource::Open( const char *pszFullName,
     hConn = NULL;
     const char *pszEffuser = CSLFetchNameValue(papszOptions,"effuser");
     const char *pszDBpwd = CSLFetchNameValue(papszOptions,"dbpwd");
-    if ( pszEffuser 
-        && strlen(pszEffuser) > 0 
-        && pszDBpwd 
+    if ( pszEffuser
+        && strlen(pszEffuser) > 0
+        && pszDBpwd
         && strlen(pszDBpwd) > 0 )
-    { 
+    {
         if (SetConnParam(&hConn, IIAPI_CP_EFFECTIVE_USER,
-			(II_PTR)pszEffuser) != IIAPI_ST_SUCCESS 
+			(II_PTR)pszEffuser) != IIAPI_ST_SUCCESS
             || SetConnParam(&hConn, IIAPI_CP_DBMS_PASSWORD,
 			(II_PTR)pszDBpwd) != IIAPI_ST_SUCCESS )
         {
             return FALSE;
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Try to connect to the database.                                 */
 /* -------------------------------------------------------------------- */
     IIAPI_CONNPARM	connParm;
     IIAPI_WAITPARM	waitParm = { -1 };
-    
+
     memset( &connParm, 0, sizeof(connParm) );
     connParm.co_genParm.gp_callback = NULL;
     connParm.co_genParm.gp_closure = NULL;
     connParm.co_target = (II_CHAR *) pszDBTarget;
     connParm.co_connHandle = hConn;
     connParm.co_tranHandle = NULL;
-    connParm.co_username = 
+    connParm.co_username =
         (II_CHAR*) CSLFetchNameValue(papszOptions,"username");
-    connParm.co_password = 
+    connParm.co_password =
         (II_CHAR*)CSLFetchNameValue(papszOptions,"password");
     connParm.co_timeout = -1;
 
@@ -269,22 +269,22 @@ int OGRIngresDataSource::Open( const char *pszFullName,
         connParm.co_timeout = atoi(CSLFetchNameValue(papszOptions,"timeout"));
 
     IIapi_connect( &connParm );
-       
+
     while( connParm.co_genParm.gp_completed == FALSE )
 	IIapi_wait( &waitParm );
 
     hConn = connParm.co_connHandle;
 
-    if( connParm.co_genParm.gp_status != IIAPI_ST_SUCCESS 
+    if( connParm.co_genParm.gp_status != IIAPI_ST_SUCCESS
         || hConn == NULL )
     {
-        OGRIngresStatement::ReportError( &(connParm.co_genParm), 
+        OGRIngresStatement::ReportError( &(connParm.co_genParm),
                                     "Failed to connect to Ingres database." );
         return FALSE;
     }
 
     pszName = CPLStrdup( pszFullName );
-    
+
     bDSUpdate = bUpdate;
 
     // Check for new or old Ingres spatial library
@@ -315,7 +315,7 @@ int OGRIngresDataSource::Open( const char *pszFullName,
     if( papszTableNames == NULL )
     {
         OGRIngresStatement oStmt( hConn );
-        
+
         if( oStmt.ExecuteSQL( "select table_name from iitables where system_use = 'U' and table_name not like 'iietab_%'" ) )
         {
             char **papszFields;
@@ -323,7 +323,7 @@ int OGRIngresDataSource::Open( const char *pszFullName,
             {
                 CPLString osTableName = papszFields[0];
                 osTableName.Trim();
-                papszTableNames = CSLAddString( papszTableNames, 
+                papszTableNames = CSLAddString( papszTableNames,
                                                 osTableName );
             }
         }
@@ -334,7 +334,7 @@ int OGRIngresDataSource::Open( const char *pszFullName,
 /* -------------------------------------------------------------------- */
     int iRecord;
 
-    for( iRecord = 0; 
+    for( iRecord = 0;
          papszTableNames != NULL && papszTableNames[iRecord] != NULL;
          iRecord++ )
     {
@@ -381,7 +381,6 @@ int OGRIngresDataSource::OpenTable( const char *pszNewName, int bUpdate )
 int OGRIngresDataSource::TestCapability( const char * pszCap )
 
 {
-	
     if( EQUAL(pszCap, ODsCCreateLayer) )
         return TRUE;
     else if( EQUAL(pszCap, ODsCDeleteLayer))
@@ -419,7 +418,7 @@ OGRErr OGRIngresDataSource::InitializeMetadataTables()
     char            szCommand[1024];
     INGRES_RES       *hResult;
     OGRErr	    eErr = OGRERR_NONE;
- 
+
     sprintf( szCommand, "DESCRIBE geometry_columns" );
     if( ingres_query(GetConn(), szCommand ) )
     {
@@ -427,7 +426,7 @@ OGRErr OGRIngresDataSource::InitializeMetadataTables()
                 "CREATE TABLE geometry_columns "
                 "( F_TABLE_CATALOG VARCHAR(256), "
                 "F_TABLE_SCHEMA VARCHAR(256), "
-                "F_TABLE_NAME VARCHAR(256) NOT NULL," 
+                "F_TABLE_NAME VARCHAR(256) NOT NULL,"
                 "F_GEOMETRY_COLUMN VARCHAR(256) NOT NULL, "
                 "COORD_DIMENSION INT, "
                 "SRID INT,"
@@ -439,17 +438,16 @@ OGRErr OGRIngresDataSource::InitializeMetadataTables()
         }
         else
             CPLDebug("INGRES","Creating geometry_columns metadata table");
- 
     }
- 
+
     // make sure to attempt to free results of successful queries
     hResult = ingres_store_result( GetConn() );
     if( hResult != NULL )
     {
         ingres_free_result( hResult );
-        hResult = NULL;   
+        hResult = NULL;
     }
- 
+
     sprintf( szCommand, "DESCRIBE spatial_ref_sys" );
     if( ingres_query(GetConn(), szCommand ) )
     {
@@ -466,9 +464,8 @@ OGRErr OGRIngresDataSource::InitializeMetadataTables()
         }
         else
             CPLDebug("INGRES","Creating spatial_ref_sys metadata table");
- 
-    }    
- 
+    }
+
     // make sure to attempt to free results of successful queries
     hResult = ingres_store_result( GetConn() );
     if( hResult != NULL )
@@ -476,7 +473,7 @@ OGRErr OGRIngresDataSource::InitializeMetadataTables()
         ingres_free_result( hResult );
         hResult = NULL;
     }
- 
+
     return eErr;
 #endif
     return OGRERR_NONE;
@@ -495,7 +492,7 @@ OGRSpatialReference *OGRIngresDataSource::FetchSRS( int nId )
     char         szCommand[1024];
     char           **papszRow;
     OGRIngresStatement oStatement(GetConn());
-            
+
     if( nId < 0 )
         return NULL;
 
@@ -523,10 +520,10 @@ OGRSpatialReference *OGRIngresDataSource::FetchSRS( int nId )
          nId );
 
     oStatement.ExecuteSQL(szCommand);
-        
+
     char    *pszWKT = NULL;
     papszRow = NULL;
-    
+
 
     papszRow = oStatement.GetRow();
 
@@ -550,7 +547,7 @@ OGRSpatialReference *OGRIngresDataSource::FetchSRS( int nId )
 /*      Add to the cache.                                               */
 /* -------------------------------------------------------------------- */
     panSRID = (int *) CPLRealloc(panSRID,sizeof(int) * (nKnownSRID+1) );
-    papoSRS = (OGRSpatialReference **) 
+    papoSRS = (OGRSpatialReference **)
         CPLRealloc(papoSRS, sizeof(void*) * (nKnownSRID + 1) );
     panSRID[nKnownSRID] = nId;
     papoSRS[nKnownSRID] = poSRS;
@@ -589,7 +586,7 @@ int OGRIngresDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 
     if (pszAuthName && pszAuthID && EQUAL(pszAuthName, "EPSG"))
     {
-         sprintf( szCommand, 
+         sprintf( szCommand,
              "SELECT srid FROM spatial_ref_sys WHERE auth_name = 'EPSG' and auth_srid= %s",
              pszAuthID );
 
@@ -626,7 +623,7 @@ int OGRIngresDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 /* -------------------------------------------------------------------- */
 /*      Try to find in the existing table.                              */
 /* -------------------------------------------------------------------- */
-    sprintf( szCommand, 
+    sprintf( szCommand,
              "SELECT srid FROM spatial_ref_sys WHERE srtext = '%s'",
              pszWKT );
 
@@ -649,8 +646,8 @@ int OGRIngresDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 /* -------------------------------------------------------------------- */
 /*      Get the current maximum srid in the srs table.                  */
 /* -------------------------------------------------------------------- */
-    sprintf( szCommand, 
-             "SELECT MAX(srid) FROM spatial_ref_sys");    
+    sprintf( szCommand,
+             "SELECT MAX(srid) FROM spatial_ref_sys");
 
     {
         OGRIngresStatement  oStateMaxSRID(GetConn());
@@ -662,24 +659,23 @@ int OGRIngresDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 #define USER_DEFINED_SR_START   10000
         if( papszRow != NULL && papszRow[0] != NULL )
         {
-            // if there is no row in spatial reference, a random value 
+            // if there is no row in spatial reference, a random value
             // will be return, how to judge?
             nSRSId = *((II_INT4 *)papszRow[0]) ;
             if (nSRSId <= 0)
             {
-                nSRSId = USER_DEFINED_SR_START+1; 
+                nSRSId = USER_DEFINED_SR_START+1;
             }
             else
             {
                 nSRSId = *((II_INT4 *)papszRow[0]) + 1;
             }
-             
+
         }
         else
             nSRSId = USER_DEFINED_SR_START+1;
+    }
 
-    }  
-    
     if(pszAuthName == NULL || strlen(pszAuthName) == 0)
     {
         poSRS->AutoIdentifyEPSG();
@@ -739,13 +735,13 @@ OGRLayer * OGRIngresDataSource::ExecuteSQL( const char *pszSQLCommand,
 /*      Use generic implementation for recognized dialects              */
 /* -------------------------------------------------------------------- */
     if( IsGenericSQLDialect(pszDialect) )
-        return OGRDataSource::ExecuteSQL( pszSQLCommand, 
-                                          poSpatialFilter, 
+        return OGRDataSource::ExecuteSQL( pszSQLCommand,
+                                          poSpatialFilter,
                                           pszDialect );
 
     if( poSpatialFilter != NULL )
     {
-        CPLDebug( "OGR_INGRES", 
+        CPLDebug( "OGR_INGRES",
           "Spatial filter ignored for now in OGRIngresDataSource::ExecuteSQL()" );
     }
 
@@ -771,7 +767,7 @@ OGRLayer * OGRIngresDataSource::ExecuteSQL( const char *pszSQLCommand,
 
     poLayer = new OGRIngresResultLayer( this, pszSQLCommand, poStatement );
     EstablishActiveLayer( poLayer );
-        
+
     return poLayer;
 }
 
@@ -817,13 +813,13 @@ int OGRIngresDataSource::DeleteLayer( int iLayer)
 {
     if( iLayer < 0 || iLayer >= nLayers )
         return OGRERR_FAILURE;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Blow away our OGR structures related to the layer.  This is     */
 /*      pretty dangerous if anything has a reference to this layer!     */
 /* -------------------------------------------------------------------- */
     CPLString osLayerName = papoLayers[iLayer]->GetLayerDefn()->GetName();
-    
+
     CPLDebug( "INGRES", "DeleteLayer(%s)", osLayerName.c_str() );
 
     delete papoLayers[iLayer];
@@ -840,7 +836,7 @@ int OGRIngresDataSource::DeleteLayer( int iLayer)
     sprintf( szCommand,
              "DROP TABLE %s ",
              osLayerName.c_str() );
-    
+
     if( oStmt.ExecuteSQL( szCommand ) )
     {
         CPLDebug("INGRES","Dropped table %s.", osLayerName.c_str());
@@ -865,8 +861,8 @@ OGRIngresDataSource::ICreateLayer( const char * pszLayerNameIn,
 {
     const char          *pszGeometryType = NULL;
     const char		*pszGeomColumnName;
-    const char 		*pszExpectedFIDName; 
-	
+    const char 		*pszExpectedFIDName;
+
     char                *pszLayerName;
     int                 nDimension = 3; // Ingres only supports 2d currently
 
@@ -891,7 +887,7 @@ OGRIngresDataSource::ICreateLayer( const char * pszLayerNameIn,
     {
         if( EQUAL(pszLayerName,papoLayers[iLayer]->GetLayerDefn()->GetName()) )
         {
-			
+
             if( CSLFetchNameValue( papszOptions, "OVERWRITE" ) != NULL
                 && !EQUAL(CSLFetchNameValue(papszOptions,"OVERWRITE"),"NO") )
             {
@@ -931,7 +927,7 @@ OGRIngresDataSource::ICreateLayer( const char * pszLayerNameIn,
 
     if( pszGeometryType != NULL )
         /* user selected type */;
-    
+
     else if( wkbFlatten(eType) == wkbPoint )
         pszGeometryType = "POINT";
 
@@ -995,7 +991,7 @@ OGRIngresDataSource::ICreateLayer( const char * pszLayerNameIn,
     /*      adding tot the srs table if needed.                             */
     /* -------------------------------------------------------------------- */
     int nSRSId = -1;
-    
+
     if( poSRS != NULL && IsNewIngres() == TRUE )
         nSRSId = FetchSRSId( poSRS );
 
@@ -1015,9 +1011,9 @@ OGRIngresDataSource::ICreateLayer( const char * pszLayerNameIn,
         if(nSRSId != -1)
         {
             osCommand.Printf( "CREATE TABLE %s ("
-                              " %s INTEGER NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS seq_%s IDENTITY (START WITH 1 INCREMENT BY 1),"  
+                              " %s INTEGER NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS seq_%s IDENTITY (START WITH 1 INCREMENT BY 1),"
                               " %s %s SRID %d ) ",
-                              pszLayerName,                              
+                              pszLayerName,
                               pszExpectedFIDName,
                               pszLayerName,
                               pszGeomColumnName,
@@ -1029,7 +1025,7 @@ OGRIngresDataSource::ICreateLayer( const char * pszLayerNameIn,
             osCommand.Printf( "CREATE TABLE %s ("
                               " %s INTEGER NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS seq_%s IDENTITY (START WITH 1 INCREMENT BY 1),"
                               " %s %s )",
-                              pszLayerName,                              
+                              pszLayerName,
                               pszExpectedFIDName,
                               pszLayerName,
                               pszGeomColumnName,
diff --git a/ogr/ogrsf_frmts/ingres/ogringresdriver.cpp b/ogr/ogrsf_frmts/ingres/ogringresdriver.cpp
index 5ceeb48..7515b09 100644
--- a/ogr/ogrsf_frmts/ingres/ogringresdriver.cpp
+++ b/ogr/ogrsf_frmts/ingres/ogringresdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogringresdriver.cpp 15463 2008-10-06 18:31:28Z rouault $
+ * $Id: ogringresdriver.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRIngresDriver class.
@@ -30,7 +30,7 @@
 #include "ogr_ingres.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogringresdriver.cpp 15463 2008-10-06 18:31:28Z rouault $");
+CPL_CVSID("$Id: ogringresdriver.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                          ~OGRIngresDriver()                           */
@@ -89,7 +89,7 @@ OGRDataSource *OGRIngresDriver::Open( const char * pszFilename,
     }
 
     CSLDestroy( papszOptions );
-    
+
     return poDS;
 }
 
@@ -117,7 +117,7 @@ OGRDataSource *OGRIngresDriver::CreateDataSource( const char * pszName,
         {
             delete poDS;
             poDS = NULL;
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Ingres driver doesn't currently support database creation.\n"
                       "Please create database before using." );
         }
@@ -139,10 +139,10 @@ int OGRIngresDriver::TestCapability( const char * pszCap )
     if( EQUAL(pszCap,ODsCCreateLayer) )
         return TRUE;
     if( EQUAL(pszCap,ODsCDeleteLayer) )
-        return TRUE;     
+        return TRUE;
     if( EQUAL(pszCap,ODrCCreateDataSource) )
         return TRUE;
-        
+
     return FALSE;
 }
 
@@ -153,8 +153,7 @@ int OGRIngresDriver::TestCapability( const char * pszCap )
 void RegisterOGRIngres()
 
 {
-    if (! GDAL_CHECK_VERSION("Ingres"))
+    if( !GDAL_CHECK_VERSION("Ingres") )
         return;
     OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver(new OGRIngresDriver);
 }
-
diff --git a/ogr/ogrsf_frmts/ingres/ogringreslayer.cpp b/ogr/ogrsf_frmts/ingres/ogringreslayer.cpp
index 811256a..d03b0d5 100644
--- a/ogr/ogrsf_frmts/ingres/ogringreslayer.cpp
+++ b/ogr/ogrsf_frmts/ingres/ogringreslayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogringreslayer.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogringreslayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRIngresLayer class.
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogringreslayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogringreslayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                           OGRIngresLayer()                            */
@@ -46,7 +46,7 @@ OGRIngresLayer::OGRIngresLayer()
     nResultOffset = 0;
 
     poSRS = NULL;
-    nSRSId = -2; // we haven't even queried the database for it yet. 
+    nSRSId = -2; // we haven't even queried the database for it yet.
 
     poFeatureDefn = NULL;
 
@@ -63,7 +63,7 @@ OGRIngresLayer::~OGRIngresLayer()
     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     {
         CPLDebug( "Ingres", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
+                  (int) m_nFeaturesRead,
                   poFeatureDefn->GetName() );
     }
 
@@ -99,7 +99,7 @@ void OGRIngresLayer::ResetReading()
 OGRFeature *OGRIngresLayer::GetNextFeature()
 
 {
-    for( ; TRUE; )
+    while( true )
     {
         OGRFeature      *poFeature;
 
@@ -151,7 +151,7 @@ static int ParseXY( const char **ppszNext, double *padfXY )
         if( pszNext[iEnd] == '\0' )
             return FALSE;
     }
-    
+
     *ppszNext += iEnd;
 
     return TRUE;
@@ -209,18 +209,18 @@ OGRGeometry *OGRIngresLayer::TranslateGeometry( const char *pszGeom )
         if( nVertCount == nVertMax )
         {
             nVertMax = nVertMax * 2 + 1;
-            padfXY = (double *) 
+            padfXY = (double *)
                 CPLRealloc(padfXY, sizeof(double) * nVertMax * 2 );
         }
 
         if( !ParseXY( &pszNext, padfXY + nVertCount*2 ) )
         {
-            CPLDebug( "INGRES", "Error parsing geometry: %s", 
+            CPLDebug( "INGRES", "Error parsing geometry: %s",
                       pszGeom );
             CPLFree( padfXY );
             return NULL;
         }
-        
+
         CPLAssert( *pszNext == ')' );
         nVertCount++;
         pszNext++;
@@ -332,28 +332,28 @@ OGRFeature *OGRIngresLayer::RecordToFeature( char **papszRow )
 /* ==================================================================== */
 /*      Transfer all result fields we can.                              */
 /* ==================================================================== */
-    for( iField = 0; 
+    for( iField = 0;
          iField < (int) poResultSet->getDescrParm.gd_descriptorCount;
          iField++ )
     {
-        IIAPI_DATAVALUE *psDV = 
+        IIAPI_DATAVALUE *psDV =
             poResultSet->pasDataBuffer + iField;
-        IIAPI_DESCRIPTOR *psFDesc = 
+        IIAPI_DESCRIPTOR *psFDesc =
             poResultSet->getDescrParm.gd_descriptor + iField;
         int     iOGRField;
 
 /* -------------------------------------------------------------------- */
 /*      Ignore NULL fields.                                             */
 /* -------------------------------------------------------------------- */
-        if( psDV->dv_null ) 
+        if( psDV->dv_null )
             continue;
 
 /* -------------------------------------------------------------------- */
 /*      Handle FID.                                                     */
 /* -------------------------------------------------------------------- */
-        if( osFIDColumn.size() 
-            && EQUAL(psFDesc->ds_columnName,osFIDColumn) 
-            && psFDesc->ds_dataType == IIAPI_INT_TYPE 
+        if( osFIDColumn.size()
+            && EQUAL(psFDesc->ds_columnName,osFIDColumn)
+            && psFDesc->ds_dataType == IIAPI_INT_TYPE
             && psDV->dv_length == 4 )
         {
             if( papszRow[iField] == NULL )
@@ -371,7 +371,7 @@ OGRFeature *OGRIngresLayer::RecordToFeature( char **papszRow )
 /* -------------------------------------------------------------------- */
 /*      Handle Ingres geometry                                           */
 /* -------------------------------------------------------------------- */
-        if( osGeomColumn.size() 
+        if( osGeomColumn.size()
             && EQUAL(psFDesc->ds_columnName,osGeomColumn))
         {
         	if( poDS->IsNewIngres() )
@@ -458,17 +458,17 @@ OGRFeature *OGRIngresLayer::RecordToFeature( char **papszRow )
                 poFeature->SetField( iOGRField, dfValue );
             }
             break;
-            
+
           case IIAPI_DEC_TYPE:
           {
               IIAPI_CONVERTPARM sCParm;
               char szFormatBuf[30];
 
               memset( &sCParm, 0, sizeof(sCParm) );
-              
-              memcpy( &(sCParm.cv_srcDesc), psFDesc, 
+
+              memcpy( &(sCParm.cv_srcDesc), psFDesc,
                       sizeof(IIAPI_DESCRIPTOR) );
-              memcpy( &(sCParm.cv_srcValue), psDV, 
+              memcpy( &(sCParm.cv_srcValue), psDV,
                       sizeof(IIAPI_DATAVALUE) );
 
               sCParm.cv_dstDesc.ds_dataType = IIAPI_CHA_TYPE;
@@ -478,7 +478,7 @@ OGRFeature *OGRIngresLayer::RecordToFeature( char **papszRow )
               sCParm.cv_dstValue.dv_value = szFormatBuf;
 
               IIapi_convertData( &sCParm );
-              
+
               poFeature->SetField( iOGRField, szFormatBuf );
               break;
           }
@@ -569,13 +569,11 @@ int OGRIngresLayer::TestCapability( const char * pszCap )
 }
 
 
-
-    
 /************************************************************************/
 /*                            GetFIDColumn()                            */
 /************************************************************************/
 
-const char *OGRIngresLayer::GetFIDColumn() 
+const char *OGRIngresLayer::GetFIDColumn()
 
 {
     return osFIDColumn;
@@ -585,7 +583,7 @@ const char *OGRIngresLayer::GetFIDColumn()
 /*                         GetGeometryColumn()                          */
 /************************************************************************/
 
-const char *OGRIngresLayer::GetGeometryColumn() 
+const char *OGRIngresLayer::GetGeometryColumn()
 
 {
     return osGeomColumn;
@@ -614,17 +612,17 @@ int OGRIngresLayer::FetchSRSId(OGRFeatureDefn *poDefn)
         char         szCommand[1024];
         char           **papszRow;
         OGRIngresStatement oStatement(poDS->GetConn());
-        
-        sprintf( szCommand, 
+
+        sprintf( szCommand,
                  "SELECT srid FROM geometry_columns "
                  "WHERE f_table_name = '%s' AND f_geometry_column = '%s'",
                  poDefn->GetName(),
                  GetGeometryColumn());
-        
+
         oStatement.ExecuteSQL(szCommand);
-        
+
         papszRow = oStatement.GetRow();
-        
+
         if( papszRow != NULL && papszRow[0] != NULL )
         {
             nSRSId = *((II_INT4 *) papszRow[0]);
diff --git a/ogr/ogrsf_frmts/ingres/ogringresresultlayer.cpp b/ogr/ogrsf_frmts/ingres/ogringresresultlayer.cpp
index bd0b022..3c6f601 100644
--- a/ogr/ogrsf_frmts/ingres/ogringresresultlayer.cpp
+++ b/ogr/ogrsf_frmts/ingres/ogringresresultlayer.cpp
@@ -36,7 +36,7 @@ CPL_CVSID("$Id: ogringresresultlayer.cpp 11522 2007-05-15 14:26:10Z mloskot $");
 /*                        OGRIngresResultLayer()                         */
 /************************************************************************/
 
-OGRIngresResultLayer::OGRIngresResultLayer( OGRIngresDataSource *poDSIn, 
+OGRIngresResultLayer::OGRIngresResultLayer( OGRIngresDataSource *poDSIn,
                                             const char * pszRawQueryIn,
                                             OGRIngresStatement *poResultSetIn )
 {
@@ -80,11 +80,11 @@ OGRFeatureDefn *OGRIngresResultLayer::ReadResultDefinition()
 
     poDefn->Reference();
 
-    for( iRawField = 0; 
-         iRawField < (int) poResultSet->getDescrParm.gd_descriptorCount; 
+    for( iRawField = 0;
+         iRawField < (int) poResultSet->getDescrParm.gd_descriptorCount;
          iRawField++ )
     {
-        IIAPI_DESCRIPTOR *psFDesc = 
+        IIAPI_DESCRIPTOR *psFDesc =
             poResultSet->getDescrParm.gd_descriptor + iRawField;
         OGRFieldDefn    oField( psFDesc->ds_columnName, OFTString);
 
@@ -128,7 +128,7 @@ OGRFeatureDefn *OGRIngresResultLayer::ReadResultDefinition()
             break;
 
           default:
-            // any other field we ignore. 
+            // any other field we ignore.
             break;
         }
     }
diff --git a/ogr/ogrsf_frmts/ingres/ogringresstatement.cpp b/ogr/ogrsf_frmts/ingres/ogringresstatement.cpp
index 1255fb6..6b22963 100644
--- a/ogr/ogrsf_frmts/ingres/ogringresstatement.cpp
+++ b/ogr/ogrsf_frmts/ingres/ogringresstatement.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogringresstatement.cpp 23896 2012-02-04 13:29:41Z rouault $
+ * $Id: ogringresstatement.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRIngresStatement class.
@@ -30,7 +30,7 @@
 #include "ogr_ingres.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogringresstatement.cpp 23896 2012-02-04 13:29:41Z rouault $");
+CPL_CVSID("$Id: ogringresstatement.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                         OGRIngresStatement()                         */
@@ -149,17 +149,17 @@ int OGRIngresStatement::ExecuteSQL( const char *pszStatement )
         CPLDebug( "INGRES", "IIapi_query(%s)", pszStatement );
 
     IIapi_query( &queryParm );
-  
+
 /* -------------------------------------------------------------------- */
 /*      Capture handles for result.                                     */
 /* -------------------------------------------------------------------- */
     while( queryParm.qy_genParm.gp_completed == FALSE )
 	IIapi_wait( &waitParm );
 
-    if( queryParm.qy_genParm.gp_status != IIAPI_ST_SUCCESS 
+    if( queryParm.qy_genParm.gp_status != IIAPI_ST_SUCCESS
         || hConn == NULL )
     {
-        ReportError( &(queryParm.qy_genParm), 
+        ReportError( &(queryParm.qy_genParm),
                      CPLString().Printf( "IIapi_query(%s)", pszStatement ) );
         return FALSE;
     }
@@ -167,7 +167,7 @@ int OGRIngresStatement::ExecuteSQL( const char *pszStatement )
     hTransaction = queryParm.qy_tranHandle;
     hStmt = queryParm.qy_stmtHandle;
 
-    if( hStmt == NULL )						
+    if( hStmt == NULL )
     {
         CPLDebug( "INGRES", "No resulting statement." );
         return TRUE;
@@ -192,7 +192,7 @@ int OGRIngresStatement::ExecuteSQL( const char *pszStatement )
     getDescrParm.gd_descriptor = NULL;
 
     IIapi_getDescriptor( &getDescrParm );
-    
+
     while( getDescrParm.gd_genParm.gp_completed == FALSE )
 	IIapi_wait( &waitParm );
 
@@ -227,14 +227,14 @@ int OGRIngresStatement::ExecuteSQL( const char *pszStatement )
     while( queryInfo.gq_genParm.gp_completed == FALSE )
         IIapi_wait( &waitParm );
 
-    CPLDebug( "INGRES", 
-              "gq_flags=%x, gq_mask=%x, gq_rowCount=%d, gq_rowStatus=%d, rowPosition=%d", 
-              queryInfo.gq_flags, 
-              queryInfo.gq_mask, 
-              queryInfo.gq_rowCount, 
-              queryInfo.gq_rowStatus, 
-              queryInfo.gq_rowPosition ); 
-              
+    CPLDebug( "INGRES",
+              "gq_flags=%x, gq_mask=%x, gq_rowCount=%d, gq_rowStatus=%d, rowPosition=%d",
+              queryInfo.gq_flags,
+              queryInfo.gq_mask,
+              queryInfo.gq_rowCount,
+              queryInfo.gq_rowStatus,
+              queryInfo.gq_rowPosition );
+
     if( queryInfo.gq_genParm.gp_status != IIAPI_ST_SUCCESS )
     {
         ReportError( &(queryInfo.gq_genParm), "IIapi_getQueryInfo()" );
@@ -252,20 +252,20 @@ int OGRIngresStatement::ExecuteSQL( const char *pszStatement )
 
     pabyWrkBuffer = (GByte *) CPLCalloc(1,nBufWidth);
 
-    papszFields = (char **) CPLCalloc(sizeof(char *), 
+    papszFields = (char **) CPLCalloc(sizeof(char *),
                                      getDescrParm.gd_descriptorCount+1);
 
     nBufWidth = 0;
     for( i = 0; i < getDescrParm.gd_descriptorCount; i++ )
     {
-        papszFields[i] = (char *) (pabyWrkBuffer + nBufWidth); 
+        papszFields[i] = (char *) (pabyWrkBuffer + nBufWidth);
         nBufWidth += getDescrParm.gd_descriptor[i].ds_length + 1;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Setup the getColumns() argument.                                */
 /* -------------------------------------------------------------------- */
-    pasDataBuffer = (IIAPI_DATAVALUE *) 
+    pasDataBuffer = (IIAPI_DATAVALUE *)
         CPLCalloc(sizeof(IIAPI_DATAVALUE),getDescrParm.gd_descriptorCount);
 
     getColParm.gc_genParm.gp_callback = NULL;
@@ -330,7 +330,7 @@ char **OGRIngresStatement::GetRow()
         if( !IsColumnLong( iBaseCol ) )
         {
             IIapi_getColumns( &getColParm );
-    
+
             while( getColParm.gc_genParm.gp_completed == FALSE )
                 IIapi_wait( &waitParm );
 
@@ -351,7 +351,7 @@ char **OGRIngresStatement::GetRow()
 
             do {
                 IIapi_getColumns( &getColParm );
-    
+
                 while( getColParm.gc_genParm.gp_completed == FALSE )
                     IIapi_wait( &waitParm );
 
@@ -405,16 +405,16 @@ void OGRIngresStatement::ClearDynamicColumns()
 
 void OGRIngresStatement::DumpRow( FILE *fp )
 
-{									
+{
     int   i;
 
     fprintf( fp, "---------------\n" );
     for( i = 0; i < getDescrParm.gd_descriptorCount; i++ )
     {
-        fprintf( fp, "  %s = %s\n", 
-                 getDescrParm.gd_descriptor[i].ds_columnName, 
+        fprintf( fp, "  %s = %s\n",
+                 getDescrParm.gd_descriptor[i].ds_columnName,
                  papszFields[i] );
-    }                 
+    }
 }
 
 /************************************************************************/
@@ -451,23 +451,23 @@ void OGRIngresStatement::ReportError( IIAPI_GENPARM *genParm,
                                       const char *pszDescription )
 
 {
-    IIAPI_GETEINFOPARM  getErrParm; 
+    IIAPI_GETEINFOPARM  getErrParm;
 
     /*
     ** Check API call status.
     */
-    const char *pszCode = 
-        (genParm->gp_status == IIAPI_ST_SUCCESS) ?  
+    const char *pszCode =
+        (genParm->gp_status == IIAPI_ST_SUCCESS) ?
         "IIAPI_ST_SUCCESS" :
-        (genParm->gp_status == IIAPI_ST_MESSAGE) ?  
+        (genParm->gp_status == IIAPI_ST_MESSAGE) ?
         "IIAPI_ST_MESSAGE" :
-        (genParm->gp_status == IIAPI_ST_WARNING) ?  
+        (genParm->gp_status == IIAPI_ST_WARNING) ?
         "IIAPI_ST_WARNING" :
-        (genParm->gp_status == IIAPI_ST_NO_DATA) ?  
+        (genParm->gp_status == IIAPI_ST_NO_DATA) ?
         "IIAPI_ST_NO_DATA" :
-        (genParm->gp_status == IIAPI_ST_ERROR)   ?  
+        (genParm->gp_status == IIAPI_ST_ERROR)   ?
         "IIAPI_ST_ERROR"   :
-        (genParm->gp_status == IIAPI_ST_FAILURE) ? 
+        (genParm->gp_status == IIAPI_ST_FAILURE) ?
         "IIAPI_ST_FAILURE" :
         (genParm->gp_status == IIAPI_ST_NOT_INITIALIZED) ?
         "IIAPI_ST_NOT_INITIALIZED" :
@@ -481,21 +481,21 @@ void OGRIngresStatement::ReportError( IIAPI_GENPARM *genParm,
     ** Check for error information.
     */
     if ( ! genParm->gp_errorHandle )
-    { 
-        CPLDebug( "INGRES", "No gp_errorHandle in ReportError(%s)", 
+    {
+        CPLDebug( "INGRES", "No gp_errorHandle in ReportError(%s)",
                   pszDescription );
         return;
     }
 
     getErrParm.ge_errorHandle = genParm->gp_errorHandle;
-    
+
     CPLString osErrorMessage;
     CPLErr eType = CE_Failure;
-        
+
     osErrorMessage.Printf( "%s: %s", pszDescription, pszCode );
 
     do
-    { 
+    {
 	/*
 	** Invoke API function call.
  	*/
@@ -513,8 +513,8 @@ void OGRIngresStatement::ReportError( IIAPI_GENPARM *genParm,
 
 	switch( getErrParm.ge_type )
 	{
-           case IIAPI_GE_ERROR		: 
-            eType = CE_Failure; 
+           case IIAPI_GE_ERROR		:
+            eType = CE_Failure;
             break;
 
           case IIAPI_GE_WARNING	:
@@ -562,7 +562,7 @@ int OGRIngresStatement::SendParms()
     setDescrParm.sd_stmtHandle = hStmt;
     setDescrParm.sd_descriptorCount = 1;
     setDescrParm.sd_descriptor = ( IIAPI_DESCRIPTOR * )( &DescrBuffer );
- 
+
     setDescrParm.sd_descriptor[0].ds_dataType = eParmType;
     setDescrParm.sd_descriptor[0].ds_nullable = FALSE;
     setDescrParm.sd_descriptor[0].ds_length = (II_UINT2) (nParmLen+2);
@@ -572,7 +572,7 @@ int OGRIngresStatement::SendParms()
     setDescrParm.sd_descriptor[0].ds_columnName = NULL;
 
     IIapi_setDescriptor( &setDescrParm );
-	
+
     while( setDescrParm.sd_genParm.gp_completed == FALSE )
 	IIapi_wait( &waitParm );
 
@@ -618,7 +618,7 @@ int OGRIngresStatement::SendParms()
 	if ( putParmParm.pp_genParm.gp_status != IIAPI_ST_SUCCESS )
         {
             ReportError( &(putParmParm.pp_genParm), "SendParm()" );
-            
+
             return FALSE;
         }
     }
@@ -634,12 +634,12 @@ int OGRIngresStatement::SendParms()
 /*      but we might change that in the future.                         */
 /************************************************************************/
 
-void OGRIngresStatement::addInputParameter( 
+void OGRIngresStatement::addInputParameter(
     IIAPI_DT_ID eDType, int nLength, GByte *pabyData )
 
 {
     CPLAssert( !bHaveParm );
-    CPLAssert( eDType == IIAPI_LVCH_TYPE || eDType == IIAPI_LBYTE_TYPE ); 
+    CPLAssert( eDType == IIAPI_LVCH_TYPE || eDType == IIAPI_LBYTE_TYPE );
     // support long varchar and long byte
 
     bHaveParm = TRUE;
diff --git a/ogr/ogrsf_frmts/ingres/ogringrestablelayer.cpp b/ogr/ogrsf_frmts/ingres/ogringrestablelayer.cpp
index 4166109..9a221dc 100644
--- a/ogr/ogrsf_frmts/ingres/ogringrestablelayer.cpp
+++ b/ogr/ogrsf_frmts/ingres/ogringrestablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogringrestablelayer.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogringrestablelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRIngresTableLayer class.
@@ -31,13 +31,13 @@
 #include "cpl_string.h"
 #include "ogr_ingres.h"
 
-CPL_CVSID("$Id: ogringrestablelayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogringrestablelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                         OGRIngresTableLayer()                         */
 /************************************************************************/
 
-OGRIngresTableLayer::OGRIngresTableLayer( OGRIngresDataSource *poDSIn, 
+OGRIngresTableLayer::OGRIngresTableLayer( OGRIngresDataSource *poDSIn,
                                   const char * pszTableName,
                                   int bUpdate, int nSRSIdIn )
 
@@ -74,7 +74,7 @@ OGRIngresTableLayer::~OGRIngresTableLayer()
 
 OGRErr  OGRIngresTableLayer::Initialize(const char * pszTableName)
 {
-    poFeatureDefn = ReadTableDefinition( pszTableName );   
+    poFeatureDefn = ReadTableDefinition( pszTableName );
     if (poFeatureDefn)
     {
         ResetReading();
@@ -107,7 +107,7 @@ OGRFeatureDefn *OGRIngresTableLayer::ReadTableDefinition( const char *pszTable )
     osCommand.Printf( "select column_name, column_datatype, column_length, "
                       "column_scale, column_ingdatatype, "
                       "column_internal_datatype "
-                      "from iicolumns where table_name = '%s'", 
+                      "from iicolumns where table_name = '%s'",
                       pszTable );
 
     if( !oStatement.ExecuteSQL( osCommand ) )
@@ -164,7 +164,7 @@ OGRFeatureDefn *OGRIngresTableLayer::ReadTableDefinition( const char *pszTable )
         {
             osGeomColumn = osFieldName;
             osIngresGeomType = osInternalType;
-            
+
             if( strstr(osInternalType,"POINT") )
                 poDefn->SetGeomType( wkbPoint );
             else if( strstr(osInternalType,"LINE")
@@ -184,19 +184,19 @@ OGRFeatureDefn *OGRIngresTableLayer::ReadTableDefinition( const char *pszTable )
                 poDefn->SetGeomType( wkbPolygon );
             continue;
         }
-        else if( EQUALN(osIngresType,"byte",4) 
-            || EQUALN(osIngresType,"long byte",9) )
+        else if( STARTS_WITH_CI(osIngresType, "byte")
+            || STARTS_WITH_CI(osIngresType, "long byte") )
         {
             oField.SetType( OFTBinary );
         }
-        else if( EQUALN(osIngresType,"varchar",7) 
-                 || EQUAL(osIngresType,"text") 
-                 || EQUALN(osIngresType,"long varchar",12) )
+        else if( STARTS_WITH_CI(osIngresType, "varchar")
+                 || EQUAL(osIngresType,"text")
+                 || STARTS_WITH_CI(osIngresType, "long varchar") )
         {
             oField.SetType( OFTString );
             oField.SetWidth( nWidth );
         }
-        else if( EQUALN(osIngresType,"char",4) || EQUAL(osIngresType,"c") )
+        else if( STARTS_WITH_CI(osIngresType, "char") || EQUAL(osIngresType,"c") )
         {
             oField.SetType( OFTString );
             oField.SetWidth( nWidth );
@@ -205,7 +205,7 @@ OGRFeatureDefn *OGRIngresTableLayer::ReadTableDefinition( const char *pszTable )
         {
             oField.SetType( OFTInteger );
         }
-        else if( EQUALN(osIngresType,"decimal", 7) )
+        else if( STARTS_WITH_CI(osIngresType, "decimal") )
         {
             if( nScale != 0 )
             {
@@ -219,13 +219,13 @@ OGRFeatureDefn *OGRIngresTableLayer::ReadTableDefinition( const char *pszTable )
                 oField.SetWidth( nWidth );
             }
         }
-        else if( EQUALN(osIngresType,"float", 5) )
+        else if( STARTS_WITH_CI(osIngresType, "float") )
         {
             oField.SetType( OFTReal );
         }
 #ifdef notdef
-        else if( EQUAL(osIngresType,"date") 
-                 || EQUAL(osIngresType,"ansidate") 
+        else if( EQUAL(osIngresType,"date")
+                 || EQUAL(osIngresType,"ansidate")
                  || EQUAL(osIngresType,"ingresdate") )
         {
             oField.SetType( OFTDate );
@@ -233,8 +233,8 @@ OGRFeatureDefn *OGRIngresTableLayer::ReadTableDefinition( const char *pszTable )
 #endif
 
         // Is this an integer primary key field?
-        if( osFIDColumn.size() == 0 
-            && oField.GetType() == OFTInteger 
+        if( osFIDColumn.size() == 0
+            && oField.GetType() == OFTInteger
             && EQUAL(oField.GetNameRef(),"ogr_fid") )
         {
             osFIDColumn = oField.GetNameRef();
@@ -248,7 +248,7 @@ OGRFeatureDefn *OGRIngresTableLayer::ReadTableDefinition( const char *pszTable )
         CPLDebug( "Ingres", "table %s has FID column %s.",
                   pszTable, osFIDColumn.c_str() );
     else
-        CPLDebug( "Ingres", 
+        CPLDebug( "Ingres",
                   "table %s has no FID column, FIDs will not be reliable!",
                   pszTable );
 
@@ -297,10 +297,10 @@ void OGRIngresTableLayer::BuildWhere()
         char szEnvelope[4096];
         OGREnvelope  sEnvelope;
         szEnvelope[0] = '\0';
-        
+
         //POLYGON((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))
         m_poFilterGeom->getEnvelope( &sEnvelope );
-        
+
         sprintf(szEnvelope,
                 "POLYGON((%.12f %.12f, %.12f %.12f, %.12f %.12f, %.12f %.12f, %.12f %.12f))",
                 sEnvelope.MinX, sEnvelope.MinY,
@@ -334,10 +334,10 @@ void OGRIngresTableLayer::BuildFullQueryStatement()
 {
     char *pszFields = BuildFields();
 
-    osQueryStatement.Printf( "SELECT %s FROM %s %s", 
-                             pszFields, poFeatureDefn->GetName(), 
+    osQueryStatement.Printf( "SELECT %s FROM %s %s",
+                             pszFields, poFeatureDefn->GetName(),
                              osWHERE.c_str() );
-    
+
     CPLFree( pszFields );
 }
 
@@ -457,7 +457,7 @@ int OGRIngresTableLayer::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCDeleteFeature) )
         return bUpdateAccess && osFIDColumn.size() != 0;
 
-    else 
+    else
         return OGRIngresLayer::TestCapability( pszCap );
 }
 
@@ -516,13 +516,13 @@ OGRErr OGRIngresTableLayer::DeleteFeature( GIntBig nFID )
 /* -------------------------------------------------------------------- */
     osCommand.Printf( "DELETE FROM %s WHERE %s = %ld",
                       poFeatureDefn->GetName(), osFIDColumn.c_str(), nFID );
-                      
+
 /* -------------------------------------------------------------------- */
 /*      Execute the delete.                                             */
 /* -------------------------------------------------------------------- */
     poDS->EstablishActiveLayer( NULL );
     OGRIngresStatement oStmt( poDS->GetConn() );
-    
+
     if( !oStmt.ExecuteSQL( osCommand ) )
         return OGRERR_FAILURE;
     else
@@ -536,7 +536,7 @@ OGRErr OGRIngresTableLayer::DeleteFeature( GIntBig nFID )
 /*      a form suitable to include in an INSERT command.                */
 /************************************************************************/
 
-OGRErr OGRIngresTableLayer::PrepareOldStyleGeometry( 
+OGRErr OGRIngresTableLayer::PrepareOldStyleGeometry(
     OGRGeometry *poGeom, CPLString &osRetGeomText )
 
 {
@@ -562,8 +562,8 @@ OGRErr OGRIngresTableLayer::PrepareOldStyleGeometry(
     {
         OGRPoint *poPoint = (OGRPoint *) poGeom;
 
-        osRetGeomText.Printf( "(%d,%d)", 
-                              (int) floor(poPoint->getX()), 
+        osRetGeomText.Printf( "(%d,%d)",
+                              (int) floor(poPoint->getX()),
                               (int) floor(poPoint->getY()) );
         return OGRERR_NONE;
     }
@@ -577,31 +577,31 @@ OGRErr OGRIngresTableLayer::PrepareOldStyleGeometry(
         CPLString osLastPoint;
         int i;
 
-        if( (EQUAL(osIngresGeomType,"LSEG") 
-             || EQUAL(osIngresGeomType,"ILSEG")) 
+        if( (EQUAL(osIngresGeomType,"LSEG")
+             || EQUAL(osIngresGeomType,"ILSEG"))
             && poLS->getNumPoints() != 2 )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "Attempt to place %d vertex linestring in %s field.", 
-                      poLS->getNumPoints(), 
+                      "Attempt to place %d vertex linestring in %s field.",
+                      poLS->getNumPoints(),
                       osIngresGeomType.c_str() );
             return OGRERR_FAILURE;
         }
-        else if( EQUAL(osIngresGeomType,"LINESTRING") 
+        else if( EQUAL(osIngresGeomType,"LINESTRING")
                  && poLS->getNumPoints() > 124 )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "Attempt to place %d vertex linestring in %s field.", 
-                      poLS->getNumPoints(), 
+                      "Attempt to place %d vertex linestring in %s field.",
+                      poLS->getNumPoints(),
                       osIngresGeomType.c_str() );
             return OGRERR_FAILURE;
         }
-        else if( EQUAL(osIngresGeomType,"ILINESTRING") 
+        else if( EQUAL(osIngresGeomType,"ILINESTRING")
                  && poLS->getNumPoints() > 248 )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "Attempt to place %d vertex linestring in %s field.", 
-                      poLS->getNumPoints(), 
+                      "Attempt to place %d vertex linestring in %s field.",
+                      poLS->getNumPoints(),
                       osIngresGeomType.c_str() );
             return OGRERR_FAILURE;
         }
@@ -611,20 +611,20 @@ OGRErr OGRIngresTableLayer::PrepareOldStyleGeometry(
         {
             CPLString osPoint;
 
-            if( i > 0 
+            if( i > 0
                 && poLS->getX(i) == poLS->getX(i-1)
                 && poLS->getY(i) == poLS->getY(i-1) )
             {
                 CPLDebug( "INGRES", "Dropping duplicate point in linestring.");
                 continue;
             }
-            
-            if( EQUALN(osIngresGeomType,"I",1) )
+
+            if( STARTS_WITH_CI(osIngresGeomType, "I") )
                 osPoint.Printf( "(%d,%d)",
-                                (int) floor(poLS->getX(i)), 
+                                (int) floor(poLS->getX(i)),
                                 (int) floor(poLS->getY(i)) );
             else
-                osPoint.Printf( "(%.15g,%.15g)", 
+                osPoint.Printf( "(%.15g,%.15g)",
                                 poLS->getX(i), poLS->getY(i) );
 
             if( osPoint == osLastPoint )
@@ -666,21 +666,21 @@ OGRErr OGRIngresTableLayer::PrepareOldStyleGeometry(
                       osIngresGeomType.c_str() );
         }
 
-        if( EQUAL(osIngresGeomType,"POLYGON") 
+        if( EQUAL(osIngresGeomType,"POLYGON")
             && poLS->getNumPoints() > 124 )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "Attempt to place %d vertex linestring in %s field.", 
-                      poLS->getNumPoints(), 
+                      "Attempt to place %d vertex linestring in %s field.",
+                      poLS->getNumPoints(),
                       osIngresGeomType.c_str() );
             return OGRERR_FAILURE;
         }
-        else if( EQUAL(osIngresGeomType,"IPOLYGON") 
+        else if( EQUAL(osIngresGeomType,"IPOLYGON")
                  && poLS->getNumPoints() > 248 )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "Attempt to place %d vertex linestring in %s field.", 
-                      poLS->getNumPoints(), 
+                      "Attempt to place %d vertex linestring in %s field.",
+                      poLS->getNumPoints(),
                       osIngresGeomType.c_str() );
             return OGRERR_FAILURE;
         }
@@ -688,7 +688,7 @@ OGRErr OGRIngresTableLayer::PrepareOldStyleGeometry(
         // INGRES geometries use *implied* closure of rings.
         nPoints = poLS->getNumPoints();
         if( poLS->getX(0) == poLS->getX(nPoints-1)
-            && poLS->getY(0) == poLS->getY(nPoints-1) 
+            && poLS->getY(0) == poLS->getY(nPoints-1)
             && nPoints > 1 )
             nPoints--;
 
@@ -696,21 +696,21 @@ OGRErr OGRIngresTableLayer::PrepareOldStyleGeometry(
         for( i = 0; i < nPoints; i++ )
         {
             CPLString osPoint;
-            
-            if( i > 0 
+
+            if( i > 0
                 && poLS->getX(i) == poLS->getX(i-1)
                 && poLS->getY(i) == poLS->getY(i-1) )
             {
                 CPLDebug( "INGRES", "Dropping duplicate point in linestring.");
                 continue;
             }
-            
-            if( EQUALN(osIngresGeomType,"I",1) )
+
+            if( STARTS_WITH_CI(osIngresGeomType, "I") )
                 osPoint.Printf( "(%d,%d)",
-                                (int) floor(poLS->getX(i)), 
+                                (int) floor(poLS->getX(i)),
                                 (int) floor(poLS->getY(i)) );
             else
-                osPoint.Printf( "(%.15g,%.15g)", 
+                osPoint.Printf( "(%.15g,%.15g)",
                                 poLS->getX(i), poLS->getY(i) );
 
             if( osRetGeomText.size() > 1 )
@@ -796,9 +796,9 @@ OGRErr OGRIngresTableLayer::PrepareNewStyleGeometry(
 /* -------------------------------------------------------------------- */
 /*      Fallback generic geometry handling.                             */
 /* -------------------------------------------------------------------- */
-    else 
+    else
     {
-        CPLDebug( 
+        CPLDebug(
             "INGRES",
             "Unexpected geometry type (%s), attempting to treat generically.",
             poGeom->getGeometryName() );
@@ -838,7 +838,7 @@ OGRErr OGRIngresTableLayer::ICreateFeature( OGRFeature *poFeature )
     {
         if( bNeedComma )
             osCommand += ", ";
-        
+
         osCommand = osCommand + osFIDColumn + " ";
         bNeedComma = TRUE;
     }
@@ -853,7 +853,7 @@ OGRErr OGRIngresTableLayer::ICreateFeature( OGRFeature *poFeature )
         else
             osCommand += ", ";
 
-        osCommand = osCommand 
+        osCommand = osCommand
              + poFeatureDefn->GetFieldDefn(i)->GetNameRef();
     }
 
@@ -864,7 +864,7 @@ OGRErr OGRIngresTableLayer::ICreateFeature( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
     CPLString osGeomText;
 
-    // Set the geometry 
+    // Set the geometry
     bNeedComma = FALSE;
     if( poFeature->GetGeometryRef() != NULL && osGeomColumn.size() )
     {
@@ -881,7 +881,7 @@ OGRErr OGRIngresTableLayer::ICreateFeature( OGRFeature *poFeature )
         }
         if( localErr == OGRERR_NONE )
         {
-            if( CSLTestBoolean( 
+            if( CPLTestBool(
                      CPLGetConfigOption( "INGRES_INSERT_SUB", "NO") ) )
             {
                 osCommand += " ~V";
@@ -938,7 +938,7 @@ OGRErr OGRIngresTableLayer::ICreateFeature( OGRFeature *poFeature )
         {
             int         iChar;
 
-            //We need to quote and escape string fields. 
+            //We need to quote and escape string fields.
             osCommand += "'";
 
             for( iChar = 0; pszStrValue[iChar] != '\0'; iChar++ )
@@ -992,7 +992,7 @@ OGRErr OGRIngresTableLayer::ICreateFeature( OGRFeature *poFeature )
     poDS->EstablishActiveLayer( NULL );
     OGRIngresStatement oStmt( poDS->GetConn() );
 
-    oStmt.bDebug = FALSE; 
+    oStmt.bDebug = FALSE;
 
     if( osGeomText.size() > 0  && poDS->IsNewIngres() == FALSE )
         oStmt.addInputParameter( IIAPI_LVCH_TYPE, osGeomText.size(),
@@ -1016,7 +1016,7 @@ OGRErr OGRIngresTableLayer::ICreateFeature( OGRFeature *poFeature )
 
     if( !oStmt.ExecuteSQL( osCommand ) )
         return OGRERR_FAILURE;
-    
+
     return OGRERR_NONE;
 
 }
@@ -1025,7 +1025,7 @@ OGRErr OGRIngresTableLayer::ICreateFeature( OGRFeature *poFeature )
 /*                            CreateField()                             */
 /************************************************************************/
 
-OGRErr OGRIngresTableLayer::CreateField( OGRFieldDefn *poFieldIn, 
+OGRErr OGRIngresTableLayer::CreateField( OGRFieldDefn *poFieldIn,
                                          int bApproxOK )
 
 {
@@ -1117,14 +1117,14 @@ OGRErr OGRIngresTableLayer::CreateField( OGRFieldDefn *poFieldIn,
     }
 
     osCommand.Printf( "ALTER TABLE %s ADD COLUMN %s %s",
-                      poFeatureDefn->GetName(), oField.GetNameRef(), 
+                      poFeatureDefn->GetName(), oField.GetNameRef(),
                       szFieldType );
 
     if( !oStatement.ExecuteSQL( osCommand ) )
         return OGRERR_FAILURE;
 
-    poFeatureDefn->AddFieldDefn( &oField );    
-    
+    poFeatureDefn->AddFieldDefn( &oField );
+
     return OGRERR_NONE;
 }
 
@@ -1150,9 +1150,9 @@ OGRFeature *OGRIngresTableLayer::GetFeature( GIntBig nFeatureId )
     char        *pszFieldList = BuildFields();
     char        *pszCommand = (char *) CPLMalloc(strlen(pszFieldList)+2000);
 
-    sprintf( pszCommand, 
-             "SELECT %s FROM %s WHERE %s = %ld", 
-             pszFieldList, poFeatureDefn->GetName(), pszFIDColumn, 
+    sprintf( pszCommand,
+             "SELECT %s FROM %s WHERE %s = %ld",
+             pszFieldList, poFeatureDefn->GetName(), pszFIDColumn,
              nFeatureId );
     CPLFree( pszFieldList );
 
@@ -1222,14 +1222,14 @@ GIntBig OGRIngresTableLayer::GetFeatureCount( int bForce )
 /*      Ensure any active long result is interrupted.                   */
 /* -------------------------------------------------------------------- */
     poDS->InterruptLongResult();
-    
+
 /* -------------------------------------------------------------------- */
 /*      Issue the appropriate select command.                           */
 /* -------------------------------------------------------------------- */
     INGRES_RES    *hResult;
     const char         *pszCommand;
 
-    pszCommand = CPLSPrintf( "SELECT COUNT(*) FROM %s %s", 
+    pszCommand = CPLSPrintf( "SELECT COUNT(*) FROM %s %s",
                              poFeatureDefn->GetName(), pszWHERE );
 
     if( ingres_query( poDS->GetConn(), pszCommand ) )
@@ -1244,7 +1244,7 @@ GIntBig OGRIngresTableLayer::GetFeatureCount( int bForce )
         poDS->ReportError( "ingres_store_result() failed on SELECT COUNT(*)." );
         return FALSE;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Capture the result.                                             */
 /* -------------------------------------------------------------------- */
@@ -1257,7 +1257,7 @@ GIntBig OGRIngresTableLayer::GetFeatureCount( int bForce )
     if( hResultSet != NULL )
         ingres_free_result( hResultSet );
  		hResultSet = NULL;
-    
+
     return nCount;
 }
 #endif
@@ -1279,7 +1279,7 @@ OGRErr OGRIngresTableLayer::GetExtent(OGREnvelope *psExtent, int bForce )
         psExtent->MaxX = 0.0;
         psExtent->MinY = 0.0;
         psExtent->MaxY = 0.0;
-        
+
         return OGRERR_FAILURE;
     }
 
@@ -1298,7 +1298,7 @@ OGRErr OGRIngresTableLayer::GetExtent(OGREnvelope *psExtent, int bForce )
             return OGRERR_FAILURE;
         }
 
-		INGRES_ROW row; 
+		INGRES_ROW row;
 		unsigned long *panLengths = NULL;
 		while ((row = ingres_fetch_row(result)))
 		{
@@ -1314,7 +1314,7 @@ OGRErr OGRIngresTableLayer::GetExtent(OGREnvelope *psExtent, int bForce )
 
 			OGRGeometry *poGeometry = NULL;
 			// Geometry columns will have the first 4 bytes contain the SRID.
-			OGRGeometryFactory::createFromWkb(((GByte *)row[0]) + 4, 
+			OGRGeometryFactory::createFromWkb(((GByte *)row[0]) + 4,
 											  NULL,
 											  &poGeometry,
 											  panLengths[0] - 4 );
@@ -1329,23 +1329,22 @@ OGRErr OGRIngresTableLayer::GetExtent(OGREnvelope *psExtent, int bForce )
 				else if (poGeometry)
 				{
 					poGeometry->getEnvelope(&oEnv);
-					if (oEnv.MinX < psExtent->MinX) 
+					if (oEnv.MinX < psExtent->MinX)
 						psExtent->MinX = oEnv.MinX;
-					if (oEnv.MinY < psExtent->MinY) 
+					if (oEnv.MinY < psExtent->MinY)
 						psExtent->MinY = oEnv.MinY;
-					if (oEnv.MaxX > psExtent->MaxX) 
+					if (oEnv.MaxX > psExtent->MaxX)
 						psExtent->MaxX = oEnv.MaxX;
-					if (oEnv.MaxY > psExtent->MaxY) 
+					if (oEnv.MaxY > psExtent->MaxY)
 						psExtent->MaxY = oEnv.MaxY;
 				}
 				delete poGeometry;
 			}
 		}
 
-		ingres_free_result(result);      
+		ingres_free_result(result);
 	}
 
 	return (bExtentSet ? OGRERR_NONE : OGRERR_FAILURE);
 }
 #endif
-
diff --git a/ogr/ogrsf_frmts/jml/drv_jml.html b/ogr/ogrsf_frmts/jml/drv_jml.html
index 0e80aa2..2c33537 100644
--- a/ogr/ogrsf_frmts/jml/drv_jml.html
+++ b/ogr/ogrsf_frmts/jml/drv_jml.html
@@ -20,7 +20,7 @@ arbitrary serialized Java objects, is converted as string when reading.
 Contrary to GML, the definition of fields is embedded in the .jml file, at its
 beginning.<p>
 
-.jml doesn't support spatial reference systems.<p>
+.jml does not support spatial reference systems.<p>
 
 <h2>Encoding issues</h2>
 
@@ -34,7 +34,7 @@ Expat library supports reading the following built-in encodings :
 </ul>
 
 The content returned by OGR will be encoded in UTF-8, after the conversion from the
-encoding mentionned in the file header is. But files produced by OpenJUMP are
+encoding mentioned in the file header is. But files produced by OpenJUMP are
 always UTF-8 encoded.<p>
 
 When writing a JML file, the driver expects UTF-8 content to be passed in.<p>
diff --git a/ogr/ogrsf_frmts/jml/ogr_jml.h b/ogr/ogrsf_frmts/jml/ogr_jml.h
index 924b738..8121c78 100644
--- a/ogr/ogrsf_frmts/jml/ogr_jml.h
+++ b/ogr/ogrsf_frmts/jml/ogr_jml.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_jml.h 27959 2014-11-14 18:29:21Z rouault $
+ * $Id: ogr_jml.h 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  JML .jml Translator
  * Purpose:  Definition of classes for OGR JML driver.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_JML_H_INCLUDED
-#define _OGR_JML_H_INCLUDED
+#ifndef OGR_JML_H_INCLUDED
+#define OGR_JML_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "ogr_p.h"
@@ -55,7 +55,8 @@ class OGRJMLColumn
         CPLString osElementName;
         CPLString osAttributeName;
         CPLString osAttributeValue;
-        int       bIsBody; /* if false: attribute */
+        bool      bIsBody; /* if false: attribute */
+        OGRJMLColumn() : bIsBody(false) {}
 };
 
 /************************************************************************/
@@ -65,20 +66,19 @@ class OGRJMLColumn
 class OGRJMLLayer : public OGRLayer
 {
     OGRFeatureDefn     *poFeatureDefn;
-    OGRJMLDataset *poDS;
 
     int                nNextFID;
     VSILFILE*          fp;
-    int                bHasReadSchema;
+    bool               bHasReadSchema;
 
     XML_Parser         oParser;
 
     int                currentDepth;
-    int                bStopParsing;
+    bool               bStopParsing;
     int                nWithoutEventCounter;
     int                nDataHandlerCounter;
-    
-    int                bAccumulateElementValue;
+
+    bool               bAccumulateElementValue;
     char              *pszElementValue;
     int                nElementValueLen;
     int                nElementValueAlloc;
@@ -88,7 +88,7 @@ class OGRJMLLayer : public OGRLayer
     int                nFeatureTabLength;
     int                nFeatureTabIndex;
 
-    int                bSchemaFinished;
+    bool               bSchemaFinished;
     int                nJCSGMLInputTemplateDepth;
     int                nCollectionElementDepth;
     CPLString          osCollectionElement;
@@ -123,7 +123,7 @@ class OGRJMLLayer : public OGRLayer
     OGRFeature *        GetNextFeature();
 
     OGRFeatureDefn *    GetLayerDefn();
-    
+
     int                 TestCapability( const char * );
 
     void                startElementCbk(const char *pszName, const char **ppszAttr);
@@ -143,24 +143,23 @@ class OGRJMLLayer : public OGRLayer
 class OGRJMLWriterLayer : public OGRLayer
 {
     OGRFeatureDefn     *poFeatureDefn;
-    OGRJMLDataset *poDS;
     VSILFILE           *fp;
-    int                 bFeaturesWritten;
-    int                 bAddRGBField;
-    int                 bAddOGRStyleField;
-    int                 bClassicGML;
+    bool                bFeaturesWritten;
+    bool                bAddRGBField;
+    bool                bAddOGRStyleField;
+    bool                bClassicGML;
     int                 nNextFID;
 
     void                WriteColumnDeclaration( const char* pszName,
                                                 const char* pszType );
 
   public:
-                        OGRJMLWriterLayer(const char* pszLayerName,
-                                               OGRJMLDataset* poDS,
-                                               VSILFILE* fp,
-                                               int bAddRGBField,
-                                               int bAddOGRStyleField,
-                                               int bClassicGML );
+                        OGRJMLWriterLayer( const char* pszLayerName,
+                                           OGRJMLDataset* poDS,
+                                           VSILFILE* fp,
+                                           bool bAddRGBField,
+                                           bool bAddOGRStyleField,
+                                           bool bClassicGML );
                         ~OGRJMLWriterLayer();
 
     void                ResetReading() {}
@@ -183,7 +182,7 @@ class OGRJMLDataset : public GDALDataset
     OGRLayer           *poLayer;
 
     VSILFILE           *fp; /* Virtual file API */
-    int                 bWriteMode;
+    bool                bWriteMode;
 
   public:
                         OGRJMLDataset();
@@ -191,7 +190,7 @@ class OGRJMLDataset : public GDALDataset
 
     int                 GetLayerCount() { return poLayer != NULL ? 1 : 0; }
     OGRLayer*           GetLayer( int );
-    
+
     OGRLayer *          ICreateLayer( const char * pszLayerName,
                                     OGRSpatialReference *poSRS,
                                     OGRwkbGeometryType eType,
@@ -201,7 +200,7 @@ class OGRJMLDataset : public GDALDataset
 
     static int          Identify( GDALOpenInfo* poOpenInfo );
     static GDALDataset* Open( GDALOpenInfo* poOpenInfo );
-    static GDALDataset* Create( const char *pszFilename, 
+    static GDALDataset* Create( const char *pszFilename,
                                  int nBands,
                                  int nXSize,
                                  int nYSize,
@@ -209,4 +208,4 @@ class OGRJMLDataset : public GDALDataset
                                  char **papszOptions );
 };
 
-#endif /* ndef _OGR_JML_H_INCLUDED */
+#endif /* ndef OGR_JML_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/jml/ogrjmldataset.cpp b/ogr/ogrsf_frmts/jml/ogrjmldataset.cpp
index f7fb48f..9bcce87 100644
--- a/ogr/ogrsf_frmts/jml/ogrjmldataset.cpp
+++ b/ogr/ogrsf_frmts/jml/ogrjmldataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrjmldataset.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrjmldataset.cpp 32786 2016-01-06 18:29:00Z goatbar $
  *
  * Project:  JML Translator
  * Purpose:  Implements OGRJMLDataset class
@@ -27,29 +27,24 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_jml.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
-
-extern "C" void RegisterOGRJML();
+#include "ogr_jml.h"
+#include "ogrsf_frmts.h"
 
 // g++ -DHAVE_EXPAT -fPIC -shared -Wall -g -DDEBUG ogr/ogrsf_frmts/jml/*.cpp -o ogr_JML.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/jml -L. -lgdal
 
-CPL_CVSID("$Id: ogrjmldataset.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrjmldataset.cpp 32786 2016-01-06 18:29:00Z goatbar $");
 
 /************************************************************************/
 /*                          OGRJMLDataset()                             */
 /************************************************************************/
 
-OGRJMLDataset::OGRJMLDataset()
-
-{
-    poLayer = NULL;
-
-    fp = NULL;
-
-    bWriteMode = FALSE;
-}
+OGRJMLDataset::OGRJMLDataset() :
+    poLayer(NULL),
+    fp(NULL),
+    bWriteMode(false)
+{}
 
 /************************************************************************/
 /*                         ~OGRJMLDataset()                             */
@@ -73,8 +68,8 @@ int OGRJMLDataset::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,ODsCCreateLayer) )
         return bWriteMode && poLayer == NULL;
-    else
-        return FALSE;
+
+    return FALSE;
 }
 
 /************************************************************************/
@@ -86,8 +81,8 @@ OGRLayer *OGRJMLDataset::GetLayer( int iLayer )
 {
     if( iLayer != 0 )
         return NULL;
-    else
-        return poLayer;
+
+    return poLayer;
 }
 
 /************************************************************************/
@@ -97,7 +92,8 @@ OGRLayer *OGRJMLDataset::GetLayer( int iLayer )
 int OGRJMLDataset::Identify( GDALOpenInfo* poOpenInfo )
 {
     return poOpenInfo->nHeaderBytes != 0 &&
-           strstr((const char*)poOpenInfo->pabyHeader, "<JCSDataFile") != NULL;
+      strstr(reinterpret_cast<char*>(poOpenInfo->pabyHeader),
+             "<JCSDataFile") != NULL;
 }
 
 /************************************************************************/
@@ -112,8 +108,9 @@ GDALDataset* OGRJMLDataset::Open( GDALOpenInfo* poOpenInfo )
         return NULL;
 
 #ifndef HAVE_EXPAT
-    CPLError(CE_Failure, CPLE_NotSupported,
-             "OGR/JML driver has not been built with read support. Expat library required");
+    CPLError( CE_Failure, CPLE_NotSupported,
+              "OGR/JML driver has not been built with read support. "
+              "Expat library required" );
     return NULL;
 #else
     OGRJMLDataset* poDS = new OGRJMLDataset();
@@ -122,7 +119,8 @@ GDALDataset* OGRJMLDataset::Open( GDALOpenInfo* poOpenInfo )
     poDS->fp = poOpenInfo->fpL;
     poOpenInfo->fpL = NULL;
 
-    poDS->poLayer = new OGRJMLLayer( CPLGetBasename(poOpenInfo->pszFilename), poDS, poDS->fp);
+    poDS->poLayer = new OGRJMLLayer(
+        CPLGetBasename(poOpenInfo->pszFilename), poDS, poDS->fp );
 
     return poDS;
 #endif
@@ -132,12 +130,12 @@ GDALDataset* OGRJMLDataset::Open( GDALOpenInfo* poOpenInfo )
 /*                               Create()                               */
 /************************************************************************/
 
-GDALDataset* OGRJMLDataset::Create( const char *pszFilename, 
-                                CPL_UNUSED int nXSize,
-                                CPL_UNUSED int nYSize,
-                                CPL_UNUSED int nBands,
-                                CPL_UNUSED GDALDataType eDT,
-                                CPL_UNUSED char **papszOptions )
+GDALDataset* OGRJMLDataset::Create( const char *pszFilename,
+                                    int /* nXSize */,
+                                    int /* nYSize */,
+                                    int /* nBands */,
+                                    GDALDataType /* eDT */,
+                                    char ** /* papszOptions */ )
 {
     if (strcmp(pszFilename, "/dev/stdout") == 0)
         pszFilename = "/vsistdout/";
@@ -149,9 +147,10 @@ GDALDataset* OGRJMLDataset::Create( const char *pszFilename,
 
     if( VSIStatL( pszFilename, &sStatBuf ) == 0 )
     {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "You have to delete %s before being able to create it with the JML driver",
-                 pszFilename);
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "You have to delete %s before being able to create it "
+                  "with the JML driver",
+                  pszFilename);
         return NULL;
     }
 
@@ -160,14 +159,14 @@ GDALDataset* OGRJMLDataset::Create( const char *pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Create the output file.                                         */
 /* -------------------------------------------------------------------- */
-    poDS->bWriteMode = TRUE;
+    poDS->bWriteMode = true;
     poDS->SetDescription( pszFilename );
 
     poDS->fp = VSIFOpenL( pszFilename, "w" );
     if( poDS->fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Failed to create JML file %s.", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to create JML file %s.",
                   pszFilename );
         delete poDS;
         return NULL;
@@ -181,22 +180,22 @@ GDALDataset* OGRJMLDataset::Create( const char *pszFilename,
 /************************************************************************/
 
 OGRLayer * OGRJMLDataset::ICreateLayer( const char * pszLayerName,
-                                             CPL_UNUSED OGRSpatialReference *poSRS,
-                                             CPL_UNUSED OGRwkbGeometryType eType,
-                                             char ** papszOptions )
+                                        OGRSpatialReference * /* poSRS */,
+                                        OGRwkbGeometryType /* eType */,
+                                        char ** papszOptions )
 {
     if (!bWriteMode || poLayer != NULL)
         return NULL;
 
-    int bAddRGBField = CSLTestBoolean(
+    bool bAddRGBField = CPLTestBool(
         CSLFetchNameValueDef(papszOptions, "CREATE_R_G_B_FIELD", "YES"));
-    int bAddOGRStyleField = CSLTestBoolean(
+    bool bAddOGRStyleField = CPLTestBool(
         CSLFetchNameValueDef(papszOptions, "CREATE_OGR_STYLE_FIELD", "NO"));
-    int bClassicGML = CSLTestBoolean(
+    bool bClassicGML = CPLTestBool(
         CSLFetchNameValueDef(papszOptions, "CLASSIC_GML", "NO"));
     poLayer = new OGRJMLWriterLayer( pszLayerName, this, fp,
-                                          bAddRGBField, bAddOGRStyleField,
-                                          bClassicGML);
+                                     bAddRGBField, bAddOGRStyleField,
+                                     bClassicGML);
 
     return poLayer;
 }
@@ -205,45 +204,36 @@ OGRLayer * OGRJMLDataset::ICreateLayer( const char * pszLayerName,
 /*                         RegisterOGRJML()                             */
 /************************************************************************/
 
-extern "C"
-{
-
 void RegisterOGRJML()
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "JML" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "JML" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver  *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "JML" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "OpenJUMP JML" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jml" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_jml.html" );
+    poDriver->SetDescription( "JML" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "OpenJUMP JML" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jml" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_jml.html" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
 "<LayerCreationOptionList>"
 "   <Option name='CREATE_R_G_B_FIELD' type='boolean' description='Whether to create a R_G_B field' default='YES'/>"
 "   <Option name='CREATE_OGR_STYLE_FIELD' type='boolean' description='Whether to create a OGR_STYLE field' default='NO'/>"
 "</LayerCreationOptionList>" );
 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
-"<CreationOptionList/>"
-);
-        
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES, "Integer Integer64 Real String Date DateTime" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+                               "<CreationOptionList/>" );
 
-        poDriver->pfnOpen = OGRJMLDataset::Open;
-        poDriver->pfnIdentify = OGRJMLDataset::Identify;
-        poDriver->pfnCreate = OGRJMLDataset::Create;
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
+                               "Integer Integer64 Real String Date DateTime" );
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
-}
+    poDriver->pfnOpen = OGRJMLDataset::Open;
+    poDriver->pfnIdentify = OGRJMLDataset::Identify;
+    poDriver->pfnCreate = OGRJMLDataset::Create;
 
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/jml/ogrjmllayer.cpp b/ogr/ogrsf_frmts/jml/ogrjmllayer.cpp
index a4bd5ad..026bf15 100644
--- a/ogr/ogrsf_frmts/jml/ogrjmllayer.cpp
+++ b/ogr/ogrsf_frmts/jml/ogrjmllayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrjmllayer.cpp 27906 2014-10-24 18:38:57Z rouault $
+ * $Id: ogrjmllayer.cpp 33180 2016-01-28 10:13:57Z rouault $
  *
  * Project:  JML Translator
  * Purpose:  Implements OGRJMLLayer class.
@@ -26,11 +26,11 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_jml.h"
 #include "cpl_conv.h"
+#include "ogr_jml.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrjmllayer.cpp 27906 2014-10-24 18:38:57Z rouault $");
+CPL_CVSID("$Id: ogrjmllayer.cpp 33180 2016-01-28 10:13:57Z rouault $");
 
 #ifdef HAVE_EXPAT
 
@@ -39,49 +39,39 @@ CPL_CVSID("$Id: ogrjmllayer.cpp 27906 2014-10-24 18:38:57Z rouault $");
 /************************************************************************/
 
 OGRJMLLayer::OGRJMLLayer( const char* pszLayerName,
-                                    OGRJMLDataset* poDS,
-                                    VSILFILE* fp )
-
+                          OGRJMLDataset * /* poDSIn */,
+                          VSILFILE* fpIn ) :
+    poFeatureDefn(new OGRFeatureDefn( pszLayerName )),
+    nNextFID(0),
+    fp(fpIn),
+    bHasReadSchema(false),
+    oParser(NULL),
+    currentDepth(0),
+    bStopParsing(false),
+    nWithoutEventCounter(0),
+    nDataHandlerCounter(0),
+    bAccumulateElementValue(false),
+    pszElementValue(static_cast<char*>(CPLCalloc(1024, 1))),
+    nElementValueLen(0),
+    nElementValueAlloc(1024),
+    poFeature(NULL),
+    ppoFeatureTab(NULL),
+    nFeatureTabLength(0),
+    nFeatureTabIndex(0),
+    bSchemaFinished(false),
+    nJCSGMLInputTemplateDepth(0),
+    nCollectionElementDepth(0),
+    nFeatureElementDepth(0),
+    nGeometryElementDepth(0),
+    nColumnDepth(0),
+    nNameDepth(0),
+    nTypeDepth(0),
+    nAttributeElementDepth(0),
+    iAttr(-1),
+    iRGBField(-1)
 {
-    nNextFID = 0;
-
-    this->poDS = poDS;
-    this->fp = fp;
-
-    poFeatureDefn = new OGRFeatureDefn( pszLayerName );
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
-
-    bAccumulateElementValue = FALSE;
-    pszElementValue = (char*)CPLCalloc(1024, 1);
-    nElementValueLen = 0;
-    nElementValueAlloc = 1024;
-
-    ppoFeatureTab = NULL;
-    nFeatureTabIndex = 0;
-    nFeatureTabLength = 0;
-
-    nWithoutEventCounter = 0;
-    nDataHandlerCounter = 0;
-    currentDepth = 0;
-    bStopParsing = FALSE;
-    bHasReadSchema = FALSE;
-    
-    bSchemaFinished = FALSE;
-    nJCSGMLInputTemplateDepth = 0;
-    nCollectionElementDepth = 0;
-    nFeatureElementDepth = 0;
-    nGeometryElementDepth = 0;
-    nColumnDepth = 0;
-    nNameDepth = 0;
-    nTypeDepth = 0;
-    nAttributeElementDepth = 0;
-    iAttr = -1;
-    iRGBField = -1;
-
-    poFeature = NULL;
-
-    oParser = NULL;
 }
 
 /************************************************************************/
@@ -97,8 +87,7 @@ OGRJMLLayer::~OGRJMLLayer()
 
     CPLFree(pszElementValue);
 
-    int i;
-    for(i=nFeatureTabIndex;i<nFeatureTabLength;i++)
+    for( int i=nFeatureTabIndex; i<nFeatureTabLength; i++ )
         delete ppoFeatureTab[i];
     CPLFree(ppoFeatureTab);
 
@@ -122,17 +111,17 @@ OGRFeatureDefn * OGRJMLLayer::GetLayerDefn()
 static void XMLCALL startElementCbk(void *pUserData, const char *pszName,
                                     const char **ppszAttr)
 {
-    ((OGRJMLLayer*)pUserData)->startElementCbk(pszName, ppszAttr);
+    static_cast<OGRJMLLayer*>(pUserData)->startElementCbk(pszName, ppszAttr);
 }
 
 static void XMLCALL endElementCbk(void *pUserData, const char *pszName)
 {
-    ((OGRJMLLayer*)pUserData)->endElementCbk(pszName);
+    static_cast<OGRJMLLayer*>(pUserData)->endElementCbk(pszName);
 }
 
 static void XMLCALL dataHandlerCbk(void *pUserData, const char *data, int nLen)
 {
-    ((OGRJMLLayer*)pUserData)->dataHandlerCbk(data, nLen);
+    static_cast<OGRJMLLayer*>(pUserData)->dataHandlerCbk(data, nLen);
 }
 
 /************************************************************************/
@@ -153,8 +142,7 @@ void OGRJMLLayer::ResetReading()
     XML_SetCharacterDataHandler(oParser, ::dataHandlerCbk);
     XML_SetUserData(oParser, this);
 
-    int i;
-    for(i=nFeatureTabIndex;i<nFeatureTabLength;i++)
+    for( int i=nFeatureTabIndex; i<nFeatureTabLength; i++ )
         delete ppoFeatureTab[i];
     nFeatureTabIndex = 0;
     nFeatureTabLength = 0;
@@ -169,7 +157,7 @@ void OGRJMLLayer::ResetReading()
     nAttributeElementDepth = 0;
     iAttr = -1;
 
-    bAccumulateElementValue = FALSE;
+    bAccumulateElementValue = false;
     nElementValueLen = 0;
     pszElementValue[0] = '\0';
 }
@@ -183,12 +171,12 @@ void OGRJMLLayer::startElementCbk(const char *pszName, const char **ppszAttr)
     if (bStopParsing) return;
 
     nWithoutEventCounter = 0;
-    
+
     if( nFeatureElementDepth > 0 && nAttributeElementDepth == 0 &&
         nGeometryElementDepth == 0 && osGeometryElement.compare(pszName) == 0 )
     {
         nGeometryElementDepth = currentDepth;
-        bAccumulateElementValue = TRUE;
+        bAccumulateElementValue = true;
     }
     else if( nFeatureElementDepth > 0 && nAttributeElementDepth == 0 &&
              nGeometryElementDepth == 0 )
@@ -196,7 +184,7 @@ void OGRJMLLayer::startElementCbk(const char *pszName, const char **ppszAttr)
         /* We assume that attributes are present in the order they are */
         /* declared, so as a first guess, we can try the aoColumns[iAttr + 1] */
         int i = (iAttr+1 < poFeatureDefn->GetFieldCount()) ? -1 : 0;
-        for(; i<(int)aoColumns.size();i++)
+        for(; i< static_cast<int>(aoColumns.size()); i++ )
         {
             const OGRJMLColumn& oColumn =
                 (i < 0) ? aoColumns[iAttr + 1] : aoColumns[i];
@@ -212,7 +200,7 @@ void OGRJMLLayer::startElementCbk(const char *pszName, const char **ppszAttr)
                 {
                     /* <osElementName osAttributeName="osAttributeValue">value</osElementName> */
 
-                    bAccumulateElementValue = TRUE;
+                    bAccumulateElementValue = true;
                     nAttributeElementDepth = currentDepth;
                     iAttr = (i < 0) ? iAttr + 1 : i;
                     break;
@@ -221,7 +209,7 @@ void OGRJMLLayer::startElementCbk(const char *pszName, const char **ppszAttr)
                 {
                     /* <osElementName>value</osElementName> */
 
-                    bAccumulateElementValue = TRUE;
+                    bAccumulateElementValue = true;
                     nAttributeElementDepth = currentDepth;
                     iAttr = (i < 0) ? iAttr + 1 : i;
                     break;
@@ -233,7 +221,7 @@ void OGRJMLLayer::startElementCbk(const char *pszName, const char **ppszAttr)
             {
                 /* <osElementName osAttributeName="value"></osElementName> */
 
-                AddStringToElementValue(ppszAttr[1], strlen(ppszAttr[1]));
+                AddStringToElementValue(ppszAttr[1], (int)strlen(ppszAttr[1]));
 
                 nAttributeElementDepth = currentDepth;
                 iAttr = (i < 0) ? iAttr + 1 : i;
@@ -250,9 +238,9 @@ void OGRJMLLayer::startElementCbk(const char *pszName, const char **ppszAttr)
         while( papszIter && *papszIter != NULL )
         {
             AddStringToElementValue(" ", 1);
-            AddStringToElementValue(papszIter[0], strlen(papszIter[0]));
+            AddStringToElementValue(papszIter[0], (int)strlen(papszIter[0]));
             AddStringToElementValue("=\"", 2);
-            AddStringToElementValue(papszIter[1], strlen(papszIter[1]));
+            AddStringToElementValue(papszIter[1], (int)strlen(papszIter[1]));
             AddStringToElementValue("\"", 1);
             papszIter += 2;
         }
@@ -260,12 +248,14 @@ void OGRJMLLayer::startElementCbk(const char *pszName, const char **ppszAttr)
         AddStringToElementValue(">", 1);
     }
     else if( nCollectionElementDepth > 0 &&
-             nFeatureElementDepth == 0 && osFeatureElement.compare(pszName) == 0 )
+             nFeatureElementDepth == 0 &&
+             osFeatureElement.compare(pszName) == 0 )
     {
         nFeatureElementDepth = currentDepth;
         poFeature = new OGRFeature(poFeatureDefn);
     }
-    else if( nCollectionElementDepth == 0 && osCollectionElement.compare(pszName) == 0 )
+    else if( nCollectionElementDepth == 0 &&
+             osCollectionElement.compare(pszName) == 0 )
     {
         nCollectionElementDepth = currentDepth;
     }
@@ -279,7 +269,7 @@ void OGRJMLLayer::startElementCbk(const char *pszName, const char **ppszAttr)
 
 void OGRJMLLayer::StopAccumulate()
 {
-    bAccumulateElementValue = FALSE;
+    bAccumulateElementValue = false;
     nElementValueLen = 0;
     pszElementValue[0] = '\0';
 }
@@ -293,9 +283,9 @@ void OGRJMLLayer::endElementCbk(const char *pszName)
     if (bStopParsing) return;
 
     nWithoutEventCounter = 0;
-    
+
     currentDepth--;
-    
+
     if( nAttributeElementDepth == currentDepth )
     {
         if( nElementValueLen )
@@ -306,14 +296,15 @@ void OGRJMLLayer::endElementCbk(const char *pszName)
     else if( nGeometryElementDepth > 0 && currentDepth > nGeometryElementDepth )
     {
         AddStringToElementValue("</", 2);
-        AddStringToElementValue(pszName, (int)strlen(pszName));
+        AddStringToElementValue(pszName, static_cast<int>(strlen(pszName)));
         AddStringToElementValue(">", 1);
     }
     else if( nGeometryElementDepth == currentDepth )
     {
         if( nElementValueLen )
         {
-            OGRGeometry* poGeom = (OGRGeometry* )OGR_G_CreateFromGML(pszElementValue);
+            OGRGeometry* poGeom = reinterpret_cast<OGRGeometry *>(
+                OGR_G_CreateFromGML(pszElementValue) );
             if( poGeom != NULL &&
                 poGeom->getGeometryType() == wkbGeometryCollection &&
                 poGeom->IsEmpty() )
@@ -332,21 +323,26 @@ void OGRJMLLayer::endElementCbk(const char *pszName)
         /* Builds a style string from R_G_B if we don't already have a */
         /* style string */
         OGRGeometry* poGeom = poFeature->GetGeometryRef();
-        int R, G, B;
+        int R;
+        int G;
+        int B;
         if( iRGBField >= 0 && poFeature->IsFieldSet(iRGBField) &&
             poFeature->GetStyleString() == NULL && poGeom != NULL &&
             sscanf(poFeature->GetFieldAsString(iRGBField),
                        "%02X%02X%02X", &R, &G, &B) == 3 )
         {
-            OGRwkbGeometryType eGeomType = wkbFlatten(poGeom->getGeometryType());
+            const OGRwkbGeometryType eGeomType
+                = wkbFlatten(poGeom->getGeometryType());
             if( eGeomType == wkbPoint || eGeomType == wkbMultiPoint ||
                 eGeomType == wkbLineString || eGeomType == wkbMultiLineString )
             {
-                poFeature->SetStyleString(CPLSPrintf("PEN(c:#%02X%02X%02X)", R, G, B));
+                poFeature->SetStyleString(
+                    CPLSPrintf("PEN(c:#%02X%02X%02X)", R, G, B));
             }
             else if( eGeomType == wkbPolygon || eGeomType == wkbMultiPolygon )
             {
-                poFeature->SetStyleString(CPLSPrintf("BRUSH(fc:#%02X%02X%02X)", R, G, B));
+                poFeature->SetStyleString(
+                    CPLSPrintf("BRUSH(fc:#%02X%02X%02X)", R, G, B));
             }
         }
 
@@ -357,9 +353,9 @@ void OGRJMLLayer::endElementCbk(const char *pszName)
             && (m_poAttrQuery == NULL
                 || m_poAttrQuery->Evaluate( poFeature )) )
         {
-            ppoFeatureTab = (OGRFeature**)
-                    CPLRealloc(ppoFeatureTab,
-                                sizeof(OGRFeature*) * (nFeatureTabLength + 1));
+            ppoFeatureTab = static_cast<OGRFeature**>(
+                CPLRealloc(ppoFeatureTab,
+                           sizeof(OGRFeature*) * (nFeatureTabLength + 1)) );
             ppoFeatureTab[nFeatureTabLength] = poFeature;
             nFeatureTabLength++;
         }
@@ -384,15 +380,23 @@ void OGRJMLLayer::endElementCbk(const char *pszName)
 
 void OGRJMLLayer::AddStringToElementValue(const char *data, int nLen)
 {
+    if( nLen > INT_MAX - nElementValueLen - 1 - 1000 )
+    {
+        CPLError(CE_Failure, CPLE_OutOfMemory,
+                 "Too much data in a single element");
+        XML_StopParser(oParser, XML_FALSE);
+        bStopParsing = true;
+        return;
+    }
     if( nElementValueLen + nLen + 1 > nElementValueAlloc )
     {
-        char* pszNewElementValue = (char*) VSIRealloc(pszElementValue,
-                                        nElementValueLen + nLen + 1 + 1000);
+        char* pszNewElementValue = static_cast<char*>(
+            VSI_REALLOC_VERBOSE( pszElementValue,
+                                 nElementValueLen + nLen + 1 + 1000) );
         if (pszNewElementValue == NULL)
         {
-            CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
             XML_StopParser(oParser, XML_FALSE);
-            bStopParsing = TRUE;
+            bStopParsing = true;
             return;
         }
         nElementValueAlloc =  nElementValueLen + nLen + 1 + 1000;
@@ -401,13 +405,6 @@ void OGRJMLLayer::AddStringToElementValue(const char *data, int nLen)
     memcpy(pszElementValue + nElementValueLen, data, nLen);
     nElementValueLen += nLen;
     pszElementValue[nElementValueLen] = '\0';
-    if (nElementValueLen > 10000000)
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                    "Too much data inside one element. File probably corrupted");
-        XML_StopParser(oParser, XML_FALSE);
-        bStopParsing = TRUE;
-    }
 }
 
 /************************************************************************/
@@ -424,12 +421,12 @@ void OGRJMLLayer::dataHandlerCbk(const char *data, int nLen)
         CPLError(CE_Failure, CPLE_AppDefined,
                  "File probably corrupted (million laugh pattern)");
         XML_StopParser(oParser, XML_FALSE);
-        bStopParsing = TRUE;
+        bStopParsing = true;
         return;
     }
 
     nWithoutEventCounter = 0;
-    
+
     if (bAccumulateElementValue)
     {
         AddStringToElementValue(data, nLen);
@@ -452,15 +449,15 @@ OGRFeature *OGRJMLLayer::GetNextFeature()
     {
         return ppoFeatureTab[nFeatureTabIndex++];
     }
-    
+
     if (VSIFEofL(fp))
         return NULL;
-    
+
     char aBuf[BUFSIZ];
-    
+
     nFeatureTabLength = 0;
     nFeatureTabIndex = 0;
-    
+
     nWithoutEventCounter = 0;
 
     int nDone;
@@ -478,7 +475,7 @@ OGRFeature *OGRJMLLayer::GetNextFeature()
                      XML_ErrorString(XML_GetErrorCode(oParser)),
                      (int)XML_GetCurrentLineNumber(oParser),
                      (int)XML_GetCurrentColumnNumber(oParser));
-            bStopParsing = TRUE;
+            bStopParsing = true;
         }
         nWithoutEventCounter ++;
     } while (!nDone && !bStopParsing && nFeatureTabLength == 0 &&
@@ -486,23 +483,26 @@ OGRFeature *OGRJMLLayer::GetNextFeature()
 
     if (nWithoutEventCounter == 10)
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Too much data inside one element. File probably corrupted");
-        bStopParsing = TRUE;
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Too much data inside one element. File probably corrupted");
+        bStopParsing = true;
     }
 
     return (nFeatureTabLength) ? ppoFeatureTab[nFeatureTabIndex++] : NULL;
 }
 
-static void XMLCALL startElementLoadSchemaCbk(void *pUserData, const char *pszName,
-                                              const char **ppszAttr)
+static void XMLCALL startElementLoadSchemaCbk( void *pUserData,
+                                               const char *pszName,
+                                               const char **ppszAttr )
 {
-    ((OGRJMLLayer*)pUserData)->startElementLoadSchemaCbk(pszName, ppszAttr);
+    static_cast<OGRJMLLayer*>(pUserData)->
+        startElementLoadSchemaCbk(pszName, ppszAttr);
 }
 
-static void XMLCALL endElementLoadSchemaCbk(void *pUserData, const char *pszName)
+static void XMLCALL endElementLoadSchemaCbk( void *pUserData,
+                                             const char *pszName )
 {
-    ((OGRJMLLayer*)pUserData)->endElementLoadSchemaCbk(pszName);
+    static_cast<OGRJMLLayer*>(pUserData)->endElementLoadSchemaCbk(pszName);
 }
 
 /************************************************************************/
@@ -515,7 +515,7 @@ void OGRJMLLayer::LoadSchema()
     if (bHasReadSchema)
         return;
 
-    bHasReadSchema = TRUE;
+    bHasReadSchema = true;
 
     oParser = OGRCreateExpatXMLParser();
     XML_SetElementHandler(oParser, ::startElementLoadSchemaCbk,
@@ -530,19 +530,22 @@ void OGRJMLLayer::LoadSchema()
     do
     {
         nDataHandlerCounter = 0;
-        unsigned int nLen = (unsigned int)VSIFReadL( aBuf, 1, sizeof(aBuf), fp );
+        const unsigned int nLen = static_cast<unsigned int>(
+            VSIFReadL( aBuf, 1, sizeof(aBuf), fp ) );
         nDone = VSIFEofL(fp);
         if (XML_Parse(oParser, aBuf, nLen, nDone) == XML_STATUS_ERROR)
         {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "XML parsing of JML file failed : %s at line %d, column %d",
-                     XML_ErrorString(XML_GetErrorCode(oParser)),
-                     (int)XML_GetCurrentLineNumber(oParser),
-                     (int)XML_GetCurrentColumnNumber(oParser));
-            bStopParsing = TRUE;
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "XML parsing of JML file failed : %s at line %d, "
+                      "column %d",
+                      XML_ErrorString(XML_GetErrorCode(oParser)),
+                      static_cast<int>(XML_GetCurrentLineNumber(oParser)),
+                      static_cast<int>(XML_GetCurrentColumnNumber(oParser)) );
+            bStopParsing = true;
         }
         nWithoutEventCounter ++;
-    } while (!nDone && !bStopParsing && !bSchemaFinished && nWithoutEventCounter < 10);
+    } while ( !nDone && !bStopParsing && !bSchemaFinished &&
+              nWithoutEventCounter < 10 );
 
     XML_ParserFree(oParser);
     oParser = NULL;
@@ -551,15 +554,16 @@ void OGRJMLLayer::LoadSchema()
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Too much data inside one element. File probably corrupted");
-        bStopParsing = TRUE;
+        bStopParsing = true;
     }
-    
+
     if( osCollectionElement.size() == 0 || osFeatureElement.size() == 0 ||
         osGeometryElement.size() == 0 )
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Missing CollectionElement, FeatureElement or GeometryElement");
-        bStopParsing = TRUE;
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Missing CollectionElement, FeatureElement or "
+                  "GeometryElement" );
+        bStopParsing = true;
     }
 
     ResetReading();
@@ -570,8 +574,8 @@ void OGRJMLLayer::LoadSchema()
 /*                  startElementLoadSchemaCbk()                         */
 /************************************************************************/
 
-void OGRJMLLayer::startElementLoadSchemaCbk(const char *pszName,
-                                                 const char **ppszAttr)
+void OGRJMLLayer::startElementLoadSchemaCbk( const char *pszName,
+                                             const char **ppszAttr )
 {
     if (bStopParsing) return;
 
@@ -586,19 +590,19 @@ void OGRJMLLayer::startElementLoadSchemaCbk(const char *pszName,
             strcmp(pszName, "CollectionElement") == 0 )
         {
             nCollectionElementDepth = currentDepth;
-            bAccumulateElementValue = TRUE;
+            bAccumulateElementValue = true;
         }
         else if( nFeatureElementDepth == 0 &&
                 strcmp(pszName, "FeatureElement") == 0 )
         {
             nFeatureElementDepth = currentDepth;
-            bAccumulateElementValue = TRUE;
+            bAccumulateElementValue = true;
         }
         else if( nGeometryElementDepth == 0 &&
                  strcmp(pszName, "GeometryElement") == 0 )
         {
             nGeometryElementDepth = currentDepth;
-            bAccumulateElementValue = TRUE;
+            bAccumulateElementValue = true;
         }
         else  if( nColumnDepth == 0 && strcmp(pszName, "column") == 0 )
         {
@@ -608,19 +612,19 @@ void OGRJMLLayer::startElementLoadSchemaCbk(const char *pszName,
             oCurColumn.osElementName = "";
             oCurColumn.osAttributeName = "";
             oCurColumn.osAttributeValue = "";
-            oCurColumn.bIsBody = FALSE;
+            oCurColumn.bIsBody = false;
         }
         else if( nColumnDepth > 0 )
         {
             if( nNameDepth == 0 && strcmp(pszName, "name") == 0 )
             {
                 nNameDepth = currentDepth;
-                bAccumulateElementValue = TRUE;
+                bAccumulateElementValue = true;
             }
             else if( nTypeDepth == 0 && strcmp(pszName, "type") == 0 )
             {
                 nTypeDepth = currentDepth;
-                bAccumulateElementValue = TRUE;
+                bAccumulateElementValue = true;
             }
             else if( strcmp(pszName, "valueElement") == 0 )
             {
@@ -658,7 +662,7 @@ void OGRJMLLayer::startElementLoadSchemaCbk(const char *pszName,
 /*                   endElementLoadSchemaCbk()                          */
 /************************************************************************/
 
-void OGRJMLLayer::endElementLoadSchemaCbk(CPL_UNUSED const char *pszName)
+void OGRJMLLayer::endElementLoadSchemaCbk( const char * /* pszName */ )
 {
     if (bStopParsing) return;
 
@@ -669,46 +673,53 @@ void OGRJMLLayer::endElementLoadSchemaCbk(CPL_UNUSED const char *pszName)
     if( nJCSGMLInputTemplateDepth == currentDepth )
     {
         nJCSGMLInputTemplateDepth = 0;
-        bSchemaFinished = TRUE;
+        bSchemaFinished = true;
     }
     else if( nCollectionElementDepth == currentDepth )
     {
         nCollectionElementDepth = 0;
         osCollectionElement = pszElementValue;
-        //CPLDebug("JML", "osCollectionElement = %s", osCollectionElement.c_str());
+#ifdef DEBUG_VERBOSE
+        CPLDebug( "JML", "osCollectionElement = %s",
+                  osCollectionElement.c_str() );
+#endif
         StopAccumulate();
     }
     else if( nFeatureElementDepth == currentDepth )
     {
         nFeatureElementDepth = 0;
         osFeatureElement = pszElementValue;
-        //CPLDebug("JML", "osFeatureElement = %s", osFeatureElement.c_str());
+#ifdef DEBUG_VERBOSE
+        CPLDebug( "JML", "osFeatureElement = %s", osFeatureElement.c_str() );
+#endif
         StopAccumulate();
     }
     else if( nGeometryElementDepth == currentDepth )
     {
         nGeometryElementDepth = 0;
         osGeometryElement = pszElementValue;
-        //CPLDebug("JML", "osGeometryElement = %s", osGeometryElement.c_str());
+#ifdef DEBUG_VERBOSE
+        CPLDebug( "JML", "osGeometryElement = %s", osGeometryElement.c_str() );
+#endif
         StopAccumulate();
     }
     else if( nColumnDepth == currentDepth )
     {
-        int bIsOK = TRUE;
+        bool bIsOK = true;
         if( oCurColumn.osName.size() == 0 )
-            bIsOK = FALSE;
+            bIsOK = false;
         if( oCurColumn.osType.size() == 0 )
-            bIsOK = FALSE;
+            bIsOK = false;
         if( oCurColumn.osElementName.size() == 0 )
-            bIsOK = FALSE;
+            bIsOK = false;
         if( oCurColumn.bIsBody )
         {
             if( oCurColumn.osAttributeName.size() == 0 &&
                 oCurColumn.osAttributeValue.size() != 0 )
-                bIsOK = FALSE;
+                bIsOK = false;
             if( oCurColumn.osAttributeName.size() != 0 &&
                 oCurColumn.osAttributeValue.size() == 0 )
-                bIsOK = FALSE;
+                bIsOK = false;
             /* Only 2 valid possibilities : */
             /* <osElementName osAttributeName="osAttributeValue">value</osElementName> */
             /* <osElementName>value</osElementName> */
@@ -717,11 +728,11 @@ void OGRJMLLayer::endElementLoadSchemaCbk(CPL_UNUSED const char *pszName)
         {
             /* <osElementName osAttributeName="value"></osElementName> */
             if( oCurColumn.osAttributeName.size() == 0 )
-                bIsOK = FALSE;
+                bIsOK = false;
             if( oCurColumn.osAttributeValue.size() != 0 )
-                bIsOK = FALSE;
+                bIsOK = false;
         }
-        
+
         if( bIsOK )
         {
             OGRFieldType eType = OFTString;
@@ -741,14 +752,15 @@ void OGRJMLLayer::endElementLoadSchemaCbk(CPL_UNUSED const char *pszName)
         }
         else
         {
-            CPLDebug("JML", "Invalid column definition: name = %s, type = %s, "
-                    "elementName = %s, attributeName = %s, attributeValue = %s, bIsBody = %d", 
-                    oCurColumn.osName.c_str(),
-                    oCurColumn.osType.c_str(), 
-                    oCurColumn.osElementName.c_str(),
-                    oCurColumn.osAttributeName.c_str(), 
-                    oCurColumn.osAttributeValue.c_str(),
-                    oCurColumn.bIsBody);
+            CPLDebug( "JML", "Invalid column definition: name = %s, type = %s, "
+                      "elementName = %s, attributeName = %s, "
+                      "attributeValue = %s, bIsBody = %d",
+                      oCurColumn.osName.c_str(),
+                      oCurColumn.osType.c_str(),
+                      oCurColumn.osElementName.c_str(),
+                      oCurColumn.osAttributeName.c_str(),
+                      oCurColumn.osAttributeValue.c_str(),
+                      static_cast<int>(oCurColumn.bIsBody) );
         }
 
         nColumnDepth = 0;
@@ -757,14 +769,18 @@ void OGRJMLLayer::endElementLoadSchemaCbk(CPL_UNUSED const char *pszName)
     {
         nNameDepth = 0;
         oCurColumn.osName = pszElementValue;
-        //CPLDebug("JML", "oCurColumn.osName = %s", oCurColumn.osName.c_str());
+#ifdef DEBUG_VERBOSE
+        CPLDebug("JML", "oCurColumn.osName = %s", oCurColumn.osName.c_str());
+#endif
         StopAccumulate();
     }
     else if( nTypeDepth == currentDepth )
     {
         nTypeDepth = 0;
         oCurColumn.osType = pszElementValue;
-        //CPLDebug("JML", "oCurColumn.osType = %s", oCurColumn.osType.c_str());
+#ifdef DEBUG_VERBOSE
+        CPLDebug("JML", "oCurColumn.osType = %s", oCurColumn.osType.c_str());
+#endif
         StopAccumulate();
     }
 }
@@ -776,10 +792,7 @@ void OGRJMLLayer::endElementLoadSchemaCbk(CPL_UNUSED const char *pszName)
 int OGRJMLLayer::TestCapability( const char * pszCap )
 
 {
-    if( EQUAL(pszCap,OLCStringsAsUTF8) )
-        return TRUE;
-    else 
-        return FALSE;
+    return EQUAL(pszCap,OLCStringsAsUTF8);
 }
 
 #endif /* HAVE_EXPAT */
diff --git a/ogr/ogrsf_frmts/jml/ogrjmlwriterlayer.cpp b/ogr/ogrsf_frmts/jml/ogrjmlwriterlayer.cpp
index 984a6b4..5f270db 100644
--- a/ogr/ogrsf_frmts/jml/ogrjmlwriterlayer.cpp
+++ b/ogr/ogrsf_frmts/jml/ogrjmlwriterlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrjmlwriterlayer.cpp 28900 2015-04-14 09:40:34Z rouault $
+ * $Id: ogrjmlwriterlayer.cpp 32783 2016-01-06 16:11:09Z goatbar $
  *
  * Project:  JML Translator
  * Purpose:  Implements OGRJMLWriterLayer class.
@@ -30,32 +30,29 @@
 #include "cpl_conv.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrjmlwriterlayer.cpp 28900 2015-04-14 09:40:34Z rouault $");
+CPL_CVSID("$Id: ogrjmlwriterlayer.cpp 32783 2016-01-06 16:11:09Z goatbar $");
 
 /************************************************************************/
 /*                           OGRJMLWriterLayer()                        */
 /************************************************************************/
 
 OGRJMLWriterLayer::OGRJMLWriterLayer( const char* pszLayerName,
-                                                OGRJMLDataset* poDS,
-                                                VSILFILE* fp,
-                                                int bAddRGBField,
-                                                int bAddOGRStyleField,
-                                                int bClassicGML )
-
+                                      OGRJMLDataset * /* poDSIn */,
+                                      VSILFILE* fpIn,
+                                      bool bAddRGBFieldIn,
+                                      bool bAddOGRStyleFieldIn,
+                                      bool bClassicGMLIn ) :
+    poFeatureDefn(new OGRFeatureDefn( pszLayerName )),
+    fp(fpIn),
+    bFeaturesWritten(false),
+    bAddRGBField(bAddRGBFieldIn),
+    bAddOGRStyleField(bAddOGRStyleFieldIn),
+    bClassicGML(bClassicGMLIn),
+    nNextFID(0)
 {
-    this->poDS = poDS;
-    this->fp = fp;
-    bFeaturesWritten = FALSE;
-    this->bAddRGBField = bAddRGBField;
-    this->bAddOGRStyleField = bAddOGRStyleField;
-    this->bClassicGML = bClassicGML;
-    nNextFID = 0;
-
-    poFeatureDefn = new OGRFeatureDefn( pszLayerName );
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
-    
+
     VSIFPrintfL(fp, "<?xml version='1.0' encoding='UTF-8'?>\n"
                     "<JCSDataFile xmlns:gml=\"http://www.opengis.net/gml\" "
                     "xmlns:xsi=\"http://www.w3.org/2000/10/XMLSchema-instance\" >\n"
@@ -74,7 +71,9 @@ OGRJMLWriterLayer::OGRJMLWriterLayer( const char* pszLayerName,
 OGRJMLWriterLayer::~OGRJMLWriterLayer()
 {
     if( !bFeaturesWritten )
-        VSIFPrintfL(fp, "</ColumnDefinitions>\n</JCSGMLInputTemplate>\n<featureCollection>\n");
+        VSIFPrintfL(
+            fp, "</ColumnDefinitions>\n</JCSGMLInputTemplate>\n"
+            "<featureCollection>\n" );
     VSIFPrintfL(fp, "</featureCollection>\n</JCSDataFile>\n");
     poFeatureDefn->Release();
 }
@@ -128,8 +127,9 @@ OGRErr OGRJMLWriterLayer::ICreateFeature( OGRFeature *poFeature )
         {
             WriteColumnDeclaration( "R_G_B", "STRING" );
         }
-        VSIFPrintfL(fp, "</ColumnDefinitions>\n</JCSGMLInputTemplate>\n<featureCollection>\n");
-        bFeaturesWritten = TRUE;
+        VSIFPrintfL( fp, "</ColumnDefinitions>\n</JCSGMLInputTemplate>\n"
+                     "<featureCollection>\n" );
+        bFeaturesWritten = true;
     }
 
     if( bClassicGML )
@@ -163,7 +163,7 @@ OGRErr OGRJMLWriterLayer::ICreateFeature( OGRFeature *poFeature )
             VSIFPrintfL(fp, "          <property name=\"%s\">", pszName);
         if( poFeature->IsFieldSet(i) )
         {
-            OGRFieldType eType = poFeatureDefn->GetFieldDefn(i)->GetType();
+            const OGRFieldType eType = poFeatureDefn->GetFieldDefn(i)->GetType();
             if( eType == OFTString )
             {
                 char* pszValue = OGRGetXML_UTF8_EscapedString(
@@ -173,10 +173,15 @@ OGRErr OGRJMLWriterLayer::ICreateFeature( OGRFeature *poFeature )
             }
             else if( eType == OFTDateTime )
             {
-                int nYear, nMonth, nDay, nHour, nMinute, nTZFlag;
+                int nYear;
+                int nMonth;
+                int nDay;
+                int nHour;
+                int nMinute;
+                int nTZFlag;
                 float fSecond;
                 poFeature->GetFieldAsDateTime(i, &nYear, &nMonth, &nDay,
-                                            &nHour, &nMinute, &fSecond, &nTZFlag);
+                                              &nHour, &nMinute, &fSecond, &nTZFlag);
                 /* When writing time zone, OpenJUMP expects .XXX seconds */
                 /* to be written */
                 if( nTZFlag > 1 || OGR_GET_MS(fSecond) != 0 )
@@ -234,7 +239,7 @@ OGRErr OGRJMLWriterLayer::ICreateFeature( OGRFeature *poFeature )
         else
             VSIFPrintfL(fp, "</property>\n");
     }
-    
+
     /* Derive R_G_B field from feature style string */
     if( bAddRGBField && poFeatureDefn->GetFieldIndex("R_G_B") < 0 )
     {
@@ -244,7 +249,6 @@ OGRErr OGRJMLWriterLayer::ICreateFeature( OGRFeature *poFeature )
             VSIFPrintfL(fp, "          <property name=\"%s\">", "R_G_B");
         if( poFeature->GetStyleString() != NULL )
         {
-            OGRGeometry* poGeom = poFeature->GetGeometryRef();
             OGRwkbGeometryType eGeomType =
                 poGeom ? wkbFlatten(poGeom->getGeometryType()) : wkbUnknown;
             OGRStyleMgr oMgr;
@@ -302,7 +306,7 @@ OGRErr OGRJMLWriterLayer::CreateField( OGRFieldDefn *poFieldDefn,
 {
     if( bFeaturesWritten )
         return OGRERR_FAILURE;
-    
+
     if( !bAddRGBField && strcmp( poFieldDefn->GetNameRef(), "R_G_B" ) == 0 )
         return OGRERR_FAILURE;
 
@@ -351,10 +355,10 @@ int OGRJMLWriterLayer::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,OLCStringsAsUTF8) )
         return TRUE;
-    else if( EQUAL(pszCap,OLCSequentialWrite) )
+    if( EQUAL(pszCap,OLCSequentialWrite) )
         return TRUE;
-    else if( EQUAL(pszCap,OLCCreateField) )
+    if( EQUAL(pszCap,OLCCreateField) )
         return !bFeaturesWritten;
-    else 
-        return FALSE;
+
+    return FALSE;
 }
diff --git a/ogr/ogrsf_frmts/kml/drv_kml.html b/ogr/ogrsf_frmts/kml/drv_kml.html
index e50b070..f43fa8e 100644
--- a/ogr/ogrsf_frmts/kml/drv_kml.html
+++ b/ogr/ogrsf_frmts/kml/drv_kml.html
@@ -7,11 +7,11 @@
 
 <h1>KML - Keyhole Markup Language</h1>
 
-<p>Keyhole Markup Language (KML) is an XML-based language for managing the display of 3D geospatial data. 
+<p>Keyhole Markup Language (KML) is an XML-based language for managing the display of 3D geospatial data.
 KML has been accepted as an OGC standard, and is supported in one way or another
-on the major GeoBrowsers. 
-Note that KML by specification uses only a single projection, EPSG:4326. All OGR KML output will be 
-presented in EPSG:4326. As such OGR will create layers in the correct coordinate system and transform 
+on the major GeoBrowsers.
+Note that KML by specification uses only a single projection, EPSG:4326. All OGR KML output will be
+presented in EPSG:4326. As such OGR will create layers in the correct coordinate system and transform
 any geometries.</p>
 
 <p>At this time, only vector layers are handled by the KML driver. <em>(there are additional scripts
@@ -23,7 +23,7 @@ supplied with the GDAL project that can build other kinds of output)</em></p>
 <p>  Supported geometry types are <code>Point</code>, <code>Linestring</code>, <code>Polygon</code>, <code>MultiPoint</code>,
 <code>MultiLineString</code>, <code>MultiPolygon</code> and <code>MultiGeometry</code>. There are limitations,
 for example: the nested nature of folders in a source KML file is lost; folder <code><description></code> tags will
-not carry through to ouput. Since GDAL 1.6.1, folders containing multiple geometry types, like POINT and POLYGON, are supported.</p>
+not carry through to output. Since GDAL 1.6.1, folders containing multiple geometry types, like POINT and POLYGON, are supported.</p>
 
 <h3>KML Writing</h3>
 <p>Since not all features of KML
@@ -41,7 +41,7 @@ it considers valid, for example '<code>Layer #0</code>', the default name of the
 Layer, becomes <code>'Layer__0'</code>.</p>
 
 
-<p>KML is mix of formatting and feature data. The <description> tag of a Placemark will 
+<p>KML is mix of formatting and feature data. The <description> tag of a Placemark will
 be displayed in most geobrowsers as an HTML-filled balloon. When writing KML, Layer element
 attributes are added as simple schema fields. This best preserves feature type information.</p>
 <p>Limited support is available for fills, line color and other styling attributes. Please try a few sample
@@ -58,10 +58,10 @@ Expat library supports reading the following built-in encodings :
 </ul>
 
 OGR 1.8.0 adds supports for Windows-1252 encoding (for previous versions, altering the encoding
-mentionned in the XML header to ISO-8859-1 might work in some cases).<p>
+mentioned in the XML header to ISO-8859-1 might work in some cases).<p>
 
 The content returned by OGR will be encoded in UTF-8, after the conversion from the
-encoding mentionned in the file header is.<p>
+encoding mentioned in the file header is.<p>
 
 If your KML file is not encoded in one of the previous encodings, it will not be parsed by the
 KML driver. You may convert it into one of the supported encoding with the <i>iconv</i> utility
@@ -77,12 +77,12 @@ When writing a KML file, the driver expects UTF-8 content to be passed in.<p>
 <pre>ogr2ogr -f KML output.kml input.shp -dsco NameField=RegionName</pre>
 <li><b>DescriptionField</b>: Allows you to specify the field to use for the KML <description> element. Default value : 'Description'</li>
 </li>
-<li><b>AltitudeMode</b>: Allows you to specify the AltitudeMode to use for KML geometries. This will only affect 3D geometries   
-and must be one of the valid KML options.  
-See the <a href="http://code.google.com/apis/kml/documentation/kml_tags_21.html#altitudemode">relevant KML reference material</a>  
-for further information. 
+<li><b>AltitudeMode</b>: Allows you to specify the AltitudeMode to use for KML geometries. This will only affect 3D geometries
+and must be one of the valid KML options.
+See the <a href="http://code.google.com/apis/kml/documentation/kml_tags_21.html#altitudemode">relevant KML reference material</a>
+for further information.
 <pre>ogr2ogr -f KML output.kml input.shp -dsco AltitudeMode=absolute</pre>
-</li>  
+</li>
 </ul>
 
 
diff --git a/ogr/ogrsf_frmts/kml/kml.cpp b/ogr/ogrsf_frmts/kml/kml.cpp
index aefaa0f..7226a8b 100644
--- a/ogr/ogrsf_frmts/kml/kml.cpp
+++ b/ogr/ogrsf_frmts/kml/kml.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: kml.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: kml.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  KML Driver
  * Purpose:  Class for reading, parsing and handling a kmlfile.
@@ -32,22 +32,23 @@
 #include "cpl_error.h"
 #include "cpl_conv.h"
 // std
-#include <cstdio>
 #include <cerrno>
-#include <string>
+#include <cstdio>
 #include <iostream>
+#include <string>
 
-KML::KML()
-{
-	nDepth_ = 0;
-	validity = KML_VALIDITY_UNKNOWN;
-	pKMLFile_ = NULL;
-	sError_ = "";
-	poTrunk_ = NULL;
-	poCurrent_ = NULL;
-	nNumLayers_ = -1;
-        papoLayers_ = NULL;
-}
+KML::KML() :
+    poTrunk_(NULL),
+    nNumLayers_(-1),
+    papoLayers_(NULL),
+    nDepth_(0),
+    validity(KML_VALIDITY_UNKNOWN),
+    pKMLFile_(NULL),
+    poCurrent_(NULL),
+    oCurrentParser(NULL),
+    nDataHandlerCounter(0),
+    nWithoutEventCounter(0)
+{ }
 
 KML::~KML()
 {
@@ -64,18 +65,13 @@ bool KML::open(const char * pszFilename)
         VSIFCloseL( pKMLFile_ );
 
     pKMLFile_ = VSIFOpenL( pszFilename, "r" );
-    if( NULL == pKMLFile_ )
-    {
-        return FALSE;
-    }
-
-    return TRUE;
+    return pKMLFile_ != NULL;
 }
 
 void KML::parse()
 {
-    std::size_t nDone = 0;
-    std::size_t nLen = 0;
+    int nDone = 0;
+    int nLen = 0;
     char aBuf[BUFSIZ] = { 0 };
 
     if( NULL == pKMLFile_ )
@@ -109,11 +105,12 @@ void KML::parse()
         nDone = VSIFEofL(pKMLFile_);
         if (XML_Parse(oParser, aBuf, nLen, nDone) == XML_STATUS_ERROR)
         {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                        "XML parsing of KML file failed : %s at line %d, column %d",
-                        XML_ErrorString(XML_GetErrorCode(oParser)),
-                        (int)XML_GetCurrentLineNumber(oParser),
-                        (int)XML_GetCurrentColumnNumber(oParser));
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "XML parsing of KML file failed : %s at line %d, "
+                      "column %d",
+                      XML_ErrorString(XML_GetErrorCode(oParser)),
+                      static_cast<int>(XML_GetCurrentLineNumber(oParser)),
+                      static_cast<int>(XML_GetCurrentColumnNumber(oParser)));
             XML_ParserFree(oParser);
             VSIRewindL(pKMLFile_);
             return;
@@ -134,8 +131,8 @@ void KML::parse()
 
 void KML::checkValidity()
 {
-    std::size_t nDone = 0;
-    std::size_t nLen = 0;
+    int nDone = 0;
+    int nLen = 0;
     char aBuf[BUFSIZ] = { 0 };
 
     if(poTrunk_ != NULL)
@@ -152,7 +149,7 @@ void KML::checkValidity()
 
     if(pKMLFile_ == NULL)
     {
-        this->sError_ = "No file given";
+        sError_ = "No file given";
         return;
     }
 
@@ -168,7 +165,7 @@ void KML::checkValidity()
     do
     {
         nDataHandlerCounter = 0;
-        nLen = (int)VSIFReadL( aBuf, 1, sizeof(aBuf), pKMLFile_ );
+        nLen = static_cast<int>(VSIFReadL( aBuf, 1, sizeof(aBuf), pKMLFile_ ));
         nDone = VSIFEofL(pKMLFile_);
         if (XML_Parse(oParser, aBuf, nLen, nDone) == XML_STATUS_ERROR)
         {
@@ -196,24 +193,24 @@ void KML::checkValidity()
         nCount ++;
         /* After reading 50 * BUFSIZE bytes, and not finding whether the file */
         /* is KML or not, we give up and fail silently */
-    } while (!nDone && nLen > 0 && validity == KML_VALIDITY_UNKNOWN && nCount < 50);
+    } while ( !nDone && nLen > 0 &&
+              validity == KML_VALIDITY_UNKNOWN && nCount < 50 );
 
     XML_ParserFree(oParser);
     VSIRewindL(pKMLFile_);
     poCurrent_ = NULL;
 }
 
-void XMLCALL KML::startElement(void* pUserData, const char* pszName, const char** ppszAttr)
+void XMLCALL KML::startElement( void* pUserData, const char* pszName,
+                                const char** ppszAttr )
 {
-    int i = 0;
     KMLNode* poMynew = NULL;
-    Attribute* poAtt = NULL;
 
-    KML* poKML = (KML*) pUserData;
+    KML* poKML = static_cast<KML*>(pUserData);
 
     poKML->nWithoutEventCounter = 0;
 
-    if(poKML->poTrunk_ == NULL 
+    if(poKML->poTrunk_ == NULL
     || (poKML->poCurrent_->getName()).compare("description") != 0)
     {
         if (poKML->nDepth_ == 1024)
@@ -229,9 +226,9 @@ void XMLCALL KML::startElement(void* pUserData, const char* pszName, const char*
             poMynew->setName(pszName);
         poMynew->setLevel(poKML->nDepth_);
 
-        for (i = 0; ppszAttr[i]; i += 2)
+        for( int i = 0; ppszAttr[i]; i += 2 )
         {
-            poAtt = new Attribute();
+            Attribute* poAtt = new Attribute();
             poAtt->sName = ppszAttr[i];
             poAtt->sValue = ppszAttr[i + 1];
             poMynew->addAttribute(poAtt);
@@ -249,7 +246,7 @@ void XMLCALL KML::startElement(void* pUserData, const char* pszName, const char*
     {
         std::string sNewContent = "<";
         sNewContent += pszName;
-        for (i = 0; ppszAttr[i]; i += 2)
+        for( int i = 0; ppszAttr[i]; i += 2 )
         {
             sNewContent += " ";
             sNewContent += ppszAttr[i];
@@ -265,11 +262,10 @@ void XMLCALL KML::startElement(void* pUserData, const char* pszName, const char*
     }
 }
 
-void XMLCALL KML::startElementValidate(void* pUserData, const char* pszName, const char** ppszAttr)
+void XMLCALL KML::startElementValidate( void* pUserData, const char* pszName,
+                                        const char** ppszAttr )
 {
-    int i = 0;
-
-    KML* poKML = (KML*) pUserData;
+    KML* poKML = static_cast<KML *>(pUserData);
 
     if (poKML->validity != KML_VALIDITY_UNKNOWN)
         return;
@@ -279,13 +275,13 @@ void XMLCALL KML::startElementValidate(void* pUserData, const char* pszName, con
     if(strcmp(pszName, "kml") == 0 || strcmp(pszName, "Document") == 0)
     {
         // Check all Attributes
-        for (i = 0; ppszAttr[i]; i += 2)
+        for( int i = 0; ppszAttr[i]; i += 2 )
         {
             // Find the namespace and determine the KML version
             if(strcmp(ppszAttr[i], "xmlns") == 0)
             {
                 // Is it KML 2.2?
-                if((strcmp(ppszAttr[i + 1], "http://earth.google.com/kml/2.2") == 0) || 
+                if((strcmp(ppszAttr[i + 1], "http://earth.google.com/kml/2.2") == 0) ||
                    (strcmp(ppszAttr[i + 1], "http://www.opengis.net/kml/2.2") == 0))
                 {
                     poKML->validity = KML_VALIDITY_VALID;
@@ -312,32 +308,33 @@ void XMLCALL KML::startElementValidate(void* pUserData, const char* pszName, con
 
         if (poKML->validity == KML_VALIDITY_INVALID)
         {
-            CPLDebug("KML", "Did not find xmlns attribute in <kml> element. Going on though...");
+            CPLDebug( "KML",
+                      "Did not find xmlns attribute in <kml> element. "
+                      "Going on though..." );
             poKML->validity = KML_VALIDITY_VALID;
             poKML->sVersion_ = "?";
         }
     }
 }
 
-void XMLCALL KML::dataHandlerValidate(void * pUserData,
-                                      CPL_UNUSED const char * pszData,
-                                      CPL_UNUSED int nLen)
+void XMLCALL KML::dataHandlerValidate( void * pUserData,
+                                       const char * /* pszData */,
+                                       int /* nLen */ )
 {
-    KML* poKML = (KML*) pUserData;
+    KML* poKML = static_cast<KML *>(pUserData);
 
     poKML->nDataHandlerCounter ++;
     if (poKML->nDataHandlerCounter >= BUFSIZ)
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "File probably corrupted (million laugh pattern)");
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "File probably corrupted (million laugh pattern)" );
         XML_StopParser(poKML->oCurrentParser, XML_FALSE);
     }
 }
 
 void XMLCALL KML::endElement(void* pUserData, const char* pszName)
 {
-    KMLNode* poTmp = NULL;
-
-    KML* poKML = (KML*) pUserData;
+    KML* poKML = static_cast<KML *>(pUserData);
 
     poKML->nWithoutEventCounter = 0;
 
@@ -345,16 +342,16 @@ void XMLCALL KML::endElement(void* pUserData, const char* pszName)
        poKML->poCurrent_->getName().compare(pszName) == 0)
     {
         poKML->nDepth_--;
-        poTmp = poKML->poCurrent_;
+        KMLNode* poTmp = poKML->poCurrent_;
         // Split the coordinates
         if(poKML->poCurrent_->getName().compare("coordinates") == 0 &&
            poKML->poCurrent_->numContent() == 1)
         {
-            std::string sData = poKML->poCurrent_->getContent(0);
+            const std::string sData = poKML->poCurrent_->getContent(0);
             std::size_t nPos = 0;
-            std::size_t nLength = sData.length();
+            const std::size_t nLength = sData.length();
             const char* pszData = sData.c_str();
-            while(TRUE)
+            while( true )
             {
                 // Cut off whitespaces
                 while(nPos < nLength &&
@@ -365,11 +362,12 @@ void XMLCALL KML::endElement(void* pUserData, const char* pszName)
                 if (nPos == nLength)
                     break;
 
-                std::size_t nPosBegin = nPos;
+                const std::size_t nPosBegin = nPos;
 
                 // Get content
                 while(nPos < nLength &&
-                      pszData[nPos] != ' ' && pszData[nPos] != '\n' && pszData[nPos] != '\r' && 
+                      pszData[nPos] != ' ' && pszData[nPos] != '\n' &&
+                      pszData[nPos] != '\r' &&
                       pszData[nPos] != '\t')
                     nPos++;
 
@@ -384,26 +382,29 @@ void XMLCALL KML::endElement(void* pUserData, const char* pszName)
         }
         else if (poKML->poCurrent_->numContent() == 1)
         {
-            std::string sData = poKML->poCurrent_->getContent(0);
+            const std::string sData = poKML->poCurrent_->getContent(0);
             std::string sDataWithoutNL;
             std::size_t nPos = 0;
-            std::size_t nLength = sData.length();
+            const std::size_t nLength = sData.length();
             const char* pszData = sData.c_str();
             std::size_t nLineStartPos = 0;
-            int bLineStart = TRUE;
+            bool bLineStart = true;
 
-            /* Re-assemble multi-line content by removing leading spaces for each line */
-            /* I'm not sure why we do that. Shouldn't we preserve content as such ? */
+            // Re-assemble multi-line content by removing leading spaces for
+            // each line.  I am not sure why we do that. Should we preserve
+            // content as such?
             while(nPos < nLength)
             {
                 char ch = pszData[nPos];
-                if (bLineStart && (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'))
+                if (bLineStart && (ch == ' ' || ch == '\t' || ch == '\n' ||
+                                   ch == '\r'))
                     nLineStartPos ++;
                 else if (ch == '\n' || ch == '\r')
                 {
                     if (!bLineStart)
                     {
-                        std::string sTmp(pszData + nLineStartPos, nPos - nLineStartPos);
+                        std::string sTmp( pszData + nLineStartPos,
+                                          nPos - nLineStartPos);
                         if (sDataWithoutNL.size() > 0)
                             sDataWithoutNL += " ";
                         sDataWithoutNL += sTmp;
@@ -413,7 +414,7 @@ void XMLCALL KML::endElement(void* pUserData, const char* pszName)
                 }
                 else
                 {
-                    bLineStart = FALSE;
+                    bLineStart = false;
                 }
                 nPos ++;
             }
@@ -422,7 +423,8 @@ void XMLCALL KML::endElement(void* pUserData, const char* pszName)
             {
                 if (nLineStartPos < nPos)
                 {
-                    std::string sTmp(pszData + nLineStartPos, nPos - nLineStartPos);
+                    std::string sTmp( pszData + nLineStartPos,
+                                      nPos - nLineStartPos);
                     if (sDataWithoutNL.size() > 0)
                         sDataWithoutNL += " ";
                     sDataWithoutNL += sTmp;
@@ -463,7 +465,7 @@ void XMLCALL KML::endElement(void* pUserData, const char* pszName)
 
 void XMLCALL KML::dataHandler(void* pUserData, const char* pszData, int nLen)
 {
-    KML* poKML = (KML*) pUserData;
+    KML* poKML = static_cast<KML *>(pUserData);
 
     poKML->nWithoutEventCounter = 0;
 
@@ -473,7 +475,8 @@ void XMLCALL KML::dataHandler(void* pUserData, const char* pszData, int nLen)
     poKML->nDataHandlerCounter ++;
     if (poKML->nDataHandlerCounter >= BUFSIZ)
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "File probably corrupted (million laugh pattern)");
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "File probably corrupted (million laugh pattern)" );
         XML_StopParser(poKML->oCurrentParser, XML_FALSE);
     }
 
@@ -498,15 +501,15 @@ bool KML::isValid()
     checkValidity();
 
     if( validity == KML_VALIDITY_VALID )
-        CPLDebug("KML", "Valid: %d Version: %s", 
-                 validity == KML_VALIDITY_VALID, sVersion_.c_str());
+        CPLDebug( "KML", "Valid: %d Version: %s",
+                  validity == KML_VALIDITY_VALID, sVersion_.c_str());
 
     return validity == KML_VALIDITY_VALID;
 }
 
 std::string KML::getError() const
 {
-	return sError_;
+    return sError_;
 }
 
 int KML::classifyNodes()
@@ -527,40 +530,36 @@ void KML::print(unsigned short nNum)
 
 bool KML::isHandled(std::string const& elem) const
 {
-    if( isLeaf(elem) || isFeature(elem) || isFeatureContainer(elem)
-        || isContainer(elem) || isRest(elem) )
-    {
-        return true;
-    }
-    return false;
+    return isLeaf(elem) || isFeature(elem) || isFeatureContainer(elem)
+        || isContainer(elem) || isRest(elem);
 }
 
-bool KML::isLeaf(CPL_UNUSED std::string const& elem) const
+bool KML::isLeaf( std::string const& /* elem */ ) const
 {
     return false;
 };
 
-bool KML::isFeature(CPL_UNUSED std::string const& elem) const
+bool KML::isFeature( std::string const& /* elem */ ) const
 {
     return false;
 };
 
-bool KML::isFeatureContainer(CPL_UNUSED std::string const& elem) const
+bool KML::isFeatureContainer( std::string const& /* elem */ ) const
 {
     return false;
 };
 
-bool KML::isContainer(CPL_UNUSED std::string const& elem) const
+bool KML::isContainer( std::string const& /* elem */ ) const
 {
     return false;
 };
 
-bool KML::isRest(CPL_UNUSED std::string const& elem) const
+bool KML::isRest( std::string const& /* elem */ ) const
 {
     return false;
 };
 
-void KML::findLayers(CPL_UNUSED KMLNode* poNode, CPL_UNUSED int bKeepEmptyContainers)
+void KML::findLayers( KMLNode* /* poNode */, int /* bKeepEmptyContainers */ )
 {
     // idle
 };
@@ -577,9 +576,9 @@ int KML::getNumLayers() const
 
 bool KML::selectLayer(int nNum) {
     if(this->nNumLayers_ < 1 || nNum >= this->nNumLayers_)
-        return FALSE;
+        return false;
     poCurrent_ = papoLayers_[nNum];
-    return TRUE;
+    return true;
 }
 
 std::string KML::getCurrentName() const
@@ -596,30 +595,30 @@ Nodetype KML::getCurrentType() const
 {
     if(poCurrent_ != NULL)
         return poCurrent_->getType();
-    else
-        return Unknown;
+
+    return Unknown;
 }
 
 int KML::is25D() const
 {
     if(poCurrent_ != NULL)
         return poCurrent_->is25D();
-    else
-        return Unknown;
+
+    return Unknown;
 }
 
 int KML::getNumFeatures()
 {
-    if(poCurrent_ != NULL)
-        return static_cast<int>(poCurrent_->getNumFeatures());
-    else
+    if(poCurrent_ == NULL)
         return -1;
+
+    return static_cast<int>(poCurrent_->getNumFeatures());
 }
 
 Feature* KML::getFeature(std::size_t nNum, int& nLastAsked, int &nLastCount)
 {
-    if(poCurrent_ != NULL)
-        return poCurrent_->getFeature(nNum, nLastAsked, nLastCount);
-    else
+    if(poCurrent_ == NULL)
         return NULL;
+
+    return poCurrent_->getFeature(nNum, nLastAsked, nLastCount);
 }
diff --git a/ogr/ogrsf_frmts/kml/kml.h b/ogr/ogrsf_frmts/kml/kml.h
index ef0ef00..ec4ec42 100644
--- a/ogr/ogrsf_frmts/kml/kml.h
+++ b/ogr/ogrsf_frmts/kml/kml.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: kml.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: kml.h 32177 2015-12-14 07:25:30Z goatbar $
  *
  * Project:  KML Driver
  * Purpose:  Class for reading, parsing and handling a kmlfile.
@@ -117,7 +117,7 @@ private:
 	std::string sError_;
 	// current KMLNode
 	KMLNode *poCurrent_;
-        
+
         XML_Parser oCurrentParser;
         int nDataHandlerCounter;
         int nWithoutEventCounter;
diff --git a/ogr/ogrsf_frmts/kml/kmlnode.cpp b/ogr/ogrsf_frmts/kml/kmlnode.cpp
index 166098e..d810013 100644
--- a/ogr/ogrsf_frmts/kml/kmlnode.cpp
+++ b/ogr/ogrsf_frmts/kml/kmlnode.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: kmlnode.cpp 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: kmlnode.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  KML Driver
  * Purpose:  Class for building up the node structure of the kml file.
@@ -66,7 +66,7 @@ std::string Nodetype2String(Nodetype const& type)
 static
 bool isNumberDigit(const char cIn)
 {
-    return ( cIn == '-' || cIn == '+' || 
+    return ( cIn == '-' || cIn == '+' ||
             (cIn >= '0' && cIn <= '9') ||
              cIn == '.' || cIn == 'e' || cIn == 'E' );
 }
@@ -110,17 +110,17 @@ Coordinate* ParseCoordinate(std::string const& text)
 /*                         KMLNode methods                              */
 /************************************************************************/
 
-KMLNode::KMLNode()
-{
-    poParent_ = NULL;
-    pvpoChildren_ = new std::vector<KMLNode*>;
-    pvsContent_ = new std::vector<std::string>;
-    pvoAttributes_ = new std::vector<Attribute*>;
-    eType_ = Unknown;
-    nLayerNumber_ = -1;
-    b25D_ = FALSE;
-    nNumFeatures_ = -1;
-}
+KMLNode::KMLNode() :
+    pvpoChildren_(new std::vector<KMLNode*>),
+    pvsContent_(new std::vector<std::string>),
+    pvoAttributes_(new std::vector<Attribute*>),
+    poParent_(NULL),
+    nLevel_(0),
+    eType_(Unknown),
+    b25D_(false),
+    nLayerNumber_(-1),
+    nNumFeatures_(-1)
+{}
 
 KMLNode::~KMLNode()
 {
@@ -156,68 +156,93 @@ void KMLNode::print(unsigned int what)
     {
         if(nLayerNumber_ > -1)
         {
-            CPLDebug("KML", "%s%s (nLevel: %d Type: %s poParent: %s pvpoChildren_: %d pvsContent_: %d pvoAttributes_: %d) <--- Layer #%d", 
-                        indent.c_str(), sName_.c_str(), (int) nLevel_, Nodetype2String(eType_).c_str(), poParent_->sName_.c_str(), 
-                        (int) pvpoChildren_->size(), (int) pvsContent_->size(), (int) pvoAttributes_->size(), nLayerNumber_);
+            CPLDebug( "KML",
+                      "%s%s (nLevel: %d Type: %s poParent: %s "
+                      "pvpoChildren_: %d pvsContent_: %d pvoAttributes_: %d) "
+                      "<--- Layer #%d",
+                      indent.c_str(), sName_.c_str(),
+                      static_cast<int>(nLevel_),
+                      Nodetype2String(eType_).c_str(),
+                      poParent_->sName_.c_str(),
+                      static_cast<int>(pvpoChildren_->size()),
+                      static_cast<int>(pvsContent_->size()),
+                      static_cast<int>(pvoAttributes_->size()),
+                      nLayerNumber_ );
         }
         else
         {
-            CPLDebug("KML", "%s%s (nLevel: %d Type: %s poParent: %s pvpoChildren_: %d pvsContent_: %d pvoAttributes_: %d)", 
-                        indent.c_str(), sName_.c_str(), (int) nLevel_, Nodetype2String(eType_).c_str(), poParent_->sName_.c_str(), 
-                        (int) pvpoChildren_->size(), (int) pvsContent_->size(), (int) pvoAttributes_->size());
+            CPLDebug( "KML",
+                      "%s%s (nLevel: %d Type: %s poParent: %s "
+                      "pvpoChildren_: %d pvsContent_: %d pvoAttributes_: %d)",
+                      indent.c_str(), sName_.c_str(), static_cast<int>(nLevel_),
+                      Nodetype2String(eType_).c_str(),
+                      poParent_->sName_.c_str(),
+                      static_cast<int>(pvpoChildren_->size()),
+                      static_cast<int>(pvsContent_->size()),
+                      static_cast<int>(pvoAttributes_->size()) );
         }
     }
     else
     {
-        CPLDebug("KML", "%s%s (nLevel: %d Type: %s pvpoChildren_: %d pvsContent_: %d pvoAttributes_: %d)", 
-                 indent.c_str(), sName_.c_str(), (int) nLevel_, Nodetype2String(eType_).c_str(), (int) pvpoChildren_->size(), 
-                 (int) pvsContent_->size(), (int) pvoAttributes_->size());
+        CPLDebug( "KML",
+                  "%s%s (nLevel: %d Type: %s pvpoChildren_: %d "
+                  "pvsContent_: %d pvoAttributes_: %d)",
+                  indent.c_str(), sName_.c_str(), static_cast<int>(nLevel_),
+                  Nodetype2String(eType_).c_str(),
+                  static_cast<int>(pvpoChildren_->size()),
+                  static_cast<int>(pvsContent_->size()),
+                  static_cast<int>(pvoAttributes_->size()) );
     }
 
     if(what == 1 || what == 3)
     {
         for(kml_content_t::size_type z = 0; z < pvsContent_->size(); z++)
-            CPLDebug("KML", "%s|->pvsContent_: '%s'", indent.c_str(), (*pvsContent_)[z].c_str());
+            CPLDebug( "KML", "%s|->pvsContent_: '%s'",
+                      indent.c_str(), (*pvsContent_)[z].c_str() );
     }
 
     if(what == 2 || what == 3)
     {
         for(kml_attributes_t::size_type z = 0; z < pvoAttributes_->size(); z++)
-            CPLDebug("KML", "%s|->pvoAttributes_: %s = '%s'", indent.c_str(), (*pvoAttributes_)[z]->sName.c_str(), (*pvoAttributes_)[z]->sValue.c_str());
+            CPLDebug( "KML", "%s|->pvoAttributes_: %s = '%s'",
+                      indent.c_str(), (*pvoAttributes_)[z]->sName.c_str(),
+                      (*pvoAttributes_)[z]->sValue.c_str() );
     }
 
     for(kml_nodes_t::size_type z = 0; z < pvpoChildren_->size(); z++)
         (*pvpoChildren_)[z]->print(what);
 }
 
-//static int nDepth = 0;
-//static char* genSpaces()
-//{
-//    static char spaces[128];
-//    int i;
-//    for(i=0;i<nDepth;i++)
-//        spaces[i] = ' ';
-//    spaces[i] = '\0';
-//    return spaces;
-//}
+#ifdef DEBUG_VERBOSE
+static int nDepth = 0;
+static char* genSpaces()
+{
+    static char spaces[128];
+    for(int i=0;i<nDepth;i++)
+        spaces[i] = ' ';
+    spaces[i] = '\0';
+    return spaces;
+}
+#endif
 
 int KMLNode::classify(KML* poKML, int nRecLevel)
 {
-    Nodetype curr = Unknown;
     Nodetype all = Empty;
 
     /* Arbitrary value, but certainly large enough for reasonable usages ! */
     if( nRecLevel == 32 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                    "Too many recursiong level (%d) while parsing KML geometry.",
-                    nRecLevel );
+                  "Too many recursion levels (%d) while parsing KML geometry.",
+                  nRecLevel );
         return FALSE;
     }
 
-    //CPLDebug("KML", "%s<%s>", genSpaces(), sName_.c_str());
-    //nDepth ++;
-    
+#ifdef DEBUG_VERBOSE
+    CPLDebug( "KML", "%s<%s>", genSpaces(), sName_.c_str() );
+    nDepth ++;
+#endif
+
     if(sName_.compare("Point") == 0)
         eType_ = Point;
     else if(sName_.compare("LineString") == 0)
@@ -233,7 +258,7 @@ int KMLNode::classify(KML* poKML, int nRecLevel)
         {
             const char* pszCoord = (*pvsContent_)[nCountP].c_str();
             int nComma = 0;
-            while(TRUE)
+            while( true )
             {
                 pszCoord = strchr(pszCoord, ',');
                 if (pszCoord)
@@ -245,20 +270,23 @@ int KMLNode::classify(KML* poKML, int nRecLevel)
                     break;
             }
             if (nComma == 2)
-                b25D_ = TRUE;
+                b25D_ = true;
         }
     }
 
     const kml_nodes_t::size_type size = pvpoChildren_->size();
     for(kml_nodes_t::size_type z = 0; z < size; z++)
     {
-        //CPLDebug("KML", "%s[%d] %s", genSpaces(), z, (*pvpoChildren_)[z]->sName_.c_str());
+#ifdef DEBUG_VERBOSE
+        CPLDebug( "KML", "%s[%d] %s", genSpaces(), z,
+                  (*pvpoChildren_)[z]->sName_.c_str() );
+#endif
 
         // Classify pvpoChildren_
         if (!(*pvpoChildren_)[z]->classify(poKML, nRecLevel + 1))
             return FALSE;
 
-        curr = (*pvpoChildren_)[z]->eType_;
+        Nodetype curr = (*pvpoChildren_)[z]->eType_;
         b25D_ |= (*pvpoChildren_)[z]->b25D_;
 
         // Compare and return if it is mixed
@@ -293,7 +321,10 @@ int KMLNode::classify(KML* poKML, int nRecLevel)
     }
 
     //nDepth --;
-    //CPLDebug("KML", "%s</%s> --> eType=%s", genSpaces(), sName_.c_str(), Nodetype2String(eType_).c_str());
+#ifdef DEBUG_VERBOSE
+    CPLDebug( "KML", "%s</%s> --> eType=%s",
+              genSpaces(), sName_.c_str(), Nodetype2String(eType_).c_str());
+#endif
 
     return TRUE;
 }
@@ -385,7 +416,7 @@ void KMLNode::addChildren(KMLNode *poChil)
     pvpoChildren_->push_back(poChil);
 }
 
-std::size_t KMLNode::countChildren()
+std::size_t KMLNode::countChildren() const
 {
     return pvpoChildren_->size();
 }
@@ -419,7 +450,7 @@ void KMLNode::deleteContent(std::size_t index)
     }
 }
 
-std::size_t KMLNode::numContent()
+std::size_t KMLNode::numContent() const
 {
     return pvsContent_->size();
 }
@@ -437,7 +468,7 @@ int KMLNode::getLayerNumber() const
 std::string KMLNode::getNameElement() const
 {
     kml_nodes_t::size_type subsize = 0;
-    kml_nodes_t::size_type size = pvpoChildren_->size();
+    const kml_nodes_t::size_type size = pvpoChildren_->size();
 
     for( kml_nodes_t::size_type i = 0; i < size; ++i )
     {
@@ -457,7 +488,7 @@ std::string KMLNode::getNameElement() const
 std::string KMLNode::getDescriptionElement() const
 {
     kml_nodes_t::size_type subsize = 0;
-    kml_nodes_t::size_type size = pvpoChildren_->size();
+    const kml_nodes_t::size_type size = pvpoChildren_->size();
     for( kml_nodes_t::size_type i = 0; i < size; ++i )
     {
         if( (*pvpoChildren_)[i]->sName_.compare("description") == 0 )
@@ -479,7 +510,7 @@ std::size_t KMLNode::getNumFeatures()
     {
         std::size_t nNum = 0;
         kml_nodes_t::size_type size = pvpoChildren_->size();
-        
+
         for( kml_nodes_t::size_type i = 0; i < size; ++i )
         {
             if( (*pvpoChildren_)[i]->sName_ == "Placemark" )
@@ -492,7 +523,6 @@ std::size_t KMLNode::getNumFeatures()
 
 OGRGeometry* KMLNode::getGeometry(Nodetype eType)
 {
-    unsigned int nCount, nCount2, nCountP;
     OGRGeometry* poGeom = NULL;
     KMLNode* poCoor = NULL;
     Coordinate* psCoord = NULL;
@@ -500,12 +530,14 @@ OGRGeometry* KMLNode::getGeometry(Nodetype eType)
     if (sName_.compare("Point") == 0)
     {
         // Search coordinate Element
-        for(nCount = 0; nCount < pvpoChildren_->size(); nCount++)
+        for( unsigned int nCount = 0; nCount < pvpoChildren_->size(); nCount++)
         {
             if((*pvpoChildren_)[nCount]->sName_.compare("coordinates") == 0)
             {
                 poCoor = (*pvpoChildren_)[nCount];
-                for(nCountP = 0; nCountP < poCoor->pvsContent_->size(); nCountP++)
+                for( unsigned int nCountP = 0;
+                     nCountP < poCoor->pvsContent_->size();
+                     nCountP++)
                 {
                     psCoord = ParseCoordinate((*poCoor->pvsContent_)[nCountP]);
                     if(psCoord != NULL)
@@ -529,12 +561,14 @@ OGRGeometry* KMLNode::getGeometry(Nodetype eType)
     {
         // Search coordinate Element
         poGeom = new OGRLineString();
-        for(nCount = 0; nCount < pvpoChildren_->size(); nCount++)
+        for( unsigned int nCount = 0; nCount < pvpoChildren_->size(); nCount++)
         {
             if((*pvpoChildren_)[nCount]->sName_.compare("coordinates") == 0)
             {
                 poCoor = (*pvpoChildren_)[nCount];
-                for(nCountP = 0; nCountP < poCoor->pvsContent_->size(); nCountP++)
+                for( unsigned int nCountP = 0;
+                     nCountP < poCoor->pvsContent_->size();
+                     nCountP++ )
                 {
                     psCoord = ParseCoordinate((*poCoor->pvsContent_)[nCountP]);
                     if(psCoord != NULL)
@@ -558,7 +592,7 @@ OGRGeometry* KMLNode::getGeometry(Nodetype eType)
         // Search outerBoundaryIs Element
         //*********************************
         poGeom = new OGRPolygon();
-        for(nCount = 0; nCount < pvpoChildren_->size(); nCount++)
+        for(unsigned int nCount = 0; nCount < pvpoChildren_->size(); nCount++)
         {
             if((*pvpoChildren_)[nCount]->sName_.compare("outerBoundaryIs") == 0 &&
                (*pvpoChildren_)[nCount]->pvpoChildren_->size() > 0)
@@ -573,11 +607,16 @@ OGRGeometry* KMLNode::getGeometry(Nodetype eType)
         }
         // Search coordinate Element
         OGRLinearRing* poLinearRing = NULL;
-        for(nCount = 0; nCount < poCoor->pvpoChildren_->size(); nCount++)
+        for( unsigned int nCount = 0;
+             nCount < poCoor->pvpoChildren_->size();
+             nCount++)
         {
             if((*poCoor->pvpoChildren_)[nCount]->sName_.compare("coordinates") == 0)
             {
-                for(nCountP = 0; nCountP < (*poCoor->pvpoChildren_)[nCount]->pvsContent_->size(); nCountP++)
+                for( unsigned int nCountP = 0;
+                     nCountP <
+                       (*poCoor->pvpoChildren_)[nCount]->pvsContent_->size();
+                     nCountP++)
                 {
                     psCoord = ParseCoordinate((*(*poCoor->pvpoChildren_)[nCount]->pvsContent_)[nCountP]);
                     if(psCoord != NULL)
@@ -611,7 +650,9 @@ OGRGeometry* KMLNode::getGeometry(Nodetype eType)
         // Search innerBoundaryIs Elements
         //*********************************
 
-        for(nCount2 = 0; nCount2 < pvpoChildren_->size(); nCount2++)
+        for( unsigned int nCount2 = 0;
+             nCount2 < pvpoChildren_->size();
+             nCount2++ )
         {
             if((*pvpoChildren_)[nCount2]->sName_.compare("innerBoundaryIs") == 0)
             {
@@ -626,11 +667,15 @@ OGRGeometry* KMLNode::getGeometry(Nodetype eType)
 
                 poCoor = (*(*pvpoChildren_)[nCount2]->pvpoChildren_)[0];
                 // Search coordinate Element
-                for(nCount = 0; nCount < poCoor->pvpoChildren_->size(); nCount++)
+                for( unsigned int nCount = 0;
+                     nCount < poCoor->pvpoChildren_->size();
+                     nCount++ )
                 {
                     if((*poCoor->pvpoChildren_)[nCount]->sName_.compare("coordinates") == 0)
                     {
-                        for(nCountP = 0; nCountP < (*poCoor->pvpoChildren_)[nCount]->pvsContent_->size(); nCountP++)
+                        for( unsigned int nCountP = 0;
+                             nCountP < (*poCoor->pvpoChildren_)[nCount]->pvsContent_->size();
+                             nCountP++)
                         {
                             psCoord = ParseCoordinate((*(*poCoor->pvpoChildren_)[nCount]->pvsContent_)[nCountP]);
                             if(psCoord != NULL)
@@ -650,8 +695,9 @@ OGRGeometry* KMLNode::getGeometry(Nodetype eType)
             }
         }
 
-        if (poLinearRing)
-            ((OGRPolygon*)poGeom)->addRingDirectly(poLinearRing);
+        if( poLinearRing )
+            reinterpret_cast<OGRPolygon *>(
+                poGeom)->addRingDirectly(poLinearRing);
     }
     else if (sName_.compare("MultiGeometry") == 0)
     {
@@ -663,7 +709,7 @@ OGRGeometry* KMLNode::getGeometry(Nodetype eType)
             poGeom = new OGRMultiPolygon();
         else
             poGeom = new OGRGeometryCollection();
-        for(nCount = 0; nCount < pvpoChildren_->size(); nCount++)
+        for(unsigned int nCount = 0; nCount < pvpoChildren_->size(); nCount++)
         {
             OGRGeometry* poSubGeom = (*pvpoChildren_)[nCount]->getGeometry();
             if (poSubGeom)
@@ -676,14 +722,15 @@ OGRGeometry* KMLNode::getGeometry(Nodetype eType)
 
 Feature* KMLNode::getFeature(std::size_t nNum, int& nLastAsked, int &nLastCount)
 {
-    unsigned int nCount, nCountP = 0;
-    KMLNode* poFeat = NULL;
-    KMLNode* poTemp = NULL;
-
     if(nNum >= this->getNumFeatures())
         return NULL;
 
-    if (nLastAsked + 1 != (int)nNum)
+    unsigned int nCount;
+    unsigned int nCountP = 0;
+    KMLNode* poFeat = NULL;
+    KMLNode* poTemp = NULL;
+
+    if (nLastAsked + 1 != static_cast<int>(nNum ))
     {
         nCount = 0;
         nCountP = 0;
@@ -707,12 +754,12 @@ Feature* KMLNode::getFeature(std::size_t nNum, int& nLastAsked, int &nLastCount)
         }
     }
 
-    nLastAsked = nNum;
+    nLastAsked = static_cast<int>(nNum);
     nLastCount = nCount;
 
     if(poFeat == NULL)
         return NULL;
-        
+
     // Create a feature structure
     Feature *psReturn = new Feature;
     // Build up the name
@@ -727,9 +774,9 @@ Feature* KMLNode::getFeature(std::size_t nNum, int& nLastAsked, int &nLastCount)
        poFeat->eType_ == LineString ||
        poFeat->eType_ == Polygon)
         sElementName = Nodetype2String(poFeat->eType_);
-    else if (poFeat->eType_ == MultiGeometry || 
-             poFeat->eType_ == MultiPoint || 
-             poFeat->eType_ == MultiLineString || 
+    else if (poFeat->eType_ == MultiGeometry ||
+             poFeat->eType_ == MultiPoint ||
+             poFeat->eType_ == MultiLineString ||
              poFeat->eType_ == MultiPolygon)
         sElementName = "MultiGeometry";
     else
diff --git a/ogr/ogrsf_frmts/kml/kmlnode.h b/ogr/ogrsf_frmts/kml/kmlnode.h
index d9d6419..3e143a4 100644
--- a/ogr/ogrsf_frmts/kml/kmlnode.h
+++ b/ogr/ogrsf_frmts/kml/kmlnode.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: kmlnode.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: kmlnode.h 32872 2016-01-09 10:16:42Z goatbar $
  *
  * Project:  KML Driver
  * Purpose:  Class for building up the node structure of the kml file.
@@ -50,31 +50,31 @@ public:
     int classify(KML* poKML, int nRecLevel = 0);
     void eliminateEmpty(KML* poKML);
     bool hasOnlyEmpty() const;
-    
+
     void setType(Nodetype type);
     Nodetype getType() const;
-    
+
     void setName(std::string const& name);
     const std::string& getName() const;
-    
+
     void setLevel(std::size_t level);
     std::size_t getLevel() const;
-    
+
     void addAttribute(Attribute* poAttr);
-    
+
     void setParent(KMLNode* poNode);
     KMLNode* getParent() const;
-    
+
     void addChildren(KMLNode* poNode);
-    std::size_t countChildren();
-    
+    std::size_t countChildren() const;
+
     KMLNode* getChild(std::size_t index) const;
 
     void addContent(std::string const& text);
     void appendContent(std::string const& text);
     std::string getContent(std::size_t index) const;
     void deleteContent(std::size_t index);
-    std::size_t numContent();
+    std::size_t numContent() const;
 
     void setLayerNumber(int nNum);
     int getLayerNumber() const;
@@ -84,10 +84,10 @@ public:
 
     std::size_t getNumFeatures();
     Feature* getFeature(std::size_t nNum, int& nLastAsked, int &nLastCount);
-    
+
     OGRGeometry* getGeometry(Nodetype eType = Unknown);
 
-    int is25D() { return b25D_; }
+    bool is25D() const { return b25D_; }
 
 private:
 
@@ -105,11 +105,10 @@ private:
     std::string sName_;
 
     Nodetype eType_;
-    int b25D_;
+    bool b25D_;
 
     int nLayerNumber_;
     int nNumFeatures_;
 };
 
 #endif /* KMLNODE_H_INCLUDED */
-
diff --git a/ogr/ogrsf_frmts/kml/kmlutility.h b/ogr/ogrsf_frmts/kml/kmlutility.h
index cdc9768..b875a6e 100644
--- a/ogr/ogrsf_frmts/kml/kmlutility.h
+++ b/ogr/ogrsf_frmts/kml/kmlutility.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: kmlutility.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: kmlutility.h 33339 2016-02-03 11:48:06Z rouault $
  *
  * Project:  KML Driver
  * Purpose:  KML driver utilities
@@ -34,9 +34,13 @@
 #include <vector>
 #include "ogr_geometry.h"
 
+namespace OGRKML
+{
+
 enum Nodetype
 {
-    Unknown, Empty, Mixed, Point, LineString, Polygon, Rest, MultiGeometry, MultiPoint, MultiLineString, MultiPolygon
+    Unknown, Empty, Mixed, Point, LineString, Polygon, Rest, MultiGeometry,
+    MultiPoint, MultiLineString, MultiPolygon
 };
 
 struct Attribute
@@ -67,13 +71,16 @@ struct Feature
     Feature()
         : eType(Unknown), poGeom(NULL)
     {}
-    
+
     ~Feature()
     {
         delete poGeom;
     }
 };
 
+}
+
+using namespace OGRKML;
 
 #endif /* OGR_KMLUTILITY_H_INCLUDED */
 
diff --git a/ogr/ogrsf_frmts/kml/kmlvector.cpp b/ogr/ogrsf_frmts/kml/kmlvector.cpp
index 92f5b44..0da556b 100644
--- a/ogr/ogrsf_frmts/kml/kmlvector.cpp
+++ b/ogr/ogrsf_frmts/kml/kmlvector.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: kmlvector.cpp 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: kmlvector.cpp 32872 2016-01-09 10:16:42Z goatbar $
  *
  * Project:  KML Driver
  * Purpose:  Specialization of the kml class, only for vectors in kml files.
@@ -30,68 +30,46 @@
 #include "kmlvector.h"
 #include "kmlnode.h"
 #include "cpl_conv.h"
-// std
+
 #include <string>
 
-KMLVector::~KMLVector()
-{
-}
+KMLVector::~KMLVector() {}
 
 bool KMLVector::isLeaf(std::string const& sIn) const
 {
-    if( sIn.compare("name") == 0
+    return sIn.compare("name") == 0
         || sIn.compare("coordinates") == 0
         || sIn.compare("altitudeMode") == 0
-        || sIn.compare("description") == 0 )
-    {
-        return true;
-    }
-    return false;
+        || sIn.compare("description") == 0;
 }
 
 // Container - FeatureContainer - Feature
 
 bool KMLVector::isContainer(std::string const& sIn) const
 {
-    if( sIn.compare("Folder") == 0
+    return sIn.compare("Folder") == 0
         || sIn.compare("Document") == 0
-        || sIn.compare("kml") == 0 )
-    {
-        return true;
-    }
-    return false;
+        || sIn.compare("kml") == 0;
 }
 
 bool KMLVector::isFeatureContainer(std::string const& sIn) const
 {
-    if( sIn.compare("MultiGeometry") == 0
-        || sIn.compare("Placemark") == 0 )
-    {
-        return true;
-    }
-    return false;
+    return sIn.compare("MultiGeometry") == 0
+        || sIn.compare("Placemark") == 0;
 }
 
 bool KMLVector::isFeature(std::string const& sIn) const
 {
-    if( sIn.compare("Polygon") == 0
+    return sIn.compare("Polygon") == 0
         || sIn.compare("LineString") == 0
-        || sIn.compare("Point") == 0 )
-    {
-        return true;
-    }
-    return false;
+        || sIn.compare("Point") == 0;
 }
 
 bool KMLVector::isRest(std::string const& sIn) const
 {
-    if( sIn.compare("outerBoundaryIs") == 0
+    return sIn.compare("outerBoundaryIs") == 0
         || sIn.compare("innerBoundaryIs") == 0
-        || sIn.compare("LinearRing") == 0 )
-    {
-        return true;
-    }
-    return false;
+        || sIn.compare("LinearRing") == 0;
 }
 
 void KMLVector::findLayers(KMLNode* poNode, int bKeepEmptyContainers)
@@ -135,7 +113,7 @@ void KMLVector::findLayers(KMLNode* poNode, int bKeepEmptyContainers)
         {
             return;
         }
-        
+
         Nodetype nodeType = poNode->getType();
         if( bKeepEmptyContainers ||
             isFeature(Nodetype2String(nodeType)) ||
@@ -144,19 +122,22 @@ void KMLVector::findLayers(KMLNode* poNode, int bKeepEmptyContainers)
             nodeType == MultiLineString || nodeType == MultiPolygon)
         {
             poNode->setLayerNumber(nNumLayers_++);
-            papoLayers_ = (KMLNode**)CPLRealloc(papoLayers_, nNumLayers_ * sizeof(KMLNode*));
+            papoLayers_ = static_cast<KMLNode**>(
+                CPLRealloc(papoLayers_, nNumLayers_ * sizeof(KMLNode*)) );
             papoLayers_[nNumLayers_ - 1] = poNode;
         }
         else
         {
             CPLDebug( "KML", "We have a strange type here for node %s: %s",
-                      poNode->getName().c_str(), Nodetype2String(poNode->getType()).c_str() );
+                      poNode->getName().c_str(),
+                      Nodetype2String(poNode->getType()).c_str() );
         }
     }
     else
     {
-        CPLDebug("KML", "There is something wrong!  Define KML_DEBUG to see details");
-        if( CPLGetConfigOption("KML_DEBUG",NULL) != NULL )
+        CPLDebug( "KML",
+                  "There is something wrong!  Define KML_DEBUG to see details");
+        if( CPLGetConfigOption("KML_DEBUG", NULL) != NULL )
             print();
     }
 }
diff --git a/ogr/ogrsf_frmts/kml/ogr2kmlgeometry.cpp b/ogr/ogrsf_frmts/kml/ogr2kmlgeometry.cpp
index 2d81ca1..9fdaf28 100644
--- a/ogr/ogrsf_frmts/kml/ogr2kmlgeometry.cpp
+++ b/ogr/ogrsf_frmts/kml/ogr2kmlgeometry.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr2kmlgeometry.cpp 27959 2014-11-14 18:29:21Z rouault $
+ * $Id: ogr2kmlgeometry.cpp 32879 2016-01-09 12:45:12Z rouault $
  *
  * Project:  KML Driver
  * Purpose:  Implementation of OGR -> KML geometries writer.
@@ -27,21 +27,22 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_minixml.h"
-#include "ogr_geometry.h"
 #include "ogr_api.h"
+#include "ogr_geometry.h"
 #include "ogr_p.h"
-#include "cpl_error.h"
-#include "cpl_conv.h"
 
 
-#define EPSILON 1e-8
+static const double EPSILON = 1e-8;
 
 /************************************************************************/
 /*                        MakeKMLCoordinate()                           */
 /************************************************************************/
 
-static void MakeKMLCoordinate( char *pszTarget, 
+static void MakeKMLCoordinate( char *pszTarget, size_t nTargetLen,
                                double x, double y, double z, int b3D )
 
 {
@@ -57,13 +58,14 @@ static void MakeKMLCoordinate( char *pszTarget,
         }
         else
         {
-            static int bFirstWarning = TRUE;
-            if (bFirstWarning)
+            static bool bFirstWarning = true;
+            if( bFirstWarning )
             {
-                CPLError(CE_Failure, CPLE_AppDefined,
-                        "Latitude %f is invalid. Valid range is [-90,90]. This warning will not be issued any more",
-                        y);
-                bFirstWarning = FALSE;
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Latitude %f is invalid. Valid range is [-90,90]. "
+                          "This warning will not be issued any more",
+                          y );
+                bFirstWarning = false;
             }
         }
     }
@@ -80,19 +82,21 @@ static void MakeKMLCoordinate( char *pszTarget,
         }
         else
         {
-            static int bFirstWarning = TRUE;
-            if (bFirstWarning)
+            static bool bFirstWarning = true;
+            if( bFirstWarning )
             {
-                CPLError(CE_Warning, CPLE_AppDefined,
-                        "Longitude %f has been modified to fit into range [-180,180]. This warning will not be issued any more",
-                        x);
-                bFirstWarning = FALSE;
+                CPLError( CE_Warning, CPLE_AppDefined,
+                          "Longitude %f has been modified to fit into "
+                          "range [-180,180]. This warning will not be "
+                          "issued any more",
+                          x );
+                bFirstWarning = false;
             }
-    
+
             if (x > 180)
-                x -= ((int) ((x+180)/360)*360);
+                x -= (static_cast<int>((x+180)/360)*360);
             else if (x < -180)
-                x += ((int) (180 - x)/360)*360;
+                x += (static_cast<int>(180 - x)/360)*360;
         }
     }
 
@@ -102,31 +106,37 @@ static void MakeKMLCoordinate( char *pszTarget,
         if( *pszTarget == ' ' )
             *pszTarget = ',';
         pszTarget++;
+        nTargetLen --;
     }
 
-#ifdef notdef
+#if 0
     if( !b3D )
     {
-        if( x == (int) x && y == (int) y )
-            sprintf( pszTarget, "%d,%d", (int) x, (int) y );
+        if( x == static_cast<int>(x) && y == static_cast<int>(y) )
+            snprintf( pszTarget, nTargetLen, "%d,%d",
+                      static_cast<int>(x), static_cast<int>(y) );
         else if( fabs(x) < 370 && fabs(y) < 370 )
-            CPLsprintf( pszTarget, "%.16g,%.16g", x, y );
+            CPLsnprintf( pszTarget, nTargetLen, "%.16g,%.16g", x, y );
         else if( fabs(x) > 100000000.0 || fabs(y) > 100000000.0 )
-            CPLsprintf( pszTarget, "%.16g,%.16g", x, y );
+            CPLsnprintf( pszTarget, nTargetLen, "%.16g,%.16g", x, y );
         else
-            CPLsprintf( pszTarget, "%.3f,%.3f", x, y );
+            CPLsnprintf( pszTarget, nTargetLen, "%.3f,%.3f", x, y );
     }
     else
     {
-        if( x == (int) x && y == (int) y && z == (int) z )
-            sprintf( pszTarget, "%d,%d,%d", (int) x, (int) y, (int) z );
+        if( x == static_cast<int>(x) &&
+            y == static_cast<int>(y) &&
+            z == static_cast<int>(z) )
+            snprintf( pszTarget, nTargetLen, "%d,%d,%d",
+                      static_cast<int>(x), static_cast<int>(y),
+                      static_cast<int>(z) );
         else if( fabs(x) < 370 && fabs(y) < 370 )
-            CPLsprintf( pszTarget, "%.16g,%.16g,%.16g", x, y, z );
-        else if( fabs(x) > 100000000.0 || fabs(y) > 100000000.0 
+            CPLsnprintf( pszTarget, nTargetLen, "%.16g,%.16g,%.16g", x, y, z );
+        else if( fabs(x) > 100000000.0 || fabs(y) > 100000000.0
                  || fabs(z) > 100000000.0 )
-            CPLsprintf( pszTarget, "%.16g,%.16g,%.16g", x, y, z );
+            CPLsnprintf( pszTarget, nTargetLen, "%.16g,%.16g,%.16g", x, y, z );
         else
-            CPLsprintf( pszTarget, "%.3f,%.3f,%.3f", x, y, z );
+            CPLsnprintf( pszTarget, nTargetLen, "%.3f,%.3f,%.3f", x, y, z );
     }
 #endif
 }
@@ -135,13 +145,13 @@ static void MakeKMLCoordinate( char *pszTarget,
 /*                            _GrowBuffer()                             */
 /************************************************************************/
 
-static void _GrowBuffer( int nNeeded, char **ppszText, int *pnMaxLength )
+static void _GrowBuffer( size_t nNeeded, char **ppszText, size_t *pnMaxLength )
 
 {
     if( nNeeded+1 >= *pnMaxLength )
     {
         *pnMaxLength = MAX(*pnMaxLength * 2,nNeeded+1);
-        *ppszText = (char *) CPLRealloc(*ppszText, *pnMaxLength);
+        *ppszText = static_cast<char *>( CPLRealloc(*ppszText, *pnMaxLength) );
     }
 }
 
@@ -149,7 +159,8 @@ static void _GrowBuffer( int nNeeded, char **ppszText, int *pnMaxLength )
 /*                            AppendString()                            */
 /************************************************************************/
 
-static void AppendString( char **ppszText, int *pnLength, int *pnMaxLength,
+static void AppendString( char **ppszText, size_t *pnLength,
+                          size_t *pnMaxLength,
                           const char *pszTextToAppend )
 
 {
@@ -165,13 +176,13 @@ static void AppendString( char **ppszText, int *pnLength, int *pnMaxLength,
 /*                        AppendCoordinateList()                        */
 /************************************************************************/
 
-static void AppendCoordinateList( OGRLineString *poLine, 
-                                  char **ppszText, int *pnLength, 
-                                  int *pnMaxLength )
+static void AppendCoordinateList( OGRLineString *poLine,
+                                  char **ppszText, size_t *pnLength,
+                                  size_t *pnMaxLength )
 
 {
     char szCoordinate[256]= { 0 };
-    int b3D = wkbHasZ(poLine->getGeometryType());
+    const bool b3D = CPL_TO_BOOL(wkbHasZ(poLine->getGeometryType()));
 
     *pnLength += strlen(*ppszText + *pnLength);
     _GrowBuffer( *pnLength + 20, ppszText, pnMaxLength );
@@ -181,12 +192,12 @@ static void AppendCoordinateList( OGRLineString *poLine,
 
     for( int iPoint = 0; iPoint < poLine->getNumPoints(); iPoint++ )
     {
-        MakeKMLCoordinate( szCoordinate, 
+        MakeKMLCoordinate( szCoordinate, sizeof(szCoordinate),
                            poLine->getX(iPoint),
                            poLine->getY(iPoint),
                            poLine->getZ(iPoint),
                            b3D );
-        _GrowBuffer( *pnLength + strlen(szCoordinate)+1, 
+        _GrowBuffer( *pnLength + strlen(szCoordinate)+1,
             ppszText, pnMaxLength );
 
         if( iPoint != 0 )
@@ -205,9 +216,9 @@ static void AppendCoordinateList( OGRLineString *poLine,
 /*                       OGR2KMLGeometryAppend()                        */
 /************************************************************************/
 
-static int OGR2KMLGeometryAppend( OGRGeometry *poGeometry, 
-                                  char **ppszText, int *pnLength, 
-                                  int *pnMaxLength, char * szAltitudeMode )
+static bool OGR2KMLGeometryAppend( OGRGeometry *poGeometry,
+                                   char **ppszText, size_t *pnLength,
+                                   size_t *pnMaxLength, char *szAltitudeMode )
 
 {
 /* -------------------------------------------------------------------- */
@@ -215,27 +226,27 @@ static int OGR2KMLGeometryAppend( OGRGeometry *poGeometry,
 /* -------------------------------------------------------------------- */
     if( poGeometry->getGeometryType() == wkbPoint )
     {
-        char szCoordinate[256] = { 0 };
         OGRPoint* poPoint = static_cast<OGRPoint*>(poGeometry);
 
         if (poPoint->getCoordinateDimension() == 0)
         {
-            _GrowBuffer( *pnLength + 10, 
+            _GrowBuffer( *pnLength + 10,
                      ppszText, pnMaxLength );
             strcat( *ppszText + *pnLength, "<Point/>");
             *pnLength += strlen( *ppszText + *pnLength );
         }
         else
         {
-            MakeKMLCoordinate( szCoordinate, 
+            char szCoordinate[256] = { 0 };
+            MakeKMLCoordinate( szCoordinate, sizeof(szCoordinate),
                             poPoint->getX(), poPoint->getY(), 0.0, FALSE );
 
-            _GrowBuffer( *pnLength + strlen(szCoordinate) + 60, 
-                        ppszText, pnMaxLength );
+            _GrowBuffer( *pnLength + strlen(szCoordinate) + 60,
+                         ppszText, pnMaxLength );
 
-            sprintf( *ppszText + *pnLength, 
-                    "<Point><coordinates>%s</coordinates></Point>",
-                    szCoordinate );
+            snprintf( *ppszText + *pnLength, *pnMaxLength - *pnLength,
+                      "<Point><coordinates>%s</coordinates></Point>",
+                      szCoordinate );
 
             *pnLength += strlen( *ppszText + *pnLength );
         }
@@ -248,28 +259,28 @@ static int OGR2KMLGeometryAppend( OGRGeometry *poGeometry,
         char szCoordinate[256] = { 0 };
         OGRPoint *poPoint = static_cast<OGRPoint*>(poGeometry);
 
-        MakeKMLCoordinate( szCoordinate, 
-                           poPoint->getX(), poPoint->getY(), poPoint->getZ(), 
-                           TRUE );
-                           
-        if (NULL == szAltitudeMode) 
-        { 
-            _GrowBuffer( *pnLength + strlen(szCoordinate) + 70, 
+        MakeKMLCoordinate( szCoordinate, sizeof(szCoordinate),
+                           poPoint->getX(), poPoint->getY(), poPoint->getZ(),
+                           true );
+
+        if (NULL == szAltitudeMode)
+        {
+            _GrowBuffer( *pnLength + strlen(szCoordinate) + 70,
                          ppszText, pnMaxLength );
 
-            sprintf( *ppszText + *pnLength,  
-                     "<Point><coordinates>%s</coordinates></Point>",
-                     szCoordinate );
+            snprintf( *ppszText + *pnLength, *pnMaxLength - *pnLength,
+                      "<Point><coordinates>%s</coordinates></Point>",
+                      szCoordinate );
         }
         else
-        { 
-            _GrowBuffer( *pnLength + strlen(szCoordinate) 
-                         + strlen(szAltitudeMode) + 70, 
+        {
+            _GrowBuffer( *pnLength + strlen(szCoordinate)
+                         + strlen(szAltitudeMode) + 70,
                          ppszText, pnMaxLength );
 
-            sprintf( *ppszText + *pnLength,  
-                     "<Point>%s<coordinates>%s</coordinates></Point>", 
-                     szAltitudeMode, szCoordinate ); 
+            snprintf( *ppszText + *pnLength, *pnMaxLength - *pnLength,
+                      "<Point>%s<coordinates>%s</coordinates></Point>",
+                      szAltitudeMode, szCoordinate );
         }
 
         *pnLength += strlen( *ppszText + *pnLength );
@@ -277,10 +288,10 @@ static int OGR2KMLGeometryAppend( OGRGeometry *poGeometry,
 /* -------------------------------------------------------------------- */
 /*      LineString and LinearRing                                       */
 /* -------------------------------------------------------------------- */
-    else if( poGeometry->getGeometryType() == wkbLineString 
+    else if( poGeometry->getGeometryType() == wkbLineString
              || poGeometry->getGeometryType() == wkbLineString25D )
     {
-        int bRing = EQUAL(poGeometry->getGeometryName(),"LINEARRING");
+        const bool bRing = EQUAL(poGeometry->getGeometryName(),"LINEARRING");
 
         if( bRing )
             AppendString( ppszText, pnLength, pnMaxLength,
@@ -289,14 +300,14 @@ static int OGR2KMLGeometryAppend( OGRGeometry *poGeometry,
             AppendString( ppszText, pnLength, pnMaxLength,
                           "<LineString>" );
 
-        if (NULL != szAltitudeMode) 
-        { 
-            AppendString( ppszText, pnLength, pnMaxLength, szAltitudeMode); 
+        if (NULL != szAltitudeMode)
+        {
+            AppendString( ppszText, pnLength, pnMaxLength, szAltitudeMode);
         }
 
-        AppendCoordinateList( (OGRLineString *) poGeometry, 
+        AppendCoordinateList( reinterpret_cast<OGRLineString *>(poGeometry),
                               ppszText, pnLength, pnMaxLength );
-        
+
         if( bRing )
             AppendString( ppszText, pnLength, pnMaxLength,
                           "</LinearRing>" );
@@ -308,16 +319,16 @@ static int OGR2KMLGeometryAppend( OGRGeometry *poGeometry,
 /* -------------------------------------------------------------------- */
 /*      Polygon                                                         */
 /* -------------------------------------------------------------------- */
-    else if( poGeometry->getGeometryType() == wkbPolygon 
+    else if( poGeometry->getGeometryType() == wkbPolygon
              || poGeometry->getGeometryType() == wkbPolygon25D )
     {
         OGRPolygon* poPolygon = static_cast<OGRPolygon*>(poGeometry);
 
         AppendString( ppszText, pnLength, pnMaxLength, "<Polygon>" );
 
-        if (NULL != szAltitudeMode) 
-        { 
-            AppendString( ppszText, pnLength, pnMaxLength, szAltitudeMode); 
+        if (NULL != szAltitudeMode)
+        {
+            AppendString( ppszText, pnLength, pnMaxLength, szAltitudeMode);
         }
 
         if( poPolygon->getExteriorRing() != NULL )
@@ -325,10 +336,11 @@ static int OGR2KMLGeometryAppend( OGRGeometry *poGeometry,
             AppendString( ppszText, pnLength, pnMaxLength,
                           "<outerBoundaryIs>" );
 
-            if( !OGR2KMLGeometryAppend( poPolygon->getExteriorRing(), 
-                                        ppszText, pnLength, pnMaxLength, szAltitudeMode ) )
+            if( !OGR2KMLGeometryAppend( poPolygon->getExteriorRing(),
+                                        ppszText, pnLength, pnMaxLength,
+                                        szAltitudeMode ) )
             {
-                return FALSE;
+                return false;
             }
             AppendString( ppszText, pnLength, pnMaxLength,
                           "</outerBoundaryIs>" );
@@ -340,11 +352,11 @@ static int OGR2KMLGeometryAppend( OGRGeometry *poGeometry,
 
             AppendString( ppszText, pnLength, pnMaxLength,
                           "<innerBoundaryIs>" );
-            
-            if( !OGR2KMLGeometryAppend( poRing, ppszText, pnLength, 
+
+            if( !OGR2KMLGeometryAppend( poRing, ppszText, pnLength,
                                         pnMaxLength, szAltitudeMode ) )
             {
-                return FALSE;
+                return false;
             }
             AppendString( ppszText, pnLength, pnMaxLength,
                           "</innerBoundaryIs>" );
@@ -357,10 +369,11 @@ static int OGR2KMLGeometryAppend( OGRGeometry *poGeometry,
 /* -------------------------------------------------------------------- */
 /*      MultiPolygon                                                    */
 /* -------------------------------------------------------------------- */
-    else if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPolygon 
+    else if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPolygon
              || wkbFlatten(poGeometry->getGeometryType()) == wkbMultiLineString
              || wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPoint
-             || wkbFlatten(poGeometry->getGeometryType()) == wkbGeometryCollection )
+             || wkbFlatten(poGeometry->getGeometryType()) ==
+                wkbGeometryCollection )
     {
         OGRGeometryCollection* poGC = NULL;
         poGC = static_cast<OGRGeometryCollection*>(poGeometry);
@@ -368,29 +381,30 @@ static int OGR2KMLGeometryAppend( OGRGeometry *poGeometry,
         AppendString( ppszText, pnLength, pnMaxLength, "<MultiGeometry>" );
 
         // XXX - mloskot
-        //if (NULL != szAltitudeMode) 
-        //{ 
-        //    AppendString( ppszText, pnLength, pnMaxLength, szAltitudeMode); 
+        //if (NULL != szAltitudeMode)
+        //{
+        //    AppendString( ppszText, pnLength, pnMaxLength, szAltitudeMode);
         //}
 
         for( int iMember = 0; iMember < poGC->getNumGeometries(); iMember++)
         {
             OGRGeometry *poMember = poGC->getGeometryRef( iMember );
 
-            if( !OGR2KMLGeometryAppend( poMember, ppszText, pnLength, pnMaxLength, szAltitudeMode ) )
+            if( !OGR2KMLGeometryAppend( poMember, ppszText, pnLength,
+                                        pnMaxLength, szAltitudeMode ) )
             {
-                return FALSE;
+                return false;
             }
         }
 
-		AppendString( ppszText, pnLength, pnMaxLength, "</MultiGeometry>" );
+        AppendString( ppszText, pnLength, pnMaxLength, "</MultiGeometry>" );
     }
     else
     {
-        return FALSE;
+        return false;
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -399,38 +413,36 @@ static int OGR2KMLGeometryAppend( OGRGeometry *poGeometry,
 /*      Export the envelope of a geometry as a KML:Box.                 */
 /************************************************************************/
 
+#if 0
 CPLXMLNode* OGR_G_ExportEnvelopeToKMLTree( OGRGeometryH hGeometry )
 {
     VALIDATE_POINTER1( hGeometry, "OGR_G_ExportEnvelopeToKMLTree", NULL );
 
-    CPLXMLNode* psBox = NULL;
-    CPLXMLNode* psCoord = NULL;
     OGREnvelope sEnvelope;
-    char szCoordinate[256] = { 0 };
-    char* pszY = NULL;
 
     memset( &sEnvelope, 0, sizeof(sEnvelope) );
     ((OGRGeometry*)(hGeometry))->getEnvelope( &sEnvelope );
 
-    if( sEnvelope.MinX == 0 && sEnvelope.MaxX == 0 
+    if( sEnvelope.MinX == 0 && sEnvelope.MaxX == 0
         && sEnvelope.MaxX == 0 && sEnvelope.MaxY == 0 )
     {
-        /* there is apparently a special way of representing a null box
+        /* There is apparently a special way of representing a null box
            geometry ... we should use it here eventually. */
 
         return NULL;
     }
 
-    psBox = CPLCreateXMLNode( NULL, CXT_Element, "Box" );
+    CPLXMLNode* psBox = CPLCreateXMLNode( NULL, CXT_Element, "Box" );
 
 /* -------------------------------------------------------------------- */
 /*      Add minxy coordinate.                                           */
 /* -------------------------------------------------------------------- */
-    psCoord = CPLCreateXMLNode( psBox, CXT_Element, "coord" );
-    
-    MakeKMLCoordinate( szCoordinate, sEnvelope.MinX, sEnvelope.MinY, 0.0, 
+    CPLXMLNode* psCoord = CPLCreateXMLNode( psBox, CXT_Element, "coord" );
+
+    char szCoordinate[256] = { 0 };
+    MakeKMLCoordinate( szCoordinate, sEnvelope.MinX, sEnvelope.MinY, 0.0,
                        FALSE );
-    pszY = strstr(szCoordinate,",") + 1;
+    char* pszY = strstr(szCoordinate,",") + 1;
     pszY[-1] = '\0';
 
     CPLCreateXMLElementAndValue( psCoord, "X", szCoordinate );
@@ -440,8 +452,8 @@ CPLXMLNode* OGR_G_ExportEnvelopeToKMLTree( OGRGeometryH hGeometry )
 /*      Add maxxy coordinate.                                           */
 /* -------------------------------------------------------------------- */
     psCoord = CPLCreateXMLNode( psBox, CXT_Element, "coord" );
-    
-    MakeKMLCoordinate( szCoordinate, sEnvelope.MaxX, sEnvelope.MaxY, 0.0, 
+
+    MakeKMLCoordinate( szCoordinate, sEnvelope.MaxX, sEnvelope.MaxY, 0.0,
                        FALSE );
     pszY = strstr(szCoordinate,",") + 1;
     pszY[-1] = '\0';
@@ -451,6 +463,7 @@ CPLXMLNode* OGR_G_ExportEnvelopeToKMLTree( OGRGeometryH hGeometry )
 
     return psBox;
 }
+#endif
 
 /************************************************************************/
 /*                         OGR_G_ExportToKML()                          */
@@ -470,34 +483,35 @@ CPLXMLNode* OGR_G_ExportEnvelopeToKMLTree( OGRGeometryH hGeometry )
 
 char *OGR_G_ExportToKML( OGRGeometryH hGeometry, const char *pszAltitudeMode )
 {
-    char* pszText = NULL;
-    int nLength = 0;
-    int nMaxLength = 1;
-    char szAltitudeMode[128]; 
+    char szAltitudeMode[128];
 
-    // TODO - mloskot: Shouldn't we use VALIDATE_POINTER1 here?
+    // TODO - mloskot: Should we use VALIDATE_POINTER1 here?
     if( hGeometry == NULL )
         return CPLStrdup( "" );
 
-    pszText = (char *) CPLMalloc(nMaxLength);
+    size_t nMaxLength = 1;
+    char* pszText = static_cast<char *>(CPLMalloc(nMaxLength));
     pszText[0] = '\0';
 
     if (NULL != pszAltitudeMode && strlen(pszAltitudeMode) < 128 - (29 + 1))
     {
-        sprintf(szAltitudeMode, "<altitudeMode>%s</altitudeMode>", pszAltitudeMode); 
+        snprintf( szAltitudeMode, sizeof(szAltitudeMode),
+                  "<altitudeMode>%s</altitudeMode>", pszAltitudeMode);
     }
-    else 
+    else
     {
-        szAltitudeMode[0] = 0; 
+        szAltitudeMode[0] = 0;
     }
 
-    if( !OGR2KMLGeometryAppend( (OGRGeometry *) hGeometry, &pszText, 
-                                &nLength, &nMaxLength, szAltitudeMode ))
+    size_t nLength = 0;
+    if( !OGR2KMLGeometryAppend(
+        reinterpret_cast<OGRGeometry *>(hGeometry), &pszText,
+        &nLength, &nMaxLength, szAltitudeMode ) )
     {
         CPLFree( pszText );
         return NULL;
     }
-    
+
     return pszText;
 }
 
@@ -505,21 +519,19 @@ char *OGR_G_ExportToKML( OGRGeometryH hGeometry, const char *pszAltitudeMode )
 /*                       OGR_G_ExportToKMLTree()                        */
 /************************************************************************/
 
+#if 0
 CPLXMLNode *OGR_G_ExportToKMLTree( OGRGeometryH hGeometry )
 {
-    char        *pszText = NULL;
-    CPLXMLNode  *psTree = NULL;
-
     // TODO - mloskot: If passed geometry is null the pszText is non-null,
     // so the condition below is false.
-    pszText = OGR_G_ExportToKML( hGeometry, NULL );
+    char *pszText = OGR_G_ExportToKML( hGeometry, NULL );
     if( pszText == NULL )
         return NULL;
 
-    psTree = CPLParseXMLString( pszText );
+    CPLXMLNode *psTree = CPLParseXMLString( pszText );
 
     CPLFree( pszText );
 
     return psTree;
 }
-
+#endif
diff --git a/ogr/ogrsf_frmts/kml/ogr_kml.h b/ogr/ogrsf_frmts/kml/ogr_kml.h
index 98a3110..5f9ea11 100644
--- a/ogr/ogrsf_frmts/kml/ogr_kml.h
+++ b/ogr/ogrsf_frmts/kml/ogr_kml.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_kml.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogr_kml.h 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  KML Driver
  * Purpose:  Declarations for OGR wrapper classes for KML, and OGR->KML
@@ -49,9 +49,9 @@ class OGRKMLLayer : public OGRLayer
 {
 public:
 
-    OGRKMLLayer( const char* pszName_, 
-                 OGRSpatialReference* poSRS, 
-                 int bWriter,
+    OGRKMLLayer( const char* pszName_,
+                 OGRSpatialReference* poSRS,
+                 bool bWriter,
                  OGRwkbGeometryType eType,
                  OGRKMLDataSource* poDS );
     ~OGRKMLLayer();
@@ -72,8 +72,8 @@ public:
     //
     void SetLayerNumber( int nLayer );
 
-    void SetClosedForWriting() { bClosedForWriting = TRUE; }
-    
+    void SetClosedForWriting() { bClosedForWriting = true; }
+
     CPLString WriteSchema();
 
 private:
@@ -82,16 +82,16 @@ private:
     OGRKMLDataSource* poDS_;
     OGRSpatialReference* poSRS_;
 	OGRCoordinateTransformation *poCT_;
-	
+
     OGRFeatureDefn* poFeatureDefn_;
 
     int iNextKMLId_;
     int nTotalKMLCount_;
-    int bWriter_;
+    bool bWriter_;
     int nLayerNumber_;
     int nWroteFeatureCount_;
-    int bSchemaWritten_;
-    int bClosedForWriting;
+    bool bSchemaWritten_;
+    bool bClosedForWriting;
     char* pszName_;
 
     int nLastAsked;
@@ -120,11 +120,11 @@ public:
                            OGRwkbGeometryType eGType = wkbUnknown,
                            char** papszOptions = NULL );
     int TestCapability( const char* pszCap );
-    
+
     //
     // OGRKMLDataSource Interface
     //
-    int Create( const char* pszName, char** papszOptions );    
+    int Create( const char* pszName, char** papszOptions );
     const char* GetNameField() const { return pszNameField_; }
     const char* GetDescriptionField() const { return pszDescriptionField_; }
     const char* GetAltitudeMode() { return pszAltitudeMode_; }
@@ -134,7 +134,7 @@ public:
     KML* GetKMLFile() { return poKMLFile_; };
 #endif
 
-	bool IsFirstCTError() { return !bIssuedCTError_; }
+	bool IsFirstCTError() const { return !bIssuedCTError_; }
 	void IssuedFirstCTError() { bIssuedCTError_ = true; }
 
 private:
@@ -152,19 +152,18 @@ private:
     char* pszNameField_;
     char* pszDescriptionField_;
 
-    //The KML altitude mode to use 
- 	char* pszAltitudeMode_; 
+    //The KML altitude mode to use
+ 	char* pszAltitudeMode_;
 
     char** papszCreateOptions_;
 
-    // output related parameters 
+    // output related parameters
     VSILFILE* fpOutput_;
 
     OGREnvelope oEnvelope_;
-	
+
 	//Have we issued a coordinate transformation already for this datasource
-	bool bIssuedCTError_;		
+	bool bIssuedCTError_;
 };
 
 #endif /* OGR_KML_H_INCLUDED */
-
diff --git a/ogr/ogrsf_frmts/kml/ogrkmldatasource.cpp b/ogr/ogrsf_frmts/kml/ogrkmldatasource.cpp
index cfcec7f..81d3116 100644
--- a/ogr/ogrsf_frmts/kml/ogrkmldatasource.cpp
+++ b/ogr/ogrsf_frmts/kml/ogrkmldatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrkmldatasource.cpp 27959 2014-11-14 18:29:21Z rouault $
+ * $Id: ogrkmldatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  KML Driver
  * Purpose:  Implementation of OGRKMLDataSource class.
@@ -47,11 +47,11 @@ OGRKMLDataSource::OGRKMLDataSource()
     pszAltitudeMode_ = NULL;
     papoLayers_ = NULL;
     nLayers_ = 0;
-    
+
     fpOutput_ = NULL;
 
     papszCreateOptions_ = NULL;
-	
+
 	bIssuedCTError_ = false;
 
 #ifdef HAVE_EXPAT
@@ -104,7 +104,7 @@ OGRKMLDataSource::~OGRKMLDataSource()
 
     CPLFree( papoLayers_ );
 
-#ifdef HAVE_EXPAT    
+#ifdef HAVE_EXPAT
     delete poKMLFile_;
 #endif
 }
@@ -230,7 +230,7 @@ int OGRKMLDataSource::Open( const char * pszNewName, int bTestOpen )
             poGeotype = wkbGeometryCollection;
         else
             poGeotype = wkbUnknown;
-        
+
         if (poGeotype != wkbUnknown && poKMLFile_->is25D())
             poGeotype = wkbSetZ(poGeotype);
 
@@ -244,7 +244,7 @@ int OGRKMLDataSource::Open( const char * pszNewName, int bTestOpen )
             sName.Printf( "Layer #%d", nCount );
         }
 
-        poLayer = new OGRKMLLayer( sName.c_str(), poSRS, FALSE, poGeotype, this );
+        poLayer = new OGRKMLLayer( sName.c_str(), poSRS, false, poGeotype, this );
 
         poLayer->SetLayerNumber( nCount );
 
@@ -253,10 +253,10 @@ int OGRKMLDataSource::Open( const char * pszNewName, int bTestOpen )
 /* -------------------------------------------------------------------- */
         papoLayers_[nCount] = poLayer;
     }
-    
+
     poSRS->Release();
-    
-    return TRUE;	
+
+    return TRUE;
 }
 #endif /* HAVE_EXPAT */
 
@@ -278,48 +278,48 @@ int OGRKMLDataSource::Create( const char* pszName, char** papszOptions )
         pszNameField_ = CPLStrdup(CSLFetchNameValue(papszOptions, "NameField"));
     else
         pszNameField_ = CPLStrdup("Name");
-    
+
     if (CSLFetchNameValue(papszOptions, "DescriptionField"))
         pszDescriptionField_ = CPLStrdup(CSLFetchNameValue(papszOptions, "DescriptionField"));
     else
         pszDescriptionField_ = CPLStrdup("Description");
 
-    pszAltitudeMode_ = CPLStrdup(CSLFetchNameValue(papszOptions, "AltitudeMode")); 
-    if( (NULL != pszAltitudeMode_) && strlen(pszAltitudeMode_) > 0) 
+    pszAltitudeMode_ = CPLStrdup(CSLFetchNameValue(papszOptions, "AltitudeMode"));
+    if( (NULL != pszAltitudeMode_) && strlen(pszAltitudeMode_) > 0)
     {
-        //Check to see that the specified AltitudeMode is valid 
+        //Check to see that the specified AltitudeMode is valid
         if ( EQUAL(pszAltitudeMode_, "clampToGround")
              || EQUAL(pszAltitudeMode_, "relativeToGround")
-             || EQUAL(pszAltitudeMode_, "absolute")) 
-        { 
-            CPLDebug("KML", "Using '%s' for AltitudeMode", pszAltitudeMode_); 
-        } 
-        else 
-        { 
-            CPLFree( pszAltitudeMode_ ); 
-            pszAltitudeMode_ = NULL; 
-            CPLError( CE_Warning, CPLE_AppDefined, "Invalide AltitideMode specified, ignoring" );  
-        } 
-    } 
-    else 
-    { 
-        CPLFree( pszAltitudeMode_ ); 
-        pszAltitudeMode_ = NULL; 
-    } 
-    
+             || EQUAL(pszAltitudeMode_, "absolute"))
+        {
+            CPLDebug("KML", "Using '%s' for AltitudeMode", pszAltitudeMode_);
+        }
+        else
+        {
+            CPLFree( pszAltitudeMode_ );
+            pszAltitudeMode_ = NULL;
+            CPLError( CE_Warning, CPLE_AppDefined, "Invalide AltitideMode specified, ignoring" );
+        }
+    }
+    else
+    {
+        CPLFree( pszAltitudeMode_ );
+        pszAltitudeMode_ = NULL;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Create the output file.                                         */
 /* -------------------------------------------------------------------- */
 
     if (strcmp(pszName, "/dev/stdout") == 0)
         pszName = "/vsistdout/";
-    
+
     pszName_ = CPLStrdup( pszName );
 
     fpOutput_ = VSIFOpenL( pszName, "wb" );
     if( fpOutput_ == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "Failed to create KML file %s.", pszName );
         return FALSE;
     }
@@ -327,8 +327,8 @@ int OGRKMLDataSource::Create( const char* pszName, char** papszOptions )
 /* -------------------------------------------------------------------- */
 /*      Write out "standard" header.                                    */
 /* -------------------------------------------------------------------- */
-    VSIFPrintfL( fpOutput_, "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" );	
-    
+    VSIFPrintfL( fpOutput_, "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" );
+
     VSIFPrintfL( fpOutput_, "<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n<Document id=\"root_doc\">\n" );
 
     return TRUE;
@@ -370,9 +370,9 @@ OGRKMLDataSource::ICreateLayer( const char * pszLayerName,
         }
 
         VSIFPrintfL( fpOutput_, "</Folder>\n");
-        ((OGRKMLLayer*)GetLayer(GetLayerCount()-1))->SetClosedForWriting();
+        ((OGRKMLLayer*)papoLayers_[GetLayerCount()-1])->SetClosedForWriting();
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Ensure name is safe as an element name.                         */
 /* -------------------------------------------------------------------- */
@@ -381,22 +381,22 @@ OGRKMLDataSource::ICreateLayer( const char * pszLayerName,
     CPLCleanXMLElementName( pszCleanLayerName );
     if( strcmp(pszCleanLayerName, pszLayerName) != 0 )
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "Layer name '%s' adjusted to '%s' for XML validity.",
                   pszLayerName, pszCleanLayerName );
     }
-    
+
     if (GetLayerCount() > 0)
     {
         VSIFPrintfL( fpOutput_, "<Folder><name>%s</name>\n", pszCleanLayerName);
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create the layer object.                                        */
 /* -------------------------------------------------------------------- */
     OGRKMLLayer *poLayer;
-    poLayer = new OGRKMLLayer( pszCleanLayerName, poSRS, TRUE, eType, this );
-    
+    poLayer = new OGRKMLLayer( pszCleanLayerName, poSRS, true, eType, this );
+
     CPLFree( pszCleanLayerName );
 
 /* -------------------------------------------------------------------- */
@@ -404,7 +404,7 @@ OGRKMLDataSource::ICreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
     papoLayers_ = (OGRKMLLayer **)
         CPLRealloc( papoLayers_,  sizeof(OGRKMLLayer *) * (nLayers_+1) );
-    
+
     papoLayers_[nLayers_++] = poLayer;
 
     return poLayer;
diff --git a/ogr/ogrsf_frmts/kml/ogrkmldriver.cpp b/ogr/ogrsf_frmts/kml/ogrkmldriver.cpp
index b46b29e..0661af3 100644
--- a/ogr/ogrsf_frmts/kml/ogrkmldriver.cpp
+++ b/ogr/ogrsf_frmts/kml/ogrkmldriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrkmldriver.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrkmldriver.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  KML Driver
  * Purpose:  Implementation of OGRKMLDriver class.
@@ -28,9 +28,10 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#include "ogr_kml.h"
+
 #include "cpl_conv.h"
 #include "cpl_error.h"
+#include "ogr_kml.h"
 
 /************************************************************************/
 /*                         OGRKMLDriverIdentify()                       */
@@ -58,16 +59,14 @@ static GDALDataset *OGRKMLDriverOpen( GDALOpenInfo* poOpenInfo )
     if( !OGRKMLDriverIdentify(poOpenInfo) )
         return NULL;
 
-    OGRKMLDataSource* poDS = NULL;
-
 #ifdef HAVE_EXPAT
-    poDS = new OGRKMLDataSource();
+    OGRKMLDataSource* poDS = new OGRKMLDataSource();
 
     if( poDS->Open( poOpenInfo->pszFilename, TRUE ) )
     {
         /*if( poDS->GetLayerCount() == 0 )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
+            CPLError( CE_Failure, CPLE_OpenFailed,
                 "No layers in KML file: %s.", pszName );
 
             delete poDS;
@@ -79,9 +78,11 @@ static GDALDataset *OGRKMLDriverOpen( GDALOpenInfo* poOpenInfo )
         delete poDS;
         poDS = NULL;
     }
-#endif
 
     return poDS;
+#else
+    return NULL;
+#endif
 }
 
 /************************************************************************/
@@ -89,10 +90,10 @@ static GDALDataset *OGRKMLDriverOpen( GDALOpenInfo* poOpenInfo )
 /************************************************************************/
 
 static GDALDataset *OGRKMLDriverCreate( const char * pszName,
-                                        CPL_UNUSED int nBands,
-                                        CPL_UNUSED int nXSize,
-                                        CPL_UNUSED int nYSize,
-                                        CPL_UNUSED GDALDataType eDT,
+                                        int /* nBands */,
+                                        int /* nXSize */ ,
+                                        int /* nYSize */,
+                                        GDALDataType /* eDT */,
                                         char **papszOptions )
 {
     CPLAssert( NULL != pszName );
@@ -115,21 +116,19 @@ static GDALDataset *OGRKMLDriverCreate( const char * pszName,
 
 void RegisterOGRKML()
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "KML" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "KML" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "KML" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Keyhole Markup Language (KML)" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "kml" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_kml.html" );
+    poDriver->SetDescription( "KML" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Keyhole Markup Language (KML)" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "kml" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_kml.html" );
 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "  <Option name='GPX_USE_EXTENSIONS' type='boolean' description='Whether to write non-GPX attributes in an <extensions> tag' default='NO'/>"
 "  <Option name='NameField' type='string' description='Field to use to fill the KML <name> element' default='Name'/>"
@@ -141,16 +140,15 @@ void RegisterOGRKML()
 "  </Option>"
 "</CreationOptionList>");
 
-        poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST, "<LayerCreationOptionList/>" );
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+                               "<LayerCreationOptionList/>" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
+                               "Integer Real String" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-        
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES, "Integer Real String" );
+    poDriver->pfnOpen = OGRKMLDriverOpen;
+    poDriver->pfnIdentify = OGRKMLDriverIdentify;
+    poDriver->pfnCreate = OGRKMLDriverCreate;
 
-        poDriver->pfnOpen = OGRKMLDriverOpen;
-        poDriver->pfnIdentify = OGRKMLDriverIdentify;
-        poDriver->pfnCreate = OGRKMLDriverCreate;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/kml/ogrkmllayer.cpp b/ogr/ogrsf_frmts/kml/ogrkmllayer.cpp
index 05603bb..7e9d661 100644
--- a/ogr/ogrsf_frmts/kml/ogrkmllayer.cpp
+++ b/ogr/ogrsf_frmts/kml/ogrkmllayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrkmllayer.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrkmllayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  KML Driver
  * Purpose:  Implementation of OGRKMLLayer class.
@@ -29,10 +29,10 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_kml.h"
-#include "ogr_api.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "ogr_api.h"
+#include "ogr_kml.h"
 #include "ogr_p.h"
 
 /* Function utility to dump OGRGeometry to KML text. */
@@ -43,16 +43,26 @@ char *OGR_G_ExportToKML( OGRGeometryH hGeometry, const char* pszAltitudeMode );
 /************************************************************************/
 
 OGRKMLLayer::OGRKMLLayer( const char * pszName,
-                          OGRSpatialReference *poSRSIn, int bWriterIn,
+                          OGRSpatialReference *poSRSIn, bool bWriterIn,
                           OGRwkbGeometryType eReqType,
-                          OGRKMLDataSource *poDSIn )
-{    	
-    poCT_ = NULL;
+                          OGRKMLDataSource *poDSIn ) :
+    poDS_(NULL),
+    poSRS_(NULL),
+    poCT_(NULL),
+    iNextKMLId_(0),
+    nTotalKMLCount_(-1),
+    bWriter_(bWriterIn),
+    nLayerNumber_(0),
+    nWroteFeatureCount_(0),
+    bSchemaWritten_(FALSE),
+    nLastAsked(-1),
+    nLastCount(-1)
+{
 
     /* KML should be created as WGS84. */
     if( poSRSIn != NULL )
     {
-        poSRS_ = new OGRSpatialReference(NULL);   
+        poSRS_ = new OGRSpatialReference(NULL);
         poSRS_->SetWellKnownGeogCS( "WGS84" );
         if (!poSRS_->IsSame(poSRSIn))
         {
@@ -68,29 +78,20 @@ OGRKMLLayer::OGRKMLLayer( const char * pszName,
                         "Failed to create coordinate transformation between the\n"
                         "input coordinate system and WGS84.  This may be because they\n"
                         "are not transformable, or because projection services\n"
-                        "(PROJ.4 DLL/.so) could not be loaded.\n" 
+                        "(PROJ.4 DLL/.so) could not be loaded.\n"
                         "KML geometries may not render correctly.\n"
                         "This message will not be issued any more. \n"
-                        "\nSource:\n%s\n", 
+                        "\nSource:\n%s\n",
                         pszWKT );
 
                 CPLFree( pszWKT );
-                poDSIn->IssuedFirstCTError(); 
+                poDSIn->IssuedFirstCTError();
             }
         }
     }
-    else
-    {
-        poSRS_ = NULL;
-    }
-
-    iNextKMLId_ = 0;
-    nTotalKMLCount_ = -1;
-    nLastAsked = -1;
-    nLastCount = -1;
 
     poDS_ = poDSIn;
-    
+
     poFeatureDefn_ = new OGRFeatureDefn( pszName );
     SetDescription( poFeatureDefn_->GetName() );
     poFeatureDefn_->Reference();
@@ -100,14 +101,11 @@ OGRKMLLayer::OGRKMLLayer( const char * pszName,
 
     OGRFieldDefn oFieldName( "Name", OFTString );
     poFeatureDefn_->AddFieldDefn( &oFieldName );
-    
+
     OGRFieldDefn oFieldDesc( "Description", OFTString );
     poFeatureDefn_->AddFieldDefn( &oFieldDesc );
 
-    bWriter_ = bWriterIn;
-    nWroteFeatureCount_ = 0;
     bClosedForWriting = (bWriterIn == FALSE);
-    bSchemaWritten_ = FALSE;
 
     pszName_ = CPLStrdup(pszName);
 }
@@ -123,10 +121,10 @@ OGRKMLLayer::~OGRKMLLayer()
 
     if( NULL != poSRS_ )
         poSRS_->Release();
-	
+
     if( NULL != poCT_ )
         delete poCT_;
-	
+
     CPLFree( pszName_ );
 }
 
@@ -145,7 +143,7 @@ OGRFeatureDefn* OGRKMLLayer::GetLayerDefn()
 
 void OGRKMLLayer::ResetReading()
 {
-    iNextKMLId_ = 0;    
+    iNextKMLId_ = 0;
     nLastAsked = -1;
     nLastCount = -1;
 }
@@ -167,37 +165,37 @@ OGRFeature *OGRKMLLayer::GetNextFeature()
         return NULL;
     poKMLFile->selectLayer(nLayerNumber_);
 
-    while(TRUE)
+    while( true )
     {
         Feature *poFeatureKML = NULL;
         poFeatureKML = poKMLFile->getFeature(iNextKMLId_++, nLastAsked, nLastCount);
-    
+
         if(poFeatureKML == NULL)
             return NULL;
-    
+
         CPLAssert( poFeatureKML != NULL );
-    
+
         OGRFeature *poFeature = new OGRFeature( poFeatureDefn_ );
-        
+
         if(poFeatureKML->poGeom)
         {
             poFeature->SetGeometryDirectly(poFeatureKML->poGeom);
             poFeatureKML->poGeom = NULL;
         }
-    
+
         // Add fields
         poFeature->SetField( poFeatureDefn_->GetFieldIndex("Name"), poFeatureKML->sName.c_str() );
         poFeature->SetField( poFeatureDefn_->GetFieldIndex("Description"), poFeatureKML->sDescription.c_str() );
         poFeature->SetFID( iNextKMLId_ - 1 );
-    
+
         // Clean up
         delete poFeatureKML;
-    
+
         if( poFeature->GetGeometryRef() != NULL && poSRS_ != NULL)
         {
             poFeature->GetGeometryRef()->assignSpatialReference( poSRS_ );
         }
-    
+
         /* Check spatial/attribute filters */
         if ((m_poFilterGeom == NULL || FilterGeometry( poFeature->GetGeometryRef() ) ) &&
             (m_poAttrQuery == NULL || m_poAttrQuery->Evaluate( poFeature )) )
@@ -301,11 +299,11 @@ CPLString OGRKMLLayer::WriteSchema()
                 pszKMLEltName = "SimpleArrayField";
                 break;
                 //TODO: KML doesn't handle these data types yet...
-              case OFTDate:                
-              case OFTTime:                
+              case OFTDate:
+              case OFTTime:
               case OFTDateTime:
                 pszKMLType = "string";
-                pszKMLEltName = "SimpleField";                
+                pszKMLEltName = "SimpleField";
                 break;
 
               default:
@@ -313,7 +311,7 @@ CPLString OGRKMLLayer::WriteSchema()
                 pszKMLEltName = "SimpleField";
                 break;
             }
-            osRet += CPLSPrintf( "\t<%s name=\"%s\" type=\"%s\"></%s>\n", 
+            osRet += CPLSPrintf( "\t<%s name=\"%s\" type=\"%s\"></%s>\n",
                         pszKMLEltName, fieldDefinition->GetNameRef() ,pszKMLType, pszKMLEltName );
         }
         if( osRet.size() )
@@ -363,12 +361,12 @@ OGRErr OGRKMLLayer::ICreateFeature( OGRFeature* poFeature )
     if (NULL != poDS_->GetNameField())
     {
         for( int iField = 0; iField < poFeatureDefn_->GetFieldCount(); iField++ )
-        {        
+        {
             OGRFieldDefn *poField = poFeatureDefn_->GetFieldDefn( iField );
 
             if( poFeature->IsFieldSet( iField )
                 && EQUAL(poField->GetNameRef(), poDS_->GetNameField()) )
-            {           
+            {
                 const char *pszRaw = poFeature->GetFieldAsString( iField );
                 while( *pszRaw == ' ' )
                     pszRaw++;
@@ -384,12 +382,12 @@ OGRErr OGRKMLLayer::ICreateFeature( OGRFeature* poFeature )
     if (NULL != poDS_->GetDescriptionField())
     {
         for( int iField = 0; iField < poFeatureDefn_->GetFieldCount(); iField++ )
-        {        
+        {
             OGRFieldDefn *poField = poFeatureDefn_->GetFieldDefn( iField );
 
             if( poFeature->IsFieldSet( iField )
                 && EQUAL(poField->GetNameRef(), poDS_->GetDescriptionField()) )
-            {           
+            {
                 const char *pszRaw = poFeature->GetFieldAsString( iField );
                 while( *pszRaw == ' ' )
                     pszRaw++;
@@ -444,7 +442,7 @@ OGRErr OGRKMLLayer::ICreateFeature( OGRFeature* poFeature )
             else
                 bHasWidth = TRUE;
             const char* pszColor = poPen->Color(bDefault);
-            int nColorLen = CPLStrnlen(pszColor, 10);
+            int nColorLen = static_cast<int>(CPLStrnlen(pszColor, 10));
             if( pszColor != NULL && pszColor[0] == '#' && !bDefault && nColorLen >= 7)
             {
                 char acColor[9] = {0};
@@ -498,7 +496,7 @@ OGRErr OGRKMLLayer::ICreateFeature( OGRFeature* poFeature )
                 continue;
 
             if (!bHasFoundOtherField)
-            {                
+            {
                 VSIFPrintfL( fp, "\t<ExtendedData><SchemaData schemaUrl=\"#%s\">\n", pszName_ );
                 bHasFoundOtherField = TRUE;
             }
@@ -517,7 +515,7 @@ OGRErr OGRKMLLayer::ICreateFeature( OGRFeature* poFeature )
                 pszEscaped = OGRGetXML_UTF8_EscapedString( pszRaw );
             }
 
-            VSIFPrintfL( fp, "\t\t<SimpleData name=\"%s\">%s</SimpleData>\n", 
+            VSIFPrintfL( fp, "\t\t<SimpleData name=\"%s\">%s</SimpleData>\n",
                         poField->GetNameRef(), pszEscaped);
 
             CPLFree( pszEscaped );
@@ -534,7 +532,7 @@ OGRErr OGRKMLLayer::ICreateFeature( OGRFeature* poFeature )
     {
         char* pszGeometry = NULL;
         OGREnvelope sGeomBounds;
-        OGRGeometry* poWGS84Geom;	
+        OGRGeometry* poWGS84Geom;
 
         if (NULL != poCT_)
         {
@@ -545,13 +543,13 @@ OGRErr OGRKMLLayer::ICreateFeature( OGRFeature* poFeature )
         {
             poWGS84Geom = poFeature->GetGeometryRef();
         }
-	
+
         // TODO - porting
         // pszGeometry = poFeature->GetGeometryRef()->exportToKML();
-        pszGeometry = 
+        pszGeometry =
             OGR_G_ExportToKML( (OGRGeometryH)poWGS84Geom,
                                poDS_->GetAltitudeMode());
-        
+
         VSIFPrintfL( fp, "      %s\n", pszGeometry );
         CPLFree( pszGeometry );
 
@@ -563,7 +561,7 @@ OGRErr OGRKMLLayer::ICreateFeature( OGRFeature* poFeature )
             delete poWGS84Geom;
         }
     }
-    
+
     VSIFPrintfL( fp, "  </Placemark>\n" );
     nWroteFeatureCount_++;
     return OGRERR_NONE;
@@ -585,8 +583,8 @@ int OGRKMLLayer::TestCapability( const char * pszCap )
     }
     else if( EQUAL(pszCap,OLCFastFeatureCount) )
     {
-//        if( poFClass == NULL 
-//            || m_poFilterGeom != NULL 
+//        if( poFClass == NULL
+//            || m_poFilterGeom != NULL
 //            || m_poAttrQuery != NULL )
             return FALSE;
 
@@ -609,7 +607,7 @@ OGRErr OGRKMLLayer::CreateField( OGRFieldDefn *poField,
     if( !bWriter_ || iNextKMLId_ != 0 )
         return OGRERR_FAILURE;
 
-	OGRFieldDefn oCleanCopy( poField );
+    OGRFieldDefn oCleanCopy( poField );
     poFeatureDefn_->AddFieldDefn( &oCleanCopy );
 
     return OGRERR_NONE;
diff --git a/ogr/ogrsf_frmts/libkml/drv_libkml.html b/ogr/ogrsf_frmts/libkml/drv_libkml.html
index 5177f55..2e4a782 100644
--- a/ogr/ogrsf_frmts/libkml/drv_libkml.html
+++ b/ogr/ogrsf_frmts/libkml/drv_libkml.html
@@ -5,11 +5,11 @@
     <meta http-equiv="content-type" content="text/html; charset=utf-8">
     <title>LIBKML Driver</title>
 </head>
- 
+
 <body bgcolor="#ffffff">
- 
+
   <h1>LIBKML Driver (.kml .kmz)</h1>
-    
+
   <p>
     The LIBKML driver is a client of
     <a href="https://github.com/google/libkml">Libkml</a> from Google, a
@@ -20,13 +20,13 @@
     Note: you need to build libkml from its latest SVN version (libkml 1.2 isn't
     enough).
   </p>
-    
+
   <p>
     Note that if you build and include this LIBKML driver, it will become the
     default reader of KML for ogr, overriding the previous KML driver. You can
-    still specify either KML or LIBKML as the ouput driver via the command line
+    still specify either KML or LIBKML as the output driver via the command line
   </p>
-    
+
   <p>
     Libkml from Google provides reading services for any valid KML file.
     However, please be advised that some KML facilities do not map into the
@@ -37,27 +37,27 @@
     In particular, nesting of feature sets more than one deep will be flattened
     to support ogr's internal format.
   </p>
-  
+
   <h2>Datasource</h2>
-  
+
   <p>
     You may specify a
-    <a href="http://www.gdal.org/ogr/ogr_arch.html#ogr_arch_data_source">datasource </a>
-    as a kml file <code>somefile.kml</code> , 
+    <a href="http://www.gdal.org/ogr_arch.html#ogr_arch_data_source">datasource </a>
+    as a kml file <code>somefile.kml</code> ,
     a directory <code>somedir/</code> , or a kmz file <code>somefile.kmz</code> .
   </p>
-  
+
   <p>
     By default on directory and kmz datasources, an index file of all the
     layers will be read from or written to doc.kml. It contains a
     <a href="https://developers.google.com/kml/documentation/kmlreference#networklink">
     <NetworkLink></a> to each layer file in the datasource. This feature
-    can be turned off by setting the enviroment variable LIBKML_USE_DOC.KML to
+    can be turned off by setting the environment variable LIBKML_USE_DOC.KML to
     "no"
    </p>
-  
+
   <h3>StyleTable</h3>
-  
+
   <p>
     Datasource style tables are written to the
     <a href="https://developers.google.com/kml/documentation/kmlreference#document">
@@ -65,10 +65,10 @@
     in a kmz file, or style.kml in a directory, as one or more
     <a href="https://developers.google.com/kml/documentation/kmlreference#style">
     <Style></a> elements. Not all of
-    <a href="http://www.gdal.org/ogr/ogr_feature_style.html">OGR Feature Style</a>
+    <a href="http://www.gdal.org/ogr_feature_style.html">OGR Feature Style</a>
     can translate into KML.
   </p>
-  
+
   <h3>Datasource creation options</h3>
 
   <p>
@@ -168,30 +168,30 @@
     The DeleteFeature() operation on a layer will be translated as a
     <a href="https://developers.google.com/kml/documentation/kmlreference#delete"><Delete></a> element.<p>
     </p>
- 
+
   <h2>Layer</h2>
-  
+
   <p>
-    <a href="http://www.gdal.org/ogr/ogr_arch.html#ogr_arch_layer">
+    <a href="http://www.gdal.org/ogr_arch.html#ogr_arch_layer">
     Layers</a> are mapped to kml files as a
     <a href="https://developers.google.com/kml/documentation/kmlreference#document">
     <Document></a>
     or
     <a href="https://developers.google.com/kml/documentation/kmlreference#folder">
-    <Folder></a>, and in kmz files or directorys as a seperate kml file.
+    <Folder></a>, and in kmz files or directories as a separate kml file.
   </p>
-  
+
   <h3>Style</h3>
   <p>
-    Layer style tables can not be read from or written to a kml layer that is a 
+    Layer style tables can not be read from or written to a kml layer that is a
     <a href="https://developers.google.com/kml/documentation/kmlreference#folder">
     <Folder></a>, otherwise they are in the
     <a href="https://developers.google.com/kml/documentation/kmlreference#document">
     <Document></a> that is the layer.
   </p>
-  
+
   <h3>Schema</h3>
-  
+
   <p>
     Read and write of
     <a href="https://developers.google.com/kml/documentation/kmlreference#schema">
@@ -271,7 +271,7 @@
     <a href="https://developers.google.com/kml/documentation/kmlreference#document">
     <Document></a> elements. By settings the <b>FOLDER</b> layer creation option
     to YES, it is also possible to write them as <a href="https://developers.google.com/kml/documentation/kmlreference#folder">
-    <Folder></a> elements (only in .kml files). 
+    <Folder></a> elements (only in .kml files).
     </p>
 
     <p>The following layer creation options can be used to set container options :
@@ -297,9 +297,9 @@
     </p>
 
   <h2>Feature</h2>
-  
+
   <p>
-    An OGR <a href="http://www.gdal.org/ogr/ogr_arch.html#ogr_arch_feature">feature</a>
+    An OGR <a href="http://www.gdal.org/ogr_arch.html#ogr_arch_feature">feature</a>
     generally translates to kml as a
     <a href="https://developers.google.com/kml/documentation/kmlreference#placemark">
     <Placemark></a>, and vice-versa.
@@ -310,7 +310,7 @@
   </p>
 
   <p>If the networklink field is defined, a <a href="https://developers.google.com/kml/documentation/kmlreference#networklink">
-    <NetworkLink></a> will be generated. Other networklink_ fields are optional.
+    <NetworkLink></a> will be generated. Other networklink fields are optional.
   </p>
 
   <p>If the photooverlay field is defined, a <a href="https://developers.google.com/kml/documentation/kmlreference#photooverlay">
@@ -331,17 +331,17 @@
   </p>
 
   <p>
-    Starting with OGR 1.10, KML 
+    Starting with OGR 1.10, KML
     <a href="https://developers.google.com/kml/documentation/kmlreference#groundoverlay">
-    <GroundOverlay></a> elements are supported for reading (unless the 
+    <GroundOverlay></a> elements are supported for reading (unless the
     LIBKML_READ_GROUND_OVERLAY configuration option is set to FALSE). For such elements, there
     are icon and drawOrder fields.
   </p>
-  
+
   <h3>Style</h3>
-  
+
   <p>
-    Style Strings at the feature level are Mapped to KML as either a 
+    Style Strings at the feature level are Mapped to KML as either a
     <a href="https://developers.google.com/kml/documentation/kmlreference#style">
     <Style></a> or
     <a href="https://developers.google.com/kml/documentation/kmlreference#styleurl">
@@ -350,24 +350,24 @@
     <Placemark></a>.
   </p>
   <p>
-     When reading a kml feature and the enviroment variable LIBKML_RESOLVE_STYLE
+     When reading a kml feature and the environment variable LIBKML_RESOLVE_STYLE
      is set to yes, styleurls are looked up in the style tables and the features
-     style string is set to the style from the table. This is to allow reading 
+     style string is set to the style from the table. This is to allow reading
      of shared styles by applications, like mapserver, that do not read style
      tables.
   </p>
-  
+
   <p>
-     When reading a kml feature and the enviroment variable LIBKML_EXTERNAL_STYLE
-     is set to yes, a styleurl that is external to the datasource is read from 
+     When reading a kml feature and the environment variable LIBKML_EXTERNAL_STYLE
+     is set to yes, a styleurl that is external to the datasource is read from
      disk or fetched from the server and parsed into the datasource style table.
      If the style kml can not be read or LIBKML_EXTERNAL_STYLE is set to no then
-     the styleurl is copyed to the style string.
+     the styleurl is copied to the style string.
   </p>
-    
+
   <p>
      When reading a kml StyleMap the default mapping is set to normal. If you
-     wish to use the highlighted styles set the enviroment variable
+     wish to use the highlighted styles set the environment variable
      LIBKML_STYLEMAP_KEY to "highlight"
   </p>
 
@@ -378,7 +378,7 @@
   </p>
 
   <h2>Fields</h2>
-  
+
   <p> OGR fields (feature attributes) are mapped to kml with
     <a href="https://developers.google.com/kml/documentation/kmlreference#schema">
     <Schema></a>; and
@@ -394,110 +394,110 @@
 
   <p>
     A rich set of environment variables are available to define how fields in
-    input and output, map to a KML 
+    input and output, map to a KML
     <a href="https://developers.google.com/kml/documentation/kmlreference#placemark">
     <Placemark></a>. For example, if you want a field called 'Cities'
     to map to the
     <a href="https://developers.google.com/kml/documentation/kmlreference#name">
     <name></a>; tag in KML, you can set an
-    environment variable. 
+    environment variable.
   </p>
- 
+
   <dl>
     <dt>Name</dt>
     <dd>
-      This String field maps to the kml tag 
+      This String field maps to the kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#name">
       <name></a>. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_NAME_FIELD .
+      environment variable LIBKML_NAME_FIELD .
     </dd>
     <dt>description</dt>
-    <dd>This String field maps to the kml tag 
+    <dd>This String field maps to the kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#description">
       <description></a>. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_DESCRIPTION_FIELD .
+      environment variable LIBKML_DESCRIPTION_FIELD .
     </dd>
     <dt>timestamp</dt>
-    <dd>This string or datetime or date and/or time field maps to the kml tag 
+    <dd>This string or datetime or date and/or time field maps to the kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#timestamp">
       <timestamp></a>. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_TIMESTAMP_FIELD .
+      environment variable LIBKML_TIMESTAMP_FIELD .
     </dd>
     <dt>begin</dt>
-    <dd>This string or datetime or date and/or time field maps to the kml tag 
+    <dd>This string or datetime or date and/or time field maps to the kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#begin">
       <begin></a>. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_BEGIN_FIELD .
+      environment variable LIBKML_BEGIN_FIELD .
     </dd>
     <dt>end</dt>
-    <dd>This string or datetime or date and/or time field maps to the kml tag 
+    <dd>This string or datetime or date and/or time field maps to the kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#end">
       <end></a>. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_END_FIELD .
+      environment variable LIBKML_END_FIELD .
     </dd>
     <dt>altitudeMode</dt>
-    <dd>This string field maps to the kml tag 
+    <dd>This string field maps to the kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#altitudemode">
       <altitudeMode></a> or
       <a href="https://developers.google.com/kml/documentation/kmlreference#gxaltitudemode">
       <gx:altitudeMode></a>. The name of the ogr field can be changed
-      with the enviroment variable LIBKML_ALTITUDEMODE_FIELD .
+      with the environment variable LIBKML_ALTITUDEMODE_FIELD .
     </dd>
     <dt>tessellate</dt>
-    <dd>This integer field maps to the kml tag 
+    <dd>This integer field maps to the kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#tessellate">
       <tessellate></a>. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_TESSELLATE_FIELD .
+      environment variable LIBKML_TESSELLATE_FIELD .
     </dd>
     <dt>extrude</dt>
-    <dd>This integer field maps to the kml tag 
+    <dd>This integer field maps to the kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#extrude">
       <extrude></a>. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_EXTRUDE_FIELD .
+      environment variable LIBKML_EXTRUDE_FIELD .
     </dd>
     <dt>visibility</dt>
-    <dd>This integer field maps to the kml tag 
+    <dd>This integer field maps to the kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#visibility">
       <visibility></a>. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_VISIBILITY_FIELD .
+      environment variable LIBKML_VISIBILITY_FIELD .
     </dd>
     <dt>icon</dt>
-    <dd>This string field maps to the kml tag 
+    <dd>This string field maps to the kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#icon">
       <icon></a>. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_ICON_FIELD .
+      environment variable LIBKML_ICON_FIELD .
     </dd>
     <dt>drawOrder</dt>
-    <dd>This integer field maps to the kml tag 
+    <dd>This integer field maps to the kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#draworder">
       <drawOrder></a>. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_DRAWORDER_FIELD .
+      environment variable LIBKML_DRAWORDER_FIELD .
     </dd>
     <dt>snippet</dt>
-    <dd>This integer field maps to the kml tag 
+    <dd>This integer field maps to the kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#snippet">
       <snippet></a>. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_SNIPPET_FIELD .
+      environment variable LIBKML_SNIPPET_FIELD .
     </dd>
     <dt>heading</dt>
-    <dd>This real field maps to the kml tag 
+    <dd>This real field maps to the kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#heading">
       <heading></a>. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_HEADING_FIELD. When reading, this field is present only if a Placemark has
+      environment variable LIBKML_HEADING_FIELD. When reading, this field is present only if a Placemark has
       a Camera with a heading element.
     </dd>
     <dt>tilt</dt>
-    <dd>This real field maps to the kml tag 
+    <dd>This real field maps to the kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#tilt">
       <tilt></a>. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_TILT_FIELD. When reading, this field is present only if a Placemark has
+      environment variable LIBKML_TILT_FIELD. When reading, this field is present only if a Placemark has
       a Camera with a tilt element.
     </dd>
     <dt>roll</dt>
-    <dd>This real field maps to the kml tag 
+    <dd>This real field maps to the kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#roll">
       <roll></a>. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_ROLL_FIELD. When reading, this field is present only if a Placemark has
+      environment variable LIBKML_ROLL_FIELD. When reading, this field is present only if a Placemark has
       a Camera with a roll element.
     </dd>
 
@@ -505,215 +505,215 @@
     <dd>This string field can be used to define the URL of a 3D
       <a href="https://developers.google.com/kml/documentation/kmlreference#model">
       <model></a>. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_MODEL_FIELD.
+      environment variable LIBKML_MODEL_FIELD.
     </dd>
     <dt>scale_x</dt>
-    <dd>This real field maps to the x element of the kml tag 
+    <dd>This real field maps to the x element of the kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#scale">
       <scale></a> for a 3D model. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_SCALE_X_FIELD.
+      environment variable LIBKML_SCALE_X_FIELD.
     </dd>
     <dt>scale_y</dt>
-    <dd>This real field maps to the y element of the kml tag 
+    <dd>This real field maps to the y element of the kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#scale">
       <scale></a>for a 3D model. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_SCALE_Y_FIELD.
+      environment variable LIBKML_SCALE_Y_FIELD.
     </dd>
     <dt>scale_z</dt>
-    <dd>This real field maps to the z element of the kml tag 
+    <dd>This real field maps to the z element of the kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#scale">
       <scale></a>for a 3D model. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_SCALE_Z_FIELD.
+      environment variable LIBKML_SCALE_Z_FIELD.
     </dd>
 
     <dt>networklink</dt>
-    <dd>This string field maps to the href element of the kml tag 
+    <dd>This string field maps to the href element of the kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#href">
       <href></a> of a NetworkLink. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_NETWORKLINK_FIELD.
+      environment variable LIBKML_NETWORKLINK_FIELD.
     </dd>
 
     <dt>networklink_refreshvisibility</dt>
-    <dd>This integer field maps to kml tag 
+    <dd>This integer field maps to kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#refreshvisibility">
       <refreshVisibility></a> of a NetworkLink. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_NETWORKLINK_REFRESHVISIBILITY_FIELD.
+      environment variable LIBKML_NETWORKLINK_REFRESHVISIBILITY_FIELD.
     </dd>
 
     <dt>networklink_flytoview</dt>
-    <dd>This integer field maps to kml tag 
+    <dd>This integer field maps to kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#flytoview">
       <flyToView></a> of a NetworkLink. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_NETWORKLINK_FLYTOVIEW_FIELD.
+      environment variable LIBKML_NETWORKLINK_FLYTOVIEW_FIELD.
     </dd>
 
     <dt>networklink_refreshmode</dt>
-    <dd>This string field maps to kml tag 
+    <dd>This string field maps to kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#refreshmode">
       <refreshMode></a> of a NetworkLink. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_NETWORKLINK_REFRESHMODE_FIELD.
+      environment variable LIBKML_NETWORKLINK_REFRESHMODE_FIELD.
     </dd>
 
     <dt>networklink_refreshinterval</dt>
-    <dd>This real field maps to kml tag 
+    <dd>This real field maps to kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#refreshinterval">
       <refreshInterval></a> of a NetworkLink. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_NETWORKLINK_REFRESHINTERVAL_FIELD.
+      environment variable LIBKML_NETWORKLINK_REFRESHINTERVAL_FIELD.
     </dd>
 
     <dt>networklink_viewrefreshmode</dt>
-    <dd>This string field maps to kml tag 
+    <dd>This string field maps to kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#viewrefreshmode">
       <viewRefreshMode></a> of a NetworkLink. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_NETWORKLINK_VIEWREFRESHMODE_FIELD.
+      environment variable LIBKML_NETWORKLINK_VIEWREFRESHMODE_FIELD.
     </dd>
 
     <dt>networklink_viewrefreshtime</dt>
-    <dd>This real field maps to kml tag 
+    <dd>This real field maps to kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#viewrefreshtime">
       <viewRefreshTime></a> of a NetworkLink. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_NETWORKLINK_VIEWREFRESHTIME_FIELD.
+      environment variable LIBKML_NETWORKLINK_VIEWREFRESHTIME_FIELD.
     </dd>
 
     <dt>networklink_viewboundscale</dt>
-    <dd>This real field maps to kml tag 
+    <dd>This real field maps to kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#viewboundscale">
       <viewBoundScale></a> of a NetworkLink. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_NETWORKLINK_VIEWBOUNDSCALE_FIELD.
+      environment variable LIBKML_NETWORKLINK_VIEWBOUNDSCALE_FIELD.
     </dd>
 
     <dt>networklink_viewformat</dt>
-    <dd>This string field maps to kml tag 
+    <dd>This string field maps to kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#viewformat">
       <viewFormat></a> of a NetworkLink. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_NETWORKLINK_VIEWFORMAT_FIELD.
+      environment variable LIBKML_NETWORKLINK_VIEWFORMAT_FIELD.
     </dd>
 
     <dt>networklink_httpquery</dt>
-    <dd>This string field maps to kml tag 
+    <dd>This string field maps to kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#httpquery">
       <httpQuery></a> of a NetworkLink. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_NETWORKLINK_HTTPQUERY_FIELD.
+      environment variable LIBKML_NETWORKLINK_HTTPQUERY_FIELD.
     </dd>
 
     <dt>camera_longitude</dt>
-    <dd>This real field maps to kml tag 
+    <dd>This real field maps to kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#longitude">
       <longitude></a> of a <a href="https://developers.google.com/kml/documentation/kmlreference#camera">
       <Camera></a>. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_CACameraMERA_LONGITUDE_FIELD.
+      environment variable LIBKML_CACameraMERA_LONGITUDE_FIELD.
     </dd>
 
     <dt>camera_latitude</dt>
-    <dd>This real field maps to kml tag 
+    <dd>This real field maps to kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#latitude">
       <latitude></a> of a <a href="https://developers.google.com/kml/documentation/kmlreference#camera">
       <Camera></a>. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_CAMERA_LATITUDE_FIELD.
+      environment variable LIBKML_CAMERA_LATITUDE_FIELD.
     </dd>
 
     <dt>camera_altitude</dt>
-    <dd>This real field maps to kml tag 
+    <dd>This real field maps to kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#altitude">
       <altitude></a> of a <a href="https://developers.google.com/kml/documentation/kmlreference#camera">
       <Camera></a>. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_CAMERA_ALTITUDE_FIELD.
+      environment variable LIBKML_CAMERA_ALTITUDE_FIELD.
     </dd>
 
     <dt>camera_altitudemode</dt>
-    <dd>This real field maps to kml tag 
+    <dd>This real field maps to kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#altitudemode">
       <altitudeMode></a> of a <a href="https://developers.google.com/kml/documentation/kmlreference#camera">
       <Camera></a>. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_CAMERA_ALTITUDEMODE_FIELD.
+      environment variable LIBKML_CAMERA_ALTITUDEMODE_FIELD.
     </dd>
 
     <dt>photooverlay</dt>
-    <dd>This string field maps to the href element of the kml tag 
+    <dd>This string field maps to the href element of the kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#href">
       <href></a> of a <a href="https://developers.google.com/kml/documentation/kmlreference#photooverlay">
       <PhotoOverlay></a>. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_PHOTOOVERLAY_FIELD.
+      environment variable LIBKML_PHOTOOVERLAY_FIELD.
     </dd>
 
     <dt>leftfov</dt>
-    <dd>This real field maps to to kml tag 
+    <dd>This real field maps to to kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#leftfov">
       <LeftFov></a> of a <a href="https://developers.google.com/kml/documentation/kmlreference#photooverlay">
       <PhotoOverlay></a>. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_LEFTFOV_FIELD.
+      environment variable LIBKML_LEFTFOV_FIELD.
     </dd>
 
     <dt>rightfov</dt>
-    <dd>This real field maps to to kml tag 
+    <dd>This real field maps to to kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#rightfov">
       <RightFov></a> of a <a href="https://developers.google.com/kml/documentation/kmlreference#photooverlay">
       <PhotoOverlay></a>. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_RightFOV_FIELD.
+      environment variable LIBKML_RightFOV_FIELD.
     </dd>
 
     <dt>bottomfov</dt>
-    <dd>This real field maps to to kml tag 
+    <dd>This real field maps to to kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#bottomfov">
       <BottomFov></a> of a <a href="https://developers.google.com/kml/documentation/kmlreference#photooverlay">
       <PhotoOverlay></a>. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_BOTTOMTFOV_FIELD.
+      environment variable LIBKML_BOTTOMTFOV_FIELD.
     </dd>
 
     <dt>topfov</dt>
-    <dd>This real field maps to to kml tag 
+    <dd>This real field maps to to kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#topfov">
       <TopFov></a> of a <a href="https://developers.google.com/kml/documentation/kmlreference#photooverlay">
       <PhotoOverlay></a>. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_TOPFOV_FIELD.
+      environment variable LIBKML_TOPFOV_FIELD.
     </dd>
 
     <dt>near</dt>
-    <dd>This real field maps to to kml tag 
+    <dd>This real field maps to to kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#leftfov">
       <Near></a> of a <a href="https://developers.google.com/kml/documentation/kmlreference#photooverlay">
       <PhotoOverlay></a>. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_NEAR_FIELD.
+      environment variable LIBKML_NEAR_FIELD.
     </dd>
 
     <dt>shape</dt>
-    <dd>This string field maps to to kml tag 
+    <dd>This string field maps to to kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#shape">
       <shape></a> of a <a href="https://developers.google.com/kml/documentation/kmlreference#photooverlay">
       <PhotoOverlay></a>. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_SHAPE_FIELD.
+      environment variable LIBKML_SHAPE_FIELD.
     </dd>
 
     <dt>imagepyramid_tilesize</dt>
-    <dd>This integer field maps to to kml tag 
+    <dd>This integer field maps to to kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#tilesize">
       <tileSize></a> of a <a href="https://developers.google.com/kml/documentation/kmlreference#imagepyramid">
       <ImagePyramid></a>. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_IMAGEPYRAMID_TILESIZE.
+      environment variable LIBKML_IMAGEPYRAMID_TILESIZE.
     </dd>
 
     <dt>imagepyramid_maxwidth</dt>
-    <dd>This integer field maps to to kml tag 
+    <dd>This integer field maps to to kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#maxwidth">
       <maxWidth></a> of a <a href="https://developers.google.com/kml/documentation/kmlreference#imagepyramid">
       <ImagePyramid></a>. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_IMAGEPYRAMID_MAXWIDTH.
+      environment variable LIBKML_IMAGEPYRAMID_MAXWIDTH.
     </dd>
 
     <dt>imagepyramid_maxheight</dt>
-    <dd>This integer field maps to to kml tag 
+    <dd>This integer field maps to to kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#maxheight">
       <maxHeight></a> of a <a href="https://developers.google.com/kml/documentation/kmlreference#imagepyramid">
       <ImagePyramid></a>. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_IMAGEPYRAMID_MAXHEIGHT.
+      environment variable LIBKML_IMAGEPYRAMID_MAXHEIGHT.
     </dd>
 
     <dt>imagepyramid_gridorigin</dt>
-    <dd>This string field maps to to kml tag 
+    <dd>This string field maps to to kml tag
       <a href="https://developers.google.com/kml/documentation/kmlreference#maxheight">
       <gridOrigin></a> of a <a href="https://developers.google.com/kml/documentation/kmlreference#imagepyramid">
       <ImagePyramid></a>. The name of the ogr field can be changed with the
-      enviroment variable LIBKML_IMAGEPYRAMID_GRIDORIGIN.
+      environment variable LIBKML_IMAGEPYRAMID_GRIDORIGIN.
     </dd>
 
     <dt>OGR_STYLE</dt>
@@ -721,14 +721,14 @@
       if there is no style string set on the feature.
     </dd>
   </dl>
-  
+
   <h2>Geometry</h2>
-  
+
   <p>
     Translation of OGR
-    <a href="http://www.gdal.org/ogr/ogr_arch.html#ogr_arch_geometry">
+    <a href="http://www.gdal.org/ogr_arch.html#ogr_arch_geometry">
     Geometry</a> to KML Geometry is pretty strait forwards with only a couple
-    of exceptions. Point to 
+    of exceptions. Point to
     <a href="https://developers.google.com/kml/documentation/kmlreference#point">
     <Point></a> (unless heading and/or tilt and/or roll field names are found, in
     which case a <a href="https://developers.google.com/kml/documentation/kmlreference#camera">Camera</a> object will be generated), LineString to
@@ -740,20 +740,20 @@
     <Polygon></a>. In OGR a polygon contains an array of LinearRings,
     the first one being the outer ring. KML has the tags
      <a href="https://developers.google.com/kml/documentation/kmlreference#outerboundaryis">
-    <outerBoundaryIs></a> and  
+    <outerBoundaryIs></a> and 
     <a href="https://developers.google.com/kml/documentation/kmlreference#innerboundaryis">
     <innerBoundaryIs></a> to differentiate between the two. OGR has
     several Multi types of geometry : GeometryCollection, MultiPolygon,
-    MultiPoint, and MultiLineString. When possible, OGR will try to map 
+    MultiPoint, and MultiLineString. When possible, OGR will try to map
     <a href="https://developers.google.com/kml/documentation/kmlreference#multigeometry">
     <MultiGeometry></a> to the more precise OGR geometry type (MultiPoint, MultiLineString or MultiPolygon),
     and default to GeometryCollection in case of mixed content.
   </p>
-  
+
   <p>
     Sometimes kml geometry will span the dateline, In applications like qgis or
     mapserver this will create horizontal lines all the way around the globe.
-    Setting the enviroment variable LIBKML_WRAPDATELINE to "yes" will cause the
+    Setting the environment variable LIBKML_WRAPDATELINE to "yes" will cause the
     libkml driver to split the geometry at the dateline when read.
   </p>
 
@@ -767,19 +767,19 @@ The driver supports reading and writing to files managed by VSI Virtual File Sys
 Writing to /dev/stdout or /vsistdout/ is also supported.<p>
 
   <h2>Example</h2>
- 
+
   <p>
     The following bash script will build a
-    <a href="http://www.gdal.org/ogr/drv_csv.html">csv</a> file and a
-    <a href="http://www.gdal.org/ogr/drv_vrt.html">vrt</a> file, and then
-    translate them to KML using 
+    <a href="http://www.gdal.org/drv_csv.html">csv</a> file and a
+    <a href="http://www.gdal.org/drv_vrt.html">vrt</a> file, and then
+    translate them to KML using
     <a href="http://www.gdal.org/ogr2ogr.html">ogr2ogr</a> into a .kml file with
     timestamps and styling.
   </p>
- 
+
   <pre>
- 
- 
+
+
 #!/bin/bash
 # Copyright (c) 2010, Brian Case
  * Copyright (c) 2010-2014, Even Rouault <even dot rouault at mines-paris dot org>
@@ -801,8 +801,8 @@ Writing to /dev/stdout or /vsistdout/ is also supported.<p>
 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 # DEALINGS IN THE SOFTWARE.
- 
- 
+
+
 icon="http://maps.google.com/mapfiles/kml/shapes/shaded_dot.png"
 rgba33="#FF9900"
 rgba70="#FFFF00"
@@ -810,63 +810,63 @@ rgba150="#00FF00"
 rgba300="#0000FF"
 rgba500="#9900FF"
 rgba800="#FF0000"
- 
+
 function docsv {
- 
+
     IFS=','
-    
+
     while read Date Time Lat Lon Mag Dep
     do
         ts=$(echo $Date | sed 's:/:-:g')T${Time%%.*}Z
         rgba=""
-        
+
         if [[ $rgba == "" ]] && [[ $Dep -lt 33 ]]
         then
             rgba=$rgba33
         fi
-        
+
         if [[ $rgba == "" ]] && [[ $Dep -lt 70 ]]
         then
             rgba=$rgba70
         fi
-        
+
         if [[ $rgba == "" ]] && [[ $Dep -lt 150 ]]
         then
             rgba=$rgba150
         fi
-        
+
         if [[ $rgba == "" ]] && [[ $Dep -lt 300 ]]
         then
             rgba=$rgba300
         fi
-        
+
         if [[ $rgba == "" ]] && [[ $Dep -lt 500 ]]
         then
             rgba=$rgba500
         fi
-        
+
         if [[ $rgba == "" ]]
         then
             rgba=$rgba800
         fi
-        
-        
-        
+
+
+
         style="\"SYMBOL(s:$Mag,id:\"\"$icon\"\",c:$rgba)\""
-        
+
         echo $Date,$Time,$Lat,$Lon,$Mag,$Dep,$ts,"$style"
     done
-        
+
 }
- 
- 
+
+
 wget http://neic.usgs.gov/neis/gis/qed.asc -O /dev/stdout |\
  tail -n +2 > qed.asc
- 
+
 echo Date,TimeUTC,Latitude,Longitude,Magnitude,Depth,timestamp,OGR_STYLE > qed.csv
- 
+
 docsv < qed.asc >> qed.csv
- 
+
 cat > qed.vrt << EOF
 <OGRVRTDataSource>
     <OGRVRTLayer name="qed">
@@ -876,12 +876,12 @@ cat > qed.vrt << EOF
         <GeometryField encoding="PointFromColumns" x="Longitude" y="Latitude"/>
     </OGRVRTLayer>
 </OGRVRTDataSource>
- 
+
 EOF
- 
+
 ogr2ogr -f libkml qed.kml qed.vrt
- 
+
   </pre>
- 
+
 </body>
 </html>
diff --git a/ogr/ogrsf_frmts/libkml/libkml_headers.h b/ogr/ogrsf_frmts/libkml/libkml_headers.h
new file mode 100644
index 0000000..3299982
--- /dev/null
+++ b/ogr/ogrsf_frmts/libkml/libkml_headers.h
@@ -0,0 +1,50 @@
+/******************************************************************************
+ *
+ * Project:  KML Translator
+ * Purpose:  Implements OGRLIBKMLDriver
+ * Author:   Even Rouault <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+#ifndef LIBKML_HEADERS_H
+#define LIBKML_HEADERS_H
+
+#if ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) && !defined(_MSC_VER))
+#pragma GCC system_header
+#endif
+
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable : 4512 ) /* assignment operator could not be generated */
+#endif
+
+#include <kml/engine.h>
+#include <kml/dom.h>
+#include <kml/base/color32.h>
+#include <kml/base/file.h>
+
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
+
+#endif
diff --git a/ogr/ogrsf_frmts/libkml/ogr_libkml.h b/ogr/ogrsf_frmts/libkml/ogr_libkml.h
index 15fef92..41d8436 100644
--- a/ogr/ogrsf_frmts/libkml/ogr_libkml.h
+++ b/ogr/ogrsf_frmts/libkml/ogr_libkml.h
@@ -32,9 +32,7 @@
 
 #include "ogrsf_frmts.h"
 
-#include <kml/engine.h>
-#include <kml/dom.h>
-
+#include "libkml_headers.h"
 
 using kmldom::KmlFactory;
 using kmldom::KmlPtr;
@@ -94,7 +92,7 @@ class OGRLIBKMLLayer:public OGRLayer
 
     CPLString                 osListStyleType;
     CPLString                 osListStyleIconHref;
-    
+
     int                       m_bUpdateIsFolder;
 
   public:
@@ -122,7 +120,8 @@ class OGRLIBKMLLayer:public OGRLayer
     GIntBig                   GetFeatureCount ( int bForce = TRUE );
     OGRErr                    GetExtent ( OGREnvelope * psExtent,
                                           int bForce = TRUE );
-
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
     //const char               *GetInfo ( const char * );
 
@@ -157,7 +156,7 @@ class OGRLIBKMLLayer:public OGRLayer
                                         const char* pszCameraAltitudeMode);
 
     static CPLString          LaunderFieldNames(CPLString osName);
-    
+
     void                      SetWriteRegion(double dfMinLodPixels,
                                              double dfMaxLodPixels,
                                              double dfMinFadeExtent,
@@ -197,11 +196,10 @@ class OGRLIBKMLDataSource:public OGRDataSource
     char                     *pszName;
 
     /***** layers *****/
-    
+
     OGRLIBKMLLayer          **papoLayers;
     int                       nLayers;
     int                       nAlloced;
-    
 
     int                       bUpdate;
     int                       bUpdated;
@@ -226,13 +224,13 @@ class OGRLIBKMLDataSource:public OGRDataSource
     /***** for dir *****/
 
     int                       m_isDir;
-    
+
     /***** the kml factory *****/
-    
+
     KmlFactory               *m_poKmlFactory;
-    
+
     /***** style table pointer *****/
-    
+
     void                      SetCommonOptions(ContainerPtr poKmlContainer,
                                                char** papszOptions);
 
@@ -267,25 +265,25 @@ class OGRLIBKMLDataSource:public OGRDataSource
 
     void                      FlushCache (  );
     int                       TestCapability (const char * );
-    
+
     KmlFactory               *GetKmlFactory() { return m_poKmlFactory; };
-        
+
     const char               *GetStylePath() {return pszStylePath; };
     int                       ParseIntoStyleTable ( std::string * oKmlStyleKml,
                                                     const char *pszStylePath);
-        
+
     //KmzFile                  *GetKmz() { return m_poKmlKmzfile; };
-        
+
     int                       IsKml() {return m_isKml;};
     int                       IsKmz() {return m_isKmz;};
     int                       IsDir() {return m_isDir;};
-    
+
     void                      Updated() {bUpdated = TRUE;};
 
     int                       ParseLayers ( ContainerPtr poKmlContainer,
                                             OGRSpatialReference *poOgrSRS );
     SchemaPtr                 FindSchema ( const char *pszSchemaUrl);
-        
+
   private:
 
     /***** methods to write out various datasource types at destroy *****/
@@ -293,9 +291,9 @@ class OGRLIBKMLDataSource:public OGRDataSource
     void                      WriteKml();
     void                      WriteKmz();
     void                      WriteDir();
-    
+
     /***** methods to open various datasource types *****/
-        
+
     int                       OpenKmz ( const char *pszFilename,
                                         int bUpdate );
     int                       OpenKml ( const char *pszFilename,
@@ -304,7 +302,7 @@ class OGRLIBKMLDataSource:public OGRDataSource
                                         int bUpdate );
 
     /***** methods to create various datasource types *****/
-    
+
     int                       CreateKml ( const char *pszFilename,
                                           char **papszOptions );
     int                       CreateKmz ( const char *pszFilename,
@@ -313,7 +311,7 @@ class OGRLIBKMLDataSource:public OGRDataSource
                                           char **papszOptions );
 
     /***** methods to create layers on various datasource types *****/
-    
+
     OGRLIBKMLLayer           *CreateLayerKml ( const char *pszLayerName,
                                                OGRSpatialReference * poOgrSRS,
                                                OGRwkbGeometryType eGType,
@@ -322,19 +320,16 @@ class OGRLIBKMLDataSource:public OGRDataSource
                                                OGRSpatialReference * poOgrSRS,
                                                OGRwkbGeometryType eGType,
                                                char **papszOptions );
-        
+
     /***** methods to delete layers on various datasource types *****/
-    
+
     OGRErr                    DeleteLayerKml ( int );
     OGRErr                    DeleteLayerKmz ( int );
-    
+
     /***** methods to write a styletable to various datasource types *****/
 
     void                      SetStyleTable2Kml ( OGRStyleTable * poStyleTable );
     void                      SetStyleTable2Kmz ( OGRStyleTable * poStyleTable );
-    
-
-    
 
     OGRLIBKMLLayer           *AddLayer ( const char *pszLayerName,
                                          OGRSpatialReference * poSpatialRef,
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmldatasource.cpp b/ogr/ogrsf_frmts/libkml/ogrlibkmldatasource.cpp
index df3c186..ac795f4 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmldatasource.cpp
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmldatasource.cpp
@@ -32,8 +32,7 @@
 //#include "cpl_error.h"
 #include <iostream>
 //#include <sstream>
-#include <kml/dom.h>
-#include <kml/base/file.h>
+#include "libkml_headers.h"
 
 using kmldom::KmlFactory;
 using kmldom::DocumentPtr;
@@ -71,36 +70,32 @@ using kmlbase::Attributes;
  OGRLIBKMLDataSource Constructor
 
  Args:          none
- 
+
  Returns:       nothing
-                
+
 ******************************************************************************/
 
-OGRLIBKMLDataSource::OGRLIBKMLDataSource ( KmlFactory * poKmlFactory )
+OGRLIBKMLDataSource::OGRLIBKMLDataSource ( KmlFactory * poKmlFactory ) :
+    pszName(NULL),
+    papoLayers(NULL),
+    nLayers(0),
+    nAlloced(0),
+    bUpdate(FALSE),
+    bUpdated(FALSE),
+    m_papszOptions(NULL),
+    m_isKml(FALSE),
+    m_poKmlDSKml(NULL),
+    m_poKmlDSContainer(NULL),
+    m_poKmlUpdate(NULL),
+    m_isKmz(FALSE),
+    m_poKmlDocKml(NULL),
+    m_poKmlDocKmlRoot(NULL),
+    m_poKmlStyleKml(NULL),
+    pszStylePath(NULL),
+    m_isDir(FALSE),
+    m_poKmlFactory(poKmlFactory)
 {
-    pszName = NULL;
-    papoLayers = NULL;
-    nLayers = 0;
-    nAlloced = 0;
-    m_papszOptions = NULL;
-
-    bUpdated = FALSE;
-
-    m_isKml = FALSE;
-    m_poKmlDSKml = NULL;
-    m_poKmlDSContainer = NULL;
-    m_poKmlUpdate = NULL;
-
-    m_isKmz = FALSE;
-    m_poKmlDocKml = NULL;
     pszStylePath = (char *) "";
-
-    m_isDir = FALSE;
-    
-    m_poKmlFactory = poKmlFactory;
-
-    //m_poStyleTable = NULL;
-
 }
 
 /************************************************************************/
@@ -112,7 +107,7 @@ OGRLIBKMLDataSource::OGRLIBKMLDataSource ( KmlFactory * poKmlFactory )
 static void OGRLIBKMLPreProcessInput(std::string& oKml)
 {
     size_t nPos = 0;
-    while( TRUE )
+    while( true )
     {
         nPos = oKml.find("<snippet>", nPos);
         if( nPos == std::string::npos )
@@ -136,7 +131,7 @@ static void OGRLIBKMLPreProcessInput(std::string& oKml)
 static void OGRLIBKMLRemoveSpaces(std::string& oKml, const std::string& osNeedle)
 {
     size_t nPos = 0;
-    while( TRUE )
+    while( true )
     {
         nPos = oKml.find("<" + osNeedle, nPos);
         if( nPos == std::string::npos )
@@ -178,7 +173,7 @@ static void OGRLIBKMLPostProcessOutput(std::string& oKml)
     if( !(oKml[0] == '<' && oKml[1] == '?') )
         oKml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + oKml;
 
-    while( TRUE )
+    while( true )
     {
         nPos = oKml.find("<Snippet>", nPos);
         if( nPos == std::string::npos )
@@ -204,9 +199,9 @@ static void OGRLIBKMLPostProcessOutput(std::string& oKml)
  method to write a single file ds .kml at ds destroy
 
  Args:          none
- 
+
  Returns:       nothing
-                
+
 ******************************************************************************/
 
 void OGRLIBKMLDataSource::WriteKml (
@@ -304,9 +299,9 @@ static KmlPtr OGRLIBKMLCreateOGCKml22(KmlFactory* poFactory,
  method to write a ds .kmz at ds destroy
 
  Args:          none
- 
+
  Returns:       nothing
-                
+
 ******************************************************************************/
 
 void OGRLIBKMLDataSource::WriteKmz (
@@ -326,11 +321,11 @@ void OGRLIBKMLDataSource::WriteKmz (
     const char *pszUseDocKml =
         CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
 
-    if ( CSLTestBoolean ( pszUseDocKml ) && (m_poKmlDocKml || m_poKmlUpdate) ) {
+    if ( CPLTestBool ( pszUseDocKml ) && (m_poKmlDocKml || m_poKmlUpdate) ) {
+
+        // If we do not have the doc.kmlroot
+        // make it and add the container.
 
-        /***** if we dont have the doc.kml root *****/
-        /***** make it and add the container    *****/
-        
         if ( !m_poKmlDocKmlRoot ) {
             m_poKmlDocKmlRoot = OGRLIBKMLCreateOGCKml22(m_poKmlFactory, m_papszOptions);
 
@@ -346,7 +341,7 @@ void OGRLIBKMLDataSource::WriteKmz (
         OGRLIBKMLPostProcessOutput(oKmlOut);
 
         if ( CPLCreateFileInZip( hZIP, "doc.kml", NULL ) != CE_None ||
-             CPLWriteFileInZip( hZIP, oKmlOut.data(), oKmlOut.size() ) != CE_None )
+             CPLWriteFileInZip( hZIP, oKmlOut.data(), static_cast<int>(oKmlOut.size()) ) != CE_None )
             CPLError ( CE_Failure, CPLE_FileIO,
                        "ERROR adding %s to %s", "doc.kml", pszName );
         CPLCloseFileInZip(hZIP);
@@ -374,8 +369,8 @@ void OGRLIBKMLDataSource::WriteKmz (
             papoLayers[iLayer]->Finalize(poKmlDocument);
         }
 
-        /***** if we dont have the layers root *****/
-        /***** make it and add the container    *****/
+        // If we do not have the layers root
+        // make it and add the container.
 
         KmlPtr poKmlKml = NULL;
 
@@ -389,17 +384,17 @@ void OGRLIBKMLDataSource::WriteKmz (
         std::string oKmlOut = kmldom::SerializePretty ( poKmlKml );
         OGRLIBKMLPostProcessOutput(oKmlOut);
 
-        if( iLayer == 0 && CSLTestBoolean ( pszUseDocKml ) )
+        if( iLayer == 0 && CPLTestBool ( pszUseDocKml ) )
             CPLCreateFileInZip( hZIP, "layers/", NULL );
-        
+
         const char* pszLayerFileName;
-        if( CSLTestBoolean ( pszUseDocKml ) )
+        if( CPLTestBool ( pszUseDocKml ) )
             pszLayerFileName = CPLSPrintf("layers/%s", papoLayers[iLayer]->GetFileName (  ));
         else
             pszLayerFileName = papoLayers[iLayer]->GetFileName (  );
 
         if ( CPLCreateFileInZip( hZIP, pszLayerFileName , NULL ) != CE_None ||
-             CPLWriteFileInZip( hZIP, oKmlOut.data(), oKmlOut.size() ) != CE_None )
+             CPLWriteFileInZip( hZIP, oKmlOut.data(), static_cast<int>(oKmlOut.size()) ) != CE_None )
             CPLError ( CE_Failure, CPLE_FileIO,
                        "ERROR adding %s to %s", papoLayers[iLayer]->GetFileName (  ), pszName );
         CPLCloseFileInZip(hZIP);
@@ -418,7 +413,7 @@ void OGRLIBKMLDataSource::WriteKmz (
 
         if ( CPLCreateFileInZip( hZIP, "style/", NULL ) != CE_None ||
              CPLCreateFileInZip( hZIP, "style/style.kml", NULL ) != CE_None ||
-             CPLWriteFileInZip( hZIP, oKmlOut.data(), oKmlOut.size() ) != CE_None )
+             CPLWriteFileInZip( hZIP, oKmlOut.data(), static_cast<int>(oKmlOut.size()) ) != CE_None )
             CPLError ( CE_Failure, CPLE_FileIO,
                        "ERROR adding %s to %s", "style/style.kml", pszName );
         CPLCloseFileInZip(hZIP);
@@ -433,9 +428,9 @@ void OGRLIBKMLDataSource::WriteKmz (
  method to write a dir ds at ds destroy
 
  Args:          none
- 
+
  Returns:       nothing
-                
+
 ******************************************************************************/
 
 void OGRLIBKMLDataSource::WriteDir (
@@ -447,11 +442,11 @@ void OGRLIBKMLDataSource::WriteDir (
     const char *pszUseDocKml =
         CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
 
-    if ( CSLTestBoolean ( pszUseDocKml ) && (m_poKmlDocKml || m_poKmlUpdate) ) {
+    if ( CPLTestBool ( pszUseDocKml ) && (m_poKmlDocKml || m_poKmlUpdate) ) {
+
+        // If we don't have the doc.kml root
+        // make it and add the container.
 
-        /***** if we dont have the doc.kml root *****/
-        /***** make it and add the container    *****/
-        
         if ( !m_poKmlDocKmlRoot ) {
             m_poKmlDocKmlRoot = OGRLIBKMLCreateOGCKml22(m_poKmlFactory, m_papszOptions);
             if( m_poKmlDocKml != NULL )
@@ -459,7 +454,7 @@ void OGRLIBKMLDataSource::WriteDir (
 
             ParseDocumentOptions(AsKml( m_poKmlDocKmlRoot ), AsDocument(m_poKmlDocKml));
         }
-        
+
         std::string oKmlOut = kmldom::SerializePretty ( m_poKmlDocKmlRoot );
         OGRLIBKMLPostProcessOutput(oKmlOut);
 
@@ -498,8 +493,8 @@ void OGRLIBKMLDataSource::WriteDir (
             papoLayers[iLayer]->Finalize(poKmlDocument);
         }
 
-        /***** if we dont have the layers root *****/
-        /***** make it and add the container    *****/
+        // If we do not have the layers root
+        // make it and add the container.
 
         KmlPtr poKmlKml = NULL;
 
@@ -596,11 +591,11 @@ void OGRLIBKMLDataSource::FlushCache (
 
 /******************************************************************************
  OGRLIBKMLDataSource Destructor
- 
+
  Args:          none
- 
+
  Returns:       nothing
-                
+
 ******************************************************************************/
 
 OGRLIBKMLDataSource::~OGRLIBKMLDataSource (  )
@@ -615,12 +610,12 @@ OGRLIBKMLDataSource::~OGRLIBKMLDataSource (  )
 
     if (! EQUAL(pszStylePath, ""))
         CPLFree ( pszStylePath );
-    
+
     for ( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
 
     CPLFree ( papoLayers );
-    
+
     CSLDestroy( m_papszOptions );
 
     //delete m_poStyleTable;
@@ -632,9 +627,9 @@ OGRLIBKMLDataSource::~OGRLIBKMLDataSource (  )
  method to parse a schemas out of a document
 
  Args:          poKmlDocument   pointer to the document to parse
- 
+
  Returns:       nothing
-                
+
 ******************************************************************************/
 
 SchemaPtr OGRLIBKMLDataSource::FindSchema (
@@ -667,7 +662,7 @@ SchemaPtr OGRLIBKMLDataSource::FindSchema (
     }
 
 
-    else if ( ( pszPound = strchr ( (char *)pszSchemaUrl, '#' ) ) ) {
+    else if ( ( pszPound = strchr ( (char *)pszSchemaUrl, '#' ) ) != NULL ) {
         pszFile = CPLStrdup ( pszSchemaUrl );
         pszID = CPLStrdup ( pszPound + 1 );
         pszPound = strchr ( pszFile, '#' );
@@ -689,7 +684,7 @@ SchemaPtr OGRLIBKMLDataSource::FindSchema (
             poKmlDocument = AsDocument ( m_poKmlDocKml );
 
     }
-    
+
 
     if ( poKmlDocument) {
 
@@ -738,10 +733,10 @@ Method to allocate memory for the layer array, create the layer,
                 poKmlRoot       pointer to the root kml element of the layer
                 pszFileName     the filename of the layer
                 bNew            true if its a new layer
-                bUpdate         true if the layer is writeable
+                bUpdate         true if the layer is writable
                 nGuess          a guess at the number of additional layers
                                 we are going to need
- 
+
  Returns:       Pointer to the new layer
 ******************************************************************************/
 
@@ -754,7 +749,7 @@ OGRLIBKMLLayer *OGRLIBKMLDataSource::AddLayer (
     ContainerPtr poKmlContainer,
     const char *pszFileName,
     int bNew,
-    int bUpdate,
+    int bUpdateIn,
     int nGuess )
 {
 
@@ -781,7 +776,7 @@ OGRLIBKMLLayer *OGRLIBKMLDataSource::AddLayer (
                                                       m_poKmlUpdate,
                                                       pszFileName,
                                                       bNew,
-                                                      bUpdate );
+                                                      bUpdateIn );
 
     /***** add the layer to the array *****/
 
@@ -791,14 +786,14 @@ OGRLIBKMLLayer *OGRLIBKMLDataSource::AddLayer (
 }
 
 /******************************************************************************
- method to parse multiple layers out of a container
+ Method to parse multiple layers out of a container.
 
  Args:          poKmlContainer  pointer to the container to parse
                 poOgrSRS        SRS to use when creating the layer
- 
+
  Returns:       number of features in the container that are not another
                 container
-                
+
 ******************************************************************************/
 
 int OGRLIBKMLDataSource::ParseLayers (
@@ -814,7 +809,7 @@ int OGRLIBKMLDataSource::ParseLayers (
 
     size_t nKmlFeatures = poKmlContainer->get_feature_array_size (  );
 
-    /***** loop over the container to seperate the style, layers, etc *****/
+    /***** loop over the container to separate the style, layers, etc *****/
 
     size_t iKmlFeature;
 
@@ -831,10 +826,10 @@ int OGRLIBKMLDataSource::ParseLayers (
             std::string oKmlFeatName;
             if ( poKmlFeat->has_name (  ) ) {
                 /* Strip leading and trailing spaces */
-                const char* pszName = poKmlFeat->get_name (  ).c_str();
-                while(*pszName == ' ' || *pszName == '\n' || *pszName == '\r' || *pszName == '\t' )
-                    pszName ++;
-                oKmlFeatName = pszName;
+                const char* l_pszName = poKmlFeat->get_name (  ).c_str();
+                while(*l_pszName == ' ' || *l_pszName == '\n' || *l_pszName == '\r' || *l_pszName == '\t' )
+                    l_pszName ++;
+                oKmlFeatName = l_pszName;
                 int nSize = (int)oKmlFeatName.size();
                 while (nSize > 0 &&
                        (oKmlFeatName[nSize-1] == ' ' || oKmlFeatName[nSize-1] == '\n' ||
@@ -859,7 +854,8 @@ int OGRLIBKMLDataSource::ParseLayers (
 
             AddLayer ( oKmlFeatName.c_str (  ),
                        poOgrSRS, wkbUnknown, this,
-                       NULL, AsContainer( poKmlFeat ), "", FALSE, bUpdate, nKmlFeatures );
+                       NULL, AsContainer( poKmlFeat ), "", FALSE, bUpdate,
+                       static_cast<int>(nKmlFeatures) );
 
         }
 
@@ -872,9 +868,9 @@ int OGRLIBKMLDataSource::ParseLayers (
 
 /******************************************************************************
  function to get the container from the kmlroot
- 
+
  Args:          poKmlRoot   the root element
- 
+
  Returns:       root if its a container, if its a kml the container it
                 contains, or NULL
 
@@ -885,7 +881,7 @@ static ContainerPtr GetContainerFromRoot (
 {
     ContainerPtr poKmlContainer = NULL;
 
-    int bReadGroundOverlay = CSLTestBoolean(CPLGetConfigOption("LIBKML_READ_GROUND_OVERLAY", "YES"));
+    int bReadGroundOverlay = CPLTestBool(CPLGetConfigOption("LIBKML_READ_GROUND_OVERLAY", "YES"));
 
     if ( poKmlRoot ) {
 
@@ -901,7 +897,7 @@ static ContainerPtr GetContainerFromRoot (
                 if ( poKmlFeat->IsA ( kmldom::Type_Container ) )
                     poKmlContainer = AsContainer ( poKmlFeat );
                 else if ( poKmlFeat->IsA ( kmldom::Type_Placemark ) ||
-                          (bReadGroundOverlay && poKmlFeat->IsA ( kmldom::Type_GroundOverlay )) ) 
+                          (bReadGroundOverlay && poKmlFeat->IsA ( kmldom::Type_GroundOverlay )) )
                 {
                     poKmlContainer = m_poKmlFactory->CreateDocument (  );
                     poKmlContainer->add_feature ( kmldom::AsFeature(kmlengine::Clone(poKmlFeat)) );
@@ -925,7 +921,7 @@ int OGRLIBKMLDataSource::ParseIntoStyleTable (
     std::string *poKmlStyleKml,
     const char *pszMyStylePath)
 {
-    
+
     /***** parse the kml into the dom *****/
 
     std::string oKmlErrors;
@@ -933,37 +929,36 @@ int OGRLIBKMLDataSource::ParseIntoStyleTable (
 
     if ( !poKmlRoot ) {
         CPLError ( CE_Failure, CPLE_OpenFailed,
-                   "ERROR Parseing style kml %s :%s",
+                   "ERROR parsing style kml %s :%s",
                    pszStylePath, oKmlErrors.c_str (  ) );
         return false;
     }
-    
+
     ContainerPtr poKmlContainer;
 
     if ( !( poKmlContainer = GetContainerFromRoot ( m_poKmlFactory, poKmlRoot ) ) ) {
         return false;
     }
-    
+
     ParseStyles ( AsDocument ( poKmlContainer ), &m_poStyleTable );
     pszStylePath = CPLStrdup(pszMyStylePath);
-    
-        
+
     return true;
 }
 
 /******************************************************************************
  method to open a kml file
- 
+
  Args:          pszFilename file to open
                 bUpdate     update mode
- 
+
  Returns:       True on success, false on failure
 
 ******************************************************************************/
 
 int OGRLIBKMLDataSource::OpenKml (
     const char *pszFilename,
-    int bUpdate )
+    int bUpdateIn )
 {
     std::string oKmlKml;
     char szBuffer[1024+1];
@@ -976,13 +971,13 @@ int OGRLIBKMLDataSource::OpenKml (
         return FALSE;
     }
     int nRead;
-    while ((nRead = VSIFReadL(szBuffer, 1, 1024, fp)) != 0)
+    while ((nRead = static_cast<int>(VSIFReadL(szBuffer, 1, 1024, fp))) != 0)
     {
         try
         {
             oKmlKml.append(szBuffer, nRead);
         }
-        catch(std::bad_alloc& e)
+        catch(const std::bad_alloc& )
         {
             VSIFCloseL(fp);
             return FALSE;
@@ -1006,7 +1001,7 @@ int OGRLIBKMLDataSource::OpenKml (
 
     if ( !poKmlRoot ) {
         CPLError ( CE_Failure, CPLE_OpenFailed,
-                   "ERROR Parseing kml %s :%s",
+                   "ERROR parsing kml %s :%s",
                    pszFilename, oKmlErrors.c_str (  ) );
         delete poOgrSRS;
 
@@ -1015,9 +1010,10 @@ int OGRLIBKMLDataSource::OpenKml (
 
     /***** get the container from root  *****/
 
-    if ( !( m_poKmlDSContainer = GetContainerFromRoot ( m_poKmlFactory, poKmlRoot ) ) ) {
+    if ( !( m_poKmlDSContainer = GetContainerFromRoot ( m_poKmlFactory,
+                                                        poKmlRoot ) ) ) {
         CPLError ( CE_Failure, CPLE_OpenFailed,
-                   "ERROR Parseing kml %s :%s %s",
+                   "ERROR parsing kml %s :%s %s",
                    pszFilename, "This file does not fit the OGR model,",
                    "there is no container element at the root." );
         delete poOgrSRS;
@@ -1038,9 +1034,17 @@ int OGRLIBKMLDataSource::OpenKml (
     /***** if there is placemarks in the root its a layer *****/
 
     if ( nPlacemarks && !nLayers ) {
-        AddLayer ( CPLGetBasename ( pszFilename ),
+
+      std::string layername_default( CPLGetBasename ( pszFilename ) );
+
+      if( m_poKmlDSContainer->has_name ( ) ) {
+	  layername_default = m_poKmlDSContainer->get_name ( );
+	}
+
+      AddLayer ( layername_default.c_str(),
                    poOgrSRS, wkbUnknown,
-                   this, poKmlRoot, m_poKmlDSContainer, pszFilename, FALSE, bUpdate, 1 );
+                   this, poKmlRoot, m_poKmlDSContainer, pszFilename, FALSE, bUpdateIn, 1 );
+
     }
 
     delete poOgrSRS;
@@ -1050,10 +1054,10 @@ int OGRLIBKMLDataSource::OpenKml (
 
 /******************************************************************************
  method to open a kmz file
- 
+
  Args:          pszFilename file to open
                 bUpdate     update mode
- 
+
  Returns:       True on success, false on failure
 
 ******************************************************************************/
@@ -1061,7 +1065,7 @@ int OGRLIBKMLDataSource::OpenKml (
 
 int OGRLIBKMLDataSource::OpenKmz (
     const char *pszFilename,
-    int bUpdate )
+    int bUpdateIn )
 {
     std::string oKmlKmz;
     char szBuffer[1024+1];
@@ -1074,13 +1078,13 @@ int OGRLIBKMLDataSource::OpenKmz (
         return FALSE;
     }
     int nRead;
-    while ((nRead = VSIFReadL(szBuffer, 1, 1024, fp)) != 0)
+    while ((nRead = static_cast<int>(VSIFReadL(szBuffer, 1, 1024, fp))) != 0)
     {
         try
         {
             oKmlKmz.append(szBuffer, nRead);
         }
-        catch(std::bad_alloc& e)
+        catch(const std::bad_alloc&)
         {
             VSIFCloseL(fp);
             return FALSE;
@@ -1119,7 +1123,7 @@ int OGRLIBKMLDataSource::OpenKmz (
 
     if ( !poKmlDocKmlRoot ) {
         CPLError ( CE_Failure, CPLE_OpenFailed,
-                   "ERROR Parseing kml layer %s from %s :%s",
+                   "ERROR parsing kml layer %s from %s :%s",
                    oKmlKmlPath.c_str (  ),
                    pszFilename, oKmlErrors.c_str (  ) );
         delete poOgrSRS;
@@ -1127,13 +1131,14 @@ int OGRLIBKMLDataSource::OpenKmz (
         return FALSE;
     }
 
-    /***** get the child contianer from root *****/
+    /***** Get the child container from root. *****/
 
     ContainerPtr poKmlContainer;
 
-    if (!(poKmlContainer = GetContainerFromRoot ( m_poKmlFactory, poKmlDocKmlRoot ))) {
+    if (!(poKmlContainer = GetContainerFromRoot ( m_poKmlFactory,
+                                                  poKmlDocKmlRoot ))) {
         CPLError ( CE_Failure, CPLE_OpenFailed,
-                   "ERROR Parseing %s from %s :%s",
+                   "ERROR parsing %s from %s :%s",
                    oKmlKmlPath.c_str (  ),
                    pszFilename, "kml contains no Containers" );
         delete poOgrSRS;
@@ -1185,12 +1190,12 @@ int OGRLIBKMLDataSource::OpenKmz (
 
                 /***** parse the kml into the DOM *****/
 
-                std::string oKmlErrors;
+                oKmlErrors.clear();
                 ElementPtr poKmlLyrRoot = kmldom::Parse ( oKml, &oKmlErrors );
 
                 if ( !poKmlLyrRoot ) {
                     CPLError ( CE_Failure, CPLE_OpenFailed,
-                               "ERROR Parseing kml layer %s from %s :%s",
+                               "ERROR parseing kml layer %s from %s :%s",
                                poKmlHref->get_path (  ).c_str (  ),
                                pszFilename, oKmlErrors.c_str (  ) );
                     delete poKmlHref;
@@ -1206,7 +1211,7 @@ int OGRLIBKMLDataSource::OpenKmz (
                 if ( !poKmlLyrContainer )
                 {
                     CPLError ( CE_Failure, CPLE_OpenFailed,
-                               "ERROR Parseing kml layer %s from %s :%s",
+                               "ERROR parsing kml layer %s from %s :%s",
                                poKmlHref->get_path (  ).c_str (  ),
                                pszFilename, oKmlErrors.c_str (  ) );
                     delete poKmlHref;
@@ -1219,8 +1224,8 @@ int OGRLIBKMLDataSource::OpenKmz (
                 AddLayer ( CPLGetBasename
                            ( poKmlHref->get_path (  ).c_str (  ) ), poOgrSRS,
                            wkbUnknown, this, poKmlLyrRoot, poKmlLyrContainer,
-                           poKmlHref->get_path (  ).c_str (  ), FALSE, bUpdate,
-                           nKmlFeatures );
+                           poKmlHref->get_path (  ).c_str (  ), FALSE, bUpdateIn,
+                           static_cast<int>(nKmlFeatures) );
 
             }
         }
@@ -1231,19 +1236,19 @@ int OGRLIBKMLDataSource::OpenKmz (
     }
 
     /***** if the doc.kml has links store it so if were in update mode we can write it *****/
-    
+
     if ( nLinks ) {
         m_poKmlDocKml = poKmlContainer;
         m_poKmlDocKmlRoot = poKmlDocKmlRoot;
     }
-        
+
     /***** if the doc.kml has no links treat it as a normal kml file *****/
 
     else {
 
-        /* todo there could still be a seperate styles file in the kmz
+        /* TODO: There could still be a separate styles file in the KMZ
            if there is this would be a layer style table IF its only a single
-           layer
+           layer.
          */
 
         /***** get the styles *****/
@@ -1257,9 +1262,17 @@ int OGRLIBKMLDataSource::OpenKmz (
         /***** if there is placemarks in the root its a layer *****/
 
         if ( nPlacemarks && !nLayers ) {
-            AddLayer ( CPLGetBasename ( pszFilename ),
-                       poOgrSRS, wkbUnknown,
-                       this, poKmlDocKmlRoot, poKmlContainer, pszFilename, FALSE, bUpdate, 1 );
+
+	  std::string layername_default( CPLGetBasename ( pszFilename ) );
+
+	  if( poKmlContainer->has_name ( ) ) {
+	      layername_default = poKmlContainer->get_name ( );
+	    }
+
+	  AddLayer ( layername_default.c_str(),
+		     poOgrSRS, wkbUnknown,
+		     this, poKmlDocKmlRoot, poKmlContainer,
+		     pszFilename, FALSE, bUpdateIn, 1 );
         }
     }
 
@@ -1275,28 +1288,28 @@ int OGRLIBKMLDataSource::OpenKmz (
 
     delete poKmlKmzfile;
     m_isKmz = TRUE;
-    
+
     return TRUE;
 }
 
 /******************************************************************************
  method to open a dir
- 
+
  Args:          pszFilename Dir to open
                 bUpdate     update mode
- 
+
  Returns:       True on success, false on failure
 
 ******************************************************************************/
 
 int OGRLIBKMLDataSource::OpenDir (
     const char *pszFilename,
-    int bUpdate )
+    int bUpdateIn )
 {
 
-    char **papszDirList = NULL;
+    char **papszDirList = VSIReadDir ( pszFilename );
 
-    if ( !( papszDirList = VSIReadDir ( pszFilename ) ) )
+    if ( papszDirList == NULL )
         return FALSE;
 
     /***** create a SRS *****/
@@ -1330,13 +1343,13 @@ int OGRLIBKMLDataSource::OpenDir (
         }
 
         int nRead;
-        while ((nRead = VSIFReadL(szBuffer, 1, 1024, fp)) != 0)
+        while ((nRead = static_cast<int>(VSIFReadL(szBuffer, 1, 1024, fp))) != 0)
         {
             try
             {
                 oKmlKml.append(szBuffer, nRead);
             }
-            catch(std::bad_alloc& e)
+            catch(const std::bad_alloc&)
             {
                 VSIFCloseL(fp);
                 CSLDestroy ( papszDirList );
@@ -1354,19 +1367,20 @@ int OGRLIBKMLDataSource::OpenDir (
 
         if ( !poKmlRoot ) {
             CPLError ( CE_Failure, CPLE_OpenFailed,
-                       "ERROR Parseing kml layer %s from %s :%s",
+                       "ERROR parsing kml layer %s from %s :%s",
                        osFilePath.c_str(), pszFilename, oKmlErrors.c_str (  ) );
 
             continue;
         }
 
-        /***** get the cintainer from the root *****/
+        /***** Get the container from the root *****/
 
         ContainerPtr poKmlContainer;
 
-        if ( !( poKmlContainer = GetContainerFromRoot ( m_poKmlFactory, poKmlRoot ) ) ) {
+        if ( !( poKmlContainer = GetContainerFromRoot ( m_poKmlFactory,
+                                                        poKmlRoot ) ) ) {
             CPLError ( CE_Failure, CPLE_OpenFailed,
-                       "ERROR Parseing kml %s :%s %s",
+                       "ERROR parsing kml %s :%s %s",
                        pszFilename,
                        "This file does not fit the OGR model,",
                        "there is no container element at the root." );
@@ -1386,7 +1400,7 @@ int OGRLIBKMLDataSource::OpenDir (
 
         AddLayer ( CPLGetBasename ( osFilePath.c_str() ),
                    poOgrSRS, wkbUnknown,
-                   this, poKmlRoot, poKmlContainer, osFilePath.c_str(), FALSE, bUpdate, nFiles );
+                   this, poKmlRoot, poKmlContainer, osFilePath.c_str(), FALSE, bUpdateIn, nFiles );
 
     }
 
@@ -1404,10 +1418,10 @@ int OGRLIBKMLDataSource::OpenDir (
 
 /******************************************************************************
  Method to open a datasource
- 
+
  Args:          pszFilename Darasource to open
                 bUpdate     update mode
- 
+
  Returns:       True on success, false on failure
 
 ******************************************************************************/
@@ -1443,10 +1457,10 @@ static int CheckIsKMZ(const char *pszFilename)
 
 int OGRLIBKMLDataSource::Open (
     const char *pszFilename,
-    int bUpdate )
+    int bUpdateIn )
 {
 
-    this->bUpdate = bUpdate;
+    this->bUpdate = bUpdateIn;
     pszName = CPLStrdup ( pszFilename );
 
     /***** dir *****/
@@ -1473,7 +1487,7 @@ int OGRLIBKMLDataSource::Open (
         if (fp == NULL)
             return FALSE;
 
-        int nRead = VSIFReadL(szBuffer, 1, 1024, fp);
+        int nRead = static_cast<int>(VSIFReadL(szBuffer, 1, 1024, fp));
         szBuffer[nRead] = 0;
 
         VSIFCloseL(fp);
@@ -1493,7 +1507,7 @@ int OGRLIBKMLDataSource::Open (
 
         if (strstr(szBuffer, "<kml>") || strstr(szBuffer, "<kml xmlns="))
             return OpenKml ( pszFilename, bUpdate );
-        
+
         return FALSE;
     }
 }
@@ -1505,7 +1519,7 @@ int OGRLIBKMLDataSource::Open (
 /* Very approximative validation of http://tools.ietf.org/html/rfc3966#page-6 */
 static int IsValidPhoneNumber(const char* pszPhoneNumber)
 {
-    if( strncmp(pszPhoneNumber, "tel:", strlen("tel:")) == 0 )
+    if( STARTS_WITH(pszPhoneNumber, "tel:") )
         pszPhoneNumber += strlen("tel:");
     char ch;
     int bDigitFound = FALSE;
@@ -1531,17 +1545,17 @@ static int IsValidPhoneNumber(const char* pszPhoneNumber)
 void OGRLIBKMLDataSource::SetCommonOptions(ContainerPtr poKmlContainer,
                                            char** papszOptions)
 {
-    const char* pszName = CSLFetchNameValue(papszOptions, "NAME");
-    if( pszName != NULL )
-        poKmlContainer->set_name(pszName);
+    const char* l_pszName = CSLFetchNameValue(papszOptions, "NAME");
+    if( l_pszName != NULL )
+        poKmlContainer->set_name(l_pszName);
 
     const char* pszVisibilility = CSLFetchNameValue(papszOptions, "VISIBILITY");
     if( pszVisibilility != NULL )
-        poKmlContainer->set_visibility(CSLTestBoolean(pszVisibilility));
+        poKmlContainer->set_visibility(CPLTestBool(pszVisibilility));
 
     const char* pszOpen = CSLFetchNameValue(papszOptions, "OPEN");
     if( pszOpen != NULL )
-        poKmlContainer->set_open(CSLTestBoolean(pszOpen));
+        poKmlContainer->set_open(CPLTestBool(pszOpen));
 
     const char* pszSnippet = CSLFetchNameValue(papszOptions, "SNIPPET");
     if( pszSnippet != NULL )
@@ -1580,8 +1594,8 @@ void OGRLIBKMLDataSource::ParseDocumentOptions(KmlPtr poKml,
             if( pszAuthorURI != NULL )
             {
                 /* Ad-hoc validation. The ABNF is horribly complicated : http://tools.ietf.org/search/rfc3987#page-7 */
-                if( strncmp(pszAuthorURI, "http://", strlen("http://")) == 0 ||
-                    strncmp(pszAuthorURI, "https://", strlen("https://")) == 0 )
+                if( STARTS_WITH(pszAuthorURI, "http://") ||
+                    STARTS_WITH(pszAuthorURI, "https://") )
                 {
                     author->set_uri(pszAuthorURI);
                 }
@@ -1618,7 +1632,7 @@ void OGRLIBKMLDataSource::ParseDocumentOptions(KmlPtr poKml,
         {
             if( IsValidPhoneNumber(pszPhoneNumber) )
             {
-                if( strncmp(pszPhoneNumber, "tel:", strlen("tel:")) != 0 )
+                if( !STARTS_WITH(pszPhoneNumber, "tel:") )
                     poKmlDocument->set_phonenumber(CPLSPrintf("tel:%s", pszPhoneNumber));
                 else
                     poKmlDocument->set_phonenumber(pszPhoneNumber);
@@ -1769,7 +1783,7 @@ int OGRLIBKMLDataSource::CreateKmz (
         const char *pszUseDocKml =
             CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
 
-        if ( CSLTestBoolean( pszUseDocKml ) ) {
+        if ( CPLTestBool( pszUseDocKml ) ) {
             m_poKmlDocKml = m_poKmlFactory->CreateDocument (  );
         }
     }
@@ -1810,7 +1824,7 @@ int OGRLIBKMLDataSource::CreateDir (
         const char *pszUseDocKml =
             CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
 
-        if ( CSLTestBoolean( pszUseDocKml ) ) {
+        if ( CPLTestBool( pszUseDocKml ) ) {
             m_poKmlDocKml = m_poKmlFactory->CreateDocument (  );
         }
     }
@@ -1823,15 +1837,15 @@ int OGRLIBKMLDataSource::CreateDir (
 
 /******************************************************************************
  method to create a datasource
- 
+
  Args:          pszFilename     the datasource to create
                 papszOptions    datasource creation options
- 
+
  Returns:       True on success, false on failure
- 
+
  env vars:
   LIBKML_USE_DOC.KML         default: yes
- 
+
 ******************************************************************************/
 
 int OGRLIBKMLDataSource::Create (
@@ -1859,7 +1873,7 @@ int OGRLIBKMLDataSource::Create (
     /***** kml *****/
 
     if ( strcmp(pszFilename, "/vsistdout/") == 0 ||
-         strncmp(pszFilename, "/vsigzip/", 9) == 0 ||
+         STARTS_WITH(pszFilename, "/vsigzip/") ||
          EQUAL ( CPLGetExtension ( pszFilename ), "kml" ) )
         bResult = CreateKml ( pszFilename, papszOptions );
 
@@ -1878,9 +1892,9 @@ int OGRLIBKMLDataSource::Create (
 
 /******************************************************************************
  method to get a layer by index
- 
+
  Args:          iLayer      the index of the layer to get
- 
+
  Returns:       pointer to the layer, or NULL if the layer does not exist
 
 ******************************************************************************/
@@ -1897,9 +1911,9 @@ OGRLayer *OGRLIBKMLDataSource::GetLayer (
 
 /******************************************************************************
  method to get a layer by name
- 
+
  Args:          pszname     name of the layer to get
- 
+
  Returns:       pointer to the layer, or NULL if the layer does not exist
 
 ******************************************************************************/
@@ -1920,9 +1934,9 @@ OGRLayer *OGRLIBKMLDataSource::GetLayerByName (
 
 /******************************************************************************
  method to DeleteLayers in a .kml datasource
- 
+
  Args:          iLayer  index of the layer to delete
- 
+
  Returns:       OGRERR_NONE on success, OGRERR_FAILURE on failure
 
 ******************************************************************************/
@@ -1954,9 +1968,9 @@ OGRErr OGRLIBKMLDataSource::DeleteLayerKml (
 
 /******************************************************************************
  method to DeleteLayers in a .kmz datasource
- 
+
  Args:          iLayer  index of the layer to delete
- 
+
  Returns:       OGRERR_NONE on success, OGRERR_FAILURE on failure
 
 ******************************************************************************/
@@ -1969,7 +1983,7 @@ OGRErr OGRLIBKMLDataSource::DeleteLayerKmz (
     const char *pszUseDocKml =
         CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
 
-    if ( CSLTestBoolean ( pszUseDocKml ) && m_poKmlDocKml ) {
+    if ( CPLTestBool ( pszUseDocKml ) && m_poKmlDocKml ) {
 
         /***** loop over the features *****/
 
@@ -2021,9 +2035,9 @@ OGRErr OGRLIBKMLDataSource::DeleteLayerKmz (
 
 /******************************************************************************
  method to delete a layer in a datasource
- 
+
  Args:          iLayer  index of the layer to delete
- 
+
  Returns:       OGRERR_NONE on success, OGRERR_FAILURE on failure
 
 ******************************************************************************/
@@ -2047,7 +2061,7 @@ OGRErr OGRLIBKMLDataSource::DeleteLayer (
     else if ( IsDir (  ) ) {
         DeleteLayerKmz ( iLayer );
 
-        /***** delete the file the layer corisponds to *****/
+        /***** delete the file the layer corresponds to *****/
 
         const char *pszFilePath =
             CPLFormFilename ( pszName, papoLayers[iLayer]->GetFileName (  ),
@@ -2074,12 +2088,12 @@ OGRErr OGRLIBKMLDataSource::DeleteLayer (
 
 /******************************************************************************
  method to create a layer in a single file .kml
- 
+
  Args:          pszLayerName    name of the layer to create
                 poOgrSRS        the SRS of the layer
                 eGType          the layers geometry type
                 papszOptions    layer creation options
- 
+
  Returns:       return a pointer to the new layer or NULL on failure
 
 ******************************************************************************/
@@ -2093,7 +2107,7 @@ OGRLIBKMLLayer *OGRLIBKMLDataSource::CreateLayerKml (
 
     OGRLIBKMLLayer *poOgrLayer = NULL;
     ContainerPtr poKmlLayerContainer = NULL;
-    
+
     if( m_poKmlDSContainer != NULL )
     {
         if( CSLFetchBoolean( papszOptions, "FOLDER", FALSE ) )
@@ -2149,9 +2163,9 @@ OGRLIBKMLLayer *OGRLIBKMLDataSource::CreateLayerKmz (
         const char *pszUseDocKml =
             CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
 
-        if ( CSLTestBoolean ( pszUseDocKml ) && m_poKmlDocKml ) {
+        if ( CPLTestBool ( pszUseDocKml ) && m_poKmlDocKml ) {
 
-            DocumentPtr poKmlDocument = AsDocument ( m_poKmlDocKml );
+            poKmlDocument = AsDocument ( m_poKmlDocKml );
 
             NetworkLinkPtr poKmlNetLink = m_poKmlFactory->CreateNetworkLink (  );
             LinkPtr poKmlLink = m_poKmlFactory->CreateLink (  );
@@ -2190,12 +2204,12 @@ OGRLIBKMLLayer *OGRLIBKMLDataSource::CreateLayerKmz (
 
 /******************************************************************************
 ICreateLayer()
- 
+
  Args:          pszLayerName    name of the layer to create
                 poOgrSRS        the SRS of the layer
                 eGType          the layers geometry type
                 papszOptions    layer creation options
- 
+
  Returns:       return a pointer to the new layer or NULL on failure
 
 ******************************************************************************/
@@ -2209,7 +2223,7 @@ OGRLayer *OGRLIBKMLDataSource::ICreateLayer(
 
     if ( !bUpdate )
         return NULL;
-    
+
     if( (IsKmz () || IsDir ()) && EQUAL(pszLayerName, "doc") )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -2272,7 +2286,7 @@ OGRLayer *OGRLIBKMLDataSource::ICreateLayer(
                                 pszCameraAltitudeMode);
         }
     }
-    
+
     const char* pszRegionAdd = CSLFetchNameValueDef(papszOptions, "ADD_REGION", "FALSE");
     const char* pszRegionXMin = CSLFetchNameValue(papszOptions, "REGION_XMIN");
     const char* pszRegionYMin = CSLFetchNameValue(papszOptions, "REGION_YMIN");
@@ -2286,7 +2300,7 @@ OGRLayer *OGRLIBKMLDataSource::ICreateLayer(
         CSLFetchNameValueDef(papszOptions, "REGION_MIN_FADE_EXTENT", "0");
     const char* pszRegionMaxFadeExtent =
         CSLFetchNameValueDef(papszOptions, "REGION_MAX_FADE_EXTENT", "0");
-    if( poOgrLayer != NULL && CSLTestBoolean(pszRegionAdd) )
+    if( poOgrLayer != NULL && CPLTestBool(pszRegionAdd) )
     {
         poOgrLayer->SetWriteRegion(CPLAtof(pszRegionMinLodPixels),
                                    CPLAtof(pszRegionMaxLodPixels),
@@ -2303,7 +2317,7 @@ OGRLayer *OGRLIBKMLDataSource::ICreateLayer(
                 poOgrLayer->SetRegionBounds(xmin, ymin, xmax, ymax);
         }
     }
-    
+
     const char* pszSOHref = CSLFetchNameValue(papszOptions, "SO_HREF");
     const char* pszSOName = CSLFetchNameValue(papszOptions, "SO_NAME");
     const char* pszSODescription = CSLFetchNameValue(papszOptions, "SO_DESCRIPTION");
@@ -2337,7 +2351,7 @@ OGRLayer *OGRLIBKMLDataSource::ICreateLayer(
                                      pszSOSizeXUnits,
                                      pszSOSizeYUnits);
     }
-    
+
     const char* pszListStyleType = CSLFetchNameValue(papszOptions, "LISTSTYLE_TYPE");
     const char* pszListStyleIconHref = CSLFetchNameValue(papszOptions, "LISTSTYLE_ICON_HREF");
     if( poOgrLayer != NULL )
@@ -2360,9 +2374,9 @@ OGRLayer *OGRLIBKMLDataSource::ICreateLayer(
 
 /******************************************************************************
  method to get a datasources style table
- 
+
  Args:          none
- 
+
  Returns:       pointer to the datasources style table, or NULL if it does
                 not have one
 
@@ -2377,9 +2391,9 @@ OGRStyleTable *OGRLIBKMLDataSource::GetStyleTable (
 
 /******************************************************************************
   method to write a style table to a single file .kml ds
- 
+
  Args:          poStyleTable    pointer to the style table to add
- 
+
  Returns:       nothing
 
 ******************************************************************************/
@@ -2393,7 +2407,7 @@ void OGRLIBKMLDataSource::SetStyleTable2Kml (
     /***** delete all the styles *****/
 
     DocumentPtr poKmlDocument = AsDocument ( m_poKmlDSContainer );
-    size_t nKmlStyles = poKmlDocument->get_styleselector_array_size (  );
+    int nKmlStyles = static_cast<int>(poKmlDocument->get_styleselector_array_size (  ));
     int iKmlStyle;
 
     for ( iKmlStyle = nKmlStyles - 1; iKmlStyle >= 0; iKmlStyle-- ) {
@@ -2410,9 +2424,9 @@ void OGRLIBKMLDataSource::SetStyleTable2Kml (
 
 /******************************************************************************
  method to write a style table to a kmz ds
- 
+
  Args:          poStyleTable    pointer to the style table to add
- 
+
  Returns:       nothing
 
 ******************************************************************************/
@@ -2435,13 +2449,13 @@ void OGRLIBKMLDataSource::SetStyleTable2Kmz (
 
 /******************************************************************************
  method to write a style table to a datasource
- 
+
  Args:          poStyleTable    pointer to the style table to add
- 
+
  Returns:       nothing
 
  note: this method assumes ownership of the style table
- 
+
 ******************************************************************************/
 
 void OGRLIBKMLDataSource::SetStyleTableDirectly (
@@ -2466,28 +2480,24 @@ void OGRLIBKMLDataSource::SetStyleTableDirectly (
 
     bUpdated = TRUE;
 
-
-
-
     return;
 }
 
 /******************************************************************************
  method to write a style table to a datasource
- 
+
  Args:          poStyleTable    pointer to the style table to add
- 
+
  Returns:       nothing
 
- note:  this method copys the style table, and the user will still be
-        responsible for its destruction
+ note:  This method copies the style table, and the user will still be
+        responsible for its destruction.
 
 ******************************************************************************/
 
 void OGRLIBKMLDataSource::SetStyleTable (
     OGRStyleTable * poStyleTable )
 {
-
     if ( !bUpdate )
         return;
 
@@ -2503,12 +2513,12 @@ void OGRLIBKMLDataSource::SetStyleTable (
  Test if capability is available.
 
  Args:          pszCap  datasource capability name to test
- 
+
  Returns:       nothing
 
  ODsCCreateLayer: True if this datasource can create new layers.
  ODsCDeleteLayer: True if this datasource can delete existing layers.
- 
+
 ******************************************************************************/
 
 int OGRLIBKMLDataSource::TestCapability (
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmldriver.cpp b/ogr/ogrsf_frmts/libkml/ogrlibkmldriver.cpp
index 11cb8df..9d8713c 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmldriver.cpp
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmldriver.cpp
@@ -26,13 +26,13 @@
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
 
+#include "libkml_headers.h"
+
 #include "ogr_libkml.h"
 #include "cpl_conv.h"
 #include "cpl_error.h"
 #include "cpl_multiproc.h"
 
-#include <kml/dom.h>
-
 using kmldom::KmlFactory;
 
 static CPLMutex *hMutex = NULL;
@@ -127,9 +127,9 @@ static GDALDataset *OGRLIBKMLDriverCreate( const char * pszName,
 /******************************************************************************
  DeleteDataSource()
 
- note: this method recursivly deletes an entire dir if the datasource is a dir
-       and all the files are kml or kmz
- 
+ Note: this method recursively deletes an entire dir if the datasource is a dir
+       and all the files are kml or kmz.
+
 ******************************************************************************/
 
 static CPLErr OGRLIBKMLDriverDelete( const char *pszName )
@@ -140,30 +140,20 @@ static CPLErr OGRLIBKMLDriverDelete( const char *pszName )
     VSIStatBufL sStatBuf;
     if ( !VSIStatL ( pszName, &sStatBuf ) && VSI_ISDIR ( sStatBuf.st_mode ) ) {
 
-        char **papszDirList = NULL;
-
-        if ( !( papszDirList = VSIReadDir ( pszName ) ) ) {
-            if ( VSIRmdir ( pszName ) < 0 )
-                return CE_Failure;
-        }
-
-        int nFiles = CSLCount ( papszDirList );
-        int iFile;
-
-        for ( iFile = 0; iFile < nFiles; iFile++ ) {
+        char **papszDirList = VSIReadDir ( pszName );
+        for ( int iFile = 0; papszDirList != NULL &&
+                             papszDirList[iFile] != NULL; iFile++ ) {
             if ( CE_Failure ==
                  OGRLIBKMLDriverDelete ( papszDirList[iFile] ) ) {
                 CSLDestroy ( papszDirList );
                 return CE_Failure;
             }
         }
+        CSLDestroy ( papszDirList );
 
         if ( VSIRmdir ( pszName ) < 0 ) {
-            CSLDestroy ( papszDirList );
             return CE_Failure;
         }
-
-        CSLDestroy ( papszDirList );
     }
 
    /***** kml *****/
@@ -192,24 +182,21 @@ static CPLErr OGRLIBKMLDriverDelete( const char *pszName )
  RegisterOGRLIBKML()
 ******************************************************************************/
 
-void RegisterOGRLIBKML (
-     )
+void RegisterOGRLIBKML ()
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "LIBKML" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "LIBKML" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "LIBKML" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Keyhole Markup Language (LIBKML)" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "kml kmz" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_libkml.html" );
+    poDriver->SetDescription( "LIBKML" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Keyhole Markup Language (LIBKML)" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "kml kmz" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_libkml.html" );
 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "  <Option name='AUTHOR_NAME' type='string' description='Name in <atom:Author> element'/>"
 "  <Option name='AUTHOR_URI' type='string' description='URI in <atom:Author> element'/>"
@@ -241,7 +228,7 @@ void RegisterOGRLIBKML (
 "  <Option name='UPDATE_TARGETHREF' type='string' description='If set, a NetworkLinkControl KML file with an <Update> element will be generated'/>"
 "</CreationOptionList>");
 
-        poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
 "<LayerCreationOptionList>"
 "  <Option name='NAME' type='string' description='Value of <name> element of layer container'/>"
 "  <Option name='VISIBILITY' type='integer' description='Value of <visibility> element of layer container (0/1)'/>"
@@ -332,16 +319,15 @@ void RegisterOGRLIBKML (
 "  <Option name='LISTSTYLE_ICON_HREF' type='string' description='URL of the icon to display for the layer folder. Sets the href element of the <ItemIcon> element'/>"
 "</LayerCreationOptionList>");
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-        
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES, "Integer Real String" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
+                               "Integer Real String" );
 
-        poDriver->pfnOpen = OGRLIBKMLDriverOpen;
-        poDriver->pfnIdentify = OGRLIBKMLDriverIdentify;
-        poDriver->pfnCreate = OGRLIBKMLDriverCreate;
-        poDriver->pfnDelete = OGRLIBKMLDriverDelete;
-        poDriver->pfnUnloadDriver = OGRLIBKMLDriverUnload;
+    poDriver->pfnOpen = OGRLIBKMLDriverOpen;
+    poDriver->pfnIdentify = OGRLIBKMLDriverIdentify;
+    poDriver->pfnCreate = OGRLIBKMLDriverCreate;
+    poDriver->pfnDelete = OGRLIBKMLDriverDelete;
+    poDriver->pfnUnloadDriver = OGRLIBKMLDriverUnload;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmlfeature.cpp b/ogr/ogrsf_frmts/libkml/ogrlibkmlfeature.cpp
index 6b956ba..360b74a 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmlfeature.cpp
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmlfeature.cpp
@@ -27,12 +27,12 @@
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
 
+#include "libkml_headers.h"
+
 #include <ogrsf_frmts.h>
 #include <ogr_geometry.h>
 #include "gdal.h"
 
-#include <kml/dom.h>
-
 using kmldom::KmlFactory;
 using kmldom::PlacemarkPtr;
 using kmldom::ElementPtr;
@@ -58,6 +58,7 @@ using kmldom::ImagePyramidPtr;
 #include "ogrlibkmlgeometry.h"
 #include "ogrlibkmlfield.h"
 #include "ogrlibkmlfeaturestyle.h"
+#include "ogrlibkmlfeature.h"
 
 static CameraPtr feat2kmlcamera( const struct fieldconfig& oFC,
                                  int iHeading,
@@ -87,11 +88,11 @@ static CameraPtr feat2kmlcamera( const struct fieldconfig& oFC,
                 poOgrFeat->GetFieldAsString(iCameraAltitudeModeField), isGX);
             camera->set_altitudemode(nAltitudeMode);
         }
-        else if( CSLTestBoolean(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+        else if( CPLTestBool(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
             CPLError(CE_Warning, CPLE_AppDefined, "Camera should define altitudeMode != 'clampToGround'");
         if( iCameraAltitudeField >= 0 && poOgrFeat->IsFieldSet(iCameraAltitudeField))
             camera->set_altitude(poOgrFeat->GetFieldAsDouble(iCameraAltitudeField));
-        else if( CSLTestBoolean(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+        else if( CPLTestBool(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
         {
             CPLError(CE_Warning, CPLE_AppDefined, "Camera should have an altitude/Z");
             camera->set_altitude(0.0);
@@ -117,7 +118,7 @@ static CPLString OGRLIBKMLReplaceLevelXYInURL(const char* pszURL,
                                               int level, int x, int y)
 {
     CPLString osRet(pszURL);
-    int nPos = osRet.find("$[level]");
+    size_t nPos = osRet.find("$[level]");
     osRet = osRet.substr(0, nPos) + CPLSPrintf("%d", level) + osRet.substr(nPos + strlen("$[level]"));
     nPos = osRet.find("$[x]");
     osRet = osRet.substr(0, nPos) + CPLSPrintf("%d", x) + osRet.substr(nPos + strlen("$[x]"));
@@ -145,7 +146,7 @@ static int IsPowerOf2(int nVal)
 /*                    OGRLIBKMLGetMaxDimensions()                       */
 /************************************************************************/
 
-static void OGRLIBKMLGetMaxDimensions(const char* pszURL, 
+static void OGRLIBKMLGetMaxDimensions(const char* pszURL,
                                       int nTileSize,
                                       int* panMaxWidth,
                                       int* panMaxHeight)
@@ -154,7 +155,7 @@ static void OGRLIBKMLGetMaxDimensions(const char* pszURL,
     int nMaxLevel = 0;
     *panMaxWidth = 0;
     *panMaxHeight = 0;
-    while( TRUE )
+    while( true )
     {
         CPLString osURL = OGRLIBKMLReplaceLevelXYInURL(pszURL, nMaxLevel, 0, 0);
         if( strstr(osURL, ".kmz/") )
@@ -357,7 +358,7 @@ FeaturePtr feat2kml (
             poKmlViewVolume->set_bottomfov(dfBottomFov);
             poKmlViewVolume->set_topfov(dfTopFov);
             poKmlViewVolume->set_near(dfNear);
-            
+
             if( bIsTiledPhotoOverlay )
             {
                 ImagePyramidPtr poKmlImagePyramid = poKmlFactory->CreateImagePyramid( );
@@ -398,10 +399,10 @@ FeaturePtr feat2kml (
         int iFlyToView = poOgrFeat->GetFieldIndex(oFC.networklink_flytoview_field);
 
         if( iRefreshVisibility >= 0 && poOgrFeat->IsFieldSet(iRefreshVisibility) )
-            poKmlNetworkLink->set_refreshvisibility(poOgrFeat->GetFieldAsInteger(iRefreshVisibility));
+            poKmlNetworkLink->set_refreshvisibility(CPL_TO_BOOL(poOgrFeat->GetFieldAsInteger(iRefreshVisibility)));
 
         if( iFlyToView >= 0 && poOgrFeat->IsFieldSet(iFlyToView) )
-            poKmlNetworkLink->set_flytoview(poOgrFeat->GetFieldAsInteger(iFlyToView));
+            poKmlNetworkLink->set_flytoview(CPL_TO_BOOL(poOgrFeat->GetFieldAsInteger(iFlyToView)));
 
         LinkPtr poKmlLink = poKmlFactory->CreateLink (  );
         poKmlLink->set_href( poOgrFeat->GetFieldAsString( iNetworkLink ) );
@@ -484,7 +485,7 @@ FeaturePtr feat2kml (
             const char* pszHttpQuery = poOgrFeat->GetFieldAsString(iHttpQuery);
             if( strstr(pszHttpQuery, "[clientVersion]") != NULL ||
                 strstr(pszHttpQuery, "[kmlVersion]") != NULL ||
-                strstr(pszHttpQuery, "[clientName]") != NULL || 
+                strstr(pszHttpQuery, "[clientName]") != NULL ||
                 strstr(pszHttpQuery, "[language]") != NULL ) /* ATC 47 */
             {
                 poKmlLink->set_httpquery(pszHttpQuery);
@@ -523,7 +524,7 @@ FeaturePtr feat2kml (
             if( nAltitudeMode != kmldom::ALTITUDEMODE_CLAMPTOGROUND &&
                 poOgrPoint->getCoordinateDimension() != 3 )
             {
-                if( CSLTestBoolean(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+                if( CPLTestBool(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
                     CPLError(CE_Warning, CPLE_AppDefined, "Altitude should be defined");
             }
         }
@@ -550,7 +551,7 @@ FeaturePtr feat2kml (
         int iScaleX = poOgrFeat->GetFieldIndex(oFC.scalexfield);
         int iScaleY = poOgrFeat->GetFieldIndex(oFC.scaleyfield);
         int iScaleZ = poOgrFeat->GetFieldIndex(oFC.scalezfield);
-        
+
         ScalePtr scale = poKmlFactory->CreateScale();
         model->set_scale(scale);
         if( iScaleX >= 0 && poOgrFeat->IsFieldSet(iScaleX) )
@@ -573,12 +574,12 @@ FeaturePtr feat2kml (
 
         /* Collada 3D file ? */
         if( EQUAL(CPLGetExtension(pszURL), "dae") &&
-            CSLTestBoolean(CPLGetConfigOption("LIBKML_ADD_RESOURCE_MAP", "TRUE")) )
+            CPLTestBool(CPLGetConfigOption("LIBKML_ADD_RESOURCE_MAP", "TRUE")) )
         {
             VSILFILE* fp;
             int bIsURL = FALSE;
-            if( EQUALN(pszURL, "http://", strlen("http://")) ||
-                EQUALN(pszURL, "https://", strlen("https://")) )
+            if( STARTS_WITH_CI(pszURL, "http://") ||
+                STARTS_WITH_CI(pszURL, "https://") )
             {
                 bIsURL = TRUE;
                 fp = VSIFOpenL(CPLSPrintf("/vsicurl/%s", pszURL), "rb");
@@ -617,7 +618,7 @@ FeaturePtr feat2kml (
                                 AliasPtr alias = poKmlFactory->CreateAlias();
                                 if( bIsURL && CPLIsFilenameRelative(osImage) )
                                 {
-                                    if( strncmp(pszURL, "http", 4) == 0 )
+                                    if( STARTS_WITH(pszURL, "http") )
                                         alias->set_targethref(CPLSPrintf("%s/%s", CPLGetPath(pszURL), osImage.c_str()));
                                     else
                                         alias->set_targethref(CPLFormFilename(CPLGetPath(pszURL), osImage, NULL));
@@ -651,7 +652,7 @@ FeaturePtr feat2kml (
         poKmlFeature = poKmlPlacemark;
 
         OGRPoint* poOgrPoint = (OGRPoint*) poOgrGeom;
-        CameraPtr camera = poKmlFactory->CreateCamera();
+        camera = poKmlFactory->CreateCamera();
         camera->set_latitude(poOgrPoint->getY());
         camera->set_longitude(poOgrPoint->getX());
         int isGX = FALSE;
@@ -663,11 +664,11 @@ FeaturePtr feat2kml (
                 poOgrFeat->GetFieldAsString(iAltitudeMode), isGX);
             camera->set_altitudemode(nAltitudeMode);
         }
-        else if( CSLTestBoolean(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+        else if( CPLTestBool(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
             CPLError(CE_Warning, CPLE_AppDefined, "Camera should define altitudeMode != 'clampToGround'");
         if( poOgrPoint->getCoordinateDimension() == 3 )
             camera->set_altitude(poOgrPoint->getZ());
-        else if( CSLTestBoolean(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+        else if( CPLTestBool(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
         {
             CPLError(CE_Warning, CPLE_AppDefined, "Camera should have an altitude/Z");
             camera->set_altitude(0.0);
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmlfeature.h b/ogr/ogrsf_frmts/libkml/ogrlibkmlfeature.h
index e7c3f3b..f0ccf80 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmlfeature.h
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmlfeature.h
@@ -26,15 +26,15 @@
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
 
-#include <kml/dom.h>
+#ifndef OGR_LIBKML_FEATURE_H
+#define OGR_LIBKML_FEATURE_H
+
+#include "ogr_libkml.h"
 
 using kmldom::KmlFactory;
 using kmldom::FeaturePtr;
 using kmldom::PlacemarkPtr;
 
-#include "ogr_libkml.h"
-
-
 /******************************************************************************
  function to output a ogr feature to a kml placemark
 ******************************************************************************/
@@ -63,3 +63,5 @@ OGRFeature *kmlgroundoverlay2feat (
     OGRLayer * poOgrLayer,
     OGRFeatureDefn * poOgrFeatDefn,
     OGRSpatialReference *poOgrSRS);
+
+#endif /*  OGR_LIBKML_FEATURE_H */
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmlfeaturestyle.cpp b/ogr/ogrsf_frmts/libkml/ogrlibkmlfeaturestyle.cpp
index 1c32222..ed61d50 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmlfeaturestyle.cpp
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmlfeaturestyle.cpp
@@ -27,14 +27,14 @@
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
 
+#include "libkml_headers.h"
+
 #include <ogrsf_frmts.h>
 #include <ogr_featurestyle.h>
 #include <string>
 #include <iostream>
 using namespace std;
 
-#include <kml/dom.h>
-
 using kmldom::KmlFactory;;
 using kmldom::IconStylePtr;
 using kmldom::PolyStylePtr;
@@ -88,10 +88,10 @@ void featurestyle2kml (
 
             /***** is the name in the layer style table *****/
 
-            OGRStyleTable *hSTBLLayer;
+            OGRStyleTable *hSTBLLayer = poOgrLayer->GetStyleTable (  );
             const char *pszTest = NULL;
 
-            if ( ( hSTBLLayer = poOgrLayer->GetStyleTable (  ) ) )
+            if ( hSTBLLayer != NULL )
                 pszTest = hSTBLLayer->Find ( pszStyleName );
 
             if ( pszTest ) {
@@ -134,7 +134,7 @@ void featurestyle2kml (
 
     /***** get the style table *****/
 
-    else if ( ( poOgrSTBL = poOgrFeat->GetStyleTable (  ) ) ) {
+    else if ( ( poOgrSTBL = poOgrFeat->GetStyleTable (  ) ) != NULL ) {
 
 
         StylePtr poKmlStyle = NULL;
@@ -142,9 +142,8 @@ void featurestyle2kml (
         /***** parse the style table *****/
 
         poOgrSTBL->ResetStyleStringReading (  );
-        const char *pszStyleString;
 
-        while ( ( pszStyleString = poOgrSTBL->GetNextStyle (  ) ) ) {
+        while ( ( pszStyleString = poOgrSTBL->GetNextStyle (  ) ) != NULL ) {
 
             if ( *pszStyleString == '@' ) {
 
@@ -153,23 +152,22 @@ void featurestyle2kml (
                 /***** is the name in the layer style table *****/
 
                 OGRStyleTable *poOgrSTBLLayer;
-                const char *pszTest = NULL;
+                // const char *pszTest = NULL;
 
-                if ( ( poOgrSTBLLayer = poOgrLayer->GetStyleTable (  ) ) )
+                if ( ( poOgrSTBLLayer = poOgrLayer->GetStyleTable (  ) ) != NULL )
                     poOgrSTBLLayer->Find ( pszStyleName );
 
-                if ( pszTest ) {
-                    string oTmp = "#";
-
-                    oTmp.append ( pszStyleName );
-
-                    poKmlFeature->set_styleurl ( oTmp );
-                }
+                // if ( pszTest ) {
+                //     string oTmp = "#";
+                //     oTmp.append ( pszStyleName );
+                //     poKmlFeature->set_styleurl ( oTmp );
+                // }
 
                 /***** assume its a dataset style,      *****/
                 /***** mayby the user will add it later *****/
 
-                else {
+                /* else */
+                {
                     string oTmp;
 
                     if ( poOgrDS->GetStylePath (  ) )
@@ -227,7 +225,7 @@ void kml2featurestyle (
         /***** is it a layer style ? *****/
 
         if ( *pszUrl == '#'
-             && ( poOgrSTBLLayer = poOgrLayer->GetStyleTable (  ) ) )
+             && ( poOgrSTBLLayer = poOgrLayer->GetStyleTable (  ) ) != NULL )
         {
              pszTest = poOgrSTBLLayer->Find ( pszUrl + 1 );
         }
@@ -238,7 +236,7 @@ void kml2featurestyle (
 
             const char *pszResolve = CPLGetConfigOption ( "LIBKML_RESOLVE_STYLE", "no" );
 
-            if (CSLTestBoolean(pszResolve)) {
+            if (CPLTestBool(pszResolve)) {
 
                 poOgrFeat->SetStyleString ( pszTest );
             }
@@ -254,10 +252,10 @@ void kml2featurestyle (
         }
 
         /***** is it a dataset style? *****/
-        
+
         else {
 
-            int nPathLen = strlen ( poOgrDS->GetStylePath (  ) );
+            int nPathLen = static_cast<int>(strlen ( poOgrDS->GetStylePath (  ) ));
 
             if (    nPathLen == 0
                  || EQUALN ( pszUrl, poOgrDS->GetStylePath (  ), nPathLen ))
@@ -267,9 +265,9 @@ void kml2featurestyle (
 
                 const char *pszResolve = CPLGetConfigOption ( "LIBKML_RESOLVE_STYLE", "no" );
 
-                if (    CSLTestBoolean(pszResolve)
-                     && ( poOgrSTBLLayer = poOgrDS->GetStyleTable (  ) )
-                     && ( pszTest = poOgrSTBLLayer->Find ( pszUrl + nPathLen + 1) )
+                if ( CPLTestBool(pszResolve)
+                     && ( poOgrSTBLLayer = poOgrDS->GetStyleTable (  ) ) != NULL
+                     && ( pszTest = poOgrSTBLLayer->Find ( pszUrl + nPathLen + 1) ) != NULL
                    )
                 {
 
@@ -281,23 +279,22 @@ void kml2featurestyle (
                     pszUrl[nPathLen] = '@';
                     poOgrFeat->SetStyleString ( pszUrl + nPathLen );
                 }
-       
+
             }
-            
+
             /**** its someplace else *****/
 
             else {
 
                 const char *pszFetch = CPLGetConfigOption ( "LIBKML_EXTERNAL_STYLE", "no" );
 
-                if ( CSLTestBoolean(pszFetch) ) {
+                if ( CPLTestBool(pszFetch) ) {
 
                     /***** load up the style table *****/
 
                     char *pszUrlTmp = CPLStrdup(pszUrl);
-                    char *pszPound;
-                    if ((pszPound = strchr(pszUrlTmp, '#'))) {
-                        
+                    char *pszPound = strchr(pszUrlTmp, '#');
+                    if (pszPound != NULL) {
                         *pszPound = '\0';
                     }
 
@@ -308,8 +305,8 @@ void kml2featurestyle (
                     if (    (fp = VSIFOpenL( CPLFormFilename( "/vsicurl/",
                                                               pszUrlTmp,
                                                               NULL),
-                                             "r" ))
-                        ||  (fp = VSIFOpenL( pszUrlTmp, "r" )))
+                                             "r" )) != NULL
+                        ||  (fp = VSIFOpenL( pszUrlTmp, "r" )) != NULL )
                     {
 
                         char szbuf[1025];
@@ -318,11 +315,11 @@ void kml2featurestyle (
                         /***** loop, read and copy to a string *****/
 
                         size_t nRead;
-                    
+
                         do {
-                            
+
                             nRead = VSIFReadL(szbuf, 1, sizeof(szbuf) - 1, fp);
-                            
+
                             if (nRead == 0)
                                 break;
 
@@ -380,17 +377,17 @@ void kml2featurestyle (
 
             OGRStyleMgr *poOgrSM = new OGRStyleMgr;
 
-            /***** if were resolveing style the feature  *****/
+            /***** if were resolving style the feature *****/
             /***** might already have styling to add too *****/
-            
+
             const char *pszResolve = CPLGetConfigOption ( "LIBKML_RESOLVE_STYLE", "no" );
-            if (CSLTestBoolean(pszResolve)) {
+            if (CPLTestBool(pszResolve)) {
                  poOgrSM->InitFromFeature ( poOgrFeat );
             }
             else {
 
                 /***** if featyurestyle gets a name tool this needs changed to the above *****/
-                
+
                 poOgrSM->InitStyleString ( NULL );
             }
 
@@ -399,7 +396,7 @@ void kml2featurestyle (
             kml2stylestring ( poKmlStyle, poOgrSM );
 
             /***** add the style to the feature *****/
-            
+
             poOgrFeat->SetStyleString(poOgrSM->GetStyleString(NULL));
 
             delete poOgrSM;
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmlfield.cpp b/ogr/ogrsf_frmts/libkml/ogrlibkmlfield.cpp
index cc1f38b..7d31fd2 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmlfield.cpp
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmlfield.cpp
@@ -27,11 +27,12 @@
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
 
+#include "libkml_headers.h"
+
 #include  <ogrsf_frmts.h>
 #include <ogr_feature.h>
 #include "ogr_p.h"
 
-#include <kml/dom.h>
 #include <iostream>
 
 using kmldom::ExtendedDataPtr;
@@ -63,7 +64,7 @@ using kmldom::GxMultiTrackPtr;
 
 #include "ogrlibkmlfield.h"
 
-void ogr2altitudemode_rec (
+static void ogr2altitudemode_rec (
     GeometryPtr poKmlGeometry,
     int iAltitudeMode,
     int isGX )
@@ -131,8 +132,8 @@ void ogr2altitudemode_rec (
 
 }
 
-void ogr2extrude_rec (
-    int nExtrude,
+static void ogr2extrude_rec (
+    bool bExtrude,
     GeometryPtr poKmlGeometry )
 {
 
@@ -147,12 +148,12 @@ void ogr2extrude_rec (
     switch ( poKmlGeometry->Type (  ) ) {
     case kmldom::Type_Point:
         poKmlPoint = AsPoint ( poKmlGeometry );
-        poKmlPoint->set_extrude ( nExtrude );
+        poKmlPoint->set_extrude ( bExtrude );
         break;
 
     case kmldom::Type_LineString:
         poKmlLineString = AsLineString ( poKmlGeometry );
-        poKmlLineString->set_extrude ( nExtrude );
+        poKmlLineString->set_extrude ( bExtrude );
         break;
 
     case kmldom::Type_LinearRing:
@@ -160,7 +161,7 @@ void ogr2extrude_rec (
 
     case kmldom::Type_Polygon:
         poKmlPolygon = AsPolygon ( poKmlGeometry );
-        poKmlPolygon->set_extrude ( nExtrude );
+        poKmlPolygon->set_extrude ( bExtrude );
         break;
 
     case kmldom::Type_MultiGeometry:
@@ -168,7 +169,7 @@ void ogr2extrude_rec (
 
         nGeom = poKmlMultiGeometry->get_geometry_array_size (  );
         for ( i = 0; i < nGeom; i++ ) {
-            ogr2extrude_rec ( nExtrude,
+            ogr2extrude_rec ( bExtrude,
                               poKmlMultiGeometry->
                               get_geometry_array_at ( i ) );
         }
@@ -180,8 +181,8 @@ void ogr2extrude_rec (
     }
 }
 
-void ogr2tessellate_rec (
-    int nTessellate,
+static void ogr2tessellate_rec (
+    bool bTessellate,
     GeometryPtr poKmlGeometry )
 {
 
@@ -199,7 +200,7 @@ void ogr2tessellate_rec (
 
     case kmldom::Type_LineString:
         poKmlLineString = AsLineString ( poKmlGeometry );
-        poKmlLineString->set_tessellate ( nTessellate );
+        poKmlLineString->set_tessellate ( bTessellate );
         break;
 
     case kmldom::Type_LinearRing:
@@ -208,7 +209,7 @@ void ogr2tessellate_rec (
     case kmldom::Type_Polygon:
         poKmlPolygon = AsPolygon ( poKmlGeometry );
 
-        poKmlPolygon->set_tessellate ( nTessellate );
+        poKmlPolygon->set_tessellate ( bTessellate );
         break;
 
     case kmldom::Type_MultiGeometry:
@@ -216,7 +217,7 @@ void ogr2tessellate_rec (
 
         nGeom = poKmlMultiGeometry->get_geometry_array_size (  );
         for ( i = 0; i < nGeom; i++ ) {
-            ogr2tessellate_rec ( nTessellate,
+            ogr2tessellate_rec ( bTessellate,
                                  poKmlMultiGeometry->
                                  get_geometry_array_at ( i ) );
         }
@@ -237,7 +238,7 @@ void ogr2tessellate_rec (
 static char* OGRLIBKMLSanitizeUTF8String(const char* pszString)
 {
     if (!CPLIsUTF8(pszString, -1) &&
-         CSLTestBoolean(CPLGetConfigOption("OGR_FORCE_ASCII", "YES")))
+         CPLTestBool(CPLGetConfigOption("OGR_FORCE_ASCII", "YES")))
     {
         static int bFirstTime = TRUE;
         if (bFirstTime)
@@ -268,7 +269,7 @@ static char* OGRLIBKMLSanitizeUTF8String(const char* pszString)
         poOgrLayer      pointer to the layer the feature is in
         poKmlFactory    pointer to the libkml dom factory
         poKmlPlacemark  pointer to the placemark to add to
- 
+
  returns:
         nothing
 
@@ -282,8 +283,6 @@ static char* OGRLIBKMLSanitizeUTF8String(const char* pszString)
 
 ******************************************************************************/
 
-
-
 void field2kml (
     OGRFeature * poOgrFeat,
     OGRLIBKMLLayer * poOgrLayer,
@@ -317,7 +316,7 @@ void field2kml (
 
     struct fieldconfig oFC;
     get_fieldconfig( &oFC );
-    
+
     TimeSpanPtr poKmlTimeSpan = NULL;
 
     int nFields = poOgrFeat->GetFieldCount (  );
@@ -397,7 +396,7 @@ void field2kml (
 
                     continue;
                 }
-                
+
                 /***** timestamp *****/
 
                 else if ( EQUAL ( name, oFC.tsfield ) ) {
@@ -666,7 +665,7 @@ void field2kml (
                         int iExtrude = poOgrFeat->GetFieldAsInteger ( i );
                         if( iExtrude &&
                             isGX == FALSE && iAltitudeMode == kmldom::ALTITUDEMODE_CLAMPTOGROUND &&
-                            CSLTestBoolean(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+                            CPLTestBool(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
                         {
                             CPLError(CE_Warning, CPLE_NotSupported,
                                 "altitudeMode=clampToGround unsupported with extrude=1");
@@ -675,7 +674,7 @@ void field2kml (
                         {
                             GeometryPtr poKmlGeometry =
                                 poKmlPlacemark->get_geometry (  );
-                            ogr2extrude_rec ( iExtrude,
+                            ogr2extrude_rec ( CPL_TO_BOOL(iExtrude),
                                             poKmlGeometry );
                         }
                     }
@@ -694,18 +693,20 @@ void field2kml (
                         && -1 < poOgrFeat->GetFieldAsInteger ( i ) ) {
                         int iTesselate = poOgrFeat->GetFieldAsInteger ( i );
                         if( iTesselate &&
-                            !(isGX == FALSE && iAltitudeMode == kmldom::ALTITUDEMODE_CLAMPTOGROUND) &&
-                            !(isGX == TRUE && iAltitudeMode == kmldom::GX_ALTITUDEMODE_CLAMPTOSEAFLOOR) &&
-                            CSLTestBoolean(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+                            !(isGX == FALSE && static_cast<kmldom::AltitudeModeEnum>(iAltitudeMode) == kmldom::ALTITUDEMODE_CLAMPTOGROUND) &&
+                            !(isGX == TRUE && static_cast<kmldom::GxAltitudeModeEnum>(iAltitudeMode) == kmldom::GX_ALTITUDEMODE_CLAMPTOSEAFLOOR) &&
+                            CPLTestBool(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
                         {
-                            CPLError(CE_Warning, CPLE_NotSupported,
-                                "altitudeMode!=clampToGround && altitudeMode!=clampToSeaFloor unsupported with tesselate=1");
+                            CPLError( CE_Warning, CPLE_NotSupported,
+                                      "altitudeMode!=clampToGround && "
+                                      "altitudeMode!=clampToSeaFloor "
+                                      "unsupported with tessellate=1" );
                         }
                         else
                         {
                             GeometryPtr poKmlGeometry =
                                 poKmlPlacemark->get_geometry (  );
-                            ogr2tessellate_rec ( iTesselate,
+                            ogr2tessellate_rec ( CPL_TO_BOOL(iTesselate),
                                                 poKmlGeometry );
                             if( isGX == FALSE && iAltitudeMode == kmldom::ALTITUDEMODE_CLAMPTOGROUND )
                                 ogr2altitudemode_rec ( poKmlGeometry, iAltitudeMode,
@@ -722,8 +723,8 @@ void field2kml (
 
             if ( EQUAL ( name, oFC.visibilityfield ) ) {
                 if ( -1 < poOgrFeat->GetFieldAsInteger ( i ) )
-                    poKmlFeature->set_visibility ( poOgrFeat->
-                                                     GetFieldAsInteger ( i ) );
+                    poKmlFeature->set_visibility ( CPL_TO_BOOL(poOgrFeat->
+                                                     GetFieldAsInteger ( i )) );
 
                 continue;
             }
@@ -830,7 +831,7 @@ void field2kml (
 
             break;
         }
-        
+
         if( poKmlSimpleData )
         {
             poKmlSchemaData->add_simpledata ( poKmlSimpleData );
@@ -843,7 +844,7 @@ void field2kml (
         }
     }
 
-    /***** dont add it to the placemark unless there is data *****/
+    // Do not add it to the placemark unless there is data.
 
     if ( bUseSimpleField && poKmlSchemaData->get_simpledata_array_size (  ) > 0 ) {
         poKmlExtendedData = poKmlFactory->CreateExtendedData (  );
@@ -861,7 +862,7 @@ void field2kml (
  recursive function to read altitude mode from the geometry
 ******************************************************************************/
 
-int kml2altitudemode_rec (
+static int kml2altitudemode_rec (
     GeometryPtr poKmlGeometry,
     int *pnAltitudeMode,
     int *pbIsGX )
@@ -949,9 +950,9 @@ int kml2altitudemode_rec (
  recursive function to read extrude from the geometry
 ******************************************************************************/
 
-int kml2extrude_rec (
+static int kml2extrude_rec (
     GeometryPtr poKmlGeometry,
-    int *pnExtrude )
+    bool *pbExtrude )
 {
 
     PointPtr poKmlPoint;
@@ -968,7 +969,7 @@ int kml2extrude_rec (
         poKmlPoint = AsPoint ( poKmlGeometry );
 
         if ( poKmlPoint->has_extrude (  ) ) {
-            *pnExtrude = poKmlPoint->get_extrude (  );
+            *pbExtrude = poKmlPoint->get_extrude (  );
             return TRUE;
         }
 
@@ -978,7 +979,7 @@ int kml2extrude_rec (
         poKmlLineString = AsLineString ( poKmlGeometry );
 
         if ( poKmlLineString->has_extrude (  ) ) {
-            *pnExtrude = poKmlLineString->get_extrude (  );
+            *pbExtrude = poKmlLineString->get_extrude (  );
             return TRUE;
         }
 
@@ -991,7 +992,7 @@ int kml2extrude_rec (
         poKmlPolygon = AsPolygon ( poKmlGeometry );
 
         if ( poKmlPolygon->has_extrude (  ) ) {
-            *pnExtrude = poKmlPolygon->get_extrude (  );
+            *pbExtrude = poKmlPolygon->get_extrude (  );
             return TRUE;
         }
 
@@ -1003,7 +1004,7 @@ int kml2extrude_rec (
         nGeom = poKmlMultiGeometry->get_geometry_array_size (  );
         for ( i = 0; i < nGeom; i++ ) {
             if ( kml2extrude_rec ( poKmlMultiGeometry->
-                                   get_geometry_array_at ( i ), pnExtrude ) )
+                                   get_geometry_array_at ( i ), pbExtrude ) )
                 return TRUE;
         }
 
@@ -1021,7 +1022,7 @@ int kml2extrude_rec (
  recursive function to read tessellate from the geometry
 ******************************************************************************/
 
-int kml2tessellate_rec (
+static int kml2tessellate_rec (
     GeometryPtr poKmlGeometry,
     int *pnTessellate )
 {
@@ -1175,7 +1176,7 @@ void kml2field (
 
     struct fieldconfig oFC;
     get_fieldconfig( &oFC );
-    
+
     /***** name *****/
 
     if ( poKmlFeature->has_name (  ) ) {
@@ -1233,7 +1234,7 @@ void kml2field (
     }
 
     /***** placemark *****/
-    
+
     PlacemarkPtr poKmlPlacemark = AsPlacemark ( poKmlFeature );
     GroundOverlayPtr poKmlGroundOverlay = AsGroundOverlay ( poKmlFeature );
     if ( poKmlPlacemark && poKmlPlacemark->has_geometry (  ) ) {
@@ -1268,17 +1269,17 @@ void kml2field (
 
         /***** extrude *****/
 
-        int nExtrude = -1;
+        bool bExtrude = false;
 
-        kml2extrude_rec ( poKmlGeometry, &nExtrude );
+        kml2extrude_rec ( poKmlGeometry, &bExtrude );
 
         iField = poOgrFeat->GetFieldIndex ( oFC.extrudefield );
         if ( iField > -1 )
-            poOgrFeat->SetField ( iField, nExtrude );
+            poOgrFeat->SetField ( iField, bExtrude ? 1 : 0 );
 
         /***** special case for gx:Track ******/
         /* we set the first timestamp as begin and the last one as end */
-        if ( poKmlGeometry->Type (  )  == kmldom::Type_GxTrack && 
+        if ( poKmlGeometry->Type (  )  == kmldom::Type_GxTrack &&
              !poKmlFeature->has_timeprimitive (  ) ) {
             GxTrackPtr poKmlGxTrack = AsGxTrack ( poKmlGeometry );
             size_t nCoords = poKmlGxTrack->get_gx_coord_array_size();
@@ -1293,7 +1294,7 @@ void kml2field (
 
         /***** special case for gx:MultiTrack ******/
         /* we set the first timestamp as begin and the last one as end */
-        else if ( poKmlGeometry->Type (  )  == kmldom::Type_GxMultiTrack && 
+        else if ( poKmlGeometry->Type (  )  == kmldom::Type_GxMultiTrack &&
              !poKmlFeature->has_timeprimitive (  ) ) {
             GxMultiTrackPtr poKmlGxMultiTrack = AsGxMultiTrack ( poKmlGeometry );
             size_t nGeom = poKmlGxMultiTrack->get_gx_track_array_size (  );
@@ -1317,9 +1318,9 @@ void kml2field (
             }
         }
     }
-    
+
     /***** camera *****/
-    
+
     else if ( poKmlPlacemark &&
               poKmlPlacemark->has_abstractview (  ) &&
               poKmlPlacemark->get_abstractview()->IsA( kmldom::Type_Camera) ) {
@@ -1481,7 +1482,7 @@ void kml2field (
 
                 /***** find the field index *****/
 
-                int iField = -1;
+                iField = -1;
 
                 if ( poKmlSimpleData->has_name (  ) ) {
                     const string oName = poKmlSimpleData->get_name (  );
@@ -1503,7 +1504,7 @@ void kml2field (
         if (nSchemaData == 0 &&  poKmlExtendedData->get_data_array_size() > 0 )
         {
             int bLaunderFieldNames =
-                        CSLTestBoolean(CPLGetConfigOption("LIBKML_LAUNDER_FIELD_NAMES", "YES"));
+                CPLTestBool(CPLGetConfigOption("LIBKML_LAUNDER_FIELD_NAMES", "YES"));
             size_t nDataArraySize = poKmlExtendedData->get_data_array_size();
             for(size_t i=0; i < nDataArraySize; i++)
             {
@@ -1513,7 +1514,7 @@ void kml2field (
                     CPLString osName = data->get_name();
                     if (bLaunderFieldNames)
                         osName = OGRLIBKMLLayer::LaunderFieldNames(osName);
-                    int iField = poOgrFeat->GetFieldIndex ( osName );
+                    iField = poOgrFeat->GetFieldIndex ( osName );
                     if (iField >= 0)
                     {
                         poOgrFeat->SetField ( iField, data->get_value().c_str() );
@@ -1599,12 +1600,12 @@ SimpleFieldPtr FieldDef2kml (
     case OFTIntegerList:
         poKmlSimpleField->set_type ( "int" );
         return poKmlSimpleField;
-			
+
     case OFTReal:
     case OFTRealList:
         poKmlSimpleField->set_type ( "float" );
         return poKmlSimpleField;
-	
+
     case OFTString:
     case OFTStringList:
         poKmlSimpleField->set_type ( "string" );
@@ -1694,11 +1695,11 @@ void kml2FeatureDef (
 
 /*******************************************************************************
  * function to fetch the field config options
- * 
+ *
 *******************************************************************************/
 
 void get_fieldconfig( struct fieldconfig *oFC) {
-	
+
     oFC->namefield = CPLGetConfigOption ( "LIBKML_NAME_FIELD",
                                                   "Name" );
     oFC->descfield = CPLGetConfigOption ( "LIBKML_DESCRIPTION_FIELD",
@@ -1764,26 +1765,26 @@ int kmlAltitudeModeFromString(const char* pszAltitudeMode,
                               int& isGX)
 {
     isGX = FALSE;
-    int iAltitudeMode = kmldom::ALTITUDEMODE_CLAMPTOGROUND;
+    int iAltitudeMode = static_cast<int>(kmldom::ALTITUDEMODE_CLAMPTOGROUND);
 
     if ( EQUAL ( pszAltitudeMode, "clampToGround" ) )
-        iAltitudeMode = kmldom::ALTITUDEMODE_CLAMPTOGROUND;
+        iAltitudeMode = static_cast<int>(kmldom::ALTITUDEMODE_CLAMPTOGROUND);
 
     else if ( EQUAL ( pszAltitudeMode, "relativeToGround" ) )
-        iAltitudeMode = kmldom::ALTITUDEMODE_RELATIVETOGROUND;
+        iAltitudeMode = static_cast<int>(kmldom::ALTITUDEMODE_RELATIVETOGROUND);
 
     else if ( EQUAL ( pszAltitudeMode, "absolute" ) )
-        iAltitudeMode = kmldom::ALTITUDEMODE_ABSOLUTE;
+        iAltitudeMode = static_cast<int>(kmldom::ALTITUDEMODE_ABSOLUTE);
 
     else if ( EQUAL ( pszAltitudeMode, "relativeToSeaFloor" ) ) {
         iAltitudeMode =
-            kmldom::GX_ALTITUDEMODE_RELATIVETOSEAFLOOR;
+            static_cast<int>(kmldom::GX_ALTITUDEMODE_RELATIVETOSEAFLOOR);
         isGX = TRUE;
     }
 
     else if ( EQUAL ( pszAltitudeMode, "clampToSeaFloor" ) ) {
         iAltitudeMode =
-            kmldom::GX_ALTITUDEMODE_CLAMPTOSEAFLOOR;
+            static_cast<int>(kmldom::GX_ALTITUDEMODE_CLAMPTOSEAFLOOR);
         isGX = TRUE;
     }
     else
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmlfield.h b/ogr/ogrsf_frmts/libkml/ogrlibkmlfield.h
index 1fa885a..d209338 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmlfield.h
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmlfield.h
@@ -41,7 +41,7 @@ using kmldom::PlacemarkPtr;
         poOgrLayer      pointer to the layer the feature is in
         poKmlFactory    pointer to the libkml dom factory
         poKmlPlacemark  pointer to the placemark to add to
- 
+
  returns:
         nothing
 
@@ -88,7 +88,7 @@ void kml2FeatureDef (
 
 /*******************************************************************************
  * function to fetch the field config options
- * 
+ *
 *******************************************************************************/
 
 struct fieldconfig {
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmlgeometry.cpp b/ogr/ogrsf_frmts/libkml/ogrlibkmlgeometry.cpp
index 697581e..c780a9f 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmlgeometry.cpp
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmlgeometry.cpp
@@ -27,9 +27,10 @@
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
 
+#include "libkml_headers.h"
+
 #include <ogr_geometry.h>
 #include "ogr_p.h"
-#include <kml/dom.h>
 
 using kmldom::KmlFactory;
 using kmldom::CoordinatesPtr;
@@ -53,7 +54,7 @@ using kmlbase::Vec3;
 #include "ogrlibkmlgeometry.h"
 
 /******************************************************************************
- funtion to write out a ogr geometry to kml
+ function to write out a ogr geometry to kml
 
 args:
           poOgrGeom     the ogr geometry
@@ -160,8 +161,8 @@ ElementPtr geom2kml (
         numpoints = poOgrLineString->getNumPoints (  );
         if( extra >= 0 )
         {
-            if( numpoints < 4 && 
-                CSLTestBoolean(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+            if( numpoints < 4 &&
+                CPLTestBool(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
             {
                 CPLError(CE_Failure, CPLE_NotSupported, "A linearring should have at least 4 points");
                 return NULL;
@@ -169,8 +170,8 @@ ElementPtr geom2kml (
         }
         else
         {
-            if( numpoints < 2 && 
-                CSLTestBoolean(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+            if( numpoints < 2 &&
+                CPLTestBool(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
             {
                 CPLError(CE_Failure, CPLE_NotSupported, "A linestring should have at least 2 points");
                 return NULL;
@@ -205,7 +206,7 @@ ElementPtr geom2kml (
             break;
         }
 
-      /***** fallthough *****/
+      /***** fallthrough *****/
 
     case wkbLinearRing:        //this case is for readability only
 
@@ -223,6 +224,8 @@ ElementPtr geom2kml (
             poKmlInnerRing->set_linearring ( poKmlLinearRing );
         }
 
+        break;
+
     case wkbLineString25D:
 
         poOgrLineString = ( OGRLineString * ) poOgrGeom;
@@ -235,8 +238,8 @@ ElementPtr geom2kml (
         numpoints = poOgrLineString->getNumPoints (  );
         if( extra >= 0 )
         {
-            if( numpoints < 4 && 
-                CSLTestBoolean(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+            if( numpoints < 4 &&
+                CPLTestBool(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
             {
                 CPLError(CE_Failure, CPLE_NotSupported, "A linearring should have at least 4 points");
                 return NULL;
@@ -244,8 +247,8 @@ ElementPtr geom2kml (
         }
         else
         {
-            if( numpoints < 2 && 
-                CSLTestBoolean(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+            if( numpoints < 2 &&
+                CPLTestBool(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
             {
                 CPLError(CE_Failure, CPLE_NotSupported, "A linestring should have at least 2 points");
                 return NULL;
@@ -279,7 +282,7 @@ ElementPtr geom2kml (
 
             break;
         }
-            /***** fallthough *****/
+            /***** fallthrough *****/
 
         //case wkbLinearRing25D: // this case is for readability only
 
@@ -302,7 +305,7 @@ ElementPtr geom2kml (
     case wkbPolygon:
 
         CPLErrorReset();
-        if( CSLTestBoolean(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) &&
+        if( CPLTestBool(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) &&
             OGRGeometryFactory::haveGEOS() && (!poOgrGeom->IsValid() ||
              CPLGetLastErrorType() != CE_None) )
         {
@@ -331,7 +334,7 @@ ElementPtr geom2kml (
     case wkbPolygon25D:
 
         CPLErrorReset();
-        if( CSLTestBoolean(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) &&
+        if( CPLTestBool(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) &&
             OGRGeometryFactory::haveGEOS() && (!poOgrGeom->IsValid() ||
              CPLGetLastErrorType() != CE_None) )
         {
@@ -370,8 +373,8 @@ ElementPtr geom2kml (
 
         nGeom = poOgrMultiGeom->getNumGeometries (  );
 
-        if( nGeom == 1 && 
-            CSLTestBoolean(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+        if( nGeom == 1 &&
+            CPLTestBool(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
         {
             CPLDebug("LIBKML", "Turning multiple geometry into single geometry");
             poKmlGeometry = geom2kml( poOgrMultiGeom->getGeometryRef ( 0 ),
@@ -379,8 +382,8 @@ ElementPtr geom2kml (
         }
         else
         {
-            if( nGeom == 0 && 
-                CSLTestBoolean(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+            if( nGeom == 0 &&
+                CPLTestBool(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
             {
                 CPLError(CE_Warning, CPLE_AppDefined, "Empty multi geometry are not recommended");
             }
@@ -411,14 +414,14 @@ ElementPtr geom2kml (
 
 Args:
             poKmlGeometry   pointer to the kml geometry to translate
-            poOgrSRS        pointer to the spatial ref to set on the geometry 
+            poOgrSRS        pointer to the spatial ref to set on the geometry
 
 Returns:
             pointer to the new ogr geometry object
 
 ******************************************************************************/
 
-OGRGeometry *kml2geom_rec (
+static OGRGeometry *kml2geom_rec (
     GeometryPtr poKmlGeometry,
     OGRSpatialReference *poOgrSRS)
 
@@ -571,7 +574,8 @@ OGRGeometry *kml2geom_rec (
         poKmlMultiGeometry = AsMultiGeometry ( poKmlGeometry );
         nGeom = poKmlMultiGeometry->get_geometry_array_size (  );
 
-        /* Detect subgeometry type to instanciate appropriate Multi geometry type */
+        // Detect subgeometry type to instantiate appropriate
+        // multi geometry type.
         kmldom::KmlDomType type = kmldom::Type_Unknown;
         for ( i = 0; i < nGeom; i++ ) {
             poKmlTmpGeometry = poKmlMultiGeometry->get_geometry_array_at ( i );
@@ -602,7 +606,7 @@ OGRGeometry *kml2geom_rec (
         poOgrGeometry = poOgrMultiGeometry;
         break;
     }
-    
+
     case kmldom::Type_GxTrack:
         poKmlGxTrack = AsGxTrack ( poKmlGeometry );
         nCoords = poKmlGxTrack->get_gx_coord_array_size();
@@ -735,7 +739,7 @@ OGRGeometry *kml2geom_latlonquad_int (
 
 Args:
             poKmlGeometry   pointer to the kml geometry to translate
-            poOgrSRS        pointer to the spatial ref to set on the geometry 
+            poOgrSRS        pointer to the spatial ref to set on the geometry
 
 Returns:
             pointer to the new ogr geometry object
@@ -749,32 +753,32 @@ OGRGeometry *kml2geom (
 {
 
     /***** get the geometry *****/
-    
+
     OGRGeometry *poOgrGeometry = kml2geom_rec (poKmlGeometry, poOgrSRS);
 
     /***** split the geometry at the dateline? *****/
-    
+
     const char *pszWrap = CPLGetConfigOption ( "LIBKML_WRAPDATELINE", "no" );
-    if (CSLTestBoolean(pszWrap)) {
-        
+    if (CPLTestBool(pszWrap)) {
+
         char **papszTransformOptions = NULL;
         papszTransformOptions = CSLAddString( papszTransformOptions,
                                                 "WRAPDATELINE=YES");
 
         /***** transform *****/
-        
-        OGRGeometry *poOgrDstGeometry = 
+
+        OGRGeometry *poOgrDstGeometry =
             OGRGeometryFactory::transformWithOptions(poOgrGeometry,
                                                         NULL,
                                                         papszTransformOptions);
 
         /***** replace the original geom *****/
-        
+
         if (poOgrDstGeometry) {
             delete poOgrGeometry;
             poOgrGeometry = poOgrDstGeometry;
         }
-        
+
         CSLDestroy(papszTransformOptions);
     }
 
@@ -788,32 +792,32 @@ OGRGeometry *kml2geom_latlonbox (
 {
 
     /***** get the geometry *****/
-    
+
     OGRGeometry *poOgrGeometry = kml2geom_latlonbox_int (poKmlLatLonBox, poOgrSRS);
 
     /***** split the geometry at the dateline? *****/
-    
+
     const char *pszWrap = CPLGetConfigOption ( "LIBKML_WRAPDATELINE", "no" );
-    if (CSLTestBoolean(pszWrap)) {
-        
+    if (CPLTestBool(pszWrap)) {
+
         char **papszTransformOptions = NULL;
         papszTransformOptions = CSLAddString( papszTransformOptions,
                                                 "WRAPDATELINE=YES");
 
         /***** transform *****/
-        
-        OGRGeometry *poOgrDstGeometry = 
+
+        OGRGeometry *poOgrDstGeometry =
             OGRGeometryFactory::transformWithOptions(poOgrGeometry,
                                                         NULL,
                                                         papszTransformOptions);
 
         /***** replace the original geom *****/
-        
+
         if (poOgrDstGeometry) {
             delete poOgrGeometry;
             poOgrGeometry = poOgrDstGeometry;
         }
-        
+
         CSLDestroy(papszTransformOptions);
     }
 
@@ -827,32 +831,32 @@ OGRGeometry *kml2geom_latlonquad (
 {
 
     /***** get the geometry *****/
-    
+
     OGRGeometry *poOgrGeometry = kml2geom_latlonquad_int (poKmlLatLonQuad, poOgrSRS);
 
     /***** split the geometry at the dateline? *****/
-    
+
     const char *pszWrap = CPLGetConfigOption ( "LIBKML_WRAPDATELINE", "no" );
-    if (CSLTestBoolean(pszWrap)) {
-        
+    if (CPLTestBool(pszWrap)) {
+
         char **papszTransformOptions = NULL;
         papszTransformOptions = CSLAddString( papszTransformOptions,
                                                 "WRAPDATELINE=YES");
 
         /***** transform *****/
-        
-        OGRGeometry *poOgrDstGeometry = 
+
+        OGRGeometry *poOgrDstGeometry =
             OGRGeometryFactory::transformWithOptions(poOgrGeometry,
                                                         NULL,
                                                         papszTransformOptions);
 
         /***** replace the original geom *****/
-        
+
         if (poOgrDstGeometry) {
             delete poOgrGeometry;
             poOgrGeometry = poOgrDstGeometry;
         }
-        
+
         CSLDestroy(papszTransformOptions);
     }
 
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmlgeometry.h b/ogr/ogrsf_frmts/libkml/ogrlibkmlgeometry.h
index 3463bce..3c36c7d 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmlgeometry.h
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmlgeometry.h
@@ -26,7 +26,10 @@
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
 
-#include <kml/dom.h>
+#ifndef OGR_LIBKML_GEOMETRY_H
+#define OGR_LIBKML_GEOMETRY_H
+
+#include "libkml_headers.h"
 
 using kmldom::ElementPtr;
 using kmldom::KmlFactory;
@@ -35,8 +38,8 @@ using kmldom::LatLonBoxPtr;
 using kmldom::GxLatLonQuadPtr;
 
 /*******************************************************************************
-	funtion to write out a ogr geometry to kml
-	
+	function to write out a ogr geometry to km
+
 args:
 						poOgrGeom		the ogr geometry
 						extra		used in recursion, just pass -1
@@ -58,7 +61,7 @@ ElementPtr geom2kml (
 
 Args:
             poKmlGeometry   pointer to the kml geometry to translate
-            poOgrSRS        pointer to the spatial ref to set on the geometry 
+            poOgrSRS        pointer to the spatial ref to set on the geometry
 
 Returns:
             pointer to the new ogr geometry object
@@ -76,3 +79,5 @@ OGRGeometry *kml2geom_latlonbox (
 OGRGeometry *kml2geom_latlonquad (
     GxLatLonQuadPtr poKmlLatLonQuad,
     OGRSpatialReference *poOgrSRS);
+
+#endif /* OGR_LIBKML_GEOMETRY_H */
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmllayer.cpp b/ogr/ogrsf_frmts/libkml/ogrlibkmllayer.cpp
index b98b8c1..6fa0bad 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmllayer.cpp
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmllayer.cpp
@@ -27,13 +27,13 @@
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
 
+#include "libkml_headers.h"
+
 #include "ogr_libkml.h"
 //#include "cpl_conv.h"
 //#include "cpl_string.h"
 #include "cpl_error.h"
 
-#include <kml/dom.h>
-
 using kmldom::KmlFactory;
 using kmldom::PlacemarkPtr;
 using kmldom::Placemark;
@@ -71,7 +71,7 @@ using kmldom::DeletePtr;
 CPLString OGRLIBKMLGetSanitizedNCName(const char* pszName)
 {
     CPLString osName(pszName);
-    /* (Approximate) validation rules for a valic NCName */
+    /* (Approximate) validation rules for a valid NCName */
     for(size_t i = 0; i < osName.size(); i++)
     {
         char ch = osName[i];
@@ -107,10 +107,10 @@ CPLString OGRLIBKMLGetSanitizedNCName(const char* pszName)
                 poKmlContainer  pointer to the kml container of the layer
                 pszFileName     the filename of the layer
                 bNew            true if its a new layer
-                bUpdate         true if the layer is writeable
- 
+                bUpdate         true if the layer is writable
+
  Returns:       nothing
-                
+
 ******************************************************************************/
 
 OGRLIBKMLLayer::OGRLIBKMLLayer ( const char *pszLayerName,
@@ -122,7 +122,7 @@ OGRLIBKMLLayer::OGRLIBKMLLayer ( const char *pszLayerName,
                                  UpdatePtr poKmlUpdate,
                                  const char *pszFileName,
                                  int bNew,
-                                 int bUpdate )
+                                 int bUpdateIn )
 {
 
     m_poStyleTable = NULL;
@@ -130,7 +130,7 @@ OGRLIBKMLLayer::OGRLIBKMLLayer ( const char *pszLayerName,
     nFeatures = 0;
     nFID = 1;
 
-    this->bUpdate = bUpdate;
+    this->bUpdate = bUpdateIn;
     bUpdated = FALSE;
     m_pszName = CPLStrdup ( pszLayerName );
     m_pszFileName = CPLStrdup ( pszFileName );
@@ -149,11 +149,11 @@ OGRLIBKMLLayer::OGRLIBKMLLayer ( const char *pszLayerName,
     /***** store the root element pointer *****/
 
     m_poKmlLayerRoot = poKmlRoot;
-    
+
     /***** store the layers container *****/
 
     m_poKmlLayer = poKmlContainer;
-    
+
     /* update container */
     m_poKmlUpdate = poKmlUpdate;
 
@@ -173,9 +173,11 @@ OGRLIBKMLLayer::OGRLIBKMLLayer ( const char *pszLayerName,
     m_dfRegionMaxY = -200;
 
 
-    m_bReadGroundOverlay = CSLTestBoolean(CPLGetConfigOption("LIBKML_READ_GROUND_OVERLAY", "YES"));
-    m_bUseSimpleField = CSLTestBoolean(CPLGetConfigOption("LIBKML_USE_SIMPLEFIELD", "YES"));
-    
+    m_bReadGroundOverlay = CPLTestBool(
+        CPLGetConfigOption("LIBKML_READ_GROUND_OVERLAY", "YES"));
+    m_bUseSimpleField = CPLTestBool(
+        CPLGetConfigOption("LIBKML_USE_SIMPLEFIELD", "YES"));
+
     m_bUpdateIsFolder = FALSE;
 
     /***** was the layer created from a DS::Open *****/
@@ -184,20 +186,20 @@ OGRLIBKMLLayer::OGRLIBKMLLayer ( const char *pszLayerName,
 
         /***** get the number of features on the layer *****/
 
-        nFeatures = m_poKmlLayer->get_feature_array_size (  );
+        nFeatures = static_cast<int>(m_poKmlLayer->get_feature_array_size (  ));
 
         /***** get the field config *****/
-        
+
         struct fieldconfig oFC;
         get_fieldconfig( &oFC );
 
         /***** name field *****/
-        
+
         OGRFieldDefn oOgrFieldName ( oFC.namefield,OFTString );
         m_poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldName );
 
-        /***** descripton field *****/
-        
+        /***** description field *****/
+
         OGRFieldDefn oOgrFieldDesc ( oFC.descfield, OFTString );
         m_poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldDesc );
 
@@ -345,7 +347,7 @@ OGRLIBKMLLayer::OGRLIBKMLLayer ( const char *pszLayerName,
                     /* Use the <Data> of the first placemark to build the feature definition */
                     /* If others have different fields, too bad... */
                     int bLaunderFieldNames =
-                        CSLTestBoolean(CPLGetConfigOption("LIBKML_LAUNDER_FIELD_NAMES", "YES"));
+                        CPLTestBool(CPLGetConfigOption("LIBKML_LAUNDER_FIELD_NAMES", "YES"));
                     size_t nDataArraySize = poKmlExtendedData->get_data_array_size();
                     for(size_t i=0; i < nDataArraySize; i++)
                     {
@@ -390,9 +392,9 @@ OGRLIBKMLLayer::OGRLIBKMLLayer ( const char *pszLayerName,
  OGRLIBKMLLayer Destructor
 
  Args:          none
- 
+
  Returns:       nothing
-                
+
 ******************************************************************************/
 
 OGRLIBKMLLayer::~OGRLIBKMLLayer (  )
@@ -412,7 +414,7 @@ OGRLIBKMLLayer::~OGRLIBKMLLayer (  )
  Method to get the next feature on the layer
 
  Args:          none
- 
+
  Returns:       The next feature, or NULL if there is no more
 
  this function copyed from the sqlite driver
@@ -421,7 +423,7 @@ OGRLIBKMLLayer::~OGRLIBKMLLayer (  )
 OGRFeature *OGRLIBKMLLayer::GetNextFeature()
 
 {
-    for( ; TRUE; )
+    while( true )
     {
         OGRFeature      *poFeature;
 
@@ -443,9 +445,9 @@ OGRFeature *OGRLIBKMLLayer::GetNextFeature()
  Method to get the next feature on the layer
 
  Args:          none
- 
+
  Returns:       The next feature, or NULL if there is no more
-                
+
 ******************************************************************************/
 
 OGRFeature *OGRLIBKMLLayer::GetNextRawFeature (
@@ -453,7 +455,7 @@ OGRFeature *OGRLIBKMLLayer::GetNextRawFeature (
 {
     FeaturePtr poKmlFeature;
     OGRFeature *poOgrFeature = NULL;
-    
+
     if( m_poKmlLayer == NULL )
         return NULL;
 
@@ -464,7 +466,7 @@ OGRFeature *OGRLIBKMLLayer::GetNextRawFeature (
             break;
 
         /***** get the next kml feature in the container *****/
-        
+
         poKmlFeature = m_poKmlLayer->get_feature_array_at ( iFeature++ );
 
         /***** what type of kml feature in the container? *****/
@@ -475,7 +477,7 @@ OGRFeature *OGRLIBKMLLayer::GetNextRawFeature (
                 poOgrFeature = kml2feat ( AsPlacemark ( poKmlFeature ),
                                           m_poOgrDS, this,
                                           m_poOgrFeatureDefn, m_poOgrSRS );
-                break;    
+                break;
 
             case kmldom::Type_GroundOverlay:
                 if (m_bReadGroundOverlay) {
@@ -486,7 +488,7 @@ OGRFeature *OGRLIBKMLLayer::GetNextRawFeature (
                                                 m_poOgrSRS );
                 }
                 break;
-                
+
             default:
                 break;
 
@@ -495,10 +497,10 @@ OGRFeature *OGRLIBKMLLayer::GetNextRawFeature (
     } while ( !poOgrFeature );
 
     /***** set the FID on the ogr feature *****/
-    
+
     if (poOgrFeature)
         poOgrFeature->SetFID(nFID ++);
-    
+
     return poOgrFeature;
 }
 
@@ -506,10 +508,10 @@ OGRFeature *OGRLIBKMLLayer::GetNextRawFeature (
  method to add a feature to a layer
 
  Args:          poOgrFeat   pointer to the feature to add
- 
+
  Returns:       OGRERR_NONE, or OGRERR_UNSUPPORTED_OPERATION of the layer is
-                not writeable
-                
+                not writable
+
 ******************************************************************************/
 
 OGRErr OGRLIBKMLLayer::ICreateFeature (
@@ -557,7 +559,7 @@ OGRErr OGRLIBKMLLayer::ICreateFeature (
     if( m_poKmlLayer != NULL )
     {
         nFeatures++;
-        
+
         const char* pszId = CPLSPrintf("%s.%d",
                         OGRLIBKMLGetSanitizedNCName(GetName()).c_str(), nFeatures);
         poOgrFeat->SetFID(nFeatures);
@@ -597,9 +599,9 @@ OGRErr OGRLIBKMLLayer::ICreateFeature (
  method to update a feature to a layer. Only work on a NetworkLinkControl/Update
 
  Args:          poOgrFeat   pointer to the feature to update
- 
+
  Returns:       OGRERR_NONE, or OGRERR_UNSUPPORTED_OPERATION of the layer is
-                not writeable
+                not writable
 
 ******************************************************************************/
 
@@ -618,7 +620,7 @@ OGRErr OGRLIBKMLLayer::ISetFeature ( OGRFeature * poOgrFeat )
     ChangePtr poChange = poKmlFactory->CreateChange();
     poChange->add_object(poKmlFeature);
     m_poKmlUpdate->add_updateoperation(poChange);
-    
+
     const char* pszId = CPLSPrintf("%s." CPL_FRMT_GIB,
                     OGRLIBKMLGetSanitizedNCName(GetName()).c_str(), poOgrFeat->GetFID());
     poKmlFeature->set_targetid(pszId);
@@ -635,13 +637,13 @@ OGRErr OGRLIBKMLLayer::ISetFeature ( OGRFeature * poOgrFeat )
  method to delete a feature to a layer. Only work on a NetworkLinkControl/Update
 
  Args:          nFID   id of the feature to delete
- 
+
  Returns:       OGRERR_NONE, or OGRERR_UNSUPPORTED_OPERATION of the layer is
-                not writeable
+                not writable
 
 ******************************************************************************/
 
-OGRErr OGRLIBKMLLayer::DeleteFeature( GIntBig nFID )
+OGRErr OGRLIBKMLLayer::DeleteFeature( GIntBig nFIDIn )
 {
     if( !bUpdate || m_poKmlUpdate == NULL )
         return OGRERR_UNSUPPORTED_OPERATION;
@@ -651,9 +653,9 @@ OGRErr OGRLIBKMLLayer::DeleteFeature( GIntBig nFID )
     m_poKmlUpdate->add_updateoperation(poDelete);
     PlacemarkPtr poKmlPlacemark = poKmlFactory->CreatePlacemark();
     poDelete->add_feature(poKmlPlacemark);
-    
+
     const char* pszId = CPLSPrintf("%s." CPL_FRMT_GIB,
-                    OGRLIBKMLGetSanitizedNCName(GetName()).c_str(), nFID);
+                    OGRLIBKMLGetSanitizedNCName(GetName()).c_str(), nFIDIn);
     poKmlPlacemark->set_targetid(pszId);
 
     /***** mark the layer as updated *****/
@@ -668,12 +670,12 @@ OGRErr OGRLIBKMLLayer::DeleteFeature( GIntBig nFID )
  method to get the number of features on the layer
 
  Args:          bForce      no effect as of now
- 
+
  Returns:       the number of features on the layer
 
  Note:          the result can include links, folders and other items that are
                 not supported by OGR
-                
+
 ******************************************************************************/
 
 GIntBig OGRLIBKMLLayer::GetFeatureCount (
@@ -681,13 +683,13 @@ GIntBig OGRLIBKMLLayer::GetFeatureCount (
 {
 
 
-    int i = 0; 
+    int i = 0;
     if (m_poFilterGeom != NULL || m_poAttrQuery != NULL ) {
-        i = OGRLayer::GetFeatureCount( bForce );
+        i = static_cast<int>(OGRLayer::GetFeatureCount( bForce ));
     }
 
     else if( m_poKmlLayer != NULL ) {
-        size_t iKmlFeature; 
+        size_t iKmlFeature;
         size_t nKmlFeatures = m_poKmlLayer->get_feature_array_size (  );
         FeaturePtr poKmlFeature;
 
@@ -712,7 +714,7 @@ GIntBig OGRLIBKMLLayer::GetFeatureCount (
                 default:
                     break;
 
-            } 
+            }
         }
     }
 
@@ -723,10 +725,10 @@ GIntBig OGRLIBKMLLayer::GetFeatureCount (
  GetExtent()
 
  Args:          psExtent    pointer to the Envelope to store the result in
-                bForce      no effect as of now 
- 
+                bForce      no effect as of now
+
  Returns:       nothing
-                
+
 ******************************************************************************/
 
 OGRErr OGRLIBKMLLayer::GetExtent (
@@ -759,7 +761,7 @@ OGRErr OGRLIBKMLLayer::GetExtent (
                 bApproxOK   no effect as of now
 
  Returns:       OGRERR_NONE on success or OGRERR_UNSUPPORTED_OPERATION if the
-                layer is not writeable
+                layer is not writable
 
 ******************************************************************************/
 
@@ -813,7 +815,7 @@ OGRErr OGRLIBKMLLayer::CreateField (
  Args:      none
 
  Returns    nothing
-                
+
 ******************************************************************************/
 
 OGRErr OGRLIBKMLLayer::SyncToDisk (
@@ -825,12 +827,12 @@ OGRErr OGRLIBKMLLayer::SyncToDisk (
 
 /******************************************************************************
  method to get a layers style table
- 
+
  Args:          none
- 
+
  Returns:       pointer to the layers style table, or NULL if it does
                 not have one
-                
+
 ******************************************************************************/
 
 OGRStyleTable *OGRLIBKMLLayer::GetStyleTable (
@@ -842,9 +844,9 @@ OGRStyleTable *OGRLIBKMLLayer::GetStyleTable (
 
 /******************************************************************************
  method to write a style table to a layer
- 
+
  Args:          poStyleTable    pointer to the style table to add
- 
+
  Returns:       nothing
 
  note: this method assumes ownership of the style table
@@ -869,7 +871,7 @@ void OGRLIBKMLLayer::SetStyleTableDirectly (
         /***** delete all the styles *****/
 
         DocumentPtr poKmlDocument = AsDocument ( m_poKmlLayer );
-        size_t nKmlStyles = poKmlDocument->get_schema_array_size (  );
+        int nKmlStyles = static_cast<int>(poKmlDocument->get_schema_array_size (  ));
         int iKmlStyle;
 
         for ( iKmlStyle = nKmlStyles - 1; iKmlStyle >= 0; iKmlStyle-- ) {
@@ -893,12 +895,12 @@ void OGRLIBKMLLayer::SetStyleTableDirectly (
 
 /******************************************************************************
  method to write a style table to a layer
- 
+
  Args:          poStyleTable    pointer to the style table to add
- 
+
  Returns:       nothing
 
- note:  this method copys the style table, and the user will still be
+ note:  This method copies the style table, and the user will still be
         responsible for its destruction
 ******************************************************************************/
 
@@ -920,7 +922,7 @@ void OGRLIBKMLLayer::SetStyleTable (
  Test if capability is available.
 
  Args:          pszCap  layer capability name to test
- 
+
  Returns:       True if the layer supports the capability, otherwise false
 
 ******************************************************************************/
@@ -1161,7 +1163,7 @@ static int LIBKMLGetUnits(const char* pszUnits)
 static void LIBKMLSetVec2(kmldom::Vec2Ptr vec2, const char* pszX, const char* pszY,
                     const char* pszXUnits, const char* pszYUnits)
 {
-    double dfX = CPLAtof(pszX); 
+    double dfX = CPLAtof(pszX);
     double dfY = CPLAtof(pszY);
     vec2->set_x(dfX);
     vec2->set_y(dfY);
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmlstyle.cpp b/ogr/ogrsf_frmts/libkml/ogrlibkmlstyle.cpp
index b3658c0..22bf975 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmlstyle.cpp
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmlstyle.cpp
@@ -27,14 +27,12 @@
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
 
+#include "libkml_headers.h"
+
 #include <ogr_featurestyle.h>
 
 #include <set>
 
-#include <kml/dom.h>
-#include <kml/engine.h>
-#include <kml/base/color32.h>
-
 using kmldom::KmlFactory;;
 using kmldom::ElementPtr;
 using kmldom::ObjectPtr;
@@ -84,7 +82,7 @@ StylePtr addstylestring2kml (
     PolyStylePtr poKmlPolyStyle = NULL;
     IconStylePtr poKmlIconStyle = NULL;
     LabelStylePtr poKmlLabelStyle = NULL;
-    
+
     /***** just bail now if stylestring is empty *****/
 
     if ( !pszStyleString || !*pszStyleString ) {
@@ -107,7 +105,7 @@ StylePtr addstylestring2kml (
         if ( !poOgrST ) {
             continue;
         }
-        
+
         switch ( poOgrST->GetType (  ) ) {
         case OGRSTCPen:
             {
@@ -128,7 +126,10 @@ StylePtr addstylestring2kml (
 
                 if ( !nullcheck
                      && poStylePen->GetRGBFromString ( pszcolor, nR, nG, nB, nA ) ) {
-                    poKmlLineStyle->set_color ( Color32 ( nA, nB, nG, nR ) );
+                    poKmlLineStyle->set_color ( Color32 ( static_cast<GByte>(nA),
+                                                          static_cast<GByte>(nB),
+                                                          static_cast<GByte>(nG),
+                                                          static_cast<GByte>(nR) ) );
                 }
                 poStylePen->SetUnit(OGRSTUPixel);
                 double dfWidth = poStylePen->Width ( nullcheck );
@@ -137,7 +138,7 @@ StylePtr addstylestring2kml (
                     dfWidth = 1.0;
 
                 poKmlLineStyle->set_width ( dfWidth );
-                
+
                 break;
             }
         case OGRSTCBrush:
@@ -158,9 +159,12 @@ StylePtr addstylestring2kml (
                 if ( !nullcheck
                      && poStyleBrush->GetRGBFromString ( pszcolor, nR, nG, nB, nA ) ) {
                     poKmlPolyStyle = poKmlFactory->CreatePolyStyle (  );
-                    poKmlPolyStyle->set_color ( Color32 ( nA, nB, nG, nR ) );
+                    poKmlPolyStyle->set_color ( Color32 ( static_cast<GByte>(nA),
+                                                          static_cast<GByte>(nB),
+                                                          static_cast<GByte>(nG),
+                                                          static_cast<GByte>(nR) ) );
                 }
-                
+
 
                 break;
             }
@@ -236,7 +240,10 @@ StylePtr addstylestring2kml (
                 const char *pszcolor = poStyleSymbol->Color ( nullcheck );
 
                 if ( !nullcheck && poOgrST->GetRGBFromString ( pszcolor, nR, nG, nB, nA ) ) {
-                    poKmlIconStyle->set_color ( Color32 ( nA, nB, nG, nR ) );
+                    poKmlIconStyle->set_color ( Color32 ( static_cast<GByte>(nA),
+                                                          static_cast<GByte>(nB),
+                                                          static_cast<GByte>(nG),
+                                                          static_cast<GByte>(nR) ) );
                 }
 
                 /***** hotspot *****/
@@ -255,14 +262,14 @@ StylePtr addstylestring2kml (
 
                     poKmlIconStyle->set_hotspot ( poKmlHotSpot );
                 }
-                
+
                 break;
             }
         case OGRSTCLabel:
             {
                 GBool nullcheck;
                 GBool nullcheck2;
-                
+
                 OGRStyleLabel *poStyleLabel = ( OGRStyleLabel * ) poOgrST;
 
                 /***** color *****/
@@ -278,7 +285,10 @@ StylePtr addstylestring2kml (
                      && poStyleLabel->GetRGBFromString ( pszcolor, nR, nG, nB, nA ) ) {
                     if( poKmlLabelStyle == NULL )
                         poKmlLabelStyle = poKmlFactory->CreateLabelStyle (  );
-                    poKmlLabelStyle->set_color ( Color32 ( nA, nB, nG, nR ) );
+                    poKmlLabelStyle->set_color ( Color32 ( static_cast<GByte>(nA),
+                                                           static_cast<GByte>(nB),
+                                                           static_cast<GByte>(nG),
+                                                           static_cast<GByte>(nR) ) );
                 }
 
                 /***** scale *****/
@@ -291,7 +301,7 @@ StylePtr addstylestring2kml (
                         poKmlLabelStyle = poKmlFactory->CreateLabelStyle (  );
                     poKmlLabelStyle->set_scale ( dfScale );
                 }
-                
+
                 /***** heading *****/
 
                 double heading = poStyleLabel->Angle ( nullcheck );
@@ -302,7 +312,7 @@ StylePtr addstylestring2kml (
                         IconStyleIconPtr poKmlIcon = poKmlFactory->CreateIconStyleIcon (  );
                         poKmlIconStyle->set_icon ( poKmlIcon );
                     }
-                    
+
                     poKmlIconStyle->set_heading ( heading );
                 }
 
@@ -317,7 +327,7 @@ StylePtr addstylestring2kml (
                         IconStyleIconPtr poKmlIcon = poKmlFactory->CreateIconStyleIcon (  );
                         poKmlIconStyle->set_icon ( poKmlIcon );
                     }
-                    
+
                     HotSpotPtr poKmlHotSpot = poKmlFactory->CreateHotSpot (  );
 
                     poKmlHotSpot->set_x ( dfDx );
@@ -336,7 +346,7 @@ StylePtr addstylestring2kml (
                         poKmlFeature->set_name( pszText );
                     }
                 }
-                    
+
                 break;
             }
         case OGRSTCNone:
@@ -366,7 +376,7 @@ StylePtr addstylestring2kml (
     }
 
     delete poOgrSM;
-    
+
     return poKmlStyle;
 }
 
@@ -418,13 +428,13 @@ void kml2stylestring (
     int i;
 
     poOgrNewSM = new OGRStyleMgr( NULL );
-    
+
     /***** linestyle / pen *****/
 
     if ( poKmlStyle->has_linestyle (  ) ) {
 
         poOgrNewSM->InitStyleString ( NULL );
-        
+
         LineStylePtr poKmlLineStyle = poKmlStyle->get_linestyle (  );
 
         poOgrTmpST = NULL;
@@ -433,7 +443,7 @@ void kml2stylestring (
 
             if ( !poOgrST )
                 continue;
-        
+
             if ( poOgrST->GetType ( ) == OGRSTCPen ) {
                 poOgrTmpST = poOgrST;
             }
@@ -442,15 +452,15 @@ void kml2stylestring (
                 delete poOgrST;
             }
         }
-        
+
         OGRStylePen *poOgrStylePen = kml2pen ( poKmlLineStyle,
                                                ( OGRStylePen *) poOgrTmpST);
-        
+
         poOgrNewSM->AddPart ( poOgrStylePen );
 
         delete poOgrStylePen;
         poOgrSM->InitStyleString ( poOgrNewSM->GetStyleString(NULL) );
-        
+
     }
 
     /***** polystyle / brush *****/
@@ -467,7 +477,7 @@ void kml2stylestring (
 
             if ( !poOgrST )
                 continue;
-        
+
             if ( poOgrST->GetType ( ) == OGRSTCBrush ) {
                 poOgrTmpST = poOgrST;
             }
@@ -490,7 +500,7 @@ void kml2stylestring (
     /***** iconstyle / symbol *****/
 
     if ( poKmlStyle->has_iconstyle (  ) ) {
-        
+
         poOgrNewSM->InitStyleString ( NULL );
 
         IconStylePtr poKmlIconStyle = poKmlStyle->get_iconstyle (  );
@@ -501,7 +511,7 @@ void kml2stylestring (
 
             if ( !poOgrST )
                 continue;
-        
+
             if ( poOgrST->GetType ( ) == OGRSTCSymbol ) {
                 poOgrTmpST = poOgrST;
             }
@@ -524,7 +534,7 @@ void kml2stylestring (
     /***** labelstyle / label *****/
 
     if ( poKmlStyle->has_labelstyle (  ) ) {
-        
+
         poOgrNewSM->InitStyleString ( NULL );
 
         LabelStylePtr poKmlLabelStyle = poKmlStyle->get_labelstyle (  );
@@ -535,7 +545,7 @@ void kml2stylestring (
 
             if ( !poOgrST )
                 continue;
-        
+
             if ( poOgrST->GetType ( ) == OGRSTCLabel ) {
                 poOgrTmpST = poOgrST;
             }
@@ -574,7 +584,7 @@ OGRStylePen *kml2pen (
         poOgrStylePen = new OGRStylePen (  );
 
     /***** <LineStyle> should always have a width in pixels *****/
-    
+
     poOgrStylePen->SetUnit(OGRSTUPixel);
 
     /***** width *****/
@@ -717,7 +727,7 @@ OGRStyleLabel *kml2label (
 
         poOgrStyleLabel->SetStretch(dfScale);
     }
-    
+
     return poOgrStyleLabel;
 }
 
@@ -725,7 +735,7 @@ OGRStyleLabel *kml2label (
  function to add a kml style to a style table
 ******************************************************************************/
 
-void kml2styletable (
+static void kml2styletable (
     OGRStyleTable * poOgrStyleTable,
     StylePtr poKmlStyle )
 {
@@ -758,7 +768,7 @@ void kml2styletable (
 
     else {
         CPLError ( CE_Failure, CPLE_AppDefined,
-                   "ERROR Parseing kml Style: No id" );
+                   "ERROR parsing kml Style: No id" );
     }
 
     return;
@@ -769,31 +779,31 @@ void kml2styletable (
 ******************************************************************************/
 
 StyleSelectorPtr StyleFromStyleSelector(
-    const StyleSelectorPtr& poKmlStyleSelector, 
-    OGRStyleTable * poStyleTable) 
+    const StyleSelectorPtr& poKmlStyleSelector,
+    OGRStyleTable * poStyleTable)
 {
-    
+
     /***** is it a style? *****/
 
     if ( poKmlStyleSelector->IsA( kmldom::Type_Style) )
         return poKmlStyleSelector;
 
     /***** is it a style map? *****/
-    
+
     else if ( poKmlStyleSelector->IsA( kmldom::Type_StyleMap) )
         return StyleFromStyleMap(kmldom::AsStyleMap(poKmlStyleSelector), poStyleTable);
 
     /***** not a style or a style map *****/
-    
+
     return NULL;
 }
 
 
 /******************************************************************************
  function to get the container from the kmlroot
- 
+
  Args:          poKmlRoot   the root element
- 
+
  Returns:       root if its a container, if its a kml the container it
                 contains, or NULL
 
@@ -834,23 +844,22 @@ static ContainerPtr MyGetContainerFromRoot (
 
 
 
-StyleSelectorPtr StyleFromStyleURL(
+static StyleSelectorPtr StyleFromStyleURL(
     const StyleMapPtr& stylemap,
     const string styleurl,
-    OGRStyleTable * poStyleTable) 
+    OGRStyleTable * poStyleTable)
 {
     // TODO:: Parse the styleURL
 
     char *pszUrl = CPLStrdup ( styleurl.c_str (  ) );
     char *pszStyleMapId = CPLStrdup ( stylemap->get_id().c_str (  ) );
-    
 
-    /***** is it an interenal style ref that starts with a # *****/
+    /***** Is it an internal style ref that starts with a #? *****/
 
     if ( *pszUrl == '#' && poStyleTable ) {
 
-        /***** searh the style table for the style we *****/
-        /***** want and copy it back into the table   *****/
+        /***** Search the style table for the style we *****/
+        /***** want and copy it back into the table.   *****/
 
         const char *pszTest = NULL;
         pszTest = poStyleTable->Find ( pszUrl + 1 );
@@ -861,19 +870,19 @@ StyleSelectorPtr StyleFromStyleURL(
 
     /***** We have a real URL and need to go out and fetch it *****/
     /***** FIXME this could be a relative path in a kmz *****/
-    
+
     else if ( strchr(pszUrl, '#') ) {
 
         const char *pszFetch = CPLGetConfigOption ( "LIBKML_EXTERNAL_STYLE", "no" );
-        if ( CSLTestBoolean(pszFetch) ) {
+        if ( CPLTestBool(pszFetch) ) {
 
             /***** Lets go out and fetch the style from the external URL *****/
 
             char *pszUrlTmp = CPLStrdup(pszUrl);
-            char *pszPound;
+            char *pszPound = strchr(pszUrlTmp, '#');
             char *pszRemoteStyleName = NULL;
             // Chop off the stuff (style id) after the URL
-            if ((pszPound = strchr(pszUrlTmp, '#'))) {
+            if (pszPound != NULL) {
                 *pszPound = '\0';
                 pszRemoteStyleName = pszPound + 1;
             }
@@ -883,8 +892,8 @@ StyleSelectorPtr StyleFromStyleURL(
             VSILFILE *fp = NULL;
             if ( (fp = VSIFOpenL( CPLFormFilename( "/vsicurl/",
                                                    pszUrlTmp,
-                                                  NULL), "r" ))
-                 ||  (fp = VSIFOpenL( pszUrlTmp, "r" )) )
+                                                  NULL), "r" )) != NULL
+                 ||  (fp = VSIFOpenL( pszUrlTmp, "r" )) != NULL )
             {
                 char szbuf[1025];
                 std::string oStyle = "";
@@ -892,27 +901,27 @@ StyleSelectorPtr StyleFromStyleURL(
                 /***** loop, read and copy to a string *****/
 
                 size_t nRead;
-                do {                        
+                do {
                     nRead = VSIFReadL(szbuf, 1, sizeof(szbuf) - 1, fp);
                     if (nRead == 0)
                         break;
-                    
+
                     /***** copy buf to the string *****/
-                    
+
                     szbuf[nRead] = '\0';
-                    oStyle.append( szbuf );                        
+                    oStyle.append( szbuf );
                 } while (!VSIFEofL(fp));
-                
+
                 VSIFCloseL(fp);
 
                 /***** parse the kml into the dom *****/
-                
+
                 std::string oKmlErrors;
                 ElementPtr poKmlRoot = kmldom::Parse ( oStyle, &oKmlErrors );
 
                 if ( !poKmlRoot ) {
                     CPLError ( CE_Failure, CPLE_OpenFailed,
-                               "ERROR Parseing style kml %s :%s",
+                               "ERROR parsing style kml %s :%s",
                                pszUrlTmp, oKmlErrors.c_str (  ) );
                     CPLFree(pszUrlTmp);
                     CPLFree ( pszUrl );
@@ -922,7 +931,7 @@ StyleSelectorPtr StyleFromStyleURL(
                 }
 
                 /***** get the root container *****/
-                
+
                 ContainerPtr poKmlContainer;
                 kmldom::KmlFactory* poKmlFactory = kmldom::KmlFactory::GetFactory();
                 if ( !( poKmlContainer = MyGetContainerFromRoot ( poKmlFactory, poKmlRoot ) ) ) {
@@ -934,10 +943,10 @@ StyleSelectorPtr StyleFromStyleURL(
                 }
 
                 /**** parse the styles into the table *****/
-                
+
                 ParseStyles ( AsDocument ( poKmlContainer ), &poStyleTable );
-                    
-                /***** look for the style we leed to map to in the table *****/
+
+                /***** look for the style we need to map to in the table *****/
 
                 const char *pszTest = NULL;
                 pszTest = poStyleTable->Find(pszRemoteStyleName);
@@ -951,8 +960,8 @@ StyleSelectorPtr StyleFromStyleURL(
         }
     }
 
-    /***** FIXME add suport here for relative links inside kml *****/
-    
+    /***** FIXME Add support here for relative links inside KML. *****/
+
     CPLFree ( pszUrl );
     CPLFree ( pszStyleMapId );
 
@@ -961,7 +970,7 @@ StyleSelectorPtr StyleFromStyleURL(
 
 StyleSelectorPtr StyleFromStyleMap(
     const StyleMapPtr& poKmlStyleMap,
-    OGRStyleTable * poStyleTable) 
+    OGRStyleTable * poStyleTable)
 {
 
     /***** check the config option to see if the    *****/
@@ -978,9 +987,9 @@ StyleSelectorPtr StyleFromStyleMap(
         PairPtr myPair = poKmlStyleMap->get_pair_array_at(i);
 
         /***** is it the right one of the pair? *****/
-        
+
         if ( myPair->get_key() == nStyleMapKey ) {
-            
+
             if (myPair->has_styleselector())
                 return StyleFromStyleSelector(myPair->get_styleselector(), poStyleTable);
 
@@ -1036,8 +1045,8 @@ void ParseStyles (
         kml2styletable ( *poStyleTable, AsStyle ( poKmlElement ) );
     }
 
-    /***** Now we have to loop back around and get the style maps. We    *****/ 
-    /***** have to do this a second time since the stylemap might matter *****/ 
+    /***** Now we have to loop back around and get the style maps. We    *****/
+    /***** have to do this a second time since the stylemap might matter *****/
     /***** and we are just looping reference styles that are farther     *****/
     /***** down in the file. Order through the XML as it is parsed.      *****/
 
@@ -1057,7 +1066,7 @@ void ParseStyles (
             *poStyleTable = new OGRStyleTable (  );
 
         /***** copy the style the style map points to since *****/
-        
+
         char *pszStyleMapId = CPLStrdup ( poKmlStyle->get_id().c_str (  ) );
         poKmlStyle = StyleFromStyleMap(kmldom::AsStyleMap(poKmlStyle), *poStyleTable);
         if (poKmlStyle == NULL) {
@@ -1132,8 +1141,8 @@ void styletable2kml (
     /***** parse the style table *****/
 
     poOgrStyleTable->ResetStyleStringReading (  );
-    
-    while ( ( pszStyleString = poOgrStyleTable->GetNextStyle (  ) ) ) {
+
+    while ( ( pszStyleString = poOgrStyleTable->GetNextStyle (  ) ) != NULL ) {
         const char *pszStyleName = poOgrStyleTable->GetLastStyleName (  );
 
         if( aoSetNormalStyles.find(pszStyleName) != aoSetNormalStyles.end() &&
@@ -1164,7 +1173,10 @@ void styletable2kml (
             BalloonStylePtr poKmlBalloonStyle = poKmlFactory->CreateBalloonStyle();
             if( pszBalloonStyleBgColor != NULL &&
                 oStyleTool.GetRGBFromString ( pszBalloonStyleBgColor, nR, nG, nB, nA ) )
-                poKmlBalloonStyle->set_bgcolor ( Color32 ( nA, nB, nG, nR ) );
+                poKmlBalloonStyle->set_bgcolor ( Color32 ( static_cast<GByte>(nA),
+                                                           static_cast<GByte>(nB),
+                                                           static_cast<GByte>(nG),
+                                                           static_cast<GByte>(nR) ) );
             if( pszBalloonStyleText != NULL )
                 poKmlBalloonStyle->set_text(pszBalloonStyleText);
             poKmlStyle->set_balloonstyle ( poKmlBalloonStyle );
diff --git a/ogr/ogrsf_frmts/makefile.vc b/ogr/ogrsf_frmts/makefile.vc
index 9f9025e..140c6f4 100644
--- a/ogr/ogrsf_frmts/makefile.vc
+++ b/ogr/ogrsf_frmts/makefile.vc
@@ -8,25 +8,27 @@ DIRLIST		=	generic geojson shape ntf sdts tiger s57 dgn mitab gml \
 			avc rec mem vrt csv gmt bna kml gpx \
 			geoconcept xplane georss gtm dxf pgdump gpsbabel \
 			sua openair pds htf aeronavfaa edigeo svg idrisi arcgen \
-			segukooa segy sxf openfilegdb wasp selafin jml \
+			segukooa segy sxf openfilegdb wasp selafin jml vdv \
 			$(ARCOBJECTS_DIR) \
 			$(OGDIDIR) $(FMEDIR) $(OCIDIR) $(PG_DIR) $(DWGDIR) \
 			$(ODBCDIR) $(SQLITE_DIR) $(MYSQL_DIR) $(ILI_DIR) \
 			$(SDE_DIR) $(IDB_DIR) $(NAS_DIR) $(DODSDIR) \
 			$(LIBKMLDIR) $(WFSDIR) $(SOSIDIR) $(GFTDIR) \
 			$(COUCHDBDIR) $(CLOUDANTDIR) $(FGDB_DIR) $(XLSDIR) $(ODSDIR) $(XLSXDIR) \
-			$(INGRESDIR) $(ELASTICDIR) $(OSMDIR) $(VFKDIR) $(CARTODBDIR) \
-			$(GMEDIR) $(PLSCENESDIR) $(CSWDIR)
+			$(INGRESDIR) $(ELASTICDIR) $(OSMDIR) $(VFKDIR) $(CARTODBDIR) $(AMIGOCLOUD_DIR) \
+			$(PLSCENESDIR) $(CSWDIR) $(MONGODBDIR)
 
 PLUGINDIRLIST	=	$(PLUGIN_ARCOBJECTS_DIR) \
 			$(PLUGIN_DWG_DIR) \
 			$(PLUGIN_PG_DIR) \
 			$(PLUGIN_SOSI_DIR) \
 			$(PLUGIN_FGDB_DIR) \
+			$(PLUGIN_AMIGOCLOUD_DIR) \
 			$(PLUGIN_OCIDIR) \
 			$(PLUGIN_SDE_DIR) \
 			$(PLUGIN_INGRESDIR) \
-			$(PLUGIN_LIBKMLDIR)
+			$(PLUGIN_LIBKMLDIR) \
+            $(PLUGIN_MONGODBDIR)
 
 !IFDEF OGDIDIR
 OGDIDIR	=	ogdi
@@ -34,8 +36,8 @@ OGDIOBJ =	ogdi\*.obj
 !ENDIF
 
 !IFDEF ODBC_SUPPORTED
-ODBCDIR	=	odbc pgeo mssqlspatial geomedia walk
-ODBCOBJ =	odbc\*.obj pgeo\*.obj mssqlspatial\*.obj geomedia\*.obj walk\*.obj
+ODBCDIR	=	odbc pgeo mssqlspatial geomedia db2 walk
+ODBCOBJ =	odbc\*.obj pgeo\*.obj mssqlspatial\*.obj geomedia\*.obj db2\*.obj walk\*.obj
 !ENDIF
 
 !IFDEF SQLITE_LIB
@@ -102,7 +104,6 @@ PLUGIN_FGDB_DIR = filegdb
 !ENDIF
 !ENDIF
 
-
 !IFDEF HAS_ARCOBJECTS
 !IF "$(ARCOBJECTS_PLUGIN)" != "YES"
 ARCOBJECTS_DIR = arcobjects
@@ -208,8 +209,12 @@ CARTODB_OBJ = cartodb\*.obj
 !ENDIF
 
 !IFDEF CURL_LIB
-GMEDIR = gme
-GME_OBJ = gme\*.obj
+!IF "$(AMIGOCLOUD_PLUGIN)" != "YES"
+AMIGOCLOUD_DIR = amigocloud
+AMIGOCLOUD_OBJ = amigocloud\*.obj
+!ELSE
+PLUGIN_AMIGOCLOUD_DIR = amigocloud
+!ENDIF
 !ENDIF
 
 !IFDEF CURL_LIB
@@ -217,6 +222,15 @@ PLSCENESDIR = plscenes
 PLSCENES_OBJ = plscenes\*.obj
 !ENDIF
 
+!IFDEF MONGODB_INC
+!IF "$(MONGODB_PLUGIN)" != "YES"
+MONGODBDIR = mongodb
+MONGODBOBJ = mongodb\*.obj
+!ELSE
+PLUGIN_MONGODBDIR = mongodb
+!ENDIF
+!ENDIF
+
 !ELSE
 
 DIRLIST		=	generic mitab
@@ -242,13 +256,14 @@ default:
 				 aeronavfaa\*.obj edigeo\*.obj svg\*.obj idrisi\*.obj \
 				 arcgen\*.obj segukooa\*.obj segy\*.obj sxf\*.obj \
 				 openfilegdb\*.obj wasp\*.obj selafin\*.obj jml\*.obj \
+				 vdv\*.obj \
 				$(OGDIOBJ) $(ODBCOBJ) $(SQLITE_OBJ) \
 				$(FMEOBJ) $(OCIOBJ) $(PG_OBJ) $(MYSQL_OBJ) \
 				$(ILI_OBJ) $(DWG_OBJ) $(SDE_OBJ) $(FGDB_OBJ) $(ARCDRIVER_OBJ) $(IDB_OBJ) \
 				$(DODS_OBJ) $(NAS_OBJ) $(LIBKMLOBJ) $(WFS_OBJ) \
 				$(SOSI_OBJ) $(GFT_OBJ) $(COUCHDB_OBJ) $(CLOUDANT_OBJ) $(XLS_OBJ) $(ODS_OBJ) $(XLSX_OBJ)  \
-				$(INGRESOBJ) $(ELASTIC_OBJ) $(OSM_OBJ) $(VFK_OBJ) $(CARTODB_OBJ) $(GME_OBJ) $(PLSCENES_OBJ) \
-				$(CSW_OBJ)
+				$(INGRESOBJ) $(ELASTIC_OBJ) $(OSM_OBJ) $(VFK_OBJ) $(CARTODB_OBJ) $(AMIGOCLOUD_OBJ) $(PLSCENES_OBJ) \
+				$(CSW_OBJ) $(MONGODBOBJ)
 	lib /out:ogrsf_frmts_sup.lib \
 				 ..\..\frmts\iso8211\*.obj \
 				 ..\..\frmts\sdts\sdtsattrreader.obj \
diff --git a/ogr/ogrsf_frmts/mdb/drv_mdb.html b/ogr/ogrsf_frmts/mdb/drv_mdb.html
index 0a0317d..4cd6a9d 100644
--- a/ogr/ogrsf_frmts/mdb/drv_mdb.html
+++ b/ogr/ogrsf_frmts/mdb/drv_mdb.html
@@ -14,7 +14,7 @@
   <p>OGR optionally supports reading access .mdb
   files by using the Java <a href="http://jackcess.sourceforge.net/">Jackcess</a> library.</p>
 
-  <p>This driver is primarly meant as being used on Unix platforms to overcome the
+  <p>This driver is primarily meant as being used on Unix platforms to overcome the
      issues often met with the MDBTools library that acts as the ODBC driver for MDB databases.</p>
 
   <p>The driver can detect ESRI Personal Geodatabases and Geomedia MDB databases, and will
diff --git a/ogr/ogrsf_frmts/mdb/ogr_mdb.h b/ogr/ogrsf_frmts/mdb/ogr_mdb.h
index 3877171..be0c16c 100644
--- a/ogr/ogrsf_frmts/mdb/ogr_mdb.h
+++ b/ogr/ogrsf_frmts/mdb/ogr_mdb.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_mdb.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogr_mdb.h 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for MDB driver.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_MDB_H_INCLUDED
-#define _OGR_MDB_H_INCLUDED
+#ifndef OGR_MDB_H_INCLUDED
+#define OGR_MDB_H_INCLUDED
 
 #include <jni.h>
 #include <vector>
@@ -54,7 +54,7 @@ class OGRMDBJavaEnv
     JNIEnv *env;
     int bCalledFromJava;
 
-    int ExceptionOccured();
+    int ExceptionOccurred();
 
     jclass byteArray_class;
 
@@ -105,7 +105,7 @@ class OGRMDBJavaEnv
 
     jclass short_class;
     jmethodID short_shortValue;
-    
+
     jclass integer_class;
     jmethodID integer_intValue;
 
@@ -188,7 +188,7 @@ public:
 
 };
 
-typedef enum 
+typedef enum
 {
     MDB_Boolean = 0x01,
     MDB_Byte = 0x02,
@@ -219,7 +219,7 @@ typedef enum
 /************************************************************************/
 
 class OGRMDBDataSource;
-    
+
 class OGRMDBLayer : public OGRLayer
 {
   protected:
@@ -274,7 +274,7 @@ class OGRMDBLayer : public OGRLayer
     virtual OGRFeature *GetNextFeature();
 
     virtual OGRFeature *GetFeature( GIntBig nFeatureId );
-    
+
     OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
 
     virtual int         TestCapability( const char * );
@@ -282,6 +282,8 @@ class OGRMDBLayer : public OGRLayer
     virtual const char *GetFIDColumn();
 
     virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce );
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 };
 
 /************************************************************************/
@@ -312,7 +314,7 @@ class OGRMDBDataSource : public OGRDataSource
                         ~OGRMDBDataSource();
 
     int                 Open( const char * );
-    int                 OpenTable( const char *pszTableName, 
+    int                 OpenTable( const char *pszTableName,
                                    const char *pszGeomCol,
                                    int bUpdate );
 
@@ -339,4 +341,4 @@ class OGRMDBDriver : public OGRSFDriver
     int          TestCapability( const char * );
 };
 
-#endif /* ndef _OGR_MDB_H_INCLUDED */
+#endif /* ndef OGR_MDB_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/mdb/ogrmdbdatasource.cpp b/ogr/ogrsf_frmts/mdb/ogrmdbdatasource.cpp
index 76a589f..02f3898 100644
--- a/ogr/ogrsf_frmts/mdb/ogrmdbdatasource.cpp
+++ b/ogr/ogrsf_frmts/mdb/ogrmdbdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmdbdatasource.cpp 27794 2014-10-04 10:13:46Z rouault $
+ * $Id: ogrmdbdatasource.cpp 32983 2016-01-14 18:32:10Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMDBDataSource class.
@@ -33,7 +33,7 @@
 #include <vector>
 #include "ogrgeomediageometry.h"
 
-CPL_CVSID("$Id: ogrmdbdatasource.cpp 27794 2014-10-04 10:13:46Z rouault $");
+CPL_CVSID("$Id: ogrmdbdatasource.cpp 32983 2016-01-14 18:32:10Z goatbar $");
 
 /************************************************************************/
 /*                         OGRMDBDataSource()                          */
@@ -304,7 +304,7 @@ int OGRMDBDataSource::Open( const char * pszNewName )
 
     /* Is it a ESRI Personal Geodatabase ? */
     OGRMDBTable* poGDB_GeomColumns = poDB->GetTable("GDB_GeomColumns");
-    if (poGDB_GeomColumns && !CSLTestBoolean(CPLGetConfigOption("MDB_RAW", "OFF")))
+    if (poGDB_GeomColumns && !CPLTestBool(CPLGetConfigOption("MDB_RAW", "OFF")))
     {
         int nRet = OpenGDB(poGDB_GeomColumns);
         delete poGDB_GeomColumns;
@@ -314,7 +314,7 @@ int OGRMDBDataSource::Open( const char * pszNewName )
 
     /* Is it a Geomedia warehouse ? */
     OGRMDBTable* poGAliasTable = poDB->GetTable("GAliasTable");
-    if (poGAliasTable && !CSLTestBoolean(CPLGetConfigOption("MDB_RAW", "OFF")))
+    if (poGAliasTable && !CPLTestBool(CPLGetConfigOption("MDB_RAW", "OFF")))
     {
         int nRet = OpenGeomediaWarehouse(poGAliasTable);
         delete poGAliasTable;
@@ -371,12 +371,12 @@ OGRLayer *OGRMDBDataSource::GetLayer( int iLayer )
 /*                              GetLayer()                              */
 /************************************************************************/
 
-OGRLayer *OGRMDBDataSource::GetLayerByName( const char* pszName )
+OGRLayer *OGRMDBDataSource::GetLayerByName( const char* pszNameIn )
 
 {
-    if (pszName == NULL)
+    if (pszNameIn == NULL)
         return NULL;
-    OGRLayer* poLayer = OGRDataSource::GetLayerByName(pszName);
+    OGRLayer* poLayer = OGRDataSource::GetLayerByName(pszNameIn);
     if (poLayer)
         return poLayer;
 
@@ -384,11 +384,11 @@ OGRLayer *OGRMDBDataSource::GetLayerByName( const char* pszName )
     {
         poLayer = papoLayersInvisible[i];
 
-        if( strcmp( pszName, poLayer->GetName() ) == 0 )
+        if( strcmp( pszNameIn, poLayer->GetName() ) == 0 )
             return poLayer;
     }
 
-    OGRMDBTable* poTable = poDB->GetTable(pszName);
+    OGRMDBTable* poTable = poDB->GetTable(pszNameIn);
     if (poTable == NULL)
         return NULL;
 
@@ -421,7 +421,7 @@ OGRSpatialReference* OGRMDBDataSource::GetGeomediaSRS(const char* pszGCoordSyste
         return NULL;
 
     poGCoordSystemTable->ResetReading();
-    
+
     OGRFeature* poFeature;
     while((poFeature = poGCoordSystemTable->GetNextFeature()) != NULL)
     {
diff --git a/ogr/ogrsf_frmts/mdb/ogrmdbdriver.cpp b/ogr/ogrsf_frmts/mdb/ogrmdbdriver.cpp
index 866372b..43cb085 100644
--- a/ogr/ogrsf_frmts/mdb/ogrmdbdriver.cpp
+++ b/ogr/ogrsf_frmts/mdb/ogrmdbdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmdbdriver.cpp 27794 2014-10-04 10:13:46Z rouault $
+ * $Id: ogrmdbdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements Personal Geodatabase driver.
@@ -30,7 +30,7 @@
 #include "ogr_mdb.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrmdbdriver.cpp 27794 2014-10-04 10:13:46Z rouault $");
+CPL_CVSID("$Id: ogrmdbdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
 
 // g++ -fPIC -g -Wall ogr/ogrsf_frmts/mdb/*.cpp -shared -o ogr_MDB.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/mdb -L. -lgdal -I/usr/lib/jvm/java-6-openjdk/include -I/usr/lib/jvm/java-6-openjdk/include/linux  -L/usr/lib/jvm/java-6-openjdk/jre/lib/amd64/server -ljvm
 
@@ -68,13 +68,13 @@ OGRDataSource *OGRMDBDriver::Open( const char * pszFilename,
     if( bUpdate )
         return NULL;
 
-    if( EQUALN(pszFilename, "PGEO:", strlen("PGEO:")) )
+    if( STARTS_WITH_CI(pszFilename, "PGEO:") )
         return NULL;
 
-    if( EQUALN(pszFilename, "GEOMEDIA:", strlen("GEOMEDIA:")) )
+    if( STARTS_WITH_CI(pszFilename, "GEOMEDIA:") )
         return NULL;
 
-    if( EQUALN(pszFilename, "WALK:", strlen("WALK:")) )
+    if( STARTS_WITH_CI(pszFilename, "WALK:") )
         return NULL;
 
     if( !EQUAL(CPLGetExtension(pszFilename),"mdb") )
@@ -116,10 +116,9 @@ void RegisterOGRMDB()
 {
     OGRSFDriver* poDriver = new OGRMDBDriver;
     poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                "Access MDB (PGeo and Geomedia capable)" );
+                               "Access MDB (PGeo and Geomedia capable)" );
     poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "mdb" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                "drv_mdb.html" );
-    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver(poDriver);
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_mdb.html" );
+    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( poDriver );
 }
 
diff --git a/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp b/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp
index 5908944..684e905 100644
--- a/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp
+++ b/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmdbjackcess.cpp 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: ogrmdbjackcess.cpp 33102 2016-01-23 11:05:59Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMDBJavaEnv class.
@@ -29,7 +29,7 @@
 
 #include "ogr_mdb.h"
 
-CPL_CVSID("$Id: ogrmdbjackcess.cpp 27044 2014-03-16 23:41:27Z rouault $");
+CPL_CVSID("$Id: ogrmdbjackcess.cpp 33102 2016-01-23 11:05:59Z rouault $");
 
 static JavaVM *jvm_static = NULL;
 static JNIEnv *env_static = NULL;
@@ -182,12 +182,12 @@ int OGRMDBJavaEnv::Init()
             JavaVMOption options[1];
             args.version = JNI_VERSION_1_2;
             const char* pszClassPath = CPLGetConfigOption("CLASSPATH", NULL);
-            CPLString osClassPathOption;
+            char* pszClassPathOption = NULL;
             if (pszClassPath)
             {
                 args.nOptions = 1;
-                osClassPathOption.Printf("-Djava.class.path=%s", pszClassPath);
-                options[0].optionString = (char*) osClassPathOption.c_str();
+                pszClassPathOption = CPLStrdup(CPLSPrintf("-Djava.class.path=%s", pszClassPath));
+                options[0].optionString = pszClassPathOption;
                 args.options = options;
             }
             else
@@ -195,6 +195,9 @@ int OGRMDBJavaEnv::Init()
             args.ignoreUnrecognized = JNI_FALSE;
 
             int ret = JNI_CreateJavaVM(&jvm, (void **)&env, &args);
+
+            CPLFree(pszClassPathOption);
+
             if (ret != 0 || jvm == NULL || env == NULL)
             {
                 CPLError(CE_Failure, CPLE_AppDefined, "JNI_CreateJavaVM failed (%d)", ret);
@@ -210,6 +213,8 @@ int OGRMDBJavaEnv::Init()
         jvm = jvm_static;
         env = env_static;
     }
+    if( env == NULL )
+        return FALSE;
 
     CHECK(byteArray_class, env->FindClass("[B"));
     CHECK(file_class, env->FindClass("java/io/File"));
@@ -275,10 +280,10 @@ int OGRMDBJavaEnv::Init()
 
 
 /************************************************************************/
-/*                       ExceptionOccured()                             */
+/*                       ExceptionOccurred()                             */
 /************************************************************************/
 
-int OGRMDBJavaEnv::ExceptionOccured()
+int OGRMDBJavaEnv::ExceptionOccurred()
 {
     jthrowable exc = env->ExceptionOccurred();
     if (exc)
@@ -324,14 +329,14 @@ OGRMDBDatabase* OGRMDBDatabase::Open(OGRMDBJavaEnv* env, const char* pszName)
 {
     jstring jstr = env->env->NewStringUTF(pszName);
     jobject file = env->env->NewObject(env->file_class, env->file_constructor, jstr);
-    if (env->ExceptionOccured()) return NULL;
+    if (env->ExceptionOccurred()) return NULL;
     env->env->ReleaseStringUTFChars(jstr, NULL);
 
     jobject database = env->env->CallStaticObjectMethod(env->database_class, env->database_open, file, JNI_TRUE);
 
     env->env->DeleteLocalRef(file);
 
-    if (env->ExceptionOccured()) return NULL;
+    if (env->ExceptionOccurred()) return NULL;
     if (database == NULL)
         return NULL;
 
@@ -352,15 +357,15 @@ int OGRMDBDatabase::FetchTableNames()
         env->Init();
 
     jobject table_set = env->env->CallObjectMethod(database, env->database_getTableNames);
-    if (env->ExceptionOccured()) return FALSE;
+    if (env->ExceptionOccurred()) return FALSE;
     jobject iterator = env->env->CallObjectMethod(table_set, env->set_iterator);
-    if (env->ExceptionOccured()) return FALSE;
+    if (env->ExceptionOccurred()) return FALSE;
 
     while( env->env->CallBooleanMethod(iterator, env->iterator_hasNext) )
     {
-        if (env->ExceptionOccured()) return FALSE;
+        if (env->ExceptionOccurred()) return FALSE;
         jstring table_name_jstring = (jstring) env->env->CallObjectMethod(iterator, env->iterator_next);
-        if (env->ExceptionOccured()) return FALSE;
+        if (env->ExceptionOccurred()) return FALSE;
         jboolean is_copy;
         const char* table_name_str = env->env->GetStringUTFChars(table_name_jstring, &is_copy);
 
@@ -386,7 +391,7 @@ OGRMDBTable* OGRMDBDatabase::GetTable(const char* pszTableName)
 
     jstring table_name_jstring = env->env->NewStringUTF(pszTableName);
     jobject table = env->env->CallObjectMethod(database, env->database_getTable, table_name_jstring);
-    if (env->ExceptionOccured()) return NULL;
+    if (env->ExceptionOccurred()) return NULL;
     env->env->DeleteLocalRef(table_name_jstring);
 
     if (!table)
@@ -409,11 +414,11 @@ OGRMDBTable* OGRMDBDatabase::GetTable(const char* pszTableName)
 /*                           OGRMDBTable()                              */
 /************************************************************************/
 
-OGRMDBTable::OGRMDBTable(OGRMDBJavaEnv* env, OGRMDBDatabase* poDB, jobject table, const char* pszTableName )
+OGRMDBTable::OGRMDBTable(OGRMDBJavaEnv* envIn, OGRMDBDatabase* poDBIn, jobject tableIn, const char* pszTableName )
 {
-    this->env = env;
-    this->poDB = poDB;
-    this->table = table;
+    this->env = envIn;
+    this->poDB = poDBIn;
+    this->table = tableIn;
     osTableName = pszTableName;
     table_iterator_obj = NULL;
     row = NULL;
@@ -451,20 +456,20 @@ int OGRMDBTable::FetchColumns()
         env->Init();
 
     jobject column_lists = env->env->CallObjectMethod(table, env->table_getColumns);
-    if (env->ExceptionOccured()) return FALSE;
+    if (env->ExceptionOccurred()) return FALSE;
 
     jobject iterator_cols = env->env->CallObjectMethod(column_lists, env->list_iterator);
-    if (env->ExceptionOccured()) return FALSE;
+    if (env->ExceptionOccurred()) return FALSE;
 
     while( env->env->CallBooleanMethod(iterator_cols, env->iterator_hasNext) )
     {
-        if (env->ExceptionOccured()) return FALSE;
+        if (env->ExceptionOccurred()) return FALSE;
 
         jobject column = env->env->CallObjectMethod(iterator_cols, env->iterator_next);
-        if (env->ExceptionOccured()) return FALSE;
+        if (env->ExceptionOccurred()) return FALSE;
 
         jstring column_name_jstring = (jstring) env->env->CallObjectMethod(column, env->column_getName);
-        if (env->ExceptionOccured()) return FALSE;
+        if (env->ExceptionOccurred()) return FALSE;
         jboolean is_copy;
         const char* column_name_str = env->env->GetStringUTFChars(column_name_jstring, &is_copy);
         apoColumnNames.push_back(column_name_str);
@@ -474,17 +479,17 @@ int OGRMDBTable::FetchColumns()
         env->env->DeleteLocalRef(column_name_jstring);
 
         jobject column_type = env->env->CallObjectMethod(column, env->column_getType);
-        if (env->ExceptionOccured()) return FALSE;
+        if (env->ExceptionOccurred()) return FALSE;
         int type = env->env->CallByteMethod(column_type, env->datatype_getValue);
-        if (env->ExceptionOccured()) return FALSE;
+        if (env->ExceptionOccurred()) return FALSE;
         apoColumnTypes.push_back(type);
 
         int isvariablelength = env->env->CallBooleanMethod(column, env->column_isVariableLength);
-        if (env->ExceptionOccured()) return FALSE;
+        if (env->ExceptionOccurred()) return FALSE;
         if (!isvariablelength)
         {
             int length = env->env->CallShortMethod(column, env->column_getLength);
-            if (env->ExceptionOccured()) return FALSE;
+            if (env->ExceptionOccurred()) return FALSE;
             apoColumnLengths.push_back(length);
         }
         else
@@ -529,7 +534,7 @@ int OGRMDBTable::GetNextRow()
     if (table_iterator_obj == NULL)
     {
         table_iterator_obj = env->env->CallObjectMethod(table, env->table_iterator);
-        if (env->ExceptionOccured()) return FALSE;
+        if (env->ExceptionOccurred()) return FALSE;
         if (table_iterator_obj)
         {
             jobject global_table_iterator_obj = env->env->NewGlobalRef(table_iterator_obj);
@@ -542,7 +547,7 @@ int OGRMDBTable::GetNextRow()
 
     if (!env->env->CallBooleanMethod(table_iterator_obj, env->iterator_hasNext))
         return FALSE;
-    if (env->ExceptionOccured()) return FALSE;
+    if (env->ExceptionOccurred()) return FALSE;
 
     if (row)
     {
@@ -551,7 +556,7 @@ int OGRMDBTable::GetNextRow()
     }
 
     row = env->env->CallObjectMethod(table_iterator_obj, env->iterator_next);
-    if (env->ExceptionOccured()) return FALSE;
+    if (env->ExceptionOccurred()) return FALSE;
     if (row == NULL)
         return FALSE;
 
@@ -572,7 +577,7 @@ jobject OGRMDBTable::GetColumnVal(int iCol)
         return NULL;
 
     jobject val = env->env->CallObjectMethod(row, env->map_get, apoColumnNameObjects[iCol]);
-    if (env->ExceptionOccured()) return NULL;
+    if (env->ExceptionOccurred()) return NULL;
     return val;
 }
 
@@ -586,7 +591,7 @@ char* OGRMDBTable::GetColumnAsString(int iCol)
     if (!val) return NULL;
 
     jstring val_jstring = (jstring) env->env->CallObjectMethod(val, env->object_toString);
-    if (env->ExceptionOccured()) return NULL;
+    if (env->ExceptionOccurred()) return NULL;
     jboolean is_copy;
     const char* val_str = env->env->GetStringUTFChars(val_jstring, &is_copy);
     char* dup_str = (val_str) ? CPLStrdup(val_str) : NULL;
@@ -616,7 +621,7 @@ int OGRMDBTable::GetColumnAsInt(int iCol)
         int_val = env->env->CallShortMethod(val, env->short_shortValue);
     else if (apoColumnTypes[iCol] == MDB_Int)
         int_val = env->env->CallIntMethod(val, env->integer_intValue);
-    if (env->ExceptionOccured()) return 0;
+    if (env->ExceptionOccurred()) return 0;
 
     env->env->DeleteLocalRef(val);
 
@@ -637,7 +642,7 @@ double OGRMDBTable::GetColumnAsDouble(int iCol)
         double_val = env->env->CallDoubleMethod(val, env->double_doubleValue);
     else if (apoColumnTypes[iCol] == MDB_Float)
         double_val = env->env->CallFloatMethod(val, env->float_floatValue);
-    if (env->ExceptionOccured()) return 0;
+    if (env->ExceptionOccurred()) return 0;
 
     env->env->DeleteLocalRef(val);
 
@@ -660,10 +665,10 @@ GByte* OGRMDBTable::GetColumnAsBinary(int iCol, int* pnBytes)
 
     jbyteArray byteArray = (jbyteArray) val;
     *pnBytes = env->env->GetArrayLength(byteArray);
-    if (env->ExceptionOccured()) return NULL;
+    if (env->ExceptionOccurred()) return NULL;
     jboolean is_copy;
     jbyte* elts = env->env->GetByteArrayElements(byteArray, &is_copy);
-    if (env->ExceptionOccured()) return NULL;
+    if (env->ExceptionOccurred()) return NULL;
 
     GByte* pData = (GByte*)CPLMalloc(*pnBytes);
     memcpy(pData, elts, *pnBytes);
@@ -683,7 +688,7 @@ void OGRMDBTable::DumpTable()
 {
     ResetReading();
     int iRow = 0;
-    int nCols = apoColumnNames.size();
+    int nCols = static_cast<int>(apoColumnNames.size());
     while(GetNextRow())
     {
         printf("Row = %d\n", iRow ++);
@@ -726,7 +731,7 @@ void OGRMDBTable::DumpTable()
 
 int OGRMDBTable::GetColumnIndex(const char* pszColName, int bEmitErrorIfNotFound)
 {
-    int nCols = apoColumnNames.size();
+    int nCols = static_cast<int>(apoColumnNames.size());
     CPLString osColName(pszColName);
     for(int i=0;i<nCols;i++)
     {
@@ -747,6 +752,6 @@ int OGRMDBTable::GetRowCount()
     if (env->bCalledFromJava)
         env->Init();
     int nRowCount = env->env->CallIntMethod(table, env->table_getRowCount);
-    if (env->ExceptionOccured()) return 0;
+    if (env->ExceptionOccurred()) return 0;
     return nRowCount;
 }
diff --git a/ogr/ogrsf_frmts/mdb/ogrmdblayer.cpp b/ogr/ogrsf_frmts/mdb/ogrmdblayer.cpp
index 73d4541..21677b0 100644
--- a/ogr/ogrsf_frmts/mdb/ogrmdblayer.cpp
+++ b/ogr/ogrsf_frmts/mdb/ogrmdblayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmdblayer.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrmdblayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMDBLayer class
@@ -33,17 +33,17 @@
 #include "ogrpgeogeometry.h"
 #include "ogrgeomediageometry.h"
 
-CPL_CVSID("$Id: ogrmdblayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrmdblayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                            OGRMDBLayer()                            */
 /************************************************************************/
 
-OGRMDBLayer::OGRMDBLayer(OGRMDBDataSource* poDS, OGRMDBTable* poMDBTable)
+OGRMDBLayer::OGRMDBLayer(OGRMDBDataSource* poDSIn, OGRMDBTable* poMDBTableIn)
 
 {
-    this->poDS = poDS;
-    this->poMDBTable = poMDBTable;
+    this->poDS = poDSIn;
+    this->poMDBTable = poMDBTableIn;
 
     eGeometryType = MDB_GEOM_NONE;
 
@@ -73,7 +73,7 @@ OGRMDBLayer::~OGRMDBLayer()
     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     {
         CPLDebug( "MDB", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
+                  (int) m_nFeaturesRead,
                   poFeatureDefn->GetName() );
     }
 
@@ -133,13 +133,13 @@ CPLErr OGRMDBLayer::BuildFeatureDefn()
         }
 
         if( eGeometryType == MDB_GEOM_PGEO
-            && pszGeomColumn == NULL 
+            && pszGeomColumn == NULL
             && EQUAL(pszColName,"Shape") )
         {
             pszGeomColumn = CPLStrdup(pszColName);
             continue;
         }
-        
+
         switch( poMDBTable->GetColumnType(iCol) )
         {
           case MDB_Boolean:
@@ -215,7 +215,7 @@ GIntBig OGRMDBLayer::GetFeatureCount(int bForce)
 OGRFeature *OGRMDBLayer::GetNextFeature()
 
 {
-    for( ; TRUE; )
+    while( true )
     {
         OGRFeature      *poFeature;
 
@@ -252,7 +252,7 @@ OGRFeature *OGRMDBLayer::GetNextRawFeature()
     OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
 
     if( pszFIDColumn != NULL && poMDBTable->GetColumnIndex(pszFIDColumn) > -1 )
-        poFeature->SetFID( 
+        poFeature->SetFID(
             poMDBTable->GetColumnAsInt(poMDBTable->GetColumnIndex(pszFIDColumn)) );
     else
         poFeature->SetFID( iNextShapeId );
@@ -275,7 +275,7 @@ OGRFeature *OGRMDBLayer::GetNextRawFeature()
         {
             int nBytes = 0;
             GByte* pData = poMDBTable->GetColumnAsBinary( iSrcField, &nBytes);
-            poFeature->SetField( iField, 
+            poFeature->SetField( iField,
                                  nBytes,
                                  pData );
             CPLFree(pData);
@@ -446,7 +446,7 @@ void OGRMDBLayer::LookupSRID( int nSRID )
     char* pszSRTextPtr = pszSRText;
     if( poSRS->importFromWkt( &pszSRTextPtr ) != OGRERR_NONE )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "importFromWKT() failed on SRS '%s'.",
                   pszSRText);
         delete poSRS;
@@ -454,7 +454,7 @@ void OGRMDBLayer::LookupSRID( int nSRID )
     }
     else if( poSRS->morphFromESRI() != OGRERR_NONE )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "morphFromESRI() failed on SRS." );
         delete poSRS;
         poSRS = NULL;
@@ -570,9 +570,9 @@ CPLErr OGRMDBLayer::Initialize( CPL_UNUSED const char *pszTableName,
 /*                             Initialize()                             */
 /************************************************************************/
 
-CPLErr OGRMDBLayer::Initialize( CPL_UNUSED const char *pszTableName,
+CPLErr OGRMDBLayer::Initialize( const char * /*pszTableName */,
                                 const char *pszGeomCol,
-                                OGRSpatialReference* poSRS )
+                                OGRSpatialReference* poSRSIn )
 
 
 {
@@ -591,7 +591,7 @@ CPLErr OGRMDBLayer::Initialize( CPL_UNUSED const char *pszTableName,
 
     eGeometryType = MDB_GEOM_GEOMEDIA;
 
-    this->poSRS = poSRS;
+    this->poSRS = poSRSIn;
 
     CPLErr eErr;
     eErr = BuildFeatureDefn();
diff --git a/ogr/ogrsf_frmts/mem/drv_memory.html b/ogr/ogrsf_frmts/mem/drv_memory.html
index d31c0ee..25d961c 100644
--- a/ogr/ogrsf_frmts/mem/drv_memory.html
+++ b/ogr/ogrsf_frmts/mem/drv_memory.html
@@ -9,7 +9,7 @@
 
 This driver implements read and write access layers of features contained
 entirely in memory.  This is primarily useful as a high performance, and highly
-malleable working data store.  All update options, geometry types, and 
+malleable working data store.  All update options, geometry types, and
 field types are supported.<p>
 
 There is no way to open an existing Memory datastore.  It must be created
@@ -18,7 +18,7 @@ datastore is closed all contents are freed and destroyed. <p>
 
 The driver does not implement spatial or attribute indexing, so spatial and
 attribute queries are still evaluated against all features.  Fetching features
-by feature id should be very fast (just an array lookup and feature copy). 
+by feature id should be very fast (just an array lookup and feature copy).
 <p>
 
 <h2>Creation Issues</h2>
@@ -27,11 +27,12 @@ Any name may be used for a created datasource.  There are no datasource
 or layer creation options supported.  Layer names need to be unique, but
 are not otherwise constrained.<p>
 
-Feature ids passed to CreateFeature() are preserved <i>unless</i> they exceed 
-10000000 in which case they will be reset to avoid a requirement for an 
-excessively large and sparse feature array.<p>
+Before GDAL 2.1, feature ids passed to CreateFeature() are preserved <i>unless</i> they exceed
+10000000 in which case they will be reset to avoid a requirement for an
+excessively large and sparse feature array. Starting with GDAL 2.1, sparse
+IDs can be handled.<p>
 
-New fields can be added to layer that already has features. <p>
+New fields can be added or removed to a layer that already has features. <p>
 
 
 </body>
diff --git a/ogr/ogrsf_frmts/mem/ogr_mem.h b/ogr/ogrsf_frmts/mem/ogr_mem.h
index 0da4f56..e6cb092 100644
--- a/ogr/ogrsf_frmts/mem/ogr_mem.h
+++ b/ogr/ogrsf_frmts/mem/ogr_mem.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_mem.h 28382 2015-01-30 15:29:41Z rouault $
+ * $Id: ogr_mem.h 32896 2016-01-10 13:37:26Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions within the OGR Memory driver.
@@ -28,31 +28,46 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGRMEM_H_INCLUDED
-#define _OGRMEM_H_INCLUDED
+#ifndef OGRMEM_H_INCLUDED
+#define OGRMEM_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 
+#include <map>
+
 /************************************************************************/
 /*                             OGRMemLayer                              */
 /************************************************************************/
 class OGRMemDataSource;
 
+class IOGRMemLayerFeatureIterator;
+
 class OGRMemLayer : public OGRLayer
 {
-    OGRFeatureDefn     *poFeatureDefn;
-    
-    GIntBig             nFeatureCount;
-    GIntBig             nMaxFeatureCount;
-    OGRFeature        **papoFeatures;
+    typedef std::map<GIntBig, OGRFeature*>           FeatureMap;
+    typedef std::map<GIntBig, OGRFeature*>::iterator FeatureIterator;
+
+    OGRFeatureDefn     *m_poFeatureDefn;
+
+    GIntBig             m_nFeatureCount;
+
+    GIntBig             m_iNextReadFID;
+    GIntBig             m_nMaxFeatureCount; // max size of papoFeatures
+    OGRFeature        **m_papoFeatures;
+    bool                m_bHasHoles;
+
+    FeatureMap          m_oMapFeatures;
+    FeatureIterator     m_oMapFeaturesIter;
 
-    GIntBig             iNextReadFID;
-    GIntBig             iNextCreateFID;
+    GIntBig             m_iNextCreateFID;
 
-    int                 bUpdatable;
-    int                 bAdvertizeUTF8;
+    bool                m_bUpdatable;
+    bool                m_bAdvertizeUTF8;
 
-    int                 bHasHoles;
+    bool                m_bUpdated;
+
+    // only use it in the lifetime of a function where the list of features doesn't change
+    IOGRMemLayerFeatureIterator* GetIterator();
 
   public:
                         OGRMemLayer( const char * pszName,
@@ -68,8 +83,8 @@ class OGRMemLayer : public OGRLayer
     OGRErr              ISetFeature( OGRFeature *poFeature );
     OGRErr              ICreateFeature( OGRFeature *poFeature );
     virtual OGRErr      DeleteFeature( GIntBig nFID );
-    
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+
+    OGRFeatureDefn *    GetLayerDefn() { return m_poFeatureDefn; }
 
     GIntBig             GetFeatureCount( int );
 
@@ -83,10 +98,13 @@ class OGRMemLayer : public OGRLayer
 
     int                 TestCapability( const char * );
 
-    void                SetUpdatable(int bUpdatableIn) { bUpdatable = bUpdatableIn; }
-    void                SetAdvertizeUTF8(int bAdvertizeUTF8In) { bAdvertizeUTF8 = bAdvertizeUTF8In; }
+    void                SetUpdatable( bool bUpdatableIn ) { m_bUpdatable = bUpdatableIn; }
+    void                SetAdvertizeUTF8( bool bAdvertizeUTF8In ) { m_bAdvertizeUTF8 = bAdvertizeUTF8In; }
+
+    bool                HasBeenUpdated() const { return m_bUpdated; }
+    void                SetUpdated(bool bUpdated) { m_bUpdated = bUpdated; }
 
-    GIntBig             GetNextReadFID() { return iNextReadFID; }
+    GIntBig             GetNextReadFID() { return m_iNextReadFID; }
 };
 
 /************************************************************************/
@@ -95,9 +113,9 @@ class OGRMemLayer : public OGRLayer
 
 class OGRMemDataSource : public OGRDataSource
 {
-    OGRMemLayer     **papoLayers;
+    OGRMemLayer       **papoLayers;
     int                 nLayers;
-    
+
     char                *pszName;
 
   public:
@@ -108,7 +126,7 @@ class OGRMemDataSource : public OGRDataSource
     int                 GetLayerCount() { return nLayers; }
     OGRLayer            *GetLayer( int );
 
-    virtual OGRLayer    *ICreateLayer( const char *, 
+    virtual OGRLayer    *ICreateLayer( const char *,
                                       OGRSpatialReference * = NULL,
                                       OGRwkbGeometryType = wkbUnknown,
                                       char ** = NULL );
@@ -125,15 +143,15 @@ class OGRMemDriver : public OGRSFDriver
 {
   public:
                 ~OGRMemDriver();
-                
+
     const char *GetName();
     OGRDataSource *Open( const char *, int );
 
     virtual OGRDataSource *CreateDataSource( const char *pszName,
                                              char ** = NULL );
-    
+
     int                 TestCapability( const char * );
 };
 
 
-#endif /* ndef _OGRMEM_H_INCLUDED */
+#endif /* ndef OGRMEM_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/mem/ogrmemdatasource.cpp b/ogr/ogrsf_frmts/mem/ogrmemdatasource.cpp
index 30627d3..bb1303b 100644
--- a/ogr/ogrsf_frmts/mem/ogrmemdatasource.cpp
+++ b/ogr/ogrsf_frmts/mem/ogrmemdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmemdatasource.cpp 27959 2014-11-14 18:29:21Z rouault $
+ * $Id: ogrmemdatasource.cpp 33400 2016-02-10 07:55:48Z ajolma $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMemDataSource class.
@@ -31,19 +31,18 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrmemdatasource.cpp 27959 2014-11-14 18:29:21Z rouault $");
+CPL_CVSID("$Id: ogrmemdatasource.cpp 33400 2016-02-10 07:55:48Z ajolma $");
 
 /************************************************************************/
 /*                          OGRMemDataSource()                          */
 /************************************************************************/
 
 OGRMemDataSource::OGRMemDataSource( const char *pszFilename,
-                                    CPL_UNUSED char **papszOptions)
-{
-    pszName = CPLStrdup(pszFilename);
-    papoLayers = NULL;
-    nLayers = 0;
-}
+                                    char ** /* papszOptions */) :
+    papoLayers(NULL),
+    nLayers(0),
+    pszName(CPLStrdup(pszFilename))
+{}
 
 /************************************************************************/
 /*                         ~OGRMemDataSource()                          */
@@ -56,7 +55,7 @@ OGRMemDataSource::~OGRMemDataSource()
 
     for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
-    
+
     CPLFree( papoLayers );
 }
 
@@ -68,21 +67,22 @@ OGRLayer *
 OGRMemDataSource::ICreateLayer( const char * pszLayerName,
                                 OGRSpatialReference *poSRS,
                                 OGRwkbGeometryType eType,
-                                CPL_UNUSED char ** papszOptions )
+                                char ** papszOptions )
 {
 /* -------------------------------------------------------------------- */
 /*      Create the layer object.                                        */
 /* -------------------------------------------------------------------- */
-    OGRMemLayer *poLayer;
+    OGRMemLayer *poLayer = new OGRMemLayer( pszLayerName, poSRS, eType );
 
-    poLayer = new OGRMemLayer( pszLayerName, poSRS, eType );
+    if( CSLFetchBoolean(papszOptions, "ADVERTIZE_UTF8", FALSE) )
+        poLayer->SetAdvertizeUTF8(TRUE);
 
 /* -------------------------------------------------------------------- */
 /*      Add layer to data source layer list.                            */
 /* -------------------------------------------------------------------- */
     papoLayers = (OGRMemLayer **)
         CPLRealloc( papoLayers,  sizeof(OGRMemLayer *) * (nLayers+1) );
-    
+
     papoLayers[nLayers++] = poLayer;
 
     return poLayer;
@@ -101,13 +101,13 @@ OGRErr OGRMemDataSource::DeleteLayer( int iLayer )
 
         for( int i = iLayer+1; i < nLayers; i++ )
             papoLayers[i-1] = papoLayers[i];
-        
+
         nLayers--;
-        
+
         return OGRERR_NONE;
     }
-    else
-        return OGRERR_FAILURE;
+
+    return OGRERR_FAILURE;
 }
 
 /************************************************************************/
@@ -125,8 +125,10 @@ int OGRMemDataSource::TestCapability( const char * pszCap )
         return TRUE;
     else if( EQUAL(pszCap,ODsCCurveGeometries) )
         return TRUE;
-    else
-        return FALSE;
+    else if( EQUAL(pszCap,ODsCMeasuredGeometries) )
+        return TRUE;
+
+    return FALSE;
 }
 
 /************************************************************************/
@@ -138,6 +140,6 @@ OGRLayer *OGRMemDataSource::GetLayer( int iLayer )
 {
     if( iLayer < 0 || iLayer >= nLayers )
         return NULL;
-    else
-        return papoLayers[iLayer];
+
+    return papoLayers[iLayer];
 }
diff --git a/ogr/ogrsf_frmts/mem/ogrmemdriver.cpp b/ogr/ogrsf_frmts/mem/ogrmemdriver.cpp
index 1e5e30b..4d3c1d8 100644
--- a/ogr/ogrsf_frmts/mem/ogrmemdriver.cpp
+++ b/ogr/ogrsf_frmts/mem/ogrmemdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmemdriver.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrmemdriver.cpp 32896 2016-01-10 13:37:26Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMemDriver class.
@@ -31,16 +31,13 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrmemdriver.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrmemdriver.cpp 32896 2016-01-10 13:37:26Z goatbar $");
 
 /************************************************************************/
 /*                          ~OGRMemDriver()                           */
 /************************************************************************/
 
-OGRMemDriver::~OGRMemDriver()
-
-{
-}
+OGRMemDriver::~OGRMemDriver() {}
 
 /************************************************************************/
 /*                              GetName()                               */
@@ -56,7 +53,7 @@ const char *OGRMemDriver::GetName()
 /*                                Open()                                */
 /************************************************************************/
 
-OGRDataSource *OGRMemDriver::Open( CPL_UNUSED const char * pszFilename, int )
+OGRDataSource *OGRMemDriver::Open( const char * /* pszFilename */, int )
 {
     return NULL;
 }
@@ -81,8 +78,8 @@ int OGRMemDriver::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,ODrCCreateDataSource) )
         return TRUE;
-    else
-        return FALSE;
+
+    return FALSE;
 }
 
 /************************************************************************/
@@ -92,9 +89,22 @@ int OGRMemDriver::TestCapability( const char * pszCap )
 void RegisterOGRMEM()
 
 {
+    if( GDALGetDriverByName( "Memory" ) != NULL )
+      return;
+
     OGRSFDriver* poDriver = new OGRMemDriver;
-    
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES, "Integer Integer64 Real String Date DateTime Time IntegerList Integer64List RealList StringList Binary" );
+
+    poDriver->SetMetadataItem(
+        GDAL_DMD_CREATIONFIELDDATATYPES,
+        "Integer Integer64 Real String Date DateTime Time IntegerList "
+        "Integer64List RealList StringList Binary" );
+
+    poDriver->SetMetadataItem(
+        GDAL_DS_LAYER_CREATIONOPTIONLIST,
+        "<LayerCreationOptionList>"
+        "  <Option name='ADVERTIZE_UTF8' type='boolean' description='Whether "
+        "the layer will contain UTF-8 strings' default='NO'/>"
+        "</LayerCreationOptionList>" );
 
     OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/mem/ogrmemlayer.cpp b/ogr/ogrsf_frmts/mem/ogrmemlayer.cpp
index 4ab1676..9953ff9 100644
--- a/ogr/ogrsf_frmts/mem/ogrmemlayer.cpp
+++ b/ogr/ogrsf_frmts/mem/ogrmemlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmemlayer.cpp 28382 2015-01-30 15:29:41Z rouault $
+ * $Id: ogrmemlayer.cpp 33400 2016-02-10 07:55:48Z ajolma $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMemLayer class.
@@ -28,41 +28,54 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_mem.h"
 #include "cpl_conv.h"
+#include "ogr_mem.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrmemlayer.cpp 28382 2015-01-30 15:29:41Z rouault $");
+CPL_CVSID("$Id: ogrmemlayer.cpp 33400 2016-02-10 07:55:48Z ajolma $");
 
 /************************************************************************/
-/*                            OGRMemLayer()                             */
+/*                      IOGRMemLayerFeatureIterator                     */
 /************************************************************************/
 
-OGRMemLayer::OGRMemLayer( const char * pszName, OGRSpatialReference *poSRSIn, 
-                          OGRwkbGeometryType eReqType )
+class IOGRMemLayerFeatureIterator
+{
+    public:
+        virtual ~IOGRMemLayerFeatureIterator() {}
+
+        virtual OGRFeature* Next() = 0;
+};
 
+/************************************************************************/
+/*                            OGRMemLayer()                             */
+/************************************************************************/
+
+OGRMemLayer::OGRMemLayer( const char * pszName, OGRSpatialReference *poSRSIn,
+                          OGRwkbGeometryType eReqType ) :
+    m_poFeatureDefn(new OGRFeatureDefn( pszName )),
+    m_nFeatureCount(0),
+    m_iNextReadFID(0),
+    m_nMaxFeatureCount(0),
+    m_papoFeatures(NULL),
+    m_bHasHoles(false),
+    m_iNextCreateFID(0),
+    m_bUpdatable(true),
+    m_bAdvertizeUTF8(false),
+    m_bUpdated(false)
 {
-    iNextReadFID = 0;
-    iNextCreateFID = 0;
+    m_poFeatureDefn->Reference();
 
-    nFeatureCount = 0;
-    nMaxFeatureCount = 0;
-    papoFeatures = NULL;
+    SetDescription( m_poFeatureDefn->GetName() );
+    m_poFeatureDefn->SetGeomType( eReqType );
 
-    poFeatureDefn = new OGRFeatureDefn( pszName );
-    SetDescription( poFeatureDefn->GetName() );
-    poFeatureDefn->SetGeomType( eReqType );
     if( eReqType != wkbNone && poSRSIn != NULL )
     {
         OGRSpatialReference* poSRS = poSRSIn->Clone();
-        poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
+        m_poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
         poSRS->Release();
     }
-    poFeatureDefn->Reference();
 
-    bUpdatable = TRUE;
-    bAdvertizeUTF8 = FALSE;
-    bHasHoles = FALSE;
+    m_oMapFeaturesIter = m_oMapFeatures.begin();
 }
 
 /************************************************************************/
@@ -72,22 +85,34 @@ OGRMemLayer::OGRMemLayer( const char * pszName, OGRSpatialReference *poSRSIn,
 OGRMemLayer::~OGRMemLayer()
 
 {
-    if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
+    if( m_nFeaturesRead > 0 && m_poFeatureDefn != NULL )
     {
         CPLDebug( "Mem", CPL_FRMT_GIB " features read on layer '%s'.",
-                  m_nFeaturesRead, 
-                  poFeatureDefn->GetName() );
+                  m_nFeaturesRead,
+                  m_poFeatureDefn->GetName() );
     }
 
-    for( GIntBig i = 0; i < nMaxFeatureCount; i++ )
+    if( m_papoFeatures != NULL )
     {
-        if( papoFeatures[i] != NULL )
-            delete papoFeatures[i];
+        for( GIntBig i = 0; i < m_nMaxFeatureCount; i++ )
+        {
+            if( m_papoFeatures[i] != NULL )
+                delete m_papoFeatures[i];
+        }
+        CPLFree( m_papoFeatures );
+    }
+    else
+    {
+        for( m_oMapFeaturesIter = m_oMapFeatures.begin();
+             m_oMapFeaturesIter != m_oMapFeatures.end();
+             ++m_oMapFeaturesIter )
+        {
+            delete m_oMapFeaturesIter->second;
+        }
     }
-    CPLFree( papoFeatures );
 
-    if( poFeatureDefn )
-        poFeatureDefn->Release();
+    if( m_poFeatureDefn )
+        m_poFeatureDefn->Release();
 }
 
 /************************************************************************/
@@ -97,7 +122,8 @@ OGRMemLayer::~OGRMemLayer()
 void OGRMemLayer::ResetReading()
 
 {
-    iNextReadFID = 0;
+    m_iNextReadFID = 0;
+    m_oMapFeaturesIter = m_oMapFeatures.begin();
 }
 
 /************************************************************************/
@@ -107,12 +133,24 @@ void OGRMemLayer::ResetReading()
 OGRFeature *OGRMemLayer::GetNextFeature()
 
 {
-    while( iNextReadFID < nMaxFeatureCount )
+    while( true )
     {
-        OGRFeature *poFeature = papoFeatures[iNextReadFID++];
-
-        if( poFeature == NULL )
-            continue;
+        OGRFeature *poFeature = NULL;
+        if( m_papoFeatures )
+        {
+            if( m_iNextReadFID >= m_nMaxFeatureCount )
+                return NULL;
+            poFeature = m_papoFeatures[m_iNextReadFID++];
+            if( poFeature == NULL )
+                continue;
+        }
+        else if( m_oMapFeaturesIter != m_oMapFeatures.end() )
+        {
+            poFeature = m_oMapFeaturesIter->second;
+            ++ m_oMapFeaturesIter;
+        }
+        else
+            break;
 
         if( (m_poFilterGeom == NULL
              || FilterGeometry( poFeature->GetGeomFieldRef(m_iGeomFieldFilter) ) )
@@ -134,13 +172,14 @@ OGRFeature *OGRMemLayer::GetNextFeature()
 OGRErr OGRMemLayer::SetNextByIndex( GIntBig nIndex )
 
 {
-    if( m_poFilterGeom != NULL || m_poAttrQuery != NULL || bHasHoles )
+    if( m_poFilterGeom != NULL || m_poAttrQuery != NULL ||
+        m_papoFeatures == NULL || m_bHasHoles )
         return OGRLayer::SetNextByIndex( nIndex );
-        
-    if (nIndex < 0 || nIndex >= nMaxFeatureCount)
+
+    if (nIndex < 0 || nIndex >= m_nMaxFeatureCount)
         return OGRERR_FAILURE;
 
-    iNextReadFID = nIndex;
+    m_iNextReadFID = nIndex;
 
     return OGRERR_NONE;
 }
@@ -152,12 +191,26 @@ OGRErr OGRMemLayer::SetNextByIndex( GIntBig nIndex )
 OGRFeature *OGRMemLayer::GetFeature( GIntBig nFeatureId )
 
 {
-    if( nFeatureId < 0 || nFeatureId >= nMaxFeatureCount )
-        return NULL;
-    else if( papoFeatures[nFeatureId] == NULL )
+    if( nFeatureId < 0 )
         return NULL;
+
+    OGRFeature* poFeature = NULL;
+    if( m_papoFeatures != NULL )
+    {
+        if( nFeatureId >= m_nMaxFeatureCount )
+            return NULL;
+        poFeature = m_papoFeatures[nFeatureId];
+    }
     else
-        return papoFeatures[nFeatureId]->Clone();
+    {
+        FeatureIterator oIter = m_oMapFeatures.find(nFeatureId);
+        if( oIter != m_oMapFeatures.end() )
+            poFeature = oIter->second;
+    }
+    if( poFeature == NULL )
+        return NULL;
+
+    return poFeature->Clone();
 }
 
 /************************************************************************/
@@ -167,70 +220,161 @@ OGRFeature *OGRMemLayer::GetFeature( GIntBig nFeatureId )
 OGRErr OGRMemLayer::ISetFeature( OGRFeature *poFeature )
 
 {
-    if (!bUpdatable)
+    if (!m_bUpdatable)
         return OGRERR_FAILURE;
 
     if( poFeature == NULL )
         return OGRERR_FAILURE;
 
+    // If we don't have a FID, find one available
     if( poFeature->GetFID() == OGRNullFID )
     {
-        while( iNextCreateFID < nMaxFeatureCount 
-               && papoFeatures[iNextCreateFID] != NULL )
-            iNextCreateFID++;
-        poFeature->SetFID( iNextCreateFID++ );
+        if( m_papoFeatures != NULL )
+        {
+            while( m_iNextCreateFID < m_nMaxFeatureCount
+                && m_papoFeatures[m_iNextCreateFID] != NULL )
+            {
+                m_iNextCreateFID++;
+            }
+        }
+        else
+        {
+            FeatureIterator oIter;
+            while( (oIter = m_oMapFeatures.find(m_iNextCreateFID)) !=
+                   m_oMapFeatures.end() )
+                m_iNextCreateFID++;
+        }
+        poFeature->SetFID( m_iNextCreateFID++ );
     }
     else if ( poFeature->GetFID() < OGRNullFID )
     {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "negative FID are not supported");
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "negative FID are not supported" );
         return OGRERR_FAILURE;
     }
 
-    if( poFeature->GetFID() >= nMaxFeatureCount )
+    OGRFeature* poFeatureCloned = poFeature->Clone();
+    if( poFeatureCloned == NULL )
+        return OGRERR_FAILURE;
+    const GIntBig nFID = poFeature->GetFID();
+
+    if( m_papoFeatures != NULL && nFID > 100000 &&
+        nFID > m_nMaxFeatureCount + 1000 )
     {
-        GIntBig nNewCount = MAX(2*nMaxFeatureCount+10, poFeature->GetFID() + 1 );
-        if( (GIntBig)(size_t)(sizeof(OGRFeature *) * nNewCount) !=
-                                (GIntBig)sizeof(OGRFeature *) * nNewCount )
+        // Convert to map if gap from current max size is too big
+        IOGRMemLayerFeatureIterator* poIter = GetIterator();
+        try
+        {
+            OGRFeature* poFeatureIter;
+            while( (poFeatureIter = poIter->Next()) != NULL )
+            {
+                m_oMapFeatures[poFeatureIter->GetFID()] = poFeatureIter;
+            }
+            delete poIter;
+            CPLFree(m_papoFeatures);
+            m_papoFeatures = NULL;
+            m_nMaxFeatureCount = 0;
+        }
+        catch( const std::bad_alloc& )
         {
+            m_oMapFeatures.clear();
             CPLError(CE_Failure, CPLE_OutOfMemory,
-                     "Cannot allocate array of " CPL_FRMT_GIB " elements", nNewCount);
+                    "Cannot allocate memory");
+            delete poFeatureCloned;
+            delete poIter;
             return OGRERR_FAILURE;
         }
+    }
 
-        OGRFeature** papoNewFeatures = (OGRFeature **) 
-            VSIRealloc( papoFeatures, (size_t)(sizeof(OGRFeature *) * nNewCount) );
-        if (papoNewFeatures == NULL)
+    if( m_papoFeatures != NULL ||
+        (m_oMapFeatures.size() == 0 && nFID <= 100000) )
+    {
+        if( nFID >= m_nMaxFeatureCount )
         {
-            CPLError(CE_Failure, CPLE_OutOfMemory,
-                     "Cannot allocate array of " CPL_FRMT_GIB " elements", nNewCount);
+            const GIntBig nNewCount =
+                MAX(m_nMaxFeatureCount+m_nMaxFeatureCount/3+10, nFID + 1 );
+            if( static_cast<GIntBig>(static_cast<size_t>(sizeof(OGRFeature *)) *
+                                     nNewCount) !=
+                static_cast<GIntBig>(sizeof(OGRFeature *)) * nNewCount )
+            {
+                CPLError( CE_Failure, CPLE_OutOfMemory,
+                          "Cannot allocate array of " CPL_FRMT_GIB " elements",
+                          nNewCount );
+                delete poFeatureCloned;
+                return OGRERR_FAILURE;
+            }
+
+            OGRFeature** papoNewFeatures = static_cast<OGRFeature **>(
+                VSI_REALLOC_VERBOSE(
+                    m_papoFeatures,
+                    static_cast<size_t>(sizeof(OGRFeature *) * nNewCount) ) );
+            if (papoNewFeatures == NULL)
+            {
+                delete poFeatureCloned;
+                return OGRERR_FAILURE;
+            }
+            m_papoFeatures = papoNewFeatures;
+            memset( m_papoFeatures + m_nMaxFeatureCount, 0,
+                    sizeof(OGRFeature *) *
+                    static_cast<size_t>(nNewCount - m_nMaxFeatureCount) );
+            m_nMaxFeatureCount = nNewCount;
+        }
+#ifdef DEBUG
+        /* Just to please Coverity. Cannot happen */
+        if( m_papoFeatures == NULL )
+        {
+            delete poFeatureCloned;
             return OGRERR_FAILURE;
         }
-        papoFeatures = papoNewFeatures;
-        memset( papoFeatures + nMaxFeatureCount, 0, 
-                sizeof(OGRFeature *) * (size_t)(nNewCount - nMaxFeatureCount) );
-        nMaxFeatureCount = nNewCount;
-    }
+#endif
+
+        if( m_papoFeatures[nFID] != NULL )
+        {
+            delete m_papoFeatures[nFID];
+            m_papoFeatures[nFID] = NULL;
+        }
+        else
+            m_nFeatureCount++;
+
+        m_papoFeatures[nFID] = poFeatureCloned;
 
-    if( papoFeatures[poFeature->GetFID()] != NULL )
+    }
+    else
     {
-        delete papoFeatures[poFeature->GetFID()];
-        papoFeatures[poFeature->GetFID()] = NULL;
-        nFeatureCount--;
+        FeatureIterator oIter = m_oMapFeatures.find(nFID);
+        if( oIter != m_oMapFeatures.end() )
+        {
+            delete oIter->second;
+            oIter->second = poFeatureCloned;
+        }
+        else
+        {
+            try
+            {
+                m_oMapFeatures[nFID] = poFeatureCloned;
+                m_nFeatureCount++;
+            }
+            catch( const std::bad_alloc& )
+            {
+                CPLError(CE_Failure, CPLE_OutOfMemory,
+                        "Cannot allocate memory");
+                delete poFeatureCloned;
+                return OGRERR_FAILURE;
+            }
+        }
     }
 
-    papoFeatures[poFeature->GetFID()] = poFeature->Clone();
-    int i;
-    for(i = 0; i < poFeatureDefn->GetGeomFieldCount(); i ++)
+    for(int i = 0; i < m_poFeatureDefn->GetGeomFieldCount(); i ++)
     {
-        OGRGeometry* poGeom = papoFeatures[poFeature->GetFID()]->GetGeomFieldRef(i);
+        OGRGeometry* poGeom = poFeatureCloned->GetGeomFieldRef(i);
         if( poGeom != NULL && poGeom->getSpatialReference() == NULL )
         {
             poGeom->assignSpatialReference(
-                poFeatureDefn->GetGeomFieldDefn(i)->GetSpatialRef());
+                m_poFeatureDefn->GetGeomFieldDefn(i)->GetSpatialRef());
         }
     }
-    nFeatureCount++;
+
+    m_bUpdated = true;
 
     return OGRERR_NONE;
 }
@@ -242,24 +386,33 @@ OGRErr OGRMemLayer::ISetFeature( OGRFeature *poFeature )
 OGRErr OGRMemLayer::ICreateFeature( OGRFeature *poFeature )
 
 {
-    if (!bUpdatable)
+    if (!m_bUpdatable)
         return OGRERR_FAILURE;
 
     if( poFeature->GetFID() != OGRNullFID &&
-        poFeature->GetFID() != iNextCreateFID )
-        bHasHoles = TRUE;
+        poFeature->GetFID() != m_iNextCreateFID )
+        m_bHasHoles = true;
 
-    if( poFeature->GetFID() != OGRNullFID 
-        && poFeature->GetFID() >= 0
-        && poFeature->GetFID() < nMaxFeatureCount )
+    // If the feature has already a FID and that a feature with the same
+    // FID is already registered in the layer, then unset our FID
+    if( poFeature->GetFID() >= 0 )
     {
-        if( papoFeatures[poFeature->GetFID()] != NULL )
-            poFeature->SetFID( OGRNullFID );
+        if( m_papoFeatures != NULL )
+        {
+            if( poFeature->GetFID() < m_nMaxFeatureCount &&
+                m_papoFeatures[poFeature->GetFID()] != NULL )
+            {
+                poFeature->SetFID( OGRNullFID );
+            }
+        }
+        else
+        {
+            FeatureIterator oIter = m_oMapFeatures.find(poFeature->GetFID());
+            if( oIter != m_oMapFeatures.end() )
+                poFeature->SetFID( OGRNullFID );
+        }
     }
 
-    if( poFeature->GetFID() > 10000000 )
-        poFeature->SetFID( OGRNullFID );
-
     return SetFeature( poFeature );
 }
 
@@ -270,23 +423,40 @@ OGRErr OGRMemLayer::ICreateFeature( OGRFeature *poFeature )
 OGRErr OGRMemLayer::DeleteFeature( GIntBig nFID )
 
 {
-    if (!bUpdatable)
+    if (!m_bUpdatable)
         return OGRERR_FAILURE;
 
-    if( nFID < 0 || nFID >= nMaxFeatureCount 
-        || papoFeatures[nFID] == NULL )
+    if( nFID < 0 )
     {
         return OGRERR_FAILURE;
     }
-    else 
-    {
-        bHasHoles = TRUE;
 
-        delete papoFeatures[nFID];
-        papoFeatures[nFID] = NULL;
-        nFeatureCount--;
-        return OGRERR_NONE;
+    if( m_papoFeatures != NULL )
+    {
+        if( nFID >= m_nMaxFeatureCount || m_papoFeatures[nFID] == NULL )
+        {
+            return OGRERR_FAILURE;
+        }
+        delete m_papoFeatures[nFID];
+        m_papoFeatures[nFID] = NULL;
     }
+    else
+    {
+        FeatureIterator oIter = m_oMapFeatures.find(nFID);
+        if( oIter == m_oMapFeatures.end() )
+        {
+            return OGRERR_FAILURE;
+        }
+        delete oIter->second;
+        m_oMapFeatures.erase(oIter);
+    }
+
+    m_bHasHoles = true;
+    m_nFeatureCount--;
+
+    m_bUpdated = true;
+
+    return OGRERR_NONE;
 }
 
 /************************************************************************/
@@ -303,8 +473,8 @@ GIntBig OGRMemLayer::GetFeatureCount( int bForce )
 {
     if( m_poFilterGeom != NULL || m_poAttrQuery != NULL )
         return OGRLayer::GetFeatureCount( bForce );
-    else
-        return nFeatureCount;
+
+    return m_nFeatureCount;
 }
 
 /************************************************************************/
@@ -317,9 +487,9 @@ int OGRMemLayer::TestCapability( const char * pszCap )
     if( EQUAL(pszCap,OLCRandomRead) )
         return TRUE;
 
-    else if( EQUAL(pszCap,OLCSequentialWrite) 
+    else if( EQUAL(pszCap,OLCSequentialWrite)
              || EQUAL(pszCap,OLCRandomWrite) )
-        return bUpdatable;
+        return m_bUpdatable;
 
     else if( EQUAL(pszCap,OLCFastFeatureCount) )
         return m_poFilterGeom == NULL && m_poAttrQuery == NULL;
@@ -328,24 +498,30 @@ int OGRMemLayer::TestCapability( const char * pszCap )
         return FALSE;
 
     else if( EQUAL(pszCap,OLCDeleteFeature) )
-        return bUpdatable;
+        return m_bUpdatable;
 
     else if( EQUAL(pszCap,OLCCreateField) ||
              EQUAL(pszCap,OLCCreateGeomField) ||
              EQUAL(pszCap,OLCDeleteField) ||
              EQUAL(pszCap,OLCReorderFields) ||
              EQUAL(pszCap,OLCAlterFieldDefn) )
-        return bUpdatable;
+        return m_bUpdatable;
 
     else if( EQUAL(pszCap,OLCFastSetNextByIndex) )
-        return m_poFilterGeom == NULL && m_poAttrQuery == NULL && !bHasHoles;
+        return m_poFilterGeom == NULL && m_poAttrQuery == NULL &&
+               ((m_papoFeatures != NULL && !m_bHasHoles) ||
+                m_oMapFeatures.size() == 0);
 
     else if( EQUAL(pszCap,OLCStringsAsUTF8) )
-        return bAdvertizeUTF8;
+        return m_bAdvertizeUTF8;
 
     else if( EQUAL(pszCap,OLCCurveGeometries) )
         return TRUE;
-    else 
+
+    else if( EQUAL(pszCap,OLCMeasuredGeometries) )
+        return TRUE;
+
+    else
         return FALSE;
 }
 
@@ -354,33 +530,31 @@ int OGRMemLayer::TestCapability( const char * pszCap )
 /************************************************************************/
 
 OGRErr OGRMemLayer::CreateField( OGRFieldDefn *poField,
-                                 CPL_UNUSED int bApproxOK )
+                                 int /* bApproxOK */ )
 {
-    if (!bUpdatable)
+    if (!m_bUpdatable)
         return OGRERR_FAILURE;
 
 /* -------------------------------------------------------------------- */
 /*      simple case, no features exist yet.                             */
 /* -------------------------------------------------------------------- */
-    if( nFeatureCount == 0 )
+    if( m_nFeatureCount == 0 )
     {
-        poFeatureDefn->AddFieldDefn( poField );
+        m_poFeatureDefn->AddFieldDefn( poField );
         return OGRERR_NONE;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Add field definition and setup remap definition.                */
 /* -------------------------------------------------------------------- */
-    int  *panRemap;
-    GIntBig   i;
+    m_poFeatureDefn->AddFieldDefn( poField );
 
-    poFeatureDefn->AddFieldDefn( poField );
-
-    panRemap = (int *) CPLMalloc(sizeof(int) * poFeatureDefn->GetFieldCount());
-    for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
+    int *panRemap = static_cast<int *>(
+        CPLMalloc(sizeof(int) * m_poFeatureDefn->GetFieldCount()) );
+    for( GIntBig i = 0; i < m_poFeatureDefn->GetFieldCount(); ++i )
     {
-        if( i < poFeatureDefn->GetFieldCount() - 1 )
-            panRemap[i] = (int)i;
+        if( i < m_poFeatureDefn->GetFieldCount() - 1 )
+            panRemap[i] = static_cast<int>(i);
         else
             panRemap[i] = -1;
     }
@@ -389,14 +563,18 @@ OGRErr OGRMemLayer::CreateField( OGRFieldDefn *poField,
 /*      Remap all the internal features.  Hopefully there aren't any    */
 /*      external features referring to our OGRFeatureDefn!              */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < nMaxFeatureCount; i++ )
+    IOGRMemLayerFeatureIterator* poIter = GetIterator();
+    OGRFeature* poFeature;
+    while( (poFeature = poIter->Next()) != NULL )
     {
-        if( papoFeatures[i] != NULL )
-            papoFeatures[i]->RemapFields( NULL, panRemap );
+        poFeature->RemapFields( NULL, panRemap );
     }
+    delete poIter;
 
     CPLFree( panRemap );
 
+    m_bUpdated = true;
+
     return OGRERR_NONE;
 }
 
@@ -406,10 +584,10 @@ OGRErr OGRMemLayer::CreateField( OGRFieldDefn *poField,
 
 OGRErr OGRMemLayer::DeleteField( int iField )
 {
-    if (!bUpdatable)
+    if (!m_bUpdatable)
         return OGRERR_FAILURE;
 
-    if (iField < 0 || iField >= poFeatureDefn->GetFieldCount())
+    if (iField < 0 || iField >= m_poFeatureDefn->GetFieldCount())
     {
         CPLError( CE_Failure, CPLE_NotSupported,
                   "Invalid field index");
@@ -420,29 +598,31 @@ OGRErr OGRMemLayer::DeleteField( int iField )
 /*      Update all the internal features.  Hopefully there aren't any   */
 /*      external features referring to our OGRFeatureDefn!              */
 /* -------------------------------------------------------------------- */
-    for( GIntBig i = 0; i < nMaxFeatureCount; i++ )
+    IOGRMemLayerFeatureIterator* poIter = GetIterator();
+    OGRFeature* poFeature;
+    while( (poFeature = poIter->Next()) != NULL )
     {
-        if( papoFeatures[i] == NULL )
-            continue;
-
-        OGRField* poFieldRaw = papoFeatures[i]->GetRawFieldRef(iField);
-        if( papoFeatures[i]->IsFieldSet(iField) )
+        OGRField* poFieldRaw = poFeature->GetRawFieldRef(iField);
+        if( poFeature->IsFieldSet(iField) )
         {
             /* Little trick to unallocate the field */
             OGRField sField;
             sField.Set.nMarker1 = OGRUnsetMarker;
             sField.Set.nMarker2 = OGRUnsetMarker;
-            papoFeatures[i]->SetField(iField, &sField);
+            poFeature->SetField(iField, &sField);
         }
 
-        if (iField < poFeatureDefn->GetFieldCount() - 1)
+        if (iField < m_poFeatureDefn->GetFieldCount() - 1)
         {
             memmove( poFieldRaw, poFieldRaw + 1,
-                     sizeof(OGRField) * (poFeatureDefn->GetFieldCount() - 1 - iField) );
+                     sizeof(OGRField) * (m_poFeatureDefn->GetFieldCount() - 1 - iField) );
         }
     }
+    delete poIter;
+
+    m_bUpdated = true;
 
-    return poFeatureDefn->DeleteFieldDefn( iField );
+    return m_poFeatureDefn->DeleteFieldDefn( iField );
 }
 
 /************************************************************************/
@@ -451,13 +631,13 @@ OGRErr OGRMemLayer::DeleteField( int iField )
 
 OGRErr OGRMemLayer::ReorderFields( int* panMap )
 {
-    if (!bUpdatable)
+    if (!m_bUpdatable)
         return OGRERR_FAILURE;
 
-    if (poFeatureDefn->GetFieldCount() == 0)
+    if (m_poFeatureDefn->GetFieldCount() == 0)
         return OGRERR_NONE;
 
-    OGRErr eErr = OGRCheckPermutation(panMap, poFeatureDefn->GetFieldCount());
+    OGRErr eErr = OGRCheckPermutation(panMap, m_poFeatureDefn->GetFieldCount());
     if (eErr != OGRERR_NONE)
         return eErr;
 
@@ -465,34 +645,39 @@ OGRErr OGRMemLayer::ReorderFields( int* panMap )
 /*      Remap all the internal features.  Hopefully there aren't any    */
 /*      external features referring to our OGRFeatureDefn!              */
 /* -------------------------------------------------------------------- */
-    for( GIntBig i = 0; i < nMaxFeatureCount; i++ )
+    IOGRMemLayerFeatureIterator* poIter = GetIterator();
+    OGRFeature* poFeature;
+    while( (poFeature = poIter->Next()) != NULL )
     {
-        if( papoFeatures[i] != NULL )
-            papoFeatures[i]->RemapFields( NULL, panMap );
+        poFeature->RemapFields( NULL, panMap );
     }
+    delete poIter;
+
+    m_bUpdated = true;
 
-    return poFeatureDefn->ReorderFieldDefns( panMap );
+    return m_poFeatureDefn->ReorderFieldDefns( panMap );
 }
 
 /************************************************************************/
 /*                           AlterFieldDefn()                           */
 /************************************************************************/
 
-OGRErr OGRMemLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags )
+OGRErr OGRMemLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn,
+                                    int nFlagsIn )
 {
-    if (!bUpdatable)
+    if (!m_bUpdatable)
         return OGRERR_FAILURE;
 
-    if (iField < 0 || iField >= poFeatureDefn->GetFieldCount())
+    if (iField < 0 || iField >= m_poFeatureDefn->GetFieldCount())
     {
         CPLError( CE_Failure, CPLE_NotSupported,
                   "Invalid field index");
         return OGRERR_FAILURE;
     }
 
-    OGRFieldDefn* poFieldDefn = poFeatureDefn->GetFieldDefn(iField);
+    OGRFieldDefn* poFieldDefn = m_poFeatureDefn->GetFieldDefn(iField);
 
-    if ((nFlags & ALTER_TYPE_FLAG) &&
+    if ((nFlagsIn & ALTER_TYPE_FLAG) &&
         poFieldDefn->GetType() != poNewFieldDefn->GetType())
     {
         if ((poNewFieldDefn->GetType() == OFTDate ||
@@ -511,17 +696,17 @@ OGRErr OGRMemLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, in
     /*      Update all the internal features.  Hopefully there aren't any   */
     /*      external features referring to our OGRFeatureDefn!              */
     /* -------------------------------------------------------------------- */
-            for( GIntBig i = 0; i < nMaxFeatureCount; i++ )
+            IOGRMemLayerFeatureIterator* poIter = GetIterator();
+            OGRFeature* poFeature;
+            while( (poFeature = poIter->Next()) != NULL )
             {
-                if( papoFeatures[i] == NULL )
-                    continue;
-
-                OGRField* poFieldRaw = papoFeatures[i]->GetRawFieldRef(iField);
-                if( papoFeatures[i]->IsFieldSet(iField) )
+                OGRField* poFieldRaw = poFeature->GetRawFieldRef(iField);
+                if( poFeature->IsFieldSet(iField) )
                 {
                     poFieldRaw->Integer64 = poFieldRaw->Integer;
                 }
             }
+            delete poIter;
         }
         else if (poNewFieldDefn->GetType() == OFTReal &&
                  poFieldDefn->GetType() == OFTInteger)
@@ -530,17 +715,17 @@ OGRErr OGRMemLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, in
     /*      Update all the internal features.  Hopefully there aren't any   */
     /*      external features referring to our OGRFeatureDefn!              */
     /* -------------------------------------------------------------------- */
-            for( GIntBig i = 0; i < nMaxFeatureCount; i++ )
+            IOGRMemLayerFeatureIterator* poIter = GetIterator();
+            OGRFeature* poFeature;
+            while( (poFeature = poIter->Next()) != NULL )
             {
-                if( papoFeatures[i] == NULL )
-                    continue;
-
-                OGRField* poFieldRaw = papoFeatures[i]->GetRawFieldRef(iField);
-                if( papoFeatures[i]->IsFieldSet(iField) )
+                OGRField* poFieldRaw = poFeature->GetRawFieldRef(iField);
+                if( poFeature->IsFieldSet(iField) )
                 {
                     poFieldRaw->Real = poFieldRaw->Integer;
                 }
             }
+            delete poIter;
         }
         else if (poNewFieldDefn->GetType() == OFTReal &&
                  poFieldDefn->GetType() == OFTInteger64)
@@ -549,24 +734,25 @@ OGRErr OGRMemLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, in
     /*      Update all the internal features.  Hopefully there aren't any   */
     /*      external features referring to our OGRFeatureDefn!              */
     /* -------------------------------------------------------------------- */
-            for( GIntBig i = 0; i < nMaxFeatureCount; i++ )
+            IOGRMemLayerFeatureIterator* poIter = GetIterator();
+            OGRFeature* poFeature;
+            while( (poFeature = poIter->Next()) != NULL )
             {
-                if( papoFeatures[i] == NULL )
-                    continue;
-
-                OGRField* poFieldRaw = papoFeatures[i]->GetRawFieldRef(iField);
-                if( papoFeatures[i]->IsFieldSet(iField) )
+                OGRField* poFieldRaw = poFeature->GetRawFieldRef(iField);
+                if( poFeature->IsFieldSet(iField) )
                 {
                     poFieldRaw->Real = (double) poFieldRaw->Integer64;
                 }
             }
+            delete poIter;
         }
         else
         {
             if (poNewFieldDefn->GetType() != OFTString)
             {
                 CPLError( CE_Failure, CPLE_NotSupported,
-                        "Can only convert from OFTInteger to OFTReal, or from anything to OFTString");
+                          "Can only convert from OFTInteger to OFTReal, "
+                          "or from anything to OFTString");
                 return OGRERR_FAILURE;
             }
 
@@ -574,38 +760,40 @@ OGRErr OGRMemLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, in
     /*      Update all the internal features.  Hopefully there aren't any   */
     /*      external features referring to our OGRFeatureDefn!              */
     /* -------------------------------------------------------------------- */
-            for( GIntBig i = 0; i < nMaxFeatureCount; i++ )
+            IOGRMemLayerFeatureIterator* poIter = GetIterator();
+            OGRFeature* poFeature;
+            while( (poFeature = poIter->Next()) != NULL )
             {
-                if( papoFeatures[i] == NULL )
-                    continue;
-
-                OGRField* poFieldRaw = papoFeatures[i]->GetRawFieldRef(iField);
-                if( papoFeatures[i]->IsFieldSet(iField) )
+                OGRField* poFieldRaw = poFeature->GetRawFieldRef(iField);
+                if( poFeature->IsFieldSet(iField) )
                 {
-                    char* pszVal = CPLStrdup(papoFeatures[i]->GetFieldAsString(iField));
+                    char* pszVal = CPLStrdup(poFeature->GetFieldAsString(iField));
 
                     /* Little trick to unallocate the field */
                     OGRField sField;
                     sField.Set.nMarker1 = OGRUnsetMarker;
                     sField.Set.nMarker2 = OGRUnsetMarker;
-                    papoFeatures[i]->SetField(iField, &sField);
+                    poFeature->SetField(iField, &sField);
 
                     poFieldRaw->String = pszVal;
                 }
             }
+            delete poIter;
         }
 
         poFieldDefn->SetType(poNewFieldDefn->GetType());
     }
 
-    if (nFlags & ALTER_NAME_FLAG)
+    if (nFlagsIn & ALTER_NAME_FLAG)
         poFieldDefn->SetName(poNewFieldDefn->GetNameRef());
-    if (nFlags & ALTER_WIDTH_PRECISION_FLAG)
+    if (nFlagsIn & ALTER_WIDTH_PRECISION_FLAG)
     {
         poFieldDefn->SetWidth(poNewFieldDefn->GetWidth());
         poFieldDefn->SetPrecision(poNewFieldDefn->GetPrecision());
     }
 
+    m_bUpdated = true;
+
     return OGRERR_NONE;
 }
 
@@ -617,31 +805,29 @@ OGRErr OGRMemLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, in
 OGRErr OGRMemLayer::CreateGeomField( OGRGeomFieldDefn *poGeomField,
                                      CPL_UNUSED int bApproxOK )
 {
-    if (!bUpdatable)
+    if (!m_bUpdatable)
         return OGRERR_FAILURE;
 
 /* -------------------------------------------------------------------- */
 /*      simple case, no features exist yet.                             */
 /* -------------------------------------------------------------------- */
-    if( nFeatureCount == 0 )
+    if( m_nFeatureCount == 0 )
     {
-        poFeatureDefn->AddGeomFieldDefn( poGeomField );
+        m_poFeatureDefn->AddGeomFieldDefn( poGeomField );
         return OGRERR_NONE;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Add field definition and setup remap definition.                */
 /* -------------------------------------------------------------------- */
-    int  *panRemap;
-    GIntBig   i;
-
-    poFeatureDefn->AddGeomFieldDefn( poGeomField );
+    m_poFeatureDefn->AddGeomFieldDefn( poGeomField );
 
-    panRemap = (int *) CPLMalloc(sizeof(int) * poFeatureDefn->GetGeomFieldCount());
-    for( i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
+    int *panRemap = static_cast<int *>(
+        CPLMalloc(sizeof(int) * m_poFeatureDefn->GetGeomFieldCount()) );
+    for( GIntBig i = 0; i < m_poFeatureDefn->GetGeomFieldCount(); i++ )
     {
-        if( i < poFeatureDefn->GetGeomFieldCount() - 1 )
-            panRemap[i] = (int) i;
+        if( i < m_poFeatureDefn->GetGeomFieldCount() - 1 )
+            panRemap[i] = static_cast<int>(i);
         else
             panRemap[i] = -1;
     }
@@ -650,13 +836,99 @@ OGRErr OGRMemLayer::CreateGeomField( OGRGeomFieldDefn *poGeomField,
 /*      Remap all the internal features.  Hopefully there aren't any    */
 /*      external features referring to our OGRFeatureDefn!              */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < nMaxFeatureCount; i++ )
+    IOGRMemLayerFeatureIterator* poIter = GetIterator();
+    OGRFeature* poFeature;
+    while( (poFeature = poIter->Next()) != NULL )
     {
-        if( papoFeatures[i] != NULL )
-            papoFeatures[i]->RemapGeomFields( NULL, panRemap );
+        poFeature->RemapGeomFields( NULL, panRemap );
     }
+    delete poIter;
 
     CPLFree( panRemap );
 
+    m_bUpdated = true;
+
     return OGRERR_NONE;
 }
+
+/************************************************************************/
+/*                        OGRMemLayerIteratorArray                      */
+/************************************************************************/
+
+class OGRMemLayerIteratorArray: public IOGRMemLayerFeatureIterator
+{
+            GIntBig      m_iCurIdx;
+            GIntBig      m_nMaxFeatureCount;
+            OGRFeature **m_papoFeatures;
+
+    public:
+        OGRMemLayerIteratorArray(GIntBig nMaxFeatureCount,
+                                 OGRFeature **papoFeatures):
+            m_iCurIdx(0), m_nMaxFeatureCount(nMaxFeatureCount),
+            m_papoFeatures(papoFeatures)
+        {
+        }
+
+       ~OGRMemLayerIteratorArray()
+       {
+       }
+
+       virtual OGRFeature* Next()
+       {
+           while( m_iCurIdx < m_nMaxFeatureCount )
+           {
+               OGRFeature* poFeature = m_papoFeatures[m_iCurIdx];
+               m_iCurIdx ++;
+               if( poFeature != NULL )
+                   return poFeature;
+           }
+           return NULL;
+       }
+};
+
+/************************************************************************/
+/*                         OGRMemLayerIteratorMap                       */
+/************************************************************************/
+
+class OGRMemLayerIteratorMap: public IOGRMemLayerFeatureIterator
+{
+    typedef std::map<GIntBig, OGRFeature*>           FeatureMap;
+    typedef std::map<GIntBig, OGRFeature*>::iterator FeatureIterator;
+
+            FeatureMap&          m_oMapFeatures;
+            FeatureIterator      m_oIter;
+
+    public:
+        OGRMemLayerIteratorMap(FeatureMap& oMapFeatures):
+            m_oMapFeatures(oMapFeatures),
+            m_oIter(oMapFeatures.begin())
+        {}
+
+       ~OGRMemLayerIteratorMap() {}
+
+       virtual OGRFeature* Next()
+       {
+           if( m_oIter != m_oMapFeatures.end() )
+           {
+               OGRFeature* poFeature = m_oIter->second;
+               ++m_oIter;
+               return poFeature;
+           }
+           return NULL;
+       }
+
+    private:
+        CPL_DISALLOW_COPY_ASSIGN(OGRMemLayerIteratorMap)
+};
+
+/************************************************************************/
+/*                            GetIterator()                             */
+/************************************************************************/
+
+IOGRMemLayerFeatureIterator* OGRMemLayer::GetIterator()
+{
+    if( m_oMapFeatures.size() == 0 )
+        return new OGRMemLayerIteratorArray(m_nMaxFeatureCount, m_papoFeatures);
+
+    return new OGRMemLayerIteratorMap(m_oMapFeatures);
+}
diff --git a/ogr/ogrsf_frmts/mitab/HISTORY.TXT b/ogr/ogrsf_frmts/mitab/HISTORY.TXT
index c6b310c..751b15c 100644
--- a/ogr/ogrsf_frmts/mitab/HISTORY.TXT
+++ b/ogr/ogrsf_frmts/mitab/HISTORY.TXT
@@ -207,7 +207,7 @@ Version 1.6.0 (2007-02-15)
 - Improved generation of the .map's internal spatial index and object
   data blocks to produce an optimal r-tree, resulting in performance 
   improvements of up to 30 times faster on some spatial searches, 
-  matching the perfomance of files generated by MapInfo. (bug 1585)
+  matching the performance of files generated by MapInfo. (bug 1585)
   (Thanks to Aircom International (Andrew Blake) for funding this.)
 
 - Fixed problem with null brush bg color becoming black when parsing
@@ -449,10 +449,10 @@ Version 1.2.4 (2003-07-23)
 
  - mitab_spatialref.cpp, mitab_coodsys.cpp: Fixed up regional mercator logic.
    It was screwing up transverse mercator with non-zero latitude when writing
-   to tab, and wasn't being written properly to .mif. NFW
+   to tab, and was not being written properly to .mif. NFW
 
  - mitab_feature.cpp: fixed C++ style true/false where TRUE/FALSE required.
-   As per GDAL bugzilla 311.  NFW
+   As per GDAL Bugzilla 311.  NFW
 
  - Fixed problem scanning node in TABINDNode::FindNext() - bug 2176, FW
 
@@ -673,7 +673,7 @@ Version 1.1.1 - (2001-05-01)
 ----------------------------
 
 - Added implementation for OGRLayer::GetExtent() that returns extents 
-  of the data, which is differents from the bounds of the projection.
+  of the data, which is different from the bounds of the projection.
 
 - Added code to set TOWGS84 values for mitab_coordsys.cpp and 
   mitab_spatialref.cpp.  
@@ -753,7 +753,7 @@ Version 1.0.4 - (2000-11-14)
 
 - Fixed a problem writing indexes - When a new entry was inserted at the 
   beginning of an index node (changing this node's key) then the parent was 
-  not properly updated and some records were not queriable through that index.
+  not properly updated and some records were not queryable through that index.
 
 - Handle '\t' just like a space when parsing mif files.
 
@@ -828,7 +828,7 @@ Version 1.0.1 - (2000-04-21)
 - Added C API documentation (mitab_capi.cpp) + functions to read vertices
   and field information and included C API in public release.
 
-- Modified fltering of new table field name to accept extended chars with
+- Modified filtering of new table field name to accept extended chars with
   accents. 
 
 
diff --git a/ogr/ogrsf_frmts/mitab/README.TXT b/ogr/ogrsf_frmts/mitab/README.TXT
index 6823244..528e80f 100644
--- a/ogr/ogrsf_frmts/mitab/README.TXT
+++ b/ogr/ogrsf_frmts/mitab/README.TXT
@@ -132,11 +132,11 @@ To open a .TAB or .MIF file for read, you can use the static method:
                                         GBool bTestOpenNoError);
 
 This function returns NULL if the file cannot be opened.  If the open
-was succesful, then it returns a new object of the type corresponding
+was successful, then it returns a new object of the type corresponding
 to the type of file that was opened:
 
   class TABFile:  Class to handle .TAB datasets for read/write access.
-                  Note that you cannot use it to modify exsiting datasets
+                  Note that you cannot use it to modify existing datasets
                   (not yet!).
 
   class TABView:  Class to handle views on pairs of .TAB files linked 
diff --git a/ogr/ogrsf_frmts/mitab/drv_mitab.html b/ogr/ogrsf_frmts/mitab/drv_mitab.html
index beb66a7..67f610f 100644
--- a/ogr/ogrsf_frmts/mitab/drv_mitab.html
+++ b/ogr/ogrsf_frmts/mitab/drv_mitab.html
@@ -20,20 +20,20 @@ Update of existing MIF/MID files is not supported.
 
 <p>
 Note: In the rest of this document "MIF/MID File" is used to refer to a
-pair of .MIF + .MID files, and "TAB file" refers to the set of files for a 
+pair of .MIF + .MID files, and "TAB file" refers to the set of files for a
 MapInfo table in binary form (usually with extensions .TAB, .DAT, .MAP, .ID,
 .IND).
 </p>
 
 <p>
-The MapInfo driver treats a whole directory of files as a dataset, and 
+The MapInfo driver treats a whole directory of files as a dataset, and
 a single file within that directory as a layer.  In this case the directory
 name should be used as the dataset name.
 </p>
 
 <p>
-However, it is also possible to use one of the files (.tab or .mif) in a 
-MapInfo set as the dataset name, and then it will be treated as a dataset 
+However, it is also possible to use one of the files (.tab or .mif) in a
+MapInfo set as the dataset name, and then it will be treated as a dataset
 with one single layer.
 </p>
 
@@ -50,7 +50,7 @@ file be set before writing the first feature.
 </p>
 
 <p>
-There is currently no automated setting of valid default bounds for 
+There is currently no automated setting of valid default bounds for
 each spatial reference system, so for the time being, the MapInfo driver sets the following
 default bounds when a new layer is created:
 </p>
@@ -70,7 +70,7 @@ This allows users to override the
 default bounds for existing projections, and to define bounds for new projections
 not listed in the hard-coded table in the driver.
 The format of the file is a simple text file with one CoordSys string
-per line.  The CoordSys lines should follow the MIF specs, and MUST 
+per line.  The CoordSys lines should follow the MIF specs, and MUST
 include the optional Bounds definition at the end of the line, e.g.
 <pre>
 # Lambert 93 French bounds
diff --git a/ogr/ogrsf_frmts/mitab/mitab.h b/ogr/ogrsf_frmts/mitab/mitab.h
index 2f6052a..e071c4d 100644
--- a/ogr/ogrsf_frmts/mitab/mitab.h
+++ b/ogr/ogrsf_frmts/mitab/mitab.h
@@ -17,16 +17,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -113,8 +113,8 @@
  *
  **********************************************************************/
 
-#ifndef _MITAB_H_INCLUDED_
-#define _MITAB_H_INCLUDED_
+#ifndef MITAB_H_INCLUDED_
+#define MITAB_H_INCLUDED_
 
 #include "mitab_priv.h"
 #include "ogr_feature.h"
@@ -127,10 +127,6 @@
 #define MITAB_VERSION      "2.0.0-dev (2008-10)"
 #define MITAB_VERSION_INT  2000000  /* version x.y.z -> xxxyyyzzz */
 
-#ifndef PI
-#  define PI 3.14159265358979323846
-#endif
-
 #ifndef ROUND_INT
 #  define ROUND_INT(dX) ((int)((dX) < 0.0 ? (dX)-0.5 : (dX)+0.5 ))
 #endif
@@ -166,7 +162,7 @@ class IMapInfoFile : public OGRLayer
 {
   private:
 
-  protected: 
+  protected:
     GIntBig             m_nCurFeatureId;
     TABFeature         *m_poCurFeature;
     GBool               m_bBoundsSet;
@@ -207,7 +203,9 @@ class IMapInfoFile : public OGRLayer
     virtual OGRFeature *GetFeature(GIntBig nFeatureId);
     virtual OGRErr      ICreateFeature(OGRFeature *poFeature);
     virtual int         TestCapability( const char * pszCap ) =0;
-    virtual int         GetExtent(OGREnvelope *psExtent, int bForce) =0;
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce) =0;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
     ///////////////
     // Read access specific stuff
@@ -218,10 +216,10 @@ class IMapInfoFile : public OGRLayer
 
     virtual TABFieldType GetNativeFieldType(int nFieldId) = 0;
 
-    virtual int GetBounds(double &dXMin, double &dYMin, 
+    virtual int GetBounds(double &dXMin, double &dYMin,
                           double &dXMax, double &dYMax,
                           GBool bForce = TRUE ) = 0;
-    
+
     virtual OGRSpatialReference *GetSpatialRef() = 0;
 
     virtual int GetFeatureCountByType(int &numPoints, int &numLines,
@@ -235,16 +233,16 @@ class IMapInfoFile : public OGRLayer
     // Write access specific stuff
     //
     GBool       IsBoundsSet()            {return m_bBoundsSet;}
-    virtual int SetBounds(double dXMin, double dYMin, 
+    virtual int SetBounds(double dXMin, double dYMin,
                           double dXMax, double dYMax) = 0;
     virtual int SetFeatureDefn(OGRFeatureDefn *poFeatureDefn,
                             TABFieldType *paeMapInfoNativeFieldTypes = NULL)=0;
     virtual int AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
                                int nWidth=0, int nPrecision=0,
-                               GBool bIndexed=FALSE, GBool bUnique=FALSE, 
+                               GBool bIndexed=FALSE, GBool bUnique=FALSE,
                                int bApproxOK = TRUE) = 0;
     virtual OGRErr CreateField( OGRFieldDefn *poField, int bApproxOK = TRUE );
-    
+
     virtual int SetSpatialRef(OGRSpatialReference *poSpatialRef) = 0;
 
     virtual OGRErr CreateFeature(TABFeature *poFeature) = 0;
@@ -258,7 +256,7 @@ class IMapInfoFile : public OGRLayer
     virtual int  GetProjInfo(TABProjInfo *poPI) = 0;
     virtual int  SetProjInfo(TABProjInfo *poPI) = 0;
     virtual int  SetMIFCoordSys(const char *pszMIFCoordSys) = 0;
-    
+
     static int GetTABType( OGRFieldDefn *poField, TABFieldType* peTABType,
                            int *pnWidth);
 
@@ -274,7 +272,7 @@ class IMapInfoFile : public OGRLayer
  * class to open a TAB dataset and read/write features from/to it.
  *
  *--------------------------------------------------------------------*/
-class TABFile: public IMapInfoFile
+class TABFile CPL_FINAL : public IMapInfoFile
 {
   private:
     char        *m_pszFname;
@@ -339,7 +337,9 @@ class TABFile: public IMapInfoFile
     virtual void        ResetReading();
     virtual int         TestCapability( const char * pszCap );
     virtual GIntBig     GetFeatureCount (int bForce);
-    virtual int         GetExtent(OGREnvelope *psExtent, int bForce);
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce);
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
     /* Implement OGRLayer's SetFeature() for random write, only with TABFile */
     virtual OGRErr      ISetFeature( OGRFeature * );
@@ -348,7 +348,7 @@ class TABFile: public IMapInfoFile
     virtual OGRErr      DeleteField( int iField );
     virtual OGRErr      ReorderFields( int* panMap );
     virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags );
-    
+
     virtual OGRErr      SyncToDisk();
 
     ///////////////
@@ -363,12 +363,12 @@ class TABFile: public IMapInfoFile
 
     virtual TABFieldType GetNativeFieldType(int nFieldId);
 
-    virtual int GetBounds(double &dXMin, double &dYMin, 
+    virtual int GetBounds(double &dXMin, double &dYMin,
                           double &dXMax, double &dYMax,
                           GBool bForce = TRUE );
-    
+
     virtual OGRSpatialReference *GetSpatialRef();
-    
+
     static OGRSpatialReference* GetSpatialRefFromTABProj(const TABProjInfo& sTABProj);
     static int                  GetTABProjFromSpatialRef(const OGRSpatialReference* poSpatialRef,
                                                          TABProjInfo& sTABProj, int& nParmCount);
@@ -385,13 +385,13 @@ class TABFile: public IMapInfoFile
     ///////////////
     // Write access specific stuff
     //
-    virtual int SetBounds(double dXMin, double dYMin, 
+    virtual int SetBounds(double dXMin, double dYMin,
                           double dXMax, double dYMax);
     virtual int SetFeatureDefn(OGRFeatureDefn *poFeatureDefn,
                             TABFieldType *paeMapInfoNativeFieldTypes = NULL);
     virtual int AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
                                int nWidth=0, int nPrecision=0,
-                               GBool bIndexed=FALSE, GBool bUnique=FALSE, 
+                               GBool bIndexed=FALSE, GBool bUnique=FALSE,
                                int bApproxOK = TRUE);
     virtual int SetSpatialRef(OGRSpatialReference *poSpatialRef);
 
@@ -423,25 +423,25 @@ class TABFile: public IMapInfoFile
  *                      class TABView
  *
  * TABView is used to handle special type of .TAB files that are
- * composed of a number of .TAB datasets linked through some indexed 
+ * composed of a number of .TAB datasets linked through some indexed
  * fields.
  *
  * NOTE: The current implementation supports only TABViews composed
  *       of 2 TABFiles linked through an indexed field of integer type.
  *       It is unclear if any other type of views could exist anyways.
  *--------------------------------------------------------------------*/
-class TABView: public IMapInfoFile
+class TABView CPL_FINAL : public IMapInfoFile
 {
   private:
     char        *m_pszFname;
     TABAccess   m_eAccessMode;
     char        **m_papszTABFile;
     char        *m_pszVersion;
-    
+
     char        **m_papszTABFnames;
     TABFile     **m_papoTABFiles;
     int         m_numTABFiles;
-    int         m_nMainTableIndex; // The main table is the one that also 
+    int         m_nMainTableIndex; // The main table is the one that also
                                    // contains the geometries
     char        **m_papszFieldNames;
     char        **m_papszWhereClause;
@@ -452,10 +452,10 @@ class TABView: public IMapInfoFile
     ///////////////
     // Private Read access specific stuff
     //
-    int         ParseTABFile(const char *pszDatasetPath, 
+    int         ParseTABFile(const char *pszDatasetPath,
                              GBool bTestOpenNoError = FALSE);
 
-    int         OpenForRead(const char *pszFname, 
+    int         OpenForRead(const char *pszFname,
                             GBool bTestOpenNoError = FALSE );
 
     ///////////////
@@ -485,8 +485,10 @@ class TABView: public IMapInfoFile
     virtual void        ResetReading();
     virtual int         TestCapability( const char * pszCap );
     virtual GIntBig     GetFeatureCount (int bForce);
-    virtual int         GetExtent(OGREnvelope *psExtent, int bForce);
-    
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce);
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
+
     ///////////////
     // Read access specific stuff
     //
@@ -497,10 +499,10 @@ class TABView: public IMapInfoFile
 
     virtual TABFieldType GetNativeFieldType(int nFieldId);
 
-    virtual int GetBounds(double &dXMin, double &dYMin, 
+    virtual int GetBounds(double &dXMin, double &dYMin,
                           double &dXMax, double &dYMax,
                           GBool bForce = TRUE );
-    
+
     virtual OGRSpatialReference *GetSpatialRef();
 
     virtual int GetFeatureCountByType(int &numPoints, int &numLines,
@@ -513,14 +515,14 @@ class TABView: public IMapInfoFile
     ///////////////
     // Write access specific stuff
     //
-    virtual int SetBounds(double dXMin, double dYMin, 
+    virtual int SetBounds(double dXMin, double dYMin,
                           double dXMax, double dYMax);
     virtual int SetFeatureDefn(OGRFeatureDefn *poFeatureDefn,
                            TABFieldType *paeMapInfoNativeFieldTypes=NULL);
     virtual int AddFieldNative(const char *pszName,
                                TABFieldType eMapInfoType,
                                int nWidth=0, int nPrecision=0,
-                               GBool bIndexed=FALSE, GBool bUnique=FALSE, 
+                               GBool bIndexed=FALSE, GBool bUnique=FALSE,
                                int bApproxOK = TRUE);
     virtual int SetSpatialRef(OGRSpatialReference *poSpatialRef);
 
@@ -553,7 +555,7 @@ class TABView: public IMapInfoFile
  *
  * TABSeamless are supported for read access only.
  *--------------------------------------------------------------------*/
-class TABSeamless: public IMapInfoFile
+class TABSeamless CPL_FINAL : public IMapInfoFile
 {
   private:
     char        *m_pszFname;
@@ -570,7 +572,7 @@ class TABSeamless: public IMapInfoFile
     ///////////////
     // Private Read access specific stuff
     //
-    int         OpenForRead(const char *pszFname, 
+    int         OpenForRead(const char *pszFname,
                             GBool bTestOpenNoError = FALSE );
     int         OpenBaseTable(TABFeature *poIndexFeature,
                               GBool bTestOpenNoError = FALSE);
@@ -596,12 +598,16 @@ class TABSeamless: public IMapInfoFile
            {return m_poFeatureDefnRef?m_poFeatureDefnRef->GetName():"";};
 
     virtual void        SetSpatialFilter( OGRGeometry * );
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+                { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
 
     virtual void        ResetReading();
     virtual int         TestCapability( const char * pszCap );
     virtual GIntBig     GetFeatureCount (int bForce);
-    virtual int         GetExtent(OGREnvelope *psExtent, int bForce);
-    
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce);
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
+
     ///////////////
     // Read access specific stuff
     //
@@ -612,10 +618,10 @@ class TABSeamless: public IMapInfoFile
 
     virtual TABFieldType GetNativeFieldType(int nFieldId);
 
-    virtual int GetBounds(double &dXMin, double &dYMin, 
+    virtual int GetBounds(double &dXMin, double &dYMin,
                           double &dXMax, double &dYMax,
                           GBool bForce = TRUE );
-    
+
     virtual OGRSpatialReference *GetSpatialRef();
 
     virtual int GetFeatureCountByType(int &numPoints, int &numLines,
@@ -668,7 +674,7 @@ class TABSeamless: public IMapInfoFile
  * class to open a (MID/MIF) dataset and read/write features from/to it.
  *
  *--------------------------------------------------------------------*/
-class MIFFile: public IMapInfoFile
+class MIFFile CPL_FINAL : public IMapInfoFile
 {
   private:
     char        *m_pszFname;
@@ -682,7 +688,7 @@ class MIFFile: public IMapInfoFile
     TABFieldType *m_paeFieldType;
     GBool       *m_pabFieldIndexed;
     GBool       *m_pabFieldUnique;
-    
+
     double       m_dfXMultiplier;
     double       m_dfYMultiplier;
     double       m_dfXDisplacement;
@@ -729,7 +735,7 @@ class MIFFile: public IMapInfoFile
     //
     GBool       m_bPreParsed;
     GBool       m_bHeaderWrote;
-    
+
     int         WriteMIFHeader();
     void UpdateExtents(double dfX,double dfY);
 
@@ -751,22 +757,24 @@ class MIFFile: public IMapInfoFile
     virtual int         TestCapability( const char * pszCap ) ;
     virtual GIntBig     GetFeatureCount (int bForce);
     virtual void        ResetReading();
-    virtual int         GetExtent(OGREnvelope *psExtent, int bForce);
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce);
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
     ///////////////
     // Read access specific stuff
     //
-    
+
     virtual GIntBig GetNextFeatureId(GIntBig nPrevId);
     virtual TABFeature *GetFeatureRef(GIntBig nFeatureId);
     virtual OGRFeatureDefn *GetLayerDefn();
 
     virtual TABFieldType GetNativeFieldType(int nFieldId);
 
-    virtual int GetBounds(double &dXMin, double &dYMin, 
+    virtual int GetBounds(double &dXMin, double &dYMin,
                           double &dXMax, double &dYMax,
                           GBool bForce = TRUE );
-    
+
     virtual OGRSpatialReference *GetSpatialRef();
 
     virtual int GetFeatureCountByType(int &numPoints, int &numLines,
@@ -777,17 +785,17 @@ class MIFFile: public IMapInfoFile
     virtual GBool IsFieldUnique(int nFieldId);
 
     virtual int GetVersion() { return m_nVersion; };
-    
+
     ///////////////
     // Write access specific stuff
     //
-    virtual int SetBounds(double dXMin, double dYMin, 
+    virtual int SetBounds(double dXMin, double dYMin,
                           double dXMax, double dYMax);
     virtual int SetFeatureDefn(OGRFeatureDefn *poFeatureDefn,
                             TABFieldType *paeMapInfoNativeFieldTypes = NULL);
     virtual int AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
                                int nWidth=0, int nPrecision=0,
-                               GBool bIndexed=FALSE, GBool bUnique=FALSE, 
+                               GBool bIndexed=FALSE, GBool bUnique=FALSE,
                                int bApproxOK = TRUE);
     /* TODO */
     virtual int SetSpatialRef(OGRSpatialReference *poSpatialRef);
@@ -885,15 +893,15 @@ typedef enum TABFontStyle_t     // Can be OR'ed
  * Values 0x200 to 0x800 in .MAP are 0x100 to 0x400 in .MIF
  *
  * What about TABFSBox (0x100) ?
- * TABFSBox is stored just like the other styles in .MAP files but it is not 
+ * TABFSBox is stored just like the other styles in .MAP files but it is not
  * explicitly stored in a MIF file.
  * If a .MIF FONT() clause contains the optional BG color, then this implies
- * that either Halo or Box was set.  Thus if TABFSHalo (value 256 in MIF) 
+ * that either Halo or Box was set.  Thus if TABFSHalo (value 256 in MIF)
  * is not set in the style, then this implies that TABFSBox should be set.
  */
 
 typedef enum TABCustSymbStyle_t // Can be OR'ed
-{ 
+{
     TABCSNone       = 0,        // Transparent BG, use default colors
     TABCSBGOpaque   = 0x01,     // White pixels are opaque
     TABCSApplyColor = 0x02      // non-white pixels drawn using symbol color
@@ -1017,7 +1025,7 @@ class ITABFeatureSymbol
  *
  * TABFeature will be used as a base class for all the feature classes.
  *
- * This class will also be used to instanciate objects with no Geometry
+ * This class will also be used to instantiate objects with no Geometry
  * (i.e. type TAB_GEOM_NONE) which is a valid case in MapInfo.
  *
  * The logic to read/write the object from/to the .DAT and .MAP files is also
@@ -1080,7 +1088,7 @@ class TABFeature: public OGRFeature
     GBool       ValidateCoordType(TABMAPFile * poMapFile);
     void        ForceCoordTypeAndOrigin(TABGeomType nMapInfoType, GBool bCompr,
                                         GInt32 nComprOrgX, GInt32 nComprOrgY,
-                                        GInt32 nXMin, GInt32 nYMin, 
+                                        GInt32 nXMin, GInt32 nYMin,
                                         GInt32 nXMax, GInt32 nYMax);
 
     /*-----------------------------------------------------------------
@@ -1099,13 +1107,13 @@ class TABFeature: public OGRFeature
     /*-----------------------------------------------------------------
      *----------------------------------------------------------------*/
 
-    void        SetMBR(double dXMin, double dYMin, 
+    void        SetMBR(double dXMin, double dYMin,
                        double dXMax, double dYMax);
-    void        GetMBR(double &dXMin, double &dYMin, 
+    void        GetMBR(double &dXMin, double &dYMin,
                        double &dXMax, double &dYMax);
-    void        SetIntMBR(GInt32 nXMin, GInt32 nYMin, 
+    void        SetIntMBR(GInt32 nXMin, GInt32 nYMin,
                           GInt32 nXMax, GInt32 nYMax);
-    void        GetIntMBR(GInt32 &nXMin, GInt32 &nYMin, 
+    void        GetIntMBR(GInt32 &nXMin, GInt32 &nYMin,
                           GInt32 &nXMax, GInt32 &nYMax);
 
     virtual void DumpMID(FILE *fpOut = NULL);
@@ -1130,7 +1138,7 @@ class TABFeature: public OGRFeature
  * NOTE: This class is also used as a base class for the other point
  * symbol types TABFontPoint and TABCustomPoint.
  *--------------------------------------------------------------------*/
-class TABPoint: public TABFeature, 
+class TABPoint: public TABFeature,
                 public ITABFeatureSymbol
 {
   public:
@@ -1166,7 +1174,7 @@ class TABPoint: public TABFeature,
  *
  * Feature class to handle MapInfo Font Point Symbol types:
  *
- *     TAB_GEOM_FONTSYMBOL_C    0x28 
+ *     TAB_GEOM_FONTSYMBOL_C    0x28
  *     TAB_GEOM_FONTSYMBOL      0x29
  *
  * Feature geometry will be a OGRPoint
@@ -1174,7 +1182,7 @@ class TABPoint: public TABFeature,
  * The symbol number refers to a character code in the specified Windows
  * Font (e.g. "Windings").
  *--------------------------------------------------------------------*/
-class TABFontPoint: public TABPoint, 
+class TABFontPoint CPL_FINAL : public TABPoint,
                     public ITABFeatureFont
 {
   protected:
@@ -1226,14 +1234,14 @@ class TABFontPoint: public TABPoint,
  * Feature geometry will be a OGRPoint
  *
  * The symbol name is the name of a BMP file stored in the "CustSymb"
- * directory (e.g. "arrow.BMP").  The symbol number has no meaning for 
+ * directory (e.g. "arrow.BMP").  The symbol number has no meaning for
  * this symbol type.
  *--------------------------------------------------------------------*/
-class TABCustomPoint: public TABPoint, 
+class TABCustomPoint CPL_FINAL : public TABPoint,
                       public ITABFeatureFont
 {
   protected:
-    GByte       m_nCustomStyle;         // Show BG/Apply Color                 
+    GByte       m_nCustomStyle;         // Show BG/Apply Color
 
   public:
     GByte       m_nUnknown_;
@@ -1260,7 +1268,7 @@ class TABCustomPoint: public TABPoint,
 
     const char *GetSymbolNameRef()      { return GetFontNameRef(); };
     void        SetSymbolName(const char *pszName) {SetFontName(pszName);};
-    
+
     GByte       GetCustomSymbolStyle()              {return m_nCustomStyle;}
     void        SetCustomSymbolStyle(GByte nStyle)  {m_nCustomStyle = nStyle;}
 };
@@ -1282,7 +1290,7 @@ class TABCustomPoint: public TABPoint,
  *
  * Feature geometry can be either a OGRLineString or a OGRMultiLineString
  *--------------------------------------------------------------------*/
-class TABPolyline: public TABFeature, 
+class TABPolyline CPL_FINAL : public TABFeature,
                    public ITABFeaturePen
 {
   private:
@@ -1349,8 +1357,8 @@ class TABPolyline: public TABFeature,
  * inside MapInfo files.  However, when writing features, OGRPolygons with
  * multiple rings will be accepted without problem.
  *--------------------------------------------------------------------*/
-class TABRegion: public TABFeature, 
-                 public ITABFeaturePen, 
+class TABRegion CPL_FINAL : public TABFeature,
+                 public ITABFeaturePen,
                  public ITABFeatureBrush
 {
     GBool       m_bSmooth;
@@ -1358,7 +1366,7 @@ class TABRegion: public TABFeature,
     GBool       m_bCenterIsSet;
     double      m_dCenterX, m_dCenterY;
 
-    int     ComputeNumRings(TABMAPCoordSecHdr **ppasSecHdrs, 
+    int     ComputeNumRings(TABMAPCoordSecHdr **ppasSecHdrs,
                             TABMAPFile *poMAPFile);
     int     AppendSecHdrs(OGRPolygon *poPolygon,
                           TABMAPCoordSecHdr * &pasSecHdrs,
@@ -1375,7 +1383,7 @@ class TABRegion: public TABFeature,
     virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = NULL );
 
     /* 2 methods to make the REGION's geometry look like a single collection
-     * of OGRLinearRings 
+     * of OGRLinearRings
      */
     int                 GetNumRings();
     OGRLinearRing      *GetRingRef(int nRequestedRingIndex);
@@ -1411,13 +1419,13 @@ class TABRegion: public TABFeature,
  *     TAB_GEOM_ROUNDRECT      0x17
  *
  * A rectangle is defined by the coords of its 2 opposite corners (the MBR)
- * Its corners can optionaly be rounded, in which case a X and Y rounding
+ * Its corners can optionally be rounded, in which case a X and Y rounding
  * radius will be defined.
  *
  * Feature geometry will be OGRPolygon
  *--------------------------------------------------------------------*/
-class TABRectangle: public TABFeature, 
-                    public ITABFeaturePen, 
+class TABRectangle CPL_FINAL : public TABFeature,
+                    public ITABFeaturePen,
                     public ITABFeatureBrush
 {
   private:
@@ -1471,14 +1479,14 @@ class TABRectangle: public TABFeature,
  * When an ellipse is read, the returned geometry is a OGRPolygon representing
  * the ellipse with 2 degrees line segments.
  *
- * In the case of the OGRPoint, then the X/Y Radius MUST be set, but.  
+ * In the case of the OGRPoint, then the X/Y Radius MUST be set, but.
  * However with an OGRPolygon, if the X/Y radius are not set (== 0) then
- * the MBR of the polygon will be used to define the ellipse parameters 
- * and the center of the MBR is used as the center of the ellipse... 
+ * the MBR of the polygon will be used to define the ellipse parameters
+ * and the center of the MBR is used as the center of the ellipse...
  * (i.e. the polygon vertices themselves will be ignored).
  *--------------------------------------------------------------------*/
-class TABEllipse: public TABFeature, 
-                  public ITABFeaturePen, 
+class TABEllipse CPL_FINAL : public TABFeature,
+                  public ITABFeaturePen,
                   public ITABFeatureBrush
 {
   private:
@@ -1525,23 +1533,23 @@ class TABEllipse: public TABFeature,
  *     TAB_GEOM_ARC_C      0x0a
  *     TAB_GEOM_ARC        0x0b
  *
- * In MapInfo, an arc is defined by the coords of the MBR corners of its 
+ * In MapInfo, an arc is defined by the coords of the MBR corners of its
  * defining ellipse, which in this case is different from the arc's MBR,
  * and a start and end angle in degrees.
  *
  * Feature geometry can be either an OGRLineString or an OGRPoint.
  *
- * In any case, X/Y radius X/Y center, and start/end angle (in degrees 
+ * In any case, X/Y radius X/Y center, and start/end angle (in degrees
  * counterclockwise) MUST be set.
  *
- * When an arc is read, the returned geometry is an OGRLineString 
+ * When an arc is read, the returned geometry is an OGRLineString
  * representing the arc with 2 degrees line segments.
  *--------------------------------------------------------------------*/
-class TABArc: public TABFeature, 
+class TABArc CPL_FINAL : public TABFeature,
               public ITABFeaturePen
 {
   private:
-    double      m_dStartAngle;  // In degrees, counterclockwise, 
+    double      m_dStartAngle;  // In degrees, counterclockwise,
     double      m_dEndAngle;    // starting at 3 o'clock
 
     virtual int UpdateMBR(TABMAPFile *poMapFile = NULL);
@@ -1591,14 +1599,14 @@ class TABArc: public TABFeature,
  *     TAB_GEOM_TEXT_C         0x10
  *     TAB_GEOM_TEXT           0x11
  *
- * Feature geometry is an OGRPoint corresponding to the lower-left 
+ * Feature geometry is an OGRPoint corresponding to the lower-left
  * corner of the text MBR BEFORE ROTATION.
- * 
+ *
  * Text string, and box height/width (box before rotation is applied)
- * are required in a valid text feature and MUST be set.  
+ * are required in a valid text feature and MUST be set.
  * Text angle and other styles are optional.
  *--------------------------------------------------------------------*/
-class TABText: public TABFeature, 
+class TABText CPL_FINAL : public TABFeature,
                public ITABFeatureFont,
                public ITABFeaturePen
 {
@@ -1705,7 +1713,7 @@ class TABText: public TABFeature,
  * The symbol number is in the range [31..67], with 31=None and corresponds
  * to one of the 35 predefined "Old MapInfo Symbols"
  *--------------------------------------------------------------------*/
-class TABMultiPoint: public TABFeature, 
+class TABMultiPoint CPL_FINAL : public TABFeature,
                      public ITABFeatureSymbol
 {
   private:
@@ -1769,7 +1777,7 @@ class TABMultiPoint: public TABFeature,
  * unless OGRFeature::SetGeometry*() are made virtual in OGR.
  *
  *--------------------------------------------------------------------*/
-class TABCollection: public TABFeature, 
+class TABCollection CPL_FINAL : public TABFeature,
                      public ITABFeatureSymbol
 {
   private:
@@ -1778,7 +1786,7 @@ class TABCollection: public TABFeature,
     TABMultiPoint   *m_poMpoint;
 
     void    EmptyCollection();
-    int     ReadLabelAndMBR(TABMAPCoordBlock *poCoordBlock, 
+    int     ReadLabelAndMBR(TABMAPCoordBlock *poCoordBlock,
                             GBool bComprCoord,
                             GInt32 nComprOrgX, GInt32 nComprOrgY,
                             GInt32 &pnMinX, GInt32 &pnMinY,
@@ -1808,7 +1816,7 @@ class TABCollection: public TABFeature,
     virtual int WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
                                        GBool bCoordDataOnly=FALSE,
                                        TABMAPCoordBlock **ppoCoordBlock=NULL);
-    
+
     virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp);
     virtual int WriteGeometryToMIFFile(MIDDATAFile *fp);
 
@@ -1829,11 +1837,11 @@ class TABCollection: public TABFeature,
 /*---------------------------------------------------------------------
  *                      class TABDebugFeature
  *
- * Feature class to use for testing purposes... this one does not 
+ * Feature class to use for testing purposes... this one does not
  * correspond to any MapInfo type... it's just used to dump info about
  * feature types that are not implemented yet.
  *--------------------------------------------------------------------*/
-class TABDebugFeature: public TABFeature
+class TABDebugFeature CPL_FINAL : public TABFeature
 {
   private:
     GByte       m_abyBuf[512];
@@ -1912,4 +1920,4 @@ int     MITABLoadCoordSysTable(const char *pszFname);
 void    MITABFreeCoordSysTable();
 GBool   MITABCoordSysTableLoaded();
 
-#endif /* _MITAB_H_INCLUDED_ */
+#endif /* MITAB_H_INCLUDED_ */
diff --git a/ogr/ogrsf_frmts/mitab/mitab_bounds.cpp b/ogr/ogrsf_frmts/mitab/mitab_bounds.cpp
index 14f12b0..75817ac 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_bounds.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_bounds.cpp
@@ -1247,10 +1247,10 @@ int MITABLoadCoordSysTable(const char *pszFname)
 
             iLine++;
 
-            if (strlen(pszLine) < 10 || EQUALN(pszLine, "#", 1))
+            if (strlen(pszLine) < 10 || STARTS_WITH_CI(pszLine, "#"))
                 continue;  // Skip empty lines/comments
 
-            if( EQUALN(pszLine, "Source", strlen("Source")) )
+            if( STARTS_WITH_CI(pszLine, "Source") )
             {
                 const char* pszEqual = strchr(pszLine, '=');
                 if( !pszEqual )
@@ -1273,7 +1273,7 @@ int MITABLoadCoordSysTable(const char *pszFname)
                 iLine++;
                 pszLine = CPLReadLineL(fp);
                 if( pszLine == NULL ||
-                    !EQUALN(pszLine, "Destination", strlen("Destination")) ||
+                    !STARTS_WITH_CI(pszLine, "Destination") ||
                     (pszEqual = strchr(pszLine, '=')) == NULL )
                 {
                     CPLError(CE_Warning, CPLE_IllegalArg, "Invalid format at line %d", iLine);
diff --git a/ogr/ogrsf_frmts/mitab/mitab_coordsys.cpp b/ogr/ogrsf_frmts/mitab/mitab_coordsys.cpp
index da49191..fbbb94c 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_coordsys.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_coordsys.cpp
@@ -17,16 +17,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -47,7 +47,7 @@
  * Fixed memory leaks in mitab_capi.cpp and mitab_coordsys.cpp
  *
  * Revision 1.37  2010-07-05 17:20:14  aboudreault
- * Added Krovak projection suppoprt (bug 2230)
+ * Added Krovak projection support (bug 2230)
  *
  * Revision 1.36  2007-11-21 21:15:45  dmorissette
  * Fix asDatumInfoList[] and asSpheroidInfoList[] defns/refs (bug 1826)
@@ -168,7 +168,7 @@ char *MITABSpatialRef2CoordSys( OGRSpatialReference * poSR )
 {
     if( poSR == NULL )
         return NULL;
-    
+
     TABProjInfo     sTABProj;
     int             nParmCount;
     TABFile::GetTABProjFromSpatialRef(poSR, sTABProj, nParmCount);
@@ -176,7 +176,7 @@ char *MITABSpatialRef2CoordSys( OGRSpatialReference * poSR )
 /* -------------------------------------------------------------------- */
 /*      Do coordsys lookup                                              */
 /* -------------------------------------------------------------------- */
-    double dXMin, dYMin, dXMax, dYMax;
+    double dXMin = 0.0, dYMin = 0.0, dXMax = 0.0, dYMax = 0.0;
     int bHasBounds = FALSE;
     if (sTABProj.nProjId > 1 &&
         MITABLookupCoordSysBounds(&sTABProj, dXMin, dYMin, dXMax, dYMax, TRUE) == TRUE)
@@ -188,7 +188,7 @@ char *MITABSpatialRef2CoordSys( OGRSpatialReference * poSR )
  * Translate the units
  *----------------------------------------------------------------*/
     const char  *pszMIFUnits = TABUnitIdToString(sTABProj.nUnitsId);
-    
+
 /* -------------------------------------------------------------------- */
 /*      Build coordinate system definition.                             */
 /* -------------------------------------------------------------------- */
@@ -221,7 +221,7 @@ char *MITABSpatialRef2CoordSys( OGRSpatialReference * poSR )
                      sTABProj.nEllipsoidId,
                      sTABProj.dDatumShiftX, sTABProj.dDatumShiftY, sTABProj.dDatumShiftZ );
         }
-        
+
         if( sTABProj.nDatumId == 9999 )
         {
             osCoordSys += CPLSPrintf(
@@ -238,7 +238,7 @@ char *MITABSpatialRef2CoordSys( OGRSpatialReference * poSR )
     {
         if( sTABProj.nProjId != 0 )
             osCoordSys += "," ;
-        
+
         osCoordSys += CPLSPrintf(
                  " \"%s\"",
                  pszMIFUnits );
@@ -306,7 +306,7 @@ GBool MITABExtractCoordSysBounds( const char * pszCoordSys,
 
     if( pszCoordSys == NULL )
         return FALSE;
-    
+
     papszFields = CSLTokenizeStringComplex( pszCoordSys, " ,()", TRUE, FALSE );
 
     int iBounds = CSLFindString( papszFields, "Bounds" );
@@ -343,14 +343,14 @@ int MITABCoordSys2TABProjInfo(const char * pszCoordSys, TABProjInfo *psProj)
 
     if( pszCoordSys == NULL )
         return -1;
-    
+
     /*-----------------------------------------------------------------
      * Parse the passed string into words.
      *----------------------------------------------------------------*/
     while(*pszCoordSys == ' ') pszCoordSys++;  // Eat leading spaces
-    if( EQUALN(pszCoordSys,"CoordSys",8) )
+    if( STARTS_WITH_CI(pszCoordSys, "CoordSys") )
         pszCoordSys += 9;
-    
+
     papszFields = CSLTokenizeStringComplex( pszCoordSys, " ,", TRUE, FALSE );
 
     /*-----------------------------------------------------------------
@@ -440,7 +440,7 @@ int MITABCoordSys2TABProjInfo(const char * pszCoordSys, TABProjInfo *psProj)
      *----------------------------------------------------------------*/
         int         iDatum;
         const MapInfoDatumInfo *psDatumInfo = NULL;
-        
+
         for(iDatum=0; asDatumInfoList[iDatum].nMapInfoDatumID != -1; iDatum++)
         {
             if( asDatumInfoList[iDatum].nMapInfoDatumID == nDatum )
@@ -470,7 +470,7 @@ int MITABCoordSys2TABProjInfo(const char * pszCoordSys, TABProjInfo *psProj)
             psProj->adDatumParams[3] = psDatumInfo->dfDatumParm3;
             psProj->adDatumParams[4] = psDatumInfo->dfDatumParm4;
         }
-    }    
+    }
 
     /*-----------------------------------------------------------------
      * Fetch the units string.
@@ -487,11 +487,10 @@ int MITABCoordSys2TABProjInfo(const char * pszCoordSys, TABProjInfo *psProj)
     for(int iParam=0; iParam < 6 && CSLCount(papszNextField) > 0; iParam++)
     {
         psProj->adProjParams[iParam] = CPLAtof(papszNextField[0]);
-        papszNextField++;         
+        papszNextField++;
     }
-    
+
     CSLDestroy(papszFields);
 
     return 0;
 }
-
diff --git a/ogr/ogrsf_frmts/mitab/mitab_datfile.cpp b/ogr/ogrsf_frmts/mitab/mitab_datfile.cpp
index d9a417c..f5be77f 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_datfile.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_datfile.cpp
@@ -18,16 +18,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -145,8 +145,9 @@ TABDATFile::TABDATFile()
     m_bCurRecordDeletedFlag = FALSE;
     m_bWriteHeaderInitialized = FALSE;
     m_bWriteEOF = FALSE;
-    
+
     m_bUpdated = FALSE;
+    m_eAccessMode = TABRead;
 }
 
 /**********************************************************************
@@ -168,9 +169,9 @@ TABDATFile::~TABDATFile()
 
 int TABDATFile::Open(const char *pszFname, const char* pszAccess, TABTableType eTableType)
 {
-    if( EQUALN(pszAccess, "r", 1) )
+    if( STARTS_WITH_CI(pszAccess, "r") )
         return Open(pszFname, TABRead, eTableType);
-    else if( EQUALN(pszAccess, "w", 1) )
+    else if( STARTS_WITH_CI(pszAccess, "w") )
         return Open(pszFname, TABWrite, eTableType);
     else
     {
@@ -253,7 +254,7 @@ int TABDATFile::Open(const char *pszFname, TABAccess eAccess,
          * m_poHeaderBlock will be reused later to read field definition
          *-----------------------------------------------------------*/
         m_poHeaderBlock = new TABRawBinBlock(m_eAccessMode, TRUE);
-        m_poHeaderBlock->ReadFromFile(m_fp, 0, 32);
+        CPL_IGNORE_RET_VAL(m_poHeaderBlock->ReadFromFile(m_fp, 0, 32));
 
         m_poHeaderBlock->ReadByte();       // Table type ??? 0x03
         m_poHeaderBlock->ReadByte();       // Last update year
@@ -263,14 +264,23 @@ int TABDATFile::Open(const char *pszFname, TABAccess eAccess,
         m_numRecords      = m_poHeaderBlock->ReadInt32();
         m_nFirstRecordPtr = m_poHeaderBlock->ReadInt16();
         m_nRecordSize     = m_poHeaderBlock->ReadInt16();
-
+        if( m_nFirstRecordPtr < 32 || m_nRecordSize <= 0 || m_numRecords < 0 )
+        {
+            VSIFCloseL(m_fp);
+            m_fp = NULL;
+            CPLFree(m_pszFname);
+            m_pszFname = NULL;
+            delete m_poHeaderBlock;
+            m_poHeaderBlock = NULL;
+            return -1;
+        }
         m_numFields = m_nFirstRecordPtr/32 - 1;
 
         /*-------------------------------------------------------------
          * Read the field definitions
          * First 32 bytes field definition starts at byte 32 in file
          *------------------------------------------------------------*/
-        m_pasFieldDef = (TABDATFieldDef*)CPLCalloc(m_numFields, 
+        m_pasFieldDef = (TABDATFieldDef*)CPLCalloc(m_numFields,
                                                    sizeof(TABDATFieldDef));
 
         for(i=0; i<m_numFields; i++)
@@ -288,18 +298,19 @@ int TABDATFile::Open(const char *pszFname, TABAccess eAccess,
         }
 
         /*-------------------------------------------------------------
-         * Establish a good record block size to use based on record size, and 
+         * Establish a good record block size to use based on record size, and
          * then create m_poRecordBlock
          * Record block size has to be a multiple of record size.
          *------------------------------------------------------------*/
         m_nBlockSize = ((1024/m_nRecordSize)+1)*m_nRecordSize;
-        m_nBlockSize = MIN(m_nBlockSize, (m_numRecords*m_nRecordSize));
+        if( m_numRecords < INT_MAX / m_nRecordSize )
+            m_nBlockSize = MIN(m_nBlockSize, (m_numRecords*m_nRecordSize));
 
         CPLAssert( m_poRecordBlock == NULL );
         m_poRecordBlock = new TABRawBinBlock(m_eAccessMode, FALSE);
         m_poRecordBlock->InitNewBlock(m_fp, m_nBlockSize);
         m_poRecordBlock->SetFirstBlockPtr(m_nFirstRecordPtr);
-        
+
         m_bWriteHeaderInitialized = TRUE;
     }
     else
@@ -344,7 +355,7 @@ int TABDATFile::Close()
         SyncToDisk();
     }
 
-    // Delete all structures 
+    // Delete all structures
     if (m_poHeaderBlock)
     {
         delete m_poHeaderBlock;
@@ -392,7 +403,7 @@ int TABDATFile::SyncToDisk()
                  "SyncToDisk() can be used only with Write access.");
         return -1;
     }
-    
+
     if( !m_bUpdated && m_bWriteHeaderInitialized )
         return 0;
 
@@ -555,15 +566,15 @@ int  TABDATFile::GetNumRecords()
  * In read access, the returned block is guaranteed to contain at least one
  * full record of data, and in write access, it is at least big enough to
  * hold one full record.
- * 
+ *
  * Note that record ids are positive and start at 1.
  *
  * In Write access, CommitRecordToFile() MUST be called after the
- * data items have been written to the record, otherwise the record 
+ * data items have been written to the record, otherwise the record
  * will never make it to the file.
  *
  * Returns a reference to the TABRawBinBlock on success or NULL on error.
- * The returned pointer is a reference to a block object owned by this 
+ * The returned pointer is a reference to a block object owned by this
  * TABDATFile object and should not be freed by the caller.
  **********************************************************************/
 TABRawBinBlock *TABDATFile::GetRecordBlock(int nRecordId)
@@ -583,7 +594,7 @@ TABRawBinBlock *TABDATFile::GetRecordBlock(int nRecordId)
         /*-------------------------------------------------------------
          * Move record block pointer to the right location
          *------------------------------------------------------------*/
-        if ( m_poRecordBlock == NULL || 
+        if ( m_poRecordBlock == NULL ||
              nRecordId < 1 || nRecordId > m_numRecords ||
              m_poRecordBlock->GotoByteInFile(nFileOffset) != 0 )
         {
@@ -613,7 +624,7 @@ TABRawBinBlock *TABDATFile::GetRecordBlock(int nRecordId)
         int nFileOffset;
 
         /*-------------------------------------------------------------
-         * Before writing the first record, we must generate the file 
+         * Before writing the first record, we must generate the file
          * header.  We will also initialize class members such as record
          * size, etc. and will create m_poRecordBlock.
          *------------------------------------------------------------*/
@@ -621,7 +632,7 @@ TABRawBinBlock *TABDATFile::GetRecordBlock(int nRecordId)
         {
             WriteHeader();
         }
-        
+
         m_bUpdated = TRUE;
 
         m_numRecords = MAX(nRecordId, m_numRecords);
@@ -662,7 +673,7 @@ int  TABDATFile::CommitRecordToFile()
 
     if (m_poRecordBlock->CommitToFile() != 0)
         return -1;
-    
+
     /* If this is the end of file, write EOF character */
     if (m_bWriteEOF)
     {
@@ -671,13 +682,13 @@ int  TABDATFile::CommitRecordToFile()
         if (VSIFSeekL(m_fp, 0L, SEEK_END) == 0)
             VSIFWriteL(&cEOF, 1, 1, m_fp);
     }
-    
+
     return 0;
 }
 
 /**********************************************************************
  *                   TABDATFile::MarkAsDeleted()
- 
+ *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
 int TABDATFile::MarkAsDeleted()
@@ -695,16 +706,16 @@ int TABDATFile::MarkAsDeleted()
 
     if (m_poRecordBlock->CommitToFile() != 0)
         return -1;
-    
+
     m_bCurRecordDeletedFlag = TRUE;
     m_bUpdated = TRUE;
-    
+
     return 0;
 }
 
 /**********************************************************************
  *                   TABDATFile::MarkRecordAsExisting()
- 
+ *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
 int TABDATFile::MarkRecordAsExisting()
@@ -722,7 +733,7 @@ int TABDATFile::MarkRecordAsExisting()
 
     m_bCurRecordDeletedFlag = FALSE;
     m_bUpdated = TRUE;
-    
+
     return 0;
 }
 
@@ -730,15 +741,15 @@ int TABDATFile::MarkRecordAsExisting()
 /**********************************************************************
  *                   TABDATFile::ValidateFieldInfoFromTAB()
  *
- * Check that the value read from the .TAB file by the caller are 
+ * Check that the value read from the .TAB file by the caller are
  * consistent with what is found in the .DAT header.
  *
  * Note that field ids are positive and start at 0.
  *
- * We have to use this function when opening a file for reading since 
+ * We have to use this function when opening a file for reading since
  * the .DAT file does not contain the full field types information...
  * a .DAT file is actually a .DBF file in which the .DBF types are
- * handled in a special way... type 'C' fields are used to store binary 
+ * handled in a special way... type 'C' fields are used to store binary
  * values for most MapInfo types.
  *
  * For TABTableDBF, we actually have no validation to do since all types
@@ -771,7 +782,7 @@ int  TABDATFile::ValidateFieldInfoFromTAB(int iField, const char *pszName,
      * With TABTableDBF, no need to validate field type since all
      * fields are stored as strings internally.
      *----------------------------------------------------------------*/
-    if ((m_eTableType == TABTableNative && 
+    if ((m_eTableType == TABTableNative &&
          ((eType == TABFChar && (m_pasFieldDef[i].cType != 'C' ||
                                 m_pasFieldDef[i].byLength != nWidth )) ||
           (eType == TABFDecimal && (m_pasFieldDef[i].cType != 'N' ||
@@ -796,7 +807,7 @@ int  TABDATFile::ValidateFieldInfoFromTAB(int iField, const char *pszName,
                  "Definition of field %d (%s) from .TAB file does not match "
                  "what is found in %s (name=%s, type=%c, width=%d, prec=%d)",
                  iField+1, pszName, m_pszFname,
-                 m_pasFieldDef[i].szName, m_pasFieldDef[i].cType, 
+                 m_pasFieldDef[i].szName, m_pasFieldDef[i].cType,
                  m_pasFieldDef[i].byLength, m_pasFieldDef[i].byDecimals);
         return -1;
     }
@@ -881,7 +892,7 @@ static int TABDATFileSetFieldDefinition(TABDATFieldDef* psFieldDef,
                  "Unsupported field type for field `%s'", pszName);
         return -1;
     }
-    
+
     return 0;
 }
 
@@ -913,7 +924,7 @@ int  TABDATFile::AddField(const char *pszName, TABFieldType eType,
         m_numFields = 0;
 
     m_numFields++;
-    m_pasFieldDef = (TABDATFieldDef*)CPLRealloc(m_pasFieldDef, 
+    m_pasFieldDef = (TABDATFieldDef*)CPLRealloc(m_pasFieldDef,
                                           m_numFields*sizeof(TABDATFieldDef));
     memcpy(&m_pasFieldDef[m_numFields-1], &sFieldDef, sizeof(sFieldDef));
 
@@ -1017,7 +1028,7 @@ int TABDATFile::DeleteField( int iField )
                  "Operation not supported on read-only files or on non-native table.");
         return -1;
     }
-    
+
     if( iField < 0 || iField >= m_numFields )
     {
         CPLError(CE_Failure, CPLE_IllegalArg, "Invalid field index: %d", iField);
@@ -1149,21 +1160,21 @@ int TABDATFile::ReorderFields( int* panMap )
                  "Operation not supported on read-only files or on non-native table.");
         return -1;
     }
-    
+
     if( m_numFields == 0)
         return 0;
 
     OGRErr eErr = OGRCheckPermutation(panMap, m_numFields);
     if (eErr != OGRERR_NONE)
         return -1;
-    
+
     /* If no records have been written, then just reorder the field */
     /* definition array */
     if( m_numRecords <= 0 )
     {
         TABDATFieldDef* pasFieldDefTmp = (TABDATFieldDef*)CPLMalloc(m_numFields*sizeof(TABDATFieldDef));
         memcpy(pasFieldDefTmp, m_pasFieldDef, m_numFields*sizeof(TABDATFieldDef));
-        for(int i = 0; i < m_numFields; i++) 
+        for(int i = 0; i < m_numFields; i++)
         {
             memcpy(m_pasFieldDef + i, pasFieldDefTmp + panMap[i],
                    sizeof(TABDATFieldDef));
@@ -1239,7 +1250,7 @@ int TABDATFile::ReorderFields( int* panMap )
                     return -1;
                 }
             }
-            
+
             oTempFile.CommitRecordToFile();
         }
     }
@@ -1310,7 +1321,7 @@ int TABDATFile::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nF
         if( IMapInfoFile::GetTABType( poNewFieldDefn, &eTABTypeDummy, &nWidth ) < 0 )
             return -1;
     }
-    
+
     if ((nFlags & ALTER_TYPE_FLAG) &&
         eTABType != m_pasFieldDef[iField].eTABType)
     {
@@ -1425,7 +1436,7 @@ int TABDATFile::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nF
         }
         else
         {
-            if( nRecordSizeBefore > 0 && 
+            if( nRecordSizeBefore > 0 &&
                 (m_poRecordBlock->ReadBytes(nRecordSizeBefore, pabyRecord) != 0 ||
                  oTempFile.m_poRecordBlock->WriteBytes(nRecordSizeBefore, pabyRecord) != 0) )
             {
@@ -1475,7 +1486,7 @@ int TABDATFile::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nF
             }
 
             if( oTempFile.m_poRecordBlock->WriteBytes(sFieldDef.byLength, (GByte*)pabyNewField) != 0 ||
-                (nRecordSizeAfter > 0 && 
+                (nRecordSizeAfter > 0 &&
                 (m_poRecordBlock->ReadBytes(nRecordSizeAfter, pabyRecord) != 0 ||
                  oTempFile.m_poRecordBlock->WriteBytes(nRecordSizeAfter, pabyRecord) != 0)) )
             {
@@ -1576,9 +1587,9 @@ int   TABDATFile::GetFieldPrecision(int nFieldId)
 /**********************************************************************
  *                   TABDATFile::ReadCharField()
  *
- * Read the character field value at the current position in the data 
+ * Read the character field value at the current position in the data
  * block.
- * 
+ *
  * Use GetRecordBlock() to position the data block to the beginning of
  * a record before attempting to read values.
  *
@@ -1590,7 +1601,7 @@ int   TABDATFile::GetFieldPrecision(int nFieldId)
  **********************************************************************/
 const char *TABDATFile::ReadCharField(int nWidth)
 {
-    // If current record has been deleted, then return an acceptable 
+    // If current record has been deleted, then return an acceptable
     // default value.
     if (m_bCurRecordDeletedFlag)
         return "";
@@ -1618,7 +1629,7 @@ const char *TABDATFile::ReadCharField(int nWidth)
     // with spaces... get rid of the trailing spaces.
     if (m_eTableType == TABTableDBF)
     {
-        int nLen = strlen(m_szBuffer)-1;
+        int nLen = static_cast<int>(strlen(m_szBuffer))-1;
         while(nLen>=0 && m_szBuffer[nLen] == ' ')
             m_szBuffer[nLen--] = '\0';
     }
@@ -1629,16 +1640,16 @@ const char *TABDATFile::ReadCharField(int nWidth)
 /**********************************************************************
  *                   TABDATFile::ReadIntegerField()
  *
- * Read the integer field value at the current position in the data 
+ * Read the integer field value at the current position in the data
  * block.
- * 
+ *
  * Note: nWidth is used only with TABTableDBF types.
  *
  * CPLError() will have been called if something fails.
  **********************************************************************/
 GInt32 TABDATFile::ReadIntegerField(int nWidth)
 {
-    // If current record has been deleted, then return an acceptable 
+    // If current record has been deleted, then return an acceptable
     // default value.
     if (m_bCurRecordDeletedFlag)
         return 0;
@@ -1659,16 +1670,16 @@ GInt32 TABDATFile::ReadIntegerField(int nWidth)
 /**********************************************************************
  *                   TABDATFile::ReadSmallIntField()
  *
- * Read the smallint field value at the current position in the data 
+ * Read the smallint field value at the current position in the data
  * block.
- * 
+ *
  * Note: nWidth is used only with TABTableDBF types.
  *
  * CPLError() will have been called if something fails.
  **********************************************************************/
 GInt16 TABDATFile::ReadSmallIntField(int nWidth)
 {
-    // If current record has been deleted, then return an acceptable 
+    // If current record has been deleted, then return an acceptable
     // default value.
     if (m_bCurRecordDeletedFlag)
         return 0;
@@ -1689,16 +1700,16 @@ GInt16 TABDATFile::ReadSmallIntField(int nWidth)
 /**********************************************************************
  *                   TABDATFile::ReadFloatField()
  *
- * Read the float field value at the current position in the data 
+ * Read the float field value at the current position in the data
  * block.
- * 
+ *
  * Note: nWidth is used only with TABTableDBF types.
  *
  * CPLError() will have been called if something fails.
  **********************************************************************/
 double TABDATFile::ReadFloatField(int nWidth)
 {
-    // If current record has been deleted, then return an acceptable 
+    // If current record has been deleted, then return an acceptable
     // default value.
     if (m_bCurRecordDeletedFlag)
         return 0.0;
@@ -1719,12 +1730,12 @@ double TABDATFile::ReadFloatField(int nWidth)
 /**********************************************************************
  *                   TABDATFile::ReadLogicalField()
  *
- * Read the logical field value at the current position in the data 
+ * Read the logical field value at the current position in the data
  * block.
  *
- * The file contains either 0 or 1, and we return a string with 
+ * The file contains either 0 or 1, and we return a string with
  * "F" (false) or "T" (true)
- * 
+ *
  * Note: nWidth is used only with TABTableDBF types.
  *
  * CPLError() will have been called if something fails.
@@ -1733,7 +1744,7 @@ const char *TABDATFile::ReadLogicalField(int nWidth)
 {
     GByte bValue;
 
-    // If current record has been deleted, then return an acceptable 
+    // If current record has been deleted, then return an acceptable
     // default value.
     if (m_bCurRecordDeletedFlag)
         return "F";
@@ -1762,14 +1773,14 @@ const char *TABDATFile::ReadLogicalField(int nWidth)
 /**********************************************************************
  *                   TABDATFile::ReadDateField()
  *
- * Read the logical field value at the current position in the data 
+ * Read the logical field value at the current position in the data
  * block.
  *
  * A date field is a 4 bytes binary value in which the first byte is
  * the day, followed by 1 byte for the month, and 2 bytes for the year.
  *
  * We return an 8 chars string in the format "YYYYMMDD"
- * 
+ *
  * Note: nWidth is used only with TABTableDBF types.
  *
  * Returns a reference to an internal buffer that will be valid only until
@@ -1784,14 +1795,14 @@ const char *TABDATFile::ReadDateField(int nWidth)
     if ((status = ReadDateField(nWidth, &nYear, &nMonth, &nDay)) == -1)
        return "";
 
-    sprintf(m_szBuffer, "%4.4d%2.2d%2.2d", nYear, nMonth, nDay);
-  
+    snprintf(m_szBuffer, sizeof(m_szBuffer), "%4.4d%2.2d%2.2d", nYear, nMonth, nDay);
+
     return m_szBuffer;
 }
 
 int TABDATFile::ReadDateField(int nWidth, int *nYear, int *nMonth, int *nDay)
 {
-    // If current record has been deleted, then return an acceptable 
+    // If current record has been deleted, then return an acceptable
     // default value.
     if (m_bCurRecordDeletedFlag)
         return -1;
@@ -1803,7 +1814,7 @@ int TABDATFile::ReadDateField(int nWidth, int *nYear, int *nMonth, int *nDay)
         return -1;
     }
 
-    // With .DBF files, the value should already be 
+    // With .DBF files, the value should already be
     // stored in YYYYMMDD format according to DBF specs.
     if (m_eTableType == TABTableDBF)
     {
@@ -1816,24 +1827,24 @@ int TABDATFile::ReadDateField(int nWidth, int *nYear, int *nMonth, int *nDay)
        *nMonth = m_poRecordBlock->ReadByte();
        *nDay   = m_poRecordBlock->ReadByte();
     }
-    
+
     if (CPLGetLastErrorNo() != 0 || (*nYear==0 && *nMonth==0 && *nDay==0))
        return -1;
-   
+
     return 0;
 }
 
 /**********************************************************************
  *                   TABDATFile::ReadTimeField()
  *
- * Read the Time field value at the current position in the data 
+ * Read the Time field value at the current position in the data
  * block.
  *
  * A time field is a 4 bytes binary value which represents the number
  * of milliseconds since midnight.
  *
  * We return a 9 char string in the format "HHMMSSMMM"
- * 
+ *
  * Note: nWidth is used only with TABTableDBF types.
  *
  * Returns a reference to an internal buffer that will be valid only until
@@ -1848,16 +1859,16 @@ const char *TABDATFile::ReadTimeField(int nWidth)
     if ((status = ReadTimeField(nWidth, &nHour, &nMinute, &nSecond, &nMS)) == -1)
        return "";
 
-    sprintf(m_szBuffer, "%2.2d%2.2d%2.2d%3.3d", nHour, nMinute, nSecond, nMS);
-    
+    snprintf(m_szBuffer, sizeof(m_szBuffer), "%2.2d%2.2d%2.2d%3.3d", nHour, nMinute, nSecond, nMS);
+
     return m_szBuffer;
 }
 
-int TABDATFile::ReadTimeField(int nWidth, int *nHour, int *nMinute, 
+int TABDATFile::ReadTimeField(int nWidth, int *nHour, int *nMinute,
                               int *nSecond, int *nMS)
 {
     GInt32 nS = 0;
-    // If current record has been deleted, then return an acceptable 
+    // If current record has been deleted, then return an acceptable
     // default value.
     if (m_bCurRecordDeletedFlag)
         return -1;
@@ -1869,7 +1880,7 @@ int TABDATFile::ReadTimeField(int nWidth, int *nHour, int *nMinute,
         return -1;
     }
 
-    // With .DBF files, the value should already be stored in 
+    // With .DBF files, the value should already be stored in
     // HHMMSSMMM format according to DBF specs.
     if (m_eTableType == TABTableDBF)
     {
@@ -1897,7 +1908,7 @@ int TABDATFile::ReadTimeField(int nWidth, int *nHour, int *nMinute,
 /**********************************************************************
  *                   TABDATFile::ReadDateTimeField()
  *
- * Read the DateTime field value at the current position in the data 
+ * Read the DateTime field value at the current position in the data
  * block.
  *
  * A datetime field is an 8 bytes binary value in which the first byte is
@@ -1905,7 +1916,7 @@ int TABDATFile::ReadTimeField(int nWidth, int *nHour, int *nMinute,
  * this is 4 bytes which represents the number of milliseconds since midnight.
  *
  * We return an 17 chars string in the format "YYYYMMDDhhmmssmmm"
- * 
+ *
  * Note: nWidth is used only with TABTableDBF types.
  *
  * Returns a reference to an internal buffer that will be valid only until
@@ -1916,12 +1927,12 @@ const char *TABDATFile::ReadDateTimeField(int nWidth)
 {
     int nDay, nMonth, nYear, nHour, nMinute, nSecond, nMS, status;
     nDay = nMonth = nYear = nHour = nMinute = nSecond = nMS = 0;
-    
-    if ((status = ReadDateTimeField(nWidth, &nYear, &nMonth, &nDay, &nHour, 
+
+    if ((status = ReadDateTimeField(nWidth, &nYear, &nMonth, &nDay, &nHour,
                                     &nMinute, &nSecond, &nMS)) == -1)
        return "";
 
-    sprintf(m_szBuffer, "%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d%3.3d", 
+    snprintf(m_szBuffer, sizeof(m_szBuffer), "%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d%3.3d",
             nYear, nMonth, nDay, nHour, nMinute, nSecond, nMS);
 
     return m_szBuffer;
@@ -1931,7 +1942,7 @@ int TABDATFile::ReadDateTimeField(int nWidth, int *nYear, int *nMonth, int *nDay
                                  int *nHour, int *nMinute, int *nSecond, int *nMS)
 {
     GInt32 nS = 0;
-    // If current record has been deleted, then return an acceptable 
+    // If current record has been deleted, then return an acceptable
     // default value.
     if (m_bCurRecordDeletedFlag)
         return -1;
@@ -1943,7 +1954,7 @@ int TABDATFile::ReadDateTimeField(int nWidth, int *nYear, int *nMonth, int *nDay
         return -1;
     }
 
-    // With .DBF files, the value should already be stored in 
+    // With .DBF files, the value should already be stored in
     // YYYYMMDD format according to DBF specs.
     if (m_eTableType == TABTableDBF)
     {
@@ -1952,14 +1963,14 @@ int TABDATFile::ReadDateTimeField(int nWidth, int *nYear, int *nMonth, int *nDay
               nYear, nMonth, nDay, nHour, nMinute, nSecond, nMS);
     }
     else
-    { 
+    {
        *nYear  = m_poRecordBlock->ReadInt16();
        *nMonth = m_poRecordBlock->ReadByte();
        *nDay   = m_poRecordBlock->ReadByte();
        nS      = m_poRecordBlock->ReadInt32();
     }
 
-    if (CPLGetLastErrorNo() != 0 || 
+    if (CPLGetLastErrorNo() != 0 ||
         (*nYear==0 && *nMonth==0 && *nDay==0) || (nS>86400000))
         return -1;
 
@@ -1974,7 +1985,7 @@ int TABDATFile::ReadDateTimeField(int nWidth, int *nYear, int *nMonth, int *nDay
 /**********************************************************************
  *                   TABDATFile::ReadDecimalField()
  *
- * Read the decimal field value at the current position in the data 
+ * Read the decimal field value at the current position in the data
  * block.
  *
  * A decimal field is a floating point value with a fixed number of digits
@@ -1983,14 +1994,14 @@ int TABDATFile::ReadDateTimeField(int nWidth, int *nYear, int *nMonth, int *nDay
  * nWidth is the field length, as defined in the .DAT header.
  *
  * We return the value as a binary double.
- * 
+ *
  * CPLError() will have been called if something fails.
  **********************************************************************/
 double TABDATFile::ReadDecimalField(int nWidth)
 {
     const char *pszVal;
 
-    // If current record has been deleted, then return an acceptable 
+    // If current record has been deleted, then return an acceptable
     // default value.
     if (m_bCurRecordDeletedFlag)
         return 0.0;
@@ -2004,9 +2015,9 @@ double TABDATFile::ReadDecimalField(int nWidth)
 /**********************************************************************
  *                   TABDATFile::WriteCharField()
  *
- * Write the character field value at the current position in the data 
+ * Write the character field value at the current position in the data
  * block.
- * 
+ *
  * Use GetRecordBlock() to position the data block to the beginning of
  * a record before attempting to write values.
  *
@@ -2031,14 +2042,14 @@ int TABDATFile::WriteCharField(const char *pszStr, int nWidth,
                  "Illegal width for a char field: %d", nWidth);
         return -1;
     }
-    
+
     //
     // Write the buffer after making sure that we don't try to read
     // past the end of the source buffer.  The rest of the field will
     // be padded with zeros if source string is shorter than specified
     // field width.
     //
-    int nLen = strlen(pszStr);
+    int nLen = static_cast<int>(strlen(pszStr));
     nLen = MIN(nLen, nWidth);
 
     if ((nLen>0 && m_poRecordBlock->WriteBytes(nLen, (GByte*)pszStr) != 0) ||
@@ -2059,9 +2070,9 @@ int TABDATFile::WriteCharField(const char *pszStr, int nWidth,
 /**********************************************************************
  *                   TABDATFile::WriteIntegerField()
  *
- * Write the integer field value at the current position in the data 
+ * Write the integer field value at the current position in the data
  * block.
- * 
+ *
  * CPLError() will have been called if something fails.
  **********************************************************************/
 int TABDATFile::WriteIntegerField(GInt32 nValue,
@@ -2088,9 +2099,9 @@ int TABDATFile::WriteIntegerField(GInt32 nValue,
 /**********************************************************************
  *                   TABDATFile::WriteSmallIntField()
  *
- * Write the smallint field value at the current position in the data 
+ * Write the smallint field value at the current position in the data
  * block.
- * 
+ *
  * CPLError() will have been called if something fails.
  **********************************************************************/
 int TABDATFile::WriteSmallIntField(GInt16 nValue,
@@ -2117,9 +2128,9 @@ int TABDATFile::WriteSmallIntField(GInt16 nValue,
 /**********************************************************************
  *                   TABDATFile::WriteFloatField()
  *
- * Write the float field value at the current position in the data 
+ * Write the float field value at the current position in the data
  * block.
- * 
+ *
  * CPLError() will have been called if something fails.
  **********************************************************************/
 int TABDATFile::WriteFloatField(double dValue,
@@ -2146,12 +2157,12 @@ int TABDATFile::WriteFloatField(double dValue,
 /**********************************************************************
  *                   TABDATFile::WriteLogicalField()
  *
- * Write the logical field value at the current position in the data 
+ * Write the logical field value at the current position in the data
  * block.
  *
  * The value written to the file is either 0 or 1, but this function
  * takes as input a string with "F" (false) or "T" (true)
- * 
+ *
  * CPLError() will have been called if something fails.
  **********************************************************************/
 int TABDATFile::WriteLogicalField(const char *pszValue,
@@ -2166,7 +2177,7 @@ int TABDATFile::WriteLogicalField(const char *pszValue,
         return -1;
     }
 
-    if (EQUALN(pszValue, "T", 1))
+    if (STARTS_WITH_CI(pszValue, "T"))
         bValue = 1;
     else
         bValue = 0;
@@ -2185,7 +2196,7 @@ int TABDATFile::WriteLogicalField(const char *pszValue,
 /**********************************************************************
  *                   TABDATFile::WriteDateField()
  *
- * Write the date field value at the current position in the data 
+ * Write the date field value at the current position in the data
  * block.
  *
  * A date field is a 4 bytes binary value in which the first byte is
@@ -2193,7 +2204,7 @@ int TABDATFile::WriteLogicalField(const char *pszValue,
  *
  * The expected input is a 10 chars string in the format "YYYY/MM/DD"
  * or "DD/MM/YYYY" or "YYYYMMDD"
- * 
+ *
  * Returns 0 on success, or -1 if the operation failed, in which case
  * CPLError() will have been called.
  **********************************************************************/
@@ -2212,7 +2223,7 @@ int TABDATFile::WriteDateField(const char *pszValue,
      * Try to automagically detect date format, one of:
      * "YYYY/MM/DD", "DD/MM/YYYY", or "YYYYMMDD"
      *----------------------------------------------------------------*/
-    
+
     if (strlen(pszValue) == 8)
     {
         /*-------------------------------------------------------------
@@ -2227,7 +2238,7 @@ int TABDATFile::WriteDateField(const char *pszValue,
         nYear = atoi(szBuf);
     }
     else if (strlen(pszValue) == 10 &&
-             (papszTok = CSLTokenizeStringComplex(pszValue, "/", 
+             (papszTok = CSLTokenizeStringComplex(pszValue, "/",
                                                   FALSE, FALSE)) != NULL &&
              CSLCount(papszTok) == 3 &&
              (strlen(papszTok[0]) == 4 || strlen(papszTok[2]) == 4) )
@@ -2275,7 +2286,7 @@ int TABDATFile::WriteDateField(int nYear, int nMonth, int nDay,
                  "Can't write field value: GetRecordBlock() has not been called.");
         return -1;
     }
-    
+
     m_poRecordBlock->WriteInt16((GInt16)nYear);
     m_poRecordBlock->WriteByte((GByte)nMonth);
     m_poRecordBlock->WriteByte((GByte)nDay);
@@ -2298,7 +2309,7 @@ int TABDATFile::WriteDateField(int nYear, int nMonth, int nDay,
 /**********************************************************************
  *                   TABDATFile::WriteTimeField()
  *
- * Write the date field value at the current position in the data 
+ * Write the date field value at the current position in the data
  * block.
  *
  * A time field is a 4 byte binary value which represents the number
@@ -2306,7 +2317,7 @@ int TABDATFile::WriteDateField(int nYear, int nMonth, int nDay,
  *
  * The expected input is a 10 chars string in the format "HH:MM:SS"
  * or "HHMMSSmmm"
- * 
+ *
  * Returns 0 on success, or -1 if the operation failed, in which case
  * CPLError() will have been called.
  **********************************************************************/
@@ -2325,7 +2336,7 @@ int TABDATFile::WriteTimeField(const char *pszValue,
      * Try to automagically detect time format, one of:
      * "HH:MM:SS", or "HHMMSSmmm"
      *----------------------------------------------------------------*/
-    
+
     if (strlen(pszValue) == 8)
     {
         /*-------------------------------------------------------------
@@ -2380,7 +2391,7 @@ int TABDATFile::WriteTimeField(const char *pszValue,
     return WriteTimeField(nHour, nMin, nSec, nMS, poINDFile, nIndexNo);
 }
 
-int TABDATFile::WriteTimeField(int nHour, int nMinute, int nSecond, int nMS, 
+int TABDATFile::WriteTimeField(int nHour, int nMinute, int nSecond, int nMS,
                                TABINDFile *poINDFile, int nIndexNo)
 {
     GInt32 nS = -1;
@@ -2391,12 +2402,12 @@ int TABDATFile::WriteTimeField(int nHour, int nMinute, int nSecond, int nMS,
             "Can't write field value: GetRecordBlock() has not been called.");
         return -1;
     }
-    
+
     nS = (nHour*3600+nMinute*60+nSecond)*1000+nMS;
     if (nS < 0)
        nS = -1;
     m_poRecordBlock->WriteInt32(nS);
-    
+
     if (CPLGetLastErrorNo() != 0)
         return -1;
 
@@ -2414,18 +2425,18 @@ int TABDATFile::WriteTimeField(int nHour, int nMinute, int nSecond, int nMS,
 /**********************************************************************
  *                   TABDATFile::WriteDateTimeField()
  *
- * Write the DateTime field value at the current position in the data 
+ * Write the DateTime field value at the current position in the data
  * block.
  *
  * A datetime field is a 8 bytes binary value in which the first byte is
  * the day, followe
 d by 1 byte for the month, and 2 bytes for the year.
- * After this the time value is stored as a 4 byte integer 
+ * After this the time value is stored as a 4 byte integer
  * (milliseconds since midnight)
  *
  * The expected input is a 10 chars string in the format "YYYY/MM/DD HH:MM:SS"
  * or "DD/MM/YYYY HH:MM:SS" or "YYYYMMDDhhmmssmmm"
- * 
+ *
  * Returns 0 on success, or -1 if the operation failed, in which case
  * CPLError() will have been called.
  **********************************************************************/
@@ -2444,7 +2455,7 @@ int TABDATFile::WriteDateTimeField(const char *pszValue,
      * Try to automagically detect date format, one of:
      * "YYYY/MM/DD HH:MM:SS", "DD/MM/YYYY HH:MM:SS", or "YYYYMMDDhhmmssmmm"
      *----------------------------------------------------------------*/
-    
+
     if (strlen(pszValue) == 17)
     {
         /*-------------------------------------------------------------
@@ -2467,7 +2478,7 @@ int TABDATFile::WriteDateTimeField(const char *pszValue,
         nYear = atoi(szBuf);
     }
     else if (strlen(pszValue) == 19 &&
-             (papszTok = CSLTokenizeStringComplex(pszValue, "/ :", 
+             (papszTok = CSLTokenizeStringComplex(pszValue, "/ :",
                                                   FALSE, FALSE)) != NULL &&
              CSLCount(papszTok) == 6 &&
              (strlen(papszTok[0]) == 4 || strlen(papszTok[2]) == 4) )
@@ -2517,7 +2528,7 @@ int TABDATFile::WriteDateTimeField(const char *pszValue,
                               poINDFile, nIndexNo);
 }
 
-int TABDATFile::WriteDateTimeField(int nYear, int nMonth, int nDay, 
+int TABDATFile::WriteDateTimeField(int nYear, int nMonth, int nDay,
                                    int nHour, int nMinute, int nSecond, int nMS,
                                    TABINDFile *poINDFile, int nIndexNo)
 {
@@ -2542,7 +2553,7 @@ int TABDATFile::WriteDateTimeField(int nYear, int nMonth, int nDay,
     if (poINDFile && nIndexNo > 0)
     {
         // __TODO__  (see bug #1844)
-        // Indexing on DateTime Fields not currently supported, that will 
+        // Indexing on DateTime Fields not currently supported, that will
         // require passing the 8 bytes datetime value to BuildKey() here...
         CPLAssert(FALSE);
         GByte *pKey = poINDFile->BuildKey(nIndexNo, (nYear*0x10000 +
@@ -2557,7 +2568,7 @@ int TABDATFile::WriteDateTimeField(int nYear, int nMonth, int nDay,
 /**********************************************************************
  *                   TABDATFile::WriteDecimalField()
  *
- * Write the decimal field value at the current position in the data 
+ * Write the decimal field value at the current position in the data
  * block.
  *
  * A decimal field is a floating point value with a fixed number of digits
@@ -2573,7 +2584,7 @@ int TABDATFile::WriteDecimalField(double dValue, int nWidth, int nPrec,
     char szFormat[10];
     const char *pszVal;
 
-    sprintf(szFormat, "%%%d.%df", nWidth, nPrec);
+    snprintf(szFormat, sizeof(szFormat), "%%%d.%df", nWidth, nPrec);
     pszVal = CPLSPrintf(szFormat, dValue);
     if ((int)strlen(pszVal) > nWidth)
         pszVal += strlen(pszVal) - nWidth;
@@ -2620,8 +2631,3 @@ void TABDATFile::Dump(FILE *fpOut /*=NULL*/)
 }
 
 #endif // DEBUG
-
-
-
-
-
diff --git a/ogr/ogrsf_frmts/mitab/mitab_feature.cpp b/ogr/ogrsf_frmts/mitab/mitab_feature.cpp
index 77e5d1b..0a7d64e 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_feature.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_feature.cpp
@@ -17,16 +17,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -191,7 +191,16 @@ TABFeature::TABFeature(OGRFeatureDefn *poDefnIn):
     m_nMapInfoType = TAB_GEOM_NONE;
     m_bDeletedFlag = FALSE;
 
-    SetMBR(0.0, 0.0, 0.0, 0.0);
+    m_nXMin = 0;
+    m_nYMin = 0;
+    m_nXMax = 0;
+    m_nYMax = 0;
+    m_nComprOrgX = 0;
+    m_nComprOrgY = 0;
+    m_dXMin = 0;
+    m_dYMin = 0;
+    m_dXMax = 0;
+    m_dYMax = 0;
 }
 
 /**********************************************************************
@@ -285,19 +294,19 @@ TABFeature *TABFeature::CreateFromMapInfoType(int nMapInfoType,
       case TAB_GEOM_COLLECTION:
       case TAB_GEOM_V800_COLLECTION_C:
       case TAB_GEOM_V800_COLLECTION:
-        poFeature = new TABCollection(poDefn);  
+        poFeature = new TABCollection(poDefn);
         break;
       default:
         /*-------------------------------------------------------------
          * Unsupported feature type... we still return a valid feature
          * with NONE geometry after producing a Warning.
-         * Callers can trap that case by checking CPLGetLastErrorNo() 
+         * Callers can trap that case by checking CPLGetLastErrorNo()
          * against TAB_WarningFeatureTypeNotSupported
          *------------------------------------------------------------*/
 //        poFeature = new TABDebugFeature(poDefn);
         poFeature = new TABFeature(poDefn);
 
-        CPLError(CE_Warning, TAB_WarningFeatureTypeNotSupported,
+        CPLError(CE_Warning, (CPLErrorNum)TAB_WarningFeatureTypeNotSupported,
                  "Unsupported object type %d (0x%2.2x).  Feature will be "
                  "returned with NONE geometry.",
                  nMapInfoType, nMapInfoType);
@@ -364,7 +373,7 @@ void TABFeature::CopyTABFeatureBase(TABFeature *poDestFeature)
  * It is possible to create the clone with a different OGRFeatureDefn,
  * in this case, the fields won't be copied of course.
  *
- * This method calls the generic TABFeature::CopyTABFeatureBase() and 
+ * This method calls the generic TABFeature::CopyTABFeatureBase() and
  * then copies any members specific to its own type.
  **********************************************************************/
 TABFeature *TABFeature::CloneTABFeature(OGRFeatureDefn *poNewDefn/*=NULL*/)
@@ -389,7 +398,7 @@ TABFeature *TABFeature::CloneTABFeature(OGRFeatureDefn *poNewDefn/*=NULL*/)
  *
  * Set the values for the MBR corners for this feature.
  **********************************************************************/
-void TABFeature::SetMBR(double dXMin, double dYMin, 
+void TABFeature::SetMBR(double dXMin, double dYMin,
                         double dXMax, double dYMax)
 {
     m_dXMin = MIN(dXMin, dXMax);
@@ -403,7 +412,7 @@ void TABFeature::SetMBR(double dXMin, double dYMin,
  *
  * Return the values for the MBR corners for this feature.
  **********************************************************************/
-void TABFeature::GetMBR(double &dXMin, double &dYMin, 
+void TABFeature::GetMBR(double &dXMin, double &dYMin,
                         double &dXMax, double &dYMax)
 {
     dXMin = m_dXMin;
@@ -417,7 +426,7 @@ void TABFeature::GetMBR(double &dXMin, double &dYMin,
  *
  * Set the integer coordinates values of the MBR of this feature.
  **********************************************************************/
-void TABFeature::SetIntMBR(GInt32 nXMin, GInt32 nYMin, 
+void TABFeature::SetIntMBR(GInt32 nXMin, GInt32 nYMin,
                            GInt32 nXMax, GInt32 nYMax)
 {
     m_nXMin = nXMin;
@@ -431,7 +440,7 @@ void TABFeature::SetIntMBR(GInt32 nXMin, GInt32 nYMin,
  *
  * Return the integer coordinates values of the MBR of this feature.
  **********************************************************************/
-void TABFeature::GetIntMBR(GInt32 &nXMin, GInt32 &nYMin, 
+void TABFeature::GetIntMBR(GInt32 &nXMin, GInt32 &nYMin,
                            GInt32 &nXMax, GInt32 &nYMax)
 {
     nXMin = m_nXMin;
@@ -443,11 +452,11 @@ void TABFeature::GetIntMBR(GInt32 &nXMin, GInt32 &nYMin,
 /**********************************************************************
  *                   TABFeature::ReadRecordFromDATFile()
  *
- * Fill the fields part of the feature from the contents of the 
+ * Fill the fields part of the feature from the contents of the
  * table record pointed to by poDATFile.
  *
  * It is assumed that poDATFile currently points to the beginning of
- * the table record and that this feature's OGRFeatureDefn has been 
+ * the table record and that this feature's OGRFeatureDefn has been
  * properly initialized for this table.
  **********************************************************************/
 int TABFeature::ReadRecordFromDATFile(TABDATFile *poDATFile)
@@ -547,7 +556,7 @@ int TABFeature::ReadRecordFromDATFile(TABDATFile *poDATFile)
             CPLError(CE_Failure, CPLE_AssertionFailed,
                      "Unsupported field type!");
         }
-        
+
     }
 
     return 0;
@@ -559,7 +568,7 @@ int TABFeature::ReadRecordFromDATFile(TABDATFile *poDATFile)
  * Write the attribute part of the feature to the .DAT file.
  *
  * It is assumed that poDATFile currently points to the beginning of
- * the table record and that this feature's OGRFeatureDefn has been 
+ * the table record and that this feature's OGRFeatureDefn has been
  * properly initialized for this table.
  *
  * Returns 0 on success, -1 on error.
@@ -575,7 +584,6 @@ int TABFeature::WriteRecordToDATFile(TABDATFile *poDATFile,
 #endif
 
     CPLAssert(poDATFile);
-    CPLAssert(panIndexNo || GetDefnRef()->GetFieldCount() == 0);
 
     numFields = poDATFile->GetNumFields();
 
@@ -586,11 +594,12 @@ int TABFeature::WriteRecordToDATFile(TABDATFile *poDATFile,
         // Hack for "extra" introduced field.
         if( iField >= GetDefnRef()->GetFieldCount() )
         {
-            CPLAssert( poDATFile->GetFieldType(iField) == TABFInteger 
+            CPLAssert( poDATFile->GetFieldType(iField) == TABFInteger
                        && iField == 0 );
             nStatus = poDATFile->WriteIntegerField( (int)GetFID(), poINDFile, 0 );
             continue;
         }
+        CPLAssert(panIndexNo != NULL);
 
         switch(poDATFile->GetFieldType(iField))
         {
@@ -653,7 +662,7 @@ int TABFeature::WriteRecordToDATFile(TABDATFile *poDATFile,
              nStatus = poDATFile->WriteTimeField(nHour, nMin, (int)fSec,
                                                  OGR_GET_MS(fSec),
                                                  poINDFile, panIndexNo[iField]);
-             
+
 #else
              nStatus = poDATFile->WriteTimeField(GetFieldAsString(iField),
                                                  poINDFile, panIndexNo[iField]);
@@ -672,7 +681,7 @@ int TABFeature::WriteRecordToDATFile(TABDATFile *poDATFile,
                  fSec = 0;
              }
 
-             nStatus = poDATFile->WriteDateTimeField(nYear, nMon, nDay, 
+             nStatus = poDATFile->WriteDateTimeField(nYear, nMon, nDay,
                                                      nHour, nMin, (int)fSec,
                                                      OGR_GET_MS(fSec),
                                                      poINDFile, panIndexNo[iField]);
@@ -707,7 +716,7 @@ int TABFeature::WriteRecordToDATFile(TABDATFile *poDATFile,
  *
  * bCoordBlockDataOnly=TRUE is used when this method is called to copy only
  * the CoordBlock data during splitting of object blocks. In this case we
- * need to process only the information related to the CoordBlock. One 
+ * need to process only the information related to the CoordBlock. One
  * important thing to avoid is reading/writing pen/brush/symbol definitions
  * as that would screw up their ref counters.
  *
@@ -717,13 +726,13 @@ int TABFeature::WriteRecordToDATFile(TABDATFile *poDATFile,
  *
  * The current implementation does nothing since instances of TABFeature
  * objects contain no geometry (i.e. TAB_GEOM_NONE).
- * 
+ *
  * Returns 0 on success, -1 on error, in which case CPLError() will have
  * been called.
  **********************************************************************/
 int TABFeature::ReadGeometryFromMAPFile(TABMAPFile * /*poMapFile*/,
                                         TABMAPObjHdr * /*poObjHdr*/,
-                                        GBool /*bCoordBlockDataOnly=FALSE*/, 
+                                        GBool /*bCoordBlockDataOnly=FALSE*/,
                                         TABMAPCoordBlock ** /*ppoCoordBlock=NULL*/)
 {
     /*-----------------------------------------------------------------
@@ -775,10 +784,10 @@ int TABFeature::UpdateMBR(TABMAPFile * poMapFile /*=NULL*/)
  *
  * Checks the feature envelope to establish if the feature should be
  * written using Compressed coordinates or not and adjust m_nMapInfoType
- * accordingly. Calling this method also sets (initializes) m_nXMin, m_nYMin, 
+ * accordingly. Calling this method also sets (initializes) m_nXMin, m_nYMin,
  * m_nXMax, m_nYMax
  *
- * This function should be used only by the ValidateMapInfoType() 
+ * This function should be used only by the ValidateMapInfoType()
  * implementations.
  *
  * Returns TRUE if coord. should be compressed, FALSE otherwise
@@ -817,14 +826,14 @@ GBool TABFeature::ValidateCoordType(TABMAPFile * poMapFile)
 /**********************************************************************
  *                   TABFeature::ForceCoordTypeAndOrigin()
  *
- * This function is used by TABCollection::ValidateMapInfoType() to force 
- * the coord type and compressed origin of all members of a collection 
- * to be the same. (A replacement for ValidateCoordType() for this 
+ * This function is used by TABCollection::ValidateMapInfoType() to force
+ * the coord type and compressed origin of all members of a collection
+ * to be the same. (A replacement for ValidateCoordType() for this
  * specific case)
  **********************************************************************/
 void TABFeature::ForceCoordTypeAndOrigin(TABGeomType nMapInfoType, GBool bCompr,
                                          GInt32 nComprOrgX, GInt32 nComprOrgY,
-                                         GInt32 nXMin, GInt32 nYMin, 
+                                         GInt32 nXMin, GInt32 nYMin,
                                          GInt32 nXMax, GInt32 nYMax)
 {
     /*-------------------------------------------------------------
@@ -859,7 +868,7 @@ void TABFeature::ForceCoordTypeAndOrigin(TABGeomType nMapInfoType, GBool bCompr,
  *
  * bCoordBlockDataOnly=TRUE is used when this method is called to copy only
  * the CoordBlock data during splitting of object blocks. In this case we
- * need to process only the information related to the CoordBlock. One 
+ * need to process only the information related to the CoordBlock. One
  * important thing to avoid is reading/writing pen/brush/symbol definitions
  * as that would screw up their ref counters.
  *
@@ -869,13 +878,13 @@ void TABFeature::ForceCoordTypeAndOrigin(TABGeomType nMapInfoType, GBool bCompr,
  *
  * The current implementation does nothing since instances of TABFeature
  * objects contain no geometry (i.e. TAB_GEOM_NONE).
- * 
+ *
  * Returns 0 on success, -1 on error, in which case CPLError() will have
  * been called.
  **********************************************************************/
 int TABFeature::WriteGeometryToMAPFile(TABMAPFile * /* poMapFile*/,
                                        TABMAPObjHdr * /*poObjHdr*/,
-                                       GBool /*bCoordBlockDataOnly=FALSE*/, 
+                                       GBool /*bCoordBlockDataOnly=FALSE*/,
                                        TABMAPCoordBlock ** /*ppoCoordBlock=NULL*/)
 {
     /*-----------------------------------------------------------------
@@ -892,15 +901,15 @@ int TABFeature::WriteGeometryToMAPFile(TABMAPFile * /* poMapFile*/,
  **********************************************************************/
 void TABFeature::DumpMID(FILE *fpOut /*=NULL*/)
 {
-    OGRFeatureDefn      *poDefn = GetDefnRef();
+    OGRFeatureDefn      *l_poDefn = GetDefnRef();
 
     if (fpOut == NULL)
         fpOut = stdout;
 
     for( int iField = 0; iField < GetFieldCount(); iField++ )
     {
-        OGRFieldDefn    *poFDefn = poDefn->GetFieldDefn(iField);
-        
+        OGRFieldDefn    *poFDefn = l_poDefn->GetFieldDefn(iField);
+
         fprintf( fpOut, "  %s (%s) = %s\n",
                  poFDefn->GetNameRef(),
                  OGRFieldDefn::GetFieldTypeName(poFDefn->GetType()),
@@ -958,7 +967,7 @@ TABPoint::~TABPoint()
  *
  * Duplicate feature, including stuff specific to each TABFeature type.
  *
- * This method calls the generic TABFeature::CloneTABFeature() and 
+ * This method calls the generic TABFeature::CloneTABFeature() and
  * then copies any members specific to its own type.
  **********************************************************************/
 TABFeature *TABPoint::CloneTABFeature(OGRFeatureDefn *poNewDefn /*=NULL*/)
@@ -995,8 +1004,8 @@ TABGeomType TABPoint::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
     OGRGeometry *poGeom;
 
     /*-----------------------------------------------------------------
-     * Fetch and validate geometry 
-     * __TODO__ For now we always write in uncompressed format (until we 
+     * Fetch and validate geometry
+     * __TODO__ For now we always write in uncompressed format (until we
      * find that this is not correct... note that at this point the
      * decision to use compressed/uncompressed will likely be based on
      * the distance between the point and the object block center in
@@ -1045,7 +1054,7 @@ TABGeomType TABPoint::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
  **********************************************************************/
 int TABPoint::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
                                       TABMAPObjHdr *poObjHdr,
-                                      GBool bCoordBlockDataOnly /*=FALSE*/, 
+                                      GBool bCoordBlockDataOnly /*=FALSE*/,
                                       TABMAPCoordBlock ** /*ppoCoordBlock=NULL*/)
 {
     double              dX, dY;
@@ -1077,17 +1086,17 @@ int TABPoint::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     m_nSymbolDefIndex = poPointHdr->m_nSymbolId;   // Symbol index
 
     poMapFile->ReadSymbolDef(m_nSymbolDefIndex, &m_sSymbolDef);
-    
+
     /*-----------------------------------------------------------------
      * Create and fill geometry object
      *----------------------------------------------------------------*/
     poMapFile->Int2Coordsys(poPointHdr->m_nX, poPointHdr->m_nY, dX, dY);
     poGeometry = new OGRPoint(dX, dY);
-    
+
     SetGeometryDirectly(poGeometry);
 
     SetMBR(dX, dY, dX, dY);
-    SetIntMBR(poObjHdr->m_nMinX, poObjHdr->m_nMinY, 
+    SetIntMBR(poObjHdr->m_nMinX, poObjHdr->m_nMinY,
               poObjHdr->m_nMaxX, poObjHdr->m_nMaxY);
 
     return 0;
@@ -1106,7 +1115,7 @@ int TABPoint::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
  **********************************************************************/
 int TABPoint::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
                                      TABMAPObjHdr *poObjHdr,
-                                     GBool bCoordBlockDataOnly /*=FALSE*/, 
+                                     GBool bCoordBlockDataOnly /*=FALSE*/,
                                      TABMAPCoordBlock ** /*ppoCoordBlock=NULL*/)
 {
     GInt32              nX, nY;
@@ -1267,7 +1276,7 @@ void TABPoint::DumpMIF(FILE *fpOut /*=NULL*/)
     if (GetFeatureClass() == TABFCFontPoint)
     {
         TABFontPoint *poFeature = (TABFontPoint *)this;
-        fprintf(fpOut, "  m_nFontStyle     = 0x%2.2x (%d)\n", 
+        fprintf(fpOut, "  m_nFontStyle     = 0x%2.2x (%d)\n",
                 poFeature->GetFontStyleTABValue(),
                 poFeature->GetFontStyleTABValue());
 
@@ -1277,10 +1286,10 @@ void TABPoint::DumpMIF(FILE *fpOut /*=NULL*/)
     {
         TABCustomPoint *poFeature = (TABCustomPoint *)this;
 
-        fprintf(fpOut, "  m_nUnknown_      = 0x%2.2x (%d)\n", 
+        fprintf(fpOut, "  m_nUnknown_      = 0x%2.2x (%d)\n",
                 poFeature->m_nUnknown_, poFeature->m_nUnknown_);
-        fprintf(fpOut, "  m_nCustomStyle   = 0x%2.2x (%d)\n", 
-                poFeature->GetCustomSymbolStyle(), 
+        fprintf(fpOut, "  m_nCustomStyle   = 0x%2.2x (%d)\n",
+                poFeature->GetCustomSymbolStyle(),
                 poFeature->GetCustomSymbolStyle());
 
         poFeature->DumpFontDef(fpOut);
@@ -1320,7 +1329,7 @@ TABFontPoint::~TABFontPoint()
  *
  * Duplicate feature, including stuff specific to each TABFeature type.
  *
- * This method calls the generic TABFeature::CloneTABFeature() and 
+ * This method calls the generic TABFeature::CloneTABFeature() and
  * then copies any members specific to its own type.
  **********************************************************************/
 TABFeature *TABFontPoint::CloneTABFeature(OGRFeatureDefn *poNewDefn /*=NULL*/)
@@ -1328,7 +1337,7 @@ TABFeature *TABFontPoint::CloneTABFeature(OGRFeatureDefn *poNewDefn /*=NULL*/)
     /*-----------------------------------------------------------------
      * Alloc new feature and copy the base stuff
      *----------------------------------------------------------------*/
-    TABFontPoint *poNew = new TABFontPoint(poNewDefn ? poNewDefn : 
+    TABFontPoint *poNew = new TABFontPoint(poNewDefn ? poNewDefn :
                                                        GetDefnRef());
 
     CopyTABFeatureBase(poNew);
@@ -1408,9 +1417,9 @@ int TABFontPoint::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
                                poPointHdr->m_nB);
 
     /*-------------------------------------------------------------
-     * Symbol Angle, in thenths of degree.
-     * Contrary to arc start/end angles, no conversion based on 
-     * origin quadrant is required here
+     * Symbol Angle, in tenths of degree.
+     * Contrary to arc start/end angles, no conversion based on
+     * origin quadrant is required here.
      *------------------------------------------------------------*/
     m_dAngle       = poPointHdr->m_nAngle/10.0;
 
@@ -1423,11 +1432,11 @@ int TABFontPoint::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
      *----------------------------------------------------------------*/
     poMapFile->Int2Coordsys(poPointHdr->m_nX, poPointHdr->m_nY, dX, dY);
     poGeometry = new OGRPoint(dX, dY);
-    
+
     SetGeometryDirectly(poGeometry);
 
     SetMBR(dX, dY, dX, dY);
-    SetIntMBR(poObjHdr->m_nMinX, poObjHdr->m_nMinY, 
+    SetIntMBR(poObjHdr->m_nMinX, poObjHdr->m_nMinY,
               poObjHdr->m_nMaxX, poObjHdr->m_nMaxY);
 
     return 0;
@@ -1446,7 +1455,7 @@ int TABFontPoint::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
  **********************************************************************/
 int TABFontPoint::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
                                          TABMAPObjHdr *poObjHdr,
-                                         GBool bCoordBlockDataOnly /*=FALSE*/, 
+                                         GBool bCoordBlockDataOnly /*=FALSE*/,
                                          TABMAPCoordBlock ** /*ppoCoordBlock=NULL*/)
 {
     GInt32              nX, nY;
@@ -1500,9 +1509,9 @@ int TABFontPoint::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
     poPointHdr->m_nB = (GByte)COLOR_B(m_sSymbolDef.rgbColor);
 
     /*-------------------------------------------------------------
-     * Symbol Angle, in thenths of degree.
-     * Contrary to arc start/end angles, no conversion based on 
-     * origin quadrant is required here
+     * Symbol Angle, in tenths of degree.
+     * Contrary to arc start/end angles, no conversion based on
+     * origin quadrant is required here.
      *------------------------------------------------------------*/
     poPointHdr->m_nAngle = (GInt16)ROUND_INT(m_dAngle * 10.0);
 
@@ -1545,7 +1554,7 @@ void TABFontPoint::ToggleFontStyle(TABFontStyle eStyleToToggle, GBool bStyleOn)
  * The reason why we have to differentiate between the TAB and the MIF font
  * style values is that in TAB, TABFSBox is included in the style value
  * as code 0x100, but in MIF it is not included, instead it is implied by
- * the presence of the BG color in the FONT() clause (the BG color is 
+ * the presence of the BG color in the FONT() clause (the BG color is
  * present only when TABFSBox or TABFSHalo is set).
  * This also has the effect of shifting all the other style values > 0x100
  * by 1 byte.
@@ -1591,10 +1600,10 @@ const char *TABFontPoint::GetStyleString()
 {
     if (m_pszStyleString == NULL)
     {
-        /* Get the SymbolStyleString, and add the outline Color 
+        /* Get the SymbolStyleString, and add the outline Color
            (halo/border in MapInfo Symbol terminology) */
         char *pszSymbolStyleString = CPLStrdup(GetSymbolStyleString(GetSymbolAngle()));
-        int nStyleStringlen = strlen(pszSymbolStyleString);
+        int nStyleStringlen = static_cast<int>(strlen(pszSymbolStyleString));
         pszSymbolStyleString[nStyleStringlen-1] = '\0';
 
         const char *outlineColor;
@@ -1645,7 +1654,7 @@ TABCustomPoint::~TABCustomPoint()
  *
  * Duplicate feature, including stuff specific to each TABFeature type.
  *
- * This method calls the generic TABFeature::CloneTABFeature() and 
+ * This method calls the generic TABFeature::CloneTABFeature() and
  * then copies any members specific to its own type.
  **********************************************************************/
 TABFeature *TABCustomPoint::CloneTABFeature(OGRFeatureDefn *poNewDefn/*=NULL*/)
@@ -1653,7 +1662,7 @@ TABFeature *TABCustomPoint::CloneTABFeature(OGRFeatureDefn *poNewDefn/*=NULL*/)
     /*-----------------------------------------------------------------
      * Alloc new feature and copy the base stuff
      *----------------------------------------------------------------*/
-    TABCustomPoint *poNew = new TABCustomPoint(poNewDefn ? poNewDefn : 
+    TABCustomPoint *poNew = new TABCustomPoint(poNewDefn ? poNewDefn :
                                                            GetDefnRef());
 
     CopyTABFeatureBase(poNew);
@@ -1715,7 +1724,7 @@ int TABCustomPoint::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
      *----------------------------------------------------------------*/
     TABMAPObjCustomPoint *poPointHdr = (TABMAPObjCustomPoint *)poObjHdr;
 
-    m_nUnknown_    = poPointHdr->m_nUnknown_;   // ??? 
+    m_nUnknown_    = poPointHdr->m_nUnknown_;   // ???
     m_nCustomStyle = poPointHdr->m_nCustomStyle;// 0x01=Show BG,
                                                 // 0x02=Apply Color
 
@@ -1730,11 +1739,11 @@ int TABCustomPoint::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
      *----------------------------------------------------------------*/
     poMapFile->Int2Coordsys(poPointHdr->m_nX, poPointHdr->m_nY, dX, dY);
     poGeometry = new OGRPoint(dX, dY);
-    
+
     SetGeometryDirectly(poGeometry);
 
     SetMBR(dX, dY, dX, dY);
-    SetIntMBR(poObjHdr->m_nMinX, poObjHdr->m_nMinY, 
+    SetIntMBR(poObjHdr->m_nMinX, poObjHdr->m_nMinY,
               poObjHdr->m_nMaxX, poObjHdr->m_nMaxY);
 
     return 0;
@@ -1843,6 +1852,8 @@ TABPolyline::TABPolyline(OGRFeatureDefn *poDefnIn):
     m_bCenterIsSet = FALSE;
     m_bSmooth = FALSE;
     m_bWriteTwoPointLineAsPolyline = FALSE;
+    m_dCenterX = 0;
+    m_dCenterY = 0;
 }
 
 /**********************************************************************
@@ -1859,7 +1870,7 @@ TABPolyline::~TABPolyline()
  *
  * Duplicate feature, including stuff specific to each TABFeature type.
  *
- * This method calls the generic TABFeature::CloneTABFeature() and 
+ * This method calls the generic TABFeature::CloneTABFeature() and
  * then copies any members specific to its own type.
  **********************************************************************/
 TABFeature *TABPolyline::CloneTABFeature(OGRFeatureDefn *poNewDefn/*=NULL*/)
@@ -1923,7 +1934,7 @@ int TABPolyline::GetNumParts()
  * Returns a reference to the specified OGRLineString number, hiding the
  * complexity of dealing with OGRMultiLineString vs OGRLineString cases.
  *
- * Returns NULL if the geometry contained in the object is invalid or 
+ * Returns NULL if the geometry contained in the object is invalid or
  * missing or if the specified part index is invalid.
  **********************************************************************/
 OGRLineString *TABPolyline::GetPartRef(int nPartIndex)
@@ -1993,12 +2004,12 @@ TABGeomType TABPolyline::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
         {
             m_nMapInfoType = TAB_GEOM_PLINE;
         }
-        else if ( (poLine->getNumPoints() == 2) && 
+        else if ( (poLine->getNumPoints() == 2) &&
                   (m_bWriteTwoPointLineAsPolyline == TRUE) )
         {
            m_nMapInfoType = TAB_GEOM_PLINE;
         }
-        else if ( (poLine->getNumPoints() == 2) && 
+        else if ( (poLine->getNumPoints() == 2) &&
                   (m_bWriteTwoPointLineAsPolyline == FALSE) )
         {
             m_nMapInfoType = TAB_GEOM_LINE;
@@ -2114,7 +2125,7 @@ int TABPolyline::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
         poGeometry = poLine = new OGRLineString();
         poLine->setNumPoints(2);
 
-        poMapFile->Int2Coordsys(poLineHdr->m_nX1, poLineHdr->m_nY1, 
+        poMapFile->Int2Coordsys(poLineHdr->m_nX1, poLineHdr->m_nY1,
                                 dXMin, dYMin);
         poLine->setPoint(0, dXMin, dYMin);
 
@@ -2149,7 +2160,7 @@ int TABPolyline::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
         m_bSmooth       = poPLineHdr->m_bSmooth;
 
         // Centroid/label point
-        poMapFile->Int2Coordsys(poPLineHdr->m_nLabelX, poPLineHdr->m_nLabelY, 
+        poMapFile->Int2Coordsys(poPLineHdr->m_nLabelX, poPLineHdr->m_nLabelY,
                                 dX, dY);
         SetCenter(dX, dY);
 
@@ -2158,9 +2169,9 @@ int TABPolyline::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
         m_nComprOrgY = poPLineHdr->m_nComprOrgY;
 
         // MBR
-        poMapFile->Int2Coordsys(poPLineHdr->m_nMinX, poPLineHdr->m_nMinY, 
+        poMapFile->Int2Coordsys(poPLineHdr->m_nMinX, poPLineHdr->m_nMinY,
                                 dXMin, dYMin);
-        poMapFile->Int2Coordsys(poPLineHdr->m_nMaxX, poPLineHdr->m_nMaxY, 
+        poMapFile->Int2Coordsys(poPLineHdr->m_nMaxX, poPLineHdr->m_nMaxY,
                                 dXMax, dYMax);
 
         if (!bCoordBlockDataOnly)
@@ -2181,7 +2192,7 @@ int TABPolyline::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
         if (poCoordBlock == NULL)
         {
             CPLError(CE_Failure, CPLE_FileIO,
-                     "Can't access coordinate block at offset %d", 
+                     "Can't access coordinate block at offset %d",
                      nCoordBlockPtr);
             return -1;
         }
@@ -2206,7 +2217,7 @@ int TABPolyline::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
             // Failed ... error message has already been produced
             delete poGeometry;
             return nStatus;
-        }   
+        }
 
     }
     else if (m_nMapInfoType == TAB_GEOM_MULTIPLINE ||
@@ -2237,7 +2248,7 @@ int TABPolyline::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
         m_bSmooth       = poPLineHdr->m_bSmooth;
 
         // Centroid/label point
-        poMapFile->Int2Coordsys(poPLineHdr->m_nLabelX, poPLineHdr->m_nLabelY, 
+        poMapFile->Int2Coordsys(poPLineHdr->m_nLabelX, poPLineHdr->m_nLabelY,
                                 dX, dY);
         SetCenter(dX, dY);
 
@@ -2246,9 +2257,9 @@ int TABPolyline::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
         m_nComprOrgY = poPLineHdr->m_nComprOrgY;
 
         // MBR
-        poMapFile->Int2Coordsys(poPLineHdr->m_nMinX, poPLineHdr->m_nMinY, 
+        poMapFile->Int2Coordsys(poPLineHdr->m_nMinX, poPLineHdr->m_nMinY,
                                 dXMin, dYMin);
-        poMapFile->Int2Coordsys(poPLineHdr->m_nMaxX, poPLineHdr->m_nMaxY, 
+        poMapFile->Int2Coordsys(poPLineHdr->m_nMaxX, poPLineHdr->m_nMaxY,
                                 dXMax, dYMax);
 
         if (!bCoordBlockDataOnly)
@@ -2260,8 +2271,10 @@ int TABPolyline::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
         /*-------------------------------------------------------------
          * Read data from the coord. block
          *------------------------------------------------------------*/
-        pasSecHdrs = (TABMAPCoordSecHdr*)CPLMalloc(numLineSections*
+        pasSecHdrs = (TABMAPCoordSecHdr*)VSI_MALLOC2_VERBOSE(numLineSections,
                                                    sizeof(TABMAPCoordSecHdr));
+        if( pasSecHdrs == NULL )
+            return -1;
 
         if (ppoCoordBlock != NULL && *ppoCoordBlock != NULL)
             poCoordBlock = *ppoCoordBlock;
@@ -2269,12 +2282,12 @@ int TABPolyline::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
             poCoordBlock = poMapFile->GetCoordBlock(nCoordBlockPtr);
 
         if (poCoordBlock == NULL ||
-            poCoordBlock->ReadCoordSecHdrs(bComprCoord, nVersion, 
+            poCoordBlock->ReadCoordSecHdrs(bComprCoord, nVersion,
                                            numLineSections,
                                            pasSecHdrs, numPointsTotal) != 0)
         {
             CPLError(CE_Failure, CPLE_FileIO,
-                     "Failed reading coordinate data at offset %d", 
+                     "Failed reading coordinate data at offset %d",
                      nCoordBlockPtr);
             CPLFree(pasSecHdrs);
             return -1;
@@ -2282,12 +2295,17 @@ int TABPolyline::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
 
         poCoordBlock->SetComprCoordOrigin(m_nComprOrgX, m_nComprOrgY);
 
-        panXY = (GInt32*)CPLMalloc(numPointsTotal*2*sizeof(GInt32));
+        panXY = (GInt32*)VSI_MALLOC2_VERBOSE(numPointsTotal,2*sizeof(GInt32));
+        if( panXY == NULL )
+        {
+            CPLFree(pasSecHdrs);
+            return -1;
+        }
 
         if (poCoordBlock->ReadIntCoords(bComprCoord,numPointsTotal,panXY) != 0)
         {
             CPLError(CE_Failure, CPLE_FileIO,
-                     "Failed reading coordinate data at offset %d", 
+                     "Failed reading coordinate data at offset %d",
                      nCoordBlockPtr);
             CPLFree(pasSecHdrs);
             CPLFree(panXY);
@@ -2345,7 +2363,7 @@ int TABPolyline::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     SetGeometryDirectly(poGeometry);
 
     SetMBR(dXMin, dYMin, dXMax, dYMax);
-    SetIntMBR(poObjHdr->m_nMinX, poObjHdr->m_nMinY, 
+    SetIntMBR(poObjHdr->m_nMinX, poObjHdr->m_nMinY,
               poObjHdr->m_nMaxX, poObjHdr->m_nMaxY);
 
     /* Return a ref to coord block so that caller can continue reading
@@ -2390,7 +2408,7 @@ int TABPolyline::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
      *----------------------------------------------------------------*/
     poGeom = GetGeometryRef();
 
-    if ((m_nMapInfoType == TAB_GEOM_LINE || 
+    if ((m_nMapInfoType == TAB_GEOM_LINE ||
          m_nMapInfoType == TAB_GEOM_LINE_C ) &&
         poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbLineString &&
         (poLine = (OGRLineString*)poGeom)->getNumPoints() == 2)
@@ -2400,9 +2418,9 @@ int TABPolyline::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
          *============================================================*/
         TABMAPObjLine *poLineHdr = (TABMAPObjLine *)poObjHdr;
 
-        poMapFile->Coordsys2Int(poLine->getX(0), poLine->getY(0), 
+        poMapFile->Coordsys2Int(poLine->getX(0), poLine->getY(0),
                                 poLineHdr->m_nX1, poLineHdr->m_nY1);
-        poMapFile->Coordsys2Int(poLine->getX(1), poLine->getY(1), 
+        poMapFile->Coordsys2Int(poLine->getX(1), poLine->getY(1),
                                 poLineHdr->m_nX2, poLineHdr->m_nY2);
         poLineHdr->SetMBR(poLineHdr->m_nX1, poLineHdr->m_nY1,
                           poLineHdr->m_nX2, poLineHdr->m_nY2 );
@@ -2445,12 +2463,12 @@ int TABPolyline::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
         for(i=0; nStatus == 0 && i<numPoints; i++)
         {
             poMapFile->Coordsys2Int(poLine->getX(i), poLine->getY(i), nX, nY);
-            if ((nStatus = poCoordBlock->WriteIntCoord(nX, nY, 
+            if ((nStatus = poCoordBlock->WriteIntCoord(nX, nY,
                                                        bCompressed)) != 0)
             {
                 // Failed ... error message has already been produced
                 return nStatus;
-            }   
+            }
         }
 
         nCoordDataSize = poCoordBlock->GetFeatureDataSize();
@@ -2473,7 +2491,7 @@ int TABPolyline::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
         double dX, dY;
         if (GetCenter(dX, dY) != -1)
         {
-            poMapFile->Coordsys2Int(dX, dY, poPLineHdr->m_nLabelX, 
+            poMapFile->Coordsys2Int(dX, dY, poPLineHdr->m_nLabelX,
                                     poPLineHdr->m_nLabelY);
         }
         else
@@ -2481,7 +2499,7 @@ int TABPolyline::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
             poPLineHdr->m_nLabelX = m_nComprOrgX;
             poPLineHdr->m_nLabelY = m_nComprOrgY;
         }
-        
+
         // Compressed coordinate origin (useful only in compressed case!)
         poPLineHdr->m_nComprOrgX = m_nComprOrgX;
         poPLineHdr->m_nComprOrgY = m_nComprOrgY;
@@ -2545,8 +2563,12 @@ int TABPolyline::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
         /*-------------------------------------------------------------
          * Build and write array of coord sections headers
          *------------------------------------------------------------*/
-        pasSecHdrs = (TABMAPCoordSecHdr*)CPLCalloc(numLines,
+        pasSecHdrs = (TABMAPCoordSecHdr*)VSI_CALLOC_VERBOSE(numLines,
                                                    sizeof(TABMAPCoordSecHdr));
+        if( pasSecHdrs == NULL )
+        {
+            return -1;
+        }
 
         /*-------------------------------------------------------------
          * In calculation of nDataOffset, we have to take into account that
@@ -2566,7 +2588,7 @@ int TABPolyline::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
         {
             if (poMultiLine)
                 poGeom = poMultiLine->getGeometryRef(iLine);
-                
+
             if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbLineString)
             {
                 poLine = (OGRLineString*)poGeom;
@@ -2596,9 +2618,9 @@ int TABPolyline::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
             }
 
         }
-         
+
         if (nStatus == 0)
-            nStatus = poCoordBlock->WriteCoordSecHdrs(nVersion, numLines, 
+            nStatus = poCoordBlock->WriteCoordSecHdrs(nVersion, numLines,
                                                       pasSecHdrs, bCompressed);
 
         CPLFree(pasSecHdrs);
@@ -2629,7 +2651,7 @@ int TABPolyline::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
                     {
                         // Failed ... error message has already been produced
                         return nStatus;
-                    }   
+                    }
                 }
             }
             else
@@ -2661,7 +2683,7 @@ int TABPolyline::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
         double dX, dY;
         if (GetCenter(dX, dY) != -1)
         {
-            poMapFile->Coordsys2Int(dX, dY, poPLineHdr->m_nLabelX, 
+            poMapFile->Coordsys2Int(dX, dY, poPLineHdr->m_nLabelX,
                                     poPLineHdr->m_nLabelY);
         }
         else
@@ -2669,7 +2691,7 @@ int TABPolyline::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
             poPLineHdr->m_nLabelX = m_nComprOrgX;
             poPLineHdr->m_nLabelY = m_nComprOrgY;
         }
-        
+
         // Compressed coordinate origin (useful only in compressed case!)
         poPLineHdr->m_nComprOrgX = m_nComprOrgX;
         poPLineHdr->m_nComprOrgY = m_nComprOrgY;
@@ -2796,14 +2818,14 @@ void TABPolyline::DumpMIF(FILE *fpOut /*=NULL*/)
 /**********************************************************************
  *                   TABPolyline::GetCenter()
  *
- * Returns the center point of the line.  Compute one if it was not 
+ * Returns the center point of the line.  Compute one if it was not
  * explicitly set:
  *
- * In MapInfo, for a simple or multiple polyline (pline), the center point 
- * in the object definition is supposed to be either the center point of 
- * the pline or the first section of a multiple pline (if an odd number of 
- * points in the pline or first section), or the midway point between the 
- * two central points (if an even number of points involved). 
+ * In MapInfo, for a simple or multiple polyline (pline), the center point
+ * in the object definition is supposed to be either the center point of
+ * the pline or the first section of a multiple pline (if an odd number of
+ * points in the pline or first section), or the midway point between the
+ * two central points (if an even number of points involved).
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
@@ -2900,6 +2922,8 @@ TABRegion::TABRegion(OGRFeatureDefn *poDefnIn):
 {
     m_bCenterIsSet = FALSE;
     m_bSmooth = FALSE;
+    m_dCenterX = 0;
+    m_dCenterY = 0;
 }
 
 /**********************************************************************
@@ -2916,7 +2940,7 @@ TABRegion::~TABRegion()
  *
  * Duplicate feature, including stuff specific to each TABFeature type.
  *
- * This method calls the generic TABFeature::CopyTABFeatureBase() and 
+ * This method calls the generic TABFeature::CopyTABFeatureBase() and
  * then copies any members specific to its own type.
  **********************************************************************/
 TABFeature *TABRegion::CloneTABFeature(OGRFeatureDefn *poNewDefn/*=NULL*/)
@@ -3062,9 +3086,9 @@ int TABRegion::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
         m_nComprOrgY = poPLineHdr->m_nComprOrgY;
 
         // MBR
-        poMapFile->Int2Coordsys(poPLineHdr->m_nMinX, poPLineHdr->m_nMinY, 
+        poMapFile->Int2Coordsys(poPLineHdr->m_nMinX, poPLineHdr->m_nMinY,
                                 dXMin, dYMin);
-        poMapFile->Int2Coordsys(poPLineHdr->m_nMaxX, poPLineHdr->m_nMaxY, 
+        poMapFile->Int2Coordsys(poPLineHdr->m_nMaxX, poPLineHdr->m_nMaxY,
                                 dXMax, dYMax);
 
         if (!bCoordBlockDataOnly)
@@ -3078,8 +3102,10 @@ int TABRegion::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
         /*-------------------------------------------------------------
          * Read data from the coord. block
          *------------------------------------------------------------*/
-        pasSecHdrs = (TABMAPCoordSecHdr*)CPLMalloc(numLineSections*
+        pasSecHdrs = (TABMAPCoordSecHdr*)VSI_MALLOC2_VERBOSE(numLineSections,
                                                    sizeof(TABMAPCoordSecHdr));
+        if( pasSecHdrs == NULL )
+            return -1;
 
         if (ppoCoordBlock != NULL && *ppoCoordBlock != NULL)
             poCoordBlock = *ppoCoordBlock;
@@ -3095,18 +3121,23 @@ int TABRegion::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
                                            pasSecHdrs, numPointsTotal) != 0)
         {
             CPLError(CE_Failure, CPLE_FileIO,
-                     "Failed reading coordinate data at offset %d", 
+                     "Failed reading coordinate data at offset %d",
                      nCoordBlockPtr);
             CPLFree(pasSecHdrs);
             return -1;
         }
 
-        panXY = (GInt32*)CPLMalloc(numPointsTotal*2*sizeof(GInt32));
+        panXY = (GInt32*)VSI_MALLOC2_VERBOSE(numPointsTotal,2*sizeof(GInt32));
+        if( panXY == NULL )
+        {
+            CPLFree(pasSecHdrs);
+            return -1;
+        }
 
         if (poCoordBlock->ReadIntCoords(bComprCoord,numPointsTotal,panXY) != 0)
         {
             CPLError(CE_Failure, CPLE_FileIO,
-                     "Failed reading coordinate data at offset %d", 
+                     "Failed reading coordinate data at offset %d",
                      nCoordBlockPtr);
             CPLFree(pasSecHdrs);
             CPLFree(panXY);
@@ -3118,7 +3149,7 @@ int TABRegion::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
          * depending on the number of outer rings found in CoordSecHdr blocks.
          * The CoodSecHdr block for each outer ring in the region has a flag
          * indicating the number of inner rings that follow.
-         * In older versions of the format, the count of inner rings was 
+         * In older versions of the format, the count of inner rings was
          * always zero, so in this case we would always return MultiPolygons.
          *
          * Note: The current implementation assumes that there cannot be
@@ -3206,7 +3237,7 @@ int TABRegion::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     SetGeometryDirectly(poGeometry);
 
     SetMBR(dXMin, dYMin, dXMax, dYMax);
-    SetIntMBR(poObjHdr->m_nMinX, poObjHdr->m_nMinY, 
+    SetIntMBR(poObjHdr->m_nMinX, poObjHdr->m_nMinY,
               poObjHdr->m_nMaxX, poObjHdr->m_nMaxY);
 
     /* Return a ref to coord block so that caller can continue reading
@@ -3261,7 +3292,7 @@ int TABRegion::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
         /*=============================================================
          * REGIONs are similar to PLINE MULTIPLE
          *
-         * We accept both OGRPolygons (with one or multiple rings) and 
+         * We accept both OGRPolygons (with one or multiple rings) and
          * OGRMultiPolygons as input.
          *============================================================*/
         int     nStatus=0, i, iRing;
@@ -3287,7 +3318,7 @@ int TABRegion::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
            m_nComprOrgX, m_nComprOrgY);
 #endif
         /*-------------------------------------------------------------
-         * Fetch total number of rings and build array of coord 
+         * Fetch total number of rings and build array of coord
          * sections headers.
          *------------------------------------------------------------*/
         numRingsTotal = ComputeNumRings(&pasSecHdrs, poMapFile);
@@ -3300,7 +3331,7 @@ int TABRegion::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
         int nVersion = TAB_GEOM_GET_VERSION(m_nMapInfoType);
 
         if (nStatus == 0)
-            nStatus = poCoordBlock->WriteCoordSecHdrs(nVersion, numRingsTotal, 
+            nStatus = poCoordBlock->WriteCoordSecHdrs(nVersion, numRingsTotal,
                                                       pasSecHdrs, bCompressed);
 
         CPLFree(pasSecHdrs);
@@ -3327,7 +3358,7 @@ int TABRegion::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
             }
 
             int numPoints = poRing->getNumPoints();
-            
+
             for(i=0; nStatus == 0 && i<numPoints; i++)
             {
                 poMapFile->Coordsys2Int(poRing->getX(i), poRing->getY(i),
@@ -3337,7 +3368,7 @@ int TABRegion::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
                 {
                     // Failed ... error message has already been produced
                     return nStatus;
-                }   
+                }
             }
         }/* for iRing*/
 
@@ -3361,7 +3392,7 @@ int TABRegion::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
         double dX, dY;
         if (GetCenter(dX, dY) != -1)
         {
-            poMapFile->Coordsys2Int(dX, dY, poPLineHdr->m_nLabelX, 
+            poMapFile->Coordsys2Int(dX, dY, poPLineHdr->m_nLabelX,
                                     poPLineHdr->m_nLabelY);
         }
         else
@@ -3369,7 +3400,7 @@ int TABRegion::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
             poPLineHdr->m_nLabelX = m_nComprOrgX;
             poPLineHdr->m_nLabelY = m_nComprOrgY;
         }
-        
+
         // Compressed coordinate origin (useful only in compressed case!)
         poPLineHdr->m_nComprOrgX = m_nComprOrgX;
         poPLineHdr->m_nComprOrgY = m_nComprOrgY;
@@ -3408,7 +3439,7 @@ int TABRegion::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
  *
  * Return the total number of rings in this object making it look like
  * all parts of the OGRMultiPolygon (or OGRPolygon) are a single collection
- * of rings... hides the complexity of handling OGRMultiPolygons vs 
+ * of rings... hides the complexity of handling OGRMultiPolygons vs
  * OGRPolygons, etc.
  *
  * Returns 0 if the geometry contained in the object is invalid or missing.
@@ -3451,7 +3482,7 @@ int TABRegion::ComputeNumRings(TABMAPCoordSecHdr **ppasSecHdrs,
 
                 if (ppasSecHdrs)
                 {
-                    if (AppendSecHdrs(poPolygon, *ppasSecHdrs, 
+                    if (AppendSecHdrs(poPolygon, *ppasSecHdrs,
                                       poMapFile, iLastSect) != 0)
                         return 0; // An error happened, return count=0
                 }
@@ -3465,7 +3496,7 @@ int TABRegion::ComputeNumRings(TABMAPCoordSecHdr **ppasSecHdrs,
 
             if (ppasSecHdrs)
             {
-                if (AppendSecHdrs(poPolygon, *ppasSecHdrs, 
+                if (AppendSecHdrs(poPolygon, *ppasSecHdrs,
                                   poMapFile, iLastSect) != 0)
                     return 0;  // An error happened, return count=0
             }
@@ -3473,7 +3504,7 @@ int TABRegion::ComputeNumRings(TABMAPCoordSecHdr **ppasSecHdrs,
     }
 
     /*-----------------------------------------------------------------
-     * If we're generating section header blocks, then init the 
+     * If we're generating section header blocks, then init the
      * coordinate offset values.
      *
      * In calculation of nDataOffset, we have to take into account that
@@ -3537,23 +3568,23 @@ int TABRegion::AppendSecHdrs(OGRPolygon *poPolygon,
 
         if (iRing == 0)
             poRing = poPolygon->getExteriorRing();
-        else 
+        else
             poRing = poPolygon->getInteriorRing(iRing-1);
 
         if (poRing == NULL)
         {
-            CPLError(CE_Failure, CPLE_AssertionFailed, 
+            CPLError(CE_Failure, CPLE_AssertionFailed,
                      "Assertion Failed: Encountered NULL ring in OGRPolygon");
             return -1;
         }
 
         poRing->getEnvelope(&sEnvelope);
-            
+
         pasSecHdrs[iLastRing].numVertices = poRing->getNumPoints();
 
         if (iRing == 0)
             pasSecHdrs[iLastRing].numHoles = numRingsInPolygon-1;
-        else 
+        else
             pasSecHdrs[iLastRing].numHoles = 0;
 
         poMapFile->Coordsys2Int(sEnvelope.MinX, sEnvelope.MinY,
@@ -3574,10 +3605,10 @@ int TABRegion::AppendSecHdrs(OGRPolygon *poPolygon,
  *
  * Returns a reference to the specified ring number making it look like
  * all parts of the OGRMultiPolygon (or OGRPolygon) are a single collection
- * of rings... hides the complexity of handling OGRMultiPolygons vs 
+ * of rings... hides the complexity of handling OGRMultiPolygons vs
  * OGRPolygons, etc.
  *
- * Returns NULL if the geometry contained in the object is invalid or 
+ * Returns NULL if the geometry contained in the object is invalid or
  * missing or if the specified ring index is invalid.
  **********************************************************************/
 OGRLinearRing *TABRegion::GetRingRef(int nRequestedRingIndex)
@@ -3593,7 +3624,6 @@ OGRLinearRing *TABRegion::GetRingRef(int nRequestedRingIndex)
         /*-------------------------------------------------------------
          * Establish number of polygons based on geometry type
          *------------------------------------------------------------*/
-        OGRPolygon      *poPolygon=NULL;
         OGRMultiPolygon *poMultiPolygon = NULL;
         int             iCurRing = 0;
         int             numOGRPolygons = 0;
@@ -3605,7 +3635,6 @@ OGRLinearRing *TABRegion::GetRingRef(int nRequestedRingIndex)
         }
         else
         {
-            poPolygon = (OGRPolygon*)poGeom;
             numOGRPolygons = 1;
         }
 
@@ -3615,6 +3644,7 @@ OGRLinearRing *TABRegion::GetRingRef(int nRequestedRingIndex)
         iCurRing = 0;
         for(int iPoly=0; poRing == NULL && iPoly < numOGRPolygons; iPoly++)
         {
+            OGRPolygon      *poPolygon;
             if (poMultiPolygon)
                 poPolygon = (OGRPolygon*)poMultiPolygon->getGeometryRef(iPoly);
             else
@@ -3657,7 +3687,6 @@ GBool TABRegion::IsInteriorRing(int nRequestedRingIndex)
         /*-------------------------------------------------------------
          * Establish number of polygons based on geometry type
          *------------------------------------------------------------*/
-        OGRPolygon      *poPolygon=NULL;
         OGRMultiPolygon *poMultiPolygon = NULL;
         int             iCurRing = 0;
         int             numOGRPolygons = 0;
@@ -3669,7 +3698,6 @@ GBool TABRegion::IsInteriorRing(int nRequestedRingIndex)
         }
         else
         {
-            poPolygon = (OGRPolygon*)poGeom;
             numOGRPolygons = 1;
         }
 
@@ -3679,6 +3707,7 @@ GBool TABRegion::IsInteriorRing(int nRequestedRingIndex)
         iCurRing = 0;
         for(int iPoly=0; poRing == NULL && iPoly < numOGRPolygons; iPoly++)
         {
+            OGRPolygon* poPolygon;
             if (poMultiPolygon)
                 poPolygon = (OGRPolygon*)poMultiPolygon->getGeometryRef(iPoly);
             else
@@ -3713,7 +3742,7 @@ const char *TABRegion::GetStyleString()
 {
     if (m_pszStyleString == NULL)
     {
-        // Since GetPen/BrushStyleString() use CPLSPrintf(), we need 
+        // Since GetPen/BrushStyleString() use CPLSPrintf(), we need
         // to use temporary buffers
         char *pszPen = CPLStrdup(GetPenStyleString());
         char *pszBrush = CPLStrdup(GetBrushStyleString());
@@ -3798,8 +3827,8 @@ void TABRegion::DumpMIF(FILE *fpOut /*=NULL*/)
 /**********************************************************************
  *                   TABRegion::GetCenter()
  *
- * Returns the center/label point of the region.  
- * Compute one using OGRPolygonLabelPoint() if it was not explicitly set 
+ * Returns the center/label point of the region.
+ * Compute one using OGRPolygonLabelPoint() if it was not explicitly set
  * before.
  *
  * Returns 0 on success, -1 on error.
@@ -3809,7 +3838,7 @@ int TABRegion::GetCenter(double &dX, double &dY)
     if (!m_bCenterIsSet)
     {
         /*-------------------------------------------------------------
-         * Calculate label point.  If we have a multipolygon then we use 
+         * Calculate label point.  If we have a multipolygon then we use
          * the first OGRPolygon in the feature to calculate the point.
          *------------------------------------------------------------*/
         OGRPoint        oLabelPoint;
@@ -3899,7 +3928,7 @@ TABRectangle::~TABRectangle()
  *
  * Duplicate feature, including stuff specific to each TABFeature type.
  *
- * This method calls the generic TABFeature::CopyTABFeatureBase() and 
+ * This method calls the generic TABFeature::CopyTABFeatureBase() and
  * then copies any members specific to its own type.
  **********************************************************************/
 TABFeature *TABRectangle::CloneTABFeature(OGRFeatureDefn *poNewDefn/*=NULL*/)
@@ -3907,7 +3936,7 @@ TABFeature *TABRectangle::CloneTABFeature(OGRFeatureDefn *poNewDefn/*=NULL*/)
     /*-----------------------------------------------------------------
      * Alloc new feature and copy the base stuff
      *----------------------------------------------------------------*/
-    TABRectangle *poNew = new TABRectangle(poNewDefn ? poNewDefn : 
+    TABRectangle *poNew = new TABRectangle(poNewDefn ? poNewDefn :
                                                        GetDefnRef());
 
     CopyTABFeatureBase(poNew);
@@ -3964,7 +3993,7 @@ TABGeomType TABRectangle::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
      * Decide if coordinates should be compressed or not.
      *----------------------------------------------------------------*/
     // __TODO__ For now we always write uncompressed for this class...
-    // ValidateCoordType(poMapFile);    
+    // ValidateCoordType(poMapFile);
     UpdateMBR(poMapFile);
 
     return m_nMapInfoType;
@@ -3996,8 +4025,8 @@ int TABRectangle::UpdateMBR(TABMAPFile * poMapFile /*=NULL*/)
     }
 
     /*-----------------------------------------------------------------
-     * Note that we will simply use the rectangle's MBR and don't really 
-     * read the polygon geometry... this should be OK unless the 
+     * Note that we will simply use the rectangle's MBR and don't really
+     * read the polygon geometry... this should be OK unless the
      * polygon geometry was not really a rectangle.
      *----------------------------------------------------------------*/
     m_dXMin = sEnvelope.MinX;
@@ -4066,7 +4095,7 @@ int TABRectangle::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
         m_nMapInfoType == TAB_GEOM_ROUNDRECT_C)
     {
         // Read the corner's diameters
-        poMapFile->Int2CoordsysDist(poRectHdr->m_nCornerWidth, 
+        poMapFile->Int2CoordsysDist(poRectHdr->m_nCornerWidth,
                                     poRectHdr->m_nCornerHeight,
                                     m_dRoundXRadius, m_dRoundYRadius);
 
@@ -4084,9 +4113,9 @@ int TABRectangle::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
 
     // A rectangle is defined by its MBR
 
-    poMapFile->Int2Coordsys(poRectHdr->m_nMinX, poRectHdr->m_nMinY, 
+    poMapFile->Int2Coordsys(poRectHdr->m_nMinX, poRectHdr->m_nMinY,
                             dXMin, dYMin);
-    poMapFile->Int2Coordsys(poRectHdr->m_nMaxX, poRectHdr->m_nMaxY, 
+    poMapFile->Int2Coordsys(poRectHdr->m_nMaxX, poRectHdr->m_nMaxY,
                             dXMax, dYMax);
 
     m_nPenDefIndex = poRectHdr->m_nPenId;       // Pen index
@@ -4103,7 +4132,7 @@ int TABRectangle::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     GetMBR(dXMin, dYMin, dXMax, dYMax);
 
     /* Copy int MBR to feature class members */
-    SetIntMBR(poObjHdr->m_nMinX, poObjHdr->m_nMinY, 
+    SetIntMBR(poObjHdr->m_nMinX, poObjHdr->m_nMinY,
               poObjHdr->m_nMaxX, poObjHdr->m_nMaxY);
 
     /*-----------------------------------------------------------------
@@ -4115,29 +4144,29 @@ int TABRectangle::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     {
         /*-------------------------------------------------------------
          * For rounded rectangles, we generate arcs with 45 line
-         * segments for each corner.  We start with lower-left corner 
+         * segments for each corner.  We start with lower-left corner
          * and proceed counterclockwise
          * We also have to make sure that rounding radius is not too
-         * large for the MBR in the generated polygon... however, we 
+         * large for the MBR in the generated polygon... however, we
          * always return the true X/Y radius (not adjusted) since this
          * is the way MapInfo seems to do it when a radius bigger than
          * the MBR is passed from TBA to MIF.
          *------------------------------------------------------------*/
         double dXRadius = MIN(m_dRoundXRadius, (dXMax-dXMin)/2.0);
         double dYRadius = MIN(m_dRoundYRadius, (dYMax-dYMin)/2.0);
-        TABGenerateArc(poRing, 45, 
+        TABGenerateArc(poRing, 45,
                        dXMin + dXRadius, dYMin + dYRadius, dXRadius, dYRadius,
-                       PI, 3.0*PI/2.0);
-        TABGenerateArc(poRing, 45, 
+                       M_PI, 3.0*M_PI/2.0);
+        TABGenerateArc(poRing, 45,
                        dXMax - dXRadius, dYMin + dYRadius, dXRadius, dYRadius,
-                       3.0*PI/2.0, 2.0*PI);
-        TABGenerateArc(poRing, 45, 
+                       3.0*M_PI/2.0, 2.0*M_PI);
+        TABGenerateArc(poRing, 45,
                        dXMax - dXRadius, dYMax - dYRadius, dXRadius, dYRadius,
-                       0.0, PI/2.0);
-        TABGenerateArc(poRing, 45, 
+                       0.0, M_PI/2.0);
+        TABGenerateArc(poRing, 45,
                        dXMin + dXRadius, dYMax - dYRadius, dXRadius, dYRadius,
-                       PI/2.0, PI);
-                       
+                       M_PI/2.0, M_PI);
+
         TABCloseRing(poRing);
     }
     else
@@ -4168,7 +4197,7 @@ int TABRectangle::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
  **********************************************************************/
 int TABRectangle::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
                                          TABMAPObjHdr *poObjHdr,
-                                         GBool bCoordBlockDataOnly /*=FALSE*/, 
+                                         GBool bCoordBlockDataOnly /*=FALSE*/,
                                          TABMAPCoordBlock ** /*ppoCoordBlock=NULL*/)
 {
 
@@ -4184,8 +4213,8 @@ int TABRectangle::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
 
     /*-----------------------------------------------------------------
      * Fetch and validate geometry and update MBR
-     * Note that we will simply use the geometry's MBR and don't really 
-     * read the polygon geometry... this should be OK unless the 
+     * Note that we will simply use the geometry's MBR and don't really
+     * read the polygon geometry... this should be OK unless the
      * polygon geometry was not really a rectangle.
      *----------------------------------------------------------------*/
     if (UpdateMBR(poMapFile) != 0)
@@ -4196,7 +4225,7 @@ int TABRectangle::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
      *----------------------------------------------------------------*/
     TABMAPObjRectEllipse *poRectHdr = (TABMAPObjRectEllipse *)poObjHdr;
 
-    if (m_nMapInfoType == TAB_GEOM_ROUNDRECT || 
+    if (m_nMapInfoType == TAB_GEOM_ROUNDRECT ||
         m_nMapInfoType == TAB_GEOM_ROUNDRECT_C)
     {
         poMapFile->Coordsys2IntDist(m_dRoundXRadius*2.0, m_dRoundYRadius*2.0,
@@ -4237,7 +4266,7 @@ const char *TABRectangle::GetStyleString()
 {
     if (m_pszStyleString == NULL)
     {
-        // Since GetPen/BrushStyleString() use CPLSPrintf(), we need 
+        // Since GetPen/BrushStyleString() use CPLSPrintf(), we need
         // to use temporary buffers
         char *pszPen = CPLStrdup(GetPenStyleString());
         char *pszBrush = CPLStrdup(GetBrushStyleString());
@@ -4271,8 +4300,8 @@ void TABRectangle::DumpMIF(FILE *fpOut /*=NULL*/)
     double dXMin, dYMin, dXMax, dYMax;
     GetMBR(dXMin, dYMin, dXMax, dYMax);
     if (m_bRoundCorners)
-        fprintf(fpOut, "(ROUNDRECT %.15g %.15g %.15g %.15g    %.15g %.15g)\n", 
-                dXMin, dYMin, dXMax, dYMax, 
+        fprintf(fpOut, "(ROUNDRECT %.15g %.15g %.15g %.15g    %.15g %.15g)\n",
+                dXMin, dYMin, dXMax, dYMax,
                 m_dRoundXRadius, m_dRoundYRadius);
     else
         fprintf(fpOut, "(RECT %.15g %.15g %.15g %.15g)\n", dXMin, dYMin, dXMax, dYMax);
@@ -4341,6 +4370,10 @@ void TABRectangle::DumpMIF(FILE *fpOut /*=NULL*/)
 TABEllipse::TABEllipse(OGRFeatureDefn *poDefnIn):
               TABFeature(poDefnIn)
 {
+    m_dCenterX = 0;
+    m_dCenterY = 0;
+    m_dXRadius = 0;
+    m_dYRadius = 0;
 }
 
 /**********************************************************************
@@ -4357,7 +4390,7 @@ TABEllipse::~TABEllipse()
  *
  * Duplicate feature, including stuff specific to each TABFeature type.
  *
- * This method calls the generic TABFeature::CopyTABFeatureBase() and 
+ * This method calls the generic TABFeature::CopyTABFeatureBase() and
  * then copies any members specific to its own type.
  **********************************************************************/
 TABFeature *TABEllipse::CloneTABFeature(OGRFeatureDefn *poNewDefn/*=NULL*/)
@@ -4365,7 +4398,7 @@ TABFeature *TABEllipse::CloneTABFeature(OGRFeatureDefn *poNewDefn/*=NULL*/)
     /*-----------------------------------------------------------------
      * Alloc new feature and copy the base stuff
      *----------------------------------------------------------------*/
-    TABEllipse *poNew = new TABEllipse(poNewDefn ? poNewDefn : 
+    TABEllipse *poNew = new TABEllipse(poNewDefn ? poNewDefn :
                                                    GetDefnRef());
 
     CopyTABFeatureBase(poNew);
@@ -4441,8 +4474,8 @@ int TABEllipse::UpdateMBR(TABMAPFile * poMapFile /*=NULL*/)
 
     /*-----------------------------------------------------------------
      * Fetch and validate geometry... Polygon and point are accepted.
-     * Note that we will simply use the ellipse's MBR and don't really 
-     * read the polygon geometry... this should be OK unless the 
+     * Note that we will simply use the ellipse's MBR and don't really
+     * read the polygon geometry... this should be OK unless the
      * polygon geometry was not really an ellipse.
      *----------------------------------------------------------------*/
     poGeom = GetGeometryRef();
@@ -4457,7 +4490,7 @@ int TABEllipse::UpdateMBR(TABMAPFile * poMapFile /*=NULL*/)
     }
 
     /*-----------------------------------------------------------------
-     * We use the center of the MBR as the ellipse center, and the 
+     * We use the center of the MBR as the ellipse center, and the
      * X/Y radius to define the MBR size.  If X/Y radius are null then
      * we'll try to use the MBR to recompute them.
      *----------------------------------------------------------------*/
@@ -4530,9 +4563,9 @@ int TABEllipse::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
 
     // An ellipse is defined by its MBR
 
-    poMapFile->Int2Coordsys(poRectHdr->m_nMinX, poRectHdr->m_nMinY, 
+    poMapFile->Int2Coordsys(poRectHdr->m_nMinX, poRectHdr->m_nMinY,
                             dXMin, dYMin);
-    poMapFile->Int2Coordsys(poRectHdr->m_nMaxX, poRectHdr->m_nMaxY, 
+    poMapFile->Int2Coordsys(poRectHdr->m_nMaxX, poRectHdr->m_nMaxY,
                             dXMax, dYMax);
 
     m_nPenDefIndex = poRectHdr->m_nPenId;       // Pen index
@@ -4551,7 +4584,7 @@ int TABEllipse::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
 
     SetMBR(dXMin, dYMin, dXMax, dYMax);
 
-    SetIntMBR(poObjHdr->m_nMinX, poObjHdr->m_nMinY, 
+    SetIntMBR(poObjHdr->m_nMinX, poObjHdr->m_nMinY,
               poObjHdr->m_nMaxX, poObjHdr->m_nMaxY);
 
     /*-----------------------------------------------------------------
@@ -4565,10 +4598,10 @@ int TABEllipse::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
      * For the OGR geometry, we generate an ellipse with 2 degrees line
      * segments.
      *----------------------------------------------------------------*/
-    TABGenerateArc(poRing, 180, 
+    TABGenerateArc(poRing, 180,
                    m_dCenterX, m_dCenterY,
                    m_dXRadius, m_dYRadius,
-                   0.0, 2.0*PI);
+                   0.0, 2.0*M_PI);
     TABCloseRing(poRing);
 
     poPolygon->addRingDirectly(poRing);
@@ -4590,7 +4623,7 @@ int TABEllipse::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
  **********************************************************************/
 int TABEllipse::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
                                        TABMAPObjHdr *poObjHdr,
-                                       GBool bCoordBlockDataOnly /*=FALSE*/, 
+                                       GBool bCoordBlockDataOnly /*=FALSE*/,
                                        TABMAPCoordBlock ** /*ppoCoordBlock=NULL*/)
 {
     /* Nothing to do for bCoordBlockDataOnly (used by index splitting) */
@@ -4605,11 +4638,11 @@ int TABEllipse::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
 
     /*-----------------------------------------------------------------
      * Fetch and validate geometry... Polygon and point are accepted.
-     * Note that we will simply use the ellipse's MBR and don't really 
-     * read the polygon geometry... this should be OK unless the 
+     * Note that we will simply use the ellipse's MBR and don't really
+     * read the polygon geometry... this should be OK unless the
      * polygon geometry was not really an ellipse.
      *
-     * We use the center of the MBR as the ellipse center, and the 
+     * We use the center of the MBR as the ellipse center, and the
      * X/Y radius to define the MBR size.  If X/Y radius are null then
      * we'll try to use the MBR to recompute them.
      *----------------------------------------------------------------*/
@@ -4653,7 +4686,7 @@ const char *TABEllipse::GetStyleString()
 {
     if (m_pszStyleString == NULL)
     {
-        // Since GetPen/BrushStyleString() use CPLSPrintf(), we need 
+        // Since GetPen/BrushStyleString() use CPLSPrintf(), we need
         // to use temporary buffers
         char *pszPen = CPLStrdup(GetPenStyleString());
         char *pszBrush = CPLStrdup(GetBrushStyleString());
@@ -4772,7 +4805,7 @@ TABArc::~TABArc()
  *
  * Duplicate feature, including stuff specific to each TABFeature type.
  *
- * This method calls the generic TABFeature::CopyTABFeatureBase() and 
+ * This method calls the generic TABFeature::CopyTABFeatureBase() and
  * then copies any members specific to its own type.
  **********************************************************************/
 TABFeature *TABArc::CloneTABFeature(OGRFeatureDefn *poNewDefn/*=NULL*/)
@@ -4858,18 +4891,18 @@ int TABArc::UpdateMBR(TABMAPFile * poMapFile /*=NULL*/)
     {
         /*-------------------------------------------------------------
          * POLYGON geometry:
-         * Note that we will simply use the ellipse's MBR and don't really 
-         * read the polygon geometry... this should be OK unless the 
+         * Note that we will simply use the ellipse's MBR and don't really
+         * read the polygon geometry... this should be OK unless the
          * polygon geometry was not really an ellipse.
          * In the case of a polygon geometry. the m_dCenterX/Y values MUST
          * have been set by the caller.
          *------------------------------------------------------------*/
         poGeom->getEnvelope(&sEnvelope);
     }
-    else if ( (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint ) ) 
+    else if ( (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint ) )
     {
         /*-------------------------------------------------------------
-         * In the case of a POINT GEOMETRY, we will make sure the the 
+         * In the case of a POINT GEOMETRY, we will make sure the
          * feature's m_dCenterX/Y are in sync with the point's X,Y coords.
          *
          * In this case we have to reconstruct the arc inside a temporary
@@ -4890,7 +4923,7 @@ int TABArc::UpdateMBR(TABMAPFile * poMapFile /*=NULL*/)
         TABGenerateArc(&oTmpLine, numPts,
                        m_dCenterX, m_dCenterY,
                        m_dXRadius, m_dYRadius,
-                       m_dStartAngle*PI/180.0, m_dEndAngle*PI/180.0);
+                       m_dStartAngle*M_PI/180.0, m_dEndAngle*M_PI/180.0);
 
         oTmpLine.getEnvelope(&sEnvelope);
     }
@@ -4930,7 +4963,7 @@ int TABArc::UpdateMBR(TABMAPFile * poMapFile /*=NULL*/)
  **********************************************************************/
 int TABArc::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
                                     TABMAPObjHdr *poObjHdr,
-                                    GBool bCoordBlockDataOnly /*=FALSE*/, 
+                                    GBool bCoordBlockDataOnly /*=FALSE*/,
                                     TABMAPCoordBlock ** /*ppoCoordBlock=NULL*/)
 {
     double              dXMin, dYMin, dXMax, dYMax;
@@ -4975,7 +5008,7 @@ int TABArc::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     /*-------------------------------------------------------------
      * OK, Arc angles again!!!!!!!!!!!!
      * After some tests in 1999-11, it appeared that the angle values
-     * ALWAYS had to be flipped (read order= end angle followed by 
+     * ALWAYS had to be flipped (read order= end angle followed by
      * start angle), no matter which quadrant the file is in.
      * This does not make any sense, so I suspect that there is something
      * that we are missing here!
@@ -4991,16 +5024,16 @@ int TABArc::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
      *  -> Quadrant 2 and 4, angles order = end, start
      * + Always adjust angles for x and y axis based on quadrant.
      *
-     * This was confirmed using some more files in which the quadrant was 
-     * manually changed, but whether these are valid results is 
-     * discutable.
+     * This was confirmed using some more files in which the quadrant was
+     * manually changed, but whether these are valid results is
+     * disputable.
      *
      * The ReflectXAxis flag seems to have no effect here...
      *------------------------------------------------------------*/
 
     /*-------------------------------------------------------------
      * In version 100 .tab files (version 400 .map), it is possible
-     * to have a quadrant value of 0 and it should be treated the 
+     * to have a quadrant value of 0 and it should be treated the
      * same way as quadrant 3
      *------------------------------------------------------------*/
     if ( poMapFile->GetHeaderBlock()->m_nCoordOriginQuadrant==1 ||
@@ -5045,9 +5078,9 @@ int TABArc::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
 
     // An arc is defined by its defining ellipse's MBR:
 
-    poMapFile->Int2Coordsys(poArcHdr->m_nArcEllipseMinX, 
+    poMapFile->Int2Coordsys(poArcHdr->m_nArcEllipseMinX,
                             poArcHdr->m_nArcEllipseMinY , dXMin, dYMin);
-    poMapFile->Int2Coordsys(poArcHdr->m_nArcEllipseMaxX, 
+    poMapFile->Int2Coordsys(poArcHdr->m_nArcEllipseMaxX,
                             poArcHdr->m_nArcEllipseMaxY , dXMax, dYMax);
 
     m_dCenterX = (dXMin + dXMax) / 2.0;
@@ -5056,9 +5089,9 @@ int TABArc::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     m_dYRadius = ABS( (dYMax - dYMin) / 2.0 );
 
     // Read the Arc's MBR and use that as this feature's MBR
-    poMapFile->Int2Coordsys(poArcHdr->m_nMinX, poArcHdr->m_nMinY, 
+    poMapFile->Int2Coordsys(poArcHdr->m_nMinX, poArcHdr->m_nMinY,
                             dXMin, dYMin);
-    poMapFile->Int2Coordsys(poArcHdr->m_nMaxX, poArcHdr->m_nMaxY, 
+    poMapFile->Int2Coordsys(poArcHdr->m_nMaxX, poArcHdr->m_nMaxY,
                             dXMax, dYMax);
     SetMBR(dXMin, dYMin, dXMax, dYMax);
 
@@ -5082,7 +5115,7 @@ int TABArc::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     TABGenerateArc(poLine, numPts,
                    m_dCenterX, m_dCenterY,
                    m_dXRadius, m_dYRadius,
-                   m_dStartAngle*PI/180.0, m_dEndAngle*PI/180.0);
+                   m_dStartAngle*M_PI/180.0, m_dEndAngle*M_PI/180.0);
 
     SetGeometryDirectly(poLine);
 
@@ -5102,7 +5135,7 @@ int TABArc::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
  **********************************************************************/
 int TABArc::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
                                    TABMAPObjHdr *poObjHdr,
-                                   GBool bCoordBlockDataOnly /*=FALSE*/, 
+                                   GBool bCoordBlockDataOnly /*=FALSE*/,
                                    TABMAPCoordBlock ** /*ppoCoordBlock=NULL*/)
 {
     /* Nothing to do for bCoordBlockDataOnly (used by index splitting) */
@@ -5138,13 +5171,13 @@ int TABArc::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
 
     poArcHdr->m_nStartAngle = ROUND_INT(m_dStartAngle*10.0);
     poArcHdr->m_nEndAngle = ROUND_INT(m_dEndAngle*10.0);
-    
+
     // An arc is defined by its defining ellipse's MBR:
     poMapFile->Coordsys2Int(m_dCenterX-m_dXRadius, m_dCenterY-m_dYRadius,
-                            poArcHdr->m_nArcEllipseMinX, 
+                            poArcHdr->m_nArcEllipseMinX,
                             poArcHdr->m_nArcEllipseMinY);
     poMapFile->Coordsys2Int(m_dCenterX+m_dXRadius, m_dCenterY+m_dYRadius,
-                            poArcHdr->m_nArcEllipseMaxX, 
+                            poArcHdr->m_nArcEllipseMaxX,
                             poArcHdr->m_nArcEllipseMaxY);
 
     // Pass the Arc's actual MBR (values were set in UpdateMBR())
@@ -5298,7 +5331,7 @@ TABText::~TABText()
  *
  * Duplicate feature, including stuff specific to each TABFeature type.
  *
- * This method calls the generic TABFeature::CopyTABFeatureBase() and 
+ * This method calls the generic TABFeature::CopyTABFeatureBase() and
  * then copies any members specific to its own type.
  **********************************************************************/
 TABFeature *TABText::CloneTABFeature(OGRFeatureDefn *poNewDefn/*=NULL*/)
@@ -5332,7 +5365,7 @@ TABFeature *TABText::CloneTABFeature(OGRFeatureDefn *poNewDefn/*=NULL*/)
 
     poNew->SetTextJustification( GetTextJustification() );
     poNew->SetTextSpacing( GetTextSpacing() );
-    // Note: Text arrow/line coordinates are not transported... but 
+    // Note: Text arrow/line coordinates are not transported... but
     //       we ignore them most of the time anyways.
     poNew->SetTextLineType( TABTLNoLine );
 
@@ -5429,9 +5462,9 @@ int TABText::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     m_nTextAlignment = poTextHdr->m_nTextAlignment; // just./spacing/arrow
 
     /*-------------------------------------------------------------
-     * Text Angle, in thenths of degree.
-     * Contrary to arc start/end angles, no conversion based on 
-     * origin quadrant is required here
+     * Text Angle, in tenths of degree.
+     * Contrary to arc start/end angles, no conversion based on
+     * origin quadrant is required here.
      *------------------------------------------------------------*/
     m_dAngle       = poTextHdr->m_nAngle/10.0;
 
@@ -5448,7 +5481,7 @@ int TABText::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     m_rgbShadow     = 0x808080;
 
     // arrow endpoint
-    poMapFile->Int2Coordsys(poTextHdr->m_nLineEndX, poTextHdr->m_nLineEndY, 
+    poMapFile->Int2Coordsys(poTextHdr->m_nLineEndX, poTextHdr->m_nLineEndY,
                             m_dfLineEndX, m_dfLineEndY);
     m_bLineEndSet = TRUE;
 
@@ -5462,9 +5495,9 @@ int TABText::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     }
 
     // MBR after rotation
-    poMapFile->Int2Coordsys(poTextHdr->m_nMinX, poTextHdr->m_nMinY, 
+    poMapFile->Int2Coordsys(poTextHdr->m_nMinX, poTextHdr->m_nMinY,
                             dXMin, dYMin);
-    poMapFile->Int2Coordsys(poTextHdr->m_nMaxX, poTextHdr->m_nMaxY, 
+    poMapFile->Int2Coordsys(poTextHdr->m_nMaxX, poTextHdr->m_nMaxY,
                             dXMax, dYMax);
 
     if (!bCoordBlockDataOnly)
@@ -5484,7 +5517,7 @@ int TABText::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     if (nStringLen > 0)
     {
         TABMAPCoordBlock        *poCoordBlock;
-        CPLAssert(nCoordBlockPtr > 0);
+
         if (ppoCoordBlock != NULL && *ppoCoordBlock != NULL)
             poCoordBlock = *ppoCoordBlock;
         else
@@ -5493,9 +5526,9 @@ int TABText::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
             poCoordBlock->ReadBytes(nStringLen,(GByte*)pszTmpString) != 0)
         {
             CPLError(CE_Failure, CPLE_FileIO,
-                     "Failed reading text string at offset %d", 
+                     "Failed reading text string at offset %d",
                      nCoordBlockPtr);
-            CPLFree(pszTmpString);                
+            CPLFree(pszTmpString);
             return -1;
         }
 
@@ -5518,11 +5551,11 @@ int TABText::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     GetMBR(dXMin, dYMin, dXMax, dYMax);
 
     /* Copy int MBR to feature class members */
-    SetIntMBR(poObjHdr->m_nMinX, poObjHdr->m_nMinY, 
+    SetIntMBR(poObjHdr->m_nMinX, poObjHdr->m_nMinY,
               poObjHdr->m_nMaxX, poObjHdr->m_nMaxY);
 
     /*-----------------------------------------------------------------
-     * Create an OGRPoint Geometry... 
+     * Create an OGRPoint Geometry...
      * The point X,Y values will be the coords of the lower-left corner before
      * rotation is applied.  (Note that the rotation in MapInfo is done around
      * the upper-left corner)
@@ -5530,8 +5563,8 @@ int TABText::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
      * on the MBR after rotation, the text height and the rotation angle.
      *----------------------------------------------------------------*/
     double dCos, dSin, dX, dY;
-    dSin = sin(m_dAngle*PI/180.0);
-    dCos = cos(m_dAngle*PI/180.0);
+    dSin = sin(m_dAngle*M_PI/180.0);
+    dCos = cos(m_dAngle*M_PI/180.0);
     if (dSin > 0.0  && dCos > 0.0)
     {
         dX = dXMin + m_dHeight * dSin;
@@ -5548,7 +5581,7 @@ int TABText::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
         dY = dYMax;
     }
     else  // dSin < 0 && dCos > 0
-    {   
+    {
         dX = dXMin;
         dY = dYMax - m_dHeight * dCos;
     }
@@ -5558,9 +5591,9 @@ int TABText::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     SetGeometryDirectly(poGeometry);
 
     /*-----------------------------------------------------------------
-     * Compute Text Width: the width of the Text MBR before rotation 
+     * Compute Text Width: the width of the Text MBR before rotation
      * in ground units... unfortunately this value is not stored in the
-     * file, so we have to compute it with the MBR after rotation and 
+     * file, so we have to compute it with the MBR after rotation and
      * the height of the MBR before rotation:
      * With  W = Width of MBR before rotation
      *       H = Height of MBR before rotation
@@ -5579,7 +5612,7 @@ int TABText::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     if (m_dHeight == 0.0)
         m_dWidth = 0.0;
     else if ( dCos > dSin )
-        m_dWidth = m_dHeight * ((dXMax-dXMin) - m_dHeight*dSin) / 
+        m_dWidth = m_dHeight * ((dXMax-dXMin) - m_dHeight*dSin) /
                                                         (m_dHeight*dCos);
     else
         m_dWidth = m_dHeight * ((dYMax-dYMin) - m_dHeight*dCos) /
@@ -5611,7 +5644,7 @@ int TABText::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
     GInt32              nCoordBlockPtr;
     TABMAPCoordBlock    *poCoordBlock;
     int                 nStringLen;
-  
+
     /*-----------------------------------------------------------------
      * We assume that ValidateMapInfoType() was called already and that
      * the type in poObjHdr->m_nType is valid.
@@ -5637,7 +5670,7 @@ int TABText::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
      * Write string to a coord block first...
      * Note that the string may contain unescaped '\n' and '\\'
      * that we have to keep like that for the MAP file.
-     * See MapTools bug 1107 for more details. 
+     * See MapTools bug 1107 for more details.
      *----------------------------------------------------------------*/
     if (ppoCoordBlock != NULL && *ppoCoordBlock != NULL)
         poCoordBlock = *ppoCoordBlock;
@@ -5649,7 +5682,7 @@ int TABText::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
     // This string was escaped before 20050714
     char *pszTmpString = m_pszString;
 
-    nStringLen = strlen(pszTmpString);
+    nStringLen = static_cast<int>(strlen(pszTmpString));
 
     if (nStringLen > 0)
     {
@@ -5672,9 +5705,9 @@ int TABText::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
     poTextHdr->m_nTextAlignment = m_nTextAlignment;   // just./spacing/arrow
 
     /*-----------------------------------------------------------------
-     * Text Angle, (written in thenths of degrees)
-     * Contrary to arc start/end angles, no conversion based on 
-     * origin quadrant is required here
+     * Text Angle, (written in tenths of degrees)
+     * Contrary to arc start/end angles, no conversion based on
+     * origin quadrant is required here.
      *----------------------------------------------------------------*/
     poTextHdr->m_nAngle = ROUND_INT(m_dAngle*10.0);
 
@@ -5697,7 +5730,7 @@ int TABText::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
      *----------------------------------------------------------------*/
     double dXMin, dYMin, dXMax, dYMax;
     // Make sure Feature MBR is in sync with other params
- 
+
     UpdateMBR();
     GetMBR(dXMin, dYMin, dXMax, dYMax);
 
@@ -5707,7 +5740,7 @@ int TABText::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
     // Label line end point
     double dX, dY;
     GetTextLineEndPoint(dX, dY); // Make sure a default line end point is set
-    poMapFile->Coordsys2Int(m_dfLineEndX, m_dfLineEndY, 
+    poMapFile->Coordsys2Int(m_dfLineEndX, m_dfLineEndY,
                            poTextHdr->m_nLineEndX, poTextHdr->m_nLineEndY);
 
     // Text Height
@@ -5765,7 +5798,7 @@ const char *TABText::GetTextString()
  * Set new text string value.
  *
  * Note: The text string may contain "\n" chars or "\\" chars
- * and we expect to receive them in a 2 chars escaped form as 
+ * and we expect to receive them in a 2 chars escaped form as
  * described in the MIF format specs.
  **********************************************************************/
 void TABText::SetTextString(const char *pszNewStr)
@@ -5890,11 +5923,11 @@ int TABText::UpdateMBR(TABMAPFile * poMapFile /*=NULL*/)
         dX0 = poPoint->getX();
         dY0 = poPoint->getY();
 
-        dSin = sin(m_dAngle*PI/180.0);
-        dCos = cos(m_dAngle*PI/180.0);
+        dSin = sin(m_dAngle*M_PI/180.0);
+        dCos = cos(m_dAngle*M_PI/180.0);
 
         GetTextBoxWidth();  // Force default width value if necessary.
-        
+
         dX[0] = dX0;
         dY[0] = dY0;
         dX[1] = dX0 + m_dWidth;
@@ -6104,7 +6137,7 @@ void TABText::ToggleFontStyle(TABFontStyle eStyleToToggle, GBool bStyleOn)
  * The reason why we have to differentiate between the TAB and the MIF font
  * style values is that in TAB, TABFSBox is included in the style value
  * as code 0x100, but in MIF it is not included, instead it is implied by
- * the presence of the BG color in the FONT() clause (the BG color is 
+ * the presence of the BG color in the FONT() clause (the BG color is
  * present only when TABFSBox or TABFSHalo is set).
  * This also has the effect of shifting all the other style values > 0x100
  * by 1 byte.
@@ -6170,7 +6203,7 @@ int TABText::IsFontUnderline()
 const char *TABText::GetLabelStyleString()
 {
     const char *pszStyle = NULL;
-    int nStringLen = strlen(GetTextString());
+    int nStringLen = static_cast<int>(strlen(GetTextString()));
     // ALL Caps, Extpanded need to modify the string value
     char *pszTextString = (char*)CPLMalloc((nStringLen+1)*sizeof(char));
     /* char szPattern[20]; */
@@ -6192,7 +6225,7 @@ const char *TABText::GetLabelStyleString()
         nJustification = 1;
         break;
     }
-    
+
     // Compute real font size, taking number of lines ("\\n", "\n") and line
     // spacing into account.
     int numLines = 1;
@@ -6200,7 +6233,7 @@ const char *TABText::GetLabelStyleString()
          numLines += ((pszTextString[i]=='\n' ||
                        (pszTextString[i]=='\\' && pszTextString[i+1]=='n')) &&
                       pszTextString[i+1] != '\0' ),++i);
-    
+
     double dHeight = GetTextBoxHeight()/numLines;
 
     // In all cases, take out 20% of font height to account for line spacing
@@ -6225,9 +6258,9 @@ const char *TABText::GetLabelStyleString()
 
     if (QueryFontStyle(TABFSAllCaps))
         for (int i=0; pszTextString[i];++i)
-            if (isalpha(pszTextString[i])) 
+            if (isalpha(pszTextString[i]))
                 pszTextString[i] = (char)toupper(pszTextString[i]);
-    
+
     /* Escape the double quote chars and expand the text */
     char *pszTmpTextString;
     int j = 0;
@@ -6236,10 +6269,10 @@ const char *TABText::GetLabelStyleString()
         pszTmpTextString = (char*)CPLMalloc(((nStringLen*4)+1)*sizeof(char));
     else
         pszTmpTextString = (char*)CPLMalloc(((nStringLen*2)+1)*sizeof(char));
-    
+
     for (int i =0; i < nStringLen; ++i,++j)
-    { 
-        if (pszTextString[i] == '"') 
+    {
+        if (pszTextString[i] == '"')
         {
             pszTmpTextString[j] = '\\';
             pszTmpTextString[j+1] = pszTextString[i];
@@ -6253,8 +6286,8 @@ const char *TABText::GetLabelStyleString()
             pszTmpTextString[j+1] = ' ';
             ++j;
         }
-    }  
-      
+    }
+
     pszTmpTextString[j] = '\0';
     CPLFree(pszTextString);
     pszTextString = (char*)CPLMalloc((strlen(pszTmpTextString)+1)*sizeof(char));
@@ -6270,16 +6303,16 @@ const char *TABText::GetLabelStyleString()
     const char *pszBold = IsFontBold() ? ",bo:1" :"";
     const char *pszItalic = IsFontItalic() ? ",it:1" :"";
     const char *pszUnderline = IsFontUnderline() ? ",un:1" : "";
-    
+
     pszStyle=CPLSPrintf("LABEL(t:\"%s\",a:%f,s:%fg,c:#%6.6x%s%s%s%s%s%s,p:%d,f:\"%s\")",
                         pszTextString,GetTextAngle(), dHeight,
                         GetFontFGColor(),pszBGColor,pszOColor,pszSColor,
                         pszBold,pszItalic,pszUnderline,nJustification,GetFontNameRef());
-     
+
     CPLFree(pszTextString);
     return pszStyle;
-    
-}  
+
+}
 
 /**********************************************************************
  *                   TABText::GetStyleString()
@@ -6330,9 +6363,9 @@ void TABText::DumpMIF(FILE *fpOut /*=NULL*/)
         fprintf(fpOut, "  m_pszString = '%s'\n", m_pszString);
         fprintf(fpOut, "  m_dAngle    = %.15g\n",   m_dAngle);
         fprintf(fpOut, "  m_dHeight   = %.15g\n",   m_dHeight);
-        fprintf(fpOut, "  m_rgbForeground  = 0x%6.6x (%d)\n", 
+        fprintf(fpOut, "  m_rgbForeground  = 0x%6.6x (%d)\n",
                                              m_rgbForeground, m_rgbForeground);
-        fprintf(fpOut, "  m_rgbBackground  = 0x%6.6x (%d)\n", 
+        fprintf(fpOut, "  m_rgbBackground  = 0x%6.6x (%d)\n",
                                              m_rgbBackground, m_rgbBackground);
         fprintf(fpOut, "  m_nTextAlignment = 0x%4.4x\n",  m_nTextAlignment);
         fprintf(fpOut, "  m_nFontStyle     = 0x%4.4x\n",  m_nFontStyle);
@@ -6364,6 +6397,8 @@ TABMultiPoint::TABMultiPoint(OGRFeatureDefn *poDefnIn):
               TABFeature(poDefnIn)
 {
     m_bCenterIsSet = FALSE;
+    m_dCenterX = 0;
+    m_dCenterY = 0;
 }
 
 /**********************************************************************
@@ -6380,7 +6415,7 @@ TABMultiPoint::~TABMultiPoint()
  *
  * Duplicate feature, including stuff specific to each TABFeature type.
  *
- * This method calls the generic TABFeature::CloneTABFeature() and 
+ * This method calls the generic TABFeature::CloneTABFeature() and
  * then copies any members specific to its own type.
  **********************************************************************/
 TABFeature *TABMultiPoint::CloneTABFeature(OGRFeatureDefn *poNewDefn /*=NULL*/)
@@ -6421,7 +6456,7 @@ TABGeomType TABMultiPoint::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
     OGRGeometry *poGeom;
 
     /*-----------------------------------------------------------------
-     * Fetch and validate geometry 
+     * Fetch and validate geometry
      *----------------------------------------------------------------*/
     poGeom = GetGeometryRef();
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbMultiPoint)
@@ -6492,9 +6527,9 @@ int TABMultiPoint::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
         TABMAPObjMultiPoint *poMPointHdr = (TABMAPObjMultiPoint *)poObjHdr;
 
         // MBR
-        poMapFile->Int2Coordsys(poMPointHdr->m_nMinX, poMPointHdr->m_nMinY, 
+        poMapFile->Int2Coordsys(poMPointHdr->m_nMinX, poMPointHdr->m_nMinY,
                                 dXMin, dYMin);
-        poMapFile->Int2Coordsys(poMPointHdr->m_nMaxX, poMPointHdr->m_nMaxY, 
+        poMapFile->Int2Coordsys(poMPointHdr->m_nMaxX, poMPointHdr->m_nMaxY,
                                 dXMax, dYMax);
 
         if (!bCoordBlockDataOnly)
@@ -6522,7 +6557,12 @@ int TABMultiPoint::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
             poCoordBlock = *ppoCoordBlock;
         else
             poCoordBlock = poMapFile->GetCoordBlock(poMPointHdr->m_nCoordBlockPtr);
-        poCoordBlock->SetComprCoordOrigin(m_nComprOrgX, 
+        if( poCoordBlock == NULL )
+        {
+            delete poGeometry;
+            return -1;
+        }
+        poCoordBlock->SetComprCoordOrigin(m_nComprOrgX,
                                           m_nComprOrgY);
 
         for(int iPoint=0; iPoint<poMPointHdr->m_nNumPoints; iPoint++)
@@ -6530,14 +6570,15 @@ int TABMultiPoint::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
             if (poCoordBlock->ReadIntCoord(bComprCoord, nX, nY) != 0)
             {
                 CPLError(CE_Failure, CPLE_FileIO,
-                         "Failed reading coordinate data at offset %d", 
+                         "Failed reading coordinate data at offset %d",
                          poMPointHdr->m_nCoordBlockPtr);
+                delete poGeometry;
                 return -1;
             }
 
             poMapFile->Int2Coordsys(nX, nY, dX, dY);
             OGRPoint *poPoint = new OGRPoint(dX, dY);
-    
+
             if (poMultiPoint->addGeometryDirectly(poPoint) != OGRERR_NONE)
             {
                 CPLAssert(FALSE); // Just in case lower-level lib is modified
@@ -6558,7 +6599,7 @@ int TABMultiPoint::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     SetMBR(dXMin, dYMin, dXMax, dYMax);
 
     /* Copy int MBR to feature class members */
-    SetIntMBR(poObjHdr->m_nMinX, poObjHdr->m_nMinY, 
+    SetIntMBR(poObjHdr->m_nMinX, poObjHdr->m_nMinY,
               poObjHdr->m_nMaxX, poObjHdr->m_nMaxY);
 
     /* Return a ref to coord block so that caller can continue reading
@@ -6629,7 +6670,7 @@ int TABMultiPoint::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
     poCoordBlock->SetComprCoordOrigin(m_nComprOrgX, m_nComprOrgY);
 
 
-    for(iPoint=0, nStatus=0; 
+    for(iPoint=0, nStatus=0;
         nStatus == 0 && iPoint < poMPointHdr->m_nNumPoints; iPoint++)
     {
         poGeom = poMPoint->getGeometryRef(iPoint);
@@ -6646,12 +6687,12 @@ int TABMultiPoint::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
                 poMPointHdr->m_nLabelY = nY;
             }
 
-            if ((nStatus = poCoordBlock->WriteIntCoord(nX, nY, 
+            if ((nStatus = poCoordBlock->WriteIntCoord(nX, nY,
                                                        bCompressed)) != 0)
             {
                 // Failed ... error message has already been produced
                 return nStatus;
-            }   
+            }
 
         }
         else
@@ -6677,7 +6718,7 @@ int TABMultiPoint::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
     double dX, dY;
     if (GetCenter(dX, dY) != -1)
     {
-        poMapFile->Coordsys2Int(dX, dY, poMPointHdr->m_nLabelX, 
+        poMapFile->Coordsys2Int(dX, dY, poMPointHdr->m_nLabelX,
                                 poMPointHdr->m_nLabelY);
     }
 
@@ -6786,7 +6827,7 @@ const char *TABMultiPoint::GetStyleString()
 /**********************************************************************
  *                   TABMultiPoint::GetCenter()
  *
- * Returns the center point (or label point?) of the object.  Compute one 
+ * Returns the center point (or label point?) of the object.  Compute one
  * if it was not explicitly set:
  *
  * The default seems to be to use the first point in the collection as
@@ -6944,7 +6985,7 @@ void TABCollection::EmptyCollection()
  *
  * Duplicate feature, including stuff specific to each TABFeature type.
  *
- * This method calls the generic TABFeature::CloneTABFeature() and 
+ * This method calls the generic TABFeature::CloneTABFeature() and
  * then copies any members specific to its own type.
  **********************************************************************/
 TABFeature *TABCollection::CloneTABFeature(OGRFeatureDefn *poNewDefn /*=NULL*/)
@@ -6986,11 +7027,11 @@ TABFeature *TABCollection::CloneTABFeature(OGRFeatureDefn *poNewDefn /*=NULL*/)
 TABGeomType TABCollection::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
 {
     OGRGeometry *poGeom;
-    int nRegionType=TAB_GEOM_NONE, nPLineType=TAB_GEOM_NONE, 
+    int nRegionType=TAB_GEOM_NONE, nPLineType=TAB_GEOM_NONE,
         nMPointType=TAB_GEOM_NONE, nVersion = 650;
 
     /*-----------------------------------------------------------------
-     * Fetch and validate geometry 
+     * Fetch and validate geometry
      *----------------------------------------------------------------*/
     poGeom = GetGeometryRef();
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbGeometryCollection)
@@ -7012,7 +7053,7 @@ TABGeomType TABCollection::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
     /*-----------------------------------------------------------------
      * Since all members of the collection share the same compressed coord
      * origin, we should force the compressed origin in all components
-     * to be the same. 
+     * to be the same.
      * This also implies that ValidateMapInfoType() should *NOT* be called
      * again until the collection components are written by WriteGeom...()
      *----------------------------------------------------------------*/
@@ -7054,7 +7095,7 @@ TABGeomType TABCollection::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
     {
         GInt32 nXMin=0, nYMin=0, nXMax=0, nYMax=0;
         m_poRegion->GetIntMBR(nXMin, nYMin, nXMax, nYMax);
-        m_poRegion->ForceCoordTypeAndOrigin((nVersion == 800 ? 
+        m_poRegion->ForceCoordTypeAndOrigin((nVersion == 800 ?
                                              TAB_GEOM_V800_REGION:
                                              TAB_GEOM_V450_REGION),
                                             bComprCoord,
@@ -7067,7 +7108,7 @@ TABGeomType TABCollection::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
     {
         GInt32 nXMin, nYMin, nXMax, nYMax;
         m_poPline->GetIntMBR(nXMin, nYMin, nXMax, nYMax);
-        m_poPline->ForceCoordTypeAndOrigin((nVersion == 800 ? 
+        m_poPline->ForceCoordTypeAndOrigin((nVersion == 800 ?
                                             TAB_GEOM_V800_MULTIPLINE:
                                             TAB_GEOM_V450_MULTIPLINE),
                                            bComprCoord,
@@ -7079,7 +7120,7 @@ TABGeomType TABCollection::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
     {
         GInt32 nXMin, nYMin, nXMax, nYMax;
         m_poMpoint->GetIntMBR(nXMin, nYMin, nXMax, nYMax);
-        m_poMpoint->ForceCoordTypeAndOrigin((nVersion == 800 ? 
+        m_poMpoint->ForceCoordTypeAndOrigin((nVersion == 800 ?
                                              TAB_GEOM_V800_MULTIPOINT:
                                              TAB_GEOM_MULTIPOINT),
                                             bComprCoord,
@@ -7108,7 +7149,7 @@ int  TABCollection::ReadLabelAndMBR(TABMAPCoordBlock *poCoordBlock,
 {
     //
     // The sections in the collection's coord blocks start with center/label
-    // point + MBR that are normally found in the object data blocks 
+    // point + MBR that are normally found in the object data blocks
     // of regular region/pline/mulitpoint objects.
     //
 
@@ -7119,13 +7160,17 @@ int  TABCollection::ReadLabelAndMBR(TABMAPCoordBlock *poCoordBlock,
         pnLabelX = poCoordBlock->ReadInt16();
         pnLabelY = poCoordBlock->ReadInt16();
 
-        pnLabelX += nComprOrgX;
-        pnLabelY += nComprOrgY;
+        TABSaturatedAdd(pnLabelX, nComprOrgX);
+        TABSaturatedAdd(pnLabelY, nComprOrgY);
 
-        pnMinX = nComprOrgX + poCoordBlock->ReadInt16(); // Read MBR
-        pnMinY = nComprOrgY + poCoordBlock->ReadInt16();
-        pnMaxX = nComprOrgX + poCoordBlock->ReadInt16();
-        pnMaxY = nComprOrgY + poCoordBlock->ReadInt16();
+        pnMinX = poCoordBlock->ReadInt16(); // Read MBR
+        pnMinY = poCoordBlock->ReadInt16();
+        pnMaxX = poCoordBlock->ReadInt16();
+        pnMaxY = poCoordBlock->ReadInt16();
+        TABSaturatedAdd(pnMinX, nComprOrgX);
+        TABSaturatedAdd(pnMinY, nComprOrgY);
+        TABSaturatedAdd(pnMaxX, nComprOrgX);
+        TABSaturatedAdd(pnMaxY, nComprOrgY);
     }
     else
     {
@@ -7160,20 +7205,20 @@ int  TABCollection::WriteLabelAndMBR(TABMAPCoordBlock *poCoordBlock,
 
     //
     // The sections in the collection's coord blocks start with center/label
-    // point + MBR that are normally found in the object data blocks 
+    // point + MBR that are normally found in the object data blocks
     // of regular region/pline/mulitpoint objects.
     //
 
-    if ((nStatus = poCoordBlock->WriteIntCoord(nLabelX, nLabelY, 
+    if ((nStatus = poCoordBlock->WriteIntCoord(nLabelX, nLabelY,
                                                bComprCoord)) != 0 ||
-        (nStatus = poCoordBlock->WriteIntCoord(nMinX, nMinY, 
+        (nStatus = poCoordBlock->WriteIntCoord(nMinX, nMinY,
                                                bComprCoord)) != 0 ||
-        (nStatus = poCoordBlock->WriteIntCoord(nMaxX, nMaxY, 
+        (nStatus = poCoordBlock->WriteIntCoord(nMaxX, nMaxY,
                                                bComprCoord)) != 0   )
     {
         // Failed ... error message has already been produced
         return nStatus;
-    }   
+    }
 
     return 0;
 }
@@ -7228,14 +7273,14 @@ int TABCollection::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     TABMAPObjCollection *poCollHdr = (TABMAPObjCollection *)poObjHdr;
 
     // MBR
-    poMapFile->Int2Coordsys(poCollHdr->m_nMinX, poCollHdr->m_nMinY, 
+    poMapFile->Int2Coordsys(poCollHdr->m_nMinX, poCollHdr->m_nMinY,
                             dXMin, dYMin);
-    poMapFile->Int2Coordsys(poCollHdr->m_nMaxX, poCollHdr->m_nMaxY, 
+    poMapFile->Int2Coordsys(poCollHdr->m_nMaxX, poCollHdr->m_nMaxY,
                             dXMax, dYMax);
 
     SetMBR(dXMin, dYMin, dXMax, dYMax);
 
-    SetIntMBR(poObjHdr->m_nMinX, poObjHdr->m_nMinY, 
+    SetIntMBR(poObjHdr->m_nMinX, poObjHdr->m_nMinY,
               poObjHdr->m_nMaxX, poObjHdr->m_nMaxY);
 
     nCurCoordBlockPtr = poCollHdr->m_nCoordBlockPtr;
@@ -7251,7 +7296,7 @@ int TABCollection::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     /*-----------------------------------------------------------------
      * Region Component
      *----------------------------------------------------------------*/
-    if(poCollHdr->m_nNumRegSections > 0)
+    if(poCoordBlock != NULL && poCollHdr->m_nNumRegSections > 0)
     {
         //
         // Build fake coord section header to pass to TABRegion::ReadGeom...()
@@ -7263,7 +7308,7 @@ int TABCollection::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
 
         //
         // The region section in the coord block starts with center/label
-        // point + MBR that are normally found in the object data blocks 
+        // point + MBR that are normally found in the object data blocks
         // of regular region objects.
         //
 
@@ -7300,21 +7345,21 @@ int TABCollection::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
         // Use a TABRegion to read/store the Region coord data
         //
         m_poRegion = new TABRegion(GetDefnRef());
-        if (m_poRegion->ReadGeometryFromMAPFile(poMapFile, &oRegionHdr, 
-                                                bCoordBlockDataOnly, 
+        if (m_poRegion->ReadGeometryFromMAPFile(poMapFile, &oRegionHdr,
+                                                bCoordBlockDataOnly,
                                                 &poCoordBlock) != 0)
             return -1;
 
         // Set new coord block ptr for next object
-        if (poCoordBlock)
-            nCurCoordBlockPtr = poCoordBlock->GetCurAddress();
+        /*if (poCoordBlock)
+            nCurCoordBlockPtr = poCoordBlock->GetCurAddress();*/
     }
 
 
     /*-----------------------------------------------------------------
      * PLine Component
      *----------------------------------------------------------------*/
-    if(poCollHdr->m_nNumPLineSections > 0)
+    if(poCoordBlock != NULL && poCollHdr->m_nNumPLineSections > 0)
     {
         //
         // Build fake coord section header to pass to TABPolyline::ReadGeom..()
@@ -7326,7 +7371,7 @@ int TABCollection::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
 
         //
         // The pline section in the coord block starts with center/label
-        // point + MBR that are normally found in the object data blocks 
+        // point + MBR that are normally found in the object data blocks
         // of regular pline objects.
         //
 
@@ -7352,7 +7397,7 @@ int TABCollection::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
         else
             oPLineHdr.m_nType = TAB_GEOM_V450_MULTIPLINE;
         if (nVersion == 800)
-            oPLineHdr.m_nType = (TABGeomType) (oPLineHdr.m_nType + (TAB_GEOM_V800_MULTIPLINE - 
+            oPLineHdr.m_nType = (TABGeomType) (oPLineHdr.m_nType + (TAB_GEOM_V800_MULTIPLINE -
                                   TAB_GEOM_V450_MULTIPLINE));
 
         oPLineHdr.m_numLineSections = poCollHdr->m_nNumPLineSections;
@@ -7363,20 +7408,20 @@ int TABCollection::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
         // Use a TABPolyline to read/store the Polyline coord data
         //
         m_poPline = new TABPolyline(GetDefnRef());
-        if (m_poPline->ReadGeometryFromMAPFile(poMapFile, &oPLineHdr, 
+        if (m_poPline->ReadGeometryFromMAPFile(poMapFile, &oPLineHdr,
                                                bCoordBlockDataOnly,
                                                &poCoordBlock) != 0)
             return -1;
 
         // Set new coord block ptr for next object
-        if (poCoordBlock)
-            nCurCoordBlockPtr = poCoordBlock->GetCurAddress();
+        /*if (poCoordBlock)
+            nCurCoordBlockPtr = poCoordBlock->GetCurAddress();*/
     }
 
     /*-----------------------------------------------------------------
      * MultiPoint Component
      *----------------------------------------------------------------*/
-    if(poCollHdr->m_nNumMultiPoints > 0)
+    if(poCoordBlock != NULL && poCollHdr->m_nNumMultiPoints > 0)
     {
         //
         // Build fake coord section header to pass to TABMultiPoint::ReadGeom()
@@ -7388,7 +7433,7 @@ int TABCollection::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
 
         //
         // The pline section in the coord block starts with center/label
-        // point + MBR that are normally found in the object data blocks 
+        // point + MBR that are normally found in the object data blocks
         // of regular pline objects.
         //
         ReadLabelAndMBR(poCoordBlock, bComprCoord,
@@ -7405,7 +7450,7 @@ int TABCollection::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
         else
             oMPointHdr.m_nType = TAB_GEOM_MULTIPOINT;
         if (nVersion == 800)
-            oMPointHdr.m_nType = (TABGeomType) (oMPointHdr.m_nType + (TAB_GEOM_V800_MULTIPOINT - 
+            oMPointHdr.m_nType = (TABGeomType) (oMPointHdr.m_nType + (TAB_GEOM_V800_MULTIPOINT -
                                   TAB_GEOM_MULTIPOINT));
 
         oMPointHdr.m_nNumPoints = poCollHdr->m_nNumMultiPoints;
@@ -7415,18 +7460,18 @@ int TABCollection::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
         // Use a TABMultiPoint to read/store the coord data
         //
         m_poMpoint = new TABMultiPoint(GetDefnRef());
-        if (m_poMpoint->ReadGeometryFromMAPFile(poMapFile, &oMPointHdr, 
+        if (m_poMpoint->ReadGeometryFromMAPFile(poMapFile, &oMPointHdr,
                                                 bCoordBlockDataOnly,
                                                 &poCoordBlock) != 0)
             return -1;
 
         // Set new coord block ptr for next object (not really useful here)
-        if (poCoordBlock)
-            nCurCoordBlockPtr = poCoordBlock->GetCurAddress();
+        /*if (poCoordBlock)
+            nCurCoordBlockPtr = poCoordBlock->GetCurAddress();*/
     }
-    
+
     /*-----------------------------------------------------------------
-     * Set the main OGRFeature Geometry 
+     * Set the main OGRFeature Geometry
      * (this is actually duplicating geometries from each member)
      *----------------------------------------------------------------*/
     if (SyncOGRGeometryCollection(TRUE, TRUE, TRUE) != 0)
@@ -7460,12 +7505,12 @@ int TABCollection::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
     /*-----------------------------------------------------------------
      * Note that the current implementation does not allow setting the
      * Geometry via OGRFeature::SetGeometry(). The geometries must be set
-     * via the SetRegion/Pline/MpointDirectly() methods which will take 
+     * via the SetRegion/Pline/MpointDirectly() methods which will take
      * care of keeping the OGRFeature's geometry in sync.
-     * 
+     *
      * TODO: If we ever want to support sync'ing changes from the OGRFeature's
      * geometry to the m_poRegion/Pline/Mpoint then a call should be added
-     * here, or perhaps in ValidateMapInfoType(), or even better in 
+     * here, or perhaps in ValidateMapInfoType(), or even better in
      * custom TABCollection::SetGeometry*()... but then this last option
      * won't work unless OGRFeature::SetGeometry*() are made virtual in OGR.
      *----------------------------------------------------------------*/
@@ -7482,7 +7527,7 @@ int TABCollection::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
     /*-----------------------------------------------------------------
      * Write data to coordinate block for each component...
      *
-     * Note that at this point, the caller (TABFile) has called 
+     * Note that at this point, the caller (TABFile) has called
      * TABCollection::ValidateMapInfoType() which in turn has called
      * each component's respective ValidateMapInfoType() and
      * ForceCoordTypeAndCoordOrigin() so the objects are ready to have
@@ -7523,8 +7568,8 @@ int TABCollection::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
         // Write a placeholder for centroid/label point and MBR mini-header
         // and we'll come back later to write the real values.
         //
-        // Note that the call to WriteGeometryToMAPFile() below will call 
-        // StartNewFeature() as well, so we need to track the current 
+        // Note that the call to WriteGeometryToMAPFile() below will call
+        // StartNewFeature() as well, so we need to track the current
         // value before calling it
 
         poCoordBlock->StartNewFeature();
@@ -7567,7 +7612,7 @@ int TABCollection::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
             poCoordBlock->WriteInt32(poRegionHdr->m_numLineSections);
         }
         WriteLabelAndMBR(poCoordBlock, bCompressed,
-                         poRegionHdr->m_nMinX, poRegionHdr->m_nMinY, 
+                         poRegionHdr->m_nMinX, poRegionHdr->m_nMinY,
                          poRegionHdr->m_nMaxX, poRegionHdr->m_nMaxY,
                          poRegionHdr->m_nLabelX, poRegionHdr->m_nLabelY);
 
@@ -7590,7 +7635,7 @@ int TABCollection::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
             poCollHdr->m_nRegionBrushId  = poRegionHdr->m_nBrushId;
             // TODO: Smooth flag         = poRegionHdr->m_bSmooth;
         }
-        
+
         delete poRegionHdr;
     }
     else
@@ -7623,8 +7668,8 @@ int TABCollection::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
         // Write a placeholder for centroid/label point and MBR mini-header
         // and we'll come back later to write the real values.
         //
-        // Note that the call to WriteGeometryToMAPFile() below will call 
-        // StartNewFeature() as well, so we need to track the current 
+        // Note that the call to WriteGeometryToMAPFile() below will call
+        // StartNewFeature() as well, so we need to track the current
         // value before calling it
 
         poCoordBlock->StartNewFeature();
@@ -7667,7 +7712,7 @@ int TABCollection::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
             poCoordBlock->WriteInt32(poPlineHdr->m_numLineSections);
         }
         WriteLabelAndMBR(poCoordBlock, bCompressed,
-                         poPlineHdr->m_nMinX, poPlineHdr->m_nMinY, 
+                         poPlineHdr->m_nMinX, poPlineHdr->m_nMinY,
                          poPlineHdr->m_nMaxX, poPlineHdr->m_nMaxY,
                          poPlineHdr->m_nLabelX, poPlineHdr->m_nLabelY);
 
@@ -7689,7 +7734,7 @@ int TABCollection::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
             // TODO: Smooth flag           = poPlineHdr->m_bSmooth;
         }
 
-        delete poPlineHdr;        
+        delete poPlineHdr;
     }
     else
     {
@@ -7721,8 +7766,8 @@ int TABCollection::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
         // Write a placeholder for centroid/label point and MBR mini-header
         // and we'll come back later to write the real values.
         //
-        // Note that the call to WriteGeometryToMAPFile() below will call 
-        // StartNewFeature() as well, so we need to track the current 
+        // Note that the call to WriteGeometryToMAPFile() below will call
+        // StartNewFeature() as well, so we need to track the current
         // value before calling it
 
         poCoordBlock->StartNewFeature();
@@ -7755,7 +7800,7 @@ int TABCollection::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
         }
 
         WriteLabelAndMBR(poCoordBlock, bCompressed,
-                         poMpointHdr->m_nMinX, poMpointHdr->m_nMinY, 
+                         poMpointHdr->m_nMinX, poMpointHdr->m_nMinY,
                          poMpointHdr->m_nMaxX, poMpointHdr->m_nMaxY,
                          poMpointHdr->m_nLabelX, poMpointHdr->m_nLabelY);
 
@@ -7776,7 +7821,7 @@ int TABCollection::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
             poCollHdr->m_nMultiPointSymbolId = poMpointHdr->m_nSymbolId;
         }
 
-        delete poMpointHdr;        
+        delete poMpointHdr;
     }
     else
     {
@@ -7830,8 +7875,7 @@ int    TABCollection::SyncOGRGeometryCollection(GBool bSyncRegion,
     // poGeometry is defined in the OGRFeature class
     if (poThisGeom == NULL)
     {
-        poThisGeom = poGeomColl = new OGRGeometryCollection();
-        SetGeometryDirectly(poGeomColl);
+        poGeomColl = new OGRGeometryCollection();
     }
     else if (wkbFlatten(poThisGeom->getGeometryType())==wkbGeometryCollection)
     {
@@ -7846,7 +7890,7 @@ int    TABCollection::SyncOGRGeometryCollection(GBool bSyncRegion,
 
     /*-----------------------------------------------------------------
      * Start by removing geometries that need to be replaced
-     * In theory there should be a single geometry of each type, but 
+     * In theory there should be a single geometry of each type, but
      * just in case, we'll loop over the whole collection and delete all
      * instances of each type if there are some.
      *----------------------------------------------------------------*/
@@ -7857,13 +7901,13 @@ int    TABCollection::SyncOGRGeometryCollection(GBool bSyncRegion,
         if (!poGeom)
             continue;
 
-        if ( (bSyncRegion && 
+        if ( (bSyncRegion &&
               (wkbFlatten(poGeom->getGeometryType()) == wkbPolygon ||
                wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon) ) ||
-             (bSyncPline && 
+             (bSyncPline &&
               (wkbFlatten(poGeom->getGeometryType()) == wkbLineString ||
                wkbFlatten(poGeom->getGeometryType()) == wkbMultiLineString)) ||
-             (bSyncMpoint && 
+             (bSyncMpoint &&
               (wkbFlatten(poGeom->getGeometryType()) == wkbMultiPoint) ) )
         {
             // Remove this geometry
@@ -7884,13 +7928,16 @@ int    TABCollection::SyncOGRGeometryCollection(GBool bSyncRegion,
      *----------------------------------------------------------------*/
     if(bSyncRegion && m_poRegion && m_poRegion->GetGeometryRef() != NULL)
         poGeomColl->addGeometry(m_poRegion->GetGeometryRef());
-    
+
     if(bSyncPline && m_poPline && m_poPline->GetGeometryRef() != NULL)
         poGeomColl->addGeometry(m_poPline->GetGeometryRef());
 
     if(bSyncMpoint && m_poMpoint && m_poMpoint->GetGeometryRef() != NULL)
         poGeomColl->addGeometry(m_poMpoint->GetGeometryRef());
 
+    if( poThisGeom == NULL )
+        SetGeometryDirectly(poGeomColl);
+
     return 0;
 }
 
@@ -7980,7 +8027,7 @@ const char *TABCollection::GetStyleString()
 /**********************************************************************
  *                   TABCollection::DumpMIF()
  *
- * Dump feature geometry 
+ * Dump feature geometry
  **********************************************************************/
 void TABCollection::DumpMIF(FILE *fpOut /*=NULL*/)
 {
@@ -8024,6 +8071,9 @@ void TABCollection::DumpMIF(FILE *fpOut /*=NULL*/)
 TABDebugFeature::TABDebugFeature(OGRFeatureDefn *poDefnIn):
               TABFeature(poDefnIn)
 {
+    m_nSize = 0;
+    m_nCoordDataPtr = 0;
+    m_nCoordDataSize = 0;
 }
 
 /**********************************************************************
@@ -8049,7 +8099,7 @@ TABDebugFeature::~TABDebugFeature()
  **********************************************************************/
 int TABDebugFeature::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
                                              TABMAPObjHdr *poObjHdr,
-                                             GBool /*bCoordBlockDataOnly=FALSE*/, 
+                                             GBool /*bCoordBlockDataOnly=FALSE*/,
                                              TABMAPCoordBlock ** /*ppoCoordBlock=NULL*/)
 {
     TABMAPObjectBlock   *poObjBlock;
@@ -8064,7 +8114,7 @@ int TABDebugFeature::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     poHeader = poMapFile->GetHeaderBlock();
 
     /*-----------------------------------------------------------------
-     * If object type has coords in a type 3 block, then its position 
+     * If object type has coords in a type 3 block, then its position
      * follows
      *----------------------------------------------------------------*/
     if (poHeader->MapObjectUsesCoordBlock(m_nMapInfoType))
@@ -8101,7 +8151,7 @@ int TABDebugFeature::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
  **********************************************************************/
 int TABDebugFeature::WriteGeometryToMAPFile(TABMAPFile * /*poMapFile*/,
                                             TABMAPObjHdr * /*poObjHdr*/,
-                                            GBool /*bCoordBlockDataOnly=FALSE*/, 
+                                            GBool /*bCoordBlockDataOnly=FALSE*/,
                                             TABMAPCoordBlock ** /*ppoCoordBlock=NULL*/)
 {
     // Nothing to do here!
@@ -8166,13 +8216,13 @@ ITABFeaturePen::ITABFeaturePen()
  *                   ITABFeaturePen::GetPenWidthPoint()
  *                   ITABFeaturePen::SetPenWidthPoint()
  *
- * Pen width can be expressed in pixels (value from 1 to 7 pixels) or 
- * in points (value from 0.1 to 203.7 points). The default pen width 
+ * Pen width can be expressed in pixels (value from 1 to 7 pixels) or
+ * in points (value from 0.1 to 203.7 points). The default pen width
  * in MapInfo is 1 pixel.  Pen width in points exist only in file version 450.
  *
  * The following methods hide the way the pen width is stored in the files.
  *
- * In order to establish if a given pen def had its width specified in 
+ * In order to establish if a given pen def had its width specified in
  * pixels or in points, one should first call GetPenWidthPoint(), and if
  * it returns 0 then the Pixel width should be used instead:
  *    if (GetPenWidthPoint() == 0)
@@ -8180,7 +8230,7 @@ ITABFeaturePen::ITABFeaturePen()
  *    else
  *       ... use Pixel width from GetPenWidthPixel()
  *
- * Note that the reverse is not true: the default pixel width is always 1, 
+ * Note that the reverse is not true: the default pixel width is always 1,
  * even when the pen width was actually set in points.
  **********************************************************************/
 
@@ -8189,7 +8239,7 @@ GByte ITABFeaturePen::GetPenWidthPixel()
     return m_sPenDef.nPixelWidth;
 }
 
-void  ITABFeaturePen::SetPenWidthPixel(GByte val) 
+void  ITABFeaturePen::SetPenWidthPixel(GByte val)
 {
     m_sPenDef.nPixelWidth = MIN(MAX(val, 1), 7);
     m_sPenDef.nPointWidth = 0;
@@ -8201,7 +8251,7 @@ double ITABFeaturePen::GetPenWidthPoint()
     return m_sPenDef.nPointWidth/10.0;
 }
 
-void  ITABFeaturePen::SetPenWidthPoint(double val) 
+void  ITABFeaturePen::SetPenWidthPoint(double val)
 {
     m_sPenDef.nPointWidth = MIN(MAX(((int)(val*10)), 1), 2037);
     m_sPenDef.nPixelWidth = 1;
@@ -8221,7 +8271,7 @@ int     ITABFeaturePen::GetPenWidthMIF()
              (m_sPenDef.nPointWidth+10): m_sPenDef.nPixelWidth );
 }
 
-void  ITABFeaturePen::SetPenWidthMIF(int val) 
+void  ITABFeaturePen::SetPenWidthMIF(int val)
 {
     if (val > 10)
     {
@@ -8245,20 +8295,20 @@ const char *ITABFeaturePen::GetPenStyleString()
     const char *pszStyle = NULL;
     int    nOGRStyle  = 0;
     char szPattern[20];
-    
+
     szPattern[0] = '\0';
 
-    // For now, I only add the 25 first styles 
+    // For now, I only add the 25 first styles
     switch (GetPenPattern())
     {
       case 1:
-        nOGRStyle =1; 
+        nOGRStyle =1;
         break;
       case 2:
         nOGRStyle = 0;
         break;
       case 3:
-        nOGRStyle = 3; 
+        nOGRStyle = 3;
         strcpy(szPattern,"1 1");
         break;
       case 4:
@@ -8407,14 +8457,14 @@ void  ITABFeaturePen::SetPenFromStyleString(const char *pszStyleString)
     int   nPenId;
     const char* pszPenId;
 
-    // Use the Style Manager to retreive all the information we need.
+    // Use the Style Manager to retrieve all the information we need.
     OGRStyleMgr *poStyleMgr = new OGRStyleMgr(NULL);
-    OGRStyleTool *poStylePart;
+    OGRStyleTool *poStylePart = NULL;
 
     // Init the StyleMgr with the StyleString.
     poStyleMgr->InitStyleString(pszStyleString);
 
-    // Retreive the Pen info.
+    // Retrieve the Pen info.
     numParts = poStyleMgr->GetPartCount();
     for(i=0; i<numParts; i++)
     {
@@ -8434,7 +8484,7 @@ void  ITABFeaturePen::SetPenFromStyleString(const char *pszStyleString)
     }
 
     // If the no Pen found, do nothing.
-    if(i >= numParts)
+    if(poStylePart == NULL)
     {
         delete poStyleMgr;
         return;
@@ -8446,8 +8496,8 @@ void  ITABFeaturePen::SetPenFromStyleString(const char *pszStyleString)
     // so just use points).
     //
     // It's very important to set the output unit of the feature.
-    // The default value is meter. If we don't do it all numerical values 
-    // will be assumed to be converted from the input unit to meter when we 
+    // The default value is meter. If we don't do it all numerical values
+    // will be assumed to be converted from the input unit to meter when we
     // will get them via GetParam...() functions.
     // See OGRStyleTool::Parse() for more details.
     poPenStyle->SetUnit(OGRSTUPoints, 1);
@@ -8474,12 +8524,12 @@ void  ITABFeaturePen::SetPenFromStyleString(const char *pszStyleString)
         if(pszPenColor[0] == '#')
             pszPenColor++;
         // The Pen color is an Hexa string that need to be convert in a int
-        nPenColor = strtol(pszPenColor, NULL, 16);
+        nPenColor = static_cast<int>(strtol(pszPenColor, NULL, 16));
         SetPenColor(nPenColor);
     }
 
     // Set the Id of the Pen, use Pattern if necessary.
-    if(pszPenName && 
+    if(pszPenName &&
        (strstr(pszPenName, "mapinfo-pen-") || strstr(pszPenName, "ogr-pen-")) )
     {
         pszPenId = strstr(pszPenName, "mapinfo-pen-");
@@ -8502,7 +8552,7 @@ void  ITABFeaturePen::SetPenFromStyleString(const char *pszStyleString)
     }
     else
     {
-        // If no Pen Id, use the Pen Pattern to retreive the Id.
+        // If no Pen Id, use the Pen Pattern to retrieve the Id.
         pszPenPattern = poPenStyle->Pattern(bIsNull);
         if (bIsNull)
             pszPenPattern = NULL;
@@ -8629,7 +8679,6 @@ const char *ITABFeatureBrush::GetBrushStyleString()
       nOGRStyle = 6;
     else if (m_sBrushDef.nFillPattern == 8)
       nOGRStyle = 7;
-          
 
     if (GetBrushTransparent())
     {
@@ -8647,8 +8696,7 @@ const char *ITABFeatureBrush::GetBrushStyleString()
     }
 
      return pszStyle;
-    
-}  
+}
 
 
 /**********************************************************************
@@ -8668,14 +8716,14 @@ void  ITABFeatureBrush::SetBrushFromStyleString(const char *pszStyleString)
     const char *pszBrushColor;
     int nBrushColor;
 
-    // Use the Style Manager to retreive all the information we need.
+    // Use the Style Manager to retrieve all the information we need.
     OGRStyleMgr *poStyleMgr = new OGRStyleMgr(NULL);
-    OGRStyleTool *poStylePart;
+    OGRStyleTool *poStylePart = NULL;
 
     // Init the StyleMgr with the StyleString.
     poStyleMgr->InitStyleString(pszStyleString);
 
-    // Retreive the Brush info.
+    // Retrieve the Brush info.
     numParts = poStyleMgr->GetPartCount();
     for(i=0; i<numParts; i++)
     {
@@ -8695,7 +8743,7 @@ void  ITABFeatureBrush::SetBrushFromStyleString(const char *pszStyleString)
     }
 
     // If the no Brush found, do nothing.
-    if(i >= numParts)
+    if(poStylePart == NULL)
     {
         delete poStyleMgr;
         return;
@@ -8707,8 +8755,8 @@ void  ITABFeatureBrush::SetBrushFromStyleString(const char *pszStyleString)
     pszBrushId = poBrushStyle->Id(bIsNull);
     if(bIsNull) pszBrushId = NULL;
 
-    if(pszBrushId && 
-       (strstr(pszBrushId, "mapinfo-brush-") || 
+    if(pszBrushId &&
+       (strstr(pszBrushId, "mapinfo-brush-") ||
         strstr(pszBrushId, "ogr-brush-")) )
     {
         if(strstr(pszBrushId, "mapinfo-brush-"))
@@ -8733,7 +8781,7 @@ void  ITABFeatureBrush::SetBrushFromStyleString(const char *pszStyleString)
     {
         if(pszBrushColor[0] == '#')
             pszBrushColor++;
-        nBrushColor = strtol(pszBrushColor, NULL, 16);
+        nBrushColor = static_cast<int>(strtol(pszBrushColor, NULL, 16));
         SetBrushBGColor((GInt32)nBrushColor);
     }
     else
@@ -8749,7 +8797,7 @@ void  ITABFeatureBrush::SetBrushFromStyleString(const char *pszStyleString)
     {
         if(pszBrushColor[0] == '#')
             pszBrushColor++;
-        nBrushColor = strtol(pszBrushColor, NULL, 16);
+        nBrushColor = static_cast<int>(strtol(pszBrushColor, NULL, 16));
         SetBrushFGColor((GInt32)nBrushColor);
     }
 
@@ -8757,7 +8805,7 @@ void  ITABFeatureBrush::SetBrushFromStyleString(const char *pszStyleString)
     delete poStylePart;
 
     return;
-}  
+}
 
 /**********************************************************************
  *                   ITABFeatureBrush::DumpBrushDef()
@@ -8771,9 +8819,9 @@ void ITABFeatureBrush::DumpBrushDef(FILE *fpOut /*=NULL*/)
 
     fprintf(fpOut, "  m_nBrushDefIndex         = %d\n", m_nBrushDefIndex);
     fprintf(fpOut, "  m_sBrushDef.nRefCount    = %d\n", m_sBrushDef.nRefCount);
-    fprintf(fpOut, "  m_sBrushDef.nFillPattern = %d\n", 
+    fprintf(fpOut, "  m_sBrushDef.nFillPattern = %d\n",
                                                 (int)m_sBrushDef.nFillPattern);
-    fprintf(fpOut, "  m_sBrushDef.bTransparentFill = %d\n", 
+    fprintf(fpOut, "  m_sBrushDef.bTransparentFill = %d\n",
                                             (int)m_sBrushDef.bTransparentFill);
     fprintf(fpOut, "  m_sBrushDef.rgbFGColor   = 0x%6.6x (%d)\n",
                                m_sBrushDef.rgbFGColor, m_sBrushDef.rgbFGColor);
@@ -8805,9 +8853,9 @@ ITABFeatureFont::ITABFeatureFont()
  *                   ITABFeatureFont::SetFontName()
  **********************************************************************/
 void ITABFeatureFont::SetFontName(const char *pszName)
-{ 
+{
     strncpy( m_sFontDef.szFontName, pszName, 32);
-    m_sFontDef.szFontName[32] = '\0';  
+    m_sFontDef.szFontName[32] = '\0';
 }
 
 /**********************************************************************
@@ -8909,17 +8957,16 @@ const char *ITABFeatureSymbol::GetSymbolStyleString(double dfAngle)
       nOGRStyle = 2;
 
     nAngle += (int)dfAngle;
-    
+
     pszStyle=CPLSPrintf("SYMBOL(a:%d,c:#%6.6x,s:%dpt,id:\"mapinfo-sym-%d,ogr-sym-%d\")",
                         nAngle,
                         m_sSymbolDef.rgbColor,
                         m_sSymbolDef.nPointSize,
                         m_sSymbolDef.nSymbolNo,
                         nOGRStyle);
-     
+
     return pszStyle;
-    
-}  
+}
 
 /**********************************************************************
  *                   ITABFeatureSymbol::SetSymbolFromStyleString()
@@ -8939,14 +8986,14 @@ void ITABFeatureSymbol::SetSymbolFromStyleString(const char *pszStyleString)
 
     double dSymbolSize;
 
-    // Use the Style Manager to retreive all the information we need.
+    // Use the Style Manager to retrieve all the information we need.
     OGRStyleMgr *poStyleMgr = new OGRStyleMgr(NULL);
-    OGRStyleTool *poStylePart;
+    OGRStyleTool *poStylePart = NULL;
 
     // Init the StyleMgr with the StyleString.
     poStyleMgr->InitStyleString(pszStyleString);
 
-    // Retreive the Symbol info.
+    // Retrieve the Symbol info.
     numParts = poStyleMgr->GetPartCount();
     for(i=0; i<numParts; i++)
     {
@@ -8966,7 +9013,7 @@ void ITABFeatureSymbol::SetSymbolFromStyleString(const char *pszStyleString)
     }
 
     // If the no Symbol found, do nothing.
-    if(i >= numParts)
+    if(poStylePart == NULL)
     {
         delete poStyleMgr;
         return;
@@ -8977,8 +9024,8 @@ void ITABFeatureSymbol::SetSymbolFromStyleString(const char *pszStyleString)
     // With Symbol, we always want to output points
     //
     // It's very important to set the output unit of the feature.
-    // The default value is meter. If we don't do it all numerical values 
-    // will be assumed to be converted from the input unit to meter when we 
+    // The default value is meter. If we don't do it all numerical values
+    // will be assumed to be converted from the input unit to meter when we
     // will get them via GetParam...() functions.
     // See OGRStyleTool::Parse() for more details.
     poSymbolStyle->SetUnit(OGRSTUPoints, (72.0 * 39.37));
@@ -8987,8 +9034,8 @@ void ITABFeatureSymbol::SetSymbolFromStyleString(const char *pszStyleString)
     pszSymbolId = poSymbolStyle->Id(bIsNull);
     if(bIsNull) pszSymbolId = NULL;
 
-    if(pszSymbolId &&  
-       (strstr(pszSymbolId, "mapinfo-sym-") || 
+    if(pszSymbolId &&
+       (strstr(pszSymbolId, "mapinfo-sym-") ||
         strstr(pszSymbolId, "ogr-sym-")) )
     {
         if(strstr(pszSymbolId, "mapinfo-sym-"))
@@ -9054,15 +9101,15 @@ void ITABFeatureSymbol::SetSymbolFromStyleString(const char *pszStyleString)
     {
         if(pszSymbolColor[0] == '#')
             pszSymbolColor++;
-        nSymbolColor = strtol(pszSymbolColor, NULL, 16);
+        nSymbolColor = static_cast<int>(strtol(pszSymbolColor, NULL, 16));
         SetSymbolColor((GInt32)nSymbolColor);
     }
 
     delete poStyleMgr;
     delete poStylePart;
-    
+
     return;
-}  
+}
 
 /**********************************************************************
  *                   ITABFeatureSymbol::DumpSymbolDef()
@@ -9078,7 +9125,7 @@ void ITABFeatureSymbol::DumpSymbolDef(FILE *fpOut /*=NULL*/)
     fprintf(fpOut, "  m_sSymbolDef.nRefCount  = %d\n", m_sSymbolDef.nRefCount);
     fprintf(fpOut, "  m_sSymbolDef.nSymbolNo  = %d\n", m_sSymbolDef.nSymbolNo);
     fprintf(fpOut, "  m_sSymbolDef.nPointSize = %d\n",m_sSymbolDef.nPointSize);
-    fprintf(fpOut, "  m_sSymbolDef._unknown_  = %d\n", 
+    fprintf(fpOut, "  m_sSymbolDef._unknown_  = %d\n",
                                             (int)m_sSymbolDef._nUnknownValue_);
     fprintf(fpOut, "  m_sSymbolDef.rgbColor   = 0x%6.6x (%d)\n",
                                 m_sSymbolDef.rgbColor, m_sSymbolDef.rgbColor);
diff --git a/ogr/ogrsf_frmts/mitab/mitab_feature_mif.cpp b/ogr/ogrsf_frmts/mitab/mitab_feature_mif.cpp
index b7c564c..64bd6bb 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_feature_mif.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_feature_mif.cpp
@@ -4,7 +4,7 @@
  * Name:     mitab_feature.cpp
  * Project:  MapInfo TAB Read/Write library
  * Language: C++
- * Purpose:  Implementation of R/W Fcts for (Mid/Mif) in feature classes 
+ * Purpose:  Implementation of R/W Fcts for (Mid/Mif) in feature classes
  *           specific to MapInfo files.
  * Author:   Stephane Villeneuve, stephane.v at videotron.ca
  *
@@ -17,16 +17,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -61,7 +61,7 @@
  * fixed Mills.mif reading, crash at file end
  *
  * Revision 1.30  2006/01/26 21:26:36  fwarmerdam
- * fixed bug with multi character delimeters in .mid file
+ * Fixed bug with multi-character delimiters in .mid file
  *
  * Revision 1.29  2005/10/04 19:36:10  dmorissette
  * Added support for reading collections from MIF files (bug 1126)
@@ -113,7 +113,7 @@
  * Include OGR StyleString stuff (implemented by Stephane)
  *
  * Revision 1.15  2000/09/28 16:39:44  warmerda
- * avoid warnings for unused, and unitialized variables
+ * Avoid warnings for unused, and uninitialized variables
  *
  * Revision 1.14  2000/09/19 17:23:53  daniel
  * Maintain and/or compute valid region and polyline center/label point
@@ -154,7 +154,7 @@
  * always return real corner radius from file even if it is bigger than MBR
  *
  * Revision 1.2  1999/11/11 01:22:05  stephane
- * Remove DebugFeature call, Point Reading error, add IsValidFeature() to 
+ * Remove DebugFeature call, Point Reading error, add IsValidFeature() to
  * test correctly if we are on a feature
  *
  * Revision 1.1  1999/11/08 19:20:30  stephane
@@ -178,7 +178,7 @@
 /*                            MIDTokenize()                             */
 /*                                                                      */
 /*      We implement a special tokenize function so we can handle       */
-/*      multibyte delimeters (ie. MITAB bug 1266).                      */
+/*      multi-byte delimiters (i.e. MITAB bug 1266).                      */
 /*                                                                      */
 /*      http://bugzilla.maptools.org/show_bug.cgi?id=1266               */
 /************************************************************************/
@@ -188,7 +188,7 @@ static char **MIDTokenize( const char *pszLine, const char *pszDelim )
     char **papszResult = NULL;
     int iChar, iTokenChar = 0, bInQuotes = FALSE;
     char *pszToken = (char *) CPLMalloc(strlen(pszLine)+1);
-    int nDelimLen = strlen(pszDelim);
+    int nDelimLen = static_cast<int>(strlen(pszDelim));
 
     for( iChar = 0; pszLine[iChar] != '\0'; iChar++ )
     {
@@ -205,8 +205,8 @@ static char **MIDTokenize( const char *pszLine, const char *pszDelim )
         {
             pszToken[iTokenChar++] = '\0';
             papszResult = CSLAddString( papszResult, pszToken );
-            
-            iChar += strlen(pszDelim) - 1;
+
+            iChar += static_cast<int>(strlen(pszDelim)) - 1;
             iTokenChar = 0;
         }
         else
@@ -228,7 +228,7 @@ static char **MIDTokenize( const char *pszLine, const char *pszDelim )
  *
  *  This method is used to read the Record (Attributs) for all type of
  *  feature included in a mid/mif file.
- * 
+ *
  * Returns 0 on success, -1 on error, in which case CPLError() will have
  * been called.
  **********************************************************************/
@@ -244,7 +244,7 @@ int TABFeature::ReadRecordFromMIDFile(MIDDATAFile *fp)
 #endif
 
     nFields = GetFieldCount();
-    
+
     pszLine = fp->GetLastLine();
 
     if (pszLine == NULL)
@@ -256,7 +256,7 @@ int TABFeature::ReadRecordFromMIDFile(MIDDATAFile *fp)
 
     papszToken = MIDTokenize( pszLine, fp->GetDelimiter() );
 
-    // Ensure that a blank line in a mid file is treated as one field 
+    // Ensure that a blank line in a mid file is treated as one field
     // containing an empty string.
     if( nFields == 1 && CSLCount(papszToken) == 0 && pszLine[0] == '\0' )
         papszToken = CSLAddString(papszToken,"");
@@ -282,7 +282,7 @@ int TABFeature::ReadRecordFromMIDFile(MIDDATAFile *fp)
                 if (strlen(papszToken[i]) == 9)
                 {
                     sscanf(papszToken[i],"%2d%2d%2d%3d",&nHour, &nMin, &nSec, &nMS);
-                    SetField(i, nYear, nMonth, nDay, nHour, nMin, nSec + nMS / 1000.0f,
+                    SetField(i, nYear, nMonth, nDay, nHour, nMin, static_cast<float>(nSec + nMS / 1000.0f),
                              0);
                 }
                 break;
@@ -292,7 +292,7 @@ int TABFeature::ReadRecordFromMIDFile(MIDDATAFile *fp)
                 if (strlen(papszToken[i]) == 8)
                 {
                     sscanf(papszToken[i], "%4d%2d%2d", &nYear, &nMonth, &nDay);
-                    SetField(i, nYear, nMonth, nDay, nHour, nMin, nSec, 0);
+                    SetField(i, nYear, nMonth, nDay, nHour, nMin, static_cast<float>(nSec), 0);
                 }
                 break;
             }
@@ -302,18 +302,18 @@ int TABFeature::ReadRecordFromMIDFile(MIDDATAFile *fp)
                 {
                     sscanf(papszToken[i], "%4d%2d%2d%2d%2d%2d%3d",
                            &nYear, &nMonth, &nDay, &nHour, &nMin, &nSec, &nMS);
-                    SetField(i, nYear, nMonth, nDay, nHour, nMin, nSec + nMS / 1000.0f,
+                    SetField(i, nYear, nMonth, nDay, nHour, nMin, static_cast<float>(nSec + nMS / 1000.0f),
                              0);
                 }
                 break;
             }
 #endif
-  
+
           default:
              SetField(i,papszToken[i]);
        }
     }
-    
+
     fp->GetLine();
 
     CSLDestroy(papszToken);
@@ -324,7 +324,7 @@ int TABFeature::ReadRecordFromMIDFile(MIDDATAFile *fp)
 /**********************************************************************
  *                   TABFeature::WriteRecordToMIDFile()
  *
- *  This methode is used to write the Record (Attributs) for all type
+ *  This method is used to write the Record (Attributes) for all type
  *  of feature included in a mid file.
  *
  *  Return 0 on success, -1 on error
@@ -341,7 +341,7 @@ int TABFeature::WriteRecordToMIDFile(MIDDATAFile *fp)
 #endif
 
     CPLAssert(fp);
-    
+
     const char *delimiter = fp->GetDelimiter();
 
     numFields = GetFieldCount();
@@ -354,15 +354,15 @@ int TABFeature::WriteRecordToMIDFile(MIDDATAFile *fp)
 
         switch(poFDefn->GetType())
         {
-          case OFTString: 
+          case OFTString:
           {
-            int nStringLen = strlen(GetFieldAsString(iField));
+            int nStringLen = static_cast<int>(strlen(GetFieldAsString(iField)));
             char *pszString = (char*)CPLMalloc((nStringLen+1)*sizeof(char));
             strcpy(pszString, GetFieldAsString(iField));
             char *pszWorkString = (char*)CPLMalloc((2*(nStringLen)+1)*sizeof(char));
             int j = 0;
             for (int i =0; i < nStringLen; ++i)
-            { 
+            {
               if (pszString[i] == '"')
               {
                 pszWorkString[j] = pszString[i];
@@ -379,7 +379,7 @@ int TABFeature::WriteRecordToMIDFile(MIDDATAFile *fp)
                 pszWorkString[j] = pszString[i];
               ++j;
             }
-            
+
             pszWorkString[j] = '\0';
             CPLFree(pszString);
             pszString = (char*)CPLMalloc((strlen(pszWorkString)+1)*sizeof(char));
@@ -392,7 +392,7 @@ int TABFeature::WriteRecordToMIDFile(MIDDATAFile *fp)
 #ifdef MITAB_USE_OFTDATETIME
           case OFTTime:
           {
-              if (!IsFieldSet(iField)) 
+              if (!IsFieldSet(iField))
               {
                  szBuffer[0] = '\0';
               }
@@ -400,7 +400,7 @@ int TABFeature::WriteRecordToMIDFile(MIDDATAFile *fp)
               {
                   GetFieldAsDateTime(iField, &nYear, &nMonth, &nDay,
                                      &nHour, &nMin, &fSec, &nTZFlag);
-                  sprintf(szBuffer, "%2.2d%2.2d%2.2d%3.3d", nHour, nMin,
+                  snprintf(szBuffer, sizeof(szBuffer), "%2.2d%2.2d%2.2d%3.3d", nHour, nMin,
                           (int)fSec, OGR_GET_MS(fSec));
               }
               fp->WriteLine("%s",szBuffer);
@@ -408,7 +408,7 @@ int TABFeature::WriteRecordToMIDFile(MIDDATAFile *fp)
           }
           case OFTDate:
           {
-              if (!IsFieldSet(iField)) 
+              if (!IsFieldSet(iField))
               {
                  szBuffer[0] = '\0';
               }
@@ -416,14 +416,14 @@ int TABFeature::WriteRecordToMIDFile(MIDDATAFile *fp)
               {
                   GetFieldAsDateTime(iField, &nYear, &nMonth, &nDay,
                                      &nHour, &nMin, &fSec, &nTZFlag);
-                  sprintf(szBuffer, "%4.4d%2.2d%2.2d", nYear, nMonth, nDay);
+                  snprintf(szBuffer, sizeof(szBuffer), "%4.4d%2.2d%2.2d", nYear, nMonth, nDay);
               }
               fp->WriteLine("%s",szBuffer);
               break;
           }
           case OFTDateTime:
           {
-              if (!IsFieldSet(iField)) 
+              if (!IsFieldSet(iField))
               {
                  szBuffer[0] = '\0';
               }
@@ -431,7 +431,7 @@ int TABFeature::WriteRecordToMIDFile(MIDDATAFile *fp)
               {
                   GetFieldAsDateTime(iField, &nYear, &nMonth, &nDay,
                                      &nHour, &nMin, &fSec, &nTZFlag);
-                  sprintf(szBuffer, "%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d%3.3d", 
+                  snprintf(szBuffer, sizeof(szBuffer), "%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d%3.3d",
                           nYear, nMonth, nDay, nHour, nMin,
                           (int)fSec, OGR_GET_MS(fSec));
               }
@@ -461,17 +461,17 @@ int TABFeature::WriteRecordToMIDFile(MIDDATAFile *fp)
  *
  * The current implementation does nothing since instances of TABFeature
  * objects contain no geometry (i.e. TAB_GEOM_NONE).
- * 
+ *
  * Returns 0 on success, -1 on error, in which case CPLError() will have
  * been called.
  **********************************************************************/
 int TABFeature::ReadGeometryFromMIFFile(MIDDATAFile *fp)
 {
     const char *pszLine;
-    
+
     /* Go to the first line of the next feature */
 
-    while (((pszLine = fp->GetLine()) != NULL) && 
+    while (((pszLine = fp->GetLine()) != NULL) &&
            fp->IsValidFeature(pszLine) == FALSE)
       ;
 
@@ -491,7 +491,7 @@ int TABFeature::ReadGeometryFromMIFFile(MIDDATAFile *fp)
  *
  * The current implementation does nothing since instances of TABFeature
  * objects contain no geometry.
- * 
+ *
  * Returns 0 on success, -1 on error, in which case CPLError() will have
  * been called.
  **********************************************************************/
@@ -505,21 +505,21 @@ int TABFeature::WriteGeometryToMIFFile(MIDDATAFile *fp)
  *
  **********************************************************************/
 int TABPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
-{  
+{
     OGRGeometry         *poGeometry;
-    
+
     char               **papszToken;
     const char *pszLine;
     double dfX,dfY;
-    papszToken = CSLTokenizeString2(fp->GetSavedLine(), 
+    papszToken = CSLTokenizeString2(fp->GetSavedLine(),
                                     " \t", CSLT_HONOURSTRINGS);
-     
+
     if (CSLCount(papszToken) !=3)
     {
         CSLDestroy(papszToken);
         return -1;
     }
-    
+
     dfX = fp->GetXTrans(CPLAtof(papszToken[1]));
     dfY = fp->GetYTrans(CPLAtof(papszToken[2]));
 
@@ -531,14 +531,14 @@ int TABPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
     if( pszLine != NULL )
         papszToken = CSLTokenizeStringComplex(pszLine," ,()\t",
                                               TRUE,FALSE);
-    if (CSLCount(papszToken) == 4 && EQUAL(papszToken[0], "SYMBOL") )
+    if (papszToken != NULL && CSLCount(papszToken) == 4 && EQUAL(papszToken[0], "SYMBOL") )
     {
         SetSymbolNo((GInt16)atoi(papszToken[1]));
         SetSymbolColor((GInt32)atoi(papszToken[2]));
         SetSymbolSize((GInt16)atoi(papszToken[3]));
     }
 
-    CSLDestroy(papszToken); 
+    CSLDestroy(papszToken);
     papszToken = NULL;
 
     // scan until we reach 1st line of next feature
@@ -548,25 +548,25 @@ int TABPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
     {
         pszLine = fp->GetLine();
     }
-    
+
     poGeometry = new OGRPoint(dfX, dfY);
-    
+
     SetGeometryDirectly(poGeometry);
 
     SetMBR(dfX, dfY, dfX, dfY);
-    
 
-    return 0; 
+
+    return 0;
 }
 
 /**********************************************************************
  *
  **********************************************************************/
 int TABPoint::WriteGeometryToMIFFile(MIDDATAFile *fp)
-{ 
+{
     OGRGeometry         *poGeom;
     OGRPoint            *poPoint;
- 
+
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
@@ -584,20 +584,20 @@ int TABPoint::WriteGeometryToMIFFile(MIDDATAFile *fp)
     fp->WriteLine("    Symbol (%d,%d,%d)\n",GetSymbolNo(),GetSymbolColor(),
                   GetSymbolSize());
 
-    return 0; 
+    return 0;
 }
 
 /**********************************************************************
  *
  **********************************************************************/
 int TABFontPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
-{   
+{
     OGRGeometry         *poGeometry;
-    
+
     char               **papszToken;
     const char *pszLine;
     double dfX,dfY;
-    papszToken = CSLTokenizeString2(fp->GetSavedLine(), 
+    papszToken = CSLTokenizeString2(fp->GetSavedLine(),
                                     " \t", CSLT_HONOURSTRINGS);
 
     if (CSLCount(papszToken) !=3)
@@ -608,9 +608,9 @@ int TABFontPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
 
     dfX = fp->GetXTrans(CPLAtof(papszToken[1]));
     dfY = fp->GetYTrans(CPLAtof(papszToken[2]));
-    
+
     CSLDestroy(papszToken);
-    
+
     papszToken = CSLTokenizeStringComplex(fp->GetLastLine()," ,()\t",
                                           TRUE,FALSE);
 
@@ -619,7 +619,7 @@ int TABFontPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
         CSLDestroy(papszToken);
         return -1;
     }
-    
+
     SetSymbolNo((GInt16)atoi(papszToken[1]));
     SetSymbolColor((GInt32)atoi(papszToken[2]));
     SetSymbolSize((GInt16)atoi(papszToken[3]));
@@ -628,29 +628,29 @@ int TABFontPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
     SetSymbolAngle(CPLAtof(papszToken[6]));
 
     CSLDestroy(papszToken);
-    
+
     poGeometry = new OGRPoint(dfX, dfY);
-    
+
     SetGeometryDirectly(poGeometry);
 
     SetMBR(dfX, dfY, dfX, dfY);
 
     /* Go to the first line of the next feature */
 
-    while (((pszLine = fp->GetLine()) != NULL) && 
+    while (((pszLine = fp->GetLine()) != NULL) &&
            fp->IsValidFeature(pszLine) == FALSE)
       ;
-    return 0; 
+    return 0;
 }
 
 /**********************************************************************
  *
  **********************************************************************/
 int TABFontPoint::WriteGeometryToMIFFile(MIDDATAFile *fp)
-{ 
+{
     OGRGeometry         *poGeom;
     OGRPoint            *poPoint;
- 
+
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
@@ -670,24 +670,24 @@ int TABFontPoint::WriteGeometryToMIFFile(MIDDATAFile *fp)
                   GetSymbolSize(),GetFontNameRef(),GetFontStyleMIFValue(),
                   GetSymbolAngle());
 
-    return 0; 
+    return 0;
 }
 
 /**********************************************************************
  *
  **********************************************************************/
 int TABCustomPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
-{   
+{
     OGRGeometry         *poGeometry;
-    
+
     char               **papszToken;
     const char          *pszLine;
     double               dfX,dfY;
 
-    papszToken = CSLTokenizeString2(fp->GetSavedLine(), 
+    papszToken = CSLTokenizeString2(fp->GetSavedLine(),
                                     " \t", CSLT_HONOURSTRINGS);
 
-    
+
     if (CSLCount(papszToken) !=3)
     {
         CSLDestroy(papszToken);
@@ -698,36 +698,36 @@ int TABCustomPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
     dfY = fp->GetYTrans(CPLAtof(papszToken[2]));
 
     CSLDestroy(papszToken);
-    
+
     papszToken = CSLTokenizeStringComplex(fp->GetLastLine()," ,()\t",
                                           TRUE,FALSE);
     if (CSLCount(papszToken) !=5)
     {
-        
+
         CSLDestroy(papszToken);
         return -1;
     }
-    
+
     SetFontName(papszToken[1]);
     SetSymbolColor((GInt32)atoi(papszToken[2]));
     SetSymbolSize((GInt16)atoi(papszToken[3]));
     m_nCustomStyle = (GByte)atoi(papszToken[4]);
-    
+
     CSLDestroy(papszToken);
-    
+
     poGeometry = new OGRPoint(dfX, dfY);
-    
+
     SetGeometryDirectly(poGeometry);
 
     SetMBR(dfX, dfY, dfX, dfY);
 
     /* Go to the first line of the next feature */
 
-    while (((pszLine = fp->GetLine()) != NULL) && 
+    while (((pszLine = fp->GetLine()) != NULL) &&
            fp->IsValidFeature(pszLine) == FALSE)
       ;
- 
-    return 0; 
+
+    return 0;
 
 }
 
@@ -735,10 +735,10 @@ int TABCustomPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
  *
  **********************************************************************/
 int TABCustomPoint::WriteGeometryToMIFFile(MIDDATAFile *fp)
-{ 
+{
     OGRGeometry         *poGeom;
     OGRPoint            *poPoint;
- 
+
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
@@ -751,13 +751,13 @@ int TABCustomPoint::WriteGeometryToMIFFile(MIDDATAFile *fp)
                  "TABCustomPoint: Missing or Invalid Geometry!");
         return -1;
     }
- 
+
 
     fp->WriteLine("Point %.15g %.15g\n",poPoint->getX(),poPoint->getY());
     fp->WriteLine("    Symbol (\"%s\",%d,%d,%d)\n",GetFontNameRef(),
                   GetSymbolColor(), GetSymbolSize(),m_nCustomStyle);
 
-    return 0; 
+    return 0;
 }
 
 /**********************************************************************
@@ -770,23 +770,26 @@ int TABPolyline::ReadGeometryFromMIFFile(MIDDATAFile *fp)
     OGRLineString       *poLine;
     OGRMultiLineString  *poMultiLine;
     GBool                bMultiple = FALSE;
-    int                  nNumPoints,nNumSec=0,i,j;
+    int                  nNumPoints=0,nNumSec=0,i,j;
     OGREnvelope          sEnvelope;
-    
 
-    papszToken = CSLTokenizeString2(fp->GetLastLine(), 
+
+    papszToken = CSLTokenizeString2(fp->GetLastLine(),
                                     " \t", CSLT_HONOURSTRINGS);
-    
+
     if (CSLCount(papszToken) < 1)
     {
         CSLDestroy(papszToken);
         return -1;
     }
 
-    if (EQUALN(papszToken[0],"LINE",4))
+    if (STARTS_WITH_CI(papszToken[0], "LINE"))
     {
         if (CSLCount(papszToken) != 5)
+        {
+          CSLDestroy(papszToken);
           return -1;
+        }
 
         poLine = new OGRLineString();
         poLine->setNumPoints(2);
@@ -794,11 +797,11 @@ int TABPolyline::ReadGeometryFromMIFFile(MIDDATAFile *fp)
                          fp->GetYTrans(CPLAtof(papszToken[2])));
         poLine->setPoint(1, fp->GetXTrans(CPLAtof(papszToken[3])),
                          fp->GetYTrans(CPLAtof(papszToken[4])));
-        SetGeometryDirectly(poLine);
         poLine->getEnvelope(&sEnvelope);
+        SetGeometryDirectly(poLine);
         SetMBR(sEnvelope.MinX, sEnvelope.MinY,sEnvelope.MaxX,sEnvelope.MaxY);
     }
-    else if (EQUALN(papszToken[0],"PLINE",5))
+    else if (STARTS_WITH_CI(papszToken[0], "PLINE"))
     {
         switch (CSLCount(papszToken))
         {
@@ -817,7 +820,7 @@ int TABPolyline::ReadGeometryFromMIFFile(MIDDATAFile *fp)
             nNumPoints = atoi(papszToken[1]);
             break;
           case 3:
-            if (EQUALN(papszToken[1],"MULTIPLE",8))
+            if (STARTS_WITH_CI(papszToken[1], "MULTIPLE"))
             {
                 bMultiple = TRUE;
                 nNumSec = atoi(papszToken[2]);
@@ -837,7 +840,7 @@ int TABPolyline::ReadGeometryFromMIFFile(MIDDATAFile *fp)
             }
             break;
           case 4:
-            if (EQUALN(papszToken[1],"MULTIPLE",8))
+            if (STARTS_WITH_CI(papszToken[1], "MULTIPLE"))
             {
                 bMultiple = TRUE;
                 nNumSec = atoi(papszToken[2]);
@@ -861,7 +864,6 @@ int TABPolyline::ReadGeometryFromMIFFile(MIDDATAFile *fp)
             poMultiLine = new OGRMultiLineString();
             for (j=0;j<nNumSec;j++)
             {
-                poLine = new OGRLineString();
                 if (j != 0)
                 {
                     pszLine = fp->GetLine();
@@ -878,13 +880,37 @@ int TABPolyline::ReadGeometryFromMIFFile(MIDDATAFile *fp)
                     CPLError(CE_Failure, CPLE_FileIO,
                              "Invalid number of vertices (%d) in PLINE "
                              "MULTIPLE segment.", nNumPoints);
+                    delete poMultiLine;
+                    CSLDestroy(papszToken);
+                    return -1;
+                }
+                poLine = new OGRLineString();
+                const int MAX_INITIAL_POINTS = 100000;
+                const int nInitialNumPoints = ( nNumPoints < MAX_INITIAL_POINTS ) ? nNumPoints : MAX_INITIAL_POINTS;
+                /* Do not allocate too much memory to begin with */
+                poLine->setNumPoints(nInitialNumPoints);
+                if( poLine->getNumPoints() != nInitialNumPoints )
+                {
+                    delete poLine;
+                    delete poMultiLine;
+                    CSLDestroy(papszToken);
                     return -1;
                 }
-                poLine->setNumPoints(nNumPoints);
                 for (i=0;i<nNumPoints;i++)
                 {
+                    if( i == MAX_INITIAL_POINTS )
+                    {
+                        poLine->setNumPoints(nNumPoints);
+                        if( poLine->getNumPoints() != nNumPoints )
+                        {
+                            delete poLine;
+                            delete poMultiLine;
+                            CSLDestroy(papszToken);
+                            return -1;
+                        }
+                    }
                     CSLDestroy(papszToken);
-                    papszToken = CSLTokenizeString2(fp->GetLine(), 
+                    papszToken = CSLTokenizeString2(fp->GetLine(),
                                                     " \t", CSLT_HONOURSTRINGS);
                     if( CSLCount(papszToken) != 2 )
                     {
@@ -901,79 +927,109 @@ int TABPolyline::ReadGeometryFromMIFFile(MIDDATAFile *fp)
                     CPLAssert(FALSE); // Just in case OGR is modified
                 }
             }
+            poMultiLine->getEnvelope(&sEnvelope);
             if (SetGeometryDirectly(poMultiLine) != OGRERR_NONE)
             {
                 CPLAssert(FALSE); // Just in case OGR is modified
             }
-            poMultiLine->getEnvelope(&sEnvelope);
             SetMBR(sEnvelope.MinX, sEnvelope.MinY,
                    sEnvelope.MaxX,sEnvelope.MaxY);
         }
         else
         {
+            if (nNumPoints < 2)
+            {
+                CPLError(CE_Failure, CPLE_FileIO,
+                            "Invalid number of vertices (%d) in PLINE "
+                            "segment.", nNumPoints);
+                CSLDestroy(papszToken);
+                return -1;
+            }
             poLine = new OGRLineString();
-            poLine->setNumPoints(nNumPoints);
+            const int MAX_INITIAL_POINTS = 100000;
+            const int nInitialNumPoints = ( nNumPoints < MAX_INITIAL_POINTS ) ? nNumPoints : MAX_INITIAL_POINTS;
+            /* Do not allocate too much memory to begin with */
+            poLine->setNumPoints(nInitialNumPoints);
+            if( poLine->getNumPoints() != nInitialNumPoints )
+            {
+                delete poLine;
+                CSLDestroy(papszToken);
+                return -1;
+            }
             for (i=0;i<nNumPoints;i++)
             {
+                if( i == MAX_INITIAL_POINTS )
+                {
+                    poLine->setNumPoints(nNumPoints);
+                    if( poLine->getNumPoints() != nNumPoints )
+                    {
+                        delete poLine;
+                        CSLDestroy(papszToken);
+                        return -1;
+                    }
+                }
                 CSLDestroy(papszToken);
-                papszToken = CSLTokenizeString2(fp->GetLine(), 
+                papszToken = CSLTokenizeString2(fp->GetLine(),
                                                 " \t", CSLT_HONOURSTRINGS);
-    
+
                 if (CSLCount(papszToken) != 2)
+                {
+                  CSLDestroy(papszToken);
+                  delete poLine;
                   return -1;
+                }
                 poLine->setPoint(i,fp->GetXTrans(CPLAtof(papszToken[0])),
                                  fp->GetYTrans(CPLAtof(papszToken[1])));
             }
-            SetGeometryDirectly(poLine);
             poLine->getEnvelope(&sEnvelope);
+            SetGeometryDirectly(poLine);
             SetMBR(sEnvelope.MinX, sEnvelope.MinY,
                    sEnvelope.MaxX,sEnvelope.MaxY);
         }
-    }    
-    
+    }
+
     CSLDestroy(papszToken);
     papszToken = NULL;
-    
-    while (((pszLine = fp->GetLine()) != NULL) && 
+
+    while (((pszLine = fp->GetLine()) != NULL) &&
            fp->IsValidFeature(pszLine) == FALSE)
     {
         papszToken = CSLTokenizeStringComplex(pszLine,"() ,",
                                               TRUE,FALSE);
-        
+
         if (CSLCount(papszToken) >= 1)
         {
-            if (EQUALN(papszToken[0],"PEN",3))
+            if (STARTS_WITH_CI(papszToken[0], "PEN"))
             {
-                
+
                 if (CSLCount(papszToken) == 4)
-                {                   
+                {
                     SetPenWidthMIF(atoi(papszToken[1]));
                     SetPenPattern((GByte)atoi(papszToken[2]));
                     SetPenColor((GInt32)atoi(papszToken[3]));
                 }
-                
             }
-            else if (EQUALN(papszToken[0],"SMOOTH",6))
+            else if (STARTS_WITH_CI(papszToken[0], "SMOOTH"))
             {
                 m_bSmooth = TRUE;
-            }             
+            }
         }
         CSLDestroy(papszToken);
     }
-    return 0; 
+    return 0;
 }
 
 /**********************************************************************
  *
  **********************************************************************/
 int TABPolyline::WriteGeometryToMIFFile(MIDDATAFile *fp)
-{ 
+{
     OGRGeometry   *poGeom;
     OGRMultiLineString *poMultiLine = NULL;
     OGRLineString *poLine = NULL;
     int nNumPoints,i;
 
-  
+
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
@@ -992,7 +1048,7 @@ int TABPolyline::WriteGeometryToMIFFile(MIDDATAFile *fp)
         }
         else
         {
-            
+
             fp->WriteLine("Pline %d\n",nNumPoints);
             for (i=0;i<nNumPoints;i++)
             {
@@ -1015,10 +1071,10 @@ int TABPolyline::WriteGeometryToMIFFile(MIDDATAFile *fp)
         {
             poGeom = poMultiLine->getGeometryRef(iLine);
             if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbLineString)
-            { 
+            {
                 poLine = (OGRLineString*)poGeom;
                 nNumPoints = poLine->getNumPoints();
-        
+
                 fp->WriteLine("  %d\n",nNumPoints);
                 for (i=0;i<nNumPoints;i++)
                 {
@@ -1037,14 +1093,14 @@ int TABPolyline::WriteGeometryToMIFFile(MIDDATAFile *fp)
         CPLError(CE_Failure, CPLE_AssertionFailed,
                  "TABPolyline: Missing or Invalid Geometry!");
     }
-    
+
     if (GetPenPattern())
       fp->WriteLine("    Pen (%d,%d,%d)\n",GetPenWidthMIF(),GetPenPattern(),
                     GetPenColor());
     if (m_bSmooth)
       fp->WriteLine("    Smooth\n");
 
-    return 0; 
+    return 0;
 
 }
 
@@ -1072,16 +1128,21 @@ int TABRegion::ReadGeometryFromMIFFile(MIDDATAFile *fp)
     /*=============================================================
      * REGION (Similar to PLINE MULTIPLE)
      *============================================================*/
-    papszToken = CSLTokenizeString2(fp->GetLastLine(), 
+    papszToken = CSLTokenizeString2(fp->GetLastLine(),
                                     " \t", CSLT_HONOURSTRINGS);
-    
+
     if (CSLCount(papszToken) ==2)
       numLineSections = atoi(papszToken[1]);
     CSLDestroy(papszToken);
     papszToken = NULL;
 
-    if (numLineSections > 0) 
-        tabPolygons = new OGRPolygon*[numLineSections];
+    if (numLineSections > 0)
+    {
+        tabPolygons = static_cast<OGRPolygon**>(
+                    VSI_MALLOC2_VERBOSE(numLineSections, sizeof(OGRPolygon*)));
+        if( tabPolygons == NULL )
+            return -1;
+    }
 
     for(iSection=0; iSection<numLineSections; iSection++)
     {
@@ -1093,43 +1154,82 @@ int TABRegion::ReadGeometryFromMIFFile(MIDDATAFile *fp)
         {
             numSectionVertices = atoi(pszLine);
         }
+        if (numSectionVertices < 2)
+        {
+            CPLError(CE_Failure, CPLE_FileIO,
+                    "Invalid number of points (%d) in REGION "
+                    "segment.", numSectionVertices);
+            for( ; iSection >= 0; --iSection )
+                delete tabPolygons[iSection];
+            VSIFree(tabPolygons);
+            return -1;
+        }
 
         poRing = new OGRLinearRing();
-        poRing->setNumPoints(numSectionVertices);
 
+        const int MAX_INITIAL_POINTS = 100000;
+        const int nInitialNumPoints = ( numSectionVertices < MAX_INITIAL_POINTS ) ? numSectionVertices : MAX_INITIAL_POINTS;
+        /* Do not allocate too much memory to begin with */
+        poRing->setNumPoints(nInitialNumPoints);
+        if( poRing->getNumPoints() != nInitialNumPoints )
+        {
+            delete poRing;
+            for( ; iSection >= 0; --iSection )
+                delete tabPolygons[iSection];
+            VSIFree(tabPolygons);
+            return -1;
+        }
         for(i=0; i<numSectionVertices; i++)
         {
-            pszLine = fp->GetLine();
-            if (pszLine)
+            if( i == MAX_INITIAL_POINTS )
             {
-                papszToken = CSLTokenizeStringComplex(pszLine," ,\t",
-                                                      TRUE,FALSE);
-                if (CSLCount(papszToken) == 2)
-                {              
-                    dX = fp->GetXTrans(CPLAtof(papszToken[0]));
-                    dY = fp->GetYTrans(CPLAtof(papszToken[1]));
-                    poRing->setPoint(i, dX, dY);
+                poRing->setNumPoints(numSectionVertices);
+                if( poRing->getNumPoints() != numSectionVertices )
+                {
+                    delete poRing;
+                    for( ; iSection >= 0; --iSection )
+                        delete tabPolygons[iSection];
+                    VSIFree(tabPolygons);
+                    return -1;
                 }
+            }
+
+            papszToken = CSLTokenizeStringComplex(fp->GetLine()," ,\t",
+                                                    TRUE,FALSE);
+            if (CSLCount(papszToken) < 2)
+            {
                 CSLDestroy(papszToken);
                 papszToken = NULL;
-            }   
+                delete poRing;
+                for( ; iSection >= 0; --iSection )
+                    delete tabPolygons[iSection];
+                VSIFree(tabPolygons);
+                return -1;
+            }
+
+            dX = fp->GetXTrans(CPLAtof(papszToken[0]));
+            dY = fp->GetYTrans(CPLAtof(papszToken[1]));
+            poRing->setPoint(i, dX, dY);
+
+            CSLDestroy(papszToken);
+            papszToken = NULL;
         }
-        
+
         poRing->closeRings();
 
         tabPolygons[iSection]->addRingDirectly(poRing);
 
         if (numLineSections == 1)
             poGeometry = tabPolygons[iSection];
-        
+
         poRing = NULL;
     }
-  
+
     if (numLineSections > 1)
     {
         int isValidGeometry;
         const char* papszOptions[] = { "METHOD=DEFAULT", NULL };
-        poGeometry = OGRGeometryFactory::organizePolygons( 
+        poGeometry = OGRGeometryFactory::organizePolygons(
             (OGRGeometry**)tabPolygons, numLineSections, &isValidGeometry, papszOptions );
 
         if (!isValidGeometry)
@@ -1140,51 +1240,50 @@ int TABRegion::ReadGeometryFromMIFFile(MIDDATAFile *fp)
         }
     }
 
-    if (tabPolygons)
-        delete[] tabPolygons;
+    VSIFree(tabPolygons);
 
     if( poGeometry )
     {
-        SetGeometryDirectly(poGeometry);
         poGeometry->getEnvelope(&sEnvelope);
-        
+        SetGeometryDirectly(poGeometry);
+
         SetMBR(sEnvelope.MinX, sEnvelope.MinY, sEnvelope.MaxX, sEnvelope.MaxY);
     }
 
-    while (((pszLine = fp->GetLine()) != NULL) && 
+    while (((pszLine = fp->GetLine()) != NULL) &&
            fp->IsValidFeature(pszLine) == FALSE)
     {
         papszToken = CSLTokenizeStringComplex(pszLine,"() ,",
                                               TRUE,FALSE);
-        
+
         if (CSLCount(papszToken) > 1)
         {
-            if (EQUALN(papszToken[0],"PEN",3))
+            if (STARTS_WITH_CI(papszToken[0], "PEN"))
             {
-                
+
                 if (CSLCount(papszToken) == 4)
-                {           
+                {
                     SetPenWidthMIF(atoi(papszToken[1]));
                     SetPenPattern((GByte)atoi(papszToken[2]));
                     SetPenColor((GInt32)atoi(papszToken[3]));
                 }
-                
+
             }
-            else if (EQUALN(papszToken[0],"BRUSH", 5))
+            else if (STARTS_WITH_CI(papszToken[0], "BRUSH"))
             {
                 if (CSLCount(papszToken) >= 3)
                 {
                     SetBrushFGColor((GInt32)atoi(papszToken[2]));
                     SetBrushPattern((GByte)atoi(papszToken[1]));
-                    
+
                     if (CSLCount(papszToken) == 4)
                        SetBrushBGColor(atoi(papszToken[3]));
                     else
                       SetBrushTransparent(TRUE);
                 }
-                
+
             }
-            else if (EQUALN(papszToken[0],"CENTER",6))
+            else if (STARTS_WITH_CI(papszToken[0], "CENTER"))
             {
                 if (CSLCount(papszToken) == 3)
                 {
@@ -1196,11 +1295,11 @@ int TABRegion::ReadGeometryFromMIFFile(MIDDATAFile *fp)
         CSLDestroy(papszToken);
         papszToken = NULL;
     }
-    
-    
-    return 0; 
+
+
+    return 0;
 }
-    
+
 /**********************************************************************
  *                   TABRegion::WriteGeometryToMIFFile()
  *
@@ -1211,7 +1310,7 @@ int TABRegion::ReadGeometryFromMIFFile(MIDDATAFile *fp)
  * been called.
  **********************************************************************/
 int TABRegion::WriteGeometryToMIFFile(MIDDATAFile *fp)
-{ 
+{
     OGRGeometry         *poGeom;
 
     poGeom = GetGeometryRef();
@@ -1222,15 +1321,15 @@ int TABRegion::WriteGeometryToMIFFile(MIDDATAFile *fp)
         /*=============================================================
          * REGIONs are similar to PLINE MULTIPLE
          *
-         * We accept both OGRPolygons (with one or multiple rings) and 
+         * We accept both OGRPolygons (with one or multiple rings) and
          * OGRMultiPolygons as input.
          *============================================================*/
         int     i, iRing, numRingsTotal, numPoints;
 
         numRingsTotal = GetNumRings();
-        
+
         fp->WriteLine("Region %d\n",numRingsTotal);
-        
+
         for(iRing=0; iRing < numRingsTotal; iRing++)
         {
             OGRLinearRing       *poRing;
@@ -1251,12 +1350,12 @@ int TABRegion::WriteGeometryToMIFFile(MIDDATAFile *fp)
                 fp->WriteLine("%.15g %.15g\n",poRing->getX(i), poRing->getY(i));
             }
         }
-        
+
         if (GetPenPattern())
           fp->WriteLine("    Pen (%d,%d,%d)\n",
                           GetPenWidthMIF(),GetPenPattern(),
                           GetPenColor());
-        
+
 
         if (GetBrushPattern())
         {
@@ -1282,7 +1381,7 @@ int TABRegion::WriteGeometryToMIFFile(MIDDATAFile *fp)
         return -1;
     }
 
-    return 0; 
+    return 0;
 }
 
 /**********************************************************************
@@ -1296,7 +1395,7 @@ int TABRectangle::ReadGeometryFromMIFFile(MIDDATAFile *fp)
     OGRPolygon          *poPolygon;
     OGRLinearRing       *poRing;
 
-    papszToken = CSLTokenizeString2(fp->GetLastLine(), 
+    papszToken = CSLTokenizeString2(fp->GetLastLine(),
                                     " \t", CSLT_HONOURSTRINGS);
 
     if (CSLCount(papszToken) <  5)
@@ -1309,19 +1408,19 @@ int TABRectangle::ReadGeometryFromMIFFile(MIDDATAFile *fp)
     dXMax = fp->GetXTrans(CPLAtof(papszToken[3]));
     dYMin = fp->GetYTrans(CPLAtof(papszToken[2]));
     dYMax = fp->GetYTrans(CPLAtof(papszToken[4]));
-    
+
     /*-----------------------------------------------------------------
      * Call SetMBR() and GetMBR() now to make sure that min values are
      * really smaller than max values.
      *----------------------------------------------------------------*/
     SetMBR(dXMin, dYMin, dXMax, dYMax);
     GetMBR(dXMin, dYMin, dXMax, dYMax);
-    
+
     m_bRoundCorners = FALSE;
     m_dRoundXRadius  = 0.0;
     m_dRoundYRadius  = 0.0;
-    
-    if (EQUALN(papszToken[0],"ROUNDRECT",9))
+
+    if (STARTS_WITH_CI(papszToken[0], "ROUNDRECT"))
     {
         m_bRoundCorners = TRUE;
         if (CSLCount(papszToken) == 6)
@@ -1329,7 +1428,7 @@ int TABRectangle::ReadGeometryFromMIFFile(MIDDATAFile *fp)
         else
         {
             CSLDestroy(papszToken);
-            papszToken = CSLTokenizeString2(fp->GetLine(), 
+            papszToken = CSLTokenizeString2(fp->GetLine(),
                                             " \t", CSLT_HONOURSTRINGS);
             if (CSLCount(papszToken) ==1 )
               m_dRoundXRadius = m_dRoundYRadius = CPLAtof(papszToken[0])/2.0;
@@ -1341,36 +1440,36 @@ int TABRectangle::ReadGeometryFromMIFFile(MIDDATAFile *fp)
     /*-----------------------------------------------------------------
      * Create and fill geometry object
      *----------------------------------------------------------------*/
-        
+
     poPolygon = new OGRPolygon;
     poRing = new OGRLinearRing();
     if (m_bRoundCorners && m_dRoundXRadius != 0.0 && m_dRoundYRadius != 0.0)
     {
         /*-------------------------------------------------------------
          * For rounded rectangles, we generate arcs with 45 line
-         * segments for each corner.  We start with lower-left corner 
+         * segments for each corner.  We start with lower-left corner
          * and proceed counterclockwise
          * We also have to make sure that rounding radius is not too
-         * large for the MBR however, we 
+         * large for the MBR however, we
          * always return the true X/Y radius (not adjusted) since this
          * is the way MapInfo seems to do it when a radius bigger than
          * the MBR is passed from TBA to MIF.
          *------------------------------------------------------------*/
         double dXRadius = MIN(m_dRoundXRadius, (dXMax-dXMin)/2.0);
         double dYRadius = MIN(m_dRoundYRadius, (dYMax-dYMin)/2.0);
-        TABGenerateArc(poRing, 45, 
+        TABGenerateArc(poRing, 45,
                        dXMin + dXRadius, dYMin + dYRadius, dXRadius, dYRadius,
-                       PI, 3.0*PI/2.0);
-        TABGenerateArc(poRing, 45, 
+                       M_PI, 3.0*M_PI/2.0);
+        TABGenerateArc(poRing, 45,
                        dXMax - dXRadius, dYMin + dYRadius, dXRadius, dYRadius,
-                       3.0*PI/2.0, 2.0*PI);
-        TABGenerateArc(poRing, 45, 
+                       3.0*M_PI/2.0, 2.0*M_PI);
+        TABGenerateArc(poRing, 45,
                        dXMax - dXRadius, dYMax - dYRadius, dXRadius, dYRadius,
-                       0.0, PI/2.0);
-        TABGenerateArc(poRing, 45, 
+                       0.0, M_PI/2.0);
+        TABGenerateArc(poRing, 45,
                        dXMin + dXRadius, dYMax - dYRadius, dXRadius, dYRadius,
-                       PI/2.0, PI);
-                       
+                       M_PI/2.0, M_PI);
+
         TABCloseRing(poRing);
     }
     else
@@ -1386,7 +1485,7 @@ int TABRectangle::ReadGeometryFromMIFFile(MIDDATAFile *fp)
     SetGeometryDirectly(poPolygon);
 
 
-   while (((pszLine = fp->GetLine()) != NULL) && 
+   while (((pszLine = fp->GetLine()) != NULL) &&
           fp->IsValidFeature(pszLine) == FALSE)
    {
        papszToken = CSLTokenizeStringComplex(pszLine,"() ,",
@@ -1394,17 +1493,17 @@ int TABRectangle::ReadGeometryFromMIFFile(MIDDATAFile *fp)
 
        if (CSLCount(papszToken) > 1)
        {
-           if (EQUALN(papszToken[0],"PEN",3))
-           {       
+           if (STARTS_WITH_CI(papszToken[0], "PEN"))
+           {
                if (CSLCount(papszToken) == 4)
-               {   
+               {
                    SetPenWidthMIF(atoi(papszToken[1]));
                    SetPenPattern((GByte)atoi(papszToken[2]));
                    SetPenColor((GInt32)atoi(papszToken[3]));
                }
-              
+
            }
-           else if (EQUALN(papszToken[0],"BRUSH", 5))
+           else if (STARTS_WITH_CI(papszToken[0], "BRUSH"))
            {
                if (CSLCount(papszToken) >=3)
                {
@@ -1416,27 +1515,26 @@ int TABRectangle::ReadGeometryFromMIFFile(MIDDATAFile *fp)
                    else
                       SetBrushTransparent(TRUE);
                }
-              
+
            }
        }
        CSLDestroy(papszToken);
        papszToken = NULL;
    }
- 
-   return 0; 
 
-}    
+   return 0;
+}
 
 
 /**********************************************************************
  *
  **********************************************************************/
 int TABRectangle::WriteGeometryToMIFFile(MIDDATAFile *fp)
-{ 
+{
     OGRGeometry         *poGeom;
     OGRPolygon          *poPolygon;
     OGREnvelope         sEnvelope;
-    
+
      /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
@@ -1450,25 +1548,25 @@ int TABRectangle::WriteGeometryToMIFFile(MIDDATAFile *fp)
         return -1;
     }
     /*-----------------------------------------------------------------
-     * Note that we will simply use the rectangle's MBR and don't really 
-     * read the polygon geometry... this should be OK unless the 
+     * Note that we will simply use the rectangle's MBR and don't really
+     * read the polygon geometry... this should be OK unless the
      * polygon geometry was not really a rectangle.
      *----------------------------------------------------------------*/
     poPolygon->getEnvelope(&sEnvelope);
 
     if (m_bRoundCorners == TRUE)
     {
-        fp->WriteLine("Roundrect %.15g %.15g %.15g %.15g %.15g\n", 
+        fp->WriteLine("Roundrect %.15g %.15g %.15g %.15g %.15g\n",
                       sEnvelope.MinX, sEnvelope.MinY,
                       sEnvelope.MaxX, sEnvelope.MaxY, m_dRoundXRadius*2.0);
     }
     else
     {
-        fp->WriteLine("Rect %.15g %.15g %.15g %.15g\n", 
+        fp->WriteLine("Rect %.15g %.15g %.15g %.15g\n",
                       sEnvelope.MinX, sEnvelope.MinY,
                       sEnvelope.MaxX, sEnvelope.MaxY);
     }
-    
+
     if (GetPenPattern())
       fp->WriteLine("    Pen (%d,%d,%d)\n",GetPenWidthMIF(),GetPenPattern(),
                     GetPenColor());
@@ -1482,21 +1580,21 @@ int TABRectangle::WriteGeometryToMIFFile(MIDDATAFile *fp)
           fp->WriteLine("    Brush (%d,%d)\n",GetBrushPattern(),
                         GetBrushFGColor());
     }
-    return 0; 
+    return 0;
 }
 
 /**********************************************************************
  *
  **********************************************************************/
 int TABEllipse::ReadGeometryFromMIFFile(MIDDATAFile *fp)
-{   
+{
     const char *pszLine;
     char **papszToken;
     double              dXMin, dYMin, dXMax, dYMax;
     OGRPolygon          *poPolygon;
     OGRLinearRing       *poRing;
 
-    papszToken = CSLTokenizeString2(fp->GetLastLine(), 
+    papszToken = CSLTokenizeString2(fp->GetLastLine(),
                                     " \t", CSLT_HONOURSTRINGS);
 
     if (CSLCount(papszToken) != 5)
@@ -1533,53 +1631,53 @@ int TABEllipse::ReadGeometryFromMIFFile(MIDDATAFile *fp)
      * For the OGR geometry, we generate an ellipse with 2 degrees line
      * segments.
      *----------------------------------------------------------------*/
-    TABGenerateArc(poRing, 180, 
+    TABGenerateArc(poRing, 180,
                    m_dCenterX, m_dCenterY,
                    m_dXRadius, m_dYRadius,
-                   0.0, 2.0*PI);
+                   0.0, 2.0*M_PI);
     TABCloseRing(poRing);
 
     poPolygon->addRingDirectly(poRing);
     SetGeometryDirectly(poPolygon);
 
-    while (((pszLine = fp->GetLine()) != NULL) && 
+    while (((pszLine = fp->GetLine()) != NULL) &&
            fp->IsValidFeature(pszLine) == FALSE)
     {
         papszToken = CSLTokenizeStringComplex(pszLine,"() ,",
                                               TRUE,FALSE);
-        
+
         if (CSLCount(papszToken) > 1)
         {
-            if (EQUALN(papszToken[0],"PEN",3))
-            {       
+            if (STARTS_WITH_CI(papszToken[0], "PEN"))
+            {
                 if (CSLCount(papszToken) == 4)
-                {   
+                {
                     SetPenWidthMIF(atoi(papszToken[1]));
                     SetPenPattern((GByte)atoi(papszToken[2]));
                     SetPenColor((GInt32)atoi(papszToken[3]));
                 }
-                
+
             }
-            else if (EQUALN(papszToken[0],"BRUSH", 5))
+            else if (STARTS_WITH_CI(papszToken[0], "BRUSH"))
             {
                 if (CSLCount(papszToken) >= 3)
                 {
                     SetBrushFGColor((GInt32)atoi(papszToken[2]));
                     SetBrushPattern((GByte)atoi(papszToken[1]));
-                    
+
                     if (CSLCount(papszToken) == 4)
                       SetBrushBGColor(atoi(papszToken[3]));
                     else
                       SetBrushTransparent(TRUE);
-                    
+
                 }
-                
+
             }
         }
         CSLDestroy(papszToken);
         papszToken = NULL;
     }
-    return 0; 
+    return 0;
 }
 
 /**********************************************************************
@@ -1589,7 +1687,7 @@ int TABEllipse::WriteGeometryToMIFFile(MIDDATAFile *fp)
 {
     OGRGeometry         *poGeom;
     OGREnvelope         sEnvelope;
- 
+
     poGeom = GetGeometryRef();
     if ( (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPolygon ) ||
          (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint )  )
@@ -1600,16 +1698,16 @@ int TABEllipse::WriteGeometryToMIFFile(MIDDATAFile *fp)
                  "TABEllipse: Missing or Invalid Geometry!");
         return -1;
     }
-      
+
     fp->WriteLine("Ellipse %.15g %.15g %.15g %.15g\n",sEnvelope.MinX, sEnvelope.MinY,
                   sEnvelope.MaxX,sEnvelope.MaxY);
-    
+
     if (GetPenPattern())
       fp->WriteLine("    Pen (%d,%d,%d)\n",GetPenWidthMIF(),GetPenPattern(),
                     GetPenColor());
-    
+
     if (GetBrushPattern())
-    {       
+    {
         if (GetBrushTransparent() == 0)
           fp->WriteLine("    Brush (%d,%d,%d)\n",GetBrushPattern(),
                         GetBrushFGColor(),GetBrushBGColor());
@@ -1617,7 +1715,7 @@ int TABEllipse::WriteGeometryToMIFFile(MIDDATAFile *fp)
           fp->WriteLine("    Brush (%d,%d)\n",GetBrushPattern(),
                         GetBrushFGColor());
     }
-    return 0; 
+    return 0;
 }
 
 /**********************************************************************
@@ -1630,8 +1728,8 @@ int TABArc::ReadGeometryFromMIFFile(MIDDATAFile *fp)
     char               **papszToken;
     double               dXMin,dXMax, dYMin,dYMax;
     int                  numPts;
-    
-    papszToken = CSLTokenizeString2(fp->GetLastLine(), 
+
+    papszToken = CSLTokenizeString2(fp->GetLastLine(),
                                     " \t", CSLT_HONOURSTRINGS);
 
     if (CSLCount(papszToken) == 5)
@@ -1642,7 +1740,7 @@ int TABArc::ReadGeometryFromMIFFile(MIDDATAFile *fp)
         dYMax = fp->GetYTrans(CPLAtof(papszToken[4]));
 
         CSLDestroy(papszToken);
-        papszToken = CSLTokenizeString2(fp->GetLine(), 
+        papszToken = CSLTokenizeString2(fp->GetLine(),
                                         " \t", CSLT_HONOURSTRINGS);
         if (CSLCount(papszToken) != 2)
         {
@@ -1687,7 +1785,7 @@ int TABArc::ReadGeometryFromMIFFile(MIDDATAFile *fp)
         m_dStartAngle = 360.0 - m_dStartAngle;
         m_dEndAngle = 360.0 - m_dEndAngle;
     }
-    
+
     m_dCenterX = (dXMin + dXMax) / 2.0;
     m_dCenterY = (dYMin + dYMax) / 2.0;
     m_dXRadius = ABS( (dXMax - dXMin) / 2.0 );
@@ -1709,70 +1807,68 @@ int TABArc::ReadGeometryFromMIFFile(MIDDATAFile *fp)
     TABGenerateArc(poLine, numPts,
                    m_dCenterX, m_dCenterY,
                    m_dXRadius, m_dYRadius,
-                   m_dStartAngle*PI/180.0, m_dEndAngle*PI/180.0);
+                   m_dStartAngle*M_PI/180.0, m_dEndAngle*M_PI/180.0);
 
     SetMBR(dXMin, dYMin, dXMax, dYMax);
     SetGeometryDirectly(poLine);
 
-    while (((pszLine = fp->GetLine()) != NULL) && 
+    while (((pszLine = fp->GetLine()) != NULL) &&
            fp->IsValidFeature(pszLine) == FALSE)
     {
         papszToken = CSLTokenizeStringComplex(pszLine,"() ,",
                                               TRUE,FALSE);
-        
+
         if (CSLCount(papszToken) > 1)
         {
-            if (EQUALN(papszToken[0],"PEN",3))
+            if (STARTS_WITH_CI(papszToken[0], "PEN"))
             {
-                
+
                 if (CSLCount(papszToken) == 4)
-                {    
+                {
                     SetPenWidthMIF(atoi(papszToken[1]));
                     SetPenPattern((GByte)atoi(papszToken[2]));
                     SetPenColor((GInt32)atoi(papszToken[3]));
                 }
-                
+
             }
         }
         CSLDestroy(papszToken);
         papszToken = NULL;
    }
-   return 0; 
+   return 0;
 }
 
 /**********************************************************************
  *
  **********************************************************************/
 int TABArc::WriteGeometryToMIFFile(MIDDATAFile *fp)
-{ 
+{
     /*-------------------------------------------------------------
      * Start/End angles
      * Since we ALWAYS produce files in quadrant 1 then we can
      * ignore the special angle conversion required by flipped axis.
      *------------------------------------------------------------*/
 
-     
+
     // Write the Arc's actual MBR
-     fp->WriteLine("Arc %.15g %.15g %.15g %.15g\n", m_dCenterX-m_dXRadius, 
-                   m_dCenterY-m_dYRadius, m_dCenterX+m_dXRadius, 
+     fp->WriteLine("Arc %.15g %.15g %.15g %.15g\n", m_dCenterX-m_dXRadius,
+                   m_dCenterY-m_dYRadius, m_dCenterX+m_dXRadius,
                    m_dCenterY+m_dYRadius);
 
-     fp->WriteLine("  %.15g %.15g\n",m_dStartAngle,m_dEndAngle); 
-     
+     fp->WriteLine("  %.15g %.15g\n",m_dStartAngle,m_dEndAngle);
+
      if (GetPenPattern())
        fp->WriteLine("    Pen (%d,%d,%d)\n",GetPenWidthMIF(),GetPenPattern(),
                      GetPenColor());
-     
-   
-    return 0; 
 
+    return 0;
 }
 
 /**********************************************************************
  *
  **********************************************************************/
 int TABText::ReadGeometryFromMIFFile(MIDDATAFile *fp)
-{ 
+{
     double               dXMin, dYMin, dXMax, dYMax;
     OGRGeometry         *poGeometry;
     const char          *pszLine;
@@ -1782,12 +1878,12 @@ int TABText::ReadGeometryFromMIFFile(MIDDATAFile *fp)
     int                  bXYBoxRead = 0;
     int                  tokenLen;
 
-    papszToken = CSLTokenizeString2(fp->GetLastLine(), 
+    papszToken = CSLTokenizeString2(fp->GetLastLine(),
                                     " \t", CSLT_HONOURSTRINGS);
     if (CSLCount(papszToken) == 1)
     {
         CSLDestroy(papszToken);
-        papszToken = CSLTokenizeString2(fp->GetLine(), 
+        papszToken = CSLTokenizeString2(fp->GetLine(),
                                         " \t", CSLT_HONOURSTRINGS);
         tokenLen = CSLCount(papszToken);
         if (tokenLen == 4)
@@ -1821,7 +1917,7 @@ int TABText::ReadGeometryFromMIFFile(MIDDATAFile *fp)
 
     /*-------------------------------------------------------------
      * Note: The text string may contain escaped "\n" chars, and we
-     * sstore them in memory in the UnEscaped form to be OGR 
+     * sstore them in memory in the UnEscaped form to be OGR
      * compliant. See Maptools bug 1107 for more details.
      *------------------------------------------------------------*/
     pszTmpString = CPLStrdup(pszString);
@@ -1832,7 +1928,7 @@ int TABText::ReadGeometryFromMIFFile(MIDDATAFile *fp)
     if (!bXYBoxRead)
     {
         CSLDestroy(papszToken);
-        papszToken = CSLTokenizeString2(fp->GetLine(), 
+        papszToken = CSLTokenizeString2(fp->GetLine(),
                                         " \t", CSLT_HONOURSTRINGS);
     }
 
@@ -1850,7 +1946,7 @@ int TABText::ReadGeometryFromMIFFile(MIDDATAFile *fp)
 
         m_dHeight = dYMax - dYMin;  //SetTextBoxHeight(dYMax - dYMin);
         m_dWidth  = dXMax - dXMin;  //SetTextBoxWidth(dXMax - dXMin);
-        
+
         if (m_dHeight <0.0)
           m_dHeight*=-1.0;
         if (m_dWidth <0.0)
@@ -1865,19 +1961,19 @@ int TABText::ReadGeometryFromMIFFile(MIDDATAFile *fp)
 
     SetMBR(dXMin, dYMin, dXMax, dYMax);
     GetMBR(dXMin, dYMin, dXMax, dYMax);
-    
-    while (((pszLine = fp->GetLine()) != NULL) && 
+
+    while (((pszLine = fp->GetLine()) != NULL) &&
            fp->IsValidFeature(pszLine) == FALSE)
     {
         papszToken = CSLTokenizeStringComplex(pszLine,"() ,",
                                               TRUE,FALSE);
-        
+
         if (CSLCount(papszToken) > 1)
         {
-            if (EQUALN(papszToken[0],"FONT",4))
+            if (STARTS_WITH_CI(papszToken[0], "FONT"))
             {
                 if (CSLCount(papszToken) >= 5)
-                {    
+                {
                     SetFontName(papszToken[1]);
                     SetFontFGColor(atoi(papszToken[4]));
                     if (CSLCount(papszToken) ==6)
@@ -1890,84 +1986,79 @@ int TABText::ReadGeometryFromMIFFile(MIDDATAFile *fp)
 
                     // papsztoken[3] = Size ???
                 }
-                
+
             }
-            else if (EQUALN(papszToken[0],"SPACING",7))
+            else if (STARTS_WITH_CI(papszToken[0], "SPACING"))
             {
                 if (CSLCount(papszToken) >= 2)
-                {   
-                    if (EQUALN(papszToken[1],"2",1))
+                {
+                    if (STARTS_WITH_CI(papszToken[1], "2"))
                     {
                         SetTextSpacing(TABTSDouble);
                     }
-                    else if (EQUALN(papszToken[1],"1.5",3))
+                    else if (STARTS_WITH_CI(papszToken[1], "1.5"))
                     {
                         SetTextSpacing(TABTS1_5);
                     }
                 }
-                
+
                 if (CSLCount(papszToken) == 7)
                 {
-                    if (EQUALN(papszToken[2],"LAbel",5))
+                    if (STARTS_WITH_CI(papszToken[2], "LAbel"))
                     {
-                        if (EQUALN(papszToken[4],"simple",6))
+                        if (STARTS_WITH_CI(papszToken[4], "simple"))
                         {
                             SetTextLineType(TABTLSimple);
                             SetTextLineEndPoint(fp->GetXTrans(CPLAtof(papszToken[5])),
                                                 fp->GetYTrans(CPLAtof(papszToken[6])));
                         }
-                        else if (EQUALN(papszToken[4],"arrow", 5))
+                        else if (STARTS_WITH_CI(papszToken[4], "arrow"))
                         {
                             SetTextLineType(TABTLArrow);
                             SetTextLineEndPoint(fp->GetXTrans(CPLAtof(papszToken[5])),
                                                 fp->GetYTrans(CPLAtof(papszToken[6])));
                         }
                     }
-                }               
+                }
             }
-            else if (EQUALN(papszToken[0],"Justify",7))
+            else if (STARTS_WITH_CI(papszToken[0], "Justify"))
             {
                 if (CSLCount(papszToken) == 2)
                 {
-                    if (EQUALN( papszToken[1],"Center",6))
+                    if (STARTS_WITH_CI(papszToken[1], "Center"))
                     {
                         SetTextJustification(TABTJCenter);
                     }
-                    else  if (EQUALN( papszToken[1],"Right",5))
+                    else  if (STARTS_WITH_CI(papszToken[1], "Right"))
                     {
                         SetTextJustification(TABTJRight);
                     }
-                    
                 }
-                
             }
-            else if (EQUALN(papszToken[0],"Angle",5))
+            else if (STARTS_WITH_CI(papszToken[0], "Angle"))
             {
                 if (CSLCount(papszToken) == 2)
-                {    
+                {
                     SetTextAngle(CPLAtof(papszToken[1]));
                 }
-                
             }
-            else if (EQUALN(papszToken[0],"LAbel",5))
+            else if (STARTS_WITH_CI(papszToken[0], "LAbel"))
             {
                 if (CSLCount(papszToken) == 5)
-                {    
-                    if (EQUALN(papszToken[2],"simple",6))
+                {
+                    if (STARTS_WITH_CI(papszToken[2], "simple"))
                     {
                         SetTextLineType(TABTLSimple);
                         SetTextLineEndPoint(fp->GetXTrans(CPLAtof(papszToken[3])),
                                            fp->GetYTrans(CPLAtof(papszToken[4])));
                     }
-                    else if (EQUALN(papszToken[2],"arrow", 5))
+                    else if (STARTS_WITH_CI(papszToken[2], "arrow"))
                     {
                         SetTextLineType(TABTLArrow);
                         SetTextLineEndPoint(fp->GetXTrans(CPLAtof(papszToken[3])),
                                            fp->GetYTrans(CPLAtof(papszToken[4])));
                     }
                 }
-                
-
                 // What I do with the XY coordonate
             }
         }
@@ -1975,7 +2066,7 @@ int TABText::ReadGeometryFromMIFFile(MIDDATAFile *fp)
         papszToken = NULL;
     }
     /*-----------------------------------------------------------------
-     * Create an OGRPoint Geometry... 
+     * Create an OGRPoint Geometry...
      * The point X,Y values will be the coords of the lower-left corner before
      * rotation is applied.  (Note that the rotation in MapInfo is done around
      * the upper-left corner)
@@ -1983,8 +2074,8 @@ int TABText::ReadGeometryFromMIFFile(MIDDATAFile *fp)
      * on the MBR after rotation, the text height and the rotation angle.
      *---------------------------------------------------------------- */
     double dCos, dSin, dX, dY;
-    dSin = sin(m_dAngle*PI/180.0);
-    dCos = cos(m_dAngle*PI/180.0);
+    dSin = sin(m_dAngle*M_PI/180.0);
+    dCos = cos(m_dAngle*M_PI/180.0);
     if (dSin > 0.0  && dCos > 0.0)
     {
         dX = dXMin + m_dHeight * dSin;
@@ -2001,20 +2092,20 @@ int TABText::ReadGeometryFromMIFFile(MIDDATAFile *fp)
         dY = dYMax;
     }
     else  // dSin < 0 && dCos > 0
-    {   
+    {
         dX = dXMin;
         dY = dYMax - m_dHeight * dCos;
     }
-    
-    
+
+
     poGeometry = new OGRPoint(dX, dY);
 
     SetGeometryDirectly(poGeometry);
 
     /*-----------------------------------------------------------------
-     * Compute Text Width: the width of the Text MBR before rotation 
+     * Compute Text Width: the width of the Text MBR before rotation
      * in ground units... unfortunately this value is not stored in the
-     * file, so we have to compute it with the MBR after rotation and 
+     * file, so we have to compute it with the MBR after rotation and
      * the height of the MBR before rotation:
      * With  W = Width of MBR before rotation
      *       H = Height of MBR before rotation
@@ -2033,14 +2124,14 @@ int TABText::ReadGeometryFromMIFFile(MIDDATAFile *fp)
     if (m_dHeight == 0.0)
         m_dWidth = 0.0;
     else if ( dCos > dSin )
-        m_dWidth = m_dHeight * ((dXMax-dXMin) - m_dHeight*dSin) / 
+        m_dWidth = m_dHeight * ((dXMax-dXMin) - m_dHeight*dSin) /
                                                         (m_dHeight*dCos);
     else
         m_dWidth = m_dHeight * ((dYMax-dYMin) - m_dHeight*dCos) /
                                                         (m_dHeight*dSin);
     m_dWidth = ABS(m_dWidth);
-    
-   return 0; 
+
+   return 0;
 }
 
 /**********************************************************************
@@ -2052,8 +2143,8 @@ int TABText::WriteGeometryToMIFFile(MIDDATAFile *fp)
     char   *pszTmpString;
 
     /*-------------------------------------------------------------
-     * Note: The text string may contain unescaped "\n" chars or 
-     * "\\" chars and we expect to receive them in an unescaped 
+     * Note: The text string may contain unescaped "\n" chars or
+     * "\\" chars and we expect to receive them in an unescaped
      * form. Those characters are unescaped in memory to be like
      * other OGR drivers. See MapTools bug 1107 for more details.
      *------------------------------------------------------------*/
@@ -2067,14 +2158,14 @@ int TABText::WriteGeometryToMIFFile(MIDDATAFile *fp)
 
     //    UpdateTextMBR();
     GetMBR(dXMin, dYMin, dXMax, dYMax);
-    fp->WriteLine("    %.15g %.15g %.15g %.15g\n",dXMin, dYMin,dXMax, dYMax); 
- 
+    fp->WriteLine("    %.15g %.15g %.15g %.15g\n",dXMin, dYMin,dXMax, dYMax);
+
     if (IsFontBGColorUsed())
-      fp->WriteLine("    Font (\"%s\",%d,%d,%d,%d)\n", GetFontNameRef(), 
+      fp->WriteLine("    Font (\"%s\",%d,%d,%d,%d)\n", GetFontNameRef(),
                     GetFontStyleMIFValue(),0,GetFontFGColor(),
                     GetFontBGColor());
     else
-      fp->WriteLine("    Font (\"%s\",%d,%d,%d)\n", GetFontNameRef(), 
+      fp->WriteLine("    Font (\"%s\",%d,%d,%d)\n", GetFontNameRef(),
                     GetFontStyleMIFValue(),0,GetFontFGColor());
 
     switch (GetTextSpacing())
@@ -2084,7 +2175,7 @@ int TABText::WriteGeometryToMIFFile(MIDDATAFile *fp)
         break;
       case TABTSDouble:
         fp->WriteLine("    Spacing 2.0\n");
-        break;    
+        break;
       case TABTSSingle:
       default:
         break;
@@ -2122,7 +2213,7 @@ int TABText::WriteGeometryToMIFFile(MIDDATAFile *fp)
       default:
         break;
     }
-    return 0; 
+    return 0;
 
 }
 
@@ -2139,15 +2230,15 @@ int TABMultiPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
     double              dfX,dfY;
     OGREnvelope         sEnvelope;
 
-    papszToken = CSLTokenizeString2(fp->GetLastLine(), 
+    papszToken = CSLTokenizeString2(fp->GetLastLine(),
                                     " \t", CSLT_HONOURSTRINGS);
-     
+
     if (CSLCount(papszToken) !=2)
     {
         CSLDestroy(papszToken);
         return -1;
     }
-    
+
     nNumPoint = atoi(papszToken[1]);
     poMultiPoint = new OGRMultiPoint;
 
@@ -2157,12 +2248,12 @@ int TABMultiPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
     // Get each point and add them to the multipoint feature
     for(i=0; i<nNumPoint; i++)
     {
-        pszLine = fp->GetLine();
-        papszToken = CSLTokenizeString2(fp->GetLastLine(), 
+        papszToken = CSLTokenizeString2(fp->GetLine(),
                                         " \t", CSLT_HONOURSTRINGS);
         if (CSLCount(papszToken) !=2)
         {
             CSLDestroy(papszToken);
+            delete poMultiPoint;
             return -1;
         }
 
@@ -2182,18 +2273,18 @@ int TABMultiPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
         CSLDestroy(papszToken);
     }
 
+    poMultiPoint->getEnvelope(&sEnvelope);
     if( SetGeometryDirectly( poMultiPoint ) != OGRERR_NONE)
     {
         CPLAssert(FALSE); // Just in case OGR is modified
     }
 
-    poMultiPoint->getEnvelope(&sEnvelope);
     SetMBR(sEnvelope.MinX, sEnvelope.MinY,
            sEnvelope.MaxX,sEnvelope.MaxY);
 
     // Read optional SYMBOL line...
 
-    while (((pszLine = fp->GetLine()) != NULL) && 
+    while (((pszLine = fp->GetLine()) != NULL) &&
            fp->IsValidFeature(pszLine) == FALSE)
     {
         papszToken = CSLTokenizeStringComplex(pszLine," ,()\t",
@@ -2207,19 +2298,19 @@ int TABMultiPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
         CSLDestroy(papszToken);
     }
 
-    return 0; 
+    return 0;
 }
 
 /**********************************************************************
  *
  **********************************************************************/
 int TABMultiPoint::WriteGeometryToMIFFile(MIDDATAFile *fp)
-{ 
+{
     OGRGeometry         *poGeom;
     OGRPoint            *poPoint;
     OGRMultiPoint       *poMultiPoint;
     int                 nNumPoints, iPoint;
- 
+
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
@@ -2238,7 +2329,7 @@ int TABMultiPoint::WriteGeometryToMIFFile(MIDDATAFile *fp)
              *-----------------------------------------------------------*/
             poGeom = poMultiPoint->getGeometryRef(iPoint);
             if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint)
-            { 
+            {
                 poPoint = (OGRPoint*)poGeom;
                 fp->WriteLine("%.15g %.15g\n",poPoint->getX(),poPoint->getY());
             }
@@ -2254,7 +2345,7 @@ int TABMultiPoint::WriteGeometryToMIFFile(MIDDATAFile *fp)
                       GetSymbolSize());
     }
 
-    return 0; 
+    return 0;
 }
 
 
@@ -2271,15 +2362,15 @@ int TABCollection::ReadGeometryFromMIFFile(MIDDATAFile *fp)
     /*-----------------------------------------------------------------
      * Fetch number of parts in "COLLECTION %d" line
      *----------------------------------------------------------------*/
-    papszToken = CSLTokenizeString2(fp->GetLastLine(), 
+    papszToken = CSLTokenizeString2(fp->GetLastLine(),
                                     " \t", CSLT_HONOURSTRINGS);
-     
+
     if (CSLCount(papszToken) !=2)
     {
         CSLDestroy(papszToken);
         return -1;
     }
-    
+
     numParts = atoi(papszToken[1]);
     CSLDestroy(papszToken);
     papszToken = NULL;
@@ -2307,8 +2398,9 @@ int TABCollection::ReadGeometryFromMIFFile(MIDDATAFile *fp)
         if (*pszLine == '\0')
             continue;  // Skip blank lines
 
-        if (EQUALN(pszLine,"REGION",6))
+        if (STARTS_WITH_CI(pszLine, "REGION"))
         {
+            delete m_poRegion;
             m_poRegion = new TABRegion(GetDefnRef());
             if (m_poRegion->ReadGeometryFromMIFFile(fp) != 0)
             {
@@ -2318,10 +2410,11 @@ int TABCollection::ReadGeometryFromMIFFile(MIDDATAFile *fp)
                 m_poRegion = NULL;
                 return -1;
             }
-        }  
-        else if (EQUALN(pszLine,"LINE",4) ||
-                 EQUALN(pszLine,"PLINE",5))
+        }
+        else if (STARTS_WITH_CI(pszLine, "LINE") ||
+                 STARTS_WITH_CI(pszLine, "PLINE"))
         {
+            delete m_poPline;
             m_poPline = new TABPolyline(GetDefnRef());
             if (m_poPline->ReadGeometryFromMIFFile(fp) != 0)
             {
@@ -2332,8 +2425,9 @@ int TABCollection::ReadGeometryFromMIFFile(MIDDATAFile *fp)
                 return -1;
             }
         }
-        else if (EQUALN(pszLine,"MULTIPOINT",10))
+        else if (STARTS_WITH_CI(pszLine, "MULTIPOINT"))
         {
+            delete m_poMpoint;
             m_poMpoint = new TABMultiPoint(GetDefnRef());
             if (m_poMpoint->ReadGeometryFromMIFFile(fp) != 0)
             {
@@ -2357,7 +2451,7 @@ int TABCollection::ReadGeometryFromMIFFile(MIDDATAFile *fp)
     }
 
     /*-----------------------------------------------------------------
-     * Set the main OGRFeature Geometry 
+     * Set the main OGRFeature Geometry
      * (this is actually duplicating geometries from each member)
      *----------------------------------------------------------------*/
     // use addGeometry() rather than addGeometryDirectly() as this clones
@@ -2367,16 +2461,16 @@ int TABCollection::ReadGeometryFromMIFFile(MIDDATAFile *fp)
     OGRGeometryCollection *poGeomColl = new OGRGeometryCollection();
     if(m_poRegion && m_poRegion->GetGeometryRef() != NULL)
         poGeomColl->addGeometry(m_poRegion->GetGeometryRef());
-    
+
     if(m_poPline && m_poPline->GetGeometryRef() != NULL)
         poGeomColl->addGeometry(m_poPline->GetGeometryRef());
 
     if(m_poMpoint && m_poMpoint->GetGeometryRef() != NULL)
         poGeomColl->addGeometry(m_poMpoint->GetGeometryRef());
 
+    poGeomColl->getEnvelope(&sEnvelope);
     this->SetGeometryDirectly(poGeomColl);
 
-    poGeomColl->getEnvelope(&sEnvelope);
     SetMBR(sEnvelope.MinX, sEnvelope.MinY,
            sEnvelope.MaxX, sEnvelope.MaxY);
 
@@ -2420,18 +2514,18 @@ int TABCollection::WriteGeometryToMIFFile(MIDDATAFile *fp)
  *
  **********************************************************************/
 int TABDebugFeature::ReadGeometryFromMIFFile(MIDDATAFile *fp)
-{ 
+{
    const char *pszLine;
-  
-   
+
+
   /* Go to the first line of the next feature */
    printf("%s\n", fp->GetLastLine());
 
-   while (((pszLine = fp->GetLine()) != NULL) && 
+   while (((pszLine = fp->GetLine()) != NULL) &&
           fp->IsValidFeature(pszLine) == FALSE)
      ;
-  
-   return 0; 
+
+   return 0;
 }
 
 
diff --git a/ogr/ogrsf_frmts/mitab/mitab_geometry.cpp b/ogr/ogrsf_frmts/mitab/mitab_geometry.cpp
index abd7c7d..5940acb 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_geometry.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_geometry.cpp
@@ -17,16 +17,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -42,14 +42,14 @@
  * expanded tabs
  *
  * Revision 1.2  2000/09/28 16:39:44  warmerda
- * avoid warnings for unused, and unitialized variables
+ * Avoid warnings for unused, and uninitialized variables
  *
  * Revision 1.1  2000/09/19 17:19:40  daniel
  * Initial Revision
  *
  **********************************************************************/
 
-#include "ogr_geometry.h"
+#include "mitab_geometry.h"
 
 #define OGR_NUM_RINGS(poly)   (poly->getNumInteriorRings()+1)
 #define OGR_GET_RING(poly, i) (i==0?poly->getExteriorRing():poly->getInteriorRing(i-1))
@@ -72,11 +72,11 @@ GBool OGRPointInRing(OGRPoint *poPoint, OGRLineString *poRing)
     x = poPoint->getX();
     y = poPoint->getY();
 
-    for (i = 0, j = numpoints-1; i < numpoints; j = i++) 
+    for (i = 0, j = numpoints-1; i < numpoints; j = i++)
     {
-        if ((((poRing->getY(i)<=y) && (y<poRing->getY(j))) || 
-             ((poRing->getY(j)<=y) && (y<poRing->getY(i)))) && 
-            (x < (poRing->getX(j) - poRing->getX(i)) * (y - poRing->getY(i)) / 
+        if ((((poRing->getY(i)<=y) && (y<poRing->getY(j))) ||
+             ((poRing->getY(j)<=y) && (y<poRing->getY(i)))) &&
+            (x < (poRing->getX(j) - poRing->getX(i)) * (y - poRing->getY(i)) /
                  (poRing->getY(j) - poRing->getY(i)) + poRing->getX(i)))
             status = !status;
     }
@@ -95,14 +95,14 @@ GBool OGRPointInRing(OGRPoint *poPoint, OGRLineString *poRing)
  *
  * Adapted version of msIntersectPointPolygon() from MapServer's mapsearch.c
  **********************************************************************/
-GBool OGRIntersectPointPolygon(OGRPoint *poPoint, OGRPolygon *poPoly) 
+GBool OGRIntersectPointPolygon(OGRPoint *poPoint, OGRPolygon *poPoly)
 {
     int i;
     GBool status = FALSE;
 
-    for(i=0; i<OGR_NUM_RINGS(poPoly); i++) 
+    for(i=0; i<OGR_NUM_RINGS(poPoly); i++)
     {
-        if (OGRPointInRing(poPoint, OGR_GET_RING(poPoly, i))) 
+        if (OGRPointInRing(poPoint, OGR_GET_RING(poPoly, i)))
         {
             /* ok, the point is in a line */
             status = !status;
@@ -117,13 +117,13 @@ GBool OGRIntersectPointPolygon(OGRPoint *poPoint, OGRPolygon *poPoly)
  *                   OGRPolygonLabelPoint()
  *
  * Generate a label point on the surface of a polygon.
- * 
- * The function is based on a scanline conversion routine used for polygon 
+ *
+ * The function is based on a scanline conversion routine used for polygon
  * fills.  Instead of processing each line the as with drawing, the
- * polygon is sampled. The center of the longest sample is chosen for the 
- * label point. The label point is guaranteed to be in the polygon even if 
+ * polygon is sampled. The center of the longest sample is chosen for the
+ * label point. The label point is guaranteed to be in the polygon even if
  * it has holes assuming the polygon is properly formed.
- * 
+ *
  * Returns OGRERR_NONE if it succeeds or OGRERR_FAILURE otherwise.
  *
  * Adapted version of msPolygonLabelPoint() from MapServer's mapprimitive.c
@@ -167,34 +167,36 @@ int OGRPolygonLabelPoint(OGRPolygon *poPoly, OGRPoint *poLabelPoint)
     skip = (oEnv.MaxY - oEnv.MinY)/NUM_SCANLINES;
 
     n=0;
-    for(j=0; j<OGR_NUM_RINGS(poPoly); j++) 
+    for(j=0; j<OGR_NUM_RINGS(poPoly); j++)
     {
         /* count total number of points */
         n += OGR_GET_RING(poPoly, j)->getNumPoints();
     }
+    if( n == 0 )
+        return OGRERR_FAILURE;
 
     xintersect = (double *)calloc(n, sizeof(double));
     if (xintersect == NULL)
         return OGRERR_FAILURE;
 
-    for(k=1; k<=NUM_SCANLINES; k++) 
-    { 
+    for(k=1; k<=NUM_SCANLINES; k++)
+    {
         /* sample the shape in the y direction */
-    
-        y = oEnv.MaxY - k*skip; 
 
-        /* need to find a y that won't intersect any vertices exactly */  
+        y = oEnv.MaxY - k*skip;
+
+        /* need to find a y that won't intersect any vertices exactly */
         hi_y = y - 1; /* first initializing lo_y, hi_y to be any 2 pnts on either side of lp->y */
         lo_y = y + 1;
-        for(j=0; j<OGR_NUM_RINGS(poPoly); j++) 
+        for(j=0; j<OGR_NUM_RINGS(poPoly); j++)
         {
             OGRLinearRing *poRing = OGR_GET_RING(poPoly,j);
 
-            if((lo_y < y) && (hi_y >= y)) 
+            if((lo_y < y) && (hi_y >= y))
                 break; /* already initialized */
-            for(i=0; i < poRing->getNumPoints(); i++) 
-            {   
-                if((lo_y < y) && (hi_y >= y)) 
+            for(i=0; i < poRing->getNumPoints(); i++)
+            {
+                if((lo_y < y) && (hi_y >= y))
                     break; /* already initialized */
                 if(poRing->getY(i) < y)
                     lo_y = poRing->getY(i);
@@ -203,27 +205,29 @@ int OGRPolygonLabelPoint(OGRPolygon *poPoly, OGRPoint *poLabelPoint)
             }
         }
 
-        n=0;
-        for(j=0; j<OGR_NUM_RINGS(poPoly); j++) 
+        for(j=0; j<OGR_NUM_RINGS(poPoly); j++)
         {
             OGRLinearRing *poRing = OGR_GET_RING(poPoly,j);
 
-            for(i=0; i < poRing->getNumPoints(); i++) 
+            for(i=0; i < poRing->getNumPoints(); i++)
             {
-                if((poRing->getY(i) < y) && 
+                if((poRing->getY(i) < y) &&
                    ((y - poRing->getY(i)) < (y - lo_y)))
                     lo_y = poRing->getY(i);
-                if((poRing->getY(i) >= y) && 
+                if((poRing->getY(i) >= y) &&
                    ((poRing->getY(i) - y) < (hi_y - y)))
                     hi_y = poRing->getY(i);
-            }      
+            }
         }
 
-        if(lo_y == hi_y) 
+        if(lo_y == hi_y)
+        {
+            free(xintersect);
             return OGRERR_FAILURE;
-        else  
-            y = (hi_y + lo_y)/2.0;    
-    
+        }
+        else
+            y = (hi_y + lo_y)/2.0;
+
         nfound = 0;
         for(j=0; j<OGR_NUM_RINGS(poPoly); j++)   /* for each line */
         {
@@ -231,49 +235,49 @@ int OGRPolygonLabelPoint(OGRPolygon *poPoly, OGRPoint *poLabelPoint)
             point1.x = poRing->getX(poRing->getNumPoints()-1);
             point1.y = poRing->getY(poRing->getNumPoints()-1);
 
-            for(i=0; i < poRing->getNumPoints(); i++) 
+            for(i=0; i < poRing->getNumPoints(); i++)
             {
                 point2.x = poRing->getX(i);
                 point2.y = poRing->getY(i);
-        
-                if(EDGE_CHECK(point1.y, y, point2.y) == CLIP_MIDDLE) 
+
+                if(EDGE_CHECK(point1.y, y, point2.y) == CLIP_MIDDLE)
                 {
                     if(point1.y == point2.y)
                         continue; /* ignore horizontal edges */
                     else
                         slope = (point2.x - point1.x) / (point2.y - point1.y);
-          
+
                     x = point1.x + (y - point1.y)*slope;
                     xintersect[nfound++] = x;
                 } /* End of checking this edge */
-        
+
                 point1 = point2;  /* Go on to next edge */
             }
         } /* Finished the scanline */
-    
+
         /* First, sort the intersections */
-        do 
+        do
         {
             wrong_order = 0;
-            for(i=0; i < nfound-1; i++) 
+            for(i=0; i < nfound-1; i++)
             {
-                if(xintersect[i] > xintersect[i+1]) 
+                if(xintersect[i] > xintersect[i+1])
                 {
                     wrong_order = 1;
                     SWAP(xintersect[i], xintersect[i+1], temp);
                 }
             }
         } while(wrong_order);
-    
+
         /* Great, now find longest span */
-        point1.y = point2.y = y;
-        for(i=0; i < nfound; i += 2) 
+        //point1.y = point2.y = y;
+        for(i=0; i < nfound; i += 2)
         {
             point1.x = xintersect[i];
             point2.x = xintersect[i+1];
             /* len = length(point1, point2); */
             len = ABS((point2.x - point1.x));
-            if(len > max_len) 
+            if(len > max_len)
             {
                 max_len = len;
                 poLabelPoint->setX( (point1.x + point2.x)/2 );
@@ -286,7 +290,7 @@ int OGRPolygonLabelPoint(OGRPolygon *poPoly, OGRPoint *poLabelPoint)
 
     /* __TODO__ Bug 673
      * There seem to be some polygons for which the label is returned
-     * completely outside of the polygon's MBR and this messes the 
+     * completely outside of the polygon's MBR and this messes the
      * file bounds, etc.
      * Until we find the source of the problem, we'll at least validate
      * the label point to make sure that it overlaps the polygon MBR.
@@ -310,12 +314,12 @@ int OGRPolygonLabelPoint(OGRPolygon *poPoly, OGRPoint *poLabelPoint)
         return OGRERR_FAILURE;
 }
 
-
+#ifdef unused
 /**********************************************************************
  *                   OGRGetCentroid()
  *
  * Calculate polygon gravity center.
- * 
+ *
  * Returns OGRERR_NONE if it succeeds or OGRERR_FAILURE otherwise.
  *
  * Adapted version of get_centroid() from MapServer's mapprimitive.c
@@ -327,7 +331,7 @@ int OGRGetCentroid(OGRPolygon *poPoly, OGRPoint *poCentroid)
     double cent_weight_x=0.0, cent_weight_y=0.0;
     double len, total_len=0;
 
-    for(i=0; i<OGR_NUM_RINGS(poPoly); i++) 
+    for(i=0; i<OGR_NUM_RINGS(poPoly); i++)
     {
         double x1, y1, x2, y2;
         OGRLinearRing *poRing = OGR_GET_RING(poPoly, i);
@@ -335,7 +339,7 @@ int OGRGetCentroid(OGRPolygon *poPoly, OGRPoint *poCentroid)
         x2 = poRing->getX(0);
         y2 = poRing->getY(0);
 
-        for(j=1; j<poRing->getNumPoints(); j++) 
+        for(j=1; j<poRing->getNumPoints(); j++)
         {
             x1 = x2;
             y1 = y2;
@@ -354,10 +358,10 @@ int OGRGetCentroid(OGRPolygon *poPoly, OGRPoint *poCentroid)
 
     poCentroid->setX( cent_weight_x / total_len );
     poCentroid->setY( cent_weight_y / total_len );
-  
+
     return OGRERR_NONE;
 }
-
+#endif
 
 
 /**********************************************************************
@@ -365,11 +369,11 @@ int OGRGetCentroid(OGRPolygon *poPoly, OGRPoint *poCentroid)
  *
  * Return the center point of a polyline.
  *
- * In MapInfo, for a simple or multiple polyline (pline), the center point 
- * in the object definition is supposed to be either the center point of 
- * the pline or the first section of a multiple pline (if an odd number of 
- * points in the pline or first section), or the midway point between the 
- * two central points (if an even number of points involved). 
+ * In MapInfo, for a simple or multiple polyline (pline), the center point
+ * in the object definition is supposed to be either the center point of
+ * the pline or the first section of a multiple pline (if an odd number of
+ * points in the pline or first section), or the midway point between the
+ * two central points (if an even number of points involved).
  *
  * Returns OGRERR_NONE if it succeeds or OGRERR_FAILURE otherwise.
  **********************************************************************/
@@ -391,7 +395,7 @@ int OGRPolylineCenterPoint(OGRLineString *poLine, OGRPoint *poLabelPoint)
         // Return the center point
         poLine->getPoint(poLine->getNumPoints()/2, poLabelPoint);
     }
-    
+
     return OGRERR_NONE;
 }
 
@@ -417,7 +421,7 @@ int OGRPolylineLabelPoint(OGRLineString *poLine, OGRPoint *poLabelPoint)
     x2 = poLine->getX(0);
     y2 = poLine->getY(0);
 
-    for(int i=1; i<poLine->getNumPoints(); i++) 
+    for(int i=1; i<poLine->getNumPoints(); i++)
     {
         x1 = x2;
         y1 = y2;
@@ -432,7 +436,6 @@ int OGRPolylineLabelPoint(OGRLineString *poLine, OGRPoint *poLabelPoint)
             poLabelPoint->setY( (y1 + y2)/2.0 );
         }
     }
-    
+
     return OGRERR_NONE;
 }
-
diff --git a/ogr/ogrsf_frmts/mitab/mitab_geometry.h b/ogr/ogrsf_frmts/mitab/mitab_geometry.h
index 65e0cb6..84c5841 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_geometry.h
+++ b/ogr/ogrsf_frmts/mitab/mitab_geometry.h
@@ -17,16 +17,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -39,8 +39,8 @@
  *
  **********************************************************************/
 
-#ifndef _MITAB_GEOMETRY_H_INCLUDED
-#define _MITAB_GEOMETRY_H_INCLUDED
+#ifndef MITAB_GEOMETRY_H_INCLUDED
+#define MITAB_GEOMETRY_H_INCLUDED
 
 #include "ogr_geometry.h"
 
@@ -50,4 +50,4 @@ int   OGRPolygonLabelPoint(OGRPolygon *poPoly, OGRPoint *poLabelPoint);
 int   OGRPolylineCenterPoint(OGRLineString *poLine, OGRPoint *poLabelPoint);
 int   OGRPolylineLabelPoint(OGRLineString *poLine, OGRPoint *poLabelPoint);
 
-#endif /* ndef _MITAB_GEOMETRY_H_INCLUDED */
+#endif /* ndef MITAB_GEOMETRY_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/mitab/mitab_idfile.cpp b/ogr/ogrsf_frmts/mitab/mitab_idfile.cpp
index 4c14be3..2d18ffb 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_idfile.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_idfile.cpp
@@ -18,16 +18,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -49,7 +49,7 @@
  * Implemented write support
  *
  * Revision 1.3  1999/09/20 18:43:01  daniel
- * Use binary acces to open file.
+ * Use binary access to open file.
  *
  * Revision 1.2  1999/09/16 02:39:16  daniel
  * Completed read support for most feature types
@@ -72,12 +72,14 @@
  *
  * Constructor.
  **********************************************************************/
-TABIDFile::TABIDFile()
+TABIDFile::TABIDFile() :
+    m_pszFname(NULL),
+    m_fp(NULL),
+    m_eAccessMode(TABRead),
+    m_poIDBlock(NULL),
+    m_nBlockSize(0),
+    m_nMaxId(-1)
 {
-    m_fp = NULL;
-    m_pszFname = NULL;
-    m_poIDBlock = NULL;
-    m_nMaxId = -1;
 }
 
 /**********************************************************************
@@ -99,9 +101,9 @@ TABIDFile::~TABIDFile()
 
 int TABIDFile::Open(const char *pszFname, const char* pszAccess)
 {
-    if( EQUALN(pszAccess, "r", 1) )
+    if( STARTS_WITH_CI(pszAccess, "r") )
         return Open(pszFname, TABRead);
-    else if( EQUALN(pszAccess, "w", 1) )
+    else if( STARTS_WITH_CI(pszAccess, "w") )
         return Open(pszFname, TABWrite);
     else
     {
@@ -124,8 +126,6 @@ int TABIDFile::Open(const char *pszFname, const char* pszAccess)
  **********************************************************************/
 int TABIDFile::Open(const char *pszFname, TABAccess eAccess)
 {
-    int         nLen;
-
     if (m_fp)
     {
         CPLError(CE_Failure, CPLE_FileIO,
@@ -166,7 +166,7 @@ int TABIDFile::Open(const char *pszFname, TABAccess eAccess)
      *----------------------------------------------------------------*/
     m_pszFname = CPLStrdup(pszFname);
 
-    nLen = strlen(m_pszFname);
+    int nLen = static_cast<int>(strlen(m_pszFname));
     if (nLen > 4 && strcmp(m_pszFname+nLen-4, ".MAP")==0)
         strcpy(m_pszFname+nLen-4, ".ID");
     else if (nLen > 4 && strcmp(m_pszFname+nLen-4, ".map")==0)
@@ -202,13 +202,16 @@ int TABIDFile::Open(const char *pszFname, TABAccess eAccess)
         VSIStatBufL  sStatBuf;
         if ( VSIStatL(m_pszFname, &sStatBuf) == -1 )
         {
-            CPLError(CE_Failure, CPLE_FileIO, 
+            CPLError(CE_Failure, CPLE_FileIO,
                      "stat() failed for %s\n", m_pszFname);
             Close();
             return -1;
         }
 
-        m_nMaxId = (int)(sStatBuf.st_size/4);
+        if( static_cast<vsi_l_offset>(sStatBuf.st_size) > static_cast<vsi_l_offset>(INT_MAX / 4) )
+            m_nMaxId = INT_MAX / 4;
+        else
+            m_nMaxId = (int)(sStatBuf.st_size/4);
         m_nBlockSize = MIN(1024, m_nMaxId*4);
 
         /*-------------------------------------------------------------
@@ -262,8 +265,8 @@ int TABIDFile::Close()
      *---------------------------------------------------------------*/
     if (m_eAccessMode != TABRead)
         SyncToDisk();
-    
-    // Delete all structures 
+
+    // Delete all structures
     delete m_poIDBlock;
     m_poIDBlock = NULL;
 
@@ -433,8 +436,3 @@ void TABIDFile::Dump(FILE *fpOut /*=NULL*/)
 }
 
 #endif // DEBUG
-
-
-
-
-
diff --git a/ogr/ogrsf_frmts/mitab/mitab_imapinfofile.cpp b/ogr/ogrsf_frmts/mitab/mitab_imapinfofile.cpp
index 3ceb688..01ba4d3 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_imapinfofile.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_imapinfofile.cpp
@@ -18,16 +18,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -60,7 +60,7 @@
  * (MITAB bug 1737, GDAL ticket 1678))
  *
  * Revision 1.23  2007/06/12 14:43:19  dmorissette
- * Use iswspace instead of sispace in IMapInfoFile::SmartOpen() (bug 1737)
+ * Use iswspace instead of ispace in IMapInfoFile::SmartOpen() (bug 1737)
  *
  * Revision 1.22  2007/06/12 13:52:37  dmorissette
  * Added IMapInfoFile::SetCharset() method (bug 1734)
@@ -182,9 +182,9 @@ IMapInfoFile::~IMapInfoFile()
 int IMapInfoFile::Open(const char *pszFname, const char* pszAccess,
                        GBool bTestOpenNoError)
 {
-    if( EQUALN(pszAccess, "r", 1) )
+    if( STARTS_WITH_CI(pszAccess, "r") )
         return Open(pszFname, TABRead, bTestOpenNoError);
-    else if( EQUALN(pszAccess, "w", 1) )
+    else if( STARTS_WITH_CI(pszAccess, "w") )
         return Open(pszFname, TABWrite, bTestOpenNoError);
     else
     {
@@ -214,7 +214,7 @@ IMapInfoFile *IMapInfoFile::SmartOpen(const char *pszFname,
     int nLen = 0;
 
     if (pszFname)
-        nLen = strlen(pszFname);
+        nLen = static_cast<int>(strlen(pszFname));
 
     if (nLen > 4 && (EQUAL(pszFname + nLen-4, ".MIF") ||
                      EQUAL(pszFname + nLen-4, ".MID") ) )
@@ -240,11 +240,11 @@ IMapInfoFile *IMapInfoFile::SmartOpen(const char *pszFname,
         while(fp && (pszLine = CPLReadLineL(fp)) != NULL)
         {
             while (isspace((unsigned char)*pszLine))  pszLine++;
-            if (EQUALN(pszLine, "Fields", 6))
+            if (STARTS_WITH_CI(pszLine, "Fields"))
                 bFoundFields = TRUE;
-            else if (EQUALN(pszLine, "create view", 11))
+            else if (STARTS_WITH_CI(pszLine, "create view"))
                 bFoundView = TRUE;
-            else if (EQUALN(pszLine, "\"\\IsSeamless\" = \"TRUE\"", 21))
+            else if (STARTS_WITH_CI(pszLine, "\"\\IsSeamless\" = \"TRUE\""))
                 bFoundSeamless = TRUE;
         }
 
@@ -285,7 +285,7 @@ IMapInfoFile *IMapInfoFile::SmartOpen(const char *pszFname,
  *                   IMapInfoFile::GetNextFeature()
  *
  * Standard OGR GetNextFeature implementation.  This method is used
- * to retreive the next OGRFeature.
+ * to retrieve the next OGRFeature.
  **********************************************************************/
 OGRFeature *IMapInfoFile::GetNextFeature()
 {
@@ -306,7 +306,7 @@ OGRFeature *IMapInfoFile::GetNextFeature()
         {
             // Avoid cloning feature... return the copy owned by the class
             CPLAssert(poFeatureRef == m_poCurFeature);
-            m_poCurFeature = NULL;  
+            m_poCurFeature = NULL;
             if( poFeatureRef->GetGeometryRef() != NULL )
                 poFeatureRef->GetGeometryRef()->assignSpatialReference(GetSpatialRef());
             return poFeatureRef;
@@ -318,7 +318,7 @@ OGRFeature *IMapInfoFile::GetNextFeature()
 /**********************************************************************
  *                   IMapInfoFile::CreateTABFeature()
  *
- * Instanciate a TABFeature* from a OGRFeature* (or NULL on error)
+ * Instantiate a TABFeature* from a OGRFeature* (or NULL on error)
  **********************************************************************/
 
 TABFeature* IMapInfoFile::CreateTABFeature(OGRFeature *poFeature)
@@ -411,20 +411,20 @@ TABFeature* IMapInfoFile::CreateTABFeature(OGRFeature *poFeature)
        *------------------------------------------------------------*/
       case wkbUnknown:
       default:
-         poTABFeature = new TABFeature(poFeature->GetDefnRef()); 
+         poTABFeature = new TABFeature(poFeature->GetDefnRef());
         break;
     }
 
     if( poGeom != NULL )
         poTABFeature->SetGeometryDirectly(poGeom->clone());
-    
+
     for (int i=0; i< poFeature->GetDefnRef()->GetFieldCount();i++)
     {
         poTABFeature->SetField(i,poFeature->GetRawFieldRef( i ));
     }
-    
+
     poTABFeature->SetFID(poFeature->GetFID());
-    
+
     return poTABFeature;
 }
 
@@ -432,7 +432,7 @@ TABFeature* IMapInfoFile::CreateTABFeature(OGRFeature *poFeature)
  *                   IMapInfoFile::ICreateFeature()
  *
  * Standard OGR CreateFeature implementation.  This method is used
- * to create a new feature in current dataset 
+ * to create a new feature in current dataset
  **********************************************************************/
 OGRErr     IMapInfoFile::ICreateFeature(OGRFeature *poFeature)
 {
@@ -448,7 +448,7 @@ OGRErr     IMapInfoFile::ICreateFeature(OGRFeature *poFeature)
         poFeature->SetFID(poTABFeature->GetFID());
 
     delete poTABFeature;
-    
+
     return eErr;
 }
 
@@ -456,13 +456,13 @@ OGRErr     IMapInfoFile::ICreateFeature(OGRFeature *poFeature)
  *                   IMapInfoFile::GetFeature()
  *
  * Standard OGR GetFeature implementation.  This method is used
- * to get the wanted (nFeatureId) feature, a NULL value will be 
+ * to get the wanted (nFeatureId) feature, a NULL value will be
  * returned on error.
  **********************************************************************/
 OGRFeature *IMapInfoFile::GetFeature(GIntBig nFeatureId)
 {
     OGRFeature *poFeatureRef;
-    
+
     /*fprintf(stderr, "GetFeature(%ld)\n", nFeatureId);*/
 
     poFeatureRef = GetFeatureRef(nFeatureId);
@@ -470,7 +470,7 @@ OGRFeature *IMapInfoFile::GetFeature(GIntBig nFeatureId)
     {
         // Avoid cloning feature... return the copy owned by the class
         CPLAssert(poFeatureRef == m_poCurFeature);
-        m_poCurFeature = NULL;  
+        m_poCurFeature = NULL;
 
         return poFeatureRef;
     }
@@ -578,7 +578,7 @@ OGRErr IMapInfoFile::CreateField( OGRFieldDefn *poField, int bApproxOK )
 /**********************************************************************
  *                   IMapInfoFile::SetCharset()
  *
- * Set the charset for the tab header. 
+ * Set the charset for the tab header.
  *
  *
  * Returns 0 on success, -1 on error.
@@ -593,4 +593,3 @@ int IMapInfoFile::SetCharset(const char* pszCharset)
     }
     return -1;
 }
-
diff --git a/ogr/ogrsf_frmts/mitab/mitab_indfile.cpp b/ogr/ogrsf_frmts/mitab/mitab_indfile.cpp
index 9e2934e..83af153 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_indfile.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_indfile.cpp
@@ -18,16 +18,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -150,17 +150,17 @@ int TABINDFile::Open(const char *pszFname, const char *pszAccess,
      * Note that for write access, we actually need read/write access to
      * the file.
      *----------------------------------------------------------------*/
-    if (EQUALN(pszAccess, "r", 1) && strchr(pszAccess, '+') != NULL)
+    if (STARTS_WITH_CI(pszAccess, "r") && strchr(pszAccess, '+') != NULL)
     {
         m_eAccessMode = TABReadWrite;
         pszAccess = "rb+";
     }
-    else if (EQUALN(pszAccess, "r", 1))
+    else if (STARTS_WITH_CI(pszAccess, "r"))
     {
         m_eAccessMode = TABRead;
         pszAccess = "rb";
     }
-    else if (EQUALN(pszAccess, "w", 1))
+    else if (STARTS_WITH_CI(pszAccess, "w"))
     {
         m_eAccessMode = TABWrite;
         pszAccess = "wb+";
@@ -177,7 +177,7 @@ int TABINDFile::Open(const char *pszFname, const char *pszAccess,
      *----------------------------------------------------------------*/
     m_pszFname = CPLStrdup(pszFname);
 
-    nLen = strlen(m_pszFname);
+    nLen = static_cast<int>(strlen(m_pszFname));
     if (nLen > 4 && !EQUAL(m_pszFname+nLen-4, ".IND") )
         strcpy(m_pszFname+nLen-4, ".ind");
 
@@ -261,7 +261,7 @@ int TABINDFile::Close()
             if (m_papoIndexRootNodes &&
                 m_papoIndexRootNodes[iIndex])
             {
-                m_papoIndexRootNodes[iIndex]->CommitToFile();
+                CPL_IGNORE_RET_VAL(m_papoIndexRootNodes[iIndex]->CommitToFile());
             }
         }
     }
@@ -376,7 +376,7 @@ int TABINDFile::ReadHeader()
 
         /*-------------------------------------------------------------
          * And init root node for this index.
-         * Note that if nRootNodePtr==0 then this means that the 
+         * Note that if nRootNodePtr==0 then this means that the
          * corresponding index does not exist (i.e. has been deleted?)
          * so we simply do not allocate the root node in this case.
          * An error will be produced if the user tries to access this index
@@ -397,7 +397,7 @@ int TABINDFile::ReadHeader()
 
             // Alloc a temporary key buffer for this index.
             // This buffer will be used by the BuildKey() method
-            m_papbyKeyBuffers[iIndex] = (GByte *)CPLCalloc(nKeyLength+1, 
+            m_papbyKeyBuffers[iIndex] = (GByte *)CPLCalloc(nKeyLength+1,
                                                            sizeof(GByte));
         }
         else
@@ -476,7 +476,7 @@ int TABINDFile::WriteHeader()
             if (poRootNode->GetSubTreeDepth() > 255)
             {
                 CPLError(CE_Failure, CPLE_AssertionFailed,
-                         "Index no %d is too large and will not be useable. "
+                         "Index no %d is too large and will not be usable. "
                          "(SubTreeDepth = %d, cannot exceed 255).",
                          iIndex+1, poRootNode->GetSubTreeDepth());
                 return -1;
@@ -507,7 +507,7 @@ int TABINDFile::WriteHeader()
  *
  * Private method to validate the index no parameter of some methods...
  * returns 0 if index no. is OK, or produces an error ands returns -1
- * if index no is not valid. 
+ * if index no is not valid.
  **********************************************************************/
 int TABINDFile::ValidateIndexNo(int nIndexNumber)
 {
@@ -519,7 +519,7 @@ int TABINDFile::ValidateIndexNo(int nIndexNumber)
     }
 
     if (nIndexNumber < 1 || nIndexNumber > m_numIndexes ||
-        m_papoIndexRootNodes == NULL || 
+        m_papoIndexRootNodes == NULL ||
         m_papoIndexRootNodes[nIndexNumber-1] == NULL)
     {
         CPLError(CE_Failure, CPLE_AssertionFailed,
@@ -550,7 +550,7 @@ int TABINDFile::SetIndexFieldType(int nIndexNumber, TABFieldType eType)
 /**********************************************************************
  *                   TABINDFile::SetIndexUnique()
  *
- * Indicate that an index's keys are unique.  This allows for some 
+ * Indicate that an index's keys are unique.  This allows for some
  * optimization with read access.  By default, an index is treated as if
  * its keys could have duplicates.
  *
@@ -571,7 +571,7 @@ int TABINDFile::SetIndexUnique(int nIndexNumber, GBool bUnique/*=TRUE*/)
  *
  * Encode a field value in the form required to be compared with index
  * keys in the specified index.
- * 
+ *
  * Note that index numbers are positive values starting at 1.
  *
  * Returns a reference to an internal buffer that is valid only until the
@@ -587,7 +587,7 @@ GByte *TABINDFile::BuildKey(int nIndexNumber, GInt32 nValue)
         return NULL;
 
     int nKeyLength = m_papoIndexRootNodes[nIndexNumber-1]->GetKeyLength();
-    
+
     /*-----------------------------------------------------------------
      * Convert all int values to MSB using the right number of bytes
      * Note:
@@ -601,12 +601,12 @@ GByte *TABINDFile::BuildKey(int nIndexNumber, GInt32 nValue)
         m_papbyKeyBuffers[nIndexNumber-1][0] = (GByte)(nValue & 0xff)+0x80;
         break;
       case 2:
-        m_papbyKeyBuffers[nIndexNumber-1][0] = 
+        m_papbyKeyBuffers[nIndexNumber-1][0] =
                                        (GByte)(nValue/0x100 & 0xff)+0x80;
         m_papbyKeyBuffers[nIndexNumber-1][1] = (GByte)(nValue & 0xff);
         break;
       case 4:
-        m_papbyKeyBuffers[nIndexNumber-1][0] = 
+        m_papbyKeyBuffers[nIndexNumber-1][0] =
                                        (GByte)(nValue/0x1000000 &0xff)+0x80;
         m_papbyKeyBuffers[nIndexNumber-1][1] = (GByte)(nValue/0x10000 & 0xff);
         m_papbyKeyBuffers[nIndexNumber-1][2] = (GByte)(nValue/0x100 &0xff);
@@ -645,10 +645,10 @@ GByte *TABINDFile::BuildKey(int nIndexNumber, const char *pszStr)
 
     /* Pad the end of the buffer with '\0' */
     for( ; i<nKeyLength; i++)
-    {   
+    {
         m_papbyKeyBuffers[nIndexNumber-1][i] = '\0';
     }
-        
+
     return m_papbyKeyBuffers[nIndexNumber-1];
 }
 
@@ -666,7 +666,7 @@ GByte *TABINDFile::BuildKey(int nIndexNumber, double dValue)
     CPLAssert(nKeyLength == 8 && sizeof(double) == 8);
 
     /*-----------------------------------------------------------------
-     * Convert double and decimal values... 
+     * Convert double and decimal values...
      * Reverse the sign of the value, and convert to MSB
      *----------------------------------------------------------------*/
     dValue = -dValue;
@@ -684,7 +684,7 @@ GByte *TABINDFile::BuildKey(int nIndexNumber, double dValue)
 /**********************************************************************
  *                   TABINDFile::FindFirst()
  *
- * Search one of the indexes for a key value.  
+ * Search one of the indexes for a key value.
  *
  * Note that index numbers are positive values starting at 1.
  *
@@ -704,7 +704,7 @@ GInt32 TABINDFile::FindFirst(int nIndexNumber, GByte *pKeyValue)
 /**********************************************************************
  *                   TABINDFile::FindNext()
  *
- * Continue the Search for pKeyValue previously initiated by FindFirst().  
+ * Continue the Search for pKeyValue previously initiated by FindFirst().
  * NOTE: FindFirst() MUST have been previously called for this call to
  *       work...
  *
@@ -742,7 +742,7 @@ int TABINDFile::CreateIndex(TABFieldType eType, int nFieldSize)
 {
     int i, nNewIndexNo = -1;
 
-    if (m_fp == NULL || 
+    if (m_fp == NULL ||
         (m_eAccessMode != TABWrite && m_eAccessMode != TABReadWrite))
         return -1;
 
@@ -806,14 +806,14 @@ int TABINDFile::CreateIndex(TABFieldType eType, int nFieldSize)
                       (eType == TABFDecimal)  ? 8:
                       (eType == TABFDate)     ? 4:
                       (eType == TABFTime)     ? 4:
-                      (eType == TABFDateTime) ? 8:
+                      /*(eType == TABFDateTime) ? 8: */
                       (eType == TABFLogical)  ? 4: MIN(128,nFieldSize));
 
     m_papoIndexRootNodes[nNewIndexNo] = new TABINDNode(m_eAccessMode);
-    if (m_papoIndexRootNodes[nNewIndexNo]->InitNode(m_fp, 0, nKeyLength, 
+    if (m_papoIndexRootNodes[nNewIndexNo]->InitNode(m_fp, 0, nKeyLength,
                                                     1,  // subtree depth=1
                                                     FALSE, // not unique
-                                                    &m_oBlockManager, 
+                                                    &m_oBlockManager,
                                                     NULL, 0, 0)!= 0)
     {
         // CPLError has already been called
@@ -842,7 +842,7 @@ int TABINDFile::CreateIndex(TABFieldType eType, int nFieldSize)
  **********************************************************************/
 int TABINDFile::AddEntry(int nIndexNumber, GByte *pKeyValue, GInt32 nRecordNo)
 {
-    if ((m_eAccessMode != TABWrite && m_eAccessMode != TABReadWrite) || 
+    if ((m_eAccessMode != TABWrite && m_eAccessMode != TABReadWrite) ||
         ValidateIndexNo(nIndexNumber) != 0)
         return -1;
 
@@ -918,6 +918,7 @@ TABINDNode::TABINDNode(TABAccess eAccessMode /*=TABRead*/)
     m_bUnique = FALSE;
 
     m_eAccessMode = eAccessMode;
+    m_nCurDataBlockPtr = 0;
 }
 
 /**********************************************************************
@@ -951,15 +952,15 @@ TABINDNode::~TABINDNode()
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABINDNode::InitNode(VSILFILE *fp, int nBlockPtr, 
-                         int nKeyLength, int nSubTreeDepth, 
+int TABINDNode::InitNode(VSILFILE *fp, int nBlockPtr,
+                         int nKeyLength, int nSubTreeDepth,
                          GBool bUnique,
                          TABBinBlockManager *poBlockMgr /*=NULL*/,
                          TABINDNode *poParentNode /*=NULL*/,
                          int nPrevNodePtr /*=0*/, int nNextNodePtr /*=0*/)
 {
     /*-----------------------------------------------------------------
-     * If the block already points to the right block, then don't do 
+     * If the block already points to the right block, then don't do
      * anything here.
      *----------------------------------------------------------------*/
     if (m_fp == fp && nBlockPtr> 0 && m_nCurDataBlockPtr == nBlockPtr)
@@ -993,7 +994,7 @@ int TABINDNode::InitNode(VSILFILE *fp, int nBlockPtr,
     if (m_poDataBlock == NULL)
         m_poDataBlock = new TABRawBinBlock(TABReadWrite, TRUE);
 
-    if ((m_eAccessMode == TABWrite || m_eAccessMode == TABReadWrite) && 
+    if ((m_eAccessMode == TABWrite || m_eAccessMode == TABReadWrite) &&
         nBlockPtr == 0 && m_poBlockManagerRef)
     {
         /*-------------------------------------------------------------
@@ -1036,19 +1037,19 @@ int TABINDNode::InitNode(VSILFILE *fp, int nBlockPtr,
  *
  * Move to the specified node ptr, and read the new node data from the file.
  *
- * This is just a cover funtion on top of InitNode()
+ * This is just a cover function on top of InitNode()
  **********************************************************************/
 int TABINDNode::GotoNodePtr(GInt32 nNewNodePtr)
 {
     // First flush current changes if any.
-    if ((m_eAccessMode == TABWrite || m_eAccessMode == TABReadWrite) && 
+    if ((m_eAccessMode == TABWrite || m_eAccessMode == TABReadWrite) &&
         m_poDataBlock && m_poDataBlock->CommitToFile() != 0)
         return -1;
 
     CPLAssert(nNewNodePtr % 512 == 0);
 
     // Then move to the requested location.
-    return InitNode(m_fp, nNewNodePtr, m_nKeyLength, m_nSubTreeDepth, 
+    return InitNode(m_fp, nNewNodePtr, m_nKeyLength, m_nSubTreeDepth,
                     m_bUnique);
 }
 
@@ -1092,9 +1093,9 @@ GInt32 TABINDNode::ReadIndexEntry(int nEntryNo, GByte *pKeyValue)
 /**********************************************************************
  *                   TABINDNode::IndexKeyCmp()
  *
- * Compare the specified index entry with the key value, and 
- * return 0 if equal, an integer less than 0 if key is smaller than 
- * index entry, and an integer greater than 0 if key is bigger than 
+ * Compare the specified index entry with the key value, and
+ * return 0 if equal, an integer less than 0 if key is smaller than
+ * index entry, and an integer greater than 0 if key is bigger than
  * index entry.
  *
  * nEntryNo is the 0-based index of the index entry that we are interested
@@ -1113,7 +1114,7 @@ int   TABINDNode::IndexKeyCmp(GByte *pKeyValue, int nEntryNo)
 /**********************************************************************
  *                   TABINDNode::SetFieldType()
  *
- * Sets the field type for the current index and recursively set all 
+ * Sets the field type for the current index and recursively set all
  * children as well.
  * This information will then be used in building the key values, etc.
  *
@@ -1144,8 +1145,8 @@ int TABINDNode::SetFieldType(TABFieldType eType)
                  "Index key length (%d) does not match field type (%s).",
                  m_nKeyLength, TABFIELDTYPE_2_STRING(eType) );
         return -1;
-    }           
-    
+    }
+
     m_eFieldType = eType;
 
     /*-----------------------------------------------------------------
@@ -1223,7 +1224,7 @@ GInt32 TABINDNode::FindFirst(GByte *pKeyValue)
          * contain the value
          *
          * In the index tree at the node level, for each node entry inside
-         * the parent node, the key value (in the parent) corresponds to 
+         * the parent node, the key value (in the parent) corresponds to
          * the value of the first key that you will find when you access
          * the corresponding child node.
          *
@@ -1252,9 +1253,9 @@ GInt32 TABINDNode::FindFirst(GByte *pKeyValue)
             else
             {
                 /*-----------------------------------------------------
-                 * We either found an indexkey >= pKeyValue or reached 
-                 * the last entry in this node... still have to decide 
-                 * what we're going to do... 
+                 * We either found an indexkey >= pKeyValue or reached
+                 * the last entry in this node... still have to decide
+                 * what we're going to do...
                  *----------------------------------------------------*/
                 if (nCmpStatus < 0 && m_nCurIndexEntry == 0)
                 {
@@ -1269,8 +1270,8 @@ GInt32 TABINDNode::FindFirst(GByte *pKeyValue)
                 }
 
                 /*-----------------------------------------------------
-                 * If we found an node for which pKeyValue < indexkey 
-                 * (or pKeyValue <= indexkey for non-unique indexes) then 
+                 * If we found an node for which pKeyValue < indexkey
+                 * (or pKeyValue <= indexkey for non-unique indexes) then
                  * we access the preceding child node.
                  *
                  * Note that for indexkey == pKeyValue in non-unique indexes
@@ -1293,7 +1294,7 @@ GInt32 TABINDNode::FindFirst(GByte *pKeyValue)
                  * OK, now it's time to load/access the candidate child nodes.
                  *----------------------------------------------------*/
                 int nRetValue = 0;
-                for(int iChild=0; nRetValue==0 && 
+                for(int iChild=0; nRetValue==0 &&
                                   iChild<numChildrenToVisit; iChild++)
                 {
                     // If we're doing a second pass then jump to next entry
@@ -1312,11 +1313,11 @@ GInt32 TABINDNode::FindFirst(GByte *pKeyValue)
                         /* Child node has never been initialized...do it now!*/
 
                         m_poCurChildNode = new TABINDNode(m_eAccessMode);
-                        if ( m_poCurChildNode->InitNode(m_fp, nChildNodePtr, 
-                                                        m_nKeyLength, 
+                        if ( m_poCurChildNode->InitNode(m_fp, nChildNodePtr,
+                                                        m_nKeyLength,
                                                         m_nSubTreeDepth-1,
                                                         m_bUnique,
-                                                        m_poBlockManagerRef, 
+                                                        m_poBlockManagerRef,
                                                         this) != 0 ||
                              m_poCurChildNode->SetFieldType(m_eFieldType)!=0)
                         {
@@ -1352,7 +1353,7 @@ GInt32 TABINDNode::FindFirst(GByte *pKeyValue)
 /**********************************************************************
  *                   TABINDNode::FindNext()
  *
- * Continue the search previously started by FindFirst() in this node 
+ * Continue the search previously started by FindFirst() in this node
  * and its children for a key value.
  *
  * Return value:
@@ -1370,7 +1371,7 @@ GInt32 TABINDNode::FindNext(GByte *pKeyValue)
     }
 
     /*-----------------------------------------------------------------
-     * m_nCurIndexEntry is the index of the last item that has been 
+     * m_nCurIndexEntry is the index of the last item that has been
      * returned by FindFirst()/FindNext().
      *----------------------------------------------------------------*/
 
@@ -1428,7 +1429,7 @@ GInt32 TABINDNode::FindNext(GByte *pKeyValue)
  **********************************************************************/
 int TABINDNode::CommitToFile()
 {
-    if ((m_eAccessMode != TABWrite && m_eAccessMode != TABReadWrite) || 
+    if ((m_eAccessMode != TABWrite && m_eAccessMode != TABReadWrite) ||
         m_poDataBlock == NULL)
         return -1;
 
@@ -1454,13 +1455,13 @@ int TABINDNode::CommitToFile()
  * that will load the whole tree branch up to the insertion point.
  * Then AddEntry() is recursively called up to the leaf node level for
  * the insertion of the actual value.
- * If the leaf node is full then it will be split and if necessary the 
+ * If the leaf node is full then it will be split and if necessary the
  * split will propagate up in the tree through the pointer that each node
  * has on its parent.
  *
  * If bAddInThisNodeOnly=TRUE, then the entry is added only locally and
- * we do not try to update the child node.  This is used when the parent 
- * of a node that is being splitted has to be updated.
+ * we do not try to update the child node.  This is used when the parent
+ * of a node that is being split has to be updated.
  *
  * bInsertAfterCurChild forces the insertion to happen immediately after
  * the m_nCurIndexEntry.  This works only when bAddInThisNodeOnly=TRUE.
@@ -1473,7 +1474,7 @@ int TABINDNode::AddEntry(GByte *pKeyValue, GInt32 nRecordNo,
                          GBool bInsertAfterCurChild /*=FALSE*/,
                          GBool bMakeNewEntryCurChild /*=FALSE*/)
 {
-    if ((m_eAccessMode != TABWrite && m_eAccessMode != TABReadWrite) || 
+    if ((m_eAccessMode != TABWrite && m_eAccessMode != TABReadWrite) ||
         m_poDataBlock == NULL)
         return -1;
 
@@ -1493,8 +1494,8 @@ int TABINDNode::AddEntry(GByte *pKeyValue, GInt32 nRecordNo,
         /*-------------------------------------------------------------
          * Propagate the call down to our children
          * Note: this recursive call could result in new levels of nodes
-         * being added under our feet by SplitRootnode() so it is very 
-         * important to return right after this call or we might not be 
+         * being added under our feet by SplitRootnode() so it is very
+         * important to return right after this call or we might not be
          * able to recognize this node at the end of the call!
          *------------------------------------------------------------*/
         return m_poCurChildNode->AddEntry(pKeyValue, nRecordNo);
@@ -1534,14 +1535,14 @@ int TABINDNode::AddEntry(GByte *pKeyValue, GInt32 nRecordNo,
                  * Splitting a regular node will leave it 50% full.
                  *----------------------------------------------------*/
                 if (SplitNode() != 0)
-                    return -1; 
+                    return -1;
             }
         }
 
         /*-------------------------------------------------------------
          * Insert new key/value at the right position in node.
          *------------------------------------------------------------*/
-        if (InsertEntry(pKeyValue, nRecordNo, 
+        if (InsertEntry(pKeyValue, nRecordNo,
                         bInsertAfterCurChild, bMakeNewEntryCurChild) != 0)
             return -1;
     }
@@ -1565,7 +1566,7 @@ int TABINDNode::InsertEntry(GByte *pKeyValue, GInt32 nRecordNo,
     int iInsertAt=0;
 
     if (GetNumEntries() >= GetMaxNumEntries())
-    {   
+    {
         CPLError(CE_Failure, CPLE_AssertionFailed,
                  "Node is full!  Cannot insert key!");
         return -1;
@@ -1598,7 +1599,7 @@ int TABINDNode::InsertEntry(GByte *pKeyValue, GInt32 nRecordNo,
      *----------------------------------------------------------------*/
     if (iInsertAt < m_numEntriesInNode)
     {
-        // Since we use memmove() directly, we need to inform 
+        // Since we use memmove() directly, we need to inform
         // m_poDataBlock that the upper limit of the buffer will move
         m_poDataBlock->GotoByteInBlock(12 + (m_numEntriesInNode+1)*
                                                         (m_nKeyLength+4));
@@ -1677,7 +1678,7 @@ int TABINDNode::UpdateCurChildEntry(GByte *pKeyValue, GInt32 nRecordNo)
 /**********************************************************************
  *                   TABINDNode::UpdateSplitChild()
  *
- * Update the key and/or record ptr information corresponding to the 
+ * Update the key and/or record ptr information corresponding to the
  * current child node.
  *
  * Returns 0 on success, -1 on error
@@ -1706,11 +1707,11 @@ int TABINDNode::UpdateSplitChild(GByte *pKeyValue1, GInt32 nRecordNo1,
     m_poDataBlock->WriteInt32(nRecordNo1);
 
     /*-----------------------------------------------------------------
-     * Add an entry for the second node after the current one and ask 
-     * AddEntry() to update m_nCurIndexEntry if the new node should 
+     * Add an entry for the second node after the current one and ask
+     * AddEntry() to update m_nCurIndexEntry if the new node should
      * become the new current child.
      *----------------------------------------------------------------*/
-    if (AddEntry(pKeyValue2, nRecordNo2, 
+    if (AddEntry(pKeyValue2, nRecordNo2,
                  TRUE, /* bInThisNodeOnly */
                  TRUE, /* bInsertAfterCurChild */
                  (nNewCurChildNo==2)) != 0)
@@ -1733,8 +1734,8 @@ int TABINDNode::UpdateSplitChild(GByte *pKeyValue1, GInt32 nRecordNo1,
  *
  * The node is split in a way that the current child stays inside this
  * node object, and a new node is created for the other half of the
- * entries.  This way, the object references in this node's parent and in its 
- * current child all remain valid.  The new node is not kept in memory, 
+ * entries.  This way, the object references in this node's parent and in its
+ * current child all remain valid.  The new node is not kept in memory,
  * it is written to disk right away.
  *
  * Returns 0 on success, -1 on error
@@ -1760,12 +1761,13 @@ int TABINDNode::SplitNode()
         /*-------------------------------------------------------------
          * We will move the second half of the array to a new node.
          *------------------------------------------------------------*/
-        if (poNewNode->InitNode(m_fp, 0, m_nKeyLength, 
-                                m_nSubTreeDepth, m_bUnique, 
-                                m_poBlockManagerRef, m_poParentNodeRef, 
+        if (poNewNode->InitNode(m_fp, 0, m_nKeyLength,
+                                m_nSubTreeDepth, m_bUnique,
+                                m_poBlockManagerRef, m_poParentNodeRef,
                                 GetNodeBlockPtr(), m_nNextNodePtr)!= 0 ||
             poNewNode->SetFieldType(m_eFieldType) != 0 )
         {
+            delete poNewNode;
             return -1;
         }
 
@@ -1774,13 +1776,15 @@ int TABINDNode::SplitNode()
         if (m_nNextNodePtr)
         {
             TABINDNode *poTmpNode = new TABINDNode(m_eAccessMode);
-            if (poTmpNode->InitNode(m_fp, m_nNextNodePtr, 
+            if (poTmpNode->InitNode(m_fp, m_nNextNodePtr,
                                     m_nKeyLength, m_nSubTreeDepth,
-                                    m_bUnique, m_poBlockManagerRef, 
+                                    m_bUnique, m_poBlockManagerRef,
                                     m_poParentNodeRef) != 0 ||
                 poTmpNode->SetPrevNodePtr(poNewNode->GetNodeBlockPtr()) != 0 ||
                 poTmpNode->CommitToFile() != 0)
             {
+                delete poTmpNode;
+                delete poNewNode;
                 return -1;
             }
             delete poTmpNode;
@@ -1791,9 +1795,12 @@ int TABINDNode::SplitNode()
         // Move half the entries to the new block
         m_poDataBlock->GotoByteInBlock(12 + numInNode1*(m_nKeyLength+4));
 
-        if (poNewNode->SetNodeBufferDirectly(numInNode2, 
+        if (poNewNode->SetNodeBufferDirectly(numInNode2,
                                         m_poDataBlock->GetCurDataPtr()) != 0)
+        {
+            delete poNewNode;
             return -1;
+        }
 
 #ifdef DEBUG
         // Just in case, reset space previously used by moved entries
@@ -1809,7 +1816,10 @@ int TABINDNode::SplitNode()
                                                     GetNodeBlockPtr(),
                                                     poNewNode->GetNodeKey(),
                                         poNewNode->GetNodeBlockPtr(), 1) != 0)
+            {
+                delete poNewNode;
                 return -1;
+            }
         }
 
     }
@@ -1818,12 +1828,13 @@ int TABINDNode::SplitNode()
         /*-------------------------------------------------------------
          * We will move the first half of the array to a new node.
          *------------------------------------------------------------*/
-        if (poNewNode->InitNode(m_fp, 0, m_nKeyLength, 
-                                m_nSubTreeDepth, m_bUnique, 
-                                m_poBlockManagerRef, m_poParentNodeRef, 
+        if (poNewNode->InitNode(m_fp, 0, m_nKeyLength,
+                                m_nSubTreeDepth, m_bUnique,
+                                m_poBlockManagerRef, m_poParentNodeRef,
                                 m_nPrevNodePtr, GetNodeBlockPtr())!= 0 ||
             poNewNode->SetFieldType(m_eFieldType) != 0 )
         {
+            delete poNewNode;
             return -1;
         }
 
@@ -1832,13 +1843,15 @@ int TABINDNode::SplitNode()
         if (m_nPrevNodePtr)
         {
             TABINDNode *poTmpNode = new TABINDNode(m_eAccessMode);
-            if (poTmpNode->InitNode(m_fp, m_nPrevNodePtr, 
+            if (poTmpNode->InitNode(m_fp, m_nPrevNodePtr,
                                     m_nKeyLength, m_nSubTreeDepth,
-                                    m_bUnique, m_poBlockManagerRef, 
+                                    m_bUnique, m_poBlockManagerRef,
                                     m_poParentNodeRef) != 0 ||
                 poTmpNode->SetNextNodePtr(poNewNode->GetNodeBlockPtr()) != 0 ||
                 poTmpNode->CommitToFile() != 0)
             {
+                delete poTmpNode;
+                delete poNewNode;
                 return -1;
             }
             delete poTmpNode;
@@ -1849,9 +1862,12 @@ int TABINDNode::SplitNode()
         // Move half the entries to the new block
         m_poDataBlock->GotoByteInBlock(12 + 0);
 
-        if (poNewNode->SetNodeBufferDirectly(numInNode1, 
+        if (poNewNode->SetNodeBufferDirectly(numInNode1,
                                         m_poDataBlock->GetCurDataPtr()) != 0)
+        {
+            delete poNewNode;
             return -1;
+        }
 
         // Shift the second half of the entries to beginning of buffer
         memmove (m_poDataBlock->GetCurDataPtr(),
@@ -1875,7 +1891,10 @@ int TABINDNode::SplitNode()
                                                   poNewNode->GetNodeBlockPtr(),
                                                     GetNodeKey(),
                                                     GetNodeBlockPtr(), 2) != 0)
+            {
+                delete poNewNode;
                 return -1;
+            }
         }
 
     }
@@ -1892,7 +1911,10 @@ int TABINDNode::SplitNode()
      * Flush and destroy temporary node
      *----------------------------------------------------------------*/
     if (poNewNode->CommitToFile() != 0)
+    {
+        delete poNewNode;
         return -1;
+    }
 
     delete poNewNode;
 
@@ -1919,21 +1941,23 @@ int TABINDNode::SplitRootNode()
      *----------------------------------------------------------------*/
     TABINDNode *poNewNode = new TABINDNode(m_eAccessMode);
 
-    if (poNewNode->InitNode(m_fp, 0, m_nKeyLength, 
-                            m_nSubTreeDepth, m_bUnique, m_poBlockManagerRef, 
+    if (poNewNode->InitNode(m_fp, 0, m_nKeyLength,
+                            m_nSubTreeDepth, m_bUnique, m_poBlockManagerRef,
                             this, 0, 0)!= 0 ||
         poNewNode->SetFieldType(m_eFieldType) != 0)
     {
+        delete poNewNode;
         return -1;
     }
 
     // Move all entries to the new child
     m_poDataBlock->GotoByteInBlock(12 + 0);
-    if (poNewNode->SetNodeBufferDirectly(m_numEntriesInNode, 
+    if (poNewNode->SetNodeBufferDirectly(m_numEntriesInNode,
                                          m_poDataBlock->GetCurDataPtr(),
                                          m_nCurIndexEntry,
                                          m_poCurChildNode) != 0)
     {
+        delete poNewNode;
         return -1;
     }
 
@@ -1972,13 +1996,13 @@ int TABINDNode::SplitRootNode()
  * (private method)
  *
  * Set the key/value part of the nodes buffer and the pointers to the
- * current child direclty.  This is used when copying info to a new node
+ * current child directly.  This is used when copying info to a new node
  * in SplitNode() and SplitRootNode()
  *
  * Returns 0 on success, -1 on error
  **********************************************************************/
 int TABINDNode::SetNodeBufferDirectly(int numEntries, GByte *pBuf,
-                                      int nCurIndexEntry/*=0*/, 
+                                      int nCurIndexEntry/*=0*/,
                                       TABINDNode *poCurChild/*=NULL*/)
 {
     m_poDataBlock->GotoByteInBlock(0);
@@ -2086,7 +2110,7 @@ void TABINDNode::Dump(FILE *fpOut /*=NULL*/)
         fprintf(fpOut, "   m_nNextNodePtr       = %d\n", m_nNextNodePtr);
         fprintf(fpOut, "   m_nSubTreeDepth      = %d\n", m_nSubTreeDepth);
         fprintf(fpOut, "   m_nKeyLength         = %d\n", m_nKeyLength);
-        fprintf(fpOut, "   m_eFieldtype         = %s\n", 
+        fprintf(fpOut, "   m_eFieldtype         = %s\n",
                                         TABFIELDTYPE_2_STRING(m_eFieldType) );
         if (m_nSubTreeDepth > 0)
         {
@@ -2106,12 +2130,12 @@ void TABINDNode::Dump(FILE *fpOut /*=NULL*/)
             {
               if (m_nSubTreeDepth > 1)
               {
-                fprintf(fpOut, "   >>>> Child %d of %d <<<<<\n", i, 
+                fprintf(fpOut, "   >>>> Child %d of %d <<<<<\n", i,
                                                          m_numEntriesInNode);
               }
               else
               {
-                fprintf(fpOut, "   >>>> Record (leaf) %d of %d <<<<<\n", i, 
+                fprintf(fpOut, "   >>>> Record (leaf) %d of %d <<<<<\n", i,
                                                          m_numEntriesInNode);
               }
 
@@ -2126,10 +2150,10 @@ void TABINDNode::Dump(FILE *fpOut /*=NULL*/)
                 GInt32 nInt32;
                 GInt16 nInt16;
                 GUInt32 nUInt32;
+                nRecordPtr = ReadIndexEntry(i, aKeyValBuf);
                 memcpy(&nInt32, aKeyValBuf, 4);
                 memcpy(&nInt16, aKeyValBuf + 2, 2);
                 memcpy(&nUInt32, aKeyValBuf, 4);
-                nRecordPtr = ReadIndexEntry(i, aKeyValBuf);
                 fprintf(fpOut, "   nRecordPtr = %d\n", nRecordPtr);
                 fprintf(fpOut, "   Int Value = %d\n", nInt32);
                 fprintf(fpOut, "   Int16 Val= %d\n",nInt16);
@@ -2145,8 +2169,8 @@ void TABINDNode::Dump(FILE *fpOut /*=NULL*/)
 
               if (m_nSubTreeDepth > 1)
               {
-                oChildNode.InitNode(m_fp, nRecordPtr, m_nKeyLength, 
-                                    m_nSubTreeDepth - 1, FALSE);
+                CPL_IGNORE_RET_VAL(oChildNode.InitNode(m_fp, nRecordPtr, m_nKeyLength,
+                                    m_nSubTreeDepth - 1, FALSE));
                 oChildNode.SetFieldType(m_eFieldType);
                 oChildNode.Dump(fpOut);
               }
diff --git a/ogr/ogrsf_frmts/mitab/mitab_mapcoordblock.cpp b/ogr/ogrsf_frmts/mitab/mitab_mapcoordblock.cpp
index e6b0695..d657f8c 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_mapcoordblock.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_mapcoordblock.cpp
@@ -18,16 +18,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -94,6 +94,7 @@
  **********************************************************************/
 
 #include "mitab.h"
+#include "mitab_utils.h"
 
 /*=====================================================================
  *                      class TABMAPCoordBlock
@@ -112,7 +113,7 @@ TABMAPCoordBlock::TABMAPCoordBlock(TABAccess eAccessMode /*= TABRead*/):
     m_nComprOrgX = m_nComprOrgY = m_nNextCoordBlock = m_numDataBytes = 0;
 
     m_numBlocksInChain = 1;  // Current block counts as 1
- 
+
     m_poBlockManagerRef = NULL;
 
     m_nTotalDataSize = 0;
@@ -142,25 +143,25 @@ TABMAPCoordBlock::~TABMAPCoordBlock()
  * Perform some initialization on the block after its binary data has
  * been set or changed (or loaded from a file).
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
 int     TABMAPCoordBlock::InitBlockFromData(GByte *pabyBuf,
-                                            int nBlockSize, int nSizeUsed, 
+                                            int nBlockSize, int nSizeUsed,
                                             GBool bMakeCopy /* = TRUE */,
-                                            VSILFILE *fpSrc /* = NULL */, 
+                                            VSILFILE *fpSrc /* = NULL */,
                                             int nOffset /* = 0 */)
 {
     int nStatus;
 #ifdef DEBUG_VERBOSE
-    CPLDebug("MITAB", "Instanciating COORD block to/from offset %d", nOffset);
+    CPLDebug("MITAB", "Instantiating COORD block to/from offset %d", nOffset);
 #endif
     /*-----------------------------------------------------------------
      * First of all, we must call the base class' InitBlockFromData()
      *----------------------------------------------------------------*/
     nStatus = TABRawBinBlock::InitBlockFromData(pabyBuf, nBlockSize, nSizeUsed,
                                                 bMakeCopy, fpSrc, nOffset);
-    if (nStatus != 0)   
+    if (nStatus != 0)
         return nStatus;
 
     /*-----------------------------------------------------------------
@@ -181,6 +182,15 @@ int     TABMAPCoordBlock::InitBlockFromData(GByte *pabyBuf,
      *----------------------------------------------------------------*/
     GotoByteInBlock(0x002);
     m_numDataBytes = ReadInt16();       /* Excluding 8 bytes header */
+    if( m_numDataBytes < 0 || m_numDataBytes + MAP_COORD_HEADER_SIZE > nBlockSize )
+    {
+        CPLError(CE_Failure, CPLE_FileIO,
+                 "TABMAPCoordBlock::InitBlockFromData(): m_numDataBytes=%d incompatible with block size %d",
+                 m_numDataBytes, nBlockSize);
+        CPLFree(m_pabyBuf);
+        m_pabyBuf = NULL;
+        return -1;
+    }
 
     m_nNextCoordBlock = ReadInt32();
 
@@ -198,14 +208,14 @@ int     TABMAPCoordBlock::InitBlockFromData(GByte *pabyBuf,
 /**********************************************************************
  *                   TABMAPCoordBlock::CommitToFile()
  *
- * Commit the current state of the binary block to the file to which 
+ * Commit the current state of the binary block to the file to which
  * it has been previously attached.
  *
  * This method makes sure all values are properly set in the map object
  * block header and then calls TABRawBinBlock::CommitToFile() to do
  * the actual writing to disk.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
 int     TABMAPCoordBlock::CommitToFile()
@@ -216,7 +226,7 @@ int     TABMAPCoordBlock::CommitToFile()
 
     if ( m_pabyBuf == NULL )
     {
-        CPLError(CE_Failure, CPLE_AssertionFailed, 
+        CPLError(CE_Failure, CPLE_AssertionFailed,
                  "CommitToFile(): Block has not been initialized yet!");
         return -1;
     }
@@ -246,7 +256,7 @@ int     TABMAPCoordBlock::CommitToFile()
     if (nStatus == 0)
     {
 #ifdef DEBUG_VERBOSE
-        CPLDebug("MITAB", "Commiting COORD block to offset %d", m_nFileOffset);
+        CPLDebug("MITAB", "Committing COORD block to offset %d", m_nFileOffset);
 #endif
         nStatus = TABRawBinBlock::CommitToFile();
     }
@@ -258,26 +268,27 @@ int     TABMAPCoordBlock::CommitToFile()
  *                   TABMAPCoordBlock::InitNewBlock()
  *
  * Initialize a newly created block so that it knows to which file it
- * is attached, its block size, etc . and then perform any specific 
- * initialization for this block type, including writing a default 
+ * is attached, its block size, etc . and then perform any specific
+ * initialization for this block type, including writing a default
  * block header, etc. and leave the block ready to receive data.
  *
  * This is an alternative to calling ReadFromFile() or InitBlockFromData()
  * that puts the block in a stable state without loading any initial
  * data in it.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
-int     TABMAPCoordBlock::InitNewBlock(VSILFILE *fpSrc, int nBlockSize, 
+int     TABMAPCoordBlock::InitNewBlock(VSILFILE *fpSrc, int nBlockSize,
                                         int nFileOffset /* = 0*/)
 {
     CPLErrorReset();
 #ifdef DEBUG_VERBOSE
-    CPLDebug("MITAB", "Instanciating new COORD block at offset %d", nFileOffset);
+    CPLDebug( "MITAB", "Instantiating new COORD block at offset %d",
+              nFileOffset);
 #endif
     /*-----------------------------------------------------------------
-     * Start with the default initialisation
+     * Start with the default initialization
      *----------------------------------------------------------------*/
     if ( TABRawBinBlock::InitNewBlock(fpSrc, nBlockSize, nFileOffset) != 0)
         return -1;
@@ -289,7 +300,7 @@ int     TABMAPCoordBlock::InitNewBlock(VSILFILE *fpSrc, int nBlockSize,
      * maintained between blocks in the same chain.
      *----------------------------------------------------------------*/
     m_nNextCoordBlock = 0;
- 
+
     m_numDataBytes = 0;
 
     // m_nMin/Max are used to keep track of current block MBR
@@ -350,16 +361,18 @@ void     TABMAPCoordBlock::SetComprCoordOrigin(GInt32 nX, GInt32 nY)
  * This means that the returned coordinates are always absolute integer
  * coordinates, even when the source coords are in compressed form.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
-int     TABMAPCoordBlock::ReadIntCoord(GBool bCompressed, 
+int     TABMAPCoordBlock::ReadIntCoord(GBool bCompressed,
                                         GInt32 &nX, GInt32 &nY)
 {
     if (bCompressed)
-    {   
-        nX = m_nComprOrgX + ReadInt16();
-        nY = m_nComprOrgY + ReadInt16();
+    {
+        nX = ReadInt16();
+        nY = ReadInt16();
+        TABSaturatedAdd(nX, m_nComprOrgX);
+        TABSaturatedAdd(nY, m_nComprOrgY);
     }
     else
     {
@@ -378,7 +391,7 @@ int     TABMAPCoordBlock::ReadIntCoord(GBool bCompressed,
  *
  * Read the specified number of pairs of X,Y integer coordinates values
  * from the block, and apply the translation relative to the origin of
- * the coord. space previously set using SetComprCoordOrigin() if 
+ * the coord. space previously set using SetComprCoordOrigin() if
  * bCompressed=TRUE.
  *
  * This means that the returned coordinates are always absolute integer
@@ -387,20 +400,22 @@ int     TABMAPCoordBlock::ReadIntCoord(GBool bCompressed,
  * panXY should point to an array big enough to receive the specified
  * number of coordinates.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
-int     TABMAPCoordBlock::ReadIntCoords(GBool bCompressed, int numCoordPairs, 
+int     TABMAPCoordBlock::ReadIntCoords(GBool bCompressed, int numCoordPairs,
                                         GInt32 *panXY)
 {
     int i, numValues = numCoordPairs*2;
 
     if (bCompressed)
-    {   
+    {
         for(i=0; i<numValues; i+=2)
         {
-            panXY[i]   = m_nComprOrgX + ReadInt16();
-            panXY[i+1] = m_nComprOrgY + ReadInt16();
+            panXY[i]   = ReadInt16();
+            panXY[i+1] = ReadInt16();
+            TABSaturatedAdd(panXY[i], m_nComprOrgX);
+            TABSaturatedAdd(panXY[i+1], m_nComprOrgY);
             if (CPLGetLastErrorType() != 0)
                 return -1;
         }
@@ -424,11 +439,11 @@ int     TABMAPCoordBlock::ReadIntCoords(GBool bCompressed, int numCoordPairs,
  *
  * Read a set of coordinate section headers for PLINE MULTIPLE or REGIONs
  * and store the result in the array of structures pasHdrs[].  It is assumed
- * that pasHdrs points to an allocated array of at least numSections 
+ * that pasHdrs points to an allocated array of at least numSections
  * TABMAPCoordSecHdr structures.
  *
- * The function will also set the values of numVerticesTotal to the 
- * total number of coordinates in the object (the sum of all sections 
+ * The function will also set the values of numVerticesTotal to the
+ * total number of coordinates in the object (the sum of all sections
  * headers read).
  *
  * At the end of the call, this TABMAPCoordBlock object will be located
@@ -443,12 +458,12 @@ int     TABMAPCoordBlock::ReadIntCoords(GBool bCompressed, int numCoordPairs,
  *            last section header block (i.e. that the coord. data is not
  *            located all over the place).  If it is not the case then
  *            an error will be produced and the code to read region and
- *            multipline objects will have to be updated. 
+ *            multipline objects will have to be updated.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
-int     TABMAPCoordBlock::ReadCoordSecHdrs(GBool bCompressed, 
+int     TABMAPCoordBlock::ReadCoordSecHdrs(GBool bCompressed,
                                            int nVersion,
                                            int numSections,
                                            TABMAPCoordSecHdr *pasHdrs,
@@ -461,7 +476,7 @@ int     TABMAPCoordBlock::ReadCoordSecHdrs(GBool bCompressed,
     /*-------------------------------------------------------------
      * Note about header+vertices size vs compressed coordinates:
      * The uncompressed header sections are actually 16 bytes, but the
-     * offset calculations are based on prior decompression of the 
+     * offset calculations are based on prior decompression of the
      * coordinates.  Our coordinate offset calculations have
      * to take this fact into account.
      * Also, V450 header section uses int32 instead of int16 for numVertices
@@ -469,10 +484,14 @@ int     TABMAPCoordBlock::ReadCoordSecHdrs(GBool bCompressed,
      * V800 header section uses int32 for numHoles but there is no need
      * for the 2 alignment bytes so the size is the same as V450
      *------------------------------------------------------------*/
-    if (nVersion >= 450)
-        nTotalHdrSizeUncompressed = 28 * numSections;
-    else
-        nTotalHdrSizeUncompressed = 24 * numSections;
+    const int nSectionSize = (nVersion >= 450) ? 28 : 24;
+    if( numSections > INT_MAX / nSectionSize )
+    {
+        CPLError(CE_Failure, CPLE_AssertionFailed,
+                 "Invalid numSections");
+        return -1;
+    }
+    nTotalHdrSizeUncompressed = nSectionSize * numSections;
 
     numVerticesTotal = 0;
 
@@ -488,30 +507,54 @@ int     TABMAPCoordBlock::ReadCoordSecHdrs(GBool bCompressed,
             pasHdrs[i].numVertices = ReadInt32();
         else
             pasHdrs[i].numVertices = ReadInt16();
+        if( pasHdrs[i].numVertices < 0 )
+        {
+            CPLError(CE_Failure, CPLE_AssertionFailed,
+                     "Invalid number of vertices for section %d", i);
+            return -1;
+        }
         if (nVersion >= 800)
             pasHdrs[i].numHoles = ReadInt32();
         else
             pasHdrs[i].numHoles = ReadInt16();
+        if( pasHdrs[i].numHoles < 0 )
+        {
+            CPLError(CE_Failure, CPLE_AssertionFailed,
+                     "Invalid number of holes for section %d", i);
+            return -1;
+        }
         ReadIntCoord(bCompressed, pasHdrs[i].nXMin, pasHdrs[i].nYMin);
         ReadIntCoord(bCompressed, pasHdrs[i].nXMax, pasHdrs[i].nYMax);
         pasHdrs[i].nDataOffset = ReadInt32();
+        if( pasHdrs[i].nDataOffset < nTotalHdrSizeUncompressed )
+        {
+            CPLError(CE_Failure, CPLE_AssertionFailed,
+                     "Invalid data offset for section %d", i);
+            return -1;
+        }
 
         if (CPLGetLastErrorType() != 0)
             return -1;
 
+        if( numVerticesTotal > INT_MAX - pasHdrs[i].numVertices )
+        {
+            CPLError(CE_Failure, CPLE_AssertionFailed,
+                     "Invalid number of vertices for section %d", i);
+            return -1;
+        }
         numVerticesTotal += pasHdrs[i].numVertices;
 
 
-        pasHdrs[i].nVertexOffset = (pasHdrs[i].nDataOffset - 
+        pasHdrs[i].nVertexOffset = (pasHdrs[i].nDataOffset -
                                     nTotalHdrSizeUncompressed ) / 8;
 #ifdef TABDUMP
         printf("READING pasHdrs[%d] @ %d = \n"
                "              { numVertices = %d, numHoles = %d, \n"
                "                nXMin=%d, nYMin=%d, nXMax=%d, nYMax=%d,\n"
                "                nDataOffset=%d, nVertexOffset=%d }\n",
-               i, nHdrAddress, pasHdrs[i].numVertices, pasHdrs[i].numHoles, 
-               pasHdrs[i].nXMin, pasHdrs[i].nYMin, pasHdrs[i].nXMax, 
-               pasHdrs[i].nYMax, pasHdrs[i].nDataOffset, 
+               i, nHdrAddress, pasHdrs[i].numVertices, pasHdrs[i].numHoles,
+               pasHdrs[i].nXMin, pasHdrs[i].nYMin, pasHdrs[i].nXMax,
+               pasHdrs[i].nYMax, pasHdrs[i].nDataOffset,
                pasHdrs[i].nVertexOffset);
         printf("                dX = %d, dY = %d  (center = %d , %d)\n",
                pasHdrs[i].nXMax - pasHdrs[i].nXMin,
@@ -527,7 +570,8 @@ int     TABMAPCoordBlock::ReadCoordSecHdrs(GBool bCompressed,
          * (Well... at least check that all the vertex indices are enclosed
          * inside the [0..numVerticesTotal] range.)
          *------------------------------------------------------------*/
-        if ( pasHdrs[i].nVertexOffset < 0 || 
+        if ( pasHdrs[i].nVertexOffset < 0 ||
+             pasHdrs[i].nVertexOffset > INT_MAX - pasHdrs[i].numVertices ||
              (pasHdrs[i].nVertexOffset +
                            pasHdrs[i].numVertices ) > numVerticesTotal)
         {
@@ -545,7 +589,7 @@ int     TABMAPCoordBlock::ReadCoordSecHdrs(GBool bCompressed,
  *                   TABMAPObjectBlock::WriteCoordSecHdrs()
  *
  * Write a set of coordinate section headers for PLINE MULTIPLE or REGIONs.
- * pasHdrs should point to an array of numSections TABMAPCoordSecHdr 
+ * pasHdrs should point to an array of numSections TABMAPCoordSecHdr
  * structures that have been properly initialized.
  *
  * In V450 the numVertices is stored on an int32 instead of an int16
@@ -555,7 +599,7 @@ int     TABMAPCoordBlock::ReadCoordSecHdrs(GBool bCompressed,
  * At the end of the call, this TABMAPCoordBlock object will be ready to
  * receive the coordinate data.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
 int     TABMAPCoordBlock::WriteCoordSecHdrs(int nVersion,
@@ -577,9 +621,9 @@ int     TABMAPCoordBlock::WriteCoordSecHdrs(int nVersion,
                "              { numVertices = %d, numHoles = %d, \n"
                "                nXMin=%d, nYMin=%d, nXMax=%d, nYMax=%d,\n"
                "                nDataOffset=%d, nVertexOffset=%d }\n",
-               i, GetCurAddress(), pasHdrs[i].numVertices, pasHdrs[i].numHoles, 
-               pasHdrs[i].nXMin, pasHdrs[i].nYMin, pasHdrs[i].nXMax, 
-               pasHdrs[i].nYMax, pasHdrs[i].nDataOffset, 
+               i, GetCurAddress(), pasHdrs[i].numVertices, pasHdrs[i].numHoles,
+               pasHdrs[i].nXMin, pasHdrs[i].nYMin, pasHdrs[i].nXMax,
+               pasHdrs[i].nYMax, pasHdrs[i].nDataOffset,
                pasHdrs[i].nVertexOffset);
         printf("                dX = %d, dY = %d  (center = %d , %d)\n",
                pasHdrs[i].nXMax - pasHdrs[i].nXMin,
@@ -613,7 +657,7 @@ int     TABMAPCoordBlock::WriteCoordSecHdrs(int nVersion,
  * Write a pair of integer coordinates values to the current position in the
  * the block.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
 
@@ -636,12 +680,12 @@ int     TABMAPCoordBlock::WriteIntCoord(GInt32 nX, GInt32 nY,
         m_nMinX = nX;
     if (nX > m_nMaxX)
         m_nMaxX = nX;
-    
+
     if (nY < m_nMinY)
         m_nMinY = nY;
     if (nY > m_nMaxY)
         m_nMaxY = nY;
-    
+
     /*-------------------------------------------------------------
      * Also keep track of current feature MBR.
      *------------------------------------------------------------*/
@@ -661,7 +705,7 @@ int     TABMAPCoordBlock::WriteIntCoord(GInt32 nX, GInt32 nY,
 /**********************************************************************
  *                   TABMAPCoordBlock::SetMAPBlockManagerRef()
  *
- * Pass a reference to the block manager object for the file this 
+ * Pass a reference to the block manager object for the file this
  * block belongs to.  The block manager will be used by this object
  * when it needs to automatically allocate a new block.
  **********************************************************************/
@@ -675,7 +719,7 @@ void TABMAPCoordBlock::SetMAPBlockManagerRef(TABBinBlockManager *poBlockMgr)
  *                   TABMAPCoordBlock::ReadBytes()
  *
  * Cover function for TABRawBinBlock::ReadBytes() that will automagically
- * load the next coordinate block in the chain before reading the 
+ * load the next coordinate block in the chain before reading the
  * requested bytes if we are at the end of the current block and if
  * m_nNextCoordBlock is a valid block.
  *
@@ -685,18 +729,18 @@ void TABMAPCoordBlock::SetMAPBlockManagerRef(TABBinBlockManager *poBlockMgr)
  * the user's buffer pointed by pabyDstBuf.
  *
  * Passing pabyDstBuf = NULL will only move the read pointer by the
- * specified number of bytes as if the copy had happened... but it 
+ * specified number of bytes as if the copy had happened... but it
  * won't crash.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
 int     TABMAPCoordBlock::ReadBytes(int numBytes, GByte *pabyDstBuf)
 {
     int nStatus;
 
-    if (m_pabyBuf && 
-        m_nCurPos >= (m_numDataBytes+MAP_COORD_HEADER_SIZE) && 
+    if (m_pabyBuf &&
+        m_nCurPos >= (m_numDataBytes+MAP_COORD_HEADER_SIZE) &&
         m_nNextCoordBlock > 0)
     {
         // We're at end of current block... advance to next block.
@@ -711,15 +755,15 @@ int     TABMAPCoordBlock::ReadBytes(int numBytes, GByte *pabyDstBuf)
         m_numBlocksInChain++;
     }
 
-    if (m_pabyBuf && 
-        m_nCurPos < (m_numDataBytes+MAP_COORD_HEADER_SIZE) && 
-        m_nCurPos+numBytes > (m_numDataBytes+MAP_COORD_HEADER_SIZE) && 
+    if (m_pabyBuf &&
+        m_nCurPos < (m_numDataBytes+MAP_COORD_HEADER_SIZE) &&
+        m_nCurPos+numBytes > (m_numDataBytes+MAP_COORD_HEADER_SIZE) &&
         m_nNextCoordBlock > 0)
     {
         // Data overlaps on more than one block
         // Read until end of this block and then recursively call ReadBytes()
         // for the rest.
-        int numBytesInThisBlock = 
+        int numBytesInThisBlock =
                       (m_numDataBytes+MAP_COORD_HEADER_SIZE)-m_nCurPos;
         nStatus = TABRawBinBlock::ReadBytes(numBytesInThisBlock, pabyDstBuf);
         if (nStatus == 0)
@@ -737,20 +781,20 @@ int     TABMAPCoordBlock::ReadBytes(int numBytes, GByte *pabyDstBuf)
  *                   TABMAPCoordBlock::WriteBytes()
  *
  * Cover function for TABRawBinBlock::WriteBytes() that will automagically
- * CommitToFile() the current block and create a new one if we are at 
+ * CommitToFile() the current block and create a new one if we are at
  * the end of the current block.
  *
  * Then the control is passed to TABRawBinBlock::WriteBytes() to finish the
  * work.
  *
  * Passing pabySrcBuf = NULL will only move the write pointer by the
- * specified number of bytes as if the copy had happened... but it 
+ * specified number of bytes as if the copy had happened... but it
  * won't crash.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
-int  TABMAPCoordBlock::WriteBytes(int nBytesToWrite, GByte *pabySrcBuf)
+int  TABMAPCoordBlock::WriteBytes(int nBytesToWrite, const GByte *pabySrcBuf)
 {
     if (m_eAccess != TABWrite && m_eAccess != TABReadWrite )
     {
@@ -764,7 +808,7 @@ int  TABMAPCoordBlock::WriteBytes(int nBytesToWrite, GByte *pabySrcBuf)
         if (nBytesToWrite <= (m_nBlockSize-MAP_COORD_HEADER_SIZE))
         {
             // Data won't fit in this block but can fit inside a single
-            // block, so we'll allocate a new block for it.  This will 
+            // block, so we'll allocate a new block for it.  This will
             // prevent us from overlapping coordinate values on 2 blocks, but
             // still allows strings longer than one block (see 'else' below).
             //
@@ -772,7 +816,7 @@ int  TABMAPCoordBlock::WriteBytes(int nBytesToWrite, GByte *pabySrcBuf)
             if ( m_nNextCoordBlock != 0 )
             {
                 // We're in read/write mode and there is already an allocated
-                // block following this one in the chain ... just reload it 
+                // block following this one in the chain ... just reload it
                 // and continue writing to it
 
                 CPLAssert( m_eAccess == TABReadWrite );
@@ -818,9 +862,9 @@ int  TABMAPCoordBlock::WriteBytes(int nBytesToWrite, GByte *pabySrcBuf)
 
                 nBytes = MIN(nBytes, nBytesToWrite);
 
-                // The following call will result in a new block being 
+                // The following call will result in a new block being
                 // allocated in the if() block above.
-                nStatus = TABMAPCoordBlock::WriteBytes(nBytes, 
+                nStatus = TABMAPCoordBlock::WriteBytes(nBytes,
                                                        pabySrcBuf);
 
                 nBytesToWrite -= nBytes;
@@ -877,13 +921,13 @@ void TABMAPCoordBlock::StartNewFeature()
  * Return the MBR of all the coords written using WriteIntCoord() since
  * the last call to StartNewFeature().
  **********************************************************************/
-void TABMAPCoordBlock::GetFeatureMBR(GInt32 &nXMin, GInt32 &nYMin, 
+void TABMAPCoordBlock::GetFeatureMBR(GInt32 &nXMin, GInt32 &nYMin,
                                      GInt32 &nXMax, GInt32 &nYMax)
 {
     nXMin = m_nFeatureXMin;
     nYMin = m_nFeatureYMin;
     nXMax = m_nFeatureXMax;
-    nYMax = m_nFeatureYMax; 
+    nYMax = m_nFeatureYMax;
 }
 
 
@@ -906,7 +950,7 @@ void TABMAPCoordBlock::Dump(FILE *fpOut /*=NULL*/)
     }
     else
     {
-        fprintf(fpOut,"Coordinate Block (type %d) at offset %d.\n", 
+        fprintf(fpOut,"Coordinate Block (type %d) at offset %d.\n",
                                                  m_nBlockType, m_nFileOffset);
         fprintf(fpOut,"  m_numDataBytes        = %d\n", m_numDataBytes);
         fprintf(fpOut,"  m_nNextCoordBlock     = %d\n", m_nNextCoordBlock);
@@ -916,6 +960,3 @@ void TABMAPCoordBlock::Dump(FILE *fpOut /*=NULL*/)
 }
 
 #endif // DEBUG
-
-
-
diff --git a/ogr/ogrsf_frmts/mitab/mitab_mapfile.cpp b/ogr/ogrsf_frmts/mitab/mitab_mapfile.cpp
index db945c1..2c825b8 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_mapfile.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_mapfile.cpp
@@ -18,16 +18,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -76,7 +76,7 @@
  *
  * Revision 1.34  2006/11/20 20:05:58  dmorissette
  * First pass at improving generation of spatial index in .map file (bug 1585)
- * New methods for insertion and splittung in the spatial index are done.
+ * New methods for insertion and splitting the spatial index are done.
  * Also implemented a method to dump the spatial index to .mif/.mid
  * Still need to implement splitting of TABMapObjectBlock to get optimal
  * results.
@@ -121,8 +121,8 @@
  * Prevent writing of coordinates outside of the +/-1e9 integer bounds.
  *
  * Revision 1.21  2001/11/17 21:54:06  daniel
- * Made several changes in order to support writing objects in 16 bits 
- * coordinate format. New TABMAPObjHdr-derived classes are used to hold 
+ * Made several changes in order to support writing objects in 16 bits
+ * coordinate format. New TABMAPObjHdr-derived classes are used to hold
  * object info in mem until block is full.
  *
  * Revision 1.20  2001/09/18 20:33:52  warmerda
@@ -222,11 +222,22 @@ TABMAPFile::TABMAPFile()
     m_nCurObjId = -1;
     m_poCurCoordBlock = NULL;
     m_poToolDefTable = NULL;
-    
+
     m_bUpdated = FALSE;
     m_bLastOpWasRead = FALSE;
     m_bLastOpWasWrite = FALSE;
-    
+
+    m_eAccessMode = TABRead;
+    m_poIdIndex = NULL;
+    m_sMinFilter.x = 0;
+    m_sMinFilter.y = 0;
+    m_sMaxFilter.x = 0;
+    m_sMaxFilter.y = 0;
+    m_XMinFilter = 0;
+    m_YMinFilter = 0;
+    m_XMaxFilter = 0;
+    m_YMaxFilter = 0;
+
     m_oBlockManager.SetName("MAP");
 }
 
@@ -250,9 +261,9 @@ TABMAPFile::~TABMAPFile()
 int TABMAPFile::Open(const char *pszFname, const char* pszAccess, GBool bNoErrorMsg,
                      int nBlockSizeForCreate)
 {
-    if( EQUALN(pszAccess, "r", 1) )
+    if( STARTS_WITH_CI(pszAccess, "r") )
         return Open(pszFname, TABRead, bNoErrorMsg, nBlockSizeForCreate);
-    else if( EQUALN(pszAccess, "w", 1) )
+    else if( STARTS_WITH_CI(pszAccess, "w") )
         return Open(pszFname, TABWrite, bNoErrorMsg, nBlockSizeForCreate);
     else
     {
@@ -269,9 +280,9 @@ int TABMAPFile::Open(const char *pszFname, const char* pszAccess, GBool bNoError
  * objects from it.
  *
  * Since .MAP and .ID files are optional, you can set bNoErrorMsg=TRUE to
- * disable the error message and receive an return value of 1 if file 
- * cannot be opened.  
- * In this case, only the methods MoveToObjId() and GetCurObjType() can 
+ * disable the error message and receive an return value of 1 if file
+ * cannot be opened.
+ * In this case, only the methods MoveToObjId() and GetCurObjType() can
  * be used.  They will behave as if the .ID file contained only null
  * references, so all object will look like they have NONE geometries.
  *
@@ -462,7 +473,6 @@ int TABMAPFile::Open(const char *pszFname, TABAccess eAccess,
 
         if( m_poHeader->m_nFirstIndexBlock != 0 )
         {
-            TABRawBinBlock *poBlock;
             poBlock = GetIndexObjectBlock( m_poHeader->m_nFirstIndexBlock );
             if( poBlock == NULL || (poBlock->GetBlockType() != TABMAP_INDEX_BLOCK &&
                                     poBlock->GetBlockType() != TABMAP_OBJECT_BLOCK) )
@@ -492,7 +502,7 @@ int TABMAPFile::Open(const char *pszFname, TABAccess eAccess,
      * as Read/Write calls are done later.
      *----------------------------------------------------------------*/
     m_poToolDefTable = NULL;
-    
+
     if( m_eAccessMode == TABReadWrite )
     {
         InitDrawingTools();
@@ -501,7 +511,11 @@ int TABMAPFile::Open(const char *pszFname, TABAccess eAccess,
     if( m_eAccessMode == TABReadWrite )
     {
         VSIStatBufL sStatBuf;
-        VSIStatL(m_pszFname, &sStatBuf);
+        if( VSIStatL(m_pszFname, &sStatBuf) != 0 )
+        {
+            Close();
+            return -1;
+        }
         m_oBlockManager.SetLastPtr((int)(((sStatBuf.st_size-1)/m_poHeader->m_nRegularBlockSize)*m_poHeader->m_nRegularBlockSize));
 
         /* Read chain of garbage blocks */
@@ -509,7 +523,7 @@ int TABMAPFile::Open(const char *pszFname, TABAccess eAccess,
         {
             int nCurGarbBlock = m_poHeader->m_nFirstGarbageBlock;
             m_oBlockManager.PushGarbageBlockAsLast(nCurGarbBlock);
-            while(TRUE)
+            while( true )
             {
                 GUInt16 nBlockType;
                 int     nNextGarbBlockPtr;
@@ -537,7 +551,7 @@ int TABMAPFile::Open(const char *pszFname, TABAccess eAccess,
     }
 
     /*-----------------------------------------------------------------
-     * Make sure all previous calls succeded.
+     * Make sure all previous calls succeeded.
      *----------------------------------------------------------------*/
     if (CPLGetLastErrorNo() != 0)
     {
@@ -571,7 +585,7 @@ int TABMAPFile::Close()
         SyncToDisk();
     }
 
-    // Delete all structures 
+    // Delete all structures
     if (m_poHeader)
         delete m_poHeader;
     m_poHeader = NULL;
@@ -635,7 +649,7 @@ int TABMAPFile::SyncToDisk()
         return -1;
     }
 
-    if( !m_bUpdated) 
+    if( !m_bUpdated)
         return 0;
 
     // Start by committing current object and coord blocks
@@ -657,17 +671,17 @@ int TABMAPFile::SyncToDisk()
         // OK, with V450 files, objects are not limited to 32k nodes
         // any more, and this means that m_nMaxCoordBufSize can become
         // huge, and actually more huge than can be held in memory.
-        // MapInfo counts m_nMaxCoordBufSize=0 for V450 objects, but 
-        // until this is cleanly implented, we will just prevent 
+        // MapInfo counts m_nMaxCoordBufSize=0 for V450 objects, but
+        // until this is cleanly implemented, we will just prevent
         // m_nMaxCoordBufSizefrom going beyond 512k in V450 files.
         if (m_nMinTABVersion >= 450)
         {
-            m_poHeader->m_nMaxCoordBufSize = 
+            m_poHeader->m_nMaxCoordBufSize =
                                 MIN(m_poHeader->m_nMaxCoordBufSize, 512*1024);
         }
 
         // Write Ref to beginning of the chain of garbage blocks
-        m_poHeader->m_nFirstGarbageBlock = 
+        m_poHeader->m_nFirstGarbageBlock =
             m_oBlockManager.GetFirstGarbageBlock();
 
         if( m_poHeader->CommitToFile() != 0 )
@@ -682,7 +696,7 @@ int TABMAPFile::SyncToDisk()
         Int2Coordsys(-1000000000, -1000000000, dBoundsMinX, dBoundsMinY);
         Int2Coordsys(1000000000, 1000000000, dBoundsMaxX, dBoundsMaxY);
 
-        CPLError(CE_Warning, TAB_WarningBoundsOverflow,
+        CPLError(CE_Warning, (CPLErrorNum)TAB_WarningBoundsOverflow,
                  "Some objects were written outside of the file's "
                  "predefined bounds.\n"
                  "These objects may have invalid coordinates when the file "
@@ -719,16 +733,16 @@ int TABMAPFile::ReOpenReadWrite()
 /**********************************************************************
  *                   TABMAPFile::SetQuickSpatialIndexMode()
  *
- * Select "quick spatial index mode". 
+ * Select "quick spatial index mode".
  *
  * The default behavior of MITAB is to generate an optimized spatial index,
- * but this results in slower write speed. 
+ * but this results in slower write speed.
  *
  * Applications that want faster write speed and do not care
  * about the performance of spatial queries on the resulting file can
  * use SetQuickSpatialIndexMode() to require the creation of a non-optimal
  * spatial index (actually emulating the type of spatial index produced
- * by MITAB before version 1.6.0). In this mode writing files can be 
+ * by MITAB before version 1.6.0). In this mode writing files can be
  * about 5 times faster, but spatial queries can be up to 30 times slower.
  *
  * Returns 0 on success, -1 on error.
@@ -782,12 +796,12 @@ TABRawBinBlock *TABMAPFile::PushBlock( int nFileOffset )
         }
         else
         {
-            CPLAssert( 
+            CPLAssert(
                 m_poSpIndexLeaf->GetEntry(
-                    m_poSpIndexLeaf->GetCurChildIndex())->nBlockPtr 
+                    m_poSpIndexLeaf->GetCurChildIndex())->nBlockPtr
                 == nFileOffset );
 
-            m_poSpIndexLeaf->SetCurChildRef( poIndex, 
+            m_poSpIndexLeaf->SetCurChildRef( poIndex,
                                          m_poSpIndexLeaf->GetCurChildIndex() );
             poIndex->SetParentRef( m_poSpIndexLeaf );
             m_poSpIndexLeaf = poIndex;
@@ -796,7 +810,7 @@ TABRawBinBlock *TABMAPFile::PushBlock( int nFileOffset )
     else
     {
         CPLAssert( poBlock->GetBlockType() == TABMAP_OBJECT_BLOCK );
-        
+
         if( m_poCurObjBlock != NULL )
             delete m_poCurObjBlock;
 
@@ -859,7 +873,7 @@ int TABMAPFile::LoadNextMatchingObjectBlock( int bFirstObject )
             else
                 delete m_poSpIndexLeaf;
             m_poSpIndexLeaf = poParent;
-            
+
             if( poParent != NULL )
             {
                 poParent->SetCurChildRef( NULL, poParent->GetCurChildIndex() );
@@ -871,7 +885,7 @@ int TABMAPFile::LoadNextMatchingObjectBlock( int bFirstObject )
 
         TABMAPIndexEntry *psEntry = m_poSpIndexLeaf->GetEntry( iEntry );
         TABRawBinBlock *poBlock;
-        
+
         if( psEntry->XMax < m_XMinFilter
             || psEntry->YMax < m_YMinFilter
             || psEntry->XMin > m_XMaxFilter
@@ -910,7 +924,7 @@ void TABMAPFile::ResetReading()
         m_poSpIndex->UnsetCurChild();
     }
     m_poSpIndexLeaf = NULL;
-    
+
     m_bLastOpWasWrite = FALSE;
     m_bLastOpWasRead = FALSE;
 }
@@ -953,8 +967,8 @@ int TABMAPFile::GetNextFeatureId( int nPrevId )
 /* -------------------------------------------------------------------- */
     if( nPrevId != -1 && m_nCurObjId != nPrevId )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "TABMAPFile::GetNextFeatureId(%d) called out of sequence.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "TABMAPFile::GetNextFeatureId(%d) called out of sequence.",
                   nPrevId );
         return -1;
     }
@@ -974,15 +988,15 @@ int TABMAPFile::GetNextFeatureId( int nPrevId )
 /*      Try to advance to the next object in the current object         */
 /*      block.                                                          */
 /* -------------------------------------------------------------------- */
-    if( nPrevId == -1 
+    if( nPrevId == -1
         || m_poCurObjBlock->AdvanceToNextObject(m_poHeader) == -1 )
     {
         // If not, try to advance to the next object block, and get
         // first object from it.  Note that some object blocks actually
-        // have no objects, so we may have to advance to additional 
+        // have no objects, so we may have to advance to additional
         // object blocks till we find a non-empty one.
         GBool bFirstCall = (nPrevId == -1);
-        do 
+        do
         {
             if( !LoadNextMatchingObjectBlock( bFirstCall ) )
                 return -1;
@@ -993,7 +1007,7 @@ int TABMAPFile::GetNextFeatureId( int nPrevId )
 
     m_nCurObjType = m_poCurObjBlock->GetCurObjectType();
     m_nCurObjId = m_poCurObjBlock->GetCurObjectId();
-    m_nCurObjPtr = m_poCurObjBlock->GetStartAddress() 
+    m_nCurObjPtr = m_poCurObjBlock->GetStartAddress()
         + m_poCurObjBlock->GetCurObjectOffset();
 
     CPLAssert( m_nCurObjId != -1 );
@@ -1023,7 +1037,7 @@ int TABMAPFile::Int2Coordsys(GInt32 nX, GInt32 nY, double &dX, double &dY)
 /**********************************************************************
  *                   TABMAPFile::Coordsys2Int()
  *
- * Convert from coordinates system units as defined in the file's 
+ * Convert from coordinates system units as defined in the file's
  * coordsys clause to long integer (internal) coordinates.
  *
  * Note that the false easting/northing and the conversion factor from
@@ -1031,7 +1045,7 @@ int TABMAPFile::Int2Coordsys(GInt32 nX, GInt32 nY, double &dX, double &dY)
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABMAPFile::Coordsys2Int(double dX, double dY, GInt32 &nX, GInt32 &nY, 
+int TABMAPFile::Coordsys2Int(double dX, double dY, GInt32 &nX, GInt32 &nY,
                              GBool bIgnoreOverflow/*=FALSE*/)
 {
     if (m_poHeader == NULL)
@@ -1066,8 +1080,8 @@ int TABMAPFile::Int2CoordsysDist(GInt32 nX, GInt32 nY, double &dX, double &dY)
 /**********************************************************************
  *                   TABMAPFile::Coordsys2IntDist()
  *
- * Convert a pair of X,Y size (or distance) values from coordinates 
- * system units as defined in the file's coordsys clause to long 
+ * Convert a pair of X,Y size (or distance) values from coordinates
+ * system units as defined in the file's coordsys clause to long
  * integer (internal) coordinate units.
  *
  * The difference with Int2Coordsys() is that this function only applies
@@ -1096,7 +1110,7 @@ int TABMAPFile::Coordsys2IntDist(double dX, double dY, GInt32 &nX, GInt32 &nY)
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABMAPFile::SetCoordsysBounds(double dXMin, double dYMin, 
+int TABMAPFile::SetCoordsysBounds(double dXMin, double dYMin,
                                   double dXMax, double dYMax)
 {
     int nStatus = 0;
@@ -1134,11 +1148,11 @@ GInt32 TABMAPFile::GetMaxObjId()
  *
  * Get ready to work with the object with the specified id.  The object
  * data pointer (inside m_poCurObjBlock) will be moved to the first byte
- * of data for this map object.  
+ * of data for this map object.
  *
- * The object type and id (i.e. table row number) will be accessible 
+ * The object type and id (i.e. table row number) will be accessible
  * using GetCurObjType() and GetCurObjId().
- * 
+ *
  * Note that object ids are positive and start at 1.
  *
  * Returns 0 on success, -1 on error.
@@ -1146,7 +1160,7 @@ GInt32 TABMAPFile::GetMaxObjId()
 int   TABMAPFile::MoveToObjId(int nObjId)
 {
     int nFileOffset;
-    
+
     if( m_bLastOpWasWrite )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -1161,7 +1175,7 @@ int   TABMAPFile::MoveToObjId(int nObjId)
     m_bLastOpWasRead = TRUE;
 
     /*-----------------------------------------------------------------
-     * In non creation mode, since the .MAP/.ID are optional, if the 
+     * In non creation mode, since the .MAP/.ID are optional, if the
      * file is not opened then we can still act as if one existed and
      * make any object id look like a TAB_GEOM_NONE
      *----------------------------------------------------------------*/
@@ -1258,17 +1272,17 @@ int   TABMAPFile::MoveToObjId(int nObjId)
 
 /**********************************************************************
  *                   TABMAPFile::MarkAsDeleted()
- 
+ *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
 int TABMAPFile::MarkAsDeleted()
 {
     if (m_eAccessMode == TABRead || m_poCurObjBlock == NULL)
         return -1;
-    
+
     if ( m_nCurObjPtr <= 0 )
         return 0;
-    
+
     /* Goto offset for object id */
     if ( m_poCurObjBlock->GotoByteInFile(m_nCurObjPtr + 1, TRUE) != 0)
         return -1;
@@ -1355,7 +1369,7 @@ void  TABMAPFile::UpdateMapHeaderInfo(TABGeomType nObjType)
     }
 
     /*-----------------------------------------------------------------
-     * Check forminimum TAB file version number
+     * Check for minimum TAB file version number
      *----------------------------------------------------------------*/
     int nVersion = TAB_GEOM_GET_VERSION(nObjType);
 
@@ -1370,7 +1384,7 @@ void  TABMAPFile::UpdateMapHeaderInfo(TABGeomType nObjType)
  *                   TABMAPFile::PrepareNewObj()
  *
  * Get ready to write a new object described by poObjHdr (using the
- * poObjHdr's m_nId (featureId), m_nType and IntMBR members which must 
+ * poObjHdr's m_nId (featureId), m_nType and IntMBR members which must
  * have been set by the caller).
  *
  * Depending on whether "quick spatial index mode" is selected, we either:
@@ -1379,14 +1393,14 @@ void  TABMAPFile::UpdateMapHeaderInfo(TABGeomType nObjType)
  * new object, update the spatial index references, and prepare the object
  * data block to be ready to write the object to it.
  * ... or ...
- * 2- prepare the current object data block to be ready to write the 
- * object to it. If the object block is full then it is inserted in the 
+ * 2- prepare the current object data block to be ready to write the
+ * object to it. If the object block is full then it is inserted in the
  * spatial index and committed to disk, and a new obj block is created.
  *
  * m_poCurObjBlock will be set to be ready to receive the new object, and
- * a new block will be created if necessary (in which case the current 
+ * a new block will be created if necessary (in which case the current
  * block contents will be committed to disk, etc.)  The actual ObjHdr
- * data won't be written to m_poCurObjBlock until CommitNewObj() is called. 
+ * data won't be written to m_poCurObjBlock until CommitNewObj() is called.
  *
  * If this object type uses coordinate blocks, then the coordinate block
  * will be prepared to receive coordinates.
@@ -1403,7 +1417,7 @@ int   TABMAPFile::PrepareNewObj(TABMAPObjHdr *poObjHdr)
     m_nCurObjPtr = m_nCurObjId = -1;
     m_nCurObjType = TAB_GEOM_UNSET;
 
-    if (m_eAccessMode == TABRead || 
+    if (m_eAccessMode == TABRead ||
         m_poIdIndex == NULL || m_poHeader == NULL)
     {
         CPLError(CE_Failure, CPLE_AssertionFailed,
@@ -1480,7 +1494,7 @@ int   TABMAPFile::PrepareNewObj(TABMAPObjHdr *poObjHdr)
     m_poIdIndex->SetObjPtr(m_nCurObjId, m_nCurObjPtr);
 
     /*-----------------------------------------------------------------
-     * Prepare Coords block... 
+     * Prepare Coords block...
      * create a new TABMAPCoordBlock if it was not done yet.
      *----------------------------------------------------------------*/
     PrepareCoordBlock(m_nCurObjType, m_poCurObjBlock, &m_poCurCoordBlock);
@@ -1498,8 +1512,8 @@ int   TABMAPFile::PrepareNewObj(TABMAPObjHdr *poObjHdr)
  *                   TABMAPFile::PrepareNewObjViaSpatialIndex()
  *
  * Used by TABMAPFile::PrepareNewObj() to walk through the spatial index
- * to find the best place to insert the new object, update the spatial 
- * index references, and prepare the object data block to be ready to 
+ * to find the best place to insert the new object, update the spatial
+ * index references, and prepare the object data block to be ready to
  * write the object to it.
  *
  * This method is used when "quick spatial index mode" is NOT selected,
@@ -1514,8 +1528,8 @@ int   TABMAPFile::PrepareNewObjViaSpatialIndex(TABMAPObjHdr *poObjHdr)
 
     /*-----------------------------------------------------------------
      * Create spatial index if we don't have one yet.
-     * We do not create the index and object data blocks in the open() 
-     * call because files that contained only "NONE" geometries ended up 
+     * We do not create the index and object data blocks in the open()
+     * call because files that contained only "NONE" geometries ended up
      * with empty object and spatial index blocks.
      *----------------------------------------------------------------*/
     if (m_poSpIndex == NULL)
@@ -1523,7 +1537,7 @@ int   TABMAPFile::PrepareNewObjViaSpatialIndex(TABMAPObjHdr *poObjHdr)
         // Spatial Index not created yet...
         m_poSpIndex = new TABMAPIndexBlock(m_eAccessMode);
 
-        m_poSpIndex->InitNewBlock(m_fp, m_poHeader->m_nRegularBlockSize, 
+        m_poSpIndex->InitNewBlock(m_fp, m_poHeader->m_nRegularBlockSize,
                                   m_oBlockManager.AllocNewBlock("INDEX"));
         m_poSpIndex->SetMAPBlockManagerRef(&m_oBlockManager);
 
@@ -1531,8 +1545,8 @@ int   TABMAPFile::PrepareNewObjViaSpatialIndex(TABMAPObjHdr *poObjHdr)
         {
             /* This can happen if the file created by MapInfo contains just */
             /* a few objects */
-            TABRawBinBlock *poBlock;
-            poBlock = GetIndexObjectBlock( m_poHeader->m_nFirstIndexBlock );
+            TABRawBinBlock *poBlock
+                = GetIndexObjectBlock( m_poHeader->m_nFirstIndexBlock );
             CPLAssert( poBlock != NULL && poBlock->GetBlockType() == TABMAP_OBJECT_BLOCK);
             delete poBlock;
 
@@ -1556,11 +1570,11 @@ int   TABMAPFile::PrepareNewObjViaSpatialIndex(TABMAPObjHdr *poObjHdr)
     }
     else
     /*-----------------------------------------------------------------
-     * Search the spatial index to find the best place to insert this 
-     * new object. 
+     * Search the spatial index to find the best place to insert this
+     * new object.
      *----------------------------------------------------------------*/
     {
-        nObjBlockForInsert=m_poSpIndex->ChooseLeafForInsert(poObjHdr->m_nMinX, 
+        nObjBlockForInsert=m_poSpIndex->ChooseLeafForInsert(poObjHdr->m_nMinX,
                                                             poObjHdr->m_nMinY,
                                                             poObjHdr->m_nMaxX,
                                                             poObjHdr->m_nMaxY);
@@ -1588,7 +1602,7 @@ int   TABMAPFile::PrepareNewObjViaSpatialIndex(TABMAPObjHdr *poObjHdr)
         /*-------------------------------------------------------------
          * Insert new object block in index, based on MBR of poObjHdr
          *------------------------------------------------------------*/
-        if (m_poSpIndex->AddEntry(poObjHdr->m_nMinX, 
+        if (m_poSpIndex->AddEntry(poObjHdr->m_nMinX,
                                   poObjHdr->m_nMinY,
                                   poObjHdr->m_nMaxX,
                                   poObjHdr->m_nMaxY,
@@ -1604,10 +1618,10 @@ int   TABMAPFile::PrepareNewObjViaSpatialIndex(TABMAPObjHdr *poObjHdr)
     else
     {
         /*-------------------------------------------------------------
-         * Load existing object and Coord blocks, unless we've already 
+         * Load existing object and Coord blocks, unless we've already
          * got the right object block in memory
          *------------------------------------------------------------*/
-        if (m_poCurObjBlock && 
+        if (m_poCurObjBlock &&
             m_poCurObjBlock->GetStartAddress() != nObjBlockForInsert)
         {
             /* Got a block in memory but it's not the right one, flush it */
@@ -1638,7 +1652,7 @@ int   TABMAPFile::PrepareNewObjViaSpatialIndex(TABMAPObjHdr *poObjHdr)
     }
 
     /*-----------------------------------------------------------------
-     * Fetch new object size, make sure there is enough room in obj. 
+     * Fetch new object size, make sure there is enough room in obj.
      * block for new object, update spatial index and split if necessary.
      *----------------------------------------------------------------*/
     nObjSize = m_poHeader->GetMapObjectSize(poObjHdr->m_nType);
@@ -1652,19 +1666,19 @@ int   TABMAPFile::PrepareNewObjViaSpatialIndex(TABMAPObjHdr *poObjHdr)
     {
         TABMAPObjHdr *poExistingObjHdr=NULL;
         TABMAPObjHdr **papoSrcObjHdrs = NULL;
-        int i, numSrcObj = 0;
+        int numSrcObj = 0;
         int nObjectSpace = 0;
 
         /* First pass to enumerate valid objects and compute their accumulated
            required size. */
         m_poCurObjBlock->Rewind();
-        while ((poExistingObjHdr = TABMAPObjHdr::ReadNextObj(m_poCurObjBlock, 
+        while ((poExistingObjHdr = TABMAPObjHdr::ReadNextObj(m_poCurObjBlock,
                                                     m_poHeader)) != NULL)
         {
             if (papoSrcObjHdrs == NULL || numSrcObj%10 == 0)
             {
                 // Realloc the array... by steps of 10
-                papoSrcObjHdrs = (TABMAPObjHdr**)CPLRealloc(papoSrcObjHdrs, 
+                papoSrcObjHdrs = (TABMAPObjHdr**)CPLRealloc(papoSrcObjHdrs,
                                                             (numSrcObj+10)*
                                                             sizeof(TABMAPObjHdr*));
             }
@@ -1683,7 +1697,7 @@ int   TABMAPFile::PrepareNewObjViaSpatialIndex(TABMAPObjHdr *poObjHdr)
 #endif
             m_poCurObjBlock->ClearObjects();
 
-            for(i=0; i<numSrcObj; i++)
+            for(int i=0; i<numSrcObj; i++)
             {
                 /*-----------------------------------------------------------------
                 * Prepare and Write ObjHdr to this ObjBlock
@@ -1695,6 +1709,12 @@ int   TABMAPFile::PrepareNewObjViaSpatialIndex(TABMAPObjHdr *poObjHdr)
                     CPLError(CE_Failure, CPLE_FileIO,
                             "Failed writing object header for feature id %d",
                             papoSrcObjHdrs[i]->m_nId);
+                    for(int j=0; j<numSrcObj; j++)
+                    {
+                      delete papoSrcObjHdrs[j];
+                    }
+                    CPLFree(papoSrcObjHdrs);
+                    papoSrcObjHdrs = NULL;
                     return -1;
                 }
 
@@ -1706,7 +1726,7 @@ int   TABMAPFile::PrepareNewObjViaSpatialIndex(TABMAPObjHdr *poObjHdr)
         }
 
         /* Cleanup papoSrcObjHdrs[] */
-        for(i=0; i<numSrcObj; i++)
+        for(int i=0; i<numSrcObj; i++)
         {
             delete papoSrcObjHdrs[i];
         }
@@ -1727,7 +1747,7 @@ int   TABMAPFile::PrepareNewObjViaSpatialIndex(TABMAPObjHdr *poObjHdr)
         nMinY = MIN(nMinY, poObjHdr->m_nMinY);
         nMaxX = MAX(nMaxX, poObjHdr->m_nMaxX);
         nMaxY = MAX(nMaxY, poObjHdr->m_nMaxY);
-        
+
         m_poCurObjBlock->SetMBR(nMinX, nMinY, nMaxX, nMaxY);
 
         if (m_poSpIndex->UpdateLeafEntry(m_poCurObjBlock->GetStartAddress(),
@@ -1739,13 +1759,13 @@ int   TABMAPFile::PrepareNewObjViaSpatialIndex(TABMAPObjHdr *poObjHdr)
         /*-------------------------------------------------------------
          * OK, the new object won't fit in the current block, need to split
          * and update index.
-         * Split() does its job so that the current obj block will remain 
-         * the best candidate to receive the new object. It also flushes 
+         * Split() does its job so that the current obj block will remain
+         * the best candidate to receive the new object. It also flushes
          * everything to disk and will update m_poCurCoordBlock to point to
          * the last coord block in the chain, ready to accept new data
          *------------------------------------------------------------*/
-        TABMAPObjectBlock *poNewObjBlock;
-        poNewObjBlock= SplitObjBlock(poObjHdr, nObjSize);
+        TABMAPObjectBlock *poNewObjBlock
+            = SplitObjBlock(poObjHdr, nObjSize);
 
         if (poNewObjBlock == NULL)
             return -1;  /* Split failed, error already reported. */
@@ -1764,7 +1784,7 @@ int   TABMAPFile::PrepareNewObjViaSpatialIndex(TABMAPObjHdr *poObjHdr)
         nMinY = MIN(nMinY, poObjHdr->m_nMinY);
         nMaxX = MAX(nMaxX, poObjHdr->m_nMaxX);
         nMaxY = MAX(nMaxY, poObjHdr->m_nMaxY);
-        
+
         m_poCurObjBlock->SetMBR(nMinX, nMinY, nMaxX, nMaxY);
 
         if (m_poSpIndex->UpdateLeafEntry(m_poCurObjBlock->GetStartAddress(),
@@ -1796,8 +1816,8 @@ int   TABMAPFile::PrepareNewObjViaSpatialIndex(TABMAPObjHdr *poObjHdr)
 /**********************************************************************
  *                   TABMAPFile::PrepareNewObjViaObjBlock()
  *
- * Used by TABMAPFile::PrepareNewObj() to prepare the current object 
- * data block to be ready to write the object to it. If the object block 
+ * Used by TABMAPFile::PrepareNewObj() to prepare the current object
+ * data block to be ready to write the object to it. If the object block
  * is full then it is inserted in the spatial index and committed to disk,
  * and a new obj block is created.
  *
@@ -1808,8 +1828,6 @@ int   TABMAPFile::PrepareNewObjViaSpatialIndex(TABMAPObjHdr *poObjHdr)
  **********************************************************************/
 int   TABMAPFile::PrepareNewObjViaObjBlock(TABMAPObjHdr *poObjHdr)
 {
-    int nObjSize;
-
     /*-------------------------------------------------------------
      * We will need an object block... check if it exists and
      * create it if it has not been created yet (first time for this file).
@@ -1826,17 +1844,17 @@ int   TABMAPFile::PrepareNewObjViaObjBlock(TABMAPObjHdr *poObjHdr)
 
         m_poCurObjBlock->InitNewBlock(m_fp, m_poHeader->m_nRegularBlockSize, nBlockOffset);
 
-        // The reference to the first object block should 
-        // actually go through the index blocks... this will be 
+        // The reference to the first object block should
+        // actually go through the index blocks... this will be
         // updated when file is closed.
         m_poHeader->m_nFirstIndexBlock = nBlockOffset;
     }
 
     /*-----------------------------------------------------------------
-     * Fetch new object size, make sure there is enough room in obj. 
+     * Fetch new object size, make sure there is enough room in obj.
      * block for new object, and save/create a new one if necessary.
      *----------------------------------------------------------------*/
-    nObjSize = m_poHeader->GetMapObjectSize(poObjHdr->m_nType);
+    const int nObjSize = m_poHeader->GetMapObjectSize(poObjHdr->m_nType);
     if (m_poCurObjBlock->GetNumUnusedBytes() < nObjSize )
     {
         /*-------------------------------------------------------------
@@ -1869,13 +1887,19 @@ int   TABMAPFile::PrepareNewObjViaObjBlock(TABMAPObjHdr *poObjHdr)
 /**********************************************************************
  *                   TABMAPFile::CommitNewObj()
  *
- * Commit object header data to the ObjBlock. Should be called after 
+ * Commit object header data to the ObjBlock. Should be called after
  * PrepareNewObj, once all members of the ObjHdr have been set.
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
 int   TABMAPFile::CommitNewObj(TABMAPObjHdr *poObjHdr)
 {
+    // Nothing to do for NONE objects
+    if (poObjHdr->m_nType == TAB_GEOM_NONE)
+    {
+        return 0;
+    }
+
     /* Update this now so that PrepareCoordBlock() doesn't try to old an older */
     /* block */
     if( m_poCurCoordBlock != NULL )
@@ -1910,7 +1934,7 @@ int TABMAPFile::CommitObjAndCoordBlocks(GBool bDeleteObjects /*=FALSE*/)
      * no object block in files that contain only "NONE" geometries.
      *----------------------------------------------------------------*/
     if (m_poCurObjBlock == NULL)
-        return 0; 
+        return 0;
 
     if (m_eAccessMode == TABRead)
     {
@@ -1918,7 +1942,7 @@ int TABMAPFile::CommitObjAndCoordBlocks(GBool bDeleteObjects /*=FALSE*/)
                  "CommitObjAndCoordBlocks() failed: file not opened for write access.");
         return -1;
     }
-    
+
     if (!m_bLastOpWasWrite)
     {
         if (bDeleteObjects)
@@ -1967,8 +1991,8 @@ int TABMAPFile::CommitObjAndCoordBlocks(GBool bDeleteObjects /*=FALSE*/)
 
 
     /*-----------------------------------------------------------------
-     * Update the spatial index ** only in "quick spatial index" mode ** 
-     * In the (default) optimized spatial index mode, the spatial index 
+     * Update the spatial index ** only in "quick spatial index" mode **
+     * In the (default) optimized spatial index mode, the spatial index
      * is already maintained up to date as part of inserting the objects in
      * PrepareNewObj().
      *
@@ -1976,20 +2000,19 @@ int TABMAPFile::CommitObjAndCoordBlocks(GBool bDeleteObjects /*=FALSE*/)
      *----------------------------------------------------------------*/
     if (nStatus == 0 && m_bQuickSpatialIndexMode)
     {
-        GInt32 nXMin, nYMin, nXMax, nYMax;
-
         if (m_poSpIndex == NULL)
         {
             // Spatial Index not created yet...
             m_poSpIndex = new TABMAPIndexBlock(m_eAccessMode);
 
-            m_poSpIndex->InitNewBlock(m_fp, m_poHeader->m_nRegularBlockSize, 
+            m_poSpIndex->InitNewBlock(m_fp, m_poHeader->m_nRegularBlockSize,
                                       m_oBlockManager.AllocNewBlock("INDEX"));
             m_poSpIndex->SetMAPBlockManagerRef(&m_oBlockManager);
 
             m_poHeader->m_nFirstIndexBlock = m_poSpIndex->GetNodeBlockPtr();
         }
 
+        GInt32 nXMin, nYMin, nXMax, nYMax;
         m_poCurObjBlock->GetMBR(nXMin, nYMin, nXMax, nYMax);
         nStatus = m_poSpIndex->AddEntry(nXMin, nYMin, nXMax, nYMax,
                                         m_poCurObjBlock->GetStartAddress());
@@ -2013,18 +2036,16 @@ int TABMAPFile::CommitObjAndCoordBlocks(GBool bDeleteObjects /*=FALSE*/)
 /**********************************************************************
  *                   TABMAPFile::LoadObjAndCoordBlocks()
  *
- * Load the TABMAPObjBlock at specified address and corresponding 
+ * Load the TABMAPObjBlock at specified address and corresponding
  * TABMAPCoordBlock, ready to write new objects to them.
  *
- * It is assumed that pre-existing m_poCurObjBlock and m_poCurCoordBlock 
+ * It is assumed that pre-existing m_poCurObjBlock and m_poCurCoordBlock
  * have been flushed to disk already using CommitObjAndCoordBlocks()
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
 int TABMAPFile::LoadObjAndCoordBlocks(GInt32 nBlockPtr)
 {
-    TABRawBinBlock *poBlock = NULL;
-
     /*-----------------------------------------------------------------
      * In Write mode, if an object block is already in memory then flush it
      *----------------------------------------------------------------*/
@@ -2038,9 +2059,10 @@ int TABMAPFile::LoadObjAndCoordBlocks(GInt32 nBlockPtr)
     /*-----------------------------------------------------------------
      * Load Obj Block
      *----------------------------------------------------------------*/
-    poBlock = TABCreateMAPBlockFromFile(m_fp, 
-                                             nBlockPtr,
-                                             m_poHeader->m_nRegularBlockSize, TRUE, TABReadWrite);;
+    TABRawBinBlock *poBlock =
+        TABCreateMAPBlockFromFile(m_fp,
+                                  nBlockPtr,
+                                  m_poHeader->m_nRegularBlockSize, TRUE, TABReadWrite);
     if (poBlock != NULL &&
         poBlock->GetBlockClass() == TABMAP_OBJECT_BLOCK)
     {
@@ -2050,7 +2072,7 @@ int TABMAPFile::LoadObjAndCoordBlocks(GInt32 nBlockPtr)
     else
     {
         CPLError(CE_Failure, CPLE_FileIO,
-                 "LoadObjAndCoordBlocks() failed for object block at %d.", 
+                 "LoadObjAndCoordBlocks() failed for object block at %d.",
                  nBlockPtr);
         return -1;
     }
@@ -2064,7 +2086,7 @@ int TABMAPFile::LoadObjAndCoordBlocks(GInt32 nBlockPtr)
         return 0;
     }
 
-    poBlock = TABCreateMAPBlockFromFile(m_fp, 
+    poBlock = TABCreateMAPBlockFromFile(m_fp,
                                    m_poCurObjBlock->GetLastCoordBlockAddress(),
                                    m_poHeader->m_nRegularBlockSize, TRUE, TABReadWrite);
     if (poBlock != NULL && poBlock->GetBlockClass() == TABMAP_COORD_BLOCK)
@@ -2076,7 +2098,7 @@ int TABMAPFile::LoadObjAndCoordBlocks(GInt32 nBlockPtr)
     else
     {
         CPLError(CE_Failure, CPLE_FileIO,
-                 "LoadObjAndCoordBlocks() failed for coord block at %d.", 
+                 "LoadObjAndCoordBlocks() failed for coord block at %d.",
                  m_poCurObjBlock->GetLastCoordBlockAddress());
         return -1;
     }
@@ -2089,9 +2111,9 @@ int TABMAPFile::LoadObjAndCoordBlocks(GInt32 nBlockPtr)
  *
  * Split m_poCurObjBlock using Guttman algorithm.
  *
- * SplitObjBlock() doe its job so that the current obj block will remain 
+ * SplitObjBlock() doe its job so that the current obj block will remain
  * the best candidate to receive the new object to add. It also flushes
- * everything to disk and will update m_poCurCoordBlock to point to the 
+ * everything to disk and will update m_poCurCoordBlock to point to the
  * last coord block in the chain, ready to accept new data
  *
  * Updates to the spatial index are left to the caller.
@@ -2109,13 +2131,13 @@ TABMAPObjectBlock *TABMAPFile::SplitObjBlock(TABMAPObjHdr *poObjHdrToAdd,
      * Read all object headers
      *----------------------------------------------------------------*/
     m_poCurObjBlock->Rewind();
-    while ((poObjHdr = TABMAPObjHdr::ReadNextObj(m_poCurObjBlock, 
+    while ((poObjHdr = TABMAPObjHdr::ReadNextObj(m_poCurObjBlock,
                                                  m_poHeader)) != NULL)
     {
         if (papoSrcObjHdrs == NULL || numSrcObj%10 == 0)
         {
             // Realloc the array... by steps of 10
-            papoSrcObjHdrs = (TABMAPObjHdr**)CPLRealloc(papoSrcObjHdrs, 
+            papoSrcObjHdrs = (TABMAPObjHdr**)CPLRealloc(papoSrcObjHdrs,
                                                         (numSrcObj+10)*
                                                         sizeof(TABMAPObjHdr*));
         }
@@ -2125,11 +2147,11 @@ TABMAPObjectBlock *TABMAPFile::SplitObjBlock(TABMAPObjHdr *poObjHdrToAdd,
     CPLAssert(numSrcObj > 1);
 
     /*-----------------------------------------------------------------
-     * Reset current obj and coord block 
+     * Reset current obj and coord block
      *----------------------------------------------------------------*/
     GInt32 nFirstSrcCoordBlock = m_poCurObjBlock->GetFirstCoordBlockAddress();
 
-    m_poCurObjBlock->InitNewBlock(m_fp, m_poHeader->m_nRegularBlockSize, 
+    m_poCurObjBlock->InitNewBlock(m_fp, m_poHeader->m_nRegularBlockSize,
                                   m_poCurObjBlock->GetStartAddress());
 
     TABMAPCoordBlock *poSrcCoordBlock = m_poCurCoordBlock;
@@ -2146,12 +2168,12 @@ TABMAPObjectBlock *TABMAPFile::SplitObjBlock(TABMAPObjHdr *poObjHdrToAdd,
     poNewObjBlock->SetCenterFromOtherBlock(m_poCurObjBlock);
 
     /* Coord block will be alloc'd automatically*/
-    TABMAPCoordBlock *poNewCoordBlock = NULL;  
+    TABMAPCoordBlock *poNewCoordBlock = NULL;
 
     /*-----------------------------------------------------------------
      * Pick Seeds for each block
      *----------------------------------------------------------------*/
-    TABMAPIndexEntry *pasSrcEntries = 
+    TABMAPIndexEntry *pasSrcEntries =
         (TABMAPIndexEntry*)CPLMalloc(numSrcObj*sizeof(TABMAPIndexEntry));
     for (i=0; i<numSrcObj; i++)
     {
@@ -2178,16 +2200,20 @@ TABMAPObjectBlock *TABMAPFile::SplitObjBlock(TABMAPObjHdr *poObjHdrToAdd,
     poObjHdr = papoSrcObjHdrs[nSeed1];
     if (MoveObjToBlock(poObjHdr, poSrcCoordBlock,
                        m_poCurObjBlock, &m_poCurCoordBlock) <= 0)
-        return NULL;
+    {
+        goto error;
+    }
 
     // Move nSeed2 to 2nd block
     poObjHdr = papoSrcObjHdrs[nSeed2];
     if (MoveObjToBlock(poObjHdr, poSrcCoordBlock,
                        poNewObjBlock, &poNewCoordBlock) <= 0)
-        return NULL;
+    {
+        goto error;
+    }
 
     /*-----------------------------------------------------------------
-     * Go through the rest of the entries and assign them to one 
+     * Go through the rest of the entries and assign them to one
      * of the 2 blocks
      *
      * Criteria is minimal area difference.
@@ -2209,14 +2235,14 @@ TABMAPObjectBlock *TABMAPFile::SplitObjBlock(TABMAPObjHdr *poObjHdrToAdd,
         {
             if (MoveObjToBlock(poObjHdr, poSrcCoordBlock,
                                poNewObjBlock, &poNewCoordBlock) <= 0)
-                return NULL;
+                goto error;
             continue;
         }
         else if (poNewObjBlock->GetNumUnusedBytes() < nObjSize+nSizeOfObjToAdd)
         {
             if (MoveObjToBlock(poObjHdr, poSrcCoordBlock,
                                m_poCurObjBlock, &m_poCurCoordBlock) <= 0)
-                return NULL;
+                goto error;
             continue;
         }
 
@@ -2224,19 +2250,19 @@ TABMAPObjectBlock *TABMAPFile::SplitObjBlock(TABMAPObjHdr *poObjHdrToAdd,
         GInt32 nXMin, nYMin, nXMax, nYMax;
         m_poCurObjBlock->GetMBR(nXMin, nYMin, nXMax, nYMax);
         CPLAssert( nXMin <= nXMax );
-        double dAreaDiff1 = 
-            TABMAPIndexBlock::ComputeAreaDiff(nXMin, nYMin, 
+        double dAreaDiff1 =
+            TABMAPIndexBlock::ComputeAreaDiff(nXMin, nYMin,
                                               nXMax, nYMax,
-                                              poObjHdr->m_nMinX, 
+                                              poObjHdr->m_nMinX,
                                               poObjHdr->m_nMinY,
                                               poObjHdr->m_nMaxX,
                                               poObjHdr->m_nMaxY);
 
         poNewObjBlock->GetMBR(nXMin, nYMin, nXMax, nYMax);
         CPLAssert( nXMin <= nXMax );
-        double dAreaDiff2 = 
+        double dAreaDiff2 =
             TABMAPIndexBlock::ComputeAreaDiff(nXMin, nYMin, nXMax, nYMax,
-                                              poObjHdr->m_nMinX, 
+                                              poObjHdr->m_nMinX,
                                               poObjHdr->m_nMinY,
                                               poObjHdr->m_nMaxX,
                                               poObjHdr->m_nMaxY);
@@ -2246,14 +2272,14 @@ TABMAPObjectBlock *TABMAPFile::SplitObjBlock(TABMAPObjHdr *poObjHdrToAdd,
             // This entry stays in this block
             if (MoveObjToBlock(poObjHdr, poSrcCoordBlock,
                                m_poCurObjBlock, &m_poCurCoordBlock) <= 0)
-                return NULL;
+                goto error;
         }
         else
         {
             // This entry goes to new block
             if (MoveObjToBlock(poObjHdr, poSrcCoordBlock,
                                poNewObjBlock, &poNewCoordBlock) <= 0)
-                return NULL;
+                goto error;
         }
     }
 
@@ -2273,7 +2299,9 @@ TABMAPObjectBlock *TABMAPFile::SplitObjBlock(TABMAPObjHdr *poObjHdrToAdd,
     if (poNewCoordBlock)
     {
         if (poNewCoordBlock->CommitToFile() != 0)
-            return NULL;
+        {
+            goto error;
+        }
         delete poNewCoordBlock;
     }
 
@@ -2285,7 +2313,9 @@ TABMAPObjectBlock *TABMAPFile::SplitObjBlock(TABMAPObjHdr *poObjHdrToAdd,
         if (poSrcCoordBlock->GetStartAddress() != nFirstSrcCoordBlock)
         {
             if (poSrcCoordBlock->GotoByteInFile(nFirstSrcCoordBlock, TRUE) != 0)
-                return NULL;
+            {
+                goto error;
+            }
         }
 
         int nNextCoordBlock = poSrcCoordBlock->GetNextCoordBlock();
@@ -2294,14 +2324,17 @@ TABMAPObjectBlock *TABMAPFile::SplitObjBlock(TABMAPObjHdr *poObjHdrToAdd,
             // Mark this block as deleted
             if (poSrcCoordBlock->CommitAsDeleted(m_oBlockManager.
                                                  GetFirstGarbageBlock()) != 0)
-                return NULL;
+            {
+                goto error;
+            }
             m_oBlockManager.PushGarbageBlockAsFirst(poSrcCoordBlock->GetStartAddress());
 
             // Advance to next
             if (nNextCoordBlock > 0)
             {
                 if (poSrcCoordBlock->GotoByteInFile(nNextCoordBlock, TRUE) != 0)
-                    return NULL;
+                    goto error;
+
                 nNextCoordBlock = poSrcCoordBlock->GetNextCoordBlock();
             }
             else
@@ -2312,18 +2345,30 @@ TABMAPObjectBlock *TABMAPFile::SplitObjBlock(TABMAPObjHdr *poObjHdrToAdd,
             }
         }
     }
-            
 
     if (poNewObjBlock->CommitToFile() != 0)
-        return NULL;
+        goto error;
 
     return poNewObjBlock;
+
+error:
+    if( papoSrcObjHdrs )
+    {
+        for(i=0; i<numSrcObj; i++)
+        {
+            delete papoSrcObjHdrs[i];
+        }
+        CPLFree(papoSrcObjHdrs);
+    }
+    delete poSrcCoordBlock;
+    delete poNewObjBlock;
+    return NULL;
 }
 
 /**********************************************************************
  *                   TABMAPFile::MoveObjToBlock()
  *
- * Moves an object and its coord data to a new ObjBlock. Used when 
+ * Moves an object and its coord data to a new ObjBlock. Used when
  * splitting Obj Blocks.
  *
  * May update the value of ppoCoordBlock if a new coord block had to
@@ -2348,11 +2393,11 @@ int TABMAPFile::MoveObjToBlock(TABMAPObjHdr       *poObjHdr,
         // Ref count defaults to 0... set it to 1
         poDummyDefn->Reference();
 
-        TABFeature *poFeature = 
+        TABFeature *poFeature =
             TABFeature::CreateFromMapInfoType(poObjHdr->m_nType, poDummyDefn);
 
 
-        if (PrepareCoordBlock(poObjHdrCoord->m_nType, 
+        if (PrepareCoordBlock(poObjHdrCoord->m_nType,
                               poDstObjBlock, ppoDstCoordBlock) != 0)
             return -1;
 
@@ -2421,7 +2466,7 @@ int TABMAPFile::PrepareCoordBlock(int nObjType,
 {
 
     /*-----------------------------------------------------------------
-     * Prepare Coords block... 
+     * Prepare Coords block...
      * create a new TABMAPCoordBlock if it was not done yet.
      * Note that in write mode, TABCollections require read/write access
      * to the coord block.
@@ -2431,9 +2476,9 @@ int TABMAPFile::PrepareCoordBlock(int nObjType,
         if (*ppoCoordBlock == NULL)
         {
             *ppoCoordBlock = new TABMAPCoordBlock(m_eAccessMode==TABWrite?
-                                                  TABReadWrite: 
+                                                  TABReadWrite:
                                                   m_eAccessMode);
-            (*ppoCoordBlock)->InitNewBlock(m_fp, m_poHeader->m_nRegularBlockSize, 
+            (*ppoCoordBlock)->InitNewBlock(m_fp, m_poHeader->m_nRegularBlockSize,
                                            m_oBlockManager.AllocNewBlock("COORD"));
             (*ppoCoordBlock)->SetMAPBlockManagerRef(&m_oBlockManager);
 
@@ -2444,7 +2489,7 @@ int TABMAPFile::PrepareCoordBlock(int nObjType,
         /* reload us */
         else if( (*ppoCoordBlock)->GetStartAddress() != poObjBlock->GetLastCoordBlockAddress() )
         {
-            TABRawBinBlock* poBlock = TABCreateMAPBlockFromFile(m_fp, 
+            TABRawBinBlock* poBlock = TABCreateMAPBlockFromFile(m_fp,
                                     poObjBlock->GetLastCoordBlockAddress(),
                                     m_poHeader->m_nRegularBlockSize, TRUE, TABReadWrite);
             if (poBlock != NULL && poBlock->GetBlockClass() == TABMAP_COORD_BLOCK)
@@ -2457,7 +2502,7 @@ int TABMAPFile::PrepareCoordBlock(int nObjType,
             {
                 delete poBlock;
                 CPLError(CE_Failure, CPLE_FileIO,
-                            "LoadObjAndCoordBlocks() failed for coord block at %d.", 
+                            "LoadObjAndCoordBlocks() failed for coord block at %d.",
                             poObjBlock->GetLastCoordBlockAddress());
                 return -1;
             }
@@ -2467,7 +2512,7 @@ int TABMAPFile::PrepareCoordBlock(int nObjType,
         {
             int nNewBlockOffset = m_oBlockManager.AllocNewBlock("COORD");
             (*ppoCoordBlock)->SetNextCoordBlock(nNewBlockOffset);
-            (*ppoCoordBlock)->CommitToFile();
+            CPL_IGNORE_RET_VAL((*ppoCoordBlock)->CommitToFile());
             (*ppoCoordBlock)->InitNewBlock(m_fp, m_poHeader->m_nRegularBlockSize, nNewBlockOffset);
             poObjBlock->AddCoordBlockRef((*ppoCoordBlock)->GetStartAddress());
         }
@@ -2511,8 +2556,8 @@ int TABMAPFile::GetCurObjId()
 /**********************************************************************
  *                   TABMAPFile::GetCurObjBlock()
  *
- * Return the m_poCurObjBlock.  If MoveToObjId() has previously been 
- * called then m_poCurObjBlock points to the beginning of the current 
+ * Return the m_poCurObjBlock.  If MoveToObjId() has previously been
+ * called then m_poCurObjBlock points to the beginning of the current
  * object data.
  *
  * Returns a reference to an object owned by this TABMAPFile object, or
@@ -2526,7 +2571,7 @@ TABMAPObjectBlock *TABMAPFile::GetCurObjBlock()
 /**********************************************************************
  *                   TABMAPFile::GetCurCoordBlock()
  *
- * Return the m_poCurCoordBlock.  This function should be used after 
+ * Return the m_poCurCoordBlock.  This function should be used after
  * PrepareNewObj() to get the reference to the coord block that has
  * just been initialized.
  *
@@ -2617,12 +2662,12 @@ TABIDFile *TABMAPFile::GetIDFileRef()
  *
  * Ownership of the returned block is turned over to the caller, who should
  * delete it when no longer needed.  The type of the block can be determined
- * with the GetBlockType() method. 
+ * with the GetBlockType() method.
  *
  * @param nFileOffset the offset in the map file of the spatial index
  * block or object block to load.
  *
- * @return The requested TABMAPIndexBlock, TABMAPObjectBlock or NULL if the 
+ * @return The requested TABMAPIndexBlock, TABMAPObjectBlock or NULL if the
  * read fails for some reason.
  **********************************************************************/
 TABRawBinBlock *TABMAPFile::GetIndexObjectBlock( int nFileOffset )
@@ -2632,7 +2677,7 @@ TABRawBinBlock *TABMAPFile::GetIndexObjectBlock( int nFileOffset )
      *---------------------------------------------------------------*/
     GByte* pabyData = (GByte*) CPLMalloc(m_poHeader->m_nRegularBlockSize);
 
-    if (VSIFSeekL(m_fp, nFileOffset, SEEK_SET) != 0 
+    if (VSIFSeekL(m_fp, nFileOffset, SEEK_SET) != 0
         || (int)VSIFReadL(pabyData, sizeof(GByte), m_poHeader->m_nRegularBlockSize, m_fp) !=
                         m_poHeader->m_nRegularBlockSize )
     {
@@ -2657,7 +2702,7 @@ TABRawBinBlock *TABMAPFile::GetIndexObjectBlock( int nFileOffset )
     }
     else
         poBlock = new TABMAPObjectBlock(m_eAccessMode);
-    
+
     poBlock->InitBlockFromData(pabyData,
                                    m_poHeader->m_nRegularBlockSize,
                                    m_poHeader->m_nRegularBlockSize,
@@ -2685,13 +2730,13 @@ int TABMAPFile::InitDrawingTools()
         return -1;    // File not opened yet!
 
     /*-------------------------------------------------------------
-     * We want to perform this initialisation only ONCE
+     * We want to perform this initialization only once
      *------------------------------------------------------------*/
     if (m_poToolDefTable != NULL)
         return 0;
 
     /*-------------------------------------------------------------
-     * Create a new ToolDefTable... no more initialization is required 
+     * Create a new ToolDefTable... no more initialization is required
      * unless we want to read tool blocks from file.
      *------------------------------------------------------------*/
     m_poToolDefTable = new TABToolDefTable;
@@ -2703,7 +2748,7 @@ int TABMAPFile::InitDrawingTools()
 
         poBlock = new TABMAPToolBlock(TABRead);
         poBlock->InitNewBlock(m_fp, m_poHeader->m_nRegularBlockSize);
-    
+
         /*-------------------------------------------------------------
          * Use GotoByteInFile() to go to the first block's location.  This will
          * force loading the block if necessary and reading its header.
@@ -2733,7 +2778,7 @@ int TABMAPFile::InitDrawingTools()
  * Write the drawing tools for this file.
  *
  * This function applies only to write access mode.
- * 
+ *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
 int TABMAPFile::CommitDrawingTools()
@@ -2760,7 +2805,7 @@ int TABMAPFile::CommitDrawingTools()
      * Create a new TABMAPToolBlock and update header fields
      *------------------------------------------------------------*/
     TABMAPToolBlock *poBlock;
-    
+
     poBlock = new TABMAPToolBlock(m_eAccessMode);
     if( m_poHeader->m_nFirstToolBlock != 0 )
         poBlock->InitNewBlock(m_fp, m_poHeader->m_nRegularBlockSize, m_poHeader->m_nFirstToolBlock);
@@ -2781,7 +2826,7 @@ int TABMAPFile::CommitDrawingTools()
      * by WriteAllToolDefs() )
      *------------------------------------------------------------*/
     nStatus = m_poToolDefTable->WriteAllToolDefs(poBlock);
-    
+
     m_poHeader->m_numMapToolBlocks = (GInt16)poBlock->GetNumBlocksInChain();
 
     delete poBlock;
@@ -2829,14 +2874,14 @@ int   TABMAPFile::ReadPenDef(int nPenIndex, TABPenDef *psDef)
  * been attributed to this Pen tool definition, or -1 if something went
  * wrong
  *
- * Note that the returned index is a 1-based index.  A value of 0 
+ * Note that the returned index is a 1-based index.  A value of 0
  * indicates "none" in MapInfo.
 
  * Returns a value >= 0 on success, -1 on error
  **********************************************************************/
 int   TABMAPFile::WritePenDef(TABPenDef *psDef)
 {
-    if (psDef == NULL || 
+    if (psDef == NULL ||
         (m_poToolDefTable == NULL && InitDrawingTools() != 0) ||
         m_poToolDefTable==NULL )
     {
@@ -2886,14 +2931,14 @@ int   TABMAPFile::ReadBrushDef(int nBrushIndex, TABBrushDef *psDef)
  * been attributed to this Brush tool definition, or -1 if something went
  * wrong
  *
- * Note that the returned index is a 1-based index.  A value of 0 
+ * Note that the returned index is a 1-based index.  A value of 0
  * indicates "none" in MapInfo.
 
  * Returns a value >= 0 on success, -1 on error
  **********************************************************************/
 int   TABMAPFile::WriteBrushDef(TABBrushDef *psDef)
 {
-    if (psDef == NULL || 
+    if (psDef == NULL ||
         (m_poToolDefTable == NULL && InitDrawingTools() != 0) ||
         m_poToolDefTable==NULL )
     {
@@ -2943,14 +2988,14 @@ int   TABMAPFile::ReadFontDef(int nFontIndex, TABFontDef *psDef)
  * been attributed to this Font tool definition, or -1 if something went
  * wrong
  *
- * Note that the returned index is a 1-based index.  A value of 0 
+ * Note that the returned index is a 1-based index.  A value of 0
  * indicates "none" in MapInfo.
 
  * Returns a value >= 0 on success, -1 on error
  **********************************************************************/
 int   TABMAPFile::WriteFontDef(TABFontDef *psDef)
 {
-    if (psDef == NULL || 
+    if (psDef == NULL ||
         (m_poToolDefTable == NULL && InitDrawingTools() != 0) ||
         m_poToolDefTable==NULL )
     {
@@ -2999,14 +3044,14 @@ int   TABMAPFile::ReadSymbolDef(int nSymbolIndex, TABSymbolDef *psDef)
  * been attributed to this Symbol tool definition, or -1 if something went
  * wrong
  *
- * Note that the returned index is a 1-based index.  A value of 0 
+ * Note that the returned index is a 1-based index.  A value of 0
  * indicates "none" in MapInfo.
 
  * Returns a value >= 0 on success, -1 on error
  **********************************************************************/
 int   TABMAPFile::WriteSymbolDef(TABSymbolDef *psDef)
 {
-    if (psDef == NULL || 
+    if (psDef == NULL ||
         (m_poToolDefTable == NULL && InitDrawingTools() != 0) ||
         m_poToolDefTable==NULL )
     {
@@ -3023,7 +3068,7 @@ int   TABMAPFile::WriteSymbolDef(TABSymbolDef *psDef)
 /**********************************************************************
  *                   TABMAPFile::SetCoordFilter()
  *
- * Set the MBR of the area of interest... only objects that at least 
+ * Set the MBR of the area of interest... only objects that at least
  * overlap with that area will be returned.
  *
  * @param sMin minimum x/y the file's projection coord.
@@ -3047,7 +3092,7 @@ void TABMAPFile::SetCoordFilter(TABVertex sMin, TABVertex sMax)
  *                   TABMAPFile::ResetCoordFilter()
  *
  * Reset the MBR of the area of interest to be the extents as defined
- * in the header. 
+ * in the header.
  **********************************************************************/
 
 void TABMAPFile::ResetCoordFilter()
@@ -3059,7 +3104,7 @@ void TABMAPFile::ResetCoordFilter()
     m_YMaxFilter = m_poHeader->m_nYMax;
     Int2Coordsys(m_XMinFilter, m_YMinFilter,
                  m_sMinFilter.x, m_sMinFilter.y);
-    Int2Coordsys(m_XMaxFilter, m_YMaxFilter, 
+    Int2Coordsys(m_XMaxFilter, m_YMaxFilter,
                  m_sMaxFilter.x, m_sMaxFilter.y);
 
     ORDER_MIN_MAX(int,m_XMinFilter,m_XMaxFilter);
@@ -3089,7 +3134,7 @@ void TABMAPFile::GetCoordFilter(TABVertex &sMin, TABVertex &sMax)
  * Write the spatial index blocks tree for this file.
  *
  * This function applies only to write access mode.
- * 
+ *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
 int TABMAPFile::CommitSpatialIndex()
@@ -3159,9 +3204,9 @@ void TABMAPFile::Dump(FILE *fpOut /*=NULL*/)
     else
     {
         fprintf(fpOut, "File is opened: %s\n", m_pszFname);
-        fprintf(fpOut, "Coordsys filter  = (%g,%g)-(%g,%g)\n", 
+        fprintf(fpOut, "Coordsys filter  = (%g,%g)-(%g,%g)\n",
                 m_sMinFilter.x, m_sMinFilter.y, m_sMaxFilter.x,m_sMaxFilter.y);
-        fprintf(fpOut, "Int coord filter = (%d,%d)-(%d,%d)\n", 
+        fprintf(fpOut, "Int coord filter = (%d,%d)-(%d,%d)\n",
                 m_XMinFilter, m_YMinFilter, m_XMaxFilter,m_YMaxFilter);
 
         fprintf(fpOut, "\nFile Header follows ...\n\n");
@@ -3186,9 +3231,9 @@ void TABMAPFile::Dump(FILE *fpOut /*=NULL*/)
  **********************************************************************/
 #ifdef DEBUG
 
-void TABMAPFile::DumpSpatialIndexToMIF(TABMAPIndexBlock *poNode, 
-                                       FILE *fpMIF, FILE *fpMID, 
-                                       int nParentId /*=-1*/, 
+void TABMAPFile::DumpSpatialIndexToMIF(TABMAPIndexBlock *poNode,
+                                       FILE *fpMIF, FILE *fpMID,
+                                       int nParentId /*=-1*/,
                                        int nIndexInNode /*=-1*/,
                                        int nCurDepth /*=0*/,
                                        int nMaxDepth /*=-1*/)
@@ -3224,8 +3269,8 @@ void TABMAPFile::DumpSpatialIndexToMIF(TABMAPIndexBlock *poNode,
 
     VSIFPrintf(fpMIF, "RECT %g %g %g %g\n", dXMin, dYMin, dXMax, dYMax);
     VSIFPrintf(fpMIF, "  Brush(1, 0)\n");  /* No fill */
-               
-    VSIFPrintf(fpMID, "%d,%d,%d,%d,%g,%d,%d,%d,%d\n", 
+
+    VSIFPrintf(fpMID, "%d,%d,%d,%d,%g,%d,%d,%d,%d\n",
                poNode->GetStartAddress(),
                nParentId,
                nIndexInNode,
@@ -3250,23 +3295,23 @@ void TABMAPFile::DumpSpatialIndexToMIF(TABMAPIndexBlock *poNode,
             if( poBlock->GetBlockType() == TABMAP_INDEX_BLOCK )
             {
                 /* Index block, dump recursively */
-                DumpSpatialIndexToMIF((TABMAPIndexBlock *)poBlock, 
-                                      fpMIF, fpMID, 
-                                      poNode->GetStartAddress(), 
+                DumpSpatialIndexToMIF((TABMAPIndexBlock *)poBlock,
+                                      fpMIF, fpMID,
+                                      poNode->GetStartAddress(),
                                       i, nCurDepth+1, nMaxDepth-1);
             }
             else
             {
                 /* Object block, dump directly */
                 CPLAssert( poBlock->GetBlockType() == TABMAP_OBJECT_BLOCK );
-        
+
                 Int2Coordsys(psEntry->XMin, psEntry->YMin, dXMin, dYMin);
                 Int2Coordsys(psEntry->XMax, psEntry->YMax, dXMax, dYMax);
 
                 VSIFPrintf(fpMIF, "RECT %g %g %g %g\n", dXMin, dYMin, dXMax, dYMax);
                 VSIFPrintf(fpMIF, "  Brush(1, 0)\n");  /* No fill */
 
-                VSIFPrintf(fpMID, "%d,%d,%d,%d,%g,%d,%d,%d,%d\n", 
+                VSIFPrintf(fpMID, "%d,%d,%d,%d,%g,%d,%d,%d,%d\n",
                            psEntry->nBlockPtr,
                            poNode->GetStartAddress(),
                            i,
diff --git a/ogr/ogrsf_frmts/mitab/mitab_mapheaderblock.cpp b/ogr/ogrsf_frmts/mitab/mitab_mapheaderblock.cpp
index 32cb905..7b3e15b 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_mapheaderblock.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_mapheaderblock.cpp
@@ -18,16 +18,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -155,10 +155,10 @@ inline double round(double r) {
 #define HDR_DEF_REFLECTXAXIS    0
 
 /*---------------------------------------------------------------------
- * The header block starts with an array of map object lenght constants.
+ * The header block starts with an array of map object length constants.
  *--------------------------------------------------------------------*/
 #define HDR_OBJ_LEN_ARRAY_SIZE   73
-static GByte  gabyObjLenArray[ HDR_OBJ_LEN_ARRAY_SIZE  ] = {
+static const GByte  gabyObjLenArray[ HDR_OBJ_LEN_ARRAY_SIZE  ] = {
             0x00,0x0a,0x0e,0x15,0x0e,0x16,0x1b,0xa2,
             0xa6,0xab,0x1a,0x2a,0x2f,0xa5,0xa9,0xb5,
             0xa7,0xb5,0xd9,0x0f,0x17,0x23,0x13,0x1f,
@@ -247,7 +247,7 @@ void TABMAPHeaderBlock::InitMembersWithDefaultValues()
     m_sProj.nEllipsoidId = 0;
     m_sProj.nUnitsId = 7;
     m_sProj.nDatumId = 0;
-    m_XScale = 1000.0;  // Default coord range (before SetCoordSysBounds()) 
+    m_XScale = 1000.0;  // Default coord range (before SetCoordSysBounds())
     m_YScale = 1000.0;  // will be [-1000000.000 .. 1000000.000]
     m_XDispl = 0.0;
     m_YDispl = 0.0;
@@ -280,13 +280,13 @@ void TABMAPHeaderBlock::InitMembersWithDefaultValues()
  * Perform some initialization on the block after its binary data has
  * been set or changed (or loaded from a file).
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
-int     TABMAPHeaderBlock::InitBlockFromData(GByte *pabyBuf, 
-                                             int nBlockSize, int nSizeUsed, 
+int     TABMAPHeaderBlock::InitBlockFromData(GByte *pabyBuf,
+                                             int nBlockSize, int nSizeUsed,
                                              GBool bMakeCopy /* = TRUE */,
-                                             VSILFILE *fpSrc /* = NULL */, 
+                                             VSILFILE *fpSrc /* = NULL */,
                                              int nOffset /* = 0 */)
 {
     int i, nStatus;
@@ -295,11 +295,11 @@ int     TABMAPHeaderBlock::InitBlockFromData(GByte *pabyBuf,
     /*-----------------------------------------------------------------
      * First of all, we must call the base class' InitBlockFromData()
      *----------------------------------------------------------------*/
-    nStatus = TABRawBinBlock::InitBlockFromData(pabyBuf, 
+    nStatus = TABRawBinBlock::InitBlockFromData(pabyBuf,
                                                 nBlockSize, nSizeUsed,
                                                 bMakeCopy,
                                                 fpSrc, nOffset);
-    if (nStatus != 0)   
+    if (nStatus != 0)
         return nStatus;
 
     /*-----------------------------------------------------------------
@@ -320,8 +320,8 @@ int     TABMAPHeaderBlock::InitBlockFromData(GByte *pabyBuf,
 
     /*-----------------------------------------------------------------
      * Init member variables
-     * Instead of having over 30 get/set methods, we'll make all data 
-     * members public and we will initialize them here.  
+     * Instead of having over 30 get/set methods, we'll make all data
+     * members public and we will initialize them here.
      * For this reason, this class should be used with care.
      *----------------------------------------------------------------*/
     GotoByteInBlock(0x104);
@@ -347,7 +347,7 @@ int     TABMAPHeaderBlock::InitBlockFromData(GByte *pabyBuf,
         CPLErrorReset();
     }
 
-    GotoByteInBlock(0x130);     // Skip 16 unknown bytes 
+    GotoByteInBlock(0x130);     // Skip 16 unknown bytes
 
     m_nFirstIndexBlock = ReadInt32();
     m_nFirstGarbageBlock = ReadInt32();
@@ -421,7 +421,7 @@ int     TABMAPHeaderBlock::InitBlockFromData(GByte *pabyBuf,
     m_sProj.nAffineFlag = 0;
     if (m_nMAPVersionNumber >= 500 && m_nSizeUsed > TAB_MIN_BLOCK_SIZE)
     {
-        // Read Affine parameters A,B,C,D,E,F 
+        // Read Affine parameters A,B,C,D,E,F
         // only if version 500+ and block is larger than TAB_MIN_BLOCK_SIZE bytes
         int nInUse = ReadByte();
         if (nInUse)
@@ -455,16 +455,16 @@ int     TABMAPHeaderBlock::InitBlockFromData(GByte *pabyBuf,
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABMAPHeaderBlock::Int2Coordsys(GInt32 nX, GInt32 nY, 
+int TABMAPHeaderBlock::Int2Coordsys(GInt32 nX, GInt32 nY,
                                     double &dX, double &dY)
 {
     if (m_pabyBuf == NULL)
         return -1;
 
-    // For some obscure reason, some guy decided that it would be 
+    // For some obscure reason, some guy decided that it would be
     // more fun to be able to define our own origin quadrant!
     //
-    // In version 100 .tab files (version 400 .map), it is possible to have 
+    // In version 100 .tab files (version 400 .map), it is possible to have
     // a quadrant 0 and it should be treated the same way as quadrant 3
 
     if (m_nCoordOriginQuadrant==2 || m_nCoordOriginQuadrant==3 ||
@@ -493,7 +493,7 @@ int TABMAPHeaderBlock::Int2Coordsys(GInt32 nX, GInt32 nY,
 /**********************************************************************
  *                   TABMAPHeaderBlock::Coordsys2Int()
  *
- * Convert from coordinates system units as defined in the file's 
+ * Convert from coordinates system units as defined in the file's
  * coordsys clause to long integer (internal) coordinates.
  *
  * Note that the false easting/northing and the conversion factor from
@@ -501,21 +501,21 @@ int TABMAPHeaderBlock::Int2Coordsys(GInt32 nX, GInt32 nY,
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABMAPHeaderBlock::Coordsys2Int(double dX, double dY, 
+int TABMAPHeaderBlock::Coordsys2Int(double dX, double dY,
                                     GInt32 &nX, GInt32 &nY,
                                     GBool bIgnoreOverflow /*=FALSE*/)
 {
     if (m_pabyBuf == NULL)
         return -1;
 
-    // For some obscure reason, some guy decided that it would be 
+    // For some obscure reason, some guy decided that it would be
     // more fun to be able to define our own origin quadrant!
     //
-    // In version 100 .tab files (version 400 .map), it is possible to have 
+    // In version 100 .tab files (version 400 .map), it is possible to have
     // a quadrant 0 and it should be treated the same way as quadrant 3
 
     /*-----------------------------------------------------------------
-     * NOTE: double values must be used here, the limit of integer value 
+     * NOTE: double values must be used here, the limit of integer value
      * have been reached some times due to the very big numbers used here.
      *----------------------------------------------------------------*/
     double dTempX, dTempY;
@@ -566,7 +566,7 @@ int TABMAPHeaderBlock::Coordsys2Int(double dX, double dY,
     {
         m_bIntBoundsOverflow = TRUE;
 #ifdef DEBUG
-        CPLError(CE_Warning, TAB_WarningBoundsOverflow, 
+        CPLError(CE_Warning, (CPLErrorNum)TAB_WarningBoundsOverflow,
                  "Integer bounds overflow: (%f, %f) -> (%d, %d)\n",
                  dX, dY, nX, nY);
 #endif
@@ -581,7 +581,7 @@ int TABMAPHeaderBlock::Coordsys2Int(double dX, double dY,
  * Convert from compressed integer (internal) to coordinates system units
  * as defined in the file's coordsys clause.
  * The difference between long integer and compressed integer coords is
- * that compressed coordinates are scaled displacement relative to an 
+ * that compressed coordinates are scaled displacement relative to an
  * object centroid.
  *
  * Note that the false easting/northing and the conversion factor from
@@ -589,8 +589,8 @@ int TABMAPHeaderBlock::Coordsys2Int(double dX, double dY,
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABMAPHeaderBlock::ComprInt2Coordsys(GInt32 nCenterX, GInt32 nCenterY, 
-                                         int nDeltaX, int nDeltaY, 
+int TABMAPHeaderBlock::ComprInt2Coordsys(GInt32 nCenterX, GInt32 nCenterY,
+                                         int nDeltaX, int nDeltaY,
                                          double &dX, double &dY)
 {
     if (m_pabyBuf == NULL)
@@ -604,7 +604,7 @@ int TABMAPHeaderBlock::ComprInt2Coordsys(GInt32 nCenterX, GInt32 nCenterY,
  *                   TABMAPHeaderBlock::Int2CoordsysDist()
  *
  * Convert a pair of X and Y size (or distance) value from long integer
- * (internal) to coordinates system units as defined in the file's 
+ * (internal) to coordinates system units as defined in the file's
  * coordsys clause.
  *
  * The difference with Int2Coordsys() is that this function only applies
@@ -615,7 +615,7 @@ int TABMAPHeaderBlock::ComprInt2Coordsys(GInt32 nCenterX, GInt32 nCenterY,
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABMAPHeaderBlock::Int2CoordsysDist(GInt32 nX, GInt32 nY, 
+int TABMAPHeaderBlock::Int2CoordsysDist(GInt32 nX, GInt32 nY,
                                     double &dX, double &dY)
 {
     if (m_pabyBuf == NULL)
@@ -642,7 +642,7 @@ int TABMAPHeaderBlock::Int2CoordsysDist(GInt32 nX, GInt32 nY,
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABMAPHeaderBlock::Coordsys2IntDist(double dX, double dY, 
+int TABMAPHeaderBlock::Coordsys2IntDist(double dX, double dY,
                                         GInt32 &nX, GInt32 &nY)
 {
     if (m_pabyBuf == NULL)
@@ -666,7 +666,7 @@ int TABMAPHeaderBlock::Coordsys2IntDist(double dX, double dY,
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABMAPHeaderBlock::SetCoordsysBounds(double dXMin, double dYMin, 
+int TABMAPHeaderBlock::SetCoordsysBounds(double dXMin, double dYMin,
                                          double dXMax, double dYMax)
 {
 //printf("SetCoordsysBounds(%10g, %10g, %10g, %10g)\n", dXMin, dYMin, dXMax, dYMax);
@@ -814,14 +814,14 @@ int  TABMAPHeaderBlock::SetProjInfo(TABProjInfo *psProjInfo)
 /**********************************************************************
  *                   TABMAPHeaderBlock::CommitToFile()
  *
- * Commit the current state of the binary block to the file to which 
+ * Commit the current state of the binary block to the file to which
  * it has been previously attached.
  *
  * This method makes sure all values are properly set in the header
  * block buffer and then calls TABRawBinBlock::CommitToFile() to do
  * the actual writing to disk.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
 int     TABMAPHeaderBlock::CommitToFile()
@@ -830,7 +830,7 @@ int     TABMAPHeaderBlock::CommitToFile()
 
     if ( m_pabyBuf == NULL || m_nRegularBlockSize == 0 )
     {
-        CPLError(CE_Failure, CPLE_AssertionFailed, 
+        CPLError(CE_Failure, CPLE_AssertionFailed,
         "TABRawBinBlock::CommitToFile(): Block has not been initialized yet!");
         return -1;
     }
@@ -851,7 +851,7 @@ int     TABMAPHeaderBlock::CommitToFile()
         // Default value for HDR_VERSION_NUMBER is 500 so this error should
         // never happen unless the caller changed the value, in which case they
         // deserve to get a failure
-        CPLError(CE_Failure, CPLE_AssertionFailed, 
+        CPLError(CE_Failure, CPLE_AssertionFailed,
                  "TABRawBinBlock::CommitToFile(): .MAP version 500 or more is "
                  "required for affine projection parameter support.");
         return -1;
@@ -938,7 +938,7 @@ int     TABMAPHeaderBlock::CommitToFile()
     if (nStatus == 0)
     {
 #ifdef DEBUG_VERBOSE
-        CPLDebug("MITAB", "Commiting HEADER block to offset %d", m_nFileOffset);
+        CPLDebug("MITAB", "Committing HEADER block to offset %d", m_nFileOffset);
 #endif
         nStatus = TABRawBinBlock::CommitToFile();
     }
@@ -950,22 +950,22 @@ int     TABMAPHeaderBlock::CommitToFile()
  *                   TABMAPHeaderBlock::InitNewBlock()
  *
  * Initialize a newly created block so that it knows to which file it
- * is attached, its block size, etc . and then perform any specific 
- * initialization for this block type, including writing a default 
+ * is attached, its block size, etc . and then perform any specific
+ * initialization for this block type, including writing a default
  * block header, etc. and leave the block ready to receive data.
  *
  * This is an alternative to calling ReadFromFile() or InitBlockFromData()
  * that puts the block in a stable state without loading any initial
  * data in it.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
-int     TABMAPHeaderBlock::InitNewBlock(VSILFILE *fpSrc, int nBlockSize, 
+int     TABMAPHeaderBlock::InitNewBlock(VSILFILE *fpSrc, int nBlockSize,
                                         int nFileOffset /* = 0*/)
 {
     /*-----------------------------------------------------------------
-     * Start with the default initialisation
+     * Start with the default initialization
      *----------------------------------------------------------------*/
 
     /* .MAP files of Version 500 and up appear to have a 1024 bytes
@@ -978,7 +978,8 @@ int     TABMAPHeaderBlock::InitNewBlock(VSILFILE *fpSrc, int nBlockSize,
      *----------------------------------------------------------------*/
     InitMembersWithDefaultValues();
 
-    m_nRegularBlockSize = nBlockSize;
+    CPLAssert( nBlockSize >= 0 && nBlockSize <= 32767 );
+    m_nRegularBlockSize = static_cast<GInt16>(nBlockSize);
 
     /*-----------------------------------------------------------------
      * And Set the map object length array in the buffer...
@@ -1067,7 +1068,7 @@ void TABMAPHeaderBlock::Dump(FILE *fpOut /*=NULL*/)
         fprintf(fpOut,"\n");
         fprintf(fpOut,"  m_sProj.nDatumId      = %d\n", m_sProj.nDatumId);
         fprintf(fpOut,"  m_sProj.nProjId       = %d\n", (int)m_sProj.nProjId);
-        fprintf(fpOut,"  m_sProj.nEllipsoidId  = %d\n", 
+        fprintf(fpOut,"  m_sProj.nEllipsoidId  = %d\n",
                                                     (int)m_sProj.nEllipsoidId);
         fprintf(fpOut,"  m_sProj.nUnitsId      = %d\n", (int)m_sProj.nUnitsId);
         fprintf(fpOut,"  m_sProj.adProjParams  =");
@@ -1086,7 +1087,7 @@ void TABMAPHeaderBlock::Dump(FILE *fpOut /*=NULL*/)
         // Dump array of map object lengths... optional
         if (FALSE)
         {
-            fprintf(fpOut, "-- Header bytes 00-FF: Array of map object lenghts --\n");
+            fprintf(fpOut, "-- Header bytes 00-FF: Array of map object lengths --\n");
             for(i=0; i<256; i++)
             {
                 fprintf(fpOut, "0x%2.2x", (int)m_pabyBuf[i]);
diff --git a/ogr/ogrsf_frmts/mitab/mitab_mapindexblock.cpp b/ogr/ogrsf_frmts/mitab/mitab_mapindexblock.cpp
index e71a801..6e32141 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_mapindexblock.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_mapindexblock.cpp
@@ -18,16 +18,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -48,7 +48,7 @@
  *
  * Revision 1.10  2006/11/20 20:05:58  dmorissette
  * First pass at improving generation of spatial index in .map file (bug 1585)
- * New methods for insertion and splittung in the spatial index are done.
+ * New methods for insertion and splitting the spatial index are done.
  * Also implemented a method to dump the spatial index to .mif/.mid
  * Still need to implement splitting of TABMapObjectBlock to get optimal
  * results.
@@ -109,6 +109,7 @@ TABMAPIndexBlock::TABMAPIndexBlock(TABAccess eAccessMode /*= TABRead*/):
     m_nCurChildIndex = -1;
     m_poParentRef = NULL;
     m_poBlockManagerRef = NULL;
+    memset(m_asEntries, 0, sizeof(m_asEntries));
 }
 
 /**********************************************************************
@@ -143,13 +144,13 @@ void TABMAPIndexBlock::UnsetCurChild()
  * Perform some initialization on the block after its binary data has
  * been set or changed (or loaded from a file).
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
-int     TABMAPIndexBlock::InitBlockFromData(GByte *pabyBuf, 
-                                            int nBlockSize, int nSizeUsed, 
+int     TABMAPIndexBlock::InitBlockFromData(GByte *pabyBuf,
+                                            int nBlockSize, int nSizeUsed,
                                             GBool bMakeCopy /* = TRUE */,
-                                            VSILFILE *fpSrc /* = NULL */, 
+                                            VSILFILE *fpSrc /* = NULL */,
                                             int nOffset /* = 0 */)
 {
     int nStatus;
@@ -157,11 +158,11 @@ int     TABMAPIndexBlock::InitBlockFromData(GByte *pabyBuf,
     /*-----------------------------------------------------------------
      * First of all, we must call the base class' InitBlockFromData()
      *----------------------------------------------------------------*/
-    nStatus = TABRawBinBlock::InitBlockFromData(pabyBuf, 
+    nStatus = TABRawBinBlock::InitBlockFromData(pabyBuf,
                                                 nBlockSize, nSizeUsed,
                                                 bMakeCopy,
                                                 fpSrc, nOffset);
-    if (nStatus != 0)   
+    if (nStatus != 0)
         return nStatus;
 
     /*-----------------------------------------------------------------
@@ -192,14 +193,14 @@ int     TABMAPIndexBlock::InitBlockFromData(GByte *pabyBuf,
 /**********************************************************************
  *                   TABMAPIndexBlock::CommitToFile()
  *
- * Commit the current state of the binary block to the file to which 
+ * Commit the current state of the binary block to the file to which
  * it has been previously attached.
  *
  * This method makes sure all values are properly set in the map object
  * block header and then calls TABRawBinBlock::CommitToFile() to do
  * the actual writing to disk.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
 int     TABMAPIndexBlock::CommitToFile()
@@ -208,7 +209,7 @@ int     TABMAPIndexBlock::CommitToFile()
 
     if ( m_pabyBuf == NULL )
     {
-        CPLError(CE_Failure, CPLE_AssertionFailed, 
+        CPLError(CE_Failure, CPLE_AssertionFailed,
                  "CommitToFile(): Block has not been initialized yet!");
         return -1;
     }
@@ -256,7 +257,7 @@ int     TABMAPIndexBlock::CommitToFile()
     if (nStatus == 0)
     {
 #ifdef DEBUG_VERBOSE
-        CPLDebug("MITAB", "Commiting INDEX block to offset %d", m_nFileOffset);
+        CPLDebug("MITAB", "Committing INDEX block to offset %d", m_nFileOffset);
 #endif
         nStatus = TABRawBinBlock::CommitToFile();
     }
@@ -269,22 +270,22 @@ int     TABMAPIndexBlock::CommitToFile()
  *                   TABMAPIndexBlock::InitNewBlock()
  *
  * Initialize a newly created block so that it knows to which file it
- * is attached, its block size, etc . and then perform any specific 
- * initialization for this block type, including writing a default 
+ * is attached, its block size, etc . and then perform any specific
+ * initialization for this block type, including writing a default
  * block header, etc. and leave the block ready to receive data.
  *
  * This is an alternative to calling ReadFromFile() or InitBlockFromData()
  * that puts the block in a stable state without loading any initial
  * data in it.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
-int     TABMAPIndexBlock::InitNewBlock(VSILFILE *fpSrc, int nBlockSize, 
+int     TABMAPIndexBlock::InitNewBlock(VSILFILE *fpSrc, int nBlockSize,
                                         int nFileOffset /* = 0*/)
 {
     /*-----------------------------------------------------------------
-     * Start with the default initialisation
+     * Start with the default initialization
      *----------------------------------------------------------------*/
     if ( TABRawBinBlock::InitNewBlock(fpSrc, nBlockSize, nFileOffset) != 0)
         return -1;
@@ -319,9 +320,9 @@ int     TABMAPIndexBlock::InitNewBlock(VSILFILE *fpSrc, int nBlockSize,
  *                   TABMAPIndexBlock::ReadNextEntry()
  *
  * Read the next index entry from the block and fill the sEntry
- * structure. 
+ * structure.
  *
- * Returns 0 if succesful or -1 if we reached the end of the block.
+ * Returns 0 if successful or -1 if we reached the end of the block.
  **********************************************************************/
 int     TABMAPIndexBlock::ReadNextEntry(TABMAPIndexEntry *psEntry)
 {
@@ -351,14 +352,14 @@ int     TABMAPIndexBlock::ReadNextEntry(TABMAPIndexEntry *psEntry)
  *
  * Init the block by reading all entries from the data block.
  *
- * Returns 0 if succesful or -1 on error.
+ * Returns 0 if successful or -1 on error.
  **********************************************************************/
 int     TABMAPIndexBlock::ReadAllEntries()
 {
     CPLAssert(m_numEntries <= GetMaxEntries());
     if (m_numEntries == 0)
         return 0;
-    
+
     if (GotoByteInBlock( 0x004 ) != 0)
         return -1;
 
@@ -376,7 +377,7 @@ int     TABMAPIndexBlock::ReadAllEntries()
  *
  * Write the sEntry index entry at current position in the block.
  *
- * Returns 0 if succesful or -1 if we reached the end of the block.
+ * Returns 0 if successful or -1 if we reached the end of the block.
  **********************************************************************/
 int     TABMAPIndexBlock::WriteNextEntry(TABMAPIndexEntry *psEntry)
 {
@@ -413,10 +414,10 @@ int     TABMAPIndexBlock::GetNumFreeEntries()
  *
  * Fetch a reference to the requested entry.
  *
- * @param iIndex index of entry, must be from 0 to GetNumEntries()-1. 
+ * @param iIndex index of entry, must be from 0 to GetNumEntries()-1.
  *
  * @return a reference to the internal copy of the entry, or NULL if out
- * of range. 
+ * of range.
  **********************************************************************/
 TABMAPIndexEntry *TABMAPIndexBlock::GetEntry( int iIndex )
 {
@@ -444,26 +445,26 @@ int     TABMAPIndexBlock::GetCurMaxDepth()
  *
  * Return the MBR for the current block.
  **********************************************************************/
-void TABMAPIndexBlock::GetMBR(GInt32 &nXMin, GInt32 &nYMin, 
+void TABMAPIndexBlock::GetMBR(GInt32 &nXMin, GInt32 &nYMin,
                                      GInt32 &nXMax, GInt32 &nYMax)
 {
     nXMin = m_nMinX;
     nYMin = m_nMinY;
     nXMax = m_nMaxX;
-    nYMax = m_nMaxY; 
+    nYMax = m_nMaxY;
 }
 
 /**********************************************************************
  *                   TABMAPIndexBlock::SetMBR()
  *
  **********************************************************************/
-void TABMAPIndexBlock::SetMBR(GInt32 nXMin, GInt32 nYMin, 
+void TABMAPIndexBlock::SetMBR(GInt32 nXMin, GInt32 nYMin,
                               GInt32 nXMax, GInt32 nYMax)
 {
     m_nMinX = nXMin;
     m_nMinY = nYMin;
     m_nMaxX = nXMax;
-    m_nMaxY = nYMax; 
+    m_nMaxY = nYMax;
 }
 
 /**********************************************************************
@@ -513,10 +514,10 @@ int     TABMAPIndexBlock::InsertEntry(GInt32 nXMin, GInt32 nYMin,
 /**********************************************************************
  *                   TABMAPIndexBlock::ChooseSubEntryForInsert()
  *
- * Select the entry in this index block in which the new entry should 
+ * Select the entry in this index block in which the new entry should
  * be inserted. The criteria used is to select the node whose MBR needs
  * the least enlargement to include the new entry. We resolve ties by
- * chosing the entry with the rectangle of smallest area.
+ * choosing the entry with the rectangle of smallest area.
  * (This is the ChooseSubtree part of Guttman's "ChooseLeaf" algorithm.)
  *
  * Returns the index of the best candidate or -1 of node is empty.
@@ -570,7 +571,7 @@ int     TABMAPIndexBlock::ChooseSubEntryForInsert(GInt32 nXMin, GInt32 nYMin,
         }
 
         /* Is this a better candidate?
-         * Note, possible Optimization: In case of tie, we could to pick the 
+         * Note, possible Optimization: In case of tie, we could to pick the
          * candidate with the smallest area
          */
 
@@ -580,10 +581,10 @@ int     TABMAPIndexBlock::ChooseSubEntryForInsert(GInt32 nXMin, GInt32 nYMin,
             || (dAreaDiff < 0 && dOptimalAreaDiff >= 0)
             /* or if both are either contained or not contained then use the one
              * with the smallest area diff, which means maximum coverage in the case
-             * of contained rects, or minimum area increase when not contained 
+             * of contained rects, or minimum area increase when not contained
              */
             || (((dOptimalAreaDiff < 0 && dAreaDiff < 0) ||
-                 (dOptimalAreaDiff > 0 && dAreaDiff > 0)) && 
+                 (dOptimalAreaDiff > 0 && dAreaDiff > 0)) &&
                 ABS(dAreaDiff) < ABS(dOptimalAreaDiff)) )
         {
             nBestCandidate = i;
@@ -604,7 +605,7 @@ int     TABMAPIndexBlock::ChooseSubEntryForInsert(GInt32 nXMin, GInt32 nYMin,
  * Returns the nBlockPtr of the selected leaf node entry (should be a
  * ref to a TABMAPObjectBlock) or -1 on error.
  *
- * After this call, m_poCurChild will be pointing at the selected child 
+ * After this call, m_poCurChild will be pointing at the selected child
  * node, for use by later calls to UpdateLeafEntry()
  **********************************************************************/
 GInt32  TABMAPIndexBlock::ChooseLeafForInsert(GInt32 nXMin, GInt32 nYMin,
@@ -620,7 +621,7 @@ GInt32  TABMAPIndexBlock::ChooseLeafForInsert(GInt32 nXMin, GInt32 nYMin,
      *----------------------------------------------------------------*/
 
     // Make sure blocks currently in memory are written to disk.
-    // TODO: Could we avoid deleting m_poCurChild if it's already 
+    // TODO: Could we avoid deleting m_poCurChild if it's already
     //       the best candidate for insert?
     if (m_poCurChild)
     {
@@ -631,7 +632,7 @@ GInt32  TABMAPIndexBlock::ChooseLeafForInsert(GInt32 nXMin, GInt32 nYMin,
     }
 
     int nBestCandidate = ChooseSubEntryForInsert(nXMin,nYMin,nXMax,nYMax);
-       
+
     CPLAssert(nBestCandidate != -1);
     if (nBestCandidate == -1)
         return -1;  /* This should never happen! */
@@ -644,7 +645,7 @@ GInt32  TABMAPIndexBlock::ChooseLeafForInsert(GInt32 nXMin, GInt32 nYMin,
     // Prevent error message if referred block not committed yet.
     CPLPushErrorHandler(CPLQuietErrorHandler);
 
-    poBlock = TABCreateMAPBlockFromFile(m_fp, 
+    poBlock = TABCreateMAPBlockFromFile(m_fp,
                                     m_asEntries[nBestCandidate].nBlockPtr,
                                     m_nBlockSize, TRUE, TABReadWrite);
     if (poBlock != NULL && poBlock->GetBlockClass() == TABMAP_INDEX_BLOCK)
@@ -656,10 +657,10 @@ GInt32  TABMAPIndexBlock::ChooseLeafForInsert(GInt32 nXMin, GInt32 nYMin,
         m_poCurChild->SetMAPBlockManagerRef(m_poBlockManagerRef);
         bFound = TRUE;
     }
-                
+
     if (poBlock)
         delete poBlock;
-            
+
     CPLPopErrorHandler();
     CPLErrorReset();
 
@@ -673,8 +674,8 @@ GInt32  TABMAPIndexBlock::ChooseLeafForInsert(GInt32 nXMin, GInt32 nYMin,
     }
 
     /*-------------------------------------------------------------
-     * Found no child index node... we must be at the leaf level 
-     * (leaf points at map object data blocks) so we return a ref 
+     * Found no child index node... we must be at the leaf level
+     * (leaf points at map object data blocks) so we return a ref
      * to the TABMAPObjBlock for insertion
      *------------------------------------------------------------*/
     return m_asEntries[nBestCandidate].nBlockPtr;
@@ -722,7 +723,7 @@ int     TABMAPIndexBlock::GetCurLeafEntryMBR(GInt32 nBlockPtr,
     /* Not found! This should not happen if method is used properly. */
     CPLError(CE_Failure, CPLE_AssertionFailed,
              "Entry to update not found in GetCurLeafEntryMBR()!");
-    return -1; 
+    return -1;
 
 }
 
@@ -782,7 +783,7 @@ int     TABMAPIndexBlock::UpdateLeafEntry(GInt32 nBlockPtr,
     /* Not found! This should not happen if method is used properly. */
     CPLError(CE_Failure, CPLE_AssertionFailed,
              "Entry to update not found in UpdateLeafEntry()!");
-    return -1; 
+    return -1;
 }
 
 
@@ -796,8 +797,8 @@ int     TABMAPIndexBlock::UpdateLeafEntry(GInt32 nBlockPtr,
  * split and this split can propagate up to its parent, etc.
  *
  * If bAddInThisNodeOnly=TRUE, then the entry is added only locally and
- * we do not try to update the child node.  This is used when the parent 
- * of a node that is being splitted has to be updated.
+ * we do not try to update the child node.  This is used when the parent
+ * of a node that is being split has to be updated.
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
@@ -838,7 +839,7 @@ int     TABMAPIndexBlock::AddEntry(GInt32 nXMin, GInt32 nYMin,
         }
 
         int nBestCandidate = ChooseSubEntryForInsert(nXMin,nYMin,nXMax,nYMax);
-       
+
         CPLAssert(nBestCandidate != -1);
 
         if (nBestCandidate != -1)
@@ -851,7 +852,7 @@ int     TABMAPIndexBlock::AddEntry(GInt32 nXMin, GInt32 nYMin,
             // Prevent error message if referred block not committed yet.
             CPLPushErrorHandler(CPLQuietErrorHandler);
 
-            poBlock = TABCreateMAPBlockFromFile(m_fp, 
+            poBlock = TABCreateMAPBlockFromFile(m_fp,
                                        m_asEntries[nBestCandidate].nBlockPtr,
                                        m_nBlockSize, TRUE, TABReadWrite);
             if (poBlock != NULL && poBlock->GetBlockClass() == TABMAP_INDEX_BLOCK)
@@ -863,10 +864,10 @@ int     TABMAPIndexBlock::AddEntry(GInt32 nXMin, GInt32 nYMin,
                 m_poCurChild->SetMAPBlockManagerRef(m_poBlockManagerRef);
                 bFound = TRUE;
             }
-                
+
             if (poBlock)
                 delete poBlock;
-            
+
             CPLPopErrorHandler();
             CPLErrorReset();
         }
@@ -913,7 +914,7 @@ int     TABMAPIndexBlock::AddEntry(GInt32 nXMin, GInt32 nYMin,
                  * Splitting a regular node
                  *----------------------------------------------------*/
                 if (SplitNode(nXMin, nYMin, nXMax, nYMax) != 0)
-                    return -1; 
+                    return -1;
             }
         }
 
@@ -966,7 +967,7 @@ double  TABMAPIndexBlock::ComputeAreaDiff(GInt32 nNodeXMin, GInt32 nNodeYMin,
          * the area difference will be the difference between the area
          * of the entry to insert and the area of the node
          */
-        dAreaDiff = MITAB_AREA(nEntryXMin, nEntryYMin, 
+        dAreaDiff = MITAB_AREA(nEntryXMin, nEntryYMin,
                                nEntryXMax, nEntryYMax) - dNodeAreaBefore;
     }
     else
@@ -996,10 +997,10 @@ double  TABMAPIndexBlock::ComputeAreaDiff(GInt32 nNodeXMin, GInt32 nNodeYMin,
  * Pick two seeds to use to start splitting this node.
  *
  * Guttman's LinearPickSeed:
- * - Along each dimension find the entry whose rectangle has the 
+ * - Along each dimension find the entry whose rectangle has the
  *   highest low side, and the one with the lowest high side
  * - Calculate the separation for each pair
- * - Normalize the separation by dividing by the extents of the 
+ * - Normalize the separation by dividing by the extents of the
  *   corresponding dimension
  * - Choose the pair with the greatest normalized separation along
  *   any dimension
@@ -1007,9 +1008,9 @@ double  TABMAPIndexBlock::ComputeAreaDiff(GInt32 nNodeXMin, GInt32 nNodeYMin,
 int  TABMAPIndexBlock::PickSeedsForSplit(TABMAPIndexEntry *pasEntries,
                                          int numEntries,
                                          int nSrcCurChildIndex,
-                                         GInt32 nNewEntryXMin, 
+                                         GInt32 nNewEntryXMin,
                                          GInt32 nNewEntryYMin,
-                                         GInt32 nNewEntryXMax, 
+                                         GInt32 nNewEntryXMax,
                                          GInt32 nNewEntryYMax,
                                          int &nSeed1, int &nSeed2)
 {
@@ -1020,7 +1021,7 @@ int  TABMAPIndexBlock::PickSeedsForSplit(TABMAPIndexEntry *pasEntries,
     nSeed1=-1;
     nSeed2=-1;
 
-    // Along each dimension find the entry whose rectangle has the 
+    // Along each dimension find the entry whose rectangle has the
     // highest low side, and the one with the lowest high side
     for(int iEntry=0; iEntry<numEntries; iEntry++)
     {
@@ -1075,7 +1076,7 @@ int  TABMAPIndexBlock::PickSeedsForSplit(TABMAPIndexEntry *pasEntries,
 
     // Calculate the separation for each pair (note that it may be negative
     // in case of overlap)
-    // Normalize the separation by dividing by the extents of the 
+    // Normalize the separation by dividing by the extents of the
     // corresponding dimension
     double dX, dY;
 
@@ -1110,14 +1111,14 @@ int  TABMAPIndexBlock::PickSeedsForSplit(TABMAPIndexEntry *pasEntries,
     // the new entry will stay in current node (new entry will be added by the
     // caller later). The other seed will go in the 2nd node
     double dAreaDiff1, dAreaDiff2;
-    dAreaDiff1 = ComputeAreaDiff(pasEntries[nSeed1].XMin, 
+    dAreaDiff1 = ComputeAreaDiff(pasEntries[nSeed1].XMin,
                                  pasEntries[nSeed1].YMin,
                                  pasEntries[nSeed1].XMax,
                                  pasEntries[nSeed1].YMax,
                                  nNewEntryXMin, nNewEntryYMin,
                                  nNewEntryXMax, nNewEntryYMax);
 
-    dAreaDiff2 = ComputeAreaDiff(pasEntries[nSeed2].XMin, 
+    dAreaDiff2 = ComputeAreaDiff(pasEntries[nSeed2].XMin,
                                  pasEntries[nSeed2].YMin,
                                  pasEntries[nSeed2].XMax,
                                  pasEntries[nSeed2].YMax,
@@ -1125,11 +1126,11 @@ int  TABMAPIndexBlock::PickSeedsForSplit(TABMAPIndexEntry *pasEntries,
                                  nNewEntryXMax, nNewEntryYMax);
 
     /* Note that we want to keep this node's current child in here.
-     * Since splitting happens only during an addentry() operation and 
+     * Since splitting happens only during an addentry() operation and
      * then both the current child and the New Entry should fit in the same
      * area.
      */
-    if (nSeed1 != nSrcCurChildIndex && 
+    if (nSeed1 != nSrcCurChildIndex &&
         (dAreaDiff1 > dAreaDiff2 || nSeed2 == nSrcCurChildIndex))
     {
         // Seed2 stays in this node, Seed1 moves to new node
@@ -1150,7 +1151,7 @@ int  TABMAPIndexBlock::PickSeedsForSplit(TABMAPIndexEntry *pasEntries,
  * Note that Root Nodes cannot be split using this method... SplitRootNode()
  * should be used instead.
  *
- * nNewEntry* are the coord. of the new entry that 
+ * nNewEntry* are the coord. of the new entry that
  * will be added after the split.  The split is done so that the current
  * node will be the one in which the new object should be stored.
  *
@@ -1165,7 +1166,7 @@ int     TABMAPIndexBlock::SplitNode(GInt32 nNewEntryXMin, GInt32 nNewEntryYMin,
      * Create a 2nd node
      *----------------------------------------------------------------*/
     TABMAPIndexBlock *poNewNode = new TABMAPIndexBlock(m_eAccess);
-    if (poNewNode->InitNewBlock(m_fp, m_nBlockSize, 
+    if (poNewNode->InitNewBlock(m_fp, m_nBlockSize,
                                 m_poBlockManagerRef->AllocNewBlock("INDEX")) != 0)
     {
         return -1;
@@ -1186,7 +1187,7 @@ int     TABMAPIndexBlock::SplitNode(GInt32 nNewEntryXMin, GInt32 nNewEntryYMin,
      *----------------------------------------------------------------*/
     int nSeed1, nSeed2;
     PickSeedsForSplit(pasSrcEntries, nSrcEntries, nSrcCurChildIndex,
-                      nNewEntryXMin, nNewEntryYMin, 
+                      nNewEntryXMin, nNewEntryYMin,
                       nNewEntryXMax, nNewEntryYMax,
                       nSeed1, nSeed2);
 
@@ -1196,16 +1197,16 @@ int     TABMAPIndexBlock::SplitNode(GInt32 nNewEntryXMin, GInt32 nNewEntryYMin,
     m_numEntries = 0;
 
     // Insert nSeed1 in this node
-    InsertEntry(pasSrcEntries[nSeed1].XMin, 
+    InsertEntry(pasSrcEntries[nSeed1].XMin,
                 pasSrcEntries[nSeed1].YMin,
-                pasSrcEntries[nSeed1].XMax, 
+                pasSrcEntries[nSeed1].XMax,
                 pasSrcEntries[nSeed1].YMax,
                 pasSrcEntries[nSeed1].nBlockPtr);
 
     // Move nSeed2 to 2nd node
-    poNewNode->InsertEntry(pasSrcEntries[nSeed2].XMin, 
+    poNewNode->InsertEntry(pasSrcEntries[nSeed2].XMin,
                            pasSrcEntries[nSeed2].YMin,
-                           pasSrcEntries[nSeed2].XMax, 
+                           pasSrcEntries[nSeed2].XMax,
                            pasSrcEntries[nSeed2].YMax,
                            pasSrcEntries[nSeed2].nBlockPtr);
 
@@ -1214,7 +1215,7 @@ int     TABMAPIndexBlock::SplitNode(GInt32 nNewEntryXMin, GInt32 nNewEntryYMin,
         m_nCurChildIndex = m_numEntries-1;
 
     /*-----------------------------------------------------------------
-     * Go through the rest of the entries and assign them to one 
+     * Go through the rest of the entries and assign them to one
      * of the 2 nodes.
      *
      * Criteria is minimal area difference.
@@ -1232,9 +1233,9 @@ int     TABMAPIndexBlock::SplitNode(GInt32 nNewEntryXMin, GInt32 nNewEntryYMin,
         // stays in this node.
         if (iEntry == nSrcCurChildIndex)
         {
-            InsertEntry(pasSrcEntries[iEntry].XMin, 
+            InsertEntry(pasSrcEntries[iEntry].XMin,
                         pasSrcEntries[iEntry].YMin,
-                        pasSrcEntries[iEntry].XMax, 
+                        pasSrcEntries[iEntry].XMax,
                         pasSrcEntries[iEntry].YMax,
                         pasSrcEntries[iEntry].nBlockPtr);
 
@@ -1246,18 +1247,18 @@ int     TABMAPIndexBlock::SplitNode(GInt32 nNewEntryXMin, GInt32 nNewEntryYMin,
         }
         else if (m_numEntries >= GetMaxEntries()-1)
         {
-            poNewNode->InsertEntry(pasSrcEntries[iEntry].XMin, 
+            poNewNode->InsertEntry(pasSrcEntries[iEntry].XMin,
                                    pasSrcEntries[iEntry].YMin,
-                                   pasSrcEntries[iEntry].XMax, 
+                                   pasSrcEntries[iEntry].XMax,
                                    pasSrcEntries[iEntry].YMax,
                                    pasSrcEntries[iEntry].nBlockPtr);
             continue;
         }
         else if (poNewNode->GetNumEntries() >= GetMaxEntries()-1)
         {
-            InsertEntry(pasSrcEntries[iEntry].XMin, 
+            InsertEntry(pasSrcEntries[iEntry].XMin,
                         pasSrcEntries[iEntry].YMin,
-                        pasSrcEntries[iEntry].XMax, 
+                        pasSrcEntries[iEntry].XMax,
                         pasSrcEntries[iEntry].YMax,
                         pasSrcEntries[iEntry].nBlockPtr);
             continue;
@@ -1268,7 +1269,7 @@ int     TABMAPIndexBlock::SplitNode(GInt32 nNewEntryXMin, GInt32 nNewEntryYMin,
         double dAreaDiff1, dAreaDiff2;
         RecomputeMBR();
         dAreaDiff1 = ComputeAreaDiff(m_nMinX, m_nMinY, m_nMaxX, m_nMaxY,
-                                     pasSrcEntries[iEntry].XMin, 
+                                     pasSrcEntries[iEntry].XMin,
                                      pasSrcEntries[iEntry].YMin,
                                      pasSrcEntries[iEntry].XMax,
                                      pasSrcEntries[iEntry].YMax);
@@ -1277,25 +1278,25 @@ int     TABMAPIndexBlock::SplitNode(GInt32 nNewEntryXMin, GInt32 nNewEntryYMin,
         poNewNode->RecomputeMBR();
         poNewNode->GetMBR(nXMin2, nYMin2, nXMax2, nYMax2);
         dAreaDiff2 = ComputeAreaDiff(nXMin2, nYMin2, nXMax2, nYMax2,
-                                     pasSrcEntries[iEntry].XMin, 
+                                     pasSrcEntries[iEntry].XMin,
                                      pasSrcEntries[iEntry].YMin,
                                      pasSrcEntries[iEntry].XMax,
                                      pasSrcEntries[iEntry].YMax);
         if (dAreaDiff1 < dAreaDiff2)
         {
             // This entry stays in this node
-            InsertEntry(pasSrcEntries[iEntry].XMin, 
+            InsertEntry(pasSrcEntries[iEntry].XMin,
                         pasSrcEntries[iEntry].YMin,
-                        pasSrcEntries[iEntry].XMax, 
+                        pasSrcEntries[iEntry].XMax,
                         pasSrcEntries[iEntry].YMax,
                         pasSrcEntries[iEntry].nBlockPtr);
         }
         else
         {
             // This entry goes to new node
-            poNewNode->InsertEntry(pasSrcEntries[iEntry].XMin, 
+            poNewNode->InsertEntry(pasSrcEntries[iEntry].XMin,
                                    pasSrcEntries[iEntry].YMin,
-                                   pasSrcEntries[iEntry].XMax, 
+                                   pasSrcEntries[iEntry].XMax,
                                    pasSrcEntries[iEntry].YMax,
                                    pasSrcEntries[iEntry].nBlockPtr);
         }
@@ -1348,7 +1349,7 @@ int TABMAPIndexBlock::SplitRootNode(GInt32 nNewEntryXMin, GInt32 nNewEntryYMin,
      *----------------------------------------------------------------*/
     TABMAPIndexBlock *poNewNode = new TABMAPIndexBlock(m_eAccess);
 
-    if (poNewNode->InitNewBlock(m_fp, m_nBlockSize, 
+    if (poNewNode->InitNewBlock(m_fp, m_nBlockSize,
                                 m_poBlockManagerRef->AllocNewBlock("INDEX")) != 0)
     {
         return -1;
@@ -1360,13 +1361,13 @@ int TABMAPIndexBlock::SplitRootNode(GInt32 nNewEntryXMin, GInt32 nNewEntryYMin,
     m_numEntries = 0;
     for(int iEntry=0; iEntry<nSrcEntries; iEntry++)
     {
-        poNewNode->InsertEntry(m_asEntries[iEntry].XMin, 
+        poNewNode->InsertEntry(m_asEntries[iEntry].XMin,
                                m_asEntries[iEntry].YMin,
-                               m_asEntries[iEntry].XMax, 
+                               m_asEntries[iEntry].XMax,
                                m_asEntries[iEntry].YMax,
                                m_asEntries[iEntry].nBlockPtr);
     }
-    
+
     /*-----------------------------------------------------------------
      * Transfer current child object to new node.
      *----------------------------------------------------------------*/
@@ -1441,7 +1442,7 @@ void TABMAPIndexBlock::RecomputeMBR()
         m_bModified = TRUE;
 
         if (m_poParentRef)
-            m_poParentRef->UpdateCurChildMBR(m_nMinX, m_nMinY, 
+            m_poParentRef->UpdateCurChildMBR(m_nMinX, m_nMinY,
                                              m_nMaxX, m_nMaxY,
                                              GetNodeBlockPtr());
     }
@@ -1449,7 +1450,7 @@ void TABMAPIndexBlock::RecomputeMBR()
 }
 
 /**********************************************************************
- *                   TABMAPIndexBlock::UpateCurChildMBR()
+ *                   TABMAPIndexBlock::UpdateCurChildMBR()
  *
  * Update current child MBR info, and propagate info in parent.
  *
@@ -1488,7 +1489,7 @@ void TABMAPIndexBlock::UpdateCurChildMBR(GInt32 nXMin, GInt32 nYMin,
             m_nMinX = m_asEntries[i].XMin;
         if (m_asEntries[i].XMax > m_nMaxX)
             m_nMaxX = m_asEntries[i].XMax;
-    
+
         if (m_asEntries[i].YMin < m_nMinY)
             m_nMinY = m_asEntries[i].YMin;
         if (m_asEntries[i].YMax > m_nMaxY)
@@ -1505,7 +1506,7 @@ void TABMAPIndexBlock::UpdateCurChildMBR(GInt32 nXMin, GInt32 nYMin,
 /**********************************************************************
  *                   TABMAPIndexBlock::SetMAPBlockManagerRef()
  *
- * Pass a reference to the block manager object for the file this 
+ * Pass a reference to the block manager object for the file this
  * block belongs to.  The block manager will be used by this object
  * when it needs to automatically allocate a new block.
  **********************************************************************/
@@ -1555,7 +1556,7 @@ void TABMAPIndexBlock::Dump(FILE *fpOut /*=NULL*/)
     }
     else
     {
-        fprintf(fpOut,"Index Block (type %d) at offset %d.\n", 
+        fprintf(fpOut,"Index Block (type %d) at offset %d.\n",
                                                 m_nBlockType, m_nFileOffset);
         fprintf(fpOut,"  m_numEntries          = %d\n", m_numEntries);
 
diff --git a/ogr/ogrsf_frmts/mitab/mitab_mapobjectblock.cpp b/ogr/ogrsf_frmts/mitab/mitab_mapobjectblock.cpp
index b1771ae..331ce3b 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_mapobjectblock.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_mapobjectblock.cpp
@@ -18,16 +18,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -81,8 +81,8 @@
  * Handle the case of TAB_GEOM_NONE with the new TABMAPObjHdr classes.
  *
  * Revision 1.9  2001/11/17 21:54:06  daniel
- * Made several changes in order to support writing objects in 16 bits 
- * coordinate format. New TABMAPObjHdr-derived classes are used to hold 
+ * Made several changes in order to support writing objects in 16 bits
+ * coordinate format. New TABMAPObjHdr-derived classes are used to hold
  * object info in mem until block is full.
  *
  * Revision 1.8  2001/09/19 19:19:11  warmerda
@@ -112,6 +112,7 @@
  **********************************************************************/
 
 #include "mitab.h"
+#include "mitab_utils.h"
 
 /*=====================================================================
  *                      class TABMAPObjectBlock
@@ -128,6 +129,18 @@ TABMAPObjectBlock::TABMAPObjectBlock(TABAccess eAccessMode /*= TABRead*/):
     TABRawBinBlock(eAccessMode, TRUE)
 {
     m_bLockCenter = FALSE;
+    m_numDataBytes = 0;
+    m_nFirstCoordBlock = 0;
+    m_nLastCoordBlock = 0;
+    m_nCenterX = 0;
+    m_nCenterY = 0;
+    m_nMinX = 0;
+    m_nMinY = 0;
+    m_nMaxX = 0;
+    m_nMaxY = 0;
+    m_nCurObjectOffset = 0;
+    m_nCurObjectId = 0;
+    m_nCurObjectType = TAB_GEOM_UNSET;
 }
 
 /**********************************************************************
@@ -151,13 +164,13 @@ TABMAPObjectBlock::~TABMAPObjectBlock()
  * Perform some initialization on the block after its binary data has
  * been set or changed (or loaded from a file).
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
 int     TABMAPObjectBlock::InitBlockFromData(GByte *pabyBuf,
-                                             int nBlockSize, int nSizeUsed, 
+                                             int nBlockSize, int nSizeUsed,
                                              GBool bMakeCopy /* = TRUE */,
-                                             VSILFILE *fpSrc /* = NULL */, 
+                                             VSILFILE *fpSrc /* = NULL */,
                                              int nOffset /* = 0 */)
 {
     int nStatus;
@@ -165,11 +178,11 @@ int     TABMAPObjectBlock::InitBlockFromData(GByte *pabyBuf,
     /*-----------------------------------------------------------------
      * First of all, we must call the base class' InitBlockFromData()
      *----------------------------------------------------------------*/
-    nStatus = TABRawBinBlock::InitBlockFromData(pabyBuf, 
-                                                nBlockSize, nSizeUsed, 
+    nStatus = TABRawBinBlock::InitBlockFromData(pabyBuf,
+                                                nBlockSize, nSizeUsed,
                                                 bMakeCopy,
                                                 fpSrc, nOffset);
-    if (nStatus != 0)   
+    if (nStatus != 0)
         return nStatus;
 
     /*-----------------------------------------------------------------
@@ -190,6 +203,15 @@ int     TABMAPObjectBlock::InitBlockFromData(GByte *pabyBuf,
      *----------------------------------------------------------------*/
     GotoByteInBlock(0x002);
     m_numDataBytes = ReadInt16();       /* Excluding 4 bytes header */
+    if( m_numDataBytes < 0 || m_numDataBytes + MAP_OBJECT_HEADER_SIZE > nBlockSize )
+    {
+        CPLError(CE_Failure, CPLE_FileIO,
+                 "TABMAPObjectBlock::InitBlockFromData(): m_numDataBytes=%d incompatible with block size %d",
+                 m_numDataBytes, nBlockSize);
+        CPLFree(m_pabyBuf);
+        m_pabyBuf = NULL;
+        return -1;
+    }
 
     m_nCenterX = ReadInt32();
     m_nCenterY = ReadInt32();
@@ -275,7 +297,7 @@ void TABMAPObjectBlock::Rewind( )
 int TABMAPObjectBlock::AdvanceToNextObject( TABMAPHeaderBlock *poHeader )
 
 {
-    if( m_nCurObjectId == -1 ) 
+    if( m_nCurObjectId == -1 )
     {
         m_nCurObjectOffset = 20;
     }
@@ -283,8 +305,6 @@ int TABMAPObjectBlock::AdvanceToNextObject( TABMAPHeaderBlock *poHeader )
     {
         m_nCurObjectOffset += poHeader->GetMapObjectSize( m_nCurObjectType );
     }
-    
-    
 
     if( m_nCurObjectOffset + 5 < m_numDataBytes + 20 )
     {
@@ -308,7 +328,7 @@ int TABMAPObjectBlock::AdvanceToNextObject( TABMAPHeaderBlock *poHeader )
 
         // Is this object marked as deleted?  If so, skip it.
         // I check both the top bits but I have only seen this occur
-        // with the second highest bit set (ie. in usa/states.tab). NFW.
+        // with the second highest bit set (i.e. in usa/states.tab). NFW.
 
         if( (((GUInt32)m_nCurObjectId) & (GUInt32) 0xC0000000) != 0 )
         {
@@ -322,14 +342,14 @@ int TABMAPObjectBlock::AdvanceToNextObject( TABMAPHeaderBlock *poHeader )
 /**********************************************************************
  *                   TABMAPObjectBlock::CommitToFile()
  *
- * Commit the current state of the binary block to the file to which 
+ * Commit the current state of the binary block to the file to which
  * it has been previously attached.
  *
  * This method makes sure all values are properly set in the map object
  * block header and then calls TABRawBinBlock::CommitToFile() to do
  * the actual writing to disk.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
 int     TABMAPObjectBlock::CommitToFile()
@@ -338,7 +358,7 @@ int     TABMAPObjectBlock::CommitToFile()
 
     if ( m_pabyBuf == NULL )
     {
-        CPLError(CE_Failure, CPLE_AssertionFailed, 
+        CPLError(CE_Failure, CPLE_AssertionFailed,
      "TABMAPObjectBlock::CommitToFile(): Block has not been initialized yet!");
         return -1;
     }
@@ -358,7 +378,7 @@ int     TABMAPObjectBlock::CommitToFile()
     m_numDataBytes = m_nSizeUsed - MAP_OBJECT_HEADER_SIZE;
     CPLAssert(m_numDataBytes >= 0 && m_numDataBytes < 32768);
     WriteInt16((GInt16)m_numDataBytes);         // num. bytes used
-    
+
     WriteInt32(m_nCenterX);
     WriteInt32(m_nCenterY);
 
@@ -374,7 +394,7 @@ int     TABMAPObjectBlock::CommitToFile()
     if (nStatus == 0)
     {
 #ifdef DEBUG_VERBOSE
-        CPLDebug("MITAB", "Commiting OBJECT block to offset %d", m_nFileOffset);
+        CPLDebug("MITAB", "Committing OBJECT block to offset %d", m_nFileOffset);
 #endif
         nStatus = TABRawBinBlock::CommitToFile();
     }
@@ -386,22 +406,22 @@ int     TABMAPObjectBlock::CommitToFile()
  *                   TABMAPObjectBlock::InitNewBlock()
  *
  * Initialize a newly created block so that it knows to which file it
- * is attached, its block size, etc . and then perform any specific 
- * initialization for this block type, including writing a default 
+ * is attached, its block size, etc . and then perform any specific
+ * initialization for this block type, including writing a default
  * block header, etc. and leave the block ready to receive data.
  *
  * This is an alternative to calling ReadFromFile() or InitBlockFromData()
  * that puts the block in a stable state without loading any initial
  * data in it.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
-int     TABMAPObjectBlock::InitNewBlock(VSILFILE *fpSrc, int nBlockSize, 
+int     TABMAPObjectBlock::InitNewBlock(VSILFILE *fpSrc, int nBlockSize,
                                         int nFileOffset /* = 0*/)
 {
     /*-----------------------------------------------------------------
-     * Start with the default initialisation
+     * Start with the default initialization
      *----------------------------------------------------------------*/
     if ( TABRawBinBlock::InitNewBlock(fpSrc, nBlockSize, nFileOffset) != 0)
         return -1;
@@ -432,7 +452,7 @@ int     TABMAPObjectBlock::InitNewBlock(VSILFILE *fpSrc, int nBlockSize,
 
         WriteInt16(TABMAP_OBJECT_BLOCK);// Block type code
         WriteInt16(0);                  // num. bytes used, excluding header
-    
+
         // MBR center here... will be written in CommitToFile()
         WriteInt32(0);
         WriteInt32(0);
@@ -458,16 +478,18 @@ int     TABMAPObjectBlock::InitNewBlock(VSILFILE *fpSrc, int nBlockSize,
  * This means that the returned coordinates are always absolute integer
  * coordinates, even when the source coords are in compressed form.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
-int     TABMAPObjectBlock::ReadIntCoord(GBool bCompressed, 
+int     TABMAPObjectBlock::ReadIntCoord(GBool bCompressed,
                                         GInt32 &nX, GInt32 &nY)
 {
     if (bCompressed)
-    {   
-        nX = m_nCenterX + ReadInt16();
-        nY = m_nCenterY + ReadInt16();
+    {
+        nX = ReadInt16();
+        nY = ReadInt16();
+        TABSaturatedAdd(nX, m_nCenterX);
+        TABSaturatedAdd(nY, m_nCenterY);
     }
     else
     {
@@ -488,10 +510,10 @@ int     TABMAPObjectBlock::ReadIntCoord(GBool bCompressed,
  * the block.  If bCompr=TRUE then the coordinates are written relative to
  * the object block center... otherwise they're written as 32 bits int.
  *
- * This function does not maintain the block's MBR and center... it is 
+ * This function does not maintain the block's MBR and center... it is
  * assumed to have been set before the first call to WriteIntCoord()
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
 int     TABMAPObjectBlock::WriteIntCoord(GInt32 nX, GInt32 nY,
@@ -514,17 +536,17 @@ int     TABMAPObjectBlock::WriteIntCoord(GInt32 nX, GInt32 nY,
 /**********************************************************************
  *                   TABMAPObjectBlock::WriteIntMBRCoord()
  *
- * Write 2 pairs of integer coordinates values to the current position 
- * in the the block after making sure that min values are smaller than
+ * Write 2 pairs of integer coordinates values to the current position
+ * in the block after making sure that min values are smaller than
  * max values.  Use this function to write MBR coordinates for an object.
  *
  * If bCompr=TRUE then the coordinates are written relative to
  * the object block center... otherwise they're written as 32 bits int.
  *
- * This function does not maintain the block's MBR and center... it is 
+ * This function does not maintain the block's MBR and center... it is
  * assumed to have been set before the first call to WriteIntCoord()
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
 int     TABMAPObjectBlock::WriteIntMBRCoord(GInt32 nXMin, GInt32 nYMin,
@@ -533,7 +555,7 @@ int     TABMAPObjectBlock::WriteIntMBRCoord(GInt32 nXMin, GInt32 nYMin,
 {
     if (WriteIntCoord(MIN(nXMin, nXMax), MIN(nYMin, nYMax),
                       bCompressed) != 0 ||
-        WriteIntCoord(MAX(nXMin, nXMax), MAX(nYMin, nYMax), 
+        WriteIntCoord(MAX(nXMin, nXMax), MAX(nYMin, nYMax),
                       bCompressed) != 0 )
     {
         return -1;
@@ -548,7 +570,7 @@ int     TABMAPObjectBlock::WriteIntMBRCoord(GInt32 nXMin, GInt32 nYMin,
  *
  * Update the block's MBR and center.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
 int     TABMAPObjectBlock::UpdateMBR(GInt32 nX, GInt32 nY)
@@ -563,13 +585,13 @@ int     TABMAPObjectBlock::UpdateMBR(GInt32 nX, GInt32 nY)
         m_nMinY = nY;
     if (nY > m_nMaxY)
         m_nMaxY = nY;
-    
+
     if( !m_bLockCenter )
     {
         m_nCenterX = (m_nMinX + m_nMaxX) /2;
         m_nCenterY = (m_nMinY + m_nMaxY) /2;
     }
-    
+
     return 0;
 }
 
@@ -583,7 +605,7 @@ void     TABMAPObjectBlock::AddCoordBlockRef(GInt32 nNewBlockAddress)
 {
     /*-----------------------------------------------------------------
      * Normally, new blocks are added to the end of the list, except
-     * the first one which is the beginning and the end of the list at 
+     * the first one which is the beginning and the end of the list at
      * the same time.
      *----------------------------------------------------------------*/
     if (m_nFirstCoordBlock == 0)
@@ -598,13 +620,13 @@ void     TABMAPObjectBlock::AddCoordBlockRef(GInt32 nNewBlockAddress)
  *
  * Set the MBR for the current block.
  **********************************************************************/
-void TABMAPObjectBlock::SetMBR(GInt32 nXMin, GInt32 nYMin, 
+void TABMAPObjectBlock::SetMBR(GInt32 nXMin, GInt32 nYMin,
                                GInt32 nXMax, GInt32 nYMax)
 {
     m_nMinX = nXMin;
     m_nMinY = nYMin;
     m_nMaxX = nXMax;
-    m_nMaxY = nYMax; 
+    m_nMaxY = nYMax;
 
     if( !m_bLockCenter )
     {
@@ -618,13 +640,13 @@ void TABMAPObjectBlock::SetMBR(GInt32 nXMin, GInt32 nYMin,
  *
  * Return the MBR for the current block.
  **********************************************************************/
-void TABMAPObjectBlock::GetMBR(GInt32 &nXMin, GInt32 &nYMin, 
+void TABMAPObjectBlock::GetMBR(GInt32 &nXMin, GInt32 &nYMin,
                                GInt32 &nXMax, GInt32 &nYMax)
 {
     nXMin = m_nMinX;
     nYMin = m_nMinY;
     nXMax = m_nMaxX;
-    nYMax = m_nMaxY; 
+    nYMax = m_nMaxY;
 }
 
 
@@ -650,13 +672,13 @@ int     TABMAPObjectBlock::PrepareNewObject(TABMAPObjHdr *poObjHdr)
     // Maintain MBR of this object block.
     UpdateMBR(poObjHdr->m_nMinX, poObjHdr->m_nMinY);
     UpdateMBR(poObjHdr->m_nMaxX, poObjHdr->m_nMaxY);
-   
+
     /*-----------------------------------------------------------------
      * Keep track of object type, ID and start address for use by
      * CommitNewObject()
      *----------------------------------------------------------------*/
     nStartAddress = GetFirstUnusedByteOffset();
-    
+
     // Backup MBR and bLockCenter as they will be reset by GotoByteInFile()
     // that will call InitBlockFromData()
     GInt32 nXMin, nYMin, nXMax, nYMax;
@@ -676,17 +698,19 @@ int     TABMAPObjectBlock::PrepareNewObject(TABMAPObjHdr *poObjHdr)
 /**********************************************************************
  *                   TABMAPObjectBlock::CommitCurObjData()
  *
- * Write the ObjHdr to this block. This is usually called after 
+ * Write the ObjHdr to this block. This is usually called after
  * PrepareNewObject() once all members of the ObjHdr have
  * been set.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
 int     TABMAPObjectBlock::CommitNewObject(TABMAPObjHdr *poObjHdr)
 {
     int nStatus = 0;
 
+    CPLAssert (poObjHdr->m_nType != TAB_GEOM_NONE);
+
     // Nothing to do for NONE objects
     if (poObjHdr->m_nType == TAB_GEOM_NONE)
     {
@@ -725,7 +749,7 @@ void TABMAPObjectBlock::Dump(FILE *fpOut, GBool bDetails)
     }
     else
     {
-        fprintf(fpOut,"Object Data Block (type %d) at offset %d.\n", 
+        fprintf(fpOut,"Object Data Block (type %d) at offset %d.\n",
                                                 m_nBlockType, m_nFileOffset);
         fprintf(fpOut,"  m_numDataBytes        = %d\n", m_numDataBytes);
         fprintf(fpOut,"  m_nCenterX            = %d\n", m_nCenterX);
@@ -744,7 +768,7 @@ void TABMAPObjectBlock::Dump(FILE *fpOut, GBool bDetails)
         poBlock = TABCreateMAPBlockFromFile(m_fp, 0, m_nBlockSize);
         if (poBlock==NULL || poBlock->GetBlockClass() != TABMAP_HEADER_BLOCK)
         {
-            CPLError(CE_Failure, CPLE_AssertionFailed, 
+            CPLError(CE_Failure, CPLE_AssertionFailed,
                      "Failed reading header block.");
             return;
         }
@@ -753,7 +777,7 @@ void TABMAPObjectBlock::Dump(FILE *fpOut, GBool bDetails)
         Rewind();
         while((poObjHdr = TABMAPObjHdr::ReadNextObj(this, poHeader)) != NULL)
         {
-            fprintf(fpOut, 
+            fprintf(fpOut,
                     "   object id=%d, type=%d, offset=%d (%d), size=%d\n"
                     "          MBR=(%d, %d, %d, %d)\n",
                     m_nCurObjectId, m_nCurObjectType, m_nCurObjectOffset,
@@ -790,7 +814,7 @@ void TABMAPObjectBlock::Dump(FILE *fpOut, GBool bDetails)
 /**********************************************************************
  *                    TABMAPObjHdr::NewObj()
  *
- * Alloc a new object of specified type or NULL for NONE types or if type 
+ * Alloc a new object of specified type or NULL for NONE types or if type
  * is not supported.
  **********************************************************************/
 TABMAPObjHdr *TABMAPObjHdr::NewObj(TABGeomType nNewObjType, GInt32 nId /*=0*/)
@@ -863,7 +887,7 @@ TABMAPObjHdr *TABMAPObjHdr::NewObj(TABGeomType nNewObjType, GInt32 nId /*=0*/)
         poObj = new TABMAPObjCollection();
     break;
       default:
-        CPLError(CE_Failure, CPLE_AssertionFailed, 
+        CPLError(CE_Failure, CPLE_AssertionFailed,
                  "TABMAPObjHdr::NewObj(): Unsupported object type %d",
                  nNewObjType);
     }
@@ -883,7 +907,7 @@ TABMAPObjHdr *TABMAPObjHdr::NewObj(TABGeomType nNewObjType, GInt32 nId /*=0*/)
  *                    TABMAPObjHdr::ReadNextObj()
  *
  * Read next object in this block and allocate/init a new object for it
- * if succesful.  
+ * if successful.
  * Returns NULL in case of error or if we reached end of block.
  **********************************************************************/
 TABMAPObjHdr *TABMAPObjHdr::ReadNextObj(TABMAPObjectBlock *poObjBlock,
@@ -937,7 +961,7 @@ int TABMAPObjHdr::WriteObjTypeAndId(TABMAPObjectBlock *poObjBlock)
  *                   TABMAPObjHdr::SetMBR()
  *
  **********************************************************************/
-void TABMAPObjHdr::SetMBR(GInt32 nMinX, GInt32 nMinY, 
+void TABMAPObjHdr::SetMBR(GInt32 nMinX, GInt32 nMinY,
                           GInt32 nMaxX, GInt32 nMaxY)
 {
     m_nMinX = MIN(nMinX, nMaxX);
@@ -956,7 +980,7 @@ void TABMAPObjHdr::SetMBR(GInt32 nMinX, GInt32 nMinY,
 /**********************************************************************
  *                   TABMAPObjLine::ReadObj()
  *
- * Read Object information starting after the object id which should 
+ * Read Object information starting after the object id which should
  * have been read by TABMAPObjHdr::ReadNextObj() already.
  * This function should be called only by TABMAPObjHdr::ReadNextObj().
  *
@@ -1031,7 +1055,7 @@ int TABMAPObjPLine::ReadObj(TABMAPObjectBlock *poObjBlock)
     }
 
 #ifdef TABDUMP
-    printf("TABMAPObjPLine::ReadObj: m_nCoordDataSize = %d @ %d\n", 
+    printf("TABMAPObjPLine::ReadObj: m_nCoordDataSize = %d @ %d\n",
            m_nCoordDataSize, m_nCoordBlockPtr);
 #endif
 
@@ -1065,10 +1089,17 @@ int TABMAPObjPLine::ReadObj(TABMAPObjectBlock *poObjBlock)
         m_numLineSections = poObjBlock->ReadInt16();
     }
 
+    if( m_numLineSections < 0 )
+    {
+        CPLError(CE_Failure, CPLE_AssertionFailed,
+                    "Invalid numLineSections");
+        return -1;
+    }
+
 #ifdef TABDUMP
     printf("PLINE/REGION: id=%d, type=%d, "
            "CoordBlockPtr=%d, CoordDataSize=%d, numLineSect=%d, bSmooth=%d\n",
-           m_nId, m_nType, m_nCoordBlockPtr, m_nCoordDataSize, 
+           m_nId, m_nType, m_nCoordBlockPtr, m_nCoordDataSize,
            m_numLineSections, m_bSmooth);
 #endif
 
@@ -1083,13 +1114,17 @@ int TABMAPObjPLine::ReadObj(TABMAPObjectBlock *poObjBlock)
         m_nComprOrgX = poObjBlock->ReadInt32();
         m_nComprOrgY = poObjBlock->ReadInt32();
 
-        m_nLabelX += m_nComprOrgX;
-        m_nLabelY += m_nComprOrgY;
+        TABSaturatedAdd(m_nLabelX, m_nComprOrgX);
+        TABSaturatedAdd(m_nLabelY, m_nComprOrgY);
 
-        m_nMinX = m_nComprOrgX + poObjBlock->ReadInt16();  // Read MBR
-        m_nMinY = m_nComprOrgY + poObjBlock->ReadInt16();
-        m_nMaxX = m_nComprOrgX + poObjBlock->ReadInt16();
-        m_nMaxY = m_nComprOrgY + poObjBlock->ReadInt16();
+        m_nMinX = poObjBlock->ReadInt16();  // Read MBR
+        m_nMinY = poObjBlock->ReadInt16();
+        m_nMaxX = poObjBlock->ReadInt16();
+        m_nMaxY = poObjBlock->ReadInt16();
+        TABSaturatedAdd(m_nMinX, m_nComprOrgX);
+        TABSaturatedAdd(m_nMinY, m_nComprOrgY);
+        TABSaturatedAdd(m_nMaxX, m_nComprOrgX);
+        TABSaturatedAdd(m_nMaxY, m_nComprOrgY);
     }
     else
     {
@@ -1108,8 +1143,8 @@ int TABMAPObjPLine::ReadObj(TABMAPObjectBlock *poObjBlock)
     if ( ! IsCompressedType() )
     {
         // Init. Compr. Origin to a default value in case type is ever changed
-        m_nComprOrgX = (m_nMinX + m_nMaxX) / 2;
-        m_nComprOrgY = (m_nMinY + m_nMaxY) / 2;
+        m_nComprOrgX = static_cast<GInt32>((static_cast<GIntBig>(m_nMinX) + m_nMaxX) / 2);
+        m_nComprOrgY = static_cast<GInt32>((static_cast<GIntBig>(m_nMinY) + m_nMaxY) / 2);
     }
 
     m_nPenId = poObjBlock->ReadByte();      // Pen index
@@ -1335,7 +1370,7 @@ int TABMAPObjFontPoint::WriteObj(TABMAPObjectBlock *poObjBlock)
     poObjBlock->WriteByte( 0 );
     poObjBlock->WriteByte( 0 );
     poObjBlock->WriteByte( 0 );
-    
+
     poObjBlock->WriteInt16(m_nAngle);
 
     poObjBlock->WriteIntCoord(m_nX, m_nY, IsCompressedType());
@@ -1361,7 +1396,7 @@ int TABMAPObjFontPoint::WriteObj(TABMAPObjectBlock *poObjBlock)
  **********************************************************************/
 int TABMAPObjCustomPoint::ReadObj(TABMAPObjectBlock *poObjBlock)
 {
-    m_nUnknown_ = poObjBlock->ReadByte();       // ??? 
+    m_nUnknown_ = poObjBlock->ReadByte();       // ???
     m_nCustomStyle = poObjBlock->ReadByte(); // 0x01=Show BG, 0x02=Apply Color
 
     poObjBlock->ReadIntCoord(IsCompressedType(), m_nX, m_nY);
@@ -1389,7 +1424,7 @@ int TABMAPObjCustomPoint::WriteObj(TABMAPObjectBlock *poObjBlock)
     // Write object type and id
     TABMAPObjHdr::WriteObjTypeAndId(poObjBlock);
 
-    poObjBlock->WriteByte(m_nUnknown_);  // ??? 
+    poObjBlock->WriteByte(m_nUnknown_);  // ???
     poObjBlock->WriteByte(m_nCustomStyle); // 0x01=Show BG, 0x02=Apply Color
     poObjBlock->WriteIntCoord(m_nX, m_nY, IsCompressedType());
 
@@ -1414,7 +1449,7 @@ int TABMAPObjCustomPoint::WriteObj(TABMAPObjectBlock *poObjBlock)
  **********************************************************************/
 int TABMAPObjRectEllipse::ReadObj(TABMAPObjectBlock *poObjBlock)
 {
-    if (m_nType == TAB_GEOM_ROUNDRECT || 
+    if (m_nType == TAB_GEOM_ROUNDRECT ||
         m_nType == TAB_GEOM_ROUNDRECT_C)
     {
         if (IsCompressedType())
@@ -1453,7 +1488,7 @@ int TABMAPObjRectEllipse::WriteObj(TABMAPObjectBlock *poObjBlock)
     // Write object type and id
     TABMAPObjHdr::WriteObjTypeAndId(poObjBlock);
 
-    if (m_nType == TAB_GEOM_ROUNDRECT || 
+    if (m_nType == TAB_GEOM_ROUNDRECT ||
         m_nType == TAB_GEOM_ROUNDRECT_C)
     {
         if (IsCompressedType())
@@ -1468,7 +1503,7 @@ int TABMAPObjRectEllipse::WriteObj(TABMAPObjectBlock *poObjBlock)
         }
     }
 
-    poObjBlock->WriteIntMBRCoord(m_nMinX, m_nMinY, m_nMaxX, m_nMaxY, 
+    poObjBlock->WriteIntMBRCoord(m_nMinX, m_nMinY, m_nMaxX, m_nMaxY,
                                  IsCompressedType());
 
     poObjBlock->WriteByte(m_nPenId);      // Pen index
@@ -1497,9 +1532,9 @@ int TABMAPObjArc::ReadObj(TABMAPObjectBlock *poObjBlock)
     m_nEndAngle   = poObjBlock->ReadInt16();
 
     // An arc is defined by its defining ellipse's MBR:
-    poObjBlock->ReadIntCoord(IsCompressedType(), 
+    poObjBlock->ReadIntCoord(IsCompressedType(),
                              m_nArcEllipseMinX, m_nArcEllipseMinY);
-    poObjBlock->ReadIntCoord(IsCompressedType(), 
+    poObjBlock->ReadIntCoord(IsCompressedType(),
                              m_nArcEllipseMaxX, m_nArcEllipseMaxY);
 
     // Read the Arc's actual MBR
@@ -1528,14 +1563,14 @@ int TABMAPObjArc::WriteObj(TABMAPObjectBlock *poObjBlock)
 
     poObjBlock->WriteInt16((GInt16)m_nStartAngle);
     poObjBlock->WriteInt16((GInt16)m_nEndAngle);
-    
+
     // An arc is defined by its defining ellipse's MBR:
-    poObjBlock->WriteIntMBRCoord(m_nArcEllipseMinX, m_nArcEllipseMinY, 
-                                 m_nArcEllipseMaxX, m_nArcEllipseMaxY, 
+    poObjBlock->WriteIntMBRCoord(m_nArcEllipseMinX, m_nArcEllipseMinY,
+                                 m_nArcEllipseMaxX, m_nArcEllipseMaxY,
                                  IsCompressedType());
 
     // Write the Arc's actual MBR
-    poObjBlock->WriteIntMBRCoord(m_nMinX, m_nMinY, m_nMaxX, m_nMaxY, 
+    poObjBlock->WriteIntMBRCoord(m_nMinX, m_nMinY, m_nMaxX, m_nMaxY,
                                  IsCompressedType());
 
     poObjBlock->WriteByte(m_nPenId);      // Pen index
@@ -1562,6 +1597,11 @@ int TABMAPObjText::ReadObj(TABMAPObjectBlock *poObjBlock)
 {
     m_nCoordBlockPtr  = poObjBlock->ReadInt32();    // String position
     m_nCoordDataSize  = poObjBlock->ReadInt16();    // String length
+    if( m_nCoordDataSize < 0 )
+    {
+        CPLError(CE_Failure, CPLE_AssertionFailed, "m_nCoordDataSize < 0");
+        return -1;
+    }
     m_nTextAlignment  = poObjBlock->ReadInt16();    // just./spacing/arrow
 
     m_nAngle     = poObjBlock->ReadInt16();         // Tenths of degree
@@ -1641,7 +1681,7 @@ int TABMAPObjText::WriteObj(TABMAPObjectBlock *poObjBlock)
     poObjBlock->WriteByte(m_nFontId);      // Font name index
 
     // MBR after rotation
-    poObjBlock->WriteIntMBRCoord(m_nMinX, m_nMinY, m_nMaxX, m_nMaxY, 
+    poObjBlock->WriteIntMBRCoord(m_nMinX, m_nMinY, m_nMaxX, m_nMaxY,
                                  IsCompressedType());
 
     poObjBlock->WriteByte(m_nPenId);      // Pen index
@@ -1661,7 +1701,7 @@ int TABMAPObjText::WriteObj(TABMAPObjectBlock *poObjBlock)
 /**********************************************************************
  *                   TABMAPObjMultiPoint::ReadObj()
  *
- * Read Object information starting after the object id which should 
+ * Read Object information starting after the object id which should
  * have been read by TABMAPObjHdr::ReadNextObj() already.
  * This function should be called only by TABMAPObjHdr::ReadNextObj().
  *
@@ -1672,15 +1712,14 @@ int TABMAPObjMultiPoint::ReadObj(TABMAPObjectBlock *poObjBlock)
     m_nCoordBlockPtr = poObjBlock->ReadInt32();
     m_nNumPoints = poObjBlock->ReadInt32();
 
-    if (IsCompressedType())
-    {
-        m_nCoordDataSize = m_nNumPoints * 2 * 2;
-    }
-    else
+    const int nPointSize = (IsCompressedType()) ? 2 * 2 : 2 * 4;
+    if( m_nNumPoints < 0 || m_nNumPoints > INT_MAX / nPointSize )
     {
-        m_nCoordDataSize = m_nNumPoints * 2 * 4;
+        CPLError(CE_Failure, CPLE_AssertionFailed,
+                 "Invalid m_nNumPoints = %d", m_nNumPoints);
+        return -1;
     }
-
+    m_nCoordDataSize = m_nNumPoints * nPointSize;
 
 #ifdef TABDUMP
     printf("MULTIPOINT: id=%d, type=%d, "
@@ -1727,13 +1766,17 @@ int TABMAPObjMultiPoint::ReadObj(TABMAPObjectBlock *poObjBlock)
         m_nComprOrgX = poObjBlock->ReadInt32();
         m_nComprOrgY = poObjBlock->ReadInt32();
 
-        m_nLabelX += m_nComprOrgX;
-        m_nLabelY += m_nComprOrgY;
+        TABSaturatedAdd(m_nLabelX, m_nComprOrgX);
+        TABSaturatedAdd(m_nLabelY, m_nComprOrgY);
 
-        m_nMinX = m_nComprOrgX + poObjBlock->ReadInt16();  // Read MBR
-        m_nMinY = m_nComprOrgY + poObjBlock->ReadInt16();
-        m_nMaxX = m_nComprOrgX + poObjBlock->ReadInt16();
-        m_nMaxY = m_nComprOrgY + poObjBlock->ReadInt16();
+        m_nMinX = poObjBlock->ReadInt16();  // Read MBR
+        m_nMinY = poObjBlock->ReadInt16();
+        m_nMaxX = poObjBlock->ReadInt16();
+        m_nMaxY = poObjBlock->ReadInt16();
+        TABSaturatedAdd(m_nMinX, m_nComprOrgX);
+        TABSaturatedAdd(m_nMinY, m_nComprOrgY);
+        TABSaturatedAdd(m_nMaxX, m_nComprOrgX);
+        TABSaturatedAdd(m_nMaxY, m_nComprOrgY);
     }
     else
     {
@@ -1747,8 +1790,8 @@ int TABMAPObjMultiPoint::ReadObj(TABMAPObjectBlock *poObjBlock)
         m_nMaxY = poObjBlock->ReadInt32();
 
         // Init. Compr. Origin to a default value in case type is ever changed
-        m_nComprOrgX = (m_nMinX + m_nMaxX) / 2;
-        m_nComprOrgY = (m_nMinY + m_nMaxY) / 2;
+        m_nComprOrgX = static_cast<GInt32>((static_cast<GIntBig>(m_nMinX) + m_nMaxX) / 2);
+        m_nComprOrgY = static_cast<GInt32>((static_cast<GIntBig>(m_nMinY) + m_nMaxY) / 2);
     }
 
     if (CPLGetLastErrorNo() != 0)
@@ -1834,7 +1877,7 @@ int TABMAPObjMultiPoint::WriteObj(TABMAPObjectBlock *poObjBlock)
 /**********************************************************************
  *                   TABMAPObjCollection::ReadObj()
  *
- * Read Object information starting after the object id which should 
+ * Read Object information starting after the object id which should
  * have been read by TABMAPObjHdr::ReadNextObj() already.
  * This function should be called only by TABMAPObjHdr::ReadNextObj().
  *
@@ -1851,18 +1894,18 @@ int TABMAPObjCollection::ReadObj(TABMAPObjectBlock *poObjBlock)
     if (IsCompressedType())
     {
         /* 6 * int16 */
-        SIZE_OF_REGION_PLINE_MINI_HDR = SIZE_OF_MPOINT_MINI_HDR = 12; 
+        SIZE_OF_REGION_PLINE_MINI_HDR = SIZE_OF_MPOINT_MINI_HDR = 12;
     }
     else
     {
         /* 6 * int32 */
         SIZE_OF_REGION_PLINE_MINI_HDR = SIZE_OF_MPOINT_MINI_HDR = 24;
     }
-  
+
     if (nVersion >= 800)
     {
         /* extra 4 bytes for num_segments in Region/Pline mini-headers */
-        SIZE_OF_REGION_PLINE_MINI_HDR += 4;  
+        SIZE_OF_REGION_PLINE_MINI_HDR += 4;
     }
 
     m_nCoordBlockPtr = poObjBlock->ReadInt32();    // pointer into coord block
@@ -1870,39 +1913,68 @@ int TABMAPObjCollection::ReadObj(TABMAPObjectBlock *poObjBlock)
     m_nRegionDataSize = poObjBlock->ReadInt32();   // size of region data inc. section hdrs
     m_nPolylineDataSize = poObjBlock->ReadInt32(); // size of multipline data inc. section hdrs
 
+    if( m_nRegionDataSize < 0 )
+    {
+        CPLError(CE_Failure, CPLE_AssertionFailed,
+                    "Invalid m_nRegionDataSize");
+        return -1;
+    }
+
+    if( m_nPolylineDataSize < 0 )
+    {
+        CPLError(CE_Failure, CPLE_AssertionFailed,
+                    "Invalid m_nRegionDataSize");
+        return -1;
+    }
+
     if (nVersion < 800)
     {
         // Num Region/Pline section headers (int16 in V650)
-        m_nNumRegSections = poObjBlock->ReadInt16();   
+        m_nNumRegSections = poObjBlock->ReadInt16();
         m_nNumPLineSections = poObjBlock->ReadInt16();
     }
     else
     {
         // Num Region/Pline section headers (int32 in V800)
-        m_nNumRegSections = poObjBlock->ReadInt32();   
+        m_nNumRegSections = poObjBlock->ReadInt32();
         m_nNumPLineSections = poObjBlock->ReadInt32();
     }
 
-
-    if (IsCompressedType())
+    const int nPointSize = (IsCompressedType()) ? 2 * 2 : 2 * 4;
+    if( m_nNumMultiPoints < 0 || m_nNumMultiPoints > INT_MAX / nPointSize )
     {
-        m_nMPointDataSize = m_nNumMultiPoints * 2 * 2;
-    }
-    else
-    {
-        m_nMPointDataSize = m_nNumMultiPoints * 2 * 4;
+        CPLError(CE_Failure, CPLE_AssertionFailed,
+                    "Invalid m_nNumMultiPoints");
+        return -1;
     }
 
+    m_nMPointDataSize = m_nNumMultiPoints * nPointSize;
+
     /* NB. MapInfo counts 2 extra bytes per Region and Pline section header
-     * in the RegionDataSize and PolylineDataSize values but those 2 extra 
+     * in the RegionDataSize and PolylineDataSize values but those 2 extra
      * bytes are not present in the section hdr (possibly due to an alignment
-     * to a 4 byte boundary in memory in MapInfo?). The real data size in 
-     * the CoordBlock is actually 2 bytes shorter per section header than 
+     * to a 4 byte boundary in memory in MapInfo?). The real data size in
+     * the CoordBlock is actually 2 bytes shorter per section header than
      * what is written in RegionDataSize and PolylineDataSize values.
      *
      * We'll adjust the values in memory to be the corrected values.
      */
+    if( m_nNumRegSections < 0 || m_nNumRegSections > INT_MAX / 2 ||
+        m_nRegionDataSize < 2 * m_nNumRegSections )
+    {
+        CPLError(CE_Failure, CPLE_AssertionFailed,
+                    "Invalid m_nNumRegSections / m_nRegionDataSize");
+        return -1;
+    }
     m_nRegionDataSize   = m_nRegionDataSize - (2 * m_nNumRegSections);
+
+    if( m_nNumPLineSections < 0 || m_nNumPLineSections > INT_MAX / 2 ||
+        m_nPolylineDataSize < 2 * m_nNumPLineSections )
+    {
+        CPLError(CE_Failure, CPLE_AssertionFailed,
+                    "Invalid m_nNumPLineSections / m_nPolylineDataSize");
+        return -1;
+    }
     m_nPolylineDataSize = m_nPolylineDataSize - (2 * m_nNumPLineSections);
 
     /* Compute total coord block data size, required when splitting blocks */
@@ -1910,14 +1982,35 @@ int TABMAPObjCollection::ReadObj(TABMAPObjectBlock *poObjBlock)
 
     if(m_nNumRegSections > 0)
     {
+        if( m_nRegionDataSize > INT_MAX - SIZE_OF_REGION_PLINE_MINI_HDR ||
+            m_nCoordDataSize > INT_MAX - (SIZE_OF_REGION_PLINE_MINI_HDR + m_nRegionDataSize) )
+        {
+            CPLError(CE_Failure, CPLE_AssertionFailed,
+                        "Invalid m_nCoordDataSize / m_nRegionDataSize");
+            return -1;
+        }
         m_nCoordDataSize += SIZE_OF_REGION_PLINE_MINI_HDR + m_nRegionDataSize;
     }
     if(m_nNumPLineSections > 0)
     {
+        if( m_nPolylineDataSize > INT_MAX - SIZE_OF_REGION_PLINE_MINI_HDR ||
+            m_nCoordDataSize > INT_MAX - (SIZE_OF_REGION_PLINE_MINI_HDR + m_nPolylineDataSize) )
+        {
+            CPLError(CE_Failure, CPLE_AssertionFailed,
+                        "Invalid m_nCoordDataSize / m_nPolylineDataSize");
+            return -1;
+        }
         m_nCoordDataSize += SIZE_OF_REGION_PLINE_MINI_HDR + m_nPolylineDataSize;
     }
     if(m_nNumMultiPoints > 0)
     {
+        if( m_nMPointDataSize > INT_MAX - SIZE_OF_MPOINT_MINI_HDR ||
+            m_nCoordDataSize > INT_MAX - (SIZE_OF_MPOINT_MINI_HDR + m_nMPointDataSize) )
+        {
+            CPLError(CE_Failure, CPLE_AssertionFailed,
+                        "Invalid m_nCoordDataSize / m_nMPointDataSize");
+            return -1;
+        }
         m_nCoordDataSize += SIZE_OF_MPOINT_MINI_HDR + m_nMPointDataSize;
     }
 
@@ -1926,7 +2019,7 @@ int TABMAPObjCollection::ReadObj(TABMAPObjectBlock *poObjBlock)
     printf("COLLECTION: id=%d, type=%d (0x%x), "
            "CoordBlockPtr=%d, numRegionSections=%d (size=%d+%d), "
            "numPlineSections=%d (size=%d+%d), numPoints=%d (size=%d+%d)\n",
-           m_nId, m_nType, m_nType, m_nCoordBlockPtr, 
+           m_nId, m_nType, m_nType, m_nCoordBlockPtr,
            m_nNumRegSections, m_nRegionDataSize, SIZE_OF_REGION_PLINE_MINI_HDR,
            m_nNumPLineSections, m_nPolylineDataSize, SIZE_OF_REGION_PLINE_MINI_HDR,
            m_nNumMultiPoints, m_nMPointDataSize, SIZE_OF_MPOINT_MINI_HDR);
@@ -1938,7 +2031,7 @@ int TABMAPObjCollection::ReadObj(TABMAPObjectBlock *poObjBlock)
         int nValue = poObjBlock->ReadByte();
         if (nValue != 4)
         {
-            CPLError(CE_Failure, CPLE_AssertionFailed, 
+            CPLError(CE_Failure, CPLE_AssertionFailed,
                      "TABMAPObjCollection::ReadObj(): Byte 29 in Collection "
                      "object header not equal to 4 as expected. Value is %d. "
                      "Please report this error to the MITAB list so that "
@@ -1974,10 +2067,14 @@ int TABMAPObjCollection::ReadObj(TABMAPObjectBlock *poObjBlock)
         m_nComprOrgX = poObjBlock->ReadInt32();
         m_nComprOrgY = poObjBlock->ReadInt32();
 
-        m_nMinX = m_nComprOrgX + poObjBlock->ReadInt16();  // Read MBR
-        m_nMinY = m_nComprOrgY + poObjBlock->ReadInt16();
-        m_nMaxX = m_nComprOrgX + poObjBlock->ReadInt16();
-        m_nMaxY = m_nComprOrgY + poObjBlock->ReadInt16();
+        m_nMinX = poObjBlock->ReadInt16();  // Read MBR
+        m_nMinY = poObjBlock->ReadInt16();
+        m_nMaxX = poObjBlock->ReadInt16();
+        m_nMaxY = poObjBlock->ReadInt16();
+        TABSaturatedAdd(m_nMinX, m_nComprOrgX);
+        TABSaturatedAdd(m_nMinY, m_nComprOrgY);
+        TABSaturatedAdd(m_nMaxX, m_nComprOrgX);
+        TABSaturatedAdd(m_nMaxY, m_nComprOrgY);
 #ifdef TABDUMP
     printf("COLLECTION: ComprOrgX,Y= (%d,%d)\n",
            m_nComprOrgX, m_nComprOrgY);
@@ -1991,8 +2088,8 @@ int TABMAPObjCollection::ReadObj(TABMAPObjectBlock *poObjBlock)
         m_nMaxY = poObjBlock->ReadInt32();
 
         // Init. Compr. Origin to a default value in case type is ever changed
-        m_nComprOrgX = (m_nMinX + m_nMaxX) / 2;
-        m_nComprOrgY = (m_nMinY + m_nMaxY) / 2;
+        m_nComprOrgX = static_cast<GInt32>((static_cast<GIntBig>(m_nMinX) + m_nMaxX) / 2);
+        m_nComprOrgY = static_cast<GInt32>((static_cast<GIntBig>(m_nMinY) + m_nMaxY) / 2);
     }
 
     if (CPLGetLastErrorNo() != 0)
@@ -2017,14 +2114,14 @@ int TABMAPObjCollection::WriteObj(TABMAPObjectBlock *poObjBlock)
     int nVersion = TAB_GEOM_GET_VERSION(m_nType);
 
     /* NB. MapInfo counts 2 extra bytes per Region and Pline section header
-     * in the RegionDataSize and PolylineDataSize values but those 2 extra 
+     * in the RegionDataSize and PolylineDataSize values but those 2 extra
      * bytes are not present in the section hdr (possibly due to an alignment
-     * to a 4 byte boundary in memory in MapInfo?). The real data size in 
-     * the CoordBlock is actually 2 bytes shorter per section header than 
+     * to a 4 byte boundary in memory in MapInfo?). The real data size in
+     * the CoordBlock is actually 2 bytes shorter per section header than
      * what is written in RegionDataSize and PolylineDataSize values.
      *
      * The values in memory are the corrected values so we need to add 2 bytes
-     * per section header in the values that we write on disk to emulate 
+     * per section header in the values that we write on disk to emulate
      * MapInfo's behavior.
      */
     GInt32 nRegionDataSizeMI = m_nRegionDataSize + (2*m_nNumRegSections);
@@ -2033,7 +2130,7 @@ int TABMAPObjCollection::WriteObj(TABMAPObjectBlock *poObjBlock)
     poObjBlock->WriteInt32(m_nCoordBlockPtr);    // pointer into coord block
     poObjBlock->WriteInt32(m_nNumMultiPoints);   // no. points in multi point
     poObjBlock->WriteInt32(nRegionDataSizeMI);   // size of region data inc. section hdrs
-    poObjBlock->WriteInt32(nPolylineDataSizeMI); // size of Mpolyline data inc. sction hdrs
+    poObjBlock->WriteInt32(nPolylineDataSizeMI); // size of Mpolyline data inc. section hdrs
 
     if (nVersion < 800)
     {
diff --git a/ogr/ogrsf_frmts/mitab/mitab_maptoolblock.cpp b/ogr/ogrsf_frmts/mitab/mitab_maptoolblock.cpp
index 521f19f..979fb9c 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_maptoolblock.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_maptoolblock.cpp
@@ -18,16 +18,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -78,7 +78,7 @@ TABMAPToolBlock::TABMAPToolBlock(TABAccess eAccessMode /*= TABRead*/):
     m_nNextToolBlock = m_numDataBytes = 0;
 
     m_numBlocksInChain = 1;  // Current block counts as 1
- 
+
     m_poBlockManagerRef = NULL;
 }
 
@@ -87,23 +87,20 @@ TABMAPToolBlock::TABMAPToolBlock(TABAccess eAccessMode /*= TABRead*/):
  *
  * Destructor.
  **********************************************************************/
-TABMAPToolBlock::~TABMAPToolBlock()
-{
-   
-}
+TABMAPToolBlock::~TABMAPToolBlock() {}
 
 
 /**********************************************************************
  *                   TABMAPToolBlock::EndOfChain()
  *
  * Return TRUE if we reached the end of the last block in the chain
- * TABMAPToolBlocks, or FALSE if there is still data to be read from 
+ * TABMAPToolBlocks, or FALSE if there is still data to be read from
  * this chain.
  **********************************************************************/
 GBool TABMAPToolBlock::EndOfChain()
 {
-   if (m_pabyBuf && 
-       (m_nCurPos < (m_numDataBytes+MAP_TOOL_HEADER_SIZE) || 
+   if (m_pabyBuf &&
+       (m_nCurPos < (m_numDataBytes+MAP_TOOL_HEADER_SIZE) ||
         m_nNextToolBlock > 0 ) )
    {
        return FALSE;  // There is still data to be read.
@@ -118,13 +115,13 @@ GBool TABMAPToolBlock::EndOfChain()
  * Perform some initialization on the block after its binary data has
  * been set or changed (or loaded from a file).
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
 int     TABMAPToolBlock::InitBlockFromData(GByte *pabyBuf,
-                                           int nBlockSize, int nSizeUsed, 
+                                           int nBlockSize, int nSizeUsed,
                                            GBool bMakeCopy /* = TRUE */,
-                                           VSILFILE *fpSrc /* = NULL */, 
+                                           VSILFILE *fpSrc /* = NULL */,
                                            int nOffset /* = 0 */)
 {
     int nStatus;
@@ -134,7 +131,7 @@ int     TABMAPToolBlock::InitBlockFromData(GByte *pabyBuf,
      *----------------------------------------------------------------*/
     nStatus = TABRawBinBlock::InitBlockFromData(pabyBuf, nBlockSize, nSizeUsed,
                                                 bMakeCopy, fpSrc, nOffset);
-    if (nStatus != 0)   
+    if (nStatus != 0)
         return nStatus;
 
     /*-----------------------------------------------------------------
@@ -155,8 +152,26 @@ int     TABMAPToolBlock::InitBlockFromData(GByte *pabyBuf,
      *----------------------------------------------------------------*/
     GotoByteInBlock(0x002);
     m_numDataBytes = ReadInt16();       /* Excluding 8 bytes header */
+    if( m_numDataBytes < 0 || m_numDataBytes + MAP_TOOL_HEADER_SIZE > nBlockSize )
+    {
+        CPLError(CE_Failure, CPLE_FileIO,
+                 "TABMAPToolBlock::InitBlockFromData(): m_numDataBytes=%d incompatible with block size %d",
+                 m_numDataBytes, nBlockSize);
+        CPLFree(m_pabyBuf);
+        m_pabyBuf = NULL;
+        return -1;
+    }
 
     m_nNextToolBlock = ReadInt32();
+    if( m_nNextToolBlock != 0 &&
+        (m_nNextToolBlock / m_nBlockSize) * m_nBlockSize == nOffset )
+    {
+        CPLError(CE_Failure, CPLE_FileIO,
+                 "InitBlockFromData(): self referencing block");
+        CPLFree(m_pabyBuf);
+        m_pabyBuf = NULL;
+        return -1;
+    }
 
     /*-----------------------------------------------------------------
      * The read ptr is now located at the beginning of the data part.
@@ -169,14 +184,14 @@ int     TABMAPToolBlock::InitBlockFromData(GByte *pabyBuf,
 /**********************************************************************
  *                   TABMAPToolBlock::CommitToFile()
  *
- * Commit the current state of the binary block to the file to which 
+ * Commit the current state of the binary block to the file to which
  * it has been previously attached.
  *
  * This method makes sure all values are properly set in the map object
  * block header and then calls TABRawBinBlock::CommitToFile() to do
  * the actual writing to disk.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
 int     TABMAPToolBlock::CommitToFile()
@@ -185,7 +200,7 @@ int     TABMAPToolBlock::CommitToFile()
 
     if ( m_pabyBuf == NULL )
     {
-        CPLError(CE_Failure, CPLE_AssertionFailed, 
+        CPLError(CE_Failure, CPLE_AssertionFailed,
                  "CommitToFile(): Block has not been initialized yet!");
         return -1;
     }
@@ -214,7 +229,7 @@ int     TABMAPToolBlock::CommitToFile()
     if (nStatus == 0)
     {
 #ifdef DEBUG_VERBOSE
-        CPLDebug("MITAB", "Commiting TOOL block to offset %d", m_nFileOffset);
+        CPLDebug("MITAB", "Committing TOOL block to offset %d", m_nFileOffset);
 #endif
         nStatus = TABRawBinBlock::CommitToFile();
     }
@@ -226,26 +241,27 @@ int     TABMAPToolBlock::CommitToFile()
  *                   TABMAPToolBlock::InitNewBlock()
  *
  * Initialize a newly created block so that it knows to which file it
- * is attached, its block size, etc . and then perform any specific 
- * initialization for this block type, including writing a default 
+ * is attached, its block size, etc . and then perform any specific
+ * initialization for this block type, including writing a default
  * block header, etc. and leave the block ready to receive data.
  *
  * This is an alternative to calling ReadFromFile() or InitBlockFromData()
  * that puts the block in a stable state without loading any initial
  * data in it.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
-int     TABMAPToolBlock::InitNewBlock(VSILFILE *fpSrc, int nBlockSize, 
+int     TABMAPToolBlock::InitNewBlock(VSILFILE *fpSrc, int nBlockSize,
                                         int nFileOffset /* = 0*/)
 {
 #ifdef DEBUG_VERBOSE
-    CPLDebug("MITAB", "Instanciating new TOOL block at offset %d", nFileOffset);
+    CPLDebug( "MITAB",
+              "Instantiating new TOOL block at offset %d", nFileOffset);
 #endif
 
     /*-----------------------------------------------------------------
-     * Start with the default initialisation
+     * Start with the default initialization
      *----------------------------------------------------------------*/
     if ( TABRawBinBlock::InitNewBlock(fpSrc, nBlockSize, nFileOffset) != 0)
         return -1;
@@ -254,7 +270,7 @@ int     TABMAPToolBlock::InitNewBlock(VSILFILE *fpSrc, int nBlockSize,
      * And then set default values for the block header.
      *----------------------------------------------------------------*/
     m_nNextToolBlock = 0;
- 
+
     m_numDataBytes = 0;
 
     GotoByteInBlock(0x000);
@@ -286,7 +302,7 @@ void     TABMAPToolBlock::SetNextToolBlock(GInt32 nNextToolBlockAddress)
 /**********************************************************************
  *                   TABMAPToolBlock::SetMAPBlockManagerRef()
  *
- * Pass a reference to the block manager object for the file this 
+ * Pass a reference to the block manager object for the file this
  * block belongs to.  The block manager will be used by this object
  * when it needs to automatically allocate a new block.
  **********************************************************************/
@@ -300,7 +316,7 @@ void TABMAPToolBlock::SetMAPBlockManagerRef(TABBinBlockManager *poBlockMgr)
  *                   TABMAPToolBlock::ReadBytes()
  *
  * Cover function for TABRawBinBlock::ReadBytes() that will automagically
- * load the next coordinate block in the chain before reading the 
+ * load the next coordinate block in the chain before reading the
  * requested bytes if we are at the end of the current block and if
  * m_nNextToolBlock is a valid block.
  *
@@ -310,18 +326,18 @@ void TABMAPToolBlock::SetMAPBlockManagerRef(TABBinBlockManager *poBlockMgr)
  * the user's buffer pointed by pabyDstBuf.
  *
  * Passing pabyDstBuf = NULL will only move the read pointer by the
- * specified number of bytes as if the copy had happened... but it 
+ * specified number of bytes as if the copy had happened... but it
  * won't crash.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
 int     TABMAPToolBlock::ReadBytes(int numBytes, GByte *pabyDstBuf)
 {
     int nStatus;
 
-    if (m_pabyBuf && 
-        m_nCurPos >= (m_numDataBytes+MAP_TOOL_HEADER_SIZE) && 
+    if (m_pabyBuf &&
+        m_nCurPos >= (m_numDataBytes+MAP_TOOL_HEADER_SIZE) &&
         m_nNextToolBlock > 0)
     {
         if ( (nStatus=GotoByteInFile(m_nNextToolBlock)) != 0)
@@ -341,20 +357,20 @@ int     TABMAPToolBlock::ReadBytes(int numBytes, GByte *pabyDstBuf)
  *                   TABMAPToolBlock::WriteBytes()
  *
  * Cover function for TABRawBinBlock::WriteBytes() that will automagically
- * CommitToFile() the current block and create a new one if we are at 
+ * CommitToFile() the current block and create a new one if we are at
  * the end of the current block.
  *
  * Then the control is passed to TABRawBinBlock::WriteBytes() to finish the
  * work.
  *
  * Passing pabySrcBuf = NULL will only move the write pointer by the
- * specified number of bytes as if the copy had happened... but it 
+ * specified number of bytes as if the copy had happened... but it
  * won't crash.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
-int  TABMAPToolBlock::WriteBytes(int nBytesToWrite, GByte *pabySrcBuf)
+int  TABMAPToolBlock::WriteBytes(int nBytesToWrite, const GByte *pabySrcBuf)
 {
     if (m_eAccess == TABWrite && m_poBlockManagerRef &&
         (m_nBlockSize - m_nCurPos) < nBytesToWrite)
@@ -379,10 +395,10 @@ int  TABMAPToolBlock::WriteBytes(int nBytesToWrite, GByte *pabySrcBuf)
  *                   TABMAPToolBlock::CheckAvailableSpace()
  *
  * Check if an object of the specified type can fit in
- * current block.  If it can't fit then force committing current block 
+ * current block.  If it can't fit then force committing current block
  * and allocating a new one.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
 int  TABMAPToolBlock::CheckAvailableSpace(int nToolType)
@@ -447,7 +463,7 @@ void TABMAPToolBlock::Dump(FILE *fpOut /*=NULL*/)
     }
     else
     {
-        fprintf(fpOut,"Tool Block (type %d) at offset %d.\n", 
+        fprintf(fpOut,"Tool Block (type %d) at offset %d.\n",
                                                  m_nBlockType, m_nFileOffset);
         fprintf(fpOut,"  m_numDataBytes        = %d\n", m_numDataBytes);
         fprintf(fpOut,"  m_nNextToolBlock     = %d\n", m_nNextToolBlock);
@@ -457,6 +473,3 @@ void TABMAPToolBlock::Dump(FILE *fpOut /*=NULL*/)
 }
 
 #endif // DEBUG
-
-
-
diff --git a/ogr/ogrsf_frmts/mitab/mitab_middatafile.cpp b/ogr/ogrsf_frmts/mitab/mitab_middatafile.cpp
index 1f856af..fffcdd5 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_middatafile.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_middatafile.cpp
@@ -17,22 +17,23 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
  * $Log: mitab_middatafile.cpp,v $
  * Revision 1.15  2010-10-12 19:02:40  aboudreault
- * Fixed incomplet patch to handle differently indented lines in mif files (gdal #3694)
+ * Fixed incomplete patch to handle differently indented lines in MIF
+ * files (gdal #3694).
  *
  * Revision 1.14  2006-01-27 13:54:06  fwarmerdam
  * fixed memory leak
@@ -71,7 +72,7 @@
  * Add ifdef to remove CPLError if OGR is define
  *
  * Revision 1.2  1999/11/11 01:22:05  stephane
- * Remove DebugFeature call, Point Reading error, add IsValidFeature() to 
+ * Remove DebugFeature call, Point Reading error, add IsValidFeature() to
  * test correctly if we are on a feature
  *
  * Revision 1.1  1999/11/08 04:16:07  stephane
@@ -93,12 +94,14 @@ MIDDATAFile::MIDDATAFile()
     m_szLastRead[0] = '\0';
     m_szSavedLine[0] = '\0';
     m_pszDelimiter = "\t"; // Encom 2003 (was NULL)
-    
+
     m_dfXMultiplier = 1.0;
     m_dfYMultiplier = 1.0;
     m_dfXDisplacement = 0.0;
     m_dfYDisplacement = 0.0;
-
+    m_pszFname = NULL;
+    m_eAccessMode = TABRead;
+    m_bEof = FALSE;
 }
 
 MIDDATAFile::~MIDDATAFile()
@@ -114,7 +117,7 @@ void MIDDATAFile::SaveLine(const char *pszLine)
     }
     else
     {
-        strncpy(m_szSavedLine,pszLine,MIDMAXCHAR);
+        CPLStrlcpy(m_szSavedLine,pszLine,MIDMAXCHAR);
     }
 }
 
@@ -133,12 +136,12 @@ int MIDDATAFile::Open(const char *pszFname, const char *pszAccess)
     /*-----------------------------------------------------------------
      * Validate access mode and make sure we use Text access.
      *----------------------------------------------------------------*/
-    if (EQUALN(pszAccess, "r", 1))
+    if (STARTS_WITH_CI(pszAccess, "r"))
     {
         m_eAccessMode = TABRead;
         pszAccess = "rt";
     }
-    else if (EQUALN(pszAccess, "w", 1))
+    else if (STARTS_WITH_CI(pszAccess, "w"))
     {
         m_eAccessMode = TABWrite;
         pszAccess = "wt";
@@ -167,7 +170,7 @@ int MIDDATAFile::Open(const char *pszFname, const char *pszAccess)
 
 int MIDDATAFile::Rewind()
 {
-    if (m_fp == NULL || m_eAccessMode == TABWrite) 
+    if (m_fp == NULL || m_eAccessMode == TABWrite)
         return -1;
 
     else
@@ -182,7 +185,7 @@ int MIDDATAFile::Close()
 {
     if (m_fp == NULL)
         return 0;
-   
+
     // Close file
     VSIFCloseL(m_fp);
     m_fp = NULL;
@@ -200,10 +203,10 @@ int MIDDATAFile::Close()
 const char *MIDDATAFile::GetLine()
 {
     const char *pszLine;
-    
+
     if (m_eAccessMode == TABRead)
     {
-        
+
         pszLine = CPLReadLineL(m_fp);
 
         if (pszLine == NULL)
@@ -217,7 +220,7 @@ const char *MIDDATAFile::GetLine()
             while(pszLine && (*pszLine == ' ' || (*m_pszDelimiter != '\t' && *pszLine == '\t')) )
                     pszLine++;
 
-            strncpy(m_szLastRead,pszLine,MIDMAXCHAR);
+            CPLStrlcpy(m_szLastRead,pszLine,MIDMAXCHAR);
         }
         //if (pszLine)
         //  printf("%s\n",pszLine);
@@ -259,7 +262,7 @@ void MIDDATAFile::WriteLine(const char *pszFormat,...)
         osStr.vPrintf( pszFormat, args );
         VSIFWriteL( osStr.c_str(), 1, osStr.size(), m_fp);
         va_end(args);
-    } 
+    }
     else
     {
         CPLAssert(FALSE);
@@ -267,7 +270,7 @@ void MIDDATAFile::WriteLine(const char *pszFormat,...)
 }
 
 
-void MIDDATAFile::SetTranslation(double dfXMul,double dfYMul, 
+void MIDDATAFile::SetTranslation(double dfXMul,double dfYMul,
                                  double dfXTran,
                                  double dfYTran)
 {
@@ -293,7 +296,7 @@ GBool MIDDATAFile::IsValidFeature(const char *pszString)
     char **papszToken ;
 
     papszToken = CSLTokenizeString(pszString);
-    
+
     //   printf("%s\n",pszString);
 
     if (CSLCount(papszToken) == 0)
diff --git a/ogr/ogrsf_frmts/mitab/mitab_miffile.cpp b/ogr/ogrsf_frmts/mitab/mitab_miffile.cpp
index 813e7ee..b6f493b 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_miffile.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_miffile.cpp
@@ -20,16 +20,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -41,7 +41,8 @@
  * Fixed crash when trying to get the same mitab mif feature twice (GDAL #3765)
  *
  * Revision 1.56  2010-10-12 19:02:40  aboudreault
- * Fixed incomplet patch to handle differently indented lines in mif files (gdal #3694)
+ * Fixed incomplete patch to handle differently indented lines in MIF
+ * files (gdal #3694).
  *
  * Revision 1.55  2010-10-08 18:50:52  aboudreault
  * Fixed handle differently indented lines in mif files. (GDAL bug #3694)
@@ -53,7 +54,8 @@
  * Fixed MIF driver: doesn't create a layer defn at layer creation (bug 2180)
  *
  * Revision 1.52  2010-01-07 20:39:12  aboudreault
- * Added support to handle duplicate field names, Added validation to check if a field name start with a number (bug 2141)
+ * Added support to handle duplicate field names, Added validation to check if
+ * a field name start with a number (bug 2141).
  *
  * Revision 1.51  2009-07-27 14:08:41  dmorissette
  * Fixed dataset version check in AddFieldNative for type TABFDateTime
@@ -100,7 +102,7 @@
  * Added support for reading collections from MIF files (bug 1126)
  *
  * Revision 1.38  2004/02/27 21:04:14  fwarmerdam
- * dont write MIF header if file is readonly - gdal bugzilla 509
+ * Do not write MIF header if file is readonly - gdal bugzilla 509
  *
  * Revision 1.37  2003/12/19 07:54:50  fwarmerdam
  * write mif header on close if not already written out
@@ -212,7 +214,7 @@ MIFFile::MIFFile()
     m_nVersion = 300;
 
     // Tab is default delimiter in MIF spec if not explicitly specified.  Use
-    // that by default for read mode. In write mode, we will use "," as 
+    // that by default for read mode. In write mode, we will use "," as
     // delimiter since it's more common than tab (we do this in Open())
     m_pszDelimiter = CPLStrdup("\t");
 
@@ -240,13 +242,18 @@ MIFFile::MIFFile()
     m_nFeatureCount = 0;
     m_nWriteFeatureId = -1;
     m_poCurFeature = NULL;
-   
+
     m_bPreParsed = FALSE;
     m_nAttribut = 0;
     m_bHeaderWrote = FALSE;
     m_nPoints = m_nLines = m_nRegions = m_nTexts = 0;
 
     m_bExtentsSet = FALSE;
+    m_eAccessMode = TABRead;
+    m_dXMin = 0;
+    m_dYMin = 0;
+    m_dXMax = 0;
+    m_dYMax = 0;
 }
 
 /**********************************************************************
@@ -269,7 +276,7 @@ int MIFFile::Open(const char *pszFname, TABAccess eAccess,
 {
     char *pszTmpFname = NULL;
     int nFnameLen = 0;
-    
+
     CPLErrorReset();
 
     if (m_poMIFFile)
@@ -310,10 +317,10 @@ int MIFFile::Open(const char *pszFname, TABAccess eAccess,
     }
 
     /*-----------------------------------------------------------------
-     * Make sure filename has a .MIF or .MID extension... 
+     * Make sure filename has a .MIF or .MID extension...
      *----------------------------------------------------------------*/
     m_pszFname = CPLStrdup(pszFname);
-    nFnameLen = strlen(m_pszFname);
+    nFnameLen = static_cast<int>(strlen(m_pszFname));
     if (nFnameLen > 4 && (strcmp(m_pszFname+nFnameLen-4, ".MID")==0 ||
                      strcmp(m_pszFname+nFnameLen-4, ".MIF")==0 ) )
         strcpy(m_pszFname+nFnameLen-4, ".MIF");
@@ -389,7 +396,7 @@ int MIFFile::Open(const char *pszFname, TABAccess eAccess,
         *----------------------------------------------------------------*/
         if (nFnameLen > 4 && strcmp(pszTmpFname+nFnameLen-4, ".MIF")==0)
             strcpy(pszTmpFname+nFnameLen-4, ".MID");
-        else 
+        else
             strcpy(pszTmpFname+nFnameLen-4, ".mid");
 
 #ifndef _WIN32
@@ -492,7 +499,7 @@ int MIFFile::Open(const char *pszFname, TABAccess eAccess,
  *                   MIFFile::ParseMIFHeader()
  *
  * Scan the header of a MIF file, and store any useful information into
- * class members.  The main piece of information being the fields 
+ * class members.  The main piece of information being the fields
  * definition that we use to build the OGRFeatureDefn for this file.
  *
  * This private method should be used only during the Open() call.
@@ -500,16 +507,15 @@ int MIFFile::Open(const char *pszFname, TABAccess eAccess,
  * Returns 0 on success, -1 on error.
  **********************************************************************/
 int MIFFile::ParseMIFHeader(int* pbIsEmpty)
-{  
+{
     GBool  bColumns = FALSE, bAllColumnsRead =  FALSE;
     int    nColumns = 0;
     GBool  bCoordSys = FALSE;
     char  *pszTmp;
-            
-    
+
     const char *pszLine;
     char **papszToken;
-    
+
     *pbIsEmpty = FALSE;
 
     char *pszFeatureClassName = TABGetBasename(m_pszFname);
@@ -518,27 +524,27 @@ int MIFFile::ParseMIFHeader(int* pbIsEmpty)
     // Ref count defaults to 0... set it to 1
     m_poDefn->Reference();
 
-    
+
     if (m_eAccessMode != TABRead)
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "ParseMIDFile() can be used only with Read access.");
         return -1;
     }
-    
+
 
     /*-----------------------------------------------------------------
      * Parse header until we find the "Data" line
      *----------------------------------------------------------------*/
     while (((pszLine = m_poMIFFile->GetLine()) != NULL) &&
-           ((bAllColumnsRead == FALSE) || !EQUALN(pszLine,"Data",4)))
-    {       
+           ((bAllColumnsRead == FALSE) || !STARTS_WITH_CI(pszLine, "Data")))
+    {
         if (bColumns == TRUE && nColumns >0)
         {
             if (AddFields(pszLine) == 0)
             {
                 nColumns--;
-                if (nColumns == 0) 
+                if (nColumns == 0)
                 {
                   bAllColumnsRead = TRUE;
                   bColumns = FALSE;
@@ -549,55 +555,55 @@ int MIFFile::ParseMIFHeader(int* pbIsEmpty)
                 bColumns = FALSE;
             }
         }
-        else if (EQUALN(pszLine,"VERSION",7))
+        else if (STARTS_WITH_CI(pszLine, "VERSION"))
         {
-            papszToken = CSLTokenizeStringComplex(pszLine," ()\t",TRUE,FALSE); 
+            papszToken = CSLTokenizeStringComplex(pszLine," ()\t",TRUE,FALSE);
             bColumns = FALSE; bCoordSys = FALSE;
             if (CSLCount(papszToken)  == 2)
               m_nVersion = atoi(papszToken[1]);
 
             CSLDestroy(papszToken);
-        
+
         }
-        else if (EQUALN(pszLine,"CHARSET",7))
+        else if (STARTS_WITH_CI(pszLine, "CHARSET"))
         {
-            papszToken = CSLTokenizeStringComplex(pszLine," ()\t",TRUE,FALSE); 
+            papszToken = CSLTokenizeStringComplex(pszLine," ()\t",TRUE,FALSE);
             bColumns = FALSE; bCoordSys = FALSE;
-          
+
             if (CSLCount(papszToken)  == 2)
             {
                 CPLFree(m_pszCharset);
                 m_pszCharset = CPLStrdup(papszToken[1]);
             }
             CSLDestroy(papszToken);
-        
+
         }
-        else if (EQUALN(pszLine,"DELIMITER",9))
+        else if (STARTS_WITH_CI(pszLine, "DELIMITER"))
         {
-            papszToken = CSLTokenizeStringComplex(pszLine," ()\t",TRUE,FALSE); 
+            papszToken = CSLTokenizeStringComplex(pszLine," ()\t",TRUE,FALSE);
              bColumns = FALSE; bCoordSys = FALSE;
-          
+
            if (CSLCount(papszToken)  == 2)
            {
                CPLFree(m_pszDelimiter);
-               m_pszDelimiter = CPLStrdup(papszToken[1]);    
+               m_pszDelimiter = CPLStrdup(papszToken[1]);
            }
           CSLDestroy(papszToken);
-        
+
         }
-        else if (EQUALN(pszLine,"UNIQUE",6))
+        else if (STARTS_WITH_CI(pszLine, "UNIQUE"))
         {
             bColumns = FALSE; bCoordSys = FALSE;
-          
+
             m_pszUnique = CPLStrdup(pszLine + 6);
         }
-        else if (EQUALN(pszLine,"INDEX",5))
+        else if (STARTS_WITH_CI(pszLine, "INDEX"))
         {
             bColumns = FALSE; bCoordSys = FALSE;
-          
+
             m_pszIndex = CPLStrdup(pszLine + 5);
         }
-        else if (EQUALN(pszLine,"COORDSYS",8) )
+        else if (STARTS_WITH_CI(pszLine, "COORDSYS") )
         {
             bCoordSys = TRUE;
             m_pszCoordSys = CPLStrdup(pszLine + 9);
@@ -617,18 +623,18 @@ int MIFFile::ParseMIFHeader(int* pbIsEmpty)
             }
             CSLDestroy( papszFields );
         }
-        else if (EQUALN(pszLine,"TRANSFORM",9))
+        else if (STARTS_WITH_CI(pszLine, "TRANSFORM"))
         {
-            papszToken = CSLTokenizeStringComplex(pszLine," ,\t",TRUE,FALSE); 
+            papszToken = CSLTokenizeStringComplex(pszLine," ,\t",TRUE,FALSE);
             bColumns = FALSE; bCoordSys = FALSE;
-          
+
             if (CSLCount(papszToken) == 5)
             {
                 m_dfXMultiplier   = CPLAtof(papszToken[1]);
                 m_dfYMultiplier   = CPLAtof(papszToken[2]);
                 m_dfXDisplacement = CPLAtof(papszToken[3]);
                 m_dfYDisplacement = CPLAtof(papszToken[4]);
-                
+
                 if (m_dfXMultiplier == 0.0)
                   m_dfXMultiplier = 1.0;
                 if (m_dfYMultiplier == 0.0)
@@ -636,9 +642,9 @@ int MIFFile::ParseMIFHeader(int* pbIsEmpty)
             }
             CSLDestroy(papszToken);
         }
-        else if (EQUALN(pszLine,"COLUMNS",7))
+        else if (STARTS_WITH_CI(pszLine, "COLUMNS"))
         {
-            papszToken = CSLTokenizeStringComplex(pszLine," ()\t",TRUE,FALSE); 
+            papszToken = CSLTokenizeStringComplex(pszLine," ()\t",TRUE,FALSE);
             bCoordSys = FALSE;
             bColumns = TRUE;
             if (CSLCount(papszToken) == 2)
@@ -650,7 +656,7 @@ int MIFFile::ParseMIFHeader(int* pbIsEmpty)
                     // Permit to 0 columns
                     bAllColumnsRead = TRUE;
                     bColumns = FALSE;
-                }            
+                }
             }
             else
             {
@@ -670,8 +676,8 @@ int MIFFile::ParseMIFHeader(int* pbIsEmpty)
         }
 
     }
-    
-    if (!bAllColumnsRead) 
+
+    if (!bAllColumnsRead)
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "COLUMNS keyword not found or invalid number of columns read in %s.  File may be corrupt.",
@@ -679,22 +685,22 @@ int MIFFile::ParseMIFHeader(int* pbIsEmpty)
         return -1;
     }
 
-    if ((pszLine = m_poMIFFile->GetLastLine()) == NULL || 
-        EQUALN(m_poMIFFile->GetLastLine(),"DATA",4) == FALSE)
+    if ((pszLine = m_poMIFFile->GetLastLine()) == NULL ||
+        STARTS_WITH_CI(m_poMIFFile->GetLastLine(), "DATA") == FALSE)
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "DATA keyword not found in %s.  File may be corrupt.",
                  m_pszFname);
         return -1;
     }
-    
+
     /*-----------------------------------------------------------------
      * Move pointer to first line of first object
      *----------------------------------------------------------------*/
-    while (((pszLine = m_poMIFFile->GetLine()) != NULL) && 
+    while (((pszLine = m_poMIFFile->GetLine()) != NULL) &&
            m_poMIFFile->IsValidFeature(pszLine) == FALSE)
         ;
-    
+
     *pbIsEmpty = (pszLine == NULL);
 
     /*-----------------------------------------------------------------
@@ -738,7 +744,7 @@ int  MIFFile::AddFields(const char *pszLine)
     int nStatus = 0,numTok;
 
     CPLAssert(m_bHeaderWrote == FALSE);
-    papszToken = CSLTokenizeStringComplex(pszLine," (,)\t",TRUE,FALSE); 
+    papszToken = CSLTokenizeStringComplex(pszLine," (,)\t",TRUE,FALSE);
     numTok = CSLCount(papszToken);
 
     if (numTok >= 3 && EQUAL(papszToken[1], "char"))
@@ -827,9 +833,9 @@ int  MIFFile::AddFields(const char *pszLine)
          *------------------------------------------------*/
         nStatus = AddFieldNative(papszToken[0], TABFLogical);
     }
-    else 
+    else
       nStatus = -1; // Unrecognized field type or line corrupt
-    
+
     CSLDestroy(papszToken);
     papszToken = NULL;
 
@@ -839,7 +845,7 @@ int  MIFFile::AddFields(const char *pszLine)
                  "Failed to parse field definition in file %s", m_pszFname);
         return -1;
     }
-    
+
     return 0;
 }
 
@@ -849,7 +855,7 @@ int  MIFFile::AddFields(const char *pszLine)
 
 GIntBig MIFFile::GetFeatureCount (int bForce)
 {
-    
+
     if( m_poFilterGeom != NULL || m_poAttrQuery != NULL )
         return OGRLayer::GetFeatureCount( bForce );
     else
@@ -870,13 +876,13 @@ GIntBig MIFFile::GetFeatureCount (int bForce)
 
 void MIFFile::ResetReading()
 
-{   
+{
     const char *pszLine;
 
     m_poMIFFile->Rewind();
 
     while ((pszLine = m_poMIFFile->GetLine()) != NULL)
-      if (EQUALN(pszLine,"DATA",4))
+      if (STARTS_WITH_CI(pszLine, "DATA"))
         break;
 
     while ((pszLine = m_poMIFFile->GetLine()) != NULL)
@@ -890,7 +896,7 @@ void MIFFile::ResetReading()
         m_poMIDFile->Rewind();
         m_poMIDFile->GetLine();
     }
-    
+
     // We're positioned on first feature.  Feature Ids start at 1.
     if (m_poCurFeature)
     {
@@ -910,7 +916,7 @@ void MIFFile::PreParseFile()
 {
     char **papszToken = NULL;
     const char *pszLine;
-    
+
     GBool bPLine = FALSE;
     GBool bText = FALSE;
 
@@ -920,7 +926,7 @@ void MIFFile::PreParseFile()
     m_poMIFFile->Rewind();
 
     while ((pszLine = m_poMIFFile->GetLine()) != NULL)
-      if (EQUALN(pszLine,"DATA",4))
+      if (STARTS_WITH_CI(pszLine, "DATA"))
         break;
 
     m_nPoints = m_nLines = m_nRegions = m_nTexts = 0;
@@ -937,7 +943,7 @@ void MIFFile::PreParseFile()
         CSLDestroy(papszToken);
         papszToken = CSLTokenizeString2(pszLine, " \t", CSLT_HONOURSTRINGS);
 
-        if (EQUALN(pszLine,"POINT",5))
+        if (STARTS_WITH_CI(pszLine, "POINT"))
         {
             m_nPoints++;
             if (CSLCount(papszToken) == 3)
@@ -945,34 +951,34 @@ void MIFFile::PreParseFile()
                 UpdateExtents(m_poMIFFile->GetXTrans(CPLAtof(papszToken[1])),
                              m_poMIFFile->GetYTrans(CPLAtof(papszToken[2])));
             }
-              
+
         }
-        else if (EQUALN(pszLine,"LINE",4) ||
-                 EQUALN(pszLine,"RECT",4) ||
-                 EQUALN(pszLine,"ROUNDRECT",9) ||
-                 EQUALN(pszLine,"ARC",3) ||
-                 EQUALN(pszLine,"ELLIPSE",7))
+        else if (STARTS_WITH_CI(pszLine, "LINE") ||
+                 STARTS_WITH_CI(pszLine, "RECT") ||
+                 STARTS_WITH_CI(pszLine, "ROUNDRECT") ||
+                 STARTS_WITH_CI(pszLine, "ARC") ||
+                 STARTS_WITH_CI(pszLine, "ELLIPSE"))
         {
             if (CSLCount(papszToken) == 5)
             {
                 m_nLines++;
-                UpdateExtents(m_poMIFFile->GetXTrans(CPLAtof(papszToken[1])), 
+                UpdateExtents(m_poMIFFile->GetXTrans(CPLAtof(papszToken[1])),
                              m_poMIFFile->GetYTrans(CPLAtof(papszToken[2])));
-                UpdateExtents(m_poMIFFile->GetXTrans(CPLAtof(papszToken[3])), 
+                UpdateExtents(m_poMIFFile->GetXTrans(CPLAtof(papszToken[3])),
                              m_poMIFFile->GetYTrans(CPLAtof(papszToken[4])));
             }
         }
-        else if (EQUALN(pszLine,"REGION",6) )
+        else if (STARTS_WITH_CI(pszLine, "REGION") )
         {
             m_nRegions++;
             bPLine = TRUE;
         }
-        else if( EQUALN(pszLine,"PLINE",5))
+        else if( STARTS_WITH_CI(pszLine, "PLINE"))
         {
             m_nLines++;
             bPLine = TRUE;
         }
-        else if (EQUALN(pszLine,"TEXT",4)) 
+        else if (STARTS_WITH_CI(pszLine, "TEXT"))
         {
             m_nTexts++;
             bText = TRUE;
@@ -995,17 +1001,17 @@ void MIFFile::PreParseFile()
                              m_poMIFFile->GetYTrans(CPLAtof(papszToken[1])));
                 UpdateExtents(m_poMIFFile->GetXTrans(CPLAtof(papszToken[2])),
                              m_poMIFFile->GetYTrans(CPLAtof(papszToken[3])));
-            } 
+            }
         }
-        
+
       }
 
     CSLDestroy(papszToken);
-    
+
     m_poMIFFile->Rewind();
 
     while ((pszLine = m_poMIFFile->GetLine()) != NULL)
-      if (EQUALN(pszLine,"DATA",4))
+      if (STARTS_WITH_CI(pszLine, "DATA"))
         break;
 
     while ((pszLine = m_poMIFFile->GetLine()) != NULL)
@@ -1019,7 +1025,7 @@ void MIFFile::PreParseFile()
         m_poMIDFile->Rewind();
         m_poMIDFile->GetLine();
     }
- 
+
     m_bPreParsed = TRUE;
 
 }
@@ -1096,26 +1102,26 @@ int MIFFile::WriteMIFHeader()
     {
         m_poMIFFile->WriteLine("CoordSys %s "
                                "Bounds (%.15g, %.15g) (%.15g, %.15g)\n",
-                               m_pszCoordSys, 
+                               m_pszCoordSys,
                                m_dXMin, m_dYMin, m_dXMax, m_dYMax);
     }
     else if (m_pszCoordSys)
     {
         m_poMIFFile->WriteLine("CoordSys %s\n",m_pszCoordSys);
     }
-    
+
     /*-----------------------------------------------------------------
      * Column definitions
      *----------------------------------------------------------------*/
     CPLAssert(m_paeFieldType);
 
     m_poMIFFile->WriteLine("Columns %d\n", m_poDefn->GetFieldCount());
-        
+
     for(iField=0; iField<m_poDefn->GetFieldCount(); iField++)
     {
         OGRFieldDefn *poFieldDefn;
         poFieldDefn = m_poDefn->GetFieldDefn(iField);
-        
+
         switch(m_paeFieldType[iField])
         {
           case TABFInteger:
@@ -1128,7 +1134,7 @@ int MIFFile::WriteMIFHeader()
             break;
           case TABFFloat:
             m_poMIFFile->WriteLine("  %s Float\n",
-                                   poFieldDefn->GetNameRef());    
+                                   poFieldDefn->GetNameRef());
             break;
           case TABFDecimal:
             m_poMIFFile->WriteLine("  %s Decimal(%d,%d)\n",
@@ -1164,7 +1170,7 @@ int MIFFile::WriteMIFHeader()
      * Ready to write objects
      *----------------------------------------------------------------*/
     m_poMIFFile->WriteLine("Data\n\n");
-   
+
     return 0;
 }
 
@@ -1178,10 +1184,10 @@ int MIFFile::WriteMIFHeader()
 int MIFFile::Close()
 {
     /* flush .mif header if not already written */
-    if ( m_poDefn != NULL && m_bHeaderWrote == FALSE 
+    if ( m_poDefn != NULL && m_bHeaderWrote == FALSE
          && m_eAccessMode != TABRead )
     {
-        WriteMIFHeader();     
+        WriteMIFHeader();
     }
 
     if (m_poMIDFile)
@@ -1205,13 +1211,13 @@ int MIFFile::Close()
     }
 
     /*-----------------------------------------------------------------
-     * Note: we have to check the reference count before deleting 
+     * Note: we have to check the reference count before deleting
      * m_poSpatialRef and m_poDefn
      *----------------------------------------------------------------*/
     if (m_poDefn && m_poDefn->Dereference() == 0)
         delete m_poDefn;
     m_poDefn = NULL;
-    
+
     if (m_poSpatialRef && m_poSpatialRef->Dereference() == 0)
         delete m_poSpatialRef;
     m_poSpatialRef = NULL;
@@ -1244,7 +1250,7 @@ int MIFFile::Close()
     m_nCurFeatureId = 0;
     m_nPreloadedId = 0;
     m_nFeatureCount =0;
-   
+
     m_bBoundsSet = FALSE;
 
     return 0;
@@ -1276,7 +1282,7 @@ GIntBig MIFFile::GetNextFeatureId(GIntBig nPrevId)
 /**********************************************************************
  *                   MIFFile::GotoFeature()
  *
- * Private method to move MIF and MID pointers ready to read specified 
+ * Private method to move MIF and MID pointers ready to read specified
  * feature.  Note that Feature Ids start at 1.
  *
  * Returns 0 on success, -1 on error (likely request for invalid feature id)
@@ -1333,8 +1339,8 @@ GBool MIFFile::NextFeature()
  *
  * Fill and return a TABFeature object for the specified feature id.
  *
- * The retruned pointer is a reference to an object owned and maintained
- * by this MIFFile object.  It should not be altered or freed by the 
+ * The returned pointer is a reference to an object owned and maintained
+ * by this MIFFile object.  It should not be altered or freed by the
  * caller and its contents is guaranteed to be valid only until the next
  * call to GetFeatureRef() or Close().
  *
@@ -1352,7 +1358,7 @@ TABFeature *MIFFile::GetFeatureRef(GIntBig nFeatureId)
                  "GetFeatureRef() can be used only with Read access.");
         return NULL;
     }
-    
+
     /*-----------------------------------------------------------------
      * Make sure file is opened and Validate feature id by positioning
      * the read pointers for the .MAP and .DAT files to this feature id.
@@ -1364,10 +1370,10 @@ TABFeature *MIFFile::GetFeatureRef(GIntBig nFeatureId)
         return NULL;
     }
 
-    if ( (GIntBig)(int)nFeatureId != nFeatureId || GotoFeature((int)nFeatureId)!= 0 )
+    if ( !CPL_INT64_FITS_ON_INT32(nFeatureId) || GotoFeature((int)nFeatureId)!= 0 )
     {
         CPLError(CE_Failure, CPLE_IllegalArg,
-                 "GetFeatureRef() failed: invalid feature id " CPL_FRMT_GIB, 
+                 "GetFeatureRef() failed: invalid feature id " CPL_FRMT_GIB,
                  nFeatureId);
         return NULL;
     }
@@ -1385,16 +1391,16 @@ TABFeature *MIFFile::GetFeatureRef(GIntBig nFeatureId)
 
         m_nCurFeatureId = m_nPreloadedId;
 
-        if (EQUALN(pszLine,"NONE",4))
+        if (STARTS_WITH_CI(pszLine, "NONE"))
         {
             m_poCurFeature = new TABFeature(m_poDefn);
         }
-        else if (EQUALN(pszLine,"POINT",5))
+        else if (STARTS_WITH_CI(pszLine, "POINT"))
         {
             // Special case, we need to know two lines to decide the type
             char **papszToken;
             papszToken = CSLTokenizeString2(pszLine, " \t", CSLT_HONOURSTRINGS);
-            
+
             if (CSLCount(papszToken) !=3)
             {
                 CSLDestroy(papszToken);
@@ -1403,7 +1409,7 @@ TABFeature *MIFFile::GetFeatureRef(GIntBig nFeatureId)
                          pszLine);
                 return NULL;
             }
-            
+
             m_poMIFFile->SaveLine(pszLine);
 
             if ((pszLine = m_poMIFFile->GetLine()) != NULL)
@@ -1411,7 +1417,7 @@ TABFeature *MIFFile::GetFeatureRef(GIntBig nFeatureId)
                 CSLDestroy(papszToken);
                 papszToken = CSLTokenizeStringComplex(pszLine," ,()\t",
                                                       TRUE,FALSE);
-                if (CSLCount(papszToken)> 0 &&EQUALN(papszToken[0],"SYMBOL",6))
+                if (CSLCount(papszToken)> 0 &&STARTS_WITH_CI(papszToken[0], "SYMBOL"))
                 {
                     switch (CSLCount(papszToken))
                     {
@@ -1443,39 +1449,39 @@ TABFeature *MIFFile::GetFeatureRef(GIntBig nFeatureId)
                 m_poCurFeature = new TABPoint(m_poDefn);
             }
         }
-        else if (EQUALN(pszLine,"LINE",4) ||
-                 EQUALN(pszLine,"PLINE",5))
+        else if (STARTS_WITH_CI(pszLine, "LINE") ||
+                 STARTS_WITH_CI(pszLine, "PLINE"))
         {
             m_poCurFeature = new TABPolyline(m_poDefn);
         }
-        else if (EQUALN(pszLine,"REGION",6))
+        else if (STARTS_WITH_CI(pszLine, "REGION"))
         {
             m_poCurFeature = new TABRegion(m_poDefn);
-        }  
-        else if (EQUALN(pszLine,"ARC",3))
-        { 
+        }
+        else if (STARTS_WITH_CI(pszLine, "ARC"))
+        {
             m_poCurFeature = new TABArc(m_poDefn);
         }
-        else if (EQUALN(pszLine,"TEXT",4))
+        else if (STARTS_WITH_CI(pszLine, "TEXT"))
         {
             m_poCurFeature = new TABText(m_poDefn);
         }
-        else if (EQUALN(pszLine,"RECT",4) ||
-                 EQUALN(pszLine,"ROUNDRECT",9))
+        else if (STARTS_WITH_CI(pszLine, "RECT") ||
+                 STARTS_WITH_CI(pszLine, "ROUNDRECT"))
         {
             m_poCurFeature = new TABRectangle(m_poDefn);
         }
-        else if (EQUALN(pszLine,"ELLIPSE",7))
+        else if (STARTS_WITH_CI(pszLine, "ELLIPSE"))
         {
-            m_poCurFeature = new TABEllipse(m_poDefn);       
+            m_poCurFeature = new TABEllipse(m_poDefn);
         }
-        else if (EQUALN(pszLine,"MULTIPOINT",10))
+        else if (STARTS_WITH_CI(pszLine, "MULTIPOINT"))
         {
-            m_poCurFeature = new TABMultiPoint(m_poDefn);       
+            m_poCurFeature = new TABMultiPoint(m_poDefn);
         }
-        else if (EQUALN(pszLine,"COLLECTION",10))
+        else if (STARTS_WITH_CI(pszLine, "COLLECTION"))
         {
-            m_poCurFeature = new TABCollection(m_poDefn);       
+            m_poCurFeature = new TABCollection(m_poDefn);
         }
         else
         {
@@ -1483,7 +1489,7 @@ TABFeature *MIFFile::GetFeatureRef(GIntBig nFeatureId)
                CPLError(CE_Failure, CPLE_NotSupported,
                    "Error during reading, unknown type %s.",
                      pszLine);
-        
+
             //m_poCurFeature = new TABDebugFeature(m_poDefn);
             return NULL;
         }
@@ -1501,12 +1507,12 @@ TABFeature *MIFFile::GetFeatureRef(GIntBig nFeatureId)
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "Error during reading Record.");
-        
+
         delete m_poCurFeature;
         m_poCurFeature = NULL;
         return NULL;
     }
-    
+
     /*-----------------------------------------------------------------
      * Read geometry from the .MAP file
      * MoveToObjId() has already been called above...
@@ -1515,13 +1521,13 @@ TABFeature *MIFFile::GetFeatureRef(GIntBig nFeatureId)
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "Error during reading Geometry.");
-        
+
         delete m_poCurFeature;
         m_poCurFeature = NULL;
         return NULL;
     }
 
-    /* If the feature geometry is Text, and the value is empty(""), transform 
+    /* If the feature geometry is Text, and the value is empty(""), transform
        it to a geometry none */
     if (m_poCurFeature->GetFeatureClass() == TABFCText)
     {
@@ -1540,14 +1546,14 @@ TABFeature *MIFFile::GetFeatureRef(GIntBig nFeatureId)
     }
 
     /*---------------------------------------------------------------------
-     * The act of reading the geometry causes the first line of the    
+     * The act of reading the geometry causes the first line of the
      * next object to be preloaded.  Set the preloaded id appropriately.
      *--------------------------------------------------------------------- */
     if( m_poMIFFile->GetLastLine() != NULL )
         m_nPreloadedId++;
     else
         m_nPreloadedId = 0;
-   
+
     /* Update the Current Feature ID */
     m_poCurFeature->SetFID(m_nCurFeatureId);
 
@@ -1557,7 +1563,7 @@ TABFeature *MIFFile::GetFeatureRef(GIntBig nFeatureId)
 /**********************************************************************
  *                   MIFFile::CreateFeature()
  *
- * Write a new feature to this dataset. The passed in feature is updated 
+ * Write a new feature to this dataset. The passed in feature is updated
  * with the new feature id.
  *
  * Returns OGRERR_NONE on success, or an appropriate OGRERR_ code if an
@@ -1594,7 +1600,7 @@ OGRErr MIFFile::CreateFeature(TABFeature *poFeature)
         if (m_poDefn == NULL)
             SetFeatureDefn(poFeature->GetDefnRef(), NULL);
 
-         WriteMIFHeader();     
+         WriteMIFHeader();
          nFeatureId = 1;
     }
     else
@@ -1656,7 +1662,7 @@ OGRFeatureDefn *MIFFile::GetLayerDefn()
  * All features that will be written to this dataset must share this same
  * OGRFeatureDefn.
  *
- * This function will use poFeatureDefn to create a local copy that 
+ * This function will use poFeatureDefn to create a local copy that
  * will be used to build the .MID file, etc.
  *
  * Returns 0 on success, -1 on error.
@@ -1739,9 +1745,9 @@ int MIFFile::SetFeatureDefn(OGRFeatureDefn *poFeatureDefn,
 /**********************************************************************
  *                   MIFFile::AddFieldNative()
  *
- * Create a new field using a native mapinfo data type... this is an 
+ * Create a new field using a native mapinfo data type... this is an
  * alternative to defining fields through the OGR interface.
- * This function should be called after creating a new dataset, but before 
+ * This function should be called after creating a new dataset, but before
  * writing the first feature.
  *
  * This function will build/update the OGRFeatureDefn that will have to be
@@ -1821,20 +1827,20 @@ int MIFFile::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
     strncpy(szNewFieldName, pszCleanName, 31);
     szNewFieldName[31] = '\0';
 
-    while (m_poDefn->GetFieldIndex(szNewFieldName) >= 0 && nRenameNum < 10) 
-      sprintf( szNewFieldName, "%.29s_%.1d", pszCleanName, nRenameNum++ );
+    while (m_poDefn->GetFieldIndex(szNewFieldName) >= 0 && nRenameNum < 10)
+      snprintf( szNewFieldName, sizeof(szNewFieldName), "%.29s_%.1d", pszCleanName, nRenameNum++ );
 
-    while (m_poDefn->GetFieldIndex(szNewFieldName) >= 0 && nRenameNum < 100) 
-      sprintf( szNewFieldName, "%.29s%.2d", pszCleanName, nRenameNum++ );
+    while (m_poDefn->GetFieldIndex(szNewFieldName) >= 0 && nRenameNum < 100)
+      snprintf( szNewFieldName, sizeof(szNewFieldName), "%.29s%.2d", pszCleanName, nRenameNum++ );
 
     if (m_poDefn->GetFieldIndex(szNewFieldName) >= 0)
     {
-      CPLError( CE_Failure, CPLE_NotSupported, 
-                "Too many field names like '%s' when truncated to 31 letters " 
+      CPLError( CE_Failure, CPLE_NotSupported,
+                "Too many field names like '%s' when truncated to 31 letters "
                 "for MapInfo format.", pszCleanName );
     }
 
-    if( !EQUAL(pszCleanName,szNewFieldName) ) 
+    if( !EQUAL(pszCleanName,szNewFieldName) )
     {
       CPLError( CE_Warning, CPLE_NotSupported,
                 "Normalized/laundered field name: '%s' to '%s'",
@@ -1889,7 +1895,7 @@ int MIFFile::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
         /*-------------------------------------------------
          * DATE type (V450, returned as a string: "DD/MM/YYYY" or "YYYYMMDD")
          *------------------------------------------------*/
-        poFieldDefn = new OGRFieldDefn(szNewFieldName, 
+        poFieldDefn = new OGRFieldDefn(szNewFieldName,
 #ifdef MITAB_USE_OFTDATETIME
                                                    OFTDate);
 #else
@@ -1902,7 +1908,7 @@ int MIFFile::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
         /*-------------------------------------------------
          * TIME type (v900, returned as a string: "HH:MM:SS" or "HHMMSSmmm")
          *------------------------------------------------*/
-        poFieldDefn = new OGRFieldDefn(szNewFieldName, 
+        poFieldDefn = new OGRFieldDefn(szNewFieldName,
 #ifdef MITAB_USE_OFTDATETIME
                                                    OFTTime);
 #else
@@ -1916,7 +1922,7 @@ int MIFFile::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
          * DATETIME type (v900, returned as a string: "DD/MM/YYYY HH:MM:SS",
          * "YYYY/MM/DD HH:MM:SS" or "YYYYMMDDHHMMSSmmm")
          *------------------------------------------------*/
-        poFieldDefn = new OGRFieldDefn(szNewFieldName, 
+        poFieldDefn = new OGRFieldDefn(szNewFieldName,
 #ifdef MITAB_USE_OFTDATETIME
                                                    OFTDateTime);
 #else
@@ -1939,7 +1945,7 @@ int MIFFile::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
     }
 
     /*-----------------------------------------------------
-     * Add the FieldDefn to the FeatureDefn 
+     * Add the FieldDefn to the FeatureDefn
      *----------------------------------------------------*/
     m_poDefn->AddFieldDefn(poFieldDefn);
     delete poFieldDefn;
@@ -2062,7 +2068,7 @@ int MIFFile::SetMIFCoordSys(const char * pszMIFCoordSys)
     int         iBounds;
 
     // Extract the word 'COORDSYS' if present
-    if (EQUALN(pszMIFCoordSys,"COORDSYS",8) )
+    if (STARTS_WITH_CI(pszMIFCoordSys, "COORDSYS") )
     {
         pszCoordSys = CPLStrdup(pszMIFCoordSys + 9);
     }
@@ -2115,7 +2121,7 @@ OGRSpatialReference *MIFFile::GetSpatialRef()
 /**********************************************************************
  *                   MIFFile::UpdateExtents()
  *
- * Private Methode used to update the dataset extents
+ * Private method used to update the dataset extents.
  **********************************************************************/
 void MIFFile::UpdateExtents(double dfX, double dfY)
 {
@@ -2148,7 +2154,7 @@ void MIFFile::UpdateExtents(double dfX, double dfY)
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int MIFFile::SetBounds(double dXMin, double dYMin, 
+int MIFFile::SetBounds(double dXMin, double dYMin,
                        double dXMax, double dYMax)
 {
     if (m_eAccessMode != TABWrite)
@@ -2163,8 +2169,8 @@ int MIFFile::SetBounds(double dXMin, double dYMin,
     m_dYMin = dYMin;
     m_dYMax = dYMax;
     m_bBoundsSet = TRUE;
-    
-    return 0; 
+
+    return 0;
 }
 
 
@@ -2214,11 +2220,10 @@ int MIFFile::GetFeatureCountByType(int &numPoints, int &numLines,
  * Returns 0 on success, -1 on error or if bounds are not available and
  * bForce=FALSE.
  **********************************************************************/
-int MIFFile::GetBounds(double &dXMin, double &dYMin, 
+int MIFFile::GetBounds(double &dXMin, double &dYMin,
                        double &dXMax, double &dYMax,
                        GBool bForce /*= TRUE*/ )
 {
-    
     if (m_bBoundsSet == FALSE && bForce == FALSE)
     {
         return -1;
@@ -2237,7 +2242,7 @@ int MIFFile::GetBounds(double &dXMin, double &dYMin,
     dXMax = m_dXMax;
     dYMin = m_dYMin;
     dYMax = m_dYMax;
-    
+
     return 0;
 }
 
@@ -2287,9 +2292,9 @@ int MIFFile::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCFastGetExtent) )
         return m_bPreParsed;
 
-    else if( EQUAL(pszCap,OLCCreateField) ) 
-        return TRUE; 
+    else if( EQUAL(pszCap,OLCCreateField) )
+        return TRUE;
 
-    else 
+    else
         return FALSE;
 }
diff --git a/ogr/ogrsf_frmts/mitab/mitab_ogr_datasource.cpp b/ogr/ogrsf_frmts/mitab/mitab_ogr_datasource.cpp
index 90661f4..3502e1c 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_ogr_datasource.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_ogr_datasource.cpp
@@ -18,16 +18,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -38,9 +38,6 @@
  * Revision 1.11  2006/01/27 14:27:35  fwarmerdam
  * fixed ogr bounds setting problems (bug 1198)
  *
- * Revision 1.10  2005/09/20 04:40:02  fwarmerdam
- * fixed CPLReadDir memory leak
- *
  * Revision 1.9  2004/10/15 01:52:30  fwarmerdam
  * ModifiedICreateLayer() to use  -1000,-1000,1000,1000 bounds for GEOGCS
  * much like in mitab_bounds.cpp.  This ensures that geographic files in
@@ -112,7 +109,7 @@ OGRTABDataSource::OGRTABDataSource()
 OGRTABDataSource::~OGRTABDataSource()
 
 {
-    CPLFree( m_pszName ); 
+    CPLFree( m_pszName );
     CPLFree( m_pszDirectory );
 
     for( int i = 0; i < m_nLayerCount; i++ )
@@ -135,12 +132,12 @@ int OGRTABDataSource::Create( const char * pszName, char **papszOptions )
     const char *pszOpt;
 
     CPLAssert( m_pszName == NULL );
-    
+
     m_pszName = CPLStrdup( pszName );
     m_papszOptions = CSLDuplicate( papszOptions );
     m_bUpdate = TRUE;
 
-    if( (pszOpt=CSLFetchNameValue(papszOptions,"FORMAT")) != NULL 
+    if( (pszOpt=CSLFetchNameValue(papszOptions,"FORMAT")) != NULL
         && EQUAL(pszOpt, "MIF") )
         m_bCreateMIF = TRUE;
     else if( EQUAL(CPLGetExtension(pszName),"mif")
@@ -183,7 +180,7 @@ int OGRTABDataSource::Create( const char * pszName, char **papszOptions )
                 return FALSE;
             }
         }
-        
+
         m_pszDirectory = CPLStrdup(pszName);
     }
 
@@ -213,11 +210,11 @@ int OGRTABDataSource::Create( const char * pszName, char **papszOptions )
             }
             poFile = poTabFile;
         }
-        
+
         m_nLayerCount = 1;
         m_papoLayers = (IMapInfoFile **) CPLMalloc(sizeof(void*));
         m_papoLayers[0] = poFile;
-        
+
         m_pszDirectory = CPLStrdup( CPLGetPath(pszName) );
         m_bSingleFile = TRUE;
     }
@@ -268,8 +265,8 @@ int OGRTABDataSource::Open( GDALOpenInfo* poOpenInfo, int bTestOpen )
 /* -------------------------------------------------------------------- */
     else
     {
-        char    **papszFileList = CPLReadDir( m_pszName );
-        
+        char    **papszFileList = VSIReadDir( m_pszName );
+
         m_pszDirectory = CPLStrdup( m_pszName );
 
         for( int iFile = 0;
@@ -288,7 +285,7 @@ int OGRTABDataSource::Open( GDALOpenInfo* poOpenInfo, int bTestOpen )
 
             poFile = IMapInfoFile::SmartOpen( pszSubFilename, m_bUpdate, bTestOpen );
             CPLFree( pszSubFilename );
-            
+
             if( poFile == NULL )
             {
                 CSLDestroy( papszFileList );
@@ -310,7 +307,7 @@ int OGRTABDataSource::Open( GDALOpenInfo* poOpenInfo, int bTestOpen )
                 CPLError( CE_Failure, CPLE_OpenFailed,
                           "No mapinfo files found in directory %s.\n",
                           m_pszDirectory );
-            
+
             return FALSE;
         }
     }
@@ -361,7 +358,7 @@ OGRTABDataSource::ICreateLayer( const char * pszLayerName,
 
     if( !m_bUpdate )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                     "Cannot create layer on read-only dataset.");
         return NULL;
     }
@@ -375,7 +372,7 @@ OGRTABDataSource::ICreateLayer( const char * pszLayerName,
     {
         if( m_bSingleLayerAlreadyCreated )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Unable to create new layers in this single file dataset.");
             return NULL;
         }
@@ -391,24 +388,32 @@ OGRTABDataSource::ICreateLayer( const char * pszLayerName,
         {
             pszFullFilename = CPLStrdup( CPLFormFilename( m_pszDirectory,
                                                           pszLayerName, "mif" ) );
-            
+
             poFile = new MIFFile;
+
+            if( poFile->Open( pszFullFilename, TABWrite, FALSE ) != 0 )
+            {
+                CPLFree( pszFullFilename );
+                delete poFile;
+                return NULL;
+            }
         }
         else
         {
             pszFullFilename = CPLStrdup( CPLFormFilename( m_pszDirectory,
                                                           pszLayerName, "tab" ) );
-            
-            poFile = new TABFile;
-        }
-        
-        if( poFile->Open( pszFullFilename, TABWrite, FALSE ) != 0 )
-        {
-            CPLFree( pszFullFilename );
-            delete poFile;
-            return FALSE;
+
+            TABFile* poTABFile = new TABFile;
+            if( poTABFile->Open( pszFullFilename, TABWrite, FALSE, m_nBlockSize ) != 0 )
+            {
+                CPLFree( pszFullFilename );
+                delete poTABFile;
+                return NULL;
+            }
+            poFile = poTABFile;
         }
 
+
         m_nLayerCount++;
         m_papoLayers = (IMapInfoFile **)
             CPLRealloc(m_papoLayers,sizeof(void*)*m_nLayerCount);
@@ -433,9 +438,9 @@ OGRTABDataSource::ICreateLayer( const char * pszLayerName,
     // Pull out the bounds if supplied
     if( (pszOpt=CSLFetchNameValue(papszOptions, "BOUNDS")) != NULL ) {
         double dfBounds[4];
-        if( CPLsscanf(pszOpt, "%lf,%lf,%lf,%lf", &dfBounds[0], 
-                                          &dfBounds[1], 
-                                          &dfBounds[2], 
+        if( CPLsscanf(pszOpt, "%lf,%lf,%lf,%lf", &dfBounds[0],
+                                          &dfBounds[1],
+                                          &dfBounds[2],
                                           &dfBounds[3]) != 4 )
         {
             CPLError( CE_Failure, CPLE_IllegalArg,
@@ -458,12 +463,12 @@ OGRTABDataSource::ICreateLayer( const char * pszLayerName,
 
     if (m_bQuickSpatialIndexMode == TRUE && poFile->SetQuickSpatialIndexMode(TRUE) != 0)
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "Setting Quick Spatial Index Mode failed.");
     }
     else if (m_bQuickSpatialIndexMode == FALSE && poFile->SetQuickSpatialIndexMode(FALSE) != 0)
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "Setting Normal Spatial Index Mode failed.");
     }
 
@@ -492,23 +497,23 @@ char **OGRTABDataSource::GetFileList()
     VSIStatBufL sStatBuf;
     CPLStringList osList;
 
-    VSIStatL( m_pszName, &sStatBuf );
-    if( VSI_ISDIR(sStatBuf.st_mode) )
+    if( VSIStatL( m_pszName, &sStatBuf ) == 0 &&
+        VSI_ISDIR(sStatBuf.st_mode) )
     {
-        static const char *apszExtensions[] = 
+        static const char * const apszExtensions[] =
             { "mif", "mid", "tab", "map", "ind", "dat", "id", NULL };
-        char **papszDirEntries = CPLReadDir( m_pszName );
+        char **papszDirEntries = VSIReadDir( m_pszName );
         int  iFile;
 
-        for( iFile = 0; 
+        for( iFile = 0;
              papszDirEntries != NULL && papszDirEntries[iFile] != NULL;
              iFile++ )
         {
-            if( CSLFindString( (char **) apszExtensions, 
+            if( CSLFindString( (char **) apszExtensions,
                                CPLGetExtension(papszDirEntries[iFile])) != -1)
             {
-                osList.AddString( CPLFormFilename( m_pszName, 
-                                            papszDirEntries[iFile], 
+                osList.AddString( CPLFormFilename( m_pszName,
+                                            papszDirEntries[iFile],
                                             NULL ) );
             }
         }
@@ -517,9 +522,9 @@ char **OGRTABDataSource::GetFileList()
     }
     else
     {
-        static const char* apszMIFExtensions[] = { "mif", "mid", NULL };
-        static const char* apszTABExtensions[] = { "tab", "map", "ind", "dat", "id", NULL };
-        const char** papszExtensions;
+        static const char* const apszMIFExtensions[] = { "mif", "mid", NULL };
+        static const char* const apszTABExtensions[] = { "tab", "map", "ind", "dat", "id", NULL };
+        const char* const * papszExtensions;
         if( EQUAL(CPLGetExtension(m_pszName), "mif") ||
             EQUAL(CPLGetExtension(m_pszName), "mid") )
         {
@@ -529,7 +534,7 @@ char **OGRTABDataSource::GetFileList()
         {
             papszExtensions = apszTABExtensions;
         }
-        const char** papszIter = papszExtensions;
+        const char* const * papszIter = papszExtensions;
         while( *papszIter )
         {
             const char *pszFile = CPLResetExtension(m_pszName, *papszIter );
diff --git a/ogr/ogrsf_frmts/mitab/mitab_ogr_driver.cpp b/ogr/ogrsf_frmts/mitab/mitab_ogr_driver.cpp
index 350f792..041c504 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_ogr_driver.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_ogr_driver.cpp
@@ -18,16 +18,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -99,14 +99,22 @@ static int OGRTABDriverIdentify( GDALOpenInfo* poOpenInfo )
         for( int i = 0; i < poOpenInfo->nHeaderBytes; i++)
         {
             const char* pszLine = (const char*)poOpenInfo->pabyHeader + i;
-            if (EQUALN(pszLine, "Fields", 6))
+            if (STARTS_WITH_CI(pszLine, "Fields"))
                 return TRUE;
-            else if (EQUALN(pszLine, "create view", 11))
+            else if (STARTS_WITH_CI(pszLine, "create view"))
                 return TRUE;
-            else if (EQUALN(pszLine, "\"\\IsSeamless\" = \"TRUE\"", 21))
+            else if (STARTS_WITH_CI(pszLine, "\"\\IsSeamless\" = \"TRUE\""))
                 return TRUE;
         }
     }
+#ifdef DEBUG
+    /* For AFL, so that .cur_input is detected as the archive filename */
+    if( !STARTS_WITH(poOpenInfo->pszFilename, "/vsitar/") &&
+        EQUAL(CPLGetFilename(poOpenInfo->pszFilename), ".cur_input") )
+    {
+        return -1;
+    }
+#endif
     return FALSE;
 }
 
@@ -131,6 +139,19 @@ static GDALDataset *OGRTABDriverOpen( GDALOpenInfo* poOpenInfo )
             return NULL;
     }
 
+#ifdef DEBUG
+    /* For AFL, so that .cur_input is detected as the archive filename */
+    if( poOpenInfo->fpL != NULL &&
+        !STARTS_WITH(poOpenInfo->pszFilename, "/vsitar/") &&
+        EQUAL(CPLGetFilename(poOpenInfo->pszFilename), ".cur_input") )
+    {
+        GDALOpenInfo oOpenInfo( (CPLString("/vsitar/") + poOpenInfo->pszFilename).c_str(),
+                                poOpenInfo->nOpenFlags );
+        oOpenInfo.papszOpenOptions = poOpenInfo->papszOpenOptions;
+        return OGRTABDriverOpen(&oOpenInfo);
+    }
+#endif
+
     poDS = new OGRTABDataSource();
     if( poDS->Open( poOpenInfo, TRUE ) )
         return poDS;
@@ -224,28 +245,23 @@ extern "C"
 void RegisterOGRTAB()
 
 {
-    GDALDriver  *poDriver;
-
-    if( GDALGetDriverByName( "MapInfo File" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-
-        poDriver->SetDescription( "MapInfo File" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "MapInfo File" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "tab mif mid" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_mitab.html" );
-
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+    if( GDALGetDriverByName( "MapInfo File" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "MapInfo File" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "MapInfo File" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "tab mif mid" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_mitab.html" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
 "<LayerCreationOptionList>"
 "  <Option name='BOUNDS' type='string' description='Custom bounds. Expect format is xmin,ymin,xmax,ymax'/>"
 "</LayerCreationOptionList>");
 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "  <Option name='FORMAT' type='string-select' description='type of MapInfo format'>"
 "    <Value>MIF</Value>"
@@ -257,17 +273,17 @@ void RegisterOGRTAB()
 "  </Option>"
 "  <Option name='BLOCKSIZE' type='int' description='.map block size' min='512' max='32256' default='512'/>"
 "</CreationOptionList>");
-        
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES, "Integer Real String Date DateTime Time" );
 
-        poDriver->pfnOpen = OGRTABDriverOpen;
-        poDriver->pfnIdentify = OGRTABDriverIdentify;
-        poDriver->pfnCreate = OGRTABDriverCreate;
-        poDriver->pfnDelete = OGRTABDriverDelete;
-        poDriver->pfnUnloadDriver = OGRTABDriverUnload;
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
+                               "Integer Real String Date DateTime Time" );
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    poDriver->pfnOpen = OGRTABDriverOpen;
+    poDriver->pfnIdentify = OGRTABDriverIdentify;
+    poDriver->pfnCreate = OGRTABDriverCreate;
+    poDriver->pfnDelete = OGRTABDriverDelete;
+    poDriver->pfnUnloadDriver = OGRTABDriverUnload;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
 
 }
diff --git a/ogr/ogrsf_frmts/mitab/mitab_ogr_driver.h b/ogr/ogrsf_frmts/mitab/mitab_ogr_driver.h
index 19d1064..dc21e71 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_ogr_driver.h
+++ b/ogr/ogrsf_frmts/mitab/mitab_ogr_driver.h
@@ -17,16 +17,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -80,12 +80,12 @@
 #include "mitab.h"
 #include "ogrsf_frmts.h"
 
-#ifndef _MITAB_OGR_DRIVER_H_INCLUDED_
-#define _MITAB_OGR_DRIVER_H_INCLUDED_
+#ifndef MITAB_OGR_DRIVER_H_INCLUDED_
+#define MITAB_OGR_DRIVER_H_INCLUDED_
 
 /*=====================================================================
  *            OGRTABDataSource Class
- * 
+ *
  * These classes handle all the file types supported by the MITAB lib.
  * through the IMapInfoFile interface.
  *====================================================================*/
@@ -117,8 +117,8 @@ class OGRTABDataSource : public OGRDataSource
     int          GetLayerCount();
     OGRLayer    *GetLayer( int );
     int          TestCapability( const char * );
-    
-    OGRLayer    *ICreateLayer(const char *, 
+
+    OGRLayer    *ICreateLayer(const char *,
                              OGRSpatialReference * = NULL,
                              OGRwkbGeometryType = wkbUnknown,
                              char ** = NULL );
@@ -128,4 +128,4 @@ class OGRTABDataSource : public OGRDataSource
 
 void CPL_DLL RegisterOGRTAB();
 
-#endif /* _MITAB_OGR_DRIVER_H_INCLUDED_ */
+#endif /* MITAB_OGR_DRIVER_H_INCLUDED_ */
diff --git a/ogr/ogrsf_frmts/mitab/mitab_priv.h b/ogr/ogrsf_frmts/mitab/mitab_priv.h
index 5173ea1..9ebca58 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_priv.h
+++ b/ogr/ogrsf_frmts/mitab/mitab_priv.h
@@ -17,16 +17,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -78,7 +78,7 @@
  *
  * Revision 1.42  2006/11/20 20:05:58  dmorissette
  * First pass at improving generation of spatial index in .map file (bug 1585)
- * New methods for insertion and splittung in the spatial index are done.
+ * New methods for insertion and splitting in the spatial index are done.
  * Also implemented a method to dump the spatial index to .mif/.mid
  * Still need to implement splitting of TABMapObjectBlock to get optimal
  * results.
@@ -129,8 +129,8 @@
  * Added TABMAPObjNone to handle the case of TAB_GEOM_NONE
  *
  * Revision 1.28  2001/11/17 21:54:06  daniel
- * Made several changes in order to support writing objects in 16 bits 
- * coordinate format. New TABMAPObjHdr-derived classes are used to hold 
+ * Made several changes in order to support writing objects in 16 bits
+ * coordinate format. New TABMAPObjHdr-derived classes are used to hold
  * object info in mem until block is full.
  *
  * Revision 1.27  2001/09/18 20:33:52  warmerda
@@ -177,8 +177,8 @@
  *
  **********************************************************************/
 
-#ifndef _MITAB_PRIV_H_INCLUDED_
-#define _MITAB_PRIV_H_INCLUDED_
+#ifndef MITAB_PRIV_H_INCLUDED_
+#define MITAB_PRIV_H_INCLUDED_
 
 #include "cpl_conv.h"
 #include "cpl_string.h"
@@ -230,8 +230,8 @@ typedef enum
 
 #define TAB_MULTIPOINT_650_MAX_VERTICES         1048576
 
-/* Use this macro to test whether the number of segments and vertices 
- * in this object exceeds the V450/650 limits and requires a V800 object 
+/* Use this macro to test whether the number of segments and vertices
+ * in this object exceeds the V450/650 limits and requires a V800 object
  */
 #define TAB_REGION_PLINE_REQUIRES_V800(numSegments, numVerticesTotal) \
     ((numSegments) > TAB_REGION_PLINE_450_MAX_SEGMENTS || \
@@ -266,7 +266,7 @@ typedef enum
     TAB_GEOM_ELLIPSE        = 0x1a,
     TAB_GEOM_MULTIPLINE_C   = 0x25,
     TAB_GEOM_MULTIPLINE     = 0x26,
-    TAB_GEOM_FONTSYMBOL_C   = 0x28, 
+    TAB_GEOM_FONTSYMBOL_C   = 0x28,
     TAB_GEOM_FONTSYMBOL     = 0x29,
     TAB_GEOM_CUSTOMSYMBOL_C = 0x2b,
     TAB_GEOM_CUSTOMSYMBOL   = 0x2c,
@@ -322,7 +322,7 @@ typedef struct TABMAPIndexEntry_t
 
 
 /*---------------------------------------------------------------------
- * TABVertex 
+ * TABVertex
  *--------------------------------------------------------------------*/
 typedef struct TABVertex_t
 {
@@ -418,7 +418,7 @@ typedef struct TABProjInfo_t
     double      adDatumParams[5];
 
     // Affine parameters only in .map version 500 and up
-    GByte       nAffineFlag;    // 0=No affine param, 1=Affine params   
+    GByte       nAffineFlag;    // 0=No affine param, 1=Affine params
     GByte       nAffineUnits;
     double      dAffineParamA;  // Affine params
     double      dAffineParamB;
@@ -555,7 +555,14 @@ class TABMAPObjHdr
     GInt32      m_nMaxX;
     GInt32      m_nMaxY;
 
-    TABMAPObjHdr() {};
+    TABMAPObjHdr():
+        m_nType(TAB_GEOM_NONE),
+        m_nId(0),
+        m_nMinX(0),
+        m_nMinY(0),
+        m_nMaxX(0),
+        m_nMaxY(0)
+        {};
     virtual ~TABMAPObjHdr() {};
 
     static TABMAPObjHdr *NewObj(TABGeomType nNewObjType, GInt32 nId=0);
@@ -572,7 +579,7 @@ class TABMAPObjHdr
     virtual int ReadObj(TABMAPObjectBlock *) {return -1;};
 };
 
-class TABMAPObjHdrWithCoord: public TABMAPObjHdr
+class TABMAPObjHdrWithCoord : public TABMAPObjHdr
 {
   public:
     GInt32      m_nCoordBlockPtr;
@@ -584,7 +591,7 @@ class TABMAPObjHdrWithCoord: public TABMAPObjHdr
 };
 
 
-class TABMAPObjNone: public TABMAPObjHdr
+class TABMAPObjNone CPL_FINAL : public TABMAPObjHdr
 {
   public:
 
@@ -605,7 +612,8 @@ class TABMAPObjPoint: public TABMAPObjHdr
     GInt32      m_nY;
     GByte       m_nSymbolId;
 
-    TABMAPObjPoint() {};
+    TABMAPObjPoint():
+        m_nX(0), m_nY(0), m_nSymbolId(0) {};
     virtual ~TABMAPObjPoint() {};
 
     virtual int WriteObj(TABMAPObjectBlock *);
@@ -625,7 +633,15 @@ class TABMAPObjFontPoint: public TABMAPObjPoint
     GInt16      m_nAngle;  /* In tenths of degree */
     GByte       m_nFontId;
 
-    TABMAPObjFontPoint() {};
+    TABMAPObjFontPoint():
+        m_nPointSize(0),
+        m_nFontStyle(0),
+        m_nR(0),
+        m_nG(0),
+        m_nB(0),
+        m_nAngle(0),
+        m_nFontId(0)
+        {};
     virtual ~TABMAPObjFontPoint() {};
 
     virtual int WriteObj(TABMAPObjectBlock *);
@@ -634,14 +650,18 @@ class TABMAPObjFontPoint: public TABMAPObjPoint
     virtual int ReadObj(TABMAPObjectBlock *);
 };
 
-class TABMAPObjCustomPoint: public TABMAPObjPoint
+class TABMAPObjCustomPoint CPL_FINAL : public TABMAPObjPoint
 {
   public:
     GByte m_nUnknown_;
     GByte m_nCustomStyle;
     GByte m_nFontId;
 
-    TABMAPObjCustomPoint() {};
+    TABMAPObjCustomPoint():
+        m_nUnknown_(0),
+        m_nCustomStyle(0),
+        m_nFontId(0)
+        {};
     virtual ~TABMAPObjCustomPoint() {};
 
     virtual int WriteObj(TABMAPObjectBlock *);
@@ -651,7 +671,7 @@ class TABMAPObjCustomPoint: public TABMAPObjPoint
 };
 
 
-class TABMAPObjLine: public TABMAPObjHdr
+class TABMAPObjLine CPL_FINAL : public TABMAPObjHdr
 {
   public:
     GInt32      m_nX1;
@@ -660,7 +680,13 @@ class TABMAPObjLine: public TABMAPObjHdr
     GInt32      m_nY2;
     GByte       m_nPenId;
 
-    TABMAPObjLine() {};
+    TABMAPObjLine():
+        m_nX1(0),
+        m_nY1(0),
+        m_nX2(0),
+        m_nY2(0),
+        m_nPenId(0)
+        {};
     virtual ~TABMAPObjLine() {};
 
     virtual int WriteObj(TABMAPObjectBlock *);
@@ -669,7 +695,7 @@ class TABMAPObjLine: public TABMAPObjHdr
     virtual int ReadObj(TABMAPObjectBlock *);
 };
 
-class TABMAPObjPLine: public TABMAPObjHdrWithCoord
+class TABMAPObjPLine CPL_FINAL : public TABMAPObjHdrWithCoord
 {
   public:
     GInt32      m_numLineSections;  /* MULTIPLINE/REGION only. Not in PLINE */
@@ -681,7 +707,16 @@ class TABMAPObjPLine: public TABMAPObjHdrWithCoord
     GByte       m_nBrushId;
     GBool       m_bSmooth;      /* TRUE if (m_nCoordDataSize & 0x80000000) */
 
-    TABMAPObjPLine() {};
+    TABMAPObjPLine():
+        m_numLineSections(0),
+        m_nLabelX(0),
+        m_nLabelY(0),
+        m_nComprOrgX(0),
+        m_nComprOrgY(0),
+        m_nPenId(0),
+        m_nBrushId(0),
+        m_bSmooth(0)
+        {};
     virtual ~TABMAPObjPLine() {};
 
     virtual int WriteObj(TABMAPObjectBlock *);
@@ -690,7 +725,7 @@ class TABMAPObjPLine: public TABMAPObjHdrWithCoord
     virtual int ReadObj(TABMAPObjectBlock *);
 };
 
-class TABMAPObjRectEllipse: public TABMAPObjHdr
+class TABMAPObjRectEllipse CPL_FINAL : public TABMAPObjHdr
 {
   public:
     GInt32      m_nCornerWidth;   /* For rounded rect only */
@@ -698,7 +733,12 @@ class TABMAPObjRectEllipse: public TABMAPObjHdr
     GByte       m_nPenId;
     GByte       m_nBrushId;
 
-    TABMAPObjRectEllipse() {};
+    TABMAPObjRectEllipse():
+        m_nCornerWidth(0),
+        m_nCornerHeight(0),
+        m_nPenId(0),
+        m_nBrushId(0)
+        {};
     virtual ~TABMAPObjRectEllipse() {};
 
     virtual int WriteObj(TABMAPObjectBlock *);
@@ -707,7 +747,7 @@ class TABMAPObjRectEllipse: public TABMAPObjHdr
     virtual int ReadObj(TABMAPObjectBlock *);
 };
 
-class TABMAPObjArc: public TABMAPObjHdr
+class TABMAPObjArc CPL_FINAL : public TABMAPObjHdr
 {
   public:
     GInt32      m_nStartAngle;
@@ -718,7 +758,15 @@ class TABMAPObjArc: public TABMAPObjHdr
     GInt32      m_nArcEllipseMaxY;
     GByte       m_nPenId;
 
-    TABMAPObjArc() {};
+    TABMAPObjArc():
+        m_nStartAngle(0),
+        m_nEndAngle(0),
+        m_nArcEllipseMinX(0),
+        m_nArcEllipseMinY(0),
+        m_nArcEllipseMaxX(0),
+        m_nArcEllipseMaxY(0),
+        m_nPenId(0)
+        {};
     virtual ~TABMAPObjArc() {};
 
     virtual int WriteObj(TABMAPObjectBlock *);
@@ -728,7 +776,7 @@ class TABMAPObjArc: public TABMAPObjHdr
 };
 
 
-class TABMAPObjText: public TABMAPObjHdrWithCoord
+class TABMAPObjText CPL_FINAL : public TABMAPObjHdrWithCoord
 {
   public:
     /* String and its len stored in the nCoordPtr and nCoordSize */
@@ -752,7 +800,22 @@ class TABMAPObjText: public TABMAPObjHdrWithCoord
 
     GByte       m_nPenId;
 
-    TABMAPObjText() {};
+    TABMAPObjText():
+        m_nTextAlignment(0),
+        m_nAngle(0),
+        m_nFontStyle(0),
+        m_nFGColorR(0),
+        m_nFGColorG(0),
+        m_nFGColorB(0),
+        m_nBGColorR(0),
+        m_nBGColorG(0),
+        m_nBGColorB(0),
+        m_nLineEndX(0),
+        m_nLineEndY(0),
+        m_nHeight(0),
+        m_nFontId(0),
+        m_nPenId(0)
+        {};
     virtual ~TABMAPObjText() {};
 
     virtual int WriteObj(TABMAPObjectBlock *);
@@ -762,7 +825,7 @@ class TABMAPObjText: public TABMAPObjHdrWithCoord
 };
 
 
-class TABMAPObjMultiPoint: public TABMAPObjHdrWithCoord
+class TABMAPObjMultiPoint CPL_FINAL : public TABMAPObjHdrWithCoord
 {
   public:
     GInt32      m_nNumPoints;
@@ -772,7 +835,14 @@ class TABMAPObjMultiPoint: public TABMAPObjHdrWithCoord
     GInt32      m_nLabelX;      /* Not sure if it's a label point, but */
     GInt32      m_nLabelY;      /* it's similar to what we find in PLINE */
 
-    TABMAPObjMultiPoint() {};
+    TABMAPObjMultiPoint():
+        m_nNumPoints(0),
+        m_nComprOrgX(0),
+        m_nComprOrgY(0),
+        m_nSymbolId(0),
+        m_nLabelX(0),
+        m_nLabelY(0)
+        {};
     virtual ~TABMAPObjMultiPoint() {};
 
     virtual int WriteObj(TABMAPObjectBlock *);
@@ -781,7 +851,7 @@ class TABMAPObjMultiPoint: public TABMAPObjHdrWithCoord
     virtual int ReadObj(TABMAPObjectBlock *);
 };
 
-class TABMAPObjCollection: public TABMAPObjHdrWithCoord
+class TABMAPObjCollection CPL_FINAL : public TABMAPObjHdrWithCoord
 {
   public:
     GInt32      m_nRegionDataSize;
@@ -798,8 +868,21 @@ class TABMAPObjCollection: public TABMAPObjHdrWithCoord
     GByte       m_nRegionBrushId;
     GByte       m_nPolylinePenId;
 
-    TABMAPObjCollection() {};
-    virtual ~TABMAPObjCollection() 
+    TABMAPObjCollection():
+        m_nRegionDataSize(0),
+        m_nPolylineDataSize(0),
+        m_nMPointDataSize(0),
+        m_nComprOrgX(0),
+        m_nComprOrgY(0),
+        m_nNumMultiPoints(0),
+        m_nNumRegSections(0),
+        m_nNumPLineSections(0),
+        m_nMultiPointSymbolId(0),
+        m_nRegionPenId(0),
+        m_nRegionBrushId(0),
+        m_nPolylinePenId(0)
+        {};
+    virtual ~TABMAPObjCollection()
     {}
 
     virtual int WriteObj(TABMAPObjectBlock *);
@@ -854,14 +937,14 @@ class TABBinBlockManager
     void        PushGarbageBlockAsLast(GInt32 nBlockPtr);
     GInt32      GetFirstGarbageBlock();
     GInt32      PopGarbageBlock();
-    
+
     void        SetName(const char* pszName);
 };
 
 /*---------------------------------------------------------------------
  *                      class TABRawBinBlock
  *
- * This is the base class used for all other data block types... it 
+ * This is the base class used for all other data block types... it
  * contains all the base functions to handle binary data.
  *--------------------------------------------------------------------*/
 
@@ -895,7 +978,7 @@ class TABRawBinBlock
     virtual int CommitToFile();
     int         CommitAsDeleted(GInt32 nNextBlockPtr);
 
-    virtual int InitBlockFromData(GByte *pabyBuf, 
+    virtual int InitBlockFromData(GByte *pabyBuf,
                                   int nBlockSize, int nSizeUsed,
                                   GBool bMakeCopy = TRUE,
                                   VSILFILE *fpSrc = NULL, int nOffset = 0);
@@ -912,7 +995,7 @@ class TABRawBinBlock
 
     int         GotoByteRel(int nOffset);
     int         GotoByteInBlock(int nOffset);
-    int         GotoByteInFile(int nOffset, 
+    int         GotoByteInFile(int nOffset,
                                GBool bForceReadFromFile = FALSE,
                                GBool bOffsetIsEndOfData = FALSE);
     void        SetFirstBlockPtr(int nOffset);
@@ -928,7 +1011,7 @@ class TABRawBinBlock
     float       ReadFloat();
     double      ReadDouble();
 
-    virtual int WriteBytes(int nBytesToWrite, GByte *pBuf);
+    virtual int WriteBytes(int nBytesToWrite, const GByte *pBuf);
     int         WriteByte(GByte byValue);
     int         WriteInt16(GInt16 n16Value);
     int         WriteInt32(GInt32 n32Value);
@@ -939,7 +1022,7 @@ class TABRawBinBlock
 
     void        SetModifiedFlag(GBool bModified) {m_bModified=bModified;};
 
-    // This semi-private method gives a direct access to the internal 
+    // This semi-private method gives a direct access to the internal
     // buffer... to be used with extreme care!!!!!!!!!
     GByte *     GetCurDataPtr() { return (m_pabyBuf + m_nCurPos); } ;
 };
@@ -948,10 +1031,10 @@ class TABRawBinBlock
 /*---------------------------------------------------------------------
  *                      class TABMAPHeaderBlock
  *
- * Class to handle Read/Write operation on .MAP Header Blocks 
+ * Class to handle Read/Write operation on .MAP Header Blocks
  *--------------------------------------------------------------------*/
 
-class TABMAPHeaderBlock: public TABRawBinBlock
+class TABMAPHeaderBlock CPL_FINAL : public TABRawBinBlock
 {
     void        InitMembersWithDefaultValues();
     void        UpdatePrecision();
@@ -974,14 +1057,14 @@ class TABMAPHeaderBlock: public TABRawBinBlock
     virtual int GetBlockClass() { return TABMAP_HEADER_BLOCK; };
 
     int         Int2Coordsys(GInt32 nX, GInt32 nY, double &dX, double &dY);
-    int         Coordsys2Int(double dX, double dY, GInt32 &nX, GInt32 &nY, 
+    int         Coordsys2Int(double dX, double dY, GInt32 &nX, GInt32 &nY,
                              GBool bIgnoreOverflow=FALSE);
-    int         ComprInt2Coordsys(GInt32 nCenterX, GInt32 nCenterY, 
-                                  int nDeltaX, int nDeltaY, 
+    int         ComprInt2Coordsys(GInt32 nCenterX, GInt32 nCenterY,
+                                  int nDeltaX, int nDeltaY,
                                   double &dX, double &dY);
     int         Int2CoordsysDist(GInt32 nX, GInt32 nY, double &dX, double &dY);
     int         Coordsys2IntDist(double dX, double dY, GInt32 &nX, GInt32 &nY);
-    int         SetCoordsysBounds(double dXMin, double dYMin, 
+    int         SetCoordsysBounds(double dXMin, double dYMin,
                                   double dXMax, double dYMax);
 
     int         GetMapObjectSize(int nObjType);
@@ -994,19 +1077,19 @@ class TABMAPHeaderBlock: public TABRawBinBlock
     virtual void Dump(FILE *fpOut = NULL);
 #endif
 
-    // Instead of having over 30 get/set methods, we'll make all data 
+    // Instead of having over 30 get/set methods, we'll make all data
     // members public and we will initialize them in the overloaded
     // LoadFromFile().  For this reason, this class should be used with care.
 
     GInt16      m_nMAPVersionNumber;
     GInt16      m_nRegularBlockSize;
-    
+
     double      m_dCoordsys2DistUnits;
     GInt32      m_nXMin;
     GInt32      m_nYMin;
     GInt32      m_nXMax;
     GInt32      m_nYMax;
-    GBool       m_bIntBoundsOverflow;  // Set to TRUE if coordinates 
+    GBool       m_bIntBoundsOverflow;  // Set to TRUE if coordinates
                                        // outside of bounds were written
 
     GInt32      m_nFirstIndexBlock;
@@ -1044,7 +1127,7 @@ class TABMAPHeaderBlock: public TABRawBinBlock
  * Class to handle Read/Write operation on .MAP Index Blocks (Type 01)
  *--------------------------------------------------------------------*/
 
-class TABMAPIndexBlock: public TABRawBinBlock
+class TABMAPIndexBlock CPL_FINAL : public TABRawBinBlock
 {
   protected:
     int         m_numEntries;
@@ -1068,7 +1151,7 @@ class TABMAPIndexBlock: public TABRawBinBlock
     TABMAPIndexBlock *m_poParentRef;
 
     int         ReadAllEntries();
-    
+
     int         GetMaxEntries() const { return ((m_nBlockSize-4)/20); }
 
   public:
@@ -1094,9 +1177,9 @@ class TABMAPIndexBlock: public TABRawBinBlock
                          GInt32 nBlockPtr,
                          GBool bAddInThisNodeOnly=FALSE);
     int         GetCurMaxDepth();
-    void        GetMBR(GInt32 &nXMin, GInt32 &nYMin, 
+    void        GetMBR(GInt32 &nXMin, GInt32 &nYMin,
                        GInt32 &nXMax, GInt32 &nYMax);
-    void        SetMBR(GInt32 nXMin, GInt32 nYMin, 
+    void        SetMBR(GInt32 nXMin, GInt32 nYMin,
                        GInt32 nXMax, GInt32 nYMax);
 
     GInt32      GetNodeBlockPtr() { return GetStartAddress();};
@@ -1107,7 +1190,7 @@ class TABMAPIndexBlock: public TABRawBinBlock
 
     int         GetCurChildIndex() { return m_nCurChildIndex; }
     TABMAPIndexBlock *GetCurChild() { return m_poCurChild; }
-    TABMAPIndexBlock *GetParentRef() { return m_poParentRef; } 
+    TABMAPIndexBlock *GetParentRef() { return m_poParentRef; }
 
     int         SplitNode(GInt32 nNewEntryXMin, GInt32 nNewEntryYMin,
                           GInt32 nNewEntryXMax, GInt32 nNewEntryYMax);
@@ -1139,9 +1222,9 @@ class TABMAPIndexBlock: public TABRawBinBlock
     static int    PickSeedsForSplit(TABMAPIndexEntry *pasEntries,
                                     int numEntries,
                                     int nSrcCurChildIndex,
-                                    GInt32 nNewEntryXMin, 
+                                    GInt32 nNewEntryXMin,
                                     GInt32 nNewEntryYMin,
-                                    GInt32 nNewEntryXMax, 
+                                    GInt32 nNewEntryXMax,
                                     GInt32 nNewEntryYMax,
                                     int &nSeed1, int &nSeed2);
 #ifdef DEBUG
@@ -1156,7 +1239,7 @@ class TABMAPIndexBlock: public TABRawBinBlock
  * Class to handle Read/Write operation on .MAP Object data Blocks (Type 02)
  *--------------------------------------------------------------------*/
 
-class TABMAPObjectBlock: public TABRawBinBlock
+class TABMAPObjectBlock CPL_FINAL : public TABRawBinBlock
 {
   protected:
     int         m_numDataBytes; /* Excluding first 4 bytes header */
@@ -1175,7 +1258,7 @@ class TABMAPObjectBlock: public TABRawBinBlock
     int         m_nCurObjectOffset; // -1 if there is no current object.
     int         m_nCurObjectId;     // -1 if there is no current object.
     TABGeomType m_nCurObjectType;   // TAB_GEOM_UNSET if there is no current object.
-    
+
     int         m_bLockCenter;
 
   public:
@@ -1205,9 +1288,9 @@ class TABMAPObjectBlock: public TABRawBinBlock
     GInt32      GetFirstCoordBlockAddress() { return m_nFirstCoordBlock; }
     GInt32      GetLastCoordBlockAddress() { return m_nLastCoordBlock; }
 
-    void        GetMBR(GInt32 &nXMin, GInt32 &nYMin, 
+    void        GetMBR(GInt32 &nXMin, GInt32 &nYMin,
                        GInt32 &nXMax, GInt32 &nYMax);
-    void        SetMBR(GInt32 nXMin, GInt32 nYMin, 
+    void        SetMBR(GInt32 nXMin, GInt32 nYMin,
                        GInt32 nXMax, GInt32 nYMax);
 
     void        Rewind();
@@ -1232,7 +1315,7 @@ class TABMAPObjectBlock: public TABRawBinBlock
  * Class to handle Read/Write operation on .MAP Coordinate Blocks (Type 03)
  *--------------------------------------------------------------------*/
 
-class TABMAPCoordBlock: public TABRawBinBlock
+class TABMAPCoordBlock CPL_FINAL : public TABRawBinBlock
 {
   protected:
     int         m_numDataBytes; /* Excluding first 8 bytes header */
@@ -1252,8 +1335,8 @@ class TABMAPCoordBlock: public TABRawBinBlock
 
     int         m_nTotalDataSize;       // Num bytes in whole chain of blocks
     int         m_nFeatureDataSize;     // Num bytes for current feature coords
-    
-    GInt32      m_nFeatureXMin;         // Used to keep track of current 
+
+    GInt32      m_nFeatureXMin;         // Used to keep track of current
     GInt32      m_nFeatureYMin;         // feature MBR.
     GInt32      m_nFeatureXMax;
     GInt32      m_nFeatureYMax;
@@ -1273,7 +1356,7 @@ class TABMAPCoordBlock: public TABRawBinBlock
 
     void        SetMAPBlockManagerRef(TABBinBlockManager *poBlockManager);
     virtual int ReadBytes(int numBytes, GByte *pabyDstBuf);
-    virtual int WriteBytes(int nBytesToWrite, GByte *pBuf);
+    virtual int WriteBytes(int nBytesToWrite, const GByte *pBuf);
     void        SetComprCoordOrigin(GInt32 nX, GInt32 nY);
     int         ReadIntCoord(GBool bCompressed, GInt32 &nX, GInt32 &nY);
     int         ReadIntCoords(GBool bCompressed, int numCoords, GInt32 *panXY);
@@ -1298,7 +1381,7 @@ class TABMAPCoordBlock: public TABRawBinBlock
     void        StartNewFeature();
     int         GetFeatureDataSize() {return m_nFeatureDataSize;};
 //__TODO__ Can we flush GetFeatureMBR() and all MBR tracking in this class???
-    void        GetFeatureMBR(GInt32 &nXMin, GInt32 &nYMin, 
+    void        GetFeatureMBR(GInt32 &nXMin, GInt32 &nYMin,
                               GInt32 &nXMax, GInt32 &nYMax);
 
 #ifdef DEBUG
@@ -1312,11 +1395,11 @@ class TABMAPCoordBlock: public TABRawBinBlock
  *
  * Class to handle Read/Write operation on .MAP Drawing Tool Blocks (Type 05)
  *
- * In addition to handling the I/O, this class also maintains the list 
+ * In addition to handling the I/O, this class also maintains the list
  * of Tool definitions in memory.
  *--------------------------------------------------------------------*/
 
-class TABMAPToolBlock: public TABRawBinBlock
+class TABMAPToolBlock CPL_FINAL : public TABRawBinBlock
 {
   protected:
     int         m_numDataBytes; /* Excluding first 8 bytes header */
@@ -1340,7 +1423,7 @@ class TABMAPToolBlock: public TABRawBinBlock
 
     void        SetMAPBlockManagerRef(TABBinBlockManager *poBlockManager);
     virtual int ReadBytes(int numBytes, GByte *pabyDstBuf);
-    virtual int WriteBytes(int nBytesToWrite, GByte *pBuf);
+    virtual int WriteBytes(int nBytesToWrite, const GByte *pBuf);
 
     void        SetNextToolBlock(GInt32 nNextCoordBlockAddress);
 
@@ -1444,7 +1527,7 @@ class TABMAPFile
     GInt32      m_YMinFilter;
     GInt32      m_XMaxFilter;
     GInt32      m_YMaxFilter;
-    
+
     int         m_bUpdated;
     int         m_bLastOpWasRead;
     int         m_bLastOpWasWrite;
@@ -1471,9 +1554,9 @@ class TABMAPFile
 
     int         LoadNextMatchingObjectBlock(int bFirstObject);
     TABRawBinBlock *PushBlock( int nFileOffset );
-    
+
     int         ReOpenReadWrite();
-    
+
   public:
     TABMAPFile();
     ~TABMAPFile();
@@ -1491,14 +1574,14 @@ class TABMAPFile
     int         SetQuickSpatialIndexMode(GBool bQuickSpatialIndexMode = TRUE);
 
     int         Int2Coordsys(GInt32 nX, GInt32 nY, double &dX, double &dY);
-    int         Coordsys2Int(double dX, double dY, GInt32 &nX, GInt32 &nY, 
+    int         Coordsys2Int(double dX, double dY, GInt32 &nX, GInt32 &nY,
                              GBool bIgnoreOveflow=FALSE);
     int         Int2CoordsysDist(GInt32 nX, GInt32 nY, double &dX, double &dY);
     int         Coordsys2IntDist(double dX, double dY, GInt32 &nX, GInt32 &nY);
     void        SetCoordFilter(TABVertex sMin, TABVertex sMax);
     void        GetCoordFilter(TABVertex &sMin, TABVertex &sMax);
     void        ResetCoordFilter();
-    int         SetCoordsysBounds(double dXMin, double dYMin, 
+    int         SetCoordsysBounds(double dXMin, double dYMin,
                                   double dXMax, double dYMax);
 
     GInt32      GetMaxObjId();
@@ -1536,10 +1619,10 @@ class TABMAPFile
 
 #ifdef DEBUG
     void Dump(FILE *fpOut = NULL);
-    void DumpSpatialIndexToMIF(TABMAPIndexBlock *poNode, 
-                               FILE *fpMIF, FILE *fpMID, 
-                               int nIndexInNode=-1, 
-                               int nParentId=-1, 
+    void DumpSpatialIndexToMIF(TABMAPIndexBlock *poNode,
+                               FILE *fpMIF, FILE *fpMID,
+                               int nIndexInNode=-1,
+                               int nParentId=-1,
                                int nCurDepth=0,
                                int nMaxDepth=-1);
 #endif
@@ -1587,14 +1670,14 @@ class TABINDNode
                             GBool bInsertAfterCurChild=FALSE,
                             GBool bMakeNewEntryCurChild=FALSE);
     int         SetNodeBufferDirectly(int numEntries, GByte *pBuf,
-                                      int nCurIndexEntry=0, 
+                                      int nCurIndexEntry=0,
                                       TABINDNode *poCurChild=NULL);
 
    public:
     TABINDNode(TABAccess eAccessMode = TABRead);
     ~TABINDNode();
 
-    int         InitNode(VSILFILE *fp, int nBlockPtr, 
+    int         InitNode(VSILFILE *fp, int nBlockPtr,
                          int nKeyLength, int nSubTreeDepth, GBool bUnique,
                          TABBinBlockManager *poBlockMgr=NULL,
                          TABINDNode *poParentNode=NULL,
@@ -1669,7 +1752,7 @@ class TABINDFile
     TABINDFile();
     ~TABINDFile();
 
-    int         Open(const char *pszFname, const char *pszAccess, 
+    int         Open(const char *pszFname, const char *pszAccess,
                      GBool bTestOpenNoError=FALSE);
     int         Close();
 
@@ -1721,7 +1804,7 @@ class TABDATFile
     GInt32      m_nFirstRecordPtr;
     GBool       m_bWriteHeaderInitialized;
     GBool       m_bWriteEOF;
-    
+
     int         m_bUpdated;
 
     int         InitWriteHeader();
@@ -1762,7 +1845,7 @@ class TABDATFile
     TABRawBinBlock *GetRecordBlock(int nRecordId);
     GBool       IsCurrentRecordDeleted() { return m_bCurRecordDeletedFlag;};
     int         CommitRecordToFile();
-    
+
     int         MarkAsDeleted();
     int         MarkRecordAsExisting();
 
@@ -1775,7 +1858,7 @@ class TABDATFile
     const char  *ReadDateField(int nWidth);
     int         ReadDateField(int nWidth, int *nYear, int *nMonth, int *nDay);
     const char  *ReadTimeField(int nWidth);
-    int         ReadTimeField(int nWidth, int *nHour, int *nMinute, 
+    int         ReadTimeField(int nWidth, int *nHour, int *nMinute,
                               int *nSecond, int *nMS);
     const char  *ReadDateTimeField(int nWidth);
     int         ReadDateTimeField(int nWidth, int *nYear, int *nMonth, int *nDay,
@@ -1803,7 +1886,7 @@ class TABDATFile
                                TABINDFile *poINDFile, int nIndexNo);
     int         WriteDateTimeField(const char *pszValue,
                                TABINDFile *poINDFile, int nIndexNo);
-    int         WriteDateTimeField(int nYear, int nMonth, int nDay, 
+    int         WriteDateTimeField(int nYear, int nMonth, int nDay,
                                    int nHour, int nMinute, int nSecond, int nMS,
                                    TABINDFile *poINDFile, int nIndexNo);
 
@@ -1818,7 +1901,7 @@ class TABDATFile
  *                      class TABRelation
  *
  * Class that maintains a relation between 2 tables through a field
- * in each table (the SQL "where table1.field1=table2.field2" found in 
+ * in each table (the SQL "where table1.field1=table2.field2" found in
  * TABView datasets).
  *
  * An instance of this class is used to read data records from the
@@ -1834,7 +1917,7 @@ class TABRelation
     char        *m_pszMainFieldName;
     int         m_nMainFieldNo;
 
-    /* Information about the related table.  
+    /* Information about the related table.
      * NOTE: The related field MUST be indexed.
      */
     TABFile     *m_poRelTable;
@@ -1895,7 +1978,7 @@ class TABRelation
 /*---------------------------------------------------------------------
  *                      class MIDDATAFile
  *
- * Class to handle a file pointer with a copy of the latest readed line
+ * Class to handle a file pointer with a copy of the latest read line.
  *
  *--------------------------------------------------------------------*/
 
@@ -1951,11 +2034,10 @@ class MIDDATAFile
                         Function prototypes
  =====================================================================*/
 
-TABRawBinBlock *TABCreateMAPBlockFromFile(VSILFILE *fpSrc, int nOffset, 
-                                          int nSize, 
+TABRawBinBlock *TABCreateMAPBlockFromFile(VSILFILE *fpSrc, int nOffset,
+                                          int nSize,
                                           GBool bHardBlockSize = TRUE,
                                           TABAccess eAccessMode = TABRead);
 
 
-#endif /* _MITAB_PRIV_H_INCLUDED_ */
-
+#endif /* MITAB_PRIV_H_INCLUDED_ */
diff --git a/ogr/ogrsf_frmts/mitab/mitab_rawbinblock.cpp b/ogr/ogrsf_frmts/mitab/mitab_rawbinblock.cpp
index 71afe0a..6f7b4f7 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_rawbinblock.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_rawbinblock.cpp
@@ -18,16 +18,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -95,8 +95,8 @@ TABRawBinBlock::TABRawBinBlock(TABAccess eAccessMode /*= TABRead*/,
 
     m_bModified = FALSE;
 
-    m_eAccess = eAccessMode; 
-
+    m_eAccess = eAccessMode;
+    m_nBlockType = 0;
 }
 
 /**********************************************************************
@@ -116,17 +116,17 @@ TABRawBinBlock::~TABRawBinBlock()
  *
  * Load data from the specified file location and initialize the block.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
-int     TABRawBinBlock::ReadFromFile(VSILFILE *fpSrc, int nOffset, 
+int     TABRawBinBlock::ReadFromFile(VSILFILE *fpSrc, int nOffset,
                                      int nSize)
 {
     GByte *pabyBuf;
 
     if (fpSrc == NULL || nSize == 0)
     {
-        CPLError(CE_Failure, CPLE_AssertionFailed, 
+        CPLError(CE_Failure, CPLE_AssertionFailed,
                  "TABRawBinBlock::ReadFromFile(): Assertion Failed!");
         return -1;
     }
@@ -139,7 +139,7 @@ int     TABRawBinBlock::ReadFromFile(VSILFILE *fpSrc, int nOffset,
     m_nFileOffset = nOffset;
     m_nCurPos = 0;
     m_bModified = FALSE;
-    
+
     /*----------------------------------------------------------------
      * Alloc a buffer to contain the data
      *---------------------------------------------------------------*/
@@ -149,7 +149,7 @@ int     TABRawBinBlock::ReadFromFile(VSILFILE *fpSrc, int nOffset,
      * Read from the file
      *---------------------------------------------------------------*/
     if (VSIFSeekL(fpSrc, nOffset, SEEK_SET) != 0 ||
-        (m_nSizeUsed = VSIFReadL(pabyBuf, sizeof(GByte), nSize, fpSrc) ) == 0 ||
+        (m_nSizeUsed = static_cast<int>(VSIFReadL(pabyBuf, sizeof(GByte), nSize, fpSrc)) ) == 0 ||
         (m_bHardBlockSize && m_nSizeUsed != nSize ) )
     {
         CPLError(CE_Failure, CPLE_FileIO,
@@ -162,7 +162,7 @@ int     TABRawBinBlock::ReadFromFile(VSILFILE *fpSrc, int nOffset,
     /*----------------------------------------------------------------
      * Init block with the data we just read
      *---------------------------------------------------------------*/
-    return InitBlockFromData(pabyBuf, nSize, m_nSizeUsed, 
+    return InitBlockFromData(pabyBuf, nSize, m_nSizeUsed,
                              FALSE, fpSrc, nOffset);
 }
 
@@ -170,7 +170,7 @@ int     TABRawBinBlock::ReadFromFile(VSILFILE *fpSrc, int nOffset,
 /**********************************************************************
  *                   TABRawBinBlock::CommitToFile()
  *
- * Commit the current state of the binary block to the file to which 
+ * Commit the current state of the binary block to the file to which
  * it has been previously attached.
  *
  * Derived classes may want to (optionally) reimplement this method if
@@ -180,7 +180,7 @@ int     TABRawBinBlock::ReadFromFile(VSILFILE *fpSrc, int nOffset,
  * the specified size is always written, otherwise only the number of
  * used bytes in the block will be written to disk.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
 int     TABRawBinBlock::CommitToFile()
@@ -190,7 +190,7 @@ int     TABRawBinBlock::CommitToFile()
     if (m_fp == NULL || m_nBlockSize <= 0 || m_pabyBuf == NULL ||
         m_nFileOffset < 0)
     {
-        CPLError(CE_Failure, CPLE_AssertionFailed, 
+        CPLError(CE_Failure, CPLE_AssertionFailed,
         "TABRawBinBlock::CommitToFile(): Block has not been initialized yet!");
         return -1;
     }
@@ -202,12 +202,12 @@ int     TABRawBinBlock::CommitToFile()
         return 0;
 
     /*----------------------------------------------------------------
-     * Move the output file pointer to the right position... 
+     * Move the output file pointer to the right position...
      *---------------------------------------------------------------*/
     if (VSIFSeekL(m_fp, m_nFileOffset, SEEK_SET) != 0)
     {
         /*------------------------------------------------------------
-         * Moving pointer failed... we may need to pad with zeros if 
+         * Moving pointer failed... we may need to pad with zeros if
          * block destination is beyond current end of file.
          *-----------------------------------------------------------*/
         int nCurPos;
@@ -231,7 +231,7 @@ int     TABRawBinBlock::CommitToFile()
                 nCurPos++;
             }
         }
-            
+
         if (nCurPos != m_nFileOffset)
             nStatus = -1; // Error message will follow below
 
@@ -244,8 +244,8 @@ int     TABRawBinBlock::CommitToFile()
      * we write only the part of the block that was used.
      *---------------------------------------------------------------*/
     int numBytesToWrite = m_bHardBlockSize?m_nBlockSize:m_nSizeUsed;
-    
-    /*CPLDebug("MITAB", "Commiting to offset %d", m_nFileOffset);*/
+
+    /*CPLDebug("MITAB", "Committing to offset %d", m_nFileOffset);*/
 
     if (nStatus != 0 ||
         VSIFWriteL(m_pabyBuf,sizeof(GByte),
@@ -273,7 +273,7 @@ int     TABRawBinBlock::CommitToFile()
  *
  * Commit current block to file using block type 4 (garbage block)
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
 int     TABRawBinBlock::CommitAsDeleted(GInt32 nNextBlockPtr)
@@ -284,7 +284,7 @@ int     TABRawBinBlock::CommitAsDeleted(GInt32 nNextBlockPtr)
 
     if ( m_pabyBuf == NULL )
     {
-        CPLError(CE_Failure, CPLE_AssertionFailed, 
+        CPLError(CE_Failure, CPLE_AssertionFailed,
                  "CommitAsDeleted(): Block has not been initialized yet!");
         return -1;
     }
@@ -305,7 +305,7 @@ int     TABRawBinBlock::CommitAsDeleted(GInt32 nNextBlockPtr)
     if (nStatus == 0)
     {
 #ifdef DEBUG_VERBOSE
-        CPLDebug("MITAB", "Commiting GARBAGE block to offset %d", m_nFileOffset);
+        CPLDebug("MITAB", "Committing GARBAGE block to offset %d", m_nFileOffset);
 #endif
         nStatus = TABRawBinBlock::CommitToFile();
         m_nSizeUsed = 0;
@@ -321,29 +321,29 @@ int     TABRawBinBlock::CommitAsDeleted(GInt32 nNextBlockPtr)
  *
  * Calling ReadFromFile() will automatically call InitBlockFromData() to
  * complete the initialization of the block after the data is read from the
- * file.  Derived classes should implement their own version of 
+ * file.  Derived classes should implement their own version of
  * InitBlockFromData() if they need specific initialization... in this
- * case the derived InitBlockFromData() should call 
+ * case the derived InitBlockFromData() should call
  * TABRawBinBlock::InitBlockFromData() before doing anything else.
  *
  * By default, the buffer will be copied, but if bMakeCopy = FALSE then
  * it won't be copied, and the object will keep a reference to the
  * user's buffer... and this object will eventually free the user's buffer.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
-int     TABRawBinBlock::InitBlockFromData(GByte *pabyBuf, 
-                                          int nBlockSize, int nSizeUsed, 
+int     TABRawBinBlock::InitBlockFromData(GByte *pabyBuf,
+                                          int nBlockSize, int nSizeUsed,
                                           GBool bMakeCopy /* = TRUE */,
-                                          VSILFILE *fpSrc /* = NULL */, 
+                                          VSILFILE *fpSrc /* = NULL */,
                                           int nOffset /* = 0 */)
 {
     m_fp = fpSrc;
     m_nFileOffset = nOffset;
     m_nCurPos = 0;
     m_bModified = FALSE;
-    
+
     /*----------------------------------------------------------------
      * Alloc or realloc the buffer to contain the data if necessary
      *---------------------------------------------------------------*/
@@ -381,17 +381,17 @@ int     TABRawBinBlock::InitBlockFromData(GByte *pabyBuf,
 /**********************************************************************
  *                   TABRawBinBlock::InitNewBlock()
  *
- * Initialize the block so that it knows to which file is is attached,
+ * Initialize the block so that it knows to which file is attached,
  * its block size, etc.
  *
  * This is an alternative to calling ReadFromFile() or InitBlockFromData()
  * that puts the block in a stable state without loading any initial
  * data in it.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
-int     TABRawBinBlock::InitNewBlock(VSILFILE *fpSrc, int nBlockSize, 
+int     TABRawBinBlock::InitNewBlock(VSILFILE *fpSrc, int nBlockSize,
                                      int nFileOffset /* = 0*/)
 {
     m_fp = fpSrc;
@@ -404,7 +404,7 @@ int     TABRawBinBlock::InitNewBlock(VSILFILE *fpSrc, int nBlockSize,
         m_nFileOffset = nFileOffset;
     else
         m_nFileOffset = 0;
-    
+
     if( m_fp != NULL && m_nFileSize < 0 && m_eAccess == TABReadWrite )
     {
         int nCurPos = (int)VSIFTellL(m_fp);
@@ -416,7 +416,8 @@ int     TABRawBinBlock::InitNewBlock(VSILFILE *fpSrc, int nBlockSize,
     m_nBlockType = -1;
 
     m_pabyBuf = (GByte*)CPLRealloc(m_pabyBuf, m_nBlockSize*sizeof(GByte));
-    memset(m_pabyBuf, 0, m_nBlockSize);
+    if( m_nBlockSize )
+        memset(m_pabyBuf, 0, m_nBlockSize);
 
     return 0;
 }
@@ -427,7 +428,7 @@ int     TABRawBinBlock::InitNewBlock(VSILFILE *fpSrc, int nBlockSize,
  *
  * Return the block type for the current object.
  *
- * Returns a block type >= 0 if succesful or -1 if an error happened, in 
+ * Returns a block type >= 0 if successful or -1 if an error happened, in
  * which case  CPLError() will have been called.
  **********************************************************************/
 int     TABRawBinBlock::GetBlockType()
@@ -442,7 +443,7 @@ int     TABRawBinBlock::GetBlockType()
     if (m_nBlockType > TABMAP_LAST_VALID_BLOCK_TYPE)
     {
         CPLError(CE_Failure, CPLE_NotSupported,
-                 "GetBlockType(): Unsupported block type %d.", 
+                 "GetBlockType(): Unsupported block type %d.",
                  m_nBlockType);
         return -1;
     }
@@ -453,10 +454,10 @@ int     TABRawBinBlock::GetBlockType()
 /**********************************************************************
  *                   TABRawBinBlock::GotoByteInBlock()
  *
- * Move the block pointer to the specified position relative to the 
+ * Move the block pointer to the specified position relative to the
  * beginning of the block.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
 int     TABRawBinBlock::GotoByteInBlock(int nOffset)
@@ -477,7 +478,7 @@ int     TABRawBinBlock::GotoByteInBlock(int nOffset)
     }
 
     m_nCurPos = nOffset;
-    
+
     m_nSizeUsed = MAX(m_nSizeUsed, m_nCurPos);
 
     return 0;
@@ -489,7 +490,7 @@ int     TABRawBinBlock::GotoByteInBlock(int nOffset)
  * Move the block pointer by the specified number of bytes relative
  * to its current position.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
 int     TABRawBinBlock::GotoByteRel(int nOffset)
@@ -500,13 +501,13 @@ int     TABRawBinBlock::GotoByteRel(int nOffset)
 /**********************************************************************
  *                   TABRawBinBlock::GotoByteInFile()
  *
- * Move the block pointer to the specified position relative to the 
- * beginning of the file.  
- * 
+ * Move the block pointer to the specified position relative to the
+ * beginning of the file.
+ *
  * In read access, the current block may be reloaded to contain a right
  * block of binary data if necessary.
  *
- * In write mode, the current block may automagically be committed to 
+ * In write mode, the current block may automagically be committed to
  * disk and a new block initialized if necessary.
  *
  * bForceReadFromFile is used in write mode to read the new block data from
@@ -515,17 +516,17 @@ int     TABRawBinBlock::GotoByteRel(int nOffset)
  *
  * bOffsetIsEndOfData is set to TRUE to indicate that the nOffset
  * to which we are attempting to go is the end of the used data in this
- * block (we are positioninig ourselves to append data), so if the nOffset 
- * corresponds to the beginning of a block then we should really 
- * be positioning ourselves at the end of the block that ends at this 
- * address instead of at the beginning of the blocks that starts at this 
+ * block (we are positioning ourselves to append data), so if the nOffset
+ * corresponds to the beginning of a block then we should really
+ * be positioning ourselves at the end of the block that ends at this
+ * address instead of at the beginning of the blocks that starts at this
  * address. This case can happen when going back and forth to write collection
  * objects to a Coordblock and is documented in bug 1657.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
-int     TABRawBinBlock::GotoByteInFile(int nOffset, 
+int     TABRawBinBlock::GotoByteInFile(int nOffset,
                                        GBool bForceReadFromFile /*=FALSE*/,
                                        GBool bOffsetIsEndOfData /*=FALSE*/)
 {
@@ -581,10 +582,10 @@ int     TABRawBinBlock::GotoByteInFile(int nOffset,
              * yet on disk */
             nNewBlockPtr -= m_nBlockSize;
 
-            if ( (nOffset < m_nFileOffset || 
+            if ( (nOffset < m_nFileOffset ||
                   nOffset > m_nFileOffset+m_nBlockSize) &&
                  (CommitToFile() != 0 ||
-                  (!bForceReadFromFile && 
+                  (!bForceReadFromFile &&
                    InitNewBlock(m_fp, m_nBlockSize, nNewBlockPtr) != 0) ||
                   (bForceReadFromFile &&
                    ReadFromFile(m_fp, nNewBlockPtr, m_nBlockSize) != 0) )  )
@@ -599,7 +600,7 @@ int     TABRawBinBlock::GotoByteInFile(int nOffset,
                 nOffset < m_nFileSize )
             {
                 bForceReadFromFile = TRUE;
-                if ( !(nOffset < m_nFileOffset || 
+                if ( !(nOffset < m_nFileOffset ||
                        nOffset >= m_nFileOffset+m_nBlockSize) )
                 {
                     if ( (nOffset<m_nFileOffset || nOffset>=m_nFileOffset+m_nSizeUsed) &&
@@ -612,10 +613,10 @@ int     TABRawBinBlock::GotoByteInFile(int nOffset,
                 }
             }
 
-            if ( (nOffset < m_nFileOffset || 
+            if ( (nOffset < m_nFileOffset ||
                   nOffset >= m_nFileOffset+m_nBlockSize) &&
                  (CommitToFile() != 0 ||
-                  (!bForceReadFromFile && 
+                  (!bForceReadFromFile &&
                    InitNewBlock(m_fp, m_nBlockSize, nNewBlockPtr) != 0) ||
                   (bForceReadFromFile &&
                    ReadFromFile(m_fp, nNewBlockPtr, m_nBlockSize) != 0) )  )
@@ -644,8 +645,8 @@ int     TABRawBinBlock::GotoByteInFile(int nOffset,
  *                   TABRawBinBlock::SetFirstBlockPtr()
  *
  * Set the position in the file at which the first block starts.
- * This value will usually be the header size and needs to be specified 
- * only if the header size is different from the other blocks size. 
+ * This value will usually be the header size and needs to be specified
+ * only if the header size is different from the other blocks size.
  *
  * This value will be used by GotoByteInFile() to properly align the data
  * blocks that it loads automatically when a requested position is outside
@@ -698,10 +699,10 @@ int     TABRawBinBlock::GetCurAddress()
  * the user's buffer pointed by pabyDstBuf.
  *
  * Passing pabyDstBuf = NULL will only move the read pointer by the
- * specified number of bytes as if the copy had happened... but it 
+ * specified number of bytes as if the copy had happened... but it
  * won't crash.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
 int     TABRawBinBlock::ReadBytes(int numBytes, GByte *pabyDstBuf)
@@ -737,23 +738,23 @@ int     TABRawBinBlock::ReadBytes(int numBytes, GByte *pabyDstBuf)
 /**********************************************************************
  *                   TABRawBinBlock::Read<datatype>()
  *
- * MapInfo files are binary files with LSB first (Intel) byte 
+ * MapInfo files are binary files with LSB first (Intel) byte
  * ordering.  The following functions will read from the input file
- * and return a value with the bytes ordered properly for the current 
+ * and return a value with the bytes ordered properly for the current
  * platform.
  **********************************************************************/
 GByte  TABRawBinBlock::ReadByte()
 {
-    GByte byValue;
+    GByte byValue = 0;
 
-    ReadBytes(1, (GByte*)(&byValue));
+    ReadBytes(1, &byValue);
 
     return byValue;
 }
 
 GInt16  TABRawBinBlock::ReadInt16()
 {
-    GInt16 n16Value;
+    GInt16 n16Value = 0;
 
     ReadBytes(2, (GByte*)(&n16Value));
 
@@ -766,7 +767,7 @@ GInt16  TABRawBinBlock::ReadInt16()
 
 GInt32  TABRawBinBlock::ReadInt32()
 {
-    GInt32 n32Value;
+    GInt32 n32Value = 0;
 
     ReadBytes(4, (GByte*)(&n32Value));
 
@@ -779,19 +780,19 @@ GInt32  TABRawBinBlock::ReadInt32()
 
 float   TABRawBinBlock::ReadFloat()
 {
-    float fValue;
+    float fValue = 0.0f;
 
     ReadBytes(4, (GByte*)(&fValue));
 
 #ifdef CPL_MSB
-    *(GUInt32*)(&fValue) = CPL_SWAP32(*(GUInt32*)(&fValue));
+    CPL_LSBPTR32(&fValue);
 #endif
     return fValue;
 }
 
 double  TABRawBinBlock::ReadDouble()
 {
-    double dValue;
+    double dValue = 0.0;
 
     ReadBytes(8, (GByte*)(&dValue));
 
@@ -813,13 +814,13 @@ double  TABRawBinBlock::ReadDouble()
  * written to the file until WriteToFile() is called.
  *
  * Passing pabySrcBuf = NULL will only move the write pointer by the
- * specified number of bytes as if the copy had happened... but it 
+ * specified number of bytes as if the copy had happened... but it
  * won't crash.
  *
- * Returns 0 if succesful or -1 if an error happened, in which case 
+ * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
-int  TABRawBinBlock::WriteBytes(int nBytesToWrite, GByte *pabySrcBuf)
+int  TABRawBinBlock::WriteBytes(int nBytesToWrite, const GByte *pabySrcBuf)
 {
     /*----------------------------------------------------------------
      * Make sure block is initialized with Write access and that the
@@ -867,13 +868,13 @@ int  TABRawBinBlock::WriteBytes(int nBytesToWrite, GByte *pabySrcBuf)
 /**********************************************************************
  *                    TABRawBinBlock::Write<datatype>()
  *
- * Arc/Info files are binary files with MSB first (Motorola) byte 
+ * Arc/Info files are binary files with MSB first (Motorola) byte
  * ordering.  The following functions will reorder the byte for the
  * value properly and write that to the output file.
  *
- * If a problem happens, then CPLError() will be called and 
- * CPLGetLastErrNo() can be used to test if a write operation was 
- * succesful.
+ * If a problem happens, then CPLError() will be called and
+ * CPLGetLastErrNo() can be used to test if a write operation was
+ * successful.
  **********************************************************************/
 int  TABRawBinBlock::WriteByte(GByte byValue)
 {
@@ -901,7 +902,7 @@ int  TABRawBinBlock::WriteInt32(GInt32 n32Value)
 int  TABRawBinBlock::WriteFloat(float fValue)
 {
 #ifdef CPL_MSB
-    *(GUInt32*)(&fValue) = CPL_SWAP32(*(GUInt32*)(&fValue));
+    CPL_LSBPTR32(&fValue);
 #endif
 
     return WriteBytes(4, (GByte*)&fValue);
@@ -920,12 +921,12 @@ int  TABRawBinBlock::WriteDouble(double dValue)
 /**********************************************************************
  *                    TABRawBinBlock::WriteZeros()
  *
- * Write a number of zeros (sepcified in bytes) at the current position 
+ * Write a number of zeros (specified in bytes) at the current position
  * in the file.
  *
- * If a problem happens, then CPLError() will be called and 
- * CPLGetLastErrNo() can be used to test if a write operation was 
- * succesful.
+ * If a problem happens, then CPLError() will be called and
+ * CPLGetLastErrNo() can be used to test if a write operation was
+ * successful.
  **********************************************************************/
 int  TABRawBinBlock::WriteZeros(int nBytesToWrite)
 {
@@ -933,7 +934,7 @@ int  TABRawBinBlock::WriteZeros(int nBytesToWrite)
     int i;
     int nStatus = 0;
 
-    /* Write by 8 bytes chunks.  The last chunk may be less than 8 bytes 
+    /* Write by 8 bytes chunks.  The last chunk may be less than 8 bytes
      */
     for(i=0; nStatus == 0 && i< nBytesToWrite; i+=8)
     {
@@ -949,9 +950,9 @@ int  TABRawBinBlock::WriteZeros(int nBytesToWrite)
  * Write a string and pad the end of the field (up to nFieldSize) with
  * spaces number of spaces at the current position in the file.
  *
- * If a problem happens, then CPLError() will be called and 
- * CPLGetLastErrNo() can be used to test if a write operation was 
- * succesful.
+ * If a problem happens, then CPLError() will be called and
+ * CPLGetLastErrNo() can be used to test if a write operation was
+ * successful.
  **********************************************************************/
 int  TABRawBinBlock::WritePaddedString(int nFieldSize, const char *pszString)
 {
@@ -959,7 +960,7 @@ int  TABRawBinBlock::WritePaddedString(int nFieldSize, const char *pszString)
     int i, nLen, numSpaces;
     int nStatus = 0;
 
-    nLen = strlen(pszString);
+    nLen = static_cast<int>(strlen(pszString));
     nLen = MIN(nLen, nFieldSize);
     numSpaces = nFieldSize - nLen;
 
@@ -997,7 +998,7 @@ void TABRawBinBlock::Dump(FILE *fpOut /*=NULL*/)
     {
         if( m_nBlockType == TABMAP_GARB_BLOCK )
         {
-            fprintf(fpOut,"Garbage Block (type %d) at offset %d.\n", 
+            fprintf(fpOut,"Garbage Block (type %d) at offset %d.\n",
                                                     m_nBlockType, m_nFileOffset);
             int nNextGarbageBlock;
             memcpy(&nNextGarbageBlock, m_pabyBuf + 2, 4);
@@ -1040,9 +1041,9 @@ void TABRawBinBlock::DumpBytes(GInt32 nValue, int nOffset /*=0*/,
 
     anVal[0] = anVal[1] = 0;
 
-    /* For double precision values, we only use the first half 
+    /* For double precision values, we only use the first half
      * of the height bytes... and leave the other 4 bytes as zeros!
-     * It's a bit of a hack, but it seems to be enough for the 
+     * It's a bit of a hack, but it seems to be enough for the
      * precision of the values we print!
      */
 #ifdef CPL_MSB
@@ -1070,14 +1071,14 @@ void TABRawBinBlock::DumpBytes(GInt32 nValue, int nOffset /*=0*/,
 /**********************************************************************
  *                   TABCreateMAPBlockFromFile()
  *
- * Load data from the specified file location and create and initialize 
+ * Load data from the specified file location and create and initialize
  * a TABMAP*Block of the right type to handle it.
  *
- * Returns the new object if succesful or NULL if an error happened, in 
+ * Returns the new object if successful or NULL if an error happened, in
  * which case CPLError() will have been called.
  **********************************************************************/
-TABRawBinBlock *TABCreateMAPBlockFromFile(VSILFILE *fpSrc, int nOffset, 
-                                          int nSize, 
+TABRawBinBlock *TABCreateMAPBlockFromFile(VSILFILE *fpSrc, int nOffset,
+                                          int nSize,
                                           GBool bHardBlockSize /*= TRUE */,
                                           TABAccess eAccessMode /*= TABRead*/)
 {
@@ -1086,7 +1087,7 @@ TABRawBinBlock *TABCreateMAPBlockFromFile(VSILFILE *fpSrc, int nOffset,
 
     if (fpSrc == NULL || nSize == 0)
     {
-        CPLError(CE_Failure, CPLE_AssertionFailed, 
+        CPLError(CE_Failure, CPLE_AssertionFailed,
                  "TABCreateMAPBlockFromFile(): Assertion Failed!");
         return NULL;
     }
@@ -1111,7 +1112,7 @@ TABRawBinBlock *TABCreateMAPBlockFromFile(VSILFILE *fpSrc, int nOffset,
 
     /*----------------------------------------------------------------
      * Create an object of the right type
-     * Header block is different: it does not start with the object 
+     * Header block is different: it does not start with the object
      * type byte but it is always the first block in a file
      *---------------------------------------------------------------*/
     if (nOffset == 0)
@@ -1144,7 +1145,7 @@ TABRawBinBlock *TABCreateMAPBlockFromFile(VSILFILE *fpSrc, int nOffset,
     /*----------------------------------------------------------------
      * Init new object with the data we just read
      *---------------------------------------------------------------*/
-    if (poBlock->InitBlockFromData(pabyBuf, nSize, nSize, 
+    if (poBlock->InitBlockFromData(pabyBuf, nSize, nSize,
                                    FALSE, fpSrc, nOffset) != 0)
     {
         // Some error happened... and CPLError() has been called
@@ -1313,7 +1314,7 @@ GInt32 TABBinBlockManager::GetFirstGarbageBlock()
  *
  * Return address of the block at the head of the list of garbage blocks
  * and remove that block from the list.
- * Retuns 0 if the list is empty.
+ * Returns 0 if the list is empty.
  **********************************************************************/
 GInt32 TABBinBlockManager::PopGarbageBlock()
 {
diff --git a/ogr/ogrsf_frmts/mitab/mitab_spatialref.cpp b/ogr/ogrsf_frmts/mitab/mitab_spatialref.cpp
index d8e5ab2..fb433af 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_spatialref.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_spatialref.cpp
@@ -17,16 +17,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -47,7 +47,7 @@
  * Cleanup Win32 Compile Warnings (GDAL bug #2930)
  *
  * Revision 1.50  2010-07-05 17:20:14  aboudreault
- * Added Krovak projection suppoprt (bug 2230)
+ * Added Krovak projection support (bug 2230)
  *
  * Revision 1.49  2009-10-15 16:16:37  fwarmerdam
  * add the default EPSG/OGR name for new zealand datums (gdal #3187)
@@ -91,7 +91,7 @@
  * Revision 1.37  2002/10/15 14:33:30  warmerda
  * Added untested support in mitab_spatialref.cpp, and mitab_coordsys.cpp for
  * projections Regional Mercator (26), Polyconic (27), Azimuthal Equidistant -
- * All origin latitudes (28), and Lambert Azimuthal Equal Area - any aspect 
+ * All origin latitudes (28), and Lambert Azimuthal Equal Area - any aspect
  * (29).
  *
  * Revision 1.36  2002/09/05 15:38:16  warmerda
@@ -144,7 +144,7 @@
  * Added new datums/ellipsoid from MapInfo V6.0
  *
  * Revision 1.20  2000/09/28 16:39:44  warmerda
- * avoid warnings for unused, and unitialized variables
+ * Avoid warnings for unused, and uninitialized variables
  *
  * Revision 1.19  2000/02/07 17:43:17  daniel
  * Fixed offset in parsing of custom datum string in SetSpatialRef()
@@ -406,7 +406,7 @@ const MapInfoDatumInfo asDatumInfoList[] =
 { 6610, 1017,"Xian 1980",                  53, 24, -123, -94, -0.02, -0.25, 0.13, 1.1, 0},
 { 0,    1018,"Lithuanian Pulkovo 1942",	   4, -40.59527, -18.54979, -69.33956, -2.508, -1.8319, 2.6114, -4.2991, 0},
 { 0,    1019,"Belgian 1972 7 Parameter",   4, -99.059, 53.322, -112.486, -0.419, 0.83, -1.885, 0.999999, 0},
-{ 6818, 1020,"S-JTSK with Ferro prime meridian", 10, 589, 76, 480, 0, 0, 0, 0, -17.666666666667}, 
+{ 6818, 1020,"S-JTSK with Ferro prime meridian", 10, 589, 76, 480, 0, 0, 0, 0, -17.666666666667},
 
 { -1,   -1, NULL,                          0, 0, 0, 0, 0, 0, 0, 0, 0}
 };
@@ -820,7 +820,7 @@ OGRSpatialReference *TABFile::GetSpatialRef()
      *----------------------------------------------------------------*/
     if (m_poSpatialRef != NULL)
         return m_poSpatialRef;
-    
+
 
     /*-----------------------------------------------------------------
      * Fetch the parameters from the header.
@@ -835,7 +835,7 @@ OGRSpatialReference *TABFile::GetSpatialRef()
                  "GetSpatialRef() failed reading projection parameters.");
         return NULL;
     }
-    
+
     m_poSpatialRef = GetSpatialRefFromTABProj(sTABProj);
     return m_poSpatialRef;
 }
@@ -864,57 +864,57 @@ OGRSpatialReference* TABFile::GetSpatialRefFromTABProj(const TABProjInfo& sTABPr
         pszUnitsName = "Kilometer";
         pszUnitsConv = "1000.0";
         break;
-            
+
       case 2:
         pszUnitsName = "IINCH";
         pszUnitsConv = "0.0254";
         break;
-            
+
       case 3:
         pszUnitsName = SRS_UL_FOOT;
         pszUnitsConv = SRS_UL_FOOT_CONV;
         break;
-            
+
       case 4:
         pszUnitsName = "IYARD";
         pszUnitsConv = "0.9144";
         break;
-            
+
       case 5:
         pszUnitsName = "Millimeter";
         pszUnitsConv = "0.001";
         break;
-            
+
       case 6:
         pszUnitsName = "Centimeter";
         pszUnitsConv = "0.01";
         break;
-            
+
       case 7:
         pszUnitsName = SRS_UL_METER;
         pszUnitsConv = "1.0";
         break;
-            
+
       case 8:
         pszUnitsName = SRS_UL_US_FOOT;
         pszUnitsConv = SRS_UL_US_FOOT_CONV;
         break;
-            
+
       case 9:
         pszUnitsName = SRS_UL_NAUTICAL_MILE;
         pszUnitsConv = SRS_UL_NAUTICAL_MILE_CONV;
         break;
-            
+
       case 30:
         pszUnitsName = SRS_UL_LINK;
         pszUnitsConv = SRS_UL_LINK_CONV;
         break;
-            
+
       case 31:
         pszUnitsName = SRS_UL_CHAIN;
         pszUnitsConv = SRS_UL_CHAIN_CONV;
         break;
-            
+
       case 32:
         pszUnitsName = SRS_UL_ROD;
         pszUnitsConv = SRS_UL_ROD_CONV;
@@ -1011,9 +1011,9 @@ OGRSpatialReference* TABFile::GetSpatialRefFromTABProj(const TABProjInfo& sTABPr
          *-------------------------------------------------------------*/
       case 7:
         poSpatialRef->SetHOM( sTABProj.adProjParams[1],
-                                sTABProj.adProjParams[0], 
+                                sTABProj.adProjParams[0],
                                 sTABProj.adProjParams[2],
-                                90.0, 
+                                90.0,
                                 sTABProj.adProjParams[3],
                                 sTABProj.adProjParams[4],
                                 sTABProj.adProjParams[5] );
@@ -1150,7 +1150,7 @@ OGRSpatialReference* TABFile::GetSpatialRefFromTABProj(const TABProjInfo& sTABPr
       case 17:
         poSpatialRef->SetGS( sTABProj.adProjParams[0], 0.0, 0.0 );
         break;
-        
+
         /*--------------------------------------------------------------
          * New Zealand Map Grid
          *-------------------------------------------------------------*/
@@ -1257,7 +1257,7 @@ OGRSpatialReference* TABFile::GetSpatialRefFromTABProj(const TABProjInfo& sTABPr
     if( sTABProj.nProjId != 1 && poSpatialRef->GetRoot() != NULL )
     {
         OGR_SRSNode     *poUnits = new OGR_SRSNode("UNIT");
-        
+
         poSpatialRef->GetRoot()->AddChild(poUnits);
 
         poUnits->AddChild( new OGR_SRSNode( pszUnitsName ) );
@@ -1266,7 +1266,7 @@ OGRSpatialReference* TABFile::GetSpatialRefFromTABProj(const TABProjInfo& sTABPr
 
     /*-----------------------------------------------------------------
      * Local (nonearth) coordinate systems have no Geographic relationship
-     * so we just return from here. 
+     * so we just return from here.
      *----------------------------------------------------------------*/
     if( sTABProj.nProjId == 0 )
         return poSpatialRef;
@@ -1290,9 +1290,9 @@ OGRSpatialReference* TABFile::GetSpatialRefFromTABProj(const TABProjInfo& sTABPr
          iDatumInfo++ )
     {
         psDatumInfo = asDatumInfoList + iDatumInfo;
-        
+
         if( TAB_EQUAL(psDatumInfo->nEllipsoid, sTABProj.nEllipsoidId) &&
-            ((sTABProj.nDatumId > 0 && 
+            ((sTABProj.nDatumId > 0 &&
               sTABProj.nDatumId == psDatumInfo->nMapInfoDatumID) ||
              (sTABProj.nDatumId <= 0
               && TAB_EQUAL(psDatumInfo->dfShiftX, sTABProj.dDatumShiftX)
@@ -1316,20 +1316,20 @@ OGRSpatialReference* TABFile::GetSpatialRefFromTABProj(const TABProjInfo& sTABPr
             && sTABProj.adDatumParams[3] == 0.0
             && sTABProj.adDatumParams[4] == 0.0 )
         {
-            sprintf( szDatumName,
-                     "MIF 999,%d,%.15g,%.15g,%.15g", 
+            snprintf( szDatumName, sizeof(szDatumName),
+                     "MIF 999,%d,%.15g,%.15g,%.15g",
                      sTABProj.nEllipsoidId,
-                     sTABProj.dDatumShiftX, 
-                     sTABProj.dDatumShiftY, 
+                     sTABProj.dDatumShiftX,
+                     sTABProj.dDatumShiftY,
                      sTABProj.dDatumShiftZ );
         }
         else
         {
-            sprintf( szDatumName,
+            snprintf( szDatumName, sizeof(szDatumName),
                      "MIF 9999,%d,%.15g,%.15g,%.15g,%.15g,%.15g,%.15g,%.15g,%.15g",
                      sTABProj.nEllipsoidId,
-                     sTABProj.dDatumShiftX, 
-                     sTABProj.dDatumShiftY, 
+                     sTABProj.dDatumShiftX,
+                     sTABProj.dDatumShiftY,
                      sTABProj.dDatumShiftZ,
                      sTABProj.adDatumParams[0],
                      sTABProj.adDatumParams[1],
@@ -1340,8 +1340,8 @@ OGRSpatialReference* TABFile::GetSpatialRefFromTABProj(const TABProjInfo& sTABPr
     }
     else if( strlen(psDatumInfo->pszOGCDatumName) > 0 )
     {
-        strncpy( szDatumName, psDatumInfo->pszOGCDatumName,
-                 sizeof(szDatumName) );
+        CPLStrlcpy( szDatumName, psDatumInfo->pszOGCDatumName,
+                    sizeof(szDatumName) );
 
         /* For LCC, standard parallel 1 and 2 can be switched indifferently */
         /* So the MapInfo order and the EPSG order are not generally identical */
@@ -1383,7 +1383,7 @@ OGRSpatialReference* TABFile::GetSpatialRefFromTABProj(const TABProjInfo& sTABPr
     }
     else
     {
-        sprintf( szDatumName, "MIF %d", psDatumInfo->nMapInfoDatumID );
+        snprintf( szDatumName, sizeof(szDatumName), "MIF %d", psDatumInfo->nMapInfoDatumID );
     }
 
     /*-----------------------------------------------------------------
@@ -1416,14 +1416,14 @@ OGRSpatialReference* TABFile::GetSpatialRefFromTABProj(const TABProjInfo& sTABPr
      *----------------------------------------------------------------*/
     double      dfPMOffset = 0.0;
     const char *pszPMName = "Greenwich";
-    
+
     if( /*sTABProj.nDatumId == 9999 ||*/ sTABProj.adDatumParams[4] != 0.0 )
     {
         dfPMOffset = sTABProj.adDatumParams[4];
 
         pszPMName = "non-Greenwich";
     }
-                    
+
     /*-----------------------------------------------------------------
      * Create a GEOGCS definition.
      *----------------------------------------------------------------*/
@@ -1437,7 +1437,7 @@ OGRSpatialReference* TABFile::GetSpatialRefFromTABProj(const TABProjInfo& sTABPr
 
     if( psDatumInfo != NULL )
     {
-        poSpatialRef->SetTOWGS84( psDatumInfo->dfShiftX, 
+        poSpatialRef->SetTOWGS84( psDatumInfo->dfShiftX,
                                     psDatumInfo->dfShiftY,
                                     psDatumInfo->dfShiftZ,
                                     psDatumInfo->dfDatumParm0 == 0 ? 0 : -psDatumInfo->dfDatumParm0, /* avoids 0 to be transformed into -0 */
@@ -1447,19 +1447,19 @@ OGRSpatialReference* TABFile::GetSpatialRefFromTABProj(const TABProjInfo& sTABPr
     }
     else
     {
-        poSpatialRef->SetTOWGS84( sTABProj.dDatumShiftX, 
-                                    sTABProj.dDatumShiftY, 
-                                    sTABProj.dDatumShiftZ, 
-                                    sTABProj.adDatumParams[0] == 0 ? 0 : -sTABProj.adDatumParams[0], 
-                                    sTABProj.adDatumParams[1] == 0 ? 0 : -sTABProj.adDatumParams[1], 
-                                    sTABProj.adDatumParams[2] == 0 ? 0 : -sTABProj.adDatumParams[2], 
+        poSpatialRef->SetTOWGS84( sTABProj.dDatumShiftX,
+                                    sTABProj.dDatumShiftY,
+                                    sTABProj.dDatumShiftZ,
+                                    sTABProj.adDatumParams[0] == 0 ? 0 : -sTABProj.adDatumParams[0],
+                                    sTABProj.adDatumParams[1] == 0 ? 0 : -sTABProj.adDatumParams[1],
+                                    sTABProj.adDatumParams[2] == 0 ? 0 : -sTABProj.adDatumParams[2],
                                     sTABProj.adDatumParams[3] );
     }
 
     /*-----------------------------------------------------------------
      * Special case for Google Mercator (datum=157, ellipse=54, gdal #4115)
      *----------------------------------------------------------------*/
-    if( sTABProj.nProjId == 10 
+    if( sTABProj.nProjId == 10
         && sTABProj.nDatumId == 157
         && sTABProj.nEllipsoidId == 54 )
     {
@@ -1522,13 +1522,13 @@ int TABFile::SetSpatialRef(OGRSpatialReference *poSpatialRef)
      *----------------------------------------------------------------*/
     if (m_poSpatialRef && m_poSpatialRef->Dereference() == 0)
         delete m_poSpatialRef;
-    
+
     m_poSpatialRef = poSpatialRef->Clone();
 
     TABProjInfo     sTABProj;
     int             nParmCount;
     GetTABProjFromSpatialRef(poSpatialRef, sTABProj, nParmCount);
-    
+
     /*-----------------------------------------------------------------
      * Set the new parameters in the .MAP header.
      * This will also trigger lookup of default bounds for the projection.
@@ -1555,7 +1555,7 @@ int TABFile::GetTABProjFromSpatialRef(const OGRSpatialReference* poSpatialRef,
     sTABProj.adProjParams[0] = sTABProj.adProjParams[1] = 0.0;
     sTABProj.adProjParams[2] = sTABProj.adProjParams[3] = 0.0;
     sTABProj.adProjParams[4] = sTABProj.adProjParams[5] = 0.0;
-    
+
     sTABProj.nDatumId = 0;
     sTABProj.dDatumShiftX = 0.0;
     sTABProj.dDatumShiftY = 0.0;
@@ -1892,7 +1892,7 @@ int TABFile::GetTABProjFromSpatialRef(const OGRSpatialReference* poSpatialRef,
      * ============================================================== */
     const char *pszWKTDatum = poSpatialRef->GetAttrValue("DATUM");
     const MapInfoDatumInfo *psDatumInfo = NULL;
-    
+
     int nDatumEPSGCode = -1;
     const char *pszDatumAuthority = poSpatialRef->GetAuthorityName("DATUM");
     const char *pszDatumCode = poSpatialRef->GetAuthorityCode("DATUM");
@@ -1919,7 +1919,7 @@ int TABFile::GetTABProjFromSpatialRef(const OGRSpatialReference* poSpatialRef,
      * We know the MIF datum number, and need to look it up to
      * translate into datum parameters.
      *----------------------------------------------------------------*/
-    else if( EQUALN(pszWKTDatum,"MIF ",4)
+    else if( STARTS_WITH_CI(pszWKTDatum, "MIF ")
              && atoi(pszWKTDatum+4) != 999
              && atoi(pszWKTDatum+4) != 9999 )
     {
@@ -1946,12 +1946,12 @@ int TABFile::GetTABProjFromSpatialRef(const OGRSpatialReference* poSpatialRef,
     /*-----------------------------------------------------------------
      * We have the MIF datum parameters, and apply those directly.
      *----------------------------------------------------------------*/
-    else if( EQUALN(pszWKTDatum,"MIF ",4)
+    else if( STARTS_WITH_CI(pszWKTDatum, "MIF ")
              && (atoi(pszWKTDatum+4) == 999 || atoi(pszWKTDatum+4) == 9999) )
     {
         char **papszFields;
 
-        sTABProj.nDatumId = atoi(pszWKTDatum+4);
+        sTABProj.nDatumId = static_cast<GInt16>(atoi(pszWKTDatum+4));
         papszFields =
             CSLTokenizeStringComplex( pszWKTDatum+4, ",", FALSE, TRUE);
 
@@ -1981,13 +1981,13 @@ int TABFile::GetTABProjFromSpatialRef(const OGRSpatialReference* poSpatialRef,
 
         CSLDestroy( papszFields );
     }
-    
+
     /*-----------------------------------------------------------------
      * We have a "real" datum name, and possibly an EPSG code for the
      * datum.  Try to look it up (using EPSG code first) and get the
      * parameters.  If we don't find it with either just use WGS84.
      *----------------------------------------------------------------*/
-    else 
+    else
     {
         int     i;
 
@@ -2056,7 +2056,20 @@ int TABFile::GetTABProjFromSpatialRef(const OGRSpatialReference* poSpatialRef,
             }
         }
     }
-    
+
+    // Google Merc
+    if( (poSpatialRef->GetAuthorityName(NULL) != NULL &&
+        EQUAL(poSpatialRef->GetAuthorityName(NULL), "EPSG") &&
+        poSpatialRef->GetAuthorityCode(NULL) != NULL &&
+        atoi(poSpatialRef->GetAuthorityCode(NULL)) == 3857) ||
+        (poSpatialRef->GetExtension(NULL, "PROJ4") != NULL &&
+         EQUAL(poSpatialRef->GetExtension(NULL, "PROJ4"),
+               "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext  +no_defs")) )
+    {
+        sTABProj.nDatumId = 157;
+        sTABProj.nEllipsoidId = 54;
+    }
+
     /*-----------------------------------------------------------------
      * Translate the units
      *----------------------------------------------------------------*/
@@ -2070,7 +2083,7 @@ int TABFile::GetTABProjFromSpatialRef(const OGRSpatialReference* poSpatialRef,
     else if( dfLinearConv == CPLAtof(SRS_UL_FOOT_CONV)
              || EQUAL(pszLinearUnits,SRS_UL_FOOT) )
         sTABProj.nUnitsId = 3;
-    else if( EQUAL(pszLinearUnits,"YARD") || EQUAL(pszLinearUnits,"IYARD") 
+    else if( EQUAL(pszLinearUnits,"YARD") || EQUAL(pszLinearUnits,"IYARD")
              || dfLinearConv == 0.9144 )
         sTABProj.nUnitsId = 4;
     else if( dfLinearConv == 0.001 )
@@ -2084,15 +2097,15 @@ int TABFile::GetTABProjFromSpatialRef(const OGRSpatialReference* poSpatialRef,
         sTABProj.nUnitsId = 8;
     else if( EQUAL(pszLinearUnits,SRS_UL_NAUTICAL_MILE) )
         sTABProj.nUnitsId = 9;
-    else if( EQUAL(pszLinearUnits,SRS_UL_LINK) 
+    else if( EQUAL(pszLinearUnits,SRS_UL_LINK)
              || EQUAL(pszLinearUnits,"GUNTERLINK") )
         sTABProj.nUnitsId = 30;
-    else if( EQUAL(pszLinearUnits,SRS_UL_CHAIN) 
+    else if( EQUAL(pszLinearUnits,SRS_UL_CHAIN)
              || EQUAL(pszLinearUnits,"GUNTERCHAIN") )
         sTABProj.nUnitsId = 31;
     else if( EQUAL(pszLinearUnits,SRS_UL_ROD) )
         sTABProj.nUnitsId = 32;
-    else if( EQUAL(pszLinearUnits,"Mile") 
+    else if( EQUAL(pszLinearUnits,"Mile")
              || EQUAL(pszLinearUnits,"IMILE") )
         sTABProj.nUnitsId = 0;
     else
diff --git a/ogr/ogrsf_frmts/mitab/mitab_tabfile.cpp b/ogr/ogrsf_frmts/mitab/mitab_tabfile.cpp
index a99041e..e4dbcc7 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_tabfile.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_tabfile.cpp
@@ -19,16 +19,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -37,7 +37,8 @@
  * Fixed missing initializations that cause crashes
  *
  * Revision 1.77  2010-10-08 18:38:13  aboudreault
- * Added attribute index support for the sql queries in mapinfo tab format (GDAL bug #3687)
+ * Added attribute index support for the sql queries in mapinfo tab format
+ * (GDAL bug #3687)
  *
  * Revision 1.76  2010-07-07 19:00:15  aboudreault
  * Cleanup Win32 Compile Warnings (GDAL bug #2930)
@@ -46,7 +47,8 @@
  * Fixed bad feature count after we deleted a feature in MapInfo (bug 2227)
  *
  * Revision 1.74  2010-01-07 20:39:12  aboudreault
- * Added support to handle duplicate field names, Added validation to check if a field name start with a number (bug 2141)
+ * Added support to handle duplicate field names, Added validation to check
+ * if a field name start with a number (bug 2141)
  *
  * Revision 1.73  2008-11-27 20:50:23  aboudreault
  * Improved support for OGR date/time types. New Read/Write methods (bug 1948)
@@ -139,9 +141,9 @@ TABFile::TABFile()
 
     bUseSpatialTraversal = FALSE;
 
-    m_panMatchingFIDs = NULL; 
-    m_iMatchingFID = 0; 
-    
+    m_panMatchingFIDs = NULL;
+    m_iMatchingFID = 0;
+
     m_bNeedTABRewrite = FALSE;
     m_bLastOpWasRead = FALSE;
     m_bLastOpWasWrite = FALSE;
@@ -164,7 +166,7 @@ TABFile::~TABFile()
 
 GIntBig TABFile::GetFeatureCount (int bForce)
 {
-    
+
     if( m_poFilterGeom != NULL || m_poAttrQuery != NULL || bForce)
         return OGRLayer::GetFeatureCount( bForce );
     else
@@ -179,7 +181,7 @@ void TABFile::ResetReading()
     CPLFree(m_panMatchingFIDs);
     m_panMatchingFIDs = NULL;
     m_iMatchingFID = 0;
-    
+
     m_nCurFeatureId = 0;
     if( m_poMAPFile != NULL )
         m_poMAPFile->ResetReading();
@@ -192,7 +194,7 @@ void TABFile::ResetReading()
     if( m_poMAPFile )
     {
         bUseSpatialTraversal = FALSE;
-    
+
         m_poMAPFile->ResetCoordFilter();
 
         if( m_poFilterGeom != NULL )
@@ -227,7 +229,7 @@ void TABFile::ResetReading()
 /**********************************************************************
  *                   TABFile::Open()
  *
- * Open a .TAB dataset and the associated files, and initialize the 
+ * Open a .TAB dataset and the associated files, and initialize the
  * structures to be ready to read features from (or write to) it.
  *
  * Supported access modes are "r" (read-only) and "w" (create new dataset or
@@ -255,7 +257,7 @@ int TABFile::Open(const char *pszFname, TABAccess eAccess,
     int nFnameLen = 0;
 
     CPLErrorReset();
-   
+
     if (m_poMAPFile)
     {
         CPLError(CE_Failure, CPLE_AssertionFailed,
@@ -263,14 +265,14 @@ int TABFile::Open(const char *pszFname, TABAccess eAccess,
 
         return -1;
     }
-    
+
     m_eAccessMode = eAccess;
 
     /*-----------------------------------------------------------------
-     * Make sure filename has a .TAB extension... 
+     * Make sure filename has a .TAB extension...
      *----------------------------------------------------------------*/
     m_pszFname = CPLStrdup(pszFname);
-    nFnameLen = strlen(m_pszFname);
+    nFnameLen = static_cast<int>(strlen(m_pszFname));
 
     if (nFnameLen > 4 && (strcmp(m_pszFname+nFnameLen-4, ".TAB")==0 ||
                      strcmp(m_pszFname+nFnameLen-4, ".MAP")==0 ||
@@ -332,13 +334,13 @@ int TABFile::Open(const char *pszFname, TABAccess eAccess,
         }
 
         /*-------------------------------------------------------------
-         * Do a first pass on the TAB header to establish the type of 
+         * Do a first pass on the TAB header to establish the type of
          * dataset we have (NATIVE, DBF, etc.)... and also to know if
          * it is a supported type.
          *------------------------------------------------------------*/
         if ( ParseTABFileFirstPass(bTestOpenNoError) != 0 )
         {
-            // No need to produce an error... it's already been done if 
+            // No need to produce an error... it's already been done if
             // necessary... just cleanup and exit.
 
             CPLFree(m_pszFname);
@@ -353,7 +355,7 @@ int TABFile::Open(const char *pszFname, TABAccess eAccess,
     else
     {
         /*-------------------------------------------------------------
-         * In Write access mode, the .TAB file will be written during the 
+         * In Write access mode, the .TAB file will be written during the
          * Close() call... we will just set some defaults here.
          *------------------------------------------------------------*/
         m_nVersion = 300;
@@ -383,7 +385,7 @@ int TABFile::Open(const char *pszFname, TABAccess eAccess,
         else  // Default is NATIVE
             strcpy(pszTmpFname+nFnameLen-4, ".DAT");
     }
-    else 
+    else
     {
         if (m_eTableType == TABTableDBF)
             strcpy(pszTmpFname+nFnameLen-4, ".dbf");
@@ -396,7 +398,7 @@ int TABFile::Open(const char *pszFname, TABAccess eAccess,
 #endif
 
     m_poDATFile = new TABDATFile;
-   
+
     if ( m_poDATFile->Open(pszTmpFname, eAccess, m_eTableType) != 0)
     {
         // Open Failed... an error has already been reported, just return.
@@ -434,7 +436,7 @@ int TABFile::Open(const char *pszFname, TABAccess eAccess,
      *----------------------------------------------------------------*/
     if (nFnameLen > 4 && strcmp(pszTmpFname+nFnameLen-4, ".DAT")==0)
         strcpy(pszTmpFname+nFnameLen-4, ".MAP");
-    else 
+    else
         strcpy(pszTmpFname+nFnameLen-4, ".map");
 
 #ifndef _WIN32
@@ -450,10 +452,10 @@ int TABFile::Open(const char *pszFname, TABAccess eAccess,
          *------------------------------------------------------------*/
         if (m_poMAPFile->Open(pszTmpFname, eAccess, TRUE) < 0)
         {
-            // File exists, but Open Failed... 
+            // File exists, but Open Failed...
             // we have to produce an error message
             if (!bTestOpenNoError)
-                CPLError(CE_Failure, CPLE_FileIO, 
+                CPLError(CE_Failure, CPLE_FileIO,
                          "Open() failed for %s", pszTmpFname);
             else
                 CPLErrorReset();
@@ -470,7 +472,8 @@ int TABFile::Open(const char *pszFname, TABAccess eAccess,
 
         GetFeatureCountByType( numPoints, numLines, numRegions, numTexts);
 
-        numPoints += numTexts;
+        if( numPoints >= 0 && numTexts >= 0 && numPoints < INT_MAX - numTexts )
+            numPoints += numTexts;
         if( numPoints > 0 && numLines == 0 && numRegions == 0 )
             m_poDefn->SetGeomType( wkbPoint );
         else if( numPoints == 0 && numLines > 0 && numRegions == 0 )
@@ -481,7 +484,7 @@ int TABFile::Open(const char *pszFname, TABAccess eAccess,
     }
     else if (m_poMAPFile->Open(pszTmpFname, eAccess, FALSE, nBlockSizeForCreate) != 0)
     {
-        // Open Failed for write... 
+        // Open Failed for write...
         // an error has already been reported, just return.
 
         m_poMAPFile->Close();
@@ -511,11 +514,11 @@ int TABFile::Open(const char *pszFname, TABAccess eAccess,
         {
             CPLXMLNode *psIndex = CPLCreateXMLNode( psRoot, CXT_Element, "OGRMIAttrIndex" );
             CPLCreateXMLElementAndValue( psIndex, "FieldIndex", CPLSPrintf( "%d", iField ) );
-            CPLCreateXMLElementAndValue( psIndex, "FieldName", 
+            CPLCreateXMLElementAndValue( psIndex, "FieldName",
                                      poLayerDefn->GetFieldDefn(iField)->GetNameRef() );
             CPLCreateXMLElementAndValue( psIndex, "IndexIndex", CPLSPrintf( "%d", iIndexIndex ) );
             bHasIndex = 1;
-        }     
+        }
     }
 
     if (bHasIndex)
@@ -591,7 +594,7 @@ int TABFile::ParseTABFileFirstPass(GBool bTestOpenNoError)
         else if (EQUAL(papszTok[0], "!edit_version"))
         {
             /* Sometimes, V450 files have version 300 + edit_version 450
-             * for us version and edit_version are the same 
+             * for us version and edit_version are the same
              */
             m_nVersion = atoi(papszTok[1]);
         }
@@ -676,7 +679,7 @@ int TABFile::ParseTABFileFirstPass(GBool bTestOpenNoError)
  *                   TABFile::ParseTABFileFields()
  *
  * Extract the field definition from the TAB header file, validate
- * with what we have in the previously opened .DAT or .DBF file, and 
+ * with what we have in the previously opened .DAT or .DBF file, and
  * finally build the m_poDefn OGRFeatureDefn for this dataset.
  *
  * This private method should be used only during the Open() call and after
@@ -716,14 +719,14 @@ int TABFile::ParseTABFileFields()
         while(*pszStr != '\0' && isspace((unsigned char)*pszStr))
             pszStr++;
 
-        if (EQUALN(pszStr, "Fields", 6))
+        if (STARTS_WITH_CI(pszStr, "Fields"))
         {
             /*---------------------------------------------------------
              * We found the list of table fields
              *--------------------------------------------------------*/
             int iField, numFields;
             numFields = atoi(pszStr+7);
-            if (numFields < 1 || numFields > 2048 || 
+            if (numFields < 1 || numFields > 2048 ||
                 iLine+numFields >= numLines)
             {
                 CPLError(CE_Failure, CPLE_FileIO,
@@ -746,15 +749,15 @@ int TABFile::ParseTABFileFields()
                  * the info with what is found in the .DAT header, and will
                  * also use this info later to interpret field values.
                  *
-                 * We also create the OGRFieldDefn at the same time to 
+                 * We also create the OGRFieldDefn at the same time to
                  * initialize the OGRFeatureDefn
                  *----------------------------------------------------*/
                 CSLDestroy(papszTok);
-                papszTok = CSLTokenizeStringComplex(m_papszTABFile[iLine], 
+                papszTok = CSLTokenizeStringComplex(m_papszTABFile[iLine],
                                                     " \t(),;",
                                                     TRUE, FALSE);
                 numTok = CSLCount(papszTok);
-                nStatus = -1;
+
                 CPLAssert(m_poDefn);
                 poFieldDefn = NULL;
                 if (numTok >= 3 && EQUAL(papszTok[1], "char"))
@@ -762,7 +765,7 @@ int TABFile::ParseTABFileFields()
                     /*-------------------------------------------------
                      * CHAR type
                      *------------------------------------------------*/
-                    nStatus = m_poDATFile->ValidateFieldInfoFromTAB(iField, 
+                    nStatus = m_poDATFile->ValidateFieldInfoFromTAB(iField,
                                                                papszTok[0],
                                                                TABFChar,
                                                             atoi(papszTok[2]),
@@ -775,7 +778,7 @@ int TABFile::ParseTABFileFields()
                     /*-------------------------------------------------
                      * INTEGER type
                      *------------------------------------------------*/
-                    nStatus = m_poDATFile->ValidateFieldInfoFromTAB(iField, 
+                    nStatus = m_poDATFile->ValidateFieldInfoFromTAB(iField,
                                                                papszTok[0],
                                                                TABFInteger,
                                                                0,
@@ -789,7 +792,7 @@ int TABFile::ParseTABFileFields()
                     /*-------------------------------------------------
                      * SMALLINT type
                      *------------------------------------------------*/
-                    nStatus = m_poDATFile->ValidateFieldInfoFromTAB(iField, 
+                    nStatus = m_poDATFile->ValidateFieldInfoFromTAB(iField,
                                                                papszTok[0],
                                                                TABFSmallInt,
                                                                0,
@@ -803,7 +806,7 @@ int TABFile::ParseTABFileFields()
                     /*-------------------------------------------------
                      * DECIMAL type
                      *------------------------------------------------*/
-                    nStatus = m_poDATFile->ValidateFieldInfoFromTAB(iField, 
+                    nStatus = m_poDATFile->ValidateFieldInfoFromTAB(iField,
                                                                papszTok[0],
                                                                TABFDecimal,
                                                            atoi(papszTok[2]),
@@ -817,7 +820,7 @@ int TABFile::ParseTABFileFields()
                     /*-------------------------------------------------
                      * FLOAT type
                      *------------------------------------------------*/
-                    nStatus = m_poDATFile->ValidateFieldInfoFromTAB(iField, 
+                    nStatus = m_poDATFile->ValidateFieldInfoFromTAB(iField,
                                                                papszTok[0],
                                                                TABFFloat,
                                                                0, 0);
@@ -828,12 +831,12 @@ int TABFile::ParseTABFileFields()
                     /*-------------------------------------------------
                      * DATE type (returned as a string: "DD/MM/YYYY")
                      *------------------------------------------------*/
-                    nStatus = m_poDATFile->ValidateFieldInfoFromTAB(iField, 
+                    nStatus = m_poDATFile->ValidateFieldInfoFromTAB(iField,
                                                                papszTok[0],
                                                                TABFDate,
                                                                0,
                                                                0);
-                    poFieldDefn = new OGRFieldDefn(papszTok[0], 
+                    poFieldDefn = new OGRFieldDefn(papszTok[0],
 #ifdef MITAB_USE_OFTDATETIME
                                                    OFTDate);
 #else
@@ -846,12 +849,12 @@ int TABFile::ParseTABFileFields()
                     /*-------------------------------------------------
                      * TIME type (returned as a string: "HH:MM:SS")
                      *------------------------------------------------*/
-                    nStatus = m_poDATFile->ValidateFieldInfoFromTAB(iField, 
+                    nStatus = m_poDATFile->ValidateFieldInfoFromTAB(iField,
                                                                papszTok[0],
                                                                TABFTime,
                                                                0,
                                                                0);
-                    poFieldDefn = new OGRFieldDefn(papszTok[0], 
+                    poFieldDefn = new OGRFieldDefn(papszTok[0],
 #ifdef MITAB_USE_OFTDATETIME
                                                    OFTTime);
 #else
@@ -864,12 +867,12 @@ int TABFile::ParseTABFileFields()
                     /*-------------------------------------------------
                      * DATETIME type (returned as a string: "DD/MM/YYYY HH:MM:SS")
                      *------------------------------------------------*/
-                    nStatus = m_poDATFile->ValidateFieldInfoFromTAB(iField, 
+                    nStatus = m_poDATFile->ValidateFieldInfoFromTAB(iField,
                                                                papszTok[0],
                                                                TABFDateTime,
                                                                0,
                                                                0);
-                    poFieldDefn = new OGRFieldDefn(papszTok[0], 
+                    poFieldDefn = new OGRFieldDefn(papszTok[0],
 #ifdef MITAB_USE_OFTDATETIME
                                                    OFTDateTime);
 #else
@@ -882,7 +885,7 @@ int TABFile::ParseTABFileFields()
                     /*-------------------------------------------------
                      * LOGICAL type (value "T" or "F")
                      *------------------------------------------------*/
-                    nStatus = m_poDATFile->ValidateFieldInfoFromTAB(iField, 
+                    nStatus = m_poDATFile->ValidateFieldInfoFromTAB(iField,
                                                                papszTok[0],
                                                                TABFLogical,
                                                                0,
@@ -890,13 +893,13 @@ int TABFile::ParseTABFileFields()
                     poFieldDefn = new OGRFieldDefn(papszTok[0], OFTString);
                     poFieldDefn->SetWidth(1);
                 }
-                else 
+                else
                     nStatus = -1; // Unrecognized field type or line corrupt
 
                 if (nStatus != 0)
                 {
                     CPLError(CE_Failure, CPLE_FileIO,
-                     "Failed to parse field definition at line %d in file %s", 
+                     "Failed to parse field definition at line %d in file %s",
                              iLine+1, m_pszFname);
                     CSLDestroy(papszTok);
                     delete poFieldDefn;
@@ -1001,7 +1004,7 @@ int TABFile::WriteTABFile()
                 switch(GetNativeFieldType(iField))
                 {
                   case TABFChar:
-                    pszFieldType = CPLSPrintf("Char (%d)", 
+                    pszFieldType = CPLSPrintf("Char (%d)",
                                               poFieldDefn->GetWidth());
                     break;
                   case TABFDecimal:
@@ -1013,14 +1016,14 @@ int TABFile::WriteTABFile()
                     if( poFieldDefn->GetWidth() == 0 )
                         pszFieldType = "Integer";
                     else
-                        pszFieldType = CPLSPrintf("Integer (%d)", 
+                        pszFieldType = CPLSPrintf("Integer (%d)",
                                                   poFieldDefn->GetWidth());
                     break;
                   case TABFSmallInt:
                     if( poFieldDefn->GetWidth() == 0 )
                         pszFieldType = "SmallInt";
                     else
-                        pszFieldType = CPLSPrintf("SmallInt (%d)", 
+                        pszFieldType = CPLSPrintf("SmallInt (%d)",
                                                   poFieldDefn->GetWidth());
                     break;
                   case TABFFloat:
@@ -1048,16 +1051,16 @@ int TABFile::WriteTABFile()
 
                 if (GetFieldIndexNumber(iField) == 0)
                 {
-                    VSIFPrintfL(fp, "    %s %s ;\n", poFieldDefn->GetNameRef(), 
+                    VSIFPrintfL(fp, "    %s %s ;\n", poFieldDefn->GetNameRef(),
                             pszFieldType );
                 }
                 else
                 {
-                    VSIFPrintfL(fp, "    %s %s Index %d ;\n", 
+                    VSIFPrintfL(fp, "    %s %s Index %d ;\n",
                             poFieldDefn->GetNameRef(), pszFieldType,
                             GetFieldIndexNumber(iField) );
                 }
-                
+
             }
         }
         else
@@ -1094,7 +1097,7 @@ int TABFile::Close()
     CPLErrorReset();
 
     // Commit the latest changes to the file...
-    
+
     if (m_poMAPFile)
     {
         // In Write access, it's time to write the .TAB file.
@@ -1131,11 +1134,11 @@ int TABFile::Close()
     if (m_poDefn )
         m_poDefn->Release();
     m_poDefn = NULL;
-    
+
     if (m_poSpatialRef)
         m_poSpatialRef->Release();
     m_poSpatialRef = NULL;
-    
+
     CSLDestroy(m_papszTABFile);
     m_papszTABFile = NULL;
 
@@ -1157,16 +1160,16 @@ int TABFile::Close()
 /**********************************************************************
  *                   TABFile::SetQuickSpatialIndexMode()
  *
- * Select "quick spatial index mode". 
+ * Select "quick spatial index mode".
  *
  * The default behavior of MITAB is to generate an optimized spatial index,
- * but this results in slower write speed. 
+ * but this results in slower write speed.
  *
  * Applications that want faster write speed and do not care
  * about the performance of spatial queries on the resulting file can
  * use SetQuickSpatialIndexMode() to require the creation of a non-optimal
  * spatial index (actually emulating the type of spatial index produced
- * by MITAB before version 1.6.0). In this mode writing files can be 
+ * by MITAB before version 1.6.0). In this mode writing files can be
  * about 5 times faster, but spatial queries can be up to 30 times slower.
  *
  * Returns 0 on success, -1 on error.
@@ -1198,7 +1201,7 @@ GIntBig TABFile::GetNextFeatureId(GIntBig nPrevId)
         ResetReading();
     m_bLastOpWasRead = TRUE;
 
-    if( (GIntBig)(int)nPrevId != nPrevId )
+    if( !CPL_INT64_FITS_ON_INT32(nPrevId) )
         return -1;
 
     /*-----------------------------------------------------------------
@@ -1256,7 +1259,7 @@ GIntBig TABFile::GetNextFeatureId(GIntBig nPrevId)
             return -1;
         }
 
-// __TODO__ Add a test here to check if object is deleted, 
+// __TODO__ Add a test here to check if object is deleted,
 // i.e. 0x40 set on object_id in object block
         if (m_poMAPFile->GetCurObjType() != TAB_GEOM_NONE ||
             m_poDATFile->IsCurrentRecordDeleted() == FALSE)
@@ -1280,7 +1283,7 @@ GIntBig TABFile::GetNextFeatureId(GIntBig nPrevId)
  * Returns feature id that follows nPrevId, or -1 if it is the
  * last feature id, but by traversing the spatial tree instead of the
  * direct object index.  Generally speaking the feature id's will be
- * returned in an unordered fashion.  
+ * returned in an unordered fashion.
  **********************************************************************/
 int TABFile::GetNextFeatureId_Spatial(int nPrevId)
 {
@@ -1306,8 +1309,8 @@ int TABFile::GetNextFeatureId_Spatial(int nPrevId)
  *
  * Fill and return a TABFeature object for the specified feature id.
  *
- * The retruned pointer is a reference to an object owned and maintained
- * by this TABFile object.  It should not be altered or freed by the 
+ * The returned pointer is a reference to an object owned and maintained
+ * by this TABFile object.  It should not be altered or freed by the
  * caller and its contents is guaranteed to be valid only until the next
  * call to GetFeatureRef() or Close().
  *
@@ -1344,11 +1347,11 @@ TABFeature *TABFile::GetFeatureRef(GIntBig nFeatureId)
         m_poDATFile->GetRecordBlock((int)nFeatureId) == NULL )
     {
         //     CPLError(CE_Failure, CPLE_IllegalArg,
-        //    "GetFeatureRef() failed: invalid feature id %d", 
+        //    "GetFeatureRef() failed: invalid feature id %d",
         //    nFeatureId);
         return NULL;
     }
-    
+
     if( m_poDATFile->IsCurrentRecordDeleted() )
     {
         if( m_poMAPFile->GetCurObjType() != TAB_GEOM_NONE )
@@ -1359,7 +1362,7 @@ TABFeature *TABFile::GetFeatureRef(GIntBig nFeatureId)
         }
         return NULL;
     }
-    
+
     /*-----------------------------------------------------------------
      * Flush current feature object
      * __TODO__ try to reuse if it is already of the right type
@@ -1375,7 +1378,7 @@ TABFeature *TABFile::GetFeatureRef(GIntBig nFeatureId)
      * Unsupported object types are returned as raw TABFeature (i.e. NONE
      * geometry)
      *----------------------------------------------------------------*/
-    m_poCurFeature = TABFeature::CreateFromMapInfoType(m_poMAPFile->GetCurObjType(), 
+    m_poCurFeature = TABFeature::CreateFromMapInfoType(m_poMAPFile->GetCurObjType(),
                                                        m_poDefn);
 
     /*-----------------------------------------------------------------
@@ -1393,8 +1396,8 @@ TABFeature *TABFile::GetFeatureRef(GIntBig nFeatureId)
      * Read geometry from the .MAP file
      * MoveToObjId() has already been called above...
      *----------------------------------------------------------------*/
-    TABMAPObjHdr *poObjHdr = 
-        TABMAPObjHdr::NewObj(m_poMAPFile->GetCurObjType(), 
+    TABMAPObjHdr *poObjHdr =
+        TABMAPObjHdr::NewObj(m_poMAPFile->GetCurObjType(),
                              m_poMAPFile->GetCurObjId());
     // Note that poObjHdr==NULL is a valid case if geometry type is NONE
 
@@ -1403,12 +1406,12 @@ TABFeature *TABFile::GetFeatureRef(GIntBig nFeatureId)
     {
         delete m_poCurFeature;
         m_poCurFeature = NULL;
-        if (poObjHdr) 
+        if (poObjHdr)
             delete poObjHdr;
         return NULL;
     }
     if (poObjHdr)       // May be NULL if feature geometry type is NONE
-        delete poObjHdr; 
+        delete poObjHdr;
 
     m_nCurFeatureId = nFeatureId;
     m_poCurFeature->SetFID(m_nCurFeatureId);
@@ -1452,11 +1455,11 @@ OGRErr TABFile::DeleteFeature(GIntBig nFeatureId)
         m_poDATFile->GetRecordBlock((int)nFeatureId) == NULL )
     {
         /*CPLError(CE_Failure, CPLE_IllegalArg,
-                 "DeleteFeature() failed: invalid feature id " CPL_FRMT_GIB, 
+                 "DeleteFeature() failed: invalid feature id " CPL_FRMT_GIB,
                  nFeatureId);*/
         return OGRERR_NON_EXISTING_FEATURE;
     }
-    
+
     if( m_poDATFile->IsCurrentRecordDeleted() )
     {
         /*CPLError(CE_Failure, CPLE_IllegalArg,
@@ -1469,7 +1472,7 @@ OGRErr TABFile::DeleteFeature(GIntBig nFeatureId)
         delete m_poCurFeature;
         m_poCurFeature = NULL;
     }
-    
+
     if( m_poMAPFile->MarkAsDeleted() != 0 ||
         m_poDATFile->MarkAsDeleted() != 0 )
     {
@@ -1482,7 +1485,7 @@ OGRErr TABFile::DeleteFeature(GIntBig nFeatureId)
 /**********************************************************************
  *                   TABFile::WriteFeature()
  *
- * Write a feature to this dataset.  
+ * Write a feature to this dataset.
  *
  * Returns 0 on success, or -1 if an error happened in which case,
  * CPLError() will have been called to
@@ -1511,7 +1514,7 @@ int TABFile::WriteFeature(TABFeature *poFeature)
     else if (m_nLastFeatureId < 1)
     {
         /*-------------------------------------------------------------
-         * Special hack to write out at least one field if none are in 
+         * Special hack to write out at least one field if none are in
          * OGRFeatureDefn.
          *------------------------------------------------------------*/
         if( m_poDATFile->GetNumFields() == 0 )
@@ -1549,7 +1552,7 @@ int TABFile::WriteFeature(TABFeature *poFeature)
      * Write geometry to the .MAP file
      * The call to PrepareNewObj() takes care of the .ID file.
      *----------------------------------------------------------------*/
-    TABMAPObjHdr *poObjHdr = 
+    TABMAPObjHdr *poObjHdr =
         TABMAPObjHdr::NewObj(poFeature->ValidateMapInfoType(m_poMAPFile),
                              nFeatureId);
 
@@ -1606,7 +1609,7 @@ int TABFile::WriteFeature(TABFeature *poFeature)
             delete poObjHdr;
         return -1;
     }
-    
+
     m_nLastFeatureId = MAX(m_nLastFeatureId, nFeatureId);
     m_nCurFeatureId = nFeatureId;
 
@@ -1619,7 +1622,7 @@ int TABFile::WriteFeature(TABFeature *poFeature)
 /**********************************************************************
  *                   TABFile::CreateFeature()
  *
- * Write a new feature to this dataset. The passed in feature is updated 
+ * Write a new feature to this dataset. The passed in feature is updated
  * with the new feature id.
  *
  * Returns OGRERR_NONE on success, or an appropriate OGRERR_ code if an
@@ -1643,7 +1646,7 @@ OGRErr TABFile::CreateFeature(TABFeature *poFeature)
         if (nFeatureId <= 0 || nFeatureId > m_nLastFeatureId )
         {
             CPLError(CE_Failure, CPLE_IllegalArg,
-                     "CreateFeature() failed: invalid feature id " CPL_FRMT_GIB, 
+                     "CreateFeature() failed: invalid feature id " CPL_FRMT_GIB,
                       nFeatureId);
             return OGRERR_FAILURE;
         }
@@ -1652,7 +1655,7 @@ OGRErr TABFile::CreateFeature(TABFeature *poFeature)
             !m_poDATFile->IsCurrentRecordDeleted() )
         {
             CPLError(CE_Failure, CPLE_IllegalArg,
-                    "CreateFeature() failed: cannot re-write already existing feature " CPL_FRMT_GIB, 
+                    "CreateFeature() failed: cannot re-write already existing feature " CPL_FRMT_GIB,
                     nFeatureId);
             return OGRERR_FAILURE;
         }
@@ -1678,7 +1681,7 @@ OGRErr TABFile::ISetFeature( OGRFeature *poFeature )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "SetFeature() cannot be used in read-only access.");
-        return -1;
+        return OGRERR_FAILURE;
     }
 
     /*-----------------------------------------------------------------
@@ -1690,7 +1693,7 @@ OGRErr TABFile::ISetFeature( OGRFeature *poFeature )
                  "SetFeature() failed: file is not opened!");
         return OGRERR_FAILURE;
     }
-    
+
     GIntBig nFeatureId = poFeature->GetFID();
     if (nFeatureId == OGRNullFID )
     {
@@ -1701,7 +1704,7 @@ OGRErr TABFile::ISetFeature( OGRFeature *poFeature )
     if (nFeatureId <= 0 || nFeatureId > m_nLastFeatureId )
     {
         /*CPLError(CE_Failure, CPLE_IllegalArg,
-                    "SetFeature() failed: invalid feature id " CPL_FRMT_GIB, 
+                    "SetFeature() failed: invalid feature id " CPL_FRMT_GIB,
                     nFeatureId);*/
         return OGRERR_NON_EXISTING_FEATURE;
     }
@@ -1726,7 +1729,7 @@ OGRErr TABFile::ISetFeature( OGRFeature *poFeature )
     if (m_poDATFile->GetRecordBlock((int)nFeatureId) == NULL )
     {
         /*CPLError(CE_Failure, CPLE_IllegalArg,
-                 "SetFeature() failed: invalid feature id " CPL_FRMT_GIB, 
+                 "SetFeature() failed: invalid feature id " CPL_FRMT_GIB,
                  nFeatureId);*/
         delete poTABFeature;
         return OGRERR_NON_EXISTING_FEATURE;
@@ -1788,9 +1791,9 @@ OGRErr TABFile::ISetFeature( OGRFeature *poFeature )
     }
 
     int nStatus = WriteFeature(poTABFeature);
-    
+
     delete poTABFeature;
-    
+
     if (nStatus < 0)
         return OGRERR_FAILURE;
 
@@ -1932,7 +1935,7 @@ int TABFile::SetFeatureDefn(OGRFeatureDefn *poFeatureDefn,
 /**********************************************************************
  *                   TABFile::AddFieldNative()
  *
- * Create a new field using a native mapinfo data type... this is an 
+ * Create a new field using a native mapinfo data type... this is an
  * alternative to defining fields through the OGR interface.
  * This function should be called after creating a new dataset.
  *
@@ -2001,20 +2004,20 @@ int TABFile::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
     strncpy(szNewFieldName, pszCleanName, 31);
     szNewFieldName[31] = '\0';
 
-    while (m_poDefn->GetFieldIndex(szNewFieldName) >= 0 && nRenameNum < 10) 
-      sprintf( szNewFieldName, "%.29s_%.1d", pszCleanName, nRenameNum++ );
+    while (m_poDefn->GetFieldIndex(szNewFieldName) >= 0 && nRenameNum < 10)
+      snprintf( szNewFieldName, sizeof(szNewFieldName), "%.29s_%.1d", pszCleanName, nRenameNum++ );
 
-    while (m_poDefn->GetFieldIndex(szNewFieldName) >= 0 && nRenameNum < 100) 
-      sprintf( szNewFieldName, "%.29s%.2d", pszCleanName, nRenameNum++ );
+    while (m_poDefn->GetFieldIndex(szNewFieldName) >= 0 && nRenameNum < 100)
+      snprintf( szNewFieldName, sizeof(szNewFieldName), "%.29s%.2d", pszCleanName, nRenameNum++ );
 
     if (m_poDefn->GetFieldIndex(szNewFieldName) >= 0)
     {
-      CPLError( CE_Failure, CPLE_NotSupported, 
-                "Too many field names like '%s' when truncated to 31 letters " 
+      CPLError( CE_Failure, CPLE_NotSupported,
+                "Too many field names like '%s' when truncated to 31 letters "
                 "for MapInfo format.", pszCleanName );
     }
 
-    if( !EQUAL(pszCleanName,szNewFieldName) ) 
+    if( !EQUAL(pszCleanName,szNewFieldName) )
     {
       CPLError( CE_Warning, CPLE_NotSupported,
                 "Normalized/laundered field name: '%s' to '%s'",
@@ -2070,7 +2073,7 @@ int TABFile::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
         /*-------------------------------------------------
          * DATE type (V450, returned as a string: "DD/MM/YYYY")
          *------------------------------------------------*/
-        poFieldDefn = new OGRFieldDefn(szNewFieldName, 
+        poFieldDefn = new OGRFieldDefn(szNewFieldName,
 #ifdef MITAB_USE_OFTDATETIME
                                                    OFTDate);
 #else
@@ -2083,7 +2086,7 @@ int TABFile::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
         /*-------------------------------------------------
          * TIME type (V900, returned as a string: "HH:MM:SS")
          *------------------------------------------------*/
-        poFieldDefn = new OGRFieldDefn(szNewFieldName, 
+        poFieldDefn = new OGRFieldDefn(szNewFieldName,
 #ifdef MITAB_USE_OFTDATETIME
                                                    OFTTime);
 #else
@@ -2096,7 +2099,7 @@ int TABFile::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
         /*-------------------------------------------------
          * DATETIME type (V900, returned as a string: "DD/MM/YYYY HH:MM:SS")
          *------------------------------------------------*/
-        poFieldDefn = new OGRFieldDefn(szNewFieldName, 
+        poFieldDefn = new OGRFieldDefn(szNewFieldName,
 #ifdef MITAB_USE_OFTDATETIME
                                                    OFTDateTime);
 #else
@@ -2120,7 +2123,7 @@ int TABFile::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
     }
 
     /*-----------------------------------------------------
-     * Add the FieldDefn to the FeatureDefn 
+     * Add the FieldDefn to the FeatureDefn
      *----------------------------------------------------*/
     m_poDefn->AddFieldDefn(poFieldDefn);
     delete poFieldDefn;
@@ -2128,7 +2131,7 @@ int TABFile::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
     /*-----------------------------------------------------
      * ... and pass field info to the .DAT file.
      *----------------------------------------------------*/
-    nStatus = m_poDATFile->AddField(szNewFieldName, eMapInfoType, 
+    nStatus = m_poDATFile->AddField(szNewFieldName, eMapInfoType,
                                     nWidth, nPrecision);
 
     /*-----------------------------------------------------------------
@@ -2184,7 +2187,7 @@ TABFieldType TABFile::GetNativeFieldType(int nFieldId)
  **********************************************************************/
 int  TABFile::GetFieldIndexNumber(int nFieldId)
 {
-    if (m_panIndexNo == NULL || nFieldId < 0 || 
+    if (m_panIndexNo == NULL || nFieldId < 0 ||
         m_poDATFile== NULL || nFieldId >= m_poDATFile->GetNumFields())
         return 0;  // no index
 
@@ -2214,7 +2217,7 @@ int TABFile::SetFieldIndexed( int nFieldId )
         return -1;
     }
 
-    if (m_panIndexNo == NULL || nFieldId < 0 || 
+    if (m_panIndexNo == NULL || nFieldId < 0 ||
         m_poDATFile== NULL || nFieldId >= m_poDATFile->GetNumFields())
     {
         CPLError(CE_Failure, CPLE_AssertionFailed,
@@ -2238,10 +2241,10 @@ int TABFile::SetFieldIndexed( int nFieldId )
     if (m_poINDFile == NULL)
     {
         m_poINDFile = new TABINDFile;
-   
+
         if ( m_poINDFile->Open(m_pszFname, "w", TRUE) != 0)
         {
-            // File could not be opened... 
+            // File could not be opened...
             delete m_poINDFile;
             m_poINDFile = NULL;
             return -1;
@@ -2283,14 +2286,14 @@ GBool TABFile::IsFieldIndexed( int nFieldId )
  *                   TABFile::GetINDFileRef()
  *
  * Opens the .IND file for this dataset and returns a reference to
- * the handle.  
- * If the .IND file has already been opened then the same handle is 
+ * the handle.
+ * If the .IND file has already been opened then the same handle is
  * returned directly.
  * If the .IND file does not exist then the function silently returns NULL.
  *
  * Note that the returned TABINDFile handle is only a reference to an
  * object that is owned by this class.  Callers can use it but cannot
- * destroy the object.  The object will remain valid for as long as 
+ * destroy the object.  The object will remain valid for as long as
  * the TABFile will remain open.
  **********************************************************************/
 TABINDFile  *TABFile::GetINDFileRef()
@@ -2307,7 +2310,7 @@ TABINDFile  *TABFile::GetINDFileRef()
          * TABINDFile class will automagically adjust the extension.
          *------------------------------------------------------------*/
         m_poINDFile = new TABINDFile;
-   
+
         if ( m_poINDFile->Open(m_pszFname, "r", TRUE) != 0)
         {
             // File could not be opened... probably does not exist
@@ -2344,7 +2347,7 @@ TABINDFile  *TABFile::GetINDFileRef()
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABFile::SetBounds(double dXMin, double dYMin, 
+int TABFile::SetBounds(double dXMin, double dYMin,
                        double dXMax, double dYMax)
 {
     if (m_eAccessMode != TABWrite)
@@ -2385,7 +2388,7 @@ int TABFile::SetBounds(double dXMin, double dYMin,
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABFile::GetBounds(double &dXMin, double &dYMin, 
+int TABFile::GetBounds(double &dXMin, double &dYMin,
                        double &dXMax, double &dYMax,
                        GBool /*bForce = TRUE*/)
 {
@@ -2397,9 +2400,9 @@ int TABFile::GetBounds(double &dXMin, double &dYMin,
          * Projection bounds correspond to the +/- 1e9 integer coord. limits
          *------------------------------------------------------------*/
         double dX0, dX1, dY0, dY1;
-        m_poMAPFile->Int2Coordsys(-1000000000, -1000000000,  
+        m_poMAPFile->Int2Coordsys(-1000000000, -1000000000,
                                   dX0, dY0);
-        m_poMAPFile->Int2Coordsys(1000000000, 1000000000, 
+        m_poMAPFile->Int2Coordsys(1000000000, 1000000000,
                                   dX1, dY1);
         /*-------------------------------------------------------------
          * ... and make sure that Min < Max
@@ -2442,9 +2445,9 @@ OGRErr TABFile::GetExtent (OGREnvelope *psExtent,
          * Fetch extent of the data from the .map header block
          * this value is different from the projection bounds.
          *------------------------------------------------------------*/
-        m_poMAPFile->Int2Coordsys(poHeader->m_nXMin, poHeader->m_nYMin,  
+        m_poMAPFile->Int2Coordsys(poHeader->m_nXMin, poHeader->m_nYMin,
                                   dX0, dY0);
-        m_poMAPFile->Int2Coordsys(poHeader->m_nXMax, poHeader->m_nYMax, 
+        m_poMAPFile->Int2Coordsys(poHeader->m_nXMax, poHeader->m_nYMax,
                                   dX1, dY1);
 
        /*-------------------------------------------------------------
@@ -2533,7 +2536,7 @@ int TABFile::SetMIFCoordSys(const char *pszMIFCoordSys)
             if (SetSpatialRef(poSpatialRef) == 0)
             {
                 if (MITABExtractCoordSysBounds(pszMIFCoordSys,
-                                               dXMin, dYMin, 
+                                               dXMin, dYMin,
                                                dXMax, dYMax) == TRUE)
                 {
                     // If the coordsys string contains bounds, then use them
@@ -2547,7 +2550,7 @@ int TABFile::SetMIFCoordSys(const char *pszMIFCoordSys)
             }
             else
             {
-                // Failed setting poSpatialRef... and error should have 
+                // Failed setting poSpatialRef... and error should have
                 // been reported.
                 return -1;
             }
@@ -2711,7 +2714,7 @@ OGRErr TABFile::ReorderFields( int* panMap )
 /*                           AlterFieldDefn()                           */
 /************************************************************************/
 
-OGRErr TABFile::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags )
+OGRErr TABFile::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlagsIn )
 {
     if( m_poDATFile == NULL || !TestCapability(OLCDeleteField) )
     {
@@ -2728,21 +2731,21 @@ OGRErr TABFile::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nF
         return OGRERR_FAILURE;
     }
 
-    if ( m_poDATFile->AlterFieldDefn( iField, poNewFieldDefn, nFlags ) == 0 )
+    if ( m_poDATFile->AlterFieldDefn( iField, poNewFieldDefn, nFlagsIn ) == 0 )
     {
         m_bNeedTABRewrite = TRUE;
 
         OGRFieldDefn* poFieldDefn = m_poDefn->GetFieldDefn(iField);
-        if ((nFlags & ALTER_TYPE_FLAG) &&
+        if ((nFlagsIn & ALTER_TYPE_FLAG) &&
             poNewFieldDefn->GetType() != poFieldDefn->GetType())
         {
             poFieldDefn->SetType(poNewFieldDefn->GetType());
-            if( (nFlags & ALTER_WIDTH_PRECISION_FLAG) == 0 )
+            if( (nFlagsIn & ALTER_WIDTH_PRECISION_FLAG) == 0 )
                 poFieldDefn->SetWidth(254);
         }
-        if (nFlags & ALTER_NAME_FLAG)
+        if (nFlagsIn & ALTER_NAME_FLAG)
             poFieldDefn->SetName(poNewFieldDefn->GetNameRef());
-        if ((nFlags & ALTER_WIDTH_PRECISION_FLAG) &&
+        if ((nFlagsIn & ALTER_WIDTH_PRECISION_FLAG) &&
             poFieldDefn->GetType() == OFTString)
         {
             poFieldDefn->SetWidth(m_poDATFile->GetFieldWidth(iField));
@@ -2767,16 +2770,23 @@ OGRErr TABFile::SyncToDisk()
     if( m_eAccessMode == TABRead )
         return OGRERR_NONE;
 
+    OGRErr eErr = OGRERR_NONE;
+
+    // This is a hack for Windows and VSIFFlushL() issue. See http://trac.osgeo.org/gdal/ticket/5556
+    CPLSetConfigOption("VSI_FLUSH", "TRUE");
+
     if( WriteTABFile() != 0 )
-        return OGRERR_FAILURE;
+        eErr = OGRERR_FAILURE;
 
     if( m_poMAPFile->SyncToDisk() != 0 )
-        return OGRERR_FAILURE;
+        eErr = OGRERR_FAILURE;
 
     if( m_poDATFile->SyncToDisk() != 0 )
-        return OGRERR_FAILURE;
+        eErr = OGRERR_FAILURE;
 
-    return OGRERR_NONE;
+    CPLSetConfigOption("VSI_FLUSH", NULL);
+
+    return eErr;
 }
 
 /************************************************************************/
@@ -2820,7 +2830,7 @@ int TABFile::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCAlterFieldDefn) )
         return m_eAccessMode != TABRead;
 
-    else 
+    else
         return FALSE;
 }
 
@@ -2854,7 +2864,7 @@ void TABFile::Dump(FILE *fpOut /*=NULL*/)
 
             GetSpatialRef()->exportToWkt( &pszWKT );
             fprintf( fpOut, "SRS = %s\n", pszWKT );
-            OGRFree( pszWKT );                                          
+            OGRFree( pszWKT );
         }
         fprintf(fpOut, "Associated .MAP file ...\n\n");
         m_poMAPFile->Dump(fpOut);
diff --git a/ogr/ogrsf_frmts/mitab/mitab_tabseamless.cpp b/ogr/ogrsf_frmts/mitab/mitab_tabseamless.cpp
index fa40e18..b9ff062 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_tabseamless.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_tabseamless.cpp
@@ -18,16 +18,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -86,7 +86,7 @@
  *    index table (upper 32 bits) and the actual feature id of each object
  *    inside the base tables (lower 32 bits).
  *  - Only relative paths are supported for base tables names.
- *    
+ *
  *====================================================================*/
 
 
@@ -103,7 +103,7 @@ TABSeamless::TABSeamless()
     m_poFeatureDefnRef = NULL;
     m_poCurFeature = NULL;
     m_nCurFeatureId = -1;
-    
+
     m_poIndexTable = NULL;
     m_nTableNameField = -1;
     m_nCurBaseTableId = -1;
@@ -139,7 +139,7 @@ void TABSeamless::ResetReading()
  * Open a seamless .TAB dataset and initialize the structures to be ready
  * to read features from it.
  *
- * Seamless .TAB files are composed of a main .TAB file in which each 
+ * Seamless .TAB files are composed of a main .TAB file in which each
  * feature is the MBR of a base table.
  *
  * Set bTestOpenNoError=TRUE to silently return -1 with no error message
@@ -153,7 +153,7 @@ int TABSeamless::Open(const char *pszFname, TABAccess eAccess,
                       GBool bTestOpenNoError /*= FALSE*/ )
 {
     char nStatus = 0;
-   
+
     if (m_poIndexTable)
     {
         CPLError(CE_Failure, CPLE_AssertionFailed,
@@ -187,11 +187,11 @@ int TABSeamless::Open(const char *pszFname, TABAccess eAccess,
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABSeamless::OpenForRead(const char *pszFname, 
+int TABSeamless::OpenForRead(const char *pszFname,
                              GBool bTestOpenNoError /*= FALSE*/ )
 {
     int nFnameLen = 0;
-   
+
     m_eAccessMode = TABRead;
 
     /*-----------------------------------------------------------------
@@ -220,7 +220,7 @@ int TABSeamless::OpenForRead(const char *pszFname,
             CPLError(CE_Failure, CPLE_FileIO,
                      "Failed opening %s.", m_pszFname);
         }
-        
+
         CPLFree(m_pszFname);
         CSLDestroy(papszTABFile);
         return -1;
@@ -237,7 +237,7 @@ int TABSeamless::OpenForRead(const char *pszFname,
         const char *pszStr = papszTABFile[i];
         while(*pszStr != '\0' && isspace((unsigned char)*pszStr))
             pszStr++;
-        if (EQUALN(pszStr, "\"\\IsSeamless\" = \"TRUE\"", 21))
+        if (STARTS_WITH_CI(pszStr, "\"\\IsSeamless\" = \"TRUE\""))
             bSeamlessFound = TRUE;
     }
     CSLDestroy(papszTABFile);
@@ -263,10 +263,10 @@ int TABSeamless::OpenForRead(const char *pszFname,
      * to build the filename of the base tables
      *----------------------------------------------------------------*/
     m_pszPath = CPLStrdup(m_pszFname);
-    nFnameLen = strlen(m_pszPath);
+    nFnameLen = static_cast<int>(strlen(m_pszPath));
     for( ; nFnameLen > 0; nFnameLen--)
     {
-        if (m_pszPath[nFnameLen-1] == '/' || 
+        if (m_pszPath[nFnameLen-1] == '/' ||
             m_pszPath[nFnameLen-1] == '\\' )
         {
             break;
@@ -299,7 +299,7 @@ int TABSeamless::OpenForRead(const char *pszFname,
                      "supported.",
                      m_pszFname);
         Close();
-        return -1;        
+        return -1;
     }
 
     /*-----------------------------------------------------------------
@@ -424,8 +424,8 @@ int TABSeamless::OpenBaseTable(TABFeature *poIndexFeature,
         return -1;
     }
 
-    // Set the spatial filter to the new table 
-    if( m_poFilterGeom != NULL &&  m_poCurBaseTable )
+    // Set the spatial filter to the new table
+    if( m_poFilterGeom != NULL )
     {
         m_poCurBaseTable->SetSpatialFilter( m_poFilterGeom );
     }
@@ -467,7 +467,7 @@ int TABSeamless::OpenBaseTable(int nTableId, GBool bTestOpenNoError /*=FALSE*/)
     else
     {
         TABFeature *poIndexFeature = m_poIndexTable->GetFeatureRef(nTableId);
-    
+
         if (poIndexFeature)
         {
             if (OpenBaseTable(poIndexFeature, bTestOpenNoError) != 0)
@@ -498,7 +498,7 @@ int TABSeamless::OpenNextBaseTable(GBool bTestOpenNoError /*=FALSE*/)
     CPLAssert(m_poIndexTable);
 
     TABFeature *poIndexFeature = (TABFeature*)m_poIndexTable->GetNextFeature();
-    
+
     if (poIndexFeature)
     {
         if (OpenBaseTable(poIndexFeature, bTestOpenNoError) != 0)
@@ -592,7 +592,7 @@ GIntBig TABSeamless::GetNextFeatureId(GIntBig nPrevId)
  * Fill and return a TABFeature object for the specified feature id.
  *
  * The returned pointer is a reference to an object owned and maintained
- * by this TABSeamless object.  It should not be altered or freed by the 
+ * by this TABSeamless object.  It should not be altered or freed by the
  * caller and its contents is guaranteed to be valid only until the next
  * call to GetFeatureRef() or Close().
  *
@@ -711,7 +711,7 @@ GBool TABSeamless::IsFieldUnique(int nFieldId)
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABSeamless::GetBounds(double &dXMin, double &dYMin, 
+int TABSeamless::GetBounds(double &dXMin, double &dYMin,
                        double &dXMax, double &dYMax,
                        GBool bForce /*= TRUE*/)
 {
@@ -814,8 +814,8 @@ OGRSpatialReference *TABSeamless::GetSpatialRef()
 /**********************************************************************
  *                   IMapInfoFile::SetSpatialFilter()
  *
- * Standard OGR SetSpatialFiltere implementation.  This methode is used
- * to set a SpatialFilter for this OGRLayer
+ * Standard OGR SetSpatialFiltere implementation.  This method is used
+ * to set a SpatialFilter for this OGRLayer.
  **********************************************************************/
 void TABSeamless::SetSpatialFilter (OGRGeometry * poGeomIn )
 
@@ -841,7 +841,7 @@ int TABSeamless::TestCapability( const char * pszCap )
     if( EQUAL(pszCap,OLCRandomRead) )
         return TRUE;
 
-    else if( EQUAL(pszCap,OLCSequentialWrite) 
+    else if( EQUAL(pszCap,OLCSequentialWrite)
              || EQUAL(pszCap,OLCRandomWrite) )
         return FALSE;
 
@@ -854,7 +854,7 @@ int TABSeamless::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCFastGetExtent) )
         return TRUE;
 
-    else 
+    else
         return FALSE;
 }
 
diff --git a/ogr/ogrsf_frmts/mitab/mitab_tabview.cpp b/ogr/ogrsf_frmts/mitab/mitab_tabview.cpp
index e1b2a1e..31caf04 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_tabview.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_tabview.cpp
@@ -5,7 +5,7 @@
  * Project:  MapInfo TAB Read/Write library
  * Language: C++
  * Purpose:  Implementation of the TABView class, used to handle .TAB
- *           datasets composed of a number of .TAB files linked through 
+ *           datasets composed of a number of .TAB files linked through
  *           indexed fields.
  * Author:   Daniel Morissette, dmorissette at dmsolutions.ca
  *
@@ -19,16 +19,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -84,7 +84,7 @@
  * Added implementation for new OGRLayer::GetExtent(), returning data MBR.
  *
  * Revision 1.7  2000/09/28 16:39:44  warmerda
- * avoid warnings for unused, and unitialized variables
+ * Avoid warnings for unused, and uninitialized variables
  *
  * Revision 1.6  2000/02/28 17:12:22  daniel
  * Write support for joined tables and indexed fields
@@ -170,7 +170,7 @@ void TABView::ResetReading()
 /**********************************************************************
  *                   TABView::Open()
  *
- * Open a .TAB dataset and the associated files, and initialize the 
+ * Open a .TAB dataset and the associated files, and initialize the
  * structures to be ready to read features from it.
  *
  * This class is used to open .TAB files that define a view on
@@ -188,7 +188,7 @@ int TABView::Open(const char *pszFname, TABAccess eAccess,
                   GBool bTestOpenNoError /*= FALSE*/ )
 {
     char nStatus = 0;
-   
+
     if (m_numTABFiles > 0)
     {
         CPLError(CE_Failure, CPLE_AssertionFailed,
@@ -227,12 +227,12 @@ int TABView::Open(const char *pszFname, TABAccess eAccess,
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABView::OpenForRead(const char *pszFname, 
+int TABView::OpenForRead(const char *pszFname,
                          GBool bTestOpenNoError /*= FALSE*/ )
 {
     char *pszPath = NULL;
     int nFnameLen = 0;
-   
+
     m_eAccessMode = TABRead;
 
     /*-----------------------------------------------------------------
@@ -261,7 +261,7 @@ int TABView::OpenForRead(const char *pszFname,
             CPLError(CE_Failure, CPLE_FileIO,
                      "Failed opening %s.", m_pszFname);
         }
-        
+
         CPLFree(m_pszFname);
         return -1;
     }
@@ -272,14 +272,14 @@ int TABView::OpenForRead(const char *pszFname,
      * but we do not support it in this class.
      *------------------------------------------------------------*/
     GBool bCreateViewFound = FALSE;
-    for (int i=0; 
+    for (int i=0;
          !bCreateViewFound && m_papszTABFile && m_papszTABFile[i];
          i++)
     {
         const char *pszStr = m_papszTABFile[i];
         while(*pszStr != '\0' && isspace((unsigned char)*pszStr))
             pszStr++;
-        if (EQUALN(pszStr, "create view", 11))
+        if (STARTS_WITH_CI(pszStr, "create view"))
             bCreateViewFound = TRUE;
     }
 
@@ -304,10 +304,10 @@ int TABView::OpenForRead(const char *pszFname,
      * to build the filename of the sub-tables
      *----------------------------------------------------------------*/
     pszPath = CPLStrdup(m_pszFname);
-    nFnameLen = strlen(pszPath);
+    nFnameLen = static_cast<int>(strlen(pszPath));
     for( ; nFnameLen > 0; nFnameLen--)
     {
-        if (pszPath[nFnameLen-1] == '/' || 
+        if (pszPath[nFnameLen-1] == '/' ||
             pszPath[nFnameLen-1] == '\\' )
         {
             break;
@@ -354,9 +354,9 @@ int TABView::OpenForRead(const char *pszFname,
 #ifndef _WIN32
         TABAdjustFilenameExtension(m_papszTABFnames[iFile]);
 #endif
-        
+
         m_papoTABFiles[iFile] = new TABFile;
-   
+
         if ( m_papoTABFiles[iFile]->Open(m_papszTABFnames[iFile],
                                          m_eAccessMode, bTestOpenNoError) != 0)
         {
@@ -373,7 +373,7 @@ int TABView::OpenForRead(const char *pszFname,
      * __TODO__ For now this assumes only 2 tables in the view...
      *----------------------------------------------------------------*/
     m_poRelation = new TABRelation;
-    
+
     CPLAssert(m_nMainTableIndex == 0);
     CPLAssert(CSLCount(m_papszWhereClause) == 5);
     char *pszTableName = TABGetBasename(m_pszFname);
@@ -403,7 +403,7 @@ int TABView::OpenForRead(const char *pszFname,
 int TABView::OpenForWrite(const char *pszFname)
 {
     int nFnameLen = 0;
-   
+
     m_eAccessMode = TABWrite;
 
     /*-----------------------------------------------------------------
@@ -424,10 +424,10 @@ int TABView::OpenForWrite(const char *pszFname)
      * Extract the path component from the main .TAB filename
      *----------------------------------------------------------------*/
     char *pszPath = CPLStrdup(m_pszFname);
-    nFnameLen = strlen(pszPath);
+    nFnameLen = static_cast<int>(strlen(pszPath));
     for( ; nFnameLen > 0; nFnameLen--)
     {
-        if (pszPath[nFnameLen-1] == '/' || 
+        if (pszPath[nFnameLen-1] == '/' ||
             pszPath[nFnameLen-1] == '\\' )
         {
             break;
@@ -453,14 +453,15 @@ int TABView::OpenForWrite(const char *pszFname)
 
     for (int iFile=0; iFile < m_numTABFiles; iFile++)
     {
-        m_papszTABFnames = CSLAppendPrintf(m_papszTABFnames, "%s%s%d.tab", 
+        m_papszTABFnames = CSLAppendPrintf(m_papszTABFnames, "%s%s%d.tab",
                                                pszPath, pszBasename, iFile+1);
 #ifndef _WIN32
+        /* coverity[var_deref_op] */
         TABAdjustFilenameExtension(m_papszTABFnames[iFile]);
 #endif
-        
+
         m_papoTABFiles[iFile] = new TABFile;
-   
+
         if ( m_papoTABFiles[iFile]->Open(m_papszTABFnames[iFile], m_eAccessMode) != 0)
         {
             // Open Failed... an error has already been reported, just return.
@@ -472,10 +473,10 @@ int TABView::OpenForWrite(const char *pszFname)
     }
 
     /*-----------------------------------------------------------------
-     * Create TABRelation... 
+     * Create TABRelation...
      *----------------------------------------------------------------*/
     m_poRelation = new TABRelation;
-    
+
     if ( m_poRelation->Init(pszBasename,
                             m_papoTABFiles[0], m_papoTABFiles[1],
                             NULL, NULL, NULL)  != 0 )
@@ -509,7 +510,7 @@ int TABView::OpenForWrite(const char *pszFname)
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABView::ParseTABFile(const char *pszDatasetPath, 
+int TABView::ParseTABFile(const char *pszDatasetPath,
                           GBool bTestOpenNoError /*=FALSE*/)
 {
     int         iLine, numLines;
@@ -550,12 +551,12 @@ int TABView::ParseTABFile(const char *pszDatasetPath,
                  CSLCount(papszTok) >= 3)
         {
             // Source table name may be either "filename" or "filename.tab"
-            int nLen = strlen(papszTok[2]);
+            int nLen = static_cast<int>(strlen(papszTok[2]));
             if (nLen > 4 && EQUAL(papszTok[2]+nLen-4, ".tab"))
                 papszTok[2][nLen-4] = '\0';
 
-            m_papszTABFnames = CSLAppendPrintf(m_papszTABFnames, 
-                                               "%s%s.tab", 
+            m_papszTABFnames = CSLAppendPrintf(m_papszTABFnames,
+                                               "%s%s.tab",
                                                pszDatasetPath, papszTok[2]);
         }
         else if (EQUAL(papszTok[0], "create") &&
@@ -571,7 +572,7 @@ int TABView::ParseTABFile(const char *pszDatasetPath,
              *--------------------------------------------------------*/
             int iTok;
             for(iTok=1; papszTok[iTok] != NULL; iTok++)
-                m_papszFieldNames = CSLAddString(m_papszFieldNames, 
+                m_papszFieldNames = CSLAddString(m_papszFieldNames,
                                                  papszTok[iTok]);
 
         }
@@ -592,9 +593,9 @@ int TABView::ParseTABFile(const char *pszDatasetPath,
             /*---------------------------------------------------------
              * For now we are very limiting on the format of the WHERE
              * clause... we will be more permitting as we learn more about
-             * what it can contain... (I don't want to implement a full SQL 
+             * what it can contain... (I don't want to implement a full SQL
              * parser here!!!).  If you encountered this error,
-             * (and are reading this!) please report the test dataset 
+             * (and are reading this!) please report the test dataset
              * that produced the error and I'll see if we can support it.
              *--------------------------------------------------------*/
             if (CSLCount( m_papszWhereClause ) != 5)
@@ -603,6 +604,7 @@ int TABView::ParseTABFile(const char *pszDatasetPath,
                     CPLError(CE_Failure, CPLE_NotSupported,
                      "WHERE clause in %s is not in a supported format: \"%s\"",
                              m_pszFname, m_papszTABFile[iLine]);
+                CSLDestroy(papszTok);
                 return -1;
             }
         }
@@ -656,7 +658,7 @@ int TABView::ParseTABFile(const char *pszDatasetPath,
 /**********************************************************************
  *                   TABView::WriteTABFile()
  *
- * Generate the TAB header file.  This is usually done during the 
+ * Generate the TAB header file.  This is usually done during the
  * Close() call.
  *
  * Returns 0 on success, -1 on error.
@@ -697,9 +699,9 @@ int TABView::WriteTABFile()
         VSIFPrintfL(fp, "\n");
 
         VSIFPrintfL(fp, "From %s, %s\n", pszTable2, pszTable1);
-        VSIFPrintfL(fp, "Where %s.%s=%s.%s\n", pszTable2, 
+        VSIFPrintfL(fp, "Where %s.%s=%s.%s\n", pszTable2,
                                            m_poRelation->GetRelFieldName(),
-                                           pszTable1, 
+                                           pszTable1,
                                            m_poRelation->GetMainFieldName());
 
 
@@ -710,7 +712,7 @@ int TABView::WriteTABFile()
         CPLFree(pszTable);
         CPLFree(pszTable1);
         CPLFree(pszTable2);
-        
+
         CPLError(CE_Failure, CPLE_FileIO,
                  "Failed to create file `%s'", m_pszFname);
         return -1;
@@ -746,7 +748,7 @@ int TABView::Close()
     m_papoTABFiles = NULL;
     m_numTABFiles = 0;
 
-    
+
     /*-----------------------------------------------------------------
      * __TODO__ OK, MapInfo does not like to see a .map and .id file
      * attached to the second table, even if they're empty.
@@ -760,7 +762,7 @@ int TABView::Close()
         TABAdjustFilenameExtension(pszFile);
         VSIUnlink(pszFile);
 
-        sprintf(pszFile, "%s2.id", m_pszFname);
+        snprintf(pszFile, strlen(pszFile)+1, "%s2.id", m_pszFname);
         TABAdjustFilenameExtension(pszFile);
         VSIUnlink(pszFile);
 
@@ -802,16 +804,16 @@ int TABView::Close()
 /**********************************************************************
  *                   TABView::SetQuickSpatialIndexMode()
  *
- * Select "quick spatial index mode". 
+ * Select "quick spatial index mode".
  *
  * The default behavior of MITAB is to generate an optimized spatial index,
- * but this results in slower write speed. 
+ * but this results in slower write speed.
  *
  * Applications that want faster write speed and do not care
  * about the performance of spatial queries on the resulting file can
  * use SetQuickSpatialIndexMode() to require the creation of a non-optimal
  * spatial index (actually emulating the type of spatial index produced
- * by MITAB before version 1.6.0). In this mode writing files can be 
+ * by MITAB before version 1.6.0). In this mode writing files can be
  * about 5 times faster, but spatial queries can be up to 30 times slower.
  *
  * Returns 0 on success, -1 on error.
@@ -857,8 +859,8 @@ GIntBig TABView::GetNextFeatureId(GIntBig nPrevId)
  *
  * Fill and return a TABFeature object for the specified feature id.
  *
- * The retruned pointer is a reference to an object owned and maintained
- * by this TABView object.  It should not be altered or freed by the 
+ * The returned pointer is a reference to an object owned and maintained
+ * by this TABView object.  It should not be altered or freed by the
  * caller and its contents is guaranteed to be valid only until the next
  * call to GetFeatureRef() or Close().
  *
@@ -868,9 +870,9 @@ GIntBig TABView::GetNextFeatureId(GIntBig nPrevId)
  **********************************************************************/
 TABFeature *TABView::GetFeatureRef(GIntBig nFeatureId)
 {
-    
+
     /*-----------------------------------------------------------------
-     * Make sure file is opened 
+     * Make sure file is open.
      *----------------------------------------------------------------*/
     if (m_poRelation == NULL)
     {
@@ -879,7 +881,7 @@ TABFeature *TABView::GetFeatureRef(GIntBig nFeatureId)
         return NULL;
     }
 
-    if( (GIntBig)(int)nFeatureId != nFeatureId )
+    if( !CPL_INT64_FITS_ON_INT32(nFeatureId) )
         return NULL;
 
     if(m_poCurFeature)
@@ -898,7 +900,7 @@ TABFeature *TABView::GetFeatureRef(GIntBig nFeatureId)
 /**********************************************************************
  *                   TABView::CreateFeature()
  *
- * Write a new feature to this dataset. The passed in feature is updated 
+ * Write a new feature to this dataset. The passed in feature is updated
  * with the new feature id.
  *
  * Returns OGRERR_NONE on success, or an appropriate OGRERR_ code if an
@@ -1002,9 +1004,9 @@ TABFieldType TABView::GetNativeFieldType(int nFieldId)
 /**********************************************************************
  *                   TABView::AddFieldNative()
  *
- * Create a new field using a native mapinfo data type... this is an 
+ * Create a new field using a native mapinfo data type... this is an
  * alternative to defining fields through the OGR interface.
- * This function should be called after creating a new dataset, but before 
+ * This function should be called after creating a new dataset, but before
  * writing the first feature.
  *
  * This function will build/update the OGRFeatureDefn that will have to be
@@ -1081,7 +1083,7 @@ GBool TABView::IsFieldUnique(int nFieldId)
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABView::GetBounds(double &dXMin, double &dYMin, 
+int TABView::GetBounds(double &dXMin, double &dYMin,
                        double &dXMax, double &dYMax,
                        GBool bForce /*= TRUE*/)
 {
@@ -1113,7 +1115,7 @@ OGRErr TABView::GetExtent (OGREnvelope *psExtent, int bForce)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
              "GetExtent() can be called only after dataset has been opened.");
-        return -1;
+        return OGRERR_FAILURE;
     }
 
     return m_papoTABFiles[m_nMainTableIndex]->GetExtent(psExtent, bForce);
@@ -1194,7 +1196,7 @@ int TABView::SetSpatialRef(OGRSpatialReference *poSpatialRef)
 /**********************************************************************
  *                   TABView::SetBounds()
  **********************************************************************/
-int TABView::SetBounds(double dXMin, double dYMin, 
+int TABView::SetBounds(double dXMin, double dYMin,
                        double dXMax, double dYMax)
 {
     if (m_nMainTableIndex == -1)
@@ -1233,7 +1235,7 @@ int TABView::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCFastGetExtent) )
         return TRUE;
 
-    else 
+    else
         return FALSE;
 }
 
@@ -1412,7 +1414,7 @@ int  TABRelation::Init(const char *pszViewName,
 
     /*-----------------------------------------------------------------
      * Init field maps.  For each field in each table, a -1 means that
-     * the field is not selected, and a value >=0 is the index of the 
+     * the field is not selected, and a value >=0 is the index of the
      * field in the view's FeatureDefn
      *----------------------------------------------------------------*/
     int i;
@@ -1429,7 +1431,7 @@ int  TABRelation::Init(const char *pszViewName,
     /*-----------------------------------------------------------------
      * If selectedFields = "*" then select all fields from both tables
      *----------------------------------------------------------------*/
-    if (CSLCount(papszSelectedFields) == 1 && 
+    if (CSLCount(papszSelectedFields) == 1 &&
         EQUAL(papszSelectedFields[0], "*") )
     {
         CSLDestroy(papszSelectedFields);
@@ -1439,7 +1441,7 @@ int  TABRelation::Init(const char *pszViewName,
         {
             OGRFieldDefn *poFieldDefn = poMainDefn->GetFieldDefn(i);
 
-            papszSelectedFields = CSLAddString(papszSelectedFields, 
+            papszSelectedFields = CSLAddString(papszSelectedFields,
                                                poFieldDefn->GetNameRef());
         }
 
@@ -1447,11 +1449,11 @@ int  TABRelation::Init(const char *pszViewName,
         {
             OGRFieldDefn *poFieldDefn = poRelDefn->GetFieldDefn(i);
 
-            if (CSLFindString(papszSelectedFields, 
+            if (CSLFindString(papszSelectedFields,
                               poFieldDefn->GetNameRef()) != -1)
                 continue;  // Avoid duplicate field name in view
 
-            papszSelectedFields = CSLAddString(papszSelectedFields, 
+            papszSelectedFields = CSLAddString(papszSelectedFields,
                                                poFieldDefn->GetNameRef());
         }
 
@@ -1461,14 +1463,14 @@ int  TABRelation::Init(const char *pszViewName,
      * Create new FeatureDefn and copy selected fields definitions
      * while updating the appropriate field maps.
      *----------------------------------------------------------------*/
-    int nIndex, numSelFields = CSLCount(papszSelectedFields);
+    int nIndex;
     OGRFieldDefn *poFieldDefn;
 
     m_poDefn = new OGRFeatureDefn(pszViewName);
     // Ref count defaults to 0... set it to 1
     m_poDefn->Reference();
 
-    for(i=0; i<numSelFields ; i++)
+    for(i=0; papszSelectedFields != NULL && papszSelectedFields[i] != NULL ; i++)
     {
         if (poMainDefn &&
             (nIndex=poMainDefn->GetFieldIndex(papszSelectedFields[i])) >=0)
@@ -1494,11 +1496,12 @@ int  TABRelation::Init(const char *pszViewName,
             // At least send a warning and ignore the field.
             CPLError(CE_Warning, CPLE_IllegalArg,
                      "Selected Field %s not found in source tables %s and %s",
-                     papszSelectedFields[i], 
-                     poMainDefn->GetName(), poRelDefn->GetName());
+                     papszSelectedFields[i],
+                     poMainDefn?poMainDefn->GetName():"(null)",
+                     poRelDefn?poRelDefn->GetName():"(null)");
         }
     }
-
+    CSLDestroy(papszSelectedFields);
     return 0;
 }
 
@@ -1518,16 +1521,17 @@ int  TABRelation::CreateRelFields()
     int i;
 
     /*-----------------------------------------------------------------
-     * Create the field in each table.  
+     * Create the field in each table.
      * The default name is "MI_refnum" but if a field with the same name
      * already exists then we'll try to generate a unique name.
      *----------------------------------------------------------------*/
     m_pszMainFieldName = CPLStrdup("MI_Refnum      ");
+    const size_t nLen = strlen(m_pszMainFieldName) + 1;
     strcpy(m_pszMainFieldName, "MI_Refnum");
     i = 1;
     while(m_poDefn->GetFieldIndex(m_pszMainFieldName) >= 0)
     {
-        sprintf(m_pszMainFieldName, "MI_Refnum_%d", i++);
+        snprintf(m_pszMainFieldName, nLen, "MI_Refnum_%d", i++);
     }
     m_pszRelFieldName = CPLStrdup(m_pszMainFieldName);
 
@@ -1582,7 +1586,7 @@ int  TABRelation::CreateRelFields()
  *
  * Fill and return a TABFeature object for the specified feature id.
  *
- * The retuned pointer is a new TABFeature that will have to be freed
+ * The returned pointer is a new TABFeature that will have to be freed
  * by the caller.
  *
  * Returns NULL if the specified feature id does not exist of if an
@@ -1590,8 +1594,8 @@ int  TABRelation::CreateRelFields()
  * report the reason of the failure.
  *
  * __TODO__ The current implementation fetches the features from each table
- * and creates a 3rd feature to merge them.  There would be room for 
- * optimization, at least by avoiding the duplication of the geometry 
+ * and creates a 3rd feature to merge them.  There would be room for
+ * optimization, at least by avoiding the duplication of the geometry
  * which can be big sometimes... but this would imply changes at the
  * lower-level in the lib. and we won't go there yet.
  **********************************************************************/
@@ -1615,7 +1619,7 @@ TABFeature *TABRelation::GetFeature(int nFeatureId)
      *----------------------------------------------------------------*/
     if ((poMainFeature = m_poMainTable->GetFeatureRef(nFeatureId)) == NULL)
     {
-        // Feature cannot be read from main table... 
+        // Feature cannot be read from main table...
         // an error has already been reported.
         return NULL;
     }
@@ -1623,7 +1627,7 @@ TABFeature *TABRelation::GetFeature(int nFeatureId)
     poCurFeature = poMainFeature->CloneTABFeature(m_poDefn);
 
     /*-----------------------------------------------------------------
-     * Keep track of FID and copy the geometry 
+     * Keep track of FID and copy the geometry
      *----------------------------------------------------------------*/
     poCurFeature->SetFID(nFeatureId);
 
@@ -1648,7 +1652,7 @@ TABFeature *TABRelation::GetFeature(int nFeatureId)
                                 m_nRelFieldIndexNo);
     int i;
     int nRelFeatureId = m_poRelINDFileRef->FindFirst(m_nRelFieldIndexNo, pKey);
-    
+
     if (nRelFeatureId > 0)
         poRelFeature = m_poRelTable->GetFeatureRef(nRelFeatureId);
 
@@ -1659,7 +1663,7 @@ TABFeature *TABRelation::GetFeature(int nFeatureId)
     {
         if (m_panMainTableFieldMap[i] != -1)
         {
-            poCurFeature->SetField(m_panMainTableFieldMap[i], 
+            poCurFeature->SetField(m_panMainTableFieldMap[i],
                                      poMainFeature->GetRawFieldRef(i));
         }
     }
@@ -1674,7 +1678,7 @@ TABFeature *TABRelation::GetFeature(int nFeatureId)
     {
         if (m_panRelTableFieldMap[i] != -1)
         {
-            poCurFeature->SetField(m_panRelTableFieldMap[i], 
+            poCurFeature->SetField(m_panRelTableFieldMap[i],
                                      poRelFeature->GetRawFieldRef(i));
         }
     }
@@ -1780,9 +1784,9 @@ TABFieldType TABRelation::GetNativeFieldType(int nFieldId)
 /**********************************************************************
  *                   TABRelation::AddFieldNative()
  *
- * Create a new field using a native mapinfo data type... this is an 
+ * Create a new field using a native mapinfo data type... this is an
  * alternative to defining fields through the OGR interface.
- * This function should be called after creating a new dataset, but before 
+ * This function should be called after creating a new dataset, but before
  * writing the first feature.
  *
  * This function will build/update the OGRFeatureDefn that will have to be
@@ -1818,7 +1822,7 @@ int TABRelation::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
         m_poDefn->AddFieldDefn(poMainDefn->GetFieldDefn(poMainDefn->
                                                           GetFieldCount()-1));
 
-        m_panMainTableFieldMap[poMainDefn->GetFieldCount()-1] = 
+        m_panMainTableFieldMap[poMainDefn->GetFieldCount()-1] =
                                             m_poDefn->GetFieldCount()-1;
     }
     else
@@ -1839,7 +1843,7 @@ int TABRelation::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
         m_poDefn->AddFieldDefn(poRelDefn->GetFieldDefn(poRelDefn->
                                                          GetFieldCount()-1));
 
-        m_panRelTableFieldMap[poRelDefn->GetFieldCount()-1] =  
+        m_panRelTableFieldMap[poRelDefn->GetFieldCount()-1] =
                                             m_poDefn->GetFieldCount()-1;
 
         // The first field in this table must be indexed.
@@ -1967,7 +1971,7 @@ GBool TABRelation::IsFieldUnique(int nFieldId)
 /**********************************************************************
  *                   TABRelation::WriteFeature()
  *
- * Write a feature to this dataset.  
+ * Write a feature to this dataset.
  *
  * For now only sequential writes are supported (i.e. with nFeatureId=-1)
  * but eventually we should be able to do random access by specifying
@@ -2016,13 +2020,13 @@ int TABRelation::WriteFeature(TABFeature *poFeature, int nFeatureId /*=-1*/)
     {
         if (m_panMainTableFieldMap[i] != -1)
         {
-            poMainFeature->SetField(i, 
+            poMainFeature->SetField(i,
                       poFeature->GetRawFieldRef(m_panMainTableFieldMap[i]));
         }
     }
 
     /*-----------------------------------------------------------------
-     * Look for a record id for the unique fields, and write a new 
+     * Look for a record id for the unique fields, and write a new
      * record if necessary
      *----------------------------------------------------------------*/
     int nRecordNo = 0;
@@ -2051,7 +2055,7 @@ int TABRelation::WriteFeature(TABFeature *poFeature, int nFeatureId /*=-1*/)
             {
                 if (m_panRelTableFieldMap[i] != -1)
                 {
-                    poRelFeature->SetField(i, 
+                    poRelFeature->SetField(i,
                           poFeature->GetRawFieldRef(m_panRelTableFieldMap[i]));
                 }
             }
@@ -2087,7 +2091,7 @@ int TABRelation::WriteFeature(TABFeature *poFeature, int nFeatureId /*=-1*/)
 /**********************************************************************
  *                   TABFile::SetFeatureDefn()
  *
- * NOT FULLY IMPLEMENTED YET... 
+ * NOT FULLY IMPLEMENTED YET...
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
diff --git a/ogr/ogrsf_frmts/mitab/mitab_tooldef.cpp b/ogr/ogrsf_frmts/mitab/mitab_tooldef.cpp
index bf7847f..d91dbbe 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_tooldef.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_tooldef.cpp
@@ -17,16 +17,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -127,7 +127,7 @@ int     TABToolDefTable::ReadAllToolDefs(TABMAPToolBlock *poBlock)
 
     /*-----------------------------------------------------------------
      * Loop until we reach the end of the chain of blocks... we assume
-     * that the first block of data is already pre-loaded. 
+     * that the first block of data is already pre-loaded.
      *----------------------------------------------------------------*/
     while( ! poBlock->EndOfChain() )
     {
@@ -139,7 +139,7 @@ int     TABToolDefTable::ReadAllToolDefs(TABMAPToolBlock *poBlock)
             {
                 // Realloc array by blocks of 20 items
                 m_numAllocatedPen += 20;
-                m_papsPen = (TABPenDef**)CPLRealloc(m_papsPen, 
+                m_papsPen = (TABPenDef**)CPLRealloc(m_papsPen,
                                         m_numAllocatedPen*sizeof(TABPenDef*));
             }
             m_papsPen[m_numPen] = (TABPenDef*)CPLCalloc(1, sizeof(TABPenDef));
@@ -149,15 +149,15 @@ int     TABToolDefTable::ReadAllToolDefs(TABMAPToolBlock *poBlock)
             m_papsPen[m_numPen]->nLinePattern = poBlock->ReadByte();
             m_papsPen[m_numPen]->nPointWidth = poBlock->ReadByte();
             m_papsPen[m_numPen]->rgbColor   = poBlock->ReadByte()*256*256+
-                                              poBlock->ReadByte()*256 + 
+                                              poBlock->ReadByte()*256 +
                                               poBlock->ReadByte();
 
-            // Adjust width value... 
+            // Adjust width value...
             // High bits for point width values > 255 are stored in the
             // pixel width byte
             if (m_papsPen[m_numPen]->nPixelWidth > 7)
             {
-                m_papsPen[m_numPen]->nPointWidth += 
+                m_papsPen[m_numPen]->nPointWidth +=
                          (m_papsPen[m_numPen]->nPixelWidth-8)*0x100;
                 m_papsPen[m_numPen]->nPixelWidth = 1;
             }
@@ -170,20 +170,20 @@ int     TABToolDefTable::ReadAllToolDefs(TABMAPToolBlock *poBlock)
             {
                 // Realloc array by blocks of 20 items
                 m_numAllocatedBrushes += 20;
-                m_papsBrush = (TABBrushDef**)CPLRealloc(m_papsBrush, 
+                m_papsBrush = (TABBrushDef**)CPLRealloc(m_papsBrush,
                                  m_numAllocatedBrushes*sizeof(TABBrushDef*));
             }
-            m_papsBrush[m_numBrushes] = 
+            m_papsBrush[m_numBrushes] =
                                (TABBrushDef*)CPLCalloc(1,sizeof(TABBrushDef));
 
             m_papsBrush[m_numBrushes]->nRefCount    = poBlock->ReadInt32();
             m_papsBrush[m_numBrushes]->nFillPattern = poBlock->ReadByte();
             m_papsBrush[m_numBrushes]->bTransparentFill = poBlock->ReadByte();
             m_papsBrush[m_numBrushes]->rgbFGColor =poBlock->ReadByte()*256*256+
-                                                   poBlock->ReadByte()*256 + 
+                                                   poBlock->ReadByte()*256 +
                                                    poBlock->ReadByte();
             m_papsBrush[m_numBrushes]->rgbBGColor =poBlock->ReadByte()*256*256+
-                                                   poBlock->ReadByte()*256 + 
+                                                   poBlock->ReadByte()*256 +
                                                    poBlock->ReadByte();
 
             m_numBrushes++;
@@ -194,10 +194,10 @@ int     TABToolDefTable::ReadAllToolDefs(TABMAPToolBlock *poBlock)
             {
                 // Realloc array by blocks of 20 items
                 m_numAllocatedFonts += 20;
-                m_papsFont = (TABFontDef**)CPLRealloc(m_papsFont, 
+                m_papsFont = (TABFontDef**)CPLRealloc(m_papsFont,
                                  m_numAllocatedFonts*sizeof(TABFontDef*));
             }
-            m_papsFont[m_numFonts] = 
+            m_papsFont[m_numFonts] =
                                (TABFontDef*)CPLCalloc(1,sizeof(TABFontDef));
 
             m_papsFont[m_numFonts]->nRefCount    = poBlock->ReadInt32();
@@ -212,10 +212,10 @@ int     TABToolDefTable::ReadAllToolDefs(TABMAPToolBlock *poBlock)
             {
                 // Realloc array by blocks of 20 items
                 m_numAllocatedSymbols += 20;
-                m_papsSymbol = (TABSymbolDef**)CPLRealloc(m_papsSymbol, 
+                m_papsSymbol = (TABSymbolDef**)CPLRealloc(m_papsSymbol,
                                  m_numAllocatedSymbols*sizeof(TABSymbolDef*));
             }
-            m_papsSymbol[m_numSymbols] = 
+            m_papsSymbol[m_numSymbols] =
                                (TABSymbolDef*)CPLCalloc(1,sizeof(TABSymbolDef));
 
             m_papsSymbol[m_numSymbols]->nRefCount    = poBlock->ReadInt32();
@@ -223,7 +223,7 @@ int     TABToolDefTable::ReadAllToolDefs(TABMAPToolBlock *poBlock)
             m_papsSymbol[m_numSymbols]->nPointSize   = poBlock->ReadInt16();
             m_papsSymbol[m_numSymbols]->_nUnknownValue_ = poBlock->ReadByte();
             m_papsSymbol[m_numSymbols]->rgbColor = poBlock->ReadByte()*256*256+
-                                                   poBlock->ReadByte()*256 + 
+                                                   poBlock->ReadByte()*256 +
                                                    poBlock->ReadByte();
 
             m_numSymbols++;
@@ -240,6 +240,7 @@ int     TABToolDefTable::ReadAllToolDefs(TABMAPToolBlock *poBlock)
         {
             // An error happened reading this tool definition... stop now.
             nStatus = -1;
+            break;
         }
     }
 
@@ -388,7 +389,7 @@ int     TABToolDefTable::GetNumPen()
  * Return a reference to the specified Pen tool definition, or NULL if
  * specified index is invalid.
  *
- * Note that nIndex is a 1-based index.  A value of 0 indicates "none" 
+ * Note that nIndex is a 1-based index.  A value of 0 indicates "none"
  * in MapInfo.
  **********************************************************************/
 TABPenDef *TABToolDefTable::GetPenDefRef(int nIndex)
@@ -404,10 +405,10 @@ TABPenDef *TABToolDefTable::GetPenDefRef(int nIndex)
  *
  * Either create a new PenDefRef or add a reference to an existing one.
  *
- * Return the pen index that has been attributed to this Pen tool 
+ * Return the pen index that has been attributed to this Pen tool
  * definition, or -1 if something went wrong
  *
- * Note that nIndex is a 1-based index.  A value of 0 indicates "none" 
+ * Note that nIndex is a 1-based index.  A value of 0 indicates "none"
  * in MapInfo.
  **********************************************************************/
 int TABToolDefTable::AddPenDefRef(TABPenDef *poNewPenDef)
@@ -437,7 +438,7 @@ int TABToolDefTable::AddPenDefRef(TABPenDef *poNewPenDef)
         {
             nNewPenIndex = i+1; // Fount it!
             poDef->nRefCount++;
-        }               
+        }
     }
 
     /*-----------------------------------------------------------------
@@ -449,7 +450,7 @@ int TABToolDefTable::AddPenDefRef(TABPenDef *poNewPenDef)
         {
             // Realloc array by blocks of 20 items
             m_numAllocatedPen += 20;
-            m_papsPen = (TABPenDef**)CPLRealloc(m_papsPen, 
+            m_papsPen = (TABPenDef**)CPLRealloc(m_papsPen,
                                        m_numAllocatedPen*sizeof(TABPenDef*));
         }
         m_papsPen[m_numPen] = (TABPenDef*)CPLCalloc(1, sizeof(TABPenDef));
@@ -478,7 +479,7 @@ int     TABToolDefTable::GetNumBrushes()
  * Return a reference to the specified Brush tool definition, or NULL if
  * specified index is invalid.
  *
- * Note that nIndex is a 1-based index.  A value of 0 indicates "none" 
+ * Note that nIndex is a 1-based index.  A value of 0 indicates "none"
  * in MapInfo.
  **********************************************************************/
 TABBrushDef *TABToolDefTable::GetBrushDefRef(int nIndex)
@@ -494,10 +495,10 @@ TABBrushDef *TABToolDefTable::GetBrushDefRef(int nIndex)
  *
  * Either create a new BrushDefRef or add a reference to an existing one.
  *
- * Return the Brush index that has been attributed to this Brush tool 
+ * Return the Brush index that has been attributed to this Brush tool
  * definition, or -1 if something went wrong
  *
- * Note that nIndex is a 1-based index.  A value of 0 indicates "none" 
+ * Note that nIndex is a 1-based index.  A value of 0 indicates "none"
  * in MapInfo.
  **********************************************************************/
 int TABToolDefTable::AddBrushDefRef(TABBrushDef *poNewBrushDef)
@@ -527,7 +528,7 @@ int TABToolDefTable::AddBrushDefRef(TABBrushDef *poNewBrushDef)
         {
             nNewBrushIndex = i+1; // Fount it!
             poDef->nRefCount++;
-        }               
+        }
     }
 
     /*-----------------------------------------------------------------
@@ -539,10 +540,10 @@ int TABToolDefTable::AddBrushDefRef(TABBrushDef *poNewBrushDef)
         {
             // Realloc array by blocks of 20 items
             m_numAllocatedBrushes += 20;
-            m_papsBrush = (TABBrushDef**)CPLRealloc(m_papsBrush, 
+            m_papsBrush = (TABBrushDef**)CPLRealloc(m_papsBrush,
                                  m_numAllocatedBrushes*sizeof(TABBrushDef*));
         }
-        m_papsBrush[m_numBrushes]=(TABBrushDef*)CPLCalloc(1, 
+        m_papsBrush[m_numBrushes]=(TABBrushDef*)CPLCalloc(1,
                                                           sizeof(TABBrushDef));
 
         *m_papsBrush[m_numBrushes] = *poNewBrushDef;
@@ -569,7 +570,7 @@ int     TABToolDefTable::GetNumFonts()
  * Return a reference to the specified Font tool definition, or NULL if
  * specified index is invalid.
  *
- * Note that nIndex is a 1-based index.  A value of 0 indicates "none" 
+ * Note that nIndex is a 1-based index.  A value of 0 indicates "none"
  * in MapInfo.
  **********************************************************************/
 TABFontDef *TABToolDefTable::GetFontDefRef(int nIndex)
@@ -585,10 +586,10 @@ TABFontDef *TABToolDefTable::GetFontDefRef(int nIndex)
  *
  * Either create a new FontDefRef or add a reference to an existing one.
  *
- * Return the Font index that has been attributed to this Font tool 
+ * Return the Font index that has been attributed to this Font tool
  * definition, or -1 if something went wrong
  *
- * Note that nIndex is a 1-based index.  A value of 0 indicates "none" 
+ * Note that nIndex is a 1-based index.  A value of 0 indicates "none"
  * in MapInfo.
  **********************************************************************/
 int TABToolDefTable::AddFontDefRef(TABFontDef *poNewFontDef)
@@ -609,7 +610,7 @@ int TABToolDefTable::AddFontDefRef(TABFontDef *poNewFontDef)
         {
             nNewFontIndex = i+1; // Fount it!
             poDef->nRefCount++;
-        }               
+        }
     }
 
     /*-----------------------------------------------------------------
@@ -621,10 +622,10 @@ int TABToolDefTable::AddFontDefRef(TABFontDef *poNewFontDef)
         {
             // Realloc array by blocks of 20 items
             m_numAllocatedFonts += 20;
-            m_papsFont = (TABFontDef**)CPLRealloc(m_papsFont, 
+            m_papsFont = (TABFontDef**)CPLRealloc(m_papsFont,
                                  m_numAllocatedFonts*sizeof(TABFontDef*));
         }
-        m_papsFont[m_numFonts]=(TABFontDef*)CPLCalloc(1, 
+        m_papsFont[m_numFonts]=(TABFontDef*)CPLCalloc(1,
                                                           sizeof(TABFontDef));
 
         *m_papsFont[m_numFonts] = *poNewFontDef;
@@ -651,7 +652,7 @@ int     TABToolDefTable::GetNumSymbols()
  * Return a reference to the specified Symbol tool definition, or NULL if
  * specified index is invalid.
  *
- * Note that nIndex is a 1-based index.  A value of 0 indicates "none" 
+ * Note that nIndex is a 1-based index.  A value of 0 indicates "none"
  * in MapInfo.
  **********************************************************************/
 TABSymbolDef *TABToolDefTable::GetSymbolDefRef(int nIndex)
@@ -668,10 +669,10 @@ TABSymbolDef *TABToolDefTable::GetSymbolDefRef(int nIndex)
  *
  * Either create a new SymbolDefRef or add a reference to an existing one.
  *
- * Return the Symbol index that has been attributed to this Symbol tool 
+ * Return the Symbol index that has been attributed to this Symbol tool
  * definition, or -1 if something went wrong
  *
- * Note that nIndex is a 1-based index.  A value of 0 indicates "none" 
+ * Note that nIndex is a 1-based index.  A value of 0 indicates "none"
  * in MapInfo.
  **********************************************************************/
 int TABToolDefTable::AddSymbolDefRef(TABSymbolDef *poNewSymbolDef)
@@ -695,7 +696,7 @@ int TABToolDefTable::AddSymbolDefRef(TABSymbolDef *poNewSymbolDef)
         {
             nNewSymbolIndex = i+1; // Fount it!
             poDef->nRefCount++;
-        }               
+        }
     }
 
     /*-----------------------------------------------------------------
@@ -707,10 +708,10 @@ int TABToolDefTable::AddSymbolDefRef(TABSymbolDef *poNewSymbolDef)
         {
             // Realloc array by blocks of 20 items
             m_numAllocatedSymbols += 20;
-            m_papsSymbol = (TABSymbolDef**)CPLRealloc(m_papsSymbol, 
+            m_papsSymbol = (TABSymbolDef**)CPLRealloc(m_papsSymbol,
                                  m_numAllocatedSymbols*sizeof(TABSymbolDef*));
         }
-        m_papsSymbol[m_numSymbols]=(TABSymbolDef*)CPLCalloc(1, 
+        m_papsSymbol[m_numSymbols]=(TABSymbolDef*)CPLCalloc(1,
                                                        sizeof(TABSymbolDef));
 
         *m_papsSymbol[m_numSymbols] = *poNewSymbolDef;
@@ -748,4 +749,3 @@ int     TABToolDefTable::GetMinVersionNumber()
 
     return nVersion;
 }
-
diff --git a/ogr/ogrsf_frmts/mitab/mitab_utils.cpp b/ogr/ogrsf_frmts/mitab/mitab_utils.cpp
index 16afa3a..27769ab 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_utils.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_utils.cpp
@@ -16,16 +16,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -45,9 +45,6 @@
  * Revision 1.22  2008-07-21 16:04:58  dmorissette
  * Fixed const char * warnings with GCC 4.3 (GDAL ticket #2325)
  *
- * Revision 1.21  2006/12/01 16:53:15  dmorissette
- * Wrapped <mbctype.h> stuff with !defined(WIN32CE) (done by mloskot in OGR)
- *
  * Revision 1.20  2005/08/07 21:02:14  fwarmerdam
  * avoid warnings about testing for characters > 255.
  *
@@ -67,7 +64,7 @@
  * Don't filter chars in TABCleanFieldName() if we're on a DBCS system
  *
  * Revision 1.14  2000/09/28 16:39:44  warmerda
- * avoid warnings for unused, and unitialized variables
+ * Avoid warnings for unused, and uninitialized variables
  *
  * Revision 1.13  2000/09/20 18:35:51  daniel
  * Fixed TABAdjustFilenameExtension() to also handle basename and path
@@ -118,7 +115,7 @@
 #include <math.h>       /* sin()/cos() */
 #include <ctype.h>      /* toupper()/tolower() */
 
-#if defined(_WIN32) && !defined(unix) && !defined(WIN32CE)
+#if defined(_WIN32) && !defined(unix)
 #  include <mbctype.h>  /* Multibyte chars stuff */
 #endif
 
@@ -126,11 +123,11 @@
 /**********************************************************************
  *                       TABGenerateArc()
  *
- * Generate the coordinates for an arc and ADD the coordinates to the 
+ * Generate the coordinates for an arc and ADD the coordinates to the
  * geometry object.  If the geometry already contains some points then
  * these won't be lost.
  *
- * poLine can be a OGRLineString or one of its derived classes, such as 
+ * poLine can be a OGRLineString or one of its derived classes, such as
  *        OGRLinearRing
  * numPoints is the number of points to generate.
  * Angles are specified in radians, valid values are in the range [0..2*PI]
@@ -139,7 +136,7 @@
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABGenerateArc(OGRLineString *poLine, int numPoints, 
+int TABGenerateArc(OGRLineString *poLine, int numPoints,
                    double dCenterX, double dCenterY,
                    double dXRadius, double dYRadius,
                    double dStartAngle, double dEndAngle)
@@ -149,7 +146,7 @@ int TABGenerateArc(OGRLineString *poLine, int numPoints,
 
     // Adjust angles to go counterclockwise
     if (dEndAngle < dStartAngle)
-        dEndAngle += 2.0*PI;
+        dEndAngle += 2.0*M_PI;
 
     dAngleStep = (dEndAngle-dStartAngle)/(numPoints-1.0);
 
@@ -161,8 +158,8 @@ int TABGenerateArc(OGRLineString *poLine, int numPoints,
         poLine->addPoint(dX, dY);
     }
 
-    // Complete the arc with the last EndAngle, to make sure that 
-    // the arc is correcly close.
+    // Complete the arc with the last EndAngle, to make sure that
+    // the arc is correctly closed.
 
     dX = dCenterX + dXRadius*cos(dAngle);
     dY = dCenterY + dYRadius*sin(dAngle);
@@ -202,7 +199,11 @@ int TABCloseRing(OGRLineString *poRing)
  * This function works on the original buffer and returns a reference to it.
  * It does nothing on Windows systems where filenames are not case sensitive.
  **********************************************************************/
-GBool TABAdjustCaseSensitiveFilename(char *pszFname)
+static GBool TABAdjustCaseSensitiveFilename(char *
+#ifndef _WIN32
+                                            pszFname
+#endif
+                                            )
 {
 
 #ifdef _WIN32
@@ -233,7 +234,7 @@ GBool TABAdjustCaseSensitiveFilename(char *pszFname)
      * go backwards until we find a portion of the path that is valid.
      *----------------------------------------------------------------*/
     pszTmpPath = CPLStrdup(pszFname);
-    nTotalLen = strlen(pszTmpPath);
+    nTotalLen = static_cast<int>(strlen(pszTmpPath));
     iTmpPtr = nTotalLen;
     bValidPath = FALSE;
 
@@ -262,7 +263,7 @@ GBool TABAdjustCaseSensitiveFilename(char *pszFname)
 
     /*-----------------------------------------------------------------
      * OK, now that we have a valid base, reconstruct the whole path
-     * by scanning all the sub-directories.  
+     * by scanning all the sub-directories.
      * If we get to a point where a path component does not exist then
      * we simply return the rest of the path as is.
      *----------------------------------------------------------------*/
@@ -272,7 +273,7 @@ GBool TABAdjustCaseSensitiveFilename(char *pszFname)
         int     iEntry, iLastPartStart;
 
         iLastPartStart = iTmpPtr;
-        papszDir = CPLReadDir(pszTmpPath);
+        papszDir = VSIReadDir(pszTmpPath);
 
         /*-------------------------------------------------------------
          * Add one component to the current path
@@ -347,19 +348,19 @@ GBool TABAdjustFilenameExtension(char *pszFname)
 {
     VSIStatBufL  sStatBuf;
     int         i;
-    
+
     /*-----------------------------------------------------------------
      * First try using filename as provided
      *----------------------------------------------------------------*/
     if (VSIStatL(pszFname, &sStatBuf) == 0)
     {
         return TRUE;
-    }     
+    }
 
     /*-----------------------------------------------------------------
      * Try using uppercase extension (we assume that fname contains a '.')
      *----------------------------------------------------------------*/
-    for(i = strlen(pszFname)-1; i >= 0 && pszFname[i] != '.'; i--)
+    for(i = static_cast<int>(strlen(pszFname))-1; i >= 0 && pszFname[i] != '.'; i--)
     {
         pszFname[i] = (char)toupper(pszFname[i]);
     }
@@ -367,12 +368,12 @@ GBool TABAdjustFilenameExtension(char *pszFname)
     if (VSIStatL(pszFname, &sStatBuf) == 0)
     {
         return TRUE;
-    }     
-    
+    }
+
     /*-----------------------------------------------------------------
      * Try using lowercase extension
      *----------------------------------------------------------------*/
-    for(i = strlen(pszFname)-1; i >= 0 && pszFname[i] != '.'; i--)
+    for(i = static_cast<int>(strlen(pszFname))-1; i >= 0 && pszFname[i] != '.'; i--)
     {
         pszFname[i] = (char)tolower(pszFname[i]);
     }
@@ -380,11 +381,11 @@ GBool TABAdjustFilenameExtension(char *pszFname)
     if (VSIStatL(pszFname, &sStatBuf) == 0)
     {
         return TRUE;
-    }     
+    }
 
     /*-----------------------------------------------------------------
-     * None of the extensions worked!  
-     * Try adjusting cases in the whole path and filename 
+     * None of the extensions worked!
+     * Try adjusting cases in the whole path and filename
      *----------------------------------------------------------------*/
     return TABAdjustCaseSensitiveFilename(pszFname);
 }
@@ -397,7 +398,7 @@ GBool TABAdjustFilenameExtension(char *pszFname)
  * Extract the basename part of a complete file path.
  *
  * Returns a newly allocated string without the leading path (dirs) and
- * the extenstion.  The returned string should be freed using CPLFree().
+ * the extension.  The returned string should be freed using CPLFree().
  **********************************************************************/
 char *TABGetBasename(const char *pszFname)
 {
@@ -408,8 +409,8 @@ char *TABGetBasename(const char *pszFname)
      * encountered.
      *----------------------------------------------------------------*/
     pszTmp = pszFname + strlen(pszFname) - 1;
-    while ( pszTmp != pszFname 
-            && *pszTmp != '/' && *pszTmp != '\\' ) 
+    while ( pszTmp != pszFname
+            && *pszTmp != '/' && *pszTmp != '\\' )
         pszTmp--;
 
     if( pszTmp != pszFname )
@@ -420,7 +421,7 @@ char *TABGetBasename(const char *pszFname)
      *----------------------------------------------------------------*/
     char *pszBasename = CPLStrdup(pszTmp);
     int i;
-    for(i=strlen(pszBasename)-1; i >= 0; i-- )
+    for(i=static_cast<int>(strlen(pszBasename))-1; i >= 0; i-- )
     {
         if (pszBasename[i] == '.')
         {
@@ -510,7 +511,7 @@ char *TABUnEscapeString(char *pszString, GBool bSrcIsConst)
     if (bSrcIsConst)
     {
         // We have to create a copy to work on.
-        pszWorkString = (char *)CPLMalloc(sizeof(char) * 
+        pszWorkString = (char *)CPLMalloc(sizeof(char) *
                                           (strlen(pszString) +1));
     }
     else
@@ -522,13 +523,13 @@ char *TABUnEscapeString(char *pszString, GBool bSrcIsConst)
 
     while (pszString[i])
     {
-        if (pszString[i] =='\\' && 
+        if (pszString[i] =='\\' &&
             pszString[i+1] == 'n')
         {
             pszWorkString[j++] = '\n';
             i+= 2;
         }
-        else if (pszString[i] =='\\' && 
+        else if (pszString[i] =='\\' &&
                  pszString[i+1] == '\\')
         {
             pszWorkString[j++] = '\\';
@@ -540,7 +541,7 @@ char *TABUnEscapeString(char *pszString, GBool bSrcIsConst)
         }
     }
     pszWorkString[j++] = '\0';
-   
+
     return pszWorkString;
 }
 
@@ -572,7 +573,7 @@ char *TABEscapeString(char *pszString)
      * OK, we need to do some replacements... alloc a copy big enough
      * to hold the worst possible case
      *----------------------------------------------------------------*/
-    char *pszWorkString = (char *)CPLMalloc(2*sizeof(char) * 
+    char *pszWorkString = (char *)CPLMalloc(2*sizeof(char) *
                                             (strlen(pszString) +1));
 
     int i =0;
@@ -620,15 +621,15 @@ char *TABCleanFieldName(const char *pszSrcName)
     if (strlen(pszNewName) > 31)
     {
         pszNewName[31] = '\0';
-        CPLError(CE_Warning, TAB_WarningInvalidFieldName,
+        CPLError(CE_Warning, (CPLErrorNum)TAB_WarningInvalidFieldName,
                  "Field name '%s' is longer than the max of 31 characters. "
                  "'%s' will be used instead.", pszSrcName, pszNewName);
     }
 
-#if defined(_WIN32) && !defined(unix) && !defined(WIN32CE)
+#if defined(_WIN32) && !defined(unix)
     /*-----------------------------------------------------------------
      * On Windows, check if we're using a double-byte codepage, and
-     * if so then just keep the field name as is... 
+     * if so then just keep the field name as is...
      *----------------------------------------------------------------*/
     if (_getmbcp() != 0)
         return pszNewName;
@@ -640,12 +641,12 @@ char *TABCleanFieldName(const char *pszSrcName)
      *  Name:
      * Displays the field name in the name box. You can also enter new field
      * names here. Defaults are Field1, Field2, etc. A field name can contain
-     * up to 31 alphanumeric characters. Use letters, numbers, and the 
+     * up to 31 alphanumeric characters. Use letters, numbers, and the
      * underscore. Do not use spaces; instead, use the underscore character
      * (_) to separate words in a field name. Use upper and lower case for
      * legibility, but MapInfo is not case-sensitive.
      *
-     * It was also verified that extended chars with accents are also 
+     * It was also verified that extended chars with accents are also
      * accepted.
      *----------------------------------------------------------------*/
     for(int i=0; pszSrcName && pszSrcName[i] != '\0'; i++)
@@ -659,8 +660,8 @@ char *TABCleanFieldName(const char *pszSrcName)
             }
         }
         else if ( !( pszSrcName[i] == '_' ||
-                     (i!=0 && pszSrcName[i]>='0' && pszSrcName[i]<='9') || 
-                     (pszSrcName[i]>='a' && pszSrcName[i]<='z') || 
+                     (i!=0 && pszSrcName[i]>='0' && pszSrcName[i]<='9') ||
+                     (pszSrcName[i]>='a' && pszSrcName[i]<='z') ||
                      (pszSrcName[i]>='A' && pszSrcName[i]<='Z') ||
                      (GByte)pszSrcName[i]>=192 ) )
         {
@@ -671,7 +672,7 @@ char *TABCleanFieldName(const char *pszSrcName)
 
     if (numInvalidChars > 0)
     {
-        CPLError(CE_Warning, TAB_WarningInvalidFieldName,
+        CPLError(CE_Warning, (CPLErrorNum)TAB_WarningInvalidFieldName,
                  "Field name '%s' contains invalid characters. "
                  "'%s' will be used instead.", pszSrcName, pszNewName);
     }
@@ -683,13 +684,13 @@ char *TABCleanFieldName(const char *pszSrcName)
 /**********************************************************************
  * MapInfo Units string to numeric ID conversion
  **********************************************************************/
-typedef struct 
+typedef struct
 {
     int         nUnitId;
     const char *pszAbbrev;
 } MapInfoUnitsInfo;
 
-static MapInfoUnitsInfo gasUnitsList[] = 
+static const MapInfoUnitsInfo gasUnitsList[] =
 {
     {0, "mi"},
     {1, "km"},
@@ -720,13 +721,13 @@ static MapInfoUnitsInfo gasUnitsList[] =
  **********************************************************************/
 const char *TABUnitIdToString(int nId)
 {
-    MapInfoUnitsInfo *psList;
+    const MapInfoUnitsInfo *psList;
 
     psList = gasUnitsList;
 
     while(psList->nUnitId != -1)
     {
-        if (psList->nUnitId == nId) 
+        if (psList->nUnitId == nId)
             return psList->pszAbbrev;
         psList++;
     }
@@ -743,17 +744,17 @@ const char *TABUnitIdToString(int nId)
  **********************************************************************/
 int TABUnitIdFromString(const char *pszName)
 {
-    MapInfoUnitsInfo *psList;
+    const MapInfoUnitsInfo *psList;
 
     psList = gasUnitsList;
-    
+
     if( pszName == NULL )
         return 13;
 
     while(psList->nUnitId != -1)
     {
         if (psList->pszAbbrev != NULL &&
-            EQUAL(psList->pszAbbrev, pszName)) 
+            EQUAL(psList->pszAbbrev, pszName))
             return psList->nUnitId;
         psList++;
     }
@@ -761,3 +762,19 @@ int TABUnitIdFromString(const char *pszName)
     return -1;
 }
 
+
+/**********************************************************************
+ *                       TABSaturatedAdd()
+ ***********************************************************************/
+
+void TABSaturatedAdd(GInt32& nVal, GInt32 nAdd)
+{
+    if( nAdd >= 0 && nVal > INT_MAX - nAdd )
+        nVal = INT_MAX;
+    else if( nAdd == INT_MIN && nVal < 0 )
+        nVal = INT_MIN;
+    else if( nAdd != INT_MIN && nAdd < 0 && nVal < INT_MIN - nAdd )
+        nVal = INT_MIN;
+    else
+        nVal += nAdd;
+}
diff --git a/ogr/ogrsf_frmts/mitab/mitab_utils.h b/ogr/ogrsf_frmts/mitab/mitab_utils.h
index b00e9e2..40bd6a6 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_utils.h
+++ b/ogr/ogrsf_frmts/mitab/mitab_utils.h
@@ -16,16 +16,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -62,8 +62,8 @@
  *
  **********************************************************************/
 
-#ifndef _MITAB_UTILS_H_INCLUDED_
-#define _MITAB_UTILS_H_INCLUDED_
+#ifndef MITAB_UTILS_H_INCLUDED_
+#define MITAB_UTILS_H_INCLUDED_
 
 #include "ogr_geometry.h"
 
@@ -75,7 +75,7 @@
                         Function prototypes
  =====================================================================*/
 
-int TABGenerateArc(OGRLineString *poLine, int numPoints, 
+int TABGenerateArc(OGRLineString *poLine, int numPoints,
                    double dCenterX, double dCenterY,
                    double dXRadius, double dYRadius,
                    double dStartAngle, double dEndAngle);
@@ -94,6 +94,6 @@ char *TABCleanFieldName(const char *pszSrcName);
 const char *TABUnitIdToString(int nId);
 int   TABUnitIdFromString(const char *pszName);
 
-#endif /* _MITAB_UTILS_H_INCLUDED_ */
-
+void TABSaturatedAdd(GInt32& nVal, GInt32 nAdd);
 
+#endif /* MITAB_UTILS_H_INCLUDED_ */
diff --git a/ogr/ogrsf_frmts/mongodb/GNUmakefile b/ogr/ogrsf_frmts/mongodb/GNUmakefile
new file mode 100644
index 0000000..9511761
--- /dev/null
+++ b/ogr/ogrsf_frmts/mongodb/GNUmakefile
@@ -0,0 +1,14 @@
+
+
+include ../../../GDALmake.opt
+
+OBJ	=	ogrmongodbdriver.o
+
+CPPFLAGS	:=	-I../generic  $(MONGODB_INC) $(CPPFLAGS)
+# Does not even solve runtime problems
+#-DDO_NOT_USE_DEBUG_BOOL
+
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
diff --git a/ogr/ogrsf_frmts/mongodb/drv_mongodb.html b/ogr/ogrsf_frmts/mongodb/drv_mongodb.html
new file mode 100644
index 0000000..a959d99
--- /dev/null
+++ b/ogr/ogrsf_frmts/mongodb/drv_mongodb.html
@@ -0,0 +1,220 @@
+<html>
+<head>
+<title>MongoDB</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>MongoDB</h1>
+
+(GDAL/OGR >= 2.1.0)<p>
+
+This driver can connect to the a MongoDB service.<p>
+The driver supports read, creation, update and delete operations.<p>
+
+<h2>MongoDB vs OGR concepts</h2>
+
+A MongoDB collection within a database is considered as a OGR layer. A MongoDB document is considered as a OGR feature.<p>
+
+<h2>Dataset name syntax</h2>
+
+There are two main possible syntaxes:
+<ul>
+<li>One using <a href="http://docs.mongodb.org/v2.6/reference/connection-string/">MongoDB URI</a>,
+such as mongodb://[usr:pwd@]host1[:port1]...[,hostN[:portN]]][/[db][?options]]</a>
+<li>On using just MongoDB: as the name and open options to specify host, port, user, password, database, etc...</li>
+</ul>
+
+The open options available are :
+<ul>
+<li><b>URI</b>=uri: <a href="http://docs.mongodb.org/v2.6/reference/connection-string/">Connection URI</a></li>
+<li><b>HOST</b>=hostname: Server hostname. Default to localhost.</li>
+<li><b>PORT</b>=port. Server port. Default to 27017.</li>
+<li><b>DBNAME</b>=dbname. Database name. Should be specified when connecting to hosts with user authentication enabled.</li>
+<li><b>AUTH_DBNAME</b>=dbname. Authentication database name, in case it is different from the database to work onto.</li>
+<li><b>USER</b>=name. User name.</li>
+<li><b>PASSWORD</b>=password. User password.</li>
+<li><b>AUTH_JSON</b>=json_string. Authentication elements as JSon object. This is for advanced authentication.
+The JSon fields to put in the dictionary are :
+<ul>
+<li>"mechanism": The string name of the sasl mechanism to use (MONGODB-CR, SCRAM-SHA-1 or DEFAULT).  Mandatory.</li>
+<li>"user": The string name of the user to authenticate. Mandatory.</li>
+<li>"db": The database target of the auth command, which identifies the location
+of the credential information for the user.  May be "$external" if
+credential information is stored outside of the mongo cluster.  Mandatory.</li>
+<li>"pwd": The password data.</li>
+<li>"digestPassword": Boolean, set to true if the "pwd" is undigested (default)</li>
+<li>"pwd": The password data.</li>
+<li>"serviceHostname": The GSSAPI hostname to use.  Defaults to the name of the remote host.</li>
+</ul>
+</li>
+<li><b>SSL_PEM_KEY_FILE</b>=filename. SSL PEM certificate/key filename.</li>
+<li><b>SSL_PEM_KEY_PASSWORD</b>=password. SSL PEM key password.</li>
+<li><b>SSL_CA_FILE</b>=filename. SSL Certification Authority filename.</li>
+<li><b>SSL_CRL_FILE</b>=filename. SSL Certification Revocation List filename.</li>
+<li><b>SSL_ALLOW_INVALID_CERTIFICATES</b>=YES/NO. Whether to allow connections to servers with invalid certificates. Defaults to NO.</li>
+<li><b>SSL_ALLOW_INVALID_HOSTNAMES</b>=YES/NO. Whether to allow connections to servers with non-matching hostnames. Defaults to NO.</li>
+<li><b>FIPS_MODE</b>=YES/NO. Whether to activate FIPS 140-2 mode at startup. Defaults to NO.</li>
+<li><b>BATCH_SIZE</b>=number. Number of features to retrieve per batch. For most queries, the first batch returns 101 documents or just enough documents to exceed 1 megabyte. Subsequent batch size is 4 megabytes.</li>
+<li><b>FEATURE_COUNT_TO_ESTABLISH_FEATURE_DEFN</b>=number. Number of features to retrieve to establish feature definition. -1 = unlimited. Defaults to 100.</li>
+<li><b>JSON_FIELD</b>=YES/NO. Whether to include a field called "_json" with the full document as JSON. Defaults to NO.</li>
+<li><b>FLATTEN_NESTED_ATTRIBUTE</b>=YES/NO. Whether to recursively explore nested objects and produce flatten OGR attributes. Defaults to YES.</li>
+<li><b>FID</b>=name. Field name, with integer values, to use as FID. Defaults to ogc_fid.</li>
+<li><b>USE_OGR_METADATA</b>=YES/NO. Whether to use the _ogr_metadata collection to read layer metadata. Defaults to YES.</li>
+<li><b>BULK_INSERT</b>=YES/NO. Whether to use bulk insert for feature creation. Defaults to YES.</li>
+</ul>
+
+Note: the SSL_* and FIPS_MODE options must be set to the same values when opening
+multiple types MongoDB databases. This is a limitation of the Mongo C++ driver.<p>
+
+<h2>Filtering</h2>
+
+The driver will forward any spatial filter set with SetSpatialFilter() to the server when
+a "2d" or "2dsphere" spatial index is available on the geometry field.<p>
+
+However, in the current state, SQL attribute filters set with SetAttributeFilter()
+are evaluated only on client-side. To enable server-side filtering, the string
+passed to SetAttributeFilter() must be a JSon object in the
+<a href="http://docs.mongodb.org/v2.6/reference/method/db.collection.find/">MongoDB filter syntax</a>.<p>
+
+<h2>Paging</h2>
+
+Features are retrieved from the server by chunks of 101 documents or just enough
+documents to exceed 1 megabyte. Subsequent batch size is 4 megabytes. This can be
+altered with the BATCH_SIZE open option.<p>
+
+<h2>Schema</h2>
+
+When reading a MongoDB collection, OGR must establish the schema of attribute and geometry
+fields, since, contrary to MongoDB collections which are schema-less, OGR has a fixed schema concept.<p>
+
+In the general case, OGR will read the first 100 documents (can be altered with
+the FEATURE_COUNT_TO_ESTABLISH_FEATURE_DEFN open option) of the collection and build
+the schema that best fit to the found fields and values.<p>
+
+If the collection/layer has been previously created with OGR, a _ogr_metadata special
+collection contains the OGR schema, in which case it will be directly used. It might
+be possible to ignore the schema written in _ogr_metadata by setting the USE_OGR_METADATA=NO
+open option.<p>
+
+It is also possible to set the JSON_FIELD=YES open option so that a _json special
+field is added to the OGR schema. When reading MongoDB documents as OGR features,
+the full JSon version of the document will be stored in the _json field. This might
+be useful in case of complex documents or with data types that do not translate well
+in OGR data types. On creation/update of documents, if the _json field is present
+and set, its content will be used directly (other fields will be ignored).<p>
+
+<h2>Feature ID</h2>
+
+MongoDB have a special _id field that contains the unique ID of the document. This
+field is returned as an OGR field, but cannot be used as the OGR special FeatureID
+field, which must be of integer type. By default, OGR will try to read a potential
+'ogc_fid' field to set the OGR FeatureID. The name of this field to look up can
+be set with the FID open option. If the field is not found, the FID returned by
+OGR will be a sequential number starting at 1, but it is not guaranteed to be
+stable at all.<p>
+
+<h2>ExecuteSQL() interface</h2>
+
+If specifying "MongoDB" as the dialect of ExecuteSQL(), a JSon string with a
+serialized <a href="http://docs.mongodb.org/v2.6/reference/command/">MongoDB command</a>
+can be passed. The result will be returned as a
+JSon string in a single OGR feature.<p>
+
+Standard SQL requests will be executed on client-side.<p>
+
+<h2>Write support</h2>
+
+Layer/collection creation and deletion is possible.<p>
+
+Write support is only enabled when the datasource is opened in update mode.<p>
+
+When inserting a new feature with CreateFeature(), and if the command is successful, OGR will fetch the
+returned _id and use it for the SetFeature() operation.<p>
+
+<h2>Layer creation options</h2>
+
+The following layer creation options are supported:
+<ul>
+<li><b>OVERWRITE</b>=YES/NO. Whether to overwrite an existing collection with the layer name to be created. Defaults to NO.</li>
+<li><b>GEOMETRY_NAME</b>=name. Name of geometry column. Defaults to 'geometry'.</li>
+<li><b>SPATIAL_INDEX</b>=YES/NO. Whether to create a spatial index (2dsphere). Defaults to YES.</li>
+<li><b>FID</b>=string. Field name, with integer values, to use as FID. Defaults to 'ogc_fid'</li>
+<li><b>WRITE_OGR_METADATA</b>=YES/NO. Whether to create a description of layer fields in the _ogr_metadata collection. Defaults to YES.</li>
+<li><b>DOT_AS_NESTED_FIELD</b>=YES/NO. Whether to consider dot character in field name as sub-document. Defaults to YES.</li>
+<li><b>IGNORE_SOURCE_ID</b>=YES/NO. Whether to ignore _id field in features passed to CreateFeature(). Defaults to NO.</li>
+</ul>
+
+<h2>Examples</h2>
+
+<li>
+Listing the tables of a MongoDB database:
+<pre>
+ogrinfo -ro mongodb://user:password@ds047612.mongolab.com:47612/gdalautotest
+</pre>
+<p>
+
+<li>
+Filtering on a MongoDB field:
+<pre>
+ogrinfo -ro mongodb://user:password@ds047612.mongolab.com:47612/gdalautotest -where '{ "field": 5 }'
+</pre>
+<p>
+
+<li>
+Creating and populating a collection from a shapefile:
+<pre>
+ogr2ogr -f mongodb mongodb://user:password@ds047612.mongolab.com:47612/gdalautotest shapefile.shp
+</pre>
+<p>
+
+<h2>Build instructions</h2>
+
+GDAL/OGR must be built against the <a href="https://github.com/mongodb/mongo-cxx-driver">MongoDB C++ driver client library</a>,
+in its "legacy" version (tested with 1.0.2), in order to the MongoDB driver to be compiled.<p>
+
+You must first follow <a href="https://github.com/mongodb/mongo-cxx-driver/wiki/Download-and-Compile-the-Legacy-Driver">MongoDB C++ driver client build instructions</a>,
+which require to have Boost libraries available.
+<p>
+Then:
+<ul>
+<li>
+On Linux/Unix, run ./configure --with-mongocxx=/path/to/installation/root (if the
+driver is already installed in /usr, this is not needed).
+If the Boost libraries are not found in the system paths, the path to the directory
+when the libraries are found can be specified --with-boost-lib-path=/path/to/boost/libs .
+<p>
+</li>
+<li>
+On Windows, uncomment and adapt the following in nmake.opt (or add in nmake.local):
+<pre>
+# Uncomment for MongoDB support
+# This configuration is valid for a libmongoclient built as a DLL with:
+# scons.bat --32 --dynamic-windows --sharedclient --prefix=c:\users\even\dev\mongo-client-install
+#           --cpppath=c:\users\even\dev\boost_1_55_0_32bit --libpath=c:\users\even\dev\boost_1_55_0_32bit\lib32-msvc-10.0 install
+
+# Uncomment if plugin is preferred
+#MONGODB_PLUGIN = YES
+
+MONGODB_INC = c:/users/even/dev/mongo-client-install/include
+# Boost library names must be edited to reflect the actual MSVC and Boost versions
+BOOST_INC = c:/users/even/dev/boost_1_55_0_32bit
+BOOST_LIB_PATH= c:\users\even\dev\boost_1_55_0_32bit\lib32-msvc-10.0
+MONGODB_LIBS = c:/users/even/dev/mongo-client-install/lib/mongoclient.lib \
+               $(BOOST_LIB_PATH)\libboost_thread-vc100-mt-1_55.lib \
+               $(BOOST_LIB_PATH)\libboost_system-vc100-mt-1_55.lib \
+               $(BOOST_LIB_PATH)\libboost_date_time-vc100-mt-1_55.lib \
+               $(BOOST_LIB_PATH)\libboost_chrono-vc100-mt-1_55.lib
+</pre>
+</li>
+</ul>
+
+<h2>See Also</h2>
+
+<ul>
+<li> <a href="https://github.com/mongodb/mongo-cxx-driver">MongoDB C++ Driver</a><p>
+<li> <a href="http://docs.mongodb.org/v2.6/reference/">MongoDB 2.6 Manual</a><p>
+</ul>
+
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/mongodb/makefile.vc b/ogr/ogrsf_frmts/mongodb/makefile.vc
new file mode 100644
index 0000000..55e80e0
--- /dev/null
+++ b/ogr/ogrsf_frmts/mongodb/makefile.vc
@@ -0,0 +1,32 @@
+OBJ     =       ogrmongodbdriver.obj
+EXTRAFLAGS =	-I.. -I..\generic -I..\.. -I$(MONGODB_INC) -I$(BOOST_INC) $(MONGODB_CFLAGS)
+
+GDAL_ROOT	=	..\..\..
+
+PLUGIN_DLL 	=	ogr_MongoDB.dll
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+default:	$(OBJ)
+
+all:	default
+
+clean:
+	-del *.obj
+	-del *.dll
+	-del *.exp
+	-del *.lib
+	-del *.manifest
+	-del *.pdb
+	-del *.tlh
+
+plugin: $(PLUGIN_DLL)
+
+$(PLUGIN_DLL):	$(OBJ)
+	link /dll $(LDEBUG) /out:$(PLUGIN_DLL) $(OBJ) $(GDAL_ROOT)/gdal_i.lib $(MONGODB_LIBS) wsock32.lib
+	if exist $(PLUGIN_DLL).manifest mt -manifest $(PLUGIN_DLL).manifest -outputresource:$(PLUGIN_DLL);2
+
+
+plugin-install:
+	-mkdir $(PLUGINDIR)
+	$(INSTALL) $(PLUGIN_DLL) $(PLUGINDIR)
diff --git a/ogr/ogrsf_frmts/mongodb/mongocxx_headers.h b/ogr/ogrsf_frmts/mongodb/mongocxx_headers.h
new file mode 100644
index 0000000..6f0831b
--- /dev/null
+++ b/ogr/ogrsf_frmts/mongodb/mongocxx_headers.h
@@ -0,0 +1,56 @@
+/******************************************************************************
+ *
+ * Project:  GDAL
+ * Purpose:  Includes MongoDB C++ SDK headers
+ * Author:   Even Rouault <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+#ifndef MONGOCXX_HEADERS_H
+#define MONGOCXX_HEADERS_H
+
+#if ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) && !defined(_MSC_VER))
+#pragma GCC system_header
+#endif
+
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable : 4351 )
+#pragma warning( disable : 4512 )
+#pragma warning( disable : 4267 )
+#pragma warning( disable : 4005 )
+#pragma warning( disable : 4244 )
+#endif
+
+#ifdef WIN32
+#include <winsock2.h>
+#undef min
+#undef max
+#endif
+#include "mongo/client/dbclient.h" // for the driver
+
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
+
+#endif
diff --git a/ogr/ogrsf_frmts/mongodb/ogrmongodbdriver.cpp b/ogr/ogrsf_frmts/mongodb/ogrmongodbdriver.cpp
new file mode 100644
index 0000000..6c3017f
--- /dev/null
+++ b/ogr/ogrsf_frmts/mongodb/ogrmongodbdriver.cpp
@@ -0,0 +1,2847 @@
+/******************************************************************************
+ * $Id: ogrmongodbdriver.cpp 33714 2016-03-13 05:42:13Z goatbar $
+ *
+ * Project:  MongoDB Translator
+ * Purpose:  Implements OGRMongoDBDriver.
+ * Author:   Even Rouault, even.rouault at spatialys.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "mongocxx_headers.h"
+
+#include "gdal_priv.h"
+#include "ogrsf_frmts.h"
+
+#include "ogr_p.h"
+#include "cpl_time.h"
+#include <limits>
+
+// g++ -DDEBUG -g -Wall -fPIC -shared -o ogr_MongoDB.so -I/home/even/boost_1_53_0 -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/mongodb ogr/ogrsf_frmts/mongodb/*.c* -L. -lgdal -I/home/even/mongo-cxx-1.0.2-install/include -L/home/even/mongo-cxx-1.0.2-install/lib -lmongoclient -L/home/even/boost_1_53_0/stage/lib -lboost_system -lboost_thread -lboost_regex
+CPL_CVSID("$Id: ogrmongodbdriver.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+
+#define MAX_DOCS_IN_BULK                1000
+
+extern "C" void RegisterOGRMongoDB();
+
+using namespace mongo;
+using mongo::client::Options;
+
+#if __cplusplus >= 201103L
+#define UNIQUE_PTR       std::unique_ptr
+#else
+#define UNIQUE_PTR       std::auto_ptr
+#endif
+
+static int bMongoInitialized = -1;
+static CPLString osStaticPEMKeyFile;
+static CPLString osStaticPEMKeyPassword;
+static CPLString osStaticCAFile;
+static CPLString osStaticCRLFile;
+static int bStaticAllowInvalidCertificates = FALSE;
+static int bStaticAllowInvalidHostnames = FALSE;
+static int bStaticFIPSMode = FALSE;
+
+class OGRMongoDBDataSource;
+
+typedef struct _IntOrMap IntOrMap;
+
+struct _IntOrMap
+{
+    int bIsMap;
+    union
+    {
+        int nField;
+        std::map< CPLString, IntOrMap*>* poMap;
+    } u;
+};
+
+class OGRMongoDBLayer: public OGRLayer
+{
+            OGRMongoDBDataSource    *m_poDS;
+            OGRFeatureDefn          *m_poFeatureDefn;
+            CPLString                m_osDatabase;
+            CPLString                m_osCollection;
+            CPLString                m_osQualifiedCollection;
+            int                      m_bHasEstablishedFeatureDefn;
+            GIntBig                  m_nIndex, m_nNextFID;
+            UNIQUE_PTR<DBClientCursor> m_poCursor;
+            int                      m_bCursorValid;
+            BSONObj                  m_oQueryAttr, m_oQuerySpat;
+            CPLString                m_osFID;
+            int                      m_bLayerMetadataUpdatable;
+            int                      m_bUpdateLayerMetadata;
+            int                      m_bDotAsNestedField;
+            int                      m_bIgnoreSourceID;
+            int                      m_bCreateSpatialIndex;
+            BulkOperationBuilder*    m_poBulkBuilder;
+            int                      m_nFeaturesInBulk;
+
+            std::vector< std::vector<CPLString> > m_aaosFieldPaths;
+
+            std::vector< std::vector<CPLString> > m_aaosGeomFieldPaths;
+            std::vector< CPLString > m_aosGeomIndexes;
+            std::vector< OGRCoordinateTransformation* > m_apoCT;
+
+            std::map< CPLString, CPLString> CollectGeomIndices();
+            int                      ReadOGRMetadata(std::map< CPLString, CPLString>& oMapIndices);
+            void                     EstablishFeatureDefn();
+            void                     WriteOGRMetadata();
+            OGRFeature*              Translate(BSONObj& obj);
+            void                     AddOrUpdateField(const char* pszAttrName,
+                                       const BSONElement* poElt,
+                                       char chNestedAttributeSeparator,
+                                       std::vector<CPLString>& aosPaths,
+                                       std::map< CPLString, CPLString>& oMapIndices);
+
+            void                     SerializeField(BSONObjBuilder& b,
+                                                    OGRFeature *poFeature,
+                                                    int iField,
+                                                    const char* pszJSonField);
+            void                     SerializeGeometry(BSONObjBuilder& b,
+                                                       OGRGeometry* poGeom, int iField,
+                                                       const char* pszJSonField);
+            void                     SerializeRecursive(BSONObjBuilder& b,
+                                         OGRFeature *poFeature,
+                                         std::map< CPLString, IntOrMap*>& aoMap );
+            void                     InsertInMap(IntOrMap* rootMap,
+                                                  std::map< std::vector<CPLString>, IntOrMap*>& aoMap,
+                                                  const std::vector<CPLString>& aosFieldPathFull,
+                                                  int nField);
+            BSONObj                  BuildBSONObjFromFeature(OGRFeature* poFeature, int bUpdate);
+            BSONObj                  BuildQuery();
+
+public:
+            OGRMongoDBLayer(OGRMongoDBDataSource* m_poDS,
+                            const char* pszDatabase,
+                            const char* pszCollection);
+           ~OGRMongoDBLayer();
+
+            virtual OGRFeatureDefn* GetLayerDefn();
+            virtual const char* GetName() { return m_poFeatureDefn->GetName(); }
+            virtual void        ResetReading();
+            virtual OGRFeature* GetNextFeature();
+            virtual OGRFeature* GetFeature(GIntBig nFID);
+            virtual OGRErr      DeleteFeature(GIntBig nFID);
+            virtual int         TestCapability(const char* pszCap);
+            virtual GIntBig     GetFeatureCount(int bForce);
+            virtual OGRErr      SetAttributeFilter(const char* pszFilter);
+            virtual void        SetSpatialFilter( OGRGeometry *poGeom ) { SetSpatialFilter(0, poGeom); }
+            virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom );
+            virtual const char* GetFIDColumn();
+            virtual OGRErr      CreateField( OGRFieldDefn *poFieldIn, int bApproxOK );
+            virtual OGRErr      CreateGeomField( OGRGeomFieldDefn *poFieldIn, int bApproxOK );
+            virtual OGRErr      ICreateFeature(OGRFeature* poFeature);
+            virtual OGRErr      ISetFeature(OGRFeature* poFeature);
+
+            virtual OGRErr      SyncToDisk();
+
+            const CPLString&    GetDatabase() const { return m_osDatabase; }
+            const CPLString&    GetCollection() const { return m_osCollection; }
+            const CPLString&    GetQualifiedCollection() const { return m_osQualifiedCollection; }
+            void                SetFID(const CPLString& m_osFIDIn) { m_osFID = m_osFIDIn; }
+            void                SetCreateLayerMetadata(int bFlag) { m_bLayerMetadataUpdatable = bFlag; m_bUpdateLayerMetadata = bFlag; }
+            void                SetDotAsNestedField(int bFlag) { m_bDotAsNestedField = bFlag; }
+            void                SetIgnoreSourceID(int bFlag) { m_bIgnoreSourceID = bFlag; }
+            void                SetCreateSpatialIndex(int bFlag) { m_bCreateSpatialIndex = bFlag; }
+};
+
+
+class OGRMongoDBDataSource: public GDALDataset
+{
+            DBClientBase *m_poConn;
+            CPLString     m_osDatabase;
+            std::vector<OGRMongoDBLayer*> m_apoLayers;
+            int           m_nBatchSize;
+            bool          m_bFlattenNestedAttributes;
+            int           m_nFeatureCountToEstablishFeatureDefn;
+            int           m_bJSonField;
+            CPLString     m_osFID;
+            int           m_bUseOGRMetadata;
+            int           m_bBulkInsert;
+
+            static int Initialize(char** papszOpenOptions);
+            int        ListLayers(const char* pszDatabase);
+
+public:
+            OGRMongoDBDataSource();
+            ~OGRMongoDBDataSource();
+
+            int Open(const char* pszFilename, GDALAccess eAccess, char** papszOpenOptions);
+            virtual int GetLayerCount() { return (int)m_apoLayers.size(); }
+            virtual OGRLayer* GetLayer(int nIdx);
+            virtual int         TestCapability(const char* pszCap);
+            virtual OGRLayer   *ICreateLayer( const char *pszName,
+                                             OGRSpatialReference *poSpatialRef = NULL,
+                                             OGRwkbGeometryType eGType = wkbUnknown,
+                                             char ** papszOptions = NULL );
+            virtual OGRErr      DeleteLayer( int iLayer );
+            virtual OGRLayer   *GetLayerByName(const char* pszLayerName);
+
+            virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
+                                            OGRGeometry *poSpatialFilter,
+                                            const char *pszDialect );
+            virtual void        ReleaseResultSet( OGRLayer * poLayer );
+
+            const CPLString& GetDatabase() const { return m_osDatabase; }
+            DBClientBase    *GetConn() const { return m_poConn; }
+            int              GetBatchSize() const { return m_nBatchSize; }
+            bool             GetFlattenNestedAttributes() const { return m_bFlattenNestedAttributes; }
+            int              GetFeatureCountToEstablishFeatureDefn() const { return m_nFeatureCountToEstablishFeatureDefn; }
+            int              JSonField() const { return m_bJSonField; }
+            int              UseOGRMetadata() const { return m_bUseOGRMetadata; }
+            int              BulkInsert() const { return m_bBulkInsert; }
+            const CPLString& GetFID() const { return m_osFID; }
+};
+
+/************************************************************************/
+/*                            OGRMongoDBLayer()                         */
+/************************************************************************/
+
+OGRMongoDBLayer::OGRMongoDBLayer(OGRMongoDBDataSource* poDS,
+                            const char* pszDatabase,
+                            const char* pszCollection)
+{
+    m_poDS = poDS;
+    m_osDatabase = pszDatabase;
+    m_osCollection = pszCollection;
+    m_osQualifiedCollection = CPLSPrintf("%s.%s", m_osDatabase.c_str(), m_osCollection.c_str());
+    if( m_poDS->GetDatabase().size() )
+        m_poFeatureDefn = new OGRFeatureDefn(pszCollection);
+    else
+        m_poFeatureDefn = new OGRFeatureDefn(m_osQualifiedCollection);
+    m_poFeatureDefn->SetGeomType(wkbNone);
+    SetDescription(m_poFeatureDefn->GetName());
+    m_poFeatureDefn->Reference();
+    m_bHasEstablishedFeatureDefn = FALSE;
+    m_bCursorValid = FALSE;
+    m_nIndex = 0;
+    m_nNextFID = 0;
+    m_bLayerMetadataUpdatable = FALSE;
+    m_bUpdateLayerMetadata = FALSE;
+    m_bDotAsNestedField = TRUE;
+    m_bIgnoreSourceID = FALSE;
+    m_bCreateSpatialIndex = TRUE;
+    m_poBulkBuilder = NULL;
+    m_nFeaturesInBulk = 0;
+
+    OGRFieldDefn oFieldDefn("_id", OFTString);
+    std::vector<CPLString> aosPath;
+    aosPath.push_back("_id");
+    m_aaosFieldPaths.push_back(aosPath);
+    m_poFeatureDefn->AddFieldDefn(&oFieldDefn);
+}
+
+/************************************************************************/
+/*                            ~OGRMongoDBLayer()                        */
+/************************************************************************/
+
+OGRMongoDBLayer::~OGRMongoDBLayer()
+{
+    SyncToDisk();
+
+    for(int i=0;i<(int)m_apoCT.size();i++)
+        delete m_apoCT[i];
+    m_poFeatureDefn->Release();
+}
+
+/************************************************************************/
+/*                            WriteOGRMetadata()                        */
+/************************************************************************/
+
+void OGRMongoDBLayer::WriteOGRMetadata()
+{
+    //CPLDebug("MongoDB", "WriteOGRMetadata(%s)", m_osQualifiedCollection.c_str());
+    if( !m_bUpdateLayerMetadata )
+        return;
+    m_bUpdateLayerMetadata = FALSE;
+
+    try
+    {
+        BSONObjBuilder b;
+
+        b.append("layer", m_osCollection.c_str());
+
+        if( m_osFID.size() )
+        {
+            b.append( "fid", m_osFID.c_str() );
+        }
+
+        BSONArrayBuilder fields;
+
+        CPLAssert( (int)m_aaosFieldPaths.size() == m_poFeatureDefn->GetFieldCount() );
+        for(int i=1;i<m_poFeatureDefn->GetFieldCount();i++)
+        {
+            OGRFieldDefn* poFieldDefn = m_poFeatureDefn->GetFieldDefn(i);
+            const char* pszFieldName = poFieldDefn->GetNameRef();
+            if( EQUAL(pszFieldName, "_json") )
+                continue;
+            BSONArrayBuilder path;
+            for(int j=0;j<(int)m_aaosFieldPaths[i].size();j++)
+                path.append(m_aaosFieldPaths[i][j]);
+            OGRFieldType eType = poFieldDefn->GetType();
+            if( eType == OFTInteger && poFieldDefn->GetSubType() == OFSTBoolean )
+                fields.append(BSON("name" << pszFieldName <<
+                                "type" << OGR_GetFieldTypeName(eType) <<
+                                "subtype" << "Boolean" <<
+                                "path" << path.arr()));
+            else
+                fields.append(BSON("name" << pszFieldName <<
+                                "type" << OGR_GetFieldTypeName(eType) <<
+                                "path" << path.arr()));
+        }
+        b.append("fields", fields.arr());
+
+        BSONArrayBuilder geomfields;
+        CPLAssert( (int)m_aaosGeomFieldPaths.size() == m_poFeatureDefn->GetGeomFieldCount() );
+        for(int i=0;i<m_poFeatureDefn->GetGeomFieldCount();i++)
+        {
+            OGRGeomFieldDefn* poGeomFieldDefn = m_poFeatureDefn->GetGeomFieldDefn(i);
+            const char* pszFieldName = poGeomFieldDefn->GetNameRef();
+            BSONArrayBuilder path;
+            for(int j=0;j<(int)m_aaosGeomFieldPaths[i].size();j++)
+                path.append(m_aaosGeomFieldPaths[i][j]);
+            const char* pszGeomType = OGRToOGCGeomType(poGeomFieldDefn->GetType());
+            geomfields.append(BSON("name" << pszFieldName <<
+                                    "type" << pszGeomType <<
+                                    "path" << path.arr()));
+        }
+        b.append("geomfields", geomfields.arr());
+
+        m_poDS->GetConn()->findAndRemove(
+            CPLSPrintf("%s._ogr_metadata", m_osDatabase.c_str()),
+            BSON("layer" << m_osCollection.c_str()),
+            BSONObj(),
+            BSONObj());
+        m_poDS->GetConn()->insert( CPLSPrintf("%s._ogr_metadata", m_osDatabase.c_str()), b.obj() );
+    }
+    catch( const DBException &e )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "%s: %s",
+                 "WriteOGRMetadata()", e.what());
+    }
+}
+
+/************************************************************************/
+/*                              SyncToDisk()                            */
+/************************************************************************/
+
+OGRErr OGRMongoDBLayer::SyncToDisk()
+{
+    OGRErr eErr = OGRERR_NONE;
+    if( m_poBulkBuilder != NULL )
+    {
+        WriteResult writeResult;
+        try
+        {
+            m_poBulkBuilder->execute(NULL, &writeResult);
+            eErr = writeResult.hasErrors() ? OGRERR_FAILURE: OGRERR_NONE;
+        }
+        catch( const DBException &e )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "%s: %s",
+                    "Bulk write", e.what());
+            eErr = OGRERR_FAILURE;
+        }
+        delete m_poBulkBuilder;
+        m_poBulkBuilder = NULL;
+        m_nFeaturesInBulk = 0;
+    }
+
+    WriteOGRMetadata();
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRMongoDBLayer::ResetReading()
+{
+    m_bCursorValid = FALSE;
+    m_nIndex = 0;
+}
+
+/************************************************************************/
+/*                            GetLayerDefn()                            */
+/************************************************************************/
+
+OGRFeatureDefn* OGRMongoDBLayer::GetLayerDefn()
+{
+    if( !m_bHasEstablishedFeatureDefn )
+        EstablishFeatureDefn();
+    return m_poFeatureDefn;
+}
+
+/************************************************************************/
+/*                     OGRMongoDBGetFieldTypeFromBSON()                 */
+/************************************************************************/
+
+static
+OGRFieldType OGRMongoDBGetFieldTypeFromBSON( const BSONElement* poElt,
+                                             OGRFieldSubType& eSubType )
+{
+    eSubType = OFSTNone;
+
+    BSONType eBSONType = poElt->type();
+    if( eBSONType == Bool )
+    {
+        eSubType = OFSTBoolean;
+        return OFTInteger;
+    }
+    else if( eBSONType == NumberDouble )
+        return OFTReal;
+    else if( eBSONType == NumberInt )
+        return OFTInteger;
+    else if( eBSONType == NumberLong )
+        return OFTInteger64;
+    else if( eBSONType == String )
+        return OFTString;
+    else if( eBSONType == Array )
+    {
+        std::vector<BSONElement> oArray = poElt->Array();
+        int nSize = (int)oArray.size();
+        if (nSize == 0)
+            return OFTStringList; /* we don't know, so let's assume it's a string list */
+        OGRFieldType eType = OFTIntegerList;
+        int bOnlyBoolean = TRUE;
+        for(int i=0;i<nSize;i++)
+        {
+            BSONElement& elt = oArray[i];
+            eBSONType = elt.type();
+
+            bOnlyBoolean &= (eBSONType == Bool);
+            if (eBSONType == NumberDouble)
+                eType = OFTRealList;
+            else if (eType == OFTIntegerList && eBSONType == NumberLong)
+                eType = OFTInteger64List;
+            else if (eBSONType != NumberInt &&
+                     eBSONType != NumberLong &&
+                     eBSONType != Bool)
+                return OFTStringList;
+        }
+        if( bOnlyBoolean )
+            eSubType = OFSTBoolean;
+        return eType;
+    }
+    else if( eBSONType == Date )
+        return OFTDateTime;
+    else if( eBSONType == BinData )
+        return OFTBinary;
+    else
+        return OFTString; /* null, object */
+}
+
+/************************************************************************/
+/*                         AddOrUpdateField()                           */
+/************************************************************************/
+
+void OGRMongoDBLayer::AddOrUpdateField(const char* pszAttrName,
+                                       const BSONElement* poElt,
+                                       char chNestedAttributeSeparator,
+                                       std::vector<CPLString>& aosPaths,
+                                       std::map< CPLString, CPLString>& oMapIndices)
+{
+    BSONType eBSONType = poElt->type();
+    if( eBSONType == jstNULL || eBSONType == Undefined ||
+        eBSONType == MinKey || eBSONType == MaxKey )
+        return;
+
+    if( eBSONType == Object )
+    {
+        BSONObj obj(poElt->Obj());
+        BSONElement eltType = obj.getField("type");
+        if( !eltType.eoo() && eltType.type() == String )
+        {
+            OGRwkbGeometryType eGeomType = OGRFromOGCGeomType(eltType.String().c_str());
+            if( eGeomType != wkbUnknown )
+            {
+                int nIndex = m_poFeatureDefn->GetGeomFieldIndex(pszAttrName);
+                if( nIndex < 0 )
+                {
+                    OGRGeomFieldDefn fldDefn( pszAttrName, eGeomType );
+                    OGRSpatialReference* poSRS = new OGRSpatialReference();
+                    poSRS->SetFromUserInput(SRS_WKT_WGS84);
+                    fldDefn.SetSpatialRef(poSRS);
+                    poSRS->Release();
+                    m_poFeatureDefn->AddGeomFieldDefn( &fldDefn );
+
+                    aosPaths.push_back(poElt->fieldName());
+                    m_aaosGeomFieldPaths.push_back(aosPaths);
+                    if( oMapIndices.find(pszAttrName) == oMapIndices.end() )
+                        m_aosGeomIndexes.push_back(oMapIndices[pszAttrName]);
+                    else
+                        m_aosGeomIndexes.push_back("none");
+                    m_apoCT.push_back(NULL);
+                }
+                else
+                {
+                    OGRGeomFieldDefn* poFDefn = m_poFeatureDefn->GetGeomFieldDefn(nIndex);
+                    if( poFDefn->GetType() != eGeomType )
+                        poFDefn->SetType(wkbUnknown);
+                }
+            }
+        }
+        else if( m_poDS->GetFlattenNestedAttributes() )
+        {
+            if( m_poFeatureDefn->GetGeomFieldIndex(pszAttrName) >= 0 )
+                return;
+            aosPaths.push_back(poElt->fieldName());
+            for( BSONObj::iterator i(obj); i.more(); )
+            {
+                BSONElement elt(i.next());
+                char szSeparator[2];
+                szSeparator[0] = chNestedAttributeSeparator;
+                szSeparator[1] = 0;
+                CPLString osAttrName(CPLSPrintf("%s%s%s", pszAttrName, szSeparator,
+                                                elt.fieldName()));
+
+                std::vector<CPLString> aosNewPaths(aosPaths);
+                AddOrUpdateField(osAttrName, &elt,chNestedAttributeSeparator,
+                                 aosNewPaths, oMapIndices);
+            }
+            return;
+        }
+    }
+    else if( eBSONType == Array )
+    {
+        if( m_poFeatureDefn->GetGeomFieldIndex(pszAttrName) >= 0 )
+            return;
+        if( oMapIndices.find(pszAttrName) != oMapIndices.end() &&
+            oMapIndices[pszAttrName] == "2d" )
+        {
+            OGRGeomFieldDefn fldDefn( pszAttrName, wkbPoint );
+            OGRSpatialReference* poSRS = new OGRSpatialReference();
+            poSRS->SetFromUserInput(SRS_WKT_WGS84);
+            fldDefn.SetSpatialRef(poSRS);
+            poSRS->Release();
+            m_poFeatureDefn->AddGeomFieldDefn( &fldDefn );
+
+            aosPaths.push_back(poElt->fieldName());
+            m_aaosGeomFieldPaths.push_back(aosPaths);
+            m_aosGeomIndexes.push_back("2d");
+            m_apoCT.push_back(NULL);
+        }
+    }
+
+    if( m_poFeatureDefn->GetGeomFieldIndex(pszAttrName) >= 0 )
+        return;
+
+    OGRFieldSubType eNewSubType;
+    OGRFieldType eNewType = OGRMongoDBGetFieldTypeFromBSON( poElt, eNewSubType );
+
+    int nIndex = m_poFeatureDefn->GetFieldIndex(pszAttrName);
+    if( nIndex < 0 )
+    {
+        OGRFieldDefn fldDefn( pszAttrName, eNewType );
+        fldDefn.SetSubType(eNewSubType);
+        if( eNewSubType == OFSTBoolean )
+            fldDefn.SetWidth(1);
+        m_poFeatureDefn->AddFieldDefn( &fldDefn );
+
+        aosPaths.push_back(poElt->fieldName());
+        m_aaosFieldPaths.push_back(aosPaths);
+    }
+    else
+    {
+        OGRFieldDefn* poFDefn = m_poFeatureDefn->GetFieldDefn(nIndex);
+        OGRUpdateFieldType(poFDefn, eNewType, eNewSubType);
+    }
+}
+
+/************************************************************************/
+/*                         CollectGeomIndices()                         */
+/************************************************************************/
+
+std::map< CPLString, CPLString> OGRMongoDBLayer::CollectGeomIndices()
+{
+    std::map< CPLString, CPLString> oMapIndices;
+    try
+    {
+        UNIQUE_PTR<DBClientCursor> cursor =
+            m_poDS->GetConn()->enumerateIndexes(m_osQualifiedCollection);
+        if( cursor.get() == NULL )
+            return oMapIndices;
+        while( cursor->more() )
+        {
+            BSONObj obj = cursor->nextSafe();
+            BSONElement key = obj.getField("key");
+            if( !key.eoo() && key.type() == Object )
+            {
+                for( BSONObj::iterator i(key.Obj()); i.more(); )
+                {
+                    BSONElement elt(i.next());
+                    if( elt.type() == String &&
+                        (elt.String() == "2d" || elt.String() == "2dsphere") )
+                    {
+                        //CPLDebug("MongoDB", "Index %s for %s of %s",
+                        //         elt.String().c_str(), elt.fieldName(), m_osQualifiedCollection.c_str());
+                        oMapIndices[elt.fieldName()] = elt.String().c_str();
+                    }
+                }
+            }
+        }
+    }
+    catch( const DBException &e )
+    {
+        CPLDebug("MongoDB", "Error when listing indices: %s", e.what());
+    }
+    return oMapIndices;
+}
+
+/************************************************************************/
+/*                          ReadOGRMetadata()                           */
+/************************************************************************/
+
+int OGRMongoDBLayer::ReadOGRMetadata(std::map< CPLString, CPLString>& oMapIndices)
+{
+    try
+    {
+        UNIQUE_PTR<DBClientCursor> cursor = m_poDS->GetConn()->query(
+            CPLSPrintf("%s._ogr_metadata", m_osDatabase.c_str()),
+            BSON("layer" << m_osCollection.c_str()), 1);
+        if( cursor->more() )
+        {
+            BSONObj obj = cursor->nextSafe();
+
+            BSONElement fid = obj.getField("fid");
+            if( !fid.eoo() && fid.type() == String )
+                m_osFID = fid.String();
+
+            BSONElement fields = obj.getField("fields");
+            if( !fields.eoo() && fields.type() == Array )
+            {
+                std::vector<BSONElement> oArray = fields.Array();
+                int nSize = (int)oArray.size();
+                for(int i=0;i<nSize;i++)
+                {
+                    BSONElement& elt = oArray[i];
+                    if( elt.type() == Object )
+                    {
+                        BSONObj obj2(elt.Obj());
+                        BSONElement name = obj2.getField("name");
+                        BSONElement type = obj2.getField("type");
+                        BSONElement subtype = obj2.getField("subtype");
+                        BSONElement path = obj2.getField("path");
+                        if( !name.eoo() && name.type() == String &&
+                            !type.eoo() && type.type() == String &&
+                            !path.eoo() && path.type() == Array )
+                        {
+                            if( name.String() == "_id" )
+                                continue;
+                            OGRFieldType eType(OFTString);
+                            for(int j=0; j<=OFTMaxType;j++)
+                            {
+                                if( EQUAL(OGR_GetFieldTypeName((OGRFieldType)j),
+                                            type.String().c_str()) )
+                                {
+                                    eType = (OGRFieldType)j;
+                                    break;
+                                }
+                            }
+                            OGRFieldDefn oFieldDefn(name.String().c_str(), eType);
+                            if( !subtype.eoo() && subtype.type() == String &&
+                                subtype.String() == "Boolean" )
+                                oFieldDefn.SetSubType(OFSTBoolean);
+                            m_poFeatureDefn->AddFieldDefn(&oFieldDefn);
+
+                            std::vector<CPLString> aosPaths;
+                            std::vector<BSONElement> oPathArray = path.Array();
+                            for(int j=0;j<(int)oPathArray.size();j++)
+                            {
+                                BSONElement& eltPath = oPathArray[j];
+                                aosPaths.push_back(eltPath.String().c_str());
+                            }
+                            m_aaosFieldPaths.push_back(aosPaths);
+                        }
+                    }
+                }
+            }
+
+            BSONElement geomfields = obj.getField("geomfields");
+            if( !geomfields.eoo() && geomfields.type() == Array )
+            {
+                std::vector<BSONElement> oArray = geomfields.Array();
+                int nSize = (int)oArray.size();
+                for(int i=0;i<nSize;i++)
+                {
+                    BSONElement& elt = oArray[i];
+                    if( elt.type() == Object )
+                    {
+                        BSONObj obj2(elt.Obj());
+                        BSONElement name = obj2.getField("name");
+                        BSONElement type = obj2.getField("type");
+                        BSONElement path = obj2.getField("path");
+                        if( !name.eoo() && name.type() == String &&
+                            !type.eoo() && type.type() == String &&
+                            !path.eoo() && path.type() == Array )
+                        {
+                            OGRwkbGeometryType eType(OGRFromOGCGeomType(type.String().c_str()));
+                            OGRGeomFieldDefn oFieldDefn(name.String().c_str(), eType);
+                            OGRSpatialReference* poSRS = new OGRSpatialReference();
+                            poSRS->SetFromUserInput(SRS_WKT_WGS84);
+                            oFieldDefn.SetSpatialRef(poSRS);
+                            poSRS->Release();
+                            m_poFeatureDefn->AddGeomFieldDefn(&oFieldDefn);
+
+                            std::vector<CPLString> aosPaths;
+                            std::vector<BSONElement> oPathArray = path.Array();
+                            for(int j=0;j<(int)oPathArray.size();j++)
+                            {
+                                BSONElement& eltPath = oPathArray[j];
+                                aosPaths.push_back(eltPath.String().c_str());
+                            }
+                            m_aaosGeomFieldPaths.push_back(aosPaths);
+                            if( oMapIndices.find(oFieldDefn.GetNameRef()) != oMapIndices.end() )
+                                m_aosGeomIndexes.push_back(oMapIndices[oFieldDefn.GetNameRef()]);
+                            else
+                                m_aosGeomIndexes.push_back("none");
+                            //CPLDebug("MongoDB", "Layer %s: m_aosGeomIndexes[%d] = %s",
+                            //         m_osQualifiedCollection.c_str(),
+                            //         m_poFeatureDefn->GetGeomFieldCount()-1,
+                            //         m_aosGeomIndexes[m_poFeatureDefn->GetGeomFieldCount()-1].c_str());
+                            m_apoCT.push_back(NULL);
+                        }
+                    }
+                }
+            }
+
+            m_bLayerMetadataUpdatable = TRUE;
+            return TRUE;
+        }
+    }
+    catch( const DBException &e )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined, "%s: %s",
+                    "ReadOGRMetadata()", e.what());
+    }
+    return FALSE;
+}
+
+/************************************************************************/
+/*                         EstablishFeatureDefn()                       */
+/************************************************************************/
+
+void OGRMongoDBLayer::EstablishFeatureDefn()
+{
+    if( m_bHasEstablishedFeatureDefn )
+        return;
+    m_bHasEstablishedFeatureDefn = TRUE;
+
+    std::map< CPLString, CPLString> oMapIndices(CollectGeomIndices());
+
+    int nCount = m_poDS->GetFeatureCountToEstablishFeatureDefn();
+    if( m_poDS->UseOGRMetadata() )
+    {
+        if( ReadOGRMetadata(oMapIndices) )
+            nCount = 0;
+    }
+
+    if( nCount != 0 )
+    {
+        if( nCount < 0 )
+            nCount = 0; /* unlimited */
+
+        try
+        {
+            UNIQUE_PTR<DBClientCursor> cursor = m_poDS->GetConn()->query(
+                                                m_osQualifiedCollection,
+                                                BSONObj(),
+                                                nCount,
+                                                0, /* nToSkip */
+                                                NULL, /* fieldsToReturn */
+                                                0, /* queryOptions */
+                                                m_poDS->GetBatchSize());
+            while ( cursor->more() )
+            {
+                BSONObj obj = cursor->nextSafe();
+                for( BSONObj::iterator i(obj); i.more(); )
+                {
+                    BSONElement elt(i.next());
+                    if( EQUAL(elt.fieldName(), m_poDS->GetFID()) )
+                    {
+                        m_osFID = elt.fieldName();
+                    }
+                    else
+                    {
+                        std::vector<CPLString> aosPaths;
+                        AddOrUpdateField(elt.fieldName(), &elt,
+                                         '.', aosPaths, oMapIndices);
+                    }
+                }
+            }
+        }
+        catch( const DBException &e )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "%s: %s",
+                     "EstablishFeatureDefn()", e.what());
+        }
+    }
+
+    if( m_poDS->JSonField() )
+    {
+        OGRFieldDefn fldDefn("_json", OFTString);
+        m_poFeatureDefn->AddFieldDefn( &fldDefn );
+        std::vector<CPLString> aosPaths;
+        m_aaosFieldPaths.push_back(aosPaths);
+    }
+}
+
+/************************************************************************/
+/*                            GetFIDColumn()                            */
+/************************************************************************/
+
+const char* OGRMongoDBLayer::GetFIDColumn()
+{
+    if( !m_bHasEstablishedFeatureDefn )
+        EstablishFeatureDefn();
+    return m_osFID.c_str();
+}
+
+/************************************************************************/
+/*                            BuildQuery()                              */
+/************************************************************************/
+
+BSONObj OGRMongoDBLayer::BuildQuery()
+{
+    BSONObjBuilder b;
+    b.appendElements(m_oQueryAttr);
+    b.appendElementsUnique(m_oQuerySpat);
+    return b.obj();
+}
+
+/************************************************************************/
+/*                           GetFeatureCount()                          */
+/************************************************************************/
+
+GIntBig OGRMongoDBLayer::GetFeatureCount(int bForce)
+{
+    if( m_poAttrQuery != NULL ||
+        (m_poFilterGeom != NULL && !TestCapability(OLCFastSpatialFilter)) )
+    {
+        return OGRLayer::GetFeatureCount(bForce);
+    }
+
+    if( !m_bHasEstablishedFeatureDefn )
+        EstablishFeatureDefn();
+    if( m_poBulkBuilder )
+        SyncToDisk();
+
+    try
+    {
+         return (GIntBig) m_poDS->GetConn()->count(m_osQualifiedCollection,
+                                                 BuildQuery());
+    }
+    catch( const DBException &e )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined, "%s: %s",
+                 "GetFeatureCount()", e.what());
+        return OGRLayer::GetFeatureCount(bForce);
+    }
+}
+
+/************************************************************************/
+/*                             Stringify()                              */
+/************************************************************************/
+
+static CPLString Stringify(const BSONElement& elt)
+{
+    BSONType eBSONType = elt.type();
+    if( eBSONType == String )
+        return elt.String();
+    else if( eBSONType == NumberInt )
+        return CPLSPrintf("%d", elt.Int());
+    else if( eBSONType == NumberLong )
+        return CPLSPrintf(CPL_FRMT_GIB, elt.Long());
+    else if( eBSONType == NumberDouble )
+        return CPLSPrintf("%.16g", elt.Double());
+    else if( eBSONType == jstOID )
+        return elt.OID().toString().c_str();
+    else if( eBSONType == Bool )
+        return CPLSPrintf("%d", elt.Bool());
+    else if( eBSONType == Date )
+    {
+        GIntBig secsandmillis = (GIntBig)elt.Date().millis;
+        struct tm tm;
+        GIntBig secs = secsandmillis / 1000;
+        int millis = (int)(secsandmillis % 1000);
+        if( millis < 0 )
+        {
+            secs --;
+            millis += 1000;
+        }
+        CPLUnixTimeToYMDHMS(secs, &tm);
+        return CPLSPrintf("%04d-%02d-%02dT%02d:%02d:%02d.%03dZ",
+                          tm.tm_year + 1900,
+                          tm.tm_mon + 1,
+                          tm.tm_mday,
+                          tm.tm_hour,
+                          tm.tm_min,
+                          tm.tm_sec,
+                          millis);
+        // Doesn't work with dates < 1970
+        //return dateToISOStringUTC(elt.Date()).c_str();
+    }
+    else
+        return elt.jsonString(Strict, false).c_str();
+}
+
+/************************************************************************/
+/*                   OGRMongoDBReaderSetField()                         */
+/************************************************************************/
+
+static void OGRMongoDBReaderSetField( OGRLayer* poLayer,
+                                      OGRFeature* poFeature,
+                                      const char* pszAttrName,
+                                      const BSONElement* poElt,
+                                      bool bFlattenNestedAttributes,
+                                      char chNestedAttributeSeparator )
+{
+    int nGeomFieldIndex;
+    if( poElt->type() == Object &&
+        (nGeomFieldIndex = poFeature->GetGeomFieldIndex(pszAttrName)) >= 0 )
+    {
+        CPLPushErrorHandler(CPLQuietErrorHandler);
+        OGRGeometry* poGeom = (OGRGeometry*)OGR_G_CreateGeometryFromJson( Stringify(*poElt) );
+        CPLPopErrorHandler();
+        if( poGeom != NULL )
+        {
+            poGeom->assignSpatialReference(
+                poFeature->GetDefnRef()->GetGeomFieldDefn(nGeomFieldIndex)->GetSpatialRef() );
+            poFeature->SetGeomFieldDirectly(nGeomFieldIndex, poGeom);
+        }
+        return;
+    }
+    else if( poElt->type() == Array &&
+        (nGeomFieldIndex = poFeature->GetGeomFieldIndex(pszAttrName)) >= 0 )
+    {
+        std::vector<BSONElement> oArray = poElt->Array();
+        int nSize = (int)oArray.size();
+        if( nSize == 2 )
+        {
+            BSONElement& x = oArray[0];
+            BSONElement& y = oArray[1];
+            if( x.type() == NumberDouble && y.type() == NumberDouble )
+            {
+                OGRGeometry* poGeom = new OGRPoint( x.Double(), y.Double() );
+                poGeom->assignSpatialReference(
+                    poFeature->GetDefnRef()->GetGeomFieldDefn(nGeomFieldIndex)->GetSpatialRef() );
+                poFeature->SetGeomFieldDirectly(nGeomFieldIndex, poGeom);
+            }
+        }
+        return;
+    }
+
+    if( bFlattenNestedAttributes && poElt->type() == Object )
+    {
+        BSONObj obj(poElt->Obj());
+        for( BSONObj::iterator i(obj); i.more(); )
+        {
+            BSONElement elt(i.next());
+            char szSeparator[2];
+            szSeparator[0] = chNestedAttributeSeparator;
+            szSeparator[1] = 0;
+            CPLString osAttrName(CPLSPrintf("%s%s%s", pszAttrName, szSeparator,
+                                            elt.fieldName()));
+            OGRMongoDBReaderSetField(poLayer, poFeature,
+                                     osAttrName, &elt,
+                                     bFlattenNestedAttributes,
+                                     chNestedAttributeSeparator);
+        }
+        return ;
+    }
+
+    int nField = poFeature->GetFieldIndex(pszAttrName);
+    if( nField < 0 )
+        return;
+    OGRFieldDefn* poFieldDefn = poFeature->GetFieldDefnRef(nField);
+    CPLAssert( NULL != poFieldDefn );
+    BSONType eBSONType = poElt->type();
+    OGRFieldType eType = poFieldDefn->GetType();
+    if( eBSONType == jstNULL )
+        return;
+
+    if( eBSONType == NumberInt )
+        poFeature->SetField( nField, poElt->Int() );
+    else if( eBSONType == NumberLong )
+        poFeature->SetField( nField, poElt->Long() );
+    else if( eBSONType == NumberDouble )
+        poFeature->SetField( nField, poElt->Double() );
+    else if( eBSONType == MinKey && eType == OFTReal )
+        poFeature->SetField( nField, -std::numeric_limits<double>::infinity() );
+    else if( eBSONType == MaxKey && eType == OFTReal )
+        poFeature->SetField( nField, std::numeric_limits<double>::infinity() );
+    else if( eBSONType == MinKey && eType == OFTInteger )
+        poFeature->SetField( nField, INT_MIN );
+    else if( eBSONType == MaxKey && eType == OFTInteger )
+        poFeature->SetField( nField, INT_MAX );
+    else if( eBSONType == MinKey && eType == OFTInteger64 )
+        poFeature->SetField( nField, std::numeric_limits<GIntBig>::min() );
+    else if( eBSONType == MaxKey && eType == OFTInteger64 )
+        poFeature->SetField( nField, std::numeric_limits<GIntBig>::max() );
+    else if( eBSONType == Array )
+    {
+        std::vector<BSONElement> oArray = poElt->Array();
+        int nSize = (int)oArray.size();
+        if( eType == OFTStringList )
+        {
+            char** papszValues = (char**)CPLCalloc(nSize + 1, sizeof(char*));
+            for(int i=0;i<nSize;i++)
+            {
+                BSONElement& elt = oArray[i];
+                papszValues[i] = CPLStrdup(Stringify(elt));
+            }
+            poFeature->SetField( nField, papszValues );
+            CSLDestroy(papszValues);
+        }
+        else if( eType == OFTRealList )
+        {
+            double* padfValues = (double*)CPLMalloc(nSize * sizeof(double));
+            for(int i=0;i<nSize;i++)
+            {
+                BSONElement& elt = oArray[i];
+                eBSONType = elt.type();
+                if( eBSONType == NumberInt )
+                    padfValues[i] = elt.Int();
+                else if( eBSONType == NumberLong )
+                    padfValues[i] = (double)elt.Long();
+                else if( eBSONType == NumberDouble )
+                    padfValues[i] = elt.Double();
+                else if( eBSONType == MinKey )
+                    padfValues[i] = -std::numeric_limits<double>::infinity();
+                else if( eBSONType == MaxKey )
+                    padfValues[i] = std::numeric_limits<double>::infinity();
+                else
+                    padfValues[i] = CPLAtof(Stringify(elt));
+            }
+            poFeature->SetField( nField, nSize, padfValues );
+            CPLFree(padfValues);
+        }
+        else if( eType == OFTIntegerList )
+        {
+            int* panValues = (int*)CPLMalloc(nSize * sizeof(int));
+            for(int i=0;i<nSize;i++)
+            {
+                BSONElement& elt = oArray[i];
+                eBSONType = elt.type();
+                if( eBSONType == NumberInt )
+                    panValues[i] = elt.Int();
+                else if( eBSONType == NumberLong )
+                {
+                    GIntBig nVal = elt.Long();
+                    if( nVal < INT_MIN )
+                        panValues[i] = INT_MIN;
+                    else if( nVal > INT_MAX )
+                        panValues[i] = INT_MAX;
+                    else
+                        panValues[i] = (int)nVal;
+                }
+                else if( eBSONType == NumberDouble )
+                {
+                    double dfVal = elt.Double();
+                    if( dfVal < INT_MIN )
+                        panValues[i] = INT_MIN;
+                    else if( dfVal > INT_MAX )
+                        panValues[i] = INT_MAX;
+                    else
+                        panValues[i] = (int)dfVal;
+                }
+                else if( eBSONType == MinKey )
+                    panValues[i] = INT_MIN;
+                else if( eBSONType == MaxKey )
+                    panValues[i] = INT_MAX;
+                else
+                    panValues[i] = atoi(Stringify(elt));
+            }
+            poFeature->SetField( nField, nSize, panValues );
+            CPLFree(panValues);
+        }
+        else if( eType == OFTInteger64List )
+        {
+            GIntBig* panValues = (GIntBig*)CPLMalloc(nSize * sizeof(GIntBig));
+            for(int i=0;i<nSize;i++)
+            {
+                BSONElement& elt = oArray[i];
+                eBSONType = elt.type();
+                if( eBSONType == NumberInt )
+                    panValues[i] = elt.Int();
+                else if( eBSONType == NumberLong )
+                    panValues[i] = elt.Long();
+                else if( eBSONType == NumberDouble )
+                {
+                    double dfVal = elt.Double();
+                    if( dfVal < std::numeric_limits<GIntBig>::min() )
+                        panValues[i] = std::numeric_limits<GIntBig>::min();
+                    else if( dfVal > std::numeric_limits<GIntBig>::max() )
+                        panValues[i] = std::numeric_limits<GIntBig>::max();
+                    else
+                        panValues[i] = (int)dfVal;
+                }
+                else if( eBSONType == MinKey )
+                    panValues[i] = std::numeric_limits<GIntBig>::min();
+                else if( eBSONType == MaxKey )
+                    panValues[i] = std::numeric_limits<GIntBig>::max();
+                else
+                    panValues[i] = CPLAtoGIntBig(Stringify(elt));
+            }
+            poFeature->SetField( nField, nSize, panValues );
+            CPLFree(panValues);
+        }
+    }
+    else if( eBSONType == String )
+        poFeature->SetField( nField, poElt->String().c_str() );
+    else if( eBSONType == jstOID )
+        poFeature->SetField( nField, poElt->OID().toString().c_str() );
+    else if( eBSONType == Bool )
+        poFeature->SetField( nField, poElt->Bool() );
+    else if( eBSONType == BinData )
+    {
+        int len;
+        const char *pabyData = poElt->binDataClean(len);
+        poFeature->SetField( nField, len, (GByte*)pabyData);
+    }
+    else
+        poFeature->SetField( nField, Stringify(*poElt) );
+}
+
+/************************************************************************/
+/*                            Translate()                               */
+/************************************************************************/
+
+OGRFeature* OGRMongoDBLayer::Translate(BSONObj& obj)
+{
+    OGRFeature* poFeature = new OGRFeature(GetLayerDefn());
+    try
+    {
+        for( BSONObj::iterator i(obj); i.more(); )
+        {
+            BSONElement elt(i.next());
+            if( m_osFID.size() && EQUAL(m_osFID, elt.fieldName()) )
+            {
+                BSONType eBSONType = elt.type();
+                if( eBSONType == NumberInt )
+                    poFeature->SetFID(elt.Int());
+                else if( eBSONType == NumberLong )
+                    poFeature->SetFID(elt.Long());
+                else if( eBSONType == NumberDouble )
+                    poFeature->SetFID((GIntBig)elt.Double());
+            }
+            else
+            {
+                OGRMongoDBReaderSetField(this, poFeature,
+                                         elt.fieldName(),
+                                         &elt,
+                                         m_poDS->GetFlattenNestedAttributes(),
+                                         '.');
+            }
+        }
+
+        if( m_poDS->JSonField() )
+        {
+            poFeature->SetField("_json", obj.jsonString().c_str());
+        }
+    }
+    catch( const DBException &e )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "%s: %s",
+                 "Translate()", e.what());
+    }
+    return poFeature;
+}
+
+/************************************************************************/
+/*                            GetNextFeature()                          */
+/************************************************************************/
+
+OGRFeature* OGRMongoDBLayer::GetNextFeature()
+{
+    if( !m_bHasEstablishedFeatureDefn )
+        EstablishFeatureDefn();
+    if( m_poBulkBuilder )
+        SyncToDisk();
+
+    try
+    {
+        if( !m_bCursorValid )
+        {
+            m_poCursor = m_poDS->GetConn()->query(m_osQualifiedCollection,
+                                              BuildQuery(),
+                                              0, /* nToReturn */
+                                              0, /* nToSkip */
+                                              NULL, /* fieldsToReturn */
+                                              0, /* queryOptions */
+                                              m_poDS->GetBatchSize());
+            m_bCursorValid = TRUE;
+        }
+
+        while( true )
+        {
+            if( !m_poCursor->more() )
+                return NULL;
+            BSONObj obj = m_poCursor->nextSafe();
+
+            OGRFeature* poFeature = Translate(obj);
+            if( poFeature->GetFID() < 0 )
+                poFeature->SetFID(++m_nIndex);
+
+            if((m_poFilterGeom == NULL
+                || FilterGeometry( poFeature->GetGeometryRef() ) )
+            && (m_poAttrQuery == NULL
+                || m_poAttrQuery->Evaluate( poFeature )) )
+            {
+                return poFeature;
+            }
+            else
+                delete poFeature;
+        }
+    }
+    catch( const DBException &e )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "%s: %s",
+                 "GetNextFeature()", e.what());
+        return NULL;
+    }
+}
+
+/************************************************************************/
+/*                             GetFeature()                             */
+/************************************************************************/
+
+OGRFeature* OGRMongoDBLayer::GetFeature(GIntBig nFID)
+{
+    if( !m_bHasEstablishedFeatureDefn )
+        EstablishFeatureDefn();
+    if( m_poBulkBuilder )
+        SyncToDisk();
+
+    if( m_osFID.size() == 0 )
+    {
+        BSONObj oQueryAttrBak(m_oQueryAttr), oQuerySpatBak(m_oQuerySpat);
+        OGRFeature* poFeature = OGRLayer::GetFeature(nFID);
+        m_oQueryAttr = oQueryAttrBak;
+        m_oQuerySpat = oQuerySpatBak;
+        return poFeature;
+    }
+
+    try
+    {
+        UNIQUE_PTR<DBClientCursor> cursor = m_poDS->GetConn()->query(
+            m_osQualifiedCollection,
+            BSON(m_osFID.c_str() << nFID),
+            1);
+        if( !cursor->more() )
+            return NULL;
+        BSONObj obj = cursor->nextSafe();
+
+        OGRFeature* poFeature = Translate(obj);
+        poFeature->SetFID(nFID);
+        return poFeature;
+    }
+    catch( const DBException &e )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "%s: %s",
+                 "GetFeature()", e.what());
+        return NULL;
+    }
+}
+
+/************************************************************************/
+/*                             DeleteFeature()                          */
+/************************************************************************/
+
+OGRErr OGRMongoDBLayer::DeleteFeature(GIntBig nFID)
+{
+    if( m_poDS->GetAccess() != GA_Update )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Dataset opened in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
+    if( !m_bHasEstablishedFeatureDefn )
+        EstablishFeatureDefn();
+    if( m_poBulkBuilder )
+        SyncToDisk();
+    if( m_osFID.size() == 0 )
+        return OGRERR_FAILURE;
+
+    try
+    {
+        BSONObj obj = m_poDS->GetConn()->findAndRemove(
+            m_osQualifiedCollection,
+            BSON(m_osFID.c_str() << nFID),
+            BSONObj(),
+            BSONObj());
+        return (obj.isEmpty()) ? OGRERR_NON_EXISTING_FEATURE : OGRERR_NONE;
+    }
+    catch( const DBException &e )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "%s: %s",
+                 "DeleteFeature()", e.what());
+        return OGRERR_FAILURE;
+    }
+}
+
+/************************************************************************/
+/*                            CreateField()                             */
+/************************************************************************/
+
+OGRErr OGRMongoDBLayer::CreateField( OGRFieldDefn *poFieldIn, CPL_UNUSED int bApproxOK )
+
+{
+    if( m_poDS->GetAccess() != GA_Update )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Dataset opened in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
+    if( m_poFeatureDefn->GetFieldIndex(poFieldIn->GetNameRef()) >= 0 )
+    {
+        if( !EQUAL(poFieldIn->GetNameRef(), "_id") &&
+            !EQUAL(poFieldIn->GetNameRef(), "_json") )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "CreateField() called with an already existing field name: %s",
+                     poFieldIn->GetNameRef());
+        }
+        return OGRERR_FAILURE;
+    }
+
+    m_poFeatureDefn->AddFieldDefn( poFieldIn );
+
+    std::vector<CPLString> aosPaths;
+    if( m_bDotAsNestedField )
+    {
+        char** papszTokens = CSLTokenizeString2(poFieldIn->GetNameRef(), ".", 0);
+        for(int i=0; papszTokens[i]; i++ )
+            aosPaths.push_back(papszTokens[i]);
+        CSLDestroy(papszTokens);
+    }
+    else
+        aosPaths.push_back(poFieldIn->GetNameRef());
+    m_aaosFieldPaths.push_back(aosPaths);
+
+    m_bUpdateLayerMetadata = m_bLayerMetadataUpdatable;
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           CreateGeomField()                          */
+/************************************************************************/
+
+OGRErr OGRMongoDBLayer::CreateGeomField( OGRGeomFieldDefn *poFieldIn, CPL_UNUSED int bApproxOK )
+
+{
+    if( m_poDS->GetAccess() != GA_Update )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Dataset opened in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
+    if( m_poFeatureDefn->GetGeomFieldIndex(poFieldIn->GetNameRef()) >= 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "CreateGeomField() called with an already existing field name: %s",
+                  poFieldIn->GetNameRef());
+        return OGRERR_FAILURE;
+    }
+
+    OGRGeomFieldDefn oFieldDefn(poFieldIn);
+    if( EQUAL(oFieldDefn.GetNameRef(), "") )
+        oFieldDefn.SetName("geometry");
+
+    m_poFeatureDefn->AddGeomFieldDefn( &oFieldDefn );
+
+    std::vector<CPLString> aosPaths;
+    if( m_bDotAsNestedField )
+    {
+        char** papszTokens = CSLTokenizeString2(oFieldDefn.GetNameRef(), ".", 0);
+        for(int i=0; papszTokens[i]; i++ )
+            aosPaths.push_back(papszTokens[i]);
+        CSLDestroy(papszTokens);
+    }
+    else
+        aosPaths.push_back(oFieldDefn.GetNameRef());
+    m_aaosGeomFieldPaths.push_back(aosPaths);
+    m_aosGeomIndexes.push_back("none");
+
+    OGRCoordinateTransformation* poCT = NULL;
+    if( oFieldDefn.GetSpatialRef() != NULL )
+    {
+        OGRSpatialReference oSRS_WGS84;
+        oSRS_WGS84.SetFromUserInput(SRS_WKT_WGS84);
+        if( !oSRS_WGS84.IsSame(oFieldDefn.GetSpatialRef()) )
+        {
+            poCT = OGRCreateCoordinateTransformation( oFieldDefn.GetSpatialRef(), &oSRS_WGS84 );
+            if( poCT == NULL )
+            {
+                CPLError( CE_Warning, CPLE_AppDefined,
+                          "On-the-fly reprojection to WGS84 long/lat would be "
+                          "needed, but instantiation of transformer failed" );
+            }
+        }
+    }
+    m_apoCT.push_back(poCT);
+
+    if( m_bCreateSpatialIndex )
+    {
+        //CPLDebug("MongoDB", "Create spatial index for %s of %s",
+        //         poFieldIn->GetNameRef(), m_osQualifiedCollection.c_str());
+        try
+        {
+            const char* pszIndexType;
+            if( wkbFlatten(poFieldIn->GetType()) != wkbPoint )
+                pszIndexType = "2dsphere";
+            else
+                pszIndexType = CPLGetConfigOption("OGR_MONGODB_SPAT_INDEX_TYPE", "2dsphere");
+            m_poDS->GetConn()->createIndex(m_osQualifiedCollection,
+                                         BSON( oFieldDefn.GetNameRef() << pszIndexType ));
+            m_aosGeomIndexes[m_aosGeomIndexes.size()-1] = pszIndexType;
+        }
+        catch( const DBException &e )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "%s: %s",
+                     "Index creation", e.what());
+        }
+    }
+
+    m_bUpdateLayerMetadata = m_bLayerMetadataUpdatable;
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           SerializeField()                           */
+/************************************************************************/
+
+void OGRMongoDBLayer::SerializeField(BSONObjBuilder& b,
+                                     OGRFeature *poFeature,
+                                     int iField,
+                                     const char* pszJSonField)
+{
+    OGRFieldType eType = m_poFeatureDefn->GetFieldDefn(iField)->GetType();
+    if( eType == OFTInteger )
+    {
+        if( m_poFeatureDefn->GetFieldDefn(iField)->GetSubType() == OFSTBoolean )
+            b.append( pszJSonField, CPL_TO_BOOL(poFeature->GetFieldAsInteger(iField)) );
+        else
+            b.append( pszJSonField, poFeature->GetFieldAsInteger(iField) );
+    }
+    else if( eType == OFTInteger64 )
+        b.append( pszJSonField, poFeature->GetFieldAsInteger64(iField) );
+    else if( eType == OFTReal )
+        b.append( pszJSonField, poFeature->GetFieldAsDouble(iField) );
+    else if( eType == OFTString )
+        b.append( pszJSonField, poFeature->GetFieldAsString(iField) );
+    else if( eType == OFTStringList )
+    {
+        char** papszValues = poFeature->GetFieldAsStringList(iField);
+        BSONArrayBuilder arrayBuilder;
+        for(int i=0; papszValues[i]; i++)
+            arrayBuilder.append( papszValues[i] );
+        b.append( pszJSonField, arrayBuilder.arr() );
+    }
+    else if( eType == OFTIntegerList )
+    {
+        int nSize;
+        const int* panValues = poFeature->GetFieldAsIntegerList(iField, &nSize);
+        BSONArrayBuilder arrayBuilder;
+        for(int i=0; i<nSize; i++)
+            arrayBuilder.append( panValues[i] );
+        b.append( pszJSonField, arrayBuilder.arr() );
+    }
+    else if( eType == OFTInteger64List )
+    {
+        int nSize;
+        const GIntBig* panValues = poFeature->GetFieldAsInteger64List(iField, &nSize);
+        BSONArrayBuilder arrayBuilder;
+        for(int i=0; i<nSize; i++)
+            arrayBuilder.append( panValues[i] );
+        b.append( pszJSonField, arrayBuilder.arr() );
+    }
+    else if( eType == OFTRealList )
+    {
+        int nSize;
+        const double* padfValues = poFeature->GetFieldAsDoubleList(iField, &nSize);
+        BSONArrayBuilder arrayBuilder;
+        for(int i=0; i<nSize; i++)
+            arrayBuilder.append( padfValues[i] );
+        b.append( pszJSonField, arrayBuilder.arr() );
+    }
+    else if( eType == OFTBinary )
+    {
+        int nSize;
+        const GByte* pabyData = poFeature->GetFieldAsBinary(iField, &nSize);
+        b.appendBinData( pszJSonField, nSize, BinDataGeneral, (const void*)pabyData);
+    }
+    else if( eType == OFTDate || eType == OFTDateTime || eType == OFTTime )
+    {
+        struct tm tm;
+        int nYear, nMonth, nDay, nHour, nMinute, nTZ;
+        float fSecond;
+        poFeature->GetFieldAsDateTime(iField, &nYear, &nMonth, &nDay,
+                                      &nHour, &nMinute, &fSecond, &nTZ);
+        tm.tm_year = nYear - 1900;
+        tm.tm_mon = nMonth - 1;
+        tm.tm_mday = nDay;
+        tm.tm_hour = nHour;
+        tm.tm_min = nMinute;
+        tm.tm_sec = (int)fSecond;
+        GIntBig millis = 1000 * CPLYMDHMSToUnixTime(&tm) + (GIntBig)(1000 * fmod(fSecond, 1));
+        b.append( pszJSonField, Date_t((GUIntBig)millis) );
+        //char* pszDT = OGRGetXMLDateTime(poFeature->GetRawFieldRef(i));
+        //StatusWith<Date_t> d = dateFromISOString(pszDT);
+        //if( d.isOK() )
+        //    b.append( pszJSonField, d.getValue() );
+        //CPLFree(pszDT);
+    }
+}
+
+/************************************************************************/
+/*                       OGRLocaleSafeFromJSON()                        */
+/************************************************************************/
+
+static BSONObj OGRLocaleSafeFromJSON(const char* pszJSon)
+{
+    CPLThreadLocaleC oCLocale;
+    return fromjson(pszJSon);
+}
+
+/************************************************************************/
+/*                        SerializeGeometry()                           */
+/************************************************************************/
+
+void OGRMongoDBLayer::SerializeGeometry(BSONObjBuilder& b,
+                                        OGRGeometry* poGeom, int iField,
+                                        const char* pszJSonField)
+{
+    if( m_aosGeomIndexes[iField] == "2d" &&
+        wkbFlatten(poGeom->getGeometryType()) == wkbPoint )
+    {
+        BSONArrayBuilder arrayBuilder;
+        arrayBuilder.append( ((OGRPoint*)poGeom)->getX() );
+        arrayBuilder.append( ((OGRPoint*)poGeom)->getY() );
+        b.append( pszJSonField, arrayBuilder.arr() );
+    }
+    else
+    {
+        char* pszJSon = OGR_G_ExportToJson((OGRGeometryH)poGeom);
+        if( pszJSon )
+            b.append(pszJSonField, OGRLocaleSafeFromJSON(pszJSon));
+        CPLFree(pszJSon);
+    }
+}
+
+/************************************************************************/
+/*                       SerializeRecursive()                           */
+/************************************************************************/
+
+void OGRMongoDBLayer::SerializeRecursive(BSONObjBuilder& b,
+                                         OGRFeature *poFeature,
+                                         std::map< CPLString, IntOrMap*>& aoMap )
+{
+    std::map< CPLString, IntOrMap* >::iterator oIter = aoMap.begin();
+    for( ; oIter != aoMap.end(); ++oIter)
+    {
+        IntOrMap* intOrMap = oIter->second;
+        if( intOrMap->bIsMap )
+        {
+            BSONObjBuilder subB;
+            SerializeRecursive(subB, poFeature, *(intOrMap->u.poMap));
+            b.append( oIter->first.c_str(), subB.obj() );
+            delete intOrMap->u.poMap;
+        }
+        else
+        {
+            int i = intOrMap->u.nField;
+            if( i >= 0)
+            {
+                SerializeField(b, poFeature, i, oIter->first.c_str());
+            }
+            else
+            {
+                i = -i - 1;
+                OGRGeometry* poGeom = poFeature->GetGeomFieldRef(i);
+                SerializeGeometry(b, poGeom, i, oIter->first.c_str());
+            }
+        }
+        delete intOrMap;
+    }
+}
+
+/************************************************************************/
+/*                           InsertInMap()                              */
+/************************************************************************/
+
+void OGRMongoDBLayer::InsertInMap(IntOrMap* rootMap,
+                                  std::map< std::vector<CPLString>, IntOrMap*>& aoMap,
+                                  const std::vector<CPLString>& aosFieldPathFull,
+                                  int nField)
+{
+    std::vector<CPLString> aosFieldPath;
+    std::vector<CPLString> aosFieldPathPrev;
+    for(int j=0; j<(int)aosFieldPathFull.size() - 1; j++)
+    {
+        aosFieldPath.push_back(aosFieldPathFull[j]);
+        if( aoMap.find(aosFieldPath) == aoMap.end() )
+        {
+            IntOrMap* intOrMap = new IntOrMap;
+            intOrMap->bIsMap = TRUE;
+            intOrMap->u.poMap = new std::map< CPLString, IntOrMap*>;
+            aoMap[aosFieldPath] = intOrMap;
+        }
+        if( j > 0 )
+        {
+            std::map< CPLString, IntOrMap* >* poPrevMap = aoMap[aosFieldPathPrev]->u.poMap;
+            (*poPrevMap)[aosFieldPathFull[j]] = aoMap[aosFieldPath];
+        }
+        else
+            (*(rootMap->u.poMap))[aosFieldPathFull[j]] = aoMap[aosFieldPath];
+        aosFieldPathPrev.push_back(aosFieldPathFull[j]);
+    }
+    IntOrMap* intOrMap = new IntOrMap;
+    intOrMap->bIsMap = FALSE;
+    intOrMap->u.nField = nField;
+    std::map< CPLString, IntOrMap* >* poPrevMap = aoMap[aosFieldPathPrev]->u.poMap;
+    const CPLString& osLastComponent(aosFieldPathFull[aosFieldPathFull.size() - 1]);
+    CPLAssert( (*poPrevMap).find(osLastComponent) == (*poPrevMap).end() );
+    (*(poPrevMap))[osLastComponent] = intOrMap;
+}
+
+/************************************************************************/
+/*                       BuildBSONObjFromFeature()                      */
+/************************************************************************/
+
+BSONObj OGRMongoDBLayer::BuildBSONObjFromFeature(OGRFeature* poFeature, int bUpdate)
+{
+    BSONObjBuilder b;
+
+    int nJSonFieldIndex = m_poFeatureDefn->GetFieldIndex("_json");
+    if( nJSonFieldIndex >= 0 && poFeature->IsFieldSet(nJSonFieldIndex) )
+    {
+        CPLString osJSon(poFeature->GetFieldAsString(nJSonFieldIndex));
+
+        // Workaround bug in  JParse::dateObject() with { "$numberLong": "-123456" }
+        // that cannot be parsed successfully
+        while( true )
+        {
+            size_t i = osJSon.find("{ \"$date\" : { \"$numberLong\" : \"-");
+            if( i == std::string::npos )
+                break;
+            size_t j = osJSon.find("\" }", i+strlen("{ \"$date\" : { \"$numberLong\" : \"-"));
+            if( j == std::string::npos )
+                break;
+            GIntBig negNumber = CPLAtoGIntBig(osJSon.c_str() + i+strlen("{ \"$date\" : { \"$numberLong\" : \"-")-1);
+            osJSon = osJSon.substr(0, i+strlen("{ \"$date\" : ")) +
+                     CPLSPrintf(CPL_FRMT_GIB, negNumber) +
+                     osJSon.substr(j+strlen("\" }"));
+        }
+
+        BSONObj obj(OGRLocaleSafeFromJSON(osJSon));
+        if( (m_bIgnoreSourceID || !obj.hasField("_id")) && !bUpdate )
+        {
+            const OID generated = OID::gen();
+            b.append("_id", generated);
+            poFeature->SetField(0, generated.toString().c_str());
+        }
+        b.appendElementsUnique(obj);
+        //BSONObj obj2(b.obj());
+        //printf("%s\n", obj2.jsonString(Strict).c_str());
+        //return obj2;
+        return b.obj();
+    }
+
+    if( poFeature->GetFID() >= 0 && m_osFID.size() )
+    {
+        b.append( m_osFID.c_str(), poFeature->GetFID() );
+    }
+
+    CPLAssert((int)m_aaosFieldPaths.size() == m_poFeatureDefn->GetFieldCount());
+
+    if( !poFeature->IsFieldSet(0) || (!bUpdate && m_bIgnoreSourceID) )
+    {
+        const OID generated = OID::gen();
+        b.append("_id", generated);
+        poFeature->SetField(0, generated.toString().c_str());
+    }
+    else
+        b.append("_id", OID(poFeature->GetFieldAsString(0)) );
+
+    IntOrMap* rootMap = new IntOrMap;
+    rootMap->bIsMap = TRUE;
+    rootMap->u.poMap = new std::map< CPLString, IntOrMap*>;
+    std::map< std::vector<CPLString>, IntOrMap*> aoMap;
+
+    for(int i=1;i<m_poFeatureDefn->GetFieldCount();i++)
+    {
+        if( !poFeature->IsFieldSet(i) )
+            continue;
+
+        if( m_aaosFieldPaths[i].size() > 1 )
+        {
+            InsertInMap(rootMap, aoMap, m_aaosFieldPaths[i], i);
+        }
+        else
+        {
+            const char* pszFieldName = m_poFeatureDefn->GetFieldDefn(i)->GetNameRef();
+            SerializeField(b, poFeature, i, pszFieldName);
+        }
+    }
+
+    CPLAssert((int)m_aaosGeomFieldPaths.size() == m_poFeatureDefn->GetGeomFieldCount());
+    CPLAssert((int)m_apoCT.size() == m_poFeatureDefn->GetGeomFieldCount());
+    for(int i=0;i<m_poFeatureDefn->GetGeomFieldCount();i++)
+    {
+        OGRGeometry* poGeom = poFeature->GetGeomFieldRef(i);
+        if( poGeom == NULL )
+            continue;
+        if( !bUpdate && m_apoCT[i] != NULL )
+            poGeom->transform( m_apoCT[i] );
+
+        if( m_aaosGeomFieldPaths[i].size() > 1 )
+        {
+            InsertInMap(rootMap, aoMap, m_aaosGeomFieldPaths[i],  -i-1);
+        }
+        else
+        {
+            const char* pszFieldName = m_poFeatureDefn->GetGeomFieldDefn(i)->GetNameRef();
+            SerializeGeometry(b, poGeom, i, pszFieldName);
+        }
+    }
+
+    SerializeRecursive(b, poFeature, *(rootMap->u.poMap));
+    delete rootMap->u.poMap;
+    delete rootMap;
+
+    return b.obj();
+}
+
+/************************************************************************/
+/*                           ICreateFeature()                           */
+/************************************************************************/
+
+OGRErr OGRMongoDBLayer::ICreateFeature( OGRFeature *poFeature )
+{
+    if( m_poDS->GetAccess() != GA_Update )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Dataset opened in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
+    if( !m_bHasEstablishedFeatureDefn )
+        EstablishFeatureDefn();
+
+    try
+    {
+        if( poFeature->GetFID() < 0 )
+        {
+            if( m_nNextFID == 0 )
+                m_nNextFID = GetFeatureCount(FALSE);
+            poFeature->SetFID(++m_nNextFID);
+        }
+
+        BSONObj bsonObj( BuildBSONObjFromFeature(poFeature, FALSE) );
+        if( m_poDS->BulkInsert() )
+        {
+            if( m_nFeaturesInBulk == MAX_DOCS_IN_BULK )
+                SyncToDisk();
+            if( m_poBulkBuilder == NULL )
+                m_poBulkBuilder = new BulkOperationBuilder(
+                    m_poDS->GetConn(), m_osQualifiedCollection, false);
+            m_poBulkBuilder->insert( bsonObj );
+            m_nFeaturesInBulk ++;
+        }
+        else
+        {
+            m_poDS->GetConn()->insert( m_osQualifiedCollection, bsonObj );
+        }
+
+        return OGRERR_NONE;
+    }
+    catch( const DBException &e )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "%s: %s",
+                 "CreateFeature()", e.what());
+        return OGRERR_FAILURE;
+    }
+}
+
+/************************************************************************/
+/*                            ISetFeature()                             */
+/************************************************************************/
+
+OGRErr OGRMongoDBLayer::ISetFeature( OGRFeature *poFeature )
+{
+    if( m_poDS->GetAccess() != GA_Update )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Dataset opened in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
+    if( !m_bHasEstablishedFeatureDefn )
+        EstablishFeatureDefn();
+    if( m_poBulkBuilder )
+        SyncToDisk();
+
+    if( !poFeature->IsFieldSet(0) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "_id field not set");
+        return OGRERR_FAILURE;
+    }
+
+    try
+    {
+        BSONObj obj( BuildBSONObjFromFeature(poFeature, TRUE) );
+        // TODO? we should theoretically detect if the provided _id doesn't exist
+        m_poDS->GetConn()->update( m_osQualifiedCollection,
+                                 MONGO_QUERY("_id" << obj.getField("_id")),
+                                 obj, false, false );
+        return OGRERR_NONE;
+    }
+    catch( const DBException &e )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "%s: %s",
+                 "SetFeature()", e.what());
+        return OGRERR_FAILURE;
+    }
+}
+
+/************************************************************************/
+/*                            TestCapability()                          */
+/************************************************************************/
+
+int OGRMongoDBLayer::TestCapability(const char* pszCap)
+{
+    if( EQUAL(pszCap, OLCStringsAsUTF8) )
+    {
+        return TRUE;
+    }
+    else if( EQUAL(pszCap,OLCRandomRead) )
+    {
+        EstablishFeatureDefn();
+        return m_osFID.size() > 0;
+    }
+    else if( EQUAL(pszCap, OLCFastSpatialFilter) )
+    {
+        EstablishFeatureDefn();
+        for(int i=0;i<m_poFeatureDefn->GetGeomFieldCount();i++)
+        {
+            if( m_aosGeomIndexes[i] == "none" )
+            {
+                return FALSE;
+            }
+        }
+        return TRUE;
+    }
+    else if( EQUAL(pszCap, OLCCreateField) ||
+             EQUAL(pszCap, OLCCreateGeomField) ||
+             EQUAL(pszCap, OLCSequentialWrite) ||
+             EQUAL(pszCap, OLCRandomWrite) )
+    {
+        return m_poDS->GetAccess() == GA_Update;
+    }
+    else if( EQUAL(pszCap,OLCDeleteFeature) )
+    {
+        EstablishFeatureDefn();
+        return m_poDS->GetAccess() == GA_Update &&
+               m_osFID.size() > 0;
+    }
+
+    return FALSE;
+}
+
+/************************************************************************/
+/*                          SetAttributeFilter()                        */
+/************************************************************************/
+
+OGRErr OGRMongoDBLayer::SetAttributeFilter(const char* pszFilter)
+{
+    m_oQueryAttr = BSONObj();
+
+    if( pszFilter != NULL && pszFilter[0] == '{' )
+    {
+        OGRLayer::SetAttributeFilter(NULL);
+        try
+        {
+            m_oQueryAttr = OGRLocaleSafeFromJSON(pszFilter);
+            return OGRERR_NONE;
+        }
+        catch( const DBException &e )
+        {
+            m_oQueryAttr = BSONObj();
+            CPLError(CE_Failure, CPLE_AppDefined, "%s: %s",
+                     "SetAttributeFilter()", e.what());
+            return OGRERR_FAILURE;
+        }
+    }
+    return OGRLayer::SetAttributeFilter(pszFilter);
+}
+
+/************************************************************************/
+/*                          SetSpatialFilter()                          */
+/************************************************************************/
+
+void OGRMongoDBLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poGeomIn )
+
+{
+    if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() ||
+        GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetType() == wkbNone )
+    {
+        if( iGeomField != 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Invalid geometry field index : %d", iGeomField);
+        }
+        return;
+    }
+    m_iGeomFieldFilter = iGeomField;
+
+    m_oQuerySpat = BSONObj();
+    if( InstallFilter( poGeomIn ) && poGeomIn )
+    {
+        OGREnvelope sEnvelope;
+        poGeomIn->getEnvelope(&sEnvelope);
+        if( sEnvelope.MaxX == sEnvelope.MinX )
+            sEnvelope.MaxX += 1e-10;
+        if( sEnvelope.MaxY == sEnvelope.MinY )
+            sEnvelope.MaxY += 1e-10;
+
+        if( sEnvelope.MinX < -180 )
+            sEnvelope.MinX = -180;
+        if( sEnvelope.MinY < -90 )
+            sEnvelope.MinY = -90;
+        if( sEnvelope.MaxX > 180 )
+            sEnvelope.MaxX = 180;
+        if( sEnvelope.MaxY > 90 )
+            sEnvelope.MaxY = 90;
+        if( sEnvelope.MinX == -180 && sEnvelope.MinY == -90 &&
+            sEnvelope.MaxX == 180 && sEnvelope.MaxY == 90 )
+        {
+            return;
+        }
+
+        try
+        {
+            if( m_aosGeomIndexes[m_iGeomFieldFilter] == "2dsphere" )
+            {
+                m_oQuerySpat = OGRLocaleSafeFromJSON(CPLSPrintf("{ \"%s\" : { $geoIntersects : "
+                "{ $geometry : { type : \"Polygon\" , coordinates : [["
+                "[%.16g,%.16g],[%.16g,%.16g],[%.16g,%.16g],[%.16g,%.16g],[%.16g,%.16g]]] } } } }",
+                              m_poFeatureDefn->GetGeomFieldDefn(iGeomField)->GetNameRef(),
+                              sEnvelope.MinX, sEnvelope.MinY,
+                              sEnvelope.MaxX, sEnvelope.MinY,
+                              sEnvelope.MaxX, sEnvelope.MaxY,
+                              sEnvelope.MinX, sEnvelope.MaxY,
+                              sEnvelope.MinX, sEnvelope.MinY));
+            }
+            else if( m_aosGeomIndexes[m_iGeomFieldFilter] == "2d" )
+            {
+                m_oQuerySpat = OGRLocaleSafeFromJSON(CPLSPrintf("{ \"%s\" : { $geoWithin : "
+                "{ $box : [ [ %.16g , %.16g ] , [ %.16g , %.16g ] ] } } }",
+                              m_poFeatureDefn->GetGeomFieldDefn(iGeomField)->GetNameRef(),
+                              sEnvelope.MinX, sEnvelope.MinY,
+                              sEnvelope.MaxX, sEnvelope.MaxY));
+            }
+        }
+        catch( const DBException &e )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "%s: %s", "SetSpatialFilter()", e.what());
+        }
+    }
+}
+/************************************************************************/
+/*                        OGRMongoDBDataSource()                        */
+/************************************************************************/
+
+OGRMongoDBDataSource::OGRMongoDBDataSource()
+{
+    m_poConn = NULL;
+    m_nBatchSize = 0;
+    m_nFeatureCountToEstablishFeatureDefn = 0;
+    m_bJSonField = FALSE;
+    m_bUseOGRMetadata = TRUE;
+    m_bBulkInsert = TRUE;
+    m_bFlattenNestedAttributes = TRUE;
+}
+
+/************************************************************************/
+/*                       ~OGRMongoDBDataSource()                        */
+/************************************************************************/
+
+OGRMongoDBDataSource::~OGRMongoDBDataSource()
+{
+    for(int i=0; i<(int)m_apoLayers.size(); i++ )
+    {
+        delete m_apoLayers[i];
+    }
+    delete m_poConn;
+}
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer* OGRMongoDBDataSource::GetLayer(int nIdx)
+{
+    if( nIdx < 0 || nIdx >= (int)m_apoLayers.size() )
+        return NULL;
+    return m_apoLayers[nIdx];
+}
+
+/************************************************************************/
+/*                         GetLayerByName()                             */
+/************************************************************************/
+
+OGRLayer *OGRMongoDBDataSource::GetLayerByName(const char* pszLayerName)
+{
+    OGRLayer* poLayer = GDALDataset::GetLayerByName(pszLayerName);
+    if( poLayer != NULL )
+        return poLayer;
+
+    for(int i=0; i<(int)m_apoLayers.size(); i++ )
+    {
+        m_apoLayers[i]->SyncToDisk();
+    }
+
+    CPLString osDatabase;
+    if( m_osDatabase.size() == 0 )
+    {
+        const char* pszDot = strchr(pszLayerName, '.');
+        if( pszDot == NULL )
+            return NULL;
+        osDatabase = pszLayerName;
+        osDatabase.resize(pszDot - pszLayerName);
+        pszLayerName = pszDot + 1;
+    }
+    else
+        osDatabase = m_osDatabase;
+
+    for(int i=0;i<2;i++)
+    {
+        try
+        {
+            std::list<std::string> l = m_poConn->getCollectionNames( osDatabase );
+            for ( std::list<std::string>::iterator oIter = l.begin(); oIter != l.end(); oIter++ )
+            {
+                const std::string& osCollection(*oIter);
+                if( EQUAL(osCollection.c_str(),pszLayerName) )
+                {
+                    OGRMongoDBLayer* l_poLayer = new OGRMongoDBLayer(this,
+                                                          osDatabase,
+                                                          osCollection.c_str());
+                    m_apoLayers.push_back(l_poLayer);
+                    return l_poLayer;
+                }
+            }
+        }
+        catch( const DBException &e)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Command failed: %s", e.what());
+        }
+        if( i == 0 )
+        {
+            if( m_osDatabase.size() == 0 )
+                break;
+            const char* pszDot = strchr(pszLayerName, '.');
+            if( pszDot == NULL )
+                break;
+            osDatabase = pszLayerName;
+            osDatabase.resize(pszDot - pszLayerName);
+            pszLayerName = pszDot + 1;
+        }
+    }
+
+    return NULL;
+}
+
+/************************************************************************/
+/*                            Initialize()                              */
+/************************************************************************/
+
+int OGRMongoDBDataSource::Initialize(char** papszOpenOptions)
+{
+    CPLString osPEMKeyFile = CSLFetchNameValueDef(papszOpenOptions, "SSL_PEM_KEY_FILE", "");
+    CPLString osPEMKeyPassword = CSLFetchNameValueDef(papszOpenOptions, "SSL_PEM_KEY_PASSWORD", "");
+    CPLString osCAFile = CSLFetchNameValueDef(papszOpenOptions, "SSL_CA_FILE", "");
+    CPLString osCRLFile = CSLFetchNameValueDef(papszOpenOptions, "SSL_CRL_FILE", "");
+    int bAllowInvalidCertificates = CSLFetchBoolean(papszOpenOptions, "SSL_ALLOW_INVALID_CERTIFICATES", FALSE);
+    int bAllowInvalidHostnames = CSLFetchBoolean(papszOpenOptions, "SSL_ALLOW_INVALID_HOSTNAMES", FALSE);
+    int bFIPSMode = CSLFetchBoolean(papszOpenOptions, "FIPS_MODE", FALSE);
+    if( bMongoInitialized < 0 )
+    {
+        Options options;
+        osStaticPEMKeyFile = osPEMKeyFile;
+        osStaticPEMKeyPassword = osPEMKeyPassword;
+        osStaticCAFile = osCAFile;
+        osStaticCRLFile = osCRLFile;
+        bStaticAllowInvalidCertificates = bAllowInvalidCertificates;
+        bStaticAllowInvalidHostnames = bAllowInvalidHostnames;
+        bStaticFIPSMode = bFIPSMode;
+
+        if( osPEMKeyFile.size() || osPEMKeyPassword.size() ||
+            osCAFile.size() || osCRLFile.size() )
+        {
+            options.setSSLMode(Options::kSSLRequired);
+            if( osPEMKeyFile.size() )
+                options.setSSLPEMKeyFile(osPEMKeyFile);
+            if( osPEMKeyPassword )
+                options.setSSLPEMKeyPassword(osPEMKeyPassword);
+            if( osCAFile.size() )
+                options.setSSLCAFile(osCAFile);
+            if( osCRLFile.size() )
+                options.setSSLCRLFile(osCRLFile);
+            if( bAllowInvalidCertificates )
+                options.setSSLAllowInvalidCertificates(true);
+            if( bAllowInvalidHostnames )
+                options.setSSLAllowInvalidHostnames(true);
+        }
+        if( bFIPSMode )
+            options.setFIPSMode(true);
+        Status status = client::initialize(options);
+        bMongoInitialized = status.isOK();
+        if( !status.isOK() )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Mongo initialization failed: %s", status.toString().c_str());
+            return FALSE;
+        }
+    }
+    else if( !bMongoInitialized )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Previous initialization of MongoDB failed");
+        return FALSE;
+    }
+
+    if( osPEMKeyFile != osStaticPEMKeyFile )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Value of %s different from first initialization. Using initial value",
+                 "SSL_PEM_KEY_FILE");
+    }
+    if( osPEMKeyPassword != osStaticPEMKeyPassword )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Value of %s different from first initialization. Using initial value",
+                 "SSL_PEM_KEY_PASSWORD");
+    }
+    if( osCAFile != osStaticCAFile )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Value of %s different from first initialization. Using initial value",
+                 "SSL_CA_FILE");
+    }
+    if( osCRLFile != osStaticCRLFile )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Value of %s different from first initialization. Using initial value",
+                 "SSL_CRL_FILE");
+    }
+    if( bAllowInvalidCertificates != bStaticAllowInvalidCertificates )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Value of %s different from first initialization. Using initial value",
+                 "SSL_ALLOW_INVALID_CERTIFICATES");
+    }
+    if( bAllowInvalidHostnames != bStaticAllowInvalidHostnames )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Value of %s different from first initialization. Using initial value",
+                 "SSL_ALLOW_INVALID_HOSTNAMES");
+    }
+    if( bFIPSMode != bStaticFIPSMode )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Value of %s different from first initialization. Using initial value",
+                 "FIPS_MODE");
+    }
+    return TRUE;
+}
+
+/************************************************************************/
+/*                              Open()                                  */
+/************************************************************************/
+
+int OGRMongoDBDataSource::Open(const char* pszFilename,
+                               GDALAccess eAccessIn,
+                               char** papszOpenOptionsIn)
+{
+    if( !Initialize(papszOpenOptionsIn) )
+        return FALSE;
+
+    this->eAccess = eAccessIn;
+
+    const char* pszHost = CSLFetchNameValueDef(papszOpenOptionsIn, "HOST", "localhost");
+    const char* pszPort = CSLFetchNameValueDef(papszOpenOptionsIn, "PORT", "27017");
+    const char* pszURI = CSLFetchNameValue(papszOpenOptionsIn, "URI");
+    if( STARTS_WITH_CI(pszFilename, "mongodb://") )
+        pszURI = pszFilename;
+
+    std::string errmsg;
+    if( pszURI != NULL )
+    {
+        try
+        {
+            /**
+             * ConnectionString can parse MongoDB URIs with the following format:
+             *
+             *    mongodb://[usr:pwd@]host1[:port1]...[,hostN[:portN]]][/[db][?options]]
+             *
+             * For a complete list of URI string options, see
+             * http://docs.mongodb.org/v2.6/reference/connection-string/
+             *
+             * Examples:
+             *
+             *    A replica set with three members (one running on default port 27017):
+             *      string uri = mongodb://localhost,localhost:27018,localhost:27019
+             *
+             *    Authenticated connection to db 'bedrock' with user 'barney' and pwd 'rubble':
+             *      string url = mongodb://barney:rubble@localhost/bedrock
+             */
+
+            ConnectionString cs = ConnectionString::parse( pszURI, errmsg );
+            if( !cs.isValid() )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Bad connection string: %s", errmsg.c_str());
+                return FALSE;
+            }
+            m_osDatabase = cs.getDatabase();
+            m_poConn = cs.connect( errmsg );
+            if( m_poConn == NULL )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Cannot connect: %s", errmsg.c_str());
+                return FALSE;
+            }
+        }
+        catch( const DBException &e)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Cannot connect: %s", e.what());
+            return FALSE;
+        }
+    }
+    else
+    {
+        DBClientConnection* poConn = new DBClientConnection();
+        m_poConn = poConn;
+        try
+        {
+            if( !poConn->connect(CPLSPrintf("%s:%s", pszHost, pszPort), errmsg ) )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Cannot connect: %s", errmsg.c_str());
+                return FALSE;
+            }
+        }
+        catch( const DBException &e)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Cannot connect: %s", e.what());
+            return FALSE;
+        }
+    }
+
+    if( m_osDatabase.size() == 0 )
+    {
+        m_osDatabase = CSLFetchNameValueDef(papszOpenOptionsIn, "DBNAME", "");
+        /*if( m_osDatabase.size() == 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "No database name specified");
+            return FALSE;
+        }*/
+    }
+
+    const char* pszAuthJSON = CSLFetchNameValue(papszOpenOptionsIn, "AUTH_JSON");
+    if( pszAuthJSON )
+    {
+        try
+        {
+             /* The "params" BSONObj should be initialized with some of the fields below.  Which fields
+             * are required depends on the mechanism, which is mandatory.
+             *
+             *     "mechanism": The string name of the sasl mechanism to use.  Mandatory.
+                    const char kAuthMechMongoCR[] = "MONGODB-CR";
+                    const char kAuthMechScramSha1[] = "SCRAM-SHA-1";
+                    const char kAuthMechDefault[] = "DEFAULT";
+             *     "user": The string name of the user to authenticate.  Mandatory.
+             *     "db": The database target of the auth command, which identifies the location
+             *         of the credential information for the user.  May be "$external" if
+             *         credential information is stored outside of the mongo cluster.  Mandatory.
+             *     "pwd": The password data.
+             *     "digestPassword": Boolean, set to true if the "pwd" is undigested (default).
+             *     "serviceName": The GSSAPI service name to use.  Defaults to "mongodb".
+             *     "serviceHostname": The GSSAPI hostname to use.  Defaults to the name of the remote
+             *          host.
+             */
+            m_poConn->auth(OGRLocaleSafeFromJSON(pszAuthJSON));
+        }
+        catch( const DBException &e)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Authentication failed: %s", e.what());
+            return FALSE;
+        }
+    }
+    else
+    {
+        const char* pszUser = CSLFetchNameValue(papszOpenOptionsIn, "USER");
+        const char* pszPassword = CSLFetchNameValue(papszOpenOptionsIn, "PASSWORD");
+        const char* pszAuthDBName = CSLFetchNameValue(papszOpenOptionsIn, "AUTH_DBNAME");
+        if( (pszUser != NULL && pszPassword == NULL) ||
+            (pszUser == NULL && pszPassword != NULL) )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "USER and PASSWORD open options must be both specified.");
+            return FALSE;
+        }
+        if( pszUser && pszPassword )
+        {
+            if( m_osDatabase.size() == 0 && pszAuthDBName == NULL)
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "No database or authentication database name specified.");
+                return FALSE;
+            }
+            try
+            {
+                if( !m_poConn->auth(pszAuthDBName ? pszAuthDBName : m_osDatabase.c_str(),
+                                    pszUser, pszPassword, errmsg) )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Authentication failed: %s", errmsg.c_str());
+                    return FALSE;
+                }
+            }
+            catch( const DBException &e)
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Authentication failed: %s", e.what());
+                return FALSE;
+            }
+        }
+        else if( pszAuthDBName != NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "AUTH_DBNAME ignored when USER and PASSWORD open options are not specified.");
+        }
+    }
+
+    m_nBatchSize = atoi(CSLFetchNameValueDef(papszOpenOptionsIn, "BATCH_SIZE", "0"));
+    m_nFeatureCountToEstablishFeatureDefn = atoi(CSLFetchNameValueDef(
+        papszOpenOptionsIn, "FEATURE_COUNT_TO_ESTABLISH_FEATURE_DEFN", "100"));
+    m_bJSonField = CSLFetchBoolean(papszOpenOptionsIn, "JSON_FIELD", FALSE);
+    m_bFlattenNestedAttributes = CPL_TO_BOOL(CSLFetchBoolean(
+            papszOpenOptionsIn, "FLATTEN_NESTED_ATTRIBUTES", TRUE));
+    m_osFID = CSLFetchNameValueDef(papszOpenOptionsIn, "FID", "ogc_fid");
+    m_bUseOGRMetadata = CSLFetchBoolean(
+            papszOpenOptionsIn, "USE_OGR_METADATA", TRUE);
+    m_bBulkInsert = CSLFetchBoolean(papszOpenOptionsIn, "BULK_INSERT", TRUE);
+
+    int bRet = TRUE;
+    if( m_osDatabase.size() == 0 )
+    {
+        try
+        {
+            std::list<std::string> l = m_poConn->getDatabaseNames();
+            for ( std::list<std::string>::iterator i = l.begin(); i != l.end(); i++ )
+            {
+                bRet &= ListLayers((*i).c_str());
+            }
+        }
+        catch( const DBException &e)
+        {
+            if( e.getCode() == 10005 )
+            {
+                try
+                {
+                    BSONObj info;
+                    m_poConn->runCommand("admin", BSON("listDatabases" << 1),
+                                          info, QueryOption_SlaveOk);
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Command failed: %s", info.jsonString().c_str());
+                }
+                catch( const DBException &e2)
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Command failed: %s", e2.what());
+                }
+            }
+            else
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Command failed: %s", e.what());
+            }
+            return FALSE;
+        }
+    }
+    else
+    {
+        bRet = ListLayers(m_osDatabase);
+    }
+
+    return bRet;
+}
+
+/************************************************************************/
+/*                             ListLayers()                             */
+/************************************************************************/
+
+int OGRMongoDBDataSource::ListLayers(const char* pszDatabase)
+{
+    try
+    {
+        std::list<std::string> aoListNames = m_poConn->getCollectionNames( pszDatabase );
+        for ( std::list<std::string>::iterator oIter = aoListNames.begin(); oIter != aoListNames.end(); ++oIter )
+        {
+            const std::string& osCollection(*oIter);
+            if( !STARTS_WITH(osCollection.c_str(), "system.") &&
+                osCollection != "startup_log" &&
+                osCollection != "_ogr_metadata" )
+            {
+                m_apoLayers.push_back(new OGRMongoDBLayer(this,
+                                                      pszDatabase,
+                                                      osCollection.c_str()));
+            }
+        }
+        return TRUE;
+    }
+    catch( const DBException &e)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Command failed: %s", e.what());
+        return FALSE;
+    }
+}
+
+/************************************************************************/
+/*                            ICreateLayer()                            */
+/************************************************************************/
+
+OGRLayer* OGRMongoDBDataSource::ICreateLayer( const char *pszName,
+                                              OGRSpatialReference *poSpatialRef,
+                                              OGRwkbGeometryType eGType,
+                                              char ** papszOptions )
+{
+    if( m_osDatabase.size() == 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot create layer/collection when dataset opened without explicit database");
+        return NULL;
+    }
+
+    if( eAccess != GA_Update )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Dataset opened in read-only mode");
+        return NULL;
+    }
+
+    for(int i=0; i<(int)m_apoLayers.size(); i++)
+    {
+        if( EQUAL(m_apoLayers[i]->GetName(), pszName) )
+        {
+            if( CSLFetchNameValue( papszOptions, "OVERWRITE" ) != NULL
+                && !EQUAL(CSLFetchNameValue(papszOptions,"OVERWRITE"),"NO") )
+            {
+                DeleteLayer( i );
+            }
+            else
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Layer %s already exists, CreateLayer failed.\n"
+                          "Use the layer creation option OVERWRITE=YES to "
+                          "replace it.",
+                          pszName );
+                return NULL;
+            }
+        }
+    }
+
+    OGRMongoDBLayer* poLayer = new OGRMongoDBLayer(this, m_osDatabase, pszName);
+
+    poLayer->SetFID(CSLFetchNameValueDef(papszOptions, "FID", "ogc_fid"));
+    poLayer->SetCreateLayerMetadata(CSLFetchBoolean(papszOptions, "WRITE_OGR_METADATA", TRUE));
+    poLayer->SetDotAsNestedField(CSLFetchBoolean(papszOptions, "DOT_AS_NESTED_FIELD", TRUE));
+    poLayer->SetIgnoreSourceID(CSLFetchBoolean(papszOptions, "IGNORE_SOURCE_ID", FALSE));
+    poLayer->SetCreateSpatialIndex(CSLFetchBoolean(papszOptions, "SPATIAL_INDEX", TRUE));
+
+    if( eGType != wkbNone )
+    {
+        const char* pszGeometryName = CSLFetchNameValueDef(papszOptions, "GEOMETRY_NAME", "geometry");
+        OGRGeomFieldDefn oFieldDefn(pszGeometryName, eGType);
+        oFieldDefn.SetSpatialRef(poSpatialRef);
+        poLayer->CreateGeomField(&oFieldDefn, FALSE);
+    }
+
+    m_apoLayers.push_back(poLayer);
+    return poLayer;
+}
+
+/************************************************************************/
+/*                            DeleteLayer()                             */
+/************************************************************************/
+
+OGRErr OGRMongoDBDataSource::DeleteLayer( int iLayer )
+
+{
+    if( eAccess != GA_Update )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Dataset opened in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
+    if( iLayer < 0 || iLayer >= (int)m_apoLayers.size() )
+        return OGRERR_FAILURE;
+
+/* -------------------------------------------------------------------- */
+/*      Blow away our OGR structures related to the layer.  This is     */
+/*      pretty dangerous if anything has a reference to this layer!     */
+/* -------------------------------------------------------------------- */
+    CPLString osLayerName = m_apoLayers[iLayer]->GetName();
+    CPLString l_osDatabase = m_apoLayers[iLayer]->GetDatabase();
+    CPLString l_osCollection = m_apoLayers[iLayer]->GetCollection();
+    CPLString l_osQualifiedCollection = m_apoLayers[iLayer]->GetQualifiedCollection();
+
+    CPLDebug( "MongoDB", "DeleteLayer(%s)", osLayerName.c_str() );
+
+    delete m_apoLayers[iLayer];
+    m_apoLayers.erase( m_apoLayers.begin() + iLayer );
+
+    try
+    {
+        m_poConn->findAndRemove(
+                CPLSPrintf("%s._ogr_metadata", l_osDatabase.c_str()),
+                BSON("layer" << l_osCollection.c_str()),
+                BSONObj(),
+                BSONObj());
+
+        return m_poConn->dropCollection(l_osQualifiedCollection) ? OGRERR_NONE: OGRERR_FAILURE;
+    }
+    catch( const DBException &e)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Command failed: %s", e.what());
+        return OGRERR_FAILURE;
+    }
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRMongoDBDataSource::TestCapability( const char * pszCap )
+
+{
+    if( EQUAL(pszCap,ODsCCreateLayer)
+        || EQUAL(pszCap,ODsCDeleteLayer)
+        || EQUAL(pszCap,ODsCCreateGeomFieldAfterCreateLayer) )
+        return eAccess == GA_Update;
+    else
+        return FALSE;
+}
+
+/************************************************************************/
+/*                    OGRMongoDBSingleFeatureLayer                      */
+/************************************************************************/
+
+class OGRMongoDBSingleFeatureLayer: public OGRLayer
+{
+    OGRFeatureDefn     *m_poFeatureDefn;
+    CPLString           osVal;
+    int                 iNextShapeId;
+    public:
+        OGRMongoDBSingleFeatureLayer( const char *pszVal );
+       ~OGRMongoDBSingleFeatureLayer() { m_poFeatureDefn->Release(); }
+       void             ResetReading() { iNextShapeId = 0; }
+       OGRFeature      *GetNextFeature();
+       OGRFeatureDefn  *GetLayerDefn() { return m_poFeatureDefn; }
+       int              TestCapability( const char * ) { return FALSE; }
+};
+
+/************************************************************************/
+/*                    OGRMongoDBSingleFeatureLayer()                     */
+/************************************************************************/
+
+OGRMongoDBSingleFeatureLayer::OGRMongoDBSingleFeatureLayer( const char *pszVal )
+{
+    m_poFeatureDefn = new OGRFeatureDefn( "RESULT" );
+    m_poFeatureDefn->Reference();
+    OGRFieldDefn oField( "_json", OFTString );
+    m_poFeatureDefn->AddFieldDefn( &oField );
+
+    iNextShapeId = 0;
+    osVal = pszVal;
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature * OGRMongoDBSingleFeatureLayer::GetNextFeature()
+{
+    if (iNextShapeId != 0)
+        return NULL;
+
+    OGRFeature* poFeature = new OGRFeature(m_poFeatureDefn);
+    poFeature->SetField(0, osVal);
+    poFeature->SetFID(iNextShapeId ++);
+    return poFeature;
+}
+
+/************************************************************************/
+/*                             ExecuteSQL()                             */
+/************************************************************************/
+
+OGRLayer* OGRMongoDBDataSource::ExecuteSQL( const char *pszSQLCommand,
+                                            OGRGeometry *poSpatialFilter,
+                                            const char *pszDialect )
+{
+    for(int i=0; i<(int)m_apoLayers.size(); i++ )
+    {
+        m_apoLayers[i]->SyncToDisk();
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Special case DELLAYER: command.                                 */
+/* -------------------------------------------------------------------- */
+    if( STARTS_WITH_CI(pszSQLCommand, "DELLAYER:") )
+    {
+        const char *pszLayerName = pszSQLCommand + 9;
+
+        while( *pszLayerName == ' ' )
+            pszLayerName++;
+
+        for( int iLayer = 0; iLayer < (int)m_apoLayers.size(); iLayer++ )
+        {
+            if( EQUAL(m_apoLayers[iLayer]->GetName(),
+                      pszLayerName ))
+            {
+                DeleteLayer( iLayer );
+                break;
+            }
+        }
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Special case WRITE_OGR_METADATA command.                        */
+/* -------------------------------------------------------------------- */
+    if( STARTS_WITH_CI(pszSQLCommand, "WRITE_OGR_METADATA ") )
+    {
+        if( eAccess != GA_Update )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Dataset opened in read-only mode");
+            return NULL;
+        }
+        const char* pszLayerName = pszSQLCommand + strlen("WRITE_OGR_METADATA ");
+        OGRMongoDBLayer* poLayer = (OGRMongoDBLayer*) GetLayerByName(pszLayerName);
+        if( poLayer == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Layer %s not found", pszLayerName);
+            return NULL;
+        }
+        poLayer->GetLayerDefn(); // force schema discovery
+        poLayer->SetCreateLayerMetadata(TRUE);
+        poLayer->SyncToDisk();
+
+        return NULL;
+    }
+
+    if( pszDialect != NULL && EQUAL(pszDialect, "MONGODB") )
+    {
+        BSONObj info;
+        try
+        {
+            m_poConn->runCommand(m_osDatabase, OGRLocaleSafeFromJSON(pszSQLCommand), info);
+            return new OGRMongoDBSingleFeatureLayer(info.jsonString().c_str());
+        }
+        catch( const DBException &e)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Command failed: %s", e.what());
+            return NULL;
+        }
+    }
+    else
+    {
+        return GDALDataset::ExecuteSQL(pszSQLCommand, poSpatialFilter, pszDialect);
+    }
+}
+
+/************************************************************************/
+/*                          ReleaseResultSet()                          */
+/************************************************************************/
+
+void OGRMongoDBDataSource::ReleaseResultSet( OGRLayer * poLayer )
+{
+    delete poLayer;
+}
+
+/************************************************************************/
+/*                          OGRMongoDBDriverUnload()                    */
+/************************************************************************/
+
+extern "C" int GDALIsInGlobalDestructor();
+
+static void OGRMongoDBDriverUnload( CPL_UNUSED GDALDriver* poDriver )
+{
+    if( bMongoInitialized != -1 && !GDALIsInGlobalDestructor() )
+    {
+        client::shutdown();
+    }
+}
+
+/************************************************************************/
+/*                     OGRMongoDBDriverIdentify()                       */
+/************************************************************************/
+
+static int OGRMongoDBDriverIdentify( GDALOpenInfo* poOpenInfo )
+
+{
+    if( STARTS_WITH_CI(poOpenInfo->pszFilename, "MongoDB:") )
+    {
+#ifdef DEBUG_BOOL
+        // Defining -DDO_NOT_USE_DEBUG_BOOL doesn't solve runtime problems
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "MongoDB incompatible at runtime with DEBUG_BOOL");
+#else
+        return TRUE;
+#endif
+    }
+    return FALSE;
+}
+
+/************************************************************************/
+/*                     OGRMongoDBDriverOpen()                           */
+/************************************************************************/
+
+static GDALDataset* OGRMongoDBDriverOpen( GDALOpenInfo* poOpenInfo )
+
+{
+    if( !OGRMongoDBDriverIdentify(poOpenInfo) )
+        return NULL;
+
+    OGRMongoDBDataSource *m_poDS = new OGRMongoDBDataSource();
+
+    if( !m_poDS->Open( poOpenInfo->pszFilename,
+                     poOpenInfo->eAccess,
+                     poOpenInfo->papszOpenOptions ) )
+    {
+        delete m_poDS;
+        m_poDS = NULL;
+    }
+
+    return m_poDS;
+}
+
+#if 0
+/************************************************************************/
+/*                     OGRMongoDBDriverCreate()                         */
+/************************************************************************/
+
+static GDALDataset* OGRMongoDBDriverCreate( const char * pszName,
+                                            int nXSize, int nYSize, int nBands,
+                                            GDALDataType eType, char ** papszOptions )
+{
+    OGRMongoDBDataSource *m_poDS = new OGRMongoDBDataSource();
+
+    if( !m_poDS->Open( pszName, papszOptions) )
+    {
+        delete m_poDS;
+        m_poDS = NULL;
+    }
+
+    return m_poDS;
+}
+#endif
+
+/************************************************************************/
+/*                         RegisterOGRMongoDB()                         */
+/************************************************************************/
+
+void RegisterOGRMongoDB()
+{
+    if( GDALGetDriverByName( "MongoDB" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "MongoDB" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "MongoDB" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_mongodb.html" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, "MongoDB:" );
+
+#if 0
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+                               "<CreationOptionList>"
+                               "</CreationOptionList>");
+#endif
+
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+"<LayerCreationOptionList>"
+"  <Option name='OVERWRITE' type='boolean' description='Whether to overwrite an existing collection with the layer name to be created' default='NO'/>"
+"  <Option name='GEOMETRY_NAME' type='string' description='Name of geometry column.' default='geometry'/>"
+"  <Option name='SPATIAL_INDEX' type='boolean' description='Whether to create a spatial index' default='YES'/>"
+"  <Option name='FID' type='string' description='Field name, with integer values, to use as FID' default='ogc_fid'/>"
+"  <Option name='WRITE_OGR_METADATA' type='boolean' description='Whether to create a description of layer fields in the _ogr_metadata collection' default='YES'/>"
+"  <Option name='DOT_AS_NESTED_FIELD' type='boolean' description='Whether to consider dot character in field name as sub-document' default='YES'/>"
+"  <Option name='IGNORE_SOURCE_ID' type='boolean' description='Whether to ignore _id field in features passed to CreateFeature()' default='NO'/>"
+"</LayerCreationOptionList>");
+
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+"<OpenOptionList>"
+"  <Option name='URI' type='string' description='Connection URI' />"
+"  <Option name='HOST' type='string' description='Server hostname' />"
+"  <Option name='PORT' type='integer' description='Server port' />"
+"  <Option name='DBNAME' type='string' description='Database name' />"
+"  <Option name='AUTH_DBNAME' type='string' description='Authentication database name' />"
+"  <Option name='USER' type='string' description='User name' />"
+"  <Option name='PASSWORD' type='string' description='User password' />"
+"  <Option name='AUTH_JSON' type='string' description='Authentication elements as JSon object' />"
+"  <Option name='SSL_PEM_KEY_FILE' type='string' description='SSL PEM certificate/key filename' />"
+"  <Option name='SSL_PEM_KEY_PASSWORD' type='string' description='SSL PEM key password' />"
+"  <Option name='SSL_CA_FILE' type='string' description='SSL Certification Authority filename' />"
+"  <Option name='SSL_CRL_FILE' type='string' description='SSL Certification Revocation List filename' />"
+"  <Option name='SSL_ALLOW_INVALID_CERTIFICATES' type='boolean' description='Whether to allow connections to servers with invalid certificates' default='NO'/>"
+"  <Option name='SSL_ALLOW_INVALID_HOSTNAMES' type='boolean' description='Whether to allow connections to servers with non-matching hostnames' default='NO'/>"
+"  <Option name='FIPS_MODE' type='boolean' description='Whether to activate FIPS 140-2 mode at startup' default='NO'/>"
+"  <Option name='BATCH_SIZE' type='integer' description='Number of features to retrieve per batch'/>"
+"  <Option name='FEATURE_COUNT_TO_ESTABLISH_FEATURE_DEFN' type='integer' description='Number of features to retrieve to establish feature definition. -1 = unlimited' default='100'/>"
+"  <Option name='JSON_FIELD' type='boolean' description='Whether to include a field with the full document as JSON' default='NO'/>"
+"  <Option name='FLATTEN_NESTED_ATTRIBUTES' type='boolean' description='Whether to recursively explore nested objects and produce flatten OGR attributes' default='YES'/>"
+"  <Option name='FID' type='string' description='Field name, with integer values, to use as FID' default='ogc_fid'/>"
+"  <Option name='USE_OGR_METADATA' type='boolean' description='Whether to use the _ogr_metadata collection to read layer metadata' default='YES'/>"
+"  <Option name='BULK_INSERT' type='boolean' description='Whether to use bulk insert for feature creation' default='YES'/>"
+"</OpenOptionList>");
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES, "Integer Integer64 Real String Date DateTime Time IntegerList Integer64List RealList StringList Binary" );
+
+    poDriver->pfnOpen = OGRMongoDBDriverOpen;
+    poDriver->pfnIdentify = OGRMongoDBDriverIdentify;
+    poDriver->pfnUnloadDriver = OGRMongoDBDriverUnload;
+    //poDriver->pfnCreate = OGRMongoDBDriverCreate;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/ogr/ogrsf_frmts/mssqlspatial/GNUmakefile b/ogr/ogrsf_frmts/mssqlspatial/GNUmakefile
index 4c478ab..d4e8cee 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/GNUmakefile
+++ b/ogr/ogrsf_frmts/mssqlspatial/GNUmakefile
@@ -2,7 +2,7 @@
 
 include ../../../GDALmake.opt
 
-OBJ	=	ogrmssqlspatialdatasource.o ogrmssqlspatiallayer.o ogrmssqlspatialtablelayer.o ogrmssqlspatialselectlayer.o ogrmssqlspatialdriver.o ogrmssqlgeometryparser.o ogrmssqlgeometryvalidator.o
+OBJ	=	ogrmssqlspatialdatasource.o ogrmssqlspatiallayer.o ogrmssqlspatialtablelayer.o ogrmssqlspatialselectlayer.o ogrmssqlspatialdriver.o ogrmssqlgeometryparser.o ogrmssqlgeometryvalidator.o ogrmssqlgeometrywriter.o
 
 CPPFLAGS	:=	 -I.. -I../.. $(CPPFLAGS)
 
diff --git a/ogr/ogrsf_frmts/mssqlspatial/drv_mssqlspatial.html b/ogr/ogrsf_frmts/mssqlspatial/drv_mssqlspatial.html
index 5d5fb65..d43cd3f 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/drv_mssqlspatial.html
+++ b/ogr/ogrsf_frmts/mssqlspatial/drv_mssqlspatial.html
@@ -7,32 +7,32 @@
 
 <h1>MSSQLSpatial - Microsoft SQL Server Spatial Database</h1>
 
-<p>This driver implements support for access to spatial tables in Microsoft SQL 
-    Server 2008+ which contains the geometry and geography data types to repesent 
+<p>This driver implements support for access to spatial tables in Microsoft SQL
+    Server 2008+ which contains the geometry and geography data types to represent
     the geometry columns.</p>
 
 <h2>Connecting to a database</h2>
 
 To connect to a MSSQL datasource, use a connection string specifying the database name,
-with additional parameters as necessary. The connection strings must be prefixed 
+with additional parameters as necessary. The connection strings must be prefixed
     with '<i>MSSQL:</i>'.<br>
 <blockquote><pre>
 MSSQL:server=.\MSSQLSERVER2008;database=dbname;trusted_connection=yes</pre></blockquote>
-In addition to the standard parameters of the 
-    <a href="http://msdn.microsoft.com/en-us/library/ms130822.aspx">ODBC driver connection string</a> 
+In addition to the standard parameters of the
+    <a href="http://msdn.microsoft.com/en-us/library/ms130822.aspx">ODBC driver connection string</a>
     format the following custom parameters can also be used in the following syntax:
 
 <ul>
-	
-<li> <b>Tables=schema1.table1(geometry column1),schema2.table2(geometry column2)</b>: 
+
+<li> <b>Tables=schema1.table1(geometry column1),schema2.table2(geometry column2)</b>:
     By using this parameter you can specify the subset of the layers to be used by the driver. If this parameter is not set, the layers are retrieved from the geometry_columns metadata table. You can omit specifying the schema and the geometry column portions of the syntax. </li>
-<li> <b>GeometryFormat=native|wkb|wkt|wkbzm</b>: 
+<li> <b>GeometryFormat=native|wkb|wkt|wkbzm</b>:
     The desired format in which the geometries should be retrieved from the server. The default value is 'native' in this case the native SqlGeometry and SqlGeography serialization format is used. When using the 'wkb' or 'wkt' setting the geometry representation is converted to 'Well Known Binary' and 'Well Known Text' at the server. This conversion requires a significant overhead at the server and makes the feature access slower than using the native format. The wkbzm format can only be [...]
 
 </ul>
-    <p>The parameter names are not case sensitive in the connection strings.</p> 
+    <p>The parameter names are not case sensitive in the connection strings.</p>
     <p>Specifying the <b>
-    Database</b> parameter is required by the driver in order to select the proper database.</p> 
+    Database</b> parameter is required by the driver in order to select the proper database.</p>
     <p>The connection may contain the optional <b>
     Driver</b> parameter if a custom SQL server driver should be loaded (like FreeTDS). The default is <b>{SQL Server}</b></p>
 
@@ -40,56 +40,58 @@ In addition to the standard parameters of the
 
 <p>Starting with GDAL 1.11 if the user defines the environment variable
 <i>MSSQLSPATIAL_LIST_ALL_TABLES=YES</i> (and does not specify Tables= in the connection string),
-all regular user tables will be treated as layers. This option is useful if you want tables with 
-with no spatial data<p>
+all regular user tables will be treated as layers. This option is useful if you want tables with
+with no spatial data</p>
 
 <p>By default the MSSQL driver will only look for layers that are registered in the <i>geometry_columns</i> metadata table.
 Starting with GDAL 1.10 if the user defines the environment variable
-<i>MSSQLSPATIAL_USE_GEOMETRY_COLUMNS=NO</i> then the driver will look for all user spatial tables found in the system catalog<p>
+<i>MSSQLSPATIAL_USE_GEOMETRY_COLUMNS=NO</i> then the driver will look for all user spatial tables found in the system catalog</p>
 
 <h2>SQL statements</h2>
 
 <p>The MS SQL Spatial driver passes SQL statements directly to MS SQL by default,
 rather than evaluating them internally when using the ExecuteSQL() call on the
 OGRDataSource, or the -sql command option to ogr2ogr.  Attribute query
-expressions are also passed directly through to MSSQL. 
-It's also possible to request the OGR MSSQL driver to handle SQL commands 
-with the <a href="/ogr/ogr_sql.html">OGR SQL</a> engine, by passing <strong>"OGRSQL"</strong> 
+expressions are also passed directly through to MSSQL.
+It's also possible to request the OGR MSSQL driver to handle SQL commands
+with the <a href="ogr_sql.html">OGR SQL</a> engine, by passing <strong>"OGRSQL"</strong>
 string to the ExecuteSQL() method, as the name of the SQL dialect.</p>
 
-<p>The MSSQL driver in OGR supports the OGRLayer::StartTrasaction(), 
+<p>The MSSQL driver in OGR supports the OGRLayer::StartTransaction(),
 OGRLayer::CommitTransaction() and OGRLayer::RollbackTransaction()
 calls in the normal SQL sense.</p>
 
 <h2>Creation Issues</h2>
 
 <p>This driver doesn't support creating new databases, you might want to use the <i>Microsoft SQL Server Client Tools</i> for this purpose, but it does allow creation of new layers within an
-existing database.</P>
+existing database.</p>
 
 <h3>Layer Creation Options</h3>
 
 <ul>
 <li>
-<b>GEOM_TYPE</b>: The GEOM_TYPE layer creation option can be set to 
-one of "geometry" or "geography". If this option is not specified the default value is "geometry". 
-    So as to create the geometry column with "geography" type, this parameter should 
-    be set "geography". In this case the layer must have a valid spatial referece of 
-    one of the geography coordinate systems defined in the <b>
-    sys.spatial_reference_systems</b> SQL Server metadata table. Projected 
-    coordinate systems are not supported in this case.</li>
+<b>GEOM_TYPE</b>: The GEOM_TYPE layer creation option can be set to
+one of "geometry" or "geography". If this option is not specified the
+default value is "geometry".  So as to create the geometry column with
+"geography" type, this parameter should be set
+"geography". In this case the layer must have a valid
+spatial reference of one of the geography coordinate systems defined
+in the <b> sys.spatial_reference_systems</b> SQL Server metadata
+table. Projected coordinate systems are not supported in this
+case.</li>
 <li> <b>OVERWRITE</b>: This may be "YES" to force an existing layer of the
 desired name to be destroyed before creating the requested layer.</li>
 <li> <b>LAUNDER</b>: This may be "YES" to force new fields created on this
 layer to have their field names "laundered" into a form more compatible with
 MSSQL.  This converts to lower case and converts some special characters
-like "-" and "#" to "_".  If "NO" exact names are preserved.  
+like "-" and "#" to "_".  If "NO" exact names are preserved.
 The default value is "YES".  If enabled the table (layer) name will also be laundered.</li>
 <li> <b>PRECISION</b>: This may be "YES" to force new fields created on this
 layer to try and represent the width and precision information, if available
 using numeric(width,precision) or char(width) types.  If "NO" then the types
 float, int and varchar will be used instead.  The default is "YES".</li>
 <li> <b>DIM={2,3}</b>: Control the dimension of the layer.  Defaults to 3.</li>
-<li> <b>GEOMETRY_NAME</b>: Set the name of geometry column in the new table.  If 
+<li> <b>GEOMETRY_NAME</b>: Set the name of geometry column in the new table.  If
 omitted it defaults to <i>ogr_geometry</i>.. Note: option was called GEOM_NAME in releases before GDAL 2</li>
 <li> <b>SCHEMA</b>: Set name of schema for new table.
 If this parameter is not supported the default schema "<i>dbo"</i> is used.</li>
@@ -98,11 +100,13 @@ The corresponding entry should already be added to the spatial_ref_sys metadata
 <li> <b>SPATIAL_INDEX</b>: (From GDAL 2.0.0) Boolean flag (YES/NO) to enable/disable the automatic creation of a spatial index on the newly created layers (enabled by default).</li>
 <li> <b>UPLOAD_GEOM_FORMAT</b>: (From GDAL 2.0.0) Specify the geometry format (wkb or wkt) when creating or modifying features. The default is wkb.</li>
 <li> <b>FID</b>: (From GDAL 2.0.0) Name of the FID column to create. Defaults to ogr_fid.</li>
+<li> <b>FID64</b>: (From GDAL 2.0.0) Specifies whether to create the FID column with bigint type to handle 64bit wide ids. Default = NO</li>
+<li> <b>GEOMETRY_NULLABLE</b>: (From GDAL 2.0.0) Specifies whether the values of the geometry column can be NULL. Default = YES</li>
 </ul>
 
 <h3>Spatial Index Creation</h3>
 
-<p>By default the MS SQL Spatial driver doesn't add spatial indexes to the tables during the layer creation. However you should create a spatial index by using the 
+<p>By default the MS SQL Spatial driver doesn't add spatial indexes to the tables during the layer creation. However you should create a spatial index by using the
     following sql option:</p>
 
 <blockquote><pre>create spatial index on schema.table</pre></blockquote>
@@ -111,6 +115,27 @@ The corresponding entry should already be added to the spatial_ref_sys metadata
 
 <blockquote><pre>drop spatial index on schema.table</pre></blockquote>
 
+<h2>Configuration options</h2>
+
+<p>There are a variety of
+<a href="http://trac.osgeo.org/gdal/wiki/ConfigOptions">Configuration
+Options</a> which help control the behavior of this driver.</p>
+
+<ul>
+<li><b>MSSQLSPATIAL_USE_BCP</b>: (From GDAL 2.1.0) Enable bulk insert when adding features. This option requires to
+    to compile GDAL against a bulk copy enabled ODBC driver like SQL Server Native
+    Client 11.0. To specify a BCP supported driver in the connection string, use the
+    driver parameter, like DRIVER={SQL Server Native Client 11.0}. If GDAL is
+    compiled against SQL Server Native Client 10.0 or 11.0 the driver is selected
+    automatically not requiring to specify that in the connection string. If GDAL is 
+    compiled against SQL Server Native Client 10.0 or 11.0 the default setting of 
+    this parameter is TRUE, otherwise the parameter is ignored by the driver.</li>
+<li><b>MSSQLSPATIAL_BCP_SIZE</b>: (From GDAL 2.1.0) Specifies the bulk insert batch size. The larger value makes the insert faster, but consumes more memory. Default = 1000.</li>
+<li><b>MSSQLSPATIAL_OGR_FID</b>: Override FID column name. Default = ogr_fid.</li>
+<li><b>MSSQLSPATIAL_USE_GEOMETRY_COLUMNS</b>: Use/create geometry_columns metadata table in the database. Default = "YES".</li>
+<li><b>MSSQLSPATIAL_LIST_ALL_TABLES</b>: Use mssql catalog to list available layers. Default = "NO".</li>
+</ul>
+
 <h2>Transaction support (GDAL >= 2.0)</h2>
 
 <p>
diff --git a/ogr/ogrsf_frmts/mssqlspatial/makefile.vc b/ogr/ogrsf_frmts/mssqlspatial/makefile.vc
index 9455ca5..aaf44f1 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/makefile.vc
+++ b/ogr/ogrsf_frmts/mssqlspatial/makefile.vc
@@ -1,13 +1,29 @@
 
-OBJ	=	ogrmssqlspatialdriver.obj ogrmssqlspatialdatasource.obj ogrmssqlspatiallayer.obj ogrmssqlspatialtablelayer.obj ogrmssqlspatialselectlayer.obj ogrmssqlgeometryparser.obj ogrmssqlgeometryvalidator.obj
+OBJ	=	ogrmssqlspatialdriver.obj ogrmssqlspatialdatasource.obj ogrmssqlspatiallayer.obj ogrmssqlspatialtablelayer.obj ogrmssqlspatialselectlayer.obj ogrmssqlgeometryparser.obj ogrmssqlgeometryvalidator.obj ogrmssqlgeometrywriter.obj
+
+PLUGIN_DLL = ogr_MSSQLSpatial.dll
 
 GDAL_ROOT	=	..\..\..
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
-EXTRAFLAGS = -I.. -I..\..
+EXTRAFLAGS = -I.. -I..\.. $(SQLNCLI_INCLUDE)
 
 default:	$(OBJ)
 
+plugin: $(PLUGIN_DLL)
+
+$(PLUGIN_DLL):	$(OBJ)
+	link /dll /out:$(PLUGIN_DLL) $(OBJ) $(GDALLIB) $(ODBCLIB) $(SQLNCLI_LIB) $(LDEBUG)
+	if exist $(PLUGIN_DLL).manifest mt -manifest $(PLUGIN_DLL).manifest -outputresource:$(PLUGIN_DLL);2
+
 clean:
-	-del *.obj *.pdb
+    -del *.lib
+	-del *.obj *.pdb *.exp
+    -del *.exe
+	-del *.dll
+	-del *.manifest
+
+plugin-install:
+	-mkdir $(PLUGINDIR)
+	$(INSTALL) $(PLUGIN_DLL) $(PLUGINDIR)
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogr_mssqlspatial.h b/ogr/ogrsf_frmts/mssqlspatial/ogr_mssqlspatial.h
index 96e031c..5090774 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/ogr_mssqlspatial.h
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogr_mssqlspatial.h
@@ -1,401 +1,523 @@
-/******************************************************************************
- * $Id: ogr_mssqlspatial.h 29185 2015-05-12 10:45:44Z tamas $
- *
- * Project:  MSSQL Spatial driver
- * Purpose:  Definition of classes for OGR MSSQL Spatial driver.
- * Author:   Tamas Szekeres, szekerest at gmail.com
- *
- ******************************************************************************
- * Copyright (c) 2010, Tamas Szekeres
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#ifndef _OGR_MSSQLSPATIAL_H_INCLUDED
-#define _OGR_MSSQLSPATIAL_H_INCLUDED
-
-#include "ogrsf_frmts.h"
-#include "cpl_odbc.h"
-#include "cpl_error.h"
-
-class OGRMSSQLSpatialDataSource;
-
-/* layer status */
-#define MSSQLLAYERSTATUS_ORIGINAL  0
-#define MSSQLLAYERSTATUS_INITIAL 1
-#define MSSQLLAYERSTATUS_CREATED 2
-#define MSSQLLAYERSTATUS_DISABLED 3
-
-/* geometry format to transfer geometry column */
-#define MSSQLGEOMETRY_NATIVE 0
-#define MSSQLGEOMETRY_WKB 1
-#define MSSQLGEOMETRY_WKT 2
-#define MSSQLGEOMETRY_WKBZM 3  /* SQL Server 2012 */
-
-/* geometry column types */
-#define MSSQLCOLTYPE_GEOMETRY  0
-#define MSSQLCOLTYPE_GEOGRAPHY 1
-#define MSSQLCOLTYPE_BINARY 2
-#define MSSQLCOLTYPE_TEXT 3
-
-/************************************************************************/
-/*                         OGRMSSQLAppendEscaped( )                     */
-/************************************************************************/
-
-void OGRMSSQLAppendEscaped( CPLODBCStatement* poStatement, const char* pszStrValue);
-
-/************************************************************************/
-/*                           OGRMSSQLGeometryParser                     */
-/************************************************************************/
-
-class OGRMSSQLGeometryValidator
-{
-protected:
-    int bIsValid;
-    OGRGeometry*    poValidGeometry;
-    OGRGeometry*    poOriginalGeometry;
-
-public:
-                    OGRMSSQLGeometryValidator(OGRGeometry* poGeom);
-                    ~OGRMSSQLGeometryValidator();
-
-    int             ValidatePoint(OGRPoint * poGeom);
-    int             ValidateMultiPoint(OGRMultiPoint * poGeom);
-    int             ValidateLineString(OGRLineString * poGeom);
-    int             ValidateLinearRing(OGRLinearRing * poGeom);
-    int             ValidateMultiLineString(OGRMultiLineString * poGeom);
-    int             ValidatePolygon(OGRPolygon* poGeom);
-    int             ValidateMultiPolygon(OGRMultiPolygon* poGeom);
-    int             ValidateGeometryCollection(OGRGeometryCollection* poGeom);
-    int             ValidateGeometry(OGRGeometry* poGeom);
-
-    OGRGeometry*    GetValidGeometryRef();
-    int             IsValid() { return bIsValid; };
-};
-
-/************************************************************************/
-/*                           OGRMSSQLGeometryParser                     */
-/************************************************************************/
-
-class OGRMSSQLGeometryParser
-{
-protected:    
-    unsigned char* pszData;
-    /* serialization propeties */
-    char chProps;
-    /* point array */
-    int nPointSize;
-    int nPointPos;
-    int nNumPoints;
-    /* figure array */
-    int nFigurePos;
-    int nNumFigures;
-    /* shape array */
-    int nShapePos;
-    int nNumShapes;
-    int nSRSId;
-    /* geometry or geography */
-    int nColType;
-
-protected:
-    OGRPoint*           ReadPoint(int iShape);
-    OGRMultiPoint*      ReadMultiPoint(int iShape);
-    OGRLineString*      ReadLineString(int iShape);
-    OGRMultiLineString* ReadMultiLineString(int iShape);
-    OGRPolygon*         ReadPolygon(int iShape);
-    OGRMultiPolygon*    ReadMultiPolygon(int iShape);
-    OGRGeometryCollection* ReadGeometryCollection(int iShape);
-
-public:
-                        OGRMSSQLGeometryParser( int nGeomColumnType );
-    OGRErr              ParseSqlGeometry(unsigned char* pszInput, int nLen,
-                                                        OGRGeometry **poGeom);
-    int                 GetSRSId() { return nSRSId; };
-};
-
-
-/************************************************************************/
-/*                             OGRMSSQLSpatialLayer                     */
-/************************************************************************/
-
-class OGRMSSQLSpatialLayer : public OGRLayer
-{
-    protected:
-    OGRFeatureDefn     *poFeatureDefn;
-
-    CPLODBCStatement   *poStmt;
-
-    // Layer spatial reference system, and srid.
-    OGRSpatialReference *poSRS;
-    int                 nSRSId;
-
-    GIntBig             iNextShapeId;
-
-    OGRMSSQLSpatialDataSource    *poDS;
-
-    int                nGeomColumnType;
-    char               *pszGeomColumn;
-    char               *pszFIDColumn;
-
-    int                bIsIdentityFid;
-
-    int                nLayerStatus;
-
-    int                *panFieldOrdinals;
-
-    CPLErr              BuildFeatureDefn( const char *pszLayerName,
-                                          CPLODBCStatement *poStmt );
-
-    virtual CPLODBCStatement *  GetStatement() { return poStmt; }
-
-  public:
-                        OGRMSSQLSpatialLayer();
-    virtual             ~OGRMSSQLSpatialLayer();
-
-    virtual void        ResetReading();
-    virtual OGRFeature *GetNextRawFeature();
-    virtual OGRFeature *GetNextFeature();
-
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
-    
-    virtual OGRFeatureDefn *GetLayerDefn() { return poFeatureDefn; }
-
-    virtual OGRSpatialReference *GetSpatialRef();
-
-    virtual OGRErr     StartTransaction();
-    virtual OGRErr     CommitTransaction();
-    virtual OGRErr     RollbackTransaction();
-
-    virtual const char *GetFIDColumn();
-    virtual const char *GetGeometryColumn();
-
-    virtual int         TestCapability( const char * );
-    char*               GByteArrayToHexString( const GByte* pabyData, int nLen);
-
-    void               SetLayerStatus( int nStatus ) { nLayerStatus = nStatus; }
-    int                GetLayerStatus() { return nLayerStatus; }
-};
-
-/************************************************************************/
-/*                       OGRMSSQLSpatialTableLayer                      */
-/************************************************************************/
-
-class OGRMSSQLSpatialTableLayer : public OGRMSSQLSpatialLayer
-{
-    int                 bUpdateAccess;
-    int                 bLaunderColumnNames;
-    int                 bPreservePrecision;
-    int                 bNeedSpatialIndex;
-
-    int                 nUploadGeometryFormat;
-    
-    char                *pszQuery;
-
-    void		ClearStatement();
-    CPLODBCStatement* BuildStatement(const char* pszColumns);
-
-    CPLString BuildFields();
-
-    virtual CPLODBCStatement *  GetStatement();
-
-    char               *pszTableName;
-    char               *pszLayerName;
-    char               *pszSchemaName;
-
-    OGRwkbGeometryType eGeomType;
-
-  public:
-                        OGRMSSQLSpatialTableLayer( OGRMSSQLSpatialDataSource * );
-                        ~OGRMSSQLSpatialTableLayer();
-
-    CPLErr              Initialize( const char *pszSchema,
-                                    const char *pszTableName, 
-                                    const char *pszGeomCol, 
-                                    int nCoordDimension, 
-                                    int nSRId,
-                                    const char *pszSRText,
-                                    OGRwkbGeometryType eType);
-
-    OGRErr              CreateSpatialIndex();
-    void                DropSpatialIndex();
-
-    virtual void        ResetReading();
-    virtual GIntBig     GetFeatureCount( int );
-
-    virtual OGRFeatureDefn *GetLayerDefn();
-
-    virtual const char* GetName();
-
-    virtual OGRErr      SetAttributeFilter( const char * );
-
-    virtual OGRErr      ISetFeature( OGRFeature *poFeature );
-    virtual OGRErr      DeleteFeature( GIntBig nFID );
-    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
-
-    const char*         GetTableName() { return pszTableName; }
-    const char*         GetLayerName() { return pszLayerName; }
-    const char*         GetSchemaName() { return pszSchemaName; }
-
-    virtual OGRErr      CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE );
-   
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
-
-    virtual int         TestCapability( const char * );
-
-    void                SetLaunderFlag( int bFlag ) 
-                                { bLaunderColumnNames = bFlag; }
-    void                SetPrecisionFlag( int bFlag )
-                                { bPreservePrecision = bFlag; }
-    void                SetSpatialIndexFlag( int bFlag )
-                                { bNeedSpatialIndex = bFlag; }
-    void                SetUploadGeometryFormat( int nGeometryFormat )
-                                { nUploadGeometryFormat = nGeometryFormat; }
-    void                AppendFieldValue(CPLODBCStatement *poStatement,
-                                       OGRFeature* poFeature, int i, int *bind_num, void **bind_buffer);
-
-    int                 FetchSRSId();
-};
-
-/************************************************************************/
-/*                      OGRMSSQLSpatialSelectLayer                      */
-/************************************************************************/
-
-class OGRMSSQLSpatialSelectLayer : public OGRMSSQLSpatialLayer
-{
-    char                *pszBaseStatement;
-
-    void		ClearStatement();
-    OGRErr              ResetStatement();
-
-    virtual CPLODBCStatement *  GetStatement();
-
-  public:
-                        OGRMSSQLSpatialSelectLayer( OGRMSSQLSpatialDataSource *, 
-                                           CPLODBCStatement * );
-                        ~OGRMSSQLSpatialSelectLayer();
-
-    virtual void        ResetReading();
-    virtual GIntBig     GetFeatureCount( int );
-
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
-    
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
-
-    virtual int         TestCapability( const char * );
-};
-
-/************************************************************************/
-/*                           OGRODBCDataSource                          */
-/************************************************************************/
-
-class OGRMSSQLSpatialDataSource : public OGRDataSource
-{
-    OGRMSSQLSpatialTableLayer    **papoLayers;
-    int                 nLayers;
-    
-    char               *pszName;
-
-    char               *pszCatalog;
-
-    int                 bDSUpdate;
-    CPLODBCSession      oSession;
-
-    int                 nGeometryFormat;
-
-    int                 bUseGeometryColumns;
-
-    int                 bListAllTables;
-
-    // We maintain a list of known SRID to reduce the number of trips to
-    // the database to get SRSes. 
-    int                 nKnownSRID;
-    int                *panSRID;
-    OGRSpatialReference **papoSRS;
-    
-  public:
-                        OGRMSSQLSpatialDataSource();
-                        ~OGRMSSQLSpatialDataSource();
-
-    const char          *GetCatalog() { return pszCatalog; }
-
-    int                 ParseValue(char** pszValue, char* pszSource, const char* pszKey,
-                                  int nStart, int nNext, int nTerm, int bRemove);
-
-    int                 Open( const char *, int bUpdate, int bTestOpen );
-    int                 OpenTable( const char *pszSchemaName, const char *pszTableName, 
-                                   const char *pszGeomCol,int nCoordDimension,
-                                   int nSRID, const char *pszSRText, 
-                                   OGRwkbGeometryType eType, int bUpdate );
-
-    const char          *GetName() { return pszName; }
-    int                 GetLayerCount();
-    OGRLayer            *GetLayer( int );
-    OGRLayer            *GetLayerByName( const char* pszLayerName );
-
-    int                 GetGeometryFormat() { return nGeometryFormat; }
-    int                 UseGeometryColumns() { return bUseGeometryColumns; }
-
-    virtual int         DeleteLayer( int iLayer );
-    virtual OGRLayer    *ICreateLayer( const char *,
-                                      OGRSpatialReference * = NULL,
-                                      OGRwkbGeometryType = wkbUnknown,
-                                      char ** = NULL );
-
-    int                 TestCapability( const char * );
-
-    virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
-                                    OGRGeometry *poSpatialFilter,
-                                    const char *pszDialect );
-    virtual void        ReleaseResultSet( OGRLayer * poLayer );
-
-    char                *LaunderName( const char *pszSrcName );
-    OGRErr              InitializeMetadataTables();
-
-    OGRSpatialReference* FetchSRS( int nId );
-    int                 FetchSRSId( OGRSpatialReference * poSRS );
-
-    OGRErr              StartTransaction(CPL_UNUSED int bForce);
-    OGRErr              CommitTransaction();
-    OGRErr              RollbackTransaction();
-
-    // Internal use
-    CPLODBCSession     *GetSession() { return &oSession; }
-
-};
-
-/************************************************************************/
-/*                             OGRODBCDriver                            */
-/************************************************************************/
-
-class OGRMSSQLSpatialDriver : public OGRSFDriver
-{
-  public:
-    ~OGRMSSQLSpatialDriver();
-                
-    const char *GetName();
-    OGRDataSource *Open( const char *, int );
-
-    virtual OGRDataSource *CreateDataSource( const char *pszName,
-                                             char ** = NULL );
-    
-    int                 TestCapability( const char * );
-};
-
-#endif /* ndef _OGR_MSSQLSPATIAL_H_INCLUDED */
+/******************************************************************************
+ * $Id: ogr_mssqlspatial.h 33807 2016-03-29 19:06:42Z tamas $
+ *
+ * Project:  MSSQL Spatial driver
+ * Purpose:  Definition of classes for OGR MSSQL Spatial driver.
+ * Author:   Tamas Szekeres, szekerest at gmail.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2010, Tamas Szekeres
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef OGR_MSSQLSPATIAL_H_INCLUDED
+#define OGR_MSSQLSPATIAL_H_INCLUDED
+
+#include "ogrsf_frmts.h"
+#include "cpl_odbc.h"
+#include "cpl_error.h"
+
+class OGRMSSQLSpatialDataSource;
+
+/* layer status */
+#define MSSQLLAYERSTATUS_ORIGINAL  0
+#define MSSQLLAYERSTATUS_INITIAL 1
+#define MSSQLLAYERSTATUS_CREATED 2
+#define MSSQLLAYERSTATUS_DISABLED 3
+
+/* geometry format to transfer geometry column */
+#define MSSQLGEOMETRY_NATIVE 0
+#define MSSQLGEOMETRY_WKB 1
+#define MSSQLGEOMETRY_WKT 2
+#define MSSQLGEOMETRY_WKBZM 3  /* SQL Server 2012 */
+
+/* geometry column types */
+#define MSSQLCOLTYPE_GEOMETRY  0
+#define MSSQLCOLTYPE_GEOGRAPHY 1
+#define MSSQLCOLTYPE_BINARY 2
+#define MSSQLCOLTYPE_TEXT 3
+
+/* sqlgeometry constants */
+
+#define SP_NONE 0
+#define SP_HASZVALUES 1
+#define SP_HASMVALUES 2
+#define SP_ISVALID 4
+#define SP_ISSINGLEPOINT 8
+#define SP_ISSINGLELINESEGMENT 0x10
+#define SP_ISWHOLEGLOBE 0x20
+
+#define ST_UNKNOWN 0
+#define ST_POINT 1
+#define ST_LINESTRING 2
+#define ST_POLYGON 3
+#define ST_MULTIPOINT 4
+#define ST_MULTILINESTRING 5
+#define ST_MULTIPOLYGON 6
+#define ST_GEOMETRYCOLLECTION 7
+
+/************************************************************************/
+/*                         OGRMSSQLAppendEscaped( )                     */
+/************************************************************************/
+
+void OGRMSSQLAppendEscaped( CPLODBCStatement* poStatement, const char* pszStrValue);
+
+/************************************************************************/
+/*                           OGRMSSQLGeometryParser                     */
+/************************************************************************/
+
+class OGRMSSQLGeometryValidator
+{
+protected:
+    int bIsValid;
+    OGRGeometry*    poValidGeometry;
+    OGRGeometry*    poOriginalGeometry;
+
+public:
+                    OGRMSSQLGeometryValidator(OGRGeometry* poGeom);
+                    ~OGRMSSQLGeometryValidator();
+
+    int             ValidatePoint(OGRPoint * poGeom);
+    int             ValidateMultiPoint(OGRMultiPoint * poGeom);
+    int             ValidateLineString(OGRLineString * poGeom);
+    int             ValidateLinearRing(OGRLinearRing * poGeom);
+    int             ValidateMultiLineString(OGRMultiLineString * poGeom);
+    int             ValidatePolygon(OGRPolygon* poGeom);
+    int             ValidateMultiPolygon(OGRMultiPolygon* poGeom);
+    int             ValidateGeometryCollection(OGRGeometryCollection* poGeom);
+    int             ValidateGeometry(OGRGeometry* poGeom);
+
+    OGRGeometry*    GetValidGeometryRef();
+    int             IsValid() { return bIsValid; };
+};
+
+/************************************************************************/
+/*                           OGRMSSQLGeometryParser                     */
+/************************************************************************/
+
+class OGRMSSQLGeometryParser
+{
+protected:    
+    unsigned char* pszData;
+    /* serialization properties */
+    char chProps;
+    /* point array */
+    int nPointSize;
+    int nPointPos;
+    int nNumPoints;
+    /* figure array */
+    int nFigurePos;
+    int nNumFigures;
+    /* shape array */
+    int nShapePos;
+    int nNumShapes;
+    int nSRSId;
+    /* geometry or geography */
+    int nColType;
+
+protected:
+    OGRPoint*           ReadPoint(int iShape);
+    OGRMultiPoint*      ReadMultiPoint(int iShape);
+    OGRLineString*      ReadLineString(int iShape);
+    OGRMultiLineString* ReadMultiLineString(int iShape);
+    OGRPolygon*         ReadPolygon(int iShape);
+    OGRMultiPolygon*    ReadMultiPolygon(int iShape);
+    OGRGeometryCollection* ReadGeometryCollection(int iShape);
+
+public:
+                        OGRMSSQLGeometryParser( int nGeomColumnType );
+    OGRErr              ParseSqlGeometry(unsigned char* pszInput, int nLen,
+                                                        OGRGeometry **poGeom);
+    int                 GetSRSId() { return nSRSId; };
+};
+
+
+/************************************************************************/
+/*                           OGRMSSQLGeometryWriter                     */
+/************************************************************************/
+
+class OGRMSSQLGeometryWriter
+{
+protected:
+    OGRGeometry *poGeom2;
+    unsigned char* pszData;
+    int nLen;
+    /* serialization propeties */
+    char chProps;
+    /* point array */
+    int nPointSize;
+    int nPointPos;
+    int nNumPoints;
+    int iPoint;
+    /* figure array */
+    int nFigurePos;
+    int nNumFigures;
+    int iFigure;
+    /* shape array */
+    int nShapePos;
+    int nNumShapes;
+    int iShape;
+    int nSRSId;
+    /* geometry or geography */
+    int nColType;
+
+protected:
+    void             WritePoint(OGRPoint* poGeom);
+    void             WritePoint(double x, double y);
+    void             WritePoint(double x, double y, double z);
+    void             WriteLineString(OGRLineString* poGeom);
+    void             WritePolygon(OGRPolygon* poGeom);
+    void             WriteGeometryCollection(OGRGeometryCollection* poGeom, int iParent);
+    void             WriteGeometry(OGRGeometry* poGeom, int iParent);
+    void             TrackGeometry(OGRGeometry* poGeom);
+
+public:
+                     OGRMSSQLGeometryWriter(OGRGeometry *poGeometry, int nGeomColumnType, int nSRS);
+    OGRErr           WriteSqlGeometry(unsigned char* pszBuffer, int nBufLen);
+    int              GetDataLen() { return nLen; }
+};
+
+
+/************************************************************************/
+/*                             OGRMSSQLSpatialLayer                     */
+/************************************************************************/
+
+class OGRMSSQLSpatialLayer : public OGRLayer
+{
+    protected:
+    OGRFeatureDefn     *poFeatureDefn;
+    int                 nRawColumns;
+
+    CPLODBCStatement   *poStmt;
+
+    // Layer spatial reference system, and srid.
+    OGRSpatialReference *poSRS;
+    int                 nSRSId;
+
+    GIntBig             iNextShapeId;
+
+    OGRMSSQLSpatialDataSource    *poDS;
+
+    int                nGeomColumnType;
+    char               *pszGeomColumn;
+    int                nGeomColumnIndex;
+    char               *pszFIDColumn;
+    int                nFIDColumnIndex;
+
+    int                bIsIdentityFid;
+
+    int                nLayerStatus;
+
+    int                *panFieldOrdinals;
+
+    CPLErr              BuildFeatureDefn( const char *pszLayerName,
+                                          CPLODBCStatement *poStmt );
+
+    virtual CPLODBCStatement *  GetStatement() { return poStmt; }
+
+  public:
+                        OGRMSSQLSpatialLayer();
+    virtual             ~OGRMSSQLSpatialLayer();
+
+    virtual void        ResetReading();
+    virtual OGRFeature *GetNextRawFeature();
+    virtual OGRFeature *GetNextFeature();
+
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+    
+    virtual OGRFeatureDefn *GetLayerDefn() { return poFeatureDefn; }
+
+    virtual OGRSpatialReference *GetSpatialRef();
+
+    virtual OGRErr     StartTransaction();
+    virtual OGRErr     CommitTransaction();
+    virtual OGRErr     RollbackTransaction();
+
+    virtual const char *GetFIDColumn();
+    virtual const char *GetGeometryColumn();
+
+    virtual int         TestCapability( const char * );
+    char*               GByteArrayToHexString( const GByte* pabyData, int nLen);
+
+    void               SetLayerStatus( int nStatus ) { nLayerStatus = nStatus; }
+    int                GetLayerStatus() { return nLayerStatus; }
+};
+
+/************************************************************************/
+/*                       OGRMSSQLSpatialTableLayer                      */
+/************************************************************************/
+
+typedef union {
+    struct {
+        int     iIndicator;
+        int     Value;
+    } Integer;
+
+    struct {
+        int     iIndicator;
+        GIntBig     Value;
+    } Integer64;
+    
+    struct {
+        int     iIndicator;
+        double  Value;
+    } Float;
+
+    struct {
+        int     nSize;
+        char* pData[8000];
+    } VarChar;
+
+    struct {
+        int     nSize;
+        GByte*  pData;
+    } RawData;
+
+} BCPData;
+
+class OGRMSSQLSpatialTableLayer : public OGRMSSQLSpatialLayer
+{
+    int                 bUpdateAccess;
+    int                 bLaunderColumnNames;
+    int                 bPreservePrecision;
+    int                 bNeedSpatialIndex;
+    int                 bUseCopy;
+    int                 nBCPSize;
+
+    int                 nUploadGeometryFormat;
+    
+    char                *pszQuery;
+
+    SQLHANDLE           hEnvBCP;
+    SQLHANDLE           hDBCBCP;
+    int                 nBCPCount;
+    BCPData             **papstBindBuffer;
+
+    int                 bIdentityInsert;
+
+    void		ClearStatement();
+    CPLODBCStatement* BuildStatement(const char* pszColumns);
+
+    CPLString BuildFields();
+
+    virtual CPLODBCStatement *  GetStatement();
+
+    char               *pszTableName;
+    char               *pszLayerName;
+    char               *pszSchemaName;
+
+    OGRwkbGeometryType eGeomType;
+
+
+  public:
+                        OGRMSSQLSpatialTableLayer( OGRMSSQLSpatialDataSource * );
+                        ~OGRMSSQLSpatialTableLayer();
+
+    CPLErr              Initialize( const char *pszSchema,
+                                    const char *pszTableName, 
+                                    const char *pszGeomCol, 
+                                    int nCoordDimension, 
+                                    int nSRId,
+                                    const char *pszSRText,
+                                    OGRwkbGeometryType eType);
+
+    OGRErr              CreateSpatialIndex();
+    void                DropSpatialIndex();
+
+    virtual void        ResetReading();
+    virtual GIntBig     GetFeatureCount( int );
+
+    virtual OGRFeatureDefn *GetLayerDefn();
+
+    virtual const char* GetName();
+
+    virtual OGRErr      SetAttributeFilter( const char * );
+
+    virtual OGRErr      ISetFeature( OGRFeature *poFeature );
+    virtual OGRErr      DeleteFeature( GIntBig nFID );
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
+
+    const char*         GetTableName() { return pszTableName; }
+    const char*         GetLayerName() { return pszLayerName; }
+    const char*         GetSchemaName() { return pszSchemaName; }
+
+    virtual OGRErr      CreateField( OGRFieldDefn *poField,
+                                     int bApproxOK = TRUE );
+   
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+
+    virtual int         TestCapability( const char * );
+
+    void                SetLaunderFlag( int bFlag ) 
+                                { bLaunderColumnNames = bFlag; }
+    void                SetPrecisionFlag( int bFlag )
+                                { bPreservePrecision = bFlag; }
+    void                SetSpatialIndexFlag( int bFlag )
+                                { bNeedSpatialIndex = bFlag; }
+    void                SetUploadGeometryFormat( int nGeometryFormat )
+                                { nUploadGeometryFormat = nGeometryFormat; }
+    void                AppendFieldValue(CPLODBCStatement *poStatement,
+                                       OGRFeature* poFeature, int i, int *bind_num, void **bind_buffer);
+
+    int                 FetchSRSId();
+
+    void                SetUseCopy(int bcpSize) { bUseCopy = TRUE; nBCPSize = bcpSize; }
+    int                 Failed( int nRetCode );
+#ifdef MSSQL_BCP_SUPPORTED
+    OGRErr              CreateFeatureBCP( OGRFeature *poFeature );
+    int                 Failed2( int nRetCode );
+    int                 InitBCP( const char* pszDSN );
+    void                CloseBCP();
+#endif
+};
+
+/************************************************************************/
+/*                      OGRMSSQLSpatialSelectLayer                      */
+/************************************************************************/
+
+class OGRMSSQLSpatialSelectLayer : public OGRMSSQLSpatialLayer
+{
+    char                *pszBaseStatement;
+
+    void		ClearStatement();
+    OGRErr              ResetStatement();
+
+    virtual CPLODBCStatement *  GetStatement();
+
+  public:
+                        OGRMSSQLSpatialSelectLayer( OGRMSSQLSpatialDataSource *, 
+                                           CPLODBCStatement * );
+                        ~OGRMSSQLSpatialSelectLayer();
+
+    virtual void        ResetReading();
+    virtual GIntBig     GetFeatureCount( int );
+
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+    
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
+
+    virtual int         TestCapability( const char * );
+};
+
+/************************************************************************/
+/*                           OGRODBCDataSource                          */
+/************************************************************************/
+
+class OGRMSSQLSpatialDataSource : public OGRDataSource
+{
+    OGRMSSQLSpatialTableLayer    **papoLayers;
+    int                 nLayers;
+    
+    char               *pszName;
+
+    char               *pszCatalog;
+
+    int                 bDSUpdate;
+    CPLODBCSession      oSession;
+
+    int                 nGeometryFormat;
+
+    int                 bUseGeometryColumns;
+
+    int                 bListAllTables;
+
+    int                 nBCPSize;
+    int                 bUseCopy;
+
+    // We maintain a list of known SRID to reduce the number of trips to
+    // the database to get SRSes. 
+    int                 nKnownSRID;
+    int                *panSRID;
+    OGRSpatialReference **papoSRS;
+
+    char                *pszConnection;
+    
+  public:
+                        OGRMSSQLSpatialDataSource();
+                        ~OGRMSSQLSpatialDataSource();
+
+    const char          *GetCatalog() { return pszCatalog; }
+
+    int                 ParseValue(char** pszValue, char* pszSource, const char* pszKey,
+                                  int nStart, int nNext, int nTerm, int bRemove);
+
+    int                 Open( const char *, int bUpdate, int bTestOpen );
+    int                 OpenTable( const char *pszSchemaName, const char *pszTableName, 
+                                   const char *pszGeomCol,int nCoordDimension,
+                                   int nSRID, const char *pszSRText, 
+                                   OGRwkbGeometryType eType, int bUpdate );
+
+    const char          *GetName() { return pszName; }
+    int                 GetLayerCount();
+    OGRLayer            *GetLayer( int );
+    OGRLayer            *GetLayerByName( const char* pszLayerName );
+
+    int                 GetGeometryFormat() { return nGeometryFormat; }
+    int                 UseGeometryColumns() { return bUseGeometryColumns; }
+
+    virtual OGRErr       DeleteLayer( int iLayer );
+    virtual OGRLayer    *ICreateLayer( const char *,
+                                      OGRSpatialReference * = NULL,
+                                      OGRwkbGeometryType = wkbUnknown,
+                                      char ** = NULL );
+
+    int                 TestCapability( const char * );
+
+    virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
+                                    OGRGeometry *poSpatialFilter,
+                                    const char *pszDialect );
+    virtual void        ReleaseResultSet( OGRLayer * poLayer );
+
+    char                *LaunderName( const char *pszSrcName );
+    OGRErr              InitializeMetadataTables();
+
+    OGRSpatialReference* FetchSRS( int nId );
+    int                 FetchSRSId( OGRSpatialReference * poSRS );
+
+    OGRErr              StartTransaction(CPL_UNUSED int bForce);
+    OGRErr              CommitTransaction();
+    OGRErr              RollbackTransaction();
+
+    // Internal use
+    CPLODBCSession     *GetSession() { return &oSession; }
+    const char         *GetConnectionString() { return pszConnection; }
+};
+
+/************************************************************************/
+/*                             OGRODBCDriver                            */
+/************************************************************************/
+
+class OGRMSSQLSpatialDriver : public OGRSFDriver
+{
+  public:
+    ~OGRMSSQLSpatialDriver();
+                
+    const char *GetName();
+    OGRDataSource *Open( const char *, int );
+
+    virtual OGRDataSource *CreateDataSource( const char *pszName,
+                                             char ** = NULL );
+    
+    int                 TestCapability( const char * );
+};
+
+#endif /* ndef OGR_MSSQLSPATIAL_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlgeometryparser.cpp b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlgeometryparser.cpp
index 51af7bb..152aa5e 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlgeometryparser.cpp
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlgeometryparser.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmssqlgeometryparser.cpp 24918 2012-09-07 12:02:01Z tamas $
+ * $Id: ogrmssqlgeometryparser.cpp 33775 2016-03-23 20:25:05Z tamas $
  *
  * Project:  MSSQL Spatial driver
  * Purpose:  Implements OGRMSSQLGeometryParser class to parse native SqlGeometries.
@@ -30,7 +30,7 @@
 #include "cpl_conv.h"
 #include "ogr_mssqlspatial.h"
 
-CPL_CVSID("$Id: ogrmssqlgeometryparser.cpp 24918 2012-09-07 12:02:01Z tamas $");
+CPL_CVSID("$Id: ogrmssqlgeometryparser.cpp 33775 2016-03-23 20:25:05Z tamas $");
 
 /*   SqlGeometry serialization format
 
@@ -68,7 +68,7 @@ FigureAttribute (1 byte)
   0x02 = Exterior Ring
 
 Shape
-  [ParentFigureOffset][FigureOffset][ShapeType]
+  [ParentOffset][FigureOffset][ShapeType]
 
 ShapeType (1 byte)
   0x00 = Unknown
@@ -86,23 +86,6 @@ ShapeType (1 byte)
 /*                         Geometry parser macros                       */
 /************************************************************************/
 
-#define SP_NONE 0
-#define SP_HASZVALUES 1
-#define SP_HASMVALUES 2
-#define SP_ISVALID 4
-#define SP_ISSINGLEPOINT 8
-#define SP_ISSINGLELINESEGMENT 0x10
-#define SP_ISWHOLEGLOBE 0x20
-
-#define ST_UNKNOWN 0
-#define ST_POINT 1
-#define ST_LINESTRING 2
-#define ST_POLYGON 3
-#define ST_MULTIPOINT 4
-#define ST_MULTILINESTRING 5
-#define ST_MULTIPOLYGON 6
-#define ST_GEOMETRYCOLLECTION 7
-
 #define ReadInt32(nPos) (*((unsigned int*)(pszData + (nPos))))
 
 #define ReadByte(nPos) (pszData[nPos])
@@ -131,6 +114,16 @@ ShapeType (1 byte)
 OGRMSSQLGeometryParser::OGRMSSQLGeometryParser(int nGeomColumnType)
 {
     nColType = nGeomColumnType;
+    pszData = NULL;
+    chProps = 0;
+    nPointSize = 0;
+    nPointPos = 0;
+    nNumPoints = 0;
+    nFigurePos = 0;
+    nNumFigures = 0;
+    nShapePos = 0;
+    nNumShapes = 0;
+    nSRSId = 0;
 }
 
 /************************************************************************/
@@ -219,7 +212,7 @@ OGRLineString* OGRMSSQLGeometryParser::ReadLineString(int iShape)
             else
                 poLineString->setPoint(i, ReadX(iPoint), ReadY(iPoint) );
         }
-        
+
         ++iPoint;
         ++i;
     }
@@ -260,7 +253,7 @@ OGRPolygon* OGRMSSQLGeometryParser::ReadPolygon(int iShape)
 {
     int iFigure, iPoint, iNextPoint, i;
     int iNextFigure = NextFigureOffset(iShape);
-    
+
     OGRPolygon* poPoly = new OGRPolygon();
     for (iFigure = FigureOffset(iShape); iFigure < iNextFigure; iFigure++)
     {
@@ -272,7 +265,7 @@ OGRPolygon* OGRMSSQLGeometryParser::ReadPolygon(int iShape)
         while (iPoint < iNextPoint)
         {
             if (nColType == MSSQLCOLTYPE_GEOGRAPHY)
-            {  
+            {
                 if ( chProps & SP_HASZVALUES )
                     poRing->setPoint(i, ReadY(iPoint), ReadX(iPoint), ReadZ(iPoint) );
                 else
@@ -371,17 +364,17 @@ OGRGeometryCollection* OGRMSSQLGeometryParser::ReadGeometryCollection(int iShape
 /************************************************************************/
 
 
-OGRErr OGRMSSQLGeometryParser::ParseSqlGeometry(unsigned char* pszInput, 
+OGRErr OGRMSSQLGeometryParser::ParseSqlGeometry(unsigned char* pszInput,
                                 int nLen, OGRGeometry **poGeom)
 {
     if (nLen < 10)
         return OGRERR_NOT_ENOUGH_DATA;
 
     pszData = pszInput;
-    
+
     /* store the SRS id for further use */
     nSRSId = ReadInt32(0);
-    
+
     if ( ReadByte(4) != 1 )
     {
         return OGRERR_CORRUPT_DATA;
@@ -435,7 +428,7 @@ OGRErr OGRMSSQLGeometryParser::ParseSqlGeometry(unsigned char* pszInput,
 
         OGRLineString* line = new OGRLineString();
         line->setNumPoints(2);
-        
+
         if (nColType == MSSQLCOLTYPE_GEOGRAPHY)
         {
             if ( chProps & SP_HASZVALUES )
@@ -462,7 +455,7 @@ OGRErr OGRMSSQLGeometryParser::ParseSqlGeometry(unsigned char* pszInput,
                 line->setPoint(1, ReadX(1), ReadY(1));
             }
         }
-        
+
         *poGeom = line;
     }
     else
@@ -480,7 +473,7 @@ OGRErr OGRMSSQLGeometryParser::ParseSqlGeometry(unsigned char* pszInput,
 
         // position of the figures
         nFigurePos = nPointPos + nPointSize * nNumPoints + 4;
-        
+
         if (nLen < nFigurePos)
         {
             return OGRERR_NOT_ENOUGH_DATA;
@@ -492,7 +485,7 @@ OGRErr OGRMSSQLGeometryParser::ParseSqlGeometry(unsigned char* pszInput,
         {
             return OGRERR_NONE;
         }
-        
+
         // position of the shapes
         nShapePos = nFigurePos + 5 * nNumFigures + 4;
 
@@ -550,4 +543,3 @@ OGRErr OGRMSSQLGeometryParser::ParseSqlGeometry(unsigned char* pszInput,
 
     return OGRERR_NONE;
 }
-
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlgeometrywriter.cpp b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlgeometrywriter.cpp
new file mode 100644
index 0000000..2c79cf2
--- /dev/null
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlgeometrywriter.cpp
@@ -0,0 +1,507 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  MSSQL Spatial driver
+ * Purpose:  Implements OGRMSSQLGeometryWriter class to write native SqlGeometries.
+ * Author:   Tamas Szekeres, szekerest at gmail.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Tamas Szekeres
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_conv.h"
+#include "ogr_mssqlspatial.h"
+
+CPL_CVSID("$Id$");
+
+/*   SqlGeometry serialization format
+
+Simple Point (SerializationProps & IsSinglePoint)
+  [SRID][0x01][SerializationProps][Point][z][m]
+
+Simple Line Segment (SerializationProps & IsSingleLineSegment)
+  [SRID][0x01][SerializationProps][Point1][Point2][z1][z2][m1][m2]
+
+Complex Geometries
+  [SRID][0x01][SerializationProps][NumPoints][Point1]..[PointN][z1]..[zN][m1]..[mN]
+  [NumFigures][Figure]..[Figure][NumShapes][Shape]..[Shape]
+
+SRID
+  Spatial Reference Id (4 bytes)
+
+SerializationProps (bitmask) 1 byte
+  0x01 = HasZValues
+  0x02 = HasMValues
+  0x04 = IsValid
+  0x08 = IsSinglePoint
+  0x10 = IsSingleLineSegment
+  0x20 = IsWholeGlobe
+
+Point (2-4)x8 bytes, size depends on SerializationProps & HasZValues & HasMValues
+  [x][y]                  - SqlGeometry
+  [latitude][longitude]   - SqlGeography
+
+Figure
+  [FigureAttribute][PointOffset]
+
+FigureAttribute (1 byte)
+  0x00 = Interior Ring
+  0x01 = Stroke
+  0x02 = Exterior Ring
+
+Shape
+  [ParentOffset][FigureOffset][ShapeType]
+
+ShapeType (1 byte)
+  0x00 = Unknown
+  0x01 = Point
+  0x02 = LineString
+  0x03 = Polygon
+  0x04 = MultiPoint
+  0x05 = MultiLineString
+  0x06 = MultiPolygon
+  0x07 = GeometryCollection
+
+*/
+
+/************************************************************************/
+/*                         Geometry writer macros                       */
+/************************************************************************/
+
+#define WriteInt32(nPos, value) (*((unsigned int*)(pszData + (nPos))) = value)
+
+#define WriteByte(nPos, value) (pszData[nPos] = value)
+
+#define WriteDouble(nPos, value) (*((double*)(pszData + (nPos))) = value)
+
+#define ParentOffset(iShape) (nShapePos + (iShape) * 9 )
+#define FigureOffset(iShape) (nShapePos + (iShape) * 9 + 4)
+#define ShapeType(iShape) (nShapePos + (iShape) * 9 + 8)
+
+#define FigureAttribute(iFigure) (nFigurePos + (iFigure) * 5)
+#define PointOffset(iFigure) (nFigurePos + (iFigure) * 5 + 1)
+
+#define WriteX(iPoint, value) (WriteDouble(nPointPos + 16 * (iPoint), value))
+#define WriteY(iPoint, value) (WriteDouble(nPointPos + 16 * (iPoint) + 8, value))
+#define WriteZ(iPoint, value) (WriteDouble(nPointPos + 16 * nNumPoints + 8 * (iPoint), value))
+#define WriteM(iPoint, value) (WriteDouble(nPointPos + 24 * nNumPoints + 8 * (iPoint), value))
+
+/************************************************************************/
+/*                   OGRMSSQLGeometryWriter()                           */
+/************************************************************************/
+
+OGRMSSQLGeometryWriter::OGRMSSQLGeometryWriter(OGRGeometry *poGeometry, int nGeomColumnType, int nSRS)
+{
+    nColType = nGeomColumnType;
+    nSRSId = nSRS;
+    poGeom2 = poGeometry;
+
+    chProps = 0;
+
+    /* calculate required buffer length and the attributes */
+    if (poGeom2->getCoordinateDimension() == 3)
+    {
+        chProps |= SP_HASZVALUES;
+        nPointSize = 24;
+    }
+    else
+    {
+        nPointSize = 16;
+    }
+
+    iPoint = 0;
+    nNumPoints = 0;
+    iFigure = 0;
+    nNumFigures = 0;
+    iShape = 0;
+    nNumShapes = 0;
+
+    /* calculate points figures and shapes*/
+    TrackGeometry(poGeom2);
+    ++nNumShapes;
+
+    OGRwkbGeometryType geomType = poGeom2->getGeometryType();
+
+    if (nNumPoints == 1 && (geomType == wkbPoint || geomType == wkbPoint25D))
+    {
+        /* writing a single point */
+        chProps |= SP_ISSINGLEPOINT | SP_ISVALID;
+        nPointPos = 6;
+        nLen = nPointPos + nPointSize;
+    }
+    else if (nNumPoints == 2 && (geomType == wkbLineString || geomType == wkbLineString25D))
+    {
+        /* writing a single line */
+        chProps |= SP_ISSINGLELINESEGMENT | SP_ISVALID;
+        nPointPos = 6;
+        nLen = nPointPos + nPointSize * 2;
+    }
+    else
+    {
+        /* complex geometry */
+        nPointPos = 10;
+        nFigurePos = nPointPos + nPointSize * nNumPoints + 4;
+        nShapePos = nFigurePos  + 5 * nNumFigures + 4;
+        nLen = nShapePos + 9 * nNumShapes;
+    }
+}
+
+/************************************************************************/
+/*                         WritePoint()                                 */
+/************************************************************************/
+
+void OGRMSSQLGeometryWriter::WritePoint(OGRPoint* poGeom)
+{
+    if (nColType == MSSQLCOLTYPE_GEOGRAPHY)
+    {
+        WriteY(iPoint, poGeom->getX());
+        WriteX(iPoint, poGeom->getY());
+        if (chProps & SP_HASZVALUES)
+            WriteZ(iPoint, poGeom->getZ());
+    }
+    else
+    {
+        WriteX(iPoint, poGeom->getX());
+        WriteY(iPoint, poGeom->getY());
+        if (chProps & SP_HASZVALUES)
+            WriteZ(iPoint, poGeom->getZ());
+    }
+    ++iPoint;
+}
+
+void OGRMSSQLGeometryWriter::WritePoint(double x, double y)
+{
+    if (nColType == MSSQLCOLTYPE_GEOGRAPHY)
+    {
+        WriteY(iPoint, x);
+        WriteX(iPoint, y);
+    }
+    else
+    {
+        WriteX(iPoint, x);
+        WriteY(iPoint, y);
+    }
+    ++iPoint;
+}
+
+void OGRMSSQLGeometryWriter::WritePoint(double x, double y, double z)
+{
+    if (nColType == MSSQLCOLTYPE_GEOGRAPHY)
+    {
+        WriteY(iPoint, x);
+        WriteX(iPoint, y);
+    }
+    else
+    {
+        WriteX(iPoint, x);
+        WriteY(iPoint, y);
+    }
+    WriteZ(iPoint, z);
+    ++iPoint;
+}
+
+/************************************************************************/
+/*                         WriteLineString()                            */
+/************************************************************************/
+
+void OGRMSSQLGeometryWriter::WriteLineString(OGRLineString* poGeom)
+{
+    int i;
+    /* write figure */
+    WriteByte(FigureAttribute(iFigure), 0x01);
+    WriteInt32(PointOffset(iFigure), iPoint);
+    if (chProps & SP_HASZVALUES)
+    {
+        for (i = 0; i < poGeom->getNumPoints(); i++)
+            WritePoint(poGeom->getX(i), poGeom->getY(i), poGeom->getZ(i));
+    }
+    else
+    {
+        for (i = 0; i < poGeom->getNumPoints(); i++)
+            WritePoint(poGeom->getX(i), poGeom->getY(i));          
+    }
+    ++iFigure;
+}
+
+/************************************************************************/
+/*                         WritePolygon()                               */
+/************************************************************************/
+
+void OGRMSSQLGeometryWriter::WritePolygon(OGRPolygon* poGeom)
+{
+    int i, r;
+    OGRLinearRing *poRing = poGeom->getExteriorRing();
+    WriteByte(FigureAttribute(iFigure), 0x02);
+    WriteInt32(PointOffset(iFigure), iPoint);
+    if (chProps & SP_HASZVALUES)
+    {
+        /* write exterior ring */
+        for (i = 0; i < poRing->getNumPoints(); i++)
+            WritePoint(poRing->getX(i), poRing->getY(i), poRing->getZ(i));
+
+        ++iFigure;
+
+        for (r = 0; r < poGeom->getNumInteriorRings(); r++)
+        {
+            /* write interior rings */
+            poRing = poGeom->getInteriorRing(r);
+            WriteByte(FigureAttribute(iFigure), 0x00);
+            WriteInt32(PointOffset(iFigure), iPoint);
+            for (i = 0; i < poRing->getNumPoints(); i++)
+                WritePoint(poRing->getX(i), poRing->getY(i), poRing->getZ(i));
+            ++iFigure;
+        }
+    }
+    else
+    {
+        /* write exterior ring */
+        for (i = 0; i < poRing->getNumPoints(); i++)
+            WritePoint(poRing->getX(i), poRing->getY(i));
+
+        ++iFigure;
+
+        for (r = 0; r < poGeom->getNumInteriorRings(); r++)
+        {
+            /* write interior rings */
+            poRing = poGeom->getInteriorRing(r);
+            WriteByte(FigureAttribute(iFigure), 0x00);
+            WriteInt32(PointOffset(iFigure), iPoint);
+            for (i = 0; i < poRing->getNumPoints(); i++)
+                WritePoint(poRing->getX(i), poRing->getY(i));
+            ++iFigure;
+        }
+    }  
+}
+
+/************************************************************************/
+/*                         WriteGeometryCollection()                    */
+/************************************************************************/
+
+void OGRMSSQLGeometryWriter::WriteGeometryCollection(OGRGeometryCollection* poGeom, int iParent)
+{
+    int i;
+    for (i = 0; i < poGeom->getNumGeometries(); i++)
+        WriteGeometry(poGeom->getGeometryRef(i), iParent);
+}
+
+/************************************************************************/
+/*                         WriteGeometry()                              */
+/************************************************************************/
+
+void OGRMSSQLGeometryWriter::WriteGeometry(OGRGeometry* poGeom, int iParent)
+{
+    /* write shape */
+    WriteInt32(ParentOffset(iShape), iParent);
+    WriteInt32(FigureOffset(iShape), iFigure);
+
+    iParent = iShape;
+    
+    switch (poGeom->getGeometryType())
+    {
+    case wkbPoint:
+    case wkbPoint25D:
+        WriteByte(ShapeType(iShape++), ST_POINT);
+        WriteByte(FigureAttribute(iFigure), 0x01);
+        WriteInt32(PointOffset(iFigure), iPoint);
+        WritePoint((OGRPoint*)poGeom);
+        ++iFigure;
+        break;
+        
+    case wkbLineString:
+    case wkbLineString25D:
+        WriteByte(ShapeType(iShape++), ST_LINESTRING);
+        WriteLineString((OGRLineString*)poGeom);
+        break;
+
+    case wkbPolygon:
+    case wkbPolygon25D:
+        WriteByte(ShapeType(iShape++), ST_POLYGON);
+        WritePolygon((OGRPolygon*)poGeom);
+        break;
+
+    case wkbMultiPoint:
+    case wkbMultiPoint25D:
+        WriteByte(ShapeType(iShape++), ST_MULTIPOINT);
+        WriteGeometryCollection((OGRGeometryCollection*)poGeom, iParent);
+        break;
+
+    case wkbMultiLineString:
+    case wkbMultiLineString25D:
+        WriteByte(ShapeType(iShape++), ST_MULTILINESTRING);
+        WriteGeometryCollection((OGRGeometryCollection*)poGeom, iParent);
+        break;
+
+    case wkbMultiPolygon:
+    case wkbMultiPolygon25D:
+        WriteByte(ShapeType(iShape++), ST_MULTIPOLYGON);
+        WriteGeometryCollection((OGRGeometryCollection*)poGeom, iParent);
+        break;
+
+    case wkbGeometryCollection:
+    case wkbGeometryCollection25D:
+        WriteByte(ShapeType(iShape++), ST_GEOMETRYCOLLECTION);
+        WriteGeometryCollection((OGRGeometryCollection*)poGeom, iParent);
+        break;
+
+    default:
+        break;
+    }
+}
+
+/************************************************************************/
+/*                         TrackGeometry()                              */
+/************************************************************************/
+
+void OGRMSSQLGeometryWriter::TrackGeometry(OGRGeometry* poGeom)
+{
+    int i;
+    switch (poGeom->getGeometryType())
+    {
+    case wkbPoint:
+    case wkbPoint25D:
+        ++nNumFigures;
+        ++nNumPoints;
+        break;
+        
+    case wkbLineString:
+    case wkbLineString25D:
+        ++nNumFigures;
+        nNumPoints += ((OGRLineString*)poGeom)->getNumPoints();
+        break;
+
+    case wkbPolygon:
+    case wkbPolygon25D:
+        {
+            OGRPolygon* g = (OGRPolygon*)poGeom;
+            TrackGeometry(g->getExteriorRing());
+            for (i = 0; i < g->getNumInteriorRings(); i++)
+                TrackGeometry(g->getInteriorRing(i));
+        }
+        break;
+
+    case wkbMultiPoint:
+    case wkbMultiPoint25D:
+    case wkbMultiLineString:
+    case wkbMultiLineString25D:
+    case wkbMultiPolygon:
+    case wkbMultiPolygon25D:
+    case wkbGeometryCollection:
+    case wkbGeometryCollection25D:
+        {
+            OGRGeometryCollection* g = (OGRGeometryCollection*)poGeom;
+            for (i = 0; i < g->getNumGeometries(); i++)
+            {
+                TrackGeometry(g->getGeometryRef(i));
+                ++nNumShapes;
+            }
+        }
+        break;
+
+    default:
+        break;
+    }
+}
+
+/************************************************************************/
+/*                         WriteSqlGeometry()                           */
+/************************************************************************/
+
+OGRErr OGRMSSQLGeometryWriter::WriteSqlGeometry(unsigned char* pszBuffer, int nBufLen)
+{
+    pszData = pszBuffer;
+
+    if (nBufLen < nLen)
+        return OGRERR_FAILURE;
+    
+    OGRwkbGeometryType geomType = poGeom2->getGeometryType();
+
+    if (nNumPoints == 1 && (geomType == wkbPoint || geomType == wkbPoint25D))
+    {
+        /* writing a single point */
+        OGRPoint* g = (OGRPoint*)poGeom2;
+        WriteInt32(0, nSRSId);
+        WriteByte(4, 0x01);
+        WriteByte(5, chProps);
+        if (nColType == MSSQLCOLTYPE_GEOGRAPHY)
+        {
+            WriteY(0, g->getX());
+            WriteX(0, g->getY());
+            if (chProps & SP_HASZVALUES)
+                WriteZ(0, g->getZ());
+        }
+        else
+        {
+            WriteX(0, g->getX());
+            WriteY(0, g->getY());
+            if (chProps & SP_HASZVALUES)
+                WriteZ(0, g->getZ());
+        }
+    }
+    else if (nNumPoints == 2 && (geomType == wkbLineString || geomType == wkbLineString25D))
+    {
+        /* writing a single line */
+        OGRLineString* g = (OGRLineString*)poGeom2;
+        WriteInt32(0, nSRSId);
+        WriteByte(4, 0x01);
+        WriteByte(5, chProps);
+        if (nColType == MSSQLCOLTYPE_GEOGRAPHY)
+        {
+            WriteY(0, g->getX(0));
+            WriteX(0, g->getY(0));
+            WriteY(1, g->getX(1));
+            WriteX(1, g->getY(1));
+            if (chProps & SP_HASZVALUES)
+            {
+                WriteZ(0, g->getZ(0));
+                WriteZ(1, g->getZ(1));
+            }
+        }
+        else
+        {
+            WriteX(0, g->getX(0));
+            WriteY(0, g->getY(0));
+            WriteX(1, g->getX(1));
+            WriteY(1, g->getY(1));
+            if (chProps & SP_HASZVALUES)
+            {
+                WriteZ(0, g->getZ(0));
+                WriteZ(1, g->getZ(1));
+            }
+        }
+    }
+    else
+    {
+        /* complex geometry */
+        if (poGeom2->IsValid())
+            chProps |= SP_ISVALID;
+
+        WriteInt32(0, nSRSId);
+        WriteByte(4, 0x01);
+        WriteByte(5, chProps);
+        WriteInt32(nPointPos - 4 , nNumPoints);
+        WriteInt32(nFigurePos - 4 , nNumFigures);
+        WriteInt32(nShapePos - 4 , nNumShapes);
+
+        WriteGeometry(poGeom2, 0xFFFFFFFF);
+    }
+    return OGRERR_NONE;
+}
+
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdatasource.cpp b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdatasource.cpp
index 250f6a3..176a808 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdatasource.cpp
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmssqlspatialdatasource.cpp 29185 2015-05-12 10:45:44Z tamas $
+ * $Id: ogrmssqlspatialdatasource.cpp 33834 2016-03-31 18:36:27Z tamas $
  *
  * Project:  MSSQL Spatial driver
  * Purpose:  Implements OGRMSSQLSpatialDataSource class..
@@ -30,14 +30,14 @@
 
 #include "ogr_mssqlspatial.h"
 
-CPL_CVSID("$Id: ogrmssqlspatialdatasource.cpp 29185 2015-05-12 10:45:44Z tamas $");
+CPL_CVSID("$Id: ogrmssqlspatialdatasource.cpp 33834 2016-03-31 18:36:27Z tamas $");
 
 /************************************************************************/
 /*                          OGRMSSQLSpatialDataSource()                 */
 /************************************************************************/
 
-OGRMSSQLSpatialDataSource::OGRMSSQLSpatialDataSource()
-
+OGRMSSQLSpatialDataSource::OGRMSSQLSpatialDataSource() :
+    bDSUpdate(FALSE)
 {
     pszName = NULL;
     pszCatalog = NULL;
@@ -49,9 +49,21 @@ OGRMSSQLSpatialDataSource::OGRMSSQLSpatialDataSource()
     papoSRS = NULL;
 
     nGeometryFormat = MSSQLGEOMETRY_NATIVE;
+    pszConnection = NULL;
+
+    bUseGeometryColumns = CPLTestBool(CPLGetConfigOption("MSSQLSPATIAL_USE_GEOMETRY_COLUMNS", "YES"));
+    bListAllTables = CPLTestBool(CPLGetConfigOption("MSSQLSPATIAL_LIST_ALL_TABLES", "NO"));
 
-    bUseGeometryColumns = CSLTestBoolean(CPLGetConfigOption("MSSQLSPATIAL_USE_GEOMETRY_COLUMNS", "YES"));
-    bListAllTables = CSLTestBoolean(CPLGetConfigOption("MSSQLSPATIAL_LIST_ALL_TABLES", "NO"));
+    const char* nBCPSizeParam = CPLGetConfigOption("MSSQLSPATIAL_BCP_SIZE", NULL);
+    if( nBCPSizeParam != NULL )
+        nBCPSize = atoi(nBCPSizeParam);
+    else
+        nBCPSize = 1000;
+#ifdef MSSQL_BCP_SUPPORTED
+    bUseCopy = CSLTestBoolean(CPLGetConfigOption("MSSQLSPATIAL_USE_BCP", "TRUE"));
+#else
+    bUseCopy = FALSE;
+#endif
 }
 
 /************************************************************************/
@@ -61,23 +73,22 @@ OGRMSSQLSpatialDataSource::OGRMSSQLSpatialDataSource()
 OGRMSSQLSpatialDataSource::~OGRMSSQLSpatialDataSource()
 
 {
-    int         i;
-
-    for( i = 0; i < nLayers; i++ )
+    for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
-    
+
     CPLFree( papoLayers );
 
     CPLFree( pszName );
     CPLFree( pszCatalog );
 
-    for( i = 0; i < nKnownSRID; i++ )
+    for( int i = 0; i < nKnownSRID; i++ )
     {
         if( papoSRS[i] != NULL )
             papoSRS[i]->Release();
     }
     CPLFree( panSRID );
     CPLFree( papoSRS );
+    CPLFree( pszConnection );
 }
 
 /************************************************************************/
@@ -119,14 +130,14 @@ OGRLayer *OGRMSSQLSpatialDataSource::GetLayerByName( const char* pszLayerName )
 {
     if (!pszLayerName)
         return NULL;
-    
+
     char *pszTableName = NULL;
     char *pszSchemaName = NULL;
 
     const char* pszDotPos = strstr(pszLayerName,".");
     if ( pszDotPos != NULL )
     {
-      int length = pszDotPos - pszLayerName;
+      int length = static_cast<int>(pszDotPos - pszLayerName);
       pszSchemaName = (char*)CPLMalloc(length+1);
       strncpy(pszSchemaName, pszLayerName, length);
       pszSchemaName[length] = '\0';
@@ -137,10 +148,10 @@ OGRLayer *OGRMSSQLSpatialDataSource::GetLayerByName( const char* pszLayerName )
       pszSchemaName = CPLStrdup("dbo");
       pszTableName = CPLStrdup( pszLayerName );
     }
-    
+
     for( int iLayer = 0; iLayer < nLayers; iLayer++ )
     {
-        if( EQUAL(pszTableName,papoLayers[iLayer]->GetTableName()) && 
+        if( EQUAL(pszTableName,papoLayers[iLayer]->GetTableName()) &&
             EQUAL(pszSchemaName,papoLayers[iLayer]->GetSchemaName()) )
         {
             CPLFree( pszSchemaName );
@@ -159,7 +170,7 @@ OGRLayer *OGRMSSQLSpatialDataSource::GetLayerByName( const char* pszLayerName )
 /*                            DeleteLayer()                             */
 /************************************************************************/
 
-int OGRMSSQLSpatialDataSource::DeleteLayer( int iLayer )
+OGRErr OGRMSSQLSpatialDataSource::DeleteLayer( int iLayer )
 
 {
     if( iLayer < 0 || iLayer >= nLayers )
@@ -174,7 +185,7 @@ int OGRMSSQLSpatialDataSource::DeleteLayer( int iLayer )
 
     CPLODBCStatement oStmt( &oSession );
     if (bUseGeometryColumns)
-        oStmt.Appendf( "DELETE FROM geometry_columns WHERE f_table_schema = '%s' AND f_table_name = '%s'\n", 
+        oStmt.Appendf( "DELETE FROM geometry_columns WHERE f_table_schema = '%s' AND f_table_name = '%s'\n",
             pszSchemaName, pszTableName );
     oStmt.Appendf("DROP TABLE [%s].[%s]", pszSchemaName, pszTableName );
 
@@ -197,7 +208,7 @@ int OGRMSSQLSpatialDataSource::DeleteLayer( int iLayer )
     int bInTransaction = oSession.IsInTransaction();
     if (!bInTransaction)
         oSession.BeginTransaction();
-    
+
     if( !oStmt.ExecuteSQL() )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -238,7 +249,7 @@ OGRLayer * OGRMSSQLSpatialDataSource::ICreateLayer( const char * pszLayerName,
 
     if( CSLFetchNameValue( papszOptions, "DIM") != NULL )
         nCoordDimension = atoi(CSLFetchNameValue( papszOptions, "DIM"));
-        
+
     /* MSSQL Schema handling:
        Extract schema name from input layer name or passed with -lco SCHEMA.
        Set layer name to "schema.table" or to "table" if schema is not
@@ -247,11 +258,12 @@ OGRLayer * OGRMSSQLSpatialDataSource::ICreateLayer( const char * pszLayerName,
     const char* pszDotPos = strstr(pszLayerName,".");
     if ( pszDotPos != NULL )
     {
-      int length = pszDotPos - pszLayerName;
+      int length = static_cast<int>(pszDotPos - pszLayerName);
       pszSchemaName = (char*)CPLMalloc(length+1);
+      CPLAssert(pszSchemaName != NULL); /* to make Coverity happy and not believe a REVERSE_INULL is possible */
       strncpy(pszSchemaName, pszLayerName, length);
       pszSchemaName[length] = '\0';
-      
+
       if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) )
           pszTableName = LaunderName( pszDotPos + 1 ); //skip "."
       else
@@ -283,20 +295,20 @@ OGRLayer * OGRMSSQLSpatialDataSource::ICreateLayer( const char * pszLayerName,
 
     for( iLayer = 0; iLayer < nLayers; iLayer++ )
     {
-        if( EQUAL(pszTableName,papoLayers[iLayer]->GetTableName()) && 
+        if( EQUAL(pszTableName,papoLayers[iLayer]->GetTableName()) &&
             EQUAL(pszSchemaName,papoLayers[iLayer]->GetSchemaName()) )
         {
             if( CSLFetchNameValue( papszOptions, "OVERWRITE" ) != NULL
                 && !EQUAL(CSLFetchNameValue(papszOptions,"OVERWRITE"),"NO") )
             {
-                if (!pszSchemaName)
-                    pszSchemaName = CPLStrdup(papoLayers[iLayer]->GetSchemaName());
+                CPLFree(pszSchemaName);
+                pszSchemaName = CPLStrdup(papoLayers[iLayer]->GetSchemaName());
 
                 DeleteLayer( iLayer );
             }
             else
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "Layer %s already exists, CreateLayer failed.\n"
                           "Use the layer creation option OVERWRITE=YES to "
                           "replace it.",
@@ -318,12 +330,12 @@ OGRLayer * OGRMSSQLSpatialDataSource::ICreateLayer( const char * pszLayerName,
 
         if( !pszGeomType )
             pszGeomType = "geometry";
-        
+
         if( !EQUAL(pszGeomType, "geometry")
             && !EQUAL(pszGeomType, "geography"))
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "FORMAT=%s not recognised or supported.", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "FORMAT=%s not recognised or supported.",
                       pszGeomType );
 
             CPLFree( pszSchemaName );
@@ -373,12 +385,12 @@ OGRLayer * OGRMSSQLSpatialDataSource::ICreateLayer( const char * pszLayerName,
     if( eType != wkbNone && bUseGeometryColumns)
     {
         const char *pszGeometryType = OGRToOGCGeomType(eType);
-      
+
         oStmt.Appendf( "DELETE FROM geometry_columns WHERE f_table_schema = '%s' "
             "AND f_table_name = '%s'\n", pszSchemaName, pszTableName );
-    
+
         oStmt.Appendf("INSERT INTO [geometry_columns] ([f_table_catalog], [f_table_schema] ,[f_table_name], "
-            "[f_geometry_column],[coord_dimension],[srid],[geometry_type]) VALUES ('%s', '%s', '%s', '%s', %d, %d, '%s')\n", 
+            "[f_geometry_column],[coord_dimension],[srid],[geometry_type]) VALUES ('%s', '%s', '%s', '%s', %d, %d, '%s')\n",
             pszCatalog, pszSchemaName, pszTableName, pszGeomColumn, nCoordDimension, nSRSId, pszGeometryType );
     }
 
@@ -398,8 +410,8 @@ OGRLayer * OGRMSSQLSpatialDataSource::ICreateLayer( const char * pszLayerName,
     int bFID64 = CSLFetchBoolean(papszOptions, "FID64", FALSE);
  	const char* pszFIDType = bFID64 ? "bigint": "int";
 
-    if( eType == wkbNone ) 
-    { 
+    if( eType == wkbNone )
+    {
         oStmt.Appendf("CREATE TABLE [%s].[%s] ([%s] [%s] IDENTITY(1,1) NOT NULL, "
             "CONSTRAINT [PK_%s] PRIMARY KEY CLUSTERED ([%s] ASC))",
             pszSchemaName, pszTableName, pszFIDColumnName, pszFIDType, pszTableName, pszFIDColumnName);
@@ -417,11 +429,11 @@ OGRLayer * OGRMSSQLSpatialDataSource::ICreateLayer( const char * pszLayerName,
     int bInTransaction = oSession.IsInTransaction();
     if (!bInTransaction)
         oSession.BeginTransaction();
-        
+
     if( !oStmt.ExecuteSQL() )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                    "Error creating layer: %s", GetSession()->GetLastError() );
+                    "Error creating layer: %s When using the overwrite option and the layer doesn't contain geometry column, you might require to use the MSSQLSPATIAL_LIST_ALL_TABLES config option to get the previous layer deleted before creating the new one.", GetSession()->GetLastError() );
 
         if (!bInTransaction)
             oSession.RollbackTransaction();
@@ -447,16 +459,22 @@ OGRLayer * OGRMSSQLSpatialDataSource::ICreateLayer( const char * pszLayerName,
     poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) );
     poLayer->SetPrecisionFlag( CSLFetchBoolean(papszOptions,"PRECISION",TRUE));
 
+    if( bUseCopy )
+        poLayer->SetUseCopy(nBCPSize);
+
     const char *pszSI = CSLFetchNameValue( papszOptions, "SPATIAL_INDEX" );
-    int bCreateSpatialIndex = ( pszSI == NULL || CSLTestBoolean(pszSI) );
+    int bCreateSpatialIndex = ( pszSI == NULL || CPLTestBool(pszSI) );
+    if (pszGeomColumn == NULL)
+        bCreateSpatialIndex = FALSE;
+
     poLayer->SetSpatialIndexFlag( bCreateSpatialIndex );
 
     const char *pszUploadGeometryFormat = CSLFetchNameValue( papszOptions, "UPLOAD_GEOM_FORMAT" );
     if (pszUploadGeometryFormat)
     {
-        if (EQUALN(pszUploadGeometryFormat,"wkb",5))
+        if (STARTS_WITH_CI(pszUploadGeometryFormat,"wkb"))
             poLayer->SetUploadGeometryFormat(MSSQLGEOMETRY_WKB);
-        else if (EQUALN(pszUploadGeometryFormat, "wkt",3))
+        else if (STARTS_WITH_CI(pszUploadGeometryFormat, "wkt"))
             poLayer->SetUploadGeometryFormat(MSSQLGEOMETRY_WKT);
     }
 
@@ -469,8 +487,8 @@ OGRLayer * OGRMSSQLSpatialDataSource::ICreateLayer( const char * pszLayerName,
 
     if( bFID64 )
         poLayer->SetMetadataItem(OLMD_FID64, "YES");
-    
-    if (poLayer->Initialize(pszSchemaName, pszTableName, pszGeomColumn, nCoordDimension, nSRSId, pszWKT, eType) == OGRERR_FAILURE)
+
+    if (poLayer->Initialize(pszSchemaName, pszTableName, pszGeomColumn, nCoordDimension, nSRSId, pszWKT, eType) == CE_Failure)
     {
         CPLFree( pszSchemaName );
         CPLFree( pszTableName );
@@ -514,13 +532,16 @@ int OGRMSSQLSpatialDataSource::OpenTable( const char *pszSchemaName, const char
         return FALSE;
     }
 
+    if (bUseCopy)
+        poLayer->SetUseCopy(nBCPSize);
+
 /* -------------------------------------------------------------------- */
 /*      Add layer to data source layer list.                            */
 /* -------------------------------------------------------------------- */
     papoLayers = (OGRMSSQLSpatialTableLayer **)
         CPLRealloc( papoLayers,  sizeof(OGRMSSQLSpatialTableLayer *) * (nLayers+1) );
     papoLayers[nLayers++] = poLayer;
-    
+
     return TRUE;
 }
 
@@ -529,9 +550,9 @@ int OGRMSSQLSpatialDataSource::OpenTable( const char *pszSchemaName, const char
 /*                       GetLayerCount()                                */
 /************************************************************************/
 
-int OGRMSSQLSpatialDataSource::GetLayerCount() 
-{ 
-    return nLayers; 
+int OGRMSSQLSpatialDataSource::GetLayerCount()
+{
+    return nLayers;
 }
 
 /************************************************************************/
@@ -540,13 +561,12 @@ int OGRMSSQLSpatialDataSource::GetLayerCount()
 
 int OGRMSSQLSpatialDataSource::ParseValue(char** pszValue, char* pszSource, const char* pszKey, int nStart, int nNext, int nTerm, int bRemove)
 {
-    int nLen = strlen(pszKey);
-    if ((*pszValue) == NULL && nStart + nLen < nNext && 
+    int nLen = static_cast<int>(strlen(pszKey));
+    if ((*pszValue) == NULL && nStart + nLen < nNext &&
             EQUALN(pszSource + nStart, pszKey, nLen))
     {
         *pszValue = (char*)CPLMalloc( sizeof(char) * (nNext - nStart - nLen + 1) );
-        if (*pszValue)
-            strncpy(*pszValue, pszSource + nStart + nLen, nNext - nStart - nLen);
+        strncpy(*pszValue, pszSource + nStart + nLen, nNext - nStart - nLen);
         (*pszValue)[nNext - nStart - nLen] = 0;
 
         if (bRemove)
@@ -573,7 +593,7 @@ int OGRMSSQLSpatialDataSource::Open( const char * pszNewName, int bUpdate,
 {
     CPLAssert( nLayers == 0 );
 
-    if( !EQUALN(pszNewName,"MSSQL:",6) )
+    if( !STARTS_WITH_CI(pszNewName, "MSSQL:") )
     {
         if( !bTestOpen )
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -588,7 +608,7 @@ int OGRMSSQLSpatialDataSource::Open( const char * pszNewName, int bUpdate,
     char* pszConnectionName = CPLStrdup(pszNewName + 6);
     char* pszDriver = NULL;
     int nCurrent, nNext, nTerm;
-    nCurrent = nNext = nTerm = strlen(pszConnectionName);
+    nCurrent = nNext = nTerm = static_cast<int>(strlen(pszConnectionName));
 
     while (nCurrent > 0)
     {
@@ -599,35 +619,35 @@ int OGRMSSQLSpatialDataSource::Open( const char * pszNewName, int bUpdate,
             continue;
         }
 
-        if (ParseValue(&pszCatalog, pszConnectionName, "database=", 
+        if (ParseValue(&pszCatalog, pszConnectionName, "database=",
             nCurrent, nNext, nTerm, FALSE))
             continue;
 
-        if (ParseValue(&pszTableSpec, pszConnectionName, "tables=", 
+        if (ParseValue(&pszTableSpec, pszConnectionName, "tables=",
             nCurrent, nNext, nTerm, TRUE))
             continue;
 
-        if (ParseValue(&pszDriver, pszConnectionName, "driver=", 
+        if (ParseValue(&pszDriver, pszConnectionName, "driver=",
             nCurrent, nNext, nTerm, FALSE))
             continue;
 
-        if (ParseValue(&pszGeometryFormat, pszConnectionName, 
+        if (ParseValue(&pszGeometryFormat, pszConnectionName,
             "geometryformat=", nCurrent, nNext, nTerm, TRUE))
         {
-            if (EQUALN(pszGeometryFormat,"wkbzm",5))
+            if (STARTS_WITH_CI(pszGeometryFormat, "wkbzm"))
                 nGeometryFormat = MSSQLGEOMETRY_WKBZM;
-            else if (EQUALN(pszGeometryFormat, "wkb",3))
+            else if (STARTS_WITH_CI(pszGeometryFormat, "wkb"))
                 nGeometryFormat = MSSQLGEOMETRY_WKB;
-            else if (EQUALN(pszGeometryFormat,"wkt",3))
+            else if (STARTS_WITH_CI(pszGeometryFormat, "wkt"))
                 nGeometryFormat = MSSQLGEOMETRY_WKT;
-            else if (EQUALN(pszGeometryFormat,"native",6))
+            else if (STARTS_WITH_CI(pszGeometryFormat, "native"))
                 nGeometryFormat = MSSQLGEOMETRY_NATIVE;
             else
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
                     "Invalid geometry type specified: %s,"
                       " MSSQL:*\n", pszGeometryFormat );
-                
+
                 CPLFree(pszTableSpec);
                 CPLFree(pszGeometryFormat);
                 CPLFree(pszConnectionName);
@@ -646,14 +666,14 @@ int OGRMSSQLSpatialDataSource::Open( const char * pszNewName, int bUpdate,
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                       "'%s' does not contain the 'database' portion\n", pszNewName );
-        
+
         CPLFree(pszTableSpec);
         CPLFree(pszGeometryFormat);
         CPLFree(pszConnectionName);
         CPLFree(pszDriver);
         return FALSE;
     }
-    
+
     pszName = CPLStrdup(pszNewName);
 
     char  **papszTableNames=NULL;
@@ -688,7 +708,7 @@ int OGRMSSQLSpatialDataSource::Open( const char * pszNewName, int bUpdate,
                 {
                     *pos = '\0';
                     pszGeomColumnName = pos+1;
-                    int len = strlen(pszGeomColumnName);
+                    int len = static_cast<int>(strlen(pszGeomColumnName));
                     if (len > 0)
                         pszGeomColumnName[len - 1] = '\0';
                 }
@@ -698,7 +718,7 @@ int OGRMSSQLSpatialDataSource::Open( const char * pszNewName, int bUpdate,
 
             if( CSLCount( papszQualifiedParts ) == 2 )
             {
-                papszSchemaNames = CSLAddString( papszSchemaNames, 
+                papszSchemaNames = CSLAddString( papszSchemaNames,
                                                 papszQualifiedParts[0] );
                 papszTableNames = CSLAddString( papszTableNames,
                                                 papszQualifiedParts[1] );
@@ -718,29 +738,58 @@ int OGRMSSQLSpatialDataSource::Open( const char * pszNewName, int bUpdate,
 
     CPLFree(pszTableSpec);
 
-    /* Initialize the SQL Server connection. */
-    int nResult;
-    if ( pszDriver != NULL )
-    {
-        /* driver has been specified */
-        CPLDebug( "OGR_MSSQLSpatial", "EstablishSession(Connection:\"%s\")", pszConnectionName);
-        nResult = oSession.EstablishSession( pszConnectionName, "", "" );
-    }
-    else
+    if ( pszDriver == NULL )
     {
-        /* no driver has been specified, defautls to SQL Server */
-        CPLDebug( "OGR_MSSQLSpatial", "EstablishSession(Connection:\"%s\")", pszConnectionName);
-        nResult = oSession.EstablishSession( CPLSPrintf("DRIVER=SQL Server;%s", pszConnectionName), "", "" );
+        char* pszConnectionName2 = pszConnectionName;
+#if SQLNCLI_VERSION == 11
+        pszDriver = CPLStrdup("{SQL Server Native Client 11.0}");
+#elif SQLNCLI_VERSION == 10
+        pszDriver = CPLStrdup("{SQL Server Native Client 10.0}");
+#else
+        pszDriver = CPLStrdup("{SQL Server}");
+#endif
+        pszConnectionName = CPLStrdup(CPLSPrintf("DRIVER=%s;%s", pszDriver, pszConnectionName2));
+        CPLFree(pszConnectionName2);
     }
 
     CPLFree(pszDriver);
 
-    if( !nResult )
+    /* Initialize the SQL Server connection. */
+    if( !oSession.EstablishSession( pszConnectionName, "", "" ) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Unable to initialize connection to the server for %s,\n"
-                  "%s", pszNewName, oSession.GetLastError() );
-        
+        /* Get a list of the available drivers */
+        HENV hEnv;
+        if ( SQL_SUCCEEDED(SQLAllocEnv( &hEnv ) ) )
+        {
+            CPLString osDriverList;
+            SQLUSMALLINT direction = SQL_FETCH_FIRST;
+            SQLSMALLINT driver_ret;
+            SQLSMALLINT attr_ret;
+            SQLCHAR attr[256];
+            SQLCHAR driver[256];
+            while(SQL_SUCCEEDED(SQLDrivers(hEnv, direction, 
+                driver, sizeof(driver), &driver_ret, attr, sizeof(attr), &attr_ret))) 
+            {
+	            direction = SQL_FETCH_NEXT;
+                osDriverList += CPLSPrintf("%s\n", driver);
+	        }
+
+            CPLError( CE_Failure, CPLE_AppDefined, 
+                "Unable to initialize connection to the server for %s,\n"
+                "%s\n"
+                "Try specifying the driver in the connection string from the list of available drivers:\n"
+                "%s", pszNewName, oSession.GetLastError(), osDriverList.c_str() );
+        }
+        else
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, 
+                "Unable to initialize connection to the server for %s,\n"
+                "%s\n", pszNewName, oSession.GetLastError() );
+        }
+
+        if( hEnv != NULL )
+            SQLFreeEnv( hEnv );
+
         CSLDestroy( papszTableNames );
         CSLDestroy( papszSchemaNames );
         CSLDestroy( papszGeomColumnNames );
@@ -757,12 +806,12 @@ int OGRMSSQLSpatialDataSource::Open( const char * pszNewName, int bUpdate,
     /* read metadata for the specified tables */
     if (papszTableNames != NULL && bUseGeometryColumns)
     {
-        for( int iTable = 0; 
-            papszTableNames != NULL && papszTableNames[iTable] != NULL; 
+        for( int iTable = 0;
+            papszTableNames != NULL && papszTableNames[iTable] != NULL;
             iTable++ )
-        {        
+        {
             CPLODBCStatement oStmt( &oSession );
-            
+
             /* Use join to make sure the existence of the referred column/table */
             oStmt.Appendf( "SELECT f_geometry_column, coord_dimension, g.srid, srtext, geometry_type FROM dbo.geometry_columns g JOIN INFORMATION_SCHEMA.COLUMNS ON f_table_schema = TABLE_SCHEMA and f_table_name = TABLE_NAME and f_geometry_column = COLUMN_NAME left outer join dbo.spatial_ref_sys s on g.srid = s.srid WHERE f_table_schema = '%s' AND f_table_name = '%s'", papszSchemaNames[iTable], papszTableNames[iTable]);
 
@@ -778,13 +827,13 @@ int OGRMSSQLSpatialDataSource::Open( const char * pszNewName, int bUpdate,
                         papszGeomColumnNames[iTable] = CPLStrdup( oStmt.GetColData(0) );
                     }
 
-                    papszCoordDimensions = 
+                    papszCoordDimensions =
                             CSLAddString( papszCoordDimensions, oStmt.GetColData(1, "2") );
-                    papszSRIds = 
+                    papszSRIds =
                             CSLAddString( papszSRIds, oStmt.GetColData(2, "0") );
-                    papszSRTexts = 
+                    papszSRTexts =
                         CSLAddString( papszSRTexts, oStmt.GetColData(3, "") );
-                    papszTypes = 
+                    papszTypes =
                             CSLAddString( papszTypes, oStmt.GetColData(4, "GEOMETRY") );
                 }
             }
@@ -796,32 +845,32 @@ int OGRMSSQLSpatialDataSource::Open( const char * pszNewName, int bUpdate,
         }
     }
 
-    /* if requesting all user database table then this takes priority */ 
- 	if (papszTableNames == NULL && bListAllTables) 
- 	{ 
- 	    CPLODBCStatement oStmt( &oSession ); 
- 	         
- 	    oStmt.Append( "select sys.schemas.name, sys.schemas.name + '.' + sys.objects.name, sys.columns.name from sys.columns join sys.types on sys.columns.system_type_id = sys.types.system_type_id and sys.columns.user_type_id = sys.types.user_type_id join sys.objects on sys.objects.object_id = sys.columns.object_id join sys.schemas on sys.objects.schema_id = sys.schemas.schema_id where (sys.types.name = 'geometry' or sys.types.name = 'geography') and (sys.objects.type = 'U' or sys.objects. [...]
- 	
- 	    if( oStmt.ExecuteSQL() ) 
- 	    { 
- 	        while( oStmt.Fetch() ) 
- 	        { 
- 	            papszSchemaNames =  
- 	                    CSLAddString( papszSchemaNames, oStmt.GetColData(0) ); 
- 	            papszTableNames =  
- 	                    CSLAddString( papszTableNames, oStmt.GetColData(1) ); 
- 	            papszGeomColumnNames =  
- 	                    CSLAddString( papszGeomColumnNames, oStmt.GetColData(2) ); 
- 	        } 
- 	    } 
- 	} 
+    /* if requesting all user database table then this takes priority */
+ 	if (papszTableNames == NULL && bListAllTables)
+ 	{
+ 	    CPLODBCStatement oStmt( &oSession );
+
+ 	    oStmt.Append( "select sys.schemas.name, sys.schemas.name + '.' + sys.objects.name, sys.columns.name from sys.columns join sys.types on sys.columns.system_type_id = sys.types.system_type_id and sys.columns.user_type_id = sys.types.user_type_id join sys.objects on sys.objects.object_id = sys.columns.object_id join sys.schemas on sys.objects.schema_id = sys.schemas.schema_id where (sys.types.name = 'geometry' or sys.types.name = 'geography') and (sys.objects.type = 'U' or sys.objects. [...]
+
+ 	    if( oStmt.ExecuteSQL() )
+ 	    {
+ 	        while( oStmt.Fetch() )
+ 	        {
+ 	            papszSchemaNames =
+ 	                    CSLAddString( papszSchemaNames, oStmt.GetColData(0) );
+ 	            papszTableNames =
+ 	                    CSLAddString( papszTableNames, oStmt.GetColData(1) );
+ 	            papszGeomColumnNames =
+ 	                    CSLAddString( papszGeomColumnNames, oStmt.GetColData(2) );
+ 	        }
+ 	    }
+ 	}
 
     /* Determine the available tables if not specified. */
     if (papszTableNames == NULL && bUseGeometryColumns)
     {
         CPLODBCStatement oStmt( &oSession );
-        
+
         /* Use join to make sure the existence of the referred column/table */
         oStmt.Append( "SELECT f_table_schema, f_table_name, f_geometry_column, coord_dimension, g.srid, srtext, geometry_type FROM dbo.geometry_columns g JOIN INFORMATION_SCHEMA.COLUMNS ON f_table_schema = TABLE_SCHEMA and f_table_name = TABLE_NAME and f_geometry_column = COLUMN_NAME left outer join dbo.spatial_ref_sys s on g.srid = s.srid");
 
@@ -829,19 +878,19 @@ int OGRMSSQLSpatialDataSource::Open( const char * pszNewName, int bUpdate,
         {
             while( oStmt.Fetch() )
             {
-                papszSchemaNames = 
+                papszSchemaNames =
                         CSLAddString( papszSchemaNames, oStmt.GetColData(0, "dbo") );
-                papszTableNames = 
+                papszTableNames =
                         CSLAddString( papszTableNames, oStmt.GetColData(1) );
-                papszGeomColumnNames = 
+                papszGeomColumnNames =
                         CSLAddString( papszGeomColumnNames, oStmt.GetColData(2) );
-                papszCoordDimensions = 
+                papszCoordDimensions =
                         CSLAddString( papszCoordDimensions, oStmt.GetColData(3, "2") );
-                papszSRIds = 
+                papszSRIds =
                         CSLAddString( papszSRIds, oStmt.GetColData(4, "0") );
-                papszSRTexts = 
+                papszSRTexts =
                     CSLAddString( papszSRTexts, oStmt.GetColData(5, "") );
-                papszTypes = 
+                papszTypes =
                         CSLAddString( papszTypes, oStmt.GetColData(6, "GEOMETRY") );
             }
         }
@@ -856,18 +905,18 @@ int OGRMSSQLSpatialDataSource::Open( const char * pszNewName, int bUpdate,
     if (papszTableNames == NULL)
     {
         CPLODBCStatement oStmt( &oSession );
-            
+
         oStmt.Append( "SELECT sys.schemas.name, sys.schemas.name + '.' + sys.objects.name, sys.columns.name from sys.columns join sys.types on sys.columns.system_type_id = sys.types.system_type_id and sys.columns.user_type_id = sys.types.user_type_id join sys.objects on sys.objects.object_id = sys.columns.object_id join sys.schemas on sys.objects.schema_id = sys.schemas.schema_id where (sys.types.name = 'geometry' or sys.types.name = 'geography') and (sys.objects.type = 'U' or sys.object [...]
 
         if( oStmt.ExecuteSQL() )
         {
             while( oStmt.Fetch() )
             {
-                papszSchemaNames = 
+                papszSchemaNames =
                         CSLAddString( papszSchemaNames, oStmt.GetColData(0) );
-                papszTableNames = 
+                papszTableNames =
                         CSLAddString( papszTableNames, oStmt.GetColData(1) );
-                papszGeomColumnNames = 
+                papszGeomColumnNames =
                         CSLAddString( papszGeomColumnNames, oStmt.GetColData(2) );
             }
         }
@@ -875,9 +924,9 @@ int OGRMSSQLSpatialDataSource::Open( const char * pszNewName, int bUpdate,
 
     int nSRId, nCoordDimension;
     OGRwkbGeometryType eType;
-        
-    for( int iTable = 0; 
-         papszTableNames != NULL && papszTableNames[iTable] != NULL; 
+
+    for( int iTable = 0;
+         papszTableNames != NULL && papszTableNames[iTable] != NULL;
          iTable++ )
     {
         if (papszSRIds != NULL)
@@ -896,10 +945,10 @@ int OGRMSSQLSpatialDataSource::Open( const char * pszNewName, int bUpdate,
             eType = wkbUnknown;
 
         if( strlen(papszGeomColumnNames[iTable]) > 0 )
-            OpenTable( papszSchemaNames[iTable], papszTableNames[iTable], papszGeomColumnNames[iTable], 
+            OpenTable( papszSchemaNames[iTable], papszTableNames[iTable], papszGeomColumnNames[iTable],
                     nCoordDimension, nSRId, papszSRTexts? papszSRTexts[iTable] : NULL, eType, bUpdate );
         else
-            OpenTable( papszSchemaNames[iTable], papszTableNames[iTable], NULL, 
+            OpenTable( papszSchemaNames[iTable], papszTableNames[iTable], NULL,
                     nCoordDimension, nSRId, papszSRTexts? papszSRTexts[iTable] : NULL, wkbNone, bUpdate );
     }
 
@@ -912,8 +961,10 @@ int OGRMSSQLSpatialDataSource::Open( const char * pszNewName, int bUpdate,
     CSLDestroy( papszTypes );
 
     CPLFree(pszGeometryFormat);
-    CPLFree(pszConnectionName);
-    
+
+    CPLFree(pszConnection);
+    pszConnection = pszConnectionName;
+
     bDSUpdate = bUpdate;
 
     return TRUE;
@@ -932,22 +983,22 @@ OGRLayer * OGRMSSQLSpatialDataSource::ExecuteSQL( const char *pszSQLCommand,
 /*      Use generic implementation for recognized dialects              */
 /* -------------------------------------------------------------------- */
     if( IsGenericSQLDialect(pszDialect) )
-        return OGRDataSource::ExecuteSQL( pszSQLCommand, 
-                                          poSpatialFilter, 
+        return OGRDataSource::ExecuteSQL( pszSQLCommand,
+                                          poSpatialFilter,
                                           pszDialect );
 
 /* -------------------------------------------------------------------- */
 /*      Special case DELLAYER: command.                                 */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszSQLCommand,"DELLAYER:",9) )
+    if( STARTS_WITH_CI(pszSQLCommand, "DELLAYER:") )
     {
         const char *pszLayerName = pszSQLCommand + 9;
 
         while( *pszLayerName == ' ' )
             pszLayerName++;
-        
+
         OGRLayer* poLayer = GetLayerByName(pszLayerName);
-        
+
         for( int iLayer = 0; iLayer < nLayers; iLayer++ )
         {
             if( papoLayers[iLayer] == poLayer )
@@ -961,7 +1012,7 @@ OGRLayer * OGRMSSQLSpatialDataSource::ExecuteSQL( const char *pszSQLCommand,
 
     CPLDebug( "MSSQLSpatial", "ExecuteSQL(%s) called.", pszSQLCommand );
 
-    if( EQUALN(pszSQLCommand, "DROP SPATIAL INDEX ON ", 22) )
+    if( STARTS_WITH_CI(pszSQLCommand, "DROP SPATIAL INDEX ON ") )
     {
         /* Handle command to drop a spatial index. */
         OGRMSSQLSpatialTableLayer  *poLayer = new OGRMSSQLSpatialTableLayer( this );
@@ -970,15 +1021,15 @@ OGRLayer * OGRMSSQLSpatialDataSource::ExecuteSQL( const char *pszSQLCommand,
         {
             if( poLayer->Initialize( "dbo", pszSQLCommand + 22, NULL, 0, 0, NULL, wkbUnknown ) != CE_None )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Failed to initialize layer '%s'", pszSQLCommand + 22 );   
+                CPLError( CE_Failure, CPLE_AppDefined,
+                      "Failed to initialize layer '%s'", pszSQLCommand + 22 );
             }
             poLayer->DropSpatialIndex();
             delete poLayer;
         }
         return NULL;
     }
-    else if( EQUALN(pszSQLCommand, "CREATE SPATIAL INDEX ON ", 24) )
+    else if( STARTS_WITH_CI(pszSQLCommand, "CREATE SPATIAL INDEX ON ") )
     {
         /* Handle command to create a spatial index. */
         OGRMSSQLSpatialTableLayer  *poLayer = new OGRMSSQLSpatialTableLayer( this );
@@ -987,22 +1038,22 @@ OGRLayer * OGRMSSQLSpatialDataSource::ExecuteSQL( const char *pszSQLCommand,
         {
             if( poLayer->Initialize( "dbo", pszSQLCommand + 24, NULL, 0, 0, NULL, wkbUnknown ) != CE_None )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Failed to initialize layer '%s'", pszSQLCommand + 24 );    
+                CPLError( CE_Failure, CPLE_AppDefined,
+                      "Failed to initialize layer '%s'", pszSQLCommand + 24 );
             }
             poLayer->CreateSpatialIndex();
             delete poLayer;
         }
         return NULL;
     }
-    
+
     /* Execute the command natively */
     CPLODBCStatement *poStmt = new CPLODBCStatement( &oSession );
     poStmt->Append( pszSQLCommand );
 
     if( !poStmt->ExecuteSQL() )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", oSession.GetLastError() );
         delete poStmt;
         return NULL;
@@ -1022,9 +1073,9 @@ OGRLayer * OGRMSSQLSpatialDataSource::ExecuteSQL( const char *pszSQLCommand,
 /*      Create a results layer.  It will take ownership of the          */
 /*      statement.                                                      */
 /* -------------------------------------------------------------------- */
-    
+
     OGRMSSQLSpatialSelectLayer *poLayer = NULL;
-        
+
     poLayer = new OGRMSSQLSpatialSelectLayer( this, poStmt );
 
     if( poSpatialFilter != NULL )
@@ -1094,12 +1145,12 @@ OGRErr OGRMSSQLSpatialDataSource::InitializeMetadataTables()
         int bInTransaction = oSession.IsInTransaction();
         if (!bInTransaction)
             oSession.BeginTransaction();
-    
+
         if( !oStmt.ExecuteSQL() )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                         "Error initializing the metadata tables : %s", GetSession()->GetLastError() );
-            
+
             if (!bInTransaction)
                 oSession.RollbackTransaction();
 
@@ -1159,7 +1210,7 @@ OGRSpatialReference *OGRMSSQLSpatialDataSource::FetchSRS( int nId )
                 {
                     delete poSRS;
                     poSRS = NULL;
-                }    
+                }
             }
         }
     }
@@ -1174,7 +1225,7 @@ OGRSpatialReference *OGRMSSQLSpatialDataSource::FetchSRS( int nId )
         {
             delete poSRS;
             poSRS = NULL;
-        } 
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -1316,7 +1367,7 @@ int OGRMSSQLSpatialDataSource::FetchSRSId( OGRSpatialReference * poSRS)
     nSRSId = nAuthorityCode;
 
     oStmt.Clear();
-    
+
     int bInTransaction = oSession.IsInTransaction();
     if (!bInTransaction)
         oSession.BeginTransaction();
@@ -1333,7 +1384,7 @@ int OGRMSSQLSpatialDataSource::FetchSRSId( OGRSpatialReference * poSRS)
 /* -------------------------------------------------------------------- */
 /*      Get the current maximum srid in the srs table.                  */
 /* -------------------------------------------------------------------- */
-    
+
     if (nSRSId == 0)
     {
         oStmt.Clear();
@@ -1354,7 +1405,7 @@ int OGRMSSQLSpatialDataSource::FetchSRSId( OGRSpatialReference * poSRS)
         CPLFree(pszWKT);
         return 0;
     }
-    
+
     oStmt.Clear();
     if( nAuthorityCode > 0 )
     {
@@ -1395,7 +1446,7 @@ int OGRMSSQLSpatialDataSource::FetchSRSId( OGRSpatialReference * poSRS)
 
     return nSRSId;
 }
-	
+
 /************************************************************************/
 /*                         StartTransaction()                           */
 /*                                                                      */
@@ -1410,7 +1461,7 @@ OGRErr OGRMSSQLSpatialDataSource::StartTransaction(CPL_UNUSED int bForce)
                     "Failed to start transaction: %s", oSession.GetLastError() );
         return OGRERR_FAILURE;
     }
-    
+
     return OGRERR_NONE;
 }
 
@@ -1441,7 +1492,7 @@ OGRErr OGRMSSQLSpatialDataSource::CommitTransaction()
         if( papoLayers[iLayer]->GetLayerStatus() == MSSQLLAYERSTATUS_INITIAL )
             papoLayers[iLayer]->SetLayerStatus(MSSQLLAYERSTATUS_CREATED);
     }
-    
+
     return OGRERR_NONE;
 }
 
@@ -1459,13 +1510,13 @@ OGRErr OGRMSSQLSpatialDataSource::RollbackTransaction()
         if( papoLayers[iLayer]->GetLayerStatus() == MSSQLLAYERSTATUS_INITIAL )
             papoLayers[iLayer]->SetLayerStatus(MSSQLLAYERSTATUS_DISABLED);
     }
-    
+
     if (!oSession.RollbackTransaction())
      {
         CPLError( CE_Failure, CPLE_AppDefined,
                     "Failed to roll back transaction: %s", oSession.GetLastError() );
         return OGRERR_FAILURE;
     }
-    
+
     return OGRERR_NONE;
 }
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdriver.cpp b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdriver.cpp
index 81a129d..572f2bf 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdriver.cpp
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmssqlspatialdriver.cpp 29025 2015-04-26 11:50:20Z tamas $
+ * $Id: ogrmssqlspatialdriver.cpp 32293 2015-12-20 01:21:31Z rouault $
  *
  * Project:  MSSQL Spatial driver
  * Purpose:  Definition of classes for OGR MSSQL Spatial driver.
@@ -30,7 +30,7 @@
 #include "ogr_mssqlspatial.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrmssqlspatialdriver.cpp 29025 2015-04-26 11:50:20Z tamas $");
+CPL_CVSID("$Id: ogrmssqlspatialdriver.cpp 32293 2015-12-20 01:21:31Z rouault $");
 
 /************************************************************************/
 /*                           ~OGRMSSQLSpatialDriver()                   */
@@ -60,7 +60,7 @@ OGRDataSource *OGRMSSQLSpatialDriver::Open( const char * pszFilename, int bUpdat
 {
     OGRMSSQLSpatialDataSource     *poDS;
 
-    if( !EQUALN(pszFilename,"MSSQL:",6) )
+    if( !STARTS_WITH_CI(pszFilename, "MSSQL:") )
         return NULL;
 
     poDS = new OGRMSSQLSpatialDataSource();
@@ -81,11 +81,10 @@ OGRDataSource *OGRMSSQLSpatialDriver::Open( const char * pszFilename, int bUpdat
 OGRDataSource *OGRMSSQLSpatialDriver::CreateDataSource( const char * pszName,
                                                         CPL_UNUSED char **papszOptions )
 {
-    OGRMSSQLSpatialDataSource   *poDS = new OGRMSSQLSpatialDataSource();
-
-    if( !EQUALN(pszName,"MSSQL:",6) )
+    if( !STARTS_WITH_CI(pszName, "MSSQL:") )
         return NULL;
 
+    OGRMSSQLSpatialDataSource   *poDS = new OGRMSSQLSpatialDataSource();
     if( !poDS->Open( pszName, TRUE, TRUE ) )
     {
         delete poDS;
@@ -121,12 +120,14 @@ void RegisterOGRMSSQLSpatial()
 {
     if (! GDAL_CHECK_VERSION("OGR/MSSQLSpatial driver"))
         return;
+
     OGRSFDriver* poDriver = new OGRMSSQLSpatialDriver;
+
     poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Microsoft SQL Server Spatial Database" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                "drv_mssqlspatial.html" );
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, "<CreationOptionList/>");
+                               "Microsoft SQL Server Spatial Database" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_mssqlspatial.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+                               "<CreationOptionList/>");
 
     poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
 "<LayerCreationOptionList>"
@@ -151,9 +152,12 @@ void RegisterOGRMSSQLSpatial()
 "  <Option name='GEOMETRY_NULLABLE' type='boolean' description='Whether the values of the geometry column can be NULL' default='YES'/>"
 "</LayerCreationOptionList>");
 
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES, "Integer Integer64 Real String Date Time DateTime Binary" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
+                               "Integer Integer64 Real String Date Time "
+                               "DateTime Binary" );
     poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_FIELDS, "YES" );
- 	poDriver->SetMetadataItem( GDAL_DCAP_DEFAULT_FIELDS, "YES" );
- 	poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_GEOMFIELDS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_DEFAULT_FIELDS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_GEOMFIELDS, "YES" );
+
     OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver(poDriver);
 }
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatiallayer.cpp b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatiallayer.cpp
index d6c7b89..5f1e6e8 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatiallayer.cpp
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatiallayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmssqlspatiallayer.cpp 31802 2015-11-27 20:47:36Z rouault $
+ * $Id: ogrmssqlspatiallayer.cpp 33807 2016-03-29 19:06:42Z tamas $
  *
  * Project:  MSSQL Spatial driver
  * Purpose:  Definition of classes for OGR MSSQL Spatial driver.
@@ -29,7 +29,7 @@
 
 #include "ogr_mssqlspatial.h"
 
-CPL_CVSID("$Id: ogrmssqlspatiallayer.cpp 31802 2015-11-27 20:47:36Z rouault $");
+CPL_CVSID("$Id: ogrmssqlspatiallayer.cpp 33807 2016-03-29 19:06:42Z tamas $");
 /************************************************************************/
 /*                        OGRMSSQLSpatialLayer()                        */
 /************************************************************************/
@@ -39,6 +39,7 @@ OGRMSSQLSpatialLayer::OGRMSSQLSpatialLayer()
 {
     poDS = NULL;
 
+    poFeatureDefn = NULL;
     nGeomColumnType = -1;
     pszGeomColumn = NULL;
     pszFIDColumn = NULL;
@@ -52,6 +53,10 @@ OGRMSSQLSpatialLayer::OGRMSSQLSpatialLayer()
     poSRS = NULL;
     nSRSId = -1; // we haven't even queried the database for it yet. 
     nLayerStatus = MSSQLLAYERSTATUS_ORIGINAL;
+
+    nGeomColumnIndex = -1;
+    nFIDColumnIndex = -1;
+    nRawColumns = 0;
 }
 
 /************************************************************************/
@@ -96,11 +101,11 @@ OGRMSSQLSpatialLayer::~OGRMSSQLSpatialLayer()
 /************************************************************************/
 
 CPLErr OGRMSSQLSpatialLayer::BuildFeatureDefn( const char *pszLayerName, 
-                                    CPLODBCStatement *poStmt )
+                                    CPLODBCStatement *poStmtIn )
 
 {
     poFeatureDefn = new OGRFeatureDefn( pszLayerName );
-    int    nRawColumns = poStmt->GetColCount();
+    nRawColumns = poStmtIn->GetColCount();
 
     poFeatureDefn->Reference();
 
@@ -112,39 +117,42 @@ CPLErr OGRMSSQLSpatialLayer::BuildFeatureDefn( const char *pszLayerName,
         if ( pszGeomColumn == NULL )
         {
             /* need to identify the geometry column */
-            if ( EQUAL(poStmt->GetColTypeName( iCol ), "geometry") )
+            if ( EQUAL(poStmtIn->GetColTypeName( iCol ), "geometry") )
             {
                 nGeomColumnType = MSSQLCOLTYPE_GEOMETRY;
-                pszGeomColumn = CPLStrdup( poStmt->GetColName(iCol) );
+                pszGeomColumn = CPLStrdup( poStmtIn->GetColName(iCol) );
                 if (poFeatureDefn->GetGeomFieldCount() == 1)
-                    poFeatureDefn->GetGeomFieldDefn(0)->SetNullable( poStmt->GetColNullable(iCol) );
+                    poFeatureDefn->GetGeomFieldDefn(0)->SetNullable( poStmtIn->GetColNullable(iCol) );
+                nGeomColumnIndex = iCol;
                 continue;
             }
-            else if ( EQUAL(poStmt->GetColTypeName( iCol ), "geography") )
+            else if ( EQUAL(poStmtIn->GetColTypeName( iCol ), "geography") )
             {
                 nGeomColumnType = MSSQLCOLTYPE_GEOGRAPHY;
-                pszGeomColumn = CPLStrdup( poStmt->GetColName(iCol) );
+                pszGeomColumn = CPLStrdup( poStmtIn->GetColName(iCol) );
                 if (poFeatureDefn->GetGeomFieldCount() == 1)
-                    poFeatureDefn->GetGeomFieldDefn(0)->SetNullable( poStmt->GetColNullable(iCol) );
+                    poFeatureDefn->GetGeomFieldDefn(0)->SetNullable( poStmtIn->GetColNullable(iCol) );
+                nGeomColumnIndex = iCol;
                 continue;
             }
         }
         else
         {
-            if( EQUAL(poStmt->GetColName(iCol),pszGeomColumn) )
+            if( EQUAL(poStmtIn->GetColName(iCol),pszGeomColumn) )
             {
                 if (poFeatureDefn->GetGeomFieldCount() == 1)
-                    poFeatureDefn->GetGeomFieldDefn(0)->SetNullable( poStmt->GetColNullable(iCol) );
+                    poFeatureDefn->GetGeomFieldDefn(0)->SetNullable( poStmtIn->GetColNullable(iCol) );
+                nGeomColumnIndex = iCol;
                 continue;
             }
         }
 
         if( pszFIDColumn != NULL)
         {
-		    if (EQUAL(poStmt->GetColName(iCol), pszFIDColumn) )
+            if (EQUAL(poStmtIn->GetColName(iCol), pszFIDColumn) )
             {
                 bool bIntegerFID = false;
-                switch( CPLODBCStatement::GetTypeMapping(poStmt->GetColType(iCol)) )
+                switch( CPLODBCStatement::GetTypeMapping(poStmtIn->GetColType(iCol)) )
                 {
                     case SQL_C_SSHORT:
                     case SQL_C_USHORT:
@@ -166,39 +174,41 @@ CPLErr OGRMSSQLSpatialLayer::BuildFeatureDefn( const char *pszLayerName,
                 }
                 else
                 {
-                    if (EQUALN(poStmt->GetColTypeName( iCol ), "bigint", strlen("bigint")))
+                    if (STARTS_WITH_CI(poStmtIn->GetColTypeName( iCol ), "bigint"))
                         SetMetadataItem(OLMD_FID64, "YES");
 
-                    if ( EQUAL(poStmt->GetColTypeName( iCol ), "int identity") ||
-                        EQUAL(poStmt->GetColTypeName( iCol ), "bigint identity"))
+                    if ( EQUAL(poStmtIn->GetColTypeName( iCol ), "int identity") ||
+                        EQUAL(poStmtIn->GetColTypeName( iCol ), "bigint identity"))
                         bIsIdentityFid = TRUE;
 
-                    /* skip FID */
+                    nFIDColumnIndex = iCol;
                     continue;
                 }
             }
         }
         else
         {
-            if (EQUAL(poStmt->GetColTypeName( iCol ), "int identity"))
+            if (EQUAL(poStmtIn->GetColTypeName( iCol ), "int identity"))
             {
-                pszFIDColumn = CPLStrdup( poStmt->GetColName(iCol) );
+                pszFIDColumn = CPLStrdup( poStmtIn->GetColName(iCol) );
                 bIsIdentityFid = TRUE;
+                nFIDColumnIndex = iCol;
                 continue;
             }
-            else if (EQUAL(poStmt->GetColTypeName( iCol ), "bigint identity"))
+            else if (EQUAL(poStmtIn->GetColTypeName( iCol ), "bigint identity"))
             {
-                pszFIDColumn = CPLStrdup( poStmt->GetColName(iCol) );
+                pszFIDColumn = CPLStrdup( poStmtIn->GetColName(iCol) );
                 bIsIdentityFid = TRUE;
                 SetMetadataItem(OLMD_FID64, "YES");
+                nFIDColumnIndex = iCol;
                 continue;
             }
         }
 
-        OGRFieldDefn    oField( poStmt->GetColName(iCol), OFTString );
-        oField.SetWidth( MAX(0,poStmt->GetColSize( iCol )) );
+        OGRFieldDefn    oField( poStmtIn->GetColName(iCol), OFTString );
+        oField.SetWidth( MAX(0,poStmtIn->GetColSize( iCol )) );
 
-        switch( CPLODBCStatement::GetTypeMapping(poStmt->GetColType(iCol)) )
+        switch( CPLODBCStatement::GetTypeMapping(poStmtIn->GetColType(iCol)) )
         {
             case SQL_C_SSHORT:
             case SQL_C_USHORT:
@@ -218,7 +228,7 @@ CPLErr OGRMSSQLSpatialLayer::BuildFeatureDefn( const char *pszLayerName,
 
             case SQL_C_NUMERIC:
                 oField.SetType( OFTReal );
-                oField.SetPrecision( poStmt->GetColPrecision(iCol) );
+                oField.SetPrecision( poStmtIn->GetColPrecision(iCol) );
                 break;
 
             case SQL_C_FLOAT:
@@ -243,24 +253,25 @@ CPLErr OGRMSSQLSpatialLayer::BuildFeatureDefn( const char *pszLayerName,
                 /* leave it as OFTString */;
         }
 
-        oField.SetNullable( poStmt->GetColNullable(iCol) );
+        oField.SetNullable( poStmtIn->GetColNullable(iCol) );
 
-        if ( poStmt->GetColColumnDef(iCol) )
+        if ( poStmtIn->GetColColumnDef(iCol) )
         {         
             /* process default value specification */
-            if ( EQUAL(poStmt->GetColColumnDef(iCol), "(getdate())") )
+            if ( EQUAL(poStmtIn->GetColColumnDef(iCol), "(getdate())") )
                 oField.SetDefault( "CURRENT_TIMESTAMP" );
-            else if ( EQUALN(poStmt->GetColColumnDef(iCol), "(CONVERT([time],getdate(),0))", 25) )
+            else if ( STARTS_WITH_CI(poStmtIn->GetColColumnDef(iCol), "(CONVERT([time],getdate()") )
                 oField.SetDefault( "CURRENT_TIME" );
-            else if ( EQUALN(poStmt->GetColColumnDef(iCol), "(CONVERT([date],getdate(),0))", 25) )
+            else if ( STARTS_WITH_CI(poStmtIn->GetColColumnDef(iCol), "(CONVERT([date],getdate()") )
                 oField.SetDefault( "CURRENT_DATE" );
             else
             {
-                char* pszDefault = CPLStrdup(poStmt->GetColColumnDef(iCol));
-                int nLen = strlen(pszDefault);
+                char* pszDefault = CPLStrdup(poStmtIn->GetColColumnDef(iCol));
+                int nLen = static_cast<int>(strlen(pszDefault));
                 if (nLen >= 1 && pszDefault[0] == '(' && pszDefault[nLen-1] == ')')
                 {
-                    /* all default values are encapsulated in backets by MSSQL server */
+                    // All default values are encapsulated in brackets
+                    // by MSSQL server.
                     if (nLen >= 4 && pszDefault[1] == '(' && pszDefault[nLen-2] == ')')
                     {
                         /* for numeric values double brackets are used */
@@ -323,7 +334,7 @@ void OGRMSSQLSpatialLayer::ResetReading()
 OGRFeature *OGRMSSQLSpatialLayer::GetNextFeature()
 
 {
-    while( TRUE )
+    while( true )
     {
         OGRFeature      *poFeature;
 
@@ -364,7 +375,6 @@ OGRFeature *OGRMSSQLSpatialLayer::GetNextRawFeature()
 /* -------------------------------------------------------------------- */
 /*      Create a feature from the current result.                       */
 /* -------------------------------------------------------------------- */
-    int         iField;
     OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
 
     if( pszFIDColumn != NULL && poStmt->GetColId(pszFIDColumn) > -1 )
@@ -379,7 +389,7 @@ OGRFeature *OGRMSSQLSpatialLayer::GetNextRawFeature()
 /* -------------------------------------------------------------------- */
 /*      Set the fields.                                                 */
 /* -------------------------------------------------------------------- */
-    for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
+    for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     {
         if ( poFeatureDefn->GetFieldDefn(iField)->IsIgnored() )
             continue;
@@ -603,7 +613,8 @@ char* OGRMSSQLSpatialLayer::GByteArrayToHexString( const GByte* pabyData, int nL
 {
     char* pszTextBuf;
 
-    pszTextBuf = (char *) CPLMalloc(nLen*2+3);
+    const size_t nTextBufLen = nLen*2+3;
+    pszTextBuf = (char *) CPLMalloc(nTextBufLen);
 
     int  iSrc, iDst=0;
 
@@ -611,12 +622,12 @@ char* OGRMSSQLSpatialLayer::GByteArrayToHexString( const GByte* pabyData, int nL
     {
         if( iSrc == 0 )
         {
-            sprintf( pszTextBuf+iDst, "0x%02x", pabyData[iSrc] );
+            snprintf( pszTextBuf+iDst, nTextBufLen-iDst, "0x%02x", pabyData[iSrc] );
             iDst += 4;
         }
         else
         {
-            sprintf( pszTextBuf+iDst, "%02x", pabyData[iSrc] );
+            snprintf( pszTextBuf+iDst, nTextBufLen-iDst, "%02x", pabyData[iSrc] );
             iDst += 2;
         }
     }
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialtablelayer.cpp b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialtablelayer.cpp
index 1eedd14..e7c1fab 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialtablelayer.cpp
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialtablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmssqlspatialtablelayer.cpp 29185 2015-05-12 10:45:44Z tamas $
+ * $Id: ogrmssqlspatialtablelayer.cpp 33834 2016-03-31 18:36:27Z tamas $
  *
  * Project:  MSSQL Spatial driver
  * Purpose:  Implements OGRMSSQLSpatialTableLayer class, access to an existing table.
@@ -30,8 +30,11 @@
 
 #include "cpl_conv.h"
 #include "ogr_mssqlspatial.h"
+#ifdef SQLNCLI_VERSION
+#include <sqlncli.h>
+#endif
 
-CPL_CVSID("$Id: ogrmssqlspatialtablelayer.cpp 29185 2015-05-12 10:45:44Z tamas $");
+CPL_CVSID("$Id: ogrmssqlspatialtablelayer.cpp 33834 2016-03-31 18:36:27Z tamas $");
 
 /************************************************************************/
 /*                         OGRMSSQLAppendEscaped( )                     */
@@ -40,13 +43,16 @@ CPL_CVSID("$Id: ogrmssqlspatialtablelayer.cpp 29185 2015-05-12 10:45:44Z tamas $
 void OGRMSSQLAppendEscaped( CPLODBCStatement* poStatement, const char* pszStrValue)
 {
     if (!pszStrValue)
+    {
         poStatement->Append("null");
-    
+        return;
+    }
+
     size_t  iIn, iOut , nTextLen = strlen(pszStrValue);
-    char    *pszEscapedText = (char *) VSIMalloc(nTextLen*2 + 3);
+    char    *pszEscapedText = (char *) CPLMalloc(nTextLen*2 + 3);
 
     pszEscapedText[0] = '\'';
-    
+
     for( iIn = 0, iOut = 1; iIn < nTextLen; iIn++ )
     {
         switch( pszStrValue[iIn] )
@@ -75,8 +81,9 @@ void OGRMSSQLAppendEscaped( CPLODBCStatement* poStatement, const char* pszStrVal
 /*                          OGRMSSQLSpatialTableLayer()                 */
 /************************************************************************/
 
-OGRMSSQLSpatialTableLayer::OGRMSSQLSpatialTableLayer( OGRMSSQLSpatialDataSource *poDSIn )
-
+OGRMSSQLSpatialTableLayer::OGRMSSQLSpatialTableLayer( OGRMSSQLSpatialDataSource *poDSIn ) :
+    bLaunderColumnNames(FALSE),
+    bPreservePrecision(FALSE)
 {
     poDS = poDSIn;
 
@@ -89,7 +96,7 @@ OGRMSSQLSpatialTableLayer::OGRMSSQLSpatialTableLayer( OGRMSSQLSpatialDataSource
     nSRSId = -1;
 
     poFeatureDefn = NULL;
-    
+
     pszTableName = NULL;
     pszLayerName = NULL;
     pszSchemaName = NULL;
@@ -97,7 +104,19 @@ OGRMSSQLSpatialTableLayer::OGRMSSQLSpatialTableLayer( OGRMSSQLSpatialDataSource
     eGeomType = wkbNone;
 
     bNeedSpatialIndex = FALSE;
+#ifdef SQL_SS_UDT
+    nUploadGeometryFormat = MSSQLGEOMETRY_NATIVE;
+#else
     nUploadGeometryFormat = MSSQLGEOMETRY_WKB;
+#endif
+
+    bUseCopy = FALSE;
+    nBCPSize = 1000;
+    papstBindBuffer = NULL;
+    hEnvBCP = NULL;
+    hDBCBCP = NULL;
+    nBCPCount = 0;
+    bIdentityInsert = FALSE;
 }
 
 /************************************************************************/
@@ -107,13 +126,17 @@ OGRMSSQLSpatialTableLayer::OGRMSSQLSpatialTableLayer( OGRMSSQLSpatialDataSource
 OGRMSSQLSpatialTableLayer::~OGRMSSQLSpatialTableLayer()
 
 {
+#ifdef MSSQL_BCP_SUPPORTED
+    CloseBCP();
+#endif
+    
     if ( bNeedSpatialIndex && nLayerStatus == MSSQLLAYERSTATUS_CREATED )
     {
         /* recreate spatial index */
         DropSpatialIndex();
         CreateSpatialIndex();
     }
-    
+
     CPLFree( pszTableName );
     CPLFree( pszLayerName );
     CPLFree( pszSchemaName );
@@ -135,23 +158,23 @@ const char *OGRMSSQLSpatialTableLayer::GetName()
 /************************************************************************/
 /*                             GetLayerDefn()                           */
 /************************************************************************/
-OGRFeatureDefn* OGRMSSQLSpatialTableLayer::GetLayerDefn() 
-{ 
+OGRFeatureDefn* OGRMSSQLSpatialTableLayer::GetLayerDefn()
+{
     if (poFeatureDefn)
         return poFeatureDefn;
-    
+
     CPLODBCSession *poSession = poDS->GetSession();
 /* -------------------------------------------------------------------- */
 /*      Do we have a simple primary key?                                */
 /* -------------------------------------------------------------------- */
     CPLODBCStatement oGetKey( poSession );
-    
-    if( oGetKey.GetPrimaryKeys( pszTableName, poDS->GetCatalog(), pszSchemaName ) 
+
+    if( oGetKey.GetPrimaryKeys( pszTableName, poDS->GetCatalog(), pszSchemaName )
         && oGetKey.Fetch() )
     {
         pszFIDColumn = CPLStrdup(oGetKey.GetColData( 3 ));
-        
-        if( oGetKey.Fetch() ) // more than one field in key! 
+
+        if( oGetKey.Fetch() ) // more than one field in key!
         {
             oGetKey.Clear();
             CPLFree( pszFIDColumn );
@@ -162,7 +185,6 @@ OGRFeatureDefn* OGRMSSQLSpatialTableLayer::GetLayerDefn()
         }
     }
 
-    
 /* -------------------------------------------------------------------- */
 /*      Get the column definitions for this table.                      */
 /* -------------------------------------------------------------------- */
@@ -175,22 +197,22 @@ OGRFeatureDefn* OGRMSSQLSpatialTableLayer::GetLayerDefn()
     eErr = BuildFeatureDefn( pszLayerName, &oGetCol );
     if( eErr != CE_None )
         return NULL;
-        
+
     if (eGeomType != wkbNone)
         poFeatureDefn->SetGeomType(eGeomType);
-    
+
     if ( GetSpatialRef() && poFeatureDefn->GetGeomFieldCount() == 1)
         poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef( poSRS );
 
     if( poFeatureDefn->GetFieldCount() == 0 &&
         pszFIDColumn == NULL && pszGeomColumn == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "No column definitions found for table '%s', layer not usable.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "No column definitions found for table '%s', layer not usable.",
                   pszLayerName );
         return NULL;
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      If we got a geometry column, does it exist?  Is it binary?      */
 /* -------------------------------------------------------------------- */
@@ -199,8 +221,8 @@ OGRFeatureDefn* OGRMSSQLSpatialTableLayer::GetLayerDefn()
         int iColumn = oGetCol.GetColId( pszGeomColumn );
         if( iColumn < 0 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Column %s requested for geometry, but it does not exist.", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Column %s requested for geometry, but it does not exist.",
                       pszGeomColumn );
             CPLFree( pszGeomColumn );
             pszGeomColumn = NULL;
@@ -223,11 +245,11 @@ OGRFeatureDefn* OGRMSSQLSpatialTableLayer::GetLayerDefn()
                 else if ( EQUAL(oGetCol.GetColTypeName( iColumn ), "ntext") )
                     nGeomColumnType = MSSQLCOLTYPE_TEXT;
                 else if ( EQUAL(oGetCol.GetColTypeName( iColumn ), "image") )
-                    nGeomColumnType = MSSQLCOLTYPE_BINARY; 
+                    nGeomColumnType = MSSQLCOLTYPE_BINARY;
                 else
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined, 
-                          "Column type %s is not supported for geometry column.", 
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                          "Column type %s is not supported for geometry column.",
                           oGetCol.GetColTypeName( iColumn ) );
                     CPLFree( pszGeomColumn );
                     pszGeomColumn = NULL;
@@ -236,7 +258,7 @@ OGRFeatureDefn* OGRMSSQLSpatialTableLayer::GetLayerDefn()
         }
     }
 
-    return poFeatureDefn; 
+    return poFeatureDefn;
 }
 
 /************************************************************************/
@@ -244,7 +266,7 @@ OGRFeatureDefn* OGRMSSQLSpatialTableLayer::GetLayerDefn()
 /************************************************************************/
 
 CPLErr OGRMSSQLSpatialTableLayer::Initialize( const char *pszSchema,
-                                              const char *pszLayerName,
+                                              const char *pszLayerNameIn,
                                               const char *pszGeomCol,
                                               CPL_UNUSED int nCoordDimension,
                                               int nSRId,
@@ -259,20 +281,20 @@ CPLErr OGRMSSQLSpatialTableLayer::Initialize( const char *pszSchema,
 /*      schema is provided if there is a dot in the name, and that      */
 /*      it is in the form <schema>.<tablename>                          */
 /* -------------------------------------------------------------------- */
-    const char *pszDot = strstr(pszLayerName,".");
+    const char *pszDot = strstr(pszLayerNameIn,".");
     if( pszDot != NULL )
     {
         pszTableName = CPLStrdup(pszDot + 1);
-        pszSchemaName = CPLStrdup(pszLayerName);
-        pszSchemaName[pszDot - pszLayerName] = '\0';
-        this->pszLayerName = CPLStrdup(pszLayerName);
+        pszSchemaName = CPLStrdup(pszLayerNameIn);
+        pszSchemaName[pszDot - pszLayerNameIn] = '\0';
+        this->pszLayerName = CPLStrdup(pszLayerNameIn);
     }
     else
     {
-        pszTableName = CPLStrdup(pszLayerName);
+        pszTableName = CPLStrdup(pszLayerNameIn);
         pszSchemaName = CPLStrdup(pszSchema);
         if ( EQUAL(pszSchemaName, "dbo") )
-            this->pszLayerName = CPLStrdup(pszLayerName);
+            this->pszLayerName = CPLStrdup(pszLayerNameIn);
         else
             this->pszLayerName = CPLStrdup(CPLSPrintf("%s.%s", pszSchemaName, pszTableName));
     }
@@ -283,7 +305,7 @@ CPLErr OGRMSSQLSpatialTableLayer::Initialize( const char *pszSchema,
 /* -------------------------------------------------------------------- */
     CPLFree( pszGeomColumn );
     if( pszGeomCol == NULL )
-        GetLayerDefn(); /* fetch geom colum if not specified */
+        GetLayerDefn(); /* fetch geom column if not specified */
     else
         pszGeomColumn = CPLStrdup( pszGeomCol );
 
@@ -307,7 +329,7 @@ CPLErr OGRMSSQLSpatialTableLayer::Initialize( const char *pszSchema,
             poSRS = NULL;
         }
     }
-    
+
     if (!poSRS)
     {
         if (nSRSId < 0)
@@ -329,7 +351,7 @@ int OGRMSSQLSpatialTableLayer::FetchSRSId()
     {
         CPLODBCStatement oStatement = CPLODBCStatement( poDS->GetSession() );
         oStatement.Appendf( "select srid from geometry_columns "
-                        "where f_table_schema = '%s' and f_table_name = '%s'", 
+                        "where f_table_schema = '%s' and f_table_name = '%s'",
                         pszSchemaName, pszTableName );
 
         if( oStatement.ExecuteSQL() && oStatement.Fetch() )
@@ -338,7 +360,7 @@ int OGRMSSQLSpatialTableLayer::FetchSRSId()
                 nSRSId = atoi( oStatement.GetColData( 0 ) );
         }
     }
-        
+
     return nSRSId;
 }
 
@@ -359,7 +381,7 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateSpatialIndex()
         OGREnvelope oExt;
         if (GetExtent(&oExt, TRUE) != OGRERR_NONE)
         {
-            CPLError( CE_Warning, CPLE_AppDefined, 
+            CPLError( CE_Warning, CPLE_AppDefined,
                           "Failed to get extent for spatial index." );
             return OGRERR_FAILURE;
         }
@@ -369,31 +391,31 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateSpatialIndex()
 
         oStatement.Appendf("CREATE SPATIAL INDEX [ogr_%s_%s_%s_sidx] ON [%s].[%s] ( [%s] ) "
             "USING GEOMETRY_GRID WITH (BOUNDING_BOX =(%.15g, %.15g, %.15g, %.15g))",
-                           pszSchemaName, pszTableName, pszGeomColumn, 
-                           pszSchemaName, pszTableName, pszGeomColumn, 
+                           pszSchemaName, pszTableName, pszGeomColumn,
+                           pszSchemaName, pszTableName, pszGeomColumn,
                            oExt.MinX, oExt.MinY, oExt.MaxX, oExt.MaxY );
     }
     else if (nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY)
     {
         oStatement.Appendf("CREATE SPATIAL INDEX [ogr_%s_%s_%s_sidx] ON [%s].[%s] ( [%s] ) "
             "USING GEOGRAPHY_GRID",
-                           pszSchemaName, pszTableName, pszGeomColumn, 
+                           pszSchemaName, pszTableName, pszGeomColumn,
                            pszSchemaName, pszTableName, pszGeomColumn );
     }
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
             "Spatial index is not supported on the geometry column '%s'", pszGeomColumn);
         return OGRERR_FAILURE;
     }
 
     if( !oStatement.ExecuteSQL() )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Failed to create the spatial index, %s.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                      "Failed to create the spatial index, %s.",
                       poDS->GetSession()->GetLastError());
         return OGRERR_FAILURE;
-    } 
+    }
 
     return OGRERR_NONE;
 }
@@ -413,18 +435,18 @@ void OGRMSSQLSpatialTableLayer::DropSpatialIndex()
     oStatement.Appendf("IF  EXISTS (SELECT * FROM sys.indexes "
         "WHERE object_id = OBJECT_ID(N'[%s].[%s]') AND name = N'ogr_%s_%s_%s_sidx') "
         "DROP INDEX [ogr_%s_%s_%s_sidx] ON [%s].[%s]",
-                       pszSchemaName, pszTableName, 
-                       pszSchemaName, pszTableName, pszGeomColumn, 
-                       pszSchemaName, pszTableName, pszGeomColumn, 
+                       pszSchemaName, pszTableName,
+                       pszSchemaName, pszTableName, pszGeomColumn,
+                       pszSchemaName, pszTableName, pszGeomColumn,
                        pszSchemaName, pszTableName );
-    
+
     if( !oStatement.ExecuteSQL() )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Failed to drop the spatial index, %s.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                      "Failed to drop the spatial index, %s.",
                       poDS->GetSession()->GetLastError());
         return;
-    } 
+    }
 }
 
 /************************************************************************/
@@ -459,7 +481,7 @@ CPLString OGRMSSQLSpatialTableLayer::BuildFields()
 
         osFieldList += "[";
         osFieldList += pszGeomColumn;
-        if (nGeomColumnType == MSSQLCOLTYPE_GEOMETRY || 
+        if (nGeomColumnType == MSSQLCOLTYPE_GEOMETRY ||
                             nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY)
         {
             if ( poDS->GetGeometryFormat() == MSSQLGEOMETRY_WKB )
@@ -494,12 +516,12 @@ CPLString OGRMSSQLSpatialTableLayer::BuildFields()
         {
             if ( poFeatureDefn->GetFieldDefn(i)->IsIgnored() )
                 continue;
-            
+
             const char *pszName = poFeatureDefn->GetFieldDefn(i)->GetNameRef();
 
             if( nColumn > 0 )
                 osFieldList += ", ";
-        
+
             osFieldList += "[";
             osFieldList += pszName;
             osFieldList += "]";
@@ -566,7 +588,7 @@ CPLODBCStatement* OGRMSSQLSpatialTableLayer::BuildStatement(const char* pszColum
     /* If we have a spatial filter, query on it */
     if ( m_poFilterGeom != NULL )
     {
-        if (nGeomColumnType == MSSQLCOLTYPE_GEOMETRY 
+        if (nGeomColumnType == MSSQLCOLTYPE_GEOMETRY
             || nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY)
         {
             if( pszQuery == NULL )
@@ -580,15 +602,15 @@ CPLODBCStatement* OGRMSSQLSpatialTableLayer::BuildStatement(const char* pszColum
                 poStatement->Append( "geography::" );
             else
                 poStatement->Append( "geometry::" );
-            
-            if ( m_sFilterEnvelope.MinX == m_sFilterEnvelope.MaxX || 
+
+            if ( m_sFilterEnvelope.MinX == m_sFilterEnvelope.MaxX ||
                  m_sFilterEnvelope.MinY == m_sFilterEnvelope.MaxY)
-                poStatement->Appendf("STGeomFromText('POINT(%.15g %.15g)',%d)) = 1", 
+                poStatement->Appendf("STGeomFromText('POINT(%.15g %.15g)',%d)) = 1",
                             m_sFilterEnvelope.MinX, m_sFilterEnvelope.MinY, nSRSId >= 0? nSRSId : 0);
             else
-                poStatement->Appendf( "STGeomFromText('POLYGON((%.15g %.15g,%.15g %.15g,%.15g %.15g,%.15g %.15g,%.15g %.15g))',%d)) = 1", 
+                poStatement->Appendf( "STGeomFromText('POLYGON((%.15g %.15g,%.15g %.15g,%.15g %.15g,%.15g %.15g,%.15g %.15g))',%d)) = 1",
                                             m_sFilterEnvelope.MinX, m_sFilterEnvelope.MinY,
-                                            m_sFilterEnvelope.MaxX, m_sFilterEnvelope.MinY, 
+                                            m_sFilterEnvelope.MaxX, m_sFilterEnvelope.MinY,
                                             m_sFilterEnvelope.MaxX, m_sFilterEnvelope.MaxY,
                                             m_sFilterEnvelope.MinX, m_sFilterEnvelope.MaxY,
                                             m_sFilterEnvelope.MinX, m_sFilterEnvelope.MinY,
@@ -596,9 +618,9 @@ CPLODBCStatement* OGRMSSQLSpatialTableLayer::BuildStatement(const char* pszColum
         }
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Spatial filter is supported only on geometry and geography column types." );
-            
+
             delete poStatement;
             return NULL;
         }
@@ -641,7 +663,7 @@ OGRFeature *OGRMSSQLSpatialTableLayer::GetFeature( GIntBig nFeatureId )
 
     poStmt = new CPLODBCStatement( poDS->GetSession() );
     CPLString osFields = BuildFields();
-    poStmt->Appendf( "select %s from %s where %s = " CPL_FRMT_GIB, osFields.c_str(), 
+    poStmt->Appendf( "select %s from %s where %s = " CPL_FRMT_GIB, osFields.c_str(),
         poFeatureDefn->GetName(), pszFIDColumn, nFeatureId );
 
     if( !poStmt->ExecuteSQL() )
@@ -658,19 +680,19 @@ OGRFeature *OGRMSSQLSpatialTableLayer::GetFeature( GIntBig nFeatureId )
 /*                         SetAttributeFilter()                         */
 /************************************************************************/
 
-OGRErr OGRMSSQLSpatialTableLayer::SetAttributeFilter( const char *pszQuery )
+OGRErr OGRMSSQLSpatialTableLayer::SetAttributeFilter( const char *pszQueryIn )
 
 {
     CPLFree(m_pszAttrQueryString);
-    m_pszAttrQueryString = (pszQuery) ? CPLStrdup(pszQuery) : NULL;
+    m_pszAttrQueryString = (pszQueryIn) ? CPLStrdup(pszQueryIn) : NULL;
 
-    if( (pszQuery == NULL && this->pszQuery == NULL)
-        || (pszQuery != NULL && this->pszQuery != NULL 
-            && EQUAL(pszQuery,this->pszQuery)) )
+    if( (pszQueryIn == NULL && this->pszQuery == NULL)
+        || (pszQueryIn != NULL && this->pszQuery != NULL
+            && EQUAL(pszQueryIn,this->pszQuery)) )
         return OGRERR_NONE;
 
     CPLFree( this->pszQuery );
-    this->pszQuery = (pszQuery) ? CPLStrdup( pszQuery ) : NULL;
+    this->pszQuery = (pszQueryIn) ? CPLStrdup( pszQueryIn ) : NULL;
 
     ClearStatement();
 
@@ -704,13 +726,13 @@ int OGRMSSQLSpatialTableLayer::TestCapability( const char * pszCap )
 #endif
 
     if( EQUAL(pszCap,OLCIgnoreFields) )
-        return TRUE; 
-    
+        return TRUE;
+
     if( EQUAL(pszCap,OLCRandomRead) )
         return (pszFIDColumn != NULL);
     else if( EQUAL(pszCap,OLCFastFeatureCount) )
         return TRUE;
-    else 
+    else
         return OGRMSSQLSpatialLayer::TestCapability( pszCap );
 }
 
@@ -727,7 +749,7 @@ GIntBig OGRMSSQLSpatialTableLayer::GetFeatureCount( int bForce )
         return OGRMSSQLSpatialLayer::GetFeatureCount( bForce );
 
     ClearStatement();
-        
+
     CPLODBCStatement* poStatement = BuildStatement( "count(*)" );
 
     if (poStatement == NULL || !poStatement->Fetch())
@@ -746,7 +768,7 @@ GIntBig OGRMSSQLSpatialTableLayer::GetFeatureCount( int bForce )
 /*                            CreateField()                             */
 /************************************************************************/
 
-OGRErr OGRMSSQLSpatialTableLayer::CreateField( OGRFieldDefn *poFieldIn, 
+OGRErr OGRMSSQLSpatialTableLayer::CreateField( OGRFieldDefn *poFieldIn,
                                          int bApproxOK )
 
 {
@@ -770,18 +792,18 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateField( OGRFieldDefn *poFieldIn,
 /* -------------------------------------------------------------------- */
 /*      Identify the MSSQL type.                                        */
 /* -------------------------------------------------------------------- */
-    
+
     if( oField.GetType() == OFTInteger )
     {
         if( oField.GetWidth() > 0 && bPreservePrecision )
-            sprintf( szFieldType, "numeric(%d,0)", oField.GetWidth() );
+            snprintf( szFieldType, sizeof(szFieldType), "numeric(%d,0)", oField.GetWidth() );
         else
             strcpy( szFieldType, "int" );
     }
     else if( oField.GetType() == OFTInteger64 )
     {
         if( oField.GetWidth() > 0 && bPreservePrecision )
-            sprintf( szFieldType, "numeric(%d,0)", oField.GetWidth() );
+            snprintf( szFieldType, sizeof(szFieldType), "numeric(%d,0)", oField.GetWidth() );
         else
             strcpy( szFieldType, "bigint" );
     }
@@ -789,17 +811,17 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateField( OGRFieldDefn *poFieldIn,
     {
         if( oField.GetWidth() > 0 && oField.GetPrecision() > 0
             && bPreservePrecision )
-            sprintf( szFieldType, "numeric(%d,%d)",
+            snprintf( szFieldType, sizeof(szFieldType), "numeric(%d,%d)",
                      oField.GetWidth(), oField.GetPrecision() );
         else
             strcpy( szFieldType, "float" );
     }
     else if( oField.GetType() == OFTString )
     {
-        if( oField.GetWidth() == 0 || !bPreservePrecision )
+        if( oField.GetWidth() == 0 || oField.GetWidth() > 4000 || !bPreservePrecision )
             strcpy( szFieldType, "nvarchar(MAX)" );
         else
-            sprintf( szFieldType, "nvarchar(%d)", oField.GetWidth() );
+            snprintf( szFieldType, sizeof(szFieldType), "nvarchar(%d)", oField.GetWidth() );
     }
     else if( oField.GetType() == OFTDate )
     {
@@ -838,10 +860,10 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateField( OGRFieldDefn *poFieldIn,
 /* -------------------------------------------------------------------- */
 /*      Create the new field.                                           */
 /* -------------------------------------------------------------------- */
-    
+
     CPLODBCStatement oStmt( poDS->GetSession() );
-            
-    oStmt.Appendf( "ALTER TABLE [%s].[%s] ADD [%s] %s", 
+
+    oStmt.Appendf( "ALTER TABLE [%s].[%s] ADD [%s] %s",
         pszSchemaName, pszTableName, oField.GetNameRef(), szFieldType);
 
     if ( !oField.IsNullable() )
@@ -855,14 +877,14 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateField( OGRFieldDefn *poFieldIn,
             oStmt.Append(" DEFAULT(CONVERT([time],getdate()))");
         else if ( EQUAL(oField.GetDefault(), "CURRENT_DATE") )
             oStmt.Append( " DEFAULT(CONVERT([date],getdate()))" );
-        else 
+        else
             oStmt.Appendf(" DEFAULT(%s)", oField.GetDefault());
     }
 
     if( !oStmt.ExecuteSQL() )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                    "Error creating field %s, %s", oField.GetNameRef(), 
+                    "Error creating field %s, %s", oField.GetNameRef(),
                     poDS->GetSession()->GetLastError() );
 
         return OGRERR_FAILURE;
@@ -912,14 +934,14 @@ OGRErr OGRMSSQLSpatialTableLayer::ISetFeature( OGRFeature *poFeature )
         return eErr;
 
     }
-    
+
     ClearStatement();
 
 /* -------------------------------------------------------------------- */
 /*      Form the UPDATE command.                                        */
 /* -------------------------------------------------------------------- */
     CPLODBCStatement oStmt( poDS->GetSession() );
-            
+
     oStmt.Appendf( "UPDATE [%s].[%s] SET ", pszSchemaName, pszTableName);
 
     OGRMSSQLGeometryValidator oValidator(poFeature->GetGeometryRef());
@@ -934,24 +956,56 @@ OGRErr OGRMSSQLSpatialTableLayer::ISetFeature( OGRFeature *poFeature )
     int nFieldCount = poFeatureDefn->GetFieldCount();
     int bind_num = 0;
     void** bind_buffer = (void**)CPLMalloc(sizeof(void*) * nFieldCount);
-    
+
 
     int bNeedComma = FALSE;
+    SQLLEN nWKBLenBindParameter;
     if(poGeom != NULL && pszGeomColumn != NULL)
     {
         oStmt.Appendf( "[%s] = ", pszGeomColumn );
-        
-        if (nUploadGeometryFormat == MSSQLGEOMETRY_WKB)
+
+        if (nUploadGeometryFormat == MSSQLGEOMETRY_NATIVE)
+        {
+            OGRMSSQLGeometryWriter poWriter(poGeom, nGeomColumnType, nSRSId);
+            int nDataLen = poWriter.GetDataLen();
+            GByte *pabyData = (GByte *) CPLMalloc(nDataLen + 1);
+            if (poWriter.WriteSqlGeometry(pabyData, nDataLen) == OGRERR_NONE)
+            {
+                char* pszBytes = GByteArrayToHexString( pabyData, nDataLen);
+                SQLLEN nts = SQL_NTS;
+                int nRetCode = SQLBindParameter(oStmt.GetStatement(), (SQLUSMALLINT)(bind_num + 1), 
+                    SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR,
+                    nDataLen, 0, (SQLPOINTER)pszBytes, 0, &nts);
+                if ( nRetCode == SQL_SUCCESS || nRetCode == SQL_SUCCESS_WITH_INFO )
+                {
+                    oStmt.Append( "?" );   
+                    bind_buffer[bind_num] = pszBytes;
+                    ++bind_num;
+                }
+                else
+                {
+                    oStmt.Append( "null" );
+                    CPLFree(pszBytes);
+                }       
+            }
+            else
+            {
+                oStmt.Append( "null" );
+            }
+            CPLFree(pabyData);
+        }
+        else if (nUploadGeometryFormat == MSSQLGEOMETRY_WKB)
         {
             int nWKBLen = poGeom->WkbSize();
             GByte *pabyWKB = (GByte *) CPLMalloc(nWKBLen + 1);
-        
-            if( poGeom->exportToWkb( wkbNDR, pabyWKB ) == OGRERR_NONE && (nGeomColumnType == MSSQLCOLTYPE_GEOMETRY 
+
+            if( poGeom->exportToWkb( wkbNDR, pabyWKB ) == OGRERR_NONE && (nGeomColumnType == MSSQLCOLTYPE_GEOMETRY
                 || nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY))
             {
-                int nRetCode = SQLBindParameter(oStmt.GetStatement(), (SQLUSMALLINT)(bind_num + 1), 
-                    SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY, 
-                    nWKBLen, 0, (SQLPOINTER)pabyWKB, nWKBLen, (SQLLEN*)&nWKBLen);
+                nWKBLenBindParameter = nWKBLen;
+                int nRetCode = SQLBindParameter(oStmt.GetStatement(), (SQLUSMALLINT)(bind_num + 1),
+                    SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY,
+                    nWKBLen, 0, (SQLPOINTER)pabyWKB, nWKBLen, &nWKBLenBindParameter);
                 if ( nRetCode == SQL_SUCCESS || nRetCode == SQL_SUCCESS_WITH_INFO )
                 {
                     if (nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY)
@@ -963,7 +1017,7 @@ OGRErr OGRMSSQLSpatialTableLayer::ISetFeature( OGRFeature *poFeature )
                     {
                         oStmt.Append( "geometry::STGeomFromWKB(?" );
                         oStmt.Appendf(",%d).MakeValid()", nSRSId );
-                    }    
+                    }
                     bind_buffer[bind_num] = pabyWKB;
                     ++bind_num;
                 }
@@ -971,7 +1025,7 @@ OGRErr OGRMSSQLSpatialTableLayer::ISetFeature( OGRFeature *poFeature )
                 {
                     oStmt.Append( "null" );
                     CPLFree(pabyWKB);
-                }           
+                }
             }
             else
             {
@@ -982,15 +1036,15 @@ OGRErr OGRMSSQLSpatialTableLayer::ISetFeature( OGRFeature *poFeature )
         else if (nUploadGeometryFormat == MSSQLGEOMETRY_WKT)
         {
             char    *pszWKT = NULL;
-            if( poGeom->exportToWkt( &pszWKT ) == OGRERR_NONE && (nGeomColumnType == MSSQLCOLTYPE_GEOMETRY 
+            if( poGeom->exportToWkt( &pszWKT ) == OGRERR_NONE && (nGeomColumnType == MSSQLCOLTYPE_GEOMETRY
                 || nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY))
             {
                 size_t nLen = 0;
                 while(pszWKT[nLen] != '\0')
                     nLen ++;
-                
-                int nRetCode = SQLBindParameter(oStmt.GetStatement(), (SQLUSMALLINT)(bind_num + 1), 
-                    SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, 
+
+                int nRetCode = SQLBindParameter(oStmt.GetStatement(), (SQLUSMALLINT)(bind_num + 1),
+                    SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR,
                     nLen, 0, (SQLPOINTER)pszWKT, 0, NULL);
                 if ( nRetCode == SQL_SUCCESS || nRetCode == SQL_SUCCESS_WITH_INFO )
                 {
@@ -1003,7 +1057,7 @@ OGRErr OGRMSSQLSpatialTableLayer::ISetFeature( OGRFeature *poFeature )
                     {
                         oStmt.Append( "geometry::STGeomFromText(?" );
                         oStmt.Appendf(",%d).MakeValid()", nSRSId );
-                    }    
+                    }
                     bind_buffer[bind_num] = pszWKT;
                     ++bind_num;
                 }
@@ -1011,7 +1065,7 @@ OGRErr OGRMSSQLSpatialTableLayer::ISetFeature( OGRFeature *poFeature )
                 {
                     oStmt.Append( "null" );
                     CPLFree(pszWKT);
-                }           
+                }
             }
             else
             {
@@ -1052,13 +1106,13 @@ OGRErr OGRMSSQLSpatialTableLayer::ISetFeature( OGRFeature *poFeature )
     if( !oStmt.ExecuteSQL() )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-            "Error updating feature with FID:" CPL_FRMT_GIB ", %s", poFeature->GetFID(), 
+            "Error updating feature with FID:" CPL_FRMT_GIB ", %s", poFeature->GetFID(),
                     poDS->GetSession()->GetLastError() );
 
         for( i = 0; i < bind_num; i++ )
             CPLFree(bind_buffer[i]);
         CPLFree(bind_buffer);
-        
+
         return OGRERR_FAILURE;
     }
 
@@ -1068,7 +1122,7 @@ OGRErr OGRMSSQLSpatialTableLayer::ISetFeature( OGRFeature *poFeature )
 
     if (oStmt.GetRowCountAffected() < 1)
         return OGRERR_NON_EXISTING_FEATURE;
-    
+
     return OGRERR_NONE;
 }
 
@@ -1080,21 +1134,21 @@ OGRErr OGRMSSQLSpatialTableLayer::DeleteFeature( GIntBig nFID )
 
 {
     GetLayerDefn();
-    
+
     if( pszFIDColumn == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "DeleteFeature() without any FID column." );
         return OGRERR_FAILURE;
     }
-    
+
     if( nFID == OGRNullFID )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "DeleteFeature() with unset FID fails." );
         return OGRERR_FAILURE;
     }
-    
+
     ClearStatement();
 
 /* -------------------------------------------------------------------- */
@@ -1102,13 +1156,13 @@ OGRErr OGRMSSQLSpatialTableLayer::DeleteFeature( GIntBig nFID )
 /* -------------------------------------------------------------------- */
     CPLODBCStatement oStatement( poDS->GetSession() );
 
-    oStatement.Appendf("DELETE FROM [%s] WHERE [%s] = " CPL_FRMT_GIB, 
+    oStatement.Appendf("DELETE FROM [%s] WHERE [%s] = " CPL_FRMT_GIB,
             poFeatureDefn->GetName(), pszFIDColumn, nFID);
-    
+
     if( !oStatement.ExecuteSQL() )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Attempt to delete feature with FID " CPL_FRMT_GIB " failed. %s", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Attempt to delete feature with FID " CPL_FRMT_GIB " failed. %s",
                   nFID, poDS->GetSession()->GetLastError() );
 
         return OGRERR_FAILURE;
@@ -1116,9 +1170,767 @@ OGRErr OGRMSSQLSpatialTableLayer::DeleteFeature( GIntBig nFID )
 
     if (oStatement.GetRowCountAffected() < 1)
         return OGRERR_NON_EXISTING_FEATURE;
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           Failed()                                   */
+/************************************************************************/
+
+int OGRMSSQLSpatialTableLayer::Failed( int nRetCode )
+
+{
+    if( nRetCode == SQL_SUCCESS || nRetCode == SQL_SUCCESS_WITH_INFO )
+        return FALSE;
+
+    char SQLState[6] = "";
+    char Msg[256] = "";
+    SQLINTEGER iNativeError = 0;
+    SQLSMALLINT iMsgLen = 0;
+
+    int iRc = SQLGetDiagRec(SQL_HANDLE_ENV, hEnvBCP, 1,
+    (SQLCHAR*)SQLState, &iNativeError, (SQLCHAR*)Msg, 256, &iMsgLen);
+    if (iRc != SQL_NO_DATA) {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "SQL Error SQLState=%s, NativeError=%d, Msg=%s\n", SQLState,
+                  static_cast<int>(iNativeError), Msg );
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                           Failed2()                                  */
+/************************************************************************/
+
+#ifdef MSSQL_BCP_SUPPORTED
+int OGRMSSQLSpatialTableLayer::Failed2( int nRetCode )
+
+{
+    if (nRetCode == SUCCEED)
+        return FALSE;
+
+    char SQLState[6] = "";
+    char Msg[256] = "";
+    SQLINTEGER iNativeError = 0;
+    SQLSMALLINT iMsgLen = 0;
+
+    int iRc = SQLGetDiagRec(SQL_HANDLE_DBC, hDBCBCP, 1,
+    (SQLCHAR*)SQLState, &iNativeError, (SQLCHAR*)Msg, 256, &iMsgLen);
+    if (iRc != SQL_NO_DATA) {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "SQL Error SQLState=%s, NativeError=%d, Msg=%s\n", SQLState,
+                  static_cast<int>(iNativeError), Msg );
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                            InitBCP()                                 */
+/************************************************************************/
+
+int OGRMSSQLSpatialTableLayer::InitBCP(const char* pszDSN)
+
+{
+    /* Create a different connection fro BCP upload */
+    if( Failed( SQLAllocHandle( SQL_HANDLE_ENV, NULL, &hEnvBCP ) ) )
+    return FALSE;
+
+    /* Notify ODBC that this is an ODBC 3.0 app. */
+    if( Failed( SQLSetEnvAttr( hEnvBCP, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER ) ) )
+    {
+        CloseBCP();
+        return FALSE;
+    }
+
+    if( Failed( SQLAllocHandle( SQL_HANDLE_DBC, hEnvBCP, &hDBCBCP ) ) )
+    {
+        CloseBCP();
+        return FALSE;
+    }
+
+    /* set bulk copy mode */
+    if( Failed( SQLSetConnectAttr(hDBCBCP, SQL_COPT_SS_BCP, (void *)SQL_BCP_ON, SQL_IS_INTEGER) ) )
+    {
+        CloseBCP();
+        return FALSE;
+    }
+
+    SQLUINTEGER timeout = 30;
+    Failed(SQLSetConnectAttr(hDBCBCP, SQL_ATTR_LOGIN_TIMEOUT, (void*)timeout, SQL_IS_INTEGER));
+
+    SQLCHAR szOutConnString[1024];
+    SQLSMALLINT nOutConnStringLen = 0;
+
+    if ( Failed(
+        SQLDriverConnect( hDBCBCP, NULL, 
+                            (SQLCHAR *) pszDSN, (SQLSMALLINT)strlen(pszDSN), 
+                            szOutConnString, sizeof(szOutConnString), 
+                            &nOutConnStringLen, SQL_DRIVER_NOPROMPT ) ))
+    {
+        CloseBCP();
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                            CloseBCP()                                */
+/************************************************************************/
+
+void OGRMSSQLSpatialTableLayer::CloseBCP()
+
+{
+    if (papstBindBuffer)
+    {
+        int iCol;
+
+        int nRecNum = bcp_done( hDBCBCP );
+        if (nRecNum == -1)
+            Failed2(nRecNum);
+
+        for( iCol = 0; iCol < nRawColumns; iCol++ )
+            CPLFree(papstBindBuffer[iCol]);
+        CPLFree(papstBindBuffer);
+
+        if( bIdentityInsert )
+        {
+            bIdentityInsert = FALSE;
+            
+            /* restore identity insert if needed */
+            CPLODBCStatement oStatement( poDS->GetSession() );
+
+            oStatement.Appendf( "SET IDENTITY_INSERT [%s].[%s] OFF;",
+                                pszSchemaName, pszTableName );
+
+            if( !oStatement.ExecuteSQL() )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                                "Failed to set identity insert on layer, %s.",
+                                poDS->GetSession()->GetLastError());
+            }
+        }
+    }
+
+    if( hDBCBCP!=NULL ) 
+    {
+        CPLDebug( "ODBC", "SQLDisconnect()" );
+        SQLDisconnect( hDBCBCP );
+        SQLFreeHandle( SQL_HANDLE_DBC, hDBCBCP );
+        hDBCBCP = NULL;
+    }
     
+    if( hEnvBCP!=NULL )
+    {
+        SQLFreeHandle( SQL_HANDLE_ENV, hEnvBCP );
+        hEnvBCP = NULL;
+    }
+}
+
+
+
+/************************************************************************/
+/*                            CreateFeatureBCP()                        */
+/************************************************************************/
+
+
+OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
+
+{
+    int iCol;
+    int iField = 0;
+    
+    if ( hDBCBCP == NULL )
+    {
+        nBCPCount = 0;
+
+        CPLODBCSession* poSession = poDS->GetSession();
+        
+        if (poSession->IsInTransaction())
+            poSession->CommitTransaction(); /* commit creating the table */
+
+        /* Get the column definitions for this table. */
+        if( poFeatureDefn )
+        {
+            /* need to re-create layer defn */
+            poFeatureDefn->Release();
+            poFeatureDefn = NULL;
+        }
+        GetLayerDefn();
+        if (!poFeatureDefn)
+            return OGRERR_FAILURE;
+
+        if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL && bIsIdentityFid )
+        {
+            CPLODBCStatement oStatement( poSession );
+
+            oStatement.Appendf( "SET IDENTITY_INSERT [%s].[%s] ON;",
+                                pszSchemaName, pszTableName );
+
+            if( !oStatement.ExecuteSQL() )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                                "Failed to set identity insert on layer, %s.",
+                                poDS->GetSession()->GetLastError());
+                return OGRERR_FAILURE;
+            }
+
+            bIdentityInsert = TRUE;
+        }
+
+        if ( !InitBCP( poDS->GetConnectionString() ) )
+            return OGRERR_FAILURE;
+
+        /* Initialize the bulk copy */
+        if (Failed2( bcp_init(hDBCBCP, pszTableName, NULL, NULL, DB_IN) ))
+        {
+            CloseBCP();
+            return OGRERR_FAILURE;
+        }
+
+        if (bIdentityInsert)
+        {
+            if (Failed2( bcp_control(hDBCBCP, BCPKEEPIDENTITY, (void*) TRUE )))
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                                "Failed to set identity insert bulk copy mode, %s.",
+                                poDS->GetSession()->GetLastError());    
+                return OGRERR_FAILURE;
+            }
+        }
+
+        papstBindBuffer = (BCPData**)CPLMalloc(sizeof(BCPData*) * (nRawColumns));
+
+        for( iCol = 0; iCol < nRawColumns; iCol++ )
+        {
+            papstBindBuffer[iCol] = NULL;
+            
+            if (iCol == nGeomColumnIndex)
+            {
+                papstBindBuffer[iCol] = (BCPData*)CPLMalloc(sizeof(BCPData));
+                if (Failed2( bcp_bind(hDBCBCP, NULL /* data is provided later */, 
+                    0, 0/*or any value < 8000*/, NULL, 0, SQLUDT, iCol + 1) ))
+                    return OGRERR_FAILURE;
+            }
+            else if (iCol == nFIDColumnIndex)
+            {
+                if ( !bIdentityInsert )
+                    continue;
+                /* bind fid column */
+                papstBindBuffer[iCol] = (BCPData*)CPLMalloc(sizeof(BCPData));
+                papstBindBuffer[iCol]->VarChar.nSize = SQL_VARLEN_DATA;
+
+                if (Failed2( bcp_bind(hDBCBCP, (LPCBYTE)papstBindBuffer[iCol]->VarChar.pData, 
+                    0, SQL_VARLEN_DATA, 
+                        (LPCBYTE)"", 1, SQLVARCHAR, iCol + 1) ))
+                    return OGRERR_FAILURE;
+            }
+            else if (iField < poFeatureDefn->GetFieldCount() && iCol == panFieldOrdinals[iField])
+            {
+                OGRFieldDefn* poFDefn = poFeatureDefn->GetFieldDefn(iField);
+
+                if ( poFDefn->IsIgnored() )
+                {
+                    /* set null */
+                    ++iField;
+                    continue;
+                }
+
+                int iSrcField = poFeature->GetFieldIndex(poFDefn->GetNameRef());
+                if (iSrcField < 0)
+                {
+                    ++iField;
+                    continue; /* no such field at the source */
+                }
+
+                if( poFDefn->GetType() == OFTInteger )
+                {
+                    /* int */
+                    papstBindBuffer[iCol] = (BCPData*)CPLMalloc(sizeof(BCPData));
+                    papstBindBuffer[iCol]->Integer.iIndicator = sizeof(papstBindBuffer[iCol]->Integer.Value);
+                
+                    if (Failed2( bcp_bind(hDBCBCP, (LPCBYTE)papstBindBuffer[iCol], 
+                        sizeof(papstBindBuffer[iCol]->Integer.iIndicator), sizeof(papstBindBuffer[iCol]->Integer.Value), 
+                            NULL, 0, SQLINT4, iCol + 1) ))
+                        return OGRERR_FAILURE;
+                }
+                else if( poFDefn->GetType() == OFTInteger64 )
+                {
+                    /* bigint */
+                    papstBindBuffer[iCol] = (BCPData*)CPLMalloc(sizeof(BCPData));
+                    papstBindBuffer[iCol]->VarChar.nSize = SQL_VARLEN_DATA;
+
+                    if (Failed2( bcp_bind(hDBCBCP, (LPCBYTE)papstBindBuffer[iCol]->VarChar.pData, 
+                        0, SQL_VARLEN_DATA, 
+                            (LPCBYTE)"", 1, SQLVARCHAR, iCol + 1) ))
+                        return OGRERR_FAILURE;
+                }
+                else if( poFDefn->GetType() == OFTReal )
+                {
+                    /* float */
+                    /* TODO convert to DBNUMERIC */
+                    papstBindBuffer[iCol] = (BCPData*)CPLMalloc(sizeof(BCPData));
+                    papstBindBuffer[iCol]->VarChar.nSize = SQL_VARLEN_DATA;
+
+                    if (Failed2( bcp_bind(hDBCBCP, (LPCBYTE)papstBindBuffer[iCol]->VarChar.pData, 
+                        0, SQL_VARLEN_DATA, 
+                            (LPCBYTE)"", 1, SQLVARCHAR, iCol + 1) ))
+                        return OGRERR_FAILURE;
+                }
+                else if( poFDefn->GetType() == OFTString )
+                {
+                    /* nvarchar */
+                    papstBindBuffer[iCol] = (BCPData*)CPLMalloc(sizeof(BCPData));
+                    papstBindBuffer[iCol]->VarChar.nSize = poFDefn->GetWidth();
+                    if (poFDefn->GetWidth() == 0)
+                    {
+                        if (Failed2( bcp_bind(hDBCBCP, NULL /* data is provided later */, 
+                            0, 0/*or any value < 8000*/, NULL, 0, 0, iCol + 1) ))
+                            return OGRERR_FAILURE;
+                    }
+                    else
+                    {
+                        if (Failed2( bcp_bind(hDBCBCP, (LPCBYTE)papstBindBuffer[iCol], 
+                            sizeof(papstBindBuffer[iCol]->VarChar.nSize), poFDefn->GetWidth(), 
+                                NULL, 0, SQLNVARCHAR, iCol + 1) ))
+                            return OGRERR_FAILURE;
+                    }
+                }
+                else if( poFDefn->GetType() == OFTDate )
+                {
+                    /* date */
+                    papstBindBuffer[iCol] = (BCPData*)CPLMalloc(sizeof(BCPData));
+                    papstBindBuffer[iCol]->VarChar.nSize = SQL_VARLEN_DATA;
+
+                    if (Failed2( bcp_bind(hDBCBCP, (LPCBYTE)papstBindBuffer[iCol]->VarChar.pData, 
+                        0, SQL_VARLEN_DATA, 
+                            (LPCBYTE)"", 1, SQLVARCHAR, iCol + 1) ))
+                        return OGRERR_FAILURE;
+                }
+                else if( poFDefn->GetType() == OFTTime )
+                {
+                    /* time(7) */
+                    papstBindBuffer[iCol] = (BCPData*)CPLMalloc(sizeof(BCPData));
+                    papstBindBuffer[iCol]->VarChar.nSize = SQL_VARLEN_DATA;
+
+                    if (Failed2( bcp_bind(hDBCBCP, (LPCBYTE)papstBindBuffer[iCol]->VarChar.pData, 
+                        0, SQL_VARLEN_DATA, 
+                            (LPCBYTE)"", 1, SQLVARCHAR, iCol + 1) ))
+                        return OGRERR_FAILURE;
+                }
+                else if( poFDefn->GetType() == OFTDateTime )
+                {
+                    /* datetime */
+                    papstBindBuffer[iCol] = (BCPData*)CPLMalloc(sizeof(BCPData));
+                    papstBindBuffer[iCol]->VarChar.nSize = SQL_VARLEN_DATA;
+
+                    if (Failed2( bcp_bind(hDBCBCP, (LPCBYTE)papstBindBuffer[iCol]->VarChar.pData, 
+                        0, SQL_VARLEN_DATA, 
+                            (LPCBYTE)"", 1, SQLVARCHAR, iCol + 1) ))
+                        return OGRERR_FAILURE;
+                }
+                else if( poFDefn->GetType() == OFTBinary )
+                {
+                    /* image */
+                    papstBindBuffer[iCol] = (BCPData*)CPLMalloc(sizeof(BCPData));
+                    if (Failed2( bcp_bind(hDBCBCP, NULL /* data is provided later */, 
+                        0, 0/*or any value < 8000*/, NULL, 0, 0, iCol + 1) ))
+                        return OGRERR_FAILURE;
+                }
+                else
+                {
+                    CPLError( CE_Failure, CPLE_NotSupported,
+                              "Filed %s with type %s is not supported for bulk insert.",
+                              poFDefn->GetNameRef(),
+                              OGRFieldDefn::GetFieldTypeName(poFDefn->GetType()) );
+
+                    return OGRERR_FAILURE;
+                }
+
+                ++iField;
+            }
+        }
+    }
+
+    /* do bulk insert here */
+
+    /* prepare data to variables */
+    iField = 0;
+    for( iCol = 0; iCol < nRawColumns; iCol++ )
+    {
+        if (iCol == nGeomColumnIndex)
+        {
+            if (poFeature->GetGeometryRef())
+            {
+                /* prepare geometry */
+                OGRMSSQLGeometryValidator oValidator(poFeature->GetGeometryRef());
+                OGRGeometry *poGeom = oValidator.GetValidGeometryRef();
+
+                OGRMSSQLGeometryWriter poWriter(poGeom, nGeomColumnType, nSRSId);
+                papstBindBuffer[iCol]->RawData.nSize = poWriter.GetDataLen();
+                papstBindBuffer[iCol]->RawData.pData = (GByte *) CPLMalloc(papstBindBuffer[iCol]->RawData.nSize + 1);
+                if (poWriter.WriteSqlGeometry(papstBindBuffer[iCol]->RawData.pData, papstBindBuffer[iCol]->RawData.nSize) != OGRERR_NONE)
+                    return OGRERR_FAILURE;
+
+                /* set data length */
+                if (Failed2( bcp_collen( hDBCBCP, papstBindBuffer[iCol]->RawData.nSize, iCol + 1) ))
+                    return OGRERR_FAILURE;
+            }
+            else
+            {
+                /* set NULL */
+                papstBindBuffer[iCol]->RawData.nSize = SQL_NULL_DATA;
+                if (Failed2( bcp_collen( hDBCBCP, SQL_NULL_DATA, iCol + 1) ))
+                    return OGRERR_FAILURE;
+            }
+        }
+        else if (iCol == nFIDColumnIndex)
+        {
+            if ( !bIdentityInsert )
+                    continue;
+            
+            GIntBig nFID = poFeature->GetFID();
+            if ( nFID == OGRNullFID )
+            {
+                papstBindBuffer[iCol]->VarChar.nSize = SQL_NULL_DATA;
+                /* set NULL */
+                if (Failed2( bcp_collen( hDBCBCP, SQL_NULL_DATA, iCol + 1) ))
+                    return OGRERR_FAILURE;
+            }
+            else
+            {
+                papstBindBuffer[iCol]->VarChar.nSize = SQL_VARLEN_DATA;
+                snprintf((char*)papstBindBuffer[iCol]->VarChar.pData, 8000, CPL_FRMT_GIB, nFID);
+
+                if (Failed2( bcp_collen( hDBCBCP, SQL_VARLEN_DATA, iCol + 1) ))
+                    return OGRERR_FAILURE;
+            }
+        }
+        else if (iField < poFeatureDefn->GetFieldCount() && iCol == panFieldOrdinals[iField])
+        {
+            OGRFieldDefn* poFDefn = poFeatureDefn->GetFieldDefn(iField);
+
+            if (papstBindBuffer[iCol] == NULL)
+            {
+                ++iField;
+                continue; /* column requires no data */
+            }
+
+            if( poFDefn->GetType() == OFTInteger )
+            {
+                /* int */
+                if (!poFeature->IsFieldSet( iField ))
+                    papstBindBuffer[iCol]->Integer.iIndicator = SQL_NULL_DATA;
+                else
+                {
+                    papstBindBuffer[iCol]->Integer.iIndicator = sizeof(papstBindBuffer[iCol]->Integer.Value);
+                    papstBindBuffer[iCol]->Integer.Value = poFeature->GetFieldAsInteger(iField);
+                }
+            }
+            else if( poFDefn->GetType() == OFTInteger64 )
+            {
+                /* bigint */
+                if (!poFeature->IsFieldSet( iField ))
+                {
+                    papstBindBuffer[iCol]->VarChar.nSize = SQL_NULL_DATA;
+                    /* set NULL */
+                    if (Failed2( bcp_collen( hDBCBCP, SQL_NULL_DATA, iCol + 1) ))
+                        return OGRERR_FAILURE;
+                }
+                else
+                {
+                    papstBindBuffer[iCol]->VarChar.nSize = SQL_VARLEN_DATA;
+                    snprintf((char*)papstBindBuffer[iCol]->VarChar.pData, 8000, "%s", poFeature->GetFieldAsString(iField));
+
+                    if (Failed2( bcp_collen( hDBCBCP, SQL_VARLEN_DATA, iCol + 1) ))
+                        return OGRERR_FAILURE;
+                }
+            }
+            else if( poFDefn->GetType() == OFTReal )
+            {
+                /* float */
+                if (!poFeature->IsFieldSet( iField ))
+                {
+                    papstBindBuffer[iCol]->VarChar.nSize = SQL_NULL_DATA;
+                    /* set NULL */
+                    if (Failed2( bcp_collen( hDBCBCP, SQL_NULL_DATA, iCol + 1) ))
+                        return OGRERR_FAILURE;
+                }
+                else
+                {
+                    papstBindBuffer[iCol]->VarChar.nSize = SQL_VARLEN_DATA;
+                    snprintf((char*)papstBindBuffer[iCol]->VarChar.pData, 8000, "%s", poFeature->GetFieldAsString(iField));
+
+                    if (Failed2( bcp_collen( hDBCBCP, SQL_VARLEN_DATA, iCol + 1) ))
+                        return OGRERR_FAILURE;
+                }
+            }
+            else if( poFDefn->GetType() == OFTString )
+            {
+                /* nvarchar */
+                if (poFDefn->GetWidth() != 0)
+                {
+                    if (!poFeature->IsFieldSet( iField ))
+                    {
+                        papstBindBuffer[iCol]->VarChar.nSize = SQL_NULL_DATA;
+                        if (Failed2( bcp_collen( hDBCBCP, SQL_NULL_DATA, iCol + 1) ))
+                            return OGRERR_FAILURE;
+                    }
+                    else
+                    {
+                    
+                        papstBindBuffer[iCol]->VarChar.nSize = CPLStrlenUTF8(poFeature->GetFieldAsString(iField)) * 2;
+                        wchar_t* buffer = CPLRecodeToWChar( poFeature->GetFieldAsString(iField), CPL_ENC_UTF8, CPL_ENC_UCS2);
+                        memcpy(papstBindBuffer[iCol]->VarChar.pData, buffer, papstBindBuffer[iCol]->VarChar.nSize + 2);
+                        CPLFree(buffer);
+
+                        if (Failed2( bcp_collen( hDBCBCP, papstBindBuffer[iCol]->VarChar.nSize, iCol + 1) ))
+                            return OGRERR_FAILURE;
+                    }
+                }
+            }
+            else if( poFDefn->GetType() == OFTDate )
+            {
+                /* date */
+                if (!poFeature->IsFieldSet( iField ))
+                {
+                    papstBindBuffer[iCol]->VarChar.nSize = SQL_NULL_DATA;
+                    /* set NULL */
+                    if (Failed2( bcp_collen( hDBCBCP, SQL_NULL_DATA, iCol + 1) ))
+                        return OGRERR_FAILURE;
+                }
+                else
+                {
+                    int	pnYear;
+                    int pnMonth;
+                    int pnDay;
+                    int pnHour;
+                    int pnMinute;
+                    float pfSecond;
+                    int pnTZFlag;
+
+                    poFeature->GetFieldAsDateTime(iField, &pnYear, &pnMonth, &pnDay, 
+                        &pnHour, &pnMinute, &pfSecond, &pnTZFlag);
+                
+                    papstBindBuffer[iCol]->VarChar.nSize = SQL_VARLEN_DATA;
+                    snprintf((char*)papstBindBuffer[iCol]->VarChar.pData, 8000, "%4d-%02d-%02d %02d:%02d:%06.3f", pnYear, pnMonth, pnDay, pnHour, pnMinute, pfSecond);
+                    if (Failed2( bcp_collen( hDBCBCP, SQL_VARLEN_DATA, iCol + 1) ))
+                        return OGRERR_FAILURE;
+                }
+            }
+            else if( poFDefn->GetType() == OFTTime )
+            {
+                /* time(7) */
+                if (!poFeature->IsFieldSet( iField ))
+                {
+                    papstBindBuffer[iCol]->VarChar.nSize = SQL_NULL_DATA;
+                    /* set NULL */
+                    if (Failed2( bcp_collen( hDBCBCP, SQL_NULL_DATA, iCol + 1) ))
+                        return OGRERR_FAILURE;
+                }
+                else
+                {
+                    int	pnYear;
+                    int pnMonth;
+                    int pnDay;
+                    int pnHour;
+                    int pnMinute;
+                    float pfSecond;
+                    int pnTZFlag;
+
+                    poFeature->GetFieldAsDateTime(iField, &pnYear, &pnMonth, &pnDay, 
+                        &pnHour, &pnMinute, &pfSecond, &pnTZFlag);
+                
+                    papstBindBuffer[iCol]->VarChar.nSize = SQL_VARLEN_DATA;
+                    snprintf((char*)papstBindBuffer[iCol]->VarChar.pData, 8000, "%4d-%02d-%02d %02d:%02d:%06.3f", pnYear, pnMonth, pnDay, pnHour, pnMinute, pfSecond);
+                    if (Failed2( bcp_collen( hDBCBCP, SQL_VARLEN_DATA, iCol + 1) ))
+                        return OGRERR_FAILURE;
+                }              
+            }
+            else if( poFDefn->GetType() == OFTDateTime )
+            {
+                /* datetime */
+                if (!poFeature->IsFieldSet( iField ))
+                {
+                    papstBindBuffer[iCol]->VarChar.nSize = SQL_NULL_DATA;
+                    /* set NULL */
+                    if (Failed2( bcp_collen( hDBCBCP, SQL_NULL_DATA, iCol + 1) ))
+                        return OGRERR_FAILURE;
+                }
+                else
+                {
+                    int	pnYear;
+                    int pnMonth;
+                    int pnDay;
+                    int pnHour;
+                    int pnMinute;
+                    float pfSecond;
+                    int pnTZFlag;
+
+                    poFeature->GetFieldAsDateTime(iField, &pnYear, &pnMonth, &pnDay, 
+                        &pnHour, &pnMinute, &pfSecond, &pnTZFlag);
+                
+                    papstBindBuffer[iCol]->VarChar.nSize = SQL_VARLEN_DATA;
+                    snprintf((char*)papstBindBuffer[iCol]->VarChar.pData, 8000, "%4d-%02d-%02d %02d:%02d:%06.3f", pnYear, pnMonth, pnDay, pnHour, pnMinute, pfSecond);
+
+                    if (Failed2( bcp_collen( hDBCBCP, SQL_VARLEN_DATA, iCol + 1) ))
+                        return OGRERR_FAILURE;
+                }              
+            }
+            else if( poFDefn->GetType() == OFTBinary )
+            {
+                if (!poFeature->IsFieldSet( iField ))
+                {
+                    papstBindBuffer[iCol]->RawData.nSize = SQL_NULL_DATA;
+                    /* set NULL */
+                    if (Failed2( bcp_collen( hDBCBCP, SQL_NULL_DATA, iCol + 1) ))
+                        return OGRERR_FAILURE;
+                }
+                else
+                {
+                    /* image */
+                    papstBindBuffer[iCol]->RawData.pData = poFeature->GetFieldAsBinary(iField, &papstBindBuffer[iCol]->RawData.nSize);
+                
+                    /* set data length */
+                    if (Failed2( bcp_collen( hDBCBCP, papstBindBuffer[iCol]->RawData.nSize, iCol + 1) ))
+                        return OGRERR_FAILURE;
+                }
+            }
+            else
+            {
+                CPLError( CE_Failure, CPLE_NotSupported,
+                            "Filed %s with type %s is not supported for bulk insert.",
+                            poFDefn->GetNameRef(),
+                            OGRFieldDefn::GetFieldTypeName(poFDefn->GetType()) );
+
+                return OGRERR_FAILURE;
+            }
+
+            ++iField;
+        }
+    }
+
+    /* send row */
+    if (Failed2( bcp_sendrow( hDBCBCP ) ))
+        return OGRERR_FAILURE;
+
+    /* send dynamic data */
+    iField = 0;
+    for( iCol = 0; iCol < nRawColumns; iCol++ )
+    {
+        if (iCol == nGeomColumnIndex)
+        {
+            if (papstBindBuffer[iCol]->RawData.nSize != SQL_NULL_DATA)
+            {
+                if (Failed2( bcp_moretext( hDBCBCP, 
+                    papstBindBuffer[iCol]->RawData.nSize,  
+                    papstBindBuffer[iCol]->RawData.pData ) ))
+                {
+                
+                }
+                CPLFree(papstBindBuffer[iCol]->RawData.pData);
+                if (Failed2( bcp_moretext( hDBCBCP, 0, NULL) ))
+                {
+                
+                }
+            }
+            else
+            {
+                if (Failed2( bcp_moretext( hDBCBCP, SQL_NULL_DATA, NULL) ))
+                {
+                
+                }
+            }
+        }
+        else if (iCol == nFIDColumnIndex)
+        {
+            /* TODO */
+            continue;
+        }
+        else if (iField < poFeatureDefn->GetFieldCount() && iCol == panFieldOrdinals[iField])
+        {
+            OGRFieldDefn* poFDefn = poFeatureDefn->GetFieldDefn(iField);
+
+            if( poFDefn->GetType() == OFTString )
+            {
+                if (poFDefn->GetWidth() == 0)
+                {
+                    if (poFeature->IsFieldSet( iField ))
+                    {
+                        papstBindBuffer[iCol]->VarChar.nSize = CPLStrlenUTF8(poFeature->GetFieldAsString(iField)) * 2;
+                        if (papstBindBuffer[iCol]->VarChar.nSize > 0)
+                        {
+                            wchar_t* buffer = CPLRecodeToWChar( poFeature->GetFieldAsString(iField), CPL_ENC_UTF8, CPL_ENC_UCS2);                       
+                            if (Failed2( bcp_moretext( hDBCBCP, 
+                                papstBindBuffer[iCol]->VarChar.nSize,  
+                                (LPCBYTE)buffer ) ))
+                            {
+                
+                            }
+
+                            CPLFree(buffer);
+                        }
+
+                        if (Failed2( bcp_moretext( hDBCBCP, 0, NULL) ))
+                        {
+                
+                        }
+                    }
+                    else
+                    {
+                        if (Failed2( bcp_moretext( hDBCBCP, SQL_NULL_DATA, NULL) ))
+                        {
+                
+                        }
+                    }
+                }
+            }
+            else if ( poFDefn->GetType() == OFTBinary )
+            {
+                if (papstBindBuffer[iCol]->RawData.nSize != SQL_NULL_DATA)
+                {
+                    if (papstBindBuffer[iCol]->RawData.nSize > 0)
+                    {
+                        if (Failed2( bcp_moretext( hDBCBCP, 
+                            papstBindBuffer[iCol]->RawData.nSize,  
+                            papstBindBuffer[iCol]->RawData.pData ) ))
+                        {
+                
+                        }
+                    }
+                    if (Failed2( bcp_moretext( hDBCBCP, 0, NULL) ))
+                    {
+                
+                    }
+                }
+                else
+                {
+                    if (Failed2( bcp_moretext( hDBCBCP, SQL_NULL_DATA, NULL) ))
+                    {
+                
+                    }
+                }
+            }
+            ++iField;
+        }
+    }
+
+    if (++nBCPCount >= nBCPSize)
+    {
+        /* commit */
+        int nRecNum = bcp_batch( hDBCBCP );
+        if (nRecNum == -1)
+            Failed2(nRecNum);
+        
+        nBCPCount = 0;
+    }
+
     return OGRERR_NONE;
 }
+#endif /* MSSQL_BCP_SUPPORTED */
 
 /************************************************************************/
 /*                           ICreateFeature()                            */
@@ -1135,14 +1947,24 @@ OGRErr OGRMSSQLSpatialTableLayer::ICreateFeature( OGRFeature *poFeature )
                   "NULL pointer to OGRFeature passed to CreateFeature()." );
         return OGRERR_FAILURE;
     }
+
+#if (ODBCVER >= 0x0300) && defined(MSSQL_BCP_SUPPORTED)
+    if (bUseCopy)
+    {
+        return CreateFeatureBCP( poFeature );
+    }
+#endif
     
     ClearStatement();
 
-    CPLODBCStatement oStatement( poDS->GetSession() );
+    CPLODBCSession* poSession = poDS->GetSession();
+
+    /* the fid values are retrieved from the source layer */
+    CPLODBCStatement oStatement( poSession );
 
-    /* the fid values are retieved from the source layer */
     if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL && bIsIdentityFid )
-        oStatement.Appendf("SET IDENTITY_INSERT [%s].[%s] ON;", pszSchemaName, pszTableName );
+        oStatement.Appendf( "SET IDENTITY_INSERT [%s].[%s] ON;",
+                            pszSchemaName, pszTableName );
 
 /* -------------------------------------------------------------------- */
 /*      Form the INSERT command.                                        */
@@ -1153,10 +1975,11 @@ OGRErr OGRMSSQLSpatialTableLayer::ICreateFeature( OGRFeature *poFeature )
     OGRMSSQLGeometryValidator oValidator(poFeature->GetGeometryRef());
     OGRGeometry *poGeom = oValidator.GetValidGeometryRef();
 
+    GIntBig nFID = poFeature->GetFID();
     if (poFeature->GetGeometryRef() != poGeom)
     {
         CPLError( CE_Warning, CPLE_NotSupported,
-                  "Geometry with FID = " CPL_FRMT_GIB " has been modified.", poFeature->GetFID() );
+                  "Geometry with FID = " CPL_FRMT_GIB " has been modified.", nFID );
     }
 
     int bNeedComma = FALSE;
@@ -1169,18 +1992,18 @@ OGRErr OGRMSSQLSpatialTableLayer::ICreateFeature( OGRFeature *poFeature )
         bNeedComma = TRUE;
     }
 
-    if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
+    if( nFID != OGRNullFID && pszFIDColumn != NULL )
     {
-        if( (GIntBig)(int)poFeature->GetFID() != poFeature->GetFID() &&
+        if( !CPL_INT64_FITS_ON_INT32(nFID) &&
             GetMetadataItem(OLMD_FID64) == NULL )
         {
             /* MSSQL server doesn't support modifying pk columns without recreating the field */
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                   "Failed to create feature with large integer fid. "
                   "The FID64 layer creation option should be used." );
             return OGRERR_FAILURE;
         }
-        
+
         if (bNeedComma)
             oStatement.Appendf( ", [%s]", pszFIDColumn );
         else
@@ -1189,11 +2012,14 @@ OGRErr OGRMSSQLSpatialTableLayer::ICreateFeature( OGRFeature *poFeature )
             bNeedComma = TRUE;
         }
     }
-  
+
     int nFieldCount = poFeatureDefn->GetFieldCount();
 
     int bind_num = 0;
     void** bind_buffer = (void**)CPLMalloc(sizeof(void*) * (nFieldCount + 1));
+#ifdef SQL_SS_UDT
+    int* bind_datalen = (int*)CPLMalloc(sizeof(int) * (nFieldCount + 1));
+#endif
     
     int i;
     for( i = 0; i < nFieldCount; i++ )
@@ -1210,6 +2036,7 @@ OGRErr OGRMSSQLSpatialTableLayer::ICreateFeature( OGRFeature *poFeature )
         }
     }
 
+    SQLLEN nWKBLenBindParameter;
     if (oStatement.GetCommand()[strlen(oStatement.GetCommand()) - 1] != ']')
     {
         /* no fields were added */
@@ -1223,17 +2050,61 @@ OGRErr OGRMSSQLSpatialTableLayer::ICreateFeature( OGRFeature *poFeature )
         bNeedComma = FALSE;
         if(poGeom != NULL && pszGeomColumn != NULL)
         {
-            if (nUploadGeometryFormat == MSSQLGEOMETRY_WKB)
+            if (nUploadGeometryFormat == MSSQLGEOMETRY_NATIVE)
+            {
+#ifdef SQL_SS_UDT
+                OGRMSSQLGeometryWriter poWriter(poGeom, nGeomColumnType, nSRSId);
+                bind_datalen[bind_num] = poWriter.GetDataLen();
+                GByte *pabyData = (GByte *) CPLMalloc(bind_datalen[bind_num] + 1);
+                if (poWriter.WriteSqlGeometry(pabyData, bind_datalen[bind_num]) == OGRERR_NONE)
+                {
+                    SQLHANDLE ipd;
+                    if ((!poSession->Failed( SQLBindParameter(oStatement.GetStatement(), (SQLUSMALLINT)(bind_num + 1), 
+                        SQL_PARAM_INPUT, SQL_C_BINARY, SQL_SS_UDT,
+                        SQL_SS_LENGTH_UNLIMITED, 0, (SQLPOINTER)pabyData, bind_datalen[bind_num], (SQLLEN*)&bind_datalen[bind_num])))
+                        && (!poSession->Failed(SQLGetStmtAttr(oStatement.GetStatement(), SQL_ATTR_IMP_PARAM_DESC, &ipd, 0, 0)))
+                        && (!poSession->Failed(SQLSetDescField(ipd, 1, SQL_CA_SS_UDT_TYPE_NAME, 
+                            (nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY? "geography" : "geometry"), SQL_NTS))))
+                    {
+                        oStatement.Append( "?" );   
+                        bind_buffer[bind_num] = pabyData;
+                        ++bind_num;
+                    }
+                    else
+                    {
+                        oStatement.Append( "null" );
+                        CPLFree(pabyData);
+                    }       
+                }
+                else
+                {
+                    oStatement.Append( "null" );
+                    CPLFree(pabyData);
+                }
+#else
+                CPLError( CE_Failure, CPLE_AppDefined,
+                  "Native geometry upload is not supported" );
+
+                for( i = 0; i < bind_num; i++ )
+                    CPLFree(bind_buffer[i]);
+                CPLFree(bind_buffer);
+
+                return OGRERR_FAILURE;
+#endif
+                //CPLFree(pabyData);
+            }
+            else if (nUploadGeometryFormat == MSSQLGEOMETRY_WKB)
             {
                 int nWKBLen = poGeom->WkbSize();
                 GByte *pabyWKB = (GByte *) CPLMalloc(nWKBLen + 1);
-        
-                if( poGeom->exportToWkb( wkbNDR, pabyWKB ) == OGRERR_NONE && (nGeomColumnType == MSSQLCOLTYPE_GEOMETRY 
+
+                if( poGeom->exportToWkb( wkbNDR, pabyWKB ) == OGRERR_NONE && (nGeomColumnType == MSSQLCOLTYPE_GEOMETRY
                     || nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY))
                 {
-                    int nRetCode = SQLBindParameter(oStatement.GetStatement(), (SQLUSMALLINT)(bind_num + 1), 
-                        SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY, 
-                        nWKBLen, 0, (SQLPOINTER)pabyWKB, nWKBLen, (SQLLEN*)&nWKBLen);
+                    nWKBLenBindParameter = nWKBLen;
+                    int nRetCode = SQLBindParameter(oStatement.GetStatement(), (SQLUSMALLINT)(bind_num + 1),
+                        SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY,
+                        nWKBLen, 0, (SQLPOINTER)pabyWKB, nWKBLen, &nWKBLenBindParameter);
                     if ( nRetCode == SQL_SUCCESS || nRetCode == SQL_SUCCESS_WITH_INFO )
                     {
                         if (nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY)
@@ -1245,7 +2116,7 @@ OGRErr OGRMSSQLSpatialTableLayer::ICreateFeature( OGRFeature *poFeature )
                         {
                             oStatement.Append( "geometry::STGeomFromWKB(?" );
                             oStatement.Appendf(",%d).MakeValid()", nSRSId );
-                        }    
+                        }
                         bind_buffer[bind_num] = pabyWKB;
                         ++bind_num;
                     }
@@ -1253,7 +2124,7 @@ OGRErr OGRMSSQLSpatialTableLayer::ICreateFeature( OGRFeature *poFeature )
                     {
                         oStatement.Append( "null" );
                         CPLFree(pabyWKB);
-                    }           
+                    }
                 }
                 else
                 {
@@ -1264,15 +2135,15 @@ OGRErr OGRMSSQLSpatialTableLayer::ICreateFeature( OGRFeature *poFeature )
             else if (nUploadGeometryFormat == MSSQLGEOMETRY_WKT)
             {
                 char    *pszWKT = NULL;
-                if( poGeom->exportToWkt( &pszWKT ) == OGRERR_NONE && (nGeomColumnType == MSSQLCOLTYPE_GEOMETRY 
+                if( poGeom->exportToWkt( &pszWKT ) == OGRERR_NONE && (nGeomColumnType == MSSQLCOLTYPE_GEOMETRY
                     || nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY))
                 {
                     size_t nLen = 0;
                     while(pszWKT[nLen] != '\0')
                         nLen ++;
-                
-                    int nRetCode = SQLBindParameter(oStatement.GetStatement(), (SQLUSMALLINT)(bind_num + 1), 
-                        SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, 
+
+                    int nRetCode = SQLBindParameter(oStatement.GetStatement(), (SQLUSMALLINT)(bind_num + 1),
+                        SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR,
                         nLen, 0, (SQLPOINTER)pszWKT, 0, NULL);
                     if ( nRetCode == SQL_SUCCESS || nRetCode == SQL_SUCCESS_WITH_INFO )
                     {
@@ -1285,7 +2156,7 @@ OGRErr OGRMSSQLSpatialTableLayer::ICreateFeature( OGRFeature *poFeature )
                         {
                             oStatement.Append( "geometry::STGeomFromText(?" );
                             oStatement.Appendf(",%d).MakeValid()", nSRSId );
-                        }    
+                        }
                         bind_buffer[bind_num] = pszWKT;
                         ++bind_num;
                     }
@@ -1293,7 +2164,7 @@ OGRErr OGRMSSQLSpatialTableLayer::ICreateFeature( OGRFeature *poFeature )
                     {
                         oStatement.Append( "null" );
                         CPLFree(pszWKT);
-                    }           
+                    }
                 }
                 else
                 {
@@ -1308,13 +2179,13 @@ OGRErr OGRMSSQLSpatialTableLayer::ICreateFeature( OGRFeature *poFeature )
         }
 
         /* Set the FID */
-        if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
+        if( nFID != OGRNullFID && pszFIDColumn != NULL )
         {
             if (bNeedComma)
-                oStatement.Appendf( ", " CPL_FRMT_GIB, poFeature->GetFID() );
+                oStatement.Appendf( ", " CPL_FRMT_GIB, nFID );
             else
             {
-                oStatement.Appendf( CPL_FRMT_GIB, poFeature->GetFID() );
+                oStatement.Appendf( CPL_FRMT_GIB, nFID );
                 bNeedComma = TRUE;
             }
         }
@@ -1335,17 +2206,17 @@ OGRErr OGRMSSQLSpatialTableLayer::ICreateFeature( OGRFeature *poFeature )
         oStatement.Append( ");" );
     }
 
-    if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL && bIsIdentityFid )
+    if( nFID != OGRNullFID && pszFIDColumn != NULL && bIsIdentityFid )
         oStatement.Appendf("SET IDENTITY_INSERT [%s].[%s] OFF;", pszSchemaName, pszTableName );
 
 /* -------------------------------------------------------------------- */
 /*      Execute the insert.                                             */
 /* -------------------------------------------------------------------- */
-    
+
     if( !oStatement.ExecuteSQL() )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "INSERT command for new feature failed. %s", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "INSERT command for new feature failed. %s",
                    poDS->GetSession()->GetLastError() );
 
         for( i = 0; i < bind_num; i++ )
@@ -1418,7 +2289,7 @@ void OGRMSSQLSpatialTableLayer::AppendFieldValue(CPLODBCStatement *poStatement,
     // Check if date is NULL: 0000-00-00
     if( nOGRFieldType == OFTDate )
     {
-        if( EQUALN( pszStrValue, "0000", 4 ) )
+        if( STARTS_WITH_CI(pszStrValue, "0000") )
         {
             pszStrValue = "null";
             bIsDateNull = TRUE;
@@ -1438,9 +2309,22 @@ void OGRMSSQLSpatialTableLayer::AppendFieldValue(CPLODBCStatement *poStatement,
         {
             // bind UTF8 as unicode parameter
             wchar_t* buffer = CPLRecodeToWChar( pszStrValue, CPL_ENC_UTF8, CPL_ENC_UCS2);
-            int nRetCode = SQLBindParameter(poStatement->GetStatement(), (SQLUSMALLINT)((*bind_num) + 1), 
-                SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WVARCHAR, 
-                wcslen(buffer) + 1, 0, (SQLPOINTER)buffer, 0, NULL);
+            size_t nLen = wcslen(buffer) + 1;
+            if (nLen > 4000)
+            {
+                /* need to handle nvarchar(max) */
+#ifdef SQL_SS_LENGTH_UNLIMITED
+                nLen = SQL_SS_LENGTH_UNLIMITED;
+#else
+                /* for older drivers truncate the data to 4000 chars */
+                buffer[4000] = 0;
+                nLen = 4000;
+                CPLError( CE_Warning, CPLE_AppDefined,
+                          "String data truncation applied on field: %s. Use a more recent ODBC driver that supports handling large string values.", poFeatureDefn->GetFieldDefn(i)->GetNameRef() );
+#endif
+            }
+            int nRetCode = SQLBindParameter(poStatement->GetStatement(), (SQLUSMALLINT)((*bind_num) + 1),
+                SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WVARCHAR, nLen, 0, (SQLPOINTER)buffer, 0, NULL);
             if ( nRetCode == SQL_SUCCESS || nRetCode == SQL_SUCCESS_WITH_INFO )
             {
                 poStatement->Append( "?" );
diff --git a/ogr/ogrsf_frmts/mysql/drv_mysql.html b/ogr/ogrsf_frmts/mysql/drv_mysql.html
index a5d4a51..4754ef6 100644
--- a/ogr/ogrsf_frmts/mysql/drv_mysql.html
+++ b/ogr/ogrsf_frmts/mysql/drv_mysql.html
@@ -7,13 +7,13 @@
 
 <h1>MySQL</h1>
 
-This driver implements read and write access for spatial data in 
-<a href="http://www.mysql.org/">MySQL</a> tables.  This functionality 
+This driver implements read and write access for spatial data in
+<a href="http://www.mysql.org/">MySQL</a> tables.  This functionality
 was introduced in GDAL/OGR 1.3.2.  <p>
 
 When opening a database, it's name should be specified in the form
-"MYSQL:dbname[,options]" where the options can include comma seperated
-items like "user=*userid*", "password=*password*", "host=*host*" and 
+"MYSQL:dbname[,options]" where the options can include comma separated
+items like "user=*userid*", "password=*password*", "host=*host*" and
 "port=*port*".<p>
 
 As well, a "tables=*table*;*table*..." option can be
@@ -25,68 +25,68 @@ Currently all regular user tables are assumed to be layers from an OGR
 point of view, with the table names as the layer names.  Named views are
 not currently supported.<p>
 
-If a single integer field is a primary key, it will be used as the FID 
+If a single integer field is a primary key, it will be used as the FID
 otherwise the FID will be assigned sequentially, and fetches by FID will
 be extremely slow. <p>
 
 <p>By default, SQL statements are passed directly to the MySQL database engine.
-It's also possible to request the driver to handle SQL commands 
-with <a href="/ogr/ogr_sql.html">OGR SQL</a> engine, 
-by passing <strong>"OGRSQL"</strong> string to the ExecuteSQL() 
+It's also possible to request the driver to handle SQL commands
+with <a href="ogr_sql.html">OGR SQL</a> engine,
+by passing <strong>"OGRSQL"</strong> string to the ExecuteSQL()
 method, as name of the SQL dialect.</p>
- 
+
 <h2>Caveats</h2>
 <ul>
     <li>
         In the case of a layer defined by a SQL statement, fields either named
-        "OGC_FID" or those that are defined as NOT NULL, are a PRIMARY KEY, and 
+        "OGC_FID" or those that are defined as NOT NULL, are a PRIMARY KEY, and
         are an integer-like field will be assumed to be the FID.
     </li>
     <li>
-        Geometry fields are read from MySQL using WKB format.  Versions older 
-        than 5.0.16 of MySQL are known to have issues with some WKB 
+        Geometry fields are read from MySQL using WKB format.  Versions older
+        than 5.0.16 of MySQL are known to have issues with some WKB
         generation and may not work properly.
     </li>
     <li>
-        The OGR_FID column, which can be overridden with the MYSQL_FID layer 
-        creation option, is implemented as a 
-        <b>INT UNIQUE NOT NULL AUTO_INCREMENT</b> field.  This 
+        The OGR_FID column, which can be overridden with the MYSQL_FID layer
+        creation option, is implemented as a
+        <b>INT UNIQUE NOT NULL AUTO_INCREMENT</b> field.  This
         appears to implicitly create an index on the field.
     </li>
     <li>
-        The geometry column, which defaults to <i>SHAPE</i> and can be overridden 
-        with the GEOMETRY_NAME layer creation option, is created as a 
+        The geometry column, which defaults to <i>SHAPE</i> and can be overridden
+        with the GEOMETRY_NAME layer creation option, is created as a
         <b>NOT NULL</b> column in unless SPATIAL_INDEX is disabled.  By default
         a spatial index is created at the point the table is created.
     </li>
     <li>
-        SRS information is stored using the OGC Simple Features for SQL layout, with 
-        <i>geometry_columns</i> and <i>spatial_ref_sys</i> metadata tables being 
-        created in the specified database if they do not already exist.  The 
-        <i>spatial_ref_sys</i> table is <b>not</b> pre-populated with SRS and 
-        EPSG values like PostGIS.  If no EPSG code is found for a given table, 
+        SRS information is stored using the OGC Simple Features for SQL layout, with
+        <i>geometry_columns</i> and <i>spatial_ref_sys</i> metadata tables being
+        created in the specified database if they do not already exist.  The
+        <i>spatial_ref_sys</i> table is <b>not</b> pre-populated with SRS and
+        EPSG values like PostGIS.  If no EPSG code is found for a given table,
         the MAX(SRID) value will be used.
     </li>
 
 	<li>
 	    Connection timeouts to the server can be specified with the <b>MYSQL_TIMEOUT</b>
-	    environment variable.  For example, SET MYSQL_TIMEOUT=3600.  It is possible this 
+	    environment variable.  For example, SET MYSQL_TIMEOUT=3600.  It is possible this
 	    variable only has an impact when the OS of the MySQL server is Windows.
 	</li>
 	<li>
 	    The MySQL driver opens a connection to the database using CLIENT_INTERACTIVE mode.
-	    You can adjust this setting (interactive_timeout) in your mysql.ini or mysql.cnf 
+	    You can adjust this setting (interactive_timeout) in your mysql.ini or mysql.cnf
 	    file of your server to your liking.
 	</li>
 	<li>
-	    We are using WKT to insert geometries into the database.  
-	    If you are inserting big geometries, you will need to be aware of the <i>max_allowed_packet</i> 
-	    parameter in the MySQL configuration.  By default it is set to 1M, but this will not 
-	    be large enough for really big geometries.  If you get an error message like: 
-	    <i>Got a packet bigger than 'max_allowed_packet' bytes</i>, you will need to increase 
+	    We are using WKT to insert geometries into the database.
+	    If you are inserting big geometries, you will need to be aware of the <i>max_allowed_packet</i>
+	    parameter in the MySQL configuration.  By default it is set to 1M, but this will not
+	    be large enough for really big geometries.  If you get an error message like:
+	    <i>Got a packet bigger than 'max_allowed_packet' bytes</i>, you will need to increase
 	    this parameter.
 	</li>
-	    
+
 </ul>
 
 <h2>Creation Issues</h2>
@@ -94,12 +94,12 @@ method, as name of the SQL dialect.</p>
 The MySQL driver does not support creation of new datasets (a database
 within MySQL), but it does allow creation of new layers within an
 existing database.<P>
-    
-By default, the MySQL driver will attempt to preserve the precision 
-of OGR features when creating and reading MySQL layers.  For integer fields 
-with a specified width, it will use <b>DECIMAL</b> as the MySQL field 
-type with a specified precision of 0.  For real fields, it will use 
-<b>DOUBLE</b> with the specified width and precision. For string fields 
+
+By default, the MySQL driver will attempt to preserve the precision
+of OGR features when creating and reading MySQL layers.  For integer fields
+with a specified width, it will use <b>DECIMAL</b> as the MySQL field
+type with a specified precision of 0.  For real fields, it will use
+<b>DOUBLE</b> with the specified width and precision. For string fields
 with a specified width, <b>VARCHAR</b> will be used.<p>
 
 The MySQL driver makes no allowances for character encodings at this time.<p>
@@ -109,28 +109,28 @@ The MySQL driver is not transactional at this time.<p>
 
 
 
-    
+
 <h3>Layer Creation Options</h3>
 
 <ul>
     <li>
-        <b>OVERWRITE</b>: This may be "YES" to force an existing layer of the 
+        <b>OVERWRITE</b>: This may be "YES" to force an existing layer of the
         desired name to be destroyed before creating the requested layer.
     </li>
     <li>
-        <b>LAUNDER</b>: This may be "YES" to force new fields created on this 
-        layer to have their field names "laundered" into a form more 
-        compatible with MySQL.  This converts to lower case and converts 
-        some special characters like "-" and "#" to "_".  If "NO" exact names 
+        <b>LAUNDER</b>: This may be "YES" to force new fields created on this
+        layer to have their field names "laundered" into a form more
+        compatible with MySQL.  This converts to lower case and converts
+        some special characters like "-" and "#" to "_".  If "NO" exact names
         are preserved.  The default value is "YES".
     </li>
     <li>
-        <b>PRECISION</b>: This may be "TRUE" to attempt to preserve field 
+        <b>PRECISION</b>: This may be "TRUE" to attempt to preserve field
         widths and precisions for the creation and reading of MySQL layers.
         The default value is "TRUE".
     </li>
     <li>
-        <b>GEOMETRY_NAME</b>: This option specifies the name of the 
+        <b>GEOMETRY_NAME</b>: This option specifies the name of the
         geometry column.  The default value is "SHAPE".
     </li>
     <li>
@@ -142,17 +142,17 @@ The MySQL driver is not transactional at this time.<p>
         64 bit identifiers. The default value is "FALSE".
     </li>
     <li>
-        <b>SPATIAL_INDEX</b>: May be "NO" to stop automatic creation of 
-        a spatial index on the geometry column, allowing NULL geometries 
-        and possibly faster loading. 
+        <b>SPATIAL_INDEX</b>: May be "NO" to stop automatic creation of
+        a spatial index on the geometry column, allowing NULL geometries
+        and possibly faster loading.
     </li>
     <li>
-        <b>ENGINE</b>: Optionally specify database engine to use.  In MySQL 
+        <b>ENGINE</b>: Optionally specify database engine to use.  In MySQL
         4.x this must be set to MyISAM for spatial tables.
     </li>
 </ul>
 
-The following example datasource name opens the database schema 
+The following example datasource name opens the database schema
 <i>westholland</i> with password <i>psv9570</i> for userid <i>root</i>
 on the port <i>3306</i>.  No hostname is provided, so localhost is assumed.
 The tables= directive means that only the bedrijven table is scanned and
@@ -162,16 +162,16 @@ presented as a layer for use.<p>
 MYSQL:westholland,user=root,password=psv9570,port=3306,tables=bedrijven
 </pre>
 
-The following example uses ogr2ogr to create copy the world_borders layer 
-from a shapefile into a MySQL table.  It overwrites a table with the existing 
-name <i>borders2</i>, sets a layer creation option to specify the geometry 
+The following example uses ogr2ogr to create copy the world_borders layer
+from a shapefile into a MySQL table.  It overwrites a table with the existing
+name <i>borders2</i>, sets a layer creation option to specify the geometry
 column name to <i>SHAPE2</i>.
 
 <pre>
-ogr2ogr -f MySQL MySQL:test,user=root world_borders.shp -nln borders2 -update -overwrite -lco GEOMETRY_NAME=SHAPE2 
+ogr2ogr -f MySQL MySQL:test,user=root world_borders.shp -nln borders2 -update -overwrite -lco GEOMETRY_NAME=SHAPE2
 </pre>
 
-The following example uses ogrinfo to return some summary information about the borders2 
+The following example uses ogrinfo to return some summary information about the borders2
 layer in the test database.
 <pre>
 ogrinfo MySQL:test,user=root borders2 -so
diff --git a/ogr/ogrsf_frmts/mysql/ogr_mysql.h b/ogr/ogrsf_frmts/mysql/ogr_mysql.h
index c1d4c4d..306ee6a 100644
--- a/ogr/ogrsf_frmts/mysql/ogr_mysql.h
+++ b/ogr/ogrsf_frmts/mysql/ogr_mysql.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_mysql.h 29019 2015-04-25 20:34:19Z rouault $
+ * $Id: ogr_mysql.h 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Declarations for MySQL OGR Driver Classes.
@@ -29,12 +29,24 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_MYSQL_H_INCLUDED
-#define _OGR_MYSQL_H_INCLUDED
+#ifndef OGR_MYSQL_H_INCLUDED
+#define OGR_MYSQL_H_INCLUDED
+
+
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable : 4324 ) /* 'my_alignment_imp<0x02>' : structure was padded due to __declspec(align()) */
+#pragma warning( disable : 4201 ) /* nonstandard extension used : nameless struct/union */
+#pragma warning( disable : 4211 ) /* nonstandard extension used : redefined extern to static */
+#endif
 
 #include <my_global.h>
 #include <mysql.h>
 
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
+
 /* my_global.h from mysql 5.1 declares the min and max macros. */
 /* This conflicts with templates in g++-4.3.2 header files. Grrr */
 #ifdef min
@@ -56,7 +68,7 @@
 /************************************************************************/
 
 class OGRMySQLDataSource;
-    
+
 class OGRMySQLLayer : public OGRLayer
 {
   protected:
@@ -69,7 +81,7 @@ class OGRMySQLLayer : public OGRLayer
     GIntBig             iNextShapeId;
 
     OGRMySQLDataSource    *poDS;
- 
+
     char               *pszQueryStatement;
 
     int                 nResultOffset;
@@ -94,7 +106,7 @@ class OGRMySQLLayer : public OGRLayer
     virtual OGRFeature *GetNextFeature();
 
     virtual OGRFeature *GetFeature( GIntBig nFeatureId );
-    
+
     OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
 
     virtual OGRSpatialReference *GetSpatialRef();
@@ -126,7 +138,7 @@ class OGRMySQLTableLayer : public OGRMySQLLayer
 
     int                 bLaunderColumnNames;
     int                 bPreservePrecision;
-    
+
   public:
                         OGRMySQLTableLayer( OGRMySQLDataSource *,
                                          const char * pszName,
@@ -134,28 +146,32 @@ class OGRMySQLTableLayer : public OGRMySQLLayer
                         ~OGRMySQLTableLayer();
 
     OGRErr              Initialize(const char* pszTableName);
-    
+
     virtual OGRFeature *GetFeature( GIntBig nFeatureId );
     virtual void        ResetReading();
     virtual GIntBig     GetFeatureCount( int );
 
     void                SetSpatialFilter( OGRGeometry * );
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+                { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
 
     virtual OGRErr      SetAttributeFilter( const char * );
     virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
     virtual OGRErr      DeleteFeature( GIntBig nFID );
     virtual OGRErr      ISetFeature( OGRFeature *poFeature );
-    
+
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
                                      int bApproxOK = TRUE );
 
     void                SetLaunderFlag( int bFlag )
                                 { bLaunderColumnNames = bFlag; }
     void                SetPrecisionFlag( int bFlag )
-                                { bPreservePrecision = bFlag; }    
+                                { bPreservePrecision = bFlag; }
 
     virtual int         TestCapability( const char * );
-	virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 };
 
 /************************************************************************/
@@ -167,10 +183,10 @@ class OGRMySQLResultLayer : public OGRMySQLLayer
     void                BuildFullQueryStatement(void);
 
     char                *pszRawStatement;
-    
+
     // Layer srid.
     int                 nSRSId;
-    
+
   public:
                         OGRMySQLResultLayer( OGRMySQLDataSource *,
                                              const char * pszRawStatement,
@@ -194,25 +210,23 @@ class OGRMySQLDataSource : public OGRDataSource
 {
     OGRMySQLLayer       **papoLayers;
     int                 nLayers;
-    
+
     char               *pszName;
 
     int                 bDSUpdate;
 
-    int                 nSoftTransactionLevel;
-
     MYSQL              *hConn;
 
-    int                DeleteLayer( int iLayer );
+    OGRErr              DeleteLayer( int iLayer );
 
     // We maintain a list of known SRID to reduce the number of trips to
-    // the database to get SRSes. 
+    // the database to get SRSes.
     int                 nKnownSRID;
     int                *panSRID;
     OGRSpatialReference **papoSRS;
 
     OGRMySQLLayer      *poLongResultLayer;
-    
+
   public:
                         OGRMySQLDataSource();
                         ~OGRMySQLDataSource();
@@ -233,7 +247,7 @@ class OGRMySQLDataSource : public OGRDataSource
     int                 GetLayerCount() { return nLayers; }
     OGRLayer            *GetLayer( int );
 
-    virtual OGRLayer    *ICreateLayer( const char *, 
+    virtual OGRLayer    *ICreateLayer( const char *,
                                       OGRSpatialReference * = NULL,
                                       OGRwkbGeometryType = wkbUnknown,
                                       char ** = NULL );
@@ -249,13 +263,11 @@ class OGRMySQLDataSource : public OGRDataSource
     // nonstandard
 
     void                ReportError( const char * = NULL );
-    
+
     char               *LaunderName( const char * );
 
     void                RequestLongResult( OGRMySQLLayer * );
     void                InterruptLongResult();
 };
 
-#endif /* ndef _OGR_MYSQL_H_INCLUDED */
-
-
+#endif /* ndef OGR_MYSQL_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/mysql/ogrmysqldatasource.cpp b/ogr/ogrsf_frmts/mysql/ogrmysqldatasource.cpp
index 2b42b27..f10959e 100644
--- a/ogr/ogrsf_frmts/mysql/ogrmysqldatasource.cpp
+++ b/ogr/ogrsf_frmts/mysql/ogrmysqldatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmysqldatasource.cpp 29019 2015-04-25 20:34:19Z rouault $
+ * $Id: ogrmysqldatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMySQLDataSource class.
@@ -32,31 +32,42 @@
 
 #include <string>
 #include "ogr_mysql.h"
+
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable : 4201 ) /* nonstandard extension used : nameless struct/union */
+#endif
+#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
+#endif
 #include <my_sys.h>
+#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
+#pragma GCC diagnostic pop
+#endif
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
 
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrmysqldatasource.cpp 29019 2015-04-25 20:34:19Z rouault $");
+CPL_CVSID("$Id: ogrmysqldatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 /************************************************************************/
 /*                         OGRMySQLDataSource()                         */
 /************************************************************************/
 
-OGRMySQLDataSource::OGRMySQLDataSource()
-
-{
-    pszName = NULL;
-    papoLayers = NULL;
-    nLayers = 0;
-    hConn = 0;
-    nSoftTransactionLevel = 0;
-
-    nKnownSRID = 0;
-    panSRID = NULL;
-    papoSRS = NULL;
-
-    poLongResultLayer = NULL;
-}
+OGRMySQLDataSource::OGRMySQLDataSource() :
+    papoLayers(NULL),
+    nLayers(0),
+    pszName(NULL),
+    bDSUpdate(FALSE),
+    hConn(NULL),
+    nKnownSRID(0),
+    panSRID(NULL),
+    papoSRS(NULL),
+    poLongResultLayer(NULL)
+{ }
 
 /************************************************************************/
 /*                        ~OGRMySQLDataSource()                         */
@@ -65,21 +76,19 @@ OGRMySQLDataSource::OGRMySQLDataSource()
 OGRMySQLDataSource::~OGRMySQLDataSource()
 
 {
-    int         i;
-
     InterruptLongResult();
 
     CPLFree( pszName );
 
-    for( i = 0; i < nLayers; i++ )
+    for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
-    
+
     CPLFree( papoLayers );
 
     if( hConn != NULL )
         mysql_close( hConn );
 
-    for( i = 0; i < nKnownSRID; i++ )
+    for( int i = 0; i < nKnownSRID; i++ )
     {
         if( papoSRS[i] != NULL )
             papoSRS[i]->Release();
@@ -96,12 +105,12 @@ void OGRMySQLDataSource::ReportError( const char *pszDescription )
 
 {
     if( pszDescription )
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "MySQL error message:%s Description: %s", 
-                  mysql_error( hConn ), 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "MySQL error message:%s Description: %s",
+                  mysql_error( hConn ),
                   pszDescription );
     else
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", mysql_error( hConn ) );
 }
 
@@ -109,16 +118,16 @@ void OGRMySQLDataSource::ReportError( const char *pszDescription )
 /*                                Open()                                */
 /************************************************************************/
 
-int OGRMySQLDataSource::Open( const char * pszNewName, char** papszOpenOptions,
+int OGRMySQLDataSource::Open( const char * pszNewName, char** papszOpenOptionsIn,
                               int bUpdate )
 
 {
     CPLAssert( nLayers == 0 );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Use options process to get .my.cnf file contents.               */
 /* -------------------------------------------------------------------- */
-    int nPort = 0, i;
+    int nPort = 0;
     char **papszTableNames=NULL;
     std::string oHost, oPassword, oUser, oDB;
 
@@ -127,7 +136,7 @@ int OGRMySQLDataSource::Open( const char * pszNewName, char** papszOpenOptions,
                                       "host", "tables" };
     for(int i=0; i <(int)(sizeof(apszOpenOptions)/sizeof(char*));i++)
     {
-        const char* pszVal = CSLFetchNameValue(papszOpenOptions, apszOpenOptions[i]);
+        const char* pszVal = CSLFetchNameValue(papszOpenOptionsIn, apszOpenOptions[i]);
         if( pszVal )
         {
             if( osNewName[osNewName.size()-1] != ':' )
@@ -151,40 +160,41 @@ int OGRMySQLDataSource::Open( const char * pszNewName, char** papszOpenOptions,
                 osNewName += pszVal;
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Parse out connection information.                               */
 /* -------------------------------------------------------------------- */
-    char **papszItems = CSLTokenizeString2( osNewName+6, ",", 
+    char **papszItems = CSLTokenizeString2( osNewName+6, ",",
                                             CSLT_HONOURSTRINGS );
 
     if( CSLCount(papszItems) < 1 )
     {
         CSLDestroy( papszItems );
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "MYSQL: request missing databasename." );
         return FALSE;
     }
 
     oDB = papszItems[0];
 
-    for( i = 1; papszItems[i] != NULL; i++ )
+    for( int i = 1; papszItems[i] != NULL; i++ )
     {
-        if( EQUALN(papszItems[i],"user=",5) )
+        if( STARTS_WITH_CI(papszItems[i], "user=") )
             oUser = papszItems[i] + 5;
-        else if( EQUALN(papszItems[i],"password=",9) )
+        else if( STARTS_WITH_CI(papszItems[i], "password=") )
             oPassword = papszItems[i] + 9;
-        else if( EQUALN(papszItems[i],"host=",5) )
+        else if( STARTS_WITH_CI(papszItems[i], "host=") )
             oHost = papszItems[i] + 5;
-        else if( EQUALN(papszItems[i],"port=",5) )
+        else if( STARTS_WITH_CI(papszItems[i], "port=") )
             nPort = atoi(papszItems[i] + 5);
-        else if( EQUALN(papszItems[i],"tables=",7) )
+        else if( STARTS_WITH_CI(papszItems[i], "tables=") )
         {
-            papszTableNames = CSLTokenizeStringComplex( 
+            CSLDestroy(papszTableNames);
+            papszTableNames = CSLTokenizeStringComplex(
                 papszItems[i] + 7, ";", FALSE, FALSE );
         }
         else
-            CPLError( CE_Warning, CPLE_AppDefined, 
+            CPLError( CE_Warning, CPLE_AppDefined,
                       "'%s' in MYSQL datasource definition not recognised and ignored.", papszItems[i] );
     }
 
@@ -206,20 +216,20 @@ int OGRMySQLDataSource::Open( const char * pszNewName, char** papszOpenOptions,
 /* -------------------------------------------------------------------- */
     if( hConn )
     {
-        const char *pszTimeoutLength = 
-            CPLGetConfigOption( "MYSQL_TIMEOUT", "0" );  
-        
-        unsigned int timeout = atoi(pszTimeoutLength);        
+        const char *pszTimeoutLength =
+            CPLGetConfigOption( "MYSQL_TIMEOUT", "0" );
+
+        unsigned int timeout = atoi(pszTimeoutLength);
         mysql_options(hConn, MYSQL_OPT_CONNECT_TIMEOUT, (char*)&timeout);
 
         mysql_options(hConn, MYSQL_SET_CHARSET_NAME, "utf8" );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Perform connection.                                             */
 /* -------------------------------------------------------------------- */
     if( hConn
-        && mysql_real_connect( hConn, 
+        && mysql_real_connect( hConn,
                                oHost.length() ? oHost.c_str() : NULL,
                                oUser.length() ? oUser.c_str() : NULL,
                                oPassword.length() ? oPassword.c_str() : NULL,
@@ -227,7 +237,7 @@ int OGRMySQLDataSource::Open( const char * pszNewName, char** papszOpenOptions,
                                nPort, NULL, CLIENT_INTERACTIVE ) == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "MySQL connect failed for: %s\n%s", 
+                  "MySQL connect failed for: %s\n%s",
                   pszNewName + 6, mysql_error( hConn ) );
         mysql_close( hConn );
         hConn = NULL;
@@ -246,9 +256,9 @@ int OGRMySQLDataSource::Open( const char * pszNewName, char** papszOpenOptions,
         my_bool reconnect = 1;
         mysql_options(hConn, MYSQL_OPT_RECONNECT, &reconnect);
     }
-    
+
     pszName = CPLStrdup( pszNewName );
-    
+
     bDSUpdate = bUpdate;
 
 /* -------------------------------------------------------------------- */
@@ -271,7 +281,7 @@ int OGRMySQLDataSource::Open( const char * pszNewName, char** papszOpenOptions,
             ReportError( "mysql_store_result() failed on SHOW TABLES result.");
             return FALSE;
         }
-    
+
         while( (papszRow = mysql_fetch_row( hResultSet )) != NULL )
         {
             if( papszRow[0] == NULL )
@@ -292,17 +302,17 @@ int OGRMySQLDataSource::Open( const char * pszNewName, char** papszOpenOptions,
 /* -------------------------------------------------------------------- */
     int iRecord;
 
-    for( iRecord = 0; 
+    for( iRecord = 0;
          papszTableNames != NULL && papszTableNames[iRecord] != NULL;
          iRecord++ )
     {
-        //  FIXME: This should be fixed to deal with tables 
-        //  for which we can't open because the name is bad/ 
+        //  FIXME: This should be fixed to deal with tables
+        //  for which we can't open because the name is bad/
         OpenTable( papszTableNames[iRecord], bUpdate );
     }
 
     CSLDestroy( papszTableNames );
-    
+
     return nLayers > 0 || bUpdate;
 }
 
@@ -330,7 +340,7 @@ int OGRMySQLDataSource::OpenTable( const char *pszNewName, int bUpdate )
     papoLayers = (OGRMySQLLayer **)
         CPLRealloc( papoLayers,  sizeof(OGRMySQLLayer *) * (nLayers+1) );
     papoLayers[nLayers++] = poLayer;
-    
+
     return TRUE;
 }
 
@@ -341,11 +351,10 @@ int OGRMySQLDataSource::OpenTable( const char *pszNewName, int bUpdate )
 int OGRMySQLDataSource::TestCapability( const char * pszCap )
 
 {
-	
     if( EQUAL(pszCap, ODsCCreateLayer) )
         return TRUE;
-	if( EQUAL(pszCap, ODsCDeleteLayer))
-		return TRUE;
+    if( EQUAL(pszCap, ODsCDeleteLayer))
+        return TRUE;
     else
         return FALSE;
 }
@@ -378,7 +387,7 @@ OGRErr OGRMySQLDataSource::InitializeMetadataTables()
     const char*      pszCommand;
     MYSQL_RES       *hResult;
     OGRErr	    eErr = OGRERR_NONE;
- 
+
     pszCommand = "DESCRIBE geometry_columns";
     if( mysql_query(GetConn(), pszCommand ) )
     {
@@ -386,7 +395,7 @@ OGRErr OGRMySQLDataSource::InitializeMetadataTables()
                 "CREATE TABLE geometry_columns "
                 "( F_TABLE_CATALOG VARCHAR(256), "
                 "F_TABLE_SCHEMA VARCHAR(256), "
-                "F_TABLE_NAME VARCHAR(256) NOT NULL," 
+                "F_TABLE_NAME VARCHAR(256) NOT NULL,"
                 "F_GEOMETRY_COLUMN VARCHAR(256) NOT NULL, "
                 "COORD_DIMENSION INT, "
                 "SRID INT,"
@@ -398,17 +407,16 @@ OGRErr OGRMySQLDataSource::InitializeMetadataTables()
         }
         else
             CPLDebug("MYSQL","Creating geometry_columns metadata table");
- 
     }
- 
+
     // make sure to attempt to free results of successful queries
     hResult = mysql_store_result( GetConn() );
     if( hResult != NULL )
     {
         mysql_free_result( hResult );
-        hResult = NULL;   
+        hResult = NULL;
     }
- 
+
     pszCommand = "DESCRIBE spatial_ref_sys";
     if( mysql_query(GetConn(), pszCommand ) )
     {
@@ -425,9 +433,8 @@ OGRErr OGRMySQLDataSource::InitializeMetadataTables()
         }
         else
             CPLDebug("MYSQL","Creating spatial_ref_sys metadata table");
- 
-    }    
- 
+    }
+
     // make sure to attempt to free results of successful queries
     hResult = mysql_store_result( GetConn() );
     if( hResult != NULL )
@@ -435,7 +442,7 @@ OGRErr OGRMySQLDataSource::InitializeMetadataTables()
         mysql_free_result( hResult );
         hResult = NULL;
     }
- 
+
     return eErr;
 }
 
@@ -450,9 +457,9 @@ OGRErr OGRMySQLDataSource::InitializeMetadataTables()
 OGRSpatialReference *OGRMySQLDataSource::FetchSRS( int nId )
 {
     char         szCommand[128];
-    char           **papszRow;  
+    char           **papszRow;
     MYSQL_RES       *hResult;
-            
+
     if( nId < 0 )
         return NULL;
 
@@ -468,23 +475,23 @@ OGRSpatialReference *OGRMySQLDataSource::FetchSRS( int nId )
     }
 
     OGRSpatialReference *poSRS = NULL;
- 
+
     // make sure to attempt to free any old results
     hResult = mysql_store_result( GetConn() );
     if( hResult != NULL )
         mysql_free_result( hResult );
-    hResult = NULL;   
-                        
-    sprintf( szCommand,
+    hResult = NULL;
+
+    snprintf( szCommand, sizeof(szCommand),
          "SELECT srtext FROM spatial_ref_sys WHERE srid = %d",
          nId );
-    
+
     if( !mysql_query( GetConn(), szCommand ) )
         hResult = mysql_store_result( GetConn() );
-        
+
     char  *pszWKT = NULL;
     papszRow = NULL;
-    
+
 
     if( hResult != NULL )
         papszRow = mysql_fetch_row( hResult );
@@ -512,7 +519,7 @@ OGRSpatialReference *OGRMySQLDataSource::FetchSRS( int nId )
 /*      Add to the cache.                                               */
 /* -------------------------------------------------------------------- */
     panSRID = (int *) CPLRealloc(panSRID,sizeof(int) * (nKnownSRID+1) );
-    papoSRS = (OGRSpatialReference **) 
+    papoSRS = (OGRSpatialReference **)
         CPLRealloc(papoSRS, sizeof(void*) * (nKnownSRID + 1) );
     panSRID[nKnownSRID] = nId;
     papoSRS[nKnownSRID] = poSRS;
@@ -533,9 +540,9 @@ OGRSpatialReference *OGRMySQLDataSource::FetchSRS( int nId )
 int OGRMySQLDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 
 {
-    char           **papszRow;  
+    char           **papszRow;
     MYSQL_RES       *hResult=NULL;
-    
+
     CPLString            osCommand;
     char                *pszWKT = NULL;
     int                 nSRSId;
@@ -548,11 +555,11 @@ int OGRMySQLDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 /* -------------------------------------------------------------------- */
     if( poSRS->exportToWkt( &pszWKT ) != OGRERR_NONE )
         return -1;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Try to find in the existing table.                              */
 /* -------------------------------------------------------------------- */
-    osCommand.Printf( 
+    osCommand.Printf(
              "SELECT srid FROM spatial_ref_sys WHERE srtext = '%s'",
              pszWKT );
 
@@ -568,7 +575,7 @@ int OGRMySQLDataSource::FetchSRSId( OGRSpatialReference * poSRS )
     papszRow = NULL;
     if( hResult != NULL )
         papszRow = mysql_fetch_row( hResult );
-        
+
     if( papszRow != NULL && papszRow[0] != NULL )
     {
         nSRSId = atoi(papszRow[0]);
@@ -594,7 +601,7 @@ int OGRMySQLDataSource::FetchSRSId( OGRSpatialReference * poSRS )
         hResult = mysql_store_result( GetConn() );
         papszRow = mysql_fetch_row( hResult );
     }
-        
+
     if( papszRow != NULL && papszRow[0] != NULL )
     {
         nSRSId = atoi(papszRow[0]) + 1;
@@ -614,7 +621,7 @@ int OGRMySQLDataSource::FetchSRSId( OGRSpatialReference * poSRS )
              nSRSId, pszWKT );
 
     if( !mysql_query( GetConn(), osCommand ) )
-        hResult = mysql_store_result( GetConn() );
+        /*hResult = */ mysql_store_result( GetConn() ); /* FIXME ? */
 
     // make sure to attempt to free results of successful queries
     hResult = mysql_store_result( GetConn() );
@@ -638,7 +645,7 @@ OGRLayer * OGRMySQLDataSource::ExecuteSQL( const char *pszSQLCommand,
 {
     if( poSpatialFilter != NULL )
     {
-        CPLDebug( "OGR_MYSQL", 
+        CPLDebug( "OGR_MYSQL",
           "Spatial filter ignored for now in OGRMySQLDataSource::ExecuteSQL()" );
     }
 
@@ -646,15 +653,15 @@ OGRLayer * OGRMySQLDataSource::ExecuteSQL( const char *pszSQLCommand,
 /*      Use generic implementation for recognized dialects              */
 /* -------------------------------------------------------------------- */
     if( IsGenericSQLDialect(pszDialect) )
-        return OGRDataSource::ExecuteSQL( pszSQLCommand, 
-                                          poSpatialFilter, 
+        return OGRDataSource::ExecuteSQL( pszSQLCommand,
+                                          poSpatialFilter,
                                           pszDialect );
 
 /* -------------------------------------------------------------------- */
 /*      Special case DELLAYER: command.                                 */
 /* -------------------------------------------------------------------- */
 #ifdef notdef
-    if( EQUALN(pszSQLCommand,"DELLAYER:",9) )
+    if( STARTS_WITH_CI(pszSQLCommand, "DELLAYER:") )
     {
         const char *pszLayerName = pszSQLCommand + 9;
 
@@ -687,8 +694,8 @@ OGRLayer * OGRMySQLDataSource::ExecuteSQL( const char *pszSQLCommand,
     {
         if( mysql_field_count( hConn ) == 0 )
         {
-            CPLDebug( "MYSQL", "Command '%s' succeeded, %d rows affected.", 
-                      pszSQLCommand, 
+            CPLDebug( "MYSQL", "Command '%s' succeeded, %d rows affected.",
+                      pszSQLCommand,
                       (int) mysql_affected_rows(hConn) );
             return NULL;
         }
@@ -707,7 +714,7 @@ OGRLayer * OGRMySQLDataSource::ExecuteSQL( const char *pszSQLCommand,
     OGRMySQLResultLayer *poLayer = NULL;
 
     poLayer = new OGRMySQLResultLayer( this, pszSQLCommand, hResultSet );
-        
+
     return poLayer;
 }
 
@@ -780,18 +787,18 @@ void OGRMySQLDataSource::InterruptLongResult()
 /*                            DeleteLayer()                             */
 /************************************************************************/
 
-int OGRMySQLDataSource::DeleteLayer( int iLayer)
+OGRErr OGRMySQLDataSource::DeleteLayer( int iLayer)
 
 {
     if( iLayer < 0 || iLayer >= nLayers )
         return OGRERR_FAILURE;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Blow away our OGR structures related to the layer.  This is     */
 /*      pretty dangerous if anything has a reference to this layer!     */
 /* -------------------------------------------------------------------- */
     CPLString osLayerName = papoLayers[iLayer]->GetLayerDefn()->GetName();
-    
+
     CPLDebug( "MYSQL", "DeleteLayer(%s)", osLayerName.c_str() );
 
     delete papoLayers[iLayer];
@@ -898,7 +905,7 @@ OGRMySQLDataSource::ICreateLayer( const char * pszLayerNameIn,
 
     int bFID64 = CSLFetchBoolean(papszOptions, "FID64", FALSE);
     const char* pszFIDType = bFID64 ? "BIGINT": "INT";
-    
+
 
     CPLDebug("MYSQL","Geometry Column Name %s.", pszGeomColumnName);
     CPLDebug("MYSQL","FID Column Name %s.", pszExpectedFIDName);
@@ -924,7 +931,7 @@ OGRMySQLDataSource::ICreateLayer( const char * pszLayerNameIn,
         osCommand += " ENGINE = ";
         osCommand += CSLFetchNameValue( papszOptions, "ENGINE" );
     }
-	
+
     if( !mysql_query(GetConn(), osCommand ) )
     {
         if( mysql_field_count( GetConn() ) == 0 )
@@ -946,10 +953,10 @@ OGRMySQLDataSource::ICreateLayer( const char * pszLayerNameIn,
     if( hResult != NULL )
         mysql_free_result( hResult );
     hResult = NULL;
-    
+
     // Calling this does no harm
     InitializeMetadataTables();
-    
+
 /* -------------------------------------------------------------------- */
 /*      Try to get the SRS Id of this spatial reference system,         */
 /*      adding tot the srs table if needed.                             */
@@ -979,8 +986,8 @@ OGRMySQLDataSource::ICreateLayer( const char * pszLayerNameIn,
     hResult = mysql_store_result( GetConn() );
     if( hResult != NULL )
         mysql_free_result( hResult );
-    hResult = NULL;   
-        
+    hResult = NULL;
+
 /* -------------------------------------------------------------------- */
 /*      Attempt to add this table to the geometry_columns table, if     */
 /*      it is a spatial layer.                                          */
@@ -1032,7 +1039,7 @@ OGRMySQLDataSource::ICreateLayer( const char * pszLayerNameIn,
         hResult = mysql_store_result( GetConn() );
         if( hResult != NULL )
             mysql_free_result( hResult );
-        hResult = NULL;   
+        hResult = NULL;
     }
 
 /* -------------------------------------------------------------------- */
@@ -1043,7 +1050,7 @@ OGRMySQLDataSource::ICreateLayer( const char * pszLayerNameIn,
 /* -------------------------------------------------------------------- */
     const char *pszSI = CSLFetchNameValue( papszOptions, "SPATIAL_INDEX" );
 
-    if( eType != wkbNone && (pszSI == NULL || CSLTestBoolean(pszSI)) )
+    if( eType != wkbNone && (pszSI == NULL || CPLTestBool(pszSI)) )
     {
         osCommand.Printf(
                  "ALTER TABLE `%s` ADD SPATIAL INDEX(`%s`) ",
@@ -1060,9 +1067,9 @@ OGRMySQLDataSource::ICreateLayer( const char * pszLayerNameIn,
         hResult = mysql_store_result( GetConn() );
         if( hResult != NULL )
             mysql_free_result( hResult );
-        hResult = NULL;   
+        hResult = NULL;
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Create the layer object.                                        */
 /* -------------------------------------------------------------------- */
diff --git a/ogr/ogrsf_frmts/mysql/ogrmysqldriver.cpp b/ogr/ogrsf_frmts/mysql/ogrmysqldriver.cpp
index 307133a..7c4b217 100644
--- a/ogr/ogrsf_frmts/mysql/ogrmysqldriver.cpp
+++ b/ogr/ogrsf_frmts/mysql/ogrmysqldriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmysqldriver.cpp 29019 2015-04-25 20:34:19Z rouault $
+ * $Id: ogrmysqldriver.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMySQLDriver class.
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: ogrmysqldriver.cpp 29019 2015-04-25 20:34:19Z rouault $");
+CPL_CVSID("$Id: ogrmysqldriver.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 static CPLMutex* hMutex = NULL;
 static int   bInitialized = FALSE;
@@ -61,9 +61,9 @@ static void OGRMySQLDriverUnload( CPL_UNUSED GDALDriver* poDriver )
 static int OGRMySQLDriverIdentify( GDALOpenInfo* poOpenInfo )
 
 {
-    return EQUALN(poOpenInfo->pszFilename,"MYSQL:",6);
+    return STARTS_WITH_CI(poOpenInfo->pszFilename, "MYSQL:");
 }
- 
+
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
@@ -75,7 +75,7 @@ static GDALDataset *OGRMySQLDriverOpen( GDALOpenInfo* poOpenInfo )
 
     if( !OGRMySQLDriverIdentify(poOpenInfo) )
         return NULL;
- 
+
     {
         CPLMutexHolderD(&hMutex);
         if( !bInitialized )
@@ -121,7 +121,7 @@ static GDALDataset *OGRMySQLDriverCreate( const char * pszName,
     if( !poDS->Open( pszName, NULL, TRUE ) )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
          "MySQL driver doesn't currently support database creation.\n"
                   "Please create database before using." );
         return NULL;
@@ -139,23 +139,20 @@ void RegisterOGRMySQL()
 {
     if (! GDAL_CHECK_VERSION("MySQL driver"))
         return;
-  
-    GDALDriver  *poDriver;
 
-    if( GDALGetDriverByName( "MySQL" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    if( GDALGetDriverByName( "MySQL" ) != NULL )
+        return;
 
-        poDriver->SetDescription( "MySQL" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "MySQL" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_mysql.html" );
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, "MYSQL:" );
+    poDriver->SetDescription( "MySQL" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "MySQL" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_mysql.html" );
 
-        poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, "MYSQL:" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
 "<OpenOptionList>"
 "  <Option name='DBNAME' type='string' description='Database name' required='true'/>"
 "  <Option name='PORT' type='int' description='Port'/>"
@@ -165,9 +162,10 @@ void RegisterOGRMySQL()
 "  <Option name='TABLES' type='string' description='Restricted set of tables to list (comma separated)'/>"
 "</OpenOptionList>");
 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, "<CreationOptionList/>");
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+                               "<CreationOptionList/>");
 
-        poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
     "<LayerCreationOptionList>"
     "  <Option name='OVERWRITE' type='boolean' description='Whether to overwrite an existing table with the layer name to be created' default='NO'/>"
     "  <Option name='LAUNDER' type='boolean' description='Whether layer and field names will be laundered' default='YES'/>"
@@ -178,16 +176,17 @@ void RegisterOGRMySQL()
     "  <Option name='FID64' type='boolean' description='Whether to create the FID column with BIGINT type to handle 64bit wide ids' default='NO'/>"
     "  <Option name='ENGINE' type='string' description='Database engine to use.'/>"
     "</LayerCreationOptionList>");
-        
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES, "Integer Integer64 Real String Date DateTime Time Binary" );
-        poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_FIELDS, "YES" );
-        poDriver->SetMetadataItem( GDAL_DCAP_DEFAULT_FIELDS, "YES" );
 
-        poDriver->pfnOpen = OGRMySQLDriverOpen;
-        poDriver->pfnIdentify = OGRMySQLDriverIdentify;
-        poDriver->pfnCreate = OGRMySQLDriverCreate;
-        poDriver->pfnUnloadDriver = OGRMySQLDriverUnload;
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
+                               "Integer Integer64 Real String Date DateTime "
+                               "Time Binary" );
+    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_FIELDS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_DEFAULT_FIELDS, "YES" );
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    poDriver->pfnOpen = OGRMySQLDriverOpen;
+    poDriver->pfnIdentify = OGRMySQLDriverIdentify;
+    poDriver->pfnCreate = OGRMySQLDriverCreate;
+    poDriver->pfnUnloadDriver = OGRMySQLDriverUnload;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/mysql/ogrmysqllayer.cpp b/ogr/ogrsf_frmts/mysql/ogrmysqllayer.cpp
index 4f6b020..7fcdb33 100644
--- a/ogr/ogrsf_frmts/mysql/ogrmysqllayer.cpp
+++ b/ogr/ogrsf_frmts/mysql/ogrmysqllayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmysqllayer.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrmysqllayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMySQLLayer class.
@@ -32,14 +32,14 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrmysqllayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrmysqllayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                           OGRMySQLLayer()                            */
 /************************************************************************/
 
-OGRMySQLLayer::OGRMySQLLayer()
-
+OGRMySQLLayer::OGRMySQLLayer() :
+    nGeomType(0)
 {
     poDS = NULL;
 
@@ -55,7 +55,7 @@ OGRMySQLLayer::OGRMySQLLayer()
     nResultOffset = 0;
 
     poSRS = NULL;
-    nSRSId = -2; // we haven't even queried the database for it yet. 
+    nSRSId = -2; // we haven't even queried the database for it yet.
 
     poFeatureDefn = NULL;
 
@@ -72,7 +72,7 @@ OGRMySQLLayer::~OGRMySQLLayer()
     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     {
         CPLDebug( "MySQL", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
+                  (int) m_nFeaturesRead,
                   poFeatureDefn->GetName() );
     }
 
@@ -116,7 +116,7 @@ OGRFeature *OGRMySQLLayer::GetNextFeature()
 
 {
 
-    for( ; TRUE; )
+    while( true )
     {
         OGRFeature      *poFeature;
 
@@ -158,7 +158,7 @@ OGRFeature *OGRMySQLLayer::RecordToFeature( char **papszRow,
 /* ==================================================================== */
 /*      Transfer all result fields we can.                              */
 /* ==================================================================== */
-    for( iField = 0; 
+    for( iField = 0;
          iField < (int) mysql_num_fields(hResultSet);
          iField++ )
     {
@@ -180,7 +180,7 @@ OGRFeature *OGRMySQLLayer::RecordToFeature( char **papszRow,
             poFeature->SetFID( CPLAtoGIntBig(papszRow[iField]) );
         }
 
-        if( papszRow[iField] == NULL ) 
+        if( papszRow[iField] == NULL )
         {
 //            CPLDebug("MYSQL", "%s was null for %d", psMSField->name,
 //                     iNextShapeId);
@@ -193,13 +193,13 @@ OGRFeature *OGRMySQLLayer::RecordToFeature( char **papszRow,
         if( pszGeomColumn && EQUAL(psMSField->name,pszGeomColumn))
         {
             OGRGeometry *poGeometry = NULL;
-            
+
             // Geometry columns will have the first 4 bytes contain the SRID.
             OGRGeometryFactory::createFromWkb(
-                ((GByte *)papszRow[iField]) + 4, 
+                ((GByte *)papszRow[iField]) + 4,
                 NULL,
                 &poGeometry,
-                panLengths[iField] - 4 );
+                static_cast<int>(panLengths[iField] - 4) );
 
             if( poGeometry != NULL )
             {
@@ -221,7 +221,7 @@ OGRFeature *OGRMySQLLayer::RecordToFeature( char **papszRow,
 
         if( psFieldDefn->GetType() == OFTBinary )
         {
-            poFeature->SetField( iOGRField, panLengths[iField], 
+            poFeature->SetField( iOGRField, static_cast<int>(panLengths[iField]),
                                  (GByte *) papszRow[iField] );
         }
         else
@@ -259,7 +259,7 @@ OGRFeature *OGRMySQLLayer::GetNextRawFeature()
         if( hResultSet == NULL )
         {
             poDS->ReportError( "mysql_use_result() failed on query." );
-            return FALSE;
+            return NULL;
         }
     }
 
@@ -304,7 +304,7 @@ OGRFeature *OGRMySQLLayer::GetFeature( GIntBig nFeatureId )
 /*                            GetFIDColumn()                            */
 /************************************************************************/
 
-const char *OGRMySQLLayer::GetFIDColumn() 
+const char *OGRMySQLLayer::GetFIDColumn()
 
 {
     if( pszFIDColumn != NULL )
@@ -317,7 +317,7 @@ const char *OGRMySQLLayer::GetFIDColumn()
 /*                         GetGeometryColumn()                          */
 /************************************************************************/
 
-const char *OGRMySQLLayer::GetGeometryColumn() 
+const char *OGRMySQLLayer::GetGeometryColumn()
 
 {
     if( pszGeomColumn != NULL )
@@ -334,12 +334,12 @@ const char *OGRMySQLLayer::GetGeometryColumn()
 int OGRMySQLLayer::FetchSRSId()
 {
 	CPLString        osCommand;
-    char           **papszRow;  
-    
+    char           **papszRow;
+
     if( hResultSet != NULL )
         mysql_free_result( hResultSet );
 		hResultSet = NULL;
-				
+
     osCommand.Printf(
              "SELECT srid FROM geometry_columns "
              "WHERE f_table_name = '%s'",
@@ -351,7 +351,6 @@ int OGRMySQLLayer::FetchSRSId()
     papszRow = NULL;
     if( hResultSet != NULL )
         papszRow = mysql_fetch_row( hResultSet );
-        
 
     if( papszRow != NULL && papszRow[0] != NULL )
     {
@@ -362,7 +361,7 @@ int OGRMySQLLayer::FetchSRSId()
     if( hResultSet != NULL )
         mysql_free_result( hResultSet );
 		hResultSet = NULL;
-        
+
 	return nSRSId;
 }
 
diff --git a/ogr/ogrsf_frmts/mysql/ogrmysqlresultlayer.cpp b/ogr/ogrsf_frmts/mysql/ogrmysqlresultlayer.cpp
index 1037e3a..0297f06 100644
--- a/ogr/ogrsf_frmts/mysql/ogrmysqlresultlayer.cpp
+++ b/ogr/ogrsf_frmts/mysql/ogrmysqlresultlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmysqlresultlayer.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrmysqlresultlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMySQLResultLayer class.
@@ -32,13 +32,13 @@
 #include "cpl_conv.h"
 #include "ogr_mysql.h"
 
-CPL_CVSID("$Id: ogrmysqlresultlayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrmysqlresultlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                        OGRMySQLResultLayer()                         */
 /************************************************************************/
 
-OGRMySQLResultLayer::OGRMySQLResultLayer( OGRMySQLDataSource *poDSIn, 
+OGRMySQLResultLayer::OGRMySQLResultLayer( OGRMySQLDataSource *poDSIn,
                                           const char * pszRawQueryIn,
                                           MYSQL_RES *hResultSetIn )
 {
@@ -87,8 +87,8 @@ OGRFeatureDefn *OGRMySQLResultLayer::ReadResultDefinition()
     int precision;
 
     mysql_field_seek( hResultSet, 0 );
-    for( iRawField = 0; 
-         iRawField < (int) mysql_num_fields(hResultSet); 
+    for( iRawField = 0;
+         iRawField < (int) mysql_num_fields(hResultSet);
          iRawField++ )
     {
         MYSQL_FIELD *psMSField = mysql_fetch_field( hResultSet );
@@ -112,15 +112,15 @@ OGRFeatureDefn *OGRMySQLResultLayer::ReadResultDefinition()
           case FIELD_TYPE_NEWDECIMAL:
 #endif
             oField.SetType( OFTReal );
-            
-            // a bunch of hackery to munge the widths that MySQL gives 
+
+            // a bunch of hackery to munge the widths that MySQL gives
             // us into corresponding widths and precisions for OGR
             precision =    (int)psMSField->decimals;
             width = (int)psMSField->length;
             if (!precision)
                 width = width - 1;
             width = width - precision;
-            
+
             oField.SetWidth(width);
             oField.SetPrecision(precision);
             poDefn->AddFieldDefn( &oField );
@@ -183,7 +183,7 @@ OGRFeatureDefn *OGRMySQLResultLayer::ReadResultDefinition()
             oField.SetWidth((int)psMSField->max_length);
             poDefn->AddFieldDefn( &oField );
             break;
-                        
+
           case FIELD_TYPE_GEOMETRY:
             if (pszGeomColumn == NULL)
             {
@@ -191,24 +191,24 @@ OGRFeatureDefn *OGRMySQLResultLayer::ReadResultDefinition()
                 pszGeomColumn = CPLStrdup( psMSField->name);
             }
             break;
-            
+
           default:
-            // any other field we ignore. 
+            // any other field we ignore.
             break;
         }
-        
+
         // assume a FID name first, and if it isn't there
-        // take a field that is not null, a primary key, 
+        // take a field that is not null, a primary key,
         // and is an integer-like field
         if( EQUAL(psMSField->name,"ogc_fid") )
         {
             bHasFid = TRUE;
             pszFIDColumn = CPLStrdup(oField.GetNameRef());
             continue;
-        } else  
+        } else
         if (IS_NOT_NULL(psMSField->flags)
             && IS_PRI_KEY(psMSField->flags)
-            && 
+            &&
                 (
                     psMSField->type == FIELD_TYPE_TINY
                     || psMSField->type == FIELD_TYPE_SHORT
@@ -227,15 +227,15 @@ OGRFeatureDefn *OGRMySQLResultLayer::ReadResultDefinition()
 
     poDefn->SetGeomType( wkbNone );
 
-    if (pszGeomColumn) 
+    if (pszGeomColumn)
     {
         char*        pszType=NULL;
         CPLString    osCommand;
-        char           **papszRow;  
-         
+        char           **papszRow;
+
         // set to unknown first
         poDefn->SetGeomType( wkbUnknown );
-        
+
         osCommand.Printf(
                 "SELECT type FROM geometry_columns WHERE f_table_name='%s'",
                 pszGeomColumnTable );
@@ -256,14 +256,13 @@ OGRFeatureDefn *OGRMySQLResultLayer::ReadResultDefinition()
         {
             pszType = papszRow[0];
 
-            OGRwkbGeometryType nGeomType = OGRFromOGCGeomType(pszType);
-
-            poDefn->SetGeomType( nGeomType );
+            OGRwkbGeometryType l_nGeomType = OGRFromOGCGeomType(pszType);
 
-        } 
+            poDefn->SetGeomType( l_nGeomType );
+        }
 
 		nSRSId = FetchSRSId();
-    } 
+    }
 
 
     return poDefn;
diff --git a/ogr/ogrsf_frmts/mysql/ogrmysqltablelayer.cpp b/ogr/ogrsf_frmts/mysql/ogrmysqltablelayer.cpp
index 1a6ce03..0492f5f 100644
--- a/ogr/ogrsf_frmts/mysql/ogrmysqltablelayer.cpp
+++ b/ogr/ogrsf_frmts/mysql/ogrmysqltablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmysqltablelayer.cpp 28809 2015-03-28 17:10:07Z rouault $
+ * $Id: ogrmysqltablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMySQLTableLayer class.
@@ -33,7 +33,7 @@
 #include "cpl_string.h"
 #include "ogr_mysql.h"
 
-CPL_CVSID("$Id: ogrmysqltablelayer.cpp 28809 2015-03-28 17:10:07Z rouault $");
+CPL_CVSID("$Id: ogrmysqltablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                         OGRMySQLTableLayer()                         */
@@ -57,7 +57,8 @@ OGRMySQLTableLayer::OGRMySQLTableLayer( OGRMySQLDataSource *poDSIn,
 
     poFeatureDefn = NULL;
     bLaunderColumnNames = TRUE;
-    
+    bPreservePrecision = FALSE;
+
     SetDescription( pszTableName );
 }
 
@@ -83,7 +84,7 @@ OGRMySQLTableLayer::~OGRMySQLTableLayer()
 
 OGRErr  OGRMySQLTableLayer::Initialize(const char * pszTableName)
 {
-    poFeatureDefn = ReadTableDefinition( pszTableName );   
+    poFeatureDefn = ReadTableDefinition( pszTableName );
     if (poFeatureDefn)
     {
         ResetReading();
@@ -107,7 +108,7 @@ OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
 {
     MYSQL_RES    *hResult;
     CPLString     osCommand;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Fire off commands to get back the schema of the table.          */
 /* -------------------------------------------------------------------- */
@@ -116,14 +117,14 @@ OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
     if( mysql_query( poDS->GetConn(), osCommand ) )
     {
         poDS->ReportError( "DESCRIBE Failed" );
-        return FALSE;
+        return NULL;
     }
 
     hResult = mysql_store_result( poDS->GetConn() );
     if( hResult == NULL )
     {
         poDS->ReportError( "mysql_store_result() failed on DESCRIBE result." );
-        return FALSE;
+        return NULL;
     }
 
 /* -------------------------------------------------------------------- */
@@ -154,14 +155,14 @@ OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
         {
             oField.SetType( OFTBinary );
         }
-        else if( EQUAL(pszType,"varchar") 
+        else if( EQUAL(pszType,"varchar")
                  || (nLenType>=4 && EQUAL(pszType+nLenType-4,"enum"))
                  || (nLenType>=3 && EQUAL(pszType+nLenType-3,"set")) )
         {
             oField.SetType( OFTString );
 
         }
-        else if( EQUALN(pszType,"char",4)  )
+        else if( STARTS_WITH_CI(pszType, "char")  )
         {
             oField.SetType( OFTString );
             char ** papszTokens;
@@ -177,18 +178,18 @@ OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
             oField.SetType( OFTString );
 
         }
-        
+
         if(nLenType>=4 && EQUAL(pszType+nLenType-4,"text"))
         {
-            oField.SetType( OFTString );            
+            oField.SetType( OFTString );
         }
-        else if( EQUALN(pszType,"varchar",6)  )
+        else if( STARTS_WITH_CI(pszType,"varchar")  )
         {
-            /* 
-               pszType is usually in the form "varchar(15)" 
+            /*
+               pszType is usually in the form "varchar(15)"
                so we'll split it up and get the width and precision
             */
-            
+
             oField.SetType( OFTString );
             char ** papszTokens;
 
@@ -202,30 +203,30 @@ OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
             CSLDestroy( papszTokens );
             oField.SetType( OFTString );
         }
-        else if( EQUALN(pszType,"int", 3) )
+        else if( STARTS_WITH_CI(pszType, "int") )
         {
             oField.SetType( OFTInteger );
         }
-        else if( EQUALN(pszType,"tinyint", 7) )
+        else if( STARTS_WITH_CI(pszType, "tinyint") )
         {
             oField.SetType( OFTInteger );
         }
-        else if( EQUALN(pszType,"smallint", 8) )
+        else if( STARTS_WITH_CI(pszType, "smallint") )
         {
             oField.SetType( OFTInteger );
         }
-        else if( EQUALN(pszType,"mediumint",9) )
+        else if( STARTS_WITH_CI(pszType, "mediumint") )
         {
             oField.SetType( OFTInteger );
         }
-        else if( EQUALN(pszType,"bigint",6) )
+        else if( STARTS_WITH_CI(pszType, "bigint") )
         {
             oField.SetType( OFTInteger64 );
         }
-        else if( EQUALN(pszType,"decimal",7) )
+        else if( STARTS_WITH_CI(pszType, "decimal") )
         {
-            /* 
-               pszType is usually in the form "decimal(15,2)" 
+            /*
+               pszType is usually in the form "decimal(15,2)"
                so we'll split it up and get the width and precision
             */
             oField.SetType( OFTReal );
@@ -242,7 +243,7 @@ OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
 
 
         }
-        else if( EQUALN(pszType,"float", 5) )
+        else if( STARTS_WITH_CI(pszType, "float") )
         {
             oField.SetType( OFTReal );
         }
@@ -250,13 +251,13 @@ OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
         {
             oField.SetType( OFTReal );
         }
-        else if( EQUALN(pszType,"double",6) )
+        else if( STARTS_WITH_CI(pszType, "double") )
         {
             // double can also be double(15,2)
-            // so we'll handle this case here after 
-            // we check for just a regular double 
+            // so we'll handle this case here after
+            // we check for just a regular double
             // without a width and precision specified
-            
+
             char ** papszTokens=NULL;
             papszTokens = CSLTokenizeString2(pszType,"(),",0);
             if (CSLCount(papszTokens) >= 3)
@@ -265,7 +266,7 @@ OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
                 oField.SetWidth(atoi(papszTokens[1]));
                 oField.SetPrecision(atoi(papszTokens[2]));
             }
-            CSLDestroy( papszTokens );  
+            CSLDestroy( papszTokens );
 
             oField.SetType( OFTReal );
         }
@@ -281,12 +282,12 @@ OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
         {
             oField.SetType( OFTTime );
         }
-        else if( EQUAL(pszType, "datetime") 
+        else if( EQUAL(pszType, "datetime")
                  || EQUAL(pszType, "timestamp") )
         {
             oField.SetType( OFTDateTime );
         }
-        else if( EQUAL(pszType, "year") )  
+        else if( EQUAL(pszType, "year") )
         {
             oField.SetType( OFTString );
             oField.SetWidth( 10 );
@@ -309,7 +310,7 @@ OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
             continue;
         }
         // Is this an integer primary key field?
-        if( !bHasFid && papszRow[3] != NULL && EQUAL(papszRow[3],"PRI") 
+        if( !bHasFid && papszRow[3] != NULL && EQUAL(papszRow[3],"PRI")
             && (oField.GetType() == OFTInteger || oField.GetType() == OFTInteger64) )
         {
             bHasFid = TRUE;
@@ -318,17 +319,17 @@ OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
                 SetMetadataItem(OLMD_FID64, "YES");
             continue;
         }
-        
+
         // Is not nullable ?
         if( papszRow[2] != NULL && EQUAL(papszRow[2], "NO") )
             oField.SetNullable(FALSE);
-        
+
         // Has default ?
         const char* pszDefault = papszRow[4];
         if( pszDefault != NULL )
         {
             if( !EQUAL(pszDefault, "NULL") &&
-                !EQUALN(pszDefault, "CURRENT_", strlen("CURRENT_")) &&
+                !STARTS_WITH_CI(pszDefault, "CURRENT_") &&
                 pszDefault[0] != '(' &&
                 pszDefault[0] != '\'' &&
                 CPLGetValueType(pszDefault) == CPL_VALUE_STRING )
@@ -357,7 +358,7 @@ OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
                 oField.SetDefault(pszDefault);
             }
         }
-        
+
         poDefn->AddFieldDefn( &oField );
     }
 
@@ -374,21 +375,21 @@ OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
         CPLDebug( "MySQL", "table %s has FID column %s.",
                   pszTable, pszFIDColumn );
     else
-        CPLDebug( "MySQL", 
+        CPLDebug( "MySQL",
                   "table %s has no FID column, FIDs will not be reliable!",
                   pszTable );
 
-    if (pszGeomColumn) 
+    if (pszGeomColumn)
     {
         char*        pszType=NULL;
-        
+
         // set to unknown first
         poDefn->SetGeomType( wkbUnknown );
-        
+
         osCommand = "SELECT type, coord_dimension FROM geometry_columns WHERE f_table_name='";
         osCommand += pszTable;
         osCommand += "'";
-        
+
         hResult = NULL;
         if( !mysql_query( poDS->GetConn(), osCommand ) )
             hResult = mysql_store_result( poDS->GetConn() );
@@ -402,12 +403,12 @@ OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
 
             pszType = papszRow[0];
 
-            OGRwkbGeometryType nGeomType = OGRFromOGCGeomType(pszType);
+            OGRwkbGeometryType l_nGeomType = OGRFromOGCGeomType(pszType);
 
             if( papszRow[1] != NULL && atoi(papszRow[1]) == 3 )
-                nGeomType = wkbSetZ(nGeomType);
+                l_nGeomType = wkbSetZ(l_nGeomType);
 
-            poDefn->SetGeomType( nGeomType );
+            poDefn->SetGeomType( l_nGeomType );
 
         }
         else if (eForcedGeomType != wkbUnknown)
@@ -415,14 +416,14 @@ OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
 
         if( bGeomColumnNotNullable )
             poDefn->GetGeomFieldDefn(0)->SetNullable(FALSE);
-        
+
         if( hResult != NULL )
             mysql_free_result( hResult );   //Free our query results for finding type.
 			hResult = NULL;
-    } 
- 
+    }
+
     // Fetch the SRID for this table now
-    nSRSId = FetchSRSId(); 
+    nSRSId = FetchSRSId();
     return poDefn;
 }
 
@@ -454,7 +455,8 @@ void OGRMySQLTableLayer::BuildWhere()
 
 {
     CPLFree( pszWHERE );
-    pszWHERE = (char*)CPLMalloc(500 + ((pszQuery) ? strlen(pszQuery) : 0));
+    const size_t nWHERELen = 500 + ((pszQuery) ? strlen(pszQuery) : 0);
+    pszWHERE = (char*)CPLMalloc(nWHERELen);
     pszWHERE[0] = '\0';
 
     if( m_poFilterGeom != NULL && pszGeomColumn )
@@ -462,10 +464,10 @@ void OGRMySQLTableLayer::BuildWhere()
         char szEnvelope[400];
         OGREnvelope  sEnvelope;
         szEnvelope[0] = '\0';
-        
+
         //POLYGON((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))
         m_poFilterGeom->getEnvelope( &sEnvelope );
-        
+
         CPLsnprintf(szEnvelope, sizeof(szEnvelope),
                 "POLYGON((%.18g %.18g, %.18g %.18g, %.18g %.18g, %.18g %.18g, %.18g %.18g))",
                 sEnvelope.MinX, sEnvelope.MinY,
@@ -474,7 +476,7 @@ void OGRMySQLTableLayer::BuildWhere()
                 sEnvelope.MinX, sEnvelope.MaxY,
                 sEnvelope.MinX, sEnvelope.MinY);
 
-        sprintf( pszWHERE,
+        snprintf( pszWHERE, nWHERELen,
                  "WHERE MBRIntersects(GeomFromText('%s'), `%s`)",
                  szEnvelope,
                  pszGeomColumn);
@@ -484,9 +486,10 @@ void OGRMySQLTableLayer::BuildWhere()
     if( pszQuery != NULL )
     {
         if( strlen(pszWHERE) == 0 )
-            sprintf( pszWHERE, "WHERE %s ", pszQuery  );
+            snprintf( pszWHERE, nWHERELen, "WHERE %s ", pszQuery  );
         else
-            sprintf( pszWHERE+strlen(pszWHERE), "&& (%s) ", pszQuery );
+            snprintf( pszWHERE+strlen(pszWHERE),
+                      nWHERELen - strlen(pszWHERE), "&& (%s) ", pszQuery );
     }
 }
 
@@ -505,13 +508,15 @@ void OGRMySQLTableLayer::BuildFullQueryStatement()
 
     char *pszFields = BuildFields();
 
-    pszQueryStatement = (char *) 
+    pszQueryStatement = (char *)
         CPLMalloc(strlen(pszFields)+strlen(pszWHERE)
                   +strlen(poFeatureDefn->GetName()) + 40);
-    sprintf( pszQueryStatement,
-             "SELECT %s FROM `%s` %s", 
+    snprintf( pszQueryStatement,
+              strlen(pszFields)+strlen(pszWHERE)
+                  +strlen(poFeatureDefn->GetName()) + 40,
+             "SELECT %s FROM `%s` %s",
              pszFields, poFeatureDefn->GetName(), pszWHERE );
-    
+
     CPLFree( pszFields );
 }
 
@@ -537,7 +542,8 @@ void OGRMySQLTableLayer::ResetReading()
 char *OGRMySQLTableLayer::BuildFields()
 
 {
-    int         i, nSize;
+    int         i;
+    size_t      nSize;
     char        *pszFieldList;
 
     nSize = 25;
@@ -546,7 +552,7 @@ char *OGRMySQLTableLayer::BuildFields()
 
     if( bHasFid )
         nSize += strlen(pszFIDColumn);
-        
+
 
     for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
         nSize += strlen(poFeatureDefn->GetFieldDefn(i)->GetNameRef()) + 6;
@@ -555,19 +561,19 @@ char *OGRMySQLTableLayer::BuildFields()
     pszFieldList[0] = '\0';
 
     if( bHasFid && poFeatureDefn->GetFieldIndex( pszFIDColumn ) == -1 )
-        sprintf( pszFieldList, "`%s`", pszFIDColumn );
+        snprintf( pszFieldList, nSize, "`%s`", pszFIDColumn );
 
     if( pszGeomColumn )
     {
         if( strlen(pszFieldList) > 0 )
             strcat( pszFieldList, ", " );
 
-		/* ------------------------------------------------------------ */
-		/*      Geometry returned from MySQL is as WKB, with the        */
+	/* ------------------------------------------------------------ */
+	/*      Geometry returned from MySQL is as WKB, with the        */
         /*      first 4 bytes being an int that defines the SRID        */
         /*      and the rest being the WKB.                             */
-		/* ------------------------------------------------------------ */            
-        sprintf( pszFieldList+strlen(pszFieldList), 
+	/* ------------------------------------------------------------ */
+        snprintf( pszFieldList+strlen(pszFieldList), nSize-strlen(pszFieldList),
                  "`%s` `%s`", pszGeomColumn, pszGeomColumn );
     }
 
@@ -583,7 +589,7 @@ char *OGRMySQLTableLayer::BuildFields()
         strcat( pszFieldList, "`");
     }
 
-    CPLAssert( (int) strlen(pszFieldList) < nSize );
+    CPLAssert( strlen(pszFieldList) < nSize );
 
     return pszFieldList;
 }
@@ -592,18 +598,18 @@ char *OGRMySQLTableLayer::BuildFields()
 /*                         SetAttributeFilter()                         */
 /************************************************************************/
 
-OGRErr OGRMySQLTableLayer::SetAttributeFilter( const char *pszQuery )
+OGRErr OGRMySQLTableLayer::SetAttributeFilter( const char *pszQueryIn )
 
 {
     CPLFree(m_pszAttrQueryString);
-    m_pszAttrQueryString = (pszQuery) ? CPLStrdup(pszQuery) : NULL;
+    m_pszAttrQueryString = (pszQueryIn) ? CPLStrdup(pszQueryIn) : NULL;
 
     CPLFree( this->pszQuery );
 
-    if( pszQuery == NULL || strlen(pszQuery) == 0 )
+    if( pszQueryIn == NULL || strlen(pszQueryIn) == 0 )
         this->pszQuery = NULL;
     else
-        this->pszQuery = CPLStrdup( pszQuery );
+        this->pszQuery = CPLStrdup( pszQueryIn );
 
     BuildWhere();
 
@@ -704,14 +710,14 @@ OGRErr OGRMySQLTableLayer::DeleteFeature( GIntBig nFID )
 /* -------------------------------------------------------------------- */
     osCommand.Printf( "DELETE FROM `%s` WHERE `%s` = " CPL_FRMT_GIB,
                       poFeatureDefn->GetName(), pszFIDColumn, nFID );
-                      
+
 /* -------------------------------------------------------------------- */
 /*      Execute the delete.                                             */
 /* -------------------------------------------------------------------- */
     poDS->InterruptLongResult();
-    if( mysql_query(poDS->GetConn(), osCommand.c_str() ) ){   
+    if( mysql_query(poDS->GetConn(), osCommand.c_str() ) ){
         poDS->ReportError(  osCommand.c_str() );
-        return OGRERR_FAILURE;   
+        return OGRERR_FAILURE;
     }
 
     // make sure to attempt to free results of successful queries
@@ -719,7 +725,7 @@ OGRErr OGRMySQLTableLayer::DeleteFeature( GIntBig nFID )
     if( hResult != NULL )
         mysql_free_result( hResult );
     hResult = NULL;
-    
+
     return mysql_affected_rows( poDS->GetConn() ) > 0 ? OGRERR_NONE : OGRERR_NON_EXISTING_FEATURE;
 }
 
@@ -750,7 +756,7 @@ OGRErr OGRMySQLTableLayer::ICreateFeature( OGRFeature *poFeature )
     {
         if( bNeedComma )
             osCommand += ", ";
-        
+
         osCommand = osCommand + "`" + pszFIDColumn + "` ";
         bNeedComma = TRUE;
     }
@@ -771,7 +777,7 @@ OGRErr OGRMySQLTableLayer::ICreateFeature( OGRFeature *poFeature )
 
     osCommand += ") VALUES (";
 
-    // Set the geometry 
+    // Set the geometry
     bNeedComma = poFeature->GetGeometryRef() != NULL;
     if( poFeature->GetGeometryRef() != NULL)
     {
@@ -780,7 +786,7 @@ OGRErr OGRMySQLTableLayer::ICreateFeature( OGRFeature *poFeature )
         if( poFeature->GetGeometryRef() != NULL )
         {
             OGRGeometry *poGeom = (OGRGeometry *) poFeature->GetGeometryRef();
-            
+
             poGeom->closeRings();
             poGeom->flattenTo2D();
             poGeom->exportToWkt( &pszWKT );
@@ -789,7 +795,7 @@ OGRErr OGRMySQLTableLayer::ICreateFeature( OGRFeature *poFeature )
         if( pszWKT != NULL )
         {
 
-            osCommand += 
+            osCommand +=
                 CPLString().Printf(
                     "GeometryFromText('%s',%d) ", pszWKT, nSRSId );
 
@@ -800,10 +806,11 @@ OGRErr OGRMySQLTableLayer::ICreateFeature( OGRFeature *poFeature )
     }
 
 
-    // Set the FID 
+    // Set the FID
     if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
     {
-        if( (GIntBig)(int)poFeature->GetFID() != poFeature->GetFID() &&
+        GIntBig nFID = poFeature->GetFID();
+        if( !CPL_INT64_FITS_ON_INT32(nFID) &&
             GetMetadataItem(OLMD_FID64) == NULL )
         {
             CPLString osCommand2;
@@ -821,14 +828,14 @@ OGRErr OGRMySQLTableLayer::ICreateFeature( OGRFeature *poFeature )
             hResult = mysql_store_result( poDS->GetConn() );
             if( hResult != NULL )
                 mysql_free_result( hResult );
-            hResult = NULL;   
+            hResult = NULL;
 
             SetMetadataItem(OLMD_FID64, "YES");
         }
-        
+
         if( bNeedComma )
             osCommand += ", ";
-        osCommand += CPLString().Printf( CPL_FRMT_GIB, poFeature->GetFID() );
+        osCommand += CPLString().Printf( CPL_FRMT_GIB, nFID );
         bNeedComma = TRUE;
     }
 
@@ -845,13 +852,13 @@ OGRErr OGRMySQLTableLayer::ICreateFeature( OGRFeature *poFeature )
         const char *pszStrValue = poFeature->GetFieldAsString(i);
 
         if( poFeatureDefn->GetFieldDefn(i)->GetType() != OFTInteger
-                 && poFeatureDefn->GetFieldDefn(i)->GetType() != OFTInteger64 
+                 && poFeatureDefn->GetFieldDefn(i)->GetType() != OFTInteger64
                  && poFeatureDefn->GetFieldDefn(i)->GetType() != OFTReal
                  && poFeatureDefn->GetFieldDefn(i)->GetType() != OFTBinary )
         {
             int         iChar;
 
-            //We need to quote and escape string fields. 
+            //We need to quote and escape string fields.
             osCommand += "'";
 
             for( iChar = 0; pszStrValue[iChar] != '\0'; iChar++ )
@@ -900,12 +907,12 @@ OGRErr OGRMySQLTableLayer::ICreateFeature( OGRFeature *poFeature )
     }
 
     osCommand += ")";
-    
+
     //CPLDebug("MYSQL", "%s", osCommand.c_str());
     int nQueryResult = mysql_query(poDS->GetConn(), osCommand.c_str() );
     const my_ulonglong nFID = mysql_insert_id( poDS->GetConn() );
-    
-    if( nQueryResult ){   
+
+    if( nQueryResult ){
         int eErrorCode = mysql_errno(poDS->GetConn());
         if (eErrorCode == 1153) {//ER_NET_PACKET_TOO_LARGE)
             poDS->ReportError("CreateFeature failed because the MySQL server " \
@@ -925,8 +932,8 @@ OGRErr OGRMySQLTableLayer::ICreateFeature( OGRFeature *poFeature )
         if( hResult != NULL )
             mysql_free_result( hResult );
         hResult = NULL;
-            
-        return OGRERR_FAILURE;   
+
+        return OGRERR_FAILURE;
     }
 
     if( nFID > 0 ) {
@@ -938,7 +945,7 @@ OGRErr OGRMySQLTableLayer::ICreateFeature( OGRFeature *poFeature )
     if( hResult != NULL )
         mysql_free_result( hResult );
     hResult = NULL;
-    
+
     return OGRERR_NONE;
 
 }
@@ -952,7 +959,7 @@ OGRErr OGRMySQLTableLayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
 
     MYSQL_RES           *hResult=NULL;
     CPLString            osCommand;
-    
+
     char                szFieldType[256];
     OGRFieldDefn        oField( poFieldIn );
 
@@ -975,14 +982,14 @@ OGRErr OGRMySQLTableLayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
     if( oField.GetType() == OFTInteger )
     {
         if( oField.GetWidth() > 0 && bPreservePrecision )
-            sprintf( szFieldType, "DECIMAL(%d,0)", oField.GetWidth() );
+            snprintf( szFieldType, sizeof(szFieldType), "DECIMAL(%d,0)", oField.GetWidth() );
         else
             strcpy( szFieldType, "INTEGER" );
     }
     else if( oField.GetType() == OFTInteger64 )
     {
         if( oField.GetWidth() > 0 && bPreservePrecision )
-            sprintf( szFieldType, "DECIMAL(%d,0)", oField.GetWidth() );
+            snprintf( szFieldType, sizeof(szFieldType), "DECIMAL(%d,0)", oField.GetWidth() );
         else
             strcpy( szFieldType, "BIGINT" );
     }
@@ -990,7 +997,7 @@ OGRErr OGRMySQLTableLayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
     {
         if( oField.GetWidth() > 0 && oField.GetPrecision() > 0
             && bPreservePrecision )
-            sprintf( szFieldType, "DOUBLE(%d,%d)",
+            snprintf( szFieldType, sizeof(szFieldType), "DOUBLE(%d,%d)",
                      oField.GetWidth(), oField.GetPrecision() );
         else
             strcpy( szFieldType, "DOUBLE" );
@@ -999,26 +1006,26 @@ OGRErr OGRMySQLTableLayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
     else if( oField.GetType() == OFTDate )
     {
         oField.SetDefault(NULL);
-        sprintf( szFieldType, "DATE" );
+        snprintf( szFieldType, sizeof(szFieldType), "DATE" );
     }
 
     else if( oField.GetType() == OFTDateTime )
     {
         if( oField.GetDefault() != NULL && EQUAL(oField.GetDefault(), "CURRENT_TIMESTAMP") )
-            sprintf( szFieldType, "TIMESTAMP" );
+            snprintf( szFieldType, sizeof(szFieldType), "TIMESTAMP" );
         else
-            sprintf( szFieldType, "DATETIME" );
+            snprintf( szFieldType, sizeof(szFieldType), "DATETIME" );
     }
 
     else if( oField.GetType() == OFTTime )
     {
         oField.SetDefault(NULL);
-        sprintf( szFieldType, "TIME" );
+        snprintf( szFieldType, sizeof(szFieldType), "TIME" );
     }
 
     else if( oField.GetType() == OFTBinary )
     {
-        sprintf( szFieldType, "LONGBLOB" );
+        snprintf( szFieldType, sizeof(szFieldType), "LONGBLOB" );
     }
 
     else if( oField.GetType() == OFTString )
@@ -1031,7 +1038,7 @@ OGRErr OGRMySQLTableLayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
                 strcpy( szFieldType, "TEXT" );
         }
         else
-            sprintf( szFieldType, "VARCHAR(%d)", oField.GetWidth() );
+            snprintf( szFieldType, sizeof(szFieldType), "VARCHAR(%d)", oField.GetWidth() );
     }
     else if( bApproxOK )
     {
@@ -1073,10 +1080,10 @@ OGRErr OGRMySQLTableLayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
     hResult = mysql_store_result( poDS->GetConn() );
     if( hResult != NULL )
         mysql_free_result( hResult );
-    hResult = NULL;   
+    hResult = NULL;
+
+    poFeatureDefn->AddFieldDefn( &oField );
 
-    poFeatureDefn->AddFieldDefn( &oField );    
-    
     return OGRERR_NONE;
 }
 
@@ -1104,8 +1111,8 @@ OGRFeature *OGRMySQLTableLayer::GetFeature( GIntBig nFeatureId )
     CPLString    osCommand;
 
     osCommand.Printf(
-             "SELECT %s FROM `%s` WHERE `%s` = " CPL_FRMT_GIB, 
-             pszFieldList, poFeatureDefn->GetName(), pszFIDColumn, 
+             "SELECT %s FROM `%s` WHERE `%s` = " CPL_FRMT_GIB,
+             pszFieldList, poFeatureDefn->GetName(), pszFIDColumn,
              nFeatureId );
     CPLFree( pszFieldList );
 
@@ -1178,7 +1185,7 @@ GIntBig OGRMySQLTableLayer::GetFeatureCount( CPL_UNUSED int bForce )
     MYSQL_RES    *hResult;
     const char         *pszCommand;
 
-    pszCommand = CPLSPrintf( "SELECT COUNT(*) FROM `%s` %s", 
+    pszCommand = CPLSPrintf( "SELECT COUNT(*) FROM `%s` %s",
                              poFeatureDefn->GetName(), pszWHERE );
 
     if( mysql_query( poDS->GetConn(), pszCommand ) )
@@ -1193,7 +1200,7 @@ GIntBig OGRMySQLTableLayer::GetFeatureCount( CPL_UNUSED int bForce )
         poDS->ReportError( "mysql_store_result() failed on SELECT COUNT(*)." );
         return FALSE;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Capture the result.                                             */
 /* -------------------------------------------------------------------- */
@@ -1206,7 +1213,7 @@ GIntBig OGRMySQLTableLayer::GetFeatureCount( CPL_UNUSED int bForce )
     if( hResult != NULL )
         mysql_free_result( hResult );
     hResult = NULL;
-    
+
     return nCount;
 }
 
@@ -1245,9 +1252,9 @@ OGRErr OGRMySQLTableLayer::GetExtent(OGREnvelope *psExtent, CPL_UNUSED int bForc
             return OGRERR_FAILURE;
         }
 
-		MYSQL_ROW row; 
+		MYSQL_ROW row;
 		unsigned long *panLengths = NULL;
-		while ((row = mysql_fetch_row(result)))
+		while ((row = mysql_fetch_row(result)) != NULL)
 		{
 			if (panLengths == NULL)
 			{
@@ -1261,10 +1268,10 @@ OGRErr OGRMySQLTableLayer::GetExtent(OGREnvelope *psExtent, CPL_UNUSED int bForc
 
 			OGRGeometry *poGeometry = NULL;
 			// Geometry columns will have the first 4 bytes contain the SRID.
-			OGRGeometryFactory::createFromWkb(((GByte *)row[0]) + 4, 
+			OGRGeometryFactory::createFromWkb(((GByte *)row[0]) + 4,
 											  NULL,
 											  &poGeometry,
-											  panLengths[0] - 4 );
+											  static_cast<int>(panLengths[0] - 4) );
 
 			if ( poGeometry != NULL )
 			{
@@ -1276,20 +1283,20 @@ OGRErr OGRMySQLTableLayer::GetExtent(OGREnvelope *psExtent, CPL_UNUSED int bForc
 				else if (poGeometry)
 				{
 					poGeometry->getEnvelope(&oEnv);
-					if (oEnv.MinX < psExtent->MinX) 
+					if (oEnv.MinX < psExtent->MinX)
 						psExtent->MinX = oEnv.MinX;
-					if (oEnv.MinY < psExtent->MinY) 
+					if (oEnv.MinY < psExtent->MinY)
 						psExtent->MinY = oEnv.MinY;
-					if (oEnv.MaxX > psExtent->MaxX) 
+					if (oEnv.MaxX > psExtent->MaxX)
 						psExtent->MaxX = oEnv.MaxX;
-					if (oEnv.MaxY > psExtent->MaxY) 
+					if (oEnv.MaxY > psExtent->MaxY)
 						psExtent->MaxY = oEnv.MaxY;
 				}
 				delete poGeometry;
 			}
 		}
 
-		mysql_free_result(result);      
+		mysql_free_result(result);
 	}
 
 	return (bExtentSet ? OGRERR_NONE : OGRERR_FAILURE);
diff --git a/ogr/ogrsf_frmts/nas/GNUmakefile b/ogr/ogrsf_frmts/nas/GNUmakefile
index 00e2833..10adfdd 100644
--- a/ogr/ogrsf_frmts/nas/GNUmakefile
+++ b/ogr/ogrsf_frmts/nas/GNUmakefile
@@ -7,6 +7,13 @@ OBJ =	ogrnasdriver.o ogrnasdatasource.o ogrnaslayer.o \
 CPPFLAGS :=	-I../gml -I.. -I../.. -DHAVE_XERCES=1 \
 		 $(XERCES_INCLUDE) $(CPPFLAGS)
 
+# To satisfy One Definition Rule, we have to define HAVE_EXPAT if it is used
+# by the GML driver so that the GMLHandler and GMLReader classes have the same
+# size
+ifeq ($(HAVE_EXPAT),yes)
+CPPFLAGS +=  -DHAVE_EXPAT
+endif
+
 # By default, XML validation is disabled.  Uncomment the following line to
 # enable XML schema validation in the parser.
 #CPPFLAGS +=  -DOGR_GML_VALIDATION=1
diff --git a/ogr/ogrsf_frmts/nas/makefile.vc b/ogr/ogrsf_frmts/nas/makefile.vc
index 13b2310..bb1f9d0 100644
--- a/ogr/ogrsf_frmts/nas/makefile.vc
+++ b/ogr/ogrsf_frmts/nas/makefile.vc
@@ -8,7 +8,14 @@ GDAL_ROOT	=	..\..\..
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
 !IFDEF XERCES_DIR
-EXTRAFLAGS =	-I.. -I..\.. -I..\gml $(XERCES_INCLUDE) -DHAVE_XERCES=1
+EXTRAFLAGS =	-I.. -I..\.. -I..\gml $(XERCES_INCLUDE) -DHAVE_XERCES=1 $(EXPAT_EXTRAFLAGS)
+!ENDIF
+
+# To satisfy One Definition Rule, we have to define HAVE_EXPAT if it is used
+# by the GML driver so that the GMLHandler and GMLReader classes have the same
+# size
+!IFDEF EXPAT_DIR
+EXPAT_EXTRAFLAGS =    $(EXPAT_INCLUDE) -DHAVE_EXPAT
 !ENDIF
 
 default:	$(OBJ)
diff --git a/ogr/ogrsf_frmts/nas/nashandler.cpp b/ogr/ogrsf_frmts/nas/nashandler.cpp
index f8ddacf..8389984 100644
--- a/ogr/ogrsf_frmts/nas/nashandler.cpp
+++ b/ogr/ogrsf_frmts/nas/nashandler.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: nashandler.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: nashandler.cpp 32898 2016-01-10 14:44:10Z goatbar $
  *
  * Project:  NAS Reader
  * Purpose:  Implementation of NASHandler class.
@@ -33,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-#define MAX_TOKEN_SIZE  1000
+static const int MAX_TOKEN_SIZE = 1000;
 
 /*
   Update modes:
@@ -75,18 +75,20 @@
 /*                             NASHandler()                             */
 /************************************************************************/
 
-NASHandler::NASHandler( NASReader *poReader )
-
-{
-    m_poReader = poReader;
-    m_pszCurField = NULL;
-    m_pszGeometry = NULL;
-    m_nGeomAlloc = m_nGeomLen = 0;
-    m_nDepthFeature = m_nDepthElement = m_nDepth = 0;
-    m_bIgnoreFeature = FALSE;
-    m_bInUpdate = FALSE;
-    m_bInUpdateProperty = FALSE;
-}
+NASHandler::NASHandler( NASReader *poReader ) :
+    m_poReader(poReader),
+    m_pszCurField(NULL),
+    m_pszGeometry(NULL),
+    m_nGeomAlloc(0),
+    m_nGeomLen(0),
+    m_nGeometryDepth(0),
+    m_nDepth(0),
+    m_nDepthFeature(0),
+    m_bIgnoreFeature(false),
+    m_bInUpdate(false),
+    m_bInUpdateProperty(false),
+    m_nDepthElement(0)
+{ }
 
 /************************************************************************/
 /*                            ~NASHandler()                             */
@@ -106,12 +108,11 @@ NASHandler::~NASHandler()
 CPLString NASHandler::GetAttributes(const Attributes* attrs)
 {
     CPLString osRes;
-    char *pszString;
 
     for(unsigned int i=0; i < attrs->getLength(); i++)
     {
         osRes += " ";
-        pszString = tr_strdup(attrs->getQName(i));
+        char *pszString = tr_strdup(attrs->getQName(i));
         osRes += pszString;
         CPLFree( pszString );
         osRes += "=\"";
@@ -128,15 +129,14 @@ CPLString NASHandler::GetAttributes(const Attributes* attrs)
 /*                            startElement()                            */
 /************************************************************************/
 
-void NASHandler::startElement(CPL_UNUSED const XMLCh* const uri,
-                              const XMLCh* const localname,
-                              CPL_UNUSED const XMLCh* const qname,
-                              const Attributes& attrs )
+void NASHandler::startElement( const XMLCh* const /* uri */,
+                               const XMLCh* const localname,
+                               const XMLCh* const /* qname */,
+                               const Attributes& attrs )
 
 {
     char        szElementName[MAX_TOKEN_SIZE];
     GMLReadState *poState = m_poReader->GetState();
-    const char *pszLast = NULL;
 
     tr_strcpy( szElementName, localname );
 
@@ -160,11 +160,13 @@ void NASHandler::startElement(CPL_UNUSED const XMLCh* const uri,
     }
 
 #ifdef DEBUG_VERBOSE
-    CPLDebug("NAS",
-              "%*sstartElement %s m_bIgnoreFeature:%d depth:%d depthFeature:%d featureClass:%s",
+    CPLDebug( "NAS",
+              "%*sstartElement %s m_bIgnoreFeature:%d depth:%d "
+              "depthFeature:%d featureClass:%s",
               m_nDepth, "", szElementName,
               m_bIgnoreFeature, m_nDepth, m_nDepthFeature,
-              poState->m_poFeature ? poState->m_poFeature->GetClass()->GetElementName() : "(no feature)"
+              poState->m_poFeature ? poState->m_poFeature->
+                  GetClass()->GetElementName() : "(no feature)"
             );
 #endif
 
@@ -184,10 +186,12 @@ void NASHandler::startElement(CPL_UNUSED const XMLCh* const uri,
 /*      If we are collecting geometry, or if we determine this is a     */
 /*      geometry element then append to the geometry info.              */
 /* -------------------------------------------------------------------- */
+    const char *pszLast = NULL;
+
     if( m_pszGeometry != NULL
         || IsGeometryElement( szElementName ) )
     {
-        int nLNLen = tr_strlen( localname );
+        const int nLNLen = tr_strlen( localname );
         CPLString osAttributes = GetAttributes( &attrs );
 
         /* should save attributes too! */
@@ -195,7 +199,8 @@ void NASHandler::startElement(CPL_UNUSED const XMLCh* const uri,
         if( m_pszGeometry == NULL )
             m_nGeometryDepth = poState->m_nPathLength;
 
-        if( m_nGeomLen + nLNLen + 4 + (int)osAttributes.size() > m_nGeomAlloc )
+        if( m_pszGeometry == NULL ||
+            m_nGeomLen + nLNLen + 4 + (int)osAttributes.size() > m_nGeomAlloc )
         {
             m_nGeomAlloc = (int) (m_nGeomAlloc * 1.3 + nLNLen + osAttributes.size() + 1000);
             m_pszGeometry = (char *)
@@ -212,7 +217,7 @@ void NASHandler::startElement(CPL_UNUSED const XMLCh* const uri,
         }
 
         strcat( m_pszGeometry+m_nGeomLen, ">" );
-        m_nGeomLen += strlen(m_pszGeometry+m_nGeomLen);
+        m_nGeomLen += static_cast<int>(strlen(m_pszGeometry+m_nGeomLen));
     }
 
 /* -------------------------------------------------------------------- */
@@ -222,43 +227,84 @@ void NASHandler::startElement(CPL_UNUSED const XMLCh* const uri,
 /* -------------------------------------------------------------------- */
     else if( EQUAL(szElementName,"Filter")
              && (pszLast = m_poReader->GetState()->GetLastComponent()) != NULL
-             && (EQUAL(pszLast,"Delete") || EQUAL(pszLast,"Replace") || EQUAL(pszLast,"Update")) )
+             && (EQUAL(pszLast,"Delete") || EQUAL(pszLast,"Replace") ||
+                 EQUAL(pszLast,"Update")) )
     {
         const char* pszFilteredClassName = m_poReader->GetFilteredClassName();
         if ( pszFilteredClassName != NULL &&
              strcmp("Delete", pszFilteredClassName) != 0 )
         {
-            m_bIgnoreFeature = TRUE;
+            m_bIgnoreFeature = true;
+            m_nDepthFeature = m_nDepth;
+            m_nDepth ++;
+
+            return;
+        }
+
+        if( m_osLastTypeName == "" )
+        {
+            CPLError( CE_Failure, CPLE_AssertionFailed,
+                      "m_osLastTypeName == \"\"");
+
+            m_bIgnoreFeature = true;
+            m_nDepthFeature = m_nDepth;
+            m_nDepth ++;
+            return;
+        }
+
+        if( EQUAL( pszLast, "Replace" )  &&
+            ( m_osLastReplacingFID == "" || m_osLastSafeToIgnore == "" ) )
+        {
+            CPLError( CE_Failure, CPLE_AssertionFailed,
+                      "m_osLastReplacingFID == \"\" || "
+                      "m_osLastSafeToIgnore == \"\"" );
+
+            m_bIgnoreFeature = true;
             m_nDepthFeature = m_nDepth;
             m_nDepth ++;
+            return;
+        }
 
+        if( EQUAL( pszLast, "Update" )  &&
+            ( m_osLastEnded == "" || m_osLastOccasion == "" ) )
+        {
+            CPLError( CE_Failure, CPLE_AssertionFailed,
+                      "m_osLastEnded == \"\" || m_osLastOccasion == \"\"" );
+
+            m_bIgnoreFeature = true;
+            m_nDepthFeature = m_nDepth;
+            m_nDepth ++;
             return;
         }
 
-        m_bIgnoreFeature = FALSE;
+        m_bIgnoreFeature = false;
 
         m_poReader->PushFeature( "Delete", attrs );
 
         m_nDepthFeature = m_nDepth;
         m_nDepth ++;
 
-        CPLAssert( m_osLastTypeName != "" );
-        m_poReader->SetFeaturePropertyDirectly( "typeName", CPLStrdup(m_osLastTypeName) );
+        m_poReader->SetFeaturePropertyDirectly(
+            "typeName", CPLStrdup(m_osLastTypeName) );
         m_poReader->SetFeaturePropertyDirectly( "context", CPLStrdup(pszLast) );
 
         if( EQUAL( pszLast, "Replace" ) )
         {
-            CPLAssert( m_osLastReplacingFID != "" );
-            CPLAssert( m_osLastSafeToIgnore != "" );
-            m_poReader->SetFeaturePropertyDirectly( "replacedBy", CPLStrdup(m_osLastReplacingFID) );
-            m_poReader->SetFeaturePropertyDirectly( "safeToIgnore", CPLStrdup(m_osLastSafeToIgnore) );
+            //CPLAssert( m_osLastReplacingFID != "" );
+            //CPLAssert( m_osLastSafeToIgnore != "" );
+            m_poReader->SetFeaturePropertyDirectly(
+                "replacedBy", CPLStrdup(m_osLastReplacingFID) );
+            m_poReader->SetFeaturePropertyDirectly(
+                "safeToIgnore", CPLStrdup(m_osLastSafeToIgnore) );
         }
         else if( EQUAL( pszLast, "Update" ) )
         {
-            CPLAssert( m_osLastEnded != "" );
-            CPLAssert( m_osLastOccasion != "" );
-            m_poReader->SetFeaturePropertyDirectly( "endet", CPLStrdup(m_osLastEnded) );
-            m_poReader->SetFeaturePropertyDirectly( "anlass", CPLStrdup(m_osLastOccasion) );
+            //CPLAssert( m_osLastEnded != "" );
+            //CPLAssert( m_osLastOccasion != "" );
+            m_poReader->SetFeaturePropertyDirectly(
+                "endet", CPLStrdup(m_osLastEnded) );
+            m_poReader->SetFeaturePropertyDirectly(
+                "anlass", CPLStrdup(m_osLastOccasion) );
             m_osLastEnded = "";
             m_osLastOccasion = "";
         }
@@ -278,14 +324,22 @@ void NASHandler::startElement(CPL_UNUSED const XMLCh* const uri,
         pszLast = m_poReader->GetState()->GetLastComponent();
         if( pszLast != NULL && EQUAL(pszLast,"Replace") )
         {
-            int nIndex;
             XMLCh  Name[100];
 
             tr_strcpy( Name, "gml:id" );
-            nIndex = attrs.getIndex( Name );
+            int nIndex = attrs.getIndex( Name );
+
+            if( nIndex == -1 || m_osLastReplacingFID !="" )
+            {
+                CPLError( CE_Failure, CPLE_AssertionFailed,
+                          "nIndex == -1 || m_osLastReplacingFID !=\"\"" );
 
-            CPLAssert( nIndex!=-1 );
-            CPLAssert( m_osLastReplacingFID=="" );
+                m_bIgnoreFeature = true;
+                m_nDepthFeature = m_nDepth;
+                m_nDepth ++;
+
+                return;
+            }
 
             // Capture "gml:id" attribute as part of the property value -
             // primarily this is for the wfsext:Replace operation's attribute.
@@ -294,21 +348,23 @@ void NASHandler::startElement(CPL_UNUSED const XMLCh* const uri,
             CPLFree( pszReplacingFID );
 
 #ifdef DEBUG_VERBOSE
-            CPLDebug("NAS", "%*s### Replace typeName=%s replacedBy=%s", m_nDepth, "", m_osLastTypeName.c_str(), m_osLastReplacingFID.c_str() );
+            CPLDebug( "NAS", "%*s### Replace typeName=%s replacedBy=%s",
+                      m_nDepth, "", m_osLastTypeName.c_str(),
+                      m_osLastReplacingFID.c_str() );
 #endif
         }
 
         if ( pszFilteredClassName != NULL &&
              strcmp(szElementName, pszFilteredClassName) != 0 )
         {
-            m_bIgnoreFeature = TRUE;
+            m_bIgnoreFeature = true;
             m_nDepthFeature = m_nDepth;
             m_nDepth ++;
 
             return;
         }
 
-        m_bIgnoreFeature = FALSE;
+        m_bIgnoreFeature = false;
 
         m_poReader->PushFeature( szElementName, attrs );
 
@@ -325,11 +381,10 @@ void NASHandler::startElement(CPL_UNUSED const XMLCh* const uri,
 /* -------------------------------------------------------------------- */
     else if( EQUAL(szElementName,"Delete") || EQUAL(szElementName,"Update") )
     {
-        int nIndex;
         XMLCh  Name[100];
 
         tr_strcpy( Name, "typeName" );
-        nIndex = attrs.getIndex( Name );
+        int nIndex = attrs.getIndex( Name );
 
         if( nIndex != -1 )
         {
@@ -343,16 +398,17 @@ void NASHandler::startElement(CPL_UNUSED const XMLCh* const uri,
 
         if( EQUAL(szElementName,"Update") )
         {
-            m_bInUpdate = TRUE;
+            m_bInUpdate = true;
         }
     }
 
     else if ( m_bInUpdate && EQUAL(szElementName, "Property") )
     {
-        m_bInUpdateProperty = TRUE;
+        m_bInUpdateProperty = true;
     }
 
-    else if ( m_bInUpdateProperty && ( EQUAL(szElementName, "Name" ) || EQUAL(szElementName, "Value" ) ) )
+    else if ( m_bInUpdateProperty && ( EQUAL(szElementName, "Name" ) ||
+                                       EQUAL(szElementName, "Value" ) ) )
     {
         // collect attribute name or value
         CPLFree( m_pszCurField );
@@ -366,11 +422,10 @@ void NASHandler::startElement(CPL_UNUSED const XMLCh* const uri,
 /* -------------------------------------------------------------------- */
     else if( EQUAL(szElementName,"Replace") )
     {
-        int nIndex;
         XMLCh  Name[100];
 
         tr_strcpy( Name, "safeToIgnore" );
-        nIndex = attrs.getIndex( Name );
+        int nIndex = attrs.getIndex( Name );
 
         if( nIndex != -1 )
         {
@@ -380,7 +435,8 @@ void NASHandler::startElement(CPL_UNUSED const XMLCh* const uri,
         }
         else
         {
-            CPLError( CE_Warning, CPLE_AppDefined, "NAS: safeToIgnore attribute missing" );
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "NAS: safeToIgnore attribute missing" );
             m_osLastSafeToIgnore = "false";
         }
 
@@ -416,25 +472,23 @@ void NASHandler::startElement(CPL_UNUSED const XMLCh* const uri,
 /************************************************************************/
 /*                             endElement()                             */
 /************************************************************************/
-void NASHandler::endElement(CPL_UNUSED const XMLCh* const uri,
-                            const XMLCh* const localname,
-                            CPL_UNUSED const XMLCh* const qname )
+void NASHandler::endElement( const XMLCh* const /* uri */ ,
+                             const XMLCh* const localname,
+                             const XMLCh* const /* qname */)
 
 {
     char        szElementName[MAX_TOKEN_SIZE];
     GMLReadState *poState = m_poReader->GetState();
-    const char  *pszLast;
 
     tr_strcpy( szElementName, localname );
 
-
     m_nDepth --;
 
     if (m_bIgnoreFeature && m_nDepth >= m_nDepthFeature)
     {
         if (m_nDepth == m_nDepthFeature)
         {
-            m_bIgnoreFeature = FALSE;
+            m_bIgnoreFeature = false;
             m_nDepthFeature = 0;
         }
         return;
@@ -494,7 +548,7 @@ void NASHandler::endElement(CPL_UNUSED const XMLCh* const uri,
 
            m_osLastPropertyName = "";
            m_osLastPropertyValue = "";
-           m_bInUpdateProperty = FALSE;
+           m_bInUpdateProperty = false;
        }
 
        poState->PopPath();
@@ -504,7 +558,7 @@ void NASHandler::endElement(CPL_UNUSED const XMLCh* const uri,
 
    if ( m_bInUpdate && EQUAL( szElementName, "Update" ) )
    {
-       m_bInUpdate = FALSE;
+       m_bInUpdate = false;
    }
 
 /* -------------------------------------------------------------------- */
@@ -541,7 +595,7 @@ void NASHandler::endElement(CPL_UNUSED const XMLCh* const uri,
         strcat( m_pszGeometry+m_nGeomLen, "</" );
         tr_strcpy( m_pszGeometry+m_nGeomLen+2, localname );
         strcat( m_pszGeometry+m_nGeomLen+nLNLen+2, ">" );
-        m_nGeomLen += strlen(m_pszGeometry+m_nGeomLen);
+        m_nGeomLen += static_cast<int>(strlen(m_pszGeometry+m_nGeomLen));
 
         if( poState->m_nPathLength == m_nGeometryDepth+1 )
         {
@@ -605,6 +659,8 @@ void NASHandler::endElement(CPL_UNUSED const XMLCh* const uri,
 /*      element name for the class, then we have finished the           */
 /*      feature, and we pop the feature read state.                     */
 /* -------------------------------------------------------------------- */
+    const char *pszLast = NULL;
+
     if( m_nDepth == m_nDepthFeature && poState->m_poFeature != NULL
         && EQUAL(szElementName,
                  poState->m_poFeature->GetClass()->GetElementName()) )
@@ -620,7 +676,8 @@ void NASHandler::endElement(CPL_UNUSED const XMLCh* const uri,
     else if( m_nDepth == m_nDepthFeature
              && poState->m_poFeature != NULL
              && EQUAL(szElementName,"Filter")
-             && (pszLast=poState->m_poFeature->GetClass()->GetElementName()) != NULL
+             && (pszLast=poState->m_poFeature->GetClass()->GetElementName())
+                != NULL
              && ( EQUAL(pszLast, "Delete") || EQUAL(pszLast, "Update") ) )
     {
         m_nDepthFeature = 0;
@@ -637,7 +694,7 @@ void NASHandler::endElement(CPL_UNUSED const XMLCh* const uri,
             poState->PopPath();
         else
         {
-            CPLAssert( FALSE );
+            CPLAssert( false );
         }
     }
 }
@@ -648,22 +705,23 @@ void NASHandler::endElement(CPL_UNUSED const XMLCh* const uri,
 
 #if XERCES_VERSION_MAJOR >= 3
 void NASHandler::characters( const XMLCh *const chars_in,
-                             CPL_UNUSED const XMLSize_t length )
+                             const XMLSize_t /* length */ )
 #else
 void NASHandler::characters( const XMLCh* const chars_in,
-                             CPL_UNUSED const unsigned int length )
+                             const unsigned int /* length */ )
 #endif
 {
     const XMLCh *chars = chars_in;
 
     if( m_pszCurField != NULL )
     {
-        int     nCurFieldLength = strlen(m_pszCurField);
+        const int nCurFieldLength = static_cast<int>(strlen(m_pszCurField));
 
         if (nCurFieldLength == 0)
         {
             // Ignore white space
-            while( *chars == ' ' || *chars == 10 || *chars == 13 || *chars == '\t')
+            while( *chars == ' ' || *chars == 10 || *chars == 13 ||
+                   *chars == '\t')
                 chars++;
         }
 
@@ -672,13 +730,12 @@ void NASHandler::characters( const XMLCh* const chars_in,
         if( m_pszCurField == NULL )
         {
             m_pszCurField = pszTranslated;
-            nCurFieldLength = strlen(m_pszCurField);
         }
         else
         {
-            m_pszCurField = (char *)
+            m_pszCurField = static_cast<char *>(
                 CPLRealloc( m_pszCurField,
-                            nCurFieldLength+strlen(pszTranslated)+1 );
+                            nCurFieldLength+strlen(pszTranslated)+1 ) );
             strcpy( m_pszCurField + nCurFieldLength, pszTranslated );
             CPLFree( pszTranslated );
         }
@@ -688,11 +745,12 @@ void NASHandler::characters( const XMLCh* const chars_in,
         if (m_nGeomLen == 0)
         {
             // Ignore white space
-            while( *chars == ' ' || *chars == 10 || *chars == 13 || *chars == '\t')
+            while( *chars == ' ' || *chars == 10 || *chars == 13 ||
+                   *chars == '\t')
                 chars++;
         }
 
-        int nCharsLen = tr_strlen(chars);
+        const int nCharsLen = tr_strlen(chars);
 
         if( m_nGeomLen + nCharsLen*4 + 4 > m_nGeomAlloc )
         {
@@ -702,7 +760,7 @@ void NASHandler::characters( const XMLCh* const chars_in,
         }
 
         tr_strcpy( m_pszGeometry+m_nGeomLen, chars );
-        m_nGeomLen += strlen(m_pszGeometry+m_nGeomLen);
+        m_nGeomLen += static_cast<int>(strlen(m_pszGeometry+m_nGeomLen));
     }
 }
 
@@ -713,12 +771,12 @@ void NASHandler::characters( const XMLCh* const chars_in,
 void NASHandler::fatalError( const SAXParseException &exception)
 
 {
-    char *pszErrorMessage;
-
-    pszErrorMessage = tr_strdup( exception.getMessage() );
+    char *pszErrorMessage = tr_strdup( exception.getMessage() );
     CPLError( CE_Failure, CPLE_AppDefined,
               "XML Parsing Error: %s at line %d, column %d\n",
-              pszErrorMessage, (int)exception.getLineNumber(), (int)exception.getColumnNumber() );
+              pszErrorMessage,
+              static_cast<int>(exception.getLineNumber()),
+              static_cast<int>(exception.getColumnNumber()) );
 
     CPLFree( pszErrorMessage );
 }
@@ -727,7 +785,7 @@ void NASHandler::fatalError( const SAXParseException &exception)
 /*                         IsGeometryElement()                          */
 /************************************************************************/
 
-int NASHandler::IsGeometryElement( const char *pszElement )
+bool NASHandler::IsGeometryElement( const char *pszElement )
 
 {
     return strcmp(pszElement,"Polygon") == 0
diff --git a/ogr/ogrsf_frmts/nas/nasreader.cpp b/ogr/ogrsf_frmts/nas/nasreader.cpp
index b950c74..c31e94a 100644
--- a/ogr/ogrsf_frmts/nas/nasreader.cpp
+++ b/ogr/ogrsf_frmts/nas/nasreader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nasreader.cpp 29051 2015-04-29 17:18:37Z rouault $
+ * $Id: nasreader.cpp 33095 2016-01-22 17:55:56Z rouault $
  *
  * Project:  NAS Reader
  * Purpose:  Implementation of NASReader class.
@@ -28,6 +28,7 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "gmlreaderp.h"
 #include "gmlreader.h"
 #include "cpl_error.h"
 #include "cpl_string.h"
@@ -52,7 +53,7 @@
 CPLMutex *NASReader::hMutex = NULL;
 
 /************************************************************************/
-/*                          CreateGMLReader()                           */
+/*                          CreateNASReader()                           */
 /************************************************************************/
 
 IGMLReader *CreateNASReader()
@@ -62,27 +63,21 @@ IGMLReader *CreateNASReader()
 }
 
 /************************************************************************/
-/*                             GMLReader()                              */
+/*                             NASReader()                              */
 /************************************************************************/
 
-NASReader::NASReader()
-
-{
-    m_nClassCount = 0;
-    m_papoClass = NULL;
-
-    m_bClassListLocked = FALSE;
-
-    m_poNASHandler = NULL;
-    m_poSAXReader = NULL;
-    m_bReadStarted = FALSE;
-
-    m_poState = NULL;
-    m_poCompleteFeature = NULL;
-
-    m_pszFilename = NULL;
-    m_pszFilteredClassName = NULL;
-}
+NASReader::NASReader() :
+    m_bClassListLocked(false),
+    m_nClassCount(0),
+    m_papoClass(NULL),
+    m_pszFilename(NULL),
+    m_poNASHandler(NULL),
+    m_poSAXReader(NULL),
+    m_bReadStarted(false),
+    m_poState(NULL),
+    m_poCompleteFeature(NULL),
+    m_pszFilteredClassName(NULL)
+{}
 
 /************************************************************************/
 /*                             ~NASReader()                             */
@@ -97,7 +92,7 @@ NASReader::~NASReader()
 
     CleanupParser();
 
-    if (CSLTestBoolean(CPLGetConfigOption("NAS_XERCES_TERMINATE", "FALSE")))
+    if (CPLTestBool(CPLGetConfigOption("NAS_XERCES_TERMINATE", "FALSE")))
         XMLPlatformUtils::Terminate();
 
     CPLFree( m_pszFilteredClassName );
@@ -128,14 +123,14 @@ const char* NASReader::GetSourceFileName()
 /*                            SetupParser()                             */
 /************************************************************************/
 
-int NASReader::SetupParser()
+bool NASReader::SetupParser()
 
 {
     {
     CPLMutexHolderD(&hMutex);
-    static int bXercesInitialized = -1;
+    static int nXercesInitialized = -1;
 
-    if( bXercesInitialized < 0)
+    if( nXercesInitialized < 0)
     {
         try
         {
@@ -147,13 +142,13 @@ int NASReader::SetupParser()
             CPLError( CE_Warning, CPLE_AppDefined,
                       "Exception initializing Xerces based GML reader.\n%s",
                       tr_strdup(toCatch.getMessage()) );
-            bXercesInitialized = FALSE;
-            return FALSE;
+            nXercesInitialized = FALSE;
+            return false;
         }
-        bXercesInitialized = TRUE;
+        nXercesInitialized = TRUE;
     }
-    if( !bXercesInitialized )
-        return FALSE;
+    if( !nXercesInitialized )
+        return false;
     }
 
     // Cleanup any old parser.
@@ -175,8 +170,10 @@ int NASReader::SetupParser()
         m_poSAXReader->setEntityResolver( m_poNASHandler );
         m_poSAXReader->setDTDHandler( m_poNASHandler );
 
-        xmlUriValid = XMLString::transcode("http://xml.org/sax/features/validation");
-        xmlUriNS = XMLString::transcode("http://xml.org/sax/features/namespaces");
+        xmlUriValid =
+            XMLString::transcode("http://xml.org/sax/features/validation");
+        xmlUriNS =
+            XMLString::transcode("http://xml.org/sax/features/namespaces");
 
 #if (OGR_GML_VALIDATION)
         m_poSAXReader->setFeature( xmlUriValid, true);
@@ -207,15 +204,15 @@ int NASReader::SetupParser()
 
         CPLError( CE_Warning, CPLE_AppDefined,
                   "Exception initializing Xerces based GML reader.\n" );
-        return FALSE;
+        return false;
     }
 
-    m_bReadStarted = FALSE;
+    m_bReadStarted = false;
 
     // Push an empty state.
     PushState( new GMLReadState() );
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -240,7 +237,7 @@ void NASReader::CleanupParser()
     delete m_poCompleteFeature;
     m_poCompleteFeature = NULL;
 
-    m_bReadStarted = FALSE;
+    m_bReadStarted = false;
 }
 
 /************************************************************************/
@@ -261,7 +258,7 @@ GMLFeature *NASReader::NextFeature()
 
             if( !m_poSAXReader->parseFirst( m_pszFilename, m_oToFill ) )
                 return NULL;
-            m_bReadStarted = TRUE;
+            m_bReadStarted = true;
         }
 
         while( m_poCompleteFeature == NULL
@@ -295,12 +292,11 @@ void NASReader::PushFeature( const char *pszElement,
                              const Attributes &attrs )
 
 {
-    int iClass;
-
 /* -------------------------------------------------------------------- */
 /*      Find the class of this element.                                 */
 /* -------------------------------------------------------------------- */
-    for( iClass = 0; iClass < GetClassCount(); iClass++ )
+    int iClass = 0;
+    for( ; iClass < GetClassCount(); iClass++ )
     {
         if( EQUAL(pszElement,GetClass(iClass)->GetElementName()) )
             break;
@@ -327,9 +323,7 @@ void NASReader::PushFeature( const char *pszElement,
 /* -------------------------------------------------------------------- */
 /*      Create and push a new read state.                               */
 /* -------------------------------------------------------------------- */
-    GMLReadState *poState;
-
-    poState = new GMLReadState();
+    GMLReadState *poState = new GMLReadState();
     poState->m_poFeature = poFeature;
     PushState( poState );
 
@@ -337,11 +331,10 @@ void NASReader::PushFeature( const char *pszElement,
 /*      Check for gml:id, and if found push it as an attribute named    */
 /*      gml_id.                                                         */
 /* -------------------------------------------------------------------- */
-    int nFIDIndex;
     XMLCh   anFID[100];
 
     tr_strcpy( anFID, "gml:id" );
-    nFIDIndex = attrs.getIndex( anFID );
+    int nFIDIndex = attrs.getIndex( anFID );
     if( nFIDIndex != -1 )
     {
         char *pszFID = tr_strdup( attrs.getValue( nFIDIndex ) );
@@ -357,13 +350,13 @@ void NASReader::PushFeature( const char *pszElement,
 /*      GML feature element?                                            */
 /************************************************************************/
 
-int NASReader::IsFeatureElement( const char *pszElement )
+bool NASReader::IsFeatureElement( const char *pszElement )
 
 {
     CPLAssert( m_poState != NULL );
 
     const char *pszLast = m_poState->GetLastComponent();
-    int        nLen = strlen(pszLast);
+    const int nLen = static_cast<int>(strlen(pszLast));
 
     // There seem to be two major NAS classes of feature identifiers
     // -- either a wfs:Insert or a gml:featureMember.
@@ -371,39 +364,39 @@ int NASReader::IsFeatureElement( const char *pszElement )
     if( (nLen < 6 || !EQUAL(pszLast+nLen-6,"Insert"))
         && (nLen < 13 || !EQUAL(pszLast+nLen-13,"featureMember"))
         && (nLen < 7 || !EQUAL(pszLast+nLen-7,"Replace")) )
-        return FALSE;
+        return false;
 
     // If the class list isn't locked, any element that is a featureMember
     // will do.
     if( !IsClassListLocked() )
-        return TRUE;
+        return true;
 
     // otherwise, find a class with the desired element name.
     for( int i = 0; i < GetClassCount(); i++ )
     {
         if( EQUAL(pszElement,GetClass(i)->GetElementName()) )
-            return TRUE;
+            return true;
     }
 
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
 /*                         IsAttributeElement()                         */
 /************************************************************************/
 
-int NASReader::IsAttributeElement( const char *pszElement )
+bool NASReader::IsAttributeElement( const char *pszElement )
 
 {
     if( m_poState->m_poFeature == NULL )
-        return FALSE;
+        return false;
 
     GMLFeatureClass *poClass = m_poState->m_poFeature->GetClass();
 
     // If the schema is not yet locked, then any simple element
     // is potentially an attribute.
     if( !poClass->IsSchemaLocked() )
-        return TRUE;
+        return true;
 
     // Otherwise build the path to this element into a single string
     // and compare against known attributes.
@@ -420,9 +413,9 @@ int NASReader::IsAttributeElement( const char *pszElement )
 
     for( int i = 0; i < poClass->GetPropertyCount(); i++ )
         if( EQUAL(poClass->GetProperty(i)->GetSrcElement(),osElemPath) )
-            return TRUE;
+            return true;
 
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
@@ -440,9 +433,7 @@ void NASReader::PopState()
             m_poState->m_poFeature = NULL;
         }
 
-        GMLReadState *poParent;
-
-        poParent = m_poState->m_poParentState;
+        GMLReadState *poParent = m_poState->m_poParentState;
 
         delete m_poState;
         m_poState = poParent;
@@ -469,8 +460,8 @@ GMLFeatureClass *NASReader::GetClass( int iClass ) const
 {
     if( iClass < 0 || iClass >= m_nClassCount )
         return NULL;
-    else
-        return m_papoClass[iClass];
+
+    return m_papoClass[iClass];
 }
 
 /************************************************************************/
@@ -503,7 +494,8 @@ int NASReader::AddClass( GMLFeatureClass *poNewClass )
         CPLRealloc( m_papoClass, sizeof(void*) * m_nClassCount );
 
     // keep delete the last entry
-    if( m_nClassCount > 1 && EQUAL( m_papoClass[m_nClassCount-2]->GetName(), "Delete" ) )
+    if( m_nClassCount > 1 &&
+        EQUAL( m_papoClass[m_nClassCount-2]->GetName(), "Delete" ) )
     {
       m_papoClass[m_nClassCount-1] = m_papoClass[m_nClassCount-2];
       m_papoClass[m_nClassCount-2] = poNewClass;
@@ -552,9 +544,9 @@ void NASReader::SetFeaturePropertyDirectly( const char *pszElement,
 /*      it.                                                             */
 /* -------------------------------------------------------------------- */
     GMLFeatureClass *poClass = poFeature->GetClass();
-    int      iProperty;
+    int iProperty = 0;
 
-    for( iProperty=0; iProperty < poClass->GetPropertyCount(); iProperty++ )
+    for( ; iProperty < poClass->GetPropertyCount(); iProperty++ )
     {
         if( EQUAL(poClass->GetProperty( iProperty )->GetSrcElement(),
                   pszElement ) )
@@ -595,7 +587,8 @@ void NASReader::SetFeaturePropertyDirectly( const char *pszElement,
         poClass->AddProperty( poPDefn );
     }
 
-    if ( GMLPropertyDefn::IsSimpleType( poClass->GetProperty( iProperty )->GetType() ) )
+    if ( GMLPropertyDefn::IsSimpleType(
+             poClass->GetProperty( iProperty )->GetType() ) )
     {
         const GMLProperty *poProp = poFeature->GetProperty(iProperty);
         if ( poProp && poProp->nSubProperties > 0 )
@@ -603,17 +596,20 @@ void NASReader::SetFeaturePropertyDirectly( const char *pszElement,
             int iId = poClass->GetPropertyIndex( "gml_id" );
             const GMLProperty *poIdProp = poFeature->GetProperty(iId);
 
-            CPLDebug("NAS",
-                     "Overwriting existing property %s.%s of value '%s' with '%s' (gml_id: %s).",
-                     poClass->GetName(), pszElement,
-                     poProp->papszSubProperties[0], pszValue,
-                     poIdProp && poIdProp->nSubProperties>0 && poIdProp->papszSubProperties[0] ? poIdProp->papszSubProperties[0] : "(null)" );
+            CPLDebug( "NAS",
+                      "Overwriting existing property %s.%s of value '%s' "
+                      "with '%s' (gml_id: %s).",
+                      poClass->GetName(), pszElement,
+                      poProp->papszSubProperties[0], pszValue,
+                      poIdProp && poIdProp->nSubProperties>0 &&
+                      poIdProp->papszSubProperties[0] ?
+                      poIdProp->papszSubProperties[0] : "(null)" );
         }
     }
 
 /* -------------------------------------------------------------------- */
 /*      We want to handle <lage> specially to ensure it is zero         */
-/*      filled, and treated as a string depspite the numeric            */
+/*      filled, and treated as a string despite the numeric             */
 /*      content. https://trac.wheregroup.com/PostNAS/ticket/9           */
 /* -------------------------------------------------------------------- */
     if( strcmp(poClass->GetProperty(iProperty)->GetName(),"lage") == 0 )
@@ -622,7 +618,8 @@ void NASReader::SetFeaturePropertyDirectly( const char *pszElement,
         {
             CPLString osValue = "00000";
             osValue += pszValue;
-            poFeature->SetPropertyDirectly( iProperty, CPLStrdup(osValue + osValue.size() - 5) );
+            poFeature->SetPropertyDirectly(
+                iProperty, CPLStrdup(osValue + osValue.size() - 5) );
             CPLFree(pszValue);
         }
         else
@@ -635,11 +632,13 @@ void NASReader::SetFeaturePropertyDirectly( const char *pszElement,
         }
         return;
     }
-    else if( strcmp(poClass->GetProperty(iProperty)->GetName(),"kartendarstellung") == 0 ||
-             strcmp(poClass->GetProperty(iProperty)->GetName(),"rechtsbehelfsverfahren") == 0 )
+    else if( strcmp( poClass->GetProperty(iProperty)->GetName(),
+                     "kartendarstellung") == 0 ||
+             strcmp( poClass->GetProperty(iProperty)->GetName(),
+                     "rechtsbehelfsverfahren") == 0 )
     {
-        poFeature->SetPropertyDirectly( iProperty,
-                                        CPLStrdup( EQUAL( pszValue, "true" ) ? "1" : "0" ) );
+        poFeature->SetPropertyDirectly(
+            iProperty, CPLStrdup( EQUAL( pszValue, "true" ) ? "1" : "0" ) );
         CPLFree(pszValue);
 
         if( !poClass->IsSchemaLocked() )
@@ -666,7 +665,8 @@ void NASReader::SetFeaturePropertyDirectly( const char *pszElement,
             poClass->GetProperty(iProperty)->SetWidth( 15 );
             poClass->GetProperty(iProperty)->SetType( GMLPT_String );
         }
-        // Special handling for artDerFlurstuecksgrenze per http://trac.osgeo.org/gdal/ticket/4255
+        // Special handling for artDerFlurstuecksgrenze per
+        // http://trac.osgeo.org/gdal/ticket/4255
         else if( strcmp(poClass->GetProperty(iProperty)->GetName(),
                    "artDerFlurstuecksgrenze") == 0)
         {
@@ -682,55 +682,51 @@ void NASReader::SetFeaturePropertyDirectly( const char *pszElement,
 /*                            LoadClasses()                             */
 /************************************************************************/
 
-int NASReader::LoadClasses( const char *pszFile )
+bool NASReader::LoadClasses( const char *pszFile )
 
 {
     // Add logic later to determine reasonable default schema file.
     if( pszFile == NULL )
-        return FALSE;
+        return false;
 
 /* -------------------------------------------------------------------- */
 /*      Load the raw XML file.                                          */
 /* -------------------------------------------------------------------- */
-    FILE       *fp;
-    int         nLength;
-    char        *pszWholeText;
-
-    fp = VSIFOpen( pszFile, "rb" );
+    VSILFILE   *fp = VSIFOpenL( pszFile, "rb" );
 
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
                   "Failed to open file %s.", pszFile );
-        return FALSE;
+        return false;
     }
 
-    VSIFSeek( fp, 0, SEEK_END );
-    nLength = VSIFTell( fp );
-    VSIFSeek( fp, 0, SEEK_SET );
+    VSIFSeekL( fp, 0, SEEK_END );
+    const int nLength = static_cast<int>(VSIFTellL( fp ));
+    VSIFSeekL( fp, 0, SEEK_SET );
 
-    pszWholeText = (char *) VSIMalloc(nLength+1);
+    char *pszWholeText = static_cast<char *>( VSIMalloc(nLength+1) );
     if( pszWholeText == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Failed to allocate %d byte buffer for %s,\n"
                   "is this really a GMLFeatureClassList file?",
                   nLength, pszFile );
-        VSIFClose( fp );
-        return FALSE;
+        VSIFCloseL( fp );
+        return false;
     }
 
-    if( VSIFRead( pszWholeText, nLength, 1, fp ) != 1 )
+    if( VSIFReadL( pszWholeText, nLength, 1, fp ) != 1 )
     {
         VSIFree( pszWholeText );
-        VSIFClose( fp );
+        VSIFCloseL( fp );
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Read failed on %s.", pszFile );
-        return FALSE;
+        return false;
     }
     pszWholeText[nLength] = '\0';
 
-    VSIFClose( fp );
+    VSIFCloseL( fp );
 
     if( strstr( pszWholeText, "<GMLFeatureClassList>" ) == NULL )
     {
@@ -738,20 +734,18 @@ int NASReader::LoadClasses( const char *pszFile )
         CPLError( CE_Failure, CPLE_AppDefined,
                   "File %s does not contain a GMLFeatureClassList tree.",
                   pszFile );
-        return FALSE;
+        return false;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Convert to XML parse tree.                                      */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psRoot;
-
-    psRoot = CPLParseXMLString( pszWholeText );
+    CPLXMLNode *psRoot = CPLParseXMLString( pszWholeText );
     VSIFree( pszWholeText );
 
     // We assume parser will report errors via CPL.
     if( psRoot == NULL )
-        return FALSE;
+        return false;
 
     if( psRoot->eType != CXT_Element
         || !EQUAL(psRoot->pszValue,"GMLFeatureClassList") )
@@ -760,31 +754,29 @@ int NASReader::LoadClasses( const char *pszFile )
         CPLError( CE_Failure, CPLE_AppDefined,
                   "File %s is not a GMLFeatureClassList document.",
                   pszFile );
-        return FALSE;
+        return false;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Extract feature classes for all definitions found.              */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psThis;
-
-    for( psThis = psRoot->psChild; psThis != NULL; psThis = psThis->psNext )
+    for( CPLXMLNode *psThis = psRoot->psChild;
+         psThis != NULL;
+         psThis = psThis->psNext )
     {
         if( psThis->eType == CXT_Element
             && EQUAL(psThis->pszValue,"GMLFeatureClass") )
         {
-            GMLFeatureClass   *poClass;
-
-            poClass = new GMLFeatureClass();
+            GMLFeatureClass *poClass = new GMLFeatureClass();
 
             if( !poClass->InitializeFromXML( psThis ) )
             {
                 delete poClass;
                 CPLDestroyXMLNode( psRoot );
-                return FALSE;
+                return false;
             }
 
-            poClass->SetSchemaLocked( TRUE );
+            poClass->SetSchemaLocked( true );
 
             AddClass( poClass );
         }
@@ -792,28 +784,27 @@ int NASReader::LoadClasses( const char *pszFile )
 
     CPLDestroyXMLNode( psRoot );
 
-    SetClassListLocked( TRUE );
+    SetClassListLocked( true );
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                            SaveClasses()                             */
 /************************************************************************/
 
-int NASReader::SaveClasses( const char *pszFile )
+bool NASReader::SaveClasses( const char *pszFile )
 
 {
     // Add logic later to determine reasonable default schema file.
     if( pszFile == NULL )
-        return FALSE;
+        return false;
 
 /* -------------------------------------------------------------------- */
 /*      Create in memory schema tree.                                   */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psRoot;
-
-    psRoot = CPLCreateXMLNode( NULL, CXT_Element, "GMLFeatureClassList" );
+    CPLXMLNode *psRoot =
+        CPLCreateXMLNode( NULL, CXT_Element, "GMLFeatureClassList" );
 
     for( int iClass = 0; iClass < GetClassCount(); iClass++ )
     {
@@ -825,20 +816,21 @@ int NASReader::SaveClasses( const char *pszFile )
 /* -------------------------------------------------------------------- */
 /*      Serialize to disk.                                              */
 /* -------------------------------------------------------------------- */
-    FILE        *fp;
-    int         bSuccess = TRUE;
+    bool         bSuccess = true;
     char        *pszWholeText = CPLSerializeXMLTree( psRoot );
 
     CPLDestroyXMLNode( psRoot );
 
-    fp = VSIFOpen( pszFile, "wb" );
+    FILE *fp = VSIFOpen( pszFile, "wb" );
 
     if( fp == NULL )
-        bSuccess = FALSE;
-    else if( VSIFWrite( pszWholeText, strlen(pszWholeText), 1, fp ) != 1 )
-        bSuccess = FALSE;
+        bSuccess = false;
     else
+    {
+        if( VSIFWrite( pszWholeText, strlen(pszWholeText), 1, fp ) != 1 )
+            bSuccess = false;
         VSIFClose( fp );
+    }
 
     CPLFree( pszWholeText );
 
@@ -854,22 +846,21 @@ int NASReader::SaveClasses( const char *pszFile )
 /*      looking for schema information.                                 */
 /************************************************************************/
 
-int NASReader::PrescanForSchema( int bGetExtents,
-                                 CPL_UNUSED int bAnalyzeSRSPerFeature,
-                                 CPL_UNUSED int bOnlyDetectSRS )
+bool NASReader::PrescanForSchema( bool bGetExtents,
+                                  bool /*bAnalyzeSRSPerFeature*/,
+                                  bool /*bOnlyDetectSRS*/ )
 {
-    GMLFeature  *poFeature;
-
     if( m_pszFilename == NULL )
-        return FALSE;
+        return false;
 
-    SetClassListLocked( FALSE );
+    SetClassListLocked( false );
 
     ClearClasses();
     if( !SetupParser() )
-        return FALSE;
+        return false;
 
     std::string osWork;
+    GMLFeature  *poFeature;
 
     while( (poFeature = NextFeature()) != NULL )
     {
@@ -898,13 +889,14 @@ int NASReader::PrescanForSchema( int bGetExtents,
                 OGREnvelope sEnvelope;
 
                 if( poClass->GetGeometryPropertyCount() == 0 )
-                    poClass->AddGeometryProperty( new GMLGeometryPropertyDefn( "", "", wkbUnknown, -1, TRUE ) );
+                    poClass->AddGeometryProperty(
+                        new GMLGeometryPropertyDefn( "", "", wkbUnknown, -1, true ) );
 
                 OGRwkbGeometryType eGType = (OGRwkbGeometryType)
                     poClass->GetGeometryProperty(0)->GetType();
 
                 // Merge SRSName into layer.
-                const char* pszSRSName = GML_ExtractSrsNameFromGeometry(papsGeometry, osWork, FALSE);
+                const char* pszSRSName = GML_ExtractSrsNameFromGeometry(papsGeometry, osWork, false);
 //                if (pszSRSName != NULL)
 //                    m_bCanUseGlobalSRSName = FALSE;
                 poClass->MergeSRSName(pszSRSName);
@@ -978,11 +970,10 @@ void NASReader::CheckForFID( const Attributes &attrs,
                              char **ppszCurField )
 
 {
-    int nIndex;
     XMLCh  Name[100];
 
     tr_strcpy( Name, "fid" );
-    nIndex = attrs.getIndex( Name );
+    int nIndex = attrs.getIndex( Name );
 
     if( nIndex != -1 )
     {
@@ -1010,17 +1001,16 @@ void NASReader::CheckForRelations( const char *pszElement,
 
     CPLAssert( poFeature  != NULL );
 
-    int nIndex;
     XMLCh  Name[100];
 
     tr_strcpy( Name, "xlink:href" );
-    nIndex = attrs.getIndex( Name );
+    const int nIndex = attrs.getIndex( Name );
 
     if( nIndex != -1 )
     {
         char *pszHRef = tr_strdup( attrs.getValue( nIndex ) );
 
-        if( EQUALN(pszHRef,"urn:adv:oid:", 12 ) )
+        if( STARTS_WITH_CI(pszHRef, "urn:adv:oid:") )
         {
             poFeature->AddOBProperty( pszElement, pszHRef );
             CPLFree( *ppszCurField );
@@ -1033,52 +1023,53 @@ void NASReader::CheckForRelations( const char *pszElement,
 
 /************************************************************************/
 /*                         HugeFileResolver()                           */
-/*      Returns TRUE for success                                        */
+/*      Returns true for success                                        */
 /************************************************************************/
 
-int NASReader::HugeFileResolver( CPL_UNUSED const char *pszFile,
-                                 CPL_UNUSED int bSqliteIsTempFile,
-                                 CPL_UNUSED int iSqliteCacheMB )
+bool NASReader::HugeFileResolver( const char * /*pszFile */,
+                                  bool /* bSqliteIsTempFile */,
+                                  int /* iSqliteCacheMB */ )
 {
     CPLDebug( "NAS", "HugeFileResolver() not currently implemented for NAS." );
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
 /*                         PrescanForTemplate()                         */
-/*      Returns TRUE for success                                        */
+/*      Returns true for success                                        */
 /************************************************************************/
 
-int NASReader::PrescanForTemplate( void )
+bool NASReader::PrescanForTemplate( void )
 
 {
-    CPLDebug( "NAS", "PrescanForTemplate() not currently implemented for NAS." );
-    return FALSE;
+    CPLDebug( "NAS",
+              "PrescanForTemplate() not currently implemented for NAS." );
+    return false;
 }
 
 /************************************************************************/
 /*                           ResolveXlinks()                            */
-/*      Returns TRUE for success                                        */
+/*      Returns true for success                                        */
 /************************************************************************/
 
-int NASReader::ResolveXlinks( CPL_UNUSED const char *pszFile,
-                              CPL_UNUSED int* pbOutIsTempFile,
-                              CPL_UNUSED char **papszSkip,
-                              CPL_UNUSED const int bStrict )
+bool NASReader::ResolveXlinks( const char * /*pszFile */,
+                               bool* /*pbOutIsTempFile */,
+                               char ** /*papszSkip */,
+                               const bool /*bStrict */ )
 {
     CPLDebug( "NAS", "ResolveXlinks() not currently implemented for NAS." );
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
 /*                       SetFilteredClassName()                         */
 /************************************************************************/
 
-int NASReader::SetFilteredClassName(const char* pszClassName)
+bool NASReader::SetFilteredClassName(const char* pszClassName)
 {
     CPLFree(m_pszFilteredClassName);
     m_pszFilteredClassName = (pszClassName) ? CPLStrdup(pszClassName) : NULL;
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/nas/nasreaderp.h b/ogr/ogrsf_frmts/nas/nasreaderp.h
index a577920..ee00eba 100644
--- a/ogr/ogrsf_frmts/nas/nasreaderp.h
+++ b/ogr/ogrsf_frmts/nas/nasreaderp.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nasreaderp.h 29051 2015-04-29 17:18:37Z rouault $
+ * $Id: nasreaderp.h 32898 2016-01-10 14:44:10Z goatbar $
  *
  * Project:  NAS Reader
  * Purpose:  Private Declarations for OGR NAS Reader code.
@@ -28,8 +28,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _CPL_NASREADERP_H_INCLUDED
-#define _CPL_NASREADERP_H_INCLUDED
+#ifndef CPL_NASREADERP_H_INCLUDED
+#define CPL_NASREADERP_H_INCLUDED
 
 #include "gmlreader.h"
 #include "gmlreaderp.h"
@@ -60,13 +60,13 @@ class NASHandler : public DefaultHandler
     int        m_nGeomLen;
 
     int        m_nGeometryDepth;
-    int        IsGeometryElement( const char * );
+    bool       IsGeometryElement( const char * );
 
     int        m_nDepth;
     int        m_nDepthFeature;
-    int        m_bIgnoreFeature;
-    int        m_bInUpdate;
-    int        m_bInUpdateProperty;
+    bool       m_bIgnoreFeature;
+    bool       m_bInUpdate;
+    bool       m_bInUpdateProperty;
     int        m_nDepthElement;
     CPLString  m_osIgnoredElement;
 
@@ -144,7 +144,7 @@ public:
 class NASReader : public IGMLReader
 {
 private:
-    int           m_bClassListLocked;
+    bool         m_bClassListLocked;
 
     int         m_nClassCount;
     GMLFeatureClass **m_papoClass;
@@ -153,14 +153,14 @@ private:
 
     NASHandler    *m_poNASHandler;
     SAX2XMLReader *m_poSAXReader;
-    int           m_bReadStarted;
+    bool          m_bReadStarted;
     XMLPScanToken m_oToFill;
 
     GMLReadState *m_poState;
 
     GMLFeature   *m_poCompleteFeature;
 
-    int           SetupParser();
+    bool          SetupParser();
     void          CleanupParser();
 
     char         *m_pszFilteredClassName;
@@ -169,8 +169,8 @@ public:
                 NASReader();
     virtual     ~NASReader();
 
-    int              IsClassListLocked() const { return m_bClassListLocked; }
-    void             SetClassListLocked( int bFlag )
+    bool            IsClassListLocked() const { return m_bClassListLocked; }
+    void             SetClassListLocked( bool bFlag )
         { m_bClassListLocked = bFlag; }
 
     void             SetSourceFile( const char *pszFilename );
@@ -185,24 +185,24 @@ public:
 
     GMLFeature       *NextFeature();
 
-    int              LoadClasses( const char *pszFile = NULL );
-    int              SaveClasses( const char *pszFile = NULL );
+    bool             LoadClasses( const char *pszFile = NULL );
+    bool             SaveClasses( const char *pszFile = NULL );
 
-    int              PrescanForSchema(int bGetExtents = TRUE,
-                                      int bAnalyzeSRSPerFeature = TRUE,
-                                      int bOnlyDetectSRS = FALSE);
-    int              PrescanForTemplate( void );
+    bool             PrescanForSchema(bool bGetExtents = true,
+                                      bool bAnalyzeSRSPerFeature = true,
+                                      bool bOnlyDetectSRS = false);
+    bool             PrescanForTemplate( void );
     void             ResetReading();
 
-    int              ParseXSD( CPL_UNUSED const char *pszFile ) { return FALSE; }
+    bool             ParseXSD( const char * /* pszFile */ ) { return false; }
 
-    int              ResolveXlinks( const char *pszFile,
-                                    int* pbOutIsTempFile,
+    bool             ResolveXlinks( const char *pszFile,
+                                    bool* pbOutIsTempFile,
                                     char **papszSkip = NULL,
-                                    const int bStrict = FALSE );
+                                    const bool bStrict = false );
 
-    int              HugeFileResolver( const char *pszFile,
-                                       int bSqliteIsTempFile,
+    bool             HugeFileResolver( const char *pszFile,
+                                       bool bSqliteIsTempFile,
                                        int iSqliteCacheMB );
 
 // ---
@@ -211,8 +211,8 @@ public:
     void             PopState();
     void             PushState( GMLReadState * );
 
-    int         IsFeatureElement( const char *pszElement );
-    int         IsAttributeElement( const char *pszElement );
+    bool        IsFeatureElement( const char *pszElement );
+    bool        IsAttributeElement( const char *pszElement );
 
     void        PushFeature( const char *pszElement,
                              const Attributes &attrs );
@@ -220,7 +220,7 @@ public:
     void        SetFeaturePropertyDirectly( const char *pszElement,
                                     char *pszValue );
 
-    int         HasStoppedParsing() { return FALSE; }
+    bool        HasStoppedParsing() { return false; }
 
     void        CheckForFID( const Attributes &attrs, char **ppszCurField );
     void        CheckForRelations( const char *pszElement,
@@ -229,14 +229,14 @@ public:
 
     virtual const char* GetGlobalSRSName() { return NULL; }
 
-    virtual int         CanUseGlobalSRSName() { return FALSE; }
+    virtual bool        CanUseGlobalSRSName() { return false; }
 
-    int         SetFilteredClassName(const char* pszClassName);
+    bool        SetFilteredClassName(const char* pszClassName);
     const char* GetFilteredClassName() { return m_pszFilteredClassName; }
 
     static CPLMutex* hMutex;
-    
+
     static      OGRGeometry* ConvertGeometry(OGRGeometry*);
 };
 
-#endif /* _CPL_NASREADERP_H_INCLUDED */
+#endif /* CPL_NASREADERP_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/nas/ogr_nas.h b/ogr/ogrsf_frmts/nas/ogr_nas.h
index 8762ad1..61e914c 100644
--- a/ogr/ogrsf_frmts/nas/ogr_nas.h
+++ b/ogr/ogrsf_frmts/nas/ogr_nas.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_nas.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogr_nas.h 32898 2016-01-10 14:44:10Z goatbar $
  *
  * Project:  NAS Reader
  * Purpose:  Declarations for OGR wrapper classes for NAS, and NAS<->OGR
@@ -28,8 +28,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_NAS_H_INCLUDED
-#define _OGR_NAS_H_INCLUDED
+#ifndef OGR_NAS_H_INCLUDED
+#define OGR_NAS_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "nasreaderp.h"
@@ -48,7 +48,6 @@ class OGRNASLayer : public OGRLayer
     OGRFeatureDefn     *poFeatureDefn;
 
     int                 iNextNASId;
-    int                 nTotalNASCount;
 
     OGRNASDataSource    *poDS;
 
@@ -67,6 +66,8 @@ class OGRNASLayer : public OGRLayer
 
     GIntBig             GetFeatureCount( int bForce = TRUE );
     OGRErr              GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
     OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
 
@@ -82,7 +83,7 @@ class OGRNASRelationLayer : public OGRLayer
     OGRFeatureDefn     *poFeatureDefn;
     OGRNASDataSource    *poDS;
 
-    int                  bPopulated;
+    bool                 bPopulated;
     int                  iNextFeature;
     std::vector<CPLString> aoRelationCollection;
 
@@ -101,7 +102,7 @@ class OGRNASRelationLayer : public OGRLayer
     void                AddRelation( const char *pszFromID,
                                      const char *pszType,
                                      const char *pszToID );
-    void                MarkRelationsPopulated() { bPopulated = TRUE; }
+    void                MarkRelationsPopulated() { bPopulated = true; }
 };
 
 /************************************************************************/
@@ -144,4 +145,4 @@ class OGRNASDataSource : public OGRDataSource
     void                PopulateRelations();
 };
 
-#endif /* _OGR_NAS_H_INCLUDED */
+#endif /* OGR_NAS_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp b/ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp
index a906580..1d0b5c7 100644
--- a/ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp
+++ b/ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrnasdatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogrnasdatasource.cpp 32898 2016-01-10 14:44:10Z goatbar $
  *
  * Project:  OGR
  * Purpose:  Implements OGRNASDataSource class.
@@ -28,13 +28,13 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_nas.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "ogr_nas.h"
 
-CPL_CVSID("$Id: ogrnasdatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogrnasdatasource.cpp 32898 2016-01-10 14:44:10Z goatbar $");
 
-static const char *apszURNNames[] =
+static const char * const apszURNNames[] =
 {
     "DE_DHDN_3GK2_*", "EPSG:31466",
     "DE_DHDN_3GK3_*", "EPSG:31467",
@@ -47,15 +47,13 @@ static const char *apszURNNames[] =
 /*                         OGRNASDataSource()                           */
 /************************************************************************/
 
-OGRNASDataSource::OGRNASDataSource()
-
-{
-    pszName = NULL;
-    papoLayers = NULL;
-    nLayers = 0;
-
-    poReader = NULL;
-}
+OGRNASDataSource::OGRNASDataSource() :
+    papoLayers(NULL),
+    nLayers(0),
+    poRelationLayer(NULL),
+    pszName(NULL),
+    poReader(NULL)
+{}
 
 /************************************************************************/
 /*                        ~OGRNASDataSource()                         */
@@ -86,8 +84,8 @@ int OGRNASDataSource::Open( const char * pszNewName )
     if( poReader == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "File %s appears to be NAS but the NAS reader can't\n"
-                  "be instantiated, likely because Xerces support wasn't\n"
+                  "File %s appears to be NAS but the NAS reader cannot\n"
+                  "be instantiated, likely because Xerces support was not\n"
                   "configured in.",
                   pszNewName );
         return FALSE;
@@ -100,16 +98,15 @@ int OGRNASDataSource::Open( const char * pszNewName )
 /* -------------------------------------------------------------------- */
 /*      Can we find a NAS Feature Schema (.gfs) for the input file?     */
 /* -------------------------------------------------------------------- */
-    const char *pszGFSFilename;
-    VSIStatBuf sGFSStatBuf, sNASStatBuf;
-    int        bHaveSchema = FALSE;
+    bool bHaveSchema = false;
 
-    pszGFSFilename = CPLResetExtension( pszNewName, "gfs" );
+    const char *pszGFSFilename = CPLResetExtension( pszNewName, "gfs" );
+    VSIStatBuf sGFSStatBuf;
     if( CPLStat( pszGFSFilename, &sGFSStatBuf ) == 0 )
     {
-        CPLStat( pszNewName, &sNASStatBuf );
-
-        if( sNASStatBuf.st_mtime > sGFSStatBuf.st_mtime )
+        VSIStatBuf sNASStatBuf;
+        if( CPLStat( pszNewName, &sNASStatBuf ) == 0 &&
+            sNASStatBuf.st_mtime > sGFSStatBuf.st_mtime )
         {
             CPLDebug( "NAS",
                       "Found %s but ignoring because it appears\n"
@@ -132,17 +129,17 @@ int OGRNASDataSource::Open( const char * pszNewName )
         && !poReader->PrescanForSchema( TRUE )
         && CPLGetLastErrorType() == CE_Failure )
     {
-        // we assume an errors have been reported.
+        // Assume an error has been reported.
         return FALSE;
     }
 
 /* -------------------------------------------------------------------- */
-/*      Save the schema file if possible.  Don't make a fuss if we      */
-/*      can't ... could be read-only directory or something.            */
+/*      Save the schema file if possible.  Do not make a fuss if we     */
+/*      cannot.  It could be read-only directory or something.          */
 /* -------------------------------------------------------------------- */
     if( !bHaveSchema && poReader->GetClassCount() > 0 )
     {
-        FILE    *fp = NULL;
+        FILE *fp = NULL;
 
         pszGFSFilename = CPLResetExtension( pszNewName, "gfs" );
         if( CPLStat( pszGFSFilename, &sGFSStatBuf ) != 0
@@ -153,9 +150,9 @@ int OGRNASDataSource::Open( const char * pszNewName )
         }
         else
         {
-            CPLDebug("NAS",
-                     "Not saving %s files already exists or can't be created.",
-                     pszGFSFilename );
+            CPLDebug( "NAS",
+                      "Not saving %s files already exists or can't be created.",
+                      pszGFSFilename );
         }
     }
 
@@ -197,12 +194,12 @@ int OGRNASDataSource::Open( const char * pszNewName )
 OGRNASLayer *OGRNASDataSource::TranslateNASSchema( GMLFeatureClass *poClass )
 
 {
-    OGRNASLayer *poLayer;
     OGRwkbGeometryType eGType = wkbNone;
 
     if( poClass->GetGeometryPropertyCount() != 0 )
     {
-        eGType = (OGRwkbGeometryType) poClass->GetGeometryProperty(0)->GetType();
+        eGType = static_cast<OGRwkbGeometryType>(
+            poClass->GetGeometryProperty(0)->GetType() );
 
         if( poClass->GetFeatureCount() == 0 )
             eGType = wkbUnknown;
@@ -215,45 +212,46 @@ OGRNASLayer *OGRNASDataSource::TranslateNASSchema( GMLFeatureClass *poClass )
     OGRSpatialReference* poSRS = NULL;
     if (pszSRSName)
     {
-        int i;
-
-        poSRS = new OGRSpatialReference();
-
         const char *pszHandle = strrchr( pszSRSName, ':' );
         if( pszHandle != NULL )
+        {
             pszHandle += 1;
 
-        for( i = 0; apszURNNames[i*2+0] != NULL; i++ )
-        {
-            const char *pszTarget = apszURNNames[i*2+0];
-            int nTLen = strlen(pszTarget);
+            poSRS = new OGRSpatialReference();
 
-            // Are we just looking for a prefix match?
-            if( pszTarget[nTLen-1] == '*' )
+            for( int i = 0; apszURNNames[i*2+0] != NULL; i++ )
             {
-                if( EQUALN(pszTarget,pszHandle,nTLen-1) )
-                    pszSRSName = apszURNNames[i*2+1];
+                const char *pszTarget = apszURNNames[i*2+0];
+                const int nTLen = static_cast<int>(strlen(pszTarget));
+
+                // Are we just looking for a prefix match?
+                if( pszTarget[nTLen-1] == '*' )
+                {
+                    if( EQUALN(pszTarget,pszHandle,nTLen-1) )
+                        pszSRSName = apszURNNames[i*2+1];
+                }
+                else
+                {
+                    if( EQUAL(pszTarget,pszHandle) )
+                        pszSRSName = apszURNNames[i*2+1];
+                }
             }
-            else
+
+            if (poSRS->SetFromUserInput(pszSRSName) != OGRERR_NONE)
             {
-                if( EQUAL(pszTarget,pszHandle) )
-                    pszSRSName = apszURNNames[i*2+1];
+                CPLDebug( "NAS", "Failed to translate srsName='%s'",
+                        pszSRSName );
+                delete poSRS;
+                poSRS = NULL;
             }
         }
-
-        if (poSRS->SetFromUserInput(pszSRSName) != OGRERR_NONE)
-        {
-            CPLDebug( "NAS", "Failed to translate srsName='%s'",
-                      pszSRSName );
-            delete poSRS;
-            poSRS = NULL;
-        }
     }
 
 /* -------------------------------------------------------------------- */
 /*      Create an empty layer.                                          */
 /* -------------------------------------------------------------------- */
-    poLayer = new OGRNASLayer( poClass->GetName(), poSRS, eGType, this );
+    OGRNASLayer *poLayer =
+        new OGRNASLayer( poClass->GetName(), poSRS, eGType, this );
     delete poSRS;
 
 /* -------------------------------------------------------------------- */
@@ -282,7 +280,7 @@ OGRNASLayer *OGRNASDataSource::TranslateNASSchema( GMLFeatureClass *poClass )
             eFType = OFTString;
 
         OGRFieldDefn oField( poProperty->GetName(), eFType );
-        if ( EQUALN(oField.GetNameRef(), "ogr:", 4) )
+        if ( STARTS_WITH_CI(oField.GetNameRef(), "ogr:") )
           oField.SetName(poProperty->GetName()+4);
         if( poProperty->GetWidth() > 0 )
             oField.SetWidth( poProperty->GetWidth() );
@@ -302,15 +300,15 @@ OGRLayer *OGRNASDataSource::GetLayer( int iLayer )
 {
     if( iLayer < 0 || iLayer >= nLayers )
         return NULL;
-    else
-        return papoLayers[iLayer];
+
+    return papoLayers[iLayer];
 }
 
 /************************************************************************/
 /*                           TestCapability()                           */
 /************************************************************************/
 
-int OGRNASDataSource::TestCapability( CPL_UNUSED const char * pszCap )
+int OGRNASDataSource::TestCapability( const char * /* pszCap */ )
 {
     return FALSE;
 }
@@ -328,25 +326,27 @@ void OGRNASDataSource::PopulateRelations()
     while( (poFeature = poReader->NextFeature()) != NULL )
     {
         char **papszOBProperties = poFeature->GetOBProperties();
-        int i;
 
-        for( i = 0; papszOBProperties != NULL && papszOBProperties[i] != NULL;
+        for( int i = 0;
+             papszOBProperties != NULL && papszOBProperties[i] != NULL;
              i++ )
         {
-            int nGMLIdIndex = poFeature->GetClass()->GetPropertyIndex( "gml_id" );
-            const GMLProperty *psGMLId = (nGMLIdIndex >= 0) ? poFeature->GetProperty(nGMLIdIndex ) : NULL;
-            char *pszName = NULL;
+            const int nGMLIdIndex =
+                poFeature->GetClass()->GetPropertyIndex( "gml_id" );
+            const GMLProperty *psGMLId =
+              (nGMLIdIndex >= 0) ? poFeature->GetProperty(nGMLIdIndex ) : NULL;
+            char *l_pszName = NULL;
             const char *pszValue = CPLParseNameValue( papszOBProperties[i],
-                                                      &pszName );
+                                                      &l_pszName );
 
-            if( EQUALN(pszValue,"urn:adv:oid:",12)
+            if( STARTS_WITH_CI(pszValue, "urn:adv:oid:")
                 && psGMLId != NULL && psGMLId->nSubProperties == 1 )
             {
                 poRelationLayer->AddRelation( psGMLId->papszSubProperties[0],
-                                              pszName,
+                                              l_pszName,
                                               pszValue + 12 );
             }
-            CPLFree( pszName );
+            CPLFree( l_pszName );
         }
 
         delete poFeature;
diff --git a/ogr/ogrsf_frmts/nas/ogrnasdriver.cpp b/ogr/ogrsf_frmts/nas/ogrnasdriver.cpp
index 7f1f15e..1a3f456 100644
--- a/ogr/ogrsf_frmts/nas/ogrnasdriver.cpp
+++ b/ogr/ogrsf_frmts/nas/ogrnasdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrnasdriver.cpp 28131 2014-12-11 22:30:16Z jef $
+ * $Id: ogrnasdriver.cpp 32898 2016-01-10 14:44:10Z goatbar $
  *
  * Project:  OGR
  * Purpose:  OGRNASDriver implementation
@@ -27,12 +27,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_nas.h"
 #include "cpl_conv.h"
-#include "nasreaderp.h"
 #include "cpl_multiproc.h"
+#include "nasreaderp.h"
+#include "ogr_nas.h"
 
-CPL_CVSID("$Id: ogrnasdriver.cpp 28131 2014-12-11 22:30:16Z jef $");
+CPL_CVSID("$Id: ogrnasdriver.cpp 32898 2016-01-10 14:44:10Z goatbar $");
 
 
 /************************************************************************/
@@ -64,7 +64,8 @@ static int OGRNASDriverIdentify( GDALOpenInfo* poOpenInfo )
 /* -------------------------------------------------------------------- */
 
     // Used to skip to actual beginning of XML data
-    const char* szPtr = (const char*)poOpenInfo->pabyHeader;
+    // const char* szPtr = (const char*)poOpenInfo->pabyHeader;
+    const char* szPtr = reinterpret_cast<char *>(poOpenInfo->pabyHeader);
 
     if( ( (unsigned char)szPtr[0] == 0xEF )
         && ( (unsigned char)szPtr[1] == 0xBB )
@@ -86,12 +87,17 @@ static int OGRNASDriverIdentify( GDALOpenInfo* poOpenInfo )
     if( strstr(szPtr,"opengis.net/gml") == NULL )
         return FALSE;
 
-    char **papszIndicators = CSLTokenizeStringComplex( CPLGetConfigOption( "NAS_INDICATOR", "NAS-Operationen.xsd;NAS-Operationen_optional.xsd;AAA-Fachschema.xsd" ), ";", 0, 0 );
+    char **papszIndicators = CSLTokenizeStringComplex(
+        CPLGetConfigOption(
+            "NAS_INDICATOR",
+            "NAS-Operationen.xsd;NAS-Operationen_optional.xsd;"
+            "AAA-Fachschema.xsd" ),
+        ";", 0, 0 );
 
-    bool bFound = FALSE;
+    bool bFound = false;
     for( int i = 0; papszIndicators[i] && !bFound; i++ )
     {
-	bFound = strstr( szPtr, papszIndicators[i] ) != NULL;
+        bFound = strstr( szPtr, papszIndicators[i] ) != NULL;
     }
 
     CSLDestroy( papszIndicators );
@@ -106,8 +112,6 @@ static int OGRNASDriverIdentify( GDALOpenInfo* poOpenInfo )
 static GDALDataset *OGRNASDriverOpen( GDALOpenInfo* poOpenInfo )
 
 {
-    OGRNASDataSource    *poDS;
-
     if( poOpenInfo->eAccess == GA_Update ||
         !OGRNASDriverIdentify(poOpenInfo) )
         return NULL;
@@ -115,7 +119,7 @@ static GDALDataset *OGRNASDriverOpen( GDALOpenInfo* poOpenInfo )
     VSIFCloseL(poOpenInfo->fpL);
     poOpenInfo->fpL = NULL;
 
-    poDS = new OGRNASDataSource();
+    OGRNASDataSource *poDS = new OGRNASDataSource();
 
     if( !poDS->Open( poOpenInfo->pszFilename )
         || poDS->GetLayerCount() == 0 )
@@ -123,8 +127,8 @@ static GDALDataset *OGRNASDriverOpen( GDALOpenInfo* poOpenInfo )
         delete poDS;
         return NULL;
     }
-    else
-        return poDS;
+
+    return poDS;
 }
 
 /************************************************************************/
@@ -134,24 +138,20 @@ static GDALDataset *OGRNASDriverOpen( GDALOpenInfo* poOpenInfo )
 void RegisterOGRNAS()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "NAS" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "NAS" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "NAS" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "NAS - ALKIS" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "xml" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_nas.html" );
+    poDriver->SetDescription( "NAS" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "NAS - ALKIS" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "xml" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_nas.html" );
 
-        poDriver->pfnOpen = OGRNASDriverOpen;
-        poDriver->pfnIdentify = OGRNASDriverIdentify;
-        poDriver->pfnUnloadDriver = OGRNASDriverUnload;
+    poDriver->pfnOpen = OGRNASDriverOpen;
+    poDriver->pfnIdentify = OGRNASDriverIdentify;
+    poDriver->pfnUnloadDriver = OGRNASDriverUnload;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/nas/ogrnaslayer.cpp b/ogr/ogrsf_frmts/nas/ogrnaslayer.cpp
index d268cef..97b0b4c 100644
--- a/ogr/ogrsf_frmts/nas/ogrnaslayer.cpp
+++ b/ogr/ogrsf_frmts/nas/ogrnaslayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrnaslayer.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrnaslayer.cpp 32898 2016-01-10 14:44:10Z goatbar $
  *
  * Project:  OGR
  * Purpose:  Implements OGRNASLayer class.
@@ -28,12 +28,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_nas.h"
 #include "cpl_conv.h"
 #include "cpl_port.h"
 #include "cpl_string.h"
+#include "ogr_nas.h"
 
-CPL_CVSID("$Id: ogrnaslayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrnaslayer.cpp 32898 2016-01-10 14:44:10Z goatbar $");
 
 /************************************************************************/
 /*                           OGRNASLayer()                              */
@@ -42,33 +42,19 @@ CPL_CVSID("$Id: ogrnaslayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
 OGRNASLayer::OGRNASLayer( const char * pszName,
                           OGRSpatialReference *poSRSIn,
                           OGRwkbGeometryType eReqType,
-                          OGRNASDataSource *poDSIn )
-
+                          OGRNASDataSource *poDSIn ) :
+    poSRS((poSRSIn != NULL) ? poSRSIn->Clone() : NULL),
+    poFeatureDefn(new OGRFeatureDefn(
+        pszName + (STARTS_WITH_CI(pszName, "ogr:") ? 4 : 0))),
+    iNextNASId(0),
+    poDS(poDSIn),
+    // Readers should get the corresponding NASFeatureClass and cache it.
+    poFClass(poDS->GetReader()->GetClass( pszName ))
 {
-    if( poSRSIn == NULL )
-        poSRS = NULL;
-    else
-        poSRS = poSRSIn->Clone();
-
-    iNextNASId = 0;
-    nTotalNASCount = -1;
-
-    poDS = poDSIn;
-
-    if ( EQUALN(pszName, "ogr:", 4) )
-        poFeatureDefn = new OGRFeatureDefn( pszName+4 );
-    else
-        poFeatureDefn = new OGRFeatureDefn( pszName );
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
     poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
     poFeatureDefn->SetGeomType( eReqType );
-
-/* -------------------------------------------------------------------- */
-/*      Reader's should get the corresponding NASFeatureClass and       */
-/*      cache it.                                                       */
-/* -------------------------------------------------------------------- */
-    poFClass = poDS->GetReader()->GetClass( pszName );
 }
 
 /************************************************************************/
@@ -115,7 +101,7 @@ OGRFeature *OGRNASLayer::GetNextFeature()
 /*      Loop till we find and translate a feature meeting all our       */
 /*      requirements.                                                   */
 /* ==================================================================== */
-    while( TRUE )
+    while( true )
     {
 /* -------------------------------------------------------------------- */
 /*      Cleanup last feature, and get a new raw nas feature.            */
@@ -147,7 +133,8 @@ OGRFeature *OGRNASLayer::GetNextFeature()
 /* -------------------------------------------------------------------- */
 /*      Does it satisfy the spatial query, if there is one?             */
 /* -------------------------------------------------------------------- */
-        const CPLXMLNode* const * papsGeometry = poNASFeature->GetGeometryList();
+        const CPLXMLNode* const * papsGeometry =
+            poNASFeature->GetGeometryList();
         if (papsGeometry[0] != NULL)
         {
             poGeom = (OGRGeometry*) OGR_G_CreateFromGMLTree(papsGeometry[0]);
@@ -155,8 +142,8 @@ OGRFeature *OGRNASLayer::GetNextFeature()
             poGeom = OGRGeometryFactory::forceTo(poGeom, GetGeomType());
             // poGeom->dumpReadable( 0, "NAS: " );
 
-            // We assume the OGR_G_CreateFromGMLTree() function would have already
-            // reported an error.
+            // We assume the OGR_G_CreateFromGMLTree() function would
+            // have already reported an error.
             if( poGeom == NULL )
             {
                 delete poNASFeature;
@@ -170,14 +157,14 @@ OGRFeature *OGRNASLayer::GetNextFeature()
 /* -------------------------------------------------------------------- */
 /*      Convert the whole feature into an OGRFeature.                   */
 /* -------------------------------------------------------------------- */
-        int iField;
         OGRFeature *poOGRFeature = new OGRFeature( GetLayerDefn() );
 
         poOGRFeature->SetFID( iNextNASId );
 
-        for( iField = 0; iField < poFClass->GetPropertyCount(); iField++ )
+        for( int iField = 0; iField < poFClass->GetPropertyCount(); iField++ )
         {
-            const GMLProperty *psGMLProperty = poNASFeature->GetProperty( iField );
+            const GMLProperty *psGMLProperty =
+                poNASFeature->GetProperty( iField );
             if( psGMLProperty == NULL || psGMLProperty->nSubProperties == 0 )
                 continue;
 
@@ -185,18 +172,20 @@ OGRFeature *OGRNASLayer::GetNextFeature()
             {
               case GMLPT_Real:
               {
-                  poOGRFeature->SetField( iField, CPLAtof(psGMLProperty->papszSubProperties[0]) );
+                  poOGRFeature->SetField(
+                      iField, CPLAtof(psGMLProperty->papszSubProperties[0]) );
               }
               break;
 
               case GMLPT_IntegerList:
               {
                   int nCount = psGMLProperty->nSubProperties;
-                  int *panIntList = (int *) CPLMalloc(sizeof(int) * nCount );
-                  int i;
+                  int *panIntList = static_cast<int *>(
+                      CPLMalloc(sizeof(int) * nCount ) );
 
-                  for( i = 0; i < nCount; i++ )
-                      panIntList[i] = atoi(psGMLProperty->papszSubProperties[i]);
+                  for( int i = 0; i < nCount; i++ )
+                      panIntList[i] =
+                          atoi(psGMLProperty->papszSubProperties[i]);
 
                   poOGRFeature->SetField( iField, nCount, panIntList );
                   CPLFree( panIntList );
@@ -206,11 +195,12 @@ OGRFeature *OGRNASLayer::GetNextFeature()
               case GMLPT_RealList:
               {
                   int nCount = psGMLProperty->nSubProperties;
-                  double *padfList = (double *)CPLMalloc(sizeof(double)*nCount);
-                  int i;
+                  double *padfList = static_cast<double *>(
+                      CPLMalloc(sizeof(double)*nCount) );
 
-                  for( i = 0; i < nCount; i++ )
-                      padfList[i] = CPLAtof(psGMLProperty->papszSubProperties[i]);
+                  for( int i = 0; i < nCount; i++ )
+                      padfList[i] =
+                          CPLAtof(psGMLProperty->papszSubProperties[i]);
 
                   poOGRFeature->SetField( iField, nCount, padfList );
                   CPLFree( padfList );
@@ -219,12 +209,14 @@ OGRFeature *OGRNASLayer::GetNextFeature()
 
               case GMLPT_StringList:
               {
-                  poOGRFeature->SetField( iField, psGMLProperty->papszSubProperties );
+                  poOGRFeature->SetField(
+                      iField, psGMLProperty->papszSubProperties );
               }
               break;
 
               default:
-                poOGRFeature->SetField( iField, psGMLProperty->papszSubProperties[0] );
+                poOGRFeature->SetField(
+                    iField, psGMLProperty->papszSubProperties[0] );
                 break;
             }
         }
@@ -265,8 +257,8 @@ GIntBig OGRNASLayer::GetFeatureCount( int bForce )
 
     if( m_poFilterGeom != NULL || m_poAttrQuery != NULL )
         return OGRLayer::GetFeatureCount( bForce );
-    else
-        return poFClass->GetFeatureCount();
+
+    return poFClass->GetFeatureCount();
 }
 
 /************************************************************************/
@@ -276,7 +268,10 @@ GIntBig OGRNASLayer::GetFeatureCount( int bForce )
 OGRErr OGRNASLayer::GetExtent(OGREnvelope *psExtent, int bForce )
 
 {
-    double dfXMin, dfXMax, dfYMin, dfYMax;
+    double dfXMin;
+    double dfXMax;
+    double dfYMin;
+    double dfYMax;
 
     if( poFClass != NULL &&
         poFClass->GetExtents( &dfXMin, &dfXMax, &dfYMin, &dfYMax ) )
@@ -288,8 +283,8 @@ OGRErr OGRNASLayer::GetExtent(OGREnvelope *psExtent, int bForce )
 
         return OGRERR_NONE;
     }
-    else
-        return OGRLayer::GetExtent( psExtent, bForce );
+
+    return OGRLayer::GetExtent( psExtent, bForce );
 }
 
 /************************************************************************/
@@ -301,7 +296,10 @@ int OGRNASLayer::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,OLCFastGetExtent) )
     {
-        double  dfXMin, dfXMax, dfYMin, dfYMax;
+        double  dfXMin;
+        double  dfXMax;
+        double  dfYMin;
+        double  dfYMax;
 
         if( poFClass == NULL )
             return FALSE;
@@ -309,7 +307,7 @@ int OGRNASLayer::TestCapability( const char * pszCap )
         return poFClass->GetExtents( &dfXMin, &dfXMax, &dfYMin, &dfYMax );
     }
 
-    else if( EQUAL(pszCap,OLCFastFeatureCount) )
+    if( EQUAL(pszCap,OLCFastFeatureCount) )
     {
         if( poFClass == NULL
             || m_poFilterGeom != NULL
@@ -319,9 +317,8 @@ int OGRNASLayer::TestCapability( const char * pszCap )
         return poFClass->GetFeatureCount() != -1;
     }
 
-    else if( EQUAL(pszCap,OLCStringsAsUTF8) )
+    if( EQUAL(pszCap,OLCStringsAsUTF8) )
         return TRUE;
 
-    else
-        return FALSE;
+    return FALSE;
 }
diff --git a/ogr/ogrsf_frmts/nas/ogrnasrelationlayer.cpp b/ogr/ogrsf_frmts/nas/ogrnasrelationlayer.cpp
index 6230c7e..866c276 100644
--- a/ogr/ogrsf_frmts/nas/ogrnasrelationlayer.cpp
+++ b/ogr/ogrsf_frmts/nas/ogrnasrelationlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrnasrelationlayer.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrnasrelationlayer.cpp 32898 2016-01-10 14:44:10Z goatbar $
  *
  * Project:  OGR
  * Purpose:  Implements OGRNASRelationLayer class, a special layer holding all
@@ -28,34 +28,31 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_nas.h"
 #include "cpl_conv.h"
 #include "cpl_port.h"
 #include "cpl_string.h"
+#include "ogr_nas.h"
 
-CPL_CVSID("$Id: ogrnasrelationlayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrnasrelationlayer.cpp 32898 2016-01-10 14:44:10Z goatbar $");
 
 /************************************************************************/
 /*                        OGRNASRelationLayer()                         */
 /************************************************************************/
 
-OGRNASRelationLayer::OGRNASRelationLayer( OGRNASDataSource *poDSIn )
-
+OGRNASRelationLayer::OGRNASRelationLayer( OGRNASDataSource *poDSIn ) :
+    poFeatureDefn(new OGRFeatureDefn( "ALKIS_beziehungen" )),
+    poDS(poDSIn),
+    bPopulated(false),
+    iNextFeature(0)
 {
-    poDS = poDSIn;
-
-    iNextFeature = 0;
-    bPopulated = FALSE;
-
 /* -------------------------------------------------------------------- */
 /*      Establish the layer fields.                                     */
 /* -------------------------------------------------------------------- */
-    poFeatureDefn = new OGRFeatureDefn( "ALKIS_beziehungen" );
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbNone );
 
-    OGRFieldDefn  oFD( "", OFTString );
+    OGRFieldDefn oFD( "", OFTString );
 
     oFD.SetName( "beziehung_von" );
     poFeatureDefn->AddFieldDefn( &oFD );
@@ -102,21 +99,19 @@ OGRFeature *OGRNASRelationLayer::GetNextFeature()
 /*      Loop till we find and translate a feature meeting all our       */
 /*      requirements.                                                   */
 /* ==================================================================== */
-    while( TRUE )
+    while( true )
     {
         // out of features?
-        if( iNextFeature >= (int) aoRelationCollection.size() )
+        if( iNextFeature >= static_cast<int>(aoRelationCollection.size()) )
             return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      The from/type/to values are stored in a packed string with      */
 /*      \0 separators for compactness.  Split out components.           */
 /* -------------------------------------------------------------------- */
-        const char *pszFromID, *pszType, *pszToID;
-
-        pszFromID = aoRelationCollection[iNextFeature].c_str();
-        pszType = pszFromID + strlen(pszFromID) + 1;
-        pszToID = pszType + strlen(pszType) + 1;
+        const char *pszFromID = aoRelationCollection[iNextFeature].c_str();
+        const char *pszType = pszFromID + strlen(pszFromID) + 1;
+        const char *pszToID = pszType + strlen(pszType) + 1;
 
         m_nFeaturesRead++;
 
@@ -156,8 +151,8 @@ GIntBig OGRNASRelationLayer::GetFeatureCount( int bForce )
 
     if( m_poAttrQuery == NULL )
         return aoRelationCollection.size();
-    else
-        return OGRLayer::GetFeatureCount( bForce );
+
+    return OGRLayer::GetFeatureCount( bForce );
 }
 
 /************************************************************************/
@@ -170,14 +165,13 @@ int OGRNASRelationLayer::TestCapability( const char * pszCap )
     if( EQUAL(pszCap,OLCFastGetExtent) )
         return TRUE;
 
-    else if( EQUAL(pszCap,OLCFastFeatureCount) )
+    if( EQUAL(pszCap,OLCFastFeatureCount) )
         return bPopulated && m_poAttrQuery == NULL;
 
-    else if( EQUAL(pszCap,OLCStringsAsUTF8) )
+    if( EQUAL(pszCap,OLCStringsAsUTF8) )
         return TRUE;
 
-    else
-        return FALSE;
+    return FALSE;
 }
 
 /************************************************************************/
@@ -189,7 +183,8 @@ void OGRNASRelationLayer::AddRelation( const char *pszFromID,
                                        const char *pszToID )
 
 {
-    int nMergedLen = strlen(pszFromID) + strlen(pszType) + strlen(pszToID) + 3;
+    const size_t nMergedLen =
+        strlen(pszFromID) + strlen(pszType) + strlen(pszToID) + 3;
     char *pszMerged = (char *) CPLMalloc(nMergedLen);
 
     strcpy( pszMerged, pszFromID );
diff --git a/ogr/ogrsf_frmts/ntf/README.txt b/ogr/ogrsf_frmts/ntf/README.txt
index a532ab5..a06ac06 100644
--- a/ogr/ogrsf_frmts/ntf/README.txt
+++ b/ogr/ogrsf_frmts/ntf/README.txt
@@ -95,7 +95,7 @@ generally contain features of many different feature codes (FEAT_CODE
 attribute).  Different features within a given layer may have a variety of
 attributes in the file; however, the schema is established based on the
 union of all attributes possible within features of a particular type
-(ie. POINT) of that product family (ie. OSCAR Network).
+(i.e. POINT) of that product family (i.e. OSCAR Network).
 
 If an NTF product is read that doesn't match one of the known schema's
 it will go through a different generic handler which has only 
@@ -151,8 +151,8 @@ Adding a New Product
 --------------------
 
 It is anticipated that over time the UK Ordnance Survey will define new 
-product formats, and to get decent milage out of them this library should
-be updated to support them.  While I will endevour to do this myself, it
+product formats, and to get decent mileage out of them this library should
+be updated to support them.  While I will endeavor to do this myself, it
 seems prudent to define how it is done in case I am not available to do it,
 or am unwilling to do it on a timely basis.  To add a new product type the 
 following steps are required:
@@ -166,10 +166,10 @@ following steps are required:
    be cloned from an existing translate function, and the attribute mapping
    in the NTFReader::ApplyAttributeValues() call can be modified. 
 
-Occationally existing products will change slightly.  This may result in a
+Occasionally existing products will change slightly.  This may result in a
 slight change to the detection logic in NTFFileReader::Open() and changes
 in the list of user attributes associated with the layer.  If the differences
-are signifiant it may be necessary to define a whole new product family 
+are significant it may be necessary to define a whole new product family 
 type (as is done for Code Point Plus vs. Code Point). 
 
 Generic Products
@@ -178,7 +178,7 @@ Generic Products
 In situations where a file is not identified as being part of an existing
 known product it will be treated generically.  In this case the entire dataset
 is scanned to establish what features have what attributes.  Because of this,
-opening a generic dataset can be much slower than opening a recognised dataset.
+opening a generic dataset can be much slower than opening a recognized dataset.
 Based on this scan a list of generic features (layers) are defined from the 
 following set:
 
diff --git a/ogr/ogrsf_frmts/ntf/drv_ntf.html b/ogr/ogrsf_frmts/ntf/drv_ntf.html
index 8131909..e9e44a6 100644
--- a/ogr/ogrsf_frmts/ntf/drv_ntf.html
+++ b/ogr/ogrsf_frmts/ntf/drv_ntf.html
@@ -23,7 +23,7 @@ than the UK Ordnance Survey.<P>
 <h3>See Also</h3>
 
 <ul>
-<li> <a href="http://home.gdal.org/projects/ntf/index.html">General UK NTF 
+<li> <a href="http://home.gdal.org/projects/ntf/index.html">General UK NTF
 Information</a><p>
 </ul>
 
@@ -61,12 +61,12 @@ Boundaryline:
 	BOUNDARYLINE_POLY
 	BOUNDARYLINE_COLLECTIONS
 
-	The _POLY layer has links to links allowing true polygons to  
+	The _POLY layer has links to links allowing true polygons to
         be formed (otherwise the _POLY's only have a seed point for geometry.
 	The collections are collections of polygons (also without geometry
 	as read).  This is the only product from which polygons can be
 	constructed.
-	
+
 BaseData.GB:
 	BASEDATA_POINT
 	BASEDATA_LINE
@@ -93,31 +93,31 @@ Code Point Plus:
 	CODE_POINT_PLUS
 </pre>
 
-The dataset as a whole will also have a FEATURE_CLASSES layer containing a 
-pure table relating FEAT_CODE numbers with feature class names (FC_NAME).  
-This applies to all products in the dataset.  A few layer types (such as 
+The dataset as a whole will also have a FEATURE_CLASSES layer containing a
+pure table relating FEAT_CODE numbers with feature class names (FC_NAME).
+This applies to all products in the dataset.  A few layer types (such as
 the Code Point, and Address Point products) don't include feature classes.
 Some products use features classes that are not defined in the file, and
 so they will not appear in the FEATURE_CLASSES layer. <p>
-	
-	
+
+
 <h3>Product Schemas</h3>
 
 The approach taken in this reader is to treat one file, or a directory
-of files as a single dataset.  All files in the dataset are scanned on 
+of files as a single dataset.  All files in the dataset are scanned on
 open.  For each particular product (listed above) a set of layers are
 created; however, these layers may be extracted from several files of the
 same product. <p>
 
 The layers are based on a low level feature type in the NTF file, but will
-generally contain features of many different feature codes (FEAT_CODE 
+generally contain features of many different feature codes (FEAT_CODE
 attribute).  Different features within a given layer may have a variety of
 attributes in the file; however, the schema is established based on the
 union of all attributes possible within features of a particular type
-(ie. POINT) of that product family (ie. OSCAR Network).<p>
+(i.e. POINT) of that product family (i.e. OSCAR Network).<p>
 
 If an NTF product is read that doesn't match one of the known schema's
-it will go through a different generic handler which has only 
+it will go through a different generic handler which has only
 layers of type GENERIC_POINT and GENERIC_LINE.  The features only have
 a FEAT_CODE attribute.  <p>
 
@@ -130,40 +130,40 @@ This file also contains all the product specific translation code. <p>
 
 <pre>
 FEAT_CODE: General feature code integer, can be used to lookup a name in the
-           FEATURE_CLASSES layer/table. 
+           FEATURE_CLASSES layer/table.
 
 TEXT_ID/POINT_ID/LINE_ID/NAME_ID/COLL_ID/POLY_ID/GEOM_ID:
-          Unique identifier for a feature of the appropriate type.  
+          Unique identifier for a feature of the appropriate type.
 
 TILE_REF: All layers (except FEATURE_CLASSES) contain a TILE_REF attribute
           which indicates which tile (file) the features came from.  Generally
           speaking the id numbers are only unique within the tile and so
           the TILE_REF can be used restrict id links within features from
-          the same file. 
+          the same file.
 
 FONT/TEXT_HT/DIG_POSTN/ORIENT:
-	Detailed information on the font, text height, digitizing position, 
+	Detailed information on the font, text height, digitizing position,
         and orientation of text or name objects.  Review the OS product
-        manuals to understand the units, and meaning of these codes. 
+        manuals to understand the units, and meaning of these codes.
 
 GEOM_ID_OF_POINT:
 	For _NODE features this defines the POINT_ID of the point layer object
         to which this node corresponds.  Generally speaking the nodes don't
         carry a geometry of their own.  The node must be related to a point
-        to establish it's position. 
+        to establish it's position.
 
 GEOM_ID_OF_LINK:
 	A _list_ of _LINK or _LINE features to end/start at a node.  Nodes,
-        and this field are generally only of value when establishing 
+        and this field are generally only of value when establishing
         connectivity of line features for network analysis.   Note that this
         should be related to the target features GEOM_ID, not it's LINE_ID.
 
         On the BOUNDARYLINE_POLY layer this attribute contains the GEOM_IDs
-        of the lines which form the edge of the polygon. 
+        of the lines which form the edge of the polygon.
 
 POLY_ID:
 	A list of POLY_ID's from the BOUNDARYLINE_POLY layer associated with
-        a given collection in the BOUNDARYLINE_COLLECTIONS layer. 
+        a given collection in the BOUNDARYLINE_COLLECTIONS layer.
 </pre>
 
 
@@ -173,7 +173,7 @@ In situations where a file is not identified as being part of an existing
 known product it will be treated generically.  In this case the entire dataset
 is scanned to establish what features have what attributes.  Because of this,
 opening a generic dataset can be much slower than opening a recognised dataset.
-Based on this scan a list of generic features (layers) are defined from the 
+Based on this scan a list of generic features (layers) are defined from the
 following set:<p>
 
 <pre>
@@ -203,7 +203,7 @@ products. <p>
 It is possible to force a known product to be treated as generic by setting
 the FORCE_GENERIC option to "ON" using OGRNTFDataSource::SetOptionsList() as
 is demonstrated in ntfdump.cpp.  This may also be accomplished from
-outside OGR applications by setting the OGR_NTF_OPTIONS environment 
+outside OGR applications by setting the OGR_NTF_OPTIONS environment
 variable to "FORCE_GENERIC=ON".<p>
 
 </body>
diff --git a/ogr/ogrsf_frmts/ntf/ntf.h b/ogr/ogrsf_frmts/ntf/ntf.h
index 7bcb1d3..ad3f6f8 100644
--- a/ogr/ogrsf_frmts/ntf/ntf.h
+++ b/ogr/ogrsf_frmts/ntf/ntf.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ntf.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ntf.h 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  NTF Translator
  * Purpose:  Main declarations for NTF translator.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _NTF_H_INCLUDED
-#define _NTF_H_INCLUDED
+#ifndef NTF_H_INCLUDED
+#define NTF_H_INCLUDED
 
 #include "cpl_conv.h"
 #include "ogrsf_frmts.h"
@@ -51,9 +51,9 @@
 #define NRT_CHAIN    24                /* Chain */
 #define NRT_POLYGON  31                /* Polygon */
 #define NRT_CPOLY    33                /* Complex Polygon */
-#define NRT_COLLECT  34                /* Collection of featues */
+#define NRT_COLLECT  34                /* Collection of features */
 #define NRT_ADR      40                /* Attribute Description Record */
-#define NRT_CODELIST 42                /* Codelist Record (ie. BL2000) */
+#define NRT_CODELIST 42                /* Codelist Record (i.e. BL2000) */
 #define NRT_TEXTREC  43                /* Text */
 #define NRT_TEXTPOS  44                /* Text position */
 #define NRT_TEXTREP  45                /* Text representation */
@@ -119,7 +119,7 @@ class NTFRecord
     char    *pszData;
 
     int      ReadPhysicalLine( FILE *fp, char *pszLine );
-    
+
   public:
              NTFRecord( FILE * );
              ~NTFRecord();
@@ -149,7 +149,7 @@ public:
 
                 NTFGenericClass();
                 ~NTFGenericClass();
-    
+
     void        CheckAddAttr( const char *, const char *, int );
     void        SetMultiple( const char * );
 };
@@ -166,9 +166,9 @@ public:
 
     const char  *Lookup( const char * );
 
-    char        szValType[3];   /* attribute code for list, ie. AC */
+    char        szValType[3];   /* attribute code for list, i.e. AC */
     char        szFInter[6];    /* format of code values */
- 
+
     int         nNumCode;
     char        **papszCodeVal; /* Short code value */
     char        **papszCodeDes; /* Long description of code */
@@ -209,7 +209,7 @@ class NTFFileReader
 {
     char             *pszFilename;
     OGRNTFDataSource *poDS;
-        
+
     FILE             *fp;
 
     // feature class list.
@@ -245,8 +245,8 @@ class NTFFileReader
 
     long              nSavedFeatureId;
     long              nBaseFeatureId;
-    long              nFeatureCount; 
-    
+    long              nFeatureCount;
+
     NTFRecord         *apoCGroup[MAX_REC_GROUP+1];
 
     char             *pszProduct;
@@ -292,8 +292,8 @@ class NTFFileReader
     int               SetFPPos( long nPos, long nFeatureId );
     void              Reset();
     void              SetBaseFID( long nFeatureId );
-  
-    
+
+
     OGRGeometry      *ProcessGeometry( NTFRecord *, int * = NULL );
     OGRGeometry      *ProcessGeometry3D( NTFRecord *, int * = NULL );
     int               ProcessAttDesc( NTFRecord *, NTFAttDesc * );
@@ -303,13 +303,13 @@ class NTFFileReader
     NTFAttDesc       *GetAttDesc( const char * );
 
     void              ApplyAttributeValues( OGRFeature *, NTFRecord **, ... );
-     
+
     int               ApplyAttributeValue( OGRFeature *, int, const char *,
                                            char **, char ** );
-    
-    int               ProcessAttValue( const char *pszValType, 
+
+    int               ProcessAttValue( const char *pszValType,
                                        const char *pszRawValue,
-                                       char **ppszAttName, 
+                                       char **ppszAttName,
                                        char **ppszAttValue,
                                        char **ppszCodeDesc );
 
@@ -367,7 +367,7 @@ class NTFFileReader
     int               GetRasterDataType() { return nRasterDataType; }
     double           *GetGeoTransform() { return adfGeoTransform; }
     CPLErr            ReadRasterColumn( int, float * );
-    
+
 };
 
 /************************************************************************/
@@ -384,7 +384,7 @@ class OGRNTFLayer : public OGRLayer
     int                 iCurrentReader;
     long                nCurrentPos;
     long                nCurrentFID;
-  
+
   public:
                         OGRNTFLayer( OGRNTFDataSource * poDS,
                                      OGRFeatureDefn * poFeatureDefine,
@@ -395,18 +395,18 @@ class OGRNTFLayer : public OGRLayer
     void                ResetReading();
     OGRFeature *        GetNextFeature();
 
-#ifdef notdef    
+#ifdef notdef
     OGRFeature         *GetFeature( GIntBig nFeatureId );
     OGRErr              ISetFeature( OGRFeature *poFeature );
     OGRErr              ICreateFeature( OGRFeature *poFeature );
 #endif
-    
+
     OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
 
-#ifdef notdef    
+#ifdef notdef
     GIntBig             GetFeatureCount( int );
 #endif
-    
+
     int                 TestCapability( const char * );
 
     // special to NTF
@@ -425,23 +425,25 @@ class OGRNTFFeatureClassLayer : public OGRLayer
     OGRNTFDataSource   *poDS;
 
     int                 iCurrentFC;
-  
+
   public:
                         OGRNTFFeatureClassLayer( OGRNTFDataSource * poDS );
                         ~OGRNTFFeatureClassLayer();
 
     OGRGeometry *       GetSpatialFilter() { return poFilterGeom; }
     void                SetSpatialFilter( OGRGeometry * );
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+                { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
 
     void                ResetReading();
     OGRFeature *        GetNextFeature();
 
     OGRFeature         *GetFeature( GIntBig nFeatureId );
-    
+
     OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
 
     GIntBig             GetFeatureCount( int = TRUE );
-    
+
     int                 TestCapability( const char * );
 };
 
@@ -462,10 +464,10 @@ class OGRNTFRasterLayer : public OGRLayer
     int                 iColumnOffset;
 
     int                 iCurrentFC;
-  
+
     int                 nDEMSample;
     int                 nFeatureCount;
-    
+
   public:
                         OGRNTFRasterLayer( OGRNTFDataSource * poDS,
                                            NTFFileReader * poReaderIn );
@@ -473,16 +475,18 @@ class OGRNTFRasterLayer : public OGRLayer
 
     OGRGeometry *       GetSpatialFilter() { return poFilterGeom; }
     void                SetSpatialFilter( OGRGeometry * );
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+                { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
 
     void                ResetReading();
     OGRFeature *        GetNextFeature();
 
     OGRFeature         *GetFeature( GIntBig nFeatureId );
-    
+
     OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
 
     GIntBig             GetFeatureCount( int = TRUE );
-    
+
     int                 TestCapability( const char * );
 };
 
@@ -503,7 +507,7 @@ class OGRNTFDataSource : public OGRDataSource
     int                 iCurrentReader;
     long                nCurrentPos;
     long                nCurrentFID;
-  
+
     int                 nNTFFileCount;
     NTFFileReader       **papoNTFFileReader;
 
@@ -518,17 +522,17 @@ class OGRNTFDataSource : public OGRDataSource
     char                **papszOptions;
 
     void                EnsureTileNameUnique( NTFFileReader * );
-    
+
   public:
                         OGRNTFDataSource();
                         ~OGRNTFDataSource();
 
     void                SetOptionList( char ** );
     const char         *GetOption( const char * );
-    
+
     int                 Open( const char * pszName, int bTestOpen = FALSE,
                               char ** papszFileList = NULL );
-    
+
     const char          *GetName() { return pszName; }
     int                 GetLayerCount();
     OGRLayer            *GetLayer( int );
@@ -562,8 +566,8 @@ class OGRNTFDataSource : public OGRDataSource
 /*                          Support functions.                          */
 /************************************************************************/
 int NTFArcCenterFromEdgePoints( double x_c0, double y_c0,
-                                double x_c1, double y_c1, 
-                                double x_c2, double y_c2, 
+                                double x_c1, double y_c1,
+                                double x_c2, double y_c2,
                                 double *x_center, double *y_center );
 OGRGeometry *
 NTFStrokeArcToOGRGeometry_Points( double dfStartX, double dfStartY,
@@ -571,9 +575,9 @@ NTFStrokeArcToOGRGeometry_Points( double dfStartX, double dfStartY,
                                   double dfEndX, double dfEndY,
                                   int nVertexCount );
 OGRGeometry *
-NTFStrokeArcToOGRGeometry_Angles( double dfCenterX, double dfCenterY, 
-                                  double dfRadius, 
+NTFStrokeArcToOGRGeometry_Angles( double dfCenterX, double dfCenterY,
+                                  double dfRadius,
                                   double dfStartAngle, double dfEndAngle,
                                   int nVertexCount );
 
-#endif /* ndef _NTF_H_INCLUDED */
+#endif /* ndef NTF_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/ntf/ntf_codelist.cpp b/ogr/ogrsf_frmts/ntf/ntf_codelist.cpp
index e5fe9a0..1388a21 100644
--- a/ogr/ogrsf_frmts/ntf/ntf_codelist.cpp
+++ b/ogr/ogrsf_frmts/ntf/ntf_codelist.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ntf_codelist.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: ntf_codelist.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  NTF Translator
  * Purpose:  NTFCodeList class implementation.
@@ -32,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ntf_codelist.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: ntf_codelist.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                             NTFCodeList                              */
@@ -45,9 +45,9 @@ NTFCodeList::NTFCodeList( NTFRecord * poRecord )
     const char  *pszText;
 
     CPLAssert( EQUAL(poRecord->GetField(1,2),"42") );
-    
-    strcpy( szValType, poRecord->GetField(13,14) );
-    strcpy( szFInter, poRecord->GetField(15,19) );
+
+    snprintf( szValType, sizeof(szValType), "%s", poRecord->GetField(13,14) );
+    snprintf( szFInter, sizeof(szFInter), "%s", poRecord->GetField(15,19) );
 
     nNumCode = atoi(poRecord->GetField(20,22));
 
@@ -55,8 +55,8 @@ NTFCodeList::NTFCodeList( NTFRecord * poRecord )
     papszCodeDes = (char **) CPLMalloc(sizeof(char*) * nNumCode );
 
     pszText = poRecord->GetData() + 22;
-    for( iThisField=0; 
-         *pszText != '\0' && iThisField < nNumCode; 
+    for( iThisField=0;
+         *pszText != '\0' && iThisField < nNumCode;
          iThisField++ )
     {
         char    szVal[128], szDes[128];
@@ -66,10 +66,10 @@ NTFCodeList::NTFCodeList( NTFRecord * poRecord )
         while( *pszText != '\\' && *pszText != '\0' )
             szVal[iLen++] = *(pszText++);
         szVal[iLen] = '\0';
-        
+
         if( *pszText == '\\' )
             pszText++;
-        
+
         iLen = 0;
         while( *pszText != '\\' && *pszText != '\0' )
             szDes[iLen++] = *(pszText++);
@@ -85,7 +85,7 @@ NTFCodeList::NTFCodeList( NTFRecord * poRecord )
     if( iThisField < nNumCode )
     {
         nNumCode = iThisField;
-        CPLDebug( "NTF", 
+        CPLDebug( "NTF",
                   "Didn't get all the expected fields from a CODELIST." );
     }
 }
@@ -122,5 +122,3 @@ const char *NTFCodeList::Lookup( const char * pszCode )
 
     return NULL;
 }
-
-
diff --git a/ogr/ogrsf_frmts/ntf/ntf_estlayers.cpp b/ogr/ogrsf_frmts/ntf/ntf_estlayers.cpp
index a104bf3..bc25656 100644
--- a/ogr/ogrsf_frmts/ntf/ntf_estlayers.cpp
+++ b/ogr/ogrsf_frmts/ntf/ntf_estlayers.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ntf_estlayers.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: ntf_estlayers.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  NTF Translator
  * Purpose:  NTFFileReader methods related to establishing the schemas
@@ -33,7 +33,7 @@
 #include "ntf.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ntf_estlayers.cpp 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: ntf_estlayers.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 #define MAX_LINK        5000
 
@@ -52,7 +52,7 @@ static OGRFeature *TranslateCodePoint( NTFFileReader *poReader,
         || papoGroup[0]->GetType() != NRT_POINTREC
         || papoGroup[1]->GetType() != NRT_GEOMETRY )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // POINT_ID
@@ -66,7 +66,7 @@ static OGRFeature *TranslateCodePoint( NTFFileReader *poReader,
         poReader->ApplyAttributeValues( poFeature, papoGroup,
                                         "PC", 1, "PQ", 2, "PR", 3, "TP", 4,
                                         "DQ", 5, "RP", 6, "BP", 7, "PD", 8,
-                                        "MP", 9, "UM", 10, "RV", 11, 
+                                        "MP", 9, "UM", 10, "RV", 11,
                                         NULL );
     else
         poReader->ApplyAttributeValues( poFeature, papoGroup,
@@ -74,7 +74,7 @@ static OGRFeature *TranslateCodePoint( NTFFileReader *poReader,
                                         "DQ", 5, "RP", 6, "BP", 7, "PD", 8,
                                         "MP", 9, "UM", 10, "RV", 11,
                                         "RH", 12, "LH", 13, "CC", 14,
-                                        "DC", 15, "WC", 16, 
+                                        "DC", 15, "WC", 16,
                                         NULL );
 
     return poFeature;
@@ -93,7 +93,7 @@ static OGRFeature *TranslateAddressPoint( NTFFileReader *poReader,
         || papoGroup[0]->GetType() != NRT_POINTREC
         || papoGroup[1]->GetType() != NRT_GEOMETRY )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // POINT_ID
@@ -134,7 +134,7 @@ static OGRFeature *TranslateOscarPoint( NTFFileReader *poReader,
         || papoGroup[0]->GetType() != NRT_POINTREC
         || papoGroup[1]->GetType() != NRT_GEOMETRY )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // POINT_ID
@@ -142,7 +142,7 @@ static OGRFeature *TranslateOscarPoint( NTFFileReader *poReader,
 
     // Geometry
     int         nGeomId;
-    
+
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
                                                              &nGeomId));
 
@@ -169,7 +169,7 @@ static OGRFeature *TranslateOscarLine( NTFFileReader *poReader,
         || papoGroup[0]->GetType() != NRT_LINEREC
         || papoGroup[1]->GetType() != NRT_GEOMETRY )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // LINE_ID
@@ -177,7 +177,7 @@ static OGRFeature *TranslateOscarLine( NTFFileReader *poReader,
 
     // Geometry
     int         nGeomId;
-    
+
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
                                                              &nGeomId));
 
@@ -205,7 +205,7 @@ static OGRFeature *TranslateOscarRoutePoint( NTFFileReader *poReader,
         || papoGroup[0]->GetType() != NRT_POINTREC
         || papoGroup[1]->GetType() != NRT_GEOMETRY )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // POINT_ID
@@ -213,7 +213,7 @@ static OGRFeature *TranslateOscarRoutePoint( NTFFileReader *poReader,
 
     // Geometry
     int         nGeomId;
-    
+
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
                                                              &nGeomId));
 
@@ -263,7 +263,7 @@ static OGRFeature *TranslateOscarRouteLine( NTFFileReader *poReader,
         || papoGroup[0]->GetType() != NRT_LINEREC
         || papoGroup[1]->GetType() != NRT_GEOMETRY )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // LINE_ID
@@ -271,7 +271,7 @@ static OGRFeature *TranslateOscarRouteLine( NTFFileReader *poReader,
 
     // Geometry
     int         nGeomId;
-    
+
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
                                                              &nGeomId));
 
@@ -280,7 +280,7 @@ static OGRFeature *TranslateOscarRouteLine( NTFFileReader *poReader,
     // Attributes
     poReader->ApplyAttributeValues( poFeature, papoGroup,
                                     "FC", 2, "OD", 3, "PN", 4, "LL", 5,
-                                    "RN", 6, "TR", 7, "NP", 8, 
+                                    "RN", 6, "TR", 7, "NP", 8,
                                     NULL );
 
     // PARENT_OSODR
@@ -348,7 +348,7 @@ static OGRFeature *TranslateOscarNetworkPoint( NTFFileReader *poReader,
         || papoGroup[0]->GetType() != NRT_POINTREC
         || papoGroup[1]->GetType() != NRT_GEOMETRY )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // POINT_ID
@@ -356,7 +356,7 @@ static OGRFeature *TranslateOscarNetworkPoint( NTFFileReader *poReader,
 
     // Geometry
     int         nGeomId;
-    
+
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
                                                              &nGeomId));
 
@@ -384,7 +384,7 @@ static OGRFeature *TranslateOscarNetworkLine( NTFFileReader *poReader,
         || papoGroup[0]->GetType() != NRT_LINEREC
         || papoGroup[1]->GetType() != NRT_GEOMETRY )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // LINE_ID
@@ -392,7 +392,7 @@ static OGRFeature *TranslateOscarNetworkLine( NTFFileReader *poReader,
 
     // Geometry
     int         nGeomId;
-    
+
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
                                                              &nGeomId));
 
@@ -401,7 +401,7 @@ static OGRFeature *TranslateOscarNetworkLine( NTFFileReader *poReader,
     // Attributes
     poReader->ApplyAttributeValues( poFeature, papoGroup,
                                     "FC", 2, "OD", 3, "PN", 4, "LL", 5,
-                                    "RN", 6, 
+                                    "RN", 6,
                                     NULL );
 
     return poFeature;
@@ -420,7 +420,7 @@ static OGRFeature *TranslateBasedataPoint( NTFFileReader *poReader,
         || papoGroup[0]->GetType() != NRT_POINTREC
         || papoGroup[1]->GetType() != NRT_GEOMETRY )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // POINT_ID
@@ -428,7 +428,7 @@ static OGRFeature *TranslateBasedataPoint( NTFFileReader *poReader,
 
     // Geometry
     int         nGeomId;
-    
+
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
                                                              &nGeomId));
 
@@ -457,7 +457,7 @@ static OGRFeature *TranslateBasedataLine( NTFFileReader *poReader,
         || papoGroup[0]->GetType() != NRT_LINEREC
         || papoGroup[1]->GetType() != NRT_GEOMETRY )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // LINE_ID
@@ -465,7 +465,7 @@ static OGRFeature *TranslateBasedataLine( NTFFileReader *poReader,
 
     // Geometry
     int         nGeomId;
-    
+
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
                                                              &nGeomId));
 
@@ -489,11 +489,11 @@ static OGRFeature *TranslateBoundarylineCollection( NTFFileReader *poReader,
                                                     NTFRecord **papoGroup )
 
 {
-    if( CSLCount((char **) papoGroup) != 2 
+    if( CSLCount((char **) papoGroup) != 2
         || papoGroup[0]->GetType() != NRT_COLLECT
         || papoGroup[1]->GetType() != NRT_ATTREC )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // COLL_ID
@@ -501,14 +501,14 @@ static OGRFeature *TranslateBoundarylineCollection( NTFFileReader *poReader,
 
     // NUM_PARTS
     int         nNumLinks = atoi(papoGroup[0]->GetField( 9, 12 ));
-    
+
     if( nNumLinks > MAX_LINK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "MAX_LINK exceeded in ntf_estlayers.cpp." );
         return poFeature;
     }
-    
+
     poFeature->SetField( 1, nNumLinks );
 
     // POLY_ID
@@ -539,13 +539,13 @@ static OGRFeature *TranslateBoundarylinePoly( NTFFileReader *poReader,
 /* ==================================================================== */
 /*      Traditional POLYGON record groups.                              */
 /* ==================================================================== */
-    if( CSLCount((char **) papoGroup) == 4 
+    if( CSLCount((char **) papoGroup) == 4
         && papoGroup[0]->GetType() == NRT_POLYGON
-        && papoGroup[1]->GetType() == NRT_ATTREC 
-        && papoGroup[2]->GetType() == NRT_CHAIN 
+        && papoGroup[1]->GetType() == NRT_ATTREC
+        && papoGroup[2]->GetType() == NRT_CHAIN
         && papoGroup[3]->GetType() == NRT_GEOMETRY )
     {
-        
+
         OGRFeature      *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
         // POLY_ID
@@ -553,14 +553,14 @@ static OGRFeature *TranslateBoundarylinePoly( NTFFileReader *poReader,
 
         // NUM_PARTS
         int             nNumLinks = atoi(papoGroup[2]->GetField( 9, 12 ));
-    
+
         if( nNumLinks > MAX_LINK )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "MAX_LINK exceeded in ntf_estlayers.cpp." );
             return poFeature;
         }
-    
+
         poFeature->SetField( 4, nNumLinks );
 
         // DIR
@@ -604,7 +604,7 @@ static OGRFeature *TranslateBoundarylinePoly( NTFFileReader *poReader,
 /*      First we do validation of the grouping.                         */
 /* -------------------------------------------------------------------- */
     int         iRec;
-    
+
     for( iRec = 0;
          papoGroup[iRec] != NULL && papoGroup[iRec+1] != NULL
              && papoGroup[iRec]->GetType() == NRT_POLYGON
@@ -622,7 +622,7 @@ static OGRFeature *TranslateBoundarylinePoly( NTFFileReader *poReader,
 /* -------------------------------------------------------------------- */
 /*      Collect the chains for each of the rings, and just aggregate    */
 /*      these into the master list without any concept of where the     */
-/*      boundaries are.  The boundary information will be emmitted      */
+/*      boundaries are.  The boundary information will be emitted      */
 /*      in the RingStart field.                                         */
 /* -------------------------------------------------------------------- */
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
@@ -641,7 +641,7 @@ static OGRFeature *TranslateBoundarylinePoly( NTFFileReader *poReader,
         nLineCount = atoi(papoGroup[iRec+1]->GetField(9,12));
 
         anRingStart[nRings++] = nNumLink;
-        
+
         for( i = 0; i < nLineCount && nNumLink < MAX_LINK*2; i++ )
         {
             anDirList[nNumLink] =
@@ -653,7 +653,7 @@ static OGRFeature *TranslateBoundarylinePoly( NTFFileReader *poReader,
 
         if( nNumLink == MAX_LINK*2 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "MAX_LINK exceeded in ntf_estlayers.cpp." );
 
             delete poFeature;
@@ -673,12 +673,13 @@ static OGRFeature *TranslateBoundarylinePoly( NTFFileReader *poReader,
     // RingStart
     poFeature->SetField( 7, nRings, anRingStart );
 
-    
+
 /* -------------------------------------------------------------------- */
 /*      collect information for whole complex polygon.                  */
 /* -------------------------------------------------------------------- */
     // POLY_ID
-    poFeature->SetField( 0, atoi(papoGroup[iRec]->GetField( 3, 8 )) );
+    if( papoGroup[iRec] != NULL )
+        poFeature->SetField( 0, atoi(papoGroup[iRec]->GetField( 3, 8 )) );
 
     // Attributes
     poReader->ApplyAttributeValues( poFeature, papoGroup,
@@ -704,16 +705,16 @@ static OGRFeature *TranslateBoundarylineLink( NTFFileReader *poReader,
                                               NTFRecord **papoGroup )
 
 {
-    if( CSLCount((char **) papoGroup) != 2 
+    if( CSLCount((char **) papoGroup) != 2
         || papoGroup[0]->GetType() != NRT_GEOMETRY
         || papoGroup[1]->GetType() != NRT_ATTREC )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // Geometry
     int         nGeomId;
-    
+
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[0],
                                                              &nGeomId));
 
@@ -740,12 +741,12 @@ static OGRFeature *TranslateBL2000Poly( NTFFileReader *poReader,
 /* ==================================================================== */
 /*      Traditional POLYGON record groups.                              */
 /* ==================================================================== */
-    if( CSLCount((char **) papoGroup) == 3 
+    if( CSLCount((char **) papoGroup) == 3
         && papoGroup[0]->GetType() == NRT_POLYGON
-        && papoGroup[1]->GetType() == NRT_ATTREC 
+        && papoGroup[1]->GetType() == NRT_ATTREC
         && papoGroup[2]->GetType() == NRT_CHAIN  )
     {
-        
+
         OGRFeature      *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
         // POLY_ID
@@ -753,15 +754,15 @@ static OGRFeature *TranslateBL2000Poly( NTFFileReader *poReader,
 
         // NUM_PARTS
         int             nNumLinks = atoi(papoGroup[2]->GetField( 9, 12 ));
-    
+
         if( nNumLinks > MAX_LINK )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "MAX_LINK exceeded in ntf_estlayers.cpp." );
 
             return poFeature;
         }
-    
+
         poFeature->SetField( 3, nNumLinks );
 
         // DIR
@@ -801,7 +802,7 @@ static OGRFeature *TranslateBL2000Poly( NTFFileReader *poReader,
 /*      First we do validation of the grouping.                         */
 /* -------------------------------------------------------------------- */
     int         iRec;
-    
+
     for( iRec = 0;
          papoGroup[iRec] != NULL && papoGroup[iRec+1] != NULL
              && papoGroup[iRec]->GetType() == NRT_POLYGON
@@ -818,7 +819,7 @@ static OGRFeature *TranslateBL2000Poly( NTFFileReader *poReader,
 /* -------------------------------------------------------------------- */
 /*      Collect the chains for each of the rings, and just aggregate    */
 /*      these into the master list without any concept of where the     */
-/*      boundaries are.  The boundary information will be emmitted      */
+/*      boundaries are.  The boundary information will be emitted      */
 /*      in the RingStart field.                                         */
 /* -------------------------------------------------------------------- */
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
@@ -837,7 +838,7 @@ static OGRFeature *TranslateBL2000Poly( NTFFileReader *poReader,
         nLineCount = atoi(papoGroup[iRec+1]->GetField(9,12));
 
         anRingStart[nRings++] = nNumLink;
-        
+
         for( i = 0; i < nLineCount && nNumLink < MAX_LINK*2; i++ )
         {
             anDirList[nNumLink] =
@@ -849,7 +850,7 @@ static OGRFeature *TranslateBL2000Poly( NTFFileReader *poReader,
 
         if( nNumLink == MAX_LINK*2 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "MAX_LINK exceeded in ntf_estlayers.cpp." );
 
             delete poFeature;
@@ -869,12 +870,13 @@ static OGRFeature *TranslateBL2000Poly( NTFFileReader *poReader,
     // RingStart
     poFeature->SetField( 6, nRings, anRingStart );
 
-    
+
 /* -------------------------------------------------------------------- */
 /*      collect information for whole complex polygon.                  */
 /* -------------------------------------------------------------------- */
     // POLY_ID
-    poFeature->SetField( 0, atoi(papoGroup[iRec]->GetField( 3, 8 )) );
+    if( papoGroup[iRec] != NULL )
+        poFeature->SetField( 0, atoi(papoGroup[iRec]->GetField( 3, 8 )) );
 
     // Attributes
     poReader->ApplyAttributeValues( poFeature, papoGroup,
@@ -901,7 +903,7 @@ static OGRFeature *TranslateBL2000Link( NTFFileReader *poReader,
         || papoGroup[1]->GetType() != NRT_GEOMETRY
         || papoGroup[2]->GetType() != NRT_ATTREC )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // LINE_ID
@@ -909,7 +911,7 @@ static OGRFeature *TranslateBL2000Link( NTFFileReader *poReader,
 
     // Geometry
     int         nGeomId;
-    
+
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
                                                              &nGeomId));
 
@@ -918,7 +920,7 @@ static OGRFeature *TranslateBL2000Link( NTFFileReader *poReader,
 
     // Attributes
     poReader->ApplyAttributeValues( poFeature, papoGroup,
-                                    "FC", 2, "LK", 3, 
+                                    "FC", 2, "LK", 3,
                                     NULL );
 
     return poFeature;
@@ -937,7 +939,7 @@ static OGRFeature *TranslateBL2000Collection( NTFFileReader *poReader,
         || papoGroup[0]->GetType() != NRT_COLLECT
         || papoGroup[1]->GetType() != NRT_ATTREC )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // COLL_ID
@@ -945,39 +947,41 @@ static OGRFeature *TranslateBL2000Collection( NTFFileReader *poReader,
 
     // NUM_PARTS
     int         nNumLinks = atoi(papoGroup[0]->GetField( 9, 12 ));
-    
+
     if( nNumLinks > MAX_LINK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "MAX_LINK exceeded in ntf_estlayers.cpp." );
 
         return poFeature;
     }
-    
+
     poFeature->SetField( 1, nNumLinks );
 
     // POLY_ID / COLL_ID_REFS
-    int         i, anList[MAX_LINK], anCollList[MAX_LINK];
+    int         anList[MAX_LINK], anCollList[MAX_LINK];
     int         nPolys=0, nCollections=0;
 
-    for( i = 0; i < nNumLinks; i++ )
+    for( int i = 0; i < nNumLinks; i++ )
     {
         if( atoi(papoGroup[0]->GetField( 13+i*8, 14+i*8 )) == 34 )
-            anCollList[nCollections++] = 
+            anCollList[nCollections++] =
                 atoi(papoGroup[0]->GetField( 15+i*8, 20+i*8 ));
         else
-            anList[nPolys++] = 
+            anList[nPolys++] =
                 atoi(papoGroup[0]->GetField( 15+i*8, 20+i*8 ));
     }
 
+    // coverity[uninit_use_in_call]
     poFeature->SetField( 2, nPolys, anList );
+    // coverity[uninit_use_in_call]
     poFeature->SetField( 10, nCollections, anCollList );
 
     // Attributes
     // Node that _CODE_DESC values are automatically applied if
-    // the target fields exist. 
+    // the target fields exist.
     poReader->ApplyAttributeValues( poFeature, papoGroup,
-                                    "AI", 3, "OP", 4, "NM", 5, "TY", 6, 
+                                    "AI", 3, "OP", 4, "NM", 5, "TY", 6,
                                     "AC", 7, "NB", 8, "NA", 9,
                                     NULL );
 
@@ -997,7 +1001,7 @@ static OGRFeature *TranslateMeridianPoint( NTFFileReader *poReader,
         || papoGroup[0]->GetType() != NRT_POINTREC
         || papoGroup[1]->GetType() != NRT_GEOMETRY )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // POINT_ID
@@ -1005,7 +1009,7 @@ static OGRFeature *TranslateMeridianPoint( NTFFileReader *poReader,
 
     // Geometry
     int         nGeomId;
-    
+
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
                                                              &nGeomId));
 
@@ -1016,7 +1020,7 @@ static OGRFeature *TranslateMeridianPoint( NTFFileReader *poReader,
     poReader->ApplyAttributeValues( poFeature, papoGroup,
                                     "FC", 2, "PN", 3, "OS", 4, "JN", 5,
                                     "RT", 6, "SI", 7, "PI", 8, "NM", 9,
-                                    "DA", 10, 
+                                    "DA", 10,
                                     NULL );
 
     return poFeature;
@@ -1035,7 +1039,7 @@ static OGRFeature *TranslateMeridianLine( NTFFileReader *poReader,
         || papoGroup[0]->GetType() != NRT_LINEREC
         || papoGroup[1]->GetType() != NRT_GEOMETRY )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // LINE_ID
@@ -1043,7 +1047,7 @@ static OGRFeature *TranslateMeridianLine( NTFFileReader *poReader,
 
     // Geometry
     int         nGeomId;
-    
+
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
                                                              &nGeomId));
 
@@ -1054,7 +1058,7 @@ static OGRFeature *TranslateMeridianLine( NTFFileReader *poReader,
     poReader->ApplyAttributeValues( poFeature, papoGroup,
                                     "FC", 1, "OM", 3, "RN", 4, "TR", 5,
                                     "RI", 6, "LC", 7, "RC", 8, "LD", 9,
-                                    "RD", 10, 
+                                    "RD", 10,
                                     NULL );
 
     return poFeature;
@@ -1073,7 +1077,7 @@ static OGRFeature *TranslateMeridian2Point( NTFFileReader *poReader,
         || papoGroup[0]->GetType() != NRT_POINTREC
         || papoGroup[1]->GetType() != NRT_GEOMETRY )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // POINT_ID
@@ -1081,7 +1085,7 @@ static OGRFeature *TranslateMeridian2Point( NTFFileReader *poReader,
 
     // Geometry
     int         nGeomId;
-    
+
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
                                                              &nGeomId));
 
@@ -1090,9 +1094,9 @@ static OGRFeature *TranslateMeridian2Point( NTFFileReader *poReader,
 
     // Attributes
     poReader->ApplyAttributeValues( poFeature, papoGroup,
-                                    "FC", 2, "PN", 3, "OD", 4, "PO", 5, 
-                                    "JN", 6, "RT", 7, "SN", 8, "SI", 9, 
-                                    "PI", 10, "NM", 11, "DA", 12, 
+                                    "FC", 2, "PN", 3, "OD", 4, "PO", 5,
+                                    "JN", 6, "RT", 7, "SN", 8, "SI", 9,
+                                    "PI", 10, "NM", 11, "DA", 12,
                                     "WA", 13, "HT", 14, "FA", 15,
                                     NULL );
 
@@ -1112,7 +1116,7 @@ static OGRFeature *TranslateMeridian2Line( NTFFileReader *poReader,
         || papoGroup[0]->GetType() != NRT_LINEREC
         || papoGroup[1]->GetType() != NRT_GEOMETRY )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // LINE_ID
@@ -1120,7 +1124,7 @@ static OGRFeature *TranslateMeridian2Line( NTFFileReader *poReader,
 
     // Geometry
     int         nGeomId;
-    
+
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
                                                              &nGeomId));
 
@@ -1129,7 +1133,7 @@ static OGRFeature *TranslateMeridian2Line( NTFFileReader *poReader,
 
     // Attributes
     poReader->ApplyAttributeValues( poFeature, papoGroup,
-                                    "FC", 1, "OD", 3, "PO", 4, "RN", 5, 
+                                    "FC", 1, "OD", 3, "PO", 4, "RN", 5,
                                     "TR", 6, "PN", 7, "RI", 8, "LC", 9,
                                     "RC", 10, "LD", 11, "RD", 12, "WI", 14,
                                     NULL );
@@ -1163,15 +1167,15 @@ static OGRFeature *TranslateStrategiNode( CPL_UNUSED NTFFileReader *poReader,
 
     // NUM_LINKS
     int         nNumLinks = atoi(papoGroup[0]->GetField( 15, 18 ));
-    
+
     if( nNumLinks > MAX_LINK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "MAX_LINK exceeded in ntf_estlayers.cpp." );
 
         return poFeature;
     }
-    
+
     poFeature->SetField( 2, nNumLinks );
 
     // DIR
@@ -1193,7 +1197,7 @@ static OGRFeature *TranslateStrategiNode( CPL_UNUSED NTFFileReader *poReader,
         anList[i] = atoi(papoGroup[0]->GetField( 19+i*12+11, 19+i*12+11 ));
 
     poFeature->SetField( 5, nNumLinks, anList );
-    
+
     // ORIENT (optional)
     if( EQUAL(poFeature->GetDefnRef()->GetFieldDefn(6)->GetNameRef(),
               "ORIENT") )
@@ -1223,11 +1227,11 @@ static OGRFeature *TranslateStrategiText( NTFFileReader *poReader,
 {
     if( CSLCount((char **) papoGroup) < 4
         || papoGroup[0]->GetType() != NRT_TEXTREC
-        || papoGroup[1]->GetType() != NRT_TEXTPOS 
-        || papoGroup[2]->GetType() != NRT_TEXTREP 
+        || papoGroup[1]->GetType() != NRT_TEXTPOS
+        || papoGroup[2]->GetType() != NRT_TEXTREP
         || papoGroup[3]->GetType() != NRT_GEOMETRY )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // POINT_ID
@@ -1273,7 +1277,7 @@ static OGRFeature *TranslateStrategiPoint( NTFFileReader *poReader,
         || papoGroup[0]->GetType() != NRT_POINTREC
         || papoGroup[1]->GetType() != NRT_GEOMETRY )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // POINT_ID
@@ -1281,7 +1285,7 @@ static OGRFeature *TranslateStrategiPoint( NTFFileReader *poReader,
 
     // Geometry
     int         nGeomId;
-    
+
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
                                                              &nGeomId));
 
@@ -1315,7 +1319,7 @@ static OGRFeature *TranslateStrategiLine( NTFFileReader *poReader,
         || papoGroup[0]->GetType() != NRT_LINEREC
         || papoGroup[1]->GetType() != NRT_GEOMETRY )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // LINE_ID
@@ -1323,7 +1327,7 @@ static OGRFeature *TranslateStrategiLine( NTFFileReader *poReader,
 
     // Geometry
     int         nGeomId;
-    
+
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
                                                              &nGeomId));
 
@@ -1354,7 +1358,7 @@ static OGRFeature *TranslateLandrangerPoint( NTFFileReader *poReader,
         || papoGroup[0]->GetType() != NRT_POINTREC
         || papoGroup[1]->GetType() != NRT_GEOMETRY )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // POINT_ID
@@ -1365,7 +1369,7 @@ static OGRFeature *TranslateLandrangerPoint( NTFFileReader *poReader,
 
     // HEIGHT
     poFeature->SetField( 2, atoi(papoGroup[0]->GetField( 11, 16 )) );
-    
+
     // Geometry
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1]));
 
@@ -1385,7 +1389,7 @@ static OGRFeature *TranslateLandrangerLine( NTFFileReader *poReader,
         || papoGroup[0]->GetType() != NRT_LINEREC
         || papoGroup[1]->GetType() != NRT_GEOMETRY )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // LINE_ID
@@ -1412,12 +1416,12 @@ static OGRFeature *TranslateProfilePoint( NTFFileReader *poReader,
                                           NTFRecord **papoGroup )
 
 {
-    if( CSLCount((char **) papoGroup) < 2 
+    if( CSLCount((char **) papoGroup) < 2
         || papoGroup[0]->GetType() != NRT_POINTREC
         || (papoGroup[1]->GetType() != NRT_GEOMETRY
             && papoGroup[1]->GetType() != NRT_GEOMETRY3D) )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // POINT_ID
@@ -1429,14 +1433,14 @@ static OGRFeature *TranslateProfilePoint( NTFFileReader *poReader,
     // Geometry
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1]));
 
-    // Attributes 
+    // Attributes
     poReader->ApplyAttributeValues( poFeature, papoGroup,
                                     "HT", 2,
                                     NULL );
 
     // Set HEIGHT/elevation
     OGRPoint    *poPoint = (OGRPoint *) poFeature->GetGeometryRef();
-    
+
     if( poPoint != NULL && poPoint->getCoordinateDimension() == 3 )
     {
         poFeature->SetField( 2, poPoint->getZ() );
@@ -1446,7 +1450,7 @@ static OGRFeature *TranslateProfilePoint( NTFFileReader *poReader,
         poFeature->SetField( 2, poFeature->GetFieldAsDouble(2) * 0.01 );
         poPoint->setZ( poFeature->GetFieldAsDouble(2) );
     }
-    
+
     return poFeature;
 }
 
@@ -1464,7 +1468,7 @@ static OGRFeature *TranslateProfileLine( NTFFileReader *poReader,
         || (papoGroup[1]->GetType() != NRT_GEOMETRY
             && papoGroup[1]->GetType() != NRT_GEOMETRY3D) )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // LINE_ID
@@ -1476,14 +1480,14 @@ static OGRFeature *TranslateProfileLine( NTFFileReader *poReader,
     // Geometry
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1]));
 
-    // Attributes 
+    // Attributes
     poReader->ApplyAttributeValues( poFeature, papoGroup,
                                     "HT", 2,
                                     NULL );
-    
+
     // Set HEIGHT/elevation
     OGRLineString *poLine = (OGRLineString *) poFeature->GetGeometryRef();
-    
+
     poFeature->SetField( 2, poFeature->GetFieldAsDouble(2) * 0.01 );
     if( poLine != NULL && poLine->getCoordinateDimension() == 2 )
     {
@@ -1496,14 +1500,14 @@ static OGRFeature *TranslateProfileLine( NTFFileReader *poReader,
     else if( poLine != NULL )
     {
         double  dfAccum = 0.0;
-        
+
         for( int i = 0; i < poLine->getNumPoints(); i++ )
         {
             dfAccum += poLine->getZ(i);
         }
         poFeature->SetField( 2, dfAccum / poLine->getNumPoints() );
     }
-    
+
     return poFeature;
 }
 
@@ -1520,7 +1524,7 @@ static OGRFeature *TranslateLandlinePoint( NTFFileReader *poReader,
         || papoGroup[0]->GetType() != NRT_POINTREC
         || papoGroup[1]->GetType() != NRT_GEOMETRY )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // POINT_ID
@@ -1568,7 +1572,7 @@ static OGRFeature *TranslateLandlineLine( NTFFileReader *poReader,
         || papoGroup[0]->GetType() != NRT_LINEREC
         || papoGroup[1]->GetType() != NRT_GEOMETRY )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // LINE_ID
@@ -1603,33 +1607,33 @@ static OGRFeature *TranslateLandlineName( NTFFileReader *poReader,
                                           NTFRecord **papoGroup )
 
 {
-    if( CSLCount((char **) papoGroup) != 3 
+    if( CSLCount((char **) papoGroup) != 3
         || papoGroup[0]->GetType() != NRT_NAMEREC
         || papoGroup[1]->GetType() != NRT_NAMEPOSTN
         || papoGroup[2]->GetType() != NRT_GEOMETRY )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
-        
+
     // NAME_ID
     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
-        
+
     // TEXT_CODE
     poFeature->SetField( 1, papoGroup[0]->GetField( 9, 12 ) );
-        
+
     // TEXT
     int         nNumChar = atoi(papoGroup[0]->GetField(13,14));
     poFeature->SetField( 2, papoGroup[0]->GetField( 15, 15+nNumChar-1) );
-    
+
     // FONT
     poFeature->SetField( 3, atoi(papoGroup[1]->GetField( 3, 6 )) );
 
     // TEXT_HT
     poFeature->SetField( 4, atoi(papoGroup[1]->GetField(7,9)) * 0.1 );
-        
+
     // DIG_POSTN
     poFeature->SetField( 5, atoi(papoGroup[1]->GetField(10,10)) );
-        
+
     // ORIENT
     poFeature->SetField( 6, CPLAtof(papoGroup[1]->GetField( 11, 14 )) * 0.1 );
 
@@ -1647,7 +1651,7 @@ static OGRFeature *TranslateLandlineName( NTFFileReader *poReader,
     // CHG_TYPE (optional)
     if( poFeature->GetFieldIndex("CHG_TYPE") == 9 )
     {
-        poFeature->SetField( 9, papoGroup[0]->GetField( 15+nNumChar+1, 
+        poFeature->SetField( 9, papoGroup[0]->GetField( 15+nNumChar+1,
                                                         15+nNumChar+1 ) );
     }
 
@@ -1683,7 +1687,7 @@ void NTFFileReader::EstablishLayer( const char * pszLayerName,
     poLayer = poDS->GetNamedLayer(pszLayerName);
 
 /* ==================================================================== */
-/*      Create a new layer matching the request if we don't aleady      */
+/*      Create a new layer matching the request if we don't already      */
 /*      have one.                                                       */
 /* ==================================================================== */
     if( poLayer == NULL )
@@ -1700,26 +1704,26 @@ void NTFFileReader::EstablishLayer( const char * pszLayerName,
 /*      Fetch definitions of each field in turn.                        */
 /* -------------------------------------------------------------------- */
         va_start(hVaArgs, poClass);
-        while( TRUE )
+        while( true )
         {
             const char  *pszFieldName = va_arg(hVaArgs, const char *);
             OGRFieldType     eType;
             int          nWidth, nPrecision;
-            
+
             if( pszFieldName == NULL )
                 break;
-            
+
             eType = (OGRFieldType) va_arg(hVaArgs, int);
             nWidth = va_arg(hVaArgs, int);
             nPrecision = va_arg(hVaArgs, int);
-            
+
             OGRFieldDefn         oFieldDefn( pszFieldName, eType );
             oFieldDefn.SetWidth( nWidth );
             oFieldDefn.SetPrecision( nPrecision );
-            
+
             poDefn->AddFieldDefn( &oFieldDefn );
         }
-        
+
         va_end(hVaArgs);
 
 /* -------------------------------------------------------------------- */
@@ -1733,18 +1737,18 @@ void NTFFileReader::EstablishLayer( const char * pszLayerName,
                 OGRFieldDefn    oFieldDefn( poClass->papszAttrNames[iGAtt],
                                             OFTInteger );
 
-                if( EQUALN(pszFormat,"I",1) )
+                if( STARTS_WITH_CI(pszFormat, "I") )
                 {
                     oFieldDefn.SetType( OFTInteger );
                     oFieldDefn.SetWidth( poClass->panAttrMaxWidth[iGAtt] );
                 }
-                else if( EQUALN(pszFormat,"D",1)
-                         || EQUALN(pszFormat,"A",1) )
+                else if( STARTS_WITH_CI(pszFormat, "D")
+                         || STARTS_WITH_CI(pszFormat, "A") )
                 {
                     oFieldDefn.SetType( OFTString );
                     oFieldDefn.SetWidth( poClass->panAttrMaxWidth[iGAtt] );
                 }
-                else if( EQUALN(pszFormat,"R",1) )
+                else if( STARTS_WITH_CI(pszFormat, "R") )
                 {
                     oFieldDefn.SetType( OFTReal );
                     oFieldDefn.SetWidth( poClass->panAttrMaxWidth[iGAtt]+1 );
@@ -1756,7 +1760,7 @@ void NTFFileReader::EstablishLayer( const char * pszLayerName,
 
                 poDefn->AddFieldDefn( &oFieldDefn );
 
-                /* 
+                /*
                 ** If this field can appear multiple times, create an
                 ** additional attribute to hold lists of values.  This
                 ** is always created as a variable length string field.
@@ -1765,7 +1769,7 @@ void NTFFileReader::EstablishLayer( const char * pszLayerName,
                 {
                     char szName[128];
 
-                    sprintf( szName, "%s_LIST", 
+                    snprintf( szName, sizeof(szName), "%s_LIST",
                              poClass->papszAttrNames[iGAtt] );
 
                     OGRFieldDefn oFieldDefnL( szName, OFTString );
@@ -1783,7 +1787,7 @@ void NTFFileReader::EstablishLayer( const char * pszLayerName,
         oTileID.SetWidth( 10 );
 
         poDefn->AddFieldDefn( &oTileID );
-            
+
 /* -------------------------------------------------------------------- */
 /*      Create the layer, and give over to the data source object to    */
 /*      maintain.                                                       */
@@ -1828,13 +1832,13 @@ void NTFFileReader::EstablishLayers()
                         "ORIENT", OFTReal, 5, 1,
                         "DISTANCE", OFTReal, 6, 3,
                         NULL );
-                        
+
         EstablishLayer( "LANDLINE_LINE", wkbLineString,
                         TranslateLandlineLine, NRT_LINEREC, NULL,
                         "LINE_ID", OFTInteger, 6, 0,
                         "FEAT_CODE", OFTString, 4, 0,
                         NULL );
-                        
+
         EstablishLayer( "LANDLINE_NAME", wkbPoint,
                         TranslateLandlineName, NRT_NAMEREC, NULL,
                         "NAME_ID", OFTInteger, 6, 0,
@@ -1855,18 +1859,18 @@ void NTFFileReader::EstablishLayers()
                         "FEAT_CODE", OFTString, 4, 0,
                         "ORIENT", OFTReal, 5, 1,
                         "DISTANCE", OFTReal, 6, 3,
-                        "CHG_DATE", OFTString, 6, 0, 
-                        "CHG_TYPE", OFTString, 1, 0, 
+                        "CHG_DATE", OFTString, 6, 0,
+                        "CHG_TYPE", OFTString, 1, 0,
                         NULL );
-                        
+
         EstablishLayer( "LANDLINE99_LINE", wkbLineString,
                         TranslateLandlineLine, NRT_LINEREC, NULL,
                         "LINE_ID", OFTInteger, 6, 0,
                         "FEAT_CODE", OFTString, 4, 0,
-                        "CHG_DATE", OFTString, 6, 0, 
-                        "CHG_TYPE", OFTString, 1, 0, 
+                        "CHG_DATE", OFTString, 6, 0,
+                        "CHG_TYPE", OFTString, 1, 0,
                         NULL );
-                        
+
         EstablishLayer( "LANDLINE99_NAME", wkbPoint,
                         TranslateLandlineName, NRT_NAMEREC, NULL,
                         "NAME_ID", OFTInteger, 6, 0,
@@ -1878,7 +1882,7 @@ void NTFFileReader::EstablishLayers()
                         "ORIENT", OFTReal, 5, 1,
                         "TEXT_HT_GROUND", OFTReal, 10, 3,
                         "CHG_DATE", OFTString, 6, 0,
-                        "CHG_TYPE", OFTString, 1, 0, 
+                        "CHG_TYPE", OFTString, 1, 0,
                         NULL );
     }
     else if( GetProductId() == NPC_LANDRANGER_CONT )
@@ -1889,7 +1893,7 @@ void NTFFileReader::EstablishLayers()
                         "FEAT_CODE", OFTString, 4, 0,
                         "HEIGHT", OFTReal, 7, 2,
                         NULL );
-                        
+
         EstablishLayer( "PANORAMA_CONTOUR", wkbLineString,
                         TranslateLandrangerLine, NRT_LINEREC, NULL,
                         "LINE_ID", OFTInteger, 6, 0,
@@ -1905,7 +1909,7 @@ void NTFFileReader::EstablishLayers()
                         "FEAT_CODE", OFTString, 4, 0,
                         "HEIGHT", OFTReal, 7, 2,
                         NULL );
-                        
+
         EstablishLayer( "PROFILE_LINE", wkbLineString25D,
                         TranslateProfileLine, NRT_LINEREC, NULL,
                         "LINE_ID", OFTInteger, 6, 0,
@@ -1919,14 +1923,14 @@ void NTFFileReader::EstablishLayers()
                         TranslateStrategiPoint, NRT_POINTREC, NULL,
                         "POINT_ID", OFTInteger, 6, 0,
                         "FEAT_CODE", OFTString, 4, 0,
-                        "PROPER_NAME", OFTString, 0, 0, 
-                        "FEATURE_NUMBER", OFTString, 0, 0, 
-                        "RB", OFTString, 1, 0, 
-                        "RU", OFTString, 1, 0, 
-                        "AN", OFTString, 0, 0, 
-                        "AO", OFTString, 0, 0, 
-                        "COUNTY_NAME", OFTString, 0, 0, 
-                        "UNITARY_NAME", OFTString, 0, 0, 
+                        "PROPER_NAME", OFTString, 0, 0,
+                        "FEATURE_NUMBER", OFTString, 0, 0,
+                        "RB", OFTString, 1, 0,
+                        "RU", OFTString, 1, 0,
+                        "AN", OFTString, 0, 0,
+                        "AO", OFTString, 0, 0,
+                        "COUNTY_NAME", OFTString, 0, 0,
+                        "UNITARY_NAME", OFTString, 0, 0,
                         "GEOM_ID", OFTInteger, 6, 0,
                         "DATE", OFTInteger, 8, 0,
                         "DISTRICT_NAME", OFTString, 0, 0,
@@ -1945,7 +1949,7 @@ void NTFFileReader::EstablishLayers()
                         "RESTRICTION_ANTICLOCKWISE", OFTString, 0, 0,
                         "USAGE", OFTInteger, 1, 0,
                         NULL );
-        
+
         EstablishLayer( "STRATEGI_LINE", wkbLineString,
                         TranslateStrategiLine, NRT_LINEREC, NULL,
                         "LINE_ID", OFTInteger, 6, 0,
@@ -1961,7 +1965,7 @@ void NTFFileReader::EstablishLayers()
                         "FERRY_RESTRICTIONS", OFTString, 0, 0,
                         "FERRY_TO", OFTString, 0, 0,
                         "GIS", OFTString, 0, 0,
-                        "FEATURE_NUMBER", OFTString, 0, 0, 
+                        "FEATURE_NUMBER", OFTString, 0, 0,
                         NULL );
 
         EstablishLayer( "STRATEGI_TEXT", wkbPoint,
@@ -1970,9 +1974,9 @@ void NTFFileReader::EstablishLayers()
                         "FEAT_CODE", OFTString, 4, 0,
                         "FONT", OFTInteger, 4, 0,
                         "TEXT_HT", OFTReal, 5, 1,
-                        "DIG_POSTN", OFTInteger, 1, 0, 
+                        "DIG_POSTN", OFTInteger, 1, 0,
                         "ORIENT", OFTReal, 5, 1,
-                        "TEXT", OFTString, 0, 0, 
+                        "TEXT", OFTString, 0, 0,
                         "TEXT_HT_GROUND", OFTReal, 10, 3,
                         "DATE", OFTInteger, 8, 0,
                         NULL );
@@ -1995,29 +1999,29 @@ void NTFFileReader::EstablishLayers()
                         "POINT_ID", OFTInteger, 6, 0,
                         "GEOM_ID", OFTInteger, 6, 0,
                         "FEAT_CODE", OFTString, 4, 0,
-                        "PROPER_NAME", OFTString, 0, 0, 
+                        "PROPER_NAME", OFTString, 0, 0,
                         "OSMDR", OFTString, 13, 0,
                         "JUNCTION_NAME", OFTString, 0, 0,
                         "ROUNDABOUT", OFTString, 1, 0,
                         "STATION_ID", OFTString, 13, 0,
-                        "GLOBAL_ID", OFTInteger, 6, 0, 
-                        "ADMIN_NAME", OFTString, 0, 0, 
-                        "DA_DLUA_ID", OFTString, 13, 0, 
+                        "GLOBAL_ID", OFTInteger, 6, 0,
+                        "ADMIN_NAME", OFTString, 0, 0,
+                        "DA_DLUA_ID", OFTString, 13, 0,
                         NULL );
-        
+
         EstablishLayer( "MERIDIAN_LINE", wkbLineString,
                         TranslateMeridianLine, NRT_LINEREC, NULL,
                         "LINE_ID", OFTInteger, 6, 0,
                         "FEAT_CODE", OFTString, 4, 0,
                         "GEOM_ID", OFTInteger, 6, 0,
-                        "OSMDR", OFTString, 13, 0, 
-                        "ROAD_NUM", OFTString, 0, 0, 
-                        "TRUNK_ROAD", OFTString, 1, 0, 
-                        "RAIL_ID", OFTString, 13, 0, 
-                        "LEFT_COUNTY", OFTInteger, 6, 0, 
-                        "RIGHT_COUNTY", OFTInteger, 6, 0, 
-                        "LEFT_DISTRICT", OFTInteger, 6, 0, 
-                        "RIGHT_DISTRICT", OFTInteger, 6, 0, 
+                        "OSMDR", OFTString, 13, 0,
+                        "ROAD_NUM", OFTString, 0, 0,
+                        "TRUNK_ROAD", OFTString, 1, 0,
+                        "RAIL_ID", OFTString, 13, 0,
+                        "LEFT_COUNTY", OFTInteger, 6, 0,
+                        "RIGHT_COUNTY", OFTInteger, 6, 0,
+                        "LEFT_DISTRICT", OFTInteger, 6, 0,
+                        "RIGHT_DISTRICT", OFTInteger, 6, 0,
                         NULL );
 
         EstablishLayer( "MERIDIAN_TEXT", wkbPoint,
@@ -2026,9 +2030,9 @@ void NTFFileReader::EstablishLayers()
                         "FEAT_CODE", OFTString, 4, 0,
                         "FONT", OFTInteger, 4, 0,
                         "TEXT_HT", OFTReal, 5, 1,
-                        "DIG_POSTN", OFTInteger, 1, 0, 
+                        "DIG_POSTN", OFTInteger, 1, 0,
                         "ORIENT", OFTReal, 5, 1,
-                        "TEXT", OFTString, 0, 0, 
+                        "TEXT", OFTString, 0, 0,
                         "TEXT_HT_GROUND", OFTReal, 10, 3,
                         NULL );
 
@@ -2050,37 +2054,37 @@ void NTFFileReader::EstablishLayers()
                         "POINT_ID", OFTInteger, 6, 0,
                         "GEOM_ID", OFTInteger, 6, 0,
                         "FEAT_CODE", OFTString, 4, 0,
-                        "PROPER_NAME", OFTString, 0, 0, 
+                        "PROPER_NAME", OFTString, 0, 0,
                         "OSODR", OFTString, 13, 0,
                         "PARENT_OSODR", OFTString, 13, 0,
                         "JUNCTION_NAME", OFTString, 0, 0,
                         "ROUNDABOUT", OFTString, 1, 0,
                         "SETTLEMENT_NAME", OFTString, 0, 0,
                         "STATION_ID", OFTString, 13, 0,
-                        "GLOBAL_ID", OFTInteger, 6, 0, 
-                        "ADMIN_NAME", OFTString, 0, 0, 
-                        "DA_DLUA_ID", OFTString, 13, 0, 
-                        "WATER_AREA", OFTString, 13, 0, 
+                        "GLOBAL_ID", OFTInteger, 6, 0,
+                        "ADMIN_NAME", OFTString, 0, 0,
+                        "DA_DLUA_ID", OFTString, 13, 0,
+                        "WATER_AREA", OFTString, 13, 0,
                         "HEIGHT", OFTInteger, 8, 0,
                         "FOREST_ID", OFTString, 13, 0,
                         NULL );
-        
+
         EstablishLayer( "MERIDIAN2_LINE", wkbLineString,
                         TranslateMeridian2Line, NRT_LINEREC, NULL,
                         "LINE_ID", OFTInteger, 6, 0,
                         "FEAT_CODE", OFTString, 4, 0,
                         "GEOM_ID", OFTInteger, 6, 0,
-                        "OSODR", OFTString, 13, 0, 
+                        "OSODR", OFTString, 13, 0,
                         "PARENT_OSODR", OFTString, 13, 0,
-                        "ROAD_NUM", OFTString, 0, 0, 
-                        "TRUNK_ROAD", OFTString, 1, 0, 
-                        "PROPER_NAME", OFTString, 0, 0, 
-                        "RAIL_ID", OFTString, 13, 0, 
-                        "LEFT_COUNTY", OFTInteger, 6, 0, 
-                        "RIGHT_COUNTY", OFTInteger, 6, 0, 
-                        "LEFT_DISTRICT", OFTInteger, 6, 0, 
-                        "RIGHT_DISTRICT", OFTInteger, 6, 0, 
-                        "WATER_LINK_ID", OFTString, 13, 0, 
+                        "ROAD_NUM", OFTString, 0, 0,
+                        "TRUNK_ROAD", OFTString, 1, 0,
+                        "PROPER_NAME", OFTString, 0, 0,
+                        "RAIL_ID", OFTString, 13, 0,
+                        "LEFT_COUNTY", OFTInteger, 6, 0,
+                        "RIGHT_COUNTY", OFTInteger, 6, 0,
+                        "LEFT_DISTRICT", OFTInteger, 6, 0,
+                        "RIGHT_DISTRICT", OFTInteger, 6, 0,
+                        "WATER_LINK_ID", OFTString, 13, 0,
                         NULL );
 
         EstablishLayer( "MERIDIAN2_TEXT", wkbPoint,
@@ -2089,9 +2093,9 @@ void NTFFileReader::EstablishLayers()
                         "FEAT_CODE", OFTString, 4, 0,
                         "FONT", OFTInteger, 4, 0,
                         "TEXT_HT", OFTReal, 5, 1,
-                        "DIG_POSTN", OFTInteger, 1, 0, 
+                        "DIG_POSTN", OFTInteger, 1, 0,
                         "ORIENT", OFTReal, 5, 1,
-                        "TEXT", OFTString, 0, 0, 
+                        "TEXT", OFTString, 0, 0,
                         "TEXT_HT_GROUND", OFTReal, 10, 3,
                         NULL );
 
@@ -2113,17 +2117,17 @@ void NTFFileReader::EstablishLayers()
                         "GEOM_ID", OFTInteger, 6, 0,
                         "FEAT_CODE", OFTString, 4, 0,
                         "GLOBAL_LINK_ID", OFTInteger, 10, 0,
-                        "HWM_FLAG", OFTInteger, 1, 0, 
+                        "HWM_FLAG", OFTInteger, 1, 0,
                         NULL );
 
-        EstablishLayer( "BOUNDARYLINE_POLY", 
+        EstablishLayer( "BOUNDARYLINE_POLY",
                         bCacheLines ? wkbPolygon : wkbPoint,
                         TranslateBoundarylinePoly, NRT_POLYGON, NULL,
                         "POLY_ID", OFTInteger, 6, 0,
                         "FEAT_CODE", OFTString, 4, 0,
                         "GLOBAL_SEED_ID", OFTInteger, 6, 0,
                         "HECTARES", OFTReal, 9, 3,
-                        "NUM_PARTS", OFTInteger, 4, 0, 
+                        "NUM_PARTS", OFTInteger, 4, 0,
                         "DIR", OFTIntegerList, 1, 0,
                         "GEOM_ID_OF_LINK", OFTIntegerList, 6, 0,
                         "RingStart", OFTIntegerList, 6, 0,
@@ -2134,7 +2138,7 @@ void NTFFileReader::EstablishLayers()
                         "COLL_ID", OFTInteger, 6, 0,
                         "NUM_PARTS", OFTInteger, 4, 0,
                         "POLY_ID", OFTIntegerList, 6, 0,
-                        "ADMIN_AREA_ID", OFTInteger, 6, 0, 
+                        "ADMIN_AREA_ID", OFTInteger, 6, 0,
                         "OPCS_CODE", OFTString, 6, 0,
                         "ADMIN_NAME", OFTString, 0, 0,
                         NULL );
@@ -2148,25 +2152,25 @@ void NTFFileReader::EstablishLayers()
                         "FEAT_CODE", OFTString, 4, 0,
                         "GLOBAL_LINK_ID", OFTInteger, 10, 0,
                         NULL );
-        EstablishLayer( "BL2000_POLY", 
+        EstablishLayer( "BL2000_POLY",
                         bCacheLines ? wkbPolygon : wkbNone,
                         TranslateBL2000Poly, NRT_POLYGON, NULL,
                         "POLY_ID", OFTInteger, 6, 0,
                         "GLOBAL_SEED_ID", OFTInteger, 6, 0,
                         "HECTARES", OFTReal, 12, 3,
-                        "NUM_PARTS", OFTInteger, 4, 0, 
+                        "NUM_PARTS", OFTInteger, 4, 0,
                         "DIR", OFTIntegerList, 1, 0,
                         "GEOM_ID_OF_LINK", OFTIntegerList, 6, 0,
                         "RingStart", OFTIntegerList, 6, 0,
                         NULL );
-        if( poDS->GetOption("CODELIST") != NULL 
+        if( poDS->GetOption("CODELIST") != NULL
             && EQUAL(poDS->GetOption("CODELIST"),"ON") )
             EstablishLayer( "BL2000_COLLECTIONS", wkbNone,
                             TranslateBL2000Collection, NRT_COLLECT, NULL,
                             "COLL_ID", OFTInteger, 6, 0,
                             "NUM_PARTS", OFTInteger, 4, 0,
                             "POLY_ID", OFTIntegerList, 6, 0,
-                            "ADMIN_AREA_ID", OFTInteger, 6, 0, 
+                            "ADMIN_AREA_ID", OFTInteger, 6, 0,
                             "CENSUS_CODE", OFTString, 7, 0,
                             "ADMIN_NAME", OFTString, 0, 0,
                             "AREA_TYPE", OFTString, 2, 0,
@@ -2184,7 +2188,7 @@ void NTFFileReader::EstablishLayers()
                             "COLL_ID", OFTInteger, 6, 0,
                             "NUM_PARTS", OFTInteger, 4, 0,
                             "POLY_ID", OFTIntegerList, 6, 0,
-                            "ADMIN_AREA_ID", OFTInteger, 6, 0, 
+                            "ADMIN_AREA_ID", OFTInteger, 6, 0,
                             "CENSUS_CODE", OFTString, 7, 0,
                             "ADMIN_NAME", OFTString, 0, 0,
                             "AREA_TYPE", OFTString, 2, 0,
@@ -2201,21 +2205,21 @@ void NTFFileReader::EstablishLayers()
                         "POINT_ID", OFTInteger, 6, 0,
                         "GEOM_ID", OFTInteger, 6, 0,
                         "FEAT_CODE", OFTString, 4, 0,
-                        "PROPER_NAME", OFTString, 0, 0, 
-                        "FEATURE_NUMBER", OFTString, 0, 0, 
-                        "COUNTY_NAME", OFTString, 0, 0, 
-                        "UNITARY_NAME", OFTString, 0, 0, 
+                        "PROPER_NAME", OFTString, 0, 0,
+                        "FEATURE_NUMBER", OFTString, 0, 0,
+                        "COUNTY_NAME", OFTString, 0, 0,
+                        "UNITARY_NAME", OFTString, 0, 0,
                         "ORIENT", OFTRealList, 5, 1,
                         NULL );
-        
+
         EstablishLayer( "BASEDATA_LINE", wkbLineString,
                         TranslateBasedataLine, NRT_LINEREC, NULL,
                         "LINE_ID", OFTInteger, 6, 0,
                         "FEAT_CODE", OFTString, 4, 0,
                         "GEOM_ID", OFTInteger, 6, 0,
-                        "PROPER_NAME", OFTString, 0, 0, 
-                        "FEATURE_NUMBER", OFTString, 0, 0, 
-                        "RB", OFTString, 1, 0, 
+                        "PROPER_NAME", OFTString, 0, 0,
+                        "FEATURE_NUMBER", OFTString, 0, 0,
+                        "RB", OFTString, 1, 0,
                         NULL );
 
         EstablishLayer( "BASEDATA_TEXT", wkbPoint,
@@ -2224,9 +2228,9 @@ void NTFFileReader::EstablishLayers()
                         "FEAT_CODE", OFTString, 4, 0,
                         "FONT", OFTInteger, 4, 0,
                         "TEXT_HT", OFTReal, 5, 1,
-                        "DIG_POSTN", OFTInteger, 1, 0, 
+                        "DIG_POSTN", OFTInteger, 1, 0,
                         "ORIENT", OFTReal, 5, 1,
-                        "TEXT", OFTString, 0, 0, 
+                        "TEXT", OFTString, 0, 0,
                         "TEXT_HT_GROUND", OFTReal, 10, 3,
                         NULL );
 
@@ -2253,7 +2257,7 @@ void NTFFileReader::EstablishLayers()
                         "JUNCTION_NAME", OFTString, 0, 0,
                         "SETTLE_NAME", OFTString, 0, 0,
                         NULL );
-        
+
         EstablishLayer( "OSCAR_LINE", wkbLineString,
                         TranslateOscarLine, NRT_LINEREC, NULL,
                         "LINE_ID", OFTInteger, 6, 0,
@@ -2265,7 +2269,7 @@ void NTFFileReader::EstablishLayers()
                         "SOURCE", OFTString, 1, 0,
                         "FORM_OF_WAY", OFTString, 1, 0,
                         "ROAD_NUM", OFTString, 0, 0,
-                        "TRUNK_ROAD", OFTString, 1, 0, 
+                        "TRUNK_ROAD", OFTString, 1, 0,
                         NULL );
 
         EstablishLayer( "OSCAR_NODE", wkbNone,
@@ -2299,7 +2303,7 @@ void NTFFileReader::EstablishLayers()
                         "PARENT_OSODR", OFTStringList, 13, 0,
                         "ROUNDABOUT", OFTString, 1, 0,
                         NULL );
-        
+
         EstablishLayer( "OSCAR_ROUTE_LINE", wkbLineString,
                         TranslateOscarRouteLine, NRT_LINEREC, NULL,
                         "LINE_ID", OFTInteger, 6, 0,
@@ -2309,7 +2313,7 @@ void NTFFileReader::EstablishLayers()
                         "PROPER_NAME", OFTString, 0, 0,
                         "LINE_LENGTH", OFTInteger, 5, 0,
                         "ROAD_NUM", OFTString, 0, 0,
-                        "TRUNK_ROAD", OFTString, 1, 0, 
+                        "TRUNK_ROAD", OFTString, 1, 0,
                         "NUM_PARENTS", OFTInteger, 2, 0,
                         "PARENT_OSODR", OFTStringList, 13, 0,
                         NULL );
@@ -2343,7 +2347,7 @@ void NTFFileReader::EstablishLayers()
                         "SETTLE_NAME", OFTString, 0, 0,
                         "ROUNDABOUT", OFTString, 1, 0,
                         NULL );
-        
+
         EstablishLayer( "OSCAR_NETWORK_LINE", wkbLineString,
                         TranslateOscarNetworkLine, NRT_LINEREC, NULL,
                         "LINE_ID", OFTInteger, 6, 0,
@@ -2394,7 +2398,7 @@ void NTFFileReader::EstablishLayers()
                         "STATUS_FLAG", OFTString, 4, 0,
                         "RM_VERSION_DATE", OFTString, 8, 0,
                         "CHG_TYPE", OFTString, 1, 0,
-                        "CHG_DATE", OFTString, 6, 0, 
+                        "CHG_DATE", OFTString, 6, 0,
                         NULL );
     }
     else if( GetProductId() == NPC_CODE_POINT )
@@ -2405,13 +2409,13 @@ void NTFFileReader::EstablishLayers()
                         "UNIT_POSTCODE", OFTString, 7, 0,
                         "POSITIONAL_QUALITY", OFTInteger, 1, 0,
                         "PO_BOX_INDICATOR", OFTString, 1, 0,
-                        "TOTAL_DELIVERY_POINTS", OFTInteger, 3, 0, 
-                        "DELIVERY_POINTS", OFTInteger, 3, 0, 
-                        "DOMESTIC_DELIVERY_POINTS", OFTInteger, 3, 0, 
-                        "NONDOMESTIC_DELIVERY_POINTS", OFTInteger, 3, 0, 
-                        "POBOX_DELIVERY_POINTS", OFTInteger, 3, 0, 
-                        "MATCHED_ADDRESS_PREMISES", OFTInteger, 3, 0, 
-                        "UNMATCHED_DELIVERY_POINTS", OFTInteger, 3, 0, 
+                        "TOTAL_DELIVERY_POINTS", OFTInteger, 3, 0,
+                        "DELIVERY_POINTS", OFTInteger, 3, 0,
+                        "DOMESTIC_DELIVERY_POINTS", OFTInteger, 3, 0,
+                        "NONDOMESTIC_DELIVERY_POINTS", OFTInteger, 3, 0,
+                        "POBOX_DELIVERY_POINTS", OFTInteger, 3, 0,
+                        "MATCHED_ADDRESS_PREMISES", OFTInteger, 3, 0,
+                        "UNMATCHED_DELIVERY_POINTS", OFTInteger, 3, 0,
                         "RM_VERSION_DATA", OFTString, 8, 0,
                         NULL );
     }
@@ -2423,13 +2427,13 @@ void NTFFileReader::EstablishLayers()
                         "UNIT_POSTCODE", OFTString, 7, 0,
                         "POSITIONAL_QUALITY", OFTInteger, 1, 0,
                         "PO_BOX_INDICATOR", OFTString, 1, 0,
-                        "TOTAL_DELIVERY_POINTS", OFTInteger, 3, 0, 
-                        "DELIVERY_POINTS", OFTInteger, 3, 0, 
-                        "DOMESTIC_DELIVERY_POINTS", OFTInteger, 3, 0, 
-                        "NONDOMESTIC_DELIVERY_POINTS", OFTInteger, 3, 0, 
-                        "POBOX_DELIVERY_POINTS", OFTInteger, 3, 0, 
-                        "MATCHED_ADDRESS_PREMISES", OFTInteger, 3, 0, 
-                        "UNMATCHED_DELIVERY_POINTS", OFTInteger, 3, 0, 
+                        "TOTAL_DELIVERY_POINTS", OFTInteger, 3, 0,
+                        "DELIVERY_POINTS", OFTInteger, 3, 0,
+                        "DOMESTIC_DELIVERY_POINTS", OFTInteger, 3, 0,
+                        "NONDOMESTIC_DELIVERY_POINTS", OFTInteger, 3, 0,
+                        "POBOX_DELIVERY_POINTS", OFTInteger, 3, 0,
+                        "MATCHED_ADDRESS_PREMISES", OFTInteger, 3, 0,
+                        "UNMATCHED_DELIVERY_POINTS", OFTInteger, 3, 0,
                         "RM_VERSION_DATA", OFTString, 8, 0,
                         "NHS_REGIONAL_HEALTH_AUTHORITY", OFTString, 3, 0,
                         "NHS_HEALTH_AUTHORITY", OFTString, 3, 0,
@@ -2441,7 +2445,7 @@ void NTFFileReader::EstablishLayers()
     else // generic case
     {
         CPLAssert( GetProductId() == NPC_UNKNOWN );
-        
+
         poDS->WorkupGeneric( this );
     }
 }
diff --git a/ogr/ogrsf_frmts/ntf/ntf_generic.cpp b/ogr/ogrsf_frmts/ntf/ntf_generic.cpp
index 45d5998..09b866b 100644
--- a/ogr/ogrsf_frmts/ntf/ntf_generic.cpp
+++ b/ogr/ogrsf_frmts/ntf/ntf_generic.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ntf_generic.cpp 27959 2014-11-14 18:29:21Z rouault $
+ * $Id: ntf_generic.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  NTF Translator
  * Purpose:  Handle NTF products that aren't recognised generically.
@@ -31,7 +31,7 @@
 #include "ntf.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ntf_generic.cpp 27959 2014-11-14 18:29:21Z rouault $");
+CPL_CVSID("$Id: ntf_generic.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 #define MAX_LINK        5000
 
@@ -96,7 +96,7 @@ void NTFGenericClass::CheckAddAttr( const char * pszName,
         pszName = "FEAT_CODE";
 
     iAttrOffset = CSLFindString( papszAttrNames, pszName );
-    
+
     if( iAttrOffset == -1 )
     {
         nAttrCount++;
@@ -169,7 +169,7 @@ void OGRNTFDataSource::WorkupGeneric( NTFFileReader * poReader )
 /* ==================================================================== */
 /*      Read all record groups in the file.                             */
 /* ==================================================================== */
-    while( TRUE )
+    while( true )
     {
 /* -------------------------------------------------------------------- */
 /*      Read a record group                                             */
@@ -181,7 +181,7 @@ void OGRNTFDataSource::WorkupGeneric( NTFFileReader * poReader )
 
         if( papoGroup == NULL || papoGroup[0]->GetType() == 99 )
             break;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Get the class corresponding to the anchor record.               */
 /* -------------------------------------------------------------------- */
@@ -189,7 +189,7 @@ void OGRNTFDataSource::WorkupGeneric( NTFFileReader * poReader )
         char           **papszFullAttList = NULL;
 
         poClass->nFeatureCount++;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Loop over constituent records collecting attributes.            */
 /* -------------------------------------------------------------------- */
@@ -215,15 +215,15 @@ void OGRNTFDataSource::WorkupGeneric( NTFFileReader * poReader )
                       {
                           poClass->CheckAddAttr( poAttDesc->val_type,
                                                  poAttDesc->finter,
-                                                 strlen(papszValues[iAtt]) );
+                                                 static_cast<int>(strlen(papszValues[iAtt])) );
                       }
 
-                      if( CSLFindString( papszFullAttList, 
+                      if( CSLFindString( papszFullAttList,
                                          papszTypes[iAtt] ) == -1 )
-                          papszFullAttList = 
-                              CSLAddString( papszFullAttList, 
+                          papszFullAttList =
+                              CSLAddString( papszFullAttList,
                                             papszTypes[iAtt] );
-                      else
+                      else if( poAttDesc != NULL )
                           poClass->SetMultiple( poAttDesc->val_type );
                   }
 
@@ -260,7 +260,7 @@ void OGRNTFDataSource::WorkupGeneric( NTFFileReader * poReader )
                 if( poReader->GetNTFLevel() < 3 )
                 {
                     NTFAttDesc  *poAttDesc;
-                      
+
                     poAttDesc = poReader->GetAttDesc(poRecord->GetField(9,10));
                     if( poAttDesc != NULL )
                         poClass->CheckAddAttr( poAttDesc->val_type,
@@ -270,7 +270,7 @@ void OGRNTFDataSource::WorkupGeneric( NTFFileReader * poReader )
                         poClass->CheckAddAttr( "FEAT_CODE", "A4", 4 );
                 }
                 break;
-                
+
               default:
                 break;
             }
@@ -303,7 +303,7 @@ static void AddGenericAttributes( NTFFileReader * poReader,
     for( int iAtt = 0; papszTypes != NULL && papszTypes[iAtt] != NULL; iAtt++ )
     {
         int             iField;
-        
+
         if( EQUAL(papszTypes[iAtt],"TX") )
             iField = poFeature->GetFieldIndex("TEXT");
         else if( EQUAL(papszTypes[iAtt],"FC") )
@@ -324,7 +324,7 @@ static void AddGenericAttributes( NTFFileReader * poReader,
         char  szListName[128];
         int   iListField;
 
-        sprintf( szListName, "%s_LIST", 
+        snprintf( szListName, sizeof(szListName), "%s_LIST",
                  poFeature->GetFieldDefnRef(iField)->GetNameRef() );
         iListField = poFeature->GetFieldIndex( szListName );
 
@@ -335,16 +335,16 @@ static void AddGenericAttributes( NTFFileReader * poReader,
         if( iListField != -1 )
         {
             char        *pszAttLongName, *pszAttValue, *pszCodeDesc;
-            
+
             poReader->ProcessAttValue( papszTypes[iAtt], papszValues[iAtt],
-                                       &pszAttLongName, &pszAttValue, 
+                                       &pszAttLongName, &pszAttValue,
                                        &pszCodeDesc );
 
             if( poFeature->IsFieldSet( iListField ) )
             {
-                poFeature->SetField( iListField, 
-                    CPLSPrintf( "%s,%s", 
-                                poFeature->GetFieldAsString( iListField ), 
+                poFeature->SetField( iListField,
+                    CPLSPrintf( "%s,%s",
+                                poFeature->GetFieldAsString( iListField ),
                                 pszAttValue ) );
             }
             else
@@ -374,7 +374,7 @@ static OGRFeature *TranslateGenericNode( NTFFileReader *poReader,
     {
         return NULL;
     }
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // NODE_ID
@@ -427,10 +427,10 @@ static OGRFeature *TranslateGenericCollection( NTFFileReader *poReader,
                                                NTFRecord **papoGroup )
 
 {
-    if( CSLCount((char **) papoGroup) < 1 
+    if( CSLCount((char **) papoGroup) < 1
         || papoGroup[0]->GetType() != NRT_COLLECT )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // COLL_ID
@@ -481,11 +481,11 @@ static OGRFeature *TranslateGenericText( NTFFileReader *poReader,
 
 {
     int         iRec;
-    
+
     if( CSLCount((char **) papoGroup) < 2
         || papoGroup[0]->GetType() != NRT_TEXTREC )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // TEXT_ID
@@ -511,7 +511,7 @@ static OGRFeature *TranslateGenericText( NTFFileReader *poReader,
     for( iRec = 0; papoGroup[iRec] != NULL; iRec++ )
     {
         NTFRecord       *poRecord = papoGroup[iRec];
-        
+
         if( poRecord->GetType() == NRT_TEXTREP )
         {
             poFeature->SetField( "FONT", atoi(poRecord->GetField(9,12)) );
@@ -541,11 +541,11 @@ static OGRFeature *TranslateGenericName( NTFFileReader *poReader,
 
 {
     int         iRec;
-    
+
     if( CSLCount((char **) papoGroup) < 2
         || papoGroup[0]->GetType() != NRT_NAMEREC )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // NAME_ID
@@ -579,7 +579,7 @@ static OGRFeature *TranslateGenericName( NTFFileReader *poReader,
     for( iRec = 0; papoGroup[iRec] != NULL; iRec++ )
     {
         NTFRecord       *poRecord = papoGroup[iRec];
-        
+
         if( poRecord->GetType() == NRT_NAMEPOSTN )
         {
             poFeature->SetField( "FONT", atoi(poRecord->GetField(3,6)) );
@@ -615,7 +615,7 @@ static OGRFeature *TranslateGenericPoint( NTFFileReader *poReader,
     {
         return NULL;
     }
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // POINT_ID
@@ -633,7 +633,7 @@ static OGRFeature *TranslateGenericPoint( NTFFileReader *poReader,
     {
         char    szValType[3];
 
-        strcpy( szValType, papoGroup[0]->GetField(9,10) );
+        snprintf( szValType, sizeof(szValType), "%s", papoGroup[0]->GetField(9,10) );
         if( !EQUAL(szValType,"  ") )
         {
             char        *pszProcessedValue;
@@ -667,7 +667,7 @@ static OGRFeature *TranslateGenericLine( NTFFileReader *poReader,
         || (papoGroup[1]->GetType() != NRT_GEOMETRY
             && papoGroup[1]->GetType() != NRT_GEOMETRY3D) )
         return NULL;
-        
+
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // LINE_ID
@@ -685,7 +685,7 @@ static OGRFeature *TranslateGenericLine( NTFFileReader *poReader,
     {
         char    szValType[3];
 
-        strcpy( szValType, papoGroup[0]->GetField(9,10) );
+        snprintf( szValType, sizeof(szValType), "%s", papoGroup[0]->GetField(9,10) );
         if( !EQUAL(szValType,"  ") )
         {
             char        *pszProcessedValue;
@@ -717,7 +717,7 @@ static OGRFeature *TranslateGenericPoly( NTFFileReader *poReader,
 /* ==================================================================== */
 /*      Traditional POLYGON record groups.                              */
 /* ==================================================================== */
-    if( CSLCount((char **) papoGroup) >= 2 
+    if( CSLCount((char **) papoGroup) >= 2
         && papoGroup[0]->GetType() == NRT_POLYGON
         && papoGroup[1]->GetType() == NRT_CHAIN )
     {
@@ -728,14 +728,14 @@ static OGRFeature *TranslateGenericPoly( NTFFileReader *poReader,
 
         // NUM_PARTS
         int             nNumLinks = atoi(papoGroup[1]->GetField( 9, 12 ));
-    
+
         if( nNumLinks > MAX_LINK )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "MAX_LINK exceeded in ntf_generic.cpp." );
             return poFeature;
         }
-    
+
         poFeature->SetField( "NUM_PARTS", nNumLinks );
 
         // DIR
@@ -789,13 +789,13 @@ static OGRFeature *TranslateGenericCPoly( NTFFileReader *poReader,
 /* -------------------------------------------------------------------- */
     if( papoGroup[0]->GetType() != NRT_CPOLY )
         return NULL;
-    
-    if( papoGroup[1] == NULL || 
-        (papoGroup[1]->GetType() != NRT_GEOMETRY 
-         && papoGroup[1]->GetType() != NRT_GEOMETRY3D) ) 
+
+    if( papoGroup[1] == NULL ||
+        (papoGroup[1]->GetType() != NRT_GEOMETRY
+         && papoGroup[1]->GetType() != NRT_GEOMETRY3D) )
         return NULL;
-    
-    if( papoGroup[1] != NULL 
+
+    if( papoGroup[1] != NULL
         && papoGroup[2]->GetType() != NRT_ATTREC )
         return NULL;
 
@@ -806,25 +806,25 @@ static OGRFeature *TranslateGenericCPoly( NTFFileReader *poReader,
 
     // CPOLY_ID
     poFeature->SetField( "CPOLY_ID", atoi(papoGroup[0]->GetField( 3, 8 )) );
-    
+
     // ATTREC Attributes
     AddGenericAttributes( poReader, papoGroup, poFeature );
-    
+
     // Read point geometry
-    if( papoGroup[1] != NULL 
+    if( papoGroup[1] != NULL
         && (papoGroup[1]->GetType() == NRT_GEOMETRY
             || papoGroup[1]->GetType() == NRT_GEOMETRY3D) )
     {
         poFeature->SetGeometryDirectly(
             poReader->ProcessGeometry(papoGroup[1]));
-        poFeature->SetField( "GEOM_ID", 
+        poFeature->SetField( "GEOM_ID",
                              atoi(papoGroup[1]->GetField(3,8)) );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Collect the chains for each of the rings, and just aggregate    */
 /*      these into the master list without any concept of where the     */
-/*      boundaries are.  The boundary information will be emmitted      */
+/*      boundaries are.  The boundary information will be emitted      */
 /*      in the RingStart field.                                         */
 /* -------------------------------------------------------------------- */
     int         nNumLink = 0, iLink;
@@ -854,7 +854,7 @@ void OGRNTFDataSource::EstablishGenericLayers()
 
 {
     int         iType;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Pick an initial NTFFileReader to build the layers against.      */
 /* -------------------------------------------------------------------- */
@@ -862,7 +862,7 @@ void OGRNTFDataSource::EstablishGenericLayers()
     {
         NTFFileReader   *poPReader = NULL;
         int              bHasZ = FALSE;
-        
+
         poPReader = papoNTFFileReader[iFile];
         if( poPReader->GetProductId() != NPC_UNKNOWN )
             continue;
@@ -874,25 +874,25 @@ void OGRNTFDataSource::EstablishGenericLayers()
         for( iType = 0; iType < 99; iType++ )
         {
             NTFGenericClass     *poClass = aoGenericClass + iType;
-        
+
             if( poClass->nFeatureCount > 0 && poClass->b3D )
                 bHasZ = TRUE;
         }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Create layers for all recognised layer types with features.     */
 /* -------------------------------------------------------------------- */
         for( iType = 0; iType < 99; iType++ )
         {
             NTFGenericClass     *poClass = aoGenericClass + iType;
-        
+
             if( poClass->nFeatureCount == 0 )
                 continue;
 
             if( iType == NRT_POINTREC )
             {
                 poPReader->
-                    EstablishLayer( "GENERIC_POINT", 
+                    EstablishLayer( "GENERIC_POINT",
                                     OGR_GT_SetModifier(wkbPoint, bHasZ, FALSE),
                                     TranslateGenericPoint,
                                     NRT_POINTREC, poClass,
@@ -902,7 +902,7 @@ void OGRNTFDataSource::EstablishGenericLayers()
             else if( iType == NRT_LINEREC )
             {
                 poPReader->
-                    EstablishLayer( "GENERIC_LINE", 
+                    EstablishLayer( "GENERIC_LINE",
                                     OGR_GT_SetModifier(wkbLineString, bHasZ, FALSE),
                                     TranslateGenericLine,
                                     NRT_LINEREC, poClass,
@@ -912,7 +912,7 @@ void OGRNTFDataSource::EstablishGenericLayers()
             else if( iType == NRT_TEXTREC )
             {
                 poPReader->
-                    EstablishLayer( "GENERIC_TEXT", 
+                    EstablishLayer( "GENERIC_TEXT",
                                     OGR_GT_SetModifier(wkbPoint, bHasZ, FALSE),
                                     TranslateGenericText,
                                     NRT_TEXTREC, poClass,
@@ -922,7 +922,7 @@ void OGRNTFDataSource::EstablishGenericLayers()
             else if( iType == NRT_NAMEREC )
             {
                 poPReader->
-                    EstablishLayer( "GENERIC_NAME", 
+                    EstablishLayer( "GENERIC_NAME",
                                     OGR_GT_SetModifier(wkbPoint, bHasZ, FALSE),
                                     TranslateGenericName,
                                     NRT_NAMEREC, poClass,
@@ -957,12 +957,12 @@ void OGRNTFDataSource::EstablishGenericLayers()
             else if( iType == NRT_POLYGON )
             {
                 poPReader->
-                    EstablishLayer( "GENERIC_POLY", 
+                    EstablishLayer( "GENERIC_POLY",
                                     OGR_GT_SetModifier(wkbPoint, bHasZ, FALSE),
                                     TranslateGenericPoly,
                                     NRT_POLYGON, poClass,
                                     "POLY_ID", OFTInteger, 6, 0,
-                                    "NUM_PARTS", OFTInteger, 4, 0, 
+                                    "NUM_PARTS", OFTInteger, 4, 0,
                                     "DIR", OFTIntegerList, 1, 0,
                                     "GEOM_ID_OF_LINK", OFTIntegerList, 6, 0,
                                     "RingStart", OFTIntegerList, 6, 0,
@@ -971,16 +971,15 @@ void OGRNTFDataSource::EstablishGenericLayers()
             else if( iType == NRT_CPOLY )
             {
                 poPReader->
-                    EstablishLayer( "GENERIC_CPOLY", 
+                    EstablishLayer( "GENERIC_CPOLY",
                                     OGR_GT_SetModifier(wkbPoint, bHasZ, FALSE),
                                     TranslateGenericCPoly,
                                     NRT_CPOLY, poClass,
                                     "CPOLY_ID", OFTInteger, 6, 0,
-                                    "NUM_PARTS", OFTInteger, 4, 0, 
+                                    "NUM_PARTS", OFTInteger, 4, 0,
                                     "POLY_ID", OFTIntegerList, 1, 0,
                                     NULL );
             }
         }
     }
 }
-
diff --git a/ogr/ogrsf_frmts/ntf/ntf_raster.cpp b/ogr/ogrsf_frmts/ntf/ntf_raster.cpp
index f77ea94..2952639 100644
--- a/ogr/ogrsf_frmts/ntf/ntf_raster.cpp
+++ b/ogr/ogrsf_frmts/ntf/ntf_raster.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ntf_raster.cpp 28382 2015-01-30 15:29:41Z rouault $
+ * $Id: ntf_raster.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  NTF Translator
  * Purpose:  Handle UK Ordnance Survey Raster DTM products.  Includes some
@@ -31,7 +31,7 @@
 
 #include "ntf.h"
 
-CPL_CVSID("$Id: ntf_raster.cpp 28382 2015-01-30 15:29:41Z rouault $");
+CPL_CVSID("$Id: ntf_raster.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -69,7 +69,8 @@ void NTFFileReader::EstablishRasterAccess()
         delete poRecord;
     }
 
-    if( poRecord->GetType() != NRT_GRIDHREC )
+    if( poRecord == NULL ||
+        poRecord->GetType() != NRT_GRIDHREC )
     {
         delete poRecord;
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -94,7 +95,7 @@ void NTFFileReader::EstablishRasterAccess()
         adfGeoTransform[3] = atoi(poRecord->GetField(35,44));
         adfGeoTransform[4] = 0;
         adfGeoTransform[5] = 50;
-        
+
         nRasterDataType = 3; /* GDT_Int16 */
     }
 
@@ -116,7 +117,7 @@ void NTFFileReader::EstablishRasterAccess()
                            + GetYOrigin();
         adfGeoTransform[4] = 0;
         adfGeoTransform[5] = atoi(poRecord->GetField(43,46));
-        
+
         nRasterDataType = 3; /* GDT_Int16 */
     }
 
@@ -153,13 +154,13 @@ CPLErr NTFFileReader::ReadRasterColumn( int iColumn, float *pafElev )
     if( panColumnOffset[iColumn] == 0 )
     {
         int     iPrev;
-        
+
         for( iPrev = 0; iPrev < iColumn-1; iPrev++ )
         {
             if( panColumnOffset[iPrev+1] == 0 )
             {
                 CPLErr  eErr;
-                
+
                 eErr = ReadRasterColumn( iPrev, NULL );
                 if( eErr != CE_None )
                     return eErr;
@@ -172,12 +173,12 @@ CPLErr NTFFileReader::ReadRasterColumn( int iColumn, float *pafElev )
 /* -------------------------------------------------------------------- */
     if( GetFP() == NULL )
         Open();
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read requested record.                                          */
 /* -------------------------------------------------------------------- */
     NTFRecord   *poRecord;
-    
+
     SetFPPos( panColumnOffset[iColumn], iColumn );
     poRecord = ReadRecord();
 
@@ -185,7 +186,7 @@ CPLErr NTFFileReader::ReadRasterColumn( int iColumn, float *pafElev )
     {
         GetFPPos( panColumnOffset+iColumn+1, NULL );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Handle LANDRANGER DTM columns.                                  */
 /* -------------------------------------------------------------------- */
@@ -202,7 +203,7 @@ CPLErr NTFFileReader::ReadRasterColumn( int iColumn, float *pafElev )
                 atoi(poRecord->GetField(84+iPixel*4,87+iPixel*4)));
         }
     }
-            
+
 /* -------------------------------------------------------------------- */
 /*      Handle PROFILE                                                  */
 /* -------------------------------------------------------------------- */
@@ -210,11 +211,11 @@ CPLErr NTFFileReader::ReadRasterColumn( int iColumn, float *pafElev )
     {
         for( int iPixel = 0; iPixel < nRasterXSize; iPixel++ )
         {
-            pafElev[iPixel] = (float) 
+            pafElev[iPixel] = (float)
            (atoi(poRecord->GetField(19+iPixel*5,23+iPixel*5)) * GetZMult());
         }
     }
-    
+
     delete poRecord;
 
     return CE_None;
@@ -236,7 +237,7 @@ OGRNTFRasterLayer::OGRNTFRasterLayer( OGRNTFDataSource *poDSIn,
 {
     char        szLayerName[128];
 
-    sprintf( szLayerName, "DTM_%s", poReaderIn->GetTileName() );
+    snprintf( szLayerName, sizeof(szLayerName), "DTM_%s", poReaderIn->GetTileName() );
     poFeatureDefn = new OGRFeatureDefn( szLayerName );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbPoint25D );
@@ -262,7 +263,7 @@ OGRNTFRasterLayer::OGRNTFRasterLayer( OGRNTFDataSource *poDSIn,
         nDEMSample = 1;
     else
         nDEMSample = MAX(1,atoi(poDS->GetOption("DEM_SAMPLE")));
-    
+
     nFeatureCount = (poReader->GetRasterXSize() / nDEMSample)
                   * (poReader->GetRasterYSize() / nDEMSample);
 }
@@ -321,7 +322,7 @@ OGRFeature *OGRNTFRasterLayer::GetNextFeature()
     else
     {
         int     iReqColumn, iReqRow;
-        
+
         iReqColumn = (iCurrentFC - 1) / poReader->GetRasterYSize();
         iReqRow = iCurrentFC - iReqColumn * poReader->GetRasterXSize() - 1;
 
@@ -350,12 +351,12 @@ OGRFeature *OGRNTFRasterLayer::GetFeature( GIntBig nFeatureId )
 
 {
     int         iReqColumn, iReqRow;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Is this in the range of legal feature ids (pixels)?             */
 /* -------------------------------------------------------------------- */
     if( nFeatureId < 1
-        || nFeatureId > poReader->GetRasterXSize()*poReader->GetRasterYSize() )
+        || nFeatureId > static_cast<GIntBig>(poReader->GetRasterXSize())*poReader->GetRasterYSize() )
     {
         return NULL;
     }
@@ -365,14 +366,14 @@ OGRFeature *OGRNTFRasterLayer::GetFeature( GIntBig nFeatureId )
 /* -------------------------------------------------------------------- */
     iReqColumn = ((int)nFeatureId - 1) / poReader->GetRasterYSize();
     iReqRow = (int)nFeatureId - iReqColumn * poReader->GetRasterXSize() - 1;
-    
+
     if( iReqColumn != iColumnOffset )
     {
         iColumnOffset = iReqColumn;
         if( poReader->ReadRasterColumn( iReqColumn, pafColumn ) != CE_None )
             return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding feature.                                 */
 /* -------------------------------------------------------------------- */
@@ -388,7 +389,7 @@ OGRFeature *OGRNTFRasterLayer::GetFeature( GIntBig nFeatureId )
                       padfGeoTransform[3] + padfGeoTransform[5] * iReqRow,
                       pafColumn[iReqRow] ) );
     poFeature->SetField( 0, pafColumn[iReqRow] );
-    
+
     return poFeature;
 }
 
@@ -416,7 +417,7 @@ int OGRNTFRasterLayer::TestCapability( const char * pszCap )
     if( EQUAL(pszCap,OLCRandomRead) )
         return TRUE;
 
-    else if( EQUAL(pszCap,OLCSequentialWrite) 
+    else if( EQUAL(pszCap,OLCSequentialWrite)
              || EQUAL(pszCap,OLCRandomWrite) )
         return FALSE;
 
@@ -426,6 +427,6 @@ int OGRNTFRasterLayer::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCFastSpatialFilter) )
         return FALSE;
 
-    else 
+    else
         return FALSE;
 }
diff --git a/ogr/ogrsf_frmts/ntf/ntfdump.cpp b/ogr/ogrsf_frmts/ntf/ntfdump.cpp
index 0fa9335..1fad9c5 100644
--- a/ogr/ogrsf_frmts/ntf/ntfdump.cpp
+++ b/ogr/ogrsf_frmts/ntf/ntfdump.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: ntfdump.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: ntfdump.cpp 32177 2015-12-14 07:25:30Z goatbar $
  *
  * Project:  NTF Translator
- * Purpose:  Simple test harnass.
+ * Purpose:  Simple test harness.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -31,7 +31,7 @@
 #include "cpl_vsi.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ntfdump.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: ntfdump.cpp 32177 2015-12-14 07:25:30Z goatbar $");
 
 static void NTFDump( const char * pszFile, char **papszOptions );
 static void NTFCount( const char * pszFile );
@@ -45,10 +45,10 @@ int main( int argc, char ** argv )
 {
     const char  *pszMode = "-d";
     char        **papszOptions = NULL;
-    
+
     if( argc == 1 )
         printf( "Usage: ntfdump [-s n] [-g] [-d] [-c] [-codelist] files\n" );
-    
+
     for( int i = 1; i < argc; i++ )
     {
         if( EQUAL(argv[i],"-g") )
@@ -92,7 +92,7 @@ static void NTFCount( const char * pszFile )
     fp = VSIFOpen( pszFile, "r" );
     if( fp == NULL )
         return;
-    
+
     do {
         if( poRecord != NULL )
             delete poRecord;
@@ -123,7 +123,7 @@ static void NTFDump( const char * pszFile, char **papszOptions )
     OGRNTFDataSource   oDS;
 
     oDS.SetOptionList( papszOptions );
-    
+
     if( !oDS.Open( pszFile ) )
         return;
 
diff --git a/ogr/ogrsf_frmts/ntf/ntffilereader.cpp b/ogr/ogrsf_frmts/ntf/ntffilereader.cpp
index f9fbce0..f58a689 100644
--- a/ogr/ogrsf_frmts/ntf/ntffilereader.cpp
+++ b/ogr/ogrsf_frmts/ntf/ntffilereader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ntffilereader.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: ntffilereader.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  NTF Translator
  * Purpose:  NTFFileReader class implementation.
@@ -34,86 +34,68 @@
 #include "cpl_string.h"
 #include "ogr_api.h"
 
-CPL_CVSID("$Id: ntffilereader.cpp 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: ntffilereader.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 static int DefaultNTFRecordGrouper( NTFFileReader *, NTFRecord **,
                                     NTFRecord * );
 
-#ifndef PI
-#  define PI 3.14159265358979323846
-#endif
-
 /************************************************************************/
 /*                            NTFFileReader                             */
 /************************************************************************/
 
-NTFFileReader::NTFFileReader( OGRNTFDataSource * poDataSource )
-
+NTFFileReader::NTFFileReader( OGRNTFDataSource * poDataSource ) :
+    pszFilename(NULL),
+    poDS(poDataSource),
+    fp(NULL),
+    nFCCount(0),
+    papszFCNum(NULL),
+    papszFCName(NULL),
+    nAttCount(0),
+    pasAttDesc(NULL),
+    pszTileName(NULL),
+    nCoordWidth(6),
+    nZWidth(6),
+    nNTFLevel(0),
+    dfXYMult(1.0),
+    dfZMult(1.0),
+    dfXOrigin(0),
+    dfYOrigin(0),
+    dfTileXSize(0),
+    dfTileYSize(0),
+    dfScale(0.0),
+    dfPaperToGround(0.0),
+    nStartPos(0),
+    nPreSavedPos(0),
+    nPostSavedPos(0),
+    poSavedRecord(NULL),
+    nSavedFeatureId(1),
+    nBaseFeatureId(1),
+    nFeatureCount(-1),
+    pszProduct(NULL),
+    pszPVName(NULL),
+    nProduct(NPC_UNKNOWN),
+    pfnRecordGrouper(DefaultNTFRecordGrouper),
+    bIndexBuilt(FALSE),
+    bIndexNeeded(FALSE),
+    nRasterXSize(1),
+    nRasterYSize(1),
+    nRasterDataType(1),
+    poRasterLayer(NULL),
+    panColumnOffset(NULL),
+    bCacheLines(TRUE),
+    nLineCacheSize(0),
+    papoLineCache(NULL)
 {
-    fp = NULL;
-
-    nFCCount = 0;
-    papszFCNum = NULL;
-    papszFCName = NULL;
-
-    nPreSavedPos = nPostSavedPos = 0;
-    nSavedFeatureId = nBaseFeatureId = 1;
-    nFeatureCount = -1;
-    poSavedRecord = NULL;
-
-    nAttCount = 0;
-    pasAttDesc = NULL;
-
-    pszTileName = NULL;
-    pszProduct = NULL;
-    pszPVName = NULL;
-    pszFilename = NULL;
-
     apoCGroup[0] = NULL;
-
-    poDS = poDataSource;
-
     memset( apoTypeTranslation, 0, sizeof(apoTypeTranslation) );
-
-    nProduct = NPC_UNKNOWN;
-
-    pfnRecordGrouper = DefaultNTFRecordGrouper;
-
-    dfXYMult = 1.0;
-    dfZMult = 1.0;
-    dfXOrigin = 0;
-    dfYOrigin = 0;
-    nNTFLevel = 0;
-    dfTileXSize = 0;
-    dfTileYSize = 0;
-
-    dfScale = 0.0;
-    dfPaperToGround = 0.0;
-
-    nCoordWidth = 6;
-    nZWidth = 6;
-
     for( int i = 0; i < 100; i++ )
     {
         anIndexSize[i] = 0;
         apapoRecordIndex[i] = NULL;
     }
-
-    panColumnOffset = NULL;
-    poRasterLayer = NULL;
-    nRasterXSize = nRasterYSize = nRasterDataType = 1;
-
-    bIndexBuilt = FALSE;
-    bIndexNeeded = FALSE;
-
     if( poDS->GetOption("CACHE_LINES") != NULL
         && EQUAL(poDS->GetOption("CACHE_LINES"),"OFF") )
         bCacheLines = FALSE;
-    else
-        bCacheLines = TRUE;
-
-    nLineCacheSize = 0;
-    papoLineCache = NULL;
 }
 
 /************************************************************************/
@@ -157,9 +139,9 @@ void NTFFileReader::ClearDefs()
     int         i;
 
     Close();
-    
+
     ClearCGroup();
-    
+
     CSLDestroy( papszFCNum );
     papszFCNum = NULL;
     CSLDestroy( papszFCName );
@@ -175,13 +157,13 @@ void NTFFileReader::ClearDefs()
     CPLFree( pasAttDesc );
     nAttCount = 0;
     pasAttDesc = NULL;
-    
+
     CPLFree( pszProduct );
     pszProduct = NULL;
 
     CPLFree( pszPVName );
     pszPVName = NULL;
-    
+
     CPLFree( pszTileName );
     pszTileName = NULL;
 }
@@ -221,20 +203,20 @@ int NTFFileReader::Open( const char * pszFilenameIn )
     if( pszFilenameIn != NULL )
     {
         ClearDefs();
-    
+
         CPLFree( pszFilename );
         pszFilename = CPLStrdup( pszFilenameIn );
     }
     else
         Close();
-    
+
 /* -------------------------------------------------------------------- */
 /*      Open the file.                                                  */
 /* -------------------------------------------------------------------- */
     fp = VSIFOpen( pszFilename, "rb" );
 
     // notdef: we should likely issue a proper CPL error message based
-    // based on errno here. 
+    // based on errno here.
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
@@ -251,7 +233,7 @@ int NTFFileReader::Open( const char * pszFilenameIn )
     {
         NTFRecord      *poRecord;
 
-        for( poRecord = new NTFRecord( fp ); 
+        for( poRecord = new NTFRecord( fp );
              poRecord->GetType() != NRT_VTR && poRecord->GetType() != NRT_SHR;
              poRecord = new NTFRecord( fp ) )
         {
@@ -270,7 +252,7 @@ int NTFFileReader::Open( const char * pszFilenameIn )
 
     if( oVHR.GetType() != NRT_VHR )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "File `%s' appears to not be a UK NTF file.\n",
                   pszFilename );
         return FALSE;
@@ -279,7 +261,7 @@ int NTFFileReader::Open( const char * pszFilenameIn )
     nNTFLevel = atoi(oVHR.GetField( 57, 57 ));
     if( !( nNTFLevel >= 1 && nNTFLevel <= 5 ) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Invalid value : nNTFLevel = %d", nNTFLevel );
         return FALSE;
     }
@@ -289,7 +271,7 @@ int NTFFileReader::Open( const char * pszFilenameIn )
 /* -------------------------------------------------------------------- */
     NTFRecord      *poRecord;
 
-    for( poRecord = new NTFRecord( fp ); 
+    for( poRecord = new NTFRecord( fp );
          poRecord->GetType() != NRT_VTR && poRecord->GetType() != NRT_SHR;
          poRecord = new NTFRecord( fp ) )
     {
@@ -300,44 +282,43 @@ int NTFFileReader::Open( const char * pszFilenameIn )
         {
             const char      *pszData;
             int             iChar;
-            char            szFCName[100];
 
             nFCCount++;
 
             papszFCNum = CSLAddString( papszFCNum, poRecord->GetField(3,6) );
 
-            szFCName[0] = '\0';
+            CPLString osFCName;
             pszData = poRecord->GetData();
-            
+
             // CODE_COM
             for( iChar = 15; pszData[iChar] == ' ' && iChar > 5; iChar-- ) {}
 
             if( iChar > 6 )
-                strcat( szFCName, poRecord->GetField(7,iChar+1) );
+                osFCName += poRecord->GetField(7,iChar+1);
 
             // STCLASS
             for( iChar = 35; pszData[iChar] == ' ' && iChar > 15; iChar-- ) {}
 
             if( iChar > 15 )
             {
-                if( strlen(szFCName) > 0 )
-                    strcat( szFCName, " : " );
-                strcat( szFCName, poRecord->GetField(17,iChar+1) );
+                if( osFCName.size() )
+                    osFCName += " : " ;
+                osFCName += poRecord->GetField(17,iChar+1);
             }
 
             // FEATDES
-            for( iChar = 36; 
+            for( iChar = 36;
                  pszData[iChar] != '\0' && pszData[iChar] != '\\';
                  iChar++ ) {}
 
             if( iChar > 37 )
             {
-                if( strlen(szFCName) > 0 )
-                    strcat( szFCName, " : " );
-                strcat( szFCName, poRecord->GetField(37,iChar) );
+                if( osFCName.size() )
+                    osFCName += " : " ;
+                osFCName += poRecord->GetField(37,iChar);
             }
 
-            papszFCName = CSLAddString(papszFCName, szFCName );
+            papszFCName = CSLAddString(papszFCName, osFCName );
         }
 
 /* -------------------------------------------------------------------- */
@@ -347,7 +328,7 @@ int NTFFileReader::Open( const char * pszFilenameIn )
         {
             nAttCount++;
 
-            pasAttDesc = (NTFAttDesc *) 
+            pasAttDesc = (NTFAttDesc *)
                 CPLRealloc( pasAttDesc, sizeof(NTFAttDesc) * nAttCount );
 
             ProcessAttDesc( poRecord, pasAttDesc + nAttCount - 1 );
@@ -365,7 +346,7 @@ int NTFFileReader::Open( const char * pszFilenameIn )
             psAttDesc = GetAttDesc( poCodeList->szValType );
             if( psAttDesc == NULL )
             {
-                CPLDebug( "NTF", "Got CODELIST for %s without ATTDESC.", 
+                CPLDebug( "NTF", "Got CODELIST for %s without ATTDESC.",
                           poCodeList->szValType );
                 delete poCodeList;
             }
@@ -382,12 +363,12 @@ int NTFFileReader::Open( const char * pszFilenameIn )
         {
             int         iChar;
             pszProduct = CPLStrdup(poRecord->GetField(3,22));
-            for( iChar = strlen(pszProduct)-1;
+            for( iChar = static_cast<int>(strlen(pszProduct))-1;
                  iChar > 0 && pszProduct[iChar] == ' ';
                  pszProduct[iChar--] = '\0' ) {}
 
             pszPVName = CPLStrdup(poRecord->GetField(76+3,76+22));
-            for( iChar = strlen(pszPVName)-1;
+            for( iChar = static_cast<int>(strlen(pszPVName))-1;
                  iChar > 0 && pszPVName[iChar] == ' ';
                  pszPVName[iChar--] = '\0' ) {}
 
@@ -404,7 +385,7 @@ int NTFFileReader::Open( const char * pszFilenameIn )
     {
         delete poRecord;
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Cound not find section header record in %s.\n", 
+                  "Cound not find section header record in %s.\n",
                   pszFilename );
         return FALSE;
     }
@@ -413,7 +394,7 @@ int NTFFileReader::Open( const char * pszFilenameIn )
     {
         delete poRecord;
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Cound not find product type in %s.\n", 
+                  "Cound not find product type in %s.\n",
                   pszFilename );
         return FALSE;
     }
@@ -421,50 +402,50 @@ int NTFFileReader::Open( const char * pszFilenameIn )
 /* -------------------------------------------------------------------- */
 /*      Classify the product type.                                      */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszProduct,"LAND-LINE",9) && CPLAtof(pszPVName+5) < 1.3 )
+    if( STARTS_WITH_CI(pszProduct, "LAND-LINE") && CPLAtof(pszPVName+5) < 1.3 )
         nProduct = NPC_LANDLINE;
-    else if( EQUALN(pszProduct,"LAND-LINE",9) )
+    else if( STARTS_WITH_CI(pszProduct, "LAND-LINE") )
         nProduct = NPC_LANDLINE99;
     else if( EQUAL(pszProduct,"OS_LANDRANGER_CONT") ) // Panorama
         nProduct = NPC_LANDRANGER_CONT;
     else if( EQUAL(pszProduct,"L-F_PROFILE_CON") ) // Panorama
         nProduct = NPC_LANDFORM_PROFILE_CONT;
-    else if( EQUALN(pszProduct,"Strategi",8) )
+    else if( STARTS_WITH_CI(pszProduct, "Strategi") )
         nProduct = NPC_STRATEGI;
-    else if( EQUALN(pszProduct,"Meridian_02",11) )
+    else if( STARTS_WITH_CI(pszProduct, "Meridian_02") )
         nProduct = NPC_MERIDIAN2;
-    else if( EQUALN(pszProduct,"Meridian_01",11) )
+    else if( STARTS_WITH_CI(pszProduct, "Meridian_01") )
         nProduct = NPC_MERIDIAN;
-    else if( EQUAL(pszProduct,NTF_BOUNDARYLINE) 
-             && EQUALN(pszPVName,"A10N_FC",7) )
+    else if( EQUAL(pszProduct,NTF_BOUNDARYLINE)
+             && STARTS_WITH_CI(pszPVName, "A10N_FC") )
         nProduct = NPC_BOUNDARYLINE;
-    else if( EQUAL(pszProduct,NTF_BOUNDARYLINE) 
-             && EQUALN(pszPVName,"A20N_FC",7) )
+    else if( EQUAL(pszProduct,NTF_BOUNDARYLINE)
+             && STARTS_WITH_CI(pszPVName, "A20N_FC") )
         nProduct = NPC_BL2000;
-    else if( EQUALN(pszProduct,"BaseData.GB",11) )
+    else if( STARTS_WITH_CI(pszProduct, "BaseData.GB") )
         nProduct = NPC_BASEDATA;
-    else if( EQUALN(pszProduct,"OSCAR_ASSET",11) )
+    else if( STARTS_WITH_CI(pszProduct, "OSCAR_ASSET") )
         nProduct = NPC_OSCAR_ASSET;
-    else if( EQUALN(pszProduct,"OSCAR_TRAFF",11) )
+    else if( STARTS_WITH_CI(pszProduct, "OSCAR_TRAFF") )
         nProduct = NPC_OSCAR_TRAFFIC;
-    else if( EQUALN(pszProduct,"OSCAR_ROUTE",11) )
+    else if( STARTS_WITH_CI(pszProduct, "OSCAR_ROUTE") )
         nProduct = NPC_OSCAR_ROUTE;
-    else if( EQUALN(pszProduct,"OSCAR_NETWO",11) )
+    else if( STARTS_WITH_CI(pszProduct, "OSCAR_NETWO") )
         nProduct = NPC_OSCAR_NETWORK;
-    else if( EQUALN(pszProduct,"ADDRESS_POI",11) )
+    else if( STARTS_WITH_CI(pszProduct, "ADDRESS_POI") )
         nProduct = NPC_ADDRESS_POINT;
-    else if( EQUALN(pszProduct,"CODE_POINT",10) )
+    else if( STARTS_WITH_CI(pszProduct, "CODE_POINT") )
     {
         if( GetAttDesc( "RH" ) == NULL )
             nProduct = NPC_CODE_POINT;
         else
             nProduct = NPC_CODE_POINT_PLUS;
     }
-    else if( EQUALN(pszProduct,"OS_LANDRANGER_DTM",17) )
+    else if( STARTS_WITH_CI(pszProduct, "OS_LANDRANGER_DTM") )
         nProduct = NPC_LANDRANGER_DTM;
-    else if( EQUALN(pszProduct,"L-F_PROFILE_DTM",15) )
+    else if( STARTS_WITH_CI(pszProduct, "L-F_PROFILE_DTM") )
         nProduct = NPC_LANDFORM_PROFILE_DTM;
-    else if( EQUALN(pszProduct,"NEXTMap Britain DTM",19) )
+    else if( STARTS_WITH_CI(pszProduct, "NEXTMap Britain DTM") )
         nProduct = NPC_LANDFORM_PROFILE_DTM; // Treat as landform
 
     if( poDS->GetOption("FORCE_GENERIC") != NULL
@@ -474,13 +455,13 @@ int NTFFileReader::Open( const char * pszFilenameIn )
     // No point in caching lines if there are no polygons.
     if( nProduct != NPC_BOUNDARYLINE && nProduct != NPC_BL2000 )
         bCacheLines = FALSE;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Handle the section header record.                               */
 /* -------------------------------------------------------------------- */
     nSavedFeatureId = nBaseFeatureId;
     nStartPos = VSIFTell(fp);
-    
+
     pszTileName = CPLStrdup(poRecord->GetField(3,12));        // SECT_REF
     while( pszTileName[strlen(pszTileName)-1] == ' ' )
         pszTileName[strlen(pszTileName)-1] = '\0';
@@ -488,11 +469,11 @@ int NTFFileReader::Open( const char * pszFilenameIn )
     nCoordWidth = atoi(poRecord->GetField(15,19));            // XYLEN
     if( nCoordWidth == 0 )
         nCoordWidth = 10;
-    
+
     nZWidth = atoi(poRecord->GetField(31,35));                // ZLEN
     if( nZWidth == 0 )
         nZWidth = 10;
-    
+
     dfXYMult = atoi(poRecord->GetField(21,30)) / 1000.0;      // XY_MULT
     dfXOrigin = atoi(poRecord->GetField(47,56));
     dfYOrigin = atoi(poRecord->GetField(57,66));
@@ -541,7 +522,7 @@ int NTFFileReader::Open( const char * pszFilenameIn )
         EstablishLayers();
     else
         EstablishRasterAccess();
-    
+
     return CPLGetLastErrorType() != CE_Failure;
 }
 
@@ -558,7 +539,7 @@ void NTFFileReader::DumpReadable( FILE *fpLog )
     fprintf( fpLog, "XYLEN = %d\n", nCoordWidth );
     fprintf( fpLog, "XY_MULT = %g\n", dfXYMult );
     fprintf( fpLog, "X_ORIG = %g\n", dfXOrigin );
-    fprintf( fpLog, "Y_ORIG = %g\n", dfYOrigin ); 
+    fprintf( fpLog, "Y_ORIG = %g\n", dfYOrigin );
     fprintf( fpLog, "XMAX = %g\n", dfTileXSize );
     fprintf( fpLog, "YMAX = %g\n", dfTileYSize );
 }
@@ -594,15 +575,15 @@ OGRGeometry *NTFFileReader::ProcessGeometry( NTFRecord * poRecord,
     if( nGType == 1 )
     {
         double      dfX, dfY;
-        
-        dfX = atoi(poRecord->GetField(14,14+GetXYLen()-1)) * GetXYMult() 
+
+        dfX = atoi(poRecord->GetField(14,14+GetXYLen()-1)) * GetXYMult()
             + GetXOrigin();
         dfY = atoi(poRecord->GetField(14+GetXYLen(),14+GetXYLen()*2-1))
             * GetXYMult() + GetYOrigin();
-      
+
         poGeometry = new OGRPoint( dfX, dfY );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Line (or arc)                                                   */
 /* -------------------------------------------------------------------- */
@@ -619,10 +600,10 @@ OGRGeometry *NTFFileReader::ProcessGeometry( NTFRecord * poRecord,
             int            iStart = 14 + iCoord * (GetXYLen()*2+1);
 
             dfX = atoi(poRecord->GetField(iStart+0,
-                                          iStart+GetXYLen()-1)) 
+                                          iStart+GetXYLen()-1))
                 * GetXYMult() + GetXOrigin();
             dfY = atoi(poRecord->GetField(iStart+GetXYLen(),
-                                          iStart+GetXYLen()*2-1)) 
+                                          iStart+GetXYLen()*2-1))
                 * GetXYMult() + GetYOrigin();
 
             if( iCoord == 0 )
@@ -656,14 +637,14 @@ OGRGeometry *NTFFileReader::ProcessGeometry( NTFRecord * poRecord,
             int            iStart = 14 + iCoord * (GetXYLen()*2+1);
 
             adfX[iCoord] = atoi(poRecord->GetField(iStart+0,
-                                                  iStart+GetXYLen()-1)) 
+                                                  iStart+GetXYLen()-1))
                 * GetXYMult() + GetXOrigin();
             adfY[iCoord] = atoi(poRecord->GetField(iStart+GetXYLen(),
-                                                  iStart+GetXYLen()*2-1)) 
+                                                  iStart+GetXYLen()*2-1))
                 * GetXYMult() + GetYOrigin();
         }
 
-        poGeometry = NTFStrokeArcToOGRGeometry_Points( adfX[0], adfY[0], 
+        poGeometry = NTFStrokeArcToOGRGeometry_Points( adfX[0], adfY[0],
                                                        adfX[1], adfY[1],
                                                        adfX[2], adfY[2], 72 );
     }
@@ -683,7 +664,7 @@ OGRGeometry *NTFFileReader::ProcessGeometry( NTFRecord * poRecord,
         dfCenterY = atoi(poRecord->GetField(iCenterStart+GetXYLen(),
                                             iCenterStart+GetXYLen()*2-1))
             * GetXYMult() + GetYOrigin();
-        
+
         dfArcX = atoi(poRecord->GetField(iArcStart,
                                          iArcStart+GetXYLen()-1))
             * GetXYMult() + GetXOrigin();
@@ -695,8 +676,8 @@ OGRGeometry *NTFFileReader::ProcessGeometry( NTFRecord * poRecord,
                          + (dfCenterY - dfArcY) * (dfCenterY - dfArcY) );
 
         poGeometry = NTFStrokeArcToOGRGeometry_Angles( dfCenterX, dfCenterY,
-                                                       dfRadius, 
-                                                       0.0, 360.0, 
+                                                       dfRadius,
+                                                       0.0, 360.0,
                                                        72 );
     }
 
@@ -734,18 +715,18 @@ OGRGeometry *NTFFileReader::ProcessGeometry3D( NTFRecord * poRecord,
     if( nGType == 1 )
     {
         double      dfX, dfY, dfZ;
-        
-        dfX = atoi(poRecord->GetField(14,14+GetXYLen()-1)) * GetXYMult() 
+
+        dfX = atoi(poRecord->GetField(14,14+GetXYLen()-1)) * GetXYMult()
             + GetXOrigin();
         dfY = atoi(poRecord->GetField(14+GetXYLen(),14+GetXYLen()*2-1))
             * GetXYMult() + GetYOrigin();
         dfZ = atoi(poRecord->GetField(14+1+2*GetXYLen(),
                                       14+1+2*GetXYLen()+nZWidth-1)) * dfZMult;
 
-      
+
         poGeometry = new OGRPoint( dfX, dfY, dfZ );
     }
-    
+
     else if( nGType == 2 )
     {
         OGRLineString      *poLine = new OGRLineString;
@@ -759,10 +740,10 @@ OGRGeometry *NTFFileReader::ProcessGeometry3D( NTFRecord * poRecord,
             int            iStart = 14 + iCoord * (GetXYLen()*2+nZWidth+2);
 
             dfX = atoi(poRecord->GetField(iStart+0,
-                                          iStart+GetXYLen()-1)) 
+                                          iStart+GetXYLen()-1))
                 * GetXYMult() + GetXOrigin();
             dfY = atoi(poRecord->GetField(iStart+GetXYLen(),
-                                          iStart+GetXYLen()*2-1)) 
+                                          iStart+GetXYLen()*2-1))
                 * GetXYMult() + GetYOrigin();
 
             dfZ = atoi(poRecord->GetField(iStart+1+2*GetXYLen(),
@@ -789,7 +770,7 @@ OGRGeometry *NTFFileReader::ProcessGeometry3D( NTFRecord * poRecord,
 
     if( poGeometry != NULL )
         poGeometry->assignSpatialReference( poDS->GetSpatialRef() );
-    
+
     return poGeometry;
 }
 
@@ -807,16 +788,16 @@ int NTFFileReader::ProcessAttDesc( NTFRecord * poRecord, NTFAttDesc* psAD )
         return FALSE;
 
     psAD->poCodeList = NULL;
-    strcpy( psAD->val_type, poRecord->GetField( 3, 4 ));
-    strcpy( psAD->fwidth, poRecord->GetField( 5, 7 ));
-    strcpy( psAD->finter, poRecord->GetField( 8, 12 ));
-    
+    snprintf( psAD->val_type, sizeof(psAD->val_type), "%s", poRecord->GetField( 3, 4 ));
+    snprintf( psAD->fwidth, sizeof(psAD->fwidth), "%s", poRecord->GetField( 5, 7 ));
+    snprintf( psAD->finter, sizeof(psAD->finter), "%s", poRecord->GetField( 8, 12 ));
+
     pszData = poRecord->GetData();
-    for( iChar = 12; 
+    for( iChar = 12;
          pszData[iChar] != '\0' && pszData[iChar] != '\\';
          iChar++ ) {}
 
-    strcpy( psAD->att_name, poRecord->GetField( 13, iChar ));
+    snprintf( psAD->att_name, sizeof(psAD->att_name), "%s", poRecord->GetField( 13, iChar ));
 
     return TRUE;
 }
@@ -835,11 +816,11 @@ int NTFFileReader::ProcessAttRecGroup( NTFRecord **papoRecords,
 {
     *ppapszTypes = NULL;
     *ppapszValues = NULL;
-    
+
     for( int iRec = 0; papoRecords[iRec] != NULL; iRec++ )
     {
         char    **papszTypes1 = NULL, **papszValues1 = NULL;
-        
+
         if( papoRecords[iRec]->GetType() != NRT_ATTREC )
             continue;
 
@@ -871,9 +852,9 @@ int NTFFileReader::ProcessAttRecGroup( NTFRecord **papoRecords,
 /*                           ProcessAttRec()                            */
 /************************************************************************/
 
-int NTFFileReader::ProcessAttRec( NTFRecord * poRecord, 
+int NTFFileReader::ProcessAttRec( NTFRecord * poRecord,
                                   int *pnAttId,
-                                  char *** ppapszTypes, 
+                                  char *** ppapszTypes,
                                   char *** ppapszValues )
 
 {
@@ -912,13 +893,13 @@ int NTFFileReader::ProcessAttRec( NTFRecord * poRecord,
         psAttDesc = GetAttDesc(pszData + iOffset );
         if( psAttDesc == NULL )
         {
-            CPLDebug( "NTF", "Couldn't translate attrec type `%2.2s'.", 
+            CPLDebug( "NTF", "Couldn't translate attrec type `%2.2s'.",
                       pszData + iOffset );
             return FALSE;
         }
 
         *ppapszTypes =
-            CSLAddString( *ppapszTypes, 
+            CSLAddString( *ppapszTypes,
                           poRecord->GetField(iOffset+1,iOffset+2) );
 
 /* -------------------------------------------------------------------- */
@@ -928,10 +909,10 @@ int NTFFileReader::ProcessAttRec( NTFRecord * poRecord,
         nFWidth = atoi(psAttDesc->fwidth);
         if( nFWidth == 0 )
         {
-            const char * pszData = poRecord->GetData();
+            const char * pszData2 = poRecord->GetData();
 
-            for( nEnd = iOffset + 2; 
-                 pszData[nEnd] != '\\' && pszData[nEnd] != '\0';
+            for( nEnd = iOffset + 2;
+                 pszData2[nEnd] != '\\' && pszData2[nEnd] != '\0';
                  nEnd++ ) {}
         }
         else
@@ -990,9 +971,9 @@ NTFAttDesc * NTFFileReader::GetAttDesc( const char * pszType )
 /*      an explicit decimal point if it has a "R" format.               */
 /************************************************************************/
 
-int NTFFileReader::ProcessAttValue( const char *pszValType, 
+int NTFFileReader::ProcessAttValue( const char *pszValType,
                                     const char *pszRawValue,
-                                    char **ppszAttName, 
+                                    char **ppszAttName,
                                     char **ppszAttValue,
                                     char **ppszCodeDesc )
 
@@ -1018,18 +999,18 @@ int NTFFileReader::ProcessAttValue( const char *pszValType,
         const char *pszDecimalPortion;
         int       nWidth, nPrecision;
 
-        for( pszDecimalPortion = psAttDesc->finter; 
+        for( pszDecimalPortion = psAttDesc->finter;
              *pszDecimalPortion != ',' && *pszDecimalPortion != '\0';
              pszDecimalPortion++ ) {}
 
-        nWidth = strlen(pszRawValue);
+        nWidth = static_cast<int>(strlen(pszRawValue));
         nPrecision = atoi(pszDecimalPortion+1);
 
         strncpy( szRealString, pszRawValue, nWidth - nPrecision );
         szRealString[nWidth-nPrecision] = '.';
-        strcpy( szRealString+nWidth-nPrecision+1, 
+        strcpy( szRealString+nWidth-nPrecision+1,
                 pszRawValue+nWidth-nPrecision );
-        
+
         *ppszAttValue = szRealString;
     }
 
@@ -1039,9 +1020,9 @@ int NTFFileReader::ProcessAttValue( const char *pszValType,
 /* -------------------------------------------------------------------- */
     else if( psAttDesc->finter[0] == 'I' )
     {
-        static char    szIntString[30];
+        static char    szIntString[30]; // FIXME thread unsafe
 
-        sprintf( szIntString, "%d", atoi(pszRawValue) );
+        snprintf( szIntString, sizeof(szIntString), "%d", atoi(pszRawValue) );
 
         *ppszAttValue = szIntString;
     }
@@ -1091,13 +1072,13 @@ void NTFFileReader::ApplyAttributeValues( OGRFeature * poFeature,
 /* -------------------------------------------------------------------- */
     if( !ProcessAttRecGroup( papoGroup, &papszTypes, &papszValues ) )
         return;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Handle attribute pairs                                          */
 /* -------------------------------------------------------------------- */
     va_list     hVaArgs;
     const char  *pszAttName;
-    
+
     va_start(hVaArgs, papoGroup);
 
     while( (pszAttName = va_arg(hVaArgs, const char *)) != NULL )
@@ -1108,13 +1089,15 @@ void NTFFileReader::ApplyAttributeValues( OGRFeature * poFeature,
                              papszTypes, papszValues );
     }
 
+    va_end(hVaArgs);
+
 /* -------------------------------------------------------------------- */
 /*      Cleanup.                                                        */
 /* -------------------------------------------------------------------- */
     CSLDestroy( papszTypes );
     CSLDestroy( papszValues );
 }
-                                          
+
 
 /************************************************************************/
 /*                        ApplyAttributeValue()                         */
@@ -1135,19 +1118,21 @@ int NTFFileReader::ApplyAttributeValue( OGRFeature * poFeature, int iField,
 /*      notification.                                                   */
 /* -------------------------------------------------------------------- */
     int         iValue;
-    
+
     iValue = CSLFindString( papszTypes, pszAttName );
     if( iValue < 0 )
         return FALSE;
 
+    CPLAssert(papszValues != NULL);
 /* -------------------------------------------------------------------- */
 /*      Process the attribute value ... this really only has a          */
 /*      useful effect for real numbers.                                 */
 /* -------------------------------------------------------------------- */
     char        *pszAttLongName, *pszAttValue, *pszCodeDesc;
 
-    ProcessAttValue( pszAttName, papszValues[iValue],
-                     &pszAttLongName, &pszAttValue, &pszCodeDesc );
+    if( !ProcessAttValue( pszAttName, papszValues[iValue],
+                     &pszAttLongName, &pszAttValue, &pszCodeDesc ) )
+        return FALSE;
 
 /* -------------------------------------------------------------------- */
 /*      Apply the value to the field using the simple set string        */
@@ -1163,7 +1148,7 @@ int NTFFileReader::ApplyAttributeValue( OGRFeature * poFeature, int iField,
     {
         char    szDescFieldName[256];
 
-        sprintf( szDescFieldName, "%s_DESC", 
+        snprintf( szDescFieldName, sizeof(szDescFieldName), "%s_DESC",
                  poFeature->GetDefnRef()->GetFieldDefn(iField)->GetNameRef() );
         poFeature->SetField( szDescFieldName, pszCodeDesc );
     }
@@ -1318,13 +1303,13 @@ int DefaultNTFRecordGrouper( NTFFileReader *, NTFRecord ** papoGroup,
         // We keep going till we get the seed geometry.
         int     iRec, bGotCPOLY=FALSE;
 
-        for( iRec = 0; papoGroup[iRec] != NULL; iRec++ ) 
+        for( iRec = 0; papoGroup[iRec] != NULL; iRec++ )
         {
             if( papoGroup[iRec]->GetType() == NRT_CPOLY )
                 bGotCPOLY = TRUE;
         }
 
-        if( bGotCPOLY 
+        if( bGotCPOLY
             && poCandidate->GetType() != NRT_GEOMETRY
             && poCandidate->GetType() != NRT_ATTREC )
             return FALSE;
@@ -1332,19 +1317,19 @@ int DefaultNTFRecordGrouper( NTFFileReader *, NTFRecord ** papoGroup,
         /*
          * this logic assumes we always get a point geometry with a CPOLY
          * but that isn't always true, for instance with BL2000 data.  The
-         * preceed check will handle this case.
+         * preceding check will handle this case.
          */
         if( papoGroup[iRec-1]->GetType() != NRT_GEOMETRY )
             return TRUE;
         else
             return FALSE;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Is this a "feature" defining record?  If so break out if it     */
 /*      isn't the first record in the group.                            */
 /* -------------------------------------------------------------------- */
-    if( papoGroup[0] != NULL 
+    if( papoGroup[0] != NULL
         && (poCandidate->GetType() == NRT_NAMEREC
             || poCandidate->GetType() == NRT_NODEREC
             || poCandidate->GetType() == NRT_LINEREC
@@ -1371,7 +1356,7 @@ int DefaultNTFRecordGrouper( NTFFileReader *, NTFRecord ** papoGroup,
             if( poCandidate->GetType() == papoGroup[iRec]->GetType() )
                 break;
         }
-           
+
         if( papoGroup[iRec] != NULL )
             return FALSE;
     }
@@ -1392,7 +1377,7 @@ NTFRecord **NTFFileReader::ReadRecordGroup()
    int            nRecordCount = 0;
 
    ClearCGroup();
-   
+
 /* -------------------------------------------------------------------- */
 /*      Loop, reading records till we think we have a grouping.         */
 /* -------------------------------------------------------------------- */
@@ -1401,19 +1386,19 @@ NTFRecord **NTFFileReader::ReadRecordGroup()
        CPLAssert( nRecordCount < MAX_REC_GROUP);
        if( nRecordCount >= MAX_REC_GROUP )
        {
-           CPLError( CE_Failure, CPLE_AppDefined, 
-                     "Maximum record group size (%d) exceeded.\n", 
+           CPLError( CE_Failure, CPLE_AppDefined,
+                     "Maximum record group size (%d) exceeded.\n",
                      MAX_REC_GROUP );
            break;
        }
 
        if( !pfnRecordGrouper( this, apoCGroup, poRecord ) )
            break;
-       
+
        apoCGroup[nRecordCount++] = poRecord;
        apoCGroup[nRecordCount] = NULL;
    }
-   
+
 /* -------------------------------------------------------------------- */
 /*      Push the last record back on the input queue.                   */
 /* -------------------------------------------------------------------- */
@@ -1474,7 +1459,7 @@ OGRFeature * NTFFileReader::ReadOGRFeature( OGRNTFLayer * poTargetLayer )
 /*      Loop looking for a group we can translate, and that if          */
 /*      needed matches our layer request.                               */
 /* -------------------------------------------------------------------- */
-    while( TRUE )
+    while( true )
     {
         if( GetProductId() == NPC_UNKNOWN && nNTFLevel > 2 )
             papoGroup = GetNextIndexedRecordGroup( apoCGroup + 1 );
@@ -1483,8 +1468,12 @@ OGRFeature * NTFFileReader::ReadOGRFeature( OGRNTFLayer * poTargetLayer )
 
         if( papoGroup == NULL )
             break;
-        
-        poLayer = apoTypeTranslation[papoGroup[0]->GetType()];
+
+        int nType = papoGroup[0]->GetType();
+        if( nType < 0 ||
+            nType >= (int)(sizeof(apoTypeTranslation) / sizeof(apoTypeTranslation[0])) )
+            continue;
+        poLayer = apoTypeTranslation[nType];
         if( poLayer == NULL )
             continue;
 
@@ -1517,7 +1506,7 @@ OGRFeature * NTFFileReader::ReadOGRFeature( OGRNTFLayer * poTargetLayer )
         int             iTileRefField;
 
         iTileRefField = poLayer->GetLayerDefn()->GetFieldCount()-1;
-    
+
         CPLAssert( EQUAL(poLayer->GetLayerDefn()->GetFieldDefn(iTileRefField)->
                          GetNameRef(), "TILE_REF") );
 
@@ -1584,7 +1573,7 @@ void NTFFileReader::IndexFile()
 
 {
     NTFRecord   *poRecord;
-    
+
     Reset();
 
     DestroyIndex();
@@ -1604,8 +1593,8 @@ void NTFFileReader::IndexFile()
 
         if( iType < 0 || iType >= 100 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Illegal type %d record, skipping.", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Illegal type %d record, skipping.",
                       iType );
             delete poRecord;
             continue;
@@ -1634,7 +1623,7 @@ void NTFFileReader::IndexFile()
 /* -------------------------------------------------------------------- */
         if( apapoRecordIndex[iType][iId] != NULL )
         {
-            CPLDebug( "OGR_NTF", 
+            CPLDebug( "OGR_NTF",
                       "Duplicate record with index %d and type %d\n"
                       "in NTFFileReader::IndexFile().",
                       iId, iType );
@@ -1678,7 +1667,7 @@ NTFRecord * NTFFileReader::GetIndexedRecord( int iType, int iId )
 
 {
     if( (iType < 0 || iType > 99)
-        || (iId < 0 || iId >= anIndexSize[iType]) 
+        || (iId < 0 || iId >= anIndexSize[iType])
         || (apapoRecordIndex[iType])[iId] == NULL )
     {
         /* If NRT_GEOMETRY3D is an acceptable alternative to 2D */
@@ -1699,7 +1688,7 @@ static void AddToIndexGroup( NTFRecord **papoGroup, NTFRecord * poRecord )
 
 {
     int         i;
-    
+
     for( i = 1; papoGroup[i] != NULL; i++ ) {}
 
     papoGroup[i] = poRecord;
@@ -1736,7 +1725,7 @@ NTFRecord **NTFFileReader::GetNextIndexedRecordGroup( NTFRecord **
 /*      Find the next anchor record.                                    */
 /* -------------------------------------------------------------------- */
     NTFRecord   *poAnchor = NULL;
-    
+
     while( nPrevType != 99 && poAnchor == NULL )
     {
         nPrevId++;
@@ -1755,7 +1744,7 @@ NTFRecord **NTFFileReader::GetNextIndexedRecordGroup( NTFRecord **
                    && nPrevType != NRT_CPOLY
                    && nPrevType != NRT_POINTREC
                    && nPrevType != NRT_LINEREC );
-            
+
             nPrevId = 0;
         }
         else
@@ -1783,16 +1772,16 @@ NTFRecord **NTFFileReader::GetNextIndexedRecordGroup( NTFRecord **
     if( poAnchor->GetType() == NRT_POINTREC
          || poAnchor->GetType() == NRT_LINEREC )
     {
-        int             nAttCount = 0;
-        
+        int             l_nAttCount = 0;
+
         AddToIndexGroup( apoCGroup,
                          GetIndexedRecord( NRT_GEOMETRY,
                                            atoi(poAnchor->GetField(9,14)) ) );
 
         if( poAnchor->GetLength() >= 16 )
-            nAttCount = atoi(poAnchor->GetField(15,16));
+            l_nAttCount = atoi(poAnchor->GetField(15,16));
 
-        for( int iAtt = 0; iAtt < nAttCount; iAtt++ )
+        for( int iAtt = 0; iAtt < l_nAttCount; iAtt++ )
         {
             AddToIndexGroup(
                 apoCGroup,
@@ -1807,16 +1796,16 @@ NTFRecord **NTFFileReader::GetNextIndexedRecordGroup( NTFRecord **
 /* -------------------------------------------------------------------- */
     else if( poAnchor->GetType() == NRT_TEXTREC )
     {
-        int             nAttCount = 0;
+        int             l_nAttCount = 0;
         int             nSelCount = 0;
 
         // Add all the text position records.
         nSelCount = atoi(poAnchor->GetField(9,10));
-        
+
         for( int iSel = 0; iSel < nSelCount; iSel++ )
         {
             int iStart = 11 + 12*iSel + 6;
-            
+
             AddToIndexGroup(
                 apoCGroup,
                 GetIndexedRecord( NRT_TEXTPOS,
@@ -1829,7 +1818,7 @@ NTFRecord **NTFFileReader::GetNextIndexedRecordGroup( NTFRecord **
         {
             int         nNumTEXR;
             NTFRecord  *poRecord = apoCGroup[iRec];
-            
+
             if( poRecord->GetType() != NRT_TEXTPOS )
                 continue;
 
@@ -1848,16 +1837,16 @@ NTFRecord **NTFFileReader::GetNextIndexedRecordGroup( NTFRecord **
                                                               22+iTEXR*12))));
             }
         }
-        
+
         // Add all the attribute records.
         if( poAnchor->GetLength() >= 10 + nSelCount*12 + 2 )
-            nAttCount = atoi(poAnchor->GetField(11+nSelCount*12,
+            l_nAttCount = atoi(poAnchor->GetField(11+nSelCount*12,
                                                 12+nSelCount*12));
 
-        for( int iAtt = 0; iAtt < nAttCount; iAtt++ )
+        for( int iAtt = 0; iAtt < l_nAttCount; iAtt++ )
         {
             int iStart = 13 + nSelCount*12 + 6 * iAtt;
-            
+
             AddToIndexGroup(
                 apoCGroup,
                 GetIndexedRecord( NRT_ATTREC,
@@ -1883,15 +1872,15 @@ NTFRecord **NTFFileReader::GetNextIndexedRecordGroup( NTFRecord **
     {
         int     nParts = atoi(poAnchor->GetField(9,12));
         int     nAttOffset = 13 + nParts * 8;
-        int     nAttCount = 0;
-        
+        int     l_nAttCount = 0;
+
         if( poAnchor->GetLength() > nAttOffset + 2 )
-            nAttCount = atoi(poAnchor->GetField(nAttOffset,nAttOffset+1));
+            l_nAttCount = atoi(poAnchor->GetField(nAttOffset,nAttOffset+1));
 
-        for( int iAtt = 0; iAtt < nAttCount; iAtt++ )
+        for( int iAtt = 0; iAtt < l_nAttCount; iAtt++ )
         {
             int iStart = nAttOffset + 2 + iAtt * 6;
-            
+
             AddToIndexGroup(
                 apoCGroup,
                 GetIndexedRecord( NRT_ATTREC,
@@ -1914,13 +1903,13 @@ NTFRecord **NTFFileReader::GetNextIndexedRecordGroup( NTFRecord **
                                           atoi(poAnchor->GetField(15,20)) ) );
 
         // Attributes
-        
-        int     nAttCount = 0;
-        
+
+        int     l_nAttCount = 0;
+
         if( poAnchor->GetLength() >= 22 )
-            nAttCount = atoi(poAnchor->GetField(21,22));
+            l_nAttCount = atoi(poAnchor->GetField(21,22));
 
-        for( int iAtt = 0; iAtt < nAttCount; iAtt++ )
+        for( int iAtt = 0; iAtt < l_nAttCount; iAtt++ )
         {
             AddToIndexGroup(
                 apoCGroup,
@@ -1941,19 +1930,19 @@ NTFRecord **NTFFileReader::GetNextIndexedRecordGroup( NTFRecord **
         {
             int  nGeomId = atoi(poAnchor->GetField(nPostPoly+1,nPostPoly+6));
 
-            AddToIndexGroup( apoCGroup, 
+            AddToIndexGroup( apoCGroup,
                              GetIndexedRecord( NRT_GEOMETRY, nGeomId) );
         }
 
         if( poAnchor->GetLength() >= nPostPoly + 8 )
         {
-            int nAttCount = atoi(poAnchor->GetField(nPostPoly+7,nPostPoly+8));
-            
-            for( int iAtt = 0; iAtt < nAttCount; iAtt++ )
+            int l_nAttCount = atoi(poAnchor->GetField(nPostPoly+7,nPostPoly+8));
+
+            for( int iAtt = 0; iAtt < l_nAttCount; iAtt++ )
             {
                 int nAttId = atoi(poAnchor->GetField(nPostPoly+9+iAtt*6,
                                                      nPostPoly+14+iAtt*6));
-                AddToIndexGroup( apoCGroup, 
+                AddToIndexGroup( apoCGroup,
                                  GetIndexedRecord( NRT_ATTREC, nAttId) );
             }
         }
@@ -1996,9 +1985,9 @@ void NTFFileReader::CacheAddByGeomId( int nGeomId, OGRGeometry *poGeometry )
     {
         int     nNewSize = nGeomId + 100;
 
-        papoLineCache = (OGRGeometry **) 
+        papoLineCache = (OGRGeometry **)
             CPLRealloc( papoLineCache, sizeof(void*) * nNewSize );
-        memset( papoLineCache + nLineCacheSize, 0, 
+        memset( papoLineCache + nLineCacheSize, 0,
                 sizeof(void*) * (nNewSize - nLineCacheSize) );
         nLineCacheSize = nNewSize;
     }
@@ -2092,7 +2081,7 @@ int NTFFileReader::FormPolygonFromCache( OGRFeature * poFeature )
 /* -------------------------------------------------------------------- */
 /*      Collect all the linked lines.                                   */
 /* -------------------------------------------------------------------- */
-    panLinks = poFeature->GetFieldAsIntegerList( "GEOM_ID_OF_LINK", 
+    panLinks = poFeature->GetFieldAsIntegerList( "GEOM_ID_OF_LINK",
                                                  &nLinkCount );
 
     if( panLinks == NULL )
@@ -2115,13 +2104,13 @@ int NTFFileReader::FormPolygonFromCache( OGRFeature * poFeature )
 /* -------------------------------------------------------------------- */
     OGRPolygon *poPoly;
 
-    poPoly = (OGRPolygon *) 
-        OGRBuildPolygonFromEdges( (OGRGeometryH) &oLines, FALSE, FALSE, 0.1, 
+    poPoly = (OGRPolygon *)
+        OGRBuildPolygonFromEdges( (OGRGeometryH) &oLines, FALSE, FALSE, 0.1,
                                   NULL );
 
     poFeature->SetGeometryDirectly( poPoly );
 
     oLines.removeGeometry( -1, FALSE );
-    
+
     return poPoly != NULL;
 }
diff --git a/ogr/ogrsf_frmts/ntf/ntfrecord.cpp b/ogr/ogrsf_frmts/ntf/ntfrecord.cpp
index c60d0cc..8e32efc 100644
--- a/ogr/ogrsf_frmts/ntf/ntfrecord.cpp
+++ b/ogr/ogrsf_frmts/ntf/ntfrecord.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ntfrecord.cpp 32416 2015-12-21 10:16:11Z rouault $
+ * $Id: ntfrecord.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  NTF Translator
  * Purpose:  NTFRecord class implementation.
@@ -31,7 +31,7 @@
 #include "ntf.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ntfrecord.cpp 32416 2015-12-21 10:16:11Z rouault $");
+CPL_CVSID("$Id: ntfrecord.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 static int nFieldBufSize = 0;
 static char *pszFieldBuf = NULL;
@@ -56,12 +56,12 @@ NTFRecord::NTFRecord( FILE * fp )
         return;
 
 /* ==================================================================== */
-/*      Read lines untill we get to one without a continuation mark.    */
+/*      Read lines until we get to one without a continuation mark.     */
 /* ==================================================================== */
     char      szLine[MAX_RECORD_LEN+3];
     int       nNewLength;
 
-    do { 
+    do {
         nNewLength = ReadPhysicalLine( fp, szLine );
         if( nNewLength == -1 || nNewLength == -2 )
             break;
@@ -71,7 +71,7 @@ NTFRecord::NTFRecord( FILE * fp )
 
         if( nNewLength < 2 || szLine[nNewLength-1] != '%' )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Corrupt NTF record, missing end '%%'." );
             CPLFree( pszData );
             pszData = NULL;
@@ -81,10 +81,9 @@ NTFRecord::NTFRecord( FILE * fp )
         if( pszData == NULL )
         {
             nLength = nNewLength - 2;
-            pszData = (char *) VSIMalloc(nLength+1);
+            pszData = (char *) VSI_MALLOC_VERBOSE(nLength+1);
             if (pszData == NULL)
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
                 return;
             }
             memcpy( pszData, szLine, nLength );
@@ -92,7 +91,7 @@ NTFRecord::NTFRecord( FILE * fp )
         }
         else
         {
-            if( !EQUALN(szLine,"00",2) || nNewLength < 4 )
+            if( !STARTS_WITH_CI(szLine, "00") || nNewLength < 4 )
             {
                 CPLError( CE_Failure, CPLE_AppDefined, "Invalid line");
                 VSIFree(pszData);
@@ -100,10 +99,9 @@ NTFRecord::NTFRecord( FILE * fp )
                 return;
             }
 
-            char* pszNewData = (char *) VSIRealloc(pszData,nLength+(nNewLength-4)+1);
+            char* pszNewData = (char *) VSI_REALLOC_VERBOSE(pszData,nLength+(nNewLength-4)+1);
             if (pszNewData == NULL)
             {
-                CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
                 VSIFree(pszData);
                 pszData = NULL;
                 return;
@@ -155,13 +153,13 @@ int NTFRecord::ReadPhysicalLine( FILE *fp, char *pszLine )
 
 {
     int         nBytesRead = 0;
-    int         nRecordStart, nRecordEnd, i, nLength = 0;
+    int         nRecordStart, nRecordEnd, i, l_nLength = 0;
 
 /* -------------------------------------------------------------------- */
 /*      Read enough data that we are sure we have a whole record.       */
 /* -------------------------------------------------------------------- */
-    nRecordStart = VSIFTell( fp );
-    nBytesRead = VSIFRead( pszLine, 1, MAX_RECORD_LEN+2, fp );
+    nRecordStart = static_cast<int>(VSIFTell( fp ));
+    nBytesRead = static_cast<int>(VSIFRead( pszLine, 1, MAX_RECORD_LEN+2, fp ));
 
     if( nBytesRead == 0 )
     {
@@ -169,12 +167,12 @@ int NTFRecord::ReadPhysicalLine( FILE *fp, char *pszLine )
             return -1;
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Low level read error occured while reading NTF file." );
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Low level read error occurred while reading NTF file." );
             return -2;
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Search for CR or LF.                                            */
 /* -------------------------------------------------------------------- */
@@ -190,7 +188,7 @@ int NTFRecord::ReadPhysicalLine( FILE *fp, char *pszLine )
 /* -------------------------------------------------------------------- */
     if( i == MAX_RECORD_LEN+2 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "%d byte record too long for NTF format.\n"
                   "No line may be longer than 80 characters though up to %d tolerated.\n",
                   nBytesRead, MAX_RECORD_LEN );
@@ -200,20 +198,21 @@ int NTFRecord::ReadPhysicalLine( FILE *fp, char *pszLine )
 /* -------------------------------------------------------------------- */
 /*      Trim CR/LF.                                                     */
 /* -------------------------------------------------------------------- */
-    nLength = i;
+    l_nLength = i;
     if( pszLine[i+1] == 10 || pszLine[i+1] == 13 )
         nRecordEnd = nRecordStart + i + 2;
     else
         nRecordEnd = nRecordStart + i + 1;
 
-    pszLine[nLength] = '\0';
+    pszLine[l_nLength] = '\0';
 
 /* -------------------------------------------------------------------- */
 /*      Restore read pointer to beginning of next record.               */
 /* -------------------------------------------------------------------- */
-    VSIFSeek( fp, nRecordEnd, SEEK_SET );
-    
-    return nLength;
+    if( VSIFSeek( fp, nRecordEnd, SEEK_SET ) != 0 )
+        return -1;
+
+    return l_nLength;
 }
 
 /************************************************************************/
@@ -259,6 +258,3 @@ const char * NTFRecord::GetField( int nStart, int nEnd )
 
     return pszFieldBuf;
 }
-
-
-
diff --git a/ogr/ogrsf_frmts/ntf/ntfstroke.cpp b/ogr/ogrsf_frmts/ntf/ntfstroke.cpp
index 0a8f47e..b5a3a52 100644
--- a/ogr/ogrsf_frmts/ntf/ntfstroke.cpp
+++ b/ogr/ogrsf_frmts/ntf/ntfstroke.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ntfstroke.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: ntfstroke.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  NTF Translator
  * Purpose:  NTF Arc to polyline stroking code.  This code is really generic,
@@ -34,11 +34,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ntfstroke.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
-
-#ifndef PI
-#define PI  3.14159265358979323846
-#endif
+CPL_CVSID("$Id: ntfstroke.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                     NTFArcCenterFromEdgePoints()                     */
@@ -47,8 +43,8 @@ CPL_CVSID("$Id: ntfstroke.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
 /************************************************************************/
 
 int NTFArcCenterFromEdgePoints( double x_c0, double y_c0,
-                                double x_c1, double y_c1, 
-                                double x_c2, double y_c2, 
+                                double x_c1, double y_c1,
+                                double x_c2, double y_c2,
                                 double *x_center, double *y_center )
 
 {
@@ -107,10 +103,10 @@ int NTFArcCenterFromEdgePoints( double x_c0, double y_c0,
 
     b1 = -1.0;
     b2 = -1.0;
-    
+
     c1 = (y1 - m1*x1);
     c2 = (y2 - m2*x2);
-    
+
 /* -------------------------------------------------------------------- */
 /*      Compute the intersection of the two lines through the center    */
 /*      of the circle, using Kramers rule.                              */
@@ -137,12 +133,12 @@ NTFStrokeArcToOGRGeometry_Points( double dfStartX, double dfStartY,
                                   double dfAlongX, double dfAlongY,
                                   double dfEndX, double dfEndY,
                                   int nVertexCount )
-    
+
 {
     double      dfStartAngle, dfEndAngle, dfAlongAngle;
     double      dfCenterX, dfCenterY, dfRadius;
 
-    if( !NTFArcCenterFromEdgePoints( dfStartX, dfStartY, dfAlongX, dfAlongY, 
+    if( !NTFArcCenterFromEdgePoints( dfStartX, dfStartY, dfAlongX, dfAlongY,
                                      dfEndX, dfEndY, &dfCenterX, &dfCenterY ) )
         return NULL;
 
@@ -157,15 +153,15 @@ NTFStrokeArcToOGRGeometry_Points( double dfStartX, double dfStartY,
 
         dfDeltaX = dfStartX - dfCenterX;
         dfDeltaY = dfStartY - dfCenterY;
-        dfStartAngle = atan2(dfDeltaY,dfDeltaX) * 180.0 / PI;
+        dfStartAngle = atan2(dfDeltaY,dfDeltaX) * 180.0 / M_PI;
 
         dfDeltaX = dfAlongX - dfCenterX;
         dfDeltaY = dfAlongY - dfCenterY;
-        dfAlongAngle = atan2(dfDeltaY,dfDeltaX) * 180.0 / PI;
+        dfAlongAngle = atan2(dfDeltaY,dfDeltaX) * 180.0 / M_PI;
 
         dfDeltaX = dfEndX - dfCenterX;
         dfDeltaY = dfEndY - dfCenterY;
-        dfEndAngle = atan2(dfDeltaY,dfDeltaX) * 180.0 / PI;
+        dfEndAngle = atan2(dfDeltaY,dfDeltaX) * 180.0 / M_PI;
 
 #ifdef notdef
         if( dfStartAngle > dfAlongAngle && dfAlongAngle > dfEndAngle )
@@ -199,9 +195,9 @@ NTFStrokeArcToOGRGeometry_Points( double dfStartX, double dfStartY,
 
     dfRadius = sqrt( (dfCenterX - dfStartX) * (dfCenterX - dfStartX)
                      + (dfCenterY - dfStartY) * (dfCenterY - dfStartY) );
-    
-    return NTFStrokeArcToOGRGeometry_Angles( dfCenterX, dfCenterY, 
-                                             dfRadius, 
+
+    return NTFStrokeArcToOGRGeometry_Angles( dfCenterX, dfCenterY,
+                                             dfRadius,
                                              dfStartAngle, dfEndAngle,
                                              nVertexCount );
 }
@@ -211,8 +207,8 @@ NTFStrokeArcToOGRGeometry_Points( double dfStartX, double dfStartY,
 /************************************************************************/
 
 OGRGeometry *
-NTFStrokeArcToOGRGeometry_Angles( double dfCenterX, double dfCenterY, 
-                                  double dfRadius, 
+NTFStrokeArcToOGRGeometry_Angles( double dfCenterX, double dfCenterY,
+                                  double dfRadius,
                                   double dfStartAngle, double dfEndAngle,
                                   int nVertexCount )
 
@@ -225,13 +221,11 @@ NTFStrokeArcToOGRGeometry_Angles( double dfCenterX, double dfCenterY,
     dfSlice = (dfEndAngle-dfStartAngle)/(nVertexCount-1);
 
     poLine->setNumPoints( nVertexCount );
-        
+
     for( iPoint=0; iPoint < nVertexCount; iPoint++ )
     {
-        double      dfAngle;
+        double dfAngle = (dfStartAngle + iPoint * dfSlice) * M_PI / 180.0;
 
-        dfAngle = (dfStartAngle + iPoint * dfSlice) * PI / 180.0;
-            
         dfArcX = dfCenterX + cos(dfAngle) * dfRadius;
         dfArcY = dfCenterY + sin(dfAngle) * dfRadius;
 
@@ -240,5 +234,3 @@ NTFStrokeArcToOGRGeometry_Angles( double dfCenterX, double dfCenterY,
 
     return poLine;
 }
-
-
diff --git a/ogr/ogrsf_frmts/ntf/ogrntfdatasource.cpp b/ogr/ogrsf_frmts/ntf/ogrntfdatasource.cpp
index d3cee33..940c5f6 100644
--- a/ogr/ogrsf_frmts/ntf/ogrntfdatasource.cpp
+++ b/ogr/ogrsf_frmts/ntf/ogrntfdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrntfdatasource.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: ogrntfdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  UK NTF Reader
  * Purpose:  Implements OGRNTFDataSource class
@@ -31,43 +31,36 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrntfdatasource.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: ogrntfdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                          OGRNTFDataSource()                          */
 /************************************************************************/
 
-OGRNTFDataSource::OGRNTFDataSource()
-
+OGRNTFDataSource::OGRNTFDataSource() :
+    pszName(NULL),
+    nLayers(0),
+    papoLayers(NULL),
+    poFCLayer(NULL),
+    iCurrentFC(0),
+    iCurrentReader(-1),
+    nCurrentPos(0),
+    nCurrentFID(0),
+    nNTFFileCount(0),
+    papoNTFFileReader(NULL),
+    nFCCount(0),
+    papszFCNum(NULL),
+    papszFCName(NULL),
+    papszOptions(NULL)
 {
-    nLayers = 0;
-    papoLayers = NULL;
-
-    nNTFFileCount = 0;
-    papoNTFFileReader = NULL;
-
-    pszName = NULL;
-
-    iCurrentReader = -1;
-    iCurrentFC = 0;
-
-    nFCCount = 0;
-    papszFCNum = NULL;
-    papszFCName = NULL;
-
-    poFCLayer = NULL;
-
-    papszOptions = NULL;
-
     poSpatialRef = new OGRSpatialReference( "PROJCS[\"OSGB 1936 / British National Grid\",GEOGCS[\"OSGB 1936\",DATUM[\"OSGB_1936\",SPHEROID[\"Airy 1830\",6377563.396,299.3249646,AUTHORITY[\"EPSG\",\"7001\"]],AUTHORITY[\"EPSG\",\"6277\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433],AUTHORITY[\"EPSG\",\"4277\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",49],PARAMETER[\"central_meridian\",-2],PARAMETER[\"scale_factor\", [...]
 
-
 /* -------------------------------------------------------------------- */
 /*      Allow initialization of options from the environment.           */
 /* -------------------------------------------------------------------- */
     if( getenv("OGR_NTF_OPTIONS") != NULL )
     {
-        papszOptions = 
+        papszOptions =
             CSLTokenizeStringComplex( getenv("OGR_NTF_OPTIONS"), ",",
                                       FALSE, FALSE );
     }
@@ -80,19 +73,17 @@ OGRNTFDataSource::OGRNTFDataSource()
 OGRNTFDataSource::~OGRNTFDataSource()
 
 {
-    int         i;
-
-    for( i = 0; i < nNTFFileCount; i++ )
+    for( int i = 0; i < nNTFFileCount; i++ )
         delete papoNTFFileReader[i];
 
     CPLFree( papoNTFFileReader );
 
-    for( i = 0; i < nLayers; i++ )
+    for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
 
     if( poFCLayer != NULL )
         delete poFCLayer;
-    
+
     CPLFree( papoLayers );
 
     CPLFree( pszName );
@@ -120,12 +111,12 @@ int OGRNTFDataSource::TestCapability( const char * )
 /*                           GetNamedLayer()                            */
 /************************************************************************/
 
-OGRNTFLayer * OGRNTFDataSource::GetNamedLayer( const char * pszName )
+OGRNTFLayer * OGRNTFDataSource::GetNamedLayer( const char * pszNameIn )
 
 {
     for( int i = 0; i < nLayers; i++ )
     {
-        if( EQUAL(papoLayers[i]->GetLayerDefn()->GetName(),pszName) )
+        if( EQUAL(papoLayers[i]->GetLayerDefn()->GetName(),pszNameIn) )
             return (OGRNTFLayer *) papoLayers[i];
     }
 
@@ -141,7 +132,7 @@ void OGRNTFDataSource::AddLayer( OGRLayer * poNewLayer )
 {
     papoLayers = (OGRLayer **)
         CPLRealloc( papoLayers, sizeof(void*) * ++nLayers );
-    
+
     papoLayers[nLayers-1] = poNewLayer;
 }
 
@@ -190,7 +181,7 @@ int OGRNTFDataSource::Open( const char * pszFilename, int bTestOpen,
 /* -------------------------------------------------------------------- */
 /*      Is the given path a directory or a regular file?                */
 /* -------------------------------------------------------------------- */
-    if( CPLStat( pszFilename, &stat ) != 0 
+    if( CPLStat( pszFilename, &stat ) != 0
         || (!VSI_ISDIR(stat.st_mode) && !VSI_ISREG(stat.st_mode)) )
     {
         if( !bTestOpen )
@@ -200,7 +191,7 @@ int OGRNTFDataSource::Open( const char * pszFilename, int bTestOpen,
 
         return FALSE;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Build a list of filenames we figure are NTF files.              */
 /* -------------------------------------------------------------------- */
@@ -210,12 +201,12 @@ int OGRNTFDataSource::Open( const char * pszFilename, int bTestOpen,
     }
     else
     {
-        char      **candidateFileList = CPLReadDir( pszFilename );
+        char      **candidateFileList = VSIReadDir( pszFilename );
         int         i;
 
-        for( i = 0; 
-             candidateFileList != NULL && candidateFileList[i] != NULL; 
-             i++ ) 
+        for( i = 0;
+             candidateFileList != NULL && candidateFileList[i] != NULL;
+             i++ )
         {
             if( papszLimitedFileList != NULL
                 && CSLFindString(papszLimitedFileList,
@@ -223,14 +214,13 @@ int OGRNTFDataSource::Open( const char * pszFilename, int bTestOpen,
             {
                 continue;
             }
-            
+
             if( strlen(candidateFileList[i]) > 4
-              && EQUALN(candidateFileList[i] + strlen(candidateFileList[i])-4,
-                       ".ntf",4) )
+              && STARTS_WITH_CI(candidateFileList[i] + strlen(candidateFileList[i])-4, ".ntf") )
             {
                 char       fullFilename[2048];
 
-                sprintf( fullFilename, "%s%c%s", 
+                snprintf( fullFilename, sizeof(fullFilename), "%s%c%s",
                          pszFilename,
 #ifdef WIN32
                          '\\',
@@ -252,7 +242,7 @@ int OGRNTFDataSource::Open( const char * pszFilename, int bTestOpen,
                           "No candidate NTF files (.ntf) found in\n"
                           "directory: %s",
                           pszFilename );
-
+            CSLDestroy(papszFileList);
             return FALSE;
         }
     }
@@ -261,15 +251,15 @@ int OGRNTFDataSource::Open( const char * pszFilename, int bTestOpen,
 /*      Loop over all these files trying to open them.  In testopen     */
 /*      mode we first read the first 80 characters, to verify that      */
 /*      it looks like an NTF file.  Note that we don't keep the file    */
-/*      open ... we don't want to occupy alot of file handles when      */
+/*      open ... we don't want to occupy a lot of file handles when      */
 /*      handling a whole directory.                                     */
 /* -------------------------------------------------------------------- */
     int         i;
 
     papoNTFFileReader = (NTFFileReader **)
         CPLCalloc(sizeof(void*), CSLCount(papszFileList));
-    
-    for( i = 0; papszFileList[i] != NULL; i++ )
+
+    for( i = 0; papszFileList != NULL && papszFileList[i] != NULL; i++ )
     {
         if( bTestOpen )
         {
@@ -280,7 +270,7 @@ int OGRNTFDataSource::Open( const char * pszFilename, int bTestOpen,
             fp = VSIFOpen( papszFileList[i], "rb" );
             if( fp == NULL )
                 continue;
-            
+
             if( VSIFRead( szHeader, 80, 1, fp ) < 1 )
             {
                 VSIFClose( fp );
@@ -288,8 +278,8 @@ int OGRNTFDataSource::Open( const char * pszFilename, int bTestOpen,
             }
 
             VSIFClose( fp );
-            
-            if( !EQUALN(szHeader,"01",2) )
+
+            if( !STARTS_WITH_CI(szHeader, "01") )
                 continue;
 
             for( j = 0; j < 80; j++ )
@@ -311,7 +301,7 @@ int OGRNTFDataSource::Open( const char * pszFilename, int bTestOpen,
         {
             delete poFR;
             CSLDestroy( papszFileList );
-            
+
             return FALSE;
         }
 
@@ -332,7 +322,7 @@ int OGRNTFDataSource::Open( const char * pszFilename, int bTestOpen,
 /*      Establish generic layers.                                       */
 /* -------------------------------------------------------------------- */
     EstablishGenericLayers();
-    
+
 /* -------------------------------------------------------------------- */
 /*      Loop over all the files, collecting a unique feature class      */
 /*      listing.                                                        */
@@ -340,14 +330,14 @@ int OGRNTFDataSource::Open( const char * pszFilename, int bTestOpen,
     for( int iSrcFile = 0; iSrcFile < nNTFFileCount; iSrcFile++ )
     {
         NTFFileReader   *poSrcReader = papoNTFFileReader[iSrcFile];
-        
+
         for( int iSrcFC = 0; iSrcFC < poSrcReader->GetFCCount(); iSrcFC++ )
         {
             int         iDstFC;
             char       *pszSrcFCName, *pszSrcFCNum;
 
             poSrcReader->GetFeatureClass( iSrcFC, &pszSrcFCNum, &pszSrcFCName);
-            
+
             for( iDstFC = 0; iDstFC < nFCCount; iDstFC++ )
             {
                 if( EQUAL(pszSrcFCNum,papszFCNum[iDstFC]) )
@@ -370,7 +360,7 @@ int OGRNTFDataSource::Open( const char * pszFilename, int bTestOpen,
         poFCLayer = new OGRNTFFeatureClassLayer( this );
     else
         poFCLayer = NULL;
-    
+
     return TRUE;
 }
 
@@ -403,7 +393,7 @@ OGRFeature *OGRNTFDataSource::GetNextFeature()
 
 /* -------------------------------------------------------------------- */
 /*      If we have already read all the conventional features, we       */
-/*      should try and return feature class features.                   */    
+/*      should try and return feature class features.                   */
 /* -------------------------------------------------------------------- */
     if( iCurrentReader == nNTFFileCount )
     {
@@ -435,7 +425,7 @@ OGRFeature *OGRNTFDataSource::GetNextFeature()
     if( nCurrentPos != -1 )
         papoNTFFileReader[iCurrentReader]->SetFPPos( nCurrentPos,
                                                      nCurrentFID );
-        
+
 /* -------------------------------------------------------------------- */
 /*      Read a feature.  If we get NULL the file must be all            */
 /*      consumed, advance to the next file.                             */
@@ -514,7 +504,7 @@ const char *OGRNTFDataSource::GetOption( const char * pszOption )
 /*      it's tilename is unique relative to all the readers already     */
 /*      assigned to this data source.  If not, a unique name is         */
 /*      selected for it and assigned.  This method should not be        */
-/*      called with readers that are allready attached to the data      */
+/*      called with readers that are already attached to the data      */
 /*      source.                                                         */
 /************************************************************************/
 
@@ -532,11 +522,11 @@ void OGRNTFDataSource::EnsureTileNameUnique( NTFFileReader *poNewReader )
         if( iSequenceNumber++ == -1 )
             strncpy( szCandidateName, poNewReader->GetTileName(), 10 );
         else
-            sprintf( szCandidateName, "%010d", iSequenceNumber );
+            snprintf( szCandidateName, sizeof(szCandidateName), "%010d", iSequenceNumber );
 
         for( int iReader = 0; iReader < nNTFFileCount && bIsUnique; iReader++ )
         {
-            if( strcmp( szCandidateName, 
+            if( strcmp( szCandidateName,
                         GetFileReader( iReader )->GetTileName() ) == 0 )
                 bIsUnique = FALSE;
         }
@@ -545,7 +535,7 @@ void OGRNTFDataSource::EnsureTileNameUnique( NTFFileReader *poNewReader )
     if( iSequenceNumber > 0 )
     {
         poNewReader->OverrideTileName( szCandidateName );
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "Forcing TILE_REF to `%s' on file %s\n"
                   "to avoid conflict with other tiles in this data source.",
                   szCandidateName, poNewReader->GetFilename() );
diff --git a/ogr/ogrsf_frmts/ntf/ogrntfdriver.cpp b/ogr/ogrsf_frmts/ntf/ogrntfdriver.cpp
index c90c546..f7ca088 100644
--- a/ogr/ogrsf_frmts/ntf/ogrntfdriver.cpp
+++ b/ogr/ogrsf_frmts/ntf/ogrntfdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrntfdriver.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogrntfdriver.cpp 33105 2016-01-23 15:27:32Z rouault $
  *
  * Project:  UK NTF Reader
  * Purpose:  Implements OGRNTFDriver
@@ -30,7 +30,7 @@
 #include "ntf.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrntfdriver.cpp 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: ogrntfdriver.cpp 33105 2016-01-23 15:27:32Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -52,7 +52,7 @@ static GDALDataset *OGRNTFDriverOpen( GDALOpenInfo* poOpenInfo )
         if( poOpenInfo->nHeaderBytes < 80 )
             return NULL;
         const char* pszHeader = (const char*)poOpenInfo->pabyHeader;
-        if( !EQUALN(pszHeader,"01",2) )
+        if( !STARTS_WITH_CI(pszHeader, "01") )
             return NULL;
 
         int j;
@@ -63,7 +63,7 @@ static GDALDataset *OGRNTFDriverOpen( GDALOpenInfo* poOpenInfo )
         }
 
         if( j == 80 || pszHeader[j-1] != '%' )
-            return FALSE;
+            return NULL;
     }
 
     OGRNTFDataSource    *poDS = new OGRNTFDataSource;
@@ -80,7 +80,7 @@ static GDALDataset *OGRNTFDriverOpen( GDALOpenInfo* poOpenInfo )
         delete poDS;
         poDS = NULL;
     }
-    
+
     return poDS;
 }
 
@@ -91,22 +91,18 @@ static GDALDataset *OGRNTFDriverOpen( GDALOpenInfo* poOpenInfo )
 void RegisterOGRNTF()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "UK .NTF" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "UK .NTF" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "UK .NTF" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "UK .NTF" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_ntf.html" );
+    poDriver->SetDescription( "UK .NTF" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "UK .NTF" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_ntf.html" );
 
-        poDriver->pfnOpen = OGRNTFDriverOpen;
+    poDriver->pfnOpen = OGRNTFDriverOpen;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
 
diff --git a/ogr/ogrsf_frmts/ntf/ogrntffeatureclasslayer.cpp b/ogr/ogrsf_frmts/ntf/ogrntffeatureclasslayer.cpp
index b1b5618..620bc6d 100644
--- a/ogr/ogrsf_frmts/ntf/ogrntffeatureclasslayer.cpp
+++ b/ogr/ogrsf_frmts/ntf/ogrntffeatureclasslayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrntffeatureclasslayer.cpp 28382 2015-01-30 15:29:41Z rouault $
+ * $Id: ogrntffeatureclasslayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  UK NTF Reader
  * Purpose:  Implements OGRNTFFeatureClassLayer class.
@@ -30,7 +30,7 @@
 #include "ntf.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrntffeatureclasslayer.cpp 28382 2015-01-30 15:29:41Z rouault $");
+CPL_CVSID("$Id: ogrntffeatureclasslayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                      OGRNTFFeatureClassLayer()                       */
@@ -60,7 +60,7 @@ OGRNTFFeatureClassLayer::OGRNTFFeatureClassLayer( OGRNTFDataSource *poDSIn )
 
     oFCNum.SetWidth( 4 );
     poFeatureDefn->AddFieldDefn( &oFCNum );
-    
+
     OGRFieldDefn      oFCName( "FC_NAME", OFTString );
 
     oFCNum.SetWidth( 80 );
@@ -132,9 +132,9 @@ OGRFeature *OGRNTFFeatureClassLayer::GetFeature( GIntBig nFeatureId )
 
     if( nFeatureId < 0 || nFeatureId >= poDS->GetFCCount() )
         return NULL;
-    
+
     poDS->GetFeatureClass( (int)nFeatureId, &pszFCId, &pszFCName );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding feature.                                 */
 /* -------------------------------------------------------------------- */
@@ -143,7 +143,7 @@ OGRFeature *OGRNTFFeatureClassLayer::GetFeature( GIntBig nFeatureId )
     poFeature->SetField( 0, pszFCId );
     poFeature->SetField( 1, pszFCName );
     poFeature->SetFID( nFeatureId );
-    
+
     return poFeature;
 }
 
@@ -171,7 +171,7 @@ int OGRNTFFeatureClassLayer::TestCapability( const char * pszCap )
     if( EQUAL(pszCap,OLCRandomRead) )
         return TRUE;
 
-    else if( EQUAL(pszCap,OLCSequentialWrite) 
+    else if( EQUAL(pszCap,OLCSequentialWrite)
              || EQUAL(pszCap,OLCRandomWrite) )
         return FALSE;
 
@@ -181,6 +181,6 @@ int OGRNTFFeatureClassLayer::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCFastSpatialFilter) )
         return TRUE;
 
-    else 
+    else
         return FALSE;
 }
diff --git a/ogr/ogrsf_frmts/ntf/ogrntflayer.cpp b/ogr/ogrsf_frmts/ntf/ogrntflayer.cpp
index 9d16f42..93d19f9 100644
--- a/ogr/ogrsf_frmts/ntf/ogrntflayer.cpp
+++ b/ogr/ogrsf_frmts/ntf/ogrntflayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrntflayer.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogrntflayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  UK NTF Reader
  * Purpose:  Implements OGRNTFLayer class.
@@ -30,7 +30,7 @@
 #include "ntf.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrntflayer.cpp 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: ogrntflayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                            OGRNTFLayer()                             */
@@ -64,7 +64,7 @@ OGRNTFLayer::~OGRNTFLayer()
     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     {
         CPLDebug( "Mem", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
+                  (int) m_nFeaturesRead,
                   poFeatureDefn->GetName() );
     }
 
@@ -123,12 +123,12 @@ OGRFeature *OGRNTFLayer::GetNextFeature()
         poCurrentReader->SetFPPos( nCurrentPos, nCurrentFID );
     else
         poCurrentReader->Reset();
-        
+
 /* -------------------------------------------------------------------- */
 /*      Read features till we find one that satisfies our current       */
 /*      spatial criteria.                                               */
 /* -------------------------------------------------------------------- */
-    while( TRUE )
+    while( true )
     {
         poFeature = poCurrentReader->ReadOGRFeature( this );
         if( poFeature == NULL )
@@ -137,7 +137,7 @@ OGRFeature *OGRNTFLayer::GetNextFeature()
         m_nFeaturesRead++;
 
         if( (m_poFilterGeom == NULL
-             || poFeature->GetGeometryRef() == NULL 
+             || poFeature->GetGeometryRef() == NULL
              || FilterGeometry( poFeature->GetGeometryRef() ) )
             && (m_poAttrQuery == NULL
                 || m_poAttrQuery->Evaluate( poFeature )) )
@@ -160,7 +160,7 @@ OGRFeature *OGRNTFLayer::GetNextFeature()
             poCurrentReader->DestroyIndex();
         }
 
-        do { 
+        do {
             iCurrentReader++;
         } while( iCurrentReader < poDS->GetFileCount()
                  && !poDS->GetFileReader(iCurrentReader)->TestForLayer(this) );
@@ -188,7 +188,7 @@ int OGRNTFLayer::TestCapability( const char * pszCap )
     if( EQUAL(pszCap,OLCRandomRead) )
         return FALSE;
 
-    else if( EQUAL(pszCap,OLCSequentialWrite) 
+    else if( EQUAL(pszCap,OLCSequentialWrite)
              || EQUAL(pszCap,OLCRandomWrite) )
         return FALSE;
 
@@ -198,7 +198,7 @@ int OGRNTFLayer::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCFastSpatialFilter) )
         return FALSE;
 
-    else 
+    else
         return FALSE;
 }
 
diff --git a/ogr/ogrsf_frmts/null/ogrnulldriver.cpp b/ogr/ogrsf_frmts/null/ogrnulldriver.cpp
index 8a82dc8..b93935b 100644
--- a/ogr/ogrsf_frmts/null/ogrnulldriver.cpp
+++ b/ogr/ogrsf_frmts/null/ogrnulldriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrnulldriver.cpp 28039 2014-11-30 18:24:59Z rouault $
+ * $Id: ogrnulldriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  NULL output driver.
@@ -27,14 +27,16 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-/* NOTE: this driver is only useful for debugging and is not included in the build process */
-/* To compile it as a pluing under Linux :
+/* NOTE: this driver is only useful for debugging and is not included
+   in the build process */
+
+/* To compile it as a plugin under Linux :
     g++ -Wall -DDEBUG -fPIC -g ogr/ogrsf_frmts/null/ogrnulldriver.cpp  -shared -o ogr_NULL.so -L. -lgdal -Iport -Igcore -Iogr -Iogr/ogrsf_frmts
 */
 
 #include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: ogrnulldriver.cpp 28039 2014-11-30 18:24:59Z rouault $");
+CPL_CVSID("$Id: ogrnulldriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
 
 extern "C" void CPL_DLL RegisterOGRNULL();
 
@@ -259,7 +261,7 @@ int OGRNULLDriver::TestCapability( const char * pszCap )
 
 void RegisterOGRNULL()
 {
-    if (! GDAL_CHECK_VERSION("OGR/NULL driver"))
+    if( !GDAL_CHECK_VERSION("OGR/NULL driver") )
         return;
 
     OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( new OGRNULLDriver );
diff --git a/ogr/ogrsf_frmts/oci/drv_oci.html b/ogr/ogrsf_frmts/oci/drv_oci.html
index 35c42fb..3a17fd2 100644
--- a/ogr/ogrsf_frmts/oci/drv_oci.html
+++ b/ogr/ogrsf_frmts/oci/drv_oci.html
@@ -14,20 +14,20 @@ Oracle client libraries are available. <p>
 
 When opening a database, it's name should be specified in the form
 "OCI:userid/password at database_instance:table,table".  The list of tables
-is optional.  The database_instance portion may be omitted 
+is optional.  The database_instance portion may be omitted
 when accessing the default local database instance.<p>
 
-If the list of tables is not provided, then all tables appearing in 
+If the list of tables is not provided, then all tables appearing in
 ALL_SDO_GEOM_METADATA will be treated by OGR as layers with the table
 names as the layer names.  Non-spatial tables or spatial tables not listed
-in the ALL_SDO_GEOM_METADATA table are not accessable unless explicitly
+in the ALL_SDO_GEOM_METADATA table are not accessible unless explicitly
 listed in the datasource name.  Even in databases where all desired layers
 are in the ALL_SDO_GEOM_METADATA table, it may be desirable to list only
 the tables to be used as this can substantially reduce initialization time
 in databases with many tables.<p>
 
 If the table has an integer column called OGR_FID it will be used as the
-feature id by OGR (and it will not appear as a regular attribute).  When 
+feature id by OGR (and it will not appear as a regular attribute).  When
 loading data into Oracle Spatial OGR will always create the OGR_FID field.
 <p>
 
@@ -39,12 +39,12 @@ OGRDataSource, or the -sql command option to ogr2ogr.  Attribute query
 expressions are also passed through to Oracle.</p>
 
 <p>As well two special commands are supported via the ExecuteSQL() interface.
-These are "<b>DELLAYER:<table_name></b>" to delete a layer, 
-and "<b>VALLAYER:<table_name></b>" to apply the 
-SDO_GEOM.VALIDATE_GEOMETRY() check to a layer.  Internally these 
+These are "<b>DELLAYER:<table_name></b>" to delete a layer,
+and "<b>VALLAYER:<table_name></b>" to apply the
+SDO_GEOM.VALIDATE_GEOMETRY() check to a layer.  Internally these
 pseudo-commands are translated into more complex SQL commands for Oracle.</p>
 
-<p>It's also possible to request the driver to handle SQL commands with <a href="/ogr/ogr_sql.html">OGR SQL</a> engine,
+<p>It's also possible to request the driver to handle SQL commands with <a href="ogr_sql.html">OGR SQL</a> engine,
 by passing <strong>"OGRSQL"</strong> string to the ExecuteSQL() method, as name of the SQL dialect.</p>
 
 <h2>Caveats</h2>
@@ -61,10 +61,10 @@ ignored by OGR.</li>
 <li> Currently the OGR transaction semantics are not properly mapped onto
 transaction semantics in Oracle.</li>
 
-<li> If an attribute called OGR_FID exists in the schema for tables being 
+<li> If an attribute called OGR_FID exists in the schema for tables being
 read, it will be used as the FID.  Random (FID based) reads on tables without
 an identified (and indexed) FID field can be very slow.  To force use of a
-particular field name the OCI_FID configuration variable (ie. environment
+particular field name the OCI_FID configuration variable (i.e. environment
 variable) can be set to the target field name.</li>
 
 <li> Curved geometry types are converted to linestrings or linear rings in six degree segments when reading.  The driver has no support for writing curved geometries.</li>
@@ -91,7 +91,7 @@ existing database.<P>
 Upon closing the OGRDataSource newly created layers will have a spatial
 index automatically built.  At this point the USER_SDO_GEOM_METADATA table
 will also be updated with bounds for the table based on the features that
-have actually been written.  One concequence of this is that once a layer
+have actually been written.  One consequence of this is that once a layer
 has been loaded it is generally not possible to load additional features
 outside the original extents without manually modifying the DIMINFO information
 in USER_SDO_GEOM_METADATA and rebuilding the spatial index.<p>
@@ -103,8 +103,8 @@ in USER_SDO_GEOM_METADATA and rebuilding the spatial index.<p>
 <li> <b>OVERWRITE</b>: This may be "YES" to force an existing layer of the
 desired name to be destroyed before creating the requested layer.<p>
 
-<li> <b>TRUNCATE</b>: This may be "YES" to force the existing table to 
-be reused, but to first truncate all records in the table, preserving 
+<li> <b>TRUNCATE</b>: This may be "YES" to force the existing table to
+be reused, but to first truncate all records in the table, preserving
 indexes or dependencies.<p>
 
 <li> <b>LAUNDER</b>: This may be "YES" to force new fields created on this
@@ -121,13 +121,13 @@ NUMBER, INTEGER and VARCHAR2 will be used instead.  The default is "YES".<p>
 created layer.  If not set 3 is used by default.<p>
 
 <li> <b>SPATIAL_INDEX</b>: This may be set to FALSE to disable creation of a spatial
-index when a layer load is complete.  By default an index is created if 
+index when a layer load is complete.  By default an index is created if
 any of the layer features have valid geometries. The default is "YES".
 Note: option was called INDEX in releases before GDAL 2<p>
 
 <li> <b>INDEX_PARAMETERS</b>: This may be set to pass creation parameters
-when the spatial index is created.  For instance setting INDEX_PARAMETERS to 
-SDO_LEVEL=5 would cause a 5 level tile index to be used.  By default no 
+when the spatial index is created.  For instance setting INDEX_PARAMETERS to
+SDO_LEVEL=5 would cause a 5 level tile index to be used.  By default no
 parameters are passed causing a default R-Tree spatial index to be created.<p>
 
 <li> <b>ADD_LAYER_GTYPE</b>=YES/NO: (starting with GDAL 2.0) This may be
@@ -156,21 +156,21 @@ row will be added to this table.  The SRID creation option allows the user
 to force use of an existing Oracle SRID item even it if does not exactly
 match the WKT the driver expects.<p>
 
-<li> <b>MULTI_LOAD</b>: If enabled new features will be created in 
+<li> <b>MULTI_LOAD</b>: If enabled new features will be created in
 groups of 100 per SQL INSERT command, instead of each feature being a separate
 INSERT command.  Having this enabled is the fastest way to load data quickly.
-Multi-load mode is enabled by default, and may be forced off for existing 
+Multi-load mode is enabled by default, and may be forced off for existing
 layers or for new layers by setting to NO.<p>
 
 <li> <b>LOADER_FILE</b>: If this option is set, all feature information will
 be written to a file suitable for use with SQL*Loader instead of inserted
 directly in the database.  The layer itself is still created in the database
-immediately.  The SQL*Loader support is experimental, and generally 
-MULTI_LOAD enabled mode should be used instead when trying for optimal 
+immediately.  The SQL*Loader support is experimental, and generally
+MULTI_LOAD enabled mode should be used instead when trying for optimal
 load performance.<p>
 
-<li> <b>GEOMETRY_NAME</b>: By default OGR creates new tables with the 
-geometry column named ORA_GEOMETRY.  If you wish to use a different name, 
+<li> <b>GEOMETRY_NAME</b>: By default OGR creates new tables with the
+geometry column named ORA_GEOMETRY.  If you wish to use a different name,
 it can be supplied with the GEOMETRY_NAME layer creation option.<p>
 
 </ul>
@@ -195,7 +195,7 @@ of the desired name exists it is overwritten.<p>
         -lco OVERWRITE=yes -nln polbndl_bnd 'polbndl at bnd(*)_line'
 </pre>
 
-This example shows using ogrinfo to evaluate an SQL query statement 
+This example shows using ogrinfo to evaluate an SQL query statement
 within Oracle.  More sophisticated Oracle Spatial specific queries may also be
 used via the -sql commandline switch to ogrinfo.<p>
 
diff --git a/ogr/ogrsf_frmts/oci/fastload.cpp b/ogr/ogrsf_frmts/oci/fastload.cpp
index d734782..7a7bad4 100644
--- a/ogr/ogrsf_frmts/oci/fastload.cpp
+++ b/ogr/ogrsf_frmts/oci/fastload.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: fastload.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: fastload.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Test mainline for fast loading.
@@ -35,7 +35,7 @@ int main()
 {
     OGROCISession oSession;
 
-    if( !oSession.EstablishSession( "warmerda", "LetoKing", 
+    if( !oSession.EstablishSession( "warmerda", "LetoKing",
                                     "gdal800.dreadfest.com" ) )
     {
         exit( 1 );
@@ -46,18 +46,19 @@ int main()
     OGROCIStatement oStatement( &oSession );
 
     oStatement.Execute( "DROP TABLE fasttest" );
-    oStatement.Execute( "CREATE TABLE fasttest (ifld INTEGER, cfld VARCHAR(4000), shape mdsys.sdo_geometry)" );
+    oStatement.Execute( "CREATE TABLE fasttest (ifld INTEGER, "
+                        "cfld VARCHAR(4000), shape mdsys.sdo_geometry)" );
 //    oStatement.Execute( "CREATE TABLE fasttest (ifld INTEGER, cfld VARCHAR(4000))" );
 
 /* -------------------------------------------------------------------- */
 /*      Prepare insert statement.                                       */
 /* -------------------------------------------------------------------- */
-    
+
     oStatement.Prepare( "INSERT INTO fasttest VALUES "
                         "(:field_1, :field_2, :field_3)" );
 //    oStatement.Prepare( "INSERT INTO fasttest VALUES "
 //                        "(:field_1, :field_2)" );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Do a conventional bind.                                         */
 /* -------------------------------------------------------------------- */
@@ -78,14 +79,14 @@ int main()
     memset( aoGeometries, 0, sizeof(SDO_GEOMETRY) * 100 );
     memset( aoGeometryIndicators, 0, sizeof(SDO_GEOMETRY_ind) * 100 );
 
-    if( oStatement.BindScalar( ":field_1", anField1, 
+    if( oStatement.BindScalar( ":field_1", anField1,
                               sizeof(int), SQLT_INT ) != CE_None )
         exit( 1 );
-    
+
     if( oStatement.BindScalar( ":field_2", szField2, 4, SQLT_STR ) != CE_None )
         exit( 1 );
 
-    if( oStatement.BindObject( ":field_3", apoGeomMap, oSession.hGeometryTDO, 
+    if( oStatement.BindObject( ":field_3", apoGeomMap, oSession.hGeometryTDO,
                                (void**)apoGeomIndMap ) != CE_None )
         exit( 1 );
 
@@ -96,18 +97,18 @@ int main()
     for( iBindRow = 0; iBindRow < 100; iBindRow++ )
     {
         if( oSession.Failed(
-                OCIObjectNew( oSession.hEnv, oSession.hError, 
+                OCIObjectNew( oSession.hEnv, oSession.hError,
                               oSession.hSvcCtx, OCI_TYPECODE_VARRAY,
-                              oSession.hElemInfoTDO, (dvoid *)NULL, 
+                              oSession.hElemInfoTDO, (dvoid *)NULL,
                               OCI_DURATION_SESSION,
                               FALSE, (dvoid **) (aphElemInfos + iBindRow)),
                 "OCIObjectNew()") )
             exit( 1 );
 
         if( oSession.Failed(
-                OCIObjectNew( oSession.hEnv, oSession.hError, 
+                OCIObjectNew( oSession.hEnv, oSession.hError,
                               oSession.hSvcCtx, OCI_TYPECODE_VARRAY,
-                              oSession.hOrdinatesTDO, (dvoid *)NULL, 
+                              oSession.hOrdinatesTDO, (dvoid *)NULL,
                               OCI_DURATION_SESSION,
                               FALSE, (dvoid **) (aphOrdinates + iBindRow)),
                 "OCIObjectNew()") )
@@ -121,7 +122,7 @@ int main()
 
     for( iRow = 0; iRow < 100; iRow++ )
     {
-        anField1[iRow] = iRow;                                         
+        anField1[iRow] = iRow;
         sprintf( szField2 + iRow*4, "%3d", iRow );
         anGType[iRow] = 3001;
         anSRID[iRow] = -1;
@@ -130,19 +131,19 @@ int main()
 
         //---------------------------------------------------------------
         int anElemInfo[3], nElemInfoCount;
-        OCINumber oci_number; 
+        OCINumber oci_number;
         int i;
-        
+
         nElemInfoCount = 3;
         anElemInfo[0] = 1;
         anElemInfo[1] = 1;
         anElemInfo[2] = 1;
 
-        // Prepare the VARRAY of ordinate values. 
+        // Prepare the VARRAY of ordinate values.
         for (i = 0; i < nElemInfoCount; i++)
         {
-            if( oSession.Failed( 
-                OCINumberFromInt( oSession.hError, 
+            if( oSession.Failed(
+                OCINumberFromInt( oSession.hError,
                                   (dvoid *) (anElemInfo + i),
                                   (uword)sizeof(int),
                                   OCI_NUMBER_SIGNED,
@@ -150,7 +151,7 @@ int main()
                 "OCINumberFromInt") )
                 exit( 1 );
 
-            if( oSession.Failed( 
+            if( oSession.Failed(
                 OCICollAppend( oSession.hEnv, oSession.hError,
                                (dvoid *) &oci_number,
                                (dvoid *)0, aphElemInfos[iRow]),
@@ -170,18 +171,18 @@ int main()
         adfOrdinates[4] = iRow - 100;
         adfOrdinates[5] = 0.0;
 
-        // Prepare the VARRAY of ordinate values. 
+        // Prepare the VARRAY of ordinate values.
         for (i = 0; i < nOrdCount; i++)
         {
-            if( oSession.Failed( 
-                OCINumberFromReal( oSession.hError, 
+            if( oSession.Failed(
+                OCINumberFromReal( oSession.hError,
                                   (dvoid *) (adfOrdinates + i),
                                   (uword)sizeof(double),
                                   &oci_number),
                 "OCINumberFromReal") )
                 exit( 1 );
 
-            if( oSession.Failed( 
+            if( oSession.Failed(
                 OCICollAppend( oSession.hEnv, oSession.hError,
                                (dvoid *) &oci_number,
                                (dvoid *)0, aphOrdinates[iRow]),
@@ -195,8 +196,8 @@ int main()
 
         poInd->sdo_point._atomic = OCI_IND_NULL;
 
-        if( oSession.Failed( 
-                OCINumberFromInt( oSession.hError, 
+        if( oSession.Failed(
+                OCINumberFromInt( oSession.hError,
                                   (dvoid *) (anGType + iRow),
                                   (uword)sizeof(int),
                                   OCI_NUMBER_SIGNED,
@@ -204,8 +205,8 @@ int main()
                 "OCINumberFromInt" ) )
             exit( 1 );
 
-        if( oSession.Failed( 
-                OCINumberFromInt( oSession.hError, 
+        if( oSession.Failed(
+                OCINumberFromInt( oSession.hError,
                                   (dvoid *) (anSRID + iRow),
                                   (uword)sizeof(int),
                                   OCI_NUMBER_SIGNED,
@@ -227,10 +228,10 @@ int main()
 
     for( iGroup = 0; iGroup < 2; iGroup++ )
     {
-        if( oSession.Failed( 
-                OCIStmtExecute( oSession.hSvcCtx, oStatement.GetStatement(), 
-                                oSession.hError, (ub4) 100, (ub4)0, 
-                                (OCISnapshot *)NULL, (OCISnapshot *)NULL, 
+        if( oSession.Failed(
+                OCIStmtExecute( oSession.hSvcCtx, oStatement.GetStatement(),
+                                oSession.hError, (ub4) 100, (ub4)0,
+                                (OCISnapshot *)NULL, (OCISnapshot *)NULL,
                                 (ub4) OCI_COMMIT_ON_SUCCESS ),
                 "OCIStmtExecute" ) )
             exit( 1 );
diff --git a/ogr/ogrsf_frmts/oci/ocitest.cpp b/ogr/ogrsf_frmts/oci/ocitest.cpp
index c9a9c9c..fbbcb3b 100644
--- a/ogr/ogrsf_frmts/oci/ocitest.cpp
+++ b/ogr/ogrsf_frmts/oci/ocitest.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ocitest.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: ocitest.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Test mainline for Oracle Spatial Driver low level functions.
@@ -30,7 +30,7 @@
 #include "ogr_oci.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ocitest.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: ocitest.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                                main()                                */
@@ -65,13 +65,9 @@ int main( int nArgc, char ** papszArgv )
         printf( "\n" );
         for( i = 0; i < nColCount; i++ )
         {
-            printf( "  %s = %s\n", 
+            printf( "  %s = %s\n",
                     poDefn->GetFieldDefn(i)->GetNameRef(),
                     papszResult[i] );
         }
     }
 }
-
-
-
-
diff --git a/ogr/ogrsf_frmts/oci/ogr_oci.h b/ogr/ogrsf_frmts/oci/ogr_oci.h
index 6e8a134..8808012 100644
--- a/ogr/ogrsf_frmts/oci/ogr_oci.h
+++ b/ogr/ogrsf_frmts/oci/ogr_oci.h
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: ogr_oci.h 29019 2015-04-25 20:34:19Z rouault $
+ * $Id: ogr_oci.h 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Oracle Spatial Driver
- * Purpose:  Oracle Spatial OGR Driver Declarations. 
+ * Purpose:  Oracle Spatial OGR Driver Declarations.
  * Author:   Frank Warmerdam <warmerdam at pobox.com>
  *
  ******************************************************************************
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_OCI_H_INCLUDED
-#define _OGR_OCI_H_INCLUDED
+#ifndef OGR_OCI_H_INCLUDED
+#define OGR_OCI_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "oci.h"
@@ -40,7 +40,7 @@
 #define TYPE_OWNER                 "MDSYS"
 #define SDO_GEOMETRY               "MDSYS.SDO_GEOMETRY"
 
-typedef struct 
+typedef struct
 {
    OCINumber x;
    OCINumber y;
@@ -83,7 +83,7 @@ typedef struct
 #define ORA_GTYPE_LINESTRING      2    // or curve
 #define ORA_GTYPE_POLYGON         3    // or surface
 #define ORA_GTYPE_COLLECTION      4
-#define ORA_GTYPE_MULTIPOINT      5 
+#define ORA_GTYPE_MULTIPOINT      5
 #define ORA_GTYPE_MULTILINESTRING 6    // or multicurve
 #define ORA_GTYPE_MULTIPOLYGON    7    // or multisurface
 #define ORA_GTYPE_SOLID           8
@@ -108,7 +108,7 @@ class CPL_DLL OGROCISession {
     char       *pszUserid;
     char       *pszPassword;
     char       *pszDatabase;
-    
+
   public:
              OGROCISession();
     virtual ~OGROCISession();
@@ -118,7 +118,7 @@ class CPL_DLL OGROCISession {
                                const char *pszDatabase );
 
     int      Failed( sword nStatus, const char *pszFunction = NULL );
-        
+
     CPLErr   GetParmInfo( OCIParam *hParmDesc, OGRFieldDefn *poOGRDefn,
                           ub2 *pnOCIType, ub4 *pnOCILen );
 
@@ -127,7 +127,7 @@ class CPL_DLL OGROCISession {
     OCIType *PinTDO( const char * );
 
   private:
-    
+
 };
 
 OGROCISession CPL_DLL*
@@ -144,7 +144,7 @@ class CPL_DLL OGROCIStatement {
     virtual     ~OGROCIStatement();
 
     OCIStmt     *GetStatement() { return hStatement; }
-    CPLErr       BindScalar( const char *pszPlaceName, 
+    CPLErr       BindScalar( const char *pszPlaceName,
                              void *pData, int nDataLen, int nSQLType,
                              sb2 *paeInd = NULL );
     CPLErr       BindObject( const char *pszPlaceName, void *pahObject,
@@ -156,14 +156,14 @@ class CPL_DLL OGROCIStatement {
     CPLErr       Execute( const char * pszStatement,
                           int nMode = -1 );
     void         Clean();
-    
+
     OGRFeatureDefn *GetResultDefn() { return poDefn; }
 
     char       **SimpleFetchRow();
-    
+
     int          GetAffectedRows() const { return nAffectedRows; }
 
-  private:    
+  private:
     OGROCISession *poSession;
     OCIStmt       *hStatement;
 
@@ -181,7 +181,7 @@ class CPL_DLL OGROCIStatement {
 /************************************************************************/
 /*                           OGROCIStringBuf                            */
 /************************************************************************/
-class OGROCIStringBuf 
+class OGROCIStringBuf
 {
   char *pszString;
   int  nLen;
@@ -211,7 +211,7 @@ public:
 /************************************************************************/
 
 class OGROCIDataSource;
-    
+
 class OGROCILayer : public OGRLayer
 {
   protected:
@@ -246,7 +246,7 @@ class OGROCILayer : public OGRLayer
                                                   int nStartOrdinal,
                                                   int nOrdCount);
     int      LoadElementInfo( int iElement, int nElemCount, int nTotalOrdCount,
-                              int *pnEType, int *pnInterpretation, 
+                              int *pnEType, int *pnInterpretation,
                               int *pnStartOrdinal, int *pnElemOrdCount );
     int                 GetOrdinalPoint( int iOrdinal, int nDimension,
                                          double *pdfX, double *pdfY,
@@ -322,9 +322,9 @@ public:
     void                SetOptions( char ** );
 
     void                SetDimension( int );
-    void                SetLaunderFlag( int bFlag ) 
+    void                SetLaunderFlag( int bFlag )
                                 { bLaunderColumnNames = bFlag; }
-    void                SetPrecisionFlag( int bFlag ) 
+    void                SetPrecisionFlag( int bFlag )
                                 { bPreservePrecision = bFlag; }
 };
 
@@ -343,7 +343,7 @@ class OGROCILoaderLayer : public OGROCIWritableLayer
     int                 iNextFIDToWrite;
 
     char                *pszLoaderFilename;
-    
+
     FILE                *fpLoader;
     int                 bHeaderWritten;
 
@@ -361,8 +361,8 @@ class OGROCILoaderLayer : public OGROCIWritableLayer
   public:
                         OGROCILoaderLayer( OGROCIDataSource *,
                                            const char * pszName,
-                                           const char *pszGeomCol, 
-                                           int nSRID, 
+                                           const char *pszGeomCol,
+                                           int nSRID,
                                            const char *pszLoaderFile );
                         ~OGROCILoaderLayer();
 
@@ -370,14 +370,16 @@ class OGROCILoaderLayer : public OGROCIWritableLayer
     virtual GIntBig     GetFeatureCount( int );
 
     virtual void        SetSpatialFilter( OGRGeometry * ) {}
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+                { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
 
-    virtual OGRErr      SetAttributeFilter( const char * ) 
+    virtual OGRErr      SetAttributeFilter( const char * )
                                 { return OGRERR_UNSUPPORTED_OPERATION; }
 
     virtual OGRFeature *GetNextFeature();
 
     virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
-    
+
     virtual OGRSpatialReference *GetSpatialRef() { return poSRS; }
 
     virtual int         TestCapability( const char * );
@@ -420,7 +422,7 @@ class OGROCITableLayer : public OGROCIWritableLayer
 
     void                TestForSpatialIndex( const char * );
 
-    OGROCIStatement   *poBoundStatement; 
+    OGROCIStatement   *poBoundStatement;
 
     int                 nWriteCacheMax;
     int                 nWriteCacheUsed;
@@ -429,7 +431,7 @@ class OGROCITableLayer : public OGROCIWritableLayer
     SDO_GEOMETRY_TYPE **papsWriteGeomMap;
     SDO_GEOMETRY_ind   *pasWriteGeomInd;
     SDO_GEOMETRY_ind  **papsWriteGeomIndMap;
-    
+
     void              **papWriteFields;
     OCIInd            **papaeWriteFieldInd;
     int                *panWriteFIDs;
@@ -450,6 +452,8 @@ class OGROCITableLayer : public OGROCIWritableLayer
     virtual GIntBig     GetFeatureCount( int );
 
     virtual void        SetSpatialFilter( OGRGeometry * );
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+                { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
 
     virtual OGRErr      SetAttributeFilter( const char * );
 
@@ -459,8 +463,10 @@ class OGROCITableLayer : public OGROCIWritableLayer
     virtual OGRErr      ISetFeature( OGRFeature *poFeature );
     virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
     virtual OGRErr      DeleteFeature( GIntBig nFID );
-    
+
     virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
     virtual int         TestCapability( const char * );
 
@@ -495,7 +501,7 @@ class OGROCIDataSource : public OGRDataSource
 {
     OGROCILayer       **papoLayers;
     int                 nLayers;
-    
+
     char               *pszName;
     char               *pszDBName;
 
@@ -504,11 +510,11 @@ class OGROCIDataSource : public OGRDataSource
     OGROCISession      *poSession;
 
     // We maintain a list of known SRID to reduce the number of trips to
-    // the database to get SRSes. 
+    // the database to get SRSes.
     int                 nKnownSRID;
     int                *panSRID;
     OGRSpatialReference **papoSRS;
-    
+
   public:
                         OGROCIDataSource();
                         ~OGROCIDataSource();
@@ -517,7 +523,7 @@ class OGROCIDataSource : public OGRDataSource
 
     int                 Open( const char *, char** papszOpenOptions,
                               int bUpdate, int bTestOpen );
-    int                 OpenTable( const char *pszTableName, 
+    int                 OpenTable( const char *pszTableName,
                                    int nSRID, int bUpdate, int bTestOpen );
 
     const char          *GetName() { return pszName; }
@@ -526,7 +532,7 @@ class OGROCIDataSource : public OGRDataSource
     OGRLayer            *GetLayerByName(const char * pszName);
 
     virtual OGRErr      DeleteLayer(int);
-    virtual OGRLayer    *ICreateLayer( const char *, 
+    virtual OGRLayer    *ICreateLayer( const char *,
                                       OGRSpatialReference * = NULL,
                                       OGRwkbGeometryType = wkbUnknown,
                                       char ** = NULL );
@@ -537,7 +543,7 @@ class OGROCIDataSource : public OGRDataSource
 
     void                TruncateLayer( const char * );
     void                ValidateLayer( const char * );
-    
+
     virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
                                     OGRGeometry *poSpatialFilter,
                                     const char *pszDialect );
@@ -550,7 +556,7 @@ class OGROCIDataSource : public OGRDataSource
 /* -------------------------------------------------------------------- */
 /*      Helper functions.                                               */
 /* -------------------------------------------------------------------- */
-int 
+int
 OGROCIStrokeArcToOGRGeometry_Points( double dfStartX, double dfStartY,
                                      double dfAlongX, double dfAlongY,
                                      double dfEndX, double dfEndY,
@@ -559,4 +565,4 @@ OGROCIStrokeArcToOGRGeometry_Points( double dfStartX, double dfStartY,
                                      OGRLineString *poLine );
 
 
-#endif /* ndef _OGR_OCI_H_INCLUDED */
+#endif /* ndef OGR_OCI_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/oci/ogrocidatasource.cpp b/ogr/ogrsf_frmts/oci/ogrocidatasource.cpp
index 2e4159c..a4301fe 100644
--- a/ogr/ogrsf_frmts/oci/ogrocidatasource.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrocidatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrocidatasource.cpp 29019 2015-04-25 20:34:19Z rouault $
+ * $Id: ogrocidatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Implementation of the OGROCIDataSource class.
@@ -31,12 +31,12 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrocidatasource.cpp 29019 2015-04-25 20:34:19Z rouault $");
+CPL_CVSID("$Id: ogrocidatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
-static int anEPSGOracleMapping[] = 
+static const int anEPSGOracleMapping[] =
 {
     /* Oracle SRID, EPSG GCS/PCS Code */
-    
+
     8192, 4326, // WGS84
     8306, 4322, // WGS72
     8267, 4269, // NAD83
@@ -79,7 +79,7 @@ OGROCIDataSource::~OGROCIDataSource()
 
     for( i = 0; i < nLayers; i++ )
         delete papoLayers[i];
-    
+
     CPLFree( papoLayers );
 
     for( i = 0; i < nKnownSRID; i++ )
@@ -98,7 +98,7 @@ OGROCIDataSource::~OGROCIDataSource()
 /************************************************************************/
 
 int OGROCIDataSource::Open( const char * pszNewName,
-                            char** papszOpenOptions,
+                            char** papszOpenOptionsIn,
                             int bUpdate,
                             int bTestOpen )
 
@@ -108,11 +108,11 @@ int OGROCIDataSource::Open( const char * pszNewName,
 /* -------------------------------------------------------------------- */
 /*      Verify Oracle prefix.                                           */
 /* -------------------------------------------------------------------- */
-    if( !EQUALN(pszNewName,"OCI:",3) )
+    if( !STARTS_WITH_CI(pszNewName,"OCI:") )
     {
         if( !bTestOpen )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "%s does not conform to Oracle OCI driver naming convention,"
                       " OCI:*\n", pszNewName );
         }
@@ -130,10 +130,10 @@ int OGROCIDataSource::Open( const char * pszNewName,
 
     if( pszNewName[4] == '\0' )
     {
-        pszUserid = CPLStrdup(CSLFetchNameValueDef(papszOpenOptions, "USER", ""));
-        pszPassword = CSLFetchNameValueDef(papszOpenOptions, "PASSWORD", "");
-        pszDatabase = CSLFetchNameValueDef(papszOpenOptions, "DBNAME", "");
-        const char* pszTables = CSLFetchNameValue(papszOpenOptions, "TABLES");
+        pszUserid = CPLStrdup(CSLFetchNameValueDef(papszOpenOptionsIn, "USER", ""));
+        pszPassword = CSLFetchNameValueDef(papszOpenOptionsIn, "PASSWORD", "");
+        pszDatabase = CSLFetchNameValueDef(papszOpenOptionsIn, "DBNAME", "");
+        const char* pszTables = CSLFetchNameValue(papszOpenOptionsIn, "TABLES");
         if( pszTables )
             papszTableList = CSLTokenizeStringComplex(pszTables, ",", TRUE, FALSE );
     }
@@ -141,8 +141,8 @@ int OGROCIDataSource::Open( const char * pszNewName,
     {
         pszUserid = CPLStrdup( pszNewName + 4 );
 
-        // Is there a table list? 
-        for( i = strlen(pszUserid)-1; i > 1; i-- )
+        // Is there a table list?
+        for( i = static_cast<int>(strlen(pszUserid))-1; i > 1; i-- )
         {
             if( pszUserid[i] == ':' )
             {
@@ -156,7 +156,7 @@ int OGROCIDataSource::Open( const char * pszNewName,
                 break;
         }
 
-        for( i = 0; 
+        for( i = 0;
             pszUserid[i] != '\0' && pszUserid[i] != '/' && pszUserid[i] != '@';
             i++ ) {}
 
@@ -177,7 +177,7 @@ int OGROCIDataSource::Open( const char * pszNewName,
 /* -------------------------------------------------------------------- */
 /*      Try to establish connection.                                    */
 /* -------------------------------------------------------------------- */
-    CPLDebug( "OCI", "Userid=%s, Password=%s, Database=%s", 
+    CPLDebug( "OCI", "Userid=%s, Password=%s, Database=%s",
               pszUserid, pszPassword, pszDatabase );
 
     if( EQUAL(pszDatabase, "") &&
@@ -201,7 +201,7 @@ int OGROCIDataSource::Open( const char * pszNewName,
     }
 
     pszName = CPLStrdup( pszNewName );
-    
+
     bDSUpdate = bUpdate;
 
 /* -------------------------------------------------------------------- */
@@ -212,8 +212,8 @@ int OGROCIDataSource::Open( const char * pszNewName,
     {
         OGROCIStatement oGetTables( poSession );
 
-        if( oGetTables.Execute( 
-            "SELECT TABLE_NAME, OWNER FROM ALL_SDO_GEOM_METADATA" ) 
+        if( oGetTables.Execute(
+            "SELECT TABLE_NAME, OWNER FROM ALL_SDO_GEOM_METADATA" )
             == CE_None )
         {
             char **papszRow;
@@ -225,11 +225,11 @@ int OGROCIDataSource::Open( const char * pszNewName,
                 if( EQUAL(papszRow[1],pszUserid) )
                     strcpy( szFullTableName, papszRow[0] );
                 else
-                    sprintf( szFullTableName, "%s.%s", 
+                    snprintf( szFullTableName, sizeof(szFullTableName), "%s.%s",
                              papszRow[1], papszRow[0] );
 
                 if( CSLFindString( papszTableList, szFullTableName ) == -1 )
-                    papszTableList = CSLAddString( papszTableList, 
+                    papszTableList = CSLAddString( papszTableList,
                                                    szFullTableName );
             }
         }
@@ -253,8 +253,8 @@ int OGROCIDataSource::Open( const char * pszNewName,
 /*                             OpenTable()                              */
 /************************************************************************/
 
-int OGROCIDataSource::OpenTable( const char *pszNewName, 
-                                 int nSRID, int bUpdate, int bTestOpen )
+int OGROCIDataSource::OpenTable( const char *pszNewName,
+                                 int nSRID, int bUpdate, CPL_UNUSED int bTestOpen )
 
 {
 /* -------------------------------------------------------------------- */
@@ -262,7 +262,7 @@ int OGROCIDataSource::OpenTable( const char *pszNewName,
 /* -------------------------------------------------------------------- */
     OGROCITableLayer    *poLayer;
 
-    poLayer = new OGROCITableLayer( this, pszNewName, wkbUnknown, nSRID, 
+    poLayer = new OGROCITableLayer( this, pszNewName, wkbUnknown, nSRID,
                                     bUpdate, FALSE );
 
     if( !poLayer->IsValid() )
@@ -301,8 +301,8 @@ void OGROCIDataSource::ValidateLayer( const char *pszLayerName )
 
     if( iLayer == nLayers )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "ValidateLayer(): %s is not a recognised layer.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "ValidateLayer(): %s is not a recognised layer.",
                   pszLayerName );
         return;
     }
@@ -314,8 +314,8 @@ void OGROCIDataSource::ValidateLayer( const char *pszLayerName )
 
     if( strlen(poLayer->GetFIDColumn()) == 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "ValidateLayer(): %s lacks a fid column.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "ValidateLayer(): %s lacks a fid column.",
                   pszLayerName );
 
         return;
@@ -325,7 +325,7 @@ void OGROCIDataSource::ValidateLayer( const char *pszLayerName )
 /*      Prepare and execute the geometry validation.                    */
 /* -------------------------------------------------------------------- */
 
-    if( !strlen(poLayer->GetGeometryColumn()) == 0 )
+    if( strlen(poLayer->GetGeometryColumn()) != 0 )
     {
         OGROCIStringBuf oValidateCmd;
         OGROCIStatement oValidateStmt( GetSession() );
@@ -379,13 +379,13 @@ OGRErr OGROCIDataSource::DeleteLayer( int iLayer )
 /*      Blow away our OGR structures related to the layer.  This is     */
 /*      pretty dangerous if anything has a reference to this layer!     */
 /* -------------------------------------------------------------------- */
-    CPLString osLayerName = 
+    CPLString osLayerName =
         papoLayers[iLayer]->GetLayerDefn()->GetName();
 
     CPLDebug( "OCI", "DeleteLayer(%s)", osLayerName.c_str() );
 
     delete papoLayers[iLayer];
-    memmove( papoLayers + iLayer, papoLayers + iLayer + 1, 
+    memmove( papoLayers + iLayer, papoLayers + iLayer + 1,
              sizeof(void *) * (nLayers - iLayer - 1) );
     nLayers--;
 
@@ -400,7 +400,7 @@ OGRErr OGROCIDataSource::DeleteLayer( int iLayer )
     if( oCommand.Execute( osCommand ) != CE_None )
         nFailures++;
 
-    osCommand.Printf( 
+    osCommand.Printf(
         "DELETE FROM USER_SDO_GEOM_METADATA WHERE TABLE_NAME = UPPER('%s')",
         osLayerName.c_str() );
 
@@ -455,7 +455,7 @@ void OGROCIDataSource::TruncateLayer( const char *pszLayerName )
 /*      Set OGR Debug statement explaining what is happening            */
 /* -------------------------------------------------------------------- */
     CPLDebug( "OCI", "Truncate TABLE %s", pszLayerName );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Truncate the layer in the database.                             */
 /* -------------------------------------------------------------------- */
@@ -482,21 +482,20 @@ OGROCIDataSource::ICreateLayer( const char * pszLayerName,
 
     poSession->CleanName( pszSafeLayerName );
     CPLDebug( "OCI", "In Create Layer ..." );
-              
 
 /* -------------------------------------------------------------------- */
 /*      Do we already have this layer?  If so, should we blow it        */
 /*      away?                                                           */
 /* -------------------------------------------------------------------- */
     int iLayer;
-    
+
     if( CSLFetchBoolean( papszOptions, "TRUNCATE", FALSE ) )
     {
         CPLDebug( "OCI", "Calling TruncateLayer for %s", pszLayerName );
         TruncateLayer( pszSafeLayerName );
     }
     else
-    {  
+    {
         for( iLayer = 0; iLayer < nLayers; iLayer++ )
         {
             if( EQUAL(pszSafeLayerName,
@@ -509,17 +508,17 @@ OGROCIDataSource::ICreateLayer( const char * pszLayerName,
                 }
                 else
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined, 
+                    CPLError( CE_Failure, CPLE_AppDefined,
                               "Layer %s already exists, CreateLayer failed.\n"
                               "Use the layer creation option OVERWRITE=YES to "
                               "replace it.",
                               pszSafeLayerName );
                     CPLFree( pszSafeLayerName );
                     return NULL;
-                }              
+                }
             }
         }
-    } 
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Try to get the SRS Id of this spatial reference system,         */
@@ -528,16 +527,16 @@ OGROCIDataSource::ICreateLayer( const char * pszLayerName,
     char szSRSId[100];
 
     if( CSLFetchNameValue( papszOptions, "SRID" ) != NULL )
-        strcpy( szSRSId, CSLFetchNameValue( papszOptions, "SRID" ) );     
+        strcpy( szSRSId, CSLFetchNameValue( papszOptions, "SRID" ) );
     else if( poSRS != NULL )
-        sprintf( szSRSId, "%d", FetchSRSId( poSRS ) );
+        snprintf( szSRSId, sizeof(szSRSId), "%d", FetchSRSId( poSRS ) );
     else
         strcpy( szSRSId, "NULL" );
 
 /* -------------------------------------------------------------------- */
 /*      Determine name of geometry column to use.                       */
 /* -------------------------------------------------------------------- */
-    const char *pszGeometryName = 
+    const char *pszGeometryName =
         CSLFetchNameValue( papszOptions, "GEOMETRY_NAME" );
     if( pszGeometryName == NULL )
         pszGeometryName = "ORA_GEOMETRY";
@@ -547,27 +546,27 @@ OGROCIDataSource::ICreateLayer( const char * pszLayerName,
 /*      Create a basic table with the FID.  Also include the            */
 /*      geometry if this is not a PostGIS enabled table.                */
 /* -------------------------------------------------------------------- */
-    const char *pszExpectedFIDName = 
-        CPLGetConfigOption( "OCI_FID", "OGR_FID" );    
-   
+    const char *pszExpectedFIDName =
+        CPLGetConfigOption( "OCI_FID", "OGR_FID" );
+
     OGROCIStatement oStatement( poSession );
 
 /* -------------------------------------------------------------------- */
-/*      If geometry type is wkbNone, do not create a geoemtry column    */
+/*      If geometry type is wkbNone, do not create a geometry column.   */
 /* -------------------------------------------------------------------- */
 
     if ( CSLFetchNameValue( papszOptions, "TRUNCATE" ) == NULL  )
     {
         if (eType == wkbNone)
         {
-            sprintf( szCommand,
+            snprintf( szCommand, sizeof(szCommand),
                      "CREATE TABLE \"%s\" ( "
                      "%s INTEGER PRIMARY KEY)",
                      pszSafeLayerName, pszExpectedFIDName);
         }
         else
         {
-            sprintf( szCommand,
+            snprintf( szCommand, sizeof(szCommand),
                      "CREATE TABLE \"%s\" ( "
                      "%s INTEGER PRIMARY KEY, "
                      "%s %s%s )",
@@ -581,7 +580,7 @@ OGROCIDataSource::ICreateLayer( const char * pszLayerName,
             CPLFree( pszSafeLayerName );
             return NULL;
         }
-    }  
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Create the layer object.                                        */
@@ -594,8 +593,8 @@ OGROCIDataSource::ICreateLayer( const char * pszLayerName,
                                         EQUAL(szSRSId,"NULL") ? -1 : atoi(szSRSId),
                                         TRUE, TRUE );
     else
-        poLayer = 
-            new OGROCILoaderLayer( this, pszSafeLayerName, 
+        poLayer =
+            new OGROCILoaderLayer( this, pszSafeLayerName,
                                    pszGeometryName,
                                    EQUAL(szSRSId,"NULL") ? -1 : atoi(szSRSId),
                                    pszLoaderFile );
@@ -618,7 +617,7 @@ OGROCIDataSource::ICreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
     papoLayers = (OGROCILayer **)
         CPLRealloc( papoLayers,  sizeof(OGROCILayer *) * (nLayers+1) );
-    
+
     papoLayers[nLayers++] = poLayer;
 
     CPLFree( pszSafeLayerName );
@@ -669,8 +668,8 @@ OGRLayer * OGROCIDataSource::ExecuteSQL( const char *pszSQLCommand,
 /*      Use generic implementation for recognized dialects              */
 /* -------------------------------------------------------------------- */
     if( IsGenericSQLDialect(pszDialect) )
-        return OGRDataSource::ExecuteSQL( pszSQLCommand, 
-                                          poSpatialFilter, 
+        return OGRDataSource::ExecuteSQL( pszSQLCommand,
+                                          poSpatialFilter,
                                           pszDialect );
 
 /* -------------------------------------------------------------------- */
@@ -683,7 +682,7 @@ OGRLayer * OGROCIDataSource::ExecuteSQL( const char *pszSQLCommand,
 /* -------------------------------------------------------------------- */
 /*      Special case DELLAYER: command.                                 */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszSQLCommand,"DELLAYER:",9) )
+    if( STARTS_WITH_CI(pszSQLCommand, "DELLAYER:") )
     {
         const char *pszLayerName = pszSQLCommand + 9;
 
@@ -697,7 +696,7 @@ OGRLayer * OGROCIDataSource::ExecuteSQL( const char *pszSQLCommand,
 /* -------------------------------------------------------------------- */
 /*      Special case VALLAYER: command.                                 */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszSQLCommand,"VALLAYER:",9) )
+    if( STARTS_WITH_CI(pszSQLCommand, "VALLAYER:") )
     {
         const char *pszLayerName = pszSQLCommand + 9;
 
@@ -711,7 +710,7 @@ OGRLayer * OGROCIDataSource::ExecuteSQL( const char *pszSQLCommand,
 /* -------------------------------------------------------------------- */
 /*      Just execute simple command.                                    */
 /* -------------------------------------------------------------------- */
-    if( !EQUALN(pszSQLCommand,"SELECT",6) )
+    if( !STARTS_WITH_CI(pszSQLCommand, "SELECT") )
     {
         OGROCIStatement oCommand( poSession );
 
@@ -726,7 +725,7 @@ OGRLayer * OGROCIDataSource::ExecuteSQL( const char *pszSQLCommand,
     else
     {
         OGROCIStatement oCommand( poSession );
-        
+
         if( oCommand.Execute( pszSQLCommand, OCI_DESCRIBE_ONLY ) == CE_None )
             return new OGROCISelectLayer( this, pszSQLCommand, &oCommand );
         else
@@ -775,7 +774,7 @@ OGRSpatialReference *OGROCIDataSource::FetchSRS( int nId )
     OGROCIStatement oStatement( GetSession() );
     char            szSelect[200], **papszResult;
 
-    sprintf( szSelect, 
+    snprintf( szSelect, sizeof(szSelect),
              "SELECT WKTEXT, AUTH_SRID, AUTH_NAME FROM MDSYS.CS_SRS "
              "WHERE SRID = %d AND WKTEXT IS NOT NULL", nId );
 
@@ -819,11 +818,11 @@ OGRSpatialReference *OGROCIDataSource::FetchSRS( int nId )
 /*      Insert authority information, if it is available.               */
 /* -------------------------------------------------------------------- */
     if( papszResult[1] != NULL && atoi(papszResult[1]) != 0
-        && papszResult[2] != NULL && strlen(papszResult[1]) != 0 
-        && poSRS->GetRoot() != NULL 
+        && papszResult[2] != NULL && strlen(papszResult[1]) != 0
+        && poSRS->GetRoot() != NULL
         && !bGotEPSGMapping )
     {
-        poSRS->SetAuthority( poSRS->GetRoot()->GetValue(), 
+        poSRS->SetAuthority( poSRS->GetRoot()->GetValue(),
                              papszResult[2], atoi(papszResult[1]) );
     }
 
@@ -831,7 +830,7 @@ OGRSpatialReference *OGROCIDataSource::FetchSRS( int nId )
 /*      Add to the cache.                                               */
 /* -------------------------------------------------------------------- */
     panSRID = (int *) CPLRealloc(panSRID,sizeof(int) * (nKnownSRID+1) );
-    papoSRS = (OGRSpatialReference **) 
+    papoSRS = (OGRSpatialReference **)
         CPLRealloc(papoSRS, sizeof(void*) * (nKnownSRID + 1) );
     panSRID[nKnownSRID] = nId;
     papoSRS[nKnownSRID] = poSRS;
@@ -881,7 +880,7 @@ int OGROCIDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 
     if( pszAuthName != NULL && pszAuthCode != NULL )
     {
-        if( EQUAL(pszAuthName,"Oracle") 
+        if( EQUAL(pszAuthName,"Oracle")
             && atoi(pszAuthCode) != 0 )
             return atoi(pszAuthCode);
 
@@ -906,7 +905,7 @@ int OGROCIDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 /*      Convert SRS into old style format (SF-SQL 1.0).                 */
 /* -------------------------------------------------------------------- */
     OGRSpatialReference *poSRS2 = poSRS->Clone();
-    
+
     poSRS2->StripCTParms();
 
 /* -------------------------------------------------------------------- */
@@ -924,9 +923,9 @@ int OGROCIDataSource::FetchSRSId( OGRSpatialReference * poSRS )
         delete poSRS2;
         return -1;
     }
-    
+
     delete poSRS2;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Try to find in the existing table.                              */
 /* -------------------------------------------------------------------- */
@@ -949,7 +948,7 @@ int OGROCIDataSource::FetchSRSId( OGRSpatialReference * poSRS )
         CPLFree( pszWKT );
         return atoi( papszResult[0] );
     }
-    
+
 /* ==================================================================== */
 /*      We didn't find it, so we need to define it as a new SRID at     */
 /*      the end of the list of known values.                            */
@@ -962,7 +961,7 @@ int OGROCIDataSource::FetchSRSId( OGRSpatialReference * poSRS )
         papszResult = oCmdStatement.SimpleFetchRow();
     else
         papszResult = NULL;
-        
+
     if( CSLCount(papszResult) == 1 )
         nSRSId = atoi(papszResult[0]) + 1;
     else
@@ -992,13 +991,13 @@ int OGROCIDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 /*                           GetLayerByName()                           */
 /************************************************************************/
 
-OGRLayer *OGROCIDataSource::GetLayerByName( const char *pszName )
+OGRLayer *OGROCIDataSource::GetLayerByName( const char *pszNameIn )
 
 {
-    OGROCILayer *poLayer;
+    OGROCILayer *poLayer = NULL;
     int  i, count;
 
-    if ( !pszName )
+    if ( !pszNameIn )
 	return NULL;
 
     count = GetLayerCount();
@@ -1008,13 +1007,13 @@ OGRLayer *OGROCIDataSource::GetLayerByName( const char *pszName )
     {
         poLayer = papoLayers[i];
 
-        if( strcmp( pszName, poLayer->GetName() ) == 0 )
+        if( strcmp( pszNameIn, poLayer->GetName() ) == 0 )
         {
             return poLayer;
         }
     }
 
-    char *pszSafeLayerName = CPLStrdup( pszName );
+    char *pszSafeLayerName = CPLStrdup( pszNameIn );
     poSession->CleanName( pszSafeLayerName );
 
     /* then case insensitive and laundered */
diff --git a/ogr/ogrsf_frmts/oci/ogrocidriver.cpp b/ogr/ogrsf_frmts/oci/ogrocidriver.cpp
index cde8882..ab0bb0e 100644
--- a/ogr/ogrsf_frmts/oci/ogrocidriver.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrocidriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrocidriver.cpp 29019 2015-04-25 20:34:19Z rouault $
+ * $Id: ogrocidriver.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Implementation of the OGROCIDriver class.
@@ -29,7 +29,7 @@
 
 #include "ogr_oci.h"
 
-CPL_CVSID("$Id: ogrocidriver.cpp 29019 2015-04-25 20:34:19Z rouault $");
+CPL_CVSID("$Id: ogrocidriver.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 
 /************************************************************************/
@@ -38,7 +38,7 @@ CPL_CVSID("$Id: ogrocidriver.cpp 29019 2015-04-25 20:34:19Z rouault $");
 
 static int OGROCIDriverIdentify( GDALOpenInfo* poOpenInfo )
 {
-    return EQUALN(poOpenInfo->pszFilename,"OCI:",4);
+    return STARTS_WITH_CI(poOpenInfo->pszFilename, "OCI:");
 }
 
 /************************************************************************/
@@ -85,7 +85,7 @@ static GDALDataset *OGROCIDriverCreate( const char * pszName,
     if( !poDS->Open( pszName, NULL, TRUE, TRUE ) )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
          "Oracle driver doesn't currently support database creation.\n"
                   "Please create database with Oracle tools before loading tables." );
         return NULL;
@@ -101,23 +101,20 @@ static GDALDataset *OGROCIDriverCreate( const char * pszName,
 void RegisterOGROCI()
 
 {
-    if (! GDAL_CHECK_VERSION("OCI driver"))
+    if( !GDAL_CHECK_VERSION("OCI driver") )
         return;
-    
-    if( GDALGetDriverByName( "OCI" ) == NULL )
-    {
-        GDALDriver* poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "OCI" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                        "Oracle Spatial" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                        "drv_oci.html" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    if( GDALGetDriverByName( "OCI" ) != NULL )
+        return;
 
-        poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, "OCI:" );
+    GDALDriver* poDriver = new GDALDriver();
 
-        poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+    poDriver->SetDescription( "OCI" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Oracle Spatial" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_oci.html" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, "OCI:" );
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
 "<OpenOptionList>"
 "  <Option name='DBNAME' type='string' description='Database name'/>"
 "  <Option name='USER' type='string' description='User name'/>"
@@ -125,7 +122,7 @@ void RegisterOGROCI()
 "  <Option name='TABLES' type='string' description='Restricted set of tables to list (comma separated)'/>"
 "</OpenOptionList>");
 
-        poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
         "<LayerCreationOptionList>"
         "  <Option name='LAUNDER' type='boolean' description='Whether layer and field names will be laundered' default='NO'/>"
         "  <Option name='PRECISION' type='boolean' description='Whether fields created should keep the width and precision' default='YES'/>"
@@ -144,17 +141,16 @@ void RegisterOGROCI()
         "  <Option name='DIMINFO_Z' type='string' description='zmin,zmax,zres values to control the Z dimension info written into the USER_SDO_GEOM_METADATA table'/>"
         "  <Option name='SRID' type='int' description='Forced SRID of the layer'/>"
         "</LayerCreationOptionList>");
-            
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES, "Integer Integer64 Real String Date DateTime" );
-        poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_FIELDS, "YES" );
-        poDriver->SetMetadataItem( GDAL_DCAP_DEFAULT_FIELDS, "YES" );
-        poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_GEOMFIELDS, "YES" );
 
-        poDriver->pfnOpen = OGROCIDriverOpen;
-        poDriver->pfnIdentify = OGROCIDriverIdentify;
-        poDriver->pfnCreate = OGROCIDriverCreate;
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
+                               "Integer Integer64 Real String Date DateTime" );
+    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_FIELDS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_DEFAULT_FIELDS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_GEOMFIELDS, "YES" );
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
-}
+    poDriver->pfnOpen = OGROCIDriverOpen;
+    poDriver->pfnIdentify = OGROCIDriverIdentify;
+    poDriver->pfnCreate = OGROCIDriverCreate;
 
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/ogr/ogrsf_frmts/oci/ogrocilayer.cpp b/ogr/ogrsf_frmts/oci/ogrocilayer.cpp
index 0cfc2c8..bd70197 100644
--- a/ogr/ogrsf_frmts/oci/ogrocilayer.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrocilayer.cpp
@@ -1,9 +1,9 @@
 /******************************************************************************
- * $Id: ogrocilayer.cpp 27855 2014-10-13 14:50:21Z rouault $
+ * $Id: ogrocilayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Implementation of the OGROCILayer class.  This is layer semantics
- *           shared between table accessors and ExecuteSQL() result 
+ *           shared between table accessors and ExecuteSQL() result
  *           pseudo-layers.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -32,7 +32,7 @@
 #include "ogr_oci.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrocilayer.cpp 27855 2014-10-13 14:50:21Z rouault $");
+CPL_CVSID("$Id: ogrocilayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                           OGROCILayer()                               */
@@ -66,7 +66,7 @@ OGROCILayer::~OGROCILayer()
     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     {
         CPLDebug( "OCI", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
+                  (int) m_nFeaturesRead,
                   poFeatureDefn->GetName() );
     }
 
@@ -113,7 +113,7 @@ void OGROCILayer::ResetReading()
 OGRFeature *OGROCILayer::GetNextFeature()
 
 {
-    while( TRUE )
+    while( true )
     {
         OGRFeature      *poFeature;
 
@@ -198,9 +198,9 @@ OGRFeature *OGROCILayer::GetNextRawFeature()
         OGROCISession      *poSession = poDS->GetSession();
 
         if( poFeature->GetGeometryRef() != NULL && hLastGeom != NULL )
-            poSession->Failed( 
-                OCIObjectFree(poSession->hEnv, poSession->hError, 
-                              (dvoid *) hLastGeom, 
+            poSession->Failed(
+                OCIObjectFree(poSession->hEnv, poSession->hError,
+                              (dvoid *) hLastGeom,
                               (ub2)OCI_OBJECTFREE_FORCE) );
 
         hLastGeom = NULL;
@@ -247,18 +247,18 @@ int OGROCILayer::ExecuteQuery( const char *pszReqQuery )
     {
         OCIDefine *hGDefine = NULL;
 
-        if( poSession->Failed(  
-            OCIDefineByPos(poStatement->GetStatement(), &hGDefine, 
+        if( poSession->Failed(
+            OCIDefineByPos(poStatement->GetStatement(), &hGDefine,
                            poSession->hError,
-                           (ub4) iGeomColumn+1, (dvoid *)0, (sb4)0, SQLT_NTY, 
+                           (ub4) iGeomColumn+1, (dvoid *)0, (sb4)0, SQLT_NTY,
                            (dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT),
             "OCIDefineByPos(geometry)") )
             return FALSE;
-        
-        if( poSession->Failed( 
-            OCIDefineObject(hGDefine, poSession->hError, 
+
+        if( poSession->Failed(
+            OCIDefineObject(hGDefine, poSession->hError,
                             poSession->hGeometryTDO,
-                            (dvoid **) &hLastGeom, (ub4 *)0, 
+                            (dvoid **) &hLastGeom, (ub4 *)0,
                             (dvoid **) &hLastGeomInd, (ub4 *)0 ),
             "OCIDefineObject") )
             return FALSE;
@@ -279,7 +279,7 @@ OGRGeometry *OGROCILayer::TranslateGeometry()
 /* -------------------------------------------------------------------- */
 /*      Is the geometry NULL?                                           */
 /* -------------------------------------------------------------------- */
-    if( hLastGeom == NULL || hLastGeomInd == NULL 
+    if( hLastGeom == NULL || hLastGeomInd == NULL
         || hLastGeomInd->_atomic == OCI_IND_NULL )
         return NULL;
 
@@ -288,14 +288,14 @@ OGRGeometry *OGROCILayer::TranslateGeometry()
 /* -------------------------------------------------------------------- */
     int nElemCount, nOrdCount;
 
-    if( poSession->Failed( 
-        OCICollSize( poSession->hEnv, poSession->hError, 
+    if( poSession->Failed(
+        OCICollSize( poSession->hEnv, poSession->hError,
                      (OCIColl *)(hLastGeom->sdo_elem_info), &nElemCount),
         "OCICollSize(sdo_elem_info)" ) )
         return NULL;
 
-    if( poSession->Failed( 
-        OCICollSize( poSession->hEnv, poSession->hError, 
+    if( poSession->Failed(
+        OCICollSize( poSession->hEnv, poSession->hError,
                      (OCIColl *)(hLastGeom->sdo_ordinates), &nOrdCount),
         "OCICollSize(sdo_ordinates)" ) )
         return NULL;
@@ -305,7 +305,7 @@ OGRGeometry *OGROCILayer::TranslateGeometry()
 /* -------------------------------------------------------------------- */
     int nGType;
 
-    if( poSession->Failed( 
+    if( poSession->Failed(
         OCINumberToInt(poSession->hError, &(hLastGeom->sdo_gtype),
                        (uword)sizeof(int), OCI_NUMBER_SIGNED,
                        (dvoid *)&nGType),
@@ -327,12 +327,12 @@ OGRGeometry *OGROCILayer::TranslateGeometry()
     {
         double     dfX, dfY, dfZ = 0.0;
 
-        OCINumberToReal(poSession->hError, &(hLastGeom->sdo_point.x), 
+        OCINumberToReal(poSession->hError, &(hLastGeom->sdo_point.x),
                         (uword)sizeof(double), (dvoid *)&dfX);
-        OCINumberToReal(poSession->hError, &(hLastGeom->sdo_point.y), 
+        OCINumberToReal(poSession->hError, &(hLastGeom->sdo_point.y),
                         (uword)sizeof(double), (dvoid *)&dfY);
         if( hLastGeomInd->sdo_point.z == OCI_IND_NOTNULL )
-            OCINumberToReal(poSession->hError, &(hLastGeom->sdo_point.z), 
+            OCINumberToReal(poSession->hError, &(hLastGeom->sdo_point.z),
                             (uword)sizeof(double), (dvoid *)&dfZ);
 
         if( nDimension == 3 )
@@ -347,18 +347,17 @@ OGRGeometry *OGROCILayer::TranslateGeometry()
 /* -------------------------------------------------------------------- */
     OGRGeometryCollection *poCollection = NULL;
     OGRPolygon *poPolygon = NULL;
-    OGRGeometry *poParent = NULL;
 
     if( ORA_GTYPE_MATCH(nGType,ORA_GTYPE_POLYGON) )
-        poParent = poPolygon = new OGRPolygon();
+        poPolygon = new OGRPolygon();
     else if( ORA_GTYPE_MATCH(nGType,ORA_GTYPE_COLLECTION) )
-        poParent = poCollection = new OGRGeometryCollection();
+        poCollection = new OGRGeometryCollection();
     else if( ORA_GTYPE_MATCH(nGType,ORA_GTYPE_MULTIPOINT) )
-        poParent = poCollection = new OGRMultiPoint();
+        poCollection = new OGRMultiPoint();
     else if( ORA_GTYPE_MATCH(nGType,ORA_GTYPE_MULTILINESTRING) )
-        poParent = poCollection = new OGRMultiLineString();
+        poCollection = new OGRMultiLineString();
     else if( ORA_GTYPE_MATCH(nGType,ORA_GTYPE_MULTIPOLYGON) )
-        poParent = poCollection = new OGRMultiPolygon();
+        poCollection = new OGRMultiPolygon();
 
 /* ==================================================================== */
 /*      Loop over the component elements.                               */
@@ -368,8 +367,8 @@ OGRGeometry *OGROCILayer::TranslateGeometry()
         int       nInterpretation, nEType;
         int       nStartOrdinal, nElemOrdCount;
 
-        LoadElementInfo( iElement, nElemCount, nOrdCount, 
-                         &nEType, &nInterpretation, 
+        LoadElementInfo( iElement, nElemCount, nOrdCount,
+                         &nEType, &nInterpretation,
                          &nStartOrdinal, &nElemOrdCount );
 
 /* -------------------------------------------------------------------- */
@@ -377,7 +376,7 @@ OGRGeometry *OGROCILayer::TranslateGeometry()
 /* -------------------------------------------------------------------- */
         OGRGeometry *poGeom;
 
-        poGeom = TranslateGeometryElement( &iElement, nGType, nDimension, 
+        poGeom = TranslateGeometryElement( &iElement, nGType, nDimension,
                                            nEType, nInterpretation,
                                            nStartOrdinal - 1, nElemOrdCount );
 
@@ -404,7 +403,7 @@ OGRGeometry *OGROCILayer::TranslateGeometry()
             CPLAssert(wkbFlatten(poGeom->getGeometryType()) == wkbLineString );
             poPolygon->addRingDirectly( (OGRLinearRing *) poGeom );
         }
-        else 
+        else
         {
             CPLAssert( poCollection != NULL );
             if( wkbFlatten(poGeom->getGeometryType()) == wkbMultiPoint )
@@ -421,7 +420,7 @@ OGRGeometry *OGROCILayer::TranslateGeometry()
                 /* its one poly ring, create new poly or add to existing */
                 if( nEType == 1003 )
                 {
-                    if( poPolygon != NULL 
+                    if( poPolygon != NULL
                         && poPolygon->getExteriorRing() != NULL )
                     {
                         poCollection->addGeometryDirectly( poPolygon );
@@ -430,7 +429,7 @@ OGRGeometry *OGROCILayer::TranslateGeometry()
 
                     poPolygon = new OGRPolygon();
                 }
-                
+
                 if( poPolygon != NULL )
                     poPolygon->addRingDirectly( (OGRLinearRing *) poGeom );
                 else
@@ -443,7 +442,7 @@ OGRGeometry *OGROCILayer::TranslateGeometry()
         }
     }
 
-    if( poCollection != NULL 
+    if( poCollection != NULL
         && poPolygon != NULL )
         poCollection->addGeometryDirectly( poPolygon );
 
@@ -463,9 +462,9 @@ OGRGeometry *OGROCILayer::TranslateGeometry()
 /*      values for a particular element.                                */
 /************************************************************************/
 
-int 
+int
 OGROCILayer::LoadElementInfo( int iElement, int nElemCount, int nTotalOrdCount,
-                              int *pnEType, int *pnInterpretation, 
+                              int *pnEType, int *pnInterpretation,
                               int *pnStartOrdinal, int *pnElemOrdCount )
 
 {
@@ -475,36 +474,36 @@ OGROCILayer::LoadElementInfo( int iElement, int nElemCount, int nTotalOrdCount,
 /* -------------------------------------------------------------------- */
 /*      Get the details about element from the elem_info array.         */
 /* -------------------------------------------------------------------- */
-    OCICollGetElem(poSession->hEnv, poSession->hError, 
-                   (OCIColl *)(hLastGeom->sdo_elem_info), 
-                   (sb4)(iElement+0), (boolean *)&bExists, 
+    OCICollGetElem(poSession->hEnv, poSession->hError,
+                   (OCIColl *)(hLastGeom->sdo_elem_info),
+                   (sb4)(iElement+0), (boolean *)&bExists,
                    (dvoid **)&hNumber, NULL );
-    OCINumberToInt(poSession->hError, hNumber, (uword)sizeof(ub4), 
+    OCINumberToInt(poSession->hError, hNumber, (uword)sizeof(ub4),
                    OCI_NUMBER_UNSIGNED, (dvoid *) pnStartOrdinal );
-        
-    OCICollGetElem(poSession->hEnv, poSession->hError, 
-                   (OCIColl *)(hLastGeom->sdo_elem_info), 
-                   (sb4)(iElement+1), (boolean *)&bExists, 
+
+    OCICollGetElem(poSession->hEnv, poSession->hError,
+                   (OCIColl *)(hLastGeom->sdo_elem_info),
+                   (sb4)(iElement+1), (boolean *)&bExists,
                    (dvoid **)&hNumber, NULL );
-    OCINumberToInt(poSession->hError, hNumber, (uword)sizeof(ub4), 
+    OCINumberToInt(poSession->hError, hNumber, (uword)sizeof(ub4),
                    OCI_NUMBER_UNSIGNED, (dvoid *) pnEType );
-        
-    OCICollGetElem(poSession->hEnv, poSession->hError, 
-                   (OCIColl *)(hLastGeom->sdo_elem_info), 
-                   (sb4)(iElement+2), (boolean *)&bExists, 
+
+    OCICollGetElem(poSession->hEnv, poSession->hError,
+                   (OCIColl *)(hLastGeom->sdo_elem_info),
+                   (sb4)(iElement+2), (boolean *)&bExists,
                    (dvoid **)&hNumber, NULL );
-    OCINumberToInt(poSession->hError, hNumber, (uword)sizeof(ub4), 
+    OCINumberToInt(poSession->hError, hNumber, (uword)sizeof(ub4),
                    OCI_NUMBER_UNSIGNED, (dvoid *) pnInterpretation );
 
     if( iElement < nElemCount-3 )
     {
         ub4 nNextStartOrdinal;
 
-        OCICollGetElem(poSession->hEnv, poSession->hError, 
-                       (OCIColl *)(hLastGeom->sdo_elem_info), 
-                       (sb4)(iElement+3), (boolean *)&bExists, 
+        OCICollGetElem(poSession->hEnv, poSession->hError,
+                       (OCIColl *)(hLastGeom->sdo_elem_info),
+                       (sb4)(iElement+3), (boolean *)&bExists,
                        (dvoid **)&hNumber,NULL);
-        OCINumberToInt(poSession->hError, hNumber, (uword)sizeof(ub4), 
+        OCINumberToInt(poSession->hError, hNumber, (uword)sizeof(ub4),
                        OCI_NUMBER_UNSIGNED, (dvoid *) &nNextStartOrdinal );
 
         *pnElemOrdCount = nNextStartOrdinal - *pnStartOrdinal;
@@ -514,16 +513,16 @@ OGROCILayer::LoadElementInfo( int iElement, int nElemCount, int nTotalOrdCount,
 
     return TRUE;
 }
-                              
+
 
 /************************************************************************/
 /*                      TranslateGeometryElement()                      */
 /************************************************************************/
 
 OGRGeometry *
-OGROCILayer::TranslateGeometryElement( int *piElement, 
+OGROCILayer::TranslateGeometryElement( int *piElement,
                                        int nGType, int nDimension,
-                                       int nEType, int nInterpretation, 
+                                       int nEType, int nInterpretation,
                                        int nStartOrdinal, int nElemOrdCount )
 
 {
@@ -558,7 +557,7 @@ OGROCILayer::TranslateGeometryElement( int *piElement,
 
         for( i = 0; i < nInterpretation; i++ )
         {
-            GetOrdinalPoint( nStartOrdinal + i*nDimension, nDimension, 
+            GetOrdinalPoint( nStartOrdinal + i*nDimension, nDimension,
                              &dfX, &dfY, &dfZ );
 
             OGRPoint *poPoint = (nDimension == 3) ? new OGRPoint( dfX, dfY, dfZ ):  new OGRPoint( dfX, dfY );
@@ -590,7 +589,7 @@ OGROCILayer::TranslateGeometryElement( int *piElement,
         {
             double dfX, dfY, dfZ = 0.0;
 
-            GetOrdinalPoint( i*nDimension + nStartOrdinal, nDimension, 
+            GetOrdinalPoint( i*nDimension + nStartOrdinal, nDimension,
                              &dfX, &dfY, &dfZ );
             if (nDimension == 3)
                 poLS->setPoint( i, dfX, dfY, dfZ );
@@ -608,21 +607,21 @@ OGROCILayer::TranslateGeometryElement( int *piElement,
     {
         OGRLineString *poLS = new OGRLineString();
         int nPointCount = nElemOrdCount / nDimension, i;
-        
+
         for( i = 0; i < nPointCount-2; i += 2 )
         {
-            double dfStartX, dfStartY, dfStartZ = 0.0; 
+            double dfStartX, dfStartY, dfStartZ = 0.0;
             double dfMidX, dfMidY, dfMidZ = 0.0;
-            double dfEndX, dfEndY, dfEndZ = 0.0; 
+            double dfEndX, dfEndY, dfEndZ = 0.0;
 
-            GetOrdinalPoint( i*nDimension + nStartOrdinal, nDimension, 
+            GetOrdinalPoint( i*nDimension + nStartOrdinal, nDimension,
                              &dfStartX, &dfStartY, &dfStartZ );
-            GetOrdinalPoint( (i+1)*nDimension + nStartOrdinal, nDimension, 
+            GetOrdinalPoint( (i+1)*nDimension + nStartOrdinal, nDimension,
                              &dfMidX, &dfMidY, &dfMidZ );
-            GetOrdinalPoint( (i+2)*nDimension + nStartOrdinal, nDimension, 
+            GetOrdinalPoint( (i+2)*nDimension + nStartOrdinal, nDimension,
                              &dfEndX, &dfEndY, &dfEndZ );
 
-            OGROCIStrokeArcToOGRGeometry_Points( dfStartX, dfStartY, 
+            OGROCIStrokeArcToOGRGeometry_Points( dfStartX, dfStartY,
                                                  dfMidX, dfMidY,
                                                  dfEndX, dfEndY,
                                                  6.0, FALSE, poLS );
@@ -646,7 +645,7 @@ OGROCILayer::TranslateGeometryElement( int *piElement,
         {
             double dfX, dfY, dfZ = 0.0;
 
-            GetOrdinalPoint( i*nDimension + nStartOrdinal, nDimension, 
+            GetOrdinalPoint( i*nDimension + nStartOrdinal, nDimension,
                              &dfX, &dfY, &dfZ );
             if (nDimension == 3)
                 poLS->setPoint( i, dfX, dfY, dfZ );
@@ -664,21 +663,21 @@ OGROCILayer::TranslateGeometryElement( int *piElement,
     {
         OGRLineString *poLS = new OGRLinearRing();
         int nPointCount = nElemOrdCount / nDimension, i;
-        
+
         for( i = 0; i < nPointCount-2; i += 2 )
         {
-            double dfStartX, dfStartY, dfStartZ = 0.0; 
+            double dfStartX, dfStartY, dfStartZ = 0.0;
             double dfMidX, dfMidY, dfMidZ = 0.0;
-            double dfEndX, dfEndY, dfEndZ = 0.0; 
+            double dfEndX, dfEndY, dfEndZ = 0.0;
 
-            GetOrdinalPoint( i*nDimension + nStartOrdinal, nDimension, 
+            GetOrdinalPoint( i*nDimension + nStartOrdinal, nDimension,
                              &dfStartX, &dfStartY, &dfStartZ );
-            GetOrdinalPoint( (i+1)*nDimension + nStartOrdinal, nDimension, 
+            GetOrdinalPoint( (i+1)*nDimension + nStartOrdinal, nDimension,
                              &dfMidX, &dfMidY, &dfMidZ );
-            GetOrdinalPoint( (i+2)*nDimension + nStartOrdinal, nDimension, 
+            GetOrdinalPoint( (i+2)*nDimension + nStartOrdinal, nDimension,
                              &dfEndX, &dfEndY, &dfEndZ );
 
-            OGROCIStrokeArcToOGRGeometry_Points( dfStartX, dfStartY, 
+            OGROCIStrokeArcToOGRGeometry_Points( dfStartX, dfStartY,
                                                  dfMidX, dfMidY,
                                                  dfEndX, dfEndY,
                                                  6.0, FALSE, poLS );
@@ -695,12 +694,12 @@ OGROCILayer::TranslateGeometryElement( int *piElement,
         OGRLinearRing *poLS = new OGRLinearRing();
         double dfX1, dfY1, dfZ1 = 0.0;
         double dfX2, dfY2, dfZ2 = 0.0;
-        
-        GetOrdinalPoint( nStartOrdinal, nDimension, 
+
+        GetOrdinalPoint( nStartOrdinal, nDimension,
                          &dfX1, &dfY1, &dfZ1 );
-        GetOrdinalPoint( nStartOrdinal + nDimension, nDimension, 
+        GetOrdinalPoint( nStartOrdinal + nDimension, nDimension,
                          &dfX2, &dfY2, &dfZ2 );
-        
+
         poLS->setNumPoints( 5 );
 
         poLS->setPoint( 0, dfX1, dfY1, dfZ1 );
@@ -721,17 +720,17 @@ OGROCILayer::TranslateGeometryElement( int *piElement,
         double dfX1, dfY1, dfZ1 = 0.0;
         double dfX2, dfY2, dfZ2 = 0.0;
         double dfX3, dfY3, dfZ3 = 0.0;
-        
-        GetOrdinalPoint( nStartOrdinal, nDimension, 
+
+        GetOrdinalPoint( nStartOrdinal, nDimension,
                          &dfX1, &dfY1, &dfZ1 );
-        GetOrdinalPoint( nStartOrdinal + nDimension, nDimension, 
+        GetOrdinalPoint( nStartOrdinal + nDimension, nDimension,
                          &dfX2, &dfY2, &dfZ2 );
-        GetOrdinalPoint( nStartOrdinal + nDimension*2, nDimension, 
+        GetOrdinalPoint( nStartOrdinal + nDimension*2, nDimension,
                          &dfX3, &dfY3, &dfZ3 );
 
-        OGROCIStrokeArcToOGRGeometry_Points( dfX1, dfY1, 
+        OGROCIStrokeArcToOGRGeometry_Points( dfX1, dfY1,
                                              dfX2, dfY2,
-                                             dfX3, dfY3, 
+                                             dfX3, dfY3,
                                              6.0, TRUE, poLS );
 
         return poLS;
@@ -749,28 +748,28 @@ OGROCILayer::TranslateGeometryElement( int *piElement,
         OGRLineString *poLS, *poElemLS;
         int nElemCount, nTotalOrdCount;
         OGROCISession      *poSession = poDS->GetSession();
-        
+
         if( nEType == 4 )
             poLS = new OGRLineString();
-        else 
+        else
             poLS = new OGRLinearRing();
 
-        if( poSession->Failed( 
-            OCICollSize( poSession->hEnv, poSession->hError, 
+        if( poSession->Failed(
+            OCICollSize( poSession->hEnv, poSession->hError,
                          (OCIColl *)(hLastGeom->sdo_elem_info), &nElemCount),
             "OCICollSize(sdo_elem_info)" ) )
             return NULL;
-        
-        if( poSession->Failed( 
-            OCICollSize( poSession->hEnv, poSession->hError, 
+
+        if( poSession->Failed(
+            OCICollSize( poSession->hEnv, poSession->hError,
                          (OCIColl*)(hLastGeom->sdo_ordinates),&nTotalOrdCount),
             "OCICollSize(sdo_ordinates)" ) )
             return NULL;
 
         for( *piElement += 3; nSubElementCount-- > 0;  *piElement += 3 )
         {
-            LoadElementInfo( *piElement, nElemCount, nTotalOrdCount, 
-                             &nEType, &nInterpretation, 
+            LoadElementInfo( *piElement, nElemCount, nTotalOrdCount,
+                             &nEType, &nInterpretation,
                              &nStartOrdinal, &nElemOrdCount );
 
             // Adjust for repeated end point except for last element.
@@ -779,7 +778,7 @@ OGROCILayer::TranslateGeometryElement( int *piElement,
 
             // translate element.
             poElemLS = (OGRLineString *)
-                TranslateGeometryElement( piElement, nGType, nDimension, 
+                TranslateGeometryElement( piElement, nGType, nDimension,
                                           nEType, nInterpretation,
                                           nStartOrdinal - 1, nElemOrdCount );
 
@@ -788,10 +787,10 @@ OGROCILayer::TranslateGeometryElement( int *piElement,
             {
                 if( poLS->getNumPoints() > 0 )
                 {
-                    CPLAssert( 
+                    CPLAssert(
                         poElemLS->getX(0) == poLS->getX(poLS->getNumPoints()-1)
                         && poElemLS->getY(0) ==poLS->getY(poLS->getNumPoints()-1));
-                    
+
                     poLS->addSubLineString( poElemLS, 1 );
                 }
                 else
@@ -799,20 +798,20 @@ OGROCILayer::TranslateGeometryElement( int *piElement,
 
                 delete poElemLS;
             }
-            
+
         }
 
         *piElement -= 3;
         return poLS;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Otherwise it is apparently unsupported.                         */
 /* -------------------------------------------------------------------- */
     else
     {
-        
-        CPLDebug( "OCI", "Geometry with EType=%d, Interp=%d ignored.", 
+
+        CPLDebug( "OCI", "Geometry with EType=%d, Interp=%d ignored.",
                   nEType, nInterpretation );
     }
 
@@ -831,23 +830,23 @@ int OGROCILayer::GetOrdinalPoint( int iOrdinal, int nDimension,
     boolean bExists;
     OCINumber *hNumber;
 
-    OCICollGetElem( poSession->hEnv, poSession->hError,         
-                    (OCIColl *)(hLastGeom->sdo_ordinates), 
-                    (sb4)iOrdinal+0, (boolean *)&bExists, 
+    OCICollGetElem( poSession->hEnv, poSession->hError,
+                    (OCIColl *)(hLastGeom->sdo_ordinates),
+                    (sb4)iOrdinal+0, (boolean *)&bExists,
                     (dvoid **)&hNumber, NULL );
-    OCINumberToReal(poSession->hError, hNumber, 
+    OCINumberToReal(poSession->hError, hNumber,
                     (uword)sizeof(double), (dvoid *)pdfX);
-    OCICollGetElem( poSession->hEnv, poSession->hError,         
-                    (OCIColl *)(hLastGeom->sdo_ordinates), 
-                    (sb4)iOrdinal + 1, (boolean *)&bExists, 
+    OCICollGetElem( poSession->hEnv, poSession->hError,
+                    (OCIColl *)(hLastGeom->sdo_ordinates),
+                    (sb4)iOrdinal + 1, (boolean *)&bExists,
                     (dvoid **)&hNumber, NULL );
     OCINumberToReal(poSession->hError, hNumber,
                     (uword)sizeof(double), (dvoid *)pdfY);
     if( nDimension == 3 )
     {
         OCICollGetElem( poSession->hEnv, poSession->hError,
-                        (OCIColl *)(hLastGeom->sdo_ordinates), 
-                        (sb4)iOrdinal + 2, (boolean *)&bExists, 
+                        (OCIColl *)(hLastGeom->sdo_ordinates),
+                        (sb4)iOrdinal + 2, (boolean *)&bExists,
                         (dvoid **)&hNumber, NULL );
         OCINumberToReal(poSession->hError, hNumber,
                         (uword)sizeof(double), (dvoid *)pdfZ);
@@ -855,7 +854,7 @@ int OGROCILayer::GetOrdinalPoint( int iOrdinal, int nDimension,
 
     return TRUE;
 }
-                                       
+
 /************************************************************************/
 /*                           TestCapability()                           */
 /************************************************************************/
@@ -875,7 +874,7 @@ int OGROCILayer::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCTransactions) )
         return TRUE;
 
-    else 
+    else
         return FALSE;
 }
 
@@ -896,7 +895,7 @@ int OGROCILayer::LookupTableSRID()
 /* -------------------------------------------------------------------- */
     if( pszGeomName == NULL )
         return -1;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Split out the owner if available.                               */
 /* -------------------------------------------------------------------- */
@@ -919,7 +918,7 @@ int OGROCILayer::LookupTableSRID()
     oCommand.Appendf( 1000, "SELECT SRID FROM ALL_SDO_GEOM_METADATA "
                       "WHERE TABLE_NAME = UPPER('%s') AND COLUMN_NAME = UPPER('%s')",
                       pszTableName, pszGeomName );
-    
+
     if( pszOwner != NULL )
     {
         oCommand.Appendf( 500, " AND OWNER = '%s'", pszOwner );
@@ -931,7 +930,7 @@ int OGROCILayer::LookupTableSRID()
 /* -------------------------------------------------------------------- */
     OGROCIStatement oGetTables( poDS->GetSession() );
     int nSRID = -1;
-    
+
     if( oGetTables.Execute( oCommand.GetString() ) == CE_None )
     {
         char **papszRow = oGetTables.SimpleFetchRow();
@@ -947,7 +946,7 @@ int OGROCILayer::LookupTableSRID()
 /*                            GetFIDColumn()                            */
 /************************************************************************/
 
-const char *OGROCILayer::GetFIDColumn() 
+const char *OGROCILayer::GetFIDColumn()
 
 {
     if( pszFIDName != NULL )
@@ -960,7 +959,7 @@ const char *OGROCILayer::GetFIDColumn()
 /*                         GetGeometryColumn()                          */
 /************************************************************************/
 
-const char *OGROCILayer::GetGeometryColumn() 
+const char *OGROCILayer::GetGeometryColumn()
 
 {
     if( pszGeomName != NULL )
diff --git a/ogr/ogrsf_frmts/oci/ogrociloaderlayer.cpp b/ogr/ogrsf_frmts/oci/ogrociloaderlayer.cpp
index d30e2d3..76c1fdd 100644
--- a/ogr/ogrsf_frmts/oci/ogrociloaderlayer.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrociloaderlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrociloaderlayer.cpp 28430 2015-02-06 20:57:41Z rouault $
+ * $Id: ogrociloaderlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Implementation of the OGROCILoaderLayer class.  This implements
@@ -32,16 +32,16 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrociloaderlayer.cpp 28430 2015-02-06 20:57:41Z rouault $");
+CPL_CVSID("$Id: ogrociloaderlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                         OGROCILoaderLayer()                          */
 /************************************************************************/
 
-OGROCILoaderLayer::OGROCILoaderLayer( OGROCIDataSource *poDSIn, 
+OGROCILoaderLayer::OGROCILoaderLayer( OGROCIDataSource *poDSIn,
                                       const char * pszTableName,
                                       const char * pszGeomColIn,
-                                      int nSRIDIn, 
+                                      int nSRIDIn,
                                       const char *pszLoaderFilenameIn )
 
 {
@@ -56,10 +56,10 @@ OGROCILoaderLayer::OGROCILoaderLayer( OGROCIDataSource *poDSIn,
     poFeatureDefn = new OGRFeatureDefn( pszTableName );
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
-    
+
     pszGeomName = CPLStrdup( pszGeomColIn );
     pszFIDName = (char*)CPLGetConfigOption( "OCI_FID", "OGR_FID" );
-    
+
 
     nSRID = nSRIDIn;
     poSRS = poDSIn->FetchSRS( nSRID );
@@ -76,8 +76,8 @@ OGROCILoaderLayer::OGROCILoaderLayer( OGROCIDataSource *poDSIn,
     fpLoader = VSIFOpen( pszLoaderFilename, "wt" );
     if( fpLoader == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Failed to open SQL*Loader control file:%s", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to open SQL*Loader control file:%s",
                   pszLoaderFilename );
         return;
     }
@@ -119,7 +119,7 @@ void OGROCILoaderLayer::WriteLoaderHeader()
 /* -------------------------------------------------------------------- */
 /*      Determine name of geometry column to use.                       */
 /* -------------------------------------------------------------------- */
-    const char *pszGeometryName = 
+    const char *pszGeometryName =
         CSLFetchNameValue( papszOptions, "GEOMETRY_NAME" );
     if( pszGeometryName == NULL )
         pszGeometryName = "ORA_GEOMETRY";
@@ -128,7 +128,7 @@ void OGROCILoaderLayer::WriteLoaderHeader()
 /*      Dermine our operation mode.                                     */
 /* -------------------------------------------------------------------- */
     const char *pszLDRMode = CSLFetchNameValue( papszOptions, "LOADER_MODE" );
-    
+
     if( pszLDRMode != NULL && EQUAL(pszLDRMode,"VARIABLE") )
         nLDRMode = LDRM_VARIABLE;
     else if( pszLDRMode != NULL && EQUAL(pszLDRMode,"BINARY") )
@@ -147,23 +147,23 @@ void OGROCILoaderLayer::WriteLoaderHeader()
     }
     else if( nLDRMode == LDRM_VARIABLE )
     {
-        const char *pszDataFilename = CPLResetExtension( pszLoaderFilename, 
+        const char *pszDataFilename = CPLResetExtension( pszLoaderFilename,
                                                          "dat" );
         fpData = VSIFOpen( pszDataFilename, "wb" );
         if( fpData == NULL )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
-                      "Unable to open data output file `%s'.", 
+            CPLError( CE_Failure, CPLE_OpenFailed,
+                      "Unable to open data output file `%s'.",
                       pszDataFilename );
             return;
         }
-            
+
         VSIFPrintf( fpLoader, "INFILE %s \"var 8\"\n", pszDataFilename );
     }
-    const char *pszExpectedFIDName = 
+    const char *pszExpectedFIDName =
         CPLGetConfigOption( "OCI_FID", "OGR_FID" );
 
-    VSIFPrintf( fpLoader, "INTO TABLE \"%s\" REPLACE\n", 
+    VSIFPrintf( fpLoader, "INTO TABLE \"%s\" REPLACE\n",
                 poFeatureDefn->GetName() );
     VSIFPrintf( fpLoader, "FIELDS TERMINATED BY '|'\n" );
     VSIFPrintf( fpLoader, "TRAILING NULLCOLS (\n" );
@@ -188,27 +188,27 @@ void OGROCILoaderLayer::WriteLoaderHeader()
 
         if( poFldDefn->GetType() == OFTInteger )
         {
-            VSIFPrintf( fpLoader, "    \"%s\" INTEGER EXTERNAL", 
+            VSIFPrintf( fpLoader, "    \"%s\" INTEGER EXTERNAL",
                         poFldDefn->GetNameRef() );
         }
         else if( poFldDefn->GetType() == OFTInteger )
         {
-            VSIFPrintf( fpLoader, "    \"%s\" LONGINTEGER EXTERNAL", 
+            VSIFPrintf( fpLoader, "    \"%s\" LONGINTEGER EXTERNAL",
                         poFldDefn->GetNameRef() );
         }
         else if( poFldDefn->GetType() == OFTReal )
         {
-            VSIFPrintf( fpLoader, "    \"%s\" FLOAT EXTERNAL", 
+            VSIFPrintf( fpLoader, "    \"%s\" FLOAT EXTERNAL",
                         poFldDefn->GetNameRef() );
         }
         else if( poFldDefn->GetType() == OFTString )
         {
-            VSIFPrintf( fpLoader, "    \"%s\" VARCHARC(4)", 
+            VSIFPrintf( fpLoader, "    \"%s\" VARCHARC(4)",
                         poFldDefn->GetNameRef() );
         }
         else
         {
-            VSIFPrintf( fpLoader, "    \"%s\" VARCHARC(4)", 
+            VSIFPrintf( fpLoader, "    \"%s\" VARCHARC(4)",
                         poFldDefn->GetNameRef() );
         }
 
@@ -237,7 +237,7 @@ void OGROCILoaderLayer::WriteLoaderHeader()
 OGRFeature *OGROCILoaderLayer::GetNextFeature()
 
 {
-    CPLError( CE_Failure, CPLE_NotSupported, 
+    CPLError( CE_Failure, CPLE_NotSupported,
               "GetNextFeature() not supported for an OGROCILoaderLayer." );
     return NULL;
 }
@@ -277,7 +277,7 @@ OGRErr OGROCILoaderLayer::WriteFeatureStreamMode( OGRFeature *poFeature )
         if( nSRID == -1 )
             strcpy( szSRID, "NULL" );
         else
-            sprintf( szSRID, "%d", nSRID );
+            snprintf( szSRID, sizeof(szSRID), "%d", nSRID );
 
         if( TranslateToSDOGeometry( poFeature->GetGeometryRef(), &nGType )
             == OGRERR_NONE )
@@ -329,7 +329,7 @@ OGRErr OGROCILoaderLayer::WriteFeatureStreamMode( OGRFeature *poFeature )
 
         if( !poFeature->IsFieldSet( i ) )
         {
-            if( poFldDefn->GetType() != OFTInteger 
+            if( poFldDefn->GetType() != OFTInteger
                 && poFldDefn->GetType() != OFTInteger64
                 && poFldDefn->GetType() != OFTReal )
                 VSIFPrintf( fpLoader, "%04d", 0 );
@@ -344,9 +344,9 @@ OGRErr OGROCILoaderLayer::WriteFeatureStreamMode( OGRFeature *poFeature )
             nLineLen = 0;
         }
 
-        nLineLen += strlen(pszStrValue);
+        nLineLen += static_cast<int>(strlen(pszStrValue));
 
-        if( poFldDefn->GetType() == OFTInteger 
+        if( poFldDefn->GetType() == OFTInteger
             || poFldDefn->GetType() == OFTInteger64
             || poFldDefn->GetType() == OFTReal )
         {
@@ -359,9 +359,9 @@ OGRErr OGROCILoaderLayer::WriteFeatureStreamMode( OGRFeature *poFeature )
             else
                 VSIFPrintf( fpLoader, "%s|", pszStrValue );
         }
-        else 
+        else
         {
-            int nLength = strlen(pszStrValue);
+            int nLength = static_cast<int>(strlen(pszStrValue));
 
             if( poFldDefn->GetWidth() > 0 && nLength > poFldDefn->GetWidth() )
             {
@@ -376,7 +376,7 @@ OGRErr OGROCILoaderLayer::WriteFeatureStreamMode( OGRFeature *poFeature )
 
     if( VSIFPrintf( fpLoader, "\n" ) == 0 )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   "Write to loader file failed, likely out of disk space." );
         return OGRERR_FAILURE;
     }
@@ -414,7 +414,7 @@ OGRErr OGROCILoaderLayer::WriteFeatureVariableMode( OGRFeature *poFeature )
         if( nSRID == -1 )
             strcpy( szSRID, "NULL" );
         else
-            sprintf( szSRID, "%d", nSRID );
+            snprintf( szSRID, sizeof(szSRID), "%d", nSRID );
 
         if( TranslateToSDOGeometry( poFeature->GetGeometryRef(), &nGType )
             == OGRERR_NONE )
@@ -453,7 +453,7 @@ OGRErr OGROCILoaderLayer::WriteFeatureVariableMode( OGRFeature *poFeature )
 
         if( !poFeature->IsFieldSet( i ) )
         {
-            if( poFldDefn->GetType() != OFTInteger 
+            if( poFldDefn->GetType() != OFTInteger
                 && poFldDefn->GetType() != OFTInteger64
                 && poFldDefn->GetType() != OFTReal )
                 oLine.Append( "0000" );
@@ -464,7 +464,7 @@ OGRErr OGROCILoaderLayer::WriteFeatureVariableMode( OGRFeature *poFeature )
 
         const char *pszStrValue = poFeature->GetFieldAsString(i);
 
-        if( poFldDefn->GetType() == OFTInteger 
+        if( poFldDefn->GetType() == OFTInteger
             || poFldDefn->GetType() == OFTInteger64
             || poFldDefn->GetType() == OFTReal )
         {
@@ -480,9 +480,9 @@ OGRErr OGROCILoaderLayer::WriteFeatureVariableMode( OGRFeature *poFeature )
                 oLine.Append( "|" );
             }
         }
-        else 
+        else
         {
-            int nLength = strlen(pszStrValue);
+            int nLength = static_cast<int>(strlen(pszStrValue));
 
             if( poFldDefn->GetWidth() > 0 && nLength > poFldDefn->GetWidth() )
             {
@@ -501,15 +501,15 @@ OGRErr OGROCILoaderLayer::WriteFeatureVariableMode( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
 /*      Update the line's length, and write to disk.                    */
 /* -------------------------------------------------------------------- */
-    char szLength[9]; 
+    char szLength[9];
     size_t  nStringLen = strlen(oLine.GetString());
 
-    sprintf( szLength, "%08d", (int) (nStringLen-8) );
+    snprintf( szLength, sizeof(szLength), "%08d", (int) (nStringLen-8) );
     strncpy( oLine.GetString(), szLength, 8 );
 
     if( VSIFWrite( oLine.GetString(), 1, nStringLen, fpData ) != nStringLen )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   "Write to loader file failed, likely out of disk space." );
         return OGRERR_FAILURE;
     }
@@ -521,7 +521,7 @@ OGRErr OGROCILoaderLayer::WriteFeatureVariableMode( OGRFeature *poFeature )
 /*                       WriteFeatureBinaryMode()                       */
 /************************************************************************/
 
-OGRErr OGROCILoaderLayer::WriteFeatureBinaryMode( OGRFeature *poFeature )
+OGRErr OGROCILoaderLayer::WriteFeatureBinaryMode( OGRFeature * /*poFeature*/ )
 
 {
     return OGRERR_UNSUPPORTED_OPERATION;
@@ -548,7 +548,7 @@ OGRErr OGROCILoaderLayer::ICreateFeature( OGRFeature *poFeature )
     if( poFeature->GetGeometryRef() != NULL )
     {
         OGREnvelope  sThisExtent;
-        
+
         poFeature->GetGeometryRef()->getEnvelope( &sThisExtent );
         sExtent.Merge( sThisExtent );
     }
@@ -579,7 +579,7 @@ int OGROCILoaderLayer::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCCreateField) )
         return TRUE;
 
-    else 
+    else
         return OGROCILayer::TestCapability( pszCap );
 }
 
@@ -592,7 +592,7 @@ int OGROCILoaderLayer::TestCapability( const char * pszCap )
 /*      way of counting features matching a spatial query.              */
 /************************************************************************/
 
-GIntBig OGROCILoaderLayer::GetFeatureCount( int bForce )
+GIntBig OGROCILoaderLayer::GetFeatureCount( int /* bForce */ )
 
 {
     return iNextFIDToWrite - 1;
@@ -620,11 +620,10 @@ void OGROCILoaderLayer::FinalizeNewLayer()
     if( sExtent.MaxX == 0 && sExtent.MinX == 0
         && sExtent.MaxY == 0 && sExtent.MinY == 0 )
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
-                  "Layer %s appears to have no geometry ... not setting SDO DIMINFO metadata.", 
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Layer %s appears to have no geometry ... not setting SDO DIMINFO metadata.",
                   poFeatureDefn->GetName() );
         return;
-                  
     }
 
 /* -------------------------------------------------------------------- */
@@ -644,17 +643,17 @@ void OGROCILoaderLayer::FinalizeNewLayer()
     dfXMax = sExtent.MaxX + dfResSize * 3;
     dfXRes = dfResSize;
     ParseDIMINFO( "DIMINFO_X", &dfXMin, &dfXMax, &dfXRes );
-    
+
     dfYMin = sExtent.MinY - dfResSize * 3;
     dfYMax = sExtent.MaxY + dfResSize * 3;
     dfYRes = dfResSize;
     ParseDIMINFO( "DIMINFO_Y", &dfYMin, &dfYMax, &dfYRes );
-    
+
     dfZMin = -100000.0;
     dfZMax = 100000.0;
     dfZRes = 0.002;
     ParseDIMINFO( "DIMINFO_Z", &dfZMin, &dfZMax, &dfZRes );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Prepare dimension update statement.                             */
 /* -------------------------------------------------------------------- */
@@ -677,7 +676,7 @@ void OGROCILoaderLayer::FinalizeNewLayer()
 
     sDimUpdate.Append( ")" );
 
-    sDimUpdate.Appendf( strlen(poFeatureDefn->GetName()) + 100,
+    sDimUpdate.Appendf( static_cast<int>(strlen(poFeatureDefn->GetName()) + 100),
                         " WHERE table_name = UPPER('%s')",
                         poFeatureDefn->GetName() );
 
diff --git a/ogr/ogrsf_frmts/oci/ogrociselectlayer.cpp b/ogr/ogrsf_frmts/oci/ogrociselectlayer.cpp
index ee9496f..a98ec8c 100644
--- a/ogr/ogrsf_frmts/oci/ogrociselectlayer.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrociselectlayer.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: ogrociselectlayer.cpp 28407 2015-02-03 10:47:59Z rouault $
+ * $Id: ogrociselectlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Oracle Spatial Driver
- * Purpose:  Implementation of the OGROCISelectLayer class.  This class 
+ * Purpose:  Implementation of the OGROCISelectLayer class.  This class
  *           provides read semantics on the result of a SELECT statement.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -32,13 +32,13 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrociselectlayer.cpp 28407 2015-02-03 10:47:59Z rouault $");
+CPL_CVSID("$Id: ogrociselectlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                          OGROCISelectLayer()                         */
 /************************************************************************/
 
-OGROCISelectLayer::OGROCISelectLayer( OGROCIDataSource *poDSIn, 
+OGROCISelectLayer::OGROCISelectLayer( OGROCIDataSource *poDSIn,
                                       const char * pszQuery,
                                       OGROCIStatement *poDescribedCommand )
 
@@ -51,7 +51,7 @@ OGROCISelectLayer::OGROCISelectLayer( OGROCIDataSource *poDSIn,
     SetDescription( poFeatureDefn->GetName() );
 
     pszQueryStatement = CPLStrdup(pszQuery);
-    
+
     ResetReading();
 }
 
@@ -80,17 +80,17 @@ OGROCISelectLayer::ReadTableDefinition( OGROCIStatement *poCommand )
 /* -------------------------------------------------------------------- */
 /*      Parse the returned table information.                           */
 /* -------------------------------------------------------------------- */
-    for( int iParm = 0; TRUE; iParm++ )
-    {                                                           
+    for( int iParm = 0; true; iParm++ )
+    {
         OGRFieldDefn oField( "", OFTString );
         int          nStatus;
         OCIParam     *hParmDesc;
         ub2          nOCIType;
         ub4          nOCILen;
 
-        nStatus = 
-            OCIParamGet( poCommand->GetStatement(), OCI_HTYPE_STMT, 
-                         poSession->hError, (dvoid**)&hParmDesc, 
+        nStatus =
+            OCIParamGet( poCommand->GetStatement(), OCI_HTYPE_STMT,
+                         poSession->hError, (dvoid**)&hParmDesc,
                          (ub4) iParm+1 );
 
         if( nStatus == OCI_ERROR )
@@ -122,7 +122,7 @@ OGROCISelectLayer::ReadTableDefinition( OGROCIStatement *poCommand )
 /* -------------------------------------------------------------------- */
 /*      Do we have an FID?                                              */
 /* -------------------------------------------------------------------- */
-    const char *pszExpectedFIDName = 
+    const char *pszExpectedFIDName =
         CPLGetConfigOption( "OCI_FID", "OGR_FID" );
     if( poDefn->GetFieldIndex(pszExpectedFIDName) > -1 )
     {
diff --git a/ogr/ogrsf_frmts/oci/ogrocisession.cpp b/ogr/ogrsf_frmts/oci/ogrocisession.cpp
index 7d20a08..ee3a1b2 100644
--- a/ogr/ogrsf_frmts/oci/ogrocisession.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrocisession.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrocisession.cpp 28481 2015-02-13 17:11:15Z rouault $
+ * $Id: ogrocisession.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Implementation of OGROCISession, which encapsulates much of the
@@ -31,13 +31,13 @@
 #include "ogr_oci.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrocisession.cpp 28481 2015-02-13 17:11:15Z rouault $");
+CPL_CVSID("$Id: ogrocisession.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                          OGRGetOCISession()                          */
 /************************************************************************/
 
-OGROCISession * OGRGetOCISession( const char *pszUserid, 
+OGROCISession * OGRGetOCISession( const char *pszUserid,
                                   const char *pszPassword,
                                   const char *pszDatabase )
 
@@ -117,9 +117,9 @@ OGROCISession::~OGROCISession()
 /*                          EstablishSession()                          */
 /************************************************************************/
 
-int OGROCISession::EstablishSession( const char *pszUserid, 
-                                     const char *pszPassword,
-                                     const char *pszDatabase )
+int OGROCISession::EstablishSession( const char *pszUseridIn,
+                                     const char *pszPasswordIn,
+                                     const char *pszDatabaseIn )
 
 {
 /* -------------------------------------------------------------------- */
@@ -128,9 +128,9 @@ int OGROCISession::EstablishSession( const char *pszUserid,
 
     ub4 eCred = OCI_CRED_RDBMS;
 
-    if( EQUAL(pszDatabase, "") &&
-        EQUAL(pszPassword, "") &&
-        EQUAL(pszUserid, "/") )
+    if( EQUAL(pszDatabaseIn, "") &&
+        EQUAL(pszPasswordIn, "") &&
+        EQUAL(pszUseridIn, "/") )
     {
         eCred = OCI_CRED_EXT;
     }
@@ -175,8 +175,8 @@ int OGROCISession::EstablishSession( const char *pszUserid,
         return FALSE;
     }
 
-    if( Failed( OCIServerAttach( hServer, hError, (text*) pszDatabase,
-                strlen((char*) pszDatabase), 0) ) )
+    if( Failed( OCIServerAttach( hServer, hError, (text*) pszDatabaseIn,
+                static_cast<int>(strlen((char*) pszDatabaseIn)), 0) ) )
     {
         return FALSE;
     }
@@ -198,14 +198,14 @@ int OGROCISession::EstablishSession( const char *pszUserid,
     }
 
     if( Failed( OCIAttrSet((dvoid *) hSession, (ub4) OCI_HTYPE_SESSION,
-                (dvoid *) pszUserid, (ub4) strlen((char *) pszUserid),
+                (dvoid *) pszUseridIn, (ub4) strlen((char *) pszUseridIn),
                 (ub4) OCI_ATTR_USERNAME, hError) ) )
     {
         return FALSE;
     }
 
     if( Failed( OCIAttrSet((dvoid *) hSession, (ub4) OCI_HTYPE_SESSION,
-                (dvoid *) pszPassword, (ub4) strlen((char *) pszPassword),
+                (dvoid *) pszPasswordIn, (ub4) strlen((char *) pszPasswordIn),
                 (ub4) OCI_ATTR_PASSWORD, hError) ) )
     {
         return FALSE;
@@ -218,7 +218,7 @@ int OGROCISession::EstablishSession( const char *pszUserid,
     if( Failed( OCISessionBegin(hSvcCtx, hError, hSession, eCred,
                 (ub4) OCI_DEFAULT) ) )
     {
-        CPLDebug("OCI", "OCISessionBegin() failed to intialize session");
+        CPLDebug("OCI", "OCISessionBegin() failed to initialize session");
         return FALSE;
     }
 
@@ -237,9 +237,9 @@ int OGROCISession::EstablishSession( const char *pszUserid,
 /*      Create a describe handle.                                       */
 /* -------------------------------------------------------------------- */
 
-    if( Failed( 
-        OCIHandleAlloc( hEnv, (dvoid **) &hDescribe, (ub4)OCI_HTYPE_DESCRIBE, 
-                        (size_t)0, (dvoid **)0 ), 
+    if( Failed(
+        OCIHandleAlloc( hEnv, (dvoid **) &hDescribe, (ub4)OCI_HTYPE_DESCRIBE,
+                        (size_t)0, (dvoid **)0 ),
         "OCIHandleAlloc(Describe)" ) )
         return FALSE;
 
@@ -249,8 +249,8 @@ int OGROCISession::EstablishSession( const char *pszUserid,
     /* If we have no MDSYS.SDO_GEOMETRY then we consider we are
         working along with the VRT driver and access non spatial tables.
         See #2202 for more details (Tamas Szekeres)*/
-    if (OCIDescribeAny(hSvcCtx, hError, 
-                       (text *) SDO_GEOMETRY, (ub4) strlen(SDO_GEOMETRY), 
+    if (OCIDescribeAny(hSvcCtx, hError,
+                       (text *) SDO_GEOMETRY, (ub4) strlen(SDO_GEOMETRY),
                        OCI_OTYPE_NAME, (ub1) OCI_DEFAULT, (ub1)OCI_PTYPE_TYPE,
                        hDescribe ) != OCI_ERROR)
     {
@@ -275,12 +275,12 @@ int OGROCISession::EstablishSession( const char *pszUserid,
 /* -------------------------------------------------------------------- */
 /*      Record information about the session.                           */
 /* -------------------------------------------------------------------- */
-    this->pszUserid = CPLStrdup(pszUserid);
-    this->pszPassword = CPLStrdup(pszPassword);
-    this->pszDatabase = CPLStrdup(pszDatabase);
+    this->pszUserid = CPLStrdup(pszUseridIn);
+    this->pszPassword = CPLStrdup(pszPasswordIn);
+    this->pszDatabase = CPLStrdup(pszDatabaseIn);
 
 /* -------------------------------------------------------------------- */
-/*      Setting upt the OGR compatible time formating rules.            */
+/*      Setting up the OGR compatible time formatting rules.            */
 /* -------------------------------------------------------------------- */
     OGROCIStatement     oSetNLSTimeFormat( this );
     if( oSetNLSTimeFormat.Execute( "ALTER SESSION SET NLS_DATE_FORMAT='YYYY/MM/DD' \
@@ -310,37 +310,37 @@ int OGROCISession::Failed( sword nStatus, const char *pszFunction )
         szErrorMsg[0] = '\0';
         if( hError != NULL )
         {
-            OCIErrorGet( (dvoid *) hError, (ub4) 1, NULL, &nErrCode, 
-                         (text *) szErrorMsg, (ub4) sizeof(szErrorMsg), 
+            OCIErrorGet( (dvoid *) hError, (ub4) 1, NULL, &nErrCode,
+                         (text *) szErrorMsg, (ub4) sizeof(szErrorMsg),
                          OCI_HTYPE_ERROR );
         }
         szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
 
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "%s in %s", szErrorMsg, pszFunction );
         return TRUE;
     }
     else if( nStatus == OCI_NEED_DATA )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "OCI_NEED_DATA" );
         return TRUE;
     }
     else if( nStatus == OCI_INVALID_HANDLE )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "OCI_INVALID_HANDLE in %s", pszFunction );
         return TRUE;
     }
     else if( nStatus == OCI_STILL_EXECUTING )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "OCI_STILL_EXECUTING in %s", pszFunction );
         return TRUE;
     }
     else if( nStatus == OCI_CONTINUE )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "OCI_CONTINUE in %s", pszFunction );
         return TRUE;
     }
@@ -352,7 +352,7 @@ int OGROCISession::Failed( sword nStatus, const char *pszFunction )
 /*                            GetParmInfo()                             */
 /************************************************************************/
 
-CPLErr 
+CPLErr
 OGROCISession::GetParmInfo( OCIParam *hParmDesc, OGRFieldDefn *poOGRDefn,
                             ub2 *pnOCIType, ub4 *pnOCILen )
 
@@ -362,46 +362,46 @@ OGROCISession::GetParmInfo( OCIParam *hParmDesc, OGRFieldDefn *poOGRDefn,
     ub1 bOCINull;
     char *pszColName;
     char szTermColName[128];
-    
+
 /* -------------------------------------------------------------------- */
 /*      Get basic parameter details.                                    */
 /* -------------------------------------------------------------------- */
-    if( Failed( 
-        OCIAttrGet( hParmDesc, OCI_DTYPE_PARAM, 
+    if( Failed(
+        OCIAttrGet( hParmDesc, OCI_DTYPE_PARAM,
                     (dvoid **)&nOCIType, 0, OCI_ATTR_DATA_TYPE, hError ),
         "OCIAttrGet(Type)" ) )
         return CE_Failure;
 
-    if( Failed( 
-        OCIAttrGet( hParmDesc, OCI_DTYPE_PARAM, 
+    if( Failed(
+        OCIAttrGet( hParmDesc, OCI_DTYPE_PARAM,
                     (dvoid **)&nOCILen, 0, OCI_ATTR_DATA_SIZE, hError ),
         "OCIAttrGet(Size)" ) )
         return CE_Failure;
 
     if( Failed(
         OCIAttrGet( hParmDesc, OCI_DTYPE_PARAM, (dvoid **)&pszColName,
-                    &nColLen, OCI_ATTR_NAME, hError ), 
+                    &nColLen, OCI_ATTR_NAME, hError ),
         "OCIAttrGet(Name)") )
         return CE_Failure;
 
     if( Failed(
         OCIAttrGet( hParmDesc, OCI_DTYPE_PARAM, (dvoid **)&bOCINull,
-                    0, OCI_ATTR_IS_NULL, hError ), 
+                    0, OCI_ATTR_IS_NULL, hError ),
         "OCIAttrGet(Null)") )
         return CE_Failure;
 
-    if( nColLen >= sizeof(szTermColName) )                              
+    if( nColLen >= sizeof(szTermColName) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Column length (%d) longer than column name buffer (%d) in\n"
-                  "OGROCISession::GetParmInfo()", 
+                  "OGROCISession::GetParmInfo()",
                   nColLen, (int) sizeof(szTermColName) );
         return CE_Failure;
     }
 
     strncpy( szTermColName, pszColName, nColLen );
     szTermColName[nColLen] = '\0';
-    
+
     poOGRDefn->SetName( szTermColName );
     poOGRDefn->SetNullable( bOCINull );
 
@@ -422,22 +422,22 @@ OGROCISession::GetParmInfo( OCIParam *hParmDesc, OGRFieldDefn *poOGRDefn,
             // NOTE: OCI docs say this should be ub1 type, but we have
             // determined that oracle is actually returning a short so we
             // use that type and try to compensate for possible problems by
-            // initializing, and dividing by 256 if it is large. 
+            // initializing, and dividing by 256 if it is large.
             unsigned short byPrecision = 0;
             sb1  nScale;
 
             if( Failed(
                 OCIAttrGet( hParmDesc, OCI_DTYPE_PARAM, (dvoid **)&byPrecision,
-                            0, OCI_ATTR_PRECISION, hError ), 
+                            0, OCI_ATTR_PRECISION, hError ),
                 "OCIAttrGet(Precision)" ) )
                 return CE_Failure;
             if( Failed(
                 OCIAttrGet( hParmDesc, OCI_DTYPE_PARAM, (dvoid **)&nScale,
-                            0, OCI_ATTR_SCALE, hError ), 
+                            0, OCI_ATTR_SCALE, hError ),
                 "OCIAttrGet(Scale)") )
                 return CE_Failure;
 #ifdef notdef
-            CPLDebug( "OCI", "%s: Scale=%d, Precision=%d", 
+            CPLDebug( "OCI", "%s: Scale=%d, Precision=%d",
                       szTermColName, nScale, byPrecision );
 #endif
             if( byPrecision > 255 )
@@ -516,8 +516,8 @@ void OGROCISession::CleanName( char * pszName )
 
     for( i = 0; pszName[i] != '\0'; i++ )
     {
-        pszName[i] = toupper(pszName[i]);
-        
+        pszName[i] = static_cast<char>(toupper(pszName[i]));
+
         if( (pszName[i] < '0' || pszName[i] > '9')
             && (pszName[i] < 'A' || pszName[i] > 'Z')
             && pszName[i] != '_' )
@@ -538,29 +538,29 @@ OCIType *OGROCISession::PinTDO( const char *pszType )
     OCIRef *hGeomTypeRef = NULL;
     OCIType *hPinnedTDO = NULL;
 
-    if( Failed( 
-        OCIDescribeAny(hSvcCtx, hError, 
-                       (text *) pszType, (ub4) strlen(pszType), 
-                       OCI_OTYPE_NAME, (ub1)1, (ub1)OCI_PTYPE_TYPE, 
-                       hDescribe ), 
+    if( Failed(
+        OCIDescribeAny(hSvcCtx, hError,
+                       (text *) pszType, (ub4) strlen(pszType),
+                       OCI_OTYPE_NAME, (ub1)1, (ub1)OCI_PTYPE_TYPE,
+                       hDescribe ),
         "GetTDO()->OCIDescribeAny()" ) )
         return NULL;
 
-    if( Failed( 
+    if( Failed(
         OCIAttrGet((dvoid *)hDescribe, (ub4)OCI_HTYPE_DESCRIBE,
-                   (dvoid *)&hGeomParam, (ub4 *)0, (ub4)OCI_ATTR_PARAM, 
+                   (dvoid *)&hGeomParam, (ub4 *)0, (ub4)OCI_ATTR_PARAM,
                    hError), "GetTDO()->OCIGetAttr(ATTR_PARAM)") )
         return NULL;
 
-    if( Failed( 
+    if( Failed(
         OCIAttrGet((dvoid *)hGeomParam, (ub4)OCI_DTYPE_PARAM,
-                   (dvoid *)&hGeomTypeRef, (ub4 *)0, (ub4)OCI_ATTR_REF_TDO, 
+                   (dvoid *)&hGeomTypeRef, (ub4 *)0, (ub4)OCI_ATTR_REF_TDO,
                    hError), "GetTDO()->OCIAttrGet(ATTR_REF_TDO)" ) )
         return NULL;
 
-    if( Failed( 
-        OCIObjectPin(hEnv, hError, hGeomTypeRef, (OCIComplexObject *)0, 
-                     OCI_PIN_ANY, OCI_DURATION_SESSION, 
+    if( Failed(
+        OCIObjectPin(hEnv, hError, hGeomTypeRef, (OCIComplexObject *)0,
+                     OCI_PIN_ANY, OCI_DURATION_SESSION,
                      OCI_LOCK_NONE, (dvoid **)&hPinnedTDO ),
         "GetTDO()->OCIObjectPin()" ) )
         return NULL;
diff --git a/ogr/ogrsf_frmts/oci/ogrocistatement.cpp b/ogr/ogrsf_frmts/oci/ogrocistatement.cpp
index aea733c..4e922cf 100644
--- a/ogr/ogrsf_frmts/oci/ogrocistatement.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrocistatement.cpp
@@ -1,9 +1,9 @@
 /******************************************************************************
- * $Id: ogrocistatement.cpp 28809 2015-03-28 17:10:07Z rouault $
+ * $Id: ogrocistatement.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Oracle Spatial Driver
- * Purpose:  Implementation of OGROCIStatement, which encapsulates the 
- *           preparation, executation and fetching from an SQL statement.
+ * Purpose:  Implementation of OGROCIStatement, which encapsulates the
+ *           preparation, execution and fetching from an SQL statement.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -31,7 +31,7 @@
 #include "ogr_oci.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrocistatement.cpp 28809 2015-03-28 17:10:07Z rouault $");
+CPL_CVSID("$Id: ogrocistatement.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                          OGROCIStatement()                           */
@@ -86,7 +86,7 @@ void OGROCIStatement::Clean()
 
     CPLFree( papszCurImage );
     papszCurImage = NULL;
-    
+
     CPLFree( panCurColumnInd );
     panCurColumnInd = NULL;
 
@@ -121,7 +121,7 @@ CPLErr OGROCIStatement::Prepare( const char *pszSQLStatement )
 
     if( hStatement != NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Statement already executed once on this OGROCIStatement." );
         return CE_Failure;
     }
@@ -129,9 +129,9 @@ CPLErr OGROCIStatement::Prepare( const char *pszSQLStatement )
 /* -------------------------------------------------------------------- */
 /*      Allocate a statement handle.                                    */
 /* -------------------------------------------------------------------- */
-    if( poSession->Failed( 
-        OCIHandleAlloc( poSession->hEnv, (dvoid **) &hStatement, 
-                        (ub4)OCI_HTYPE_STMT,(size_t)0, (dvoid **)0 ), 
+    if( poSession->Failed(
+        OCIHandleAlloc( poSession->hEnv, (dvoid **) &hStatement,
+                        (ub4)OCI_HTYPE_STMT,(size_t)0, (dvoid **)0 ),
         "OCIHandleAlloc(Statement)" ) )
         return CE_Failure;
 
@@ -139,8 +139,8 @@ CPLErr OGROCIStatement::Prepare( const char *pszSQLStatement )
 /*      Prepare the statement.                                          */
 /* -------------------------------------------------------------------- */
     if( poSession->Failed(
-        OCIStmtPrepare( hStatement, poSession->hError, 
-                        (text *) pszSQLStatement, strlen(pszSQLStatement),
+        OCIStmtPrepare( hStatement, poSession->hError,
+                        (text *) pszSQLStatement, static_cast<unsigned int>(strlen(pszSQLStatement)),
                         (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT ),
         "OCIStmtPrepare" ) )
         return CE_Failure;
@@ -152,25 +152,25 @@ CPLErr OGROCIStatement::Prepare( const char *pszSQLStatement )
 /*                             BindObject()                             */
 /************************************************************************/
 
-CPLErr OGROCIStatement::BindObject( const char *pszPlaceName, 
+CPLErr OGROCIStatement::BindObject( const char *pszPlaceName,
                                     void *pahObjects, OCIType *hTDO,
                                     void **papIndicators )
 
 {
     OCIBind *hBindOrd = NULL;
 
-    if( poSession->Failed( 
+    if( poSession->Failed(
             OCIBindByName( hStatement, &hBindOrd, poSession->hError,
-                           (text *) pszPlaceName, (sb4) strlen(pszPlaceName), 
-                           (dvoid *) 0, (sb4) 0, SQLT_NTY, (dvoid *)0, 
-                           (ub2 *)0, (ub2 *)0, (ub4)0, (ub4 *)0, 
+                           (text *) pszPlaceName, (sb4) strlen(pszPlaceName),
+                           (dvoid *) 0, (sb4) 0, SQLT_NTY, (dvoid *)0,
+                           (ub2 *)0, (ub2 *)0, (ub4)0, (ub4 *)0,
                            (ub4)OCI_DEFAULT),
             "OCIBindByName()") )
         return CE_Failure;
-    
+
     if( poSession->Failed(
             OCIBindObject( hBindOrd, poSession->hError, hTDO,
-                           (dvoid **) pahObjects, (ub4 *)0, 
+                           (dvoid **) pahObjects, (ub4 *)0,
                            (dvoid **)papIndicators, (ub4 *)0),
             "OCIBindObject()" ) )
         return CE_Failure;
@@ -182,19 +182,19 @@ CPLErr OGROCIStatement::BindObject( const char *pszPlaceName,
 /*                             BindScalar()                             */
 /************************************************************************/
 
-CPLErr OGROCIStatement::BindScalar( const char *pszPlaceName, 
+CPLErr OGROCIStatement::BindScalar( const char *pszPlaceName,
                                     void *pData, int nDataLen,
                                     int nSQLType, sb2 *paeInd )
 
 {
     OCIBind *hBindOrd = NULL;
 
-    if( poSession->Failed( 
+    if( poSession->Failed(
             OCIBindByName( hStatement, &hBindOrd, poSession->hError,
-                           (text *) pszPlaceName, (sb4) strlen(pszPlaceName), 
-                           (dvoid *) pData, (sb4) nDataLen, 
-                           (ub2) nSQLType, (dvoid *)paeInd, (ub2 *)0, 
-                           (ub2 *)0, (ub4)0, (ub4 *)0, 
+                           (text *) pszPlaceName, (sb4) strlen(pszPlaceName),
+                           (dvoid *) pData, (sb4) nDataLen,
+                           (ub2) nSQLType, (dvoid *)paeInd, (ub2 *)0,
+                           (ub2 *)0, (ub4)0, (ub4 *)0,
                            (ub4)OCI_DEFAULT),
             "OCIBindByName()") )
         return CE_Failure;
@@ -222,7 +222,7 @@ CPLErr OGROCIStatement::Execute( const char *pszSQLStatement,
 
     if( hStatement == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "No prepared statement in call to OGROCIStatement::Execute(NULL)" );
         return CE_Failure;
     }
@@ -232,12 +232,12 @@ CPLErr OGROCIStatement::Execute( const char *pszSQLStatement,
 /* -------------------------------------------------------------------- */
     ub2  nStmtType;
 
-    if( poSession->Failed( 
+    if( poSession->Failed(
         OCIAttrGet( hStatement, OCI_HTYPE_STMT,
                     &nStmtType, 0, OCI_ATTR_STMT_TYPE, poSession->hError ),
         "OCIAttrGet(ATTR_STMT_TYPE)") )
         return CE_Failure;
-    
+
     int bSelect = (nStmtType == OCI_STMT_SELECT);
 
 /* -------------------------------------------------------------------- */
@@ -254,9 +254,9 @@ CPLErr OGROCIStatement::Execute( const char *pszSQLStatement,
 /* -------------------------------------------------------------------- */
 /*      Execute the statement.                                          */
 /* -------------------------------------------------------------------- */
-    if( poSession->Failed( 
-        OCIStmtExecute( poSession->hSvcCtx, hStatement, 
-                        poSession->hError, (ub4)bSelect ? 0 : 1, (ub4)0, 
+    if( poSession->Failed(
+        OCIStmtExecute( poSession->hSvcCtx, hStatement,
+                        poSession->hError, (ub4)bSelect ? 0 : 1, (ub4)0,
                         (OCISnapshot *)NULL, (OCISnapshot *)NULL, nMode ),
         pszCommandText ) )
         return CE_Failure;
@@ -264,7 +264,7 @@ CPLErr OGROCIStatement::Execute( const char *pszSQLStatement,
     if( !bSelect )
     {
         ub4 row_count;
-        if( poSession->Failed( 
+        if( poSession->Failed(
             OCIAttrGet( hStatement, OCI_HTYPE_STMT,
                         &row_count, 0, OCI_ATTR_ROW_COUNT, poSession->hError ),
                         "OCIAttrGet(OCI_ATTR_ROW_COUNT)") )
@@ -277,21 +277,21 @@ CPLErr OGROCIStatement::Execute( const char *pszSQLStatement,
 /* -------------------------------------------------------------------- */
 /*      Count the columns.                                              */
 /* -------------------------------------------------------------------- */
-    for( nRawColumnCount = 0; TRUE; nRawColumnCount++ )
-    {                                                           
+    for( nRawColumnCount = 0; true; nRawColumnCount++ )
+    {
         OCIParam     *hParmDesc;
 
-        if( OCIParamGet( hStatement, OCI_HTYPE_STMT, poSession->hError, 
-                         (dvoid**)&hParmDesc, 
+        if( OCIParamGet( hStatement, OCI_HTYPE_STMT, poSession->hError,
+                         (dvoid**)&hParmDesc,
                          (ub4) nRawColumnCount+1 ) != OCI_SUCCESS )
             break;
     }
-    
+
     panFieldMap = (int *) CPLCalloc(sizeof(int),nRawColumnCount);
-    
+
     papszCurColumn = (char **) CPLCalloc(sizeof(char*),nRawColumnCount+1);
     panCurColumnInd = (sb2 *) CPLCalloc(sizeof(sb2),nRawColumnCount+1);
-        
+
 /* ==================================================================== */
 /*      Establish result column definitions, and setup parameter        */
 /*      defines.                                                        */
@@ -301,7 +301,7 @@ CPLErr OGROCIStatement::Execute( const char *pszSQLStatement,
     poDefn->Reference();
 
     for( int iParm = 0; iParm < nRawColumnCount; iParm++ )
-    {                                                           
+    {
         OGRFieldDefn oField( "", OFTString );
         OCIParam     *hParmDesc;
         ub2          nOCIType;
@@ -310,8 +310,8 @@ CPLErr OGROCIStatement::Execute( const char *pszSQLStatement,
 /* -------------------------------------------------------------------- */
 /*      Get parameter definition.                                       */
 /* -------------------------------------------------------------------- */
-        if( poSession->Failed( 
-            OCIParamGet( hStatement, OCI_HTYPE_STMT, poSession->hError, 
+        if( poSession->Failed(
+            OCIParamGet( hStatement, OCI_HTYPE_STMT, poSession->hError,
                          (dvoid**)&hParmDesc, (ub4) iParm+1 ),
             "OCIParamGet") )
             return CE_Failure;
@@ -345,7 +345,7 @@ CPLErr OGROCIStatement::Execute( const char *pszSQLStatement,
         OCIDefine *hDefn = NULL;
 
         if( oField.GetWidth() > 0 )
-            /* extra space needed for the decimal separator the string 
+            /* extra space needed for the decimal separator the string
             terminator and the negative sign (Tamas Szekeres)*/
             nBufWidth = oField.GetWidth() + 3;
         else if( oField.GetType() == OFTInteger )
@@ -362,9 +362,9 @@ CPLErr OGROCIStatement::Execute( const char *pszSQLStatement,
 
         if( poSession->Failed(
             OCIDefineByPos( hStatement, &hDefn, poSession->hError,
-                            iParm+1, 
+                            iParm+1,
                             (ub1 *) papszCurColumn[nOGRField], nBufWidth,
-                            SQLT_STR, panCurColumnInd + nOGRField, 
+                            SQLT_STR, panCurColumnInd + nOGRField,
                             NULL, NULL, OCI_DEFAULT ),
             "OCIDefineByPos" ) )
             return CE_Failure;
@@ -381,14 +381,14 @@ char **OGROCIStatement::SimpleFetchRow()
 
 {
     int nStatus, i;
-    
+
     if( papszCurImage == NULL )
     {
-        papszCurImage = (char **) 
+        papszCurImage = (char **)
             CPLCalloc(sizeof(char *), nRawColumnCount+1 );
     }
 
-    nStatus = OCIStmtFetch( hStatement, poSession->hError, 1, 
+    nStatus = OCIStmtFetch( hStatement, poSession->hError, 1,
                             OCI_FETCH_NEXT, OCI_DEFAULT );
 
     if( nStatus == OCI_NO_DATA )
@@ -406,4 +406,3 @@ char **OGROCIStatement::SimpleFetchRow()
 
     return papszCurImage;
 }
-
diff --git a/ogr/ogrsf_frmts/oci/ogrocistringbuf.cpp b/ogr/ogrsf_frmts/oci/ogrocistringbuf.cpp
index 2f091aa..ab911a4 100644
--- a/ogr/ogrsf_frmts/oci/ogrocistringbuf.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrocistringbuf.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: ogrocistringbuf.cpp 28429 2015-02-06 20:56:30Z rouault $
+ * $Id: ogrocistringbuf.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Oracle Spatial Driver
- * Purpose:  Simple string buffer used to accumulate text of commands 
+ * Purpose:  Simple string buffer used to accumulate text of commands
  *           efficiently.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -31,7 +31,7 @@
 #include "ogr_oci.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrocistringbuf.cpp 28429 2015-02-06 20:56:30Z rouault $");
+CPL_CVSID("$Id: ogrocistringbuf.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                          OGROCIStringBuf()                           */
@@ -78,7 +78,7 @@ void OGROCIStringBuf::MakeRoomFor( int nCharacters )
 void OGROCIStringBuf::Append( const char *pszNewText )
 
 {
-    int  nNewLen = strlen(pszNewText);
+    int  nNewLen = static_cast<int>(strlen(pszNewText));
 
     MakeRoomFor( nNewLen );
     strcat( pszString+nLen, pszNewText );
@@ -96,7 +96,7 @@ void OGROCIStringBuf::Appendf( int nMax, const char *pszFormat, ... )
     char    szSimpleBuf[100];
     char    *pszBuffer;
 
-    if( nMax > (int) sizeof(szSimpleBuf-1) )
+    if( nMax > (int) sizeof(szSimpleBuf)-1 )
         pszBuffer = (char *) CPLMalloc(nMax+1);
     else
         pszBuffer = szSimpleBuf;
@@ -117,7 +117,7 @@ void OGROCIStringBuf::Appendf( int nMax, const char *pszFormat, ... )
 void OGROCIStringBuf::UpdateEnd()
 
 {
-    nLen += strlen(pszString+nLen);
+    nLen += static_cast<int>(strlen(pszString+nLen));
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/oci/ogrocistroke.cpp b/ogr/ogrsf_frmts/oci/ogrocistroke.cpp
index 5d0e21d..da7aa4d 100644
--- a/ogr/ogrsf_frmts/oci/ogrocistroke.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrocistroke.cpp
@@ -32,22 +32,18 @@
 
 CPL_CVSID("$Id: ntfstroke.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
 
-#ifndef PI
-#define PI  3.14159265358979323846
-#endif 
-
 /************************************************************************/
 /*                   OGROCIArcCenterFromEdgePoints()                    */
 /*                                                                      */
 /*      Compute the center of an arc/circle from three edge points.     */
 /************************************************************************/
 
-static int 
+static int
 OGROCIArcCenterFromEdgePoints( double x_c0, double y_c0,
-                               double x_c1, double y_c1, 
-                               double x_c2, double y_c2, 
+                               double x_c1, double y_c1,
+                               double x_c2, double y_c2,
                                double *x_center, double *y_center )
-    
+
 {
 
 /* -------------------------------------------------------------------- */
@@ -97,29 +93,29 @@ OGROCIArcCenterFromEdgePoints( double x_c0, double y_c0,
 /* -------------------------------------------------------------------- */
 /*      Turn these into the Ax+By+C = 0 form of the lines.              */
 /* -------------------------------------------------------------------- */
-    double      a1, a2, b1, b2, c1, c2;
+    double      a1, a2, l_b1, l_b2, c1, c2;
 
     a1 = m1;
     a2 = m2;
 
-    b1 = -1.0;
-    b2 = -1.0;
-    
+    l_b1 = -1.0;
+    l_b2 = -1.0;
+
     c1 = (y1 - m1*x1);
     c2 = (y2 - m2*x2);
-    
+
 /* -------------------------------------------------------------------- */
 /*      Compute the intersection of the two lines through the center    */
 /*      of the circle, using Kramers rule.                              */
 /* -------------------------------------------------------------------- */
     double      det_inv;
 
-    if( a1*b2 - a2*b1 == 0.0 )
+    if( a1*l_b2 - a2*l_b1 == 0.0 )
         return FALSE;
 
-    det_inv = 1 / (a1*b2 - a2*b1);
+    det_inv = 1 / (a1*l_b2 - a2*l_b1);
 
-    *x_center = (b1*c2 - b2*c1) * det_inv;
+    *x_center = (l_b1*c2 - l_b2*c1) * det_inv;
     *y_center = (a2*c1 - a1*c2) * det_inv;
 
     return TRUE;
@@ -129,9 +125,9 @@ OGROCIArcCenterFromEdgePoints( double x_c0, double y_c0,
 /*                OGROCIStrokeArcToOGRGeometry_Angles()                 */
 /************************************************************************/
 
-static int 
-OGROCIStrokeArcToOGRGeometry_Angles( double dfCenterX, double dfCenterY, 
-                                     double dfRadius, 
+static int
+OGROCIStrokeArcToOGRGeometry_Angles( double dfCenterX, double dfCenterY,
+                                     double dfRadius,
                                      double dfStartAngle, double dfEndAngle,
                                      double dfMaxAngleStepSizeDegrees,
                                      OGRLineString *poLine )
@@ -141,34 +137,33 @@ OGROCIStrokeArcToOGRGeometry_Angles( double dfCenterX, double dfCenterY,
     int                iPoint, iAppendLocation, nVertexCount;
     double             dfEps = dfRadius / 100000.0;
 
-    nVertexCount = (int) 
+    nVertexCount = (int)
         ceil(fabs(dfEndAngle - dfStartAngle)/dfMaxAngleStepSizeDegrees) + 1;
     nVertexCount = MAX(2,nVertexCount);
     dfSlice = (dfEndAngle-dfStartAngle)/(nVertexCount-1);
+    iAppendLocation = poLine->getNumPoints();
 
     for( iPoint=0; iPoint < nVertexCount; iPoint++ )
     {
         double      dfAngle;
 
-        dfAngle = (dfStartAngle + iPoint * dfSlice) * PI / 180.0;
+        dfAngle = (dfStartAngle + iPoint * dfSlice) * M_PI / 180.0;
 
         dfArcX = dfCenterX + cos(dfAngle) * dfRadius;
         dfArcY = dfCenterY + sin(dfAngle) * dfRadius;
 
         if( iPoint == 0 )
         {
-            iAppendLocation = poLine->getNumPoints();
-
-            if( poLine->getNumPoints() > 0 
+            if( poLine->getNumPoints() > 0
                 && fabs(poLine->getX(poLine->getNumPoints()-1)-dfArcX) < dfEps
                 && fabs(poLine->getY(poLine->getNumPoints()-1)-dfArcY) < dfEps)
             {
-                poLine->setNumPoints( 
+                poLine->setNumPoints(
                     poLine->getNumPoints() + nVertexCount - 1 );
             }
             else
             {
-                poLine->setNumPoints( 
+                poLine->setNumPoints(
                     poLine->getNumPoints() + nVertexCount - 1 );
                 poLine->setPoint( iAppendLocation++, dfArcX, dfArcY );
             }
@@ -185,21 +180,21 @@ OGROCIStrokeArcToOGRGeometry_Angles( double dfCenterX, double dfCenterY,
 /*                OGROCIStrokeArcToOGRGeometry_Points()                 */
 /************************************************************************/
 
-int 
+int
 OGROCIStrokeArcToOGRGeometry_Points( double dfStartX, double dfStartY,
                                      double dfAlongX, double dfAlongY,
                                      double dfEndX, double dfEndY,
                                      double dfMaxAngleStepSizeDegrees,
                                      int bForceWholeCircle,
                                      OGRLineString *poLine )
-    
+
 {
     double      dfStartAngle, dfEndAngle, dfAlongAngle;
     double      dfCenterX, dfCenterY, dfRadius;
 
-    if( !OGROCIArcCenterFromEdgePoints( dfStartX, dfStartY, 
+    if( !OGROCIArcCenterFromEdgePoints( dfStartX, dfStartY,
                                         dfAlongX, dfAlongY,
-                                        dfEndX, dfEndY, 
+                                        dfEndX, dfEndY,
                                         &dfCenterX, &dfCenterY ) )
         return FALSE;
 
@@ -214,15 +209,15 @@ OGROCIStrokeArcToOGRGeometry_Points( double dfStartX, double dfStartY,
 
         dfDeltaX = dfStartX - dfCenterX;
         dfDeltaY = dfStartY - dfCenterY;
-        dfStartAngle = atan2(dfDeltaY,dfDeltaX) * 180.0 / PI;
+        dfStartAngle = atan2(dfDeltaY,dfDeltaX) * 180.0 / M_PI;
 
         dfDeltaX = dfAlongX - dfCenterX;
         dfDeltaY = dfAlongY - dfCenterY;
-        dfAlongAngle = atan2(dfDeltaY,dfDeltaX) * 180.0 / PI;
+        dfAlongAngle = atan2(dfDeltaY,dfDeltaX) * 180.0 / M_PI;
 
         dfDeltaX = dfEndX - dfCenterX;
         dfDeltaY = dfEndY - dfCenterY;
-        dfEndAngle = atan2(dfDeltaY,dfDeltaX) * 180.0 / PI;
+        dfEndAngle = atan2(dfDeltaY,dfDeltaX) * 180.0 / M_PI;
 
         // Try positive (clockwise?) winding.
         while( dfAlongAngle < dfStartAngle )
@@ -236,7 +231,7 @@ OGROCIStrokeArcToOGRGeometry_Points( double dfStartX, double dfStartY,
         {
             while( dfAlongAngle > dfStartAngle )
                 dfAlongAngle -= 360.0;
-            
+
             while( dfEndAngle > dfAlongAngle )
                 dfEndAngle -= 360.0;
         }
@@ -247,9 +242,9 @@ OGROCIStrokeArcToOGRGeometry_Points( double dfStartX, double dfStartY,
 
     int bResult;
 
-    bResult = 
-        OGROCIStrokeArcToOGRGeometry_Angles( dfCenterX, dfCenterY, 
-                                             dfRadius, 
+    bResult =
+        OGROCIStrokeArcToOGRGeometry_Angles( dfCenterX, dfCenterY,
+                                             dfRadius,
                                              dfStartAngle, dfEndAngle,
                                              dfMaxAngleStepSizeDegrees,
                                              poLine );
@@ -262,10 +257,9 @@ OGROCIStrokeArcToOGRGeometry_Points( double dfStartX, double dfStartY,
 /* -------------------------------------------------------------------- */
     if( bResult && !bForceWholeCircle )
     {
-        poLine->setPoint( poLine->getNumPoints() - 1, 
+        poLine->setPoint( poLine->getNumPoints() - 1,
                           dfEndX, dfEndY );
     }
 
     return bResult;
 }
-
diff --git a/ogr/ogrsf_frmts/oci/ogrocitablelayer.cpp b/ogr/ogrsf_frmts/oci/ogrocitablelayer.cpp
index 241840f..5cf9b45 100644
--- a/ogr/ogrsf_frmts/oci/ogrocitablelayer.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrocitablelayer.cpp
@@ -1,9 +1,9 @@
 /******************************************************************************
- * $Id: ogrocitablelayer.cpp 28809 2015-03-28 17:10:07Z rouault $
+ * $Id: ogrocitablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Implementation of the OGROCITableLayer class.  This class provides
- *           layer semantics on a table, but utilizing alot of machinery from
+ *           layer semantics on a table, but utilizing a lot of machinery from
  *           the OGROCILayer base class.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -33,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrocitablelayer.cpp 28809 2015-03-28 17:10:07Z rouault $");
+CPL_CVSID("$Id: ogrocitablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 static int nDiscarded = 0;
 static int nHits = 0;
@@ -44,7 +44,7 @@ static int nHits = 0;
 /*                          OGROCITableLayer()                          */
 /************************************************************************/
 
-OGROCITableLayer::OGROCITableLayer( OGROCIDataSource *poDSIn, 
+OGROCITableLayer::OGROCITableLayer( OGROCIDataSource *poDSIn,
                                     const char * pszTableName, OGRwkbGeometryType eGType,
                                     int nSRIDIn, int bUpdate, int bNewLayerIn )
 
@@ -55,7 +55,7 @@ OGROCITableLayer::OGROCITableLayer( OGROCIDataSource *poDSIn,
     pszQuery = NULL;
     pszWHERE = CPLStrdup( "" );
     pszQueryStatement = NULL;
-    
+
     bUpdateAccess = bUpdate;
     bNewLayer = bNewLayerIn;
 
@@ -76,7 +76,7 @@ OGROCITableLayer::OGROCITableLayer( OGROCIDataSource *poDSIn,
     nSRID = nSRIDIn;
     if( nSRID == -1 )
         nSRID = LookupTableSRID();
-        
+
     poSRS = poDSIn->FetchSRS( nSRID );
     if( poSRS != NULL )
         poSRS->Reference();
@@ -130,7 +130,7 @@ OGROCITableLayer::~OGROCITableLayer()
 
     CPLFree( pasWriteGeomInd );
     CPLFree( papsWriteGeomIndMap );
-    
+
     CPLFree( papsWriteGeomMap );
     CPLFree( pasWriteGeoms );
 
@@ -188,10 +188,10 @@ OGRFeatureDefn *OGROCITableLayer::ReadTableDefinition( const char * pszTable )
 
     // Table name unquoted
 
-    nStatus = 
+    nStatus =
         OCIDescribeAny( poSession->hSvcCtx, poSession->hError,
-                        (dvoid *) osUnquotedTableName.c_str(), 
-                        osUnquotedTableName.length(), OCI_OTYPE_NAME,
+                        (dvoid *) osUnquotedTableName.c_str(),
+                        static_cast<ub4>(osUnquotedTableName.length()), OCI_OTYPE_NAME,
                         OCI_DEFAULT, OCI_PTYPE_TABLE, poSession->hDescribe );
 
     if( poSession->Failed( nStatus, "OCIDescribeAny" ) )
@@ -202,8 +202,8 @@ OGRFeatureDefn *OGROCITableLayer::ReadTableDefinition( const char * pszTable )
 
         nStatus =
             OCIDescribeAny(poSession->hSvcCtx, poSession->hError,
-                           (dvoid *) osQuotedTableName.c_str(), 
-                           osQuotedTableName.length(), OCI_OTYPE_NAME,
+                           (dvoid *) osQuotedTableName.c_str(),
+                           static_cast<ub4>(osQuotedTableName.length()), OCI_OTYPE_NAME,
                            OCI_DEFAULT, OCI_PTYPE_VIEW, poSession->hDescribe );
 
         if( poSession->Failed( nStatus, "OCIDescribeAny" ) )
@@ -212,10 +212,10 @@ OGRFeatureDefn *OGROCITableLayer::ReadTableDefinition( const char * pszTable )
 
             // Table name quoted
 
-            nStatus = 
+            nStatus =
                 OCIDescribeAny( poSession->hSvcCtx, poSession->hError,
-                                (dvoid *) osQuotedTableName.c_str(), 
-                                osQuotedTableName.length(), OCI_OTYPE_NAME,
+                                (dvoid *) osQuotedTableName.c_str(),
+                                static_cast<ub4>(osQuotedTableName.length()), OCI_OTYPE_NAME,
                                 OCI_DEFAULT, OCI_PTYPE_TABLE, poSession->hDescribe );
 
             if( poSession->Failed( nStatus, "OCIDescribeAny" ) )
@@ -226,8 +226,8 @@ OGRFeatureDefn *OGROCITableLayer::ReadTableDefinition( const char * pszTable )
 
                 nStatus =
                     OCIDescribeAny(poSession->hSvcCtx, poSession->hError,
-                                   (dvoid *) osQuotedTableName.c_str(), 
-                                   osQuotedTableName.length(), OCI_OTYPE_NAME,
+                                   (dvoid *) osQuotedTableName.c_str(),
+                                   static_cast<ub4>(osQuotedTableName.length()), OCI_OTYPE_NAME,
                                    OCI_DEFAULT, OCI_PTYPE_VIEW, poSession->hDescribe );
 
                 if( poSession->Failed( nStatus, "OCIDescribeAny" ) )
@@ -236,14 +236,14 @@ OGRFeatureDefn *OGROCITableLayer::ReadTableDefinition( const char * pszTable )
         }
     }
 
-    if( poSession->Failed( 
-        OCIAttrGet( poSession->hDescribe, OCI_HTYPE_DESCRIBE, 
+    if( poSession->Failed(
+        OCIAttrGet( poSession->hDescribe, OCI_HTYPE_DESCRIBE,
                     &hAttrParam, 0, OCI_ATTR_PARAM, poSession->hError ),
         "OCIAttrGet(ATTR_PARAM)") )
         return poDefn;
 
-    if( poSession->Failed( 
-        OCIAttrGet( hAttrParam, OCI_DTYPE_PARAM, &hAttrList, 0, 
+    if( poSession->Failed(
+        OCIAttrGet( hAttrParam, OCI_DTYPE_PARAM, &hAttrList, 0,
                     OCI_ATTR_LIST_COLUMNS, poSession->hError ),
         "OCIAttrGet(ATTR_LIST_COLUMNS)" ) )
         return poDefn;
@@ -255,23 +255,22 @@ OGRFeatureDefn *OGROCITableLayer::ReadTableDefinition( const char * pszTable )
 /*      primary key and use that, but I'm not yet sure how to           */
 /*      accomplish that.                                                */
 /* -------------------------------------------------------------------- */
-    const char *pszExpectedFIDName = 
+    const char *pszExpectedFIDName =
         CPLGetConfigOption( "OCI_FID", "OGR_FID" );
     int bGeomFieldNullable = FALSE;
 
 /* -------------------------------------------------------------------- */
 /*      Parse the returned table information.                           */
 /* -------------------------------------------------------------------- */
-    for( int iRawFld = 0; TRUE; iRawFld++ )
+    for( int iRawFld = 0; true; iRawFld++ )
     {
         OGRFieldDefn    oField( "", OFTString);
         OCIParam     *hParmDesc;
         ub2          nOCIType;
         ub4          nOCILen;
-        sword        nStatus;
 
         nStatus = OCIParamGet( hAttrList, OCI_DTYPE_PARAM,
-                               poSession->hError, (dvoid**)&hParmDesc, 
+                               poSession->hError, (dvoid**)&hParmDesc,
                                (ub4) iRawFld+1 );
         if( nStatus != OCI_SUCCESS )
             break;
@@ -289,10 +288,10 @@ OGRFeatureDefn *OGROCITableLayer::ReadTableDefinition( const char * pszTable )
                 iGeomColumn = iRawFld;
                 bGeomFieldNullable = oField.IsNullable();
             }
-            continue;                   
+            continue;
         }
 
-        if( EQUAL(oField.GetNameRef(),pszExpectedFIDName) 
+        if( EQUAL(oField.GetNameRef(),pszExpectedFIDName)
             && (oField.GetType() == OFTInteger ||
                 oField.GetType() == OFTInteger64) )
         {
@@ -335,7 +334,7 @@ OGRFeatureDefn *OGROCITableLayer::ReadTableDefinition( const char * pszTable )
             }
         }
     }
-    
+
     /* -------------------------------------------------------------------- */
     /*      Identify Geometry dimension                                     */
     /* -------------------------------------------------------------------- */
@@ -402,7 +401,7 @@ OGRFeatureDefn *OGROCITableLayer::ReadTableDefinition( const char * pszTable )
         {
             CPLDebug( "OCI", "get dim based of existing data or index failed." );
         }
-        
+
         {
             OGROCIStringBuf oDimCmd2;
             OGROCIStatement oDimStatement2( poSession );
@@ -485,7 +484,7 @@ void OGROCITableLayer::TestForSpatialIndex( const char *pszSpatWHERE )
 {
     OGROCIStringBuf oTestCmd;
     OGROCIStatement oTestStatement( poDS->GetSession() );
-        
+
     oTestCmd.Append( "SELECT COUNT(*) FROM " );
     oTestCmd.Append( poFeatureDefn->GetName() );
     oTestCmd.Append( pszSpatWHERE );
@@ -615,8 +614,8 @@ OGRFeature *OGROCITableLayer::GetFeature( GIntBig nFeatureId )
     oCmd.Append( " FROM " );
     oCmd.Append( poFeatureDefn->GetName() );
     oCmd.Append( " " );
-    oCmd.Appendf( 50+strlen(pszFIDName), 
-                  " WHERE \"%s\" = " CPL_FRMT_GIB " ", 
+    oCmd.Appendf( static_cast<int>(50+strlen(pszFIDName)),
+                  " WHERE \"%s\" = " CPL_FRMT_GIB " ",
                   pszFIDName, nFeatureId );
 
 /* -------------------------------------------------------------------- */
@@ -631,7 +630,7 @@ OGRFeature *OGROCITableLayer::GetFeature( GIntBig nFeatureId )
     OGRFeature *poFeature;
 
     poFeature = GetNextRawFeature();
-    
+
     if( poFeature != NULL && poFeature->GetGeometryRef() != NULL )
         poFeature->GetGeometryRef()->assignSpatialReference( poSRS );
 
@@ -645,7 +644,7 @@ OGRFeature *OGROCITableLayer::GetFeature( GIntBig nFeatureId )
 /* -------------------------------------------------------------------- */
     if( poFeature != NULL && poFeature->GetFID() != nFeatureId )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "OGROCITableLayer::GetFeature(" CPL_FRMT_GIB ") ... query returned feature " CPL_FRMT_GIB " instead!",
                   nFeatureId, poFeature->GetFID() );
         delete poFeature;
@@ -668,7 +667,7 @@ OGRFeature *OGROCITableLayer::GetNextFeature()
 
 {
 
-    for( ; TRUE; )
+    while( true )
     {
         OGRFeature      *poFeature;
 
@@ -728,7 +727,7 @@ char *OGROCITableLayer::BuildFields()
     int         i;
     OGROCIStringBuf oFldList;
 
-    if( pszGeomName )                                                   
+    if( pszGeomName )
     {
         oFldList.Append( "\"" );
         oFldList.Append( pszGeomName );
@@ -763,23 +762,23 @@ char *OGROCITableLayer::BuildFields()
 /*                         SetAttributeFilter()                         */
 /************************************************************************/
 
-OGRErr OGROCITableLayer::SetAttributeFilter( const char *pszQuery )
+OGRErr OGROCITableLayer::SetAttributeFilter( const char *pszQueryIn )
 
 {
     CPLFree(m_pszAttrQueryString);
-    m_pszAttrQueryString = (pszQuery) ? CPLStrdup(pszQuery) : NULL;
+    m_pszAttrQueryString = (pszQueryIn) ? CPLStrdup(pszQueryIn) : NULL;
 
-    if( (pszQuery == NULL && this->pszQuery == NULL)
-        || (pszQuery != NULL && this->pszQuery != NULL
-            && strcmp(pszQuery,this->pszQuery) == 0) )
+    if( (pszQueryIn == NULL && this->pszQuery == NULL)
+        || (pszQueryIn != NULL && this->pszQuery != NULL
+            && strcmp(pszQueryIn,this->pszQuery) == 0) )
         return OGRERR_NONE;
-    
+
     CPLFree( this->pszQuery );
 
-    if( pszQuery == NULL )
+    if( pszQueryIn == NULL )
         this->pszQuery = NULL;
     else
-        this->pszQuery = CPLStrdup( pszQuery );
+        this->pszQuery = CPLStrdup( pszQueryIn );
 
     BuildWhere();
 
@@ -805,10 +804,10 @@ OGRErr OGROCITableLayer::ISetFeature( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
     if( pszFIDName == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "OGROCITableLayer::ISetFeature(" CPL_FRMT_GIB ") failed because there is "
                   "no apparent FID column on table %s.",
-                  poFeature->GetFID(), 
+                  poFeature->GetFID(),
                   poFeatureDefn->GetName() );
 
         return OGRERR_FAILURE;
@@ -816,7 +815,7 @@ OGRErr OGROCITableLayer::ISetFeature( OGRFeature *poFeature )
 
     if( poFeature->GetFID() == OGRNullFID )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "OGROCITableLayer::ISetFeature(" CPL_FRMT_GIB ") failed because the feature "
                   "has no FID!", poFeature->GetFID() );
 
@@ -842,10 +841,10 @@ OGRErr OGROCITableLayer::DeleteFeature( GIntBig nFID )
 /* -------------------------------------------------------------------- */
     if( pszFIDName == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "OGROCITableLayer::DeleteFeature(" CPL_FRMT_GIB ") failed because there is "
                   "no apparent FID column on table %s.",
-                  nFID, 
+                  nFID,
                   poFeatureDefn->GetName() );
 
         return OGRERR_FAILURE;
@@ -853,8 +852,8 @@ OGRErr OGROCITableLayer::DeleteFeature( GIntBig nFID )
 
     if( nFID == OGRNullFID )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "OGROCITableLayer::DeleteFeature(" CPL_FRMT_GIB ") failed for Null FID", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "OGROCITableLayer::DeleteFeature(" CPL_FRMT_GIB ") failed for Null FID",
                   nFID );
 
         return OGRERR_FAILURE;
@@ -868,10 +867,10 @@ OGRErr OGROCITableLayer::DeleteFeature( GIntBig nFID )
     OGROCIStringBuf     oCmdText;
     OGROCIStatement     oCmdStatement( poDS->GetSession() );
 
-    oCmdText.Appendf( strlen(poFeatureDefn->GetName())+strlen(pszFIDName)+100,
+    oCmdText.Appendf( static_cast<int>(strlen(poFeatureDefn->GetName())+strlen(pszFIDName)+100),
                       "DELETE FROM %s WHERE \"%s\" = " CPL_FRMT_GIB,
-                      poFeatureDefn->GetName(), 
-                      pszFIDName, 
+                      poFeatureDefn->GetName(),
+                      pszFIDName,
                       nFID );
 
     if( oCmdStatement.Execute( oCmdText.GetString() ) == CE_None )
@@ -893,7 +892,7 @@ OGRErr OGROCITableLayer::ICreateFeature( OGRFeature *poFeature )
     if( poFeature->GetGeometryRef() != NULL )
     {
         OGREnvelope  sThisExtent;
-        
+
         poFeature->GetGeometryRef()->getEnvelope( &sThisExtent );
 
         if( !sExtent.Contains( sThisExtent ) )
@@ -921,8 +920,8 @@ OGRErr OGROCITableLayer::UnboundCreateFeature( OGRFeature *poFeature )
 {
     OGROCISession      *poSession = poDS->GetSession();
     char                *pszCommand;
-    int                 i, bNeedComma = FALSE;
-    unsigned int        nCommandBufSize;;
+    int                 bNeedComma = FALSE;
+    size_t              nCommandBufSize;
 
 /* -------------------------------------------------------------------- */
 /*      Prepare SQL statement buffer.                                   */
@@ -933,25 +932,25 @@ OGRErr OGROCITableLayer::UnboundCreateFeature( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
 /*      Form the INSERT command.                                        */
 /* -------------------------------------------------------------------- */
-    sprintf( pszCommand, "INSERT INTO \"%s\"(\"", poFeatureDefn->GetName() );
+    snprintf( pszCommand, nCommandBufSize, "INSERT INTO \"%s\"(\"", poFeatureDefn->GetName() );
 
     if( poFeature->GetGeometryRef() != NULL )
     {
         bNeedComma = TRUE;
         strcat( pszCommand, pszGeomName );
     }
-    
+
     if( pszFIDName != NULL )
     {
         if( bNeedComma )
             strcat( pszCommand, "\",\"" );
-        
+
         strcat( pszCommand, pszFIDName );
         bNeedComma = TRUE;
     }
-    
 
-    for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
+
+    for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
     {
         if( !poFeature->IsFieldSet( i ) )
             continue;
@@ -961,7 +960,8 @@ OGRErr OGROCITableLayer::UnboundCreateFeature( OGRFeature *poFeature )
         else
             strcat( pszCommand, "\",\"" );
 
-        sprintf( pszCommand + strlen(pszCommand), "%s",
+        snprintf( pszCommand + strlen(pszCommand),
+                  nCommandBufSize - strlen(pszCommand), "%s",
                  poFeatureDefn->GetFieldDefn(i)->GetNameRef() );
     }
 
@@ -982,21 +982,21 @@ OGRErr OGROCITableLayer::UnboundCreateFeature( OGRFeature *poFeature )
         if( nSRID == -1 )
             strcpy( szSRID, "NULL" );
         else
-            sprintf( szSRID, "%d", nSRID );
+            snprintf( szSRID, sizeof(szSRID), "%d", nSRID );
 
         if( wkbFlatten(poGeometry->getGeometryType()) == wkbPoint )
         {
             OGRPoint *poPoint = (OGRPoint *) poGeometry;
 
             if( nDimension == 2 )
-                CPLsprintf( szSDO_GEOMETRY,
+                CPLsnprintf( szSDO_GEOMETRY, sizeof(szSDO_GEOMETRY),
                          "%s(%d,%s,MDSYS.SDO_POINT_TYPE(%.16g,%.16g,0),NULL,NULL)",
-                         SDO_GEOMETRY, 2001, szSRID, 
+                         SDO_GEOMETRY, 2001, szSRID,
                          poPoint->getX(), poPoint->getY() );
             else
-                CPLsprintf( szSDO_GEOMETRY, 
+                CPLsnprintf( szSDO_GEOMETRY, sizeof(szSDO_GEOMETRY),
                          "%s(%d,%s,MDSYS.SDO_POINT_TYPE(%.16g,%.16g,%.16g),NULL,NULL)",
-                         SDO_GEOMETRY, 3001, szSRID, 
+                         SDO_GEOMETRY, 3001, szSRID,
                          poPoint->getX(), poPoint->getY(), poPoint->getZ() );
         }
         else
@@ -1005,18 +1005,18 @@ OGRErr OGROCITableLayer::UnboundCreateFeature( OGRFeature *poFeature )
 
             if( TranslateToSDOGeometry( poFeature->GetGeometryRef(), &nGType )
                 == OGRERR_NONE )
-                sprintf( szSDO_GEOMETRY, 
-                         "%s(%d,%s,NULL,:elem_info,:ordinates)", 
+                CPLsnprintf( szSDO_GEOMETRY, sizeof(szSDO_GEOMETRY),
+                         "%s(%d,%s,NULL,:elem_info,:ordinates)",
                          SDO_GEOMETRY, nGType, szSRID );
             else
-                sprintf( szSDO_GEOMETRY, "NULL" );
+                CPLsnprintf( szSDO_GEOMETRY, sizeof(szSDO_GEOMETRY),"NULL" );
         }
 
-        if( strlen(pszCommand) + strlen(szSDO_GEOMETRY) 
+        if( strlen(pszCommand) + strlen(szSDO_GEOMETRY)
             > nCommandBufSize - 50 )
         {
-            nCommandBufSize = 
-                strlen(pszCommand) + strlen(szSDO_GEOMETRY) + 10000;
+            nCommandBufSize =
+               strlen(pszCommand) + strlen(szSDO_GEOMETRY) + 10000;
             pszCommand = (char *) CPLRealloc(pszCommand, nCommandBufSize );
         }
 
@@ -1026,7 +1026,7 @@ OGRErr OGROCITableLayer::UnboundCreateFeature( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
 /*      Set the FID.                                                    */
 /* -------------------------------------------------------------------- */
-    int nOffset = strlen(pszCommand);
+    size_t nOffset = strlen(pszCommand);
 
     if( pszFIDName != NULL )
     {
@@ -1048,13 +1048,13 @@ OGRErr OGROCITableLayer::UnboundCreateFeature( OGRFeature *poFeature )
             nFID = iNextFIDToWrite++;
             poFeature->SetFID( nFID );
         }
-        sprintf( pszCommand+nOffset, CPL_FRMT_GIB, nFID );
+        snprintf( pszCommand+nOffset, nCommandBufSize - nOffset, CPL_FRMT_GIB, nFID );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Set the other fields.                                           */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
+    for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
     {
         if( !poFeature->IsFieldSet( i ) )
             continue;
@@ -1067,14 +1067,14 @@ OGRErr OGROCITableLayer::UnboundCreateFeature( OGRFeature *poFeature )
         else
             bNeedComma = TRUE;
 
-        if( strlen(pszStrValue) + strlen(pszCommand+nOffset) + nOffset 
+        if( strlen(pszStrValue) + strlen(pszCommand+nOffset) + nOffset
             > nCommandBufSize-50 )
         {
             nCommandBufSize = strlen(pszCommand) + strlen(pszStrValue) + 10000;
             pszCommand = (char *) CPLRealloc(pszCommand, nCommandBufSize );
         }
-        
-        if( poFldDefn->GetType() == OFTInteger 
+
+        if( poFldDefn->GetType() == OFTInteger
             || poFldDefn->GetType() == OFTInteger64
             || poFldDefn->GetType() == OFTReal )
         {
@@ -1087,7 +1087,7 @@ OGRErr OGROCITableLayer::UnboundCreateFeature( OGRFeature *poFeature )
             else
                 strcat( pszCommand+nOffset, pszStrValue );
         }
-        else 
+        else
         {
             int         iChar;
 
@@ -1095,7 +1095,7 @@ OGRErr OGROCITableLayer::UnboundCreateFeature( OGRFeature *poFeature )
             strcat( pszCommand+nOffset, "'" );
 
             nOffset += strlen(pszCommand+nOffset);
-            
+
             for( iChar = 0; pszStrValue[iChar] != '\0'; iChar++ )
             {
                 if( poFldDefn->GetWidth() != 0 && bPreservePrecision
@@ -1114,7 +1114,7 @@ OGRErr OGROCITableLayer::UnboundCreateFeature( OGRFeature *poFeature )
                     pszCommand[nOffset++] = pszStrValue[iChar];
             }
             pszCommand[nOffset] = '\0';
-            
+
             strcat( pszCommand+nOffset, "'" );
         }
         nOffset += strlen(pszCommand+nOffset);
@@ -1144,15 +1144,15 @@ OGRErr OGROCITableLayer::UnboundCreateFeature( OGRFeature *poFeature )
     {
         OCIBind *hBindOrd = NULL;
         int i;
-        OCINumber oci_number; 
+        OCINumber oci_number;
 
-        // Create or clear VARRAY 
+        // Create or clear VARRAY
         if( hElemInfoVARRAY == NULL )
         {
             if( poSession->Failed(
-                OCIObjectNew( poSession->hEnv, poSession->hError, 
+                OCIObjectNew( poSession->hEnv, poSession->hError,
                               poSession->hSvcCtx, OCI_TYPECODE_VARRAY,
-                              poSession->hElemInfoTDO, (dvoid *)NULL, 
+                              poSession->hElemInfoTDO, (dvoid *)NULL,
                               OCI_DURATION_SESSION,
                               FALSE, (dvoid **)&hElemInfoVARRAY),
                 "OCIObjectNew(hElemInfoVARRAY)") )
@@ -1162,17 +1162,17 @@ OGRErr OGROCITableLayer::UnboundCreateFeature( OGRFeature *poFeature )
         {
             sb4  nOldCount;
 
-            OCICollSize( poSession->hEnv, poSession->hError, 
+            OCICollSize( poSession->hEnv, poSession->hError,
                          hElemInfoVARRAY, &nOldCount );
-            OCICollTrim( poSession->hEnv, poSession->hError, 
+            OCICollTrim( poSession->hEnv, poSession->hError,
                          nOldCount, hElemInfoVARRAY );
         }
 
-        // Prepare the VARRAY of ordinate values. 
+        // Prepare the VARRAY of ordinate values.
         for (i = 0; i < nElemInfoCount; i++)
         {
-            if( poSession->Failed( 
-                OCINumberFromInt( poSession->hError, 
+            if( poSession->Failed(
+                OCINumberFromInt( poSession->hError,
                                   (dvoid *) (panElemInfo + i),
                                   (uword)sizeof(int),
                                   OCI_NUMBER_SIGNED,
@@ -1180,7 +1180,7 @@ OGRErr OGROCITableLayer::UnboundCreateFeature( OGRFeature *poFeature )
                 "OCINumberFromInt") )
                 return OGRERR_FAILURE;
 
-            if( poSession->Failed( 
+            if( poSession->Failed(
                 OCICollAppend( poSession->hEnv, poSession->hError,
                                (dvoid *) &oci_number,
                                (dvoid *)0, hElemInfoVARRAY),
@@ -1189,20 +1189,20 @@ OGRErr OGROCITableLayer::UnboundCreateFeature( OGRFeature *poFeature )
         }
 
         // Do the binding.
-        if( poSession->Failed( 
-            OCIBindByName( oInsert.GetStatement(), &hBindOrd, 
+        if( poSession->Failed(
+            OCIBindByName( oInsert.GetStatement(), &hBindOrd,
                            poSession->hError,
-                           (text *) ":elem_info", (sb4) -1, (dvoid *) 0, 
-                           (sb4) 0, SQLT_NTY, (dvoid *)0, (ub2 *)0, 
-                           (ub2 *)0, (ub4)0, (ub4 *)0, 
+                           (text *) ":elem_info", (sb4) -1, (dvoid *) 0,
+                           (sb4) 0, SQLT_NTY, (dvoid *)0, (ub2 *)0,
+                           (ub2 *)0, (ub4)0, (ub4 *)0,
                            (ub4)OCI_DEFAULT),
             "OCIBindByName(:elem_info)") )
             return OGRERR_FAILURE;
 
         if( poSession->Failed(
-            OCIBindObject( hBindOrd, poSession->hError, 
+            OCIBindObject( hBindOrd, poSession->hError,
                            poSession->hElemInfoTDO,
-                           (dvoid **)&hElemInfoVARRAY, (ub4 *)0, 
+                           (dvoid **)&hElemInfoVARRAY, (ub4 *)0,
                            (dvoid **)0, (ub4 *)0),
             "OCIBindObject(:elem_info)" ) )
             return OGRERR_FAILURE;
@@ -1215,15 +1215,15 @@ OGRErr OGROCITableLayer::UnboundCreateFeature( OGRFeature *poFeature )
     {
         OCIBind *hBindOrd = NULL;
         int i;
-        OCINumber oci_number; 
+        OCINumber oci_number;
 
-        // Create or clear VARRAY 
+        // Create or clear VARRAY
         if( hOrdVARRAY == NULL )
         {
             if( poSession->Failed(
-                OCIObjectNew( poSession->hEnv, poSession->hError, 
+                OCIObjectNew( poSession->hEnv, poSession->hError,
                               poSession->hSvcCtx, OCI_TYPECODE_VARRAY,
-                              poSession->hOrdinatesTDO, (dvoid *)NULL, 
+                              poSession->hOrdinatesTDO, (dvoid *)NULL,
                               OCI_DURATION_SESSION,
                               FALSE, (dvoid **)&hOrdVARRAY),
                 "OCIObjectNew(hOrdVARRAY)") )
@@ -1233,24 +1233,24 @@ OGRErr OGROCITableLayer::UnboundCreateFeature( OGRFeature *poFeature )
         {
             sb4  nOldCount;
 
-            OCICollSize( poSession->hEnv, poSession->hError, 
+            OCICollSize( poSession->hEnv, poSession->hError,
                          hOrdVARRAY, &nOldCount );
-            OCICollTrim( poSession->hEnv, poSession->hError, 
+            OCICollTrim( poSession->hEnv, poSession->hError,
                          nOldCount, hOrdVARRAY );
         }
 
-        // Prepare the VARRAY of ordinate values. 
+        // Prepare the VARRAY of ordinate values.
         for (i = 0; i < nOrdinalCount; i++)
         {
-            if( poSession->Failed( 
-                OCINumberFromReal( poSession->hError, 
+            if( poSession->Failed(
+                OCINumberFromReal( poSession->hError,
                                    (dvoid *) (padfOrdinals + i),
                                    (uword)sizeof(double),
                                    &oci_number),
                 "OCINumberFromReal") )
                 return OGRERR_FAILURE;
 
-            if( poSession->Failed( 
+            if( poSession->Failed(
                 OCICollAppend( poSession->hEnv, poSession->hError,
                                (dvoid *) &oci_number,
                                (dvoid *)0, hOrdVARRAY),
@@ -1259,20 +1259,20 @@ OGRErr OGROCITableLayer::UnboundCreateFeature( OGRFeature *poFeature )
         }
 
         // Do the binding.
-        if( poSession->Failed( 
-            OCIBindByName( oInsert.GetStatement(), &hBindOrd, 
+        if( poSession->Failed(
+            OCIBindByName( oInsert.GetStatement(), &hBindOrd,
                            poSession->hError,
-                           (text *) ":ordinates", (sb4) -1, (dvoid *) 0, 
-                           (sb4) 0, SQLT_NTY, (dvoid *)0, (ub2 *)0, 
-                           (ub2 *)0, (ub4)0, (ub4 *)0, 
+                           (text *) ":ordinates", (sb4) -1, (dvoid *) 0,
+                           (sb4) 0, SQLT_NTY, (dvoid *)0, (ub2 *)0,
+                           (ub2 *)0, (ub4)0, (ub4 *)0,
                            (ub4)OCI_DEFAULT),
             "OCIBindByName(:ordinates)") )
             return OGRERR_FAILURE;
 
         if( poSession->Failed(
-            OCIBindObject( hBindOrd, poSession->hError, 
+            OCIBindObject( hBindOrd, poSession->hError,
                            poSession->hOrdinatesTDO,
-                           (dvoid **)&hOrdVARRAY, (ub4 *)0, 
+                           (dvoid **)&hOrdVARRAY, (ub4 *)0,
                            (dvoid **)0, (ub4 *)0),
             "OCIBindObject(:ordinates)" ) )
             return OGRERR_FAILURE;
@@ -1344,7 +1344,7 @@ OGRErr OGROCITableLayer::GetExtent(OGREnvelope *psExtent, int bForce)
     CPLAssert( NULL != poSession );
 
     OGROCIStatement oGetExtent( poSession );
-    
+
     if( oGetExtent.Execute( oCommand.GetString() ) == CE_None )
     {
         char **papszRow = oGetExtent.SimpleFetchRow();
@@ -1369,7 +1369,7 @@ OGRErr OGROCITableLayer::GetExtent(OGREnvelope *psExtent, int bForce)
     if( err != OGRERR_NONE )
     {
         err = OGRLayer::GetExtent( psExtent, bForce );
-        CPLDebug( "OCI", 
+        CPLDebug( "OCI",
                   "Failing to query extent of %s using default GetExtent",
                   osTableName.c_str() );
     }
@@ -1384,14 +1384,14 @@ OGRErr OGROCITableLayer::GetExtent(OGREnvelope *psExtent, int bForce)
 int OGROCITableLayer::TestCapability( const char * pszCap )
 
 {
-    if( EQUAL(pszCap,OLCSequentialWrite) 
+    if( EQUAL(pszCap,OLCSequentialWrite)
              || EQUAL(pszCap,OLCRandomWrite) )
         return bUpdateAccess;
 
     else if( EQUAL(pszCap,OLCCreateField) )
         return bUpdateAccess;
 
-    else 
+    else
         return OGROCILayer::TestCapability( pszCap );
 }
 
@@ -1425,7 +1425,7 @@ GIntBig OGROCITableLayer::GetFeatureCount( int bForce )
     char               szCommand[1024];
     char               **papszResult;
 
-    sprintf( szCommand, "SELECT COUNT(*) FROM %s %s", 
+    snprintf( szCommand, sizeof(szCommand), "SELECT COUNT(*) FROM %s %s",
              poFeatureDefn->GetName(), pszWHERE );
 
     oGetCount.Execute( szCommand );
@@ -1437,7 +1437,7 @@ GIntBig OGROCITableLayer::GetFeatureCount( int bForce )
         CPLDebug( "OCI", "Fast get count failed, doing hard way." );
         return OGROCILayer::GetFeatureCount( bForce );
     }
-    
+
     return CPLAtoGIntBig(papszResult[0]);
 }
 
@@ -1463,30 +1463,30 @@ void OGROCITableLayer::UpdateLayerExtents()
     {
         OGROCIStringBuf oCommand;
 
-        oCommand.Appendf(1000, 
-                          "select min(case when r=1 then sdo_lb else null end) minx, min(case when r=2 then sdo_lb else null end) miny, " 
-                          "min(case when r=1 then sdo_ub else null end) maxx, min(case when r=2 then sdo_ub else null end) maxy" 
-                          " from (SELECT d.sdo_dimname, d.sdo_lb, sdo_ub, sdo_tolerance, rownum r" 
-                          " FROM ALL_SDO_GEOM_METADATA m, table(m.diminfo) d"  
-                          " where m.table_name = UPPER('%s') and m.COLUMN_NAME = UPPER('%s')", 
-                          osTableName.c_str(), pszGeomName ); 
+        oCommand.Appendf(1000,
+                          "select min(case when r=1 then sdo_lb else null end) minx, min(case when r=2 then sdo_lb else null end) miny, "
+                          "min(case when r=1 then sdo_ub else null end) maxx, min(case when r=2 then sdo_ub else null end) maxy"
+                          " from (SELECT d.sdo_dimname, d.sdo_lb, sdo_ub, sdo_tolerance, rownum r"
+                          " FROM ALL_SDO_GEOM_METADATA m, table(m.diminfo) d"
+                          " where m.table_name = UPPER('%s') and m.COLUMN_NAME = UPPER('%s')",
+                          osTableName.c_str(), pszGeomName );
 
-        if( osOwner != "" ) 
-        { 
-            oCommand.Appendf(500, " AND OWNER = UPPER('%s')", osOwner.c_str() ); 
-        } 
+        if( osOwner != "" )
+        {
+            oCommand.Appendf(500, " AND OWNER = UPPER('%s')", osOwner.c_str() );
+        }
 
         oCommand.Append(" ) ");
 
         OGROCISession *poSession = poDS->GetSession();
         CPLAssert( NULL != poSession );
-        
+
         OGROCIStatement oGetExtent( poSession );
-        
+
         if( oGetExtent.Execute( oCommand.GetString() ) == CE_None )
         {
             char **papszRow = oGetExtent.SimpleFetchRow();
-            
+
             if( papszRow != NULL
                 && papszRow[0] != NULL && papszRow[1] != NULL
                 && papszRow[2] != NULL && papszRow[3] != NULL )
@@ -1532,12 +1532,12 @@ void OGROCITableLayer::UpdateLayerExtents()
     dfXMax = sExtent.MaxX + dfResSize * 3;
     dfXRes = dfResSize;
     ParseDIMINFO( "DIMINFO_X", &dfXMin, &dfXMax, &dfXRes );
-    
+
     dfYMin = sExtent.MinY - dfResSize * 3;
     dfYMax = sExtent.MaxY + dfResSize * 3;
     dfYRes = dfResSize;
     ParseDIMINFO( "DIMINFO_Y", &dfYMin, &dfYMax, &dfYRes );
-    
+
     dfZMin = -100000.0;
     dfZMax = 100000.0;
     dfZRes = 0.002;
@@ -1566,18 +1566,19 @@ void OGROCITableLayer::UpdateLayerExtents()
             sDimUpdate.Appendf(200,
                                ",MDSYS.SDO_DIM_ELEMENT('Z',%.16g,%.16g,%.12g)",
                                dfZMin, dfZMax, dfZRes );
-        }      
-    
-        sDimUpdate.Appendf(strlen(poFeatureDefn->GetName()) + 100,") WHERE TABLE_NAME = '%s'", poFeatureDefn->GetName());    
-        
-    } 
+        }
+
+        sDimUpdate.Appendf(static_cast<int>(strlen(poFeatureDefn->GetName()) + 100),
+                           ") WHERE TABLE_NAME = '%s'", poFeatureDefn->GetName());
+
+    }
     else
     {
 /* -------------------------------------------------------------------- */
 /*      Prepare dimension update statement.                             */
 /* -------------------------------------------------------------------- */
         sDimUpdate.Append( "INSERT INTO USER_SDO_GEOM_METADATA VALUES " );
-        sDimUpdate.Appendf( strlen(poFeatureDefn->GetName()) + 100,
+        sDimUpdate.Appendf( static_cast<int>(strlen(poFeatureDefn->GetName()) + 100),
                             "('%s', '%s', ",
                             poFeatureDefn->GetName(),
                             pszGeomName );
@@ -1607,7 +1608,7 @@ void OGROCITableLayer::UpdateLayerExtents()
 /*      Run the update/insert command.                                  */
 /* -------------------------------------------------------------------- */
     OGROCIStatement oExecStatement( poDS->GetSession() );
-    
+
     oExecStatement.Execute( sDimUpdate.GetString() );
 }
 
@@ -1661,7 +1662,7 @@ int OGROCITableLayer::AllocAndBindForWrite()
         oCmdBuf.Append( ", " );
         oCmdBuf.Appendf( 20, " :field_%d", i );
     }
-    
+
     oCmdBuf.Append( ") " );
 
 /* -------------------------------------------------------------------- */
@@ -1677,7 +1678,7 @@ int OGROCITableLayer::AllocAndBindForWrite()
     {
         pasWriteGeomInd = (SDO_GEOMETRY_ind *)
             CPLCalloc(sizeof(SDO_GEOMETRY_ind),nWriteCacheMax);
-    
+
         papsWriteGeomIndMap = (SDO_GEOMETRY_ind **)
             CPLCalloc(sizeof(SDO_GEOMETRY_ind *),nWriteCacheMax);
 
@@ -1702,21 +1703,21 @@ int OGROCITableLayer::AllocAndBindForWrite()
         for( i = 0; i < nWriteCacheMax; i++ )
         {
             if( poSession->Failed(
-                OCIObjectNew( poSession->hEnv, poSession->hError, 
+                OCIObjectNew( poSession->hEnv, poSession->hError,
                               poSession->hSvcCtx, OCI_TYPECODE_VARRAY,
-                              poSession->hElemInfoTDO, (dvoid *)NULL, 
+                              poSession->hElemInfoTDO, (dvoid *)NULL,
                               OCI_DURATION_SESSION,
-                              FALSE, 
+                              FALSE,
                               (dvoid **) &(pasWriteGeoms[i].sdo_elem_info)),
                 "OCIObjectNew(elem_info)") )
                 return FALSE;
 
             if( poSession->Failed(
-                OCIObjectNew( poSession->hEnv, poSession->hError, 
+                OCIObjectNew( poSession->hEnv, poSession->hError,
                               poSession->hSvcCtx, OCI_TYPECODE_VARRAY,
-                              poSession->hOrdinatesTDO, (dvoid *)NULL, 
+                              poSession->hOrdinatesTDO, (dvoid *)NULL,
                               OCI_DURATION_SESSION,
-                              FALSE, 
+                              FALSE,
                               (dvoid **) &(pasWriteGeoms[i].sdo_ordinates)),
                 "OCIObjectNew(ordinates)") )
                 return FALSE;
@@ -1726,7 +1727,7 @@ int OGROCITableLayer::AllocAndBindForWrite()
 /*      Bind the geometry column.                                       */
 /* -------------------------------------------------------------------- */
         if( poBoundStatement->BindObject(
-            ":geometry", papsWriteGeomMap, poSession->hGeometryTDO, 
+            ":geometry", papsWriteGeomMap, poSession->hGeometryTDO,
             (void**) papsWriteGeomIndMap) != CE_None )
             return FALSE;
     }
@@ -1735,18 +1736,18 @@ int OGROCITableLayer::AllocAndBindForWrite()
 /*      Bind the FID column.                                            */
 /* -------------------------------------------------------------------- */
     panWriteFIDs = (int *) CPLMalloc(sizeof(int) * nWriteCacheMax );
-        
-    if( poBoundStatement->BindScalar( ":fid", panWriteFIDs, sizeof(int), 
+
+    if( poBoundStatement->BindScalar( ":fid", panWriteFIDs, sizeof(int),
                                       SQLT_INT ) != CE_None )
         return FALSE;
 
 /* -------------------------------------------------------------------- */
 /*      Allocate each of the column data bind arrays.                   */
 /* -------------------------------------------------------------------- */
-    
-    papWriteFields = (void **) 
+
+    papWriteFields = (void **)
         CPLMalloc(sizeof(void*) * poFeatureDefn->GetFieldCount() );
-    papaeWriteFieldInd = (OCIInd **) 
+    papaeWriteFieldInd = (OCIInd **)
         CPLCalloc(sizeof(OCIInd*),poFeatureDefn->GetFieldCount() );
 
     for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
@@ -1754,42 +1755,42 @@ int OGROCITableLayer::AllocAndBindForWrite()
         OGRFieldDefn *poFldDefn = poFeatureDefn->GetFieldDefn(i);
         char szFieldPlaceholderName[80];
 
-        sprintf( szFieldPlaceholderName, ":field_%d", i );
+        snprintf( szFieldPlaceholderName, sizeof(szFieldPlaceholderName), ":field_%d", i );
 
-        papaeWriteFieldInd[i] = (OCIInd *) 
+        papaeWriteFieldInd[i] = (OCIInd *)
             CPLCalloc(sizeof(OCIInd), nWriteCacheMax );
 
         if( poFldDefn->GetType() == OFTInteger )
         {
-            papWriteFields[i] = 
+            papWriteFields[i] =
                 (void *) CPLCalloc( sizeof(int), nWriteCacheMax );
 
-            if( poBoundStatement->BindScalar( 
+            if( poBoundStatement->BindScalar(
                     szFieldPlaceholderName, papWriteFields[i],
                     sizeof(int), SQLT_INT, papaeWriteFieldInd[i] ) != CE_None )
                 return FALSE;
         }
         else if( poFldDefn->GetType() == OFTInteger64 )
         {
-            papWriteFields[i] = 
+            papWriteFields[i] =
                 (void *) CPLCalloc( sizeof(GIntBig), nWriteCacheMax );
 
-            if( poBoundStatement->BindScalar( 
+            if( poBoundStatement->BindScalar(
                     szFieldPlaceholderName, papWriteFields[i],
                     sizeof(GIntBig), SQLT_INT, papaeWriteFieldInd[i] ) != CE_None )
                 return FALSE;
         }
         else if( poFldDefn->GetType() == OFTReal )
         {
-            papWriteFields[i] = (void *) CPLCalloc( sizeof(double), 
+            papWriteFields[i] = (void *) CPLCalloc( sizeof(double),
                                                     nWriteCacheMax );
 
-            if( poBoundStatement->BindScalar( 
+            if( poBoundStatement->BindScalar(
                     szFieldPlaceholderName, papWriteFields[i],
                     sizeof(double), SQLT_FLT, papaeWriteFieldInd[i] ) != CE_None )
                 return FALSE;
         }
-        else 
+        else
         {
             int nEachBufSize = 4001;
 
@@ -1797,10 +1798,10 @@ int OGROCITableLayer::AllocAndBindForWrite()
                 && poFldDefn->GetWidth() != 0 )
                 nEachBufSize = poFldDefn->GetWidth() + 1;
 
-            papWriteFields[i] = 
+            papWriteFields[i] =
                 (void *) CPLCalloc( nEachBufSize, nWriteCacheMax );
 
-            if( poBoundStatement->BindScalar( 
+            if( poBoundStatement->BindScalar(
                     szFieldPlaceholderName, papWriteFields[i],
                     nEachBufSize, SQLT_STR, papaeWriteFieldInd[i]) != CE_None )
                 return FALSE;
@@ -1820,12 +1821,12 @@ OGRErr OGROCITableLayer::BoundCreateFeature( OGRFeature *poFeature )
     OGROCISession      *poSession = poDS->GetSession();
     int                iCache, i;
     OGRErr             eErr;
-    OCINumber          oci_number; 
+    OCINumber          oci_number;
 
     /* If an unset field has a default value, the current implementation */
     /* of BoundCreateFeature() doesn't work. */
     for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
-    { 
+    {
         if( !poFeature->IsFieldSet( i ) &&
             poFeature->GetFieldDefnRef(i)->GetDefault() != NULL )
         {
@@ -1865,7 +1866,7 @@ OGRErr OGROCITableLayer::BoundCreateFeature( OGRFeature *poFeature )
         else
         {
             psInd->sdo_srid = OCI_IND_NOTNULL;
-            OCINumberFromInt( poSession->hError, &nSRID, 
+            OCINumberFromInt( poSession->hError, &nSRID,
                               (uword)sizeof(int), OCI_NUMBER_SIGNED,
                               &(psGeom->sdo_srid) );
         }
@@ -1879,14 +1880,14 @@ OGRErr OGROCITableLayer::BoundCreateFeature( OGRFeature *poFeature )
             psInd->sdo_point._atomic = OCI_IND_NOTNULL;
             psInd->sdo_elem_info = OCI_IND_NULL;
             psInd->sdo_ordinates = OCI_IND_NULL;
-            
+
             dfValue = poPoint->getX();
-            OCINumberFromReal( poSession->hError, &dfValue, 
+            OCINumberFromReal( poSession->hError, &dfValue,
                                (uword)sizeof(double),
                                &(psGeom->sdo_point.x) );
 
             dfValue = poPoint->getY();
-            OCINumberFromReal( poSession->hError, &dfValue, 
+            OCINumberFromReal( poSession->hError, &dfValue,
                                (uword)sizeof(double),
                                &(psGeom->sdo_point.y) );
 
@@ -1901,7 +1902,7 @@ OGRErr OGROCITableLayer::BoundCreateFeature( OGRFeature *poFeature )
                 psInd->sdo_point.z = OCI_IND_NOTNULL;
 
                 dfValue = poPoint->getZ();
-                OCINumberFromReal( poSession->hError, &dfValue, 
+                OCINumberFromReal( poSession->hError, &dfValue,
                                    (uword)sizeof(double),
                                    &(psGeom->sdo_point.z) );
             }
@@ -1912,29 +1913,29 @@ OGRErr OGROCITableLayer::BoundCreateFeature( OGRFeature *poFeature )
             psInd->sdo_elem_info = OCI_IND_NOTNULL;
             psInd->sdo_ordinates = OCI_IND_NOTNULL;
 
-            eErr = TranslateToSDOGeometry( poFeature->GetGeometryRef(), 
+            eErr = TranslateToSDOGeometry( poFeature->GetGeometryRef(),
                                            &nGType );
-            
+
             if( eErr != OGRERR_NONE )
                 return eErr;
 
             /* Clear the existing eleminfo and ordinates arrays */
             sb4  nOldCount;
 
-            OCICollSize( poSession->hEnv, poSession->hError, 
+            OCICollSize( poSession->hEnv, poSession->hError,
                          psGeom->sdo_elem_info, &nOldCount );
-            OCICollTrim( poSession->hEnv, poSession->hError, 
+            OCICollTrim( poSession->hEnv, poSession->hError,
                          nOldCount, psGeom->sdo_elem_info );
 
-            OCICollSize( poSession->hEnv, poSession->hError, 
+            OCICollSize( poSession->hEnv, poSession->hError,
                          psGeom->sdo_ordinates, &nOldCount );
-            OCICollTrim( poSession->hEnv, poSession->hError, 
+            OCICollTrim( poSession->hEnv, poSession->hError,
                          nOldCount, psGeom->sdo_ordinates );
 
-            // Prepare the VARRAY of element values. 
+            // Prepare the VARRAY of element values.
             for (i = 0; i < nElemInfoCount; i++)
             {
-                OCINumberFromInt( poSession->hError, 
+                OCINumberFromInt( poSession->hError,
                                   (dvoid *) (panElemInfo + i),
                                   (uword)sizeof(int), OCI_NUMBER_SIGNED,
                                   &oci_number );
@@ -1944,10 +1945,10 @@ OGRErr OGROCITableLayer::BoundCreateFeature( OGRFeature *poFeature )
                                (dvoid *)0, psGeom->sdo_elem_info );
             }
 
-            // Prepare the VARRAY of ordinate values. 
+            // Prepare the VARRAY of ordinate values.
             for (i = 0; i < nOrdinalCount; i++)
             {
-                OCINumberFromReal( poSession->hError, 
+                OCINumberFromReal( poSession->hError,
                                    (dvoid *) (padfOrdinals + i),
                                    (uword)sizeof(double), &oci_number );
                 OCICollAppend( poSession->hEnv, poSession->hError,
@@ -1985,13 +1986,13 @@ OGRErr OGROCITableLayer::BoundCreateFeature( OGRFeature *poFeature )
         poFeature->SetFID( iNextFIDToWrite++ );
     }
 
-    panWriteFIDs[iCache] = poFeature->GetFID();
+    panWriteFIDs[iCache] = static_cast<int>(poFeature->GetFID());
 
 /* -------------------------------------------------------------------- */
 /*      Set the other fields.                                           */
 /* -------------------------------------------------------------------- */
     for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
-    { 
+    {
         if( !poFeature->IsFieldSet( i ) )
         {
             papaeWriteFieldInd[i][iCache] = OCI_IND_NULL;
@@ -2003,15 +2004,15 @@ OGRErr OGROCITableLayer::BoundCreateFeature( OGRFeature *poFeature )
         OGRFieldDefn *poFldDefn = poFeatureDefn->GetFieldDefn(i);
 
         if( poFldDefn->GetType() == OFTInteger )
-            ((int *) (papWriteFields[i]))[iCache] = 
+            ((int *) (papWriteFields[i]))[iCache] =
                 poFeature->GetFieldAsInteger( i );
 
         else if( poFldDefn->GetType() == OFTInteger64 )
-            ((GIntBig *) (papWriteFields[i]))[iCache] = 
+            ((GIntBig *) (papWriteFields[i]))[iCache] =
                 poFeature->GetFieldAsInteger64( i );
 
         else if( poFldDefn->GetType() == OFTReal )
-            ((double *) (papWriteFields[i]))[iCache] = 
+            ((double *) (papWriteFields[i]))[iCache] =
                 poFeature->GetFieldAsDouble( i );
 
         else
@@ -2023,7 +2024,7 @@ OGRErr OGROCITableLayer::BoundCreateFeature( OGRFeature *poFeature )
                 && poFldDefn->GetWidth() != 0 )
                 nEachBufSize = poFldDefn->GetWidth() + 1;
 
-            nLen = strlen(pszStrValue);
+            nLen = static_cast<int>(strlen(pszStrValue));
             if( nLen > nEachBufSize-1 )
                 nLen = nEachBufSize-1;
 
@@ -2055,15 +2056,15 @@ OGRErr OGROCITableLayer::FlushPendingFeatures()
 
     if( nWriteCacheUsed > 0 )
     {
-        CPLDebug( "OCI", "Flushing %d features on layer %s", 
+        CPLDebug( "OCI", "Flushing %d features on layer %s",
                   nWriteCacheUsed, poFeatureDefn->GetName() );
 
-        if( poSession->Failed( 
-                OCIStmtExecute( poSession->hSvcCtx, 
-                                poBoundStatement->GetStatement(), 
-                                poSession->hError, (ub4) nWriteCacheUsed, 
-                                (ub4) 0, 
-                                (OCISnapshot *)NULL, (OCISnapshot *)NULL, 
+        if( poSession->Failed(
+                OCIStmtExecute( poSession->hSvcCtx,
+                                poBoundStatement->GetStatement(),
+                                poSession->hError, (ub4) nWriteCacheUsed,
+                                (ub4) 0,
+                                (OCISnapshot *)NULL, (OCISnapshot *)NULL,
                                 (ub4) OCI_COMMIT_ON_SUCCESS ),
                 "OCIStmtExecute" ) )
         {
@@ -2084,7 +2085,7 @@ OGRErr OGROCITableLayer::FlushPendingFeatures()
 /*                             SyncToDisk()                             */
 /*                                                                      */
 /*      Perhaps we should also be putting the metadata into a           */
-/*      useable state?                                                  */
+/*      usable state?                                                   */
 /************************************************************************/
 
 OGRErr OGROCITableLayer::SyncToDisk()
@@ -2129,9 +2130,9 @@ void OGROCITableLayer::CreateSpatialIndex()
         char  szIndexName[20];
 
         if( strlen(poFeatureDefn->GetName()) < 15 )
-            sprintf( szIndexName, "%s_idx", poFeatureDefn->GetName() );
+            snprintf( szIndexName, sizeof(szIndexName), "%s_idx", poFeatureDefn->GetName() );
         else if( strlen(poFeatureDefn->GetName()) < 17 )
-            sprintf( szIndexName, "%si", poFeatureDefn->GetName() );
+            snprintf( szIndexName, sizeof(szIndexName), "%si", poFeatureDefn->GetName() );
         else
         {
             int i, nHash = 0;
@@ -2140,7 +2141,7 @@ void OGROCITableLayer::CreateSpatialIndex()
             for( i = 0; pszSrcName[i] != '\0'; i++ )
                 nHash = (nHash + i * pszSrcName[i]) % 987651;
 
-            sprintf( szIndexName, "OSI_%d", nHash );
+            snprintf( szIndexName, sizeof(szIndexName), "OSI_%d", nHash );
         }
 
         poDS->GetSession()->CleanName( szIndexName );
@@ -2159,10 +2160,10 @@ void OGROCITableLayer::CreateSpatialIndex()
                            poFeatureDefn->GetName(),
                            pszGeomName );
 
-        int bAddLayerGType = CSLTestBoolean(
+        int bAddLayerGType = CPLTestBool(
             CSLFetchNameValueDef( papszOptions, "ADD_LAYER_GTYPE", "YES") ) &&
             GetGeomType() != wkbUnknown;
-      
+
         CPLString osParams(CSLFetchNameValueDef(papszOptions,"INDEX_PARAMETERS", ""));
         if( bAddLayerGType || osParams.size() != 0 )
         {
diff --git a/ogr/ogrsf_frmts/oci/ogrociwritablelayer.cpp b/ogr/ogrsf_frmts/oci/ogrociwritablelayer.cpp
index 02c2e89..219cf54 100644
--- a/ogr/ogrsf_frmts/oci/ogrociwritablelayer.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrociwritablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrociwritablelayer.cpp 28481 2015-02-13 17:11:15Z rouault $
+ * $Id: ogrociwritablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Implementation of the OGROCIWritableLayer class.  This provides
@@ -33,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrociwritablelayer.cpp 28481 2015-02-13 17:11:15Z rouault $");
+CPL_CVSID("$Id: ogrociwritablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                        OGROCIWritableLayer()                         */
@@ -55,7 +55,6 @@ OGROCIWritableLayer::OGROCIWritableLayer()
 
     bLaunderColumnNames = TRUE;
     bTruncationReported = FALSE;
-    nSRID = -1;
     poSRS = NULL;
 
     papszOptions = NULL;
@@ -84,10 +83,10 @@ void OGROCIWritableLayer::PushOrdinal( double dfOrd )
     if( nOrdinalCount == nOrdinalMax )
     {
         nOrdinalMax = nOrdinalMax * 2 + 100;
-        padfOrdinals = (double *) CPLRealloc(padfOrdinals, 
+        padfOrdinals = (double *) CPLRealloc(padfOrdinals,
                                              sizeof(double) * nOrdinalMax);
     }
-    
+
     padfOrdinals[nOrdinalCount++] = dfOrd;
 }
 
@@ -103,7 +102,7 @@ void OGROCIWritableLayer::PushElemInfo( int nOffset, int nEType, int nInterp )
         nElemInfoMax = nElemInfoMax * 2 + 100;
         panElemInfo = (int *) CPLRealloc(panElemInfo,sizeof(int)*nElemInfoMax);
     }
-    
+
     panElemInfo[nElemInfoCount++] = nOffset;
     panElemInfo[nElemInfoCount++] = nEType;
     panElemInfo[nElemInfoCount++] = nInterp;
@@ -116,7 +115,7 @@ void OGROCIWritableLayer::PushElemInfo( int nOffset, int nEType, int nInterp )
 /*      info and ordinates lists for the passed geometry.               */
 /************************************************************************/
 
-OGRErr 
+OGRErr
 OGROCIWritableLayer::TranslateElementGroup( OGRGeometry *poGeometry )
 
 {
@@ -140,7 +139,7 @@ OGROCIWritableLayer::TranslateElementGroup( OGRGeometry *poGeometry )
       {
           OGRLineString *poLine = (OGRLineString *) poGeometry;
           int  iVert;
-          
+
           PushElemInfo( nOrdinalCount+1, 2, 1 );
 
           for( iVert = 0; iVert < poLine->getNumPoints(); iVert++ )
@@ -219,7 +218,7 @@ void OGROCIWritableLayer::ReportTruncation( OGRFieldDefn * psFldDefn )
     CPLError( CE_Warning, CPLE_AppDefined,
               "The value for the field %s is being truncated to fit the\n"
               "declared width/precision of the field.  No more truncations\n"
-              "for table %s will be reported.", 
+              "for table %s will be reported.",
               psFldDefn->GetNameRef(), poFeatureDefn->GetName() );
 
     bTruncationReported = TRUE;
@@ -262,28 +261,28 @@ OGRErr OGROCIWritableLayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK
         oField.SetName( pszSafeName );
         CPLFree( pszSafeName );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Work out the Oracle type.                                       */
 /* -------------------------------------------------------------------- */
     if( oField.GetType() == OFTInteger )
     {
         if( bPreservePrecision && oField.GetWidth() != 0 )
-            sprintf( szFieldType, "NUMBER(%d)", oField.GetWidth() );
+            snprintf( szFieldType, sizeof(szFieldType), "NUMBER(%d)", oField.GetWidth() );
         else
             strcpy( szFieldType, "INTEGER" );
     }
     else if( oField.GetType() == OFTInteger64 )
     {
         if( bPreservePrecision && oField.GetWidth() != 0 )
-            sprintf( szFieldType, "NUMBER(%d)", oField.GetWidth() );
+            snprintf( szFieldType, sizeof(szFieldType), "NUMBER(%d)", oField.GetWidth() );
         else
             strcpy( szFieldType, "NUMBER(20)" );
     }
     else if( oField.GetType() == OFTReal )
     {
         if( bPreservePrecision && oField.GetWidth() != 0 )
-            sprintf( szFieldType, "NUMBER(%d,%d)", 
+            snprintf( szFieldType, sizeof(szFieldType), "NUMBER(%d,%d)",
                      oField.GetWidth(), oField.GetPrecision() );
         else
             strcpy( szFieldType, "FLOAT(126)" );
@@ -293,15 +292,15 @@ OGRErr OGROCIWritableLayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK
         if( oField.GetWidth() == 0 || !bPreservePrecision )
             strcpy( szFieldType, "VARCHAR2(2047)" );
         else
-            sprintf( szFieldType, "VARCHAR2(%d)", oField.GetWidth() );
+            snprintf( szFieldType, sizeof(szFieldType), "VARCHAR2(%d)", oField.GetWidth() );
     }
     else if ( oField.GetType() == OFTDate )
     {
-        sprintf( szFieldType, "DATE" );
+        snprintf( szFieldType, sizeof(szFieldType), "DATE" );
     }
     else if ( oField.GetType() == OFTDateTime )
     {
-        sprintf( szFieldType, "TIMESTAMP" );
+        snprintf( szFieldType, sizeof(szFieldType), "TIMESTAMP" );
     }
     else if( bApproxOK )
     {
@@ -328,31 +327,33 @@ OGRErr OGROCIWritableLayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK
     OGROCIStringBuf     oCommand;
     OGROCIStatement     oAddField( poSession );
 
-    oCommand.MakeRoomFor( 70 + strlen(poFeatureDefn->GetName())
+    const int nCommandSize = static_cast<int>(70 + strlen(poFeatureDefn->GetName())
                           + strlen(oField.GetNameRef())
                           + strlen(szFieldType)
-                          + (oField.GetDefault() ? strlen(oField.GetDefault()) : 0) );
+                          + (oField.GetDefault() ? strlen(oField.GetDefault()) : 0));
+    oCommand.MakeRoomFor( nCommandSize );
 
     snprintf( szFieldName, sizeof( szFieldName ), "%s", oField.GetNameRef());
     szFieldName[sizeof( szFieldName )-1] = '\0';
     if ( strlen(oField.GetNameRef()) > sizeof ( szFieldName ) )
     {
         szFieldName[sizeof( szFieldName ) - 1] = '_';
-        CPLError( CE_Warning, CPLE_AppDefined, 
-                  "Column %s is too long (at most 30 characters). Using %s.", 
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Column %s is too long (at most 30 characters). Using %s.",
                   oField.GetNameRef(), szFieldName );
         oField.SetName(szFieldName);
     }
-    sprintf( oCommand.GetString(), "ALTER TABLE %s ADD \"%s\" %s", 
+    snprintf( oCommand.GetString(), nCommandSize, "ALTER TABLE %s ADD \"%s\" %s",
              poFeatureDefn->GetName(), szFieldName, szFieldType);
     if( oField.GetDefault() != NULL && !oField.IsDefaultDriverSpecific() )
     {
-        sprintf( oCommand.GetString() + strlen(oCommand.GetString()),
+        snprintf( oCommand.GetString() + strlen(oCommand.GetString()),
+                  nCommandSize - strlen(oCommand.GetString()),
                  " DEFAULT %s", oField.GetDefault() );
     }
     if( !oField.IsNullable() )
         strcat( oCommand.GetString(), " NOT NULL");
-    
+
     if( oAddField.Execute( oCommand.GetString() ) != CE_None )
         return OGRERR_FAILURE;
 
@@ -375,8 +376,8 @@ void OGROCIWritableLayer::SetDimension( int nNewDim )
 /*                            ParseDIMINFO()                            */
 /************************************************************************/
 
-void OGROCIWritableLayer::ParseDIMINFO( const char *pszOptionName, 
-                                        double *pdfMin, 
+void OGROCIWritableLayer::ParseDIMINFO( const char *pszOptionName,
+                                        double *pdfMin,
                                         double *pdfMax,
                                         double *pdfRes )
 
@@ -388,13 +389,13 @@ void OGROCIWritableLayer::ParseDIMINFO( const char *pszOptionName,
     if( pszUserDIMINFO == NULL )
         return;
 
-    papszTokens = 
+    papszTokens =
         CSLTokenizeStringComplex( pszUserDIMINFO, ",", FALSE, FALSE );
     if( CSLCount(papszTokens) != 3 )
     {
         CSLDestroy( papszTokens );
-        CPLError( CE_Warning, CPLE_AppDefined, 
-                  "Ignoring %s, it does not contain three comma separated values.", 
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Ignoring %s, it does not contain three comma separated values.",
                   pszOptionName );
         return;
     }
@@ -430,14 +431,14 @@ OGRErr OGROCIWritableLayer::TranslateToSDOGeometry( OGRGeometry * poGeometry,
         OGRPoint *poPoint = (OGRPoint *) poGeometry;
 
         if( nDimension == 2 )
-            CPLsprintf( szResult, 
+            CPLsprintf( szResult,
                      "%s(%d,%s,MDSYS.SDO_POINT_TYPE(%.16g,%.16g,0.0),NULL,NULL)",
-                     SDO_GEOMETRY, 2001, szSRID, 
+                     SDO_GEOMETRY, 2001, szSRID,
                      poPoint->getX(), poPoint->getY() );
         else
-            CPLsprintf( szResult, 
+            CPLsprintf( szResult,
                      "%s(%d,%s,MDSYS.SDO_POINT_TYPE(%.16g,%.16g,%.16g),NULL,NULL)",
-                     SDO_GEOMETRY, 3001, szSRID, 
+                     SDO_GEOMETRY, 3001, szSRID,
                      poPoint->getX(), poPoint->getY(), poPoint->getZ() );
 
         return CPLStrdup(szResult );
@@ -474,7 +475,7 @@ OGRErr OGROCIWritableLayer::TranslateToSDOGeometry( OGRGeometry * poGeometry,
 
         *pnGType = nDimension*1000 + 5;
         PushElemInfo( 1, 1, poMP->getNumGeometries() );
-        
+
         for( iVert = 0; iVert < poMP->getNumGeometries(); iVert++ )
         {
             OGRPoint *poPoint = (OGRPoint *)poMP->getGeometryRef( iVert );
@@ -500,15 +501,15 @@ OGRErr OGROCIWritableLayer::TranslateToSDOGeometry( OGRGeometry * poGeometry,
             *pnGType = nDimension * 1000 + 6;
         else if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPolygon )
             *pnGType = nDimension * 1000 + 7;
-        else if( wkbFlatten(poGeometry->getGeometryType()) 
+        else if( wkbFlatten(poGeometry->getGeometryType())
                  == wkbGeometryCollection )
             *pnGType = nDimension * 1000 + 4;
-        else 
+        else
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Unexpected geometry type (%d/%s) in "
                       "OGROCIWritableLayer::TranslateToSDOGeometry()",
-                      poGeometry->getGeometryType(), 
+                      poGeometry->getGeometryType(),
                       poGeometry->getGeometryName() );
             return OGRERR_FAILURE;
         }
@@ -547,4 +548,3 @@ int OGROCIWritableLayer::FindFieldIndex( const char *pszFieldName, int bExactMat
 
   return iField;
 }
-
diff --git a/ogr/ogrsf_frmts/odbc/drv_odbc.html b/ogr/ogrsf_frmts/odbc/drv_odbc.html
index 4f7c27c..fbd7507 100644
--- a/ogr/ogrsf_frmts/odbc/drv_odbc.html
+++ b/ogr/ogrsf_frmts/odbc/drv_odbc.html
@@ -7,7 +7,7 @@
 
 <h1>ODBC RDBMS</h1>
 
-OGR optionally supports spatial and non-spatial tables accessed via ODBC. 
+OGR optionally supports spatial and non-spatial tables accessed via ODBC.
 ODBC is a generic access layer for access to many database systems, and
 data that can be represented as a database (collection of tables). ODBC
 support is potentially available on Unix and Windows platforms, but is
@@ -32,15 +32,15 @@ is what is used to access the datasource.<p>
 By default the ODBC searches for GEOMETRY_COLUMNS table.  If found it is
 used to identify the set of spatial tables that should be treated as layers
 by OGR.  If not found, then all tables in the datasource are returned as
-non-spatial layers.  However, if a table list (a list of comma seperated table
+non-spatial layers.  However, if a table list (a list of comma separated table
 names) is provided, then only those tables will be represented as layers
 (non-spatial).  Fetching the full definition of all tables in a complicated
-database can be quite timeconsuming, so the ability to restrict the set of
+database can be quite time consuming, so the ability to restrict the set of
 tables accessed is primarily a performance issue.<p>
 
-If the GEOMETRY_COLUMNS table is found, it is used to select a column to 
-be the geometry source.  If the tables are passed in the datasource name, 
-then the geometry column associated with a table can be included in 
+If the GEOMETRY_COLUMNS table is found, it is used to select a column to
+be the geometry source.  If the tables are passed in the datasource name,
+then the geometry column associated with a table can be included in
 round brackets after the tablename.  It is currently a hardcoded assumption
 that the geometry is in Well Known Binary (WKB) format if the field
 is binary, or Well Known Text (WKT) otherwise.  The GEOMETRY_COLUMNS
@@ -52,16 +52,16 @@ and YMAX then direct table queries with a spatial filter accelerate the
 spatial query.  The XMIN, YMIN, XMAX and YMAX fields should represent the
 extent of the geometry in the row in the tables coordinate system.<p>
 
-<p>By default, SQL statements are passed directly to the underlying database 
-engine.  It's also possible to request the driver to handle SQL commands 
-with the <a href="/ogr/ogr_sql.html">OGR SQL</a> engine, by passing 
-<strong>"OGRSQL"</strong> string to the ExecuteSQL() method, as name of 
+<p>By default, SQL statements are passed directly to the underlying database
+engine.  It's also possible to request the driver to handle SQL commands
+with the <a href="ogr_sql.html">OGR SQL</a> engine, by passing
+<strong>"OGRSQL"</strong> string to the ExecuteSQL() method, as name of
 the SQL dialect.</p>
 
 <h2>Access Databases (.MDB) support</h2>
 
 Starting with GDAL 1.10, and on Windows provided that the "Microsoft Access Driver (*.mdb)"
-ODBC driver is installed, non-spatial MS Access Databases (not Personnal
+ODBC driver is installed, non-spatial MS Access Databases (not Personal
 Geodabases or Geomedia databases) can be opened directly by their filenames.
 
 <h2>Creation Issues</h2>
diff --git a/ogr/ogrsf_frmts/odbc/ogr_odbc.h b/ogr/ogrsf_frmts/odbc/ogr_odbc.h
index 4b71851..d0cd383 100644
--- a/ogr/ogrsf_frmts/odbc/ogr_odbc.h
+++ b/ogr/ogrsf_frmts/odbc/ogr_odbc.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_odbc.h 28382 2015-01-30 15:29:41Z rouault $
+ * $Id: ogr_odbc.h 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/ODBC driver.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_ODBC_H_INCLUDED
-#define _OGR_ODBC_H_INCLUDED
+#ifndef OGR_ODBC_H_INCLUDED
+#define OGR_ODBC_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "cpl_odbc.h"
@@ -39,7 +39,7 @@
 /************************************************************************/
 
 class OGRODBCDataSource;
-    
+
 class OGRODBCLayer : public OGRLayer
 {
   protected:
@@ -75,7 +75,7 @@ class OGRODBCLayer : public OGRLayer
     virtual OGRFeature *GetNextFeature();
 
     virtual OGRFeature *GetFeature( GIntBig nFeatureId );
-    
+
     OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
 
     virtual OGRSpatialReference *GetSpatialRef();
@@ -107,7 +107,7 @@ class OGRODBCTableLayer : public OGRODBCLayer
                         OGRODBCTableLayer( OGRODBCDataSource * );
                         ~OGRODBCTableLayer();
 
-    CPLErr              Initialize( const char *pszTableName, 
+    CPLErr              Initialize( const char *pszTableName,
                                     const char *pszGeomCol );
 
     virtual void        ResetReading();
@@ -117,21 +117,21 @@ class OGRODBCTableLayer : public OGRODBCLayer
 #ifdef notdef
     virtual OGRErr      ISetFeature( OGRFeature *poFeature );
     virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
-    
+
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
                                      int bApproxOK = TRUE );
-#endif    
+#endif
     virtual OGRFeature *GetFeature( GIntBig nFeatureId );
-    
+
     virtual OGRSpatialReference *GetSpatialRef();
 
     virtual int         TestCapability( const char * );
 
 #ifdef notdef
     // follow methods are not base class overrides
-    void                SetLaunderFlag( int bFlag ) 
+    void                SetLaunderFlag( int bFlag )
                                 { bLaunderColumnNames = bFlag; }
-    void                SetPrecisionFlag( int bFlag ) 
+    void                SetPrecisionFlag( int bFlag )
                                 { bPreservePrecision = bFlag; }
 #endif
 };
@@ -150,7 +150,7 @@ class OGRODBCSelectLayer : public OGRODBCLayer
     virtual CPLODBCStatement *  GetStatement();
 
   public:
-                        OGRODBCSelectLayer( OGRODBCDataSource *, 
+                        OGRODBCSelectLayer( OGRODBCDataSource *,
                                            CPLODBCStatement * );
                         ~OGRODBCSelectLayer();
 
@@ -158,8 +158,10 @@ class OGRODBCSelectLayer : public OGRODBCLayer
     virtual GIntBig     GetFeatureCount( int );
 
     virtual OGRFeature *GetFeature( GIntBig nFeatureId );
-    
+
     virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
     virtual int         TestCapability( const char * );
 };
@@ -172,26 +174,26 @@ class OGRODBCDataSource : public OGRDataSource
 {
     OGRODBCLayer        **papoLayers;
     int                 nLayers;
-    
+
     char               *pszName;
 
     int                 bDSUpdate;
     CPLODBCSession      oSession;
 
     // We maintain a list of known SRID to reduce the number of trips to
-    // the database to get SRSes. 
+    // the database to get SRSes.
     int                 nKnownSRID;
     int                *panSRID;
     OGRSpatialReference **papoSRS;
-    
+
     int                 OpenMDB( const char *, int bUpdate );
-    
+
   public:
                         OGRODBCDataSource();
                         ~OGRODBCDataSource();
 
     int                 Open( const char *, int bUpdate, int bTestOpen );
-    int                 OpenTable( const char *pszTableName, 
+    int                 OpenTable( const char *pszTableName,
                                    const char *pszGeomCol,
                                    int bUpdate );
 
@@ -219,17 +221,15 @@ class OGRODBCDriver : public OGRSFDriver
 {
   public:
                 ~OGRODBCDriver();
-                
+
     const char *GetName();
     OGRDataSource *Open( const char *, int );
 
     virtual OGRDataSource *CreateDataSource( const char *pszName,
                                              char ** = NULL );
-    
+
     int                 TestCapability( const char * );
 };
 
 
-#endif /* ndef _OGR_ODBC_H_INCLUDED */
-
-
+#endif /* ndef OGR_ODBC_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/odbc/ogrodbcdatasource.cpp b/ogr/ogrsf_frmts/odbc/ogrodbcdatasource.cpp
index a746534..338ad75 100644
--- a/ogr/ogrsf_frmts/odbc/ogrodbcdatasource.cpp
+++ b/ogr/ogrsf_frmts/odbc/ogrodbcdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrodbcdatasource.cpp 28368 2015-01-27 14:25:17Z rouault $
+ * $Id: ogrodbcdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRODBCDataSource class.
@@ -32,13 +32,13 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrodbcdatasource.cpp 28368 2015-01-27 14:25:17Z rouault $");
+CPL_CVSID("$Id: ogrodbcdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 /************************************************************************/
 /*                         OGRODBCDataSource()                          */
 /************************************************************************/
 
-OGRODBCDataSource::OGRODBCDataSource()
-
+OGRODBCDataSource::OGRODBCDataSource() :
+    bDSUpdate(FALSE)
 {
     pszName = NULL;
     papoLayers = NULL;
@@ -62,7 +62,7 @@ OGRODBCDataSource::~OGRODBCDataSource()
 
     for( i = 0; i < nLayers; i++ )
         delete papoLayers[i];
-    
+
     CPLFree( papoLayers );
 
     for( i = 0; i < nKnownSRID; i++ )
@@ -130,7 +130,10 @@ int OGRODBCDataSource::OpenMDB( const char * pszNewName, int bUpdate )
         return FALSE;
     }
     char* pszDSN = (char *) CPLMalloc(strlen(pszNewName)+strlen(pszDSNStringTemplate)+100);
-    sprintf( pszDSN, pszDSNStringTemplate,  pszNewName );
+    /* coverity[tainted_string] */
+    snprintf( pszDSN,
+              strlen(pszNewName)+strlen(pszDSNStringTemplate)+100,
+              pszDSNStringTemplate,  pszNewName );
 
 /* -------------------------------------------------------------------- */
 /*      Initialize based on the DSN.                                    */
@@ -146,7 +149,9 @@ int OGRODBCDataSource::OpenMDB( const char * pszNewName, int bUpdate )
             pszDSNStringTemplate = "DRIVER=Microsoft Access Driver (*.mdb, *.accdb);DBQ=%s";
             CPLFree( pszDSN );
             pszDSN = (char *) CPLMalloc(strlen(pszNewName)+strlen(pszDSNStringTemplate)+100);
-            sprintf( pszDSN, pszDSNStringTemplate,  pszNewName );
+            snprintf( pszDSN,
+                      strlen(pszNewName)+strlen(pszDSNStringTemplate)+100,
+                      pszDSNStringTemplate,  pszNewName );
             CPLDebug( "ODBC", "EstablishSession(%s)", pszDSN );
             if( oSession.EstablishSession( pszDSN, NULL, NULL ) )
             {
@@ -155,7 +160,7 @@ int OGRODBCDataSource::OpenMDB( const char * pszNewName, int bUpdate )
         }
         if( bError )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                     "Unable to initialize ODBC connection to DSN for %s,\n"
                     "%s", pszDSN, oSession.GetLastError() );
             CPLFree( pszDSN );
@@ -249,7 +254,7 @@ int OGRODBCDataSource::Open( const char * pszNewName, int bUpdate,
 {
     CPLAssert( nLayers == 0 );
 
-    if( !EQUALN(pszNewName, "ODBC:",5) && EQUAL(CPLGetExtension(pszNewName), "MDB") )
+    if( !STARTS_WITH_CI(pszNewName, "ODBC:") && EQUAL(CPLGetExtension(pszNewName), "MDB") )
         return OpenMDB(pszNewName, bUpdate);
 
 /* -------------------------------------------------------------------- */
@@ -293,7 +298,7 @@ int OGRODBCDataSource::Open( const char * pszNewName, int bUpdate,
                 *pszComma = '\0';
                 pszSRIDCol = CPLStrdup( pszComma + 1 );
             }
-            
+
             *pszOBracket = '\0';
             pszSRSTableName = CPLStrdup( pszDelimiter + 1 );
             pszSRTextCol = CPLStrdup( pszOBracket + 1 );
@@ -303,7 +308,7 @@ int OGRODBCDataSource::Open( const char * pszNewName, int bUpdate,
     }
 
 /* -------------------------------------------------------------------- */
-/*      Strip off any comma delimeted set of tables names to access     */
+/*      Strip off any comma delimited set of tables names to access     */
 /*      from the end of the string first.  Also allow an optional       */
 /*      bracketed geometry column name after the table name.            */
 /* -------------------------------------------------------------------- */
@@ -318,10 +323,10 @@ int OGRODBCDataSource::Open( const char * pszNewName, int bUpdate,
         else
         {
             char *pszCBracket = strstr(pszOBracket,")");
-            
+
             if( pszCBracket != NULL )
                 *pszCBracket = '\0';
-            
+
             *pszOBracket = '\0';
             papszTables = CSLAddString( papszTables, pszDelimiter + 1 );
             papszGeomCol = CSLAddString( papszGeomCol, pszOBracket+1 );
@@ -374,21 +379,24 @@ int OGRODBCDataSource::Open( const char * pszNewName, int bUpdate,
 /*      Initialize based on the DSN.                                    */
 /* -------------------------------------------------------------------- */
     CPLDebug( "OGR_ODBC",
-              "EstablishSession(DSN:\"%s\", userid:\"%s\", password:\"%s\")", 
+              "EstablishSession(DSN:\"%s\", userid:\"%s\", password:\"%s\")",
               pszDSN, pszUserid ? pszUserid : "",
               pszPassword ? pszPassword : "" );
 
     if( !oSession.EstablishSession( pszDSN, pszUserid, pszPassword ) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to initialize ODBC connection to DSN for %s,\n"
-                  "%s", 
+                  "%s",
                   pszNewName+5, oSession.GetLastError() );
         CSLDestroy( papszTables );
         CSLDestroy( papszGeomCol );
         CPLFree( pszDSN );
         CPLFree( pszUserid );
         CPLFree( pszPassword );
+        CPLFree( pszSRIDCol );
+        CPLFree( pszSRTextCol );
+        CPLFree( pszSRSTableName );
         return FALSE;
     }
 
@@ -397,7 +405,7 @@ int OGRODBCDataSource::Open( const char * pszNewName, int bUpdate,
     CPLFree( pszPassword );
 
     pszName = CPLStrdup( pszNewName );
-    
+
     bDSUpdate = bUpdate;
 
 /* -------------------------------------------------------------------- */
@@ -407,21 +415,21 @@ int OGRODBCDataSource::Open( const char * pszNewName, int bUpdate,
     if( papszTables == NULL )
     {
         CPLODBCStatement oStmt( &oSession );
-        
+
         oStmt.Append( "SELECT f_table_name, f_geometry_column, geometry_type"
                       " FROM geometry_columns" );
         if( oStmt.ExecuteSQL() )
         {
             while( oStmt.Fetch() )
             {
-                papszTables = 
+                papszTables =
                     CSLAddString( papszTables, oStmt.GetColData(0) );
-                papszGeomCol = 
+                papszGeomCol =
                     CSLAddString( papszGeomCol, oStmt.GetColData(1) );
             }
         }
     }
-            
+
 /* -------------------------------------------------------------------- */
 /*      Otherwise our final resort is to return all tables as           */
 /*      non-spatial tables.                                             */
@@ -429,7 +437,7 @@ int OGRODBCDataSource::Open( const char * pszNewName, int bUpdate,
     if( papszTables == NULL )
     {
         CPLODBCStatement oTableList( &oSession );
-        
+
         if( oTableList.GetTables() )
         {
             while( oTableList.Fetch() )
@@ -456,8 +464,8 @@ int OGRODBCDataSource::Open( const char * pszNewName, int bUpdate,
 /*      If we have an explicit list of requested tables, use them       */
 /*      (non-spatial).                                                  */
 /* -------------------------------------------------------------------- */
-    for( int iTable = 0; 
-         papszTables != NULL && papszTables[iTable] != NULL; 
+    for( int iTable = 0;
+         papszTables != NULL && papszTables[iTable] != NULL;
          iTable++ )
     {
         if( strlen(papszGeomCol[iTable]) > 0 )
@@ -568,7 +576,7 @@ int OGRODBCDataSource::OpenTable( const char *pszNewName,
     papoLayers = (OGRODBCLayer **)
         CPLRealloc( papoLayers,  sizeof(OGRODBCLayer *) * (nLayers+1) );
     papoLayers[nLayers++] = poLayer;
-    
+
     return TRUE;
 }
 
@@ -606,8 +614,8 @@ OGRLayer * OGRODBCDataSource::ExecuteSQL( const char *pszSQLCommand,
 /*      Use generic implementation for recognized dialects              */
 /* -------------------------------------------------------------------- */
     if( IsGenericSQLDialect(pszDialect) )
-        return OGRDataSource::ExecuteSQL( pszSQLCommand, 
-                                          poSpatialFilter, 
+        return OGRDataSource::ExecuteSQL( pszSQLCommand,
+                                          poSpatialFilter,
                                           pszDialect );
 
 /* -------------------------------------------------------------------- */
@@ -619,8 +627,9 @@ OGRLayer * OGRODBCDataSource::ExecuteSQL( const char *pszSQLCommand,
     poStmt->Append( pszSQLCommand );
     if( !poStmt->ExecuteSQL() )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", oSession.GetLastError() );
+        delete poStmt;
         return NULL;
     }
 
@@ -639,12 +648,12 @@ OGRLayer * OGRODBCDataSource::ExecuteSQL( const char *pszSQLCommand,
 /*      statement.                                                      */
 /* -------------------------------------------------------------------- */
     OGRODBCSelectLayer *poLayer = NULL;
-        
+
     poLayer = new OGRODBCSelectLayer( this, poStmt );
 
     if( poSpatialFilter != NULL )
         poLayer->SetSpatialFilter( poSpatialFilter );
-    
+
     return poLayer;
 }
 
diff --git a/ogr/ogrsf_frmts/odbc/ogrodbcdriver.cpp b/ogr/ogrsf_frmts/odbc/ogrodbcdriver.cpp
index dbce232..b077616 100644
--- a/ogr/ogrsf_frmts/odbc/ogrodbcdriver.cpp
+++ b/ogr/ogrsf_frmts/odbc/ogrodbcdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrodbcdriver.cpp 24957 2012-09-23 17:03:30Z rouault $
+ * $Id: ogrodbcdriver.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRODBCDriver class.
@@ -30,7 +30,7 @@
 #include "ogr_odbc.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrodbcdriver.cpp 24957 2012-09-23 17:03:30Z rouault $");
+CPL_CVSID("$Id: ogrodbcdriver.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                            ~OGRODBCDriver()                            */
@@ -61,7 +61,7 @@ OGRDataSource *OGRODBCDriver::Open( const char * pszFilename,
 {
     OGRODBCDataSource     *poDS;
 
-    if( !EQUALN(pszFilename,"ODBC:",5) 
+    if( !STARTS_WITH_CI(pszFilename, "ODBC:")
 #ifdef WIN32
         && !EQUAL(CPLGetExtension(pszFilename), "MDB")
 #endif
@@ -89,7 +89,7 @@ OGRDataSource *OGRODBCDriver::CreateDataSource( const char * pszName,
 {
     OGRODBCDataSource     *poDS;
 
-    if( !EQUALN(pszName,"ODBC:",5) )
+    if( !STARTS_WITH_CI(pszName, "ODBC:") )
         return NULL;
 
     poDS = new OGRODBCDataSource();
@@ -98,7 +98,7 @@ OGRDataSource *OGRODBCDriver::CreateDataSource( const char * pszName,
     if( !poDS->Open( pszName, TRUE, TRUE ) )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
          "ODBC driver doesn't currently support database creation.\n"
                   "Please create database with the `createdb' command." );
         return NULL;
@@ -129,4 +129,3 @@ void RegisterOGRODBC()
 {
     OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( new OGRODBCDriver );
 }
-
diff --git a/ogr/ogrsf_frmts/odbc/ogrodbclayer.cpp b/ogr/ogrsf_frmts/odbc/ogrodbclayer.cpp
index 9651982..52b15bb 100644
--- a/ogr/ogrsf_frmts/odbc/ogrodbclayer.cpp
+++ b/ogr/ogrsf_frmts/odbc/ogrodbclayer.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: ogrodbclayer.cpp 29014 2015-04-25 18:14:49Z tamas $
+ * $Id: ogrodbclayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
- * Purpose:  Implements OGRODBCLayer class, code shared between 
+ * Purpose:  Implements OGRODBCLayer class, code shared between
  *           the direct table access, and the generic SQL results.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -32,7 +32,7 @@
 #include "ogr_odbc.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrodbclayer.cpp 29014 2015-04-25 18:14:49Z tamas $");
+CPL_CVSID("$Id: ogrodbclayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                            OGRODBCLayer()                            */
@@ -53,7 +53,8 @@ OGRODBCLayer::OGRODBCLayer()
     iNextShapeId = 0;
 
     poSRS = NULL;
-    nSRSId = -2; // we haven't even queried the database for it yet. 
+    nSRSId = -2; // we haven't even queried the database for it yet.
+    poFeatureDefn = NULL;
 }
 
 /************************************************************************/
@@ -66,7 +67,7 @@ OGRODBCLayer::~OGRODBCLayer()
     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     {
         CPLDebug( "OGR_ODBC", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
+                  (int) m_nFeaturesRead,
                   poFeatureDefn->GetName() );
     }
 
@@ -99,13 +100,13 @@ OGRODBCLayer::~OGRODBCLayer()
 /*      set on a statement.  Sift out geometry and FID fields.          */
 /************************************************************************/
 
-CPLErr OGRODBCLayer::BuildFeatureDefn( const char *pszLayerName, 
-                                    CPLODBCStatement *poStmt )
+CPLErr OGRODBCLayer::BuildFeatureDefn( const char *pszLayerName,
+                                    CPLODBCStatement *poStmtIn )
 
 {
     poFeatureDefn = new OGRFeatureDefn( pszLayerName );
     SetDescription( poFeatureDefn->GetName() );
-    int    nRawColumns = poStmt->GetColCount();
+    int    nRawColumns = poStmtIn->GetColCount();
 
     poFeatureDefn->Reference();
 
@@ -113,15 +114,15 @@ CPLErr OGRODBCLayer::BuildFeatureDefn( const char *pszLayerName,
 
     for( int iCol = 0; iCol < nRawColumns; iCol++ )
     {
-        OGRFieldDefn    oField( poStmt->GetColName(iCol), OFTString );
+        OGRFieldDefn    oField( poStmtIn->GetColName(iCol), OFTString );
 
-        oField.SetWidth( MAX(0,poStmt->GetColSize( iCol )) );
+        oField.SetWidth( MAX(0,poStmtIn->GetColSize( iCol )) );
 
-        if( pszGeomColumn != NULL 
-            && EQUAL(poStmt->GetColName(iCol),pszGeomColumn) )
+        if( pszGeomColumn != NULL
+            && EQUAL(poStmtIn->GetColName(iCol),pszGeomColumn) )
             continue;
 
-        switch( CPLODBCStatement::GetTypeMapping(poStmt->GetColType(iCol)) )
+        switch( CPLODBCStatement::GetTypeMapping(poStmtIn->GetColType(iCol)) )
         {
             case SQL_C_SSHORT:
             case SQL_C_USHORT:
@@ -141,7 +142,7 @@ CPLErr OGRODBCLayer::BuildFeatureDefn( const char *pszLayerName,
 
             case SQL_C_NUMERIC:
                 oField.SetType( OFTReal );
-                oField.SetPrecision( poStmt->GetColPrecision(iCol) );
+                oField.SetPrecision( poStmtIn->GetColPrecision(iCol) );
                 break;
 
             case SQL_C_FLOAT:
@@ -209,7 +210,7 @@ void OGRODBCLayer::ResetReading()
 OGRFeature *OGRODBCLayer::GetNextFeature()
 
 {
-    for( ; TRUE; )
+    while( true )
     {
         OGRFeature      *poFeature;
 
@@ -250,11 +251,10 @@ OGRFeature *OGRODBCLayer::GetNextRawFeature()
 /* -------------------------------------------------------------------- */
 /*      Create a feature from the current result.                       */
 /* -------------------------------------------------------------------- */
-    int         iField;
     OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
 
     if( pszFIDColumn != NULL && poStmt->GetColId(pszFIDColumn) > -1 )
-        poFeature->SetFID( 
+        poFeature->SetFID(
             atoi(poStmt->GetColData(poStmt->GetColId(pszFIDColumn))) );
     else
         poFeature->SetFID( iNextShapeId );
@@ -265,7 +265,7 @@ OGRFeature *OGRODBCLayer::GetNextRawFeature()
 /* -------------------------------------------------------------------- */
 /*      Set the fields.                                                 */
 /* -------------------------------------------------------------------- */
-    for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
+    for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     {
         int iSrcField = panFieldOrdinals[iField]-1;
         const char *pszValue = poStmt->GetColData( iSrcField );
@@ -273,7 +273,7 @@ OGRFeature *OGRODBCLayer::GetNextRawFeature()
         if( pszValue == NULL )
             /* no value */;
         else if( poFeature->GetFieldDefnRef(iField)->GetType() == OFTBinary )
-            poFeature->SetField( iField, 
+            poFeature->SetField( iField,
                                  poStmt->GetColDataLength(iSrcField),
                                  (GByte *) pszValue );
         else
@@ -304,7 +304,7 @@ OGRFeature *OGRODBCLayer::GetNextRawFeature()
                 OGRGeometryFactory::createFromWkb((unsigned char *) pszGeomText,
                                                   NULL, &poGeom, nLength);
         }
-        
+
         if ( eErr != OGRERR_NONE )
         {
             const char *pszMessage;
diff --git a/ogr/ogrsf_frmts/odbc/ogrodbctablelayer.cpp b/ogr/ogrsf_frmts/odbc/ogrodbctablelayer.cpp
index f74c6bd..aa0cf96 100644
--- a/ogr/ogrsf_frmts/odbc/ogrodbctablelayer.cpp
+++ b/ogr/ogrsf_frmts/odbc/ogrodbctablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrodbctablelayer.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrodbctablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRODBCTableLayer class, access to an existing table.
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "ogr_odbc.h"
 
-CPL_CVSID("$Id: ogrodbctablelayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrodbctablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 /************************************************************************/
 /*                          OGRODBCTableLayer()                         */
 /************************************************************************/
@@ -51,7 +51,7 @@ OGRODBCTableLayer::OGRODBCTableLayer( OGRODBCDataSource *poDSIn )
     nSRSId = -1;
 
     poFeatureDefn = NULL;
-    
+
     pszTableName = NULL;
     pszSchemaName = NULL;
 }
@@ -74,7 +74,7 @@ OGRODBCTableLayer::~OGRODBCTableLayer()
 /*                             Initialize()                             */
 /************************************************************************/
 
-CPLErr OGRODBCTableLayer::Initialize( const char *pszLayerName, 
+CPLErr OGRODBCTableLayer::Initialize( const char *pszLayerName,
                                       const char *pszGeomCol )
 
 {
@@ -82,7 +82,7 @@ CPLErr OGRODBCTableLayer::Initialize( const char *pszLayerName,
 
     CPLFree( pszFIDColumn );
     pszFIDColumn = NULL;
-    
+
     SetDescription( pszLayerName );
 
 /* -------------------------------------------------------------------- */
@@ -106,13 +106,13 @@ CPLErr OGRODBCTableLayer::Initialize( const char *pszLayerName,
 /*      Do we have a simple primary key?                                */
 /* -------------------------------------------------------------------- */
     CPLODBCStatement oGetKey( poSession );
-    
-    if( oGetKey.GetPrimaryKeys( pszTableName, NULL, pszSchemaName ) 
+
+    if( oGetKey.GetPrimaryKeys( pszTableName, NULL, pszSchemaName )
         && oGetKey.Fetch() )
     {
         pszFIDColumn = CPLStrdup(oGetKey.GetColData( 3 ));
-        
-        if( oGetKey.Fetch() ) // more than one field in key! 
+
+        if( oGetKey.Fetch() ) // more than one field in key!
         {
             CPLFree( pszFIDColumn );
             pszFIDColumn = NULL;
@@ -146,8 +146,8 @@ CPLErr OGRODBCTableLayer::Initialize( const char *pszLayerName,
 
     if( poFeatureDefn->GetFieldCount() == 0 )
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
-                  "No column definitions found for table '%s', layer not usable.", 
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "No column definitions found for table '%s', layer not usable.",
                   pszLayerName );
         return CE_Failure;
     }
@@ -155,16 +155,16 @@ CPLErr OGRODBCTableLayer::Initialize( const char *pszLayerName,
 /* -------------------------------------------------------------------- */
 /*      Do we have XMIN, YMIN, XMAX, YMAX extent fields?                */
 /* -------------------------------------------------------------------- */
-    if( poFeatureDefn->GetFieldIndex( "XMIN" ) != -1 
-        && poFeatureDefn->GetFieldIndex( "XMAX" ) != -1 
-        && poFeatureDefn->GetFieldIndex( "YMIN" ) != -1 
+    if( poFeatureDefn->GetFieldIndex( "XMIN" ) != -1
+        && poFeatureDefn->GetFieldIndex( "XMAX" ) != -1
+        && poFeatureDefn->GetFieldIndex( "YMIN" ) != -1
         && poFeatureDefn->GetFieldIndex( "YMAX" ) != -1 )
     {
         bHaveSpatialExtents = TRUE;
         CPLDebug( "OGR_ODBC", "Table %s has geometry extent fields.",
                   pszLayerName );
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      If we got a geometry column, does it exist?  Is it binary?      */
 /* -------------------------------------------------------------------- */
@@ -173,8 +173,8 @@ CPLErr OGRODBCTableLayer::Initialize( const char *pszLayerName,
         int iColumn = oGetCol.GetColId( pszGeomColumn );
         if( iColumn < 0 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Column %s requested for geometry, but it does not exist.", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Column %s requested for geometry, but it does not exist.",
                       pszGeomColumn );
             CPLFree( pszGeomColumn );
             pszGeomColumn = NULL;
@@ -244,10 +244,10 @@ OGRErr OGRODBCTableLayer::ResetStatement()
             poStmt->Append( " WHERE" );
         else
             poStmt->Append( " AND" );
-        
+
         poStmt->Appendf( " XMAX > %.8f AND XMIN < %.8f"
-                         " AND YMAX > %.8f AND YMIN < %.8f", 
-                         m_sFilterEnvelope.MinX, m_sFilterEnvelope.MaxX, 
+                         " AND YMAX > %.8f AND YMIN < %.8f",
+                         m_sFilterEnvelope.MinX, m_sFilterEnvelope.MaxX,
                          m_sFilterEnvelope.MinY, m_sFilterEnvelope.MaxY );
     }
 
@@ -306,19 +306,19 @@ OGRFeature *OGRODBCTableLayer::GetFeature( GIntBig nFeatureId )
 /*                         SetAttributeFilter()                         */
 /************************************************************************/
 
-OGRErr OGRODBCTableLayer::SetAttributeFilter( const char *pszQuery )
+OGRErr OGRODBCTableLayer::SetAttributeFilter( const char *pszQueryIn )
 
 {
     CPLFree(m_pszAttrQueryString);
-    m_pszAttrQueryString = (pszQuery) ? CPLStrdup(pszQuery) : NULL;
+    m_pszAttrQueryString = (pszQueryIn) ? CPLStrdup(pszQueryIn) : NULL;
 
-    if( (pszQuery == NULL && this->pszQuery == NULL)
-        || (pszQuery != NULL && this->pszQuery != NULL 
-            && EQUAL(pszQuery,this->pszQuery)) )
+    if( (pszQueryIn == NULL && this->pszQuery == NULL)
+        || (pszQueryIn != NULL && this->pszQuery != NULL
+            && EQUAL(pszQueryIn,this->pszQuery)) )
         return OGRERR_NONE;
 
     CPLFree( this->pszQuery );
-    this->pszQuery = (pszQuery != NULL ) ? CPLStrdup( pszQuery ) : NULL;
+    this->pszQuery = (pszQueryIn != NULL ) ? CPLStrdup( pszQueryIn ) : NULL;
 
     ClearStatement();
 
@@ -335,8 +335,8 @@ int OGRODBCTableLayer::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,OLCRandomRead) )
         return TRUE;
-        
-    else 
+
+    else
         return OGRODBCLayer::TestCapability( pszCap );
 }
 
@@ -364,7 +364,7 @@ GIntBig OGRODBCTableLayer::GetFeatureCount( int bForce )
 
     if( !oStmt.ExecuteSQL() || !oStmt.Fetch() )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "GetFeatureCount() failed on query %s.\n%s",
                   oStmt.GetCommand(), poDS->GetSession()->GetLastError() );
         return OGRODBCLayer::GetFeatureCount(bForce);
@@ -395,14 +395,14 @@ OGRSpatialReference *OGRODBCTableLayer::GetSpatialRef()
 
         poDS->SoftStartTransaction();
 
-        sprintf( szCommand, 
+        sprintf( szCommand,
                  "SELECT srid FROM geometry_columns "
                  "WHERE f_table_name = '%s'",
                  poFeatureDefn->GetName() );
         hResult = PQexec(hPGConn, szCommand );
 
-        if( hResult 
-            && PQresultStatus(hResult) == PGRES_TUPLES_OK 
+        if( hResult
+            && PQresultStatus(hResult) == PGRES_TUPLES_OK
             && PQntuples(hResult) == 1 )
         {
             nSRSId = atoi(PQgetvalue(hResult,0,0));
@@ -414,4 +414,3 @@ OGRSpatialReference *OGRODBCTableLayer::GetSpatialRef()
 
     return OGRODBCLayer::GetSpatialRef();
 }
-
diff --git a/ogr/ogrsf_frmts/ods/GNUmakefile b/ogr/ogrsf_frmts/ods/GNUmakefile
index a0884e7..585a438 100644
--- a/ogr/ogrsf_frmts/ods/GNUmakefile
+++ b/ogr/ogrsf_frmts/ods/GNUmakefile
@@ -2,7 +2,7 @@
 
 include ../../../GDALmake.opt
 
-OBJ	=	ogrodsdriver.o ogrodsdatasource.o ods_formula.o ods_formula_parser.o ods_formula_node.o
+OBJ	=	ogrodsdriver.o ogrodsdatasource.o ods_formula.o ods_formula_node.o
 
 ifeq ($(HAVE_EXPAT),yes)
 CPPFLAGS +=   -DHAVE_EXPAT
@@ -17,16 +17,17 @@ clean:
 
 $(O_OBJ):	ogr_ods.h ods_formula.h ods_formula_parser.hpp ../mem/ogr_mem.h
 
-# The sed substition below workarounds a bug with gcc 4.1 -O2 (checked on 64bit platforms)
+# The sed substitution below workarounds a bug with gcc 4.1 -O2 (checked on 64bit platforms)
 # that produces buggy compiled code.
 # Seen on gcc 4.1.2-27ubuntu1 (Ubuntu 10.04) (not the default compiler) and gcc-4.1.2-48.el5 (CentOS 5.5)
 # (default compiler...)
 # The memset isn't necessary at all with a non-buggy compiler, but I've found
 # that it helps gcc 4.1 generating correct code here...
+# The sed with yyerrorlab shut up MSVC warnings about unreachable code
 parser:
 	bison -p ods_formula -d -oods_formula_parser.cpp ods_formula_parser.y
-	sed "s/yytype_int16 yyssa\[YYINITDEPTH\];/yytype_int16 yyssa[YYINITDEPTH]; \/\* workaround bug with gcc 4.1 -O2 \*\/ memset(yyssa, 0, sizeof(yyssa));/" < ods_formula_parser.cpp > ods_formula_parser.cpp.tmp
+	sed "s/yytype_int16 yyssa\[YYINITDEPTH\];/yytype_int16 yyssa[YYINITDEPTH]; \/\* workaround bug with gcc 4.1 -O2 \*\/ memset(yyssa, 0, sizeof(yyssa));/" < ods_formula_parser.cpp | sed "s/\*yyssp = yystate/\*yyssp = (yytype_int16)yystate/" | sed "s/yyerrorlab:/#if 0\nyyerrorlab:/" | sed "s/yyerrlab1:/#endif\nyyerrlab1:/" | sed "s/YY_INITIAL_VALUE (static YYSTYPE yyval_default;)//" | sed "s/YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);/YYSTYPE yylval = NULL;/" > ods_formula_parser.cpp.tmp
 	mv ods_formula_parser.cpp.tmp ods_formula_parser.cpp
 
 testparser$(EXE):	testparser.$(OBJ_EXT)
-	$(LD) $(LDFLAGS) testparser.$(OBJ_EXT) $(CONFIG_LIBS) -o testparser$(EXE)
\ No newline at end of file
+	$(LD) $(LDFLAGS) testparser.$(OBJ_EXT) $(CONFIG_LIBS) -o testparser$(EXE)
diff --git a/ogr/ogrsf_frmts/ods/drv_ods.html b/ogr/ogrsf_frmts/ods/drv_ods.html
index 82adc40..a994370 100644
--- a/ogr/ogrsf_frmts/ods/drv_ods.html
+++ b/ogr/ogrsf_frmts/ods/drv_ods.html
@@ -25,7 +25,7 @@ not understood by OGR will be lost : the document is re-written from scratch fro
 <ul>
 <li>OGR_ODS_HEADERS = FORCE / DISABLE / AUTO : By default, the driver will read the first lines of each sheet to detect if the
 first line might be the name of columns. If set to FORCE, the driver will consider the first line will be taken as the header line.
-If set to DISABLE, it will be considered as the first feature. Otherwise auto-dection will occur.</li>
+If set to DISABLE, it will be considered as the first feature. Otherwise auto-detection will occur.</li>
 <li>OGR_ODS_FIELD_TYPES = STRING / AUTO : By default, the driver will try to detect the data type of fields. If set to STRING,
 all fields will be of String type.</li>
 </ul>
diff --git a/ogr/ogrsf_frmts/ods/makefile.vc b/ogr/ogrsf_frmts/ods/makefile.vc
index 3f27728..edb53b3 100644
--- a/ogr/ogrsf_frmts/ods/makefile.vc
+++ b/ogr/ogrsf_frmts/ods/makefile.vc
@@ -1,5 +1,5 @@
 
-OBJ	=	ogrodsdriver.obj ogrodsdatasource.obj ods_formula.obj ods_formula_parser.obj ods_formula_node.obj
+OBJ	=	ogrodsdriver.obj ogrodsdatasource.obj ods_formula.obj ods_formula_node.obj
 
 GDAL_ROOT	=	..\..\..
 
diff --git a/ogr/ogrsf_frmts/ods/ods_formula.cpp b/ogr/ogrsf_frmts/ods/ods_formula.cpp
index 9a9d2d3..3d949f8 100644
--- a/ogr/ogrsf_frmts/ods/ods_formula.cpp
+++ b/ogr/ogrsf_frmts/ods/ods_formula.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ods_formula.cpp 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: ods_formula.cpp 32967 2016-01-13 14:40:01Z goatbar $
  *
  * Component: ODS formula Engine
  * Purpose:
@@ -28,13 +28,21 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include <ctype.h>
-#include <math.h>
+#include <cctype>
+#include <cmath>
 
 #include "cpl_conv.h"
 #include "ods_formula.h"
+
+namespace {
 #include "ods_formula_parser.hpp"
 
+int ods_formulalex( ods_formula_node **ppNode,
+                    ods_formula_parse_context *context );
+
+#include "ods_formula_parser.cpp"
+} /* end of anonymous namespace */
+
 #define YYSTYPE  ods_formula_node*
 
 static const SingleOpStruct apsSingleOp[] =
@@ -78,7 +86,7 @@ const SingleOpStruct* ODSGetSingleOpEntry(ods_formula_op eOp)
 /*                                                                      */
 /*      Read back a token from the input.                               */
 /************************************************************************/
-
+namespace {
 int ods_formulalex( YYSTYPE *ppNode, ods_formula_parse_context *context )
 {
     const char *pszInput = context->pszNext;
@@ -105,7 +113,7 @@ int ods_formulalex( YYSTYPE *ppNode, ods_formula_parse_context *context )
     if( *pszInput == '\0' )
     {
         context->pszNext = pszInput;
-        return EOF; 
+        return EOF;
     }
 
 /* -------------------------------------------------------------------- */
@@ -113,13 +121,10 @@ int ods_formulalex( YYSTYPE *ppNode, ods_formula_parse_context *context )
 /* -------------------------------------------------------------------- */
     if( *pszInput == '"' )
     {
-        char *token;
-        int i_token;
-
         pszInput++;
 
-        token = (char *) CPLMalloc(strlen(pszInput)+1);
-        i_token = 0;
+        char *token = static_cast<char *>( CPLMalloc(strlen(pszInput)+1) );
+        int i_token = 0;
 
         while( *pszInput != '\0' )
         {
@@ -139,7 +144,7 @@ int ods_formulalex( YYSTYPE *ppNode, ods_formula_parse_context *context )
                 pszInput++;
                 break;
             }
-            
+
             token[i_token++] = *(pszInput++);
         }
         token[i_token] = '\0';
@@ -157,9 +162,9 @@ int ods_formulalex( YYSTYPE *ppNode, ods_formula_parse_context *context )
 /* -------------------------------------------------------------------- */
     else if( *pszInput >= '0' && *pszInput <= '9' )
     {
-        CPLString osToken;
         const char *pszNext = pszInput + 1;
 
+        CPLString osToken;
         osToken += *pszInput;
 
         // collect non-decimal part of number
@@ -186,8 +191,8 @@ int ods_formulalex( YYSTYPE *ppNode, ods_formula_parse_context *context )
 
         context->pszNext = pszNext;
 
-        if( strstr(osToken,".") 
-            || strstr(osToken,"e") 
+        if( strstr(osToken,".")
+            || strstr(osToken,"e")
             || strstr(osToken,"E") )
         {
             *ppNode = new ods_formula_node( CPLAtof(osToken) );
@@ -206,13 +211,13 @@ int ods_formulalex( YYSTYPE *ppNode, ods_formula_parse_context *context )
     else if( *pszInput == '.' || isalnum( *pszInput ) )
     {
         int nReturn = ODST_IDENTIFIER;
-        CPLString osToken;
         const char *pszNext = pszInput + 1;
 
+        CPLString osToken;
         osToken += *pszInput;
 
         // collect text characters
-        while( isalnum( *pszNext ) || *pszNext == '_' 
+        while( isalnum( *pszNext ) || *pszNext == '_'
                || ((unsigned char) *pszNext) > 127 )
             osToken += *(pszNext++);
 
@@ -258,7 +263,7 @@ int ods_formulalex( YYSTYPE *ppNode, ods_formula_parse_context *context )
             *ppNode = new ods_formula_node( ODS_T );
             return ODST_FUNCTION_SINGLE_ARG;
         }*/
-        
+
         /* Tow-arg functions */
         else if( EQUAL(osToken,"MOD") )
         {
@@ -342,6 +347,7 @@ int ods_formulalex( YYSTYPE *ppNode, ods_formula_parse_context *context )
         return *pszInput;
     }
 }
+} /* end of anonymous namespace */
 
 /************************************************************************/
 /*                        ods_formula_compile()                         */
@@ -360,9 +366,7 @@ ods_formula_node* ods_formula_compile( const char *expr )
     {
         return context.poRoot;
     }
-    else
-    {
-        delete context.poRoot;
-        return NULL;
-    }
+
+    delete context.poRoot;
+    return NULL;
 }
diff --git a/ogr/ogrsf_frmts/ods/ods_formula.h b/ogr/ogrsf_frmts/ods/ods_formula.h
index e55f4db..289cfae 100644
--- a/ogr/ogrsf_frmts/ods/ods_formula.h
+++ b/ogr/ogrsf_frmts/ods/ods_formula.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ods_formula.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: ods_formula.h 32967 2016-01-13 14:40:01Z goatbar $
  *
  * Component: ODS formula Engine
  * Purpose: Implementation of the ods_formula_node class used to represent a
@@ -29,18 +29,16 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _ODS_FORMULA_H_INCLUDED_
-#define _ODS_FORMULA_H_INCLUDED_
+#ifndef ODS_FORMULA_H_INCLUDED_
+#define ODS_FORMULA_H_INCLUDED_
 
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
 #include <vector>
 
-#if defined(_WIN32) && !defined(_WIN32_WCE)
+#if defined(_WIN32)
 #  define strcasecmp stricmp
-#elif defined(_WIN32_WCE)
-#  define strcasecmp _stricmp
 #endif
 
 typedef enum {
@@ -95,6 +93,8 @@ typedef enum {
 
     ODS_CELL,
     ODS_CELL_RANGE,
+
+    ODS_INVALID
 } ods_formula_op;
 
 typedef enum {
@@ -116,6 +116,7 @@ private:
     void           FreeSubExpr();
     std::string    TransformToString() const;
 
+    // TODO: It appears that all the Evaluate methods should return bool.
     int            EvaluateOR(IODSCellEvaluator* poEvaluator);
     int            EvaluateAND(IODSCellEvaluator* poEvaluator);
     int            EvaluateNOT(IODSCellEvaluator* poEvaluator);
@@ -178,7 +179,11 @@ public:
 
 class ods_formula_parse_context {
 public:
-    ods_formula_parse_context() : nStartToken(0), poRoot(NULL) {}
+    ods_formula_parse_context() :
+        nStartToken(0),
+        pszInput(NULL),
+        pszNext(NULL),
+        poRoot(NULL) {}
 
     int        nStartToken;
     const char *pszInput;
@@ -195,8 +200,6 @@ public:
     virtual ~IODSCellEvaluator() {}
 };
 
-int ods_formulaparse( ods_formula_parse_context *context );
-int ods_formulalex( ods_formula_node **ppNode, ods_formula_parse_context *context );
 ods_formula_node* ods_formula_compile( const char *expr );
 
 typedef struct
@@ -209,4 +212,4 @@ typedef struct
 const SingleOpStruct* ODSGetSingleOpEntry(const char* pszName);
 const SingleOpStruct* ODSGetSingleOpEntry(ods_formula_op eOp);
 
-#endif /* def _ODS_FORMULA_H_INCLUDED_ */
+#endif /* def ODS_FORMULA_H_INCLUDED_ */
diff --git a/ogr/ogrsf_frmts/ods/ods_formula_node.cpp b/ogr/ogrsf_frmts/ods/ods_formula_node.cpp
index bfdb479..ae59eb8 100644
--- a/ogr/ogrsf_frmts/ods/ods_formula_node.cpp
+++ b/ogr/ogrsf_frmts/ods/ods_formula_node.cpp
@@ -1,11 +1,11 @@
 /******************************************************************************
- * $Id: ods_formula_node.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: ods_formula_node.cpp 32967 2016-01-13 14:40:01Z goatbar $
  *
  * Component: ODS formula Engine
  * Purpose: Implementation of the ods_formula_node class used to represent a
  *          node in a ODS expression.
  * Author: Even Rouault <even dot rouault at mines dash paris dot org>
- * 
+ *
  ******************************************************************************
  * Copyright (C) 2010 Frank Warmerdam <warmerdam at pobox.com>
  * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
@@ -32,73 +32,81 @@
 #include "cpl_conv.h"
 #include "ods_formula.h"
 
-#ifndef PI
-#define PI  3.14159265358979323846
-#endif
-
 /************************************************************************/
 /*                          ods_formula_node()                          */
 /************************************************************************/
 
-ods_formula_node::ods_formula_node()
-
-{
-    Initialize();
-}
+ods_formula_node::ods_formula_node() :
+    eNodeType(SNT_CONSTANT),
+    field_type(ODS_FIELD_TYPE_EMPTY),
+    eOp(ODS_INVALID),
+    nSubExprCount(0),
+    papoSubExpr(NULL),
+    string_value(NULL),
+    int_value(0),
+    float_value(0)
+{}
 
 /************************************************************************/
 /*                         ods_formula_node(int)                        */
 /************************************************************************/
 
-ods_formula_node::ods_formula_node( int nValueIn )
-
-{
-    Initialize();
-
-    field_type = ODS_FIELD_TYPE_INTEGER;
-    int_value = nValueIn;
-}
+ods_formula_node::ods_formula_node( int nValueIn ) :
+    eNodeType(SNT_CONSTANT),
+    field_type(ODS_FIELD_TYPE_INTEGER),
+    eOp(ODS_INVALID),
+    nSubExprCount(0),
+    papoSubExpr(NULL),
+    string_value(NULL),
+    int_value(nValueIn),
+    float_value(0)
+{}
 
 /************************************************************************/
 /*                      ods_formula_node(double)                        */
 /************************************************************************/
 
-ods_formula_node::ods_formula_node( double dfValueIn )
-
-{
-    Initialize();
-
-    field_type = ODS_FIELD_TYPE_FLOAT;
-    float_value = dfValueIn;
-}
+ods_formula_node::ods_formula_node( double dfValueIn ) :
+    eNodeType(SNT_CONSTANT),
+    field_type(ODS_FIELD_TYPE_FLOAT),
+    eOp(ODS_INVALID),
+    nSubExprCount(0),
+    papoSubExpr(NULL),
+    string_value(NULL),
+    int_value(0),
+    float_value(dfValueIn)
+{}
 
 /************************************************************************/
 /*                       ods_formula_node(const char*)                  */
 /************************************************************************/
 
 ods_formula_node::ods_formula_node( const char *pszValueIn,
-                                    ods_formula_field_type field_type_in )
-
-{
-    Initialize();
-
-    field_type = field_type_in;
-    string_value = CPLStrdup( pszValueIn ? pszValueIn : "" );
-}
+                                    ods_formula_field_type field_type_in ) :
+    eNodeType(SNT_CONSTANT),
+    field_type(field_type_in),
+    eOp(ODS_INVALID),
+    nSubExprCount(0),
+    papoSubExpr(NULL),
+    string_value(CPLStrdup( pszValueIn ? pszValueIn : "" )),
+    int_value(0),
+    float_value(0)
+{}
 
 /************************************************************************/
 /*                        ods_formula_node(ods_formula_op)              */
 /************************************************************************/
 
-ods_formula_node::ods_formula_node( ods_formula_op eOpIn )
-
-{
-    Initialize();
-
-    eNodeType = SNT_OPERATION;
-
-    eOp = eOpIn;
-}
+ods_formula_node::ods_formula_node( ods_formula_op eOpIn ) :
+    eNodeType(SNT_OPERATION),
+    field_type(ODS_FIELD_TYPE_EMPTY),
+    eOp(eOpIn),
+    nSubExprCount(0),
+    papoSubExpr(NULL),
+    string_value(NULL),
+    int_value(0),
+    float_value(0)
+{}
 
 /************************************************************************/
 /*              ods_formula_node(const ods_formula_node&)               */
@@ -115,8 +123,8 @@ ods_formula_node::ods_formula_node( const ods_formula_node& other )
     nSubExprCount = other.nSubExprCount;
     if (nSubExprCount)
     {
-        papoSubExpr = (ods_formula_node **)
-            CPLMalloc( sizeof(void*) * nSubExprCount );
+        papoSubExpr = static_cast<ods_formula_node **>(
+            CPLMalloc( sizeof(void*) * nSubExprCount ) );
         for(int i=0;i<nSubExprCount;i++)
         {
             papoSubExpr[i] = new ods_formula_node( *(other.papoSubExpr[i]) );
@@ -127,22 +135,6 @@ ods_formula_node::ods_formula_node( const ods_formula_node& other )
 }
 
 /************************************************************************/
-/*                             Initialize()                             */
-/************************************************************************/
-
-void ods_formula_node::Initialize()
-
-{
-    eNodeType = SNT_CONSTANT;
-    field_type = ODS_FIELD_TYPE_EMPTY;
-    int_value = 0;
-    float_value = 0;
-    string_value = NULL;
-    papoSubExpr = NULL;
-    nSubExprCount = 0;
-}
-
-/************************************************************************/
 /*                          ~ods_formula_node()                         */
 /************************************************************************/
 
@@ -161,8 +153,8 @@ void ods_formula_node::PushSubExpression( ods_formula_node *child )
 
 {
     nSubExprCount++;
-    papoSubExpr = (ods_formula_node **)
-        CPLRealloc( papoSubExpr, sizeof(void*) * nSubExprCount );
+    papoSubExpr = static_cast<ods_formula_node **>(
+        CPLRealloc( papoSubExpr, sizeof(void*) * nSubExprCount ) );
 
     papoSubExpr[nSubExprCount-1] = child;
 }
@@ -174,12 +166,9 @@ void ods_formula_node::PushSubExpression( ods_formula_node *child )
 void ods_formula_node::ReverseSubExpressions()
 
 {
-    int i;
-    for( i = 0; i < nSubExprCount / 2; i++ )
+    for( int i = 0; i < nSubExprCount / 2; i++ )
     {
-        ods_formula_node *temp;
-
-        temp = papoSubExpr[i];
+        ods_formula_node *temp = papoSubExpr[i];
         papoSubExpr[i] = papoSubExpr[nSubExprCount - i - 1];
         papoSubExpr[nSubExprCount - i - 1] = temp;
     }
@@ -247,12 +236,12 @@ static const char* ODSGetOperatorName( ods_formula_op eOp )
 void ods_formula_node::Dump( FILE * fp, int depth )
 
 {
-    char        spaces[60];
-    int         i;
+    const int max_num_spaces = 60;
+    char spaces[max_num_spaces];
 
-    for( i = 0; i < depth*2 && i < (int) sizeof(spaces) - 1; i++ )
+    for( int i = 0; i < depth*2 && i < max_num_spaces - 1; i++ )
         spaces[i] = ' ';
-    spaces[i] = '\0';
+    spaces[max_num_spaces - 1] = '\0';
 
     if( eNodeType == SNT_CONSTANT )
     {
@@ -269,7 +258,7 @@ void ods_formula_node::Dump( FILE * fp, int depth )
 
     fprintf( fp, "%s%s\n", spaces, ODSGetOperatorName(eOp) );
 
-    for( i = 0; i < nSubExprCount; i++ )
+    for( int i = 0; i < nSubExprCount; i++ )
         papoSubExpr[i]->Dump( fp, depth+1 );
 }
 
@@ -279,8 +268,7 @@ void ods_formula_node::Dump( FILE * fp, int depth )
 
 void  ods_formula_node::FreeSubExpr()
 {
-    int i;
-    for( i = 0; i < nSubExprCount; i++ )
+    for( int i = 0; i < nSubExprCount; i++ )
         delete papoSubExpr[i];
     CPLFree( papoSubExpr );
 
@@ -309,7 +297,7 @@ int ods_formula_node::Evaluate(IODSCellEvaluator* poEvaluator)
         case ODS_PI:
             eNodeType = SNT_CONSTANT;
             field_type = ODS_FIELD_TYPE_FLOAT;
-            float_value = PI;
+            float_value = M_PI;
             return TRUE;
 
         case ODS_LEN : return EvaluateLEN(poEvaluator);
@@ -379,24 +367,26 @@ int ods_formula_node::EvaluateOR(IODSCellEvaluator* poEvaluator)
     CPLAssert(nSubExprCount == 1);
     CPLAssert(papoSubExpr[0]->eNodeType == SNT_OPERATION );
     CPLAssert(papoSubExpr[0]->eOp == ODS_LIST );
-    int bVal = FALSE;
+    bool bVal = false;
     for(int i = 0; i < papoSubExpr[0]->nSubExprCount; i++)
     {
         if (!(papoSubExpr[0]->papoSubExpr[i]->Evaluate(poEvaluator)))
             return FALSE;
         CPLAssert(papoSubExpr[0]->papoSubExpr[i]->eNodeType == SNT_CONSTANT );
-        if (papoSubExpr[0]->papoSubExpr[i]->field_type == ODS_FIELD_TYPE_INTEGER)
+        if( papoSubExpr[0]->papoSubExpr[i]->field_type ==
+            ODS_FIELD_TYPE_INTEGER )
         {
             bVal |= (papoSubExpr[0]->papoSubExpr[i]->int_value != 0);
         }
-        else if (papoSubExpr[0]->papoSubExpr[i]->field_type == ODS_FIELD_TYPE_FLOAT)
+        else if( papoSubExpr[0]->papoSubExpr[i]->field_type ==
+                 ODS_FIELD_TYPE_FLOAT )
         {
             bVal |= (papoSubExpr[0]->papoSubExpr[i]->float_value != 0);
         }
         else
         {
-            CPLError(CE_Failure, CPLE_NotSupported,
-                     "Bad argument type for %s", ODSGetOperatorName(eOp));
+            CPLError( CE_Failure, CPLE_NotSupported,
+                      "Bad argument type for %s", ODSGetOperatorName(eOp));
             return FALSE;
         }
     }
@@ -422,7 +412,7 @@ int ods_formula_node::EvaluateAND(IODSCellEvaluator* poEvaluator)
     CPLAssert(nSubExprCount == 1);
     CPLAssert(papoSubExpr[0]->eNodeType == SNT_OPERATION );
     CPLAssert(papoSubExpr[0]->eOp == ODS_LIST );
-    int bVal = TRUE;
+    bool bVal = true;
     for(int i = 0; i < papoSubExpr[0]->nSubExprCount; i++)
     {
         if (!(papoSubExpr[0]->papoSubExpr[i]->Evaluate(poEvaluator)))
@@ -432,14 +422,15 @@ int ods_formula_node::EvaluateAND(IODSCellEvaluator* poEvaluator)
         {
             bVal &= (papoSubExpr[0]->papoSubExpr[i]->int_value != 0);
         }
-        else if (papoSubExpr[0]->papoSubExpr[i]->field_type == ODS_FIELD_TYPE_FLOAT)
+        else if( papoSubExpr[0]->papoSubExpr[i]->field_type ==
+                 ODS_FIELD_TYPE_FLOAT )
         {
             bVal &= (papoSubExpr[0]->papoSubExpr[i]->float_value != 0);
         }
         else
         {
-            CPLError(CE_Failure, CPLE_NotSupported,
-                     "Bad argument type for %s", ODSGetOperatorName(eOp));
+            CPLError( CE_Failure, CPLE_NotSupported,
+                      "Bad argument type for %s", ODSGetOperatorName(eOp));
             return FALSE;
         }
     }
@@ -467,7 +458,7 @@ int ods_formula_node::EvaluateNOT(IODSCellEvaluator* poEvaluator)
         return FALSE;
     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
 
-    int bVal = FALSE;
+    bool bVal = false;
     if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_INTEGER)
     {
         bVal = !(papoSubExpr[0]->int_value != 0);
@@ -515,7 +506,7 @@ int ods_formula_node::EvaluateIF(IODSCellEvaluator* poEvaluator)
     {
         CPLAssert(papoSubExpr[2]->eNodeType == SNT_CONSTANT );
     }
-    int bCond = FALSE;
+    bool bCond = false;
     if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_INTEGER)
     {
         bCond = (papoSubExpr[0]->int_value != 0);
@@ -589,7 +580,7 @@ int ods_formula_node::EvaluateEQ(IODSCellEvaluator* poEvaluator)
     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
 
-    int bVal = FALSE;
+    bool bVal = false;
     if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_INTEGER)
     {
         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_INTEGER)
@@ -612,9 +603,11 @@ int ods_formula_node::EvaluateEQ(IODSCellEvaluator* poEvaluator)
             bVal = (papoSubExpr[0]->float_value == papoSubExpr[1]->float_value);
         }
     }
-    else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_STRING)
+    else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_STRING &&
+             papoSubExpr[0]->string_value != NULL)
     {
-        if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_STRING)
+        if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_STRING &&
+            papoSubExpr[1]->string_value != NULL)
         {
             bVal = (strcmp(papoSubExpr[0]->string_value,
                            papoSubExpr[1]->string_value) == 0);
@@ -666,7 +659,7 @@ typedef enum
 
 static CaseType GetCase(const char* pszStr)
 {
-    int bInit = TRUE;
+    bool bInit = true;
     char ch;
     CaseType eCase = CASE_UNKNOWN;
     while((ch = *(pszStr++)) != '\0')
@@ -679,6 +672,7 @@ static CaseType GetCase(const char* pszStr)
                 eCase = CASE_UPPER;
             else
                 return CASE_UNKNOWN;
+            bInit = false;
         }
         else if (ch >= 'a' && ch <= 'z' && eCase == CASE_LOWER)
             ;
@@ -708,7 +702,7 @@ int ods_formula_node::EvaluateLE(IODSCellEvaluator* poEvaluator)
     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
 
-    int bVal = FALSE;
+    bool bVal = false;
     if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_INTEGER)
     {
         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_INTEGER)
@@ -720,7 +714,7 @@ int ods_formula_node::EvaluateLE(IODSCellEvaluator* poEvaluator)
             bVal = (papoSubExpr[0]->int_value <= papoSubExpr[1]->float_value);
         }
         else
-            bVal = TRUE;
+            bVal = true;
     }
     else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_FLOAT)
     {
@@ -733,11 +727,13 @@ int ods_formula_node::EvaluateLE(IODSCellEvaluator* poEvaluator)
             bVal = (papoSubExpr[0]->float_value <= papoSubExpr[1]->float_value);
         }
         else
-            bVal = TRUE;
+            bVal = true;
     }
-    else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_STRING)
+    else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_STRING &&
+             papoSubExpr[0]->string_value != NULL)
     {
-        if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_STRING)
+        if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_STRING &&
+            papoSubExpr[1]->string_value != NULL)
         {
             if (GetCase(papoSubExpr[0]->string_value) ==
                 GetCase(papoSubExpr[1]->string_value))
@@ -782,7 +778,7 @@ int ods_formula_node::EvaluateGE(IODSCellEvaluator* poEvaluator)
     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
 
-    int bVal = FALSE;
+    bool bVal = false;
     if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_INTEGER)
     {
         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_INTEGER)
@@ -805,9 +801,11 @@ int ods_formula_node::EvaluateGE(IODSCellEvaluator* poEvaluator)
             bVal = (papoSubExpr[0]->float_value >= papoSubExpr[1]->float_value);
         }
     }
-    else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_STRING)
+    else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_STRING &&
+             papoSubExpr[0]->string_value != NULL)
     {
-        if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_STRING)
+        if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_STRING &&
+            papoSubExpr[1]->string_value != NULL)
         {
             if (GetCase(papoSubExpr[0]->string_value) ==
                 GetCase(papoSubExpr[1]->string_value))
@@ -818,7 +816,7 @@ int ods_formula_node::EvaluateGE(IODSCellEvaluator* poEvaluator)
                                    papoSubExpr[1]->string_value) >= 0);
         }
         else
-            bVal = TRUE;
+            bVal = true;
     }
     else
     {
@@ -854,7 +852,7 @@ int ods_formula_node::EvaluateLT(IODSCellEvaluator* poEvaluator)
     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
 
-    int bVal = FALSE;
+    bool bVal = false;
     if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_INTEGER)
     {
         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_INTEGER)
@@ -866,7 +864,7 @@ int ods_formula_node::EvaluateLT(IODSCellEvaluator* poEvaluator)
             bVal = (papoSubExpr[0]->int_value < papoSubExpr[1]->float_value);
         }
         else
-            bVal = TRUE;
+            bVal = true;
     }
     else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_FLOAT)
     {
@@ -879,11 +877,13 @@ int ods_formula_node::EvaluateLT(IODSCellEvaluator* poEvaluator)
             bVal = (papoSubExpr[0]->float_value < papoSubExpr[1]->float_value);
         }
         else
-            bVal = TRUE;
+            bVal = true;
     }
-    else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_STRING)
+    else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_STRING &&
+             papoSubExpr[0]->string_value != NULL)
     {
-        if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_STRING)
+        if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_STRING &&
+            papoSubExpr[1]->string_value != NULL)
         {
             if (GetCase(papoSubExpr[0]->string_value) ==
                 GetCase(papoSubExpr[1]->string_value))
@@ -928,7 +928,7 @@ int ods_formula_node::EvaluateGT(IODSCellEvaluator* poEvaluator)
     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
 
-    int bVal = FALSE;
+    bool bVal = false;
     if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_INTEGER)
     {
         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_INTEGER)
@@ -951,9 +951,11 @@ int ods_formula_node::EvaluateGT(IODSCellEvaluator* poEvaluator)
             bVal = (papoSubExpr[0]->float_value > papoSubExpr[1]->float_value);
         }
     }
-    else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_STRING)
+    else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_STRING &&
+             papoSubExpr[0]->string_value != NULL)
     {
-        if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_STRING)
+        if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_STRING &&
+            papoSubExpr[1]->string_value != NULL)
         {
             if (GetCase(papoSubExpr[0]->string_value) ==
                 GetCase(papoSubExpr[1]->string_value))
@@ -964,7 +966,7 @@ int ods_formula_node::EvaluateGT(IODSCellEvaluator* poEvaluator)
                                    papoSubExpr[1]->string_value) > 0);
         }
         else
-            bVal = TRUE;
+            bVal = true;
     }
     else
     {
@@ -998,7 +1000,7 @@ int ods_formula_node::EvaluateSingleArgOp(IODSCellEvaluator* poEvaluator)
         return FALSE;
 
     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
-    double dfVal = 0;
+    double dfVal = 0.0;
 
     if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_INTEGER)
     {
@@ -1046,25 +1048,35 @@ int ods_formula_node::EvaluateBinaryArithmetic(IODSCellEvaluator* poEvaluator)
     {
         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_INTEGER)
         {
-            int nVal;
+            int nVal = 0;
+            CPL_IGNORE_RET_VAL(nVal);
             switch (eOp)
             {
-                case ODS_ADD      : nVal = (papoSubExpr[0]->int_value + papoSubExpr[1]->int_value); break;
-                case ODS_SUBTRACT : nVal = (papoSubExpr[0]->int_value - papoSubExpr[1]->int_value); break;
-                case ODS_MULTIPLY : nVal = (papoSubExpr[0]->int_value * papoSubExpr[1]->int_value); break;
+                case ODS_ADD:
+                  nVal = papoSubExpr[0]->int_value + papoSubExpr[1]->int_value;
+                  break;
+                case ODS_SUBTRACT:
+                  nVal = papoSubExpr[0]->int_value - papoSubExpr[1]->int_value;
+                  break;
+                case ODS_MULTIPLY:
+                  nVal = papoSubExpr[0]->int_value * papoSubExpr[1]->int_value;
+                  break;
                 case ODS_DIVIDE   :
-                    if (papoSubExpr[1]->int_value != 0)
-                        nVal = (papoSubExpr[0]->int_value / papoSubExpr[1]->int_value);
+                    if( papoSubExpr[1]->int_value != 0 )
+                        nVal = papoSubExpr[0]->int_value /
+                            papoSubExpr[1]->int_value;
                     else
                         return FALSE;
                     break;
                 case ODS_MODULUS  :
-                    if (papoSubExpr[1]->int_value != 0)
-                        nVal = (papoSubExpr[0]->int_value % papoSubExpr[1]->int_value);
+                    if( papoSubExpr[1]->int_value != 0 )
+                        nVal = papoSubExpr[0]->int_value %
+                            papoSubExpr[1]->int_value;
                     else
                         return FALSE;
                     break;
-                default: nVal = 0; CPLAssert(0);
+                default:
+                    CPLAssert(0);
             }
 
             eNodeType = SNT_CONSTANT;
@@ -1098,7 +1110,8 @@ int ods_formula_node::EvaluateBinaryArithmetic(IODSCellEvaluator* poEvaluator)
 
         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_FLOAT)
         {
-            float dfVal;
+            double dfVal = 0.0;
+            CPL_IGNORE_RET_VAL(dfVal);
             switch (eOp)
             {
                 case ODS_ADD      : dfVal = (papoSubExpr[0]->float_value + papoSubExpr[1]->float_value); break;
@@ -1116,7 +1129,7 @@ int ods_formula_node::EvaluateBinaryArithmetic(IODSCellEvaluator* poEvaluator)
                     else
                         return FALSE;
                     break;
-                default: dfVal = 0.0; CPLAssert(0);
+                default: CPLAssert(0);
             }
 
             eNodeType = SNT_CONSTANT;
@@ -1155,19 +1168,19 @@ std::string ods_formula_node::TransformToString() const
         snprintf(szTmp, sizeof(szTmp), "%d", int_value);
         return szTmp;
     }
-    else if (field_type == ODS_FIELD_TYPE_FLOAT)
+
+    if (field_type == ODS_FIELD_TYPE_FLOAT)
     {
         CPLsnprintf(szTmp, sizeof(szTmp), "%.16g", float_value);
         return szTmp;
     }
-    else if (field_type == ODS_FIELD_TYPE_STRING)
+
+    if (field_type == ODS_FIELD_TYPE_STRING)
     {
         return string_value;
     }
-    else
-    {
-        return "";
-    }
+
+    return "";
 }
 
 /************************************************************************/
@@ -1188,8 +1201,8 @@ int ods_formula_node::EvaluateCONCAT(IODSCellEvaluator* poEvaluator)
     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
 
-    std::string osLeft(papoSubExpr[0]->TransformToString());
-    std::string osRight(papoSubExpr[1]->TransformToString());
+    const std::string osLeft(papoSubExpr[0]->TransformToString());
+    const std::string osRight(papoSubExpr[1]->TransformToString());
 
     eNodeType = SNT_CONSTANT;
     field_type = ODS_FIELD_TYPE_STRING;
@@ -1204,25 +1217,24 @@ int ods_formula_node::EvaluateCONCAT(IODSCellEvaluator* poEvaluator)
 /*                             GetRowCol()                              */
 /************************************************************************/
 
-static int GetRowCol(const char* pszCell, int& nRow, int& nCol)
+static bool GetRowCol(const char* pszCell, int& nRow, int& nCol)
 {
-    int i;
-
-    if (pszCell[0] != '.')
+    if( pszCell[0] != '.' )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Invalid cell %s", pszCell);
-        return FALSE;
+        return false;
     }
 
     nCol = 0;
-    for(i=1; pszCell[i]>='A' && pszCell[i]<='Z';i++)
+    int i = 1;
+    for( ; pszCell[i]>='A' && pszCell[i]<='Z'; i++ )
     {
         nCol = nCol * 26 + (pszCell[i] - 'A');
     }
     nRow = atoi(pszCell + i) - 1;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -1241,7 +1253,8 @@ int ods_formula_node::EvaluateListArgOp(IODSCellEvaluator* poEvaluator)
     std::vector<double> adfVal;
     int i;
 
-    int nCount = 0, nCountA = 0;
+    int nCount = 0;
+    int nCountA = 0;
 
     for(i=0;i<papoSubExpr[0]->nSubExprCount;i++)
     {
@@ -1262,10 +1275,12 @@ int ods_formula_node::EvaluateListArgOp(IODSCellEvaluator* poEvaluator)
 
             const char* psz1 = papoSubExpr[0]->papoSubExpr[i]->papoSubExpr[0]->string_value;
             const char* psz2 = papoSubExpr[0]->papoSubExpr[i]->papoSubExpr[1]->string_value;
-            int nRow1 = 0,nCol1 = 0;
+            int nRow1 = 0;
+            int nCol1 = 0;
             if (!GetRowCol(psz1, nRow1, nCol1))
                 return FALSE;
-            int nRow2 = 0,nCol2 = 0;
+            int nRow2 = 0;
+            int nCol2 = 0;
             if (!GetRowCol(psz2, nRow2, nCol2))
                 return FALSE;
 
@@ -1279,8 +1294,8 @@ int ods_formula_node::EvaluateListArgOp(IODSCellEvaluator* poEvaluator)
                         if (aoOutValues[j].field_type == ODS_FIELD_TYPE_INTEGER)
                         {
                             adfVal.push_back(aoOutValues[j].int_value);
-                            nCount ++;
-                            nCountA ++;
+                            nCount++;
+                            nCountA++;
                         }
                         else if (aoOutValues[j].field_type == ODS_FIELD_TYPE_FLOAT)
                         {
@@ -1349,7 +1364,7 @@ int ods_formula_node::EvaluateListArgOp(IODSCellEvaluator* poEvaluator)
         return TRUE;
     }
 
-    double dfVal = 0;
+    double dfVal = 0.0;
 
     switch(eOp)
     {
@@ -1424,7 +1439,8 @@ int ods_formula_node::EvaluateCELL(IODSCellEvaluator* poEvaluator)
         return FALSE;
     }
 
-    int nRow = 0,nCol = 0;
+    int nRow = 0;
+    int nCol = 0;
     if (!GetRowCol(papoSubExpr[0]->string_value, nRow, nCol))
         return FALSE;
 
@@ -1440,7 +1456,8 @@ int ods_formula_node::EvaluateCELL(IODSCellEvaluator* poEvaluator)
             field_type = aoOutValues[0].field_type;
             int_value = aoOutValues[0].int_value;
             float_value = aoOutValues[0].float_value;
-            string_value = aoOutValues[0].string_value ? CPLStrdup(aoOutValues[0].string_value) : NULL;
+            string_value = aoOutValues[0].string_value ?
+                CPLStrdup(aoOutValues[0].string_value) : NULL;
 
             return TRUE;
         }
@@ -1463,11 +1480,11 @@ int ods_formula_node::EvaluateLEN(IODSCellEvaluator* poEvaluator)
 
     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
 
-    std::string osVal = papoSubExpr[0]->TransformToString();
+    const std::string osVal = papoSubExpr[0]->TransformToString();
 
     eNodeType = SNT_CONSTANT;
     field_type = ODS_FIELD_TYPE_INTEGER;
-    int_value = strlen(osVal.c_str()); // FIXME : UTF8 support
+    int_value = static_cast<int>(strlen(osVal.c_str())); // FIXME : UTF8 support
 
     FreeSubExpr();
 
@@ -1497,7 +1514,7 @@ int ods_formula_node::EvaluateLEFT(IODSCellEvaluator* poEvaluator)
         return FALSE;
 
     // FIXME : UTF8 support
-    int nVal = papoSubExpr[1]->int_value;
+    const int nVal = papoSubExpr[1]->int_value;
     if (nVal < 0)
         return FALSE;
 
@@ -1535,8 +1552,8 @@ int ods_formula_node::EvaluateRIGHT(IODSCellEvaluator* poEvaluator)
         return FALSE;
 
     // FIXME : UTF8 support
-    size_t nLen = osVal.size();
-    int nVal = papoSubExpr[1]->int_value;
+    const size_t nLen = osVal.size();
+    const int nVal = papoSubExpr[1]->int_value;
     if (nVal < 0)
         return FALSE;
 
@@ -1581,9 +1598,9 @@ int ods_formula_node::EvaluateMID(IODSCellEvaluator* poEvaluator)
         return FALSE;
 
     // FIXME : UTF8 support
-    size_t nLen = osVal.size();
-    int nStart = papoSubExpr[1]->int_value;
-    int nExtractLen = papoSubExpr[2]->int_value;
+    const size_t nLen = osVal.size();
+    const int nStart = papoSubExpr[1]->int_value;
+    const int nExtractLen = papoSubExpr[2]->int_value;
     if (nStart <= 0)
         return FALSE;
     if (nExtractLen < 0)
diff --git a/ogr/ogrsf_frmts/ods/ods_formula_parser.cpp b/ogr/ogrsf_frmts/ods/ods_formula_parser.cpp
index 38c2182..1da46ff 100644
--- a/ogr/ogrsf_frmts/ods/ods_formula_parser.cpp
+++ b/ogr/ogrsf_frmts/ods/ods_formula_parser.cpp
@@ -1,22 +1,19 @@
+/* A Bison parser, made by GNU Bison 3.0.  */
 
-/* A Bison parser, made by GNU Bison 2.4.1.  */
+/* Bison implementation for Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
 
-/* Skeleton implementation for Bison's Yacc-like parsers in C
-   
-      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
-   
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
@@ -29,7 +26,7 @@
    special exception, which will cause the skeleton and the resulting
    Bison output files to be licensed under the GNU General Public
    License without this special exception.
-   
+
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
@@ -47,7 +44,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "2.4.1"
+#define YYBISON_VERSION "3.0"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -61,32 +58,26 @@
 /* Pull parsers.  */
 #define YYPULL 1
 
-/* Using locations.  */
-#define YYLSP_NEEDED 0
 
 /* Substitute the variable and function names.  */
 #define yyparse         ods_formulaparse
 #define yylex           ods_formulalex
 #define yyerror         ods_formulaerror
-#define yylval          ods_formulalval
-#define yychar          ods_formulachar
 #define yydebug         ods_formuladebug
 #define yynerrs         ods_formulanerrs
 
 
 /* Copy the first part of user declarations.  */
-
-/* Line 189 of yacc.c  */
-#line 1 "ods_formula_parser.y"
+#line 1 "ods_formula_parser.y" /* yacc.c:339  */
 
 /******************************************************************************
- * $Id: ods_formula_parser.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ods_formula_parser.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Component: OGR ODS Formula Engine
  * Purpose: expression and select parser grammar.
  *          Requires Bison 2.4.0 or newer to process.  Use "make parser" target.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
- * 
+ *
  ******************************************************************************
  * Copyright (C) 2010 Frank Warmerdam <warmerdam at pobox.com>
  * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
@@ -123,21 +114,23 @@
 /* it appears to be a non documented feature of Bison */
 #define YYSTYPE_IS_TRIVIAL 1
 
-static void ods_formulaerror( CPL_UNUSED ods_formula_parse_context *context, const char *msg )
+static void ods_formulaerror( ods_formula_parse_context * /* context */,
+                              const char *msg )
 {
     CPLError( CE_Failure, CPLE_AppDefined,
               "Formula Parsing Error: %s", msg );
 }
 
 
+#line 126 "ods_formula_parser.cpp" /* yacc.c:339  */
 
-/* Line 189 of yacc.c  */
-#line 135 "ods_formula_parser.cpp"
-
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
+# ifndef YY_NULL
+#  if defined __cplusplus && 201103L <= __cplusplus
+#   define YY_NULL nullptr
+#  else
+#   define YY_NULL 0
+#  endif
+# endif
 
 /* Enabling verbose error messages.  */
 #ifdef YYERROR_VERBOSE
@@ -147,50 +140,56 @@ static void ods_formulaerror( CPL_UNUSED ods_formula_parse_context *context, con
 # define YYERROR_VERBOSE 0
 #endif
 
-/* Enabling the token table.  */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
+/* In a future release of Bison, this section will be replaced
+   by #include "ods_formula_parser.hpp".  */
+#ifndef YY_ODS_FORMULA_ODS_FORMULA_PARSER_HPP_INCLUDED
+# define YY_ODS_FORMULA_ODS_FORMULA_PARSER_HPP_INCLUDED
+/* Debug traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int ods_formuladebug;
 #endif
 
-
-/* Tokens.  */
+/* Token type.  */
 #ifndef YYTOKENTYPE
 # define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     ODST_NUMBER = 258,
-     ODST_STRING = 259,
-     ODST_IDENTIFIER = 260,
-     ODST_FUNCTION_NO_ARG = 261,
-     ODST_FUNCTION_SINGLE_ARG = 262,
-     ODST_FUNCTION_TWO_ARG = 263,
-     ODST_FUNCTION_THREE_ARG = 264,
-     ODST_FUNCTION_ARG_LIST = 265,
-     ODST_START = 266,
-     ODST_NOT = 267,
-     ODST_OR = 268,
-     ODST_AND = 269,
-     ODST_IF = 270,
-     ODST_UMINUS = 271
-   };
+  enum yytokentype
+  {
+    ODST_NUMBER = 258,
+    ODST_STRING = 259,
+    ODST_IDENTIFIER = 260,
+    ODST_FUNCTION_NO_ARG = 261,
+    ODST_FUNCTION_SINGLE_ARG = 262,
+    ODST_FUNCTION_TWO_ARG = 263,
+    ODST_FUNCTION_THREE_ARG = 264,
+    ODST_FUNCTION_ARG_LIST = 265,
+    ODST_START = 266,
+    ODST_NOT = 267,
+    ODST_OR = 268,
+    ODST_AND = 269,
+    ODST_IF = 270,
+    ODST_UMINUS = 271
+  };
 #endif
 
-
-
+/* Value type.  */
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef int YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
 #endif
 
 
-/* Copy the second part of user declarations.  */
 
+int ods_formulaparse (ods_formula_parse_context *context);
 
-/* Line 264 of yacc.c  */
-#line 193 "ods_formula_parser.cpp"
+#endif /* !YY_ODS_FORMULA_ODS_FORMULA_PARSER_HPP_INCLUDED  */
+
+/* Copy the second part of user declarations.  */
+
+#line 193 "ods_formula_parser.cpp" /* yacc.c:358  */
 
 #ifdef short
 # undef short
@@ -204,11 +203,8 @@ typedef unsigned char yytype_uint8;
 
 #ifdef YYTYPE_INT8
 typedef YYTYPE_INT8 yytype_int8;
-#elif (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-typedef signed char yytype_int8;
 #else
-typedef short int yytype_int8;
+typedef signed char yytype_int8;
 #endif
 
 #ifdef YYTYPE_UINT16
@@ -228,8 +224,7 @@ typedef short int yytype_int16;
 #  define YYSIZE_T __SIZE_TYPE__
 # elif defined size_t
 #  define YYSIZE_T size_t
-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
+# elif ! defined YYSIZE_T
 #  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
 #  define YYSIZE_T size_t
 # else
@@ -240,42 +235,52 @@ typedef short int yytype_int16;
 #define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
 
 #ifndef YY_
-# if YYENABLE_NLS
+# if defined YYENABLE_NLS && YYENABLE_NLS
 #  if ENABLE_NLS
 #   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-#   define YY_(msgid) dgettext ("bison-runtime", msgid)
+#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
 #  endif
 # endif
 # ifndef YY_
-#  define YY_(msgid) msgid
+#  define YY_(Msgid) Msgid
+# endif
+#endif
+
+#ifndef __attribute__
+/* This feature is available in gcc versions 2.5 and later.  */
+# if (! defined __GNUC__ || __GNUC__ < 2 \
+      || (__GNUC__ == 2 && __GNUC_MINOR__ < 5))
+#  define __attribute__(Spec) /* empty */
 # endif
 #endif
 
 /* Suppress unused-variable warnings by "using" E.  */
 #if ! defined lint || defined __GNUC__
-# define YYUSE(e) ((void) (e))
+# define YYUSE(E) ((void) (E))
 #else
-# define YYUSE(e) /* empty */
+# define YYUSE(E) /* empty */
 #endif
 
-/* Identity function, used to suppress warnings about constant conditions.  */
-#ifndef lint
-# define YYID(n) (n)
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized.  */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+    _Pragma ("GCC diagnostic push") \
+    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+    _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+    _Pragma ("GCC diagnostic pop")
 #else
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int yyi)
-#else
-static int
-YYID (yyi)
-    int yyi;
+# define YY_INITIAL_VALUE(Value) Value
 #endif
-{
-  return yyi;
-}
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
+#endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
 #endif
 
+
 #if ! defined yyoverflow || YYERROR_VERBOSE
 
 /* The parser invokes alloca or malloc; define the necessary symbols.  */
@@ -293,11 +298,11 @@ YYID (yyi)
 #    define alloca _alloca
 #   else
 #    define YYSTACK_ALLOC alloca
-#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
+#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
 #     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#     ifndef _STDLIB_H
-#      define _STDLIB_H 1
+      /* Use EXIT_SUCCESS as a witness for stdlib.h.  */
+#     ifndef EXIT_SUCCESS
+#      define EXIT_SUCCESS 0
 #     endif
 #    endif
 #   endif
@@ -305,8 +310,8 @@ YYID (yyi)
 # endif
 
 # ifdef YYSTACK_ALLOC
-   /* Pacify GCC's `empty if-body' warning.  */
-#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+   /* Pacify GCC's 'empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
 #  ifndef YYSTACK_ALLOC_MAXIMUM
     /* The OS might guarantee only one guard page at the bottom of the stack,
        and a page size can be as small as 4096 bytes.  So we cannot safely
@@ -320,25 +325,23 @@ YYID (yyi)
 #  ifndef YYSTACK_ALLOC_MAXIMUM
 #   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
 #  endif
-#  if (defined __cplusplus && ! defined _STDLIB_H \
+#  if (defined __cplusplus && ! defined EXIT_SUCCESS \
        && ! ((defined YYMALLOC || defined malloc) \
-	     && (defined YYFREE || defined free)))
+             && (defined YYFREE || defined free)))
 #   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#   ifndef _STDLIB_H
-#    define _STDLIB_H 1
+#   ifndef EXIT_SUCCESS
+#    define EXIT_SUCCESS 0
 #   endif
 #  endif
 #  ifndef YYMALLOC
 #   define YYMALLOC malloc
-#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
+#   if ! defined malloc && ! defined EXIT_SUCCESS
 void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
 #   endif
 #  endif
 #  ifndef YYFREE
 #   define YYFREE free
-#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
+#   if ! defined free && ! defined EXIT_SUCCESS
 void free (void *); /* INFRINGES ON USER NAME SPACE */
 #   endif
 #  endif
@@ -348,7 +351,7 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
 
 #if (! defined yyoverflow \
      && (! defined __cplusplus \
-	 || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+         || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
 
 /* A type that is properly aligned for any stack member.  */
 union yyalloc
@@ -366,42 +369,46 @@ union yyalloc
      ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
       + YYSTACK_GAP_MAXIMUM)
 
-/* Copy COUNT objects from FROM to TO.  The source and destination do
-   not overlap.  */
-# ifndef YYCOPY
-#  if defined __GNUC__ && 1 < __GNUC__
-#   define YYCOPY(To, From, Count) \
-      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
-#  else
-#   define YYCOPY(To, From, Count)		\
-      do					\
-	{					\
-	  YYSIZE_T yyi;				\
-	  for (yyi = 0; yyi < (Count); yyi++)	\
-	    (To)[yyi] = (From)[yyi];		\
-	}					\
-      while (YYID (0))
-#  endif
-# endif
+# define YYCOPY_NEEDED 1
 
 /* Relocate STACK from its old location to the new one.  The
    local variables YYSIZE and YYSTACKSIZE give the old and new number of
    elements in the stack, and YYPTR gives the new location of the
    stack.  Advance YYPTR to a properly aligned location for the next
    stack.  */
-# define YYSTACK_RELOCATE(Stack_alloc, Stack)				\
-    do									\
-      {									\
-	YYSIZE_T yynewbytes;						\
-	YYCOPY (&yyptr->Stack_alloc, Stack, yysize);			\
-	Stack = &yyptr->Stack_alloc;					\
-	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
-	yyptr += yynewbytes / sizeof (*yyptr);				\
-      }									\
-    while (YYID (0))
+# define YYSTACK_RELOCATE(Stack_alloc, Stack)                           \
+    do                                                                  \
+      {                                                                 \
+        YYSIZE_T yynewbytes;                                            \
+        YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
+        Stack = &yyptr->Stack_alloc;                                    \
+        yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+        yyptr += yynewbytes / sizeof (*yyptr);                          \
+      }                                                                 \
+    while (0)
 
 #endif
 
+#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
+/* Copy COUNT objects from SRC to DST.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(Dst, Src, Count) \
+      __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+#  else
+#   define YYCOPY(Dst, Src, Count)              \
+      do                                        \
+        {                                       \
+          YYSIZE_T yyi;                         \
+          for (yyi = 0; yyi < (Count); yyi++)   \
+            (Dst)[yyi] = (Src)[yyi];            \
+        }                                       \
+      while (0)
+#  endif
+# endif
+#endif /* !YYCOPY_NEEDED */
+
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  18
 /* YYLAST -- Last index in YYTABLE.  */
@@ -413,17 +420,19 @@ union yyalloc
 #define YYNNTS  7
 /* YYNRULES -- Number of rules.  */
 #define YYNRULES  41
-/* YYNRULES -- Number of states.  */
+/* YYNSTATES -- Number of states.  */
 #define YYNSTATES  108
 
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
+/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
+   by yylex, with out-of-bounds checking.  */
 #define YYUNDEFTOK  2
 #define YYMAXUTOK   271
 
-#define YYTRANSLATE(YYX)						\
+#define YYTRANSLATE(YYX)                                                \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
 
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+   as returned by yylex, without out-of-bounds checking.  */
 static const yytype_uint8 yytranslate[] =
 {
        0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -457,52 +466,18 @@ static const yytype_uint8 yytranslate[] =
 };
 
 #if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
-   YYRHS.  */
-static const yytype_uint8 yyprhs[] =
-{
-       0,     0,     3,     6,     8,    10,    12,    14,    18,    23,
-      30,    39,    44,    49,    54,    61,    70,    75,    79,    83,
-      88,    93,    97,   101,   106,   111,   116,   121,   124,   128,
-     132,   136,   140,   144,   148,   152,   156,   158,   162,   164,
-     168,   170
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
-static const yytype_int8 yyrhs[] =
-{
-      35,     0,    -1,    11,    37,    -1,    23,    -1,    24,    -1,
-       3,    -1,     4,    -1,     6,    25,    26,    -1,     7,    25,
-      37,    26,    -1,     8,    25,    37,    36,    37,    26,    -1,
-       9,    25,    37,    36,    37,    36,    37,    26,    -1,    14,
-      25,    38,    26,    -1,    13,    25,    38,    26,    -1,    12,
-      25,    37,    26,    -1,    15,    25,    37,    36,    37,    26,
-      -1,    15,    25,    37,    36,    37,    36,    37,    26,    -1,
-      10,    25,    39,    26,    -1,    25,    37,    26,    -1,    37,
-      27,    37,    -1,    37,    28,    29,    37,    -1,    37,    30,
-      27,    37,    -1,    37,    28,    37,    -1,    37,    29,    37,
-      -1,    37,    28,    27,    37,    -1,    37,    27,    28,    37,
-      -1,    37,    27,    29,    37,    -1,    37,    29,    27,    37,
-      -1,    17,    37,    -1,    37,    16,    37,    -1,    37,    17,
-      37,    -1,    37,    18,    37,    -1,    37,    19,    37,    -1,
-      37,    20,    37,    -1,    37,    21,    37,    -1,    31,     5,
-      32,    -1,    37,    36,    38,    -1,    37,    -1,    37,    36,
-      39,    -1,    37,    -1,    40,    36,    39,    -1,    40,    -1,
-      31,     5,    33,     5,    32,    -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
+  /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,    88,    88,    93,    93,    97,   102,   107,   112,   118,
-     125,   133,   140,   147,   153,   160,   168,   175,   180,   187,
-     194,   201,   208,   215,   222,   229,   236,   243,   259,   266,
-     273,   280,   287,   294,   301,   308,   314,   321,   327,   332,
-     338,   345
+       0,    89,    89,    94,    94,    98,   103,   108,   113,   119,
+     126,   134,   141,   148,   154,   161,   169,   176,   181,   188,
+     195,   202,   209,   216,   223,   230,   237,   244,   260,   267,
+     274,   281,   288,   295,   302,   309,   315,   322,   328,   333,
+     339,   346
 };
 #endif
 
-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+#if YYDEBUG || YYERROR_VERBOSE || 0
 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
    First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
 static const char *const yytname[] =
@@ -514,13 +489,13 @@ static const char *const yytname[] =
   "ODST_AND", "ODST_IF", "'+'", "'-'", "'&'", "'*'", "'/'", "'%'",
   "ODST_UMINUS", "','", "';'", "'('", "')'", "'='", "'<'", "'>'", "'!'",
   "'['", "']'", "':'", "$accept", "input", "comma", "value_expr",
-  "value_expr_list", "value_expr_and_cell_range_list", "cell_range", 0
+  "value_expr_list", "value_expr_and_cell_range_list", "cell_range", YY_NULL
 };
 #endif
 
 # ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
-   token YYLEX-NUM.  */
+/* YYTOKNUM[NUM] -- (External) token number corresponding to the
+   (internal) symbol number NUM (which must be that of a token).  */
 static const yytype_uint16 yytoknum[] =
 {
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
@@ -530,29 +505,36 @@ static const yytype_uint16 yytoknum[] =
 };
 # endif
 
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
-static const yytype_uint8 yyr1[] =
-{
-       0,    34,    35,    36,    36,    37,    37,    37,    37,    37,
-      37,    37,    37,    37,    37,    37,    37,    37,    37,    37,
-      37,    37,    37,    37,    37,    37,    37,    37,    37,    37,
-      37,    37,    37,    37,    37,    38,    38,    39,    39,    39,
-      39,    40
-};
+#define YYPACT_NINF -75
 
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
-static const yytype_uint8 yyr2[] =
+#define yypact_value_is_default(Yystate) \
+  (!!((Yystate) == (-75)))
+
+#define YYTABLE_NINF -1
+
+#define yytable_value_is_error(Yytable_value) \
+  0
+
+  /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+     STATE-NUM.  */
+static const yytype_int16 yypact[] =
 {
-       0,     2,     2,     1,     1,     1,     1,     3,     4,     6,
-       8,     4,     4,     4,     6,     8,     4,     3,     3,     4,
-       4,     3,     3,     4,     4,     4,     4,     2,     3,     3,
-       3,     3,     3,     3,     3,     3,     1,     3,     1,     3,
-       1,     5
+      -4,   162,    12,   -75,   -75,    -3,     4,    14,    21,    32,
+      33,    34,    35,    38,   162,   162,    44,   303,   -75,    40,
+     162,   162,   162,   182,   162,   162,   162,   162,   -12,   213,
+      36,   162,   162,   162,   162,   162,   162,    78,   107,   136,
+      43,   -75,   228,    24,    24,    66,    24,    46,   -14,   243,
+      24,    49,    50,    24,   -75,   -75,   181,   181,   181,   -12,
+     -12,   -12,   162,   162,   303,   162,   162,   303,   162,   303,
+     162,   -75,   -75,   -75,   162,   162,    -5,   182,   -75,   182,
+     -75,   162,   -75,   -75,   162,   303,   303,   303,   303,   303,
+     303,   258,    24,    72,   -75,   -75,   -75,   198,   -75,   162,
+      47,   -75,   162,   273,   -75,   288,   -75,   -75
 };
 
-/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
-   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
-   means the default is an error.  */
+  /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+     Performed when YYTABLE does not specify something else to do.  Zero
+     means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
        0,     0,     0,     5,     6,     0,     0,     0,     0,     0,
@@ -568,41 +550,21 @@ static const yytype_uint8 yydefact[] =
        0,    14,     0,     0,    41,     0,    10,    15
 };
 
-/* YYDEFGOTO[NTERM-NUM].  */
-static const yytype_int8 yydefgoto[] =
-{
-      -1,     2,    74,    46,    51,    47,    48
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
-   STATE-NUM.  */
-#define YYPACT_NINF -75
-static const yytype_int16 yypact[] =
+  /* YYPGOTO[NTERM-NUM].  */
+static const yytype_int8 yypgoto[] =
 {
-      -4,   162,    12,   -75,   -75,    -3,     4,    14,    21,    32,
-      33,    34,    35,    38,   162,   162,    44,   303,   -75,    40,
-     162,   162,   162,   182,   162,   162,   162,   162,   -12,   213,
-      36,   162,   162,   162,   162,   162,   162,    78,   107,   136,
-      43,   -75,   228,    24,    24,    66,    24,    46,   -14,   243,
-      24,    49,    50,    24,   -75,   -75,   181,   181,   181,   -12,
-     -12,   -12,   162,   162,   303,   162,   162,   303,   162,   303,
-     162,   -75,   -75,   -75,   162,   162,    -5,   182,   -75,   182,
-     -75,   162,   -75,   -75,   162,   303,   303,   303,   303,   303,
-     303,   258,    24,    72,   -75,   -75,   -75,   198,   -75,   162,
-      47,   -75,   162,   273,   -75,   288,   -75,   -75
+     -75,   -75,   -42,    -1,   -25,   -74,   -75
 };
 
-/* YYPGOTO[NTERM-NUM].  */
-static const yytype_int8 yypgoto[] =
+  /* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int8 yydefgoto[] =
 {
-     -75,   -75,   -42,    -1,   -25,   -74,   -75
+      -1,     2,    74,    46,    51,    47,    48
 };
 
-/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
-   positive, shift that token.  If negative, reduce the rule which
-   number is the opposite.  If zero, do what YYDEFACT says.
-   If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -1
+  /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
+     positive, shift that token.  If negative, reduce the rule whose
+     number is the opposite.  If YYTABLE_NINF, syntax error.  */
 static const yytype_uint8 yytable[] =
 {
       17,    52,    75,    94,    77,    95,    79,     1,    81,    72,
@@ -679,8 +641,8 @@ static const yytype_int8 yycheck[] =
       27,    28,    29,    30
 };
 
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
-   symbol of state STATE-NUM.  */
+  /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+     symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
        0,    11,    35,     3,     4,     6,     7,     8,     9,    10,
@@ -696,95 +658,61 @@ static const yytype_uint8 yystos[] =
        5,    26,    36,    37,    32,    37,    26,    26
 };
 
-#define yyerrok		(yyerrstatus = 0)
-#define yyclearin	(yychar = YYEMPTY)
-#define YYEMPTY		(-2)
-#define YYEOF		0
+  /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint8 yyr1[] =
+{
+       0,    34,    35,    36,    36,    37,    37,    37,    37,    37,
+      37,    37,    37,    37,    37,    37,    37,    37,    37,    37,
+      37,    37,    37,    37,    37,    37,    37,    37,    37,    37,
+      37,    37,    37,    37,    37,    38,    38,    39,    39,    39,
+      39,    40
+};
+
+  /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     2,     1,     1,     1,     1,     3,     4,     6,
+       8,     4,     4,     4,     6,     8,     4,     3,     3,     4,
+       4,     3,     3,     4,     4,     4,     4,     2,     3,     3,
+       3,     3,     3,     3,     3,     3,     1,     3,     1,     3,
+       1,     5
+};
 
-#define YYACCEPT	goto yyacceptlab
-#define YYABORT		goto yyabortlab
-#define YYERROR		goto yyerrorlab
 
+#define yyerrok         (yyerrstatus = 0)
+#define yyclearin       (yychar = YYEMPTY)
+#define YYEMPTY         (-2)
+#define YYEOF           0
 
-/* Like YYERROR except do call yyerror.  This remains here temporarily
-   to ease the transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  */
+#define YYACCEPT        goto yyacceptlab
+#define YYABORT         goto yyabortlab
+#define YYERROR         goto yyerrorlab
 
-#define YYFAIL		goto yyerrlab
 
 #define YYRECOVERING()  (!!yyerrstatus)
 
-#define YYBACKUP(Token, Value)					\
-do								\
-  if (yychar == YYEMPTY && yylen == 1)				\
-    {								\
-      yychar = (Token);						\
-      yylval = (Value);						\
-      yytoken = YYTRANSLATE (yychar);				\
-      YYPOPSTACK (1);						\
-      goto yybackup;						\
-    }								\
-  else								\
-    {								\
+#define YYBACKUP(Token, Value)                                  \
+do                                                              \
+  if (yychar == YYEMPTY)                                        \
+    {                                                           \
+      yychar = (Token);                                         \
+      yylval = (Value);                                         \
+      YYPOPSTACK (yylen);                                       \
+      yystate = *yyssp;                                         \
+      goto yybackup;                                            \
+    }                                                           \
+  else                                                          \
+    {                                                           \
       yyerror (context, YY_("syntax error: cannot back up")); \
-      YYERROR;							\
-    }								\
-while (YYID (0))
-
-
-#define YYTERROR	1
-#define YYERRCODE	256
-
-
-/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
-   If N is 0, then set CURRENT to the empty location which ends
-   the previous symbol: RHS[0] (always defined).  */
-
-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N)				\
-    do									\
-      if (YYID (N))                                                    \
-	{								\
-	  (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;	\
-	  (Current).first_column = YYRHSLOC (Rhs, 1).first_column;	\
-	  (Current).last_line    = YYRHSLOC (Rhs, N).last_line;		\
-	  (Current).last_column  = YYRHSLOC (Rhs, N).last_column;	\
-	}								\
-      else								\
-	{								\
-	  (Current).first_line   = (Current).last_line   =		\
-	    YYRHSLOC (Rhs, 0).last_line;				\
-	  (Current).first_column = (Current).last_column =		\
-	    YYRHSLOC (Rhs, 0).last_column;				\
-	}								\
-    while (YYID (0))
-#endif
+      YYERROR;                                                  \
+    }                                                           \
+while (0)
 
+/* Error token number */
+#define YYTERROR        1
+#define YYERRCODE       256
 
-/* YY_LOCATION_PRINT -- Print the location on the stream.
-   This macro was not mandated originally: define only if we know
-   we won't break user code: when these are the locations we know.  */
 
-#ifndef YY_LOCATION_PRINT
-# if YYLTYPE_IS_TRIVIAL
-#  define YY_LOCATION_PRINT(File, Loc)			\
-     fprintf (File, "%d.%d-%d.%d",			\
-	      (Loc).first_line, (Loc).first_column,	\
-	      (Loc).last_line,  (Loc).last_column)
-# else
-#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-# endif
-#endif
-
-
-/* YYLEX -- calling `yylex' with the right arguments.  */
-
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (&yylval, YYLEX_PARAM)
-#else
-# define YYLEX yylex (&yylval, context)
-#endif
 
 /* Enable debugging if requested.  */
 #if YYDEBUG
@@ -794,56 +722,47 @@ while (YYID (0))
 #  define YYFPRINTF fprintf
 # endif
 
-# define YYDPRINTF(Args)			\
-do {						\
-  if (yydebug)					\
-    YYFPRINTF Args;				\
-} while (YYID (0))
+# define YYDPRINTF(Args)                        \
+do {                                            \
+  if (yydebug)                                  \
+    YYFPRINTF Args;                             \
+} while (0)
 
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)			  \
-do {									  \
-  if (yydebug)								  \
-    {									  \
-      YYFPRINTF (stderr, "%s ", Title);					  \
-      yy_symbol_print (stderr,						  \
-		  Type, Value, context); \
-      YYFPRINTF (stderr, "\n");						  \
-    }									  \
-} while (YYID (0))
+/* This macro is provided for backward compatibility. */
+#ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+#endif
 
 
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                    \
+do {                                                                      \
+  if (yydebug)                                                            \
+    {                                                                     \
+      YYFPRINTF (stderr, "%s ", Title);                                   \
+      yy_symbol_print (stderr,                                            \
+                  Type, Value, context); \
+      YYFPRINTF (stderr, "\n");                                           \
+    }                                                                     \
+} while (0)
+
+
+/*----------------------------------------.
+| Print this symbol's value on YYOUTPUT.  |
+`----------------------------------------*/
 
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static void
 yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, ods_formula_parse_context *context)
-#else
-static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep, context)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-    ods_formula_parse_context *context;
-#endif
 {
+  FILE *yyo = yyoutput;
+  YYUSE (yyo);
+  YYUSE (context);
   if (!yyvaluep)
     return;
-  YYUSE (context);
 # ifdef YYPRINT
   if (yytype < YYNTOKENS)
     YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
-  YYUSE (yyoutput);
 # endif
-  switch (yytype)
-    {
-      default:
-	break;
-    }
+  YYUSE (yytype);
 }
 
 
@@ -851,23 +770,11 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, context)
 | Print this symbol on YYOUTPUT.  |
 `--------------------------------*/
 
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static void
 yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, ods_formula_parse_context *context)
-#else
-static void
-yy_symbol_print (yyoutput, yytype, yyvaluep, context)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-    ods_formula_parse_context *context;
-#endif
 {
-  if (yytype < YYNTOKENS)
-    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-  else
-    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+  YYFPRINTF (yyoutput, "%s %s (",
+             yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
 
   yy_symbol_value_print (yyoutput, yytype, yyvaluep, context);
   YYFPRINTF (yyoutput, ")");
@@ -878,16 +785,8 @@ yy_symbol_print (yyoutput, yytype, yyvaluep, context)
 | TOP (included).                                                   |
 `------------------------------------------------------------------*/
 
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static void
 yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
-#else
-static void
-yy_stack_print (yybottom, yytop)
-    yytype_int16 *yybottom;
-    yytype_int16 *yytop;
-#endif
 {
   YYFPRINTF (stderr, "Stack now");
   for (; yybottom <= yytop; yybottom++)
@@ -898,50 +797,42 @@ yy_stack_print (yybottom, yytop)
   YYFPRINTF (stderr, "\n");
 }
 
-# define YY_STACK_PRINT(Bottom, Top)				\
-do {								\
-  if (yydebug)							\
-    yy_stack_print ((Bottom), (Top));				\
-} while (YYID (0))
+# define YY_STACK_PRINT(Bottom, Top)                            \
+do {                                                            \
+  if (yydebug)                                                  \
+    yy_stack_print ((Bottom), (Top));                           \
+} while (0)
 
 
 /*------------------------------------------------.
 | Report that the YYRULE is going to be reduced.  |
 `------------------------------------------------*/
 
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_reduce_print (YYSTYPE *yyvsp, int yyrule, ods_formula_parse_context *context)
-#else
 static void
-yy_reduce_print (yyvsp, yyrule, context)
-    YYSTYPE *yyvsp;
-    int yyrule;
-    ods_formula_parse_context *context;
-#endif
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, ods_formula_parse_context *context)
 {
+  unsigned long int yylno = yyrline[yyrule];
   int yynrhs = yyr2[yyrule];
   int yyi;
-  unsigned long int yylno = yyrline[yyrule];
   YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
-	     yyrule - 1, yylno);
+             yyrule - 1, yylno);
   /* The symbols being reduced.  */
   for (yyi = 0; yyi < yynrhs; yyi++)
     {
       YYFPRINTF (stderr, "   $%d = ", yyi + 1);
-      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
-		       &(yyvsp[(yyi + 1) - (yynrhs)])
-		       		       , context);
+      yy_symbol_print (stderr,
+                       yystos[yyssp[yyi + 1 - yynrhs]],
+                       &(yyvsp[(yyi + 1) - (yynrhs)])
+                                              , context);
       YYFPRINTF (stderr, "\n");
     }
 }
 
-# define YY_REDUCE_PRINT(Rule)		\
-do {					\
-  if (yydebug)				\
-    yy_reduce_print (yyvsp, Rule, context); \
-} while (YYID (0))
+# define YY_REDUCE_PRINT(Rule)          \
+do {                                    \
+  if (yydebug)                          \
+    yy_reduce_print (yyssp, yyvsp, Rule, context); \
+} while (0)
 
 /* Nonzero means print parse trace.  It is left uninitialized so that
    multiple parsers can coexist.  */
@@ -955,7 +846,7 @@ int yydebug;
 
 
 /* YYINITDEPTH -- initial size of the parser's stacks.  */
-#ifndef	YYINITDEPTH
+#ifndef YYINITDEPTH
 # define YYINITDEPTH 200
 #endif
 
@@ -970,7 +861,6 @@ int yydebug;
 # define YYMAXDEPTH 10000
 #endif
 
-

 
 #if YYERROR_VERBOSE
 
@@ -979,15 +869,8 @@ int yydebug;
 #   define yystrlen strlen
 #  else
 /* Return the length of YYSTR.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static YYSIZE_T
 yystrlen (const char *yystr)
-#else
-static YYSIZE_T
-yystrlen (yystr)
-    const char *yystr;
-#endif
 {
   YYSIZE_T yylen;
   for (yylen = 0; yystr[yylen]; yylen++)
@@ -1003,16 +886,8 @@ yystrlen (yystr)
 #  else
 /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
    YYDEST.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static char *
 yystpcpy (char *yydest, const char *yysrc)
-#else
-static char *
-yystpcpy (yydest, yysrc)
-    char *yydest;
-    const char *yysrc;
-#endif
 {
   char *yyd = yydest;
   const char *yys = yysrc;
@@ -1042,27 +917,27 @@ yytnamerr (char *yyres, const char *yystr)
       char const *yyp = yystr;
 
       for (;;)
-	switch (*++yyp)
-	  {
-	  case '\'':
-	  case ',':
-	    goto do_not_strip_quotes;
-
-	  case '\\':
-	    if (*++yyp != '\\')
-	      goto do_not_strip_quotes;
-	    /* Fall through.  */
-	  default:
-	    if (yyres)
-	      yyres[yyn] = *yyp;
-	    yyn++;
-	    break;
-
-	  case '"':
-	    if (yyres)
-	      yyres[yyn] = '\0';
-	    return yyn;
-	  }
+        switch (*++yyp)
+          {
+          case '\'':
+          case ',':
+            goto do_not_strip_quotes;
+
+          case '\\':
+            if (*++yyp != '\\')
+              goto do_not_strip_quotes;
+            /* Fall through.  */
+          default:
+            if (yyres)
+              yyres[yyn] = *yyp;
+            yyn++;
+            break;
+
+          case '"':
+            if (yyres)
+              yyres[yyn] = '\0';
+            return yyn;
+          }
     do_not_strip_quotes: ;
     }
 
@@ -1073,307 +948,256 @@ yytnamerr (char *yyres, const char *yystr)
 }
 # endif
 
-/* Copy into YYRESULT an error message about the unexpected token
-   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
-   including the terminating null byte.  If YYRESULT is null, do not
-   copy anything; just return the number of bytes that would be
-   copied.  As a special case, return 0 if an ordinary "syntax error"
-   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
-   size calculation.  */
-static YYSIZE_T
-yysyntax_error (char *yyresult, int yystate, int yychar)
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+   about the unexpected token YYTOKEN for the state stack whose top is
+   YYSSP.
+
+   Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
+   not large enough to hold the message.  In that case, also set
+   *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
+   required number of bytes is too large to store.  */
+static int
+yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
+                yytype_int16 *yyssp, int yytoken)
 {
-  int yyn = yypact[yystate];
+  YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]);
+  YYSIZE_T yysize = yysize0;
+  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+  /* Internationalized format string. */
+  const char *yyformat = YY_NULL;
+  /* Arguments of yyformat. */
+  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+  /* Number of reported tokens (one for the "unexpected", one per
+     "expected"). */
+  int yycount = 0;
+
+  /* There are many possibilities here to consider:
+     - If this state is a consistent state with a default action, then
+       the only way this function was invoked is if the default action
+       is an error action.  In that case, don't check for expected
+       tokens because there are none.
+     - The only way there can be no lookahead present (in yychar) is if
+       this state is a consistent state with a default action.  Thus,
+       detecting the absence of a lookahead is sufficient to determine
+       that there is no unexpected or expected token to report.  In that
+       case, just report a simple "syntax error".
+     - Don't assume there isn't a lookahead just because this state is a
+       consistent state with a default action.  There might have been a
+       previous inconsistent state, consistent state with a non-default
+       action, or user semantic action that manipulated yychar.
+     - Of course, the expected token list depends on states to have
+       correct lookahead information, and it depends on the parser not
+       to perform extra reductions after fetching a lookahead from the
+       scanner and before detecting a syntax error.  Thus, state merging
+       (from LALR or IELR) and default reductions corrupt the expected
+       token list.  However, the list is correct for canonical LR with
+       one exception: it will still contain any token that will not be
+       accepted due to an error action in a later state.
+  */
+  if (yytoken != YYEMPTY)
+    {
+      int yyn = yypact[*yyssp];
+      yyarg[yycount++] = yytname[yytoken];
+      if (!yypact_value_is_default (yyn))
+        {
+          /* Start YYX at -YYN if negative to avoid negative indexes in
+             YYCHECK.  In other words, skip the first -YYN actions for
+             this state because they are default actions.  */
+          int yyxbegin = yyn < 0 ? -yyn : 0;
+          /* Stay within bounds of both yycheck and yytname.  */
+          int yychecklim = YYLAST - yyn + 1;
+          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+          int yyx;
+
+          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
+                && !yytable_value_is_error (yytable[yyx + yyn]))
+              {
+                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+                  {
+                    yycount = 1;
+                    yysize = yysize0;
+                    break;
+                  }
+                yyarg[yycount++] = yytname[yyx];
+                {
+                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]);
+                  if (! (yysize <= yysize1
+                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+                    return 2;
+                  yysize = yysize1;
+                }
+              }
+        }
+    }
 
-  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
-    return 0;
-  else
+  switch (yycount)
     {
-      int yytype = YYTRANSLATE (yychar);
-      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
-      YYSIZE_T yysize = yysize0;
-      YYSIZE_T yysize1;
-      int yysize_overflow = 0;
-      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
-      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
-      int yyx;
-
-# if 0
-      /* This is so xgettext sees the translatable formats that are
-	 constructed on the fly.  */
-      YY_("syntax error, unexpected %s");
-      YY_("syntax error, unexpected %s, expecting %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
-# endif
-      char *yyfmt;
-      char const *yyf;
-      static char const yyunexpected[] = "syntax error, unexpected %s";
-      static char const yyexpecting[] = ", expecting %s";
-      static char const yyor[] = " or %s";
-      char yyformat[sizeof yyunexpected
-		    + sizeof yyexpecting - 1
-		    + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
-		       * (sizeof yyor - 1))];
-      char const *yyprefix = yyexpecting;
-
-      /* Start YYX at -YYN if negative to avoid negative indexes in
-	 YYCHECK.  */
-      int yyxbegin = yyn < 0 ? -yyn : 0;
-
-      /* Stay within bounds of both yycheck and yytname.  */
-      int yychecklim = YYLAST - yyn + 1;
-      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
-      int yycount = 1;
-
-      yyarg[0] = yytname[yytype];
-      yyfmt = yystpcpy (yyformat, yyunexpected);
-
-      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-	if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
-	  {
-	    if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
-	      {
-		yycount = 1;
-		yysize = yysize0;
-		yyformat[sizeof yyunexpected - 1] = '\0';
-		break;
-	      }
-	    yyarg[yycount++] = yytname[yyx];
-	    yysize1 = yysize + yytnamerr (0, yytname[yyx]);
-	    yysize_overflow |= (yysize1 < yysize);
-	    yysize = yysize1;
-	    yyfmt = yystpcpy (yyfmt, yyprefix);
-	    yyprefix = yyor;
-	  }
-
-      yyf = YY_(yyformat);
-      yysize1 = yysize + yystrlen (yyf);
-      yysize_overflow |= (yysize1 < yysize);
-      yysize = yysize1;
-
-      if (yysize_overflow)
-	return YYSIZE_MAXIMUM;
-
-      if (yyresult)
-	{
-	  /* Avoid sprintf, as that infringes on the user's name space.
-	     Don't have undefined behavior even if the translation
-	     produced a string with the wrong number of "%s"s.  */
-	  char *yyp = yyresult;
-	  int yyi = 0;
-	  while ((*yyp = *yyf) != '\0')
-	    {
-	      if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
-		{
-		  yyp += yytnamerr (yyp, yyarg[yyi++]);
-		  yyf += 2;
-		}
-	      else
-		{
-		  yyp++;
-		  yyf++;
-		}
-	    }
-	}
-      return yysize;
+# define YYCASE_(N, S)                      \
+      case N:                               \
+        yyformat = S;                       \
+      break
+      YYCASE_(0, YY_("syntax error"));
+      YYCASE_(1, YY_("syntax error, unexpected %s"));
+      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
+      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
+      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
+      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
+# undef YYCASE_
+    }
+
+  {
+    YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+      return 2;
+    yysize = yysize1;
+  }
+
+  if (*yymsg_alloc < yysize)
+    {
+      *yymsg_alloc = 2 * yysize;
+      if (! (yysize <= *yymsg_alloc
+             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
+        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
+      return 1;
     }
+
+  /* Avoid sprintf, as that infringes on the user's name space.
+     Don't have undefined behavior even if the translation
+     produced a string with the wrong number of "%s"s.  */
+  {
+    char *yyp = *yymsg;
+    int yyi = 0;
+    while ((*yyp = *yyformat) != '\0')
+      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
+        {
+          yyp += yytnamerr (yyp, yyarg[yyi++]);
+          yyformat += 2;
+        }
+      else
+        {
+          yyp++;
+          yyformat++;
+        }
+  }
+  return 0;
 }
 #endif /* YYERROR_VERBOSE */
-

 
 /*-----------------------------------------------.
 | Release the memory associated to this symbol.  |
 `-----------------------------------------------*/
 
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static void
 yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, ods_formula_parse_context *context)
-#else
-static void
-yydestruct (yymsg, yytype, yyvaluep, context)
-    const char *yymsg;
-    int yytype;
-    YYSTYPE *yyvaluep;
-    ods_formula_parse_context *context;
-#endif
 {
   YYUSE (yyvaluep);
   YYUSE (context);
-
   if (!yymsg)
     yymsg = "Deleting";
   YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
 
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
   switch (yytype)
     {
-      case 3: /* "ODST_NUMBER" */
-
-/* Line 1000 of yacc.c  */
-#line 82 "ods_formula_parser.y"
-	{ delete (*yyvaluep); };
-
-/* Line 1000 of yacc.c  */
-#line 1220 "ods_formula_parser.cpp"
-	break;
-      case 4: /* "ODST_STRING" */
-
-/* Line 1000 of yacc.c  */
-#line 82 "ods_formula_parser.y"
-	{ delete (*yyvaluep); };
-
-/* Line 1000 of yacc.c  */
-#line 1229 "ods_formula_parser.cpp"
-	break;
-      case 5: /* "ODST_IDENTIFIER" */
-
-/* Line 1000 of yacc.c  */
-#line 82 "ods_formula_parser.y"
-	{ delete (*yyvaluep); };
-
-/* Line 1000 of yacc.c  */
-#line 1238 "ods_formula_parser.cpp"
-	break;
-      case 6: /* "ODST_FUNCTION_NO_ARG" */
-
-/* Line 1000 of yacc.c  */
-#line 82 "ods_formula_parser.y"
-	{ delete (*yyvaluep); };
-
-/* Line 1000 of yacc.c  */
-#line 1247 "ods_formula_parser.cpp"
-	break;
-      case 7: /* "ODST_FUNCTION_SINGLE_ARG" */
-
-/* Line 1000 of yacc.c  */
-#line 82 "ods_formula_parser.y"
-	{ delete (*yyvaluep); };
-
-/* Line 1000 of yacc.c  */
-#line 1256 "ods_formula_parser.cpp"
-	break;
-      case 8: /* "ODST_FUNCTION_TWO_ARG" */
-
-/* Line 1000 of yacc.c  */
-#line 82 "ods_formula_parser.y"
-	{ delete (*yyvaluep); };
-
-/* Line 1000 of yacc.c  */
-#line 1265 "ods_formula_parser.cpp"
-	break;
-      case 9: /* "ODST_FUNCTION_THREE_ARG" */
-
-/* Line 1000 of yacc.c  */
-#line 82 "ods_formula_parser.y"
-	{ delete (*yyvaluep); };
-
-/* Line 1000 of yacc.c  */
-#line 1274 "ods_formula_parser.cpp"
-	break;
-      case 10: /* "ODST_FUNCTION_ARG_LIST" */
-
-/* Line 1000 of yacc.c  */
-#line 82 "ods_formula_parser.y"
-	{ delete (*yyvaluep); };
-
-/* Line 1000 of yacc.c  */
-#line 1283 "ods_formula_parser.cpp"
-	break;
-      case 37: /* "value_expr" */
-
-/* Line 1000 of yacc.c  */
-#line 83 "ods_formula_parser.y"
-	{ delete (*yyvaluep); };
-
-/* Line 1000 of yacc.c  */
-#line 1292 "ods_formula_parser.cpp"
-	break;
-      case 38: /* "value_expr_list" */
-
-/* Line 1000 of yacc.c  */
-#line 83 "ods_formula_parser.y"
-	{ delete (*yyvaluep); };
-
-/* Line 1000 of yacc.c  */
-#line 1301 "ods_formula_parser.cpp"
-	break;
-      case 39: /* "value_expr_and_cell_range_list" */
-
-/* Line 1000 of yacc.c  */
-#line 83 "ods_formula_parser.y"
-	{ delete (*yyvaluep); };
-
-/* Line 1000 of yacc.c  */
-#line 1310 "ods_formula_parser.cpp"
-	break;
-      case 40: /* "cell_range" */
-
-/* Line 1000 of yacc.c  */
-#line 83 "ods_formula_parser.y"
-	{ delete (*yyvaluep); };
-
-/* Line 1000 of yacc.c  */
-#line 1319 "ods_formula_parser.cpp"
-	break;
+          case 3: /* ODST_NUMBER  */
+#line 83 "ods_formula_parser.y" /* yacc.c:1257  */
+      { delete ((*yyvaluep)); }
+#line 1107 "ods_formula_parser.cpp" /* yacc.c:1257  */
+        break;
+
+    case 4: /* ODST_STRING  */
+#line 83 "ods_formula_parser.y" /* yacc.c:1257  */
+      { delete ((*yyvaluep)); }
+#line 1113 "ods_formula_parser.cpp" /* yacc.c:1257  */
+        break;
+
+    case 5: /* ODST_IDENTIFIER  */
+#line 83 "ods_formula_parser.y" /* yacc.c:1257  */
+      { delete ((*yyvaluep)); }
+#line 1119 "ods_formula_parser.cpp" /* yacc.c:1257  */
+        break;
+
+    case 6: /* ODST_FUNCTION_NO_ARG  */
+#line 83 "ods_formula_parser.y" /* yacc.c:1257  */
+      { delete ((*yyvaluep)); }
+#line 1125 "ods_formula_parser.cpp" /* yacc.c:1257  */
+        break;
+
+    case 7: /* ODST_FUNCTION_SINGLE_ARG  */
+#line 83 "ods_formula_parser.y" /* yacc.c:1257  */
+      { delete ((*yyvaluep)); }
+#line 1131 "ods_formula_parser.cpp" /* yacc.c:1257  */
+        break;
+
+    case 8: /* ODST_FUNCTION_TWO_ARG  */
+#line 83 "ods_formula_parser.y" /* yacc.c:1257  */
+      { delete ((*yyvaluep)); }
+#line 1137 "ods_formula_parser.cpp" /* yacc.c:1257  */
+        break;
+
+    case 9: /* ODST_FUNCTION_THREE_ARG  */
+#line 83 "ods_formula_parser.y" /* yacc.c:1257  */
+      { delete ((*yyvaluep)); }
+#line 1143 "ods_formula_parser.cpp" /* yacc.c:1257  */
+        break;
+
+    case 10: /* ODST_FUNCTION_ARG_LIST  */
+#line 83 "ods_formula_parser.y" /* yacc.c:1257  */
+      { delete ((*yyvaluep)); }
+#line 1149 "ods_formula_parser.cpp" /* yacc.c:1257  */
+        break;
+
+    case 37: /* value_expr  */
+#line 84 "ods_formula_parser.y" /* yacc.c:1257  */
+      { delete ((*yyvaluep)); }
+#line 1155 "ods_formula_parser.cpp" /* yacc.c:1257  */
+        break;
+
+    case 38: /* value_expr_list  */
+#line 84 "ods_formula_parser.y" /* yacc.c:1257  */
+      { delete ((*yyvaluep)); }
+#line 1161 "ods_formula_parser.cpp" /* yacc.c:1257  */
+        break;
+
+    case 39: /* value_expr_and_cell_range_list  */
+#line 84 "ods_formula_parser.y" /* yacc.c:1257  */
+      { delete ((*yyvaluep)); }
+#line 1167 "ods_formula_parser.cpp" /* yacc.c:1257  */
+        break;
+
+    case 40: /* cell_range  */
+#line 84 "ods_formula_parser.y" /* yacc.c:1257  */
+      { delete ((*yyvaluep)); }
+#line 1173 "ods_formula_parser.cpp" /* yacc.c:1257  */
+        break;
+
 
       default:
-	break;
+        break;
     }
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
 }
 
-/* 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 (ods_formula_parse_context *context);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
 
 
 
+/*----------.
+| yyparse.  |
+`----------*/
 
-/*-------------------------.
-| yyparse or yypush_parse.  |
-`-------------------------*/
-
-#ifdef YYPARSE_PARAM
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void *YYPARSE_PARAM)
-#else
-int
-yyparse (YYPARSE_PARAM)
-    void *YYPARSE_PARAM;
-#endif
-#else /* ! YYPARSE_PARAM */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 int
 yyparse (ods_formula_parse_context *context)
-#else
-int
-yyparse (context)
-    ods_formula_parse_context *context;
-#endif
-#endif
 {
 /* The lookahead symbol.  */
 int yychar;
 
+
 /* The semantic value of the lookahead symbol.  */
-YYSTYPE yylval;
+/* Default value used for initialization, for pacifying older GCCs
+   or non-GCC compilers.  */
+
+YYSTYPE yylval = NULL;
 
     /* Number of syntax errors so far.  */
     int yynerrs;
@@ -1383,10 +1207,10 @@ YYSTYPE yylval;
     int yyerrstatus;
 
     /* The stacks and their tools:
-       `yyss': related to states.
-       `yyvs': related to semantic values.
+       'yyss': related to states.
+       'yyvs': related to semantic values.
 
-       Refer to the stacks thru separate pointers, to allow yyoverflow
+       Refer to the stacks through separate pointers, to allow yyoverflow
        to reallocate them elsewhere.  */
 
     /* The state stack.  */
@@ -1404,7 +1228,7 @@ YYSTYPE yylval;
   int yyn;
   int yyresult;
   /* Lookahead token as an internal (translated) token number.  */
-  int yytoken;
+  int yytoken = 0;
   /* The variables used to return semantic value and location from the
      action routines.  */
   YYSTYPE yyval;
@@ -1422,9 +1246,8 @@ YYSTYPE yylval;
      Keep to zero when no symbol should be popped.  */
   int yylen = 0;
 
-  yytoken = 0;
-  yyss = yyssa;
-  yyvs = yyvsa;
+  yyssp = yyss = yyssa;
+  yyvsp = yyvs = yyvsa;
   yystacksize = YYINITDEPTH;
 
   YYDPRINTF ((stderr, "Starting parse\n"));
@@ -1433,14 +1256,6 @@ YYSTYPE yylval;
   yyerrstatus = 0;
   yynerrs = 0;
   yychar = YYEMPTY; /* Cause a token to be read.  */
-
-  /* Initialize stack pointers.
-     Waste one element of value and location stack
-     so that they stay on the same level as the state stack.
-     The wasted elements are never initialized.  */
-  yyssp = yyss;
-  yyvsp = yyvs;
-
   goto yysetstate;
 
 /*------------------------------------------------------------.
@@ -1452,7 +1267,7 @@ YYSTYPE yylval;
   yyssp++;
 
  yysetstate:
-  *yyssp = yystate;
+  *yyssp = (yytype_int16)yystate;
 
   if (yyss + yystacksize - 1 <= yyssp)
     {
@@ -1461,23 +1276,23 @@ YYSTYPE yylval;
 
 #ifdef yyoverflow
       {
-	/* Give user a chance to reallocate the stack.  Use copies of
-	   these so that the &'s don't force the real ones into
-	   memory.  */
-	YYSTYPE *yyvs1 = yyvs;
-	yytype_int16 *yyss1 = yyss;
-
-	/* Each stack pointer address is followed by the size of the
-	   data in use in that stack, in bytes.  This used to be a
-	   conditional around just the two extra args, but that might
-	   be undefined if yyoverflow is a macro.  */
-	yyoverflow (YY_("memory exhausted"),
-		    &yyss1, yysize * sizeof (*yyssp),
-		    &yyvs1, yysize * sizeof (*yyvsp),
-		    &yystacksize);
-
-	yyss = yyss1;
-	yyvs = yyvs1;
+        /* Give user a chance to reallocate the stack.  Use copies of
+           these so that the &'s don't force the real ones into
+           memory.  */
+        YYSTYPE *yyvs1 = yyvs;
+        yytype_int16 *yyss1 = yyss;
+
+        /* Each stack pointer address is followed by the size of the
+           data in use in that stack, in bytes.  This used to be a
+           conditional around just the two extra args, but that might
+           be undefined if yyoverflow is a macro.  */
+        yyoverflow (YY_("memory exhausted"),
+                    &yyss1, yysize * sizeof (*yyssp),
+                    &yyvs1, yysize * sizeof (*yyvsp),
+                    &yystacksize);
+
+        yyss = yyss1;
+        yyvs = yyvs1;
       }
 #else /* no yyoverflow */
 # ifndef YYSTACK_RELOCATE
@@ -1485,22 +1300,22 @@ YYSTYPE yylval;
 # else
       /* Extend the stack our own way.  */
       if (YYMAXDEPTH <= yystacksize)
-	goto yyexhaustedlab;
+        goto yyexhaustedlab;
       yystacksize *= 2;
       if (YYMAXDEPTH < yystacksize)
-	yystacksize = YYMAXDEPTH;
+        yystacksize = YYMAXDEPTH;
 
       {
-	yytype_int16 *yyss1 = yyss;
-	union yyalloc *yyptr =
-	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
-	if (! yyptr)
-	  goto yyexhaustedlab;
-	YYSTACK_RELOCATE (yyss_alloc, yyss);
-	YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+        yytype_int16 *yyss1 = yyss;
+        union yyalloc *yyptr =
+          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+        if (! yyptr)
+          goto yyexhaustedlab;
+        YYSTACK_RELOCATE (yyss_alloc, yyss);
+        YYSTACK_RELOCATE (yyvs_alloc, yyvs);
 #  undef YYSTACK_RELOCATE
-	if (yyss1 != yyssa)
-	  YYSTACK_FREE (yyss1);
+        if (yyss1 != yyssa)
+          YYSTACK_FREE (yyss1);
       }
 # endif
 #endif /* no yyoverflow */
@@ -1509,10 +1324,10 @@ YYSTYPE yylval;
       yyvsp = yyvs + yysize - 1;
 
       YYDPRINTF ((stderr, "Stack size increased to %lu\n",
-		  (unsigned long int) yystacksize));
+                  (unsigned long int) yystacksize));
 
       if (yyss + yystacksize - 1 <= yyssp)
-	YYABORT;
+        YYABORT;
     }
 
   YYDPRINTF ((stderr, "Entering state %d\n", yystate));
@@ -1532,7 +1347,7 @@ yybackup:
 
   /* First try to decide what to do without reference to lookahead token.  */
   yyn = yypact[yystate];
-  if (yyn == YYPACT_NINF)
+  if (yypact_value_is_default (yyn))
     goto yydefault;
 
   /* Not known => get a lookahead token if don't already have one.  */
@@ -1541,7 +1356,7 @@ yybackup:
   if (yychar == YYEMPTY)
     {
       YYDPRINTF ((stderr, "Reading a token: "));
-      yychar = YYLEX;
+      yychar = yylex (&yylval, context);
     }
 
   if (yychar <= YYEOF)
@@ -1563,8 +1378,8 @@ yybackup:
   yyn = yytable[yyn];
   if (yyn <= 0)
     {
-      if (yyn == 0 || yyn == YYTABLE_NINF)
-	goto yyerrlab;
+      if (yytable_value_is_error (yyn))
+        goto yyerrlab;
       yyn = -yyn;
       goto yyreduce;
     }
@@ -1581,7 +1396,9 @@ yybackup:
   yychar = YYEMPTY;
 
   yystate = yyn;
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
   *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
 
   goto yynewstate;
 
@@ -1604,7 +1421,7 @@ yyreduce:
   yylen = yyr2[yyn];
 
   /* If YYLEN is nonzero, implement the default value of the action:
-     `$$ = $1'.
+     '$$ = $1'.
 
      Otherwise, the following line sets YYVAL to garbage.
      This behavior is undocumented and Bison
@@ -1618,256 +1435,231 @@ yyreduce:
   switch (yyn)
     {
         case 2:
-
-/* Line 1455 of yacc.c  */
-#line 89 "ods_formula_parser.y"
+#line 90 "ods_formula_parser.y" /* yacc.c:1646  */
     {
-            context->poRoot = (yyvsp[(2) - (2)]);
-        ;}
+            context->poRoot = (yyvsp[0]);
+        }
+#line 1443 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 5:
-
-/* Line 1455 of yacc.c  */
-#line 98 "ods_formula_parser.y"
+#line 99 "ods_formula_parser.y" /* yacc.c:1646  */
     {
-            (yyval) = (yyvsp[(1) - (1)]);
-        ;}
+            (yyval) = (yyvsp[0]);
+        }
+#line 1451 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 6:
-
-/* Line 1455 of yacc.c  */
-#line 103 "ods_formula_parser.y"
+#line 104 "ods_formula_parser.y" /* yacc.c:1646  */
     {
-            (yyval) = (yyvsp[(1) - (1)]);
-        ;}
+            (yyval) = (yyvsp[0]);
+        }
+#line 1459 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 7:
-
-/* Line 1455 of yacc.c  */
-#line 108 "ods_formula_parser.y"
+#line 109 "ods_formula_parser.y" /* yacc.c:1646  */
     {
-            (yyval) = (yyvsp[(1) - (3)]);
-        ;}
+            (yyval) = (yyvsp[-2]);
+        }
+#line 1467 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 8:
-
-/* Line 1455 of yacc.c  */
-#line 113 "ods_formula_parser.y"
+#line 114 "ods_formula_parser.y" /* yacc.c:1646  */
     {
-            (yyval) = (yyvsp[(1) - (4)]);
-            (yyval)->PushSubExpression( (yyvsp[(3) - (4)]) );
-        ;}
+            (yyval) = (yyvsp[-3]);
+            (yyval)->PushSubExpression( (yyvsp[-1]) );
+        }
+#line 1476 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 9:
-
-/* Line 1455 of yacc.c  */
-#line 119 "ods_formula_parser.y"
+#line 120 "ods_formula_parser.y" /* yacc.c:1646  */
     {
-            (yyval) = (yyvsp[(1) - (6)]);
-            (yyval)->PushSubExpression( (yyvsp[(3) - (6)]) );
-            (yyval)->PushSubExpression( (yyvsp[(5) - (6)]) );
-        ;}
+            (yyval) = (yyvsp[-5]);
+            (yyval)->PushSubExpression( (yyvsp[-3]) );
+            (yyval)->PushSubExpression( (yyvsp[-1]) );
+        }
+#line 1486 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 10:
-
-/* Line 1455 of yacc.c  */
-#line 126 "ods_formula_parser.y"
+#line 127 "ods_formula_parser.y" /* yacc.c:1646  */
     {
-            (yyval) = (yyvsp[(1) - (8)]);
-            (yyval)->PushSubExpression( (yyvsp[(3) - (8)]) );
-            (yyval)->PushSubExpression( (yyvsp[(5) - (8)]) );
-            (yyval)->PushSubExpression( (yyvsp[(7) - (8)]) );
-        ;}
+            (yyval) = (yyvsp[-7]);
+            (yyval)->PushSubExpression( (yyvsp[-5]) );
+            (yyval)->PushSubExpression( (yyvsp[-3]) );
+            (yyval)->PushSubExpression( (yyvsp[-1]) );
+        }
+#line 1497 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 11:
-
-/* Line 1455 of yacc.c  */
-#line 134 "ods_formula_parser.y"
+#line 135 "ods_formula_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new ods_formula_node( ODS_AND );
-            (yyvsp[(3) - (4)])->ReverseSubExpressions();
-            (yyval)->PushSubExpression( (yyvsp[(3) - (4)]) );
-        ;}
+            (yyvsp[-1])->ReverseSubExpressions();
+            (yyval)->PushSubExpression( (yyvsp[-1]) );
+        }
+#line 1507 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 12:
-
-/* Line 1455 of yacc.c  */
-#line 141 "ods_formula_parser.y"
+#line 142 "ods_formula_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new ods_formula_node( ODS_OR );
-            (yyvsp[(3) - (4)])->ReverseSubExpressions();
-            (yyval)->PushSubExpression( (yyvsp[(3) - (4)]) );
-        ;}
+            (yyvsp[-1])->ReverseSubExpressions();
+            (yyval)->PushSubExpression( (yyvsp[-1]) );
+        }
+#line 1517 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 13:
-
-/* Line 1455 of yacc.c  */
-#line 148 "ods_formula_parser.y"
+#line 149 "ods_formula_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new ods_formula_node( ODS_NOT );
-            (yyval)->PushSubExpression( (yyvsp[(3) - (4)]) );
-        ;}
+            (yyval)->PushSubExpression( (yyvsp[-1]) );
+        }
+#line 1526 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 14:
-
-/* Line 1455 of yacc.c  */
-#line 154 "ods_formula_parser.y"
+#line 155 "ods_formula_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new ods_formula_node( ODS_IF );
-            (yyval)->PushSubExpression( (yyvsp[(3) - (6)]) );
-            (yyval)->PushSubExpression( (yyvsp[(5) - (6)]) );
-        ;}
+            (yyval)->PushSubExpression( (yyvsp[-3]) );
+            (yyval)->PushSubExpression( (yyvsp[-1]) );
+        }
+#line 1536 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 15:
-
-/* Line 1455 of yacc.c  */
-#line 161 "ods_formula_parser.y"
+#line 162 "ods_formula_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new ods_formula_node( ODS_IF );
-            (yyval)->PushSubExpression( (yyvsp[(3) - (8)]) );
-            (yyval)->PushSubExpression( (yyvsp[(5) - (8)]) );
-            (yyval)->PushSubExpression( (yyvsp[(7) - (8)]) );
-        ;}
+            (yyval)->PushSubExpression( (yyvsp[-5]) );
+            (yyval)->PushSubExpression( (yyvsp[-3]) );
+            (yyval)->PushSubExpression( (yyvsp[-1]) );
+        }
+#line 1547 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 16:
-
-/* Line 1455 of yacc.c  */
-#line 169 "ods_formula_parser.y"
+#line 170 "ods_formula_parser.y" /* yacc.c:1646  */
     {
-            (yyval) = (yyvsp[(1) - (4)]);
-            (yyvsp[(3) - (4)])->ReverseSubExpressions();
-            (yyval)->PushSubExpression( (yyvsp[(3) - (4)]) );
-        ;}
+            (yyval) = (yyvsp[-3]);
+            (yyvsp[-1])->ReverseSubExpressions();
+            (yyval)->PushSubExpression( (yyvsp[-1]) );
+        }
+#line 1557 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 17:
-
-/* Line 1455 of yacc.c  */
-#line 176 "ods_formula_parser.y"
+#line 177 "ods_formula_parser.y" /* yacc.c:1646  */
     {
-            (yyval) = (yyvsp[(2) - (3)]);
-        ;}
+            (yyval) = (yyvsp[-1]);
+        }
+#line 1565 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 18:
-
-/* Line 1455 of yacc.c  */
-#line 181 "ods_formula_parser.y"
+#line 182 "ods_formula_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new ods_formula_node( ODS_EQ );
-            (yyval)->PushSubExpression( (yyvsp[(1) - (3)]) );
-            (yyval)->PushSubExpression( (yyvsp[(3) - (3)]) );
-        ;}
+            (yyval)->PushSubExpression( (yyvsp[-2]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1575 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 19:
-
-/* Line 1455 of yacc.c  */
-#line 188 "ods_formula_parser.y"
+#line 189 "ods_formula_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new ods_formula_node( ODS_NE );
-            (yyval)->PushSubExpression( (yyvsp[(1) - (4)]) );
-            (yyval)->PushSubExpression( (yyvsp[(4) - (4)]) );
-        ;}
+            (yyval)->PushSubExpression( (yyvsp[-3]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1585 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 20:
-
-/* Line 1455 of yacc.c  */
-#line 195 "ods_formula_parser.y"
+#line 196 "ods_formula_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new ods_formula_node( ODS_NE );
-            (yyval)->PushSubExpression( (yyvsp[(1) - (4)]) );
-            (yyval)->PushSubExpression( (yyvsp[(4) - (4)]) );
-        ;}
+            (yyval)->PushSubExpression( (yyvsp[-3]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1595 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 21:
-
-/* Line 1455 of yacc.c  */
-#line 202 "ods_formula_parser.y"
+#line 203 "ods_formula_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new ods_formula_node( ODS_LT );
-            (yyval)->PushSubExpression( (yyvsp[(1) - (3)]) );
-            (yyval)->PushSubExpression( (yyvsp[(3) - (3)]) );
-        ;}
+            (yyval)->PushSubExpression( (yyvsp[-2]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1605 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 22:
-
-/* Line 1455 of yacc.c  */
-#line 209 "ods_formula_parser.y"
+#line 210 "ods_formula_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new ods_formula_node( ODS_GT );
-            (yyval)->PushSubExpression( (yyvsp[(1) - (3)]) );
-            (yyval)->PushSubExpression( (yyvsp[(3) - (3)]) );
-        ;}
+            (yyval)->PushSubExpression( (yyvsp[-2]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1615 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 23:
-
-/* Line 1455 of yacc.c  */
-#line 216 "ods_formula_parser.y"
+#line 217 "ods_formula_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new ods_formula_node( ODS_LE );
-            (yyval)->PushSubExpression( (yyvsp[(1) - (4)]) );
-            (yyval)->PushSubExpression( (yyvsp[(4) - (4)]) );
-        ;}
+            (yyval)->PushSubExpression( (yyvsp[-3]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1625 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 24:
-
-/* Line 1455 of yacc.c  */
-#line 223 "ods_formula_parser.y"
+#line 224 "ods_formula_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new ods_formula_node( ODS_LE );
-            (yyval)->PushSubExpression( (yyvsp[(1) - (4)]) );
-            (yyval)->PushSubExpression( (yyvsp[(4) - (4)]) );
-        ;}
+            (yyval)->PushSubExpression( (yyvsp[-3]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1635 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 25:
-
-/* Line 1455 of yacc.c  */
-#line 230 "ods_formula_parser.y"
+#line 231 "ods_formula_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new ods_formula_node( ODS_LE );
-            (yyval)->PushSubExpression( (yyvsp[(1) - (4)]) );
-            (yyval)->PushSubExpression( (yyvsp[(4) - (4)]) );
-        ;}
+            (yyval)->PushSubExpression( (yyvsp[-3]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1645 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 26:
-
-/* Line 1455 of yacc.c  */
-#line 237 "ods_formula_parser.y"
+#line 238 "ods_formula_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new ods_formula_node( ODS_GE );
-            (yyval)->PushSubExpression( (yyvsp[(1) - (4)]) );
-            (yyval)->PushSubExpression( (yyvsp[(4) - (4)]) );
-        ;}
+            (yyval)->PushSubExpression( (yyvsp[-3]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1655 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 27:
-
-/* Line 1455 of yacc.c  */
-#line 244 "ods_formula_parser.y"
+#line 245 "ods_formula_parser.y" /* yacc.c:1646  */
     {
-            if ((yyvsp[(2) - (2)])->eNodeType == SNT_CONSTANT)
+            if ((yyvsp[0])->eNodeType == SNT_CONSTANT)
             {
-                (yyval) = (yyvsp[(2) - (2)]);
+                (yyval) = (yyvsp[0]);
                 (yyval)->int_value *= -1;
                 (yyval)->float_value *= -1;
             }
@@ -1875,164 +1667,160 @@ yyreduce:
             {
                 (yyval) = new ods_formula_node( ODS_MULTIPLY );
                 (yyval)->PushSubExpression( new ods_formula_node(-1) );
-                (yyval)->PushSubExpression( (yyvsp[(2) - (2)]) );
+                (yyval)->PushSubExpression( (yyvsp[0]) );
             }
-        ;}
+        }
+#line 1674 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 28:
-
-/* Line 1455 of yacc.c  */
-#line 260 "ods_formula_parser.y"
+#line 261 "ods_formula_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new ods_formula_node( ODS_ADD );
-            (yyval)->PushSubExpression( (yyvsp[(1) - (3)]) );
-            (yyval)->PushSubExpression( (yyvsp[(3) - (3)]) );
-        ;}
+            (yyval)->PushSubExpression( (yyvsp[-2]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1684 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 29:
-
-/* Line 1455 of yacc.c  */
-#line 267 "ods_formula_parser.y"
+#line 268 "ods_formula_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new ods_formula_node( ODS_SUBTRACT );
-            (yyval)->PushSubExpression( (yyvsp[(1) - (3)]) );
-            (yyval)->PushSubExpression( (yyvsp[(3) - (3)]) );
-        ;}
+            (yyval)->PushSubExpression( (yyvsp[-2]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1694 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 30:
-
-/* Line 1455 of yacc.c  */
-#line 274 "ods_formula_parser.y"
+#line 275 "ods_formula_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new ods_formula_node( ODS_CONCAT );
-            (yyval)->PushSubExpression( (yyvsp[(1) - (3)]) );
-            (yyval)->PushSubExpression( (yyvsp[(3) - (3)]) );
-        ;}
+            (yyval)->PushSubExpression( (yyvsp[-2]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1704 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 31:
-
-/* Line 1455 of yacc.c  */
-#line 281 "ods_formula_parser.y"
+#line 282 "ods_formula_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new ods_formula_node( ODS_MULTIPLY );
-            (yyval)->PushSubExpression( (yyvsp[(1) - (3)]) );
-            (yyval)->PushSubExpression( (yyvsp[(3) - (3)]) );
-        ;}
+            (yyval)->PushSubExpression( (yyvsp[-2]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1714 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 32:
-
-/* Line 1455 of yacc.c  */
-#line 288 "ods_formula_parser.y"
+#line 289 "ods_formula_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new ods_formula_node( ODS_DIVIDE );
-            (yyval)->PushSubExpression( (yyvsp[(1) - (3)]) );
-            (yyval)->PushSubExpression( (yyvsp[(3) - (3)]) );
-        ;}
+            (yyval)->PushSubExpression( (yyvsp[-2]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1724 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 33:
-
-/* Line 1455 of yacc.c  */
-#line 295 "ods_formula_parser.y"
+#line 296 "ods_formula_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new ods_formula_node( ODS_MODULUS );
-            (yyval)->PushSubExpression( (yyvsp[(1) - (3)]) );
-            (yyval)->PushSubExpression( (yyvsp[(3) - (3)]) );
-        ;}
+            (yyval)->PushSubExpression( (yyvsp[-2]) );
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1734 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 34:
-
-/* Line 1455 of yacc.c  */
-#line 302 "ods_formula_parser.y"
+#line 303 "ods_formula_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new ods_formula_node( ODS_CELL );
-            (yyval)->PushSubExpression( (yyvsp[(2) - (3)]) );
-        ;}
+            (yyval)->PushSubExpression( (yyvsp[-1]) );
+        }
+#line 1743 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 35:
-
-/* Line 1455 of yacc.c  */
-#line 309 "ods_formula_parser.y"
+#line 310 "ods_formula_parser.y" /* yacc.c:1646  */
     {
-            (yyval) = (yyvsp[(3) - (3)]);
-            (yyvsp[(3) - (3)])->PushSubExpression( (yyvsp[(1) - (3)]) );
-        ;}
+            (yyval) = (yyvsp[0]);
+            (yyvsp[0])->PushSubExpression( (yyvsp[-2]) );
+        }
+#line 1752 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 36:
-
-/* Line 1455 of yacc.c  */
-#line 315 "ods_formula_parser.y"
+#line 316 "ods_formula_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new ods_formula_node( ODS_LIST );
-            (yyval)->PushSubExpression( (yyvsp[(1) - (1)]) );
-        ;}
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1761 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 37:
-
-/* Line 1455 of yacc.c  */
-#line 322 "ods_formula_parser.y"
+#line 323 "ods_formula_parser.y" /* yacc.c:1646  */
     {
-            (yyval) = (yyvsp[(3) - (3)]);
-            (yyvsp[(3) - (3)])->PushSubExpression( (yyvsp[(1) - (3)]) );
-        ;}
+            (yyval) = (yyvsp[0]);
+            (yyvsp[0])->PushSubExpression( (yyvsp[-2]) );
+        }
+#line 1770 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 38:
-
-/* Line 1455 of yacc.c  */
-#line 328 "ods_formula_parser.y"
+#line 329 "ods_formula_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new ods_formula_node( ODS_LIST );
-            (yyval)->PushSubExpression( (yyvsp[(1) - (1)]) );
-        ;}
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1779 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 39:
-
-/* Line 1455 of yacc.c  */
-#line 333 "ods_formula_parser.y"
+#line 334 "ods_formula_parser.y" /* yacc.c:1646  */
     {
-            (yyval) = (yyvsp[(3) - (3)]);
-            (yyvsp[(3) - (3)])->PushSubExpression( (yyvsp[(1) - (3)]) );
-        ;}
+            (yyval) = (yyvsp[0]);
+            (yyvsp[0])->PushSubExpression( (yyvsp[-2]) );
+        }
+#line 1788 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 40:
-
-/* Line 1455 of yacc.c  */
-#line 339 "ods_formula_parser.y"
+#line 340 "ods_formula_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new ods_formula_node( ODS_LIST );
-            (yyval)->PushSubExpression( (yyvsp[(1) - (1)]) );
-        ;}
+            (yyval)->PushSubExpression( (yyvsp[0]) );
+        }
+#line 1797 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 41:
-
-/* Line 1455 of yacc.c  */
-#line 346 "ods_formula_parser.y"
+#line 347 "ods_formula_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new ods_formula_node( ODS_CELL_RANGE );
-            (yyval)->PushSubExpression( (yyvsp[(2) - (5)]) );
-            (yyval)->PushSubExpression( (yyvsp[(4) - (5)]) );
-        ;}
+            (yyval)->PushSubExpression( (yyvsp[-3]) );
+            (yyval)->PushSubExpression( (yyvsp[-1]) );
+        }
+#line 1807 "ods_formula_parser.cpp" /* yacc.c:1646  */
     break;
 
 
-
-/* Line 1455 of yacc.c  */
-#line 2033 "ods_formula_parser.cpp"
+#line 1811 "ods_formula_parser.cpp" /* yacc.c:1646  */
       default: break;
     }
+  /* User semantic actions sometimes alter yychar, and that requires
+     that yytoken be updated with the new translation.  We take the
+     approach of translating immediately before every use of yytoken.
+     One alternative is translating here after every semantic action,
+     but that translation would be missed if the semantic action invokes
+     YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
+     if it invokes YYBACKUP.  In the case of YYABORT or YYACCEPT, an
+     incorrect destructor might then be invoked immediately.  In the
+     case of YYERROR or YYBACKUP, subsequent parser actions might lead
+     to an incorrect destructor call or verbose syntax error message
+     before the lookahead is translated.  */
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
 
   YYPOPSTACK (yylen);
@@ -2041,7 +1829,7 @@ yyreduce:
 
   *++yyvsp = yyval;
 
-  /* Now `shift' the result of the reduction.  Determine what state
+  /* Now 'shift' the result of the reduction.  Determine what state
      that goes to, based on the state we popped back to and the rule
      number reduced by.  */
 
@@ -2056,10 +1844,14 @@ yyreduce:
   goto yynewstate;
 
 
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
+/*--------------------------------------.
+| yyerrlab -- here on detecting error.  |
+`--------------------------------------*/
 yyerrlab:
+  /* Make sure we have latest lookahead translation.  See comments at
+     user semantic actions for why this is necessary.  */
+  yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
+
   /* If not already recovering from an error, report this error.  */
   if (!yyerrstatus)
     {
@@ -2067,37 +1859,36 @@ yyerrlab:
 #if ! YYERROR_VERBOSE
       yyerror (context, YY_("syntax error"));
 #else
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
+                                        yyssp, yytoken)
       {
-	YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
-	if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
-	  {
-	    YYSIZE_T yyalloc = 2 * yysize;
-	    if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
-	      yyalloc = YYSTACK_ALLOC_MAXIMUM;
-	    if (yymsg != yymsgbuf)
-	      YYSTACK_FREE (yymsg);
-	    yymsg = (char *) YYSTACK_ALLOC (yyalloc);
-	    if (yymsg)
-	      yymsg_alloc = yyalloc;
-	    else
-	      {
-		yymsg = yymsgbuf;
-		yymsg_alloc = sizeof yymsgbuf;
-	      }
-	  }
-
-	if (0 < yysize && yysize <= yymsg_alloc)
-	  {
-	    (void) yysyntax_error (yymsg, yystate, yychar);
-	    yyerror (context, yymsg);
-	  }
-	else
-	  {
-	    yyerror (context, YY_("syntax error"));
-	    if (yysize != 0)
-	      goto yyexhaustedlab;
-	  }
+        char const *yymsgp = YY_("syntax error");
+        int yysyntax_error_status;
+        yysyntax_error_status = YYSYNTAX_ERROR;
+        if (yysyntax_error_status == 0)
+          yymsgp = yymsg;
+        else if (yysyntax_error_status == 1)
+          {
+            if (yymsg != yymsgbuf)
+              YYSTACK_FREE (yymsg);
+            yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
+            if (!yymsg)
+              {
+                yymsg = yymsgbuf;
+                yymsg_alloc = sizeof yymsgbuf;
+                yysyntax_error_status = 2;
+              }
+            else
+              {
+                yysyntax_error_status = YYSYNTAX_ERROR;
+                yymsgp = yymsg;
+              }
+          }
+        yyerror (context, yymsgp);
+        if (yysyntax_error_status == 2)
+          goto yyexhaustedlab;
       }
+# undef YYSYNTAX_ERROR
 #endif
     }
 
@@ -2106,20 +1897,20 @@ yyerrlab:
   if (yyerrstatus == 3)
     {
       /* If just tried and failed to reuse lookahead token after an
-	 error, discard it.  */
+         error, discard it.  */
 
       if (yychar <= YYEOF)
-	{
-	  /* Return failure if at end of input.  */
-	  if (yychar == YYEOF)
-	    YYABORT;
-	}
+        {
+          /* Return failure if at end of input.  */
+          if (yychar == YYEOF)
+            YYABORT;
+        }
       else
-	{
-	  yydestruct ("Error: discarding",
-		      yytoken, &yylval, context);
-	  yychar = YYEMPTY;
-	}
+        {
+          yydestruct ("Error: discarding",
+                      yytoken, &yylval, context);
+          yychar = YYEMPTY;
+        }
     }
 
   /* Else will try to reuse lookahead token after shifting the error
@@ -2130,6 +1921,7 @@ yyerrlab:
 /*---------------------------------------------------.
 | yyerrorlab -- error raised explicitly by YYERROR.  |
 `---------------------------------------------------*/
+#if 0
 yyerrorlab:
 
   /* Pacify compilers like GCC when the user code never invokes
@@ -2138,7 +1930,7 @@ yyerrorlab:
   if (/*CONSTCOND*/ 0)
      goto yyerrorlab;
 
-  /* Do not reclaim the symbols of the rule which action triggered
+  /* Do not reclaim the symbols of the rule whose action triggered
      this YYERROR.  */
   YYPOPSTACK (yylen);
   yylen = 0;
@@ -2150,36 +1942,39 @@ yyerrorlab:
 /*-------------------------------------------------------------.
 | yyerrlab1 -- common code for both syntax error and YYERROR.  |
 `-------------------------------------------------------------*/
+#endif
 yyerrlab1:
-  yyerrstatus = 3;	/* Each real token shifted decrements this.  */
+  yyerrstatus = 3;      /* Each real token shifted decrements this.  */
 
   for (;;)
     {
       yyn = yypact[yystate];
-      if (yyn != YYPACT_NINF)
-	{
-	  yyn += YYTERROR;
-	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
-	    {
-	      yyn = yytable[yyn];
-	      if (0 < yyn)
-		break;
-	    }
-	}
+      if (!yypact_value_is_default (yyn))
+        {
+          yyn += YYTERROR;
+          if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+            {
+              yyn = yytable[yyn];
+              if (0 < yyn)
+                break;
+            }
+        }
 
       /* Pop the current state because it cannot handle the error token.  */
       if (yyssp == yyss)
-	YYABORT;
+        YYABORT;
 
 
       yydestruct ("Error: popping",
-		  yystos[yystate], yyvsp, context);
+                  yystos[yystate], yyvsp, context);
       YYPOPSTACK (1);
       yystate = *yyssp;
       YY_STACK_PRINT (yyss, yyssp);
     }
 
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
   *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
 
 
   /* Shift the error token.  */
@@ -2203,7 +1998,7 @@ yyabortlab:
   yyresult = 1;
   goto yyreturn;
 
-#if !defined(yyoverflow) || YYERROR_VERBOSE
+#if !defined yyoverflow || YYERROR_VERBOSE
 /*-------------------------------------------------.
 | yyexhaustedlab -- memory exhaustion comes here.  |
 `-------------------------------------------------*/
@@ -2215,16 +2010,21 @@ yyexhaustedlab:
 
 yyreturn:
   if (yychar != YYEMPTY)
-     yydestruct ("Cleanup: discarding lookahead",
-		 yytoken, &yylval, context);
-  /* Do not reclaim the symbols of the rule which action triggered
+    {
+      /* Make sure we have latest lookahead translation.  See comments at
+         user semantic actions for why this is necessary.  */
+      yytoken = YYTRANSLATE (yychar);
+      yydestruct ("Cleanup: discarding lookahead",
+                  yytoken, &yylval, context);
+    }
+  /* Do not reclaim the symbols of the rule whose action triggered
      this YYABORT or YYACCEPT.  */
   YYPOPSTACK (yylen);
   YY_STACK_PRINT (yyss, yyssp);
   while (yyssp != yyss)
     {
       yydestruct ("Cleanup: popping",
-		  yystos[*yyssp], yyvsp, context);
+                  yystos[*yyssp], yyvsp, context);
       YYPOPSTACK (1);
     }
 #ifndef yyoverflow
@@ -2235,6 +2035,5 @@ yyreturn:
   if (yymsg != yymsgbuf)
     YYSTACK_FREE (yymsg);
 #endif
-  /* Make sure YYID is used.  */
-  return YYID (yyresult);
+  return yyresult;
 }
diff --git a/ogr/ogrsf_frmts/ods/ods_formula_parser.hpp b/ogr/ogrsf_frmts/ods/ods_formula_parser.hpp
index 1657c60..7673816 100644
--- a/ogr/ogrsf_frmts/ods/ods_formula_parser.hpp
+++ b/ogr/ogrsf_frmts/ods/ods_formula_parser.hpp
@@ -1,22 +1,19 @@
+/* A Bison parser, made by GNU Bison 3.0.  */
 
-/* A Bison parser, made by GNU Bison 2.4.1.  */
+/* Bison interface for Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
 
-/* Skeleton interface for Bison's Yacc-like parsers in C
-   
-      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
-   
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
@@ -29,43 +26,51 @@
    special exception, which will cause the skeleton and the resulting
    Bison output files to be licensed under the GNU General Public
    License without this special exception.
-   
+
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
+#ifndef YY_ODS_FORMULA_ODS_FORMULA_PARSER_HPP_INCLUDED
+# define YY_ODS_FORMULA_ODS_FORMULA_PARSER_HPP_INCLUDED
+/* Debug traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int ods_formuladebug;
+#endif
 
-/* Tokens.  */
+/* Token type.  */
 #ifndef YYTOKENTYPE
 # define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     ODST_NUMBER = 258,
-     ODST_STRING = 259,
-     ODST_IDENTIFIER = 260,
-     ODST_FUNCTION_NO_ARG = 261,
-     ODST_FUNCTION_SINGLE_ARG = 262,
-     ODST_FUNCTION_TWO_ARG = 263,
-     ODST_FUNCTION_THREE_ARG = 264,
-     ODST_FUNCTION_ARG_LIST = 265,
-     ODST_START = 266,
-     ODST_NOT = 267,
-     ODST_OR = 268,
-     ODST_AND = 269,
-     ODST_IF = 270,
-     ODST_UMINUS = 271
-   };
+  enum yytokentype
+  {
+    ODST_NUMBER = 258,
+    ODST_STRING = 259,
+    ODST_IDENTIFIER = 260,
+    ODST_FUNCTION_NO_ARG = 261,
+    ODST_FUNCTION_SINGLE_ARG = 262,
+    ODST_FUNCTION_TWO_ARG = 263,
+    ODST_FUNCTION_THREE_ARG = 264,
+    ODST_FUNCTION_ARG_LIST = 265,
+    ODST_START = 266,
+    ODST_NOT = 267,
+    ODST_OR = 268,
+    ODST_AND = 269,
+    ODST_IF = 270,
+    ODST_UMINUS = 271
+  };
 #endif
 
-
-
+/* Value type.  */
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef int YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
 #endif
 
 
 
+int ods_formulaparse (ods_formula_parse_context *context);
 
+#endif /* !YY_ODS_FORMULA_ODS_FORMULA_PARSER_HPP_INCLUDED  */
diff --git a/ogr/ogrsf_frmts/ods/ods_formula_parser.y b/ogr/ogrsf_frmts/ods/ods_formula_parser.y
index 23a59a8..67187ea 100644
--- a/ogr/ogrsf_frmts/ods/ods_formula_parser.y
+++ b/ogr/ogrsf_frmts/ods/ods_formula_parser.y
@@ -1,12 +1,12 @@
 %{
 /******************************************************************************
- * $Id: ods_formula_parser.y 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ods_formula_parser.y 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Component: OGR ODS Formula Engine
  * Purpose: expression and select parser grammar.
  *          Requires Bison 2.4.0 or newer to process.  Use "make parser" target.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
- * 
+ *
  ******************************************************************************
  * Copyright (C) 2010 Frank Warmerdam <warmerdam at pobox.com>
  * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
@@ -36,17 +36,17 @@
 
 #define YYSTYPE  ods_formula_node*
 
-/* Defining YYSTYPE_IS_TRIVIAL is needed because the parser is generated as a C++ file. */ 
-/* See http://www.gnu.org/s/bison/manual/html_node/Memory-Management.html that suggests */ 
-/* increase YYINITDEPTH instead, but this will consume memory. */ 
-/* Setting YYSTYPE_IS_TRIVIAL overcomes this limitation, but might be fragile because */ 
-/* it appears to be a non documented feature of Bison */ 
+/* Defining YYSTYPE_IS_TRIVIAL is needed because the parser is generated as a C++ file. */
+/* See http://www.gnu.org/s/bison/manual/html_node/Memory-Management.html that suggests */
+/* increase YYINITDEPTH instead, but this will consume memory. */
+/* Setting YYSTYPE_IS_TRIVIAL overcomes this limitation, but might be fragile because */
+/* it appears to be a non documented feature of Bison */
 #define YYSTYPE_IS_TRIVIAL 1
 
-static void ods_formulaerror( CPL_UNUSED ods_formula_parse_context *context,
+static void ods_formulaerror( ods_formula_parse_context * /* context */,
                               const char *msg )
 {
-    CPLError( CE_Failure, CPLE_AppDefined, 
+    CPLError( CE_Failure, CPLE_AppDefined,
               "Formula Parsing Error: %s", msg );
 }
 
diff --git a/ogr/ogrsf_frmts/ods/ogr_ods.h b/ogr/ogrsf_frmts/ods/ogr_ods.h
index 86550dc..47af44f 100644
--- a/ogr/ogrsf_frmts/ods/ogr_ods.h
+++ b/ogr/ogrsf_frmts/ods/ogr_ods.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_ods.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogr_ods.h 32989 2016-01-14 21:28:07Z rouault $
  *
  * Project:  ODS Translator
  * Purpose:  Definition of classes for OGR OpenOfficeSpreadsheet .ods driver.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_ODS_H_INCLUDED
-#define _OGR_ODS_H_INCLUDED
+#ifndef OGR_ODS_H_INCLUDED
+#define OGR_ODS_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "ogr_mem.h"
@@ -39,6 +39,8 @@
 #include <string>
 #include <set>
 
+namespace OGRODS {
+
 /************************************************************************/
 /*                             OGRODSLayer                              */
 /************************************************************************/
@@ -48,18 +50,18 @@ class OGRODSDataSource;
 class OGRODSLayer : public OGRMemLayer
 {
     OGRODSDataSource* poDS;
-    int               bUpdated;
-    int               bHasHeaderLine;
+    bool              bUpdated;
+    bool              bHasHeaderLine;
 
     public:
         OGRODSLayer( OGRODSDataSource* poDSIn,
                       const char * pszName,
-                      int bUpdateIn = FALSE);
+                      bool bUpdateIn = FALSE);
 
-    void                SetUpdated(int bUpdatedIn = TRUE);
+    void                SetUpdated(bool bUpdatedIn = true);
 
-    int                 GetHasHeaderLine() { return bHasHeaderLine; }
-    void                SetHasHeaderLine(int bIn) { bHasHeaderLine = bIn; }
+    bool                GetHasHeaderLine() { return bHasHeaderLine; }
+    void                SetHasHeaderLine(bool bIn) { bHasHeaderLine = bIn; }
 
     const char         *GetName() { return OGRMemLayer::GetLayerDefn()->GetName(); };
     OGRwkbGeometryType  GetGeomType() { return wkbNone; }
@@ -88,8 +90,8 @@ class OGRODSLayer : public OGRMemLayer
     virtual OGRErr      ReorderFields( int* panMap )
     { SetUpdated(); return OGRMemLayer::ReorderFields(panMap); }
 
-    virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags )
-    { SetUpdated(); return OGRMemLayer::AlterFieldDefn(iField, poNewFieldDefn, nFlags); }
+    virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlagsIn )
+    { SetUpdated(); return OGRMemLayer::AlterFieldDefn(iField, poNewFieldDefn, nFlagsIn); }
 
     virtual OGRErr      SyncToDisk();
 };
@@ -117,9 +119,9 @@ typedef struct
 class OGRODSDataSource : public OGRDataSource
 {
     char*               pszName;
-    int                 bUpdatable;
-    int                 bUpdated;
-    int                 bAnalysedFile;
+    bool                bUpdatable;
+    bool                bUpdated;
+    bool                bAnalysedFile;
 
     int                 nLayers;
     OGRLayer          **papoLayers;
@@ -134,11 +136,11 @@ class OGRODSDataSource : public OGRDataSource
     VSILFILE*           fpContent;
     void                AnalyseFile();
 
-    int                 bFirstLineIsHeaders;
+    bool                bFirstLineIsHeaders;
     int                 bAutodetectTypes;
 
     XML_Parser          oParser;
-    int                 bStopParsing;
+    bool                bStopParsing;
     int                 nWithoutEventCounter;
     int                 nDataHandlerCounter;
     int                 nCurLine;
@@ -213,10 +215,12 @@ class OGRODSDataSource : public OGRDataSource
     void endElementStylesCbk(const char *pszName);
     void dataHandlerStylesCbk(const char *data, int nLen);
 
-    int                 GetUpdatable() { return bUpdatable; }
-    void                SetUpdated() { bUpdated = TRUE; }
+    bool                GetUpdatable() { return bUpdatable; }
+    void                SetUpdated() { bUpdated = true; }
 };
 
+} /* end of OGRODS namespace */
+
 /************************************************************************/
 /*                             OGRODSDriver                             */
 /************************************************************************/
@@ -235,5 +239,4 @@ class OGRODSDriver : public OGRSFDriver
     virtual OGRErr      DeleteDataSource( const char *pszName );
 };
 
-
-#endif /* ndef _OGR_ODS_H_INCLUDED */
+#endif /* ndef OGR_ODS_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/ods/ogrodsdatasource.cpp b/ogr/ogrsf_frmts/ods/ogrodsdatasource.cpp
index 74815ee..4e84acc 100644
--- a/ogr/ogrsf_frmts/ods/ogrodsdatasource.cpp
+++ b/ogr/ogrsf_frmts/ods/ogrodsdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrodsdatasource.cpp 28900 2015-04-14 09:40:34Z rouault $
+ * $Id: ogrodsdatasource.cpp 33199 2016-01-29 15:48:41Z rouault $
  *
  * Project:  ODS Translator
  * Purpose:  Implements OGRODSDataSource class
@@ -34,8 +34,9 @@
 #include "ods_formula.h"
 #include <set>
 
-CPL_CVSID("$Id: ogrodsdatasource.cpp 28900 2015-04-14 09:40:34Z rouault $");
+CPL_CVSID("$Id: ogrodsdatasource.cpp 33199 2016-01-29 15:48:41Z rouault $");
 
+namespace OGRODS {
 
 /************************************************************************/
 /*                          ODSCellEvaluator                            */
@@ -61,29 +62,28 @@ public:
 /************************************************************************/
 
 OGRODSLayer::OGRODSLayer( OGRODSDataSource* poDSIn,
-                            const char * pszName,
-                            int bUpdatedIn) :
-                                OGRMemLayer(pszName, NULL, wkbNone)
-{
-    poDS = poDSIn;
-    bUpdated = bUpdatedIn;
-    bHasHeaderLine = FALSE;
-}
+                          const char * pszName,
+                          bool bUpdatedIn) :
+    OGRMemLayer(pszName, NULL, wkbNone),
+    poDS(poDSIn),
+    bUpdated(CPL_TO_BOOL(bUpdatedIn)),
+    bHasHeaderLine(false)
+{}
 
 /************************************************************************/
 /*                             Updated()                                */
 /************************************************************************/
 
-void OGRODSLayer::SetUpdated(int bUpdatedIn)
+void OGRODSLayer::SetUpdated(bool bUpdatedIn)
 {
     if (bUpdatedIn && !bUpdated && poDS->GetUpdatable())
     {
-        bUpdated = TRUE;
+        bUpdated = true;
         poDS->SetUpdated();
     }
     else if (bUpdated && !bUpdatedIn)
     {
-        bUpdated = FALSE;
+        bUpdated = false;
     }
 }
 
@@ -105,7 +105,7 @@ OGRFeature* OGRODSLayer::GetNextFeature()
 {
     OGRFeature* poFeature = OGRMemLayer::GetNextFeature();
     if (poFeature)
-        poFeature->SetFID(poFeature->GetFID() + 1 + bHasHeaderLine);
+        poFeature->SetFID(poFeature->GetFID() + 1 + (bHasHeaderLine ? 1 : 0));
     return poFeature;
 }
 
@@ -115,7 +115,8 @@ OGRFeature* OGRODSLayer::GetNextFeature()
 
 OGRFeature* OGRODSLayer::GetFeature( GIntBig nFeatureId )
 {
-    OGRFeature* poFeature = OGRMemLayer::GetFeature(nFeatureId - (1 + bHasHeaderLine));
+    OGRFeature* poFeature =
+        OGRMemLayer::GetFeature(nFeatureId - (1 + (bHasHeaderLine ? 1 : 0)));
     if (poFeature)
         poFeature->SetFID(nFeatureId);
     return poFeature;
@@ -132,8 +133,8 @@ OGRErr OGRODSLayer::ISetFeature( OGRFeature *poFeature )
 
     GIntBig nFID = poFeature->GetFID();
     if (nFID != OGRNullFID)
-        poFeature->SetFID(nFID - (1 + bHasHeaderLine));
-    SetUpdated(); 
+        poFeature->SetFID(nFID - (1 + (bHasHeaderLine ? 1 : 0)));
+    SetUpdated();
     OGRErr eErr = OGRMemLayer::ISetFeature(poFeature);
     poFeature->SetFID(nFID);
     return eErr;
@@ -146,30 +147,30 @@ OGRErr OGRODSLayer::ISetFeature( OGRFeature *poFeature )
 OGRErr OGRODSLayer::DeleteFeature( GIntBig nFID )
 {
     SetUpdated();
-    return OGRMemLayer::DeleteFeature(nFID - (1 + bHasHeaderLine));
+    return OGRMemLayer::DeleteFeature(nFID - (1 + (bHasHeaderLine ? 1 : 0)));
 }
 
 /************************************************************************/
 /*                          OGRODSDataSource()                          */
 /************************************************************************/
 
-OGRODSDataSource::OGRODSDataSource()
-
+OGRODSDataSource::OGRODSDataSource() :
+    nFlags(0)
 {
     pszName = NULL;
     fpContent = NULL;
     fpSettings = NULL;
-    bUpdatable = FALSE;
-    bUpdated = FALSE;
-    bAnalysedFile = FALSE;
+    bUpdatable = false;
+    bUpdated = false;
+    bAnalysedFile = false;
 
     nLayers = 0;
     papoLayers = NULL;
 
-    bFirstLineIsHeaders = FALSE;
+    bFirstLineIsHeaders = false;
 
     oParser = NULL;
-    bStopParsing = FALSE;
+    bStopParsing = false;
     nWithoutEventCounter = 0;
     nDataHandlerCounter = 0;
     nStackDepth = 0;
@@ -261,7 +262,7 @@ int OGRODSDataSource::Open( const char * pszFilename,
                             int bUpdatableIn)
 
 {
-    bUpdatable = bUpdatableIn;
+    bUpdatable = CPL_TO_BOOL(bUpdatableIn);
 
     pszName = CPLStrdup( pszFilename );
     fpContent = fpContentIn;
@@ -275,11 +276,11 @@ int OGRODSDataSource::Open( const char * pszFilename,
 /************************************************************************/
 
 int OGRODSDataSource::Create( const char * pszFilename,
-                              CPL_UNUSED char **papszOptions )
+                              char ** /* papszOptions */ )
 {
-    bUpdated = TRUE;
-    bUpdatable = TRUE;
-    bAnalysedFile = TRUE;
+    bUpdated = true;
+    bUpdatable = true;
+    bAnalysedFile = true;
 
     pszName = CPLStrdup( pszFilename );
 
@@ -293,21 +294,23 @@ int OGRODSDataSource::Create( const char * pszFilename,
 static void XMLCALL startElementCbk(void *pUserData, const char *pszName,
                                     const char **ppszAttr)
 {
-    ((OGRODSDataSource*)pUserData)->startElementCbk(pszName, ppszAttr);
+  static_cast<OGRODSDataSource *>(pUserData)->
+      startElementCbk( pszName, ppszAttr );
 }
 
-void OGRODSDataSource::startElementCbk(const char *pszName,
-                                       const char **ppszAttr)
+void OGRODSDataSource::startElementCbk( const char *pszNameIn,
+                                        const char **ppszAttr)
 {
-    if (bStopParsing) return;
+    if( bStopParsing )
+        return;
 
     nWithoutEventCounter = 0;
     switch(stateStack[nStackDepth].eVal)
     {
-        case STATE_DEFAULT: startElementDefault(pszName, ppszAttr); break;
-        case STATE_TABLE:   startElementTable(pszName, ppszAttr); break;
-        case STATE_ROW:     startElementRow(pszName, ppszAttr); break;
-        case STATE_CELL:    startElementCell(pszName, ppszAttr); break;
+        case STATE_DEFAULT: startElementDefault(pszNameIn, ppszAttr); break;
+        case STATE_TABLE:   startElementTable(pszNameIn, ppszAttr); break;
+        case STATE_ROW:     startElementRow(pszNameIn, ppszAttr); break;
+        case STATE_CELL:    startElementCell(pszNameIn, ppszAttr); break;
         case STATE_TEXTP:   break;
         default:            break;
     }
@@ -320,12 +323,13 @@ void OGRODSDataSource::startElementCbk(const char *pszName,
 
 static void XMLCALL endElementCbk(void *pUserData, const char *pszName)
 {
-    ((OGRODSDataSource*)pUserData)->endElementCbk(pszName);
+    static_cast<OGRODSDataSource*>(pUserData)->endElementCbk(pszName);
 }
 
-void OGRODSDataSource::endElementCbk(const char *pszName)
+void OGRODSDataSource::endElementCbk(const char *pszNameIn)
 {
-    if (bStopParsing) return;
+    if (bStopParsing)
+        return;
 
     nWithoutEventCounter = 0;
 
@@ -333,9 +337,9 @@ void OGRODSDataSource::endElementCbk(const char *pszName)
     switch(stateStack[nStackDepth].eVal)
     {
         case STATE_DEFAULT: break;
-        case STATE_TABLE:   endElementTable(pszName); break;
-        case STATE_ROW:     endElementRow(pszName); break;
-        case STATE_CELL:    endElementCell(pszName); break;
+        case STATE_TABLE:   endElementTable(pszNameIn); break;
+        case STATE_ROW:     endElementRow(pszNameIn); break;
+        case STATE_CELL:    endElementCell(pszNameIn); break;
         case STATE_TEXTP:   break;
         default:            break;
     }
@@ -350,12 +354,13 @@ void OGRODSDataSource::endElementCbk(const char *pszName)
 
 static void XMLCALL dataHandlerCbk(void *pUserData, const char *data, int nLen)
 {
-    ((OGRODSDataSource*)pUserData)->dataHandlerCbk(data, nLen);
+    static_cast<OGRODSDataSource*>(pUserData)->dataHandlerCbk(data, nLen);
 }
 
 void OGRODSDataSource::dataHandlerCbk(const char *data, int nLen)
 {
-    if (bStopParsing) return;
+    if (bStopParsing)
+        return;
 
     nDataHandlerCounter ++;
     if (nDataHandlerCounter >= BUFSIZ)
@@ -363,7 +368,7 @@ void OGRODSDataSource::dataHandlerCbk(const char *data, int nLen)
         CPLError(CE_Failure, CPLE_AppDefined,
                  "File probably corrupted (million laugh pattern)");
         XML_StopParser(oParser, XML_FALSE);
-        bStopParsing = TRUE;
+        bStopParsing = true;
         return;
     }
 
@@ -375,7 +380,9 @@ void OGRODSDataSource::dataHandlerCbk(const char *data, int nLen)
         case STATE_TABLE:   break;
         case STATE_ROW:     break;
         case STATE_CELL:    break;
-        case STATE_TEXTP:   dataHandlerTextP(data, nLen);
+        case STATE_TEXTP:
+            dataHandlerTextP(data, nLen);
+            break;
         default:            break;
     }
 }
@@ -388,7 +395,7 @@ void OGRODSDataSource::PushState(HandlerStateEnum eVal)
 {
     if (nStackDepth + 1 == STACK_SIZE)
     {
-        bStopParsing = TRUE;
+        bStopParsing = true;
         return;
     }
     nStackDepth ++;
@@ -430,7 +437,7 @@ OGRFieldType OGRODSDataSource::GetOGRFieldType(const char* pszValue,
         if (CPLGetValueType(pszValue) == CPL_VALUE_INTEGER)
         {
             GIntBig nVal = CPLAtoGIntBig(pszValue);
-            if( (GIntBig)(int)nVal != nVal )
+            if( !CPL_INT64_FITS_ON_INT32(nVal) )
                 return OFTInteger64;
             else
                 return OFTInteger;
@@ -471,20 +478,20 @@ static void SetField(OGRFeature* poFeature,
     {
         int nHour, nHourRepeated, nMinute, nSecond;
         char c;
-        if (strncmp(pszValue, "PT", 2) == 0 &&
+        if (STARTS_WITH(pszValue, "PT") &&
             sscanf(pszValue + 2, "%02d%c%02d%c%02d%c",
                    &nHour, &c, &nMinute, &c, &nSecond, &c) == 6)
         {
-            poFeature->SetField(i, 0, 0, 0, nHour, nMinute, nSecond, 0);
+            poFeature->SetField(i, 0, 0, 0, nHour, nMinute, static_cast<float>(nSecond), 0);
         }
         /* bug with kspread 2.1.2 ? */
         /* ex PT121234M56S */
-        else if (strncmp(pszValue, "PT", 2) == 0 &&
+        else if (STARTS_WITH(pszValue, "PT") &&
                  sscanf(pszValue + 2, "%02d%02d%02d%c%02d%c",
                         &nHour, &nHourRepeated, &nMinute, &c, &nSecond, &c) == 6 &&
                  nHour == nHourRepeated)
         {
-            poFeature->SetField(i, 0, 0, 0, nHour, nMinute, nSecond, 0);
+            poFeature->SetField(i, 0, 0, 0, nHour, nMinute, static_cast<float>(nSecond), 0);
         }
     }
     else if (eType == OFTDate || eType == OFTDateTime)
@@ -536,15 +543,15 @@ void OGRODSDataSource::DetectHeaderLine()
     }
 
     const char* pszODSHeaders = CPLGetConfigOption("OGR_ODS_HEADERS", "");
-    bFirstLineIsHeaders = FALSE;
+    bFirstLineIsHeaders = false;
     if (EQUAL(pszODSHeaders, "FORCE"))
-        bFirstLineIsHeaders = TRUE;
+        bFirstLineIsHeaders = true;
     else if (EQUAL(pszODSHeaders, "DISABLE"))
-        bFirstLineIsHeaders = FALSE;
+        bFirstLineIsHeaders = false;
     else if (osSetLayerHasSplitter.find(poCurLayer->GetName()) !=
              osSetLayerHasSplitter.end())
     {
-        bFirstLineIsHeaders = TRUE;
+        bFirstLineIsHeaders = true;
     }
     else if (bHeaderLineCandidate &&
              apoFirstLineTypes.size() != 0 &&
@@ -552,7 +559,7 @@ void OGRODSDataSource::DetectHeaderLine()
              nCountTextOnCurLine != apoFirstLineTypes.size() &&
              nCountNonEmptyOnCurLine != 0)
     {
-        bFirstLineIsHeaders = TRUE;
+        bFirstLineIsHeaders = true;
     }
     CPLDebug("ODS", "%s %s",
              poCurLayer->GetName(),
@@ -563,10 +570,10 @@ void OGRODSDataSource::DetectHeaderLine()
 /*                          startElementDefault()                       */
 /************************************************************************/
 
-void OGRODSDataSource::startElementDefault(const char *pszName,
+void OGRODSDataSource::startElementDefault(const char *pszNameIn,
                                            const char **ppszAttr)
 {
-    if (strcmp(pszName, "table:table") == 0)
+    if (strcmp(pszNameIn, "table:table") == 0)
     {
         const char* pszTableName =
             GetAttributeValue(ppszAttr, "table:name", "unnamed");
@@ -588,10 +595,10 @@ void OGRODSDataSource::startElementDefault(const char *pszName,
 /*                          startElementTable()                        */
 /************************************************************************/
 
-void OGRODSDataSource::startElementTable(const char *pszName,
+void OGRODSDataSource::startElementTable(const char *pszNameIn,
                                          const char **ppszAttr)
 {
-    if (strcmp(pszName, "table:table-row") == 0 && !bEndTableParsing)
+    if (strcmp(pszNameIn, "table:table-row") == 0 && !bEndTableParsing)
     {
         nRowsRepeated = atoi(
             GetAttributeValue(ppszAttr, "table:number-rows-repeated", "1"));
@@ -614,11 +621,12 @@ void OGRODSDataSource::startElementTable(const char *pszName,
 /*                           endElementTable()                          */
 /************************************************************************/
 
-void OGRODSDataSource::endElementTable(CPL_UNUSED const char *pszName)
+void OGRODSDataSource::endElementTable( CPL_UNUSED /* in non-DEBUG*/ const char * pszNameIn )
 {
     if (stateStack[nStackDepth].nBeginDepth == nDepth)
     {
-        CPLAssert(strcmp(pszName, "table:table") == 0);
+        // Only use of pszNameIn.
+        CPLAssert(strcmp(pszNameIn, "table:table") == 0);
 
         if (nCurLine == 0 ||
             (nCurLine == 1 && apoFirstLineValues.size() == 0))
@@ -644,9 +652,9 @@ void OGRODSDataSource::endElementTable(CPL_UNUSED const char *pszName)
             OGRFeature* poFeature = new OGRFeature(poCurLayer->GetLayerDefn());
             for(i = 0; i < apoFirstLineValues.size(); i++)
             {
-                SetField(poFeature, i, apoFirstLineValues[i].c_str());
+                SetField(poFeature, static_cast<int>(i), apoFirstLineValues[i].c_str());
             }
-            poCurLayer->CreateFeature(poFeature);
+            CPL_IGNORE_RET_VAL(poCurLayer->CreateFeature(poFeature));
             delete poFeature;
         }
 
@@ -654,7 +662,7 @@ void OGRODSDataSource::endElementTable(CPL_UNUSED const char *pszName)
         {
             OGRFeature* poFeature;
 
-            if (CSLTestBoolean(CPLGetConfigOption("ODS_RESOLVE_FORMULAS", "YES")))
+            if( CPLTestBool(CPLGetConfigOption("ODS_RESOLVE_FORMULAS", "YES")) )
             {
                 poCurLayer->ResetReading();
 
@@ -668,7 +676,7 @@ void OGRODSDataSource::endElementTable(CPL_UNUSED const char *pszName)
                             poFeature->GetFieldDefnRef(i)->GetType() == OFTString)
                         {
                             const char* pszVal = poFeature->GetFieldAsString(i);
-                            if (strncmp(pszVal, "of:=", 4) == 0)
+                            if (STARTS_WITH(pszVal, "of:="))
                             {
                                 ODSCellEvaluator oCellEvaluator(poCurLayer);
                                 oCellEvaluator.Evaluate(nRow, i);
@@ -684,9 +692,10 @@ void OGRODSDataSource::endElementTable(CPL_UNUSED const char *pszName)
 
             poCurLayer->ResetReading();
 
-            ((OGRMemLayer*)poCurLayer)->SetUpdatable(bUpdatable);
-            ((OGRMemLayer*)poCurLayer)->SetAdvertizeUTF8(TRUE);
-            ((OGRODSLayer*)poCurLayer)->SetUpdated(FALSE);
+            reinterpret_cast<OGRMemLayer*>(poCurLayer)->
+                SetUpdatable(bUpdatable);
+            reinterpret_cast<OGRMemLayer*>(poCurLayer)->SetAdvertizeUTF8(true);
+            reinterpret_cast<OGRODSLayer*>(poCurLayer)->SetUpdated(false);
         }
 
         poCurLayer = NULL;
@@ -697,10 +706,10 @@ void OGRODSDataSource::endElementTable(CPL_UNUSED const char *pszName)
 /*                            startElementRow()                         */
 /************************************************************************/
 
-void OGRODSDataSource::startElementRow(const char *pszName,
+void OGRODSDataSource::startElementRow(const char *pszNameIn,
                                        const char **ppszAttr)
 {
-    if (strcmp(pszName, "table:table-cell") == 0)
+    if (strcmp(pszNameIn, "table:table-cell") == 0)
     {
         PushState(STATE_CELL);
 
@@ -720,7 +729,7 @@ void OGRODSDataSource::startElementRow(const char *pszName,
         }
 
         const char* pszFormula = GetAttributeValue(ppszAttr, "table:formula", NULL);
-        if (pszFormula && strncmp(pszFormula, "of:=", 4) == 0)
+        if (pszFormula && STARTS_WITH(pszFormula, "of:="))
         {
             osFormula = pszFormula;
             if (osValueType.size() == 0)
@@ -732,7 +741,7 @@ void OGRODSDataSource::startElementRow(const char *pszName,
         nCellsRepeated = atoi(
             GetAttributeValue(ppszAttr, "table:number-columns-repeated", "1"));
     }
-    else if (strcmp(pszName, "table:covered-table-cell") == 0)
+    else if (strcmp(pszNameIn, "table:covered-table-cell") == 0)
     {
         /* Merged cell */
         apoCurLineValues.push_back("");
@@ -746,11 +755,11 @@ void OGRODSDataSource::startElementRow(const char *pszName,
 /*                            endElementRow()                           */
 /************************************************************************/
 
-void OGRODSDataSource::endElementRow(CPL_UNUSED const char *pszName)
+void OGRODSDataSource::endElementRow( CPL_UNUSED /*in non-DEBUG*/ const char * pszNameIn )
 {
     if (stateStack[nStackDepth].nBeginDepth == nDepth)
     {
-        CPLAssert(strcmp(pszName, "table:table-row") == 0);
+        CPLAssert(strcmp(pszNameIn, "table:table-row") == 0);
 
         OGRFeature* poFeature;
         size_t i;
@@ -782,7 +791,7 @@ void OGRODSDataSource::endElementRow(CPL_UNUSED const char *pszName)
             for(i = 0; i < (size_t)nEmptyRowsAccumulated; i++)
             {
                 poFeature = new OGRFeature(poCurLayer->GetLayerDefn());
-                poCurLayer->CreateFeature(poFeature);
+                CPL_IGNORE_RET_VAL(poCurLayer->CreateFeature(poFeature));
                 delete poFeature;
             }
             nCurLine += nEmptyRowsAccumulated;
@@ -845,9 +854,9 @@ void OGRODSDataSource::endElementRow(CPL_UNUSED const char *pszName)
                 poFeature = new OGRFeature(poCurLayer->GetLayerDefn());
                 for(i = 0; i < apoFirstLineValues.size(); i++)
                 {
-                    SetField(poFeature, i, apoFirstLineValues[i].c_str());
+                    SetField(poFeature, static_cast<int>(i), apoFirstLineValues[i].c_str());
                 }
-                poCurLayer->CreateFeature(poFeature);
+                CPL_IGNORE_RET_VAL(poCurLayer->CreateFeature(poFeature));
                 delete poFeature;
             }
         }
@@ -858,15 +867,16 @@ void OGRODSDataSource::endElementRow(CPL_UNUSED const char *pszName)
             if (apoCurLineValues.size() >
                 (size_t)poCurLayer->GetLayerDefn()->GetFieldCount())
             {
-                for(i = (size_t)poCurLayer->GetLayerDefn()->GetFieldCount();
-                    i < apoCurLineValues.size();
-                    i++)
+                for( i = static_cast<size_t>(
+                         poCurLayer->GetLayerDefn()->GetFieldCount());
+                     i < apoCurLineValues.size();
+                     i++ )
                 {
                     const char* pszFieldName =
-                        CPLSPrintf("Field%d", (int)i + 1);
-                    OGRFieldType eType = GetOGRFieldType(
-                                                apoCurLineValues[i].c_str(),
-                                                apoCurLineTypes[i].c_str());
+                        CPLSPrintf("Field%d", static_cast<int>(i) + 1);
+                    const OGRFieldType eType = GetOGRFieldType(
+                        apoCurLineValues[i].c_str(),
+                        apoCurLineTypes[i].c_str() );
                     OGRFieldDefn oFieldDefn(pszFieldName, eType);
                     poCurLayer->CreateField(&oFieldDefn);
                 }
@@ -879,40 +889,50 @@ void OGRODSDataSource::endElementRow(CPL_UNUSED const char *pszName)
                 {
                     if (apoCurLineValues[i].size())
                     {
-                        OGRFieldType eValType = GetOGRFieldType(
-                                                apoCurLineValues[i].c_str(),
-                                                apoCurLineTypes[i].c_str());
-                        OGRFieldType eFieldType =
-                            poCurLayer->GetLayerDefn()->GetFieldDefn(i)->GetType();
+                        const OGRFieldType eValType = GetOGRFieldType(
+                            apoCurLineValues[i].c_str(),
+                            apoCurLineTypes[i].c_str());
+                        const OGRFieldType eFieldType =
+                            poCurLayer->GetLayerDefn()->GetFieldDefn(
+                                static_cast<int>(i))->GetType();
                         if (eFieldType == OFTDateTime &&
                             (eValType == OFTDate || eValType == OFTTime) )
                         {
                             /* ok */
                         }
-                        else if (eFieldType == OFTReal && (eValType == OFTInteger || eValType == OFTInteger64))
+                        else if ( eFieldType == OFTReal &&
+                                  (eValType == OFTInteger ||
+                                   eValType == OFTInteger64))
                         {
                            /* ok */;
                         }
-                        else if (eFieldType == OFTInteger64 && eValType == OFTInteger )
+                        else if ( eFieldType == OFTInteger64 &&
+                                  eValType == OFTInteger )
                         {
                             /* ok */;
                         }
-                        else if (eFieldType != OFTString && eValType != eFieldType)
+                        else if ( eFieldType != OFTString &&
+                                  eValType != eFieldType)
                         {
                             OGRFieldDefn oNewFieldDefn(
-                                poCurLayer->GetLayerDefn()->GetFieldDefn(i));
-                            if ((eFieldType == OFTDate || eFieldType == OFTTime) &&
-                                   eValType == OFTDateTime)
+                                poCurLayer->GetLayerDefn()->GetFieldDefn(
+                                    static_cast<int>(i)));
+                            if( ( eFieldType == OFTDate ||
+                                  eFieldType == OFTTime) &&
+                                eValType == OFTDateTime )
                                 oNewFieldDefn.SetType(OFTDateTime);
-                            else if ((eFieldType == OFTInteger || eFieldType == OFTInteger64) &&
+                            else if( (eFieldType == OFTInteger ||
+                                      eFieldType == OFTInteger64 ) &&
                                      eValType == OFTReal)
                                 oNewFieldDefn.SetType(OFTReal);
-                            else if( eFieldType == OFTInteger && eValType == OFTInteger64 )
+                            else if( eFieldType == OFTInteger &&
+                                     eValType == OFTInteger64 )
                                 oNewFieldDefn.SetType(OFTInteger64);
                             else
                                 oNewFieldDefn.SetType(OFTString);
-                            poCurLayer->AlterFieldDefn(i, &oNewFieldDefn,
-                                                       ALTER_TYPE_FLAG);
+                            poCurLayer->AlterFieldDefn(
+                                static_cast<int>(i), &oNewFieldDefn,
+                                ALTER_TYPE_FLAG);
                         }
                     }
                 }
@@ -924,9 +944,10 @@ void OGRODSDataSource::endElementRow(CPL_UNUSED const char *pszName)
                 poFeature = new OGRFeature(poCurLayer->GetLayerDefn());
                 for(i = 0; i < apoCurLineValues.size(); i++)
                 {
-                    SetField(poFeature, i, apoCurLineValues[i].c_str());
+                    SetField( poFeature, static_cast<int>(i),
+                              apoCurLineValues[i].c_str() );
                 }
-                poCurLayer->CreateFeature(poFeature);
+                CPL_IGNORE_RET_VAL(poCurLayer->CreateFeature(poFeature));
                 delete poFeature;
             }
         }
@@ -939,10 +960,10 @@ void OGRODSDataSource::endElementRow(CPL_UNUSED const char *pszName)
 /*                           startElementCell()                         */
 /************************************************************************/
 
-void OGRODSDataSource::startElementCell(const char *pszName,
-                                        CPL_UNUSED const char **ppszAttr)
+void OGRODSDataSource::startElementCell(const char *pszNameIn,
+                                        const char ** /*ppszAttr*/)
 {
-    if (osValue.size() == 0 && strcmp(pszName, "text:p") == 0)
+    if (osValue.size() == 0 && strcmp(pszNameIn, "text:p") == 0)
     {
         PushState(STATE_TEXTP);
     }
@@ -952,11 +973,11 @@ void OGRODSDataSource::startElementCell(const char *pszName,
 /*                            endElementCell()                          */
 /************************************************************************/
 
-void OGRODSDataSource::endElementCell(CPL_UNUSED const char *pszName)
+void OGRODSDataSource::endElementCell( CPL_UNUSED /*in non-DEBUG*/ const char * pszNameIn )
 {
     if (stateStack[nStackDepth].nBeginDepth == nDepth)
     {
-        CPLAssert(strcmp(pszName, "table:table-cell") == 0);
+        CPLAssert(strcmp(pszNameIn, "table:table-cell") == 0);
 
         for(int i = 0; i < nCellsRepeated; i++)
         {
@@ -989,19 +1010,20 @@ void OGRODSDataSource::AnalyseFile()
     if (bAnalysedFile)
         return;
 
-    bAnalysedFile = TRUE;
+    bAnalysedFile = true;
 
     AnalyseSettings();
 
     oParser = OGRCreateExpatXMLParser();
-    XML_SetElementHandler(oParser, ::startElementCbk, ::endElementCbk);
-    XML_SetCharacterDataHandler(oParser, ::dataHandlerCbk);
+    XML_SetElementHandler( oParser, OGRODS::startElementCbk,
+                           OGRODS::endElementCbk);
+    XML_SetCharacterDataHandler(oParser, OGRODS::dataHandlerCbk);
     XML_SetUserData(oParser, this);
 
     nDepth = 0;
     nStackDepth = 0;
     stateStack[0].nBeginDepth = 0;
-    bStopParsing = FALSE;
+    bStopParsing = false;
     nWithoutEventCounter = 0;
 
     VSIFSeekL( fpContent, 0, SEEK_SET );
@@ -1012,16 +1034,18 @@ void OGRODSDataSource::AnalyseFile()
     {
         nDataHandlerCounter = 0;
         unsigned int nLen =
-            (unsigned int)VSIFReadL( aBuf, 1, sizeof(aBuf), fpContent );
+            static_cast<unsigned int>(
+                VSIFReadL( aBuf, 1, sizeof(aBuf), fpContent ) );
         nDone = VSIFEofL(fpContent);
         if (XML_Parse(oParser, aBuf, nLen, nDone) == XML_STATUS_ERROR)
         {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "XML parsing of ODS file failed : %s at line %d, column %d",
-                     XML_ErrorString(XML_GetErrorCode(oParser)),
-                     (int)XML_GetCurrentLineNumber(oParser),
-                     (int)XML_GetCurrentColumnNumber(oParser));
-            bStopParsing = TRUE;
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "XML parsing of ODS file failed : %s at line %d, "
+                      "column %d",
+                      XML_ErrorString(XML_GetErrorCode(oParser)),
+                      static_cast<int>(XML_GetCurrentLineNumber(oParser)),
+                      static_cast<int>(XML_GetCurrentColumnNumber(oParser)));
+            bStopParsing = true;
         }
         nWithoutEventCounter ++;
     } while (!nDone && !bStopParsing && nWithoutEventCounter < 10);
@@ -1033,41 +1057,45 @@ void OGRODSDataSource::AnalyseFile()
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Too much data inside one element. File probably corrupted");
-        bStopParsing = TRUE;
+        bStopParsing = true;
     }
 
     VSIFCloseL(fpContent);
     fpContent = NULL;
 
-    bUpdated = FALSE;
+    bUpdated = false;
 }
 
 /************************************************************************/
 /*                        startElementStylesCbk()                       */
 /************************************************************************/
 
-static void XMLCALL startElementStylesCbk(void *pUserData, const char *pszName,
-                                    const char **ppszAttr)
+static void XMLCALL startElementStylesCbk( void *pUserData, const char *pszName,
+                                           const char **ppszAttr)
 {
-    ((OGRODSDataSource*)pUserData)->startElementStylesCbk(pszName, ppszAttr);
+    static_cast<OGRODSDataSource*>(pUserData)->
+        startElementStylesCbk( pszName, ppszAttr );
 }
 
-void OGRODSDataSource::startElementStylesCbk(const char *pszName,
-                                             const char **ppszAttr)
+void OGRODSDataSource::startElementStylesCbk( const char *pszNameIn,
+                                              const char **ppszAttr)
 {
-    if (bStopParsing) return;
+    if (bStopParsing)
+        return;
 
     nWithoutEventCounter = 0;
 
     if (nStackDepth == 0 &&
-        strcmp(pszName, "config:config-item-map-named") == 0 &&
+        strcmp(pszNameIn, "config:config-item-map-named") == 0 &&
         strcmp(GetAttributeValue(ppszAttr, "config:name", ""), "Tables") == 0)
     {
         stateStack[++nStackDepth].nBeginDepth = nDepth;
     }
-    else if (nStackDepth == 1 && strcmp(pszName, "config:config-item-map-entry") == 0)
+    else if( nStackDepth == 1 &&
+             strcmp(pszNameIn, "config:config-item-map-entry") == 0 )
     {
-        const char* pszTableName = GetAttributeValue(ppszAttr, "config:name", NULL);
+        const char* pszTableName =
+            GetAttributeValue(ppszAttr, "config:name", NULL);
         if (pszTableName)
         {
             osCurrentConfigTableName = pszTableName;
@@ -1075,9 +1103,10 @@ void OGRODSDataSource::startElementStylesCbk(const char *pszName,
             stateStack[++nStackDepth].nBeginDepth = nDepth;
         }
     }
-    else if (nStackDepth == 2 && strcmp(pszName, "config:config-item") == 0)
+    else if (nStackDepth == 2 && strcmp(pszNameIn, "config:config-item") == 0)
     {
-        const char* pszConfigName = GetAttributeValue(ppszAttr, "config:name", NULL);
+        const char* pszConfigName =
+            GetAttributeValue(ppszAttr, "config:name", NULL);
         if (pszConfigName)
         {
             osConfigName = pszConfigName;
@@ -1095,12 +1124,13 @@ void OGRODSDataSource::startElementStylesCbk(const char *pszName,
 
 static void XMLCALL endElementStylesCbk(void *pUserData, const char *pszName)
 {
-    ((OGRODSDataSource*)pUserData)->endElementStylesCbk(pszName);
+    static_cast<OGRODSDataSource*>(pUserData)->endElementStylesCbk(pszName);
 }
 
-void OGRODSDataSource::endElementStylesCbk(CPL_UNUSED const char *pszName)
+void OGRODSDataSource::endElementStylesCbk(const char * /*pszName*/)
 {
-    if (bStopParsing) return;
+    if (bStopParsing)
+        return;
 
     nWithoutEventCounter = 0;
     nDepth--;
@@ -1127,22 +1157,24 @@ void OGRODSDataSource::endElementStylesCbk(CPL_UNUSED const char *pszName)
 /*                         dataHandlerStylesCbk()                       */
 /************************************************************************/
 
-static void XMLCALL dataHandlerStylesCbk(void *pUserData, const char *data, int nLen)
+static void XMLCALL dataHandlerStylesCbk( void *pUserData, const char *data,
+                                          int nLen )
 {
-    ((OGRODSDataSource*)pUserData)->dataHandlerStylesCbk(data, nLen);
+  static_cast<OGRODSDataSource *>(pUserData)->dataHandlerStylesCbk(data, nLen);
 }
 
 void OGRODSDataSource::dataHandlerStylesCbk(const char *data, int nLen)
 {
-    if (bStopParsing) return;
+    if (bStopParsing)
+        return;
 
     nDataHandlerCounter ++;
     if (nDataHandlerCounter >= BUFSIZ)
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "File probably corrupted (million laugh pattern)");
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "File probably corrupted (million laugh pattern)");
         XML_StopParser(oParser, XML_FALSE);
-        bStopParsing = TRUE;
+        bStopParsing = true;
         return;
     }
 
@@ -1167,13 +1199,14 @@ void OGRODSDataSource::AnalyseSettings()
         return;
 
     oParser = OGRCreateExpatXMLParser();
-    XML_SetElementHandler(oParser, ::startElementStylesCbk, ::endElementStylesCbk);
-    XML_SetCharacterDataHandler(oParser, ::dataHandlerStylesCbk);
+    XML_SetElementHandler( oParser, OGRODS::startElementStylesCbk,
+                           OGRODS::endElementStylesCbk );
+    XML_SetCharacterDataHandler(oParser, OGRODS::dataHandlerStylesCbk);
     XML_SetUserData(oParser, this);
 
     nDepth = 0;
     nStackDepth = 0;
-    bStopParsing = FALSE;
+    bStopParsing = false;
     nWithoutEventCounter = 0;
 
     VSIFSeekL( fpSettings, 0, SEEK_SET );
@@ -1193,7 +1226,7 @@ void OGRODSDataSource::AnalyseSettings()
                      XML_ErrorString(XML_GetErrorCode(oParser)),
                      (int)XML_GetCurrentLineNumber(oParser),
                      (int)XML_GetCurrentColumnNumber(oParser));
-            bStopParsing = TRUE;
+            bStopParsing = true;
         }
         nWithoutEventCounter ++;
     } while (!nDone && !bStopParsing && nWithoutEventCounter < 10);
@@ -1205,7 +1238,7 @@ void OGRODSDataSource::AnalyseSettings()
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Too much data inside one element. File probably corrupted");
-        bStopParsing = TRUE;
+        bStopParsing = true;
     }
 
     VSIFCloseL(fpSettings);
@@ -1218,8 +1251,8 @@ void OGRODSDataSource::AnalyseSettings()
 
 OGRLayer *
 OGRODSDataSource::ICreateLayer( const char * pszLayerName,
-                                CPL_UNUSED OGRSpatialReference *poSRS,
-                                CPL_UNUSED OGRwkbGeometryType eType,
+                                OGRSpatialReference * /* poSRS */,
+                                OGRwkbGeometryType /* eType */,
                                 char ** papszOptions )
 {
 /* -------------------------------------------------------------------- */
@@ -1241,9 +1274,7 @@ OGRODSDataSource::ICreateLayer( const char * pszLayerName,
 /*      Do we already have this layer?  If so, should we blow it        */
 /*      away?                                                           */
 /* -------------------------------------------------------------------- */
-    int iLayer;
-
-    for( iLayer = 0; iLayer < nLayers; iLayer++ )
+    for( int iLayer = 0; iLayer < nLayers; iLayer++ )
     {
         if( EQUAL(pszLayerName,papoLayers[iLayer]->GetName()) )
         {
@@ -1269,11 +1300,12 @@ OGRODSDataSource::ICreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
     OGRLayer* poLayer = new OGRODSLayer(this, pszLayerName, TRUE);
 
-    papoLayers = (OGRLayer**)CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
+    papoLayers = static_cast<OGRLayer**>(
+        CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*)) );
     papoLayers[nLayers] = poLayer;
     nLayers ++;
 
-    bUpdated = TRUE;
+    bUpdated = true;
 
     return poLayer;
 }
@@ -1285,8 +1317,6 @@ OGRODSDataSource::ICreateLayer( const char * pszLayerName,
 void OGRODSDataSource::DeleteLayer( const char *pszLayerName )
 
 {
-    int iLayer;
-
 /* -------------------------------------------------------------------- */
 /*      Verify we are in update mode.                                   */
 /* -------------------------------------------------------------------- */
@@ -1303,7 +1333,8 @@ void OGRODSDataSource::DeleteLayer( const char *pszLayerName )
 /* -------------------------------------------------------------------- */
 /*      Try to find layer.                                              */
 /* -------------------------------------------------------------------- */
-    for( iLayer = 0; iLayer < nLayers; iLayer++ )
+    int iLayer = 0;
+    for( ; iLayer < nLayers; iLayer++ )
     {
         if( EQUAL(pszLayerName,papoLayers[iLayer]->GetName()) )
             break;
@@ -1346,7 +1377,7 @@ OGRErr OGRODSDataSource::DeleteLayer(int iLayer)
              sizeof(void *) * (nLayers - iLayer - 1) );
     nLayers--;
 
-    bUpdated = TRUE;
+    bUpdated = true;
 
     return OGRERR_NONE;
 }
@@ -1355,16 +1386,16 @@ OGRErr OGRODSDataSource::DeleteLayer(int iLayer)
 /*                           HasHeaderLine()                            */
 /************************************************************************/
 
-static int HasHeaderLine(OGRLayer* poLayer)
+static bool HasHeaderLine(OGRLayer* poLayer)
 {
     OGRFeatureDefn* poFDefn = poLayer->GetLayerDefn();
-    int bHasHeaders = FALSE;
+    bool bHasHeaders = false;
 
     for(int j=0;j<poFDefn->GetFieldCount();j++)
     {
         if (strcmp(poFDefn->GetFieldDefn(j)->GetNameRef(),
                     CPLSPrintf("Field%d", j+1)) != 0)
-            bHasHeaders = TRUE;
+            bHasHeaders = true;
     }
 
     return bHasHeaders;
@@ -1376,20 +1407,19 @@ static int HasHeaderLine(OGRLayer* poLayer)
 
 static void WriteLayer(VSILFILE* fp, OGRLayer* poLayer)
 {
-    int j;
     const char* pszLayerName = poLayer->GetName();
     char* pszXML = OGRGetXML_UTF8_EscapedString(pszLayerName);
     VSIFPrintfL(fp, "<table:table table:name=\"%s\">\n", pszXML);
     CPLFree(pszXML);
-    
+
     poLayer->ResetReading();
 
     OGRFeature* poFeature = poLayer->GetNextFeature();
 
     OGRFeatureDefn* poFDefn = poLayer->GetLayerDefn();
-    int bHasHeaders = HasHeaderLine(poLayer);
+    const bool bHasHeaders = HasHeaderLine(poLayer);
 
-    for(j=0;j<poFDefn->GetFieldCount();j++)
+    for( int j=0; j<poFDefn->GetFieldCount(); j++ )
     {
         int nStyleNumber = 1;
         if (poFDefn->GetFieldDefn(j)->GetType() == OFTDateTime)
@@ -1402,11 +1432,12 @@ static void WriteLayer(VSILFILE* fp, OGRLayer* poLayer)
     if (bHasHeaders && poFeature != NULL)
     {
         VSIFPrintfL(fp, "<table:table-row>\n");
-        for(j=0;j<poFDefn->GetFieldCount();j++)
+        for( int j=0; j<poFDefn->GetFieldCount(); j++)
         {
             const char* pszVal = poFDefn->GetFieldDefn(j)->GetNameRef();
 
-            VSIFPrintfL(fp, "<table:table-cell office:value-type=\"string\">\n");
+            VSIFPrintfL(
+                 fp, "<table:table-cell office:value-type=\"string\">\n" );
             pszXML = OGRGetXML_UTF8_EscapedString(pszVal);
             VSIFPrintfL(fp, "<text:p>%s</text:p>\n", pszXML);
             CPLFree(pszXML);
@@ -1418,78 +1449,119 @@ static void WriteLayer(VSILFILE* fp, OGRLayer* poLayer)
     while(poFeature != NULL)
     {
         VSIFPrintfL(fp, "<table:table-row>\n");
-        for(j=0;j<poFeature->GetFieldCount();j++)
+        for( int j=0; j<poFeature->GetFieldCount(); j++ )
         {
             if (poFeature->IsFieldSet(j))
             {
-                OGRFieldType eType = poFDefn->GetFieldDefn(j)->GetType();
+                const OGRFieldType eType = poFDefn->GetFieldDefn(j)->GetType();
 
                 if (eType == OFTReal)
                 {
-                    VSIFPrintfL(fp, "<table:table-cell office:value-type=\"float\" "
-                                "office:value=\"%.16f\"/>\n",
-                                poFeature->GetFieldAsDouble(j));
+                    VSIFPrintfL(
+                        fp,
+                        "<table:table-cell office:value-type=\"float\" "
+                        "office:value=\"%.16f\"/>\n",
+                        poFeature->GetFieldAsDouble(j) );
                 }
                 else if (eType == OFTInteger)
                 {
-                    VSIFPrintfL(fp, "<table:table-cell office:value-type=\"float\" "
-                                "office:value=\"%d\"/>\n",
-                                poFeature->GetFieldAsInteger(j));
+                    VSIFPrintfL(
+                         fp, "<table:table-cell office:value-type=\"float\" "
+                         "office:value=\"%d\"/>\n",
+                         poFeature->GetFieldAsInteger(j));
                 }
                 else if (eType == OFTInteger64)
                 {
-                    VSIFPrintfL(fp, "<table:table-cell office:value-type=\"float\" "
-                                "office:value=\"" CPL_FRMT_GIB "\"/>\n",
-                                poFeature->GetFieldAsInteger64(j));
+                    VSIFPrintfL(
+                         fp, "<table:table-cell office:value-type=\"float\" "
+                         "office:value=\"" CPL_FRMT_GIB "\"/>\n",
+                         poFeature->GetFieldAsInteger64(j));
                 }
                 else if (eType == OFTDateTime)
                 {
-                    int nYear, nMonth, nDay, nHour, nMinute, nTZFlag;
+                    int nYear;
+                    int  nMonth;
+                    int  nDay;
+                    int  nHour;
+                    int  nMinute;
+                    int  nTZFlag;
                     float fSecond;
-                    poFeature->GetFieldAsDateTime(j, &nYear, &nMonth, &nDay,
-                                                    &nHour, &nMinute, &fSecond, &nTZFlag );
+                    poFeature->GetFieldAsDateTime(
+                        j, &nYear, &nMonth, &nDay,
+                        &nHour, &nMinute, &fSecond, &nTZFlag );
                     if( OGR_GET_MS(fSecond) )
                     {
-                        VSIFPrintfL(fp, "<table:table-cell table:style-name=\"stDateTimeMilliseconds\" "
-                                    "office:value-type=\"date\" "
-                                    "office:date-value=\"%04d-%02d-%02dT%02d:%02d:%06.3f\">\n",
-                                    nYear, nMonth, nDay, nHour, nMinute, fSecond);
-                        VSIFPrintfL(fp, "<text:p>%02d/%02d/%04d %02d:%02d:%06.3f</text:p>\n",
-                                    nDay, nMonth, nYear, nHour, nMinute, fSecond);
+                        VSIFPrintfL(
+                            fp,
+                            "<table:table-cell "
+                            "table:style-name=\"stDateTimeMilliseconds\" "
+                            "office:value-type=\"date\" "
+                            "office:date-value="
+                            "\"%04d-%02d-%02dT%02d:%02d:%06.3f\">\n",
+                            nYear, nMonth, nDay, nHour, nMinute, fSecond );
+                        VSIFPrintfL(
+                            fp,
+                            "<text:p>%02d/%02d/%04d "
+                            "%02d:%02d:%06.3f</text:p>\n",
+                            nDay, nMonth, nYear, nHour, nMinute, fSecond );
                     }
                     else
                     {
-                        VSIFPrintfL(fp, "<table:table-cell table:style-name=\"stDateTime\" "
-                                    "office:value-type=\"date\" "
-                                    "office:date-value=\"%04d-%02d-%02dT%02d:%02d:%02d\">\n",
-                                    nYear, nMonth, nDay, nHour, nMinute, (int)fSecond);
-                        VSIFPrintfL(fp, "<text:p>%02d/%02d/%04d %02d:%02d:%02d</text:p>\n",
-                                    nDay, nMonth, nYear, nHour, nMinute, (int)fSecond);
+                        VSIFPrintfL(
+                            fp,
+                            "<table:table-cell "
+                            "table:style-name=\"stDateTime\" "
+                            "office:value-type=\"date\" "
+                            "office:date-value="
+                            "\"%04d-%02d-%02dT%02d:%02d:%02d\">\n",
+                            nYear, nMonth, nDay, nHour, nMinute,
+                            static_cast<int>(fSecond) );
+                        VSIFPrintfL(
+                            fp,
+                            "<text:p>%02d/%02d/%04d %02d:%02d:%02d</text:p>\n",
+                            nDay, nMonth, nYear, nHour, nMinute,
+                            static_cast<int>(fSecond) );
                     }
                     VSIFPrintfL(fp, "</table:table-cell>\n");
                 }
                 else if (eType == OFTDate)
                 {
-                    int nYear, nMonth, nDay, nHour, nMinute, nSecond, nTZFlag;
-                    poFeature->GetFieldAsDateTime(j, &nYear, &nMonth, &nDay,
-                                                    &nHour, &nMinute, &nSecond, &nTZFlag);
-                    VSIFPrintfL(fp, "<table:table-cell table:style-name=\"stDate\" "
-                                "office:value-type=\"date\" "
-                                "office:date-value=\"%04d-%02d-%02d\">\n",
-                                nYear, nMonth, nDay);
+                    int nYear;
+                    int  nMonth;
+                    int  nDay;
+                    int  nHour;
+                    int  nMinute;
+                    int  nSecond;
+                    int  nTZFlag;
+                    poFeature->GetFieldAsDateTime(
+                        j, &nYear, &nMonth, &nDay,
+                        &nHour, &nMinute, &nSecond, &nTZFlag );
+                    VSIFPrintfL(
+                        fp, "<table:table-cell table:style-name=\"stDate\" "
+                        "office:value-type=\"date\" "
+                        "office:date-value=\"%04d-%02d-%02d\">\n",
+                        nYear, nMonth, nDay);
                     VSIFPrintfL(fp, "<text:p>%02d/%02d/%04d</text:p>\n",
                                 nDay, nMonth, nYear);
                     VSIFPrintfL(fp, "</table:table-cell>\n");
                 }
                 else if (eType == OFTTime)
                 {
-                    int nYear, nMonth, nDay, nHour, nMinute, nSecond, nTZFlag;
-                    poFeature->GetFieldAsDateTime(j, &nYear, &nMonth, &nDay,
-                                                    &nHour, &nMinute, &nSecond, &nTZFlag);
-                    VSIFPrintfL(fp, "<table:table-cell table:style-name=\"stTime\" "
-                                "office:value-type=\"time\" "
-                                "office:time-value=\"PT%02dH%02dM%02dS\">\n",
-                                nHour, nMinute, nSecond);
+                    int nYear;
+                    int  nMonth;
+                    int  nDay;
+                    int  nHour;
+                    int  nMinute;
+                    int  nSecond;
+                    int  nTZFlag;
+                    poFeature->GetFieldAsDateTime(
+                        j, &nYear, &nMonth, &nDay,
+                        &nHour, &nMinute, &nSecond, &nTZFlag );
+                    VSIFPrintfL(
+                        fp, "<table:table-cell table:style-name=\"stTime\" "
+                        "office:value-type=\"time\" "
+                        "office:time-value=\"PT%02dH%02dM%02dS\">\n",
+                        nHour, nMinute, nSecond );
                     VSIFPrintfL(fp, "<text:p>%02d:%02d:%02d</text:p>\n",
                                 nHour, nMinute, nSecond);
                     VSIFPrintfL(fp, "</table:table-cell>\n");
@@ -1498,13 +1570,18 @@ static void WriteLayer(VSILFILE* fp, OGRLayer* poLayer)
                 {
                     const char* pszVal = poFeature->GetFieldAsString(j);
                     pszXML = OGRGetXML_UTF8_EscapedString(pszVal);
-                    if (strncmp(pszVal, "of:=", 4) == 0)
+                    if (STARTS_WITH(pszVal, "of:="))
                     {
-                        VSIFPrintfL(fp, "<table:table-cell table:formula=\"%s\"/>\n", pszXML);
+                        VSIFPrintfL(
+                            fp,
+                            "<table:table-cell table:formula=\"%s\"/>\n",
+                            pszXML);
                     }
                     else
                     {
-                        VSIFPrintfL(fp, "<table:table-cell office:value-type=\"string\">\n");
+                        VSIFPrintfL(
+                             fp, "<table:table-cell "
+                             "office:value-type=\"string\">\n");
                         VSIFPrintfL(fp, "<text:p>%s</text:p>\n", pszXML);
                         VSIFPrintfL(fp, "</table:table-cell>\n");
                     }
@@ -1542,8 +1619,8 @@ void OGRODSDataSource::FlushCache()
     {
         if (VSIUnlink( pszName ) != 0)
         {
-            CPLError(CE_Failure, CPLE_FileIO,
-                    "Cannot delete %s", pszName);
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Cannot delete %s", pszName);
             return;
         }
     }
@@ -1552,12 +1629,12 @@ void OGRODSDataSource::FlushCache()
     void *hZIP = CPLCreateZip(pszName, NULL);
     if (hZIP == NULL)
     {
-        CPLError(CE_Failure, CPLE_FileIO,
-                 "Cannot create %s", pszName);
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Cannot create %s", pszName);
         return;
     }
 
-    /* Write uncopressed mimetype */
+    /* Write uncompressed mimetype */
     char** papszOptions = CSLAddString(NULL, "COMPRESSED=NO");
     if( CPLCreateFileInZip(hZIP, "mimetype", papszOptions ) != CE_None )
     {
@@ -1566,8 +1643,11 @@ void OGRODSDataSource::FlushCache()
         return;
     }
     CSLDestroy(papszOptions);
-    if( CPLWriteFileInZip(hZIP, "application/vnd.oasis.opendocument.spreadsheet",
-                      strlen("application/vnd.oasis.opendocument.spreadsheet")) != CE_None )
+    if( CPLWriteFileInZip(
+        hZIP, "application/vnd.oasis.opendocument.spreadsheet",
+        static_cast<int>(
+            strlen("application/vnd.oasis.opendocument.spreadsheet")) )
+        != CE_None )
     {
         CPLCloseZip(hZIP);
         return;
@@ -1583,15 +1663,18 @@ void OGRODSDataSource::FlushCache()
     if (fpZIP == NULL)
         return;
 
-    VSILFILE* fp;
-    int i;
-
-    fp = VSIFOpenL(CPLSPrintf("/vsizip/%s/META-INF/manifest.xml", pszName), "wb");
+    VSILFILE* fp = VSIFOpenL(CPLSPrintf(
+        "/vsizip/%s/META-INF/manifest.xml", pszName), "wb");
     VSIFPrintfL(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
-    VSIFPrintfL(fp, "<manifest:manifest xmlns:manifest=\"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0\">\n");
-    VSIFPrintfL(fp, "<manifest:file-entry "
-                "manifest:media-type=\"application/vnd.oasis.opendocument.spreadsheet\" "
-                "manifest:version=\"1.2\" manifest:full-path=\"/\"/>\n");
+    VSIFPrintfL(
+        fp,
+        "<manifest:manifest ""xmlns:manifest=\"urn:oasis:names:tc:"
+        "opendocument:xmlns:manifest:1.0\">\n");
+    VSIFPrintfL(
+         fp, "<manifest:file-entry "
+         "manifest:media-type=\"application/vnd.oasis."
+         "opendocument.spreadsheet\" "
+         "manifest:version=\"1.2\" manifest:full-path=\"/\"/>\n");
     VSIFPrintfL(fp, "<manifest:file-entry manifest:media-type=\"text/xml\" "
                     "manifest:full-path=\"content.xml\"/>\n");
     VSIFPrintfL(fp, "<manifest:file-entry manifest:media-type=\"text/xml\" "
@@ -1605,38 +1688,57 @@ void OGRODSDataSource::FlushCache()
 
     fp = VSIFOpenL(CPLSPrintf("/vsizip/%s/meta.xml", pszName), "wb");
     VSIFPrintfL(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
-    VSIFPrintfL(fp, "<office:document-meta "
-                "xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\" "
-                "office:version=\"1.2\">\n");
+    VSIFPrintfL(
+        fp, "<office:document-meta "
+        "xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\" "
+        "office:version=\"1.2\">\n" );
     VSIFPrintfL(fp, "</office:document-meta>\n");
     VSIFCloseL(fp);
 
     fp = VSIFOpenL(CPLSPrintf("/vsizip/%s/settings.xml", pszName), "wb");
     VSIFPrintfL(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
-    VSIFPrintfL(fp, "<office:document-settings "
-                "xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\" "
-                "xmlns:config=\"urn:oasis:names:tc:opendocument:xmlns:config:1.0\" "
-                "xmlns:ooo=\"http://openoffice.org/2004/office\" "
-                "office:version=\"1.2\">\n");
+    VSIFPrintfL(
+         fp, "<office:document-settings "
+         "xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\" "
+         "xmlns:config=\"urn:oasis:names:tc:opendocument:xmlns:config:1.0\" "
+         "xmlns:ooo=\"http://openoffice.org/2004/office\" "
+         "office:version=\"1.2\">\n" );
     VSIFPrintfL(fp, "<office:settings>\n");
-    VSIFPrintfL(fp, "<config:config-item-set config:name=\"ooo:view-settings\">\n");
+    VSIFPrintfL(
+         fp, "<config:config-item-set config:name=\"ooo:view-settings\">\n");
     VSIFPrintfL(fp, "<config:config-item-map-indexed config:name=\"Views\">\n");
     VSIFPrintfL(fp, "<config:config-item-map-entry>\n");
     VSIFPrintfL(fp, "<config:config-item-map-named config:name=\"Tables\">\n");
-    for(i=0;i<nLayers;i++)
+    for(int i=0;i<nLayers;i++)
     {
-        OGRLayer* poLayer = GetLayer(i);
+        OGRLayer* poLayer = papoLayers[i];
         if (HasHeaderLine(poLayer))
         {
             /* Add vertical splitter */
-            char* pszXML = OGRGetXML_UTF8_EscapedString(GetLayer(i)->GetName());
-            VSIFPrintfL(fp, "<config:config-item-map-entry config:name=\"%s\">\n", pszXML);
+            char* pszXML = OGRGetXML_UTF8_EscapedString(poLayer->GetName());
+            VSIFPrintfL(
+                 fp,
+                 "<config:config-item-map-entry config:name=\"%s\">\n", pszXML);
             CPLFree(pszXML);
-            VSIFPrintfL(fp, "<config:config-item config:name=\"VerticalSplitMode\" config:type=\"short\">2</config:config-item>\n");
-            VSIFPrintfL(fp, "<config:config-item config:name=\"VerticalSplitPosition\" config:type=\"int\">1</config:config-item>\n");
-            VSIFPrintfL(fp, "<config:config-item config:name=\"ActiveSplitRange\" config:type=\"short\">2</config:config-item>\n");
-            VSIFPrintfL(fp, "<config:config-item config:name=\"PositionTop\" config:type=\"int\">0</config:config-item>\n");
-            VSIFPrintfL(fp, "<config:config-item config:name=\"PositionBottom\" config:type=\"int\">1</config:config-item>\n");
+            VSIFPrintfL(
+                 fp,
+                 "<config:config-item config:name=\"VerticalSplitMode\" "
+                 "config:type=\"short\">2</config:config-item>\n" );
+            VSIFPrintfL(
+                 fp,
+                 "<config:config-item config:name=\"VerticalSplitPosition\" "
+                 "config:type=\"int\">1</config:config-item>\n" );
+            VSIFPrintfL(
+                fp,
+                "<config:config-item config:name=\"ActiveSplitRange\" "
+                "config:type=\"short\">2</config:config-item>\n" );
+            VSIFPrintfL(
+                fp,
+                "<config:config-item config:name=\"PositionTop\" "
+                "config:type=\"int\">0</config:config-item>\n" );
+            VSIFPrintfL(
+                fp, "<config:config-item config:name=\"PositionBottom\" "
+                "config:type=\"int\">1</config:config-item>\n" );
             VSIFPrintfL(fp, "</config:config-item-map-entry>\n");
         }
     }
@@ -1650,10 +1752,11 @@ void OGRODSDataSource::FlushCache()
 
     fp = VSIFOpenL(CPLSPrintf("/vsizip/%s/styles.xml", pszName), "wb");
     VSIFPrintfL(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
-    VSIFPrintfL(fp, "<office:document-styles "
-                "xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\" "
-                "xmlns:style=\"urn:oasis:names:tc:opendocument:xmlns:style:1.0\" "
-                "office:version=\"1.2\">\n");
+    VSIFPrintfL(
+         fp, "<office:document-styles "
+         "xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\" "
+         "xmlns:style=\"urn:oasis:names:tc:opendocument:xmlns:style:1.0\" "
+         "office:version=\"1.2\">\n" );
     VSIFPrintfL(fp, "<office:styles>\n");
     VSIFPrintfL(fp, "<style:style style:name=\"Default\" "
                     "style:family=\"table-cell\">\n");
@@ -1664,15 +1767,17 @@ void OGRODSDataSource::FlushCache()
 
     fp = VSIFOpenL(CPLSPrintf("/vsizip/%s/content.xml", pszName), "wb");
     VSIFPrintfL(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
-    VSIFPrintfL(fp, "<office:document-content "
-                "xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\" "
-                "xmlns:style=\"urn:oasis:names:tc:opendocument:xmlns:style:1.0\" "
-                "xmlns:text=\"urn:oasis:names:tc:opendocument:xmlns:text:1.0\" "
-                "xmlns:table=\"urn:oasis:names:tc:opendocument:xmlns:table:1.0\" "
-                "xmlns:number=\"urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0\" "
-                "xmlns:fo=\"urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0\" "
-                "xmlns:of=\"urn:oasis:names:tc:opendocument:xmlns:of:1.2\" "
-                "office:version=\"1.2\">\n");
+    VSIFPrintfL(
+         fp, "<office:document-content "
+         "xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\" "
+         "xmlns:style=\"urn:oasis:names:tc:opendocument:xmlns:style:1.0\" "
+         "xmlns:text=\"urn:oasis:names:tc:opendocument:xmlns:text:1.0\" "
+         "xmlns:table=\"urn:oasis:names:tc:opendocument:xmlns:table:1.0\" "
+         "xmlns:number=\"urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0\" "
+         "xmlns:fo=\"urn:oasis:names:tc:opendocument:xmlns:"
+         "xsl-fo-compatible:1.0\" "
+         "xmlns:of=\"urn:oasis:names:tc:opendocument:xmlns:of:1.2\" "
+         "office:version=\"1.2\">\n" );
     VSIFPrintfL(fp, "<office:scripts/>\n");
     VSIFPrintfL(fp, "<office:automatic-styles>\n");
     VSIFPrintfL(fp, "<style:style style:name=\"co1\" "
@@ -1716,7 +1821,8 @@ void OGRODSDataSource::FlushCache()
     VSIFPrintfL(fp, "<number:text>:</number:text>\n");
     VSIFPrintfL(fp, "<number:seconds number:style=\"long\"/>\n");
     VSIFPrintfL(fp, "</number:date-style>\n");
-    VSIFPrintfL(fp, "<number:date-style style:name=\"nDateTimeMilliseconds\">\n");
+    VSIFPrintfL(
+         fp, "<number:date-style style:name=\"nDateTimeMilliseconds\">\n");
     VSIFPrintfL(fp, "<number:day number:style=\"long\"/>\n");
     VSIFPrintfL(fp, "<number:text>/</number:text>\n");
     VSIFPrintfL(fp, "<number:month number:style=\"long\"/>\n");
@@ -1727,7 +1833,10 @@ void OGRODSDataSource::FlushCache()
     VSIFPrintfL(fp, "<number:text>:</number:text>\n");
     VSIFPrintfL(fp, "<number:minutes number:style=\"long\"/>\n");
     VSIFPrintfL(fp, "<number:text>:</number:text>\n");
-    VSIFPrintfL(fp, "<number:seconds number:style=\"long\" number:decimal-places=\"3\"/>\n");
+    VSIFPrintfL(
+         fp,
+         "<number:seconds number:style=\"long\" "
+         "number:decimal-places=\"3\"/>\n" );
     VSIFPrintfL(fp, "</number:date-style>\n");
     VSIFPrintfL(fp, "<style:style style:name=\"stDate\" "
                     "style:family=\"table-cell\" "
@@ -1748,9 +1857,9 @@ void OGRODSDataSource::FlushCache()
     VSIFPrintfL(fp, "</office:automatic-styles>\n");
     VSIFPrintfL(fp, "<office:body>\n");
     VSIFPrintfL(fp, "<office:spreadsheet>\n");
-    for(i=0;i<nLayers;i++)
+    for(int i=0;i<nLayers;i++)
     {
-        WriteLayer(fp, GetLayer(i));
+        WriteLayer(fp, papoLayers[i]);
     }
     VSIFPrintfL(fp, "</office:spreadsheet>\n");
     VSIFPrintfL(fp, "</office:body>\n");
@@ -1761,10 +1870,10 @@ void OGRODSDataSource::FlushCache()
     VSIFCloseL(fpZIP);
 
     /* Reset updated flag at datasource and layer level */
-    bUpdated = FALSE;
+    bUpdated = false;
     for(int i = 0; i<nLayers; i++)
     {
-        ((OGRODSLayer*)papoLayers[i])->SetUpdated(FALSE);
+        reinterpret_cast<OGRODSLayer*>(papoLayers[i])->SetUpdated(false);
     }
 
     return;
@@ -1793,7 +1902,7 @@ int ODSCellEvaluator::EvaluateRange(int nRow1, int nCol1, int nRow2, int nCol2,
         return FALSE;
     }
 
-    int nIndexBackup = poLayer->GetNextReadFID();
+    const int nIndexBackup = static_cast<int>(poLayer->GetNextReadFID());
 
     if (poLayer->SetNextByIndex(nRow1) != OGRERR_NONE)
     {
@@ -1822,25 +1931,30 @@ int ODSCellEvaluator::EvaluateRange(int nRow1, int nCol1, int nRow2, int nCol2,
             }
             else if (poFeature->GetFieldDefnRef(nCol)->GetType() == OFTInteger)
             {
-                aoOutValues.push_back(ods_formula_node(poFeature->GetFieldAsInteger(nCol)));
+                aoOutValues.push_back(ods_formula_node(
+                    poFeature->GetFieldAsInteger(nCol)));
             }
             else if (poFeature->GetFieldDefnRef(nCol)->GetType() == OFTReal)
             {
-                aoOutValues.push_back(ods_formula_node(poFeature->GetFieldAsDouble(nCol)));
+                aoOutValues.push_back(ods_formula_node(
+                    poFeature->GetFieldAsDouble(nCol)));
             }
             else
             {
                 std::string osVal(poFeature->GetFieldAsString(nCol));
-                if (strncmp(osVal.c_str(), "of:=", 4) == 0)
+                if (STARTS_WITH(osVal.c_str(), "of:="))
                 {
                     delete poFeature;
                     poFeature = NULL;
 
                     if (!Evaluate(nRow, nCol))
                     {
-                        /*CPLError(CE_Warning, CPLE_AppDefined,
-                                "Formula at cell (%d, %d) has not yet been resolved",
-                                nRow + 1, nCol + 1);*/
+#ifdef DEBUG_VERBOSE
+                        CPLError( CE_Warning, CPLE_AppDefined,
+                                  "Formula at cell (%d, %d) "
+                                  "has not yet been resolved",
+                                  nRow + 1, nCol + 1 );
+#endif
                         poLayer->SetNextByIndex(nIndexBackup);
                         return FALSE;
                     }
@@ -1863,7 +1977,7 @@ int ODSCellEvaluator::EvaluateRange(int nRow1, int nCol1, int nRow2, int nCol2,
                     else
                     {
                         osVal = poFeature->GetFieldAsString(nCol);
-                        if (strncmp(osVal.c_str(), "of:=", 4) != 0)
+                        if (!STARTS_WITH(osVal.c_str(), "of:="))
                         {
                             CPLValueType eType = CPLGetValueType(osVal.c_str());
                             /* Try to convert into numeric value if possible */
@@ -1921,7 +2035,7 @@ int ODSCellEvaluator::Evaluate(int nRow, int nCol)
         poFeature->GetFieldDefnRef(nCol)->GetType() == OFTString)
     {
         const char* pszVal = poFeature->GetFieldAsString(nCol);
-        if (strncmp(pszVal, "of:=", 4) == 0)
+        if (STARTS_WITH(pszVal, "of:="))
         {
             ods_formula_node* expr_out = ods_formula_compile( pszVal + 4 );
             if (expr_out &&
@@ -1962,3 +2076,5 @@ int ODSCellEvaluator::Evaluate(int nRow, int nCol)
 
     return TRUE;
 }
+
+} /* end of OGRODS namespace */
diff --git a/ogr/ogrsf_frmts/ods/ogrodsdriver.cpp b/ogr/ogrsf_frmts/ods/ogrodsdriver.cpp
index 3cd8870..a546b8f 100644
--- a/ogr/ogrsf_frmts/ods/ogrodsdriver.cpp
+++ b/ogr/ogrsf_frmts/ods/ogrodsdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrodsdriver.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrodsdriver.cpp 32967 2016-01-13 14:40:01Z goatbar $
  *
  * Project:  ODS Translator
  * Purpose:  Implements OGRODSDriver.
@@ -27,23 +27,23 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_ods.h"
 #include "cpl_conv.h"
+#include "ogr_ods.h"
+#include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: ogrodsdriver.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrodsdriver.cpp 32967 2016-01-13 14:40:01Z goatbar $");
 
-extern "C" void RegisterOGRODS();
+using namespace OGRODS;
 
-// g++ -DHAVE_EXPAT -g -Wall -fPIC ogr/ogrsf_frmts/ods/*.cpp -shared -o ogr_ODS.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/mem -Iogr/ogrsf_frmts/ods -L. -lgdal
+// g++ -DHAVE_EXPAT -g -Wall -fPIC ogr/ogrsf_frmts/ods/*.cpp -shared
+// -o ogr_ODS.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts
+// -Iogr/ogrsf_frmts/mem -Iogr/ogrsf_frmts/ods -L. -lgdal
 
 /************************************************************************/
 /*                           ~OGRODSDriver()                            */
 /************************************************************************/
 
-OGRODSDriver::~OGRODSDriver()
-
-{
-}
+OGRODSDriver::~OGRODSDriver() {}
 
 /************************************************************************/
 /*                              GetName()                               */
@@ -74,12 +74,12 @@ OGRDataSource *OGRODSDriver::Open( const char * pszFilename, int bUpdate )
         if (fp == NULL)
             return NULL;
 
-        int bOK = FALSE;
+        bool bOK = false;
         char szBuffer[1024];
-        if (VSIFReadL(szBuffer, sizeof(szBuffer), 1, fp) == 1 &&
-            memcmp(szBuffer, "PK", 2) == 0)
+        if( VSIFReadL(szBuffer, sizeof(szBuffer), 1, fp) == 1 &&
+            memcmp(szBuffer, "PK", 2) == 0 )
         {
-            bOK = TRUE;
+            bOK = true;
         }
 
         VSIFCloseL(fp);
@@ -95,10 +95,10 @@ OGRDataSource *OGRODSDriver::Open( const char * pszFilename, int bUpdate )
         return NULL;
     }
 
-    if (EQUALN(pszContentFilename, "ODS:", 4) ||
+    if (STARTS_WITH_CI(pszContentFilename, "ODS:") ||
         EQUAL(CPLGetFilename(pszContentFilename), "content.xml"))
     {
-        if (EQUALN(pszContentFilename, "ODS:", 4))
+        if (STARTS_WITH_CI(pszContentFilename, "ODS:"))
             pszContentFilename += 4;
 
         fpContent = VSIFOpenL(pszContentFilename, "rb");
@@ -125,10 +125,11 @@ OGRDataSource *OGRODSDriver::Open( const char * pszFilename, int bUpdate )
 
     if (EQUAL(CPLGetExtension(pszFilename), "ODS"))
     {
-        fpSettings = VSIFOpenL(CPLSPrintf("/vsizip/%s/settings.xml", pszFilename), "rb");
+        fpSettings =
+            VSIFOpenL(CPLSPrintf("/vsizip/%s/settings.xml", pszFilename), "rb");
     }
 
-    OGRODSDataSource   *poDS = new OGRODSDataSource();
+    OGRODSDataSource *poDS = new OGRODSDataSource();
 
     if( !poDS->Open( pszFilename, fpContent, fpSettings, bUpdate ) )
     {
@@ -144,7 +145,7 @@ OGRDataSource *OGRODSDriver::Open( const char * pszFilename, int bUpdate )
 /************************************************************************/
 
 OGRDataSource *OGRODSDriver::CreateDataSource( const char * pszName,
-                                                char **papszOptions )
+                                               char **papszOptions )
 
 {
     if (!EQUAL(CPLGetExtension(pszName), "ODS"))
@@ -170,17 +171,15 @@ OGRDataSource *OGRODSDriver::CreateDataSource( const char * pszName,
 /* -------------------------------------------------------------------- */
 /*      Try to create datasource.                                       */
 /* -------------------------------------------------------------------- */
-    OGRODSDataSource     *poDS;
-
-    poDS = new OGRODSDataSource();
+    OGRODSDataSource *poDS = new OGRODSDataSource();
 
     if( !poDS->Create( pszName, papszOptions ) )
     {
         delete poDS;
         return NULL;
     }
-    else
-        return poDS;
+
+    return poDS;
 }
 
 /************************************************************************/
@@ -191,23 +190,23 @@ OGRErr OGRODSDriver::DeleteDataSource( const char *pszName )
 {
     if (VSIUnlink( pszName ) == 0)
         return OGRERR_NONE;
-    else
-        return OGRERR_FAILURE;
+
+    return OGRERR_FAILURE;
 }
 
 /************************************************************************/
 /*                           TestCapability()                           */
 /************************************************************************/
 
-int OGRODSDriver::TestCapability( const char * pszCap )
+int OGRODSDriver::TestCapability( const char *pszCap )
 
 {
     if( EQUAL(pszCap,ODrCCreateDataSource) )
         return TRUE;
-    else if( EQUAL(pszCap,ODrCDeleteDataSource) )
+    if( EQUAL(pszCap,ODrCDeleteDataSource) )
         return TRUE;
-    else
-        return FALSE;
+
+    return FALSE;
 }
 
 /************************************************************************/
@@ -218,13 +217,17 @@ void RegisterOGRODS()
 
 {
     OGRSFDriver* poDriver = new OGRODSDriver;
+
     poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                "Open Document/ LibreOffice / OpenOffice Spreadsheet " );
+                                "Open Document/ LibreOffice / "
+                               "OpenOffice Spreadsheet " );
     poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "ods" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                "drv_ods.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_ods.html" );
     poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES, "Integer Integer64 Real String Date DateTime Time Binary" );
-    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver(poDriver);
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
+                               "Integer Integer64 Real String Date DateTime "
+                               "Time Binary" );
+
+    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( poDriver );
 }
 
diff --git a/ogr/ogrsf_frmts/ogdi/drv_ogdi.html b/ogr/ogrsf_frmts/ogdi/drv_ogdi.html
index 77e05d4..afaeaa4 100644
--- a/ogr/ogrsf_frmts/ogdi/drv_ogdi.html
+++ b/ogr/ogrsf_frmts/ogdi/drv_ogdi.html
@@ -8,7 +8,7 @@
 <h1>OGDI Vectors</h1>
 
 OGDI vector support is optional in OGR, and is normally only configured if
-OGDI is installed on the build system.  If available OGDI vectors are 
+OGDI is installed on the build system.  If available OGDI vectors are
 supported for read access for the following family types:
 <ul>
   <li> Point
@@ -23,7 +23,7 @@ OGDI can (among other formats) read VPF products, such as DCW and VMAP.<p>
 If an OGDI gltp url is opened directly the OGDI 3.1 capabilities for the
 driver/server are queried to get a list of layers.  One OGR layer is created
 for each OGDI family available for each layer in the datastore.  For drivers
-such as VRF this can result in alot of layers.  Each of the layers has an
+such as VRF this can result in a lot of layers.  Each of the layers has an
 OGR name based on the OGDI name plus an underscore and the family name.  For
 instance a layer might be called <b>watrcrsl at hydro(*)_line</b> if coming
 out of the VRF driver.<p>
@@ -32,7 +32,7 @@ From GDAL/OGR 1.8.0, setting the <i>OGR_OGDI_LAUNDER_LAYER_NAMES</i> configurati
 option (or environment variable) to YES causes the layer names to be simplified. For example :
 <i>watrcrsl_hydro</i> instead of 'watrcrsl at hydro(*)_line'<p>
 
-Alternatively to accessing all the layers in a datastore, it is possible to 
+Alternatively to accessing all the layers in a datastore, it is possible to
 open a particular layer using a customized filename consisting
 of the regular GLTP URL to
 which you append the layer name and family type (separated by colons).  This
@@ -46,7 +46,7 @@ OGDI 3.1 there was no regular way to discover available layers in OGDI.<p>
 Where <layer_name> is the OGDI Layer name, and <family> is one of:
 "line", "area", "point", or "text".<p>
 
-OGDI coordinate system information is supported for most coordinate systems. 
+OGDI coordinate system information is supported for most coordinate systems.
 A warning will be produced when a layer is opened if the coordinate
 system cannot be translated.<p>
 
@@ -58,7 +58,7 @@ using the GDAL OGDI Raster driver.<p>
 <H3>Examples</H3>
 
 Usage example 'ogrinfo':<BR>
- 
+
 <PRE>
    ogrinfo gltp:/vrf/usr4/mpp1/v0eur/vmaplv0/eurnasia 'watrcrsl at hydro(*)_line'
 </PRE>
diff --git a/ogr/ogrsf_frmts/ogdi/ogrogdi.h b/ogr/ogrsf_frmts/ogdi/ogrogdi.h
index 40597be..6c20c56 100644
--- a/ogr/ogrsf_frmts/ogdi/ogrogdi.h
+++ b/ogr/ogrsf_frmts/ogdi/ogrogdi.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrogdi.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrogdi.h 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OGDI Bridge
  * Purpose:  Private definitions within the OGDI driver to implement
@@ -29,8 +29,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGDOGDI_H_INCLUDED
-#define _OGDOGDI_H_INCLUDED
+#ifndef OGDOGDI_H_INCLUDED
+#define OGDOGDI_H_INCLUDED
 
 #include <math.h>
 extern "C" {
@@ -58,15 +58,17 @@ class OGROGDILayer : public OGRLayer
     int                 m_iNextShapeId;
     int                 m_nTotalShapeCount;
     int                 m_nFilteredOutShapes;
-    
+
     OGRFeature *        GetNextRawFeature();
 
   public:
-                        OGROGDILayer(OGROGDIDataSource *, const char *, 
+                        OGROGDILayer(OGROGDIDataSource *, const char *,
                                      ecs_Family);
                         ~OGROGDILayer();
 
     virtual void        SetSpatialFilter( OGRGeometry * );
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+                { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
     virtual OGRErr      SetAttributeFilter( const char *pszQuery );
 
     void                ResetReading();
@@ -92,7 +94,7 @@ class OGROGDIDataSource : public OGRDataSource
 {
     OGROGDILayer      **m_papoLayers;
     int                 m_nLayers;
-    
+
     int                 m_nClientID;
 
     ecs_Region          m_sGlobalBounds;
@@ -104,7 +106,7 @@ class OGROGDIDataSource : public OGRDataSource
 
     int                 m_bLaunderLayerNames;
 
-    void                IAddLayer( const char *pszLayerName, 
+    void                IAddLayer( const char *pszLayerName,
                                    ecs_Family eFamily );
 
   public:
@@ -137,7 +139,7 @@ class OGROGDIDriver : public OGRSFDriver
 {
   public:
                 ~OGROGDIDriver();
-                
+
     const char *GetName();
     OGRDataSource *Open( const char *, int );
 
@@ -145,4 +147,4 @@ class OGROGDIDriver : public OGRSFDriver
 };
 
 
-#endif /* _OGDOGDI_H_INCLUDED */
+#endif /* OGDOGDI_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/ogdi/ogrogdidatasource.cpp b/ogr/ogrsf_frmts/ogdi/ogrogdidatasource.cpp
index e42041d..5853378 100644
--- a/ogr/ogrsf_frmts/ogdi/ogrogdidatasource.cpp
+++ b/ogr/ogrsf_frmts/ogdi/ogrogdidatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrogdidatasource.cpp 27794 2014-10-04 10:13:46Z rouault $
+ * $Id: ogrogdidatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OGDI Bridge
  * Purpose:  Implements OGROGDIDataSource class.
@@ -32,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrogdidatasource.cpp 27794 2014-10-04 10:13:46Z rouault $");
+CPL_CVSID("$Id: ogrogdidatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                         OGROGDIDataSource()                          */
@@ -48,7 +48,7 @@ OGROGDIDataSource::OGROGDIDataSource()
     m_poSpatialRef = NULL;
     m_poCurrentLayer = NULL;
     m_bLaunderLayerNames =
-            CSLTestBoolean(CPLGetConfigOption("OGR_OGDI_LAUNDER_LAYER_NAMES", "NO"));
+            CPLTestBool(CPLGetConfigOption("OGR_OGDI_LAUNDER_LAYER_NAMES", "NO"));
 }
 
 /************************************************************************/
@@ -88,7 +88,7 @@ int OGROGDIDataSource::Open( const char * pszNewName, int bTestOpen )
     char *pszWorkingName;
 
     CPLAssert( m_nLayers == 0 );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Parse the dataset name.                                         */
 /*      i.e.                                                            */
@@ -96,7 +96,7 @@ int OGROGDIDataSource::Open( const char * pszNewName, int bTestOpen )
 /*                                                                      */
 /*      Where <Family> is one of: Line, Area, Point, and Text           */
 /* -------------------------------------------------------------------- */
-        if( !EQUALN(pszNewName,"gltp:",5) )
+        if( !STARTS_WITH_CI(pszNewName, "gltp:") )
             return FALSE;
 
         pszWorkingName = CPLStrdup( pszNewName );
@@ -104,13 +104,13 @@ int OGROGDIDataSource::Open( const char * pszNewName, int bTestOpen )
         pszFamily = strrchr(pszWorkingName, ':');
 
         // Don't treat drive name colon as family separator.  It is assumed
-        // that drive names are on character long, and preceeded by a 
+        // that drive names are on character long, and preceded by a
         // forward or backward slash.
-        if( pszFamily < pszWorkingName+2 
+        if( pszFamily < pszWorkingName+2
             || pszFamily[-2] == '/'
             || pszFamily[-2] == '\\' )
             pszFamily = NULL;
-        
+
         if (pszFamily && pszFamily != pszWorkingName + 4)
         {
             *pszFamily = '\0';
@@ -172,7 +172,7 @@ int OGROGDIDataSource::Open( const char * pszNewName, int bTestOpen )
         if( m_poSpatialRef->importFromProj4( ECSTEXT(psResult) ) != OGRERR_NONE )
         {
             CPLError( CE_Warning, CPLE_NotSupported,
-                      "untranslatable PROJ.4 projection: %s\n", 
+                      "untranslatable PROJ.4 projection: %s\n",
                       ECSTEXT(psResult) );
             delete m_poSpatialRef;
             m_poSpatialRef = NULL;
@@ -188,7 +188,7 @@ int OGROGDIDataSource::Open( const char * pszNewName, int bTestOpen )
                       "%s", psResult->message );
             return FALSE;
         }
-    
+
 /* -------------------------------------------------------------------- */
 /*      If an explicit layer was selected, just create that layer.      */
 /* -------------------------------------------------------------------- */
@@ -228,7 +228,7 @@ int OGROGDIDataSource::Open( const char * pszNewName, int bTestOpen )
             int         i;
             const ecs_LayerCapabilities *psLayerCap;
 
-            for( i = 0; 
+            for( i = 0;
                 (psLayerCap = cln_GetLayerCapabilities(m_nClientID,i)) != NULL;
                  i++ )
             {
@@ -253,13 +253,13 @@ int OGROGDIDataSource::Open( const char * pszNewName, int bTestOpen )
 /*      the datasource.                                                 */
 /************************************************************************/
 
-void OGROGDIDataSource::IAddLayer( const char *pszLayerName, 
+void OGROGDIDataSource::IAddLayer( const char *pszLayerName,
                                    ecs_Family eFamily )
 
 {
     m_papoLayers = (OGROGDILayer**)
         CPLRealloc( m_papoLayers, (m_nLayers+1) * sizeof(OGROGDILayer*));
-    
+
     m_papoLayers[m_nLayers++] = new OGROGDILayer(this, pszLayerName, eFamily);
 }
 
diff --git a/ogr/ogrsf_frmts/ogdi/ogrogdidriver.cpp b/ogr/ogrsf_frmts/ogdi/ogrogdidriver.cpp
index 343ccc3..6d864e7 100644
--- a/ogr/ogrsf_frmts/ogdi/ogrogdidriver.cpp
+++ b/ogr/ogrsf_frmts/ogdi/ogrogdidriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrogdidriver.cpp 27794 2014-10-04 10:13:46Z rouault $
+ * $Id: ogrogdidriver.cpp 33199 2016-01-29 15:48:41Z rouault $
  *
  * Project:  OGDI Bridge
  * Purpose:  Implements OGROGDIDriver class.
@@ -31,7 +31,7 @@
 #include "ogrogdi.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrogdidriver.cpp 27794 2014-10-04 10:13:46Z rouault $");
+CPL_CVSID("$Id: ogrogdidriver.cpp 33199 2016-01-29 15:48:41Z rouault $");
 
 /************************************************************************/
 /*                           ~OGROGDIDriver()                           */
@@ -62,8 +62,8 @@ OGRDataSource *OGROGDIDriver::Open( const char * pszFilename,
 {
     OGROGDIDataSource   *poDS;
 
-    if( !EQUALN(pszFilename,"gltp:",5) )
-        return FALSE;
+    if( !STARTS_WITH_CI(pszFilename, "gltp:") )
+        return NULL;
 
     poDS = new OGROGDIDataSource();
 
@@ -80,7 +80,7 @@ OGRDataSource *OGROGDIDriver::Open( const char * pszFilename,
         delete poDS;
         poDS = NULL;
     }
- 
+
     return poDS;
 }
 
@@ -102,13 +102,14 @@ int OGROGDIDriver::TestCapability( CPL_UNUSED const char * pszCap )
 void RegisterOGROGDI()
 
 {
-    if (! GDAL_CHECK_VERSION("OGR/OGDI driver"))
+    if( !GDAL_CHECK_VERSION("OGR/OGDI driver") )
         return;
+
     OGRSFDriver* poDriver = new OGROGDIDriver;
     poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                "OGDI Vectors (VPF, VMAP, DCW)" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                "drv_ogdi.html" );
-    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver(poDriver);
+                               "OGDI Vectors (VPF, VMAP, DCW)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_ogdi.html" );
+
+    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( poDriver );
 }
 
diff --git a/ogr/ogrsf_frmts/ogdi/ogrogdilayer.cpp b/ogr/ogrsf_frmts/ogdi/ogrogdilayer.cpp
index adad5f7..5fd073c 100644
--- a/ogr/ogrsf_frmts/ogdi/ogrogdilayer.cpp
+++ b/ogr/ogrsf_frmts/ogdi/ogrogdilayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrogdilayer.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrogdilayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OGDI Bridge
  * Purpose:  Implements OGROGDILayer class.
@@ -57,13 +57,13 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrogdilayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrogdilayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                           OGROGDILayer()                            */
 /************************************************************************/
 
-OGROGDILayer::OGROGDILayer( OGROGDIDataSource *poODS, 
+OGROGDILayer::OGROGDILayer( OGROGDIDataSource *poODS,
                             const char * pszName, ecs_Family eFamily )
 
 {
@@ -98,7 +98,7 @@ OGROGDILayer::~OGROGDILayer()
     if( m_nFeaturesRead > 0 && m_poFeatureDefn != NULL )
     {
         CPLDebug( "OGDI", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
+                  (int) m_nFeaturesRead,
                   m_poFeatureDefn->GetName() );
     }
 
@@ -208,14 +208,14 @@ OGRFeature *OGROGDILayer::GetNextFeature()
     OGRFeature  *poFeature;
 
     /* Reset reading if we are not the current layer */
-    /* WARNING : this does not allow interleaved reading of layers */ 
+    /* WARNING : this does not allow interleaved reading of layers */
     if( m_poODS->GetCurrentLayer() != this )
     {
         m_poODS->SetCurrentLayer(this);
         ResetReading();
     }
 
-    while( TRUE )
+    while( true )
     {
         poFeature = GetNextRawFeature();
         if( poFeature == NULL )
@@ -225,8 +225,8 @@ OGRFeature *OGROGDILayer::GetNextFeature()
     /*      Do we need to apply an attribute test?                          */
     /* -------------------------------------------------------------------- */
         if( (m_poAttrQuery != NULL
-            && !m_poAttrQuery->Evaluate( poFeature ) ) 
-            || (m_poFilterGeom != NULL 
+            && !m_poAttrQuery->Evaluate( poFeature ) )
+            || (m_poFilterGeom != NULL
                 && !FilterGeometry( poFeature->GetGeometryRef() ) ) )
         {
             m_nFilteredOutShapes ++;
@@ -258,7 +258,7 @@ OGRFeature *OGROGDILayer::GetNextRawFeature()
         m_nTotalShapeCount = m_iNextShapeId - m_nFilteredOutShapes;
         return NULL;
     }
-   
+
     poFeature = new OGRFeature(m_poFeatureDefn);
 
     poFeature->SetFID( m_iNextShapeId++ );
@@ -282,7 +282,7 @@ OGRFeature *OGROGDILayer::GetNextRawFeature()
 
         poOGRLine->setNumPoints( psLine->c.c_len );
 
-        for( i=0; i < (int) psLine->c.c_len; i++ ) 
+        for( i=0; i < (int) psLine->c.c_len; i++ )
         {
             poOGRLine->setPoint(i, psLine->c.c_val[i].x, psLine->c.c_val[i].y);
         }
@@ -302,9 +302,9 @@ OGRFeature *OGROGDILayer::GetNextRawFeature()
 
             poOGRRing->setNumPoints( psRing->c.c_len );
 
-            for( i=0; i < (int) psRing->c.c_len; i++ ) 
+            for( i=0; i < (int) psRing->c.c_len; i++ )
             {
-                poOGRRing->setPoint(i, psRing->c.c_val[i].x, 
+                poOGRRing->setPoint(i, psRing->c.c_val[i].x,
                                     psRing->c.c_val[i].y);
             }
             poOGRPolygon->addRingDirectly(poOGRRing);
@@ -456,7 +456,7 @@ GIntBig OGROGDILayer::GetFeatureCount( int bForce )
 {
     if( m_nTotalShapeCount == -1)
     {
-        m_nTotalShapeCount = OGRLayer::GetFeatureCount( bForce );
+        m_nTotalShapeCount = static_cast<int>(OGRLayer::GetFeatureCount( bForce ));
     }
 
     return m_nTotalShapeCount;
@@ -481,7 +481,7 @@ int OGROGDILayer::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCFastSpatialFilter) )
         return FALSE;
 
-    else 
+    else
         return FALSE;
 #endif
 
@@ -511,7 +511,7 @@ void OGROGDILayer::BuildFeatureDefn()
 /* -------------------------------------------------------------------- */
 /*      Feature Defn name will be "<OGDILyrName>_<FeatureFamily>"       */
 /* -------------------------------------------------------------------- */
-    
+
     switch(m_eFamily)
     {
       case Point:
@@ -535,7 +535,7 @@ void OGROGDILayer::BuildFeatureDefn()
         eLayerGeomType = wkbUnknown;
         break;
     }
-    
+
     char* pszFeatureDefnName;
     if (m_poODS->LaunderLayerNames())
     {
@@ -548,15 +548,15 @@ void OGROGDILayer::BuildFeatureDefn()
             *pszLeftParenthesis = '\0';
     }
     else
-        pszFeatureDefnName = CPLStrdup(CPLSPrintf("%s_%s", 
-                                                    m_pszOGDILayerName, 
+        pszFeatureDefnName = CPLStrdup(CPLSPrintf("%s_%s",
+                                                    m_pszOGDILayerName,
                                                     pszGeomName ));
 
     m_poFeatureDefn = new OGRFeatureDefn(pszFeatureDefnName);
     SetDescription( m_poFeatureDefn->GetName() );
     CPLFree(pszFeatureDefnName);
     pszFeatureDefnName = NULL;
-    
+
     m_poFeatureDefn->SetGeomType(eLayerGeomType);
     m_poFeatureDefn->Reference();
     m_poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(m_poSpatialRef);
@@ -587,6 +587,7 @@ void OGROGDILayer::BuildFeatureDefn()
           case Smallint:
           case Integer:
             oField.SetType( OFTInteger );
+            // TODO: Fix spelling - lenght -> length
             if( oaf->oa.oa_val[i].lenght > 0 )
                 oField.SetWidth( oaf->oa.oa_val[i].lenght );
             else
@@ -635,9 +636,4 @@ void OGROGDILayer::BuildFeatureDefn()
 
         m_poFeatureDefn->AddFieldDefn( &oField );
     }
-    
 }
-
-
-
-
diff --git a/ogr/ogrsf_frmts/ogr_attrind.h b/ogr/ogrsf_frmts/ogr_attrind.h
index b2d8f2d..593b343 100644
--- a/ogr/ogrsf_frmts/ogr_attrind.h
+++ b/ogr/ogrsf_frmts/ogr_attrind.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_attrind.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogr_attrind.h 32177 2015-12-14 07:25:30Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Classes related to generic implementation of attribute indexing.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_ATTRIND_H_INCLUDED
-#define _OGR_ATTRIND_H_INCLUDED
+#ifndef OGR_ATTRIND_H_INCLUDED
+#define OGR_ATTRIND_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 
@@ -49,7 +49,7 @@ public:
     virtual GIntBig   GetFirstMatch( OGRField *psKey ) = 0;
     virtual GIntBig  *GetAllMatches( OGRField *psKey ) = 0;
     virtual GIntBig  *GetAllMatches( OGRField *psKey, GIntBig* panFIDList, int* nFIDCount, int* nLength ) = 0;
-    
+
     virtual OGRErr AddEntry( OGRField *psKey, GIntBig nFID ) = 0;
     virtual OGRErr RemoveEntry( OGRField *psKey, GIntBig nFID ) = 0;
 
@@ -89,5 +89,5 @@ public:
 OGRLayerAttrIndex CPL_DLL *OGRCreateDefaultLayerIndex();
 
 
-#endif /* ndef _OGR_ATTRIND_H_INCLUDED */
+#endif /* ndef OGR_ATTRIND_H_INCLUDED */
 
diff --git a/ogr/ogrsf_frmts/ogr_formats.html b/ogr/ogrsf_frmts/ogr_formats.html
index 6abd9bc..f9b9daa 100644
--- a/ogr/ogrsf_frmts/ogr_formats.html
+++ b/ogr/ogrsf_frmts/ogr_formats.html
@@ -24,6 +24,13 @@
 </td><td> Yes
 </td></tr>
 
+<tr><td> <a href="drv_amigocloud.html">AmigoCloud API</a>
+</td><td> AmigoCloud
+</td><td> Yes
+</td><td> Yes
+</td><td> No, needs libcurl
+</td></tr>
+
 <tr><td> <a href="drv_ao.html">ESRI ArcObjects</a>
 </td><td> ArcObjects
 </td><td> No
@@ -63,7 +70,7 @@
 </td><td> DWG
 </td><td> No
 </td><td> No
-</td><td> No
+</td><td> No, needs Open Design Alliance Teiga library
 </td></tr>
 
 <tr><td> <a href="drv_dxf.html">AutoCAD DXF</a>
@@ -116,6 +123,13 @@
 </td><td> No, needs libsqlite3
 </td></tr>
 
+<tr><td> <a href="drv_db2.html">DB2 Spatial</a>
+</td><td> DB2ODBC
+</td><td> Yes
+</td><td> Yes
+</td><td> No, needs ODBC library
+</td></tr>
+
 <tr><td> <a href="drv_dods.html">DODS/OPeNDAP</a>
 </td><td> DODS
 </td><td> No
@@ -132,8 +146,8 @@
 
 <tr><td> <a href="drv_elasticsearch.html">ElasticSearch</a>
 </td><td> ElasticSearch
-</td><td> Yes (write-only)
-</td><td> -
+</td><td> Yes
+</td><td> Yes
 </td><td> No, needs libcurl
 </td></tr>
 
@@ -158,7 +172,7 @@
 </td><td> No, needs ESRI SDE
 </td></tr>
 
-<tr><td> <a href="drv_shapefile.html">ESRI Shapefile</a>
+<tr><td> <a href="drv_shapefile.html">ESRI Shapefile / DBF</a>
 </td><td> ESRI Shapefile
 </td><td> Yes
 </td><td> Yes
@@ -214,13 +228,6 @@
 </td><td> No, needs libcurl
 </td></tr>
 
-<tr><td> <a href="http://trac.osgeo.org/gdal/wiki/GMEDriver">Google Maps Engine</a>
-</td><td> GME
-</td><td> Yes
-</td><td> Yes
-</td><td> No, needs libcurl
-</td></tr>
-
 <tr><td> <a href="drv_gml.html">GML</a>
 </td><td> GML
 </td><td> Yes
@@ -281,10 +288,9 @@
 </td><td> IDB
 </td><td> Yes
 </td><td> Yes
-</td><td> No, needs Informix DataBlade 
+</td><td> No, needs Informix DataBlade
 </td></tr>
 
-
 <tr><td> <a href="drv_ili.html">INTERLIS</a>
 </td><td> "Interlis 1" and "Interlis 2"
 </td><td> Yes
@@ -348,6 +354,13 @@
 </td><td> Yes
 </td></tr>
 
+<tr><td><a href="drv_mongodb.html">MongoDB</a>
+</td><td> MongoDB
+</td><td> Yes
+</td><td> Yes
+</td><td> No, needs Mongo C++ client library
+</td></tr>
+
 <tr><td> <a href="drv_mysql.html">MySQL</a>
 </td><td> MySQL
 </td><td> No
@@ -362,6 +375,13 @@
 </td><td> No, needs Xerces
 </td></tr>
 
+<tr><td> <a href="frmt_netcdf_vector.html">NetCDF</a>
+</td><td> netCDF
+</td><td> Yes
+</td><td> Yes
+</td><td> No, needs libnetcdf
+</td></tr>
+
 <tr><td> <a href="drv_oci.html">Oracle Spatial</a>
 </td><td> OCI
 </td><td> Yes
@@ -586,6 +606,13 @@
 </td><td> Yes
 </td></tr>
 
+<tr><td> <a href="drv_vdv.html">VDV-451/VDV-452/IDF</a>
+</td><td> VDV
+</td><td> Yes
+</td><td> Yes
+</td><td> Yes
+</td></tr>
+
 <tr><td> <a href="drv_walk.html">Walk</a>
 </td><td> Walk
 </td><td> No
diff --git a/ogr/ogrsf_frmts/ogrsf_frmts.dox b/ogr/ogrsf_frmts/ogrsf_frmts.dox
index 1d22ff1..6f8d05c 100644
--- a/ogr/ogrsf_frmts/ogrsf_frmts.dox
+++ b/ogr/ogrsf_frmts/ogrsf_frmts.dox
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsf_frmts.dox 29035 2015-04-27 12:38:54Z rouault $
+ * $Id: ogrsf_frmts.dox 32114 2015-12-10 22:03:51Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Documentation for ogrsf_frmts.h classes.
@@ -152,7 +152,7 @@
 
   This function is the same as the C++ method OGRSFDriver::GetName().
 
-  @param hDriver handle to the the driver to get the name from.
+  @param hDriver handle to the driver to get the name from.
   @return driver name.  This is an internal string and should not be modified
   or freed. 
 */
@@ -197,7 +197,7 @@
  </ul>
 
  The \#define macro forms of the capability names should be used in preference
- to the strings themselves to avoid mispelling.
+ to the strings themselves to avoid misspelling.
 
  @deprecated Use GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATE) in GDAL 2.0
 
@@ -254,7 +254,7 @@ based.
  @param pszName the name for the new data source. UTF-8 encoded.
  @param papszOptions a StringList of name=value options.  Options are driver
 specific, and driver information can be found at the following url:  
-http://www.gdal.org/ogr/ogr_formats.html 
+http://www.gdal.org/ogr_formats.html 
 
  @return NULL is returned on failure, or a new OGRDataSource handle on 
 success. 
@@ -280,7 +280,7 @@ based.
  @param pszNewName the name for the new data source.
  @param papszOptions a StringList of name=value options.  Options are driver
 specific, and driver information can be found at the following url:  
-http://www.gdal.org/ogr/ogr_formats.html 
+http://www.gdal.org/ogr_formats.html 
 
  @return NULL is returned on failure, or a new OGRDataSource handle on 
 success. 
@@ -429,7 +429,7 @@ success.
  (destroyed).  
 
  For more information on the SQL dialect supported internally by OGR
- review the <a href="ogr_sql.html">OGR SQL</a> document.  Some drivers (ie.
+ review the <a href="ogr_sql.html">OGR SQL</a> document.  Some drivers (i.e.
  Oracle and PostGIS) pass the SQL directly through to the underlying RDBMS.
 
  Starting with OGR 1.10, the <a href="ogr_sql_sqlite.html">SQLITE dialect</a>
@@ -489,7 +489,7 @@ can also be used.
  </ul>
 
  The \#define macro forms of the capability names should be used in preference
- to the strings themselves to avoid mispelling.
+ to the strings themselves to avoid misspelling.
 
  @deprecated Use GDALDatasetTestCapability() in GDAL 2.0
 
@@ -524,7 +524,7 @@ or NULL if no coordinate system is available.
 are no constraints on the types geometry to be written. 
  @param papszOptions a StringList of name=value options.  Options are driver
 specific, and driver information can be found at the following url:  
-http://www.gdal.org/ogr/ogr_formats.html 
+http://www.gdal.org/ogr_formats.html 
 
  @return NULL is returned on failure, or a new OGRLayer handle on success. 
 
@@ -702,9 +702,9 @@ by the OGRSFDriverManager.
 
  \brief Fetch the next available feature from this layer.
 
- The returned feature
- becomes the responsiblity of the caller to delete with OGRFeature::DestroyFeature(). It is critical that
- all features associated with an OGRLayer (more specifically an 
+ The returned feature becomes the responsibility of the caller to
+ delete with OGRFeature::DestroyFeature(). It is critical that all
+ features associated with an OGRLayer (more specifically an
  OGRFeatureDefn) be deleted before that layer/datasource is deleted.
 
  Only features matching the current spatial filter (set with 
@@ -713,14 +713,14 @@ by the OGRSFDriverManager.
  This method implements sequential access to the features of a layer.  The
  ResetReading() method can be used to start at the beginning again.  
 
- Features returned by GetNextFeature() may or may not be affected by concurrent
- modifications depending on drivers. A guaranteed way of seing modifications in
- effect is to call ResetReading() on layers where GetNextFeature() has been called,
- before reading again.
- Structural changes in layers (field addition, deletion, ...) when a read is in
- progress may or may not be possible depending on drivers.
- If a transaction is committed/aborted, the current sequential reading may or may not be
- valid after that operation and a call to ResetReading() might be needed.
+ Features returned by GetNextFeature() may or may not be affected by
+ concurrent modifications depending on drivers. A guaranteed way of seeing
+ modifications in effect is to call ResetReading() on layers where
+ GetNextFeature() has been called, before reading again.  Structural changes
+ in layers (field addition, deletion, ...) when a read is in progress may or
+ may not be possible depending on drivers.  If a transaction is
+ committed/aborted, the current sequential reading may or may not be valid
+ after that operation and a call to ResetReading() might be needed.
 
  This method is the same as the C function OGR_L_GetNextFeature().
 
@@ -734,10 +734,10 @@ by the OGRSFDriverManager.
 
  \brief Fetch the next available feature from this layer.
 
- The returned feature
- becomes the responsiblity of the caller to delete with OGR_F_Destroy().  It is critical that
- all features associated with an OGRLayer (more specifically an 
- OGRFeatureDefn) be deleted before that layer/datasource is deleted.
+ The returned feature becomes the responsibility of the caller to
+ delete with OGR_F_Destroy().  It is critical that all features
+ associated with an OGRLayer (more specifically an OGRFeatureDefn) be
+ deleted before that layer/datasource is deleted.
 
  Only features matching the current spatial filter (set with 
  SetSpatialFilter()) will be returned.  
@@ -746,14 +746,14 @@ by the OGRSFDriverManager.
  The OGR_L_ResetReading() function can be used to start at the beginning 
  again.
 
- Features returned by OGR_GetNextFeature() may or may not be affected by concurrent
- modifications depending on drivers. A guaranteed way of seing modifications in
- effect is to call OGR_L_ResetReading() on layers where OGR_GetNextFeature() has been called,
- before reading again.
- Structural changes in layers (field addition, deletion, ...) when a read is in
- progress may or may not be possible depending on drivers.
- If a transaction is committed/aborted, the current sequential reading may or may not be
- valid after that operation and a call to OGR_L_ResetReading() might be needed.
+ Features returned by OGR_GetNextFeature() may or may not be affected by
+ concurrent modifications depending on drivers. A guaranteed way of seeing
+ modifications in effect is to call OGR_L_ResetReading() on layers where
+ OGR_GetNextFeature() has been called, before reading again.  Structural
+ changes in layers (field addition, deletion, ...) when a read is in progress
+ may or may not be possible depending on drivers.  If a transaction is
+ committed/aborted, the current sequential reading may or may not be valid
+ after that operation and a call to OGR_L_ResetReading() might be needed.
 
  This function is the same as the C++ method OGRLayer::GetNextFeature().
 
@@ -906,7 +906,7 @@ by the OGRSFDriverManager.
  Note that some implementations of this method may alter the read cursor
  of the layer.
 
- Note to driver implementators: if you implement GetExtent(int,OGREnvelope*,int),
+ Note to driver implementer: if you implement GetExtent(int,OGREnvelope*,int),
  you must also implement GetExtent(OGREnvelope*, int) to make it call
  GetExtent(0,OGREnvelope*,int).
 
@@ -1106,7 +1106,7 @@ by the OGRSFDriverManager.
  Note that only the last spatial filter set is applied, even if several
  successive calls are done with different iGeomField values.
 
- Note to driver implementators: if you implement SetSpatialFilter(int,OGRGeometry*),
+ Note to driver implementer: if you implement SetSpatialFilter(int,OGRGeometry*),
  you must also implement SetSpatialFilter(OGRGeometry*) to make it call
  SetSpatialFilter(0,OGRGeometry*).
 
@@ -1277,7 +1277,7 @@ by the OGRSFDriverManager.
  form of SQL  WHERE clause as described in the "WHERE" section of the 
  <a href="ogr_sql.html">OGR SQL</a> tutorial.  In some cases (RDBMS 
  backed drivers) the native capabilities of the database may be used to 
- interprete the WHERE clause in which case the capabilities will be broader
+ interpret the WHERE clause in which case the capabilities will be broader
  than those of OGR SQL.
 
  Note that installing a query string will generally result in resetting
@@ -1712,13 +1712,13 @@ should build and maintain its own spatial index for features in this layer.<p>
 
  <li> <b>OLCFastFeatureCount</b> / "FastFeatureCount": 
 TRUE if this layer can return a feature
-count (via GetFeatureCount()) efficiently ... ie. without counting
+count (via GetFeatureCount()) efficiently. i.e. without counting
 the features.  In some cases this will return TRUE until a spatial filter is
 installed after which it will return FALSE.<p>
 
  <li> <b>OLCFastGetExtent</b> / "FastGetExtent": 
 TRUE if this layer can return its data extent (via GetExtent())
-efficiently ... ie. without scanning all the features.  In some cases this
+efficiently, i.e. without scanning all the features.  In some cases this
 will return TRUE until a spatial filter is installed after which it will
 return FALSE.<p>
 
@@ -1767,7 +1767,7 @@ writing curve geometries or may return such geometries. (GDAL 2.0).
  @param pszCap the name of the capability to test.
 
  @return TRUE if the layer has the requested capability, or FALSE otherwise.
-OGRLayers will return FALSE for any unrecognised capabilities.<p>
+OGRLayers will return FALSE for any unrecognized capabilities.<p>
 
 */
 
@@ -1809,13 +1809,13 @@ layer.<p>
 
  <li> <b>OLCFastFeatureCount</b> / "FastFeatureCount": 
 TRUE if this layer can return a feature
-count (via OGR_L_GetFeatureCount()) efficiently ... ie. without counting
+count (via OGR_L_GetFeatureCount()) efficiently, i.e. without counting
 the features.  In some cases this will return TRUE until a spatial filter is
 installed after which it will return FALSE.<p>
 
  <li> <b>OLCFastGetExtent</b> / "FastGetExtent": 
 TRUE if this layer can return its data extent (via OGR_L_GetExtent())
-efficiently ... ie. without scanning all the features.  In some cases this
+efficiently, i.e. without scanning all the features.  In some cases this
 will return TRUE until a spatial filter is installed after which it will
 return FALSE.<p>
 
@@ -1862,7 +1862,7 @@ writing curve geometries or may return such geometries. (GDAL 2.0).
  @param pszCap the name of the capability to test.
 
  @return TRUE if the layer has the requested capability, or FALSE otherwise.
-OGRLayers will return FALSE for any unrecognised capabilities.<p>
+OGRLayers will return FALSE for any unrecognized capabilities.<p>
 
 */
 
@@ -2009,12 +2009,12 @@ on a real layer. Internally the OGRFeatureDefn for the layer will be updated
 to reflect the new field.  Applications should never modify the OGRFeatureDefn
 used by a layer directly.
 
-This method should not be called while there are feature objects in existance that
+This method should not be called while there are feature objects in existence that
 were obtained or created with the previous layer definition.
 
 Not all drivers support this method. You can query a layer to check if it supports it
 with the OLCCreateField capability. Some drivers may only support this method while
-there are still no features in the layer. When it is supported, the existings features of the
+there are still no features in the layer. When it is supported, the existing features of the
 backing file/database should be updated accordingly.
 
 Drivers may or may not support not-null constraints. If they support creating
@@ -2041,12 +2041,12 @@ on a real layer. Internally the OGRFeatureDefn for the layer will be updated
 to reflect the new field.  Applications should never modify the OGRFeatureDefn
 used by a layer directly.
 
-This function should not be called while there are feature objects in existance that
+This function should not be called while there are feature objects in existence that
 were obtained or created with the previous layer definition.
 
 Not all drivers support this function. You can query a layer to check if it supports it
 with the OLCCreateField capability. Some drivers may only support this method while
-there are still no features in the layer. When it is supported, the existings features of the
+there are still no features in the layer. When it is supported, the existing features of the
 backing file/database should be updated accordingly.
 
 Drivers may or may not support not-null constraints. If they support creating
@@ -2073,12 +2073,12 @@ on a real layer. Internally the OGRFeatureDefn for the layer will be updated
 to reflect the deleted field.  Applications should never modify the OGRFeatureDefn
 used by a layer directly.
 
-This method should not be called while there are feature objects in existance that
+This method should not be called while there are feature objects in existence that
 were obtained or created with the previous layer definition.
 
 Not all drivers support this method. You can query a layer to check if it supports it
 with the OLCDeleteField capability. Some drivers may only support this method while
-there are still no features in the layer. When it is supported, the existings features of the
+there are still no features in the layer. When it is supported, the existing features of the
 backing file/database should be updated accordingly.
 
 This function is the same as the C function OGR_L_DeleteField().
@@ -2101,12 +2101,12 @@ on a real layer. Internally the OGRFeatureDefn for the layer will be updated
 to reflect the deleted field.  Applications should never modify the OGRFeatureDefn
 used by a layer directly.
 
-This function should not be called while there are feature objects in existance that
+This function should not be called while there are feature objects in existence that
 were obtained or created with the previous layer definition.
 
 Not all drivers support this function. You can query a layer to check if it supports it
 with the OLCDeleteField capability. Some drivers may only support this method while
-there are still no features in the layer. When it is supported, the existings features of the
+there are still no features in the layer. When it is supported, the existing features of the
 backing file/database should be updated accordingly.
 
 This function is the same as the C++ method OGRLayer::DeleteField().
@@ -2129,7 +2129,7 @@ on a real layer. Internally the OGRFeatureDefn for the layer will be updated
 to reflect the reordering of the fields.  Applications should never modify the OGRFeatureDefn
 used by a layer directly.
 
-This method should not be called while there are feature objects in existance that
+This method should not be called while there are feature objects in existence that
 were obtained or created with the previous layer definition.
 
 panMap is such that,for each field definition at position i after reordering,
@@ -2140,7 +2140,7 @@ ReorderFields([0,2,3,1,4]) will reorder them as "0","2","3","1","4".
 
 Not all drivers support this method. You can query a layer to check if it supports it
 with the OLCReorderFields capability. Some drivers may only support this method while
-there are still no features in the layer. When it is supported, the existings features of the
+there are still no features in the layer. When it is supported, the existing features of the
 backing file/database should be updated accordingly.
 
 This function is the same as the C function OGR_L_ReorderFields().
@@ -2164,7 +2164,7 @@ on a real layer. Internally the OGRFeatureDefn for the layer will be updated
 to reflect the reordering of the fields.  Applications should never modify the OGRFeatureDefn
 used by a layer directly.
 
-This function should not be called while there are feature objects in existance that
+This function should not be called while there are feature objects in existence that
 were obtained or created with the previous layer definition.
 
 panMap is such that,for each field definition at position i after reordering,
@@ -2175,7 +2175,7 @@ ReorderFields([0,2,3,1,4]) will reorder them as "0","2","3","1","4".
 
 Not all drivers support this function. You can query a layer to check if it supports it
 with the OLCReorderFields capability. Some drivers may only support this method while
-there are still no features in the layer. When it is supported, the existings features of the
+there are still no features in the layer. When it is supported, the existing features of the
 backing file/database should be updated accordingly.
 
 This function is the same as the C++ method OGRLayer::ReorderFields().
@@ -2194,7 +2194,7 @@ is a permutation of [0, GetLayerDefn()->OGRFeatureDefn::GetFieldCount()-1].
 
 \brief Reorder an existing field on a layer.
 
-This method is a conveniency wrapper of ReorderFields() dedicated to move a single field.
+This method is a convenience wrapper of ReorderFields() dedicated to move a single field.
 It is a non-virtual method, so drivers should implement ReorderFields() instead.
 
 You must use this to reorder existing fields
@@ -2202,7 +2202,7 @@ on a real layer. Internally the OGRFeatureDefn for the layer will be updated
 to reflect the reordering of the fields.  Applications should never modify the OGRFeatureDefn
 used by a layer directly.
 
-This method should not be called while there are feature objects in existance that
+This method should not be called while there are feature objects in existence that
 were obtained or created with the previous layer definition.
 
 The field definition that was at initial position iOldFieldPos will be moved at
@@ -2213,7 +2213,7 @@ ReorderField(1, 3) will reorder them as "0","2","3","1","4".
 
 Not all drivers support this method. You can query a layer to check if it supports it
 with the OLCReorderFields capability. Some drivers may only support this method while
-there are still no features in the layer. When it is supported, the existings features of the
+there are still no features in the layer. When it is supported, the existing features of the
 backing file/database should be updated accordingly.
 
 This function is the same as the C function OGR_L_ReorderField().
@@ -2232,14 +2232,14 @@ This function is the same as the C function OGR_L_ReorderField().
 
 \brief Reorder an existing field on a layer.
 
-This function is a conveniency wrapper of OGR_L_ReorderFields() dedicated to move a single field.
+This function is a convenience wrapper of OGR_L_ReorderFields() dedicated to move a single field.
 
 You must use this to reorder existing fields
 on a real layer. Internally the OGRFeatureDefn for the layer will be updated
 to reflect the reordering of the fields.  Applications should never modify the OGRFeatureDefn
 used by a layer directly.
 
-This function should not be called while there are feature objects in existance that
+This function should not be called while there are feature objects in existence that
 were obtained or created with the previous layer definition.
 
 The field definition that was at initial position iOldFieldPos will be moved at
@@ -2250,7 +2250,7 @@ ReorderField(1, 3) will reorder them as "0","2","3","1","4".
 
 Not all drivers support this function. You can query a layer to check if it supports it
 with the OLCReorderFields capability. Some drivers may only support this method while
-there are still no features in the layer. When it is supported, the existings features of the
+there are still no features in the layer. When it is supported, the existing features of the
 backing file/database should be updated accordingly.
 
 This function is the same as the C++ method OGRLayer::ReorderField().
@@ -2274,12 +2274,12 @@ Internally the OGRFeatureDefn for the layer will be updated
 to reflect the altered field.  Applications should never modify the OGRFeatureDefn
 used by a layer directly.
 
-This method should not be called while there are feature objects in existance that
+This method should not be called while there are feature objects in existence that
 were obtained or created with the previous layer definition.
 
 Not all drivers support this method. You can query a layer to check if it supports it
 with the OLCAlterFieldDefn capability. Some drivers may only support this method while
-there are still no features in the layer. When it is supported, the existings features of the
+there are still no features in the layer. When it is supported, the existing features of the
 backing file/database should be updated accordingly. Some drivers might also not support
 all update flags.
 
@@ -2307,12 +2307,12 @@ Internally the OGRFeatureDefn for the layer will be updated
 to reflect the altered field.  Applications should never modify the OGRFeatureDefn
 used by a layer directly.
 
-This function should not be called while there are feature objects in existance that
+This function should not be called while there are feature objects in existence that
 were obtained or created with the previous layer definition.
 
 Not all drivers support this function. You can query a layer to check if it supports it
 with the OLCAlterFieldDefn capability. Some drivers may only support this method while
-there are still no features in the layer. When it is supported, the existings features of the
+there are still no features in the layer. When it is supported, the existing features of the
 backing file/database should be updated accordingly. Some drivers might also not support
 all update flags.
 
@@ -2343,12 +2343,12 @@ on a real layer. Internally the OGRFeatureDefn for the layer will be updated
 to reflect the new field.  Applications should never modify the OGRFeatureDefn
 used by a layer directly.
 
-This method should not be called while there are feature objects in existance that
+This method should not be called while there are feature objects in existence that
 were obtained or created with the previous layer definition.
 
 Not all drivers support this method. You can query a layer to check if it supports it
 with the OLCCreateGeomField capability. Some drivers may only support this method while
-there are still no features in the layer. When it is supported, the existings features of the
+there are still no features in the layer. When it is supported, the existing features of the
 backing file/database should be updated accordingly.
 
 Drivers may or may not support not-null constraints. If they support creating
@@ -2377,12 +2377,12 @@ on a real layer. Internally the OGRFeatureDefn for the layer will be updated
 to reflect the new field.  Applications should never modify the OGRFeatureDefn
 used by a layer directly.
 
-This function should not be called while there are feature objects in existance that
+This function should not be called while there are feature objects in existence that
 were obtained or created with the previous layer definition.
 
 Not all drivers support this function. You can query a layer to check if it supports it
 with the OLCCreateField capability. Some drivers may only support this method while
-there are still no features in the layer. When it is supported, the existings features of the
+there are still no features in the layer. When it is supported, the existing features of the
 backing file/database should be updated accordingly.
 
 Drivers may or may not support not-null constraints. If they support creating
diff --git a/ogr/ogrsf_frmts/ogrsf_frmts.h b/ogr/ogrsf_frmts/ogrsf_frmts.h
index 8a00307..cff2944 100644
--- a/ogr/ogrsf_frmts/ogrsf_frmts.h
+++ b/ogr/ogrsf_frmts/ogrsf_frmts.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsf_frmts.h 29035 2015-04-27 12:38:54Z rouault $
+ * $Id: ogrsf_frmts.h 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Classes related to format registration, and file opening.
@@ -28,8 +28,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGRSF_FRMTS_H_INCLUDED
-#define _OGRSF_FRMTS_H_INCLUDED
+#ifndef OGRSF_FRMTS_H_INCLUDED
+#define OGRSF_FRMTS_H_INCLUDED
 
 #include "cpl_progress.h"
 #include "ogr_feature.h"
@@ -45,7 +45,7 @@
 #if !defined(GDAL_COMPILATION) && !defined(SUPPRESS_DEPRECATION_WARNINGS)
 #define OGR_DEPRECATED(x) CPL_WARN_DEPRECATED(x)
 #else
-#define OGR_DEPRECATED(x) 
+#define OGR_DEPRECATED(x)
 #endif
 
 class OGRLayerAttrIndex;
@@ -66,7 +66,7 @@ class OGRSFDriver;
 class CPL_DLL OGRLayer : public GDALMajorObject
 {
   private:
-    void         ConvertNonLinearGeomsIfNecessary( OGRFeature *poFeature );
+    void         ConvertGeomsIfNecessary( OGRFeature *poFeature );
 
   protected:
     int          m_bFilterIsEnvelope;
@@ -75,15 +75,15 @@ class CPL_DLL OGRLayer : public GDALMajorObject
     OGREnvelope  m_sFilterEnvelope;
     int          m_iGeomFieldFilter; // specify the index on which the spatial
                                      // filter is active.
-    
+
     int          FilterGeometry( OGRGeometry * );
     //int          FilterGeometry( OGRGeometry *, OGREnvelope* psGeometryEnvelope);
     int          InstallFilter( OGRGeometry * );
-    
+
     OGRErr       GetExtentInternal(int iGeomField, OGREnvelope *psExtent, int bForce );
 
-    virtual OGRErr      ISetFeature( OGRFeature *poFeature );
-    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
+    virtual OGRErr      ISetFeature( OGRFeature *poFeature ) CPL_WARN_UNUSED_RESULT;
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature )  CPL_WARN_UNUSED_RESULT;
 
   public:
     OGRLayer();
@@ -102,14 +102,14 @@ class CPL_DLL OGRLayer : public GDALMajorObject
     virtual OGRErr      SetAttributeFilter( const char * );
 
     virtual void        ResetReading() = 0;
-    virtual OGRFeature *GetNextFeature() = 0;
+    virtual OGRFeature *GetNextFeature() CPL_WARN_UNUSED_RESULT = 0;
     virtual OGRErr      SetNextByIndex( GIntBig nIndex );
-    virtual OGRFeature *GetFeature( GIntBig nFID );
+    virtual OGRFeature *GetFeature( GIntBig nFID )  CPL_WARN_UNUSED_RESULT;
 
-    OGRErr      SetFeature( OGRFeature *poFeature );
-    OGRErr      CreateFeature( OGRFeature *poFeature );
+    OGRErr      SetFeature( OGRFeature *poFeature )  CPL_WARN_UNUSED_RESULT;
+    OGRErr      CreateFeature( OGRFeature *poFeature ) CPL_WARN_UNUSED_RESULT;
 
-    virtual OGRErr      DeleteFeature( GIntBig nFID );
+    virtual OGRErr      DeleteFeature( GIntBig nFID )  CPL_WARN_UNUSED_RESULT;
 
     virtual const char *GetName();
     virtual OGRwkbGeometryType GetGeomType();
@@ -119,9 +119,9 @@ class CPL_DLL OGRLayer : public GDALMajorObject
     virtual OGRSpatialReference *GetSpatialRef();
 
     virtual GIntBig     GetFeatureCount( int bForce = TRUE );
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE)  CPL_WARN_UNUSED_RESULT;
     virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent,
-                                  int bForce = TRUE);
+                                  int bForce = TRUE)  CPL_WARN_UNUSED_RESULT;
 
     virtual int         TestCapability( const char * ) = 0;
 
@@ -138,11 +138,11 @@ class CPL_DLL OGRLayer : public GDALMajorObject
 
     virtual OGRStyleTable *GetStyleTable();
     virtual void        SetStyleTableDirectly( OGRStyleTable *poStyleTable );
-                            
+
     virtual void        SetStyleTable(OGRStyleTable *poStyleTable);
 
-    virtual OGRErr      StartTransaction();
-    virtual OGRErr      CommitTransaction();
+    virtual OGRErr      StartTransaction() CPL_WARN_UNUSED_RESULT;
+    virtual OGRErr      CommitTransaction() CPL_WARN_UNUSED_RESULT;
     virtual OGRErr      RollbackTransaction();
 
     virtual const char *GetFIDColumn();
@@ -150,49 +150,49 @@ class CPL_DLL OGRLayer : public GDALMajorObject
 
     virtual OGRErr      SetIgnoredFields( const char **papszFields );
 
-    OGRErr              Intersection( OGRLayer *pLayerMethod, 
-                                      OGRLayer *pLayerResult, 
-                                      char** papszOptions = NULL, 
-                                      GDALProgressFunc pfnProgress = NULL, 
+    OGRErr              Intersection( OGRLayer *pLayerMethod,
+                                      OGRLayer *pLayerResult,
+                                      char** papszOptions = NULL,
+                                      GDALProgressFunc pfnProgress = NULL,
                                       void * pProgressArg = NULL );
-    OGRErr              Union( OGRLayer *pLayerMethod, 
-                               OGRLayer *pLayerResult, 
-                               char** papszOptions = NULL, 
-                               GDALProgressFunc pfnProgress = NULL, 
+    OGRErr              Union( OGRLayer *pLayerMethod,
+                               OGRLayer *pLayerResult,
+                               char** papszOptions = NULL,
+                               GDALProgressFunc pfnProgress = NULL,
                                void * pProgressArg = NULL );
-    OGRErr              SymDifference( OGRLayer *pLayerMethod, 
-                                       OGRLayer *pLayerResult, 
-                                       char** papszOptions, 
-                                       GDALProgressFunc pfnProgress, 
+    OGRErr              SymDifference( OGRLayer *pLayerMethod,
+                                       OGRLayer *pLayerResult,
+                                       char** papszOptions,
+                                       GDALProgressFunc pfnProgress,
                                        void * pProgressArg );
-    OGRErr              Identity( OGRLayer *pLayerMethod, 
-                                  OGRLayer *pLayerResult, 
-                                  char** papszOptions = NULL, 
-                                  GDALProgressFunc pfnProgress = NULL, 
+    OGRErr              Identity( OGRLayer *pLayerMethod,
+                                  OGRLayer *pLayerResult,
+                                  char** papszOptions = NULL,
+                                  GDALProgressFunc pfnProgress = NULL,
                                   void * pProgressArg = NULL );
-    OGRErr              Update( OGRLayer *pLayerMethod, 
-                                OGRLayer *pLayerResult, 
-                                char** papszOptions = NULL, 
-                                GDALProgressFunc pfnProgress = NULL, 
+    OGRErr              Update( OGRLayer *pLayerMethod,
+                                OGRLayer *pLayerResult,
+                                char** papszOptions = NULL,
+                                GDALProgressFunc pfnProgress = NULL,
                                 void * pProgressArg = NULL );
-    OGRErr              Clip( OGRLayer *pLayerMethod, 
-                              OGRLayer *pLayerResult, 
-                              char** papszOptions = NULL, 
-                              GDALProgressFunc pfnProgress = NULL, 
+    OGRErr              Clip( OGRLayer *pLayerMethod,
+                              OGRLayer *pLayerResult,
+                              char** papszOptions = NULL,
+                              GDALProgressFunc pfnProgress = NULL,
                               void * pProgressArg = NULL );
-    OGRErr              Erase( OGRLayer *pLayerMethod, 
-                               OGRLayer *pLayerResult, 
-                               char** papszOptions = NULL, 
-                               GDALProgressFunc pfnProgress = NULL, 
+    OGRErr              Erase( OGRLayer *pLayerMethod,
+                               OGRLayer *pLayerResult,
+                               char** papszOptions = NULL,
+                               GDALProgressFunc pfnProgress = NULL,
                                void * pProgressArg = NULL );
-    
+
     int                 Reference();
     int                 Dereference();
     int                 GetRefCount() const;
 
     GIntBig             GetFeaturesRead();
 
-    /* non virtual : conveniency wrapper for ReorderFields() */
+    /* non virtual : convenience wrapper for ReorderFields() */
     OGRErr              ReorderField( int iOldFieldPos, int iNewFieldPos );
 
     int                 AttributeFilterEvaluationNeedsGeometry();
@@ -219,7 +219,7 @@ class CPL_DLL OGRLayer : public GDALMajorObject
 /**
  * LEGACY class. Use GDALDataset in your new code ! This class may be
  * removed in a later release.
- * 
+ *
  * This class represents a data source.  A data source potentially
  * consists of many layers (OGRLayer).  A data source normally consists
  * of one, or a related set of files, though the name doesn't have to be
@@ -233,7 +233,7 @@ class CPL_DLL OGRLayer : public GDALMajorObject
  * is needed, the handle should be cast to GDALDataset*.
  *
  * @deprecated
- */ 
+ */
 
 class CPL_DLL OGRDataSource : public GDALDataset
 {
@@ -275,7 +275,7 @@ class CPL_DLL OGRSFDriver : public GDALDriver
     virtual const char  *GetName() OGR_DEPRECATED("Use GDALDriver class instead") = 0;
 
     virtual OGRDataSource *Open( const char *pszName, int bUpdate=FALSE ) OGR_DEPRECATED("Use GDALDriver class instead") = 0;
-    
+
     virtual int            TestCapability( const char *pszCap ) OGR_DEPRECATED("Use GDALDriver class instead") = 0;
 
     virtual OGRDataSource *CreateDataSource( const char *pszName,
@@ -293,7 +293,7 @@ class CPL_DLL OGRSFDriver : public GDALDriver
  * removed in a later release.
  *
  * Singleton manager for OGRSFDriver instances that will be used to try
- * and open datasources.  Normally the registrar is populated with 
+ * and open datasources.  Normally the registrar is populated with
  * standard drivers using the OGRRegisterAll() function and does not need
  * to be directly accessed.  The driver registrar and all registered drivers
  * may be cleaned up on shutdown using OGRCleanupAll().
@@ -338,6 +338,7 @@ void OGRRegisterAllInternal();
 
 void CPL_DLL RegisterOGRFileGDB();
 void CPL_DLL RegisterOGRShape();
+void CPL_DLL RegisterOGRDB2();
 void CPL_DLL RegisterOGRNTF();
 void CPL_DLL RegisterOGRFME();
 void CPL_DLL RegisterOGRSDTS();
@@ -398,7 +399,6 @@ void CPL_DLL RegisterOGRGeomedia();
 void CPL_DLL RegisterOGRMDB();
 void CPL_DLL RegisterOGREDIGEO();
 void CPL_DLL RegisterOGRGFT();
-void CPL_DLL RegisterOGRGME();
 void CPL_DLL RegisterOGRSVG();
 void CPL_DLL RegisterOGRCouchDB();
 void CPL_DLL RegisterOGRCloudant();
@@ -413,13 +413,15 @@ void CPL_DLL RegisterOGRElastic();
 void CPL_DLL RegisterOGRGeoPackage();
 void CPL_DLL RegisterOGRWalk();
 void CPL_DLL RegisterOGRCartoDB();
+void CPL_DLL RegisterOGRAmigoCloud();
 void CPL_DLL RegisterOGRSXF();
 void CPL_DLL RegisterOGROpenFileGDB();
 void CPL_DLL RegisterOGRSelafin();
 void CPL_DLL RegisterOGRJML();
 void CPL_DLL RegisterOGRPLSCENES();
 void CPL_DLL RegisterOGRCSW();
+void CPL_DLL RegisterOGRMongoDB();
+void CPL_DLL RegisterOGRVDV();
 CPL_C_END
 
-
-#endif /* ndef _OGRSF_FRMTS_H_INCLUDED */
+#endif /* ndef OGRSF_FRMTS_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/openair/drv_openair.html b/ogr/ogrsf_frmts/openair/drv_openair.html
index 720d78d..c7987f4 100644
--- a/ogr/ogrsf_frmts/openair/drv_openair.html
+++ b/ogr/ogrsf_frmts/openair/drv_openair.html
@@ -11,12 +11,16 @@
 
 This driver reads files describing Special Use Airspaces in the OpenAir format<p>
 
-Airspace are returned as features of a single layer called 'airspaces', with a geometry of type Polygon and the following fields :
-CLASS, NAME, FLOOR, CEILING.<p>
+Airspace are returned as features of a single layer called 'airspaces', with a
+geometry of type Polygon and the following fields: CLASS, NAME, FLOOR, CEILING.
+<p>
 
-Airspace geometries made of arcs will be tesselated. Styling information when present is returned at the feature level.<p>
+Airspace geometries made of arcs will be tessellated. Styling information when
+present is returned at the feature level.<p>
 
-An extra layer called 'labels' will contain a feature for each label (AT element). There can be multiple AT records for a single airspace segment. The fields are the same as the 'airspaces' layer.<p>
+An extra layer called 'labels' will contain a feature for each label (AT
+element). There can be multiple AT records for a single airspace segment. The
+fields are the same as the 'airspaces' layer.<p>
 
 <h3>See Also</h3>
 
diff --git a/ogr/ogrsf_frmts/openair/ogr_openair.h b/ogr/ogrsf_frmts/openair/ogr_openair.h
index fa7d963..895c04c 100644
--- a/ogr/ogrsf_frmts/openair/ogr_openair.h
+++ b/ogr/ogrsf_frmts/openair/ogr_openair.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_openair.h 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogr_openair.h 32976 2016-01-14 00:07:34Z goatbar $
  *
  * Project:  OpenAir Translator
  * Purpose:  Definition of classes for OGR .sua driver.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_OPENAIR_H_INCLUDED
-#define _OGR_OPENAIR_H_INCLUDED
+#ifndef OGR_OPENAIR_H_INCLUDED
+#define OGR_OPENAIR_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include <map>
@@ -42,7 +42,9 @@ typedef struct
     int penStyle;
     int penWidth;
     int penR, penG, penB;
-    int fillR, fillG, fillB;
+    int fillR;
+    int fillG;
+    int fillB;
 } OpenAirStyle;
 
 class OGROpenAirLayer : public OGRLayer
@@ -51,8 +53,8 @@ class OGROpenAirLayer : public OGRLayer
     OGRSpatialReference *poSRS;
 
     VSILFILE*          fpOpenAir;
-    int                bEOF;
-    int                bHasLastLine;
+    bool               bEOF;
+    bool               bHasLastLine;
     CPLString          osLastLine;
 
     int                nNextFID;
@@ -90,13 +92,15 @@ class OGROpenAirLabelLayer : public OGRLayer
 
     OGRFeature *       GetNextRawFeature();
 
-    CPLString          osCLASS, osNAME, osFLOOR, osCEILING;
+    CPLString          osCLASS;
+    CPLString          osNAME;
+    CPLString          osFLOOR;
+    CPLString          osCEILING;
 
   public:
                         OGROpenAirLabelLayer(VSILFILE* fp);
                         ~OGROpenAirLabelLayer();
 
-
     virtual void                ResetReading();
     virtual OGRFeature *        GetNextFeature();
 
@@ -130,6 +134,6 @@ class OGROpenAirDataSource : public OGRDataSource
     virtual int                 TestCapability( const char * );
 };
 
-int OGROpenAirGetLatLon(const char* pszStr, double& dfLat, double& dfLon);
+bool OGROpenAirGetLatLon( const char* pszStr, double& dfLat, double& dfLon );
 
-#endif /* ndef _OGR_OPENAIR_H_INCLUDED */
+#endif /* ndef OGR_OPENAIR_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/openair/ogropenairdatasource.cpp b/ogr/ogrsf_frmts/openair/ogropenairdatasource.cpp
index 1af84d0..089a454 100644
--- a/ogr/ogrsf_frmts/openair/ogropenairdatasource.cpp
+++ b/ogr/ogrsf_frmts/openair/ogropenairdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogropenairdatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogropenairdatasource.cpp 32976 2016-01-14 00:07:34Z goatbar $
  *
  * Project:  OpenAir Translator
  * Purpose:  Implements OGROpenAirDataSource class
@@ -31,20 +31,17 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogropenairdatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogropenairdatasource.cpp 32976 2016-01-14 00:07:34Z goatbar $");
 
 /************************************************************************/
 /*                        OGROpenAirDataSource()                        */
 /************************************************************************/
 
-OGROpenAirDataSource::OGROpenAirDataSource()
-
-{
-    papoLayers = NULL;
-    nLayers = 0;
-
-    pszName = NULL;
-}
+OGROpenAirDataSource::OGROpenAirDataSource() :
+    pszName(NULL),
+    papoLayers(NULL),
+    nLayers(0)
+{}
 
 /************************************************************************/
 /*                       ~OGROpenAirDataSource()                        */
@@ -64,7 +61,7 @@ OGROpenAirDataSource::~OGROpenAirDataSource()
 /*                           TestCapability()                           */
 /************************************************************************/
 
-int OGROpenAirDataSource::TestCapability( CPL_UNUSED const char * pszCap )
+int OGROpenAirDataSource::TestCapability( const char * /* pszCap */ )
 {
     return FALSE;
 }
@@ -78,8 +75,8 @@ OGRLayer *OGROpenAirDataSource::GetLayer( int iLayer )
 {
     if( iLayer < 0 || iLayer >= nLayers )
         return NULL;
-    else
-        return papoLayers[iLayer];
+
+    return papoLayers[iLayer];
 }
 
 /************************************************************************/
@@ -119,33 +116,38 @@ int OGROpenAirDataSource::Open( const char * pszFilename )
 
 enum { DEGREE, MINUTE, SECOND };
 
-int OGROpenAirGetLatLon(const char* pszStr, double& dfLat, double& dfLon)
+bool OGROpenAirGetLatLon( const char* pszStr, double& dfLat, double& dfLon )
 {
     dfLat = 0;
     dfLon = 0;
 
-    int nCurInt = 0;
+    GUIntBig nCurInt = 0;
     double dfExp = 1.;
-    int bHasExp = FALSE;
+    bool bHasExp = false;
     int nCurPart = DEGREE;
-    double dfDegree = 0, dfMinute = 0, dfSecond = 0;
+    double dfDegree = 0;
+    double dfMinute = 0;
+    double dfSecond = 0;
     char c;
-    int bHasLat = FALSE, bHasLon = FALSE;
+    bool bHasLat = false;
+    bool bHasLon = false;
     while((c = *pszStr) != 0)
     {
         if (c >= '0' && c <= '9')
         {
-            nCurInt = nCurInt * 10 + c - '0';
-            if (bHasExp)
+            nCurInt = nCurInt * 10U + static_cast<unsigned char>(c) - '0';
+            if( nCurInt >> 60 ) // to avoid uint64 overflow at next iteration
+                return FALSE;
+            if( bHasExp )
                 dfExp *= 10;
         }
         else if (c == '.')
         {
-            bHasExp = TRUE;
+            bHasExp = true;
         }
         else if (c == ':')
         {
-            double dfVal = nCurInt / dfExp;
+            const double dfVal = nCurInt / dfExp;
             if (nCurPart == DEGREE)
                 dfDegree = dfVal;
             else if (nCurPart == MINUTE)
@@ -155,7 +157,7 @@ int OGROpenAirGetLatLon(const char* pszStr, double& dfLat, double& dfLon)
             nCurPart ++;
             nCurInt = 0;
             dfExp = 1.;
-            bHasExp = FALSE;
+            bHasExp = false;
         }
         else if (c == ' ')
         {
@@ -163,7 +165,7 @@ int OGROpenAirGetLatLon(const char* pszStr, double& dfLat, double& dfLon)
         }
         else if (c == 'N' || c == 'S')
         {
-            double dfVal = nCurInt / dfExp;
+            const double dfVal = nCurInt / dfExp;
             if (nCurPart == DEGREE)
                 dfDegree = dfVal;
             else if (nCurPart == MINUTE)
@@ -176,13 +178,13 @@ int OGROpenAirGetLatLon(const char* pszStr, double& dfLat, double& dfLon)
                 dfLat = -dfLat;
             nCurInt = 0;
             dfExp = 1.;
-            bHasExp = FALSE;
+            bHasExp = false;
             nCurPart = DEGREE;
-            bHasLat = TRUE;
+            bHasLat = true;
         }
         else if (c == 'E' || c == 'W')
         {
-            double dfVal = nCurInt / dfExp;
+            const double dfVal = nCurInt / dfExp;
             if (nCurPart == DEGREE)
                 dfDegree = dfVal;
             else if (nCurPart == MINUTE)
@@ -193,7 +195,7 @@ int OGROpenAirGetLatLon(const char* pszStr, double& dfLat, double& dfLon)
             dfLon = dfDegree + dfMinute / 60 + dfSecond / 3600;
             if (c == 'W')
                 dfLon = -dfLon;
-            bHasLon = TRUE;
+            bHasLon = true;
             break;
         }
 
diff --git a/ogr/ogrsf_frmts/openair/ogropenairdriver.cpp b/ogr/ogrsf_frmts/openair/ogropenairdriver.cpp
index 61ef2ef..9af6d1d 100644
--- a/ogr/ogrsf_frmts/openair/ogropenairdriver.cpp
+++ b/ogr/ogrsf_frmts/openair/ogropenairdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogropenairdriver.cpp 29253 2015-05-27 08:49:16Z rouault $
+ * $Id: ogropenairdriver.cpp 32976 2016-01-14 00:07:34Z goatbar $
  *
  * Project:  OpenAir Translator
  * Purpose:  Implements OGROpenAirDriver.
@@ -27,12 +27,11 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_openair.h"
 #include "cpl_conv.h"
+#include "ogr_openair.h"
+#include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: ogropenairdriver.cpp 29253 2015-05-27 08:49:16Z rouault $");
-
-extern "C" void RegisterOGROpenAir();
+CPL_CVSID("$Id: ogropenairdriver.cpp 32976 2016-01-14 00:07:34Z goatbar $");
 
 /************************************************************************/
 /*                                Open()                                */
@@ -46,21 +45,25 @@ static GDALDataset *OGROpenAirDriverOpen( GDALOpenInfo* poOpenInfo )
         !poOpenInfo->TryToIngest(10000) )
         return NULL;
 
-    int bIsOpenAir = (strstr((const char*)poOpenInfo->pabyHeader, "\nAC ") != NULL &&
-                  strstr((const char*)poOpenInfo->pabyHeader, "\nAN ") != NULL &&
-                  strstr((const char*)poOpenInfo->pabyHeader, "\nAL ") != NULL &&
-                  strstr((const char*)poOpenInfo->pabyHeader, "\nAH") != NULL);
+    const char *pabyHeader = reinterpret_cast<char *>(poOpenInfo->pabyHeader);
+    bool bIsOpenAir =
+        strstr(pabyHeader, "\nAC ") != NULL &&
+        strstr(pabyHeader, "\nAN ") != NULL &&
+        strstr(pabyHeader, "\nAL ") != NULL &&
+        strstr(pabyHeader, "\nAH") != NULL;
     if( !bIsOpenAir )
     {
-        /* Some files such http://soaringweb.org/Airspace/CZ/CZ_combined_2014_05_01.txt */
-        /* have very long comments in the header, so we will have to check */
-        /* further, but only do this is we have a hint that the file might be */
-        /* a candidate */
+        // Some files, such as
+        // http://soaringweb.org/Airspace/CZ/CZ_combined_2014_05_01.txt ,
+        // have very long comments in the header, so we will have to
+        // check further, but only do this is we have a hint that the
+        // file might be a candidate.
         int nLen = poOpenInfo->nHeaderBytes;
         if( nLen < 10000 )
             return NULL;
         /* Check the 'Airspace' word in the header */
-        if( strstr((const char*)poOpenInfo->pabyHeader, "Airspace") == NULL )
+        if( strstr(pabyHeader, "Airspace")
+            == NULL )
             return NULL;
         // Check that the header is at least UTF-8
         // but do not take into account partial UTF-8 characters at the end
@@ -76,19 +79,20 @@ static GDALDataset *OGROpenAirDriverOpen( GDALOpenInfo* poOpenInfo )
             if( nTruncated == 7 )
                 return NULL;
         }
-        if( !CPLIsUTF8((const char*)poOpenInfo->pabyHeader, nLen) )
+        if( !CPLIsUTF8(pabyHeader, nLen) )
             return NULL;
         if( !poOpenInfo->TryToIngest(30000) )
             return NULL;
-        bIsOpenAir = (strstr((const char*)poOpenInfo->pabyHeader, "\nAC ") != NULL &&
-                  strstr((const char*)poOpenInfo->pabyHeader, "\nAN ") != NULL &&
-                  strstr((const char*)poOpenInfo->pabyHeader, "\nAL ") != NULL &&
-                  strstr((const char*)poOpenInfo->pabyHeader, "\nAH") != NULL);
+        bIsOpenAir =
+            strstr(pabyHeader, "\nAC ") != NULL &&
+            strstr(pabyHeader, "\nAN ") != NULL &&
+            strstr(pabyHeader, "\nAL ") != NULL &&
+            strstr(pabyHeader, "\nAH") != NULL;
         if( !bIsOpenAir )
             return NULL;
     }
 
-    OGROpenAirDataSource   *poDS = new OGROpenAirDataSource();
+    OGROpenAirDataSource *poDS = new OGROpenAirDataSource();
 
     if( !poDS->Open( poOpenInfo->pszFilename ) )
     {
@@ -106,24 +110,19 @@ static GDALDataset *OGROpenAirDriverOpen( GDALOpenInfo* poOpenInfo )
 void RegisterOGROpenAir()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "OpenAir" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "OpenAir" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-
-        poDriver->SetDescription( "OpenAir" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "OpenAir" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_openair.html" );
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetDescription( "OpenAir" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "OpenAir" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_openair.html" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = OGROpenAirDriverOpen;
+    poDriver->pfnOpen = OGROpenAirDriverOpen;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
 
diff --git a/ogr/ogrsf_frmts/openair/ogropenairlabellayer.cpp b/ogr/ogrsf_frmts/openair/ogropenairlabellayer.cpp
index 495966c..2153793 100644
--- a/ogr/ogrsf_frmts/openair/ogropenairlabellayer.cpp
+++ b/ogr/ogrsf_frmts/openair/ogropenairlabellayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogropenairlabellayer.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogropenairlabellayer.cpp 32976 2016-01-14 00:07:34Z goatbar $
  *
  * Project:  OpenAir Translator
  * Purpose:  Implements OGROpenAirLabelLayer class.
@@ -27,27 +27,24 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_openair.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "ogr_openair.h"
 #include "ogr_p.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ogropenairlabellayer.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogropenairlabellayer.cpp 32976 2016-01-14 00:07:34Z goatbar $");
 
 /************************************************************************/
 /*                      OGROpenAirLabelLayer()                          */
 /************************************************************************/
 
-OGROpenAirLabelLayer::OGROpenAirLabelLayer( VSILFILE* fp )
-
+OGROpenAirLabelLayer::OGROpenAirLabelLayer( VSILFILE* fp ) :
+    poFeatureDefn(new OGRFeatureDefn("labels")),
+    poSRS(new OGRSpatialReference(SRS_WKT_WGS84)),
+    fpOpenAir(fp),
+    nNextFID(0)
 {
-    fpOpenAir = fp;
-    nNextFID = 0;
-
-    poSRS = new OGRSpatialReference(SRS_WKT_WGS84);
-
-    poFeatureDefn = new OGRFeatureDefn( "labels"  );
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbPoint );
@@ -97,11 +94,9 @@ void OGROpenAirLabelLayer::ResetReading()
 
 OGRFeature *OGROpenAirLabelLayer::GetNextFeature()
 {
-    OGRFeature  *poFeature;
-
-    while(TRUE)
+    while( true )
     {
-        poFeature = GetNextRawFeature();
+        OGRFeature *poFeature = GetNextRawFeature();
         if (poFeature == NULL)
             return NULL;
 
@@ -112,8 +107,8 @@ OGRFeature *OGROpenAirLabelLayer::GetNextFeature()
         {
             return poFeature;
         }
-        else
-            delete poFeature;
+
+        delete poFeature;
     }
 }
 
@@ -123,20 +118,20 @@ OGRFeature *OGROpenAirLabelLayer::GetNextFeature()
 
 OGRFeature *OGROpenAirLabelLayer::GetNextRawFeature()
 {
-    const char* pszLine;
-    double dfLat = 0, dfLon = 0;
-    int bHasCoord = FALSE;
+    double dfLat = 0;
+    double dfLon = 0;
+    bool bHasCoord = false;
 
-    while(TRUE)
+    while( true )
     {
-        pszLine = CPLReadLine2L(fpOpenAir, 1024, NULL);
+        const char* pszLine = CPLReadLine2L(fpOpenAir, 1024, NULL);
         if (pszLine == NULL)
             return NULL;
 
         if (pszLine[0] == '*' || pszLine[0] == '\0')
             continue;
 
-        if (EQUALN(pszLine, "AC ", 3))
+        if (STARTS_WITH_CI(pszLine, "AC "))
         {
             if (osCLASS.size() != 0)
             {
@@ -146,13 +141,13 @@ OGRFeature *OGROpenAirLabelLayer::GetNextRawFeature()
             }
             osCLASS = pszLine + 3;
         }
-        else if (EQUALN(pszLine, "AN ", 3))
+        else if (STARTS_WITH_CI(pszLine, "AN "))
             osNAME = pszLine + 3;
-        else if (EQUALN(pszLine, "AH ", 3))
+        else if (STARTS_WITH_CI(pszLine, "AH "))
             osCEILING = pszLine + 3;
-        else if (EQUALN(pszLine, "AL ", 3))
+        else if (STARTS_WITH_CI(pszLine, "AL "))
             osFLOOR = pszLine + 3;
-        else if (EQUALN(pszLine, "AT ", 3))
+        else if (STARTS_WITH_CI(pszLine, "AT "))
         {
             bHasCoord = OGROpenAirGetLatLon(pszLine + 3, dfLat, dfLon);
             break;
@@ -185,7 +180,7 @@ OGRFeature *OGROpenAirLabelLayer::GetNextRawFeature()
 /*                           TestCapability()                           */
 /************************************************************************/
 
-int OGROpenAirLabelLayer::TestCapability( CPL_UNUSED const char * pszCap )
+int OGROpenAirLabelLayer::TestCapability( const char * /* pszCap */ )
 {
     return FALSE;
 }
diff --git a/ogr/ogrsf_frmts/openair/ogropenairlayer.cpp b/ogr/ogrsf_frmts/openair/ogropenairlayer.cpp
index 005b6e3..3f1c449 100644
--- a/ogr/ogrsf_frmts/openair/ogropenairlayer.cpp
+++ b/ogr/ogrsf_frmts/openair/ogropenairlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogropenairlayer.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: ogropenairlayer.cpp 32977 2016-01-14 00:52:59Z goatbar $
  *
  * Project:  OpenAir Translator
  * Purpose:  Implements OGROpenAirLayer class.
@@ -27,30 +27,27 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_openair.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
 #include "ogr_p.h"
-#include "ogr_xplane_geo_utils.h"
+#include "ogr_openair.h"
 #include "ogr_srs_api.h"
+#include "ogr_xplane_geo_utils.h"
 
-CPL_CVSID("$Id: ogropenairlayer.cpp 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: ogropenairlayer.cpp 32977 2016-01-14 00:52:59Z goatbar $");
 
 /************************************************************************/
 /*                         OGROpenAirLayer()                            */
 /************************************************************************/
 
-OGROpenAirLayer::OGROpenAirLayer( VSILFILE* fp )
-
+OGROpenAirLayer::OGROpenAirLayer( VSILFILE* fp ) :
+    poFeatureDefn(new OGRFeatureDefn( "airspaces" )),
+    poSRS(new OGRSpatialReference(SRS_WKT_WGS84)),
+    fpOpenAir(fp),
+    bEOF(false),
+    bHasLastLine(false),
+    nNextFID(0)
 {
-    fpOpenAir = fp;
-    nNextFID = 0;
-    bEOF = FALSE;
-    bHasLastLine = FALSE;
-
-    poSRS = new OGRSpatialReference(SRS_WKT_WGS84);
-
-    poFeatureDefn = new OGRFeatureDefn( "airspaces" );
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbPolygon );
@@ -97,8 +94,8 @@ void OGROpenAirLayer::ResetReading()
 
 {
     nNextFID = 0;
-    bEOF = FALSE;
-    bHasLastLine = FALSE;
+    bEOF = false;
+    bHasLastLine = false;
     VSIFSeekL( fpOpenAir, 0, SEEK_SET );
 }
 
@@ -109,11 +106,9 @@ void OGROpenAirLayer::ResetReading()
 
 OGRFeature *OGROpenAirLayer::GetNextFeature()
 {
-    OGRFeature  *poFeature;
-
-    while(TRUE)
+    while( true )
     {
-        poFeature = GetNextRawFeature();
+        OGRFeature *poFeature = GetNextRawFeature();
         if (poFeature == NULL)
             return NULL;
 
@@ -124,8 +119,8 @@ OGRFeature *OGROpenAirLayer::GetNextFeature()
         {
             return poFeature;
         }
-        else
-            delete poFeature;
+
+        delete poFeature;
     }
 }
 
@@ -135,36 +130,39 @@ OGRFeature *OGROpenAirLayer::GetNextFeature()
 
 OGRFeature *OGROpenAirLayer::GetNextRawFeature()
 {
-    const char* pszLine;
-    CPLString osCLASS, osNAME, osFLOOR, osCEILING;
+    if( bEOF )
+        return NULL;
+
+    CPLString osCLASS;
+    CPLString osNAME;
+    CPLString osFLOOR;
+    CPLString osCEILING;
     OGRLinearRing oLR;
     /* double dfLastLat = 0, dfLastLon = 0; */
-    int bFirst = TRUE;
-    int bClockWise = TRUE;
+    bool bFirst = true;
+    bool bClockWise = true;
     double dfCenterLat = 0, dfCenterLon = 0;
-    int bHasCenter = FALSE;
+    bool bHasCenter = false;
     OpenAirStyle sStyle;
     sStyle.penStyle = -1;
     sStyle.penWidth = -1;
     sStyle.penR = sStyle.penG = sStyle.penB = -1;
     sStyle.fillR = sStyle.fillG = sStyle.fillB = -1;
 
-    if (bEOF)
-        return NULL;
-
-    while(TRUE)
+    while( true )
     {
-        if (bFirst && bHasLastLine)
+        const char* pszLine = NULL;
+        if( bFirst && bHasLastLine )
         {
             pszLine = osLastLine.c_str();
-            bFirst = FALSE;
+            bFirst = false;
         }
         else
         {
             pszLine = CPLReadLine2L(fpOpenAir, 1024, NULL);
             if (pszLine == NULL)
             {
-                bEOF = TRUE;
+                bEOF = true;
                 if (oLR.getNumPoints() == 0)
                     return NULL;
 
@@ -176,13 +174,13 @@ OGRFeature *OGROpenAirLayer::GetNextRawFeature()
                 break;
             }
             osLastLine = pszLine;
-            bHasLastLine = TRUE;
+            bHasLastLine = true;
         }
 
         if (pszLine[0] == '*' || pszLine[0] == '\0')
             continue;
 
-        if (EQUALN(pszLine, "AC ", 3) || EQUALN(pszLine, "AC,", 3))
+        if (STARTS_WITH_CI(pszLine, "AC ") || STARTS_WITH_CI(pszLine, "AC,"))
         {
             if (osCLASS.size() != 0)
             {
@@ -217,24 +215,24 @@ OGRFeature *OGROpenAirLayer::GetNextRawFeature()
             sStyle.penR = sStyle.penG = sStyle.penB = -1;
             sStyle.fillR = sStyle.fillG = sStyle.fillB = -1;
             osCLASS = pszLine + 3;
-            bClockWise = TRUE;
-            bHasCenter = FALSE;
+            bClockWise = true;
+            bHasCenter = false;
         }
-        else if (EQUALN(pszLine, "AN ", 3))
+        else if (STARTS_WITH_CI(pszLine, "AN "))
         {
             if (osNAME.size() != 0)
                 break;
             osNAME = pszLine + 3;
         }
-        else if (EQUALN(pszLine, "AH ", 3))
+        else if (STARTS_WITH_CI(pszLine, "AH "))
             osCEILING = pszLine + 3;
-        else if (EQUALN(pszLine, "AL ", 3))
+        else if (STARTS_WITH_CI(pszLine, "AL "))
             osFLOOR = pszLine + 3;
-        else if (EQUALN(pszLine, "AT ", 3))
+        else if (STARTS_WITH_CI(pszLine, "AT "))
         {
             /* Ignored for that layer*/
         }
-        else if (EQUALN(pszLine, "SP ", 3))
+        else if (STARTS_WITH_CI(pszLine, "SP "))
         {
             if (osCLASS.size() != 0)
             {
@@ -250,7 +248,7 @@ OGRFeature *OGROpenAirLayer::GetNextRawFeature()
                 CSLDestroy(papszTokens);
             }
         }
-        else if (EQUALN(pszLine, "SB ", 3))
+        else if (STARTS_WITH_CI(pszLine, "SB "))
         {
             if (osCLASS.size() != 0)
             {
@@ -264,11 +262,12 @@ OGRFeature *OGROpenAirLayer::GetNextRawFeature()
                 CSLDestroy(papszTokens);
             }
         }
-        else if (EQUALN(pszLine, "DP ", 3))
+        else if (STARTS_WITH_CI(pszLine, "DP "))
         {
             pszLine += 3;
 
-            double dfLat, dfLon;
+            double dfLat;
+            double dfLon;
             if (!OGROpenAirGetLatLon(pszLine, dfLat, dfLon))
                 continue;
 
@@ -276,17 +275,19 @@ OGRFeature *OGROpenAirLayer::GetNextRawFeature()
             /* dfLastLat = dfLat; */
             /* dfLastLon = dfLon; */
         }
-        else if (EQUALN(pszLine, "DA ", 3))
+        else if (STARTS_WITH_CI(pszLine, "DA "))
         {
             pszLine += 3;
 
-            char* pszStar = strchr((char*)pszLine, '*');
+            // TODO: Explain why writing a zero over the star.
+            char* pszStar = strchr(const_cast<char *>(pszLine), '*');
             if (pszStar) *pszStar = 0;
             char** papszTokens = CSLTokenizeString2(pszLine, ",", 0);
             if (bHasCenter && CSLCount(papszTokens) == 3)
             {
-                double dfRadius = CPLAtof(papszTokens[0]) * 1852;
-                double dfStartAngle = CPLAtof(papszTokens[1]);
+                // TODO: Explain the 1852.
+                const double dfRadius = CPLAtof(papszTokens[0]) * 1852;
+                const double dfStartAngle = CPLAtof(papszTokens[1]);
                 double dfEndAngle = CPLAtof(papszTokens[2]);
 
                 if (bClockWise && dfEndAngle < dfStartAngle)
@@ -294,25 +295,26 @@ OGRFeature *OGROpenAirLayer::GetNextRawFeature()
                 else if (!bClockWise && dfStartAngle < dfEndAngle)
                     dfEndAngle -= 360;
 
-                double dfStartDistance = dfRadius;
-                double dfEndDistance = dfRadius;
-                int nSign = (bClockWise) ? 1 : -1;
-                double dfAngle;
-                double dfLat, dfLon;
-                for(dfAngle = dfStartAngle;
+                const double dfStartDistance = dfRadius;
+                const double dfEndDistance = dfRadius;
+                const int nSign = (bClockWise) ? 1 : -1;
+                double dfLat;
+                double dfLon;
+                for(double dfAngle = dfStartAngle;
                     (dfAngle - dfEndAngle) * nSign < 0;
                     dfAngle += nSign)
                 {
-                    double pct = (dfAngle - dfStartAngle) /
-                                    (dfEndAngle - dfStartAngle);
-                    double dfDist = dfStartDistance * (1-pct) +
-                                                        dfEndDistance * pct;
+                    const double pct = (dfAngle - dfStartAngle) /
+                        (dfEndAngle - dfStartAngle);
+                    const double dfDist = dfStartDistance * (1-pct) +
+                        dfEndDistance * pct;
                     OGRXPlane_ExtendPosition(dfCenterLat, dfCenterLon,
                                              dfDist, dfAngle, &dfLat, &dfLon);
                     oLR.addPoint(dfLon, dfLat);
                 }
-                OGRXPlane_ExtendPosition(dfCenterLat, dfCenterLon,
-                                         dfEndDistance, dfEndAngle, &dfLat, &dfLon);
+                OGRXPlane_ExtendPosition(
+                    dfCenterLat, dfCenterLon,
+                    dfEndDistance, dfEndAngle, &dfLat, &dfLon );
                 oLR.addPoint(dfLon, dfLat);
 
                 /* dfLastLat = oLR.getY(oLR.getNumPoints() - 1); */
@@ -320,24 +322,26 @@ OGRFeature *OGROpenAirLayer::GetNextRawFeature()
             }
             CSLDestroy(papszTokens);
         }
-        else if (EQUALN(pszLine, "DB ", 3))
+        else if (STARTS_WITH_CI(pszLine, "DB "))
         {
             pszLine += 3;
 
-            char* pszStar = strchr((char*)pszLine, '*');
+            char* pszStar = strchr(const_cast<char *>(pszLine), '*');
             if (pszStar) *pszStar = 0;
             char** papszTokens = CSLTokenizeString2(pszLine, ",", 0);
-            double dfFirstLat, dfFirstLon;
-            double dfSecondLat, dfSecondLon;
+            double dfFirstLat;
+            double dfFirstLon;
+            double dfSecondLat;
+            double dfSecondLon;
             if (bHasCenter && CSLCount(papszTokens) == 2 &&
                 OGROpenAirGetLatLon(papszTokens[0], dfFirstLat, dfFirstLon) &&
                 OGROpenAirGetLatLon(papszTokens[1], dfSecondLat, dfSecondLon))
             {
-                double dfStartDistance =OGRXPlane_Distance(dfCenterLat,
+                const double dfStartDistance =OGRXPlane_Distance(dfCenterLat,
                         dfCenterLon, dfFirstLat, dfFirstLon);
-                double dfEndDistance = OGRXPlane_Distance(dfCenterLat,
+                const double dfEndDistance = OGRXPlane_Distance(dfCenterLat,
                         dfCenterLon, dfSecondLat, dfSecondLon);
-                double dfStartAngle = OGRXPlane_Track(dfCenterLat,
+                const double dfStartAngle = OGRXPlane_Track(dfCenterLat,
                         dfCenterLon, dfFirstLat, dfFirstLon);
                 double dfEndAngle = OGRXPlane_Track(dfCenterLat,
                         dfCenterLon, dfSecondLat, dfSecondLon);
@@ -347,17 +351,17 @@ OGRFeature *OGROpenAirLayer::GetNextRawFeature()
                 else if (!bClockWise && dfStartAngle < dfEndAngle)
                     dfEndAngle -= 360;
 
-                int nSign = (bClockWise) ? 1 : -1;
-                double dfAngle;
-                for(dfAngle = dfStartAngle;
+                const int nSign = (bClockWise) ? 1 : -1;
+                for(double dfAngle = dfStartAngle;
                     (dfAngle - dfEndAngle) * nSign < 0;
                     dfAngle += nSign)
                 {
-                    double dfLat, dfLon;
-                    double pct = (dfAngle - dfStartAngle) /
-                                    (dfEndAngle - dfStartAngle);
-                    double dfDist = dfStartDistance * (1-pct) +
-                                                    dfEndDistance * pct;
+                    double dfLat;
+                    double dfLon;
+                    const double pct = (dfAngle - dfStartAngle) /
+                        (dfEndAngle - dfStartAngle);
+                    const double dfDist = dfStartDistance * (1-pct) +
+                        dfEndDistance * pct;
                     OGRXPlane_ExtendPosition(dfCenterLat, dfCenterLon,
                                              dfDist, dfAngle, &dfLat, &dfLon);
                     oLR.addPoint(dfLon, dfLat);
@@ -369,23 +373,25 @@ OGRFeature *OGROpenAirLayer::GetNextRawFeature()
             }
             CSLDestroy(papszTokens);
         }
-        else if ((EQUALN(pszLine, "DC ", 3) || EQUALN(pszLine, "DC=", 3)) &&
+        else if ((STARTS_WITH_CI(pszLine, "DC ") ||
+                  STARTS_WITH_CI(pszLine, "DC=")) &&
                  (bHasCenter || strstr(pszLine, "V X=") != NULL))
         {
             if (!bHasCenter)
             {
                 const char* pszVX = strstr(pszLine, "V X=");
-                bHasCenter = OGROpenAirGetLatLon(pszVX, dfCenterLat, dfCenterLon);
+                if( pszVX != NULL )
+                    bHasCenter =
+                        OGROpenAirGetLatLon(pszVX, dfCenterLat, dfCenterLon);
             }
             if (bHasCenter)
             {
                 pszLine += 3;
 
-                double dfRADIUS = CPLAtof(pszLine) * 1852;
-
-                double dfAngle;
-                double dfLat, dfLon;
-                for(dfAngle = 0; dfAngle < 360; dfAngle += 1)
+                const double dfRADIUS = CPLAtof(pszLine) * 1852;
+                double dfLat;
+                double dfLon;
+                for(double dfAngle = 0; dfAngle < 360; dfAngle += 1)
                 {
                     OGRXPlane_ExtendPosition(dfCenterLat, dfCenterLon,
                                              dfRADIUS, dfAngle, &dfLat, &dfLon);
@@ -399,18 +405,18 @@ OGRFeature *OGROpenAirLayer::GetNextRawFeature()
                 /* dfLastLon = oLR.getX(oLR.getNumPoints() - 1); */
             }
         }
-        else if (EQUALN(pszLine, "V X=", 4))
+        else if (STARTS_WITH_CI(pszLine, "V X="))
         {
             bHasCenter =
                     OGROpenAirGetLatLon(pszLine + 4, dfCenterLat, dfCenterLon);
         }
-        else if (EQUALN(pszLine, "V D=-", 5))
+        else if (STARTS_WITH_CI(pszLine, "V D=-"))
         {
-            bClockWise = FALSE;
+            bClockWise = false;
         }
-        else if (EQUALN(pszLine, "V D=+", 5))
+        else if (STARTS_WITH_CI(pszLine, "V D=+"))
         {
-            bClockWise = TRUE;
+            bClockWise = true;
         }
         else
         {
@@ -466,7 +472,7 @@ OGRFeature *OGROpenAirLayer::GetNextRawFeature()
 /*                           TestCapability()                           */
 /************************************************************************/
 
-int OGROpenAirLayer::TestCapability( CPL_UNUSED const char * pszCap )
+int OGROpenAirLayer::TestCapability( const char * /* pszCap */ )
 {
     return FALSE;
 }
diff --git a/ogr/ogrsf_frmts/openfilegdb/drv_openfilegdb.html b/ogr/ogrsf_frmts/openfilegdb/drv_openfilegdb.html
index e0c0ce4..cf79d0b 100644
--- a/ogr/ogrsf_frmts/openfilegdb/drv_openfilegdb.html
+++ b/ogr/ogrsf_frmts/openfilegdb/drv_openfilegdb.html
@@ -48,7 +48,7 @@ ArcGIS 10 or above)
 <h2>Comparison with the FileGDB driver</h2>
 
 <p>
-(Comparison done with a FileGDB driver using FileGDB API SDK 1.3)
+(Comparison done with a FileGDB driver using FileGDB API SDK 1.4)
 </p>
 
 <p>
@@ -73,7 +73,13 @@ Drawbacks of the OpenFileGDB driver:
 <ul>
 <li>Read-only.</li>
 <li>Cannot use spatial indexes.</li>
-<li>Cannot read data from compressed feature classes (SDC, Smart Data Compression). Nor can can FileGDB driver because the ESRI FileGDB SDK lacks also this feature.</li>
+<li>Cannot read data from compressed data in CDF format (Compressed Data Format).</li>
+</ul>
+
+<h2>Known Issues</h2>
+
+<ul>
+        <li>Curve in geometries are not currently supported.</li>
 </ul>
 
 <h2>Examples</h2>
diff --git a/ogr/ogrsf_frmts/openfilegdb/filegdbindex.cpp b/ogr/ogrsf_frmts/openfilegdb/filegdbindex.cpp
index ec02e52..44a07f4 100644
--- a/ogr/ogrsf_frmts/openfilegdb/filegdbindex.cpp
+++ b/ogr/ogrsf_frmts/openfilegdb/filegdbindex.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: filegdbindex.cpp 29195 2015-05-14 11:27:35Z rouault $
+ * $Id: filegdbindex.cpp 33027 2016-01-17 18:47:10Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements reading of FileGDB indexes
@@ -41,7 +41,8 @@ namespace OpenFileGDB
 /*                     FileGDBOGRDateToDoubleDate()                     */
 /************************************************************************/
 
-static int FileGDBOGRDateToDoubleDate( const OGRField* psField, double *pdfVal )
+static bool FileGDBOGRDateToDoubleDate( const OGRField* psField,
+                                        double *pdfVal )
 {
     struct tm brokendowntime;
 
@@ -50,20 +51,20 @@ static int FileGDBOGRDateToDoubleDate( const OGRField* psField, double *pdfVal )
     brokendowntime.tm_mday = psField->Date.Day;
     brokendowntime.tm_hour = psField->Date.Hour;
     brokendowntime.tm_min = psField->Date.Minute;
-    brokendowntime.tm_sec = psField->Date.Second;
+    brokendowntime.tm_sec = static_cast<int>(psField->Date.Second);
 
-    GIntBig nTime = CPLYMDHMSToUnixTime(&brokendowntime);
+    const GIntBig nTime = CPLYMDHMSToUnixTime(&brokendowntime);
 
     *pdfVal = nTime / 3600. / 24 + 25569;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                        FileGDBTrivialIterator                        */
 /************************************************************************/
 
-class FileGDBTrivialIterator : public FileGDBIterator
+class FileGDBTrivialIterator CPL_FINAL : public FileGDBIterator
 {
         FileGDBIterator            *poParentIter;
         FileGDBTable               *poTable;
@@ -95,7 +96,7 @@ class FileGDBTrivialIterator : public FileGDBIterator
 /*                        FileGDBNotIterator                            */
 /************************************************************************/
 
-class FileGDBNotIterator : public FileGDBIterator
+class FileGDBNotIterator CPL_FINAL : public FileGDBIterator
 {
         FileGDBIterator            *poIterBase;
         FileGDBTable               *poTable;
@@ -117,7 +118,7 @@ class FileGDBNotIterator : public FileGDBIterator
 /*                        FileGDBAndIterator                            */
 /************************************************************************/
 
-class FileGDBAndIterator : public FileGDBIterator
+class FileGDBAndIterator CPL_FINAL : public FileGDBIterator
 {
         FileGDBIterator             *poIter1;
         FileGDBIterator             *poIter2;
@@ -138,14 +139,14 @@ class FileGDBAndIterator : public FileGDBIterator
 /*                        FileGDBOrIterator                             */
 /************************************************************************/
 
-class FileGDBOrIterator : public FileGDBIterator
+class FileGDBOrIterator CPL_FINAL : public FileGDBIterator
 {
         FileGDBIterator             *poIter1;
         FileGDBIterator             *poIter2;
         int                          bIteratorAreExclusive;
         int                          iNextRow1;
         int                          iNextRow2;
-        int                          bHasJustReset;
+        bool                         bHasJustReset;
 
     public:
                                      FileGDBOrIterator(FileGDBIterator* poIter1,
@@ -163,16 +164,16 @@ class FileGDBOrIterator : public FileGDBIterator
 /*                        FileGDBIndexIterator                          */
 /************************************************************************/
 
-#define MAX_DEPTH               3
-#define UUID_LEN_AS_STRING      38
-#define MAX_CAR_COUNT_STR       80
-#define MAX_UTF8_LEN_STR        (4 * MAX_CAR_COUNT_STR)
-#define FGDB_PAGE_SIZE          4096
+static const int MAX_DEPTH = 3;
+static const int UUID_LEN_AS_STRING = 38;
+static const int MAX_CAR_COUNT_STR = 80;
+static const int MAX_UTF8_LEN_STR = 4 * MAX_CAR_COUNT_STR;
+static const int FGDB_PAGE_SIZE = 4096;
 
-class FileGDBIndexIterator : public FileGDBIterator
+class FileGDBIndexIterator CPL_FINAL : public FileGDBIterator
 {
         FileGDBTable        *poParent;
-        int                  bAscending;
+        bool                 bAscending;
         VSILFILE            *fpCurIdx;
         FileGDBFieldType     eFieldType;
         GUInt32              nMaxPerPages;
@@ -382,8 +383,8 @@ int FileGDBIterator::GetRowCount()
 /*                         FileGDBTrivialIterator()                     */
 /************************************************************************/
 
-FileGDBTrivialIterator::FileGDBTrivialIterator(FileGDBIterator* poParentIter) :
-        poParentIter(poParentIter), poTable(poParentIter->GetTable()), iRow(0)
+FileGDBTrivialIterator::FileGDBTrivialIterator(FileGDBIterator* poParentIterIn) :
+        poParentIter(poParentIterIn), poTable(poParentIterIn->GetTable()), iRow(0)
 {
 }
 
@@ -403,8 +404,8 @@ int FileGDBTrivialIterator::GetNextRowSortedByFID()
 /*                           FileGDBNotIterator()                       */
 /************************************************************************/
 
-FileGDBNotIterator::FileGDBNotIterator(FileGDBIterator* poIterBase) :
-    poIterBase(poIterBase), poTable(poIterBase->GetTable()), iRow(0), iNextRowBase(-1)
+FileGDBNotIterator::FileGDBNotIterator(FileGDBIterator* poIterBaseIn) :
+    poIterBase(poIterBaseIn), poTable(poIterBaseIn->GetTable()), iRow(0), iNextRowBase(-1)
 {
     bNoHoles = (poTable->GetValidRecordCount() == poTable->GetTotalRecordCount());
 }
@@ -442,7 +443,7 @@ int FileGDBNotIterator::GetNextRowSortedByFID()
             iNextRowBase = poTable->GetTotalRecordCount();
     }
 
-    while( TRUE )
+    while( true )
     {
         if( iRow < iNextRowBase )
         {
@@ -481,9 +482,9 @@ int FileGDBNotIterator::GetRowCount()
 /*                          FileGDBAndIterator()                        */
 /************************************************************************/
 
-FileGDBAndIterator::FileGDBAndIterator(FileGDBIterator* poIter1,
-                                       FileGDBIterator* poIter2) :
-                                       poIter1(poIter1), poIter2(poIter2),
+FileGDBAndIterator::FileGDBAndIterator(FileGDBIterator* poIter1In,
+                                       FileGDBIterator* poIter2In) :
+                                       poIter1(poIter1In), poIter2(poIter2In),
                                        iNextRow1(-1), iNextRow2(-1)
 {
     CPLAssert(poIter1->GetTable() == poIter2->GetTable());
@@ -527,7 +528,7 @@ int FileGDBAndIterator::GetNextRowSortedByFID()
         }
     }
 
-    while( TRUE )
+    while( true )
     {
         if( iNextRow1 < iNextRow2 )
         {
@@ -551,12 +552,15 @@ int FileGDBAndIterator::GetNextRowSortedByFID()
 /************************************************************************/
 
 
-FileGDBOrIterator::FileGDBOrIterator(FileGDBIterator* poIter1,
-                                     FileGDBIterator* poIter2,
-                                     int bIteratorAreExclusive) :
-                            poIter1(poIter1), poIter2(poIter2),
-                            bIteratorAreExclusive(bIteratorAreExclusive),
-                            iNextRow1(-1), iNextRow2(-1), bHasJustReset(TRUE)
+FileGDBOrIterator::FileGDBOrIterator(FileGDBIterator* poIter1In,
+                                     FileGDBIterator* poIter2In,
+                                     int bIteratorAreExclusiveIn) :
+    poIter1(poIter1In),
+    poIter2(poIter2In),
+    bIteratorAreExclusive(bIteratorAreExclusiveIn),
+    iNextRow1(-1),
+    iNextRow2(-1),
+    bHasJustReset(true)
 {
     CPLAssert(poIter1->GetTable() == poIter2->GetTable());
 }
@@ -581,7 +585,7 @@ void FileGDBOrIterator::Reset()
     poIter2->Reset();
     iNextRow1 = -1;
     iNextRow2 = -1;
-    bHasJustReset = TRUE;
+    bHasJustReset = true;
 }
 
 /************************************************************************/
@@ -592,7 +596,7 @@ int FileGDBOrIterator::GetNextRowSortedByFID()
 {
     if( bHasJustReset )
     {
-        bHasJustReset = FALSE;
+        bHasJustReset = false;
         iNextRow1 = poIter1->GetNextRowSortedByFID();
         iNextRow2 = poIter2->GetNextRowSortedByFID();
     }
@@ -641,15 +645,25 @@ int FileGDBOrIterator::GetRowCount()
 /*                         FileGDBIndexIterator()                       */
 /************************************************************************/
 
-FileGDBIndexIterator::FileGDBIndexIterator(FileGDBTable* poParent, int bAscending) :
-                    poParent(poParent), bAscending(bAscending),
-                    fpCurIdx(NULL), eFieldType(FGFT_UNDEFINED),
-                    nMaxPerPages(0), nOffsetFirstValInPage(0),
-                    nValueCountInIdx(0), nIndexDepth(0), eOp(FGSO_ISNOTNULL),
-                    iCurFeatureInPage(-1), nFeaturesInPage(0),
-                    bEvaluateToFALSE(FALSE), bEOF(FALSE),
-                    iSorted(0), nSortedCount(-1), panSortedRows(NULL),
-                    nStrLen(0)
+FileGDBIndexIterator::FileGDBIndexIterator( FileGDBTable* poParentIn,
+                                            int bAscendingIn) :
+  poParent(poParentIn),
+  bAscending(CPL_TO_BOOL(bAscendingIn)),
+  fpCurIdx(NULL),
+  eFieldType(FGFT_UNDEFINED),
+  nMaxPerPages(0),
+  nOffsetFirstValInPage(0),
+  nValueCountInIdx(0),
+  nIndexDepth(0),
+  eOp(FGSO_ISNOTNULL),
+  iCurFeatureInPage(-1),
+  nFeaturesInPage(0),
+  bEvaluateToFALSE(FALSE),
+  bEOF(FALSE),
+  iSorted(0),
+  nSortedCount(-1),
+  panSortedRows(NULL),
+  nStrLen(0)
 {
     memset(iFirstPageIdx, 0xFF, MAX_DEPTH * sizeof(int));
     memset(iLastPageIdx, 0xFF, MAX_DEPTH * sizeof(int));
@@ -903,8 +917,10 @@ int FileGDBIndexIterator::SetConstraint(int nFieldIdx,
                 returnErrorIf(eOGRFieldType != OFTString);
                 memset(szUUID, 0, UUID_LEN_AS_STRING + 1);
                 strncpy(szUUID, psValue->String, UUID_LEN_AS_STRING);
-                bEvaluateToFALSE = (eOp == FGSO_EQ &&
-                        strlen(psValue->String) != UUID_LEN_AS_STRING);
+                bEvaluateToFALSE =
+                    eOp == FGSO_EQ &&
+                    strlen(psValue->String) !=
+                    static_cast<size_t>(UUID_LEN_AS_STRING);
             }
             break;
         }
@@ -1046,7 +1062,7 @@ int FileGDBIndexIterator::FindPages(int iLevel, int nPage)
             case FGFT_STRING:
             {
                 GUInt16* pasMax;
-#ifdef CPL_MSB
+#if defined(CPL_MSB) || defined(CPL_CPU_REQUIRES_ALIGNED_ACCESS)
                 GUInt16 asMax[MAX_CAR_COUNT_STR];
                 pasMax = asMax;
                 memcpy(asMax, abyPage[iLevel] + nOffsetFirstValInPage +
@@ -1289,7 +1305,7 @@ int FileGDBIndexIterator::GetNextRow()
     if( bEOF )
         return -1;
 
-    while( TRUE )
+    while( true )
     {
         if( iCurFeatureInPage >= nFeaturesInPage || iCurFeatureInPage < 0 )
         {
@@ -1308,7 +1324,6 @@ int FileGDBIndexIterator::GetNextRow()
         else
         {
             int nComp;
-            bMatch = FALSE;
             switch( eFieldType )
             {
                 case FGFT_INT16:
@@ -1346,7 +1361,7 @@ int FileGDBIndexIterator::GetNextRow()
 
                 case FGFT_STRING:
                 {
-#ifdef CPL_MSB
+#if defined(CPL_MSB) || defined(CPL_CPU_REQUIRES_ALIGNED_ACCESS)
                     GUInt16 asVal[MAX_CAR_COUNT_STR];
                     memcpy(asVal, abyPageFeature + nOffsetFirstValInPage +
                                     nStrLen * 2 * iCurFeatureInPage, nStrLen * 2);
@@ -1377,6 +1392,8 @@ int FileGDBIndexIterator::GetNextRow()
                     break;
             }
 
+            bMatch = FALSE;
+            CPL_IGNORE_RET_VAL(bMatch);
             switch( eOp )
             {
                 case FGSO_LT:
@@ -1451,7 +1468,7 @@ int FileGDBIndexIterator::SortRows()
     iSorted = 0;
     int nSortedAlloc = 0;
     Reset();
-    while( TRUE )
+    while( true )
     {
         int nRow = GetNextRow();
         if( nRow < 0 )
@@ -1459,7 +1476,7 @@ int FileGDBIndexIterator::SortRows()
         if( nSortedCount == nSortedAlloc )
         {
             int nNewSortedAlloc = 4 * nSortedAlloc / 3 + 16;
-            int* panNewSortedRows = (int*)VSIRealloc(panSortedRows,
+            int* panNewSortedRows = (int*)VSI_REALLOC_VERBOSE(panSortedRows,
                                             sizeof(int) * nNewSortedAlloc);
             if( panNewSortedRows == NULL )
             {
@@ -1525,8 +1542,8 @@ int FileGDBIndexIterator::GetRowCount()
         return nSortedCount;
 
     int nRowCount = 0;
-    int bSaveAscending = bAscending;
-    bAscending = TRUE; /* for a tiny bit of more efficiency */
+    bool bSaveAscending = bAscending;
+    bAscending = true; /* for a tiny bit of more efficiency */
     Reset();
     while( GetNextRow() >= 0 )
         nRowCount ++;
@@ -1548,26 +1565,26 @@ const OGRField* FileGDBIndexIterator::GetMinMaxValue(OGRField* psField,
     if( nValueCountInIdx == 0 )
         return NULL;
 
-    GByte abyPage[FGDB_PAGE_SIZE];
+    GByte l_abyPage[FGDB_PAGE_SIZE];
     GUInt32 nPage = 1;
     for( GUInt32 iLevel = 0; iLevel < nIndexDepth - 1; iLevel ++ )
     {
         VSIFSeekL(fpCurIdx, (nPage - 1) * FGDB_PAGE_SIZE, SEEK_SET);
-        returnErrorIf(VSIFReadL( abyPage, FGDB_PAGE_SIZE, 1, fpCurIdx ) != 1 );
-        GUInt32 nSubPagesCount = GetUInt32(abyPage + 4, 0);
-        returnErrorIf(nSubPagesCount == 0 || nSubPagesCount > nMaxPerPages);
+        returnErrorIf(VSIFReadL( l_abyPage, FGDB_PAGE_SIZE, 1, fpCurIdx ) != 1 );
+        GUInt32 l_nSubPagesCount = GetUInt32(l_abyPage + 4, 0);
+        returnErrorIf(l_nSubPagesCount == 0 || l_nSubPagesCount > nMaxPerPages);
 
         if( bIsMin )
-            nPage = GetUInt32(abyPage + 8, 0);
+            nPage = GetUInt32(l_abyPage + 8, 0);
         else
-            nPage = GetUInt32(abyPage + 8, nSubPagesCount);
+            nPage = GetUInt32(l_abyPage + 8, l_nSubPagesCount);
         returnErrorIf(nPage < 2 );
     }
 
     VSIFSeekL(fpCurIdx, (nPage - 1) * FGDB_PAGE_SIZE, SEEK_SET);
-    returnErrorIf(VSIFReadL( abyPage, FGDB_PAGE_SIZE, 1, fpCurIdx ) != 1);
+    returnErrorIf(VSIFReadL( l_abyPage, FGDB_PAGE_SIZE, 1, fpCurIdx ) != 1);
 
-    GUInt32 nFeatures = GetUInt32(abyPage + 4, 0);
+    GUInt32 nFeatures = GetUInt32(l_abyPage + 4, 0);
     returnErrorIf(nFeatures < 1 || nFeatures > nMaxPerPages);
 
     int iFeature = (bIsMin) ? 0 : nFeatures-1;
@@ -1576,7 +1593,7 @@ const OGRField* FileGDBIndexIterator::GetMinMaxValue(OGRField* psField,
     {
         case FGFT_INT16:
         {
-            GInt16 nVal = GetInt16(abyPage + nOffsetFirstValInPage, iFeature);
+            GInt16 nVal = GetInt16(l_abyPage + nOffsetFirstValInPage, iFeature);
             psField->Integer = nVal;
             eOutType = OFTInteger;
             return psField;
@@ -1584,7 +1601,7 @@ const OGRField* FileGDBIndexIterator::GetMinMaxValue(OGRField* psField,
 
         case FGFT_INT32:
         {
-            GInt32 nVal = GetInt32(abyPage + nOffsetFirstValInPage, iFeature);
+            GInt32 nVal = GetInt32(l_abyPage + nOffsetFirstValInPage, iFeature);
             psField->Integer = nVal;
             eOutType = OFTInteger;
             return psField;
@@ -1592,7 +1609,7 @@ const OGRField* FileGDBIndexIterator::GetMinMaxValue(OGRField* psField,
 
         case FGFT_FLOAT32:
         {
-            float fVal = GetFloat32(abyPage + nOffsetFirstValInPage, iFeature);
+            float fVal = GetFloat32(l_abyPage + nOffsetFirstValInPage, iFeature);
             psField->Real = fVal;
             eOutType = OFTReal;
             return psField;
@@ -1600,7 +1617,7 @@ const OGRField* FileGDBIndexIterator::GetMinMaxValue(OGRField* psField,
 
         case FGFT_FLOAT64:
         {
-            double dfVal = GetFloat64(abyPage + nOffsetFirstValInPage, iFeature);
+            double dfVal = GetFloat64(l_abyPage + nOffsetFirstValInPage, iFeature);
             psField->Real = dfVal;
             eOutType = OFTReal;
             return psField;
@@ -1608,7 +1625,7 @@ const OGRField* FileGDBIndexIterator::GetMinMaxValue(OGRField* psField,
 
         case FGFT_DATETIME:
         {
-            double dfVal = GetFloat64(abyPage + nOffsetFirstValInPage, iFeature);
+            double dfVal = GetFloat64(l_abyPage + nOffsetFirstValInPage, iFeature);
             FileGDBDoubleDateToOGRDate(dfVal, psField);
             eOutType = OFTDateTime;
             return psField;
@@ -1619,15 +1636,16 @@ const OGRField* FileGDBIndexIterator::GetMinMaxValue(OGRField* psField,
             wchar_t awsVal[MAX_CAR_COUNT_STR+1];
             for(int j=0;j<nStrLen;j++)
             {
-                GUInt16 nCh = GetUInt16(abyPage + nOffsetFirstValInPage +
+                GUInt16 nCh = GetUInt16(l_abyPage + nOffsetFirstValInPage +
                     nStrLen * sizeof(GUInt16) * iFeature, j);
                 awsVal[j] = nCh;
             }
             awsVal[nStrLen] = 0;
             char* pszOut = CPLRecodeFromWChar(awsVal, CPL_ENC_UCS2, CPL_ENC_UTF8);
             returnErrorIf(pszOut == NULL );
-            returnErrorAndCleanupIf(strlen(pszOut) >
-                                        MAX_UTF8_LEN_STR, VSIFree(pszOut) );
+            returnErrorAndCleanupIf(
+                strlen(pszOut) > static_cast<size_t>(MAX_UTF8_LEN_STR),
+                VSIFree(pszOut) );
             strcpy(psField->String, pszOut);
             CPLFree(pszOut);
             eOutType = OFTString;
@@ -1637,7 +1655,7 @@ const OGRField* FileGDBIndexIterator::GetMinMaxValue(OGRField* psField,
         case FGFT_UUID_1:
         case FGFT_UUID_2:
         {
-            memcpy(psField->String, abyPage + nOffsetFirstValInPage +
+            memcpy(psField->String, l_abyPage + nOffsetFirstValInPage +
                    UUID_LEN_AS_STRING *iFeature, UUID_LEN_AS_STRING);
             psField->String[UUID_LEN_AS_STRING] = 0;
             eOutType = OFTString;
@@ -1726,7 +1744,7 @@ template <class Getter> void FileGDBIndexIterator::GetMinMaxSumCount(
     double dfLocalSum = 0.0;
     double dfVal = 0.0;
 
-    while( TRUE )
+    while( true )
     {
         if( iCurFeatureInPage >= nFeaturesInPage )
         {
@@ -1764,8 +1782,8 @@ int FileGDBIndexIterator::GetMinMaxSumCount(double& dfMin, double& dfMax,
                   eFieldType != FGFT_FLOAT32 && eFieldType != FGFT_FLOAT64 &&
                   eFieldType != FGFT_DATETIME );
 
-    int bSaveAscending = bAscending;
-    bAscending = TRUE;
+    bool bSaveAscending = bAscending;
+    bAscending = true;
     Reset();
 
     switch( eFieldType )
diff --git a/ogr/ogrsf_frmts/openfilegdb/filegdbtable.cpp b/ogr/ogrsf_frmts/openfilegdb/filegdbtable.cpp
index ceb004c..0287a50 100644
--- a/ogr/ogrsf_frmts/openfilegdb/filegdbtable.cpp
+++ b/ogr/ogrsf_frmts/openfilegdb/filegdbtable.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: filegdbtable.cpp 33153 2016-01-25 12:45:47Z rouault $
+ * $Id: filegdbtable.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements reading of FileGDB tables
@@ -28,6 +28,7 @@
  ****************************************************************************/
 
 #include "filegdbtable_priv.h"
+#include "cpl_port.h"
 #include "cpl_string.h"
 #include "cpl_time.h"
 #include "ogrpgeogeometry.h" /* SHPT_ constants and OGRCreateFromMultiPatchPart() */
@@ -56,8 +57,8 @@ namespace OpenFileGDB
 
 void FileGDBTablePrintError(const char* pszFile, int nLineNumber)
 {
-    CPLError(CE_Failure, CPLE_AppDefined, "Error occured in %s at line %d",
-             pszFile, nLineNumber);
+    CPLError( CE_Failure, CPLE_AppDefined, "Error occurred in %s at line %d",
+              pszFile, nLineNumber );
 }
 
 /************************************************************************/
@@ -199,7 +200,7 @@ static int ReadVarUInt(GByte*& pabyIter, GByte* pabyEnd, OutType& nOutVal)
     GByte* pabyLocalIter = pabyIter + 1;
     int nShift = 7;
     OutType nVal = ( b & 0x7F );
-    while(TRUE)
+    while( true )
     {
         if( !(ControleType::check_bounds) )
         {
@@ -229,20 +230,20 @@ static int ReadVarUInt(GByte*& pabyIter, GByte* pabyEnd, OutType& nOutVal)
 
 struct ControleTypeVerboseErrorTrue
 {
-    static const bool check_bounds = true;
-    static const bool verbose_error = true;
+    static const EMULATED_BOOL check_bounds = true;
+    static const EMULATED_BOOL verbose_error = true;
 };
 
 struct ControleTypeVerboseErrorFalse
 {
-    static const bool check_bounds = true;
-    static const bool verbose_error = false;
+    static const EMULATED_BOOL check_bounds = true;
+    static const EMULATED_BOOL verbose_error = false;
 };
 
 struct ControleTypeNone
 {
-    static const bool check_bounds = false;
-    static const bool verbose_error = false;
+    static const EMULATED_BOOL check_bounds = false;
+    static const EMULATED_BOOL verbose_error = false;
 };
 
 static int ReadVarUInt32(GByte*& pabyIter, GByte* pabyEnd, GUInt32& nOutVal)
@@ -306,7 +307,7 @@ int FileGDBTable::IsLikelyFeatureAtOffset(vsi_l_offset nOffset,
 
     if( nRowBlobLength > nBufferMaxSize )
     {
-        GByte* pabyNewBuffer = (GByte*) VSIRealloc( pabyBuffer,
+        GByte* pabyNewBuffer = (GByte*) VSI_REALLOC_VERBOSE( pabyBuffer,
                                 nRowBlobLength + ZEROES_AFTER_END_OF_BUFFER );
         if( pabyNewBuffer == NULL )
             return FALSE;
@@ -392,7 +393,7 @@ int FileGDBTable::IsLikelyFeatureAtOffset(vsi_l_offset nOffset,
                     if( !ReadVarUInt32Silent(pabyIter, pabyBuffer + nRowBlobLength, nLength) ||
                         pabyIter - (pabyBuffer + nRequiredLength) > 5 )
                         return FALSE;
-                    nRequiredLength = pabyIter - pabyBuffer;
+                    nRequiredLength = static_cast<GUInt32>(pabyIter - pabyBuffer);
                     if( nLength > nRowBlobLength - nRequiredLength )
                         return FALSE;
                     for( GUInt32 j=0;j<nLength;j++ )
@@ -414,7 +415,7 @@ int FileGDBTable::IsLikelyFeatureAtOffset(vsi_l_offset nOffset,
                     if( !ReadVarUInt32Silent(pabyIter, pabyBuffer + nRowBlobLength, nLength) ||
                         pabyIter - (pabyBuffer + nRequiredLength) > 5 )
                         return FALSE;
-                    nRequiredLength = pabyIter - pabyBuffer;
+                    nRequiredLength = static_cast<GUInt32>(pabyIter - pabyBuffer);
                     if( nLength > nRowBlobLength - nRequiredLength )
                         return FALSE;
                     nRequiredLength += nLength;
@@ -449,20 +450,20 @@ int FileGDBTable::IsLikelyFeatureAtOffset(vsi_l_offset nOffset,
 /*                      GuessFeatureLocations()                         */
 /************************************************************************/
 
-#define MARK_DELETED(x)  ((x) | (((GIntBig)1) << 63))
-#define IS_DELETED(x)    (((x) & (((GIntBig)1) << 63)) != 0)
-#define GET_OFFSET(x)    ((x) & ~(((GIntBig)1) << 63))
+#define MARK_DELETED(x)  ((x) | (((GUIntBig)1) << 63))
+#define IS_DELETED(x)    (((x) & (((GUIntBig)1) << 63)) != 0)
+#define GET_OFFSET(x)    ((x) & ~(((GUIntBig)1) << 63))
 
 int FileGDBTable::GuessFeatureLocations()
 {
     VSIFSeekL(fpTable, 0, SEEK_END);
     nFileSize = VSIFTellL(fpTable);
-    
+
     int bReportDeletedFeatures =
-        CSLTestBoolean(CPLGetConfigOption("OPENFILEGDB_REPORT_DELETED_FEATURES", "NO"));
+        CPLTestBool(CPLGetConfigOption("OPENFILEGDB_REPORT_DELETED_FEATURES", "NO"));
 
     vsi_l_offset nOffset = 40 + nFieldDescLength;
-    
+
     if( nOffsetFieldDesc != 40 )
     {
         /* Check if there is a deleted field description at offset 40 */
@@ -586,7 +587,7 @@ int FileGDBTable::ReadTableXHeader()
 
             // Allocate a bit mask array for blocks of 1024 features.
             int nSizeInBytes = BIT_ARRAY_SIZE_IN_BYTES(nBitsForBlockMap);
-            pabyTablXBlockMap = (GByte*) VSIMalloc( nSizeInBytes );
+            pabyTablXBlockMap = (GByte*) VSI_MALLOC_VERBOSE( nSizeInBytes );
             returnErrorIf(pabyTablXBlockMap == NULL );
             returnErrorIf(VSIFReadL( pabyTablXBlockMap, nSizeInBytes, 1, fpTableX ) != 1 );
             /* returnErrorIf(nMagic2 == 0 ); */
@@ -633,7 +634,7 @@ int FileGDBTable::Open(const char* pszFilename,
 
     CPLString osTableXName;
     if( nValidRecordCount > 0 &&
-        !CSLTestBoolean(CPLGetConfigOption("OPENFILEGDB_IGNORE_GDBTABLX", "FALSE")) )
+        !CPLTestBool(CPLGetConfigOption("OPENFILEGDB_IGNORE_GDBTABLX", "FALSE")) )
     {
         osTableXName = CPLFormFilename(CPLGetPath(pszFilename),
                                         CPLGetBasename(pszFilename), "gdbtablx");
@@ -648,7 +649,7 @@ int FileGDBTable::Open(const char* pszFilename,
                         "Trying to guess feature locations, but this might fail or "
                         "return incorrect results", osTableXName.c_str());
             }
-            else if( !CSLTestBoolean(pszIgnoreGDBTablXAbsence) )
+            else if( !CPLTestBool(pszIgnoreGDBTablXAbsence) )
             {
                 returnErrorIf(fpTableX == NULL );
             }
@@ -661,7 +662,7 @@ int FileGDBTable::Open(const char* pszFilename,
     {
         if(nValidRecordCount > nTotalRecordCount )
         {
-            if( CSLTestBoolean(CPLGetConfigOption("OPENFILEGDB_USE_GDBTABLE_RECORD_COUNT", "FALSE")) )
+            if( CPLTestBool(CPLGetConfigOption("OPENFILEGDB_USE_GDBTABLE_RECORD_COUNT", "FALSE")) )
             {
                 /* Potentially unsafe. See #5842 */
                 CPLDebug("OpenFileGDB", "%s: nTotalRecordCount (was %d) forced to nValidRecordCount=%d",
@@ -727,7 +728,7 @@ int FileGDBTable::Open(const char* pszFilename,
 
     GUInt32 nRemaining = nFieldDescLength - 10;
     nBufferMaxSize = nRemaining;
-    pabyBuffer = (GByte*)VSIMalloc(nBufferMaxSize + ZEROES_AFTER_END_OF_BUFFER);
+    pabyBuffer = (GByte*)VSI_MALLOC_VERBOSE(nBufferMaxSize + ZEROES_AFTER_END_OF_BUFFER);
     returnErrorIf(pabyBuffer == NULL );
     returnErrorIf(VSIFReadL(pabyBuffer, nRemaining, 1, fpTable) != 1 );
 
@@ -787,7 +788,7 @@ int FileGDBTable::Open(const char* pszFilename,
                     nRemaining -= 5;
                     GByte* pabyIterBefore = pabyIter;
                     returnErrorIf(!ReadVarUInt32(pabyIter, pabyIter + nRemaining, defaultValueLength));
-                    nRemaining -= (pabyIter - pabyIterBefore);
+                    nRemaining -= static_cast<GUInt32>(pabyIter - pabyIterBefore);
                     break;
                 }
 
@@ -964,6 +965,10 @@ int FileGDBTable::Open(const char* pszFilename,
                 if( poField->bHasM )
                 {
                     READ_DOUBLE(poField->dfMTolerance);
+#ifdef DEBUG_VERBOSE
+                    CPLDebug("OpenFileGDB", "MOrigin = %g, MScale = %g, MTolerance = %g",
+                             poField->dfMOrigin, poField->dfMScale, poField->dfMTolerance);
+#endif
                 }
 
                 if( poField->bHasZ )
@@ -991,7 +996,7 @@ int FileGDBTable::Open(const char* pszFilename,
                 /* here. When there are 3, the first one is zmin and the second */
                 /* one is zmax */
                 int nCountDoubles = 0;
-                while( TRUE )
+                while( true )
                 {
                     returnErrorIf(nRemaining < 5 );
 
@@ -1050,7 +1055,7 @@ static int SkipVarUInt(GByte*& pabyIter, GByte* pabyEnd, int nIter = 1)
     returnErrorIf(pabyLocalIter /*+ nIter - 1*/ >= pabyEnd);
     while( nIter -- > 0 )
     {
-        while(TRUE)
+        while( true )
         {
             GByte b = *pabyLocalIter;
             pabyLocalIter ++;
@@ -1084,12 +1089,12 @@ static void ReadVarIntAndAddNoCheck(GByte*& pabyIter, GIntBig& nOutVal)
 
     GByte* pabyLocalIter = pabyIter + 1;
     int nShift = 6;
-    while(TRUE)
+    while( true )
     {
-        GUIntBig b = *pabyLocalIter;
+        GUIntBig b64 = *pabyLocalIter;
         pabyLocalIter ++;
-        nVal |= ( b & 0x7F ) << nShift;
-        if( (b & 0x80) == 0 )
+        nVal |= ( b64 & 0x7F ) << nShift;
+        if( (b64 & 0x80) == 0 )
         {
             pabyIter = pabyLocalIter;
             nOutVal += nVal * nSign;
@@ -1260,7 +1265,7 @@ int FileGDBTable::SelectRow(int iRow)
                     returnErrorAndCleanupIf( nOffsetTable + 4 + nRowBlobLength > nFileSize, nCurRow = -1 );
                 }
 
-                GByte* pabyNewBuffer = (GByte*) VSIRealloc( pabyBuffer,
+                GByte* pabyNewBuffer = (GByte*) VSI_REALLOC_VERBOSE( pabyBuffer,
                                 nRowBlobLength + ZEROES_AFTER_END_OF_BUFFER );
                 returnErrorAndCleanupIf(pabyNewBuffer == NULL, nCurRow = -1 );
 
@@ -1270,7 +1275,7 @@ int FileGDBTable::SelectRow(int iRow)
             returnErrorAndCleanupIf(
                 VSIFReadL(pabyBuffer, nRowBlobLength, 1, fpTable) != 1, nCurRow = -1 );
             /* Protection for 4 ReadVarUInt64NoCheck */
-            CPLAssert(ZEROES_AFTER_END_OF_BUFFER == 4);
+            CPL_STATIC_ASSERT(ZEROES_AFTER_END_OF_BUFFER == 4);
             pabyBuffer[nRowBlobLength] = 0;
             pabyBuffer[nRowBlobLength+1] = 0;
             pabyBuffer[nRowBlobLength+2] = 0;
@@ -1350,7 +1355,8 @@ const OGRField* FileGDBTable::GetFieldValue(int iCol)
                 continue;
         }
 
-        GUInt32 nLength;
+        GUInt32 nLength = 0;
+        CPL_IGNORE_RET_VAL(nLength);
         switch( apoFields[j]->eType )
         {
             case FGFT_STRING:
@@ -1378,7 +1384,6 @@ const OGRField* FileGDBTable::GetFieldValue(int iCol)
             case FGFT_UUID_2: nLength = UUID_SIZE_IN_BYTES; break;
 
             default:
-                nLength = 0;
                 CPLAssert(FALSE);
                 break;
         }
@@ -1429,7 +1434,7 @@ const OGRField* FileGDBTable::GetFieldValue(int iCol)
             nChSaved = *pabyIterVals;
             *pabyIterVals = '\0';
 
-            /* CPLDebug("OpenFileGDB", "Field %d, row %d: %s", iCol, nCurRow, sCurField.String); */ 
+            /* CPLDebug("OpenFileGDB", "Field %d, row %d: %s", iCol, nCurRow, sCurField.String); */
 
             break;
         }
@@ -1444,7 +1449,7 @@ const OGRField* FileGDBTable::GetFieldValue(int iCol)
 
             /* eCurFieldType = OFTInteger; */
             sCurField.Integer = GetInt16(pabyIterVals, 0);
-            
+
             pabyIterVals += sizeof(GInt16);
             /* CPLDebug("OpenFileGDB", "Field %d, row %d: %d", iCol, nCurRow, sCurField.Integer); */
 
@@ -1461,7 +1466,7 @@ const OGRField* FileGDBTable::GetFieldValue(int iCol)
 
             /* eCurFieldType = OFTInteger; */
             sCurField.Integer = GetInt32(pabyIterVals, 0);
-            
+
             pabyIterVals += sizeof(GInt32);
             /* CPLDebug("OpenFileGDB", "Field %d, row %d: %d", iCol, nCurRow, sCurField.Integer); */
 
@@ -1478,7 +1483,7 @@ const OGRField* FileGDBTable::GetFieldValue(int iCol)
 
             /* eCurFieldType = OFTReal; */
             sCurField.Real = GetFloat32(pabyIterVals, 0);
-            
+
             pabyIterVals += sizeof(float);
             /* CPLDebug("OpenFileGDB", "Field %d, row %d: %f", iCol, nCurRow, sCurField.Real); */
 
@@ -1495,7 +1500,7 @@ const OGRField* FileGDBTable::GetFieldValue(int iCol)
 
             /* eCurFieldType = OFTReal; */
             sCurField.Real = GetFloat64(pabyIterVals, 0);
-            
+
             pabyIterVals += sizeof(double);
             /* CPLDebug("OpenFileGDB", "Field %d, row %d: %f", iCol, nCurRow, sCurField.Real); */
 
@@ -1583,7 +1588,7 @@ const OGRField* FileGDBTable::GetFieldValue(int iCol)
             /* eCurFieldType = OFTString; */
             sCurField.String = achGUIDBuffer;
             /*78563412BC9AF0DE1234567890ABCDEF --> {12345678-9ABC-DEF0-1234-567890ABCDEF} */
-            sprintf(achGUIDBuffer,
+            snprintf(achGUIDBuffer, sizeof(achGUIDBuffer),
                     "{%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
                     pabyIterVals[3], pabyIterVals[2], pabyIterVals[1], pabyIterVals[0],
                     pabyIterVals[5], pabyIterVals[4],
@@ -1637,19 +1642,19 @@ int FileGDBTable::GetIndexCount()
     }
 
     VSIFSeekL(fpIndexes, 0, SEEK_END);
-    vsi_l_offset nFileSize = VSIFTellL(fpIndexes);
-    returnErrorAndCleanupIf(nFileSize > 1024 * 1024, VSIFCloseL(fpIndexes) );
+    vsi_l_offset l_nFileSize = VSIFTellL(fpIndexes);
+    returnErrorAndCleanupIf(l_nFileSize > 1024 * 1024, VSIFCloseL(fpIndexes) );
 
-    GByte* pabyIdx = (GByte*)VSIMalloc((size_t)nFileSize);
+    GByte* pabyIdx = (GByte*)VSI_MALLOC_VERBOSE((size_t)l_nFileSize);
     returnErrorAndCleanupIf(pabyIdx == NULL, VSIFCloseL(fpIndexes) );
 
     VSIFSeekL(fpIndexes, 0, SEEK_SET);
-    int nRead = (int)VSIFReadL( pabyIdx, (size_t)nFileSize, 1, fpIndexes );
+    int nRead = (int)VSIFReadL( pabyIdx, (size_t)l_nFileSize, 1, fpIndexes );
     VSIFCloseL(fpIndexes);
     returnErrorAndCleanupIf(nRead != 1, VSIFree(pabyIdx) );
 
     GByte* pabyCur = pabyIdx;
-    GByte* pabyEnd = pabyIdx + nFileSize;
+    GByte* pabyEnd = pabyIdx + l_nFileSize;
     returnErrorAndCleanupIf(pabyEnd - pabyCur < 4, VSIFree(pabyIdx) );
     GUInt32 nIndexCount = GetUInt32(pabyCur, 0);
     pabyCur += 4;
@@ -1859,7 +1864,7 @@ int FileGDBTable::GetFeatureExtent(const OGRField* psField,
     if( nPoints == 0 )
         return TRUE;
     returnErrorIf(!SkipVarUInt(pabyCur, pabyEnd, nToSkip) );
-    
+
     GUIntBig vxmin, vymin, vdx, vdy;
 
     returnErrorIf(pabyCur >= pabyEnd);
@@ -1867,7 +1872,7 @@ int FileGDBTable::GetFeatureExtent(const OGRField* psField,
     ReadVarUInt64NoCheck(pabyCur, vymin);
     ReadVarUInt64NoCheck(pabyCur, vdx);
     ReadVarUInt64NoCheck(pabyCur, vdy);
-    
+
     psOutFeatureEnvelope->MinX = vxmin / poGeomField->dfXYScale + poGeomField->dfXOrigin;
     psOutFeatureEnvelope->MinY = vymin / poGeomField->dfXYScale + poGeomField->dfYOrigin;
     psOutFeatureEnvelope->MaxX = (vxmin + vdx) / poGeomField->dfXYScale + poGeomField->dfXOrigin;
@@ -1955,7 +1960,7 @@ int FileGDBTable::DoesGeometryIntersectsFilterEnvelope(const OGRField* psField)
     if( nPoints == 0 )
         return TRUE;
     returnErrorIf(!SkipVarUInt(pabyCur, pabyEnd, nToSkip) );
-    
+
     GUIntBig vxmin, vymin, vdx, vdy;
 
     returnErrorIf(pabyCur >= pabyEnd);
@@ -1976,8 +1981,8 @@ int FileGDBTable::DoesGeometryIntersectsFilterEnvelope(const OGRField* psField)
 /*                           FileGDBField()                             */
 /************************************************************************/
 
-FileGDBField::FileGDBField(FileGDBTable* poParent) :
-    poParent(poParent), eType(FGFT_UNDEFINED), bNullable(FALSE),
+FileGDBField::FileGDBField(FileGDBTable* poParentIn) :
+    poParent(poParentIn), eType(FGFT_UNDEFINED), bNullable(FALSE),
     nMaxWidth(0), poIndex(NULL)
 {
     sDefault.Set.nMarker1 = OGRUnsetMarker;
@@ -2021,8 +2026,8 @@ FileGDBIndex *FileGDBField::GetIndex()
 /*                           FileGDBGeomField()                         */
 /************************************************************************/
 
-FileGDBGeomField::FileGDBGeomField(FileGDBTable* poParent) :
-    FileGDBField(poParent), bHasZ(FALSE), bHasM(FALSE),
+FileGDBGeomField::FileGDBGeomField(FileGDBTable* poParentIn) :
+    FileGDBField(poParentIn), bHasZ(FALSE), bHasM(FALSE),
     dfXOrigin(0.0), dfYOrigin(0.0), dfXYScale(0.0), dfMOrigin(0.0),
     dfMScale(0.0), dfZOrigin(0.0), dfZScale(0.0), dfXYTolerance(0.0),
     dfMTolerance(0.0), dfZTolerance(0.0), dfXMin(0.0), dfYMin(0.0),
@@ -2034,7 +2039,7 @@ FileGDBGeomField::FileGDBGeomField(FileGDBTable* poParent) :
 /*                      FileGDBOGRGeometryConverterImpl                 */
 /************************************************************************/
 
-class FileGDBOGRGeometryConverterImpl : public FileGDBOGRGeometryConverter
+class FileGDBOGRGeometryConverterImpl CPL_FINAL : public FileGDBOGRGeometryConverter
 {
         const FileGDBGeomField      *poGeomField;
         GUInt32                     *panPointCount;
@@ -2060,6 +2065,11 @@ class FileGDBOGRGeometryConverterImpl : public FileGDBOGRGeometryConverter
                                                 GByte* pabyEnd,
                                                 GUInt32 nPoints,
                                                 GIntBig& dz);
+        template <class MSetter> int ReadMArray(MSetter& setter,
+                                                GByte*& pabyCur,
+                                                GByte* pabyEnd,
+                                                GUInt32 nPoints,
+                                                GIntBig& dm);
 
     public:
                                         FileGDBOGRGeometryConverterImpl(
@@ -2074,8 +2084,8 @@ class FileGDBOGRGeometryConverterImpl : public FileGDBOGRGeometryConverter
 /************************************************************************/
 
 FileGDBOGRGeometryConverterImpl::FileGDBOGRGeometryConverterImpl(
-                                    const FileGDBGeomField* poGeomField) :
-                                                poGeomField(poGeomField)
+                                    const FileGDBGeomField* poGeomFieldIn) :
+                                                poGeomField(poGeomFieldIn)
 {
     panPointCount = NULL;
     nPointCountMax = 0;
@@ -2125,7 +2135,7 @@ int FileGDBOGRGeometryConverterImpl::ReadPartDefs( GByte*& pabyCur,
     if( nParts > nPointCountMax )
     {
         GUInt32* panPointCountNew =
-            (GUInt32*) VSIRealloc( panPointCount, nParts * sizeof(GUInt32) );
+            (GUInt32*) VSI_REALLOC_VERBOSE( panPointCount, nParts * sizeof(GUInt32) );
         returnErrorIf(panPointCountNew == NULL );
         panPointCount = panPointCountNew;
         nPointCountMax = nParts;
@@ -2169,7 +2179,7 @@ class XYLineStringSetter
 {
         OGRRawPoint* paoPoints;
     public:
-        XYLineStringSetter(OGRRawPoint* paoPoints) : paoPoints(paoPoints) {}
+        XYLineStringSetter(OGRRawPoint* paoPointsIn) : paoPoints(paoPointsIn) {}
 
         void set(int i, double dfX, double dfY)
         {
@@ -2186,7 +2196,7 @@ class XYMultiPointSetter
 {
         OGRMultiPoint* poMPoint;
     public:
-        XYMultiPointSetter(OGRMultiPoint* poMPoint) : poMPoint(poMPoint) {}
+        XYMultiPointSetter(OGRMultiPoint* poMPointIn) : poMPoint(poMPointIn) {}
 
         void set(int i, double dfX, double dfY)
         {
@@ -2204,7 +2214,7 @@ class XYArraySetter
         double* padfX;
         double* padfY;
     public:
-        XYArraySetter(double* padfX, double* padfY) : padfX(padfX), padfY(padfY) {}
+        XYArraySetter(double* padfXIn, double* padfYIn) : padfX(padfXIn), padfY(padfYIn) {}
 
         void set(int i, double dfX, double dfY)
         {
@@ -2253,7 +2263,7 @@ class ZLineStringSetter
 {
         OGRLineString* poLS;
     public:
-        ZLineStringSetter(OGRLineString* poLS) : poLS(poLS) {}
+        ZLineStringSetter(OGRLineString* poLSIn) : poLS(poLSIn) {}
 
         void set(int i, double dfZ)
         {
@@ -2269,7 +2279,7 @@ class ZMultiPointSetter
 {
         OGRMultiPoint* poMPoint;
     public:
-        ZMultiPointSetter(OGRMultiPoint* poMPoint) : poMPoint(poMPoint) {}
+        ZMultiPointSetter(OGRMultiPoint* poMPointIn) : poMPoint(poMPointIn) {}
 
         void set(int i, double dfZ)
         {
@@ -2278,18 +2288,18 @@ class ZMultiPointSetter
 };
 
 /************************************************************************/
-/*                             ZArraySetter                            */
+/*                             FileGDBArraySetter                            */
 /************************************************************************/
 
-class ZArraySetter
+class FileGDBArraySetter
 {
-        double* padfZ;
+        double* padfValues;
     public:
-        ZArraySetter(double* padfZ) : padfZ(padfZ) {}
+        FileGDBArraySetter(double* padfValuesIn) : padfValues(padfValuesIn) {}
 
-        void set(int i, double dfZ)
+        void set(int i, double dfValue)
         {
-            padfZ[i] = dfZ;
+            padfValues[i] = dfValue;
         }
 };
 
@@ -2316,6 +2326,60 @@ template <class ZSetter> int FileGDBOGRGeometryConverterImpl::ReadZArray(ZSetter
 }
 
 /************************************************************************/
+/*                          MLineStringSetter                           */
+/************************************************************************/
+
+class MLineStringSetter
+{
+        OGRLineString* poLS;
+    public:
+        MLineStringSetter(OGRLineString* poLSIn) : poLS(poLSIn) {}
+
+        void set(int i, double dfM)
+        {
+            poLS->setM(i, dfM);
+        }
+};
+
+/************************************************************************/
+/*                         MMultiPointSetter                           */
+/************************************************************************/
+
+class MMultiPointSetter
+{
+        OGRMultiPoint* poMPoint;
+    public:
+        MMultiPointSetter(OGRMultiPoint* poMPointIn) : poMPoint(poMPointIn) {}
+
+        void set(int i, double dfM)
+        {
+            ((OGRPoint*)poMPoint->getGeometryRef(i))->setM(dfM);
+        }
+};
+
+/************************************************************************/
+/*                          ReadMArray()                                */
+/************************************************************************/
+
+template <class MSetter> int FileGDBOGRGeometryConverterImpl::ReadMArray(MSetter& setter,
+                                                      GByte*& pabyCur,
+                                                      GByte* pabyEnd,
+                                                      GUInt32 nPoints,
+                                                      GIntBig& dm)
+{
+    const int errorRetValue = FALSE;
+    for(GUInt32 i = 0; i < nPoints; i++ )
+    {
+        returnErrorIf(pabyCur >= pabyEnd);
+        ReadVarIntAndAddNoCheck(pabyCur, dm);
+
+        double dfM = dm / poGeomField->GetMScale() + poGeomField->GetMOrigin();
+        setter.set(i, dfM);
+    }
+    return TRUE;
+}
+
+/************************************************************************/
 /*                          GetAsGeometry()                             */
 /************************************************************************/
 
@@ -2331,6 +2395,7 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
     ReadVarUInt32NoCheck(pabyCur, nGeomType);
 
     int bHasZ = (nGeomType & 0x80000000) != 0;
+    bool bHasM = (nGeomType & 0x40000000) != 0;
     switch( (nGeomType & 0xff) )
     {
         case SHPT_NULL:
@@ -2339,9 +2404,13 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
         case SHPT_POINTZ:
         case SHPT_POINTZM:
             bHasZ = TRUE; /* go on */
+            // CPL_FALLTHROUGH
         case SHPT_POINT:
         case SHPT_POINTM:
         {
+            if( nGeomType == SHPT_POINTM || nGeomType == SHPT_POINTZM )
+                bHasM = true;
+
             double dfX, dfY, dfZ;
             ReadVarUInt64NoCheck(pabyCur, x);
             ReadVarUInt64NoCheck(pabyCur, y);
@@ -2352,8 +2421,24 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
             {
                 ReadVarUInt64NoCheck(pabyCur, z);
                 dfZ = (z - 1) / poGeomField->GetZScale() + poGeomField->GetZOrigin();
+                if( bHasM )
+                {
+                    GUIntBig m;
+                    ReadVarUInt64NoCheck(pabyCur, m);
+                    double dfM = (m - 1) / poGeomField->GetMScale() + poGeomField->GetMOrigin();
+                    return new OGRPoint(dfX, dfY, dfZ, dfM);
+                }
                 return new OGRPoint(dfX, dfY, dfZ);
             }
+            else if( bHasM )
+            {
+                OGRPoint* poPoint = new OGRPoint(dfX, dfY);
+                GUIntBig m;
+                ReadVarUInt64NoCheck(pabyCur, m);
+                double dfM = (m - 1) / poGeomField->GetMScale() + poGeomField->GetMOrigin();
+                poPoint->setM(dfM);
+                return poPoint;
+            }
             else
             {
                 return new OGRPoint(dfX, dfY);
@@ -2364,15 +2449,21 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
         case SHPT_MULTIPOINTZM:
         case SHPT_MULTIPOINTZ:
             bHasZ = TRUE; /* go on */
+            // CPL_FALLTHROUGH
         case SHPT_MULTIPOINT:
         case SHPT_MULTIPOINTM:
         {
+            if( nGeomType == SHPT_MULTIPOINTM || nGeomType == SHPT_MULTIPOINTZM )
+                bHasM = true;
+
             returnErrorIf(!ReadVarUInt32(pabyCur, pabyEnd, nPoints) );
             if( nPoints == 0 )
             {
                 OGRMultiPoint* poMP = new OGRMultiPoint();
                 if( bHasZ )
-                    poMP->setCoordinateDimension(3);
+                    poMP->set3D(TRUE);
+                if( bHasM )
+                    poMP->setMeasured(TRUE);
                 return poMP;
             }
 
@@ -2401,6 +2492,19 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
                 }
             }
 
+            if( bHasM )
+            {
+                poMP->setMeasured(TRUE);
+                GIntBig dm = 0;
+                MMultiPointSetter mpmSetter(poMP);
+                if( !ReadMArray<MMultiPointSetter>(mpmSetter,
+                                pabyCur, pabyEnd, nPoints, dm) )
+                {
+                    delete poMP;
+                    returnError();
+                }
+            }
+
             return poMP;
             break;
         }
@@ -2408,10 +2512,14 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
         case SHPT_ARCZ:
         case SHPT_ARCZM:
             bHasZ = TRUE; /* go on */
+            // CPL_FALLTHROUGH
         case SHPT_ARC:
         case SHPT_ARCM:
         case SHPT_GENERALPOLYLINE:
         {
+            if( nGeomType == SHPT_ARCM || nGeomType == SHPT_ARCZM )
+                bHasM = true;
+
             returnErrorIf(!ReadPartDefs(pabyCur, pabyEnd, nPoints, nParts,
                               (nGeomType & 0x20000000) != 0,
                               FALSE) );
@@ -2420,7 +2528,9 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
             {
                 OGRLineString* poLS = new OGRLineString();
                 if( bHasZ )
-                    poLS->setCoordinateDimension(3);
+                    poLS->set3D(TRUE);
+                if( bHasM )
+                    poLS->setMeasured(TRUE);
                 return poLS;
             }
 
@@ -2476,6 +2586,28 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
                 }
             }
 
+            if( bHasM )
+            {
+                GIntBig dm = 0;
+                for(i=0;i<nParts;i++)
+                {
+                    if( nParts > 1 )
+                        poLS = (FileGDBOGRLineString*) poMLS->getGeometryRef(i);
+
+                    MLineStringSetter lsmSetter(poLS);
+                    if( !ReadMArray<MLineStringSetter>(lsmSetter,
+                                    pabyCur, pabyEnd,
+                                    panPointCount[i], dm) )
+                    {
+                        if( nParts > 1 )
+                            delete poMLS;
+                        else
+                            delete poLS;
+                        returnError();
+                    }
+                }
+            }
+
             if( poMLS )
                 return poMLS;
             else
@@ -2487,10 +2619,14 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
         case SHPT_POLYGONZ:
         case SHPT_POLYGONZM:
             bHasZ = TRUE; /* go on */
+            // CPL_FALLTHROUGH
         case SHPT_POLYGON:
         case SHPT_POLYGONM:
         case SHPT_GENERALPOLYGON:
         {
+            if( nGeomType == SHPT_POLYGONM || nGeomType == SHPT_POLYGONZM )
+                bHasM = true;
+
             returnErrorIf(!ReadPartDefs(pabyCur, pabyEnd, nPoints, nParts,
                               (nGeomType & 0x20000000) != 0,
                               FALSE) );
@@ -2499,7 +2635,9 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
             {
                 OGRPolygon* poPoly = new OGRPolygon();
                 if( bHasZ )
-                    poPoly->setCoordinateDimension(3);
+                    poPoly->set3D(TRUE);
+                if( bHasM )
+                    poPoly->setMeasured(TRUE);
                 return poPoly;
             }
 
@@ -2544,6 +2682,26 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
                 }
             }
 
+            if( bHasM )
+            {
+                GIntBig dm = 0;
+                for(i=0;i<nParts;i++)
+                {
+                    papoRings[i]->setMeasured(TRUE);
+
+                    MLineStringSetter lsmSetter(papoRings[i]);
+                    if( !ReadMArray<MLineStringSetter>(lsmSetter,
+                                    pabyCur, pabyEnd,
+                                    panPointCount[i], dm) )
+                    {
+                        while( (int)i >= 0 )
+                            delete papoRings[i--];
+                        delete[] papoRings;
+                        returnError();
+                    }
+                }
+            }
+
             OGRGeometry* poRet;
             if( nParts == 1 )
             {
@@ -2623,6 +2781,7 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
         case SHPT_MULTIPATCHM:
         case SHPT_MULTIPATCH:
             bHasZ = TRUE; /* go on */
+            // CPL_FALLTHROUGH
         case SHPT_GENERALMULTIPATCH:
         {
             returnErrorIf(!ReadPartDefs(pabyCur, pabyEnd, nPoints, nParts, FALSE, TRUE ) );
@@ -2634,8 +2793,8 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
                     poPoly->setCoordinateDimension(3);
                 return poPoly;
             }
-            int* panPartType = (int*) VSIMalloc(sizeof(int) * nParts);
-            double* padfXYZ =  (double*) VSIMalloc(3 * sizeof(double) * nPoints);
+            int* panPartType = (int*) VSI_MALLOC_VERBOSE(sizeof(int) * nParts);
+            double* padfXYZ =  (double*) VSI_MALLOC_VERBOSE(3 * sizeof(double) * nPoints);
             double* padfX = padfXYZ;
             double* padfY = padfXYZ + nPoints;
             double* padfZ = padfXYZ + 2 * nPoints;
@@ -2669,8 +2828,8 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
 
             if( bHasZ )
             {
-                ZArraySetter arrayzSetter(padfZ);
-                if( !ReadZArray<ZArraySetter>(arrayzSetter,
+                FileGDBArraySetter arrayzSetter(padfZ);
+                if( !ReadZArray<FileGDBArraySetter>(arrayzSetter,
                                 pabyCur, pabyEnd, nPoints, dz) )
                 {
                     VSIFree(panPartType);
diff --git a/ogr/ogrsf_frmts/openfilegdb/filegdbtable.h b/ogr/ogrsf_frmts/openfilegdb/filegdbtable.h
index 421b7bb..090e5fe 100644
--- a/ogr/ogrsf_frmts/openfilegdb/filegdbtable.h
+++ b/ogr/ogrsf_frmts/openfilegdb/filegdbtable.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: filegdbtable.h 29158 2015-05-05 21:19:37Z rouault $
+ * $Id: filegdbtable.h 33024 2016-01-17 16:10:22Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements reading of FileGDB tables
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _FILEGDBTABLE_H_INCLUDED
-#define _FILEGDBTABLE_H_INCLUDED
+#ifndef FILEGDBTABLE_H_INCLUDED
+#define FILEGDBTABLE_H_INCLUDED
 
 #include "ogr_core.h"
 #include "cpl_vsi.h"
@@ -171,7 +171,7 @@ class FileGDBGeomField: public FileGDBField
         double             GetMOrigin() const { return dfMOrigin; }
         double             GetMScale() const { return dfMScale; }
         double             GetMTolerance() const { return dfMTolerance; }
-        
+
         int                Has3D() const { return bHas3D; }
 };
 
@@ -186,7 +186,7 @@ class FileGDBRasterField: public FileGDBGeomField
         std::string       osRasterColumnName;
 
     public:
-                          FileGDBRasterField(FileGDBTable* poParent) : FileGDBGeomField(poParent) {}
+                          FileGDBRasterField(FileGDBTable* poParentIn) : FileGDBGeomField(poParentIn) {}
         virtual          ~FileGDBRasterField() {}
 
         const std::string& GetRasterColumnName() const { return osRasterColumnName; }
@@ -265,7 +265,7 @@ class FileGDBTable
         void                        Init();
 
         GUIntBig                    nFilterXMin, nFilterXMax, nFilterYMin, nFilterYMax;
-        
+
         GUInt32                     nOffsetHeaderEnd;
 
         int                         ReadTableXHeader();
@@ -290,7 +290,9 @@ class FileGDBTable
        int                      GetFieldCount() const { return (int)apoFields.size(); }
        FileGDBField*            GetField(int i) const { return apoFields[i]; }
        int                      GetGeomFieldIdx() const { return iGeomField; }
-       const FileGDBGeomField*  GetGeomField() const { return (iGeomField >= 0) ? (FileGDBGeomField*)apoFields[iGeomField] : NULL; }
+       const FileGDBGeomField*  GetGeomField() const {
+           return (iGeomField >= 0) ?
+               reinterpret_cast<FileGDBGeomField*>(apoFields[iGeomField]) : NULL; }
        const std::string&       GetObjectIdColName() const { return osObjectIdColName; }
 
        int                      GetFieldIdx(const std::string& osName) const;
@@ -299,7 +301,7 @@ class FileGDBTable
        const FileGDBIndex*      GetIndex(int i) const { return apoIndexes[i]; }
 
        vsi_l_offset             GetOffsetInTableForRow(int iRow);
-       
+
        int                      HasDeletedFeaturesListed() const { return bHasDeletedFeaturesListed; }
 
        /* Next call to SelectRow() or GetFieldValue() invalidates previously returned values */
@@ -391,4 +393,4 @@ int FileGDBDoubleDateToOGRDate(double dfVal, OGRField* psField);
 
 }; /* namespace OpenFileGDB */
 
-#endif /* ndef _FILEGDBTABLE_H_INCLUDED */
+#endif /* ndef FILEGDBTABLE_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/openfilegdb/filegdbtable_priv.h b/ogr/ogrsf_frmts/openfilegdb/filegdbtable_priv.h
index b9cd381..9d64350 100644
--- a/ogr/ogrsf_frmts/openfilegdb/filegdbtable_priv.h
+++ b/ogr/ogrsf_frmts/openfilegdb/filegdbtable_priv.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: filegdbtable_priv.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: filegdbtable_priv.h 31777 2015-11-26 14:14:41Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements reading of FileGDB tables
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _FILEGDBTABLE_PRIV_H_INCLUDED
-#define _FILEGDBTABLE_PRIV_H_INCLUDED
+#ifndef FILEGDBTABLE_PRIV_H_INCLUDED
+#define FILEGDBTABLE_PRIV_H_INCLUDED
 
 #include "filegdbtable.h"
 #include "cpl_error.h"
@@ -135,4 +135,4 @@ void FileGDBTablePrintError(const char* pszFile, int nLineNumber);
 
 }; /* namespace OpenFileGDB */
 
-#endif /* _FILEGDBTABLE_PRIV_H_INCLUDED */
+#endif /* FILEGDBTABLE_PRIV_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/openfilegdb/ogr_openfilegdb.h b/ogr/ogrsf_frmts/openfilegdb/ogr_openfilegdb.h
index fac7ec5..8c56200 100644
--- a/ogr/ogrsf_frmts/openfilegdb/ogr_openfilegdb.h
+++ b/ogr/ogrsf_frmts/openfilegdb/ogr_openfilegdb.h
@@ -1,5 +1,5 @@
 /******************************************************************************
-* $Id: ogr_openfilegdb.h 28967 2015-04-21 11:01:15Z rouault $
+* $Id: ogr_openfilegdb.h 33024 2016-01-17 16:10:22Z goatbar $
 *
 * Project:  OpenGIS Simple Features Reference Implementation
 * Purpose:  Implements Open FileGDB OGR driver.
@@ -27,8 +27,8 @@
 * DEALINGS IN THE SOFTWARE.
 ****************************************************************************/
 
-#ifndef _OGR_OPENFILEGDB_H_INCLUDED
-#define _OGR_OPENFILEGDB_H_INCLUDED
+#ifndef OGR_OPENFILEGDB_H_INCLUDED
+#define OGR_OPENFILEGDB_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "filegdbtable.h"
@@ -77,7 +77,7 @@ class OGROpenFileGDBLayer : public OGRLayer
     OGRFeature       *GetCurrentFeature();
 
     FileGDBOGRGeometryConverter* m_poGeomConverter;
-    
+
     int               m_iFieldToReadAsBinary;
 
     FileGDBIterator      *m_poIterator;
@@ -103,7 +103,7 @@ public:
                                             const char* pszGeomName = NULL,
                                             OGRwkbGeometryType eGeomType = wkbUnknown);
   virtual              ~OGROpenFileGDBLayer();
-  
+
   const std::string&    GetXMLDefinition() { return m_osDefinition; }
   const std::string&    GetXMLDocumentation() { return m_osDocumentation; }
   int                   GetAttrIndexUse() { return (m_poIterator == NULL) ? 0 : (m_bIteratorSufficientToEvaluateFilter) ? 2 : 1; }
@@ -132,11 +132,14 @@ public:
 
   virtual GIntBig     GetFeatureCount( int bForce = TRUE );
   virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+  virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
   virtual OGRFeatureDefn* GetLayerDefn();
 
   virtual void        SetSpatialFilter( OGRGeometry * );
-
+  virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+                { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
   virtual OGRErr      SetAttributeFilter( const char* pszFilter );
 
   virtual int         TestCapability( const char * );
@@ -156,7 +159,7 @@ class OGROpenFileGDBDataSource : public OGRDataSource
   std::map<std::string, int>     m_osMapNameToIdx;
 
   /* For debugging/testing */
-  int                            bLastSQLUsedOptimizedImplementation;
+  bool                           bLastSQLUsedOptimizedImplementation;
 
   int                 OpenFileGDBv10(int iGDBItems,
                                      int nInterestTable);
@@ -168,7 +171,7 @@ class OGROpenFileGDBDataSource : public OGRDataSource
   void                AddLayer( const CPLString& osName,
                                 int nInterestTable,
                                 int& nCandidateLayers,
-                                int& nLayersSDC,
+                                int& nLayersSDCOrCDF,
                                 const CPLString& osDefinition,
                                 const CPLString& osDocumentation,
                                 const char* pszGeomName,
@@ -192,10 +195,10 @@ public:
   virtual void        ReleaseResultSet( OGRLayer * poResultsSet );
 
   virtual int         TestCapability( const char * );
-  
+
   virtual char      **GetFileList();
 };
 
 int OGROpenFileGDBIsComparisonOp(int op);
 
-#endif /* ndef _OGR_OPENFILEGDB_H_INCLUDED */
+#endif /* ndef OGR_OPENFILEGDB_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdbdatasource.cpp b/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdbdatasource.cpp
index a06a2b7..e6e3ceb 100644
--- a/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdbdatasource.cpp
+++ b/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdbdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogropenfilegdbdatasource.cpp 29024 2015-04-26 10:42:08Z rouault $
+ * $Id: ogropenfilegdbdatasource.cpp 33712 2016-03-12 10:51:56Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements Open FileGDB OGR driver.
@@ -36,12 +36,11 @@ CPL_CVSID("$Id");
 /************************************************************************/
 /*                      OGROpenFileGDBDataSource()                      */
 /************************************************************************/
-OGROpenFileGDBDataSource::OGROpenFileGDBDataSource()
-{
-    m_pszName = NULL;
-    m_papszFiles = NULL;
-    bLastSQLUsedOptimizedImplementation = FALSE;
-}
+OGROpenFileGDBDataSource::OGROpenFileGDBDataSource() :
+    m_pszName(NULL),
+    m_papszFiles(NULL),
+    bLastSQLUsedOptimizedImplementation(false)
+{}
 
 /************************************************************************/
 /*                     ~OGROpenFileGDBDataSource()                      */
@@ -49,10 +48,9 @@ OGROpenFileGDBDataSource::OGROpenFileGDBDataSource()
 OGROpenFileGDBDataSource::~OGROpenFileGDBDataSource()
 
 {
-    size_t i;
-    for( i = 0; i < m_apoLayers.size(); i++ )
+    for( size_t i = 0; i < m_apoLayers.size(); i++ )
         delete m_apoLayers[i];
-    for( i = 0; i < m_apoHiddenLayers.size(); i++ )
+    for( size_t i = 0; i < m_apoHiddenLayers.size(); i++ )
         delete m_apoHiddenLayers[i];
     CPLFree(m_pszName);
     CSLDestroy(m_papszFiles);
@@ -66,11 +64,9 @@ int OGROpenFileGDBDataSource::FileExists(const char* pszFilename)
 {
     if( m_papszFiles )
         return CSLFindString(m_papszFiles, CPLGetFilename(pszFilename)) >= 0;
-    else
-    {
-        VSIStatBufL sStat;
-        return VSIStatExL(pszFilename, &sStat, VSI_STAT_EXISTS_FLAG) == 0;
-    }
+
+    VSIStatBufL sStat;
+    return VSIStatExL(pszFilename, &sStat, VSI_STAT_EXISTS_FLAG) == 0;
 }
 
 /************************************************************************/
@@ -99,27 +95,28 @@ int OGROpenFileGDBDataSource::Open( const char* pszFilename )
     }
 
     if( EQUAL(CPLGetExtension(m_osDirName), "zip") &&
-        strncmp(m_osDirName, "/vsizip/", strlen("/vsizip/")) != 0 )
+        !STARTS_WITH(m_osDirName, "/vsizip/") )
     {
         m_osDirName = "/vsizip/" + m_osDirName;
     }
     else  if( EQUAL(CPLGetExtension(m_osDirName), "tar") &&
-        strncmp(m_osDirName, "/vsitar/", strlen("/vsitar/")) != 0 )
+        !STARTS_WITH(m_osDirName, "/vsitar/") )
     {
         m_osDirName = "/vsitar/" + m_osDirName;
     }
 
-    if( strncmp(m_osDirName, "/vsizip/", strlen("/vsizip/")) == 0 ||
-        strncmp(m_osDirName, "/vsitar/", strlen("/vsitar/")) == 0)
+    if( STARTS_WITH(m_osDirName, "/vsizip/") ||
+        STARTS_WITH(m_osDirName, "/vsitar/"))
     {
         /* Look for one subdirectory ending with .gdb extension */
-        char** papszDir = CPLReadDir(m_osDirName);
+        char** papszDir = VSIReadDir(m_osDirName);
         int iCandidate = -1;
         for( int i=0; papszDir && papszDir[i] != NULL; i++ )
         {
             VSIStatBufL sStat;
             if( EQUAL(CPLGetExtension(papszDir[i]), "gdb") &&
-                VSIStatL( CPLSPrintf("%s/%s", m_osDirName.c_str(), papszDir[i]), &sStat ) == 0 &&
+                VSIStatL( CPLSPrintf("%s/%s", m_osDirName.c_str(), papszDir[i]),
+                          &sStat ) == 0 &&
                 VSI_ISDIR(sStat.st_mode) )
             {
                 if( iCandidate < 0 )
@@ -142,7 +139,8 @@ int OGROpenFileGDBDataSource::Open( const char* pszFilename )
     m_papszFiles = VSIReadDir(m_osDirName);
 
     /* Explore catalog table */
-    const char* psza00000001 = CPLFormFilename(m_osDirName, "a00000001", "gdbtable");
+    const char* psza00000001 =
+        CPLFormFilename(m_osDirName, "a00000001", "gdbtable");
     if( !FileExists(psza00000001) || !oTable.Open(psza00000001) )
     {
         if( nInterestTable >= 0 && FileExists(m_pszName) )
@@ -178,10 +176,9 @@ int OGROpenFileGDBDataSource::Open( const char* pszFilename )
     int iGDBItems = -1; /* V10 */
     int iGDBFeatureClasses = -1; /* V9.X */
     int iGDBObjectClasses = -1; /* V9.X */
-    int i;
 
     std::vector<std::string> aosTableNames;
-    for(i=0;i<oTable.GetTotalRecordCount();i++)
+    for( int i=0;i<oTable.GetTotalRecordCount();i++)
     {
         if( !oTable.SelectRow(i) )
         {
@@ -269,7 +266,7 @@ int OGROpenFileGDBDataSource::Open( const char* pszFilename )
 void OGROpenFileGDBDataSource::AddLayer( const CPLString& osName,
                                          int nInterestTable,
                                          int& nCandidateLayers,
-                                         int& nLayersSDC,
+                                         int& nLayersSDCOrCDF,
                                          const CPLString& osDefinition,
                                          const CPLString& osDocumentation,
                                          const char* pszGeomName,
@@ -291,12 +288,22 @@ void OGROpenFileGDBDataSource::AddLayer( const CPLString& osName,
             if( m_papszFiles != NULL )
             {
                 const char* pszSDC = CPLResetExtension(pszFilename, "gdbtable.sdc");
-                if( FileExists(pszSDC) )
+                const char* pszCDF = CPLResetExtension(pszFilename, "gdbtable.cdf");
+                if( FileExists(pszSDC) || FileExists(pszCDF) )
                 {
-                    nLayersSDC ++;
-                    CPLError(CE_Warning, CPLE_AppDefined,
-                            "%s layer has a %s file whose format is unhandled",
-                            osName.c_str(), pszSDC);
+                    nLayersSDCOrCDF ++;
+                    if( GDALGetDriverByName("FileGDB") == NULL )
+                    {
+                        CPLError(CE_Warning, CPLE_AppDefined,
+                                "%s layer has a %s file whose format is unhandled",
+                                osName.c_str(), FileExists(pszSDC) ? pszSDC : pszCDF);
+                    }
+                    else
+                    {
+                        CPLDebug("OpenFileGDB",
+                                 "%s layer has a %s file whose format is unhandled",
+                                  osName.c_str(), FileExists(pszSDC) ? pszSDC : pszCDF);
+                    }
                     return;
                 }
             }
@@ -318,11 +325,11 @@ void OGROpenFileGDBDataSource::AddLayer( const CPLString& osName,
 int OGROpenFileGDBDataSource::OpenFileGDBv10(int iGDBItems,
                                              int nInterestTable)
 {
-    FileGDBTable oTable;
-    int i;
 
     CPLDebug("OpenFileGDB", "FileGDB v10 or later");
 
+    FileGDBTable oTable;
+
     if( !oTable.Open(CPLFormFilename(m_osDirName,
             CPLSPrintf("a%08x.gdbtable", iGDBItems + 1), NULL)) )
         return FALSE;
@@ -340,8 +347,9 @@ int OGROpenFileGDBDataSource::OpenFileGDBv10(int iGDBItems,
         return FALSE;
     }
 
-    int nCandidateLayers = 0, nLayersSDC = 0;
-    for(i=0;i<oTable.GetTotalRecordCount();i++)
+    int nCandidateLayers = 0;
+    int nLayersSDCOrCDF = 0;
+    for( int i=0;i<oTable.GetTotalRecordCount();i++)
     {
         if( !oTable.SelectRow(i) )
         {
@@ -363,7 +371,7 @@ int OGROpenFileGDBDataSource::OpenFileGDBv10(int iGDBItems,
             psField = oTable.GetFieldValue(iName);
             if( psField != NULL )
             {
-                AddLayer( psField->String, nInterestTable, nCandidateLayers, nLayersSDC,
+                AddLayer( psField->String, nInterestTable, nCandidateLayers, nLayersSDCOrCDF,
                           osDefinition, osDocumentation,
                           NULL, wkbUnknown );
             }
@@ -371,7 +379,7 @@ int OGROpenFileGDBDataSource::OpenFileGDBv10(int iGDBItems,
     }
 
     if( m_apoLayers.size() == 0 && nCandidateLayers > 0 &&
-        nCandidateLayers == nLayersSDC )
+        nCandidateLayers == nLayersSDCOrCDF )
         return FALSE;
 
     return TRUE;
@@ -404,9 +412,9 @@ int OGROpenFileGDBDataSource::OpenFileGDBv9(int iGDBFeatureClasses,
                     "Wrong structure for GDB_ObjectClasses table");
         return FALSE;
     }
-    
+
     std::vector< std::string > aosName;
-    int nCandidateLayers = 0, nLayersSDC = 0;
+    int nCandidateLayers = 0, nLayersSDCOrCDF = 0;
     for(i=0;i<oTable.GetTotalRecordCount();i++)
     {
         if( !oTable.SelectRow(i) )
@@ -428,7 +436,7 @@ int OGROpenFileGDBDataSource::OpenFileGDBv9(int iGDBFeatureClasses,
                 if( strcmp(psField->String, "{7A566981-C114-11D2-8A28-006097AFF44E}") == 0 )
                 {
                     aosName.push_back( "" );
-                    AddLayer( osName, nInterestTable, nCandidateLayers, nLayersSDC,
+                    AddLayer( osName, nInterestTable, nCandidateLayers, nLayersSDCOrCDF,
                               "", "", NULL, wkbNone );
                 }
                 else
@@ -473,7 +481,7 @@ int OGROpenFileGDBDataSource::OpenFileGDBv9(int iGDBFeatureClasses,
         psField = oTable.GetFieldValue(iGeometryType);
         if( psField == NULL )
             continue;
-        int nGeomType = psField->Integer;
+        const int nGeomType = psField->Integer;
         OGRwkbGeometryType eGeomType = wkbUnknown;
         switch( nGeomType )
         {
@@ -495,17 +503,17 @@ int OGROpenFileGDBDataSource::OpenFileGDBv9(int iGDBFeatureClasses,
             continue;
 
         int idx = psField->Integer;
-        if( psField != NULL && idx > 0 && idx <= (int)aosName.size() &&
+        if( idx > 0 && idx <= static_cast<int>(aosName.size()) &&
             aosName[idx-1].size() > 0 )
         {
             const std::string osName(aosName[idx-1]);
-            AddLayer( osName, nInterestTable, nCandidateLayers, nLayersSDC,
+            AddLayer( osName, nInterestTable, nCandidateLayers, nLayersSDCOrCDF,
                       "", "", osGeomFieldName.c_str(), eGeomType);
         }
     }
 
     if( m_apoLayers.size() == 0 && nCandidateLayers > 0 &&
-        nCandidateLayers == nLayersSDC )
+        nCandidateLayers == nLayersSDCOrCDF )
         return FALSE;
 
     return TRUE;
@@ -515,9 +523,8 @@ int OGROpenFileGDBDataSource::OpenFileGDBv9(int iGDBFeatureClasses,
 /*                         TestCapability()                            */
 /***********************************************************************/
 
-int OGROpenFileGDBDataSource::TestCapability( const char * pszCap )
+int OGROpenFileGDBDataSource::TestCapability( const char * /* pszCap */ )
 {
-    (void)pszCap;
     return FALSE;
 }
 
@@ -595,7 +602,7 @@ class OGROpenFileGDBSingleFeatureLayer : public OGRLayer
 /************************************************************************/
 
 OGROpenFileGDBSingleFeatureLayer::OGROpenFileGDBSingleFeatureLayer(const char* pszLayerName,
-                                                                   const char *pszVal )
+                                                                   const char *pszValIn )
 {
     poFeatureDefn = new OGRFeatureDefn( pszLayerName );
     SetDescription( poFeatureDefn->GetName() );
@@ -604,7 +611,7 @@ OGROpenFileGDBSingleFeatureLayer::OGROpenFileGDBSingleFeatureLayer(const char* p
     poFeatureDefn->AddFieldDefn( &oField );
 
     iNextShapeId = 0;
-    this->pszVal = pszVal ? CPLStrdup(pszVal) : NULL;
+    this->pszVal = pszValIn ? CPLStrdup(pszValIn) : NULL;
 }
 
 /************************************************************************/
@@ -660,6 +667,8 @@ class OGROpenFileGDBSimpleSQLLayer: public OGRLayer
        virtual const char* GetFIDColumn() { return poBaseLayer->GetFIDColumn(); }
        virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce )
                             { return poBaseLayer->GetExtent(psExtent, bForce); }
+       virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
        virtual GIntBig     GetFeatureCount(int bForce);
 };
 
@@ -668,11 +677,11 @@ class OGROpenFileGDBSimpleSQLLayer: public OGRLayer
 /***********************************************************************/
 
 OGROpenFileGDBSimpleSQLLayer::OGROpenFileGDBSimpleSQLLayer(
-                                            OGRLayer* poBaseLayer,
-                                            FileGDBIterator* poIter,
+                                            OGRLayer* poBaseLayerIn,
+                                            FileGDBIterator* poIterIn,
                                             int nColumns,
                                             swq_col_def* pasColDefs) :
-        poBaseLayer(poBaseLayer), poIter(poIter)
+        poBaseLayer(poBaseLayerIn), poIter(poIterIn)
 {
     if( nColumns == 1 && strcmp(pasColDefs[0].field_name, "*") == 0 )
     {
@@ -759,7 +768,7 @@ OGRFeature* OGROpenFileGDBSimpleSQLLayer::GetFeature( GIntBig nFeatureId )
 
 OGRFeature* OGROpenFileGDBSimpleSQLLayer::GetNextFeature()
 {
-    while(TRUE)
+    while( true )
     {
         int nRow = poIter->GetNextRowSortedByValue();
         if( nRow < 0 )
@@ -835,69 +844,72 @@ OGRLayer* OGROpenFileGDBDataSource::ExecuteSQL( const char *pszSQLCommand,
 /* -------------------------------------------------------------------- */
 /*      Special case GetLayerDefinition                                 */
 /* -------------------------------------------------------------------- */
-    if (EQUALN(pszSQLCommand, "GetLayerDefinition ", strlen("GetLayerDefinition ")))
+    if (STARTS_WITH_CI(pszSQLCommand, "GetLayerDefinition "))
     {
-        OGROpenFileGDBLayer* poLayer = (OGROpenFileGDBLayer*)
-            GetLayerByName(pszSQLCommand + strlen("GetLayerDefinition "));
+        OGROpenFileGDBLayer* poLayer = reinterpret_cast<OGROpenFileGDBLayer *>(
+            GetLayerByName(pszSQLCommand + strlen("GetLayerDefinition ")) );
         if (poLayer)
         {
             OGRLayer* poRet = new OGROpenFileGDBSingleFeatureLayer(
                 "LayerDefinition", poLayer->GetXMLDefinition().c_str() );
             return poRet;
         }
-        else
-            return NULL;
+
+        return NULL;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Special case GetLayerMetadata                                   */
 /* -------------------------------------------------------------------- */
-    if (EQUALN(pszSQLCommand, "GetLayerMetadata ", strlen("GetLayerMetadata ")))
+    if (STARTS_WITH_CI(pszSQLCommand, "GetLayerMetadata "))
     {
-        OGROpenFileGDBLayer* poLayer = (OGROpenFileGDBLayer*)
-            GetLayerByName(pszSQLCommand + strlen("GetLayerMetadata "));
+        OGROpenFileGDBLayer* poLayer = reinterpret_cast<OGROpenFileGDBLayer *>(
+            GetLayerByName(pszSQLCommand + strlen("GetLayerMetadata ")) );
         if (poLayer)
         {
             OGRLayer* poRet = new OGROpenFileGDBSingleFeatureLayer(
                 "LayerMetadata", poLayer->GetXMLDocumentation().c_str() );
             return poRet;
         }
-        else
-            return NULL;
+
+        return NULL;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Special case GetLayerAttrIndexUse (only for debugging purposes) */
 /* -------------------------------------------------------------------- */
-    if (EQUALN(pszSQLCommand, "GetLayerAttrIndexUse ", strlen("GetLayerAttrIndexUse ")))
+    if (STARTS_WITH_CI(pszSQLCommand, "GetLayerAttrIndexUse "))
     {
-        OGROpenFileGDBLayer* poLayer = (OGROpenFileGDBLayer*)
-            GetLayerByName(pszSQLCommand + strlen("GetLayerAttrIndexUse "));
+        OGROpenFileGDBLayer* poLayer = reinterpret_cast<OGROpenFileGDBLayer *>(
+            GetLayerByName(pszSQLCommand + strlen("GetLayerAttrIndexUse ")) );
         if (poLayer)
         {
             OGRLayer* poRet = new OGROpenFileGDBSingleFeatureLayer(
-                "LayerAttrIndexUse", CPLSPrintf("%d", poLayer->GetAttrIndexUse()) );
+                "LayerAttrIndexUse",
+                CPLSPrintf("%d", poLayer->GetAttrIndexUse()) );
             return poRet;
         }
-        else
-            return NULL;
+
+        return NULL;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Special case GetLayerSpatialIndexState (only for debugging purposes) */
 /* -------------------------------------------------------------------- */
-    if (EQUALN(pszSQLCommand, "GetLayerSpatialIndexState ", strlen("GetLayerSpatialIndexState ")))
+    if (STARTS_WITH_CI(pszSQLCommand, "GetLayerSpatialIndexState "))
     {
-        OGROpenFileGDBLayer* poLayer = (OGROpenFileGDBLayer*)
-            GetLayerByName(pszSQLCommand + strlen("GetLayerSpatialIndexState "));
+        OGROpenFileGDBLayer* poLayer = reinterpret_cast<OGROpenFileGDBLayer*>(
+            GetLayerByName(pszSQLCommand +
+                           strlen("GetLayerSpatialIndexState ")) );
         if (poLayer)
         {
             OGRLayer* poRet = new OGROpenFileGDBSingleFeatureLayer(
-                "LayerSpatialIndexState", CPLSPrintf("%d", poLayer->GetSpatialIndexState()) );
+                "LayerSpatialIndexState",
+                CPLSPrintf("%d", poLayer->GetSpatialIndexState()) );
             return poRet;
         }
-        else
-            return NULL;
+
+        return NULL;
     }
 
 /* -------------------------------------------------------------------- */
@@ -907,21 +919,23 @@ OGRLayer* OGROpenFileGDBDataSource::ExecuteSQL( const char *pszSQLCommand,
     {
         OGRLayer* poRet = new OGROpenFileGDBSingleFeatureLayer(
             "GetLastSQLUsedOptimizedImplementation",
-                    CPLSPrintf("%d", bLastSQLUsedOptimizedImplementation) );
+            CPLSPrintf(
+                "%d", static_cast<int>(bLastSQLUsedOptimizedImplementation))) ;
         return poRet;
     }
 
-    bLastSQLUsedOptimizedImplementation = FALSE;
+    bLastSQLUsedOptimizedImplementation = false;
 
 /* -------------------------------------------------------------------- */
 /*      Special cases for SQL optimizations                             */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszSQLCommand, "SELECT ", strlen("SELECT ")) &&
-        (pszDialect == NULL || EQUAL(pszDialect, "") || EQUAL(pszDialect, "OGRSQL")) &&
-        CSLTestBoolean(CPLGetConfigOption("OPENFILEGDB_USE_INDEX", "YES")) )
+    if( STARTS_WITH_CI(pszSQLCommand, "SELECT ") &&
+        (pszDialect == NULL || EQUAL(pszDialect, "") ||
+         EQUAL(pszDialect, "OGRSQL")) &&
+        CPLTestBool(CPLGetConfigOption("OPENFILEGDB_USE_INDEX", "YES")) )
     {
         swq_select oSelect;
-        if( oSelect.preparse(pszSQLCommand) != OGRERR_NONE )
+        if( oSelect.preparse(pszSQLCommand) != CE_None )
             return NULL;
 
 /* -------------------------------------------------------------------- */
@@ -931,8 +945,9 @@ OGRLayer* OGROpenFileGDBDataSource::ExecuteSQL( const char *pszSQLCommand,
             oSelect.table_count == 1 && oSelect.order_specs == 0 &&
             oSelect.query_mode != SWQM_DISTINCT_LIST )
         {
-            OGROpenFileGDBLayer* poLayer = 
-                (OGROpenFileGDBLayer*)GetLayerByName( oSelect.table_defs[0].table_name);
+            OGROpenFileGDBLayer* poLayer =
+                reinterpret_cast<OGROpenFileGDBLayer *>(
+                    GetLayerByName( oSelect.table_defs[0].table_name));
             if( poLayer )
             {
                 OGRMemLayer* poMemLayer = NULL;
@@ -964,8 +979,6 @@ OGRLayer* OGROpenFileGDBDataSource::ExecuteSQL( const char *pszSQLCommand,
                         break;
 
                     int eOutOGRType = -1;
-                    int nCount = 0;
-                    double dfSum = 0.0;
                     const OGRField* psField = NULL;
                     OGRField sField;
                     if( col_func == SWQCF_MIN || col_func == SWQCF_MAX )
@@ -977,8 +990,13 @@ OGRLayer* OGROpenFileGDBDataSource::ExecuteSQL( const char *pszSQLCommand,
                     }
                     else
                     {
-                        double dfMin = 0.0, dfMax = 0.0;
-                        if( !poLayer->GetMinMaxSumCount(poFieldDefn, dfMin, dfMax,
+                        double dfMin = 0.0;
+                        double dfMax = 0.0;
+                        int nCount = 0;
+                        double dfSum = 0.0;
+
+                        if( !poLayer->GetMinMaxSumCount(poFieldDefn,
+                                                        dfMin, dfMax,
                                                         dfSum, nCount) )
                             break;
                         psField = &sField;
@@ -1019,7 +1037,7 @@ OGRLayer* OGROpenFileGDBDataSource::ExecuteSQL( const char *pszSQLCommand,
                     {
                         poMemLayer = new OGRMemLayer("SELECT", NULL, wkbNone);
                         OGRFeature* poFeature = new OGRFeature(poMemLayer->GetLayerDefn());
-                        poMemLayer->CreateFeature(poFeature);
+                        CPL_IGNORE_RET_VAL(poMemLayer->CreateFeature(poFeature));
                         delete poFeature;
                     }
 
@@ -1037,7 +1055,7 @@ OGRLayer* OGROpenFileGDBDataSource::ExecuteSQL( const char *pszSQLCommand,
                     {
                         OGRFeature* poFeature = poMemLayer->GetFeature(0);
                         poFeature->SetField(oFieldDefn.GetNameRef(), (OGRField*) psField);
-                        poMemLayer->SetFeature(poFeature);
+                        CPL_IGNORE_RET_VAL(poMemLayer->SetFeature(poFeature));
                         delete poFeature;
                     }
                 }
@@ -1049,7 +1067,7 @@ OGRLayer* OGROpenFileGDBDataSource::ExecuteSQL( const char *pszSQLCommand,
                 {
                     CPLDebug("OpenFileGDB",
                         "Using optimized MIN/MAX/SUM/AVG/COUNT implementation");
-                    bLastSQLUsedOptimizedImplementation = TRUE;
+                    bLastSQLUsedOptimizedImplementation = true;
                     return poMemLayer;
                 }
             }
@@ -1062,8 +1080,9 @@ OGRLayer* OGROpenFileGDBDataSource::ExecuteSQL( const char *pszSQLCommand,
             oSelect.table_count == 1 && oSelect.order_specs == 1 &&
             oSelect.query_mode != SWQM_DISTINCT_LIST )
         {
-            OGROpenFileGDBLayer* poLayer = 
-                (OGROpenFileGDBLayer*)GetLayerByName( oSelect.table_defs[0].table_name);
+            OGROpenFileGDBLayer* poLayer =
+                reinterpret_cast<OGROpenFileGDBLayer *>(
+                    GetLayerByName( oSelect.table_defs[0].table_name) );
             if( poLayer != NULL &&
                 poLayer->HasIndexForField(oSelect.order_defs[0].field_name) )
             {
@@ -1135,7 +1154,7 @@ OGRLayer* OGROpenFileGDBDataSource::ExecuteSQL( const char *pszSQLCommand,
                     if( poIter != NULL )
                     {
                         CPLDebug("OpenFileGDB", "Using OGROpenFileGDBSimpleSQLLayer");
-                        bLastSQLUsedOptimizedImplementation = TRUE;
+                        bLastSQLUsedOptimizedImplementation = true;
                         return new OGROpenFileGDBSimpleSQLLayer(poLayer,
                                                                 poIter,
                                                                 oSelect.result_columns,
diff --git a/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdbdriver.cpp b/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdbdriver.cpp
index ea4a23c..2fea181 100644
--- a/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdbdriver.cpp
+++ b/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdbdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogropenfilegdbdriver.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogropenfilegdbdriver.cpp 33031 2016-01-17 19:21:44Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements Open FileGDB OGR driver.
@@ -31,7 +31,9 @@
 
 CPL_CVSID("$Id");
 
-// g++ -O2 -Wall -Wextra -g -shared -fPIC ogr/ogrsf_frmts/openfilegdb/*.cpp -o ogr_OpenFileGDB.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/mem -Iogr/ogrsf_frmts/openfilegdb -L. -lgdal
+// g++ -O2 -Wall -Wextra -g -shared -fPIC ogr/ogrsf_frmts/openfilegdb/*.cpp
+// -o ogr_OpenFileGDB.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts
+// -Iogr/ogrsf_frmts/mem -Iogr/ogrsf_frmts/openfilegdb -L. -lgdal
 
 extern "C" void RegisterOGROpenFileGDB();
 
@@ -43,9 +45,10 @@ extern "C" void RegisterOGROpenFileGDB();
 /*                         OGROpenFileGDBDriverIdentify()               */
 /************************************************************************/
 
-static int OGROpenFileGDBDriverIdentifyInternal( GDALOpenInfo* poOpenInfo,
-                                         const char*& pszFilename )
+static GDALIdentifyEnum OGROpenFileGDBDriverIdentifyInternal( GDALOpenInfo* poOpenInfo,
+                                                 const char*& pszFilename )
 {
+    // FUSIL is a fuzzer
 #ifdef FOR_FUSIL
     CPLString osOrigFilename(pszFilename);
 #endif
@@ -55,24 +58,25 @@ static int OGROpenFileGDBDriverIdentifyInternal( GDALOpenInfo* poOpenInfo,
     if( ENDS_WITH(pszFilename, nLen, ".gdb") ||
         ENDS_WITH(pszFilename, nLen, ".gdb/") )
     {
-        /* Check that the filename is really a directory, to avoid confusion with */
-        /* Garmin MapSource - gdb format which can be a problem when the */
-        /* driver is loaded as a plugin, and loaded before the GPSBabel driver */
-        /* (http://trac.osgeo.org/osgeo4w/ticket/245) */
-        if( strncmp(pszFilename, "/vsicurl/https://github.com/",
-                    strlen("/vsicurl/https://github.com/")) == 0 ||
+        // Check that the filename is really a directory, to avoid confusion
+        // with Garmin MapSource - gdb format which can be a problem when the
+        // driver is loaded as a plugin, and loaded before the GPSBabel driver
+        // (http://trac.osgeo.org/osgeo4w/ticket/245)
+        if( STARTS_WITH(pszFilename, "/vsicurl/https://github.com/") ||
             !poOpenInfo->bStatOK ||
             !poOpenInfo->bIsDirectory )
         {
-            /* In case we don't manage to list the directory, try to stat one file */
+            // In case we do not manage to list the directory, try to stat one
+            // file.
             VSIStatBufL stat;
-            if( !(strncmp(pszFilename, "/vsicurl/", strlen("/vsicurl/")) == 0 &&
-                  VSIStatL( CPLFormFilename(pszFilename, "a00000001", "gdbtable"), &stat ) == 0) )
+            if( !(STARTS_WITH(pszFilename, "/vsicurl/") &&
+                  VSIStatL( CPLFormFilename(
+                      pszFilename, "a00000001", "gdbtable"), &stat ) == 0) )
             {
-                return FALSE;
+                return GDAL_IDENTIFY_FALSE;
             }
         }
-        return TRUE;
+        return GDAL_IDENTIFY_TRUE;
     }
     /* We also accept zipped GDB */
     else if( ENDS_WITH(pszFilename, nLen, ".gdb.zip") ||
@@ -82,12 +86,12 @@ static int OGROpenFileGDBDriverIdentifyInternal( GDALOpenInfo* poOpenInfo,
               (strstr(pszFilename, "_gdb") != NULL ||
                strstr(pszFilename, "_GDB") != NULL)) )
     {
-        return TRUE;
+        return GDAL_IDENTIFY_TRUE;
     }
     /* We also accept tables themselves */
     else if( ENDS_WITH(pszFilename, nLen, ".gdbtable") )
     {
-        return TRUE;
+        return GDAL_IDENTIFY_TRUE;
     }
 #ifdef FOR_FUSIL
     /* To be able to test fuzzer on any auxiliary files used (indexes, etc.) */
@@ -97,20 +101,32 @@ static int OGROpenFileGDBDriverIdentifyInternal( GDALOpenInfo* poOpenInfo,
         pszFilename = CPLFormFilename(CPLGetPath(pszFilename),
                                       CPLGetBasename(pszFilename),
                                       "gdbtable");
-        return TRUE;
+        return GDAL_IDENTIFY_TRUE;
     }
     else if( strlen(CPLGetBasename(CPLGetBasename(pszFilename))) == 9 &&
              CPLGetBasename(CPLGetBasename(pszFilename))[0] == 'a' )
     {
-        pszFilename = CPLFormFilename(CPLGetPath(pszFilename),
-                                      CPLGetBasename(CPLGetBasename(pszFilename)),
-                                      "gdbtable");
-        return TRUE;
+        pszFilename =
+            CPLFormFilename( CPLGetPath(pszFilename),
+                             CPLGetBasename(CPLGetBasename(pszFilename)),
+                             "gdbtable");
+        return GDAL_IDENTIFY_TRUE;
+    }
+#endif
+
+#ifdef DEBUG
+    /* For AFL, so that .cur_input is detected as the archive filename */
+    else if( EQUAL(CPLGetFilename(pszFilename), ".cur_input") )
+    {
+        // This file may be recognized or not by this driver,
+        // but there were not enough elements to judge.
+        return GDAL_IDENTIFY_UNKNOWN;
     }
 #endif
+
     else
     {
-        return FALSE;
+        return GDAL_IDENTIFY_FALSE;
     }
 }
 
@@ -129,11 +145,12 @@ static GDALDataset* OGROpenFileGDBDriverOpen( GDALOpenInfo* poOpenInfo )
 {
     if( poOpenInfo->eAccess == GA_Update )
         return NULL;
+
     const char* pszFilename = poOpenInfo->pszFilename;
 #ifdef FOR_FUSIL
     CPLString osOrigFilename(pszFilename);
 #endif
-    if( OGROpenFileGDBDriverIdentifyInternal( poOpenInfo, pszFilename ) == FALSE )
+    if( OGROpenFileGDBDriverIdentifyInternal( poOpenInfo, pszFilename ) == GDAL_IDENTIFY_FALSE )
         return NULL;
 
 #ifdef FOR_FUSIL
@@ -149,8 +166,10 @@ static GDALDataset* OGROpenFileGDBDriverOpen( GDALOpenInfo* poOpenInfo )
         {
             if( strcmp(papszFiles[i], CPLGetFilename(osOrigFilename)) != 0 )
             {
-                CPLCopyFile(CPLFormFilename(CPLGetPath(osOrigFilename), papszFiles[i], NULL),
-                            CPLFormFilename(pszSrcDir, papszFiles[i], NULL));
+                CPLCopyFile(
+                    CPLFormFilename(CPLGetPath(osOrigFilename), papszFiles[i],
+                                    NULL),
+                    CPLFormFilename(pszSrcDir, papszFiles[i], NULL) );
             }
         }
         CSLDestroy(papszFiles);
@@ -158,16 +177,28 @@ static GDALDataset* OGROpenFileGDBDriverOpen( GDALOpenInfo* poOpenInfo )
     }
 #endif
 
+#ifdef DEBUG
+    /* For AFL, so that .cur_input is detected as the archive filename */
+    if( poOpenInfo->fpL != NULL &&
+        !STARTS_WITH(poOpenInfo->pszFilename, "/vsitar/") &&
+        EQUAL(CPLGetFilename(poOpenInfo->pszFilename), ".cur_input") )
+    {
+        GDALOpenInfo oOpenInfo(
+            (CPLString("/vsitar/") + poOpenInfo->pszFilename).c_str(),
+            poOpenInfo->nOpenFlags );
+        oOpenInfo.papszOpenOptions = poOpenInfo->papszOpenOptions;
+        return OGROpenFileGDBDriverOpen(&oOpenInfo);
+    }
+#endif
+
     OGROpenFileGDBDataSource* poDS = new OGROpenFileGDBDataSource();
     if( poDS->Open( pszFilename ) )
     {
         return poDS;
     }
-    else
-    {
-        delete poDS;
-        return NULL;
-    }
+
+    delete poDS;
+    return NULL;
 }
 
 /***********************************************************************/
@@ -177,27 +208,23 @@ static GDALDataset* OGROpenFileGDBDriverOpen( GDALOpenInfo* poOpenInfo )
 void RegisterOGROpenFileGDB()
 
 {
-    if (! GDAL_CHECK_VERSION("OGR OpenFileGDB"))
+    if( !GDAL_CHECK_VERSION("OGR OpenFileGDB") )
         return;
-    GDALDriver  *poDriver;
 
-    if( GDALGetDriverByName( "OpenFileGDB" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    if( GDALGetDriverByName( "OpenFileGDB" ) != NULL )
+        return;
 
-        poDriver->SetDescription( "OpenFileGDB" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "ESRI FileGDB" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gdb" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_openfilegdb.html" );
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetDescription( "OpenFileGDB" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "ESRI FileGDB" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gdb" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_openfilegdb.html" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = OGROpenFileGDBDriverOpen;
-        poDriver->pfnIdentify = OGROpenFileGDBDriverIdentify;
+    poDriver->pfnOpen = OGROpenFileGDBDriverOpen;
+    poDriver->pfnIdentify = OGROpenFileGDBDriverIdentify;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdblayer.cpp b/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdblayer.cpp
index a718263..894df42 100644
--- a/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdblayer.cpp
+++ b/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdblayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogropenfilegdblayer.cpp 31070 2015-10-19 14:28:04Z rouault $
+ * $Id: ogropenfilegdblayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements Open FileGDB OGR driver.
@@ -44,9 +44,9 @@ class OGROpenFileGDBGeomFieldDefn: public OGRGeomFieldDefn
         OGROpenFileGDBGeomFieldDefn(OGROpenFileGDBLayer* poLayer,
                                     const char *pszNameIn,
                                     OGRwkbGeometryType eGeomTypeIn) :
-                OGRGeomFieldDefn(pszNameIn, eGeomTypeIn), m_poLayer(poLayer)
-        {
-        };
+            OGRGeomFieldDefn(pszNameIn, eGeomTypeIn),
+            m_poLayer(poLayer)
+        {};
 
         ~OGROpenFileGDBGeomFieldDefn() {}
 
@@ -83,7 +83,8 @@ class OGROpenFileGDBFeatureDefn: public OGRFeatureDefn
         void UnsetLayer()
         {
             if( nGeomFieldCount )
-                ((OGROpenFileGDBGeomFieldDefn*)papoGeomFieldDefn[0])->UnsetLayer();
+                reinterpret_cast<OGROpenFileGDBGeomFieldDefn *>(
+                    papoGeomFieldDefn[0])->UnsetLayer();
             m_poLayer = NULL;
         }
 
@@ -134,7 +135,7 @@ OGROpenFileGDBLayer::OGROpenFileGDBLayer(const char* pszGDBFilename,
                                          const char* pszName,
                                          const std::string& osDefinition,
                                          const std::string& osDocumentation,
-                                         CPL_UNUSED const char* pszGeomName,
+                                         const char* /* pszGeomName */,
                                          OGRwkbGeometryType eGeomType) :
             m_osGDBFilename(pszGDBFilename),
             m_osName(pszName),
@@ -157,6 +158,8 @@ OGROpenFileGDBLayer::OGROpenFileGDBLayer(const char* pszGDBFilename,
             m_pahFilteredFeatures(NULL),
             m_nFilteredFeatureCount(-1)
 {
+    // We cannot initialize m_poFeatureDefn in above list since MSVC doesn't like
+    // this to be used in initialization list.
     m_poFeatureDefn = new OGROpenFileGDBFeatureDefn(this, pszName);
     SetDescription( m_poFeatureDefn->GetName() );
     m_poFeatureDefn->SetGeomType(wkbNone);
@@ -199,6 +202,7 @@ int OGROpenFileGDBLayer::BuildGeometryColumnGDBv10()
     CPLXMLNode* psTree = CPLParseXMLString(m_osDefinition.c_str());
     if( psTree == NULL )
     {
+        m_osDefinition = "";
         return FALSE;
     }
 
@@ -209,6 +213,7 @@ int OGROpenFileGDBLayer::BuildGeometryColumnGDBv10()
         psInfo = CPLSearchXMLNode( psTree, "=DETableInfo" );
     if( psInfo == NULL )
     {
+        m_osDefinition = "";
         CPLDestroyXMLNode(psTree);
         return FALSE;
     }
@@ -216,20 +221,27 @@ int OGROpenFileGDBLayer::BuildGeometryColumnGDBv10()
     /* We cannot trust the XML definition to build the field definitions. */
     /* It sometimes misses a few fields ! */
 
-    int bHasZ = CSLTestBoolean(CPLGetXMLValue( psInfo, "HasZ", "NO" ));
+    const bool bHasZ = CPLTestBool(CPLGetXMLValue( psInfo, "HasZ", "NO" ));
+    const bool bHasM = CPLTestBool(CPLGetXMLValue( psInfo, "HasM", "NO" ));
     const char* pszShapeType = CPLGetXMLValue(psInfo, "ShapeType", NULL);
-    const char* pszShapeFieldName = CPLGetXMLValue(psInfo, "ShapeFieldName", NULL);
+    const char* pszShapeFieldName =
+        CPLGetXMLValue(psInfo, "ShapeFieldName", NULL);
     if( pszShapeType != NULL && pszShapeFieldName != NULL )
     {
         m_eGeomType =
             FileGDBOGRGeometryConverter::GetGeometryTypeFromESRI(pszShapeType);
         if( bHasZ )
             m_eGeomType = wkbSetZ( m_eGeomType );
-
-        const char* pszWKT = CPLGetXMLValue( psInfo, "SpatialReference.WKT", NULL );
-        int nWKID = atoi(CPLGetXMLValue( psInfo, "SpatialReference.WKID", "0" ));
-        /* The concept of LatestWKID is explained in http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#//02r3000000n1000000 */
-        int nLatestWKID = atoi(CPLGetXMLValue( psInfo, "SpatialReference.LatestWKID", "0" ));
+        if( bHasM )
+            m_eGeomType = wkbSetM( m_eGeomType );
+        const char* pszWKT =
+            CPLGetXMLValue( psInfo, "SpatialReference.WKT", NULL );
+        const int nWKID =
+            atoi(CPLGetXMLValue( psInfo, "SpatialReference.WKID", "0" ));
+        // The concept of LatestWKID is explained in
+        // http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#//02r3000000n1000000
+        int nLatestWKID = atoi(
+            CPLGetXMLValue( psInfo, "SpatialReference.LatestWKID", "0" ));
 
         OGROpenFileGDBGeomFieldDefn* poGeomFieldDefn =
             new OGROpenFileGDBGeomFieldDefn(NULL, pszShapeFieldName, m_eGeomType);
@@ -243,10 +255,13 @@ int OGROpenFileGDBLayer::BuildGeometryColumnGDBv10()
             {
                 if( psChild->eType != CXT_Element )
                     continue;
-                if( EQUAL(psChild->pszValue, "GPFieldInfoEx") &&
-                    EQUAL(CPLGetXMLValue(psChild, "Name", ""), pszShapeFieldName) )
+                if( EQUAL( psChild->pszValue, "GPFieldInfoEx" ) &&
+                    EQUAL( CPLGetXMLValue(psChild, "Name", "" ),
+                           pszShapeFieldName ) )
                 {
-                    poGeomFieldDefn->SetNullable( CSLTestBoolean(CPLGetXMLValue( psChild, "IsNullable", "TRUE" )) );
+                    poGeomFieldDefn->SetNullable(
+                        CPLTestBool(CPLGetXMLValue(
+                            psChild, "IsNullable", "TRUE" )) );
                     break;
                 }
             }
@@ -258,7 +273,8 @@ int OGROpenFileGDBLayer::BuildGeometryColumnGDBv10()
             int bSuccess = FALSE;
             poSRS = new OGRSpatialReference();
             CPLPushErrorHandler(CPLQuietErrorHandler);
-            /* Try first with nLatestWKID as there's a higher chance it is a EPSG code and not an ESRI one */
+            // Try first with nLatestWKID as there is a higher chance it is a
+            // EPSG code and not an ESRI one.
             if( nLatestWKID > 0 )
             {
                 if( poSRS->importFromEPSG(nLatestWKID) == OGRERR_NONE )
@@ -267,7 +283,8 @@ int OGROpenFileGDBLayer::BuildGeometryColumnGDBv10()
                 }
                 else
                 {
-                    CPLDebug("OpenFileGDB", "Cannot import SRID %d", nLatestWKID);
+                    CPLDebug( "OpenFileGDB", "Cannot import SRID %d",
+                              nLatestWKID);
                 }
             }
             if( !bSuccess && nWKID > 0 )
@@ -337,10 +354,13 @@ int OGROpenFileGDBLayer::BuildLayerDefinition()
     if( m_iGeomFieldIdx >= 0 )
     {
         FileGDBGeomField* poGDBGeomField =
-            (FileGDBGeomField* )m_poLyrTable->GetField(m_iGeomFieldIdx);
-        m_poGeomConverter = FileGDBOGRGeometryConverter::BuildConverter(poGDBGeomField);
+            reinterpret_cast<FileGDBGeomField *>(
+                m_poLyrTable->GetField(m_iGeomFieldIdx));
+        m_poGeomConverter =
+            FileGDBOGRGeometryConverter::BuildConverter(poGDBGeomField);
 
-        if( CSLTestBoolean(CPLGetConfigOption("OPENFILEGDB_IN_MEMORY_SPI", "YES")) )
+        if( CPLTestBool(
+                CPLGetConfigOption("OPENFILEGDB_IN_MEMORY_SPI", "YES")) )
         {
             CPLRectObj sGlobalBounds;
             sGlobalBounds.minx = poGDBGeomField->GetXMin();
@@ -350,7 +370,8 @@ int OGROpenFileGDBLayer::BuildLayerDefinition()
             m_pQuadTree = CPLQuadTreeCreate(&sGlobalBounds,
                                             NULL);
             CPLQuadTreeSetMaxDepth(m_pQuadTree,
-                CPLQuadTreeGetAdvisedMaxDepth(m_poLyrTable->GetValidRecordCount()));
+                CPLQuadTreeGetAdvisedMaxDepth(
+                    m_poLyrTable->GetValidRecordCount()));
         }
         else
         {
@@ -358,13 +379,16 @@ int OGROpenFileGDBLayer::BuildLayerDefinition()
         }
     }
 
-    if( m_osDefinition.size() == 0 && m_iGeomFieldIdx >= 0 )
+    if( m_iGeomFieldIdx >= 0 &&
+        (m_osDefinition.size() == 0 ||
+         m_poFeatureDefn->OGRFeatureDefn::GetGeomFieldCount() == 0) )
     {
         /* FileGDB v9 case */
-        FileGDBGeomField* poGDBGeomField =
-            (FileGDBGeomField* )m_poLyrTable->GetField(m_iGeomFieldIdx);
+        FileGDBGeomField* poGDBGeomField = reinterpret_cast<FileGDBGeomField *>(
+            m_poLyrTable->GetField(m_iGeomFieldIdx) );
         const char* pszName = poGDBGeomField->GetName().c_str();
-        FileGDBTableGeometryType eGDBGeomType = m_poLyrTable->GetGeometryType();
+        const FileGDBTableGeometryType eGDBGeomType =
+            m_poLyrTable->GetGeometryType();
 
         OGRwkbGeometryType eGeomType = wkbUnknown;
         switch( eGDBGeomType )
@@ -387,6 +411,20 @@ int OGROpenFileGDBLayer::BuildLayerDefinition()
         if( poGDBGeomField->Has3D() )
             m_eGeomType = wkbSetZ(m_eGeomType);
 
+        // Check that the first feature has actually a M value before advertizing
+        // it.
+        if( poGDBGeomField->HasM() && m_poLyrTable->GetAndSelectNextNonEmptyRow(0) >= 0 )
+        {
+            const OGRField* psField = m_poLyrTable->GetFieldValue(m_iGeomFieldIdx);
+            if( psField != NULL )
+            {
+                OGRGeometry* poGeom = m_poGeomConverter->GetAsGeometry(psField);
+                if( poGeom != NULL && poGeom->IsMeasured() )
+                    m_eGeomType = wkbSetM(m_eGeomType);
+                delete poGeom;
+            }
+        }
+
         OGROpenFileGDBGeomFieldDefn* poGeomFieldDefn;
 
         poGeomFieldDefn =
@@ -396,7 +434,7 @@ int OGROpenFileGDBLayer::BuildLayerDefinition()
         m_poFeatureDefn->AddGeomFieldDefn(poGeomFieldDefn, FALSE);
 
         OGRSpatialReference* poSRS = NULL;
-        if( poGDBGeomField->GetWKT().size() && 
+        if( poGDBGeomField->GetWKT().size() &&
             poGDBGeomField->GetWKT()[0] != '{' )
         {
             poSRS = new OGRSpatialReference( poGDBGeomField->GetWKT().c_str() );
@@ -480,9 +518,9 @@ int OGROpenFileGDBLayer::BuildLayerDefinition()
         }
         OGRFieldDefn oFieldDefn(poGDBField->GetName().c_str(), eType);
         oFieldDefn.SetSubType(eSubType);
-        /* On creation in the FileGDB driver (GDBFieldTypeToWidthPrecision) if string width is 0, we pick up */
-        /* 65535 by default to mean unlimited string length, but we don't want */
-        /* to advertize such a big number */
+        // On creation in the FileGDB driver (GDBFieldTypeToWidthPrecision) if
+        // string width is 0, we pick up 65535 by default to mean unlimited
+        // string length, but we do not want to advertize such a big number.
         if( eType == OFTString && nWidth < 65535 )
             oFieldDefn.SetWidth(nWidth);
         oFieldDefn.SetNullable(poGDBField->IsNullable());
@@ -501,22 +539,24 @@ int OGROpenFileGDBLayer::BuildLayerDefinition()
             }
             else if( eType == OFTInteger || eType == OFTReal )
             {
-                /* GDBs and the FileGDB SDK aren't always reliable for numeric values */
-                /* It often occurs that the XML definition in a00000004.gdbtable doesn't */
-                /* match the default values (in binary) found in the field definition */
-                /* section of the .gdbtable of the layers themselves */
-                /* So check consistency */
+                // GDBs and the FileGDB SDK are not always reliable for
+                // numeric values It often occurs that the XML definition in
+                // a00000004.gdbtable does not match the default values (in
+                // binary) found in the field definition section of the
+                // .gdbtable of the layers themselves So check consistency.
                 if( m_osDefinition.size() && psTree == NULL )
                 {
                     psTree = CPLParseXMLString(m_osDefinition.c_str());
                     if( psTree != NULL )
                     {
                         CPLStripXMLNamespace( psTree, NULL, TRUE );
-                        CPLXMLNode* psInfo = CPLSearchXMLNode( psTree, "=DEFeatureClassInfo" );
+                        CPLXMLNode* psInfo =
+                            CPLSearchXMLNode( psTree, "=DEFeatureClassInfo" );
                         if( psInfo == NULL )
                             psInfo = CPLSearchXMLNode( psTree, "=DETableInfo" );
                         if( psInfo != NULL )
-                            psGPFieldInfoExs = CPLGetXMLNode(psInfo, "GPFieldInfoExs");
+                            psGPFieldInfoExs =
+                                CPLGetXMLNode(psInfo, "GPFieldInfoExs");
                     }
                 }
                 const char* pszDefaultValue = NULL;
@@ -528,14 +568,21 @@ int OGROpenFileGDBLayer::BuildLayerDefinition()
                     {
                         if( psChild->eType != CXT_Element )
                             continue;
-                        if( EQUAL(psChild->pszValue, "GPFieldInfoEx") &&
-                            EQUAL(CPLGetXMLValue(psChild, "Name", ""), poGDBField->GetName().c_str()) )
+                        if( EQUAL( psChild->pszValue, "GPFieldInfoEx") &&
+                            EQUAL( CPLGetXMLValue(psChild, "Name", ""),
+                                   poGDBField->GetName().c_str()) )
                         {
-                            /* From ArcGIS this is called DefaultValueNumeric for integer and real */
-                            /* From FileGDB API this is called DefaultValue xsi:type=xs:int for integer and DefaultValueNumeric for real ... */
-                            pszDefaultValue = CPLGetXMLValue( psChild, "DefaultValueNumeric", NULL );
+                            // From ArcGIS this is called DefaultValueNumeric
+                            // for integer and real From FileGDB API this is
+                            // called DefaultValue xsi:type=xs:int for integer
+                            // and DefaultValueNumeric for real ...
+                            pszDefaultValue =
+                                CPLGetXMLValue( psChild, "DefaultValueNumeric",
+                                                NULL );
                             if( pszDefaultValue == NULL )
-                                pszDefaultValue = CPLGetXMLValue( psChild, "DefaultValue", NULL );
+                                pszDefaultValue =
+                                    CPLGetXMLValue( psChild, "DefaultValue",
+                                                    NULL );
                             break;
                         }
                     }
@@ -546,38 +593,45 @@ int OGROpenFileGDBLayer::BuildLayerDefinition()
                     {
                         if ( atoi(pszDefaultValue) != psDefault->Integer)
                         {
-                            CPLDebug("OpenFileGDB", "For field %s, XML definition mentions %s "
-                                     "as default value whereas .gdbtable header mentions %d. Using %s",
-                                     poGDBField->GetName().c_str(),
-                                     pszDefaultValue,
-                                     psDefault->Integer,
-                                     pszDefaultValue);
+                            CPLDebug(
+                                "OpenFileGDB",
+                                "For field %s, XML definition mentions %s "
+                                "as default value whereas .gdbtable header "
+                                "mentions %d. Using %s",
+                                poGDBField->GetName().c_str(),
+                                pszDefaultValue,
+                                psDefault->Integer,
+                                pszDefaultValue );
                         }
                         oFieldDefn.SetDefault(pszDefaultValue);
                     }
                     else if( eType == OFTReal )
                     {
-                        if( fabs(CPLAtof(pszDefaultValue) -  psDefault->Real) > 1e-15 )
+                        if( fabs(CPLAtof(pszDefaultValue) - psDefault->Real) >
+                            1e-15 )
                         {
-                            CPLDebug("OpenFileGDB", "For field %s, XML definition mentions %s "
-                                     "as default value whereas .gdbtable header mentions %.18g. Using %s",
-                                     poGDBField->GetName().c_str(),
-                                     pszDefaultValue,
-                                     psDefault->Real,
-                                     pszDefaultValue);
+                            CPLDebug(
+                                "OpenFileGDB", "For field %s, XML definition "
+                                "mentions %s as default value whereas "
+                                ".gdbtable header mentions %.18g. Using %s",
+                                poGDBField->GetName().c_str(),
+                                pszDefaultValue,
+                                psDefault->Real,
+                                pszDefaultValue );
                         }
                         oFieldDefn.SetDefault(pszDefaultValue);
                     }
                 }
             }
             else if( eType == OFTDateTime )
-                oFieldDefn.SetDefault(CPLSPrintf("'%04d/%02d/%02d %02d:%02d:%02d'",
-                                                 psDefault->Date.Year,
-                                                 psDefault->Date.Month,
-                                                 psDefault->Date.Day,
-                                                 psDefault->Date.Hour,
-                                                 psDefault->Date.Minute,
-                                                 (int)psDefault->Date.Second));
+                oFieldDefn.SetDefault(
+                    CPLSPrintf( "'%04d/%02d/%02d %02d:%02d:%02d'",
+                                psDefault->Date.Year,
+                                psDefault->Date.Month,
+                                psDefault->Date.Day,
+                                psDefault->Date.Hour,
+                                psDefault->Date.Minute,
+                                static_cast<int>(psDefault->Date.Second) ));
         }
         m_poFeatureDefn->AddFieldDefn(&oFieldDefn);
     }
@@ -729,9 +783,10 @@ static int CompValues(OGRFieldDefn* poFieldDefn,
                 n2 = (int) poValue2->int_value;
             if( n1 < n2 )
                 return -1;
+
             if( n1 == n2 )
                 return 0;
-            else 
+            else
                 return 1;
             break;
         }
@@ -786,14 +841,14 @@ int OGROpenFileGDBIsComparisonOp(int op)
 /*                        AreExprExclusive()                           */
 /***********************************************************************/
 
-static const struct 
+static const struct
 {
     swq_op op1;
     swq_op op2;
     int    expected_comp_1;
     int    expected_comp_2;
 }
-asPairsOfComparisons[] = 
+asPairsOfComparisons[] =
 {
     { SWQ_EQ, SWQ_EQ, -1, 1 },
     { SWQ_LT, SWQ_GT, -1, 0 },
@@ -815,8 +870,9 @@ static int AreExprExclusive(OGRFeatureDefn* poFeatureDefn,
     if( poNode2->eNodeType != SNT_OPERATION )
         return FALSE;
 
-    const size_t nParis = sizeof(asPairsOfComparisons) / sizeof(asPairsOfComparisons[0]);
-    for(size_t i = 0; i < nParis; i++ )
+    const size_t nPairs = sizeof(asPairsOfComparisons) /
+        sizeof(asPairsOfComparisons[0]);
+    for(size_t i = 0; i < nPairs; i++ )
     {
         if( poNode1->nOperation == asPairsOfComparisons[i].op1 &&
             poNode2->nOperation == asPairsOfComparisons[i].op2 &&
@@ -834,10 +890,10 @@ static int AreExprExclusive(OGRFeatureDefn* poFeatureDefn,
                 poColumn1->field_index == poColumn2->field_index &&
                 poColumn1->field_index < poFeatureDefn->GetFieldCount() )
             {
-                OGRFieldDefn *poFieldDefn;
-                poFieldDefn = poFeatureDefn->GetFieldDefn(poColumn1->field_index);
+                OGRFieldDefn *poFieldDefn =
+                    poFeatureDefn->GetFieldDefn(poColumn1->field_index);
 
-                int nComp = CompValues(poFieldDefn, poValue1, poValue2);
+                const int nComp = CompValues(poFieldDefn, poValue1, poValue2);
                 return nComp == asPairsOfComparisons[i].expected_comp_1 ||
                        nComp == asPairsOfComparisons[i].expected_comp_2;
             }
@@ -978,14 +1034,17 @@ FileGDBIterator* OGROpenFileGDBLayer::BuildIteratorFromExprNode(swq_expr_node* p
     if( poNode->eNodeType == SNT_OPERATION &&
         poNode->nOperation == SWQ_AND && poNode->nSubExprCount == 2 )
     {
-        /* Even if there's only one branch of the 2 that results to an iterator, */
-        /* it is useful. Of course, the iterator will not be sufficient to evaluate */
-        /* the filter, but it will be a super-set of the features */
-        FileGDBIterator* poIter1 = BuildIteratorFromExprNode(poNode->papoSubExpr[0]);
+        // Even if there is only one branch of the 2 that results to an
+        // iterator, it is useful. Of course, the iterator will not be
+        // sufficient to evaluatethe filter, but it will be a super-set of the
+        // features
+        FileGDBIterator* poIter1 =
+            BuildIteratorFromExprNode(poNode->papoSubExpr[0]);
 
         /* In case the first branch didn't result to an iterator, temporarily */
         /* restore the flag */
-        int bSaveIteratorSufficientToEvaluateFilter = m_bIteratorSufficientToEvaluateFilter;
+        const bool bSaveIteratorSufficientToEvaluateFilter =
+            CPL_TO_BOOL(m_bIteratorSufficientToEvaluateFilter);
         m_bIteratorSufficientToEvaluateFilter = -1;
         FileGDBIterator* poIter2 = BuildIteratorFromExprNode(poNode->papoSubExpr[1]);
         m_bIteratorSufficientToEvaluateFilter = bSaveIteratorSufficientToEvaluateFilter;
@@ -1040,7 +1099,8 @@ FileGDBIterator* OGROpenFileGDBLayer::BuildIteratorFromExprNode(swq_expr_node* p
 
                 if( FillTargetValueFromSrcExpr(poFieldDefn, &sValue, poValue) )
                 {
-                    FileGDBSQLOp eOp;
+                    FileGDBSQLOp eOp = FGSO_EQ;
+                    CPL_IGNORE_RET_VAL(eOp);
                     if( poColumn == poNode->papoSubExpr[0] )
                     {
                         switch( poNode->nOperation )
@@ -1051,7 +1111,7 @@ FileGDBIterator* OGROpenFileGDBLayer::BuildIteratorFromExprNode(swq_expr_node* p
                             case SWQ_EQ: eOp = FGSO_EQ; break;
                             case SWQ_GE: eOp = FGSO_GE; break;
                             case SWQ_GT: eOp = FGSO_GT; break;
-                            default: eOp = FGSO_EQ; CPLAssert(FALSE); break;
+                            default: CPLAssert(FALSE); break;
                         }
                     }
                     else
@@ -1066,7 +1126,7 @@ FileGDBIterator* OGROpenFileGDBLayer::BuildIteratorFromExprNode(swq_expr_node* p
                             case SWQ_EQ: eOp = FGSO_EQ; break;
                             case SWQ_GE: eOp = FGSO_LE; break;
                             case SWQ_GT: eOp = FGSO_LT; break;
-                            default: eOp = FGSO_EQ; CPLAssert(FALSE); break;
+                            default: CPLAssert(FALSE); break;
                         }
                     }
 
@@ -1090,8 +1150,8 @@ FileGDBIterator* OGROpenFileGDBLayer::BuildIteratorFromExprNode(swq_expr_node* p
         if( poColumn->eNodeType == SNT_COLUMN &&
             poColumn->field_index < GetLayerDefn()->GetFieldCount() )
         {
-            OGRFieldDefn *poFieldDefn;
-            poFieldDefn = GetLayerDefn()->GetFieldDefn(poColumn->field_index);
+            OGRFieldDefn *poFieldDefn =
+                GetLayerDefn()->GetFieldDefn(poColumn->field_index);
 
             int nTableColIdx = m_poLyrTable->GetFieldIdx(poFieldDefn->GetNameRef());
             if( nTableColIdx >= 0 && m_poLyrTable->GetField(nTableColIdx)->HasIndex() )
@@ -1117,8 +1177,8 @@ FileGDBIterator* OGROpenFileGDBLayer::BuildIteratorFromExprNode(swq_expr_node* p
         if( poColumn->eNodeType == SNT_COLUMN &&
             poColumn->field_index < GetLayerDefn()->GetFieldCount() )
         {
-            OGRFieldDefn *poFieldDefn;
-            poFieldDefn = GetLayerDefn()->GetFieldDefn(poColumn->field_index);
+            OGRFieldDefn *poFieldDefn =
+                GetLayerDefn()->GetFieldDefn(poColumn->field_index);
 
             int nTableColIdx = m_poLyrTable->GetFieldIdx(poFieldDefn->GetNameRef());
             if( nTableColIdx >= 0 && m_poLyrTable->GetField(nTableColIdx)->HasIndex() )
@@ -1138,22 +1198,22 @@ FileGDBIterator* OGROpenFileGDBLayer::BuildIteratorFromExprNode(swq_expr_node* p
         if( poColumn->eNodeType == SNT_COLUMN &&
             poColumn->field_index < GetLayerDefn()->GetFieldCount() )
         {
-            int bAllConstants = TRUE;
-            int i;
-            for(i=1;i<poNode->nSubExprCount;i++)
+            bool bAllConstants = true;
+            for( int i=1; i<poNode->nSubExprCount; i++ )
             {
                 if( poNode->papoSubExpr[i]->eNodeType != SNT_CONSTANT )
-                    bAllConstants = FALSE;
+                    bAllConstants = false;
             }
-            OGRFieldDefn *poFieldDefn;
-            poFieldDefn = GetLayerDefn()->GetFieldDefn(poColumn->field_index);
+            OGRFieldDefn *poFieldDefn =
+                GetLayerDefn()->GetFieldDefn(poColumn->field_index);
 
-            int nTableColIdx = m_poLyrTable->GetFieldIdx(poFieldDefn->GetNameRef());
+            int nTableColIdx =
+                m_poLyrTable->GetFieldIdx(poFieldDefn->GetNameRef());
             if( bAllConstants && nTableColIdx >= 0 &&
                 m_poLyrTable->GetField(nTableColIdx)->HasIndex() )
             {
                 FileGDBIterator* poRet = NULL;
-                for(i=1;i<poNode->nSubExprCount;i++)
+                for( int i=1; i<poNode->nSubExprCount; i++ )
                 {
                     OGRField sValue;
                     if( !FillTargetValueFromSrcExpr(poFieldDefn, &sValue,
@@ -1225,7 +1285,7 @@ OGRErr OGROpenFileGDBLayer::SetAttributeFilter( const char* pszFilter )
 
     OGRErr eErr = OGRLayer::SetAttributeFilter(pszFilter);
     if( eErr != OGRERR_NONE ||
-        !CSLTestBoolean(CPLGetConfigOption("OPENFILEGDB_USE_INDEX", "YES")) )
+        !CPLTestBool(CPLGetConfigOption("OPENFILEGDB_USE_INDEX", "YES")) )
         return eErr;
 
     if( m_poAttrQuery != NULL && m_nFilteredFeatureCount < 0 )
@@ -1329,7 +1389,7 @@ OGRFeature* OGROpenFileGDBLayer::GetCurrentFeature()
 
     if( poFeature == NULL )
         poFeature = new OGRFeature(m_poFeatureDefn);
-    
+
     if( m_poLyrTable->HasDeletedFeaturesListed() )
     {
         poFeature->SetField(poFeature->GetFieldCount() - 1,
@@ -1349,13 +1409,13 @@ OGRFeature* OGROpenFileGDBLayer::GetNextFeature()
     if( !BuildLayerDefinition() || m_bEOF )
         return NULL;
 
-    while( TRUE )
+    while( true )
     {
         OGRFeature *poFeature = NULL;
 
         if( m_nFilteredFeatureCount >= 0 )
         {
-            while( TRUE )
+            while( true )
             {
                 if( m_iCurFeat >= m_nFilteredFeatureCount )
                 {
@@ -1377,7 +1437,7 @@ OGRFeature* OGROpenFileGDBLayer::GetNextFeature()
         }
         else if( m_poIterator != NULL )
         {
-            while( TRUE )
+            while( true )
             {
                 int iRow = m_poIterator->GetNextRowSortedByFID();
                 if( iRow < 0 )
@@ -1397,7 +1457,7 @@ OGRFeature* OGROpenFileGDBLayer::GetNextFeature()
         }
         else
         {
-            while( TRUE )
+            while( true )
             {
                 if( m_iCurFeat == m_poLyrTable->GetTotalRecordCount() )
                 {
@@ -1506,25 +1566,23 @@ OGRErr OGROpenFileGDBLayer::SetNextByIndex( GIntBig nIndex )
 /*                           GetExtent()                               */
 /***********************************************************************/
 
-OGRErr OGROpenFileGDBLayer::GetExtent( OGREnvelope *psExtent, int bForce )
+OGRErr OGROpenFileGDBLayer::GetExtent( OGREnvelope *psExtent, int /* bForce */)
 {
-    (void)bForce;
-
     if( !BuildLayerDefinition() )
         return OGRERR_FAILURE;
 
     if( m_iGeomFieldIdx >= 0 && m_poLyrTable->GetValidRecordCount() > 0 )
     {
-        FileGDBGeomField* poGDBGeomField =
-            (FileGDBGeomField* )m_poLyrTable->GetField(m_iGeomFieldIdx);
+        FileGDBGeomField* poGDBGeomField = reinterpret_cast<FileGDBGeomField *>(
+            m_poLyrTable->GetField(m_iGeomFieldIdx));
         psExtent->MinX = poGDBGeomField->GetXMin();
         psExtent->MinY = poGDBGeomField->GetYMin();
         psExtent->MaxX = poGDBGeomField->GetXMax();
         psExtent->MaxY = poGDBGeomField->GetYMax();
         return OGRERR_NONE;
     }
-    else
-        return OGRERR_FAILURE;
+
+    return OGRERR_FAILURE;
 }
 
 /***********************************************************************/
@@ -1553,7 +1611,7 @@ GIntBig OGROpenFileGDBLayer::GetFeatureCount( int bForce )
         int nCount = 0;
         if( m_eSpatialIndexState == SPI_IN_BUILDING && m_iCurFeat != 0 )
             m_eSpatialIndexState = SPI_INVALID;
-        
+
         int nFilteredFeatureCountAlloc = 0;
         if( m_eSpatialIndexState == SPI_IN_BUILDING )
         {
@@ -1601,9 +1659,13 @@ GIntBig OGROpenFileGDBLayer::GetFeatureCount( int bForce )
                         {
                             if( nCount == nFilteredFeatureCountAlloc )
                             {
-                                nFilteredFeatureCountAlloc = 4 * nFilteredFeatureCountAlloc / 3 + 1024;
-                                m_pahFilteredFeatures = (void**)CPLRealloc(
-                                    m_pahFilteredFeatures, sizeof(void*) * nFilteredFeatureCountAlloc);
+                                nFilteredFeatureCountAlloc =
+                                  4 * nFilteredFeatureCountAlloc / 3 + 1024;
+                                m_pahFilteredFeatures = static_cast<void**>(
+                                    CPLRealloc(
+                                        m_pahFilteredFeatures,
+                                        sizeof(void*) *
+                                        nFilteredFeatureCountAlloc));
                             }
                             m_pahFilteredFeatures[nCount] = (void*)(size_t)i;
                         }
@@ -1679,7 +1741,7 @@ int OGROpenFileGDBLayer::HasIndexForField(const char* pszFieldName)
 {
     if( !BuildLayerDefinition() )
         return FALSE;
-    
+
     int nTableColIdx = m_poLyrTable->GetFieldIdx(pszFieldName);
     return ( nTableColIdx >= 0 &&
              m_poLyrTable->GetField(nTableColIdx)->HasIndex() );
@@ -1707,26 +1769,24 @@ FileGDBIterator* OGROpenFileGDBLayer::BuildIndex(const char* pszFieldName,
     {
         if( op < 0 )
             return FileGDBIterator::BuildIsNotNull(m_poLyrTable, nTableColIdx, bAscending);
-        else
+
+        OGRField sValue;
+        if( FillTargetValueFromSrcExpr(poFieldDefn, &sValue, poValue) )
         {
-            OGRField sValue;
-            if( FillTargetValueFromSrcExpr(poFieldDefn, &sValue, poValue) )
+            FileGDBSQLOp eOp;
+            switch( op )
             {
-                FileGDBSQLOp eOp;
-                switch( op )
-                {
-                    case SWQ_LE: eOp = FGSO_LE; break;
-                    case SWQ_LT: eOp = FGSO_LT; break;
-                    case SWQ_EQ: eOp = FGSO_EQ; break;
-                    case SWQ_GE: eOp = FGSO_GE; break;
-                    case SWQ_GT: eOp = FGSO_GT; break;
-                    default: return NULL;
-                }
-
-                return FileGDBIterator::Build(
-                                m_poLyrTable, nTableColIdx, bAscending,
-                                eOp, poFieldDefn->GetType(), &sValue);
+                case SWQ_LE: eOp = FGSO_LE; break;
+                case SWQ_LT: eOp = FGSO_LT; break;
+                case SWQ_EQ: eOp = FGSO_EQ; break;
+                case SWQ_GE: eOp = FGSO_GE; break;
+                case SWQ_GT: eOp = FGSO_GT; break;
+                default: return NULL;
             }
+
+            return FileGDBIterator::Build(
+                            m_poLyrTable, nTableColIdx, bAscending,
+                            eOp, poFieldDefn->GetType(), &sValue);
         }
     }
     return NULL;
@@ -1744,12 +1804,12 @@ const OGRField* OGROpenFileGDBLayer::GetMinMaxValue(OGRFieldDefn* poFieldDefn,
     if( !BuildLayerDefinition() )
         return NULL;
 
-    int nTableColIdx = m_poLyrTable->GetFieldIdx(poFieldDefn->GetNameRef());
+    const int nTableColIdx = m_poLyrTable->GetFieldIdx(poFieldDefn->GetNameRef());
     if( nTableColIdx >= 0 && m_poLyrTable->GetField(nTableColIdx)->HasIndex() )
     {
         delete m_poIterMinMax;
         m_poIterMinMax = FileGDBIterator::BuildIsNotNull(
-                                                m_poLyrTable, nTableColIdx, TRUE);
+            m_poLyrTable, nTableColIdx, TRUE);
         if( m_poIterMinMax != NULL )
         {
             const OGRField* poRet = (bIsMin ) ?
@@ -1782,7 +1842,7 @@ int OGROpenFileGDBLayer::GetMinMaxSumCount(OGRFieldDefn* poFieldDefn,
     if( nTableColIdx >= 0 && m_poLyrTable->GetField(nTableColIdx)->HasIndex() )
     {
         FileGDBIterator* poIter = FileGDBIterator::BuildIsNotNull(
-                                                m_poLyrTable, nTableColIdx, TRUE);
+            m_poLyrTable, nTableColIdx, TRUE);
         if( poIter != NULL )
         {
             int nRet = poIter->GetMinMaxSumCount(dfMin, dfMax, dfSum, nCount);
diff --git a/ogr/ogrsf_frmts/osm/drv_osm.html b/ogr/ogrsf_frmts/osm/drv_osm.html
index 3061f30..80cf888 100644
--- a/ogr/ogrsf_frmts/osm/drv_osm.html
+++ b/ogr/ogrsf_frmts/osm/drv_osm.html
@@ -76,16 +76,18 @@ effect of this option will be less efficient. This option consumes addionnal 60
 
 <h3>Interleaved reading</h3>
 
-Due to the nature of OSM files and how the driver works internally, the default reading mode might not work
-correctly, because too many features will accumulate in the layers before being consummed by the user application.
-For large files, applications should set the OGR_INTERLEAVED_READING=YES configuration option to turn on a
-special reading mode where the following reading pattern must be used :
+Due to the nature of OSM files and how the driver works internally,
+the default reading mode might not work correctly, because too many
+features will accumulate in the layers before being consumed by the
+user application.  For large files, applications should set the
+OGR_INTERLEAVED_READING=YES configuration option to turn on a special
+reading mode where the following reading pattern must be used:
 
 <pre>
-    int bHasLayersNonEmpty;
+    bool bHasLayersNonEmpty;
     do
     {
-        bHasLayersNonEmpty = FALSE;
+        bHasLayersNonEmpty = false;
 
         for( int iLayer = 0; iLayer < poDS->GetLayerCount(); iLayer++ )
         {
@@ -94,7 +96,7 @@ special reading mode where the following reading pattern must be used :
             OGRFeature* poFeature;
             while( (poFeature = poLayer->GetNextFeature()) != NULL )
             {
-                bHasLayersNonEmpty = TRUE;
+                bHasLayersNonEmpty = true;
                 OGRFeature::DestroyFeature(poFeature);
             }
         }
@@ -142,7 +144,7 @@ Whether to compress nodes in temporary DB. Defaults to NO.</li>
 of in-memory temporary file. If it exceeds that value, it will go to disk.
 Defaults to 100.</li>
 <li> <b>INTERLEAVED_READING=YES/NO</b>: (GDAL >=2.0) Whether to
-enable interleveaved reading. Defaults to NO.</li>
+enable interleaved reading. Defaults to NO.</li>
 </ul>
 
 <h3>See Also</h3>
diff --git a/ogr/ogrsf_frmts/osm/gpb.h b/ogr/ogrsf_frmts/osm/gpb.h
index 5f9dd91..c9d025c 100644
--- a/ogr/ogrsf_frmts/osm/gpb.h
+++ b/ogr/ogrsf_frmts/osm/gpb.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gpb.h 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: gpb.h 33040 2016-01-19 05:49:25Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _GPB_H_INCLUDED
-#define _GPB_H_INCLUDED
+#ifndef GPB_H_INCLUDED
+#define GPB_H_INCLUDED
 
 #include "cpl_port.h"
 #include "cpl_error.h"
@@ -39,12 +39,12 @@
 
 //#define DEBUG_GPB_ERRORS
 #ifdef DEBUG_GPB_ERRORS
-static void error_occured(int nLine)
+static void error_occurred(int nLine)
 {
-    CPLError(CE_Failure, CPLE_AppDefined, "Parsing error occured at line %d", nLine);
+    CPLError(CE_Failure, CPLE_AppDefined, "Parsing error occurred at line %d", nLine);
 }
 
-#define GOTO_END_ERROR do { error_occured(__LINE__); goto end_error; } while(0)
+#define GOTO_END_ERROR do { error_occurred(__LINE__); goto end_error; } while(0)
 #else
 #define GOTO_END_ERROR goto end_error
 #endif
@@ -80,7 +80,7 @@ static int ReadVarInt32(GByte** ppabyData)
     int nShift = 0;
     GByte* pabyData = *ppabyData;
 
-    while(TRUE)
+    while(true)
     {
         int nByte = *pabyData;
         if (!(nByte & 0x80))
@@ -103,7 +103,7 @@ static int ReadVarInt32(GByte** ppabyData)
 #define READ_VARSINT32(pabyData, pabyDataLimit, nVal)  \
     { \
         nVal = ReadVarInt32(&pabyData); \
-        nVal = ((nVal & 1) == 0) ? (((unsigned int)nVal) >> 1) : -(((unsigned int)nVal) >> 1)-1; \
+        nVal = ((nVal & 1) == 0) ? (int)(((unsigned int)nVal) >> 1) : -(int)(((unsigned int)nVal) >> 1)-1; \
         if (CHECK_OOB && pabyData > pabyDataLimit) GOTO_END_ERROR; \
     }
 
@@ -111,13 +111,15 @@ static int ReadVarInt32(GByte** ppabyData)
 /*                          ReadVarUInt32()                             */
 /************************************************************************/
 
+#ifndef DO_NOT_DEFINE_READ_VARUINT32
+
 static unsigned int ReadVarUInt32(GByte** ppabyData)
 {
     unsigned int nVal = 0;
     int nShift = 0;
     GByte* pabyData = *ppabyData;
 
-    while(TRUE)
+    while(true)
     {
         int nByte = *pabyData;
         if (!(nByte & 0x80))
@@ -143,6 +145,8 @@ static unsigned int ReadVarUInt32(GByte** ppabyData)
         if (CHECK_OOB && nSize > (unsigned int)(pabyDataLimit - pabyData)) GOTO_END_ERROR; \
     }
 
+#endif /* DO_NOT_DEFINE_READ_VARUINT32 */
+
 /************************************************************************/
 /*                           ReadVarInt64()                             */
 /************************************************************************/
@@ -153,7 +157,7 @@ static GIntBig ReadVarInt64(GByte** ppabyData)
     int nShift = 0;
     GByte* pabyData = *ppabyData;
 
-    while(TRUE)
+    while(true)
     {
         int nByte = *pabyData;
         if (!(nByte & 0x80))
@@ -176,24 +180,26 @@ static GIntBig ReadVarInt64(GByte** ppabyData)
 #define READ_VARSINT64(pabyData, pabyDataLimit, nVal)  \
     { \
         nVal = ReadVarInt64(&pabyData); \
-        nVal = ((nVal & 1) == 0) ? (((GUIntBig)nVal) >> 1) : -(((GUIntBig)nVal) >> 1)-1; \
+        nVal = ((nVal & 1) == 0) ? (GIntBig)(((GUIntBig)nVal) >> 1) : -(GIntBig)(((GUIntBig)nVal) >> 1)-1; \
         if (CHECK_OOB && pabyData > pabyDataLimit) GOTO_END_ERROR; \
     }
 
 #define READ_VARSINT64_NOCHECK(pabyData, pabyDataLimit, nVal)  \
     { \
         nVal = ReadVarInt64(&pabyData); \
-        nVal = ((nVal & 1) == 0) ? (((GUIntBig)nVal) >> 1) : -(((GUIntBig)nVal) >> 1)-1; \
+        nVal = ((nVal & 1) == 0) ? (GIntBig)(((GUIntBig)nVal) >> 1) : -(GIntBig)(((GUIntBig)nVal) >> 1)-1; \
     }
 
 /************************************************************************/
 /*                            SkipVarInt()                              */
 /************************************************************************/
 
+#ifndef DO_NOT_DEFINE_SKIP_VARINT
+
 static void SkipVarInt(GByte** ppabyData)
 {
     GByte* pabyData = *ppabyData;
-    while(TRUE)
+    while(true)
     {
         int nByte = *pabyData;
         if (!(nByte & 0x80))
@@ -211,12 +217,14 @@ static void SkipVarInt(GByte** ppabyData)
         if (CHECK_OOB && pabyData > pabyDataLimit) GOTO_END_ERROR; \
     }
 
+#endif /* DO_NOT_DEFINE_SKIP_VARINT */
+
 #define READ_FIELD_KEY(nKey) READ_VARINT32(pabyData, pabyDataLimit, nKey)
 
 #define READ_TEXT(pabyData, pabyDataLimit, pszTxt) \
         unsigned int nDataLength; \
         READ_SIZE(pabyData, pabyDataLimit, nDataLength); \
-        pszTxt = (char*)VSIMalloc(nDataLength + 1); \
+        pszTxt = (char*)VSI_MALLOC_VERBOSE(nDataLength + 1); \
         if( pszTxt == NULL ) GOTO_END_ERROR; \
         memcpy(pszTxt, pabyData, nDataLength); \
         pszTxt[nDataLength] = 0; \
@@ -263,6 +271,8 @@ static void SkipVarInt(GByte** ppabyData)
                 GOTO_END_ERROR; \
         }
 
+#ifndef DO_NOT_DEFINE_SKIP_UNKNOWN_FIELD
+
 static
 int SkipUnknownField(int nKey, GByte* pabyData, GByte* pabyDataLimit, int verbose) CPL_NO_INLINE;
 
@@ -273,7 +283,7 @@ int SkipUnknownField(int nKey, GByte* pabyData, GByte* pabyDataLimit, int verbos
 {
     GByte* pabyDataBefore = pabyData;
     SKIP_UNKNOWN_FIELD_INLINE(pabyData, pabyDataLimit, verbose);
-    return pabyData - pabyDataBefore;
+    return static_cast<int>(pabyData - pabyDataBefore);
 end_error:
     return -1;
 }
@@ -286,4 +296,6 @@ end_error:
         pabyData += _nOffset; \
     }
 
-#endif /* _GPB_H_INCLUDED */
+#endif /* DO_NOT_DEFINE_SKIP_UNKNOWN_FIELD */
+
+#endif /* GPB_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/osm/ogr_osm.h b/ogr/ogrsf_frmts/osm/ogr_osm.h
index ea86a07..9d03d2e 100644
--- a/ogr/ogrsf_frmts/osm/ogr_osm.h
+++ b/ogr/ogrsf_frmts/osm/ogr_osm.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_osm.h 29242 2015-05-24 10:59:41Z rouault $
+ * $Id: ogr_osm.h 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/OpenStreeMap driver.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_OSM_H_INCLUDED
-#define _OGR_OSM_H_INCLUDED
+#ifndef OGR_OSM_H_INCLUDED
+#define OGR_OSM_H_INCLUDED
 
 // replace O(log2(N)) complexity of FindNode() by O(1)
 #define ENABLE_NODE_LOOKUP_BY_HASHING 1
@@ -42,6 +42,7 @@
 
 #include "osm_parser.h"
 
+#define DO_NOT_INCLUDE_SQLITE_CLASSES
 #include "ogr_sqlite.h"
 
 class ConstCharComp
@@ -84,37 +85,37 @@ class OGROSMLayer : public OGRLayer
     OGRSpatialReference *poSRS;
     long                 nFeatureCount;
 
-    std::vector<char*>   apszNames;
+    std::vector<char*>   apszNames; /* Needed to keep a "reference" to the string inserted into oMapFieldNameToIndex */
     std::map<const char*, int, ConstCharComp> oMapFieldNameToIndex;
-    
+
     std::vector<OGROSMComputedAttribute> oComputedAttributes;
 
-    int                  bResetReadingAllowed;
-    
+    bool                 bResetReadingAllowed;
+
     int                  nFeatureArraySize;
     int                  nFeatureArrayMaxSize;
     int                  nFeatureArrayIndex;
     OGRFeature**         papoFeatures;
 
-    int                   bHasOSMId;
+    bool                  bHasOSMId;
     int                   nIndexOSMId;
     int                   nIndexOSMWayId;
-    int                   bHasVersion;
-    int                   bHasTimestamp;
-    int                   bHasUID;
-    int                   bHasUser;
-    int                   bHasChangeset;
-    int                   bHasOtherTags;
+    bool                  bHasVersion;
+    bool                  bHasTimestamp;
+    bool                  bHasUID;
+    bool                  bHasUser;
+    bool                  bHasChangeset;
+    bool                  bHasOtherTags;
     int                   nIndexOtherTags;
-    int                   bHasAllTags;
+    bool                  bHasAllTags;
     int                   nIndexAllTags;
 
-    int                   bHasWarnedTooManyFeatures;
+    bool                  bHasWarnedTooManyFeatures;
 
     char                 *pszAllTags;
-    int                   bHasWarnedAllTagsTruncated;
+    bool                  bHasWarnedAllTagsTruncated;
 
-    int                   bUserInterested;
+    bool                  bUserInterested;
 
     int                  AddToArray(OGRFeature* poFeature, int bCheckFeatureThreshold);
 
@@ -138,16 +139,18 @@ class OGROSMLayer : public OGRLayer
     virtual             ~OGROSMLayer();
 
     virtual OGRFeatureDefn *GetLayerDefn() {return poFeatureDefn;}
-    
+
     virtual void        ResetReading();
     virtual int         TestCapability( const char * );
-                                     
+
     virtual OGRFeature *GetNextFeature();
     virtual GIntBig     GetFeatureCount( int bForce );
-        
+
     virtual OGRErr      SetAttributeFilter( const char* pszAttrQuery );
 
     virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce );
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
     const OGREnvelope*  GetSpatialFilterEnvelope();
 
@@ -160,29 +163,29 @@ class OGROSMLayer : public OGRLayer
     void                AddField(const char* pszName, OGRFieldType eFieldType);
     int                 GetFieldIndex(const char* pszName);
 
-    int                 HasOSMId() const { return bHasOSMId; }
-    void                SetHasOSMId(int bIn) { bHasOSMId = bIn; }
+    bool                HasOSMId() const { return bHasOSMId; }
+    void                SetHasOSMId(bool bIn) { bHasOSMId = bIn; }
 
-    int                 HasVersion() const { return bHasVersion; }
-    void                SetHasVersion(int bIn) { bHasVersion = bIn; }
+    bool                HasVersion() const { return bHasVersion; }
+    void                SetHasVersion(bool bIn) { bHasVersion = bIn; }
 
-    int                 HasTimestamp() const { return bHasTimestamp; }
-    void                SetHasTimestamp(int bIn) { bHasTimestamp = bIn; }
+    bool                HasTimestamp() const { return bHasTimestamp; }
+    void                SetHasTimestamp(bool bIn) { bHasTimestamp = bIn; }
 
-    int                 HasUID() const { return bHasUID; }
-    void                SetHasUID(int bIn) { bHasUID = bIn; }
+    bool                HasUID() const { return bHasUID; }
+    void                SetHasUID(bool bIn) { bHasUID = bIn; }
 
-    int                 HasUser() const { return bHasUser; }
-    void                SetHasUser(int bIn) { bHasUser = bIn; }
+    bool                HasUser() const { return bHasUser; }
+    void                SetHasUser(bool bIn) { bHasUser = bIn; }
 
-    int                 HasChangeset() const { return bHasChangeset; }
-    void                SetHasChangeset(int bIn) { bHasChangeset = bIn; }
+    bool                HasChangeset() const { return bHasChangeset; }
+    void                SetHasChangeset(bool bIn) { bHasChangeset = bIn; }
 
-    void                SetHasOtherTags(int bIn) { bHasOtherTags = bIn; }
-    int                 HasOtherTags() const { return bHasOtherTags; }
+    bool                HasOtherTags() const { return bHasOtherTags; }
+    void                SetHasOtherTags(bool bIn) { bHasOtherTags = bIn; }
 
-    void                SetHasAllTags(int bIn) { bHasAllTags = bIn; }
-    int                 HasAllTags() const { return bHasAllTags; }
+    bool                HasAllTags() const { return bHasAllTags; }
+    void                SetHasAllTags(bool bIn) { bHasAllTags = bIn; }
 
     void                SetFieldsFromTags(OGRFeature* poFeature,
                                           GIntBig nID,
@@ -190,8 +193,8 @@ class OGROSMLayer : public OGRLayer
                                           unsigned int nTags, OSMTag* pasTags,
                                           OSMInfo* psInfo);
 
-    void                SetDeclareInterest(int bIn) { bUserInterested = bIn; }
-    int                 IsUserInterested() const { return bUserInterested; }
+    void                SetDeclareInterest(bool bIn) { bUserInterested = bIn; }
+    bool                IsUserInterested() const { return bUserInterested; }
 
     int                 HasAttributeFilter() const { return m_poAttrQuery != NULL; }
     int                 EvaluateAttributeFilter(OGRFeature* poFeature);
@@ -216,7 +219,7 @@ typedef struct
 {
     char* pszK;
     int nKeyIndex;
-    int nOccurences;
+    int nOccurrences;
     std::vector<char*> asValues;
     std::map<const char*, int, ConstCharComp> anMapV; /* map that is the reverse of asValues */
 } KeyDesc;
@@ -258,8 +261,8 @@ typedef struct
     IndexedKVP*         pasTags; /*  point to a sub-array of OGROSMDataSource.pasAccumulatedTags */
     OSMInfo             sInfo;
     OGRFeature         *poFeature;
-    int                 bIsArea : 1;
-    int                 bAttrFilterAlreadyEvaluated : 1;
+    EMULATED_BOOL       bIsArea : 1;
+    EMULATED_BOOL       bAttrFilterAlreadyEvaluated : 1;
 } WayFeaturePair;
 
 #ifdef ENABLE_NODE_LOOKUP_BY_HASHING
@@ -273,20 +276,21 @@ typedef struct
 class OGROSMDataSource : public OGRDataSource
 {
     friend class OGROSMLayer;
-    
+
     int                 nLayers;
     OGROSMLayer**       papoLayers;
     char*               pszName;
 
     OGREnvelope         sExtent;
-    int                 bExtentValid;
+    bool                bExtentValid;
 
+    // Starts off at -1 to indicate that we do not know.
     int                 bInterleavedReading;
     OGROSMLayer        *poCurrentLayer;
 
     OSMContext         *psParser;
-    int                 bHasParsedFirstChunk;
-    int                 bStopParsing;
+    bool                bHasParsedFirstChunk;
+    bool                bStopParsing;
 
 #ifdef HAVE_SQLITE_VFS
     sqlite3_vfs*        pMyVFS;
@@ -301,13 +305,13 @@ class OGROSMDataSource : public OGRDataSource
     sqlite3_stmt       *hInsertPolygonsStandaloneStmt;
     sqlite3_stmt       *hDeletePolygonsStandaloneStmt;
     sqlite3_stmt       *hSelectPolygonsStandaloneStmt;
-    int                 bHasRowInPolygonsStandalone;
+    bool                bHasRowInPolygonsStandalone;
 
     sqlite3            *hDBForComputedAttributes;
 
     int                 nMaxSizeForInMemoryDBInMB;
-    int                 bInMemoryTmpDB;
-    int                 bMustUnlink;
+    bool                bInMemoryTmpDB;
+    bool                bMustUnlink;
     CPLString           osTmpDBName;
 
     int                 nNodesInTransaction;
@@ -316,36 +320,36 @@ class OGROSMDataSource : public OGRDataSource
 
     LonLat             *pasLonLatCache;
 
-    int                 bReportAllNodes;
-    int                 bReportAllWays;
+    bool                bReportAllNodes;
+    bool                bReportAllWays;
 
-    int                 bFeatureAdded;
+    bool                bFeatureAdded;
 
-    int                 bInTransaction;
+    bool                bInTransaction;
 
-    int                 bIndexPoints;
-    int                 bUsePointsIndex;
-    int                 bIndexWays;
-    int                 bUseWaysIndex;
+    bool                bIndexPoints;
+    bool                bUsePointsIndex;
+    bool                bIndexWays;
+    bool                bUseWaysIndex;
 
-    std::vector<int>      abSavedDeclaredInterest;
-    OGRLayer*             poResultSetLayer;
-    int                   bIndexPointsBackup;
-    int                   bUsePointsIndexBackup;
-    int                   bIndexWaysBackup;
-    int                   bUseWaysIndexBackup;
+    std::vector<bool>   abSavedDeclaredInterest;
+    OGRLayer*           poResultSetLayer;
+    bool                bIndexPointsBackup;
+    bool                bUsePointsIndexBackup;
+    bool                bIndexWaysBackup;
+    bool                bUseWaysIndexBackup;
 
-    int                 bIsFeatureCountEnabled;
+    bool                bIsFeatureCountEnabled;
 
-    int                 bAttributeNameLaundering;
+    bool                bAttributeNameLaundering;
 
     GByte              *pabyWayBuffer;
 
     int                 nWaysProcessed;
     int                 nRelationsProcessed;
 
-    int                 bCustomIndexing;
-    int                 bCompressNodes;
+    bool                bCustomIndexing;
+    bool                bCompressNodes;
 
     unsigned int        nUnsortedReqIds;
     GIntBig            *panUnsortedReqIds;
@@ -354,13 +358,13 @@ class OGROSMDataSource : public OGRDataSource
     GIntBig            *panReqIds;
 
 #ifdef ENABLE_NODE_LOOKUP_BY_HASHING
-    int                 bEnableHashedIndex;
+    bool                bEnableHashedIndex;
     /* values >= 0 are indexes of panReqIds. */
     /*        == -1 for unoccupied */
     /*        < -1 are expressed as -nIndexToCollisonBuckets-2 where nIndexToCollisonBuckets point to psCollisionBuckets */
-    int                *panHashedIndexes; 
+    int                *panHashedIndexes;
     CollisionBucket    *psCollisionBuckets;
-    int                 bHashedIndexValid;
+    bool                bHashedIndexValid;
 #endif
 
     LonLat             *pasLonLatArray;
@@ -377,8 +381,8 @@ class OGROSMDataSource : public OGRDataSource
     std::map<const char*, KeyDesc*, ConstCharComp> aoMapIndexedKeys; /* map that is the reverse of asKeys */
 
     CPLString           osNodesFilename;
-    int                 bInMemoryNodesFile;
-    int                 bMustUnlinkNodesFile;
+    bool                bInMemoryNodesFile;
+    bool                bMustUnlinkNodesFile;
     GIntBig             nNodesFileSize;
     VSILFILE           *fpNodes;
 
@@ -389,7 +393,7 @@ class OGROSMDataSource : public OGRDataSource
     Bucket             *papsBuckets;
     int                 nBuckets;
 
-    int                 bNeedsToSaveWayInfo;
+    bool                bNeedsToSaveWayInfo;
 
     int                 CompressWay (unsigned int nTags, IndexedKVP* pasTags,
                                      int nPoints, LonLat* pasLonLatPairs,
@@ -400,27 +404,27 @@ class OGROSMDataSource : public OGRDataSource
                                        unsigned int* pnTags, OSMTag* pasTags,
                                        OSMInfo* psInfo );
 
-    int                 ParseConf(char** papszOpenOptions);
+    bool                ParseConf(char** papszOpenOptions);
     int                 CreateTempDB();
-    int                 SetDBOptions();
-    int                 SetCacheSize();
-    int                 CreatePreparedStatements();
+    bool                SetDBOptions();
+    bool                SetCacheSize();
+    bool                CreatePreparedStatements();
     void                CloseDB();
 
     int                 IndexPoint(OSMNode* psNode);
     int                 IndexPointSQLite(OSMNode* psNode);
-    int                 FlushCurrentSector();
-    int                 FlushCurrentSectorCompressedCase();
-    int                 FlushCurrentSectorNonCompressedCase();
-    int                 IndexPointCustom(OSMNode* psNode);
+    bool                FlushCurrentSector();
+    bool                FlushCurrentSectorCompressedCase();
+    bool                FlushCurrentSectorNonCompressedCase();
+    bool                IndexPointCustom(OSMNode* psNode);
 
     void                IndexWay(GIntBig nWayID,
                                  unsigned int nTags, IndexedKVP* pasTags,
                                  LonLat* pasLonLatPairs, int nPairs,
                                  OSMInfo* psInfo);
 
-    int                 StartTransactionCacheDB();
-    int                 CommitTransactionCacheDB();
+    bool                StartTransactionCacheDB();
+    bool                CommitTransactionCacheDB();
 
     int                 FindNode(GIntBig nID);
     void                ProcessWaysBatch();
@@ -441,10 +445,11 @@ class OGROSMDataSource : public OGRDataSource
                                           OSMTag* pasTags);
     OGRGeometry*        BuildGeometryCollection(OSMRelation* psRelation, int bMultiLineString);
 
-    int                 TransferToDiskIfNecesserary();
+    bool                TransferToDiskIfNecesserary();
 
-    int                 AllocBucket(int iBucket);
-    int                 AllocMoreBuckets(int nNewBucketIdx, int bAllocBucket = FALSE);
+    bool                AllocBucket(int iBucket);
+    bool                AllocMoreBuckets( int nNewBucketIdx,
+                                          bool bAllocBucket = false );
 
     void                AddComputedAttributes(int iCurLayer,
                                              const std::vector<OGROSMComputedAttribute>& oAttributes);
@@ -468,7 +473,7 @@ class OGROSMDataSource : public OGRDataSource
     int                 Open ( const char* pszFilename, char** papszOpenOptions );
 
     int                 ResetReading();
-    int                 ParseNextChunk(int nIdxLayer);
+    bool                ParseNextChunk(int nIdxLayer);
     OGRErr              GetExtent( OGREnvelope *psExtent );
     int                 IsInterleavedReading();
 
@@ -481,10 +486,9 @@ class OGROSMDataSource : public OGRDataSource
     OGROSMLayer*        GetCurrentLayer() { return poCurrentLayer; }
     void                SetCurrentLayer(OGROSMLayer* poLyr) { poCurrentLayer = poLyr; }
 
-    int                 IsFeatureCountEnabled() const { return bIsFeatureCountEnabled; }
+    bool                IsFeatureCountEnabled() const { return bIsFeatureCountEnabled; }
 
-    int                 DoesAttributeNameLaundering() const { return bAttributeNameLaundering; }
+    bool                DoesAttributeNameLaundering() const { return bAttributeNameLaundering; }
 };
 
-#endif /* ndef _OGR_OSM_H_INCLUDED */
-
+#endif /* ndef OGR_OSM_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/osm/ogrosmdatasource.cpp b/ogr/ogrsf_frmts/osm/ogrosmdatasource.cpp
index 9dbaeb1..50bbd6c 100644
--- a/ogr/ogrsf_frmts/osm/ogrosmdatasource.cpp
+++ b/ogr/ogrsf_frmts/osm/ogrosmdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrosmdatasource.cpp 29242 2015-05-24 10:59:41Z rouault $
+ * $Id: ogrosmdatasource.cpp 33199 2016-01-29 15:48:41Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGROSMDataSource class.
@@ -27,20 +27,25 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_osm.h"
 #include "cpl_conv.h"
+#include "cpl_multiproc.h"
 #include "cpl_time.h"
-#include "ogr_p.h"
 #include "ogr_api.h"
+#include "ogr_osm.h"
+#include "ogr_p.h"
 #include "swq.h"
+
+#define DO_NOT_DEFINE_SKIP_UNKNOWN_FIELD
+#define DO_NOT_DEFINE_READ_VARUINT32
+#define DO_NOT_DEFINE_SKIP_VARINT
 #include "gpb.h"
+
 #include "ogrlayerdecorator.h"
 #include "ogrsqliteexecutesql.h"
-#include "cpl_multiproc.h"
 
 #include <algorithm>
 
-#define LIMIT_IDS_PER_REQUEST 200
+static const int LIMIT_IDS_PER_REQUEST = 200;
 
 #define MAX_NODES_PER_WAY 2000
 
@@ -121,7 +126,7 @@ size_t GetMaxTotalAllocs();
 static void WriteVarInt64(GUIntBig nSVal, GByte** ppabyData);
 static void WriteVarSInt64(GIntBig nSVal, GByte** ppabyData);
 
-CPL_CVSID("$Id: ogrosmdatasource.cpp 29242 2015-05-24 10:59:41Z rouault $");
+CPL_CVSID("$Id: ogrosmdatasource.cpp 33199 2016-01-29 15:48:41Z rouault $");
 
 class DSToBeOpened
 {
@@ -174,99 +179,85 @@ static CPLString GetInterestLayersForDSName(const CPLString& osDSName)
 /*                        OGROSMDataSource()                            */
 /************************************************************************/
 
-OGROSMDataSource::OGROSMDataSource()
-
-{
-    nLayers = 0;
-    papoLayers = NULL;
-    pszName = NULL;
-    bExtentValid = FALSE;
-    bInterleavedReading = -1;
-    poCurrentLayer = NULL;
-    psParser = NULL;
-    bHasParsedFirstChunk = FALSE;
-    bStopParsing = FALSE;
+OGROSMDataSource::OGROSMDataSource() :
+    nLayers(0),
+    papoLayers(NULL),
+    pszName(NULL),
+    bExtentValid(false),
+    bInterleavedReading(-1),
+    poCurrentLayer(NULL),
+    psParser(NULL),
+    bHasParsedFirstChunk(false),
+    bStopParsing(false),
 #ifdef HAVE_SQLITE_VFS
-    pMyVFS = NULL;
+    pMyVFS(NULL),
 #endif
-    hDB = NULL;
-    hInsertNodeStmt = NULL;
-    hInsertWayStmt = NULL;
-    hInsertPolygonsStandaloneStmt = NULL;
-    hDeletePolygonsStandaloneStmt = NULL;
-    hSelectPolygonsStandaloneStmt = NULL;
-    bHasRowInPolygonsStandalone = FALSE;
-
-    hDBForComputedAttributes = NULL;
-
-    nNodesInTransaction = 0;
-    bInTransaction = FALSE;
-    pahSelectNodeStmt = NULL;
-    pahSelectWayStmt = NULL;
-    pasLonLatCache = NULL;
-    bInMemoryTmpDB = FALSE;
-    bMustUnlink = TRUE;
-    nMaxSizeForInMemoryDBInMB = 0;
-    bReportAllNodes = FALSE;
-    bReportAllWays = FALSE;
-    bFeatureAdded = FALSE;
-
-    bIndexPoints = TRUE;
-    bUsePointsIndex = TRUE;
-    bIndexWays = TRUE;
-    bUseWaysIndex = TRUE;
-
-    poResultSetLayer = NULL;
-    bIndexPointsBackup = FALSE;
-    bUsePointsIndexBackup = FALSE;
-    bIndexWaysBackup = FALSE;
-    bUseWaysIndexBackup = FALSE;
-
-    bIsFeatureCountEnabled = FALSE;
-
-    bAttributeNameLaundering = TRUE;
-
-    pabyWayBuffer = NULL;
-
-    nWaysProcessed = 0;
-    nRelationsProcessed = 0;
-
-    bCustomIndexing = TRUE;
-    bCompressNodes = FALSE;
-
-    bInMemoryNodesFile = FALSE;
-    bMustUnlinkNodesFile = TRUE;
-    fpNodes = NULL;
-    nNodesFileSize = 0;
-
-    nPrevNodeId = -INT_MAX;
-    nBucketOld = -1;
-    nOffInBucketReducedOld = -1;
-    pabySector = NULL;
-    papsBuckets = NULL;
-    nBuckets = 0;
-
-    nReqIds = 0;
-    panReqIds = NULL;
+    hDB(NULL),
+    hInsertNodeStmt(NULL),
+    hInsertWayStmt(NULL),
+    hSelectNodeBetweenStmt(NULL),
+    pahSelectNodeStmt(NULL),
+    pahSelectWayStmt(NULL),
+    hInsertPolygonsStandaloneStmt(NULL),
+    hDeletePolygonsStandaloneStmt(NULL),
+    hSelectPolygonsStandaloneStmt(NULL),
+    bHasRowInPolygonsStandalone(false),
+    hDBForComputedAttributes(NULL),
+    nMaxSizeForInMemoryDBInMB(0),
+    bInMemoryTmpDB(false),
+    bMustUnlink(true),
+    nNodesInTransaction(0),
+    pasLonLatCache(NULL),
+    bReportAllNodes(false),
+    bReportAllWays(false),
+    bFeatureAdded(false),
+    bInTransaction(false),
+    bIndexPoints(true),
+    bUsePointsIndex(true),
+    bIndexWays(true),
+    bUseWaysIndex(true),
+    poResultSetLayer(NULL),
+    bIndexPointsBackup(false),
+    bUsePointsIndexBackup(false),
+    bIndexWaysBackup(false),
+    bUseWaysIndexBackup(false),
+    bIsFeatureCountEnabled(false),
+    bAttributeNameLaundering(true),
+    pabyWayBuffer(NULL),
+    nWaysProcessed(0),
+    nRelationsProcessed(0),
+    bCustomIndexing(true),
+    bCompressNodes(false),
+    nUnsortedReqIds(0),
+    panUnsortedReqIds(NULL),
+    nReqIds(0),
+    panReqIds(NULL),
 #ifdef ENABLE_NODE_LOOKUP_BY_HASHING
-    bEnableHashedIndex = TRUE;
-    panHashedIndexes = NULL;
-    psCollisionBuckets = NULL;
-    bHashedIndexValid = FALSE;
+    bEnableHashedIndex(true),
+    panHashedIndexes(NULL),
+    psCollisionBuckets(NULL),
+    bHashedIndexValid(false),
 #endif
-    pasLonLatArray = NULL;
-    nUnsortedReqIds = 0;
-    panUnsortedReqIds = NULL;
-    nWayFeaturePairs = 0;
-    pasWayFeaturePairs = NULL;
-    nAccumulatedTags = 0;
-    pasAccumulatedTags = NULL;
-    nNonRedundantValuesLen = 0;
-    pabyNonRedundantValues = NULL;
-    nNextKeyIndex = 0;
-
-    bNeedsToSaveWayInfo = FALSE;
-}
+    pasLonLatArray(NULL),
+    pasAccumulatedTags(NULL),
+    nAccumulatedTags(0),
+    pabyNonRedundantValues(NULL),
+    nNonRedundantValuesLen(0),
+    pasWayFeaturePairs(NULL),
+    nWayFeaturePairs(0),
+    nNextKeyIndex(0),
+    bInMemoryNodesFile(false),
+    bMustUnlinkNodesFile(true),
+    nNodesFileSize(0),
+    fpNodes(NULL),
+    nPrevNodeId(-INT_MAX),
+    nBucketOld(-1),
+    nOffInBucketReducedOld(-1),
+    pabySector(NULL),
+    papsBuckets(NULL),
+    nBuckets(0),
+    bNeedsToSaveWayInfo(false)
+{}
 
 /************************************************************************/
 /*                          ~OGROSMDataSource()                         */
@@ -275,15 +266,16 @@ OGROSMDataSource::OGROSMDataSource()
 OGROSMDataSource::~OGROSMDataSource()
 
 {
-    int i;
-    for(i=0;i<nLayers;i++)
+    for( int i=0; i<nLayers; i++ )
         delete papoLayers[i];
     CPLFree(papoLayers);
 
     CPLFree(pszName);
 
     if( psParser != NULL )
-        CPLDebug("OSM", "Number of bytes read in file : " CPL_FRMT_GUIB, OSM_GetBytesRead(psParser));
+        CPLDebug( "OSM",
+                  "Number of bytes read in file : " CPL_FRMT_GUIB,
+                  OSM_GetBytesRead(psParser) );
     OSM_Close(psParser);
 
     CPLFree(pasLonLatCache);
@@ -319,7 +311,7 @@ OGROSMDataSource::~OGROSMDataSource()
     CPLFree(pasLonLatArray);
     CPLFree(panUnsortedReqIds);
 
-    for( i = 0; i < nWayFeaturePairs; i++)
+    for( int i = 0; i < nWayFeaturePairs; i++)
     {
         delete pasWayFeaturePairs[i].poFeature;
     }
@@ -328,24 +320,23 @@ OGROSMDataSource::~OGROSMDataSource()
     CPLFree(pabyNonRedundantValues);
 
 #ifdef OSM_DEBUG
-    FILE* f;
-    f = fopen("keys.txt", "wt");
-    for(i=0;i<(int)asKeys.size();i++)
+    FILE* f = fopen("keys.txt", "wt");
+    for( int i=0; i<startic_cast<int>(asKeys.size()); i++ )
     {
         KeyDesc* psKD = asKeys[i];
         fprintf(f, "%08d idx=%d %s\n",
-                psKD->nOccurences,
+                psKD->nOccurrences,
                 psKD->nKeyIndex,
                 psKD->pszK);
     }
     fclose(f);
 #endif
 
-    for(i=0;i<(int)asKeys.size();i++)
+    for( int i=0; i<static_cast<int>(asKeys.size()); i++ )
     {
         KeyDesc* psKD = asKeys[i];
         CPLFree(psKD->pszK);
-        for(int j=0;j<(int)psKD->asValues.size();j++)
+        for( int j=0; j<static_cast<int>(psKD->asValues.size());j++)
             CPLFree(psKD->asValues[j]);
         delete psKD;
     }
@@ -362,7 +353,7 @@ OGROSMDataSource::~OGROSMDataSource()
     CPLFree(pabySector);
     if( papsBuckets )
     {
-        for( i = 0; i < nBuckets; i++)
+        for( int i = 0; i < nBuckets; i++)
         {
             if( bCompressNodes )
             {
@@ -387,8 +378,6 @@ OGROSMDataSource::~OGROSMDataSource()
 
 void OGROSMDataSource::CloseDB()
 {
-    int i;
-
     if( hInsertNodeStmt != NULL )
         sqlite3_finalize( hInsertNodeStmt );
     hInsertNodeStmt = NULL;
@@ -411,7 +400,7 @@ void OGROSMDataSource::CloseDB()
 
     if( pahSelectNodeStmt != NULL )
     {
-        for(i = 0; i < LIMIT_IDS_PER_REQUEST; i++)
+        for( int i = 0; i < LIMIT_IDS_PER_REQUEST; i++ )
         {
             if( pahSelectNodeStmt[i] != NULL )
                 sqlite3_finalize( pahSelectNodeStmt[i] );
@@ -422,7 +411,7 @@ void OGROSMDataSource::CloseDB()
 
     if( pahSelectWayStmt != NULL )
     {
-        for(i = 0; i < LIMIT_IDS_PER_REQUEST; i++)
+        for( int i = 0; i < LIMIT_IDS_PER_REQUEST; i++ )
         {
             if( pahSelectWayStmt[i] != NULL )
                 sqlite3_finalize( pahSelectWayStmt[i] );
@@ -468,8 +457,8 @@ int OGROSMDataSource::IndexPoint(OSMNode* psNode)
 
     if( bCustomIndexing)
         return IndexPointCustom(psNode);
-    else
-        return IndexPointSQLite(psNode);
+
+    return IndexPointSQLite(psNode);
 }
 
 /************************************************************************/
@@ -484,13 +473,15 @@ int OGROSMDataSource::IndexPointSQLite(OSMNode* psNode)
     sLonLat.nLon = DBL_TO_INT(psNode->dfLon);
     sLonLat.nLat = DBL_TO_INT(psNode->dfLat);
 
-    sqlite3_bind_blob( hInsertNodeStmt, 2, &sLonLat, sizeof(sLonLat), SQLITE_STATIC );
+    sqlite3_bind_blob( hInsertNodeStmt, 2, &sLonLat, sizeof(sLonLat),
+                       SQLITE_STATIC );
 
     int rc = sqlite3_step( hInsertNodeStmt );
     sqlite3_reset( hInsertNodeStmt );
     if( !(rc == SQLITE_OK || rc == SQLITE_DONE) )
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "Failed inserting node " CPL_FRMT_GIB ": %s",
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Failed inserting node " CPL_FRMT_GIB ": %s",
             psNode->nID, sqlite3_errmsg(hDB));
     }
 
@@ -501,15 +492,15 @@ int OGROSMDataSource::IndexPointSQLite(OSMNode* psNode)
 /*                           FlushCurrentSector()                       */
 /************************************************************************/
 
-int OGROSMDataSource::FlushCurrentSector()
+bool OGROSMDataSource::FlushCurrentSector()
 {
 #ifndef FAKE_LOOKUP_NODES
     if( bCompressNodes )
         return FlushCurrentSectorCompressedCase();
-    else
-        return FlushCurrentSectorNonCompressedCase();
+
+    return FlushCurrentSectorNonCompressedCase();
 #else
-    return TRUE;
+    return true;
 #endif
 }
 
@@ -517,74 +508,75 @@ int OGROSMDataSource::FlushCurrentSector()
 /*                            AllocBucket()                             */
 /************************************************************************/
 
-int OGROSMDataSource::AllocBucket(int iBucket)
+bool OGROSMDataSource::AllocBucket(int iBucket)
 {
-    int bOOM = FALSE;
     if( bCompressNodes )
     {
-        int nRem = iBucket % (PAGE_SIZE / BUCKET_SECTOR_SIZE_ARRAY_SIZE);
-        if( papsBuckets[iBucket - nRem].u.panSectorSize == NULL )
-            papsBuckets[iBucket - nRem].u.panSectorSize = (GByte*)VSICalloc(1, PAGE_SIZE);
+        const int nRem = iBucket % (PAGE_SIZE / BUCKET_SECTOR_SIZE_ARRAY_SIZE);
         if( papsBuckets[iBucket - nRem].u.panSectorSize == NULL )
+            papsBuckets[iBucket - nRem].u.panSectorSize =
+                static_cast<GByte*>(VSI_CALLOC_VERBOSE(1, PAGE_SIZE));
+        if( papsBuckets[iBucket - nRem].u.panSectorSize != NULL )
         {
-            papsBuckets[iBucket].u.panSectorSize = NULL;
-            bOOM = TRUE;
+            papsBuckets[iBucket].u.panSectorSize =
+                papsBuckets[iBucket - nRem].u.panSectorSize +
+                nRem * BUCKET_SECTOR_SIZE_ARRAY_SIZE;
+            return true;
         }
-        else
-            papsBuckets[iBucket].u.panSectorSize = papsBuckets[iBucket - nRem].u.panSectorSize + nRem * BUCKET_SECTOR_SIZE_ARRAY_SIZE;
+        papsBuckets[iBucket].u.panSectorSize = NULL;
     }
     else
     {
-        int nRem = iBucket % (PAGE_SIZE / BUCKET_BITMAP_SIZE);
-        if( papsBuckets[iBucket - nRem].u.pabyBitmap == NULL )
-            papsBuckets[iBucket - nRem].u.pabyBitmap = (GByte*)VSICalloc(1, PAGE_SIZE);
+        const int nRem = iBucket % (PAGE_SIZE / BUCKET_BITMAP_SIZE);
         if( papsBuckets[iBucket - nRem].u.pabyBitmap == NULL )
+            papsBuckets[iBucket - nRem].u.pabyBitmap =
+                reinterpret_cast<GByte *>(VSI_CALLOC_VERBOSE(1, PAGE_SIZE));
+        if( papsBuckets[iBucket - nRem].u.pabyBitmap != NULL )
         {
-            papsBuckets[iBucket].u.pabyBitmap = NULL;
-            bOOM = TRUE;
+            papsBuckets[iBucket].u.pabyBitmap =
+                papsBuckets[iBucket - nRem].u.pabyBitmap +
+                nRem * BUCKET_BITMAP_SIZE;
+            return true;
         }
-        else
-            papsBuckets[iBucket].u.pabyBitmap = papsBuckets[iBucket - nRem].u.pabyBitmap + nRem * BUCKET_BITMAP_SIZE;
+        papsBuckets[iBucket].u.pabyBitmap = NULL;
     }
 
-    if( bOOM )
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "AllocBucket() failed. Use OSM_USE_CUSTOM_INDEXING=NO");
-        bStopParsing = TRUE;
-        return FALSE;
-    }
-
-    return TRUE;
+    // Out of memory.
+    CPLError( CE_Failure, CPLE_AppDefined,
+              "AllocBucket() failed. Use OSM_USE_CUSTOM_INDEXING=NO" );
+    bStopParsing = true;
+    return false;
 }
 
 /************************************************************************/
 /*                         AllocMoreBuckets()                           */
 /************************************************************************/
 
-int OGROSMDataSource::AllocMoreBuckets(int nNewBucketIdx, int bAllocBucket)
+bool OGROSMDataSource::AllocMoreBuckets(int nNewBucketIdx, bool bAllocBucket)
 {
     CPLAssert(nNewBucketIdx >= nBuckets);
 
-    int nNewBuckets = MAX(nBuckets + nBuckets / 2, nNewBucketIdx);
+    const int nNewBuckets = MAX(nBuckets + nBuckets / 2, nNewBucketIdx);
 
     size_t nNewSize = sizeof(Bucket) * nNewBuckets;
-    if( (GUIntBig)nNewSize != sizeof(Bucket) * (GUIntBig)nNewBuckets )
+    if( static_cast<GUIntBig>(nNewSize) !=
+        sizeof(Bucket) * static_cast<GUIntBig>(nNewBuckets) )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "AllocMoreBuckets() failed. Use OSM_USE_CUSTOM_INDEXING=NO");
-        bStopParsing = TRUE;
-        return FALSE;
+        bStopParsing = true;
+        return false;
     }
 
-    Bucket* papsNewBuckets = (Bucket*) VSIRealloc(papsBuckets, nNewSize);
+    Bucket* papsNewBuckets = (Bucket*) VSI_REALLOC_VERBOSE(papsBuckets, nNewSize);
     if( papsNewBuckets == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "AllocMoreBuckets() failed. Use OSM_USE_CUSTOM_INDEXING=NO");
-        bStopParsing = TRUE;
-        return FALSE;
+        bStopParsing = true;
+        return false;
     }
     papsBuckets = papsNewBuckets;
 
-    int bOOM = FALSE;
+    bool bOOM = false;
     int i;
     for(i = nBuckets; i < nNewBuckets && !bOOM; i++)
     {
@@ -592,7 +584,7 @@ int OGROSMDataSource::AllocMoreBuckets(int nNewBucketIdx, int bAllocBucket)
         if( bAllocBucket )
         {
             if( !AllocBucket(i) )
-                bOOM = TRUE;
+                bOOM = true;
         }
         else
         {
@@ -606,39 +598,42 @@ int OGROSMDataSource::AllocMoreBuckets(int nNewBucketIdx, int bAllocBucket)
 
     if( bOOM )
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "AllocMoreBuckets() failed. Use OSM_USE_CUSTOM_INDEXING=NO");
-        bStopParsing = TRUE;
-        return FALSE;
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "AllocMoreBuckets() failed. Use OSM_USE_CUSTOM_INDEXING=NO");
+        bStopParsing = true;
+        return false;
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                     FlushCurrentSectorCompressedCase()               */
 /************************************************************************/
 
-int OGROSMDataSource::FlushCurrentSectorCompressedCase()
+bool OGROSMDataSource::FlushCurrentSectorCompressedCase()
 {
     GByte abyOutBuffer[2 * SECTOR_SIZE];
     GByte* pabyOut = abyOutBuffer;
     LonLat* pasLonLatIn = (LonLat*)pabySector;
-    int nLastLon = 0, nLastLat = 0;
-    int bLastValid = FALSE;
-    int i;
+    int nLastLon = 0;
+    int nLastLat = 0;
+    bool bLastValid = false;
 
     CPLAssert((NODE_PER_SECTOR % 8) == 0);
     memset(abyOutBuffer, 0, NODE_PER_SECTOR / 8);
     pabyOut += NODE_PER_SECTOR / 8;
-    for(i = 0; i < NODE_PER_SECTOR; i++)
+    for( int i = 0; i < NODE_PER_SECTOR; i++)
     {
         if( pasLonLatIn[i].nLon || pasLonLatIn[i].nLat )
         {
             abyOutBuffer[i >> 3] |= (1 << (i % 8));
             if( bLastValid )
             {
-                GIntBig nDiff64Lon = (GIntBig)pasLonLatIn[i].nLon - (GIntBig)nLastLon;
-                GIntBig nDiff64Lat = pasLonLatIn[i].nLat - nLastLat;
+                const GIntBig nDiff64Lon =
+                  static_cast<GIntBig>(pasLonLatIn[i].nLon) -
+                  static_cast<GIntBig>(nLastLon);
+                const GIntBig nDiff64Lat = pasLonLatIn[i].nLat - nLastLat;
                 WriteVarSInt64(nDiff64Lon, &pabyOut);
                 WriteVarSInt64(nDiff64Lat, &pabyOut);
             }
@@ -647,14 +642,14 @@ int OGROSMDataSource::FlushCurrentSectorCompressedCase()
                 memcpy(pabyOut, &pasLonLatIn[i], sizeof(LonLat));
                 pabyOut += sizeof(LonLat);
             }
-            bLastValid = TRUE;
+            bLastValid = true;
 
             nLastLon = pasLonLatIn[i].nLon;
             nLastLat = pasLonLatIn[i].nLat;
         }
     }
 
-    size_t nCompressSize = (size_t)(pabyOut - abyOutBuffer);
+    size_t nCompressSize = static_cast<size_t>(pabyOut - abyOutBuffer);
     CPLAssert(nCompressSize < sizeof(abyOutBuffer) - 1);
     abyOutBuffer[nCompressSize] = 0;
 
@@ -676,88 +671,88 @@ int OGROSMDataSource::FlushCurrentSectorCompressedCase()
         if( nBucketOld >= nBuckets )
         {
             if( !AllocMoreBuckets(nBucketOld + 1) )
-                return FALSE;
+                return false;
         }
         Bucket* psBucket = &papsBuckets[nBucketOld];
         if( psBucket->u.panSectorSize == NULL && !AllocBucket(nBucketOld) )
-            return FALSE;
+            return false;
+        CPLAssert( psBucket->u.panSectorSize != NULL );
         psBucket->u.panSectorSize[nOffInBucketReducedOld] =
                                     COMPRESS_SIZE_TO_BYTE(nCompressSize);
 
-        return TRUE;
-    }
-    else
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Cannot write in temporary node file %s : %s",
-                 osNodesFilename.c_str(), VSIStrerror(errno));
+        return true;
     }
 
-    return FALSE;
+    CPLError( CE_Failure, CPLE_AppDefined,
+              "Cannot write in temporary node file %s : %s",
+              osNodesFilename.c_str(), VSIStrerror(errno));
+
+    return false;
 }
 
 /************************************************************************/
 /*                   FlushCurrentSectorNonCompressedCase()              */
 /************************************************************************/
 
-int OGROSMDataSource::FlushCurrentSectorNonCompressedCase()
+bool OGROSMDataSource::FlushCurrentSectorNonCompressedCase()
 {
-   if( VSIFWriteL(pabySector, 1, SECTOR_SIZE, fpNodes) == SECTOR_SIZE )
+    if( VSIFWriteL(pabySector, 1, SECTOR_SIZE, fpNodes) == SECTOR_SIZE )
     {
         memset(pabySector, 0, SECTOR_SIZE);
         nNodesFileSize += SECTOR_SIZE;
-        return TRUE;
-    }
-    else
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Cannot write in temporary node file %s : %s",
-                 osNodesFilename.c_str(), VSIStrerror(errno));
+        return true;
     }
 
-    return FALSE;
+    CPLError( CE_Failure, CPLE_AppDefined,
+              "Cannot write in temporary node file %s : %s",
+              osNodesFilename.c_str(), VSIStrerror(errno));
+
+    return false;
 }
 
 /************************************************************************/
 /*                          IndexPointCustom()                          */
 /************************************************************************/
 
-int OGROSMDataSource::IndexPointCustom(OSMNode* psNode)
+bool OGROSMDataSource::IndexPointCustom(OSMNode* psNode)
 {
     if( psNode->nID <= nPrevNodeId)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Non increasing node id. Use OSM_USE_CUSTOM_INDEXING=NO");
-        bStopParsing = TRUE;
-        return FALSE;
+        bStopParsing = true;
+        return false;
     }
     if( !VALID_ID_FOR_CUSTOM_INDEXING(psNode->nID) )
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Unsupported node id value (" CPL_FRMT_GIB "). Use OSM_USE_CUSTOM_INDEXING=NO",
-                 psNode->nID);
-        bStopParsing = TRUE;
-        return FALSE;
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Unsupported node id value (" CPL_FRMT_GIB
+                  "). Use OSM_USE_CUSTOM_INDEXING=NO",
+                  psNode->nID);
+        bStopParsing = true;
+        return false;
     }
 
-    int nBucket = (int)(psNode->nID / NODE_PER_BUCKET);
-    int nOffInBucket = psNode->nID % NODE_PER_BUCKET;
-    int nOffInBucketReduced = nOffInBucket >> NODE_PER_SECTOR_SHIFT;
-    int nOffInBucketReducedRemainer = nOffInBucket & ((1 << NODE_PER_SECTOR_SHIFT) - 1);
+    const int nBucket = static_cast<int>(psNode->nID / NODE_PER_BUCKET);
+    const int nOffInBucket = static_cast<int>(psNode->nID % NODE_PER_BUCKET);
+    const int nOffInBucketReduced = nOffInBucket >> NODE_PER_SECTOR_SHIFT;
+    const int nOffInBucketReducedRemainer =
+        nOffInBucket & ((1 << NODE_PER_SECTOR_SHIFT) - 1);
 
     if( nBucket >= nBuckets )
     {
         if( !AllocMoreBuckets(nBucket + 1) )
-            return FALSE;
+            return false;
     }
     Bucket* psBucket = &papsBuckets[nBucket];
 
     if( !bCompressNodes )
     {
-        int nBitmapIndex = nOffInBucketReduced / 8;
-        int nBitmapRemainer = nOffInBucketReduced % 8;
+        const int nBitmapIndex = nOffInBucketReduced / 8;
+        const int nBitmapRemainer = nOffInBucketReduced % 8;
         if( psBucket->u.pabyBitmap == NULL && !AllocBucket(nBucket) )
-            return FALSE;
+            return false;
+        CPLAssert( psBucket->u.pabyBitmap != NULL );
         psBucket->u.pabyBitmap[nBitmapIndex] |= (1 << nBitmapRemainer);
     }
 
@@ -768,8 +763,8 @@ int OGROSMDataSource::IndexPointCustom(OSMNode* psNode)
         {
             if( !FlushCurrentSector() )
             {
-                bStopParsing = TRUE;
-                return FALSE;
+                bStopParsing = true;
+                return false;
             }
         }
         nBucketOld = nBucket;
@@ -782,19 +777,20 @@ int OGROSMDataSource::IndexPointCustom(OSMNode* psNode)
         CPLAssert(nOffInBucketReduced > nOffInBucketReducedOld);
         if( !FlushCurrentSector() )
         {
-            bStopParsing = TRUE;
-            return FALSE;
+            bStopParsing = true;
+            return false;
         }
         nOffInBucketReducedOld = nOffInBucketReduced;
     }
 
-    LonLat* psLonLat = (LonLat*)(pabySector + sizeof(LonLat) * nOffInBucketReducedRemainer);
+    LonLat* psLonLat = reinterpret_cast<LonLat*>(
+        pabySector + sizeof(LonLat) * nOffInBucketReducedRemainer);
     psLonLat->nLon = DBL_TO_INT(psNode->dfLon);
     psLonLat->nLat = DBL_TO_INT(psNode->dfLat);
 
     nPrevNodeId = psNode->nID;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -803,12 +799,10 @@ int OGROSMDataSource::IndexPointCustom(OSMNode* psNode)
 
 void OGROSMDataSource::NotifyNodes(unsigned int nNodes, OSMNode* pasNodes)
 {
-    unsigned int i;
-
     const OGREnvelope* psEnvelope =
         papoLayers[IDX_LYR_POINTS]->GetSpatialFilterEnvelope();
 
-    for(i = 0; i < nNodes; i++)
+    for( unsigned int i = 0; i < nNodes; i++ )
     {
         /* If the point doesn't fit into the envelope of the spatial filter */
         /* then skip it */
@@ -825,13 +819,12 @@ void OGROSMDataSource::NotifyNodes(unsigned int nNodes, OSMNode* pasNodes)
         if( !papoLayers[IDX_LYR_POINTS]->IsUserInterested() )
             continue;
 
-        unsigned int j;
-        int bInterestingTag = bReportAllNodes;
+        bool bInterestingTag = bReportAllNodes;
         OSMTag* pasTags = pasNodes[i].pasTags;
 
         if( !bReportAllNodes )
         {
-            for(j = 0; j < pasNodes[i].nTags; j++)
+            for( unsigned int j = 0; j < pasNodes[i].nTags; j++)
             {
                 const char* pszK = pasTags[j].pszK;
                 if( papoLayers[IDX_LYR_POINTS]->IsSignificantKey(pszK) )
@@ -851,28 +844,29 @@ void OGROSMDataSource::NotifyNodes(unsigned int nNodes, OSMNode* pasNodes)
                 new OGRPoint(pasNodes[i].dfLon, pasNodes[i].dfLat));
 
             papoLayers[IDX_LYR_POINTS]->SetFieldsFromTags(
-                poFeature, pasNodes[i].nID, FALSE, pasNodes[i].nTags, pasTags, &pasNodes[i].sInfo );
+                poFeature, pasNodes[i].nID, FALSE, pasNodes[i].nTags,
+                pasTags, &pasNodes[i].sInfo );
 
             int bFilteredOut = FALSE;
             if( !papoLayers[IDX_LYR_POINTS]->AddFeature(poFeature, FALSE,
                                                         &bFilteredOut,
                                                         !bFeatureAdded) )
             {
-                bStopParsing = TRUE;
+                bStopParsing = true;
                 break;
             }
             else if (!bFilteredOut)
-                bFeatureAdded = TRUE;
+                bFeatureAdded = true;
         }
     }
 }
 
-static void OGROSMNotifyNodes (unsigned int nNodes,
-                               OSMNode* pasNodes,
-                               CPL_UNUSED OSMContext* psOSMContext,
-                               void* user_data)
+static void OGROSMNotifyNodes ( unsigned int nNodes,
+                                OSMNode *pasNodes,
+                                OSMContext * /* psOSMContext */,
+                                void *user_data)
 {
-    ((OGROSMDataSource*) user_data)->NotifyNodes(nNodes, pasNodes);
+    static_cast<OGROSMDataSource *>(user_data)->NotifyNodes(nNodes, pasNodes);
 }
 
 /************************************************************************/
@@ -892,14 +886,14 @@ void OGROSMDataSource::LookupNodes( )
     if( nReqIds > 1 && bEnableHashedIndex )
     {
         memset(panHashedIndexes, 0xFF, HASHED_INDEXES_ARRAY_SIZE * sizeof(int));
-        bHashedIndexValid = TRUE;
+        bHashedIndexValid = true;
 #ifdef DEBUG_COLLISIONS
         int nCollisions = 0;
 #endif
         int iNextFreeBucket = 0;
         for(unsigned int i = 0; i < nReqIds; i++)
         {
-            int nIndInHashArray = HASH_ID_FUNC(panReqIds[i]) % HASHED_INDEXES_ARRAY_SIZE;
+            int nIndInHashArray = static_cast<int>(HASH_ID_FUNC(panReqIds[i]) % HASHED_INDEXES_ARRAY_SIZE);
             int nIdx = panHashedIndexes[nIndInHashArray];
             if( nIdx == -1 )
             {
@@ -916,8 +910,8 @@ void OGROSMDataSource::LookupNodes( )
                     if(iNextFreeBucket == COLLISION_BUCKET_ARRAY_SIZE)
                     {
                         CPLDebug("OSM", "Too many collisions. Disabling hashed indexing");
-                        bHashedIndexValid = FALSE;
-                        bEnableHashedIndex = FALSE;
+                        bHashedIndexValid = false;
+                        bEnableHashedIndex = false;
                         break;
                     }
                     iBucket = iNextFreeBucket;
@@ -931,11 +925,11 @@ void OGROSMDataSource::LookupNodes( )
                 if(iNextFreeBucket == COLLISION_BUCKET_ARRAY_SIZE)
                 {
                     CPLDebug("OSM", "Too many collisions. Disabling hashed indexing");
-                    bHashedIndexValid = FALSE;
-                    bEnableHashedIndex = FALSE;
+                    bHashedIndexValid = false;
+                    bEnableHashedIndex = false;
                     break;
                 }
-                while( TRUE )
+                while( true )
                 {
                     int iNext = psCollisionBuckets[iBucket].nNext;
                     if( iNext < 0 )
@@ -959,7 +953,7 @@ void OGROSMDataSource::LookupNodes( )
 #endif
     }
     else
-        bHashedIndexValid = FALSE;
+        bHashedIndexValid = false;
 #endif // ENABLE_NODE_LOOKUP_BY_HASHING
 }
 
@@ -969,13 +963,10 @@ void OGROSMDataSource::LookupNodes( )
 
 void OGROSMDataSource::LookupNodesSQLite( )
 {
-    unsigned int iCur;
-    unsigned int i;
-
     CPLAssert(nUnsortedReqIds <= MAX_ACCUMULATED_NODES);
 
     nReqIds = 0;
-    for(i = 0; i < nUnsortedReqIds; i++)
+    for( unsigned int i = 0; i < nUnsortedReqIds; i++)
     {
         GIntBig id = panUnsortedReqIds[i];
         panReqIds[nReqIds++] = id;
@@ -985,23 +976,23 @@ void OGROSMDataSource::LookupNodesSQLite( )
 
     /* Remove duplicates */
     unsigned int j = 0;
-    for(i = 0; i < nReqIds; i++)
+    for( unsigned int i = 0; i < nReqIds; i++)
     {
         if (!(i > 0 && panReqIds[i] == panReqIds[i-1]))
             panReqIds[j++] = panReqIds[i];
     }
     nReqIds = j;
 
-    iCur = 0;
+    unsigned int iCur = 0;
     j = 0;
     while( iCur < nReqIds )
     {
         unsigned int nToQuery = nReqIds - iCur;
-        if( nToQuery > LIMIT_IDS_PER_REQUEST )
-            nToQuery = LIMIT_IDS_PER_REQUEST;
+        if( nToQuery > static_cast<unsigned int>(LIMIT_IDS_PER_REQUEST) )
+            nToQuery = static_cast<unsigned int>(LIMIT_IDS_PER_REQUEST);
 
         sqlite3_stmt* hStmt = pahSelectNodeStmt[nToQuery-1];
-        for(i=iCur;i<iCur + nToQuery;i++)
+        for( unsigned int i=iCur;i<iCur + nToQuery;i++)
         {
              sqlite3_bind_int64( hStmt, i - iCur +1, panReqIds[i] );
         }
@@ -1009,7 +1000,7 @@ void OGROSMDataSource::LookupNodesSQLite( )
 
         while( sqlite3_step(hStmt) == SQLITE_ROW )
         {
-            GIntBig id = sqlite3_column_int64(hStmt, 0);
+            const GIntBig id = sqlite3_column_int64(hStmt, 0);
             LonLat* psLonLat = (LonLat*)sqlite3_column_blob(hStmt, 1);
 
             panReqIds[j] = id;
@@ -1030,7 +1021,9 @@ void OGROSMDataSource::LookupNodesSQLite( )
 static GIntBig ReadVarSInt64(GByte** ppabyPtr)
 {
     GIntBig nSVal64 = ReadVarInt64(ppabyPtr);
-    GIntBig nDiff64 = ((nSVal64 & 1) == 0) ? (((GUIntBig)nSVal64) >> 1) : -(((GUIntBig)nSVal64) >> 1)-1;
+    GIntBig nDiff64 = ((nSVal64 & 1) == 0) ?
+        (GIntBig)(((GUIntBig)nSVal64) >> 1) :
+        -(GIntBig)(((GUIntBig)nSVal64) >> 1)-1;
     return nDiff64;
 }
 
@@ -1042,12 +1035,12 @@ static int DecompressSector(GByte* pabyIn, int nSectorSize, GByte* pabyOut)
 {
     GByte* pabyPtr = pabyIn;
     LonLat* pasLonLatOut = (LonLat*) pabyOut;
-    int nLastLon = 0, nLastLat = 0;
-    int bLastValid = FALSE;
-    int i;
+    int nLastLon = 0;
+    int nLastLat = 0;
+    bool bLastValid = false;
 
     pabyPtr += NODE_PER_SECTOR / 8;
-    for(i = 0; i < NODE_PER_SECTOR; i++)
+    for( int i = 0; i < NODE_PER_SECTOR; i++)
     {
         if( pabyIn[i >> 3] & (1 << (i % 8)) )
         {
@@ -1058,7 +1051,7 @@ static int DecompressSector(GByte* pabyIn, int nSectorSize, GByte* pabyOut)
             }
             else
             {
-                bLastValid = TRUE;
+                bLastValid = true;
                 memcpy(&(pasLonLatOut[i]), pabyPtr, sizeof(LonLat));
                 pabyPtr += sizeof(LonLat);
             }
@@ -1090,7 +1083,7 @@ void OGROSMDataSource::LookupNodesCustom( )
     {
         if( !FlushCurrentSector() )
         {
-            bStopParsing = TRUE;
+            bStopParsing = true;
             return;
         }
 
@@ -1108,8 +1101,8 @@ void OGROSMDataSource::LookupNodesCustom( )
         if( !VALID_ID_FOR_CUSTOM_INDEXING(id) )
             continue;
 
-        int nBucket = (int)(id / NODE_PER_BUCKET);
-        int nOffInBucket = id % NODE_PER_BUCKET;
+        int nBucket = static_cast<int>(id / NODE_PER_BUCKET);
+        int nOffInBucket = static_cast<int>(id % NODE_PER_BUCKET);
         int nOffInBucketReduced = nOffInBucket >> NODE_PER_SECTOR_SHIFT;
 
         if( nBucket >= nBuckets )
@@ -1171,8 +1164,8 @@ void OGROSMDataSource::LookupNodesCustomCompressedCase()
     GByte abyRawSector[SECTOR_SIZE + SECURITY_MARGIN];
     memset(abyRawSector + SECTOR_SIZE, 0, SECURITY_MARGIN);
 
-    int nBucketOld = -1;
-    int nOffInBucketReducedOld = -1;
+    int l_nBucketOld = -1;
+    int l_nOffInBucketReducedOld = -1;
     int k = 0;
     int nOffFromBucketStart = 0;
 
@@ -1180,19 +1173,19 @@ void OGROSMDataSource::LookupNodesCustomCompressedCase()
     {
         GIntBig id = panReqIds[i];
 
-        int nBucket = (int)(id / NODE_PER_BUCKET);
-        int nOffInBucket = id % NODE_PER_BUCKET;
+        int nBucket = static_cast<int>(id / NODE_PER_BUCKET);
+        int nOffInBucket = static_cast<int>(id % NODE_PER_BUCKET);
         int nOffInBucketReduced = nOffInBucket >> NODE_PER_SECTOR_SHIFT;
         int nOffInBucketReducedRemainer = nOffInBucket & ((1 << NODE_PER_SECTOR_SHIFT) - 1);
 
-        if( nBucket != nBucketOld )
+        if( nBucket != l_nBucketOld )
         {
-            nOffInBucketReducedOld = -1;
+            l_nOffInBucketReducedOld = -1;
             k = 0;
             nOffFromBucketStart = 0;
         }
 
-        if ( nOffInBucketReduced != nOffInBucketReducedOld )
+        if ( nOffInBucketReduced != l_nOffInBucketReducedOld )
         {
             if( nBucket >= nBuckets )
             {
@@ -1243,15 +1236,16 @@ void OGROSMDataSource::LookupNodesCustomCompressedCase()
 
                 if( !DecompressSector(abyRawSector, nSectorSize, pabySector) )
                 {
-                    CPLError(CE_Failure,  CPLE_AppDefined,
-                            "Error while uncompressing sector for node " CPL_FRMT_GIB, id);
+                    CPLError( CE_Failure,  CPLE_AppDefined,
+                              "Error while uncompressing sector for node "
+                              CPL_FRMT_GIB, id );
                     continue;
                     // FIXME ?
                 }
             }
 
-            nBucketOld = nBucket;
-            nOffInBucketReducedOld = nOffInBucketReduced;
+            l_nBucketOld = nBucket;
+            l_nOffInBucketReducedOld = nOffInBucketReduced;
         }
 
         panReqIds[j] = id;
@@ -1278,8 +1272,8 @@ void OGROSMDataSource::LookupNodesCustomNonCompressedCase()
     {
         GIntBig id = panReqIds[i];
 
-        int nBucket = (int)(id / NODE_PER_BUCKET);
-        int nOffInBucket = id % NODE_PER_BUCKET;
+        int nBucket = static_cast<int>(id / NODE_PER_BUCKET);
+        int nOffInBucket = static_cast<int>(id % NODE_PER_BUCKET);
         int nOffInBucketReduced = nOffInBucket >> NODE_PER_SECTOR_SHIFT;
         int nOffInBucketReducedRemainer = nOffInBucket & ((1 << NODE_PER_SECTOR_SHIFT) - 1);
 
@@ -1333,9 +1327,9 @@ void OGROSMDataSource::LookupNodesCustomNonCompressedCase()
 static void WriteVarInt(unsigned int nVal, GByte** ppabyData)
 {
     GByte* pabyData = *ppabyData;
-    while(TRUE)
+    while( true )
     {
-        if( (nVal & (~0x7f)) == 0 )
+        if( (nVal & (~0x7fU)) == 0 )
         {
             *pabyData = (GByte)nVal;
             *ppabyData = pabyData + 1;
@@ -1355,9 +1349,9 @@ static void WriteVarInt(unsigned int nVal, GByte** ppabyData)
 static void WriteVarInt64(GUIntBig nVal, GByte** ppabyData)
 {
     GByte* pabyData = *ppabyData;
-    while(TRUE)
+    while( true )
     {
-        if( (nVal & (~0x7f)) == 0 )
+        if( (((GUInt32)nVal) & (~0x7fU)) == 0 )
         {
             *pabyData = (GByte)nVal;
             *ppabyData = pabyData + 1;
@@ -1383,7 +1377,7 @@ static void WriteVarSInt64(GIntBig nSVal, GByte** ppabyData)
         nVal = ((-1-nSVal) << 1) + 1;
 
     GByte* pabyData = *ppabyData;
-    while(TRUE)
+    while( true )
     {
         if( (nVal & (~0x7f)) == 0 )
         {
@@ -1436,7 +1430,7 @@ int OGROSMDataSource::CompressWay ( unsigned int nTags, IndexedKVP* pasTags,
             const char* pszV = (const char*)pabyNonRedundantValues +
                 pasTags[iTag].u.nOffsetInpabyNonRedundantValues;
 
-            int nLenV = strlen(pszV) + 1;
+            int nLenV = static_cast<int>(strlen(pszV)) + 1;
             if ((int)(pabyPtr - pabyCompressedWay) + 2 + nLenV >= MAX_SIZE_FOR_TAGS_IN_WAY)
             {
                 break;
@@ -1543,7 +1537,7 @@ int OGROSMDataSource::UncompressWay( int nBytes, GByte* pabyCompressedWay,
             psInfo->nVersion = ReadVarInt32(&pabyPtr);
             psInfo->nUID = ReadVarInt32(&pabyPtr);
 
-            psInfo->bTimeStampIsStr = FALSE;
+            psInfo->bTimeStampIsStr = false;
             psInfo->pszUserSID = ""; // FIXME
         }
         else
@@ -1626,32 +1620,31 @@ void OGROSMDataSource::ProcessWaysBatch()
     //printf("nodes = %d, features = %d\n", nUnsortedReqIds, nWayFeaturePairs);
     LookupNodes();
 
-    int iPair;
-    for(iPair = 0; iPair < nWayFeaturePairs; iPair ++)
+    for( int iPair = 0; iPair < nWayFeaturePairs; iPair ++)
     {
         WayFeaturePair* psWayFeaturePairs = &pasWayFeaturePairs[iPair];
 
-        int bIsArea = psWayFeaturePairs->bIsArea;
+        const EMULATED_BOOL bIsArea = psWayFeaturePairs->bIsArea;
 
         unsigned int nFound = 0;
-        unsigned int i;
 
 #ifdef ENABLE_NODE_LOOKUP_BY_HASHING
         if( bHashedIndexValid )
         {
-            for(i=0;i<psWayFeaturePairs->nRefs;i++)
+            for( unsigned int i=0;i<psWayFeaturePairs->nRefs;i++)
             {
-                int nIndInHashArray =
+                int nIndInHashArray = static_cast<int>(
                     HASH_ID_FUNC(psWayFeaturePairs->panNodeRefs[i]) %
-                        HASHED_INDEXES_ARRAY_SIZE;
+                        HASHED_INDEXES_ARRAY_SIZE);
                 int nIdx = panHashedIndexes[nIndInHashArray];
                 if( nIdx < -1 )
                 {
                     int iBucket = -nIdx - 2;
-                    while( TRUE )
+                    while( true )
                     {
                         nIdx = psCollisionBuckets[iBucket].nInd;
-                        if( panReqIds[nIdx] == psWayFeaturePairs->panNodeRefs[i] )
+                        if( panReqIds[nIdx] ==
+                            psWayFeaturePairs->panNodeRefs[i] )
                             break;
                         iBucket = psCollisionBuckets[iBucket].nNext;
                         if( iBucket < 0 )
@@ -1677,7 +1670,7 @@ void OGROSMDataSource::ProcessWaysBatch()
 #endif // ENABLE_NODE_LOOKUP_BY_HASHING
         {
             int nIdx = -1;
-            for(i=0;i<psWayFeaturePairs->nRefs;i++)
+            for( unsigned int i=0;i<psWayFeaturePairs->nRefs;i++)
             {
                 if( nIdx >= 0 && psWayFeaturePairs->panNodeRefs[i] ==
                                  psWayFeaturePairs->panNodeRefs[i-1] + 1 )
@@ -1712,7 +1705,7 @@ void OGROSMDataSource::ProcessWaysBatch()
                     psWayFeaturePairs->nWayID, nFound);
             delete psWayFeaturePairs->poFeature;
             psWayFeaturePairs->poFeature = NULL;
-            psWayFeaturePairs->bIsArea = FALSE;
+            psWayFeaturePairs->bIsArea = false;
             continue;
         }
 
@@ -1733,14 +1726,11 @@ void OGROSMDataSource::ProcessWaysBatch()
             continue;
         }
 
-        OGRLineString* poLS;
-        OGRGeometry* poGeom;
-
-        poLS = new OGRLineString();
-        poGeom = poLS;
+        OGRLineString* poLS = new OGRLineString();
+        OGRGeometry* poGeom = poLS;
 
         poLS->setNumPoints((int)nFound);
-        for(i=0;i<nFound;i++)
+        for( unsigned int i=0;i<nFound;i++)
         {
             poLS->setPoint(i,
                         INT_TO_DBL(pasLonLatCache[i].nLon),
@@ -1759,14 +1749,14 @@ void OGROSMDataSource::ProcessWaysBatch()
                                                    psWayFeaturePairs->bAttrFilterAlreadyEvaluated,
                                                    &bFilteredOut,
                                                    !bFeatureAdded) )
-            bStopParsing = TRUE;
+            bStopParsing = true;
         else if (!bFilteredOut)
-            bFeatureAdded = TRUE;
+            bFeatureAdded = true;
     }
 
     if( papoLayers[IDX_LYR_MULTIPOLYGONS]->IsUserInterested() )
     {
-        for(iPair = 0; iPair < nWayFeaturePairs; iPair ++)
+        for( int iPair = 0; iPair < nWayFeaturePairs; iPair ++)
         {
             WayFeaturePair* psWayFeaturePairs = &pasWayFeaturePairs[iPair];
 
@@ -1800,8 +1790,6 @@ void OGROSMDataSource::ProcessWaysBatch()
 
 void OGROSMDataSource::NotifyWay (OSMWay* psWay)
 {
-    unsigned int i;
-
     nWaysProcessed++;
     if( (nWaysProcessed % 10000) == 0 )
     {
@@ -1831,49 +1819,48 @@ void OGROSMDataSource::NotifyWay (OSMWay* psWay)
     }
 
     /* Is a closed way a polygon ? */
-    int bIsArea = FALSE;
+    bool bIsArea = false;
     if( psWay->panNodeRefs[0] == psWay->panNodeRefs[psWay->nRefs - 1] )
     {
-        for(i=0;i<psWay->nTags;i++)
+        for( unsigned int i=0;i<psWay->nTags;i++)
         {
             const char* pszK = psWay->pasTags[i].pszK;
             if( strcmp(pszK, "area") == 0 )
             {
                 if( strcmp(psWay->pasTags[i].pszV, "yes") == 0 )
                 {
-                    bIsArea = TRUE;
+                    bIsArea = true;
                 }
                 else if( strcmp(psWay->pasTags[i].pszV, "no") == 0 )
                 {
-                    bIsArea = FALSE;
+                    bIsArea = false;
                     break;
                 }
             }
             else if( aoSetClosedWaysArePolygons.find(pszK) !=
                      aoSetClosedWaysArePolygons.end() )
             {
-                bIsArea = TRUE;
+                bIsArea = true;
             }
         }
     }
 
-    OGRFeature* poFeature = NULL;
-
-    int bInterestingTag = bReportAllWays;
+    bool bInterestingTag = bReportAllWays;
     if( !bIsArea && !bReportAllWays )
     {
-        for(i=0;i<psWay->nTags;i++)
+        for( unsigned int i=0;i<psWay->nTags;i++)
         {
             const char* pszK = psWay->pasTags[i].pszK;
             if( papoLayers[IDX_LYR_LINES]->IsSignificantKey(pszK) )
             {
-                bInterestingTag = TRUE;
+                bInterestingTag = true;
                 break;
             }
         }
     }
 
-    int bAttrFilterAlreadyEvaluated = FALSE;
+    OGRFeature* poFeature = NULL;
+    bool bAttrFilterAlreadyEvaluated = false;
     if( !bIsArea && papoLayers[IDX_LYR_LINES]->IsUserInterested() && bInterestingTag )
     {
         poFeature = new OGRFeature(papoLayers[IDX_LYR_LINES]->GetLayerDefn());
@@ -1893,7 +1880,7 @@ void OGROSMDataSource::NotifyWay (OSMWay* psWay)
                 delete poFeature;
                 return;
             }
-            bAttrFilterAlreadyEvaluated = TRUE;
+            bAttrFilterAlreadyEvaluated = true;
         }
     }
     else if( !bIndexWays )
@@ -1912,7 +1899,7 @@ void OGROSMDataSource::NotifyWay (OSMWay* psWay)
     WayFeaturePair* psWayFeaturePairs = &pasWayFeaturePairs[nWayFeaturePairs];
 
     psWayFeaturePairs->nWayID = psWay->nID;
-    psWayFeaturePairs->nRefs = psWay->nRefs - bIsArea;
+    psWayFeaturePairs->nRefs = psWay->nRefs - (bIsArea ? 1 : 0);
     psWayFeaturePairs->panNodeRefs = panUnsortedReqIds + nUnsortedReqIds;
     psWayFeaturePairs->poFeature = poFeature;
     psWayFeaturePairs->bIsArea = bIsArea;
@@ -1948,7 +1935,7 @@ void OGROSMDataSource::NotifyWay (OSMWay* psWay)
             psWayFeaturePairs->sInfo.nChangeset = psWay->sInfo.nChangeset;
             psWayFeaturePairs->sInfo.nVersion = psWay->sInfo.nVersion;
             psWayFeaturePairs->sInfo.nUID = psWay->sInfo.nUID;
-            psWayFeaturePairs->sInfo.bTimeStampIsStr = FALSE;
+            psWayFeaturePairs->sInfo.bTimeStampIsStr = false;
             psWayFeaturePairs->sInfo.pszUserSID = ""; // FIXME
         }
         else
@@ -1957,7 +1944,7 @@ void OGROSMDataSource::NotifyWay (OSMWay* psWay)
             psWayFeaturePairs->sInfo.nChangeset = 0;
             psWayFeaturePairs->sInfo.nVersion = 0;
             psWayFeaturePairs->sInfo.nUID = 0;
-            psWayFeaturePairs->sInfo.bTimeStampIsStr = FALSE;
+            psWayFeaturePairs->sInfo.bTimeStampIsStr = false;
             psWayFeaturePairs->sInfo.pszUserSID = "";
         }
 
@@ -2002,14 +1989,14 @@ void OGROSMDataSource::NotifyWay (OSMWay* psWay)
                 psKD->pszK = CPLStrdup(pszK);
                 psKD->nKeyIndex = nNextKeyIndex ++;
                 //CPLDebug("OSM", "nNextKeyIndex=%d", nNextKeyIndex);
-                psKD->nOccurences = 0;
+                psKD->nOccurrences = 0;
                 psKD->asValues.push_back(CPLStrdup(""));
                 aoMapIndexedKeys[psKD->pszK] = psKD;
                 asKeys.push_back(psKD);
             }
             else
                 psKD = oIterK->second;
-            psKD->nOccurences ++;
+            psKD->nOccurrences ++;
 
             pasAccumulatedTags[nAccumulatedTags].nKeyIndex = (short)psKD->nKeyIndex;
 
@@ -2034,17 +2021,20 @@ void OGROSMDataSource::NotifyWay (OSMWay* psWay)
             }
             else
             {
-                int nLenV = strlen(pszV) + 1;
+                const int nLenV = static_cast<int>(strlen(pszV)) + 1;
 
                 if( psKD->asValues.size() == 1024 )
                 {
-                    CPLDebug("OSM", "More than %d different values for tag %s",
-                            1024, pszK);
-                    psKD->asValues.push_back(CPLStrdup(""));  /* to avoid next warnings */
+                    CPLDebug( "OSM", "More than %d different values for tag %s",
+                              1024, pszK);
+                    // To avoid next warnings.
+                    psKD->asValues.push_back(CPLStrdup(""));
                 }
 
-                CPLAssert( nNonRedundantValuesLen + nLenV <= MAX_NON_REDUNDANT_VALUES );
-                memcpy(pabyNonRedundantValues + nNonRedundantValuesLen, pszV, nLenV);
+                CPLAssert( nNonRedundantValuesLen + nLenV <=
+                           MAX_NON_REDUNDANT_VALUES );
+                memcpy( pabyNonRedundantValues + nNonRedundantValuesLen, pszV,
+                        nLenV);
                 pasAccumulatedTags[nAccumulatedTags].bVIsIndex = FALSE;
                 pasAccumulatedTags[nAccumulatedTags].u.nOffsetInpabyNonRedundantValues = nNonRedundantValuesLen;
                 nNonRedundantValuesLen += nLenV;
@@ -2064,7 +2054,7 @@ void OGROSMDataSource::NotifyWay (OSMWay* psWay)
         psWayFeaturePairs->sInfo.nChangeset = 0;
         psWayFeaturePairs->sInfo.nVersion = 0;
         psWayFeaturePairs->sInfo.nUID = 0;
-        psWayFeaturePairs->sInfo.bTimeStampIsStr = FALSE;
+        psWayFeaturePairs->sInfo.bTimeStampIsStr = false;
         psWayFeaturePairs->sInfo.pszUserSID = "";
 
         psWayFeaturePairs->nTags = 0;
@@ -2073,22 +2063,24 @@ void OGROSMDataSource::NotifyWay (OSMWay* psWay)
 
     nWayFeaturePairs++;
 
-    memcpy(panUnsortedReqIds + nUnsortedReqIds, psWay->panNodeRefs, sizeof(GIntBig) * (psWay->nRefs - bIsArea));
-    nUnsortedReqIds += (psWay->nRefs - bIsArea);
+    memcpy( panUnsortedReqIds + nUnsortedReqIds,
+            psWay->panNodeRefs, sizeof(GIntBig) * (psWay->nRefs - (bIsArea ? 1 : 0)));
+    nUnsortedReqIds += (psWay->nRefs - (bIsArea ? 1 : 0));
 }
 
-static void OGROSMNotifyWay (OSMWay* psWay,
-                             CPL_UNUSED OSMContext* psOSMContext,
-                             void* user_data)
+static void OGROSMNotifyWay ( OSMWay *psWay,
+                              OSMContext * /* psOSMContext */,
+                              void *user_data)
 {
-    ((OGROSMDataSource*) user_data)->NotifyWay(psWay);
+    static_cast<OGROSMDataSource *>(user_data)->NotifyWay(psWay);
 }
 
 /************************************************************************/
 /*                            LookupWays()                              */
 /************************************************************************/
 
-unsigned int OGROSMDataSource::LookupWays( std::map< GIntBig, std::pair<int,void*> >& aoMapWays,
+unsigned int OGROSMDataSource::LookupWays( std::map< GIntBig,
+                                           std::pair<int,void*> >& aoMapWays,
                                            OSMRelation* psRelation )
 {
     unsigned int nFound = 0;
@@ -2104,8 +2096,11 @@ unsigned int OGROSMDataSource::LookupWays( std::map< GIntBig, std::pair<int,void
                 strcmp(psRelation->pasMembers[i].pszRole, "subarea") != 0 )
             {
                 nToQuery ++;
-                if( nToQuery == LIMIT_IDS_PER_REQUEST )
+                if( nToQuery ==
+                    static_cast<unsigned int>(LIMIT_IDS_PER_REQUEST) )
+                {
                     break;
+                }
             }
         }
 
@@ -2160,7 +2155,7 @@ OGRGeometry* OGROSMDataSource::BuildMultiPolygon(OSMRelation* psRelation,
     std::map< GIntBig, std::pair<int,void*> > aoMapWays;
     LookupWays( aoMapWays, psRelation );
 
-    int bMissing = FALSE;
+    bool bMissing = false;
     unsigned int i;
     for(i = 0; i < psRelation->nMembers; i ++ )
     {
@@ -2171,24 +2166,25 @@ OGRGeometry* OGROSMDataSource::BuildMultiPolygon(OSMRelation* psRelation,
             {
                 CPLDebug("OSM", "Relation " CPL_FRMT_GIB " has missing ways. Ignoring it",
                         psRelation->nID);
-                bMissing = TRUE;
+                bMissing = true;
                 break;
             }
         }
     }
 
-    OGRGeometry* poRet = NULL;
-    OGRMultiLineString* poMLS = NULL;
-    OGRGeometry** papoPolygons = NULL;
-    int nPolys = 0;
-
     if( bMissing )
-        goto cleanup;
+    {
+        std::map< GIntBig, std::pair<int,void*> >::iterator oIter;
+        for( oIter = aoMapWays.begin(); oIter != aoMapWays.end(); ++oIter )
+            CPLFree(oIter->second.second);
+
+        return NULL;
+    }
 
-    poMLS = new OGRMultiLineString();
-    papoPolygons = (OGRGeometry**) CPLMalloc(
-        sizeof(OGRGeometry*) *  psRelation->nMembers);
-    nPolys = 0;
+    OGRMultiLineString* poMLS = new OGRMultiLineString();
+    OGRGeometry** papoPolygons = static_cast<OGRGeometry**>( CPLMalloc(
+        sizeof(OGRGeometry*) * psRelation->nMembers) );
+    int nPolys = 0;
 
     if( pnTags != NULL )
         *pnTags = 0;
@@ -2235,7 +2231,7 @@ OGRGeometry* OGROSMDataSource::BuildMultiPolygon(OSMRelation* psRelation,
                 if( strcmp(psRelation->pasMembers[i].pszRole, "outer") == 0 )
                 {
                     sqlite3_bind_int64( hDeletePolygonsStandaloneStmt, 1, psRelation->pasMembers[i].nID );
-                    sqlite3_step( hDeletePolygonsStandaloneStmt );
+                    CPL_IGNORE_RET_VAL(sqlite3_step( hDeletePolygonsStandaloneStmt ));
                     sqlite3_reset( hDeletePolygonsStandaloneStmt );
                 }
             }
@@ -2268,13 +2264,13 @@ OGRGeometry* OGROSMDataSource::BuildMultiPolygon(OSMRelation* psRelation,
             OGRPolygon* poSuperPoly = (OGRPolygon* ) hPoly;
             for(i = 0; i < 1 + (unsigned int)poSuperPoly->getNumInteriorRings(); i++)
             {
-                OGRPolygon* poPoly = new OGRPolygon();
                 OGRLinearRing* poRing =  (i == 0) ? poSuperPoly->getExteriorRing() :
                                                     poSuperPoly->getInteriorRing(i - 1);
                 if( poRing != NULL && poRing->getNumPoints() >= 4 &&
                     poRing->getX(0) == poRing->getX(poRing->getNumPoints() -1) &&
                     poRing->getY(0) == poRing->getY(poRing->getNumPoints() -1) )
                 {
+                    OGRPolygon* poPoly = new OGRPolygon();
                     poPoly->addRing( poRing );
                     papoPolygons[nPolys ++] = poPoly;
                 }
@@ -2285,6 +2281,8 @@ OGRGeometry* OGROSMDataSource::BuildMultiPolygon(OSMRelation* psRelation,
     }
     delete poMLS;
 
+    OGRGeometry* poRet = NULL;
+
     if( nPolys > 0 )
     {
         int bIsValidGeometry = FALSE;
@@ -2305,17 +2303,19 @@ OGRGeometry* OGROSMDataSource::BuildMultiPolygon(OSMRelation* psRelation,
         }
         else
         {
-            CPLDebug("OSM", "Relation " CPL_FRMT_GIB ": Geometry has incompatible type : %s",
-                     psRelation->nID,
-                     poGeom != NULL ? OGR_G_GetGeometryName((OGRGeometryH)poGeom) : "null" );
+            CPLDebug( "OSM",
+                      "Relation " CPL_FRMT_GIB
+                      ": Geometry has incompatible type : %s",
+                      psRelation->nID,
+                      poGeom != NULL ?
+                      OGR_G_GetGeometryName(
+                          reinterpret_cast<OGRGeometryH>(poGeom)) : "null" );
             delete poGeom;
         }
     }
 
     CPLFree(papoPolygons);
 
-cleanup:
-    /* Cleanup */
     std::map< GIntBig, std::pair<int,void*> >::iterator oIter;
     for( oIter = aoMapWays.begin(); oIter != aoMapWays.end(); ++oIter )
         CPLFree(oIter->second.second);
@@ -2327,22 +2327,19 @@ cleanup:
 /*                          BuildGeometryCollection()                   */
 /************************************************************************/
 
-OGRGeometry* OGROSMDataSource::BuildGeometryCollection(OSMRelation* psRelation, int bMultiLineString)
+OGRGeometry* OGROSMDataSource::BuildGeometryCollection(OSMRelation* psRelation,
+                                                       int bMultiLineString)
 {
     std::map< GIntBig, std::pair<int,void*> > aoMapWays;
     LookupWays( aoMapWays, psRelation );
 
-    unsigned int i;
+    OGRGeometryCollection* poColl = ( bMultiLineString ) ?
+        new OGRMultiLineString() : new OGRGeometryCollection();
 
-    OGRGeometryCollection* poColl;
-    if( bMultiLineString )
-        poColl = new OGRMultiLineString();
-    else
-        poColl = new OGRGeometryCollection();
-
-    for(i = 0; i < psRelation->nMembers; i ++ )
+    for( unsigned int i = 0; i < psRelation->nMembers; i ++ )
     {
-        if( psRelation->pasMembers[i].eType == MEMBER_NODE && !bMultiLineString )
+        if( psRelation->pasMembers[i].eType ==
+            MEMBER_NODE && !bMultiLineString )
         {
             nUnsortedReqIds = 1;
             panUnsortedReqIds[0] = psRelation->pasMembers[i].nID;
@@ -2360,12 +2357,13 @@ OGRGeometry* OGROSMDataSource::BuildGeometryCollection(OSMRelation* psRelation,
         {
             const std::pair<int, void*>& oGeom = aoMapWays[ psRelation->pasMembers[i].nID ];
 
-            LonLat* pasCoords = (LonLat*) pasLonLatCache;
-            int nPoints = UncompressWay (oGeom.first, (GByte*) oGeom.second, pasCoords, NULL, NULL, NULL);
+            LonLat* pasCoords = reinterpret_cast<LonLat *>(pasLonLatCache);
+            const int nPoints = UncompressWay(
+                oGeom.first,
+                reinterpret_cast<GByte *>(oGeom.second),
+                pasCoords, NULL, NULL, NULL );
 
-            OGRLineString* poLS;
-
-            poLS = new OGRLineString();
+            OGRLineString* poLS = new OGRLineString();
             poColl->addGeometryDirectly(poLS);
 
             poLS->setNumPoints(nPoints);
@@ -2385,7 +2383,6 @@ OGRGeometry* OGROSMDataSource::BuildGeometryCollection(OSMRelation* psRelation,
         poColl = NULL;
     }
 
-    /* Cleanup */
     std::map< GIntBig, std::pair<int,void*> >::iterator oIter;
     for( oIter = aoMapWays.begin(); oIter != aoMapWays.end(); ++oIter )
         CPLFree(oIter->second.second);
@@ -2399,28 +2396,28 @@ OGRGeometry* OGROSMDataSource::BuildGeometryCollection(OSMRelation* psRelation,
 
 void OGROSMDataSource::NotifyRelation (OSMRelation* psRelation)
 {
-    unsigned int i;
-
     if( nWayFeaturePairs != 0 )
         ProcessWaysBatch();
 
     nRelationsProcessed++;
     if( (nRelationsProcessed % 10000) == 0 )
     {
-        CPLDebug("OSM", "Relations processed : %d", nRelationsProcessed);
+        CPLDebug( "OSM", "Relations processed : %d", nRelationsProcessed );
 #ifdef DEBUG_MEM_USAGE
-        CPLDebug("OSM", "GetMaxTotalAllocs() = " CPL_FRMT_GUIB, (GUIntBig)GetMaxTotalAllocs());
+        CPLDebug( "OSM",
+                  "GetMaxTotalAllocs() = " CPL_FRMT_GUIB,
+                  static_cast<GUIntBig>(GetMaxTotalAllocs()) );
 #endif
     }
 
     if( !bUseWaysIndex )
         return;
 
-    int bMultiPolygon = FALSE;
-    int bMultiLineString = FALSE;
-    int bInterestingTagFound = FALSE;
+    bool bMultiPolygon = false;
+    bool bMultiLineString = false;
+    bool bInterestingTagFound = false;
     const char* pszTypeV = NULL;
-    for(i = 0; i < psRelation->nTags; i ++ )
+    for( unsigned int i = 0; i < psRelation->nTags; i ++ )
     {
         const char* pszK = psRelation->pasTags[i].pszK;
         if( strcmp(pszK, "type") == 0 )
@@ -2430,16 +2427,16 @@ void OGROSMDataSource::NotifyRelation (OSMRelation* psRelation)
             if( strcmp(pszV, "multipolygon") == 0 ||
                 strcmp(pszV, "boundary") == 0)
             {
-                bMultiPolygon = TRUE;
+                bMultiPolygon = true;
             }
             else if( strcmp(pszV, "multilinestring") == 0 ||
                      strcmp(pszV, "route") == 0 )
             {
-                bMultiLineString = TRUE;
+                bMultiLineString = true;
             }
         }
         else if ( strcmp(pszK, "created_by") != 0 )
-            bInterestingTagFound = TRUE;
+            bInterestingTagFound = true;
     }
 
     /* Optimization : if we have an attribute filter, that does not require geometry, */
@@ -2452,7 +2449,9 @@ void OGROSMDataSource::NotifyRelation (OSMRelation* psRelation)
 
     OGRFeature* poFeature = NULL;
 
-    if( !(bMultiPolygon && !bInterestingTagFound) && /* we cannot do early filtering for multipolygon that has no interesting tag, since we may fetch attributes from ways */
+    if( !(bMultiPolygon && !bInterestingTagFound) &&
+        // We cannot do early filtering for multipolygon that has no
+        // interesting tag, since we may fetch attributes from ways.
         papoLayers[iCurLayer]->HasAttributeFilter() &&
         !papoLayers[iCurLayer]->AttributeFilterEvaluationNeedsGeometry() )
     {
@@ -2495,22 +2494,21 @@ void OGROSMDataSource::NotifyRelation (OSMRelation* psRelation)
 
     if( poGeom != NULL )
     {
-        int bAttrFilterAlreadyEvaluated;
+        bool bAttrFilterAlreadyEvaluated = true;
         if( poFeature == NULL )
         {
             poFeature = new OGRFeature(papoLayers[iCurLayer]->GetLayerDefn());
 
-            papoLayers[iCurLayer]->SetFieldsFromTags( poFeature,
-                                                      psRelation->nID,
-                                                      FALSE,
-                                                      nExtraTags ? nExtraTags : psRelation->nTags,
-                                                      nExtraTags ? pasExtraTags : psRelation->pasTags,
-                                                      &psRelation->sInfo);
+            papoLayers[iCurLayer]->SetFieldsFromTags(
+                poFeature,
+                psRelation->nID,
+                FALSE,
+                nExtraTags ? nExtraTags : psRelation->nTags,
+                nExtraTags ? pasExtraTags : psRelation->pasTags,
+                &psRelation->sInfo);
 
-            bAttrFilterAlreadyEvaluated = FALSE;
+            bAttrFilterAlreadyEvaluated = false;
         }
-        else
-            bAttrFilterAlreadyEvaluated = TRUE;
 
         poFeature->SetGeometryDirectly(poGeom);
 
@@ -2519,19 +2517,19 @@ void OGROSMDataSource::NotifyRelation (OSMRelation* psRelation)
                                                 bAttrFilterAlreadyEvaluated,
                                                 &bFilteredOut,
                                                 !bFeatureAdded ) )
-            bStopParsing = TRUE;
+            bStopParsing = true;
         else if (!bFilteredOut)
-            bFeatureAdded = TRUE;
+            bFeatureAdded = true;
     }
     else
         delete poFeature;
 }
 
-static void OGROSMNotifyRelation (OSMRelation* psRelation,
-                                  CPL_UNUSED OSMContext* psOSMContext,
-                                  void* user_data)
+static void OGROSMNotifyRelation ( OSMRelation *psRelation,
+                                   OSMContext * /* psOSMContext */,
+                                   void *user_data)
 {
-    ((OGROSMDataSource*) user_data)->NotifyRelation(psRelation);
+    static_cast<OGROSMDataSource *>(user_data)->NotifyRelation(psRelation);
 }
 
 
@@ -2544,25 +2542,27 @@ void OGROSMDataSource::ProcessPolygonsStandalone()
     unsigned int nTags = 0;
     OSMTag pasTags[MAX_COUNT_FOR_TAGS_IN_WAY];
     OSMInfo sInfo;
-    int bFirst = TRUE;
 
     sInfo.ts.nTimeStamp = 0;
     sInfo.nChangeset = 0;
     sInfo.nVersion = 0;
     sInfo.nUID = 0;
-    sInfo.bTimeStampIsStr = FALSE;
+    sInfo.bTimeStampIsStr = false;
     sInfo.pszUserSID = "";
 
     if( !bHasRowInPolygonsStandalone )
-        bHasRowInPolygonsStandalone = (sqlite3_step(hSelectPolygonsStandaloneStmt) == SQLITE_ROW);
+        bHasRowInPolygonsStandalone =
+            sqlite3_step(hSelectPolygonsStandaloneStmt) == SQLITE_ROW;
+
+    bool bFirst = true;
 
     while( bHasRowInPolygonsStandalone &&
            papoLayers[IDX_LYR_MULTIPOLYGONS]->nFeatureArraySize < 10000 )
     {
         if( bFirst )
         {
-            CPLDebug("OSM", "Remaining standalone polygons");
-            bFirst = FALSE;
+            CPLDebug( "OSM", "Remaining standalone polygons" );
+            bFirst = false;
         }
 
         GIntBig id = sqlite3_column_int64(hSelectPolygonsStandaloneStmt, 0);
@@ -2573,21 +2573,20 @@ void OGROSMDataSource::ProcessPolygonsStandalone()
             int nBlobSize = sqlite3_column_bytes(pahSelectWayStmt[0], 1);
             const void* blob = sqlite3_column_blob(pahSelectWayStmt[0], 1);
 
-            LonLat* pasCoords = (LonLat*) pasLonLatCache;
+            LonLat* pasCoords = reinterpret_cast<LonLat *>(pasLonLatCache);
 
-            int nPoints = UncompressWay (nBlobSize, (GByte*) blob,
-                                         pasCoords,
-                                         &nTags, pasTags, &sInfo );
+            const int nPoints = UncompressWay(
+                nBlobSize, reinterpret_cast<GByte *>(const_cast<void *>(blob)),
+                pasCoords, &nTags, pasTags, &sInfo );
             CPLAssert(nTags <= MAX_COUNT_FOR_TAGS_IN_WAY);
 
-            OGRLineString* poLS;
 
             OGRMultiPolygon* poMulti = new OGRMultiPolygon();
             OGRPolygon* poPoly = new OGRPolygon();
             OGRLinearRing* poRing = new OGRLinearRing();
             poMulti->addGeometryDirectly(poPoly);
             poPoly->addRingDirectly(poRing);
-            poLS = poRing;
+            OGRLineString* poLS = poRing;
 
             poLS->setNumPoints(nPoints);
             for(int j=0;j<nPoints;j++)
@@ -2597,7 +2596,9 @@ void OGROSMDataSource::ProcessPolygonsStandalone()
                                 INT_TO_DBL(pasCoords[j].nLat) );
             }
 
-            OGRFeature* poFeature = new OGRFeature(papoLayers[IDX_LYR_MULTIPOLYGONS]->GetLayerDefn());
+            OGRFeature* poFeature =
+                new OGRFeature(
+                    papoLayers[IDX_LYR_MULTIPOLYGONS]->GetLayerDefn());
 
             papoLayers[IDX_LYR_MULTIPOLYGONS]->SetFieldsFromTags( poFeature,
                                                                   id,
@@ -2614,20 +2615,21 @@ void OGROSMDataSource::ProcessPolygonsStandalone()
                                                     &bFilteredOut,
                                                     !bFeatureAdded ) )
             {
-                bStopParsing = TRUE;
+                bStopParsing = true;
                 break;
             }
             else if (!bFilteredOut)
-                bFeatureAdded = TRUE;
+                bFeatureAdded = true;
 
         }
         else {
-            CPLAssert(FALSE);
+            CPLAssert(false);
         }
 
         sqlite3_reset(pahSelectWayStmt[0]);
 
-        bHasRowInPolygonsStandalone = (sqlite3_step(hSelectPolygonsStandaloneStmt) == SQLITE_ROW);
+        bHasRowInPolygonsStandalone =
+            sqlite3_step(hSelectPolygonsStandaloneStmt) == SQLITE_ROW;
     }
 }
 
@@ -2642,26 +2644,27 @@ void OGROSMDataSource::NotifyBounds (double dfXMin, double dfYMin,
     sExtent.MinY = dfYMin;
     sExtent.MaxX = dfXMax;
     sExtent.MaxY = dfYMax;
-    bExtentValid = TRUE;
+    bExtentValid = true;
 
-    CPLDebug("OSM", "Got bounds : minx=%f, miny=%f, maxx=%f, maxy=%f",
-             dfXMin, dfYMin, dfXMax, dfYMax);
+    CPLDebug( "OSM", "Got bounds : minx=%f, miny=%f, maxx=%f, maxy=%f",
+              dfXMin, dfYMin, dfXMax, dfYMax);
 }
 
 static void OGROSMNotifyBounds( double dfXMin, double dfYMin,
                                 double dfXMax, double dfYMax,
-                                CPL_UNUSED OSMContext* psCtxt,
+                                OSMContext* /* psCtxt */,
                                 void* user_data )
 {
-    ((OGROSMDataSource*) user_data)->NotifyBounds(dfXMin, dfYMin,
-                                                  dfXMax, dfYMax);
+    static_cast<OGROSMDataSource *>(user_data)->NotifyBounds( dfXMin, dfYMin,
+                                                              dfXMax, dfYMax );
 }
 
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
 
-int OGROSMDataSource::Open( const char * pszFilename, char** papszOpenOptions )
+int OGROSMDataSource::Open( const char * pszFilename,
+                            char** papszOpenOptionsIn )
 
 {
     pszName = CPLStrdup( pszFilename );
@@ -2675,48 +2678,58 @@ int OGROSMDataSource::Open( const char * pszFilename, char** papszOpenOptions )
     if( psParser == NULL )
         return FALSE;
 
-    if( CSLFetchBoolean(papszOpenOptions, "INTERLEAVED_READING", FALSE) )
+    if( CSLFetchBoolean(papszOpenOptionsIn, "INTERLEAVED_READING", FALSE) )
         bInterleavedReading = TRUE;
 
     /* The following 4 config options are only useful for debugging */
-    bIndexPoints = CSLTestBoolean(CPLGetConfigOption("OSM_INDEX_POINTS", "YES"));
-    bUsePointsIndex = CSLTestBoolean(CPLGetConfigOption("OSM_USE_POINTS_INDEX", "YES"));
-    bIndexWays = CSLTestBoolean(CPLGetConfigOption("OSM_INDEX_WAYS", "YES"));
-    bUseWaysIndex = CSLTestBoolean(CPLGetConfigOption("OSM_USE_WAYS_INDEX", "YES"));
-
-    bCustomIndexing = CSLTestBoolean(CSLFetchNameValueDef(
-            papszOpenOptions, "USE_CUSTOM_INDEXING",
+    bIndexPoints = CPLTestBool(CPLGetConfigOption("OSM_INDEX_POINTS", "YES"));
+    bUsePointsIndex = CPLTestBool(
+        CPLGetConfigOption("OSM_USE_POINTS_INDEX", "YES"));
+    bIndexWays = CPLTestBool(CPLGetConfigOption("OSM_INDEX_WAYS", "YES"));
+    bUseWaysIndex = CPLTestBool(
+        CPLGetConfigOption("OSM_USE_WAYS_INDEX", "YES"));
+
+    bCustomIndexing = CPLTestBool(CSLFetchNameValueDef(
+            papszOpenOptionsIn, "USE_CUSTOM_INDEXING",
                         CPLGetConfigOption("OSM_USE_CUSTOM_INDEXING", "YES")));
     if( !bCustomIndexing )
         CPLDebug("OSM", "Using SQLite indexing for points");
-    bCompressNodes = CSLTestBoolean(CSLFetchNameValueDef(
-            papszOpenOptions, "COMPRESS_NODES",
+    bCompressNodes = CPLTestBool(CSLFetchNameValueDef(
+            papszOpenOptionsIn, "COMPRESS_NODES",
                         CPLGetConfigOption("OSM_COMPRESS_NODES", "NO")));
     if( bCompressNodes )
         CPLDebug("OSM", "Using compression for nodes DB");
 
     nLayers = 5;
-    papoLayers = (OGROSMLayer**) CPLMalloc(nLayers * sizeof(OGROSMLayer*));
+    papoLayers = static_cast<OGROSMLayer **>(
+        CPLMalloc(nLayers * sizeof(OGROSMLayer*)) );
 
-    papoLayers[IDX_LYR_POINTS] = new OGROSMLayer(this, IDX_LYR_POINTS, "points");
+    papoLayers[IDX_LYR_POINTS] =
+        new OGROSMLayer(this, IDX_LYR_POINTS, "points");
     papoLayers[IDX_LYR_POINTS]->GetLayerDefn()->SetGeomType(wkbPoint);
 
     papoLayers[IDX_LYR_LINES] = new OGROSMLayer(this, IDX_LYR_LINES, "lines");
     papoLayers[IDX_LYR_LINES]->GetLayerDefn()->SetGeomType(wkbLineString);
 
-    papoLayers[IDX_LYR_MULTILINESTRINGS] = new OGROSMLayer(this, IDX_LYR_MULTILINESTRINGS, "multilinestrings");
-    papoLayers[IDX_LYR_MULTILINESTRINGS]->GetLayerDefn()->SetGeomType(wkbMultiLineString);
+    papoLayers[IDX_LYR_MULTILINESTRINGS] =
+        new OGROSMLayer(this, IDX_LYR_MULTILINESTRINGS, "multilinestrings");
+    papoLayers[IDX_LYR_MULTILINESTRINGS]->GetLayerDefn()->
+        SetGeomType(wkbMultiLineString);
 
-    papoLayers[IDX_LYR_MULTIPOLYGONS] = new OGROSMLayer(this, IDX_LYR_MULTIPOLYGONS, "multipolygons");
-    papoLayers[IDX_LYR_MULTIPOLYGONS]->GetLayerDefn()->SetGeomType(wkbMultiPolygon);
+    papoLayers[IDX_LYR_MULTIPOLYGONS] =
+        new OGROSMLayer(this, IDX_LYR_MULTIPOLYGONS, "multipolygons");
+    papoLayers[IDX_LYR_MULTIPOLYGONS]->GetLayerDefn()->
+        SetGeomType(wkbMultiPolygon);
 
-    papoLayers[IDX_LYR_OTHER_RELATIONS] = new OGROSMLayer(this, IDX_LYR_OTHER_RELATIONS, "other_relations");
-    papoLayers[IDX_LYR_OTHER_RELATIONS]->GetLayerDefn()->SetGeomType(wkbGeometryCollection);
+    papoLayers[IDX_LYR_OTHER_RELATIONS] =
+        new OGROSMLayer(this, IDX_LYR_OTHER_RELATIONS, "other_relations");
+    papoLayers[IDX_LYR_OTHER_RELATIONS]->GetLayerDefn()->
+        SetGeomType(wkbGeometryCollection);
 
-    if( !ParseConf(papszOpenOptions) )
+    if( !ParseConf(papszOpenOptionsIn) )
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Could not parse configuration file for OSM import");
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Could not parse configuration file for OSM import");
         return FALSE;
     }
 
@@ -2727,19 +2740,29 @@ int OGROSMDataSource::Open( const char * pszFilename, char** papszOpenOptions )
           papoLayers[IDX_LYR_MULTIPOLYGONS]->HasUID() ||
           papoLayers[IDX_LYR_MULTIPOLYGONS]->HasUser() );
 
-    pasLonLatCache = (LonLat*)VSIMalloc(MAX_NODES_PER_WAY * sizeof(LonLat));
-    pabyWayBuffer = (GByte*)VSIMalloc(WAY_BUFFER_SIZE);
+    pasLonLatCache = static_cast<LonLat*>(
+        VSI_MALLOC_VERBOSE(MAX_NODES_PER_WAY * sizeof(LonLat)));
+    pabyWayBuffer = static_cast<GByte*>(VSI_MALLOC_VERBOSE(WAY_BUFFER_SIZE));
 
-    panReqIds = (GIntBig*)VSIMalloc(MAX_ACCUMULATED_NODES * sizeof(GIntBig));
+    panReqIds = static_cast<GIntBig*>(
+        VSI_MALLOC_VERBOSE(MAX_ACCUMULATED_NODES * sizeof(GIntBig)));
 #ifdef ENABLE_NODE_LOOKUP_BY_HASHING
-    panHashedIndexes = (int*)VSIMalloc(HASHED_INDEXES_ARRAY_SIZE * sizeof(int));
-    psCollisionBuckets = (CollisionBucket*)VSIMalloc(COLLISION_BUCKET_ARRAY_SIZE * sizeof(CollisionBucket));
+    panHashedIndexes = static_cast<int*>(
+        VSI_MALLOC_VERBOSE(HASHED_INDEXES_ARRAY_SIZE * sizeof(int)));
+    psCollisionBuckets = static_cast<CollisionBucket*>(
+        VSI_MALLOC_VERBOSE(COLLISION_BUCKET_ARRAY_SIZE *
+                           sizeof(CollisionBucket)));
 #endif
-    pasLonLatArray = (LonLat*)VSIMalloc(MAX_ACCUMULATED_NODES * sizeof(LonLat));
-    panUnsortedReqIds = (GIntBig*)VSIMalloc(MAX_ACCUMULATED_NODES * sizeof(GIntBig));
-    pasWayFeaturePairs = (WayFeaturePair*)VSIMalloc(MAX_DELAYED_FEATURES * sizeof(WayFeaturePair));
-    pasAccumulatedTags = (IndexedKVP*) VSIMalloc(MAX_ACCUMULATED_TAGS * sizeof(IndexedKVP));
-    pabyNonRedundantValues = (GByte*) VSIMalloc(MAX_NON_REDUNDANT_VALUES);
+    pasLonLatArray = static_cast<LonLat*>(
+        VSI_MALLOC_VERBOSE(MAX_ACCUMULATED_NODES * sizeof(LonLat)));
+    panUnsortedReqIds = static_cast<GIntBig*>(
+        VSI_MALLOC_VERBOSE(MAX_ACCUMULATED_NODES * sizeof(GIntBig)));
+    pasWayFeaturePairs = static_cast<WayFeaturePair*>(
+        VSI_MALLOC_VERBOSE(MAX_DELAYED_FEATURES * sizeof(WayFeaturePair)));
+    pasAccumulatedTags = static_cast<IndexedKVP*>(
+        VSI_MALLOC_VERBOSE(MAX_ACCUMULATED_TAGS * sizeof(IndexedKVP)) );
+    pabyNonRedundantValues = static_cast<GByte*>(
+        VSI_MALLOC_VERBOSE(MAX_NON_REDUNDANT_VALUES) );
 
     if( pasLonLatCache == NULL ||
         pabyWayBuffer == NULL ||
@@ -2750,33 +2773,31 @@ int OGROSMDataSource::Open( const char * pszFilename, char** papszOpenOptions )
         pasAccumulatedTags == NULL ||
         pabyNonRedundantValues == NULL )
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory,
-                 "Out-of-memory when allocating one of the buffer used for the processing.");
         return FALSE;
     }
 
-    nMaxSizeForInMemoryDBInMB = atoi(CSLFetchNameValueDef(papszOpenOptions,
+    nMaxSizeForInMemoryDBInMB = atoi(CSLFetchNameValueDef(papszOpenOptionsIn,
         "MAX_TMPFILE_SIZE", CPLGetConfigOption("OSM_MAX_TMPFILE_SIZE", "100")));
-    GIntBig nSize = (GIntBig)nMaxSizeForInMemoryDBInMB * 1024 * 1024;
+    GIntBig nSize =
+        static_cast<GIntBig>(nMaxSizeForInMemoryDBInMB) * 1024 * 1024;
     if (nSize < 0 || (GIntBig)(size_t)nSize != nSize)
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "Invalid value for OSM_MAX_TMPFILE_SIZE. Using 100 instead.");
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Invalid value for OSM_MAX_TMPFILE_SIZE. Using 100 instead." );
         nMaxSizeForInMemoryDBInMB = 100;
-        nSize = (GIntBig)nMaxSizeForInMemoryDBInMB * 1024 * 1024;
+        nSize = static_cast<GIntBig>(nMaxSizeForInMemoryDBInMB) * 1024 * 1024;
     }
 
     if( bCustomIndexing )
     {
-        pabySector = (GByte*) VSICalloc(1, SECTOR_SIZE);
+        pabySector = static_cast<GByte *>(VSI_CALLOC_VERBOSE(1, SECTOR_SIZE));
 
         if( pabySector == NULL || !AllocMoreBuckets(INIT_BUCKET_COUNT) )
         {
-            CPLError(CE_Failure, CPLE_OutOfMemory,
-                    "Out-of-memory when allocating one of the buffer used for the processing.");
             return FALSE;
         }
 
-        bInMemoryNodesFile = TRUE;
+        bInMemoryNodesFile = true;
         osNodesFilename.Printf("/vsimem/osm_importer/osm_temp_nodes_%p", this);
         fpNodes = VSIFOpenL(osNodesFilename, "wb+");
         if( fpNodes == NULL )
@@ -2785,7 +2806,8 @@ int OGROSMDataSource::Open( const char * pszFilename, char** papszOpenOptions )
         }
 
         CPLPushErrorHandler(CPLQuietErrorHandler);
-        int bSuccess = VSIFSeekL(fpNodes, (vsi_l_offset) (nSize * 3 / 4), SEEK_SET) == 0;
+        bool bSuccess =
+            VSIFSeekL(fpNodes, (vsi_l_offset) (nSize * 3 / 4), SEEK_SET) == 0;
         CPLPopErrorHandler();
 
         if( bSuccess )
@@ -2795,13 +2817,15 @@ int OGROSMDataSource::Open( const char * pszFilename, char** papszOpenOptions )
         }
         else
         {
-            CPLDebug("OSM", "Not enough memory for in-memory file. Using disk temporary file instead.");
+            CPLDebug( "OSM",
+                      "Not enough memory for in-memory file. "
+                      "Using disk temporary file instead." );
 
             VSIFCloseL(fpNodes);
             fpNodes = NULL;
             VSIUnlink(osNodesFilename);
 
-            bInMemoryNodesFile = FALSE;
+            bInMemoryNodesFile = false;
             osNodesFilename = CPLGenerateTempFilename("osm_tmp_nodes");
 
             fpNodes = VSIFOpenL(osNodesFilename, "wb+");
@@ -2824,7 +2848,7 @@ int OGROSMDataSource::Open( const char * pszFilename, char** papszOpenOptions )
         }
     }
 
-    int bRet = CreateTempDB();
+    const int bRet = CreateTempDB();
     if( bRet )
     {
         CPLString osInterestLayers = GetInterestLayersForDSName(GetName());
@@ -2845,15 +2869,15 @@ int OGROSMDataSource::CreateTempDB()
     char* pszErrMsg = NULL;
 
     int rc = 0;
-    int bIsExisting = FALSE;
-    int bSuccess = FALSE;
+    bool bIsExisting = false;
+    bool bSuccess = false;
 
 #ifdef HAVE_SQLITE_VFS
     const char* pszExistingTmpFile = CPLGetConfigOption("OSM_EXISTING_TMPFILE", NULL);
     if ( pszExistingTmpFile != NULL )
     {
-        bSuccess = TRUE;
-        bIsExisting = TRUE;
+        bSuccess = true;
+        bIsExisting = true;
         rc = sqlite3_open_v2( pszExistingTmpFile, &hDB,
                               SQLITE_OPEN_READWRITE | SQLITE_OPEN_NOMUTEX,
                               NULL );
@@ -2862,17 +2886,19 @@ int OGROSMDataSource::CreateTempDB()
     {
         osTmpDBName.Printf("/vsimem/osm_importer/osm_temp_%p.sqlite", this);
 
-        /* On 32 bit, the virtual memory space is scarce, so we need to reserve it right now */
-        /* Won't hurt on 64 bit either. */
+        // On 32 bit, the virtual memory space is scarce, so we need to
+        // reserve it right now Will not hurt on 64 bit either.
         VSILFILE* fp = VSIFOpenL(osTmpDBName, "wb");
         if( fp )
         {
-            GIntBig nSize = (GIntBig)nMaxSizeForInMemoryDBInMB * 1024 * 1024;
+            GIntBig nSize =
+                static_cast<GIntBig>(nMaxSizeForInMemoryDBInMB) * 1024 * 1024;
             if( bCustomIndexing && bInMemoryNodesFile )
                 nSize = nSize * 1 / 4;
 
             CPLPushErrorHandler(CPLQuietErrorHandler);
-            bSuccess = VSIFSeekL(fp, (vsi_l_offset) nSize, SEEK_SET) == 0;
+            bSuccess =
+                VSIFSeekL(fp, static_cast<vsi_l_offset>(nSize), SEEK_SET) == 0;
             CPLPopErrorHandler();
 
             if( bSuccess )
@@ -2882,19 +2908,23 @@ int OGROSMDataSource::CreateTempDB()
 
             if( !bSuccess )
             {
-                CPLDebug("OSM", "Not enough memory for in-memory file. Using disk temporary file instead.");
+                CPLDebug( "OSM",
+                          "Not enough memory for in-memory file. "
+                          "Using disk temporary file instead.");
                 VSIUnlink(osTmpDBName);
             }
         }
 
         if( bSuccess )
         {
-            bInMemoryTmpDB = TRUE;
+            bInMemoryTmpDB = true;
             pMyVFS = OGRSQLiteCreateVFS(NULL, this);
             sqlite3_vfs_register(pMyVFS, 0);
-            rc = sqlite3_open_v2( osTmpDBName.c_str(), &hDB,
-                                SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX,
-                                pMyVFS->zName );
+            rc = sqlite3_open_v2(
+                osTmpDBName.c_str(), &hDB,
+                SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
+                SQLITE_OPEN_NOMUTEX,
+                pMyVFS->zName );
         }
     }
 #endif
@@ -2908,7 +2938,8 @@ int OGROSMDataSource::CreateTempDB()
         /* opened */
         if( rc == SQLITE_OK )
         {
-            const char* pszVal = CPLGetConfigOption("OSM_UNLINK_TMPFILE", "YES");
+            const char* pszVal =
+                CPLGetConfigOption("OSM_UNLINK_TMPFILE", "YES");
             if( EQUAL(pszVal, "YES") )
             {
                 CPLPushErrorHandler(CPLQuietErrorHandler);
@@ -2933,9 +2964,10 @@ int OGROSMDataSource::CreateTempDB()
 
     if( !bIsExisting )
     {
-        rc = sqlite3_exec( hDB,
-                        "CREATE TABLE nodes (id INTEGER PRIMARY KEY, coords BLOB)",
-                        NULL, NULL, &pszErrMsg );
+        rc = sqlite3_exec(
+            hDB,
+            "CREATE TABLE nodes (id INTEGER PRIMARY KEY, coords BLOB)",
+            NULL, NULL, &pszErrMsg );
         if( rc != SQLITE_OK )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -2944,24 +2976,27 @@ int OGROSMDataSource::CreateTempDB()
             return FALSE;
         }
 
-        rc = sqlite3_exec( hDB,
-                        "CREATE TABLE ways (id INTEGER PRIMARY KEY, data BLOB)",
-                        NULL, NULL, &pszErrMsg );
+        rc = sqlite3_exec(
+            hDB,
+            "CREATE TABLE ways (id INTEGER PRIMARY KEY, data BLOB)",
+            NULL, NULL, &pszErrMsg );
         if( rc != SQLITE_OK )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                    "Unable to create table ways : %s", pszErrMsg );
+                      "Unable to create table ways : %s", pszErrMsg );
             sqlite3_free( pszErrMsg );
             return FALSE;
         }
 
-        rc = sqlite3_exec( hDB,
-                        "CREATE TABLE polygons_standalone (id INTEGER PRIMARY KEY)",
-                        NULL, NULL, &pszErrMsg );
+        rc = sqlite3_exec(
+            hDB,
+            "CREATE TABLE polygons_standalone (id INTEGER PRIMARY KEY)",
+            NULL, NULL, &pszErrMsg );
         if( rc != SQLITE_OK )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                    "Unable to create table polygons_standalone : %s", pszErrMsg );
+                      "Unable to create table polygons_standalone : %s",
+                      pszErrMsg );
             sqlite3_free( pszErrMsg );
             return FALSE;
         }
@@ -2973,131 +3008,134 @@ int OGROSMDataSource::CreateTempDB()
 /*                            SetDBOptions()                            */
 /************************************************************************/
 
-int OGROSMDataSource::SetDBOptions()
+bool OGROSMDataSource::SetDBOptions()
 {
     char* pszErrMsg = NULL;
-    int rc;
-
-    rc = sqlite3_exec( hDB, "PRAGMA synchronous = OFF", NULL, NULL, &pszErrMsg );
+    int rc =
+        sqlite3_exec( hDB, "PRAGMA synchronous = OFF", NULL, NULL, &pszErrMsg );
     if( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                     "Unable to run PRAGMA synchronous : %s",
                     pszErrMsg );
         sqlite3_free( pszErrMsg );
-        return FALSE;
+        return false;
     }
 
-    rc = sqlite3_exec( hDB, "PRAGMA journal_mode = OFF", NULL, NULL, &pszErrMsg );
+    rc = sqlite3_exec(
+        hDB, "PRAGMA journal_mode = OFF", NULL, NULL, &pszErrMsg );
     if( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                     "Unable to run PRAGMA journal_mode : %s",
                     pszErrMsg );
         sqlite3_free( pszErrMsg );
-        return FALSE;
+        return false;
     }
 
-    rc = sqlite3_exec( hDB, "PRAGMA temp_store = MEMORY", NULL, NULL, &pszErrMsg );
+    rc = sqlite3_exec(
+        hDB, "PRAGMA temp_store = MEMORY", NULL, NULL, &pszErrMsg );
     if( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                     "Unable to run PRAGMA temp_store : %s",
                     pszErrMsg );
         sqlite3_free( pszErrMsg );
-        return FALSE;
+        return false;
     }
 
     if( !SetCacheSize() )
-        return FALSE;
+        return false;
 
     if( !StartTransactionCacheDB() )
-        return FALSE;
+        return false;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                              SetCacheSize()                          */
 /************************************************************************/
 
-int OGROSMDataSource::SetCacheSize()
+bool OGROSMDataSource::SetCacheSize()
 {
-    int rc;
     const char* pszSqliteCacheMB = CPLGetConfigOption("OSM_SQLITE_CACHE", NULL);
-    if (pszSqliteCacheMB != NULL)
-    {
-        char* pszErrMsg = NULL;
-        char **papszResult;
-        int nRowCount, nColCount;
-        int iSqliteCachePages;
-        int iSqlitePageSize = -1;
-        int iSqliteCacheBytes = atoi( pszSqliteCacheMB ) * 1024 * 1024;
-
-        /* querying the current PageSize */
-        rc = sqlite3_get_table( hDB, "PRAGMA page_size",
+
+    if (pszSqliteCacheMB == NULL)
+        return true;
+
+    char* pszErrMsg = NULL;
+    char **papszResult;
+    int nRowCount;
+    int nColCount;
+    int iSqlitePageSize = -1;
+    const int iSqliteCacheBytes = atoi( pszSqliteCacheMB ) * 1024 * 1024;
+
+    /* querying the current PageSize */
+    int rc = sqlite3_get_table( hDB, "PRAGMA page_size",
                                 &papszResult, &nRowCount, &nColCount,
                                 &pszErrMsg );
-        if( rc == SQLITE_OK )
-        {
-            int iRow;
-            for (iRow = 1; iRow <= nRowCount; iRow++)
-            {
-                iSqlitePageSize = atoi( papszResult[(iRow * nColCount) + 0] );
-            }
-            sqlite3_free_table(papszResult);
-        }
-        if( iSqlitePageSize < 0 )
+    if( rc == SQLITE_OK )
+    {
+        int iRow;
+        for (iRow = 1; iRow <= nRowCount; iRow++)
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Unable to run PRAGMA page_size : %s",
-                      pszErrMsg ? pszErrMsg : sqlite3_errmsg(hDB) );
-            sqlite3_free( pszErrMsg );
-            return TRUE;
+            iSqlitePageSize = atoi( papszResult[(iRow * nColCount) + 0] );
         }
+        sqlite3_free_table(papszResult);
+    }
+    if( iSqlitePageSize < 0 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Unable to run PRAGMA page_size : %s",
+                  pszErrMsg ? pszErrMsg : sqlite3_errmsg(hDB) );
+        sqlite3_free( pszErrMsg );
+        return true;
+    }
+    if( iSqlitePageSize == 0 )
+        return true;
 
-        /* computing the CacheSize as #Pages */
-        iSqliteCachePages = iSqliteCacheBytes / iSqlitePageSize;
-        if( iSqliteCachePages <= 0)
-            return TRUE;
+    /* computing the CacheSize as #Pages */
+    const int iSqliteCachePages = iSqliteCacheBytes / iSqlitePageSize;
+    if( iSqliteCachePages <= 0)
+        return true;
 
-        rc = sqlite3_exec( hDB, CPLSPrintf( "PRAGMA cache_size = %d",
-                                            iSqliteCachePages ),
-                           NULL, NULL, &pszErrMsg );
-        if( rc != SQLITE_OK )
-        {
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "Unrecognized value for PRAGMA cache_size : %s",
-                      pszErrMsg );
-            sqlite3_free( pszErrMsg );
-            rc = SQLITE_OK;
-        }
+    rc = sqlite3_exec( hDB, CPLSPrintf( "PRAGMA cache_size = %d",
+                                        iSqliteCachePages ),
+                       NULL, NULL, &pszErrMsg );
+    if( rc != SQLITE_OK )
+    {
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Unrecognized value for PRAGMA cache_size : %s",
+                  pszErrMsg );
+        sqlite3_free( pszErrMsg );
     }
-    return TRUE;
+
+    return true;
 }
 
 /************************************************************************/
 /*                        CreatePreparedStatements()                    */
 /************************************************************************/
 
-int OGROSMDataSource::CreatePreparedStatements()
+bool OGROSMDataSource::CreatePreparedStatements()
 {
-    int rc;
-
-    rc = sqlite3_prepare( hDB, "INSERT INTO nodes (id, coords) VALUES (?,?)", -1,
-                          &hInsertNodeStmt, NULL );
+    int rc =
+        sqlite3_prepare( hDB, "INSERT INTO nodes (id, coords) VALUES (?,?)", -1,
+                         &hInsertNodeStmt, NULL );
     if( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "sqlite3_prepare() failed :  %s", sqlite3_errmsg(hDB) );
-        return FALSE;
+        return false;
     }
 
-    pahSelectNodeStmt = (sqlite3_stmt**) CPLCalloc(sizeof(sqlite3_stmt*), LIMIT_IDS_PER_REQUEST);
+    pahSelectNodeStmt = static_cast<sqlite3_stmt**>(
+        CPLCalloc(sizeof(sqlite3_stmt*), LIMIT_IDS_PER_REQUEST) );
 
     char szTmp[LIMIT_IDS_PER_REQUEST*2 + 128];
     strcpy(szTmp, "SELECT id, coords FROM nodes WHERE id IN (");
-    int nLen = strlen(szTmp);
+    int nLen = static_cast<int>(strlen(szTmp));
     for(int i=0;i<LIMIT_IDS_PER_REQUEST;i++)
     {
         if(i == 0)
@@ -3115,7 +3153,7 @@ int OGROSMDataSource::CreatePreparedStatements()
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                     "sqlite3_prepare() failed :  %s", sqlite3_errmsg(hDB) );
-            return FALSE;
+            return false;
         }
     }
 
@@ -3125,13 +3163,14 @@ int OGROSMDataSource::CreatePreparedStatements()
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "sqlite3_prepare() failed :  %s", sqlite3_errmsg(hDB) );
-        return FALSE;
+        return false;
     }
 
-    pahSelectWayStmt = (sqlite3_stmt**) CPLCalloc(sizeof(sqlite3_stmt*), LIMIT_IDS_PER_REQUEST);
+    pahSelectWayStmt = static_cast<sqlite3_stmt**>(
+        CPLCalloc(sizeof(sqlite3_stmt*), LIMIT_IDS_PER_REQUEST) );
 
     strcpy(szTmp, "SELECT id, data FROM ways WHERE id IN (");
-    nLen = strlen(szTmp);
+    nLen = static_cast<int>(strlen(szTmp));
     for(int i=0;i<LIMIT_IDS_PER_REQUEST;i++)
     {
         if(i == 0)
@@ -3149,48 +3188,51 @@ int OGROSMDataSource::CreatePreparedStatements()
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                     "sqlite3_prepare() failed :  %s", sqlite3_errmsg(hDB) );
-            return FALSE;
+            return false;
         }
     }
 
-    rc = sqlite3_prepare( hDB, "INSERT INTO polygons_standalone (id) VALUES (?)", -1,
-                          &hInsertPolygonsStandaloneStmt, NULL );
+    rc = sqlite3_prepare(
+        hDB, "INSERT INTO polygons_standalone (id) VALUES (?)", -1,
+        &hInsertPolygonsStandaloneStmt, NULL );
     if( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "sqlite3_prepare() failed :  %s", sqlite3_errmsg(hDB) );
-        return FALSE;
+        return false;
     }
 
-    rc = sqlite3_prepare( hDB, "DELETE FROM polygons_standalone WHERE id = ?", -1,
-                          &hDeletePolygonsStandaloneStmt, NULL );
+    rc = sqlite3_prepare(
+        hDB, "DELETE FROM polygons_standalone WHERE id = ?", -1,
+        &hDeletePolygonsStandaloneStmt, NULL );
     if( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "sqlite3_prepare() failed :  %s", sqlite3_errmsg(hDB) );
-        return FALSE;
+        return false;
     }
 
-    rc = sqlite3_prepare( hDB, "SELECT id FROM polygons_standalone ORDER BY id", -1,
-                          &hSelectPolygonsStandaloneStmt, NULL );
+    rc = sqlite3_prepare(
+        hDB, "SELECT id FROM polygons_standalone ORDER BY id", -1,
+        &hSelectPolygonsStandaloneStmt, NULL );
     if( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                 "sqlite3_prepare() failed :  %s", sqlite3_errmsg(hDB) );
-        return FALSE;
+        return false;
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                      StartTransactionCacheDB()                       */
 /************************************************************************/
 
-int OGROSMDataSource::StartTransactionCacheDB()
+bool OGROSMDataSource::StartTransactionCacheDB()
 {
     if( bInTransaction )
-        return FALSE;
+        return false;
 
     char* pszErrMsg = NULL;
     int rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, &pszErrMsg );
@@ -3199,24 +3241,24 @@ int OGROSMDataSource::StartTransactionCacheDB()
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to start transaction : %s", pszErrMsg );
         sqlite3_free( pszErrMsg );
-        return FALSE;
+        return false;
     }
 
-    bInTransaction = TRUE;
+    bInTransaction = true;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                        CommitTransactionCacheDB()                    */
 /************************************************************************/
 
-int OGROSMDataSource::CommitTransactionCacheDB()
+bool OGROSMDataSource::CommitTransactionCacheDB()
 {
     if( !bInTransaction )
-        return FALSE;
+        return false;
 
-    bInTransaction = FALSE;
+    bInTransaction = false;
 
     char* pszErrMsg = NULL;
     int rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL, &pszErrMsg );
@@ -3225,18 +3267,19 @@ int OGROSMDataSource::CommitTransactionCacheDB()
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to commit transaction : %s", pszErrMsg );
         sqlite3_free( pszErrMsg );
-        return FALSE;
+        return false;
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                     AddComputedAttributes()                          */
 /************************************************************************/
 
-void OGROSMDataSource::AddComputedAttributes(int iCurLayer,
-                                             const std::vector<OGROSMComputedAttribute>& oAttributes)
+void OGROSMDataSource::AddComputedAttributes(
+    int iCurLayer,
+    const std::vector<OGROSMComputedAttribute>& oAttributes)
 {
     for(size_t i=0; i<oAttributes.size();i++)
     {
@@ -3253,29 +3296,28 @@ void OGROSMDataSource::AddComputedAttributes(int iCurLayer,
 /*                           ParseConf()                                */
 /************************************************************************/
 
-int OGROSMDataSource::ParseConf(char** papszOpenOptions)
+bool OGROSMDataSource::ParseConf(char** papszOpenOptionsIn)
 {
-    const char *pszFilename = 
-        CSLFetchNameValueDef(papszOpenOptions, "CONFIG_FILE",
+    const char *pszFilename =
+        CSLFetchNameValueDef(papszOpenOptionsIn, "CONFIG_FILE",
                              CPLGetConfigOption("OSM_CONFIG_FILE", NULL));
     if( pszFilename == NULL )
         pszFilename = CPLFindFile( "gdal", "osmconf.ini" );
     if( pszFilename == NULL )
     {
-        CPLError(CE_Warning, CPLE_AppDefined, "Cannot find osmconf.ini configuration file");
-        return FALSE;
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Cannot find osmconf.ini configuration file");
+        return false;
     }
 
     VSILFILE* fpConf = VSIFOpenL(pszFilename, "rb");
     if( fpConf == NULL )
-        return FALSE;
+        return false;
 
     const char* pszLine;
     int iCurLayer = -1;
     std::vector<OGROSMComputedAttribute> oAttributes;
 
-    int i;
-
     while((pszLine = CPLReadLine2L(fpConf, -1, NULL)) != NULL)
     {
         if(pszLine[0] == '#')
@@ -3289,7 +3331,7 @@ int OGROSMDataSource::ParseConf(char** papszOpenOptions)
             iCurLayer = -1;
             pszLine ++;
             ((char*)pszLine)[strlen(pszLine)-1] = '\0'; /* Evil but OK */
-            for(i = 0; i < nLayers; i++)
+            for(int i = 0; i < nLayers; i++)
             {
                 if( strcmp(pszLine, papoLayers[i]->GetName()) == 0 )
                 {
@@ -3300,15 +3342,13 @@ int OGROSMDataSource::ParseConf(char** papszOpenOptions)
             if( iCurLayer < 0 )
             {
                 CPLError(CE_Warning, CPLE_AppDefined,
-                         "Layer '%s' mentionned in %s is unknown to the driver",
+                         "Layer '%s' mentioned in %s is unknown to the driver",
                          pszLine, pszFilename);
             }
             continue;
         }
 
-        if( strncmp(pszLine, "closed_ways_are_polygons=",
-                    strlen("closed_ways_are_polygons=")) == 0)
-        {
+        if( STARTS_WITH(pszLine, "closed_ways_are_polygons="))        {
             char** papszTokens = CSLTokenizeString2(pszLine, "=", 0);
             if( CSLCount(papszTokens) == 2)
             {
@@ -3322,39 +3362,39 @@ int OGROSMDataSource::ParseConf(char** papszOpenOptions)
             CSLDestroy(papszTokens);
         }
 
-        else if(strncmp(pszLine, "report_all_nodes=", strlen("report_all_nodes=")) == 0)
+        else if(STARTS_WITH(pszLine, "report_all_nodes="))
         {
             if( strcmp(pszLine + strlen("report_all_nodes="), "no") == 0 )
             {
-                bReportAllNodes = FALSE;
+                bReportAllNodes = false;
             }
             else if( strcmp(pszLine + strlen("report_all_nodes="), "yes") == 0 )
             {
-                bReportAllNodes = TRUE;
+                bReportAllNodes = true;
             }
         }
 
-        else if(strncmp(pszLine, "report_all_ways=", strlen("report_all_ways=")) == 0)
+        else if(STARTS_WITH(pszLine, "report_all_ways="))
         {
             if( strcmp(pszLine + strlen("report_all_ways="), "no") == 0 )
             {
-                bReportAllWays = FALSE;
+                bReportAllWays = false;
             }
             else if( strcmp(pszLine + strlen("report_all_ways="), "yes") == 0 )
             {
-                bReportAllWays = TRUE;
+                bReportAllWays = true;
             }
         }
 
-        else if(strncmp(pszLine, "attribute_name_laundering=", strlen("attribute_name_laundering=")) == 0)
+        else if(STARTS_WITH(pszLine, "attribute_name_laundering="))
         {
             if( strcmp(pszLine + strlen("attribute_name_laundering="), "no") == 0 )
             {
-                bAttributeNameLaundering = FALSE;
+                bAttributeNameLaundering = false;
             }
             else if( strcmp(pszLine + strlen("attribute_name_laundering="), "yes") == 0 )
             {
-                bAttributeNameLaundering = TRUE;
+                bAttributeNameLaundering = true;
             }
         }
 
@@ -3364,24 +3404,24 @@ int OGROSMDataSource::ParseConf(char** papszOpenOptions)
             if( CSLCount(papszTokens) == 2 && strcmp(papszTokens[0], "other_tags") == 0 )
             {
                 if( strcmp(papszTokens[1], "no") == 0 )
-                    papoLayers[iCurLayer]->SetHasOtherTags(FALSE);
+                    papoLayers[iCurLayer]->SetHasOtherTags(false);
                 else if( strcmp(papszTokens[1], "yes") == 0 )
-                    papoLayers[iCurLayer]->SetHasOtherTags(TRUE);
+                    papoLayers[iCurLayer]->SetHasOtherTags(true);
             }
             else if( CSLCount(papszTokens) == 2 && strcmp(papszTokens[0], "all_tags") == 0 )
             {
                 if( strcmp(papszTokens[1], "no") == 0 )
-                    papoLayers[iCurLayer]->SetHasAllTags(FALSE);
+                    papoLayers[iCurLayer]->SetHasAllTags(false);
                 else if( strcmp(papszTokens[1], "yes") == 0 )
-                    papoLayers[iCurLayer]->SetHasAllTags(TRUE);
+                    papoLayers[iCurLayer]->SetHasAllTags(true);
             }
             else if( CSLCount(papszTokens) == 2 && strcmp(papszTokens[0], "osm_id") == 0 )
             {
                 if( strcmp(papszTokens[1], "no") == 0 )
-                    papoLayers[iCurLayer]->SetHasOSMId(FALSE);
+                    papoLayers[iCurLayer]->SetHasOSMId(false);
                 else if( strcmp(papszTokens[1], "yes") == 0 )
                 {
-                    papoLayers[iCurLayer]->SetHasOSMId(TRUE);
+                    papoLayers[iCurLayer]->SetHasOSMId(true);
                     papoLayers[iCurLayer]->AddField("osm_id", OFTString);
 
                     if( iCurLayer == IDX_LYR_MULTIPOLYGONS )
@@ -3391,50 +3431,50 @@ int OGROSMDataSource::ParseConf(char** papszOpenOptions)
              else if( CSLCount(papszTokens) == 2 && strcmp(papszTokens[0], "osm_version") == 0 )
             {
                 if( strcmp(papszTokens[1], "no") == 0 )
-                    papoLayers[iCurLayer]->SetHasVersion(FALSE);
+                    papoLayers[iCurLayer]->SetHasVersion(false);
                 else if( strcmp(papszTokens[1], "yes") == 0 )
                 {
-                    papoLayers[iCurLayer]->SetHasVersion(TRUE);
+                    papoLayers[iCurLayer]->SetHasVersion(true);
                     papoLayers[iCurLayer]->AddField("osm_version", OFTInteger);
                 }
             }
             else if( CSLCount(papszTokens) == 2 && strcmp(papszTokens[0], "osm_timestamp") == 0 )
             {
                 if( strcmp(papszTokens[1], "no") == 0 )
-                    papoLayers[iCurLayer]->SetHasTimestamp(FALSE);
+                    papoLayers[iCurLayer]->SetHasTimestamp(false);
                 else if( strcmp(papszTokens[1], "yes") == 0 )
                 {
-                    papoLayers[iCurLayer]->SetHasTimestamp(TRUE);
+                    papoLayers[iCurLayer]->SetHasTimestamp(true);
                     papoLayers[iCurLayer]->AddField("osm_timestamp", OFTDateTime);
                 }
             }
             else if( CSLCount(papszTokens) == 2 && strcmp(papszTokens[0], "osm_uid") == 0 )
             {
                 if( strcmp(papszTokens[1], "no") == 0 )
-                    papoLayers[iCurLayer]->SetHasUID(FALSE);
+                    papoLayers[iCurLayer]->SetHasUID(false);
                 else if( strcmp(papszTokens[1], "yes") == 0 )
                 {
-                    papoLayers[iCurLayer]->SetHasUID(TRUE);
+                    papoLayers[iCurLayer]->SetHasUID(true);
                     papoLayers[iCurLayer]->AddField("osm_uid", OFTInteger);
                 }
             }
             else if( CSLCount(papszTokens) == 2 && strcmp(papszTokens[0], "osm_user") == 0 )
             {
                 if( strcmp(papszTokens[1], "no") == 0 )
-                    papoLayers[iCurLayer]->SetHasUser(FALSE);
+                    papoLayers[iCurLayer]->SetHasUser(false);
                 else if( strcmp(papszTokens[1], "yes") == 0 )
                 {
-                    papoLayers[iCurLayer]->SetHasUser(TRUE);
+                    papoLayers[iCurLayer]->SetHasUser(true);
                     papoLayers[iCurLayer]->AddField("osm_user", OFTString);
                 }
             }
             else if( CSLCount(papszTokens) == 2 && strcmp(papszTokens[0], "osm_changeset") == 0 )
             {
                 if( strcmp(papszTokens[1], "no") == 0 )
-                    papoLayers[iCurLayer]->SetHasChangeset(FALSE);
+                    papoLayers[iCurLayer]->SetHasChangeset(false);
                 else if( strcmp(papszTokens[1], "yes") == 0 )
                 {
-                    papoLayers[iCurLayer]->SetHasChangeset(TRUE);
+                    papoLayers[iCurLayer]->SetHasChangeset(true);
                     papoLayers[iCurLayer]->AddField("osm_changeset", OFTInteger);
                 }
             }
@@ -3482,8 +3522,8 @@ int OGROSMDataSource::ParseConf(char** papszOpenOptions)
                 CPLString osName(papszTokens[0]);
                 osName.resize(strlen(papszTokens[0]) - 5);
                 const char* pszType = papszTokens[1];
-                int bFound = FALSE;
-                 OGRFieldType eType = OFTString;
+                bool bFound = false;
+                OGRFieldType eType = OFTString;
                 if( EQUAL(pszType, "Integer") )
                     eType = OFTInteger;
                 else if( EQUAL(pszType, "Integer64") )
@@ -3502,7 +3542,7 @@ int OGROSMDataSource::ParseConf(char** papszOpenOptions)
                 {
                     if( oAttributes[i].osName == osName )
                     {
-                        bFound = TRUE;
+                        bFound = true;
                         oAttributes[i].eType = eType;
                         break;
                     }
@@ -3513,7 +3553,7 @@ int OGROSMDataSource::ParseConf(char** papszOpenOptions)
                     if( idx >= 0 )
                     {
                         papoLayers[iCurLayer]->GetLayerDefn()->GetFieldDefn(idx)->SetType(eType);
-                        bFound = TRUE;
+                        bFound = true;
                     }
                 }
                 if( !bFound )
@@ -3550,8 +3590,9 @@ int OGROSMDataSource::ParseConf(char** papszOpenOptions)
                 }
                 if( i == oAttributes.size() )
                 {
-                    CPLError(CE_Warning, CPLE_AppDefined, "Undeclared attribute : %s",
-                             osName.c_str());
+                    CPLError( CE_Warning, CPLE_AppDefined,
+                              "Undeclared attribute : %s",
+                              osName.c_str());
                 }
             }
             CSLDestroy(papszTokens);
@@ -3561,14 +3602,14 @@ int OGROSMDataSource::ParseConf(char** papszOpenOptions)
     if( iCurLayer >= 0 )
         AddComputedAttributes(iCurLayer, oAttributes);
 
-    for(i=0;i<nLayers;i++)
+    for(int i=0;i<nLayers;i++)
     {
         if( papoLayers[i]->HasAllTags() )
         {
             papoLayers[i]->AddField("all_tags", OFTString);
             if( papoLayers[i]->HasOtherTags() )
             {
-                papoLayers[i]->SetHasOtherTags(FALSE);
+                papoLayers[i]->SetHasOtherTags(false);
             }
         }
         else if( papoLayers[i]->HasOtherTags() )
@@ -3577,7 +3618,7 @@ int OGROSMDataSource::ParseConf(char** papszOpenOptions)
 
     VSIFCloseL(fpConf);
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -3612,7 +3653,8 @@ int OGROSMDataSource::ResetReading()
         return FALSE;
     }
 
-    rc = sqlite3_exec( hDB, "DELETE FROM polygons_standalone", NULL, NULL, &pszErrMsg );
+    rc = sqlite3_exec( hDB, "DELETE FROM polygons_standalone", NULL, NULL,
+                       &pszErrMsg );
     if( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -3620,11 +3662,10 @@ int OGROSMDataSource::ResetReading()
         sqlite3_free( pszErrMsg );
         return FALSE;
     }
-    bHasRowInPolygonsStandalone = FALSE;
+    bHasRowInPolygonsStandalone = false;
 
     {
-        int i;
-        for( i = 0; i < nWayFeaturePairs; i++)
+        for( int i = 0; i < nWayFeaturePairs; i++)
         {
             delete pasWayFeaturePairs[i].poFeature;
         }
@@ -3634,7 +3675,7 @@ int OGROSMDataSource::ResetReading()
         nAccumulatedTags = 0;
         nNonRedundantValuesLen = 0;
 
-        for(i=0;i<(int)asKeys.size();i++)
+        for( int i=0;i<static_cast<int>(asKeys.size()); i++ )
         {
             KeyDesc* psKD = asKeys[i];
             CPLFree(psKD->pszK);
@@ -3679,7 +3720,7 @@ int OGROSMDataSource::ResetReading()
         papoLayers[i]->ForceResetReading();
     }
 
-    bStopParsing = FALSE;
+    bStopParsing = false;
 
     return TRUE;
 }
@@ -3688,20 +3729,21 @@ int OGROSMDataSource::ResetReading()
 /*                           ParseNextChunk()                           */
 /************************************************************************/
 
-int OGROSMDataSource::ParseNextChunk(int nIdxLayer)
+bool OGROSMDataSource::ParseNextChunk(int nIdxLayer)
 {
     if( bStopParsing )
-        return FALSE;
+        return false;
 
-    bHasParsedFirstChunk = TRUE;
-    bFeatureAdded = FALSE;
-    while( TRUE )
+    bHasParsedFirstChunk = true;
+    bFeatureAdded = false;
+    while( true )
     {
 #ifdef DEBUG_MEM_USAGE
         static int counter = 0;
         counter ++;
         if ((counter % 1000) == 0)
-            CPLDebug("OSM", "GetMaxTotalAllocs() = " CPL_FRMT_GUIB, (GUIntBig)GetMaxTotalAllocs());
+            CPLDebug("OSM", "GetMaxTotalAllocs() = " CPL_FRMT_GUIB,
+                     static_cast<GUIntBig>(GetMaxTotalAllocs()));
 #endif
 
         OSMRetCode eRet = OSM_ProcessBlock(psParser);
@@ -3715,13 +3757,13 @@ int OGROSMDataSource::ParseNextChunk(int nIdxLayer)
                 ProcessPolygonsStandalone();
 
                 if( !bHasRowInPolygonsStandalone )
-                    bStopParsing = TRUE;
+                    bStopParsing = true;
 
                 if( !bInterleavedReading && !bFeatureAdded &&
                     bHasRowInPolygonsStandalone &&
                     nIdxLayer != IDX_LYR_MULTIPOLYGONS )
                 {
-                    return FALSE;
+                    return false;
                 }
 
                 return bFeatureAdded || bHasRowInPolygonsStandalone;
@@ -3729,11 +3771,12 @@ int OGROSMDataSource::ParseNextChunk(int nIdxLayer)
             else
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
-                         "An error occured during the parsing of data around byte " CPL_FRMT_GUIB,
+                         "An error occurred during the parsing of data "
+                         "around byte " CPL_FRMT_GUIB,
                          OSM_GetBytesRead(psParser));
 
-                bStopParsing = TRUE;
-                return FALSE;
+                bStopParsing = true;
+                return false;
             }
         }
         else
@@ -3741,7 +3784,7 @@ int OGROSMDataSource::ParseNextChunk(int nIdxLayer)
             if( bInMemoryTmpDB )
             {
                 if( !TransferToDiskIfNecesserary() )
-                    return FALSE;
+                    return false;
             }
 
             if( bFeatureAdded )
@@ -3749,20 +3792,20 @@ int OGROSMDataSource::ParseNextChunk(int nIdxLayer)
         }
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                    TransferToDiskIfNecesserary()                     */
 /************************************************************************/
 
-int OGROSMDataSource::TransferToDiskIfNecesserary()
+bool OGROSMDataSource::TransferToDiskIfNecesserary()
 {
     if( bInMemoryNodesFile )
     {
         if( nNodesFileSize / 1024 / 1024 > 3 * nMaxSizeForInMemoryDBInMB / 4 )
         {
-            bInMemoryNodesFile = FALSE;
+            bInMemoryNodesFile = false;
 
             VSIFCloseL(fpNodes);
             fpNodes = NULL;
@@ -3779,8 +3822,8 @@ int OGROSMDataSource::TransferToDiskIfNecesserary()
                          "Cannot copy %s to %s",
                          osNodesFilename.c_str(), osNewTmpDBName.c_str() );
                 VSIUnlink(osNewTmpDBName);
-                bStopParsing = TRUE;
-                return FALSE;
+                bStopParsing = true;
+                return false;
             }
 
             VSIUnlink(osNodesFilename);
@@ -3794,9 +3837,12 @@ int OGROSMDataSource::TransferToDiskIfNecesserary()
                 {
                     VSIFSeekL(fp, 0, SEEK_END);
                     vsi_l_offset nCurSize = VSIFTellL(fp);
-                    GIntBig nNewSize = ((GIntBig)nMaxSizeForInMemoryDBInMB) * 1024 * 1024;
+                    GIntBig nNewSize =
+                        static_cast<GIntBig>(nMaxSizeForInMemoryDBInMB) *
+                        1024 * 1024;
                     CPLPushErrorHandler(CPLQuietErrorHandler);
-                    int bSuccess = VSIFSeekL(fp, (vsi_l_offset) nNewSize, SEEK_SET) == 0;
+                    const bool bSuccess =
+                        VSIFSeekL(fp, (vsi_l_offset) nNewSize, SEEK_SET) == 0;
                     CPLPopErrorHandler();
 
                     if( bSuccess )
@@ -3811,8 +3857,8 @@ int OGROSMDataSource::TransferToDiskIfNecesserary()
             fpNodes = VSIFOpenL(osNodesFilename, "rb+");
             if( fpNodes == NULL )
             {
-                bStopParsing = TRUE;
-                return FALSE;
+                bStopParsing = true;
+                return false;
             }
 
             VSIFSeekL(fpNodes, 0, SEEK_END);
@@ -3840,7 +3886,7 @@ int OGROSMDataSource::TransferToDiskIfNecesserary()
         if( VSIStatL( osTmpDBName, &sStat ) == 0 &&
             sStat.st_size / 1024 / 1024 > nLimitMB )
         {
-            bInMemoryTmpDB = FALSE;
+            bInMemoryTmpDB = false;
 
             CloseDB();
 
@@ -3858,8 +3904,8 @@ int OGROSMDataSource::TransferToDiskIfNecesserary()
                          "Cannot copy %s to %s",
                          osTmpDBName.c_str(), osNewTmpDBName.c_str() );
                 VSIUnlink(osNewTmpDBName);
-                bStopParsing = TRUE;
-                return FALSE;
+                bStopParsing = true;
+                return false;
             }
 
             VSIUnlink(osTmpDBName);
@@ -3878,14 +3924,15 @@ int OGROSMDataSource::TransferToDiskIfNecesserary()
                 CPLError( CE_Failure, CPLE_OpenFailed,
                         "sqlite3_open(%s) failed: %s",
                         osTmpDBName.c_str(), sqlite3_errmsg( hDB ) );
-                bStopParsing = TRUE;
+                bStopParsing = true;
                 CloseDB();
-                return FALSE;
+                return false;
             }
 
             /* On Unix filesystems, you can remove a file even if it */
             /* opened */
-            const char* pszVal = CPLGetConfigOption("OSM_UNLINK_TMPFILE", "YES");
+            const char* pszVal =
+                CPLGetConfigOption("OSM_UNLINK_TMPFILE", "YES");
             if( EQUAL(pszVal, "YES") )
             {
                 CPLPushErrorHandler(CPLQuietErrorHandler);
@@ -3895,21 +3942,21 @@ int OGROSMDataSource::TransferToDiskIfNecesserary()
 
             if( !SetDBOptions() || !CreatePreparedStatements() )
             {
-                bStopParsing = TRUE;
+                bStopParsing = true;
                 CloseDB();
-                return FALSE;
+                return false;
             }
         }
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                           TestCapability()                           */
 /************************************************************************/
 
-int OGROSMDataSource::TestCapability( CPL_UNUSED const char * pszCap )
+int OGROSMDataSource::TestCapability( const char * /* pszCap */ )
 {
     return FALSE;
 }
@@ -3923,8 +3970,8 @@ OGRLayer *OGROSMDataSource::GetLayer( int iLayer )
 {
     if( iLayer < 0 || iLayer >= nLayers )
         return NULL;
-    else
-        return papoLayers[iLayer];
+
+    return papoLayers[iLayer];
 }
 
 /************************************************************************/
@@ -3935,7 +3982,7 @@ OGRErr OGROSMDataSource::GetExtent( OGREnvelope *psExtent )
 {
     if (!bHasParsedFirstChunk)
     {
-        bHasParsedFirstChunk = TRUE;
+        bHasParsedFirstChunk = true;
         OSM_ProcessBlock(psParser);
     }
 
@@ -3979,34 +4026,33 @@ class OGROSMSingleFeatureLayer : public OGRLayer
 /*                    OGROSMSingleFeatureLayer()                        */
 /************************************************************************/
 
-OGROSMSingleFeatureLayer::OGROSMSingleFeatureLayer(  const char* pszLayerName,
-                                                     int nVal )
+OGROSMSingleFeatureLayer::OGROSMSingleFeatureLayer( const char* pszLayerName,
+                                                    int nValIn ) :
+    nVal(nValIn),
+    pszVal(NULL),
+    poFeatureDefn(new OGRFeatureDefn( "SELECT" )),
+    iNextShapeId(0)
 {
-    poFeatureDefn = new OGRFeatureDefn( "SELECT" );
     poFeatureDefn->Reference();
     OGRFieldDefn oField( pszLayerName, OFTInteger );
     poFeatureDefn->AddFieldDefn( &oField );
-
-    iNextShapeId = 0;
-    this->nVal = nVal;
-    pszVal = NULL;
 }
 
 /************************************************************************/
 /*                    OGROSMSingleFeatureLayer()                        */
 /************************************************************************/
 
-OGROSMSingleFeatureLayer::OGROSMSingleFeatureLayer(  const char* pszLayerName,
-                                                     const char *pszVal )
+OGROSMSingleFeatureLayer::OGROSMSingleFeatureLayer( const char* pszLayerName,
+                                                    const char *pszValIn ) :
+    nVal(0),
+    pszVal(CPLStrdup(pszValIn)),
+    poFeatureDefn(new OGRFeatureDefn( "SELECT" )),
+    iNextShapeId(0)
 {
-    poFeatureDefn = new OGRFeatureDefn( "SELECT" );
     poFeatureDefn->Reference();
     OGRFieldDefn oField( pszLayerName, OFTString );
     poFeatureDefn->AddFieldDefn( &oField );
 
-    iNextShapeId = 0;
-    nVal = 0;
-    this->pszVal = CPLStrdup(pszVal);
 }
 
 /************************************************************************/
@@ -4048,11 +4094,11 @@ class OGROSMResultLayerDecorator : public OGRLayerDecorator
 
     public:
         OGROSMResultLayerDecorator(OGRLayer* poLayer,
-                                   CPLString osDSName,
-                                   CPLString osInterestLayers) :
+                                   CPLString osDSNameIn,
+                                   CPLString osInterestLayersIn) :
                                         OGRLayerDecorator(poLayer, TRUE),
-                                        osDSName(osDSName),
-                                        osInterestLayers(osInterestLayers) {}
+                                        osDSName(osDSNameIn),
+                                        osInterestLayers(osInterestLayersIn) {}
 
         virtual GIntBig     GetFeatureCount( int bForce = TRUE )
         {
@@ -4079,7 +4125,8 @@ OGRLayer * OGROSMDataSource::ExecuteSQL( const char *pszSQLCommand,
     if (strcmp(pszSQLCommand, "GetBytesRead()") == 0)
     {
         char szVal[64];
-        sprintf(szVal, CPL_FRMT_GUIB, OSM_GetBytesRead(psParser));
+        snprintf( szVal, sizeof(szVal), CPL_FRMT_GUIB,
+                  OSM_GetBytesRead(psParser) );
         return new OGROSMSingleFeatureLayer( "GetBytesRead", szVal );
     }
 
@@ -4093,19 +4140,20 @@ OGRLayer * OGROSMDataSource::ExecuteSQL( const char *pszSQLCommand,
 /* -------------------------------------------------------------------- */
 /*      Special SET interest_layers = command                           */
 /* -------------------------------------------------------------------- */
-    if (strncmp(pszSQLCommand, "SET interest_layers =", 21) == 0)
+    if (STARTS_WITH(pszSQLCommand, "SET interest_layers ="))
     {
-        char** papszTokens = CSLTokenizeString2(pszSQLCommand + 21, ",", CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES);
-        int i;
-
-        for(i=0; i < nLayers; i++)
+        char** papszTokens =
+            CSLTokenizeString2(pszSQLCommand + 21, ",",
+                               CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES);
+        for( int i=0; i < nLayers; i++ )
         {
             papoLayers[i]->SetDeclareInterest(FALSE);
         }
 
-        for(i=0; papszTokens[i] != NULL; i++)
+        for( int i=0; papszTokens[i] != NULL; i++ )
         {
-            OGROSMLayer* poLayer = (OGROSMLayer*) GetLayerByName(papszTokens[i]);
+            OGROSMLayer* poLayer = reinterpret_cast<OGROSMLayer *>(
+                GetLayerByName(papszTokens[i]) );
             if( poLayer != NULL )
             {
                 poLayer->SetDeclareInterest(TRUE);
@@ -4121,20 +4169,20 @@ OGRLayer * OGROSMDataSource::ExecuteSQL( const char *pszSQLCommand,
             if( CPLGetConfigOption("OSM_INDEX_POINTS", NULL) == NULL )
             {
                 CPLDebug("OSM", "Disabling indexing of nodes");
-                bIndexPoints = FALSE;
+                bIndexPoints = false;
             }
             if( CPLGetConfigOption("OSM_USE_POINTS_INDEX", NULL) == NULL )
             {
-                bUsePointsIndex = FALSE;
+                bUsePointsIndex = false;
             }
             if( CPLGetConfigOption("OSM_INDEX_WAYS", NULL) == NULL )
             {
                 CPLDebug("OSM", "Disabling indexing of ways");
-                bIndexWays = FALSE;
+                bIndexWays = false;
             }
             if( CPLGetConfigOption("OSM_USE_WAYS_INDEX", NULL) == NULL )
             {
-                bUseWaysIndex = FALSE;
+                bUseWaysIndex = false;
             }
         }
         else if( papoLayers[IDX_LYR_LINES]->IsUserInterested() &&
@@ -4145,11 +4193,11 @@ OGRLayer * OGROSMDataSource::ExecuteSQL( const char *pszSQLCommand,
             if( CPLGetConfigOption("OSM_INDEX_WAYS", NULL) == NULL )
             {
                 CPLDebug("OSM", "Disabling indexing of ways");
-                bIndexWays = FALSE;
+                bIndexWays = false;
             }
             if( CPLGetConfigOption("OSM_USE_WAYS_INDEX", NULL) == NULL )
             {
-                bUseWaysIndex = FALSE;
+                bUseWaysIndex = false;
             }
         }
 
@@ -4162,14 +4210,15 @@ OGRLayer * OGROSMDataSource::ExecuteSQL( const char *pszSQLCommand,
         pszSQLCommand ++;
 
     /* Try to analyse the SQL command to get the interest table */
-    if( EQUALN(pszSQLCommand, "SELECT", 5) )
+    if( STARTS_WITH_CI(pszSQLCommand, "SELECT") )
     {
-        int bLayerAlreadyAdded = FALSE;
+        bool bLayerAlreadyAdded = false;
         CPLString osInterestLayers = "SET interest_layers =";
 
         if( pszDialect != NULL && EQUAL(pszDialect, "SQLITE") )
         {
-            std::set<LayerDesc> oSetLayers = OGRSQLiteGetReferencedLayers(pszSQLCommand);
+            std::set<LayerDesc> oSetLayers =
+                OGRSQLiteGetReferencedLayers(pszSQLCommand);
             std::set<LayerDesc>::iterator oIter = oSetLayers.begin();
             for(; oIter != oSetLayers.end(); ++oIter)
             {
@@ -4177,7 +4226,7 @@ OGRLayer * OGROSMDataSource::ExecuteSQL( const char *pszSQLCommand,
                 if( oLayerDesc.osDSName.size() == 0 )
                 {
                     if( bLayerAlreadyAdded ) osInterestLayers += ",";
-                    bLayerAlreadyAdded = TRUE;
+                    bLayerAlreadyAdded = true;
                     osInterestLayers += oLayerDesc.osLayerName;
                 }
             }
@@ -4190,18 +4239,20 @@ OGRLayer * OGROSMDataSource::ExecuteSQL( const char *pszSQLCommand,
             CPLErr eErr = sSelectInfo.preparse( pszSQLCommand );
             CPLPopErrorHandler();
 
-            if( eErr == CPLE_None )
+            if( eErr == CE_None )
             {
                 swq_select* pCurSelect = &sSelectInfo;
                 while(pCurSelect != NULL)
                 {
-                    for( int iTable = 0; iTable < pCurSelect->table_count; iTable++ )
+                    for( int iTable = 0; iTable < pCurSelect->table_count;
+                         iTable++ )
                     {
-                        swq_table_def *psTableDef = pCurSelect->table_defs + iTable;
+                        swq_table_def *psTableDef =
+                            pCurSelect->table_defs + iTable;
                         if( psTableDef->data_source == NULL )
                         {
                             if( bLayerAlreadyAdded ) osInterestLayers += ",";
-                            bLayerAlreadyAdded = TRUE;
+                            bLayerAlreadyAdded = true;
                             osInterestLayers += psTableDef->table_name;
                         }
                     }
@@ -4230,8 +4281,8 @@ OGRLayer * OGROSMDataSource::ExecuteSQL( const char *pszSQLCommand,
 
             /* Run the request */
             poResultSetLayer = OGRDataSource::ExecuteSQL( pszSQLCommand,
-                                                            poSpatialFilter,
-                                                            pszDialect );
+                                                          poSpatialFilter,
+                                                          pszDialect );
 
             /* If the user explicitly run a COUNT() request, then do it ! */
             if( poResultSetLayer )
@@ -4241,7 +4292,7 @@ OGRLayer * OGROSMDataSource::ExecuteSQL( const char *pszSQLCommand,
                     poResultSetLayer = new OGROSMResultLayerDecorator(
                                 poResultSetLayer, GetName(), osInterestLayers);
                 }
-                bIsFeatureCountEnabled = TRUE;
+                bIsFeatureCountEnabled = true;
             }
 
             return poResultSetLayer;
@@ -4264,7 +4315,7 @@ void OGROSMDataSource::ReleaseResultSet( OGRLayer * poLayer )
     {
         poResultSetLayer = NULL;
 
-        bIsFeatureCountEnabled = FALSE;
+        bIsFeatureCountEnabled = false;
 
         /* Restore backup'ed optimization parameters */
         for(int i=0; i < nLayers; i++)
@@ -4293,7 +4344,7 @@ int OGROSMDataSource::IsInterleavedReading()
 {
     if( bInterleavedReading < 0 )
     {
-        bInterleavedReading = CSLTestBoolean(
+        bInterleavedReading = CPLTestBool(
                         CPLGetConfigOption("OGR_INTERLEAVED_READING", "NO"));
         CPLDebug("OSM", "OGR_INTERLEAVED_READING = %d", bInterleavedReading);
     }
diff --git a/ogr/ogrsf_frmts/osm/ogrosmdriver.cpp b/ogr/ogrsf_frmts/osm/ogrosmdriver.cpp
index f9ab442..6963a76 100644
--- a/ogr/ogrsf_frmts/osm/ogrosmdriver.cpp
+++ b/ogr/ogrsf_frmts/osm/ogrosmdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrosmdriver.cpp 29242 2015-05-24 10:59:41Z rouault $
+ * $Id: ogrosmdriver.cpp 33039 2016-01-18 17:04:21Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGROSMDriver class.
@@ -34,7 +34,7 @@
 
 extern "C" void CPL_DLL RegisterOGROSM();
 
-CPL_CVSID("$Id: ogrosmdriver.cpp 29242 2015-05-24 10:59:41Z rouault $");
+CPL_CVSID("$Id: ogrosmdriver.cpp 33039 2016-01-18 17:04:21Z rouault $");
 
 /************************************************************************/
 /*                      OGROSMDriverIdentify()                          */
@@ -43,17 +43,26 @@ CPL_CVSID("$Id: ogrosmdriver.cpp 29242 2015-05-24 10:59:41Z rouault $");
 static int OGROSMDriverIdentify( GDALOpenInfo* poOpenInfo )
 
 {
-    if (poOpenInfo->fpL == NULL )
-        return FALSE;
-    const char* pszExt = CPLGetExtension(poOpenInfo->pszFilename);
-    if( EQUAL(pszExt, "pbf") ||
-        EQUAL(pszExt, "osm") )
-        return TRUE;
-    if( EQUALN(poOpenInfo->pszFilename, "/vsicurl_streaming/", strlen("/vsicurl_streaming/")) ||
-        strcmp(poOpenInfo->pszFilename, "/vsistdin/") == 0 ||
-        strcmp(poOpenInfo->pszFilename, "/dev/stdin/") == 0 )
-        return -1;
-    return FALSE;
+    if (poOpenInfo->fpL == NULL || poOpenInfo->nHeaderBytes == 0)
+        return GDAL_IDENTIFY_FALSE;
+
+    if( strstr((const char*)poOpenInfo->pabyHeader, "<osm") != NULL )
+    {
+        return GDAL_IDENTIFY_TRUE;
+    }
+
+    const int nLimitI =
+        poOpenInfo->nHeaderBytes - static_cast<int>(strlen("OSMHeader"));
+    for(int i = 0; i < nLimitI; i++)
+    {
+        if( memcmp( poOpenInfo->pabyHeader + i, "OSMHeader",
+                    strlen("OSMHeader") ) == 0 )
+        {
+            return GDAL_IDENTIFY_TRUE;
+        }
+    }
+
+    return GDAL_IDENTIFY_FALSE;
 }
 
 /************************************************************************/
@@ -68,7 +77,7 @@ static GDALDataset *OGROSMDriverOpen( GDALOpenInfo* poOpenInfo )
     if( OGROSMDriverIdentify(poOpenInfo) == FALSE )
         return NULL;
 
-    OGROSMDataSource   *poDS = new OGROSMDataSource();
+    OGROSMDataSource *poDS = new OGROSMDataSource();
 
     if( !poDS->Open( poOpenInfo->pszFilename, poOpenInfo->papszOpenOptions ) )
     {
@@ -85,37 +94,33 @@ static GDALDataset *OGROSMDriverOpen( GDALOpenInfo* poOpenInfo )
 
 void RegisterOGROSM()
 {
-    if (! GDAL_CHECK_VERSION("OGR/OSM driver"))
+    if( !GDAL_CHECK_VERSION("OGR/OSM driver") )
         return;
-    GDALDriver  *poDriver;
 
-    if( GDALGetDriverByName( "OSM" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    if( GDALGetDriverByName( "OSM" ) != NULL )
+        return;
 
-        poDriver->SetDescription( "OSM" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "OpenStreetMap XML and PBF" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "osm pbf" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_osm.html" );
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetDescription( "OSM" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "OpenStreetMap XML and PBF" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "osm pbf" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_osm.html" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
 "<OpenOptionList>"
 "  <Option name='CONFIG_FILE' type='string' description='Configuration filename.'/>"
 "  <Option name='USE_CUSTOM_INDEXING' type='boolean' description='Whether to enable custom indexing.' default='YES'/>"
 "  <Option name='COMPRESS_NODES' type='boolean' description='Whether to compress nodes in temporary DB.' default='NO'/>"
 "  <Option name='MAX_TMPFILE_SIZE' type='int' description='Maximum size in MB of in-memory temporary file. If it exceeds that value, it will go to disk' default='100'/>"
-"  <Option name='INTERLEAVED_READING' type='boolean' description='Whether to enable interleveaved reading.' default='NO'/>"
+"  <Option name='INTERLEAVED_READING' type='boolean' description='Whether to enable interleaved reading.' default='NO'/>"
 "</OpenOptionList>" );
 
-        poDriver->pfnOpen = OGROSMDriverOpen;
-        poDriver->pfnIdentify = OGROSMDriverIdentify;
+    poDriver->pfnOpen = OGROSMDriverOpen;
+    poDriver->pfnIdentify = OGROSMDriverIdentify;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
 
diff --git a/ogr/ogrsf_frmts/osm/ogrosmlayer.cpp b/ogr/ogrsf_frmts/osm/ogrosmlayer.cpp
index d598c9d..bd85e82 100644
--- a/ogr/ogrsf_frmts/osm/ogrosmlayer.cpp
+++ b/ogr/ogrsf_frmts/osm/ogrosmlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrosmlayer.cpp 28900 2015-04-14 09:40:34Z rouault $
+ * $Id: ogrosmlayer.cpp 33332 2016-02-02 23:01:31Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGROSMLayer class
@@ -33,7 +33,7 @@
 #include "cpl_time.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrosmlayer.cpp 28900 2015-04-14 09:40:34Z rouault $");
+CPL_CVSID("$Id: ogrosmlayer.cpp 33332 2016-02-02 23:01:31Z rouault $");
 
 #define SWITCH_THRESHOLD   10000
 #define MAX_THRESHOLD      100000
@@ -45,47 +45,41 @@ CPL_CVSID("$Id: ogrosmlayer.cpp 28900 2015-04-14 09:40:34Z rouault $");
 /************************************************************************/
 
 
-OGROSMLayer::OGROSMLayer(OGROSMDataSource* poDS, int nIdxLayer, const char* pszName )
+OGROSMLayer::OGROSMLayer( OGROSMDataSource* poDSIn, int nIdxLayerIn,
+                          const char* pszName ) :
+    poDS(poDSIn),
+    nIdxLayer(nIdxLayerIn),
+    poFeatureDefn(new OGRFeatureDefn( pszName )),
+    poSRS(new OGRSpatialReference()),
+    nFeatureCount(0),
+    bResetReadingAllowed(false),
+    nFeatureArraySize(0),
+    nFeatureArrayMaxSize(0),
+    nFeatureArrayIndex(0),
+    papoFeatures(NULL),
+    bHasOSMId(false),
+    nIndexOSMId(-1),
+    nIndexOSMWayId(-1),
+    bHasVersion(false),
+    bHasTimestamp(false),
+    bHasUID(false),
+    bHasUser(false),
+    bHasChangeset(false),
+    bHasOtherTags(true),
+    nIndexOtherTags(-1),
+    bHasAllTags(false),
+    nIndexAllTags(-1),
+    bHasWarnedTooManyFeatures(false),
+    pszAllTags(static_cast<char *>(CPLMalloc(ALLTAGS_LENGTH))),
+    bHasWarnedAllTagsTruncated(false),
+    bUserInterested(true)
 {
-    this->poDS = poDS;
-    this->nIdxLayer = nIdxLayer;
-
-    poFeatureDefn = new OGRFeatureDefn( pszName );
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
 
-    poSRS = new OGRSpatialReference();
     poSRS->SetWellKnownGeogCS("WGS84");
     if( poFeatureDefn->GetGeomFieldCount() != 0 )
         poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
-
-    nFeatureArraySize = 0;
-    nFeatureArrayMaxSize = 0;
-    nFeatureArrayIndex = 0;
-    papoFeatures = NULL;
-    
-    nFeatureCount = 0;
-
-    bHasOSMId = FALSE;
-    nIndexOSMId = -1;
-    nIndexOSMWayId = -1;
-    bHasVersion = FALSE;
-    bHasTimestamp = FALSE;
-    bHasUID = FALSE;
-    bHasUser = FALSE;
-    bHasChangeset = FALSE;
-    bHasOtherTags = TRUE;
-    nIndexOtherTags = -1;
-    bHasAllTags = FALSE;
-    nIndexAllTags = -1;
-
-    bResetReadingAllowed = FALSE;
-    bHasWarnedTooManyFeatures = FALSE;
-
-    pszAllTags = (char*)CPLMalloc(ALLTAGS_LENGTH);
-    bHasWarnedAllTagsTruncated = FALSE;
-
-    bUserInterested = TRUE;
 }
 
 /************************************************************************/
@@ -94,33 +88,31 @@ OGROSMLayer::OGROSMLayer(OGROSMDataSource* poDS, int nIdxLayer, const char* pszN
 
 OGROSMLayer::~OGROSMLayer()
 {
-    int i;
-    
     poFeatureDefn->Release();
-    
+
     if (poSRS)
         poSRS->Release();
 
-    for(i=0;i<nFeatureArraySize;i++)
+    for( int i=0; i<nFeatureArraySize; i++ )
     {
         if (papoFeatures[i])
             delete papoFeatures[i];
     }
 
-    for(i=0;i<(int)apszNames.size();i++)
+    for( int i=0; i<static_cast<int>(apszNames.size()); i++ )
         CPLFree(apszNames[i]);
 
-    for(i=0;i<(int)apszUnsignificantKeys.size();i++)
+    for( int i=0; i<static_cast<int>(apszUnsignificantKeys.size()); i++ )
         CPLFree(apszUnsignificantKeys[i]);
 
-    for(i=0;i<(int)apszIgnoreKeys.size();i++)
+    for( int i=0; i<static_cast<int>(apszIgnoreKeys.size()); i++ )
         CPLFree(apszIgnoreKeys[i]);
-    
-    for(i=0; i<(int)oComputedAttributes.size();i++)
+
+    for( int i=0; i<static_cast<int>(oComputedAttributes.size()); i++ )
     {
         sqlite3_finalize(oComputedAttributes[i].hStmt);
     }
-    
+
     CPLFree(pszAllTags);
 
     CPLFree(papoFeatures);
@@ -152,7 +144,7 @@ void OGROSMLayer::ForceResetReading()
     nFeatureArrayIndex = 0;
     nFeatureArraySize = 0;
     nFeatureCount = 0;
-    bResetReadingAllowed = FALSE;
+    bResetReadingAllowed = false;
 }
 
 /************************************************************************/
@@ -180,9 +172,11 @@ OGRErr OGROSMLayer::SetAttributeFilter( const char* pszAttrQuery )
     }
     else
     {
-        CPLError(CE_Warning, CPLE_AppDefined, "The new attribute filter will "
-                 "not be taken into account immediately. It is advised to "
-                 "set attribute filters for all needed layers, before reading *any* layer");
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "The new attribute filter will "
+                  "not be taken into account immediately. It is advised to "
+                  "set attribute filters for all needed layers, before "
+                  "reading *any* layer" );
     }
 
     return OGRERR_NONE;
@@ -206,7 +200,7 @@ GIntBig OGROSMLayer::GetFeatureCount( int bForce )
 
 OGRFeature *OGROSMLayer::GetNextFeature()
 {
-    bResetReadingAllowed = TRUE;
+    bResetReadingAllowed = true;
 
     if ( nFeatureArraySize == 0)
     {
@@ -270,7 +264,7 @@ OGRFeature *OGROSMLayer::GetNextFeature()
         }
         else
         {
-            while(TRUE)
+            while( true )
             {
                 int bRet = poDS->ParseNextChunk(nIdxLayer);
                 if (nFeatureArraySize != 0)
@@ -282,13 +276,13 @@ OGRFeature *OGROSMLayer::GetNextFeature()
     }
 
     OGRFeature* poFeature = papoFeatures[nFeatureArrayIndex];
-    
+
     papoFeatures[nFeatureArrayIndex] = NULL;
     nFeatureArrayIndex++;
 
     if ( nFeatureArrayIndex == nFeatureArraySize)
         nFeatureArrayIndex = nFeatureArraySize = 0;
-    
+
     return poFeature;
 }
 
@@ -323,7 +317,7 @@ int  OGROSMLayer::AddToArray(OGRFeature* poFeature, int bCheckFeatureThreshold)
                     "Use OGR_INTERLEAVED_READING=YES mode",
                     GetName());
         }
-        bHasWarnedTooManyFeatures = TRUE;
+        bHasWarnedTooManyFeatures = true;
         return FALSE;
     }
 
@@ -331,7 +325,7 @@ int  OGROSMLayer::AddToArray(OGRFeature* poFeature, int bCheckFeatureThreshold)
     {
         nFeatureArrayMaxSize = nFeatureArrayMaxSize + nFeatureArrayMaxSize / 2 + 128;
         CPLDebug("OSM", "For layer %s, new max size is %d", GetName(), nFeatureArrayMaxSize);
-        OGRFeature** papoNewFeatures = (OGRFeature**)VSIRealloc(papoFeatures,
+        OGRFeature** papoNewFeatures = (OGRFeature**)VSI_REALLOC_VERBOSE(papoFeatures,
                                 nFeatureArrayMaxSize * sizeof(OGRFeature*));
         if (papoNewFeatures == NULL)
         {
@@ -343,7 +337,7 @@ int  OGROSMLayer::AddToArray(OGRFeature* poFeature, int bCheckFeatureThreshold)
         papoFeatures = papoNewFeatures;
     }
     papoFeatures[nFeatureArraySize ++] = poFeature;
-    
+
     return TRUE;
 }
 
@@ -377,7 +371,7 @@ int  OGROSMLayer::AddFeature(OGRFeature* poFeature,
     OGRGeometry* poGeom = poFeature->GetGeometryRef();
     if (poGeom)
         poGeom->assignSpatialReference( poSRS );
-    
+
     if( (m_poFilterGeom == NULL
         || FilterGeometry( poFeature->GetGeometryRef() ) )
         && (m_poAttrQuery == NULL || bAttrFilterAlreadyEvaluated
@@ -396,7 +390,7 @@ int  OGROSMLayer::AddFeature(OGRFeature* poFeature,
         delete poFeature;
         return TRUE;
     }
-    
+
     if (pbFilteredOut)
         *pbFilteredOut = FALSE;
     return TRUE;
@@ -407,7 +401,7 @@ int  OGROSMLayer::AddFeature(OGRFeature* poFeature,
 /************************************************************************/
 
 OGRErr OGROSMLayer::GetExtent( OGREnvelope *psExtent,
-                               CPL_UNUSED int bForce )
+                               int /* bForce */ )
 {
     if (poDS->GetExtent(psExtent) == OGRERR_NONE)
         return OGRERR_NONE;
@@ -425,20 +419,20 @@ const char* OGROSMLayer::GetLaunderedFieldName(const char* pszName)
     if( poDS->DoesAttributeNameLaundering()  &&
         strchr(pszName, ':') != NULL )
     {
-        size_t i;
-        for( i = 0;
-             pszName[i] != '\0' && i < sizeof(szLaunderedFieldName) - 1; i++ )
+        for( size_t i = 0;
+             i < sizeof(szLaunderedFieldName) - 1 && pszName[i] != '\0';
+             i++ )
         {
             if( pszName[i] == ':' )
                 szLaunderedFieldName[i] = '_';
             else
                 szLaunderedFieldName[i] = pszName[i];
         }
-        szLaunderedFieldName[i] = '\0';
+        szLaunderedFieldName[sizeof(szLaunderedFieldName) - 1] = '\0';
         return szLaunderedFieldName;
     }
-    else
-        return pszName;
+
+    return pszName;
 }
 
 /************************************************************************/
@@ -479,8 +473,8 @@ int OGROSMLayer::GetFieldIndex(const char* pszName)
         oMapFieldNameToIndex.find(pszName);
     if( oIter != oMapFieldNameToIndex.end() )
         return oIter->second;
-    else
-        return -1;
+
+    return -1;
 }
 
 /************************************************************************/
@@ -489,7 +483,7 @@ int OGROSMLayer::GetFieldIndex(const char* pszName)
 
 int OGROSMLayer::AddInOtherOrAllTags(const char* pszK)
 {
-    int bAddToOtherTags = FALSE;
+    bool bAddToOtherTags = false;
 
     if ( aoSetIgnoreKeys.find(pszK) == aoSetIgnoreKeys.end() )
     {
@@ -503,7 +497,7 @@ int OGROSMLayer::AddInOtherOrAllTags(const char* pszK)
             pszColon[1] = chBackup;
         }
         else
-            bAddToOtherTags = TRUE;
+            bAddToOtherTags = true;
     }
 
     return bAddToOtherTags;
@@ -515,13 +509,11 @@ int OGROSMLayer::AddInOtherOrAllTags(const char* pszK)
 
 static int OGROSMFormatForHSTORE(const char* pszV, char* pszAllTags)
 {
-    int k;
-
     int nAllTagsOff = 0;
 
     pszAllTags[nAllTagsOff++] = '"';
 
-    for(k=0;pszV[k] != '\0'; k++)
+    for( int k=0; pszV[k] != '\0'; k++ )
     {
         if( pszV[k] == '"' || pszV[k] == '\\' )
             pszAllTags[nAllTagsOff++] = '\\';
@@ -550,7 +542,7 @@ void OGROSMLayer::SetFieldsFromTags(OGRFeature* poFeature,
         if( bHasOSMId )
         {
             char szID[32];
-            sprintf(szID, CPL_FRMT_GIB, nID );
+            snprintf(szID, sizeof(szID), CPL_FRMT_GIB, nID );
             poFeature->SetField(nIndexOSMId, szID);
         }
     }
@@ -561,7 +553,7 @@ void OGROSMLayer::SetFieldsFromTags(OGRFeature* poFeature,
         if( nIndexOSMWayId >= 0 )
         {
             char szID[32];
-            sprintf(szID, CPL_FRMT_GIB, nID );
+            snprintf(szID, sizeof(szID), CPL_FRMT_GIB, nID );
             poFeature->SetField(nIndexOSMWayId, szID );
         }
     }
@@ -590,7 +582,7 @@ void OGROSMLayer::SetFieldsFromTags(OGRFeature* poFeature,
                                 brokendown.tm_mday,
                                 brokendown.tm_hour,
                                 brokendown.tm_min,
-                                brokendown.tm_sec,
+                                static_cast<float>(brokendown.tm_sec),
                                 0);
         }
 
@@ -614,7 +606,7 @@ void OGROSMLayer::SetFieldsFromTags(OGRFeature* poFeature,
         const char* pszK = pasTags[j].pszK;
         const char* pszV = pasTags[j].pszV;
         int nIndex = GetFieldIndex(pszK);
-        if( nIndex >= 0 )
+        if( nIndex >= 0 && nIndex != nIndexOSMId )
         {
             poFeature->SetField(nIndex, pszV);
             if( nIndexAllTags < 0 )
@@ -633,20 +625,22 @@ void OGROSMLayer::SetFieldsFromTags(OGRFeature* poFeature,
                     1 >= ALLTAGS_LENGTH - 1 )
                 {
                     if( !bHasWarnedAllTagsTruncated )
-                        CPLDebug("OSM", "all_tags/other_tags field truncated for feature " CPL_FRMT_GIB, nID);
-                    bHasWarnedAllTagsTruncated = TRUE;
+                        CPLDebug( "OSM",
+                                  "all_tags/other_tags field truncated for "
+                                  "feature " CPL_FRMT_GIB, nID);
+                    bHasWarnedAllTagsTruncated = true;
                     continue;
                 }
 
                 if( nAllTagsOff )
                     pszAllTags[nAllTagsOff++] = ',';
-                
+
                 nAllTagsOff += OGROSMFormatForHSTORE(pszK,
                                                      pszAllTags + nAllTagsOff);
 
                 pszAllTags[nAllTagsOff++] = '=';
                 pszAllTags[nAllTagsOff++] = '>';
-                
+
                 nAllTagsOff += OGROSMFormatForHSTORE(pszV,
                                                      pszAllTags + nAllTagsOff);
             }
@@ -674,7 +668,7 @@ void OGROSMLayer::SetFieldsFromTags(OGRFeature* poFeature,
     for(size_t i=0; i<oComputedAttributes.size();i++)
     {
         const OGROSMComputedAttribute& oAttr = oComputedAttributes[i];
-        for(size_t j=0;j<oAttr.anIndexToBind.size();j++)
+        for(int j=0;j<static_cast<int>(oAttr.anIndexToBind.size());j++)
         {
             if( oAttr.anIndexToBind[j] >= 0 )
             {
@@ -684,7 +678,9 @@ void OGROSMLayer::SetFieldsFromTags(OGRFeature* poFeature,
                 }
                 else
                 {
-                    OGRFieldType eType = poFeatureDefn->GetFieldDefn(oAttr.anIndexToBind[j])->GetType();
+                    OGRFieldType eType =
+                        poFeatureDefn->GetFieldDefn(oAttr.anIndexToBind[j])->
+                          GetType();
                     if( eType == OFTInteger )
                         sqlite3_bind_int( oAttr.hStmt, j + 1,
                                           poFeature->GetFieldAsInteger(oAttr.anIndexToBind[j]) );
@@ -702,7 +698,7 @@ void OGROSMLayer::SetFieldsFromTags(OGRFeature* poFeature,
             }
             else
             {
-                int bTagFound = FALSE;
+                bool bTagFound = false;
                 for(unsigned int k = 0; k < nTags; k++)
                 {
                     const char* pszK = pasTags[k].pszK;
@@ -710,7 +706,7 @@ void OGROSMLayer::SetFieldsFromTags(OGRFeature* poFeature,
                     if( strcmp(pszK, oAttr.aosAttrToBind[j]) == 0 )
                     {
                         sqlite3_bind_text( oAttr.hStmt, j + 1, pszV, -1, SQLITE_TRANSIENT);
-                        bTagFound = TRUE;
+                        bTagFound = true;
                         break;
                     }
                 }
@@ -824,7 +820,7 @@ void OGROSMLayer::AddComputedAttribute(const char* pszName,
     std::vector<CPLString> aosAttrToBind;
     std::vector<int> anIndexToBind;
     size_t nStartSearch = 0;
-    while(TRUE)
+    while( true )
     {
         size_t nPos = osSQL.find("[", nStartSearch);
         if( nPos == std::string::npos )
@@ -844,7 +840,7 @@ void OGROSMLayer::AddComputedAttribute(const char* pszName,
             anIndexToBind.push_back(poFeatureDefn->GetFieldIndex(osAttr));
         }
     }
-    while(TRUE)
+    while( true )
     {
         size_t nPos = osSQL.find("\\");
         if( nPos == std::string::npos || nPos == osSQL.size() - 1 )
diff --git a/ogr/ogrsf_frmts/osm/osm2osm.c b/ogr/ogrsf_frmts/osm/osm2osm.c
index ced8032..1da6ed3 100644
--- a/ogr/ogrsf_frmts/osm/osm2osm.c
+++ b/ogr/ogrsf_frmts/osm/osm2osm.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: osm2osm.c 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: osm2osm.c 33138 2016-01-24 11:18:11Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
@@ -48,7 +48,7 @@
 #define DAYSPERLYEAR    366
 
 #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
-#define LEAPS_THRU_END_OF(y)    ((y) / 4 - (y) / 100 + (y) / 400)
+#define LEAPS_THROUGH_END_OF(y)    ((y) / 4 - (y) / 100 + (y) / 400)
 
 static const int mon_lengths[2][MONSPERYEAR] = {
   {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
@@ -107,8 +107,8 @@ struct tm * myCPLUnixTimeToYMDHMS(GIntBig unixTime, struct tm* pRet)
         if (days < 0)
             --newy;
         days -= (newy - y) * DAYSPERNYEAR +
-            LEAPS_THRU_END_OF(newy - 1) -
-            LEAPS_THRU_END_OF(y - 1);
+            LEAPS_THROUGH_END_OF(newy - 1) -
+            LEAPS_THROUGH_END_OF(y - 1);
         y = newy;
     }
     pRet->tm_year = (int) (y - TM_YEAR_BASE);
diff --git a/ogr/ogrsf_frmts/osm/osm_parser.cpp b/ogr/ogrsf_frmts/osm/osm_parser.cpp
index afb5a63..ec6353f 100644
--- a/ogr/ogrsf_frmts/osm/osm_parser.cpp
+++ b/ogr/ogrsf_frmts/osm/osm_parser.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: osm_parser.cpp 28435 2015-02-07 14:35:34Z rouault $
+ * $Id: osm_parser.cpp 33138 2016-01-24 11:18:11Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
@@ -45,7 +45,7 @@
 
 #define XML_BUFSIZE 64*1024
 
-CPL_CVSID("$Id: osm_parser.cpp 28435 2015-02-07 14:35:34Z rouault $");
+CPL_CVSID("$Id: osm_parser.cpp 33138 2016-01-24 11:18:11Z rouault $");
 
 /************************************************************************/
 /*                            INIT_INFO()                               */
@@ -56,7 +56,7 @@ CPL_CVSID("$Id: osm_parser.cpp 28435 2015-02-07 14:35:34Z rouault $");
     sInfo.nChangeset = 0; \
     sInfo.nVersion = 0; \
     sInfo.nUID = 0; \
-    sInfo.bTimeStampIsStr = 0; \
+    sInfo.bTimeStampIsStr = false; \
     sInfo.pszUserSID = NULL;
 /*    \    sInfo.nVisible = 1; */
 
@@ -97,23 +97,23 @@ struct _OSMContext
 
 #ifdef HAVE_EXPAT
     XML_Parser     hXMLParser;
-    int            bEOF;
-    int            bStopParsing;
-    int            bHasFoundFeature;
+    bool           bEOF;
+    bool           bStopParsing;
+    bool           bHasFoundFeature;
     int            nWithoutEventCounter;
     int            nDataHandlerCounter;
 
     unsigned int   nStrLength;
     unsigned int   nTags;
 
-    int            bInNode;
-    int            bInWay;
-    int            bInRelation;
+    bool           bInNode;
+    bool           bInWay;
+    bool           bInRelation;
 
     OSMWay         sWay;
     OSMRelation    sRelation;
 
-    int            bTryToFetchBounds;
+    bool           bTryToFetchBounds;
 #endif
 
     VSILFILE      *fp;
@@ -144,7 +144,7 @@ struct _OSMContext
 
 typedef enum
 {
-    BLOB_UNKNOW,
+    BLOB_UNKNOWN,
     BLOB_OSMHEADER,
     BLOB_OSMDATA
 } BlobType;
@@ -154,7 +154,7 @@ int ReadBlobHeader(GByte* pabyData, GByte* pabyDataLimit,
                    unsigned int* pnBlobSize, BlobType* peBlobType)
 {
     *pnBlobSize = 0;
-    *peBlobType = BLOB_UNKNOW;
+    *peBlobType = BLOB_UNKNOWN;
 
     while(pabyData < pabyDataLimit)
     {
@@ -384,7 +384,7 @@ int ReadStringTable(GByte* pabyData, GByte* pabyDataLimit,
         int* panStrOffNew;
         psCtxt->nStrAllocated = MAX(psCtxt->nStrAllocated * 2,
                                           (unsigned int)(pabyDataLimit - pabyData));
-        panStrOffNew = (int*) VSIRealloc(
+        panStrOffNew = (int*) VSI_REALLOC_VERBOSE(
             panStrOff, psCtxt->nStrAllocated * sizeof(int));
         if( panStrOffNew == NULL )
             GOTO_END_ERROR;
@@ -402,7 +402,7 @@ int ReadStringTable(GByte* pabyData, GByte* pabyDataLimit,
             unsigned int nDataLength;
             READ_SIZE(pabyData, pabyDataLimit, nDataLength);
 
-            panStrOff[nStrCount ++] = pabyData - (GByte*)pszStrBuf;
+            panStrOff[nStrCount ++] = static_cast<int>(pabyData - (GByte*)pszStrBuf);
             pbSaved = &pabyData[nDataLength];
 
             pabyData += nDataLength;
@@ -487,7 +487,7 @@ int ReadDenseNodes(GByte* pabyData, GByte* pabyDataLimit,
                 OSMNode* pasNodesNew;
                 psCtxt->nNodesAllocated = MAX(psCtxt->nNodesAllocated * 2,
                                                  nSize);
-                pasNodesNew = (OSMNode*) VSIRealloc(
+                pasNodesNew = (OSMNode*) VSI_REALLOC_VERBOSE(
                     psCtxt->pasNodes, psCtxt->nNodesAllocated * sizeof(OSMNode));
                 if( pasNodesNew == NULL )
                     GOTO_END_ERROR;
@@ -502,7 +502,7 @@ int ReadDenseNodes(GByte* pabyData, GByte* pabyDataLimit,
         {
             unsigned int nSize;
             GByte* pabyDataNewLimit;
- 
+
             READ_SIZE(pabyData, pabyDataLimit, nSize);
 
             /* Inline reading of DenseInfo structure */
@@ -565,7 +565,7 @@ int ReadDenseNodes(GByte* pabyData, GByte* pabyDataLimit,
 
                 psCtxt->nTagsAllocated = MAX(
                     psCtxt->nTagsAllocated * 2, nSize);
-                pasTagsNew = (OSMTag*) VSIRealloc(
+                pasTagsNew = (OSMTag*) VSI_REALLOC_VERBOSE(
                     psCtxt->pasTags,
                     psCtxt->nTagsAllocated * sizeof(OSMTag));
                 if( pasTagsNew == NULL )
@@ -656,9 +656,9 @@ int ReadDenseNodes(GByte* pabyData, GByte* pabyDataLimit,
             /* if( pabyDataVisible )
                 READ_VARINT32(pabyDataVisible, pabyDataLimit, nVisible); */
 
-            if( pabyDataKeyVal )
+            if( pabyDataKeyVal != NULL && pasTags != NULL )
             {
-                while (TRUE)
+                while( true )
                 {
                     unsigned int nKey, nVal;
                     READ_VARUINT32(pabyDataKeyVal, pabyDataLimit, nKey);
@@ -679,21 +679,27 @@ int ReadDenseNodes(GByte* pabyData, GByte* pabyDataLimit,
                 }
             }
 
-            if( nTags > nKVIndexStart )
+            if( pasTags != NULL && nTags > nKVIndexStart )
                 pasNodes[nNodes].pasTags = pasTags + nKVIndexStart;
             else
                 pasNodes[nNodes].pasTags = NULL;
             pasNodes[nNodes].nTags = nTags - nKVIndexStart;
 
             pasNodes[nNodes].nID = nID;
-            pasNodes[nNodes].dfLat = .000000001 * (psCtxt->nLatOffset + (psCtxt->nGranularity * nLat));
-            pasNodes[nNodes].dfLon = .000000001 * (psCtxt->nLonOffset + (psCtxt->nGranularity * nLon));
-            pasNodes[nNodes].sInfo.bTimeStampIsStr = FALSE;
+            pasNodes[nNodes].dfLat = .000000001 * (psCtxt->nLatOffset + ((double)psCtxt->nGranularity * nLat));
+            pasNodes[nNodes].dfLon = .000000001 * (psCtxt->nLonOffset + ((double)psCtxt->nGranularity * nLon));
+            if( pasNodes[nNodes].dfLon < -180 || pasNodes[nNodes].dfLon > 180 ||
+                pasNodes[nNodes].dfLat < -90 || pasNodes[nNodes].dfLat > 90 )
+                GOTO_END_ERROR;
+            pasNodes[nNodes].sInfo.bTimeStampIsStr = false;
             pasNodes[nNodes].sInfo.ts.nTimeStamp = nTimeStamp;
             pasNodes[nNodes].sInfo.nChangeset = nChangeset;
             pasNodes[nNodes].sInfo.nVersion = nVersion;
             pasNodes[nNodes].sInfo.nUID = nUID;
-            pasNodes[nNodes].sInfo.pszUserSID = pszStrBuf + panStrOff[nUserSID];
+            if( nUserSID >= nStrCount )
+                pasNodes[nNodes].sInfo.pszUserSID = "";
+            else
+                pasNodes[nNodes].sInfo.pszUserSID = pszStrBuf + panStrOff[nUserSID];
             /* pasNodes[nNodes].sInfo.nVisible = nVisible; */
             nNodes ++;
             /* printf("nLat = " CPL_FRMT_GIB "\n", nLat); printf("nLon = " CPL_FRMT_GIB "\n", nLon); */
@@ -789,12 +795,16 @@ end_error:
 /*                             ReadNode()                               */
 /************************************************************************/
 
+/* From https://github.com/openstreetmap/osmosis/blob/master/osmosis-osm-binary/src/main/protobuf/osmformat.proto */
+/* The one advertized in http://wiki.openstreetmap.org/wiki/PBF_Format and */
+/* used previously seem wrong/old-dated */
+
 #define NODE_IDX_ID      1
-#define NODE_IDX_LAT     7
-#define NODE_IDX_LON     8
-#define NODE_IDX_KEYS    9
-#define NODE_IDX_VALS    10
-#define NODE_IDX_INFO    11
+#define NODE_IDX_LAT     8
+#define NODE_IDX_LON     9
+#define NODE_IDX_KEYS    2
+#define NODE_IDX_VALS    3
+#define NODE_IDX_INFO    4
 
 static
 int ReadNode(GByte* pabyData, GByte* pabyDataLimit,
@@ -823,13 +833,13 @@ int ReadNode(GByte* pabyData, GByte* pabyDataLimit,
         {
             GIntBig nLat;
             READ_VARSINT64_NOCHECK(pabyData, pabyDataLimit, nLat);
-            sNode.dfLat = .000000001 * (psCtxt->nLatOffset + (psCtxt->nGranularity * nLat));
+            sNode.dfLat = .000000001 * (psCtxt->nLatOffset + ((double)psCtxt->nGranularity * nLat));
         }
         else if (nKey == MAKE_KEY(NODE_IDX_LON, WT_VARINT))
         {
             GIntBig nLon;
             READ_VARSINT64_NOCHECK(pabyData, pabyDataLimit, nLon);
-            sNode.dfLon = .000000001 * (psCtxt->nLonOffset + (psCtxt->nGranularity * nLon));
+            sNode.dfLon = .000000001 * (psCtxt->nLonOffset + ((double)psCtxt->nGranularity * nLon));
         }
         else if (nKey == MAKE_KEY(NODE_IDX_KEYS, WT_DATA))
         {
@@ -845,7 +855,7 @@ int ReadNode(GByte* pabyData, GByte* pabyDataLimit,
 
                 psCtxt->nTagsAllocated = MAX(
                     psCtxt->nTagsAllocated * 2, nSize);
-                pasTagsNew = (OSMTag*) VSIRealloc(
+                pasTagsNew = (OSMTag*) VSI_REALLOC_VERBOSE(
                     psCtxt->pasTags,
                     psCtxt->nTagsAllocated * sizeof(OSMTag));
                 if( pasTagsNew == NULL )
@@ -856,15 +866,15 @@ int ReadNode(GByte* pabyData, GByte* pabyDataLimit,
             pabyDataNewLimit = pabyData + nSize;
             while (pabyData < pabyDataNewLimit)
             {
-                unsigned int nKey;
-                READ_VARUINT32(pabyData, pabyDataNewLimit, nKey);
+                unsigned int nKey2;
+                READ_VARUINT32(pabyData, pabyDataNewLimit, nKey2);
 
-                if (nKey >= psCtxt->nStrCount)
+                if (nKey2 >= psCtxt->nStrCount)
                     GOTO_END_ERROR;
 
                 psCtxt->pasTags[sNode.nTags].pszK = psCtxt->pszStrBuf +
-                                              psCtxt->panStrOff[nKey];
-                psCtxt->pasTags[sNode.nTags].pszV = NULL;
+                                              psCtxt->panStrOff[nKey2];
+                psCtxt->pasTags[sNode.nTags].pszV = "";
                 sNode.nTags ++;
             }
             if (pabyData != pabyDataNewLimit)
@@ -907,6 +917,10 @@ int ReadNode(GByte* pabyData, GByte* pabyDataLimit,
         }
     }
 
+    if( sNode.dfLon < -180 || sNode.dfLon > 180 ||
+        sNode.dfLat < -90 || sNode.dfLat > 90 )
+        GOTO_END_ERROR;
+
     if( pabyData != pabyDataLimit )
         GOTO_END_ERROR;
 
@@ -971,7 +985,7 @@ int ReadWay(GByte* pabyData, GByte* pabyDataLimit,
 
                 psCtxt->nTagsAllocated = MAX(
                     psCtxt->nTagsAllocated * 2, nSize);
-                pasTagsNew = (OSMTag*) VSIRealloc(
+                pasTagsNew = (OSMTag*) VSI_REALLOC_VERBOSE(
                     psCtxt->pasTags,
                     psCtxt->nTagsAllocated * sizeof(OSMTag));
                 if( pasTagsNew == NULL )
@@ -982,15 +996,15 @@ int ReadWay(GByte* pabyData, GByte* pabyDataLimit,
             pabyDataNewLimit = pabyData + nSize;
             while (pabyData < pabyDataNewLimit)
             {
-                unsigned int nKey;
-                READ_VARUINT32(pabyData, pabyDataNewLimit, nKey);
+                unsigned int nKey2;
+                READ_VARUINT32(pabyData, pabyDataNewLimit, nKey2);
 
-                if (nKey >= psCtxt->nStrCount)
+                if (nKey2 >= psCtxt->nStrCount)
                     GOTO_END_ERROR;
 
                 psCtxt->pasTags[sWay.nTags].pszK = psCtxt->pszStrBuf +
-                                                   psCtxt->panStrOff[nKey];
-                psCtxt->pasTags[sWay.nTags].pszV = NULL;
+                                                   psCtxt->panStrOff[nKey2];
+                psCtxt->pasTags[sWay.nTags].pszV = "";
                 sWay.nTags ++;
             }
             if (pabyData != pabyDataNewLimit)
@@ -1041,7 +1055,7 @@ int ReadWay(GByte* pabyData, GByte* pabyDataLimit,
                 GIntBig* panNodeRefsNew;
                 psCtxt->nNodeRefsAllocated =
                     MAX(psCtxt->nNodeRefsAllocated * 2, nSize);
-                panNodeRefsNew = (GIntBig*) VSIRealloc(
+                panNodeRefsNew = (GIntBig*) VSI_REALLOC_VERBOSE(
                         psCtxt->panNodeRefs,
                         psCtxt->nNodeRefsAllocated * sizeof(GIntBig));
                 if( panNodeRefsNew == NULL )
@@ -1135,7 +1149,7 @@ int ReadRelation(GByte* pabyData, GByte* pabyDataLimit,
 
                 psCtxt->nTagsAllocated = MAX(
                     psCtxt->nTagsAllocated * 2, nSize);
-                pasTagsNew = (OSMTag*) VSIRealloc(
+                pasTagsNew = (OSMTag*) VSI_REALLOC_VERBOSE(
                     psCtxt->pasTags,
                     psCtxt->nTagsAllocated * sizeof(OSMTag));
                 if( pasTagsNew == NULL )
@@ -1146,15 +1160,15 @@ int ReadRelation(GByte* pabyData, GByte* pabyDataLimit,
             pabyDataNewLimit = pabyData + nSize;
             while (pabyData < pabyDataNewLimit)
             {
-                unsigned int nKey;
-                READ_VARUINT32(pabyData, pabyDataNewLimit, nKey);
+                unsigned int nKey2;
+                READ_VARUINT32(pabyData, pabyDataNewLimit, nKey2);
 
-                if (nKey >= psCtxt->nStrCount)
+                if (nKey2 >= psCtxt->nStrCount)
                     GOTO_END_ERROR;
 
                 psCtxt->pasTags[sRelation.nTags].pszK = psCtxt->pszStrBuf +
-                                                        psCtxt->panStrOff[nKey];
-                psCtxt->pasTags[sRelation.nTags].pszV = NULL;
+                                                        psCtxt->panStrOff[nKey2];
+                psCtxt->pasTags[sRelation.nTags].pszV = "";
                 sRelation.nTags ++;
             }
             if (pabyData != pabyDataNewLimit)
@@ -1204,7 +1218,7 @@ int ReadRelation(GByte* pabyData, GByte* pabyDataLimit,
                 OSMMember* pasMembersNew;
                 psCtxt->nMembersAllocated =
                     MAX(psCtxt->nMembersAllocated * 2, nSize);
-                pasMembersNew = (OSMMember*) VSIRealloc(
+                pasMembersNew = (OSMMember*) VSI_REALLOC_VERBOSE(
                         psCtxt->pasMembers,
                         psCtxt->nMembersAllocated * sizeof(OSMMember));
                 if( pasMembersNew == NULL )
@@ -1388,6 +1402,8 @@ int ReadPrimitiveBlock(GByte* pabyData, GByte* pabyDataLimit,
         if (nKey == MAKE_KEY(PRIMITIVEBLOCK_IDX_GRANULARITY, WT_VARINT))
         {
             READ_VARINT32(pabyData, pabyDataLimit, psCtxt->nGranularity);
+            if( psCtxt->nGranularity <= 0 )
+                GOTO_END_ERROR;
         }
         else if (nKey == MAKE_KEY(PRIMITIVEBLOCK_IDX_DATE_GRANULARITY, WT_VARINT))
         {
@@ -1427,7 +1443,7 @@ int ReadPrimitiveBlock(GByte* pabyData, GByte* pabyDataLimit,
 
             /* Dirty little trick */
             /* ReadStringTable() will over-write the byte after the */
-            /* StringTable message with a NUL charachter, so we backup */
+            /* StringTable message with a NUL character, so we backup */
             /* it to be able to restore it just before issuing the next */
             /* READ_FIELD_KEY. Then we will re-NUL it to have valid */
             /* NUL terminated strings */
@@ -1540,9 +1556,14 @@ int ReadBlob(GByte* pabyData, unsigned int nDataSize, BlobType eType,
                 if (nUncompressedSize > psCtxt->nUncompressedAllocated)
                 {
                     GByte* pabyUncompressedNew;
-                    psCtxt->nUncompressedAllocated =
-                        MAX(psCtxt->nUncompressedAllocated * 2, nUncompressedSize);
-                    pabyUncompressedNew = (GByte*)VSIRealloc(psCtxt->pabyUncompressed,
+                    if( psCtxt->nUncompressedAllocated <= INT_MAX )
+                        psCtxt->nUncompressedAllocated =
+                            MAX(psCtxt->nUncompressedAllocated * 2, nUncompressedSize);
+                    else
+                        psCtxt->nUncompressedAllocated = nUncompressedSize;
+                    if( psCtxt->nUncompressedAllocated > 0xFFFFFFFFU - EXTRA_BYTES )
+                        GOTO_END_ERROR;
+                    pabyUncompressedNew = (GByte*)VSI_REALLOC_VERBOSE(psCtxt->pabyUncompressed,
                                         psCtxt->nUncompressedAllocated + EXTRA_BYTES);
                     if( pabyUncompressedNew == NULL )
                         GOTO_END_ERROR;
@@ -1590,46 +1611,42 @@ end_error:
 /*                        EmptyNotifyNodesFunc()                        */
 /************************************************************************/
 
-static void EmptyNotifyNodesFunc(CPL_UNUSED unsigned int nNodes,
-                                 CPL_UNUSED OSMNode* pasNodes,
-                                 CPL_UNUSED OSMContext* psCtxt,
-                                 CPL_UNUSED void* user_data)
-{
-}
+static void EmptyNotifyNodesFunc(unsigned int /* nNodes */,
+                                 OSMNode* /* pasNodes */,
+                                 OSMContext* /* psCtxt */,
+                                 void* /* user_data */)
+{}
 
 
 /************************************************************************/
 /*                         EmptyNotifyWayFunc()                         */
 /************************************************************************/
 
-static void EmptyNotifyWayFunc(CPL_UNUSED OSMWay* psWay,
-                               CPL_UNUSED OSMContext* psCtxt,
-                               CPL_UNUSED void* user_data)
-{
-}
+static void EmptyNotifyWayFunc(OSMWay* /* psWay */,
+                               OSMContext* /* psCtxt */,
+                               void* /* user_data */)
+{}
 
 /************************************************************************/
 /*                       EmptyNotifyRelationFunc()                      */
 /************************************************************************/
 
-static void EmptyNotifyRelationFunc(CPL_UNUSED OSMRelation* psRelation,
-                                    CPL_UNUSED OSMContext* psCtxt,
-                                    CPL_UNUSED void* user_data)
-{
-}
+static void EmptyNotifyRelationFunc( OSMRelation* /* psRelation */,
+                                     OSMContext* /* psCtxt */,
+                                     void* /* user_data */)
+{}
 
 /************************************************************************/
 /*                         EmptyNotifyBoundsFunc()                      */
 /************************************************************************/
 
-static void EmptyNotifyBoundsFunc( CPL_UNUSED double dfXMin,
-                                   CPL_UNUSED double dfYMin,
-                                   CPL_UNUSED double dfXMax,
-                                   CPL_UNUSED double dfYMax,
-                                   CPL_UNUSED OSMContext* psCtxt,
-                                   CPL_UNUSED void* user_data )
-{
-}
+static void EmptyNotifyBoundsFunc( double /* dfXMin */,
+                                   double /* dfYMin */,
+                                   double /* dfXMax */,
+                                   double /* dfYMax */,
+                                   OSMContext* /*psCtxt */,
+                                   void * /* user_data */)
+{}
 
 #ifdef HAVE_EXPAT
 
@@ -1677,8 +1694,9 @@ static GIntBig OSM_Atoi64( const char *pszString )
 /*                      OSM_XML_startElementCbk()                       */
 /************************************************************************/
 
-static void XMLCALL OSM_XML_startElementCbk(void *pUserData, const char *pszName,
-                                            const char **ppszAttr)
+static void XMLCALL OSM_XML_startElementCbk( void *pUserData,
+                                             const char *pszName,
+                                             const char **ppszAttr)
 {
     OSMContext* psCtxt = (OSMContext*) pUserData;
     const char** ppszIter = ppszAttr;
@@ -1694,7 +1712,7 @@ static void XMLCALL OSM_XML_startElementCbk(void *pUserData, const char *pszName
         {
             int nCountCoords = 0;
 
-            psCtxt->bTryToFetchBounds = FALSE;
+            psCtxt->bTryToFetchBounds = false;
 
             if( ppszIter )
             {
@@ -1749,8 +1767,8 @@ static void XMLCALL OSM_XML_startElementCbk(void *pUserData, const char *pszName
     if( !psCtxt->bInNode && !psCtxt->bInWay && !psCtxt->bInRelation &&
         strcmp(pszName, "node") == 0 )
     {
-        psCtxt->bInNode = TRUE;
-        psCtxt->bTryToFetchBounds = FALSE;
+        psCtxt->bInNode = true;
+        psCtxt->bTryToFetchBounds = false;
 
         psCtxt->nStrLength = 0;
         psCtxt->pszStrBuf[0] = '\0';
@@ -1794,7 +1812,7 @@ static void XMLCALL OSM_XML_startElementCbk(void *pUserData, const char *pszName
                 else if( strcmp(ppszIter[0], "timestamp") == 0 )
                 {
                     psCtxt->pasNodes[0].sInfo.ts.pszTimeStamp = OSM_AddString(psCtxt, ppszIter[1]);
-                    psCtxt->pasNodes[0].sInfo.bTimeStampIsStr = 1;
+                    psCtxt->pasNodes[0].sInfo.bTimeStampIsStr = true;
                 }
                 ppszIter += 2;
             }
@@ -1804,7 +1822,7 @@ static void XMLCALL OSM_XML_startElementCbk(void *pUserData, const char *pszName
     else if( !psCtxt->bInNode && !psCtxt->bInWay && !psCtxt->bInRelation &&
              strcmp(pszName, "way") == 0 )
     {
-        psCtxt->bInWay = TRUE;
+        psCtxt->bInWay = true;
 
         psCtxt->nStrLength = 0;
         psCtxt->pszStrBuf[0] = '\0';
@@ -1840,7 +1858,7 @@ static void XMLCALL OSM_XML_startElementCbk(void *pUserData, const char *pszName
                 else if( strcmp(ppszIter[0], "timestamp") == 0 )
                 {
                     psCtxt->sWay.sInfo.ts.pszTimeStamp = OSM_AddString(psCtxt, ppszIter[1]);
-                    psCtxt->sWay.sInfo.bTimeStampIsStr = 1;
+                    psCtxt->sWay.sInfo.bTimeStampIsStr = true;
                 }
                 ppszIter += 2;
             }
@@ -1850,7 +1868,7 @@ static void XMLCALL OSM_XML_startElementCbk(void *pUserData, const char *pszName
     else if( !psCtxt->bInNode && !psCtxt->bInWay && !psCtxt->bInRelation &&
              strcmp(pszName, "relation") == 0 )
     {
-        psCtxt->bInRelation = TRUE;
+        psCtxt->bInRelation = true;
 
         psCtxt->nStrLength = 0;
         psCtxt->pszStrBuf[0] = '\0';
@@ -1886,7 +1904,7 @@ static void XMLCALL OSM_XML_startElementCbk(void *pUserData, const char *pszName
                 else if( strcmp(ppszIter[0], "timestamp") == 0 )
                 {
                     psCtxt->sRelation.sInfo.ts.pszTimeStamp = OSM_AddString(psCtxt, ppszIter[1]);
-                    psCtxt->sRelation.sInfo.bTimeStampIsStr = 1;
+                    psCtxt->sRelation.sInfo.bTimeStampIsStr = true;
 
                 }
                 ppszIter += 2;
@@ -1924,7 +1942,7 @@ static void XMLCALL OSM_XML_startElementCbk(void *pUserData, const char *pszName
             OSMMember* pasMembersNew;
             int nMembersAllocated =
                 MAX(psCtxt->nMembersAllocated * 2, psCtxt->sRelation.nMembers + 1);
-            pasMembersNew = (OSMMember*) VSIRealloc(
+            pasMembersNew = (OSMMember*) VSI_REALLOC_VERBOSE(
                     psCtxt->pasMembers,
                     nMembersAllocated * sizeof(OSMMember));
             if( pasMembersNew == NULL )
@@ -2029,13 +2047,23 @@ static void XMLCALL OSM_XML_endElementCbk(void *pUserData, const char *pszName)
 
     if( psCtxt->bInNode && strcmp(pszName, "node") == 0 )
     {
-        psCtxt->pasNodes[0].nTags = psCtxt->nTags;
-        psCtxt->pasNodes[0].pasTags = psCtxt->pasTags;
-
-        psCtxt->pfnNotifyNodes(1, psCtxt->pasNodes, psCtxt, psCtxt->user_data);
+        if( psCtxt->pasNodes[0].dfLon < -180 || psCtxt->pasNodes[0].dfLon > 180 ||
+            psCtxt->pasNodes[0].dfLat < -90 || psCtxt->pasNodes[0].dfLat > 90 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Invalid lon=%f lat=%f",
+                     psCtxt->pasNodes[0].dfLon,
+                     psCtxt->pasNodes[0].dfLat);
+        }
+        else
+        {
+            psCtxt->pasNodes[0].nTags = psCtxt->nTags;
+            psCtxt->pasNodes[0].pasTags = psCtxt->pasTags;
 
-        psCtxt->bHasFoundFeature = TRUE;
+            psCtxt->pfnNotifyNodes(1, psCtxt->pasNodes, psCtxt, psCtxt->user_data);
 
+            psCtxt->bHasFoundFeature = true;
+        }
         psCtxt->bInNode = FALSE;
     }
 
@@ -2049,7 +2077,7 @@ static void XMLCALL OSM_XML_endElementCbk(void *pUserData, const char *pszName)
 
         psCtxt->pfnNotifyWay(&(psCtxt->sWay), psCtxt, psCtxt->user_data);
 
-        psCtxt->bHasFoundFeature = TRUE;
+        psCtxt->bHasFoundFeature = true;
 
         psCtxt->bInWay = FALSE;
     }
@@ -2064,20 +2092,20 @@ static void XMLCALL OSM_XML_endElementCbk(void *pUserData, const char *pszName)
 
         psCtxt->pfnNotifyRelation(&(psCtxt->sRelation), psCtxt, psCtxt->user_data);
 
-        psCtxt->bHasFoundFeature = TRUE;
+        psCtxt->bHasFoundFeature = true;
 
-        psCtxt->bInRelation = FALSE;
+        psCtxt->bInRelation = false;
     }
 }
 /************************************************************************/
 /*                           dataHandlerCbk()                           */
 /************************************************************************/
 
-static void XMLCALL OSM_XML_dataHandlerCbk(void *pUserData,
-                                           CPL_UNUSED const char *data,
-                                           CPL_UNUSED int nLen)
+static void XMLCALL OSM_XML_dataHandlerCbk( void *pUserData,
+                                            const char * /* data */,
+                                            int /* nLen */)
 {
-    OSMContext* psCtxt = (OSMContext*) pUserData;
+    OSMContext* psCtxt = static_cast<OSMContext *>(pUserData);
 
     if (psCtxt->bStopParsing) return;
 
@@ -2089,7 +2117,7 @@ static void XMLCALL OSM_XML_dataHandlerCbk(void *pUserData,
         CPLError(CE_Failure, CPLE_AppDefined,
                  "File probably corrupted (million laugh pattern)");
         XML_StopParser(psCtxt->hXMLParser, XML_FALSE);
-        psCtxt->bStopParsing = TRUE;
+        psCtxt->bStopParsing = true;
         return;
     }
 }
@@ -2105,7 +2133,7 @@ static OSMRetCode XML_ProcessBlock(OSMContext* psCtxt)
     if( psCtxt->bStopParsing )
         return OSM_ERROR;
 
-    psCtxt->bHasFoundFeature = FALSE;
+    psCtxt->bHasFoundFeature = false;
     psCtxt->nWithoutEventCounter = 0;
 
     do
@@ -2120,7 +2148,7 @@ static OSMRetCode XML_ProcessBlock(OSMContext* psCtxt)
 
         psCtxt->nBytesRead += nLen;
 
-        psCtxt->bEOF = VSIFEofL(psCtxt->fp);
+        psCtxt->bEOF = CPL_TO_BOOL(VSIFEofL(psCtxt->fp));
         eErr = XML_Parse(psCtxt->hXMLParser, (const char*) psCtxt->pabyBlob,
                          nLen, psCtxt->bEOF );
 
@@ -2132,18 +2160,18 @@ static OSMRetCode XML_ProcessBlock(OSMContext* psCtxt)
                      XML_ErrorString(XML_GetErrorCode(psCtxt->hXMLParser)),
                      (int)XML_GetCurrentLineNumber(psCtxt->hXMLParser),
                      (int)XML_GetCurrentColumnNumber(psCtxt->hXMLParser));
-            psCtxt->bStopParsing = TRUE;
+            psCtxt->bStopParsing = true;
         }
         psCtxt->nWithoutEventCounter ++;
     } while (!psCtxt->bEOF && !psCtxt->bStopParsing &&
-             psCtxt->bHasFoundFeature == FALSE &&
+             !psCtxt->bHasFoundFeature &&
              psCtxt->nWithoutEventCounter < 10);
 
     if (psCtxt->nWithoutEventCounter == 10)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Too much data inside one element. File probably corrupted");
-        psCtxt->bStopParsing = TRUE;
+        psCtxt->bStopParsing = true;
     }
 
     return psCtxt->bStopParsing ? OSM_ERROR : psCtxt->bEOF ? OSM_EOF : OSM_OK;
@@ -2162,20 +2190,18 @@ OSMContext* OSM_Open( const char* pszFilename,
                       NotifyBoundsFunc pfnNotifyBounds,
                       void* user_data )
 {
-    OSMContext* psCtxt;
-    GByte abyHeader[1024];
-    int nRead;
-    VSILFILE* fp;
-    int i;
-    int bPBF = FALSE;
 
-    fp = VSIFOpenL(pszFilename, "rb");
+    VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
     if (fp == NULL)
         return NULL;
 
-    nRead = (int)VSIFReadL(abyHeader, 1, sizeof(abyHeader)-1, fp);
+    GByte abyHeader[1024];
+    int nRead = static_cast<int>(
+        VSIFReadL(abyHeader, 1, sizeof(abyHeader)-1, fp));
     abyHeader[nRead] = '\0';
 
+    bool bPBF = false;
+
     if( strstr((const char*)abyHeader, "<osm") != NULL )
     {
         /* OSM XML */
@@ -2188,8 +2214,8 @@ OSMContext* OSM_Open( const char* pszFilename,
     }
     else
     {
-        int nLimitI = nRead - strlen("OSMHeader");
-        for(i = 0; i < nLimitI; i++)
+        const int nLimitI = nRead - static_cast<int>(strlen("OSMHeader"));
+        for( int i = 0; i < nLimitI; i++)
         {
             if( memcmp(abyHeader + i, "OSMHeader", strlen("OSMHeader") ) == 0 )
             {
@@ -2206,7 +2232,8 @@ OSMContext* OSM_Open( const char* pszFilename,
 
     VSIFSeekL(fp, 0, SEEK_SET);
 
-    psCtxt = (OSMContext*) VSIMalloc(sizeof(OSMContext));
+    OSMContext* psCtxt = static_cast<OSMContext *>(
+        VSI_MALLOC_VERBOSE(sizeof(OSMContext)) );
     if (psCtxt == NULL)
     {
         VSIFCloseL(fp);
@@ -2239,7 +2266,7 @@ OSMContext* OSM_Open( const char* pszFilename,
         psCtxt->nBlobSizeAllocated = XML_BUFSIZE;
 
         psCtxt->nStrAllocated = 65536;
-        psCtxt->pszStrBuf = (char*) VSIMalloc(psCtxt->nStrAllocated);
+        psCtxt->pszStrBuf = (char*) VSI_MALLOC_VERBOSE(psCtxt->nStrAllocated);
         if( psCtxt->pszStrBuf )
             psCtxt->pszStrBuf[0] = '\0';
 
@@ -2250,21 +2277,21 @@ OSMContext* OSM_Open( const char* pszFilename,
                               OSM_XML_endElementCbk);
         XML_SetCharacterDataHandler(psCtxt->hXMLParser, OSM_XML_dataHandlerCbk);
 
-        psCtxt->bTryToFetchBounds = TRUE;
+        psCtxt->bTryToFetchBounds = true;
 
         psCtxt->nNodesAllocated = 1;
-        psCtxt->pasNodes = (OSMNode*) VSIMalloc(sizeof(OSMNode) * psCtxt->nNodesAllocated);
+        psCtxt->pasNodes = (OSMNode*) VSI_MALLOC_VERBOSE(sizeof(OSMNode) * psCtxt->nNodesAllocated);
 
         psCtxt->nTagsAllocated = 256;
-        psCtxt->pasTags = (OSMTag*) VSIMalloc(sizeof(OSMTag) * psCtxt->nTagsAllocated);
+        psCtxt->pasTags = (OSMTag*) VSI_MALLOC_VERBOSE(sizeof(OSMTag) * psCtxt->nTagsAllocated);
 
         /* 300 is the recommended value, but there are files with more than 2000 so we should be able */
         /* to realloc over that value */
         psCtxt->nMembersAllocated = 2000;
-        psCtxt->pasMembers = (OSMMember*) VSIMalloc(sizeof(OSMMember) * psCtxt->nMembersAllocated);
+        psCtxt->pasMembers = (OSMMember*) VSI_MALLOC_VERBOSE(sizeof(OSMMember) * psCtxt->nMembersAllocated);
 
         psCtxt->nNodeRefsAllocated = 2000;
-        psCtxt->panNodeRefs = (GIntBig*) VSIMalloc(sizeof(GIntBig) * psCtxt->nNodeRefsAllocated);
+        psCtxt->panNodeRefs = (GIntBig*) VSI_MALLOC_VERBOSE(sizeof(GIntBig) * psCtxt->nNodeRefsAllocated);
 
         if( psCtxt->pszStrBuf == NULL ||
             psCtxt->pasNodes == NULL ||
@@ -2279,7 +2306,7 @@ OSMContext* OSM_Open( const char* pszFilename,
     }
 #endif
 
-    psCtxt->pabyBlob = (GByte*)VSIMalloc(psCtxt->nBlobSizeAllocated);
+    psCtxt->pabyBlob = (GByte*)VSI_MALLOC_VERBOSE(psCtxt->nBlobSizeAllocated);
     if( psCtxt->pabyBlob == NULL )
     {
         OSM_Close(psCtxt);
@@ -2339,16 +2366,16 @@ void OSM_ResetReading( OSMContext* psCtxt )
                               OSM_XML_startElementCbk,
                               OSM_XML_endElementCbk);
         XML_SetCharacterDataHandler(psCtxt->hXMLParser, OSM_XML_dataHandlerCbk);
-        psCtxt->bEOF = FALSE;
-        psCtxt->bStopParsing = FALSE;
+        psCtxt->bEOF = false;
+        psCtxt->bStopParsing = false;
         psCtxt->nStrLength = 0;
         psCtxt->pszStrBuf[0] = '\0';
         psCtxt->nTags = 0;
 
-        psCtxt->bTryToFetchBounds = TRUE;
-        psCtxt->bInNode = FALSE;
+        psCtxt->bTryToFetchBounds = true;
+        psCtxt->bInNode = false;
         psCtxt->bInWay = FALSE;
-        psCtxt->bInRelation = FALSE;
+        psCtxt->bInRelation = false;
     }
 #endif
 }
@@ -2384,7 +2411,7 @@ static OSMRetCode PBF_ProcessBlock(OSMContext* psCtxt)
 
     memset(psCtxt->pabyBlob + nHeaderSize, 0, EXTRA_BYTES);
     nRet = ReadBlobHeader(psCtxt->pabyBlob, psCtxt->pabyBlob + nHeaderSize, &nBlobSize, &eType);
-    if (!nRet || eType == BLOB_UNKNOW)
+    if (!nRet || eType == BLOB_UNKNOWN)
         GOTO_END_ERROR;
 
     if (nBlobSize > 64*1024*1024)
@@ -2393,7 +2420,7 @@ static OSMRetCode PBF_ProcessBlock(OSMContext* psCtxt)
     {
         GByte* pabyBlobNew;
         psCtxt->nBlobSizeAllocated = MAX(psCtxt->nBlobSizeAllocated * 2, nBlobSize);
-        pabyBlobNew = (GByte*)VSIRealloc(psCtxt->pabyBlob,
+        pabyBlobNew = (GByte*)VSI_REALLOC_VERBOSE(psCtxt->pabyBlob,
                                         psCtxt->nBlobSizeAllocated + EXTRA_BYTES);
         if( pabyBlobNew == NULL )
             GOTO_END_ERROR;
diff --git a/ogr/ogrsf_frmts/osm/osm_parser.h b/ogr/ogrsf_frmts/osm/osm_parser.h
index bd9fea5..03ae4a2 100644
--- a/ogr/ogrsf_frmts/osm/osm_parser.h
+++ b/ogr/ogrsf_frmts/osm/osm_parser.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: osm_parser.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: osm_parser.h 31777 2015-11-26 14:14:41Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OSM_PARSER_H_INCLUDED
-#define _OSM_PARSER_H_INCLUDED
+#ifndef OSM_PARSER_H_INCLUDED
+#define OSM_PARSER_H_INCLUDED
 
 #include "cpl_port.h"
 /* typedef long long GIntBig; */
@@ -130,4 +130,4 @@ void OSM_Close( OSMContext* psOSMContext );
 
 CPL_C_END
 
-#endif /*  _OSM_PARSER_H_INCLUDED */
+#endif /*  OSM_PARSER_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/pds/ogr_pds.h b/ogr/ogrsf_frmts/pds/ogr_pds.h
index f56692e..c9e975d 100644
--- a/ogr/ogrsf_frmts/pds/ogr_pds.h
+++ b/ogr/ogrsf_frmts/pds/ogr_pds.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_pds.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogr_pds.h 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  PDS Translator
  * Purpose:  Definition of classes for OGR .pdstable driver.
@@ -27,12 +27,14 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_PDS_H_INCLUDED
-#define _OGR_PDS_H_INCLUDED
+#ifndef OGR_PDS_H_INCLUDED
+#define OGR_PDS_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "nasakeywordhandler.h"
 
+namespace OGRPDS {
+
 /************************************************************************/
 /*                              OGRPDSLayer                             */
 /************************************************************************/
@@ -71,7 +73,7 @@ class OGRPDSLayer : public OGRLayer
     int                nLatitudeIndex;
 
     FieldDesc*         pasFieldDesc;
-    
+
     void               ReadStructure(CPLString osStructureFilename);
     OGRFeature        *GetNextRawFeature();
 
@@ -82,7 +84,7 @@ class OGRPDSLayer : public OGRLayer
                                          CPLString osStructureFilename,
                                          int nRecords,
                                          int nStartBytes, int nRecordSize,
-                                         GByte* pabyRecord, int bIsASCII);
+                                         GByte* pabyRecord, bool bIsASCII);
                         ~OGRPDSLayer();
 
 
@@ -100,6 +102,8 @@ class OGRPDSLayer : public OGRLayer
     virtual OGRErr              SetNextByIndex( GIntBig nIndex );
 };
 
+} /* end of OGRPDS namespace */
+
 /************************************************************************/
 /*                           OGRPDSDataSource                           */
 /************************************************************************/
@@ -114,7 +118,7 @@ class OGRPDSDataSource : public OGRDataSource
     NASAKeywordHandler  oKeywords;
 
     CPLString           osTempResult;
-    const char         *GetKeywordSub( const char *pszPath, 
+    const char         *GetKeywordSub( const char *pszPath,
                                        int iSubscript,
                                        const char *pszDefault );
 
@@ -138,4 +142,4 @@ class OGRPDSDataSource : public OGRDataSource
     static void         CleanString( CPLString &osInput );
 };
 
-#endif /* ndef _OGR_PDS_H_INCLUDED */
+#endif /* ndef OGR_PDS_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/pds/ogrpdsdatasource.cpp b/ogr/ogrsf_frmts/pds/ogrpdsdatasource.cpp
index 0f999b5..48a25ea 100644
--- a/ogr/ogrsf_frmts/pds/ogrpdsdatasource.cpp
+++ b/ogr/ogrsf_frmts/pds/ogrpdsdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpdsdatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogrpdsdatasource.cpp 33047 2016-01-19 14:47:32Z goatbar $
  *
  * Project:  PDS Translator
  * Purpose:  Implements OGRPDSDataSource class
@@ -27,24 +27,23 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_pds.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "ogr_pds.h"
+
+CPL_CVSID("$Id: ogrpdsdatasource.cpp 33047 2016-01-19 14:47:32Z goatbar $");
 
-CPL_CVSID("$Id: ogrpdsdatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+using namespace OGRPDS;
 
 /************************************************************************/
 /*                           OGRPDSDataSource()                         */
 /************************************************************************/
 
-OGRPDSDataSource::OGRPDSDataSource()
-
-{
-    papoLayers = NULL;
-    nLayers = 0;
-
-    pszName = NULL;
-}
+OGRPDSDataSource::OGRPDSDataSource() :
+    pszName(NULL),
+    papoLayers(NULL),
+    nLayers(0)
+{}
 
 /************************************************************************/
 /*                        ~OGRPDSDataSource()                           */
@@ -64,7 +63,7 @@ OGRPDSDataSource::~OGRPDSDataSource()
 /*                           TestCapability()                           */
 /************************************************************************/
 
-int OGRPDSDataSource::TestCapability( CPL_UNUSED const char * pszCap )
+int OGRPDSDataSource::TestCapability( const char * /* pszCap */ )
 {
     return FALSE;
 }
@@ -78,8 +77,8 @@ OGRLayer *OGRPDSDataSource::GetLayer( int iLayer )
 {
     if( iLayer < 0 || iLayer >= nLayers )
         return NULL;
-    else
-        return papoLayers[iLayer];
+
+    return papoLayers[iLayer];
 }
 
 
@@ -87,20 +86,20 @@ OGRLayer *OGRPDSDataSource::GetLayer( int iLayer )
 /*                          GetKeywordSub()                             */
 /************************************************************************/
 
-const char * OGRPDSDataSource::GetKeywordSub( const char *pszPath, 
-                                                   int iSubscript,
-                                                   const char *pszDefault )
+const char * OGRPDSDataSource::GetKeywordSub( const char *pszPath,
+                                              int iSubscript,
+                                              const char *pszDefault )
 
 {
     const char *pszResult = oKeywords.GetKeyword( pszPath, NULL );
-    
+
     if( pszResult == NULL )
         return pszDefault;
 
-    if( pszResult[0] != '(' ) 
+    if( pszResult[0] != '(' )
         return pszDefault;
 
-    char **papszTokens = CSLTokenizeString2( pszResult, "(,)", 
+    char **papszTokens = CSLTokenizeString2( pszResult, "(,)",
                                              CSLT_HONOURSTRINGS );
 
     if( iSubscript <= CSLCount(papszTokens) )
@@ -109,11 +108,9 @@ const char * OGRPDSDataSource::GetKeywordSub( const char *pszPath,
         CSLDestroy( papszTokens );
         return osTempResult.c_str();
     }
-    else
-    {
-        CSLDestroy( papszTokens );
-        return pszDefault;
-    }
+
+    CSLDestroy( papszTokens );
+    return pszDefault;
 }
 
 /************************************************************************/
@@ -126,17 +123,16 @@ const char * OGRPDSDataSource::GetKeywordSub( const char *pszPath,
 void OGRPDSDataSource::CleanString( CPLString &osInput )
 
 {
-   if(  ( osInput.size() < 2 ) ||
-        ((osInput.at(0) != '"'   || osInput.at(osInput.size()-1) != '"' ) &&
-        ( osInput.at(0) != '\'' || osInput.at(osInput.size()-1) != '\'')) )
-        return;
+    if( ( osInput.size() < 2 ) ||
+      ((osInput.at(0) != '"'   || osInput.at(osInput.size()-1) != '"' ) &&
+       ( osInput.at(0) != '\'' || osInput.at(osInput.size()-1) != '\'')) )
+         return;
 
     char *pszWrk = CPLStrdup(osInput.c_str() + 1);
-    int i;
 
     pszWrk[strlen(pszWrk)-1] = '\0';
-    
-    for( i = 0; pszWrk[i] != '\0'; i++ )
+
+    for( int i = 0; pszWrk[i] != '\0'; i++ )
     {
         if( pszWrk[i] == ' ' )
             pszWrk[i] = '_';
@@ -155,17 +151,16 @@ static CPLString MakeAttr(CPLString os1, CPLString os2)
     return os1 + "." + os2;
 }
 
-int OGRPDSDataSource::LoadTable(const char* pszFilename,
-                                     int nRecordSize,
-                                     CPLString osTableID )
+int OGRPDSDataSource::LoadTable( const char* pszFilename,
+                                 int nRecordSize,
+                                 CPLString osTableID )
 {
-
     CPLString osTableFilename;
     int nStartBytes;
-    
+
     CPLString osTableLink = "^";
     osTableLink += osTableID;
-    
+
     CPLString osTable = oKeywords.GetKeyword( osTableLink, "" );
     if( osTable[0] == '(' )
     {
@@ -198,12 +193,14 @@ int OGRPDSDataSource::LoadTable(const char* pszFilename,
         {
             CPLString osTPath = CPLGetPath(pszFilename);
             CleanString( osTableFilename );
-            osTableFilename = CPLFormCIFilename( osTPath, osTableFilename, NULL );
+            osTableFilename =
+                CPLFormCIFilename( osTPath, osTableFilename, NULL );
             nStartBytes = 0;
         }
     }
 
-    CPLString osTableName = oKeywords.GetKeyword( MakeAttr(osTableID, "NAME"), "" );
+    CPLString osTableName =
+        oKeywords.GetKeyword( MakeAttr(osTableID, "NAME"), "" );
     if (osTableName.size() == 0)
     {
         if (GetLayerByName(osTableID.c_str()) == NULL)
@@ -213,9 +210,11 @@ int OGRPDSDataSource::LoadTable(const char* pszFilename,
     }
     CleanString(osTableName);
     CPLString osTableInterchangeFormat =
-            oKeywords.GetKeyword( MakeAttr(osTableID, "INTERCHANGE_FORMAT"), "" );
-    CPLString osTableRows = oKeywords.GetKeyword( MakeAttr(osTableID, "ROWS"), "" );
-    int nRecords = atoi(osTableRows);
+            oKeywords.GetKeyword( MakeAttr(osTableID, "INTERCHANGE_FORMAT"),
+                                  "" );
+    CPLString osTableRows =
+        oKeywords.GetKeyword( MakeAttr(osTableID, "ROWS"), "" );
+    const int nRecords = atoi(osTableRows);
     if (osTableInterchangeFormat.size() == 0 ||
         osTableRows.size() == 0 || nRecords < 0)
     {
@@ -223,7 +222,7 @@ int OGRPDSDataSource::LoadTable(const char* pszFilename,
                  "One of TABLE.INTERCHANGE_FORMAT or TABLE.ROWS is missing");
         return FALSE;
     }
-    
+
     CleanString(osTableInterchangeFormat);
     if (osTableInterchangeFormat.compare("ASCII") != 0 &&
         osTableInterchangeFormat.compare("BINARY") != 0)
@@ -241,7 +240,8 @@ int OGRPDSDataSource::LoadTable(const char* pszFilename,
         return FALSE;
     }
 
-    CPLString osTableStructure = oKeywords.GetKeyword( MakeAttr(osTableID, "^STRUCTURE"), "" );
+    CPLString osTableStructure =
+        oKeywords.GetKeyword( MakeAttr(osTableID, "^STRUCTURE"), "" );
     if (osTableStructure.size() != 0)
     {
         CPLString osTPath = CPLGetPath(pszFilename);
@@ -249,7 +249,7 @@ int OGRPDSDataSource::LoadTable(const char* pszFilename,
         osTableStructure = CPLFormCIFilename( osTPath, osTableStructure, NULL );
     }
 
-    GByte* pabyRecord = (GByte*) VSIMalloc(nRecordSize + 1);
+    GByte* pabyRecord = (GByte*) VSI_MALLOC_VERBOSE(nRecordSize + 1);
     if (pabyRecord == NULL)
     {
         VSIFCloseL(fp);
@@ -257,13 +257,15 @@ int OGRPDSDataSource::LoadTable(const char* pszFilename,
     }
     pabyRecord[nRecordSize] = 0;
 
-    papoLayers = (OGRLayer**) CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
-    papoLayers[nLayers] = new OGRPDSLayer(osTableID, osTableName, fp,
-                                         pszFilename,
-                                         osTableStructure,
-                                         nRecords, nStartBytes,
-                                         nRecordSize, pabyRecord,
-                                         osTableInterchangeFormat.compare("ASCII") == 0);
+    papoLayers = static_cast<OGRLayer**>(
+        CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*)));
+    papoLayers[nLayers] = new OGRPDSLayer(
+        osTableID, osTableName, fp,
+        pszFilename,
+        osTableStructure,
+        nRecords, nStartBytes,
+        nRecordSize, pabyRecord,
+        osTableInterchangeFormat.compare("ASCII") == 0);
     nLayers++;
 
     return TRUE;
@@ -287,11 +289,12 @@ int OGRPDSDataSource::Open( const char * pszFilename )
         return FALSE;
 
     char szBuffer[512];
-    int nbRead = (int)VSIFReadL(szBuffer, 1, sizeof(szBuffer) - 1, fp);
+    int nbRead = static_cast<int>(
+        VSIFReadL(szBuffer, 1, sizeof(szBuffer) - 1, fp));
     szBuffer[nbRead] = '\0';
 
     const char* pszPos = strstr(szBuffer, "PDS_VERSION_ID");
-    int bIsPDS = (pszPos != NULL);
+    const bool bIsPDS = pszPos != NULL;
 
     if (!bIsPDS)
     {
@@ -299,7 +302,7 @@ int OGRPDSDataSource::Open( const char * pszFilename )
         return FALSE;
     }
 
-    if (!oKeywords.Ingest(fp, pszPos - szBuffer))
+    if (!oKeywords.Ingest(fp, static_cast<int>(pszPos - szBuffer)))
     {
         VSIFCloseL(fp);
         return FALSE;
@@ -330,11 +333,11 @@ int OGRPDSDataSource::Open( const char * pszFilename )
         LoadTable(pszFilename, nRecordSize, "TABLE");
     else
     {
-        VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
+        fp = VSIFOpenL(pszFilename, "rb");
         if (fp == NULL)
             return FALSE;
 
-        while(TRUE)
+        while( true )
         {
             CPLPushErrorHandler(CPLQuietErrorHandler);
             const char* pszLine = CPLReadLine2L(fp, 256, NULL);
diff --git a/ogr/ogrsf_frmts/pds/ogrpdsdriver.cpp b/ogr/ogrsf_frmts/pds/ogrpdsdriver.cpp
index ae4d032..f7a5cf8 100644
--- a/ogr/ogrsf_frmts/pds/ogrpdsdriver.cpp
+++ b/ogr/ogrsf_frmts/pds/ogrpdsdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpdsdriver.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: ogrpdsdriver.cpp 33047 2016-01-19 14:47:32Z goatbar $
  *
  * Project:  PDS Translator
  * Purpose:  Implements OGRPDSDriver.
@@ -27,13 +27,15 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_pds.h"
 #include "cpl_conv.h"
+#include "ogr_pds.h"
 
-CPL_CVSID("$Id: ogrpdsdriver.cpp 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: ogrpdsdriver.cpp 33047 2016-01-19 14:47:32Z goatbar $");
 
 extern "C" void RegisterOGRPDS();
 
+using namespace OGRPDS;
+
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
@@ -48,7 +50,7 @@ static GDALDataset *OGRPDSDriverOpen( GDALOpenInfo* poOpenInfo )
     if( strstr((const char*)poOpenInfo->pabyHeader, "PDS_VERSION_ID") == NULL )
         return NULL;
 
-    OGRPDSDataSource   *poDS = new OGRPDSDataSource();
+    OGRPDSDataSource *poDS = new OGRPDSDataSource();
 
     if( !poDS->Open( poOpenInfo->pszFilename ) )
     {
@@ -61,30 +63,26 @@ static GDALDataset *OGRPDSDriverOpen( GDALOpenInfo* poOpenInfo )
 
 
 /************************************************************************/
-/*                           RegisterOGRPDS()                      */
+/*                           RegisterOGRPDS()                           */
 /************************************************************************/
 
 void RegisterOGRPDS()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "OGR_PDS" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "OGR_PDS" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-
-        poDriver->SetDescription( "OGR_PDS" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Planetary Data Systems TABLE" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_pds.html" );
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetDescription( "OGR_PDS" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Planetary Data Systems TABLE" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_pds.html" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = OGRPDSDriverOpen;
+    poDriver->pfnOpen = OGRPDSDriverOpen;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
 
diff --git a/ogr/ogrsf_frmts/pds/ogrpdslayer.cpp b/ogr/ogrsf_frmts/pds/ogrpdslayer.cpp
index 1f0fab6..2ed8d51 100644
--- a/ogr/ogrsf_frmts/pds/ogrpdslayer.cpp
+++ b/ogr/ogrsf_frmts/pds/ogrpdslayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpdslayer.cpp 28382 2015-01-30 15:29:41Z rouault $
+ * $Id: ogrpdslayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  PDS Translator
  * Purpose:  Implements OGRPDSLayer class.
@@ -32,38 +32,37 @@
 #include "cpl_string.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrpdslayer.cpp 28382 2015-01-30 15:29:41Z rouault $");
+CPL_CVSID("$Id: ogrpdslayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+
+namespace OGRPDS {
 
 /************************************************************************/
 /*                           OGRPDSLayer()                              */
 /************************************************************************/
 
-OGRPDSLayer::OGRPDSLayer(   CPLString osTableID,
+OGRPDSLayer::OGRPDSLayer(   CPLString osTableIDIn,
                             const char* pszLayerName, VSILFILE* fp,
                             CPLString osLabelFilename,
                             CPLString osStructureFilename,
-                            int nRecords,
-                            int nStartBytes, int nRecordSize,
-                            GByte* pabyRecordIn, int bIsASCII)
-
+                            int nRecordsIn,
+                            int nStartBytesIn, int nRecordSizeIn,
+                            GByte* pabyRecordIn, bool bIsASCII) :
+    poFeatureDefn(new OGRFeatureDefn( pszLayerName )),
+    osTableID(osTableIDIn),
+    fpPDS(fp),
+    nRecords(nRecordsIn),
+    nStartBytes(nStartBytesIn),
+    nRecordSize(nRecordSizeIn),
+    pabyRecord(pabyRecordIn),
+    nNextFID(0),
+    nLongitudeIndex(-1),
+    nLatitudeIndex(-1),
+    pasFieldDesc(NULL)
 {
-    fpPDS = fp;
-    this->osTableID = osTableID;
-    this->nRecords = nRecords;
-    this->nStartBytes = nStartBytes;
-    this->nRecordSize = nRecordSize;
-    nLongitudeIndex = -1;
-    nLatitudeIndex = -1;
-
-    poFeatureDefn = new OGRFeatureDefn( pszLayerName );
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbNone );
 
-    pasFieldDesc = NULL;
-
-    pabyRecord = pabyRecordIn;
-
     if (osStructureFilename.size() != 0)
     {
         ReadStructure(osStructureFilename);
@@ -81,9 +80,8 @@ OGRPDSLayer::OGRPDSLayer(   CPLString osTableID,
 
         char **papszTokens = CSLTokenizeString2(
                 (const char*)pabyRecord, " ", CSLT_HONOURSTRINGS );
-        int nTokens = CSLCount(papszTokens);
-        int i;
-        for(i=0;i<nTokens;i++)
+        const int nTokens = CSLCount(papszTokens);
+        for( int i=0; i<nTokens; i++)
         {
             const char* pszStr = papszTokens[i];
             char ch;
@@ -105,7 +103,7 @@ OGRPDSLayer::OGRPDSLayer(   CPLString osTableID,
                 pszStr ++;
             }
             char szFieldName[32];
-            sprintf(szFieldName, "field_%d",
+            snprintf(szFieldName, sizeof(szFieldName), "field_%d",
                     poFeatureDefn->GetFieldCount() + 1);
             OGRFieldDefn oFieldDefn(szFieldName, eFieldType);
             poFeatureDefn->AddFieldDefn(&oFieldDefn);
@@ -143,22 +141,26 @@ OGRPDSLayer::~OGRPDSLayer()
 void OGRPDSLayer::ReadStructure(CPLString osStructureFilename)
 
 {
-    int nFields = 0;
     VSILFILE* fpStructure = VSIFOpenL(osStructureFilename, "rb");
     if (fpStructure == NULL)
         return;
 
-    const char* pszLine;
-    int bInObjectColumn = FALSE;
+    int nFields = 0;
+    bool bInObjectColumn = false;
     int nExpectedColumnNumber = 0;
-    CPLString osColumnName, osColumnDataType, osColumnStartByte,
-              osColumnBytes, osColumnFormat, osColumnUnit,
-              osColumnItems, osColumnItemBytes;
+    CPLString osColumnName;
+    CPLString osColumnDataType;
+    CPLString osColumnStartByte;
+    CPLString osColumnBytes;
+    CPLString osColumnFormat;
+    CPLString osColumnUnit;
+    CPLString osColumnItems;
+    CPLString osColumnItemBytes;
     int nRowBytes = nRecordSize;
-    while(TRUE)
+    while( true )
     {
         CPLPushErrorHandler(CPLQuietErrorHandler);
-        pszLine = CPLReadLine2L(fpStructure, 256, NULL);
+        const char* pszLine = CPLReadLine2L(fpStructure, 256, NULL);
         CPLPopErrorHandler();
         CPLErrorReset();
         if (pszLine == NULL)
@@ -166,7 +168,7 @@ void OGRPDSLayer::ReadStructure(CPLString osStructureFilename)
 
         char **papszTokens =
                 CSLTokenizeString2( pszLine, " =", CSLT_HONOURSTRINGS );
-        int nTokens = CSLCount(papszTokens);
+        const int nTokens = CSLCount(papszTokens);
 
         if (bInObjectColumn && nTokens >= 1 &&
             EQUAL(papszTokens[0], "END_OBJECT"))
@@ -177,11 +179,12 @@ void OGRPDSLayer::ReadStructure(CPLString osStructureFilename)
                 osColumnBytes.size() != 0)
             {
                 pasFieldDesc =
-                        (FieldDesc*) CPLRealloc(pasFieldDesc,
-                                (nFields + 1) * sizeof(FieldDesc));
+                    static_cast<FieldDesc*>(
+                        CPLRealloc( pasFieldDesc,
+                                    (nFields + 1) * sizeof(FieldDesc)) );
                 pasFieldDesc[nFields].nStartByte = atoi(osColumnStartByte) - 1;
                 pasFieldDesc[nFields].nByteCount = atoi(osColumnBytes);
-                if (pasFieldDesc[nFields].nStartByte >= 0 && 
+                if (pasFieldDesc[nFields].nStartByte >= 0 &&
                     pasFieldDesc[nFields].nByteCount > 0 &&
                     pasFieldDesc[nFields].nStartByte +
                     pasFieldDesc[nFields].nByteCount <= nRecordSize)
@@ -194,7 +197,8 @@ void OGRPDSLayer::ReadStructure(CPLString osStructureFilename)
                         pasFieldDesc[nFields].nItems = 1;
                     if (pasFieldDesc[nFields].nItemBytes == 0 &&
                         pasFieldDesc[nFields].nItems == 1)
-                        pasFieldDesc[nFields].nItemBytes = pasFieldDesc[nFields].nByteCount;
+                        pasFieldDesc[nFields].nItemBytes =
+                            pasFieldDesc[nFields].nByteCount;
 
                     if (osColumnDataType.compare("ASCII_REAL") == 0)
                     {
@@ -206,7 +210,8 @@ void OGRPDSLayer::ReadStructure(CPLString osStructureFilename)
                         eFieldType = OFTInteger;
                         pasFieldDesc[nFields].eFormat = ASCII_INTEGER;
                     }
-                    else if (osColumnDataType.compare("MSB_UNSIGNED_INTEGER") == 0)
+                    else if (osColumnDataType.compare("MSB_UNSIGNED_INTEGER") ==
+                             0)
                     {
                         if (pasFieldDesc[nFields].nItemBytes == 1 ||
                             pasFieldDesc[nFields].nItemBytes == 2)
@@ -302,7 +307,7 @@ void OGRPDSLayer::ReadStructure(CPLString osStructureFilename)
                 CSLDestroy(papszTokens);
                 break;
             }
-            bInObjectColumn = FALSE;
+            bInObjectColumn = false;
         }
         else if (nTokens == 2)
         {
@@ -310,7 +315,7 @@ void OGRPDSLayer::ReadStructure(CPLString osStructureFilename)
             {
                 CSLDestroy(papszTokens);
                 papszTokens = NULL;
-                while(TRUE)
+                while( true )
                 {
                     CPLPushErrorHandler(CPLQuietErrorHandler);
                     pszLine = CPLReadLine2L(fpStructure, 256, NULL);
@@ -320,8 +325,8 @@ void OGRPDSLayer::ReadStructure(CPLString osStructureFilename)
                         break;
                     papszTokens =
                         CSLTokenizeString2( pszLine, " =", CSLT_HONOURSTRINGS );
-                    int nTokens = CSLCount(papszTokens);
-                    if (nTokens == 2 &&
+                    int nTokens2 = CSLCount(papszTokens);
+                    if (nTokens2 == 2 &&
                         EQUAL(papszTokens[0], "OBJECT") &&
                         EQUAL(papszTokens[1], osTableID.c_str()))
                     {
@@ -357,7 +362,7 @@ void OGRPDSLayer::ReadStructure(CPLString osStructureFilename)
                     nRecordSize = nRowBytes;
 
                 nExpectedColumnNumber ++;
-                bInObjectColumn = TRUE;
+                bInObjectColumn = true;
                 osColumnName = "";
                 osColumnDataType = "";
                 osColumnStartByte = "";
@@ -439,11 +444,9 @@ void OGRPDSLayer::ResetReading()
 
 OGRFeature *OGRPDSLayer::GetNextFeature()
 {
-    OGRFeature  *poFeature;
-
-    while(TRUE)
+    while( true )
     {
-        poFeature = GetNextRawFeature();
+        OGRFeature *poFeature = GetNextRawFeature();
         if (poFeature == NULL)
             return NULL;
 
@@ -454,8 +457,8 @@ OGRFeature *OGRPDSLayer::GetNextFeature()
         {
             return poFeature;
         }
-        else
-            delete poFeature;
+
+        delete poFeature;
     }
 }
 
@@ -476,15 +479,16 @@ OGRFeature *OGRPDSLayer::GetNextRawFeature()
     int nFieldCount = poFeatureDefn->GetFieldCount();
     if (pasFieldDesc != NULL)
     {
-        int i, j;
-        for(i=0;i<nFieldCount;i++)
+        int j;
+        for( int i=0;i<nFieldCount;i++)
         {
             if (pasFieldDesc[i].eFormat == ASCII_REAL ||
                 pasFieldDesc[i].eFormat == ASCII_INTEGER ||
                 pasFieldDesc[i].eFormat == CHARACTER)
             {
-                char* pchEnd = (char*) &pabyRecord[pasFieldDesc[i].nStartByte +
-                                                pasFieldDesc[i].nByteCount];
+                char* pchEnd = reinterpret_cast<char*>(
+                    &pabyRecord[pasFieldDesc[i].nStartByte +
+                                pasFieldDesc[i].nByteCount]);
                 char chSaved = *pchEnd;
                 *pchEnd = 0;
                 poFeature->SetField(i, (const char*)(pabyRecord +
@@ -499,7 +503,8 @@ OGRFeature *OGRPDSLayer::GetNextRawFeature()
                 {
                     if (pasFieldDesc[i].nItems > 1)
                     {
-                        int* panValues = (int*)CPLMalloc(sizeof(int) * pasFieldDesc[i].nItems);
+                        int* panValues = static_cast<int *>(
+                            CPLMalloc(sizeof(int) * pasFieldDesc[i].nItems) );
                         for(j=0;j<pasFieldDesc[i].nItems;j++)
                         {
                             panValues[j] = pabyRecord[pasFieldDesc[i].nStartByte + j];
@@ -689,10 +694,12 @@ int OGRPDSLayer::TestCapability( const char * pszCap )
     if (EQUAL(pszCap,OLCFastFeatureCount) &&
         m_poFilterGeom == NULL && m_poAttrQuery == NULL)
         return TRUE;
-    else if (EQUAL(pszCap,OLCRandomRead))
+
+    if (EQUAL(pszCap,OLCRandomRead))
         return TRUE;
-    else if (EQUAL(pszCap,OLCFastSetNextByIndex) &&
-             m_poFilterGeom == NULL && m_poAttrQuery == NULL)
+
+    if (EQUAL(pszCap,OLCFastSetNextByIndex) &&
+        m_poFilterGeom == NULL && m_poAttrQuery == NULL)
         return TRUE;
 
     return FALSE;
@@ -740,3 +747,5 @@ OGRErr OGRPDSLayer::SetNextByIndex( GIntBig nIndex )
     VSIFSeekL( fpPDS, nStartBytes + nNextFID * nRecordSize, SEEK_SET );
     return OGRERR_NONE;
 }
+
+} /* end of OGRPDS namespace */
diff --git a/ogr/ogrsf_frmts/pg/drv_pg.html b/ogr/ogrsf_frmts/pg/drv_pg.html
index 05bcb15..a04df22 100644
--- a/ogr/ogrsf_frmts/pg/drv_pg.html
+++ b/ogr/ogrsf_frmts/pg/drv_pg.html
@@ -7,9 +7,9 @@
 
 <h1>PostgreSQL / PostGIS</h1>
 
-This driver implements support for access to spatial tables in 
-PostgreSQL extended with the 
-<a href="http://postgis.net/">PostGIS</a> spatial data support. 
+This driver implements support for access to spatial tables in
+PostgreSQL extended with the
+<a href="http://postgis.net/">PostGIS</a> spatial data support.
 Some support exists in the driver for use with PostgreSQL without PostGIS
 but with less functionalities.<p>
 
@@ -50,12 +50,12 @@ following non-linear geometry types :CIRCULARSTRING, COMPOUNDCURVE, CURVEPOLYGON
 <p>The PostgreSQL driver passes SQL statements directly to PostgreSQL by default,
 rather than evaluating them internally when using the ExecuteSQL() call on the
 OGRDataSource, or the -sql command option to ogr2ogr.  Attribute query
-expressions are also passed directly through to PostgreSQL. 
-It's also possible to request the ogr Pg driver to handle SQL commands 
-with the <a href="/ogr/ogr_sql.html">OGR SQL</a> engine, by passing <strong>"OGRSQL"</strong> 
+expressions are also passed directly through to PostgreSQL.
+It's also possible to request the ogr Pg driver to handle SQL commands
+with the <a href="ogr_sql.html">OGR SQL</a> engine, by passing <strong>"OGRSQL"</strong>
 string to the ExecuteSQL() method, as the name of the SQL dialect.</p>
 
-<p>The PostgreSQL driver in OGR supports the OGRDataSource::StartTrasaction(), 
+<p>The PostgreSQL driver in OGR supports the OGRDataSource::StartTransaction(),
 OGRDataSource::CommitTransaction() and OGRDataSource::RollbackTransaction()
 calls in the normal SQL sense.<p>
 
@@ -68,28 +68,46 @@ existing database.<P>
 As mentioned above the type system is impoverished, and many OGR types
 are not appropriately mapped into PostgreSQL.<p>
 
-If the database has PostGIS types loaded (ie. the geometry type) newly
+If the database has PostGIS types loaded (i.e. the geometry type), newly
 created layers will be created with the PostGIS Geometry type.  Otherwise
 they will use OID. <p>
 
 By default it is assumed that text being sent to Postgres is in the UTF-8
 encoding.  This is fine for plain ASCII, but can result in errors for
 extended characters (ASCII 155+, LATIN1, etc).  While OGR provides no direct
-control over this, you can set the PGCLIENTENCODING environment variable 
-to indicate the format being provided.  For instance, if your text is 
+control over this, you can set the PGCLIENTENCODING environment variable
+to indicate the format being provided.  For instance, if your text is
 LATIN1 you could set the environment variable to LATIN1 before using OGR
-and input would be assumed to be LATIN1 instead of UTF-8. 
+and input would be assumed to be LATIN1 instead of UTF-8.
 An alternate way of setting the client encoding is to issue the following SQL command
 with ExecuteSQL() : "SET client_encoding TO encoding_name" where encoding_name is LATIN1, etc.
-Errors can be catched by enclosing this command with a CPLPushErrorHandler()/CPLPopErrorHandler() pair.<p>
+Errors can be caught by enclosing this command with a CPLPushErrorHandler()/CPLPopErrorHandler() pair.<p>
 
 <h3>Dataset open options</h3>
 
 (GDAL >= 2.0)
 
 <ul>
+<li> <b>DBNAME</b>=string: Database name.<p>
+<li> <b>PORT</b>=integer: Port.<p>
+<li> <b>USER</b>=string: User name.<p>
+<li> <b>PASSWORD</b>=string: Password.<p>
+<li> <b>HOST</b>=string: Server hostname.<p>
+<li> <b>ACTIVE_SCHEMA</b>=string: Active schema.<p>
+<li> <b>SCHEMAS</b>=string: Restricted sets of schemas to explore (comma separated).<p>
+<li> <b>TABLES</b>=string: Restricted set of tables to list (comma separated).<p>
 <li> <b>LIST_ALL_TABLES</b>=YES/NO: This may be "YES" to force all tables,
 including non-spatial ones, to be listed.<p>
+<li> <b>PRELUDE_STATEMENTS</b>=string (GDAL >= 2.1). SQL statement(s) to send on the
+PostgreSQL client connection before any other ones. In case of several statement,
+they must be separated with the semi-column (;) sign. The driver will specifically
+recognize BEGIN as the first statement to avoid emitting BEGIN/COMMIT itself.
+This option may be useful when using the driver with pg_bouncer in transaction pooling,
+e.g. 'BEGIN; SET LOCAL statement_timeout TO "1h";'<p>
+<li> <b>CLOSING_STATEMENTS</b>=string (GDAL >= 2.1). SQL statement(s) to send on the
+PostgreSQL client connection after any other ones. In case of several statement,
+they must be separated with the semi-column (;) sign. With the above example value
+for PRELUDE_STATEMENTS, the appropriate CLOSING_STATEMENTS would be "COMMIT".<p>
 </ul>
 
 <h3>Dataset Creation Options</h3>
@@ -100,7 +118,7 @@ None<p>
 
 <ul>
 <li>
-<b>GEOM_TYPE</b>: The GEOM_TYPE layer creation option can be set to 
+<b>GEOM_TYPE</b>: The GEOM_TYPE layer creation option can be set to
 one of "geometry", "geography" (PostGIS >= 1.5), "BYTEA" or "OID" to force the type of geometry used for
 a table. For a PostGIS database, "geometry" is the default value.<p>
 <li> <b>OVERWRITE</b>: This may be "YES" to force an existing layer of the
@@ -108,16 +126,16 @@ desired name to be destroyed before creating the requested layer.<p>
 <li> <b>LAUNDER</b>: This may be "YES" to force new fields created on this
 layer to have their field names "laundered" into a form more compatible with
 PostgreSQL.  This converts to lower case and converts some special characters
-like "-" and "#" to "_".  If "NO" exact names are preserved.  
+like "-" and "#" to "_".  If "NO" exact names are preserved.
 The default value is "YES".  If enabled the table (layer) name will also be laundered.<p>
 <li> <b>PRECISION</b>: This may be "YES" to force new fields created on this
 layer to try and represent the width and precision information, if available
 using NUMERIC(width,precision) or CHAR(width) types.  If "NO" then the types
 FLOAT8, INTEGER and VARCHAR will be used instead.  The default is "YES".<p>
-<li> <b>DIM={2,3}</b>: Control the dimension of the layer.  Defaults to 3. 
+<li> <b>DIM={2,3,XYM,XYZM}</b>: Control the dimension of the layer.
 Important to set to 2 for 2D layers with PostGIS 1.0+ as it has constraints
 on the geometry dimension during loading.<p>
-<li> <b>GEOMETRY_NAME</b>: Set name of geometry column in new table.  If 
+<li> <b>GEOMETRY_NAME</b>: Set name of geometry column in new table.  If
 omitted it defaults to <i>wkb_geometry</i> for GEOM_TYPE=geometry, or <i>the_geog</i> for GEOM_TYPE=geography.<p>
 <li> <b>SCHEMA</b>: Set name of schema for new table.
 Using the same layer name in different schemas is supported, but not in the public schema and others. Note that
@@ -140,12 +158,16 @@ as the separator between the schema and the table name. Defaults to YES.<p>
 <li> <b>COLUMN_TYPES</b>: (From GDAL 1.10) A list of strings of format field_name=pg_field_type (separated by comma)
 that should be use when CreateField() is invoked on them. This will override the default choice that OGR would have made.
 This can for example be used to create a column of type <a href="http://www.postgresql.org/docs/9.0/static/hstore.html">HSTORE</a>.<p>
+<li> <b>DESCRIPTION</b> (From GDAL 2.1) Description string to put in the pg_description system table. On
+reading, if such a description is found, it is exposed in the DESCRIPTION metadata item. The description
+can also be written with SetMetadataItem("DESCRIPTION", description_string). Descriptions are preserved
+by default by ogr2ogr, unless the -nomd option is used.</p>
 </ul>
 
 <h3>Configuration Options</h3>
 
-There are a variety of 
-<a href="http://trac.osgeo.org/gdal/wiki/ConfigOptions">Configuration 
+There are a variety of
+<a href="http://trac.osgeo.org/gdal/wiki/ConfigOptions">Configuration
 Options</a> which help control the behavior of this driver.<p>
 
 <ul>
@@ -170,7 +192,7 @@ Typical use case: "ogr2ogr -append PG:dbname=foo abc.shp --config OGR_TRUNCATE Y
 <ul>
 <li>
 Simple translation of a shapefile into PostgreSQL.  The table 'abc' will
-be created with the features from abc.shp and attributes from abc.dbf. 
+be created with the features from abc.shp and attributes from abc.dbf.
 The database instance (warmerda) must already exist, and the table abc must
 not already exist. <p>
 
@@ -208,7 +230,7 @@ and no OVERWRITE=yes. <p>
 
 <li>
 <p>
-This example shows using ogrinfo to evaluate an SQL query statement 
+This example shows using ogrinfo to evaluate an SQL query statement
 within PostgreSQL.  More sophisticated PostGIS specific queries may also be
 used via the -sql commandline switch to ogrinfo.<p>
 
@@ -232,7 +254,7 @@ ogrinfo -ro PG:'host=myserver.velocet.ca user=postgres dbname=warmerda'
 
 <ul>
 <li> <b>Why can't I see my tables? PostGIS is installed and I have data</b><br>
-You must have permissions on all tables you want to read <i>and</i> geometry_columns and spatial_ref_sys.<br> 
+You must have permissions on all tables you want to read <i>and</i> geometry_columns and spatial_ref_sys.<br>
 Misleading behavior may follow without an error message if you do not have permissions to these tables. Permission
 issues on geometry_columns and/or spatial_ref_sys tables can be generally confirmed if you can see the tables
 by setting the configuration option PG_LIST_ALL_TABLES to YES. (e.g. ogrinfo --config PG_LIST_ALL_TABLES YES PG:xxxxx)
diff --git a/ogr/ogrsf_frmts/pg/drv_pg_advanced.html b/ogr/ogrsf_frmts/pg/drv_pg_advanced.html
index 6ac9127..455cbdd 100644
--- a/ogr/ogrsf_frmts/pg/drv_pg_advanced.html
+++ b/ogr/ogrsf_frmts/pg/drv_pg_advanced.html
@@ -34,7 +34,7 @@ Note that this does not restrict the tables that will be listed (see <i>schemas=
 When getting the list of tables, the name of the tables within that active schema will
 not be prefixed by the schema name. For example, if you have a table 'foo' within the public
 schema, and a table 'foo' within the 'bar_schema' schema, and that you specify
-active_schema=bar_schema, 2 layers will be listed : 'foo' (implicetly within 'bar_schema') and 'public.foo'.<p>
+active_schema=bar_schema, 2 layers will be listed : 'foo' (implicitly within 'bar_schema') and 'public.foo'.<p>
 
 <h2>Multiple geometry columns</h2>
 
@@ -151,7 +151,7 @@ that relied on implicit transactions being regularly flushed by the PG driver in
 
 <p>Efficient sequential reading in PostgreSQL requires to be done within a transaction
 (technically this is a CURSOR WITHOUT HOLD).
-So the PG driver will implicitely open such a transaction if none is currently
+So the PG driver will implicitly open such a transaction if none is currently
 opened as soon as a feature is retrieved. This transaction will be released if
 ResetReading() is called (provided that no other layer is still being read).</p>
 
@@ -167,7 +167,7 @@ reading from the beginning.</p>
 
 <p>As calling SetAttributeFilter() or SetSpatialFilter() implies an implicit
 ResetReading(), they have the same effect as ResetReading(). That is to say,
-while an implict transaction is in progress, the transaction will be committed
+while an implicit transaction is in progress, the transaction will be committed
 (if no other layer is being read), and a new one will be started again at the next
 GetNextFeature() call. On the contrary, if they are called within an explicit
 transaction, the transaction is maintained.</p>
@@ -176,7 +176,7 @@ transaction, the transaction is maintained.</p>
 run when using the OGR API in different scenarios.</p>
 <pre>
 
-lyr1->GetNextFeature()             BEGIN (implict)
+lyr1->GetNextFeature()             BEGIN (implicit)
                                    DECLARE cur1 CURSOR FOR SELECT * FROM lyr1
                                    FETCH 1 IN cur1
 
@@ -184,7 +184,7 @@ lyr1->SetAttributeFilter('xxx')
      --> lyr1->ResetReading()      CLOSE cur1
                                    COMMIT (implicit)
 
-lyr1->GetNextFeature()             BEGIN (implict)
+lyr1->GetNextFeature()             BEGIN (implicit)
                                    DECLARE cur1 CURSOR  FOR SELECT * FROM lyr1 WHERE xxx
                                    FETCH 1 IN cur1
 
@@ -337,7 +337,7 @@ This example shows how to overwrite an existing table in an existing schema. Not
 ogr2ogr -overwrite -f PostgreSQL "PG:dbname=warmerda" mytable.shp mytable -nln myschema.mytable
 </pre>
 
-Note that using -lco SCHEMA=mytable instead of -nln wouldn't have worked in that case
+Note that using -lco SCHEMA=mytable instead of -nln would not have worked in that case
 (see <a href="http://trac.osgeo.org/gdal/ticket/2821">#2821</a> for more details).<p>
 
 If you need to overwrite many tables located in a schema at once, the -nln option is not
diff --git a/ogr/ogrsf_frmts/pg/ogr_pg.h b/ogr/ogrsf_frmts/pg/ogr_pg.h
index a35d14e..5bf5ffd 100644
--- a/ogr/ogrsf_frmts/pg/ogr_pg.h
+++ b/ogr/ogrsf_frmts/pg/ogr_pg.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_pg.h 28988 2015-04-24 11:58:49Z rouault $
+ * $Id: ogr_pg.h 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/PostgreSQL driver.
@@ -28,8 +28,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_PG_H_INCLUDED
-#define _OGR_PG_H_INCLUDED
+#ifndef OGR_PG_H_INCLUDED
+#define OGR_PG_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "libpq-fe.h"
@@ -59,6 +59,7 @@
 #define FLOAT4OID               700
 #define FLOAT8OID               701
 #define BOOLARRAYOID            1000
+#define INT2ARRAYOID            1005
 #define INT4ARRAYOID            1007
 #define TEXTARRAYOID            1009
 #define BPCHARARRAYOID          1014
@@ -73,6 +74,7 @@
 #define TIMESTAMPOID	        1114
 #define TIMESTAMPTZOID	        1184
 #define NUMERICOID              1700
+#define NUMERICARRAYOID         1231
 
 CPLString OGRPGEscapeString(PGconn *hPGConn,
                             const char* pszStrValue, int nMaxLength = -1,
@@ -97,7 +99,7 @@ typedef struct
 {
     char* pszName;
     char* pszGeomType;
-    int   nCoordDimension;
+    int   GeometryTypeFlags;
     int   nSRID;
     PostgisType   ePostgisType;
     int   bNullable;
@@ -116,7 +118,7 @@ class OGRPGGeomFieldDefn : public OGRGeomFieldDefn
         OGRPGGeomFieldDefn( OGRPGLayer* poLayerIn,
                                 const char* pszFieldName ) :
             OGRGeomFieldDefn(pszFieldName, wkbUnknown), poLayer(poLayerIn),
-            nSRSId(UNDETERMINED_SRID), nCoordDimension(2), ePostgisType(GEOM_TYPE_UNKNOWN)
+            nSRSId(UNDETERMINED_SRID), GeometryTypeFlags(0), ePostgisType(GEOM_TYPE_UNKNOWN)
             {
             }
 
@@ -125,7 +127,7 @@ class OGRPGGeomFieldDefn : public OGRGeomFieldDefn
         void UnsetLayer() { poLayer = NULL; }
 
         int nSRSId;
-        int nCoordDimension;
+        int GeometryTypeFlags;
         PostgisType   ePostgisType;
 };
 
@@ -167,7 +169,7 @@ class OGRPGLayer : public OGRLayer
     GIntBig             iNextShapeId;
 
     static char        *GByteArrayToBYTEA( const GByte* pabyData, int nLen);
-    static char        *GeometryToBYTEA( OGRGeometry *, int bIsPostGIS1 );
+    static char        *GeometryToBYTEA( OGRGeometry *, int nPostGISMajor, int nPostGISMinor );
     static GByte       *BYTEAToGByteArray( const char *pszBytea, int* pnLength );
     static OGRGeometry *BYTEAToGeometry( const char *, int bIsPostGIS1 );
     Oid                 GeometryToOID( OGRGeometry * );
@@ -233,7 +235,7 @@ class OGRPGLayer : public OGRLayer
     virtual const char *GetFIDColumn();
 
     virtual OGRErr      SetNextByIndex( GIntBig nIndex );
-    
+
     OGRPGDataSource    *GetDS() { return poDS; }
 
     virtual void        ResolveSRID(OGRPGGeomFieldDefn* poGFldDefn) = 0;
@@ -253,6 +255,8 @@ class OGRPGTableLayer : public OGRPGLayer
 
     char               *pszTableName;
     char               *pszSchemaName;
+    char               *pszDescription;
+    CPLString           osForcedDescription;
     char               *pszSqlTableName;
     int                 bTableDefinitionValid;
 
@@ -284,23 +288,25 @@ class OGRPGTableLayer : public OGRPGLayer
 
     int                 bRetrieveFID;
     int                 bHasWarnedAlreadySetFID;
-    
+
     char              **papszOverrideColumnTypes;
     int                 nForcedSRSId;
-    int                 nForcedDimension;
+    int                 nForcedGeometryTypeFlags;
     int                 bCreateSpatialIndexFlag;
     int                 bInResetReading;
-    
+
     int                 bAutoFIDOnCreateViaCopy;
     int                 bUseCopyByDefault;
-    
-    int                 bDifferedCreation;
+
+    int                 bDeferredCreation;
     CPLString           osCreateTable;
-    
+
     int                 iFIDAsRegularColumnIndex;
 
+    CPLString           m_osFirstGeometryFieldName;
+
     virtual CPLString   GetFromClauseForGetExtent() { return pszSqlTableName; }
-    
+
     OGRErr              RunAddGeometryColumn( OGRPGGeomFieldDefn *poGeomField );
     OGRErr              RunCreateSpatialIndex( OGRPGGeomFieldDefn *poGeomField );
 
@@ -309,6 +315,7 @@ public:
                                          CPLString& osCurrentSchema,
                                          const char * pszTableName,
                                          const char * pszSchemaName,
+                                         const char * pszDescriptionIn,
                                          const char * pszGeomColForced,
                                          int bUpdate );
                         ~OGRPGTableLayer();
@@ -347,6 +354,12 @@ public:
 
     virtual const char *GetFIDColumn();
 
+    virtual char      **GetMetadataDomainList();
+    virtual char      **GetMetadata(const char* pszDomain = "");
+    virtual const char *GetMetadataItem(const char* pszName, const char* pszDomain = "");
+    virtual CPLErr      SetMetadata(char** papszMD, const char* pszDomain = "");
+    virtual CPLErr      SetMetadataItem(const char* pszName, const char* pszValue, const char* pszDomain = "");
+
     // follow methods are not base class overrides
     void                SetLaunderFlag( int bFlag )
                                 { bLaunderColumnNames = bFlag; }
@@ -365,19 +378,20 @@ public:
                                            OGRwkbGeometryType eType,
                                            const char* pszGeomType,
                                            int nSRSId,
-                                           int nCoordDimension);
+                                           int GeometryTypeFlags);
 
     void                SetForcedSRSId( int nForcedSRSIdIn )
                                 { nForcedSRSId = nForcedSRSIdIn; }
-    void                SetForcedDimension( int nForcedDimensionIn )
-                                { nForcedDimension = nForcedDimensionIn; }
+    void                SetForcedGeometryTypeFlags( int GeometryTypeFlagsIn )
+                                { nForcedGeometryTypeFlags = GeometryTypeFlagsIn; }
     void                SetCreateSpatialIndexFlag( int bFlag )
                                 { bCreateSpatialIndexFlag = bFlag; }
+    void                SetForcedDescription( const char* pszDescriptionIn );
     void                AllowAutoFIDOnCreateViaCopy() { bAutoFIDOnCreateViaCopy = TRUE; }
     void                SetUseCopy() { bUseCopy = TRUE; bUseCopyByDefault = TRUE; }
 
-    void                SetDifferedCreation(int bDifferedCreationIn, CPLString osCreateTable);
-    OGRErr              RunDifferedCreationIfNecessary();
+    void                SetDeferredCreation(int bDeferredCreationIn, CPLString osCreateTable);
+    OGRErr              RunDeferredCreationIfNecessary();
 
     virtual void        ResolveSRID(OGRPGGeomFieldDefn* poGFldDefn);
 };
@@ -396,7 +410,7 @@ class OGRPGResultLayer : public OGRPGLayer
     char                *pszGeomTableSchemaName;
 
     CPLString           osWHERE;
-    
+
     virtual CPLString   GetFromClauseForGetExtent()
         { CPLString osStr("(");
           osStr += pszRawStatement; osStr += ")"; return osStr; }
@@ -448,7 +462,7 @@ class OGRPGDataSource : public OGRDataSource
 
     PGconn              *hPGConn;
 
-    int                 DeleteLayer( int iLayer );
+    OGRErr              DeleteLayer( int iLayer );
 
     Oid                 nGeometryOID;
     Oid                 nGeographyOID;
@@ -467,7 +481,7 @@ class OGRPGDataSource : public OGRDataSource
     CPLString           GetCurrentSchema();
 
     int                 nUndefinedSRID;
-    
+
     char               *pszForcedTables;
     char              **papszSchemaList;
     int                 bHasLoadTables;
@@ -505,6 +519,7 @@ class OGRPGDataSource : public OGRDataSource
     OGRPGTableLayer*    OpenTable( CPLString& osCurrentSchema,
                                    const char * pszTableName,
                                    const char * pszSchemaName,
+                                   const char * pszDescription,
                                    const char * pszGeomColForced,
                                    int bUpdate, int bTestOpen );
 
@@ -512,7 +527,7 @@ class OGRPGDataSource : public OGRDataSource
     int                 GetLayerCount();
     OGRLayer            *GetLayer( int );
     OGRLayer            *GetLayerByName(const char * pszName);
-    
+
     virtual void        FlushCache(void);
 
     virtual OGRLayer    *ICreateLayer( const char *,
@@ -546,5 +561,4 @@ class OGRPGDataSource : public OGRDataSource
     OGRErr              EndCopy( );
 };
 
-#endif /* ndef _OGR_PG_H_INCLUDED */
-
+#endif /* ndef OGR_PG_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp b/ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp
index 4ecf66c..1487659 100644
--- a/ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp
+++ b/ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgdatasource.cpp 31320 2015-11-02 17:22:45Z rouault $
+ * $Id: ogrpgdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGDataSource class.
@@ -37,7 +37,7 @@
 
 #define PQexec this_is_an_error
 
-CPL_CVSID("$Id: ogrpgdatasource.cpp 31320 2015-11-02 17:22:45Z rouault $");
+CPL_CVSID("$Id: ogrpgdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 static void OGRPGNoticeProcessor( void *arg, const char * pszMessage );
 
@@ -45,8 +45,8 @@ static void OGRPGNoticeProcessor( void *arg, const char * pszMessage );
 /*                          OGRPGDataSource()                           */
 /************************************************************************/
 
-OGRPGDataSource::OGRPGDataSource()
-
+OGRPGDataSource::OGRPGDataSource() :
+    bDSUpdate(FALSE)
 {
     pszName = NULL;
     pszDBName = NULL;
@@ -55,13 +55,19 @@ OGRPGDataSource::OGRPGDataSource()
     hPGConn = NULL;
     bHavePostGIS = FALSE;
     bHaveGeography = FALSE;
+    sPostgreSQLVersion.nMajor = 0;
+    sPostgreSQLVersion.nMinor = 0;
+    sPostgreSQLVersion.nRelease = 0;
+    sPostGISVersion.nMajor = 0;
+    sPostGISVersion.nMinor = 0;
+    sPostGISVersion.nRelease = 0;
     bUseBinaryCursor = FALSE;
     bUserTransactionActive = FALSE;
     bSavePointActive = FALSE;
     nSoftTransactionLevel = 0;
     bBinaryTimeFormatIsInt8 = FALSE;
     bUseEscapeStringSyntax = FALSE;
-    
+
     nGeometryOID = (Oid) 0;
     nGeographyOID = (Oid) 0;
 
@@ -70,7 +76,8 @@ OGRPGDataSource::OGRPGDataSource()
     papoSRS = NULL;
 
     poLayerInCopyMode = NULL;
-    nUndefinedSRID = -1; /* actual value will be autotected if PostGIS >= 2.0 detected */
+    // Actual value will be auto-detected if PostGIS >= 2.0 detected.
+    nUndefinedSRID = -1;
 
     pszForcedTables = NULL;
     papszSchemaList = NULL;
@@ -87,7 +94,7 @@ OGRPGDataSource::~OGRPGDataSource()
 {
     int         i;
 
-    FlushSoftTransaction();
+    FlushCache();
 
     CPLFree( pszName );
     CPLFree( pszDBName );
@@ -101,6 +108,21 @@ OGRPGDataSource::~OGRPGDataSource()
 
     if( hPGConn != NULL )
     {
+        /* If there are prelude statements we don't want to mess with transactions */
+        if( CSLFetchNameValue(papszOpenOptions, "PRELUDE_STATEMENTS") == NULL )
+            FlushSoftTransaction();
+
+/* -------------------------------------------------------------------- */
+/*      Send closing statements                                         */
+/* -------------------------------------------------------------------- */
+        const char* pszClosingStatements = CSLFetchNameValue(papszOpenOptions,
+                                                             "CLOSING_STATEMENTS");
+        if( pszClosingStatements != NULL )
+        {
+            PGresult    *hResult = OGRPG_PQexec( hPGConn, pszClosingStatements, TRUE );
+            OGRPGClearResult(hResult);
+        }
+
         /* XXX - mloskot: After the connection is closed, valgrind still
          * reports 36 bytes definitely lost, somewhere in the libpq.
          */
@@ -126,7 +148,7 @@ void OGRPGDataSource::FlushCache(void)
     EndCopy();
     for( int iLayer = 0; iLayer < nLayers; iLayer++ )
     {
-        papoLayers[iLayer]->RunDifferedCreationIfNecessary();
+        papoLayers[iLayer]->RunDeferredCreationIfNecessary();
     }
 }
 
@@ -165,7 +187,7 @@ void OGRPGDataSource::OGRPGDecodeVersionString(PGver* psVersion, const char* psz
     ptr = pszVer;
     // get Version string
     while (*ptr && *ptr != ' ') ptr++;
-    iLen = ptr-pszVer;
+    iLen = static_cast<int>(ptr-pszVer);
     if ( iLen > sizeof(szVer) - 1 ) iLen = sizeof(szVer) - 1;
     strncpy(szVer,pszVer,iLen);
     szVer[iLen] = '\0';
@@ -174,7 +196,7 @@ void OGRPGDataSource::OGRPGDecodeVersionString(PGver* psVersion, const char* psz
 
     // get Major number
     while (*ptr && *ptr != '.') ptr++;
-    iLen = ptr-pszVer;
+    iLen = static_cast<int>(ptr-pszVer);
     if ( iLen > sizeof(szNum) - 1) iLen = sizeof(szNum) - 1;
     strncpy(szNum,pszVer,iLen);
     szNum[iLen] = '\0';
@@ -186,7 +208,7 @@ void OGRPGDataSource::OGRPGDecodeVersionString(PGver* psVersion, const char* psz
 
     // get Minor number
     while (*ptr && *ptr != '.') ptr++;
-    iLen = ptr-pszVer;
+    iLen = static_cast<int>(ptr-pszVer);
     if ( iLen > sizeof(szNum) - 1) iLen = sizeof(szNum) - 1;
     strncpy(szNum,pszVer,iLen);
     szNum[iLen] = '\0';
@@ -199,7 +221,7 @@ void OGRPGDataSource::OGRPGDecodeVersionString(PGver* psVersion, const char* psz
 
         // get Release number
         while (*ptr && *ptr != '.') ptr++;
-        iLen = ptr-pszVer;
+        iLen = static_cast<int>(ptr-pszVer);
         if ( iLen > sizeof(szNum) - 1) iLen = sizeof(szNum) - 1;
         strncpy(szNum,pszVer,iLen);
         szNum[iLen] = '\0';
@@ -218,6 +240,7 @@ typedef struct
 {
     char* pszTableName;
     char* pszSchemaName;
+    char* pszDescription;
     int   nGeomColumnCount;
     PGGeomColumnDesc* pasGeomColumns;   /* list of geometry columns */
     int   bDerivedInfoAdded;            /* set to TRUE if it derives from another table */
@@ -241,7 +264,7 @@ static int OGRPGEqualTableEntry(const void* _psTableEntry1, const void* _psTable
 static void OGRPGTableEntryAddGeomColumn(PGTableEntry* psTableEntry,
                                          const char* pszName,
                                          const char* pszGeomType = NULL,
-                                         int nCoordDimension = 0,
+                                         int GeometryTypeFlags = 0,
                                          int nSRID = UNDETERMINED_SRID,
                                          PostgisType ePostgisType = GEOM_TYPE_UNKNOWN,
                                          int bNullable = TRUE)
@@ -251,7 +274,7 @@ static void OGRPGTableEntryAddGeomColumn(PGTableEntry* psTableEntry,
                sizeof(PGGeomColumnDesc) * (psTableEntry->nGeomColumnCount + 1));
     psTableEntry->pasGeomColumns[psTableEntry->nGeomColumnCount].pszName = CPLStrdup(pszName);
     psTableEntry->pasGeomColumns[psTableEntry->nGeomColumnCount].pszGeomType = (pszGeomType) ? CPLStrdup(pszGeomType) : NULL;
-    psTableEntry->pasGeomColumns[psTableEntry->nGeomColumnCount].nCoordDimension = nCoordDimension;
+    psTableEntry->pasGeomColumns[psTableEntry->nGeomColumnCount].GeometryTypeFlags = GeometryTypeFlags;
     /* With PostGIS 2.0, querying geometry_columns can return 0, not only when */
     /* the SRID is truly set to 0, but also when there's no constraint */
     psTableEntry->pasGeomColumns[psTableEntry->nGeomColumnCount].nSRID = nSRID > 0 ? nSRID : UNDETERMINED_SRID;
@@ -266,7 +289,7 @@ static void OGRPGTableEntryAddGeomColumn(PGTableEntry* psTableEntry,
     OGRPGTableEntryAddGeomColumn(psTableEntry,
                                  psGeomColumnDesc->pszName,
                                  psGeomColumnDesc->pszGeomType,
-                                 psGeomColumnDesc->nCoordDimension,
+                                 psGeomColumnDesc->GeometryTypeFlags,
                                  psGeomColumnDesc->nSRID,
                                  psGeomColumnDesc->ePostgisType,
                                  psGeomColumnDesc->bNullable);
@@ -277,6 +300,7 @@ static void OGRPGFreeTableEntry(void * _psTableEntry)
     PGTableEntry* psTableEntry = (PGTableEntry*)_psTableEntry;
     CPLFree(psTableEntry->pszTableName);
     CPLFree(psTableEntry->pszSchemaName);
+    CPLFree(psTableEntry->pszDescription);
     int i;
     for(i=0;i<psTableEntry->nGeomColumnCount;i++)
     {
@@ -299,11 +323,13 @@ static PGTableEntry* OGRPGFindTableEntry(CPLHashSet* hSetTables,
 
 static PGTableEntry* OGRPGAddTableEntry(CPLHashSet* hSetTables,
                                         const char* pszTableName,
-                                        const char* pszSchemaName)
+                                        const char* pszSchemaName,
+                                        const char* pszDescription)
 {
     PGTableEntry* psEntry = (PGTableEntry*) CPLCalloc(1, sizeof(PGTableEntry));
     psEntry->pszTableName = CPLStrdup(pszTableName);
     psEntry->pszSchemaName = CPLStrdup(pszSchemaName);
+    psEntry->pszDescription = CPLStrdup( pszDescription ? pszDescription : "" );
 
     CPLHashSetInsert(hSetTables, psEntry);
 
@@ -315,21 +341,34 @@ static PGTableEntry* OGRPGAddTableEntry(CPLHashSet* hSetTables,
 /************************************************************************/
 
 int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
-                           int bTestOpen, char** papszOpenOptions )
+                           int bTestOpen, char** papszOpenOptionsIn )
 
 {
     CPLAssert( nLayers == 0 );
+    papszOpenOptions = CSLDuplicate(papszOpenOptionsIn);
+
+    const char* pszPreludeStatements = CSLFetchNameValue(papszOpenOptions,
+                                                         "PRELUDE_STATEMENTS");
+    if( pszPreludeStatements )
+    {
+        // If the prelude statements starts with BEGIN, then don't emit one
+        // in our code.
+        if( STARTS_WITH_CI(pszPreludeStatements, "BEGIN") )
+            nSoftTransactionLevel = 1;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Verify postgresql prefix.                                       */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszNewName,"PGB:",4) )
+    if( STARTS_WITH_CI(pszNewName, "PGB:") )
     {
+#if defined(BINARY_CURSOR_ENABLED)
         bUseBinaryCursor = TRUE;
         CPLDebug("PG","BINARY cursor is used for geometry fetching");
+#endif
     }
     else
-    if( !EQUALN(pszNewName,"PG:",3) )
+    if( !STARTS_WITH_CI(pszNewName, "PG:") )
     {
         if( !bTestOpen )
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -339,7 +378,7 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
     }
 
     pszName = CPLStrdup( pszNewName );
-    
+
     CPLString osConnectionName(pszName);
     const char* apszOpenOptions[] = { "dbname", "port", "user", "password",
                                       "host", "active_schema", "schemas", "tables" };
@@ -355,9 +394,9 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
             osConnectionName += pszVal;
         }
     }
-    
+
     char* pszConnectionName = CPLStrdup(osConnectionName);
-    
+
 
 /* -------------------------------------------------------------------- */
 /*      Determine if the connection string contains an optional         */
@@ -459,13 +498,10 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
     }
 
 
-    CPLString      osCurrentSchema;
-    PGresult      *hResult = NULL;
-
 /* -------------------------------------------------------------------- */
 /*      Try to establish connection.                                    */
 /* -------------------------------------------------------------------- */
-    hPGConn = PQconnectdb( pszConnectionName + (bUseBinaryCursor ? 4 : 3) );
+    hPGConn = PQconnectdb( pszConnectionName + (STARTS_WITH_CI(pszNewName, "PGB:") ? 4 : 3) );
     CPLFree(pszConnectionName);
     pszConnectionName = NULL;
 
@@ -484,6 +520,21 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
     bDSUpdate = bUpdate;
 
 /* -------------------------------------------------------------------- */
+/*      Send prelude statements                                         */
+/* -------------------------------------------------------------------- */
+    if( pszPreludeStatements != NULL )
+    {
+        PGresult    *hResult = OGRPG_PQexec( hPGConn, pszPreludeStatements, TRUE );
+        if( !hResult || PQresultStatus(hResult) != PGRES_COMMAND_OK )
+        {
+            OGRPGClearResult( hResult );
+            return FALSE;
+        }
+
+        OGRPGClearResult(hResult);
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Set the encoding to UTF8 as the driver advertizes UTF8          */
 /*      unless PGCLIENTENCODING is defined                              */
 /* -------------------------------------------------------------------- */
@@ -493,7 +544,7 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
         if (PQsetClientEncoding(hPGConn, encoding) == -1)
         {
             CPLError( CE_Warning, CPLE_AppDefined,
-                    "PQsetClientEncoding(%s) failed.\n%s", 
+                    "PQsetClientEncoding(%s) failed.\n%s",
                     encoding, PQerrorMessage( hPGConn ) );
         }
     }
@@ -564,7 +615,7 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
     sPostgreSQLVersion.nMinor = -1;
     sPostgreSQLVersion.nRelease = -1;
 
-    hResult = OGRPG_PQexec(hPGConn, "SELECT version()" );
+    PGresult* hResult = OGRPG_PQexec(hPGConn, "SELECT version()" );
     if( hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK
         && PQntuples(hResult) > 0 )
     {
@@ -578,6 +629,7 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
         if( pszSpace != NULL && isdigit(pszSpace[1]) )
         {
             OGRPGDecodeVersionString(&sPostgreSQLVersion, pszSpace + 1);
+#if defined(BINARY_CURSOR_ENABLED)
             if (sPostgreSQLVersion.nMajor == 7 && sPostgreSQLVersion.nMinor < 4)
             {
                 /* We don't support BINARY CURSOR for PostgreSQL < 7.4. */
@@ -585,6 +637,7 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
                 CPLDebug("PG","BINARY cursor will finally NOT be used because version < 7.4");
                 bUseBinaryCursor = FALSE;
             }
+#endif
         }
     }
     OGRPGClearResult(hResult);
@@ -607,7 +660,7 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
 /* -------------------------------------------------------------------- */
 /*      Test if time binary format is int8 or float8                    */
 /* -------------------------------------------------------------------- */
-#if !defined(PG_PRE74)
+#if !defined(PG_PRE74) && defined(BINARY_CURSOR_ENABLED)
     if (bUseBinaryCursor)
     {
         SoftStartTransaction();
@@ -665,8 +718,8 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
     /* bytea hex format */
     if (sPostgreSQLVersion.nMajor >= 9)
     {
-        /* Starting with PostgreSQL 9.0, the default output format for values of type bytea */
-        /* is hex, whereas we traditionnaly expect escape */
+        // Starting with PostgreSQL 9.0, the default output format for values
+        // of type bytea is hex, whereas we traditionally expect escape.
         hResult = OGRPG_PQexec(hPGConn, "SET bytea_output TO escape");
         OGRPGClearResult( hResult );
     }
@@ -681,7 +734,7 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
                         "SELECT oid, typname FROM pg_type WHERE typname IN ('geometry', 'geography')" );
 
     if( hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK
-        && PQntuples(hResult) > 0  && CSLTestBoolean(CPLGetConfigOption("PG_USE_POSTGIS", "YES")))
+        && PQntuples(hResult) > 0  && CPLTestBool(CPLGetConfigOption("PG_USE_POSTGIS", "YES")))
     {
         for( int iRecord = 0; iRecord < PQntuples(hResult); iRecord++ )
         {
@@ -692,7 +745,7 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
                 bHavePostGIS = TRUE;
                 nGeometryOID = atoi(pszOid);
             }
-            else if( CSLTestBoolean(CPLGetConfigOption("PG_USE_GEOGRAPHY", "YES")) )
+            else if( CPLTestBool(CPLGetConfigOption("PG_USE_GEOGRAPHY", "YES")) )
             {
                 bHaveGeography = TRUE;
                 nGeographyOID = atoi(pszOid);
@@ -730,7 +783,7 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
         {
             // Turning off sequential scans for PostGIS < 0.8
             hResult = OGRPG_PQexec(hPGConn, "SET ENABLE_SEQSCAN = OFF");
-            
+
             CPLDebug( "PG", "SET ENABLE_SEQSCAN=OFF" );
         }
         else
@@ -762,9 +815,9 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
     else
         nUndefinedSRID = -1;
 
-    osCurrentSchema = GetCurrentSchema();
+    GetCurrentSchema();
 
-    bListAllTables = CSLTestBoolean(CSLFetchNameValueDef(
+    bListAllTables = CPLTestBool(CSLFetchNameValueDef(
         papszOpenOptions, "LIST_ALL_TABLES",
         CPLGetConfigOption("PG_LIST_ALL_TABLES", "NO")));
 
@@ -787,8 +840,7 @@ void OGRPGDataSource::LoadTables()
     CPLHashSet    *hSetTables = NULL;
     std::set<CPLString> osRegisteredLayers;
 
-    int i;
-    for( i = 0; i < nLayers; i++) 
+    for( int i = 0; i < nLayers; i++)
     {
         osRegisteredLayers.insert(papoLayers[i]->GetName());
     }
@@ -799,7 +851,7 @@ void OGRPGDataSource::LoadTables()
 
         papszTableList = CSLTokenizeString2( pszForcedTables, ",", 0 );
 
-        for( i = 0; i < CSLCount(papszTableList); i++ )
+        for( int i = 0; i < CSLCount(papszTableList); i++ )
         {
             char      **papszQualifiedParts;
 
@@ -817,7 +869,7 @@ void OGRPGDataSource::LoadTables()
                 {
                     *pos = '\0';
                     pszGeomColumnName = pos+1;
-                    int len = strlen(pszGeomColumnName);
+                    int len = static_cast<int>(strlen(pszGeomColumnName));
                     if (len > 0)
                         pszGeomColumnName[len - 1] = '\0';
                 }
@@ -851,7 +903,7 @@ void OGRPGDataSource::LoadTables()
 /*      specified through the TABLES connection string param           */
 /* -------------------------------------------------------------------- */
     const char* pszAllowedRelations;
-    if( CSLTestBoolean(CPLGetConfigOption("PG_SKIP_VIEWS", "NO")) )
+    if( CPLTestBool(CPLGetConfigOption("PG_SKIP_VIEWS", "NO")) )
         pszAllowedRelations = "'r'";
     else
         pszAllowedRelations = "'r','v','m','f'";
@@ -861,7 +913,7 @@ void OGRPGDataSource::LoadTables()
     if( nTableCount == 0 && bHavePostGIS && sPostGISVersion.nMajor >= 2 &&
         !bListAllTables &&
         /* Config option mostly for comparison/debugging/etc... */
-        CSLTestBoolean(CPLGetConfigOption("PG_USE_POSTGIS2_OPTIM", "YES")) )
+        CPLTestBool(CPLGetConfigOption("PG_USE_POSTGIS2_OPTIM", "YES")) )
     {
 /* -------------------------------------------------------------------- */
 /*      With PostGIS 2.0, the geometry_columns and geography_columns    */
@@ -875,7 +927,8 @@ void OGRPGDataSource::LoadTables()
               "postgis_typmod_dims(a.atttypmod) dim, "
               "postgis_typmod_srid(a.atttypmod) srid, "
               "postgis_typmod_type(a.atttypmod)::text geomtyp, "
-              "array_agg(s.consrc)::text att_constraints, a.attnotnull "
+              "array_agg(s.consrc)::text att_constraints, a.attnotnull, "
+              "d.description "
               "FROM pg_class c JOIN pg_attribute a ON a.attrelid=c.oid "
               "JOIN pg_namespace n ON c.relnamespace = n.oid "
               "AND c.relkind in (%s) AND NOT ( n.nspname = 'public' AND c.relname = 'raster_columns' ) "
@@ -883,7 +936,8 @@ void OGRPGDataSource::LoadTables()
               "LEFT JOIN pg_constraint s ON s.connamespace = n.oid AND s.conrelid = c.oid "
               "AND a.attnum = ANY (s.conkey) "
               "AND (s.consrc LIKE '%%geometrytype(%% = %%' OR s.consrc LIKE '%%ndims(%% = %%' OR s.consrc LIKE '%%srid(%% = %%') "
-              "GROUP BY c.relname, n.nspname, c.relkind, a.attname, t.typname, dim, srid, geomtyp, a.attnotnull, c.oid, a.attnum "
+              "LEFT JOIN pg_description d ON d.objoid = c.oid AND d.classoid = 'pg_class'::regclass::oid AND d.objsubid = 0 "
+              "GROUP BY c.relname, n.nspname, c.relkind, a.attname, t.typname, dim, srid, geomtyp, a.attnotnull, c.oid, a.attnum, d.description "
               "ORDER BY c.oid, a.attnum",
               pszAllowedRelations);
         hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
@@ -910,6 +964,7 @@ void OGRPGDataSource::LoadTables()
             const char *pszGeomType = PQgetvalue(hResult, iRecord, 7);
             const char *pszConstraint = PQgetvalue(hResult, iRecord, 8);
             const char *pszNotNull = PQgetvalue(hResult, iRecord, 9);
+            const char *pszDescription = PQgetvalue(hResult, iRecord, 10);
             /*const char *pszRelkind = PQgetvalue(hResult, iRecord, 2);
             CPLDebug("PG", "%s %s %s %s %s %s %s %s %s %s",
                      pszTable, pszSchemaName, pszRelkind,
@@ -925,6 +980,7 @@ void OGRPGDataSource::LoadTables()
                 ePostgisType = GEOM_TYPE_GEOGRAPHY;
 
             int nGeomCoordDimension = atoi(pszDim);
+            bool bHasM = pszGeomType[strlen(pszGeomType)-1] == 'M';
             int nSRID = atoi(pszSRID);
 
             /* Analyze constraints that might override geometrytype, */
@@ -946,6 +1002,7 @@ void OGRPGDataSource::LoadTables()
                         osGeometryType = pszNeedle;
                         osGeometryType.resize(pszEnd - pszNeedle);
                         pszGeomType = osGeometryType.c_str();
+                        bHasM = pszGeomType[strlen(pszGeomType)-1] == 'M';
                     }
                 }
             }
@@ -972,24 +1029,38 @@ void OGRPGDataSource::LoadTables()
                 }
             }
 
+            int GeomTypeFlags = 0;
+            if( nGeomCoordDimension == 3 )
+            {
+                if (bHasM)
+                    GeomTypeFlags |= OGRGeometry::OGR_G_MEASURED;
+                else
+                    GeomTypeFlags |= OGRGeometry::OGR_G_3D;
+            }
+            else if( nGeomCoordDimension == 4 )
+            {
+                GeomTypeFlags |= OGRGeometry::OGR_G_3D | OGRGeometry::OGR_G_MEASURED;
+            }
+
             papsTables = (PGTableEntry**)CPLRealloc(papsTables, sizeof(PGTableEntry*) * (nTableCount + 1));
             papsTables[nTableCount] = (PGTableEntry*) CPLCalloc(1, sizeof(PGTableEntry));
             papsTables[nTableCount]->pszTableName = CPLStrdup( pszTable );
             papsTables[nTableCount]->pszSchemaName = CPLStrdup( pszSchemaName );
+            papsTables[nTableCount]->pszDescription = CPLStrdup( pszDescription ? pszDescription : "" );
 
             OGRPGTableEntryAddGeomColumn(papsTables[nTableCount],
                                             pszGeomColumnName,
-                                            pszGeomType, nGeomCoordDimension,
+                                            pszGeomType, GeomTypeFlags,
                                             nSRID, ePostgisType, bNullable);
             nTableCount ++;
 
             PGTableEntry* psEntry = OGRPGFindTableEntry(hSetTables, pszTable, pszSchemaName);
             if (psEntry == NULL)
-                psEntry = OGRPGAddTableEntry(hSetTables, pszTable, pszSchemaName);
+                psEntry = OGRPGAddTableEntry(hSetTables, pszTable, pszSchemaName, pszDescription);
             OGRPGTableEntryAddGeomColumn(psEntry,
                                             pszGeomColumnName,
                                             pszGeomType,
-                                            nGeomCoordDimension,
+                                            GeomTypeFlags,
                                             nSRID, ePostgisType, bNullable);
         }
 
@@ -1003,16 +1074,34 @@ void OGRPGDataSource::LoadTables()
         /* non-PostGIS case it has only 3 columns */
         if ( bHavePostGIS && !bListAllTables )
         {
-            osCommand.Printf(   "SELECT c.relname, n.nspname, c.relkind, g.f_geometry_column, g.type, g.coord_dimension, g.srid, %d, a.attnotnull, c.oid as oid, a.attnum as attnum FROM pg_class c, pg_namespace n, geometry_columns g, pg_attribute a "
-                                "WHERE (c.relkind in (%s) AND c.relname !~ '^pg_' AND c.relnamespace=n.oid "
-                                "AND c.relname::TEXT = g.f_table_name::TEXT AND n.nspname = g.f_table_schema AND a.attname = g.f_geometry_column AND a.attrelid = c.oid) ",
+            osCommand.Printf(   "SELECT c.relname, n.nspname, c.relkind, g.f_geometry_column, "
+                                "g.type, g.coord_dimension, g.srid, %d, a.attnotnull, "
+                                "d.description, c.oid as oid, a.attnum as attnum "
+                                "FROM pg_class c "
+                                "JOIN pg_namespace n ON c.relnamespace=n.oid "
+                                "JOIN geometry_columns g "
+                                "ON c.relname::TEXT = g.f_table_name::TEXT AND n.nspname = g.f_table_schema "
+                                "JOIN pg_attribute a "
+                                "ON a.attname = g.f_geometry_column AND a.attrelid = c.oid "
+                                "LEFT JOIN pg_description d "
+                                "ON d.objoid = c.oid AND d.classoid = 'pg_class'::regclass::oid AND d.objsubid = 0 "
+                                "WHERE c.relkind in (%s) ",
                                 GEOM_TYPE_GEOMETRY, pszAllowedRelations);
 
             if (bHaveGeography)
                 osCommand += CPLString().Printf(
-                                    "UNION SELECT c.relname, n.nspname, c.relkind, g.f_geography_column, g.type, g.coord_dimension, g.srid, %d, a.attnotnull, c.oid as oid, a.attnum as attnum FROM pg_class c, pg_namespace n, geography_columns g, pg_attribute a "
-                                    "WHERE (c.relkind in (%s) AND c.relname !~ '^pg_' AND c.relnamespace=n.oid "
-                                    "AND c.relname::TEXT = g.f_table_name::TEXT AND n.nspname = g.f_table_schema AND a.attname = g.f_geography_column AND a.attrelid = c.oid)",
+                                    "UNION SELECT c.relname, n.nspname, c.relkind, g.f_geography_column, "
+                                    "g.type, g.coord_dimension, g.srid, %d, a.attnotnull, "
+                                    "d.description, c.oid as oid, a.attnum as attnum "
+                                    "FROM pg_class c "
+                                    "JOIN pg_namespace n ON c.relnamespace=n.oid "
+                                    "JOIN geography_columns g "
+                                    "ON c.relname::TEXT = g.f_table_name::TEXT AND n.nspname = g.f_table_schema "
+                                    "JOIN pg_attribute a "
+                                    "ON a.attname = g.f_geography_column AND a.attrelid = c.oid "
+                                    "LEFT JOIN pg_description d "
+                                    "ON d.objoid = c.oid AND d.classoid = 'pg_class'::regclass::oid AND d.objsubid = 0 "
+                                    "WHERE c.relkind in (%s)",
                                     GEOM_TYPE_GEOGRAPHY, pszAllowedRelations);
             osCommand += " ORDER BY oid, attnum";
         }
@@ -1021,7 +1110,7 @@ void OGRPGDataSource::LoadTables()
                                 "SELECT c.relname, n.nspname, c.relkind FROM pg_class c, pg_namespace n "
                                 "WHERE (c.relkind in (%s) AND c.relname !~ '^pg_' AND c.relnamespace=n.oid)",
                                 pszAllowedRelations);
-                            
+
         hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
 
         if( !hResult || PQresultStatus(hResult) != PGRES_TUPLES_OK )
@@ -1043,7 +1132,9 @@ void OGRPGDataSource::LoadTables()
             const char *pszRelkind = PQgetvalue(hResult, iRecord, 2);
             const char *pszGeomColumnName = NULL;
             const char *pszGeomType = NULL;
+            const char *pszDescription = NULL;
             int nGeomCoordDimension = 0;
+            bool bHasM = false;
             int nSRID = 0;
             int bNullable = TRUE;
             PostgisType ePostgisType = GEOM_TYPE_UNKNOWN;
@@ -1051,10 +1142,12 @@ void OGRPGDataSource::LoadTables()
             {
                 pszGeomColumnName = PQgetvalue(hResult, iRecord, 3);
                 pszGeomType = PQgetvalue(hResult, iRecord, 4);
+                bHasM = pszGeomType[strlen(pszGeomType)-1] == 'M';
                 nGeomCoordDimension = atoi(PQgetvalue(hResult, iRecord, 5));
                 nSRID = atoi(PQgetvalue(hResult, iRecord, 6));
                 ePostgisType = (PostgisType) atoi(PQgetvalue(hResult, iRecord, 7));
                 bNullable = EQUAL(PQgetvalue(hResult, iRecord, 8), "f");
+                pszDescription = PQgetvalue(hResult, iRecord, 9);
 
                 /* We cannot reliably find geometry columns of a view that is */
                 /* based on a table that inherits from another one, wit that */
@@ -1072,25 +1165,39 @@ void OGRPGDataSource::LoadTables()
             if( EQUAL(pszSchemaName,"information_schema") )
                 continue;
 
+            int GeomTypeFlags = 0;
+            if( nGeomCoordDimension == 3 )
+            {
+                if (bHasM)
+                    GeomTypeFlags |= OGRGeometry::OGR_G_MEASURED;
+                else
+                    GeomTypeFlags |= OGRGeometry::OGR_G_3D;
+            }
+            else if( nGeomCoordDimension == 4 )
+            {
+                GeomTypeFlags |= OGRGeometry::OGR_G_3D | OGRGeometry::OGR_G_MEASURED;
+            }
+
             papsTables = (PGTableEntry**)CPLRealloc(papsTables, sizeof(PGTableEntry*) * (nTableCount + 1));
             papsTables[nTableCount] = (PGTableEntry*) CPLCalloc(1, sizeof(PGTableEntry));
             papsTables[nTableCount]->pszTableName = CPLStrdup( pszTable );
             papsTables[nTableCount]->pszSchemaName = CPLStrdup( pszSchemaName );
+            papsTables[nTableCount]->pszDescription = CPLStrdup( pszDescription ? pszDescription : "" );
             if (pszGeomColumnName)
                 OGRPGTableEntryAddGeomColumn(papsTables[nTableCount],
                                              pszGeomColumnName,
-                                             pszGeomType, nGeomCoordDimension,
+                                             pszGeomType, GeomTypeFlags,
                                              nSRID, ePostgisType, bNullable);
             nTableCount ++;
 
             PGTableEntry* psEntry = OGRPGFindTableEntry(hSetTables, pszTable, pszSchemaName);
             if (psEntry == NULL)
-                psEntry = OGRPGAddTableEntry(hSetTables, pszTable, pszSchemaName);
+                psEntry = OGRPGAddTableEntry(hSetTables, pszTable, pszSchemaName, pszDescription);
             if (pszGeomColumnName)
                 OGRPGTableEntryAddGeomColumn(psEntry,
                                              pszGeomColumnName,
                                              pszGeomType,
-                                             nGeomCoordDimension,
+                                             GeomTypeFlags,
                                              nSRID, ePostgisType, bNullable);
         }
 
@@ -1103,15 +1210,18 @@ void OGRPGDataSource::LoadTables()
         /* tables */
         if ( bHavePostGIS && !bListAllTables && sPostGISVersion.nMajor < 2 )
         {
-        /* -------------------------------------------------------------------- */
-        /*      Fetch inherited tables                                          */
-        /* -------------------------------------------------------------------- */
-            hResult = OGRPG_PQexec(hPGConn,
-                                "SELECT c1.relname AS derived, c2.relname AS parent, n.nspname "
-                                "FROM pg_class c1, pg_class c2, pg_namespace n, pg_inherits i "
-                                "WHERE i.inhparent = c2.oid AND i.inhrelid = c1.oid AND c1.relnamespace=n.oid "
-                                "AND c1.relkind in ('r', 'v') AND c1.relnamespace=n.oid AND c2.relkind in ('r','v') "
-                                "AND c2.relname !~ '^pg_' AND c2.relnamespace=n.oid");
+        /* ------------------------------------------------------------------ */
+        /*      Fetch inherited tables                                        */
+        /* ------------------------------------------------------------------ */
+            hResult = OGRPG_PQexec(
+                hPGConn,
+                "SELECT c1.relname AS derived, c2.relname AS parent, n.nspname "
+                "FROM pg_class c1, pg_class c2, pg_namespace n, pg_inherits i "
+                "WHERE i.inhparent = c2.oid AND i.inhrelid = c1.oid AND "
+                "c1.relnamespace=n.oid "
+                "AND c1.relkind in ('r', 'v') AND c1.relnamespace=n.oid AND "
+                "c2.relkind in ('r','v') "
+                "AND c2.relname !~ '^pg_' AND c2.relnamespace=n.oid");
 
             if( !hResult || PQresultStatus(hResult) != PGRES_TUPLES_OK )
             {
@@ -1122,9 +1232,9 @@ void OGRPGDataSource::LoadTables()
                 goto end;
             }
 
-        /* -------------------------------------------------------------------- */
-        /*      Parse the returned table list                                   */
-        /* -------------------------------------------------------------------- */
+        /* ------------------------------------------------------------------ */
+        /*      Parse the returned table list                                 */
+        /* ------------------------------------------------------------------ */
             int bHasDoneSomething;
             do
             {
@@ -1157,7 +1267,7 @@ void OGRPGDataSource::LoadTables()
                             bHasDoneSomething = TRUE;
 
                             if (psEntry == NULL)
-                                psEntry = OGRPGAddTableEntry(hSetTables, pszTable, pszSchemaName);
+                                psEntry = OGRPGAddTableEntry(hSetTables, pszTable, pszSchemaName, NULL);
 
                             int iGeomColumn;
                             for(iGeomColumn = 0; iGeomColumn < psParentEntry->nGeomColumnCount; iGeomColumn++)
@@ -1221,8 +1331,9 @@ void OGRPGDataSource::LoadTables()
 
         OGRPGTableLayer* poLayer;
         poLayer = OpenTable( osCurrentSchema, papsTables[iRecord]->pszTableName,
-            papsTables[iRecord]->pszSchemaName,
-            NULL, bDSUpdate, FALSE );
+                             papsTables[iRecord]->pszSchemaName,
+                             papsTables[iRecord]->pszDescription,
+                             NULL, bDSUpdate, FALSE );
         if( psEntry != NULL )
         {
             if( psEntry->nGeomColumnCount > 0 )
@@ -1254,9 +1365,10 @@ end:
 /*                             OpenTable()                              */
 /************************************************************************/
 
-OGRPGTableLayer* OGRPGDataSource::OpenTable( CPLString& osCurrentSchema,
+OGRPGTableLayer* OGRPGDataSource::OpenTable( CPLString& osCurrentSchemaIn,
                                 const char *pszNewName,
                                 const char *pszSchemaName,
+                                const char* pszDescription,
                                 const char * pszGeomColumnForced,
                                 int bUpdate,
                                 int bTestOpen)
@@ -1267,8 +1379,9 @@ OGRPGTableLayer* OGRPGDataSource::OpenTable( CPLString& osCurrentSchema,
 /* -------------------------------------------------------------------- */
     OGRPGTableLayer  *poLayer;
 
-    poLayer = new OGRPGTableLayer( this, osCurrentSchema,
+    poLayer = new OGRPGTableLayer( this, osCurrentSchemaIn,
                                    pszNewName, pszSchemaName,
+                                   pszDescription,
                                    pszGeomColumnForced, bUpdate );
     if( bTestOpen && !(poLayer->ReadTableDefinition()) )
     {
@@ -1290,7 +1403,7 @@ OGRPGTableLayer* OGRPGDataSource::OpenTable( CPLString& osCurrentSchema,
 /*                            DeleteLayer()                             */
 /************************************************************************/
 
-int OGRPGDataSource::DeleteLayer( int iLayer )
+OGRErr OGRPGDataSource::DeleteLayer( int iLayer )
 
 {
     /* Force loading of all registered tables */
@@ -1328,11 +1441,12 @@ int OGRPGDataSource::DeleteLayer( int iLayer )
 
     if( bHavePostGIS  && sPostGISVersion.nMajor < 2)
     {
-        /* This is unnecessary if the layer is not a geometry table, or an inherited geometry table */
-        /* but it shouldn't hurt */
+        // This is unnecessary if the layer is not a geometry table,
+        // or an inherited geometry table but it should not hurt.
         osCommand.Printf(
-                 "DELETE FROM geometry_columns WHERE f_table_name='%s' and f_table_schema='%s'",
-                 osTableName.c_str(), osSchemaName.c_str() );
+            "DELETE FROM geometry_columns WHERE f_table_name='%s' and "
+            "f_table_schema='%s'",
+            osTableName.c_str(), osSchemaName.c_str() );
 
         hResult = OGRPG_PQexec( hPGConn, osCommand.c_str() );
         OGRPGClearResult( hResult );
@@ -1365,55 +1479,80 @@ OGRPGDataSource::ICreateLayer( const char * pszLayerName,
     const char          *pszGeomType = NULL;
     char                *pszTableName = NULL;
     char                *pszSchemaName = NULL;
-    int                 nDimension = 3;
+    int                 GeometryTypeFlags = 0;
 
     if (pszLayerName == NULL)
         return NULL;
 
     EndCopy();
 
-    const char* pszFIDColumnName = CSLFetchNameValue(papszOptions, "FID");
+    const char* pszFIDColumnNameIn = CSLFetchNameValue(papszOptions, "FID");
     CPLString osFIDColumnName;
-    if (pszFIDColumnName == NULL)
+    if (pszFIDColumnNameIn == NULL)
         osFIDColumnName = "ogc_fid";
     else
     {
         if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) )
         {
-            char* pszLaunderedFid = OGRPGCommonLaunderName(pszFIDColumnName, "PG");
-            osFIDColumnName += OGRPGEscapeColumnName(pszLaunderedFid);
+            char* pszLaunderedFid = OGRPGCommonLaunderName(pszFIDColumnNameIn, "PG");
+            osFIDColumnName += pszLaunderedFid;
             CPLFree(pszLaunderedFid);
         }
         else
-            osFIDColumnName += OGRPGEscapeColumnName(pszFIDColumnName);
+            osFIDColumnName += pszFIDColumnNameIn;
     }
-    pszFIDColumnName = osFIDColumnName.c_str();
+    CPLString osFIDColumnNameEscaped = OGRPGEscapeColumnName(osFIDColumnName);
 
-    if (strncmp(pszLayerName, "pg", 2) == 0)
+    if (STARTS_WITH(pszLayerName, "pg"))
     {
         CPLError(CE_Warning, CPLE_AppDefined,
                  "The layer name should not begin by 'pg' as it is a reserved prefix");
     }
 
-    if( wkbFlatten(eType) == eType )
-        nDimension = 2;
+    if( OGR_GT_HasZ((OGRwkbGeometryType)eType) )
+        GeometryTypeFlags |= OGRGeometry::OGR_G_3D;
+    if( OGR_GT_HasM((OGRwkbGeometryType)eType) )
+        GeometryTypeFlags |= OGRGeometry::OGR_G_MEASURED;
 
-    int nForcedDimension = -1;
-    if( CSLFetchNameValue( papszOptions, "DIM") != NULL )
+    int ForcedGeometryTypeFlags = -1;
+    const char* pszDim = CSLFetchNameValue(papszOptions, "DIM");
+    if( pszDim != NULL )
     {
-        nDimension = atoi(CSLFetchNameValue( papszOptions, "DIM"));
-        nForcedDimension = nDimension;
+        if( EQUAL(pszDim, "XY") || EQUAL(pszDim, "2") )
+        {
+            GeometryTypeFlags = 0;
+            ForcedGeometryTypeFlags = GeometryTypeFlags;
+        }
+        else if( EQUAL(pszDim, "XYZ") || EQUAL(pszDim, "3") )
+        {
+            GeometryTypeFlags = OGRGeometry::OGR_G_3D;
+            ForcedGeometryTypeFlags = GeometryTypeFlags;
+        }
+        else if( EQUAL(pszDim, "XYM") )
+        {
+            GeometryTypeFlags = OGRGeometry::OGR_G_MEASURED;
+            ForcedGeometryTypeFlags = GeometryTypeFlags;
+        }
+        else if( EQUAL(pszDim, "XYZM") || EQUAL(pszDim, "4") )
+        {
+            GeometryTypeFlags = OGRGeometry::OGR_G_3D | OGRGeometry::OGR_G_MEASURED;
+            ForcedGeometryTypeFlags = GeometryTypeFlags;
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Invalid value for DIM");
+        }
     }
 
     /* Should we turn layers with None geometry type as Unknown/GEOMETRY */
     /* so they are still recorded in geometry_columns table ? (#4012) */
-    int bNoneAsUnknown = CSLTestBoolean(CSLFetchNameValueDef(
+    int bNoneAsUnknown = CPLTestBool(CSLFetchNameValueDef(
                                     papszOptions, "NONE_AS_UNKNOWN", "NO"));
     if (bNoneAsUnknown && eType == wkbNone)
         eType = wkbUnknown;
 
 
-    int bExtractSchemaFromLayerName = CSLTestBoolean(CSLFetchNameValueDef(
+    int bExtractSchemaFromLayerName = CPLTestBool(CSLFetchNameValueDef(
                                     papszOptions, "EXTRACT_SCHEMA_FROM_LAYER_NAME", "YES"));
 
     /* Postgres Schema handling:
@@ -1424,11 +1563,11 @@ OGRPGDataSource::ICreateLayer( const char * pszLayerName,
     const char* pszDotPos = strstr(pszLayerName,".");
     if ( pszDotPos != NULL && bExtractSchemaFromLayerName )
     {
-      int length = pszDotPos - pszLayerName;
+      int length = static_cast<int>(pszDotPos - pszLayerName);
       pszSchemaName = (char*)CPLMalloc(length+1);
       strncpy(pszSchemaName, pszLayerName, length);
       pszSchemaName[length] = '\0';
-      
+
       if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) )
           pszTableName = OGRPGCommonLaunderName( pszDotPos + 1, "PG" ); //skip "."
       else
@@ -1464,7 +1603,9 @@ OGRPGDataSource::ICreateLayer( const char * pszLayerName,
     int iLayer;
 
     CPLString osSQLLayerName;
-    if (pszSchemaName == NULL || (strlen(osCurrentSchema) > 0 && EQUAL(pszSchemaName, osCurrentSchema.c_str())))
+    if (pszSchemaName == NULL ||
+        ( strlen(osCurrentSchema) > 0 &&
+          EQUAL(pszSchemaName, osCurrentSchema.c_str() ) ) )
         osSQLLayerName = pszTableName;
     else
     {
@@ -1473,10 +1614,10 @@ OGRPGDataSource::ICreateLayer( const char * pszLayerName,
         osSQLLayerName += pszTableName;
     }
 
-    /* GetLayerByName() can instanciate layers that would have been */
+    /* GetLayerByName() can instantiate layers that would have been */
     /* 'hidden' otherwise, for example, non-spatial tables in a */
-    /* Postgis-enabled database, so this apparently useless command is */
-    /* not useless... (#4012) */
+    /* PostGIS-enabled database, so this apparently useless command is */
+    /* not useless. (#4012) */
     CPLPushErrorHandler(CPLQuietErrorHandler);
     GetLayerByName(osSQLLayerName);
     CPLPopErrorHandler();
@@ -1519,7 +1660,7 @@ OGRPGDataSource::ICreateLayer( const char * pszLayerName,
             pszGeomType = "bytea";
     }
 
-    const char *pszGFldName = NULL;
+    const char *pszGFldName = CSLFetchNameValue( papszOptions, "GEOMETRY_NAME");
     if( eType != wkbNone && EQUAL(pszGeomType, "geography") )
     {
         if( !bHaveGeography )
@@ -1533,16 +1674,12 @@ OGRPGDataSource::ICreateLayer( const char * pszLayerName,
             return NULL;
         }
 
-        if( CSLFetchNameValue( papszOptions, "GEOMETRY_NAME") != NULL )
-            pszGFldName = CSLFetchNameValue( papszOptions, "GEOMETRY_NAME");
-        else
+        if( pszGFldName == NULL )
             pszGFldName = "the_geog";
     }
     else if ( eType != wkbNone && bHavePostGIS && !EQUAL(pszGeomType, "geography") )
     {
-        if( CSLFetchNameValue( papszOptions, "GEOMETRY_NAME") != NULL )
-            pszGFldName = CSLFetchNameValue( papszOptions, "GEOMETRY_NAME");
-        else
+        if( pszGFldName == NULL )
             pszGFldName = "wkb_geometry";
     }
 
@@ -1573,13 +1710,13 @@ OGRPGDataSource::ICreateLayer( const char * pszLayerName,
 
     if( poSRS != NULL )
         nSRSId = FetchSRSId( poSRS );
-        
+
     const char *pszGeometryType = OGRToOGCGeomType(eType);
 
-    int bDifferedCreation = CSLTestBoolean(CPLGetConfigOption( "OGR_PG_DIFFERED_CREATION", "YES" ));
+    int bDeferredCreation = CPLTestBool(CPLGetConfigOption( "OGR_PG_DEFERRED_CREATION", "YES" ));
     if( !bHavePostGIS )
-        bDifferedCreation = FALSE;  /* to avoid unnecessary implementation and testing burden */
-    
+        bDeferredCreation = FALSE;  /* to avoid unnecessary implementation and testing burden */
+
 /* -------------------------------------------------------------------- */
 /*      Create a basic table with the FID.  Also include the            */
 /*      geometry if this is not a PostGIS enabled table.                */
@@ -1599,9 +1736,20 @@ OGRPGDataSource::ICreateLayer( const char * pszLayerName,
     else
         osCreateTable.Printf("CREATE%s TABLE %s.%s",
                              CSLFetchBoolean( papszOptions, "UNLOGGED", FALSE ) ? " UNLOGGED": "",
-                             OGRPGEscapeColumnName(pszSchemaName).c_str(), 
+                             OGRPGEscapeColumnName(pszSchemaName).c_str(),
                              OGRPGEscapeColumnName(pszTableName).c_str());
-    
+
+    const char *suffix;
+    if( (GeometryTypeFlags & OGRGeometry::OGR_G_3D) && (GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED) )
+        suffix = "ZM";
+    else if( (GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED) &&
+              (EQUAL(pszGeomType, "geography") || wkbFlatten(eType) != wkbUnknown ) )
+        suffix = "M";
+    else if( GeometryTypeFlags & OGRGeometry::OGR_G_3D )
+        suffix = "Z";
+    else
+        suffix = "";
+
     if( eType != wkbNone && !bHavePostGIS )
     {
         pszGFldName = "wkb_geometry";
@@ -1611,50 +1759,50 @@ OGRPGDataSource::ICreateLayer( const char * pszLayerName,
                  "   %s %s, "
                  "   PRIMARY KEY (%s)",
                  osCreateTable.c_str(),
-                 pszFIDColumnName,
+                 osFIDColumnNameEscaped.c_str(),
                  pszSerialType,
                  pszGFldName,
                  pszGeomType,
-                 pszFIDColumnName);
+                 osFIDColumnNameEscaped.c_str());
     }
-    else if ( !bDifferedCreation && eType != wkbNone && EQUAL(pszGeomType, "geography") )
+    else if ( !bDeferredCreation && eType != wkbNone && EQUAL(pszGeomType, "geography") )
     {
         osCommand.Printf(
                     "%s ( %s %s, %s geography(%s%s%s), PRIMARY KEY (%s)",
                     osCreateTable.c_str(),
-                    pszFIDColumnName,
+                    osFIDColumnNameEscaped.c_str(),
                     pszSerialType,
                     OGRPGEscapeColumnName(pszGFldName).c_str(), pszGeometryType,
-                    nDimension == 2 ? "" : "Z",
-                    nSRSId ? CPLSPrintf(",%d", nSRSId) : "", 
-                    pszFIDColumnName);
+                    suffix,
+                    nSRSId ? CPLSPrintf(",%d", nSRSId) : "",
+                    osFIDColumnNameEscaped.c_str());
     }
-    else if ( !bDifferedCreation && eType != wkbNone && !EQUAL(pszGeomType, "geography") &&
+    else if ( !bDeferredCreation && eType != wkbNone && !EQUAL(pszGeomType, "geography") &&
               sPostGISVersion.nMajor >= 2 )
     {
         osCommand.Printf(
                     "%s ( %s %s, %s geometry(%s%s%s), PRIMARY KEY (%s)",
                     osCreateTable.c_str(),
-                    pszFIDColumnName,
+                    osFIDColumnNameEscaped.c_str(),
                     pszSerialType,
                     OGRPGEscapeColumnName(pszGFldName).c_str(), pszGeometryType,
-                    nDimension == 2 ? "" : "Z",
-                    nSRSId ? CPLSPrintf(",%d", nSRSId) : "", 
-                    pszFIDColumnName);
+                    suffix,
+                    nSRSId ? CPLSPrintf(",%d", nSRSId) : "",
+                    osFIDColumnNameEscaped.c_str());
     }
     else
     {
         osCommand.Printf(
                  "%s ( %s %s, PRIMARY KEY (%s)",
                  osCreateTable.c_str(),
-                 pszFIDColumnName,
+                 osFIDColumnNameEscaped.c_str(),
                  pszSerialType,
-                 pszFIDColumnName );
+                 osFIDColumnNameEscaped.c_str() );
     }
     osCreateTable = osCommand;
 
     const char *pszSI = CSLFetchNameValue( papszOptions, "SPATIAL_INDEX" );
-    int bCreateSpatialIndex = ( pszSI == NULL || CSLTestBoolean(pszSI) );
+    int bCreateSpatialIndex = ( pszSI == NULL || CPLTestBool(pszSI) );
     if( eType != wkbNone &&
         pszSI == NULL &&
         CSLFetchBoolean( papszOptions, "UNLOGGED", FALSE ) &&
@@ -1685,8 +1833,8 @@ OGRPGDataSource::ICreateLayer( const char * pszLayerName,
         hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
         OGRPGClearResult( hResult );
     }
-    
-    if( !bDifferedCreation )
+
+    if( !bDeferredCreation )
     {
         SoftStartTransaction();
 
@@ -1717,11 +1865,16 @@ OGRPGDataSource::ICreateLayer( const char * pszLayerName,
         if( eType != wkbNone && bHavePostGIS && !EQUAL(pszGeomType, "geography") &&
             sPostGISVersion.nMajor <= 1 )
         {
+            int dim = 2;
+            if( GeometryTypeFlags & OGRGeometry::OGR_G_3D )
+                dim++;
+            if( GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED )
+                dim++;
             osCommand.Printf(
                     "SELECT AddGeometryColumn(%s,%s,%s,%d,'%s',%d)",
                     pszEscapedSchemaNameSingleQuote, pszEscapedTableNameSingleQuote,
                     OGRPGEscapeString(hPGConn, pszGFldName).c_str(),
-                    nSRSId, pszGeometryType, nDimension );
+                    nSRSId, pszGeometryType, dim );
 
             hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
 
@@ -1744,7 +1897,7 @@ OGRPGDataSource::ICreateLayer( const char * pszLayerName,
 
             OGRPGClearResult( hResult );
         }
-        
+
         if( eType != wkbNone && bHavePostGIS && bCreateSpatialIndex )
         {
     /* -------------------------------------------------------------------- */
@@ -1794,16 +1947,19 @@ OGRPGDataSource::ICreateLayer( const char * pszLayerName,
     OGRPGTableLayer     *poLayer;
 
     poLayer = new OGRPGTableLayer( this, osCurrentSchema, pszTableName,
-                                   pszSchemaName, NULL, TRUE );
-    poLayer->SetTableDefinition(pszFIDColumnName, pszGFldName, eType,
-                                pszGeomType, nSRSId, nDimension);
+                                   pszSchemaName, "", NULL, TRUE );
+    poLayer->SetTableDefinition(osFIDColumnName, pszGFldName, eType,
+                                pszGeomType, nSRSId, GeometryTypeFlags);
     poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) );
     poLayer->SetPrecisionFlag( CSLFetchBoolean(papszOptions,"PRECISION",TRUE));
     //poLayer->SetForcedSRSId(nForcedSRSId);
-    poLayer->SetForcedDimension(nForcedDimension);
+    poLayer->SetForcedGeometryTypeFlags(ForcedGeometryTypeFlags);
     poLayer->SetCreateSpatialIndexFlag(bCreateSpatialIndex);
-    poLayer->SetDifferedCreation(bDifferedCreation, osCreateTable);
-    
+    poLayer->SetDeferredCreation(bDeferredCreation, osCreateTable);
+
+    const char* pszDescription = CSLFetchNameValue(papszOptions, "DESCRIPTION");
+    if( pszDescription != NULL )
+        poLayer->SetForcedDescription( pszDescription );
 
     /* HSTORE_COLUMNS existed at a time during GDAL 1.10dev */
     const char* pszHSTOREColumns = CSLFetchNameValue( papszOptions, "HSTORE_COLUMNS" );
@@ -1814,7 +1970,7 @@ OGRPGDataSource::ICreateLayer( const char * pszLayerName,
     poLayer->SetOverrideColumnTypes(pszOverrideColumnTypes);
 
     poLayer->AllowAutoFIDOnCreateViaCopy();
-    if( CSLTestBoolean(CPLGetConfigOption("PG_USE_COPY", "YES")) )
+    if( CPLTestBool(CPLGetConfigOption("PG_USE_COPY", "YES")) )
         poLayer->SetUseCopy();
 
     if( bFID64 )
@@ -1841,7 +1997,7 @@ OGRPGDataSource::ICreateLayer( const char * pszLayerName,
 int OGRPGDataSource::TestCapability( const char * pszCap )
 
 {
-    if( EQUAL(pszCap,ODsCCreateLayer) 
+    if( EQUAL(pszCap,ODsCCreateLayer)
         || EQUAL(pszCap,ODsCDeleteLayer)
         || EQUAL(pszCap,ODsCCreateGeomFieldAfterCreateLayer) )
         return TRUE;
@@ -1849,6 +2005,8 @@ int OGRPGDataSource::TestCapability( const char * pszCap )
         return TRUE;
     else if( EQUAL(pszCap,ODsCTransactions) )
         return TRUE;
+    else if ( EQUAL(pszCap,ODsCMeasuredGeometries) )
+        return TRUE;
     else
         return FALSE;
 }
@@ -1881,48 +2039,48 @@ OGRLayer *OGRPGDataSource::GetLayer( int iLayer )
 /*                           GetLayerByName()                           */
 /************************************************************************/
 
-OGRLayer *OGRPGDataSource::GetLayerByName( const char *pszName )
+OGRLayer *OGRPGDataSource::GetLayerByName( const char *pszNameIn )
 
 {
     char* pszTableName = NULL;
     char *pszGeomColumnName = NULL;
     char *pszSchemaName = NULL;
 
-    if ( ! pszName )
+    if ( ! pszNameIn )
         return NULL;
 
     int  i;
-    
+
     /* first a case sensitive check */
     /* do NOT force loading of all registered tables */
     for( i = 0; i < nLayers; i++ )
     {
         OGRPGTableLayer *poLayer = papoLayers[i];
 
-        if( strcmp( pszName, poLayer->GetName() ) == 0 )
+        if( strcmp( pszNameIn, poLayer->GetName() ) == 0 )
         {
             return poLayer;
         }
     }
-        
+
     /* then case insensitive */
     for( i = 0; i < nLayers; i++ )
     {
         OGRPGTableLayer *poLayer = papoLayers[i];
 
-        if( EQUAL( pszName, poLayer->GetName() ) )
+        if( EQUAL( pszNameIn, poLayer->GetName() ) )
         {
             return poLayer;
         }
     }
 
-    char* pszNameWithoutBracket = CPLStrdup(pszName);
+    char* pszNameWithoutBracket = CPLStrdup(pszNameIn);
     char *pos = strchr(pszNameWithoutBracket, '(');
     if (pos != NULL)
     {
         *pos = '\0';
         pszGeomColumnName = CPLStrdup(pos+1);
-        int len = strlen(pszGeomColumnName);
+        int len = static_cast<int>(strlen(pszGeomColumnName));
         if (len > 0)
             pszGeomColumnName[len - 1] = '\0';
     }
@@ -1959,6 +2117,7 @@ OGRLayer *OGRPGDataSource::GetLayerByName( const char *pszName )
             CPLPushErrorHandler(CPLQuietErrorHandler);
         poLayer = OpenTable( osCurrentSchema, pszTableName,
                              pszSchemaName,
+                             NULL,
                              pszGeomColumnName,
                              bDSUpdate, TRUE );
         if( osTableName != osTableNameLower )
@@ -1967,6 +2126,7 @@ OGRLayer *OGRPGDataSource::GetLayerByName( const char *pszName )
         {
             poLayer = OpenTable( osCurrentSchema, osTableNameLower,
                                 pszSchemaName,
+                                NULL,
                                 pszGeomColumnName,
                                 bDSUpdate, TRUE );
         }
@@ -2091,7 +2251,6 @@ int OGRPGDataSource::FetchSRSId( OGRSpatialReference * poSRS )
     PGresult            *hResult = NULL;
     CPLString           osCommand;
     char                *pszWKT = NULL;
-    int                 nSRSId = nUndefinedSRID;
     const char*         pszAuthorityName;
 
     if( poSRS == NULL )
@@ -2142,7 +2301,7 @@ int OGRPGDataSource::FetchSRSId( OGRSpatialReference * poSRS )
             if( hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK
                 && PQntuples(hResult) > 0 )
             {
-                nSRSId = atoi(PQgetvalue( hResult, 0, 0 ));
+                int nSRSId = atoi(PQgetvalue( hResult, 0, 0 ));
 
                 OGRPGClearResult( hResult );
 
@@ -2179,7 +2338,7 @@ int OGRPGDataSource::FetchSRSId( OGRSpatialReference * poSRS )
     if( hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK
         && PQntuples(hResult) > 0 )
     {
-        nSRSId = atoi(PQgetvalue( hResult, 0, 0 ));
+        int nSRSId = atoi(PQgetvalue( hResult, 0, 0 ));
 
         OGRPGClearResult( hResult );
 
@@ -2208,6 +2367,7 @@ int OGRPGDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 /* -------------------------------------------------------------------- */
     hResult = OGRPG_PQexec(hPGConn, "SELECT MAX(srid) FROM spatial_ref_sys" );
 
+    int nSRSId;
     if( hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK )
     {
         nSRSId = atoi(PQgetvalue(hResult,0,0)) + 1;
@@ -2326,7 +2486,7 @@ OGRErr OGRPGDataSource::CommitTransaction()
     {
         CPLAssert(nSoftTransactionLevel > 0);
         bSavePointActive = FALSE;
-        
+
         eErr = DoTransactionCommand("RELEASE SAVEPOINT ogr_savepoint");
     }
     else
@@ -2426,7 +2586,7 @@ OGRErr OGRPGDataSource::SoftCommitTransaction()
 
 {
     EndCopy();
-    
+
     /*CPLDebug("PG", "poDS=%p SoftCommitTransaction() nSoftTransactionLevel=%d",
              this, nSoftTransactionLevel);*/
 
@@ -2459,7 +2619,7 @@ OGRErr OGRPGDataSource::SoftRollbackTransaction()
 
 {
     EndCopy();
-    
+
     /*CPLDebug("PG", "poDS=%p SoftRollbackTransaction() nSoftTransactionLevel=%d",
              this, nSoftTransactionLevel);*/
 
@@ -2491,16 +2651,12 @@ OGRErr OGRPGDataSource::SoftRollbackTransaction()
 OGRErr OGRPGDataSource::FlushSoftTransaction()
 
 {
-    FlushCache(); 
-    
     /*CPLDebug("PG", "poDS=%p FlushSoftTransaction() nSoftTransactionLevel=%d",
              this, nSoftTransactionLevel);*/
 
     if( nSoftTransactionLevel <= 0 )
         return OGRERR_NONE;
 
-    for(int i=0;i<nLayers;i++)
-        papoLayers[i]->InvalidateCursor();
     bSavePointActive = FALSE;
 
     OGRErr eErr = OGRERR_NONE;
@@ -2522,9 +2678,9 @@ OGRErr OGRPGDataSource::DoTransactionCommand(const char* pszCommand)
 {
     OGRErr      eErr = OGRERR_NONE;
     PGresult    *hResult = NULL;
-    PGconn      *hPGConn = GetPGConn();
+    PGconn      *l_hPGConn = GetPGConn();
 
-    hResult = OGRPG_PQexec(hPGConn, pszCommand);
+    hResult = OGRPG_PQexec(l_hPGConn, pszCommand);
     osDebugLastTransactionCommand = pszCommand;
 
     if( !hResult || PQresultStatus(hResult) != PGRES_COMMAND_OK )
@@ -2554,7 +2710,7 @@ class OGRPGNoResetResultLayer : public OGRPGLayer
     virtual int         TestCapability( const char * ) { return FALSE; }
 
     virtual OGRFeature *GetNextFeature();
-    
+
     virtual CPLString   GetFromClauseForGetExtent() { CPLAssert(FALSE); return ""; }
     virtual void        ResolveSRID(OGRPGGeomFieldDefn* poGFldDefn) { poGFldDefn->nSRSId = -1; }
 };
@@ -2610,7 +2766,7 @@ OGRFeature *OGRPGNoResetResultLayer::GetNextFeature()
     return RecordToFeature(hCursorResult,
                            m_panMapFieldNameToIndex,
                            m_panMapFieldNameToGeomIndex,
-                           iNextShapeId ++);
+                           static_cast<int>(iNextShapeId ++));
 }
 
 /************************************************************************/
@@ -2663,7 +2819,7 @@ const char* OGRPGDataSource::GetMetadataItem(const char* pszKey,
             osDebugLastTransactionCommand = "";
             return pszRet;
         }
-            
+
     }
     return OGRDataSource::GetMetadataItem(pszKey, pszDomain);
 }
@@ -2695,17 +2851,17 @@ OGRLayer * OGRPGDataSource::ExecuteSQL( const char *pszSQLCommand,
 /* -------------------------------------------------------------------- */
 /*      Special case DELLAYER: command.                                 */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszSQLCommand,"DELLAYER:",9) )
+    if( STARTS_WITH_CI(pszSQLCommand, "DELLAYER:") )
     {
         const char *pszLayerName = pszSQLCommand + 9;
 
         while( *pszLayerName == ' ' )
             pszLayerName++;
-        
+
         GetLayerCount();
         for( int iLayer = 0; iLayer < nLayers; iLayer++ )
         {
-            if( EQUAL(papoLayers[iLayer]->GetName(), 
+            if( EQUAL(papoLayers[iLayer]->GetName(),
                       pszLayerName ))
             {
                 DeleteLayer( iLayer );
@@ -2720,7 +2876,7 @@ OGRLayer * OGRPGDataSource::ExecuteSQL( const char *pszSQLCommand,
 /* -------------------------------------------------------------------- */
     PGresult    *hResult = NULL;
 
-    if (EQUALN(pszSQLCommand, "SELECT", 6) == FALSE ||
+    if (STARTS_WITH_CI(pszSQLCommand, "SELECT") == FALSE ||
         (strstr(pszSQLCommand, "from") == NULL && strstr(pszSQLCommand, "FROM") == NULL))
     {
         /* For something that is not a select or a select without table, do not */
@@ -2772,11 +2928,11 @@ OGRLayer * OGRPGDataSource::ExecuteSQL( const char *pszSQLCommand,
             poLayer = new OGRPGResultLayer( this, pszSQLCommand, hResult );
 
             OGRPGClearResult( hResult );
-            
+
             osCommand.Printf( "CLOSE %s", "executeSQLCursor" );
             hResult = OGRPG_PQexec(hPGConn, osCommand );
             OGRPGClearResult( hResult );
-            
+
             SoftCommitTransaction();
 
             if( poSpatialFilter != NULL )
@@ -2834,4 +2990,3 @@ OGRErr OGRPGDataSource::EndCopy( )
     else
         return OGRERR_NONE;
 }
-
diff --git a/ogr/ogrsf_frmts/pg/ogrpgdriver.cpp b/ogr/ogrsf_frmts/pg/ogrpgdriver.cpp
index 7d04ee8..15bb1a5 100644
--- a/ogr/ogrsf_frmts/pg/ogrpgdriver.cpp
+++ b/ogr/ogrsf_frmts/pg/ogrpgdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgdriver.cpp 29019 2015-04-25 20:34:19Z rouault $
+ * $Id: ogrpgdriver.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGDriver class.
@@ -30,7 +30,7 @@
 #include "ogr_pg.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrpgdriver.cpp 29019 2015-04-25 20:34:19Z rouault $");
+CPL_CVSID("$Id: ogrpgdriver.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 
 /************************************************************************/
@@ -39,8 +39,8 @@ CPL_CVSID("$Id: ogrpgdriver.cpp 29019 2015-04-25 20:34:19Z rouault $");
 
 static int OGRPGDriverIdentify( GDALOpenInfo* poOpenInfo )
 {
-    if( !EQUALN(poOpenInfo->pszFilename,"PGB:",4) &&
-        !EQUALN(poOpenInfo->pszFilename,"PG:",3) )
+    if( !STARTS_WITH_CI(poOpenInfo->pszFilename, "PGB:") &&
+        !STARTS_WITH_CI(poOpenInfo->pszFilename, "PG:") )
         return FALSE;
     return TRUE;
 }
@@ -79,17 +79,17 @@ static GDALDataset *OGRPGDriverCreate( const char * pszName,
                                           CPL_UNUSED int nXSize,
                                           CPL_UNUSED int nYSize,
                                           CPL_UNUSED GDALDataType eDT,
-                                          CPL_UNUSED char **papszOptions )
+                                          char **papszOptions )
 
 {
     OGRPGDataSource     *poDS;
 
     poDS = new OGRPGDataSource();
 
-    if( !poDS->Open( pszName, TRUE, TRUE, NULL ) )
+    if( !poDS->Open( pszName, TRUE, TRUE, papszOptions ) )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
          "PostgreSQL driver doesn't currently support database creation.\n"
                   "Please create database with the `createdb' command." );
         return NULL;
@@ -107,22 +107,19 @@ void RegisterOGRPG()
 {
     if (! GDAL_CHECK_VERSION("PG driver"))
         return;
-    
-    if( GDALGetDriverByName( "PostgreSQL" ) == NULL )
-    {
-        GDALDriver* poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "PostgreSQL" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                  "PostgreSQL/PostGIS" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    if( GDALGetDriverByName( "PostgreSQL" ) != NULL )
+        return;
 
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                    "drv_pg.html" );
+    GDALDriver* poDriver = new GDALDriver();
 
-        poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, "PG:" );
+    poDriver->SetDescription( "PostgreSQL" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "PostgreSQL/PostGIS" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_pg.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, "PG:" );
 
-        poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
 "<OpenOptionList>"
 "  <Option name='DBNAME' type='string' description='Database name'/>"
 "  <Option name='PORT' type='int' description='Port'/>"
@@ -133,11 +130,14 @@ void RegisterOGRPG()
 "  <Option name='SCHEMAS' type='string' description='Restricted sets of schemas to explore (comma separated)'/>"
 "  <Option name='TABLES' type='string' description='Restricted set of tables to list (comma separated)'/>"
 "  <Option name='LIST_ALL_TABLES' type='boolean' description='Whether all tables, including non-spatial ones, should be listed' default='NO'/>"
+"  <Option name='PRELUDE_STATEMENTS' type='string' description='SQL statement(s) to send on the PostgreSQL client connection before any other ones'/>"
+"  <Option name='CLOSING_STATEMENTS' type='string' description='SQL statements() to send on the PostgreSQL client connection after any other ones'/>"
 "</OpenOptionList>");
 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, "<CreationOptionList/>");
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+                               "<CreationOptionList/>");
 
-        poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
 "<LayerCreationOptionList>"
 "  <Option name='GEOM_TYPE' type='string-select' description='Format of geometry columns' default='geometry'>"
 "    <Value>geometry</Value>"
@@ -148,7 +148,7 @@ void RegisterOGRPG()
 "  <Option name='OVERWRITE' type='boolean' description='Whether to overwrite an existing table with the layer name to be created' default='NO'/>"
 "  <Option name='LAUNDER' type='boolean' description='Whether layer and field names will be laundered' default='YES'/>"
 "  <Option name='PRECISION' type='boolean' description='Whether fields created should keep the width and precision' default='YES'/>"
-"  <Option name='DIM' type='integer' description='Set to 2 to force the geometries to be 2D, or 3 to be 2.5D'/>"
+"  <Option name='DIM' type='string' description='Set to 2 to force the geometries to be 2D, 3 to be 2.5D, XYM or XYZM'/>"
 "  <Option name='GEOMETRY_NAME' type='string' description='Name of geometry column. Defaults to wkb_geometry for GEOM_TYPE=geometry or the_geog for GEOM_TYPE=geography'/>"
 "  <Option name='SCHEMA' type='string' description='Name of schema into which to create the new table'/>"
 "  <Option name='SPATIAL_INDEX' type='boolean' description='Whether to create a spatial index' default='YES'/>"
@@ -159,18 +159,20 @@ void RegisterOGRPG()
 "  <Option name='FID64' type='boolean' description='Whether to create the FID column with BIGSERIAL type to handle 64bit wide ids' default='NO'/>"
 "  <Option name='EXTRACT_SCHEMA_FROM_LAYER_NAME' type='boolean' description='Whether a dot in a layer name should be considered as the separator for the schema and table name' default='YES'/>"
 "  <Option name='COLUMN_TYPES' type='string' description='A list of strings of format field_name=pg_field_type (separated by comma) to force the PG column type of fields to be created'/>"
+"  <Option name='DESCRIPTION' type='string' description='Description string to put in the pg_description system table'/>"
 "</LayerCreationOptionList>");
-        
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES, "Integer Integer64 Real String Date DateTime Time IntegerList Integer64List RealList StringList Binary" );
-        poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_FIELDS, "YES" );
-        poDriver->SetMetadataItem( GDAL_DCAP_DEFAULT_FIELDS, "YES" );
-        poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_GEOMFIELDS, "YES" );
 
-        poDriver->pfnOpen = OGRPGDriverOpen;
-        poDriver->pfnIdentify = OGRPGDriverIdentify;
-        poDriver->pfnCreate = OGRPGDriverCreate;
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
+                               "Integer Integer64 Real String Date DateTime "
+                               "Time IntegerList Integer64List RealList "
+                               "StringList Binary" );
+    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_FIELDS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_DEFAULT_FIELDS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_GEOMFIELDS, "YES" );
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
-}
+    poDriver->pfnOpen = OGRPGDriverOpen;
+    poDriver->pfnIdentify = OGRPGDriverIdentify;
+    poDriver->pfnCreate = OGRPGDriverCreate;
 
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/ogr/ogrsf_frmts/pg/ogrpglayer.cpp b/ogr/ogrsf_frmts/pg/ogrpglayer.cpp
index 22d1f67..f2a9187 100644
--- a/ogr/ogrsf_frmts/pg/ogrpglayer.cpp
+++ b/ogr/ogrsf_frmts/pg/ogrpglayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpglayer.cpp 29330 2015-06-14 12:11:11Z rouault $
+ * $Id: ogrpglayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGLayer class  which implements shared handling
@@ -65,7 +65,7 @@ PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 
 #define PQexec this_is_an_error
 
-CPL_CVSID("$Id: ogrpglayer.cpp 29330 2015-06-14 12:11:11Z rouault $");
+CPL_CVSID("$Id: ogrpglayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 // These originally are defined in libpq-fs.h.
 
@@ -131,6 +131,8 @@ OGRPGLayer::~OGRPGLayer()
         poFeatureDefn->UnsetLayer();
         poFeatureDefn->Release();
     }
+
+    CloseCursor();
 }
 
 /************************************************************************/
@@ -149,7 +151,7 @@ void OGRPGLayer::CloseCursor()
         osCommand.Printf("CLOSE %s", pszCursorName );
 
         /* In case of interleaving read in different layers we might have */
-        /* close the transaction, and thus implicitely the cursor, so be */
+        /* close the transaction, and thus implicitly the cursor, so be */
         /* quiet about errors. This is potentially an issue by the way */
         hCursorResult = OGRPG_PQexec(hPGConn, osCommand.c_str(), FALSE, TRUE);
         OGRPGClearResult( hCursorResult );
@@ -185,6 +187,7 @@ void OGRPGLayer::ResetReading()
     bInvalidated = FALSE;
 }
 
+#if defined(BINARY_CURSOR_ENABLED)
 /************************************************************************/
 /*                    OGRPGGetStrFromBinaryNumeric()                    */
 /************************************************************************/
@@ -210,9 +213,9 @@ typedef struct NumericVar
 /*
 * get_str_from_var() -
 *
-*	Convert a var to text representation (guts of numeric_out).
-*	CAUTION: var's contents may be modified by rounding!
-*	Returns a palloc'd string.
+*       Convert a var to text representation (guts of numeric_out).
+*       CAUTION: var's contents may be modified by rounding!
+*       Returns a malloc'd string.
 */
 static char *
 OGRPGGetStrFromBinaryNumeric(NumericVar *var)
@@ -224,7 +227,7 @@ OGRPGGetStrFromBinaryNumeric(NumericVar *var)
         int			d;
         NumericDigit dig;
         NumericDigit d1;
-        
+
         int dscale = var->dscale;
 
         /*
@@ -262,9 +265,10 @@ OGRPGGetStrFromBinaryNumeric(NumericVar *var)
                 {
                         dig = (d < var->ndigits) ? var->digits[d] : 0;
                         CPL_MSBPTR16(&dig);
-                        /* In the first digit, suppress extra leading decimal zeroes */
+                        /* In the first digit, suppress extra leading
+                           decimal zeroes */
                         {
-                                bool		putit = (d > 0);
+                                bool putit = (d > 0);
 
                                 d1 = dig / 1000;
                                 dig -= d1 * 1000;
@@ -285,8 +289,8 @@ OGRPGGetStrFromBinaryNumeric(NumericVar *var)
                         }
                 }
         }
-        
-                /*
+
+        /*
         * If requested, output a decimal point and all the digits that follow it.
         * We initially put out a multiple of DEC_DIGITS digits, then truncate if
         * needed.
@@ -443,6 +447,7 @@ int OGRPGTimeStamp2DMYHMS(GIntBig dt, int *year, int *month, int *day,
         return 0;
 }
 
+#endif // defined(BINARY_CURSOR_ENABLED)
 
 /************************************************************************/
 /*                   TokenizeStringListFromText()                       */
@@ -598,7 +603,7 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
     {
         int     iOGRField;
 
-#if !defined(PG_PRE74)
+#if !defined(PG_PRE74) && defined(BINARY_CURSOR_ENABLED)
         int nTypeOID = PQftype(hResult, iField);
 #endif
         const char* pszFieldName = PQfname(hResult,iField);
@@ -608,7 +613,7 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
 /* -------------------------------------------------------------------- */
         if( pszFIDColumn != NULL && EQUAL(pszFieldName,pszFIDColumn) )
         {
-#if !defined(PG_PRE74)
+#if !defined(PG_PRE74) && defined(BINARY_CURSOR_ENABLED)
             if ( PQfformat( hResult, iField ) == 1 ) // Binary data representation
             {
                 if ( nTypeOID == INT4OID)
@@ -656,33 +661,8 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
                 poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOMETRY ||
                 poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOGRAPHY) )
         {
-            if ( !poDS->bUseBinaryCursor &&
-                 EQUALN(pszFieldName,"BinaryBase64", strlen("BinaryBase64")) )
-            {
-                GByte* pabyData = (GByte*)PQgetvalue( hResult,
-                                                        iRecord, iField);
-
-                int nLength = PQgetlength(hResult, iRecord, iField);
-
-                /* No geometry */
-                if (nLength == 0)
-                    continue;
-
-                nLength = CPLBase64DecodeInPlace(pabyData);
-                OGRGeometry * poGeom = NULL;
-                OGRGeometryFactory::createFromWkb( pabyData, NULL, &poGeom, nLength,
-                                                   (poDS->sPostGISVersion.nMajor < 2) ? wkbVariantPostGIS1 : wkbVariantOldOgc );
-
-                if( poGeom != NULL )
-                {
-                    poGeom->assignSpatialReference( poGeomFieldDefn->GetSpatialRef() );
-                    poFeature->SetGeomFieldDirectly(iOGRGeomField,  poGeom );
-                }
-
-                continue;
-            }
-            else if ( EQUALN(pszFieldName,"ST_AsBinary", strlen("ST_AsBinary")) ||
-                      EQUALN(pszFieldName,"AsBinary", strlen("AsBinary")) )
+            if ( STARTS_WITH_CI(pszFieldName, "ST_AsBinary") ||
+                      STARTS_WITH_CI(pszFieldName, "AsBinary") )
             {
                 GByte* pabyVal = (GByte*) PQgetvalue( hResult,
                                              iRecord, iField);
@@ -693,20 +673,20 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
                 /* No geometry */
                 if (nLength == 0)
                     continue;
-                    
+
                 OGRGeometry * poGeom = NULL;
                 if( !poDS->bUseBinaryCursor && nLength >= 4 &&
                     /* escaped byea data */
-                    (strncmp(pszVal, "\\000",4) == 0 || strncmp(pszVal, "\\001",4) == 0 ||
+                    (STARTS_WITH(pszVal, "\\000") || STARTS_WITH(pszVal, "\\001") ||
                     /* hex bytea data (PostgreSQL >= 9.0) */
-                     strncmp(pszVal, "\\x00",4) == 0 || strncmp(pszVal, "\\x01",4) == 0) )
+                     STARTS_WITH(pszVal, "\\x00") || STARTS_WITH(pszVal, "\\x01")) )
                 {
                     poGeom = BYTEAToGeometry(pszVal, (poDS->sPostGISVersion.nMajor < 2));
                 }
                 else
                     OGRGeometryFactory::createFromWkb( pabyVal, NULL, &poGeom, nLength,
                                                        (poDS->sPostGISVersion.nMajor < 2) ? wkbVariantPostGIS1 : wkbVariantOldOgc );
-                
+
                 if( poGeom != NULL )
                 {
                     poGeom->assignSpatialReference( poGeomFieldDefn->GetSpatialRef() );
@@ -716,7 +696,7 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
                 continue;
             }
             else if ( !poDS->bUseBinaryCursor &&
-                      EQUALN(pszFieldName,"EWKBBase64",strlen("EWKBBase64")) )
+                      STARTS_WITH_CI(pszFieldName, "EWKBBase64") )
             {
                 GByte* pabyData = (GByte*)PQgetvalue( hResult,
                                                         iRecord, iField);
@@ -756,15 +736,15 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
                 OGRGeometry * poGeom;
 
                 if( !poDS->bUseBinaryCursor &&
-                    (strncmp(pabyData, "\\x00",4) == 0 || strncmp(pabyData, "\\x01",4) == 0 ||
-                     strncmp(pabyData, "\\000",4) == 0 || strncmp(pabyData, "\\001",4) == 0) )
+                    (STARTS_WITH(pabyData, "\\x00") || STARTS_WITH(pabyData, "\\x01") ||
+                     STARTS_WITH(pabyData, "\\000") || STARTS_WITH(pabyData, "\\001")) )
                 {
                     GByte* pabyEWKB = BYTEAToGByteArray(pabyData, &nLength);
                     poGeom = OGRGeometryFromEWKB(pabyEWKB, nLength, NULL,
                                                  poDS->sPostGISVersion.nMajor < 2);
                     CPLFree(pabyEWKB);
                 }
-                else if( nLength >= 2 && (EQUALN(pabyData,"00",2) || EQUALN(pabyData,"01",2)) )
+                else if( nLength >= 2 && (STARTS_WITH_CI(pabyData, "00") || STARTS_WITH_CI(pabyData, "01")) )
                 {
                     poGeom = OGRGeometryFromHexEWKB(pabyData, NULL,
                                                     poDS->sPostGISVersion.nMajor < 2);
@@ -798,7 +778,7 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
 
                 // optionally strip off PostGIS SRID identifier.  This
                 // happens if we got a raw geometry field.
-                if( EQUALN(pszPostSRID,"SRID=",5) )
+                if( STARTS_WITH_CI(pszPostSRID, "SRID=") )
                 {
                     while( *pszPostSRID != '\0' && *pszPostSRID != ';' )
                         pszPostSRID++;
@@ -806,7 +786,7 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
                         pszPostSRID++;
                 }
 
-                if( EQUALN(pszPostSRID,"00",2) || EQUALN(pszPostSRID,"01",2) )
+                if( STARTS_WITH_CI(pszPostSRID, "00") || STARTS_WITH_CI(pszPostSRID, "01") )
                 {
                     poGeometry = OGRGeometryFromHexEWKB( pszWKT, NULL,
                                                          poDS->sPostGISVersion.nMajor < 2 );
@@ -827,7 +807,7 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
 /*      Handle raw binary geometry ... this hasn't been tested in a     */
 /*      while.                                                          */
 /* -------------------------------------------------------------------- */
-        else if( iOGRGeomField >= 0 && 
+        else if( iOGRGeomField >= 0 &&
                  poGeomFieldDefn->ePostgisType == GEOM_TYPE_WKB )
         {
             OGRGeometry *poGeometry = NULL;
@@ -840,9 +820,10 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
             }
             else
             {
+#if defined(BINARY_CURSOR_ENABLED)
                 if (poDS->bUseBinaryCursor
 #if !defined(PG_PRE74)
-                    && PQfformat( hResult, iField ) == 1 
+                    && PQfformat( hResult, iField ) == 1
 #endif
                    )
                 {
@@ -850,6 +831,7 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
                     poGeometry = OGRGeometryFromEWKB(pabyData, nLength, NULL,
                                                      poDS->sPostGISVersion.nMajor < 2 );
                 }
+#endif
                 if (poGeometry == NULL)
                 {
                     poGeometry = BYTEAToGeometry( (const char*)pabyData,
@@ -877,17 +859,17 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
         if( PQgetisnull( hResult, iRecord, iField ) )
             continue;
 
-        OGRFieldType eOGRType = 
+        OGRFieldType eOGRType =
             poFeatureDefn->GetFieldDefn(iOGRField)->GetType();
 
         if( eOGRType == OFTIntegerList)
         {
             int *panList, nCount, i;
 
-#if !defined(PG_PRE74)
+#if !defined(PG_PRE74) && defined(BINARY_CURSOR_ENABLED)
             if ( PQfformat( hResult, iField ) == 1 ) // Binary data representation
             {
-                if (nTypeOID == INT4ARRAYOID)
+                if (nTypeOID == INT2ARRAYOID || nTypeOID == INT4ARRAYOID)
                 {
                     char * pData = PQgetvalue( hResult, iRecord, iField );
 
@@ -906,13 +888,22 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
                         // get element size
                         int nSize = *(int *)(pData);
                         CPL_MSBPTR32( &nSize );
-
-                        CPLAssert( nSize == sizeof(int) );
-
                         pData += sizeof(int);
 
-                        memcpy( &panList[i], pData, nSize );
-                        CPL_MSBPTR32(&panList[i]);
+                        if (nTypeOID == INT4ARRAYOID  )
+                        {
+                            CPLAssert( nSize == sizeof(int) );
+                            memcpy( &panList[i], pData, nSize );
+                            CPL_MSBPTR32(&panList[i]);
+                        }
+                        else
+                        {
+                            CPLAssert( nSize == sizeof(GInt16) );
+                            GInt16 nVal;
+                            memcpy( &nVal, pData, nSize );
+                            CPL_MSBPTR16(&nVal);
+                            panList[i] = nVal;
+                        }
 
                         pData += nSize;
                     }
@@ -955,7 +946,7 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
             GIntBig *panList;
             int nCount, i;
 
-#if !defined(PG_PRE74)
+#if !defined(PG_PRE74) && defined(BINARY_CURSOR_ENABLED)
             if ( PQfformat( hResult, iField ) == 1 ) // Binary data representation
             {
                 if (nTypeOID == INT8ARRAYOID)
@@ -1026,7 +1017,7 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
             int nCount, i;
             double *padfList;
 
-#if !defined(PG_PRE74)
+#if !defined(PG_PRE74) && defined(BINARY_CURSOR_ENABLED)
             if ( PQfformat( hResult, iField ) == 1 ) // Binary data representation
             {
                 if (nTypeOID == FLOAT8ARRAYOID || nTypeOID == FLOAT4ARRAYOID)
@@ -1100,9 +1091,9 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
 
         else if( eOGRType == OFTStringList )
         {
-            char **papszTokens = 0;
+            char **papszTokens = NULL;
 
-#if !defined(PG_PRE74)
+#if !defined(PG_PRE74) && defined(BINARY_CURSOR_ENABLED)
             if ( PQfformat( hResult, iField ) == 1 ) // Binary data representation
             {
                 char * pData = PQgetvalue( hResult, iRecord, iField );
@@ -1157,11 +1148,11 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
             }
         }
 
-        else if( eOGRType == OFTDate 
-                 || eOGRType == OFTTime 
+        else if( eOGRType == OFTDate
+                 || eOGRType == OFTTime
                  || eOGRType == OFTDateTime )
         {
-#if !defined(PG_PRE74)
+#if !defined(PG_PRE74) && defined(BINARY_CURSOR_ENABLED)
             if ( PQfformat( hResult, iField ) == 1 ) // Binary data
             {
                 if ( nTypeOID == DATEOID )
@@ -1196,7 +1187,7 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
                         CPL_MSBPTR64(&dfVal);
                         OGRPGdt2timeFloat8(dfVal, &nHour, &nMinute, &nSecond, &dfsec);
                     }
-                    sprintf(szTime, "%02d:%02d:%02d", nHour, nMinute, nSecond);
+                    snprintf(szTime, sizeof(szTime), "%02d:%02d:%02d", nHour, nMinute, nSecond);
                     poFeature->SetField( iOGRField, szTime);
                 }
                 else if ( nTypeOID == TIMESTAMPOID || nTypeOID == TIMESTAMPTZOID )
@@ -1204,7 +1195,7 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
                     unsigned int nVal[2];
                     GIntBig llVal;
                     int nYear, nMonth, nDay, nHour, nMinute;
-                    double dfSecond;
+                    double dfSecond = 0.0;
                     CPLAssert(PQgetlength(hResult, iRecord, iField) == 8);
                     memcpy( nVal, PQgetvalue( hResult, iRecord, iField ), 8 );
                     CPL_MSBPTR32(&nVal[0]);
@@ -1242,7 +1233,7 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
         }
         else if( eOGRType == OFTBinary )
         {
-#if !defined(PG_PRE74)
+#if !defined(PG_PRE74) && defined(BINARY_CURSOR_ENABLED)
             if ( PQfformat( hResult, iField ) == 1)
             {
                 int nLength = PQgetlength(hResult, iRecord, iField);
@@ -1261,7 +1252,7 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
         }
         else
         {
-#if !defined(PG_PRE74)
+#if !defined(PG_PRE74) && defined(BINARY_CURSOR_ENABLED)
             if ( PQfformat( hResult, iField ) == 1 &&
                  eOGRType != OFTString ) // Binary data
             {
@@ -1360,9 +1351,9 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
                      poFeatureDefn->GetFieldDefn(iOGRField)->GetWidth() == 1)
                 {
                     char* pabyData = PQgetvalue( hResult, iRecord, iField );
-                    if (EQUALN(pabyData, "T", 1))
+                    if (STARTS_WITH_CI(pabyData, "T"))
                         poFeature->SetField( iOGRField, 1);
-                    else if (EQUALN(pabyData, "F", 1))
+                    else if (STARTS_WITH_CI(pabyData, "F"))
                         poFeature->SetField( iOGRField, 0);
                     else
                         poFeature->SetField( iOGRField, pabyData);
@@ -1388,16 +1379,16 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
 /*                    OGRPGIsKnownGeomFuncPrefix()                      */
 /************************************************************************/
 
-static const char* papszKnownGeomFuncPrefixes[] = {
-    "ST_AsBinary", "BinaryBase64", "ST_AsEWKT", "ST_AsEWKB", "EWKBBase64",
+static const char* const apszKnownGeomFuncPrefixes[] = {
+    "ST_AsBinary", "ST_AsEWKT", "ST_AsEWKB", "EWKBBase64",
     "ST_AsText", "AsBinary", "asEWKT", "asEWKB", "asText" };
 static int OGRPGIsKnownGeomFuncPrefix(const char* pszFieldName)
 {
-    for(size_t i=0; i<sizeof(papszKnownGeomFuncPrefixes) / sizeof(char*); i++)
+    for(size_t i=0; i<sizeof(apszKnownGeomFuncPrefixes) / sizeof(char*); i++)
     {
-        if( EQUALN(pszFieldName, papszKnownGeomFuncPrefixes[i],
-                   strlen(papszKnownGeomFuncPrefixes[i])) )
-            return i;
+        if( EQUALN(pszFieldName, apszKnownGeomFuncPrefixes[i],
+                   static_cast<int>(strlen(apszKnownGeomFuncPrefixes[i]))) )
+            return static_cast<int>(i);
     }
     return -1;
 }
@@ -1440,11 +1431,11 @@ void OGRPGLayer::CreateMapFromFieldNameToIndex(PGresult* hResult,
                 {
                     int iKnownPrefix = OGRPGIsKnownGeomFuncPrefix(pszName);
                     if( iKnownPrefix >= 0 &&
-                        pszName[ strlen(papszKnownGeomFuncPrefixes[iKnownPrefix]) ] == '_' )
+                        pszName[ strlen(apszKnownGeomFuncPrefixes[iKnownPrefix]) ] == '_' )
                     {
                         panMapFieldNameToGeomIndex[iField] =
                             poFeatureDefn->GetGeomFieldIndex(pszName +
-                            strlen(papszKnownGeomFuncPrefixes[iKnownPrefix]) + 1);
+                            strlen(apszKnownGeomFuncPrefixes[iKnownPrefix]) + 1);
                     }
                 }
             }
@@ -1468,10 +1459,12 @@ void OGRPGLayer::SetInitialQueryCursor()
 
     poDS->SoftStartTransaction();
 
+#if defined(BINARY_CURSOR_ENABLED)
     if ( poDS->bUseBinaryCursor && bCanUseBinaryCursor )
         osCommand.Printf( "DECLARE %s BINARY CURSOR for %s",
                             pszCursorName, pszQueryStatement );
     else
+#endif
         osCommand.Printf( "DECLARE %s CURSOR for %s",
                             pszCursorName, pszQueryStatement );
 
@@ -1512,7 +1505,7 @@ OGRFeature *OGRPGLayer::GetNextRawFeature()
                  "ResetReading() must be explicitly called to restart reading");
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Do we need to establish an initial query?                       */
 /* -------------------------------------------------------------------- */
@@ -1545,7 +1538,7 @@ OGRFeature *OGRPGLayer::GetNextRawFeature()
         nResultOffset == PQntuples(hCursorResult) )
     {
         OGRPGClearResult( hCursorResult );
-        
+
         osCommand.Printf( "FETCH %d in %s", nCursorPage, pszCursorName );
         hCursorResult = OGRPG_PQexec(hPGConn, osCommand );
 
@@ -1596,29 +1589,29 @@ OGRErr OGRPGLayer::SetNextByIndex( GIntBig nIndex )
     {
         return OGRERR_NONE;
     }
-    
+
     if( nIndex < 0 )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Invalid index");
         return OGRERR_FAILURE;
     }
-    
+
     if( nIndex == 0 )
     {
         ResetReading();
         return OGRERR_NONE;
     }
-    
+
     PGconn      *hPGConn = poDS->GetPGConn();
     CPLString   osCommand;
-    
+
     if (hCursorResult == NULL )
     {
         SetInitialQueryCursor();
     }
-    
+
     OGRPGClearResult( hCursorResult );
-    
+
     osCommand.Printf( "FETCH ABSOLUTE " CPL_FRMT_GIB " in %s", nIndex+1, pszCursorName );
     hCursorResult = OGRPG_PQexec(hPGConn, osCommand );
 
@@ -1637,7 +1630,7 @@ OGRErr OGRPGLayer::SetNextByIndex( GIntBig nIndex )
 
     nResultOffset = 0;
     iNextShapeId = nIndex;
-    
+
     return OGRERR_NONE;
 }
 
@@ -1660,7 +1653,8 @@ GByte* OGRPGLayer::BYTEAToGByteArray( const char *pszBytea, int* pnLength )
     if (pszBytea[0] == '\\' && pszBytea[1] == 'x')
         return CPLHexToBinary(pszBytea + 2, pnLength);
 
-    pabyData = (GByte *) CPLMalloc(strlen(pszBytea));
+    /* +1 just to please Coverity that thinks we allocate for a null-terminate string */
+    pabyData = (GByte *) CPLMalloc(strlen(pszBytea)+1);
 
     while( pszBytea[iSrc] != '\0' )
     {
@@ -1731,7 +1725,8 @@ char* OGRPGLayer::GByteArrayToBYTEA( const GByte* pabyData, int nLen)
 {
     char* pszTextBuf;
 
-    pszTextBuf = (char *) CPLMalloc(nLen*5+1);
+    const size_t nTextBufLen = nLen*5+1;
+    pszTextBuf = (char *) CPLMalloc(nTextBufLen);
 
     int  iSrc, iDst=0;
 
@@ -1740,7 +1735,7 @@ char* OGRPGLayer::GByteArrayToBYTEA( const GByte* pabyData, int nLen)
         if( pabyData[iSrc] < 40 || pabyData[iSrc] > 126
             || pabyData[iSrc] == '\\' )
         {
-            sprintf( pszTextBuf+iDst, "\\\\%03o", pabyData[iSrc] );
+            snprintf( pszTextBuf+iDst, nTextBufLen-iDst, "\\\\%03o", pabyData[iSrc] );
             iDst += 5;
         }
         else
@@ -1755,7 +1750,7 @@ char* OGRPGLayer::GByteArrayToBYTEA( const GByte* pabyData, int nLen)
 /*                          GeometryToBYTEA()                           */
 /************************************************************************/
 
-char *OGRPGLayer::GeometryToBYTEA( OGRGeometry * poGeometry, int bIsPostGIS1 )
+char *OGRPGLayer::GeometryToBYTEA( OGRGeometry * poGeometry, int nPostGISMajor, int nPostGISMinor )
 
 {
     int         nWkbSize = poGeometry->WkbSize();
@@ -1763,8 +1758,18 @@ char *OGRPGLayer::GeometryToBYTEA( OGRGeometry * poGeometry, int bIsPostGIS1 )
     char        *pszTextBuf;
 
     pabyWKB = (GByte *) CPLMalloc(nWkbSize);
-    if( poGeometry->exportToWkb( wkbNDR, pabyWKB,
-                                 (bIsPostGIS1) ? wkbVariantPostGIS1 : wkbVariantOldOgc ) != OGRERR_NONE )
+    if( (nPostGISMajor > 2 || (nPostGISMajor == 2 && nPostGISMinor >= 2)) &&
+        wkbFlatten(poGeometry->getGeometryType()) == wkbPoint &&
+        poGeometry->IsEmpty() )
+    {
+        if( poGeometry->exportToWkb( wkbNDR, pabyWKB, wkbVariantIso ) != OGRERR_NONE )
+        {
+            CPLFree( pabyWKB );
+            return CPLStrdup("");
+        }
+    }
+    else if( poGeometry->exportToWkb( wkbNDR, pabyWKB,
+                                 (nPostGISMajor < 2) ? wkbVariantPostGIS1 : wkbVariantOldOgc ) != OGRERR_NONE )
     {
         CPLFree(pabyWKB);
         return CPLStrdup("");
@@ -1880,7 +1885,7 @@ OGRErr OGRPGLayer::RollbackTransaction()
 /*                            GetFIDColumn()                            */
 /************************************************************************/
 
-const char *OGRPGLayer::GetFIDColumn() 
+const char *OGRPGLayer::GetFIDColumn()
 
 {
     GetLayerDefn();
@@ -2008,11 +2013,11 @@ OGRErr OGRPGLayer::RunGetExtentRequest( OGREnvelope *psExtent,
     }
 
     // Take X,Y coords
-    // For PostGis ver >= 1.0.0 -> Tokens: X1 Y1 X2 Y2 (nTokenCnt = 4)
+    // For PostGIS ver >= 1.0.0 -> Tokens: X1 Y1 X2 Y2 (nTokenCnt = 4)
     // For PostGIS ver < 1.0.0 -> Tokens: X1 Y1 Z1 X2 Y2 Z2 (nTokenCnt = 6)
     // =>   X2 index calculated as nTokenCnt/2
-    //      Y2 index caluclated as nTokenCnt/2+1
-    
+    //      Y2 index calculated as nTokenCnt/2+1
+
     psExtent->MinX = CPLAtof( papszTokens[0] );
     psExtent->MinY = CPLAtof( papszTokens[1] );
     psExtent->MaxX = CPLAtof( papszTokens[nTokenCnt/2] );
@@ -2081,10 +2086,10 @@ int OGRPGLayer::ReadResultDefinition(PGresult *hInitialResultIn)
                 new OGRPGGeomFieldDefn(this, oField.GetNameRef());
             if( iGeomFuncPrefix >= 0 &&
                 oField.GetNameRef()[strlen(
-                    papszKnownGeomFuncPrefixes[iGeomFuncPrefix])] == '_' )
+                    apszKnownGeomFuncPrefixes[iGeomFuncPrefix])] == '_' )
             {
                 poGeomFieldDefn->SetName( oField.GetNameRef() +
-                    strlen(papszKnownGeomFuncPrefixes[iGeomFuncPrefix]) + 1 );
+                    strlen(apszKnownGeomFuncPrefixes[iGeomFuncPrefix]) + 1 );
             }
             if (nTypeOID == poDS->GetGeographyOID())
             {
@@ -2106,7 +2111,7 @@ int OGRPGLayer::ReadResultDefinition(PGresult *hInitialResultIn)
             poFeatureDefn->AddGeomFieldDefn(poGeomFieldDefn, FALSE);
             continue;
         }
-            
+
         //CPLDebug("PG", "Field %s, oid %d", oField.GetNameRef(), nTypeOID);
 
         if( nTypeOID == BYTEAOID )
@@ -2158,7 +2163,7 @@ int OGRPGLayer::ReadResultDefinition(PGresult *hInitialResultIn)
         {
             oField.SetType( OFTReal );
         }
-        else if( nTypeOID == NUMERICOID )
+        else if( nTypeOID == NUMERICOID || nTypeOID == NUMERICARRAYOID )
         {
             /* See http://www.mail-archive.com/pgsql-hackers@postgresql.org/msg57726.html */
             /* typmod = (width << 16) + precision + 4 */
@@ -2169,18 +2174,18 @@ int OGRPGLayer::ReadResultDefinition(PGresult *hInitialResultIn)
                 int nPrecision = (nTypmod - 4) & 0xFFFF;
                 if (nWidth <= 10 && nPrecision == 0)
                 {
-                    oField.SetType( OFTInteger );
+                    oField.SetType( (nTypeOID == NUMERICOID) ? OFTInteger : OFTIntegerList );
                     oField.SetWidth( nWidth );
                 }
                 else
                 {
-                    oField.SetType( OFTReal );
+                    oField.SetType( (nTypeOID == NUMERICOID) ? OFTReal : OFTRealList );
                     oField.SetWidth( nWidth );
                     oField.SetPrecision( nPrecision );
                 }
             }
             else
-                oField.SetType( OFTReal );
+                oField.SetType( (nTypeOID == NUMERICOID) ? OFTReal : OFTRealList );
         }
         else if ( nTypeOID == BOOLARRAYOID )
         {
@@ -2188,6 +2193,11 @@ int OGRPGLayer::ReadResultDefinition(PGresult *hInitialResultIn)
             oField.SetSubType( OFSTBoolean );
             oField.SetWidth( 1 );
         }
+        else if ( nTypeOID == INT2ARRAYOID )
+        {
+            oField.SetType ( OFTIntegerList );
+            oField.SetSubType( OFSTInt16 );
+        }
         else if ( nTypeOID == INT4ARRAYOID )
         {
             oField.SetType ( OFTIntegerList );
@@ -2196,8 +2206,12 @@ int OGRPGLayer::ReadResultDefinition(PGresult *hInitialResultIn)
         {
             oField.SetType ( OFTInteger64List );
         }
-        else if ( nTypeOID == FLOAT4ARRAYOID ||
-                  nTypeOID == FLOAT8ARRAYOID )
+        else if ( nTypeOID == FLOAT4ARRAYOID )
+        {
+          oField.SetType ( OFTRealList );
+          oField.SetSubType( OFSTFloat32 );
+        }
+        else if ( nTypeOID == FLOAT8ARRAYOID )
         {
             oField.SetType ( OFTRealList );
         }
@@ -2218,10 +2232,12 @@ int OGRPGLayer::ReadResultDefinition(PGresult *hInitialResultIn)
         else if ( nTypeOID == TIMESTAMPOID ||
                   nTypeOID == TIMESTAMPTZOID )
         {
+#if defined(BINARY_CURSOR_ENABLED)
             /* We can't deserialize properly timestamp with time zone */
             /* with binary cursors */
             if (nTypeOID == TIMESTAMPTZOID)
                 bCanUseBinaryCursor = FALSE;
+#endif
 
             oField.SetType( OFTDateTime );
         }
diff --git a/ogr/ogrsf_frmts/pg/ogrpgresultlayer.cpp b/ogr/ogrsf_frmts/pg/ogrpgresultlayer.cpp
index 88e50f9..87cc9bc 100644
--- a/ogr/ogrsf_frmts/pg/ogrpgresultlayer.cpp
+++ b/ogr/ogrsf_frmts/pg/ogrpgresultlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgresultlayer.cpp 28481 2015-02-13 17:11:15Z rouault $
+ * $Id: ogrpgresultlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGResultLayer class, access the resultset from
@@ -32,7 +32,7 @@
 #include "cpl_conv.h"
 #include "ogr_pg.h"
 
-CPL_CVSID("$Id: ogrpgresultlayer.cpp 28481 2015-02-13 17:11:15Z rouault $");
+CPL_CVSID("$Id: ogrpgresultlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 #define PQexec this_is_an_error
 
@@ -40,7 +40,7 @@ CPL_CVSID("$Id: ogrpgresultlayer.cpp 28481 2015-02-13 17:11:15Z rouault $");
 /*                          OGRPGResultLayer()                          */
 /************************************************************************/
 
-OGRPGResultLayer::OGRPGResultLayer( OGRPGDataSource *poDSIn, 
+OGRPGResultLayer::OGRPGResultLayer( OGRPGDataSource *poDSIn,
                                     const char * pszRawQueryIn,
                                     PGresult *hInitialResultIn )
 {
@@ -65,8 +65,7 @@ OGRPGResultLayer::OGRPGResultLayer( OGRPGDataSource *poDSIn,
     CPLString osRequest;
     std::map< std::pair<int,int>, int> oMapAttributeToFieldIndex;
 
-    int iRawField;
-    for( iRawField = 0; iRawField < PQnfields(hInitialResultIn); iRawField++ )
+    for( int iRawField = 0; iRawField < PQnfields(hInitialResultIn); iRawField++ )
     {
         if( poFeatureDefn->GetGeomFieldCount() == 1 &&
             strcmp(PQfname(hInitialResultIn,iRawField),
@@ -82,9 +81,9 @@ OGRPGResultLayer::OGRPGResultLayer( OGRPGDataSource *poDSIn,
             if( osRequest.size() )
                 osRequest += " OR ";
             osRequest += "(attrelid = ";
-            osRequest += CPLSPrintf("%d", tableOID); 
+            osRequest += CPLSPrintf("%d", tableOID);
             osRequest += " AND attnum = ";
-            osRequest += CPLSPrintf("%d)", tableCol); 
+            osRequest += CPLSPrintf("%d)", tableCol);
             oMapAttributeToFieldIndex[std::pair<int,int>(tableOID,tableCol)] = iRawField;
         }
     }
@@ -167,12 +166,13 @@ void OGRPGResultLayer::BuildFullQueryStatement()
         pszQueryStatement = NULL;
     }
 
-    pszQueryStatement = (char*) CPLMalloc(strlen(pszRawStatement) + strlen(osWHERE) + 40);
+    const size_t nLen = strlen(pszRawStatement) + strlen(osWHERE) + 40;
+    pszQueryStatement = (char*) CPLMalloc(nLen);
 
     if (strlen(osWHERE) == 0)
         strcpy(pszQueryStatement, pszRawStatement);
     else
-        sprintf(pszQueryStatement, "SELECT * FROM (%s) AS ogrpgsubquery %s",
+        snprintf(pszQueryStatement, nLen, "SELECT * FROM (%s) AS ogrpgsubquery %s",
                 pszRawStatement, osWHERE.c_str());
 }
 
@@ -224,7 +224,7 @@ int OGRPGResultLayer::TestCapability( const char * pszCap )
 
 {
     GetLayerDefn();
-    
+
     if( EQUAL(pszCap,OLCFastFeatureCount) ||
         EQUAL(pszCap,OLCFastSetNextByIndex) )
     {
@@ -234,7 +234,7 @@ int OGRPGResultLayer::TestCapability( const char * pszCap )
         return (m_poFilterGeom == NULL ||
                 poGeomFieldDefn == NULL ||
                 poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOMETRY ||
-                poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOGRAPHY ) 
+                poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOGRAPHY )
                && m_poAttrQuery == NULL;
     }
     else if( EQUAL(pszCap,OLCFastSpatialFilter) )
@@ -244,7 +244,7 @@ int OGRPGResultLayer::TestCapability( const char * pszCap )
             poGeomFieldDefn = poFeatureDefn->myGetGeomFieldDefn(m_iGeomFieldFilter);
         return (poGeomFieldDefn == NULL ||
                 poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOMETRY ||
-                poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOGRAPHY ) 
+                poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOGRAPHY )
                && m_poAttrQuery == NULL;
     }
 
@@ -254,7 +254,7 @@ int OGRPGResultLayer::TestCapability( const char * pszCap )
         if( poFeatureDefn->GetGeomFieldCount() > 0 )
             poGeomFieldDefn = poFeatureDefn->myGetGeomFieldDefn(0);
         return (poGeomFieldDefn == NULL ||
-                poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOMETRY ) 
+                poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOMETRY )
                && m_poAttrQuery == NULL;
     }
     else if( EQUAL(pszCap,OLCStringsAsUTF8) )
@@ -276,7 +276,7 @@ OGRFeature *OGRPGResultLayer::GetNextFeature()
     if( poFeatureDefn->GetGeomFieldCount() != 0 )
         poGeomFieldDefn = poFeatureDefn->myGetGeomFieldDefn(m_iGeomFieldFilter);
 
-    for( ; TRUE; )
+    while( true )
     {
         OGRFeature      *poFeature;
 
@@ -407,6 +407,8 @@ void OGRPGResultLayer::ResolveSRID(OGRPGGeomFieldDefn* poGFldDefn)
             osGetSRID += psGetSRIDFct;
             osGetSRID += "(";
             osGetSRID += OGRPGEscapeColumnName(poGFldDefn->GetNameRef());
+            if (poDS->sPostGISVersion.nMajor > 2 || (poDS->sPostGISVersion.nMajor == 2 && poDS->sPostGISVersion.nMinor >= 2))
+                osGetSRID += "::geometry";
             osGetSRID += ") FROM(";
             osGetSRID += pszRawStatement;
             osGetSRID += ") AS ogrpggetsrid LIMIT 1";
diff --git a/ogr/ogrsf_frmts/pg/ogrpgtablelayer.cpp b/ogr/ogrsf_frmts/pg/ogrpgtablelayer.cpp
index 558f39a..ffd7d80 100644
--- a/ogr/ogrsf_frmts/pg/ogrpgtablelayer.cpp
+++ b/ogr/ogrsf_frmts/pg/ogrpgtablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgtablelayer.cpp 29330 2015-06-14 12:11:11Z rouault $
+ * $Id: ogrpgtablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
 
  *
  * Project:  OpenGIS Simple Features Reference Implementation
@@ -37,7 +37,7 @@
 
 #define PQexec this_is_an_error
 
-CPL_CVSID("$Id: ogrpgtablelayer.cpp 29330 2015-06-14 12:11:11Z rouault $");
+CPL_CVSID("$Id: ogrpgtablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 
 #define USE_COPY_UNSET  -10
@@ -106,7 +106,7 @@ void OGRPGTableFeatureDefn::SolveFields()
 /*                            GetFIDColumn()                            */
 /************************************************************************/
 
-const char *OGRPGTableLayer::GetFIDColumn() 
+const char *OGRPGTableLayer::GetFIDColumn()
 
 {
     ReadTableDefinition();
@@ -125,7 +125,8 @@ OGRPGTableLayer::OGRPGTableLayer( OGRPGDataSource *poDSIn,
                                   CPLString& osCurrentSchema,
                                   const char * pszTableNameIn,
                                   const char * pszSchemaNameIn,
-                                  const char * pszGeomColForced,
+                                  const char * pszDescriptionIn,
+                                  const char * pszGeomColForcedIn,
                                   int bUpdate )
 
 {
@@ -151,7 +152,7 @@ OGRPGTableLayer::OGRPGTableLayer( OGRPGDataSource *poDSIn,
     else
         pszSchemaName = CPLStrdup( osCurrentSchema );
     this->pszGeomColForced =
-        pszGeomColForced ? CPLStrdup(pszGeomColForced) : NULL;
+        pszGeomColForcedIn ? CPLStrdup(pszGeomColForcedIn) : NULL;
 
     pszSqlGeomParentTableName = NULL;
     bTableDefinitionValid = -1;
@@ -160,7 +161,7 @@ OGRPGTableLayer::OGRPGTableLayer( OGRPGDataSource *poDSIn,
     bHasWarnedAlreadySetFID = FALSE;
 
     /* Just in provision for people yelling about broken backward compatibility ... */
-    bRetrieveFID = CSLTestBoolean(CPLGetConfigOption("OGR_PG_RETRIEVE_FID", "TRUE"));
+    bRetrieveFID = CPLTestBool(CPLGetConfigOption("OGR_PG_RETRIEVE_FID", "TRUE"));
 
 /* -------------------------------------------------------------------- */
 /*      Build the layer defn name.                                      */
@@ -190,18 +191,24 @@ OGRPGTableLayer::OGRPGTableLayer( OGRPGDataSource *poDSIn,
 
     papszOverrideColumnTypes = NULL;
     nForcedSRSId = UNDETERMINED_SRID;
-    nForcedDimension = -1;
+    nForcedGeometryTypeFlags = -1;
     bCreateSpatialIndexFlag = TRUE;
     bInResetReading = FALSE;
 
     poFeatureDefn = new OGRPGTableFeatureDefn( this, osDefnName );
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
-    
+
     bAutoFIDOnCreateViaCopy = FALSE;
-    
-    bDifferedCreation = FALSE;
+
+    bDeferredCreation = FALSE;
     iFIDAsRegularColumnIndex = -1;
+
+    pszDescription = (pszDescriptionIn) ? CPLStrdup(pszDescriptionIn) : NULL;
+    if( pszDescriptionIn != NULL && !EQUAL(pszDescriptionIn, "") )
+    {
+        OGRLayer::SetMetadataItem("DESCRIPTION", pszDescriptionIn);
+    }
 }
 
 //************************************************************************/
@@ -211,24 +218,151 @@ OGRPGTableLayer::OGRPGTableLayer( OGRPGDataSource *poDSIn,
 OGRPGTableLayer::~OGRPGTableLayer()
 
 {
-    if( bDifferedCreation ) RunDifferedCreationIfNecessary();
+    if( bDeferredCreation ) RunDeferredCreationIfNecessary();
     if ( bCopyActive ) EndCopy();
     CPLFree( pszSqlTableName );
     CPLFree( pszTableName );
     CPLFree( pszSqlGeomParentTableName );
     CPLFree( pszSchemaName );
+    CPLFree( pszDescription );
     CPLFree( pszGeomColForced );
     CSLDestroy( papszOverrideColumnTypes );
 }
 
 /************************************************************************/
+/*                          GetMetadataDomainList()                     */
+/************************************************************************/
+
+char ** OGRPGTableLayer::GetMetadataDomainList()
+{
+    if( pszDescription == NULL )
+        GetMetadata();
+    if( pszDescription[0] != '\0' )
+        return CSLAddString(NULL, "");
+    return NULL;
+}
+
+/************************************************************************/
+/*                              GetMetadata()                           */
+/************************************************************************/
+
+char ** OGRPGTableLayer::GetMetadata(const char* pszDomain)
+{
+    if( (pszDomain == NULL || EQUAL(pszDomain, "")) &&
+        pszDescription == NULL )
+    {
+        PGconn              *hPGConn = poDS->GetPGConn();
+        CPLString osCommand;
+        osCommand.Printf(
+            "SELECT d.description FROM pg_class c "
+            "JOIN pg_namespace n ON c.relnamespace=n.oid "
+            "JOIN pg_description d "
+            "ON d.objoid = c.oid AND d.classoid = 'pg_class'::regclass::oid AND d.objsubid = 0 "
+            "WHERE c.relname = %s AND n.nspname = %s AND c.relkind in ('r', 'v') ",
+            OGRPGEscapeString(hPGConn, pszTableName).c_str(),
+            OGRPGEscapeString(hPGConn, pszSchemaName).c_str());
+        PGresult* hResult = OGRPG_PQexec(hPGConn, osCommand.c_str() );
+
+        const char* pszDesc = NULL;
+        if ( hResult && PGRES_TUPLES_OK == PQresultStatus(hResult) &&
+             PQntuples( hResult ) == 1  )
+        {
+            pszDesc = PQgetvalue(hResult,0,0);
+            if( pszDesc )
+                OGRLayer::SetMetadataItem("DESCRIPTION", pszDesc);
+        }
+        pszDescription = CPLStrdup(pszDesc ? pszDesc : "");
+
+        OGRPGClearResult( hResult );
+    }
+
+    return OGRLayer::GetMetadata(pszDomain);
+}
+
+/************************************************************************/
+/*                            GetMetadataItem()                         */
+/************************************************************************/
+
+const char *OGRPGTableLayer::GetMetadataItem(const char* pszName, const char* pszDomain)
+{
+    GetMetadata(pszDomain);
+    return OGRLayer::GetMetadataItem(pszName, pszDomain);
+}
+
+/************************************************************************/
+/*                              SetMetadata()                           */
+/************************************************************************/
+
+CPLErr OGRPGTableLayer::SetMetadata(char** papszMD, const char* pszDomain)
+{
+    OGRLayer::SetMetadata(papszMD, pszDomain);
+    if( osForcedDescription.size() && (pszDomain == NULL || EQUAL(pszDomain, "")) )
+    {
+        OGRLayer::SetMetadataItem("DESCRIPTION", osForcedDescription);
+    }
+
+    if( !bDeferredCreation && (pszDomain == NULL || EQUAL(pszDomain, "")) )
+    {
+        const char* l_pszDescription = OGRLayer::GetMetadataItem("DESCRIPTION");
+        PGconn              *hPGConn = poDS->GetPGConn();
+        CPLString osCommand;
+
+        osCommand.Printf( "COMMENT ON TABLE %s IS %s",
+                           pszSqlTableName,
+                           l_pszDescription && l_pszDescription[0] != '\0' ?
+                              OGRPGEscapeString(hPGConn, l_pszDescription).c_str() : "NULL" );
+        PGresult* hResult = OGRPG_PQexec(hPGConn, osCommand.c_str() );
+        OGRPGClearResult( hResult );
+
+        CPLFree(pszDescription);
+        pszDescription = CPLStrdup(l_pszDescription ? l_pszDescription : "");
+    }
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                            SetMetadataItem()                         */
+/************************************************************************/
+
+CPLErr OGRPGTableLayer::SetMetadataItem(const char* pszName, const char* pszValue,
+                                        const char* pszDomain)
+{
+    if( (pszDomain == NULL || EQUAL(pszDomain, "")) && pszName != NULL &&
+        EQUAL(pszName, "DESCRIPTION") && osForcedDescription.size() )
+    {
+        pszValue = osForcedDescription;
+    }
+    OGRLayer::SetMetadataItem(pszName, pszValue, pszDomain);
+    if( !bDeferredCreation &&
+        (pszDomain == NULL || EQUAL(pszDomain, "")) && pszName != NULL &&
+        EQUAL(pszName, "DESCRIPTION") )
+    {
+        SetMetadata( GetMetadata() );
+    }
+    return CE_None;
+}
+
+/************************************************************************/
+/*                      SetForcedDescription()                          */
+/************************************************************************/
+
+void OGRPGTableLayer::SetForcedDescription( const char* pszDescriptionIn )
+{
+    osForcedDescription = pszDescriptionIn;
+    CPLFree(pszDescription);
+    pszDescription = CPLStrdup( pszDescriptionIn );
+    SetMetadataItem( "DESCRIPTION", osForcedDescription );
+}
+
+/************************************************************************/
 /*                      SetGeometryInformation()                        */
 /************************************************************************/
 
 void  OGRPGTableLayer::SetGeometryInformation(PGGeomColumnDesc* pasDesc,
                                               int nGeomFieldCount)
 {
-    /* flag must be set before instanciating geometry fields */
+    // Flag must be set before instantiating geometry fields.
     bGeometryInformationSet = TRUE;
 
     for(int i=0; i<nGeomFieldCount; i++)
@@ -237,13 +371,15 @@ void  OGRPGTableLayer::SetGeometryInformation(PGGeomColumnDesc* pasDesc,
             new OGRPGGeomFieldDefn(this, pasDesc[i].pszName);
         poGeomFieldDefn->SetNullable(pasDesc[i].bNullable);
         poGeomFieldDefn->nSRSId = pasDesc[i].nSRID;
-        poGeomFieldDefn->nCoordDimension = pasDesc[i].nCoordDimension;
+        poGeomFieldDefn->GeometryTypeFlags = pasDesc[i].GeometryTypeFlags;
         poGeomFieldDefn->ePostgisType = pasDesc[i].ePostgisType;
         if( pasDesc[i].pszGeomType != NULL )
         {
             OGRwkbGeometryType eGeomType = OGRFromOGCGeomType(pasDesc[i].pszGeomType);
-            if( poGeomFieldDefn->nCoordDimension == 3 && eGeomType != wkbUnknown )
+            if( (poGeomFieldDefn->GeometryTypeFlags & OGRGeometry::OGR_G_3D) && (eGeomType != wkbUnknown) )
                 eGeomType = wkbSetZ(eGeomType);
+            if( (poGeomFieldDefn->GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED) && (eGeomType != wkbUnknown) )
+                eGeomType = wkbSetM(eGeomType);
             poGeomFieldDefn->SetType(eGeomType);
         }
         poFeatureDefn->AddGeomFieldDefn(poGeomFieldDefn, FALSE);
@@ -269,6 +405,8 @@ int OGRPGTableLayer::ReadTableDefinition()
         return bTableDefinitionValid;
     bTableDefinitionValid = FALSE;
 
+    poDS->EndCopy();
+
     CPLString osSchemaClause;
     osSchemaClause.Printf("AND n.nspname=%s",
                               OGRPGEscapeString(hPGConn, pszSchemaName).c_str());
@@ -278,7 +416,7 @@ int OGRPGTableLayer::ReadTableDefinition()
         pszTypnameEqualsAnyClause = "ANY(SELECT '{int2, int4, int8, serial, bigserial}')";
     else
         pszTypnameEqualsAnyClause = "ANY(ARRAY['int2','int4','int8','serial','bigserial'])";
-    
+
     const char* pszAttnumEqualAnyIndkey;
     if( poDS->sPostgreSQLVersion.nMajor > 8 || (
         poDS->sPostgreSQLVersion.nMajor == 8 && poDS->sPostgreSQLVersion.nMinor >= 2) )
@@ -303,7 +441,7 @@ int OGRPGTableLayer::ReadTableDefinition()
               "AND %s %s ORDER BY a.attnum",
               pszTypnameEqualsAnyClause, pszEscapedTableNameSingleQuote,
               pszAttnumEqualAnyIndkey, osSchemaClause.c_str() );
-     
+
     hResult = OGRPG_PQexec(hPGConn, osCommand.c_str() );
 
     if ( hResult && PGRES_TUPLES_OK == PQresultStatus(hResult) )
@@ -514,9 +652,9 @@ int OGRPGTableLayer::ReadTableDefinition()
 
       while(bGoOn)
       {
-        CPLString osEscapedTableNameSingleQuote = OGRPGEscapeString(hPGConn,
+        osEscapedTableNameSingleQuote = OGRPGEscapeString(hPGConn,
                 (pszSqlGeomParentTableName) ? pszSqlGeomParentTableName : pszTableName);
-        const char* pszEscapedTableNameSingleQuote = osEscapedTableNameSingleQuote.c_str();
+        pszEscapedTableNameSingleQuote = osEscapedTableNameSingleQuote.c_str();
 
         osCommand.Printf(
             "SELECT type, coord_dimension, srid FROM %s WHERE f_table_name = %s",
@@ -536,16 +674,29 @@ int OGRPGTableLayer::ReadTableDefinition()
         {
             const char* pszType = PQgetvalue(hResult,0,0);
 
-            int nCoordDimension = atoi(PQgetvalue(hResult,0,1));
+            int dim = atoi(PQgetvalue(hResult,0,1));
+            bool bHasM = pszType[strlen(pszType)-1] == 'M';
+            int GeometryTypeFlags = 0;
+            if( dim == 3 )
+            {
+                if (bHasM)
+                    GeometryTypeFlags |= OGRGeometry::OGR_G_MEASURED;
+                else
+                    GeometryTypeFlags |= OGRGeometry::OGR_G_3D;
+            }
+            else if( dim == 4 )
+                GeometryTypeFlags |= OGRGeometry::OGR_G_3D | OGRGeometry::OGR_G_MEASURED;
 
             int nSRSId = atoi(PQgetvalue(hResult,0,2));
 
-            poGeomFieldDefn->nCoordDimension = nCoordDimension;
+            poGeomFieldDefn->GeometryTypeFlags = GeometryTypeFlags;
             if( nSRSId > 0 )
                 poGeomFieldDefn->nSRSId = nSRSId;
             OGRwkbGeometryType eGeomType = OGRFromOGCGeomType(pszType);
-            if( poGeomFieldDefn->nCoordDimension == 3 && eGeomType != wkbUnknown )
+            if( poGeomFieldDefn->GeometryTypeFlags & OGRGeometry::OGR_G_3D && eGeomType != wkbUnknown )
                 eGeomType = wkbSetZ(eGeomType);
+            if( poGeomFieldDefn->GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED && eGeomType != wkbUnknown )
+                eGeomType = wkbSetM(eGeomType);
             poGeomFieldDefn->SetType(eGeomType);
 
             bGoOn = FALSE;
@@ -553,9 +704,12 @@ int OGRPGTableLayer::ReadTableDefinition()
         else
         {
             /* Fetch the name of the parent table */
-            osCommand.Printf("SELECT pg_class.relname FROM pg_class WHERE oid = "
-                            "(SELECT pg_inherits.inhparent FROM pg_inherits WHERE inhrelid = "
-                            "(SELECT c.oid FROM pg_class c, pg_namespace n WHERE c.relname = %s AND c.relnamespace=n.oid AND n.nspname = %s))",
+            osCommand.Printf(
+                "SELECT pg_class.relname FROM pg_class WHERE oid = "
+                "(SELECT pg_inherits.inhparent FROM pg_inherits WHERE inhrelid = "
+                "(SELECT c.oid FROM pg_class c, pg_namespace n "
+                "WHERE c.relname = %s AND c.relnamespace=n.oid AND "
+                "n.nspname = %s))",
                             pszEscapedTableNameSingleQuote,
                             OGRPGEscapeString(hPGConn, pszSchemaName).c_str() );
 
@@ -590,24 +744,17 @@ void OGRPGTableLayer::SetTableDefinition(const char* pszFIDColumnName,
                                            OGRwkbGeometryType eType,
                                            const char* pszGeomType,
                                            int nSRSId,
-                                           int nCoordDimension)
+                                           int GeometryTypeFlags)
 {
     bTableDefinitionValid = TRUE;
     bGeometryInformationSet = TRUE;
-    if( pszFIDColumnName[0] == '"' &&
-             pszFIDColumnName[strlen(pszFIDColumnName)-1] == '"')
-    {
-        pszFIDColumn = CPLStrdup(pszFIDColumnName + 1);
-        pszFIDColumn[strlen(pszFIDColumn)-1] = '\0';
-    }
-    else
-        pszFIDColumn = CPLStrdup(pszFIDColumnName);
+    pszFIDColumn = CPLStrdup(pszFIDColumnName);
     poFeatureDefn->SetGeomType(wkbNone);
     if( eType != wkbNone )
     {
         OGRPGGeomFieldDefn* poGeomFieldDefn = new OGRPGGeomFieldDefn(this, pszGFldName);
         poGeomFieldDefn->SetType(eType);
-        poGeomFieldDefn->nCoordDimension = nCoordDimension;
+        poGeomFieldDefn->GeometryTypeFlags = GeometryTypeFlags;
 
         if( EQUAL(pszGeomType,"geometry") )
         {
@@ -627,6 +774,8 @@ void OGRPGTableLayer::SetTableDefinition(const char* pszFIDColumnName,
         }
         poFeatureDefn->AddGeomFieldDefn(poGeomFieldDefn, FALSE);
     }
+    else if( pszGFldName != NULL )
+        m_osFirstGeometryFieldName = pszGFldName;
 }
 
 /************************************************************************/
@@ -731,7 +880,9 @@ void OGRPGTableLayer::BuildFullQueryStatement()
     pszQueryStatement = (char *)
         CPLMalloc(strlen(osFields)+strlen(osWHERE)
                   +strlen(pszSqlTableName) + 40);
-    sprintf( pszQueryStatement,
+    snprintf( pszQueryStatement,
+              strlen(osFields)+strlen(osWHERE)
+                  +strlen(pszSqlTableName) + 40,
              "SELECT %s FROM %s %s",
              osFields.c_str(), pszSqlTableName, osWHERE.c_str() );
 }
@@ -747,7 +898,7 @@ void OGRPGTableLayer::ResetReading()
         return;
     bInResetReading = TRUE;
 
-    if( bDifferedCreation ) RunDifferedCreationIfNecessary();
+    if( bDeferredCreation ) RunDeferredCreationIfNecessary();
     poDS->EndCopy();
     bUseCopyByDefault = FALSE;
 
@@ -765,7 +916,7 @@ void OGRPGTableLayer::ResetReading()
 OGRFeature *OGRPGTableLayer::GetNextFeature()
 
 {
-    if( bDifferedCreation && RunDifferedCreationIfNecessary() != OGRERR_NONE )
+    if( bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
         return NULL;
     poDS->EndCopy();
 
@@ -780,7 +931,7 @@ OGRFeature *OGRPGTableLayer::GetNextFeature()
         poGeomFieldDefn = poFeatureDefn->myGetGeomFieldDefn(m_iGeomFieldFilter);
     poFeatureDefn->GetFieldCount();
 
-    for( ; TRUE; )
+    while( true )
     {
         OGRFeature      *poFeature;
 
@@ -845,8 +996,7 @@ CPLString OGRPGTableLayer::BuildFields()
             {
                 osFieldList += osEscapedGeom;
             }
-            else if (CSLTestBoolean(CPLGetConfigOption("PG_USE_BASE64", "NO")) &&
-                     poGeomFieldDefn->nCoordDimension != 4 /* we don't know how to decode 4-dim EWKB for now */)
+            else if (CPLTestBool(CPLGetConfigOption("PG_USE_BASE64", "NO")))
             {
                 if (poDS->sPostGISVersion.nMajor >= 2)
                     osFieldList += "encode(ST_AsEWKB(";
@@ -857,8 +1007,7 @@ CPLString OGRPGTableLayer::BuildFields()
                 osFieldList += OGRPGEscapeColumnName(
                     CPLSPrintf("EWKBBase64_%s", poGeomFieldDefn->GetNameRef()));
             }
-            else if ( !CSLTestBoolean(CPLGetConfigOption("PG_USE_TEXT", "NO")) &&
-                     poGeomFieldDefn->nCoordDimension != 4 && /* we don't know how to decode 4-dim EWKB for now */
+            else if ( !CPLTestBool(CPLGetConfigOption("PG_USE_TEXT", "NO")) &&
                       /* perhaps works also for older version, but I didn't check */
                       (poDS->sPostGISVersion.nMajor > 1 ||
                       (poDS->sPostGISVersion.nMajor == 1 && poDS->sPostGISVersion.nMinor >= 1)) )
@@ -889,6 +1038,7 @@ CPLString OGRPGTableLayer::BuildFields()
         }
         else if ( poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOGRAPHY )
         {
+#if defined(BINARY_CURSOR_ENABLED)
             if ( poDS->bUseBinaryCursor )
             {
                 osFieldList += "ST_AsBinary(";
@@ -897,25 +1047,27 @@ CPLString OGRPGTableLayer::BuildFields()
                 osFieldList += OGRPGEscapeColumnName(
                     CPLSPrintf("AsBinary_%s", poGeomFieldDefn->GetNameRef()));
             }
-            else if (CSLTestBoolean(CPLGetConfigOption("PG_USE_BASE64", "NO")))
+            else
+#endif
+            if (CPLTestBool(CPLGetConfigOption("PG_USE_BASE64", "NO")))
             {
-                osFieldList += "encode(ST_AsBinary(";
+                osFieldList += "encode(ST_AsEWKB(";
                 osFieldList += osEscapedGeom;
-                osFieldList += "), 'base64') AS ";
+                osFieldList += "::geometry), 'base64') AS ";
                 osFieldList += OGRPGEscapeColumnName(
-                    CPLSPrintf("BinaryBase64_%s", poGeomFieldDefn->GetNameRef()));
+                    CPLSPrintf("EWKBBase64_%s", poGeomFieldDefn->GetNameRef()));
             }
-            else if ( !CSLTestBoolean(CPLGetConfigOption("PG_USE_TEXT", "NO")) )
+            else if ( !CPLTestBool(CPLGetConfigOption("PG_USE_TEXT", "NO")) )
             {
                 osFieldList += osEscapedGeom;
             }
             else
             {
-                osFieldList += "ST_AsText(";
+                osFieldList += "ST_AsEWKT(";
                 osFieldList += osEscapedGeom;
-                osFieldList += ") AS ";
+                osFieldList += "::geometry) AS ";
                 osFieldList += OGRPGEscapeColumnName(
-                    CPLSPrintf("AsText_%s", poGeomFieldDefn->GetNameRef()));
+                    CPLSPrintf("AsEWKT_%s", poGeomFieldDefn->GetNameRef()));
             }
         }
         else
@@ -931,6 +1083,7 @@ CPLString OGRPGTableLayer::BuildFields()
         if( osFieldList.size() > 0 )
             osFieldList += ", ";
 
+#if defined(BINARY_CURSOR_ENABLED)
         /* With a binary cursor, it is not possible to get the time zone */
         /* of a timestamptz column. So we fallback to asking it in text mode */
         if ( poDS->bUseBinaryCursor &&
@@ -941,6 +1094,7 @@ CPLString OGRPGTableLayer::BuildFields()
             osFieldList += " AS text)";
         }
         else
+#endif
         {
             osFieldList += OGRPGEscapeColumnName(pszName);
         }
@@ -992,7 +1146,7 @@ OGRErr OGRPGTableLayer::DeleteFeature( GIntBig nFID )
         return OGRERR_FAILURE;
     }
 
-    if( bDifferedCreation && RunDifferedCreationIfNecessary() != OGRERR_NONE )
+    if( bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
         return OGRERR_FAILURE;
     poDS->EndCopy();
     bAutoFIDOnCreateViaCopy = FALSE;
@@ -1071,7 +1225,7 @@ OGRErr OGRPGTableLayer::ISetFeature( OGRFeature *poFeature )
         return OGRERR_FAILURE;
     }
 
-    if( bDifferedCreation && RunDifferedCreationIfNecessary() != OGRERR_NONE )
+    if( bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
         return OGRERR_FAILURE;
     poDS->EndCopy();
 
@@ -1106,7 +1260,7 @@ OGRErr OGRPGTableLayer::ISetFeature( OGRFeature *poFeature )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
                         "Inconsistent values of FID and field of same name");
-            return CE_Failure;
+            return OGRERR_FAILURE;
         }
     }
 
@@ -1134,7 +1288,9 @@ OGRErr OGRPGTableLayer::ISetFeature( OGRFeature *poFeature )
             {
                 if( !bWkbAsOid  )
                 {
-                    char    *pszBytea = GeometryToBYTEA( poGeom, poDS->sPostGISVersion.nMajor < 2 );
+                    char    *pszBytea = GeometryToBYTEA( poGeom,
+                                                         poDS->sPostGISVersion.nMajor,
+                                                         poDS->sPostGISVersion.nMinor );
 
                     if( pszBytea != NULL )
                     {
@@ -1174,15 +1330,17 @@ OGRErr OGRPGTableLayer::ISetFeature( OGRFeature *poFeature )
             if( poGeom != NULL )
             {
                 poGeom->closeRings();
-                poGeom->setCoordinateDimension( poGeomFieldDefn->nCoordDimension );
+                poGeom->set3D(poGeomFieldDefn->GeometryTypeFlags & OGRGeometry::OGR_G_3D);
+                poGeom->setMeasured(poGeomFieldDefn->GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED);
             }
 
-            if ( !CSLTestBoolean(CPLGetConfigOption("PG_USE_TEXT", "NO")) )
+            if ( !CPLTestBool(CPLGetConfigOption("PG_USE_TEXT", "NO")) )
             {
                 if ( poGeom != NULL )
                 {
                     char* pszHexEWKB = OGRGeometryToHexEWKB( poGeom, poGeomFieldDefn->nSRSId,
-                                                             poDS->sPostGISVersion.nMajor < 2 );
+                                                             poDS->sPostGISVersion.nMajor,
+                                                             poDS->sPostGISVersion.nMinor);
                     if ( poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOGRAPHY )
                         osCommand += CPLString().Printf("'%s'::GEOGRAPHY", pszHexEWKB);
                     else
@@ -1190,12 +1348,12 @@ OGRErr OGRPGTableLayer::ISetFeature( OGRFeature *poFeature )
                     OGRFree( pszHexEWKB );
                 }
                 else
-                    osCommand += "NULL";    
+                    osCommand += "NULL";
             }
             else
             {
                 char    *pszWKT = NULL;
-        
+
                 if (poGeom != NULL)
                     poGeom->exportToWkt( &pszWKT );
 
@@ -1211,7 +1369,7 @@ OGRErr OGRPGTableLayer::ISetFeature( OGRFeature *poFeature )
                             CPLString().Printf(
                                 "GeomFromEWKT('SRID=%d;%s'::TEXT) ", nSRSId, pszWKT );
                     else
-                        osCommand += 
+                        osCommand +=
                             CPLString().Printf(
                                 "GeometryFromText('%s'::TEXT,%d) ", pszWKT, nSRSId );
                     OGRFree( pszWKT );
@@ -1232,7 +1390,7 @@ OGRErr OGRPGTableLayer::ISetFeature( OGRFeature *poFeature )
         else
             bNeedComma = TRUE;
 
-        osCommand = osCommand 
+        osCommand = osCommand
             + OGRPGEscapeColumnName(poFeatureDefn->GetFieldDefn(i)->GetNameRef()) + " = ";
 
         if( !poFeature->IsFieldSet( i ) )
@@ -1299,13 +1457,14 @@ OGRErr OGRPGTableLayer::ICreateFeature( OGRFeature *poFeature )
         return OGRERR_FAILURE;
     }
 
-    if( bDifferedCreation && RunDifferedCreationIfNecessary() != OGRERR_NONE )
+    if( bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
         return OGRERR_FAILURE;
 
     /* In case the FID column has also been created as a regular field */
+    GIntBig nFID = poFeature->GetFID();
     if( iFIDAsRegularColumnIndex >= 0 )
     {
-        if( poFeature->GetFID() == OGRNullFID )
+        if( nFID == OGRNullFID )
         {
             if( poFeature->IsFieldSet( iFIDAsRegularColumnIndex ) )
             {
@@ -1316,18 +1475,18 @@ OGRErr OGRPGTableLayer::ICreateFeature( OGRFeature *poFeature )
         else
         {
             if( !poFeature->IsFieldSet( iFIDAsRegularColumnIndex ) ||
-                poFeature->GetFieldAsInteger64(iFIDAsRegularColumnIndex) != poFeature->GetFID() )
+                poFeature->GetFieldAsInteger64(iFIDAsRegularColumnIndex) != nFID )
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
                             "Inconsistent values of FID and field of same name");
-                return CE_Failure;
+                return OGRERR_FAILURE;
             }
         }
     }
 
     /* Auto-promote FID column to 64bit if necessary */
     if( pszFIDColumn != NULL &&
-        (GIntBig)(int)poFeature->GetFID() != poFeature->GetFID() &&
+        !CPL_INT64_FITS_ON_INT32(nFID) &&
         GetMetadataItem(OLMD_FID64) == NULL )
     {
         poDS->EndCopy();
@@ -1350,14 +1509,14 @@ OGRErr OGRPGTableLayer::ICreateFeature( OGRFeature *poFeature )
             return OGRERR_FAILURE;
         }
         OGRPGClearResult( hResult );
-        
+
         SetMetadataItem(OLMD_FID64, "YES");
     }
 
     if( bFirstInsertion )
     {
         bFirstInsertion = FALSE;
-        if( CSLTestBoolean(CPLGetConfigOption("OGR_TRUNCATE", "NO")) )
+        if( CPLTestBool(CPLGetConfigOption("OGR_TRUNCATE", "NO")) )
         {
             PGconn              *hPGConn = poDS->GetPGConn();
             PGresult            *hResult;
@@ -1369,9 +1528,9 @@ OGRErr OGRPGTableLayer::ICreateFeature( OGRFeature *poFeature )
         }
     }
 
-    // We avoid testing the config option too often. 
+    // We avoid testing the config option too often.
     if( bUseCopy == USE_COPY_UNSET )
-        bUseCopy = CSLTestBoolean( CPLGetConfigOption( "PG_USE_COPY", "NO") );
+        bUseCopy = CPLTestBool( CPLGetConfigOption( "PG_USE_COPY", "NO") );
 
     OGRErr eErr;
     if( !bUseCopy )
@@ -1424,7 +1583,7 @@ OGRErr OGRPGTableLayer::ICreateFeature( OGRFeature *poFeature )
                 eErr = CreateFeatureViaCopy( poFeature );
                 if( bFIDSet )
                     bAutoFIDOnCreateViaCopy = FALSE;
-                if( eErr == CE_None && bAutoFIDOnCreateViaCopy )
+                if( eErr == OGRERR_NONE && bAutoFIDOnCreateViaCopy )
                 {
                     poFeature->SetFID( ++iNextShapeId );
                 }
@@ -1432,7 +1591,7 @@ OGRErr OGRPGTableLayer::ICreateFeature( OGRFeature *poFeature )
         }
     }
 
-    if( eErr == CE_None && iFIDAsRegularColumnIndex >= 0 )
+    if( eErr == OGRERR_NONE && iFIDAsRegularColumnIndex >= 0 )
     {
         poFeature->SetField(iFIDAsRegularColumnIndex, poFeature->GetFID());
     }
@@ -1478,7 +1637,7 @@ CPLString OGRPGEscapeString(PGconn *hPGConn,
     osCommand += "'";
 
 
-    int nSrcLen = strlen(pszStrValue);
+    int nSrcLen = static_cast<int>(strlen(pszStrValue));
     int nSrcLenUTF = CPLStrlenUTF8(pszStrValue);
 
     if (nMaxLength > 0 && nSrcLenUTF > nMaxLength)
@@ -1516,7 +1675,7 @@ CPLString OGRPGEscapeString(PGconn *hPGConn,
     if (nError == 0)
         osCommand += pszDestStr;
     else
-        CPLError(CE_Warning, CPLE_AppDefined, 
+        CPLError(CE_Warning, CPLE_AppDefined,
                  "PQescapeString(): %s\n"
                  "  input: '%s'\n"
                  "    got: '%s'\n",
@@ -1568,13 +1727,13 @@ OGRErr OGRPGTableLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
             osCommand += ", ";
         osCommand += OGRPGEscapeColumnName(poGeomFieldDefn->GetNameRef()) + " ";
     }
-    
+
     /* Use case of ogr_pg_60 test */
     if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
     {
         if( bNeedComma )
             osCommand += ", ";
-        
+
         osCommand = osCommand + OGRPGEscapeColumnName(pszFIDColumn) + " ";
         bNeedComma = TRUE;
     }
@@ -1592,7 +1751,7 @@ OGRErr OGRPGTableLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
         else
             osCommand += ", ";
 
-        osCommand = osCommand 
+        osCommand = osCommand
             + OGRPGEscapeColumnName(poFeatureDefn->GetFieldDefn(i)->GetNameRef());
     }
 
@@ -1621,14 +1780,16 @@ OGRErr OGRPGTableLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
             CheckGeomTypeCompatibility(i, poGeom);
 
             poGeom->closeRings();
-            poGeom->setCoordinateDimension( poGeomFieldDefn->nCoordDimension );
+            poGeom->set3D(poGeomFieldDefn->GeometryTypeFlags & OGRGeometry::OGR_G_3D);
+            poGeom->setMeasured(poGeomFieldDefn->GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED);
 
             int nSRSId = poGeomFieldDefn->nSRSId;
 
-            if ( !CSLTestBoolean(CPLGetConfigOption("PG_USE_TEXT", "NO")) )
+            if ( !CPLTestBool(CPLGetConfigOption("PG_USE_TEXT", "NO")) )
             {
                 char    *pszHexEWKB = OGRGeometryToHexEWKB( poGeom, nSRSId,
-                                                            poDS->sPostGISVersion.nMajor < 2 );
+                                                            poDS->sPostGISVersion.nMajor,
+                                                            poDS->sPostGISVersion.nMinor );
                 if ( poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOGRAPHY )
                     osCommand += CPLString().Printf("'%s'::GEOGRAPHY", pszHexEWKB);
                 else
@@ -1636,7 +1797,7 @@ OGRErr OGRPGTableLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
                 OGRFree( pszHexEWKB );
             }
             else
-            { 
+            {
                 char    *pszWKT = NULL;
                 poGeom->exportToWkt( &pszWKT );
 
@@ -1651,19 +1812,21 @@ OGRErr OGRPGTableLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
                             CPLString().Printf(
                                 "GeomFromEWKT('SRID=%d;%s'::TEXT) ", nSRSId, pszWKT );
                     else
-                        osCommand += 
+                        osCommand +=
                             CPLString().Printf(
                                 "GeometryFromText('%s'::TEXT,%d) ", pszWKT, nSRSId );
                     OGRFree( pszWKT );
                 }
                 else
                     osCommand += "''";
-                
+
             }
         }
         else if( !bWkbAsOid )
         {
-            char    *pszBytea = GeometryToBYTEA( poGeom, poDS->sPostGISVersion.nMajor < 2 );
+            char    *pszBytea = GeometryToBYTEA( poGeom,
+                                                 poDS->sPostGISVersion.nMajor,
+                                                 poDS->sPostGISVersion.nMinor );
 
             if( pszBytea != NULL )
             {
@@ -1780,7 +1943,7 @@ OGRErr OGRPGTableLayer::CreateFeatureViaCopy( OGRFeature *poFeature )
     int                  i;
 
     /* Tell the datasource we are now planning to copy data */
-    poDS->StartCopy( this ); 
+    poDS->StartCopy( this );
 
     /* First process geometry */
     for( i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
@@ -1795,13 +1958,17 @@ OGRErr OGRPGTableLayer::CreateFeatureViaCopy( OGRFeature *poFeature )
             CheckGeomTypeCompatibility(i, poGeom);
 
             poGeom->closeRings();
-            poGeom->setCoordinateDimension( poGeomFieldDefn->nCoordDimension );
+            poGeom->set3D(poGeomFieldDefn->GeometryTypeFlags & OGRGeometry::OGR_G_3D);
+            poGeom->setMeasured(poGeomFieldDefn->GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED);
 
             if( poGeomFieldDefn->ePostgisType == GEOM_TYPE_WKB )
-                pszGeom = GeometryToBYTEA( poGeom, poDS->sPostGISVersion.nMajor < 2 );
+                pszGeom = GeometryToBYTEA( poGeom,
+                                           poDS->sPostGISVersion.nMajor,
+                                           poDS->sPostGISVersion.nMinor );
             else
                 pszGeom = OGRGeometryToHexEWKB( poGeom, poGeomFieldDefn->nSRSId,
-                                                poDS->sPostGISVersion.nMajor < 2 );
+                                                poDS->sPostGISVersion.nMajor,
+                                                poDS->sPostGISVersion.nMinor );
         }
 
         if (osCommand.size() > 0)
@@ -1817,7 +1984,7 @@ OGRErr OGRPGTableLayer::CreateFeatureViaCopy( OGRFeature *poFeature )
             osCommand += "\\N";
         }
     }
-    
+
     OGRPGCommonAppendCopyFieldsExceptGeom(osCommand,
                                           poFeature,
                                           pszFIDColumn,
@@ -1837,7 +2004,8 @@ OGRErr OGRPGTableLayer::CreateFeatureViaCopy( OGRFeature *poFeature )
 
     /* This is for postgresql  7.4 and higher */
 #if !defined(PG_PRE74)
-    int copyResult = PQputCopyData(hPGConn, osCommand.c_str(), strlen(osCommand.c_str()));
+    int copyResult = PQputCopyData(hPGConn, osCommand.c_str(),
+                                   static_cast<int>(strlen(osCommand.c_str())));
 #ifdef DEBUG_VERBOSE
     CPLDebug("PG", "PQputCopyData(%s)", osCommand.c_str());
 #endif
@@ -1860,7 +2028,7 @@ OGRErr OGRPGTableLayer::CreateFeatureViaCopy( OGRFeature *poFeature )
     {
       CPLError( CE_Failure, CPLE_AppDefined, "Writing COPY data blocked.");
       result = OGRERR_FAILURE;
-    }  
+    }
 #endif /* end of defined(PG_PRE74) */
 
     return result;
@@ -1941,6 +2109,9 @@ int OGRPGTableLayer::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCCurveGeometries) )
         return TRUE;
 
+    else if( EQUAL(pszCap,OLCMeasuredGeometries) )
+        return TRUE;
+
     else
         return FALSE;
 }
@@ -1967,7 +2138,7 @@ OGRErr OGRPGTableLayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
                   "CreateField");
         return OGRERR_FAILURE;
     }
-    
+
     if( pszFIDColumn != NULL &&
         EQUAL( oField.GetNameRef(), pszFIDColumn ) &&
         oField.GetType() != OFTInteger &&
@@ -1975,9 +2146,9 @@ OGRErr OGRPGTableLayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Wrong field type for %s",
                  oField.GetNameRef());
-        return CE_Failure;
+        return OGRERR_FAILURE;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Do we want to "launder" the column names into Postgres          */
 /*      friendly format?                                                */
@@ -2020,7 +2191,7 @@ OGRErr OGRPGTableLayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
 /* -------------------------------------------------------------------- */
 /*      Create the new field.                                           */
 /* -------------------------------------------------------------------- */
-    if( bDifferedCreation )
+    if( bDeferredCreation )
     {
         if( !(pszFIDColumn != NULL && EQUAL(pszFIDColumn,oField.GetNameRef())) )
         {
@@ -2039,13 +2210,13 @@ OGRErr OGRPGTableLayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
                         pszSqlTableName, OGRPGEscapeColumnName(oField.GetNameRef()).c_str(),
                         osFieldType.c_str() );
         osCommand += osNotNullDefault;
-        
+
         hResult = OGRPG_PQexec(hPGConn, osCommand);
         if( PQresultStatus(hResult) != PGRES_COMMAND_OK )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                    "%s\n%s", 
-                    osCommand.c_str(), 
+                    "%s\n%s",
+                    osCommand.c_str(),
                     PQerrorMessage(hPGConn) );
 
             OGRPGClearResult( hResult );
@@ -2079,12 +2250,26 @@ OGRErr OGRPGTableLayer::RunAddGeometryColumn( OGRPGGeomFieldDefn *poGeomField )
     CPLString            osCommand;
 
     const char *pszGeometryType = OGRToOGCGeomType(poGeomField->GetType());
+    const char *suffix = "";
+    int dim = 2;
+    if( (poGeomField->GeometryTypeFlags & OGRGeometry::OGR_G_3D) &&
+        (poGeomField->GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED) )
+        dim = 4;
+    else if( (poGeomField->GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED) )
+    {
+        if( !(wkbFlatten(poGeomField->GetType()) == wkbUnknown) )
+            suffix = "M";
+        dim = 3;
+    }
+    else if( poGeomField->GeometryTypeFlags & OGRGeometry::OGR_G_3D )
+        dim = 3;
+
     osCommand.Printf(
-            "SELECT AddGeometryColumn(%s,%s,%s,%d,'%s',%d)",
+            "SELECT AddGeometryColumn(%s,%s,%s,%d,'%s%s',%d)",
             OGRPGEscapeString(hPGConn, pszSchemaName).c_str(),
             OGRPGEscapeString(hPGConn, pszTableName).c_str(),
             OGRPGEscapeString(hPGConn, poGeomField->GetNameRef()).c_str(),
-            poGeomField->nSRSId, pszGeometryType, poGeomField->nCoordDimension );
+            poGeomField->nSRSId, pszGeometryType, suffix, dim );
 
     hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
 
@@ -2100,7 +2285,7 @@ OGRErr OGRPGTableLayer::RunAddGeometryColumn( OGRPGGeomFieldDefn *poGeomField )
     }
 
     OGRPGClearResult( hResult );
-    
+
     if( !poGeomField->IsNullable() )
     {
         osCommand.Printf( "ALTER TABLE %s ALTER COLUMN %s SET NOT NULL",
@@ -2162,9 +2347,16 @@ OGRErr OGRPGTableLayer::CreateGeomField( OGRGeomFieldDefn *poGeomFieldIn,
                  "Cannot create geometry field of type wkbNone");
         return OGRERR_FAILURE;
     }
-    
+
+    // Check if GEOMETRY_NAME layer creation option was set, but no initial
+    // column was created in ICreateLayer()
+    CPLString osGeomFieldName =
+        ( m_osFirstGeometryFieldName.size() ) ? m_osFirstGeometryFieldName :
+                                                CPLString(poGeomFieldIn->GetNameRef());
+    m_osFirstGeometryFieldName = ""; // reset for potential next geom columns
+
     OGRPGGeomFieldDefn *poGeomField =
-        new OGRPGGeomFieldDefn( this, poGeomFieldIn->GetNameRef() );
+        new OGRPGGeomFieldDefn( this, osGeomFieldName );
     if( EQUAL(poGeomField->GetNameRef(), "") )
     {
         if( poFeatureDefn->GetGeomFieldCount() == 0 )
@@ -2186,7 +2378,7 @@ OGRErr OGRPGTableLayer::CreateGeomField( OGRGeomFieldDefn *poGeomFieldIn,
         poGeomField->SetName( pszSafeName );
         CPLFree( pszSafeName );
     }
-    
+
     OGRSpatialReference* poSRS = poGeomField->GetSpatialRef();
     int nSRSId = poDS->GetUndefinedSRID();
     if( nForcedSRSId != UNDETERMINED_SRID )
@@ -2194,24 +2386,28 @@ OGRErr OGRPGTableLayer::CreateGeomField( OGRGeomFieldDefn *poGeomFieldIn,
     else if( poSRS != NULL )
         nSRSId = poDS->FetchSRSId( poSRS );
 
-    int nDimension = 3;
-    if( wkbFlatten(eType) == eType )
-        nDimension = 2;
-    if( nForcedDimension > 0 )
+    int GeometryTypeFlags = 0;
+    if( OGR_GT_HasZ((OGRwkbGeometryType)eType) )
+        GeometryTypeFlags |= OGRGeometry::OGR_G_3D;
+    if( OGR_GT_HasM((OGRwkbGeometryType)eType) )
+        GeometryTypeFlags |= OGRGeometry::OGR_G_MEASURED;
+    if( nForcedGeometryTypeFlags >= 0 )
     {
-        nDimension = nForcedDimension;
-        eType = OGR_GT_SetModifier(eType, nDimension == 3, FALSE);
+        GeometryTypeFlags = nForcedGeometryTypeFlags;
+        eType = OGR_GT_SetModifier(eType,
+                                   GeometryTypeFlags & OGRGeometry::OGR_G_3D,
+                                   GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED);
     }
     poGeomField->SetType(eType);
     poGeomField->SetNullable( poGeomFieldIn->IsNullable() );
     poGeomField->nSRSId = nSRSId;
-    poGeomField->nCoordDimension = nDimension;
+    poGeomField->GeometryTypeFlags = GeometryTypeFlags;
     poGeomField->ePostgisType = GEOM_TYPE_GEOMETRY;
 
 /* -------------------------------------------------------------------- */
 /*      Create the new field.                                           */
 /* -------------------------------------------------------------------- */
-    if( !bDifferedCreation )
+    if( !bDeferredCreation )
     {
         poDS->EndCopy();
 
@@ -2265,7 +2461,7 @@ OGRErr OGRPGTableLayer::DeleteField( int iField )
         return OGRERR_FAILURE;
     }
 
-    if( bDifferedCreation && RunDifferedCreationIfNecessary() != OGRERR_NONE )
+    if( bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
         return OGRERR_FAILURE;
     poDS->EndCopy();
 
@@ -2294,7 +2490,7 @@ OGRErr OGRPGTableLayer::DeleteField( int iField )
 /*                           AlterFieldDefn()                           */
 /************************************************************************/
 
-OGRErr OGRPGTableLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags )
+OGRErr OGRPGTableLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlagsIn )
 {
     PGconn              *hPGConn = poDS->GetPGConn();
     PGresult            *hResult = NULL;
@@ -2317,7 +2513,7 @@ OGRErr OGRPGTableLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn
         return OGRERR_FAILURE;
     }
 
-    if( bDifferedCreation && RunDifferedCreationIfNecessary() != OGRERR_NONE )
+    if( bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
         return OGRERR_FAILURE;
     poDS->EndCopy();
 
@@ -2326,17 +2522,17 @@ OGRErr OGRPGTableLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn
 
     poDS->SoftStartTransaction();
 
-    if (!(nFlags & ALTER_TYPE_FLAG))
+    if (!(nFlagsIn & ALTER_TYPE_FLAG))
         oField.SetType(poFieldDefn->GetType());
 
-    if (!(nFlags & ALTER_WIDTH_PRECISION_FLAG))
+    if (!(nFlagsIn & ALTER_WIDTH_PRECISION_FLAG))
     {
         oField.SetWidth(poFieldDefn->GetWidth());
         oField.SetPrecision(poFieldDefn->GetPrecision());
     }
 
-    if ((nFlags & ALTER_TYPE_FLAG) ||
-        (nFlags & ALTER_WIDTH_PRECISION_FLAG))
+    if ((nFlagsIn & ALTER_TYPE_FLAG) ||
+        (nFlagsIn & ALTER_WIDTH_PRECISION_FLAG))
     {
         CPLString osFieldType = OGRPGCommonLayerGetType(oField,
                                                        bPreservePrecision,
@@ -2370,7 +2566,7 @@ OGRErr OGRPGTableLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn
         OGRPGClearResult( hResult );
     }
 
-    if( (nFlags & ALTER_NULLABLE_FLAG) &&
+    if( (nFlagsIn & ALTER_NULLABLE_FLAG) &&
         poFieldDefn->IsNullable() != poNewFieldDefn->IsNullable() )
     {
         oField.SetNullable(poNewFieldDefn->IsNullable());
@@ -2400,8 +2596,8 @@ OGRErr OGRPGTableLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn
         }
         OGRPGClearResult( hResult );
     }
-    
-    if( (nFlags & ALTER_DEFAULT_FLAG) &&
+
+    if( (nFlagsIn & ALTER_DEFAULT_FLAG) &&
         ((poFieldDefn->GetDefault() == NULL && poNewFieldDefn->GetDefault() != NULL) ||
          (poFieldDefn->GetDefault() != NULL && poNewFieldDefn->GetDefault() == NULL) ||
          (poFieldDefn->GetDefault() != NULL && poNewFieldDefn->GetDefault() != NULL &&
@@ -2436,7 +2632,7 @@ OGRErr OGRPGTableLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn
         OGRPGClearResult( hResult );
     }
 
-    if( (nFlags & ALTER_NAME_FLAG) )
+    if( (nFlagsIn & ALTER_NAME_FLAG) )
     {
         if (bLaunderColumnNames)
         {
@@ -2478,18 +2674,18 @@ OGRErr OGRPGTableLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn
 
     poDS->SoftCommitTransaction();
 
-    if (nFlags & ALTER_NAME_FLAG)
+    if (nFlagsIn & ALTER_NAME_FLAG)
         poFieldDefn->SetName(oField.GetNameRef());
-    if (nFlags & ALTER_TYPE_FLAG)
+    if (nFlagsIn & ALTER_TYPE_FLAG)
         poFieldDefn->SetType(oField.GetType());
-    if (nFlags & ALTER_WIDTH_PRECISION_FLAG)
+    if (nFlagsIn & ALTER_WIDTH_PRECISION_FLAG)
     {
         poFieldDefn->SetWidth(oField.GetWidth());
         poFieldDefn->SetPrecision(oField.GetPrecision());
     }
-    if (nFlags & ALTER_NULLABLE_FLAG)
+    if (nFlagsIn & ALTER_NULLABLE_FLAG)
         poFieldDefn->SetNullable(oField.IsNullable());
-    if (nFlags & ALTER_DEFAULT_FLAG)
+    if (nFlagsIn & ALTER_DEFAULT_FLAG)
         poFieldDefn->SetDefault(oField.GetDefault());
 
     return OGRERR_NONE;
@@ -2597,7 +2793,7 @@ OGRFeature *OGRPGTableLayer::GetFeature( GIntBig nFeatureId )
 GIntBig OGRPGTableLayer::GetFeatureCount( int bForce )
 
 {
-    if( bDifferedCreation && RunDifferedCreationIfNecessary() != OGRERR_NONE )
+    if( bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
         return 0;
     poDS->EndCopy();
 
@@ -2710,10 +2906,10 @@ OGRErr OGRPGTableLayer::StartCopy()
 
     CPLString osFields = BuildCopyFields();
 
-    int size = strlen(osFields) +  strlen(pszSqlTableName) + 100;
+    size_t size = strlen(osFields) +  strlen(pszSqlTableName) + 100;
     char *pszCommand = (char *) CPLMalloc(size);
 
-    sprintf( pszCommand,
+    snprintf( pszCommand, size,
              "COPY %s (%s) FROM STDIN;",
              pszSqlTableName, osFields.c_str() );
 
@@ -2870,13 +3066,13 @@ void OGRPGTableLayer::CheckGeomTypeCompatibility(int iGeomField,
                                      eFlatGeomType != wkbGeometryCollection;
     else
         bHasWarnedIncompatibleGeom = (eFlatGeomType != eFlatLayerGeomType);
-    
+
     if (bHasWarnedIncompatibleGeom)
     {
         CPLError(CE_Warning, CPLE_AppDefined,
                  "Geometry to be inserted is of type %s, whereas the layer geometry type is %s.\n"
                  "Insertion is likely to fail",
-                 OGRGeometryTypeToName(poGeom->getGeometryType()), 
+                 OGRGeometryTypeToName(poGeom->getGeometryType()),
                  OGRGeometryTypeToName(eExpectedGeomType));
     }
 }
@@ -2947,7 +3143,7 @@ OGRErr OGRPGTableLayer::GetExtent( int iGeomField, OGREnvelope *psExtent, int bF
         return OGRERR_FAILURE;
     }
 
-    if( bDifferedCreation && RunDifferedCreationIfNecessary() != OGRERR_NONE )
+    if( bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
         return OGRERR_FAILURE;
     poDS->EndCopy();
 
@@ -2955,10 +3151,10 @@ OGRErr OGRPGTableLayer::GetExtent( int iGeomField, OGREnvelope *psExtent, int bF
         poFeatureDefn->myGetGeomFieldDefn(iGeomField);
 
     const char* pszExtentFct;
-    // if bForce is 0 and ePostgisType is not GEOM_TYPE_GEOGRAPHY we can use 
+    // if bForce is 0 and ePostgisType is not GEOM_TYPE_GEOGRAPHY we can use
     // the ST_EstimatedExtent function which is quicker
     // ST_EstimatedExtent was called ST_Estimated_Extent up to PostGIS 2.0.x
-    // ST_EstimatedExtent returns NULL in absence of statistics (an exception before 
+    // ST_EstimatedExtent returns NULL in absence of statistics (an exception before
     //   PostGIS 1.5.4)
     if ( bForce == 0 && TestCapability(OLCFastGetExtent) )
     {
@@ -2981,31 +3177,33 @@ OGRErr OGRPGTableLayer::GetExtent( int iGeomField, OGREnvelope *psExtent, int bF
         if( RunGetExtentRequest(psExtent, bForce, osCommand, TRUE) == OGRERR_NONE )
             return OGRERR_NONE;
 
-        CPLDebug("PG","Unable to get extimated extent by PostGIS. Trying real extent.");
+        CPLDebug(
+            "PG",
+            "Unable to get estimated extent by PostGIS. Trying real extent." );
     }
 
     return OGRPGLayer::GetExtent( iGeomField, psExtent, bForce );
 }
 
 /************************************************************************/
-/*                        SetDifferedCreation()                         */
+/*                        SetDeferredCreation()                         */
 /************************************************************************/
 
-void OGRPGTableLayer::SetDifferedCreation(int bDifferedCreationIn, CPLString osCreateTableIn)
+void OGRPGTableLayer::SetDeferredCreation(int bDeferredCreationIn, CPLString osCreateTableIn)
 {
-    bDifferedCreation = bDifferedCreationIn;
+    bDeferredCreation = bDeferredCreationIn;
     osCreateTable = osCreateTableIn;
 }
 
 /************************************************************************/
-/*                      RunDifferedCreationIfNecessary()                */
+/*                      RunDeferredCreationIfNecessary()                */
 /************************************************************************/
 
-OGRErr OGRPGTableLayer::RunDifferedCreationIfNecessary()
+OGRErr OGRPGTableLayer::RunDeferredCreationIfNecessary()
 {
-    if( !bDifferedCreation )
+    if( !bDeferredCreation )
         return OGRERR_NONE;
-    bDifferedCreation = FALSE;
+    bDeferredCreation = FALSE;
 
     poDS->EndCopy();
 
@@ -3028,8 +3226,12 @@ OGRErr OGRPGTableLayer::RunDifferedCreationIfNecessary()
             else
                 osCreateTable += "geography(";
             osCreateTable += pszGeometryType;
-            if( poGeomField->nCoordDimension == 3 )
+            if( (poGeomField->GeometryTypeFlags & OGRGeometry::OGR_G_3D) && (poGeomField->GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED) )
+                osCreateTable += "ZM";
+            else if( poGeomField->GeometryTypeFlags & OGRGeometry::OGR_G_3D )
                 osCreateTable += "Z";
+            else if( poGeomField->GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED )
+                osCreateTable += "M";
             if( poGeomField->nSRSId > 0 )
                 osCreateTable += CPLSPrintf(",%d", poGeomField->nSRSId);
             osCreateTable += ")";
@@ -3040,10 +3242,10 @@ OGRErr OGRPGTableLayer::RunDifferedCreationIfNecessary()
 
     osCreateTable += " )";
     CPLString osCommand(osCreateTable);
-    
+
     PGresult            *hResult;
     PGconn              *hPGConn = poDS->GetPGConn();
-    
+
     hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
     if( PQresultStatus(hResult) != PGRES_COMMAND_OK )
     {
@@ -3069,7 +3271,7 @@ OGRErr OGRPGTableLayer::RunDifferedCreationIfNecessary()
             }
         }
     }
-    
+
     if( bCreateSpatialIndexFlag )
     {
         for( i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
@@ -3082,5 +3284,9 @@ OGRErr OGRPGTableLayer::RunDifferedCreationIfNecessary()
         }
     }
 
+    char** papszMD = OGRLayer::GetMetadata();
+    if( papszMD != NULL )
+        SetMetadata( papszMD );
+
     return OGRERR_NONE;
 }
diff --git a/ogr/ogrsf_frmts/pg/ogrpgutility.cpp b/ogr/ogrsf_frmts/pg/ogrpgutility.cpp
index a982e1e..58e12ae 100644
--- a/ogr/ogrsf_frmts/pg/ogrpgutility.cpp
+++ b/ogr/ogrsf_frmts/pg/ogrpgutility.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgutility.cpp 27784 2014-10-02 15:43:18Z rouault $
+ * $Id: ogrpgutility.cpp 32078 2015-12-08 09:09:45Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Utility methods
@@ -30,7 +30,7 @@
 #include "ogr_pg.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrpgutility.cpp 27784 2014-10-02 15:43:18Z rouault $");
+CPL_CVSID("$Id: ogrpgutility.cpp 32078 2015-12-08 09:09:45Z rouault $");
 
 /************************************************************************/
 /*                         OGRPG_PQexec()                               */
@@ -60,7 +60,7 @@ PGresult *OGRPG_PQexec(PGconn *conn, const char *query, int bMultipleCommandAllo
         {
             case PGRES_TUPLES_OK:
                 pszRetCode = "PGRES_TUPLES_OK";
-                sprintf(szNTuples, ", ntuples = %d", PQntuples(hResult));
+                snprintf(szNTuples, sizeof(szNTuples), ", ntuples = %d", PQntuples(hResult));
                 break;
             case PGRES_COMMAND_OK:
                 pszRetCode = "PGRES_COMMAND_OK";
@@ -81,7 +81,7 @@ PGresult *OGRPG_PQexec(PGconn *conn, const char *query, int bMultipleCommandAllo
 #endif
 
 /* -------------------------------------------------------------------- */
-/*      Generate an error report if an error occured.                   */
+/*      Generate an error report if an error occurred.                  */
 /* -------------------------------------------------------------------- */
     if ( !hResult || (PQresultStatus(hResult) == PGRES_NONFATAL_ERROR ||
                       PQresultStatus(hResult) == PGRES_FATAL_ERROR ) )
diff --git a/ogr/ogrsf_frmts/pgdump/drv_pgdump.html b/ogr/ogrsf_frmts/pgdump/drv_pgdump.html
index 4b39a7a..196cca2 100644
--- a/ogr/ogrsf_frmts/pgdump/drv_pgdump.html
+++ b/ogr/ogrsf_frmts/pgdump/drv_pgdump.html
@@ -11,7 +11,7 @@
 
 This write-only driver implements support for generating a SQL dump file that
 can later be injected into a live PostgreSQL instance. It supports
-PostgreSQL extended with the 
+PostgreSQL extended with the
 <a href="http://postgis.net/">PostGIS</a> geometries.<p>
 
 This driver is very similar to the PostGIS shp2pgsql utility.<p>
@@ -29,7 +29,7 @@ geometry columns (following
 <ul>
 <li> <b>LINEFORMAT</b>:
 By default files are created with the line
-termination conventions of the local platform (CR/LF on win32 or 
+termination conventions of the local platform (CR/LF on win32 or
 LF on all other systems).  This may be overridden through use of the
 LINEFORMAT layer creation option which may have a value of <b>CRLF</b>
 (DOS format) or <b>LF</b> (Unix format). <p>
@@ -39,22 +39,22 @@ LINEFORMAT layer creation option which may have a value of <b>CRLF</b>
 
 <ul>
 <li>
-<b>GEOM_TYPE</b>: The GEOM_TYPE layer creation option can be set to 
+<b>GEOM_TYPE</b>: The GEOM_TYPE layer creation option can be set to
 one of "geometry" or "geography" (PostGIS >= 1.5) to force the type of geometry used for
 a table. "geometry" is the default value.<p>
 <li> <b>LAUNDER</b>: This may be "YES" to force new fields created on this
 layer to have their field names "laundered" into a form more compatible with
 PostgreSQL.  This converts to lower case and converts some special characters
-like "-" and "#" to "_".  If "NO" exact names are preserved.  
+like "-" and "#" to "_".  If "NO" exact names are preserved.
 The default value is "YES".  If enabled the table (layer) name will also be laundered.<p>
 <li> <b>PRECISION</b>: This may be "YES" to force new fields created on this
 layer to try and represent the width and precision information, if available
 using NUMERIC(width,precision) or CHAR(width) types.  If "NO" then the types
 FLOAT8, INTEGER and VARCHAR will be used instead.  The default is "YES".<p>
-<li> <b>DIM={2,3}</b>: Control the dimension of the layer.  Defaults to 3. 
+<li> <b>DIM={2,3,XYM,XYZM}</b>: Control the dimension of the layer.
 Important to set to 2 for 2D layers with PostGIS 1.0+ as it has constraints
 on the geometry dimension during loading.<p>
-<li> <b>GEOMETRY_NAME</b>: Set name of geometry column in new table.  If 
+<li> <b>GEOMETRY_NAME</b>: Set name of geometry column in new table.  If
 omitted it defaults to <i>wkb_geometry</i> for GEOM_TYPE=geometry, or <i>the_geog</i> for GEOM_TYPE=geography.<p>
 <li> <b>SCHEMA</b>: Set name of schema for new table.
 Using the same layer name in different schemas is supported, but not in the public schema and others.<p>
@@ -70,7 +70,7 @@ This option will have no effect if PG_USE_COPY environment variable is to YES.<p
 <li> <b>CREATE_TABLE</b>: Set to ON by default so that tables are recreated if necessary. Turn to OFF to disable this and use existing table structure.<p>
 <li> <b>DROP_TABLE</b>=ON/OFF/IF_EXISTS: (OGR >= 1.8.1) Set to ON so that tables are destroyed before being recreated.
 Set to OFF to prevent DROP TABLE from being emitted. Set to IF_EXISTS (default in GDAL 2.0) in order DROP TABLE IF EXISTS to be emitted (needs PostgreSQL >= 8.2)<p>
-<li> <b>SRID</b>: Set the SRID of the geometry. Defaults to -1, unless a SRS is associated with the layer. In the case, if the EPSG code is mentionned, it will be used as the SRID. (Note: the spatial_ref_sys table must be correctly populated with the specified SRID) <p>
+<li> <b>SRID</b>: Set the SRID of the geometry. Defaults to -1, unless a SRS is associated with the layer. In the case, if the EPSG code is mentioned, it will be used as the SRID. (Note: the spatial_ref_sys table must be correctly populated with the specified SRID) <p>
 <li> <b>NONE_AS_UNKNOWN</b>: (From GDAL 1.9.0) Can bet set to TRUE to force non-spatial layers (wkbNone) to be created as
 spatial tables of type GEOMETRY (wkbUnknown), which was the behaviour prior to GDAL 1.8.0. Defaults to NO, in which case
 a regular table is created and not recorded in the PostGIS geometry_columns table.<p>
@@ -83,7 +83,11 @@ as the separator between the schema and the table name. Defaults to YES.<p>
 that should be use when CreateField() is invoked on them. This will override the default choice that OGR would have made.
 This can for example be used to create a column of type <a href="http://www.postgresql.org/docs/9.0/static/hstore.html">HSTORE</a>.<p>
 <li> <b>POSTGIS_VERSION</b>: (From GDAL 1.9.0) Can be set to 2.0 for PostGIS 2.0 compatibility. Starting with GDAL 2.0,
-it is important to set it correctly when dealing with non-linear geometry types.<p>
+it is important to set it correctly when dealing with non-linear geometry types. Starting with GDAL 2.1, can be
+POSTGIS_VERSION=2.2 is specially dealt with to correctly export POINT EMPTY geometries<p>
+<li> <b>DESCRIPTION</b> (From GDAL 2.1) Description string to put in the pg_description system table. The description
+can also be written with SetMetadataItem("DESCRIPTION", description_string). Descriptions are preserved
+by default by ogr2ogr, unless the -nomd option is used.</p>
 </ul>
 
 <h3>Environment variables</h3>
@@ -108,7 +112,7 @@ Writing to /dev/stdout or /vsistdout/ is also supported.<p>
 <li>
 Simple translation of a shapefile into PostgreSQL into a file abc.sql.  The table 'abc' will
 be created with the features from abc.shp and attributes from abc.dbf. The SRID is specified.
-PG_USE_COPY is set to YES to improve the peformance.<p>
+PG_USE_COPY is set to YES to improve the performance.<p>
 
 <pre>
 % ogr2ogr --config PG_USE_COPY YES -f PGDump abc.sql abc.shp -lco SRID=32631
diff --git a/ogr/ogrsf_frmts/pgdump/ogr_pgdump.h b/ogr/ogrsf_frmts/pgdump/ogr_pgdump.h
index 226cf92..4711eb8 100644
--- a/ogr/ogrsf_frmts/pgdump/ogr_pgdump.h
+++ b/ogr/ogrsf_frmts/pgdump/ogr_pgdump.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_pgdump.h 28988 2015-04-24 11:58:49Z rouault $
+ * $Id: ogr_pgdump.h 33639 2016-03-04 23:39:40Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/PostgreSQL dump driver.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_PGDUMP_H_INCLUDED
-#define _OGR_PGDUMP_H_INCLUDED
+#ifndef OGR_PGDUMP_H_INCLUDED
+#define OGR_PGDUMP_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "cpl_string.h"
@@ -74,12 +74,12 @@ class OGRPGDumpGeomFieldDefn : public OGRGeomFieldDefn
 {
     public:
         OGRPGDumpGeomFieldDefn( OGRGeomFieldDefn *poGeomField ) :
-            OGRGeomFieldDefn(poGeomField), nSRSId(-1), nCoordDimension(2)
+            OGRGeomFieldDefn(poGeomField), nSRSId(-1), GeometryTypeFlags(0)
             {
             }
             
         int nSRSId;
-        int nCoordDimension;
+        int GeometryTypeFlags;
 };
 
 /************************************************************************/
@@ -93,6 +93,7 @@ class OGRPGDumpLayer : public OGRLayer
 {
     char                *pszSchemaName;
     char                *pszSqlTableName;
+    CPLString           osForcedDescription;
     char                *pszFIDColumn;
     OGRFeatureDefn      *poFeatureDefn;
     OGRPGDumpDataSource *poDS;
@@ -105,8 +106,10 @@ class OGRPGDumpLayer : public OGRLayer
     int                 bCreateTable;
     int                 nUnknownSRSId;
     int                 nForcedSRSId;
+    int                 nForcedGeometryTypeFlags;
     int                 bCreateSpatialIndexFlag;
-    int                 bPostGIS2;
+    int                 nPostGISMajor;
+    int                 nPostGISMinor;
 
     int                 iNextShapeId;
     int                 iFIDAsRegularColumnIndex;
@@ -115,6 +118,8 @@ class OGRPGDumpLayer : public OGRLayer
 
     char              **papszOverrideColumnTypes;
 
+    CPLString           m_osFirstGeometryFieldName;
+
     OGRErr              StartCopy(int bSetFID);
     CPLString           BuildCopyFields(int bSetFID);
 
@@ -144,6 +149,9 @@ class OGRPGDumpLayer : public OGRLayer
 
     virtual OGRFeature *GetNextFeature();
 
+    virtual CPLErr      SetMetadata(char** papszMD, const char* pszDomain = "");
+    virtual CPLErr      SetMetadataItem(const char* pszName, const char* pszValue, const char* pszDomain = "");
+
     // follow methods are not base class overrides
     void                SetLaunderFlag( int bFlag )
                                 { bLaunderColumnNames = bFlag; }
@@ -155,10 +163,14 @@ class OGRPGDumpLayer : public OGRLayer
                                 { nUnknownSRSId = nUnknownSRSIdIn; }
     void                SetForcedSRSId( int nForcedSRSIdIn )
                                 { nForcedSRSId = nForcedSRSIdIn; }
+    void                SetForcedGeometryTypeFlags( int GeometryTypeFlagsIn )
+                                { nForcedGeometryTypeFlags = GeometryTypeFlagsIn; }
     void                SetCreateSpatialIndexFlag( int bFlag )
                                 { bCreateSpatialIndexFlag = bFlag; }
-    void                SetPostGIS2( int bFlag )
-                                { bPostGIS2 = bFlag; }
+    void                SetPostGISVersion(int nPostGISMajorIn, int nPostGISMinorIn)
+                                { nPostGISMajor = nPostGISMajorIn; nPostGISMinor = nPostGISMinorIn; }
+    void                SetGeometryFieldName( const char* pszGeomFieldName ) { m_osFirstGeometryFieldName = pszGeomFieldName; }
+    void                SetForcedDescription( const char* pszDescriptionIn );
     OGRErr              EndCopy();
 
     static char*        GByteArrayToBYTEA( const GByte* pabyData, int nLen);
@@ -203,5 +215,5 @@ class OGRPGDumpDataSource : public OGRDataSource
     OGRErr              EndCopy( );
 };
 
-#endif /* ndef _OGR_PGDUMP_H_INCLUDED */
+#endif /* ndef OGR_PGDUMP_H_INCLUDED */
 
diff --git a/ogr/ogrsf_frmts/pgdump/ogrpgdumpdatasource.cpp b/ogr/ogrsf_frmts/pgdump/ogrpgdumpdatasource.cpp
index 7712dda..e9814f4 100644
--- a/ogr/ogrsf_frmts/pgdump/ogrpgdumpdatasource.cpp
+++ b/ogr/ogrsf_frmts/pgdump/ogrpgdumpdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgdumpdatasource.cpp 31741 2015-11-24 10:22:41Z rouault $
+ * $Id: ogrpgdumpdatasource.cpp 33639 2016-03-04 23:39:40Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGDumpDataSource class.
@@ -32,19 +32,19 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrpgdumpdatasource.cpp 31741 2015-11-24 10:22:41Z rouault $");
+CPL_CVSID("$Id: ogrpgdumpdatasource.cpp 33639 2016-03-04 23:39:40Z rouault $");
 
 /************************************************************************/
 /*                      OGRPGDumpDataSource()                           */
 /************************************************************************/
 
-OGRPGDumpDataSource::OGRPGDumpDataSource(const char* pszName,
+OGRPGDumpDataSource::OGRPGDumpDataSource(const char* pszNameIn,
                                          char** papszOptions)
 
 {
     nLayers = 0;
     papoLayers = NULL;
-    this->pszName = CPLStrdup(pszName);
+    this->pszName = CPLStrdup(pszNameIn);
     bTriedOpen = FALSE;
     fp = NULL;
     bInTransaction = FALSE;
@@ -165,8 +165,8 @@ OGRPGDumpDataSource::ICreateLayer( const char * pszLayerName,
     const char          *pszGeomType = NULL;
     char                *pszTableName = NULL;
     char                *pszSchemaName = NULL;
-    int                  nDimension = 3;
     int                  bHavePostGIS = TRUE;
+    int                 GeometryTypeFlags = 0;
 
     const char* pszFIDColumnNameIn = CSLFetchNameValue(papszOptions, "FID");
     CPLString osFIDColumnName, osFIDColumnNameEscaped;
@@ -187,7 +187,7 @@ OGRPGDumpDataSource::ICreateLayer( const char * pszLayerName,
     }
     osFIDColumnNameEscaped = OGRPGDumpEscapeColumnName(osFIDColumnName);
 
-    if (strncmp(pszLayerName, "pg", 2) == 0)
+    if (STARTS_WITH(pszLayerName, "pg"))
     {
         CPLError(CE_Warning, CPLE_AppDefined,
                  "The layer name should not begin by 'pg' as it is a reserved prefix");
@@ -199,22 +199,54 @@ OGRPGDumpDataSource::ICreateLayer( const char * pszLayerName,
     int bCreateSchema = CSLFetchBoolean(papszOptions,"CREATE_SCHEMA", TRUE);
     const char* pszDropTable = CSLFetchNameValueDef(papszOptions,"DROP_TABLE", "IF_EXISTS");
 
-    if( wkbFlatten(eType) == eType )
-        nDimension = 2;
+    if( OGR_GT_HasZ((OGRwkbGeometryType)eType) )
+        GeometryTypeFlags |= OGRGeometry::OGR_G_3D;
+    if( OGR_GT_HasM((OGRwkbGeometryType)eType) )
+        GeometryTypeFlags |= OGRGeometry::OGR_G_MEASURED;
 
-    if( CSLFetchNameValue( papszOptions, "DIM") != NULL )
-        nDimension = atoi(CSLFetchNameValue( papszOptions, "DIM"));
+    int ForcedGeometryTypeFlags = -1;
+    const char* pszDim = CSLFetchNameValue( papszOptions, "DIM");
+    if( pszDim != NULL )
+    {
+        if( EQUAL(pszDim, "XY") || EQUAL(pszDim, "2") )
+        {
+            GeometryTypeFlags = 0;
+            ForcedGeometryTypeFlags = GeometryTypeFlags;
+        }
+        else if( EQUAL(pszDim, "XYZ") || EQUAL(pszDim, "3") )
+        {
+            GeometryTypeFlags = OGRGeometry::OGR_G_3D;
+            ForcedGeometryTypeFlags = GeometryTypeFlags;
+        }
+        else if( EQUAL(pszDim, "XYM") )
+        {
+            GeometryTypeFlags = OGRGeometry::OGR_G_MEASURED;
+            ForcedGeometryTypeFlags = GeometryTypeFlags;
+        }
+        else if( EQUAL(pszDim, "XYZM") || EQUAL(pszDim, "4") )
+        {
+            GeometryTypeFlags = OGRGeometry::OGR_G_3D | OGRGeometry::OGR_G_MEASURED;
+            ForcedGeometryTypeFlags = GeometryTypeFlags;
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Invalid value for DIM");
+        }
+    }
+
+    const int nDimension = 2 + ((GeometryTypeFlags & OGRGeometry::OGR_G_3D) ? 1 : 0)
+                       + ((GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED) ? 1 : 0);
 
     /* Should we turn layers with None geometry type as Unknown/GEOMETRY */
     /* so they are still recorded in geometry_columns table ? (#4012) */
-    int bNoneAsUnknown = CSLTestBoolean(CSLFetchNameValueDef(
+    int bNoneAsUnknown = CPLTestBool(CSLFetchNameValueDef(
                                     papszOptions, "NONE_AS_UNKNOWN", "NO"));
     if (bNoneAsUnknown && eType == wkbNone)
         eType = wkbUnknown;
     else if (eType == wkbNone)
         bHavePostGIS = FALSE;
 
-    int bExtractSchemaFromLayerName = CSLTestBoolean(CSLFetchNameValueDef(
+    int bExtractSchemaFromLayerName = CPLTestBool(CSLFetchNameValueDef(
                                     papszOptions, "EXTRACT_SCHEMA_FROM_LAYER_NAME", "YES"));
 
     /* Postgres Schema handling:
@@ -225,7 +257,7 @@ OGRPGDumpDataSource::ICreateLayer( const char * pszLayerName,
     const char* pszDotPos = strstr(pszLayerName,".");
     if ( pszDotPos != NULL && bExtractSchemaFromLayerName )
     {
-      int length = pszDotPos - pszLayerName;
+      int length = static_cast<int>(pszDotPos - pszLayerName);
       pszSchemaName = (char*)CPLMalloc(length+1);
       strncpy(pszSchemaName, pszLayerName, length);
       pszSchemaName[length] = '\0';
@@ -322,10 +354,15 @@ OGRPGDumpDataSource::ICreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
     int nUnknownSRSId = -1;
     const char* pszPostgisVersion = CSLFetchNameValue( papszOptions, "POSTGIS_VERSION" );
-    int bPostGIS2 = FALSE;
+    int nPostGISMajor = 1;
+    int nPostGISMinor = 5;
     if( pszPostgisVersion != NULL && atoi(pszPostgisVersion) >= 2 )
     {
-        bPostGIS2 = TRUE;
+        nPostGISMajor = atoi(pszPostgisVersion);
+        if( strchr(pszPostgisVersion, '.') )
+            nPostGISMinor = atoi(strchr(pszPostgisVersion, '.')+1);
+        else
+            nPostGISMinor = 0;
         nUnknownSRSId = 0;
     }
 
@@ -360,15 +397,13 @@ OGRPGDumpDataSource::ICreateLayer( const char * pszLayerName,
 
     const char *pszGeometryType = OGRToOGCGeomType(eType);
 
-    const char *pszGFldName = NULL;
+    const char *pszGFldName = CSLFetchNameValue( papszOptions, "GEOMETRY_NAME");
     if( bHavePostGIS && !EQUAL(pszGeomType, "geography"))
     {
-        if( CSLFetchNameValue( papszOptions, "GEOMETRY_NAME") != NULL )
-            pszGFldName = CSLFetchNameValue( papszOptions, "GEOMETRY_NAME");
-        else
+        if( pszGFldName == NULL )
             pszGFldName = "wkb_geometry";
 
-        if( pszPostgisVersion == NULL || atoi(pszPostgisVersion) < 2 )
+        if( nPostGISMajor < 2 )
         {
             /* Sometimes there is an old cruft entry in the geometry_columns
             * table if things were not properly cleaned up before.  We make
@@ -429,14 +464,28 @@ OGRPGDumpDataSource::ICreateLayer( const char * pszLayerName,
         else
             pszGFldName = "the_geog";
 
+        const char *suffix = "";
+        if( (GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED) && (GeometryTypeFlags & OGRGeometry::OGR_G_3D) )
+        {
+            suffix = "ZM";
+        }
+        else if( (GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED) )
+        {
+            suffix = "M";
+        }
+        else if( (GeometryTypeFlags & OGRGeometry::OGR_G_3D) )
+        {
+            suffix = "Z";
+        }
+
         if (nSRSId)
             osCommand.Printf(
                      "%s ( %s %s, \"%s\" geography(%s%s,%d), CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
-                     osCreateTable.c_str(), osFIDColumnNameEscaped.c_str(), pszSerialType, pszGFldName, pszGeometryType, nDimension == 2 ? "" : "Z", nSRSId, pszTableName, osFIDColumnNameEscaped.c_str() );
+                     osCreateTable.c_str(), osFIDColumnNameEscaped.c_str(), pszSerialType, pszGFldName, pszGeometryType, suffix, nSRSId, pszTableName, osFIDColumnNameEscaped.c_str() );
         else
             osCommand.Printf(
                      "%s ( %s %s, \"%s\" geography(%s%s), CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
-                     osCreateTable.c_str(), osFIDColumnNameEscaped.c_str(), pszSerialType, pszGFldName, pszGeometryType, nDimension == 2 ? "" : "Z", pszTableName, osFIDColumnNameEscaped.c_str() );
+                     osCreateTable.c_str(), osFIDColumnNameEscaped.c_str(), pszSerialType, pszGFldName, pszGeometryType, suffix, pszTableName, osFIDColumnNameEscaped.c_str() );
     }
     else
     {
@@ -455,15 +504,22 @@ OGRPGDumpDataSource::ICreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
     if( bCreateTable && bHavePostGIS && !EQUAL(pszGeomType, "geography"))
     {
+        const char *suffix = "";
+        if( GeometryTypeFlags == static_cast<int>(OGRGeometry::OGR_G_MEASURED) &&
+            wkbFlatten(eType) != wkbUnknown )
+        {
+            suffix = "M";
+        }
+
         osCommand.Printf(
-                "SELECT AddGeometryColumn('%s',%s,'%s',%d,'%s',%d)",
+                "SELECT AddGeometryColumn('%s',%s,'%s',%d,'%s%s',%d)",
                 pszSchemaName, pszEscapedTableNameSingleQuote, pszGFldName,
-                nSRSId, pszGeometryType, nDimension );
+                nSRSId, pszGeometryType, suffix, nDimension );
         Log(osCommand);
     }
 
     const char *pszSI = CSLFetchNameValue( papszOptions, "SPATIAL_INDEX" );
-    int bCreateSpatialIndex = ( pszSI == NULL || CSLTestBoolean(pszSI) );
+    int bCreateSpatialIndex = ( pszSI == NULL || CPLTestBool(pszSI) );
     if( bCreateTable && bHavePostGIS && bCreateSpatialIndex )
     {
 /* -------------------------------------------------------------------- */
@@ -497,7 +553,12 @@ OGRPGDumpDataSource::ICreateLayer( const char * pszLayerName,
     poLayer->SetUnknownSRSId(nUnknownSRSId);
     poLayer->SetForcedSRSId(nForcedSRSId);
     poLayer->SetCreateSpatialIndexFlag(bCreateSpatialIndex);
-    poLayer->SetPostGIS2(bPostGIS2);
+    poLayer->SetPostGISVersion(nPostGISMajor, nPostGISMinor);
+    poLayer->SetForcedGeometryTypeFlags(ForcedGeometryTypeFlags);
+
+    const char* pszDescription = CSLFetchNameValue(papszOptions, "DESCRIPTION");
+    if( pszDescription != NULL )
+        poLayer->SetForcedDescription( pszDescription );
 
     if( bHavePostGIS )
     {
@@ -505,9 +566,11 @@ OGRPGDumpDataSource::ICreateLayer( const char * pszLayerName,
         OGRPGDumpGeomFieldDefn *poGeomField =
             new OGRPGDumpGeomFieldDefn(&oTmp);
         poGeomField->nSRSId = nSRSId;
-        poGeomField->nCoordDimension = nDimension;
+        poGeomField->GeometryTypeFlags = GeometryTypeFlags;
         poLayer->GetLayerDefn()->AddGeomFieldDefn(poGeomField, FALSE);
     }
+    else if( pszGFldName )
+        poLayer->SetGeometryFieldName(pszGFldName);
 
 /* -------------------------------------------------------------------- */
 /*      Add layer to data source layer list.                            */
@@ -536,6 +599,8 @@ int OGRPGDumpDataSource::TestCapability( const char * pszCap )
         return TRUE;
     else if( EQUAL(pszCap,ODsCCurveGeometries) )
         return TRUE;
+    else if( EQUAL(pszCap,ODsCMeasuredGeometries) )
+        return TRUE;
     else
         return FALSE;
 }
diff --git a/ogr/ogrsf_frmts/pgdump/ogrpgdumpdriver.cpp b/ogr/ogrsf_frmts/pgdump/ogrpgdumpdriver.cpp
index dd8aaae..c9f7acb 100644
--- a/ogr/ogrsf_frmts/pgdump/ogrpgdumpdriver.cpp
+++ b/ogr/ogrsf_frmts/pgdump/ogrpgdumpdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgdumpdriver.cpp 28908 2015-04-15 09:01:01Z rouault $
+ * $Id: ogrpgdumpdriver.cpp 33639 2016-03-04 23:39:40Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGDumpDriver class.
@@ -30,7 +30,7 @@
 #include "ogr_pgdump.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrpgdumpdriver.cpp 28908 2015-04-15 09:01:01Z rouault $");
+CPL_CVSID("$Id: ogrpgdumpdriver.cpp 33639 2016-03-04 23:39:40Z rouault $");
 
 /************************************************************************/
 /*                         OGRPGDumpDriverCreate()                      */
@@ -65,21 +65,18 @@ static GDALDataset* OGRPGDumpDriverCreate( const char * pszName,
 void RegisterOGRPGDump()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "PGDUMP" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "PGDUMP" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "PGDUMP" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                    "PostgreSQL SQL dump" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                    "drv_pgdump.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "sql" );
+    poDriver->SetDescription( "PGDUMP" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "PostgreSQL SQL dump" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_pgdump.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "sql" );
 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
     "<CreationOptionList>"
     #ifdef WIN32
     "  <Option name='LINEFORMAT' type='string-select' description='end-of-line sequence' default='CRLF'>"
@@ -91,7 +88,7 @@ void RegisterOGRPGDump()
     "  </Option>"
     "</CreationOptionList>");
 
-        poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
     "<LayerCreationOptionList>"
     "  <Option name='GEOM_TYPE' type='string-select' description='Format of geometry columns' default='geometry'>"
     "    <Value>geometry</Value>"
@@ -99,16 +96,16 @@ void RegisterOGRPGDump()
     "  </Option>"
     "  <Option name='LAUNDER' type='boolean' description='Whether layer and field names will be laundered' default='YES'/>"
     "  <Option name='PRECISION' type='boolean' description='Whether fields created should keep the width and precision' default='YES'/>"
-    "  <Option name='DIM' type='integer' description='Set to 2 to force the geometries to be 2D, or 3 to be 2.5D'/>"
+    "  <Option name='DIM' type='string' description='Set to 2 to force the geometries to be 2D, 3 to be 2.5D, XYM or XYZM'/>"
     "  <Option name='GEOMETRY_NAME' type='string' description='Name of geometry column. Defaults to wkb_geometry for GEOM_TYPE=geometry or the_geog for GEOM_TYPE=geography'/>"
     "  <Option name='SCHEMA' type='string' description='Name of schema into which to create the new table'/>"
-    "  <Option name='CREATE_SCHEMA' type='boolean' description='Whether to explictely emit the CREATE SCHEMA statement to create the specified schema' default='YES'/>"
+    "  <Option name='CREATE_SCHEMA' type='boolean' description='Whether to explicitly emit the CREATE SCHEMA statement to create the specified schema' default='YES'/>"
     "  <Option name='SPATIAL_INDEX' type='boolean' description='Whether to create a spatial index' default='YES'/>"
     "  <Option name='TEMPORARY' type='boolean' description='Whether to a temporary table instead of a permanent one' default='NO'/>"
     "  <Option name='UNLOGGED' type='boolean' description='Whether to create the table as a unlogged one' default='NO'/>"
-    "  <Option name='WRITE_EWKT_GEOM' type='boolean' description='Whether to write EWKT geometries instead of HEX geometrie' default='NO'/>"
-    "  <Option name='CREATE_TABLE' type='boolean' description='Whether to explictely recreate the table if necessary' default='YES'/>"
-    "  <Option name='DROP_TABLE' type='string-select' description='Whether to explictely destroy tables before recreating them' default='YES'>"
+    "  <Option name='WRITE_EWKT_GEOM' type='boolean' description='Whether to write EWKT geometries instead of HEX geometry' default='NO'/>"
+    "  <Option name='CREATE_TABLE' type='boolean' description='Whether to explicitly recreate the table if necessary' default='YES'/>"
+    "  <Option name='DROP_TABLE' type='string-select' description='Whether to explicitly destroy tables before recreating them' default='YES'>"
     "    <Value>YES</Value>"
     "    <Value>ON</Value>"
     "    <Value>TRUE</Value>"
@@ -123,18 +120,21 @@ void RegisterOGRPGDump()
     "  <Option name='FID64' type='boolean' description='Whether to create the FID column with BIGSERIAL type to handle 64bit wide ids' default='NO'/>"
     "  <Option name='EXTRACT_SCHEMA_FROM_LAYER_NAME' type='boolean' description='Whether a dot in a layer name should be considered as the separator for the schema and table name' default='YES'/>"
     "  <Option name='COLUMN_TYPES' type='string' description='A list of strings of format field_name=pg_field_type (separated by comma) to force the PG column type of fields to be created'/>"
-    "  <Option name='POSTGIS_VERSION' type='string' description='Can be set to 2.0 for PostGIS 2.0 compatibility. Important to set it correctly if using non-linear geometry types'/>"
+    "  <Option name='POSTGIS_VERSION' type='string' description='Can be set to 2.0 or 2.2 for PostGIS 2.0/2.2 compatibility. Important to set it correctly if using non-linear geometry types'/>"
+    "  <Option name='DESCRIPTION' type='string' description='Description string to put in the pg_description system table'/>"
     "</LayerCreationOptionList>");
-        
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES, "Integer Integer64 Real String Date DateTime Time IntegerList Integer64List RealList StringList Binary" );
-        poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_FIELDS, "YES" );
-        poDriver->SetMetadataItem( GDAL_DCAP_DEFAULT_FIELDS, "YES" );
-        poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_GEOMFIELDS, "YES" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
+                               "Integer Integer64 Real String Date DateTime "
+                               "Time IntegerList Integer64List RealList "
+                               "StringList Binary" );
+    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_FIELDS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_DEFAULT_FIELDS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_GEOMFIELDS, "YES" );
 
-        poDriver->pfnCreate = OGRPGDumpDriverCreate;
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    poDriver->pfnCreate = OGRPGDumpDriverCreate;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/pgdump/ogrpgdumplayer.cpp b/ogr/ogrsf_frmts/pgdump/ogrpgdumplayer.cpp
index fa07f1f..617b4e0 100644
--- a/ogr/ogrsf_frmts/pgdump/ogrpgdumplayer.cpp
+++ b/ogr/ogrsf_frmts/pgdump/ogrpgdumplayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgdumplayer.cpp 29330 2015-06-14 12:11:11Z rouault $
+ * $Id: ogrpgdumplayer.cpp 33645 2016-03-05 15:43:17Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGDumpLayer class
@@ -32,7 +32,7 @@
 #include "cpl_string.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrpgdumplayer.cpp 29330 2015-06-14 12:11:11Z rouault $");
+CPL_CVSID("$Id: ogrpgdumplayer.cpp 33645 2016-03-05 15:43:17Z rouault $");
 
 #define USE_COPY_UNSET -1
 
@@ -41,9 +41,9 @@ static CPLString OGRPGDumpEscapeStringList(
                                        OGRPGCommonEscapeStringCbk pfnEscapeString,
                                        void* userdata);
 
-static CPLString OGRPGDumpEscapeStringWithUserData(   void* user_data,
+static CPLString OGRPGDumpEscapeStringWithUserData(   CPL_UNUSED void* user_data,
                                    const char* pszStrValue, int nMaxLength,
-                                   const char* pszLayerName,
+                                   CPL_UNUSED const char* pszLayerName,
                                    const char* pszFieldName)
 {
     return OGRPGDumpEscapeString(pszStrValue, nMaxLength, pszFieldName);
@@ -53,14 +53,17 @@ static CPLString OGRPGDumpEscapeStringWithUserData(   void* user_data,
 /*                        OGRPGDumpLayer()                              */
 /************************************************************************/
 
-OGRPGDumpLayer::OGRPGDumpLayer(OGRPGDumpDataSource* poDS,
-                               const char* pszSchemaName,
+OGRPGDumpLayer::OGRPGDumpLayer(OGRPGDumpDataSource* poDSIn,
+                               const char* pszSchemaNameIn,
                                const char* pszTableName,
-                               const char *pszFIDColumn,
+                               const char *pszFIDColumnIn,
                                int         bWriteAsHexIn,
-                               int         bCreateTable)
+                               int         bCreateTableIn)
 {
-    this->poDS = poDS;
+    this->poDS = poDSIn;
+    this->pszSchemaName = CPLStrdup(pszSchemaNameIn);
+    this->pszFIDColumn = CPLStrdup(pszFIDColumnIn);
+    this->bCreateTable = bCreateTableIn;
     poFeatureDefn = new OGRFeatureDefn( pszTableName );
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->SetGeomType(wkbNone);
@@ -68,9 +71,6 @@ OGRPGDumpLayer::OGRPGDumpLayer(OGRPGDumpDataSource* poDS,
     pszSqlTableName = CPLStrdup(CPLString().Printf("%s.%s",
                                OGRPGDumpEscapeColumnName(pszSchemaName).c_str(),
                                OGRPGDumpEscapeColumnName(pszTableName).c_str() ));
-    this->pszSchemaName = CPLStrdup(pszSchemaName);
-    this->pszFIDColumn = CPLStrdup(pszFIDColumn);
-    this->bCreateTable = bCreateTable;
     bLaunderColumnNames = TRUE;
     bPreservePrecision = TRUE;
     bUseCopy = USE_COPY_UNSET;
@@ -80,8 +80,10 @@ OGRPGDumpLayer::OGRPGDumpLayer(OGRPGDumpDataSource* poDS,
     papszOverrideColumnTypes = NULL;
     nUnknownSRSId = -1;
     nForcedSRSId = -2;
+    nForcedGeometryTypeFlags = -1;
     bCreateSpatialIndexFlag = TRUE;
-    bPostGIS2 = FALSE;
+    nPostGISMajor = 1;
+    nPostGISMinor = 2;
     iNextShapeId = 0;
     iFIDAsRegularColumnIndex = -1;
     bAutoFIDOnCreateViaCopy = TRUE;
@@ -122,7 +124,8 @@ int OGRPGDumpLayer::TestCapability( const char * pszCap )
     if( EQUAL(pszCap,OLCSequentialWrite) ||
         EQUAL(pszCap,OLCCreateField) ||
         EQUAL(pszCap,OLCCreateGeomField) ||
-        EQUAL(pszCap,OLCCurveGeometries) )
+        EQUAL(pszCap,OLCCurveGeometries) ||
+        EQUAL(pszCap,OLCMeasuredGeometries) )
         return TRUE;
     else
         return FALSE;
@@ -159,17 +162,17 @@ OGRErr OGRPGDumpLayer::ICreateFeature( OGRFeature *poFeature )
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
                             "Inconsistent values of FID and field of same name");
-                return CE_Failure;
+                return OGRERR_FAILURE;
             }
         }
     }
 
-    if( !poFeature->Validate(OGR_F_VAL_ALL & ~OGR_F_VAL_WIDTH, TRUE ) )
+    if( !poFeature->Validate((OGR_F_VAL_ALL & ~OGR_F_VAL_WIDTH) | OGR_F_VAL_ALLOW_DIFFERENT_GEOM_DIM, TRUE ) )
         return OGRERR_FAILURE;
 
     // We avoid testing the config option too often. 
     if( bUseCopy == USE_COPY_UNSET )
-        bUseCopy = CSLTestBoolean( CPLGetConfigOption( "PG_USE_COPY", "NO") );
+        bUseCopy = CPLTestBool( CPLGetConfigOption( "PG_USE_COPY", "NO") );
 
     OGRErr eErr;
     if( !bUseCopy )
@@ -220,7 +223,7 @@ OGRErr OGRPGDumpLayer::ICreateFeature( OGRFeature *poFeature )
                 eErr = CreateFeatureViaCopy( poFeature );
                 if( bFIDSet )
                     bAutoFIDOnCreateViaCopy = FALSE;
-                if( eErr == CE_None && bAutoFIDOnCreateViaCopy )
+                if( eErr == OGRERR_NONE && bAutoFIDOnCreateViaCopy )
                 {
                     poFeature->SetFID( ++iNextShapeId );
                 }
@@ -228,7 +231,7 @@ OGRErr OGRPGDumpLayer::ICreateFeature( OGRFeature *poFeature )
         }
     }
 
-    if( eErr == CE_None && iFIDAsRegularColumnIndex >= 0 )
+    if( eErr == OGRERR_NONE && iFIDAsRegularColumnIndex >= 0 )
     {
         poFeature->SetField(iFIDAsRegularColumnIndex, poFeature->GetFID());
     }
@@ -317,7 +320,8 @@ OGRErr OGRPGDumpLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
                 (OGRPGDumpGeomFieldDefn*) poFeature->GetGeomFieldDefnRef(i);
 
             poGeom->closeRings();
-            poGeom->setCoordinateDimension( poGFldDefn->nCoordDimension );
+            poGeom->set3D(poGFldDefn->GeometryTypeFlags & OGRGeometry::OGR_G_3D);
+            poGeom->setMeasured(poGFldDefn->GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED);
 
             if( bNeedComma )
                 osCommand += ", ";
@@ -325,7 +329,8 @@ OGRErr OGRPGDumpLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
             if( bWriteAsHex )
             {
                 char* pszHex = OGRGeometryToHexEWKB( poGeom, poGFldDefn->nSRSId,
-                                                     bPostGIS2 );
+                                                     nPostGISMajor,
+                                                     nPostGISMinor );
                 osCommand += "'";
                 if (pszHex)
                     osCommand += pszHex;
@@ -414,7 +419,8 @@ OGRErr OGRPGDumpLayer::CreateFeatureViaCopy( OGRFeature *poFeature )
                 (OGRPGDumpGeomFieldDefn*) poFeature->GetGeomFieldDefnRef(i);
 
             poGeometry->closeRings();
-            poGeometry->setCoordinateDimension( poGFldDefn->nCoordDimension );
+            poGeometry->set3D(poGFldDefn->GeometryTypeFlags & OGRGeometry::OGR_G_3D);
+            poGeometry->setMeasured(poGFldDefn->GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED);
 
             //CheckGeomTypeCompatibility(poGeometry);
     
@@ -422,7 +428,8 @@ OGRErr OGRPGDumpLayer::CreateFeatureViaCopy( OGRFeature *poFeature )
                 pszGeom = GeometryToBYTEA( poGeometry );
             else*/
                 pszGeom = OGRGeometryToHexEWKB( poGeometry, poGFldDefn->nSRSId,
-                                                bPostGIS2 );
+                                                nPostGISMajor,
+                                                nPostGISMinor );
         }
     
         if (osCommand.size() > 0)
@@ -527,15 +534,16 @@ void OGRPGCommonAppendCopyFieldsExceptGeom(CPLString& osCommand,
             int nCount, nOff = 0, j;
             const int *panItems = poFeature->GetFieldAsIntegerList(i,&nCount);
 
-            pszNeedToFree = (char *) CPLMalloc(nCount * 13 + 10);
+            const size_t nLen = nCount * 13 + 10;
+            pszNeedToFree = (char *) CPLMalloc(nLen);
             strcpy( pszNeedToFree, "{" );
             for( j = 0; j < nCount; j++ )
             {
                 if( j != 0 )
                     strcat( pszNeedToFree+nOff, "," );
 
-                nOff += strlen(pszNeedToFree+nOff);
-                sprintf( pszNeedToFree+nOff, "%d", panItems[j] );
+                nOff += static_cast<int>(strlen(pszNeedToFree+nOff));
+                snprintf( pszNeedToFree+nOff, nLen-nOff, "%d", panItems[j] );
             }
             strcat( pszNeedToFree+nOff, "}" );
             pszStrValue = pszNeedToFree;
@@ -546,15 +554,16 @@ void OGRPGCommonAppendCopyFieldsExceptGeom(CPLString& osCommand,
             int nCount, nOff = 0, j;
             const GIntBig *panItems = poFeature->GetFieldAsInteger64List(i,&nCount);
 
-            pszNeedToFree = (char *) CPLMalloc(nCount * 26 + 10);
+            const size_t nLen = nCount * 26 + 10;
+            pszNeedToFree = (char *) CPLMalloc(nLen);
             strcpy( pszNeedToFree, "{" );
             for( j = 0; j < nCount; j++ )
             {
                 if( j != 0 )
                     strcat( pszNeedToFree+nOff, "," );
 
-                nOff += strlen(pszNeedToFree+nOff);
-                sprintf( pszNeedToFree+nOff, CPL_FRMT_GIB, panItems[j] );
+                nOff += static_cast<int>(strlen(pszNeedToFree+nOff));
+                snprintf( pszNeedToFree+nOff, nLen-nOff, CPL_FRMT_GIB, panItems[j] );
             }
             strcat( pszNeedToFree+nOff, "}" );
             pszStrValue = pszNeedToFree;
@@ -566,21 +575,22 @@ void OGRPGCommonAppendCopyFieldsExceptGeom(CPLString& osCommand,
             int nCount, nOff = 0, j;
             const double *padfItems =poFeature->GetFieldAsDoubleList(i,&nCount);
 
-            pszNeedToFree = (char *) CPLMalloc(nCount * 40 + 10);
+            const size_t nLen = nCount * 40 + 10;
+            pszNeedToFree = (char *) CPLMalloc(nLen);
             strcpy( pszNeedToFree, "{" );
             for( j = 0; j < nCount; j++ )
             {
                 if( j != 0 )
                     strcat( pszNeedToFree+nOff, "," );
 
-                nOff += strlen(pszNeedToFree+nOff);
+                nOff += static_cast<int>(strlen(pszNeedToFree+nOff));
                 //Check for special values. They need to be quoted.
                 if( CPLIsNan(padfItems[j]) )
-                    sprintf( pszNeedToFree+nOff, "NaN" );
+                    snprintf( pszNeedToFree+nOff, nLen-nOff, "NaN" );
                 else if( CPLIsInf(padfItems[j]) )
-                    sprintf( pszNeedToFree+nOff, (padfItems[j] > 0) ? "Infinity" : "-Infinity" );
+                    snprintf( pszNeedToFree+nOff, nLen-nOff, (padfItems[j] > 0) ? "Infinity" : "-Infinity" );
                 else
-                    CPLsprintf( pszNeedToFree+nOff, "%.16g", padfItems[j] );
+                    CPLsnprintf( pszNeedToFree+nOff, nLen-nOff, "%.16g", padfItems[j] );
 
             }
             strcat( pszNeedToFree+nOff, "}" );
@@ -634,7 +644,7 @@ void OGRPGCommonAppendCopyFieldsExceptGeom(CPLString& osCommand,
             for( iChar = 0; pszStrValue[iChar] != '\0'; iChar++ )
             {
                 //count of utf chars
-                if ((pszStrValue[iChar] & 0xc0) != 0x80) 
+                if (nOGRFieldType != OFTStringList && (pszStrValue[iChar] & 0xc0) != 0x80) 
                 {
                     if( nMaxWidth > 0 && iUTFChar == nMaxWidth )
                     {
@@ -681,10 +691,10 @@ OGRErr OGRPGDumpLayer::StartCopy(int bSetFID)
 
     CPLString osFields = BuildCopyFields(bSetFID);
 
-    int size = strlen(osFields) +  strlen(pszSqlTableName) + 100;
+    size_t size = strlen(osFields) +  strlen(pszSqlTableName) + 100;
     char *pszCommand = (char *) CPLMalloc(size);
 
-    sprintf( pszCommand,
+    snprintf( pszCommand, size,
              "COPY %s (%s) FROM STDIN",
              pszSqlTableName, osFields.c_str() );
 
@@ -799,7 +809,7 @@ CPLString OGRPGDumpEscapeString(
     /* We need to quote and escape string fields. */
     osCommand += "'";
 
-    int nSrcLen = strlen(pszStrValue);
+    int nSrcLen = static_cast<int>(strlen(pszStrValue));
     int nSrcLenUTF = CPLStrlenUTF8(pszStrValue);
 
     if (nMaxLength > 0 && nSrcLenUTF > nMaxLength)
@@ -960,15 +970,16 @@ void OGRPGCommonAppendFieldValue(CPLString& osCommand,
         const int *panItems = poFeature->GetFieldAsIntegerList(i,&nCount);
         char *pszNeedToFree = NULL;
 
-        pszNeedToFree = (char *) CPLMalloc(nCount * 13 + 10);
+        const size_t nLen = nCount * 13 + 10;
+        pszNeedToFree = (char *) CPLMalloc(nLen);
         strcpy( pszNeedToFree, "'{" );
         for( j = 0; j < nCount; j++ )
         {
             if( j != 0 )
                 strcat( pszNeedToFree+nOff, "," );
 
-            nOff += strlen(pszNeedToFree+nOff);
-            sprintf( pszNeedToFree+nOff, "%d", panItems[j] );
+            nOff += static_cast<int>(strlen(pszNeedToFree+nOff));
+            snprintf( pszNeedToFree+nOff, nLen-nOff, "%d", panItems[j] );
         }
         strcat( pszNeedToFree+nOff, "}'" );
 
@@ -984,15 +995,16 @@ void OGRPGCommonAppendFieldValue(CPLString& osCommand,
         const GIntBig *panItems = poFeature->GetFieldAsInteger64List(i,&nCount);
         char *pszNeedToFree = NULL;
 
-        pszNeedToFree = (char *) CPLMalloc(nCount * 26 + 10);
+        const size_t nLen = nCount * 26 + 10;
+        pszNeedToFree = (char *) CPLMalloc(nLen);
         strcpy( pszNeedToFree, "'{" );
         for( j = 0; j < nCount; j++ )
         {
             if( j != 0 )
                 strcat( pszNeedToFree+nOff, "," );
 
-            nOff += strlen(pszNeedToFree+nOff);
-            sprintf( pszNeedToFree+nOff, CPL_FRMT_GIB, panItems[j] );
+            nOff += static_cast<int>(strlen(pszNeedToFree+nOff));
+            snprintf( pszNeedToFree+nOff, nLen-nOff, CPL_FRMT_GIB, panItems[j] );
         }
         strcat( pszNeedToFree+nOff, "}'" );
 
@@ -1009,21 +1021,22 @@ void OGRPGCommonAppendFieldValue(CPLString& osCommand,
         const double *padfItems =poFeature->GetFieldAsDoubleList(i,&nCount);
         char *pszNeedToFree = NULL;
 
-        pszNeedToFree = (char *) CPLMalloc(nCount * 40 + 10);
+        const size_t nLen = nCount * 40 + 10;
+        pszNeedToFree = (char *) CPLMalloc(nLen);
         strcpy( pszNeedToFree, "'{" );
         for( j = 0; j < nCount; j++ )
         {
             if( j != 0 )
                 strcat( pszNeedToFree+nOff, "," );
 
-            nOff += strlen(pszNeedToFree+nOff);
+            nOff += static_cast<int>(strlen(pszNeedToFree+nOff));
             //Check for special values. They need to be quoted.
             if( CPLIsNan(padfItems[j]) )
-                sprintf( pszNeedToFree+nOff, "NaN" );
+                snprintf( pszNeedToFree+nOff, nLen-nOff, "NaN" );
             else if( CPLIsInf(padfItems[j]) )
-                sprintf( pszNeedToFree+nOff, (padfItems[j] > 0) ? "Infinity" : "-Infinity" );
+                snprintf( pszNeedToFree+nOff, nLen-nOff, (padfItems[j] > 0) ? "Infinity" : "-Infinity" );
             else
-                CPLsprintf( pszNeedToFree+nOff, "%.16g", padfItems[j] );
+                CPLsnprintf( pszNeedToFree+nOff, nLen-nOff, "%.16g", padfItems[j] );
 
         }
         strcat( pszNeedToFree+nOff, "}'" );
@@ -1071,7 +1084,7 @@ void OGRPGCommonAppendFieldValue(CPLString& osCommand,
     // Check if date is NULL: 0000-00-00
     if( nOGRFieldType == OFTDate )
     {
-        if( EQUALN( pszStrValue, "0000", 4 ) )
+        if( STARTS_WITH_CI(pszStrValue, "0000") )
         {
             pszStrValue = "NULL";
             bIsDateNull = TRUE;
@@ -1091,7 +1104,7 @@ void OGRPGCommonAppendFieldValue(CPLString& osCommand,
         pszStrValue = poFeature->GetFieldAsInteger(i) ? "'t'" : "'f'";
 
     if( nOGRFieldType != OFTInteger && nOGRFieldType != OFTInteger64 && 
-        nOGRFieldType != OFTReal
+        nOGRFieldType != OFTReal && nOGRFieldType != OFTStringList 
         && !bIsDateNull )
     {
         osCommand += pfnEscapeString( userdata, pszStrValue,
@@ -1114,7 +1127,8 @@ char* OGRPGDumpLayer::GByteArrayToBYTEA( const GByte* pabyData, int nLen)
 {
     char* pszTextBuf;
 
-    pszTextBuf = (char *) CPLMalloc(nLen*5+1);
+    const size_t nTextBufLen = nLen * 5 + 1;
+    pszTextBuf = (char *) CPLMalloc(nTextBufLen);
 
     int  iSrc, iDst=0;
 
@@ -1123,7 +1137,7 @@ char* OGRPGDumpLayer::GByteArrayToBYTEA( const GByte* pabyData, int nLen)
         if( pabyData[iSrc] < 40 || pabyData[iSrc] > 126
             || pabyData[iSrc] == '\\' )
         {
-            sprintf( pszTextBuf+iDst, "\\\\%03o", pabyData[iSrc] );
+            snprintf( pszTextBuf+iDst, nTextBufLen - iDst, "\\\\%03o", pabyData[iSrc] );
             iDst += 5;
         }
         else
@@ -1154,14 +1168,14 @@ CPLString OGRPGCommonLayerGetType(OGRFieldDefn& oField,
         else if( oField.GetSubType() == OFSTInt16 )
             strcpy( szFieldType, "SMALLINT" );
         else if( oField.GetWidth() > 0 && bPreservePrecision )
-            sprintf( szFieldType, "NUMERIC(%d,0)", oField.GetWidth() );
+            snprintf( szFieldType, sizeof(szFieldType), "NUMERIC(%d,0)", oField.GetWidth() );
         else
             strcpy( szFieldType, "INTEGER" );
     }
     else if( oField.GetType() == OFTInteger64 )
     {
         if( oField.GetWidth() > 0 && bPreservePrecision )
-            sprintf( szFieldType, "NUMERIC(%d,0)", oField.GetWidth() );
+            snprintf( szFieldType, sizeof(szFieldType), "NUMERIC(%d,0)", oField.GetWidth() );
         else
             strcpy( szFieldType, "INT8" );
     }
@@ -1171,7 +1185,7 @@ CPLString OGRPGCommonLayerGetType(OGRFieldDefn& oField,
             strcpy( szFieldType, "REAL" );
         else if( oField.GetWidth() > 0 && oField.GetPrecision() > 0
             && bPreservePrecision )
-            sprintf( szFieldType, "NUMERIC(%d,%d)",
+            snprintf( szFieldType, sizeof(szFieldType), "NUMERIC(%d,%d)",
                      oField.GetWidth(), oField.GetPrecision() );
         else
             strcpy( szFieldType, "FLOAT8" );
@@ -1179,7 +1193,7 @@ CPLString OGRPGCommonLayerGetType(OGRFieldDefn& oField,
     else if( oField.GetType() == OFTString )
     {
         if (oField.GetWidth() > 0 &&  bPreservePrecision )
-            sprintf( szFieldType, "VARCHAR(%d)",  oField.GetWidth() );
+            snprintf( szFieldType, sizeof(szFieldType), "VARCHAR(%d)",  oField.GetWidth() );
         else
             strcpy( szFieldType, "VARCHAR");
     }
@@ -1187,6 +1201,8 @@ CPLString OGRPGCommonLayerGetType(OGRFieldDefn& oField,
     {
         if( oField.GetSubType() == OFSTBoolean )
             strcpy( szFieldType, "BOOLEAN[]" );
+        else if( oField.GetSubType() == OFSTInt16 )
+            strcpy( szFieldType, "INT2[]" );
         else
             strcpy( szFieldType, "INTEGER[]" );
     }
@@ -1196,7 +1212,10 @@ CPLString OGRPGCommonLayerGetType(OGRFieldDefn& oField,
     }
     else if( oField.GetType() == OFTRealList )
     {
-        strcpy( szFieldType, "FLOAT8[]" );
+        if( oField.GetSubType() == OFSTFloat32 )
+            strcpy( szFieldType, "REAL[]" );
+        else
+            strcpy( szFieldType, "FLOAT8[]" );
     }
     else if( oField.GetType() == OFTStringList )
     {
@@ -1261,9 +1280,9 @@ int OGRPGCommonLayerSetType(OGRFieldDefn& oField,
     {
         if( nWidth == -1 )
         {
-            if( EQUALN(pszFormatType,"character(",10) )
+            if( STARTS_WITH_CI(pszFormatType, "character(") )
                 nWidth = atoi(pszFormatType+10);
-            else if( EQUALN(pszFormatType,"character varying(",18) )
+            else if( STARTS_WITH_CI(pszFormatType, "character varying(") )
                 nWidth = atoi(pszFormatType+18);
             else
                 nWidth = 0;
@@ -1277,6 +1296,33 @@ int OGRPGCommonLayerSetType(OGRFieldDefn& oField,
         oField.SetSubType( OFSTBoolean );
         oField.SetWidth( 1 );
     }
+    else if( EQUAL(pszType,"_numeric") )
+    {
+        if( EQUAL(pszFormatType, "numeric[]") )
+            oField.SetType( OFTRealList );
+        else
+        {
+            const char *pszPrecision = strstr(pszFormatType,",");
+            int    nPrecision = 0;
+
+            nWidth = atoi(pszFormatType + 8);
+            if( pszPrecision != NULL )
+                nPrecision = atoi(pszPrecision+1);
+
+            if( nPrecision == 0 )
+            {
+                if( nWidth >= 10 )
+                    oField.SetType( OFTInteger64List );
+                else
+                    oField.SetType( OFTIntegerList );
+            }
+            else
+                oField.SetType( OFTRealList );
+
+            oField.SetWidth( nWidth );
+            oField.SetPrecision( nPrecision );
+        }
+    }
     else if( EQUAL(pszType,"numeric") )
     {
         if( EQUAL(pszFormatType, "numeric") )
@@ -1284,7 +1330,7 @@ int OGRPGCommonLayerSetType(OGRFieldDefn& oField,
         else
         {
             const char *pszPrecision = strstr(pszFormatType,",");
-            int    nWidth, nPrecision = 0;
+            int    nPrecision = 0;
 
             nWidth = atoi(pszFormatType + 8);
             if( pszPrecision != NULL )
@@ -1308,6 +1354,11 @@ int OGRPGCommonLayerSetType(OGRFieldDefn& oField,
     {
         oField.SetType( OFTIntegerList );
     }
+    else if( EQUAL(pszFormatType,"smallint[]") )
+    {
+        oField.SetType( OFTIntegerList );
+        oField.SetSubType( OFSTInt16 );
+    }
     else if( EQUAL(pszFormatType,"boolean[]") )
     {
         oField.SetType( OFTIntegerList );
@@ -1337,7 +1388,7 @@ int OGRPGCommonLayerSetType(OGRFieldDefn& oField,
     {
         oField.SetType( OFTInteger64List );
     }
-    else if( EQUALN(pszType,"int",3) )
+    else if( STARTS_WITH_CI(pszType, "int") )
     {
         oField.SetType( OFTInteger );
     }
@@ -1346,21 +1397,21 @@ int OGRPGCommonLayerSetType(OGRFieldDefn& oField,
         oField.SetType( OFTReal );
         oField.SetSubType( OFSTFloat32 );
     }
-    else if( EQUALN(pszType,"float",5) ||
-            EQUALN(pszType,"double",6) ||
+    else if( STARTS_WITH_CI(pszType, "float") ||
+            STARTS_WITH_CI(pszType, "double") ||
             EQUAL(pszType,"real") )
     {
         oField.SetType( OFTReal );
     }
-    else if( EQUALN(pszType, "timestamp",9) )
+    else if( STARTS_WITH_CI(pszType, "timestamp") )
     {
         oField.SetType( OFTDateTime );
     }
-    else if( EQUALN(pszType, "date",4) )
+    else if( STARTS_WITH_CI(pszType, "date") )
     {
         oField.SetType( OFTDate );
     }
-    else if( EQUALN(pszType, "time",4) )
+    else if( STARTS_WITH_CI(pszType, "time") )
     {
         oField.SetType( OFTTime );
     }
@@ -1459,7 +1510,7 @@ OGRErr OGRPGDumpLayer::CreateField( OGRFieldDefn *poFieldIn,
     
     // Can be set to NO to test ogr2ogr default behaviour
     int bAllowCreationOfFieldWithFIDName =
-        CSLTestBoolean(CPLGetConfigOption("PGDUMP_DEBUG_ALLOW_CREATION_FIELD_WITH_FID_NAME", "YES"));
+        CPLTestBool(CPLGetConfigOption("PGDUMP_DEBUG_ALLOW_CREATION_FIELD_WITH_FID_NAME", "YES"));
 
     if( bAllowCreationOfFieldWithFIDName && pszFIDColumn != NULL &&
         EQUAL( oField.GetNameRef(), pszFIDColumn ) &&
@@ -1468,7 +1519,7 @@ OGRErr OGRPGDumpLayer::CreateField( OGRFieldDefn *poFieldIn,
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Wrong field type for %s",
                  oField.GetNameRef());
-        return CE_Failure;
+        return OGRERR_FAILURE;
     }
 
 /* -------------------------------------------------------------------- */
@@ -1545,9 +1596,19 @@ OGRErr OGRPGDumpLayer::CreateGeomField( OGRGeomFieldDefn *poGeomFieldIn,
         return OGRERR_FAILURE;
     }
 
+    // Check if GEOMETRY_NAME layer creation option was set, but no initial
+    // column was created in ICreateLayer()
+    CPLString osGeomFieldName = 
+        ( m_osFirstGeometryFieldName.size() ) ? m_osFirstGeometryFieldName :
+                                                CPLString(poGeomFieldIn->GetNameRef());
+    m_osFirstGeometryFieldName = ""; // reset for potential next geom columns
+
+    OGRGeomFieldDefn oTmpGeomFieldDefn( poGeomFieldIn );
+    oTmpGeomFieldDefn.SetName(osGeomFieldName);
+
     CPLString               osCommand;
     OGRPGDumpGeomFieldDefn *poGeomField =
-        new OGRPGDumpGeomFieldDefn( poGeomFieldIn );
+        new OGRPGDumpGeomFieldDefn( &oTmpGeomFieldDefn );
 
 /* -------------------------------------------------------------------- */
 /*      Do we want to "launder" the column names into Postgres          */
@@ -1580,25 +1641,49 @@ OGRErr OGRPGDumpLayer::CreateGeomField( OGRGeomFieldDefn *poGeomFieldIn,
                 nSRSId = 4326;
         }
     }
-    
-    int nDimension = 3;
-    if( wkbFlatten(eType) == eType )
-        nDimension = 2;
+
     poGeomField->nSRSId = nSRSId;
-    poGeomField->nCoordDimension = nDimension;
+
+    int GeometryTypeFlags = 0;
+    if( OGR_GT_HasZ((OGRwkbGeometryType)eType) )
+        GeometryTypeFlags |= OGRGeometry::OGR_G_3D;
+    if( OGR_GT_HasM((OGRwkbGeometryType)eType) )
+        GeometryTypeFlags |= OGRGeometry::OGR_G_MEASURED;
+    if( nForcedGeometryTypeFlags >= 0 )
+    {
+        GeometryTypeFlags = nForcedGeometryTypeFlags;
+        eType = OGR_GT_SetModifier(eType, 
+                                   GeometryTypeFlags & OGRGeometry::OGR_G_3D, 
+                                   GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED);
+    }
+    poGeomField->SetType(eType);
+    poGeomField->GeometryTypeFlags = GeometryTypeFlags;
 
 /* -------------------------------------------------------------------- */
 /*      Create the new field.                                           */
 /* -------------------------------------------------------------------- */
     if (bCreateTable)
     {
+        const char *suffix = "";
+        int dim = 2;
+        if( (poGeomField->GeometryTypeFlags & OGRGeometry::OGR_G_3D) && (poGeomField->GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED) )
+            dim = 4;
+        else if( poGeomField->GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED )
+        {
+            if( wkbFlatten(poGeomField->GetType()) != wkbUnknown )
+                suffix = "M";
+            dim = 3;
+        }
+        else if( poGeomField->GeometryTypeFlags & OGRGeometry::OGR_G_3D )
+            dim = 3;
+
         const char *pszGeometryType = OGRToOGCGeomType(poGeomField->GetType());
         osCommand.Printf(
-                "SELECT AddGeometryColumn(%s,%s,%s,%d,'%s',%d)",
+                "SELECT AddGeometryColumn(%s,%s,%s,%d,'%s%s',%d)",
                 OGRPGDumpEscapeString(pszSchemaName).c_str(),
                 OGRPGDumpEscapeString(poFeatureDefn->GetName()).c_str(),
                 OGRPGDumpEscapeString(poGeomField->GetNameRef()).c_str(),
-                nSRSId, pszGeometryType, nDimension );
+                nSRSId, pszGeometryType, suffix, dim );
         
         poDS->Log(osCommand);
 
@@ -1671,3 +1756,72 @@ void OGRPGDumpLayer::SetOverrideColumnTypes( const char* pszOverrideColumnTypes
     if( osCur.size() )
         papszOverrideColumnTypes = CSLAddString(papszOverrideColumnTypes, osCur);
 }
+
+/************************************************************************/
+/*                              SetMetadata()                           */
+/************************************************************************/
+
+CPLErr OGRPGDumpLayer::SetMetadata(char** papszMD, const char* pszDomain)
+{
+    OGRLayer::SetMetadata(papszMD, pszDomain);
+    if( osForcedDescription.size() != 0 &&
+        (pszDomain == NULL || EQUAL(pszDomain, "")) )
+    {
+        OGRLayer::SetMetadataItem("DESCRIPTION", osForcedDescription);
+    }
+
+    if( (pszDomain == NULL || EQUAL(pszDomain, "")) &&
+        osForcedDescription.size() == 0 )
+    {
+        const char* l_pszDescription = OGRLayer::GetMetadataItem("DESCRIPTION");
+        CPLString osCommand;
+
+        osCommand.Printf( "COMMENT ON TABLE %s IS %s",
+                           pszSqlTableName,
+                           l_pszDescription && l_pszDescription[0] != '\0' ?
+                              OGRPGDumpEscapeString(l_pszDescription).c_str() : "NULL" );
+        poDS->Log( osCommand );
+    }
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                            SetMetadataItem()                         */
+/************************************************************************/
+
+CPLErr OGRPGDumpLayer::SetMetadataItem(const char* pszName, const char* pszValue,
+                                       const char* pszDomain)
+{
+    if( (pszDomain == NULL || EQUAL(pszDomain, "")) && pszName != NULL &&
+        EQUAL(pszName, "DESCRIPTION") && osForcedDescription.size() )
+    {
+        return CE_None;
+    }
+    OGRLayer::SetMetadataItem(pszName, pszValue, pszDomain);
+    if( (pszDomain == NULL || EQUAL(pszDomain, "")) && pszName != NULL &&
+        EQUAL(pszName, "DESCRIPTION") )
+    {
+        SetMetadata( GetMetadata() );
+    }
+    return CE_None;
+}
+
+/************************************************************************/
+/*                      SetForcedDescription()                          */
+/************************************************************************/
+
+void OGRPGDumpLayer::SetForcedDescription( const char* pszDescriptionIn )
+{
+    osForcedDescription = pszDescriptionIn;
+    OGRLayer::SetMetadataItem("DESCRIPTION", osForcedDescription);
+
+    if( pszDescriptionIn[0] != '\0' )
+    {
+        CPLString osCommand;
+        osCommand.Printf( "COMMENT ON TABLE %s IS %s",
+                            pszSqlTableName,
+                            OGRPGDumpEscapeString(pszDescriptionIn).c_str() );
+        poDS->Log( osCommand );
+    }
+}
diff --git a/ogr/ogrsf_frmts/pgeo/drv_pgeo.html b/ogr/ogrsf_frmts/pgeo/drv_pgeo.html
index 3c85388..f4b391c 100644
--- a/ogr/ogrsf_frmts/pgeo/drv_pgeo.html
+++ b/ogr/ogrsf_frmts/pgeo/drv_pgeo.html
@@ -22,18 +22,18 @@
   <p>Personal Geodatabases are accessed by passing the file name of
   the .mdb file to be accessed as the data source name. On Windows,
   no ODBC DSN is required. On Linux, there are problems with DSN-less
-  connection due to incomplete or buggy implementation of this feature 
+  connection due to incomplete or buggy implementation of this feature
   in the <a href="http://mdbtools.sourceforge.net/">MDB Tools</a> package,
   So, it is required to configure Data Source Name (DSN) if the MDB
   Tools driver is used (check instructions below).</p>
-  
-  <p>In order to facilitate compatibility with different configurations, 
-  the PGEO_DRIVER_TEMPLATE Config Option was added to provide a way to 
-  programmatically set the DSN programmatically with the filename as 
+
+  <p>In order to facilitate compatibility with different configurations,
+  the PGEO_DRIVER_TEMPLATE Config Option was added to provide a way to
+  programmatically set the DSN programmatically with the filename as
   an argument.   In cases where the driver name is known, this allows for
   the construction of the DSN based on that information in a manner similar
   to the default (used for Windows access to the Microsoft Access Driver).</p>
-  
+
   <p>OGR treats all feature tables as layers. Most geometry types
   should be supported, including 3D data. Measures information will
   be discarded. Coordinate system information should be properly
@@ -44,9 +44,9 @@
   that may be added in the future.</p>
 
 <p>By default, SQL statements are passed directly to the MDB database engine.
-It's also possible to request the driver to handle SQL commands 
-with <a href="/ogr/ogr_sql.html">OGR SQL</a> engine, 
-by passing <strong>"OGRSQL"</strong> string to the ExecuteSQL() 
+It's also possible to request the driver to handle SQL commands
+with <a href="ogr_sql.html">OGR SQL</a> engine,
+by passing <strong>"OGRSQL"</strong> string to the ExecuteSQL()
 method, as name of the SQL dialect.</p>
 
   <h2>How to use PGeo driver with unixODBC and MDB Tools (on Unix and Linux)</h2>
diff --git a/ogr/ogrsf_frmts/pgeo/ogr_pgeo.h b/ogr/ogrsf_frmts/pgeo/ogr_pgeo.h
index f60c6ba..2dfa353 100644
--- a/ogr/ogrsf_frmts/pgeo/ogr_pgeo.h
+++ b/ogr/ogrsf_frmts/pgeo/ogr_pgeo.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_pgeo.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogr_pgeo.h 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for Personal Geodatabase driver.
@@ -28,8 +28,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_ODBC_H_INCLUDED
-#define _OGR_ODBC_H_INCLUDED
+#ifndef OGR_ODBC_H_INCLUDED
+#define OGR_ODBC_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "cpl_odbc.h"
@@ -40,7 +40,7 @@
 /************************************************************************/
 
 class OGRPGeoDataSource;
-    
+
 class OGRPGeoLayer : public OGRLayer
 {
   protected:
@@ -77,7 +77,7 @@ class OGRPGeoLayer : public OGRLayer
     virtual OGRFeature *GetNextFeature();
 
     virtual OGRFeature *GetFeature( GIntBig nFeatureId );
-    
+
     OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
 
     virtual int         TestCapability( const char * );
@@ -107,7 +107,7 @@ class OGRPGeoTableLayer : public OGRPGeoLayer
                         OGRPGeoTableLayer( OGRPGeoDataSource * );
                         ~OGRPGeoTableLayer();
 
-    CPLErr              Initialize( const char *pszTableName, 
+    CPLErr              Initialize( const char *pszTableName,
                                     const char *pszGeomCol,
                                     int nShapeType,
                                     double dfExtentLeft,
@@ -122,10 +122,12 @@ class OGRPGeoTableLayer : public OGRPGeoLayer
 
     virtual OGRErr      SetAttributeFilter( const char * );
     virtual OGRFeature *GetFeature( GIntBig nFeatureId );
-    
+
     virtual int         TestCapability( const char * );
 
     virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 };
 
 /************************************************************************/
@@ -142,7 +144,7 @@ class OGRPGeoSelectLayer : public OGRPGeoLayer
     virtual CPLODBCStatement *  GetStatement();
 
   public:
-                        OGRPGeoSelectLayer( OGRPGeoDataSource *, 
+                        OGRPGeoSelectLayer( OGRPGeoDataSource *,
                                            CPLODBCStatement * );
                         ~OGRPGeoSelectLayer();
 
@@ -150,7 +152,7 @@ class OGRPGeoSelectLayer : public OGRPGeoLayer
     virtual GIntBig     GetFeatureCount( int );
 
     virtual OGRFeature *GetFeature( GIntBig nFeatureId );
-    
+
     virtual int         TestCapability( const char * );
 };
 
@@ -162,7 +164,7 @@ class OGRPGeoDataSource : public OGRDataSource
 {
     OGRPGeoLayer        **papoLayers;
     int                 nLayers;
-    
+
     char               *pszName;
 
     int                 bDSUpdate;
@@ -173,7 +175,7 @@ class OGRPGeoDataSource : public OGRDataSource
                         ~OGRPGeoDataSource();
 
     int                 Open( const char *, int bUpdate, int bTestOpen );
-    int                 OpenTable( const char *pszTableName, 
+    int                 OpenTable( const char *pszTableName,
                                    const char *pszGeomCol,
                                    int bUpdate );
 
@@ -219,7 +221,7 @@ class OGRPGeoDriver : public OGRODBCMDBDriver
 {
   public:
                 ~OGRPGeoDriver();
-                
+
     const char  *GetName();
     OGRDataSource *Open( const char *, int );
 
diff --git a/ogr/ogrsf_frmts/pgeo/ogrpgeodatasource.cpp b/ogr/ogrsf_frmts/pgeo/ogrpgeodatasource.cpp
index 5d38f07..2d054f9 100644
--- a/ogr/ogrsf_frmts/pgeo/ogrpgeodatasource.cpp
+++ b/ogr/ogrsf_frmts/pgeo/ogrpgeodatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgeodatasource.cpp 28368 2015-01-27 14:25:17Z rouault $
+ * $Id: ogrpgeodatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGeoDataSource class.
@@ -33,19 +33,18 @@
 #include "cpl_string.h"
 #include <vector>
 
-CPL_CVSID("$Id: ogrpgeodatasource.cpp 28368 2015-01-27 14:25:17Z rouault $");
+CPL_CVSID("$Id: ogrpgeodatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                         OGRPGeoDataSource()                          */
 /************************************************************************/
 
-OGRPGeoDataSource::OGRPGeoDataSource()
-
-{
-    pszName = NULL;
-    papoLayers = NULL;
-    nLayers = 0;
-}
+OGRPGeoDataSource::OGRPGeoDataSource() :
+    papoLayers(NULL),
+    nLayers(0),
+    pszName(NULL),
+    bDSUpdate(FALSE)
+{ }
 
 /************************************************************************/
 /*                         ~OGRPGeoDataSource()                         */
@@ -54,13 +53,11 @@ OGRPGeoDataSource::OGRPGeoDataSource()
 OGRPGeoDataSource::~OGRPGeoDataSource()
 
 {
-    int         i;
-
     CPLFree( pszName );
 
-    for( i = 0; i < nLayers; i++ )
+    for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
-    
+
     CPLFree( papoLayers );
 }
 
@@ -112,7 +109,7 @@ int OGRPGeoDataSource::Open( const char * pszNewName, int bUpdate,
     char *pszDSN;
     const char* pszOptionName = "";
     const char* pszDSNStringTemplate = NULL;
-    if( EQUALN(pszNewName,"PGEO:",5) )
+    if( STARTS_WITH_CI(pszNewName, "PGEO:") )
         pszDSN = CPLStrdup( pszNewName + 5 );
     else
     {
@@ -120,7 +117,6 @@ int OGRPGeoDataSource::Open( const char * pszNewName, int bUpdate,
         pszDSNStringTemplate = CPLGetConfigOption( pszOptionName, NULL );
         if( pszDSNStringTemplate == NULL )
         {
-            pszOptionName = "";
             pszDSNStringTemplate = "DRIVER=Microsoft Access Driver (*.mdb);DBQ=%s";
         }
         if (!CheckDSNStringTemplate(pszDSNStringTemplate))
@@ -130,7 +126,10 @@ int OGRPGeoDataSource::Open( const char * pszNewName, int bUpdate,
             return FALSE;
         }
         pszDSN = (char *) CPLMalloc(strlen(pszNewName)+strlen(pszDSNStringTemplate)+100);
-        sprintf( pszDSN, pszDSNStringTemplate,  pszNewName );
+        /* coverity[tainted_string] */
+        snprintf( pszDSN,
+                  strlen(pszNewName)+strlen(pszDSNStringTemplate)+100,
+                  pszDSNStringTemplate,  pszNewName );
     }
 
 /* -------------------------------------------------------------------- */
@@ -141,13 +140,15 @@ int OGRPGeoDataSource::Open( const char * pszNewName, int bUpdate,
     if( !oSession.EstablishSession( pszDSN, NULL, NULL ) )
     {
         int bError = TRUE;
-        if( !EQUALN(pszNewName,"PGEO:",5) )
+        if( !STARTS_WITH_CI(pszNewName, "PGEO:") )
         {
             // Trying with another template (#5594)
             pszDSNStringTemplate = "DRIVER=Microsoft Access Driver (*.mdb, *.accdb);DBQ=%s";
             CPLFree( pszDSN );
             pszDSN = (char *) CPLMalloc(strlen(pszNewName)+strlen(pszDSNStringTemplate)+100);
-            sprintf( pszDSN, pszDSNStringTemplate,  pszNewName );
+            snprintf( pszDSN,
+                     strlen(pszNewName)+strlen(pszDSNStringTemplate)+100,
+                     pszDSNStringTemplate,  pszNewName );
             CPLDebug( "PGeo", "EstablishSession(%s)", pszDSN );
             if( oSession.EstablishSession( pszDSN, NULL, NULL ) )
             {
@@ -156,7 +157,7 @@ int OGRPGeoDataSource::Open( const char * pszNewName, int bUpdate,
         }
         if( bError )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                     "Unable to initialize ODBC connection to DSN for %s,\n"
                     "%s", pszDSN, oSession.GetLastError() );
             CPLFree( pszDSN );
@@ -167,7 +168,7 @@ int OGRPGeoDataSource::Open( const char * pszNewName, int bUpdate,
     CPLFree( pszDSN );
 
     pszName = CPLStrdup( pszNewName );
-    
+
     bDSUpdate = bUpdate;
 
 /* -------------------------------------------------------------------- */
@@ -176,28 +177,28 @@ int OGRPGeoDataSource::Open( const char * pszNewName, int bUpdate,
 /* -------------------------------------------------------------------- */
     std::vector<char **> apapszGeomColumns;
     CPLODBCStatement oStmt( &oSession );
-        
+
     oStmt.Append( "SELECT TableName, FieldName, ShapeType, ExtentLeft, ExtentRight, ExtentBottom, ExtentTop, SRID, HasZ FROM GDB_GeomColumns" );
 
     if( !oStmt.ExecuteSQL() )
     {
-        CPLDebug( "PGEO", 
-                  "SELECT on GDB_GeomColumns fails, perhaps not a personal geodatabase?\n%s", 
+        CPLDebug( "PGEO",
+                  "SELECT on GDB_GeomColumns fails, perhaps not a personal geodatabase?\n%s",
                   oSession.GetLastError() );
         return FALSE;
     }
 
     while( oStmt.Fetch() )
     {
-        int i, iNew = apapszGeomColumns.size();
+        int i, iNew = static_cast<int>(apapszGeomColumns.size());
         char **papszRecord = NULL;
         for( i = 0; i < 9; i++ )
-            papszRecord = CSLAddString( papszRecord, 
+            papszRecord = CSLAddString( papszRecord,
                                         oStmt.GetColData(i) );
         apapszGeomColumns.resize(iNew+1);
         apapszGeomColumns[iNew] = papszRecord;
     }
-            
+
 /* -------------------------------------------------------------------- */
 /*      Create a layer for each spatial table.                          */
 /* -------------------------------------------------------------------- */
@@ -231,7 +232,7 @@ int OGRPGeoDataSource::Open( const char * pszNewName, int bUpdate,
 
         CSLDestroy( papszRecord );
     }
-    
+
     return TRUE;
 }
 
@@ -271,8 +272,8 @@ OGRLayer * OGRPGeoDataSource::ExecuteSQL( const char *pszSQLCommand,
 /*      Use generic implementation for recognized dialects              */
 /* -------------------------------------------------------------------- */
     if( IsGenericSQLDialect(pszDialect) )
-        return OGRDataSource::ExecuteSQL( pszSQLCommand, 
-                                          poSpatialFilter, 
+        return OGRDataSource::ExecuteSQL( pszSQLCommand,
+                                          poSpatialFilter,
                                           pszDialect );
 
 /* -------------------------------------------------------------------- */
@@ -283,8 +284,9 @@ OGRLayer * OGRPGeoDataSource::ExecuteSQL( const char *pszSQLCommand,
     poStmt->Append( pszSQLCommand );
     if( !poStmt->ExecuteSQL() )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", oSession.GetLastError() );
+        delete poStmt;
         return NULL;
     }
 
@@ -303,12 +305,12 @@ OGRLayer * OGRPGeoDataSource::ExecuteSQL( const char *pszSQLCommand,
 /*      statement.                                                      */
 /* -------------------------------------------------------------------- */
     OGRPGeoSelectLayer *poLayer = NULL;
-        
+
     poLayer = new OGRPGeoSelectLayer( this, poStmt );
 
     if( poSpatialFilter != NULL )
         poLayer->SetSpatialFilter( poSpatialFilter );
-    
+
     return poLayer;
 }
 
diff --git a/ogr/ogrsf_frmts/pgeo/ogrpgeodriver.cpp b/ogr/ogrsf_frmts/pgeo/ogrpgeodriver.cpp
index 24ee679..9cdc983 100644
--- a/ogr/ogrsf_frmts/pgeo/ogrpgeodriver.cpp
+++ b/ogr/ogrsf_frmts/pgeo/ogrpgeodriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgeodriver.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogrpgeodriver.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements Personal Geodatabase driver.
@@ -31,7 +31,7 @@
 #include "ogr_pgeo.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrpgeodriver.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogrpgeodriver.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                            ~OGRODBCDriver()                            */
@@ -62,23 +62,24 @@ OGRDataSource *OGRPGeoDriver::Open( const char * pszFilename,
 {
     OGRPGeoDataSource     *poDS;
 
-    if( EQUALN(pszFilename, "WALK:", strlen("WALK:")) )
+    if( STARTS_WITH_CI(pszFilename, "WALK:") )
         return NULL;
 
-    if( EQUALN(pszFilename, "GEOMEDIA:", strlen("GEOMEDIA:")) )
+    if( STARTS_WITH_CI(pszFilename, "GEOMEDIA:") )
         return NULL;
 
-    if( !EQUALN(pszFilename,"PGEO:",5) 
+    if( !STARTS_WITH_CI(pszFilename, "PGEO:")
         && !EQUAL(CPLGetExtension(pszFilename),"mdb") )
         return NULL;
 
-    /* Disabling the attempt to guess if a MDB file is a PGeo database */
-    /* or not. The mention to GDB_GeomColumns might be quite far in the */
-    /* file, which can cause mis-detection. See http://trac.osgeo.org/gdal/ticket/4498 */
-    /* This was initially meant to know if a MDB should be opened by the PGeo or the */
-    /* Geomedia driver. */
+    // Disabling the attempt to guess if a MDB file is a PGeo database
+    // or not. The mention to GDB_GeomColumns might be quite far in
+    // the/ file, which can cause misdetection.  See
+    // http://trac.osgeo.org/gdal/ticket/4498 This was initially meant
+    // to know if a MDB should be opened by the PGeo or the Geomedia
+    // driver.
 #if 0
-    if( !EQUALN(pszFilename,"PGEO:",5) &&
+    if( !STARTS_WITH_CI(pszFilename, "PGEO:") &&
         EQUAL(CPLGetExtension(pszFilename),"mdb") )
     {
         VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
@@ -89,7 +90,9 @@ OGRDataSource *OGRPGeoDriver::Open( const char * pszFilename,
         VSIFCloseL(fp);
 
         /* Look for GDB_GeomColumns table */
-        const GByte pabyNeedle[] = { 'G', 0, 'D', 0, 'B', 0, '_', 0, 'G', 0, 'e', 0, 'o', 0, 'm', 0, 'C', 0, 'o', 0, 'l', 0, 'u', 0, 'm', 0, 'n', 0, 's' };
+        const GByte pabyNeedle[] = {
+            'G', 0, 'D', 0, 'B', 0, '_', 0, 'G', 0, 'e', 0, 'o', 0, 'm', 0,
+            'C', 0, 'o', 0, 'l', 0, 'u', 0, 'm', 0, 'n', 0, 's' };
         int bFound = FALSE;
         for(int i=0;i<100000 - (int)sizeof(pabyNeedle);i++)
         {
@@ -120,7 +123,7 @@ OGRDataSource *OGRPGeoDriver::Open( const char * pszFilename,
     //
     if ( !InstallMdbDriver() )
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "Unable to install MDB driver for ODBC, MDB access may not supported.\n" );
     }
     else
@@ -183,7 +186,7 @@ bool OGRODBCMDBDriver::InstallMdbDriver()
         // Create installer and register driver
         CPLODBCDriverInstaller dri;
 
-        if ( !dri.InstallDriver(driver.c_str(), 0, ODBC_INSTALL_COMPLETE) )
+        if ( !dri.InstallDriver(driver.c_str(), NULL, ODBC_INSTALL_COMPLETE) )
         {
             // Report ODBC error
             CPLError( CE_Failure, CPLE_AppDefined, "ODBC: %s", dri.GetLastError() );
@@ -206,7 +209,7 @@ bool OGRODBCMDBDriver::FindDriverLib()
         "libmdbodbc.so.0" /* for Ubuntu 8.04 support */
     };
     const int nLibNames = sizeof(aszDefaultLibName) / sizeof(aszDefaultLibName[0]);
-    const char* libPath[] = { 
+    const char* libPath[] = {
         "/usr/lib",
         "/usr/local/lib"
     };
@@ -222,12 +225,12 @@ bool OGRODBCMDBDriver::FindDriverLib()
 
         VSIStatBuf sStatBuf;
         if ( VSIStat( pszDrvCfg, &sStatBuf ) == 0
-             && VSI_ISDIR( sStatBuf.st_mode ) ) 
+             && VSI_ISDIR( sStatBuf.st_mode ) )
         {
             // Find default library in custom directory
             const char* pszDriverFile = CPLFormFilename( pszDrvCfg, aszDefaultLibName[0], NULL );
-            CPLAssert( 0 != pszDriverFile );
-        
+            CPLAssert( NULL != pszDriverFile );
+
             strLibPath = pszDriverFile;
         }
 
@@ -245,7 +248,7 @@ bool OGRODBCMDBDriver::FindDriverLib()
         for ( int j = 0; j < nLibNames; j++ )
         {
             const char* pszDriverFile = CPLFormFilename( libPath[i], aszDefaultLibName[j], NULL );
-            CPLAssert( 0 != pszDriverFile );
+            CPLAssert( NULL != pszDriverFile );
 
             if ( LibraryExists( pszDriverFile ) )
             {
@@ -267,7 +270,7 @@ bool OGRODBCMDBDriver::FindDriverLib()
 
 bool OGRODBCMDBDriver::LibraryExists(const char* pszLibPath)
 {
-    CPLAssert( 0 != pszLibPath );
+    CPLAssert( NULL != pszLibPath );
 
     VSIStatBuf stb;
 
@@ -295,10 +298,10 @@ void RegisterOGRPGeo()
 
 {
     OGRSFDriver* poDriver = new OGRPGeoDriver;
-    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                "ESRI Personal GeoDatabase" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "ESRI Personal GeoDatabase" );
     poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "mdb" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                "drv_pgeo.html" );
-    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver(poDriver);
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_pgeo.html" );
+
+    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/pgeo/ogrpgeolayer.cpp b/ogr/ogrsf_frmts/pgeo/ogrpgeolayer.cpp
index 6baedf8..eb9fe46 100644
--- a/ogr/ogrsf_frmts/pgeo/ogrpgeolayer.cpp
+++ b/ogr/ogrsf_frmts/pgeo/ogrpgeolayer.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: ogrpgeolayer.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrpgeolayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
- * Purpose:  Implements OGRPGeoLayer class, code shared between 
+ * Purpose:  Implements OGRPGeoLayer class, code shared between
  *           the direct table access, and the generic SQL results.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -34,7 +34,7 @@
 #include "cpl_string.h"
 #include "ogrpgeogeometry.h"
 
-CPL_CVSID("$Id: ogrpgeolayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrpgeolayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                            OGRPGeoLayer()                            */
@@ -53,7 +53,9 @@ OGRPGeoLayer::OGRPGeoLayer()
     iNextShapeId = 0;
 
     poSRS = NULL;
-    nSRSId = -2; // we haven't even queried the database for it yet. 
+    nSRSId = -2; // we haven't even queried the database for it yet.
+    poFeatureDefn = NULL;
+    panFieldOrdinals = NULL;
 }
 
 /************************************************************************/
@@ -66,7 +68,7 @@ OGRPGeoLayer::~OGRPGeoLayer()
     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     {
         CPLDebug( "PGeo", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
+                  (int) m_nFeaturesRead,
                   poFeatureDefn->GetName() );
     }
 
@@ -83,7 +85,7 @@ OGRPGeoLayer::~OGRPGeoLayer()
     }
 
     CPLFree( pszGeomColumn );
-    CPLFree( panFieldOrdinals ); 
+    CPLFree( panFieldOrdinals );
     CPLFree( pszFIDColumn );
 
     if( poSRS != NULL )
@@ -100,13 +102,13 @@ OGRPGeoLayer::~OGRPGeoLayer()
 /*      set on a statement.  Sift out geometry and FID fields.          */
 /************************************************************************/
 
-CPLErr OGRPGeoLayer::BuildFeatureDefn( const char *pszLayerName, 
-                                       CPLODBCStatement *poStmt )
+CPLErr OGRPGeoLayer::BuildFeatureDefn( const char *pszLayerName,
+                                       CPLODBCStatement *poStmtIn )
 
 {
     poFeatureDefn = new OGRFeatureDefn( pszLayerName );
     SetDescription( poFeatureDefn->GetName() );
-    int    nRawColumns = poStmt->GetColCount();
+    int    nRawColumns = poStmtIn->GetColCount();
 
     poFeatureDefn->Reference();
     poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
@@ -115,28 +117,28 @@ CPLErr OGRPGeoLayer::BuildFeatureDefn( const char *pszLayerName,
 
     for( int iCol = 0; iCol < nRawColumns; iCol++ )
     {
-        OGRFieldDefn    oField( poStmt->GetColName(iCol), OFTString );
+        OGRFieldDefn    oField( poStmtIn->GetColName(iCol), OFTString );
 
-        oField.SetWidth( MAX(0,poStmt->GetColSize( iCol )) );
+        oField.SetWidth( MAX(0,poStmtIn->GetColSize( iCol )) );
 
-        if( pszGeomColumn != NULL 
-            && EQUAL(poStmt->GetColName(iCol),pszGeomColumn) )
+        if( pszGeomColumn != NULL
+            && EQUAL(poStmtIn->GetColName(iCol),pszGeomColumn) )
             continue;
 
-        if( pszFIDColumn == NULL 
-            && EQUAL(poStmt->GetColName(iCol),"OBJECTID") )
+        if( pszFIDColumn == NULL
+            && EQUAL(poStmtIn->GetColName(iCol),"OBJECTID") )
         {
-            pszFIDColumn = CPLStrdup(poStmt->GetColName(iCol));
+            pszFIDColumn = CPLStrdup(poStmtIn->GetColName(iCol));
         }
 
-        if( pszGeomColumn == NULL 
-            && EQUAL(poStmt->GetColName(iCol),"Shape") )
+        if( pszGeomColumn == NULL
+            && EQUAL(poStmtIn->GetColName(iCol),"Shape") )
         {
-            pszGeomColumn = CPLStrdup(poStmt->GetColName(iCol));
+            pszGeomColumn = CPLStrdup(poStmtIn->GetColName(iCol));
             continue;
         }
-        
-        switch( poStmt->GetColType(iCol) )
+
+        switch( poStmtIn->GetColType(iCol) )
         {
           case SQL_INTEGER:
           case SQL_SMALLINT:
@@ -151,7 +153,7 @@ CPLErr OGRPGeoLayer::BuildFeatureDefn( const char *pszLayerName,
 
           case SQL_DECIMAL:
             oField.SetType( OFTReal );
-            oField.SetPrecision( poStmt->GetColPrecision(iCol) );
+            oField.SetPrecision( poStmtIn->GetColPrecision(iCol) );
             break;
 
           case SQL_FLOAT:
@@ -205,7 +207,7 @@ void OGRPGeoLayer::ResetReading()
 OGRFeature *OGRPGeoLayer::GetNextFeature()
 
 {
-    for( ; TRUE; )
+    while( true )
     {
         OGRFeature      *poFeature;
 
@@ -248,11 +250,10 @@ OGRFeature *OGRPGeoLayer::GetNextRawFeature()
 /* -------------------------------------------------------------------- */
 /*      Create a feature from the current result.                       */
 /* -------------------------------------------------------------------- */
-    int         iField;
     OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
 
     if( pszFIDColumn != NULL && poStmt->GetColId(pszFIDColumn) > -1 )
-        poFeature->SetFID( 
+        poFeature->SetFID(
             atoi(poStmt->GetColData(poStmt->GetColId(pszFIDColumn))) );
     else
         poFeature->SetFID( iNextShapeId );
@@ -263,7 +264,7 @@ OGRFeature *OGRPGeoLayer::GetNextRawFeature()
 /* -------------------------------------------------------------------- */
 /*      Set the fields.                                                 */
 /* -------------------------------------------------------------------- */
-    for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
+    for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     {
         int iSrcField = panFieldOrdinals[iField]-1;
         const char *pszValue = poStmt->GetColData( iSrcField );
@@ -271,7 +272,7 @@ OGRFeature *OGRPGeoLayer::GetNextRawFeature()
         if( pszValue == NULL )
             /* no value */;
         else if( poFeature->GetFieldDefnRef(iField)->GetType() == OFTBinary )
-            poFeature->SetField( iField, 
+            poFeature->SetField( iField,
                                  poStmt->GetColDataLength(iSrcField),
                                  (GByte *) pszValue );
         else
@@ -341,14 +342,14 @@ void OGRPGeoLayer::LookupSRID( int nSRID )
 /*      Fetch the corresponding WKT from the SpatialRef table.          */
 /* -------------------------------------------------------------------- */
     CPLODBCStatement oStmt( poDS->GetSession() );
-        
+
     oStmt.Appendf( "SELECT srtext FROM GDB_SpatialRefs WHERE srid = %d",
                   nSRID );
 
     if( !oStmt.ExecuteSQL() )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "'%s' failed.\n%s", 
+                  "'%s' failed.\n%s",
                   oStmt.GetCommand(),
                   poDS->GetSession()->GetLastError() );
         return;
@@ -357,7 +358,7 @@ void OGRPGeoLayer::LookupSRID( int nSRID )
     if( !oStmt.Fetch() )
     {
         CPLError( CE_Warning, CPLE_AppDefined,
-                  "SRID %d lookup failed.\n%s", 
+                  "SRID %d lookup failed.\n%s",
                   nSRID, poDS->GetSession()->GetLastError() );
         return;
     }
@@ -378,10 +379,10 @@ void OGRPGeoLayer::LookupSRID( int nSRID )
 /*      Turn it into an OGRSpatialReference.                            */
 /* -------------------------------------------------------------------- */
     poSRS = new OGRSpatialReference();
-    
+
     if( poSRS->importFromWkt( &pszSRText ) != OGRERR_NONE )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "importFromWKT() failed on SRS '%s'.",
                   pszSRText);
         delete poSRS;
@@ -389,7 +390,7 @@ void OGRPGeoLayer::LookupSRID( int nSRID )
     }
     else if( poSRS->morphFromESRI() != OGRERR_NONE )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "morphFromESRI() failed on SRS." );
         delete poSRS;
         poSRS = NULL;
@@ -402,7 +403,7 @@ void OGRPGeoLayer::LookupSRID( int nSRID )
 /*                            GetFIDColumn()                            */
 /************************************************************************/
 
-const char *OGRPGeoLayer::GetFIDColumn() 
+const char *OGRPGeoLayer::GetFIDColumn()
 
 {
     if( pszFIDColumn != NULL )
@@ -415,7 +416,7 @@ const char *OGRPGeoLayer::GetFIDColumn()
 /*                         GetGeometryColumn()                          */
 /************************************************************************/
 
-const char *OGRPGeoLayer::GetGeometryColumn() 
+const char *OGRPGeoLayer::GetGeometryColumn()
 
 {
     if( pszGeomColumn != NULL )
diff --git a/ogr/ogrsf_frmts/pgeo/ogrpgeoselectlayer.cpp b/ogr/ogrsf_frmts/pgeo/ogrpgeoselectlayer.cpp
index b104b18..db4defb 100644
--- a/ogr/ogrsf_frmts/pgeo/ogrpgeoselectlayer.cpp
+++ b/ogr/ogrsf_frmts/pgeo/ogrpgeoselectlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgeoselectlayer.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrpgeoselectlayer.cpp 32177 2015-12-14 07:25:30Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGeoSelectLayer class, layer access to the results
@@ -32,7 +32,7 @@
 #include "cpl_conv.h"
 #include "ogr_pgeo.h"
 
-CPL_CVSID("$Id: ogrpgeoselectlayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrpgeoselectlayer.cpp 32177 2015-12-14 07:25:30Z goatbar $");
 
 /************************************************************************/
 /*                          OGRPGeoSelectLayer()                        */
@@ -50,12 +50,12 @@ OGRPGeoSelectLayer::OGRPGeoSelectLayer( OGRPGeoDataSource *poDSIn,
 
     poStmt = poStmtIn;
     pszBaseStatement = CPLStrdup( poStmtIn->GetCommand() );
-    
+
     /* Just to make test_ogrsf happy, but would/could need be extended to */
     /* other cases */
-    if( EQUALN(pszBaseStatement, "SELECT * FROM ", strlen("SELECT * FROM ")) )
+    if( STARTS_WITH_CI(pszBaseStatement, "SELECT * FROM ") )
     {
-        
+
         OGRLayer* poBaseLayer =
             poDSIn->GetLayerByName(pszBaseStatement + strlen("SELECT * FROM "));
         if( poBaseLayer != NULL )
diff --git a/ogr/ogrsf_frmts/pgeo/ogrpgeotablelayer.cpp b/ogr/ogrsf_frmts/pgeo/ogrpgeotablelayer.cpp
index 200a2cd..2239479 100644
--- a/ogr/ogrsf_frmts/pgeo/ogrpgeotablelayer.cpp
+++ b/ogr/ogrsf_frmts/pgeo/ogrpgeotablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgeotablelayer.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrpgeotablelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGeoTableLayer class, access to an existing table.
@@ -32,7 +32,7 @@
 #include "ogr_pgeo.h"
 #include "ogrpgeogeometry.h"
 
-CPL_CVSID("$Id: ogrpgeotablelayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrpgeotablelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                          OGRPGeoTableLayer()                         */
@@ -65,9 +65,9 @@ OGRPGeoTableLayer::~OGRPGeoTableLayer()
 /*                             Initialize()                             */
 /************************************************************************/
 
-CPLErr OGRPGeoTableLayer::Initialize( const char *pszTableName, 
+CPLErr OGRPGeoTableLayer::Initialize( const char *pszTableName,
                                       const char *pszGeomCol,
-                                      int nShapeType, 
+                                      int nShapeType,
                                       double dfExtentLeft,
                                       double dfExtentRight,
                                       double dfExtentBottom,
@@ -75,10 +75,9 @@ CPLErr OGRPGeoTableLayer::Initialize( const char *pszTableName,
                                       int nSRID,
                                       int bHasZ )
 
-
 {
     CPLODBCSession *poSession = poDS->GetSession();
-    
+
     SetDescription( pszTableName );
 
     CPLFree( pszGeomColumn );
@@ -133,17 +132,18 @@ CPLErr OGRPGeoTableLayer::Initialize( const char *pszTableName,
 
     if( eOGRType != wkbUnknown && eOGRType != wkbNone && bHasZ )
         eOGRType = wkbSetZ(eOGRType);
+    CPL_IGNORE_RET_VAL(eOGRType);
 
 /* -------------------------------------------------------------------- */
 /*      Do we have a simple primary key?                                */
 /* -------------------------------------------------------------------- */
     CPLODBCStatement oGetKey( poSession );
-    
+
     if( oGetKey.GetPrimaryKeys( pszTableName ) && oGetKey.Fetch() )
     {
         pszFIDColumn = CPLStrdup(oGetKey.GetColData( 3 ));
-        
-        if( oGetKey.Fetch() ) // more than one field in key! 
+
+        if( oGetKey.Fetch() ) // more than one field in key!
         {
             CPLFree( pszFIDColumn );
             pszFIDColumn = NULL;
@@ -151,7 +151,7 @@ CPLErr OGRPGeoTableLayer::Initialize( const char *pszTableName,
                       pszTableName );
         }
         else
-            CPLDebug( "PGeo", 
+            CPLDebug( "PGeo",
                       "%s: Got primary key %s.",
                       pszTableName, pszFIDColumn );
     }
@@ -166,7 +166,7 @@ CPLErr OGRPGeoTableLayer::Initialize( const char *pszTableName,
 
     if( !oGetCol.GetColumns( pszTableName ) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "GetColumns() failed on %s.\n%s",
                   pszTableName, poSession->GetLastError() );
         return CE_Failure;
@@ -178,8 +178,8 @@ CPLErr OGRPGeoTableLayer::Initialize( const char *pszTableName,
 
     if( poFeatureDefn->GetFieldCount() == 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "No column definitions found for table '%s', layer not usable.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "No column definitions found for table '%s', layer not usable.",
                   pszTableName );
         return CE_Failure;
     }
@@ -299,19 +299,19 @@ OGRFeature *OGRPGeoTableLayer::GetFeature( GIntBig nFeatureId )
 /*                         SetAttributeFilter()                         */
 /************************************************************************/
 
-OGRErr OGRPGeoTableLayer::SetAttributeFilter( const char *pszQuery )
+OGRErr OGRPGeoTableLayer::SetAttributeFilter( const char *pszQueryIn )
 
 {
     CPLFree(m_pszAttrQueryString);
-    m_pszAttrQueryString = (pszQuery) ? CPLStrdup(pszQuery) : NULL;
+    m_pszAttrQueryString = (pszQueryIn) ? CPLStrdup(pszQueryIn) : NULL;
 
-    if( (pszQuery == NULL && this->pszQuery == NULL)
-        || (pszQuery != NULL && this->pszQuery != NULL 
-            && EQUAL(pszQuery,this->pszQuery)) )
+    if( (pszQueryIn == NULL && this->pszQuery == NULL)
+        || (pszQueryIn != NULL && this->pszQuery != NULL
+            && EQUAL(pszQueryIn,this->pszQuery)) )
         return OGRERR_NONE;
 
     CPLFree( this->pszQuery );
-    this->pszQuery = pszQuery ? CPLStrdup( pszQuery ) : NULL; 
+    this->pszQuery = pszQueryIn ? CPLStrdup( pszQueryIn ) : NULL;
 
     ClearStatement();
 
@@ -335,7 +335,7 @@ int OGRPGeoTableLayer::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCFastSpatialFilter) )
         return FALSE;
 
-    else 
+    else
         return OGRPGeoLayer::TestCapability( pszCap );
 }
 
@@ -363,7 +363,7 @@ GIntBig OGRPGeoTableLayer::GetFeatureCount( int bForce )
 
     if( !oStmt.ExecuteSQL() || !oStmt.Fetch() )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "GetFeatureCount() failed on query %s.\n%s",
                   oStmt.GetCommand(), poDS->GetSession()->GetLastError() );
         return OGRPGeoLayer::GetFeatureCount(bForce);
diff --git a/ogr/ogrsf_frmts/plscenes/GNUmakefile b/ogr/ogrsf_frmts/plscenes/GNUmakefile
index 9a88649..fc911e9 100644
--- a/ogr/ogrsf_frmts/plscenes/GNUmakefile
+++ b/ogr/ogrsf_frmts/plscenes/GNUmakefile
@@ -2,7 +2,7 @@
 
 include ../../../GDALmake.opt
 
-OBJ	=	ogrplscenesdataset.o ogrplsceneslayer.o
+OBJ	=	ogrplscenesdriver.o ogrplscenesdataset.o ogrplscenesv1dataset.o ogrplsceneslayer.o ogrplscenesv1layer.o
 
 CPPFLAGS	:=	$(JSON_INCLUDE) -I.. -I../.. -I../geojson  $(CPPFLAGS)
 
diff --git a/ogr/ogrsf_frmts/plscenes/drv_plscenes.html b/ogr/ogrsf_frmts/plscenes/drv_plscenes.html
index 813f906..df570af 100644
--- a/ogr/ogrsf_frmts/plscenes/drv_plscenes.html
+++ b/ogr/ogrsf_frmts/plscenes/drv_plscenes.html
@@ -1,20 +1,20 @@
 <html>
 <head>
-<title>PLScenes (Planet Labs Scenes API)</title>
+<title>PLScenes (Planet Labs Scenes/Catalog API)</title>
 </head>
 
 <body bgcolor="#ffffff">
 
-<h1>PLScenes (Planet Labs Scenes API)</h1>
+<h1>PLScenes (Planet Labs Scenes/Catalog API)</h1>
 
-(GDAL/OGR >= 2.0)<p>
+(GDAL/OGR >= 2.0 for v0 API, and GDAL/OGR >= 2.1 for v1 API)<p>
 
-This driver can connect to Planet Labs Scenes API.
+This driver can connect to Planet Labs Scenes v0/Catalog v1 API.
 GDAL/OGR must be built with Curl support in order for the
 PLScenes driver to be compiled.<p>
 
 The driver supports read-only operations to list scenes and their metadata
-as a vector layer per scene type ("ortho" for example). It can also access raster scenes.<p>
+as a vector layer per scene type/catalog ("ortho" for example). It can also access raster scenes.<p>
 
 <h2>Dataset name syntax</h2>
 
@@ -24,12 +24,18 @@ Additionnal optional parameters can be specified after the ':' sign.
 Currently the following one is supported :<p>
 
 <ul>
+<li> <b>version</b>=v0/v1: To specify the API version to request. Defaults to v0.</li>
 <li> <b>api_key</b>=value: To specify the Planet API KEY. It is mandatory, unless
 it is supplied through the open option API_KEY, or the configuration option PL_API_KEY.</li>
 <li> <b>scene</b>=scene_id: To specify the scene ID, when accessing raster data.
 Optional for vector layer access.</li>
+<li> <b>catalog</b>=name: To specify the catalog name.
+Optional for vector layer access. Mandatory for raster access with v1 API.</li>
 <li> <b>product_type</b>=value: To specify the product type: 'visual', 'analytic' or 'thumb'
-(for raster fetching). Default is "visual". Optional for vector layer access.</li>
+(for raster fetching). Default is "visual". Optional for vector layer access. For V1 API,
+if the option is not specified and the 'visual' asset category does not exist for the scene
+(or if the value is set to 'list'), the returned dataset will have subdatasets
+for the available asset categories.</li>
 </ul>
 
 If several parameters are specified, they must be separated by a comma.<p>
@@ -38,11 +44,17 @@ If several parameters are specified, they must be separated by a comma.<p>
 
 The following open options are available :
 <ul>
+<li><b>VERSION</b>=v0/v1: To specify the API version to request. Defaults to v0.</li>
 <li><b>API_KEY</b>=value: To specify the Planet API KEY.</li>
 <li><b>SCENE</b>=scene_id: To specify the scene ID, when accessing raster data.
 Optional for vector layer access.</li>
-<li><b>PRODUCT_TYPE</b>=value: To specify the product type: 'visual', 'analytic' or 'thumb
-(for raster fetching). Default is "visual". Optional for vector layer access.</li>
+<li><b>PRODUCT_TYPE</b>=value:: To specify the product type: 'visual', 'analytic' or 'thumb'
+(for raster fetching). Default is "visual". Optional for vector layer access. For V1 API,
+if the option is not specified and the 'visual' asset category does not exist for the scene
+(or if the value is set to 'list'), the returned dataset will have subdatasets
+for the available asset categories.</li>
+<li> <b>CATALOG</b>=name: To specify the catalog name.
+Optional for vector layer access. Mandatory for raster access with v1 API.</li>
 <li><b>RANDOM_ACCESS</b>=YES/NO: Whether raster should be accessed in random access mode
 (but with potentially not optimal throughput). If NO, in-memory ingestion is done.
 Default is YES.</li>
@@ -57,6 +69,8 @@ The following configuration options are available :
 
 <h2>Attributes</h2>
 
+<h3>v0 API</h3>
+
 The <a href="https://www.planet.com/docs/v0/scenes/#metadata">scene metadata</a>
 are retrieved into the following feature fields for the "ortho" layer :<p>
 
@@ -94,6 +108,184 @@ are retrieved into the following feature fields for the "ortho" layer :<p>
 
 For other layers / scene types, additional attributes may be retrieved.<p>
 
+<h3>v1 API</h3>
+
+<p>For the v1 API, the layer field definition is built dynamically from the catalog
+specification. The links to downloadable products are
+in <i>asset_XXXXX_file</i> attributes where XXXXX is the asset category id.</p>
+
+<p>The details about the layer field description are given in the FIELDS_DESCRIPTION
+metadata item as a JSon serialized object. The keys are the OGR field names, and
+the value is an object that contains the definition of each field, with the following
+attributes :
+<ul>
+<li><i>description</i>: string with human readable description of the filed</li>
+<li><i>type</i>: e.g: string, number or integer</li>
+<li><i>format</i> (optional): e.g. date-time, float, int32, ...</li>
+<li><i>server_queryable</i>: true if filters on the property are forwarded to the server.
+Otherwise the filter is evaluated on client side.</li>
+<li><i>src_field</i>: path to the property from the root of the JSon Feature object.</li>
+</ul>
+For example:</p>
+<pre>
+{
+  "id":{
+    "description":"Identifier of this Item.",
+    "type":"string",
+    "src_field":"id",
+    "server_queryable":true
+  },
+  "self_link":{
+    "description":"RFC 3986 URI representing the canonical location of this object.",
+    "type":"string",
+    "src_field":"_links._self",
+    "server_queryable":false
+  },
+  "assets_link":{
+    "description":"RFC 3986 URI representing the canonical location of the ItemAssets subcollection.",
+    "type":"string",
+    "src_field":"_links.assets",
+    "server_queryable":false
+  },
+  "acquired":{
+    "description":"The RFC 3339 acquisition time of underlying image.",
+    "format":"date-time",
+    "type":"string",
+    "src_field":"properties.acquired",
+    "server_queryable":true
+  },
+  "created":{
+    "description":"The RFC 3339 timestamp at which this Item was added to the Catalog.",
+    "format":"date-time",
+    "type":"string",
+    "src_field":"properties.created",
+    "server_queryable":true
+  },
+  "black_fill":{
+    "description":"Ratio of image containing artificial black fill due to clipping to actual data.",
+    "format":"float",
+    "maximum":1.000000,
+    "minimum":0.000000,
+    "type":"number",
+    "src_field":"properties.catalog::black_fill",
+    "server_queryable":true
+  },
+  "cloud_cover":{
+    "description":"Ratio of the image covered by clouds to that which is uncovered.",
+    "format":"float",
+    "maximum":1.000000,
+    "minimum":0.000000,
+    "type":"number",
+    "src_field":"properties.catalog::cloud_cover",
+    "server_queryable":true
+  },
+  "grid_cell":{
+    "description":"The grid cell identifier of the gridded Item.",
+    "type":"string",
+    "src_field":"properties.catalog::grid_cell",
+    "server_queryable":true
+  },
+  "provider":{
+    "description":"Name of the imagery provider.",
+    "enum":[
+      "planetscope",
+      "rapideye",
+      "landsat",
+      "sentinel"
+    ],
+    "type":"string",
+    "src_field":"properties.catalog::provider",
+    "server_queryable":true
+  },
+  "resolution":{
+    "description":"Pixel resolution of the Item image(s) in meters.",
+    "format":"float",
+    "minimum":0.000000,
+    "type":"number",
+    "src_field":"properties.catalog::resolution",
+    "server_queryable":true
+  },
+  "satellite_id":{
+    "description":"Globally unique identifier of the satellite that acquired the underlying image.",
+    "type":"string",
+    "src_field":"properties.catalog::satellite_id",
+    "server_queryable":true
+  },
+  "sun_azimuth":{
+    "description":"Angle from the True North to the Sun Vector projected on the horizontal plane in degrees.",
+    "format":"float",
+    "maximum":360.000000,
+    "minimum":0.000000,
+    "type":"number",
+    "src_field":"properties.catalog::sun_azimuth",
+    "server_queryable":true
+  },
+  "sun_elevation":{
+    "description":"Elevation angle of the sun in degrees.",
+    "format":"float",
+    "maximum":90.000000,
+    "minimum":0.000000,
+    "type":"number",
+    "src_field":"properties.catalog::sun_elevation",
+    "server_queryable":true
+  },
+  "usable_data":{
+    "description":"Ratio of the usable to unusable portion of the image due to cloud cover or black fill.",
+    "format":"float",
+    "maximum":1.000000,
+    "minimum":0.000000,
+    "type":"number",
+    "src_field":"properties.catalog::usable_data",
+    "server_queryable":true
+  },
+  "view_angle":{
+    "description":"Spacecraft across-track off-nadir viewing angle used for imaging, in degrees with \"+\" being East and \"-\" being West.",
+    "format":"float",
+    "maximum":25.000000,
+    "minimum":-25.000000,
+    "type":"number",
+    "src_field":"properties.catalog::view_angle",
+    "server_queryable":true
+  },
+  "asset_analytic_self_link":{
+    "description":"RFC 3986 URI representing the canonical location of this asset.",
+    "type":"string",
+    "src_field":"_embeds.assets.analytic._links._self",
+    "server_queryable":false
+  },
+  "asset_analytic_file":{
+    "description":"RFC 3986 URI representing a location that will either directly serve the underlying asset data, or redirect to a location that will. A client must never attempt to construct this URI, as only its behavior is governed by this specification, not its location. In the event that a 202 is returned from a GET request against this URI, the response's `X-Retry-After` header indicates how long the client should wait before reattempting the request.",
+    "type":"string",
+    "src_field":"_embeds.assets.analytic.file",
+    "server_queryable":false
+  },
+  "asset_analytic_mimetype":{
+    "description":"The MIME type of the underlying asset file.",
+    "type":"string",
+    "src_field":"_embeds.assets.analytic.mimetype",
+    "server_queryable":false
+  },
+  "asset_visual_self_link":{
+    "description":"RFC 3986 URI representing the canonical location of this asset.",
+    "type":"string",
+    "src_field":"_embeds.assets.visual._links._self",
+    "server_queryable":false
+  },
+  "asset_visual_file":{
+    "description":"RFC 3986 URI representing a location that will either directly serve the underlying asset data, or redirect to a location that will. A client must never attempt to construct this URI, as only its behavior is governed by this specification, not its location. In the event that a 202 is returned from a GET request against this URI, the response's `X-Retry-After` header indicates how long the client should wait before reattempting the request.",
+    "type":"string",
+    "src_field":"_embeds.assets.visual.file",
+    "server_queryable":false
+  },
+  "asset_visual_mimetype":{
+    "description":"The MIME type of the underlying asset file.",
+    "type":"string",
+    "src_field":"_embeds.assets.visual.mimetype",
+    "server_queryable":false
+  }
+}
+</pre>
+
 <h3>Geometry</h3>
 
 The footprint of each scene is reported as a MultiPolygon with a longitude/latitude
@@ -145,7 +337,7 @@ ogrinfo -ro -al "PLScenes:" -oo API_KEY=some_value -spat -100,40,-99,39
 <p>
 
 <li>
-Listing all scenes available matching critera :
+Listing all scenes available matching criteria :
 <pre>
 ogrinfo -ro -al "PLScenes:" -oo API_KEY=some_value -where "acquired >= '2015/03/26 00:00:00' AND \"cloud_cover.estimated\" < 10"
 </pre>
@@ -157,12 +349,16 @@ ogrinfo -ro -al "PLScenes:" -oo API_KEY=some_value -where "acquired >= '2015/03/
 that the scene ID is specified with the 'scene' parameter / SCENE open option.
 The product type (visual, analytic or thumb) can be specified with the
 'product_type' parameter / PRODUCT_TYPE open option. The scene id is the
-content of the value of the 'id' field of the features of the 'ortho' vector layer </p>
+content of the value of the 'id' field of the features of the 'ortho' vector layer.</p>
 
-<p>This functionality is a conveniency wrapper of the
+<p>This functionality is a convenience wrapper of the
 <a href="https://www.planet.com/docs/v0/scenes/#get-scene-full">API for fetching the scene GeoTIFF</a>
 </p>
 
+<p>For API v1, the CATALOG open option must be specified. If the product is not
+already cached on the server, it will be asynchronously generated and the open
+attempt will return an error. Further retries will be needed.</p>
+
 <h3>Raster access examples</h3>
 
 <li>
@@ -187,7 +383,7 @@ gdal_translate "PLScenes:" -oo API_KEY=some_value -oo SCENE=scene_id \
 <h2>See Also</h2>
 
 <ul>
-<li> <a href="https://www.planet.com/docs/v0/scenes/">Documentation of Planet Scenes API</a><p>
+<li> <a href="https://www.planet.com/docs/v0/scenes/">Documentation of Planet Scenes API v0</a><p>
 <li> <a href="https://www.planet.com/docs/v0/general-concepts/#authentication">API Authentication</a><p>
 <li> <a href="frmt_plmosaic.html">Raster PLMosaic / Planet Mosaics API driver</a><p>
 </ul>
diff --git a/ogr/ogrsf_frmts/plscenes/makefile.vc b/ogr/ogrsf_frmts/plscenes/makefile.vc
index 2840008..41a9cd4 100644
--- a/ogr/ogrsf_frmts/plscenes/makefile.vc
+++ b/ogr/ogrsf_frmts/plscenes/makefile.vc
@@ -1,5 +1,5 @@
 
-OBJ	=	ogrplscenesdataset.obj ogrplsceneslayer.obj
+OBJ	=	ogrplscenesdriver.obj ogrplscenesdataset.obj ogrplscenesv1dataset.obj ogrplsceneslayer.obj ogrplscenesv1layer.obj
 EXTRAFLAGS =	-I.. -I..\..  -I..\geojson -I..\geojson\libjson
 
 GDAL_ROOT	=	..\..\..
diff --git a/ogr/ogrsf_frmts/plscenes/ogr_plscenes.h b/ogr/ogrsf_frmts/plscenes/ogr_plscenes.h
index a5b6d77..12017c2 100644
--- a/ogr/ogrsf_frmts/plscenes/ogr_plscenes.h
+++ b/ogr/ogrsf_frmts/plscenes/ogr_plscenes.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_plscenes.h 29164 2015-05-06 15:01:37Z rouault $
+ * $Id: ogr_plscenes.h 33602 2016-02-29 20:20:12Z rouault $
  *
  * Project:  PlanetLabs scene driver
  * Purpose:  PLScenes driver interface
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_PLSCENES_H_INCLUDED
-#define _OGR_PLSCENES_H_INCLUDED
+#ifndef OGR_PLSCENES_H_INCLUDED
+#define OGR_PLSCENES_H_INCLUDED
 
 #include "gdal_priv.h"
 #include "ogrsf_frmts.h"
@@ -39,18 +39,20 @@
 #include "ogrgeojsonreader.h"
 #include "swq.h"
 #include <map>
+#include <set>
+#include <vector>
 
 class OGRPLScenesLayer;
 class OGRPLScenesDataset: public GDALDataset
 {
-        int             bMustCleanPersistant;
+        int             bMustCleanPersistent;
         CPLString       osBaseURL;
         CPLString       osAPIKey;
-        
+
         int             nLayers;
         OGRPLScenesLayer  **papoLayers;
         std::map<OGRLayer*, OGRPLScenesLayer*> oMapResultSetToSourceLayer;
-        
+
         char             **GetBaseHTTPOptions();
         GDALDataset       *OpenRasterScene(GDALOpenInfo* poOpenInfo,
                                            CPLString osScene,
@@ -71,7 +73,6 @@ class OGRPLScenesDataset: public GDALDataset
         json_object        *RunRequest(const char* pszURL,
                                        int bQuiet404Error = FALSE);
 
-        static int          Identify(GDALOpenInfo* poOpenInfo);
         static GDALDataset* Open(GDALOpenInfo* poOpenInfo);
 };
 
@@ -89,16 +90,16 @@ class OGRPLScenesLayer: public OGRLayer
             CPLString       osNextURL;
             CPLString       osRequestURL;
             CPLString       osQuery;
-            
+
             OGRGeoJSONDataSource *poGeoJSONDS;
             OGRLayer             *poGeoJSONLayer;
-            
+
             OGRGeometry    *poMainFilter;
-            
+
             int             nPageSize;
             int             bStillInFirstPage;
             int             bAcquiredAscending;
-            
+
             int             bFilterMustBeClientSideEvaluated;
             CPLString       osFilterURLPart;
 
@@ -121,15 +122,157 @@ class OGRPLScenesLayer: public OGRLayer
         virtual OGRFeatureDefn *GetLayerDefn() { return poFeatureDefn; }
 
         virtual void        SetSpatialFilter( OGRGeometry *poGeom );
+        virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+                { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
+
         virtual OGRErr      SetAttributeFilter( const char * );
-        
+
         virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce );
-        
+        virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
+
         void                SetMainFilterRect(double dfMinX, double dfMinY,
                                               double dfMaxX, double dfMaxY);
         void                SetAcquiredOrderingFlag(int bAcquiredAscendingIn)
                                 { bAcquiredAscending = bAcquiredAscendingIn; }
 };
 
-#endif /* ndef _OGR_PLSCENES_H_INCLUDED */
+class OGRPLScenesV1Layer;
+class OGRPLScenesV1Dataset: public GDALDataset
+{
+        bool            m_bLayerListInitialized;
+        bool            m_bMustCleanPersistent;
+        CPLString       m_osBaseURL;
+        CPLString       m_osAPIKey;
+        CPLString       m_osNextCatalogPageURL;
+
+        int                   m_nLayers;
+        OGRPLScenesV1Layer  **m_papoLayers;
+
+        char              **GetBaseHTTPOptions();
+        OGRLayer           *ParseCatalog(json_object* poCatalog);
+        bool                ParseCatalogsPage(json_object* poObj,
+                                              CPLString& osNext);
+        void                EstablishLayerList();
+        GDALDataset       *OpenRasterScene(GDALOpenInfo* poOpenInfo,
+                                           CPLString osScene,
+                                           char** papszOptions);
+
+    public:
+                            OGRPLScenesV1Dataset();
+                           ~OGRPLScenesV1Dataset();
+
+        virtual int         GetLayerCount();
+        virtual OGRLayer   *GetLayer(int idx);
+        virtual OGRLayer   *GetLayerByName(const char* pszName);
+
+        json_object        *RunRequest(const char* pszURL,
+                                       int bQuiet404Error = FALSE);
+
+        static GDALDataset* Open(GDALOpenInfo* poOpenInfo);
+};
+
+class OGRPLScenesV1FeatureDefn: public OGRFeatureDefn
+{
+            OGRPLScenesV1Layer* m_poLayer;
+
+    public:
+        OGRPLScenesV1FeatureDefn(OGRPLScenesV1Layer* poLayer,
+                                 const char* pszName):
+                            OGRFeatureDefn(pszName), m_poLayer(poLayer) {}
+       ~OGRPLScenesV1FeatureDefn() {}
+
+       virtual int GetFieldCount();
+
+       void DropRefToLayer() { m_poLayer = NULL; }
+};
+
+struct OGRPLScenesV1LayerExprComparator;
+
+class OGRPLScenesV1Layer: public OGRLayer
+{
+            friend class OGRPLScenesV1Dataset;
+            friend class OGRPLScenesV1FeatureDefn;
+            friend struct OGRPLScenesV1LayerExprComparator;
+
+            OGRPLScenesV1Dataset* m_poDS;
+            bool                  m_bFeatureDefnEstablished;
+            OGRPLScenesV1FeatureDefn* m_poFeatureDefn;
+            OGRSpatialReference*  m_poSRS;
+            CPLString             m_osSpecURL;
+            CPLString             m_osItemsURL;
+            GIntBig               m_nTotalFeatures;
+            std::vector<CPLString> m_aoAssetCategories;
+            std::map<CPLString, int> m_oMapPrefixedJSonFieldNameToFieldIdx;
+            std::map<int,CPLString>  m_oMapFieldIdxToQueriableJSonFieldName;
+            std::set<CPLString>   m_oSetQueriable;
+
+            GIntBig               m_nNextFID;
+            bool                  m_bEOF;
+            bool                  m_bStillInFirstPage;
+            CPLString             m_osNextURL;
+            CPLString             m_osRequestURL;
+            int                   m_nPageSize;
+
+            json_object          *m_poPageObj;
+            json_object          *m_poFeatures;
+            int                   m_nFeatureIdx;
+
+            CPLString             m_osFilterURLPart;
+            bool                  m_bFilterMustBeClientSideEvaluated;
+
+            OGRFeature           *GetNextRawFeature();
+            void                  SetFieldFromPrefixedJSonFieldName(
+                                        OGRFeature* poFeature,
+                                        const CPLString& osPrefixedJSonFieldName,
+                                        json_object* poVal );
+            void                  EstablishLayerDefn();
+            void                  RegisterField(OGRFieldDefn* poFieldDefn,
+                                                const char* pszQueriableJSonName,
+                                                const char* pszPrefixedJSonName);
+            static json_object*   ResolveRefIfNecessary(json_object* poObj,
+                                                       json_object* poMain);
+            void                  ParseProperties(json_object* poProperties,
+                                                  json_object* poSpec,
+                                                  CPLString& osPropertiesDesc,
+                                                  const char* pszCategory);
+            void                  ParseEmbeds(json_object* poProperties,
+                                              json_object* poSpec,
+                                              CPLString& osPropertiesDesc);
+            bool                  GetNextPage();
+            CPLString             BuildRequestURL(bool bForHits);
+            CPLString             BuildFilter(swq_expr_node* poNode);
+            bool                  IsSimpleComparison(const swq_expr_node* poNode);
+            void                  FlattendAndOperands(swq_expr_node* poNode,
+                                                      std::vector<swq_expr_node*>& oVector);
+    public:
+                            OGRPLScenesV1Layer(OGRPLScenesV1Dataset* poDS,
+                                               const char* pszName,
+                                               const char* pszSpecURL,
+                                               const char* pszItemsURL,
+                                               GIntBig nCount,
+                                               std::vector<CPLString> aoAssetCategories);
+                           ~OGRPLScenesV1Layer();
+
+        virtual void            ResetReading();
+        virtual OGRFeature     *GetNextFeature();
+        virtual int             TestCapability(const char*);
+        virtual OGRFeatureDefn *GetLayerDefn();
+        virtual GIntBig         GetFeatureCount(int bForce = FALSE);
+
+        virtual char      **GetMetadata( const char * pszDomain = "" );
+        virtual const char *GetMetadataItem( const char * pszName, const char* pszDomain = "" );
+
+        virtual void        SetSpatialFilter( OGRGeometry *poGeom );
+        virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+                { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
+
+        virtual OGRErr      SetAttributeFilter( const char * );
+
+        virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce );
+        virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
+
+};
 
+#endif /* ndef OGR_PLSCENES_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/plscenes/ogrplscenesdataset.cpp b/ogr/ogrsf_frmts/plscenes/ogrplscenesdataset.cpp
index 930d352..776bc1b 100644
--- a/ogr/ogrsf_frmts/plscenes/ogrplscenesdataset.cpp
+++ b/ogr/ogrsf_frmts/plscenes/ogrplscenesdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrplscenesdataset.cpp 29164 2015-05-06 15:01:37Z rouault $
+ * $Id: ogrplscenesdataset.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  PlanetLabs scene driver
  * Purpose:  Implements OGRPLScenesDataset
@@ -29,11 +29,7 @@
 
 #include "ogr_plscenes.h"
 
-// g++ -g -Wall -fPIC -shared -o ogr_PLSCENES.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/plscene ogr/ogrsf_frmts/plscenes/*.c* -L. -lgdal -Iogr/ogrsf_frmts/geojson -Iogr/ogrsf_frmts/geojson/libjson 
-
-CPL_CVSID("$Id: ogrplscenesdataset.cpp 29164 2015-05-06 15:01:37Z rouault $");
-
-extern "C" void RegisterOGRPLSCENES();
+CPL_CVSID("$Id: ogrplscenesdataset.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                         OGRPLScenesDataset()                         */
@@ -41,7 +37,7 @@ extern "C" void RegisterOGRPLSCENES();
 
 OGRPLScenesDataset::OGRPLScenesDataset()
 {
-    bMustCleanPersistant = FALSE;
+    bMustCleanPersistent = FALSE;
     nLayers = 0;
     papoLayers = NULL;
 }
@@ -56,11 +52,11 @@ OGRPLScenesDataset::~OGRPLScenesDataset()
         delete papoLayers[i];
     CPLFree(papoLayers);
 
-    if (bMustCleanPersistant)
+    if (bMustCleanPersistent)
     {
         char** papszOptions = NULL;
         papszOptions = CSLSetNameValue(papszOptions, "CLOSE_PERSISTENT", CPLSPrintf("PLSCENES:%p", this));
-        CPLHTTPFetch( osBaseURL, papszOptions);
+        CPLHTTPDestroyResult(CPLHTTPFetch(osBaseURL, papszOptions));
         CSLDestroy(papszOptions);
     }
 }
@@ -112,7 +108,7 @@ OGRLayer* OGRPLScenesDataset::ExecuteSQL( const char *pszSQLCommand,
                                           OGRGeometry *poSpatialFilter,
                                           const char *pszDialect )
 {
-    if( EQUALN(pszSQLCommand, "SELECT ", strlen("SELECT ")) )
+    if( STARTS_WITH_CI(pszSQLCommand, "SELECT ") )
     {
         swq_select oSelect;
         CPLString osSQLCommand(pszSQLCommand);
@@ -121,9 +117,9 @@ OGRLayer* OGRPLScenesDataset::ExecuteSQL( const char *pszSQLCommand,
             osSQLCommand.resize(nLimitPos);
 
         CPLPushErrorHandler(CPLQuietErrorHandler);
-        OGRErr eErr = oSelect.preparse(osSQLCommand);
+        CPLErr eErr = oSelect.preparse(osSQLCommand);
         CPLPopErrorHandler();
-        if( eErr != OGRERR_NONE )
+        if( eErr != CE_None )
             return GDALDataset::ExecuteSQL(pszSQLCommand, poSpatialFilter, pszDialect);
 
 /* -------------------------------------------------------------------- */
@@ -178,21 +174,12 @@ void OGRPLScenesDataset::ReleaseResultSet( OGRLayer * poResultsSet )
 }
 
 /************************************************************************/
-/*                             Identify()                               */
-/************************************************************************/
-
-int OGRPLScenesDataset::Identify(GDALOpenInfo* poOpenInfo)
-{
-    return EQUALN(poOpenInfo->pszFilename, "PLSCENES:", strlen("PLSCENES:"));
-}
-
-/************************************************************************/
 /*                          GetBaseHTTPOptions()                         */
 /************************************************************************/
 
 char** OGRPLScenesDataset::GetBaseHTTPOptions()
 {
-    bMustCleanPersistant = TRUE;
+    bMustCleanPersistent = TRUE;
 
     char** papszOptions = NULL;
     papszOptions = CSLAddString(papszOptions, CPLSPrintf("PERSISTENT=PLSCENES:%p", this));
@@ -209,19 +196,20 @@ json_object* OGRPLScenesDataset::RunRequest(const char* pszURL,
 {
     char** papszOptions = CSLAddString(GetBaseHTTPOptions(), NULL);
     CPLHTTPResult * psResult;
-    if( strncmp(osBaseURL, "/vsimem/", strlen("/vsimem/")) == 0 &&
-        strncmp(pszURL, "/vsimem/", strlen("/vsimem/")) == 0 )
+    if( STARTS_WITH(osBaseURL, "/vsimem/") &&
+        STARTS_WITH(pszURL, "/vsimem/") )
     {
         CPLDebug("PLSCENES", "Fetching %s", pszURL);
         psResult = (CPLHTTPResult*) CPLCalloc(1, sizeof(CPLHTTPResult));
-        vsi_l_offset nDataLength = 0;
+        vsi_l_offset nDataLengthLarge = 0;
         CPLString osURL(pszURL);
         if( osURL[osURL.size()-1 ] == '/' )
             osURL.resize(osURL.size()-1);
-        GByte* pabyBuf = VSIGetMemFileBuffer(osURL, &nDataLength, FALSE); 
+        GByte* pabyBuf = VSIGetMemFileBuffer(osURL, &nDataLengthLarge, FALSE);
+        size_t nDataLength = static_cast<size_t>(nDataLengthLarge);
         if( pabyBuf )
         {
-            psResult->pabyData = (GByte*) VSIMalloc(1 + nDataLength);
+            psResult->pabyData = (GByte*) VSI_MALLOC_VERBOSE(1 + nDataLength);
             if( psResult->pabyData )
             {
                 memcpy(psResult->pabyData, pabyBuf, nDataLength);
@@ -243,7 +231,7 @@ json_object* OGRPLScenesDataset::RunRequest(const char* pszURL,
             CPLPopErrorHandler();
     }
     CSLDestroy(papszOptions);
-    
+
     if( psResult->pszErrBuf != NULL )
     {
         if( !(bQuiet404Error && strstr(psResult->pszErrBuf, "404")) )
@@ -255,7 +243,7 @@ json_object* OGRPLScenesDataset::RunRequest(const char* pszURL,
         CPLHTTPDestroyResult(psResult);
         return NULL;
     }
-    
+
     if( psResult->pabyData == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Empty content returned by server");
@@ -287,7 +275,7 @@ json_object* OGRPLScenesDataset::RunRequest(const char* pszURL,
         json_object_put(poObj);
         poObj = NULL;
     }
-    
+
     return poObj;
 }
 
@@ -312,7 +300,8 @@ GDALDataset* OGRPLScenesDataset::OpenRasterScene(GDALOpenInfo* poOpenInfo,
         {
             if( !EQUAL(pszKey, "api_key") &&
                 !EQUAL(pszKey, "scene") &&
-                !EQUAL(pszKey, "product_type") )
+                !EQUAL(pszKey, "product_type") &&
+                !EQUAL(pszKey, "version") )
             {
                 CPLError(CE_Failure, CPLE_NotSupported, "Unsupported option %s", pszKey);
                 CPLFree(pszKey);
@@ -377,12 +366,12 @@ GDALDataset* OGRPLScenesDataset::OpenRasterScene(GDALOpenInfo* poOpenInfo,
                  osScene.c_str());
         return NULL;
     }
-    
-    if( strncmp(osRasterURL, "http://", strlen("http://")) == 0 )
+
+    if( STARTS_WITH(osRasterURL, "http://") )
     {
         osRasterURL = "http://" + osAPIKey + ":@" + osRasterURL.substr(strlen("http://"));
     }
-    else if( strncmp(osRasterURL, "https://", strlen("https://")) == 0 )
+    else if( STARTS_WITH(osRasterURL, "https://") )
     {
         osRasterURL = "https://" + osAPIKey + ":@" + osRasterURL.substr(strlen("https://"));
     }
@@ -391,7 +380,7 @@ GDALDataset* OGRPLScenesDataset::OpenRasterScene(GDALOpenInfo* poOpenInfo,
     CPLString osOldExt(CPLGetConfigOption("CPL_VSIL_CURL_ALLOWED_EXTENSIONS", ""));
 
     int bUseVSICURL = CSLFetchBoolean(poOpenInfo->papszOpenOptions, "RANDOM_ACCESS", TRUE);
-    if( bUseVSICURL && !(strncmp(osBaseURL, "/vsimem/", strlen("/vsimem/")) == 0) )
+    if( bUseVSICURL && !(STARTS_WITH(osBaseURL, "/vsimem/")) )
     {
         CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_USE_HEAD", "NO");
         CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_ALLOWED_EXTENSIONS", "{noext}");
@@ -412,7 +401,7 @@ GDALDataset* OGRPLScenesDataset::OpenRasterScene(GDALOpenInfo* poOpenInfo,
     if( poOutDS )
     {
         poOutDS->SetDescription(poOpenInfo->pszFilename);
-        poOutDS->GetFileList(); /* so as to probe all auxiliary files before reseting the allowed extensions */
+        CSLDestroy(poOutDS->GetFileList()); /* so as to probe all auxiliary files before reseting the allowed extensions */
 
         if( !EQUAL(pszProductType, "thumb") )
         {
@@ -422,7 +411,7 @@ GDALDataset* OGRPLScenesDataset::OpenRasterScene(GDALOpenInfo* poOpenInfo,
                                         sizeof(OGRPLScenesLayer*) * (nLayers + 1));
             papoLayers[nLayers ++] = poLayer;
 
-            /* Attach scene matadata */
+            /* Attach scene metadata. */
             poLayer->SetAttributeFilter(CPLSPrintf("id = '%s'", osScene.c_str()));
             OGRFeature* poFeat = poLayer->GetNextFeature();
             if( poFeat )
@@ -444,7 +433,7 @@ GDALDataset* OGRPLScenesDataset::OpenRasterScene(GDALOpenInfo* poOpenInfo,
             delete poFeat;
         }
     }
-    
+
     if( bUseVSICURL )
     {
         CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_USE_HEAD",
@@ -462,9 +451,6 @@ GDALDataset* OGRPLScenesDataset::OpenRasterScene(GDALOpenInfo* poOpenInfo,
 
 GDALDataset* OGRPLScenesDataset::Open(GDALOpenInfo* poOpenInfo)
 {
-    if( !Identify(poOpenInfo) || poOpenInfo->eAccess == GA_Update )
-        return NULL;
-
     OGRPLScenesDataset* poDS = new OGRPLScenesDataset();
 
     poDS->osBaseURL = CPLGetConfigOption("PL_URL", "https://api.planet.com/v0/scenes/");
@@ -502,9 +488,10 @@ GDALDataset* OGRPLScenesDataset::Open(GDALOpenInfo* poOpenInfo)
         if( pszValue != NULL )
         {
             if( !EQUAL(pszKey, "api_key") &&
-                !EQUAL(pszKey, "spat") )
+                !EQUAL(pszKey, "spat") &&
+                !EQUAL(pszKey, "version") )
             {
-                CPLError(CE_Failure, CPLE_NotSupported, "Unsupported option %s", pszKey);
+                CPLError(CE_Failure, CPLE_NotSupported, "Unsupported option '%s'", pszKey);
                 CPLFree(pszKey);
                 delete poDS;
                 CSLDestroy(papszOptions);
@@ -521,7 +508,7 @@ GDALDataset* OGRPLScenesDataset::Open(GDALOpenInfo* poOpenInfo)
         CSLDestroy(papszOptions);
         return NULL;
     }
-    
+
     json_object_iter it;
     it.key = NULL;
     it.val = NULL;
@@ -532,19 +519,19 @@ GDALDataset* OGRPLScenesDataset::Open(GDALOpenInfo* poOpenInfo)
         {
             const char* pszSceneType = it.key;
             const char* pszSceneTypeURL = json_object_get_string(it.val);
-            json_object* poObj = NULL;
+            json_object* poObj2 = NULL;
             if( !EQUAL(pszSceneType, "ortho") )
-                poObj = poDS->RunRequest( (CPLString(pszSceneTypeURL) + CPLString("?count=10")).c_str() );
+                poObj2 = poDS->RunRequest( (CPLString(pszSceneTypeURL) + CPLString("?count=10")).c_str() );
 
-            OGRPLScenesLayer* poLayer = new OGRPLScenesLayer(poDS, pszSceneType, pszSceneTypeURL, poObj);
+            OGRPLScenesLayer* poLayer = new OGRPLScenesLayer(poDS, pszSceneType, pszSceneTypeURL, poObj2);
 
-            if( poObj )
-                json_object_put(poObj);
+            if( poObj2 )
+                json_object_put(poObj2);
 
             poDS->papoLayers = (OGRPLScenesLayer**) CPLRealloc(poDS->papoLayers,
                                         sizeof(OGRPLScenesLayer*) * (poDS->nLayers + 1));
             poDS->papoLayers[poDS->nLayers ++] = poLayer;
-            
+
             const char* pszSpat = CSLFetchNameValue(papszOptions, "spat");
             if( pszSpat )
             {
@@ -573,42 +560,3 @@ GDALDataset* OGRPLScenesDataset::Open(GDALOpenInfo* poOpenInfo)
 
     return poDS;
 }
-
-/************************************************************************/
-/*                        RegisterOGRPLSCENES()                         */
-/************************************************************************/
-
-void RegisterOGRPLSCENES()
-
-{
-    GDALDriver  *poDriver;
-
-    if( GDALGetDriverByName( "PLSCENES" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "PLSCENES" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Planet Labs Scenes API" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "drv_plscenes.html" );
-
-        poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, "PLSCENES:" );
-
-        poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
-"<OpenOptionList>"
-"  <Option name='API_KEY' type='string' description='Account API key' required='true'/>"
-"  <Option name='SCENE' type='string' description='Scene id (for raster fetching)'/>"
-"  <Option name='PRODUCT_TYPE' type='string' description='Product type: visual, analytic or thumb (for raster fetching)' default='visual'/>"
-"  <Option name='RANDOM_ACCESS' type='boolean' description='Whether raster should be accessed in random access mode (but with potentially not optimal throughput). If no, in-memory ingestion is done' default='YES'/>"
-"</OpenOptionList>");
-
-        poDriver->pfnOpen = OGRPLScenesDataset::Open;
-        poDriver->pfnIdentify = OGRPLScenesDataset::Identify;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
-}
-
diff --git a/ogr/ogrsf_frmts/plscenes/ogrplscenesdriver.cpp b/ogr/ogrsf_frmts/plscenes/ogrplscenesdriver.cpp
new file mode 100644
index 0000000..61a6761
--- /dev/null
+++ b/ogr/ogrsf_frmts/plscenes/ogrplscenesdriver.cpp
@@ -0,0 +1,100 @@
+/******************************************************************************
+ * $Id: ogrplscenesdriver.cpp 33602 2016-02-29 20:20:12Z rouault $
+ *
+ * Project:  PlanetLabs scene driver
+ * Purpose:  PlanetLabs scene driver
+ * Author:   Even Rouault, even dot rouault at spatialys.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2015-2016, Planet Labs
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_plscenes.h"
+
+/************************************************************************/
+/*                         OGRPLScenesIdentify()                        */
+/************************************************************************/
+
+static int OGRPLScenesIdentify(GDALOpenInfo* poOpenInfo)
+{
+    return STARTS_WITH_CI(poOpenInfo->pszFilename, "PLSCENES:");
+}
+
+
+/************************************************************************/
+/*                            OGRPLScenesOpen()                         */
+/************************************************************************/
+
+static GDALDataset* OGRPLScenesOpen(GDALOpenInfo* poOpenInfo)
+{
+    if( !OGRPLScenesIdentify(poOpenInfo) || poOpenInfo->eAccess == GA_Update )
+        return NULL;
+
+    char** papszOptions = CSLTokenizeStringComplex(
+            poOpenInfo->pszFilename+strlen("PLScenes:"), ",", TRUE, FALSE );
+    CPLString osVersion = CSLFetchNameValueDef(papszOptions, "version",
+                CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "VERSION", ""));
+    CSLDestroy(papszOptions);
+    if( EQUAL(osVersion, "v0") || EQUAL(osVersion, "") )
+        return OGRPLScenesDataset::Open(poOpenInfo);
+    if( EQUAL(osVersion, "v1") )
+        return OGRPLScenesV1Dataset::Open(poOpenInfo);
+    CPLError(CE_Failure, CPLE_AppDefined,
+             "Unhandled API version: %s", osVersion.c_str());
+    return NULL;
+}
+
+/************************************************************************/
+/*                        RegisterOGRPLSCENES()                         */
+/************************************************************************/
+
+void RegisterOGRPLSCENES()
+
+{
+    if( GDALGetDriverByName( "PLSCENES" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "PLSCENES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Planet Labs Scenes API" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_plscenes.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, "PLSCENES:" );
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+"<OpenOptionList>"
+"  <Option name='VERSION' type='string-select' description='API version' default='V0'>"
+"    <Value>V0</Value>"
+"    <Value>V1</Value>"
+"  </Option>"
+"  <Option name='API_KEY' type='string' description='Account API key' required='true'/>"
+"  <Option name='SCENE' type='string' description='Scene id (for raster fetching)'/>"
+"  <Option name='CATALOG' type='string' description='Catalog id (API v1 only, mandatory for raster fetching)'/>"
+"  <Option name='PRODUCT_TYPE' type='string' description='Product type/asset category. For v0 API: visual, analytic or thumb (for raster fetching)' default='visual'/>"
+"  <Option name='RANDOM_ACCESS' type='boolean' description='Whether raster should be accessed in random access mode (but with potentially not optimal throughput). If no, in-memory ingestion is done' default='YES'/>"
+"</OpenOptionList>");
+
+    poDriver->pfnOpen = OGRPLScenesOpen;
+    poDriver->pfnIdentify = OGRPLScenesIdentify;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/ogr/ogrsf_frmts/plscenes/ogrplsceneslayer.cpp b/ogr/ogrsf_frmts/plscenes/ogrplsceneslayer.cpp
index 72d92e6..7d15359 100644
--- a/ogr/ogrsf_frmts/plscenes/ogrplsceneslayer.cpp
+++ b/ogr/ogrsf_frmts/plscenes/ogrplsceneslayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrplsceneslayer.cpp 29164 2015-05-06 15:01:37Z rouault $
+ * $Id: ogrplsceneslayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  PlanetLabs scene driver
  * Purpose:  Implements OGRPLScenesLayer
@@ -30,7 +30,7 @@
 #include "ogr_plscenes.h"
 #include <algorithm>
 
-CPL_CVSID("$Id: ogrplsceneslayer.cpp 29164 2015-05-06 15:01:37Z rouault $");
+CPL_CVSID("$Id: ogrplsceneslayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 typedef struct
 {
@@ -73,7 +73,7 @@ static bool OGRPLScenesLayerFieldNameComparator(const CPLString& osFirst,
 {
     const char* pszUnderscore1 = strrchr(osFirst.c_str(), '_');
     const char* pszUnderscore2 = strrchr(osSecond.c_str(), '_');
-    int val1, val2;
+    int val1 = 0, val2 = 0;
     if( pszUnderscore1 && pszUnderscore2 &&
         (CPLString(osFirst).substr(0, pszUnderscore1-osFirst.c_str()) ==
          CPLString(osSecond).substr(0, pszUnderscore2-osSecond.c_str())) &&
@@ -89,12 +89,12 @@ static bool OGRPLScenesLayerFieldNameComparator(const CPLString& osFirst,
 /*                           OGRPLScenesLayer()                         */
 /************************************************************************/
 
-OGRPLScenesLayer::OGRPLScenesLayer(OGRPLScenesDataset* poDS,
+OGRPLScenesLayer::OGRPLScenesLayer(OGRPLScenesDataset* poDSIn,
                                    const char* pszName,
                                    const char* pszBaseURL,
                                    json_object* poObjCount10)
 {
-    this->poDS = poDS;
+    this->poDS = poDSIn;
     osBaseURL = pszBaseURL;
     SetDescription(pszName);
     poFeatureDefn = new OGRFeatureDefn(pszName);
@@ -118,7 +118,7 @@ OGRPLScenesLayer::OGRPLScenesLayer(OGRPLScenesDataset* poDS,
     bAcquiredAscending = -1;
     bFilterMustBeClientSideEvaluated = FALSE;
     ResetReading();
-    
+
     if( poObjCount10 != NULL )
     {
         json_object* poCount = json_object_object_get(poObjCount10, "count");
@@ -172,7 +172,7 @@ CPLString OGRPLScenesLayer::BuildFilter(swq_expr_node* poNode)
     {
         if( poNode->nOperation == SWQ_AND && poNode->nSubExprCount == 2 )
         {
-            // For AND, we can deal with a failure in one of the branch 
+            // For AND, we can deal with a failure in one of the branch
             // since client-side will do that extra filtering
             CPLString osFilter1 = BuildFilter(poNode->papoSubExpr[0]);
             CPLString osFilter2 = BuildFilter(poNode->papoSubExpr[1]);
@@ -298,12 +298,12 @@ CPLString OGRPLScenesLayer::BuildURL(int nFeatures)
         osURL += "&order_by=acquired%20asc";
     else if( bAcquiredAscending == 0 )
         osURL += "&order_by=acquired%20desc";
-    
+
     if( m_poFilterGeom != NULL || poMainFilter != NULL )
     {
         OGRGeometry* poIntersection = NULL;
         OGRGeometry* poFilterGeom = m_poFilterGeom;
-        if( poFilterGeom ) 
+        if( poFilterGeom )
         {
             OGREnvelope sEnvelope;
             poFilterGeom->getEnvelope(&sEnvelope);
@@ -315,7 +315,7 @@ CPLString OGRPLScenesLayer::BuildURL(int nFeatures)
         if( poFilterGeom && poMainFilter )
             poIntersection = poFilterGeom->Intersection(poMainFilter);
         else if( poFilterGeom )
-            poIntersection = poFilterGeom; 
+            poIntersection = poFilterGeom;
         else if( poMainFilter )
             poIntersection = poMainFilter;
         if( poIntersection )
@@ -369,7 +369,7 @@ int OGRPLScenesLayer::GetNextPage()
             nFeatureCount = 0;
         return FALSE;
     }
-    // In the case of a "id = 'foo'" filter, a non existing resource 
+    // In the case of a "id = 'foo'" filter, a non existing resource
     // will cause a 404 error, which we want to be silent
     int bQuiet404Error = ( osRequestURL.find('?') == std::string::npos );
     json_object* poObj = poDS->RunRequest(osRequestURL, bQuiet404Error);
@@ -409,7 +409,7 @@ int OGRPLScenesLayer::GetNextPage()
     oReader.SetFlattenNestedAttributes(true, '.');
     oReader.ReadLayer( poGeoJSONDS, "layer", poObj);
     poGeoJSONLayer = poGeoJSONDS->GetLayer(0);
-    
+
     // Get URL of next page
     osNextURL = "";
     if( poGeoJSONLayer )
@@ -505,7 +505,7 @@ OGRErr OGRPLScenesLayer::SetAttributeFilter( const char *pszQuery )
 
     return eErr;
 }
-  
+
 /************************************************************************/
 /*                           GetNextFeature()                           */
 /************************************************************************/
@@ -517,7 +517,7 @@ OGRFeature *OGRPLScenesLayer::GetNextFeature()
 
     OGRFeature  *poFeature;
 
-    while(TRUE)
+    while( true )
     {
         poFeature = GetNextRawFeature();
         if (poFeature == NULL)
@@ -552,7 +552,7 @@ OGRFeature* OGRPLScenesLayer::GetNextRawFeature()
     }
 
 #ifdef notdef
-    if( CSLTestBoolean(CPLGetConfigOption("OGR_LIMIT_TOO_MANY_FEATURES", "FALSE")) &&
+    if( CPLTestBool(CPLGetConfigOption("OGR_LIMIT_TOO_MANY_FEATURES", "FALSE")) &&
         nFeatureCount > nPageSize )
     {
         bEOF = TRUE;
@@ -594,7 +594,7 @@ OGRFeature* OGRPLScenesLayer::GetNextRawFeature()
         poGeom->assignSpatialReference(poSRS);
         poFeature->SetGeometryDirectly(poGeom);
     }
-    
+
     for(int i=0;i<poFeatureDefn->GetFieldCount();i++)
     {
         OGRFieldDefn* poFieldDefn = poFeatureDefn->GetFieldDefn(i);
@@ -678,7 +678,7 @@ OGRErr OGRPLScenesLayer::GetExtent( OGREnvelope *psExtent, int bForce )
     GetFeatureCount();
     if( nFeatureCount > 0 && nFeatureCount < nPageSize )
         return OGRLayer::GetExtentInternal(0, psExtent, bForce);
-    
+
     psExtent->MinX = -180;
     psExtent->MinY = -90;
     psExtent->MaxX = 180;
diff --git a/ogr/ogrsf_frmts/plscenes/ogrplscenesv1dataset.cpp b/ogr/ogrsf_frmts/plscenes/ogrplscenesv1dataset.cpp
new file mode 100644
index 0000000..d1f5831
--- /dev/null
+++ b/ogr/ogrsf_frmts/plscenes/ogrplscenesv1dataset.cpp
@@ -0,0 +1,669 @@
+/******************************************************************************
+ * $Id: ogrplscenesv1dataset.cpp 33714 2016-03-13 05:42:13Z goatbar $
+ *
+ * Project:  PlanetLabs scene driver
+ * Purpose:  Implements OGRPLScenesV1Dataset
+ * Author:   Even Rouault, even dot rouault at spatialys.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Planet Labs
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_plscenes.h"
+
+CPL_CVSID("$Id: ogrplscenesv1dataset.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+
+/************************************************************************/
+/*                         OGRPLScenesV1Dataset()                       */
+/************************************************************************/
+
+OGRPLScenesV1Dataset::OGRPLScenesV1Dataset()
+{
+    m_bLayerListInitialized = false;
+    m_bMustCleanPersistent = false;
+    m_nLayers = 0;
+    m_papoLayers = NULL;
+}
+
+/************************************************************************/
+/*                         ~OGRPLScenesV1Dataset()                      */
+/************************************************************************/
+
+OGRPLScenesV1Dataset::~OGRPLScenesV1Dataset()
+{
+    for(int i=0;i<m_nLayers;i++)
+        delete m_papoLayers[i];
+    CPLFree(m_papoLayers);
+
+    if (m_bMustCleanPersistent)
+    {
+        char** papszOptions = NULL;
+        papszOptions = CSLSetNameValue(papszOptions, "CLOSE_PERSISTENT", CPLSPrintf("PLSCENES:%p", this));
+        CPLHTTPDestroyResult(CPLHTTPFetch(m_osBaseURL, papszOptions));
+        CSLDestroy(papszOptions);
+    }
+}
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer *OGRPLScenesV1Dataset::GetLayer(int idx)
+{
+    if( idx < 0 || idx >= GetLayerCount() )
+        return NULL;
+    return m_papoLayers[idx];
+}
+
+/************************************************************************/
+/*                           GetLayerCount()                            */
+/************************************************************************/
+
+int OGRPLScenesV1Dataset::GetLayerCount()
+{
+    if( !m_bLayerListInitialized )
+    {
+        m_bLayerListInitialized = true;
+        EstablishLayerList();
+    }
+    return m_nLayers;
+}
+
+/************************************************************************/
+/*                           ParseCatalog()                             */
+/************************************************************************/
+
+OGRLayer* OGRPLScenesV1Dataset::ParseCatalog(json_object* poCatalog)
+{
+    if( poCatalog == NULL || json_object_get_type(poCatalog) != json_type_object )
+        return NULL;
+    json_object* poId = json_object_object_get(poCatalog, "id");
+    if( poId == NULL || json_object_get_type(poId) != json_type_string )
+        return NULL;
+    json_object* poLinks = json_object_object_get(poCatalog, "_links");
+    if( poLinks == NULL || json_object_get_type(poLinks) != json_type_object )
+        return NULL;
+    json_object* poSpec = json_object_object_get(poLinks, "spec");
+    if( poSpec == NULL || json_object_get_type(poSpec) != json_type_string )
+        return NULL;
+    json_object* poItems = json_object_object_get(poLinks, "items");
+    if( poItems == NULL || json_object_get_type(poItems) != json_type_string )
+        return NULL;
+    json_object* poCount = json_object_object_get(poCatalog, "count");
+    GIntBig nCount = -1;
+    if( poCount != NULL && json_object_get_type(poCount) == json_type_int )
+    {
+        nCount = json_object_get_int64(poCount);
+    }
+    json_object* poAssetCategories = json_object_object_get(poCatalog, "asset_categories");
+    std::vector<CPLString> aoAssetCategories;
+    if( poAssetCategories != NULL && json_object_get_type(poAssetCategories) == json_type_object )
+    {
+        json_object_iter it;
+        it.key = NULL;
+        it.val = NULL;
+        it.entry = NULL;
+        json_object_object_foreachC( poAssetCategories, it )
+        {
+            aoAssetCategories.push_back(it.key);
+        }
+    }
+
+    const char* pszId = json_object_get_string(poId);
+    const char* pszSpecURL = json_object_get_string(poSpec);
+    const char* pszItemsURL = json_object_get_string(poItems);
+
+    // The layer might already exist if GetLayerByName() is called before
+    // GetLayer()/GetLayerCount() is
+
+    // Prevent GetLayerCount() from calling EstablishLayerList()
+    bool bLayerListInitializedBackup = m_bLayerListInitialized;
+    m_bLayerListInitialized = true;
+    OGRLayer* poExistingLayer = GDALDataset::GetLayerByName(pszId);
+    m_bLayerListInitialized = bLayerListInitializedBackup;
+    if( poExistingLayer != NULL )
+        return poExistingLayer;
+
+    OGRPLScenesV1Layer* poPLLayer = new OGRPLScenesV1Layer(
+                            this, pszId, pszSpecURL, pszItemsURL, nCount, aoAssetCategories);
+    m_papoLayers = (OGRPLScenesV1Layer**) CPLRealloc(m_papoLayers,
+                                sizeof(OGRPLScenesV1Layer*) * (m_nLayers + 1));
+    m_papoLayers[m_nLayers ++] = poPLLayer;
+    return poPLLayer;
+}
+
+
+/************************************************************************/
+/*                          ParseCatalogsPage()                         */
+/************************************************************************/
+
+bool OGRPLScenesV1Dataset::ParseCatalogsPage(json_object* poObj,
+                                             CPLString& osNext)
+{
+    json_object* poCatalogs = json_object_object_get(poObj, "catalogs");
+    if( poCatalogs == NULL || json_object_get_type(poCatalogs) != json_type_array )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                "Missing catalogs object, or not of type array");
+        return false;
+    }
+    const int nCatalogsLength = json_object_array_length(poCatalogs);
+    for( int i=0; i<nCatalogsLength; i++ )
+    {
+        json_object* poCatalog = json_object_array_get_idx(poCatalogs, i);
+        ParseCatalog(poCatalog);
+    }
+
+    // Is there a next page ?
+    osNext = "";
+    json_object* poLinks = json_object_object_get(poObj, "_links");
+    if( poLinks && json_object_get_type(poLinks) == json_type_object )
+    {
+        json_object* poNext = json_object_object_get(poLinks, "_next");
+        if( poNext && json_object_get_type(poNext) == json_type_string )
+        {
+            osNext = json_object_get_string(poNext);
+        }
+    }
+
+    return true;
+}
+
+/************************************************************************/
+/*                          EstablishLayerList()                        */
+/************************************************************************/
+
+void OGRPLScenesV1Dataset::EstablishLayerList()
+{
+    CPLString osURL(m_osNextCatalogPageURL);
+    m_osNextCatalogPageURL = "";
+
+    while( osURL.size() != 0 )
+    {
+        json_object* poObj = RunRequest(osURL);
+        if( poObj == NULL )
+            break;
+        if( !ParseCatalogsPage( poObj, osURL ) )
+        {
+            json_object_put(poObj);
+            break;
+        }
+        json_object_put(poObj);
+    }
+}
+
+/************************************************************************/
+/*                          GetLayerByName()                            */
+/************************************************************************/
+
+OGRLayer *OGRPLScenesV1Dataset::GetLayerByName(const char* pszName)
+{
+    // Prevent GetLayerCount() from calling EstablishLayerList()
+    bool bLayerListInitializedBackup = m_bLayerListInitialized;
+    m_bLayerListInitialized = true;
+    OGRLayer* poRet = GDALDataset::GetLayerByName(pszName);
+    m_bLayerListInitialized = bLayerListInitializedBackup;
+    if( poRet != NULL )
+        return poRet;
+
+    CPLString osURL(m_osBaseURL + pszName);
+    json_object* poObj = RunRequest(osURL);
+    if( poObj == NULL )
+        return NULL;
+    poRet = ParseCatalog(poObj);
+    json_object_put(poObj);
+    return poRet;
+}
+
+/************************************************************************/
+/*                          GetBaseHTTPOptions()                         */
+/************************************************************************/
+
+char** OGRPLScenesV1Dataset::GetBaseHTTPOptions()
+{
+    m_bMustCleanPersistent = true;
+
+    char** papszOptions = NULL;
+    papszOptions = CSLAddString(papszOptions, CPLSPrintf("PERSISTENT=PLSCENES:%p", this));
+    papszOptions = CSLAddString(papszOptions, CPLSPrintf("HEADERS=Authorization: api-key %s", m_osAPIKey.c_str()));
+    return papszOptions;
+}
+
+/************************************************************************/
+/*                               RunRequest()                           */
+/************************************************************************/
+
+json_object* OGRPLScenesV1Dataset::RunRequest(const char* pszURL,
+                                            int bQuiet404Error)
+{
+    char** papszOptions = CSLAddString(GetBaseHTTPOptions(), NULL);
+    CPLHTTPResult * psResult;
+    if( STARTS_WITH(m_osBaseURL, "/vsimem/") &&
+        STARTS_WITH(pszURL, "/vsimem/") )
+    {
+        CPLDebug("PLSCENES", "Fetching %s", pszURL);
+        psResult = (CPLHTTPResult*) CPLCalloc(1, sizeof(CPLHTTPResult));
+        vsi_l_offset nDataLengthLarge = 0;
+        CPLString osURL(pszURL);
+        if( osURL[osURL.size()-1 ] == '/' )
+            osURL.resize(osURL.size()-1);
+        GByte* pabyBuf = VSIGetMemFileBuffer(osURL, &nDataLengthLarge, FALSE);
+        size_t nDataLength = static_cast<size_t>(nDataLengthLarge);
+        if( pabyBuf )
+        {
+            psResult->pabyData = (GByte*) VSI_MALLOC_VERBOSE(1 + nDataLength);
+            if( psResult->pabyData )
+            {
+                memcpy(psResult->pabyData, pabyBuf, nDataLength);
+                psResult->pabyData[nDataLength] = 0;
+            }
+        }
+        else
+        {
+            psResult->pszErrBuf =
+                CPLStrdup(CPLSPrintf("Error 404. Cannot find %s", pszURL));
+        }
+    }
+    else
+    {
+        if( bQuiet404Error )
+            CPLPushErrorHandler(CPLQuietErrorHandler);
+        psResult = CPLHTTPFetch( pszURL, papszOptions);
+        if( bQuiet404Error )
+            CPLPopErrorHandler();
+    }
+    CSLDestroy(papszOptions);
+
+    if( psResult->pszErrBuf != NULL )
+    {
+        if( !(bQuiet404Error && strstr(psResult->pszErrBuf, "404")) )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "%s",
+                    psResult->pabyData ? (const char*) psResult->pabyData :
+                    psResult->pszErrBuf);
+        }
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+
+    if( psResult->pabyData == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Empty content returned by server");
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+
+    json_tokener* jstok = NULL;
+    json_object* poObj = NULL;
+
+#ifdef DEBUG_VERBOSE
+    CPLDebug("PLScenes", "%s", (const char*) psResult->pabyData);
+#endif
+
+    jstok = json_tokener_new();
+    poObj = json_tokener_parse_ex(jstok, (const char*) psResult->pabyData, -1);
+    if( jstok->err != json_tokener_success)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                    "JSON parsing error: %s (at offset %d)",
+                    json_tokener_error_desc(jstok->err), jstok->char_offset);
+        json_tokener_free(jstok);
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+    json_tokener_free(jstok);
+
+    CPLHTTPDestroyResult(psResult);
+
+    if( json_object_get_type(poObj) != json_type_object )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Return is not a JSON dictionary");
+        json_object_put(poObj);
+        poObj = NULL;
+    }
+
+    return poObj;
+}
+
+/************************************************************************/
+/*                            OpenRasterScene()                         */
+/************************************************************************/
+
+GDALDataset* OGRPLScenesV1Dataset::OpenRasterScene(GDALOpenInfo* poOpenInfo,
+                                                 CPLString osScene,
+                                                 char** papszOptions)
+{
+    if( !(poOpenInfo->nOpenFlags & GDAL_OF_RASTER) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "The scene option must only be used with vector access");
+        return NULL;
+    }
+
+    for( char** papszIter = papszOptions; papszIter && *papszIter; papszIter ++ )
+    {
+        char* pszKey;
+        const char* pszValue = CPLParseNameValue(*papszIter, &pszKey);
+        if( pszValue != NULL )
+        {
+            if( !EQUAL(pszKey, "api_key") &&
+                !EQUAL(pszKey, "scene") &&
+                !EQUAL(pszKey, "product_type") &&
+                !EQUAL(pszKey, "catalog") &&
+                !EQUAL(pszKey, "version") )
+            {
+                CPLError(CE_Failure, CPLE_NotSupported, "Unsupported option %s", pszKey);
+                CPLFree(pszKey);
+                return NULL;
+            }
+            CPLFree(pszKey);
+        }
+    }
+
+    const char* pszCatalog = CSLFetchNameValueDef(papszOptions, "catalog",
+                CSLFetchNameValue(poOpenInfo->papszOpenOptions, "CATALOG"));
+    if( pszCatalog == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Missing catalog");
+        return NULL;
+    }
+
+    const char* pszProductType = CSLFetchNameValueDef(papszOptions, "product_type",
+                CSLFetchNameValue(poOpenInfo->papszOpenOptions, "PRODUCT_TYPE"));
+
+    CPLString osRasterURL;
+    osRasterURL = m_osBaseURL;
+    osRasterURL += pszCatalog;
+    osRasterURL += "/items/";
+    osRasterURL += osScene;
+    osRasterURL += "/assets/";
+
+    json_object* poObj = RunRequest( osRasterURL );
+    if( poObj == NULL )
+        return NULL;
+
+    json_object* poSubObj = NULL;
+    if( pszProductType != NULL &&
+        (poSubObj = json_object_object_get(poObj, pszProductType)) != NULL )
+    {
+       /* do nothing */
+    }
+    else if( pszProductType != NULL && !EQUAL(pszProductType, "LIST") &&
+        (poSubObj = json_object_object_get(poObj, pszProductType)) == NULL )
+    {
+       CPLError(CE_Failure, CPLE_AppDefined, "Cannot find asset %s", pszProductType);
+       json_object_put(poObj);
+       return NULL;
+    }
+    else if( pszProductType == NULL &&
+             (poSubObj = json_object_object_get(poObj, "visual")) != NULL )
+    {
+        /* do nothing */
+    }
+    else
+    {
+        json_object_iter it;
+        it.key = NULL;
+        it.val = NULL;
+        it.entry = NULL;
+        char** papszSubdatasets = NULL;
+        int nSubDataset = 0;
+        json_object_object_foreachC( poObj, it )
+        {
+            ++nSubDataset;
+            papszSubdatasets = CSLSetNameValue(papszSubdatasets,
+                    CPLSPrintf("SUBDATASET_%d_NAME", nSubDataset),
+                    CPLSPrintf("Scene=%s of catalog %s, type %s",
+                               osScene.c_str(), pszCatalog, it.key));
+            papszSubdatasets = CSLSetNameValue(papszSubdatasets,
+                    CPLSPrintf("SUBDATASET_%d_DESC", nSubDataset),
+                    CPLSPrintf("PLScenes:version=v1,catalog=%s,scene=%s,product_type=%s",
+                               pszCatalog, osScene.c_str(), it.key));
+        }
+        json_object_put(poObj);
+        if( nSubDataset != 0 )
+        {
+            GDALDataset* poDS = new OGRPLScenesV1Dataset();
+            poDS->SetMetadata(papszSubdatasets, "SUBDATASETS");
+            CSLDestroy(papszSubdatasets);
+            return poDS;
+        }
+        return NULL;
+    }
+    if( json_object_get_type(poSubObj) != json_type_object )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find link");
+        json_object_put(poObj);
+        return NULL;
+    }
+    json_object* poFile = json_object_object_get(poSubObj, "file");
+    if( poFile == NULL || json_object_get_type(poFile) != json_type_string )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find link");
+        json_object_put(poObj);
+        return NULL;
+    }
+    const char* pszLink = json_object_get_string(poFile);
+
+    osRasterURL = pszLink ? pszLink : "";
+    json_object_put(poObj);
+    if( osRasterURL.size() == 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find link to scene %s",
+                 osScene.c_str());
+        return NULL;
+    }
+
+    if( STARTS_WITH(osRasterURL, "http://") )
+    {
+        osRasterURL = "http://" + m_osAPIKey + ":@" + osRasterURL.substr(strlen("http://"));
+    }
+    else if( STARTS_WITH(osRasterURL, "https://") )
+    {
+        osRasterURL = "https://" + m_osAPIKey + ":@" + osRasterURL.substr(strlen("https://"));
+    }
+
+    CPLString osOldHead(CPLGetConfigOption("CPL_VSIL_CURL_USE_HEAD", ""));
+    CPLString osOldExt(CPLGetConfigOption("CPL_VSIL_CURL_ALLOWED_EXTENSIONS", ""));
+
+    int bUseVSICURL = CSLFetchBoolean(poOpenInfo->papszOpenOptions, "RANDOM_ACCESS", TRUE);
+    if( bUseVSICURL && !(STARTS_WITH(m_osBaseURL, "/vsimem/")) )
+    {
+        CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_USE_HEAD", "NO");
+        CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_ALLOWED_EXTENSIONS", "{noext}");
+
+        VSIStatBufL sStat;
+        if( VSIStatL(("/vsicurl/" + osRasterURL).c_str(), &sStat) == 0 &&
+            sStat.st_size > 0 )
+        {
+            osRasterURL = "/vsicurl/" + osRasterURL;
+        }
+        else
+        {
+            CPLDebug("PLSCENES", "Cannot use random access for that file");
+        }
+    }
+
+    GDALDataset* poOutDS = (GDALDataset*) GDALOpenEx(osRasterURL, GDAL_OF_RASTER, NULL, NULL, NULL);
+    if( poOutDS )
+    {
+        OGRLayer* poLayer = GetLayerByName(pszCatalog);
+        if( poLayer != NULL )
+        {
+            // Set a dummy name so that PAM goes here
+            CPLPushErrorHandler(CPLQuietErrorHandler);
+            poOutDS->SetDescription("/vsimem/tmp/ogrplscenesv1");
+
+            /* Attach scene metadata. */
+            poLayer->SetAttributeFilter(CPLSPrintf("id = '%s'", osScene.c_str()));
+            OGRFeature* poFeat = poLayer->GetNextFeature();
+            if( poFeat )
+            {
+                for(int i=0;i<poFeat->GetFieldCount();i++)
+                {
+                    if( poFeat->IsFieldSet(i) )
+                    {
+                        const char* pszKey = poFeat->GetFieldDefnRef(i)->GetNameRef();
+                        const char* pszVal = poFeat->GetFieldAsString(i);
+                        if( strncmp(pszKey, "asset_", strlen("asset_")) == 0 ||
+                            strstr(pszVal, "https://") != NULL )
+                        {
+                            continue;
+                        }
+                        poOutDS->SetMetadataItem(pszKey, pszVal);
+                    }
+                }
+            }
+            delete poFeat;
+
+            poOutDS->FlushCache();
+            VSIUnlink("/vsimem/tmp/ogrplscenesv1");
+            VSIUnlink("/vsimem/tmp/ogrplscenesv1.aux.xml");
+            CPLPopErrorHandler();
+        }
+
+        CPLErrorReset();
+        poOutDS->SetDescription(poOpenInfo->pszFilename);
+        CSLDestroy(poOutDS->GetFileList()); /* so as to probe all auxiliary files before reseting the allowed extensions */
+    }
+    else if( CPLGetLastErrorType() == CE_None )
+    {
+        poObj = RunRequest( osRasterURL );
+        if( poObj == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                    "The generation of the product is in progress. Retry later");
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "%s", json_object_to_json_string_ext( poObj, JSON_C_TO_STRING_PRETTY ));
+            json_object_put(poObj);
+        }
+    }
+
+    if( bUseVSICURL )
+    {
+        CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_USE_HEAD",
+                                    osOldHead.size() ? osOldHead.c_str(): NULL);
+        CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_ALLOWED_EXTENSIONS",
+                                    osOldExt.size() ? osOldExt.c_str(): NULL);
+    }
+
+    return poOutDS;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset* OGRPLScenesV1Dataset::Open(GDALOpenInfo* poOpenInfo)
+{
+    OGRPLScenesV1Dataset* poDS = new OGRPLScenesV1Dataset();
+
+    poDS->m_osBaseURL = CPLGetConfigOption("PL_URL", "https://api.planet.com/v1/catalogs/");
+
+    char** papszOptions = CSLTokenizeStringComplex(
+            poOpenInfo->pszFilename+strlen("PLScenes:"), ",", TRUE, FALSE );
+
+    poDS->m_osAPIKey = CSLFetchNameValueDef(papszOptions, "api_key",
+        CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "API_KEY",
+                                CPLGetConfigOption("PL_API_KEY","")) );
+    if( poDS->m_osAPIKey.size() == 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Missing PL_API_KEY configuration option or API_KEY open option");
+        delete poDS;
+        CSLDestroy(papszOptions);
+        return NULL;
+    }
+
+    const char* pszScene = CSLFetchNameValueDef(papszOptions, "scene",
+                CSLFetchNameValue(poOpenInfo->papszOpenOptions, "SCENE"));
+    if( pszScene )
+    {
+        GDALDataset* poRasterDS = poDS->OpenRasterScene(poOpenInfo, pszScene,
+                                                        papszOptions);
+        delete poDS;
+        CSLDestroy(papszOptions);
+        return poRasterDS;
+    }
+
+    for( char** papszIter = papszOptions; papszIter && *papszIter; papszIter ++ )
+    {
+        char* pszKey;
+        const char* pszValue = CPLParseNameValue(*papszIter, &pszKey);
+        if( pszValue != NULL )
+        {
+            if( !EQUAL(pszKey, "api_key") &&
+                !EQUAL(pszKey, "version") &&
+                !EQUAL(pszKey, "catalog") )
+            {
+                CPLError(CE_Failure, CPLE_NotSupported, "Unsupported option '%s'", pszKey);
+                CPLFree(pszKey);
+                delete poDS;
+                CSLDestroy(papszOptions);
+                return NULL;
+            }
+            CPLFree(pszKey);
+        }
+    }
+
+    json_object* poObj = poDS->RunRequest(poDS->m_osBaseURL);
+    if( poObj == NULL )
+    {
+        delete poDS;
+        CSLDestroy(papszOptions);
+        return NULL;
+    }
+
+    const char* pszCatalog = CSLFetchNameValueDef(papszOptions, "catalog",
+                CSLFetchNameValue(poOpenInfo->papszOpenOptions, "CATALOG"));
+    if( pszCatalog == NULL )
+    {
+        // Establish (partial if there are other pages) layer list.
+        if( !poDS->ParseCatalogsPage( poObj, poDS->m_osNextCatalogPageURL) )
+        {
+            delete poDS;
+            poDS = NULL;
+        }
+    }
+    else
+    {
+        if( poDS->GetLayerByName( pszCatalog ) == NULL )
+        {
+            delete poDS;
+            poDS = NULL;
+        }
+    }
+
+    json_object_put(poObj);
+
+    CSLDestroy(papszOptions);
+
+    if( !(poOpenInfo->nOpenFlags & GDAL_OF_VECTOR) )
+    {
+        delete poDS;
+        return NULL;
+    }
+
+    return poDS;
+}
diff --git a/ogr/ogrsf_frmts/plscenes/ogrplscenesv1layer.cpp b/ogr/ogrsf_frmts/plscenes/ogrplscenesv1layer.cpp
new file mode 100644
index 0000000..a58b07a
--- /dev/null
+++ b/ogr/ogrsf_frmts/plscenes/ogrplscenesv1layer.cpp
@@ -0,0 +1,1454 @@
+/******************************************************************************
+ * $Id: ogrplscenesv1layer.cpp 33714 2016-03-13 05:42:13Z goatbar $
+ *
+ * Project:  PlanetLabs scene driver
+ * Purpose:  Implements OGRPLScenesV1Layer
+ * Author:   Even Rouault, even dot rouault at spatialys.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Planet Labs
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_plscenes.h"
+#include <algorithm>
+
+CPL_CVSID("$Id: ogrplscenesv1layer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+
+/************************************************************************/
+/*                           GetFieldCount()                            */
+/************************************************************************/
+
+int OGRPLScenesV1FeatureDefn::GetFieldCount()
+{
+    if( nFieldCount == 0 && m_poLayer != NULL )
+        m_poLayer->EstablishLayerDefn();
+    return nFieldCount;
+}
+
+/************************************************************************/
+/*                          OGRPLScenesV1Layer()                        */
+/************************************************************************/
+
+OGRPLScenesV1Layer::OGRPLScenesV1Layer(OGRPLScenesV1Dataset* poDS,
+                                       const char* pszName,
+                                       const char* pszSpecURL,
+                                       const char* pszItemsURL,
+                                       GIntBig nCount,
+                                       std::vector<CPLString> aoAssetCategories)
+{
+    m_poDS = poDS;
+    SetDescription(pszName);
+    m_bFeatureDefnEstablished = false;
+    m_poFeatureDefn = new OGRPLScenesV1FeatureDefn(this, pszName);
+    m_poFeatureDefn->SetGeomType(wkbMultiPolygon);
+    m_poFeatureDefn->Reference();
+    m_poSRS = new OGRSpatialReference(SRS_WKT_WGS84);
+    m_poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(m_poSRS);
+    m_osSpecURL = pszSpecURL;
+    m_osItemsURL = pszItemsURL;
+    m_nTotalFeatures = nCount;
+    m_aoAssetCategories = aoAssetCategories;
+    m_nNextFID = 1;
+    m_bEOF = false;
+    m_bStillInFirstPage = true;
+    m_poPageObj = NULL;
+    m_poFeatures = NULL;
+    m_nFeatureIdx = 0;
+    m_nPageSize = atoi(CPLGetConfigOption("PLSCENES_PAGE_SIZE", "1000"));
+    m_bFilterMustBeClientSideEvaluated = false;
+    ResetReading();
+}
+
+/************************************************************************/
+/*                          ~OGRPLScenesV1Layer()                       */
+/************************************************************************/
+
+OGRPLScenesV1Layer::~OGRPLScenesV1Layer()
+{
+    m_poFeatureDefn->DropRefToLayer();
+    m_poFeatureDefn->Release();
+    m_poSRS->Release();
+    if( m_poPageObj != NULL )
+        json_object_put(m_poPageObj);
+}
+
+/************************************************************************/
+/*                             GetLayerDefn()                           */
+/************************************************************************/
+
+OGRFeatureDefn* OGRPLScenesV1Layer::GetLayerDefn()
+{
+    return m_poFeatureDefn;
+}
+
+/************************************************************************/
+/*                       ResolveRefIfNecessary()                        */
+/************************************************************************/
+
+json_object* OGRPLScenesV1Layer::ResolveRefIfNecessary(json_object* poObj,
+                                                      json_object* poMain)
+{
+    json_object* poRef = json_object_object_get(poObj, "$ref");
+    if( poRef == NULL )
+        return poObj;
+    if( json_object_get_type(poRef) != json_type_string )
+        return NULL;
+    const char* pszRef = json_object_get_string(poRef);
+    if( strncmp(pszRef, "#/", 2) != 0 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, "Cannot expand ref %s",
+                 pszRef);
+        return NULL;
+    }
+    char** papszPath = CSLTokenizeStringComplex(pszRef+2, "/", FALSE, FALSE );
+    json_object* poCurNode = poMain;
+    for(int i=0; papszPath != NULL && papszPath[i] != NULL; i++)
+    {
+        poCurNode = json_object_object_get(poCurNode, papszPath[i]);
+        if( poCurNode == NULL || json_object_get_type(poCurNode) != json_type_object )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Cannot find object '%s' of '%s'",
+                     papszPath[i], pszRef);
+            CSLDestroy(papszPath);
+            return NULL;
+        }
+    }
+    CSLDestroy(papszPath);
+    return poCurNode;
+}
+
+/************************************************************************/
+/*                          RegisterField()                             */
+/************************************************************************/
+
+void OGRPLScenesV1Layer::RegisterField(OGRFieldDefn* poFieldDefn,
+                                       const char* pszQueriableJSonName,
+                                       const char* pszPrefixedJSonName)
+{
+    const int nIdx = m_poFeatureDefn->GetFieldCount();
+    m_oMapPrefixedJSonFieldNameToFieldIdx[pszPrefixedJSonName] = nIdx;
+    if( pszQueriableJSonName &&
+        m_oSetQueriable.find(pszQueriableJSonName) != m_oSetQueriable.end() )
+    {
+        m_oMapFieldIdxToQueriableJSonFieldName[nIdx] = pszQueriableJSonName;
+    }
+    m_poFeatureDefn->AddFieldDefn(poFieldDefn);
+}
+
+/************************************************************************/
+/*                         EstablishLayerDefn()                         */
+/************************************************************************/
+
+void OGRPLScenesV1Layer::EstablishLayerDefn()
+{
+    if( m_bFeatureDefnEstablished )
+        return;
+    m_bFeatureDefnEstablished = true;
+
+    json_object* poSpec = m_poDS->RunRequest(m_osSpecURL);
+    if( poSpec == NULL )
+        return;
+    json_object* poPaths = json_object_object_get(poSpec, "paths");
+    if( poPaths == NULL || json_object_get_type(poPaths) != json_type_object )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find paths");
+        json_object_put(poSpec);
+        return;
+    }
+
+/* Parse
+    "paths": {
+        "/catalogs/my_catalog/items/" : {
+            "get": {
+                "responses": {
+                    "200": {
+                        "schema": {
+                            "$ref": "#/definitions/ItemPage"
+                        }
+                    }
+                }
+            }
+        }
+    }
+*/
+    json_object_iter it;
+    it.key = NULL;
+    it.val = NULL;
+    it.entry = NULL;
+    json_object* poItemsDef = NULL;
+    json_object_object_foreachC( poPaths, it )
+    {
+        if( m_osItemsURL.size() >= strlen(it.key) &&
+            strcmp( m_osItemsURL.c_str() + m_osItemsURL.size() - strlen(it.key), it.key ) == 0 &&
+            it.val != NULL &&
+            json_object_get_type(it.val) == json_type_object )
+        {
+            poItemsDef = it.val;
+            break;
+        }
+    }
+    if( poItemsDef == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot find path for %s", m_osItemsURL.c_str());
+        json_object_put(poSpec);
+        return;
+    }
+
+    json_object* poSchema = json_ex_get_object_by_path(poItemsDef, "get.responses.200.schema");
+    if( poSchema == NULL || json_object_get_type(poSchema) != json_type_object )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot find schema for %s", m_osItemsURL.c_str());
+        json_object_put(poSpec);
+        return;
+    }
+    poSchema = ResolveRefIfNecessary(poSchema, poSpec);
+    if( poSchema == NULL )
+    {
+        json_object_put(poSpec);
+        return;
+    }
+
+/* Parse:
+    "ItemPage": {
+      "type": "object",
+      "allOf": [
+        {
+          "$ref": "#/definitions/GeoJSONFeatureCollection"
+        },
+        {
+          "required": [
+            "features",
+            "_links"
+          ],
+          "type": "object",
+          "properties": {
+            "_links": {
+              "$ref": "#/definitions/PageLinks"
+            },
+            "features": {
+              "items": {
+                "$ref": "#/definitions/Item"
+              },
+              "type": "array"
+            }
+          }
+        }
+      ]
+    }
+*/
+    json_object* poProperties = json_object_object_get(poSchema, "properties");
+    if( poProperties == NULL )
+    {
+        json_object* poAllOf = json_object_object_get(poSchema, "allOf");
+        if( poAllOf == NULL || json_object_get_type(poAllOf) != json_type_array )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                    "Cannot find ItemPage allOf for %s", m_osItemsURL.c_str());
+            json_object_put(poSpec);
+            return;
+        }
+
+        const int nAllOfSize = json_object_array_length(poAllOf);
+        for(int i=0;i<nAllOfSize;i++)
+        {
+            json_object* poAllOfItem = json_object_array_get_idx(poAllOf, i);
+            if( poAllOfItem != NULL && json_object_get_type(poAllOfItem) == json_type_object )
+            {
+                poProperties = json_object_object_get(poAllOfItem, "properties");
+                if( poProperties != NULL )
+                    break;
+            }
+        }
+    }
+
+    if( poProperties == NULL || json_object_get_type(poProperties) != json_type_object )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot find ItemPage properties for %s", m_osItemsURL.c_str());
+        json_object_put(poSpec);
+        return;
+    }
+
+    json_object* poItems = json_ex_get_object_by_path(poProperties, "features.items");
+    if( poItems == NULL || json_object_get_type(poItems) != json_type_object )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot find ItemPage properties.features.items for %s", m_osItemsURL.c_str());
+        json_object_put(poSpec);
+        return;
+    }
+    poItems = ResolveRefIfNecessary(poItems, poSpec);
+    if( poItems == NULL )
+    {
+        json_object_put(poSpec);
+        return;
+    }
+
+
+    // Look for parameters (fields that can be queried)
+    json_object* poParameters = json_ex_get_object_by_path(poItemsDef, "get.parameters");
+    if( poParameters == NULL || json_object_get_type(poParameters) != json_type_array )
+    {
+        CPLDebug("PLSCENES", "No queryable parameters found");
+    }
+    else
+    {
+        const int nParameters = json_object_array_length(poParameters);
+        for(int i=0;i<nParameters;i++)
+        {
+            json_object* poParameter = json_object_array_get_idx(poParameters, i);
+            if( poParameter == NULL || json_object_get_type(poParameter) != json_type_object )
+                continue;
+            poParameter = ResolveRefIfNecessary(poParameter, poSpec);
+            if( poParameter == NULL )
+                continue;
+            json_object* poName = json_object_object_get(poParameter, "name");
+            if( poName == NULL || json_object_get_type(poName) != json_type_string )
+                continue;
+            const char* pszName = json_object_get_string(poName);
+            json_object* poIn = json_object_object_get(poParameter, "in");
+            if( poIn == NULL || json_object_get_type(poIn) != json_type_string )
+                continue;
+            const char* pszIn = json_object_get_string(poIn);
+            if( !EQUAL(pszIn, "query") )
+                continue;
+            if( EQUAL(pszName, "_sort") )
+            {
+                // TODO
+            }
+            else
+            {
+                m_oSetQueriable.insert(pszName);
+            }
+        }
+    }
+
+
+/* Parse:
+    "Item": {
+      "type": "object",
+      "allOf": [
+        {
+          "$ref": "#/definitions/GeoJSONFeature"
+        },
+        {
+          "required": [
+            "id",
+            "properties",
+            "_links"
+          ],
+          "type": "object",
+          "properties": {
+            "_embeds": {
+              "$ref": "#/definitions/ItemEmbeds"
+            },
+            "_links": {
+              "$ref": "#/definitions/ItemLinks"
+            },
+            "id": {
+              "type": "string",
+              "description": "Identifier of this Item.\n"
+            },
+            "properties": {
+              "$ref": "#/definitions/ItemProperties"
+            }
+          }
+        }
+      ]
+    },
+*/
+
+    poProperties = json_object_object_get(poItems, "properties");
+    if( poProperties == NULL )
+    {
+        json_object* poAllOf = json_object_object_get(poItems, "allOf");
+        if( poAllOf == NULL || json_object_get_type(poAllOf) != json_type_array )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                    "Cannot find Item allOf for %s", m_osItemsURL.c_str());
+            json_object_put(poSpec);
+            return;
+        }
+
+        const int nItemsAllOfSize = json_object_array_length(poAllOf);
+        for(int i=0;i<nItemsAllOfSize;i++)
+        {
+            json_object* poAllOfItem = json_object_array_get_idx(poAllOf, i);
+            if( poAllOfItem != NULL && json_object_get_type(poAllOfItem) == json_type_object )
+            {
+                poProperties = json_object_object_get(poAllOfItem, "properties");
+                if( poProperties != NULL )
+                    break;
+            }
+        }
+    }
+
+    if( poProperties == NULL || json_object_get_type(poProperties) != json_type_object )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot find Item properties for %s", m_osItemsURL.c_str());
+        json_object_put(poSpec);
+        return;
+    }
+
+    CPLString osPropertiesDesc = "{";
+
+    json_object* poId = json_object_object_get(poProperties, "id");
+    if( poId != NULL )
+    {
+        json_object_object_add(poId, "src_field", json_object_new_string("id") );
+        json_object_object_add(poId, "server_queryable", json_object_new_boolean(TRUE) );
+
+        osPropertiesDesc += "\"id\"";
+        osPropertiesDesc += ":";
+        osPropertiesDesc += json_object_to_json_string(poId);
+
+        OGRFieldDefn oFieldDefn("id", OFTString);
+        RegisterField(&oFieldDefn, NULL, "id");
+    }
+
+    json_object* poLinks = json_object_object_get(poProperties, "_links");
+    if( poLinks != NULL && json_object_get_type(poLinks) == json_type_object )
+        poLinks = ResolveRefIfNecessary(poLinks, poSpec);
+    else
+        poLinks = NULL;
+    if( poLinks != NULL )
+    {
+        ParseProperties(poLinks, poSpec, osPropertiesDesc, "_links");
+    }
+
+    json_object* poEmbeds = json_object_object_get(poProperties, "_embeds");
+
+    poProperties = json_object_object_get(poProperties, "properties");
+    if( poProperties == NULL || json_object_get_type(poProperties) != json_type_object )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot find Item properties.properties for %s", m_osItemsURL.c_str());
+        json_object_put(poSpec);
+        return;
+    }
+
+    poProperties = ResolveRefIfNecessary(poProperties, poSpec);
+    if( poProperties == NULL )
+    {
+        json_object_put(poSpec);
+        return;
+    }
+
+    ParseProperties(poProperties, poSpec, osPropertiesDesc, "properties");
+
+    if( poEmbeds != NULL && json_object_get_type(poEmbeds) == json_type_object )
+        poEmbeds = ResolveRefIfNecessary(poEmbeds, poSpec);
+    else
+        poEmbeds = NULL;
+    if( poEmbeds != NULL )
+    {
+        ParseEmbeds(poEmbeds, poSpec, osPropertiesDesc);
+    }
+
+    osPropertiesDesc += "}";
+
+    // Prettify description
+    json_tokener* jstok = json_tokener_new();
+    json_object* poPropertiesDesc = json_tokener_parse_ex(jstok, osPropertiesDesc, -1);
+    if( jstok->err == json_tokener_success)
+    {
+        osPropertiesDesc = json_object_to_json_string_ext( poPropertiesDesc, JSON_C_TO_STRING_PRETTY );
+        json_object_put(poPropertiesDesc);
+    }
+    json_tokener_free(jstok);
+
+    SetMetadataItem("FIELDS_DESCRIPTION", osPropertiesDesc.c_str());
+
+    json_object_put(poSpec);
+}
+
+/************************************************************************/
+/*                             GetMetadata()                            */
+/************************************************************************/
+
+char **OGRPLScenesV1Layer::GetMetadata( const char * pszDomain  )
+{
+    if( pszDomain == NULL || EQUAL(pszDomain, "") )
+    {
+        EstablishLayerDefn();
+    }
+    return OGRLayer::GetMetadata(pszDomain);
+}
+
+/************************************************************************/
+/*                           GetMetadataItem()                          */
+/************************************************************************/
+
+const char *OGRPLScenesV1Layer::GetMetadataItem( const char * pszName, const char* pszDomain )
+{
+    if( pszDomain == NULL || EQUAL(pszDomain, "") )
+    {
+        EstablishLayerDefn();
+    }
+    return OGRLayer::GetMetadataItem(pszName, pszDomain);
+}
+
+/************************************************************************/
+/*                      OGRPLScenesV1LayerGetFieldType()                */
+/************************************************************************/
+
+static OGRFieldType OGRPLScenesV1LayerGetFieldType(json_object* poObj,
+                                                   const char* pszJSonFieldName )
+{
+    json_object* poType = json_object_object_get(poObj, "type");
+    OGRFieldType eType = OFTString;
+    if( poType != NULL && json_object_get_type(poType) == json_type_string )
+    {
+        const char* pszType = json_object_get_string(poType);
+        if( EQUAL(pszType, "string") )
+            eType = OFTString;
+        else if( EQUAL(pszType, "number") )
+            eType = OFTReal;
+        else if( EQUAL(pszType, "integer") )
+            eType = OFTInteger;
+        else
+        {
+            CPLDebug("PLSCENES", "Unknown type '%s' for '%s'",
+                      pszType, pszJSonFieldName);
+        }
+        json_object* poFormat = json_object_object_get(poObj, "format");
+        if( poFormat != NULL && json_object_get_type(poFormat) == json_type_string )
+        {
+            const char* pszFormat = json_object_get_string(poFormat);
+            if( EQUAL(pszFormat, "date-time") )
+                eType = OFTDateTime;
+            else if( EQUAL(pszFormat, "int32") )
+                eType = OFTInteger;
+            else if( EQUAL(pszFormat, "int64") )
+                eType = OFTInteger64;
+            else if( EQUAL(pszFormat, "float") )
+                eType = OFTReal;
+            else
+            {
+                CPLDebug("PLSCENES", "Unknown type '%s' for '%s'",
+                          pszFormat, pszJSonFieldName);
+            }
+        }
+    }
+    return eType;
+}
+
+/************************************************************************/
+/*                           ParseProperties()                          */
+/************************************************************************/
+
+void OGRPLScenesV1Layer::ParseProperties(json_object* poProperties,
+                                         json_object* poSpec,
+                                         CPLString& osPropertiesDesc,
+                                         const char* pszCategory)
+{
+    json_object* poAllOf = json_object_object_get(poProperties, "allOf");
+    if( poAllOf != NULL && json_object_get_type(poAllOf) == json_type_array )
+    {
+        const int nAllOfSize = json_object_array_length(poAllOf);
+        for(int i=0;i<nAllOfSize;i++)
+        {
+            json_object* poAllOfItem = json_object_array_get_idx(poAllOf, i);
+            if( poAllOfItem != NULL && json_object_get_type(poAllOfItem) == json_type_object )
+            {
+                poAllOfItem = ResolveRefIfNecessary(poAllOfItem, poSpec);
+                if( poAllOfItem != NULL )
+                    ParseProperties(poAllOfItem, poSpec, osPropertiesDesc, pszCategory);
+            }
+        }
+        return;
+    }
+
+    poProperties = json_object_object_get(poProperties, "properties");
+    if( poProperties == NULL || json_object_get_type(poProperties) != json_type_object )
+        return;
+
+    json_object_iter it;
+    it.key = NULL;
+    it.val = NULL;
+    it.entry = NULL;
+    json_object_object_foreachC( poProperties, it )
+    {
+        if( it.val != NULL && json_object_get_type(it.val) == json_type_object )
+        {
+            const char* pszJSonFieldName = it.key;
+            const char* pszOGRFieldName = pszJSonFieldName;
+            if( EQUAL(pszCategory, "_links") )
+            {
+                if( EQUAL(pszJSonFieldName, "_self") )
+                    pszOGRFieldName = "self_link";
+                else if( EQUAL(pszJSonFieldName, "assets") )
+                    pszOGRFieldName = "assets_link";
+            }
+            else if( strstr(pszOGRFieldName, "catalog::") == pszOGRFieldName &&
+                m_poFeatureDefn->GetFieldIndex(pszOGRFieldName + strlen("catalog::")) < 0 )
+            {
+                pszOGRFieldName += strlen("catalog::");
+            }
+
+            json_object* poKey = json_object_new_string(pszOGRFieldName);
+            const char* pszKeySerialized = json_object_to_json_string(poKey);
+            if( osPropertiesDesc != "{" )
+                osPropertiesDesc += ",";
+            osPropertiesDesc += pszKeySerialized;
+            osPropertiesDesc += ":";
+            json_object_put(poKey);
+
+            json_object_object_add( it.val, "src_field",
+                json_object_new_string( (CPLString(pszCategory) + CPLString(".") + pszJSonFieldName).c_str() ) );
+
+             json_object_object_add( it.val, "server_queryable",
+                json_object_new_boolean( EQUAL(pszCategory, "properties") &&
+                    m_oSetQueriable.find(pszJSonFieldName) != m_oSetQueriable.end() ) );
+
+            osPropertiesDesc += json_object_to_json_string(it.val);
+
+            const OGRFieldType eType =
+                  OGRPLScenesV1LayerGetFieldType(it.val, pszJSonFieldName);
+            OGRFieldDefn oFieldDefn(pszOGRFieldName, eType);
+            RegisterField(&oFieldDefn,
+                          EQUAL(pszCategory, "_links") ? NULL : pszJSonFieldName,
+                          (CPLString(pszCategory) + CPLString(".") + pszJSonFieldName).c_str());
+        }
+    }
+}
+
+/************************************************************************/
+/*                           ParseEmbeds()                          */
+/************************************************************************/
+
+void OGRPLScenesV1Layer::ParseEmbeds(json_object* poProperties,
+                                         json_object* poSpec,
+                                         CPLString& osPropertiesDesc)
+{
+/*
+    "ItemEmbeds": {
+      "properties": {
+        "assets": {
+          "additionalProperties": {
+            "$ref": "#/definitions/ItemAsset"
+          },
+          "type": "object"
+        }
+      },
+      "type": "object"
+    },
+*/
+    json_object* poAddProperties = json_ex_get_object_by_path(poProperties, "properties.assets.additionalProperties");
+    if( poAddProperties == NULL || json_object_get_type(poAddProperties) != json_type_object )
+        return;
+    poAddProperties = ResolveRefIfNecessary(poAddProperties, poSpec);
+    if( poAddProperties == NULL )
+      return;
+
+/*
+    "ItemAsset": {
+      "properties": {
+        "_links": {
+          "$ref": "#/definitions/SelfLink"
+        },
+        "category_id": {
+          "description": "Category identifier of this ItemAsset.",
+          "type": "string"
+        },
+        "file": {
+          "description": "RFC 3986 URI representing a location that will either directly serve the underlying asset data, or redirect to a location that will. A client must never attempt to construct this URI, as only its behavior is governed by this specification, not its location. In the event that a 202 is returned from a GET request against this URI, the response's `X-Retry-After` header indicates how long the client should wait before reattempting the request.",
+          "type": "string"
+        },
+        "mimetype": {
+          "description": "The MIME type of the underlying asset file.",
+          "type": "string"
+        }
+      }
+*/
+    poProperties = json_object_object_get(poAddProperties, "properties");
+    if( poProperties == NULL || json_object_get_type(poProperties) != json_type_object )
+        return;
+
+    bool bFoundLinks = false;
+    for(size_t i = 0; i < m_aoAssetCategories.size(); i++ )
+    {
+        json_object_iter it;
+        it.key = NULL;
+        it.val = NULL;
+        it.entry = NULL;
+        json_object_object_foreachC( poProperties, it )
+        {
+            if( it.val != NULL && json_object_get_type(it.val) == json_type_object )
+            {
+                const char* pszJSonFieldName = it.key;
+                if( strcmp(pszJSonFieldName, "category_id") == 0 )
+                  continue;
+                const char* pszOGRFieldName;
+                CPLString osSrcField(CPLString("_embeds.assets.") + m_aoAssetCategories[i] + CPLString("."));
+                json_object* poLinksRef = NULL;
+                if( EQUAL(pszJSonFieldName, "_links") &&
+                    (bFoundLinks ||
+                     ((poLinksRef = json_object_object_get( it.val, "$ref" )) != NULL &&
+                     json_object_get_type(poLinksRef) == json_type_string &&
+                     strcmp(json_object_get_string(poLinksRef), "#/definitions/SelfLink") == 0)) )
+                {
+                    bFoundLinks = true;
+                    pszOGRFieldName = CPLSPrintf("asset_%s_self_link", m_aoAssetCategories[i].c_str());
+                    osSrcField += "_links._self";
+                }
+                else
+                {
+                    pszOGRFieldName = CPLSPrintf("asset_%s_%s", m_aoAssetCategories[i].c_str(), pszJSonFieldName);
+                    osSrcField += pszJSonFieldName;
+                }
+                json_object* poKey = json_object_new_string(pszOGRFieldName);
+                const char* pszKeySerialized = json_object_to_json_string(poKey);
+                if( osPropertiesDesc != "{" )
+                    osPropertiesDesc += ",";
+                osPropertiesDesc += pszKeySerialized;
+                osPropertiesDesc += ":";
+                json_object_put(poKey);
+
+                if( EQUAL(pszJSonFieldName, "_links") && bFoundLinks )
+                {
+                    json_object_object_del( it.val, "$ref" );
+                    json_object_object_add( it.val, "description",
+                            json_object_new_string("RFC 3986 URI representing the canonical location of this asset.") );
+                    json_object_object_add( it.val, "type", json_object_new_string("string") );
+                }
+
+                json_object_object_add( it.val, "src_field",
+                    json_object_new_string( osSrcField.c_str() ) );
+
+                json_object_object_add( it.val, "server_queryable",
+                                        json_object_new_boolean( FALSE ) );
+
+                osPropertiesDesc += json_object_to_json_string(it.val);
+
+                const OGRFieldType eType =
+                  OGRPLScenesV1LayerGetFieldType(it.val, pszJSonFieldName);
+                OGRFieldDefn oFieldDefn(pszOGRFieldName, eType);
+                RegisterField(&oFieldDefn,
+                              NULL,
+                              osSrcField.c_str());
+            }
+        }
+    }
+}
+
+/************************************************************************/
+/*                              GetNextPage()                           */
+/************************************************************************/
+
+bool OGRPLScenesV1Layer::GetNextPage()
+{
+    if( m_poPageObj != NULL )
+        json_object_put(m_poPageObj);
+    m_poPageObj = NULL;
+    m_poFeatures = NULL;
+    m_nFeatureIdx = 0;
+
+    if( m_osRequestURL.size() == 0 )
+    {
+        m_bEOF = true;
+        return false;
+    }
+
+    json_object* poObj = m_poDS->RunRequest(m_osRequestURL);
+    if( poObj == NULL )
+    {
+        m_bEOF = true;
+        return false;
+    }
+
+    json_object* poFeatures = json_object_object_get(poObj, "features");
+    if( poFeatures == NULL ||
+        json_object_get_type(poFeatures) != json_type_array ||
+        json_object_array_length(poFeatures) == 0 )
+    {
+        // If this is a single item, then wrap it in a features array
+        json_object* poProperties = json_object_object_get(poObj, "properties");
+        if( poProperties != NULL )
+        {
+            m_poPageObj = json_object_new_object();
+            poFeatures = json_object_new_array();
+            json_object_array_add(poFeatures, poObj);
+            json_object_object_add(m_poPageObj, "features", poFeatures);
+            poObj = m_poPageObj;
+        }
+        else
+        {
+            json_object_put(poObj);
+            m_bEOF = true;
+            return false;
+        }
+    }
+
+    m_poPageObj = poObj;
+    m_poFeatures = poFeatures;
+
+    // Get URL of next page
+    m_osNextURL = "";
+    json_object* poLinks = json_object_object_get(poObj, "_links");
+    if( poLinks && json_object_get_type(poLinks) == json_type_object )
+    {
+        json_object* poNext = json_object_object_get(poLinks, "_next");
+        if( poNext && json_object_get_type(poNext) == json_type_string )
+        {
+            m_osNextURL = json_object_get_string(poNext);
+        }
+    }
+
+    return true;
+}
+
+/************************************************************************/
+/*                             ResetReading()                           */
+/************************************************************************/
+
+void OGRPLScenesV1Layer::ResetReading()
+{
+    m_bEOF = false;
+
+    if( m_poFeatures != NULL && m_bStillInFirstPage )
+        m_nFeatureIdx = 0;
+    else
+        m_poFeatures = NULL;
+    m_nNextFID = 1;
+    m_bStillInFirstPage = true;
+    m_osRequestURL = BuildRequestURL(false);
+}
+
+/************************************************************************/
+/*                          BuildRequestURL()                           */
+/************************************************************************/
+
+CPLString OGRPLScenesV1Layer::BuildRequestURL(bool bForHits)
+{
+    CPLString osURL = m_osItemsURL;
+
+    if( bForHits )
+        osURL += "?_page_size=0";
+    else
+    {
+        osURL += "?_embeds=features.*.assets";
+        if( m_nPageSize > 0 )
+            osURL += CPLSPrintf("&_page_size=%d", m_nPageSize);
+    }
+
+    if( m_poFilterGeom != NULL )
+    {
+        OGREnvelope sEnvelope;
+        m_poFilterGeom->getEnvelope(&sEnvelope);
+        if( !(sEnvelope.MinX <= -180 && sEnvelope.MinY <= -90 &&
+              sEnvelope.MaxX >= 180 && sEnvelope.MaxY >= 90) )
+        {
+            char* pszWKT = NULL;
+            if( sEnvelope.MinX == sEnvelope.MaxX && sEnvelope.MinY == sEnvelope.MaxY )
+            {
+                pszWKT = CPLStrdup(CPLSPrintf("POINT(%.18g %.18g)",
+                                            sEnvelope.MinX, sEnvelope.MinY));
+            }
+            else
+                m_poFilterGeom->exportToWkt(&pszWKT);
+
+            osURL += "&geometry=";
+            char* pszWKTEscaped = CPLEscapeString(pszWKT, -1, CPLES_URL);
+            osURL += pszWKTEscaped;
+            CPLFree(pszWKTEscaped);
+            CPLFree(pszWKT);
+        }
+    }
+
+    if( m_osFilterURLPart.size() )
+    {
+        if( m_osFilterURLPart[0] == '&' )
+            osURL += m_osFilterURLPart;
+        else
+            osURL = m_osItemsURL + m_osFilterURLPart + "?_embeds=assets";
+    }
+
+    return osURL;
+}
+
+/************************************************************************/
+/*                          SetSpatialFilter()                          */
+/************************************************************************/
+
+void OGRPLScenesV1Layer::SetSpatialFilter(  OGRGeometry *poGeomIn )
+{
+    m_poFeatures = NULL;
+
+    if( poGeomIn )
+    {
+        OGREnvelope sEnvelope;
+        poGeomIn->getEnvelope(&sEnvelope);
+        if( sEnvelope.MinX == sEnvelope.MaxX && sEnvelope.MinY == sEnvelope.MaxY )
+        {
+            OGRPoint p(sEnvelope.MinX, sEnvelope.MinY);
+            InstallFilter(&p);
+        }
+        else
+            InstallFilter( poGeomIn );
+    }
+    else
+        InstallFilter( poGeomIn );
+
+    ResetReading();
+}
+
+/************************************************************************/
+/*                          FlattendAndOperands()                       */
+/************************************************************************/
+
+/*((a AND (b OR c)) AND d) --> [a, b OR c, d] */
+
+void OGRPLScenesV1Layer::FlattendAndOperands(swq_expr_node* poNode,
+                                             std::vector<swq_expr_node*>& oVector)
+{
+    if( poNode->eNodeType == SNT_OPERATION && poNode->nOperation == SWQ_AND &&
+        poNode->nSubExprCount == 2 )
+    {
+        FlattendAndOperands(poNode->papoSubExpr[0], oVector);
+        FlattendAndOperands(poNode->papoSubExpr[1], oVector);
+    }
+    else
+    {
+        oVector.push_back(poNode);
+    }
+}
+
+/************************************************************************/
+/*                      OGRPLScenesV1ParseDateTime()                    */
+/************************************************************************/
+
+static bool OGRPLScenesV1ParseDateTime(const char* pszValue,
+                                       int& nYear, int &nMonth, int &nDay,
+                                       int& nHour, int &nMinute, int &nSecond)
+{
+    return ( sscanf(pszValue,"%04d/%02d/%02d %02d:%02d:%02d",
+                    &nYear, &nMonth, &nDay, &nHour, &nMinute, &nSecond) >= 3 ||
+             sscanf(pszValue,"%04d-%02d-%02dT%02d:%02d:%02d",
+                    &nYear, &nMonth, &nDay, &nHour, &nMinute, &nSecond) >= 3 );
+}
+
+/************************************************************************/
+/*                    OGRPLScenesV1LayerFormatValue()                   */
+/************************************************************************/
+
+static const char* OGRPLScenesV1LayerFormatValue(const swq_expr_node* poNode)
+{
+    if (poNode->field_type == SWQ_FLOAT)
+        return CPLSPrintf("%.8f", poNode->float_value);
+    else if (poNode->field_type == SWQ_INTEGER)
+        return CPLSPrintf(CPL_FRMT_GIB, poNode->int_value);
+    else if (poNode->field_type == SWQ_STRING)
+        return poNode->string_value;
+    else if (poNode->field_type == SWQ_TIMESTAMP)
+    {
+        int nYear = 0, nMonth = 0, nDay = 0, nHour = 0, nMinute = 0, nSecond = 0;
+        if( OGRPLScenesV1ParseDateTime(poNode->string_value,
+                    nYear, nMonth, nDay, nHour, nMinute, nSecond)  )
+        {
+            return CPLSPrintf("%04d-%02d-%02dT%02d:%02d:%02dZ",
+                                    nYear, nMonth, nDay, nHour, nMinute, nSecond);
+        }
+        else
+        {
+            return poNode->string_value;
+        }
+    }
+    else
+        return ""; /* should not happen */
+}
+
+/************************************************************************/
+/*                          IsSimpleComparison()                        */
+/************************************************************************/
+
+bool OGRPLScenesV1Layer::IsSimpleComparison(const swq_expr_node* poNode)
+{
+    return  poNode->eNodeType == SNT_OPERATION &&
+            (poNode->nOperation == SWQ_EQ ||
+             poNode->nOperation == SWQ_LT ||
+             poNode->nOperation == SWQ_LE ||
+             poNode->nOperation == SWQ_GT ||
+             poNode->nOperation == SWQ_GE) &&
+             poNode->nSubExprCount == 2 &&
+             poNode->papoSubExpr[0]->eNodeType == SNT_COLUMN &&
+             poNode->papoSubExpr[1]->eNodeType == SNT_CONSTANT &&
+             m_oMapFieldIdxToQueriableJSonFieldName.find(poNode->papoSubExpr[0]->field_index) !=
+                                m_oMapFieldIdxToQueriableJSonFieldName.end();
+}
+
+/************************************************************************/
+/*                  OGRPLScenesV1LayerExprComparator()                  */
+/************************************************************************/
+
+/* We want to have things sorted like :
+    varA >= xxx AND varA <= yyy AND varB >= zzz AND varB <= ttt AND (other_expr_not_server_side_compatible)
+    so as to be able to generate a filter like:
+    varA=[xxx:yyy]&varB=[zzz:ttt]
+*/
+
+struct OGRPLScenesV1LayerExprComparator
+{
+    OGRPLScenesV1Layer* m_poLayer;
+
+    OGRPLScenesV1LayerExprComparator(OGRPLScenesV1Layer* poLayer) :
+                m_poLayer(poLayer) {}
+
+    bool operator() (const swq_expr_node* poNode1,
+                                       const swq_expr_node* poNode2)
+    {
+        const bool bIsSimpleComparison1 = m_poLayer->IsSimpleComparison(poNode1);
+        const bool bIsSimpleComparison2 = m_poLayer->IsSimpleComparison(poNode2);
+
+        if( bIsSimpleComparison1 && bIsSimpleComparison2 )
+        {
+            if( poNode1->papoSubExpr[0]->field_index == poNode2->papoSubExpr[0]->field_index )
+            {
+                return (poNode1->nOperation == SWQ_GT || poNode1->nOperation == SWQ_GE) &&
+                       (poNode2->nOperation == SWQ_LT || poNode2->nOperation == SWQ_LE);
+            }
+            return poNode1->papoSubExpr[0]->field_index <
+                                            poNode2->papoSubExpr[0]->field_index;
+        }
+        else if( bIsSimpleComparison1 )
+            return true;
+        else
+            return false;
+    }
+};
+
+/************************************************************************/
+/*                             BuildFilter()                            */
+/************************************************************************/
+
+CPLString OGRPLScenesV1Layer::BuildFilter(swq_expr_node* poNode)
+{
+    std::vector<swq_expr_node*> oVector;
+    FlattendAndOperands(poNode, oVector);
+    OGRPLScenesV1LayerExprComparator oComparator(this);
+    std::sort(oVector.begin(), oVector.end(), oComparator);
+
+    bool bOnlyServerSide = true;
+    CPLString osFilter = "";
+    for(size_t i=0; i<oVector.size(); i++)
+    {
+        if( !IsSimpleComparison( oVector[i] ) )
+        {
+            bOnlyServerSide = false;
+            // We break since that, given the sorting, there can not be
+            // a following simple comparison
+            break;
+        }
+
+        const int iFieldIdx = oVector[i]->papoSubExpr[0]->field_index;
+        const CPLString& osJSonName = m_oMapFieldIdxToQueriableJSonFieldName[iFieldIdx];
+
+        if( i+1 < oVector.size() && IsSimpleComparison( oVector[i+1] ) &&
+            iFieldIdx == oVector[i+1]->papoSubExpr[0]->field_index )
+        {
+            const int nOp1 = oVector[i]->nOperation;
+            const int nOp2 = oVector[i+1]->nOperation;
+            if( !((nOp1 == SWQ_GT || nOp1 == SWQ_GE ) && (nOp2 == SWQ_LT || nOp2 == SWQ_LE)) )
+            {
+                CPLDebug("PLSCENES", "Field %s used but not with >/>= AND </<= comparisons",
+                            osJSonName.c_str());
+                bOnlyServerSide = false;
+                continue;
+            }
+            if( i + 2 < oVector.size() && iFieldIdx == oVector[i+2]->papoSubExpr[0]->field_index )
+            {
+                CPLDebug("PLSCENES", "Field %s used more than twice in same expression",
+                            osJSonName.c_str());
+                bOnlyServerSide = false;
+                continue;
+            }
+
+            if( osFilter.size() )
+                osFilter += "&";
+
+            osFilter += osJSonName;
+            osFilter += "=[";
+            osFilter += OGRPLScenesV1LayerFormatValue(oVector[i]->papoSubExpr[1]);
+            osFilter += ":";
+            osFilter += OGRPLScenesV1LayerFormatValue(oVector[i+1]->papoSubExpr[1]);
+            osFilter += "]";
+
+            i++;
+        }
+        else if( oVector[i]->nOperation == SWQ_EQ )
+        {
+            if( osFilter.size() )
+                osFilter += "&";
+
+            osFilter += osJSonName;
+            osFilter += "=";
+
+            int nYear = 0, nMonth = 0, nDay = 0, nHour = 0, nMinute = 0, nSecond = 0;
+            if (oVector[i]->papoSubExpr[1]->field_type == SWQ_TIMESTAMP &&
+                OGRPLScenesV1ParseDateTime(oVector[i]->papoSubExpr[1]->string_value,
+                    nYear, nMonth, nDay, nHour, nMinute, nSecond)  )
+            {
+                osFilter += "[";
+                osFilter += OGRPLScenesV1LayerFormatValue(oVector[i]->papoSubExpr[1]);
+                osFilter += ":";
+                nSecond ++;
+                if( nSecond == 60 ) { nSecond = 0; nMinute ++; }
+                if( nMinute == 60 ) { nMinute = 0; nHour ++; }
+                if( nHour == 24 ) { nHour = 0; nDay ++; }
+                osFilter += CPLSPrintf("%04d-%02d-%02dT%02d:%02d:%02dZ",
+                                        nYear, nMonth, nDay, nHour, nMinute, nSecond);
+                osFilter += "]";
+            }
+            else
+            {
+                osFilter += OGRPLScenesV1LayerFormatValue(oVector[i]->papoSubExpr[1]);
+            }
+        }
+        else if( oVector[i]->nOperation == SWQ_GT || oVector[i]->nOperation == SWQ_GE )
+        {
+            if( osFilter.size() )
+                osFilter += "&";
+
+            osFilter += osJSonName;
+            osFilter += "=[";
+            osFilter += OGRPLScenesV1LayerFormatValue(oVector[i]->papoSubExpr[1]);
+            osFilter += ":]";
+        }
+        else if( oVector[i]->nOperation == SWQ_LT || oVector[i]->nOperation == SWQ_LE )
+        {
+            if( osFilter.size() )
+                osFilter += "&";
+
+            osFilter += osJSonName;
+            osFilter += "=[:";
+            osFilter += OGRPLScenesV1LayerFormatValue(oVector[i]->papoSubExpr[1]);
+            osFilter += "]";
+        }
+        else
+        {
+            CPLDebug("PLSCENES", "Should not happen");
+            bOnlyServerSide = false;
+            osFilter = "";
+            break;
+        }
+    }
+
+    if( osFilter.size() == 0 && !m_bFilterMustBeClientSideEvaluated )
+    {
+        m_bFilterMustBeClientSideEvaluated = true;
+        CPLDebug("PLSCENES",
+                 "Full filter will be evaluated on client side.");
+    }
+    else if( !bOnlyServerSide && !m_bFilterMustBeClientSideEvaluated )
+    {
+        m_bFilterMustBeClientSideEvaluated = true;
+        CPLDebug("PLSCENES",
+                 "Only part of the filter will be evaluated on server side.");
+    }
+
+    return osFilter;
+}
+
+/************************************************************************/
+/*                         SetAttributeFilter()                         */
+/************************************************************************/
+
+OGRErr OGRPLScenesV1Layer::SetAttributeFilter( const char *pszQuery )
+
+{
+    m_poFeatures = NULL;
+
+    OGRErr eErr = OGRLayer::SetAttributeFilter(pszQuery);
+
+    m_osFilterURLPart = "";
+    m_bFilterMustBeClientSideEvaluated = false;
+    if( m_poAttrQuery != NULL )
+    {
+        swq_expr_node* poNode = (swq_expr_node*) m_poAttrQuery->GetSWQExpr();
+
+        poNode->ReplaceBetweenByGEAndLERecurse();
+
+        if( poNode->eNodeType == SNT_OPERATION &&
+            poNode->nOperation == SWQ_EQ && poNode->nSubExprCount == 2 &&
+            poNode->papoSubExpr[0]->eNodeType == SNT_COLUMN &&
+            poNode->papoSubExpr[0]->field_index == m_poFeatureDefn->GetFieldIndex("id") &&
+            poNode->papoSubExpr[1]->eNodeType == SNT_CONSTANT &&
+            poNode->papoSubExpr[1]->field_type == SWQ_STRING )
+        {
+            m_osFilterURLPart = poNode->papoSubExpr[1]->string_value;
+        }
+        else
+        {
+            CPLString osFilter = BuildFilter(poNode);
+            if( osFilter.size() )
+            {
+                m_osFilterURLPart = "&";
+                m_osFilterURLPart += osFilter;
+            }
+        }
+    }
+
+    ResetReading();
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature *OGRPLScenesV1Layer::GetNextFeature()
+{
+    OGRFeature  *poFeature;
+
+    while( true )
+    {
+        poFeature = GetNextRawFeature();
+        if (poFeature == NULL)
+            return NULL;
+
+        if((m_poFilterGeom == NULL
+            || FilterGeometry( poFeature->GetGeometryRef() ) )
+        && (m_poAttrQuery == NULL
+            || m_poAttrQuery->Evaluate( poFeature )) )
+        {
+            return poFeature;
+        }
+        else
+            delete poFeature;
+    }
+}
+
+/************************************************************************/
+/*                            GetNextRawFeature()                       */
+/************************************************************************/
+
+OGRFeature* OGRPLScenesV1Layer::GetNextRawFeature()
+{
+    EstablishLayerDefn();
+    if( m_bEOF )
+        return NULL;
+
+    if( m_poFeatures == NULL )
+    {
+        if( !GetNextPage() )
+            return NULL;
+    }
+
+    if( m_nFeatureIdx == json_object_array_length(m_poFeatures) )
+    {
+        m_osRequestURL = m_osNextURL;
+        m_bStillInFirstPage = false;
+        if( !GetNextPage() )
+            return NULL;
+    }
+    json_object* poJSonFeature = json_object_array_get_idx(m_poFeatures, m_nFeatureIdx);
+    m_nFeatureIdx ++;
+    if( poJSonFeature == NULL || json_object_get_type(poJSonFeature) != json_type_object )
+    {
+        m_bEOF = true;
+        return NULL;
+    }
+
+    OGRFeature* poFeature = new OGRFeature(m_poFeatureDefn);
+    poFeature->SetFID(m_nNextFID++);
+
+    json_object* poJSonGeom = json_object_object_get(poJSonFeature, "geometry");
+    if( poJSonGeom != NULL && json_object_get_type(poJSonGeom) == json_type_object )
+    {
+        OGRGeometry* poGeom = OGRGeoJSONReadGeometry(poJSonGeom);
+        if( poGeom != NULL )
+        {
+            if( poGeom->getGeometryType() == wkbPolygon )
+            {
+                OGRMultiPolygon* poMP = new OGRMultiPolygon();
+                poMP->addGeometryDirectly(poGeom);
+                poGeom = poMP;
+            }
+            poGeom->assignSpatialReference(m_poSRS);
+            poFeature->SetGeometryDirectly(poGeom);
+        }
+    }
+
+    json_object* poId = json_object_object_get(poJSonFeature, "id");
+    if( poId != NULL && json_object_get_type(poId) == json_type_string )
+    {
+        std::map<CPLString, int>::iterator oIter = m_oMapPrefixedJSonFieldNameToFieldIdx.find("id");
+        if( oIter != m_oMapPrefixedJSonFieldNameToFieldIdx.end() )
+        {
+            const int iField = oIter->second;
+            poFeature->SetField(iField, json_object_get_string(poId));
+        }
+    }
+
+    for(int i=0;i<2;i++)
+    {
+        const char* pszFeaturePart = (i == 0) ? "properties": "_links";
+        json_object* poProperties = json_object_object_get(poJSonFeature, pszFeaturePart);
+        if( poProperties != NULL && json_object_get_type(poProperties) == json_type_object )
+        {
+            json_object_iter it;
+            it.key = NULL;
+            it.val = NULL;
+            it.entry = NULL;
+            json_object_object_foreachC( poProperties, it )
+            {
+                SetFieldFromPrefixedJSonFieldName(
+                    poFeature, CPLString(pszFeaturePart) + CPLString(".") + it.key,
+                    it.val);
+            }
+        }
+    }
+
+    json_object* poAssets = json_ex_get_object_by_path(poJSonFeature, "_embeds.assets");
+    if( poAssets != NULL && json_object_get_type(poAssets) == json_type_object )
+    {
+        json_object_iter itAsset;
+        itAsset.key = NULL;
+        itAsset.val = NULL;
+        itAsset.entry = NULL;
+        json_object_object_foreachC( poAssets, itAsset )
+        {
+            json_object* poAsset = itAsset.val;
+            if( poAsset != NULL && json_object_get_type(poAsset) == json_type_object )
+            {
+                json_object_iter it;
+                it.key = NULL;
+                it.val = NULL;
+                it.entry = NULL;
+                json_object_object_foreachC( poAsset, it )
+                {
+                    if( it.val == NULL ) continue;
+                    CPLString osPrefixedJSonFieldName("_embeds.assets." + CPLString(itAsset.key));
+                    if( strcmp(it.key, "_links") == 0 &&
+                        json_object_get_type(it.val) == json_type_object &&
+                        json_object_object_get(it.val, "_self") != NULL )
+                    {
+                        osPrefixedJSonFieldName += "._links._self";
+                        SetFieldFromPrefixedJSonFieldName(
+                            poFeature, osPrefixedJSonFieldName, json_object_object_get(it.val, "_self"));
+                    }
+                    else
+                    {
+                        osPrefixedJSonFieldName += "." + CPLString(it.key);
+                        SetFieldFromPrefixedJSonFieldName(
+                            poFeature, osPrefixedJSonFieldName, it.val);
+                    }
+                }
+            }
+        }
+    }
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                    SetFieldFromPrefixedJSonFieldName()               */
+/************************************************************************/
+
+void OGRPLScenesV1Layer::SetFieldFromPrefixedJSonFieldName(
+                                  OGRFeature* poFeature,
+                                  const CPLString& osPrefixedJSonFieldName,
+                                  json_object* poVal )
+{
+    std::map<CPLString, int>::iterator oIter = m_oMapPrefixedJSonFieldNameToFieldIdx.find(
+            osPrefixedJSonFieldName);
+    if( poVal != NULL && oIter != m_oMapPrefixedJSonFieldNameToFieldIdx.end() )
+    {
+        const int iField = oIter->second;
+        json_type eJSonType = json_object_get_type(poVal);
+        if( eJSonType == json_type_int )
+        {
+            poFeature->SetField(iField,
+                    static_cast<GIntBig>(json_object_get_int64(poVal)));
+        }
+        else if( eJSonType == json_type_double )
+        {
+            poFeature->SetField(iField, json_object_get_double(poVal));
+        }
+        else if( eJSonType == json_type_string )
+        {
+            poFeature->SetField(iField, json_object_get_string(poVal));
+        }
+    }
+}
+
+/************************************************************************/
+/*                          GetFeatureCount()                           */
+/************************************************************************/
+
+GIntBig OGRPLScenesV1Layer::GetFeatureCount(int bForce)
+{
+    if( m_nTotalFeatures > 0 && m_poFilterGeom == NULL && m_poAttrQuery == NULL )
+        return m_nTotalFeatures;
+
+    json_object* poRes = m_poDS->RunRequest(BuildRequestURL(true));
+    if( poRes != NULL )
+    {
+        json_object* poResultCount = json_object_object_get(poRes, "_result_count");
+        if( poResultCount != NULL && json_object_get_type(poResultCount) == json_type_int )
+        {
+            GIntBig nRes = static_cast<GIntBig>(json_object_get_int64(poResultCount));
+            json_object_put(poRes);
+            return nRes;
+        }
+        json_object_put(poRes);
+    }
+
+    return OGRLayer::GetFeatureCount(bForce);
+}
+
+/************************************************************************/
+/*                                GetExtent()                           */
+/************************************************************************/
+
+OGRErr OGRPLScenesV1Layer::GetExtent( OGREnvelope *psExtent, int bForce )
+{
+    if( m_poFilterGeom != NULL ||
+        ( m_nTotalFeatures > 0 && m_poFeatures != NULL &&
+          m_bStillInFirstPage &&
+          json_object_array_length(m_poFeatures) < m_nTotalFeatures) )
+    {
+        return OGRLayer::GetExtentInternal(0, psExtent, bForce);
+    }
+
+    psExtent->MinX = -180;
+    psExtent->MinY = -90;
+    psExtent->MaxX = 180;
+    psExtent->MaxY = 90;
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                              TestCapability()                        */
+/************************************************************************/
+
+int OGRPLScenesV1Layer::TestCapability(const char* pszCap)
+{
+    if( EQUAL(pszCap, OLCFastFeatureCount) )
+        return !m_bFilterMustBeClientSideEvaluated;
+    if( EQUAL(pszCap, OLCStringsAsUTF8) )
+        return TRUE;
+    return FALSE;
+}
diff --git a/ogr/ogrsf_frmts/rec/ll_recio.cpp b/ogr/ogrsf_frmts/rec/ll_recio.cpp
index baca46c..5de8242 100644
--- a/ogr/ogrsf_frmts/rec/ll_recio.cpp
+++ b/ogr/ogrsf_frmts/rec/ll_recio.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ll_recio.cpp 25185 2012-10-27 19:40:46Z rouault $
+ * $Id: ll_recio.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  EPIInfo .REC Reader
  * Purpose:  Implements low level REC reading API.
@@ -27,11 +27,11 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_rec.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "ogr_rec.h"
 
-CPL_CVSID("$Id: ll_recio.cpp 25185 2012-10-27 19:40:46Z rouault $");
+CPL_CVSID("$Id: ll_recio.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 static int nNextRecLine = 0;
 
@@ -57,13 +57,11 @@ int RECGetFieldCount( FILE * fp )
 /*                       RECGetFieldDefinition()                        */
 /************************************************************************/
 
-int RECGetFieldDefinition( FILE *fp, char *pszFieldname, 
+int RECGetFieldDefinition( FILE *fp, char *pszFieldname,
                            int *pnType, int *pnWidth, int *pnPrecision )
 
 {
     const char *pszLine = CPLReadLine( fp );
-    int         nTypeCode;
-    OGRFieldType eFType = OFTString;
 
     if( pszLine == NULL )
         return FALSE;
@@ -71,11 +69,13 @@ int RECGetFieldDefinition( FILE *fp, char *pszFieldname,
     if( strlen(pszLine) < 44 )
         return FALSE;
 
-    // Extract field width. 
+    // Extract field width.
     *pnWidth = atoi( RECGetField( pszLine, 37, 4 ) );
 
+    OGRFieldType eFType = OFTString;
+
     // Is this an real, integer or string field?  Default to string.
-    nTypeCode = atoi(RECGetField(pszLine,33,4));
+    int nTypeCode = atoi(RECGetField(pszLine,33,4));
     if( nTypeCode == 0 )
         eFType = OFTInteger;
     else if( nTypeCode > 100 && nTypeCode < 120 )
@@ -118,12 +118,12 @@ const char *RECGetField( const char *pszSrc, int nStart, int nWidth )
 {
     static char szWorkField[128];
     int         i;
-    
+
     strncpy( szWorkField, pszSrc+nStart-1, nWidth );
     szWorkField[nWidth] = '\0';
 
-    i = strlen(szWorkField)-1;
-    
+    i = (int)strlen(szWorkField)-1;
+
     while( i >= 0 && szWorkField[i] == ' ' )
         szWorkField[i--] = '\0';
 
@@ -153,7 +153,7 @@ int RECReadRecord( FILE *fp, char *pszRecord, int nRecordLength )
             return FALSE;
 
         // If the end-of-line markers is '?' the record is deleted.
-        iSegLen = strlen(pszLine);
+        iSegLen = (int)strlen(pszLine);
         if( pszLine[iSegLen-1] == '?' )
         {
             pszRecord[0] = '\0';
@@ -161,12 +161,12 @@ int RECReadRecord( FILE *fp, char *pszRecord, int nRecordLength )
             continue;
         }
 
-        // Strip off end-of-line '!' marker. 
-        if( pszLine[iSegLen-1] != '!' 
+        // Strip off end-of-line '!' marker.
+        if( pszLine[iSegLen-1] != '!'
             && pszLine[iSegLen-1] != '^' )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Apparent corrupt data line at line=%d", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Apparent corrupt data line at line=%d",
                       nNextRecLine );
             return FALSE;
         }
@@ -174,8 +174,8 @@ int RECReadRecord( FILE *fp, char *pszRecord, int nRecordLength )
         iSegLen--;
         if( nDataLen + iSegLen > nRecordLength )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Too much data for line at line %d.", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Too much data for line at line %d.",
                       nNextRecLine-1 );
             return FALSE;
         }
diff --git a/ogr/ogrsf_frmts/rec/ogr_rec.h b/ogr/ogrsf_frmts/rec/ogr_rec.h
index b27ff06..ff90da5 100644
--- a/ogr/ogrsf_frmts/rec/ogr_rec.h
+++ b/ogr/ogrsf_frmts/rec/ogr_rec.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_rec.h 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogr_rec.h 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Epi .REC Translator
  * Purpose:  Definition of classes for OGR .REC support.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_REC_H_INCLUDED
-#define _OGR_REC_H_INCLUDED
+#ifndef OGR_REC_H_INCLUDED
+#define OGR_REC_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 
@@ -36,7 +36,7 @@ class OGRRECDataSource;
 
 CPL_C_START
 int CPL_DLL RECGetFieldCount( FILE *fp);
-int CPL_DLL RECGetFieldDefinition( FILE *fp, char *pszFieldName, int *pnType, 
+int CPL_DLL RECGetFieldDefinition( FILE *fp, char *pszFieldName, int *pnType,
                                    int *pnWidth, int *pnPrecision );
 int CPL_DLL RECReadRecord( FILE *fp, char *pszRecBuf, int nRecordLength  );
 const char CPL_DLL *RECGetField( const char *pszSrc, int nStart, int nWidth );
@@ -65,7 +65,7 @@ class OGRRECLayer : public OGRLayer
     OGRFeature *        GetNextUnfilteredFeature();
 
   public:
-                        OGRRECLayer( const char *pszName, FILE *fp, 
+                        OGRRECLayer( const char *pszName, FILE *fp,
                                      int nFieldCount );
                         ~OGRRECLayer();
 
@@ -74,8 +74,6 @@ class OGRRECLayer : public OGRLayer
 
     OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
 
-    void                SetSpatialFilter( OGRGeometry * ) {}
-
     int                 TestCapability( const char * );
 
     int                 IsValid() { return bIsValid; }
@@ -97,11 +95,11 @@ class OGRRECDataSource : public OGRDataSource
                         ~OGRRECDataSource();
 
     int                 Open( const char * pszFilename );
-    
+
     const char          *GetName() { return pszName; }
     int                 GetLayerCount() { return 1; }
     OGRLayer            *GetLayer( int );
     int                 TestCapability( const char * );
 };
 
-#endif /* ndef _OGR_REC_H_INCLUDED */
+#endif /* ndef OGR_REC_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/rec/ogrrecdatasource.cpp b/ogr/ogrsf_frmts/rec/ogrrecdatasource.cpp
index 3febb84..0fb2841 100644
--- a/ogr/ogrsf_frmts/rec/ogrrecdatasource.cpp
+++ b/ogr/ogrsf_frmts/rec/ogrrecdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrrecdatasource.cpp 26243 2013-07-29 20:45:59Z rouault $
+ * $Id: ogrrecdatasource.cpp 33089 2016-01-22 15:02:53Z goatbar $
  *
  * Project:  Epiinfo .REC Translator
  * Purpose:  Implements OGRRECDataSource class
@@ -31,19 +31,16 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrrecdatasource.cpp 26243 2013-07-29 20:45:59Z rouault $");
+CPL_CVSID("$Id: ogrrecdatasource.cpp 33089 2016-01-22 15:02:53Z goatbar $");
 
 /************************************************************************/
 /*                          OGRRECDataSource()                          */
 /************************************************************************/
 
-OGRRECDataSource::OGRRECDataSource()
-
-{
-    poLayer = NULL;
-
-    pszName = NULL;
-}
+OGRRECDataSource::OGRRECDataSource() :
+    pszName(NULL),
+    poLayer(NULL)
+{}
 
 /************************************************************************/
 /*                         ~OGRRECDataSource()                          */
@@ -77,8 +74,8 @@ OGRLayer *OGRRECDataSource::GetLayer( int iLayer )
 {
     if( iLayer == 0 )
         return poLayer;
-    else
-        return NULL;
+
+    return NULL;
 }
 
 /************************************************************************/
@@ -89,32 +86,28 @@ int OGRRECDataSource::Open( const char * pszFilename )
 
 {
     pszName = CPLStrdup( pszFilename );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Verify that the extension is REC.                               */
 /* -------------------------------------------------------------------- */
     if( !(strlen(pszFilename) > 4 &&
           EQUAL(pszFilename+strlen(pszFilename)-4,".rec") ) )
         return FALSE;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Open the file.                                                  */
 /* -------------------------------------------------------------------- */
-    const char * pszLine;
-    FILE       * fp;
-
-    fp = VSIFOpen( pszFilename, "rb" );
+    FILE *fp = VSIFOpen( pszFilename, "rb" );
     if( fp == NULL )
         return FALSE;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read a line, and verify that it consists of at least one        */
 /*      field that is a number greater than zero.                       */
 /* -------------------------------------------------------------------- */
-    int  nFieldCount;
-    pszLine = CPLReadLine( fp );
+    const char * pszLine = CPLReadLine( fp );
 
-    nFieldCount = atoi(pszLine);
+    const int nFieldCount = atoi(pszLine);
     if( nFieldCount < 1 || nFieldCount > 1000 )
     {
         VSIFClose( fp );
diff --git a/ogr/ogrsf_frmts/rec/ogrrecdriver.cpp b/ogr/ogrsf_frmts/rec/ogrrecdriver.cpp
index a8cd38d..06baa14 100644
--- a/ogr/ogrsf_frmts/rec/ogrrecdriver.cpp
+++ b/ogr/ogrsf_frmts/rec/ogrrecdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrrecdriver.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogrrecdriver.cpp 33089 2016-01-22 15:02:53Z goatbar $
  *
  * Project:  REC Translator
  * Purpose:  Implements EpiInfo .REC driver.
@@ -30,7 +30,7 @@
 #include "ogr_rec.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrrecdriver.cpp 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: ogrrecdriver.cpp 33089 2016-01-22 15:02:53Z goatbar $");
 
 /************************************************************************/
 /*                                Open()                                */
@@ -39,15 +39,13 @@ CPL_CVSID("$Id: ogrrecdriver.cpp 27384 2014-05-24 12:28:12Z rouault $");
 static GDALDataset *OGRRECDriverOpen( GDALOpenInfo* poOpenInfo )
 
 {
-    OGRRECDataSource   *poDS;
-
     if( poOpenInfo->fpL == NULL ||
         !EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "REC") )
     {
         return NULL;
     }
 
-    poDS = new OGRRECDataSource();
+    OGRRECDataSource *poDS = new OGRRECDataSource();
     if( !poDS->Open( poOpenInfo->pszFilename ) )
     {
         delete poDS;
@@ -61,7 +59,7 @@ static GDALDataset *OGRRECDriverOpen( GDALOpenInfo* poOpenInfo )
         delete poDS;
         poDS = NULL;
     }
-    
+
     return poDS;
 }
 
@@ -72,21 +70,18 @@ static GDALDataset *OGRRECDriverOpen( GDALOpenInfo* poOpenInfo )
 void RegisterOGRREC()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "REC" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "REC" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "REC" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "rec" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "EPIInfo .REC " );
+    poDriver->SetDescription( "REC" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "rec" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "EPIInfo .REC " );
 
-        poDriver->pfnOpen = OGRRECDriverOpen;
+    poDriver->pfnOpen = OGRRECDriverOpen;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
 
diff --git a/ogr/ogrsf_frmts/rec/ogrreclayer.cpp b/ogr/ogrsf_frmts/rec/ogrreclayer.cpp
index 3648261..1952a08 100644
--- a/ogr/ogrsf_frmts/rec/ogrreclayer.cpp
+++ b/ogr/ogrsf_frmts/rec/ogrreclayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrreclayer.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogrreclayer.cpp 33089 2016-01-22 15:02:53Z goatbar $
  *
  * Project:  EPIInfo .REC Reader
  * Purpose:  Implements OGRRECLayer class.
@@ -27,11 +27,11 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_rec.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "ogr_rec.h"
 
-CPL_CVSID("$Id: ogrreclayer.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogrreclayer.cpp 33089 2016-01-22 15:02:53Z goatbar $");
 
 /************************************************************************/
 /*                            OGRRECLayer()                             */
@@ -40,34 +40,27 @@ CPL_CVSID("$Id: ogrreclayer.cpp 27745 2014-09-27 16:38:57Z goatbar $");
 /*      file pointer.                                                   */
 /************************************************************************/
 
-OGRRECLayer::OGRRECLayer( const char *pszLayerNameIn, 
-                          FILE * fp, int nFieldCountIn )
-
+OGRRECLayer::OGRRECLayer( const char *pszLayerNameIn,
+                          FILE * fp, int nFieldCountIn ) :
+  poFeatureDefn(new OGRFeatureDefn( pszLayerNameIn )),
+    fpREC(fp),
+    nStartOfData(0),
+    bIsValid(FALSE),
+    nFieldCount(0),
+    panFieldOffset(static_cast<int *>(CPLCalloc(sizeof(int),nFieldCountIn))),
+    panFieldWidth(static_cast<int *>(CPLCalloc(sizeof(int),nFieldCountIn))),
+    nRecordLength(0),
+    nNextFID(1)
 {
-    fpREC = fp;
-    bIsValid = FALSE;
-    nStartOfData = 0;
-
-    nNextFID = 1;
-
-    poFeatureDefn = new OGRFeatureDefn( pszLayerNameIn );
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
 
-    nFieldCount = 0;
-    panFieldOffset = (int *) CPLCalloc(sizeof(int),nFieldCountIn);
-    panFieldWidth = (int *) CPLCalloc(sizeof(int),nFieldCountIn);
-
 /* -------------------------------------------------------------------- */
 /*      Read field definition lines.                                    */
 /* -------------------------------------------------------------------- */
-    int         iField;
-
-    for( nFieldCount=0, iField = 0; iField < nFieldCountIn; iField++ )
+    for( int iField = 0; iField < nFieldCountIn; iField++ )
     {
         const char *pszLine = CPLReadLine( fp );
-        int         nTypeCode;
-        OGRFieldType eFType = OFTString;
 
         if( pszLine == NULL )
             return;
@@ -75,13 +68,14 @@ OGRRECLayer::OGRRECLayer( const char *pszLayerNameIn,
         if( strlen(pszLine) < 44 )
             return;
 
-        // Extract field width. 
+        // Extract field width.
         panFieldWidth[nFieldCount] = atoi( RECGetField( pszLine, 37, 4 ) );
         if( panFieldWidth[nFieldCount] < 0 )
             return;
 
         // Is this an real, integer or string field?  Default to string.
-        nTypeCode = atoi(RECGetField(pszLine,33,4));
+        int nTypeCode = atoi(RECGetField(pszLine,33,4));
+        OGRFieldType eFType = OFTString;
         if( nTypeCode == 12 )
             eFType = OFTInteger;
         else if( nTypeCode > 100 && nTypeCode < 120 )
@@ -100,7 +94,7 @@ OGRRECLayer::OGRRECLayer( const char *pszLayerNameIn,
 
         OGRFieldDefn oField( RECGetField( pszLine, 2, 10 ), eFType );
 
-        // Establish field offset. 
+        // Establish field offset.
         if( nFieldCount > 0 )
             panFieldOffset[nFieldCount]
                 = panFieldOffset[nFieldCount-1] + panFieldWidth[nFieldCount-1];
@@ -132,7 +126,7 @@ OGRRECLayer::OGRRECLayer( const char *pszLayerNameIn,
     nRecordLength = panFieldOffset[nFieldCount-1]+panFieldWidth[nFieldCount-1];
     bIsValid = TRUE;
 
-    nStartOfData = VSIFTell( fp );
+    nStartOfData = static_cast<int>(VSIFTell( fp ));
 }
 
 /************************************************************************/
@@ -145,10 +139,10 @@ OGRRECLayer::~OGRRECLayer()
     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     {
         CPLDebug( "REC", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
+                  static_cast<int>(m_nFeaturesRead),
                   poFeatureDefn->GetName() );
     }
-    
+
     if( fpREC != NULL )
         VSIFClose( fpREC );
 
@@ -166,7 +160,7 @@ OGRRECLayer::~OGRRECLayer()
 void OGRRECLayer::ResetReading()
 
 {
-    VSIFSeek( fpREC, nStartOfData, SEEK_SET );
+    CPL_IGNORE_RET_VAL(VSIFSeek( fpREC, nStartOfData, SEEK_SET ));
     nNextFID = 1;
 }
 
@@ -181,12 +175,11 @@ OGRFeature * OGRRECLayer::GetNextUnfilteredFeature()
 /*      Read and assemble the source data record.                       */
 /* -------------------------------------------------------------------- */
     int        nDataLen = 0;
-    char       *pszRecord = (char *) CPLMalloc(nRecordLength + 2 );
+    char       *pszRecord = static_cast<char *>(CPLMalloc(nRecordLength + 2 ));
 
     while( nDataLen < nRecordLength )
     {
         const char *pszLine = CPLReadLine( fpREC );
-        int         iSegLen;
 
         if( pszLine == NULL )
         {
@@ -201,7 +194,7 @@ OGRFeature * OGRRECLayer::GetNextUnfilteredFeature()
         }
 
         // If the end-of-line markers is '?' the record is deleted.
-        iSegLen = strlen(pszLine);
+        int iSegLen = static_cast<int>(strlen(pszLine));
         if( pszLine[iSegLen-1] == '?' )
         {
             pszRecord[0] = '\0';
@@ -209,12 +202,12 @@ OGRFeature * OGRRECLayer::GetNextUnfilteredFeature()
             continue;
         }
 
-        // Strip off end-of-line '!' marker. 
-        if( pszLine[iSegLen-1] != '!' 
+        // Strip off end-of-line '!' marker.
+        if( pszLine[iSegLen-1] != '!'
             && pszLine[iSegLen-1] != '^' )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Apparent corrupt data line .. record FID=%d", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Apparent corrupt data line .. record FID=%d",
                       nNextFID );
             CPLFree( pszRecord );
             return NULL;
@@ -223,8 +216,8 @@ OGRFeature * OGRRECLayer::GetNextUnfilteredFeature()
         iSegLen--;
         if( nDataLen + iSegLen > nRecordLength )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Too much data for record %d.", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Too much data for record %d.",
                       nNextFID );
             CPLFree( pszRecord );
             return NULL;
@@ -238,26 +231,25 @@ OGRFeature * OGRRECLayer::GetNextUnfilteredFeature()
 /* -------------------------------------------------------------------- */
 /*      Create the OGR feature.                                         */
 /* -------------------------------------------------------------------- */
-    OGRFeature *poFeature;
-
-    poFeature = new OGRFeature( poFeatureDefn );
+    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
 
 /* -------------------------------------------------------------------- */
 /*      Set attributes for any indicated attribute records.             */
 /* -------------------------------------------------------------------- */
-    int         iAttr;
-    
-    for( iAttr = 0; iAttr < nFieldCount; iAttr++)
+    for( int iAttr = 0; iAttr < nFieldCount; iAttr++)
     {
-        const char *pszFieldText = 
-            RECGetField( pszRecord, 
+        const char *pszFieldText =
+            RECGetField( pszRecord,
                          panFieldOffset[iAttr] + 1,
                          panFieldWidth[iAttr] );
 
         if( strlen(pszFieldText) != 0 )
+        {
+            /* coverity[tainted_data] */
             poFeature->SetField( iAttr, pszFieldText );
+        }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Translate the record id.                                        */
 /* -------------------------------------------------------------------- */
@@ -278,12 +270,12 @@ OGRFeature *OGRRECLayer::GetNextFeature()
 
 {
     OGRFeature  *poFeature = NULL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read features till we find one that satisfies our current       */
 /*      spatial criteria.                                               */
 /* -------------------------------------------------------------------- */
-    while( TRUE )
+    while( true )
     {
         poFeature = GetNextUnfilteredFeature();
         if( poFeature == NULL )
@@ -302,7 +294,7 @@ OGRFeature *OGRRECLayer::GetNextFeature()
 /*                           TestCapability()                           */
 /************************************************************************/
 
-int OGRRECLayer::TestCapability( CPL_UNUSED const char * pszCap )
+int OGRRECLayer::TestCapability( const char * /* pszCap */)
 {
     return FALSE;
 }
diff --git a/ogr/ogrsf_frmts/s57/ddfrecordindex.cpp b/ogr/ogrsf_frmts/s57/ddfrecordindex.cpp
index 2da9825..a24d378 100644
--- a/ogr/ogrsf_frmts/s57/ddfrecordindex.cpp
+++ b/ogr/ogrsf_frmts/s57/ddfrecordindex.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ddfrecordindex.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: ddfrecordindex.cpp 33271 2016-01-30 16:01:55Z goatbar $
  *
  * Project:  S-57 Translator
  * Purpose:  Implements DDFRecordIndex class.  This class is used to cache
@@ -29,27 +29,23 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "s57.h"
 #include "cpl_conv.h"
+#include "s57.h"
 
-CPL_CVSID("$Id: ddfrecordindex.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: ddfrecordindex.cpp 33271 2016-01-30 16:01:55Z goatbar $");
 
 /************************************************************************/
 /*                           DDFRecordIndex()                           */
 /************************************************************************/
 
-DDFRecordIndex::DDFRecordIndex()
-
-{
-    bSorted = FALSE;
-
-    nRecordCount = 0;
-    nRecordMax = 0;
-    pasRecords = NULL;
-
-    nLastObjlPos = 0;             /* rjensen. added for FindRecordByObjl() */
-    nLastObjl    = 0;             /* rjensen. added for FindRecordByObjl() */
-}
+DDFRecordIndex::DDFRecordIndex() :
+    bSorted(false),
+    nRecordCount(0),
+    nRecordMax(0),
+    nLastObjlPos(0),
+    nLastObjl(0),
+    pasRecords(NULL)
+{}
 
 /************************************************************************/
 /*                          ~DDFRecordIndex()                           */
@@ -71,24 +67,24 @@ DDFRecordIndex::~DDFRecordIndex()
 void DDFRecordIndex::Clear()
 
 {
-    // It turns out that deleting these records here is very expensive
-    // due to the linear search in DDFModule::RemoveClone().  For now we
+    // Deleting these records is very expensive
+    // due to the linear search in DDFModule::RemoveClone().  For now,
     // just leave the clones depending on DDFModule::~DDFModule() to clean
     // them up eventually.
 
-    //for( int i = 0; i < nRecordCount; i++ )
-    //  delete pasRecords[i].poRecord;
+    // for( int i = 0; i < nRecordCount; i++ )
+    //   delete pasRecords[i].poRecord;
 
-    CPLFree( pasRecords );
-    pasRecords = NULL;
+    bSorted = false;
 
     nRecordCount = 0;
     nRecordMax = 0;
 
-    nLastObjlPos = 0;             /* rjensen. added for FindRecordByObjl() */
-    nLastObjl      = 0;             /* rjensen. added for FindRecordByObjl() */
+    nLastObjlPos = 0;
+    nLastObjl = 0;
 
-    bSorted = FALSE;
+    CPLFree( pasRecords );
+    pasRecords = NULL;
 }
 
 /************************************************************************/
@@ -96,7 +92,7 @@ void DDFRecordIndex::Clear()
 /*                                                                      */
 /*      Add a record to the index.  The index will assume ownership     */
 /*      of the record.  If passing a record just read from a            */
-/*      DDFModule it is imperitive that the caller Clone()'s the        */
+/*      DDFModule it is imperative that the caller Clone()'s the        */
 /*      record first.                                                   */
 /************************************************************************/
 
@@ -105,12 +101,12 @@ void DDFRecordIndex::AddRecord( int nKey, DDFRecord * poRecord )
 {
     if( nRecordCount == nRecordMax )
     {
-        nRecordMax = (int) (nRecordCount * 1.3 + 100);
-        pasRecords = (DDFIndexedRecord *)
-            CPLRealloc( pasRecords, sizeof(DDFIndexedRecord)*nRecordMax );
+        nRecordMax = static_cast<int>(nRecordCount * 1.3 + 100);
+        pasRecords = static_cast<DDFIndexedRecord *>(
+            CPLRealloc( pasRecords, sizeof(DDFIndexedRecord)*nRecordMax ) );
     }
 
-    bSorted = FALSE;
+    bSorted = false;
 
     pasRecords[nRecordCount].nKey = nKey;
     pasRecords[nRecordCount].poRecord = poRecord;
@@ -136,11 +132,12 @@ DDFRecord * DDFRecordIndex::FindRecord( int nKey )
 /* -------------------------------------------------------------------- */
 /*      Do a binary search based on the key to find the desired record. */
 /* -------------------------------------------------------------------- */
-    int         nMinIndex = 0, nMaxIndex = nRecordCount-1;
+    int nMinIndex = 0;
+    int nMaxIndex = nRecordCount-1;
 
     while( nMinIndex <= nMaxIndex )
     {
-        int     nTestIndex = (nMaxIndex + nMinIndex) / 2;
+        const int nTestIndex = (nMaxIndex + nMinIndex) / 2;
 
         if( pasRecords[nTestIndex].nKey < nKey )
             nMinIndex = nTestIndex + 1;
@@ -174,9 +171,11 @@ DDFRecord * DDFRecordIndex::FindRecordByObjl( int nObjl )
 
     for (nMinIndex = nLastObjlPos; nMinIndex < nRecordCount; nMinIndex++)
     {
-        if (nObjl == pasRecords[nMinIndex].poRecord->GetIntSubfield( "FRID", 0, "OBJL", 0 ) )
+        if (nObjl == pasRecords[nMinIndex].poRecord->GetIntSubfield(
+            "FRID", 0, "OBJL", 0 ) )
         {
-            nLastObjlPos=nMinIndex+1;  /* add 1, don't want to look at same again */
+            // Add 1.  Do not want to look at same again.
+            nLastObjlPos=nMinIndex+1;
             nLastObjl=nObjl;
             return pasRecords[nMinIndex].poRecord;
         }
@@ -201,8 +200,9 @@ int DDFRecordIndex::RemoveRecord( int nKey )
 /* -------------------------------------------------------------------- */
 /*      Do a binary search based on the key to find the desired record. */
 /* -------------------------------------------------------------------- */
-    int         nMinIndex = 0, nMaxIndex = nRecordCount-1;
-    int         nTestIndex = 0;
+    int nMinIndex = 0;
+    int nMaxIndex = nRecordCount-1;
+    int nTestIndex = 0;
 
     while( nMinIndex <= nMaxIndex )
     {
@@ -249,21 +249,17 @@ static int DDFCompare( const void *pRec1, const void *pRec2 )
     if( ((const DDFIndexedRecord *) pRec1)->nKey
         == ((const DDFIndexedRecord *) pRec2)->nKey )
         return 0;
-    else if( ((const DDFIndexedRecord *) pRec1)->nKey
-             < ((const DDFIndexedRecord *) pRec2)->nKey )
+    if( ((const DDFIndexedRecord *) pRec1)->nKey
+        < ((const DDFIndexedRecord *) pRec2)->nKey )
         return -1;
-    else
-        return 1;
+
+    return 1;
 }
 
 /************************************************************************/
 /*                                Sort()                                */
 /*                                                                      */
-/*      Sort the records based on the key.  This is currently           */
-/*      implemented as a bubble sort, and could gain in efficiency      */
-/*      by reimplementing as a quick sort; however, I believe that      */
-/*      the keys will always be in order so a bubble sort should        */
-/*      only require one pass to verify this.                           */
+/*      Sort the records based on the key.                              */
 /************************************************************************/
 
 void DDFRecordIndex::Sort()
@@ -274,7 +270,7 @@ void DDFRecordIndex::Sort()
 
     qsort( pasRecords, nRecordCount, sizeof(DDFIndexedRecord), DDFCompare );
 
-    bSorted = TRUE;
+    bSorted = true;
 }
 
 /************************************************************************/
@@ -289,8 +285,8 @@ DDFRecord * DDFRecordIndex::GetByIndex( int nIndex )
 
     if( nIndex < 0 || nIndex >= nRecordCount )
         return NULL;
-    else
-        return pasRecords[nIndex].poRecord;
+
+    return pasRecords[nIndex].poRecord;
 }
 
 /************************************************************************/
@@ -305,8 +301,8 @@ void * DDFRecordIndex::GetClientInfoByIndex( int nIndex )
 
     if( nIndex < 0 || nIndex >= nRecordCount )
         return NULL;
-    else
-        return pasRecords[nIndex].pClientData;
+
+    return pasRecords[nIndex].pClientData;
 }
 
 /************************************************************************/
@@ -321,7 +317,6 @@ void DDFRecordIndex::SetClientInfoByIndex( int nIndex, void *pClientData )
 
     if( nIndex < 0 || nIndex >= nRecordCount )
         return;
-    else
-        pasRecords[nIndex].pClientData = pClientData;
-}
 
+    pasRecords[nIndex].pClientData = pClientData;
+}
diff --git a/ogr/ogrsf_frmts/s57/drv_s57.html b/ogr/ogrsf_frmts/s57/drv_s57.html
index a225f06..7020a7d 100644
--- a/ogr/ogrsf_frmts/s57/drv_s57.html
+++ b/ogr/ogrsf_frmts/s57/drv_s57.html
@@ -7,14 +7,15 @@
 
 <h1>IHO S-57 (ENC)</h1>
 
-IHO S-57 datasets are supported for read access.<p>
+IHO S-57 Electronic Navication Charts (ENC) datasets are supported for
+read access.<p>
 
-The S-57 driver module produces features for all S-57 features in 
+The S-57 driver module produces features for all S-57 features in
 S-57 file, and associated updates.  S-57 (ENC) files normally have
 the extension ".000".<p>
 
 S-57 feature objects are translated into features.  S-57 geometry
-objects are automatically collected and formed into geometries on the 
+objects are automatically collected and formed into geometries on the
 features.<P>
 
 The S-57 reader depends on having two supporting files, s57objectclasses.csv,
@@ -23,11 +24,11 @@ in an object class specific manner.  These should be in the directory pointed
 to by the environment variable S57_CSV, or in the current working directory.
 <p>
 
-S-57 update files contain information on how to update a distributed S-57 
+S-57 update files contain information on how to update a distributed S-57
 base data file.  The base files normally have the extension .000 while the
-update files have extensions like .001, .002 and so on.  The S-57 reader 
+update files have extensions like .001, .002 and so on.  The S-57 reader
 will normally read and apply all updates files to the in memory version of
-the base file on the fly.  The feature data provided to the application 
+the base file on the fly.  The feature data provided to the application
 therefore includes all the updates. <p>
 
 <h3>Feature Translation</h3>
@@ -45,11 +46,11 @@ NINFOM, NTXTDS, PICREP, SCAMAX, SCAMIN, TXTDSC, ,RECDAT, RECIND, SORDAT,
 and SORIND attributes.  These short names can be related to longer, more
 meaningful names using an S-57 object/attribute catalog such as the
 S-57 standard document itself, or the catalog files (s57attributes.csv,
-and s57objectclasses.csv).  
+and s57objectclasses.csv).
 Such a catalog can also be used to establish all the available object classes,
 and their attributes.<p>
 
-The following are some common attributes, including generic attributes 
+The following are some common attributes, including generic attributes
 which appear on all feature, regardless of object class.
 is turned on. <p>
 
@@ -60,14 +61,14 @@ is turned on. <p>
   GRUP            Group number.			         All features
 
   OBJL            Object label code.  This number	 All features
-	          indicates the object class of the 
-                  feature. 
+	          indicates the object class of the
+                  feature.
 
   RVER            Record version.
 
   AGEN            Numeric agency code, such as 50 for    All features
                   the Canadian Hydrographic Service.
-		  A potentially outdated list is 
+		  A potentially outdated list is
 		  available in agencode.txt.
 
   FIDN            Feature identification number.         All features
@@ -82,31 +83,31 @@ is turned on. <p>
   INFORM          Informational text.                    Some features
 
   NINFOM	  Informational text in national         Some features
-                  language. 
+                  language.
 
   OBJNAM          Object name				 Some features
 
   NOBJNM          Object name in national		 Some features
                   language.
-                         
+
   SCAMAX          Maximum scale for display              Some features
- 
+
   SCAMIN          Minimum scale for display              Some features
-  
+
   SORDAT          Source date                            Some features
 </pre>
 
 The following are present if LNAM_REFS is enabled:
 <pre>
   LNAM            Long name.  An encoding of AGEN,       All features
-                  FIDN and FIDS used to uniquely 
+                  FIDN and FIDS used to uniquely
                   identify this features within an
-                  S-57 file.  
+                  S-57 file.
 
   LNAM_REFS       List of long names of related features All Features
 
   FFPT_RIND       Relationship indicators for each of    All Features
-                  the LNAM_REFS relationships. 
+                  the LNAM_REFS relationships.
 
 </pre>
 
@@ -122,10 +123,10 @@ feature record will have the same AGEN, FIDN, FIDS and LNAM value.<p>
 <h3>S57 Control Options</h3>
 
 There are several control options which can be used to alter the behavior of
-the S-57 reader.  Users can set these by appending them in the 
-OGR_S57_OPTIONS environment variable. 
+the S-57 reader.  Users can set these by appending them in the
+OGR_S57_OPTIONS environment variable.
 <p>
-Starting with GDAL 2.0, they can also be specified independantly as open options
+Starting with GDAL 2.0, they can also be specified independently as open options
 to the driver.
 <p>
 
@@ -141,25 +142,25 @@ features with many points into many single point features.  Default is OFF. <p>
 
 <li> <b>ADD_SOUNDG_DEPTH</b>=ON/OFF: Should a DEPTH attribute be added on
 SOUNDG features and assign the depth of the sounding.  This should only be
-enabled with SPLIT_MULTIPOINT is also enabled.  
+enabled with SPLIT_MULTIPOINT is also enabled.
 Default is OFF. <p>
 
-<li> <b>RETURN_PRIMITIVES</b>=ON/OFF: Should all the low level geometry 
+<li> <b>RETURN_PRIMITIVES</b>=ON/OFF: Should all the low level geometry
 primitives be returned as special IsolatedNode, ConnectedNode, Edge and
 Face layers.  Default is OFF. <p>
 
 <li> <b>PRESERVE_EMPTY_NUMBERS</b>=ON/OFF: If enabled, numeric attributes
 assigned an empty string as a value will be preserved as a special numeric
-value.  This option should not generally be needed, but may be useful 
+value.  This option should not generally be needed, but may be useful
 when translated S-57 to S-57 losslessly.  Default is OFF. <p>
 
-<li> <b>LNAM_REFS</b>=ON/OFF: Should LNAM and LNAM_REFS fields be 
+<li> <b>LNAM_REFS</b>=ON/OFF: Should LNAM and LNAM_REFS fields be
 attached to features capturing the feature to feature relationships in the
 FFPT group of the S-57 file.  Default is ON.<p>
 
-<li> <b>RETURN_LINKAGES</b>=ON/OFF: Should additional attributes 
-relating features to their underlying geometric primtives be attached.  These
-are the values of the FSPT group, and are primarily needed when doing 
+<li> <b>RETURN_LINKAGES</b>=ON/OFF: Should additional attributes
+relating features to their underlying geometric primitives be attached.  These
+are the values of the FSPT group, and are primarily needed when doing
 S-57 to S-57 translations.  Default is OFF.<p>
 
 <li> <b>RECODE_BY_DSSI</b>=ON/OFF: (OGR >= 1.10) Should attribute values be recoded to UTF-8
@@ -177,7 +178,7 @@ set OGR_S57_OPTIONS = "RETURN_PRIMITIVES=ON,RETURN_LINKAGES=ON,LNAM_REFS=ON"
 
 Preliminary S-57 export capability has been added in GDAL/OGR 1.2.0 but
 is intended only for specialized use, and is not properly documented at
-this time.  Setting the following options is a minimum required to 
+this time.  Setting the following options is a minimum required to
 support S-57 to S-57 conversion via OGR.<p>
 
 <pre>
@@ -217,7 +218,7 @@ DSPM, see the S-57 standard for a more detailed description):
 
 <li> <a href="http://www.s-57.com/">S-57 Online Object/Attribute Catalog</a><p>
 <li> <a href="https://web.archive.org/web/20130730111701/http://home.gdal.org/projects/s57/index.html">Frank's S-57
-Page (at archive.org)</a>: Links to other resources, and sample datasts.<p>
+Page (at archive.org)</a>: Links to other resources, and sample datasets.<p>
 <li> <a href="http://www.iho.int/iho_pubs/standard/S-57Ed3.1/31Main.pdf">IHO S-57 Edition 3.1 (main)<p>
 
 </ul>
diff --git a/ogr/ogrsf_frmts/s57/ogr_s57.h b/ogr/ogrsf_frmts/s57/ogr_s57.h
index 9c0a479..8e30622 100644
--- a/ogr/ogrsf_frmts/s57/ogr_s57.h
+++ b/ogr/ogrsf_frmts/s57/ogr_s57.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_s57.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogr_s57.h 32433 2015-12-23 23:48:56Z goatbar $
  *
  * Project:  S-57 Translator
  * Purpose:  Declarations for classes binding S57 support onto OGRLayer,
@@ -28,8 +28,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_S57_H_INCLUDED
-#define _OGR_S57_H_INCLUDED
+#ifndef OGR_S57_H_INCLUDED
+#define OGR_S57_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "s57.h"
@@ -64,9 +64,11 @@ class OGRS57Layer : public OGRLayer
     OGRFeature *        GetNextFeature();
     OGRFeature *        GetNextUnfilteredFeature();
     virtual OGRFeature *GetFeature( GIntBig nFeatureId );
-    
+
     virtual GIntBig     GetFeatureCount( int bForce = TRUE );
     virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
     OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
 
@@ -88,7 +90,7 @@ class OGRS57DataSource : public OGRDataSource
     OGRSpatialReference *poSpatialRef;
 
     char                **papszOptions;
-    
+
     int                 nModules;
     S57Reader           **papoModules;
 
@@ -96,16 +98,16 @@ class OGRS57DataSource : public OGRDataSource
 
     S57ClassContentExplorer* poClassContentExplorer;
 
-    int                 bExtentsSet;
+    bool                bExtentsSet;
     OGREnvelope         oExtents;
-    
+
   public:
                         OGRS57DataSource(char** papszOpenOptions = NULL);
                         ~OGRS57DataSource();
 
     void                SetOptionList( char ** );
     const char         *GetOption( const char * );
-    
+
     int                 Open( const char * pszName );
     int                 Create( const char *pszName, char **papszOptions );
 
@@ -135,7 +137,7 @@ class OGRS57Driver : public GDALDriver
   public:
                  OGRS57Driver();
                 ~OGRS57Driver();
-                
+
     static GDALDataset *Open( GDALOpenInfo* poOpenInfo );
     static GDALDataset *Create( const char * pszName,
                                 int nBands, int nXSize, int nYSize, GDALDataType eDT,
@@ -144,4 +146,4 @@ class OGRS57Driver : public GDALDriver
     static S57ClassRegistrar *GetS57Registrar();
 };
 
-#endif /* ndef _OGR_S57_H_INCLUDED */
+#endif /* ndef OGR_S57_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/s57/ogrs57datasource.cpp b/ogr/ogrsf_frmts/s57/ogrs57datasource.cpp
index 169a756..b0fbeb5 100644
--- a/ogr/ogrsf_frmts/s57/ogrs57datasource.cpp
+++ b/ogr/ogrsf_frmts/s57/ogrs57datasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrs57datasource.cpp 28348 2015-01-23 15:27:13Z rouault $
+ * $Id: ogrs57datasource.cpp 33271 2016-01-30 16:01:55Z goatbar $
  *
  * Project:  S-57 Translator
  * Purpose:  Implements OGRS57DataSource class
@@ -28,62 +28,53 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_s57.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "ogr_s57.h"
 
-CPL_CVSID("$Id: ogrs57datasource.cpp 28348 2015-01-23 15:27:13Z rouault $");
+CPL_CVSID("$Id: ogrs57datasource.cpp 33271 2016-01-30 16:01:55Z goatbar $");
 
 /************************************************************************/
 /*                          OGRS57DataSource()                          */
 /************************************************************************/
 
-OGRS57DataSource::OGRS57DataSource(char** papszOpenOptions)
-
+OGRS57DataSource::OGRS57DataSource(char** papszOpenOptionsIn) :
+    pszName(NULL),
+    nLayers(0),
+    papoLayers(NULL),
+    poSpatialRef(new OGRSpatialReference()),
+    papszOptions(NULL),
+    nModules(0),
+    papoModules(NULL),
+    poWriter(NULL),
+    poClassContentExplorer(NULL),
+    bExtentsSet(false)
 {
-    nLayers = 0;
-    papoLayers = NULL;
-
-    nModules = 0;
-    papoModules = NULL;
-    poClassContentExplorer = NULL;
-    poWriter = NULL;
-
-    pszName = NULL;
-
-    poSpatialRef = new OGRSpatialReference();
     poSpatialRef->SetWellKnownGeogCS( "WGS84" );
-    
-    bExtentsSet = FALSE;
-
 
 /* -------------------------------------------------------------------- */
 /*      Allow initialization of options from the environment.           */
 /* -------------------------------------------------------------------- */
-    if( papszOpenOptions != NULL )
+    if( papszOpenOptionsIn != NULL )
     {
-        papszOptions = CSLDuplicate(papszOpenOptions);
+        papszOptions = CSLDuplicate(papszOpenOptionsIn);
+        return;
     }
-    else
-    {
-        const char *pszOptString = CPLGetConfigOption( "OGR_S57_OPTIONS", NULL );
-        papszOptions = NULL;
 
-        if ( pszOptString )
-        {
-            char    **papszCurOption;
+    const char *pszOptString = CPLGetConfigOption( "OGR_S57_OPTIONS", NULL );
 
-            papszOptions = 
-                CSLTokenizeStringComplex( pszOptString, ",", FALSE, FALSE );
+    if ( pszOptString == NULL )
+        return;
 
-            if ( papszOptions && *papszOptions )
-            {
-                CPLDebug( "S57", "The following S57 options are being set:" );
-                papszCurOption = papszOptions;
-                while( *papszCurOption )
-                    CPLDebug( "S57", "    %s", *papszCurOption++ );
-            }
-        }
+    papszOptions =
+        CSLTokenizeStringComplex( pszOptString, ",", FALSE, FALSE );
+
+    if ( papszOptions && *papszOptions )
+    {
+        CPLDebug( "S57", "The following S57 options are being set:" );
+        char **papszCurOption = papszOptions;
+        while( *papszCurOption )
+            CPLDebug( "S57", "    %s", *papszCurOption++ );
     }
 }
 
@@ -94,14 +85,12 @@ OGRS57DataSource::OGRS57DataSource(char** papszOpenOptions)
 OGRS57DataSource::~OGRS57DataSource()
 
 {
-    int         i;
-
-    for( i = 0; i < nLayers; i++ )
+    for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
 
     CPLFree( papoLayers );
 
-    for( i = 0; i < nModules; i++ )
+    for( int i = 0; i < nModules; i++ )
         delete papoModules[i];
     CPLFree( papoModules );
 
@@ -157,69 +146,65 @@ int OGRS57DataSource::TestCapability( const char * )
 int OGRS57DataSource::Open( const char * pszFilename )
 
 {
-    int         iModule;
-    
     pszName = CPLStrdup( pszFilename );
 
 /* -------------------------------------------------------------------- */
 /*      Setup reader options.                                           */
 /* -------------------------------------------------------------------- */
     char **papszReaderOptions = NULL;
-    S57Reader   *poModule;
-
-    poModule = new S57Reader( pszFilename );
 
     if( GetOption(S57O_LNAM_REFS) == NULL )
-        papszReaderOptions = CSLSetNameValue(papszReaderOptions, 
-                                         S57O_LNAM_REFS, "ON" );
+        papszReaderOptions = CSLSetNameValue( papszReaderOptions,
+                                              S57O_LNAM_REFS, "ON" );
     else
-        papszReaderOptions = 
-            CSLSetNameValue( papszReaderOptions, S57O_LNAM_REFS, 
-                             GetOption(S57O_LNAM_REFS));
+        papszReaderOptions =
+            CSLSetNameValue( papszReaderOptions, S57O_LNAM_REFS,
+                             GetOption(S57O_LNAM_REFS) );
 
     if( GetOption(S57O_UPDATES) != NULL )
-        papszReaderOptions = 
-            CSLSetNameValue( papszReaderOptions, S57O_UPDATES, 
+        papszReaderOptions =
+            CSLSetNameValue( papszReaderOptions, S57O_UPDATES,
                              GetOption(S57O_UPDATES));
-                                              
+
     if( GetOption(S57O_SPLIT_MULTIPOINT) != NULL )
-        papszReaderOptions = 
+        papszReaderOptions =
             CSLSetNameValue( papszReaderOptions, S57O_SPLIT_MULTIPOINT,
                              GetOption(S57O_SPLIT_MULTIPOINT) );
-                                              
+
     if( GetOption(S57O_ADD_SOUNDG_DEPTH) != NULL )
-        papszReaderOptions = 
+        papszReaderOptions =
             CSLSetNameValue( papszReaderOptions, S57O_ADD_SOUNDG_DEPTH,
                              GetOption(S57O_ADD_SOUNDG_DEPTH));
-                                              
+
     if( GetOption(S57O_PRESERVE_EMPTY_NUMBERS) != NULL )
-        papszReaderOptions = 
+        papszReaderOptions =
             CSLSetNameValue( papszReaderOptions, S57O_PRESERVE_EMPTY_NUMBERS,
                              GetOption(S57O_PRESERVE_EMPTY_NUMBERS) );
-                                              
+
     if( GetOption(S57O_RETURN_PRIMITIVES) != NULL )
-        papszReaderOptions = 
+        papszReaderOptions =
             CSLSetNameValue( papszReaderOptions, S57O_RETURN_PRIMITIVES,
                              GetOption(S57O_RETURN_PRIMITIVES) );
-                                              
+
     if( GetOption(S57O_RETURN_LINKAGES) != NULL )
-        papszReaderOptions = 
+        papszReaderOptions =
             CSLSetNameValue( papszReaderOptions, S57O_RETURN_LINKAGES,
                              GetOption(S57O_RETURN_LINKAGES) );
-                                              
+
     if( GetOption(S57O_RETURN_DSID) != NULL )
-        papszReaderOptions = 
+        papszReaderOptions =
             CSLSetNameValue( papszReaderOptions, S57O_RETURN_DSID,
                              GetOption(S57O_RETURN_DSID) );
 
     if( GetOption(S57O_RECODE_BY_DSSI) != NULL )
-        papszReaderOptions = 
+        papszReaderOptions =
             CSLSetNameValue( papszReaderOptions, S57O_RECODE_BY_DSSI,
                              GetOption(S57O_RECODE_BY_DSSI) );
 
+    S57Reader *poModule = new S57Reader( pszFilename );
     int bRet = poModule->SetOptions( papszReaderOptions );
     CSLDestroy( papszReaderOptions );
-    
+
     if( !bRet )
     {
         delete poModule;
@@ -239,21 +224,19 @@ int OGRS57DataSource::Open( const char * pszFilename )
         return FALSE;
     }
 
-    int bSuccess = TRUE;
+    bool bSuccess = true;
 
     nModules = 1;
-    papoModules = (S57Reader **) CPLMalloc(sizeof(void*));
+    papoModules = static_cast<S57Reader **>( CPLMalloc(sizeof(void*)) );
     papoModules[0] = poModule;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Add the header layers if they are called for.                   */
 /* -------------------------------------------------------------------- */
-    if( GetOption( S57O_RETURN_DSID ) == NULL 
-        || CSLTestBoolean(GetOption( S57O_RETURN_DSID )) )
+    if( GetOption( S57O_RETURN_DSID ) == NULL
+        || CPLTestBool(GetOption( S57O_RETURN_DSID )) )
     {
-        OGRFeatureDefn  *poDefn;
-
-        poDefn = S57GenerateDSIDFeatureDefn();
+        OGRFeatureDefn  *poDefn = S57GenerateDSIDFeatureDefn();
         AddLayer( new OGRS57Layer( this, poDefn ) );
     }
 
@@ -262,18 +245,21 @@ int OGRS57DataSource::Open( const char * pszFilename )
 /* -------------------------------------------------------------------- */
     if( GetOption( S57O_RETURN_PRIMITIVES ) != NULL )
     {
-        OGRFeatureDefn  *poDefn;
-
-        poDefn = S57GenerateVectorPrimitiveFeatureDefn( RCNM_VI, poModule->GetOptionFlags());
+        OGRFeatureDefn  *poDefn
+            = S57GenerateVectorPrimitiveFeatureDefn(
+                RCNM_VI, poModule->GetOptionFlags());
         AddLayer( new OGRS57Layer( this, poDefn ) );
 
-        poDefn = S57GenerateVectorPrimitiveFeatureDefn( RCNM_VC, poModule->GetOptionFlags());
+        poDefn = S57GenerateVectorPrimitiveFeatureDefn(
+            RCNM_VC, poModule->GetOptionFlags());
         AddLayer( new OGRS57Layer( this, poDefn ) );
 
-        poDefn = S57GenerateVectorPrimitiveFeatureDefn( RCNM_VE, poModule->GetOptionFlags());
+        poDefn = S57GenerateVectorPrimitiveFeatureDefn(
+            RCNM_VE, poModule->GetOptionFlags());
         AddLayer( new OGRS57Layer( this, poDefn ) );
 
-        poDefn = S57GenerateVectorPrimitiveFeatureDefn( RCNM_VF, poModule->GetOptionFlags());
+        poDefn = S57GenerateVectorPrimitiveFeatureDefn(
+            RCNM_VF, poModule->GetOptionFlags());
         AddLayer( new OGRS57Layer( this, poDefn ) );
     }
 
@@ -283,21 +269,20 @@ int OGRS57DataSource::Open( const char * pszFilename )
 /* -------------------------------------------------------------------- */
     if( OGRS57Driver::GetS57Registrar() == NULL )
     {
-        OGRFeatureDefn  *poDefn;
-
-        poDefn = S57GenerateGeomFeatureDefn( wkbPoint, 
-                                             poModule->GetOptionFlags() );
+        OGRFeatureDefn  *poDefn
+            = S57GenerateGeomFeatureDefn( wkbPoint,
+                                          poModule->GetOptionFlags() );
         AddLayer( new OGRS57Layer( this, poDefn ) );
-    
-        poDefn = S57GenerateGeomFeatureDefn( wkbLineString, 
+
+        poDefn = S57GenerateGeomFeatureDefn( wkbLineString,
                                              poModule->GetOptionFlags() );
         AddLayer( new OGRS57Layer( this, poDefn ) );
-    
-        poDefn = S57GenerateGeomFeatureDefn( wkbPolygon, 
+
+        poDefn = S57GenerateGeomFeatureDefn( wkbPolygon,
                                              poModule->GetOptionFlags() );
         AddLayer( new OGRS57Layer( this, poDefn ) );
-    
-        poDefn = S57GenerateGeomFeatureDefn( wkbNone, 
+
+        poDefn = S57GenerateGeomFeatureDefn( wkbNone,
                                              poModule->GetOptionFlags() );
         AddLayer( new OGRS57Layer( this, poDefn ) );
     }
@@ -308,42 +293,41 @@ int OGRS57DataSource::Open( const char * pszFilename )
 /* -------------------------------------------------------------------- */
     else
     {
-        OGRFeatureDefn  *poDefn;
-        std::vector<int> anClassCount;
-        int              bGeneric = FALSE;
-        unsigned int     iClass;
-        
         poClassContentExplorer =
             new S57ClassContentExplorer( OGRS57Driver::GetS57Registrar() );
 
-        for( iModule = 0; iModule < nModules; iModule++ )
-            papoModules[iModule]->SetClassBased( OGRS57Driver::GetS57Registrar(),
-                                                 poClassContentExplorer );
-        
-        for( iModule = 0; iModule < nModules; iModule++ )
+        for( int iModule = 0; iModule < nModules; iModule++ )
+            papoModules[iModule]->SetClassBased(
+                OGRS57Driver::GetS57Registrar(), poClassContentExplorer );
+
+        std::vector<int> anClassCount;
+
+        for( int iModule = 0; iModule < nModules; iModule++ )
         {
-            bSuccess &= 
-                papoModules[iModule]->CollectClassList(anClassCount);
+            bSuccess &= CPL_TO_BOOL(
+                papoModules[iModule]->CollectClassList(anClassCount) );
         }
 
-        for( iClass = 0; iClass < anClassCount.size(); iClass++ )
+        bool bGeneric = false;
+
+        for( unsigned int iClass = 0; iClass < anClassCount.size(); iClass++ )
         {
             if( anClassCount[iClass] > 0 )
             {
-                poDefn = 
+                OGRFeatureDefn  *poDefn =
                     S57GenerateObjectClassDefn( OGRS57Driver::GetS57Registrar(),
                                                 poClassContentExplorer,
-                                                iClass, 
+                                                iClass,
                                                 poModule->GetOptionFlags() );
 
                 if( poDefn != NULL )
-                    AddLayer( new OGRS57Layer( this, poDefn, 
+                    AddLayer( new OGRS57Layer( this, poDefn,
                                                anClassCount[iClass] ) );
                 else
                 {
-                    bGeneric = TRUE;
-                    CPLDebug( "S57", 
-                              "Unable to find definition for OBJL=%d\n", 
+                    bGeneric = true;
+                    CPLDebug( "S57",
+                              "Unable to find definition for OBJL=%d\n",
                               iClass );
                 }
             }
@@ -351,8 +335,9 @@ int OGRS57DataSource::Open( const char * pszFilename )
 
         if( bGeneric )
         {
-            poDefn = S57GenerateGeomFeatureDefn( wkbUnknown, 
-                                                 poModule->GetOptionFlags() );
+            OGRFeatureDefn  *poDefn
+                = S57GenerateGeomFeatureDefn( wkbUnknown,
+                                              poModule->GetOptionFlags() );
             AddLayer( new OGRS57Layer( this, poDefn ) );
         }
     }
@@ -360,7 +345,7 @@ int OGRS57DataSource::Open( const char * pszFilename )
 /* -------------------------------------------------------------------- */
 /*      Attach the layer definitions to each of the readers.            */
 /* -------------------------------------------------------------------- */
-    for( iModule = 0; iModule < nModules; iModule++ )
+    for( int iModule = 0; iModule < nModules; iModule++ )
     {
         for( int iLayer = 0; iLayer < nLayers; iLayer++ )
         {
@@ -368,7 +353,7 @@ int OGRS57DataSource::Open( const char * pszFilename )
                 papoLayers[iLayer]->GetLayerDefn() );
         }
     }
-    
+
     return bSuccess;
 }
 
@@ -381,8 +366,8 @@ OGRLayer *OGRS57DataSource::GetLayer( int iLayer )
 {
     if( iLayer < 0 || iLayer >= nLayers )
         return NULL;
-    else
-        return papoLayers[iLayer];
+
+    return papoLayers[iLayer];
 }
 
 /************************************************************************/
@@ -392,9 +377,9 @@ OGRLayer *OGRS57DataSource::GetLayer( int iLayer )
 void OGRS57DataSource::AddLayer( OGRS57Layer * poNewLayer )
 
 {
-    papoLayers = (OGRS57Layer **)
-        CPLRealloc( papoLayers, sizeof(void*) * ++nLayers );
-    
+    papoLayers = static_cast<OGRS57Layer **> (
+        CPLRealloc( papoLayers, sizeof(void*) * ++nLayers ) );
+
     papoLayers[nLayers-1] = poNewLayer;
 }
 
@@ -407,8 +392,8 @@ S57Reader * OGRS57DataSource::GetModule( int i )
 {
     if( i < 0 || i >= nModules )
         return NULL;
-    else
-        return papoModules[i];
+
+    return papoModules[i];
 }
 
 /************************************************************************/
@@ -436,9 +421,9 @@ OGRErr OGRS57DataSource::GetDSExtent( OGREnvelope *psExtent, int bForce )
     for( int iModule=0; iModule < nModules; iModule++ )
     {
         OGREnvelope     oModuleEnvelope;
-        OGRErr          eErr;
 
-        eErr = papoModules[iModule]->GetExtent( &oModuleEnvelope, bForce );
+        OGRErr eErr
+            = papoModules[iModule]->GetExtent( &oModuleEnvelope, bForce );
         if( eErr != OGRERR_NONE )
             return eErr;
 
@@ -454,7 +439,7 @@ OGRErr OGRS57DataSource::GetDSExtent( OGREnvelope *psExtent, int bForce )
     }
 
     *psExtent = oExtents;
-    bExtentsSet = TRUE;
+    bExtentsSet = true;
 
     return OGRERR_NONE;
 }
@@ -466,7 +451,7 @@ OGRErr OGRS57DataSource::GetDSExtent( OGREnvelope *psExtent, int bForce )
 /************************************************************************/
 
 int OGRS57DataSource::Create( const char *pszFilename,
-                              char **papszOptions )
+                              char **papszOptionsIn )
 {
 /* -------------------------------------------------------------------- */
 /*      Instantiate the class registrar if possible.                    */
@@ -474,7 +459,7 @@ int OGRS57DataSource::Create( const char *pszFilename,
     if( OGRS57Driver::GetS57Registrar() == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to load s57objectclasses.csv, unable to continue." );
+                  "Unable to load s57objectclasses.csv.  Unable to continue." );
         return FALSE;
     }
 
@@ -496,18 +481,18 @@ int OGRS57DataSource::Create( const char *pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Add the primitive layers if they are called for.                */
 /* -------------------------------------------------------------------- */
-    OGRFeatureDefn  *poDefn;
     int nOptionFlags = S57M_RETURN_LINKAGES | S57M_LNAM_REFS;
 
-    poDefn = S57GenerateVectorPrimitiveFeatureDefn( RCNM_VI, nOptionFlags );
+    OGRFeatureDefn *poDefn
+        = S57GenerateVectorPrimitiveFeatureDefn( RCNM_VI, nOptionFlags );
     AddLayer( new OGRS57Layer( this, poDefn ) );
-    
+
     poDefn = S57GenerateVectorPrimitiveFeatureDefn( RCNM_VC, nOptionFlags );
     AddLayer( new OGRS57Layer( this, poDefn ) );
-    
+
     poDefn = S57GenerateVectorPrimitiveFeatureDefn( RCNM_VE, nOptionFlags );
     AddLayer( new OGRS57Layer( this, poDefn ) );
-    
+
     poDefn = S57GenerateVectorPrimitiveFeatureDefn( RCNM_VF, nOptionFlags );
     AddLayer( new OGRS57Layer( this, poDefn ) );
 
@@ -517,37 +502,43 @@ int OGRS57DataSource::Create( const char *pszFilename,
     poClassContentExplorer->Rewind();
     while( poClassContentExplorer->NextClass() )
     {
-        poDefn = 
-            S57GenerateObjectClassDefn( OGRS57Driver::GetS57Registrar(), 
+        poDefn =
+            S57GenerateObjectClassDefn( OGRS57Driver::GetS57Registrar(),
                                         poClassContentExplorer,
                                         poClassContentExplorer->GetOBJL(),
                                         nOptionFlags );
-        
-        AddLayer( new OGRS57Layer( this, poDefn, 0, 
+
+        AddLayer( new OGRS57Layer( this, poDefn, 0,
                                    poClassContentExplorer->GetOBJL() ) );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Write out "header" records.                                     */
 /* -------------------------------------------------------------------- */
-    int nEXPP = 1, nINTU = 4, nAGEN = 540, nNOMR = 0, nNOGR = 0,
-        nNOLR = 0, nNOIN = 0, nNOCN = 0, nNOED = 0;
-    const char
-        *pszEXPP = CSLFetchNameValue(papszOptions, "S57_EXPP"),
-        *pszINTU = CSLFetchNameValue(papszOptions, "S57_INTU"),
-        *pszEDTN = CSLFetchNameValue(papszOptions, "S57_EDTN"),
-        *pszUPDN = CSLFetchNameValue(papszOptions, "S57_UPDN"),
-        *pszUADT = CSLFetchNameValue(papszOptions, "S57_UADT"),
-        *pszISDT = CSLFetchNameValue(papszOptions, "S57_ISDT"),
-        *pszSTED = CSLFetchNameValue(papszOptions, "S57_STED"),
-        *pszAGEN = CSLFetchNameValue(papszOptions, "S57_AGEN"),
-        *pszCOMT = CSLFetchNameValue(papszOptions, "S57_COMT"),
-        *pszNOMR = CSLFetchNameValue(papszOptions, "S57_NOMR"),
-        *pszNOGR = CSLFetchNameValue(papszOptions, "S57_NOGR"),
-        *pszNOLR = CSLFetchNameValue(papszOptions, "S57_NOLR"),
-        *pszNOIN = CSLFetchNameValue(papszOptions, "S57_NOIN"),
-        *pszNOCN = CSLFetchNameValue(papszOptions, "S57_NOCN"),
-        *pszNOED = CSLFetchNameValue(papszOptions, "S57_NOED");
+    int nEXPP = 1;
+    int nINTU = 4;
+    int nAGEN = 540;
+    int nNOMR = 0;
+    int nNOGR = 0;
+    int nNOLR = 0;
+    int nNOIN = 0;
+    int nNOCN = 0;
+    int nNOED = 0;
+    const char *pszEXPP = CSLFetchNameValue( papszOptionsIn, "S57_EXPP" );
+    const char *pszINTU = CSLFetchNameValue( papszOptionsIn, "S57_INTU" );
+    const char *pszEDTN = CSLFetchNameValue( papszOptionsIn, "S57_EDTN" );
+    const char *pszUPDN = CSLFetchNameValue( papszOptionsIn, "S57_UPDN" );
+    const char *pszUADT = CSLFetchNameValue( papszOptionsIn, "S57_UADT" );
+    const char *pszISDT = CSLFetchNameValue( papszOptionsIn, "S57_ISDT" );
+    const char *pszSTED = CSLFetchNameValue( papszOptionsIn, "S57_STED" );
+    const char *pszAGEN = CSLFetchNameValue( papszOptionsIn, "S57_AGEN" );
+    const char *pszCOMT = CSLFetchNameValue( papszOptionsIn, "S57_COMT" );
+    const char *pszNOMR = CSLFetchNameValue( papszOptionsIn, "S57_NOMR" );
+    const char *pszNOGR = CSLFetchNameValue( papszOptionsIn, "S57_NOGR" );
+    const char *pszNOLR = CSLFetchNameValue( papszOptionsIn, "S57_NOLR" );
+    const char *pszNOIN = CSLFetchNameValue( papszOptionsIn, "S57_NOIN" );
+    const char *pszNOCN = CSLFetchNameValue( papszOptionsIn, "S57_NOCN" );
+    const char *pszNOED = CSLFetchNameValue( papszOptionsIn, "S57_NOED" );
     if (pszEXPP) nEXPP = atoi(pszEXPP);
     if (pszINTU) nINTU = atoi(pszINTU);
     if (pszAGEN) nAGEN = atoi(pszAGEN);
@@ -561,12 +552,14 @@ int OGRS57DataSource::Create( const char *pszFilename,
                          pszEDTN, pszUPDN, pszUADT, pszISDT, pszSTED, nAGEN,
                          pszCOMT, nNOMR, nNOGR, nNOLR, nNOIN, nNOCN, nNOED );
 
-    int nHDAT = 2, nVDAT = 17, nSDAT = 23, nCSCL = 52000;
-    const char
-        *pszHDAT = CSLFetchNameValue(papszOptions, "S57_HDAT"),
-        *pszVDAT = CSLFetchNameValue(papszOptions, "S57_VDAT"),
-        *pszSDAT = CSLFetchNameValue(papszOptions, "S57_SDAT"),
-        *pszCSCL = CSLFetchNameValue(papszOptions, "S57_CSCL");
+    int nHDAT = 2;
+    int nVDAT = 17;
+    int nSDAT = 23;
+    int nCSCL = 52000;
+    const char *pszHDAT = CSLFetchNameValue( papszOptionsIn, "S57_HDAT" );
+    const char *pszVDAT = CSLFetchNameValue( papszOptionsIn, "S57_VDAT" );
+    const char *pszSDAT = CSLFetchNameValue( papszOptionsIn, "S57_SDAT" );
+    const char *pszCSCL = CSLFetchNameValue( papszOptionsIn, "S57_CSCL" );
     if (pszHDAT)
         nHDAT = atoi(pszHDAT);
     if (pszVDAT)
@@ -577,6 +570,5 @@ int OGRS57DataSource::Create( const char *pszFilename,
         nCSCL = atoi(pszCSCL);
     poWriter->WriteDSPM(nHDAT, nVDAT, nSDAT, nCSCL);
 
-
     return TRUE;
 }
diff --git a/ogr/ogrsf_frmts/s57/ogrs57driver.cpp b/ogr/ogrsf_frmts/s57/ogrs57driver.cpp
index a407d8e..79b2980 100644
--- a/ogr/ogrsf_frmts/s57/ogrs57driver.cpp
+++ b/ogr/ogrsf_frmts/s57/ogrs57driver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrs57driver.cpp 28459 2015-02-12 13:48:21Z rouault $
+ * $Id: ogrs57driver.cpp 32433 2015-12-23 23:48:56Z goatbar $
  *
  * Project:  S-57 Translator
  * Purpose:  Implements OGRS57Driver
@@ -32,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: ogrs57driver.cpp 28459 2015-02-12 13:48:21Z rouault $");
+CPL_CVSID("$Id: ogrs57driver.cpp 32433 2015-12-23 23:48:56Z goatbar $");
 
 S57ClassRegistrar *OGRS57Driver::poRegistrar = NULL;
 static CPLMutex* hS57RegistrarMutex = NULL;
@@ -41,10 +41,7 @@ static CPLMutex* hS57RegistrarMutex = NULL;
 /*                            OGRS57Driver()                            */
 /************************************************************************/
 
-OGRS57Driver::OGRS57Driver()
-
-{
-}
+OGRS57Driver::OGRS57Driver() {}
 
 /************************************************************************/
 /*                           ~OGRS57Driver()                            */
@@ -58,7 +55,7 @@ OGRS57Driver::~OGRS57Driver()
         delete poRegistrar;
         poRegistrar = NULL;
     }
-    
+
     if( hS57RegistrarMutex != NULL )
     {
         CPLDestroyMutex(hS57RegistrarMutex);
@@ -74,14 +71,14 @@ static int OGRS57DriverIdentify( GDALOpenInfo* poOpenInfo )
 
 {
     if( poOpenInfo->nHeaderBytes < 10 )
-        return FALSE;
-    const char* pachLeader = (const char* )poOpenInfo->pabyHeader;
+        return false;
+    const char* pachLeader = reinterpret_cast<char *>( poOpenInfo->pabyHeader );
     if( (pachLeader[5] != '1' && pachLeader[5] != '2'
                 && pachLeader[5] != '3' )
             || pachLeader[6] != 'L'
             || (pachLeader[8] != '1' && pachLeader[8] != ' ') )
     {
-        return FALSE;
+        return false;
     }
     return strstr( pachLeader, "DSID") != NULL;
 }
@@ -93,12 +90,10 @@ static int OGRS57DriverIdentify( GDALOpenInfo* poOpenInfo )
 GDALDataset *OGRS57Driver::Open( GDALOpenInfo* poOpenInfo )
 
 {
-    OGRS57DataSource    *poDS;
-
     if( !OGRS57DriverIdentify(poOpenInfo) )
         return NULL;
 
-    poDS = new OGRS57DataSource(poOpenInfo->papszOpenOptions);
+    OGRS57DataSource *poDS = new OGRS57DataSource(poOpenInfo->papszOpenOptions);
     if( !poDS->Open( poOpenInfo->pszFilename ) )
     {
         delete poDS;
@@ -121,21 +116,19 @@ GDALDataset *OGRS57Driver::Open( GDALOpenInfo* poOpenInfo )
 /************************************************************************/
 
 GDALDataset *OGRS57Driver::Create( const char * pszName,
-                                   CPL_UNUSED int nBands,
-                                   CPL_UNUSED int nXSize,
-                                   CPL_UNUSED int nYSize,
-                                   CPL_UNUSED GDALDataType eDT,
+                                   int /* nBands */,
+                                   int /* nXSize */,
+                                   int /* nYSize */,
+                                   GDALDataType /* eDT */,
                                    char **papszOptions )
 {
     OGRS57DataSource *poDS = new OGRS57DataSource();
 
     if( poDS->Create( pszName, papszOptions ) )
         return poDS;
-    else
-    {
-        delete poDS;
-        return NULL;
-    }
+
+    delete poDS;
+    return NULL;
 }
 
 /************************************************************************/
@@ -171,63 +164,61 @@ S57ClassRegistrar *OGRS57Driver::GetS57Registrar()
 void RegisterOGRS57()
 
 {
-    GDALDriver  *poDriver;
-
-    if( GDALGetDriverByName( "S57" ) == NULL )
-    {
-        poDriver = new OGRS57Driver();
-
-        poDriver->SetDescription( "S57" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "IHO S-57 (ENC)" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "000" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_s57.html" );
-
-        poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
-"<OpenOptionList>"
-"  <Option name='" S57O_UPDATES "' type='string-select' description='Should update files be incorporated into the base data on the fly' default='APPLY'>"
-"    <Value>APPLY</Value>"
-"    <Value>IGNORE</Value>"
-"  </Option>"
-"  <Option name='" S57O_SPLIT_MULTIPOINT "' type='boolean' description='Should multipoint soundings be split into many single point sounding features' default='NO'/>"
-"  <Option name='" S57O_ADD_SOUNDG_DEPTH "' type='boolean' description='Should a DEPTH attribute be added on SOUNDG features and assign the depth of the sounding' default='NO'/>"
-"  <Option name='" S57O_RETURN_PRIMITIVES "' type='boolean' description='Should all the low level geometry primitives be returned as special IsolatedNode, ConnectedNode, Edge and Face layers' default='NO'/>"
-"  <Option name='" S57O_PRESERVE_EMPTY_NUMBERS "' type='boolean' description='If enabled, numeric attributes assigned an empty string as a value will be preserved as a special numeric value' default='NO'/>"
-"  <Option name='" S57O_LNAM_REFS "' type='boolean' description='Should LNAM and LNAM_REFS fields be attached to features capturing the feature to feature relationships in the FFPT group of the S-57 file' default='YES'/>"
-"  <Option name='" S57O_RETURN_LINKAGES "' type='boolean' description='Should additional attributes relating features to their underlying geometric primtives be attached' default='NO'/>"
-"  <Option name='" S57O_RECODE_BY_DSSI "' type='boolean' description='Should attribute values be recoded to UTF-8 from the character encoding specified in the S57 DSSI record.' default='NO'/>"
-"</OpenOptionList>");
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
-"<CreationOptionList>"
-"   <Option name='S57_EXPP' type='int' description='Exchange purpose' default='1'/>"
-"   <Option name='S57_INTU' type='int' description='Intended usage' default='4'/>"
-"   <Option name='S57_EDTN' type='string' description='Edition number' default='2'/>"
-"   <Option name='S57_UPDN' type='string' description='Update number' default='0'/>"
-"   <Option name='S57_UADT' type='string' description='Update application date' default='20030801'/>"
-"   <Option name='S57_ISDT' type='string' description='Issue date' default='20030801'/>"
-"   <Option name='S57_STED' type='string' description='Edition number of S-57' default='03.1'/>"
-"   <Option name='S57_AGEN' type='int' description='Producing agency' default='540'/>"
-"   <Option name='S57_COMT' type='string' description='Comment' default=''/>"
-"   <Option name='S57_NOMR' type='int' description='Number of meta records (objects with acronym starting with \"M_\")' default='0'/>"
-"   <Option name='S57_NOGR' type='int' description='Number of geo records' default='0'/>"
-"   <Option name='S57_NOLR' type='int' description='Number of collection records' default='0'/>"
-"   <Option name='S57_NOIN' type='int' description='Number of isolated node records' default='0'/>"
-"   <Option name='S57_NOCN' type='int' description='Number of connected node records' default='0'/>"
-"   <Option name='S57_NOED' type='int' description='Number of edge records' default='0'/>"
-"   <Option name='S57_HDAT' type='int' description='Horizontal geodetic datum' default='2'/>"
-"   <Option name='S57_VDAT' type='int' description='Vertical datum' default='17'/>"
-"   <Option name='S57_SDAT' type='int' description='Sounding datum' default='23'/>"
-"   <Option name='S57_CSCL' type='int' description='Compilation scale of data (1:X)' default='52000'/>"
-"</CreationOptionList>" );
-
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = OGRS57Driver::Open;
-        poDriver->pfnIdentify = OGRS57DriverIdentify;
-        poDriver->pfnCreate = OGRS57Driver::Create;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    if( GDALGetDriverByName( "S57" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new OGRS57Driver();
+
+    poDriver->SetDescription( "S57" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "IHO S-57 (ENC)" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "000" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_s57.html" );
+
+    poDriver->SetMetadataItem(
+        GDAL_DMD_OPENOPTIONLIST,
+        "<OpenOptionList>"
+        "  <Option name='" S57O_UPDATES "' type='string-select' description='Should update files be incorporated into the base data on the fly' default='APPLY'>"
+        "    <Value>APPLY</Value>"
+        "    <Value>IGNORE</Value>"
+        "  </Option>"
+        "  <Option name='" S57O_SPLIT_MULTIPOINT "' type='boolean' description='Should multipoint soundings be split into many single point sounding features' default='NO'/>"
+        "  <Option name='" S57O_ADD_SOUNDG_DEPTH "' type='boolean' description='Should a DEPTH attribute be added on SOUNDG features and assign the depth of the sounding' default='NO'/>"
+        "  <Option name='" S57O_RETURN_PRIMITIVES "' type='boolean' description='Should all the low level geometry primitives be returned as special IsolatedNode, ConnectedNode, Edge and Face layers' default='NO'/>"
+        "  <Option name='" S57O_PRESERVE_EMPTY_NUMBERS "' type='boolean' description='If enabled, numeric attributes assigned an empty string as a value will be preserved as a special numeric value' default='NO'/>"
+        "  <Option name='" S57O_LNAM_REFS "' type='boolean' description='Should LNAM and LNAM_REFS fields be attached to features capturing the feature to feature relationships in the FFPT group of the S-57 file' default='YES'/>"
+        "  <Option name='" S57O_RETURN_LINKAGES "' type='boolean' description='Should additional attributes relating features to their underlying geometric primitives be attached' default='NO'/>"
+        "  <Option name='" S57O_RECODE_BY_DSSI "' type='boolean' description='Should attribute values be recoded to UTF-8 from the character encoding specified in the S57 DSSI record.' default='NO'/>"
+        "</OpenOptionList>");
+    poDriver->SetMetadataItem(
+        GDAL_DMD_CREATIONOPTIONLIST,
+        "<CreationOptionList>"
+        "   <Option name='S57_EXPP' type='int' description='Exchange purpose' default='1'/>"
+        "   <Option name='S57_INTU' type='int' description='Intended usage' default='4'/>"
+        "   <Option name='S57_EDTN' type='string' description='Edition number' default='2'/>"
+        "   <Option name='S57_UPDN' type='string' description='Update number' default='0'/>"
+        "   <Option name='S57_UADT' type='string' description='Update application date' default='20030801'/>"
+        "   <Option name='S57_ISDT' type='string' description='Issue date' default='20030801'/>"
+        "   <Option name='S57_STED' type='string' description='Edition number of S-57' default='03.1'/>"
+        "   <Option name='S57_AGEN' type='int' description='Producing agency' default='540'/>"
+        "   <Option name='S57_COMT' type='string' description='Comment' default=''/>"
+        "   <Option name='S57_NOMR' type='int' description='Number of meta records (objects with acronym starting with \"M_\")' default='0'/>"
+        "   <Option name='S57_NOGR' type='int' description='Number of geo records' default='0'/>"
+        "   <Option name='S57_NOLR' type='int' description='Number of collection records' default='0'/>"
+        "   <Option name='S57_NOIN' type='int' description='Number of isolated node records' default='0'/>"
+        "   <Option name='S57_NOCN' type='int' description='Number of connected node records' default='0'/>"
+        "   <Option name='S57_NOED' type='int' description='Number of edge records' default='0'/>"
+        "   <Option name='S57_HDAT' type='int' description='Horizontal geodetic datum' default='2'/>"
+        "   <Option name='S57_VDAT' type='int' description='Vertical datum' default='17'/>"
+        "   <Option name='S57_SDAT' type='int' description='Sounding datum' default='23'/>"
+        "   <Option name='S57_CSCL' type='int' description='Compilation scale of data (1:X)' default='52000'/>"
+        "</CreationOptionList>" );
+
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = OGRS57Driver::Open;
+    poDriver->pfnIdentify = OGRS57DriverIdentify;
+    poDriver->pfnCreate = OGRS57Driver::Create;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/s57/ogrs57layer.cpp b/ogr/ogrsf_frmts/s57/ogrs57layer.cpp
index c40dc22..c6d7016 100644
--- a/ogr/ogrsf_frmts/s57/ogrs57layer.cpp
+++ b/ogr/ogrsf_frmts/s57/ogrs57layer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrs57layer.cpp 28382 2015-01-30 15:29:41Z rouault $
+ * $Id: ogrs57layer.cpp 33271 2016-01-30 16:01:55Z goatbar $
  *
  * Project:  S-57 Translator
  * Purpose:  Implements OGRS57Layer class.
@@ -28,11 +28,11 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_s57.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "ogr_s57.h"
 
-CPL_CVSID("$Id: ogrs57layer.cpp 28382 2015-01-30 15:29:41Z rouault $");
+CPL_CVSID("$Id: ogrs57layer.cpp 33271 2016-01-30 16:01:55Z goatbar $");
 
 /************************************************************************/
 /*                            OGRS57Layer()                             */
@@ -44,22 +44,19 @@ CPL_CVSID("$Id: ogrs57layer.cpp 28382 2015-01-30 15:29:41Z rouault $");
 OGRS57Layer::OGRS57Layer( OGRS57DataSource *poDSIn,
                           OGRFeatureDefn * poDefnIn,
                           int nFeatureCountIn,
-                          int nOBJLIn)
-
+                          int nOBJLIn) :
+    poDS(poDSIn),
+    poFeatureDefn(poDefnIn),
+    nCurrentModule(-1),
+    nRCNM(100),  // Default to feature.
+    nOBJL(nOBJLIn),
+    nNextFEIndex(0),
+    nFeatureCount(nFeatureCountIn)
 {
-    poDS = poDSIn;
-
-    nFeatureCount = nFeatureCountIn;
-
-    poFeatureDefn = poDefnIn;
     SetDescription( poFeatureDefn->GetName() );
     if( poFeatureDefn->GetGeomFieldCount() > 0 )
-        poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poDS->GetSpatialRef());
-
-    nOBJL = nOBJLIn;
-
-    nNextFEIndex = 0;
-    nCurrentModule = -1;
+        poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(
+            poDS->GetSpatialRef() );
 
     if( EQUAL(poDefnIn->GetName(),OGRN_VI) )
         nRCNM = RCNM_VI;
@@ -71,8 +68,7 @@ OGRS57Layer::OGRS57Layer( OGRS57DataSource *poDSIn,
         nRCNM = RCNM_VF;
     else if( EQUAL(poDefnIn->GetName(),"DSID") )
         nRCNM = RCNM_DSID;
-    else 
-        nRCNM = 100;  /* feature */
+    // Leave as feature.
 }
 
 /************************************************************************/
@@ -82,10 +78,10 @@ OGRS57Layer::OGRS57Layer( OGRS57DataSource *poDSIn,
 OGRS57Layer::~OGRS57Layer()
 
 {
-    if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
+    if( m_nFeaturesRead > 0 )
     {
         CPLDebug( "S57", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
+                  static_cast<int>( m_nFeaturesRead ),
                   poFeatureDefn->GetName() );
     }
 
@@ -110,8 +106,6 @@ void OGRS57Layer::ResetReading()
 OGRFeature *OGRS57Layer::GetNextUnfilteredFeature()
 
 {
-    OGRFeature  *poFeature = NULL;
-    
 /* -------------------------------------------------------------------- */
 /*      Are we out of modules to request features from?                 */
 /* -------------------------------------------------------------------- */
@@ -123,7 +117,8 @@ OGRFeature *OGRS57Layer::GetNextUnfilteredFeature()
 /*      feature.                                                        */
 /* -------------------------------------------------------------------- */
     S57Reader   *poReader = poDS->GetModule(nCurrentModule);
-    
+    OGRFeature  *poFeature = NULL;
+
     if( poReader != NULL )
     {
         poReader->SetNextFEIndex( nNextFEIndex, nRCNM );
@@ -154,7 +149,7 @@ OGRFeature *OGRS57Layer::GetNextUnfilteredFeature()
             poFeature->GetGeometryRef()->assignSpatialReference(
                 GetSpatialRef() );
     }
-    
+
     return poFeature;
 }
 
@@ -171,7 +166,7 @@ OGRFeature *OGRS57Layer::GetNextFeature()
 /*      Read features till we find one that satisfies our current       */
 /*      spatial criteria.                                               */
 /* -------------------------------------------------------------------- */
-    while( TRUE )
+    while( true )
     {
         poFeature = GetNextUnfilteredFeature();
         if( poFeature == NULL )
@@ -196,33 +191,34 @@ OGRFeature *OGRS57Layer::GetNextFeature()
 int OGRS57Layer::TestCapability( const char * pszCap )
 
 {
-    if( EQUAL(pszCap,OLCRandomRead) )
-        return FALSE;
+    if( EQUAL(pszCap, OLCRandomRead) )
+        return false;
 
-    else if( EQUAL(pszCap,OLCSequentialWrite) )
-        return TRUE;
+    if( EQUAL(pszCap, OLCSequentialWrite) )
+        return true;
 
-    else if( EQUAL(pszCap,OLCRandomWrite) )
-        return FALSE;
+    if( EQUAL(pszCap, OLCRandomWrite) )
+        return false;
 
-    else if( EQUAL(pszCap,OLCFastFeatureCount) )
-        return !(m_poFilterGeom != NULL || m_poAttrQuery != NULL 
+    if( EQUAL(pszCap, OLCFastFeatureCount) )
+        return !(m_poFilterGeom != NULL || m_poAttrQuery != NULL
                  || nFeatureCount == -1 ||
                  ( EQUAL(poFeatureDefn->GetName(), "SOUNDG") &&
                    poDS->GetModule(0) != NULL &&
-                   (poDS->GetModule(0)->GetOptionFlags() & S57M_SPLIT_MULTIPOINT)));
+                   (poDS->GetModule(0)->GetOptionFlags()
+                    & S57M_SPLIT_MULTIPOINT)));
 
-    else if( EQUAL(pszCap,OLCFastGetExtent) )
+    if( EQUAL(pszCap, OLCFastGetExtent) )
     {
         OGREnvelope oEnvelope;
 
         return GetExtent( &oEnvelope, FALSE ) == OGRERR_NONE;
     }
-    else if( EQUAL(pszCap,OLCFastSpatialFilter) )
-        return FALSE;
 
-    else 
-        return FALSE;
+    if( EQUAL(pszCap, OLCFastSpatialFilter) )
+        return false;
+
+    return false;
 }
 
 /************************************************************************/
@@ -243,11 +239,11 @@ OGRErr OGRS57Layer::GetExtent( OGREnvelope *psExtent, int bForce )
 /************************************************************************/
 GIntBig OGRS57Layer::GetFeatureCount (int bForce)
 {
-    
+
     if( !TestCapability(OLCFastFeatureCount) )
         return OGRLayer::GetFeatureCount( bForce );
-    else
-        return nFeatureCount;
+
+    return nFeatureCount;
 }
 
 /************************************************************************/
@@ -261,16 +257,16 @@ OGRFeature *OGRS57Layer::GetFeature( GIntBig nFeatureId )
 
     if( poReader != NULL && nFeatureId <= INT_MAX )
     {
-        OGRFeature      *poFeature;
+        OGRFeature *poFeature = poReader->ReadFeature(
+            static_cast<int>(nFeatureId), poFeatureDefn );
 
-        poFeature = poReader->ReadFeature( (int)nFeatureId, poFeatureDefn );
         if( poFeature != NULL &&  poFeature->GetGeometryRef() != NULL )
             poFeature->GetGeometryRef()->assignSpatialReference(
                 GetSpatialRef() );
         return poFeature;
     }
-    else
-        return NULL;
+
+    return NULL;
 }
 
 /************************************************************************/
@@ -283,7 +279,7 @@ OGRErr OGRS57Layer::ICreateFeature( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
 /*      Set RCNM if not already set.                                    */
 /* -------------------------------------------------------------------- */
-    int iRCNMFld = poFeature->GetFieldIndex( "RCNM" );
+    const int iRCNMFld = poFeature->GetFieldIndex( "RCNM" );
 
     if( iRCNMFld != -1 )
     {
@@ -300,7 +296,7 @@ OGRErr OGRS57Layer::ICreateFeature( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
     if( nOBJL != -1 )
     {
-        int iOBJLFld = poFeature->GetFieldIndex( "OBJL" );
+        const int iOBJLFld = poFeature->GetFieldIndex( "OBJL" );
 
         if( !poFeature->IsFieldSet( iOBJLFld ) )
             poFeature->SetField( iOBJLFld, nOBJL );
@@ -315,6 +311,6 @@ OGRErr OGRS57Layer::ICreateFeature( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
     if( poDS->GetWriter()->WriteCompleteFeature( poFeature ) )
         return OGRERR_NONE;
-    else
-        return OGRERR_FAILURE;
+
+    return OGRERR_FAILURE;
 }
diff --git a/ogr/ogrsf_frmts/s57/s57.h b/ogr/ogrsf_frmts/s57/s57.h
index 74f5d07..3095faf 100644
--- a/ogr/ogrsf_frmts/s57/s57.h
+++ b/ogr/ogrsf_frmts/s57/s57.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: s57.h 28348 2015-01-23 15:27:13Z rouault $
+ * $Id: s57.h 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  S-57 Translator
  * Purpose:  Declarations for S-57 translator not including the
@@ -30,8 +30,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _S57_H_INCLUDED
-#define _S57_H_INCLUDED
+#ifndef S57_H_INCLUDED
+#define S57_H_INCLUDED
 
 #include <vector>
 #include "ogr_feature.h"
@@ -98,7 +98,7 @@ char **S57FileCollector( const char * pszDataset );
 
 class S57ClassContentExplorer;
 
-class CPL_DLL S57AttrInfo 
+class CPL_DLL S57AttrInfo
 {
   public:
     CPLString    osName;
@@ -135,7 +135,7 @@ public:
     // attribute table methods.
     //int         GetMaxAttrIndex() { return nAttrMax; }
     const S57AttrInfo *GetAttrInfo(int i);
-    const char *GetAttrName( int i ) 
+    const char *GetAttrName( int i )
     { return GetAttrInfo(i) == NULL ? NULL : aoAttrInfos[i]->osName.c_str(); }
     const char *GetAttrAcronym( int i )
     { return GetAttrInfo(i) == NULL ? NULL : aoAttrInfos[i]->osAcronym.c_str(); }
@@ -182,12 +182,12 @@ class S57ClassContentExplorer
     int         NextClass() { return SelectClassByIndex(iCurrentClass+1); }
 
     int         GetOBJL();
-    const char *GetDescription();
-    const char *GetAcronym();
+    const char *GetDescription() const;
+    const char *GetAcronym() const;
 
     char      **GetAttributeList( const char * = NULL );
 
-    char        GetClassCode();
+    char        GetClassCode() const;
     char      **GetPrimitives();
 };
 
@@ -206,13 +206,13 @@ typedef struct
 
 class CPL_DLL DDFRecordIndex
 {
-    int         bSorted;
+    bool        bSorted;
 
     int         nRecordCount;
     int         nRecordMax;
 
-    int         nLastObjlPos;            /* rjensen. added for FindRecordByObjl() */
-    int         nLastObjl;                  /* rjensen. added for FindRecordByObjl() */
+    int         nLastObjlPos;  // Added for FindRecordByObjl().
+    int         nLastObjl;     // Added for FindRecordByObjl().
 
     DDFIndexedRecord *pasRecords;
 
@@ -227,7 +227,7 @@ public:
 
     DDFRecord  *FindRecord( int nKey );
 
-    DDFRecord  *FindRecordByObjl( int nObjl );    /* rjensen. added for FindRecordByObjl() */
+    DDFRecord  *FindRecordByObjl( int nObjl );  // Added for FindRecordByObjl().
 
     void        Clear();
 
@@ -260,7 +260,7 @@ class CPL_DLL S57Reader
     int                 nCOMF;  /* Coordinate multiplier */
     int                 nSOMF;  /* Vertical (sounding) multiplier */
 
-    int                 bFileIngested;
+    bool                bFileIngested;
     DDFRecordIndex      oVI_Index;
     DDFRecordIndex      oVC_Index;
     DDFRecordIndex      oVE_Index;
@@ -281,11 +281,11 @@ class CPL_DLL S57Reader
 
     char                **papszOptions;
 
-    int                 nOptionFlags; 
+    int                 nOptionFlags;
 
     int                 iPointOffset;
     OGRFeature          *poMultiPoint;
-    
+
     int                 Aall;               // see RecodeByDSSI() function
     int                 Nall;               // see RecodeByDSSI() function
     bool                needAallNallSetup;  // see RecodeByDSSI() function
@@ -313,8 +313,8 @@ class CPL_DLL S57Reader
 
     int                 ApplyRecordUpdate( DDFRecord *, DDFRecord * );
 
-    int                 bMissingWarningIssued;
-    int                 bAttrWarningIssued;
+    bool                bMissingWarningIssued;
+    bool                bAttrWarningIssued;
 
   public:
                         S57Reader( const char * );
@@ -408,10 +408,10 @@ private:
 /* -------------------------------------------------------------------- */
 void           CPL_DLL  S57GenerateStandardAttributes( OGRFeatureDefn *, int );
 OGRFeatureDefn CPL_DLL *S57GenerateGeomFeatureDefn( OGRwkbGeometryType, int );
-OGRFeatureDefn CPL_DLL *S57GenerateObjectClassDefn( S57ClassRegistrar *, 
+OGRFeatureDefn CPL_DLL *S57GenerateObjectClassDefn( S57ClassRegistrar *,
                                                     S57ClassContentExplorer* poClassContentExplorer,
                                                     int, int );
 OGRFeatureDefn CPL_DLL  *S57GenerateVectorPrimitiveFeatureDefn( int, int );
 OGRFeatureDefn CPL_DLL  *S57GenerateDSIDFeatureDefn( void );
 
-#endif /* ndef _S57_H_INCLUDED */
+#endif /* ndef S57_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/s57/s57classregistrar.cpp b/ogr/ogrsf_frmts/s57/s57classregistrar.cpp
index d2ab8ce..91b558c 100644
--- a/ogr/ogrsf_frmts/s57/s57classregistrar.cpp
+++ b/ogr/ogrsf_frmts/s57/s57classregistrar.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: s57classregistrar.cpp 27885 2014-10-19 22:56:48Z rouault $
+ * $Id: s57classregistrar.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  S-57 Translator
  * Purpose:  Implements S57ClassRegistrar class for keeping track of
@@ -29,11 +29,11 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "s57.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "s57.h"
 
-CPL_CVSID("$Id: s57classregistrar.cpp 27885 2014-10-19 22:56:48Z rouault $");
+CPL_CVSID("$Id: s57classregistrar.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 
 #ifdef S57_BUILTIN_CLASSES
@@ -44,11 +44,11 @@ CPL_CVSID("$Id: s57classregistrar.cpp 27885 2014-10-19 22:56:48Z rouault $");
 /*                         S57ClassRegistrar()                          */
 /************************************************************************/
 
-S57ClassRegistrar::S57ClassRegistrar()
-
-{
-    papszNextLine = NULL;
-}
+S57ClassRegistrar::S57ClassRegistrar() :
+    nClasses(0),
+    nAttrCount(0),
+    papszNextLine(NULL)
+{ }
 
 /************************************************************************/
 /*                         ~S57ClassRegistrar()                         */
@@ -68,10 +68,9 @@ S57ClassRegistrar::~S57ClassRegistrar()
 /*                        S57ClassContentExplorer()                     */
 /************************************************************************/
 
-S57ClassContentExplorer::S57ClassContentExplorer(S57ClassRegistrar* poRegistrar):
-    poRegistrar(poRegistrar)
+S57ClassContentExplorer::S57ClassContentExplorer(S57ClassRegistrar* poRegistrarIn):
+    poRegistrar(poRegistrarIn)
 {
-    
     iCurrentClass = -1;
 
     papszCurrentFields = NULL;
@@ -86,7 +85,7 @@ S57ClassContentExplorer::S57ClassContentExplorer(S57ClassRegistrar* poRegistrar)
 S57ClassContentExplorer::~S57ClassContentExplorer()
 {
     CSLDestroy( papszTempResult );
-    
+
     if( papapszClassesFields != NULL )
     {
         for( int i = 0; i < poRegistrar->nClasses; i++ )
@@ -99,14 +98,14 @@ S57ClassContentExplorer::~S57ClassContentExplorer()
 /*                              FindFile()                              */
 /************************************************************************/
 
-int S57ClassRegistrar::FindFile( const char *pszTarget, 
-                                 const char *pszDirectory, 
+int S57ClassRegistrar::FindFile( const char *pszTarget,
+                                 const char *pszDirectory,
                                  int bReportErr,
                                  VSILFILE **pfp )
 
 {
     const char *pszFilename;
-    
+
     if( pszDirectory == NULL )
     {
         pszFilename = CPLFindFile( "s57", pszTarget );
@@ -171,14 +170,11 @@ const char *S57ClassRegistrar::ReadLine( VSILFILE * fp )
 /*                              LoadInfo()                              */
 /************************************************************************/
 
-int S57ClassRegistrar::LoadInfo( const char * pszDirectory, 
+int S57ClassRegistrar::LoadInfo( const char * pszDirectory,
                                  const char * pszProfile,
                                  int bReportErr )
 
 {
-    VSILFILE   *fp;
-    char        szTargetFile[1024];
-
     if( pszDirectory == NULL )
         pszDirectory = CPLGetConfigOption("S57_CSV",NULL);
 
@@ -187,14 +183,15 @@ int S57ClassRegistrar::LoadInfo( const char * pszDirectory,
 /* ==================================================================== */
     if( pszProfile == NULL )
         pszProfile = CPLGetConfigOption( "S57_PROFILE", "" );
-    
+
+    char szTargetFile[1024];  // TODO: Get this off of the stack.
     if( EQUAL(pszProfile, "Additional_Military_Layers") )
     {
-       sprintf( szTargetFile, "s57objectclasses_%s.csv", "aml" );
+       snprintf( szTargetFile, sizeof(szTargetFile), "s57objectclasses_%s.csv", "aml" );
     }
     else if ( EQUAL(pszProfile, "Inland_Waterways") )
     {
-       sprintf( szTargetFile, "s57objectclasses_%s.csv", "iw" );
+       snprintf( szTargetFile, sizeof(szTargetFile), "s57objectclasses_%s.csv", "iw" );
     }
     else if( strlen(pszProfile) > 0 )
     {
@@ -205,6 +202,7 @@ int S57ClassRegistrar::LoadInfo( const char * pszDirectory,
        strcpy( szTargetFile, "s57objectclasses.csv" );
     }
 
+    VSILFILE *fp = NULL;
     if( !FindFile( szTargetFile, pszDirectory, bReportErr, &fp ) )
         return FALSE;
 
@@ -249,11 +247,11 @@ int S57ClassRegistrar::LoadInfo( const char * pszDirectory,
 
     if( EQUAL(pszProfile, "Additional_Military_Layers") )
     {
-        sprintf( szTargetFile, "s57attributes_%s.csv", "aml" );
+      snprintf( szTargetFile, sizeof(szTargetFile), "s57attributes_%s.csv", "aml" );
     }
     else if ( EQUAL(pszProfile, "Inland_Waterways") )
     {
-       sprintf( szTargetFile, "s57attributes_%s.csv", "iw" );
+       snprintf( szTargetFile, sizeof(szTargetFile),"s57attributes_%s.csv", "iw" );
     }
     else if( strlen(pszProfile) > 0 )
     {
@@ -263,7 +261,7 @@ int S57ClassRegistrar::LoadInfo( const char * pszDirectory,
     {
        strcpy( szTargetFile, "s57attributes.csv" );
     }
-       
+
     if( !FindFile( szTargetFile, pszDirectory, bReportErr, &fp ) )
         return FALSE;
 
@@ -281,12 +279,10 @@ int S57ClassRegistrar::LoadInfo( const char * pszDirectory,
             VSIFCloseL( fp );
         return FALSE;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read and form string list.                                      */
 /* -------------------------------------------------------------------- */
-    int        iAttr;
-
     while( (pszLine = ReadLine(fp)) != NULL )
     {
         char    **papszTokens = CSLTokenizeStringComplex( pszLine, ",",
@@ -297,16 +293,17 @@ int S57ClassRegistrar::LoadInfo( const char * pszDirectory,
             CPLAssert( FALSE );
             continue;
         }
-        
-        iAttr = atoi(papszTokens[0]);
+
+        int iAttr = atoi(papszTokens[0]);
         if( iAttr >= (int) aoAttrInfos.size() )
             aoAttrInfos.resize(iAttr+1);
 
         if( iAttr < 0 || aoAttrInfos[iAttr] != NULL )
         {
-            CPLDebug( "S57", 
-                      "Duplicate/corrupt definition for attribute %d:%s", 
+            CPLDebug( "S57",
+                      "Duplicate/corrupt definition for attribute %d:%s",
                       iAttr, papszTokens[2] );
+            CSLDestroy( papszTokens );
             continue;
         }
 
@@ -322,30 +319,28 @@ int S57ClassRegistrar::LoadInfo( const char * pszDirectory,
     if( fp != NULL )
         VSIFCloseL( fp );
 
-    nAttrCount = anAttrIndex.size();
-    
+    nAttrCount = static_cast<int>(anAttrIndex.size());
+
 /* -------------------------------------------------------------------- */
 /*      Sort index by acronym.                                          */
 /* -------------------------------------------------------------------- */
-    int         bModified;
+    bool bModified = false;
     do
     {
-        bModified = FALSE;
-        for( iAttr = 0; iAttr < nAttrCount-1; iAttr++ )
+        bModified = false;
+        for( int iAttr = 0; iAttr < nAttrCount-1; iAttr++ )
         {
             if( strcmp(aoAttrInfos[anAttrIndex[iAttr]]->osAcronym,
                        aoAttrInfos[anAttrIndex[iAttr+1]]->osAcronym) > 0 )
             {
-                int     nTemp;
-
-                nTemp = anAttrIndex[iAttr];
+                int nTemp = anAttrIndex[iAttr];
                 anAttrIndex[iAttr] = anAttrIndex[iAttr+1];
                 anAttrIndex[iAttr+1] = nTemp;
-                bModified = TRUE;
+                bModified = true;
             }
         }
     } while( bModified );
-    
+
     return TRUE;
 }
 
@@ -371,7 +366,7 @@ int S57ClassContentExplorer::SelectClassByIndex( int nNewIndex )
 /*      Has this info been parsed yet?                                  */
 /* -------------------------------------------------------------------- */
     if( papapszClassesFields[nNewIndex] == NULL )
-        papapszClassesFields[nNewIndex] = 
+        papapszClassesFields[nNewIndex] =
             CSLTokenizeStringComplex( poRegistrar->apszClassesInfo[nNewIndex],
                                       ",", TRUE, TRUE );
 
@@ -426,36 +421,36 @@ int S57ClassContentExplorer::GetOBJL()
 {
     if( iCurrentClass >= 0 )
         return atoi(poRegistrar->apszClassesInfo[iCurrentClass]);
-    else
-        return -1;
+
+    return -1;
 }
 
 /************************************************************************/
 /*                           GetDescription()                           */
 /************************************************************************/
 
-const char * S57ClassContentExplorer::GetDescription()
+const char * S57ClassContentExplorer::GetDescription() const
 
 {
     if( iCurrentClass >= 0 && papszCurrentFields[0] != NULL )
         return papszCurrentFields[1];
-    else
-        return NULL;
+
+    return NULL;
 }
 
 /************************************************************************/
 /*                             GetAcronym()                             */
 /************************************************************************/
 
-const char * S57ClassContentExplorer::GetAcronym()
+const char * S57ClassContentExplorer::GetAcronym() const
 
 {
-    if( iCurrentClass >= 0 
-        && papszCurrentFields[0] != NULL 
+    if( iCurrentClass >= 0
+        && papszCurrentFields[0] != NULL
         && papszCurrentFields[1] != NULL )
         return papszCurrentFields[2];
-    else
-        return NULL;
+
+    return NULL;
 }
 
 /************************************************************************/
@@ -470,7 +465,7 @@ char **S57ClassContentExplorer::GetAttributeList( const char * pszType )
 {
     if( iCurrentClass < 0 )
         return NULL;
-    
+
     CSLDestroy( papszTempResult );
     papszTempResult = NULL;
 
@@ -478,16 +473,14 @@ char **S57ClassContentExplorer::GetAttributeList( const char * pszType )
     {
         if( pszType != NULL && iColumn == 3 && !EQUAL(pszType,"a") )
             continue;
-        
+
         if( pszType != NULL && iColumn == 4 && !EQUAL(pszType,"b") )
             continue;
-        
+
         if( pszType != NULL && iColumn == 5 && !EQUAL(pszType,"c") )
             continue;
 
-        char    **papszTokens;
-
-        papszTokens =
+        char **papszTokens =
             CSLTokenizeStringComplex( papszCurrentFields[iColumn], ";",
                                       TRUE, FALSE );
 
@@ -504,7 +497,7 @@ char **S57ClassContentExplorer::GetAttributeList( const char * pszType )
 /*                            GetClassCode()                            */
 /************************************************************************/
 
-char S57ClassContentExplorer::GetClassCode()
+char S57ClassContentExplorer::GetClassCode() const
 
 {
     if( iCurrentClass >= 0
@@ -513,11 +506,11 @@ char S57ClassContentExplorer::GetClassCode()
         && papszCurrentFields[2] != NULL
         && papszCurrentFields[3] != NULL
         && papszCurrentFields[4] != NULL
-        && papszCurrentFields[5] != NULL 
+        && papszCurrentFields[5] != NULL
         && papszCurrentFields[6] != NULL )
         return papszCurrentFields[6][0];
-    else
-        return '\0';
+
+    return '\0';
 }
 
 /************************************************************************/
@@ -531,13 +524,13 @@ char **S57ClassContentExplorer::GetPrimitives()
         && CSLCount(papszCurrentFields) > 7 )
     {
         CSLDestroy( papszTempResult );
-        papszTempResult = 
+        papszTempResult =
             CSLTokenizeStringComplex( papszCurrentFields[7], ";",
                                       TRUE, FALSE );
         return papszTempResult;
     }
-    else
-        return NULL;
+
+    return NULL;
 }
 
 /************************************************************************/
@@ -548,8 +541,8 @@ const S57AttrInfo *S57ClassRegistrar::GetAttrInfo(int iAttr)
 {
     if( iAttr < 0 || iAttr >= (int) aoAttrInfos.size() )
         return NULL;
-    else 
-        return aoAttrInfos[iAttr];
+
+    return aoAttrInfos[iAttr];
 }
 
 /************************************************************************/
@@ -559,17 +552,13 @@ const S57AttrInfo *S57ClassRegistrar::GetAttrInfo(int iAttr)
 int    S57ClassRegistrar::FindAttrByAcronym( const char * pszName )
 
 {
-    int         iStart, iEnd, iCandidate;
-
-    iStart = 0;
-    iEnd = nAttrCount-1;
+    int iStart = 0;
+    int iEnd = nAttrCount-1;
 
     while( iStart <= iEnd )
     {
-        int     nCompareValue;
-        
-        iCandidate = (iStart + iEnd)/2;
-        nCompareValue =
+        const int iCandidate = (iStart + iEnd)/2;
+        int nCompareValue =
             strcmp(pszName, aoAttrInfos[anAttrIndex[iCandidate]]->osAcronym);
 
         if( nCompareValue < 0 )
diff --git a/ogr/ogrsf_frmts/s57/s57dump.cpp b/ogr/ogrsf_frmts/s57/s57dump.cpp
index 814a291..5f8c8af 100644
--- a/ogr/ogrsf_frmts/s57/s57dump.cpp
+++ b/ogr/ogrsf_frmts/s57/s57dump.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: s57dump.cpp 26388 2013-09-02 18:04:16Z warmerdam $
+ * $Id: s57dump.cpp 32445 2015-12-25 01:28:55Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Simple client for viewing S57 driver data.
@@ -27,11 +27,11 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "s57.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "s57.h"
 
-CPL_CVSID("$Id: s57dump.cpp 26388 2013-09-02 18:04:16Z warmerdam $");
+CPL_CVSID("$Id: s57dump.cpp 32445 2015-12-25 01:28:55Z goatbar $");
 
 /************************************************************************/
 /*                                main()                                */
@@ -40,13 +40,10 @@ CPL_CVSID("$Id: s57dump.cpp 26388 2013-09-02 18:04:16Z warmerdam $");
 int main( int nArgc, char ** papszArgv )
 
 {
-    char        **papszOptions = NULL;
-    int         bReturnPrimitives = FALSE;
-    char       *pszDataPath = NULL;
-    
     if( nArgc < 2 )
     {
-        printf( "Usage: s57dump [-pen] [-split] [-lnam] [-return-prim] [-no-update]\n"
+        printf( "Usage: s57dump [-pen] [-split] [-lnam] [-return-prim] "
+                "[-no-update]\n"
                 "               [-return-link] [-data <dirpath>] filename\n" );
         exit( 1 );
     }
@@ -54,6 +51,10 @@ int main( int nArgc, char ** papszArgv )
 /* -------------------------------------------------------------------- */
 /*      Process commandline arguments.                                  */
 /* -------------------------------------------------------------------- */
+    char **papszOptions = NULL;
+    bool bReturnPrimitives = false;
+    char *pszDataPath = NULL;
+
     for( int iArg = 1; iArg < nArgc-1; iArg++ )
     {
         if( EQUAL(papszArgv[iArg],"-split") )
@@ -68,91 +69,91 @@ int main( int nArgc, char ** papszArgv )
             papszOptions =
                 CSLSetNameValue( papszOptions, S57O_PRESERVE_EMPTY_NUMBERS,
                                  "ON" );
-        else if( EQUALN(papszArgv[iArg],"-return-prim",12) )
+        else if( STARTS_WITH_CI(papszArgv[iArg], "-return-prim") )
         {
             papszOptions =
                 CSLSetNameValue( papszOptions, S57O_RETURN_PRIMITIVES,
                                  "ON" );
-            bReturnPrimitives = TRUE;
+            bReturnPrimitives = true;
         }
-        else if( EQUALN(papszArgv[iArg],"-lnam",4) )
+        else if( STARTS_WITH_CI(papszArgv[iArg],"-lnam") )
             papszOptions =
                 CSLSetNameValue( papszOptions, S57O_LNAM_REFS, "ON" );
-        else if( EQUALN(papszArgv[iArg],"-return-link",12) )
+        else if( STARTS_WITH_CI(papszArgv[iArg], "-return-link") )
             papszOptions =
                 CSLSetNameValue( papszOptions, S57O_RETURN_LINKAGES, "ON" );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Load the class definitions into the registrar.                  */
 /* -------------------------------------------------------------------- */
-    S57ClassRegistrar   oRegistrar;
-    int                 bRegistrarLoaded;
-
-    bRegistrarLoaded = oRegistrar.LoadInfo( pszDataPath, NULL, TRUE );
+    S57ClassRegistrar oRegistrar;
+    bool bRegistrarLoaded = oRegistrar.LoadInfo( pszDataPath, NULL, true );
 
     S57ClassContentExplorer *poClassContentExplorer = NULL;
     if (bRegistrarLoaded)
         poClassContentExplorer = new S57ClassContentExplorer(&oRegistrar);
-            
+
 /* -------------------------------------------------------------------- */
 /*      Get a list of candidate files.                                  */
 /* -------------------------------------------------------------------- */
-    char        **papszFiles;
-    int         iFile;
-
-    papszFiles = S57FileCollector( papszArgv[nArgc-1] );
+    char **papszFiles = S57FileCollector( papszArgv[nArgc-1] );
 
-    for( iFile = 0; papszFiles != NULL && papszFiles[iFile] != NULL; iFile++ )
+    for( int iFile = 0;
+         papszFiles != NULL && papszFiles[iFile] != NULL;
+         iFile++ )
     {
         printf( "Found: %s\n", papszFiles[iFile] );
     }
 
-    for( iFile = 0; papszFiles != NULL && papszFiles[iFile] != NULL; iFile++ )
+    for( int iFile = 0;
+         papszFiles != NULL && papszFiles[iFile] != NULL;
+         iFile++ )
     {
-        printf( "<------------------------------------------------------------------------->\n" );
+        printf( "<------------------------------------------------------------"
+                "------------->\n" );
         printf( "\nFile: %s\n\n", papszFiles[iFile] );
-        
-        S57Reader       oReader( papszFiles[iFile] );
+
+        S57Reader oReader( papszFiles[iFile] );
 
         oReader.SetOptions( papszOptions );
-        
-        int             nOptionFlags = oReader.GetOptionFlags();
 
         if( !oReader.Open( FALSE ) )
             continue;
 
+        int nOptionFlags = oReader.GetOptionFlags();
+
         if( bRegistrarLoaded )
         {
-            int bGeneric = FALSE;
+            bool bGeneric = false;
             std::vector<int> anClassList;
-            unsigned int i;
+
             oReader.CollectClassList(anClassList);
 
             oReader.SetClassBased( &oRegistrar, poClassContentExplorer );
 
             printf( "Classes found:\n" );
-            for( i = 0; i < anClassList.size(); i++ )
+            for( unsigned int i = 0; i < anClassList.size(); i++ )
             {
                 if( anClassList[i] == 0 )
                     continue;
-                
+
                 if( poClassContentExplorer->SelectClass( i ) )
                 {
-                    printf( "%d: %s/%s\n",
+                    printf( "%u: %s/%s\n",
                             i,
                             poClassContentExplorer->GetAcronym(),
                             poClassContentExplorer->GetDescription() );
-                    
+
                     oReader.AddFeatureDefn(
-                        S57GenerateObjectClassDefn( &oRegistrar, 
+                        S57GenerateObjectClassDefn( &oRegistrar,
                                                     poClassContentExplorer,
                                                     i, nOptionFlags ) );
                 }
                 else
                 {
-                    printf( "%d: unrecognised ... treat as generic.\n", i );
-                    bGeneric = TRUE;
+                    printf( "%u: unrecognized ... treat as generic.\n", i );
+                    bGeneric = true;
                 }
             }
 
@@ -176,21 +177,20 @@ int main( int nArgc, char ** papszArgv )
 
         if( bReturnPrimitives )
         {
-            oReader.AddFeatureDefn( 
+            oReader.AddFeatureDefn(
                 S57GenerateVectorPrimitiveFeatureDefn( RCNM_VI, nOptionFlags));
-            oReader.AddFeatureDefn( 
+            oReader.AddFeatureDefn(
                 S57GenerateVectorPrimitiveFeatureDefn( RCNM_VC, nOptionFlags));
-            oReader.AddFeatureDefn( 
+            oReader.AddFeatureDefn(
                 S57GenerateVectorPrimitiveFeatureDefn( RCNM_VE, nOptionFlags));
-            oReader.AddFeatureDefn( 
+            oReader.AddFeatureDefn(
                 S57GenerateVectorPrimitiveFeatureDefn( RCNM_VF, nOptionFlags));
         }
-    
+
         oReader.AddFeatureDefn( S57GenerateDSIDFeatureDefn() );
 
         OGRFeature      *poFeature;
         int             nFeatures = 0;
-        DDFModule       oUpdate;
 
         while( (poFeature = oReader.ReadNextFeature()) != NULL )
         {
diff --git a/ogr/ogrsf_frmts/s57/s57featuredefns.cpp b/ogr/ogrsf_frmts/s57/s57featuredefns.cpp
index a52934e..acdc18f 100644
--- a/ogr/ogrsf_frmts/s57/s57featuredefns.cpp
+++ b/ogr/ogrsf_frmts/s57/s57featuredefns.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: s57featuredefns.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: s57featuredefns.cpp 33271 2016-01-30 16:01:55Z goatbar $
  *
  * Project:  S-57 Translator
  * Purpose:  Implements methods to create OGRFeatureDefns for various
@@ -28,12 +28,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "s57.h"
-#include "ogr_api.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "ogr_api.h"
+#include "s57.h"
 
-CPL_CVSID("$Id: s57featuredefns.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: s57featuredefns.cpp 33271 2016-01-30 16:01:55Z goatbar $");
 
 
 /************************************************************************/
@@ -44,7 +44,6 @@ OGRFeatureDefn *S57GenerateDSIDFeatureDefn()
 
 {
     OGRFeatureDefn      *poFDefn = new OGRFeatureDefn( "DSID" );
-    OGRFieldDefn         oField( "", OFTInteger );
 
     poFDefn->SetGeomType( wkbNone );
     poFDefn->Reference();
@@ -52,122 +51,124 @@ OGRFeatureDefn *S57GenerateDSIDFeatureDefn()
 /* -------------------------------------------------------------------- */
 /*      DSID fields.                                                    */
 /* -------------------------------------------------------------------- */
+    OGRFieldDefn oField( "", OFTInteger );
+
     oField.Set( "DSID_EXPP", OFTInteger, 3, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSID_INTU", OFTInteger, 3, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSID_DSNM", OFTString, 0, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSID_EDTN", OFTString, 0, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSID_UPDN", OFTString, 0, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSID_UADT", OFTString, 8, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSID_ISDT", OFTString, 8, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSID_STED", OFTReal, 11, 6 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSID_PRSP", OFTInteger, 3, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSID_PSDN", OFTString, 0, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSID_PRED", OFTString, 0, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSID_PROF", OFTInteger, 3, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSID_AGEN", OFTInteger, 5, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSID_COMT", OFTString, 0, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
 /* -------------------------------------------------------------------- */
 /*      DSSI fields.                                                    */
 /* -------------------------------------------------------------------- */
 
     oField.Set( "DSSI_DSTR", OFTInteger, 3, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSSI_AALL", OFTInteger, 3, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSSI_NALL", OFTInteger, 3, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSSI_NOMR", OFTInteger, 10, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSSI_NOCR", OFTInteger, 10, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSSI_NOGR", OFTInteger, 10, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSSI_NOLR", OFTInteger, 10, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSSI_NOIN", OFTInteger, 10, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSSI_NOCN", OFTInteger, 10, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSSI_NOED", OFTInteger, 10, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSSI_NOFA", OFTInteger, 10, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
 /* -------------------------------------------------------------------- */
 /*      DSPM fields.                                                    */
 /* -------------------------------------------------------------------- */
 
     oField.Set( "DSPM_HDAT", OFTInteger, 3, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSPM_VDAT", OFTInteger, 3, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSPM_SDAT", OFTInteger, 3, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSPM_CSCL", OFTInteger, 10, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSPM_DUNI", OFTInteger, 3, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSPM_HUNI", OFTInteger, 3, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSPM_PUNI", OFTInteger, 3, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSPM_COUN", OFTInteger, 3, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSPM_COMF", OFTInteger, 10, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSPM_SOMF", OFTInteger, 10, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     oField.Set( "DSPM_COMT", OFTString, 0, 0 );
     poFDefn->AddFieldDefn( &oField );
-    
+
     return poFDefn;
 }
 
@@ -180,8 +181,8 @@ OGRFeatureDefn *S57GenerateGeomFeatureDefn( OGRwkbGeometryType eGType,
 
 {
     OGRFeatureDefn      *poFDefn = NULL;
-    
-    if( eGType == wkbPoint )                                            
+
+    if( eGType == wkbPoint )
     {
         poFDefn = new OGRFeatureDefn( "Point" );
         poFDefn->SetGeomType( eGType );
@@ -221,7 +222,7 @@ OGRFeatureDefn *S57GenerateGeomFeatureDefn( OGRwkbGeometryType eGType,
 
 OGRFeatureDefn *
 S57GenerateVectorPrimitiveFeatureDefn( int nRCNM,
-                                       CPL_UNUSED int nOptionFlags )
+                                       int /* nOptionFlags */ )
 {
     OGRFeatureDefn      *poFDefn = NULL;
 
@@ -317,29 +318,28 @@ S57GenerateVectorPrimitiveFeatureDefn( int nRCNM,
 /*                     S57GenerateObjectClassDefn()                     */
 /************************************************************************/
 
-OGRFeatureDefn *S57GenerateObjectClassDefn( S57ClassRegistrar *poCR,
-                                            S57ClassContentExplorer* poClassContentExplorer,
-                                            int nOBJL, int nOptionFlags )
+OGRFeatureDefn *S57GenerateObjectClassDefn(
+    S57ClassRegistrar *poCR,
+    S57ClassContentExplorer* poClassContentExplorer,
+    int nOBJL, int nOptionFlags )
 
 {
-    OGRFeatureDefn      *poFDefn = NULL;
-    char               **papszGeomPrim;
-
     if( !poClassContentExplorer->SelectClass( nOBJL ) )
         return NULL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create the feature definition based on the object class         */
 /*      acronym.                                                        */
 /* -------------------------------------------------------------------- */
-    poFDefn = new OGRFeatureDefn( poClassContentExplorer->GetAcronym() );
+    OGRFeatureDefn *poFDefn
+        = new OGRFeatureDefn( poClassContentExplorer->GetAcronym() );
     poFDefn->Reference();
 
 /* -------------------------------------------------------------------- */
 /*      Try and establish the geometry type.  If more than one          */
 /*      geometry type is allowed we just fall back to wkbUnknown.       */
 /* -------------------------------------------------------------------- */
-    papszGeomPrim = poClassContentExplorer->GetPrimitives();
+    char **papszGeomPrim = poClassContentExplorer->GetPrimitives();
     if( CSLCount(papszGeomPrim) == 0 )
     {
         poFDefn->SetGeomType( wkbNone );
@@ -369,7 +369,7 @@ OGRFeatureDefn *S57GenerateObjectClassDefn( S57ClassRegistrar *poCR,
         // unfortunately this could be a multilinestring
         poFDefn->SetGeomType( wkbUnknown );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Add the standard attributes.                                    */
 /* -------------------------------------------------------------------- */
@@ -378,13 +378,13 @@ OGRFeatureDefn *S57GenerateObjectClassDefn( S57ClassRegistrar *poCR,
 /* -------------------------------------------------------------------- */
 /*      Add the attributes specific to this object class.               */
 /* -------------------------------------------------------------------- */
-    char        **papszAttrList = poClassContentExplorer->GetAttributeList();
+    char **papszAttrList = poClassContentExplorer->GetAttributeList();
 
     for( int iAttr = 0;
          papszAttrList != NULL && papszAttrList[iAttr] != NULL;
          iAttr++ )
     {
-        int     iAttrIndex = poCR->FindAttrByAcronym( papszAttrList[iAttr] );
+        const int iAttrIndex = poCR->FindAttrByAcronym( papszAttrList[iAttr] );
 
         if( iAttrIndex == -1 )
         {
@@ -395,8 +395,8 @@ OGRFeatureDefn *S57GenerateObjectClassDefn( S57ClassRegistrar *poCR,
             continue;
         }
 
-        OGRFieldDefn    oField( papszAttrList[iAttr], OFTInteger );
-        
+        OGRFieldDefn oField( papszAttrList[iAttr], OFTInteger );
+
         switch( poCR->GetAttrType( iAttrIndex ) )
         {
           case SAT_ENUM:
@@ -421,14 +421,13 @@ OGRFeatureDefn *S57GenerateObjectClassDefn( S57ClassRegistrar *poCR,
         poFDefn->AddFieldDefn( &oField );
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Do we need to add DEPTH attributes to soundings?                */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(poClassContentExplorer->GetAcronym(),"SOUNDG") 
+    if( EQUAL(poClassContentExplorer->GetAcronym(), "SOUNDG")
         && (nOptionFlags & S57M_ADD_SOUNDG_DEPTH) )
     {
-        OGRFieldDefn    oField( "DEPTH", OFTReal );
+        OGRFieldDefn oField( "DEPTH", OFTReal );
         poFDefn->AddFieldDefn( &oField );
     }
 
@@ -501,14 +500,14 @@ void S57GenerateStandardAttributes( OGRFeatureDefn *poFDefn, int nOptionFlags )
     {
         oField.Set( "LNAM", OFTString, 16, 0 );
         poFDefn->AddFieldDefn( &oField );
-        
+
         oField.Set( "LNAM_REFS", OFTStringList, 16, 0 );
         poFDefn->AddFieldDefn( &oField );
-        
+
         oField.Set( "FFPT_RIND", OFTIntegerList, 1, 0 );
         poFDefn->AddFieldDefn( &oField );
 
-        // We should likely include FFPT_COMT here. 
+        // We should likely include FFPT_COMT here.
     }
 
 /* -------------------------------------------------------------------- */
@@ -518,13 +517,13 @@ void S57GenerateStandardAttributes( OGRFeatureDefn *poFDefn, int nOptionFlags )
     {
         oField.Set( "NAME_RCNM", OFTIntegerList, 3, 0 );
         poFDefn->AddFieldDefn( &oField );
-        
+
         oField.Set( "NAME_RCID", OFTIntegerList, 10, 0 );
         poFDefn->AddFieldDefn( &oField );
-        
+
         oField.Set( "ORNT", OFTIntegerList, 1, 0 );
         poFDefn->AddFieldDefn( &oField );
-        
+
         oField.Set( "USAG", OFTIntegerList, 1, 0 );
         poFDefn->AddFieldDefn( &oField );
 
diff --git a/ogr/ogrsf_frmts/s57/s57filecollector.cpp b/ogr/ogrsf_frmts/s57/s57filecollector.cpp
index b58b209..61115fd 100644
--- a/ogr/ogrsf_frmts/s57/s57filecollector.cpp
+++ b/ogr/ogrsf_frmts/s57/s57filecollector.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: s57filecollector.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: s57filecollector.cpp 33712 2016-03-12 10:51:56Z goatbar $
  *
  * Project:  S-57 Translator
  * Purpose:  Implements S57FileCollector() function.  This function collects
@@ -29,11 +29,11 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "s57.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "s57.h"
 
-CPL_CVSID("$Id: s57filecollector.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: s57filecollector.cpp 33712 2016-03-12 10:51:56Z goatbar $");
 
 /************************************************************************/
 /*                          S57FileCollector()                          */
@@ -42,12 +42,10 @@ CPL_CVSID("$Id: s57filecollector.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
 char **S57FileCollector( const char *pszDataset )
 
 {
-    VSIStatBuf  sStatBuf;
-    char        **papszRetList = NULL;
-
 /* -------------------------------------------------------------------- */
 /*      Stat the dataset, and fail if it isn't a file or directory.     */
 /* -------------------------------------------------------------------- */
+    VSIStatBuf  sStatBuf;
     if( CPLStat( pszDataset, &sStatBuf ) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -61,23 +59,22 @@ char **S57FileCollector( const char *pszDataset )
 /*      We handle directories by scanning for all S-57 data files in    */
 /*      them, but not for catalogs.                                     */
 /* -------------------------------------------------------------------- */
+    char **papszRetList = NULL;
+
     if( VSI_ISDIR(sStatBuf.st_mode) )
     {
-        char    **papszDirFiles = CPLReadDir( pszDataset );
-        int     iFile;
+        char    **papszDirFiles = VSIReadDir( pszDataset );
         DDFModule oModule;
 
-        for( iFile = 0;
+        for( int iFile = 0;
              papszDirFiles != NULL && papszDirFiles[iFile] != NULL;
              iFile++ )
         {
-            char        *pszFullFile;
-
-            pszFullFile = CPLStrdup(
+            char *pszFullFile = CPLStrdup(
                 CPLFormFilename( pszDataset, papszDirFiles[iFile], NULL ) );
 
             // Add to list if it is an S-57 _data_ file.
-            if( VSIStat( pszFullFile, &sStatBuf ) == 0 
+            if( VSIStat( pszFullFile, &sStatBuf ) == 0
                 && VSI_ISREG( sStatBuf.st_mode )
                 && oModule.Open( pszFullFile, TRUE ) )
             {
@@ -96,7 +93,6 @@ char **S57FileCollector( const char *pszDataset )
 /*      Note that the caller may still open it and fail.                */
 /* -------------------------------------------------------------------- */
     DDFModule   oModule;
-    DDFRecord   *poRecord;
 
     if( !oModule.Open(pszDataset) )
     {
@@ -107,10 +103,10 @@ char **S57FileCollector( const char *pszDataset )
         return NULL;
     }
 
-    poRecord = oModule.ReadRecord();
+    DDFRecord *poRecord = oModule.ReadRecord();
     if( poRecord == NULL )
         return NULL;
-    
+
     if( poRecord->FindField( "CATD" ) == NULL
         || oModule.FindFieldDefn("CATD")->FindSubfieldDefn( "IMPL" ) == NULL )
     {
@@ -127,25 +123,25 @@ char **S57FileCollector( const char *pszDataset )
 /* -------------------------------------------------------------------- */
     char        *pszCatDir = CPLStrdup( CPLGetPath( pszDataset ) );
     char        *pszRootDir = NULL;
-    
+
     if( CPLStat( CPLFormFilename(pszCatDir,"ENC_ROOT",NULL), &sStatBuf ) == 0
         && VSI_ISDIR(sStatBuf.st_mode) )
     {
         pszRootDir = CPLStrdup(CPLFormFilename( pszCatDir, "ENC_ROOT", NULL ));
     }
-    else if( CPLStat( CPLFormFilename( pszCatDir, "enc_root", NULL ), 
+    else if( CPLStat( CPLFormFilename( pszCatDir, "enc_root", NULL ),
                       &sStatBuf ) == 0 && VSI_ISDIR(sStatBuf.st_mode) )
     {
         pszRootDir = CPLStrdup(CPLFormFilename( pszCatDir, "enc_root", NULL ));
     }
 
     if( pszRootDir )
-        CPLDebug( "S57", "Found root directory to be %s.", 
+        CPLDebug( "S57", "Found root directory to be %s.",
                   pszRootDir );
 
 /* -------------------------------------------------------------------- */
 /*      We have a catalog.  Scan it for data files, those with an       */
-/*      IMPL of BIN.  Shouldn't there be a better way of testing        */
+/*      IMPL of BIN.  Is there be a better way of testing               */
 /*      whether a file is a data file or another catalog file?          */
 /* -------------------------------------------------------------------- */
     for( ; poRecord != NULL; poRecord = oModule.ReadRecord() )
@@ -153,24 +149,24 @@ char **S57FileCollector( const char *pszDataset )
         if( poRecord->FindField( "CATD" ) != NULL
             && EQUAL(poRecord->GetStringSubfield("CATD",0,"IMPL",0),"BIN") )
         {
-            const char  *pszFile, *pszWholePath;
+            const char  *pszFile
+                = poRecord->GetStringSubfield("CATD", 0, "FILE", 0);
 
-            pszFile = poRecord->GetStringSubfield("CATD",0,"FILE",0);
+            // Often there is an extra ENC_ROOT in the path, try finding
+            // this file.
 
-            // Often there is an extra ENC_ROOT in the path, try finding 
-            // this file. 
-
-            pszWholePath = CPLFormFilename( pszCatDir, pszFile, NULL );
+            const char  *pszWholePath
+                = CPLFormFilename( pszCatDir, pszFile, NULL );
             if( CPLStat( pszWholePath, &sStatBuf ) != 0
                 && pszRootDir != NULL )
             {
                 pszWholePath = CPLFormFilename( pszRootDir, pszFile, NULL );
             }
-                
+
             if( CPLStat( pszWholePath, &sStatBuf ) != 0 )
             {
                 CPLError( CE_Warning, CPLE_OpenFailed,
-                          "Can't find file %s from catalog %s.", 
+                          "Can't find file %s from catalog %s.",
                           pszFile, pszDataset );
                 continue;
             }
@@ -185,4 +181,3 @@ char **S57FileCollector( const char *pszDataset )
 
     return papszRetList;
 }
-
diff --git a/ogr/ogrsf_frmts/s57/s57reader.cpp b/ogr/ogrsf_frmts/s57/s57reader.cpp
index 9142910..4f51182 100644
--- a/ogr/ogrsf_frmts/s57/s57reader.cpp
+++ b/ogr/ogrsf_frmts/s57/s57reader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: s57reader.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: s57reader.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  S-57 Translator
  * Purpose:  Implements S57Reader class.
@@ -28,47 +28,44 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "s57.h"
-#include "ogr_api.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "ogr_api.h"
+#include "s57.h"
 
 #include <string>
-#include <fstream>
-
-CPL_CVSID("$Id: s57reader.cpp 27745 2014-09-27 16:38:57Z goatbar $");
 
-#ifndef PI
-#define PI  3.14159265358979323846
-#endif
+CPL_CVSID("$Id: s57reader.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
-/***************************************************************************************************************
-* Recode the given string from a source encoding to UTF-8 encoding.
-* The source encoding is established by inspecting the AALL and NALL fields of the S57 DSSI record. If first
-* time, the DSSI is read to setup appropriate variables. Main scope of this function is to have the strings
-* of all attributes encoded/recoded to the same codepage in the final Shapefiles .DBF.
-* 
-* @param[in]	SourceString: source string to be recoded to UTF-8.
-*				LookAtAALL-NALL: flag indicating if the string becomes from an international attribute (e.g.
-*								 INFORM, OBJNAM) or national attribute (e.g NINFOM, NOBJNM). The type of
-*								 encoding is contained in two different fields of the S57 DSSI record: AALL for
-*								 the international attributes, NAAL for the national ones, so depending on the
-*								 type of encoding, different fields must be checked to fetch in which way the
-*								 source string is encoded.
-*								 0: the type of endoding is for international attributes
-*								 1: the type of endoding is for national attributes
+/******************************************************************************
+* Recode the given string from a source encoding to UTF-8 encoding.  The source
+* encoding is established by inspecting the AALL and NALL fields of the S57
+* DSSI record. If first time, the DSSI is read to setup appropriate
+* variables. Main scope of this function is to have the strings of all
+* attributes encoded/recoded to the same codepage in the final Shapefiles .DBF.
+*
+* @param[in] SourceString: source string to be recoded to UTF-8.
+*     LookAtAALL-NALL: flag indicating if the string becomes from an
+*     international attribute (e.g.  INFORM, OBJNAM) or national attribute (e.g
+*     NINFOM, NOBJNM). The type of encoding is contained in two different
+*     fields of the S57 DSSI record: AALL for the international attributes,
+*     NAAL for the national ones, so depending on the type of encoding,
+*     different fields must be checked to fetch in which way the source string
+*     is encoded.
+*
+*     0: the type of endoding is for international attributes
+*     1: the type of endoding is for national attributes
 *
 * @param[out]
 *
-* @return:		- the output string recoded to UTF-8 or left unchanged if no valid recoding applicable. The
-*				recodinf relies on GDAL functions appropriately called, which allocate themselves the 
-*				necessary memory to hold the recoded string.
+* @return: the output string recoded to UTF-8 or left unchanged if no valid
+*     recoding applicable. The recodinf relies on GDAL functions appropriately
+*     called, which allocate themselves the necessary memory to hold the
+*     recoded string.
 * NOTE: Aall variable is currently not used.
-***************************************************************************************************************/
+*******************************************************************************/
 char *S57Reader::RecodeByDSSI(const char *SourceString, bool LookAtAALL_NALL)
 {
-    char *RecodedString = NULL;
-
     if(needAallNallSetup==true)
     {
         OGRFeature *dsidFeature=ReadDSID();
@@ -81,18 +78,21 @@ char *S57Reader::RecodeByDSSI(const char *SourceString, bool LookAtAALL_NALL)
         delete dsidFeature;
     }
 
+    char *RecodedString = NULL;
     if(!LookAtAALL_NALL)
     {
-        //in case of international attributes, only ISO8859-1 code page is used (standard ascii). The result
-        //is identical to the source string if it contains 0..127 ascii code (LL0), can sligthly differ if
-        //it contains diacritics 0..255 ascii codes (LL1)
+        // In case of international attributes, only ISO8859-1 code page is
+        // used (standard ascii). The result is identical to the source string
+        // if it contains 0..127 ascii code (LL0), can slightly differ if it
+        // contains diacritics 0..255 ascii codes (LL1).
         RecodedString = CPLRecode(SourceString,CPL_ENC_ISO8859_1,CPL_ENC_UTF8);
     }
     else
     {
         if(Nall==2) //national string encoded in UCS-2
         {
-            GByte* pabyStr = (GByte*)SourceString;
+            GByte *pabyStr = reinterpret_cast<GByte *>(
+                const_cast<char *>( SourceString ) );
 
             /* Count the number of characters */
             int i=0;
@@ -100,17 +100,18 @@ char *S57Reader::RecodeByDSSI(const char *SourceString, bool LookAtAALL_NALL)
                       (pabyStr[2 * i] == 0 && pabyStr[2 * i + 1] == 0)) )
                 i++;
 
-            wchar_t *wideString = (wchar_t*) CPLMalloc((i+1) * sizeof(wchar_t));
+            wchar_t *wideString
+                = static_cast<wchar_t*>( CPLMalloc((i+1) * sizeof(wchar_t)) );
             i = 0;
-            int bLittleEndian = TRUE;
+            bool bLittleEndian = true;
 
             /* Skip BOM */
             if( pabyStr[0] == 0xFF && pabyStr[1] == 0xFE )
-                i ++;
+                i++;
             else if( pabyStr[0] == 0xFE && pabyStr[1] == 0xFF )
             {
-                bLittleEndian = FALSE;
-                i ++;
+                bLittleEndian = false;
+                i++;
             }
 
             int j=0;
@@ -127,15 +128,17 @@ char *S57Reader::RecodeByDSSI(const char *SourceString, bool LookAtAALL_NALL)
             RecodedString = CPLRecodeFromWChar(wideString,CPL_ENC_UCS2,CPL_ENC_UTF8);
             CPLFree(wideString);
         }
-        else        //national string encoded as ISO8859-1 (see comment for above on LL0/LL1)
+        else
         {
+            // National string encoded as ISO8859-1.
+            // See comment for above on LL0/LL1).
             RecodedString = CPLRecode(SourceString,CPL_ENC_ISO8859_1,CPL_ENC_UTF8);
         }
     }
 
     if( RecodedString == NULL )
         RecodedString = CPLStrdup(SourceString);
-    
+
     return(RecodedString);
 }
 
@@ -143,49 +146,36 @@ char *S57Reader::RecodeByDSSI(const char *SourceString, bool LookAtAALL_NALL)
 /*                             S57Reader()                              */
 /************************************************************************/
 
-S57Reader::S57Reader( const char * pszFilename )
-
+S57Reader::S57Reader( const char * pszFilename ) :
+    poRegistrar(NULL),
+    poClassContentExplorer(NULL),
+    nFDefnCount(0),
+    papoFDefnList(NULL),
+    pszModuleName(CPLStrdup( pszFilename )),
+    pszDSNM(NULL),
+    poModule(NULL),
+    nCOMF(1000000),
+    nSOMF(10),
+    bFileIngested(false),
+    nNextVIIndex(0),
+    nNextVCIndex(0),
+    nNextVEIndex(0),
+    nNextVFIndex(0),
+    nNextFEIndex(0),
+    nNextDSIDIndex(0),
+    poDSIDRecord(NULL),
+    poDSPMRecord(NULL),
+    papszOptions(NULL),
+    nOptionFlags(S57M_UPDATES),
+    iPointOffset(0),
+    poMultiPoint(NULL),
+    Aall(0),  // See RecodeByDSSI() function.
+    Nall(0),  // See RecodeByDSSI() function.
+    needAallNallSetup(true),  // See RecodeByDSSI() function.
+    bMissingWarningIssued(false),
+    bAttrWarningIssued(false)
 {
-    pszModuleName = CPLStrdup( pszFilename );
-    pszDSNM = NULL;
-
-    poModule = NULL;
-
-    nFDefnCount = 0;
-    papoFDefnList = NULL;
-
-    nCOMF = 1000000;
-    nSOMF = 10;
-
-    poRegistrar = NULL;
-    poClassContentExplorer = NULL;
-    bFileIngested = FALSE;
-
-    nNextFEIndex = 0;
-    nNextVIIndex = 0;
-    nNextVCIndex = 0;
-    nNextVEIndex = 0;
-    nNextVFIndex = 0;
-    nNextDSIDIndex = 0;
-
-    poDSIDRecord = NULL;
-    poDSPMRecord = NULL;
     szUPDNUpdate[0] = '\0';
-
-    iPointOffset = 0;
-    poMultiPoint = NULL;
-
-    papszOptions = NULL;
-
-    nOptionFlags = S57M_UPDATES;
-
-    bMissingWarningIssued = FALSE;
-    bAttrWarningIssued = FALSE;
-
-    Aall=0;                 // see RecodeByDSSI() function
-    Nall=0;                 // see RecodeByDSSI() function
-    needAallNallSetup=true; // see RecodeByDSSI() function
-    
 }
 
 /************************************************************************/
@@ -196,7 +186,7 @@ S57Reader::~S57Reader()
 
 {
     Close();
-    
+
     CPLFree( pszModuleName );
     CSLDestroy( papszOptions );
 
@@ -253,7 +243,7 @@ int S57Reader::Open( int bTestOpen )
     nNextVEIndex = 0;
     nNextVFIndex = 0;
     nNextDSIDIndex = 0;
-    
+
     return TRUE;
 }
 
@@ -288,7 +278,7 @@ void S57Reader::Close()
         delete poModule;
         poModule = NULL;
 
-        bFileIngested = FALSE;
+        bFileIngested = false;
 
         CPLFree( pszDSNM );
         pszDSNM = NULL;
@@ -322,20 +312,22 @@ OGRFeature *S57Reader::NextPendingMultiPoint()
 
     OGRFeatureDefn *poDefn = poMultiPoint->GetDefnRef();
     OGRFeature  *poPoint = new OGRFeature( poDefn );
-    OGRMultiPoint *poMPGeom = (OGRMultiPoint *) poMultiPoint->GetGeometryRef();
-    OGRPoint    *poSrcPoint;
+    OGRMultiPoint *poMPGeom
+        = static_cast<OGRMultiPoint *>( poMultiPoint->GetGeometryRef() );
 
     poPoint->SetFID( poMultiPoint->GetFID() );
-    
+
     for( int i = 0; i < poDefn->GetFieldCount(); i++ )
     {
         poPoint->SetField( i, poMultiPoint->GetRawFieldRef(i) );
     }
 
-    poSrcPoint = (OGRPoint *) poMPGeom->getGeometryRef( iPointOffset++ );
+    OGRPoint *poSrcPoint
+        = static_cast<OGRPoint *>( poMPGeom->getGeometryRef( iPointOffset++ ) );
+    CPLAssert( poSrcPoint != NULL );
     poPoint->SetGeometry( poSrcPoint );
 
-    if( poPoint != NULL && (nOptionFlags & S57M_ADD_SOUNDG_DEPTH) )
+    if( (nOptionFlags & S57M_ADD_SOUNDG_DEPTH) )
         poPoint->SetField( "DEPTH", poSrcPoint->getZ() );
 
     if( iPointOffset >= poMPGeom->getNumGeometries() )
@@ -351,19 +343,18 @@ OGRFeature *S57Reader::NextPendingMultiPoint()
 int S57Reader::SetOptions( char ** papszOptionsIn )
 
 {
-    const char * pszOptionValue;
-    
     CSLDestroy( papszOptions );
     papszOptions = CSLDuplicate( papszOptionsIn );
 
-    pszOptionValue = CSLFetchNameValue( papszOptions, S57O_SPLIT_MULTIPOINT );
-    if( pszOptionValue != NULL && CSLTestBoolean(pszOptionValue) )
+    const char *pszOptionValue
+        = CSLFetchNameValue( papszOptions, S57O_SPLIT_MULTIPOINT );
+    if( pszOptionValue != NULL && CPLTestBool(pszOptionValue) )
         nOptionFlags |= S57M_SPLIT_MULTIPOINT;
     else
         nOptionFlags &= ~S57M_SPLIT_MULTIPOINT;
 
     pszOptionValue = CSLFetchNameValue( papszOptions, S57O_ADD_SOUNDG_DEPTH );
-    if( pszOptionValue != NULL && CSLTestBoolean(pszOptionValue) )
+    if( pszOptionValue != NULL && CPLTestBool(pszOptionValue) )
         nOptionFlags |= S57M_ADD_SOUNDG_DEPTH;
     else
         nOptionFlags &= ~S57M_ADD_SOUNDG_DEPTH;
@@ -372,12 +363,13 @@ int S57Reader::SetOptions( char ** papszOptionsIn )
         !(nOptionFlags & S57M_SPLIT_MULTIPOINT) )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
-                 "Inconsistent options : ADD_SOUNDG_DEPTH should only be enabled if SPLIT_MULTIPOINT is also enabled");
+                 "Inconsistent options : ADD_SOUNDG_DEPTH should only be "
+                 "enabled if SPLIT_MULTIPOINT is also enabled");
         return FALSE;
     }
 
     pszOptionValue = CSLFetchNameValue( papszOptions, S57O_LNAM_REFS );
-    if( pszOptionValue != NULL && CSLTestBoolean(pszOptionValue) )
+    if( pszOptionValue != NULL && CPLTestBool(pszOptionValue) )
         nOptionFlags |= S57M_LNAM_REFS;
     else
         nOptionFlags &= ~S57M_LNAM_REFS;
@@ -390,33 +382,33 @@ int S57Reader::SetOptions( char ** papszOptionsIn )
     else
         nOptionFlags |= S57M_UPDATES;
 
-    pszOptionValue = CSLFetchNameValue(papszOptions, 
+    pszOptionValue = CSLFetchNameValue(papszOptions,
                                        S57O_PRESERVE_EMPTY_NUMBERS);
-    if( pszOptionValue != NULL && CSLTestBoolean(pszOptionValue) )
+    if( pszOptionValue != NULL && CPLTestBool(pszOptionValue) )
         nOptionFlags |= S57M_PRESERVE_EMPTY_NUMBERS;
     else
         nOptionFlags &= ~S57M_PRESERVE_EMPTY_NUMBERS;
 
     pszOptionValue = CSLFetchNameValue( papszOptions, S57O_RETURN_PRIMITIVES );
-    if( pszOptionValue != NULL && CSLTestBoolean(pszOptionValue) )
+    if( pszOptionValue != NULL && CPLTestBool(pszOptionValue) )
         nOptionFlags |= S57M_RETURN_PRIMITIVES;
     else
         nOptionFlags &= ~S57M_RETURN_PRIMITIVES;
 
     pszOptionValue = CSLFetchNameValue( papszOptions, S57O_RETURN_LINKAGES );
-    if( pszOptionValue != NULL && CSLTestBoolean(pszOptionValue) )
+    if( pszOptionValue != NULL && CPLTestBool(pszOptionValue) )
         nOptionFlags |= S57M_RETURN_LINKAGES;
     else
         nOptionFlags &= ~S57M_RETURN_LINKAGES;
 
     pszOptionValue = CSLFetchNameValue( papszOptions, S57O_RETURN_DSID );
-    if( pszOptionValue == NULL || CSLTestBoolean(pszOptionValue) )
+    if( pszOptionValue == NULL || CPLTestBool(pszOptionValue) )
         nOptionFlags |= S57M_RETURN_DSID;
     else
         nOptionFlags &= ~S57M_RETURN_DSID;
 
     pszOptionValue = CSLFetchNameValue( papszOptions, S57O_RECODE_BY_DSSI );
-    if( pszOptionValue != NULL && CSLTestBoolean(pszOptionValue) )
+    if( pszOptionValue != NULL && CPLTestBool(pszOptionValue) )
         nOptionFlags |= S57M_RECODE_BY_DSSI;
     else
         nOptionFlags &= ~S57M_RECODE_BY_DSSI;
@@ -462,8 +454,6 @@ void S57Reader::Rewind()
 int S57Reader::Ingest()
 
 {
-    DDFRecord   *poRecord;
-    
     if( poModule == NULL || bFileIngested )
         return TRUE;
 
@@ -472,16 +462,17 @@ int S57Reader::Ingest()
 /*      appropriate indexes.                                            */
 /* -------------------------------------------------------------------- */
     CPLErrorReset();
+    DDFRecord *poRecord;
     while( (poRecord = poModule->ReadRecord()) != NULL )
     {
         DDFField        *poKeyField = poRecord->GetField(1);
         if (poKeyField == NULL)
             return FALSE;
-        
+
         if( EQUAL(poKeyField->GetFieldDefn()->GetName(),"VRID") )
         {
-            int         nRCNM = poRecord->GetIntSubfield( "VRID",0, "RCNM",0);
-            int         nRCID = poRecord->GetIntSubfield( "VRID",0, "RCID",0);
+            const int nRCNM = poRecord->GetIntSubfield( "VRID",0, "RCNM",0 );
+            const int nRCID = poRecord->GetIntSubfield( "VRID",0, "RCID",0 );
 
             switch( nRCNM )
             {
@@ -511,7 +502,7 @@ int S57Reader::Ingest()
         else if( EQUAL(poKeyField->GetFieldDefn()->GetName(),"FRID") )
         {
             int         nRCID = poRecord->GetIntSubfield( "FRID",0, "RCID",0);
-            
+
             oFE_Index.AddRecord( nRCID, poRecord->Clone() );
         }
 
@@ -555,15 +546,15 @@ int S57Reader::Ingest()
     if( CPLGetLastErrorType() == CE_Failure )
         return FALSE;
 
-    bFileIngested = TRUE;
+    bFileIngested = true;
 
 /* -------------------------------------------------------------------- */
 /*      If update support is enabled, read and apply them.              */
 /* -------------------------------------------------------------------- */
     if( nOptionFlags & S57M_UPDATES )
         return FindAndApplyUpdates();
-    else
-        return TRUE;
+
+    return TRUE;
 }
 
 /************************************************************************/
@@ -587,7 +578,7 @@ void S57Reader::SetNextFEIndex( int nNewIndex, int nRCNM )
     {
         if( nNextFEIndex != nNewIndex )
             ClearPendingMultiPoint();
-        
+
         nNextFEIndex = nNewIndex;
     }
 }
@@ -601,16 +592,16 @@ int S57Reader::GetNextFEIndex( int nRCNM )
 {
     if( nRCNM == RCNM_VI )
         return nNextVIIndex;
-    else if( nRCNM == RCNM_VC )
+    if( nRCNM == RCNM_VC )
         return nNextVCIndex;
-    else if( nRCNM == RCNM_VE )
+    if( nRCNM == RCNM_VE )
         return nNextVEIndex;
-    else if( nRCNM == RCNM_VF )
+    if( nRCNM == RCNM_VF )
         return nNextVFIndex;
-    else if( nRCNM == RCNM_DSID )
+    if( nRCNM == RCNM_DSID )
         return nNextDSIDIndex;
-    else
-        return nNextFEIndex;
+
+    return nNextFEIndex;
 }
 
 /************************************************************************/
@@ -641,13 +632,13 @@ OGRFeature * S57Reader::ReadNextFeature( OGRFeatureDefn * poTarget )
 /* -------------------------------------------------------------------- */
 /*      Next vector feature?                                            */
 /* -------------------------------------------------------------------- */
-    if( (nOptionFlags & S57M_RETURN_DSID) 
-        && nNextDSIDIndex == 0 
+    if( (nOptionFlags & S57M_RETURN_DSID)
+        && nNextDSIDIndex == 0
         && (poTarget == NULL || EQUAL(poTarget->GetName(),"DSID")) )
     {
         return ReadDSID();
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Next vector feature?                                            */
 /* -------------------------------------------------------------------- */
@@ -713,17 +704,14 @@ OGRFeature * S57Reader::ReadNextFeature( OGRFeatureDefn * poTarget )
             }
         }
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Next feature.                                                   */
 /* -------------------------------------------------------------------- */
     while( nNextFEIndex < oFE_Index.GetCount() )
     {
-        OGRFeature      *poFeature;
-        OGRFeatureDefn *poFeatureDefn;
-
-        poFeatureDefn = (OGRFeatureDefn *) 
-            oFE_Index.GetClientInfoByIndex( nNextFEIndex );
+        OGRFeatureDefn *poFeatureDefn
+          = static_cast<OGRFeatureDefn *>( oFE_Index.GetClientInfoByIndex( nNextFEIndex ) );
 
         if( poFeatureDefn == NULL )
         {
@@ -737,7 +725,7 @@ OGRFeature * S57Reader::ReadNextFeature( OGRFeatureDefn * poTarget )
             continue;
         }
 
-        poFeature = ReadFeature( nNextFEIndex++, poTarget );
+        OGRFeature *poFeature = ReadFeature( nNextFEIndex++, poTarget );
         if( poFeature != NULL )
         {
             if( (nOptionFlags & S57M_SPLIT_MULTIPOINT)
@@ -766,13 +754,13 @@ OGRFeature * S57Reader::ReadNextFeature( OGRFeatureDefn * poTarget )
 OGRFeature *S57Reader::ReadFeature( int nFeatureId, OGRFeatureDefn *poTarget )
 
 {
-    OGRFeature  *poFeature;
-
     if( nFeatureId < 0 || nFeatureId >= oFE_Index.GetCount() )
         return NULL;
 
-    if( (nOptionFlags & S57M_RETURN_DSID) 
-        && nFeatureId == 0 
+    OGRFeature  *poFeature = NULL;
+
+    if( (nOptionFlags & S57M_RETURN_DSID)
+        && nFeatureId == 0
         && (poTarget == NULL || EQUAL(poTarget->GetName(),"DSID")) )
     {
         poFeature = ReadDSID();
@@ -799,16 +787,13 @@ OGRFeature *S57Reader::AssembleFeature( DDFRecord * poRecord,
                                         OGRFeatureDefn * poTarget )
 
 {
-    int         nPRIM, nOBJL;
-    OGRFeatureDefn *poFDefn;
-
 /* -------------------------------------------------------------------- */
 /*      Find the feature definition to use.  Currently this is based    */
 /*      on the primitive, but eventually this should be based on the    */
 /*      object class (FRID.OBJL) in some cases, and the primitive in    */
 /*      others.                                                         */
 /* -------------------------------------------------------------------- */
-    poFDefn = FindFDefn( poRecord );
+    OGRFeatureDefn *poFDefn = FindFDefn( poRecord );
     if( poFDefn == NULL )
         return NULL;
 
@@ -822,14 +807,12 @@ OGRFeature *S57Reader::AssembleFeature( DDFRecord * poRecord,
 /* -------------------------------------------------------------------- */
 /*      Create the new feature object.                                  */
 /* -------------------------------------------------------------------- */
-    OGRFeature          *poFeature;
-
-    poFeature = new OGRFeature( poFDefn );
+    OGRFeature *poFeature = new OGRFeature( poFDefn );
 
 /* -------------------------------------------------------------------- */
-/*      Assign a few standard feature attribues.                        */
+/*      Assign a few standard feature attributes.                        */
 /* -------------------------------------------------------------------- */
-    nOBJL = poRecord->GetIntSubfield( "FRID", 0, "OBJL", 0 );
+    int nOBJL = poRecord->GetIntSubfield( "FRID", 0, "OBJL", 0 );
     poFeature->SetField( "OBJL", nOBJL );
 
     poFeature->SetField( "RCID",
@@ -870,7 +853,7 @@ OGRFeature *S57Reader::AssembleFeature( DDFRecord * poRecord,
 /* -------------------------------------------------------------------- */
 /*      Find and assign spatial component.                              */
 /* -------------------------------------------------------------------- */
-    nPRIM = poRecord->GetIntSubfield( "FRID", 0, "PRIM", 0 );
+    const int nPRIM = poRecord->GetIntSubfield( "FRID", 0, "PRIM", 0 );
 
     if( nPRIM == PRIM_P )
     {
@@ -903,16 +886,16 @@ void S57Reader::ApplyObjectClassAttributes( DDFRecord * poRecord,
 /*      ATTF Attributes                                                 */
 /* -------------------------------------------------------------------- */
     DDFField    *poATTF = poRecord->FindField( "ATTF" );
-    int         nAttrCount, iAttr;
 
     if( poATTF == NULL )
         return;
 
-    nAttrCount = poATTF->GetRepeatCount();
-    for( iAttr = 0; iAttr < nAttrCount; iAttr++ )
+    int nAttrCount = poATTF->GetRepeatCount();
+    for( int iAttr = 0; iAttr < nAttrCount; iAttr++ )
     {
-        int     nAttrId = poRecord->GetIntSubfield("ATTF",0,"ATTL",iAttr);
-        
+        const int nAttrId
+            = poRecord->GetIntSubfield( "ATTF", 0, "ATTL", iAttr );
+
         if( poRegistrar->GetAttrInfo(nAttrId) == NULL )
         {
             if( !bAttrWarningIssued )
@@ -921,8 +904,9 @@ void S57Reader::ApplyObjectClassAttributes( DDFRecord * poRecord,
                 CPLError( CE_Warning, CPLE_AppDefined,
                           "Illegal feature attribute id (ATTF:ATTL[%d]) of %d\n"
                           "on feature FIDN=%d, FIDS=%d.\n"
-                          "Skipping attribute, no more warnings will be issued.",
-                          iAttr, nAttrId, 
+                          "Skipping attribute. "
+                          "No more warnings will be issued.",
+                          iAttr, nAttrId,
                           poFeature->GetFieldAsInteger( "FIDN" ),
                           poFeature->GetFieldAsInteger( "FIDS" ) );
             }
@@ -931,8 +915,8 @@ void S57Reader::ApplyObjectClassAttributes( DDFRecord * poRecord,
         }
 
         /* Fetch the attribute value */
-        const char *pszValue;
-        pszValue = poRecord->GetStringSubfield("ATTF",0,"ATVL",iAttr);
+        const char *pszValue =
+            poRecord->GetStringSubfield("ATTF",0,"ATVL",iAttr);
         if( pszValue == NULL )
             return;
 
@@ -942,26 +926,24 @@ void S57Reader::ApplyObjectClassAttributes( DDFRecord * poRecord,
             pszValue = pszValueToFree = RecodeByDSSI(pszValue,false);
 
         /* Apply to feature in an appropriate way */
-        int iField;
-        OGRFieldDefn *poFldDefn;
-
         const char *pszAcronym = poRegistrar->GetAttrAcronym(nAttrId);
-        iField = poFeature->GetDefnRef()->GetFieldIndex(pszAcronym);
+        const int iField = poFeature->GetDefnRef()->GetFieldIndex(pszAcronym);
         if( iField < 0 )
         {
             if( !bMissingWarningIssued )
             {
                 bMissingWarningIssued = TRUE;
-                CPLError( CE_Warning, CPLE_AppDefined, 
+                CPLError( CE_Warning, CPLE_AppDefined,
                           "Attributes %s ignored, not in expected schema.\n"
-                          "No more warnings will be issued for this dataset.", 
+                          "No more warnings will be issued for this dataset.",
                           pszAcronym );
             }
             CPLFree(pszValueToFree);
             continue;
         }
 
-        poFldDefn = poFeature->GetDefnRef()->GetFieldDefn( iField );
+        OGRFieldDefn *poFldDefn
+            = poFeature->GetDefnRef()->GetFieldDefn( iField );
         if( poFldDefn->GetType() == OFTInteger
             || poFldDefn->GetType() == OFTReal )
         {
@@ -992,15 +974,13 @@ void S57Reader::ApplyObjectClassAttributes( DDFRecord * poRecord,
         return;
 
     nAttrCount = poNATF->GetRepeatCount();
-    for( iAttr = 0; iAttr < nAttrCount; iAttr++ )
+    for( int iAttr = 0; iAttr < nAttrCount; iAttr++ )
     {
-        int     nAttrId = poRecord->GetIntSubfield("NATF",0,"ATTL",iAttr);
+        const int nAttrId = poRecord->GetIntSubfield("NATF",0,"ATTL",iAttr);
         const char *pszAcronym = poRegistrar->GetAttrAcronym(nAttrId);
 
         if( pszAcronym == NULL )
         {
-            static int bAttrWarningIssued = FALSE;
-
             if( !bAttrWarningIssued )
             {
                 bAttrWarningIssued = TRUE;
@@ -1008,7 +988,7 @@ void S57Reader::ApplyObjectClassAttributes( DDFRecord * poRecord,
                           "Illegal feature attribute id (NATF:ATTL[%d]) of %d\n"
                           "on feature FIDN=%d, FIDS=%d.\n"
                           "Skipping attribute, no more warnings will be issued.",
-                          iAttr, nAttrId, 
+                          iAttr, nAttrId,
                           poFeature->GetFieldAsInteger( "FIDN" ),
                           poFeature->GetFieldAsInteger( "FIDS" ) );
             }
@@ -1040,12 +1020,11 @@ void S57Reader::GenerateLNAMAndRefs( DDFRecord * poRecord,
                                      OGRFeature * poFeature )
 
 {
-    char        szLNAM[32];
-        
 /* -------------------------------------------------------------------- */
 /*      Apply the LNAM to the object.                                   */
 /* -------------------------------------------------------------------- */
-    sprintf( szLNAM, "%04X%08X%04X",
+    char szLNAM[32];
+    snprintf( szLNAM, sizeof(szLNAM), "%04X%08X%04X",
              poFeature->GetFieldAsInteger( "AGEN" ),
              poFeature->GetFieldAsInteger( "FIDN" ),
              poFeature->GetFieldAsInteger( "FIDS" ) );
@@ -1054,9 +1033,7 @@ void S57Reader::GenerateLNAMAndRefs( DDFRecord * poRecord,
 /* -------------------------------------------------------------------- */
 /*      Do we have references to other features.                        */
 /* -------------------------------------------------------------------- */
-    DDFField    *poFFPT;
-
-    poFFPT = poRecord->FindField( "FFPT" );
+    DDFField *poFFPT = poRecord->FindField( "FFPT" );
 
     if( poFFPT == NULL )
         return;
@@ -1064,23 +1041,27 @@ void S57Reader::GenerateLNAMAndRefs( DDFRecord * poRecord,
 /* -------------------------------------------------------------------- */
 /*      Apply references.                                               */
 /* -------------------------------------------------------------------- */
-    int         nRefCount = poFFPT->GetRepeatCount();
-    DDFSubfieldDefn *poLNAM, *poRIND;
-    char        **papszRefs = NULL;
-    int         *panRIND = (int *) CPLMalloc(sizeof(int) * nRefCount);
+    const int nRefCount = poFFPT->GetRepeatCount();
 
-    poLNAM = poFFPT->GetFieldDefn()->FindSubfieldDefn( "LNAM" );
-    poRIND = poFFPT->GetFieldDefn()->FindSubfieldDefn( "RIND" );
+    DDFSubfieldDefn *poLNAM
+        = poFFPT->GetFieldDefn()->FindSubfieldDefn( "LNAM" );
+    DDFSubfieldDefn *poRIND
+        = poFFPT->GetFieldDefn()->FindSubfieldDefn( "RIND" );
     if( poLNAM == NULL || poRIND == NULL )
+    {
         return;
+    }
+
+    int *panRIND = static_cast<int *>( CPLMalloc(sizeof(int) * nRefCount) );
+    char **papszRefs = NULL;
 
     for( int iRef = 0; iRef < nRefCount; iRef++ )
     {
-        unsigned char *pabyData;
-        int nMaxBytes;
+        int nMaxBytes = 0;
 
-        pabyData = (unsigned char *)
-            poFFPT->GetSubfieldData( poLNAM, &nMaxBytes, iRef );
+        unsigned char *pabyData = reinterpret_cast<unsigned char *>(
+            const_cast<char *>(
+                poFFPT->GetSubfieldData( poLNAM, &nMaxBytes, iRef ) ) );
         if( pabyData == NULL || nMaxBytes < 8 )
         {
             CSLDestroy( papszRefs );
@@ -1088,15 +1069,15 @@ void S57Reader::GenerateLNAMAndRefs( DDFRecord * poRecord,
             return;
         }
 
-        sprintf( szLNAM, "%02X%02X%02X%02X%02X%02X%02X%02X",
+        snprintf( szLNAM, sizeof(szLNAM), "%02X%02X%02X%02X%02X%02X%02X%02X",
                  pabyData[1], pabyData[0], /* AGEN */
                  pabyData[5], pabyData[4], pabyData[3], pabyData[2], /* FIDN */
                  pabyData[7], pabyData[6] );
 
         papszRefs = CSLAddString( papszRefs, szLNAM );
 
-        pabyData = (unsigned char *)
-            poFFPT->GetSubfieldData( poRIND, &nMaxBytes, iRef );
+        pabyData = reinterpret_cast<unsigned char *>(const_cast<char *>(
+            poFFPT->GetSubfieldData( poRIND, &nMaxBytes, iRef ) ) );
         if( pabyData == NULL || nMaxBytes < 1 )
         {
             CSLDestroy( papszRefs );
@@ -1124,30 +1105,25 @@ void S57Reader::GenerateFSPTAttributes( DDFRecord * poRecord,
 /* -------------------------------------------------------------------- */
 /*      Feature the spatial record containing the point.                */
 /* -------------------------------------------------------------------- */
-    DDFField    *poFSPT;
-    int         nCount, i;
-
-    poFSPT = poRecord->FindField( "FSPT" );
+    DDFField *poFSPT = poRecord->FindField( "FSPT" );
     if( poFSPT == NULL )
         return;
-        
-    nCount = poFSPT->GetRepeatCount();
+
+    const int nCount = poFSPT->GetRepeatCount();
 
 /* -------------------------------------------------------------------- */
 /*      Allocate working lists of the attributes.                       */
 /* -------------------------------------------------------------------- */
-    int *panORNT, *panUSAG, *panMASK, *panRCNM, *panRCID;
-    
-    panORNT = (int *) CPLMalloc( sizeof(int) * nCount );
-    panUSAG = (int *) CPLMalloc( sizeof(int) * nCount );
-    panMASK = (int *) CPLMalloc( sizeof(int) * nCount );
-    panRCNM = (int *) CPLMalloc( sizeof(int) * nCount );
-    panRCID = (int *) CPLMalloc( sizeof(int) * nCount );
+    int * const panORNT = static_cast<int *>( CPLMalloc( sizeof(int) * nCount ) );
+    int * const panUSAG = static_cast<int *>( CPLMalloc( sizeof(int) * nCount ) );
+    int * const panMASK = static_cast<int *>( CPLMalloc( sizeof(int) * nCount ) );
+    int * const panRCNM = static_cast<int *>( CPLMalloc( sizeof(int) * nCount ) );
+    int *panRCID = static_cast<int *>( CPLMalloc( sizeof(int) * nCount ) );
 
 /* -------------------------------------------------------------------- */
 /*      loop over all entries, decoding them.                           */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < nCount; i++ )
+    for( int i = 0; i < nCount; i++ )
     {
         panRCID[i] = ParseName( poFSPT, i, panRCNM + i );
         panORNT[i] = poRecord->GetIntSubfield( "FSPT", 0, "ORNT",i);
@@ -1191,13 +1167,13 @@ OGRFeature *S57Reader::ReadDSID()
 
     for( int i = 0; i < nFDefnCount; i++ )
     {
-        if( EQUAL(papoFDefnList[i]->GetName(),"DSID") )              
+        if( EQUAL(papoFDefnList[i]->GetName(),"DSID") )
         {
             poFDefn = papoFDefnList[i];
             break;
         }
     }
-    
+
     if( poFDefn == NULL )
     {
         //CPLAssert( FALSE );
@@ -1227,7 +1203,7 @@ OGRFeature *S57Reader::ReadDSID()
         else
             poFeature->SetField( "DSID_UPDN",
                      poDSIDRecord->GetStringSubfield( "DSID", 0, "UPDN", 0 ));
-        
+
         poFeature->SetField( "DSID_UADT",
                      poDSIDRecord->GetStringSubfield( "DSID", 0, "UADT", 0 ));
         poFeature->SetField( "DSID_ISDT",
@@ -1319,7 +1295,7 @@ OGRFeature *S57Reader::ReadDSID()
 OGRFeature *S57Reader::ReadVector( int nFeatureId, int nRCNM )
 
 {
-    DDFRecordIndex *poIndex;
+    DDFRecordIndex *poIndex = NULL;
     const char *pszFDName = NULL;
 
 /* -------------------------------------------------------------------- */
@@ -1331,12 +1307,12 @@ OGRFeature *S57Reader::ReadVector( int nFeatureId, int nRCNM )
         poIndex = &oVI_Index;
         pszFDName = OGRN_VI;
         break;
-        
+
       case RCNM_VC:
         poIndex = &oVC_Index;
         pszFDName = OGRN_VC;
         break;
-        
+
       case RCNM_VE:
         poIndex = &oVE_Index;
         pszFDName = OGRN_VE;
@@ -1346,7 +1322,7 @@ OGRFeature *S57Reader::ReadVector( int nFeatureId, int nRCNM )
         poIndex = &oVF_Index;
         pszFDName = OGRN_VF;
         break;
-        
+
       default:
         CPLAssert( FALSE );
         return NULL;
@@ -1364,13 +1340,13 @@ OGRFeature *S57Reader::ReadVector( int nFeatureId, int nRCNM )
 
     for( int i = 0; i < nFDefnCount; i++ )
     {
-        if( EQUAL(papoFDefnList[i]->GetName(),pszFDName) )              
+        if( EQUAL(papoFDefnList[i]->GetName(),pszFDName) )
         {
             poFDefn = papoFDefnList[i];
             break;
         }
     }
-    
+
     if( poFDefn == NULL )
     {
         //CPLAssert( FALSE );
@@ -1381,24 +1357,25 @@ OGRFeature *S57Reader::ReadVector( int nFeatureId, int nRCNM )
 /*      Create feature, and assign standard fields.                     */
 /* -------------------------------------------------------------------- */
     OGRFeature *poFeature = new OGRFeature( poFDefn );
-    
+
     poFeature->SetFID( nFeatureId );
 
-    poFeature->SetField( "RCNM", 
+    poFeature->SetField( "RCNM",
                          poRecord->GetIntSubfield( "VRID", 0, "RCNM",0) );
-    poFeature->SetField( "RCID", 
+    poFeature->SetField( "RCID",
                          poRecord->GetIntSubfield( "VRID", 0, "RCID",0) );
-    poFeature->SetField( "RVER", 
+    poFeature->SetField( "RVER",
                          poRecord->GetIntSubfield( "VRID", 0, "RVER",0) );
-    poFeature->SetField( "RUIN", 
+    poFeature->SetField( "RUIN",
                          poRecord->GetIntSubfield( "VRID", 0, "RUIN",0) );
 
 /* -------------------------------------------------------------------- */
 /*      Collect point geometries.                                       */
 /* -------------------------------------------------------------------- */
-    if( nRCNM == RCNM_VI || nRCNM == RCNM_VC ) 
+    if( nRCNM == RCNM_VI || nRCNM == RCNM_VC )
     {
-        double dfX=0.0, dfY=0.0, dfZ=0.0;
+        double dfX = 0.0;
+        double dfY = 0.0;
 
         if( poRecord->FindField( "SG2D" ) != NULL )
         {
@@ -1409,7 +1386,8 @@ OGRFeature *S57Reader::ReadVector( int nFeatureId, int nRCNM )
 
         else if( poRecord->FindField( "SG3D" ) != NULL ) /* presume sounding*/
         {
-            int i, nVCount = poRecord->FindField("SG3D")->GetRepeatCount();
+            double dfZ = 0.0;
+            const int nVCount = poRecord->FindField("SG3D")->GetRepeatCount();
             if( nVCount == 1 )
             {
                 dfX =poRecord->GetIntSubfield("SG3D",0,"XCOO",0)/(double)nCOMF;
@@ -1421,15 +1399,15 @@ OGRFeature *S57Reader::ReadVector( int nFeatureId, int nRCNM )
             {
                 OGRMultiPoint *poMP = new OGRMultiPoint();
 
-                for( i = 0; i < nVCount; i++ )
+                for( int i = 0; i < nVCount; i++ )
                 {
                     dfX = poRecord->GetIntSubfield("SG3D",0,"XCOO",i)
-                        / (double)nCOMF;
+                        / static_cast<double>( nCOMF );
                     dfY = poRecord->GetIntSubfield("SG3D",0,"YCOO",i)
-                        / (double)nCOMF;
+                        / static_cast<double>( nCOMF );
                     dfZ = poRecord->GetIntSubfield("SG3D",0,"VE3D",i)
-                        / (double)nSOMF;
-                    
+                        / static_cast<double>( nSOMF );
+
                     poMP->addGeometryDirectly( new OGRPoint( dfX, dfY, dfZ ) );
                 }
 
@@ -1445,16 +1423,15 @@ OGRFeature *S57Reader::ReadVector( int nFeatureId, int nRCNM )
     else if( nRCNM == RCNM_VE )
     {
         int nPoints = 0;
-        DDFField *poSG2D;
         OGRLineString *poLine = new OGRLineString();
 
         for( int iField = 0; iField < poRecord->GetFieldCount(); ++iField )
         {
-            poSG2D = poRecord->GetField( iField );
+            DDFField *poSG2D = poRecord->GetField( iField );
 
             if( EQUAL(poSG2D->GetFieldDefn()->GetName(), "SG2D") )
             {
-                int nVCount = poSG2D->GetRepeatCount();
+                const int nVCount = poSG2D->GetRepeatCount();
 
                 poLine->setNumPoints( nPoints + nVCount );
 
@@ -1462,8 +1439,10 @@ OGRFeature *S57Reader::ReadVector( int nFeatureId, int nRCNM )
                 {
                     poLine->setPoint
                         (nPoints++,
-                        poRecord->GetIntSubfield("SG2D",0,"XCOO",i) / (double)nCOMF,
-                        poRecord->GetIntSubfield("SG2D",0,"YCOO",i) / (double)nCOMF );
+                        poRecord->GetIntSubfield("SG2D",0,"XCOO",i)
+                           / static_cast<double>( nCOMF ),
+                        poRecord->GetIntSubfield("SG2D",0,"YCOO",i)
+                           / static_cast<double>(nCOMF ) );
                 }
             }
         }
@@ -1475,28 +1454,30 @@ OGRFeature *S57Reader::ReadVector( int nFeatureId, int nRCNM )
 /*      Special edge fields.                                            */
 /*      Allow either 2 VRPT fields or one VRPT field with 2 rows        */
 /* -------------------------------------------------------------------- */
-    DDFField *poVRPT;
+    DDFField *poVRPT = NULL;
 
-    if( nRCNM == RCNM_VE 
+    if( nRCNM == RCNM_VE
         && (poVRPT = poRecord->FindField( "VRPT" )) != NULL )
     {
-        int iField = 0, iSubField = 1;
-
         poFeature->SetField( "NAME_RCNM_0", RCNM_VC );
         poFeature->SetField( "NAME_RCID_0", ParseName( poVRPT ) );
-        poFeature->SetField( "ORNT_0", 
+        poFeature->SetField( "ORNT_0",
                              poRecord->GetIntSubfield("VRPT",0,"ORNT",0) );
-        poFeature->SetField( "USAG_0", 
+        poFeature->SetField( "USAG_0",
                              poRecord->GetIntSubfield("VRPT",0,"USAG",0) );
-        poFeature->SetField( "TOPI_0", 
+        poFeature->SetField( "TOPI_0",
                              poRecord->GetIntSubfield("VRPT",0,"TOPI",0) );
-        poFeature->SetField( "MASK_0", 
+        poFeature->SetField( "MASK_0",
                              poRecord->GetIntSubfield("VRPT",0,"MASK",0) );
-                             
+
+        int iField = 0;
+        int iSubField = 1;
+
         if( poVRPT != NULL && poVRPT->GetRepeatCount() == 1 )
         {
             // Only one row, need a second VRPT field
-            iField = 1; iSubField = 0;
+            iField = 1;
+            iSubField = 0;
 
             if( (poVRPT = poRecord->FindField( "VRPT", iField )) == NULL )
             {
@@ -1510,19 +1491,19 @@ OGRFeature *S57Reader::ReadVector( int nFeatureId, int nRCNM )
                 return poFeature;
             }
         }
-        
+
         poFeature->SetField( "NAME_RCID_1", ParseName( poVRPT, iSubField ) );
         poFeature->SetField( "NAME_RCNM_1", RCNM_VC );
-        poFeature->SetField( "ORNT_1", 
+        poFeature->SetField( "ORNT_1",
                              poRecord->GetIntSubfield("VRPT",iField,
                              "ORNT",iSubField) );
-        poFeature->SetField( "USAG_1", 
+        poFeature->SetField( "USAG_1",
                              poRecord->GetIntSubfield("VRPT",iField,
                              "USAG",iSubField) );
-        poFeature->SetField( "TOPI_1", 
+        poFeature->SetField( "TOPI_1",
                              poRecord->GetIntSubfield("VRPT",iField,
                              "TOPI",iSubField) );
-        poFeature->SetField( "MASK_1", 
+        poFeature->SetField( "MASK_1",
                              poRecord->GetIntSubfield("VRPT",iField,
                              "MASK",iSubField) );
     }
@@ -1540,8 +1521,8 @@ int S57Reader::FetchPoint( int nRCNM, int nRCID,
                            double * pdfX, double * pdfY, double * pdfZ )
 
 {
-    DDFRecord   *poSRecord;
-    
+    DDFRecord *poSRecord = NULL;
+
     if( nRCNM == RCNM_VI )
         poSRecord = oVI_Index.FindRecord( nRCID );
     else
@@ -1550,18 +1531,25 @@ int S57Reader::FetchPoint( int nRCNM, int nRCID,
     if( poSRecord == NULL )
         return FALSE;
 
-    double      dfX = 0.0, dfY = 0.0, dfZ = 0.0;
+    double dfX = 0.0;
+    double dfY = 0.0;
+    double dfZ = 0.0;
 
     if( poSRecord->FindField( "SG2D" ) != NULL )
     {
-        dfX = poSRecord->GetIntSubfield("SG2D",0,"XCOO",0) / (double)nCOMF;
-        dfY = poSRecord->GetIntSubfield("SG2D",0,"YCOO",0) / (double)nCOMF;
+        dfX = poSRecord->GetIntSubfield("SG2D",0,"XCOO",0)
+            / static_cast<double>( nCOMF );
+        dfY = poSRecord->GetIntSubfield("SG2D",0,"YCOO",0)
+            / static_cast<double>( nCOMF );
     }
     else if( poSRecord->FindField( "SG3D" ) != NULL )
     {
-        dfX = poSRecord->GetIntSubfield("SG3D",0,"XCOO",0) / (double)nCOMF;
-        dfY = poSRecord->GetIntSubfield("SG3D",0,"YCOO",0) / (double)nCOMF;
-        dfZ = poSRecord->GetIntSubfield("SG3D",0,"VE3D",0) / (double)nSOMF;
+        dfX = poSRecord->GetIntSubfield("SG3D",0,"XCOO",0)
+            / static_cast<double>( nCOMF );
+        dfY = poSRecord->GetIntSubfield("SG3D",0,"YCOO",0)
+            / static_cast<double>( nCOMF );
+        dfZ = poSRecord->GetIntSubfield("SG3D",0,"VE3D",0)
+            / static_cast<double>( nSOMF );
     }
     else
         return FALSE;
@@ -1581,29 +1569,25 @@ int S57Reader::FetchPoint( int nRCNM, int nRCID,
 /************************************************************************/
 
 static OGRLineString *
-S57StrokeArcToOGRGeometry_Angles( double dfCenterX, double dfCenterY, 
-                                  double dfRadius, 
+S57StrokeArcToOGRGeometry_Angles( double dfCenterX, double dfCenterY,
+                                  double dfRadius,
                                   double dfStartAngle, double dfEndAngle,
                                   int nVertexCount )
 
 {
-    OGRLineString      *poLine = new OGRLineString;
-    double             dfArcX, dfArcY, dfSlice;
-    int                iPoint;
+    OGRLineString * const poLine = new OGRLineString;
 
     nVertexCount = MAX(2,nVertexCount);
-    dfSlice = (dfEndAngle-dfStartAngle)/(nVertexCount-1);
+    const double dfSlice = (dfEndAngle-dfStartAngle)/(nVertexCount-1);
 
     poLine->setNumPoints( nVertexCount );
-        
-    for( iPoint=0; iPoint < nVertexCount; iPoint++ )
+
+    for( int iPoint=0; iPoint < nVertexCount; iPoint++ )
     {
-        double      dfAngle;
+        const double dfAngle = (dfStartAngle + iPoint * dfSlice) * M_PI / 180.0;
 
-        dfAngle = (dfStartAngle + iPoint * dfSlice) * PI / 180.0;
-            
-        dfArcX = dfCenterX + cos(dfAngle) * dfRadius;
-        dfArcY = dfCenterY + sin(dfAngle) * dfRadius;
+        const double dfArcX = dfCenterX + cos(dfAngle) * dfRadius;
+        const double dfArcY = dfCenterY + sin(dfAngle) * dfRadius;
 
         poLine->setPoint( iPoint, dfArcX, dfArcY );
     }
@@ -1621,9 +1605,10 @@ S57StrokeArcToOGRGeometry_Points( double dfStartX, double dfStartY,
                                   double dfCenterX, double dfCenterY,
                                   double dfEndX, double dfEndY,
                                   int nVertexCount )
-    
+
 {
-    double      dfStartAngle, dfEndAngle;
+    double      dfStartAngle;
+    double      dfEndAngle;
     double      dfRadius;
 
     if( dfStartX == dfEndX && dfStartY == dfEndY )
@@ -1633,22 +1618,19 @@ S57StrokeArcToOGRGeometry_Points( double dfStartX, double dfStartY,
     }
     else
     {
-        double  dfDeltaX, dfDeltaY;
-
-        dfDeltaX = dfStartX - dfCenterX;
-        dfDeltaY = dfStartY - dfCenterY;
-        dfStartAngle = atan2(dfDeltaY,dfDeltaX) * 180.0 / PI;
+        double dfDeltaX = dfStartX - dfCenterX;
+        double dfDeltaY = dfStartY - dfCenterY;
+        dfStartAngle = atan2(dfDeltaY, dfDeltaX) * 180.0 / M_PI;
 
         dfDeltaX = dfEndX - dfCenterX;
         dfDeltaY = dfEndY - dfCenterY;
-        dfEndAngle = atan2(dfDeltaY,dfDeltaX) * 180.0 / PI;
+        dfEndAngle = atan2(dfDeltaY, dfDeltaX) * 180.0 / M_PI;
 
 #ifdef notdef
         if( dfStartAngle > dfAlongAngle && dfAlongAngle > dfEndAngle )
         {
-            double dfTempAngle;
-
-            dfTempAngle = dfStartAngle;
+            // TODO: Use std::swap.
+            const double dfTempAngle = dfStartAngle;
             dfStartAngle = dfEndAngle;
             dfEndAngle = dfTempAngle;
         }
@@ -1665,9 +1647,8 @@ S57StrokeArcToOGRGeometry_Points( double dfStartX, double dfStartY,
 
         if( dfEndAngle - dfStartAngle > 360.0 )
         {
-            double dfTempAngle;
-
-            dfTempAngle = dfStartAngle;
+            // TODO: Use std::swap.
+            const double dfTempAngle = dfStartAngle;
             dfStartAngle = dfEndAngle;
             dfEndAngle = dfTempAngle;
 
@@ -1678,9 +1659,9 @@ S57StrokeArcToOGRGeometry_Points( double dfStartX, double dfStartY,
 
     dfRadius = sqrt( (dfCenterX - dfStartX) * (dfCenterX - dfStartX)
                      + (dfCenterY - dfStartY) * (dfCenterY - dfStartY) );
-    
-    return S57StrokeArcToOGRGeometry_Angles( dfCenterX, dfCenterY, 
-                                             dfRadius, 
+
+    return S57StrokeArcToOGRGeometry_Angles( dfCenterX, dfCenterY,
+                                             dfRadius,
                                              dfStartAngle, dfEndAngle,
                                              nVertexCount );
 }
@@ -1689,15 +1670,17 @@ S57StrokeArcToOGRGeometry_Points( double dfStartX, double dfStartY,
 /*                             FetchLine()                              */
 /************************************************************************/
 
-int S57Reader::FetchLine( DDFRecord *poSRecord, 
+int S57Reader::FetchLine( DDFRecord *poSRecord,
                           int iStartVertex, int iDirection,
                           OGRLineString *poLine )
 
 {
     int             nPoints = 0;
-    DDFField        *poSG2D, *poAR2D;
-    DDFSubfieldDefn *poXCOO=NULL, *poYCOO=NULL;
-    int bStandardFormat = TRUE;
+    DDFField        *poSG2D = NULL;
+    DDFField        *poAR2D = NULL;
+    DDFSubfieldDefn *poXCOO = NULL;
+    DDFSubfieldDefn *poYCOO = NULL;
+    bool bStandardFormat = true;
 
 /* -------------------------------------------------------------------- */
 /*      Points may be multiple rows in one SG2D/AR2D field or           */
@@ -1736,7 +1719,7 @@ int S57Reader::FetchLine( DDFRecord *poSRecord,
             return FALSE;
         }
 
-        int nVCount = poSG2D->GetRepeatCount();
+        const int nVCount = poSG2D->GetRepeatCount();
 
 /* -------------------------------------------------------------------- */
 /*      It is legitimate to have zero vertices for line segments        */
@@ -1747,12 +1730,12 @@ int S57Reader::FetchLine( DDFRecord *poSRecord,
 /* -------------------------------------------------------------------- */
         if( nVCount == 0 )
             continue;
- 
+
 /* -------------------------------------------------------------------- */
 /*      Make sure out line is long enough to hold all the vertices      */
 /*      we will apply.                                                  */
 /* -------------------------------------------------------------------- */
-        int nVBase;
+        int nVBase = 0;
 
         if( iDirection < 0 )
             nVBase = iStartVertex + nPoints + nVCount;
@@ -1766,7 +1749,7 @@ int S57Reader::FetchLine( DDFRecord *poSRecord,
 /* -------------------------------------------------------------------- */
 /*      Are the SG2D and XCOO/YCOO definitions in the form we expect?   */
 /* -------------------------------------------------------------------- */
-        bStandardFormat = 
+        bStandardFormat =
             (poSG2D->GetFieldDefn()->GetSubfieldCount() == 2) &&
             EQUAL(poXCOO->GetFormat(),"b24") &&
             EQUAL(poYCOO->GetFormat(),"b24");
@@ -1781,18 +1764,18 @@ int S57Reader::FetchLine( DDFRecord *poSRecord,
 /* -------------------------------------------------------------------- */
         if( bStandardFormat )
         {
-            const char  *pachData;
-            int         nBytesRemaining;
+            int nBytesRemaining = 0;
 
-            pachData = poSG2D->GetSubfieldData(poYCOO,&nBytesRemaining,0);
+            const char *pachData
+                = poSG2D->GetSubfieldData( poYCOO,&nBytesRemaining, 0 );
 
             for( int i = 0; i < nVCount; i++ )
             {
-                double      dfX, dfY;
-                GInt32      nXCOO, nYCOO;
-
+                GInt32      nYCOO;
                 memcpy( &nYCOO, pachData, 4 );
                 pachData += 4;
+
+                GInt32 nXCOO = 0;
                 memcpy( &nXCOO, pachData, 4 );
                 pachData += 4;
 
@@ -1800,8 +1783,8 @@ int S57Reader::FetchLine( DDFRecord *poSRecord,
                 CPL_SWAP32PTR( &nXCOO );
                 CPL_SWAP32PTR( &nYCOO );
 #endif
-                dfX = nXCOO / (double) nCOMF;
-                dfY = nYCOO / (double) nCOMF;
+                const double dfX = nXCOO / static_cast<double>( nCOMF );
+                const double dfY = nYCOO / static_cast<double>( nCOMF );
 
                 poLine->setPoint( nVBase, dfX, dfY );
 
@@ -1821,19 +1804,20 @@ int S57Reader::FetchLine( DDFRecord *poSRecord,
         {
             for( int i = 0; i < nVCount; i++ )
             {
-                double      dfX, dfY;
-                const char  *pachData;
-                int         nBytesRemaining;
+                int nBytesRemaining = 0;
 
-                pachData = poSG2D->GetSubfieldData(poXCOO,&nBytesRemaining,i);
+                const char *pachData
+                    = poSG2D->GetSubfieldData( poXCOO, &nBytesRemaining, i );
 
-                dfX = poXCOO->ExtractIntData(pachData,nBytesRemaining,NULL)
-                    / (double) nCOMF;
+                const double dfX
+                    = poXCOO->ExtractIntData( pachData, nBytesRemaining, NULL )
+                    / static_cast<double>( nCOMF );
 
                 pachData = poSG2D->GetSubfieldData(poYCOO,&nBytesRemaining,i);
 
-                dfY = poXCOO->ExtractIntData(pachData,nBytesRemaining,NULL)
-                    / (double) nCOMF;
+                const double dfY
+                    = poXCOO->ExtractIntData( pachData, nBytesRemaining, NULL )
+                    / static_cast<double>( nCOMF );
 
                 poLine->setPoint( nVBase, dfX, dfY );
 
@@ -1847,10 +1831,9 @@ int S57Reader::FetchLine( DDFRecord *poSRecord,
 /* -------------------------------------------------------------------- */
         if( poAR2D != NULL && poLine->getNumPoints() >= 3 )
         {
-            OGRLineString *poArc;
-            int i, iLast = poLine->getNumPoints() - 1;
+            int iLast = poLine->getNumPoints() - 1;
 
-            poArc = S57StrokeArcToOGRGeometry_Points(
+            OGRLineString *poArc = S57StrokeArcToOGRGeometry_Points(
                 poLine->getX(iLast-0), poLine->getY(iLast-0),
                 poLine->getX(iLast-1), poLine->getY(iLast-1),
                 poLine->getX(iLast-2), poLine->getY(iLast-2),
@@ -1858,8 +1841,9 @@ int S57Reader::FetchLine( DDFRecord *poSRecord,
 
             if( poArc != NULL )
             {
-                for( i = 0; i < poArc->getNumPoints(); i++ )
-                        poLine->setPoint( iLast-2+i, poArc->getX(i), poArc->getY(i) );
+                for( int i = 0; i < poArc->getNumPoints(); i++ )
+                    poLine->setPoint( iLast-2+i, poArc->getX(i),
+                                      poArc->getY(i) );
 
                 delete poArc;
             }
@@ -1877,30 +1861,30 @@ void S57Reader::AssemblePointGeometry( DDFRecord * poFRecord,
                                        OGRFeature * poFeature )
 
 {
-    DDFField    *poFSPT;
-    int         nRCNM, nRCID;
-
 /* -------------------------------------------------------------------- */
 /*      Feature the spatial record containing the point.                */
 /* -------------------------------------------------------------------- */
-    poFSPT = poFRecord->FindField( "FSPT" );
+    DDFField *poFSPT = poFRecord->FindField( "FSPT" );
     if( poFSPT == NULL )
         return;
 
     if( poFSPT->GetRepeatCount() != 1 )
     {
 #ifdef DEBUG
-        fprintf( stderr, 
+        fprintf( stderr,
                  "Point features with other than one spatial linkage.\n" );
         poFRecord->Dump( stderr );
 #endif
-        CPLDebug( "S57", 
+        CPLDebug( "S57",
            "Point feature encountered with other than one spatial linkage." );
     }
-        
-    nRCID = ParseName( poFSPT, 0, &nRCNM );
 
-    double      dfX = 0.0, dfY = 0.0, dfZ = 0.0;
+    int nRCNM = 0;
+    const int nRCID = ParseName( poFSPT, 0, &nRCNM );
+
+    double dfX = 0.0;
+    double dfY = 0.0;
+    double dfZ = 0.0;
 
     if( nRCID == -1 || !FetchPoint( nRCNM, nRCID, &dfX, &dfY, &dfZ ) )
     {
@@ -1925,23 +1909,20 @@ void S57Reader::AssembleSoundingGeometry( DDFRecord * poFRecord,
                                           OGRFeature * poFeature )
 
 {
-    DDFField    *poFSPT;
-    int         nRCNM, nRCID;
-    DDFRecord   *poSRecord;
-    
-
 /* -------------------------------------------------------------------- */
 /*      Feature the spatial record containing the point.                */
 /* -------------------------------------------------------------------- */
-    poFSPT = poFRecord->FindField( "FSPT" );
+    DDFField *poFSPT = poFRecord->FindField( "FSPT" );
     if( poFSPT == NULL )
         return;
 
     if( poFSPT->GetRepeatCount() != 1 )
         return;
-        
-    nRCID = ParseName( poFSPT, 0, &nRCNM );
 
+    int nRCNM = 0;
+    const int nRCID = ParseName( poFSPT, 0, &nRCNM );
+
+    DDFRecord *poSRecord;
     if( nRCNM == RCNM_VI )
         poSRecord = oVI_Index.FindRecord( nRCID );
     else
@@ -1953,51 +1934,57 @@ void S57Reader::AssembleSoundingGeometry( DDFRecord * poFRecord,
 /* -------------------------------------------------------------------- */
 /*      Extract vertices.                                               */
 /* -------------------------------------------------------------------- */
-    OGRMultiPoint       *poMP = new OGRMultiPoint();
-    DDFField            *poField;
-    int                 nPointCount, i, nBytesLeft;
-    DDFSubfieldDefn    *poXCOO, *poYCOO, *poVE3D;
-    const char         *pachData;
+    OGRMultiPoint * const poMP = new OGRMultiPoint();
 
-    poField = poSRecord->FindField( "SG2D" );
+    DDFField *poField = poSRecord->FindField( "SG2D" );
     if( poField == NULL )
         poField = poSRecord->FindField( "SG3D" );
     if( poField == NULL )
+    {
+        delete poMP;
         return;
+    }
 
-    poXCOO = poField->GetFieldDefn()->FindSubfieldDefn( "XCOO" );
-    poYCOO = poField->GetFieldDefn()->FindSubfieldDefn( "YCOO" );
+    DDFSubfieldDefn *poXCOO
+        = poField->GetFieldDefn()->FindSubfieldDefn( "XCOO" );
+    DDFSubfieldDefn *poYCOO
+        = poField->GetFieldDefn()->FindSubfieldDefn( "YCOO" );
     if( poXCOO == NULL || poYCOO == NULL )
     {
         CPLDebug( "S57", "XCOO or YCOO are NULL" );
+        delete poMP;
         return;
     }
-    poVE3D = poField->GetFieldDefn()->FindSubfieldDefn( "VE3D" );
+    DDFSubfieldDefn * const poVE3D
+        = poField->GetFieldDefn()->FindSubfieldDefn( "VE3D" );
 
-    nPointCount = poField->GetRepeatCount();
+    const int nPointCount = poField->GetRepeatCount();
 
-    pachData = poField->GetData();
-    nBytesLeft = poField->GetDataSize();
+    const char *pachData = poField->GetData();
+    int nBytesLeft = poField->GetDataSize();
 
-    for( i = 0; i < nPointCount; i++ )
+    for( int i = 0; i < nPointCount; i++ )
     {
-        double          dfX, dfY, dfZ = 0.0;
-        int             nBytesConsumed;
+        int nBytesConsumed;
 
-        dfY = poYCOO->ExtractIntData( pachData, nBytesLeft,
-                                      &nBytesConsumed ) / (double) nCOMF;
+        const double dfY = poYCOO->ExtractIntData( pachData, nBytesLeft,
+                                                   &nBytesConsumed )
+            / static_cast<double>( nCOMF );
         nBytesLeft -= nBytesConsumed;
         pachData += nBytesConsumed;
 
-        dfX = poXCOO->ExtractIntData( pachData, nBytesLeft,
-                                      &nBytesConsumed ) / (double) nCOMF;
+        const double dfX = poXCOO->ExtractIntData( pachData, nBytesLeft,
+                                                   &nBytesConsumed )
+            / static_cast<double>( nCOMF );
         nBytesLeft -= nBytesConsumed;
         pachData += nBytesConsumed;
-        
+
+        double dfZ = 0.0;
         if( poVE3D != NULL )
         {
             dfZ = poYCOO->ExtractIntData( pachData, nBytesLeft,
-                                          &nBytesConsumed ) / (double) nSOMF;
+                                          &nBytesConsumed )
+                / static_cast<double>( nSOMF );
             nBytesLeft -= nBytesConsumed;
             pachData += nBytesConsumed;
         }
@@ -2026,7 +2013,7 @@ GetIntSubfield( DDFField *poField,
 /* -------------------------------------------------------------------- */
 /*      Get a pointer to the data.                                      */
 /* -------------------------------------------------------------------- */
-    int nBytesRemaining;
+    int nBytesRemaining = 0;
 
     const char *pachData = poField->GetSubfieldData( poSFDefn,
                                 &nBytesRemaining,
@@ -2043,10 +2030,8 @@ void S57Reader::AssembleLineGeometry( DDFRecord * poFRecord,
                                       OGRFeature * poFeature )
 
 {
-    DDFField    *poFSPT;
     OGRLineString *poLine = new OGRLineString();
     OGRMultiLineString *poMLS = new OGRMultiLineString();
-    double dlastfX( 0.0 ), dlastfY( 0.0 ), dfX, dfY;
 
 /* -------------------------------------------------------------------- */
 /*      Loop collecting edges.                                          */
@@ -2056,7 +2041,10 @@ void S57Reader::AssembleLineGeometry( DDFRecord * poFRecord,
 
     for( int iField = 0; iField < nFieldCount; ++iField )
     {
-        poFSPT = poFRecord->GetField( iField );
+        double dlastfX = 0.0;
+        double dlastfY = 0.0;
+
+        DDFField *poFSPT = poFRecord->GetField( iField );
 
         if( !EQUAL(poFSPT->GetFieldDefn()->GetName(), "FSPT") )
             continue;
@@ -2068,13 +2056,13 @@ void S57Reader::AssembleLineGeometry( DDFRecord * poFRecord,
 
         for( int iEdge = 0; iEdge < nEdgeCount; ++iEdge )
         {
-            int  nVC_RCID_firstnode, nVC_RCID_lastnode;
-            bool bReverse = (GetIntSubfield( poFSPT, "ORNT", iEdge ) == 2);
+            const bool bReverse
+              = ( GetIntSubfield( poFSPT, "ORNT", iEdge ) == 2 );
 
 /* -------------------------------------------------------------------- */
 /*      Find the spatial record for this edge.                          */
 /* -------------------------------------------------------------------- */
-            int nRCID = ParseName( poFSPT, iEdge );
+            const int nRCID = ParseName( poFSPT, iEdge );
 
             DDFRecord *poSRecord = oVE_Index.FindRecord( nRCID );
             if( poSRecord == NULL )
@@ -2088,7 +2076,7 @@ void S57Reader::AssembleLineGeometry( DDFRecord * poFRecord,
                           GetIntSubfield( poFSPT, "RCID", 0 ) );
                 continue;
             }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Get the first and last nodes                                    */
 /* -------------------------------------------------------------------- */
@@ -2096,17 +2084,20 @@ void S57Reader::AssembleLineGeometry( DDFRecord * poFRecord,
             if( poVRPT == NULL )
             {
                 CPLError( CE_Warning, CPLE_AppDefined,
-                    "Unable to fetch start node for RCID %d.\n"
-                    "Feature OBJL=%s, RCID=%d may have corrupt or"
-                    "missing geometry.",
-                    nRCID,
-                    poFeature->GetDefnRef()->GetName(),
-                    GetIntSubfield( poFSPT, "RCID", 0 ) );
+                          "Unable to fetch start node for RCID %d.\n"
+                          "Feature OBJL=%s, RCID=%d may have corrupt or"
+                          "missing geometry.",
+                          nRCID,
+                          poFeature->GetDefnRef()->GetName(),
+                          GetIntSubfield( poFSPT, "RCID", 0 ) );
                 continue;
             }
 
             // The "VRPT" field has only one row
             // Get the next row from a second "VRPT" field
+            int nVC_RCID_firstnode = 0;
+            int nVC_RCID_lastnode = 0;
+
             if( poVRPT != NULL && poVRPT->GetRepeatCount() == 1 )
             {
                 nVC_RCID_firstnode = ParseName( poVRPT );
@@ -2115,12 +2106,12 @@ void S57Reader::AssembleLineGeometry( DDFRecord * poFRecord,
                 if( poVRPT == NULL )
                 {
                     CPLError( CE_Warning, CPLE_AppDefined,
-                            "Unable to fetch end node for RCID %d.\n"
-                            "Feature OBJL=%s, RCID=%d may have corrupt or"
-                            "missing geometry.",
-                            nRCID,
-                            poFeature->GetDefnRef()->GetName(),
-                            GetIntSubfield( poFSPT, "RCID", 0 ) );
+                              "Unable to fetch end node for RCID %d.\n"
+                              "Feature OBJL=%s, RCID=%d may have corrupt or"
+                              "missing geometry.",
+                              nRCID,
+                              poFeature->GetDefnRef()->GetName(),
+                              GetIntSubfield( poFSPT, "RCID", 0 ) );
                     continue;
                 }
 
@@ -2128,7 +2119,8 @@ void S57Reader::AssembleLineGeometry( DDFRecord * poFRecord,
 
                 if( bReverse )
                 {
-                    int tmp = nVC_RCID_lastnode;
+                    // TODO: std::swap.
+                    const int tmp = nVC_RCID_lastnode;
                     nVC_RCID_lastnode = nVC_RCID_firstnode;
                     nVC_RCID_firstnode = tmp;
                 }
@@ -2144,6 +2136,8 @@ void S57Reader::AssembleLineGeometry( DDFRecord * poFRecord,
                 nVC_RCID_lastnode = ParseName( poVRPT, 1 );
             }
 
+            double dfX = 0.0;
+            double dfY = 0.0;
             if( nVC_RCID_firstnode == -1 ||
                 ! FetchPoint( RCNM_VC, nVC_RCID_firstnode, &dfX, &dfY ) )
             {
@@ -2182,73 +2176,78 @@ void S57Reader::AssembleLineGeometry( DDFRecord * poFRecord,
                 /* omit point, already present */
             }
 
-            // remember the coordinates of the last point
-            dlastfX = dfX; dlastfY = dfY;
-
 /* -------------------------------------------------------------------- */
 /*      Collect the vertices.                                           */
 /*      Iterate over all the SG2D fields in the Spatial record          */
 /* -------------------------------------------------------------------- */
-            int             nVBase, nVCount;
-            int             nStart, nEnd, nInc;
-            DDFField        *poSG2D;
-            DDFSubfieldDefn *poXCOO=NULL, *poYCOO=NULL;
-
-            for( int iSField = 0; iSField < poSRecord->GetFieldCount();
-                ++iSField )
+            for( int iSField = 0;
+                 iSField < poSRecord->GetFieldCount();
+                 ++iSField )
             {
-                poSG2D = poSRecord->GetField( iSField );
+                DDFField *poSG2D = poSRecord->GetField( iSField );
 
                 if( EQUAL(poSG2D->GetFieldDefn()->GetName(), "SG2D") ||
                     EQUAL(poSG2D->GetFieldDefn()->GetName(), "AR2D") )
                 {
-                    poXCOO = poSG2D->GetFieldDefn()->FindSubfieldDefn("XCOO");
-                    poYCOO = poSG2D->GetFieldDefn()->FindSubfieldDefn("YCOO");
+                    DDFSubfieldDefn *poXCOO
+                        = poSG2D->GetFieldDefn()->FindSubfieldDefn("XCOO");
+                    DDFSubfieldDefn *poYCOO
+                        = poSG2D->GetFieldDefn()->FindSubfieldDefn("YCOO");
 
                     if( poXCOO == NULL || poYCOO == NULL )
                     {
                         CPLDebug( "S57", "XCOO or YCOO are NULL" );
+                        delete poLine;
+                        delete poMLS;
                         return;
                     }
 
-                    nVCount = poSG2D->GetRepeatCount();
+                    const int nVCount = poSG2D->GetRepeatCount();
 
+                    int nStart = 0;
+                    int nEnd = 0;
+                    int nInc = 0;
                     if( bReverse )
                     {
                         nStart = nVCount-1;
-                        nEnd = 0;
                         nInc = -1;
                     }
                     else
                     {
-                        nStart = 0;
                         nEnd = nVCount-1;
                         nInc = 1;
                     }
 
-                    nVBase = poLine->getNumPoints();
+                    int nVBase = poLine->getNumPoints();
                     poLine->setNumPoints( nVBase + nVCount );
 
-                    const char *pachData;
-                    int nBytesRemaining;
+                    int nBytesRemaining = 0;
 
                     for( int i = nStart; i != nEnd+nInc; i += nInc )
                     {
-                        pachData = poSG2D->GetSubfieldData(poXCOO,&nBytesRemaining,i);
+                        const char *pachData
+                          = poSG2D->GetSubfieldData(
+                              poXCOO, &nBytesRemaining, i );
 
-                        dfX = poXCOO->ExtractIntData(pachData,nBytesRemaining,NULL)
-                            / (double) nCOMF;
+                        dfX = poXCOO->ExtractIntData(
+                            pachData, nBytesRemaining, NULL )
+                            / static_cast<double>( nCOMF );
 
-                        pachData = poSG2D->GetSubfieldData(poYCOO,&nBytesRemaining,i);
+                        pachData = poSG2D->GetSubfieldData(
+                            poYCOO, &nBytesRemaining, i );
 
-                        dfY = poXCOO->ExtractIntData(pachData,nBytesRemaining,NULL)
-                            / (double) nCOMF;
+                        dfY = poXCOO->ExtractIntData(
+                            pachData, nBytesRemaining, NULL )
+                            / static_cast<double>( nCOMF );
 
                         poLine->setPoint( nVBase++, dfX, dfY );
                     }
                 }
             }
-            dlastfX = dfX; dlastfY = dfY;
+
+            // remember the coordinates of the last point
+            dlastfX = dfX;
+            dlastfY = dfY;
 
 /* -------------------------------------------------------------------- */
 /*      Add the end node.                                               */
@@ -2257,17 +2256,18 @@ void S57Reader::AssembleLineGeometry( DDFRecord * poFRecord,
                 FetchPoint( RCNM_VC, nVC_RCID_lastnode, &dfX, &dfY ) )
             {
                 poLine->addPoint( dfX, dfY );
-                dlastfX = dfX; dlastfY = dfY;
+                dlastfX = dfX;
+                dlastfY = dfY;
             }
             else
             {
                 CPLError( CE_Warning, CPLE_AppDefined,
-                    "Unable to fetch end node RCID=%d.\n"
-                    "Feature OBJL=%s, RCID=%d may have corrupt or"
-                    " missing geometry.",
-                    nVC_RCID_lastnode,
-                    poFeature->GetDefnRef()->GetName(),
-                    poFRecord->GetIntSubfield( "FRID", 0, "RCID", 0 ) );
+                          "Unable to fetch end node RCID=%d.\n"
+                          "Feature OBJL=%s, RCID=%d may have corrupt or"
+                          " missing geometry.",
+                          nVC_RCID_lastnode,
+                          poFeature->GetDefnRef()->GetName(),
+                          poFRecord->GetIntSubfield( "FRID", 0, "RCID", 0 ) );
                 continue;
             }
         }
@@ -2300,11 +2300,10 @@ void S57Reader::AssembleLineGeometry( DDFRecord * poFRecord,
 /************************************************************************/
 
 void S57Reader::AssembleAreaGeometry( DDFRecord * poFRecord,
-                                         OGRFeature * poFeature )
+                                      OGRFeature * poFeature )
 
 {
-    DDFField    *poFSPT;
-    OGRGeometryCollection * poLines = new OGRGeometryCollection();
+    OGRGeometryCollection * const poLines = new OGRGeometryCollection();
 
 /* -------------------------------------------------------------------- */
 /*      Find the FSPT fields.                                           */
@@ -2313,46 +2312,41 @@ void S57Reader::AssembleAreaGeometry( DDFRecord * poFRecord,
 
     for( int iFSPT = 0; iFSPT < nFieldCount; ++iFSPT )
     {
-        poFSPT = poFRecord->GetField(iFSPT);
+        DDFField *poFSPT = poFRecord->GetField(iFSPT);
 
         if ( !EQUAL(poFSPT->GetFieldDefn()->GetName(), "FSPT") )
             continue;
 
-        int         nEdgeCount;
-
-        nEdgeCount = poFSPT->GetRepeatCount();
+        const int nEdgeCount = poFSPT->GetRepeatCount();
 
 /* ==================================================================== */
 /*      Loop collecting edges.                                          */
 /* ==================================================================== */
         for( int iEdge = 0; iEdge < nEdgeCount; iEdge++ )
         {
-            DDFRecord       *poSRecord;
-            int             nRCID;
-
 /* -------------------------------------------------------------------- */
 /*      Find the spatial record for this edge.                          */
 /* -------------------------------------------------------------------- */
-            nRCID = ParseName( poFSPT, iEdge );
+            const int nRCID = ParseName( poFSPT, iEdge );
 
-            poSRecord = oVE_Index.FindRecord( nRCID );
+            DDFRecord *poSRecord = oVE_Index.FindRecord( nRCID );
             if( poSRecord == NULL )
             {
                 CPLError( CE_Warning, CPLE_AppDefined,
-                    "Couldn't find spatial record %d.\n"
-                    "Feature OBJL=%s, RCID=%d may have corrupt or"
-                    "missing geometry.",
-                    nRCID,
-                    poFeature->GetDefnRef()->GetName(),
-                    GetIntSubfield( poFSPT, "RCID", 0 ) );
+                          "Couldn't find spatial record %d.\n"
+                          "Feature OBJL=%s, RCID=%d may have corrupt or"
+                          "missing geometry.",
+                          nRCID,
+                          poFeature->GetDefnRef()->GetName(),
+                          GetIntSubfield( poFSPT, "RCID", 0 ) );
                 continue;
             }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create the line string.                                         */
 /* -------------------------------------------------------------------- */
             OGRLineString *poLine = new OGRLineString();
-        
+
 /* -------------------------------------------------------------------- */
 /*      Add the start node.                                             */
 /* -------------------------------------------------------------------- */
@@ -2362,7 +2356,8 @@ void S57Reader::AssembleAreaGeometry( DDFRecord * poFRecord,
                 int nVC_RCID = ParseName( poVRPT );
                 double dfX, dfY;
 
-                if( nVC_RCID != -1 && FetchPoint( RCNM_VC, nVC_RCID, &dfX, &dfY ) )
+                if( nVC_RCID != -1
+                    && FetchPoint( RCNM_VC, nVC_RCID, &dfX, &dfY ) )
                     poLine->addPoint( dfX, dfY );
             }
 
@@ -2371,27 +2366,31 @@ void S57Reader::AssembleAreaGeometry( DDFRecord * poFRecord,
 /* -------------------------------------------------------------------- */
             if( !FetchLine( poSRecord, poLine->getNumPoints(), 1, poLine ) )
             {
-                CPLDebug( "S57", "FetchLine() failed in AssembleAreaGeometry()!" );
+                CPLDebug( "S57",
+                          "FetchLine() failed in AssembleAreaGeometry()!" );
             }
 
-
 /* -------------------------------------------------------------------- */
 /*      Add the end node.                                               */
 /* -------------------------------------------------------------------- */
             if( poVRPT != NULL && poVRPT->GetRepeatCount() > 1 )
             {
-                int nVC_RCID = ParseName( poVRPT, 1 );
-                double dfX, dfY;
+                const int nVC_RCID = ParseName( poVRPT, 1 );
+                double dfX;
+                double dfY;
 
-                if( nVC_RCID != -1 && FetchPoint( RCNM_VC, nVC_RCID, &dfX, &dfY ) )
+                if( nVC_RCID != -1
+                    && FetchPoint( RCNM_VC, nVC_RCID, &dfX, &dfY ) )
                     poLine->addPoint( dfX, dfY );
             }
             else if( (poVRPT = poSRecord->FindField( "VRPT", 1 )) != NULL )
             {
-                int nVC_RCID = ParseName( poVRPT );
-                double dfX, dfY;
+                const int nVC_RCID = ParseName( poVRPT );
+                double dfX;
+                double dfY;
 
-                if( nVC_RCID != -1 && FetchPoint( RCNM_VC, nVC_RCID, &dfX, &dfY ) )
+                if( nVC_RCID != -1
+                    && FetchPoint( RCNM_VC, nVC_RCID, &dfX, &dfY ) )
                     poLine->addPoint( dfX, dfY );
             }
 
@@ -2402,17 +2401,16 @@ void S57Reader::AssembleAreaGeometry( DDFRecord * poFRecord,
 /* -------------------------------------------------------------------- */
 /*      Build lines into a polygon.                                     */
 /* -------------------------------------------------------------------- */
-    OGRPolygon  *poPolygon;
-    OGRErr      eErr;
+    OGRErr eErr;
 
-    poPolygon = (OGRPolygon *) 
-        OGRBuildPolygonFromEdges( (OGRGeometryH) poLines, 
-                                  TRUE, FALSE, 0.0, &eErr );
+    OGRPolygon  *poPolygon = reinterpret_cast<OGRPolygon *>(
+        OGRBuildPolygonFromEdges( reinterpret_cast<OGRGeometryH>( poLines ),
+                                  TRUE, FALSE, 0.0, &eErr ) );
     if( eErr != OGRERR_NONE )
     {
         CPLError( CE_Warning, CPLE_AppDefined,
                   "Polygon assembly has failed for feature FIDN=%d,FIDS=%d.\n"
-                  "Geometry may be missing or incomplete.", 
+                  "Geometry may be missing or incomplete.",
                   poFeature->GetFieldAsInteger( "FIDN" ),
                   poFeature->GetFieldAsInteger( "FIDS" ) );
     }
@@ -2436,9 +2434,9 @@ OGRFeatureDefn * S57Reader::FindFDefn( DDFRecord * poRecord )
 {
     if( poRegistrar != NULL )
     {
-        int     nOBJL = poRecord->GetIntSubfield( "FRID", 0, "OBJL", 0 );
+        const int nOBJL = poRecord->GetIntSubfield( "FRID", 0, "OBJL", 0 );
 
-        if( nOBJL < (int)apoFDefnByOBJL.size() 
+        if( nOBJL < static_cast<int>( apoFDefnByOBJL.size() )
             && apoFDefnByOBJL[nOBJL] != NULL )
             return apoFDefnByOBJL[nOBJL];
 
@@ -2463,9 +2461,9 @@ OGRFeatureDefn * S57Reader::FindFDefn( DDFRecord * poRecord )
     }
     else
     {
-        int     nPRIM = poRecord->GetIntSubfield( "FRID", 0, "PRIM", 0 );
+        const int nPRIM = poRecord->GetIntSubfield( "FRID", 0, "PRIM", 0 );
         OGRwkbGeometryType eGType;
-        
+
         if( nPRIM == PRIM_P )
             eGType = wkbPoint;
         else if( nPRIM == PRIM_L )
@@ -2496,8 +2494,6 @@ OGRFeatureDefn * S57Reader::FindFDefn( DDFRecord * poRecord )
 int S57Reader::ParseName( DDFField * poField, int nIndex, int * pnRCNM )
 
 {
-    unsigned char       *pabyData;
-
     if( poField == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -2505,13 +2501,15 @@ int S57Reader::ParseName( DDFField * poField, int nIndex, int * pnRCNM )
         return -1;
     }
 
-    DDFSubfieldDefn* poName = poField->GetFieldDefn()->FindSubfieldDefn( "NAME" );
+    DDFSubfieldDefn* poName
+        = poField->GetFieldDefn()->FindSubfieldDefn( "NAME" );
     if( poName == NULL )
         return -1;
 
     int nMaxBytes;
-    pabyData = (unsigned char *)
-        poField->GetSubfieldData( poName, &nMaxBytes, nIndex );
+    unsigned char *pabyData = reinterpret_cast<unsigned char *>(
+        const_cast<char *>(
+            poField->GetSubfieldData( poName, &nMaxBytes, nIndex ) ) );
     if( pabyData == NULL || nMaxBytes < 5 )
         return -1;
 
@@ -2532,8 +2530,8 @@ void S57Reader::AddFeatureDefn( OGRFeatureDefn * poFDefn )
 
 {
     nFDefnCount++;
-    papoFDefnList = (OGRFeatureDefn **)
-        CPLRealloc(papoFDefnList, sizeof(OGRFeatureDefn*)*nFDefnCount );
+    papoFDefnList = static_cast<OGRFeatureDefn **>(
+        CPLRealloc(papoFDefnList, sizeof(OGRFeatureDefn*)*nFDefnCount ) );
 
     papoFDefnList[nFDefnCount-1] = poFDefn;
 
@@ -2541,10 +2539,13 @@ void S57Reader::AddFeatureDefn( OGRFeatureDefn * poFDefn )
     {
         if( poClassContentExplorer->SelectClass( poFDefn->GetName() ) )
         {
-            int nOBJL = poClassContentExplorer->GetOBJL();
-            if( nOBJL >= (int) apoFDefnByOBJL.size() )
-                apoFDefnByOBJL.resize(nOBJL+1);
-            apoFDefnByOBJL[nOBJL] = poFDefn;
+            const int nOBJL = poClassContentExplorer->GetOBJL();
+            if( nOBJL >= 0 )
+            {
+                if( nOBJL >= (int) apoFDefnByOBJL.size() )
+                    apoFDefnByOBJL.resize(nOBJL+1);
+                apoFDefnByOBJL[nOBJL] = poFDefn;
+            }
         }
     }
 }
@@ -2559,18 +2560,18 @@ void S57Reader::AddFeatureDefn( OGRFeatureDefn * poFDefn )
 int S57Reader::CollectClassList(std::vector<int> &anClassCount)
 
 {
-    int         bSuccess = TRUE;
-
     if( !bFileIngested && !Ingest() )
         return FALSE;
 
+    bool bSuccess = true;
+
     for( int iFEIndex = 0; iFEIndex < oFE_Index.GetCount(); iFEIndex++ )
     {
         DDFRecord *poRecord = oFE_Index.GetByIndex( iFEIndex );
-        int     nOBJL = poRecord->GetIntSubfield( "FRID", 0, "OBJL", 0 );
+        const int nOBJL = poRecord->GetIntSubfield( "FRID", 0, "OBJL", 0 );
 
         if( nOBJL < 0 )
-            bSuccess = FALSE;
+            bSuccess = false;
         else
         {
             if( nOBJL >= (int) anClassCount.size() )
@@ -2601,34 +2602,34 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
     if( poTarget->GetIntSubfield( pszKey, 0, "RVER", 0 ) + 1
         != poUpdate->GetIntSubfield( pszKey, 0, "RVER", 0 )  )
     {
-        CPLDebug( "S57", 
+        CPLDebug( "S57",
                   "Mismatched RVER value on RCNM=%d,RCID=%d.\n",
                   poTarget->GetIntSubfield( pszKey, 0, "RCNM", 0 ),
                   poTarget->GetIntSubfield( pszKey, 0, "RCID", 0 ) );
 
-        //CPLAssert( FALSE );
+        // CPLAssert( FALSE );
         return FALSE;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Update the target version.                                      */
 /* -------------------------------------------------------------------- */
-    unsigned char       *pnRVER;
-    DDFField    *poKey = poTarget->FindField( pszKey );
-    DDFSubfieldDefn *poRVER_SFD;
+    DDFField *poKey = poTarget->FindField( pszKey );
 
     if( poKey == NULL )
     {
-        //CPLAssert( FALSE );
+        // CPLAssert( FALSE );
         return FALSE;
     }
 
-    poRVER_SFD = poKey->GetFieldDefn()->FindSubfieldDefn( "RVER" );
+    DDFSubfieldDefn *poRVER_SFD
+        = poKey->GetFieldDefn()->FindSubfieldDefn( "RVER" );
     if( poRVER_SFD == NULL )
         return FALSE;
 
-    pnRVER = (unsigned char *) poKey->GetSubfieldData( poRVER_SFD, NULL, 0 );
- 
+    unsigned char *pnRVER
+        = (unsigned char *) poKey->GetSubfieldData( poRVER_SFD, NULL, 0 );
+
     *pnRVER += 1;
 
 /* -------------------------------------------------------------------- */
@@ -2637,37 +2638,38 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
 /* -------------------------------------------------------------------- */
     if( poUpdate->FindField( "FSPC" ) != NULL )
     {
-        int     nFSUI = poUpdate->GetIntSubfield( "FSPC", 0, "FSUI", 0 );
-        int     nFSIX = poUpdate->GetIntSubfield( "FSPC", 0, "FSIX", 0 );
-        int     nNSPT = poUpdate->GetIntSubfield( "FSPC", 0, "NSPT", 0 );
+        const int nFSUI = poUpdate->GetIntSubfield( "FSPC", 0, "FSUI", 0 );
         DDFField *poSrcFSPT = poUpdate->FindField( "FSPT" );
         DDFField *poDstFSPT = poTarget->FindField( "FSPT" );
-        int     nPtrSize;
 
         if( (poSrcFSPT == NULL && nFSUI != 2) || poDstFSPT == NULL )
         {
-            //CPLAssert( FALSE );
+            // CPLAssert( FALSE );
             return FALSE;
         }
 
-        nPtrSize = poDstFSPT->GetFieldDefn()->GetFixedWidth();
+        const int nFSIX = poUpdate->GetIntSubfield( "FSPC", 0, "FSIX", 0 );
+        const int nNSPT = poUpdate->GetIntSubfield( "FSPC", 0, "NSPT", 0 );
+
+        int nPtrSize = poDstFSPT->GetFieldDefn()->GetFixedWidth();
 
         if( nFSUI == 1 ) /* INSERT */
         {
-            char        *pachInsertion;
-            int         nInsertionBytes = nPtrSize * nNSPT;
+            int nInsertionBytes = nPtrSize * nNSPT;
 
             if( poSrcFSPT->GetDataSize() < nInsertionBytes )
             {
-                CPLDebug("S57", "Not enough bytes in source FSPT field. Has %d, requires %d",
-                         poSrcFSPT->GetDataSize(), nInsertionBytes );
+                CPLDebug( "S57", "Not enough bytes in source FSPT field. "
+                          "Has %d, requires %d",
+                          poSrcFSPT->GetDataSize(), nInsertionBytes );
                 return FALSE;
             }
 
-            pachInsertion = (char *) CPLMalloc(nInsertionBytes + nPtrSize);
+            char *pachInsertion
+                = static_cast<char *>( CPLMalloc(nInsertionBytes + nPtrSize) );
             memcpy( pachInsertion, poSrcFSPT->GetData(), nInsertionBytes );
 
-            /* 
+            /*
             ** If we are inserting before an instance that already
             ** exists, we must add it to the end of the data being
             ** inserted.
@@ -2676,19 +2678,20 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
             {
                 if( poDstFSPT->GetDataSize() < nPtrSize * nFSIX )
                 {
-                    CPLDebug("S57", "Not enough bytes in dest FSPT field. Has %d, requires %d",
-                         poDstFSPT->GetDataSize(), nPtrSize * nFSIX );
+                    CPLDebug( "S57", "Not enough bytes in dest FSPT field. "
+                              "Has %d, requires %d",
+                              poDstFSPT->GetDataSize(), nPtrSize * nFSIX );
                     CPLFree( pachInsertion );
                     return FALSE;
                 }
 
-                memcpy( pachInsertion + nInsertionBytes, 
-                        poDstFSPT->GetData() + nPtrSize * (nFSIX-1), 
+                memcpy( pachInsertion + nInsertionBytes,
+                        poDstFSPT->GetData() + nPtrSize * (nFSIX-1),
                         nPtrSize );
                 nInsertionBytes += nPtrSize;
             }
 
-            poTarget->SetFieldRaw( poDstFSPT, nFSIX - 1, 
+            poTarget->SetFieldRaw( poDstFSPT, nFSIX - 1,
                                    pachInsertion, nInsertionBytes );
             CPLFree( pachInsertion );
         }
@@ -2712,10 +2715,8 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
 
             for( int i = 0; i < nNSPT; i++ )
             {
-                const char *pachRawData;
-
-                pachRawData = poSrcFSPT->GetData() + nPtrSize * i;
-                poTarget->SetFieldRaw( poDstFSPT, i + nFSIX - 1, 
+                const char *pachRawData = poSrcFSPT->GetData() + nPtrSize * i;
+                poTarget->SetFieldRaw( poDstFSPT, i + nFSIX - 1,
                                        pachRawData, nPtrSize );
             }
         }
@@ -2727,12 +2728,9 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
 /* -------------------------------------------------------------------- */
     if( poUpdate->FindField( "VRPC" ) != NULL )
     {
-        int     nVPUI = poUpdate->GetIntSubfield( "VRPC", 0, "VPUI", 0 );
-        int     nVPIX = poUpdate->GetIntSubfield( "VRPC", 0, "VPIX", 0 );
-        int     nNVPT = poUpdate->GetIntSubfield( "VRPC", 0, "NVPT", 0 );
+        const int nVPUI = poUpdate->GetIntSubfield( "VRPC", 0, "VPUI", 0 );
         DDFField *poSrcVRPT = poUpdate->FindField( "VRPT" );
         DDFField *poDstVRPT = poTarget->FindField( "VRPT" );
-        int     nPtrSize;
 
         if( (poSrcVRPT == NULL && nVPUI != 2) || poDstVRPT == NULL )
         {
@@ -2740,12 +2738,14 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
             return FALSE;
         }
 
-        nPtrSize = poDstVRPT->GetFieldDefn()->GetFixedWidth();
+        const int nVPIX = poUpdate->GetIntSubfield( "VRPC", 0, "VPIX", 0 );
+        const int nNVPT = poUpdate->GetIntSubfield( "VRPC", 0, "NVPT", 0 );
+
+        const int nPtrSize = poDstVRPT->GetFieldDefn()->GetFixedWidth();
 
         if( nVPUI == 1 ) /* INSERT */
         {
-            char        *pachInsertion;
-            int         nInsertionBytes = nPtrSize * nNVPT;
+            int nInsertionBytes = nPtrSize * nNVPT;
 
             if( poSrcVRPT->GetDataSize() < nInsertionBytes )
             {
@@ -2754,10 +2754,11 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
                 return FALSE;
             }
 
-            pachInsertion = (char *) CPLMalloc(nInsertionBytes + nPtrSize);
+            char *pachInsertion
+                = static_cast<char *>( CPLMalloc(nInsertionBytes + nPtrSize) );
             memcpy( pachInsertion, poSrcVRPT->GetData(), nInsertionBytes );
 
-            /* 
+            /*
             ** If we are inserting before an instance that already
             ** exists, we must add it to the end of the data being
             ** inserted.
@@ -2772,13 +2773,13 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
                     return FALSE;
                 }
 
-                memcpy( pachInsertion + nInsertionBytes, 
-                        poDstVRPT->GetData() + nPtrSize * (nVPIX-1), 
+                memcpy( pachInsertion + nInsertionBytes,
+                        poDstVRPT->GetData() + nPtrSize * (nVPIX-1),
                         nPtrSize );
                 nInsertionBytes += nPtrSize;
             }
 
-            poTarget->SetFieldRaw( poDstVRPT, nVPIX - 1, 
+            poTarget->SetFieldRaw( poDstVRPT, nVPIX - 1,
                                    pachInsertion, nInsertionBytes );
             CPLFree( pachInsertion );
         }
@@ -2794,19 +2795,18 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
         {
             if( poSrcVRPT->GetDataSize() < nNVPT * nPtrSize )
             {
-                CPLDebug("S57", "Not enough bytes in source VRPT field. Has %d, requires %d",
-                         poSrcVRPT->GetDataSize(), nNVPT * nPtrSize );
+                CPLDebug( "S57", "Not enough bytes in source VRPT field. "
+                          "Has %d, requires %d",
+                          poSrcVRPT->GetDataSize(), nNVPT * nPtrSize );
                 return FALSE;
             }
 
             /* copy over each ptr */
             for( int i = 0; i < nNVPT; i++ )
             {
-                const char *pachRawData;
+                const char *pachRawData = poSrcVRPT->GetData() + nPtrSize * i;
 
-                pachRawData = poSrcVRPT->GetData() + nPtrSize * i;
-
-                poTarget->SetFieldRaw( poDstVRPT, i + nVPIX - 1, 
+                poTarget->SetFieldRaw( poDstVRPT, i + nVPIX - 1,
                                        pachRawData, nPtrSize );
             }
         }
@@ -2817,31 +2817,29 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
 /* -------------------------------------------------------------------- */
     if( poUpdate->FindField( "SGCC" ) != NULL )
     {
-        int     nCCUI = poUpdate->GetIntSubfield( "SGCC", 0, "CCUI", 0 );
-        int     nCCIX = poUpdate->GetIntSubfield( "SGCC", 0, "CCIX", 0 );
-        int     nCCNC = poUpdate->GetIntSubfield( "SGCC", 0, "CCNC", 0 );
         DDFField *poSrcSG2D = poUpdate->FindField( "SG2D" );
         DDFField *poDstSG2D = poTarget->FindField( "SG2D" );
-        int     nCoordSize;
 
         /* If we don't have SG2D, check for SG3D */
         if( poDstSG2D == NULL )
         {
             poDstSG2D = poTarget->FindField( "SG3D" );
-            if (poDstSG2D != NULL) 
-            { 
-                poSrcSG2D = poUpdate->FindField("SG3D"); 
-            } 
+            if (poDstSG2D != NULL)
+            {
+                poSrcSG2D = poUpdate->FindField("SG3D");
+            }
         }
 
-        if( (poSrcSG2D == NULL && nCCUI != 2) 
+        const int nCCUI = poUpdate->GetIntSubfield( "SGCC", 0, "CCUI", 0 );
+
+        if( (poSrcSG2D == NULL && nCCUI != 2)
             || (poDstSG2D == NULL && nCCUI != 1) )
         {
             //CPLAssert( FALSE );
             return FALSE;
         }
 
-        if (poDstSG2D == NULL) 
+        if (poDstSG2D == NULL)
         {
             poTarget->AddField(poTarget->GetModule()->FindFieldDefn("SG2D"));
             poDstSG2D = poTarget->FindField("SG2D");
@@ -2854,24 +2852,28 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
             poTarget->SetFieldRaw( poDstSG2D, 0, NULL, 0 );
         }
 
-        nCoordSize = poDstSG2D->GetFieldDefn()->GetFixedWidth();
+        int nCoordSize = poDstSG2D->GetFieldDefn()->GetFixedWidth();
+        const int nCCIX = poUpdate->GetIntSubfield( "SGCC", 0, "CCIX", 0 );
+        const int nCCNC = poUpdate->GetIntSubfield( "SGCC", 0, "CCNC", 0 );
 
         if( nCCUI == 1 ) /* INSERT */
         {
-            char        *pachInsertion;
-            int         nInsertionBytes = nCoordSize * nCCNC;
+            int nInsertionBytes = nCoordSize * nCCNC;
 
             if( poSrcSG2D->GetDataSize() < nInsertionBytes )
             {
-                CPLDebug("S57", "Not enough bytes in source SG2D field. Has %d, requires %d",
-                         poSrcSG2D->GetDataSize(), nInsertionBytes );
+                CPLDebug( "S57", "Not enough bytes in source SG2D field. "
+                          "Has %d, requires %d",
+                          poSrcSG2D->GetDataSize(), nInsertionBytes );
                 return FALSE;
             }
 
-            pachInsertion = (char *) CPLMalloc(nInsertionBytes + nCoordSize);
+            char *pachInsertion
+                = static_cast<char *>(
+                    CPLMalloc(nInsertionBytes + nCoordSize) );
             memcpy( pachInsertion, poSrcSG2D->GetData(), nInsertionBytes );
 
-            /* 
+            /*
             ** If we are inserting before an instance that already
             ** exists, we must add it to the end of the data being
             ** inserted.
@@ -2880,19 +2882,20 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
             {
                 if( poDstSG2D->GetDataSize() < nCoordSize * nCCIX )
                 {
-                    CPLDebug("S57", "Not enough bytes in dest SG2D field. Has %d, requires %d",
-                         poDstSG2D->GetDataSize(), nCoordSize * nCCIX );
+                    CPLDebug( "S57", "Not enough bytes in dest SG2D field. "
+                              "Has %d, requires %d",
+                              poDstSG2D->GetDataSize(), nCoordSize * nCCIX );
                     CPLFree( pachInsertion );
                     return FALSE;
                 }
 
-                memcpy( pachInsertion + nInsertionBytes, 
-                        poDstSG2D->GetData() + nCoordSize * (nCCIX-1), 
+                memcpy( pachInsertion + nInsertionBytes,
+                        poDstSG2D->GetData() + nCoordSize * (nCCIX-1),
                         nCoordSize );
                 nInsertionBytes += nCoordSize;
             }
 
-            poTarget->SetFieldRaw( poDstSG2D, nCCIX - 1, 
+            poTarget->SetFieldRaw( poDstSG2D, nCCIX - 1,
                                    pachInsertion, nInsertionBytes );
             CPLFree( pachInsertion );
         }
@@ -2908,19 +2911,18 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
         {
             if( poSrcSG2D->GetDataSize() < nCCNC * nCoordSize )
             {
-                CPLDebug("S57", "Not enough bytes in source SG2D field. Has %d, requires %d",
-                         poSrcSG2D->GetDataSize(), nCCNC * nCoordSize );
+                CPLDebug( "S57", "Not enough bytes in source SG2D field. "
+                          "Has %d, requires %d",
+                          poSrcSG2D->GetDataSize(), nCCNC * nCoordSize );
                 return FALSE;
             }
 
             /* copy over each ptr */
             for( int i = 0; i < nCCNC; i++ )
             {
-                const char *pachRawData;
-
-                pachRawData = poSrcSG2D->GetData() + nCoordSize * i;
+                const char *pachRawData = poSrcSG2D->GetData() + nCoordSize * i;
 
-                poTarget->SetFieldRaw( poDstSG2D, i + nCCIX - 1, 
+                poTarget->SetFieldRaw( poDstSG2D, i + nCCIX - 1,
                                        pachRawData, nCoordSize );
             }
         }
@@ -2933,12 +2935,10 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
     if( poUpdate->FindField( "FFPC" ) != NULL )
     {
         int     nFFUI = poUpdate->GetIntSubfield( "FFPC", 0, "FFUI", 0 );
-        int     nFFIX = poUpdate->GetIntSubfield( "FFPC", 0, "FFIX", 0 );
-        int     nNFPT = poUpdate->GetIntSubfield( "FFPC", 0, "NFPT", 0 );
         DDFField *poSrcFFPT = poUpdate->FindField( "FFPT" );
         DDFField *poDstFFPT = poTarget->FindField( "FFPT" );
 
-        if( (poSrcFFPT == NULL && nFFUI != 2) 
+        if( (poSrcFFPT == NULL && nFFUI != 2)
             || (poDstFFPT == NULL && nFFUI != 1) )
         {
             CPLDebug( "S57", "Missing source or target FFPT applying update.");
@@ -2947,7 +2947,7 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
         }
 
         // Create FFPT field on target record, if it does not yet exist.
-        if (poDstFFPT == NULL) 
+        if (poDstFFPT == NULL)
         {
             // Untested!
             poTarget->AddField(poTarget->GetModule()->FindFieldDefn("FFPT"));
@@ -2966,27 +2966,30 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
         // an empty string so we will take a chance and assume that so
         // we have a fixed record length.  We *could* actually verify that
         // but I have not done so for now.
-        int nFFPTSize = 10;
+        const int nFFPTSize = 10;
+        const int nFFIX = poUpdate->GetIntSubfield( "FFPC", 0, "FFIX", 0 );
+        const int nNFPT = poUpdate->GetIntSubfield( "FFPC", 0, "NFPT", 0 );
 
         if (nFFUI == 1 ) /* INSERT */
         {
             // Untested!
             CPLDebug( "S57", "Using untested FFPT INSERT code!");
 
-            char        *pachInsertion;
-            int         nInsertionBytes = nFFPTSize * nNFPT;
+            int nInsertionBytes = nFFPTSize * nNFPT;
 
             if( poSrcFFPT->GetDataSize() < nInsertionBytes )
             {
-                CPLDebug("S57", "Not enough bytes in source FFPT field. Has %d, requires %d",
-                         poSrcFFPT->GetDataSize(), nInsertionBytes );
+                CPLDebug( "S57", "Not enough bytes in source FFPT field. "
+                          "Has %d, requires %d",
+                          poSrcFFPT->GetDataSize(), nInsertionBytes );
                 return FALSE;
             }
 
-            pachInsertion = (char *) CPLMalloc(nInsertionBytes + nFFPTSize);
+            char *pachInsertion
+                = static_cast<char *>( CPLMalloc(nInsertionBytes + nFFPTSize) );
             memcpy( pachInsertion, poSrcFFPT->GetData(), nInsertionBytes );
 
-            /* 
+            /*
             ** If we are inserting before an instance that already
             ** exists, we must add it to the end of the data being
             ** inserted.
@@ -2995,22 +2998,23 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
             {
                 if( poDstFFPT->GetDataSize() < nFFPTSize * nFFIX )
                 {
-                    CPLDebug("S57", "Not enough bytes in dest FFPT field. Has %d, requires %d",
-                         poDstFFPT->GetDataSize(), nFFPTSize * nFFIX );
+                    CPLDebug( "S57", "Not enough bytes in dest FFPT field. "
+                              "Has %d, requires %d",
+                              poDstFFPT->GetDataSize(), nFFPTSize * nFFIX );
                     CPLFree( pachInsertion );
                     return FALSE;
                 }
 
-                memcpy( pachInsertion + nInsertionBytes, 
-                        poDstFFPT->GetData() + nFFPTSize * (nFFIX-1), 
+                memcpy( pachInsertion + nInsertionBytes,
+                        poDstFFPT->GetData() + nFFPTSize * (nFFIX-1),
                         nFFPTSize );
                 nInsertionBytes += nFFPTSize;
             }
 
-            poTarget->SetFieldRaw( poDstFFPT, nFFIX - 1, 
+            poTarget->SetFieldRaw( poDstFFPT, nFFIX - 1,
                                    pachInsertion, nInsertionBytes );
             CPLFree( pachInsertion );
-        } 
+        }
         else if( nFFUI == 2 ) /* DELETE */
         {
             // Untested!
@@ -3026,19 +3030,18 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
         {
             if( poSrcFFPT->GetDataSize() < nNFPT * nFFPTSize )
             {
-                CPLDebug("S57", "Not enough bytes in source FFPT field. Has %d, requires %d",
-                         poSrcFFPT->GetDataSize(), nNFPT * nFFPTSize );
+                CPLDebug( "S57", "Not enough bytes in source FFPT field. "
+                          "Has %d, requires %d",
+                          poSrcFFPT->GetDataSize(), nNFPT * nFFPTSize );
                 return FALSE;
             }
 
             /* copy over each ptr */
             for( int i = 0; i < nNFPT; i++ )
             {
-                const char *pachRawData;
+                const char *pachRawData = poSrcFFPT->GetData() + nFFPTSize * i;
 
-                pachRawData = poSrcFFPT->GetData() + nFFPTSize * i;
-
-                poTarget->SetFieldRaw( poDstFFPT, i + nFFIX - 1, 
+                poTarget->SetFieldRaw( poDstFFPT, i + nFFIX - 1,
                                        pachRawData, nFFPTSize );
             }
         }
@@ -3049,22 +3052,24 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
 /* -------------------------------------------------------------------- */
     if( poUpdate->FindField( "ATTF" ) != NULL )
     {
-        DDFField *poSrcATTF = poUpdate->FindField( "ATTF" );
         DDFField *poDstATTF = poTarget->FindField( "ATTF" );
-        int     nRepeatCount = poSrcATTF->GetRepeatCount();
 
         if( poDstATTF == NULL )
         {
             CPLError( CE_Warning, CPLE_AppDefined,
-                      "Unable to apply ATTF change to target record without an ATTF field (see GDAL/OGR Bug #1648)" );
+                      "Unable to apply ATTF change to target record without "
+                      "an ATTF field (see GDAL/OGR Bug #1648)" );
             return FALSE;
         }
 
+        DDFField *poSrcATTF = poUpdate->FindField( "ATTF" );
+        const int nRepeatCount = poSrcATTF->GetRepeatCount();
+
         for( int iAtt = 0; iAtt < nRepeatCount; iAtt++ )
         {
-            int nATTL = poUpdate->GetIntSubfield( "ATTF", 0, "ATTL", iAtt );
-            int iTAtt, nDataBytes;
-            const char *pszRawData;
+            const int nATTL
+                = poUpdate->GetIntSubfield( "ATTF", 0, "ATTL", iAtt );
+            int iTAtt;
 
             for( iTAtt = poDstATTF->GetRepeatCount()-1; iTAtt >= 0; iTAtt-- )
             {
@@ -3075,14 +3080,16 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
             if( iTAtt == -1 )
                 iTAtt = poDstATTF->GetRepeatCount();
 
-            pszRawData = poSrcATTF->GetInstanceData( iAtt, &nDataBytes );
+            int nDataBytes;
+            const char *pszRawData
+                = poSrcATTF->GetInstanceData( iAtt, &nDataBytes );
             if( pszRawData[2] == 0x7f /* delete marker */ )
             {
                 poTarget->SetFieldRaw( poDstATTF, iTAtt, NULL, 0 );
             }
             else
             {
-                poTarget->SetFieldRaw( poDstATTF, iTAtt, pszRawData, 
+                poTarget->SetFieldRaw( poDstATTF, iTAtt, pszRawData,
                                        nDataBytes );
             }
         }
@@ -3102,8 +3109,6 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
 int S57Reader::ApplyUpdates( DDFModule *poUpdateModule )
 
 {
-    DDFRecord   *poRecord;
-
 /* -------------------------------------------------------------------- */
 /*      Ensure base file is loaded.                                     */
 /* -------------------------------------------------------------------- */
@@ -3114,19 +3119,23 @@ int S57Reader::ApplyUpdates( DDFModule *poUpdateModule )
 /*      Read records, and apply as updates.                             */
 /* -------------------------------------------------------------------- */
     CPLErrorReset();
+
+    DDFRecord *poRecord;
+
     while( (poRecord = poUpdateModule->ReadRecord()) != NULL )
     {
-        DDFField        *poKeyField = poRecord->GetField(1);
+        DDFField *poKeyField = poRecord->GetField(1);
         if( poKeyField == NULL )
             return FALSE;
-        const char      *pszKey = poKeyField->GetFieldDefn()->GetName();
-        
+
+        const char *pszKey = poKeyField->GetFieldDefn()->GetName();
+
         if( EQUAL(pszKey,"VRID") || EQUAL(pszKey,"FRID"))
         {
-            int         nRCNM = poRecord->GetIntSubfield( pszKey,0, "RCNM",0 );
-            int         nRCID = poRecord->GetIntSubfield( pszKey,0, "RCID",0 );
-            int         nRVER = poRecord->GetIntSubfield( pszKey,0, "RVER",0 );
-            int         nRUIN = poRecord->GetIntSubfield( pszKey,0, "RUIN",0 );
+            const int nRCNM = poRecord->GetIntSubfield( pszKey,0, "RCNM",0 );
+            const int nRCID = poRecord->GetIntSubfield( pszKey,0, "RCID",0 );
+            const int nRVER = poRecord->GetIntSubfield( pszKey,0, "RVER",0 );
+            const int nRUIN = poRecord->GetIntSubfield( pszKey,0, "RUIN",0 );
             DDFRecordIndex *poIndex = NULL;
 
             if( EQUAL(poKeyField->GetFieldDefn()->GetName(),"VRID") )
@@ -3168,9 +3177,7 @@ int S57Reader::ApplyUpdates( DDFModule *poUpdateModule )
                 }
                 else if( nRUIN == 2 ) /* delete */
                 {
-                    DDFRecord   *poTarget;
-
-                    poTarget = poIndex->FindRecord( nRCID );
+                    DDFRecord *poTarget = poIndex->FindRecord( nRCID );
                     if( poTarget == NULL )
                     {
                         CPLError( CE_Warning, CPLE_AppDefined,
@@ -3192,12 +3199,10 @@ int S57Reader::ApplyUpdates( DDFModule *poUpdateModule )
 
                 else if( nRUIN == 3 ) /* modify in place */
                 {
-                    DDFRecord   *poTarget;
-
-                    poTarget = poIndex->FindRecord( nRCID );
+                    DDFRecord *poTarget = poIndex->FindRecord( nRCID );
                     if( poTarget == NULL )
                     {
-                        CPLError( CE_Warning, CPLE_AppDefined, 
+                        CPLError( CE_Warning, CPLE_AppDefined,
                                   "Can't find RCNM=%d,RCID=%d for update.\n",
                                   nRCNM, nRCID );
                     }
@@ -3205,7 +3210,7 @@ int S57Reader::ApplyUpdates( DDFModule *poUpdateModule )
                     {
                         if( !ApplyRecordUpdate( poTarget, poRecord ) )
                         {
-                            CPLError( CE_Warning, CPLE_AppDefined, 
+                            CPLError( CE_Warning, CPLE_AppDefined,
                                       "An update to RCNM=%d,RCID=%d failed.\n",
                                       nRCNM, nRCID );
                         }
@@ -3218,7 +3223,8 @@ int S57Reader::ApplyUpdates( DDFModule *poUpdateModule )
         {
             if( poDSIDRecord != NULL )
             {
-                const char* pszUPDN = poRecord->GetStringSubfield( "DSID", 0, "UPDN", 0 );
+                const char* pszUPDN
+                    = poRecord->GetStringSubfield( "DSID", 0, "UPDN", 0 );
                 if( pszUPDN != NULL && strlen(pszUPDN) < sizeof(szUPDNUpdate) )
                     strcpy( szUPDNUpdate, pszUPDN );
             }
@@ -3245,21 +3251,20 @@ int S57Reader::ApplyUpdates( DDFModule *poUpdateModule )
 int S57Reader::FindAndApplyUpdates( const char * pszPath )
 
 {
-    int         iUpdate;
-    int         bSuccess = TRUE;
-
     if( pszPath == NULL )
         pszPath = pszModuleName;
 
     if( !EQUAL(CPLGetExtension(pszPath),"000") )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Can't apply updates to a base file with a different\n"
                   "extension than .000.\n" );
         return FALSE;
     }
 
-    for( iUpdate = 1; bSuccess; iUpdate++ )
+    bool bSuccess = true;
+
+    for( int iUpdate = 1; bSuccess; iUpdate++ )
     {
         //Creaing file extension
         CPLString extension;
@@ -3267,7 +3272,7 @@ int S57Reader::FindAndApplyUpdates( const char * pszPath )
         if( 1 <= iUpdate &&  iUpdate < 10 )
         {
             char buf[2];
-            sprintf( buf, "%i", iUpdate );
+            snprintf( buf, sizeof(buf), "%i", iUpdate );
             extension.append("00");
             extension.append(buf);
             dirname.append(buf);
@@ -3275,7 +3280,7 @@ int S57Reader::FindAndApplyUpdates( const char * pszPath )
         else if( 10 <= iUpdate && iUpdate < 100 )
         {
             char buf[3];
-            sprintf( buf, "%i", iUpdate );
+            snprintf( buf, sizeof(buf), "%i", iUpdate );
             extension.append("0");
             extension.append(buf);
             dirname.append(buf);
@@ -3283,32 +3288,32 @@ int S57Reader::FindAndApplyUpdates( const char * pszPath )
         else if( 100 <= iUpdate && iUpdate < 1000 )
         {
             char buf[4];
-            sprintf( buf, "%i", iUpdate );
+            snprintf( buf, sizeof(buf), "%i", iUpdate );
             extension.append(buf);
             dirname.append(buf);
         }
 
         DDFModule oUpdateModule;
-          
+
         //trying current dir first
-        char    *pszUpdateFilename = 
+        char *pszUpdateFilename =
             CPLStrdup(CPLResetExtension(pszPath,extension.c_str()));
 
         VSILFILE *file = VSIFOpenL( pszUpdateFilename, "r" );
         if( file )
         {
             VSIFCloseL( file );
-            bSuccess = oUpdateModule.Open( pszUpdateFilename, TRUE );
-            if( bSuccess )
-                CPLDebug( "S57", "Applying feature updates from %s.", 
-                          pszUpdateFilename );
+            bSuccess = CPL_TO_BOOL(
+                oUpdateModule.Open( pszUpdateFilename, TRUE ) );
             if( bSuccess )
             {
+                CPLDebug( "S57", "Applying feature updates from %s.",
+                          pszUpdateFilename );
                 if( !ApplyUpdates( &oUpdateModule ) )
                     return FALSE;
             }
         }
-        else // file is store on Primar generated cd
+        else // File is store on Primar generated CD.
         {
             char* pszBaseFileDir = CPLStrdup(CPLGetDirname(pszPath));
             char* pszFileDir = CPLStrdup(CPLGetDirname(pszBaseFileDir));
@@ -3320,10 +3325,11 @@ int S57Reader::FindAndApplyUpdates( const char * pszPath )
             remotefile.append( CPLGetBasename(pszPath) );
             remotefile.append( "." );
             remotefile.append( extension );
-            bSuccess = oUpdateModule.Open( remotefile.c_str(), TRUE );
-	
+            bSuccess = CPL_TO_BOOL(
+                oUpdateModule.Open( remotefile.c_str(), TRUE ) );
+
             if( bSuccess )
-                CPLDebug( "S57", "Applying feature updates from %s.", 
+                CPLDebug( "S57", "Applying feature updates from %s.",
                           remotefile.c_str() );
             CPLFree( pszBaseFileDir );
             CPLFree( pszFileDir );
@@ -3349,10 +3355,6 @@ int S57Reader::FindAndApplyUpdates( const char * pszPath )
 OGRErr S57Reader::GetExtent( OGREnvelope *psExtent, int bForce )
 
 {
-#define INDEX_COUNT     4
-
-    DDFRecordIndex      *apoIndex[INDEX_COUNT];
-
 /* -------------------------------------------------------------------- */
 /*      If we aren't forced to get the extent say no if we haven't      */
 /*      already indexed the iso8211 records.                            */
@@ -3367,8 +3369,14 @@ OGRErr S57Reader::GetExtent( OGREnvelope *psExtent, int bForce )
 /*      We will scan all the low level vector elements for extents      */
 /*      coordinates.                                                    */
 /* -------------------------------------------------------------------- */
-    int         bGotExtents = FALSE;
-    int         nXMin=0, nXMax=0, nYMin=0, nYMax=0;
+    bool bGotExtents = false;
+    int nXMin=0;
+    int nXMax=0;
+    int nYMin=0;
+    int nYMax=0;
+
+    const int INDEX_COUNT = 4;
+    DDFRecordIndex *apoIndex[INDEX_COUNT];
 
     apoIndex[0] = &oVI_Index;
     apoIndex[1] = &oVC_Index;
@@ -3382,22 +3390,21 @@ OGRErr S57Reader::GetExtent( OGREnvelope *psExtent, int bForce )
         for( int iVIndex = 0; iVIndex < poIndex->GetCount(); iVIndex++ )
         {
             DDFRecord *poRecord = poIndex->GetByIndex( iVIndex );
-            DDFField    *poSG3D = poRecord->FindField( "SG3D" );
-            DDFField    *poSG2D = poRecord->FindField( "SG2D" );
+            DDFField *poSG3D = poRecord->FindField( "SG3D" );
+            DDFField *poSG2D = poRecord->FindField( "SG2D" );
 
             if( poSG3D != NULL )
             {
-                int     i, nVCount = poSG3D->GetRepeatCount();
-                GInt32  *panData, nX, nY;
-
-                panData = (GInt32 *) poSG3D->GetData();
-                if( poSG3D->GetDataSize() < 3 * nVCount * (int)sizeof(int) )
+                const int  nVCount = poSG3D->GetRepeatCount();
+                const GByte *pabyData = (const GByte*)poSG3D->GetData();
+                if( poSG3D->GetDataSize() <
+                    3 * nVCount * static_cast<int>( sizeof(int) ) )
                     return OGRERR_FAILURE;
 
-                for( i = 0; i < nVCount; i++ )
+                for( int i = 0; i < nVCount; i++ )
                 {
-                    nX = CPL_LSBWORD32(panData[i*3+1]);
-                    nY = CPL_LSBWORD32(panData[i*3+0]);
+                    GInt32 nX = CPL_LSBINT32PTR(pabyData + 4*(i*3+1));
+                    GInt32 nY = CPL_LSBINT32PTR(pabyData + 4*(i*3+0));
 
                     if( bGotExtents )
                     {
@@ -3408,8 +3415,10 @@ OGRErr S57Reader::GetExtent( OGREnvelope *psExtent, int bForce )
                     }
                     else
                     {
-                        nXMin = nXMax = nX; 
-                        nYMin = nYMax = nY;
+                        nXMin = nX;
+                        nXMax = nX;
+                        nYMin = nY;
+                        nYMax = nY;
                         bGotExtents = TRUE;
                     }
                 }
@@ -3417,16 +3426,17 @@ OGRErr S57Reader::GetExtent( OGREnvelope *psExtent, int bForce )
             else if( poSG2D != NULL )
             {
                 int     i, nVCount = poSG2D->GetRepeatCount();
-                GInt32  *panData, nX, nY;
+                GInt32  nX, nY;
+                const GByte   *pabyData;
 
-                panData = (GInt32 *) poSG2D->GetData();
+                pabyData = (const GByte*)poSG2D->GetData();
                 if( poSG2D->GetDataSize() < 2 * nVCount * (int)sizeof(int) )
                     return OGRERR_FAILURE;
 
                 for( i = 0; i < nVCount; i++ )
                 {
-                    nX = CPL_LSBWORD32(panData[i*2+1]);
-                    nY = CPL_LSBWORD32(panData[i*2+0]);
+                    nX = CPL_LSBINT32PTR(pabyData + 4*(i*2+1));
+                    nY = CPL_LSBINT32PTR(pabyData + 4*(i*2+0));
 
                     if( bGotExtents )
                     {
@@ -3437,8 +3447,10 @@ OGRErr S57Reader::GetExtent( OGREnvelope *psExtent, int bForce )
                     }
                     else
                     {
-                        nXMin = nXMax = nX; 
-                        nYMin = nYMax = nY;
+                        nXMin = nX;
+                        nXMax = nX;
+                        nYMin = nY;
+                        nYMax = nY;
                         bGotExtents = TRUE;
                     }
                 }
@@ -3450,10 +3462,10 @@ OGRErr S57Reader::GetExtent( OGREnvelope *psExtent, int bForce )
         return OGRERR_FAILURE;
     else
     {
-        psExtent->MinX = nXMin / (double) nCOMF;
-        psExtent->MaxX = nXMax / (double) nCOMF;
-        psExtent->MinY = nYMin / (double) nCOMF;
-        psExtent->MaxY = nYMax / (double) nCOMF;
+        psExtent->MinX = nXMin / static_cast<double>( nCOMF );
+        psExtent->MaxX = nXMax / static_cast<double>( nCOMF );
+        psExtent->MinY = nYMin / static_cast<double>( nCOMF );
+        psExtent->MaxY = nYMax / static_cast<double>( nCOMF );
 
         return OGRERR_NONE;
     }
diff --git a/ogr/ogrsf_frmts/s57/s57tables.h b/ogr/ogrsf_frmts/s57/s57tables.h
index fc809bf..0048aed 100644
--- a/ogr/ogrsf_frmts/s57/s57tables.h
+++ b/ogr/ogrsf_frmts/s57/s57tables.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: s57tables.h 9412 2006-03-28 23:13:12Z fwarmerdam $
+ * $Id: s57tables.h 32444 2015-12-25 01:14:58Z goatbar $
  *
  * Project:  S-57 Translator
  * Purpose:  Inline tables.
@@ -27,7 +27,9 @@
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
 
-char *gpapszS57Classes[] = {
+// Only included in s57classregistrar.cpp.
+
+static const char *gpapszS57Classes[] = {
 "\"Code\",\"ObjectClass\",\"Acronym\",\"Attribute_A\",\"Attribute_B\",\"Attribute_C\",\"Class\",\"Primitives\"",
 "1,Administration area (Named),ADMARE,JRSDTN;NATION;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;",
 "2,Airport / airfield,AIRARE,CATAIR;CONDTN;CONVIS;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;",
@@ -211,7 +213,7 @@ char *gpapszS57Classes[] = {
 "503,Compass,$COMPS,$CSIZE;RYRMGV;VALACM;VALMAG;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,$,",
 "504,Text,$TEXTS,$CHARS;COLOUR;$JUSTH;$JUSTV;$NTXST;$SPACE;$TXSTR;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,$,",
 NULL };
-char *gpapszS57attributes[] = {
+static const char *gpapszS57attributes[] = {
 "\"Code\",\"Attribute\",\"Acronym\",\"Attributetype\",\"Class\"",
 "1,Agency responsible for production,AGENCY,A,F",
 "2,Beacon shape,BCNSHP,E,F",
diff --git a/ogr/ogrsf_frmts/s57/s57tables.py b/ogr/ogrsf_frmts/s57/s57tables.py
index 79f1b23..5f56e71 100755
--- a/ogr/ogrsf_frmts/s57/s57tables.py
+++ b/ogr/ogrsf_frmts/s57/s57tables.py
@@ -1,24 +1,24 @@
 #!/usr/bin/env python
 #******************************************************************************
-#  $Id: s57tables.py 2780 2001-12-17 22:33:06Z warmerda $
-# 
+#  $Id: s57tables.py 32444 2015-12-25 01:14:58Z goatbar $
+#
 #  Project:  S-57 OGR Translator
 #  Purpose:  Script to translate s57 .csv files into C code "data" statements.
 #  Author:   Frank Warmerdam, warmerdam at pobox.com
-# 
+#
 #******************************************************************************
 #  Copyright (c) 2001, Frank Warmerdam
-# 
+#
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
 #  to deal in the Software without restriction, including without limitation
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -27,18 +27,13 @@
 #  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 #  DEALINGS IN THE SOFTWARE.
 #******************************************************************************
-# 
-# $Log$
-# Revision 1.1  2001/12/17 22:33:06  warmerda
-# New
-#
 
-import sys
 import os
 import string
+import sys
 
 # -----------------------------------------------------------------------------
-#	EscapeLine - escape anything C-problematic in a line.
+# EscapeLine - escape anything C-problematic in a line.
 # -----------------------------------------------------------------------------
 
 def EscapeLine( line ):
@@ -53,7 +48,7 @@ def EscapeLine( line ):
     return line_out
 
 # -----------------------------------------------------------------------------
-# 
+#
 
 if __name__ != '__main__':
     print 'This module should only be used as a mainline.'
@@ -70,7 +65,7 @@ classes = open( directory + '/s57objectclasses.csv' ).readlines()
 
 for line in classes:
     print '"%s",' % EscapeLine(string.strip(line))
-    
+
 print 'NULL };'
 
 print 'char *gpapszS57attributes[] = {'
@@ -78,7 +73,7 @@ classes = open( directory + '/s57attributes.csv' ).readlines()
 
 for line in classes:
     print '"%s",' % EscapeLine(string.strip(line))
-    
+
 print 'NULL };'
 
-    
+
diff --git a/ogr/ogrsf_frmts/s57/s57writer.cpp b/ogr/ogrsf_frmts/s57/s57writer.cpp
index 54750c5..02e3eed 100644
--- a/ogr/ogrsf_frmts/s57/s57writer.cpp
+++ b/ogr/ogrsf_frmts/s57/s57writer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: s57writer.cpp 28348 2015-01-23 15:27:13Z rouault $
+ * $Id: s57writer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  S-57 Translator
  * Purpose:  Implements S57Writer class.
@@ -28,27 +28,25 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "s57.h"
-#include "ogr_api.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "ogr_api.h"
+#include "s57.h"
 
-CPL_CVSID("$Id: s57writer.cpp 28348 2015-01-23 15:27:13Z rouault $");
+CPL_CVSID("$Id: s57writer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                             S57Writer()                              */
 /************************************************************************/
 
-S57Writer::S57Writer()
-
-{
-    poModule = NULL;
-    poRegistrar = NULL;
-    poClassContentExplorer = NULL;
-
-    nCOMF = 10000000;
-    nSOMF = 10;
-}
+S57Writer::S57Writer() :
+    poModule(NULL),
+    nNext0001Index(0),
+    poRegistrar(NULL),
+    poClassContentExplorer(NULL),
+    nCOMF(10000000),
+    nSOMF(10)
+{ }
 
 /************************************************************************/
 /*                             ~S57Writer()                             */
@@ -88,9 +86,8 @@ int S57Writer::Close()
 int S57Writer::CreateS57File( const char *pszFilename )
 
 {
-    DDFModule  oModule;
-    DDFFieldDefn *poFDefn;
-
+    // TODO: What was oModule for if it was unused?
+    // DDFModule  oModule;
     Close();
 
     nNext0001Index = 1;
@@ -104,10 +101,13 @@ int S57Writer::CreateS57File( const char *pszFilename )
 /* -------------------------------------------------------------------- */
 /*      Create the '0000' definition.                                   */
 /* -------------------------------------------------------------------- */
-    poFDefn = new DDFFieldDefn();
+    DDFFieldDefn *poFDefn = new DDFFieldDefn();
 
-    poFDefn->Create( "0000", "", "0001DSIDDSIDDSSI0001DSPM0001VRIDVRIDATTVVRIDVRPCVRIDVRPTVRIDSGCCVRIDSG2DVRIDSG3D0001FRIDFRIDFOIDFRIDATTFFRIDNATFFRIDFFPCFRIDFFPTFRIDFSPCFRIDFSPT",
-                     dsc_elementary, 
+    poFDefn->Create( "0000", "",
+                     "0001DSIDDSIDDSSI0001DSPM0001VRIDVRIDATTVVRIDVRPCVRID"
+                     "VRPTVRIDSGCCVRIDSG2DVRIDSG3D0001FRIDFRIDFOIDFRIDATTF"
+                     "FRIDNATFFRIDFFPCFRIDFFPTFRIDFSPCFRIDFSPT",
+                     dsc_elementary,
                      dtc_char_string );
 
     poModule->AddField( poFDefn );
@@ -117,7 +117,7 @@ int S57Writer::CreateS57File( const char *pszFilename )
 /* -------------------------------------------------------------------- */
     poFDefn = new DDFFieldDefn();
 
-    poFDefn->Create( "0001", "ISO 8211 Record Identifier", "", 
+    poFDefn->Create( "0001", "ISO 8211 Record Identifier", "",
                      dsc_elementary, dtc_bit_string,
                      "(b12)" );
 
@@ -358,7 +358,9 @@ int S57Writer::CreateS57File( const char *pszFilename )
 /* -------------------------------------------------------------------- */
     poFDefn = new DDFFieldDefn();
 
-    poFDefn->Create( "FFPC", "Feature record to feature object pointer control field", "",
+    poFDefn->Create( "FFPC",
+                     "Feature record to feature object pointer control field",
+                     "",
                      dsc_vector, dtc_mixed_data_type );
 
     poFDefn->AddSubfield( "FFUI", "b11" );
@@ -372,7 +374,8 @@ int S57Writer::CreateS57File( const char *pszFilename )
 /* -------------------------------------------------------------------- */
     poFDefn = new DDFFieldDefn();
 
-    poFDefn->Create( "FFPT", "Feature record to feature object pointer field", "*",
+    poFDefn->Create( "FFPT", "Feature record to feature object pointer field",
+                     "*",
                      dsc_array, dtc_mixed_data_type );
 
     poFDefn->AddSubfield( "LNAM", "B(64)" );
@@ -386,7 +389,9 @@ int S57Writer::CreateS57File( const char *pszFilename )
 /* -------------------------------------------------------------------- */
     poFDefn = new DDFFieldDefn();
 
-    poFDefn->Create( "FSPC", "Feature record to spatial record pointer control field", "",
+    poFDefn->Create( "FSPC",
+                     "Feature record to spatial record pointer control field",
+                     "",
                      dsc_vector, dtc_mixed_data_type );
 
     poFDefn->AddSubfield( "FSUI", "b11" );
@@ -400,7 +405,7 @@ int S57Writer::CreateS57File( const char *pszFilename )
 /* -------------------------------------------------------------------- */
     poFDefn = new DDFFieldDefn();
 
-    poFDefn->Create( "FSPT", "Feature record to spatial record pointer field", 
+    poFDefn->Create( "FSPT", "Feature record to spatial record pointer field",
                      "*", dsc_array, dtc_mixed_data_type );
 
     poFDefn->AddSubfield( "NAME", "B(40)" );
@@ -489,13 +494,18 @@ int S57Writer::WriteDSID( int nEXPP /*1*/, int nINTU /*4*/,
     poRec->SetIntSubfield   ( "DSSI", 0, "AALL", 0, 0 );
     poRec->SetIntSubfield   ( "DSSI", 0, "NALL", 0, 0 );
     poRec->SetIntSubfield   ( "DSSI", 0, "NOMR", 0, nNOMR ); // Meta records
-    poRec->SetIntSubfield   ( "DSSI", 0, "NOCR", 0, 0 ); // Cartographic records are not permitted in ENC
+    // Cartographic records are not permitted in ENC.
+    poRec->SetIntSubfield   ( "DSSI", 0, "NOCR", 0, 0 );
     poRec->SetIntSubfield   ( "DSSI", 0, "NOGR", 0, nNOGR ); // Geo records
-    poRec->SetIntSubfield   ( "DSSI", 0, "NOLR", 0, nNOLR ); // Collection records
-    poRec->SetIntSubfield   ( "DSSI", 0, "NOIN", 0, nNOIN ); // Isolated node records
-    poRec->SetIntSubfield   ( "DSSI", 0, "NOCN", 0, nNOCN ); // Connected node records
+    // Collection records.
+    poRec->SetIntSubfield   ( "DSSI", 0, "NOLR", 0, nNOLR );
+    // Isolated node records.
+    poRec->SetIntSubfield   ( "DSSI", 0, "NOIN", 0, nNOIN );
+    // Connected node records.
+    poRec->SetIntSubfield   ( "DSSI", 0, "NOCN", 0, nNOCN );
     poRec->SetIntSubfield   ( "DSSI", 0, "NOED", 0, nNOED ); // Edge records
-    poRec->SetIntSubfield   ( "DSSI", 0, "NOFA", 0, 0 ); // Face are not permitted in chain node structure
+    // Face are not permitted in chain node structure.
+    poRec->SetIntSubfield   ( "DSSI", 0, "NOFA", 0, 0 );
 
 /* -------------------------------------------------------------------- */
 /*      Write out the record.                                           */
@@ -532,7 +542,8 @@ int S57Writer::WriteDSPM( int nHDAT, int nVDAT, int nSDAT, int nCSCL )
 
     poRec->SetIntSubfield   ( "DSPM", 0, "RCNM", 0, 20 );
     poRec->SetIntSubfield   ( "DSPM", 0, "RCID", 0, 1 );
-    poRec->SetIntSubfield   ( "DSPM", 0, "HDAT", 0, nHDAT ); // Must be 2 for ENC
+    // Must be 2 for ENC.
+    poRec->SetIntSubfield   ( "DSPM", 0, "HDAT", 0, nHDAT );
     poRec->SetIntSubfield   ( "DSPM", 0, "VDAT", 0, nVDAT );
     poRec->SetIntSubfield   ( "DSPM", 0, "SDAT", 0, nSDAT );
     poRec->SetIntSubfield   ( "DSPM", 0, "CSCL", 0, nCSCL );
@@ -562,14 +573,13 @@ int S57Writer::WriteDSPM( int nHDAT, int nVDAT, int nSDAT, int nCSCL )
 DDFRecord *S57Writer::MakeRecord()
 
 {
-    DDFRecord *poRec = new DDFRecord( poModule );
-    DDFField *poField;
-    unsigned char abyData[2];
-
-    abyData[0] = nNext0001Index % 256;
-    abyData[1] = (unsigned char) (nNext0001Index / 256); 
+    unsigned char abyData[2] = {
+        static_cast<unsigned char>( nNext0001Index % 256 ),
+        static_cast<unsigned char>( nNext0001Index / 256 )
+    };
 
-    poField = poRec->AddField( poModule->FindFieldDefn( "0001" ) );
+    DDFRecord *poRec = new DDFRecord( poModule );
+    DDFField *poField = poRec->AddField( poModule->FindFieldDefn( "0001" ) );
     poRec->SetFieldRaw( poField, 0, (const char *) abyData, 2 );
 
     nNext0001Index++;
@@ -581,34 +591,34 @@ DDFRecord *S57Writer::MakeRecord()
 /*                           WriteGeometry()                            */
 /************************************************************************/
 
-int S57Writer::WriteGeometry( DDFRecord *poRec, int nVertCount, 
+int S57Writer::WriteGeometry( DDFRecord *poRec, int nVertCount,
                               double *padfX, double *padfY, double *padfZ )
 
 {
     const char *pszFieldName = "SG2D";
-    DDFField *poField;
-    int nRawDataSize, i, nSuccess;
-    unsigned char *pabyRawData;
 
     if( padfZ != NULL )
         pszFieldName = "SG3D";
 
-    poField = poRec->AddField( poModule->FindFieldDefn( pszFieldName ) );
+    DDFField *poField
+        = poRec->AddField( poModule->FindFieldDefn( pszFieldName ) );
 
+    int nRawDataSize;
     if( padfZ )
         nRawDataSize = 12 * nVertCount;
     else
         nRawDataSize = 8 * nVertCount;
 
-    pabyRawData = (unsigned char *) CPLMalloc(nRawDataSize);
+    unsigned char *pabyRawData
+        = static_cast<unsigned char *>( CPLMalloc(nRawDataSize) );
 
-    for( i = 0; i < nVertCount; i++ )
+    for( int i = 0; i < nVertCount; i++ )
     {
-        GInt32 nXCOO, nYCOO, nVE3D;
+        const GInt32 nXCOO = CPL_LSBWORD32(
+            static_cast<GInt32>( floor(padfX[i] * nCOMF + 0.5)) );
+        const GInt32 nYCOO = CPL_LSBWORD32(
+            static_cast<GInt32>( floor(padfY[i] * nCOMF + 0.5)) );
 
-        nXCOO = CPL_LSBWORD32((GInt32) floor(padfX[i] * nCOMF + 0.5));
-        nYCOO = CPL_LSBWORD32((GInt32) floor(padfY[i] * nCOMF + 0.5));
-        
         if( padfZ == NULL )
         {
             memcpy( pabyRawData + i * 8, &nYCOO, 4 );
@@ -616,15 +626,17 @@ int S57Writer::WriteGeometry( DDFRecord *poRec, int nVertCount,
         }
         else
         {
-            nVE3D = CPL_LSBWORD32((GInt32) floor( padfZ[i] * nSOMF + 0.5 ));
+            const GInt32 nVE3D = CPL_LSBWORD32(
+                static_cast<GInt32>( floor( padfZ[i] * nSOMF + 0.5 )) );
             memcpy( pabyRawData + i * 12, &nYCOO, 4 );
             memcpy( pabyRawData + i * 12 + 4, &nXCOO, 4 );
             memcpy( pabyRawData + i * 12 + 8, &nVE3D, 4 );
         }
     }
 
-    nSuccess = poRec->SetFieldRaw( poField, 0, 
-                                   (const char *) pabyRawData, nRawDataSize );
+    int nSuccess = poRec->SetFieldRaw(
+        poField, 0,
+        reinterpret_cast<const char *>( pabyRawData ), nRawDataSize );
 
     CPLFree( pabyRawData );
 
@@ -663,13 +675,13 @@ int S57Writer::WritePrimitive( OGRFeature *poFeature )
         double dfX, dfY, dfZ;
         OGRPoint *poPoint = (OGRPoint *) poGeom;
 
-        CPLAssert( poFeature->GetFieldAsInteger( "RCNM") == RCNM_VI 
-                   || poFeature->GetFieldAsInteger( "RCNM") == RCNM_VC ); 
+        CPLAssert( poFeature->GetFieldAsInteger( "RCNM") == RCNM_VI
+                   || poFeature->GetFieldAsInteger( "RCNM") == RCNM_VC );
 
         dfX = poPoint->getX();
         dfY = poPoint->getY();
         dfZ = poPoint->getZ();
-        
+
         if( dfZ == 0.0 )
             WriteGeometry( poRec, 1, &dfX, &dfY, NULL );
         else
@@ -679,15 +691,15 @@ int S57Writer::WritePrimitive( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
 /*      For multipoints we assuming SOUNDG, and write out as SG3D.      */
 /* -------------------------------------------------------------------- */
-    else if( poGeom != NULL 
+    else if( poGeom != NULL
              && wkbFlatten(poGeom->getGeometryType()) == wkbMultiPoint )
     {
         OGRMultiPoint *poMP = (OGRMultiPoint *) poGeom;
         int i, nVCount = poMP->getNumGeometries();
         double *padfX, *padfY, *padfZ;
 
-        CPLAssert( poFeature->GetFieldAsInteger( "RCNM") == RCNM_VI 
-                   || poFeature->GetFieldAsInteger( "RCNM") == RCNM_VC ); 
+        CPLAssert( poFeature->GetFieldAsInteger( "RCNM") == RCNM_VI
+                   || poFeature->GetFieldAsInteger( "RCNM") == RCNM_VC );
 
         padfX = (double *) CPLMalloc(sizeof(double) * nVCount);
         padfY = (double *) CPLMalloc(sizeof(double) * nVCount);
@@ -711,7 +723,7 @@ int S57Writer::WritePrimitive( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
 /*      Handle LINESTRINGs (edge) geometry.                             */
 /* -------------------------------------------------------------------- */
-    else if( poGeom != NULL 
+    else if( poGeom != NULL
              && wkbFlatten(poGeom->getGeometryType()) == wkbLineString )
     {
         OGRLineString *poLS = (OGRLineString *) poGeom;
@@ -756,17 +768,17 @@ int S57Writer::WritePrimitive( OGRFeature *poFeature )
         szName[2] = (char) ((nRCID & 0xff00) >> 8);
         szName[3] = (char) ((nRCID & 0xff0000) >> 16);
         szName[4] = (char) ((nRCID & 0xff000000) >> 24);
-        
+
         poRec->SetStringSubfield( "VRPT", 0, "NAME", 0, szName, 5 );
-        poRec->SetIntSubfield   ( "VRPT", 0, "ORNT", 0, 
+        poRec->SetIntSubfield   ( "VRPT", 0, "ORNT", 0,
                                   poFeature->GetFieldAsInteger( "ORNT_0") );
-        poRec->SetIntSubfield   ( "VRPT", 0, "USAG", 0, 
+        poRec->SetIntSubfield   ( "VRPT", 0, "USAG", 0,
                                   poFeature->GetFieldAsInteger( "USAG_0") );
-        poRec->SetIntSubfield   ( "VRPT", 0, "TOPI", 0, 
+        poRec->SetIntSubfield   ( "VRPT", 0, "TOPI", 0,
                                   poFeature->GetFieldAsInteger( "TOPI_0") );
-        poRec->SetIntSubfield   ( "VRPT", 0, "MASK", 0, 
+        poRec->SetIntSubfield   ( "VRPT", 0, "MASK", 0,
                                   poFeature->GetFieldAsInteger( "MASK_0") );
-        
+
         nRCID = poFeature->GetFieldAsInteger( "NAME_RCID_1");
         szName[0] = RCNM_VC;
         szName[1] = nRCID & 0xff;
@@ -775,13 +787,13 @@ int S57Writer::WritePrimitive( OGRFeature *poFeature )
         szName[4] = (char) ((nRCID & 0xff000000) >> 24);
 
         poRec->SetStringSubfield( "VRPT", 0, "NAME", 1, szName, 5 );
-        poRec->SetIntSubfield   ( "VRPT", 0, "ORNT", 1, 
+        poRec->SetIntSubfield   ( "VRPT", 0, "ORNT", 1,
                                   poFeature->GetFieldAsInteger( "ORNT_1") );
-        poRec->SetIntSubfield   ( "VRPT", 0, "USAG", 1, 
+        poRec->SetIntSubfield   ( "VRPT", 0, "USAG", 1,
                                   poFeature->GetFieldAsInteger( "USAG_1") );
-        poRec->SetIntSubfield   ( "VRPT", 0, "TOPI", 1, 
+        poRec->SetIntSubfield   ( "VRPT", 0, "TOPI", 1,
                                   poFeature->GetFieldAsInteger( "TOPI_1") );
-        poRec->SetIntSubfield   ( "VRPT", 0, "MASK", 1, 
+        poRec->SetIntSubfield   ( "VRPT", 0, "MASK", 1,
                                   poFeature->GetFieldAsInteger( "MASK_1") );
     }
 
@@ -833,10 +845,10 @@ int S57Writer::WriteCompleteFeature( OGRFeature *poFeature )
     OGRFeatureDefn *poFDefn = poFeature->GetDefnRef();
 
 /* -------------------------------------------------------------------- */
-/*      We handle primitives in a seperate method.                      */
+/*      We handle primitives in a separate method.                      */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(poFDefn->GetName(),OGRN_VI) 
-        || EQUAL(poFDefn->GetName(),OGRN_VC) 
+    if( EQUAL(poFDefn->GetName(),OGRN_VI)
+        || EQUAL(poFDefn->GetName(),OGRN_VC)
         || EQUAL(poFDefn->GetName(),OGRN_VE) )
         return WritePrimitive( poFeature );
 
@@ -848,42 +860,45 @@ int S57Writer::WriteCompleteFeature( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
 /*      Add the FRID.                                                   */
 /* -------------------------------------------------------------------- */
-    DDFField *poField;
+    /*DDFField *poField;*/
 
-    poField = poRec->AddField( poModule->FindFieldDefn( "FRID" ) );
+    /*poField = */poRec->AddField( poModule->FindFieldDefn( "FRID" ) );
 
     poRec->SetIntSubfield   ( "FRID", 0, "RCNM", 0, 100 );
-    poRec->SetIntSubfield   ( "FRID", 0, "RCID", 0, 
+    poRec->SetIntSubfield   ( "FRID", 0, "RCID", 0,
                               poFeature->GetFieldAsInteger( "RCID" ) );
-    poRec->SetIntSubfield   ( "FRID", 0, "PRIM", 0, 
+    poRec->SetIntSubfield   ( "FRID", 0, "PRIM", 0,
                               poFeature->GetFieldAsInteger( "PRIM" ) );
-    poRec->SetIntSubfield   ( "FRID", 0, "GRUP", 0, 
+    poRec->SetIntSubfield   ( "FRID", 0, "GRUP", 0,
                               poFeature->GetFieldAsInteger( "GRUP") );
-    poRec->SetIntSubfield   ( "FRID", 0, "OBJL", 0, 
+    poRec->SetIntSubfield   ( "FRID", 0, "OBJL", 0,
                               poFeature->GetFieldAsInteger( "OBJL") );
     poRec->SetIntSubfield   ( "FRID", 0, "RVER", 0, 1 ); /* always new insert*/
     poRec->SetIntSubfield   ( "FRID", 0, "RUIN", 0, 1 );
-        
+
 /* -------------------------------------------------------------------- */
 /*      Add the FOID                                                    */
 /* -------------------------------------------------------------------- */
-    poField = poRec->AddField( poModule->FindFieldDefn( "FOID" ) );
+    /*poField = */poRec->AddField( poModule->FindFieldDefn( "FOID" ) );
 
-    poRec->SetIntSubfield   ( "FOID", 0, "AGEN", 0, 
+    poRec->SetIntSubfield   ( "FOID", 0, "AGEN", 0,
                               poFeature->GetFieldAsInteger( "AGEN") );
-    poRec->SetIntSubfield   ( "FOID", 0, "FIDN", 0, 
+    poRec->SetIntSubfield   ( "FOID", 0, "FIDN", 0,
                               poFeature->GetFieldAsInteger( "FIDN") );
-    poRec->SetIntSubfield   ( "FOID", 0, "FIDS", 0, 
+    poRec->SetIntSubfield   ( "FOID", 0, "FIDS", 0,
                               poFeature->GetFieldAsInteger( "FIDS") );
 
 /* -------------------------------------------------------------------- */
 /*      ATTF support.                                                   */
 /* -------------------------------------------------------------------- */
-    
-    if( poRegistrar != NULL 
+
+    if( poRegistrar != NULL
         && poClassContentExplorer->SelectClass( poFeature->GetDefnRef()->GetName() )
         && !WriteATTF( poRec, poFeature ) )
+    {
+        delete poRec;
         return FALSE;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Add the FSPT if needed.                                         */
@@ -917,8 +932,8 @@ int S57Writer::WriteCompleteFeature( OGRFeature *poFeature )
             pabyRawData[i*8 + 7] = (GByte) panMASK[i];
         }
 
-        poField = poRec->AddField( poModule->FindFieldDefn( "FSPT" ) );
-        poRec->SetFieldRaw( poField, 0, 
+        DDFField* poField = poRec->AddField( poModule->FindFieldDefn( "FSPT" ) );
+        poRec->SetFieldRaw( poField, 0,
                             (const char *) pabyRawData, nRawDataSize );
         CPLFree( pabyRawData );
     }
@@ -931,7 +946,7 @@ int S57Writer::WriteCompleteFeature( OGRFeature *poFeature )
     if( CSLCount(papszLNAM_REFS) > 0 )
     {
         int i, nRefCount = CSLCount(papszLNAM_REFS);
-        const int *panRIND = 
+        const int *panRIND =
             poFeature->GetFieldAsIntegerList( "FFPT_RIND", NULL );
 
         poRec->AddField( poModule->FindFieldDefn( "FFPT" ) );
@@ -946,7 +961,7 @@ int S57Writer::WriteCompleteFeature( OGRFeature *poFeature )
             // AGEN
             szLNAM[1] = GetHEXChar( papszLNAM_REFS[i] + 0 );
             szLNAM[0] = GetHEXChar( papszLNAM_REFS[i] + 2 );
-            
+
             // FIDN
             szLNAM[5] = GetHEXChar( papszLNAM_REFS[i] + 4 );
             szLNAM[4] = GetHEXChar( papszLNAM_REFS[i] + 6 );
@@ -959,9 +974,9 @@ int S57Writer::WriteCompleteFeature( OGRFeature *poFeature )
 
             szLNAM[8] = '\0';
 
-            poRec->SetStringSubfield( "FFPT", 0, "LNAM", i, 
+            poRec->SetStringSubfield( "FFPT", 0, "LNAM", i,
                                       (char *) szLNAM, 8 );
-            poRec->SetIntSubfield( "FFPT", 0, "RIND", i, 
+            poRec->SetIntSubfield( "FFPT", 0, "RIND", i,
                                    panRIND[i] );
         }
     }
@@ -995,24 +1010,24 @@ int S57Writer::WriteATTF( DDFRecord *poRec, OGRFeature *poFeature )
 {
     int nRawSize=0, nACount = 0;
     char achRawData[5000];
-    char **papszAttrList; 
+    char **papszAttrList;
 
     CPLAssert( poRegistrar != NULL );
 
 /* -------------------------------------------------------------------- */
 /*      Loop over all attributes.                                       */
 /* -------------------------------------------------------------------- */
-    papszAttrList = poClassContentExplorer->GetAttributeList(NULL); 
-    
+    papszAttrList = poClassContentExplorer->GetAttributeList(NULL);
+
     for( int iAttr = 0; papszAttrList[iAttr] != NULL; iAttr++ )
     {
         int iField = poFeature->GetFieldIndex( papszAttrList[iAttr] );
-        OGRFieldType eFldType = 
+        OGRFieldType eFldType =
             poFeature->GetDefnRef()->GetFieldDefn(iField)->GetType();
         int nATTLInt;
         GUInt16 nATTL;
         const char *pszATVL;
-        
+
         if( iField < 0 )
             continue;
 
@@ -1027,27 +1042,27 @@ int S57Writer::WriteATTF( DDFRecord *poRec, OGRFeature *poFeature )
         nATTL = CPL_LSBWORD16( nATTL );
         memcpy( achRawData + nRawSize, &nATTL, 2 );
         nRawSize += 2;
-        
+
         pszATVL = poFeature->GetFieldAsString( iField );
 
         // Special hack to handle special "empty" marker in integer fields.
-        if( atoi(pszATVL) == EMPTY_NUMBER_MARKER 
+        if( atoi(pszATVL) == EMPTY_NUMBER_MARKER
             && (eFldType == OFTInteger || eFldType == OFTReal) )
             pszATVL = "";
 
         // Watch for really long data.
         if( strlen(pszATVL) + nRawSize + 10 > sizeof(achRawData) )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Too much ATTF data for fixed buffer size." );
             return FALSE;
         }
 
         // copy data into record buffer.
         memcpy( achRawData + nRawSize, pszATVL, strlen(pszATVL) );
-        nRawSize += strlen(pszATVL);
+        nRawSize += static_cast<int>(strlen(pszATVL));
         achRawData[nRawSize++] = DDF_UNIT_TERMINATOR;
-    
+
         nACount++;
     }
 
diff --git a/ogr/ogrsf_frmts/sde/drv_sde.html b/ogr/ogrsf_frmts/sde/drv_sde.html
index b93c9db..58bb053 100644
--- a/ogr/ogrsf_frmts/sde/drv_sde.html
+++ b/ogr/ogrsf_frmts/sde/drv_sde.html
@@ -13,47 +13,47 @@ relational databases.  The OGR ArcSDE driver depends on being built with the
 ESRI provided ArcSDE client libraries. <p>
 
 ArcSDE instances are accessed with a datasource name of the following
-form.  The server, instance, username and password fields are required. The instance 
-is the port number of the SDE server, which generally defaults to 5151.  
-If the layer parameter is specified then the SDE driver is able to skip reading 
+form.  The server, instance, username and password fields are required. The instance
+is the port number of the SDE server, which generally defaults to 5151.
+If the layer parameter is specified then the SDE driver is able to skip reading
 the summary metadata for each layer; skipping this step can be a significant time savings. <p>
 
-<b>Note</b>: Only GDAL 1.6+ supports querying against versions and write 
-operations.  Older versions only support querying against the base (SDE.DEFAULT) version 
+<b>Note</b>: Only GDAL 1.6+ supports querying against versions and write
+operations.  Older versions only support querying against the base (SDE.DEFAULT) version
 and no writing operations. <p>
-    
+
 <pre>
   SDE:server,instance,database,username,password[,layer]
 </pre>
 
-To specify a version to query against, you *must* specify a layer as well. 
+To specify a version to query against, you *must* specify a layer as well.
 The SDE.DEFAULT version will be used when no version name is specified. <p>
 <pre>
   SDE:server,instance,database,username,password,layer,[version]
 </pre>
 
-You can also request to create a new version if it does not already exist.  
-If the child version already exists, it will be used unless the SDE_VERSIONOVERWRITE 
-environment variable is set to "TRUE".  In that case, the version will be deleted 
+You can also request to create a new version if it does not already exist.
+If the child version already exists, it will be used unless the SDE_VERSIONOVERWRITE
+environment variable is set to "TRUE".  In that case, the version will be deleted
 and recreated.  <p>
 <pre>
   SDE:server,instance,database,username,password,layer,[parentversion],[childversion]
 </pre>
 
 The OGR ArcSDE driver does not support reading CAD data (treated as BLOB
-attribute), annotation properties, measure values at vertices, or raster data.  
-The ExecuteSQL() method does <b>not</b> get passed through to the underlying 
-database.  For now it is interpreted by the limited OGR SQL handler.  
+attribute), annotation properties, measure values at vertices, or raster data.
+The ExecuteSQL() method does <b>not</b> get passed through to the underlying
+database.  For now it is interpreted by the limited OGR SQL handler.
 Spatial indexes are used to accelerate spatial queries.<p>
 
 The driver has been tested with ArcSDE 9.x, and should work with newer
 versions, as well as ArcSDE 8.2 or 8.3.  Both 2D and 3D geometries are
-supported.  Curve geometries are approximated as line strings (actually 
+supported.  Curve geometries are approximated as line strings (actually
 still TODO).<p>
-    
-ArcSDE is generally sensitive to case-specific, fully-qualified tablenames.  
-While you may be able to use short names for some operations, others (notably deleting) 
-will require a fully-qualified name.  Because of this fact, it is generally best 
+
+ArcSDE is generally sensitive to case-specific, fully-qualified tablenames.
+While you may be able to use short names for some operations, others (notably deleting)
+will require a fully-qualified name.  Because of this fact, it is generally best
 to <b>always</b> use fully-qualified table names. <p>
 
 <h3>Layer Creation Options</h3>
@@ -83,18 +83,18 @@ to <b>always</b> use fully-qualified table names. <p>
     </li>
     <li>
         <b>SDE_DESCRIPTION</b>: The text description of the layer.  Defaults to
-        "Created by GDAL/OGR 1.6"  (Also used as the version description when 
+        "Created by GDAL/OGR 1.6"  (Also used as the version description when
         creating a new child version from a parent version.)
     </li>
     <li>
-        <b>SDE_MULTIVERSION</b>: If this creation option is set is set to 
+        <b>SDE_MULTIVERSION</b>: If this creation option is set is set to
         "FALSE", multi-versioning will be disabled for the layer at creation
-        time.  By default, multiversion tables are created when layers are created 
+        time.  By default, multiversion tables are created when layers are created
         on an SDE datasource.
     </li>
     <li>
         <b>USE_NSTRING</b>: If this option is set to "TRUE" then string fields
-        will be created as type NSTRING.  This option was added for GDAL/OGR 
+        will be created as type NSTRING.  This option was added for GDAL/OGR
         1.9.0.
     </li>
 </ul>
@@ -103,29 +103,29 @@ to <b>always</b> use fully-qualified table names. <p>
 <h3>Environment variables</h3>
 
 <ul>
-<li><b>OGR_SDE_GETLAYERTYPE</b>: This may be "TRUE" to determine the 
-    geometry type from the database.  Otherwise, the SDE driver will always 
+<li><b>OGR_SDE_GETLAYERTYPE</b>: This may be "TRUE" to determine the
+    geometry type from the database.  Otherwise, the SDE driver will always
     return an Unknown geometry type.
 </li>
-<li><b>OGR_SDE_SEARCHORDER</b>: This may be "ATTRIBUTE_FIRST" to tell ArcSDE 
-    to filter based on attributes *before* using a spatial filter or 
-    "SPATIAL_FIRST" to use the spatial filter.  By default, it uses the 
+<li><b>OGR_SDE_SEARCHORDER</b>: This may be "ATTRIBUTE_FIRST" to tell ArcSDE
+    to filter based on attributes *before* using a spatial filter or
+    "SPATIAL_FIRST" to use the spatial filter.  By default, it uses the
     spatial filter first.
 </li>
 <li>
     <b>SDE_VERSIONOVERWRITE</b>: If set to "TRUE", the specified child
-    version will be deleted before being recreated.  Note that this action 
-    does nothing to reconsile any edits that existed on that version before 
+    version will be deleted before being recreated.  Note that this action
+    does nothing to reconcile any edits that existed on that version before
     doing so and essentially throws them away.
 </li>
 <li>
-    <b>OGR_SDE_USE_NSTRING</b>: If this option is set to "TRUE" then string 
-    fields will be created as type NSTRING.  This option was added for 
-    GDAL/OGR 1.9.0.  
+    <b>OGR_SDE_USE_NSTRING</b>: If this option is set to "TRUE" then string
+    fields will be created as type NSTRING.  This option was added for
+    GDAL/OGR 1.9.0.
 </li>
 
-<li> 
-   
+<li>
+
 
 </ul>
 
diff --git a/ogr/ogrsf_frmts/sde/ogr_sde.h b/ogr/ogrsf_frmts/sde/ogr_sde.h
index 3ed9746..2694a83 100644
--- a/ogr/ogrsf_frmts/sde/ogr_sde.h
+++ b/ogr/ogrsf_frmts/sde/ogr_sde.h
@@ -1,10 +1,10 @@
 /******************************************************************************
- * $Id: ogr_sde.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogr_sde.h 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR SDE driver.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
- * Copyright (c) 2008, Shawn Gervais <project10 at project10.net> 
+ * Copyright (c) 2008, Shawn Gervais <project10 at project10.net>
  * Copyright (c) 2008, Howard Butler <hobu.inc at gmail.com>
  *
  ******************************************************************************
@@ -29,8 +29,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_SDE_H_INCLUDED
-#define _OGR_SDE_H_INCLUDED
+#ifndef OGR_SDE_H_INCLUDED
+#define OGR_SDE_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 
@@ -62,18 +62,18 @@ class OGRSDELayer : public OGRLayer
 
     char               *pszOwnerName;
     char               *pszDbTableName;
-    
+
     int                 bUpdateAccess;
     int                 bVersioned;
     int                 bPreservePrecision;
-    
+
     CPLString           osAttributeFilter;
 
     int                 bQueryInstalled;
     int                 bQueryActive;
 
     SE_STREAM           hStream;
-    
+
     int                 bHaveLayerInfo;
     SE_LAYERINFO        hLayerInfo;
     SE_COORDREF         hCoordRef;
@@ -88,7 +88,7 @@ class OGRSDELayer : public OGRLayer
 
     int                 iShapeColumn;
 
-    int                 bUseNSTRING; 
+    int                 bUseNSTRING;
 
 
     char              **papszAllColumns;
@@ -115,7 +115,7 @@ class OGRSDELayer : public OGRLayer
 
     CPLString           osFIDColumnName;
     CPLString           osShapeColumnName;
-    
+
     int                 Initialize( const char *, const char *, const char * );
 
     virtual void        ResetReading();
@@ -124,26 +124,28 @@ class OGRSDELayer : public OGRLayer
     virtual OGRFeature *GetNextFeature();
     virtual OGRFeature *GetFeature( GIntBig nFeatureId );
     virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce );
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
     virtual GIntBig     GetFeatureCount( int bForce );
 
     virtual OGRErr      SetAttributeFilter( const char *pszQuery );
-    
+
     virtual OGRErr      CreateField( OGRFieldDefn *poFieldIn,
                                      int bApproxOK );
 
     virtual OGRErr      ISetFeature( OGRFeature *poFeature );
     virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
     virtual OGRErr      DeleteFeature( GIntBig nFID );
-    
+
     OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
-    
+
     virtual OGRSpatialReference *GetSpatialRef();
 
     virtual int         TestCapability( const char * );
-    
+
     // The following methods are not base class overrides
     //void                SetOptions( char ** );
-    
+
     void                SetFIDColType( LONG nType )
                                 { nFIDColumnType = nType; }
     void                SetPrecisionFlag( int bFlag )
@@ -161,11 +163,11 @@ class OGRSDEDataSource : public OGRDataSource
     int                 nLayers;
 
     char               *pszName;
-    
+
     int                 bDSUpdate;
     int                 bDSUseVersionEdits;
     int                 bDSVersionLocked;
-    
+
     SE_CONNECTION       hConnection;
     LONG                nState;
     LONG                nNextState;
@@ -176,22 +178,22 @@ class OGRSDEDataSource : public OGRDataSource
                         ~OGRSDEDataSource();
 
     int                 Open( const char *, int );
-    int                 OpenTable( const char *pszTableName, 
-                                   const char *pszFIDColumn, 
+    int                 OpenTable( const char *pszTableName,
+                                   const char *pszFIDColumn,
                                    const char *pszShapeColumn,
                                    LONG nFIDColumnType );
 
     const char          *GetName() { return pszName; }
     int                 GetLayerCount() { return nLayers; }
     OGRLayer            *GetLayer( int );
-    
+
     virtual OGRLayer    *ICreateLayer( const char *,
                                       OGRSpatialReference * = NULL,
                                       OGRwkbGeometryType = wkbUnknown,
                                       char ** = NULL );
-    
+
     virtual OGRErr      DeleteLayer( int );
-    
+
     int                 TestCapability( const char * );
 
     SE_CONNECTION       GetConnection() { return hConnection; }
@@ -202,9 +204,9 @@ class OGRSDEDataSource : public OGRDataSource
 
     OGRErr              ConvertOSRtoSDESpatRef( OGRSpatialReference *,
                                                 SE_COORDREF * );
-    int                 IsOpenForUpdate() { return bDSUpdate; } 
+    int                 IsOpenForUpdate() { return bDSUpdate; }
     int                 UseVersionEdits() { return bDSUseVersionEdits; }
-    
+
   protected:
     void                EnumerateSpatialTables();
     void                OpenSpatialTable( const char* pszTableName );
@@ -233,5 +235,3 @@ class OGRSDEDriver : public OGRSFDriver
 
 
 #endif /* ndef _OGR_PG_H_INCLUDED */
-
-
diff --git a/ogr/ogrsf_frmts/sde/ogrsdedatasource.cpp b/ogr/ogrsf_frmts/sde/ogrsdedatasource.cpp
index 42f2f60..72904de 100644
--- a/ogr/ogrsf_frmts/sde/ogrsdedatasource.cpp
+++ b/ogr/ogrsf_frmts/sde/ogrsdedatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsdedatasource.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogrsdedatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSDEDataSource class.
@@ -7,7 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
- * Copyright (c) 2008, Shawn Gervais <project10 at project10.net> 
+ * Copyright (c) 2008, Shawn Gervais <project10 at project10.net>
  * Copyright (c) 2008, Howard Butler <hobu.inc at gmail.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -34,7 +34,7 @@
 #include "cpl_string.h"
 #include "gdal.h"
 
-CPL_CVSID("$Id: ogrsdedatasource.cpp 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: ogrsdedatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                          OGRSDEDataSource()                           */
@@ -50,7 +50,7 @@ OGRSDEDataSource::OGRSDEDataSource()
     bDSVersionLocked = TRUE;
     bDSUpdate = FALSE;
     bDSUseVersionEdits = FALSE;
-    
+
     nState = SE_DEFAULT_STATE_ID;
     nNextState = -2;
     hConnection = NULL;
@@ -67,11 +67,11 @@ OGRSDEDataSource::~OGRSDEDataSource()
     int         i;
     LONG        nSDEErr;
     char       pszVersionName[SE_MAX_VERSION_LEN];
-    
-    
+
+
     // Commit our transactions if we were opened for update
     if (bDSUpdate && bDSUseVersionEdits && (nNextState != -2 && nState != SE_DEFAULT_STATE_ID )  ) {
-        CPLDebug("OGR_SDE", "Moving states from %ld to %ld", 
+        CPLDebug("OGR_SDE", "Moving states from %ld to %ld",
                  (long) nState, (long) nNextState);
 
         SE_connection_commit_transaction(hConnection);
@@ -84,12 +84,12 @@ OGRSDEDataSource::~OGRSDEDataSource()
         if( nSDEErr != SE_SUCCESS )
         {
             IssueSDEError( nSDEErr, "SE_versioninfo_get_name" );
-        }  
+        }
         nSDEErr = SE_version_free_lock(hConnection, pszVersionName);
         if( nSDEErr != SE_SUCCESS )
         {
             IssueSDEError( nSDEErr, "SE_version_free_lock" );
-        }  
+        }
         nSDEErr = SE_version_change_state(hConnection, hVersion, nNextState);
         if( nSDEErr != SE_SUCCESS )
         {
@@ -102,8 +102,7 @@ OGRSDEDataSource::~OGRSDEDataSource()
             IssueSDEError( nSDEErr, "SE_state_trim_tree" );
         }
 
-        bDSVersionLocked = TRUE;      
-
+        bDSVersionLocked = TRUE;
     }
 
     CPLFree( pszName );
@@ -113,73 +112,70 @@ OGRSDEDataSource::~OGRSDEDataSource()
 
     CPLFree( papoLayers );
 
-    if (hVersion != NULL) 
+    if (hVersion != NULL)
     {
-        SE_versioninfo_free(hVersion); 
-    }   
-    
+        SE_versioninfo_free(hVersion);
+    }
+
     if( hConnection != NULL )
     {
         SE_connection_free( hConnection );
     }
-
- 
-
 }
 
 /************************************************************************/
 /*                           IssueSDEError()                            */
 /************************************************************************/
 
-void OGRSDEDataSource::IssueSDEError( int nErrorCode, 
+void OGRSDEDataSource::IssueSDEError( int nErrorCode,
                                       const char *pszFunction )
 
 {
     char szErrorMsg[SE_MAX_MESSAGE_LENGTH+1];
     LONG nSDEErr;
     char pszVersionName[SE_MAX_VERSION_LEN];
-    
+
     if( pszFunction == NULL )
         pszFunction = "SDE";
-       
+
     if (bDSUpdate && bDSUseVersionEdits && !bDSVersionLocked) {
         // try to clean up our state/transaction mess if we can
         nSDEErr = SE_state_delete(hConnection, nNextState);
         if (nSDEErr && nSDEErr != SE_STATE_INUSE) {
             SE_error_get_string( nSDEErr, szErrorMsg );
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "SE_state_delete could not complete in IssueSDEError %d/%s", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "SE_state_delete could not complete in IssueSDEError %d/%s",
                       nErrorCode, szErrorMsg );
         }
         nSDEErr = SE_versioninfo_get_name(hVersion, pszVersionName);
         if( nSDEErr != SE_SUCCESS )
         {
             SE_error_get_string( nSDEErr, szErrorMsg );
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "SE_versioninfo_get_name could not complete in IssueSDEError %d/%s", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "SE_versioninfo_get_name could not complete in IssueSDEError %d/%s",
                       nErrorCode, szErrorMsg );
-        }  
+        }
         nSDEErr = SE_version_free_lock(hConnection, pszVersionName);
         if( nSDEErr != SE_SUCCESS )
         {
             SE_error_get_string( nSDEErr, szErrorMsg );
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "SE_version_free_lock could not complete in IssueSDEError %d/%s", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "SE_version_free_lock could not complete in IssueSDEError %d/%s",
                       nErrorCode, szErrorMsg );
-        }  
+        }
         nSDEErr = SE_connection_rollback_transaction(hConnection);
         if (nSDEErr) {
             SE_error_get_string( nSDEErr, szErrorMsg );
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "SE_connection_rollback_transaction could not complete in IssueSDEError %d/%s", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "SE_connection_rollback_transaction could not complete in IssueSDEError %d/%s",
                       nErrorCode, szErrorMsg );
         }
     }
     bDSVersionLocked = TRUE;
     SE_error_get_string( nErrorCode, szErrorMsg );
 
-    CPLError( CE_Failure, CPLE_AppDefined, 
-              "%s: %d/%s", 
+    CPLError( CE_Failure, CPLE_AppDefined,
+              "%s: %d/%s",
               pszFunction, nErrorCode, szErrorMsg );
 }
 
@@ -195,7 +191,7 @@ int OGRSDEDataSource::Open( const char * pszNewName, int bUpdate )
 /* -------------------------------------------------------------------- */
 /*      If we aren't prefixed with SDE: then ignore this datasource.    */
 /* -------------------------------------------------------------------- */
-    if( !EQUALN(pszNewName,"SDE:",4) )
+    if( !STARTS_WITH_CI(pszNewName, "SDE:") )
         return FALSE;
 
 /* -------------------------------------------------------------------- */
@@ -210,11 +206,11 @@ int OGRSDEDataSource::Open( const char * pszNewName, int bUpdate )
 
     if( CSLCount( papszTokens ) < 5 || CSLCount( papszTokens ) > 8 )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "SDE connect string had wrong number of arguments.\n"
                   "Expected 'SDE:server,instance,database,username,password,layer'\n"
 		          "The layer name value is optional.\n"
-                  "Got '%s'", 
+                  "Got '%s'",
                   pszNewName );
         return FALSE;
     }
@@ -225,9 +221,9 @@ int OGRSDEDataSource::Open( const char * pszNewName, int bUpdate )
     int 	nSDEErr;
     SE_ERROR    sSDEErrorInfo;
 
-    nSDEErr = SE_connection_create( papszTokens[0], 
-                                    papszTokens[1], 
-                                    papszTokens[2], 
+    nSDEErr = SE_connection_create( papszTokens[0],
+                                    papszTokens[1],
+                                    papszTokens[2],
                                     papszTokens[3],
                                     papszTokens[4],
                                     &sSDEErrorInfo, &hConnection );
@@ -238,9 +234,9 @@ int OGRSDEDataSource::Open( const char * pszNewName, int bUpdate )
         CSLDestroy( papszTokens );
         return FALSE;
     }
-    
+
     pszName = CPLStrdup( pszNewName );
-    
+
     bDSUpdate = bUpdate;
 
     // Use SDE Versioned edits by default
@@ -252,7 +248,7 @@ int OGRSDEDataSource::Open( const char * pszNewName, int bUpdate )
         bDSUseVersionEdits = FALSE;
     }
 
-    
+
 /* -------------------------------------------------------------------- */
 /*      Set unprotected concurrency policy, suitable for single         */
 /*      threaded access.                                                */
@@ -293,9 +289,9 @@ int OGRSDEDataSource::Open( const char * pszNewName, int bUpdate )
             // We've already set the error
             CSLDestroy( papszTokens );
             return FALSE;
-        }        
+        }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Fetch the specified version or use SDE.DEFAULT if none is       */
 /*      specified.                                                      */
@@ -312,12 +308,12 @@ int OGRSDEDataSource::Open( const char * pszNewName, int bUpdate )
             // We've already set the error
             CSLDestroy( papszTokens );
             return FALSE;
-        }        
+        }
     }
     else if ( CSLCount( papszTokens ) == 8 && *papszTokens[7] != '\0' )
     {
         // For user-specified version names, the input is not fully qualified
-        // We have to append the connection's username to the version name for 
+        // We have to append the connection's username to the version name for
         // SDE to be able to find it.
         char username[SE_MAX_OWNER_LEN];
         nSDEErr = SE_connection_get_user_name(hConnection, username);
@@ -330,7 +326,7 @@ int OGRSDEDataSource::Open( const char * pszNewName, int bUpdate )
 
         const char* pszVersionName= CPLSPrintf( "%s.%s", username, papszTokens[7]);
 
-        
+
         CPLDebug("OGR_SDE", "Setting version to %s", pszVersionName);
         CPLDebug("OGR_SDE", "Opening layer %s", papszTokens[5]);
         OpenSpatialTable( papszTokens[5] );
@@ -340,8 +336,7 @@ int OGRSDEDataSource::Open( const char * pszNewName, int bUpdate )
             // We've already set the error
             CSLDestroy( papszTokens );
             return FALSE;
-        }        
-        
+        }
     }
 
     else
@@ -354,11 +349,10 @@ int OGRSDEDataSource::Open( const char * pszNewName, int bUpdate )
             // We've already set the error
             CSLDestroy( papszTokens );
             return FALSE;
-        }        
-
+        }
     }
     CSLDestroy( papszTokens );
- 
+
     return TRUE;
 }
 
@@ -370,7 +364,7 @@ int OGRSDEDataSource::CreateVersion( const char* pszParentVersion, const char* p
     SE_VERSIONINFO hParentVersion = NULL;
     SE_VERSIONINFO hChildVersion = NULL;
     SE_VERSIONINFO hDummyVersion = NULL;
-    
+
     LONG nSDEErr;
     nSDEErr = SE_versioninfo_create(&hParentVersion);
     if( nSDEErr != SE_SUCCESS )
@@ -389,7 +383,7 @@ int OGRSDEDataSource::CreateVersion( const char* pszParentVersion, const char* p
     const char* pszOverwriteVersion =  CPLGetConfigOption( "SDE_VERSIONOVERWRITE", "FALSE" );
     if( EQUAL(pszOverwriteVersion, "TRUE") && bDSUpdate ) {
         nSDEErr = SE_version_delete(hConnection, pszChildVersion);
-        
+
         // if the version didn't exist in the first place, just continue on.
         if( nSDEErr != SE_SUCCESS && nSDEErr != SE_VERSION_NOEXIST)
         {
@@ -401,29 +395,30 @@ int OGRSDEDataSource::CreateVersion( const char* pszParentVersion, const char* p
     // Attempt to use the child version if it is there.
     nSDEErr = SE_version_get_info(hConnection, pszChildVersion, hChildVersion);
     if( nSDEErr != SE_SUCCESS)
-    {   
+    {
         if (nSDEErr != SE_VERSION_NOEXIST) {
             IssueSDEError( nSDEErr, "SE_version_get_info child" );
             return FALSE;
-        } 
-    } else { 
+        }
+    } else {
         SE_versioninfo_free(hParentVersion);
         SE_versioninfo_free(hChildVersion);
-        return TRUE; 
+        return TRUE;
     }
 
     if (!bDSUpdate) {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "The version %s does not exist and cannot be created because the datasource is not in update mode", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "The version %s does not exist and cannot be created "
+                  "because the datasource is not in update mode",
                   pszChildVersion);
         return FALSE;
     }
-    
+
     nSDEErr = SE_version_get_info(hConnection, pszParentVersion, hParentVersion);
     if( nSDEErr != SE_SUCCESS )
     {
-        // this usually denotes incongruent versions of the client 
-        // and server.  If this is the case, we're going to attempt to 
+        // This usually denotes incongruent versions of the client
+        // and server.  If this is the case, we're going to attempt to
         // not do versioned queries at all.
         if ( nSDEErr == SE_INVALID_RELEASE ) {
             CPLDebug("OGR_SDE", "nState was set to SE_INVALID_RELEASE\n\n\n");
@@ -431,15 +426,15 @@ int OGRSDEDataSource::CreateVersion( const char* pszParentVersion, const char* p
             SE_versioninfo_free(hParentVersion);
             hParentVersion = NULL;
             IssueSDEError( nSDEErr, "SE_INVALID_RELEASE."
-                           "  Your client/server versions must not match or " 
+                           "  Your client/server versions must not match or "
                            "you have some other major configuration problem");
             return FALSE;
-            
+
         } else {
             IssueSDEError( nSDEErr, "SE_version_get_info parent" );
             return FALSE;
         }
-    } 
+    }
 
     // Fill in details of our child version from our parent version
     nSDEErr = SE_versioninfo_set_name(hChildVersion, pszChildVersion);
@@ -449,14 +444,14 @@ int OGRSDEDataSource::CreateVersion( const char* pszParentVersion, const char* p
                                 "Version names must be in the form \"MYVERSION\""
                                 "not \"SDE.MYVERSION\"" );
         return FALSE;
-    }    
+    }
 
     nSDEErr = SE_versioninfo_set_access(hChildVersion, SE_VERSION_ACCESS_PUBLIC);
     if( nSDEErr != SE_SUCCESS )
     {
         IssueSDEError( nSDEErr, "SE_versioninfo_set_access" );
         return FALSE;
-    }    
+    }
 
     const char* pszDescription =  CPLGetConfigOption( "SDE_DESCRIPTION", "Created by OGR" );
     nSDEErr = SE_versioninfo_set_description(hChildVersion, pszDescription);
@@ -464,7 +459,7 @@ int OGRSDEDataSource::CreateVersion( const char* pszParentVersion, const char* p
     {
         IssueSDEError( nSDEErr, "SE_versioninfo_set_description" );
         return FALSE;
-    }    
+    }
 
     nSDEErr = SE_versioninfo_set_parent_name(hChildVersion, pszParentVersion);
     if( nSDEErr != SE_SUCCESS )
@@ -472,7 +467,7 @@ int OGRSDEDataSource::CreateVersion( const char* pszParentVersion, const char* p
         IssueSDEError( nSDEErr, "SE_versioninfo_set_parent_name" );
         return FALSE;
     }
-    
+
     LONG nStateID;
     nSDEErr = SE_versioninfo_get_state_id(hParentVersion, &nStateID);
     if( nSDEErr != SE_SUCCESS )
@@ -499,11 +494,11 @@ int OGRSDEDataSource::CreateVersion( const char* pszParentVersion, const char* p
         IssueSDEError( nSDEErr, "SE_version_create" );
         return FALSE;
     }
-    
+
     SE_versioninfo_free(hParentVersion);
     SE_versioninfo_free(hChildVersion);
     SE_versioninfo_free(hDummyVersion);
-    
+
     return TRUE;
 }
 
@@ -514,7 +509,7 @@ int OGRSDEDataSource::SetVersionState( const char* pszVersionName ) {
 
     int nSDEErr;
     SE_STATEINFO hCurrentStateInfo= NULL;
-    SE_STATEINFO hNextStateInfo= NULL;    
+    SE_STATEINFO hNextStateInfo= NULL;
     SE_STATEINFO hDummyStateInfo = NULL;
 
     nSDEErr = SE_versioninfo_create(&hVersion);
@@ -526,8 +521,8 @@ int OGRSDEDataSource::SetVersionState( const char* pszVersionName ) {
     nSDEErr = SE_version_get_info(hConnection, pszVersionName, hVersion);
     if( nSDEErr != SE_SUCCESS )
     {
-        // this usually denotes incongruent versions of the client 
-        // and server.  If this is the case, we're going to attempt to 
+        // This usually denotes incongruent versions of the client
+        // and server.  If this is the case, we're going to attempt to
         // not do versioned queries at all.
         if ( nSDEErr == SE_INVALID_RELEASE ) {
             CPLDebug("OGR_SDE", "nState was set to SE_INVALID_RELEASE\n\n\n");
@@ -535,16 +530,15 @@ int OGRSDEDataSource::SetVersionState( const char* pszVersionName ) {
             SE_versioninfo_free(hVersion);
             hVersion = NULL;
             IssueSDEError( nSDEErr, "SE_INVALID_RELEASE."
-                           "  Your client/server versions must not match or " 
+                           "  Your client/server versions must not match or "
                            "you have some other major configuration problem");
             return FALSE;
-            
         } else {
             IssueSDEError( nSDEErr, "SE_version_get_info" );
             return FALSE;
         }
-    } 
-    
+    }
+
     nSDEErr = SE_versioninfo_get_state_id(hVersion, &nState);
     if( nSDEErr != SE_SUCCESS )
     {
@@ -552,54 +546,52 @@ int OGRSDEDataSource::SetVersionState( const char* pszVersionName ) {
         return FALSE;
     }
 
-
-    
     if (bDSUpdate && bDSUseVersionEdits) {
         LONG nLockCount = 0;
         SE_VERSION_LOCK* pahLocks = NULL;
         nSDEErr = SE_version_get_locks(hConnection, pszVersionName, &nLockCount, &pahLocks);
-    
+
         if( nSDEErr != SE_SUCCESS )
         {
             IssueSDEError( nSDEErr, "SE_version_get_locks" );
             return FALSE;
         }
-    
-        if (nLockCount > 0) 
+
+        if (nLockCount > 0)
         {
-            // This version is already locked for edit.  We can't edit this 
+            // This version is already locked for edit.  We can't edit this
             // version right now until the lock is released.  All we can do is issue
             // an error.
 
             SE_version_free_locks(pahLocks, nLockCount);
             bDSVersionLocked = TRUE;
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "The %s version is already locked and open for edit", pszVersionName);            
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "The %s version is already locked and open for edit", pszVersionName);
             return FALSE;
         }
 
-        // So we're in update mode.  We need to get the state id 
-        // of the active version, create a child state of it to 
-        // push our edits onto, and close the state and move the 
-        // version to it when we're done. 
+        // So we're in update mode.  We need to get the state id
+        // of the active version, create a child state of it to
+        // push our edits onto, and close the state and move the
+        // version to it when we're done.
 
         nSDEErr = SE_connection_start_transaction(hConnection);
         if( nSDEErr != SE_SUCCESS )
         {
             IssueSDEError( nSDEErr, "SE_connection_start_transaction" );
             return FALSE;
-        } 
-        
-        // Lock the version we're editing on so no one can change the state 
+        }
+
+        // Lock the version we're editing on so no one can change the state
         // of it underneath us.  SHARED_LOCK is the same lock mode that ArcGIS uses,
-        // and it means the state of the version cannot be moved until until we 
+        // and it means the state of the version cannot be moved until until we
         // release the lock and move it.
         nSDEErr = SE_version_lock(hConnection, pszVersionName, SE_VERSION_SHARED_LOCK);
         if( nSDEErr != SE_SUCCESS )
         {
             IssueSDEError( nSDEErr, "SE_version_lock" );
             return FALSE;
-        } 
+        }
         nSDEErr = SE_stateinfo_create(&hCurrentStateInfo);
         if( nSDEErr != SE_SUCCESS )
         {
@@ -613,10 +605,10 @@ int OGRSDEDataSource::SetVersionState( const char* pszVersionName ) {
             return FALSE;
         }
         if (SE_stateinfo_is_open(hCurrentStateInfo)) {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "The editing state for this version is currently open.  "
                           "It must be closed for edits before it can be opened by OGR for update. ");
-                return FALSE;            
+                return FALSE;
         }
         nSDEErr = SE_stateinfo_create(&hNextStateInfo);
         if( nSDEErr != SE_SUCCESS )
@@ -624,7 +616,7 @@ int OGRSDEDataSource::SetVersionState( const char* pszVersionName ) {
             IssueSDEError( nSDEErr, "SE_stateinfo_create" );
             return FALSE;
         }
-        
+
         nSDEErr = SE_stateinfo_create(&hDummyStateInfo);
         if( nSDEErr != SE_SUCCESS )
         {
@@ -655,7 +647,7 @@ int OGRSDEDataSource::SetVersionState( const char* pszVersionName ) {
         SE_stateinfo_free(hNextStateInfo);
 
     }
-    return TRUE; 
+    return TRUE;
 
 
 }
@@ -663,7 +655,7 @@ int OGRSDEDataSource::SetVersionState( const char* pszVersionName ) {
 /*                             OpenTable()                              */
 /************************************************************************/
 
-int OGRSDEDataSource::OpenTable( const char *pszTableName, 
+int OGRSDEDataSource::OpenTable( const char *pszTableName,
                                  const char *pszFIDColumn,
                                  const char *pszShapeColumn,
                                  LONG nFIDColType )
@@ -681,7 +673,7 @@ int OGRSDEDataSource::OpenTable( const char *pszTableName,
         delete poLayer;
         return FALSE;
     }
-    
+
     poLayer->SetFIDColType( nFIDColType );
 
 /* -------------------------------------------------------------------- */
@@ -703,25 +695,24 @@ OGRErr OGRSDEDataSource::DeleteLayer( int iLayer )
 {
     if( iLayer < 0 || iLayer >= nLayers )
         return OGRERR_FAILURE;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Blow away our OGR structures related to the layer.  This is     */
 /*      pretty dangerous if anything has a reference to this layer!     */
 /* -------------------------------------------------------------------- */
-    
-    
+
     OGRSDELayer* poLayer = (OGRSDELayer*) papoLayers[iLayer];
-    
+
     CPLString osGeometryName = poLayer->osShapeColumnName;
     CPLString osLayerName = poLayer->GetLayerDefn()->GetName();
-    
-    CPLDebug( "OGR_SDE", 
-              "DeleteLayer(%s,%s)", 
+
+    CPLDebug( "OGR_SDE",
+              "DeleteLayer(%s,%s)",
               osLayerName.c_str(),
               osGeometryName.c_str() );
 
     delete papoLayers[iLayer];
-    memmove( papoLayers + iLayer, papoLayers + iLayer + 1, 
+    memmove( papoLayers + iLayer, papoLayers + iLayer + 1,
              sizeof(void *) * (nLayers - iLayer - 1) );
     nLayers--;
 
@@ -732,7 +723,7 @@ OGRErr OGRSDEDataSource::DeleteLayer( int iLayer )
     char** paszTables;
     LONG nCount;
     char pszVersionName[SE_MAX_VERSION_LEN];
-    
+
     nSDEErr = SE_layer_delete( hConnection, osLayerName.c_str(), osGeometryName.c_str());
     if( nSDEErr != SE_SUCCESS )
     {
@@ -750,10 +741,10 @@ OGRErr OGRSDEDataSource::DeleteLayer( int iLayer )
     for (int i=0; i<nCount; i++) {
         CPLDebug("OGR_SDE", "Dependent multiversion table: %s", paszTables[i]);
     }
-    
-    // if we still have dependent tables after deleting the layer, it is because the 
-    // table is multiversion.  We need to smash the table to single version before 
-    // deleting its registration.  If the user deletes the table from this version, 
+
+    // if we still have dependent tables after deleting the layer, it is because the
+    // table is multiversion.  We need to smash the table to single version before
+    // deleting its registration.  If the user deletes the table from this version,
     // all other versions are gone too.
     if (nCount) {
         nSDEErr = SE_versioninfo_get_name(hVersion, pszVersionName);
@@ -761,7 +752,7 @@ OGRErr OGRSDEDataSource::DeleteLayer( int iLayer )
         {
             IssueSDEError( nSDEErr, "SE_versioninfo_get_name" );
             return OGRERR_FAILURE;
-        }        
+        }
         nSDEErr = SE_registration_make_single_version(hConnection, pszVersionName, osLayerName.c_str());
         if( nSDEErr != SE_SUCCESS )
         {
@@ -778,15 +769,15 @@ OGRErr OGRSDEDataSource::DeleteLayer( int iLayer )
         IssueSDEError( nSDEErr, "SE_registration_delete" );
         return OGRERR_FAILURE;
     }
-    
+
     nSDEErr = SE_table_delete( hConnection, osLayerName.c_str() );
-    
+
     if( nSDEErr != SE_SUCCESS )
     {
         IssueSDEError( nSDEErr, "SE_table_delete" );
         return OGRERR_FAILURE;
     }
-    
+
     CPLDebug( "OGR_SDE", "DeleteLayer(%s) successful", osLayerName.c_str() );
 
     return OGRERR_NONE;
@@ -798,7 +789,7 @@ OGRErr OGRSDEDataSource::DeleteLayer( int iLayer )
 /************************************************************************/
 void OGRSDEDataSource::CleanupLayerCreation(const char* pszLayerName)
 {
-    
+
     LONG nSDEErr;
 
 
@@ -807,14 +798,14 @@ void OGRSDEDataSource::CleanupLayerCreation(const char* pszLayerName)
     {
         IssueSDEError( nSDEErr, "SE_registration_delete" );
     }
-    
+
     nSDEErr = SE_table_delete( hConnection, pszLayerName);
-    
+
     if( nSDEErr != SE_SUCCESS )
     {
         IssueSDEError( nSDEErr, "SE_table_delete" );
     }
-    
+
     CPLDebug( "OGR_SDE", "CleanupLayerCreation(%s) successful", pszLayerName );
 
 }
@@ -845,10 +836,10 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
     for( iLayer = 0; iLayer < nLayers; iLayer++ )
     {
         // We look for an exact match or for SDE.layername which is how
-        // the layer will be known after reading back. 
+        // the layer will be known after reading back.
         if( EQUAL(osFullName,
                   papoLayers[iLayer]->GetLayerDefn()->GetName())
-            || EQUAL(pszLayerName, 
+            || EQUAL(pszLayerName,
                      papoLayers[iLayer]->GetLayerDefn()->GetName()) )
         {
             if( CSLFetchBoolean( papszOptions, "OVERWRITE", FALSE ) )
@@ -857,7 +848,7 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
             }
             else
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "Layer %s already exists, CreateLayer failed.\n"
                           "Use the layer creation option OVERWRITE=YES to "
                           "replace it.",
@@ -889,15 +880,18 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
         szTableName[0] = '\0';
 
         SE_reginfo_get_table_name( ahTableList[iTable], szTableName );
-        if( EQUAL(szTableName,pszLayerName) 
+        if( EQUAL(szTableName,pszLayerName)
             || EQUAL(szTableName,osFullName) )
         {
             if( !CSLFetchBoolean( papszOptions, "OVERWRITE", FALSE ) )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                          "Registration informatin for  %s already exists, CreateLayer failed.\n"
-                          "Use the layer creation option OVERWRITE=YES to pre-clear it.",
-                          pszLayerName );
+                CPLError(
+                    CE_Failure, CPLE_AppDefined,
+                    "Registration information for  %s already exists, "
+                    "CreateLayer failed.\n"
+                    "Use the layer creation option OVERWRITE=YES to "
+                    "pre-clear it.",
+                    pszLayerName );
                 return NULL;
             }
 
@@ -925,24 +919,24 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
     if( pszGeometryName == NULL )
         pszGeometryName = "SHAPE";
 
-    
+
     pszExpectedFIDName = CPLGetConfigOption( "SDE_FID", "OBJECTID" );
 
     pszDbtuneKeyword = CSLFetchNameValue( papszOptions, "SDE_KEYWORD" );
     if( pszDbtuneKeyword == NULL )
         pszDbtuneKeyword = "DEFAULTS";
-    
+
     // Set layer description
     pszLayerDescription = CSLFetchNameValue( papszOptions, "SDE_DESCRIPTION" );
     if( pszLayerDescription == NULL )
-        pszLayerDescription = CPLSPrintf( "Created by GDAL/OGR %s", 
+        pszLayerDescription = CPLSPrintf( "Created by GDAL/OGR %s",
                                       GDALVersionInfo( "RELEASE_NAME" ) );
 
 /* -------------------------------------------------------------------- */
 /*      Create a basic table with the FID column                        */
 /* -------------------------------------------------------------------- */
     SE_COLUMN_DEF       sColumnDef;
- 
+
     /*
      * Setting the size and decimal_digits to 0 instructs SDE to
      * use default values for the SE_INTEGER_TYPE - these might be specific
@@ -953,10 +947,10 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
     sColumnDef.size           = 0;
     sColumnDef.decimal_digits = 0;
     sColumnDef.nulls_allowed  = FALSE;
-    
-    nSDEErr = SE_table_create( hConnection, pszLayerName, 1, &sColumnDef, 
+
+    nSDEErr = SE_table_create( hConnection, pszLayerName, 1, &sColumnDef,
                                pszDbtuneKeyword );
-    
+
     if( nSDEErr != SE_SUCCESS )
     {
         IssueSDEError( nSDEErr, "SE_table_create" );
@@ -968,7 +962,7 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
 /*      Convert the OGRSpatialReference to a SDE coordref object        */
 /* -------------------------------------------------------------------- */
     SE_COORDREF         hCoordRef;
-    
+
     if( ConvertOSRtoSDESpatRef( poSRS, &hCoordRef ) != OGRERR_NONE )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -987,7 +981,7 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
     SE_LAYERINFO        hLayerInfo;
     SE_ENVELOPE         sLayerEnvelope;
     LONG                nLayerShapeTypes = 0L;
-    
+
     nSDEErr = SE_layerinfo_create( hCoordRef, &hLayerInfo );
     if( nSDEErr != SE_SUCCESS )
     {
@@ -995,13 +989,13 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
         CleanupLayerCreation(pszLayerName);
         return NULL;
     }
-    
+
     // Determine the type of geometries that this layer will allow
     nLayerShapeTypes |= SE_NIL_TYPE_MASK;
-    
+
     if( wkbFlatten(eType) == wkbPoint || wkbFlatten(eType) == wkbMultiPoint )
         nLayerShapeTypes |= SE_POINT_TYPE_MASK;
-    
+
     else if( wkbFlatten(eType) == wkbLineString
              || wkbFlatten(eType) == wkbMultiLineString )
         nLayerShapeTypes |= ( SE_LINE_TYPE_MASK | SE_SIMPLE_LINE_TYPE_MASK );
@@ -1018,7 +1012,7 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
     else if( eType == wkbUnknown )
     {
         nLayerShapeTypes |= (  SE_POINT_TYPE_MASK
-                             | SE_LINE_TYPE_MASK 
+                             | SE_LINE_TYPE_MASK
                              | SE_SIMPLE_LINE_TYPE_MASK
                              | SE_AREA_TYPE_MASK );
         CPLError( CE_Warning, CPLE_AppDefined,
@@ -1026,18 +1020,18 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
                   "result in layers which are not displayable in Arc* "
                   "software" );
     }
-    
+
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Cannot create SDE layer %s with geometry type %d.",
                    pszLayerName, eType );
-        
+
         SE_layerinfo_free( hLayerInfo );
         CleanupLayerCreation(pszLayerName);
         return NULL;
     }
-    
+
     nSDEErr = SE_layerinfo_set_shape_types( hLayerInfo, nLayerShapeTypes );
     if( nSDEErr != SE_SUCCESS )
     {
@@ -1046,8 +1040,8 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
         CleanupLayerCreation(pszLayerName);
         return NULL;
     }
-    
-    
+
+
     // Set geometry column name
     nSDEErr = SE_layerinfo_set_spatial_column( hLayerInfo, pszLayerName,
                                                pszGeometryName );
@@ -1058,7 +1052,7 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
         CleanupLayerCreation(pszLayerName);
         return NULL;
     }
-    
+
     // Set creation keyword
     nSDEErr = SE_layerinfo_set_creation_keyword( hLayerInfo, pszDbtuneKeyword );
     if( nSDEErr != SE_SUCCESS )
@@ -1068,7 +1062,7 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
         CleanupLayerCreation(pszLayerName);
         return NULL;
     }
-    
+
     // Set layer extent based on coordinate system envelope
     if( poSRS != NULL && poSRS->IsGeographic() )
     {
@@ -1103,7 +1097,7 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
         return NULL;
     }
 
-    
+
     nSDEErr = SE_layerinfo_set_description( hLayerInfo, pszLayerDescription );
     if( nSDEErr != SE_SUCCESS )
     {
@@ -1112,8 +1106,8 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
         CleanupLayerCreation(pszLayerName);
         return NULL;
     }
-    
-    
+
+
     // Set grid size
     nSDEErr = SE_layerinfo_set_grid_sizes( hLayerInfo,
                                            OGR_SDE_LAYER_CO_GRID1,
@@ -1126,8 +1120,7 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
         CleanupLayerCreation(pszLayerName);
         return NULL;
     }
-    
-    
+
     // Set layer coordinate reference
     nSDEErr = SE_layerinfo_set_coordref( hLayerInfo, hCoordRef );
     if( nSDEErr != SE_SUCCESS )
@@ -1137,8 +1130,7 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
         CleanupLayerCreation(pszLayerName);
         return NULL;
     }
-    
-    
+
 /* -------------------------------------------------------------------- */
 /*      Spatially enable the newly created table                        */
 /* -------------------------------------------------------------------- */
@@ -1147,7 +1139,7 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
                                OGR_SDE_LAYER_CO_AVG_PTS );
 
     SE_layerinfo_free( hLayerInfo );
-    
+
     if( nSDEErr != SE_SUCCESS )
     {
         IssueSDEError( nSDEErr, "SE_layer_create" );
@@ -1160,7 +1152,7 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
     char                szQualifiedTable[SE_QUALIFIED_TABLE_NAME];
     SE_REGINFO          hRegInfo;
-    
+
     nSDEErr = SE_reginfo_create( &hRegInfo );
     if( nSDEErr != SE_SUCCESS )
     {
@@ -1168,7 +1160,7 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
         CleanupLayerCreation(pszLayerName);
         return NULL;
     }
-    
+
     nSDEErr = SE_registration_get_info( hConnection, pszLayerName,
                                         hRegInfo );
     if( nSDEErr != SE_SUCCESS )
@@ -1178,7 +1170,7 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
         CleanupLayerCreation(pszLayerName);
         return NULL;
     }
-    
+
     nSDEErr = SE_reginfo_set_creation_keyword( hRegInfo, pszDbtuneKeyword );
     if( nSDEErr != SE_SUCCESS )
     {
@@ -1197,7 +1189,7 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
         CleanupLayerCreation(pszLayerName);
         return NULL;
     }
-    
+
     /*
      * If the layer creation option 'MULTIVERSION' is set, enable
      * multi-versioning for this layer
@@ -1214,7 +1206,7 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
             return NULL;
         }
     }
-    
+
     nSDEErr = SE_registration_alter( hConnection, hRegInfo );
     if( nSDEErr != SE_SUCCESS )
     {
@@ -1223,7 +1215,7 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
         CleanupLayerCreation(pszLayerName);
         return NULL;
     }
-    
+
     nSDEErr = SE_reginfo_get_table_name( hRegInfo, szQualifiedTable );
     if( nSDEErr != SE_SUCCESS )
     {
@@ -1235,15 +1227,14 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
 
     SE_reginfo_free( hRegInfo );
     SE_coordref_free( hCoordRef );
-    
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create the layer object.                                        */
 /* -------------------------------------------------------------------- */
     OGRSDELayer *poLayer;
 
     poLayer = new OGRSDELayer( this, bDSUpdate );
-    
+
     if( !poLayer->Initialize( szQualifiedTable, pszExpectedFIDName,
                               pszGeometryName) )
     {
@@ -1260,7 +1251,7 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
     poLayer->SetFIDColType( SE_REGISTRATION_ROW_ID_COLUMN_TYPE_SDE );
 
-    poLayer->SetUseNSTRING( 
+    poLayer->SetUseNSTRING(
         CSLFetchBoolean( papszOptions, "USE_NSTRING", FALSE ) );
 
 /* -------------------------------------------------------------------- */
@@ -1268,7 +1259,7 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
     papoLayers = (OGRSDELayer **)
         CPLRealloc( papoLayers,  sizeof(OGRSDELayer *) * (nLayers+1) );
-    
+
     papoLayers[nLayers++] = poLayer;
 
     return poLayer;
@@ -1322,8 +1313,8 @@ void OGRSDEDataSource::EnumerateSpatialTables()
         return;
     }
 
-    CPLDebug( "OGR_SDE", 
-              "SDE::EnumerateSpatialTables() found %d tables.", 
+    CPLDebug( "OGR_SDE",
+              "SDE::EnumerateSpatialTables() found %d tables.",
               (int) nTableListCount );
 
 /* -------------------------------------------------------------------- */
@@ -1383,17 +1374,17 @@ void OGRSDEDataSource::CreateLayerFromRegInfo( SE_REGINFO& reginfo )
     nSDEErr = SE_reginfo_get_table_name( reginfo, szTableName );
     if( nSDEErr != SE_SUCCESS )
     {
-        CPLDebug( "SDE", 
+        CPLDebug( "SDE",
                   "Ignoring reginfo '%p', no table name.",
                   reginfo );
         return;
     }
 
-    // Ignore non-spatial, or hidden tables. 
+    // Ignore non-spatial, or hidden tables.
     if( !SE_reginfo_has_layer( reginfo ) || SE_reginfo_is_hidden( reginfo ) )
     {
-        CPLDebug( "SDE", 
-                  "Ignoring layer '%s' as it is hidden or does not have a reginfo layer.", 
+        CPLDebug( "SDE",
+                  "Ignoring layer '%s' as it is hidden or does not have a reginfo layer.",
                   szTableName );
         return;
     }
@@ -1405,7 +1396,7 @@ void OGRSDEDataSource::CreateLayerFromRegInfo( SE_REGINFO& reginfo )
     if( nFIDColType == SE_REGISTRATION_ROW_ID_COLUMN_TYPE_NONE
         || strlen(szIDColName) == 0 )
     {
-        CPLDebug( "OGR_SDE", "Unable to determine FID column for %s.", 
+        CPLDebug( "OGR_SDE", "Unable to determine FID column for %s.",
                   szTableName );
         OpenTable( szTableName, NULL, NULL, nFIDColType );
     }
@@ -1422,33 +1413,32 @@ OGRErr OGRSDEDataSource::ConvertOSRtoSDESpatRef( OGRSpatialReference *poSRS,
 {
     OGRSpatialReference  *poESRISRS;
     char                 *pszWkt;
-    
+
     if( SE_coordref_create( psCoordRef ) != SE_SUCCESS )
         return OGRERR_FAILURE;
-    
+
     // Construct a generic SE_COORDREF if poSRS is NULL
     if( poSRS == NULL )
     {
         SE_ENVELOPE     sGenericEnvelope;
-        
+
         sGenericEnvelope.minx = -1000000;
         sGenericEnvelope.miny = -1000000;
         sGenericEnvelope.maxx =  1000000;
         sGenericEnvelope.maxy =  1000000;
-        
+
         if( SE_coordref_set_xy_by_envelope( *psCoordRef, &sGenericEnvelope )
                 != SE_SUCCESS )
         {
             SE_coordref_free( *psCoordRef );
             return OGRERR_FAILURE;
         }
-        
+
         return OGRERR_NONE;
     }
 
-    
     poESRISRS = poSRS->Clone();
-    
+
     if (poSRS->IsLocal()) {
         CPLDebug("OGR_SDE", "Coordinate reference was local, using UNKNOWN for ESRI SRS description");
         if( SE_coordref_set_by_description( *psCoordRef, "UNKNOWN") != SE_SUCCESS )
@@ -1456,31 +1446,31 @@ OGRErr OGRSDEDataSource::ConvertOSRtoSDESpatRef( OGRSpatialReference *poSRS,
         CPLFree(pszWkt);
         return OGRERR_NONE;
     }
-    
+
     if( poESRISRS->morphToESRI() != OGRERR_NONE )
     {
         SE_coordref_free( *psCoordRef );
         delete poESRISRS;
         return OGRERR_FAILURE;
     }
-    
+
     if( poESRISRS->exportToWkt( &pszWkt ) != OGRERR_NONE )
     {
         SE_coordref_free( *psCoordRef );
         delete poESRISRS;
         return OGRERR_FAILURE;
     }
-    
+
     delete poESRISRS;
-    
+
     if( SE_coordref_set_by_description( *psCoordRef, pszWkt ) != SE_SUCCESS )
         return OGRERR_FAILURE;
-    
+
     {
         SE_ENVELOPE     sGenericEnvelope;
         SE_coordref_get_xy_envelope( *psCoordRef, &sGenericEnvelope );
 
-        CPLDebug( "SDE", 
+        CPLDebug( "SDE",
                   "Created coordref '%s' with envelope (%g,%g) to (%g,%g)",
                   pszWkt,
                   sGenericEnvelope.minx,
@@ -1494,10 +1484,10 @@ OGRErr OGRSDEDataSource::ConvertOSRtoSDESpatRef( OGRSpatialReference *poSRS,
         LONG nSDEErr;
 
         // Reset the offset and precision to match the ordinary values
-        // for SDE geographic coordinate systems. 
+        // for SDE geographic coordinate systems.
         nSDEErr = SE_coordref_set_xy( *psCoordRef, -400, -400, 1.11195e9 );
 
-        if( nSDEErr != SE_SUCCESS ) 
+        if( nSDEErr != SE_SUCCESS )
         {
             IssueSDEError( nSDEErr, "SE_coordref_set_xy()" );
         }
diff --git a/ogr/ogrsf_frmts/sde/ogrsdedriver.cpp b/ogr/ogrsf_frmts/sde/ogrsdedriver.cpp
index b679553..e90f605 100644
--- a/ogr/ogrsf_frmts/sde/ogrsdedriver.cpp
+++ b/ogr/ogrsf_frmts/sde/ogrsdedriver.cpp
@@ -1,10 +1,10 @@
 /******************************************************************************
- * $Id: ogrsdedriver.cpp 14165 2008-03-31 17:50:47Z rouault $
+ * $Id: ogrsdedriver.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSDEDriver class.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
- * Copyright (c) 2008, Shawn Gervais <project10 at project10.net> 
+ * Copyright (c) 2008, Shawn Gervais <project10 at project10.net>
  * Copyright (c) 2008, Howard Butler <hobu.inc at gmail.com>
  *
  ******************************************************************************
@@ -32,7 +32,7 @@
 #include "ogr_sde.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrsdedriver.cpp 14165 2008-03-31 17:50:47Z rouault $");
+CPL_CVSID("$Id: ogrsdedriver.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                            ~OGRSDEDriver()                            */
@@ -59,7 +59,7 @@ const char *OGRSDEDriver::GetName()
 
 OGRDataSource *OGRSDEDriver::Open( const char * pszFilename,
                                    int bUpdate )
-    
+
 {
     OGRSDEDataSource     *poDS;
 
@@ -80,7 +80,7 @@ OGRDataSource *OGRSDEDriver::Open( const char * pszFilename,
 
 OGRDataSource *OGRSDEDriver::CreateDataSource( const char * pszName,
                                                char **papszOptions)
-    
+
 {
     OGRSDEDataSource     *poDS;
 
@@ -110,7 +110,7 @@ int OGRSDEDriver::TestCapability( const char * pszCap )
         return true;
     if( EQUAL(pszCap, ODrCCreateDataSource) )
         return TRUE;
-      
+
     return FALSE;
 }
 
@@ -121,8 +121,8 @@ int OGRSDEDriver::TestCapability( const char * pszCap )
 void RegisterOGRSDE()
 
 {
-    if (! GDAL_CHECK_VERSION("OGR SDE"))
+    if( !GDAL_CHECK_VERSION("OGR SDE") )
         return;
+
     OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( new OGRSDEDriver );
 }
-
diff --git a/ogr/ogrsf_frmts/sde/ogrsdelayer.cpp b/ogr/ogrsf_frmts/sde/ogrsdelayer.cpp
index 1ae7016..7a3e79b 100644
--- a/ogr/ogrsf_frmts/sde/ogrsdelayer.cpp
+++ b/ogr/ogrsf_frmts/sde/ogrsdelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsdelayer.cpp 28831 2015-04-01 16:46:05Z rouault $
+ * $Id: ogrsdelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSDELayer class.
@@ -7,7 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
- * Copyright (c) 2008, Shawn Gervais <project10 at project10.net> 
+ * Copyright (c) 2008, Shawn Gervais <project10 at project10.net>
  * Copyright (c) 2008, Howard Butler <hobu.inc at gmail.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -33,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrsdelayer.cpp 28831 2015-04-01 16:46:05Z rouault $");
+CPL_CVSID("$Id: ogrsdelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                            OGRSDELayer()                             */
@@ -43,7 +43,7 @@ OGRSDELayer::OGRSDELayer( OGRSDEDataSource *poDSIn, int bUpdate )
 
 {
     poDS = poDSIn;
-    
+
     bUpdateAccess = bUpdate;
     bPreservePrecision = TRUE;
 
@@ -73,7 +73,7 @@ OGRSDELayer::~OGRSDELayer()
     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     {
         CPLDebug( "OGR_SDE", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
+                  (int) m_nFeaturesRead,
                   poFeatureDefn->GetName() );
     }
 
@@ -96,7 +96,7 @@ OGRSDELayer::~OGRSDELayer()
         poSRS->Release();
 
     CSLDestroy( papszAllColumns );
-    
+
     CPLFree( pszOwnerName );
     CPLFree( pszDbTableName );
 }
@@ -105,7 +105,7 @@ OGRSDELayer::~OGRSDELayer()
 /*                             Initialize()                             */
 /************************************************************************/
 
-int OGRSDELayer::Initialize( const char *pszTableName, 
+int OGRSDELayer::Initialize( const char *pszTableName,
                              const char *pszFIDColumn,
                              const char *pszShapeColumn )
 
@@ -113,14 +113,14 @@ int OGRSDELayer::Initialize( const char *pszTableName,
     SE_COLUMN_DEF *asColumnDefs;
     SHORT   nColumnCount;
     int nSDEErr, iCol;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Determine DBMS table owner name and the table name part         */
 /*      from pszTableName which is a fully-qualified table name         */
 /* -------------------------------------------------------------------- */
     char               *pszTableNameCopy = CPLStrdup( pszTableName );
     char               *pszPeriodPtr;
-    
+
     if( (pszPeriodPtr = strstr( pszTableNameCopy,"." )) != NULL )
     {
         *pszPeriodPtr  = '\0';
@@ -132,21 +132,21 @@ int OGRSDELayer::Initialize( const char *pszTableName,
         pszOwnerName   = NULL;
         pszDbTableName = CPLStrdup(pszTableName);
     }
-    
+
     CPLFree( pszTableNameCopy );
 
 /* -------------------------------------------------------------------- */
 /*      Determine whether multi-versioning is enabled for this table.   */
 /* -------------------------------------------------------------------- */
     SE_REGINFO          hRegInfo;
-    
+
     nSDEErr = SE_reginfo_create( &hRegInfo );
     if( nSDEErr != SE_SUCCESS )
     {
         poDS->IssueSDEError( nSDEErr, "SE_reginfo_create" );
         return FALSE;
     }
-    
+
     // TODO: This is called from places that have RegInfo already -
     // should we just pass that in?
     nSDEErr = SE_registration_get_info( poDS->GetConnection(),
@@ -157,14 +157,14 @@ int OGRSDELayer::Initialize( const char *pszTableName,
         poDS->IssueSDEError( nSDEErr, "SE_registration_get_info" );
         return FALSE;
     }
-    
+
     bVersioned = SE_reginfo_is_multiversion( hRegInfo );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Describe table                                                  */
 /* -------------------------------------------------------------------- */
-    nSDEErr = 
-        SE_table_describe( poDS->GetConnection(), pszTableName, 
+    nSDEErr =
+        SE_table_describe( poDS->GetConnection(), pszTableName,
                            &nColumnCount, &asColumnDefs );
 
     if( nSDEErr != SE_SUCCESS )
@@ -182,10 +182,10 @@ int OGRSDELayer::Initialize( const char *pszTableName,
 /*  is tested to see if it contains one, and only one, type of geometry */
 /*  then that geometry type is placed into the LayerDefn.               */
 /* -------------------------------------------------------------------- */
-    const char *pszLayerType = CPLGetConfigOption( "OGR_SDE_GETLAYERTYPE", 
+    const char *pszLayerType = CPLGetConfigOption( "OGR_SDE_GETLAYERTYPE",
                                                    "FALSE" );
 
-    if( CSLTestBoolean(pszLayerType) != FALSE )
+    if( CPLTestBool(pszLayerType) )
     {
         poFeatureDefn->SetGeomType(DiscoverLayerType());
     }
@@ -195,7 +195,7 @@ int OGRSDELayer::Initialize( const char *pszTableName,
         OGRFieldType eOGRType = OFTIntegerList; // dummy
         int nWidth = -1, nPrecision = -1;
 
-        papszAllColumns = CSLAddString( papszAllColumns, 
+        papszAllColumns = CSLAddString( papszAllColumns,
                                         asColumnDefs[iCol].column_name );
 
         switch( asColumnDefs[iCol].sde_type )
@@ -268,7 +268,7 @@ int OGRSDELayer::Initialize( const char *pszTableName,
             oField.SetPrecision( nPrecision );
 
         poFeatureDefn->AddFieldDefn( &oField );
-        
+
         anFieldMap.push_back( iCol );
         anFieldTypeMap.push_back( asColumnDefs[iCol].sde_type );
 
@@ -309,11 +309,11 @@ int OGRSDELayer::NeedLayerInfo()
         return FALSE;
     }
 
-    CPLDebug( "OGR_SDE", "Loading %s layerinfo.", 
+    CPLDebug( "OGR_SDE", "Loading %s layerinfo.",
               poFeatureDefn->GetName() );
 
-    nSDEErr = SE_layer_get_info( poDS->GetConnection(), 
-                                 poFeatureDefn->GetName(), 
+    nSDEErr = SE_layer_get_info( poDS->GetConnection(),
+                                 poFeatureDefn->GetName(),
                                  osShapeColumnName.c_str(),
                                  hLayerInfo );
     if( nSDEErr != SE_SUCCESS )
@@ -328,7 +328,7 @@ int OGRSDELayer::NeedLayerInfo()
 /*      Fetch coordinate reference system.                              */
 /* -------------------------------------------------------------------- */
     SE_coordref_create( &hCoordRef );
-    
+
     nSDEErr = SE_layerinfo_get_coordref( hLayerInfo, hCoordRef );
     if( nSDEErr != SE_SUCCESS )
     {
@@ -349,10 +349,10 @@ int OGRSDELayer::NeedLayerInfo()
             poSRS->morphFromESRI();
         }
 
-	LFLOAT falsex, falsey, xyunits;
-	nSDEErr = SE_coordref_get_xy( hCoordRef, &falsex, &falsey, &xyunits );
-	CPLDebug( "SDE", "SE_coordref_get_xy(%s) = %g/%g/%g",
-		  pszDbTableName, falsex, falsey, xyunits );
+        LFLOAT falsex, falsey, xyunits;
+        nSDEErr = SE_coordref_get_xy( hCoordRef, &falsex, &falsey, &xyunits );
+        CPLDebug( "SDE", "SE_coordref_get_xy(%s) = %g/%g/%g",
+                  pszDbTableName, falsex, falsey, xyunits );
     }
 
     return TRUE;
@@ -369,7 +369,7 @@ OGRwkbGeometryType OGRSDELayer::DiscoverLayerType()
 
     int nSDEErr;
     LONG nShapeTypeMask = 0;
-  
+
 /* -------------------------------------------------------------------- */
 /*      Check layerinfo flags to establish what geometry types may      */
 /*      occur.                                                          */
@@ -387,14 +387,14 @@ OGRwkbGeometryType OGRSDELayer::DiscoverLayerType()
     int bIsMultipart = ( nShapeTypeMask & SE_MULTIPART_TYPE_MASK ? 1 : 0);
     nShapeTypeMask &= ~SE_MULTIPART_TYPE_MASK;
 
-    // Since we assume that all layers can bear a NULL geometry, 
+    // Since we assume that all layers can bear a NULL geometry,
     // throw the flag away.
     nShapeTypeMask &= ~SE_NIL_TYPE_MASK;
 
     int nTypeCount = 0;
     if ( nShapeTypeMask & SE_POINT_TYPE_MASK )
         nTypeCount++;
-    if ( nShapeTypeMask & SE_LINE_TYPE_MASK 
+    if ( nShapeTypeMask & SE_LINE_TYPE_MASK
          || nShapeTypeMask & SE_SIMPLE_LINE_TYPE_MASK )
         nTypeCount++;
 
@@ -422,7 +422,7 @@ OGRwkbGeometryType OGRSDELayer::DiscoverLayerType()
         szTableName[0] = '\0';
         szShapeColumn[0] = '\0';
 
-        nSDEErr = SE_layerinfo_get_spatial_column( hLayerInfo, szTableName, 
+        nSDEErr = SE_layerinfo_get_spatial_column( hLayerInfo, szTableName,
                                                    szShapeColumn );
         if ( nSDEErr != SE_SUCCESS )
         {
@@ -430,7 +430,7 @@ OGRwkbGeometryType OGRSDELayer::DiscoverLayerType()
             return wkbUnknown;
         }
 
-        nSDEErr = SE_layer_get_statistics( poDS->GetConnection(), szTableName, 
+        nSDEErr = SE_layer_get_statistics( poDS->GetConnection(), szTableName,
                                            szShapeColumn,
                                            &layerstats);
         if( nSDEErr != SE_SUCCESS )
@@ -439,7 +439,7 @@ OGRwkbGeometryType OGRSDELayer::DiscoverLayerType()
             return wkbUnknown;
         }
 
-        if ( nShapeTypeMask & SE_POINT_TYPE_MASK && 
+        if ( nShapeTypeMask & SE_POINT_TYPE_MASK &&
              ( layerstats.POINTs + layerstats.MultiPOINTs ) == 0 )
             nShapeTypeMask &= ~SE_POINT_TYPE_MASK;
 
@@ -458,7 +458,7 @@ OGRwkbGeometryType OGRSDELayer::DiscoverLayerType()
 
 /* -------------------------------------------------------------------- */
 /*      Select a geometry type based on the remaining flags.  If        */
-/*      there is a mix we will fall through to the default (wkbUknown). */
+/*      there is a mix we will fall through to the default (wkbUnknown). */
 /* -------------------------------------------------------------------- */
     OGRwkbGeometryType eGeoType;
     char *pszTypeName;
@@ -481,7 +481,7 @@ OGRwkbGeometryType OGRSDELayer::DiscoverLayerType()
             eGeoType = wkbLineString;
         pszTypeName = "line";
         break;
-      
+
       case SE_AREA_TYPE_MASK:
         if (bIsMultipart)
             eGeoType = wkbMultiPolygon;
@@ -489,14 +489,14 @@ OGRwkbGeometryType OGRSDELayer::DiscoverLayerType()
             eGeoType = wkbPolygon;
         pszTypeName = "polygon";
         break;
-      
+
       default:
         eGeoType = wkbUnknown;
         pszTypeName = "unknown";
         break;
     }
 
-    CPLDebug( "OGR_SDE", 
+    CPLDebug( "OGR_SDE",
               "DiscoverLayerType is returning type=%d (%s), multipart=%d.",
               eGeoType, pszTypeName, bIsMultipart );
 
@@ -541,27 +541,27 @@ int OGRSDELayer::InstallQuery( int bCountingOnly )
     if( nSDEErr != SE_SUCCESS) {
         poDS->IssueSDEError( nSDEErr, "SE_queryinfo_create" );
         return FALSE;
-    }    
-    
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Select table.                                                   */
 /* -------------------------------------------------------------------- */
-    nSDEErr = SE_queryinfo_set_tables( hQueryInfo, 1, 
+    nSDEErr = SE_queryinfo_set_tables( hQueryInfo, 1,
                                        &pszTableName, NULL );
     if( nSDEErr != SE_SUCCESS) {
         poDS->IssueSDEError( nSDEErr, "SE_queryinfo_set_tables" );
         return FALSE;
-    }    
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Set where clause.                                               */
 /* -------------------------------------------------------------------- */
-    nSDEErr = SE_queryinfo_set_where_clause( hQueryInfo, 
+    nSDEErr = SE_queryinfo_set_where_clause( hQueryInfo,
                                              osAttributeFilter.c_str() );
     if( nSDEErr != SE_SUCCESS) {
         poDS->IssueSDEError( nSDEErr, "SE_queryinfo_set_where_clause" );
         return FALSE;
-    }    
+    }
 
 /* -------------------------------------------------------------------- */
 /*      We want to join the spatial and attribute tables.               */
@@ -570,7 +570,7 @@ int OGRSDELayer::InstallQuery( int bCountingOnly )
     if( nSDEErr != SE_SUCCESS) {
         poDS->IssueSDEError( nSDEErr, "SE_queryinfo_set_query_type" );
         return FALSE;
-    }    
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Establish the columns to query.  If only counting features,     */
@@ -579,25 +579,25 @@ int OGRSDELayer::InstallQuery( int bCountingOnly )
 /* -------------------------------------------------------------------- */
     if( bCountingOnly && iFIDColumn != -1 )
     {
-        const char *pszFIDColName = 
+        const char *pszFIDColName =
             poFeatureDefn->GetFieldDefn( iFIDColumn )->GetNameRef();
-        
-        nSDEErr = SE_queryinfo_set_columns( hQueryInfo, 1, 
+
+        nSDEErr = SE_queryinfo_set_columns( hQueryInfo, 1,
                                             (const char **) &pszFIDColName );
         if( nSDEErr != SE_SUCCESS) {
             poDS->IssueSDEError( nSDEErr, "SE_queryinfo_set_columns" );
             return FALSE;
-        }    
+        }
     }
     else
     {
-        nSDEErr = SE_queryinfo_set_columns( hQueryInfo, 
+        nSDEErr = SE_queryinfo_set_columns( hQueryInfo,
                                             CSLCount(papszAllColumns),
                                             (const char **) papszAllColumns );
         if( nSDEErr != SE_SUCCESS) {
             poDS->IssueSDEError( nSDEErr, "SE_queryinfo_set_columns" );
             return FALSE;
-        }    
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -607,7 +607,7 @@ int OGRSDELayer::InstallQuery( int bCountingOnly )
     if( nSDEErr != SE_SUCCESS) {
         poDS->IssueSDEError( nSDEErr, "SE_stream_query_with_info" );
         return FALSE;
-    }    
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Free query resources.                                           */
@@ -627,16 +627,16 @@ int OGRSDELayer::InstallQuery( int bCountingOnly )
 
         if( osAttributeFilter.size() > 0 )
         {
-            const char *pszOrder = CPLGetConfigOption( "OGR_SDE_SEARCHORDER", 
+            const char *pszOrder = CPLGetConfigOption( "OGR_SDE_SEARCHORDER",
                                                        "ATTRIBUTE_FIRST" );
 
             if( EQUAL(pszOrder, "ATTRIBUTE_FIRST") )
                 nSearchOrder = SE_ATTRIBUTE_FIRST;
-            else 
+            else
             {
                 if( !EQUAL(pszOrder, "SPATIAL_FIRST") )
-                    CPLError( CE_Warning, CPLE_AppDefined, 
-                              "Unrecognised OGR_SDE_SEARCHORDER value of %s.",
+                    CPLError( CE_Warning, CPLE_AppDefined,
+                              "Unrecognized OGR_SDE_SEARCHORDER value of %s.",
                               pszOrder );
                 nSearchOrder = SE_SPATIAL_FIRST;
             }
@@ -645,7 +645,7 @@ int OGRSDELayer::InstallQuery( int bCountingOnly )
         NeedLayerInfo(); // need hCoordRef
 
         nSDEErr = SE_shape_create( hCoordRef, &hRectShape );
-        if( nSDEErr != SE_SUCCESS) 
+        if( nSDEErr != SE_SUCCESS)
         {
             poDS->IssueSDEError( nSDEErr, "SE_shape_create");
             return FALSE;
@@ -663,22 +663,22 @@ int OGRSDELayer::InstallQuery( int bCountingOnly )
         }
         // ensure that the spatial filter overlaps area of the layer
         if (sEnvelope.minx > sLayerEnvelope.maxx || sEnvelope.maxx < sLayerEnvelope.minx ||
-            sEnvelope.miny > sLayerEnvelope.maxy || sEnvelope.maxy < sLayerEnvelope.miny ) 
+            sEnvelope.miny > sLayerEnvelope.maxy || sEnvelope.maxy < sLayerEnvelope.miny )
         {
             // using a small rectangle to filter out all the shapes
             sEnvelope.minx = sLayerEnvelope.minx;
             sEnvelope.miny = sLayerEnvelope.miny;
             sEnvelope.maxx = sLayerEnvelope.minx + 0.00000001;
-            sEnvelope.maxy = sLayerEnvelope.miny + 0.00000001;  
+            sEnvelope.maxy = sLayerEnvelope.miny + 0.00000001;
         }
-        
+
         nSDEErr = SE_shape_generate_rectangle( &sEnvelope, hRectShape );
-        if( nSDEErr != SE_SUCCESS) 
+        if( nSDEErr != SE_SUCCESS)
         {
             poDS->IssueSDEError( nSDEErr, "SE_shape_generate_rectangle");
             return FALSE;
         }
-        
+
         sConstraint.filter.shape = hRectShape;
         strcpy( sConstraint.table, poFeatureDefn->GetName() );
         strcpy( sConstraint.column, osShapeColumnName.c_str() );
@@ -688,11 +688,11 @@ int OGRSDELayer::InstallQuery( int bCountingOnly )
 
         nSDEErr = SE_stream_set_spatial_constraints( hStream, nSearchOrder,
                                                      FALSE, 1, &sConstraint );
-        if( nSDEErr != SE_SUCCESS) 
+        if( nSDEErr != SE_SUCCESS)
         {
             poDS->IssueSDEError( nSDEErr, "SE_stream_set_spatial_constraints");
             return FALSE;
-        }    
+        }
 
         SE_shape_free( hRectShape );
     }
@@ -704,7 +704,7 @@ int OGRSDELayer::InstallQuery( int bCountingOnly )
     if( nSDEErr != SE_SUCCESS ) {
         poDS->IssueSDEError( nSDEErr, "SE_stream_execute" );
         return FALSE;
-    }    
+    }
 
     bQueryInstalled = TRUE;
 
@@ -743,7 +743,7 @@ OGRErr OGRSDELayer::SetAttributeFilter( const char *pszQuery )
 /************************************************************************/
 OGRErr OGRSDELayer::TranslateOGRRecord( OGRFeature *poFeature,
                                         int bIsInsert )
-        
+
 {
     SE_SHAPE            hShape;
     LONG                nSDEErr;
@@ -770,10 +770,10 @@ OGRErr OGRSDELayer::TranslateOGRRecord( OGRFeature *poFeature,
     int                 nAttributeCols = 0;
     int                 nSpecialCols = 0;
     int                 i;
-    
-    paiColToDefMap = (int *) CPLMalloc( sizeof(int) 
+
+    paiColToDefMap = (int *) CPLMalloc( sizeof(int)
                                         * poFeatureDefn->GetFieldCount() );
-    
+
     /*
      * If the row id is managed by USER, and not SDE, then we need to take
      * care to set the FID column ourselves. If the row id column is managed by
@@ -784,15 +784,15 @@ OGRErr OGRSDELayer::TranslateOGRRecord( OGRFeature *poFeature,
     {
         papszInsertCols = CSLAddString( papszInsertCols,
                                         osFIDColumnName.c_str() );
-        
+
         nSpecialCols++;
     }
 
     if( poFeature->GetGeometryRef() != NULL )
     {
-        papszInsertCols = CSLAddString( papszInsertCols, 
+        papszInsertCols = CSLAddString( papszInsertCols,
                                         osShapeColumnName.c_str() );
-        
+
         nSpecialCols++;
     }
 
@@ -801,10 +801,10 @@ OGRErr OGRSDELayer::TranslateOGRRecord( OGRFeature *poFeature,
     for( i=0; i < poFeatureDefn->GetFieldCount(); i++ )
     {
         OGRFieldDefn   *poFieldDefn = poFeatureDefn->GetFieldDefn(i);
-        
+
         if( !poFeature->IsFieldSet(i) )
             continue;
-        
+
         // Skip FID and Geometry columns
         if( EQUAL(poFieldDefn->GetNameRef(), osFIDColumnName.c_str()) )
         {
@@ -812,34 +812,33 @@ OGRErr OGRSDELayer::TranslateOGRRecord( OGRFeature *poFeature,
             if( nFIDColumnType == SE_REGISTRATION_ROW_ID_COLUMN_TYPE_SDE )
                 continue;
         }
-        
+
         if( EQUAL(poFieldDefn->GetNameRef(), osShapeColumnName.c_str()) )
             continue;
-        
+
         papszInsertCols = CSLAddString( papszInsertCols,
                                         poFieldDefn->GetNameRef() );
-        
+
         paiColToDefMap[nAttributeCols] = i;
         nAttributeCols++;
     }
-    
-    
+
 /* -------------------------------------------------------------------- */
 /*      Prepare the insert or update stream mode                        */
 /* -------------------------------------------------------------------- */
     const char         *pszMethod;
-    
+
     if( bIsInsert )
     {
         nSDEErr = SE_stream_insert_table( hStream, poFeatureDefn->GetName(),
-                                          nSpecialCols + nAttributeCols, 
+                                          nSpecialCols + nAttributeCols,
                                           (const char **)papszInsertCols );
         pszMethod = "SE_stream_insert_table";
     }
     else // It's an UPDATE
     {
         const char     *pszWhere;
-        
+
         // Check that there is a FID column detected on the table, and that
         // this feature has a non-null FID
         if( iFIDColumn == -1 )
@@ -847,27 +846,27 @@ OGRErr OGRSDELayer::TranslateOGRRecord( OGRFeature *poFeature,
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Cannot update feature: Layer \"%s\" has no FID column",
                       poFeatureDefn->GetName() );
-            
+
             CSLDestroy( papszInsertCols );
             CPLFree( paiColToDefMap );
-            
+
             return OGRERR_FAILURE;
         }
         else if( poFeature->GetFID() == OGRNullFID )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Cannot update feature: Feature has a NULL Feature ID" );
-            
+
             CSLDestroy( papszInsertCols );
             CPLFree( paiColToDefMap );
-            
+
             return OGRERR_FAILURE;
         }
-        
+
         // Build WHERE clause
         pszWhere = CPLSPrintf( "%s = %ld", osFIDColumnName.c_str(),
                                            poFeature->GetFID() );
-        
+
         nSDEErr = SE_stream_update_table( hStream, poFeatureDefn->GetName(),
                                           nSpecialCols + nAttributeCols,
                                           (const char **)papszInsertCols,
@@ -875,40 +874,40 @@ OGRErr OGRSDELayer::TranslateOGRRecord( OGRFeature *poFeature,
 
         pszMethod = "SE_stream_update_table";
     }
-        
+
     if( nSDEErr != SE_SUCCESS )
     {
         poDS->IssueSDEError( nSDEErr, pszMethod );
         return OGRERR_FAILURE;
     }
 
-    
+
 /* -------------------------------------------------------------------- */
 /*      Set the feature attributes                                      */
 /* -------------------------------------------------------------------- */
     short               iCurColNum = 1;
-    
+
     if( nFIDColumnType == SE_REGISTRATION_ROW_ID_COLUMN_TYPE_USER
         && iFIDColumn != -1 )
     {
         LONG            nFID;
-        
+
         nFID = poFeature->GetFID();
         if( nFID == OGRNullFID )
         {
             nFID = iNextFIDToWrite++;
             poFeature->SetFID( nFID );
         }
-        
+
         nSDEErr = SE_stream_set_integer( hStream, iCurColNum++,
                                          &nFID );
         if( nSDEErr != SE_SUCCESS )
         {
             poDS->IssueSDEError( nSDEErr, "SE_stream_set_integer" );
-            
+
             CSLDestroy( papszInsertCols );
             CPLFree( paiColToDefMap );
-            
+
             return OGRERR_FAILURE;
         }
     }
@@ -917,18 +916,18 @@ OGRErr OGRSDELayer::TranslateOGRRecord( OGRFeature *poFeature,
     if( poFeature->GetGeometryRef() != NULL )
     {
         nSDEErr = SE_stream_set_shape( hStream, iCurColNum++, hShape );
-        
+
         if( nSDEErr != SE_SUCCESS )
         {
             poDS->IssueSDEError( nSDEErr, "SE_stream_set_shape" );
-            
+
             CSLDestroy( papszInsertCols );
             CPLFree( paiColToDefMap );
             SE_shape_free( hShape );
             return OGRERR_FAILURE;
         }
     }
-    
+
     // Set attribute columns
     for( i=0; i < nAttributeCols; i++ )
     {
@@ -938,14 +937,14 @@ OGRErr OGRSDELayer::TranslateOGRRecord( OGRFeature *poFeature,
 
         poFieldDefn = poFeatureDefn->GetFieldDefn(iFieldDefnIdx);
         poField = poFeature->GetRawFieldRef(iFieldDefnIdx);
-        
+
         CPLAssert( poFieldDefn != NULL );
         CPLAssert( poField != NULL );
-        
+
         if( poFieldDefn->GetType() == OFTInteger )
         {
             LONG        nLong = poField->Integer;
-            
+
             nSDEErr = SE_stream_set_integer( hStream, iCurColNum++,
                                              &nLong );
             if( nSDEErr != SE_SUCCESS )
@@ -956,11 +955,11 @@ OGRErr OGRSDELayer::TranslateOGRRecord( OGRFeature *poFeature,
                 return OGRERR_FAILURE;
             }
         }
-        
+
         else if( poFieldDefn->GetType() == OFTReal )
         {
             LFLOAT      nDouble = poField->Real;
-            
+
             nSDEErr = SE_stream_set_double( hStream, iCurColNum++,
                                             &nDouble );
             if( nSDEErr != SE_SUCCESS )
@@ -971,12 +970,12 @@ OGRErr OGRSDELayer::TranslateOGRRecord( OGRFeature *poFeature,
                 return OGRERR_FAILURE;
             }
         }
-        
-        else if( poFieldDefn->GetType() == OFTString 
+
+        else if( poFieldDefn->GetType() == OFTString
                  && anFieldTypeMap[iFieldDefnIdx] == SE_NSTRING_TYPE )
         {
-            SE_WCHAR *pszUTF16 = (SE_WCHAR *) 
-                CPLRecodeToWChar( poField->String, CPL_ENC_UTF8, 
+            SE_WCHAR *pszUTF16 = (SE_WCHAR *)
+                CPLRecodeToWChar( poField->String, CPL_ENC_UTF8,
                                   CPL_ENC_UTF16 );
 
             nSDEErr = SE_stream_set_nstring( hStream, iCurColNum++,
@@ -991,7 +990,7 @@ OGRErr OGRSDELayer::TranslateOGRRecord( OGRFeature *poFeature,
                 return OGRERR_FAILURE;
             }
         }
-        
+
         else if( poFieldDefn->GetType() == OFTString )
         {
             nSDEErr = SE_stream_set_string( hStream, iCurColNum++,
@@ -1004,12 +1003,12 @@ OGRErr OGRSDELayer::TranslateOGRRecord( OGRFeature *poFeature,
                 return OGRERR_FAILURE;
             }
         }
-        
+
         else if( poFieldDefn->GetType() == OFTDate
                  || poFieldDefn->GetType() == OFTDateTime )
         {
             struct tm sDateVal;
-            
+
             // TODO: hobu, please double-check this.
             sDateVal.tm_year  = poField->Date.Year - 1900;
             sDateVal.tm_mon   = poField->Date.Month - 1;
@@ -1018,7 +1017,7 @@ OGRErr OGRSDELayer::TranslateOGRRecord( OGRFeature *poFeature,
             sDateVal.tm_min   = poField->Date.Minute;
             sDateVal.tm_sec   = poField->Date.Second;
             sDateVal.tm_isdst = (poField->Date.TZFlag == 0 ? 0 : 1);
-            
+
             nSDEErr = SE_stream_set_date( hStream, iCurColNum++,
                                           &sDateVal );
             if( nSDEErr != SE_SUCCESS )
@@ -1029,17 +1028,17 @@ OGRErr OGRSDELayer::TranslateOGRRecord( OGRFeature *poFeature,
                 return OGRERR_FAILURE;
             }
         }
-        
+
         else
         {
             CPLError( CE_Warning, CPLE_AppDefined,
                       "Cannot set attribute of type %s in SDE layer: "
                       "attempting to create as STRING",
                       OGRFieldDefn::GetFieldTypeName(poFieldDefn->GetType()) );
-            
+
             CSLDestroy( papszInsertCols );
             CPLFree( paiColToDefMap );
-        
+
             return OGRERR_FAILURE;
         }
     }
@@ -1056,16 +1055,16 @@ OGRErr OGRSDELayer::TranslateOGRRecord( OGRFeature *poFeature,
 OGRErr OGRSDELayer::TranslateOGRGeometry( OGRGeometry *poGeom,
                                           SE_SHAPE *phShape,
                                           SE_COORDREF hCoordRef )
-        
+
 {
     LONG                nSDEErr;
-    
+
     CPLAssert( poGeom != NULL );
     CPLAssert( phShape != NULL );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Initialize shape.                                               */
-/* -------------------------------------------------------------------- */    
+/* -------------------------------------------------------------------- */
     nSDEErr = SE_shape_create( hCoordRef, phShape );
     if( nSDEErr != SE_SUCCESS )
     {
@@ -1075,11 +1074,11 @@ OGRErr OGRSDELayer::TranslateOGRGeometry( OGRGeometry *poGeom,
 
 /* -------------------------------------------------------------------- */
 /*      Determine whether the geometry includes Z coordinates.          */
-/* -------------------------------------------------------------------- */    
+/* -------------------------------------------------------------------- */
     int                 b3D = FALSE;
-    
+
     b3D = wkbHasZ(poGeom->getGeometryType());
-    
+
 /* -------------------------------------------------------------------- */
 /*      Translate POINT/MULTIPOINT type.                                */
 /* -------------------------------------------------------------------- */
@@ -1096,16 +1095,16 @@ OGRErr OGRSDELayer::TranslateOGRGeometry( OGRGeometry *poGeom,
                       "Cannot allocate asPointParts" );
             return OGRERR_FAILURE;
         }
-        
+
         anfZcoords = (LFLOAT*) CPLMalloc(nParts * sizeof(LFLOAT));
         if (!anfZcoords) {
             CPLError( CE_Fatal, CPLE_AppDefined,
                       "Cannot allocate anfZcoords" );
             return OGRERR_FAILURE;
-        }        
+        }
         asPointParts[0].x = poPoint->getX();
         asPointParts[0].y = poPoint->getY();
-        
+
         if( b3D )
         {
             anfZcoords[0] = poPoint->getZ();
@@ -1132,30 +1131,30 @@ OGRErr OGRSDELayer::TranslateOGRGeometry( OGRGeometry *poGeom,
         SE_POINT       *pasPointParts;
         LFLOAT         *panfZcoords = NULL;
         int             i;
-        
+
         nParts = poMulPoint->getNumGeometries();
-        
+
         pasPointParts = (SE_POINT *) CPLMalloc( sizeof(SE_POINT) * nParts );
-        
+
         if( b3D )
             panfZcoords = (LFLOAT *) CPLMalloc( sizeof(LFLOAT) * nParts );
-        
+
         for( i=0; i < nParts; i++ )
         {
             OGRPoint   *poThisPoint;
-            
+
             poThisPoint = (OGRPoint *) poMulPoint->getGeometryRef(i);
-                    
+
             pasPointParts[i].x = poThisPoint->getX();
             pasPointParts[i].y = poThisPoint->getY();
-            
+
             if( b3D )
                 panfZcoords[i] = poThisPoint->getZ();
         }
-        
+
         nSDEErr = SE_shape_generate_point( nParts, pasPointParts, panfZcoords,
                                            NULL, *phShape );
-        
+
         CPLFree( pasPointParts );
         if( b3D )
             CPLFree( panfZcoords );
@@ -1177,10 +1176,10 @@ OGRErr OGRSDELayer::TranslateOGRGeometry( OGRGeometry *poGeom,
         SE_POINT       *pasPoints;
         LFLOAT         *panfZcoords = NULL;
         int             i, j;
-        
+
         // Get exterior ring
         OGRLinearRing  *poExtRing = poPoly->getExteriorRing();
-        
+
         if( poExtRing == NULL )
         {
             // The polygon is empty
@@ -1192,67 +1191,67 @@ OGRErr OGRSDELayer::TranslateOGRGeometry( OGRGeometry *poGeom,
                 return OGRERR_FAILURE;
             }
         }
-        
+
         // Get total number of points in polygon
         nPoints += poExtRing->getNumPoints();
-        
+
         for( i=0; i < poPoly->getNumInteriorRings(); i++ )
             nPoints += poPoly->getInteriorRing(i)->getNumPoints();
-        
+
         pasPoints = (SE_POINT *) CPLMalloc( sizeof(SE_POINT) * nPoints );
-        
+
         if( b3D )
             panfZcoords = (LFLOAT *) CPLMalloc( sizeof(LFLOAT) * nPoints );
-        
+
         for( i=0; i < poExtRing->getNumPoints(); i++ )
         {
             OGRPoint    oLRPnt;
-            
+
             poExtRing->getPoint( i, &oLRPnt );
-            
+
             pasPoints[iCurPoint].x = oLRPnt.getX();
             pasPoints[iCurPoint].y = oLRPnt.getY();
-            
+
             if( b3D )
                 panfZcoords[iCurPoint] = oLRPnt.getZ();
 
             iCurPoint++;
         }
-        
+
         for( i=0; i < poPoly->getNumInteriorRings(); i++ )
         {
             OGRLinearRing   *poIntRing = poPoly->getInteriorRing(i);
-            
+
             for( j=0; j < poIntRing->getNumPoints(); j++ )
             {
                 OGRPoint    oLRPnt;
-                
+
                 poIntRing->getPoint( j, &oLRPnt );
-                
+
                 pasPoints[iCurPoint].x = oLRPnt.getX();
                 pasPoints[iCurPoint].y = oLRPnt.getY();
-                
+
                 if( b3D )
                     panfZcoords[iCurPoint] = oLRPnt.getZ();
-                
+
                 iCurPoint++;
             }
         }
-        
+
         nSDEErr = SE_shape_generate_polygon( nPoints, 1, NULL, pasPoints,
                                              panfZcoords, NULL, *phShape );
-        
+
         CPLFree( pasPoints );
         if( b3D )
             CPLFree( panfZcoords );
-        
+
         if( nSDEErr != SE_SUCCESS )
         {
             poDS->IssueSDEError( nSDEErr, "SE_shape_generate_polygon" );
             return OGRERR_FAILURE;
         }
     }
-    
+
     else if( wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon )
     {
         OGRMultiPolygon *poMP = (OGRMultiPolygon *) poGeom;
@@ -1263,9 +1262,9 @@ OGRErr OGRSDELayer::TranslateOGRGeometry( OGRGeometry *poGeom,
         SE_POINT        *pasPoints;
         LFLOAT          *panfZcoords = NULL;
         int              i, j, k;
-        
+
         nParts = poMP->getNumGeometries();
-        
+
         // Find total number of points
         for( i=0; i < nParts; i++ )
         {
@@ -1277,22 +1276,22 @@ OGRErr OGRSDELayer::TranslateOGRGeometry( OGRGeometry *poGeom,
             for( j=0; j < poPoly->getNumInteriorRings(); j++ )
                 nPoints += poPoly->getInteriorRing(j)->getNumPoints();
         }
-        
+
         // Allocate points and part offset arrays
         pasPoints = (SE_POINT *) CPLMalloc( sizeof(SE_POINT) * nPoints );
         panPartOffsets = (LONG *) CPLMalloc( sizeof(LONG) * nParts );
         if( b3D )
             panfZcoords = (LFLOAT *) CPLMalloc( sizeof(LFLOAT) * nPoints );
-        
-        
+
+
         // Build arrays of points and part offsets
         for( i=0; i < nParts; i++ )
         {
             OGRPolygon      *poPoly = (OGRPolygon *) poMP->getGeometryRef(i);
             OGRLinearRing   *poExtRing = poPoly->getExteriorRing();
-            
+
             panPartOffsets[i] = iCurPoint;
-            
+
             for( j=0; j < poExtRing->getNumPoints(); j++ )
             {
                 OGRPoint    oLRPnt;
@@ -1301,7 +1300,7 @@ OGRErr OGRSDELayer::TranslateOGRGeometry( OGRGeometry *poGeom,
 
                 pasPoints[iCurPoint].x = oLRPnt.getX();
                 pasPoints[iCurPoint].y = oLRPnt.getY();
-                
+
                 if( b3D )
                     panfZcoords[iCurPoint] = oLRPnt.getZ();
 
@@ -1320,7 +1319,7 @@ OGRErr OGRSDELayer::TranslateOGRGeometry( OGRGeometry *poGeom,
 
                     pasPoints[iCurPoint].x = oLRPnt.getX();
                     pasPoints[iCurPoint].y = oLRPnt.getY();
-                    
+
                     if( b3D )
                         panfZcoords[iCurPoint] = oLRPnt.getZ();
 
@@ -1328,16 +1327,16 @@ OGRErr OGRSDELayer::TranslateOGRGeometry( OGRGeometry *poGeom,
                 }
             }
         }
-        
+
         nSDEErr = SE_shape_generate_polygon( nPoints, nParts, panPartOffsets,
                                              pasPoints, panfZcoords, NULL,
                                              *phShape );
-        
+
         CPLFree( pasPoints );
         CPLFree( panPartOffsets );
         if( b3D )
             CPLFree( panfZcoords );
-        
+
         if( nSDEErr != SE_SUCCESS )
         {
             poDS->IssueSDEError( nSDEErr, "SE_shape_generate_polygon" );
@@ -1345,10 +1344,10 @@ OGRErr OGRSDELayer::TranslateOGRGeometry( OGRGeometry *poGeom,
         }
     }
 
-    
+
 /* -------------------------------------------------------------------- */
 /*      Translate LINESTRING/MULTILINESTRING type.                      */
-/* -------------------------------------------------------------------- */    
+/* -------------------------------------------------------------------- */
     else if( wkbFlatten(poGeom->getGeometryType()) == wkbLineString )
     {
         OGRLineString  *poLineString = (OGRLineString *) poGeom;
@@ -1357,40 +1356,40 @@ OGRErr OGRSDELayer::TranslateOGRGeometry( OGRGeometry *poGeom,
         SE_POINT       *pasPoints;
         LFLOAT         *panfZcoords = NULL;
         int             i;
-        
+
         nPoints = poLineString->getNumPoints();
-        
+
         pasPoints = (SE_POINT *) CPLMalloc( sizeof(SE_POINT) * nPoints );
         if( b3D )
             panfZcoords = (LFLOAT *) CPLMalloc( sizeof(LFLOAT) * nPoints );
-        
+
         for( i=0; i < nPoints; i++ )
         {
             OGRPoint   oPoint;
-            
+
             poLineString->getPoint( i, &oPoint );
 
             pasPoints[i].x = oPoint.getX();
             pasPoints[i].y = oPoint.getY();
-            
+
             if( b3D )
                 panfZcoords[i] = oPoint.getZ();
         }
-        
+
         nSDEErr = SE_shape_generate_line( nPoints, nParts, NULL, pasPoints,
                                           panfZcoords, NULL, *phShape );
-        
+
         CPLFree( pasPoints );
         if( b3D )
             CPLFree( panfZcoords );
-        
+
         if( nSDEErr != SE_SUCCESS )
         {
             poDS->IssueSDEError( nSDEErr, "SE_shape_generate_line" );
             return OGRERR_FAILURE;
         }
     }
-    
+
     else if( wkbFlatten(poGeom->getGeometryType()) == wkbMultiLineString )
     {
         OGRMultiLineString *poMLS = (OGRMultiLineString *) poGeom;
@@ -1401,74 +1400,74 @@ OGRErr OGRSDELayer::TranslateOGRGeometry( OGRGeometry *poGeom,
         LONG           *panPartOffsets;
         LFLOAT         *panfZcoords = NULL;
         int             i, j;
-        
+
         // Get number of parts and total number of points
         nParts = poMLS->getNumGeometries();
-        
+
         for( i=0; i < nParts; i++ )
         {
             OGRLineString   *poLS = (OGRLineString *) poMLS->getGeometryRef(i);
-            
+
             nPoints += poLS->getNumPoints();
         }
-        
+
         // Allocate arrays for points and part offsets
         pasPoints = (SE_POINT *) CPLMalloc( sizeof(SE_POINT) * nPoints );
         panPartOffsets = (LONG *) CPLMalloc( sizeof(LONG) * nParts );
         if( b3D )
             panfZcoords = (LFLOAT *) CPLMalloc( sizeof(LFLOAT) * nPoints );
-        
+
         for( i=0; i < nParts; i++ )
         {
             OGRLineString   *poLS = (OGRLineString *) poMLS->getGeometryRef(i);
-            
+
             panPartOffsets[i] = iCurPoint;
-            
+
             for( j=0; j < poLS->getNumPoints(); j++ )
             {
                 OGRPoint    oPoint;
-                
+
                 poLS->getPoint( j, &oPoint );
-                
+
                 pasPoints[iCurPoint].x = oPoint.getX();
                 pasPoints[iCurPoint].y = oPoint.getY();
-                
+
                 if( b3D )
                     panfZcoords[iCurPoint] = oPoint.getZ();
-                
+
                 iCurPoint++;
             }
         }
-        
+
         nSDEErr = SE_shape_generate_line( nPoints, nParts, panPartOffsets,
                                           pasPoints, panfZcoords, NULL,
                                           *phShape );
-        
+
         CPLFree( pasPoints );
         CPLFree( panPartOffsets );
         if( b3D )
             CPLFree( panfZcoords );
-        
+
         if( nSDEErr != SE_SUCCESS )
         {
             poDS->IssueSDEError( nSDEErr, "SE_shape_generate_line" );
             return OGRERR_FAILURE;
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*       Error on other geometry types.                                 */
-/* -------------------------------------------------------------------- */    
+/* -------------------------------------------------------------------- */
     else
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "OGR_SDE: TranslateOGRGeometry() cannot translate "
                   "geometries of type %s (%d)", poGeom->getGeometryName(),
                   poGeom->getGeometryType() );
-        
+
         return OGRERR_FAILURE;
     }
-    
+
     return OGRERR_NONE;
 }
 
@@ -1489,7 +1488,7 @@ OGRGeometry *OGRSDELayer::TranslateSDEGeometry( SE_SHAPE hShape )
 
     if( nSDEGeomType == SG_NIL_SHAPE )
         return NULL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Fetch points and parts.                                         */
 /* -------------------------------------------------------------------- */
@@ -1505,12 +1504,12 @@ OGRGeometry *OGRSDELayer::TranslateSDEGeometry( SE_SHAPE hShape )
     pasPoints = (SE_POINT *) CPLMalloc(nPointCount * sizeof(SE_POINT));
     panParts = (LONG *) CPLMalloc(nPartCount * sizeof(LONG));
     panSubParts = (LONG *) CPLMalloc(nSubPartCount * sizeof(LONG));
-    
+
     if( SE_shape_is_3D( hShape ) )
         padfZ = (LFLOAT *) CPLMalloc(nPointCount * sizeof(LFLOAT));
 
-    nSDEErr = SE_shape_get_all_points( hShape, SE_DEFAULT_ROTATION, 
-                                       panParts, panSubParts, 
+    nSDEErr = SE_shape_get_all_points( hShape, SE_DEFAULT_ROTATION,
+                                       panParts, panSubParts,
                                        pasPoints, padfZ, NULL );
     if( nSDEErr != SE_SUCCESS )
     {
@@ -1568,7 +1567,7 @@ OGRGeometry *OGRSDELayer::TranslateSDEGeometry( SE_SHAPE hShape )
       {
           OGRLineString *poLine = new OGRLineString();
           int i;
-          
+
           CPLAssert( nPartCount == 1 && nSubPartCount == 1 );
 
           poLine->setNumPoints( nPointCount );
@@ -1576,7 +1575,7 @@ OGRGeometry *OGRSDELayer::TranslateSDEGeometry( SE_SHAPE hShape )
           for( i = 0; i < nPointCount; i++ )
           {
               if( padfZ )
-                  poLine->setPoint( i, pasPoints[i].x, pasPoints[i].y, 
+                  poLine->setPoint( i, pasPoints[i].x, pasPoints[i].y,
                                     padfZ[i] );
               else
                   poLine->setPoint( i, pasPoints[i].x, pasPoints[i].y );
@@ -1596,33 +1595,33 @@ OGRGeometry *OGRSDELayer::TranslateSDEGeometry( SE_SHAPE hShape )
 	  int iPart;
 
           CPLAssert( nPartCount == nSubPartCount );
-              
+
           for( iPart = 0; iPart < nPartCount; iPart++ )
           {
               OGRLineString *poLine = new OGRLineString();
               int i, nLineVertCount;
 
-              CPLAssert( panParts[iPart] == iPart ); // 1:1 correspondance
-          
+              CPLAssert( panParts[iPart] == iPart ); // 1:1 correspondence
+
               if( iPart == nPartCount-1 )
                   nLineVertCount = nPointCount - panSubParts[iPart];
               else
                   nLineVertCount = panSubParts[iPart+1] - panSubParts[iPart];
 
               poLine->setNumPoints( nLineVertCount );
-              
+
               for( i = 0; i < nLineVertCount; i++ )
               {
                   int iVert = i + panSubParts[iPart];
 
                   if( padfZ )
-                      poLine->setPoint( i, 
-                                        pasPoints[iVert].x, 
-                                        pasPoints[iVert].y, 
+                      poLine->setPoint( i,
+                                        pasPoints[iVert].x,
+                                        pasPoints[iVert].y,
                                         padfZ[iVert] );
                   else
-                      poLine->setPoint( i, 
-                                        pasPoints[iVert].x, 
+                      poLine->setPoint( i,
+                                        pasPoints[iVert].x,
                                         pasPoints[iVert].y );
               }
 
@@ -1655,35 +1654,35 @@ OGRGeometry *OGRSDELayer::TranslateSDEGeometry( SE_SHAPE hShape )
                   nNextSubPart = nSubPartCount;
               else
                   nNextSubPart = panParts[iPart+1];
-              
+
               for( iSubPart = panParts[iPart]; iSubPart < nNextSubPart; iSubPart++ )
               {
                   OGRLinearRing *poRing = new OGRLinearRing();
-                  int nRingVertCount; 
-                  
+                  int nRingVertCount;
+
                   if( iSubPart == nSubPartCount-1 )
                       nRingVertCount = nPointCount - panSubParts[iSubPart];
                   else
-                      nRingVertCount = 
+                      nRingVertCount =
                           panSubParts[iSubPart+1] - panSubParts[iSubPart];
-                  
+
                   poRing->setNumPoints( nRingVertCount );
-                  
+
                   for( iVert=0; iVert < nRingVertCount; iVert++ )
                   {
                       if( padfZ )
-                          poRing->setPoint( 
-                              iVert, 
+                          poRing->setPoint(
+                              iVert,
                               pasPoints[iVert+panSubParts[iSubPart]].x,
                               pasPoints[iVert+panSubParts[iSubPart]].y,
                               padfZ[iVert+panSubParts[iSubPart]] );
                       else
-                          poRing->setPoint( 
-                              iVert, 
+                          poRing->setPoint(
+                              iVert,
                               pasPoints[iVert+panSubParts[iSubPart]].x,
                               pasPoints[iVert+panSubParts[iSubPart]].y );
                   }
-                  
+
                   poPoly->addRingDirectly( poRing );
               }
 
@@ -1703,8 +1702,8 @@ OGRGeometry *OGRSDELayer::TranslateSDEGeometry( SE_SHAPE hShape )
 /* -------------------------------------------------------------------- */
       default:
       {
-          CPLError( CE_Warning, CPLE_NotSupported, 
-                    "Unsupported geometry type: %d", 
+          CPLError( CE_Warning, CPLE_NotSupported,
+                    "Unsupported geometry type: %d",
                     (int) nSDEGeomType );
       }
     }
@@ -1743,7 +1742,7 @@ OGRFeature *OGRSDELayer::TranslateSDERecord()
           case SE_SMALLINT_TYPE:
           {
               short   nShort;
-              nSDEErr = SE_stream_get_smallint( hStream, anFieldMap[i]+1, 
+              nSDEErr = SE_stream_get_smallint( hStream, anFieldMap[i]+1,
                                                 &nShort );
               if( nSDEErr == SE_SUCCESS )
                   poFeat->SetField( i, (int) nShort );
@@ -1758,7 +1757,7 @@ OGRFeature *OGRSDELayer::TranslateSDERecord()
           case SE_INTEGER_TYPE:
           {
               LONG nValue;
-              nSDEErr = SE_stream_get_integer( hStream, anFieldMap[i]+1, 
+              nSDEErr = SE_stream_get_integer( hStream, anFieldMap[i]+1,
                                                &nValue );
               if( nSDEErr == SE_SUCCESS )
                   poFeat->SetField( i, (int) nValue );
@@ -1774,7 +1773,7 @@ OGRFeature *OGRSDELayer::TranslateSDERecord()
           {
               float fValue;
 
-              nSDEErr = SE_stream_get_float( hStream, anFieldMap[i]+1, 
+              nSDEErr = SE_stream_get_float( hStream, anFieldMap[i]+1,
                                              &fValue );
               if( nSDEErr == SE_SUCCESS )
                   poFeat->SetField( i, (double) fValue );
@@ -1790,7 +1789,7 @@ OGRFeature *OGRSDELayer::TranslateSDERecord()
           {
               double dfValue;
 
-              nSDEErr = SE_stream_get_double( hStream, anFieldMap[i]+1, 
+              nSDEErr = SE_stream_get_double( hStream, anFieldMap[i]+1,
                                               &dfValue );
               if( nSDEErr == SE_SUCCESS )
                   poFeat->SetField( i, dfValue );
@@ -1807,7 +1806,7 @@ OGRFeature *OGRSDELayer::TranslateSDERecord()
               char *pszTempString = (char *)
                   CPLMalloc(poFieldDef->GetWidth()+1);
 
-              nSDEErr = SE_stream_get_string( hStream, anFieldMap[i]+1, 
+              nSDEErr = SE_stream_get_string( hStream, anFieldMap[i]+1,
                                               pszTempString );
               if( nSDEErr == SE_SUCCESS )
                   poFeat->SetField( i, pszTempString );
@@ -1822,20 +1821,20 @@ OGRFeature *OGRSDELayer::TranslateSDERecord()
 
           case SE_NSTRING_TYPE:
           {
-              SE_WCHAR * pszTempStringUTF16 = (SE_WCHAR *) 
+              SE_WCHAR * pszTempStringUTF16 = (SE_WCHAR *)
                   CPLMalloc ((poFieldDef->GetWidth()+1) * sizeof(SE_WCHAR ));
 
-              nSDEErr = SE_stream_get_nstring( hStream, anFieldMap[i]+1, 
+              nSDEErr = SE_stream_get_nstring( hStream, anFieldMap[i]+1,
                                                pszTempStringUTF16 );
 
-              if( nSDEErr == SE_SUCCESS ) 
+              if( nSDEErr == SE_SUCCESS )
               {
                   char* pszUTF8 = CPLRecodeFromWChar((const wchar_t*)pszTempStringUTF16, CPL_ENC_UTF16, CPL_ENC_UTF8);
 
                   poFeat->SetField( i, pszUTF8 );
                   CPLFree( pszUTF8 );
 
-              } 
+              }
               else if( nSDEErr != SE_NULL_VALUE )
               {
                   poDS->IssueSDEError( nSDEErr, "SE_stream_get_nstring" );
@@ -1853,7 +1852,7 @@ OGRFeature *OGRSDELayer::TranslateSDERecord()
               char *pszTempString = (char *)
                   CPLMalloc(poFieldDef->GetWidth()+1);
 
-              nSDEErr = SE_stream_get_uuid( hStream, anFieldMap[i]+1, 
+              nSDEErr = SE_stream_get_uuid( hStream, anFieldMap[i]+1,
                                               pszTempString );
               if( nSDEErr == SE_SUCCESS )
                   poFeat->SetField( i, pszTempString );
@@ -1870,12 +1869,12 @@ OGRFeature *OGRSDELayer::TranslateSDERecord()
           {
               SE_BLOB_INFO sBlobVal;
 
-              nSDEErr = SE_stream_get_blob( hStream, anFieldMap[i]+1, 
+              nSDEErr = SE_stream_get_blob( hStream, anFieldMap[i]+1,
                                             &sBlobVal );
               if( nSDEErr == SE_SUCCESS )
               {
-                  poFeat->SetField( i, 
-                                    sBlobVal.blob_length, 
+                  poFeat->SetField( i,
+                                    sBlobVal.blob_length,
                                     (GByte *) sBlobVal.blob_buffer );
                   SE_blob_free( &sBlobVal );
               }
@@ -1893,7 +1892,7 @@ OGRFeature *OGRSDELayer::TranslateSDERecord()
               SE_CLOB_INFO sClobVal;
 
               memset(&sClobVal, 0, sizeof(sClobVal)); /* to prevent from the crash in SE_stream_get_clob */
-              nSDEErr = SE_stream_get_clob( hStream, anFieldMap[i]+1, 
+              nSDEErr = SE_stream_get_clob( hStream, anFieldMap[i]+1,
                                             &sClobVal );
               if( nSDEErr == SE_SUCCESS )
               {
@@ -1901,7 +1900,7 @@ OGRFeature *OGRSDELayer::TranslateSDERecord()
                   char* sClobstring = (char*)CPLMalloc(sizeof(char)*(sClobVal.clob_length+1));
                   memcpy(sClobstring, sClobVal.clob_buffer, sClobVal.clob_length);
 				  sClobstring[sClobVal.clob_length] = '\0';
-                  
+
                   poFeat->SetField( i, sClobstring );
                   SE_clob_free( &sClobVal );
                   CPLFree(sClobstring);
@@ -1922,7 +1921,7 @@ OGRFeature *OGRSDELayer::TranslateSDERecord()
               SE_NCLOB_INFO sNclobVal;
 
               memset(&sNclobVal, 0, sizeof(sNclobVal)); /* to prevent from the crash in SE_stream_get_nclob */
-              nSDEErr = SE_stream_get_nclob( hStream, anFieldMap[i]+1, 
+              nSDEErr = SE_stream_get_nclob( hStream, anFieldMap[i]+1,
                                             &sNclobVal );
               if( nSDEErr == SE_SUCCESS )
               {
@@ -1935,7 +1934,7 @@ OGRFeature *OGRSDELayer::TranslateSDERecord()
 
                   poFeat->SetField( i, pszUTF8 );
                   CPLFree( pszUTF8 );
-                  
+
                   SE_nclob_free( &sNclobVal );
                   CPLFree(sNclobstring);
               }
@@ -1953,11 +1952,11 @@ OGRFeature *OGRSDELayer::TranslateSDERecord()
           {
               struct tm sDateVal;
 
-              nSDEErr = SE_stream_get_date( hStream, anFieldMap[i]+1, 
+              nSDEErr = SE_stream_get_date( hStream, anFieldMap[i]+1,
                                             &sDateVal );
               if( nSDEErr == SE_SUCCESS )
 			  {
-			      poFeat->SetField( i, sDateVal.tm_year + 1900, sDateVal.tm_mon + 1, sDateVal.tm_mday, 
+			      poFeat->SetField( i, sDateVal.tm_year + 1900, sDateVal.tm_mon + 1, sDateVal.tm_mday,
 					  sDateVal.tm_hour, sDateVal.tm_min, sDateVal.tm_sec, (sDateVal.tm_isdst > 0));
               }
               else if( nSDEErr != SE_NULL_VALUE )
@@ -1992,7 +1991,7 @@ OGRFeature *OGRSDELayer::TranslateSDERecord()
             poDS->IssueSDEError( nSDEErr, "SE_shape_create" );
         else
         {
-            nSDEErr = SE_stream_get_shape( hStream, (short) (iShapeColumn+1), 
+            nSDEErr = SE_stream_get_shape( hStream, (short) (iShapeColumn+1),
                                            hShape );
             if( nSDEErr != SE_SUCCESS )
                 poDS->IssueSDEError( nSDEErr, "SE_stream_get_shape" );
@@ -2025,7 +2024,7 @@ OGRFeature *OGRSDELayer::GetNextFeature()
 /* -------------------------------------------------------------------- */
 /*      Fetch the next record.                                          */
 /* -------------------------------------------------------------------- */
-    while( TRUE )
+    while( true )
     {
         nSDEErr = SE_stream_fetch( hStream );
         if( nSDEErr == SE_FINISHED )
@@ -2038,7 +2037,7 @@ OGRFeature *OGRSDELayer::GetNextFeature()
             poDS->IssueSDEError( nSDEErr, "SE_stream_fetch" );
             return NULL;
         }
-        
+
         m_nFeaturesRead++;
 
 /* -------------------------------------------------------------------- */
@@ -2057,7 +2056,7 @@ OGRFeature *OGRSDELayer::GetNextFeature()
 
             delete poFeature;
         }
-    }        
+    }
 }
 
 /************************************************************************/
@@ -2068,14 +2067,14 @@ OGRFeature *OGRSDELayer::GetFeature( GIntBig nFeatureId )
 
 {
     int nSDEErr;
-    
+
     if( iFIDColumn == -1 )
         return OGRLayer::GetFeature( nFeatureId );
 
 /* -------------------------------------------------------------------- */
 /*      Our direct row access will terminate any active queries.        */
 /* -------------------------------------------------------------------- */
-    ResetReading(); 
+    ResetReading();
 
 /* -------------------------------------------------------------------- */
 /*      Create stream, or reset it.                                     */
@@ -2087,9 +2086,9 @@ OGRFeature *OGRSDELayer::GetFeature( GIntBig nFeatureId )
 /*      We want to fetch all the columns, just like we normally         */
 /*      would for GetNextFeature().                                     */
 /* -------------------------------------------------------------------- */
-    nSDEErr = SE_stream_fetch_row( hStream, poFeatureDefn->GetName(), 
-                                   nFeatureId, 
-                                   CSLCount( papszAllColumns ), 
+    nSDEErr = SE_stream_fetch_row( hStream, poFeatureDefn->GetName(),
+                                   nFeatureId,
+                                   CSLCount( papszAllColumns ),
                                    (const char **) papszAllColumns );
     if( nSDEErr != SE_SUCCESS )
     {
@@ -2114,7 +2113,7 @@ OGRErr OGRSDELayer::ResetStream()
 
 {
     LONG                nSDEErr;
-    
+
     if( hStream == NULL )
     {
         nSDEErr = SE_stream_create( poDS->GetConnection(), &hStream );
@@ -2123,9 +2122,9 @@ OGRErr OGRSDELayer::ResetStream()
             return OGRERR_FAILURE;
         }
         if (poDS->IsOpenForUpdate() && poDS->UseVersionEdits()) {
-            nSDEErr = SE_stream_set_state(  hStream, 
-                                            poDS->GetNextState(), 
-                                            SE_NULL_STATE_ID, 
+            nSDEErr = SE_stream_set_state(  hStream,
+                                            poDS->GetNextState(),
+                                            SE_NULL_STATE_ID,
                                             SE_STATE_DIFF_NOCHECK );
             if( nSDEErr != SE_SUCCESS) {
                 poDS->IssueSDEError( nSDEErr, "SE_stream_set_state" );
@@ -2133,15 +2132,15 @@ OGRErr OGRSDELayer::ResetStream()
             }
         }
         else {
-            nSDEErr = SE_stream_set_state(  hStream, 
-                                            poDS->GetState(), 
-                                            poDS->GetState(), 
+            nSDEErr = SE_stream_set_state(  hStream,
+                                            poDS->GetState(),
+                                            poDS->GetState(),
                                             SE_STATE_DIFF_NOCHECK );
             if( nSDEErr != SE_SUCCESS) {
                 poDS->IssueSDEError( nSDEErr, "SE_stream_set_state" );
                 return OGRERR_FAILURE;
             }
-        }   
+        }
     }
     else
     {
@@ -2152,9 +2151,9 @@ OGRErr OGRSDELayer::ResetStream()
             return OGRERR_FAILURE;
         }
         if (poDS->IsOpenForUpdate() && poDS->UseVersionEdits()) {
-            nSDEErr = SE_stream_set_state(  hStream, 
-                                            poDS->GetNextState(), 
-                                            SE_NULL_STATE_ID, 
+            nSDEErr = SE_stream_set_state(  hStream,
+                                            poDS->GetNextState(),
+                                            SE_NULL_STATE_ID,
                                             SE_STATE_DIFF_NOCHECK );
             if( nSDEErr != SE_SUCCESS) {
                 poDS->IssueSDEError( nSDEErr, "SE_stream_set_state" );
@@ -2162,18 +2161,17 @@ OGRErr OGRSDELayer::ResetStream()
             }
         }
         else {
-            nSDEErr = SE_stream_set_state(  hStream, 
-                                            poDS->GetState(), 
-                                            poDS->GetState(), 
+            nSDEErr = SE_stream_set_state(  hStream,
+                                            poDS->GetState(),
+                                            poDS->GetState(),
                                             SE_STATE_DIFF_NOCHECK );
             if( nSDEErr != SE_SUCCESS) {
                 poDS->IssueSDEError( nSDEErr, "SE_stream_set_state" );
                 return OGRERR_FAILURE;
             }
-        }        
-
+        }
     }
-    
+
     return OGRERR_NONE;
 }
 
@@ -2196,7 +2194,7 @@ GIntBig OGRSDELayer::GetFeatureCount( int bForce )
 /*      features. The performance difference between this and manual    */
 /*      iteration is significant.                                       */
 /* -------------------------------------------------------------------- */
-    if( osAttributeFilter.empty() && m_poFilterGeom == NULL 
+    if( osAttributeFilter.empty() && m_poFilterGeom == NULL
         && NeedLayerInfo() )
     {
         SE_LAYER_STATS layerstats = {0};
@@ -2206,14 +2204,14 @@ GIntBig OGRSDELayer::GetFeatureCount( int bForce )
 
         szTableName[0] = '\0';
         szShapeColumn[0] = '\0';
-      
+
         nSDEErr = SE_layerinfo_get_spatial_column( hLayerInfo, szTableName, szShapeColumn );
         if( nSDEErr != SE_SUCCESS )
         {
             poDS->IssueSDEError( nSDEErr, "SE_layerinfo_get_spatial_column" );
             return -1;
         }
-      
+
         nSDEErr = SE_layer_get_statistics( poDS->GetConnection(), szTableName, szShapeColumn,
                                            &layerstats);
         if( nSDEErr != SE_SUCCESS )
@@ -2235,7 +2233,7 @@ GIntBig OGRSDELayer::GetFeatureCount( int bForce )
     if( !InstallQuery( TRUE ) )
         return -1;
 
-    for( nSDEErr = SE_stream_fetch( hStream ); 
+    for( nSDEErr = SE_stream_fetch( hStream );
          nSDEErr == SE_SUCCESS;
          nSDEErr = SE_stream_fetch( hStream ) )
     {
@@ -2247,7 +2245,7 @@ GIntBig OGRSDELayer::GetFeatureCount( int bForce )
         poDS->IssueSDEError( nSDEErr, "SE_stream_fetch" );
         return -1;
     }
-        
+
     ResetReading();
 
     return nFeatureCount;
@@ -2262,10 +2260,10 @@ OGRErr OGRSDELayer::GetExtent (OGREnvelope *psExtent, int bForce)
 {
     if( !NeedLayerInfo() )
         return OGRERR_FAILURE;
-    
+
     if (bForce) {
         return OGRLayer::GetExtent( psExtent, bForce );
-    }        
+    }
 
     SE_ENVELOPE  sEnvelope;
     int nSDEErr;
@@ -2294,17 +2292,17 @@ OGRErr OGRSDELayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
     SE_COLUMN_DEF       sColumnDef;
     OGRFieldDefn        oField( poFieldIn );
     LONG                nSDEErr;
-    
+
     CPLAssert( poFieldIn != NULL );
     CPLAssert( poFeatureDefn != NULL );
-    
+
     /* TODO: Do we need to launder column names in the same way that OCI/PG
      * do? If so, do we also need to launder table names? */
     strncpy( sColumnDef.column_name, oField.GetNameRef(), SE_MAX_COLUMN_LEN );
 
     sColumnDef.nulls_allowed = TRUE;
     sColumnDef.decimal_digits = 0;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Set the new column's SDE type. We intentionally use deprecated  */
 /*      SDE field types for backwards compatibility with 8.x servers    */
@@ -2317,10 +2315,10 @@ OGRErr OGRSDELayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
 
     else if( oField.GetType() == OFTString )
     {
-        const char *pszUseNSTRING = 
+        const char *pszUseNSTRING =
             CPLGetConfigOption( "OGR_SDE_USE_NSTRING", "FALSE" );
 
-        if( bUseNSTRING || CSLTestBoolean( pszUseNSTRING ) )
+        if( bUseNSTRING || CPLTestBool( pszUseNSTRING ) )
             sColumnDef.sde_type = SE_NSTRING_TYPE;
         else
             sColumnDef.sde_type = SE_STRING_TYPE;
@@ -2338,7 +2336,7 @@ OGRErr OGRSDELayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
                   "as SE_STRING_TYPE.",
                   oField.GetNameRef(),
                   OGRFieldDefn::GetFieldTypeName(oField.GetType()) );
-        
+
         sColumnDef.sde_type = SE_STRING_TYPE;
     }
 
@@ -2348,11 +2346,11 @@ OGRErr OGRSDELayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
                   "Can't create field %s with type %s on SDE layers.",
                   oField.GetNameRef(),
                   OGRFieldDefn::GetFieldTypeName(oField.GetType()) );
-        
+
         return OGRERR_FAILURE;
     }
 
-    
+
 /* -------------------------------------------------------------------- */
 /*      Set field width and precision                                   */
 /* -------------------------------------------------------------------- */
@@ -2384,7 +2382,7 @@ OGRErr OGRSDELayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
             sColumnDef.size = 0;
         }
     }
-    
+
 
 /* -------------------------------------------------------------------- */
 /*      Create the new field                                            */
@@ -2400,7 +2398,7 @@ OGRErr OGRSDELayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
 
     poFeatureDefn->AddFieldDefn( &oField );
     anFieldTypeMap.push_back( sColumnDef.sde_type );
-    
+
     return OGRERR_NONE;
 }
 
@@ -2412,15 +2410,15 @@ OGRErr OGRSDELayer::ISetFeature( OGRFeature *poFeature )
 
 {
     LONG                nSDEErr;
-    
+
     CPLAssert( poFeature != NULL );
     CPLAssert( poFeatureDefn != NULL );
-    
+
     if( !NeedLayerInfo() ) // Need hCoordRef, layerinfo shape types
         return OGRERR_FAILURE;
-    
+
     ResetReading();
-    
+
     if( ResetStream() != OGRERR_NONE )
         return OGRERR_FAILURE;
 
@@ -2429,7 +2427,7 @@ OGRErr OGRSDELayer::ISetFeature( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
     if( TranslateOGRRecord( poFeature, FALSE ) != OGRERR_NONE )
         return OGRERR_FAILURE; // TranslateOGRRecord() will report the error
-    
+
 /* -------------------------------------------------------------------- */
 /*      Execute the update                                              */
 /* -------------------------------------------------------------------- */
@@ -2439,7 +2437,7 @@ OGRErr OGRSDELayer::ISetFeature( OGRFeature *poFeature )
         poDS->IssueSDEError( nSDEErr, "SE_stream_execute" );
         return OGRERR_FAILURE;
     }
-    
+
     return OGRERR_NONE;
 }
 
@@ -2450,15 +2448,15 @@ OGRErr OGRSDELayer::ICreateFeature( OGRFeature *poFeature )
 
 {
     LONG                nSDEErr;
-    
+
     CPLAssert( poFeature != NULL );
     CPLAssert( poFeatureDefn != NULL );
-    
+
     if( !NeedLayerInfo() ) // Need hCoordRef, layerinfo shape types
         return OGRERR_FAILURE;
-    
+
     ResetReading();
-    
+
     if( ResetStream() != OGRERR_NONE )
         return OGRERR_FAILURE;
 
@@ -2467,7 +2465,7 @@ OGRErr OGRSDELayer::ICreateFeature( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
     if( TranslateOGRRecord( poFeature, TRUE ) != OGRERR_NONE )
         return OGRERR_FAILURE; // TranslateOGRRecord() will report the error
-    
+
 /* -------------------------------------------------------------------- */
 /*      Execute the insert                                              */
 /* -------------------------------------------------------------------- */
@@ -2494,10 +2492,10 @@ OGRErr OGRSDELayer::ICreateFeature( OGRFeature *poFeature )
             poDS->IssueSDEError( nSDEErr, "SE_stream_last_inserted_row_id" );
             return OGRERR_FAILURE;
         }
-        
+
         poFeature->SetFID( nLastFID );
     }
-    
+
     return OGRERR_NONE;
 }
 
@@ -2509,18 +2507,18 @@ OGRErr OGRSDELayer::DeleteFeature( GIntBig nFID )
 {
     LONG                nSDEErr;
     const char         *pszWhere;
-    
+
     ResetReading();
-    
+
     if( ResetStream() != OGRERR_NONE )
         return OGRERR_FAILURE;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Verify that this layer has a FID column                         */
-/* -------------------------------------------------------------------- */    
+/* -------------------------------------------------------------------- */
     if( iFIDColumn == -1 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Layer \"%s\": cannot DeleteFeature(%ld): the layer has no "
                   "FID column detected.", poFeatureDefn->GetName(), nFID );
         return OGRERR_FAILURE;
@@ -2530,10 +2528,10 @@ OGRErr OGRSDELayer::DeleteFeature( GIntBig nFID )
 /*      Perform the deletion                                            */
 /* -------------------------------------------------------------------- */
     pszWhere = CPLSPrintf( "%s = %ld", osFIDColumnName.c_str(), nFID );
-    
+
     nSDEErr = SE_stream_delete_from_table( hStream, poFeatureDefn->GetName(),
                                            pszWhere );
-    
+
     if( nSDEErr == SE_NO_ROWS_DELETED )
     {
         CPLError( CE_Warning, CPLE_AppDefined,
@@ -2546,7 +2544,7 @@ OGRErr OGRSDELayer::DeleteFeature( GIntBig nFID )
         poDS->IssueSDEError( nSDEErr, "SE_stream_delete_from_table" );
         return OGRERR_FAILURE;
     }
-    
+
     return OGRERR_NONE;
 }
 
@@ -2561,7 +2559,7 @@ int OGRSDELayer::TestCapability( const char * pszCap )
     if( EQUAL(pszCap,OLCRandomRead) )
         return iFIDColumn != -1;
 
-    else if( EQUAL(pszCap,OLCFastFeatureCount) 
+    else if( EQUAL(pszCap,OLCFastFeatureCount)
              && osAttributeFilter.empty()
              && m_poFilterGeom == NULL )
         return TRUE;
@@ -2571,23 +2569,23 @@ int OGRSDELayer::TestCapability( const char * pszCap )
 
     else if( EQUAL(pszCap,OLCFastGetExtent) )
         return TRUE;
-    
+
     else if( EQUAL(pszCap,OLCCreateField) )
         return bUpdateAccess;
 
     else if( EQUAL(pszCap,OLCSequentialWrite)
              || EQUAL(pszCap,OLCRandomWrite) )
         return bUpdateAccess;
-    
+
     else if( EQUAL(pszCap,OLCStringsAsUTF8) )
     {
         // We always treat NSTRING fields by translating to UTF8, but
         // we don't do anything to regular string fields so this is a
         // bit hard to answer simply.  Also, whether writes support UTF8
-        // depend on whether the field(s) were created as NSTRING fields. 
+        // depend on whether the field(s) were created as NSTRING fields.
         return TRUE;
     }
-    else 
+    else
         return FALSE;
 }
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/sdts/drv_sdts.html b/ogr/ogrsf_frmts/sdts/drv_sdts.html
index 860023a..7011f6f 100644
--- a/ogr/ogrsf_frmts/sdts/drv_sdts.html
+++ b/ogr/ogrsf_frmts/sdts/drv_sdts.html
@@ -7,7 +7,7 @@
 
 <h1>SDTS</h1>
 
-SDTS TVP (Topological Vector Profile) and Point Profile datasets are 
+SDTS TVP (Topological Vector Profile) and Point Profile datasets are
 supported for read access.  Each primary attribute, node (point), line
 and polygon module is treated as a distinct layer.<p>
 
@@ -21,7 +21,7 @@ systems defined in SDTS.<p>
 There is no update or creation support in the SDTS driver.<p>
 
 Note that in TVP datasets the polygon geometry is formed from the geometry
-in the line modules.  Primary attribute module attributes should be 
+in the line modules.  Primary attribute module attributes should be
 properly attached to their related node, line or polygon features, but can
 be accessed separately as their own layers.<p>
 
diff --git a/ogr/ogrsf_frmts/sdts/ogr_sdts.h b/ogr/ogrsf_frmts/sdts/ogr_sdts.h
index f14a7e9..1c3df5c 100644
--- a/ogr/ogrsf_frmts/sdts/ogr_sdts.h
+++ b/ogr/ogrsf_frmts/sdts/ogr_sdts.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_sdts.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogr_sdts.h 32177 2015-12-14 07:25:30Z goatbar $
  *
  * Project:  STS Translator
  * Purpose:  Definition of classes finding SDTS support into OGRDriver
@@ -28,8 +28,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_SDTS_H_INCLUDED
-#define _OGR_SDTS_H_INCLUDED
+#ifndef OGR_SDTS_H_INCLUDED
+#define OGR_SDTS_H_INCLUDED
 
 #include "sdts_al.h"
 #include "ogrsf_frmts.h"
@@ -54,7 +54,7 @@ class OGRSDTSLayer : public OGRLayer
 
     void                BuildPolygons();
     int                 bPolygonsBuilt;
-    
+
   public:
                         OGRSDTSLayer( SDTSTransfer *, int, OGRSDTSDataSource*);
                         ~OGRSDTSLayer();
@@ -63,11 +63,11 @@ class OGRSDTSLayer : public OGRLayer
     OGRFeature *        GetNextFeature();
 
 //    OGRFeature         *GetFeature( GIntBig nFeatureId );
-    
+
     OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
 
 //    GIntBig             GetFeatureCount( int );
-    
+
     int                 TestCapability( const char * );
 };
 
@@ -84,13 +84,13 @@ class OGRSDTSDataSource : public OGRDataSource
     OGRSDTSLayer        **papoLayers;
 
     OGRSpatialReference *poSRS;
-    
+
   public:
                         OGRSDTSDataSource();
                         ~OGRSDTSDataSource();
 
     int                 Open( const char * pszFilename, int bTestOpen );
-    
+
     const char          *GetName() { return pszName; }
     int                 GetLayerCount() { return nLayers; }
     OGRLayer            *GetLayer( int );
@@ -99,4 +99,4 @@ class OGRSDTSDataSource : public OGRDataSource
     OGRSpatialReference *GetSpatialRef() { return poSRS; }
 };
 
-#endif /* ndef _OGR_SDTS_H_INCLUDED */
+#endif /* ndef OGR_SDTS_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/sdts/ogrsdtsdatasource.cpp b/ogr/ogrsf_frmts/sdts/ogrsdtsdatasource.cpp
index 5a777af..d22bf87 100644
--- a/ogr/ogrsf_frmts/sdts/ogrsdtsdatasource.cpp
+++ b/ogr/ogrsf_frmts/sdts/ogrsdtsdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsdtsdatasource.cpp 13025 2007-11-25 18:03:46Z rouault $
+ * $Id: ogrsdtsdatasource.cpp 32177 2015-12-14 07:25:30Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Implements OGRSDTSDataSource class
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrsdtsdatasource.cpp 13025 2007-11-25 18:03:46Z rouault $");
+CPL_CVSID("$Id: ogrsdtsdatasource.cpp 32177 2015-12-14 07:25:30Z goatbar $");
 
 /************************************************************************/
 /*                          OGRSDTSDataSource()                          */
@@ -103,14 +103,14 @@ int OGRSDTSDataSource::Open( const char * pszFilename, int bTestOpen )
 
 {
     pszName = CPLStrdup( pszFilename );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Verify that the extension is DDF if we are testopening.         */
 /* -------------------------------------------------------------------- */
     if( bTestOpen && !(strlen(pszFilename) > 4 &&
         EQUAL(pszFilename+strlen(pszFilename)-4,".ddf")) )
         return FALSE;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Check a few bits of the header to see if it looks like an       */
 /*      SDTS file (really, if it looks like an ISO8211 file).           */
@@ -123,7 +123,7 @@ int OGRSDTSDataSource::Open( const char * pszFilename, int bTestOpen )
         fp = VSIFOpen( pszFilename, "rb" );
         if( fp == NULL )
             return FALSE;
-        
+
         if( VSIFRead( pachLeader, 1, 10, fp ) != 10
             || (pachLeader[5] != '1' && pachLeader[5] != '2'
                 && pachLeader[5] != '3' )
@@ -146,7 +146,7 @@ int OGRSDTSDataSource::Open( const char * pszFilename, int bTestOpen )
     {
         delete poTransfer;
         poTransfer = NULL;
-        
+
         return FALSE;
     }
 
@@ -165,14 +165,14 @@ int OGRSDTSDataSource::Open( const char * pszFilename, int bTestOpen )
     if( EQUAL(poXREF->pszDatum,"NAS") )
         poSRS->SetGeogCS("NAD27", "North_American_Datum_1927",
                          "Clarke 1866", 6378206.4, 294.978698213901 );
-    
+
     else if( EQUAL(poXREF->pszDatum,"NAX") )
         poSRS->SetGeogCS("NAD83", "North_American_Datum_1983",
                          "GRS 1980", 6378137, 298.257222101 );
-    
+
     else if( EQUAL(poXREF->pszDatum,"WGC") )
         poSRS->SetGeogCS("WGS 72", "WGS_1972", "NWL 10D", 6378135, 298.26 );
-    
+
     else if( EQUAL(poXREF->pszDatum,"WGE") )
         poSRS->SetGeogCS("WGS 84", "WGS_1984",
                          "WGS 84", 6378137, 298.257223563 );
@@ -189,19 +189,19 @@ int OGRSDTSDataSource::Open( const char * pszFilename, int bTestOpen )
     for( int iLayer = 0; iLayer < poTransfer->GetLayerCount(); iLayer++ )
     {
         SDTSIndexedReader       *poReader;
-        
+
         if( poTransfer->GetLayerType( iLayer ) == SLTRaster )
             continue;
 
         poReader = poTransfer->GetLayerIndexedReader( iLayer );
         if( poReader == NULL )
             continue;
-        
+
         papoLayers = (OGRSDTSLayer **)
             CPLRealloc( papoLayers, sizeof(void*) * ++nLayers );
         papoLayers[nLayers-1] = new OGRSDTSLayer( poTransfer, iLayer, this );
     }
-    
+
     return TRUE;
 }
 
diff --git a/ogr/ogrsf_frmts/sdts/ogrsdtsdriver.cpp b/ogr/ogrsf_frmts/sdts/ogrsdtsdriver.cpp
index 098ddc5..0ad918e 100644
--- a/ogr/ogrsf_frmts/sdts/ogrsdtsdriver.cpp
+++ b/ogr/ogrsf_frmts/sdts/ogrsdtsdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsdtsdriver.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogrsdtsdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Implements OGRSDTSDriver
@@ -30,7 +30,7 @@
 #include "ogr_sdts.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrsdtsdriver.cpp 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: ogrsdtsdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
 
 /************************************************************************/
 /*                                Open()                                */
@@ -66,7 +66,7 @@ static GDALDataset *OGRSDTSDriverOpen( GDALOpenInfo* poOpenInfo )
         delete poDS;
         poDS = NULL;
     }
-    
+
     return poDS;
 }
 
@@ -77,21 +77,17 @@ static GDALDataset *OGRSDTSDriverOpen( GDALOpenInfo* poOpenInfo )
 void RegisterOGRSDTS()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "OGR_SDTS" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "OGR_SDTS" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "OGR_SDTS" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "SDTS" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_sdts.html" );
+    poDriver->SetDescription( "OGR_SDTS" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "SDTS" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_sdts.html" );
 
-        poDriver->pfnOpen = OGRSDTSDriverOpen;
+    poDriver->pfnOpen = OGRSDTSDriverOpen;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/sdts/ogrsdtslayer.cpp b/ogr/ogrsf_frmts/sdts/ogrsdtslayer.cpp
index cfac5af..5158f17 100644
--- a/ogr/ogrsf_frmts/sdts/ogrsdtslayer.cpp
+++ b/ogr/ogrsf_frmts/sdts/ogrsdtslayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsdtslayer.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogrsdtslayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  SDTSReader
  * Purpose:  Implements OGRSDTSLayer class.
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrsdtslayer.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogrsdtslayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                            OGRSDTSLayer()                            */
@@ -41,8 +41,8 @@ CPL_CVSID("$Id: ogrsdtslayer.cpp 27745 2014-09-27 16:38:57Z goatbar $");
 /************************************************************************/
 
 OGRSDTSLayer::OGRSDTSLayer( SDTSTransfer * poTransferIn, int iLayerIn,
-                            OGRSDTSDataSource * poDSIn )
-
+                            OGRSDTSDataSource * poDSIn ) :
+    bPolygonsBuilt(FALSE)
 {
     poDS = poDSIn;
 
@@ -55,7 +55,7 @@ OGRSDTSLayer::OGRSDTSLayer( SDTSTransfer * poTransferIn, int iLayerIn,
 /*      Define the feature.                                             */
 /* -------------------------------------------------------------------- */
     int         iCATDEntry = poTransfer->GetLayerCATDEntry( iLayer );
-    
+
     poFeatureDefn =
         new OGRFeatureDefn(poTransfer->GetCATD()->GetEntryModule(iCATDEntry));
     SetDescription( poFeatureDefn->GetName() );
@@ -92,11 +92,11 @@ OGRSDTSLayer::OGRSDTSLayer( SDTSTransfer * poTransferIn, int iLayerIn,
 /*      Add schema from referenced attribute records.                   */
 /* -------------------------------------------------------------------- */
     char        **papszATIDRefs = NULL;
-    
+
     if( poTransfer->GetLayerType(iLayer) != SLTAttr )
         papszATIDRefs = poReader->ScanModuleReferences();
     else
-        papszATIDRefs = CSLAddString( papszATIDRefs, 
+        papszATIDRefs = CSLAddString( papszATIDRefs,
                                       poTransfer->GetCATD()->GetEntryModule(iCATDEntry) );
 
     for( int iTable = 0;
@@ -105,14 +105,16 @@ OGRSDTSLayer::OGRSDTSLayer( SDTSTransfer * poTransferIn, int iLayerIn,
     {
         SDTSAttrReader  *poAttrReader;
         DDFFieldDefn    *poFDefn;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Get the attribute table reader, and the associated user         */
 /*      attribute field.                                                */
 /* -------------------------------------------------------------------- */
+        int nLayerIdx = poTransfer->FindLayer( papszATIDRefs[iTable] );
+        if( nLayerIdx < 0 )
+            continue;
         poAttrReader = (SDTSAttrReader *)
-            poTransfer->GetLayerIndexedReader(
-                poTransfer->FindLayer( papszATIDRefs[iTable] ) );
+            poTransfer->GetLayerIndexedReader(nLayerIdx);
 
         if( poAttrReader == NULL )
             continue;
@@ -122,7 +124,7 @@ OGRSDTSLayer::OGRSDTSLayer( SDTSTransfer * poTransferIn, int iLayerIn,
             poFDefn = poAttrReader->GetModule()->FindFieldDefn( "ATTS" );
         if( poFDefn == NULL )
             continue;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Process each user subfield on the attribute table into an       */
 /*      OGR field definition.                                           */
@@ -139,7 +141,7 @@ OGRSDTSLayer::OGRSDTSLayer( SDTSTransfer * poTransferIn, int iLayerIn,
                                                       poSFDefn->GetName() ) );
             else
                 pszFieldName = CPLStrdup( poSFDefn->GetName() );
-            
+
             switch( poSFDefn->GetType() )
             {
               case DDFString:
@@ -181,7 +183,7 @@ OGRSDTSLayer::OGRSDTSLayer( SDTSTransfer * poTransferIn, int iLayerIn,
             }
 
             CPLFree( pszFieldName );
-            
+
         } /* next iSF (subfield) */
     } /* next iTable */
     CSLDestroy( papszATIDRefs );
@@ -197,7 +199,7 @@ OGRSDTSLayer::~OGRSDTSLayer()
     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     {
         CPLDebug( "SDTS", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
+                  (int) m_nFeaturesRead,
                   poFeatureDefn->GetName() );
     }
 
@@ -321,7 +323,7 @@ OGRFeature * OGRSDTSLayer::GetNextUnfilteredFeature()
       case SLTPoint:
       {
           SDTSRawPoint  *poPoint = (SDTSRawPoint *) poSDTSFeature;
-          
+
           poFeature->SetGeometryDirectly( new OGRPoint( poPoint->dfX,
                                                         poPoint->dfY,
                                                         poPoint->dfZ ) );
@@ -383,9 +385,9 @@ OGRFeature * OGRSDTSLayer::GetNextUnfilteredFeature()
 /*      Set attributes for any indicated attribute records.             */
 /* -------------------------------------------------------------------- */
     int         iAttrRecord;
-    
-    for( iAttrRecord = 0; 
-         iAttrRecord < poSDTSFeature->nAttributes; 
+
+    for( iAttrRecord = 0;
+         iAttrRecord < poSDTSFeature->nAttributes;
          iAttrRecord++)
     {
         DDFField        *poSR;
@@ -401,10 +403,10 @@ OGRFeature * OGRSDTSLayer::GetNextUnfilteredFeature()
 /* -------------------------------------------------------------------- */
     if( poTransfer->GetLayerType(iLayer) == SLTAttr )
     {
-        AssignAttrRecordToFeature( poFeature, poTransfer, 
+        AssignAttrRecordToFeature( poFeature, poTransfer,
                                    ((SDTSAttrRecord *) poSDTSFeature)->poATTR);
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Translate the record id.                                        */
 /* -------------------------------------------------------------------- */
@@ -429,12 +431,12 @@ OGRFeature *OGRSDTSLayer::GetNextFeature()
 
 {
     OGRFeature  *poFeature = NULL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Read features till we find one that satisfies our current       */
 /*      spatial criteria.                                               */
 /* -------------------------------------------------------------------- */
-    while( TRUE )
+    while( true )
     {
         poFeature = GetNextUnfilteredFeature();
         if( poFeature == NULL )
@@ -462,7 +464,7 @@ int OGRSDTSLayer::TestCapability( const char * pszCap )
     if( EQUAL(pszCap,OLCRandomRead) )
         return FALSE;
 
-    else if( EQUAL(pszCap,OLCSequentialWrite) 
+    else if( EQUAL(pszCap,OLCSequentialWrite)
              || EQUAL(pszCap,OLCRandomWrite) )
         return FALSE;
 
@@ -472,6 +474,6 @@ int OGRSDTSLayer::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCFastSpatialFilter) )
         return FALSE;
 
-    else 
+    else
         return FALSE;
 }
diff --git a/ogr/ogrsf_frmts/segukooa/ogr_segukooa.h b/ogr/ogrsf_frmts/segukooa/ogr_segukooa.h
index c422018..c00352d 100644
--- a/ogr/ogrsf_frmts/segukooa/ogr_segukooa.h
+++ b/ogr/ogrsf_frmts/segukooa/ogr_segukooa.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_segukooa.h 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogr_segukooa.h 31777 2015-11-26 14:14:41Z rouault $
  *
  * Project:  SEG-P1 / UKOOA P1-90 Translator
  * Purpose:  Definition of classes for OGR SEG-P1 / UKOOA P1-90 driver.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_SEGUKOOA_H_INCLUDED
-#define _OGR_SEGUKOOA_H_INCLUDED
+#ifndef OGR_SEGUKOOA_H_INCLUDED
+#define OGR_SEGUKOOA_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 
@@ -154,4 +154,4 @@ class OGRSEGUKOOADataSource : public OGRDataSource
     virtual int                 TestCapability( const char * );
 };
 
-#endif /* ndef _OGR_SEGUKOOA_H_INCLUDED */
+#endif /* ndef OGR_SEGUKOOA_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/segukooa/ogrsegukooadatasource.cpp b/ogr/ogrsf_frmts/segukooa/ogrsegukooadatasource.cpp
index c8fbbca..330e577 100644
--- a/ogr/ogrsf_frmts/segukooa/ogrsegukooadatasource.cpp
+++ b/ogr/ogrsf_frmts/segukooa/ogrsegukooadatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsegukooadatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogrsegukooadatasource.cpp 31122 2015-10-25 09:28:57Z rouault $
  *
  * Project:  SEG-P1 / UKOOA P1-90 Translator
  * Purpose:  Implements OGRSEGUKOOADataSource class
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrsegukooadatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogrsegukooadatasource.cpp 31122 2015-10-25 09:28:57Z rouault $");
 
 /************************************************************************/
 /*                        OGRSEGUKOOADataSource()                       */
@@ -112,7 +112,7 @@ int OGRSEGUKOOADataSource::Open( const char * pszFilename )
 //      Does this appear to be a UKOOA P1/90 file?
 // --------------------------------------------------------------------
 
-    if (strncmp(pszLine, "H0100 ", 6) == 0)
+    if (STARTS_WITH(pszLine, "H0100 "))
     {
         VSIFSeekL( fp, 0, SEEK_SET );
 
diff --git a/ogr/ogrsf_frmts/segukooa/ogrsegukooadriver.cpp b/ogr/ogrsf_frmts/segukooa/ogrsegukooadriver.cpp
index 266d75d..9bd5268 100644
--- a/ogr/ogrsf_frmts/segukooa/ogrsegukooadriver.cpp
+++ b/ogr/ogrsf_frmts/segukooa/ogrsegukooadriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsegukooadriver.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogrsegukooadriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  SEG-P1 / UKOOA P1-90 Translator
  * Purpose:  Implements OGRSEGUKOOADriver.
@@ -30,7 +30,7 @@
 #include "ogr_segukooa.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrsegukooadriver.cpp 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: ogrsegukooadriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
 
 extern "C" void RegisterOGRSEGUKOOA();
 
@@ -65,24 +65,19 @@ static GDALDataset *OGRSEGUKOOADriverOpen( GDALOpenInfo* poOpenInfo )
 void RegisterOGRSEGUKOOA()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "SEGUKOOA" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "SEGUKOOA" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-
-        poDriver->SetDescription( "SEGUKOOA" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "SEG-P1 / UKOOA P1/90" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_segukooa.html" );
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetDescription( "SEGUKOOA" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "SEG-P1 / UKOOA P1/90" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_segukooa.html" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = OGRSEGUKOOADriverOpen;
+    poDriver->pfnOpen = OGRSEGUKOOADriverOpen;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
 
diff --git a/ogr/ogrsf_frmts/segukooa/ogrsegukooalayer.cpp b/ogr/ogrsf_frmts/segukooa/ogrsegukooalayer.cpp
index 4c4ebcd..db888cd 100644
--- a/ogr/ogrsf_frmts/segukooa/ogrsegukooalayer.cpp
+++ b/ogr/ogrsf_frmts/segukooa/ogrsegukooalayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsegukooalayer.cpp 28849 2015-04-05 14:05:18Z goatbar $
+ * $Id: ogrsegukooalayer.cpp 32982 2016-01-14 16:53:57Z goatbar $
  *
  * Project:  SEG-P1 / UKOOA P1-90 Translator
  * Purpose:  Implements OGRUKOOAP190Layer class.
@@ -33,7 +33,7 @@
 #include "ogr_p.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ogrsegukooalayer.cpp 28849 2015-04-05 14:05:18Z goatbar $");
+CPL_CVSID("$Id: ogrsegukooalayer.cpp 32982 2016-01-14 16:53:57Z goatbar $");
 
 /************************************************************************/
 /*                            ExtractField()                            */
@@ -53,7 +53,7 @@ OGRFeature *OGRSEGUKOOABaseLayer::GetNextFeature()
 {
     OGRFeature  *poFeature;
 
-    while(TRUE)
+    while( true )
     {
         poFeature = GetNextRawFeature();
         if (poFeature == NULL)
@@ -75,11 +75,13 @@ OGRFeature *OGRSEGUKOOABaseLayer::GetNextFeature()
 /*                         OGRUKOOAP190Layer()                          */
 /************************************************************************/
 
+namespace {
 typedef struct
 {
     const char*     pszName;
     OGRFieldType    eType;
 } FieldDesc;
+} /* end of anonymous namespace */
 
 static const FieldDesc UKOOAP190Fields[] =
 {
@@ -113,10 +115,10 @@ static const FieldDesc UKOOAP190Fields[] =
 #define FIELD_DATETIME      12
 
 OGRUKOOAP190Layer::OGRUKOOAP190Layer( const char* pszFilename,
-                                      VSILFILE* fp )
+                                      VSILFILE* fpIn )
 
 {
-    this->fp = fp;
+    this->fp = fpIn;
     nNextFID = 0;
     bEOF = FALSE;
     poSRS = NULL;
@@ -135,7 +137,7 @@ OGRUKOOAP190Layer::OGRUKOOAP190Layer( const char* pszFilename,
     }
 
     bUseEastingNorthingAsGeometry =
-        CSLTestBoolean(CPLGetConfigOption("UKOOAP190_USE_EASTING_NORTHING", "NO"));
+        CPLTestBool(CPLGetConfigOption("UKOOAP190_USE_EASTING_NORTHING", "NO"));
 
     ParseHeaders();
 
@@ -163,15 +165,15 @@ OGRUKOOAP190Layer::~OGRUKOOAP190Layer()
 
 void OGRUKOOAP190Layer::ParseHeaders()
 {
-    while(TRUE)
+    while( true )
     {
         const char* pszLine = CPLReadLine2L(fp,81,NULL);
-        if (pszLine == NULL || EQUALN(pszLine, "EOF", 3))
+        if (pszLine == NULL || STARTS_WITH_CI(pszLine, "EOF"))
         {
             break;
         }
 
-        int nLineLen = strlen(pszLine);
+        int nLineLen = static_cast<int>(strlen(pszLine));
         while(nLineLen > 0 && pszLine[nLineLen-1] == ' ')
         {
             ((char*)pszLine)[nLineLen-1] = '\0';
@@ -185,21 +187,21 @@ void OGRUKOOAP190Layer::ParseHeaders()
             continue;
 
         if (!bUseEastingNorthingAsGeometry &&
-            strncmp(pszLine, "H1500", 5) == 0 && poSRS == NULL)
+            STARTS_WITH(pszLine, "H1500") && poSRS == NULL)
         {
-            if (strncmp(pszLine + 33 - 1, "WGS84", 5) == 0 ||
-                strncmp(pszLine + 33 - 1, "WGS-84", 6) == 0)
+            if (STARTS_WITH(pszLine + 33 - 1, "WGS84") ||
+                STARTS_WITH(pszLine + 33 - 1, "WGS-84"))
             {
                 poSRS = new OGRSpatialReference(SRS_WKT_WGS84);
             }
-            else if (strncmp(pszLine + 33 - 1, "WGS72", 5) == 0)
+            else if (STARTS_WITH(pszLine + 33 - 1, "WGS72"))
             {
                 poSRS = new OGRSpatialReference();
                 poSRS->SetFromUserInput("WGS72");
             }
         }
         else if (!bUseEastingNorthingAsGeometry &&
-                 strncmp(pszLine, "H1501", 5) == 0 && poSRS != NULL &&
+                 STARTS_WITH(pszLine, "H1501") && poSRS != NULL &&
                  nLineLen >= 32 + 6 * 6 + 10)
         {
             char aszParams[6][6+1];
@@ -218,7 +220,7 @@ void OGRUKOOAP190Layer::ParseHeaders()
                               CPLAtof(aszParams[5]),
                               CPLAtof(szZ));
         }
-        else if (strncmp(pszLine, "H0200", 5) == 0)
+        else if (STARTS_WITH(pszLine, "H0200"))
         {
             char** papszTokens = CSLTokenizeString(pszLine + 33 - 1);
             for(int i = 0; papszTokens[i] != NULL; i++)
@@ -268,16 +270,16 @@ OGRFeature *OGRUKOOAP190Layer::GetNextRawFeature()
 
     const char* pszLine;
 
-    while(TRUE)
+    while( true )
     {
         pszLine = CPLReadLine2L(fp,81,NULL);
-        if (pszLine == NULL || EQUALN(pszLine, "EOF", 3))
+        if (pszLine == NULL || STARTS_WITH_CI(pszLine, "EOF"))
         {
             bEOF = TRUE;
             return NULL;
         }
 
-        int nLineLen = strlen(pszLine);
+        int nLineLen = static_cast<int>(strlen(pszLine));
         while(nLineLen > 0 && pszLine[nLineLen-1] == ' ')
         {
             ((char*)pszLine)[nLineLen-1] = '\0';
@@ -401,7 +403,7 @@ OGRFeature *OGRUKOOAP190Layer::GetNextRawFeature()
             ExtractField(szH, pszLine, 74-1, 2);
             ExtractField(szM, pszLine, 74-1+2, 2);
             ExtractField(szS, pszLine, 74-1+2+2, 2);
-            poFeature->SetField(FIELD_TIME, 0, 0, 0, atoi(szH), atoi(szM), atoi(szS) );
+            poFeature->SetField(FIELD_TIME, 0, 0, 0, atoi(szH), atoi(szM), static_cast<float>(atoi(szS)) );
 
             if (nYear != 0)
             {
@@ -425,7 +427,7 @@ OGRFeature *OGRUKOOAP190Layer::GetNextRawFeature()
                     nMonth ++;
 
                     poFeature->SetField(FIELD_DATETIME, nYear, nMonth, nDayOfMonth,
-                                        atoi(szH), atoi(szM), atoi(szS) );
+                                        atoi(szH), atoi(szM), static_cast<float>(atoi(szS)) );
                 }
 
             }
@@ -470,12 +472,12 @@ static const FieldDesc SEGP1Fields[] =
 #define SEGP1_FIELD_DATETIME      10
 
 OGRSEGP1Layer::OGRSEGP1Layer( const char* pszFilename,
-                              VSILFILE* fp,
-                              int nLatitudeCol )
+                              VSILFILE* fpIn,
+                              int nLatitudeColIn )
 
 {
-    this->fp = fp;
-    this->nLatitudeCol = nLatitudeCol;
+    this->fp = fpIn;
+    this->nLatitudeCol = nLatitudeColIn;
     nNextFID = 0;
     bEOF = FALSE;
     poSRS = NULL;
@@ -493,7 +495,7 @@ OGRSEGP1Layer::OGRSEGP1Layer( const char* pszFilename,
     }
 
     bUseEastingNorthingAsGeometry =
-        CSLTestBoolean(CPLGetConfigOption("SEGP1_USE_EASTING_NORTHING", "NO"));
+        CPLTestBool(CPLGetConfigOption("SEGP1_USE_EASTING_NORTHING", "NO"));
 
     ResetReading();
 }
@@ -547,16 +549,16 @@ OGRFeature *OGRSEGP1Layer::GetNextRawFeature()
         return NULL;
 
     const char* pszLine = NULL;
-    while(TRUE)
+    while( true )
     {
         pszLine = CPLReadLine2L(fp,81,NULL);
-        if (pszLine == NULL || EQUALN(pszLine, "EOF", 3))
+        if (pszLine == NULL || STARTS_WITH_CI(pszLine, "EOF"))
         {
             bEOF = TRUE;
             return NULL;
         }
 
-        int nLineLen = strlen(pszLine);
+        int nLineLen = static_cast<int>(strlen(pszLine));
         while(nLineLen > 0 && pszLine[nLineLen-1] == ' ')
         {
             ((char*)pszLine)[nLineLen-1] = '\0';
@@ -565,7 +567,7 @@ OGRFeature *OGRSEGP1Layer::GetNextRawFeature()
 
         char* pszExpandedLine = ExpandTabs(pszLine);
         pszLine = pszExpandedLine;
-        nLineLen = strlen(pszLine);
+        nLineLen = static_cast<int>(strlen(pszLine));
 
         OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
         poFeature->SetFID(nNextFID ++);
@@ -697,7 +699,7 @@ char* OGRSEGP1Layer::ExpandTabs(const char* pszLine)
 
 int OGRSEGP1Layer::DetectLatitudeColumn(const char* pszLine)
 {
-    int nLen = strlen(pszLine);
+    int nLen = static_cast<int>(strlen(pszLine));
     if (nLen >= 45 && pszLine[0] == ' ' &&
         (pszLine[35-1] == 'N' || pszLine[35-1] == 'S') &&
         (pszLine[45-1] == 'E' || pszLine[45-1] == 'W'))
@@ -719,10 +721,11 @@ int OGRSEGP1Layer::DetectLatitudeColumn(const char* pszLine)
 /************************************************************************/
 
 OGRSEGUKOOALineLayer::OGRSEGUKOOALineLayer(const char* pszFilename,
-                                           OGRLayer *poBaseLayer)
+                                           OGRLayer *poBaseLayerIn)
 {
     nNextFID = 0;
     bEOF = FALSE;
+    this->poBaseLayer = poBaseLayerIn;
 
     poFeatureDefn = new OGRFeatureDefn( CPLSPrintf("%s_lines",
                                                    CPLGetBasename(pszFilename)) );
@@ -733,7 +736,6 @@ OGRSEGUKOOALineLayer::OGRSEGUKOOALineLayer(const char* pszFilename,
     OGRFieldDefn    oField( "LINENAME", OFTString );
     poFeatureDefn->AddFieldDefn( &oField );
 
-    this->poBaseLayer = poBaseLayer;
     poNextBaseFeature = NULL;
 }
 
@@ -790,6 +792,7 @@ OGRFeature *OGRSEGUKOOALineLayer::GetNextRawFeature()
                 strcmp(poFeature->GetFieldAsString(0),
                     poNextBaseFeature->GetFieldAsString(0)) != 0)
             {
+                poFeature->SetGeometryDirectly(poLS);
                 return poFeature;
             }
 
@@ -807,7 +810,6 @@ OGRFeature *OGRSEGUKOOALineLayer::GetNextRawFeature()
                     if (poBaseLayer->GetSpatialRef())
                         poLS->assignSpatialReference(
                                     poBaseLayer->GetSpatialRef());
-                    poFeature->SetGeometryDirectly(poLS);
                 }
 
                 poLS->addPoint(poPoint);
@@ -819,5 +821,7 @@ OGRFeature *OGRSEGUKOOALineLayer::GetNextRawFeature()
     }
 
     bEOF = TRUE;
+    if( poFeature )
+        poFeature->SetGeometryDirectly(poLS);
     return poFeature;
 }
diff --git a/ogr/ogrsf_frmts/segy/ogr_segy.h b/ogr/ogrsf_frmts/segy/ogr_segy.h
index 6e495ea..97981f7 100644
--- a/ogr/ogrsf_frmts/segy/ogr_segy.h
+++ b/ogr/ogrsf_frmts/segy/ogr_segy.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_segy.h 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogr_segy.h 31777 2015-11-26 14:14:41Z rouault $
  *
  * Project:  SEG-Y Translator
  * Purpose:  Definition of classes for OGR SEG-Y driver.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_SEGY_H_INCLUDED
-#define _OGR_SEGY_H_INCLUDED
+#ifndef OGR_SEGY_H_INCLUDED
+#define OGR_SEGY_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 
@@ -155,4 +155,4 @@ class OGRSEGYDataSource : public OGRDataSource
     virtual int                 TestCapability( const char * );
 };
 
-#endif /* ndef _OGR_SEGY_H_INCLUDED */
+#endif /* ndef OGR_SEGY_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/segy/ogrsegydriver.cpp b/ogr/ogrsf_frmts/segy/ogrsegydriver.cpp
index 0a95620..e819a91 100644
--- a/ogr/ogrsf_frmts/segy/ogrsegydriver.cpp
+++ b/ogr/ogrsf_frmts/segy/ogrsegydriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsegydriver.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogrsegydriver.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  SEG-Y Translator
  * Purpose:  Implements OGRSEGYDriver class.
@@ -30,7 +30,7 @@
 #include "ogr_segy.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrsegydriver.cpp 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: ogrsegydriver.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                           EBCDICToASCII                              */
@@ -49,7 +49,7 @@ static const GByte EBCDICToASCII[] =
 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x5C, 0x00, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -69,7 +69,7 @@ static GDALDataset *OGRSEGYDriverOpen( GDALOpenInfo* poOpenInfo )
     {
         return NULL;
     }
-    if( EQUALN((const char*)poOpenInfo->pabyHeader, "%PDF", 4))
+    if( STARTS_WITH_CI((const char*)poOpenInfo->pabyHeader, "%PDF"))
     {
         return NULL;
     }
@@ -103,7 +103,7 @@ static GDALDataset *OGRSEGYDriverOpen( GDALOpenInfo* poOpenInfo )
         if (k == 1)
         {
             CPLFree(pabyASCIITextHeader);
-            return FALSE;
+            return NULL;
         }
     }
 
@@ -162,24 +162,18 @@ static GDALDataset *OGRSEGYDriverOpen( GDALOpenInfo* poOpenInfo )
 void RegisterOGRSEGY()
 
 {
-    GDALDriver  *poDriver;
-
-    if( GDALGetDriverByName( "SEGY" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    if( GDALGetDriverByName( "SEGY" ) != NULL )
+        return;
 
-        poDriver->SetDescription( "SEGY" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "SEG-Y" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_segy.html" );
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetDescription( "SEGY" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "SEG-Y" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_segy.html" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = OGRSEGYDriverOpen;
+    poDriver->pfnOpen = OGRSEGYDriverOpen;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
-
diff --git a/ogr/ogrsf_frmts/segy/ogrsegylayer.cpp b/ogr/ogrsf_frmts/segy/ogrsegylayer.cpp
index 0182446..e4ebbb7 100644
--- a/ogr/ogrsf_frmts/segy/ogrsegylayer.cpp
+++ b/ogr/ogrsf_frmts/segy/ogrsegylayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsegylayer.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogrsegylayer.cpp 32011 2015-12-06 10:19:18Z rouault $
  *
  * Project:  SEG-Y Translator
  * Purpose:  Implements OGRSEGYLayer class.
@@ -33,7 +33,7 @@
 #include "ogr_p.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ogrsegylayer.cpp 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: ogrsegylayer.cpp 32011 2015-12-06 10:19:18Z rouault $");
 
 #define DT_IBM_4BYTES_FP         1
 #define DT_4BYTES_INT            2
@@ -226,11 +226,11 @@ static float SEGYReadMSBFloat32(const GByte* pabyVal)
 
 
 OGRSEGYLayer::OGRSEGYLayer( const char* pszFilename,
-                            VSILFILE* fp,
+                            VSILFILE* fpIn,
                             SEGYBinaryFileHeader* psBFH )
 
 {
-    this->fp = fp;
+    this->fp = fpIn;
     nNextFID = 0;
     bEOF = FALSE;
     memcpy(&sBFH, psBFH, sizeof(sBFH));
@@ -309,7 +309,7 @@ OGRFeature *OGRSEGYLayer::GetNextFeature()
 {
     OGRFeature  *poFeature;
 
-    while(TRUE)
+    while( true )
     {
         poFeature = GetNextRawFeature();
         if (poFeature == NULL)
@@ -573,8 +573,8 @@ OGRFeature *OGRSEGYLayer::GetNextRawFeature()
     }
 #endif
 
-    GByte* pabyData = (GByte*) VSIMalloc( nDataSize * nSamples );
-    double* padfValues = (double*) VSICalloc( nSamples, sizeof(double) );
+    GByte* pabyData = (GByte*) VSI_MALLOC_VERBOSE( nDataSize * nSamples );
+    double* padfValues = (double*) VSI_CALLOC_VERBOSE( nSamples, sizeof(double) );
     if (pabyData == NULL || padfValues == NULL)
     {
         VSIFSeekL( fp, nDataSize * nSamples, SEEK_CUR );
@@ -857,7 +857,7 @@ OGRFeature *OGRSEGYHeaderLayer::GetNextFeature()
 {
     OGRFeature  *poFeature;
 
-    while(TRUE)
+    while( true )
     {
         poFeature = GetNextRawFeature();
         if (poFeature == NULL)
diff --git a/ogr/ogrsf_frmts/selafin/GNUmakefile b/ogr/ogrsf_frmts/selafin/GNUmakefile
index 7344dbe..23b4f57 100644
--- a/ogr/ogrsf_frmts/selafin/GNUmakefile
+++ b/ogr/ogrsf_frmts/selafin/GNUmakefile
@@ -6,6 +6,9 @@ OBJ	=	ogrselafindriver.o ogrselafindatasource.o ogrselafinlayer.o io_selafin.o
 
 CPPFLAGS	:=	-I.. -I../..  $(CPPFLAGS) 
 
+# To pass -Wextra -Werror, enable this next line:
+# CPPFLAGS += -Wno-missing-field-initializers
+
 default:	$(O_OBJ:.o=.$(OBJ_EXT))
 
 clean:
diff --git a/ogr/ogrsf_frmts/selafin/drv_selafin.html b/ogr/ogrsf_frmts/selafin/drv_selafin.html
index b6bf8bf..d6579ff 100644
--- a/ogr/ogrsf_frmts/selafin/drv_selafin.html
+++ b/ogr/ogrsf_frmts/selafin/drv_selafin.html
@@ -36,7 +36,7 @@
 </ul>
 </p>
 
-<p>Files which match those two criterias are considered to be Selafin files and the driver will report it has opened them successfully.</p>
+<p>Files which match those two criteria are considered to be Selafin files and the driver will report it has opened them successfully.</p>
 
 <h2><a id="format">Format</a></h2>
 
@@ -171,7 +171,7 @@
 <h2>Layer filtering specification</h2>
 <p>As a single Selafin files may hold millions of layers, and the user is generally interested in only a few of them, the driver supports syntactic sugar to filter the layers before they are read.</p>
 
-<p>When the datasource is specified, it may be followed immediatly by a <em>layer filtering specification.</em>, as in <tt>Results[0:10]</tt>. The effects of the layer filtering specification is to indicate which time steps shall be loaded from all Selafin files.</p>
+<p>When the datasource is specified, it may be followed immediately by a <em>layer filtering specification.</em>, as in <tt>Results[0:10]</tt>. The effects of the layer filtering specification is to indicate which time steps shall be loaded from all Selafin files.</p>
 
 <p>The layer filtering specification is a comma-separated sequence of range specifications, delimited by square brackets and maybe preceded by the character 'e' or 'p'. The effect of characters 'e' and 'p' is to select respectively either only elements or only nodes. If no character is added, both nodes and elements are selected.
 Each range specification is:
@@ -207,7 +207,7 @@ Numbers can also be negative. In this case, they are counted from the end of the
 	<dd>Date of the time step relative to the starting date of the simulation (see <a href="#DCO">Datasource creation options</a>). This is a single floating-point value giving the number of seconds since the starting date.</dd>
 </dl>
 
-<p>An example of datasource creation option is: <tt>-lco DATE=24000</tt>. 
+<p>An example of datasource creation option is: <tt>-lco DATE=24000</tt>.
 
 <h2>Notes about the creation and the update of a Selafin datasource</h2>
 <p>The driver supports creating and writing to Selafin datasources, but there are some caveats when doing so.</p>
@@ -250,7 +250,7 @@ Numbers can also be negative. In this case, they are counted from the end of the
 
 <h2>VSI Virtual File System API support</h2>
 
-<p>The driver supports reading and writing to files managed by VSI Virtual File System API, which include "regular" files, as well as files in the /vsizip/ (read-write) , /vsigzip/ (read-only) , /vsicurl/ (read-only) domains.</p> 
+<p>The driver supports reading and writing to files managed by VSI Virtual File System API, which include "regular" files, as well as files in the /vsizip/ (read-write) , /vsigzip/ (read-only) , /vsicurl/ (read-only) domains.</p>
 
 <h2>Other notes</h2>
 <p>There is no SRS specification in the Selafin standard. The implementation of SRS is an addition of the driver and stores the SRS in an unused data field in the file. Future software using the Selafin standard may use this field and break the SRS specification. In this case, Selafin files will still be readable by the driver, but their writing will overwrite a value which may have another purpose.</p>
diff --git a/ogr/ogrsf_frmts/selafin/io_selafin.cpp b/ogr/ogrsf_frmts/selafin/io_selafin.cpp
index 33bd190..dff01a3 100644
--- a/ogr/ogrsf_frmts/selafin/io_selafin.cpp
+++ b/ogr/ogrsf_frmts/selafin/io_selafin.cpp
@@ -37,11 +37,11 @@ namespace Selafin {
     const char SELAFIN_ERROR_MESSAGE[]="Error when reading Selafin file\n";
 
     struct Point {
-        long nIndex;
+        int nIndex;
         const Header *poHeader;
     };
 
-    void GetBoundsFunc(const void *hFeature,CPLRectObj *poBounds) {
+    static void GetBoundsFunc(const void *hFeature,CPLRectObj *poBounds) {
         const Point *poPoint=(const Point*)hFeature;
         poBounds->minx=poPoint->poHeader->paadfCoords[0][poPoint->nIndex];
         poBounds->maxx=poPoint->poHeader->paadfCoords[0][poPoint->nIndex];
@@ -49,7 +49,7 @@ namespace Selafin {
         poBounds->maxy=poPoint->poHeader->paadfCoords[1][poPoint->nIndex];
     }
 
-    int DumpFeatures(void *pElt,
+    static int DumpFeatures(void *pElt,
                      CPL_UNUSED void *pUserData) {
         Point *poPoint=(Point*)pElt;
         delete poPoint;
@@ -60,38 +60,59 @@ namespace Selafin {
     /****************************************************************/
     /*                         Header                               */
     /****************************************************************/
-    Header::Header():nMinxIndex(-1),nMaxxIndex(-1),nMinyIndex(-1),nMaxyIndex(-1),bTreeUpdateNeeded(true),fp(0),pszFilename(0),pszTitle(0),papszVariables(0),nPointsPerElement(0),panConnectivity(0),poTree(0),panBorder(0),panStartDate(0),nEpsg(0) {
-        paadfCoords[0]=0;
-        paadfCoords[1]=0;
+    Header::Header() :
+        nHeaderSize(0),
+        nStepSize(0),
+        nMinxIndex(-1),
+        nMaxxIndex(-1),
+        nMinyIndex(-1),
+        nMaxyIndex(-1),
+        bTreeUpdateNeeded(true),
+        fp(NULL),
+        pszFilename(NULL),
+        pszTitle(NULL),
+        nVar(0),
+        papszVariables(NULL),
+        nPoints(0),
+        nElements(0),
+        nPointsPerElement(0),
+        panConnectivity(NULL),
+        poTree(NULL),
+        panBorder(NULL),
+        panStartDate(NULL),
+        nSteps(0),
+        nEpsg(0) {
+        paadfCoords[0]=NULL;
+        paadfCoords[1]=NULL;
         for (size_t i=0;i<7;++i) anUnused[i]=0;
-    } 
+    }
 
     Header::~Header() {
-        if (pszFilename!=0) CPLFree(pszFilename);
-        if (pszTitle!=0) CPLFree(pszTitle);
-        if (papszVariables!=0) {
-            for (int i=0;i<nVar;++i) if (papszVariables[i]!=0) CPLFree(papszVariables[i]);
+        CPLFree(pszFilename);
+        CPLFree(pszTitle);
+        if (papszVariables!=NULL) {
+            for (int i=0;i<nVar;++i) CPLFree(papszVariables[i]);
             CPLFree(papszVariables);
         }
-        if (panConnectivity!=0) CPLFree(panConnectivity);
-        if (panBorder!=0) CPLFree(panBorder);
-        if (poTree!=0) {
-            CPLQuadTreeForeach(poTree,DumpFeatures,0);
+        CPLFree(panConnectivity);
+        CPLFree(panBorder);
+        if (poTree!=NULL) {
+            CPLQuadTreeForeach(poTree,DumpFeatures,NULL);
             CPLQuadTreeDestroy(poTree);
         }
-        if (panStartDate!=0) CPLFree(panStartDate);
-        for (size_t i=0;i<2;++i) if (paadfCoords[i]!=0) CPLFree(paadfCoords[i]);
-        if (fp!=0) VSIFCloseL(fp);
+        CPLFree(panStartDate);
+        for (size_t i=0;i<2;++i) CPLFree(paadfCoords[i]);
+        if (fp!=NULL) VSIFCloseL(fp);
     }
 
     void Header::setUpdated() {
-        nHeaderSize=88+16+nVar*40+12*4+((panStartDate==0)?0:32)+24+(nElements*nPointsPerElement+2)*4+(nPoints+2)*12;
+        nHeaderSize=88+16+nVar*40+12*4+((panStartDate==NULL)?0:32)+24+(nElements*nPointsPerElement+2)*4+(nPoints+2)*12;
         nStepSize=12+nVar*(nPoints+2)*4;
     }
 
-    long Header::getPosition(long nStep,long nFeature,long nAttribute) const {
-        long a=(nFeature!=-1 || nAttribute!=-1)?(12+nAttribute*(nPoints+2)*4+4+nFeature*4):0;
-        long b=nStep*nStepSize;
+    int Header::getPosition(int nStep,int nFeature,int nAttribute) const {
+        int a=(nFeature!=-1 || nAttribute!=-1)?(12+nAttribute*(nPoints+2)*4+4+nFeature*4):0;
+        int b=nStep*nStepSize;
         return nHeaderSize+b+a;
     }
 
@@ -107,31 +128,31 @@ namespace Selafin {
     void Header::updateBoundingBox() {
         if (nPoints>0) {
             nMinxIndex=0;
-            for (long i=1;i<nPoints;++i) if (paadfCoords[0][i]<paadfCoords[0][nMinxIndex]) nMinxIndex=i;
+            for (int i=1;i<nPoints;++i) if (paadfCoords[0][i]<paadfCoords[0][nMinxIndex]) nMinxIndex=i;
             nMaxxIndex=0;
-            for (long i=1;i<nPoints;++i) if (paadfCoords[0][i]>paadfCoords[0][nMaxxIndex]) nMaxxIndex=i;
+            for (int i=1;i<nPoints;++i) if (paadfCoords[0][i]>paadfCoords[0][nMaxxIndex]) nMaxxIndex=i;
             nMinyIndex=0;
-            for (long i=1;i<nPoints;++i) if (paadfCoords[1][i]<paadfCoords[1][nMinyIndex]) nMinyIndex=i;
+            for (int i=1;i<nPoints;++i) if (paadfCoords[1][i]<paadfCoords[1][nMinyIndex]) nMinyIndex=i;
             nMaxyIndex=0;
-            for (long i=1;i<nPoints;++i) if (paadfCoords[1][i]>paadfCoords[1][nMaxyIndex]) nMaxyIndex=i;
+            for (int i=1;i<nPoints;++i) if (paadfCoords[1][i]>paadfCoords[1][nMaxyIndex]) nMaxyIndex=i;
         }
     }
 
-    long Header::getClosestPoint(const double &dfx,const double &dfy,const double &dfMax) {
+    int Header::getClosestPoint(const double &dfx,const double &dfy,const double &dfMax) {
         // If there is no quad-tree of the points, build it now
         if (bTreeUpdateNeeded) {
-            if (poTree!=0) {
-                CPLQuadTreeForeach(poTree,DumpFeatures,0);
+            if (poTree!=NULL) {
+                CPLQuadTreeForeach(poTree,DumpFeatures,NULL);
                 CPLQuadTreeDestroy(poTree);
             }
         }
-        if (bTreeUpdateNeeded || poTree==0) {
+        if (bTreeUpdateNeeded || poTree==NULL) {
             bTreeUpdateNeeded=false;
             CPLRectObj *poBB=getBoundingBox();
             poTree=CPLQuadTreeCreate(poBB,GetBoundsFunc);
             delete poBB;
             CPLQuadTreeSetBucketCapacity(poTree,2);
-            for (long i=0;i<nPoints;++i) {
+            for (int i=0;i<nPoints;++i) {
                 Point *poPoint=new Point;
                 poPoint->poHeader=this;
                 poPoint->nIndex=i;
@@ -139,7 +160,7 @@ namespace Selafin {
             }
         }
         // Now we can look for the nearest neighbour using this tree
-        long nIndex=-1;
+        int nIndex=-1;
         double dfMin;
         CPLRectObj poObj;
         poObj.minx=dfx-dfMax;
@@ -151,7 +172,7 @@ namespace Selafin {
         if (nFeatureCount<=0) return -1;
         double dfa,dfb,dfc;
         dfMin=dfMax*dfMax;
-        for (long i=0;i<nFeatureCount;++i) {
+        for (int i=0;i<nFeatureCount;++i) {
             Point *poPoint=(Point*)(phResults[i]);
             dfa=dfx-poPoint->poHeader->paadfCoords[0][poPoint->nIndex];
             dfa*=dfa;
@@ -173,7 +194,7 @@ namespace Selafin {
         for (size_t i=0;i<2;++i) paadfCoords[i]=(double*)CPLRealloc(paadfCoords[i],sizeof(double)*nPoints);
         paadfCoords[0][nPoints-1]=dfx;
         paadfCoords[1][nPoints-1]=dfy;
-        panBorder=(long*)CPLRealloc(panBorder,sizeof(long)*nPoints);
+        panBorder=(int*)CPLRealloc(panBorder,sizeof(int)*nPoints);
         panBorder[nPoints-1]=0;
         // We update the bounding box
         if (nMinxIndex==-1 || dfx<paadfCoords[0][nMinxIndex]) nMinxIndex=nPoints-1;
@@ -185,48 +206,48 @@ namespace Selafin {
         setUpdated();
     }
 
-    void Header::removePoint(long nIndex) {
+    void Header::removePoint(int nIndex) {
         // We remove the point from all the tables
         nPoints--;
         for (size_t i=0;i<2;++i) {
-            for (long j=nIndex;j<nPoints;++j) paadfCoords[i][j]=paadfCoords[i][j+1];
+            for (int j=nIndex;j<nPoints;++j) paadfCoords[i][j]=paadfCoords[i][j+1];
             paadfCoords[i]=(double*)CPLRealloc(paadfCoords[i],sizeof(double)*nPoints);
         }
-        for (long j=nIndex;j<nPoints;++j) panBorder[j]=panBorder[j+1];
-        panBorder=(long*)CPLRealloc(panBorder,sizeof(long)*nPoints);
+        for (int j=nIndex;j<nPoints;++j) panBorder[j]=panBorder[j+1];
+        panBorder=(int*)CPLRealloc(panBorder,sizeof(int)*nPoints);
 
-        // We must also remove all the elements referencing the deleted feature, otherwise the file will not be consistent any longer
-        long nOldElements=nElements;
-        for (long i=0;i<nElements;++i) {
+        // We must also remove all the elements referencing the deleted feature, otherwise the file will not be consistent any inter
+        int nOldElements=nElements;
+        for (int i=0;i<nElements;++i) {
             bool bReferencing=false;
-            long *panTemp=panConnectivity+i*nPointsPerElement;
-            for (long j=0;j<nPointsPerElement;++j) bReferencing |= (panTemp[j]==nIndex+1);
+            int *panTemp=panConnectivity+i*nPointsPerElement;
+            for (int j=0;j<nPointsPerElement;++j) bReferencing |= (panTemp[j]==nIndex+1);
             if (bReferencing) {
                 nElements--;
-                for (long j=i;j<nElements;++j) 
-                    for (long k=0;k<nPointsPerElement;++k) panConnectivity[j*nPointsPerElement+k]=panConnectivity[(j+1)*nPointsPerElement+k];
+                for (int j=i;j<nElements;++j)
+                    for (int k=0;k<nPointsPerElement;++k) panConnectivity[j*nPointsPerElement+k]=panConnectivity[(j+1)*nPointsPerElement+k];
                 --i;
             }
         }
-        if (nOldElements!=nElements) panConnectivity=(long*)CPLRealloc(panConnectivity,sizeof(long)*nElements*nPointsPerElement);
+        if (nOldElements!=nElements) panConnectivity=(int*)CPLRealloc(panConnectivity,sizeof(int)*nElements*nPointsPerElement);
 
         // Now we update the bounding box if needed
         if (nPoints==0) {nMinxIndex=-1;nMaxxIndex=-1;nMinyIndex=-1;nMaxyIndex=-1;} else {
             if (nIndex==nMinxIndex) {
                 nMinxIndex=0;
-                for (long i=1;i<nPoints;++i) if (paadfCoords[0][i]<paadfCoords[0][nMinxIndex]) nMinxIndex=i;
+                for (int i=1;i<nPoints;++i) if (paadfCoords[0][i]<paadfCoords[0][nMinxIndex]) nMinxIndex=i;
             }
             if (nIndex==nMaxxIndex) {
                 nMaxxIndex=0;
-                for (long i=1;i<nPoints;++i) if (paadfCoords[0][i]>paadfCoords[0][nMaxxIndex]) nMaxxIndex=i;
+                for (int i=1;i<nPoints;++i) if (paadfCoords[0][i]>paadfCoords[0][nMaxxIndex]) nMaxxIndex=i;
             }
             if (nIndex==nMinyIndex) {
                 nMinyIndex=0;
-                for (long i=1;i<nPoints;++i) if (paadfCoords[1][i]<paadfCoords[1][nMinyIndex]) nMinyIndex=i;
+                for (int i=1;i<nPoints;++i) if (paadfCoords[1][i]<paadfCoords[1][nMinyIndex]) nMinyIndex=i;
             }
             if (nIndex==nMaxyIndex) {
                 nMaxyIndex=0;
-                for (long i=1;i<nPoints;++i) if (paadfCoords[1][i]>paadfCoords[1][nMaxyIndex]) nMaxyIndex=i;
+                for (int i=1;i<nPoints;++i) if (paadfCoords[1][i]>paadfCoords[1][nMaxyIndex]) nMaxyIndex=i;
             }
         }
 
@@ -239,13 +260,13 @@ namespace Selafin {
     /****************************************************************/
     /*                         TimeStep                             */
     /****************************************************************/
-    TimeStep::TimeStep(long nRecordsP,long nFieldsP):nFields(nFieldsP) {
-        papadfData=(double**)VSIMalloc2(sizeof(double*),nFieldsP);
-        for (long i=0;i<nFieldsP;++i) papadfData[i]=(double*)VSIMalloc2(sizeof(double),nRecordsP);
+    TimeStep::TimeStep(int nRecordsP,int nFieldsP):nFields(nFieldsP) {
+        papadfData=(double**)VSI_MALLOC2_VERBOSE(sizeof(double*),nFieldsP);
+        for (int i=0;i<nFieldsP;++i) papadfData[i]=(double*)VSI_MALLOC2_VERBOSE(sizeof(double),nRecordsP);
     }
-    
+
     TimeStep::~TimeStep() {
-        for (long i=0;i<nFields;++i) CPLFree(papadfData[i]);
+        for (int i=0;i<nFields;++i) CPLFree(papadfData[i]);
         CPLFree(papadfData);
     }
 
@@ -267,7 +288,7 @@ namespace Selafin {
     /****************************************************************/
     /*                     General functions                        */
     /****************************************************************/
-    int read_integer(VSILFILE *fp,long &nData,bool bDiscard) {
+    int read_integer(VSILFILE *fp,int &nData,bool bDiscard) {
         unsigned char anb[4];
         if (VSIFReadL(anb,1,4,fp)<4) {
             CPLError(CE_Failure,CPLE_FileIO,"%s",SELAFIN_ERROR_MESSAGE);
@@ -280,7 +301,7 @@ namespace Selafin {
         return 1;
     }
 
-    int write_integer(VSILFILE *fp,long nData) {
+    int write_integer(VSILFILE *fp,int nData) {
         unsigned char anb[4];
         for (int i=3;i>=0;--i) {
             anb[i]=nData%0x100;
@@ -292,9 +313,9 @@ namespace Selafin {
         };
         return 1;
     }
-    
-    long read_string(VSILFILE *fp,char *&pszData,bool bDiscard) {
-        long nLength=0;
+
+    int read_string(VSILFILE *fp,char *&pszData,bool bDiscard) {
+        int nLength=0;
         read_integer(fp,nLength);
         if (nLength<=0 || nLength+1<=0) {
             CPLError(CE_Failure,CPLE_FileIO,"%s",SELAFIN_ERROR_MESSAGE);
@@ -308,7 +329,7 @@ namespace Selafin {
         }
         else {
             pszData=(char*)CPLMalloc(sizeof(char)*(nLength+1));
-            if ((long)VSIFReadL(pszData,1,nLength,fp)<(long)nLength) {
+            if ((int)VSIFReadL(pszData,1,nLength,fp)<(int)nLength) {
                 CPLError(CE_Failure,CPLE_FileIO,"%s",SELAFIN_ERROR_MESSAGE);
                 return 0;
             }
@@ -323,17 +344,17 @@ namespace Selafin {
 
     int write_string(VSILFILE *fp,char *pszData,size_t nLength) {
         if (nLength==0) nLength=strlen(pszData);
-        if (write_integer(fp,nLength)==0) return 0;
+        if (write_integer(fp,static_cast<int>(nLength))==0) return 0;
         if (VSIFWriteL(pszData,1,nLength,fp)<nLength) {
             CPLError(CE_Failure,CPLE_FileIO,"%s",SELAFIN_ERROR_MESSAGE);
             return 0;
         }
-        if (write_integer(fp,nLength)==0) return 0;
+        if (write_integer(fp,static_cast<int>(nLength))==0) return 0;
         return 1;
     }
 
-    long read_intarray(VSILFILE *fp,long *&panData,bool bDiscard) {
-        long nLength=0;
+    int read_intarray(VSILFILE *fp,int *&panData,bool bDiscard) {
+        int nLength=0;
         read_integer(fp,nLength);
         if (nLength<0 || nLength+1<=0) {
             CPLError(CE_Failure,CPLE_FileIO,"%s",SELAFIN_ERROR_MESSAGE);
@@ -346,17 +367,17 @@ namespace Selafin {
             }
         }
         else {
-            if (nLength==0) panData=0; else {
-                panData=(long *)VSIMalloc2(nLength/4,sizeof(long));
-                if (panData==0) return -1;
+            if (nLength==0) panData=NULL; else {
+                panData=(int *)VSI_MALLOC2_VERBOSE(nLength/4,sizeof(int));
+                if (panData==NULL) return -1;
             }
-            for (long i=0;i<nLength/4;++i) if (read_integer(fp,panData[i])==0) {
+            for (int i=0;i<nLength/4;++i) if (read_integer(fp,panData[i])==0) {
                 CPLFree(panData);
                 CPLError(CE_Failure,CPLE_FileIO,"%s",SELAFIN_ERROR_MESSAGE);
                 return -1;
             }
             if (VSIFSeekL(fp,4,SEEK_CUR)!=0) {
-                if (panData!=0) CPLFree(panData);
+                CPLFree(panData);
                 CPLError(CE_Failure,CPLE_FileIO,"%s",SELAFIN_ERROR_MESSAGE);
                 return -1;
             }
@@ -364,15 +385,15 @@ namespace Selafin {
         return nLength/4;
     }
 
-    int write_intarray(VSILFILE *fp,long *panData,size_t nLength) {
-        if (write_integer(fp,nLength*4)==0) return 0;
+    int write_intarray(VSILFILE *fp,int *panData,size_t nLength) {
+        if (write_integer(fp,static_cast<int>(nLength*4))==0) return 0;
         for (size_t i=0;i<nLength;++i) {
             if (write_integer(fp,panData[i])==0) {
                 CPLError(CE_Failure,CPLE_FileIO,"%s",SELAFIN_ERROR_MESSAGE);
                 return 0;
             }
         }
-        if (write_integer(fp,nLength*4)==0) return 0;
+        if (write_integer(fp,static_cast<int>(nLength*4))==0) return 0;
         return 1;
     }
 
@@ -399,8 +420,8 @@ namespace Selafin {
         return 1;
     }
 
-    long read_floatarray(VSILFILE *fp,double **papadfData,bool bDiscard) {
-        long nLength=0;
+    int read_floatarray(VSILFILE *fp,double **papadfData,bool bDiscard) {
+        int nLength=0;
         read_integer(fp,nLength);
         if (nLength<0 || nLength+1<=0) {
             CPLError(CE_Failure,CPLE_FileIO,"%s",SELAFIN_ERROR_MESSAGE);
@@ -413,17 +434,17 @@ namespace Selafin {
             }
         }
         else {
-            if (nLength==0) *papadfData=0; else {
-                *papadfData=(double*)VSIMalloc2(sizeof(double),nLength/4);
-                if (papadfData==0) return -1;
+            if (nLength==0) *papadfData=NULL; else {
+                *papadfData=(double*)VSI_MALLOC2_VERBOSE(sizeof(double),nLength/4);
+                if (*papadfData==NULL) return -1;
             }
-            for (long i=0;i<nLength/4;++i) if (read_float(fp,(*papadfData)[i])==0) {
+            for (int i=0;i<nLength/4;++i) if (read_float(fp,(*papadfData)[i])==0) {
                 CPLFree(*papadfData);
                 CPLError(CE_Failure,CPLE_FileIO,"%s",SELAFIN_ERROR_MESSAGE);
                 return -1;
             }
             if (VSIFSeekL(fp,4,SEEK_CUR)!=0) {
-                if (*papadfData!=0) CPLFree(*papadfData);
+                CPLFree(*papadfData);
                 CPLError(CE_Failure,CPLE_FileIO,"%s",SELAFIN_ERROR_MESSAGE);
                 return -1;
             }
@@ -432,56 +453,56 @@ namespace Selafin {
     }
 
     int write_floatarray(VSILFILE *fp,double *papadfData,size_t nLength) {
-        if (write_integer(fp,nLength*4)==0) return 0;
+        if (write_integer(fp,static_cast<int>(nLength*4))==0) return 0;
         for (size_t i=0;i<nLength;++i) {
             if (write_float(fp,papadfData[i])==0) {
                 CPLError(CE_Failure,CPLE_FileIO,"%s",SELAFIN_ERROR_MESSAGE);
                 return 0;
             }
         }
-        if (write_integer(fp,nLength*4)==0) return 0;
+        if (write_integer(fp,static_cast<int>(nLength*4))==0) return 0;
         return 1;
     }
 
     Header *read_header(VSILFILE *fp,const char *pszFilename) {
         // Get the total file size (used later to estimate the number of time steps)
-        long nFileSize;
+        int nFileSize;
         VSIFSeekL(fp,0,SEEK_END);
-        nFileSize=(long)VSIFTellL(fp);
+        nFileSize=(int)VSIFTellL(fp);
         VSIRewindL(fp);
         // Save the filename
-        long nLength;
+        int nLength;
         Header *poHeader=new Header();
         poHeader->fp=fp;
         poHeader->pszFilename=CPLStrdup(pszFilename);
-        long *panTemp;
+        int *panTemp = NULL;
         // Read the title
         nLength=read_string(fp,poHeader->pszTitle);
         if (nLength==0) {
             delete poHeader;
-            return 0;
+            return NULL;
         }
         // Read the array of 2 integers, with the number of variables at the first position
         nLength=read_intarray(fp,panTemp);
         if (nLength!=2) {
             delete poHeader;
             CPLFree(panTemp);
-            return 0;
+            return NULL;
         }
         poHeader->nVar=panTemp[0];
         poHeader->anUnused[0]=panTemp[1];
         CPLFree(panTemp);
         if (poHeader->nVar<0) {
             delete poHeader;
-            return 0;
+            return NULL;
         }
         // For each variable, read its name as a string of 32 characters
-        poHeader->papszVariables=(char**)VSIMalloc2(sizeof(char*),poHeader->nVar);
-        for (long i=0;i<poHeader->nVar;++i) {
+        poHeader->papszVariables=(char**)VSI_MALLOC2_VERBOSE(sizeof(char*),poHeader->nVar);
+        for (int i=0;i<poHeader->nVar;++i) {
             nLength=read_string(fp,poHeader->papszVariables[i]);
             if (nLength==0) {
                 delete poHeader;
-                return 0;
+                return NULL;
             }
             // We eliminate quotes in the names of the variables because SQL requests don't seem to appreciate them
             char *pszc=poHeader->papszVariables[i];
@@ -495,7 +516,7 @@ namespace Selafin {
         if (nLength<10) {
             delete poHeader;
             CPLFree(panTemp);
-            return 0;
+            return NULL;
         }
         poHeader->anUnused[1]=panTemp[0];
         poHeader->nEpsg=panTemp[1];
@@ -508,7 +529,7 @@ namespace Selafin {
             if (nLength<6) {
                 delete poHeader;
                 CPLFree(panTemp);
-                return 0;
+                return NULL;
             }
         }
         CPLFree(panTemp);
@@ -517,7 +538,7 @@ namespace Selafin {
         if (nLength<4) {
             delete poHeader;
             CPLFree(panTemp);
-            return 0;
+            return NULL;
         }
         poHeader->nElements=panTemp[0];
         poHeader->nPoints=panTemp[1];
@@ -525,41 +546,41 @@ namespace Selafin {
         if (poHeader->nElements<0 || poHeader->nPoints<0 || poHeader->nPointsPerElement<0 || panTemp[3]!=1) {
             delete poHeader;
             CPLFree(panTemp);
-            return 0;
+            return NULL;
         }
         CPLFree(panTemp);
         // Read the connectivity table as an array of nPointsPerElement*nElements integers, and check if all point numbers are valid
         nLength=read_intarray(fp,poHeader->panConnectivity);
         if (nLength!=poHeader->nElements*poHeader->nPointsPerElement) {
             delete poHeader;
-            return 0;
+            return NULL;
         }
-        for (long i=0;i<poHeader->nElements*poHeader->nPointsPerElement;++i) {
+        for (int i=0;i<poHeader->nElements*poHeader->nPointsPerElement;++i) {
             if (poHeader->panConnectivity[i]<=0 || poHeader->panConnectivity[i]>poHeader->nPoints) {
                 delete poHeader;
-                return 0;
+                return NULL;
             }
         }
         // Read the array of nPoints integers with the border points
         nLength=read_intarray(fp,poHeader->panBorder);
         if (nLength!=poHeader->nPoints) {
             delete poHeader;
-            return 0;
+            return NULL;
         }
         // Read two arrays of nPoints floats with the coordinates of each point
         for (size_t i=0;i<2;++i) {
             read_floatarray(fp,poHeader->paadfCoords+i);
             if (nLength<poHeader->nPoints) {
                 delete poHeader;
-                return 0;
+                return NULL;
             }
-            for (long j=0;j<poHeader->nPoints;++j) poHeader->paadfCoords[i][j]+=poHeader->adfOrigin[i];
+            for (int j=0;j<poHeader->nPoints;++j) poHeader->paadfCoords[i][j]+=poHeader->adfOrigin[i];
         }
         // Update the boundinx box
         poHeader->updateBoundingBox();
         // Update the size of the header and calculate the number of time steps
         poHeader->setUpdated();
-        long nPos=poHeader->getPosition(0);
+        int nPos=poHeader->getPosition(0);
         poHeader->nSteps=(nFileSize-nPos)/(poHeader->getPosition(1)-nPos);
         return poHeader;
     }
@@ -567,19 +588,19 @@ namespace Selafin {
     int write_header(VSILFILE *fp,Header *poHeader) {
         VSIRewindL(fp);
         if (write_string(fp,poHeader->pszTitle,80)==0) return 0;
-        long anTemp[10]={0};
+        int anTemp[10]={0};
         anTemp[0]=poHeader->nVar;
         anTemp[1]=poHeader->anUnused[0];
         if (write_intarray(fp,anTemp,2)==0) return 0;
-        for (long i=0;i<poHeader->nVar;++i) if (write_string(fp,poHeader->papszVariables[i],32)==0) return 0;
+        for (int i=0;i<poHeader->nVar;++i) if (write_string(fp,poHeader->papszVariables[i],32)==0) return 0;
         anTemp[0]=poHeader->anUnused[1];
         anTemp[1]=poHeader->nEpsg;
-        anTemp[2]=(long)poHeader->adfOrigin[0];
-        anTemp[3]=(long)poHeader->adfOrigin[1];
+        anTemp[2]=(int)poHeader->adfOrigin[0];
+        anTemp[3]=(int)poHeader->adfOrigin[1];
         for (size_t i=4;i<9;++i) anTemp[i]=poHeader->anUnused[i-2];
-        anTemp[9]=(poHeader->panStartDate!=0)?1:0;
+        anTemp[9]=(poHeader->panStartDate!=NULL)?1:0;
         if (write_intarray(fp,anTemp,10)==0) return 0;
-        if (poHeader->panStartDate!=0 && write_intarray(fp,poHeader->panStartDate,6)==0) return 0;
+        if (poHeader->panStartDate!=NULL && write_intarray(fp,poHeader->panStartDate,6)==0) return 0;
         anTemp[0]=poHeader->nElements;
         anTemp[1]=poHeader->nPoints;
         anTemp[2]=poHeader->nPointsPerElement;
@@ -588,10 +609,10 @@ namespace Selafin {
         if (write_intarray(fp,poHeader->panConnectivity,poHeader->nElements*poHeader->nPointsPerElement)==0) return 0;
         if (write_intarray(fp,poHeader->panBorder,poHeader->nPoints)==0) return 0;
         double *dfVals;
-        dfVals=(double*)VSIMalloc2(sizeof(double),poHeader->nPoints);
-        if (poHeader->nPoints>0 && dfVals==0) return 0;
+        dfVals=(double*)VSI_MALLOC2_VERBOSE(sizeof(double),poHeader->nPoints);
+        if (poHeader->nPoints>0 && dfVals==NULL) return 0;
         for (size_t i=0;i<2;++i) {
-            for (long j=0;j<poHeader->nPoints;++j) dfVals[j]=poHeader->paadfCoords[i][j]-poHeader->adfOrigin[i];
+            for (int j=0;j<poHeader->nPoints;++j) dfVals[j]=poHeader->paadfCoords[i][j]-poHeader->adfOrigin[i];
             if (write_floatarray(fp,dfVals,poHeader->nPoints)==0) {
                 CPLFree(dfVals);
                 return 0;
@@ -604,7 +625,7 @@ namespace Selafin {
 #ifdef notdef
     int read_step(VSILFILE *fp,const Header *poHeader,TimeStep *&poStep) {
         poStep=new TimeStep(poHeader->nPoints,poHeader->nVar);
-        long nLength;
+        int nLength;
         if (read_integer(fp,nLength)==0 || nLength!=1) {
             delete poStep;
             return 0;
@@ -617,7 +638,7 @@ namespace Selafin {
             delete poStep;
             return 0;
         }
-        for (long i=0;i<poHeader->nVar;++i) {
+        for (int i=0;i<poHeader->nVar;++i) {
             nLength=read_floatarray(fp,&(poStep->papadfData[i]));
             if (nLength!=poHeader->nPoints) {
                 delete poStep;
@@ -627,12 +648,12 @@ namespace Selafin {
         return 1;
     }
 
-    
+
     int write_step(VSILFILE *fp,const Header *poHeader,const TimeStep *poStep) {
         if (write_integer(fp,1)==0) return 0;
         if (write_float(fp,poStep->dfDate)==0) return 0;
         if (write_integer(fp,1)==0) return 0;
-        for (long i=0;i<poHeader->nVar;++i) {
+        for (int i=0;i<poHeader->nVar;++i) {
             if (write_floatarray(fp,poStep->papadfData[i])==0) return 0;
         }
         return 1;
@@ -641,7 +662,7 @@ namespace Selafin {
     int read_steps(VSILFILE *fp,const Header *poHeader,TimeStepList *&poSteps) {
         poSteps=0;
         TimeStepList *poCur,*poNew;
-        for (long i=0;i<poHeader->nSteps;++i) {
+        for (int i=0;i<poHeader->nSteps;++i) {
             poNew=new TimeStepList(0,0);
             if (read_step(fp,poHeader,poNew->poStep)==0) {
                 delete poSteps;
@@ -662,5 +683,4 @@ namespace Selafin {
         return 1;
     }
 #endif
-    
 }
diff --git a/ogr/ogrsf_frmts/selafin/io_selafin.h b/ogr/ogrsf_frmts/selafin/io_selafin.h
index d7205ed..29415b8 100644
--- a/ogr/ogrsf_frmts/selafin/io_selafin.h
+++ b/ogr/ogrsf_frmts/selafin/io_selafin.h
@@ -38,32 +38,32 @@ namespace Selafin {
      */
     class Header {
         private:
-            long nHeaderSize; //!< Size (in bytes) of the header of the file (seeking to this location brings to the first "feature")
-            long nStepSize;    //!< Size (in bytes) of one feature in the file
-            long nMinxIndex;    //!< Index of the point at the western border of the bounding box
-            long nMaxxIndex;    //!< Index of the point at the eastern border of the bounding box
-            long nMinyIndex;    //!< Index of the point at the southern border of the bounding box
-            long nMaxyIndex;    //!< Index of the point at the northern border of the bounding box
+            int nHeaderSize; //!< Size (in bytes) of the header of the file (seeking to this location brings to the first "feature")
+            int nStepSize;    //!< Size (in bytes) of one feature in the file
+            int nMinxIndex;    //!< Index of the point at the western border of the bounding box
+            int nMaxxIndex;    //!< Index of the point at the eastern border of the bounding box
+            int nMinyIndex;    //!< Index of the point at the southern border of the bounding box
+            int nMaxyIndex;    //!< Index of the point at the northern border of the bounding box
             bool bTreeUpdateNeeded;  //!< Tell if the quad tree has to be updated
         public:
             //size_t nRefCount;   //!< Number of references to this object
             VSILFILE *fp;   //!< Pointer to the file with the layers
             char *pszFilename;  //!< Name of the Selafin file
             char *pszTitle; //!< Title of the simulation
-            long nVar;   //!< Number of variables
+            int nVar;   //!< Number of variables
             char **papszVariables;  //!< Name of the variables
-            long nPoints;    //!< Total number of points
-            long nElements;  //!< Total number of elements
-            long nPointsPerElement;  //!< Number of points per element
-            long *panConnectivity;   //!< Connectivity table of elements: first nPointsPerElement elements are the indices of the points making the first element, and so on. In the Selafin file, the first point has index 1.
+            int nPoints;    //!< Total number of points
+            int nElements;  //!< Total number of elements
+            int nPointsPerElement;  //!< Number of points per element
+            int *panConnectivity;   //!< Connectivity table of elements: first nPointsPerElement elements are the indices of the points making the first element, and so on. In the Selafin file, the first point has index 1.
             double *paadfCoords[2]; //!< Table of coordinates of points: x then y
             CPLQuadTree *poTree;    //!< Quad-tree for spatially indexing points in the array paadfCoords. The tree will mostly contain a Null value, until a request is made to find a closest neighbour, in which case it will be built and maintained
             double adfOrigin[2];  //!< Table of coordinates of the origin of the axis
-            long *panBorder;    //!< Array of integers defining border points (0 for an inner point, and the index of the border point otherwise). This table is not used by the driver but stored to allow to rewrite the header if needed
-            long *panStartDate;    //!< Table with the starting date of the simulation (may be 0 if date is not defined). Date is registered as a set of six elements: year, month, day, hour, minute, second.
-            long nSteps;    //!< Number of steps in the Selafin file
-            long nEpsg; //!< EPSG of the file
-            long anUnused[7];   //!< Array of integers for storing the eight values read from the header but not actually used by the driver. These values are merely saved to rewrite them in the file if it is changed.
+            int *panBorder;    //!< Array of integers defining border points (0 for an inner point, and the index of the border point otherwise). This table is not used by the driver but stored to allow to rewrite the header if needed
+            int *panStartDate;    //!< Table with the starting date of the simulation (may be 0 if date is not defined). Date is registered as a set of six elements: year, month, day, hour, minute, second.
+            int nSteps;    //!< Number of steps in the Selafin file
+            int nEpsg; //!< EPSG of the file
+            int anUnused[7];   //!< Array of integers for storing the eight values read from the header but not actually used by the driver. These values are merely saved to rewrite them in the file if it is changed.
 
             Header(); //!< Standard constructor
             ~Header();  //!< Destructor of structure
@@ -77,7 +77,7 @@ namespace Selafin {
              * \param nAttribute Index of the attribute, starting with 0
              * \return Position (in bytes) from the start of the file
              */
-            long getPosition(long nStep,long nFeature=-1,long nAttribute=-1) const; // {return nHeaderSize+nStep*nStepSize+(nFeature!=-1)?(12+nAttribute*(nPoints+2)*4+4+nFeature*4):0;}
+            int getPosition(int nStep,int nFeature=-1,int nAttribute=-1) const; // {return nHeaderSize+nStep*nStepSize+(nFeature!=-1)?(12+nAttribute*(nPoints+2)*4+4+nFeature*4):0;}
 
             /**
              * \brief Return the bounding box of the points
@@ -103,7 +103,7 @@ namespace Selafin {
              * \param dfMax Maximum distance allowed to the point
              * \return Index of the closest point in the array, -1 if there was no point at all in the array closer than distance dfMax
              */
-            long getClosestPoint(const double &dfx,const double &dfy,const double &dfMax);
+            int getClosestPoint(const double &dfx,const double &dfy,const double &dfMax);
 
             /**
              * \brief Tells that the header has been changed
@@ -127,7 +127,7 @@ namespace Selafin {
              * This function removes a point at position nIndex from the array of points. The bounding box is updated. All the elements which referenced this point are also removed.
              * \param nIndex Index of the point which has to be removed
              */
-            void removePoint(long nIndex);
+            void removePoint(int nIndex);
 
     };
 
@@ -137,11 +137,11 @@ namespace Selafin {
      */
     class TimeStep {
         private:
-            //long nRecords;  //!< Number of records (first index) in the TimeStep::papadfData array, which should correspond to the number of features (either points or elements) in a Selafin layer
-            long nFields;   //!< Number of fields for each record (second index) in the TimeStep::papadfData array, which should correspond to the number of attributes in a Selafin layer
+            //int nRecords;  //!< Number of records (first index) in the TimeStep::papadfData array, which should correspond to the number of features (either points or elements) in a Selafin layer
+            int nFields;   //!< Number of fields for each record (second index) in the TimeStep::papadfData array, which should correspond to the number of attributes in a Selafin layer
         public:
             double dfDate;  //!< Date of the time step (usually in seconds after the starting date)
-            double **papadfData;    //!< Double-indexed array with values of all atributes for all features. The first index is the number of the attribute, the second is the number of the feature.
+            double **papadfData;    //!< Double-indexed array with values of all attributes for all features. The first index is the number of the attribute, the second is the number of the feature.
 
             /**
              * \brief Constructor of the structure
@@ -150,7 +150,7 @@ namespace Selafin {
              * \param nRecords Number of records (first index) in the TimeStep::papadfData array, which should correspond to the number of features (either points or elements) in a Selafin layer
              * \param nFields Number of fields for each record (second index) in the TimeStep::papadfData array, which should correspond to the number of attributes in a Selafin layer
              */
-            TimeStep(long nRecordsP,long nFieldsP);
+            TimeStep(int nRecordsP,int nFieldsP);
 
             ~TimeStep();    //!< Standard destructor
     };
@@ -177,7 +177,7 @@ namespace Selafin {
      * \param bDiscard If true, the function does not attempt to save the value read in the variable nData, but only advances in the file as it should. Default value is false.
      * \return 1 if the integer was successfully read, 0 otherwise
      */
-    int read_integer(VSILFILE *fp,long &nData,bool bDiscard=false);
+    int read_integer(VSILFILE *fp,int &nData,bool bDiscard=false);
 
     /**
      * \brief Write an integer to a Selafin file
@@ -187,7 +187,7 @@ namespace Selafin {
      * \param nData Value to be written to the file
      * \return 1 if the integer was successfully written, 0 otherwise
      */
-    int write_integer(VSILFILE *fp,long nData);
+    int write_integer(VSILFILE *fp,int nData);
 
     /**
      * \brief Read a string from a Selafin file
@@ -196,13 +196,13 @@ namespace Selafin {
      *   - an integer \a n (therefore on 4 bytes) with the length of the string
      *   - the \a n bytes of the string, preferably in ASCII format
      *   - once again the integer \a n (on 4 bytes)
-     * The function does not check if the last integer is the same as the first one. 
+     * The function does not check if the last integer is the same as the first one.
      * \param fp Pointer to an open file
      * \param pszData After the execution, contains the value read. The structure is allocated by the function.
      * \param bDiscard If true, the function does not attempt to save the value read in the variable nData, but only advances in the file as it should. Default value is false.
      * \return Number of characters in string read
      */
-    long read_string(VSILFILE *fp,char *&pszData,bool bDiscard=false);
+    int read_string(VSILFILE *fp,char *&pszData,bool bDiscard=false);
 
     /**
      * \brief Write a string to a Selafin file
@@ -228,7 +228,7 @@ namespace Selafin {
      * \param bDiscard If true, the function does not attempt to save the value read in the variable nData, but only advances in the file as it should. Default value is false.
      * \return Number of elements in array read, -1 if an error occurred
      */
-    long read_intarray(VSILFILE *fp,long *&panData,bool bDiscard=false);
+    int read_intarray(VSILFILE *fp,int *&panData,bool bDiscard=false);
 
     /**
      * \brief Write an array of integers to a Selafin file
@@ -239,7 +239,7 @@ namespace Selafin {
      * \param nLength Number of elements in the array
      * \return 1 if the array was successfully written, 0 otherwise
      */
-    int write_intarray(VSILFILE *fp,long *panData,size_t nLength);
+    int write_intarray(VSILFILE *fp,int *panData,size_t nLength);
 
     /**
      * \brief Read a floating point number from a Selafin file
@@ -275,8 +275,8 @@ namespace Selafin {
      * \param bDiscard If true, the function does not attempt to save the value read in the variable nData, but only advances in the file as it should. Default value is false.
      * \return Number of elements in array read, -1 if an error occurred
      */
-    long read_floatarray(VSILFILE *fp,double **papadfData,bool bDiscard=false);
-        
+    int read_floatarray(VSILFILE *fp,double **papadfData,bool bDiscard=false);
+
     /**
      * \brief Write an array of floats to a Selafin file
      *
diff --git a/ogr/ogrsf_frmts/selafin/ogr_selafin.h b/ogr/ogrsf_frmts/selafin/ogr_selafin.h
index 3ccf613..6468ffe 100644
--- a/ogr/ogrsf_frmts/selafin/ogr_selafin.h
+++ b/ogr/ogrsf_frmts/selafin/ogr_selafin.h
@@ -25,8 +25,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_SELAFIN_H_INCLUDED
-#define _OGR_SELAFIN_H_INCLUDED
+#ifndef OGR_SELAFIN_H_INCLUDED
+#define OGR_SELAFIN_H_INCLUDED
 
 #include "io_selafin.h"
 #include "ogrsf_frmts.h"
@@ -42,21 +42,21 @@ class Range {
     private:
         typedef struct List {
             SelafinTypeDef eType;
-            long nMin,nMax;
+            int nMin,nMax;
             List *poNext;
-            List():poNext(0) {}
-            List(SelafinTypeDef eTypeP,long nMinP,long nMaxP,List *poNextP):eType(eTypeP),nMin(nMinP),nMax(nMaxP),poNext(poNextP) {}
+            List():poNext(NULL) {}
+            List(SelafinTypeDef eTypeP,int nMinP,int nMaxP,List *poNextP):eType(eTypeP),nMin(nMinP),nMax(nMaxP),poNext(poNextP) {}
         } List;
         List *poVals,*poActual;
-        long nMaxValue;
-        static void sortList(List *&poList,List *poEnd=0);
+        int nMaxValue;
+        static void sortList(List *&poList,List *poEnd=NULL);
         static void deleteList(List *poList);
     public:
-        Range():poVals(0),poActual(0),nMaxValue(0) {}
+        Range():poVals(NULL),poActual(NULL),nMaxValue(0) {}
         void setRange(const char *pszStr);
         ~Range();
-        void setMaxValue(long nMaxValueP);
-        bool contains(SelafinTypeDef eType,long nValue) const;
+        void setMaxValue(int nMaxValueP);
+        bool contains(SelafinTypeDef eType,int nValue) const;
         size_t getSize() const;
 };
 
@@ -69,7 +69,7 @@ class OGRSelafinLayer : public OGRLayer {
     private:
         SelafinTypeDef eType;
         int bUpdate;
-        long nStepNumber;
+        int nStepNumber;
         Selafin::Header *poHeader;
         OGRFeatureDefn *poFeatureDefn;
         OGRSpatialReference *poSpatialRef;
@@ -78,7 +78,7 @@ class OGRSelafinLayer : public OGRLayer {
         OGRSelafinLayer( const char *pszLayerNameP, int bUpdateP,OGRSpatialReference *poSpatialRefP,Selafin::Header *poHeaderP,int nStepNumberP,SelafinTypeDef eTypeP);
         ~OGRSelafinLayer();
         OGRSpatialReference *GetSpatialRef() {return poSpatialRef;}
-        long GetStepNumber() {return nStepNumber;}
+        int GetStepNumber() {return nStepNumber;}
         OGRFeature *GetNextFeature();
         OGRFeature *GetFeature(GIntBig nFID);
         void ResetReading();
@@ -87,6 +87,8 @@ class OGRSelafinLayer : public OGRLayer {
         int TestCapability(const char *pszCap);
         GIntBig GetFeatureCount(int bForce=TRUE);
         OGRErr GetExtent(OGREnvelope *psExtent,int bForce=TRUE);
+        virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
         OGRErr ISetFeature(OGRFeature *poFeature);
         OGRErr ICreateFeature(OGRFeature *poFeature);
         OGRErr CreateField(OGRFieldDefn *poField,int bApproxOK=TRUE);
@@ -122,9 +124,9 @@ class OGRSelafinDataSource : public OGRDataSource {
         int GetLayerCount() { return nLayers; }
         OGRLayer *GetLayer( int );
         virtual OGRLayer *ICreateLayer( const char *pszName, OGRSpatialReference *poSpatialRefP = NULL, OGRwkbGeometryType eGType = wkbUnknown, char ** papszOptions = NULL );
-        virtual OGRErr DeleteLayer(int); 
+        virtual OGRErr DeleteLayer(int);
         int TestCapability( const char * );
-        void SetDefaultSelafinName( const char *pszName ) { osDefaultSelafinName = pszName; }
+        void SetDefaultSelafinName( const char *pszNameIn ) { osDefaultSelafinName = pszNameIn; }
 };
 
-#endif /* ndef _OGR_SELAFIN_H_INCLUDED */
+#endif /* ndef OGR_SELAFIN_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/selafin/ogrselafindatasource.cpp b/ogr/ogrsf_frmts/selafin/ogrselafindatasource.cpp
index dedbcbf..6fc1130 100644
--- a/ogr/ogrsf_frmts/selafin/ogrselafindatasource.cpp
+++ b/ogr/ogrsf_frmts/selafin/ogrselafindatasource.cpp
@@ -43,9 +43,9 @@ Range::~Range() {
 }
 
 void Range::deleteList(Range::List *poList) {
-    if (poList==0) return;
+    if (poList==NULL) return;
     Range::List *pol=poList;
-    while (pol!=0) {
+    while (pol!=NULL) {
         poList=poList->poNext;
         delete pol;
         pol=poList;
@@ -55,15 +55,15 @@ void Range::deleteList(Range::List *poList) {
 void Range::setRange(const char *pszStr) {
     deleteList(poVals);
     deleteList(poActual);
-    poVals=0;
-    Range::List *poEnd=0;
+    poVals=NULL;
+    Range::List *poEnd=NULL;
     if (pszStr==NULL || pszStr[0]!='[') {
         CPLError( CE_Warning, CPLE_IllegalArg, "Invalid range specified\n");
         return;
     }
     const char *pszc=pszStr;
     char *psze;
-    long nMin,nMax;
+    int nMin,nMax;
     SelafinTypeDef eType;
     while (*pszc!=0 && *pszc!=']') {
         pszc++;
@@ -77,11 +77,11 @@ void Range::setRange(const char *pszStr) {
         if (*pszc==':') {
             nMin=0;
         } else {
-            nMin=strtol(pszc,&psze,10);
+            nMin=(int)strtol(pszc,&psze,10);
             if (*psze!=':' && *psze!=',' && *psze!=']') {
                 CPLError( CE_Warning, CPLE_IllegalArg, "Invalid range specified\n");
                 deleteList(poVals);
-                poVals=0;
+                poVals=NULL;
                 return;
             }
             pszc=psze;
@@ -89,13 +89,13 @@ void Range::setRange(const char *pszStr) {
         if (*pszc==':') {
             ++pszc;
             if (*pszc==',' || *pszc==']') {
-                nMax=-1; 
+                nMax=-1;
             } else {
-                nMax=strtol(pszc,&psze,10);
+                nMax=(int)strtol(pszc,&psze,10);
                 if (*psze!=',' && *psze!=']') {
                     CPLError( CE_Warning, CPLE_IllegalArg, "Invalid range specified\n");
                     deleteList(poVals);
-                    poVals=0;
+                    poVals=NULL;
                     return;
                 }
                 pszc=psze;
@@ -103,7 +103,7 @@ void Range::setRange(const char *pszStr) {
         } else nMax=nMin;
         Range::List *poNew;
         if (eType!=ALL) poNew=new Range::List(eType,nMin,nMax,NULL); else poNew=new Range::List(POINTS,nMin,nMax,new Range::List(ELEMENTS,nMin,nMax,NULL));
-        if (poVals==0) {
+        if (poVals==NULL) {
             poVals=poNew;
             poEnd=poNew;
         } else {
@@ -115,14 +115,14 @@ void Range::setRange(const char *pszStr) {
     if (*pszc!=']') {
         CPLError( CE_Warning, CPLE_IllegalArg, "Invalid range specified\n");
         deleteList(poVals);
-        poVals=0;
+        poVals=NULL;
     }
 }
 
-bool Range::contains(SelafinTypeDef eType,long nValue) const {
-    if (poVals==0) return true;
+bool Range::contains(SelafinTypeDef eType,int nValue) const {
+    if (poVals==NULL) return true;
     Range::List *poCur=poActual;
-    while (poCur!=0) {
+    while (poCur!=NULL) {
         if (poCur->eType==eType && nValue>=poCur->nMin && nValue<=poCur->nMax) return true;
         poCur=poCur->poNext;
     }
@@ -130,15 +130,15 @@ bool Range::contains(SelafinTypeDef eType,long nValue) const {
 }
 
 void Range::sortList(Range::List *&poList,Range::List *poEnd) {
-    if (poList==0 || poList==poEnd) return;
+    if (poList==NULL || poList==poEnd) return;
     Range::List *pol=poList;
-    Range::List *poBefore=0;
-    Range::List *poBeforeEnd=0;
+    Range::List *poBefore=NULL;
+    Range::List *poBeforeEnd=NULL;
     // poList plays the role of the pivot value. Values greater and smaller are sorted on each side of it.
     // The order relation here is POINTS ranges first, then sorted by nMin value.
     while (pol->poNext!=poEnd) {
         if ((pol->eType==ELEMENTS && (pol->poNext->eType==POINTS || pol->poNext->nMin<pol->nMin)) || (pol->eType==POINTS && pol->poNext->eType==POINTS && pol->poNext->nMin<pol->nMin)) {
-            if (poBefore==0) {
+            if (poBefore==NULL) {
                 poBefore=pol->poNext;
                 poBeforeEnd=poBefore;
             } else {
@@ -148,24 +148,24 @@ void Range::sortList(Range::List *&poList,Range::List *poEnd) {
             pol->poNext=pol->poNext->poNext;
         } else pol=pol->poNext;
     }
-    if (poBefore!=0) poBeforeEnd->poNext=poList;
+    if (poBefore!=NULL) poBeforeEnd->poNext=poList;
     // Now, poList is well placed. We do the same for the sublists before and after poList
     Range::sortList(poBefore,poList);
     Range::sortList(poList->poNext,poEnd);
     // Finally, we restore the right starting point of the list
-    if (poBefore!=0) poList=poBefore;
+    if (poBefore!=NULL) poList=poBefore;
 }
 
-void Range::setMaxValue(long nMaxValueP) {
+void Range::setMaxValue(int nMaxValueP) {
     nMaxValue=nMaxValueP;
-    if (poVals==0) return;
+    if (poVals==NULL) return;
     // We keep an internal private copy of the list where the range is "resolved", that is simplified to a union of disjoint intervals
     deleteList(poActual);
-    poActual=0;
+    poActual=NULL;
     Range::List *pol=poVals;
-    Range::List *poActualEnd=0;
-    long nMinT,nMaxT;
-    while (pol!=0) {
+    Range::List *poActualEnd=NULL;
+    int nMinT,nMaxT;
+    while (pol!=NULL) {
         if (pol->nMin<0) nMinT=pol->nMin+nMaxValue; else nMinT=pol->nMin;
         if (pol->nMin<0) pol->nMin=0;
         if (pol->nMin>=nMaxValue) pol->nMin=nMaxValue-1;
@@ -173,20 +173,20 @@ void Range::setMaxValue(long nMaxValueP) {
         if (pol->nMax<0) pol->nMax=0;
         if (pol->nMax>=nMaxValue) pol->nMax=nMaxValue-1;
         if (nMaxT<nMinT) continue;
-        if (poActual==0) {
-            poActual=new Range::List(pol->eType,nMinT,nMaxT,0);
+        if (poActual==NULL) {
+            poActual=new Range::List(pol->eType,nMinT,nMaxT,NULL);
             poActualEnd=poActual;
         } else {
-            poActualEnd->poNext=new Range::List(pol->eType,nMinT,nMaxT,0);
+            poActualEnd->poNext=new Range::List(pol->eType,nMinT,nMaxT,NULL);
             poActualEnd=poActualEnd->poNext;
         }
         pol=pol->poNext;
     }
     sortList(poActual);
     // Now we merge successive ranges when they intersect or are consecutive
-    if (poActual!=0) {
+    if (poActual!=NULL) {
         pol=poActual;
-        while (pol->poNext!=0) {
+        while (pol->poNext!=NULL) {
             if (pol->poNext->eType==pol->eType && pol->poNext->nMin<=pol->nMax+1) {
                 if (pol->poNext->nMax>pol->nMax) pol->nMax=pol->poNext->nMax;
                 poActualEnd=pol->poNext->poNext;
@@ -198,10 +198,10 @@ void Range::setMaxValue(long nMaxValueP) {
 }
 
 size_t Range::getSize() const {
-    if (poVals==0) return nMaxValue*2;
+    if (poVals==NULL) return nMaxValue*2;
     Range::List *pol=poActual;
     size_t nSize=0;
-    while (pol!=0) {
+    while (pol!=NULL) {
         nSize+=(pol->nMax-pol->nMin+1);
         pol=pol->poNext;
     }
@@ -212,14 +212,15 @@ size_t Range::getSize() const {
 /*                          OGRSelafinDataSource()                      */
 /************************************************************************/
 
-OGRSelafinDataSource::OGRSelafinDataSource() {
-    papoLayers = NULL;
-    nLayers = 0;
-    pszName = NULL;
-    poHeader=0;
-    pszLockName=0;
-    poSpatialRef=0;
-}
+OGRSelafinDataSource::OGRSelafinDataSource() :
+    pszName(NULL),
+    pszLockName(NULL),
+    papoLayers(NULL),
+    nLayers(0),
+    bUpdate(FALSE),
+    poHeader(NULL),
+    poSpatialRef(NULL)
+{ }
 
 /************************************************************************/
 /*                         ~OGRSelafinDataSource()                      */
@@ -232,7 +233,7 @@ OGRSelafinDataSource::~OGRSelafinDataSource() {
     CPLFree( pszName );
     ReleaseLock();
     delete poHeader;
-    if (poSpatialRef!=0) poSpatialRef->Release();
+    if (poSpatialRef!=NULL) poSpatialRef->Release();
 }
 
 /************************************************************************/
@@ -274,7 +275,7 @@ int OGRSelafinDataSource::Open(const char * pszFilename, int bUpdateIn, int bCre
     bUpdate = bUpdateIn;
     if (bCreate && EQUAL(pszName, "/vsistdout/")) return TRUE;
     /* For writable /vsizip/, do nothing more */
-    if (bCreate && strncmp(pszName, "/vsizip/", 8) == 0) return TRUE;
+    if (bCreate && STARTS_WITH(pszName, "/vsizip/")) return TRUE;
     CPLString osFilename(pszName);
     CPLString osBaseFilename = CPLGetFilename(pszName);
     // Determine what sort of object this is.
@@ -285,7 +286,7 @@ int OGRSelafinDataSource::Open(const char * pszFilename, int bUpdateIn, int bCre
     if (VSI_ISREG(sStatBuf.st_mode)) return OpenTable( pszName );
 
     // Is this a single a ZIP file with only a Selafin file inside ?
-    if( strncmp(osFilename, "/vsizip/", 8) == 0 && VSI_ISREG(sStatBuf.st_mode) ) {
+    if( STARTS_WITH(osFilename, "/vsizip/") && VSI_ISREG(sStatBuf.st_mode) ) {
         char** papszFiles = VSIReadDir(osFilename);
         if (CSLCount(papszFiles) != 1) {
             CSLDestroy(papszFiles);
@@ -302,7 +303,7 @@ int OGRSelafinDataSource::Open(const char * pszFilename, int bUpdateIn, int bCre
 
     // Scan through for entries which look like Selafin files
     int nNotSelafinCount = 0, i;
-    char **papszNames = CPLReadDir( osFilename );
+    char **papszNames = VSIReadDir( osFilename );
     for( i = 0; papszNames != NULL && papszNames[i] != NULL; i++ ) {
         CPLString oSubFilename = CPLFormFilename( osFilename, papszNames[i], NULL );
         if( EQUAL(papszNames[i],".") || EQUAL(papszNames[i],"..") ) continue;
@@ -318,7 +319,7 @@ int OGRSelafinDataSource::Open(const char * pszFilename, int bUpdateIn, int bCre
     }
     CSLDestroy( papszNames );
 
-    // We presume that this is indeed intended to be a Selafin datasource if over half the files were Selafin files. 
+    // We presume that this is indeed intended to be a Selafin datasource if over half the files were Selafin files.
     return nNotSelafinCount < nLayers;
 #else
     return FALSE;
@@ -383,7 +384,7 @@ int OGRSelafinDataSource::OpenTable(const char * pszFilename) {
     if( fp == NULL ) {
         CPLError( CE_Warning, CPLE_OpenFailed, "Failed to open %s, %s.", pszFilename, VSIStrerror( errno ) );
         return FALSE;
-    } 
+    }
     if( !bUpdate && strstr(pszFilename, "/vsigzip/") == NULL && strstr(pszFilename, "/vsizip/") == NULL ) fp = (VSILFILE*) VSICreateBufferedReaderHandle((VSIVirtualHandle*)fp);
 
     // Quickly check if the file is in Selafin format, before actually starting to read to make it faster
@@ -409,11 +410,11 @@ int OGRSelafinDataSource::OpenTable(const char * pszFilename) {
     // Get layer base name
     CPLString osBaseLayerName = CPLGetBasename(pszFilename);
     CPLString osExt = CPLGetExtension(pszFilename);
-    if( strncmp(pszFilename, "/vsigzip/", 9) == 0 && EQUAL(osExt, "gz") ) {
+    if( STARTS_WITH(pszFilename, "/vsigzip/") && EQUAL(osExt, "gz") ) {
         size_t nPos=std::string::npos;
         if (strlen(pszFilename)>3) nPos=osExt.find_last_of('.',strlen(pszFilename)-4);
         if (nPos!=std::string::npos) {
-            osExt=osExt.substr(nPos+1,strlen(pszFilename)-4-nPos); 
+            osExt=osExt.substr(nPos+1,strlen(pszFilename)-4-nPos);
             osBaseLayerName=osBaseLayerName.substr(0,nPos);
         } else {
             osExt="";
@@ -422,7 +423,7 @@ int OGRSelafinDataSource::OpenTable(const char * pszFilename) {
 
     // Read header of file to get common information for all layers
     poHeader=Selafin::read_header(fp,pszFilename);
-    if (poHeader==0) {
+    if (poHeader==NULL) {
         VSIFCloseL(fp);
         CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open %s, wrong format.\n", pszFilename);
         return FALSE;
@@ -430,22 +431,22 @@ int OGRSelafinDataSource::OpenTable(const char * pszFilename) {
     if (poHeader->nEpsg!=0) {
         poSpatialRef=new OGRSpatialReference();
         if (poSpatialRef->importFromEPSG(poHeader->nEpsg)!=OGRERR_NONE) {
-            CPLError( CE_Warning, CPLE_AppDefined, "EPSG %li not found. Could not set datasource SRS.\n", poHeader->nEpsg);
+            CPLError( CE_Warning, CPLE_AppDefined, "EPSG %d not found. Could not set datasource SRS.\n", poHeader->nEpsg);
             delete poSpatialRef;
-            poSpatialRef=0;
+            poSpatialRef=NULL;
         }
     }
 
     // Create two layers for each selected time step: one for points, the other for elements
     int nNewLayers;
     poRange.setMaxValue(poHeader->nSteps);
-    nNewLayers=poRange.getSize();
+    nNewLayers=static_cast<int>(poRange.getSize());
     if (EQUAL(pszFilename, "/vsistdin/")) osBaseLayerName = "layer";
     CPLString osLayerName;
     papoLayers = (OGRSelafinLayer **) CPLRealloc(papoLayers, sizeof(void*) * (nLayers+nNewLayers));
     for (size_t j=0;j<2;++j) {
         SelafinTypeDef eType=(j==0)?POINTS:ELEMENTS;
-        for (long i=0;i<poHeader->nSteps;++i) {
+        for (int i=0;i<poHeader->nSteps;++i) {
             if (poRange.contains(eType,i)) {
                 char szTemp[30];
                 double dfTime;
@@ -454,8 +455,9 @@ int OGRSelafinDataSource::OpenTable(const char * pszFilename) {
                     CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open %s, wrong format.\n", pszFilename);
                     return FALSE;
                 }
-                if (poHeader->panStartDate==0) snprintf(szTemp,29,"%li",i); else {
-                    struct tm sDate={0};
+                if (poHeader->panStartDate==NULL) snprintf(szTemp,29,"%d",i); else {
+                    struct tm sDate;
+                    memset(&sDate, 0, sizeof(sDate));
                     sDate.tm_year=poHeader->panStartDate[0]-1900;
                     sDate.tm_mon=poHeader->panStartDate[1]-1;
                     sDate.tm_mday=poHeader->panStartDate[2];
@@ -471,7 +473,7 @@ int OGRSelafinDataSource::OpenTable(const char * pszFilename) {
             }
         }
     }
-    
+
     // Free allocated variables and exit
     return TRUE;
 }
@@ -495,14 +497,14 @@ OGRLayer *OGRSelafinDataSource::ICreateLayer( const char *pszLayerName, OGRSpati
     // Parse options
     double dfDate;
     const char *pszTemp=CSLFetchNameValue(papszOptions,"DATE");
-    if (pszTemp!=0) dfDate=CPLAtof(pszTemp); else dfDate=0.0;
+    if (pszTemp!=NULL) dfDate=CPLAtof(pszTemp); else dfDate=0.0;
     // Set the SRS of the datasource if this is the first layer
-    if (nLayers==0 && poSpatialRefP!=0) {
+    if (nLayers==0 && poSpatialRefP!=NULL) {
         poSpatialRef=poSpatialRefP;
         poSpatialRef->Reference();
         const char* szEpsg=poSpatialRef->GetAttrValue("GEOGCS|AUTHORITY",1);
-        long nEpsg=0;
-        if (szEpsg!=0) nEpsg=strtol(szEpsg,0,10);
+        int nEpsg=0;
+        if (szEpsg!=NULL) nEpsg=(int)strtol(szEpsg,NULL,10);
         if (nEpsg==0) {
             CPLError(CE_Warning,CPLE_AppDefined,"Could not find EPSG code for SRS. The SRS won't be saved in the datasource.");
         } else {
@@ -518,9 +520,14 @@ OGRLayer *OGRSelafinDataSource::ICreateLayer( const char *pszLayerName, OGRSpati
         CPLError( CE_Failure, CPLE_FileIO, "Could not write to Selafin file %s.\n",pszName);
         return NULL;
     }
-    double *pdfValues=0;
-    if (poHeader->nPoints>0) pdfValues=(double*)VSIMalloc2(sizeof(double),poHeader->nPoints);
-    for (long i=0;i<poHeader->nVar;++i) {
+    double *pdfValues=NULL;
+    if (poHeader->nPoints>0)
+    {
+        pdfValues=(double*)VSI_MALLOC2_VERBOSE(sizeof(double),poHeader->nPoints);
+        if( pdfValues == NULL )
+            return NULL;
+    }
+    for (int i=0;i<poHeader->nVar;++i) {
         if (Selafin::write_floatarray(poHeader->fp,pdfValues,poHeader->nPoints)==0) {
             CPLError( CE_Failure, CPLE_FileIO, "Could not write to Selafin file %s.\n",pszName);
             CPLFree(pdfValues);
@@ -555,19 +562,19 @@ OGRErr OGRSelafinDataSource::DeleteLayer( int iLayer ) {
         return OGRERR_FAILURE;
     }
     // Delete layer in file. Here we don't need to create a copy of the file because we only update values and it can't get corrupted even if the system crashes during the operation
-    long nNum=papoLayers[iLayer]->GetStepNumber();
+    int nNum=papoLayers[iLayer]->GetStepNumber();
     double dfTime;
-    double *dfValues=0;
-    long nTemp;
-    for (long i=nNum;i<poHeader->nSteps-1;++i) {
+    double *dfValues=NULL;
+    int nTemp;
+    for (int i=nNum;i<poHeader->nSteps-1;++i) {
         if (VSIFSeekL(poHeader->fp,poHeader->getPosition(i+1)+4,SEEK_SET)!=0 ||
-            Selafin::read_float(poHeader->fp,dfTime)==0 || 
+            Selafin::read_float(poHeader->fp,dfTime)==0 ||
             VSIFSeekL(poHeader->fp,poHeader->getPosition(i)+4,SEEK_SET)!=0 ||
             Selafin::write_float(poHeader->fp,dfTime)==0) {
             CPLError( CE_Failure, CPLE_FileIO, "Could not update Selafin file %s.\n",pszName);
             return OGRERR_FAILURE;
         }
-        for (long j=0;j<poHeader->nVar;++j) {
+        for (int j=0;j<poHeader->nVar;++j) {
             if (VSIFSeekL(poHeader->fp,poHeader->getPosition(i+1)+12,SEEK_SET)!=0 ||
                 (nTemp=Selafin::read_floatarray(poHeader->fp,&dfValues)) !=poHeader->nPoints ||
                 VSIFSeekL(poHeader->fp,poHeader->getPosition(i)+12,SEEK_SET)!=0 ||
@@ -580,11 +587,11 @@ OGRErr OGRSelafinDataSource::DeleteLayer( int iLayer ) {
         }
     }
     // Delete all layers with the same step number in layer list. Usually there are two of them: one for points and one for elements, but we can't rely on that because of possible layer filtering specifications
-    for (long i=0;i<nLayers;++i) {
+    for (int i=0;i<nLayers;++i) {
         if (papoLayers[i]->GetStepNumber()==nNum) {
             delete papoLayers[i];
             nLayers--;
-            for (long j=i;j<nLayers;++j) papoLayers[j]=papoLayers[j+1];
+            for (int j=i;j<nLayers;++j) papoLayers[j]=papoLayers[j+1];
             --i;
         }
     }
diff --git a/ogr/ogrsf_frmts/selafin/ogrselafindriver.cpp b/ogr/ogrsf_frmts/selafin/ogrselafindriver.cpp
index db27242..2ee2e29 100644
--- a/ogr/ogrsf_frmts/selafin/ogrselafindriver.cpp
+++ b/ogr/ogrsf_frmts/selafin/ogrselafindriver.cpp
@@ -63,7 +63,7 @@ static GDALDataset *OGRSelafinDriverOpen( GDALOpenInfo* poOpenInfo ) {
 
     if( OGRSelafinDriverIdentify(poOpenInfo) == 0 )
         return NULL;
-    
+
     OGRSelafinDataSource *poDS = new OGRSelafinDataSource();
     if( !poDS->Open(poOpenInfo->pszFilename, poOpenInfo->eAccess == GA_Update, FALSE) ) {
         delete poDS;
@@ -92,15 +92,15 @@ static GDALDataset *OGRSelafinDriverCreate( const char * pszName,
     // Parse options
     const char *pszTemp=CSLFetchNameValue(papszOptions,"TITLE");
     char pszTitle[81];
-    long pnDate[6]={-1,0};
-    if (pszTemp!=0) strncpy(pszTitle,pszTemp,72); else memset(pszTitle,' ',72);
+    int pnDate[6]={-1,0};
+    if (pszTemp!=NULL) strncpy(pszTitle,pszTemp,72); else memset(pszTitle,' ',72);
     pszTemp=CSLFetchNameValue(papszOptions,"DATE");
-    if (pszTemp!=0) {
+    if (pszTemp!=NULL) {
         const char* pszErrorMessage="Wrong format for date parameter: must be \"%%Y-%%m-%%d_%%H:%%M:%%S\", ignored";
         const char *pszc=pszTemp;
         pnDate[0]=atoi(pszTemp);
         if (pnDate[0]<=0) CPLError(CE_Warning, CPLE_AppDefined,"%s",pszErrorMessage); else {
-            if (pnDate[0]<100) pnDate[0]+=2000; 
+            if (pnDate[0]<100) pnDate[0]+=2000;
         }
         while (*pszc!=0 && *pszc!='-') ++pszc;
         pnDate[1]=atoi(pszc);
@@ -127,7 +127,7 @@ static GDALDataset *OGRSelafinDriverCreate( const char * pszName,
     strncpy(pszTitle+72,"SERAPHIN",9);
     bool bError=false;
     if (Selafin::write_string(fp,pszTitle,80)==0) bError=true;
-    long pnTemp[10]={0};
+    int pnTemp[10]={0};
     if (Selafin::write_intarray(fp,pnTemp,2)==0) bError=true;
     if (pnDate[0]>=0) pnTemp[9]=1;
     if (Selafin::write_intarray(fp,pnTemp,10)==0) bError=true;
@@ -138,8 +138,8 @@ static GDALDataset *OGRSelafinDriverCreate( const char * pszName,
     if (Selafin::write_intarray(fp,pnTemp,4)==0) bError=true;
     if (Selafin::write_intarray(fp,pnTemp,0)==0) bError=true;
     if (Selafin::write_intarray(fp,pnTemp,0)==0) bError=true;
-    if (Selafin::write_floatarray(fp,0,0)==0) bError=true;
-    if (Selafin::write_floatarray(fp,0,0)==0) bError=true;
+    if (Selafin::write_floatarray(fp,NULL,0)==0) bError=true;
+    if (Selafin::write_floatarray(fp,NULL,0)==0) bError=true;
     VSIFCloseL(fp);
     if (bError) {
         CPLError(CE_Failure, CPLE_AppDefined,"Error writing to file %s.",pszName);
@@ -165,37 +165,35 @@ static CPLErr OGRSelafinDriverDelete( const char *pszFilename ) {
 /************************************************************************/
 /*                           RegisterOGRSelafin()                       */
 /************************************************************************/
+
 void RegisterOGRSelafin() {
-    GDALDriver  *poDriver;
 
-    if( GDALGetDriverByName( "Selafin" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    if( GDALGetDriverByName( "Selafin" ) != NULL )
+        return;
 
-        poDriver->SetDescription( "Selafin" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "Selafin" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Selafin" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_selafin.html" );
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    poDriver->SetDescription( "Selafin" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "Selafin" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Selafin" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_selafin.html" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "  <Option name='TITLE' type='string' description='Title of the datasource, stored in the Selafin file. The title must not hold more than 72 characters.'/>"
 "  <Option name='DATE' type='string' description='Starting date of the simulation. Each layer in a Selafin file is characterized by a date, counted in seconds since a reference date. This option allows providing the reference date. The format of this field must be YYYY-MM-DD_hh:mm:ss'/>"
 "</CreationOptionList>");
-        poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
 "<LayerCreationOptionList>"
 "  <Option name='DATE' type='float' description='Date of the time step, in seconds, relative to the starting date of the simulation.'/>"
 "</LayerCreationOptionList>");
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = OGRSelafinDriverOpen;
-        poDriver->pfnIdentify = OGRSelafinDriverIdentify;
-        poDriver->pfnCreate = OGRSelafinDriverCreate;
-        poDriver->pfnDelete = OGRSelafinDriverDelete;
+    poDriver->pfnOpen = OGRSelafinDriverOpen;
+    poDriver->pfnIdentify = OGRSelafinDriverIdentify;
+    poDriver->pfnCreate = OGRSelafinDriverCreate;
+    poDriver->pfnDelete = OGRSelafinDriverDelete;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/selafin/ogrselafinlayer.cpp b/ogr/ogrsf_frmts/selafin/ogrselafinlayer.cpp
index 0423daa..a5a5dc8 100644
--- a/ogr/ogrsf_frmts/selafin/ogrselafinlayer.cpp
+++ b/ogr/ogrsf_frmts/selafin/ogrselafinlayer.cpp
@@ -37,7 +37,7 @@
 /************************************************************************/
 /*                           Utilities functions                        */
 /************************************************************************/
-void MoveOverwrite(VSILFILE *fpDest,VSILFILE *fpSource) {
+static void MoveOverwrite(VSILFILE *fpDest,VSILFILE *fpSource) {
     VSIRewindL(fpSource);
     VSIRewindL(fpDest);
     VSIFTruncateL(fpDest,0);
@@ -76,8 +76,8 @@ OGRSelafinLayer::OGRSelafinLayer( const char *pszLayerNameP, int bUpdateP,OGRSpa
 OGRSelafinLayer::~OGRSelafinLayer() {
     //CPLDebug("Selafin","Closing layer %s",GetName());
     poFeatureDefn->Release();
-    //poHeader->nRefCount--;  
-    //if (poHeader->nRefCount==0) delete poHeader; 
+    //poHeader->nRefCount--;
+    //if (poHeader->nRefCount==0) delete poHeader;
 }
 
 /************************************************************************/
@@ -148,25 +148,25 @@ OGRFeature* OGRSelafinLayer::GetFeature(GIntBig nFID) {
         poFeature->SetGeometryDirectly(new OGRPoint(poHeader->paadfCoords[0][nFID],poHeader->paadfCoords[1][nFID]));
         poFeature->SetFID(nFID);
         for (int i=0;i<poHeader->nVar;++i) {
-            VSIFSeekL(poHeader->fp,poHeader->getPosition(nStepNumber,(long)nFID,i),SEEK_SET);
+            VSIFSeekL(poHeader->fp,poHeader->getPosition(nStepNumber,(int)nFID,i),SEEK_SET);
             if (Selafin::read_float(poHeader->fp,nData)==1) poFeature->SetField(i,nData);
         }
         return poFeature;
     } else {
         if (nFID>=poHeader->nElements) return NULL;
         double *anData;
-        anData=(double*)VSIMalloc2(sizeof(double),poHeader->nVar);
-        if (poHeader->nVar>0 && anData==0) return NULL;
-        for (long i=0;i<poHeader->nVar;++i) anData[i]=0;
+        anData=(double*)VSI_MALLOC2_VERBOSE(sizeof(double),poHeader->nVar);
+        if (poHeader->nVar>0 && anData==NULL) return NULL;
+        for (int i=0;i<poHeader->nVar;++i) anData[i]=0;
         double nData;
         OGRFeature *poFeature=new OGRFeature(poFeatureDefn);
         poFeature->SetFID(nFID);
         OGRPolygon *poPolygon=new OGRPolygon();
         OGRLinearRing *poLinearRing=new OGRLinearRing();
-        for (long j=0;j<poHeader->nPointsPerElement;++j) {
-            long nPointNum=poHeader->panConnectivity[nFID*poHeader->nPointsPerElement+j]-1;
+        for (int j=0;j<poHeader->nPointsPerElement;++j) {
+            int nPointNum=poHeader->panConnectivity[nFID*poHeader->nPointsPerElement+j]-1;
             poLinearRing->addPoint(poHeader->paadfCoords[0][nPointNum],poHeader->paadfCoords[1][nPointNum]);
-            for (long i=0;i<poHeader->nVar;++i) {
+            for (int i=0;i<poHeader->nVar;++i) {
                 VSIFSeekL(poHeader->fp,poHeader->getPosition(nStepNumber,nPointNum,i),SEEK_SET);
                 if (Selafin::read_float(poHeader->fp,nData)==1) anData[i]+=nData;
             }
@@ -174,7 +174,7 @@ OGRFeature* OGRSelafinLayer::GetFeature(GIntBig nFID) {
         poPolygon->addRingDirectly(poLinearRing);
         poPolygon->closeRings();
         poFeature->SetGeometryDirectly(poPolygon);
-        for (long i=0;i<poHeader->nVar;++i) poFeature->SetField(i,anData[i]/poHeader->nPointsPerElement);
+        for (int i=0;i<poHeader->nVar;++i) poFeature->SetField(i,anData[i]/poHeader->nPointsPerElement);
         CPLFree(anData);
         return poFeature;
     }
@@ -188,9 +188,9 @@ GIntBig OGRSelafinLayer::GetFeatureCount(int bForce) {
     //CPLDebug("Selafin","GetFeatureCount(%i)",bForce);
     if (m_poFilterGeom==NULL && m_poAttrQuery==NULL) return (eType==POINTS)?poHeader->nPoints:poHeader->nElements;
     if (bForce==FALSE) return -1;
-    long i=0;
+    int i=0;
     int nFeatureCount=0;
-    long nMax=(eType==POINTS)?poHeader->nPoints:poHeader->nElements;
+    int nMax=(eType==POINTS)?poHeader->nPoints:poHeader->nElements;
     while (i<nMax) {
         OGRFeature *poFeature=GetFeature(i++);
         if( (m_poFilterGeom == NULL || FilterGeometry( poFeature->GetGeometryRef() ) ) && (m_poAttrQuery == NULL || m_poAttrQuery->Evaluate( poFeature )) ) ++nFeatureCount;
@@ -220,7 +220,7 @@ OGRErr OGRSelafinLayer::GetExtent(OGREnvelope *psExtent,
 /************************************************************************/
 OGRErr OGRSelafinLayer::ISetFeature(OGRFeature *poFeature) {
     OGRGeometry *poGeom=poFeature->GetGeometryRef();
-    if (poGeom==0) return OGRERR_FAILURE;
+    if (poGeom==NULL) return OGRERR_FAILURE;
     if (eType==POINTS) {
         // If it's a point layer, it's the "easy" case: we change the coordinates and attributes of the feature and update the file
         if (poGeom->getGeometryType()!=wkbPoint) {
@@ -232,15 +232,15 @@ OGRErr OGRSelafinLayer::ISetFeature(OGRFeature *poFeature) {
         poHeader->paadfCoords[0][nFID]=poPoint->getX();
         poHeader->paadfCoords[1][nFID]=poPoint->getY();
         CPLDebug("Selafin","SetFeature(" CPL_FRMT_GIB ",%f,%f)",nFID,poHeader->paadfCoords[0][nFID],poHeader->paadfCoords[1][nFID]);
-        if (VSIFSeekL(poHeader->fp,88+16+40*poHeader->nVar+48+((poHeader->panStartDate!=0)?32:0)+24+(poHeader->nElements*poHeader->nPointsPerElement+2)*4+(poHeader->nPoints+2)*4+4+nFID*4,SEEK_SET)!=0) return OGRERR_FAILURE;
+        if (VSIFSeekL(poHeader->fp,88+16+40*poHeader->nVar+48+((poHeader->panStartDate!=NULL)?32:0)+24+(poHeader->nElements*poHeader->nPointsPerElement+2)*4+(poHeader->nPoints+2)*4+4+nFID*4,SEEK_SET)!=0) return OGRERR_FAILURE;
         CPLDebug("Selafin","Write_float(" CPL_FRMT_GUIB ",%f)",VSIFTellL(poHeader->fp),poHeader->paadfCoords[0][nFID]-poHeader->adfOrigin[0]);
         if (Selafin::write_float(poHeader->fp,poHeader->paadfCoords[0][nFID]-poHeader->adfOrigin[0])==0) return OGRERR_FAILURE;
-        if (VSIFSeekL(poHeader->fp,88+16+40*poHeader->nVar+48+((poHeader->panStartDate!=0)?32:0)+24+(poHeader->nElements*poHeader->nPointsPerElement+2)*4+(poHeader->nPoints+2)*4+(poHeader->nPoints+2)*4+4+nFID*4,SEEK_SET)!=0) return OGRERR_FAILURE;
+        if (VSIFSeekL(poHeader->fp,88+16+40*poHeader->nVar+48+((poHeader->panStartDate!=NULL)?32:0)+24+(poHeader->nElements*poHeader->nPointsPerElement+2)*4+(poHeader->nPoints+2)*4+(poHeader->nPoints+2)*4+4+nFID*4,SEEK_SET)!=0) return OGRERR_FAILURE;
         CPLDebug("Selafin","Write_float(" CPL_FRMT_GUIB ",%f)",VSIFTellL(poHeader->fp),poHeader->paadfCoords[1][nFID]-poHeader->adfOrigin[1]);
         if (Selafin::write_float(poHeader->fp,poHeader->paadfCoords[1][nFID]-poHeader->adfOrigin[1])==0) return OGRERR_FAILURE;
-        for (long i=0;i<poHeader->nVar;++i) {
+        for (int i=0;i<poHeader->nVar;++i) {
             double nData=poFeature->GetFieldAsDouble(i);
-            if (VSIFSeekL(poHeader->fp,poHeader->getPosition(nStepNumber,(long)nFID,i),SEEK_SET)!=0) return OGRERR_FAILURE;
+            if (VSIFSeekL(poHeader->fp,poHeader->getPosition(nStepNumber,(int)nFID,i),SEEK_SET)!=0) return OGRERR_FAILURE;
             if (Selafin::write_float(poHeader->fp,nData)==0) return OGRERR_FAILURE;
         }
     } else {
@@ -252,21 +252,21 @@ OGRErr OGRSelafinLayer::ISetFeature(OGRFeature *poFeature) {
         }
         OGRLinearRing *poLinearRing=((OGRPolygon*)poGeom)->getExteriorRing();
         if (poLinearRing->getNumPoints()!=poHeader->nPointsPerElement+1) {
-            CPLError( CE_Failure, CPLE_AppDefined, "The new feature should have the same number of vertices %li as the existing ones in the layer.",poHeader->nPointsPerElement);
+            CPLError( CE_Failure, CPLE_AppDefined, "The new feature should have the same number of vertices %d as the existing ones in the layer.",poHeader->nPointsPerElement);
             return OGRERR_FAILURE;
         }
         CPLError(CE_Warning,CPLE_AppDefined,"The attributes of elements layer in Selafin files can't be updated.");
         CPLDebug("Selafin","SetFeature(" CPL_FRMT_GIB ",%f,%f,%f,%f,%f,%f)",poFeature->GetFID(),poLinearRing->getX(0),poLinearRing->getY(0),poLinearRing->getX(1),poLinearRing->getY(1),poLinearRing->getX(2),poLinearRing->getY(2));   //!< This is not safe as we can't be sure there are at least three vertices in the linear ring, but we can assume that for a debug mode
-        long nFID=poFeature->GetFID();
+        int nFID=static_cast<int>(poFeature->GetFID());
         // Now we change the coordinates of points in the layer based on the vertices of the new polygon. We don't look at the order of points and we assume that it is the same as in the original layer.
-        for (long i=0;i<poHeader->nPointsPerElement;++i) {
-            long nPointId=poHeader->panConnectivity[nFID*poHeader->nPointsPerElement+i]-1;
+        for (int i=0;i<poHeader->nPointsPerElement;++i) {
+            int nPointId=poHeader->panConnectivity[nFID*poHeader->nPointsPerElement+i]-1;
             poHeader->paadfCoords[0][nPointId]=poLinearRing->getX(i);
             poHeader->paadfCoords[1][nPointId]=poLinearRing->getY(i);
-            if (VSIFSeekL(poHeader->fp,88+16+40*poHeader->nVar+48+((poHeader->panStartDate!=0)?32:0)+24+(poHeader->nElements*poHeader->nPointsPerElement+2)*4+(poHeader->nPoints+2)*4+4+nPointId*4,SEEK_SET)!=0) return OGRERR_FAILURE;
+            if (VSIFSeekL(poHeader->fp,88+16+40*poHeader->nVar+48+((poHeader->panStartDate!=NULL)?32:0)+24+(poHeader->nElements*poHeader->nPointsPerElement+2)*4+(poHeader->nPoints+2)*4+4+nPointId*4,SEEK_SET)!=0) return OGRERR_FAILURE;
             CPLDebug("Selafin","Write_float(" CPL_FRMT_GUIB ",%f)",VSIFTellL(poHeader->fp),poHeader->paadfCoords[0][nPointId]-poHeader->adfOrigin[0]);
             if (Selafin::write_float(poHeader->fp,poHeader->paadfCoords[0][nPointId]-poHeader->adfOrigin[0])==0) return OGRERR_FAILURE;
-            if (VSIFSeekL(poHeader->fp,88+16+40*poHeader->nVar+48+((poHeader->panStartDate!=0)?32:0)+24+(poHeader->nElements*poHeader->nPointsPerElement+2)*4+(poHeader->nPoints+2)*4+(poHeader->nPoints+2)*4+4+nPointId*4,SEEK_SET)!=0) return OGRERR_FAILURE;
+            if (VSIFSeekL(poHeader->fp,88+16+40*poHeader->nVar+48+((poHeader->panStartDate!=NULL)?32:0)+24+(poHeader->nElements*poHeader->nPointsPerElement+2)*4+(poHeader->nPoints+2)*4+(poHeader->nPoints+2)*4+4+nPointId*4,SEEK_SET)!=0) return OGRERR_FAILURE;
             CPLDebug("Selafin","Write_float(" CPL_FRMT_GUIB ",%f)",VSIFTellL(poHeader->fp),poHeader->paadfCoords[1][nPointId]-poHeader->adfOrigin[1]);
             if (Selafin::write_float(poHeader->fp,poHeader->paadfCoords[1][nPointId]-poHeader->adfOrigin[1])==0) return OGRERR_FAILURE;
         }
@@ -280,7 +280,7 @@ OGRErr OGRSelafinLayer::ISetFeature(OGRFeature *poFeature) {
 /************************************************************************/
 OGRErr OGRSelafinLayer::ICreateFeature(OGRFeature *poFeature) {
     OGRGeometry *poGeom=poFeature->GetGeometryRef();
-    if (poGeom==0) return OGRERR_FAILURE;
+    if (poGeom==NULL) return OGRERR_FAILURE;
     if (VSIFSeekL(poHeader->fp,poHeader->getPosition(0),SEEK_SET)!=0) return OGRERR_FAILURE;
     if (eType==POINTS) {
         // If it's a point layer, it's the "easy" case: we add a new point feature and update the file
@@ -290,7 +290,7 @@ OGRErr OGRSelafinLayer::ICreateFeature(OGRFeature *poFeature) {
         }
         OGRPoint *poPoint=(OGRPoint*)poGeom;
         poFeature->SetFID(poHeader->nPoints);
-        CPLDebug("Selafin","CreateFeature(%li,%f,%f)",poHeader->nPoints,poPoint->getX(),poPoint->getY());
+        CPLDebug("Selafin","CreateFeature(%d,%f,%f)",poHeader->nPoints,poPoint->getX(),poPoint->getY());
         // Change the header to add the new feature
         poHeader->addPoint(poPoint->getX(),poPoint->getY());
     } else {
@@ -316,66 +316,65 @@ OGRErr OGRSelafinLayer::ICreateFeature(OGRFeature *poFeature) {
             }
             poHeader->nPointsPerElement=nNum-1;
             if (poHeader->nElements>0) {
-                poHeader->panConnectivity=(long*)CPLRealloc(poHeader->panConnectivity,poHeader->nElements*poHeader->nPointsPerElement);
-                if (poHeader->panConnectivity==0) return OGRERR_FAILURE;
+                poHeader->panConnectivity=(int*)CPLRealloc(poHeader->panConnectivity,poHeader->nElements*poHeader->nPointsPerElement);
+                if (poHeader->panConnectivity==NULL) return OGRERR_FAILURE;
             }
         } else {
             if (poLinearRing->getNumPoints()!=poHeader->nPointsPerElement+1) {
-                CPLError( CE_Failure, CPLE_AppDefined, "The new feature should have the same number of vertices %li as the existing ones in the layer.",poHeader->nPointsPerElement);
+                CPLError( CE_Failure, CPLE_AppDefined, "The new feature should have the same number of vertices %d as the existing ones in the layer.",poHeader->nPointsPerElement);
                 return OGRERR_FAILURE;
             }
         }
 
         // Now we look for vertices that are already referenced as points in the file
         int *anMap;
-        anMap=(int*)VSIMalloc2(sizeof(int),poHeader->nPointsPerElement);
-        if (anMap==0) {
-            CPLError(CE_Failure,CPLE_AppDefined,"%s","Not enough memory for operation");
+        anMap=(int*)VSI_MALLOC2_VERBOSE(sizeof(int),poHeader->nPointsPerElement);
+        if (anMap==NULL) {
             return OGRERR_FAILURE;
         }
-        for (long i=0;i<poHeader->nPointsPerElement;++i) anMap[i]=-1;
+        for (int i=0;i<poHeader->nPointsPerElement;++i) anMap[i]=-1;
         if (poHeader->nPoints>0) {
             CPLRectObj *poBB=poHeader->getBoundingBox();
             double dfMaxDist=(poBB->maxx-poBB->minx)/sqrt((double)(poHeader->nPoints))/1000.0;   //!< Heuristic approach to estimate a maximum distance such that two points are considered equal if they are closer from each other
             dfMaxDist*=dfMaxDist;
             delete poBB;
-            for (long i=0;i<poHeader->nPointsPerElement;++i) anMap[i]=poHeader->getClosestPoint(poLinearRing->getX(i),poLinearRing->getY(i),dfMaxDist);
+            for (int i=0;i<poHeader->nPointsPerElement;++i) anMap[i]=poHeader->getClosestPoint(poLinearRing->getX(i),poLinearRing->getY(i),dfMaxDist);
         }
 
         // We add new points if needed only
-        for (long i=0;i<poHeader->nPointsPerElement;++i) if (anMap[i]==-1) {
+        for (int i=0;i<poHeader->nPointsPerElement;++i) if (anMap[i]==-1) {
             poHeader->addPoint(poLinearRing->getX(i),poLinearRing->getY(i));
             anMap[i]=poHeader->nPoints-1;
         }
 
         // And we update the connectivity table to add the new element
         poHeader->nElements++;
-        poHeader->panConnectivity=(long*)CPLRealloc(poHeader->panConnectivity,sizeof(long)*poHeader->nPointsPerElement*poHeader->nElements);
-        for (long i=0;i<poHeader->nPointsPerElement;++i) {
+        poHeader->panConnectivity=(int*)CPLRealloc(poHeader->panConnectivity,sizeof(int)*poHeader->nPointsPerElement*poHeader->nElements);
+        for (int i=0;i<poHeader->nPointsPerElement;++i) {
             poHeader->panConnectivity[poHeader->nPointsPerElement*(poHeader->nElements-1)+i]=anMap[i]+1;
         }
         poHeader->setUpdated();
         CPLFree(anMap);
-        
+
     }
 
     // Now comes the real insertion. Since values have to be inserted nearly everywhere in the file and we don't want to store everything in memory to overwrite it, we create a new copy of it where we write the new values
     VSILFILE *fpNew;
-    const char *pszTempfile=CPLGenerateTempFilename(0);
+    const char *pszTempfile=CPLGenerateTempFilename(NULL);
     fpNew=VSIFOpenL(pszTempfile,"wb+");
     if( fpNew == NULL ) {
         CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open temporary file %s with write access, %s.",pszTempfile, VSIStrerror( errno ) );
         return OGRERR_FAILURE;
-    } 
+    }
     if (Selafin::write_header(fpNew,poHeader)==0) {
         VSIFCloseL(fpNew);
         VSIUnlink(pszTempfile);
         return OGRERR_FAILURE;
     }
-    long nLen;
+    int nLen;
     double dfDate;
     double *padfValues;
-    for (long i=0;i<poHeader->nSteps;++i) {
+    for (int i=0;i<poHeader->nSteps;++i) {
         if (Selafin::read_integer(poHeader->fp,nLen,true)==0 ||
                 Selafin::read_float(poHeader->fp,dfDate)==0 ||
                 Selafin::read_integer(poHeader->fp,nLen,true)==0 ||
@@ -386,7 +385,7 @@ OGRErr OGRSelafinLayer::ICreateFeature(OGRFeature *poFeature) {
             VSIUnlink(pszTempfile);
             return OGRERR_FAILURE;
         }
-        for (long j=0;j<poHeader->nVar;++j) {
+        for (int j=0;j<poHeader->nVar;++j) {
             if (Selafin::read_floatarray(poHeader->fp,&padfValues)==-1) {
                 VSIFCloseL(fpNew);
                 VSIUnlink(pszTempfile);
@@ -406,7 +405,7 @@ OGRErr OGRSelafinLayer::ICreateFeature(OGRFeature *poFeature) {
                 VSIUnlink(pszTempfile);
                 return OGRERR_FAILURE;
             }
-            CPLFree(padfValues);   
+            CPLFree(padfValues);
         }
     }
 
@@ -440,28 +439,28 @@ OGRErr OGRSelafinLayer::CreateField(OGRFieldDefn *poField,
     poHeader->nVar++;
     poHeader->setUpdated();
     poHeader->papszVariables=(char**)CPLRealloc(poHeader->papszVariables,sizeof(char*)*poHeader->nVar);
-    poHeader->papszVariables[poHeader->nVar-1]=(char*)VSIMalloc2(sizeof(char),33);
+    poHeader->papszVariables[poHeader->nVar-1]=(char*)VSI_MALLOC2_VERBOSE(sizeof(char),33);
     strncpy(poHeader->papszVariables[poHeader->nVar-1],poField->GetNameRef(),32);
     poHeader->papszVariables[poHeader->nVar-1][32]=0;
     poFeatureDefn->AddFieldDefn(poField);
 
     // Now comes the real insertion. Since values have to be inserted nearly everywhere in the file and we don't want to store everything in memory to overwrite it, we create a new copy of it where we write the new values
     VSILFILE *fpNew;
-    const char *pszTempfile=CPLGenerateTempFilename(0);
+    const char *pszTempfile=CPLGenerateTempFilename(NULL);
     fpNew=VSIFOpenL(pszTempfile,"wb+");
     if( fpNew == NULL ) {
         CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open temporary file %s with write access, %s.",pszTempfile, VSIStrerror( errno ) );
         return OGRERR_FAILURE;
-    } 
+    }
     if (Selafin::write_header(fpNew,poHeader)==0) {
         VSIFCloseL(fpNew);
         VSIUnlink(pszTempfile);
         return OGRERR_FAILURE;
     }
-    long nLen;
+    int nLen;
     double dfDate;
     double *padfValues;
-    for (long i=0;i<poHeader->nSteps;++i) {
+    for (int i=0;i<poHeader->nSteps;++i) {
         if (Selafin::read_integer(poHeader->fp,nLen,true)==0 ||
                 Selafin::read_float(poHeader->fp,dfDate)==0 ||
                 Selafin::read_integer(poHeader->fp,nLen,true)==0 ||
@@ -472,7 +471,7 @@ OGRErr OGRSelafinLayer::CreateField(OGRFieldDefn *poField,
             VSIUnlink(pszTempfile);
             return OGRERR_FAILURE;
         }
-        for (long j=0;j<poHeader->nVar-1;++j) {
+        for (int j=0;j<poHeader->nVar-1;++j) {
             if (Selafin::read_floatarray(poHeader->fp,&padfValues)==-1) {
                 VSIFCloseL(fpNew);
                 VSIUnlink(pszTempfile);
@@ -484,17 +483,17 @@ OGRErr OGRSelafinLayer::CreateField(OGRFieldDefn *poField,
                 VSIUnlink(pszTempfile);
                 return OGRERR_FAILURE;
             }
-            CPLFree(padfValues);   
+            CPLFree(padfValues);
         }
-        padfValues=(double*)VSIMalloc2(sizeof(double),poHeader->nPoints);
-        for (long k=0;k<poHeader->nPoints;++k) padfValues[k]=0;
+        padfValues=(double*)VSI_MALLOC2_VERBOSE(sizeof(double),poHeader->nPoints);
+        for (int k=0;k<poHeader->nPoints;++k) padfValues[k]=0;
         if (Selafin::write_floatarray(fpNew,padfValues,poHeader->nPoints)==0) {
             CPLFree(padfValues);
             VSIFCloseL(fpNew);
             VSIUnlink(pszTempfile);
             return OGRERR_FAILURE;
         }
-        CPLFree(padfValues);   
+        CPLFree(padfValues);
     }
     MoveOverwrite(poHeader->fp,fpNew);
     VSIUnlink(pszTempfile);
@@ -511,27 +510,27 @@ OGRErr OGRSelafinLayer::DeleteField(int iField) {
     poHeader->nVar--;
     poHeader->setUpdated();
     CPLFree(poHeader->papszVariables[iField]);
-    for (long i=iField;i<poHeader->nVar;++i) poHeader->papszVariables[i]=poHeader->papszVariables[i+1];
+    for (int i=iField;i<poHeader->nVar;++i) poHeader->papszVariables[i]=poHeader->papszVariables[i+1];
     poHeader->papszVariables=(char**)CPLRealloc(poHeader->papszVariables,sizeof(char*)*poHeader->nVar);
     poFeatureDefn->DeleteFieldDefn(iField);
-    
+
     // Now comes the real deletion. Since values have to be deleted nearly everywhere in the file and we don't want to store everything in memory to overwrite it, we create a new copy of it where we write the new values
     VSILFILE *fpNew;
-    const char *pszTempfile=CPLGenerateTempFilename(0);
+    const char *pszTempfile=CPLGenerateTempFilename(NULL);
     fpNew=VSIFOpenL(pszTempfile,"wb+");
     if( fpNew == NULL ) {
         CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open temporary file %s with write access, %s.",pszTempfile, VSIStrerror( errno ) );
         return OGRERR_FAILURE;
-    } 
+    }
     if (Selafin::write_header(fpNew,poHeader)==0) {
         VSIFCloseL(fpNew);
         VSIUnlink(pszTempfile);
         return OGRERR_FAILURE;
     }
-    long nLen;
+    int nLen;
     double dfDate;
     double *padfValues;
-    for (long i=0;i<poHeader->nSteps;++i) {
+    for (int i=0;i<poHeader->nSteps;++i) {
         if (Selafin::read_integer(poHeader->fp,nLen,true)==0 ||
                 Selafin::read_float(poHeader->fp,dfDate)==0 ||
                 Selafin::read_integer(poHeader->fp,nLen,true)==0 ||
@@ -542,7 +541,7 @@ OGRErr OGRSelafinLayer::DeleteField(int iField) {
             VSIUnlink(pszTempfile);
             return OGRERR_FAILURE;
         }
-        for (long j=0;j<poHeader->nVar;++j) {
+        for (int j=0;j<poHeader->nVar;++j) {
             if (Selafin::read_floatarray(poHeader->fp,&padfValues)==-1) {
                 VSIFCloseL(fpNew);
                 VSIUnlink(pszTempfile);
@@ -556,7 +555,7 @@ OGRErr OGRSelafinLayer::DeleteField(int iField) {
                     return OGRERR_FAILURE;
                 }
             }
-            CPLFree(padfValues);   
+            CPLFree(padfValues);
         }
     }
     MoveOverwrite(poHeader->fp,fpNew);
@@ -571,29 +570,29 @@ OGRErr OGRSelafinLayer::ReorderFields(int *panMap) {
     CPLDebug("Selafin","ReorderFields()");
     if (VSIFSeekL(poHeader->fp,poHeader->getPosition(0),SEEK_SET)!=0) return OGRERR_FAILURE;
     // Change the header according to the map
-    char **papszNew=(char**)VSIMalloc2(sizeof(char*),poHeader->nVar);
-    for (long i=0;i<poHeader->nVar;++i) papszNew[i]=poHeader->papszVariables[panMap[i]];
+    char **papszNew=(char**)VSI_MALLOC2_VERBOSE(sizeof(char*),poHeader->nVar);
+    for (int i=0;i<poHeader->nVar;++i) papszNew[i]=poHeader->papszVariables[panMap[i]];
     CPLFree(poHeader->papszVariables);
     poHeader->papszVariables=papszNew;
     poFeatureDefn->ReorderFieldDefns(panMap);
 
     // Now comes the real change.
     VSILFILE *fpNew;
-    const char *pszTempfile=CPLGenerateTempFilename(0);
+    const char *pszTempfile=CPLGenerateTempFilename(NULL);
     fpNew=VSIFOpenL(pszTempfile,"wb+");
     if( fpNew == NULL ) {
         CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open temporary file %s with write access, %s.",pszTempfile, VSIStrerror( errno ) );
         return OGRERR_FAILURE;
-    } 
+    }
     if (Selafin::write_header(fpNew,poHeader)==0) {
         VSIFCloseL(fpNew);
         VSIUnlink(pszTempfile);
         return OGRERR_FAILURE;
     }
-    long nLen;
+    int nLen;
     double dfDate;
-    double *padfValues=0;
-    for (long i=0;i<poHeader->nSteps;++i) {
+    double *padfValues=NULL;
+    for (int i=0;i<poHeader->nSteps;++i) {
         if (Selafin::read_integer(poHeader->fp,nLen,true)==0 ||
                 Selafin::read_float(poHeader->fp,dfDate)==0 ||
                 Selafin::read_integer(poHeader->fp,nLen,true)==0 ||
@@ -604,7 +603,7 @@ OGRErr OGRSelafinLayer::ReorderFields(int *panMap) {
             VSIUnlink(pszTempfile);
             return OGRERR_FAILURE;
         }
-        for (long j=0;j<poHeader->nVar;++j) {
+        for (int j=0;j<poHeader->nVar;++j) {
             if (VSIFSeekL(poHeader->fp,poHeader->getPosition(i,-1,panMap[j]),SEEK_SET)!=0 || Selafin::read_floatarray(poHeader->fp,&padfValues)==-1) {
                 VSIFCloseL(fpNew);
                 VSIUnlink(pszTempfile);
@@ -629,7 +628,7 @@ OGRErr OGRSelafinLayer::ReorderFields(int *panMap) {
 /************************************************************************/
 OGRErr OGRSelafinLayer::AlterFieldDefn(int iField,
                                        OGRFieldDefn *poNewFieldDefn,
-                                       CPL_UNUSED int nFlags) {
+                                       int /* nFlagsIn */) {
     CPLDebug("Selafin","AlterFieldDefn(%i,%s,%s)",iField,poNewFieldDefn->GetNameRef(),OGRFieldDefn::GetFieldTypeName(poNewFieldDefn->GetType()));
     // Test if the field type is legal (only double precision values are allowed)
     if (poNewFieldDefn->GetType()!=OFTReal) {
@@ -638,7 +637,7 @@ OGRErr OGRSelafinLayer::AlterFieldDefn(int iField,
     }
     // Since the field type can't change, only the field name is changed. We change it in the header
     CPLFree(poHeader->papszVariables[iField]);
-    poHeader->papszVariables[iField]=(char*)VSIMalloc2(sizeof(char),33);
+    poHeader->papszVariables[iField]=(char*)VSI_MALLOC2_VERBOSE(sizeof(char),33);
     strncpy(poHeader->papszVariables[iField],poNewFieldDefn->GetNameRef(),32);
     poHeader->papszVariables[iField][32]=0;
     // And we update the file
@@ -655,33 +654,33 @@ OGRErr OGRSelafinLayer::DeleteFeature(GIntBig nFID) {
     CPLDebug("Selafin","DeleteFeature(" CPL_FRMT_GIB ")",nFID);
     if (VSIFSeekL(poHeader->fp,poHeader->getPosition(0),SEEK_SET)!=0) return OGRERR_FAILURE;
     // Change the header to delete the feature
-    if (eType==POINTS) poHeader->removePoint((long)nFID); else {
+    if (eType==POINTS) poHeader->removePoint((int)nFID); else {
         // For elements layer, we only delete the element and not the vertices
         poHeader->nElements--;
-        for (long i=(long)nFID;i<poHeader->nElements;++i)
-            for (long j=0;j<poHeader->nPointsPerElement;++j)
+        for (int i=(int)nFID;i<poHeader->nElements;++i)
+            for (int j=0;j<poHeader->nPointsPerElement;++j)
                 poHeader->panConnectivity[poHeader->nPointsPerElement*i+j]=poHeader->panConnectivity[poHeader->nPointsPerElement*(i+1)+j];
-        poHeader->panConnectivity=(long*)CPLRealloc(poHeader->panConnectivity,sizeof(long)*poHeader->nPointsPerElement*poHeader->nElements);
+        poHeader->panConnectivity=(int*)CPLRealloc(poHeader->panConnectivity,sizeof(int)*poHeader->nPointsPerElement*poHeader->nElements);
         poHeader->setUpdated();
     }
 
     // Now we perform the deletion by creating a new temporary layer
     VSILFILE *fpNew;
-    const char *pszTempfile=CPLGenerateTempFilename(0);
+    const char *pszTempfile=CPLGenerateTempFilename(NULL);
     fpNew=VSIFOpenL(pszTempfile,"wb+");
     if( fpNew == NULL ) {
         CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open temporary file %s with write access, %s.",pszTempfile, VSIStrerror( errno ) );
         return OGRERR_FAILURE;
-    } 
+    }
     if (Selafin::write_header(fpNew,poHeader)==0) {
         VSIFCloseL(fpNew);
         VSIUnlink(pszTempfile);
         return OGRERR_FAILURE;
     }
-    long nLen;
+    int nLen;
     double dfDate;
     double *padfValues;
-    for (long i=0;i<poHeader->nSteps;++i) {
+    for (int i=0;i<poHeader->nSteps;++i) {
         if (Selafin::read_integer(poHeader->fp,nLen,true)==0 ||
                 Selafin::read_float(poHeader->fp,dfDate)==0 ||
                 Selafin::read_integer(poHeader->fp,nLen,true)==0 ||
@@ -692,14 +691,14 @@ OGRErr OGRSelafinLayer::DeleteFeature(GIntBig nFID) {
             VSIUnlink(pszTempfile);
             return OGRERR_FAILURE;
         }
-        for (long j=0;j<poHeader->nVar;++j) {
+        for (int j=0;j<poHeader->nVar;++j) {
             if (Selafin::read_floatarray(poHeader->fp,&padfValues)==-1) {
                 VSIFCloseL(fpNew);
                 VSIUnlink(pszTempfile);
                 return OGRERR_FAILURE;
             }
             if (eType==POINTS) {
-                for (long k=(long)nFID;k<=poHeader->nPoints;++k) padfValues[k-1]=padfValues[k];
+                for (int k=(int)nFID;k<=poHeader->nPoints;++k) padfValues[k-1]=padfValues[k];
             }
             if (Selafin::write_floatarray(fpNew,padfValues,poHeader->nPoints)==0) {
                 CPLFree(padfValues);
@@ -707,13 +706,13 @@ OGRErr OGRSelafinLayer::DeleteFeature(GIntBig nFID) {
                 VSIUnlink(pszTempfile);
                 return OGRERR_FAILURE;
             }
-            CPLFree(padfValues);   
+            CPLFree(padfValues);
         }
     }
 
     // If everything went fine, we overwrite the new file with the content of the old one. This way, even if something goes bad, we can still recover the layer. The copy process is format-agnostic.
     MoveOverwrite(poHeader->fp,fpNew);
     VSIUnlink(pszTempfile);
+
     return OGRERR_NONE;
-    
 }
diff --git a/ogr/ogrsf_frmts/shape/GNUmakefile b/ogr/ogrsf_frmts/shape/GNUmakefile
index b1a8650..17543ba 100644
--- a/ogr/ogrsf_frmts/shape/GNUmakefile
+++ b/ogr/ogrsf_frmts/shape/GNUmakefile
@@ -6,7 +6,7 @@ OBJ	=	shape2ogr.o shpopen.o dbfopen.o shptree.o sbnsearch.o shp_vsi.o \
 		ogrshapedriver.o ogrshapedatasource.o ogrshapelayer.o
 
 CPPFLAGS :=	-DSAOffset=vsi_l_offset -DUSE_CPL \
-		-I.. -I../.. -I../generic  $(CPPFLAGS) 
+		-I.. -I../.. -I../generic  $(CPPFLAGS)
 
 default:	$(O_OBJ:.o=.$(OBJ_EXT))
 
diff --git a/ogr/ogrsf_frmts/shape/dbfopen.c b/ogr/ogrsf_frmts/shape/dbfopen.c
index 95aa57a..257c84e 100644
--- a/ogr/ogrsf_frmts/shape/dbfopen.c
+++ b/ogr/ogrsf_frmts/shape/dbfopen.c
@@ -14,7 +14,7 @@
  * option is discussed in more detail in shapelib.html.
  *
  * --
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * to deal in the Software without restriction, including without limitation
@@ -76,8 +76,8 @@
  *
  * Revision 1.77  2007/12/15 20:25:21  bram
  * dbfopen.c now reads the Code Page information from the DBF file, and exports
- * this information as a string through the DBFGetCodePage function.  This is 
- * either the number from the LDID header field ("LDID/<number>") or as the 
+ * this information as a string through the DBFGetCodePage function.  This is
+ * either the number from the LDID header field ("LDID/<number>") or as the
  * content of an accompanying .CPG file.  When creating a DBF file, the code can
  * be set using DBFCreateEx.
  *
@@ -177,6 +177,8 @@ SHP_CVSID("$Id: dbfopen.c,v 1.89 2011-07-24 05:59:25 fwarmerdam Exp $")
 #  define TRUE		1
 #endif
 
+CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused) {}
+
 /************************************************************************/
 /*                             SfRealloc()                              */
 /*                                                                      */
@@ -230,7 +232,7 @@ static void DBFWriteHeader(DBFHandle psDBF)
 
     abyHeader[8] = (unsigned char) (psDBF->nHeaderLength % 256);
     abyHeader[9] = (unsigned char) (psDBF->nHeaderLength / 256);
-    
+
     abyHeader[10] = (unsigned char) (psDBF->nRecordLength % 256);
     abyHeader[11] = (unsigned char) (psDBF->nRecordLength / 256);
 
@@ -242,7 +244,7 @@ static void DBFWriteHeader(DBFHandle psDBF)
 /* -------------------------------------------------------------------- */
     psDBF->sHooks.FSeek( psDBF->fp, 0, 0 );
     psDBF->sHooks.FWrite( abyHeader, XBASE_FLDHDR_SZ, 1, psDBF->fp );
-    psDBF->sHooks.FWrite( psDBF->pszHeader, XBASE_FLDHDR_SZ, psDBF->nFields, 
+    psDBF->sHooks.FWrite( psDBF->pszHeader, XBASE_FLDHDR_SZ, psDBF->nFields,
                           psDBF->fp );
 
 /* -------------------------------------------------------------------- */
@@ -272,17 +274,17 @@ static int DBFFlushRecord( DBFHandle psDBF )
     {
 	psDBF->bCurrentRecordModified = FALSE;
 
-	nRecordOffset = 
-            psDBF->nRecordLength * (SAOffset) psDBF->nCurrentRecord 
+	nRecordOffset =
+            psDBF->nRecordLength * (SAOffset) psDBF->nCurrentRecord
             + psDBF->nHeaderLength;
 
-	if( psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 ) != 0 
-            || psDBF->sHooks.FWrite( psDBF->pszCurrentRecord, 
-                                     psDBF->nRecordLength, 
+	if( psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 ) != 0
+            || psDBF->sHooks.FWrite( psDBF->pszCurrentRecord,
+                                     psDBF->nRecordLength,
                                      1, psDBF->fp ) != 1 )
         {
             char szMessage[128];
-            sprintf( szMessage, "Failure writing DBF record %d.", 
+            snprintf( szMessage, sizeof(szMessage), "Failure writing DBF record %d.",
                      psDBF->nCurrentRecord );
             psDBF->sHooks.Error( szMessage );
             return FALSE;
@@ -306,23 +308,23 @@ static int DBFLoadRecord( DBFHandle psDBF, int iRecord )
 	if( !DBFFlushRecord( psDBF ) )
             return FALSE;
 
-	nRecordOffset = 
+	nRecordOffset =
             psDBF->nRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
 
 	if( psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, SEEK_SET ) != 0 )
         {
             char szMessage[128];
-            sprintf( szMessage, "fseek(%ld) failed on DBF file.\n",
+            snprintf( szMessage, sizeof(szMessage), "fseek(%ld) failed on DBF file.\n",
                      (long) nRecordOffset );
             psDBF->sHooks.Error( szMessage );
             return FALSE;
         }
 
-	if( psDBF->sHooks.FRead( psDBF->pszCurrentRecord, 
+	if( psDBF->sHooks.FRead( psDBF->pszCurrentRecord,
                                  psDBF->nRecordLength, 1, psDBF->fp ) != 1 )
         {
             char szMessage[128];
-            sprintf( szMessage, "fread(%d) failed on DBF file.\n",
+            snprintf( szMessage, sizeof(szMessage), "fread(%d) failed on DBF file.\n",
                      psDBF->nRecordLength );
             psDBF->sHooks.Error( szMessage );
             return FALSE;
@@ -347,11 +349,12 @@ DBFUpdateHeader( DBFHandle psDBF )
     if( psDBF->bNoHeader )
         DBFWriteHeader( psDBF );
 
-    DBFFlushRecord( psDBF );
+    if( !DBFFlushRecord( psDBF ) )
+        return;
 
     psDBF->sHooks.FSeek( psDBF->fp, 0, 0 );
     psDBF->sHooks.FRead( abyFileHeader, 32, 1, psDBF->fp );
-    
+
     abyFileHeader[1] = (unsigned char) psDBF->nUpdateYearSince1900;
     abyFileHeader[2] = (unsigned char) psDBF->nUpdateMonth;
     abyFileHeader[3] = (unsigned char) psDBF->nUpdateDay;
@@ -359,7 +362,7 @@ DBFUpdateHeader( DBFHandle psDBF )
     abyFileHeader[5] = (unsigned char) ((psDBF->nRecords/256) % 256);
     abyFileHeader[6] = (unsigned char) ((psDBF->nRecords/(256*256)) % 256);
     abyFileHeader[7] = (unsigned char) ((psDBF->nRecords/(256*256*256)) % 256);
-    
+
     psDBF->sHooks.FSeek( psDBF->fp, 0, 0 );
     psDBF->sHooks.FWrite( abyFileHeader, 32, 1, psDBF->fp );
 
@@ -383,7 +386,7 @@ DBFSetLastModifiedDate( DBFHandle psDBF, int nYYSince1900, int nMM, int nDD )
 /*                                                                      */
 /*      Open a .dbf file.                                               */
 /************************************************************************/
-   
+
 DBFHandle SHPAPI_CALL
 DBFOpen( const char * pszFilename, const char * pszAccess )
 
@@ -400,7 +403,7 @@ DBFOpen( const char * pszFilename, const char * pszAccess )
 /*                                                                      */
 /*      Open a .dbf file.                                               */
 /************************************************************************/
-   
+
 DBFHandle SHPAPI_CALL
 DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
 
@@ -411,18 +414,19 @@ DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
     int			nFields, nHeadLen, iField, i;
     char		*pszBasename, *pszFullname;
     int                 nBufSize = 500;
+    size_t              nFullnameLen;
 
 /* -------------------------------------------------------------------- */
 /*      We only allow the access strings "rb" and "r+".                  */
 /* -------------------------------------------------------------------- */
-    if( strcmp(pszAccess,"r") != 0 && strcmp(pszAccess,"r+") != 0 
+    if( strcmp(pszAccess,"r") != 0 && strcmp(pszAccess,"r+") != 0
         && strcmp(pszAccess,"rb") != 0 && strcmp(pszAccess,"rb+") != 0
         && strcmp(pszAccess,"r+b") != 0 )
         return( NULL );
 
     if( strcmp(pszAccess,"r") == 0 )
         pszAccess = "rb";
- 
+
     if( strcmp(pszAccess,"r+") == 0 )
         pszAccess = "rb+";
 
@@ -432,7 +436,7 @@ DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
 /* -------------------------------------------------------------------- */
     pszBasename = (char *) malloc(strlen(pszFilename)+5);
     strcpy( pszBasename, pszFilename );
-    for( i = strlen(pszBasename)-1; 
+    for( i = (int)strlen(pszBasename)-1;
 	 i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
 	       && pszBasename[i] != '\\';
 	 i-- ) {}
@@ -440,30 +444,31 @@ DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
     if( pszBasename[i] == '.' )
         pszBasename[i] = '\0';
 
-    pszFullname = (char *) malloc(strlen(pszBasename) + 5);
-    sprintf( pszFullname, "%s.dbf", pszBasename );
-        
+    nFullnameLen = strlen(pszBasename) + 5;
+    pszFullname = (char *) malloc(nFullnameLen);
+    snprintf( pszFullname, nFullnameLen, "%s.dbf", pszBasename );
+
     psDBF = (DBFHandle) calloc( 1, sizeof(DBFInfo) );
     psDBF->fp = psHooks->FOpen( pszFullname, pszAccess );
     memcpy( &(psDBF->sHooks), psHooks, sizeof(SAHooks) );
 
     if( psDBF->fp == NULL )
     {
-        sprintf( pszFullname, "%s.DBF", pszBasename );
+        snprintf( pszFullname, nFullnameLen, "%s.DBF", pszBasename );
         psDBF->fp = psDBF->sHooks.FOpen(pszFullname, pszAccess );
     }
 
-    sprintf( pszFullname, "%s.cpg", pszBasename );
+    snprintf( pszFullname, nFullnameLen, "%s.cpg", pszBasename );
     pfCPG = psHooks->FOpen( pszFullname, "r" );
     if( pfCPG == NULL )
     {
-        sprintf( pszFullname, "%s.CPG", pszBasename );
+        snprintf( pszFullname, nFullnameLen, "%s.CPG", pszBasename );
         pfCPG = psHooks->FOpen( pszFullname, "r" );
     }
 
     free( pszBasename );
     free( pszFullname );
-    
+
     if( psDBF->fp == NULL )
     {
         free( psDBF );
@@ -487,17 +492,17 @@ DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
         free( psDBF );
         return NULL;
     }
-    
+
     DBFSetLastModifiedDate(psDBF, pabyBuf[1], pabyBuf[2], pabyBuf[3]);
 
-    psDBF->nRecords = 
-     pabyBuf[4] + pabyBuf[5]*256 + pabyBuf[6]*256*256 + pabyBuf[7]*256*256*256;
+    psDBF->nRecords =
+     pabyBuf[4] + pabyBuf[5]*256 + pabyBuf[6]*256*256 + (pabyBuf[7] & 0x7f) *256*256*256;
 
     psDBF->nHeaderLength = nHeadLen = pabyBuf[8] + pabyBuf[9]*256;
     psDBF->nRecordLength = pabyBuf[10] + pabyBuf[11]*256;
     psDBF->iLanguageDriver = pabyBuf[29];
 
-    if (nHeadLen < 32)
+    if (psDBF->nRecordLength == 0 || nHeadLen < 32)
     {
         psDBF->sHooks.FClose( psDBF->fp );
         if( pfCPG ) psDBF->sHooks.FClose( pfCPG );
@@ -531,7 +536,7 @@ DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
     }
     if( psDBF->pszCodePage == NULL && pabyBuf[29] != 0 )
     {
-        sprintf( (char *) pabyBuf, "LDID/%d", psDBF->iLanguageDriver );
+        snprintf( (char *) pabyBuf, nBufSize, "LDID/%d", psDBF->iLanguageDriver );
         psDBF->pszCodePage = (char *) malloc(strlen((char*)pabyBuf) + 1);
         strcpy( psDBF->pszCodePage, (char *) pabyBuf );
     }
@@ -539,7 +544,7 @@ DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
 /* -------------------------------------------------------------------- */
 /*  Read in Field Definitions                                           */
 /* -------------------------------------------------------------------- */
-    
+
     pabyBuf = (unsigned char *) SfRealloc(pabyBuf,nHeadLen);
     psDBF->pszHeader = (char *) pabyBuf;
 
@@ -588,7 +593,7 @@ DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
 	if( iField == 0 )
 	    psDBF->panFieldOffset[iField] = 1;
 	else
-	    psDBF->panFieldOffset[iField] = 
+	    psDBF->panFieldOffset[iField] =
 	      psDBF->panFieldOffset[iField-1] + psDBF->panFieldSize[iField-1];
     }
 
@@ -611,7 +616,7 @@ DBFClose(DBFHandle psDBF)
     if( psDBF->bNoHeader )
         DBFWriteHeader( psDBF );
 
-    DBFFlushRecord( psDBF );
+    CPL_IGNORE_RET_VAL_INT(DBFFlushRecord( psDBF ));
 
 /* -------------------------------------------------------------------- */
 /*      Update last access date, and number of records if we have	*/
@@ -688,6 +693,7 @@ DBFCreateLL( const char * pszFilename, const char * pszCodePage, SAHooks *psHook
     char	*pszFullname, *pszBasename;
     int		i, ldid = -1;
     char chZero = '\0';
+    size_t      nFullnameLen;
 
 /* -------------------------------------------------------------------- */
 /*	Compute the base (layer) name.  If there is any extension	*/
@@ -695,7 +701,7 @@ DBFCreateLL( const char * pszFilename, const char * pszCodePage, SAHooks *psHook
 /* -------------------------------------------------------------------- */
     pszBasename = (char *) malloc(strlen(pszFilename)+5);
     strcpy( pszBasename, pszFilename );
-    for( i = strlen(pszBasename)-1; 
+    for( i = (int)strlen(pszBasename)-1;
 	 i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
 	       && pszBasename[i] != '\\';
 	 i-- ) {}
@@ -703,8 +709,9 @@ DBFCreateLL( const char * pszFilename, const char * pszCodePage, SAHooks *psHook
     if( pszBasename[i] == '.' )
         pszBasename[i] = '\0';
 
-    pszFullname = (char *) malloc(strlen(pszBasename) + 5);
-    sprintf( pszFullname, "%s.dbf", pszBasename );
+    nFullnameLen = strlen(pszBasename) + 5;
+    pszFullname = (char *) malloc(nFullnameLen);
+    snprintf( pszFullname, nFullnameLen, "%s.dbf", pszBasename );
 
 /* -------------------------------------------------------------------- */
 /*      Create the file.                                                */
@@ -716,7 +723,7 @@ DBFCreateLL( const char * pszFilename, const char * pszCodePage, SAHooks *psHook
         free( pszFullname );
         return( NULL );
     }
-    
+
     psHooks->FWrite( &chZero, 1, 1, fp );
     psHooks->FClose( fp );
 
@@ -728,7 +735,7 @@ DBFCreateLL( const char * pszFilename, const char * pszCodePage, SAHooks *psHook
         return( NULL );
     }
 
-    sprintf( pszFullname, "%s.cpg", pszBasename );
+    snprintf( pszFullname, nFullnameLen, "%s.cpg", pszBasename );
     if( pszCodePage != NULL )
     {
         if( strncmp( pszCodePage, "LDID/", 5 ) == 0 )
@@ -763,7 +770,7 @@ DBFCreateLL( const char * pszFilename, const char * pszCodePage, SAHooks *psHook
     psDBF->nFields = 0;
     psDBF->nRecordLength = 1;
     psDBF->nHeaderLength = 33;
-    
+
     psDBF->panFieldOffset = NULL;
     psDBF->panFieldSize = NULL;
     psDBF->panFieldDecimals = NULL;
@@ -795,7 +802,7 @@ DBFCreateLL( const char * pszFilename, const char * pszCodePage, SAHooks *psHook
 /************************************************************************/
 
 int SHPAPI_CALL
-DBFAddField(DBFHandle psDBF, const char * pszFieldName, 
+DBFAddField(DBFHandle psDBF, const char * pszFieldName,
             DBFFieldType eType, int nWidth, int nDecimals )
 
 {
@@ -808,7 +815,7 @@ DBFAddField(DBFHandle psDBF, const char * pszFieldName,
     else
         chNativeType = 'N';
 
-    return DBFAddNativeFieldType( psDBF, pszFieldName, chNativeType, 
+    return DBFAddNativeFieldType( psDBF, pszFieldName, chNativeType,
                                   nWidth, nDecimals );
 }
 
@@ -840,7 +847,7 @@ static char DBFGetNullCharacter(char chType)
 /************************************************************************/
 
 int SHPAPI_CALL
-DBFAddNativeFieldType(DBFHandle psDBF, const char * pszFieldName, 
+DBFAddNativeFieldType(DBFHandle psDBF, const char * pszFieldName,
                       char chType, int nWidth, int nDecimals )
 
 {
@@ -873,16 +880,16 @@ DBFAddNativeFieldType(DBFHandle psDBF, const char * pszFieldName,
 /* -------------------------------------------------------------------- */
     psDBF->nFields++;
 
-    psDBF->panFieldOffset = (int *) 
+    psDBF->panFieldOffset = (int *)
         SfRealloc( psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );
 
-    psDBF->panFieldSize = (int *) 
+    psDBF->panFieldSize = (int *)
         SfRealloc( psDBF->panFieldSize, sizeof(int) * psDBF->nFields );
 
-    psDBF->panFieldDecimals = (int *) 
+    psDBF->panFieldDecimals = (int *)
         SfRealloc( psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields );
 
-    psDBF->pachFieldType = (char *) 
+    psDBF->pachFieldType = (char *)
         SfRealloc( psDBF->pachFieldType, sizeof(char) * psDBF->nFields );
 
 /* -------------------------------------------------------------------- */
@@ -924,7 +931,7 @@ DBFAddNativeFieldType(DBFHandle psDBF, const char * pszFieldName,
         pszFInfo[16] = (unsigned char) nWidth;
         pszFInfo[17] = (unsigned char) nDecimals;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Make the current record buffer appropriately larger.            */
 /* -------------------------------------------------------------------- */
@@ -1065,7 +1072,7 @@ static void *DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField,
             *pchDst = '\0';
     }
 #endif
-    
+
     return( pReturnField );
 }
 
@@ -1263,10 +1270,10 @@ DBFGetFieldInfo( DBFHandle psDBF, int iField, char * pszFieldName,
     if ( psDBF->pachFieldType[iField] == 'L' )
 	return( FTLogical);
 
-    else if( psDBF->pachFieldType[iField] == 'N' 
+    else if( psDBF->pachFieldType[iField] == 'N'
              || psDBF->pachFieldType[iField] == 'F' )
     {
-	if( psDBF->panFieldDecimals[iField] > 0 
+	if( psDBF->panFieldDecimals[iField] > 0
             || psDBF->panFieldSize[iField] >= 10 )
 	    return( FTDouble );
 	else
@@ -1355,9 +1362,9 @@ static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
         if( (int) sizeof(szSField)-2 < nWidth )
             nWidth = sizeof(szSField)-2;
 
-        sprintf( szFormat, "%%%d.%df", 
+        snprintf( szFormat, sizeof(szFormat), "%%%d.%df",
                     nWidth, psDBF->panFieldDecimals[iField] );
-        CPLsprintf(szSField, szFormat, *((double *) pValue) );
+        CPLsnprintf(szSField, sizeof(szSField), szFormat, *((double *) pValue) );
         if( (int) strlen(szSField) > psDBF->panFieldSize[iField] )
         {
             szSField[psDBF->panFieldSize[iField]] = '\0';
@@ -1369,7 +1376,7 @@ static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
       }
 
       case 'L':
-        if (psDBF->panFieldSize[iField] >= 1  && 
+        if (psDBF->panFieldSize[iField] >= 1  &&
             (*(char*)pValue == 'F' || *(char*)pValue == 'T'))
             *(pabyRec+psDBF->panFieldOffset[iField]) = *(char*)pValue;
         break;
@@ -1384,7 +1391,7 @@ static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
         {
             memset( pabyRec+psDBF->panFieldOffset[iField], ' ',
                     psDBF->panFieldSize[iField] );
-	    j = strlen((char *) pValue);
+	    j = (int)strlen((char *) pValue);
         }
 
 	strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
@@ -1453,7 +1460,7 @@ DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField,
     {
         memset( pabyRec+psDBF->panFieldOffset[iField], ' ',
                 psDBF->panFieldSize[iField] );
-        j = strlen((char *) pValue);
+        j = (int)strlen((char *) pValue);
     }
 
     strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
@@ -1617,21 +1624,21 @@ DBFReadTuple(DBFHandle psDBF, int hEntity )
 /************************************************************************/
 
 DBFHandle SHPAPI_CALL
-DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename ) 
+DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename )
 {
     DBFHandle	newDBF;
 
    newDBF = DBFCreateEx ( pszFilename, psDBF->pszCodePage );
-   if ( newDBF == NULL ) return ( NULL ); 
-   
+   if ( newDBF == NULL ) return ( NULL );
+
    newDBF->nFields = psDBF->nFields;
    newDBF->nRecordLength = psDBF->nRecordLength;
    newDBF->nHeaderLength = psDBF->nHeaderLength;
-    
+
    newDBF->pszHeader = (char *) malloc ( newDBF->nHeaderLength );
    memcpy ( newDBF->pszHeader, psDBF->pszHeader, newDBF->nHeaderLength );
-   
-   newDBF->panFieldOffset = (int *) malloc ( sizeof(int) * psDBF->nFields ); 
+
+   newDBF->panFieldOffset = (int *) malloc ( sizeof(int) * psDBF->nFields );
    memcpy ( newDBF->panFieldOffset, psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );
    newDBF->panFieldSize = (int *) malloc ( sizeof(int) * psDBF->nFields );
    memcpy ( newDBF->panFieldSize, psDBF->panFieldSize, sizeof(int) * psDBF->nFields );
@@ -1642,10 +1649,10 @@ DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename )
 
    newDBF->bNoHeader = TRUE;
    newDBF->bUpdated = TRUE;
-   
+
    DBFWriteHeader ( newDBF );
    DBFClose ( newDBF );
-   
+
    newDBF = DBFOpen ( pszFilename, "rb+" );
 
    return ( newDBF );
@@ -1679,9 +1686,9 @@ DBFGetNativeFieldType( DBFHandle psDBF, int iField )
 static void str_to_upper (char *string)
 {
     int len;
-    short i = -1;
+    int i = -1;
 
-    len = strlen (string);
+    len = (int)strlen (string);
 
     while (++i < len)
         if (isalpha(string[i]) && islower(string[i]))
@@ -1751,7 +1758,7 @@ int SHPAPI_CALL DBFIsRecordDeleted( DBFHandle psDBF, int iShape )
 /*                        DBFMarkRecordDeleted()                        */
 /************************************************************************/
 
-int SHPAPI_CALL DBFMarkRecordDeleted( DBFHandle psDBF, int iShape, 
+int SHPAPI_CALL DBFMarkRecordDeleted( DBFHandle psDBF, int iShape,
                                       int bIsDeleted )
 
 {
@@ -1775,7 +1782,7 @@ int SHPAPI_CALL DBFMarkRecordDeleted( DBFHandle psDBF, int iShape,
 /* -------------------------------------------------------------------- */
     if( bIsDeleted )
         chNewFlag = '*';
-    else 
+    else
         chNewFlag = ' ';
 
     if( psDBF->pszCurrentRecord[0] != chNewFlag )
@@ -1840,16 +1847,16 @@ DBFDeleteField(DBFHandle psDBF, int iField)
     /* resize fields arrays */
     psDBF->nFields--;
 
-    psDBF->panFieldOffset = (int *) 
+    psDBF->panFieldOffset = (int *)
         SfRealloc( psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );
 
-    psDBF->panFieldSize = (int *) 
+    psDBF->panFieldSize = (int *)
         SfRealloc( psDBF->panFieldSize, sizeof(int) * psDBF->nFields );
 
-    psDBF->panFieldDecimals = (int *) 
+    psDBF->panFieldDecimals = (int *)
         SfRealloc( psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields );
 
-    psDBF->pachFieldType = (char *) 
+    psDBF->pachFieldType = (char *)
         SfRealloc( psDBF->pachFieldType, sizeof(char) * psDBF->nFields );
 
     /* update header information */
@@ -1881,14 +1888,14 @@ DBFDeleteField(DBFHandle psDBF, int iField)
     /* shift records to their new positions */
     for (iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
     {
-        nRecordOffset = 
+        nRecordOffset =
             nOldRecordLength * (SAOffset) iRecord + nOldHeaderLength;
 
         /* load record */
         psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
         psDBF->sHooks.FRead( pszRecord, nOldRecordLength, 1, psDBF->fp );
 
-        nRecordOffset = 
+        nRecordOffset =
             psDBF->nRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
 
         /* move record in two steps */
@@ -1942,7 +1949,8 @@ DBFReorderFields( DBFHandle psDBF, int* panMap )
     if( !DBFFlushRecord( psDBF ) )
         return FALSE;
 
-    panFieldOffsetNew = (int *) malloc(sizeof(int) * psDBF->nFields);
+    /* a simple malloc() would be enough, but calloc() helps clang static analyzer */
+    panFieldOffsetNew = (int *) calloc(sizeof(int), psDBF->nFields);
     panFieldSizeNew = (int *) malloc(sizeof(int) *  psDBF->nFields);
     panFieldDecimalsNew = (int *) malloc(sizeof(int) *  psDBF->nFields);
     pachFieldTypeNew = (char *) malloc(sizeof(char) *  psDBF->nFields);
@@ -2039,7 +2047,7 @@ DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
     int   nOffset;
     int   nOldWidth;
     int   nOldRecordLength;
-    int   nRecordOffset;
+    SAOffset  nRecordOffset;
     char* pszFInfo;
     char  chOldType;
     int   bIsNULL;
diff --git a/ogr/ogrsf_frmts/shape/drv_shapefile.html b/ogr/ogrsf_frmts/shape/drv_shapefile.html
index 40cfd6d..d8d3f33 100644
--- a/ogr/ogrsf_frmts/shape/drv_shapefile.html
+++ b/ogr/ogrsf_frmts/shape/drv_shapefile.html
@@ -1,15 +1,16 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
 <html lang=en>
 <head>
-<title>ESRI Shapefile</title>
+<title>ESRI Shapefile / DBF</title>
 </head>
 
 <body>
 
-<h1>ESRI Shapefile</h1>
+<h1>ESRI Shapefile / DBF</h1>
 
 <p>All varieties of ESRI Shapefiles should be available for reading, and
-simple 3D files can be created.</p>
+simple 3D files can be created. The driver can also handle standalone DBF
+files without associated .shp files.</p>
 
 <p>Normally the OGR Shapefile driver treats a whole directory of shapefiles
 as a dataset, and a single shapefile within that directory as a layer.  In
@@ -26,25 +27,33 @@ The same applies for SHPT_POLYGON shapefiles, reported as layers of type
 wkbPolygon, but depending on the number of parts of each geometry, the
 actual type can be either OGRPolygon or OGRMultiPolygon.</p>
 
-<p>ESRI measure values (XYM) are read as XYZ geometries. MultiPatch
-files are read and each patch geometry is turned into a multi-polygon 
-representation with one polygon per triangle in triangle fans and meshes.</p>
+<p>Starting with GDAL 2.1 measures (M coordinate) are supported. A
+Shapefile with measures is created if the specified geometry type is
+measured or an appropriate layer creation option is used. When a
+shapefile which may have measured geometries is opened, the first
+shape is examined and if it uses measures, the geometry type of the
+layer is set accordingly. This behaviour can be changed with the
+ADJUST_GEOM_TYPE open option.</p>
+
+<p>MultiPatch files are read and each patch geometry is turned into a
+multi-polygon representation with one polygon per triangle in triangle
+fans and meshes.</p>
 
 <p>If a .prj files in old Arc/Info style or new ESRI OGC WKT style is present,
 it will be read and used to associate a projection with features.</p>
 
-<p>The read driver assumes that multipart polygons follow the specification, 
-that is to say the vertices of outer rings should be oriented clockwise on the 
+<p>The read driver assumes that multipart polygons follow the specification,
+that is to say the vertices of outer rings should be oriented clockwise on the
 X/Y plane, and those of inner rings counterclockwise.
-If a Shapefile is broken w.r.t. that rule, it is possible to define the 
-configuration option OGR_ORGANIZE_POLYGONS=DEFAULT to proceed to a full 
-analysis based on topological relationships of the parts of the polygons so 
+If a Shapefile is broken w.r.t. that rule, it is possible to define the
+configuration option OGR_ORGANIZE_POLYGONS=DEFAULT to proceed to a full
+analysis based on topological relationships of the parts of the polygons so
 that the resulting polygons are correctly
 defined in the OGC Simple Feature convention. </p>
 
-<p>An attempt is made to read the LDID/codepage setting from the .dbf file 
+<p>An attempt is made to read the LDID/codepage setting from the .dbf file
 and use it to translate string fields to UTF-8 on read, and back when writing.
-LDID "87 / 0x57" is treated as ISO8859_1 which may not be appropriate.  
+LDID "87 / 0x57" is treated as ISO8859_1 which may not be appropriate.
 The SHAPE_ENCODING <a href="http://trac.osgeo.org/gdal/wiki/ConfigOptions">
 configuration option</a> may be used to override the encoding interpretation
 of the shapefile with any encoding supported by CPLRecode or to "" to avoid
@@ -55,16 +64,24 @@ any recoding. (Recoding support is new for GDAL/OGR 1.9.0)</p>
 <p>Starting with GDAL 2.0, the following open options are available.</p>
 <ul>
 <li><b>ENCODING</b>=encoding_name: to override the encoding interpretation of the
-sshapefile with any encoding supported by CPLRecode or to "" to avoid any
+shapefile with any encoding supported by CPLRecode or to "" to avoid any
 recoding</li>
 <li><b>DBF_DATE_LAST_UPDATE=</b><i>YYYY-MM-DD</i>: Modification
 date to write in DBF header with year-month-day format. If not specified, current date is used.</li>
-<li><b>ADJUST_TYPE</b>=YES/NO: Set to YES (default is NO) to read the whole .dbf to adjust 
+<li><b>ADJUST_TYPE</b>=YES/NO: Set to YES (default is NO) to read the whole .dbf to adjust
 Real->Integer/Integer64 or Integer64->Integer field types when possible. This
 can be used when field widths are ambiguous and that by default OGR would select
 the larger data type. For example, a numeric column with 0 decimal figures and with
 width of 10/11 character may hold Integer or Integer64, and with width 19/20 may
 hold Integer64 or larger integer (hold as Real)</li>
+<li><b>ADJUST_GEOM_TYPE</b>=NO/FIRST_SHAPE/ALL_SHAPES. (Starting with GDAL 2.1)
+Defines how layer geometry type is computed, in particular to distinguish
+shapefiles that have shapes with significant values in the M dimension from the
+ones where the M values are set to the nodata value. By default (FIRST_SHAPE),
+the driver will look at the first shape and if it has M values it will expose the
+layer as having a M dimension. By specifying
+ALL_SHAPES, the driver will iterate over features until a shape with a valid
+M value is found to decide the appropriate layer type.</li>
 </ul>
 
 <h2>Spatial and Attribute Indexing</h2>
@@ -77,7 +94,7 @@ are used by UMN MapServer. Spatial indexing can accelerate spatially filtered
 passes through large datasets to pick out a small area quite dramatically.</p>
 
 <p>Starting with OGR 1.10, it can also use the ESRI spatial index
-files (.sbn / .sbx), but writing them is not supported currently.</p> 
+files (.sbn / .sbx), but writing them is not supported currently.</p>
 
 <p>To create a spatial index (in .qix format), issue a SQL command of the form</p>
 <pre>CREATE SPATIAL INDEX ON tablename [DEPTH N]</pre>
@@ -98,7 +115,7 @@ More information is available about this utility at the
 <a href="http://mapserver.org/utilities/shptree.html">MapServer shptree page</a>
 </p>
 
-<p>Currently the OGR Shapefile driver only supports attribute indexes for 
+<p>Currently the OGR Shapefile driver only supports attribute indexes for
 looking up specific values in a unique key column.  To create an attribute
 index for a column issue an SQL command of the form "CREATE INDEX ON tablename
 USING fieldname".  To drop the attribute indexes issue a command of the
@@ -111,14 +128,14 @@ with any other shapefile applications.</p>
 
 <p>The Shapefile driver treats a directory as a dataset, and each Shapefile
 set (.shp, .shx, and .dbf) as a layer.  The dataset name will be treated
-as a directory name.  If the directory already exists it is used and 
+as a directory name.  If the directory already exists it is used and
 existing files in the directory are ignored.  If the directory does not
 exist it will be created.</p>
 
 <p>As a special case attempts to create a new dataset with the extension .shp
 will result in a single file set being created instead of a directory.</p>
 
-<p>ESRI shapefiles can only store one kind of geometry per layer (shapefile). 
+<p>ESRI shapefiles can only store one kind of geometry per layer (shapefile).
 On creation this is may be set based on the source file (if a uniform geometry
 type is known from the source driver), or it may be set directly by the
 user with the layer creation option SHPT (shown below).  If not set the
@@ -127,7 +144,7 @@ to the layer, the output will be terminated with an error.</p>
 
 <p>Note that this can make it very difficult to translate a mixed geometry layer
 from another format into Shapefile format using ogr2ogr, since ogr2ogr has
-no support for separating out geometries from a source layer. See 
+no support for separating out geometries from a source layer. See
 the <a href="http://trac.osgeo.org/gdal/wiki/FAQVector#HowdoItranslateamixedgeometryfiletoshapefileformat">FAQ</a> for a solution.</p>
 
 <p>Shapefile feature attributes are stored in an associated .dbf file, and so
@@ -147,7 +164,7 @@ with a serial number from 1 to 99. </p><p>For example:</p>
 field types are supported.  The various list, and binary field types cannot
 be created.</p></li>
 
-<li><p> The field width and precision are directly used to establish storage 
+<li><p> The field width and precision are directly used to establish storage
 size in the .dbf file.  This means that strings longer than the field
 width, or numbers that don't fit into the indicated field format will suffer
 truncation.</p></li>
@@ -170,7 +187,7 @@ by the application an "FID" field will be automatically created and populated
 with the record number.</p>
 
 <p>The OGR shapefile driver supports rewriting existing shapes in a shapefile
-as well as deleting shapes.  Deleted shapes are marked for deletion in 
+as well as deleting shapes.  Deleted shapes are marked for deletion in
 the .dbf file, and then ignored by OGR.  To actually remove them permanently
 (resulting in renumbering of FIDs) invoke the SQL 'REPACK <tablename>' via
 the datasource ExecuteSQL() method.</p>
@@ -210,7 +227,7 @@ implementation has a limitation to 4GB.</p>
 <p>Attributes: The dbf format does not have any offsets in it, so it can be
 arbitrarily large.</p>
 
-<p>However, for compatibility with other software implementation, it is is not
+<p>However, for compatibility with other software implementation, it is not
 recommended to use a file size over 2GB for both .SHP and .DBF files.</p>
 
 <p>Starting with OGR 1.11, the 2GB_LIMIT=YES layer creation option can be used
@@ -225,12 +242,14 @@ emitted when the 2GB limit is reached.</p>
 <h3>Layer Creation Options</h3>
 
 <ul>
-<li>
-<b>SHPT=type</b>: Override the type of shapefile created.  Can be one of
-NULL for a simple .dbf file with no .shp file, 
- POINT, ARC, POLYGON or MULTIPOINT for 2D, or 
-POINTZ, ARCZ, POLYGONZ or MULTIPOINTZ for 3D.  Shapefiles with <i>measure</i>
-values are not supported, nor are MULTIPATCH files.</li>
+
+<li><b>SHPT=type</b>: Override the type of shapefile created.  Can be
+one of NULL for a simple .dbf file with no .shp file, POINT, ARC,
+POLYGON or MULTIPOINT for 2D; POINTZ, ARCZ, POLYGONZ or MULTIPOINTZ
+for 3D; POINTM, ARCM, POLYGONM or MULTIPOINTM for measured geometries;
+and POINTZM, ARCZM, POLYGONZM or MULTIPOINTZM for 3D measured
+geometries. The measure support was added in GDAL 2.1. MULTIPATCH
+files are not supported.</li>
 
 <li> <b>ENCODING=</b><i>value</i>: set the encoding value in the DBF file. The
 default value is "LDID/87".  It is not clear what other values may be
diff --git a/ogr/ogrsf_frmts/shape/ogrshape.h b/ogr/ogrsf_frmts/shape/ogrshape.h
index 1238720..0d926cb 100644
--- a/ogr/ogrsf_frmts/shape/ogrshape.h
+++ b/ogr/ogrsf_frmts/shape/ogrshape.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrshape.h 28775 2015-03-25 16:24:02Z rouault $
+ * $Id: ogrshape.h 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions within the Shapefile driver to implement
@@ -29,8 +29,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGRSHAPE_H_INCLUDED
-#define _OGRSHAPE_H_INCLUDED
+#ifndef OGRSHAPE_H_INCLUDED
+#define OGRSHAPE_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "shapefil.h"
@@ -39,7 +39,7 @@
 #include <vector>
 
 /* Was limited to 255 until OGR 1.10, but 254 seems to be a more */
-/* conventionnal limit (http://en.wikipedia.org/wiki/Shapefile, */
+/* conventional limit (http://en.wikipedia.org/wiki/Shapefile, */
 /* http://www.clicketyclick.dk/databases/xbase/format/data_types.html, */
 /* #5052 ) */
 #define OGR_DBF_MAX_FIELD_WIDTH 254
@@ -48,7 +48,7 @@
 /*      Functions from Shape2ogr.cpp.                                   */
 /* ==================================================================== */
 OGRFeature *SHPReadOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
-                               OGRFeatureDefn * poDefn, int iShape, 
+                               OGRFeatureDefn * poDefn, int iShape,
                                SHPObject *psShape, const char *pszSHPEncoding );
 OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape );
 OGRFeatureDefn *SHPReadOGRFeatureDefn( const char * pszName,
@@ -65,7 +65,7 @@ OGRErr SHPWriteOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
 /*                         OGRShapeGeomFieldDefn                        */
 /************************************************************************/
 
-class OGRShapeGeomFieldDefn: public OGRGeomFieldDefn
+class OGRShapeGeomFieldDefn CPL_FINAL: public OGRGeomFieldDefn
 {
     char* pszFullName;
     int   bSRSSet;
@@ -94,7 +94,7 @@ class OGRShapeGeomFieldDefn: public OGRGeomFieldDefn
 
 class OGRShapeDataSource;
 
-class OGRShapeLayer : public OGRAbstractProxiedLayer
+class OGRShapeLayer CPL_FINAL: public OGRAbstractProxiedLayer
 {
     OGRShapeDataSource  *poDS;
 
@@ -150,7 +150,7 @@ class OGRShapeLayer : public OGRAbstractProxiedLayer
     int                 bResizeAtClose;
 
     void                TruncateDBF();
-    
+
     int                 bCreateSpatialIndexAtClose;
     int                 bRewindOnWrite;
 
@@ -195,11 +195,13 @@ class OGRShapeLayer : public OGRAbstractProxiedLayer
     OGRErr              DeleteFeature( GIntBig nFID );
     OGRErr              ICreateFeature( OGRFeature *poFeature );
     OGRErr              SyncToDisk();
-    
+
     OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
 
     GIntBig             GetFeatureCount( int );
     OGRErr              GetExtent(OGREnvelope *psExtent, int bForce);
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
                                      int bApproxOK = TRUE );
@@ -209,8 +211,11 @@ class OGRShapeLayer : public OGRAbstractProxiedLayer
 
     virtual int         TestCapability( const char * );
     virtual void        SetSpatialFilter( OGRGeometry * );
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+                { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
+
     virtual OGRErr      SetAttributeFilter( const char * );
-    
+
     void                AddToFileList( CPLStringList& oFileList );
     void                CreateSpatialIndexAtClose( int bFlag ) { bCreateSpatialIndexAtClose = bFlag; }
     void                SetModificationDate(const char* pszStr);
@@ -220,11 +225,11 @@ class OGRShapeLayer : public OGRAbstractProxiedLayer
 /*                          OGRShapeDataSource                          */
 /************************************************************************/
 
-class OGRShapeDataSource : public OGRDataSource
+class OGRShapeDataSource CPL_FINAL: public OGRDataSource
 {
     OGRShapeLayer     **papoLayers;
     int                 nLayers;
-    
+
     char                *pszName;
 
     int                 bDSUpdate;
@@ -236,9 +241,9 @@ class OGRShapeDataSource : public OGRDataSource
     void                AddLayer(OGRShapeLayer* poLayer);
 
     std::vector<CPLString> oVectorLayerName;
-    
+
     int                 b2GBLimit;
-    
+
     char              **papszOpenOptions;
 
   public:
@@ -257,7 +262,7 @@ class OGRShapeDataSource : public OGRDataSource
     virtual OGRLayer    *GetLayer( int );
     virtual OGRLayer    *GetLayerByName(const char *);
 
-    virtual OGRLayer    *ICreateLayer( const char *, 
+    virtual OGRLayer    *ICreateLayer( const char *,
                                       OGRSpatialReference * = NULL,
                                       OGRwkbGeometryType = wkbUnknown,
                                       char ** = NULL );
@@ -279,4 +284,4 @@ class OGRShapeDataSource : public OGRDataSource
     char               **GetOpenOptions() { return papszOpenOptions; }
 };
 
-#endif /* ndef _OGRSHAPE_H_INCLUDED */
+#endif /* ndef OGRSHAPE_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/shape/ogrshapedatasource.cpp b/ogr/ogrsf_frmts/shape/ogrshapedatasource.cpp
index 8dec7f7..85ebc17 100644
--- a/ogr/ogrsf_frmts/shape/ogrshapedatasource.cpp
+++ b/ogr/ogrsf_frmts/shape/ogrshapedatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrshapedatasource.cpp 28585 2015-03-01 19:42:37Z rouault $
+ * $Id: ogrshapedatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRShapeDataSource class.
@@ -35,8 +35,7 @@
 
 //#define IMMEDIATE_OPENING 1
 
-CPL_CVSID("$Id: ogrshapedatasource.cpp 28585 2015-03-01 19:42:37Z rouault $");
-
+CPL_CVSID("$Id: ogrshapedatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                          DS_SHPOpen()                                */
@@ -45,7 +44,7 @@ CPL_CVSID("$Id: ogrshapedatasource.cpp 28585 2015-03-01 19:42:37Z rouault $");
 SHPHandle OGRShapeDataSource::DS_SHPOpen( const char * pszShapeFile, const char * pszAccess )
 {
     /* Do lazy shx loading for /vsicurl/ */
-    if( strncmp(pszShapeFile, "/vsicurl/", strlen("/vsicurl/")) == 0 &&
+    if( STARTS_WITH(pszShapeFile, "/vsicurl/") &&
         strcmp(pszAccess, "r") == 0 )
         pszAccess = "rl";
     SHPHandle hSHP = SHPOpenLL( pszShapeFile, pszAccess, (SAHooks*) VSI_SHP_GetHook(b2GBLimit) );
@@ -68,16 +67,16 @@ DBFHandle OGRShapeDataSource::DS_DBFOpen( const char * pszDBFFile, const char *
 /*                         OGRShapeDataSource()                         */
 /************************************************************************/
 
-OGRShapeDataSource::OGRShapeDataSource()
-
+OGRShapeDataSource::OGRShapeDataSource() :
+    papoLayers(NULL),
+    nLayers(0),
+    pszName(NULL),
+    bDSUpdate(FALSE),
+    bSingleFileDataSource(FALSE),
+    papszOpenOptions(NULL)
 {
-    pszName = NULL;
-    papoLayers = NULL;
-    nLayers = 0;
-    bSingleFileDataSource = FALSE;
     poPool = new OGRLayerPool();
-    b2GBLimit = CSLTestBoolean(CPLGetConfigOption("SHAPE_2GB_LIMIT", "FALSE"));
-    papszOpenOptions = NULL;
+    b2GBLimit = CPLTestBool(CPLGetConfigOption("SHAPE_2GB_LIMIT", "FALSE"));
 }
 
 
@@ -112,11 +111,11 @@ int OGRShapeDataSource::Open( GDALOpenInfo* poOpenInfo,
 
 {
     CPLAssert( nLayers == 0 );
-    
+
     const char * pszNewName = poOpenInfo->pszFilename;
     int bUpdate = poOpenInfo->eAccess == GA_Update;
     papszOpenOptions = CSLDuplicate( poOpenInfo->papszOpenOptions );
-    
+
     pszName = CPLStrdup( pszNewName );
 
     bDSUpdate = bUpdate;
@@ -124,15 +123,16 @@ int OGRShapeDataSource::Open( GDALOpenInfo* poOpenInfo,
     bSingleFileDataSource = bForceSingleFileDataSource;
 
 /* -------------------------------------------------------------------- */
-/*      If  bSingleFileDataSource is TRUE we don't try to do anything else.     */
+/*      If bSingleFileDataSource is TRUE we don't try to do anything    */
+/*      else.                                                           */
 /*      This is only utilized when the OGRShapeDriver::Create()         */
 /*      method wants to create a stub OGRShapeDataSource for a          */
 /*      single shapefile.  The driver will take care of creating the    */
-/*      file by callingICreateLayer().                                  */
+/*      file by calling ICreateLayer().                                 */
 /* -------------------------------------------------------------------- */
     if( bSingleFileDataSource )
         return TRUE;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Is the given path a directory or a regular file?                */
 /* -------------------------------------------------------------------- */
@@ -145,7 +145,7 @@ int OGRShapeDataSource::Open( GDALOpenInfo* poOpenInfo,
 
         return FALSE;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Build a list of filenames we figure are Shape files.            */
 /* -------------------------------------------------------------------- */
@@ -168,7 +168,7 @@ int OGRShapeDataSource::Open( GDALOpenInfo* poOpenInfo,
     }
     else
     {
-        char      **papszCandidates = CPLReadDir( pszNewName );
+        char      **papszCandidates = VSIReadDir( pszNewName );
         int       iCan, nCandidateCount = CSLCount( papszCandidates );
         int       bMightBeOldCoverage = FALSE;
         std::set<CPLString> osLayerNameSet;
@@ -215,7 +215,7 @@ int OGRShapeDataSource::Open( GDALOpenInfo* poOpenInfo,
             CPLFree( pszFilename );
         }
 
-        // Try and .dbf files without apparent associated shapefiles. 
+        // Try and .dbf files without apparent associated shapefiles.
         for( iCan = 0; iCan < nCandidateCount; iCan++ )
         {
             char        *pszFilename;
@@ -228,7 +228,7 @@ int OGRShapeDataSource::Open( GDALOpenInfo* poOpenInfo,
 
             // We don't consume .dbf files in a directory that looks like
             // an old style Arc/Info (for PC?) that unless we found at least
-            // some shapefiles.  See Bug 493. 
+            // some shapefiles.  See Bug 493.
             if( bMightBeOldCoverage && osLayerNameSet.size() == 0 )
                 continue;
 
@@ -282,7 +282,7 @@ int OGRShapeDataSource::Open( GDALOpenInfo* poOpenInfo,
 #ifdef IMMEDIATE_OPENING
         int nDirLayers = nLayers;
 #else
-        int nDirLayers = oVectorLayerName.size();
+        int nDirLayers = static_cast<int>(oVectorLayerName.size());
 #endif
 
         CPLErrorReset();
@@ -311,7 +311,7 @@ int OGRShapeDataSource::OpenFile( const char *pszNewName, int bUpdate,
 
 /* -------------------------------------------------------------------- */
 /*      SHPOpen() should include better (CPL based) error reporting,    */
-/*      and we should be trying to distinquish at this point whether    */
+/*      and we should be trying to distinguish at this point whether    */
 /*      failure is a result of trying to open a non-shapefile, or       */
 /*      whether it was a shapefile and we want to report the error      */
 /*      up.                                                             */
@@ -326,8 +326,8 @@ int OGRShapeDataSource::OpenFile( const char *pszNewName, int bUpdate,
         hSHP = DS_SHPOpen( pszNewName, "r" );
     CPLPopErrorHandler();
 
-    if( hSHP == NULL 
-        && (!EQUAL(CPLGetExtension(pszNewName),"dbf") 
+    if( hSHP == NULL
+        && (!EQUAL(CPLGetExtension(pszNewName),"dbf")
             || strstr(CPLGetLastErrorMsg(),".shp") == NULL) )
     {
         CPLString osMsg = CPLGetLastErrorMsg();
@@ -337,7 +337,7 @@ int OGRShapeDataSource::OpenFile( const char *pszNewName, int bUpdate,
         return FALSE;
     }
     CPLErrorReset();
-    
+
 /* -------------------------------------------------------------------- */
 /*      Open the .dbf file, if it exists.  To open a dbf file, the      */
 /*      filename has to either refer to a successfully opened shp       */
@@ -378,7 +378,7 @@ int OGRShapeDataSource::OpenFile( const char *pszNewName, int bUpdate,
     }
     else
         hDBF = NULL;
-        
+
     if( hDBF == NULL && hSHP == NULL )
         return FALSE;
 
@@ -477,20 +477,44 @@ OGRShapeDataSource::ICreateLayer( const char * pszLayerName,
         nShapeType = SHPT_MULTIPOINT;
     else if( eType == wkbPoint25D )
         nShapeType = SHPT_POINTZ;
+    else if( eType == wkbPointM )
+        nShapeType = SHPT_POINTM;
+    else if( eType == wkbPointZM )
+        nShapeType = SHPT_POINTZ;
     else if( eType == wkbLineString25D )
         nShapeType = SHPT_ARCZ;
+    else if( eType == wkbLineStringM )
+        nShapeType = SHPT_ARCM;
+    else if( eType == wkbLineStringZM )
+        nShapeType = SHPT_ARCZ;
     else if( eType == wkbMultiLineString )
         nShapeType = SHPT_ARC;
     else if( eType == wkbMultiLineString25D )
         nShapeType = SHPT_ARCZ;
+    else if( eType == wkbMultiLineStringM )
+        nShapeType = SHPT_ARCM;
+    else if( eType == wkbMultiLineStringZM )
+        nShapeType = SHPT_ARCZ;
     else if( eType == wkbPolygon25D )
         nShapeType = SHPT_POLYGONZ;
+    else if( eType == wkbPolygonM )
+        nShapeType = SHPT_POLYGONM;
+    else if( eType == wkbPolygonZM )
+        nShapeType = SHPT_POLYGONZ;
     else if( eType == wkbMultiPolygon )
         nShapeType = SHPT_POLYGON;
     else if( eType == wkbMultiPolygon25D )
         nShapeType = SHPT_POLYGONZ;
+    else if( eType == wkbMultiPolygonM )
+        nShapeType = SHPT_POLYGONM;
+    else if( eType == wkbMultiPolygonZM )
+        nShapeType = SHPT_POLYGONZ;
     else if( eType == wkbMultiPoint25D )
         nShapeType = SHPT_MULTIPOINTZ;
+    else if( eType == wkbMultiPointM )
+        nShapeType = SHPT_MULTIPOINTM;
+    else if( eType == wkbMultiPointZM )
+        nShapeType = SHPT_MULTIPOINTZ;
     else if( eType == wkbNone )
         nShapeType = SHPT_NULL;
     else
@@ -544,6 +568,46 @@ OGRShapeDataSource::ICreateLayer( const char * pszLayerName,
         nShapeType = SHPT_MULTIPOINTZ;
         eType = wkbMultiPoint25D;
     }
+    else if( EQUAL(pszOverride,"POINTM") )
+    {
+        nShapeType = SHPT_POINTM;
+        eType = wkbPointM;
+    }
+    else if( EQUAL(pszOverride,"ARCM") )
+    {
+        nShapeType = SHPT_ARCM;
+        eType = wkbLineStringM;
+    }
+    else if( EQUAL(pszOverride,"POLYGONM") )
+    {
+        nShapeType = SHPT_POLYGONM;
+        eType = wkbPolygonM;
+    }
+    else if( EQUAL(pszOverride,"MULTIPOINTM") )
+    {
+        nShapeType = SHPT_MULTIPOINTM;
+        eType = wkbMultiPointM;
+    }
+    else if( EQUAL(pszOverride,"POINTZM") )
+    {
+        nShapeType = SHPT_POINTZ;
+        eType = wkbPointZM;
+    }
+    else if( EQUAL(pszOverride,"ARCZM") )
+    {
+        nShapeType = SHPT_ARCZ;
+        eType = wkbLineStringZM;
+    }
+    else if( EQUAL(pszOverride,"POLYGONZM") )
+    {
+        nShapeType = SHPT_POLYGONZ;
+        eType = wkbPolygonZM;
+    }
+    else if( EQUAL(pszOverride,"MULTIPOINTZM") )
+    {
+        nShapeType = SHPT_MULTIPOINTZ;
+        eType = wkbMultiPointZM;
+    }
     else if( EQUAL(pszOverride,"NONE") || EQUAL(pszOverride,"NULL") )
     {
         nShapeType = SHPT_NULL;
@@ -568,7 +632,7 @@ OGRShapeDataSource::ICreateLayer( const char * pszLayerName,
                   OGRGeometryTypeToName(eType) );
         return NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      What filename do we use, excluding the extension?               */
 /* -------------------------------------------------------------------- */
@@ -604,14 +668,14 @@ OGRShapeDataSource::ICreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
     char        *pszFilename;
 
-    int b2GBLimit = CSLTestBoolean(CSLFetchNameValueDef( papszOptions, "2GB_LIMIT", "FALSE" ));
+    int l_b2GBLimit = CPLTestBool(CSLFetchNameValueDef( papszOptions, "2GB_LIMIT", "FALSE" ));
 
     if( nShapeType != SHPT_NULL )
     {
         pszFilename = CPLStrdup(CPLFormFilename( NULL, pszFilenameWithoutExt, "shp" ));
 
-        hSHP = SHPCreateLL( pszFilename, nShapeType, (SAHooks*) VSI_SHP_GetHook(b2GBLimit) );
-        
+        hSHP = SHPCreateLL( pszFilename, nShapeType, (SAHooks*) VSI_SHP_GetHook(l_b2GBLimit) );
+
         if( hSHP == NULL )
         {
             CPLError( CE_Failure, CPLE_OpenFailed,
@@ -621,7 +685,7 @@ OGRShapeDataSource::ICreateLayer( const char * pszLayerName,
             CPLFree( pszFilenameWithoutExt );
             return NULL;
         }
-        
+
         SHPSetFastModeReadObject( hSHP, TRUE );
 
         CPLFree( pszFilename );
@@ -670,7 +734,7 @@ OGRShapeDataSource::ICreateLayer( const char * pszLayerName,
         poSRS = poSRS->Clone();
         poSRS->morphToESRI();
 
-        if( poSRS->exportToWkt( &pszWKT ) == OGRERR_NONE 
+        if( poSRS->exportToWkt( &pszWKT ) == OGRERR_NONE
             && (fp = VSIFOpenL( osPrjFile, "wt" )) != NULL )
         {
             VSIFWriteL( pszWKT, strlen(pszWKT), 1, fp );
@@ -722,6 +786,8 @@ int OGRShapeDataSource::TestCapability( const char * pszCap )
         return bDSUpdate;
     else if( EQUAL(pszCap,ODsCDeleteLayer) )
         return bDSUpdate;
+    else if( EQUAL(pszCap,ODsCMeasuredGeometries) )
+        return TRUE;
     else
         return FALSE;
 }
@@ -860,9 +926,9 @@ OGRLayer * OGRShapeDataSource::ExecuteSQL( const char *pszStatement,
 /* ==================================================================== */
 /*      Handle command to drop a spatial index.                         */
 /* ==================================================================== */
-    if( EQUALN(pszStatement, "REPACK ", 7) )
+    if( STARTS_WITH_CI(pszStatement, "REPACK ") )
     {
-        OGRShapeLayer *poLayer = (OGRShapeLayer *) 
+        OGRShapeLayer *poLayer = (OGRShapeLayer *)
             GetLayerByName( pszStatement + 7 );
 
         if( poLayer != NULL )
@@ -876,8 +942,8 @@ OGRLayer * OGRShapeDataSource::ExecuteSQL( const char *pszStatement,
         }
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "No such layer as '%s' in REPACK.", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "No such layer as '%s' in REPACK.",
                       pszStatement + 7 );
         }
         return NULL;
@@ -886,7 +952,7 @@ OGRLayer * OGRShapeDataSource::ExecuteSQL( const char *pszStatement,
 /* ==================================================================== */
 /*      Handle command to shrink columns to their minimum size.         */
 /* ==================================================================== */
-    if( EQUALN(pszStatement, "RESIZE ", 7) )
+    if( STARTS_WITH_CI(pszStatement, "RESIZE ") )
     {
         OGRShapeLayer *poLayer = (OGRShapeLayer *)
             GetLayerByName( pszStatement + 7 );
@@ -905,45 +971,45 @@ OGRLayer * OGRShapeDataSource::ExecuteSQL( const char *pszStatement,
 /* ==================================================================== */
 /*      Handle command to recompute extent                             */
 /* ==================================================================== */
-    if( EQUALN(pszStatement, "RECOMPUTE EXTENT ON ", 20) )
+    if( STARTS_WITH_CI(pszStatement, "RECOMPUTE EXTENT ON ") )
     {
-        OGRShapeLayer *poLayer = (OGRShapeLayer *) 
+        OGRShapeLayer *poLayer = (OGRShapeLayer *)
             GetLayerByName( pszStatement + 20 );
 
         if( poLayer != NULL )
             poLayer->RecomputeExtent();
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "No such layer as '%s' in RECOMPUTE EXTENT.", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "No such layer as '%s' in RECOMPUTE EXTENT.",
                       pszStatement + 20 );
         }
         return NULL;
     }
-    
+
 /* ==================================================================== */
 /*      Handle command to drop a spatial index.                         */
 /* ==================================================================== */
-    if( EQUALN(pszStatement, "DROP SPATIAL INDEX ON ", 22) )
+    if( STARTS_WITH_CI(pszStatement, "DROP SPATIAL INDEX ON ") )
     {
-        OGRShapeLayer *poLayer = (OGRShapeLayer *) 
+        OGRShapeLayer *poLayer = (OGRShapeLayer *)
             GetLayerByName( pszStatement + 22 );
 
         if( poLayer != NULL )
             poLayer->DropSpatialIndex();
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "No such layer as '%s' in DROP SPATIAL INDEX.", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "No such layer as '%s' in DROP SPATIAL INDEX.",
                       pszStatement + 22 );
         }
         return NULL;
     }
-    
+
 /* ==================================================================== */
-/*      Handle all comands except spatial index creation generically.   */
+/*      Handle all commands except spatial index creation generically.  */
 /* ==================================================================== */
-    if( !EQUALN(pszStatement,"CREATE SPATIAL INDEX ON ",24) )
+    if( !STARTS_WITH_CI(pszStatement, "CREATE SPATIAL INDEX ON ") )
     {
         char **papszTokens = CSLTokenizeString( pszStatement );
         if( CSLCount(papszTokens) >=4
@@ -957,7 +1023,7 @@ OGRLayer * OGRShapeDataSource::ExecuteSQL( const char *pszStatement,
         }
         CSLDestroy( papszTokens );
 
-        return OGRDataSource::ExecuteSQL( pszStatement, poSpatialFilter, 
+        return OGRDataSource::ExecuteSQL( pszStatement, poSpatialFilter,
                                           pszDialect );
     }
 
@@ -965,20 +1031,21 @@ OGRLayer * OGRShapeDataSource::ExecuteSQL( const char *pszStatement,
 /*      Parse into keywords.                                            */
 /* -------------------------------------------------------------------- */
     char **papszTokens = CSLTokenizeString( pszStatement );
-    
+
     if( CSLCount(papszTokens) < 5
         || !EQUAL(papszTokens[0],"CREATE")
         || !EQUAL(papszTokens[1],"SPATIAL")
-        || !EQUAL(papszTokens[2],"INDEX") 
-        || !EQUAL(papszTokens[3],"ON") 
-        || CSLCount(papszTokens) > 7 
+        || !EQUAL(papszTokens[2],"INDEX")
+        || !EQUAL(papszTokens[3],"ON")
+        || CSLCount(papszTokens) > 7
         || (CSLCount(papszTokens) == 7 && !EQUAL(papszTokens[5],"DEPTH")) )
     {
         CSLDestroy( papszTokens );
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Syntax error in CREATE SPATIAL INDEX command.\n"
                   "Was '%s'\n"
-                  "Should be of form 'CREATE SPATIAL INDEX ON <table> [DEPTH <n>]'",
+                  "Should be of form 'CREATE SPATIAL INDEX ON <table> "
+                  "[DEPTH <n>]'",
                   pszStatement );
         return NULL;
     }
@@ -997,8 +1064,8 @@ OGRLayer * OGRShapeDataSource::ExecuteSQL( const char *pszStatement,
 
     if( poLayer == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Layer %s not recognised.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Layer %s not recognised.",
                   papszTokens[4] );
         CSLDestroy( papszTokens );
         return NULL;
@@ -1018,8 +1085,6 @@ OGRLayer * OGRShapeDataSource::ExecuteSQL( const char *pszStatement,
 OGRErr OGRShapeDataSource::DeleteLayer( int iLayer )
 
 {
-    char *pszFilename;
-
 /* -------------------------------------------------------------------- */
 /*      Verify we are in update mode.                                   */
 /* -------------------------------------------------------------------- */
@@ -1027,7 +1092,7 @@ OGRErr OGRShapeDataSource::DeleteLayer( int iLayer )
     {
         CPLError( CE_Failure, CPLE_NoWriteAccess,
                   "Data source %s opened read-only.\n"
-                  "Layer %d cannot be deleted.\n",
+                  "Layer %d cannot be deleted.",
                   pszName, iLayer );
 
         return OGRERR_FAILURE;
@@ -1035,15 +1100,15 @@ OGRErr OGRShapeDataSource::DeleteLayer( int iLayer )
 
     if( iLayer < 0 || iLayer >= nLayers )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Layer %d not in legal range of 0 to %d.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Layer %d not in legal range of 0 to %d.",
                   iLayer, nLayers-1 );
         return OGRERR_FAILURE;
     }
 
     OGRShapeLayer* poLayerToDelete = (OGRShapeLayer*) papoLayers[iLayer];
 
-    pszFilename = CPLStrdup(poLayerToDelete->GetFullName());
+    char *pszFilename = CPLStrdup(poLayerToDelete->GetFullName());
 
     delete poLayerToDelete;
 
@@ -1077,7 +1142,7 @@ void OGRShapeDataSource::SetLastUsedLayer( OGRShapeLayer* poLayer )
     /* The only rationale for that test is to avoid breaking applications */
     /* that would deal with layers of the same datasource in different */
     /* threads. In GDAL < 1.9.0, this would work in most cases I can */
-    /* imagine as shapefile layers are pretty much independant from each */
+    /* imagine as shapefile layers are pretty much independent from each */
     /* others (although it has never been guaranteed to be a valid use case, */
     /* and the shape driver is likely more the exception than the rule in */
     /* permitting accessing layers from different threads !) */
diff --git a/ogr/ogrsf_frmts/shape/ogrshapedriver.cpp b/ogr/ogrsf_frmts/shape/ogrshapedriver.cpp
index e0826fa..10b35f4 100644
--- a/ogr/ogrsf_frmts/shape/ogrshapedriver.cpp
+++ b/ogr/ogrsf_frmts/shape/ogrshapedriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrshapedriver.cpp 29528 2015-07-15 17:01:23Z rouault $
+ * $Id: ogrshapedriver.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRShapeDriver class.
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrshapedriver.cpp 29528 2015-07-15 17:01:23Z rouault $");
+CPL_CVSID("$Id: ogrshapedriver.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                              Identify()                              */
@@ -44,14 +44,17 @@ static int OGRShapeDriverIdentify( GDALOpenInfo* poOpenInfo )
         return FALSE;
     if( poOpenInfo->bIsDirectory )
         return -1; /* unsure */
-    if( poOpenInfo->fpL != NULL &&
-        (EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "SHP") ||
-         EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "SHX")) )
+    if( poOpenInfo->fpL == NULL )
+    {
+        return FALSE;
+    }
+    CPLString osExt(CPLGetExtension(poOpenInfo->pszFilename));
+    if (EQUAL(osExt, "SHP") ||  EQUAL(osExt, "SHX") )
     {
         return memcmp(poOpenInfo->pabyHeader, "\x00\x00\x27\x0A", 4) == 0 ||
                memcmp(poOpenInfo->pabyHeader, "\x00\x00\x27\x0D", 4) == 0;
     }
-    if( poOpenInfo->fpL != NULL && EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "DBF") )
+    if( EQUAL(osExt, "DBF") )
     {
         if( poOpenInfo->nHeaderBytes < 32 )
             return FALSE;
@@ -71,6 +74,14 @@ static int OGRShapeDriverIdentify( GDALOpenInfo* poOpenInfo )
             return FALSE;
         return TRUE;
     }
+#ifdef DEBUG
+    /* For AFL, so that .cur_input is detected as the archive filename */
+    if( !STARTS_WITH(poOpenInfo->pszFilename, "/vsitar/") &&
+        EQUAL(CPLGetFilename(poOpenInfo->pszFilename), ".cur_input") )
+    {
+        return -1;
+    }
+#endif
     return FALSE;
 }
 
@@ -86,6 +97,19 @@ static GDALDataset *OGRShapeDriverOpen( GDALOpenInfo* poOpenInfo )
     if( OGRShapeDriverIdentify(poOpenInfo) == FALSE )
         return NULL;
 
+#ifdef DEBUG
+    /* For AFL, so that .cur_input is detected as the archive filename */
+    if( poOpenInfo->fpL != NULL &&
+        !STARTS_WITH(poOpenInfo->pszFilename, "/vsitar/") &&
+        EQUAL(CPLGetFilename(poOpenInfo->pszFilename), ".cur_input") )
+    {
+        GDALOpenInfo oOpenInfo( (CPLString("/vsitar/") + poOpenInfo->pszFilename).c_str(),
+                                poOpenInfo->nOpenFlags );
+        oOpenInfo.papszOpenOptions = poOpenInfo->papszOpenOptions;
+        return OGRShapeDriverOpen(&oOpenInfo);
+    }
+#endif
+
     poDS = new OGRShapeDataSource();
 
     if( !poDS->Open( poOpenInfo, TRUE ) )
@@ -121,7 +145,7 @@ static GDALDataset *OGRShapeDriverCreate( const char * pszName,
             CPLError( CE_Failure, CPLE_AppDefined,
                       "%s is not a directory.\n",
                       pszName );
-            
+
             return NULL;
         }
     }
@@ -130,7 +154,7 @@ static GDALDataset *OGRShapeDriverCreate( const char * pszName,
 /*      Does it end in the extension .shp indicating the user likely    */
 /*      wants to create a single file set?                              */
 /* -------------------------------------------------------------------- */
-    else if( EQUAL(CPLGetExtension(pszName),"shp") 
+    else if( EQUAL(CPLGetExtension(pszName),"shp")
              || EQUAL(CPLGetExtension(pszName),"dbf") )
     {
         bSingleNewFile = TRUE;
@@ -147,7 +171,7 @@ static GDALDataset *OGRShapeDriverCreate( const char * pszName,
                       "Failed to create directory %s\n"
                       "for shapefile datastore.\n",
                       pszName );
-            
+
             return NULL;
         }
     }
@@ -158,7 +182,7 @@ static GDALDataset *OGRShapeDriverCreate( const char * pszName,
     OGRShapeDataSource  *poDS = NULL;
 
     poDS = new OGRShapeDataSource();
-    
+
     GDALOpenInfo oOpenInfo( pszName, GA_Update );
     if( !poDS->Open( &oOpenInfo, FALSE, bSingleNewFile ) )
     {
@@ -178,8 +202,8 @@ static CPLErr OGRShapeDriverDelete( const char *pszDataSource )
 {
     int iExt;
     VSIStatBufL sStatBuf;
-    static const char *apszExtensions[] = 
-        { "shp", "shx", "dbf", "sbn", "sbx", "prj", "idm", "ind", 
+    static const char * const apszExtensions[] =
+        { "shp", "shx", "dbf", "sbn", "sbx", "prj", "idm", "ind",
           "qix", "cpg", NULL };
 
     if( VSIStatL( pszDataSource, &sStatBuf ) != 0 )
@@ -191,7 +215,7 @@ static CPLErr OGRShapeDriverDelete( const char *pszDataSource )
         return CE_Failure;
     }
 
-    if( VSI_ISREG(sStatBuf.st_mode) 
+    if( VSI_ISREG(sStatBuf.st_mode)
         && (EQUAL(CPLGetExtension(pszDataSource),"shp")
             || EQUAL(CPLGetExtension(pszDataSource),"shx")
             || EQUAL(CPLGetExtension(pszDataSource),"dbf")) )
@@ -206,18 +230,18 @@ static CPLErr OGRShapeDriverDelete( const char *pszDataSource )
     }
     else if( VSI_ISDIR(sStatBuf.st_mode) )
     {
-        char **papszDirEntries = CPLReadDir( pszDataSource );
+        char **papszDirEntries = VSIReadDir( pszDataSource );
         int  iFile;
 
-        for( iFile = 0; 
+        for( iFile = 0;
              papszDirEntries != NULL && papszDirEntries[iFile] != NULL;
              iFile++ )
         {
-            if( CSLFindString( (char **) apszExtensions, 
+            if( CSLFindString( (char **) apszExtensions,
                                CPLGetExtension(papszDirEntries[iFile])) != -1)
             {
-                VSIUnlink( CPLFormFilename( pszDataSource, 
-                                            papszDirEntries[iFile], 
+                VSIUnlink( CPLFormFilename( pszDataSource,
+                                            papszDirEntries[iFile],
                                             NULL ) );
             }
         }
@@ -237,30 +261,33 @@ static CPLErr OGRShapeDriverDelete( const char *pszDataSource )
 void RegisterOGRShape()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "ESRI Shapefile" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "ESRI Shapefile" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-
-        poDriver->SetDescription( "ESRI Shapefile" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "ESRI Shapefile" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "shp" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "shp dbf" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_shape.html" );
-
-        poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "ESRI Shapefile" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "ESRI Shapefile" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "shp" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "shp dbf" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_shape.html" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
 "<OpenOptionList>"
 "  <Option name='ENCODING' type='string' description='to override the encoding interpretation of the DBF with any encoding supported by CPLRecode or to \"\" to avoid any recoding'/>"
 "  <Option name='DBF_DATE_LAST_UPDATE' type='string' description='Modification date to write in DBF header with YYYY-MM-DD format'/>"
 "  <Option name='ADJUST_TYPE' type='boolean' description='Whether to read whole .dbf to adjust Real->Integer/Integer64 or Integer64->Integer field types if possible' default='NO'/>"
+"  <Option name='ADJUST_GEOM_TYPE' type='string-select' description='Whether and how to adjust layer geometry type from actual shapes' default='FIRST_SHAPE'>"
+"    <Value>NO</Value>"
+"    <Value>FIRST_SHAPE</Value>"
+"    <Value>ALL_SHAPES</Value>"
+"  </Option>"
 "</OpenOptionList>");
 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, "<CreationOptionList/>" );
-        poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+                               "<CreationOptionList/>" );
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
 "<LayerCreationOptionList>"
 "  <Option name='SHPT' type='string-select' description='type of shape' default='automatically detected'>"
 "    <Value>POINT</Value>"
@@ -271,6 +298,14 @@ void RegisterOGRShape()
 "    <Value>ARCZ</Value>"
 "    <Value>POLYGONZ</Value>"
 "    <Value>MULTIPOINTZ</Value>"
+"    <Value>POINTM</Value>"
+"    <Value>ARCM</Value>"
+"    <Value>POLYGONM</Value>"
+"    <Value>MULTIPOINTM</Value>"
+"    <Value>POINTZM</Value>"
+"    <Value>ARCZM</Value>"
+"    <Value>POLYGONZM</Value>"
+"    <Value>MULTIPOINTZM</Value>"
 "    <Value>NONE</Value>"
 "    <Value>NULL</Value>"
 "  </Option>"
@@ -280,16 +315,15 @@ void RegisterOGRShape()
 "  <Option name='SPATIAL_INDEX' type='boolean' description='To create a spatial index.' default='NO'/>"
 "  <Option name='DBF_DATE_LAST_UPDATE' type='string' description='Modification date to write in DBF header with YYYY-MM-DD format'/>"
 "</LayerCreationOptionList>");
-        
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES, "Integer Integer64 Real String Date DateTime" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
+                               "Integer Integer64 Real String Date DateTime" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = OGRShapeDriverOpen;
-        poDriver->pfnIdentify = OGRShapeDriverIdentify;
-        poDriver->pfnCreate = OGRShapeDriverCreate;
-        poDriver->pfnDelete = OGRShapeDriverDelete;
+    poDriver->pfnOpen = OGRShapeDriverOpen;
+    poDriver->pfnIdentify = OGRShapeDriverIdentify;
+    poDriver->pfnCreate = OGRShapeDriverCreate;
+    poDriver->pfnDelete = OGRShapeDriverDelete;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/shape/ogrshapelayer.cpp b/ogr/ogrsf_frmts/shape/ogrshapelayer.cpp
index d6666f7..4b61cae 100644
--- a/ogr/ogrsf_frmts/shape/ogrshapelayer.cpp
+++ b/ogr/ogrsf_frmts/shape/ogrshapelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrshapelayer.cpp 32350 2015-12-20 17:46:02Z rouault $
+ * $Id: ogrshapelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRShapeLayer class.
@@ -34,17 +34,13 @@
 #include "ogr_p.h"
 #include "cpl_time.h"
 
-#if defined(_WIN32_WCE)
-#  include <wce_errno.h>
-#endif
-
 #define FD_OPENED           0
 #define FD_CLOSED           1
 #define FD_CANNOT_REOPEN    2
 
 #define UNSUPPORTED_OP_READ_ONLY "%s : unsupported operation on a read-only datasource."
 
-CPL_CVSID("$Id: ogrshapelayer.cpp 32350 2015-12-20 17:46:02Z rouault $");
+CPL_CVSID("$Id: ogrshapelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                           OGRShapeLayer()                            */
@@ -52,40 +48,36 @@ CPL_CVSID("$Id: ogrshapelayer.cpp 32350 2015-12-20 17:46:02Z rouault $");
 
 OGRShapeLayer::OGRShapeLayer( OGRShapeDataSource* poDSIn,
                               const char * pszFullNameIn,
-                              SHPHandle hSHPIn, DBFHandle hDBFIn, 
+                              SHPHandle hSHPIn, DBFHandle hDBFIn,
                               OGRSpatialReference *poSRSIn, int bSRSSetIn,
                               int bUpdate,
                               OGRwkbGeometryType eReqType,
                               char ** papszCreateOptions ) :
-                                OGRAbstractProxiedLayer(poDSIn->GetPool())
-
+    OGRAbstractProxiedLayer(poDSIn->GetPool()),
+    poDS(poDSIn),
+    iNextShapeId(0),
+    hSHP(hSHPIn),
+    hDBF(hDBFIn),
+    bUpdateAccess(bUpdate),
+    eRequestedGeomType(eReqType),
+    panMatchingFIDs(NULL),
+    iMatchingFID(0),
+    m_poFilterGeomLastValid(NULL),
+    nSpatialFIDCount(0),
+    panSpatialFIDs(NULL),
+    bHeaderDirty(FALSE),
+    bSHPNeedsRepack(FALSE),
+    bCheckedForQIX(FALSE),
+    hQIX(NULL),
+    bCheckedForSBN(FALSE),
+    hSBN(NULL),
+    bSbnSbxDeleted(FALSE),
+    bTruncationWarningEmitted(FALSE),
+    eFileDescriptorsState(FD_OPENED),
+    bResizeAtClose(FALSE),
+    bCreateSpatialIndexAtClose(FALSE)
 {
-    poDS = poDSIn;
-
     pszFullName = CPLStrdup(pszFullNameIn);
-    
-    hSHP = hSHPIn;
-    hDBF = hDBFIn;
-    bUpdateAccess = bUpdate;
-
-    iNextShapeId = 0;
-    iMatchingFID = 0;
-    panMatchingFIDs = NULL;
-
-    nSpatialFIDCount = 0;
-    panSpatialFIDs = NULL;
-    m_poFilterGeomLastValid = NULL;
-
-    bCheckedForQIX = FALSE;
-    hQIX = NULL;
-
-    bCheckedForSBN = FALSE;
-    hSBN = NULL;
-
-    bSbnSbxDeleted = FALSE;
-
-    bHeaderDirty = FALSE;
-    bSHPNeedsRepack = FALSE;
 
     if( hSHP != NULL )
     {
@@ -96,30 +88,25 @@ OGRShapeLayer::OGRShapeLayer( OGRShapeDataSource* poDSIn,
                      hSHP->nRecords, hDBF->nRecords);
         }
     }
-    else 
+    else
         nTotalShapeCount = hDBF->nRecords;
-    
-    eRequestedGeomType = eReqType;
-
-    bTruncationWarningEmitted = FALSE;
 
     bHSHPWasNonNULL = hSHPIn != NULL;
     bHDBFWasNonNULL = hDBFIn != NULL;
-    eFileDescriptorsState = FD_OPENED;
-    TouchLayer();
-
-    bResizeAtClose = FALSE;
-    bCreateSpatialIndexAtClose = FALSE;
+    if (!TouchLayer())
+    {
+        CPLDebug("Shape", "TouchLayer in shape ctor failed. ");
+    }
 
     if( hDBF != NULL && hDBF->pszCodePage != NULL )
     {
-        CPLDebug( "Shape", "DBF Codepage = %s for %s", 
+        CPLDebug( "Shape", "DBF Codepage = %s for %s",
                   hDBF->pszCodePage, pszFullName );
 
         // Not too sure about this, but it seems like better than nothing.
         osEncoding = ConvertCodePage( hDBF->pszCodePage );
     }
-    
+
     if( hDBF != NULL )
     {
         if( !(hDBF->nUpdateYearSince1900 == 95 &&
@@ -135,7 +122,7 @@ OGRShapeLayer::OGRShapeLayer( OGRShapeDataSource* poDSIn,
         DBFSetLastModifiedDate( hDBF, tm.tm_year,
                                 tm.tm_mon + 1, tm.tm_mday );
     }
-    
+
     const char* pszShapeEncoding = NULL;
     pszShapeEncoding = CSLFetchNameValue(poDS->GetOpenOptions(), "ENCODING");
     if( pszShapeEncoding == NULL && osEncoding == "")
@@ -164,15 +151,64 @@ OGRShapeLayer::OGRShapeLayer( OGRShapeDataSource* poDSIn,
     OGRwkbGeometryType eGeomType = poFeatureDefn->GetGeomType();
     if( eGeomType != wkbNone )
     {
+        OGRwkbGeometryType eType;
+
+        if( eRequestedGeomType == wkbNone )
+        {
+            eType = eGeomType;
+
+            const char* pszAdjustGeomType = CSLFetchNameValueDef(
+                            poDS->GetOpenOptions(), "ADJUST_GEOM_TYPE", "FIRST_SHAPE");
+            const bool bFirstShape = EQUAL(pszAdjustGeomType, "FIRST_SHAPE");
+            const bool bAllShapes  = EQUAL(pszAdjustGeomType, "ALL_SHAPES");
+            if( (hSHP != NULL) && (hSHP->nRecords > 0) && wkbHasM(eType) &&
+                (bFirstShape || bAllShapes) )
+            {
+                bool bMIsUsed = false;
+                for(int iShape=0; iShape < hSHP->nRecords; iShape++)
+                {
+                    SHPObject   *psShape = SHPReadObject( hSHP, iShape );
+                    if( psShape )
+                    {
+                        if( psShape->bMeasureIsUsed &&
+                            psShape->nVertices > 0 &&
+                            psShape->padfM != NULL )
+                        {
+                            for(int i=0;i<psShape->nVertices;i++)
+                            {
+                                /* Per the spec, if the M value is smaller than -1e38,
+                                 * it is a nodata value
+                                 */
+                                if( psShape->padfM[i] > -1e38 )
+                                {
+                                    bMIsUsed = true;
+                                    break;
+                                }
+                            }
+                        }
+
+                        SHPDestroyObject(psShape);
+                    }
+                    if( bFirstShape || bMIsUsed )
+                        break;
+                }
+                if( !bMIsUsed )
+                    eType = OGR_GT_SetModifier(eType, wkbHasZ(eType), FALSE);
+            }
+        }
+        else
+            eType = eRequestedGeomType;
+
         OGRShapeGeomFieldDefn* poGeomFieldDefn =
-            new OGRShapeGeomFieldDefn(pszFullName, eGeomType, bSRSSetIn, poSRSIn);
+            //new OGRShapeGeomFieldDefn(pszFullName, eGeomType, bSRSSetIn, poSRSIn);
+            new OGRShapeGeomFieldDefn(pszFullName, eType, bSRSSetIn, poSRSIn);
         poFeatureDefn->SetGeomType(wkbNone);
         poFeatureDefn->AddGeomFieldDefn(poGeomFieldDefn, FALSE);
     }
     else if( bSRSSetIn && poSRSIn != NULL )
         poSRSIn->Release();
     SetDescription( poFeatureDefn->GetName() );
-    bRewindOnWrite = CSLTestBoolean(CPLGetConfigOption( "SHAPE_REWIND_ON_WRITE", "YES" ));
+    bRewindOnWrite = CPLTestBool(CPLGetConfigOption( "SHAPE_REWIND_ON_WRITE", "YES" ));
 }
 
 /************************************************************************/
@@ -194,7 +230,7 @@ OGRShapeLayer::~OGRShapeLayer()
     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     {
         CPLDebug( "Shape", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
+                  (int) m_nFeaturesRead,
                   poFeatureDefn->GetName() );
     }
 
@@ -246,14 +282,14 @@ void OGRShapeLayer::SetModificationDate(const char* pszStr)
 CPLString OGRShapeLayer::ConvertCodePage( const char *pszCodePage )
 
 {
-    CPLString osEncoding;
+    CPLString l_osEncoding;
 
     if( pszCodePage == NULL )
-        return osEncoding;
+        return l_osEncoding;
 
-    if( EQUALN(pszCodePage,"LDID/",5) )
+    if( STARTS_WITH_CI(pszCodePage, "LDID/") )
     {
-        int nCP = -1; // windows code page. 
+        int nCP = -1; // windows code page.
 
         //http://www.autopark.ru/ASBProgrammerGuide/DBFSTRUC.HTM
         switch( atoi(pszCodePage+5) )
@@ -326,29 +362,29 @@ CPLString OGRShapeLayer::ConvertCodePage( const char *pszCodePage )
 
         if( nCP != -1 )
         {
-            osEncoding.Printf( "CP%d", nCP );
-            return osEncoding;
+            l_osEncoding.Printf( "CP%d", nCP );
+            return l_osEncoding;
         }
     }
 
     // From the CPG file
     // http://resources.arcgis.com/fr/content/kbase?fa=articleShow&d=21106
-    
+
     if( (atoi(pszCodePage) >= 437 && atoi(pszCodePage) <= 950)
         || (atoi(pszCodePage) >= 1250 && atoi(pszCodePage) <= 1258) )
     {
-        osEncoding.Printf( "CP%d", atoi(pszCodePage) );
-        return osEncoding;
+        l_osEncoding.Printf( "CP%d", atoi(pszCodePage) );
+        return l_osEncoding;
     }
-    if( EQUALN(pszCodePage,"8859",4) )
+    if( STARTS_WITH_CI(pszCodePage, "8859") )
     {
         if( pszCodePage[4] == '-' )
-            osEncoding.Printf( "ISO-8859-%s", pszCodePage + 5 );
+            l_osEncoding.Printf( "ISO-8859-%s", pszCodePage + 5 );
         else
-            osEncoding.Printf( "ISO-8859-%s", pszCodePage + 4 );
-        return osEncoding;
+            l_osEncoding.Printf( "ISO-8859-%s", pszCodePage + 4 );
+        return l_osEncoding;
     }
-    if( EQUALN(pszCodePage,"UTF-8",5) )
+    if( STARTS_WITH_CI(pszCodePage, "UTF-8") )
         return CPL_ENC_UTF8;
 
     // try just using the CPG value directly.  Works for stuff like Big5.
@@ -369,7 +405,7 @@ int OGRShapeLayer::CheckForQIX()
 
     pszQIXFilename = CPLResetExtension( pszFullName, "qix" );
 
-    hQIX = SHPOpenDiskTree( pszQIXFilename, NULL ); 
+    hQIX = SHPOpenDiskTree( pszQIXFilename, NULL );
 
     bCheckedForQIX = TRUE;
 
@@ -460,9 +496,9 @@ int OGRShapeLayer::ScanIndices()
     if( bTryQIXorSBN )
     {
         if( !bCheckedForQIX )
-            CheckForQIX();
+            CPL_IGNORE_RET_VAL(CheckForQIX());
         if( hQIX == NULL && !bCheckedForSBN )
-            CheckForSBN();
+            CPL_IGNORE_RET_VAL(CheckForSBN());
     }
 
 /* -------------------------------------------------------------------- */
@@ -490,7 +526,7 @@ int OGRShapeLayer::ScanIndices()
                                                 adfBoundsMin, adfBoundsMax,
                                                 &nSpatialFIDCount );
 
-        CPLDebug( "SHAPE", "Used spatial index, got %d matches.", 
+        CPLDebug( "SHAPE", "Used spatial index, got %d matches.",
                   nSpatialFIDCount );
 
         delete m_poFilterGeomLastValid;
@@ -642,7 +678,7 @@ OGRErr OGRShapeLayer::SetAttributeFilter( const char * pszAttributeFilter )
 /************************************************************************/
 /*                           SetNextByIndex()                           */
 /*                                                                      */
-/*      If we already have an FID list, we can easily resposition       */
+/*      If we already have an FID list, we can easily reposition        */
 /*      ourselves in it.                                                */
 /************************************************************************/
 
@@ -655,8 +691,8 @@ OGRErr OGRShapeLayer::SetNextByIndex( GIntBig nIndex )
     if( nIndex < 0 || nIndex > INT_MAX )
         return OGRERR_FAILURE;
 
-    // Eventually we should try to use panMatchingFIDs list 
-    // if available and appropriate. 
+    // Eventually we should try to use panMatchingFIDs list
+    // if available and appropriate.
     if( m_poFilterGeom != NULL || m_poAttrQuery != NULL )
         return OGRLayer::SetNextByIndex( nIndex );
 
@@ -677,10 +713,10 @@ OGRFeature *OGRShapeLayer::FetchShape(int iShapeId /*, OGREnvelope* psShapeExten
 {
     OGRFeature *poFeature;
 
-    if (m_poFilterGeom != NULL && hSHP != NULL ) 
+    if (m_poFilterGeom != NULL && hSHP != NULL )
     {
         SHPObject   *psShape;
-        
+
         psShape = SHPReadObject( hSHP, iShapeId );
 
         // do not trust degenerate bounds on non-point geometries
@@ -696,15 +732,15 @@ OGRFeature *OGRShapeLayer::FetchShape(int iShapeId /*, OGREnvelope* psShapeExten
             poFeature = SHPReadOGRFeature( hSHP, hDBF, poFeatureDefn,
                                            iShapeId, psShape, osEncoding );
         }
-        else if( m_sFilterEnvelope.MaxX < psShape->dfXMin 
+        else if( m_sFilterEnvelope.MaxX < psShape->dfXMin
                  || m_sFilterEnvelope.MaxY < psShape->dfYMin
                  || psShape->dfXMax  < m_sFilterEnvelope.MinX
-                 || psShape->dfYMax < m_sFilterEnvelope.MinY ) 
+                 || psShape->dfYMax < m_sFilterEnvelope.MinY )
         {
             SHPDestroyObject(psShape);
             poFeature = NULL;
-        } 
-        else 
+        }
+        else
         {
             /*psShapeExtent->MinX = psShape->dfXMin;
             psShapeExtent->MinY = psShape->dfYMin;
@@ -712,14 +748,14 @@ OGRFeature *OGRShapeLayer::FetchShape(int iShapeId /*, OGREnvelope* psShapeExten
             psShapeExtent->MaxY = psShape->dfYMax;*/
             poFeature = SHPReadOGRFeature( hSHP, hDBF, poFeatureDefn,
                                            iShapeId, psShape, osEncoding );
-        }                
-    } 
-    else 
+        }
+    }
+    else
     {
         poFeature = SHPReadOGRFeature( hSHP, hDBF, poFeatureDefn,
                                        iShapeId, NULL, osEncoding );
-    }    
-    
+    }
+
     return poFeature;
 }
 
@@ -745,11 +781,11 @@ OGRFeature *OGRShapeLayer::GetNextFeature()
     {
         ScanIndices();
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Loop till we find a feature matching our criteria.              */
 /* -------------------------------------------------------------------- */
-    while( TRUE )
+    while( true )
     {
         //OGREnvelope oShapeExtent;
 
@@ -759,11 +795,11 @@ OGRFeature *OGRShapeLayer::GetNextFeature()
             {
                 return NULL;
             }
-            
+
             // Check the shape object's geometry, and if it matches
-            // any spatial filter, return it.  
+            // any spatial filter, return it.
             poFeature = FetchShape((int)panMatchingFIDs[iMatchingFID] /*, &oShapeExtent*/);
-            
+
             iMatchingFID++;
 
         }
@@ -788,7 +824,7 @@ OGRFeature *OGRShapeLayer::GetNextFeature()
 
             iNextShapeId++;
         }
-        
+
         if( poFeature != NULL )
         {
             OGRGeometry* poGeom = poFeature->GetGeometryRef();
@@ -832,7 +868,7 @@ OGRFeature *OGRShapeLayer::GetFeature( GIntBig nFeatureId )
         }
 
         m_nFeaturesRead++;
-    
+
         return poFeature;
     }
 
@@ -914,7 +950,7 @@ OGRErr OGRShapeLayer::DeleteFeature( GIntBig nFID )
         return OGRERR_FAILURE;
     }
 
-    if( nFID < 0 
+    if( nFID < 0
         || (hSHP != NULL && nFID >= hSHP->nRecords)
         || (hDBF != NULL && nFID >= hDBF->nRecords) )
     {
@@ -923,7 +959,7 @@ OGRErr OGRShapeLayer::DeleteFeature( GIntBig nFID )
 
     if( !hDBF )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Attempt to delete shape in shapefile with no .dbf file.\n"
                   "Deletion is done by marking record deleted in dbf\n"
                   "and is not supported without a .dbf file." );
@@ -977,13 +1013,13 @@ OGRErr OGRShapeLayer::ICreateFeature( OGRFeature *poFeature )
 
     poFeature->SetFID( OGRNullFID );
 
-    if( nTotalShapeCount == 0 
-        && eRequestedGeomType == wkbUnknown 
+    if( nTotalShapeCount == 0
+        && eRequestedGeomType == wkbUnknown
         && poFeature->GetGeometryRef() != NULL )
     {
         OGRGeometry     *poGeom = poFeature->GetGeometryRef();
         int             nShapeType;
-        
+
         switch( poGeom->getGeometryType() )
         {
           case wkbPoint:
@@ -996,6 +1032,16 @@ OGRErr OGRShapeLayer::ICreateFeature( OGRFeature *poFeature )
             eRequestedGeomType = wkbPoint25D;
             break;
 
+          case wkbPointM:
+            nShapeType = SHPT_POINTM;
+            eRequestedGeomType = wkbPointM;
+            break;
+
+          case wkbPointZM:
+            nShapeType = SHPT_POINTZ;
+            eRequestedGeomType = wkbPointZM;
+            break;
+
           case wkbMultiPoint:
             nShapeType = SHPT_MULTIPOINT;
             eRequestedGeomType = wkbMultiPoint;
@@ -1006,6 +1052,16 @@ OGRErr OGRShapeLayer::ICreateFeature( OGRFeature *poFeature )
             eRequestedGeomType = wkbMultiPoint25D;
             break;
 
+          case wkbMultiPointM:
+            nShapeType = SHPT_MULTIPOINTM;
+            eRequestedGeomType = wkbMultiPointM;
+            break;
+
+          case wkbMultiPointZM:
+            nShapeType = SHPT_MULTIPOINTZ;
+            eRequestedGeomType = wkbMultiPointM;
+            break;
+
           case wkbLineString:
           case wkbMultiLineString:
             nShapeType = SHPT_ARC;
@@ -1018,6 +1074,18 @@ OGRErr OGRShapeLayer::ICreateFeature( OGRFeature *poFeature )
             eRequestedGeomType = wkbLineString25D;
             break;
 
+          case wkbLineStringM:
+          case wkbMultiLineStringM:
+            nShapeType = SHPT_ARCM;
+            eRequestedGeomType = wkbLineStringM;
+            break;
+
+          case wkbLineStringZM:
+          case wkbMultiLineStringZM:
+            nShapeType = SHPT_ARCZ;
+            eRequestedGeomType = wkbLineStringZM;
+            break;
+
           case wkbPolygon:
           case wkbMultiPolygon:
             nShapeType = SHPT_POLYGON;
@@ -1030,6 +1098,18 @@ OGRErr OGRShapeLayer::ICreateFeature( OGRFeature *poFeature )
             eRequestedGeomType = wkbPolygon25D;
             break;
 
+          case wkbPolygonM:
+          case wkbMultiPolygonM:
+            nShapeType = SHPT_POLYGONM;
+            eRequestedGeomType = wkbPolygonM;
+            break;
+
+          case wkbPolygonZM:
+          case wkbMultiPolygonZM:
+            nShapeType = SHPT_POLYGONZ;
+            eRequestedGeomType = wkbPolygonZM;
+            break;
+
           default:
             nShapeType = -1;
             break;
@@ -1037,19 +1117,20 @@ OGRErr OGRShapeLayer::ICreateFeature( OGRFeature *poFeature )
 
         if( nShapeType != -1 )
         {
+            poFeatureDefn->SetGeomType(eRequestedGeomType);
             ResetGeomType( nShapeType );
         }
     }
-    
-    eErr = SHPWriteOGRFeature( hSHP, hDBF, poFeatureDefn, poFeature, 
+
+    eErr = SHPWriteOGRFeature( hSHP, hDBF, poFeatureDefn, poFeature,
                                osEncoding, &bTruncationWarningEmitted,
                                bRewindOnWrite );
 
     if( hSHP != NULL )
         nTotalShapeCount = hSHP->nRecords;
-    else 
+    else
         nTotalShapeCount = hDBF->nRecords;
-    
+
     return eErr;
 }
 
@@ -1088,7 +1169,7 @@ int OGRShapeLayer::GetFeatureCountWithSpatialFilterOnly()
     SHPObject sShape;
     memset(&sShape, 0, sizeof(sShape));
 
-    while( TRUE )
+    while( true )
     {
         SHPObject* psShape = NULL;
         int iShape = -1;
@@ -1350,7 +1431,7 @@ OGRErr OGRShapeLayer::GetExtent (OGREnvelope *psExtent, int bForce)
     psExtent->MinY = adMin[1];
     psExtent->MaxX = adMax[0];
     psExtent->MaxY = adMax[1];
-    
+
     if( CPLIsNan(adMin[0]) || CPLIsNan(adMin[1]) ||
         CPLIsNan(adMax[0]) || CPLIsNan(adMax[1]) )
     {
@@ -1363,9 +1444,9 @@ OGRErr OGRShapeLayer::GetExtent (OGREnvelope *psExtent, int bForce)
         m_poAttrQuery = NULL;
         OGRGeometry* poFilterGeom = m_poFilterGeom;
         m_poFilterGeom = NULL;
-        
+
         eErr = OGRLayer::GetExtent(psExtent, bForce);
-        
+
         m_poAttrQuery = poAttrQuery;
         m_poFilterGeom = poFilterGeom;
         return eErr;
@@ -1387,7 +1468,7 @@ int OGRShapeLayer::TestCapability( const char * pszCap )
     if( EQUAL(pszCap,OLCRandomRead) )
         return TRUE;
 
-    else if( EQUAL(pszCap,OLCSequentialWrite) 
+    else if( EQUAL(pszCap,OLCSequentialWrite)
              || EQUAL(pszCap,OLCRandomWrite) )
         return bUpdateAccess;
 
@@ -1467,7 +1548,11 @@ int OGRShapeLayer::TestCapability( const char * pszCap )
 
         return TRUE;
     }
-    else 
+
+    else if( EQUAL(pszCap,OLCMeasuredGeometries) )
+        return TRUE;
+
+    else
         return FALSE;
 }
 
@@ -1482,7 +1567,7 @@ OGRErr OGRShapeLayer::CreateField( OGRFieldDefn *poFieldDefn, int bApproxOK )
         return OGRERR_FAILURE;
 
     CPLAssert( NULL != poFieldDefn );
-    
+
     int         iNewField;
 
     if( !bUpdateAccess )
@@ -1528,7 +1613,7 @@ OGRErr OGRShapeLayer::CreateField( OGRFieldDefn *poFieldDefn, int bApproxOK )
 /* -------------------------------------------------------------------- */
 /*      Normalize field name                                            */
 /* -------------------------------------------------------------------- */
-        
+
     char szNewFieldName[10 + 1];
     char * pszTmp = NULL;
     int nRenameNum = 1;
@@ -1554,7 +1639,7 @@ OGRErr OGRShapeLayer::CreateField( OGRFieldDefn *poFieldDefn, int bApproxOK )
     else
         osFieldName = poFieldDefn->GetNameRef();
 
-    size_t nNameSize = osFieldName.size();
+    int nNameSize = static_cast<int>(osFieldName.size());
     pszTmp = CPLScanString( osFieldName,
                             MIN( nNameSize, 10) , TRUE, TRUE);
     strncpy(szNewFieldName, pszTmp, 10);
@@ -1567,19 +1652,19 @@ OGRErr OGRShapeLayer::CreateField( OGRFieldDefn *poFieldDefn, int bApproxOK )
         CPLError( CE_Failure, CPLE_NotSupported,
                   "Failed to add field named '%s'",
                   poFieldDefn->GetNameRef() );
-                  
+
         CPLFree( pszTmp );
         return OGRERR_FAILURE;
     }
 
     while( DBFGetFieldIndex( hDBF, szNewFieldName ) >= 0 && nRenameNum < 10 )
-        sprintf( szNewFieldName, "%.8s_%.1d", pszTmp, nRenameNum++ );
+        snprintf( szNewFieldName, sizeof(szNewFieldName), "%.8s_%.1d", pszTmp, nRenameNum++ );
     while( DBFGetFieldIndex( hDBF, szNewFieldName ) >= 0 && nRenameNum < 100 )
-        sprintf( szNewFieldName, "%.8s%.2d", pszTmp, nRenameNum++ );
+        snprintf( szNewFieldName, sizeof(szNewFieldName), "%.8s%.2d", pszTmp, nRenameNum++ );
 
     CPLFree( pszTmp );
     pszTmp = NULL;
-    
+
     if( DBFGetFieldIndex( hDBF, szNewFieldName ) >= 0 )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
@@ -1593,7 +1678,7 @@ OGRErr OGRShapeLayer::CreateField( OGRFieldDefn *poFieldDefn, int bApproxOK )
     if( !EQUAL(osFieldName,szNewFieldName) )
     {
         CPLError( CE_Warning, CPLE_NotSupported,
-                  "Normalized/laundered field name: '%s' to '%s'", 
+                  "Normalized/laundered field name: '%s' to '%s'",
                   poFieldDefn->GetNameRef(),
                   szNewFieldName );
 
@@ -1706,7 +1791,7 @@ OGRErr OGRShapeLayer::CreateField( OGRFieldDefn *poFieldDefn, int bApproxOK )
 
         return OGRERR_NONE;
     }
-    else        
+    else
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Can't create field %s in Shape DBF file, reason unknown.",
@@ -1786,7 +1871,7 @@ OGRErr OGRShapeLayer::ReorderFields( int* panMap )
 /*                           AlterFieldDefn()                           */
 /************************************************************************/
 
-OGRErr OGRShapeLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags )
+OGRErr OGRShapeLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlagsIn )
 {
     if (!TouchLayer())
         return OGRERR_FAILURE;
@@ -1818,7 +1903,7 @@ OGRErr OGRShapeLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn,
     /* eDBFType = */ DBFGetFieldInfo( hDBF, iField, szFieldName,
                                       &nWidth, &nPrecision );
 
-    if ((nFlags & ALTER_TYPE_FLAG) &&
+    if ((nFlagsIn & ALTER_TYPE_FLAG) &&
         poNewFieldDefn->GetType() != poFieldDefn->GetType())
     {
         if (poNewFieldDefn->GetType() == OFTInteger64 && poFieldDefn->GetType() == OFTInteger )
@@ -1838,7 +1923,7 @@ OGRErr OGRShapeLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn,
         }
     }
 
-    if (nFlags & ALTER_NAME_FLAG)
+    if (nFlagsIn & ALTER_NAME_FLAG)
     {
         CPLString osFieldName;
         if( osEncoding.size() )
@@ -1864,7 +1949,7 @@ OGRErr OGRShapeLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn,
         strncpy(szFieldName, osFieldName, 10);
         szFieldName[10] = '\0';
     }
-    if (nFlags & ALTER_WIDTH_PRECISION_FLAG)
+    if (nFlagsIn & ALTER_WIDTH_PRECISION_FLAG)
     {
         nWidth = poNewFieldDefn->GetWidth();
         nPrecision = poNewFieldDefn->GetPrecision();
@@ -1873,11 +1958,11 @@ OGRErr OGRShapeLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn,
     if ( DBFAlterFieldDefn( hDBF, iField, szFieldName,
                             chNativeType, nWidth, nPrecision) )
     {
-        if (nFlags & ALTER_TYPE_FLAG)
+        if (nFlagsIn & ALTER_TYPE_FLAG)
             poFieldDefn->SetType(eType);
-        if (nFlags & ALTER_NAME_FLAG)
+        if (nFlagsIn & ALTER_NAME_FLAG)
             poFieldDefn->SetName(poNewFieldDefn->GetNameRef());
-        if (nFlags & ALTER_WIDTH_PRECISION_FLAG)
+        if (nFlagsIn & ALTER_WIDTH_PRECISION_FLAG)
         {
             poFieldDefn->SetWidth(nWidth);
             poFieldDefn->SetPrecision(nPrecision);
@@ -1960,7 +2045,7 @@ int OGRShapeLayer::ResetGeomType( int nNewGeomType )
 
     if( hSHP->fpSHX == NULL)
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   " OGRShapeLayer::ResetGeomType failed : SHX file is closed");
         return FALSE;
     }
@@ -1987,7 +2072,7 @@ int OGRShapeLayer::ResetGeomType( int nNewGeomType )
 /*      Update .shx header.                                             */
 /* -------------------------------------------------------------------- */
     nStartPos = (int)( hSHP->sHooks.FTell( hSHP->fpSHX ) );
-    
+
     if( hSHP->sHooks.FSeek( hSHP->fpSHX, 0, SEEK_SET ) != 0
         || hSHP->sHooks.FRead( abyHeader, 100, 1, hSHP->fpSHX ) != 1 )
         return FALSE;
@@ -2057,7 +2142,7 @@ OGRErr OGRShapeLayer::DropSpatialIndex()
 
     if( !CheckForQIX() && !CheckForSBN() )
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "Layer %s has no spatial index, DROP SPATIAL INDEX failed.",
                   poFeatureDefn->GetName() );
         return OGRERR_FAILURE;
@@ -2102,7 +2187,7 @@ OGRErr OGRShapeLayer::DropSpatialIndex()
             if( VSIUnlink( pszIndexFilename ) != 0 )
             {
                 CPLDebug( "SHAPE",
-                          "Failed to delete file %s.\n%s", 
+                          "Failed to delete file %s.\n%s",
                           pszIndexFilename, VSIStrerror( errno ) );
             }
         }
@@ -2226,7 +2311,7 @@ OGRErr OGRShapeLayer::Repack()
                         return OGRERR_FAILURE;
                     }
                     nDeleteCountAlloc = nDeleteCountAllocNew;
-                    int* panRecordsToDeleteNew = (int*) VSIRealloc(
+                    int* panRecordsToDeleteNew = (int*) VSI_REALLOC_VERBOSE(
                         panRecordsToDelete, nDeleteCountAlloc * sizeof(int) );
                     if( panRecordsToDeleteNew == NULL )
                     {
@@ -2261,9 +2346,9 @@ OGRErr OGRShapeLayer::Repack()
 /* -------------------------------------------------------------------- */
     CPLString osDirname(CPLGetPath(pszFullName));
     CPLString osBasename(CPLGetBasename(pszFullName));
-    
+
     CPLString osDBFName, osSHPName, osSHXName, osCPGName;
-    char **papszCandidates = CPLReadDir( osDirname );
+    char **papszCandidates = VSIReadDir( osDirname );
     int i = 0;
     while(papszCandidates != NULL && papszCandidates[i] != NULL)
     {
@@ -2286,12 +2371,12 @@ OGRErr OGRShapeLayer::Repack()
             else if (EQUAL(osCandidateExtension, "cpg"))
                 osCPGName = CPLFormFilename(osDirname, papszCandidates[i], NULL);
         }
-        
+
         i++;
     }
     CSLDestroy(papszCandidates);
     papszCandidates = NULL;
-    
+
     if( hDBF != NULL && osDBFName.size() == 0)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -2343,8 +2428,8 @@ OGRErr OGRShapeLayer::Repack()
         {
             CPLFree( panRecordsToDelete );
 
-            CPLError( CE_Failure, CPLE_OpenFailed, 
-                    "Failed to create temp file %s.", 
+            CPLError( CE_Failure, CPLE_OpenFailed,
+                    "Failed to create temp file %s.",
                     oTempFile.c_str() );
             return OGRERR_FAILURE;
         }
@@ -2367,8 +2452,8 @@ OGRErr OGRShapeLayer::Repack()
         int iDestShape = 0;
         int iNextDeletedShape = 0;
 
-        for( iShape = 0; 
-            iShape < nTotalShapeCount && eErr == OGRERR_NONE; 
+        for( iShape = 0;
+            iShape < nTotalShapeCount && eErr == OGRERR_NONE;
             iShape++ )
         {
             if( panRecordsToDelete[iNextDeletedShape] == iShape )
@@ -2380,7 +2465,7 @@ OGRErr OGRShapeLayer::Repack()
                     eErr = OGRERR_FAILURE;
                 else if( !DBFWriteTuple( hNewDBF, iDestShape++, pTuple ) )
                     eErr = OGRERR_FAILURE;
-            }                           
+            }
         }
 
         if( eErr != OGRERR_NONE )
@@ -2409,7 +2494,7 @@ OGRErr OGRShapeLayer::Repack()
 
             return OGRERR_FAILURE;
         }
-            
+
         if( VSIRename( oTempFile, osDBFName ) != 0 )
         {
             CPLDebug( "Shape", "Can not rename DBF file: %s", VSIStrerror( errno ) );
@@ -2442,8 +2527,8 @@ OGRErr OGRShapeLayer::Repack()
 /* -------------------------------------------------------------------- */
         int iNextDeletedShape = 0;
 
-        for( iShape = 0; 
-             iShape < nTotalShapeCount && eErr == OGRERR_NONE; 
+        for( iShape = 0;
+             iShape < nTotalShapeCount && eErr == OGRERR_NONE;
              iShape++ )
         {
             if( panRecordsToDelete[iNextDeletedShape] == iShape )
@@ -2485,38 +2570,40 @@ OGRErr OGRShapeLayer::Repack()
         oTempFile = CPLResetExtension( oTempFile, "shp" );
         if( VSIRename( oTempFile, osSHPName ) != 0 )
         {
-            CPLDebug( "Shape", "Can not rename SHP file: %s", VSIStrerror( errno ) );
+            CPLDebug( "Shape", "Can not rename SHP file: %s",
+                      VSIStrerror( errno ) );
             CPLFree( panRecordsToDelete );
             return OGRERR_FAILURE;
         }
-    
+
         oTempFile = CPLResetExtension( oTempFile, "shx" );
         if( VSIRename( oTempFile, osSHXName ) != 0 )
         {
-            CPLDebug( "Shape", "Can not rename SHX file: %s", VSIStrerror( errno ) );
+            CPLDebug( "Shape", "Can not rename SHX file: %s",
+                      VSIStrerror( errno ) );
             CPLFree( panRecordsToDelete );
             return OGRERR_FAILURE;
         }
     }
-    
+
     CPLFree( panRecordsToDelete );
     panRecordsToDelete = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Reopen the shapefile                                            */
 /*                                                                      */
-/* We do not need to reimplement OGRShapeDataSource::OpenFile() here    */  
+/* We do not need to reimplement OGRShapeDataSource::OpenFile() here    */
 /* with the fully featured error checking.                              */
-/* If all operations above succeeded, then all necessery files are      */
+/* If all operations above succeeded, then all necessary files are      */
 /* in the right place and accessible.                                   */
 /* -------------------------------------------------------------------- */
-    
+
     const char* pszAccess = NULL;
     if( bUpdateAccess )
         pszAccess = "r+";
     else
         pszAccess = "r";
-    
+
     if( bMustReopenSHP )
         hSHP = poDS->DS_SHPOpen ( osSHPName , pszAccess );
     if( bMustReopenDBF )
@@ -2602,7 +2689,7 @@ OGRErr OGRShapeLayer::ResizeDBF()
                     continue;
 
                 const char* pszVal = DBFReadStringAttribute(hDBF, i, panColMap[j]);
-                int nLen = strlen(pszVal);
+                int nLen =  static_cast<int>(strlen(pszVal));
                 if (nLen > panBestWidth[j])
                     panBestWidth[j] = nLen;
             }
@@ -2702,21 +2789,21 @@ OGRErr OGRShapeLayer::RecomputeExtent()
                   "RecomputeExtent");
         return OGRERR_FAILURE;
     }
-    
+
     if( hSHP == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "The RECOMPUTE EXTENT operation is not permitted on a layer without .SHP file." );
         return OGRERR_FAILURE;
     }
-    
+
     double adBoundsMin[4] = { 0.0, 0.0, 0.0, 0.0 };
     double adBoundsMax[4] = { 0.0, 0.0, 0.0, 0.0 };
 
     int bHasBeenInit = FALSE;
 
-    for( int iShape = 0; 
-         iShape < nTotalShapeCount; 
+    for( int iShape = 0;
+         iShape < nTotalShapeCount;
          iShape++ )
     {
         if( hDBF == NULL || !DBFIsRecordDeleted( hDBF, iShape ) )
@@ -2767,7 +2854,7 @@ OGRErr OGRShapeLayer::RecomputeExtent()
         memcpy(hSHP->adBoundsMin, adBoundsMin, 4*sizeof(double));
         memcpy(hSHP->adBoundsMax, adBoundsMax, 4*sizeof(double));
     }
-    
+
     return OGRERR_NONE;
 }
 
@@ -2850,7 +2937,7 @@ void OGRShapeLayer::CloseUnderlyingLayer()
     /* We close QIX and reset the check flag, so that CheckForQIX() */
     /* will retry opening it if necessary when the layer is active again */
     if( hQIX != NULL )
-        SHPCloseDiskTree( hQIX ); 
+        SHPCloseDiskTree( hQIX );
     hQIX = NULL;
     bCheckedForQIX = FALSE;
 
diff --git a/ogr/ogrsf_frmts/shape/sbnsearch.c b/ogr/ogrsf_frmts/shape/sbnsearch.c
index 727f9a8..8ad4317 100644
--- a/ogr/ogrsf_frmts/shape/sbnsearch.c
+++ b/ogr/ogrsf_frmts/shape/sbnsearch.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sbnsearch.c 28039 2014-11-30 18:24:59Z rouault $
+ * $Id: sbnsearch.c 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Shapelib
  * Purpose:  Implementation of search in ESRI SBN spatial index.
@@ -40,7 +40,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-SHP_CVSID("$Id: sbnsearch.c 28039 2014-11-30 18:24:59Z rouault $")
+SHP_CVSID("$Id: sbnsearch.c 33713 2016-03-12 17:41:57Z goatbar $")
 
 #ifndef TRUE
 #  define TRUE 1
@@ -230,12 +230,13 @@ SBNSearchHandle SBNOpenDiskTree( const char* pszSBNFilename,
     if (nShapeCount < 0 || nShapeCount > 256000000 )
     {
         char szErrorMsg[64];
-        sprintf(szErrorMsg, "Invalid shape count in .sbn : %d", nShapeCount );
+        snprintf(szErrorMsg, sizeof(szErrorMsg),
+                "Invalid shape count in .sbn : %d", nShapeCount );
         hSBN->sHooks.Error( szErrorMsg );
         SBNCloseDiskTree(hSBN);
         return NULL;
     }
-    
+
     /* Empty spatial index */
     if( nShapeCount == 0 )
     {
@@ -279,13 +280,14 @@ SBNSearchHandle SBNOpenDiskTree( const char* pszSBNFilename,
         nNodeDescCount < 0 || nNodeDescCount > nMaxNodes )
     {
         char szErrorMsg[64];
-        sprintf(szErrorMsg,
+        snprintf(szErrorMsg, sizeof(szErrorMsg),
                 "Invalid node descriptor size in .sbn : %d", nNodeDescSize );
         hSBN->sHooks.Error( szErrorMsg );
         SBNCloseDiskTree(hSBN);
         return NULL;
     }
 
+    /* coverity[tainted_data] */
     pabyData = (uchar*) malloc( nNodeDescSize );
     pasNodeDescriptor = (SBNNodeDescriptor*)
                 calloc ( nMaxNodes, sizeof(SBNNodeDescriptor) );
@@ -350,7 +352,7 @@ SBNSearchHandle SBNOpenDiskTree( const char* pszSBNFilename,
     }
 
     pasNodeDescriptor[nCurNode].nBinOffset =
-        hSBN->sHooks.FTell(hSBN->fpSBN);
+        (int) hSBN->sHooks.FTell(hSBN->fpSBN);
 
     /* Compute the index of the next non empty node. */
     nNextNonEmptyNode = nCurNode + 1;
@@ -398,7 +400,7 @@ SBNSearchHandle SBNOpenDiskTree( const char* pszSBNFilename,
         {
             nCurNode = nNextNonEmptyNode;
             pasNodeDescriptor[nCurNode].nBinOffset =
-                hSBN->sHooks.FTell(hSBN->fpSBN) - 8;
+                (int) hSBN->sHooks.FTell(hSBN->fpSBN) - 8;
 
             /* Compute the index of the next non empty node. */
             nNextNonEmptyNode = nCurNode + 1;
@@ -720,7 +722,7 @@ static int SBNSearchDiskInternal( SearchStruct* psSearch,
                     nShapeId = READ_MSB_INT(pabyBinShape + 4);
 
                     /* Caution : we count shape id starting from 0, and not 1 */
-                    nShapeId --; 
+                    nShapeId --;
 
                     /*printf("shape=%d, minx=%d, miny=%d, maxx=%d, maxy=%d\n",
                         nShapeId, bMinX, bMinY, bMaxX, bMaxY);*/
@@ -931,7 +933,7 @@ int* SBNSearchDiskTreeInteger( SBNSearchHandle hSBN,
     sSearch.bMaxY = (coord) (bMaxY <= 255 ? bMaxY : 255);
     sSearch.nShapeCount = 0;
     sSearch.nShapeAlloc = 0;
-    sSearch.panShapeId = NULL;
+    sSearch.panShapeId = (int*) calloc(1, sizeof(int));
 #ifdef DEBUG_IO
     sSearch.nBytesRead = 0;
 #endif
@@ -945,8 +947,7 @@ int* SBNSearchDiskTreeInteger( SBNSearchHandle hSBN,
 
     if( !bRet )
     {
-        if( sSearch.panShapeId != NULL )
-            free( sSearch.panShapeId );
+        free( sSearch.panShapeId );
         *pnShapeCount = 0;
         return NULL;
     }
@@ -958,10 +959,6 @@ int* SBNSearchDiskTreeInteger( SBNSearchHandle hSBN,
 /* -------------------------------------------------------------------- */
     qsort(sSearch.panShapeId, *pnShapeCount, sizeof(int), compare_ints);
 
-    /* To distinguish between empty intersection from error case */
-    if( sSearch.panShapeId == NULL )
-        sSearch.panShapeId = (int*) calloc(1, sizeof(int));
-
     return sSearch.panShapeId;
 }
 
diff --git a/ogr/ogrsf_frmts/shape/shape2ogr.cpp b/ogr/ogrsf_frmts/shape/shape2ogr.cpp
index 84e750f..29b4b38 100644
--- a/ogr/ogrsf_frmts/shape/shape2ogr.cpp
+++ b/ogr/ogrsf_frmts/shape/shape2ogr.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: shape2ogr.cpp 33049 2016-01-19 15:52:01Z rouault $
+ * $Id: shape2ogr.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements translation of Shapefile shapes into OGR
@@ -31,8 +31,9 @@
 
 #include "ogrshape.h"
 #include "cpl_conv.h"
+#include <limits>
 
-CPL_CVSID("$Id: shape2ogr.cpp 33049 2016-01-19 15:52:01Z rouault $");
+CPL_CVSID("$Id: shape2ogr.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                        RingStartEnd                                  */
@@ -55,12 +56,12 @@ static void RingStartEnd ( SHPObject *psShape, int ring, int *start, int *end )
         *start = psShape->panPartStart[ring];
     }
 }
-    
+
 /************************************************************************/
 /*                        CreateLinearRing                              */
 /*                                                                      */
 /************************************************************************/
-static OGRLinearRing * CreateLinearRing ( SHPObject *psShape, int ring, int bHasZ )
+static OGRLinearRing * CreateLinearRing ( SHPObject *psShape, int ring, int bHasZ, int bHasM )
 {
     OGRLinearRing *poRing;
     int nRingStart, nRingEnd, nRingPoints;
@@ -68,16 +69,23 @@ static OGRLinearRing * CreateLinearRing ( SHPObject *psShape, int ring, int bHas
     poRing = new OGRLinearRing();
 
     RingStartEnd ( psShape, ring, &nRingStart, &nRingEnd );
-
-    nRingPoints = nRingEnd - nRingStart + 1;
-
-    if (bHasZ)
-        poRing->setPoints( nRingPoints, psShape->padfX + nRingStart, 
-                           psShape->padfY + nRingStart,
-                           psShape->padfZ + nRingStart );
-    else
-        poRing->setPoints( nRingPoints, psShape->padfX + nRingStart,
-                           psShape->padfY + nRingStart );
+    if( nRingEnd >= nRingStart )
+    {
+        nRingPoints = nRingEnd - nRingStart + 1;
+
+        if (bHasZ && bHasM)
+            poRing->setPoints( nRingPoints, psShape->padfX + nRingStart,
+                            psShape->padfY + nRingStart,
+                            psShape->padfZ + nRingStart,
+                               psShape->padfM ? psShape->padfM + nRingStart : NULL );
+        else if (bHasM)
+            poRing->setPointsM( nRingPoints, psShape->padfX + nRingStart,
+                            psShape->padfY + nRingStart,
+                                psShape->padfM ? psShape->padfM + nRingStart :NULL );
+        else
+            poRing->setPoints( nRingPoints, psShape->padfX + nRingStart,
+                            psShape->padfY + nRingStart );
+    }
 
     return ( poRing );
 }
@@ -113,15 +121,22 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
     }
     else if(psShape->nSHPType == SHPT_POINTZ )
     {
-        poOGR = new OGRPoint( psShape->padfX[0], psShape->padfY[0],
-                              psShape->padfZ[0] );
+        if( psShape->bMeasureIsUsed )
+        {
+            poOGR = new OGRPoint( psShape->padfX[0], psShape->padfY[0],
+                                  psShape->padfZ[0], psShape->padfM[0] );
+        }
+        else
+        {
+            poOGR = new OGRPoint( psShape->padfX[0], psShape->padfY[0],
+                                  psShape->padfZ[0] );
+        }
     }
     else if(psShape->nSHPType == SHPT_POINTM )
     {
-        /* padfM will be always not NULL in the case */
-        // Read XYM as XYZ
         poOGR = new OGRPoint( psShape->padfX[0], psShape->padfY[0],
-                            psShape->padfM[0] );
+                              0.0, psShape->padfM[0] );
+        poOGR->set3D(FALSE);
     }
 /* -------------------------------------------------------------------- */
 /*      Multipoint.                                                     */
@@ -144,8 +159,24 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
                 OGRPoint    *poPoint;
 
                 if( psShape->nSHPType == SHPT_MULTIPOINTZ )
+                {
+                    if( psShape->padfM )
+                    {
+                        poPoint = new OGRPoint( psShape->padfX[i], psShape->padfY[i],
+                                                psShape->padfZ[i], psShape->padfM[i] );
+                    }
+                    else
+                    {
+                        poPoint = new OGRPoint( psShape->padfX[i], psShape->padfY[i],
+                                                psShape->padfZ[i] );
+                    }
+                }
+                else if( psShape->nSHPType == SHPT_MULTIPOINTM )
+                {
                     poPoint = new OGRPoint( psShape->padfX[i], psShape->padfY[i],
-                                            psShape->padfZ[i] );
+                                            0.0, psShape->padfM[i] );
+                    poPoint->set3D(FALSE);
+                }
                 else
                     poPoint = new OGRPoint( psShape->padfX[i], psShape->padfY[i] );
 
@@ -177,14 +208,13 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
 
             if( psShape->nSHPType == SHPT_ARCZ )
                 poOGRLine->setPoints( psShape->nVertices,
-                                    psShape->padfX, psShape->padfY, psShape->padfZ );
-            else if( psShape->nSHPType == SHPT_ARCM && psShape->padfM != NULL )
-                // Read XYM as XYZ
-                poOGRLine->setPoints( psShape->nVertices,
-                                    psShape->padfX, psShape->padfY, psShape->padfM );
+                                      psShape->padfX, psShape->padfY, psShape->padfZ, psShape->padfM );
+            else if( psShape->nSHPType == SHPT_ARCM )
+                poOGRLine->setPointsM( psShape->nVertices,
+                                       psShape->padfX, psShape->padfY, psShape->padfM );
             else
                 poOGRLine->setPoints( psShape->nVertices,
-                                    psShape->padfX, psShape->padfY );
+                                      psShape->padfX, psShape->padfY );
 
             poOGR = poOGRLine;
         }
@@ -192,9 +222,9 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
         {
             int iRing;
             OGRMultiLineString *poOGRMulti;
-        
+
             poOGR = poOGRMulti = new OGRMultiLineString();
-            
+
             for( iRing = 0; iRing < psShape->nParts; iRing++ )
             {
                 OGRLineString   *poLine;
@@ -224,10 +254,10 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
                     poLine->setPoints( nRingPoints,
                                     psShape->padfX + nRingStart,
                                     psShape->padfY + nRingStart,
-                                    psShape->padfZ + nRingStart );
+                                    psShape->padfZ + nRingStart,
+                                    psShape->padfM ? psShape->padfM + nRingStart : NULL );
                 else if( psShape->nSHPType == SHPT_ARCM && psShape->padfM != NULL )
-                    // Read XYM as XYZ
-                    poLine->setPoints( nRingPoints,
+                    poLine->setPointsM( nRingPoints,
                                     psShape->padfX + nRingStart,
                                     psShape->padfY + nRingStart,
                                     psShape->padfM + nRingStart );
@@ -252,7 +282,8 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
     {
         int iRing;
         int bHasZ = ( psShape->nSHPType == SHPT_POLYGONZ );
-        
+        int bHasM = ( bHasZ || (psShape->nSHPType == SHPT_POLYGONM) );
+
         //CPLDebug( "Shape", "Shape type: polygon with nParts=%d \n", psShape->nParts );
 
         if ( psShape->nParts == 0 )
@@ -266,7 +297,7 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
             OGRLinearRing *poRing = NULL;
 
             poOGR = poOGRPoly = new OGRPolygon();
-            poRing = CreateLinearRing ( psShape, 0, bHasZ );
+            poRing = CreateLinearRing ( psShape, 0, bHasZ, bHasM );
             poOGRPoly->addRingDirectly( poRing );
         }
 
@@ -276,17 +307,17 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
             for( iRing = 0; iRing < psShape->nParts; iRing++ )
             {
                 tabPolygons[iRing] = new OGRPolygon();
-                tabPolygons[iRing]->addRingDirectly(CreateLinearRing ( psShape, iRing, bHasZ ));
+                tabPolygons[iRing]->addRingDirectly(CreateLinearRing ( psShape, iRing, bHasZ, bHasM ));
             }
 
             int isValidGeometry;
             const char* papszOptions[] = { "METHOD=ONLY_CCW", NULL };
-            poOGR = OGRGeometryFactory::organizePolygons( 
+            poOGR = OGRGeometryFactory::organizePolygons(
                 (OGRGeometry**)tabPolygons, psShape->nParts, &isValidGeometry, papszOptions );
 
             if (!isValidGeometry)
             {
-                CPLError(CE_Warning, CPLE_AppDefined, 
+                CPLError(CE_Warning, CPLE_AppDefined,
                         "Geometry of polygon of fid %d cannot be translated to Simple Geometry. "
                         "All polygons will be contained in a multipolygon.\n",
                         iShape);
@@ -317,7 +348,7 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
             }
             else
             {
-                
+
                 if( iPart == psShape->nParts - 1 )
                     nPartPoints =
                         psShape->nVertices - psShape->panPartStart[iPart];
@@ -343,24 +374,24 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
                     OGRLinearRing *poRing = new OGRLinearRing();
                     int iSrcVert = iBaseVert + nPartStart;
 
-                    poRing->setPoint( 0, 
-                                      psShape->padfX[iSrcVert], 
-                                      psShape->padfY[iSrcVert], 
+                    poRing->setPoint( 0,
+                                      psShape->padfX[iSrcVert],
+                                      psShape->padfY[iSrcVert],
                                       psShape->padfZ[iSrcVert] );
-                    poRing->setPoint( 1, 
-                                      psShape->padfX[iSrcVert+1], 
-                                      psShape->padfY[iSrcVert+1], 
+                    poRing->setPoint( 1,
+                                      psShape->padfX[iSrcVert+1],
+                                      psShape->padfY[iSrcVert+1],
                                       psShape->padfZ[iSrcVert+1] );
 
-                    poRing->setPoint( 2, 
-                                      psShape->padfX[iSrcVert+2], 
-                                      psShape->padfY[iSrcVert+2], 
+                    poRing->setPoint( 2,
+                                      psShape->padfX[iSrcVert+2],
+                                      psShape->padfY[iSrcVert+2],
                                       psShape->padfZ[iSrcVert+2] );
-                    poRing->setPoint( 3, 
-                                      psShape->padfX[iSrcVert], 
-                                      psShape->padfY[iSrcVert], 
+                    poRing->setPoint( 3,
+                                      psShape->padfX[iSrcVert],
+                                      psShape->padfY[iSrcVert],
                                       psShape->padfZ[iSrcVert] );
-                        
+
                     poPoly->addRingDirectly( poRing );
                     poMP->addGeometryDirectly( poPoly );
                 }
@@ -381,24 +412,24 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
                     OGRLinearRing *poRing = new OGRLinearRing();
                     int iSrcVert = iBaseVert + nPartStart;
 
-                    poRing->setPoint( 0, 
-                                      psShape->padfX[nPartStart], 
+                    poRing->setPoint( 0,
+                                      psShape->padfX[nPartStart],
                                       psShape->padfY[nPartStart],
                                       psShape->padfZ[nPartStart] );
-                    poRing->setPoint( 1, 
-                                      psShape->padfX[iSrcVert+1], 
-                                      psShape->padfY[iSrcVert+1], 
+                    poRing->setPoint( 1,
+                                      psShape->padfX[iSrcVert+1],
+                                      psShape->padfY[iSrcVert+1],
                                       psShape->padfZ[iSrcVert+1] );
 
-                    poRing->setPoint( 2, 
-                                      psShape->padfX[iSrcVert+2], 
-                                      psShape->padfY[iSrcVert+2], 
+                    poRing->setPoint( 2,
+                                      psShape->padfX[iSrcVert+2],
+                                      psShape->padfY[iSrcVert+2],
                                       psShape->padfZ[iSrcVert+2] );
-                    poRing->setPoint( 3, 
-                                      psShape->padfX[nPartStart], 
-                                      psShape->padfY[nPartStart], 
+                    poRing->setPoint( 3,
+                                      psShape->padfX[nPartStart],
+                                      psShape->padfY[nPartStart],
                                       psShape->padfZ[nPartStart] );
-                        
+
                     poPoly->addRingDirectly( poRing );
                     poMP->addGeometryDirectly( poPoly );
                 }
@@ -408,7 +439,7 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
                      || psShape->panPartType[iPart] == SHPP_FIRSTRING
                      || psShape->panPartType[iPart] == SHPP_RING )
             {
-                if( poLastPoly != NULL 
+                if( poLastPoly != NULL
                     && (psShape->panPartType[iPart] == SHPP_OUTERRING
                         || psShape->panPartType[iPart] == SHPP_FIRSTRING) )
                 {
@@ -419,11 +450,11 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
                 if( poLastPoly == NULL )
                     poLastPoly = new OGRPolygon();
 
-                poLastPoly->addRingDirectly( 
-                    CreateLinearRing( psShape, iPart, TRUE ) );
+                poLastPoly->addRingDirectly(
+                    CreateLinearRing( psShape, iPart, TRUE, TRUE ) );
             }
             else
-                CPLDebug( "OGR", "Unrecognised parttype %d, ignored.", 
+                CPLDebug( "OGR", "Unrecognized parttype %d, ignored.",
                           psShape->panPartType[iPart] );
         }
 
@@ -448,7 +479,7 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
 
         /* nothing returned */
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Cleanup shape, and set feature id.                              */
 /* -------------------------------------------------------------------- */
@@ -460,9 +491,9 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
 /************************************************************************/
 /*                         SHPWriteOGRObject()                          */
 /************************************************************************/
-
+static
 OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
-                          int bRewind)
+                          int bRewind, OGRwkbGeometryType eLayerGeomType )
 
 {
     int nReturnedShapeID;
@@ -473,7 +504,7 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
     {
         SHPObject       *psShape;
 
-        psShape = SHPCreateSimpleObject( SHPT_NULL, 0, NULL, NULL, NULL );
+        psShape = SHPCreateObject( SHPT_NULL, -1, 0, NULL, NULL, 0, NULL, NULL, NULL, NULL );
         nReturnedShapeID = SHPWriteObject( hSHP, iShape, psShape );
         SHPDestroyObject( psShape );
         if( nReturnedShapeID == -1 )
@@ -491,11 +522,10 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
              || hSHP->nShapeType == SHPT_POINTZ )
     {
         SHPObject       *psShape;
-        OGRPoint        *poPoint = (OGRPoint *) poGeom;
-        double          dfX, dfY, dfZ = 0;
+        double          dfX, dfY, dfZ, dfM;
+        double          *pdfM;
 
-        if( poGeom->getGeometryType() != wkbPoint
-            && poGeom->getGeometryType() != wkbPoint25D )        
+        if( wkbFlatten(poGeom->getGeometryType()) != wkbPoint )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Attempt to write non-point (%s) geometry to"
@@ -505,12 +535,23 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
             return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
         }
 
+        OGRPoint        *poPoint = (OGRPoint *) poGeom;
         dfX = poPoint->getX();
         dfY = poPoint->getY();
         dfZ = poPoint->getZ();
-        
-        psShape = SHPCreateSimpleObject( hSHP->nShapeType, 1,
-                                         &dfX, &dfY, &dfZ );
+        if( wkbHasM(eLayerGeomType) && (hSHP->nShapeType == SHPT_POINTM || hSHP->nShapeType == SHPT_POINTZ) )
+        {
+            if( poGeom->IsMeasured() )
+                dfM = poPoint->getM();
+            else
+                dfM = -std::numeric_limits<double>::max();
+            pdfM = &dfM;
+        }
+        else
+            pdfM = NULL;
+
+        psShape = SHPCreateObject( hSHP->nShapeType, -1, 0, NULL, NULL, 1,
+                                   &dfX, &dfY, &dfZ, pdfM );
         nReturnedShapeID = SHPWriteObject( hSHP, iShape, psShape );
         SHPDestroyObject( psShape );
         if( nReturnedShapeID == -1 )
@@ -523,8 +564,7 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
              || hSHP->nShapeType == SHPT_MULTIPOINTM
              || hSHP->nShapeType == SHPT_MULTIPOINTZ )
     {
-        OGRMultiPoint   *poMP = (OGRMultiPoint *) poGeom;
-        double          *padfX, *padfY, *padfZ;
+        double          *padfX, *padfY, *padfZ, *padfM;
         int             iPoint;
         SHPObject       *psShape;
 
@@ -538,9 +578,14 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
             return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
         }
 
+        OGRMultiPoint   *poMP = (OGRMultiPoint *) poGeom;
         padfX = (double *) CPLMalloc(sizeof(double)*poMP->getNumGeometries());
         padfY = (double *) CPLMalloc(sizeof(double)*poMP->getNumGeometries());
         padfZ = (double *) CPLCalloc(sizeof(double),poMP->getNumGeometries());
+        if( wkbHasM(eLayerGeomType) && (hSHP->nShapeType == SHPT_MULTIPOINTM || hSHP->nShapeType == SHPT_MULTIPOINTZ) )
+            padfM = (double *) CPLCalloc(sizeof(double),poMP->getNumGeometries());
+        else
+            padfM = NULL;
 
         int iDstPoints = 0;
         for( iPoint = 0; iPoint < poMP->getNumGeometries(); iPoint++ )
@@ -553,22 +598,30 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
                 padfX[iDstPoints] = poPoint->getX();
                 padfY[iDstPoints] = poPoint->getY();
                 padfZ[iDstPoints] = poPoint->getZ();
+                if( padfM )
+                {
+                    if( poGeom->IsMeasured() )
+                        padfM[iDstPoints] = poPoint->getM();
+                    else
+                        padfM[iDstPoints] = -std::numeric_limits<double>::max();
+                }
                 iDstPoints ++;
             }
             else
-                CPLDebug( "OGR", 
+                CPLDebug( "OGR",
                               "Ignore POINT EMPTY inside MULTIPOINT in shapefile writer." );
         }
 
-        psShape = SHPCreateSimpleObject( hSHP->nShapeType,
-                                         iDstPoints,
-                                         padfX, padfY, padfZ );
+        psShape = SHPCreateObject( hSHP->nShapeType, -1, 0, NULL, NULL,
+                                   iDstPoints,
+                                   padfX, padfY, padfZ, padfM );
         nReturnedShapeID = SHPWriteObject( hSHP, iShape, psShape );
         SHPDestroyObject( psShape );
-        
+
         CPLFree( padfX );
         CPLFree( padfY );
         CPLFree( padfZ );
+        CPLFree( padfM );
         if( nReturnedShapeID == -1 )
             return OGRERR_FAILURE;
     }
@@ -582,30 +635,42 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
              && wkbFlatten(poGeom->getGeometryType()) == wkbLineString )
     {
         OGRLineString   *poArc = (OGRLineString *) poGeom;
-        double          *padfX, *padfY, *padfZ;
+        double          *padfX, *padfY, *padfZ, *padfM;
         int             iPoint;
         SHPObject       *psShape;
 
         padfX = (double *) CPLMalloc(sizeof(double)*poArc->getNumPoints());
         padfY = (double *) CPLMalloc(sizeof(double)*poArc->getNumPoints());
         padfZ = (double *) CPLCalloc(sizeof(double),poArc->getNumPoints());
+        if( wkbHasM(eLayerGeomType) && (hSHP->nShapeType == SHPT_ARCM || hSHP->nShapeType == SHPT_ARCZ) )
+            padfM = (double *) CPLCalloc(sizeof(double),poArc->getNumPoints());
+        else
+            padfM = NULL;
 
         for( iPoint = 0; iPoint < poArc->getNumPoints(); iPoint++ )
         {
             padfX[iPoint] = poArc->getX( iPoint );
             padfY[iPoint] = poArc->getY( iPoint );
             padfZ[iPoint] = poArc->getZ( iPoint );
+            if( padfM )
+            {
+                if( poGeom->IsMeasured() )
+                    padfM[iPoint] = poArc->getM( iPoint );
+                else
+                    padfM[iPoint] = -std::numeric_limits<double>::max();
+            }
         }
 
-        psShape = SHPCreateSimpleObject( hSHP->nShapeType,
-                                         poArc->getNumPoints(),
-                                         padfX, padfY, padfZ );
+        psShape = SHPCreateObject( hSHP->nShapeType, -1, 0, NULL, NULL,
+                                   poArc->getNumPoints(),
+                                   padfX, padfY, padfZ, padfM );
         nReturnedShapeID = SHPWriteObject( hSHP, iShape, psShape );
         SHPDestroyObject( psShape );
-        
+
         CPLFree( padfX );
         CPLFree( padfY );
         CPLFree( padfZ );
+        CPLFree( padfM );
         if( nReturnedShapeID == -1 )
             return OGRERR_FAILURE;
     }
@@ -616,19 +681,21 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
              || hSHP->nShapeType == SHPT_ARCM
              || hSHP->nShapeType == SHPT_ARCZ )
     {
-        OGRMultiLineString *poML;
-        double          *padfX=NULL, *padfY=NULL, *padfZ=NULL;
+        OGRGeometry     *poForcedGeom;
+        double          *padfX=NULL, *padfY=NULL, *padfZ=NULL, *padfM=NULL;
         int             iGeom, iPoint, nPointCount = 0;
         SHPObject       *psShape;
         int             *panRingStart;
         int             nParts = 0;
+        const bool       bSupportMeasures =
+            wkbHasM(eLayerGeomType) && (hSHP->nShapeType == SHPT_ARCM ||
+                                            hSHP->nShapeType == SHPT_ARCZ);
 
-        poML = (OGRMultiLineString *) 
-            OGRGeometryFactory::forceToMultiLineString( poGeom->clone() );
+        poForcedGeom = OGRGeometryFactory::forceToMultiLineString( poGeom->clone() );
 
-        if( wkbFlatten(poML->getGeometryType()) != wkbMultiLineString )
+        if( wkbFlatten(poForcedGeom->getGeometryType()) != wkbMultiLineString )
         {
-            delete poML;
+            delete poForcedGeom;
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Attempt to write non-linestring (%s) geometry to "
                       "ARC type shapefile.",
@@ -636,8 +703,9 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
 
             return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
         }
+        OGRMultiLineString *poML = (OGRMultiLineString *)poForcedGeom;
 
-        panRingStart = (int *) 
+        panRingStart = (int *)
             CPLMalloc(sizeof(int) * poML->getNumGeometries());
 
         for( iGeom = 0; iGeom < poML->getNumGeometries(); iGeom++ )
@@ -649,35 +717,43 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
             /* Ignore LINESTRING EMPTY */
             if (nNewPoints == 0)
             {
-                CPLDebug( "OGR", 
+                CPLDebug( "OGR",
                           "Ignore LINESTRING EMPTY inside MULTILINESTRING in shapefile writer." );
                 continue;
             }
 
             panRingStart[nParts ++] = nPointCount;
 
-            padfX = (double *) 
+            padfX = (double *)
                 CPLRealloc( padfX, sizeof(double)*(nNewPoints+nPointCount) );
-            padfY = (double *) 
+            padfY = (double *)
                 CPLRealloc( padfY, sizeof(double)*(nNewPoints+nPointCount) );
-            padfZ = (double *) 
+            padfZ = (double *)
                 CPLRealloc( padfZ, sizeof(double)*(nNewPoints+nPointCount) );
+            if( bSupportMeasures )
+            {
+                padfM = (double *)
+                    CPLRealloc( padfM, sizeof(double)*(nNewPoints+nPointCount) );
+            }
 
             for( iPoint = 0; iPoint < nNewPoints; iPoint++ )
             {
                 padfX[nPointCount] = poArc->getX( iPoint );
                 padfY[nPointCount] = poArc->getY( iPoint );
                 padfZ[nPointCount] = poArc->getZ( iPoint );
+                if( bSupportMeasures )
+                    padfM[nPointCount] = poGeom->IsMeasured() ?
+                        poArc->getM( iPoint ) : -std::numeric_limits<double>::max();
                 nPointCount++;
             }
         }
 
         CPLAssert(nParts != 0);
 
-        psShape = SHPCreateObject( hSHP->nShapeType, iShape, 
-                                    nParts, 
+        psShape = SHPCreateObject( hSHP->nShapeType, iShape,
+                                    nParts,
                                     panRingStart, NULL,
-                                    nPointCount, padfX, padfY, padfZ, NULL);
+                                    nPointCount, padfX, padfY, padfZ, padfM);
         nReturnedShapeID = SHPWriteObject( hSHP, iShape, psShape );
         SHPDestroyObject( psShape );
 
@@ -685,6 +761,7 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
         CPLFree( padfX );
         CPLFree( padfY );
         CPLFree( padfZ );
+        CPLFree( padfM );
 
         delete poML;
         if( nReturnedShapeID == -1 )
@@ -698,22 +775,20 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
              || hSHP->nShapeType == SHPT_POLYGONM
              || hSHP->nShapeType == SHPT_POLYGONZ )
     {
-        OGRPolygon      *poPoly;
         OGRLinearRing   *poRing, **papoRings=NULL;
-        double          *padfX=NULL, *padfY=NULL, *padfZ=NULL;
+        double          *padfX=NULL, *padfY=NULL, *padfZ=NULL, *padfM=NULL;
         int             iPoint, iRing, nRings, nVertex=0, *panRingStart;
-        SHPObject       *psShape;
 
         /* Collect list of rings */
 
         if( wkbFlatten(poGeom->getGeometryType()) == wkbPolygon )
         {
-            poPoly =  (OGRPolygon *) poGeom;
+            OGRPolygon* poPoly =  (OGRPolygon *) poGeom;
 
             if( poPoly->getExteriorRing() == NULL ||
                 poPoly->getExteriorRing()->IsEmpty() )
             {
-                CPLDebug( "OGR", 
+                CPLDebug( "OGR",
                           "Ignore POLYGON EMPTY in shapefile writer." );
                 nRings = 0;
             }
@@ -733,13 +808,13 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
                     if (papoRings[nRings]->getNumPoints() != 0)
                         nRings ++;
                     else
-                        CPLDebug( "OGR", 
+                        CPLDebug( "OGR",
                                 "Ignore LINEARRING EMPTY inside POLYGON in shapefile writer." );
                 }
             }
         }
         else if( wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon
-                 || wkbFlatten(poGeom->getGeometryType()) 
+                 || wkbFlatten(poGeom->getGeometryType())
                                                 == wkbGeometryCollection )
         {
             OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeom;
@@ -748,50 +823,51 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
             nRings = 0;
             for( iGeom=0; iGeom < poGC->getNumGeometries(); iGeom++ )
             {
-                poPoly =  (OGRPolygon *) poGC->getGeometryRef( iGeom );
+                OGRGeometry* poSubGeom = poGC->getGeometryRef( iGeom );
 
-                if( wkbFlatten(poPoly->getGeometryType()) != wkbPolygon )
+                if( wkbFlatten(poSubGeom->getGeometryType()) != wkbPolygon )
                 {
                     CPLFree( papoRings );
                     CPLError( CE_Failure, CPLE_AppDefined,
                               "Attempt to write non-polygon (%s) geometry to "
                               "POLYGON type shapefile.",
-                              poGeom->getGeometryName());
+                              poSubGeom->getGeometryName());
 
                     return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
                 }
+                OGRPolygon* poPoly =  (OGRPolygon *) poSubGeom;
 
                 /* Ignore POLYGON EMPTY */
                 if( poPoly->getExteriorRing() == NULL ||
                     poPoly->getExteriorRing()->IsEmpty() )
                 {
-                    CPLDebug( "OGR", 
+                    CPLDebug( "OGR",
                               "Ignore POLYGON EMPTY inside MULTIPOLYGON in shapefile writer." );
                     continue;
                 }
 
-                papoRings = (OGRLinearRing **) CPLRealloc(papoRings, 
+                papoRings = (OGRLinearRing **) CPLRealloc(papoRings,
                      sizeof(void*) * (nRings+poPoly->getNumInteriorRings()+1));
-                for( iRing = 0; 
-                     iRing < poPoly->getNumInteriorRings()+1; 
+                for( iRing = 0;
+                     iRing < poPoly->getNumInteriorRings()+1;
                      iRing++ )
                 {
                     if( iRing == 0 )
                         papoRings[nRings] = poPoly->getExteriorRing();
                     else
-                        papoRings[nRings] = 
+                        papoRings[nRings] =
                             poPoly->getInteriorRing( iRing-1 );
 
                     /* Ignore LINEARRING EMPTY */
                     if (papoRings[nRings]->getNumPoints() != 0)
                         nRings ++;
                     else
-                        CPLDebug( "OGR", 
+                        CPLDebug( "OGR",
                               "Ignore LINEARRING EMPTY inside POLYGON in shapefile writer." );
                 }
             }
         }
-        else 
+        else
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Attempt to write non-polygon (%s) geometry to "
@@ -808,8 +884,8 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
         if( nRings == 0 )
         {
             SHPObject       *psShape;
-            
-            psShape = SHPCreateSimpleObject( SHPT_NULL, 0, NULL, NULL, NULL );
+
+            psShape = SHPCreateObject( SHPT_NULL, -1, 0, NULL, NULL, 0, NULL, NULL, NULL, NULL );
             nReturnedShapeID = SHPWriteObject( hSHP, iShape, psShape );
             SHPDestroyObject( psShape );
 
@@ -818,7 +894,7 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
 
             return OGRERR_NONE;
         }
-        
+
         /* count vertices */
         nVertex = 0;
         for( iRing = 0; iRing < nRings; iRing++ )
@@ -828,6 +904,8 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
         padfX = (double *) CPLMalloc(sizeof(double)*nVertex);
         padfY = (double *) CPLMalloc(sizeof(double)*nVertex);
         padfZ = (double *) CPLMalloc(sizeof(double)*nVertex);
+        if( wkbHasM(eLayerGeomType) && (hSHP->nShapeType == SHPT_POLYGONM || hSHP->nShapeType == SHPT_POLYGONZ) )
+            padfM = (double *) CPLMalloc(sizeof(double)*nVertex);
 
         /* collect vertices */
         nVertex = 0;
@@ -841,23 +919,29 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
                 padfX[nVertex] = poRing->getX( iPoint );
                 padfY[nVertex] = poRing->getY( iPoint );
                 padfZ[nVertex] = poRing->getZ( iPoint );
+                if( padfM )
+                {
+                    padfM[nVertex] = poGeom->IsMeasured() ?
+                        poRing->getM( iPoint ) : -std::numeric_limits<double>::max();
+                }
                 nVertex++;
             }
         }
 
-        psShape = SHPCreateObject( hSHP->nShapeType, iShape, nRings,
+        SHPObject* psShape = SHPCreateObject( hSHP->nShapeType, iShape, nRings,
                                    panRingStart, NULL,
-                                   nVertex, padfX, padfY, padfZ, NULL );
+                                   nVertex, padfX, padfY, padfZ, padfM );
         if( bRewind )
             SHPRewindObject( hSHP, psShape );
         nReturnedShapeID = SHPWriteObject( hSHP, iShape, psShape );
         SHPDestroyObject( psShape );
-        
+
         CPLFree( papoRings );
         CPLFree( panRingStart );
         CPLFree( padfX );
         CPLFree( padfY );
         CPLFree( padfZ );
+        CPLFree( padfM );
         if( nReturnedShapeID == -1 )
             return OGRERR_FAILURE;
     }
@@ -916,9 +1000,10 @@ OGRFeatureDefn *SHPReadOGRFeatureDefn( const char * pszName,
         {
             /* XXX - mloskot:
              * Shapefile date has following 8-chars long format: 20060101.
-             * OGR splits it as YYYY/MM/DD, so 2 additional characters are required.
-             * Is this correct assumtion? What about time part of date?
-             * Shouldn't this format look as datetime: YYYY/MM/DD HH:MM:SS
+             * OGR splits it as YYYY/MM/DD, so 2 additional characters are
+             * required.
+             * Is this a correct assumption? What about time part of date?
+             * Should this format look as datetime: YYYY/MM/DD HH:MM:SS
              * with 4 additional characters?
              */
             oField.SetWidth( nWidth + 2 );
@@ -939,7 +1024,7 @@ OGRFeatureDefn *SHPReadOGRFeatureDefn( const char * pszName,
 
         poDefn->AddFieldDefn( &oField );
     }
-    
+
     /* Do an optional past if requested and needed to demote Integer64->Integer */
     /* or Real->Integer64/Integer */
     if( nAdjustableFields && bAdjustType )
@@ -956,7 +1041,7 @@ OGRFeatureDefn *SHPReadOGRFeatureDefn( const char * pszName,
                 //poDefn->GetFieldDefn(iField)->SetWidth(0);
             }
         }
-       
+
         int nRowCount = DBFGetRecordCount(hDBF);
         for( int iRow = 0; iRow < nRowCount && nAdjustableFields; iRow ++ )
         {
@@ -977,21 +1062,21 @@ OGRFeatureDefn *SHPReadOGRFeatureDefn( const char * pszName,
                            poDefn->GetFieldDefn(iField)->SetType(OFTReal);
                            panAdjustableField[iField] = FALSE;
                            nAdjustableFields --;
-                           
+
                            /*char            szFieldName[12] = {};
                            int             nWidth, nPrecision;
                            DBFGetFieldInfo( hDBF, iField, szFieldName,
                                             &nWidth, &nPrecision );
                            poDefn->GetFieldDefn(iField)->SetWidth(nWidth);*/
                        }
-                       else if( (GIntBig)(int)nVal != nVal )
+                       else if( !CPL_INT64_FITS_ON_INT32(nVal) )
                        {
                            poDefn->GetFieldDefn(iField)->SetType(OFTInteger64);
                            if( poDefn->GetFieldDefn(iField)->GetWidth() <= 18 )
                            {
                                panAdjustableField[iField] = FALSE;
                                nAdjustableFields --;
-                               
+
                                /*char            szFieldName[12] = {};
                                int             nWidth, nPrecision;
                                DBFGetFieldInfo( hDBF, iField, szFieldName,
@@ -1003,7 +1088,7 @@ OGRFeatureDefn *SHPReadOGRFeatureDefn( const char * pszName,
                }
            }
         }
-        
+
         CPLFree(panAdjustableField);
     }
 
@@ -1018,8 +1103,11 @@ OGRFeatureDefn *SHPReadOGRFeatureDefn( const char * pszName,
             break;
 
           case SHPT_POINTZ:
+            poDefn->SetGeomType( wkbPointZM );
+            break;
+
           case SHPT_POINTM:
-            poDefn->SetGeomType( wkbPoint25D );
+            poDefn->SetGeomType( wkbPointM );
             break;
 
           case SHPT_ARC:
@@ -1027,8 +1115,11 @@ OGRFeatureDefn *SHPReadOGRFeatureDefn( const char * pszName,
             break;
 
           case SHPT_ARCZ:
+            poDefn->SetGeomType( wkbLineStringZM );
+            break;
+
           case SHPT_ARCM:
-            poDefn->SetGeomType( wkbLineString25D );
+            poDefn->SetGeomType( wkbLineStringM );
             break;
 
           case SHPT_MULTIPOINT:
@@ -1036,8 +1127,11 @@ OGRFeatureDefn *SHPReadOGRFeatureDefn( const char * pszName,
             break;
 
           case SHPT_MULTIPOINTZ:
+            poDefn->SetGeomType( wkbMultiPointZM );
+            break;
+
           case SHPT_MULTIPOINTM:
-            poDefn->SetGeomType( wkbMultiPoint25D );
+            poDefn->SetGeomType( wkbMultiPointM );
             break;
 
           case SHPT_POLYGON:
@@ -1045,10 +1139,13 @@ OGRFeatureDefn *SHPReadOGRFeatureDefn( const char * pszName,
             break;
 
           case SHPT_POLYGONZ:
+            poDefn->SetGeomType( wkbPolygonZM );
+            break;
+
           case SHPT_POLYGONM:
-            poDefn->SetGeomType( wkbPolygon25D );
+            poDefn->SetGeomType( wkbPolygonM );
             break;
-            
+
         }
     }
 
@@ -1064,11 +1161,11 @@ OGRFeature *SHPReadOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
                                SHPObject *psShape, const char *pszSHPEncoding )
 
 {
-    if( iShape < 0 
+    if( iShape < 0
         || (hSHP != NULL && iShape >= hSHP->nRecords)
         || (hDBF != NULL && iShape >= hDBF->nRecords) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Attempt to read shape with feature id (%d) out of available"
                   " range.", iShape );
         return NULL;
@@ -1076,7 +1173,7 @@ OGRFeature *SHPReadOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
 
     if( hDBF && DBFIsRecordDeleted( hDBF, iShape ) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Attempt to read shape with feature id (%d), but it is marked deleted.",
                   iShape );
         if( psShape != NULL )
@@ -1098,13 +1195,40 @@ OGRFeature *SHPReadOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
 
             /*
             * NOTE - mloskot:
-            * Two possibilities are expected here (bot hare tested by GDAL Autotests):
+            * Two possibilities are expected here (both are tested by GDAL Autotests):
             * 1. Read valid geometry and assign it directly.
             * 2. Read and assign null geometry if it can not be read correctly from a shapefile
             *
             * It's NOT required here to test poGeometry == NULL.
             */
 
+            if (poGeometry)
+            {
+                /* Set/unset flags. */
+                OGRwkbGeometryType eMyGeomType = poFeature->GetDefnRef()->GetGeomFieldDefn(0)->GetType();
+
+                if( eMyGeomType != wkbUnknown )
+                {
+                    OGRwkbGeometryType eGeomInType = poGeometry->getGeometryType();
+                    if( wkbHasZ(eMyGeomType) && !wkbHasZ(eGeomInType) )
+                    {
+                        poGeometry->set3D(TRUE);
+                    }
+                    else if( !wkbHasZ(eMyGeomType) && wkbHasZ(eGeomInType) )
+                    {
+                        poGeometry->set3D(FALSE);
+                    }
+                    if( wkbHasM(eMyGeomType) && !wkbHasM(eGeomInType) )
+                    {
+                        poGeometry->setMeasured(TRUE);
+                    }
+                    else if( !wkbHasM(eMyGeomType) && wkbHasM(eGeomInType) )
+                    {
+                        poGeometry->setMeasured(FALSE);
+                    }
+                }
+            }
+
             poFeature->SetGeometryDirectly( poGeometry );
         }
         else if( psShape != NULL )
@@ -1117,7 +1241,7 @@ OGRFeature *SHPReadOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
 /*      Fetch feature attributes to OGRFeature fields.                  */
 /* -------------------------------------------------------------------- */
 
-    for( int iField = 0; iField < poDefn->GetFieldCount(); iField++ )
+    for( int iField = 0; hDBF != NULL && iField < poDefn->GetFieldCount(); iField++ )
     {
         OGRFieldDefn* poFieldDefn = poDefn->GetFieldDefn(iField);
         if (poFieldDefn->IsIgnored() )
@@ -1127,7 +1251,7 @@ OGRFeature *SHPReadOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
         {
           case OFTString:
           {
-              const char *pszFieldVal = 
+              const char *pszFieldVal =
                   DBFReadStringAttribute( hDBF, iShape, iField );
               if( pszFieldVal != NULL && pszFieldVal[0] != '\0' )
               {
@@ -1159,7 +1283,7 @@ OGRFeature *SHPReadOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
               if( DBFIsAttributeNULL( hDBF, iShape, iField ) )
                   continue;
 
-              const char* pszDateValue = 
+              const char* pszDateValue =
                   DBFReadStringAttribute(hDBF,iShape,iField);
 
               /* Some DBF files have fields filled with spaces */
@@ -1184,7 +1308,7 @@ OGRFeature *SHPReadOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
                   sFld.Date.Month = (GByte)((nFullDate / 100) % 100);
                   sFld.Date.Day = (GByte)(nFullDate % 100);
               }
-              
+
               poFeature->SetField( iField, &sFld );
           }
           break;
@@ -1242,7 +1366,7 @@ static OGRErr GrowField(DBFHandle hDBF, int iField, OGRFieldDefn* poFieldDefn,
 /************************************************************************/
 
 OGRErr SHPWriteOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
-                           OGRFeatureDefn * poDefn, 
+                           OGRFeatureDefn * poDefn,
                            OGRFeature * poFeature,
                            const char *pszSHPEncoding,
                            int* pbTruncationWarningEmitted,
@@ -1258,7 +1382,7 @@ OGRErr SHPWriteOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Attempt to write feature without geometry not supported"
                   " for shapefile driver." );
-        
+
         return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
     }
 #endif
@@ -1271,11 +1395,12 @@ OGRErr SHPWriteOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
     if( hSHP != NULL )
     {
         eErr = SHPWriteOGRObject( hSHP, (int)poFeature->GetFID(),
-                                  poFeature->GetGeometryRef(), bRewind );
+                                  poFeature->GetGeometryRef(), bRewind,
+                                  poDefn->GetGeomType() );
         if( eErr != OGRERR_NONE )
             return eErr;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      If there is no DBF, the job is done now.                        */
 /* -------------------------------------------------------------------- */
@@ -1304,7 +1429,7 @@ OGRErr SHPWriteOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
 /* -------------------------------------------------------------------- */
     if( DBFGetRecordCount( hDBF ) == 0 && DBFGetFieldCount( hDBF ) == 0 )
     {
-        CPLDebug( "OGR", 
+        CPLDebug( "OGR",
                "Created dummy FID field for shapefile since schema is empty.");
         DBFAddField( hDBF, "FID", FTInteger, 11, 0 );
     }
@@ -1314,7 +1439,7 @@ OGRErr SHPWriteOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
 /* -------------------------------------------------------------------- */
     if( DBFGetFieldCount( hDBF ) == 1 && poDefn->GetFieldCount() == 0 )
     {
-        DBFWriteIntegerAttribute( hDBF, (int)poFeature->GetFID(), 0, 
+        DBFWriteIntegerAttribute( hDBF, (int)poFeature->GetFID(), 0,
                                   (int)poFeature->GetFID() );
     }
 
@@ -1360,7 +1485,8 @@ OGRErr SHPWriteOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
 
                 nStrLen = OGR_DBF_MAX_FIELD_WIDTH;
 
-                if(EQUAL(pszSHPEncoding, CPL_ENC_UTF8))
+                if(pszEncoded != NULL && /* to please Coverity */
+                   EQUAL(pszSHPEncoding, CPL_ENC_UTF8))
                 {
                     const char *p = pszStr + nStrLen;
                     int byteCount = nStrLen;
@@ -1402,9 +1528,9 @@ OGRErr SHPWriteOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
               char szFormat[20];
               char szValue[32];
               int nFieldWidth = poFieldDefn->GetWidth();
-              sprintf(szFormat, "%%%d" CPL_FRMT_GB_WITHOUT_PREFIX "d", MIN(nFieldWidth, (int)sizeof(szValue)-1));
-              sprintf(szValue, szFormat, poFeature->GetFieldAsInteger64(iField) );
-              int nStrLen = strlen(szValue);
+              snprintf(szFormat, sizeof(szFormat), "%%%d" CPL_FRMT_GB_WITHOUT_PREFIX "d", MIN(nFieldWidth, (int)sizeof(szValue)-1));
+              snprintf(szValue, sizeof(szValue), szFormat, poFeature->GetFieldAsInteger64(iField) );
+              int nStrLen = static_cast<int>(strlen(szValue));
               if( nStrLen > nFieldWidth )
               {
                   if (GrowField(hDBF, iField, poFieldDefn, nStrLen) != OGRERR_NONE)
@@ -1413,7 +1539,7 @@ OGRErr SHPWriteOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
                   }
               }
 
-              DBFWriteAttributeDirectly( hDBF, (int)poFeature->GetFID(), iField, 
+              DBFWriteAttributeDirectly( hDBF, (int)poFeature->GetFID(), iField,
                                          szValue );
 
               break;
@@ -1428,14 +1554,19 @@ OGRErr SHPWriteOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
                 static int nCounter = 0;
                 if( nCounter <= 10 )
                 {
-                    CPLError(CE_Warning, CPLE_AppDefined,
-                             "Value %.18g of field %s with 0 decimal of feature " CPL_FRMT_GIB " is bigger than 2^53. Precision loss likely occured or going to happen.%s",
-                             dfVal, poFieldDefn->GetNameRef(), poFeature->GetFID(),
-                             (nCounter == 10) ? " This warning will not be emitted anymore." : "");
+                    CPLError( CE_Warning, CPLE_AppDefined,
+                              "Value %.18g of field %s with 0 decimal of "
+                              "feature " CPL_FRMT_GIB " is bigger than 2^53. "
+                              "Precision loss likely occurred or going to "
+                              "happen.%s",
+                              dfVal, poFieldDefn->GetNameRef(),
+                              poFeature->GetFID(),
+                              (nCounter == 10) ? " This warning will not be "
+                              "emitted anymore." : "");
                     nCounter ++;
                 }
             }
-            int ret = DBFWriteDoubleAttribute( hDBF, (int)poFeature->GetFID(), iField, 
+            int ret = DBFWriteDoubleAttribute( hDBF, (int)poFeature->GetFID(), iField,
                                                dfVal );
             if( !ret )
             {
@@ -1457,7 +1588,7 @@ OGRErr SHPWriteOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
                           "Year < 0 or > 9999 is not a valid date for shapefile");
               }
               else
-                  DBFWriteIntegerAttribute( hDBF, (int)poFeature->GetFID(), iField, 
+                  DBFWriteIntegerAttribute( hDBF, (int)poFeature->GetFID(), iField,
                                             psField->Date.Year*10000 + psField->Date.Month*100 + psField->Date.Day );
           }
           break;
diff --git a/ogr/ogrsf_frmts/shape/shapefil.h b/ogr/ogrsf_frmts/shape/shapefil.h
index fc78b07..0b8a202 100644
--- a/ogr/ogrsf_frmts/shape/shapefil.h
+++ b/ogr/ogrsf_frmts/shape/shapefil.h
@@ -2,7 +2,7 @@
 #define SHAPEFILE_H_INCLUDED
 
 /******************************************************************************
- * $Id: shapefil.h 28337 2015-01-21 21:10:33Z rouault $
+ * $Id: shapefil.h 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Shapelib
  * Purpose:  Primary include file for Shapelib.
@@ -17,7 +17,7 @@
  * option is discussed in more detail in shapelib.html.
  *
  * --
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * to deal in the Software without restriction, including without limitation
@@ -77,8 +77,8 @@
  *
  * Revision 1.41  2007/12/15 20:25:32  bram
  * dbfopen.c now reads the Code Page information from the DBF file, and exports
- * this information as a string through the DBFGetCodePage function.  This is 
- * either the number from the LDID header field ("LDID/<number>") or as the 
+ * this information as a string through the DBFGetCodePage function.  This is
+ * either the number from the LDID header field ("LDID/<number>") or as the
  * content of an accompanying .CPG file.  When creating a DBF file, the code can
  * be set using DBFCreateEx.
  *
@@ -171,7 +171,7 @@ extern "C" {
 /*      is disabled.                                                    */
 /* -------------------------------------------------------------------- */
 #define DISABLE_MULTIPATCH_MEASURE
-    
+
 /* -------------------------------------------------------------------- */
 /*      SHPAPI_CALL                                                     */
 /*                                                                      */
@@ -195,7 +195,7 @@ extern "C" {
 /*        #define SHPAPI_CALL __declspec(dllexport) __stdcall           */
 /*        #define SHPAPI_CALL1 __declspec(dllexport) * __stdcall        */
 /*                                                                      */
-/*      The complexity of the situtation is partly caused by the        */
+/*      The complexity of the situation is partly caused by the        */
 /*      peculiar requirement of Visual C++ that __stdcall appear        */
 /*      after any "*"'s in the return value of a function while the     */
 /*      __declspec(dllexport) must appear before them.                  */
@@ -218,17 +218,17 @@ extern "C" {
 #ifndef SHPAPI_CALL1
 #  define SHPAPI_CALL1(x)      x SHPAPI_CALL
 #endif
-    
+
 /* -------------------------------------------------------------------- */
 /*      Macros for controlling CVSID and ensuring they don't appear     */
 /*      as unreferenced variables resulting in lots of warnings.        */
 /* -------------------------------------------------------------------- */
 #ifndef DISABLE_CVSID
 #  if defined(__GNUC__) && __GNUC__ >= 4
-#    define SHP_CVSID(string)     static char cpl_cvsid[] __attribute__((used)) = string;
+#    define SHP_CVSID(string)     static const char cpl_cvsid[] __attribute__((used)) = string;
 #  else
-#    define SHP_CVSID(string)     static char cpl_cvsid[] = string; \
-static char *cvsid_aw() { return( cvsid_aw() ? ((char *) NULL) : cpl_cvsid ); }
+#    define SHP_CVSID(string)     static const char cpl_cvsid[] = string; \
+static const char *cvsid_aw() { return( cvsid_aw() ? NULL : cpl_cvsid ); }
 #  endif
 #else
 #  define SHP_CVSID(string)
@@ -284,7 +284,7 @@ typedef struct
     SAFile 	fpSHX;
 
     int		nShapeType;				/* SHPT_* */
-    
+
     unsigned int 	nFileSize;				/* SHP file */
 
     int         nRecords;
@@ -299,7 +299,7 @@ typedef struct
 
     unsigned char *pabyRec;
     int         nBufSize;
-    
+
     int            bFastModeReadObject;
     unsigned char *pabyObjectBuf;
     int            nObjectBufSize;
@@ -352,7 +352,7 @@ struct tagSHPObject
     int		nParts;
     int		*panPartStart;
     int		*panPartType;
-    
+
     int		nVertices;
     double	*padfX;
     double	*padfY;
@@ -382,7 +382,7 @@ struct tagSHPObject
 SHPHandle SHPAPI_CALL
       SHPOpen( const char * pszShapeFile, const char * pszAccess );
 SHPHandle SHPAPI_CALL
-      SHPOpenLL( const char *pszShapeFile, const char *pszAccess, 
+      SHPOpenLL( const char *pszShapeFile, const char *pszAccess,
                  SAHooks *psHooks );
 
 /* If setting bFastMode = TRUE, the content of SHPReadObject() is owned by the SHPHandle. */
@@ -410,15 +410,15 @@ void SHPAPI_CALL
 void SHPAPI_CALL
       SHPComputeExtents( SHPObject * psObject );
 SHPObject SHPAPI_CALL1(*)
-      SHPCreateObject( int nSHPType, int nShapeId, int nParts, 
+      SHPCreateObject( int nSHPType, int nShapeId, int nParts,
                        const int * panPartStart, const int * panPartType,
-                       int nVertices, 
+                       int nVertices,
                        const double * padfX, const double * padfY,
                        const double * padfZ, const double * padfM );
 SHPObject SHPAPI_CALL1(*)
       SHPCreateSimpleObject( int nSHPType, int nVertices,
-                             const double * padfX, 
-                             const double * padfY, 
+                             const double * padfX,
+                             const double * padfY,
                              const double * padfZ );
 
 int SHPAPI_CALL
@@ -456,17 +456,17 @@ typedef struct shape_tree_node
 
     int		nSubNodes;
     struct shape_tree_node *apsSubNode[MAX_SUBNODE];
-    
+
 } SHPTreeNode;
 
 typedef struct
 {
     SHPHandle   hSHP;
-    
+
     int		nMaxDepth;
     int		nDimension;
     int         nTotalCount;
-    
+
     SHPTreeNode	*psRoot;
 } SHPTree;
 
@@ -495,8 +495,8 @@ int    SHPAPI_CALL1(*)
 int     SHPAPI_CALL
       SHPCheckBoundsOverlap( double *, double *, double *, double *, int );
 
-int SHPAPI_CALL1(*) 
-SHPSearchDiskTree( FILE *fp, 
+int SHPAPI_CALL1(*)
+SHPSearchDiskTree( FILE *fp,
                    double *padfBoundsMin, double *padfBoundsMax,
                    int *pnShapeCount );
 
@@ -510,8 +510,8 @@ SHPTreeDiskHandle SHPAPI_CALL
 void SHPAPI_CALL
     SHPCloseDiskTree( SHPTreeDiskHandle hDiskTree );
 
-int SHPAPI_CALL1(*) 
-SHPSearchDiskTreeEx( SHPTreeDiskHandle hDiskTree, 
+int SHPAPI_CALL1(*)
+SHPSearchDiskTreeEx( SHPTreeDiskHandle hDiskTree,
                    double *padfBoundsMin, double *padfBoundsMax,
                    int *pnShapeCount );
 
@@ -571,7 +571,7 @@ typedef	struct
 
     int         nWorkFieldLength;
     char        *pszWorkField;
-    
+
     int		bNoHeader;
     int		bUpdated;
 
@@ -583,7 +583,7 @@ typedef	struct
 
     int         iLanguageDriver;
     char        *pszCodePage;
-    
+
     int         nUpdateYearSince1900; /* 0-255 */
     int         nUpdateMonth; /* 1-12 */
     int         nUpdateDay; /* 1-31 */
@@ -637,7 +637,7 @@ int SHPAPI_CALL
                          char chType, int nWidth, int nDecimals );
 
 DBFFieldType SHPAPI_CALL
-      DBFGetFieldInfo( DBFHandle psDBF, int iField, 
+      DBFGetFieldInfo( DBFHandle psDBF, int iField,
                        char * pszFieldName, int * pnWidth, int * pnDecimals );
 
 int SHPAPI_CALL
@@ -655,7 +655,7 @@ int     SHPAPI_CALL
       DBFIsAttributeNULL( DBFHandle hDBF, int iShape, int iField );
 
 int SHPAPI_CALL
-      DBFWriteIntegerAttribute( DBFHandle hDBF, int iShape, int iField, 
+      DBFWriteIntegerAttribute( DBFHandle hDBF, int iShape, int iField,
                                 int nFieldValue );
 int SHPAPI_CALL
       DBFWriteDoubleAttribute( DBFHandle hDBF, int iShape, int iField,
@@ -678,12 +678,12 @@ int SHPAPI_CALL
       DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple );
 
 int SHPAPI_CALL DBFIsRecordDeleted( DBFHandle psDBF, int iShape );
-int SHPAPI_CALL DBFMarkRecordDeleted( DBFHandle psDBF, int iShape, 
+int SHPAPI_CALL DBFMarkRecordDeleted( DBFHandle psDBF, int iShape,
                                       int bIsDeleted );
 
 DBFHandle SHPAPI_CALL
       DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename );
- 
+
 void	SHPAPI_CALL
       DBFClose( DBFHandle hDBF );
 void    SHPAPI_CALL
diff --git a/ogr/ogrsf_frmts/shape/shp_vsi.c b/ogr/ogrsf_frmts/shape/shp_vsi.c
index 4dda3f7..8af56f8 100644
--- a/ogr/ogrsf_frmts/shape/shp_vsi.c
+++ b/ogr/ogrsf_frmts/shape/shp_vsi.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: shp_vsi.c 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: shp_vsi.c 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  IO Redirection via VSI services for shp/dbf io.
@@ -32,7 +32,7 @@
 #include "cpl_error.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: shp_vsi.c 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: shp_vsi.c 33714 2016-03-13 05:42:13Z goatbar $");
 
 typedef struct
 {
@@ -115,7 +115,7 @@ SAOffset VSI_SHP_Read( void *p, SAOffset size, SAOffset nmemb, SAFile file )
 
 {
     OGRSHPDBFFile* pFile = (OGRSHPDBFFile*) file;
-    SAOffset ret = (SAOffset) VSIFReadL( p, (size_t) size, (size_t) nmemb, 
+    SAOffset ret = (SAOffset) VSIFReadL( p, (size_t) size, (size_t) nmemb,
                                  pFile->fp );
     pFile->nCurOffset += ret * size;
     return ret;
@@ -160,7 +160,7 @@ SAOffset VSI_SHP_Write( void *p, SAOffset size, SAOffset nmemb, SAFile file )
     SAOffset ret;
     if( !VSI_SHP_WriteMoreDataOK( file, size * nmemb ) )
         return 0;
-    ret = (SAOffset) VSIFWriteL( p, (size_t) size, (size_t) nmemb, 
+    ret = (SAOffset) VSIFWriteL( p, (size_t) size, (size_t) nmemb,
                                   pFile->fp );
     pFile->nCurOffset += ret * size;
     return ret;
diff --git a/ogr/ogrsf_frmts/shape/shpopen.c b/ogr/ogrsf_frmts/shape/shpopen.c
index c0d1b08..8e269ac 100644
--- a/ogr/ogrsf_frmts/shape/shpopen.c
+++ b/ogr/ogrsf_frmts/shape/shpopen.c
@@ -14,7 +14,7 @@
  * option is discussed in more detail in shapelib.html.
  *
  * --
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * to deal in the Software without restriction, including without limitation
@@ -160,7 +160,7 @@
  * move pabyRec into SHPInfo for thread safety
  *
  * Revision 1.33  2001/07/03 12:18:15  warmerda
- * Improved cleanup if SHX not found, provied by Riccardo Cohen.
+ * Improved cleanup if SHX not found, provided by Riccardo Cohen.
  *
  * Revision 1.32  2001/06/22 01:58:07  warmerda
  * be more careful about establishing initial bounds in face of NULL shapes
@@ -360,7 +360,7 @@ void SHPAPI_CALL SHPWriteHeader( SHPHandle psSHP )
     int32	i32;
     double	dValue;
     int32	*panSHX;
-    
+
     if (psSHP->fpSHX == NULL)
     {
         psSHP->sHooks.Error( "SHPWriteHeader failed : SHX file is closed");
@@ -379,11 +379,11 @@ void SHPAPI_CALL SHPWriteHeader( SHPHandle psSHP )
     i32 = psSHP->nFileSize/2;				/* file size */
     ByteCopy( &i32, abyHeader+24, 4 );
     if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
-    
+
     i32 = 1000;						/* version */
     ByteCopy( &i32, abyHeader+28, 4 );
     if( bBigEndian ) SwapWord( 4, abyHeader+28 );
-    
+
     i32 = psSHP->nShapeType;				/* shape type */
     ByteCopy( &i32, abyHeader+32, 4 );
     if( bBigEndian ) SwapWord( 4, abyHeader+32 );
@@ -423,7 +423,7 @@ void SHPAPI_CALL SHPWriteHeader( SHPHandle psSHP )
 /* -------------------------------------------------------------------- */
 /*      Write .shp file header.                                         */
 /* -------------------------------------------------------------------- */
-    if( psSHP->sHooks.FSeek( psSHP->fpSHP, 0, 0 ) != 0 
+    if( psSHP->sHooks.FSeek( psSHP->fpSHP, 0, 0 ) != 0
         || psSHP->sHooks.FWrite( abyHeader, 100, 1, psSHP->fpSHP ) != 1 )
     {
         psSHP->sHooks.Error( "Failure writing .shp header" );
@@ -436,8 +436,8 @@ void SHPAPI_CALL SHPWriteHeader( SHPHandle psSHP )
     i32 = (psSHP->nRecords * 2 * sizeof(int32) + 100)/2;   /* file size */
     ByteCopy( &i32, abyHeader+24, 4 );
     if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
-    
-    if( psSHP->sHooks.FSeek( psSHP->fpSHX, 0, 0 ) != 0 
+
+    if( psSHP->sHooks.FSeek( psSHP->fpSHX, 0, 0 ) != 0
         || psSHP->sHooks.FWrite( abyHeader, 100, 1, psSHP->fpSHX ) != 1 )
     {
         psSHP->sHooks.Error( "Failure writing .shx header" );
@@ -448,6 +448,11 @@ void SHPAPI_CALL SHPWriteHeader( SHPHandle psSHP )
 /*      Write out the .shx contents.                                    */
 /* -------------------------------------------------------------------- */
     panSHX = (int32 *) malloc(sizeof(int32) * 2 * psSHP->nRecords);
+    if( panSHX == NULL )
+    {
+        psSHP->sHooks.Error( "Failure allocatin panSHX" );
+        return;
+    }
 
     for( i = 0; i < psSHP->nRecords; i++ )
     {
@@ -457,7 +462,7 @@ void SHPAPI_CALL SHPWriteHeader( SHPHandle psSHP )
         if( !bBigEndian ) SwapWord( 4, panSHX+i*2+1 );
     }
 
-    if( (int)psSHP->sHooks.FWrite( panSHX, sizeof(int32)*2, psSHP->nRecords, psSHP->fpSHX ) 
+    if( (int)psSHP->sHooks.FWrite( panSHX, sizeof(int32)*2, psSHP->nRecords, psSHP->fpSHX )
         != psSHP->nRecords )
     {
         psSHP->sHooks.Error( "Failure writing .shx contents" );
@@ -493,19 +498,20 @@ SHPOpen( const char * pszLayer, const char * pszAccess )
 /*      Open the .shp and .shx files based on the basename of the       */
 /*      files or either file name.                                      */
 /************************************************************************/
-   
+
 SHPHandle SHPAPI_CALL
 SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
 
 {
     char		*pszFullname, *pszBasename;
     SHPHandle		psSHP;
-    
+
     uchar		*pabyBuf;
     int			i;
     double		dValue;
     int         bLazySHXLoading = FALSE;
-    
+    size_t nFullnameLen;
+
 /* -------------------------------------------------------------------- */
 /*      Ensure the access string is one of the legal ones.  We          */
 /*      ensure the result string indicates binary to avoid common       */
@@ -519,7 +525,7 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
         bLazySHXLoading = strchr(pszAccess, 'l') != NULL;
         pszAccess = "rb";
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*	Establish the byte order on this machine.			*/
 /* -------------------------------------------------------------------- */
@@ -545,7 +551,7 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
 /* -------------------------------------------------------------------- */
     pszBasename = (char *) malloc(strlen(pszLayer)+5);
     strcpy( pszBasename, pszLayer );
-    for( i = strlen(pszBasename)-1; 
+    for( i = (int)strlen(pszBasename)-1;
          i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
              && pszBasename[i] != '\\';
          i-- ) {}
@@ -557,19 +563,21 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
 /*	Open the .shp and .shx files.  Note that files pulled from	*/
 /*	a PC to Unix with upper case filenames won't work!		*/
 /* -------------------------------------------------------------------- */
-    pszFullname = (char *) malloc(strlen(pszBasename) + 5);
-    sprintf( pszFullname, "%s.shp", pszBasename ) ;
+    nFullnameLen = strlen(pszBasename) + 5;
+    pszFullname = (char *) malloc(nFullnameLen);
+    snprintf( pszFullname, nFullnameLen, "%s.shp", pszBasename ) ;
     psSHP->fpSHP = psSHP->sHooks.FOpen(pszFullname, pszAccess );
     if( psSHP->fpSHP == NULL )
     {
-        sprintf( pszFullname, "%s.SHP", pszBasename );
+        snprintf( pszFullname, nFullnameLen, "%s.SHP", pszBasename );
         psSHP->fpSHP = psSHP->sHooks.FOpen(pszFullname, pszAccess );
     }
-    
+
     if( psSHP->fpSHP == NULL )
     {
-        char *pszMessage = (char *) malloc(strlen(pszBasename)*2+256);
-        sprintf( pszMessage, "Unable to open %s.shp or %s.SHP.", 
+        size_t nMessageLen = strlen(pszBasename)*2+256;
+        char *pszMessage = (char *) malloc(nMessageLen);
+        snprintf( pszMessage, nMessageLen, "Unable to open %s.shp or %s.SHP.",
                   pszBasename, pszBasename );
         psHooks->Error( pszMessage );
         free( pszMessage );
@@ -581,18 +589,19 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
         return NULL;
     }
 
-    sprintf( pszFullname, "%s.shx", pszBasename );
+    snprintf( pszFullname, nFullnameLen, "%s.shx", pszBasename );
     psSHP->fpSHX =  psSHP->sHooks.FOpen(pszFullname, pszAccess );
     if( psSHP->fpSHX == NULL )
     {
-        sprintf( pszFullname, "%s.SHX", pszBasename );
+        snprintf( pszFullname, nFullnameLen, "%s.SHX", pszBasename );
         psSHP->fpSHX = psSHP->sHooks.FOpen(pszFullname, pszAccess );
     }
-    
+
     if( psSHP->fpSHX == NULL )
     {
-        char *pszMessage = (char *) malloc(strlen(pszBasename)*2+256);
-        sprintf( pszMessage, "Unable to open %s.shx or %s.SHX.", 
+        size_t nMessageLen = strlen(pszBasename)*2+256;
+        char *pszMessage = (char *) malloc(nMessageLen);
+        snprintf( pszMessage, nMessageLen, "Unable to open %s.shx or %s.SHX.",
                   pszBasename, pszBasename );
         psHooks->Error( pszMessage );
         free( pszMessage );
@@ -616,15 +625,19 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
     psSHP->nFileSize = ((unsigned int)pabyBuf[24] * 256 * 256 * 256
                         + (unsigned int)pabyBuf[25] * 256 * 256
                         + (unsigned int)pabyBuf[26] * 256
-                        + (unsigned int)pabyBuf[27]) * 2;
+                        + (unsigned int)pabyBuf[27]);
+    if( psSHP->nFileSize < 0xFFFFFFFFU / 2 )
+        psSHP->nFileSize *= 2;
+    else
+        psSHP->nFileSize = 0xFFFFFFFEU;
 
 /* -------------------------------------------------------------------- */
 /*  Read SHX file Header info                                           */
 /* -------------------------------------------------------------------- */
-    if( psSHP->sHooks.FRead( pabyBuf, 100, 1, psSHP->fpSHX ) != 1 
-        || pabyBuf[0] != 0 
-        || pabyBuf[1] != 0 
-        || pabyBuf[2] != 0x27 
+    if( psSHP->sHooks.FRead( pabyBuf, 100, 1, psSHP->fpSHX ) != 1
+        || pabyBuf[0] != 0
+        || pabyBuf[1] != 0
+        || pabyBuf[2] != 0x27
         || (pabyBuf[3] != 0x0a && pabyBuf[3] != 0x0d) )
     {
         psSHP->sHooks.Error( ".shx file is unreadable, or corrupt." );
@@ -636,20 +649,20 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
     }
 
     psSHP->nRecords = pabyBuf[27] + pabyBuf[26] * 256
-        + pabyBuf[25] * 256 * 256 + pabyBuf[24] * 256 * 256 * 256;
-    psSHP->nRecords = (psSHP->nRecords*2 - 100) / 8;
+        + pabyBuf[25] * 256 * 256 + (pabyBuf[24] & 0x7F) * 256 * 256 * 256;
+    psSHP->nRecords = (psSHP->nRecords - 50) / 4;
 
     psSHP->nShapeType = pabyBuf[32];
 
     if( psSHP->nRecords < 0 || psSHP->nRecords > 256000000 )
     {
         char szError[200];
-        
-        sprintf( szError, 
+
+        snprintf( szError, sizeof(szError),
                  "Record count in .shp header is %d, which seems\n"
                  "unreasonable.  Assuming header is corrupt.",
                  psSHP->nRecords );
-        psSHP->sHooks.Error( szError );				       
+        psSHP->sHooks.Error( szError );
         psSHP->sHooks.FClose( psSHP->fpSHP );
         psSHP->sHooks.FClose( psSHP->fpSHX );
         free( psSHP );
@@ -658,6 +671,21 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
         return( NULL );
     }
 
+    /* If a lot of records are advertized, check that the file is big enough */
+    /* to hold them */
+    if( psSHP->nRecords >= 1024 * 1024 )
+    {
+        SAOffset nFileSize;
+        psSHP->sHooks.FSeek( psSHP->fpSHX, 0, 2 );
+        nFileSize = psSHP->sHooks.FTell( psSHP->fpSHX );
+        if( nFileSize > 100 &&
+            nFileSize/2 < (SAOffset)(psSHP->nRecords * 4 + 50) )
+        {
+            psSHP->nRecords = (int)((nFileSize - 100) / 8);
+        }
+        psSHP->sHooks.FSeek( psSHP->fpSHX, 100, 0 );
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Read the bounds.                                                */
 /* -------------------------------------------------------------------- */
@@ -680,11 +708,11 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
     if( bBigEndian ) SwapWord( 8, pabyBuf+68 );		/* z */
     memcpy( &dValue, pabyBuf+68, 8 );
     psSHP->adBoundsMin[2] = dValue;
-    
+
     if( bBigEndian ) SwapWord( 8, pabyBuf+76 );
     memcpy( &dValue, pabyBuf+76, 8 );
     psSHP->adBoundsMax[2] = dValue;
-    
+
     if( bBigEndian ) SwapWord( 8, pabyBuf+84 );		/* z */
     memcpy( &dValue, pabyBuf+84, 8 );
     psSHP->adBoundsMin[3] = dValue;
@@ -716,9 +744,9 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
     {
         char szError[200];
 
-        sprintf(szError, 
+        snprintf( szError, sizeof(szError),
                 "Not enough memory to allocate requested memory (nRecords=%d).\n"
-                "Probably broken SHP file", 
+                "Probably broken SHP file",
                 psSHP->nRecords );
         psSHP->sHooks.Error( szError );
         psSHP->sHooks.FClose( psSHP->fpSHP );
@@ -737,12 +765,12 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
         return( psSHP );
     }
 
-    if( (int) psSHP->sHooks.FRead( pabyBuf, 8, psSHP->nRecords, psSHP->fpSHX ) 
+    if( (int) psSHP->sHooks.FRead( pabyBuf, 8, psSHP->nRecords, psSHP->fpSHX )
         != psSHP->nRecords )
     {
         char szError[200];
 
-        sprintf( szError, 
+        snprintf( szError, sizeof(szError),
                  "Failed to read all values for %d records in .shx file.",
                  psSHP->nRecords );
         psSHP->sHooks.Error( szError );
@@ -757,7 +785,7 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
 
         return( NULL );
     }
-    
+
     /* In read-only mode, we can close the SHX now */
     if (strcmp(pszAccess, "rb") == 0)
     {
@@ -767,7 +795,7 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
 
     for( i = 0; i < psSHP->nRecords; i++ )
     {
-        int32		nOffset, nLength;
+        unsigned int		nOffset, nLength;
 
         memcpy( &nOffset, pabyBuf + i * 8, 4 );
         if( !bBigEndian ) SwapWord( 4, &nOffset );
@@ -775,6 +803,28 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
         memcpy( &nLength, pabyBuf + i * 8 + 4, 4 );
         if( !bBigEndian ) SwapWord( 4, &nLength );
 
+        if( nOffset > (unsigned int)INT_MAX )
+        {
+            char str[128];
+            snprintf( str, sizeof(str),
+                    "Invalid offset for entity %d", i);
+
+            psSHP->sHooks.Error( str );
+            SHPClose(psSHP);
+            free( pabyBuf );
+            return NULL;
+        }
+        if( nLength > (unsigned int)(INT_MAX / 2 - 4) )
+        {
+            char str[128];
+            snprintf( str, sizeof(str),
+                    "Invalid length for entity %d", i);
+
+            psSHP->sHooks.Error( str );
+            SHPClose(psSHP);
+            free( pabyBuf );
+            return NULL;
+        }
         psSHP->panRecOffset[i] = nOffset*2;
         psSHP->panRecSize[i] = nLength*2;
     }
@@ -816,7 +866,7 @@ SHPClose(SHPHandle psSHP )
     {
         free( psSHP->pabyRec );
     }
-    
+
     if( psSHP->pabyObjectBuf != NULL )
     {
         free( psSHP->pabyObjectBuf );
@@ -825,7 +875,7 @@ SHPClose(SHPHandle psSHP )
     {
         free( psSHP->psCachedObject );
     }
-    
+
     free( psSHP );
 }
 
@@ -866,7 +916,7 @@ SHPGetInfo(SHPHandle psSHP, int * pnEntities, int * pnShapeType,
 
     if( psSHP == NULL )
         return;
-    
+
     if( pnEntities != NULL )
         *pnEntities = psSHP->nRecords;
 
@@ -917,7 +967,8 @@ SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
     uchar     	abyHeader[100];
     int32	i32;
     double	dValue;
-    
+    size_t      nFullnameLen;
+
 /* -------------------------------------------------------------------- */
 /*      Establish the byte order on this system.                        */
 /* -------------------------------------------------------------------- */
@@ -935,7 +986,7 @@ SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
 /* -------------------------------------------------------------------- */
     pszBasename = (char *) malloc(strlen(pszLayer)+5);
     strcpy( pszBasename, pszLayer );
-    for( i = strlen(pszBasename)-1; 
+    for( i = (int)strlen(pszBasename)-1;
          i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
              && pszBasename[i] != '\\';
          i-- ) {}
@@ -946,8 +997,9 @@ SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
 /* -------------------------------------------------------------------- */
 /*      Open the two files so we can write their headers.               */
 /* -------------------------------------------------------------------- */
-    pszFullname = (char *) malloc(strlen(pszBasename) + 5);
-    sprintf( pszFullname, "%s.shp", pszBasename );
+    nFullnameLen = strlen(pszBasename) + 5;
+    pszFullname = (char *) malloc(nFullnameLen);
+    snprintf( pszFullname, nFullnameLen, "%s.shp", pszBasename );
     fpSHP = psHooks->FOpen(pszFullname, "wb" );
     if( fpSHP == NULL )
     {
@@ -955,7 +1007,7 @@ SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
         goto error;
     }
 
-    sprintf( pszFullname, "%s.shx", pszBasename );
+    snprintf( pszFullname, nFullnameLen, "%s.shx", pszBasename );
     fpSHX = psHooks->FOpen(pszFullname, "wb" );
     if( fpSHX == NULL )
     {
@@ -978,11 +1030,11 @@ SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
     i32 = 50;						/* file size */
     ByteCopy( &i32, abyHeader+24, 4 );
     if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
-    
+
     i32 = 1000;						/* version */
     ByteCopy( &i32, abyHeader+28, 4 );
     if( bBigEndian ) SwapWord( 4, abyHeader+28 );
-    
+
     i32 = nShapeType;					/* shape type */
     ByteCopy( &i32, abyHeader+32, 4 );
     if( bBigEndian ) SwapWord( 4, abyHeader+32 );
@@ -1008,7 +1060,7 @@ SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
     i32 = 50;						/* file size */
     ByteCopy( &i32, abyHeader+24, 4 );
     if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
-    
+
     if( psHooks->FWrite( abyHeader, 100, 1, fpSHX ) != 1 )
     {
         psHooks->Error( "Failed to write .shx header." );
@@ -1067,7 +1119,7 @@ SHPComputeExtents( SHPObject * psObject )
 
 {
     int		i;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Build extents for this object.                                  */
 /* -------------------------------------------------------------------- */
@@ -1078,7 +1130,7 @@ SHPComputeExtents( SHPObject * psObject )
         psObject->dfZMin = psObject->dfZMax = psObject->padfZ[0];
         psObject->dfMMin = psObject->dfMMax = psObject->padfM[0];
     }
-    
+
     for( i = 0; i < psObject->nVertices; i++ )
     {
         psObject->dfXMin = MIN(psObject->dfXMin, psObject->padfX[i]);
@@ -1159,10 +1211,10 @@ SHPCreateObject( int nSHPType, int nShapeId, int nParts,
 
         psObject->panPartStart[0] = 0;
         psObject->panPartType[0] = SHPP_RING;
-        
+
         for( i = 0; i < nParts; i++ )
         {
-            if( psObject->panPartStart != NULL )
+            if( panPartStart != NULL )
                 psObject->panPartStart[i] = panPartStart[i];
 
             if( panPartType != NULL )
@@ -1225,7 +1277,7 @@ SHPCreateSimpleObject( int nSHPType, int nVertices,
     return( SHPCreateObject( nSHPType, -1, 0, NULL, NULL,
                              nVertices, padfX, padfY, padfZ, NULL ) );
 }
-                                  
+
 /************************************************************************/
 /*                           SHPWriteObject()                           */
 /*                                                                      */
@@ -1235,7 +1287,7 @@ SHPCreateSimpleObject( int nSHPType, int nVertices,
 
 int SHPAPI_CALL
 SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
-		      
+
 {
     unsigned int	       	nRecordOffset, nRecordSize=0;
     int i;
@@ -1249,7 +1301,7 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
 /*      Ensure that shape object matches the type of the file it is     */
 /*      being written to.                                               */
 /* -------------------------------------------------------------------- */
-    assert( psObject->nSHPType == psSHP->nShapeType 
+    assert( psObject->nSHPType == psSHP->nShapeType
             || psObject->nSHPType == SHPT_NULL );
 
 /* -------------------------------------------------------------------- */
@@ -1257,7 +1309,7 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
 /*      assertion, or if they are disabled, set the shapeid to -1       */
 /*      for appends.                                                    */
 /* -------------------------------------------------------------------- */
-    assert( nShapeId == -1 
+    assert( nShapeId == -1
             || (nShapeId >= 0 && nShapeId < psSHP->nRecords) );
 
     if( nShapeId != -1 && nShapeId >= psSHP->nRecords )
@@ -1268,33 +1320,45 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
 /* -------------------------------------------------------------------- */
     if( nShapeId == -1 && psSHP->nRecords+1 > psSHP->nMaxRecords )
     {
-        psSHP->nMaxRecords =(int) ( psSHP->nMaxRecords * 1.3 + 100);
+        int nNewMaxRecords = psSHP->nMaxRecords + psSHP->nMaxRecords / 3 + 100;
+        unsigned int* panRecOffsetNew;
+        unsigned int* panRecSizeNew;
+
+        panRecOffsetNew = (unsigned int *)
+            SfRealloc(psSHP->panRecOffset,sizeof(unsigned int) * nNewMaxRecords );
+        if( panRecOffsetNew == NULL )
+            return -1;
+        psSHP->panRecOffset = panRecOffsetNew;
+
+        panRecSizeNew = (unsigned int *)
+            SfRealloc(psSHP->panRecSize,sizeof(unsigned int) * nNewMaxRecords );
+        if( panRecSizeNew == NULL )
+            return -1;
+        psSHP->panRecSize = panRecSizeNew;
 
-        psSHP->panRecOffset = (unsigned int *) 
-            SfRealloc(psSHP->panRecOffset,sizeof(unsigned int) * psSHP->nMaxRecords );
-        psSHP->panRecSize = (unsigned int *) 
-            SfRealloc(psSHP->panRecSize,sizeof(unsigned int) * psSHP->nMaxRecords );
+        psSHP->nMaxRecords = nNewMaxRecords;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Initialize record.                                              */
 /* -------------------------------------------------------------------- */
-    pabyRec = (uchar *) malloc(psObject->nVertices * 4 * sizeof(double) 
+    pabyRec = (uchar *) malloc(psObject->nVertices * 4 * sizeof(double)
                                + psObject->nParts * 8 + 128);
-    
+    if( pabyRec == NULL )
+        return -1;
+
 /* -------------------------------------------------------------------- */
 /*  Extract vertices for a Polygon or Arc.				*/
 /* -------------------------------------------------------------------- */
     if( psObject->nSHPType == SHPT_POLYGON
         || psObject->nSHPType == SHPT_POLYGONZ
         || psObject->nSHPType == SHPT_POLYGONM
-        || psObject->nSHPType == SHPT_ARC 
+        || psObject->nSHPType == SHPT_ARC
         || psObject->nSHPType == SHPT_ARCZ
         || psObject->nSHPType == SHPT_ARCM
         || psObject->nSHPType == SHPT_MULTIPATCH )
     {
         int32		nPoints, nParts;
-        int    		i;
 
         nPoints = psObject->nVertices;
         nParts = psObject->nParts;
@@ -1344,7 +1408,7 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
 
             if( bBigEndian )
                 SwapWord( 8, pabyRec + nRecordSize );
-            
+
             if( bBigEndian )
                 SwapWord( 8, pabyRec + nRecordSize + 8 );
 
@@ -1361,7 +1425,7 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
             ByteCopy( &(psObject->dfZMin), pabyRec + nRecordSize, 8 );
             if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
             nRecordSize += 8;
-            
+
             ByteCopy( &(psObject->dfZMax), pabyRec + nRecordSize, 8 );
             if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
             nRecordSize += 8;
@@ -1380,16 +1444,16 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
         if( psObject->bMeasureIsUsed
             && (psObject->nSHPType == SHPT_POLYGONM
                 || psObject->nSHPType == SHPT_ARCM
-#ifndef DISABLE_MULTIPATCH_MEASURE            
+#ifndef DISABLE_MULTIPATCH_MEASURE
                 || psObject->nSHPType == SHPT_MULTIPATCH
-#endif            
+#endif
                 || psObject->nSHPType == SHPT_POLYGONZ
                 || psObject->nSHPType == SHPT_ARCZ) )
         {
             ByteCopy( &(psObject->dfMMin), pabyRec + nRecordSize, 8 );
             if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
             nRecordSize += 8;
-            
+
             ByteCopy( &(psObject->dfMMax), pabyRec + nRecordSize, 8 );
             if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
             nRecordSize += 8;
@@ -1411,7 +1475,6 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
              || psObject->nSHPType == SHPT_MULTIPOINTM )
     {
         int32		nPoints;
-        int    		i;
 
         nPoints = psObject->nVertices;
 
@@ -1419,7 +1482,7 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
 
         if( bBigEndian ) SwapWord( 4, &nPoints );
         ByteCopy( &nPoints, pabyRec + 44, 4 );
-	
+
         for( i = 0; i < psObject->nVertices; i++ )
         {
             ByteCopy( psObject->padfX + i, pabyRec + 48 + i*16, 8 );
@@ -1440,7 +1503,7 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
             ByteCopy( &(psObject->dfZMax), pabyRec + nRecordSize, 8 );
             if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
             nRecordSize += 8;
-            
+
             for( i = 0; i < psObject->nVertices; i++ )
             {
                 ByteCopy( psObject->padfZ + i, pabyRec + nRecordSize, 8 );
@@ -1460,7 +1523,7 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
             ByteCopy( &(psObject->dfMMax), pabyRec + nRecordSize, 8 );
             if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
             nRecordSize += 8;
-            
+
             for( i = 0; i < psObject->nVertices; i++ )
             {
                 ByteCopy( psObject->padfM + i, pabyRec + nRecordSize, 8 );
@@ -1484,14 +1547,14 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
         if( bBigEndian ) SwapWord( 8, pabyRec + 20 );
 
         nRecordSize = 28;
-        
+
         if( psObject->nSHPType == SHPT_POINTZ )
         {
             ByteCopy( psObject->padfZ, pabyRec + nRecordSize, 8 );
             if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
             nRecordSize += 8;
         }
-        
+
         if( psObject->bMeasureIsUsed
             && (psObject->nSHPType == SHPT_POINTZ
                 || psObject->nSHPType == SHPT_POINTM) )
@@ -1527,7 +1590,7 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
         if( nExpectedSize < psSHP->nFileSize ) // due to unsigned int overflow
         {
             char str[128];
-            sprintf( str, "Failed to write shape object. "
+            snprintf( str, sizeof(str), "Failed to write shape object. "
                      "File size cannot reach %u + %u.",
                      psSHP->nFileSize, nRecordSize );
             psSHP->sHooks.Error( str );
@@ -1542,7 +1605,7 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
     {
         nRecordOffset = psSHP->panRecOffset[nShapeId];
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Set the shape type, record number, and record size.             */
 /* -------------------------------------------------------------------- */
@@ -1573,7 +1636,7 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
         free( pabyRec );
         return -1;
     }
-    
+
     free( pabyRec );
 
     if( bExtendFile )
@@ -1704,14 +1767,14 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
 /* -------------------------------------------------------------------- */
     if( psSHP->panRecOffset[hEntity] == 0 && psSHP->fpSHX != NULL )
     {
-        int32       nOffset, nLength;
+        unsigned int       nOffset, nLength;
 
         if( psSHP->sHooks.FSeek( psSHP->fpSHX, 100 + 8 * hEntity, 0 ) != 0 ||
             psSHP->sHooks.FRead( &nOffset, 1, 4, psSHP->fpSHX ) != 4 ||
             psSHP->sHooks.FRead( &nLength, 1, 4, psSHP->fpSHX ) != 4 )
         {
             char str[128];
-            sprintf( str,
+            snprintf( str, sizeof(str),
                     "Error in fseek()/fread() reading object from .shx file at offset %d",
                     100 + 8 * hEntity);
 
@@ -1721,6 +1784,25 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         if( !bBigEndian ) SwapWord( 4, &nOffset );
         if( !bBigEndian ) SwapWord( 4, &nLength );
 
+        if( nOffset > (unsigned int)INT_MAX )
+        {
+            char str[128];
+            snprintf( str, sizeof(str),
+                    "Invalid offset for entity %d", hEntity);
+
+            psSHP->sHooks.Error( str );
+            return NULL;
+        }
+        if( nLength > (unsigned int)(INT_MAX / 2 - 4) )
+        {
+            char str[128];
+            snprintf( str, sizeof(str),
+                    "Invalid length for entity %d", hEntity);
+
+            psSHP->sHooks.Error( str );
+            return NULL;
+        }
+
         psSHP->panRecOffset[hEntity] = nOffset*2;
         psSHP->panRecSize[hEntity] = nLength*2;
     }
@@ -1731,23 +1813,55 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
     nEntitySize = psSHP->panRecSize[hEntity]+8;
     if( nEntitySize > psSHP->nBufSize )
     {
-        psSHP->pabyRec = (uchar *) SfRealloc(psSHP->pabyRec,nEntitySize);
-        if (psSHP->pabyRec == NULL)
+        uchar* pabyRecNew;
+        int nNewBufSize = nEntitySize;
+        if( nNewBufSize < INT_MAX - nNewBufSize / 3 )
+            nNewBufSize += nNewBufSize / 3;
+        else
+            nNewBufSize = INT_MAX;
+
+        /* Before allocating too much memory, check that the file is big enough */
+        if( nEntitySize >= 10 * 1024 * 1024 &&
+            (psSHP->panRecOffset[hEntity] >= psSHP->nFileSize ||
+             (unsigned int)nEntitySize > psSHP->nFileSize - psSHP->panRecOffset[hEntity]) )
         {
-            char szError[200];
+            /* We do as is we didn't trust the file size in the header */
+            SAOffset nFileSize;
+            psSHP->sHooks.FSeek( psSHP->fpSHP, 0, 2 );
+            nFileSize = psSHP->sHooks.FTell(psSHP->fpSHP);
+            if( nFileSize >= 0xFFFFFFFFU )
+                psSHP->nFileSize = 0xFFFFFFFFU;
+            else
+                psSHP->nFileSize = (unsigned int)nFileSize;
 
-            /* Reallocate previous successful size for following features */
-            psSHP->pabyRec = (uchar *) malloc(psSHP->nBufSize);
+            if( psSHP->panRecOffset[hEntity] >= psSHP->nFileSize ||
+                (unsigned int)nEntitySize > psSHP->nFileSize - psSHP->panRecOffset[hEntity] )
+            {
+                char str[128];
+                snprintf( str, sizeof(str),
+                         "Error in fread() reading object of size %u at offset %u from .shp file",
+                         nEntitySize, psSHP->panRecOffset[hEntity] );
 
-            sprintf( szError, 
-                     "Not enough memory to allocate requested memory (nBufSize=%d). "
-                     "Probably broken SHP file", psSHP->nBufSize );
+                psSHP->sHooks.Error( str );
+                return NULL;
+            }
+        }
+
+        pabyRecNew = (uchar *) SfRealloc(psSHP->pabyRec,nNewBufSize);
+        if (pabyRecNew == NULL)
+        {
+            char szError[200];
+
+            snprintf( szError, sizeof(szError),
+                     "Not enough memory to allocate requested memory (nNewBufSize=%d). "
+                     "Probably broken SHP file", nNewBufSize);
             psSHP->sHooks.Error( szError );
             return NULL;
         }
 
         /* Only set new buffer size after successful alloc */
-        psSHP->nBufSize = nEntitySize;
+        psSHP->pabyRec = pabyRecNew;
+        psSHP->nBufSize = nNewBufSize;
     }
 
     /* In case we were not able to reallocate the buffer on a previous step */
@@ -1766,7 +1880,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
          * for example to detect if file is truncated.
          */
         char str[128];
-        sprintf( str,
+        snprintf( str, sizeof(str),
                  "Error in fseek() reading object from .shp file at offset %u",
                  psSHP->panRecOffset[hEntity]);
 
@@ -1774,7 +1888,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         return NULL;
     }
 
-    nBytesRead = psSHP->sHooks.FRead( psSHP->pabyRec, 1, nEntitySize, psSHP->fpSHP );
+    nBytesRead = (int)psSHP->sHooks.FRead( psSHP->pabyRec, 1, nEntitySize, psSHP->fpSHP );
 
     /* Special case for a shapefile whose .shx content length field is not equal */
     /* to the content length field of the .shp, which is a violation of "The */
@@ -1782,16 +1896,18 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
     /* file record header." (http://www.esri.com/library/whitepapers/pdfs/shapefile.pdf, page 24) */
     /* Actually in that case the .shx content length is equal to the .shp content length + */
     /* 4 (16 bit words), representing the 8 bytes of the record header... */
-    if( nBytesRead == nEntitySize - 8 )
+    if( nBytesRead >= 8 && nBytesRead == nEntitySize - 8 )
     {
         /* Do a sanity check */
         int nSHPContentLength;
         memcpy( &nSHPContentLength, psSHP->pabyRec + 4, 4 );
         if( !bBigEndian ) SwapWord( 4, &(nSHPContentLength) );
-        if( 2 * nSHPContentLength + 8 != nBytesRead )
+        if( nSHPContentLength < 0 ||
+            nSHPContentLength > INT_MAX / 2 - 4 ||
+            2 * nSHPContentLength + 8 != nBytesRead )
         {
             char str[128];
-            sprintf( str,
+            snprintf( str, sizeof(str),
                     "Sanity check failed when trying to recover from inconsistent .shx/.shp with shape %d",
                     hEntity );
 
@@ -1806,7 +1922,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
          * for example to detect if file is truncated.
          */
         char str[128];
-        sprintf( str,
+        snprintf( str, sizeof(str),
                  "Error in fread() reading object of size %u at offset %u from .shp file",
                  nEntitySize, psSHP->panRecOffset[hEntity] );
 
@@ -1818,7 +1934,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
     {
         snprintf(szErrorMsg, sizeof(szErrorMsg),
                  "Corrupted .shp file : shape %d : nEntitySize = %d",
-                 hEntity, nEntitySize); 
+                 hEntity, nEntitySize);
         psSHP->sHooks.Error( szErrorMsg );
         return NULL;
     }
@@ -1867,7 +1983,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         {
             snprintf(szErrorMsg, sizeof(szErrorMsg),
                      "Corrupted .shp file : shape %d : nEntitySize = %d",
-                     hEntity, nEntitySize); 
+                     hEntity, nEntitySize);
             psSHP->sHooks.Error( szErrorMsg );
             SHPDestroyObject(psShape);
             return NULL;
@@ -1906,7 +2022,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             SHPDestroyObject(psShape);
             return NULL;
         }
-        
+
         /* With the previous checks on nPoints and nParts, */
         /* we should not overflow here and after */
         /* since 50 M * (16 + 8 + 8) = 1 600 MB */
@@ -1977,11 +2093,12 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             /* We check that the offset is inside the vertex array */
             if (psShape->panPartStart[i] < 0
                 || (psShape->panPartStart[i] >= psShape->nVertices
-                    && psShape->nVertices > 0) )
+                    && psShape->nVertices > 0)
+                || (psShape->panPartStart[i] > 0 && psShape->nVertices == 0) )
             {
                 snprintf(szErrorMsg, sizeof(szErrorMsg),
                          "Corrupted .shp file : shape %d : panPartStart[%d] = %d, nVertices = %d",
-                         hEntity, i, psShape->panPartStart[i], psShape->nVertices); 
+                         hEntity, i, psShape->panPartStart[i], psShape->nVertices);
                 psSHP->sHooks.Error( szErrorMsg );
                 SHPDestroyObject(psShape);
                 return NULL;
@@ -1990,7 +2107,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             {
                 snprintf(szErrorMsg, sizeof(szErrorMsg),
                          "Corrupted .shp file : shape %d : panPartStart[%d] = %d, panPartStart[%d] = %d",
-                         hEntity, i, psShape->panPartStart[i], i - 1, psShape->panPartStart[i - 1]); 
+                         hEntity, i, psShape->panPartStart[i], i - 1, psShape->panPartStart[i - 1]);
                 psSHP->sHooks.Error( szErrorMsg );
                 SHPDestroyObject(psShape);
                 return NULL;
@@ -2031,7 +2148,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         }
 
         nOffset += 16*nPoints;
-        
+
 /* -------------------------------------------------------------------- */
 /*      If we have a Z coordinate, collect that now.                    */
 /* -------------------------------------------------------------------- */
@@ -2103,7 +2220,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         {
             snprintf(szErrorMsg, sizeof(szErrorMsg),
                      "Corrupted .shp file : shape %d : nEntitySize = %d",
-                     hEntity, nEntitySize); 
+                     hEntity, nEntitySize);
             psSHP->sHooks.Error( szErrorMsg );
             SHPDestroyObject(psShape);
             return NULL;
@@ -2117,7 +2234,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         {
             snprintf(szErrorMsg, sizeof(szErrorMsg),
                      "Corrupted .shp file : shape %d : nPoints = %d",
-                     hEntity, nPoints); 
+                     hEntity, nPoints);
             psSHP->sHooks.Error( szErrorMsg );
             SHPDestroyObject(psShape);
             return NULL;
@@ -2132,12 +2249,12 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         {
             snprintf(szErrorMsg, sizeof(szErrorMsg),
                      "Corrupted .shp file : shape %d : nPoints = %d, nEntitySize = %d",
-                     hEntity, nPoints, nEntitySize); 
+                     hEntity, nPoints, nEntitySize);
             psSHP->sHooks.Error( szErrorMsg );
             SHPDestroyObject(psShape);
             return NULL;
         }
-        
+
         if( psShape->bFastModeReadObject )
         {
             int nObjectBufSize = 4 * sizeof(double) * nPoints;
@@ -2246,7 +2363,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
              || psShape->nSHPType == SHPT_POINTZ )
     {
         int	nOffset;
-        
+
         psShape->nVertices = 1;
         if( psShape->bFastModeReadObject )
         {
@@ -2269,7 +2386,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         {
             snprintf(szErrorMsg, sizeof(szErrorMsg),
                      "Corrupted .shp file : shape %d : nEntitySize = %d",
-                     hEntity, nEntitySize); 
+                     hEntity, nEntitySize);
             psSHP->sHooks.Error( szErrorMsg );
             SHPDestroyObject(psShape);
             return NULL;
@@ -2281,16 +2398,16 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         if( bBigEndian ) SwapWord( 8, psShape->padfY );
 
         nOffset = 20 + 8;
-        
+
 /* -------------------------------------------------------------------- */
 /*      If we have a Z coordinate, collect that now.                    */
 /* -------------------------------------------------------------------- */
         if( psShape->nSHPType == SHPT_POINTZ )
         {
             memcpy( psShape->padfZ, psSHP->pabyRec + nOffset, 8 );
-        
+
             if( bBigEndian ) SwapWord( 8, psShape->padfZ );
-            
+
             nOffset += 8;
         }
 
@@ -2303,7 +2420,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         if( nEntitySize >= nOffset + 8 )
         {
             memcpy( psShape->padfM, psSHP->pabyRec + nOffset, 8 );
-        
+
             if( bBigEndian ) SwapWord( 8, psShape->padfM );
             psShape->bMeasureIsUsed = TRUE;
         }
@@ -2345,7 +2462,7 @@ SHPTypeName( int nSHPType )
 
       case SHPT_MULTIPOINT:
         return "MultiPoint";
-        
+
       case SHPT_POINTZ:
         return "PointZ";
 
@@ -2357,7 +2474,7 @@ SHPTypeName( int nSHPType )
 
       case SHPT_MULTIPOINTZ:
         return "MultiPointZ";
-        
+
       case SHPT_POINTM:
         return "PointM";
 
@@ -2390,7 +2507,7 @@ SHPPartTypeName( int nPartType )
     {
       case SHPP_TRISTRIP:
         return "TriangleStrip";
-        
+
       case SHPP_TRIFAN:
         return "TriangleFan";
 
@@ -2427,7 +2544,7 @@ SHPDestroyObject( SHPObject * psShape )
         psShape->bFastModeReadObject = FALSE;
         return;
     }
-    
+
     if( psShape->padfX != NULL )
         free( psShape->padfX );
     if( psShape->padfY != NULL )
@@ -2501,14 +2618,14 @@ SHPRewindObject( CPL_UNUSED SHPHandle hSHP,
 
             if( iCheckRing == iOpRing )
                 continue;
-            
+
             nVertStart = psObject->panPartStart[iCheckRing];
 
             if( iCheckRing == psObject->nParts-1 )
-                nVertCount = psObject->nVertices 
+                nVertCount = psObject->nVertices
                     - psObject->panPartStart[iCheckRing];
             else
-                nVertCount = psObject->panPartStart[iCheckRing+1] 
+                nVertCount = psObject->panPartStart[iCheckRing+1]
                     - psObject->panPartStart[iCheckRing];
 
             for( iEdge = 0; iEdge < nVertCount; iEdge++ )
@@ -2522,7 +2639,7 @@ SHPRewindObject( CPL_UNUSED SHPHandle hSHP,
 
                 /* Rule #1:
                  * Test whether the edge 'straddles' the horizontal ray from the test point (dfTestY,dfTestY)
-                 * The rule #1 also excludes edges collinear with the ray.
+                 * The rule #1 also excludes edges colinear with the ray.
                  */
                 if ( ( psObject->padfY[iEdge+nVertStart] < dfTestY
                        && dfTestY <= psObject->padfY[iNext+nVertStart] )
@@ -2532,9 +2649,9 @@ SHPRewindObject( CPL_UNUSED SHPHandle hSHP,
                     /* Rule #2:
                      * Test if edge-ray intersection is on the right from the test point (dfTestY,dfTestY)
                      */
-                    double const intersect = 
+                    double const intersect =
                         ( psObject->padfX[iEdge+nVertStart]
-                          + ( dfTestY - psObject->padfY[iEdge+nVertStart] ) 
+                          + ( dfTestY - psObject->padfY[iEdge+nVertStart] )
                           / ( psObject->padfY[iNext+nVertStart] - psObject->padfY[iEdge+nVertStart] )
                           * ( psObject->padfX[iNext+nVertStart] - psObject->padfX[iEdge+nVertStart] ) );
 
@@ -2542,7 +2659,7 @@ SHPRewindObject( CPL_UNUSED SHPHandle hSHP,
                     {
                         bInner = !bInner;
                     }
-                }    
+                }
             }
         } /* for iCheckRing */
 
@@ -2555,7 +2672,7 @@ SHPRewindObject( CPL_UNUSED SHPHandle hSHP,
         if( iOpRing == psObject->nParts-1 )
             nVertCount = psObject->nVertices - psObject->panPartStart[iOpRing];
         else
-            nVertCount = psObject->panPartStart[iOpRing+1] 
+            nVertCount = psObject->panPartStart[iOpRing+1]
                 - psObject->panPartStart[iOpRing];
 
         if (nVertCount < 2)
@@ -2583,13 +2700,13 @@ SHPRewindObject( CPL_UNUSED SHPHandle hSHP,
 
                 /* Swap X */
                 dfSaved = psObject->padfX[nVertStart+i];
-                psObject->padfX[nVertStart+i] = 
+                psObject->padfX[nVertStart+i] =
                     psObject->padfX[nVertStart+nVertCount-i-1];
                 psObject->padfX[nVertStart+nVertCount-i-1] = dfSaved;
 
                 /* Swap Y */
                 dfSaved = psObject->padfY[nVertStart+i];
-                psObject->padfY[nVertStart+i] = 
+                psObject->padfY[nVertStart+i] =
                     psObject->padfY[nVertStart+nVertCount-i-1];
                 psObject->padfY[nVertStart+nVertCount-i-1] = dfSaved;
 
@@ -2597,7 +2714,7 @@ SHPRewindObject( CPL_UNUSED SHPHandle hSHP,
                 if( psObject->padfZ )
                 {
                     dfSaved = psObject->padfZ[nVertStart+i];
-                    psObject->padfZ[nVertStart+i] = 
+                    psObject->padfZ[nVertStart+i] =
                         psObject->padfZ[nVertStart+nVertCount-i-1];
                     psObject->padfZ[nVertStart+nVertCount-i-1] = dfSaved;
                 }
@@ -2606,7 +2723,7 @@ SHPRewindObject( CPL_UNUSED SHPHandle hSHP,
                 if( psObject->padfM )
                 {
                     dfSaved = psObject->padfM[nVertStart+i];
-                    psObject->padfM[nVertStart+i] = 
+                    psObject->padfM[nVertStart+i] =
                         psObject->padfM[nVertStart+nVertCount-i-1];
                     psObject->padfM[nVertStart+nVertCount-i-1] = dfSaved;
                 }
diff --git a/ogr/ogrsf_frmts/shape/shptree.c b/ogr/ogrsf_frmts/shape/shptree.c
index ab98c61..b6f1b85 100644
--- a/ogr/ogrsf_frmts/shape/shptree.c
+++ b/ogr/ogrsf_frmts/shape/shptree.c
@@ -14,7 +14,7 @@
  * option is discussed in more detail in shapelib.html.
  *
  * --
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * to deal in the Software without restriction, including without limitation
@@ -32,61 +32,7 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- ******************************************************************************
- *
- * $Log: shptree.c,v $
- * Revision 1.17  2012-01-27 21:09:26  fwarmerdam
- * optimize .qix output (gdal #4472)
- *
- * Revision 1.16  2011-12-11 22:26:46  fwarmerdam
- * upgrade .qix access code to use SAHooks (gdal #3365)
- *
- * Revision 1.15  2011-07-24 05:59:25  fwarmerdam
- * minimize use of CPLError in favor of SAHooks.Error()
- *
- * Revision 1.14  2010-08-27 23:43:27  fwarmerdam
- * add SHPAPI_CALL attribute in code
- *
- * Revision 1.13  2010-06-29 05:50:15  fwarmerdam
- * fix sign of Z/M comparisons in SHPCheckObjectContained (#2223)
- *
- * Revision 1.12  2008-11-12 15:39:50  fwarmerdam
- * improve safety in face of buggy .shp file.
- *
- * Revision 1.11  2007/10/27 03:31:14  fwarmerdam
- * limit default depth of tree to 12 levels (gdal ticket #1594)
- *
- * Revision 1.10  2005/01/03 22:30:13  fwarmerdam
- * added support for saved quadtrees
- *
- * Revision 1.9  2003/01/28 15:53:41  warmerda
- * Avoid build warnings.
- *
- * Revision 1.8  2002/05/07 13:07:45  warmerda
- * use qsort() - patch from Bernhard Herzog
- *
- * Revision 1.7  2002/01/15 14:36:07  warmerda
- * updated email address
- *
- * Revision 1.6  2001/05/23 13:36:52  warmerda
- * added use of SHPAPI_CALL
- *
- * Revision 1.5  1999/11/05 14:12:05  warmerda
- * updated license terms
- *
- * Revision 1.4  1999/06/02 18:24:21  warmerda
- * added trimming code
- *
- * Revision 1.3  1999/06/02 17:56:12  warmerda
- * added quad'' subnode support for trees
- *
- * Revision 1.2  1999/05/18 19:11:11  warmerda
- * Added example searching capability
- *
- * Revision 1.1  1999/05/18 17:49:20  warmerda
- * New
- *
- */
+ *******************************************************************************/
 
 #include "shapefil.h"
 
@@ -239,6 +185,7 @@ SHPTree SHPAPI_CALL1(*)
     psTree->psRoot = SHPTreeNodeCreate( padfBoundsMin, padfBoundsMax );
     if( NULL == psTree->psRoot )
     {
+        free( psTree );
         return NULL;
     }
 
@@ -247,13 +194,10 @@ SHPTree SHPAPI_CALL1(*)
 /*      use the bounds of the provided file otherwise the create        */
 /*      function will have already set the bounds.                      */
 /* -------------------------------------------------------------------- */
-    assert( NULL != psTree );
-    assert( NULL != psTree->psRoot );
-	
     if( padfBoundsMin == NULL )
     {
         SHPGetInfo( hSHP, NULL, NULL,
-                    psTree->psRoot->adfBoundsMin, 
+                    psTree->psRoot->adfBoundsMin,
                     psTree->psRoot->adfBoundsMax );
     }
 
@@ -263,13 +207,13 @@ SHPTree SHPAPI_CALL1(*)
     if( hSHP != NULL )
     {
         int	iShape, nShapeCount;
-        
+
         SHPGetInfo( hSHP, &nShapeCount, NULL, NULL, NULL );
 
         for( iShape = 0; iShape < nShapeCount; iShape++ )
         {
             SHPObject	*psShape;
-            
+
             psShape = SHPReadObject( hSHP, iShape );
             if( psShape != NULL )
             {
@@ -277,7 +221,7 @@ SHPTree SHPAPI_CALL1(*)
                 SHPDestroyObject( psShape );
             }
         }
-    }        
+    }
 
     return psTree;
 }
@@ -290,7 +234,7 @@ static void SHPDestroyTreeNode( SHPTreeNode * psTreeNode )
 
 {
     int		i;
-    
+
 	assert( NULL != psTreeNode );
 
     for( i = 0; i < psTreeNode->nSubNodes; i++ )
@@ -298,7 +242,7 @@ static void SHPDestroyTreeNode( SHPTreeNode * psTreeNode )
         if( psTreeNode->apsSubNode[i] != NULL )
             SHPDestroyTreeNode( psTreeNode->apsSubNode[i] );
     }
-    
+
     if( psTreeNode->panShapeIds != NULL )
         free( psTreeNode->panShapeIds );
 
@@ -346,7 +290,7 @@ SHPCheckBoundsOverlap( double * padfBox1Min, double * padfBox1Max,
     {
         if( padfBox2Max[iDim] < padfBox1Min[iDim] )
             return FALSE;
-        
+
         if( padfBox1Max[iDim] < padfBox2Min[iDim] )
             return FALSE;
     }
@@ -367,18 +311,18 @@ static int SHPCheckObjectContained( SHPObject * psObject, int nDimension,
     if( psObject->dfXMin < padfBoundsMin[0]
         || psObject->dfXMax > padfBoundsMax[0] )
         return FALSE;
-    
+
     if( psObject->dfYMin < padfBoundsMin[1]
         || psObject->dfYMax > padfBoundsMax[1] )
         return FALSE;
 
     if( nDimension == 2 )
         return TRUE;
-    
+
     if( psObject->dfZMin < padfBoundsMin[2]
         || psObject->dfZMax > padfBoundsMax[2] )
         return FALSE;
-        
+
     if( nDimension == 3 )
         return TRUE;
 
@@ -396,7 +340,7 @@ static int SHPCheckObjectContained( SHPObject * psObject, int nDimension,
 /*      longest dimension.                                              */
 /************************************************************************/
 
-void SHPAPI_CALL
+static void
 SHPTreeSplitBounds( double *padfBoundsMinIn, double *padfBoundsMaxIn,
                     double *padfBoundsMin1, double * padfBoundsMax1,
                     double *padfBoundsMin2, double * padfBoundsMax2 )
@@ -410,7 +354,7 @@ SHPTreeSplitBounds( double *padfBoundsMinIn, double *padfBoundsMaxIn,
     memcpy( padfBoundsMax1, padfBoundsMaxIn, sizeof(double) * 4 );
     memcpy( padfBoundsMin2, padfBoundsMinIn, sizeof(double) * 4 );
     memcpy( padfBoundsMax2, padfBoundsMaxIn, sizeof(double) * 4 );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Split in X direction.                                           */
 /* -------------------------------------------------------------------- */
@@ -445,9 +389,9 @@ SHPTreeNodeAddShapeId( SHPTreeNode * psTreeNode, SHPObject * psObject,
 
 {
     int		i;
-    
+
 /* -------------------------------------------------------------------- */
-/*      If there are subnodes, then consider wiether this object        */
+/*      If there are subnodes, then consider whether this object        */
 /*      will fit in them.                                               */
 /* -------------------------------------------------------------------- */
     if( nMaxDepth > 1 && psTreeNode->nSubNodes > 0 )
@@ -564,7 +508,7 @@ SHPTreeNodeAddShapeId( SHPTreeNode * psTreeNode, SHPObject * psObject,
 /* -------------------------------------------------------------------- */
     psTreeNode->nShapeCount++;
 
-    psTreeNode->panShapeIds = (int *) 
+    psTreeNode->panShapeIds = (int *)
         SfRealloc( psTreeNode->panShapeIds,
                    sizeof(int) * psTreeNode->nShapeCount );
     psTreeNode->panShapeIds[psTreeNode->nShapeCount-1] = psObject->nShapeId;
@@ -604,7 +548,7 @@ SHPTreeAddShapeId( SHPTree * psTree, SHPObject * psObject )
 /*      tree node by tree node basis.                                   */
 /************************************************************************/
 
-void SHPAPI_CALL
+static void
 SHPTreeCollectShapeIds( SHPTree *hTree, SHPTreeNode * psTreeNode,
                         double * padfBoundsMin, double * padfBoundsMax,
                         int * pnShapeCount, int * pnMaxShapes,
@@ -612,7 +556,7 @@ SHPTreeCollectShapeIds( SHPTree *hTree, SHPTreeNode * psTreeNode,
 
 {
     int		i;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Does this node overlap the area of interest at all?  If not,    */
 /*      return without adding to the list at all.                       */
@@ -641,7 +585,7 @@ SHPTreeCollectShapeIds( SHPTree *hTree, SHPTreeNode * psTreeNode,
     {
         (*ppanShapeList)[(*pnShapeCount)++] = psTreeNode->panShapeIds[i];
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Recurse to subnodes if they exist.                              */
 /* -------------------------------------------------------------------- */
@@ -694,7 +638,8 @@ SHPTreeFindLikelyShapes( SHPTree * hTree,
 /*      Sort the id array                                               */
 /* -------------------------------------------------------------------- */
 
-    qsort(panShapeList, *pnShapeCount, sizeof(int), compare_ints);
+    if( panShapeList != NULL )
+        qsort(panShapeList, *pnShapeCount, sizeof(int), compare_ints);
 
     return panShapeList;
 }
@@ -702,7 +647,7 @@ SHPTreeFindLikelyShapes( SHPTree * hTree,
 /************************************************************************/
 /*                          SHPTreeNodeTrim()                           */
 /*                                                                      */
-/*      This is the recurve version of SHPTreeTrimExtraNodes() that     */
+/*      This is the recursive version of SHPTreeTrimExtraNodes() that   */
 /*      walks the tree cleaning it up.                                  */
 /************************************************************************/
 
@@ -844,7 +789,7 @@ void SHPCloseDiskTree( SHPTreeDiskHandle hDiskTree )
 
 static int
 SHPSearchDiskTreeNode( SHPTreeDiskHandle hDiskTree, double *padfBoundsMin, double *padfBoundsMax,
-                       int **ppanResultBuffer, int *pnBufferMax, 
+                       int **ppanResultBuffer, int *pnBufferMax,
                        int *pnResultCount, int bNeedSwap, int nRecLevel )
 
 {
@@ -869,7 +814,7 @@ SHPSearchDiskTreeNode( SHPTreeDiskHandle hDiskTree, double *padfBoundsMin, doubl
         SwapWord( 8, adfNodeBoundsMax + 0 );
         SwapWord( 8, adfNodeBoundsMax + 1 );
     }
-      
+
     nFReadAcc += (int)hDiskTree->sHooks.FRead( &numshapes, 4, 1, hDiskTree->fpQIX );
     if ( bNeedSwap ) SwapWord ( 4, &numshapes );
 
@@ -898,7 +843,7 @@ SHPSearchDiskTreeNode( SHPTreeDiskHandle hDiskTree, double *padfBoundsMin, doubl
 /*      If we don't overlap this node at all, we can just fseek()       */
 /*      pass this node info and all subnodes.                           */
 /* -------------------------------------------------------------------- */
-    if( !SHPCheckBoundsOverlap( adfNodeBoundsMin, adfNodeBoundsMax, 
+    if( !SHPCheckBoundsOverlap( adfNodeBoundsMin, adfNodeBoundsMax,
                                 padfBoundsMin, padfBoundsMax, 2 ) )
     {
         offset += numshapes*sizeof(int) + sizeof(int);
@@ -909,7 +854,7 @@ SHPSearchDiskTreeNode( SHPTreeDiskHandle hDiskTree, double *padfBoundsMin, doubl
 /* -------------------------------------------------------------------- */
 /*      Add all the shapeids at this node to our list.                  */
 /* -------------------------------------------------------------------- */
-    if(numshapes > 0) 
+    if(numshapes > 0)
     {
         if( *pnResultCount + numshapes > (unsigned int)*pnBufferMax )
         {
@@ -945,8 +890,8 @@ SHPSearchDiskTreeNode( SHPTreeDiskHandle hDiskTree, double *padfBoundsMin, doubl
                 SwapWord( 4, *ppanResultBuffer + *pnResultCount + i );
         }
 
-        *pnResultCount += numshapes; 
-    } 
+        *pnResultCount += numshapes;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Process the subnodes.                                           */
@@ -965,8 +910,8 @@ SHPSearchDiskTreeNode( SHPTreeDiskHandle hDiskTree, double *padfBoundsMin, doubl
 
     for(i=0; i<numsubnodes; i++)
     {
-        if( !SHPSearchDiskTreeNode( hDiskTree, padfBoundsMin, padfBoundsMax, 
-                                    ppanResultBuffer, pnBufferMax, 
+        if( !SHPSearchDiskTreeNode( hDiskTree, padfBoundsMin, padfBoundsMax,
+                                    ppanResultBuffer, pnBufferMax,
                                     pnResultCount, bNeedSwap, nRecLevel + 1 ) )
             return FALSE;
     }
@@ -1001,8 +946,8 @@ SAOffset SHPTreeSeekLibc( SAFile file, SAOffset offset, int whence )
 /*                         SHPSearchDiskTree()                          */
 /************************************************************************/
 
-int SHPAPI_CALL1(*) 
-SHPSearchDiskTree( FILE *fp, 
+int SHPAPI_CALL1(*)
+SHPSearchDiskTree( FILE *fp,
                    double *padfBoundsMin, double *padfBoundsMax,
                    int *pnShapeCount )
 {
@@ -1024,9 +969,9 @@ SHPSearchDiskTree( FILE *fp,
 /*                       SHPSearchDiskTreeEx()                         */
 /************************************************************************/
 
-int* SHPSearchDiskTreeEx( SHPTreeDiskHandle hDiskTree, 
-                     double *padfBoundsMin, double *padfBoundsMax,
-                     int *pnShapeCount )
+int* SHPSearchDiskTreeEx( SHPTreeDiskHandle hDiskTree,
+                          double *padfBoundsMin, double *padfBoundsMax,
+                          int *pnShapeCount )
 
 {
     int i, bNeedSwap, nBufferMax = 0;
@@ -1060,10 +1005,10 @@ int* SHPSearchDiskTreeEx( SHPTreeDiskHandle hDiskTree,
         bNeedSwap = TRUE;
 
 /* -------------------------------------------------------------------- */
-/*      Search through root node and it's decendents.                   */
+/*      Search through root node and it's descendants.                  */
 /* -------------------------------------------------------------------- */
-    if( !SHPSearchDiskTreeNode( hDiskTree, padfBoundsMin, padfBoundsMax, 
-                                &panResultBuffer, &nBufferMax, 
+    if( !SHPSearchDiskTreeNode( hDiskTree, padfBoundsMin, padfBoundsMax,
+                                &panResultBuffer, &nBufferMax,
                                 pnShapeCount, bNeedSwap, 0 ) )
     {
         if( panResultBuffer != NULL )
@@ -1074,12 +1019,14 @@ int* SHPSearchDiskTreeEx( SHPTreeDiskHandle hDiskTree,
 /* -------------------------------------------------------------------- */
 /*      Sort the id array                                               */
 /* -------------------------------------------------------------------- */
-    qsort(panResultBuffer, *pnShapeCount, sizeof(int), compare_ints);
 
     /* To distinguish between empty intersection from error case */
     if( panResultBuffer == NULL )
         panResultBuffer = (int*) calloc(1, sizeof(int));
-    
+    else
+        qsort(panResultBuffer, *pnShapeCount, sizeof(int), compare_ints);
+
+
     return panResultBuffer;
 }
 
@@ -1091,16 +1038,16 @@ int* SHPSearchDiskTreeEx( SHPTreeDiskHandle hDiskTree,
 /*      seek past them all efficiently.                                 */
 /************************************************************************/
 
-static int SHPGetSubNodeOffset( SHPTreeNode *node) 
+static int SHPGetSubNodeOffset( SHPTreeNode *node)
 {
     int i;
-    long offset=0;
+    int offset=0;
 
-    for(i=0; i<node->nSubNodes; i++ ) 
+    for(i=0; i<node->nSubNodes; i++ )
     {
-        if(node->apsSubNode[i]) 
+        if(node->apsSubNode[i])
         {
-            offset += 4*sizeof(double) 
+            offset += 4*sizeof(double)
                 + (node->apsSubNode[i]->nShapeCount+3)*sizeof(int);
             offset += SHPGetSubNodeOffset(node->apsSubNode[i]);
         }
@@ -1113,7 +1060,7 @@ static int SHPGetSubNodeOffset( SHPTreeNode *node)
 /*                          SHPWriteTreeNode()                          */
 /************************************************************************/
 
-static void SHPWriteTreeNode( SAFile fp, SHPTreeNode *node, SAHooks* psHooks) 
+static void SHPWriteTreeNode( SAFile fp, SHPTreeNode *node, SAHooks* psHooks)
 {
     int i,j;
     int offset;
@@ -1121,8 +1068,8 @@ static void SHPWriteTreeNode( SAFile fp, SHPTreeNode *node, SAHooks* psHooks)
     assert( NULL != node );
 
     offset = SHPGetSubNodeOffset(node);
-  
-    pabyRec = (unsigned char *) 
+
+    pabyRec = (unsigned char *)
         malloc(sizeof(double) * 4
                + (3 * sizeof(int)) + (node->nShapeCount * sizeof(int)) );
     if( NULL == pabyRec )
@@ -1144,13 +1091,14 @@ static void SHPWriteTreeNode( SAFile fp, SHPTreeNode *node, SAHooks* psHooks)
 
     memcpy( pabyRec+36, &node->nShapeCount, 4);
     j = node->nShapeCount * sizeof(int);
-    memcpy( pabyRec+40, node->panShapeIds, j);
+    if( j )
+        memcpy( pabyRec+40, node->panShapeIds, j);
     memcpy( pabyRec+j+40, &node->nSubNodes, 4);
 
     psHooks->FWrite( pabyRec, 44+j, 1, fp );
     free (pabyRec);
-  
-    for(i=0; i<node->nSubNodes; i++ ) 
+
+    for(i=0; i<node->nSubNodes; i++ )
     {
         if(node->apsSubNode[i])
             SHPWriteTreeNode( fp, node->apsSubNode[i], psHooks);
@@ -1187,12 +1135,12 @@ int SHPWriteTreeLL(SHPTree *tree, const char *filename, SAHooks* psHooks )
         SASetupDefaultHooks( &sHooks );
         psHooks = &sHooks;
     }
-  
+
 /* -------------------------------------------------------------------- */
 /*      Open the output file.                                           */
 /* -------------------------------------------------------------------- */
     fp = psHooks->FOpen(filename, "wb");
-    if( fp == NULL ) 
+    if( fp == NULL )
     {
         return FALSE;
     }
@@ -1205,12 +1153,12 @@ int SHPWriteTreeLL(SHPTree *tree, const char *filename, SAHooks* psHooks )
         bBigEndian = FALSE;
     else
         bBigEndian = TRUE;
-  
+
 /* -------------------------------------------------------------------- */
 /*      Write the header.                                               */
 /* -------------------------------------------------------------------- */
     memcpy( abyBuf+0, signature, 3 );
-    
+
     if( bBigEndian )
         abyBuf[3] = 2; /* New MSB */
     else
@@ -1233,8 +1181,8 @@ int SHPWriteTreeLL(SHPTree *tree, const char *filename, SAHooks* psHooks )
 /*      Write all the nodes "in order".                                 */
 /* -------------------------------------------------------------------- */
 
-    SHPWriteTreeNode( fp, tree->psRoot, psHooks );  
-    
+    SHPWriteTreeNode( fp, tree->psRoot, psHooks );
+
     psHooks->FClose( fp );
 
     return TRUE;
diff --git a/ogr/ogrsf_frmts/sosi/fyba_melding.cpp b/ogr/ogrsf_frmts/sosi/fyba_melding.cpp
index 7eda5e4..ba2b30c 100644
--- a/ogr/ogrsf_frmts/sosi/fyba_melding.cpp
+++ b/ogr/ogrsf_frmts/sosi/fyba_melding.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: fyba_melding.cpp 29469 2015-07-04 11:42:30Z rouault $
+ * $Id: fyba_melding.cpp 33128 2016-01-23 20:05:32Z rouault $
  *
  * Project:  FYBA Callbacks
  * Purpose:  Needed by FYBA - however we do not want to display most messages
@@ -40,12 +40,13 @@ void LC_Error(short feil_nr, const char *logtx, const char *vartx)
    char *pszFeilmelding;
 
 
+   // Translate all to English.
    // Egen enkel implementasjon av feilhandtering
    /* Hent feilmeldingstekst og strategi */
    strategi = LC_StrError(feil_nr,&pszFeilmelding);
    switch(strategi) {
-      case 2:  sprintf(szErrMsg,"%s","Observer f�lgende! \n\n");break;
-      case 3:  sprintf(szErrMsg,"%s","Det er oppst�tt en feil! \n\n");break;
+      case 2:  sprintf(szErrMsg,"%s","Observer følgende! \n\n");break;
+      case 3:  sprintf(szErrMsg,"%s","Det er oppstått en feil! \n\n");break;
       case 4:  sprintf(szErrMsg,"%s","Alvorlig feil avslutt programmet! \n\n");break;
       default: szErrMsg[0]='\0';
    }
@@ -56,7 +57,7 @@ void LC_StartMessage(const char *pszFilnavn)
 {
 }
 
-void LC_ShowMessage(double prosent)
+void LC_ShowMessage(double prosent) // TODO: prosent?
 {
 }
 
diff --git a/ogr/ogrsf_frmts/sosi/ogr_sosi.h b/ogr/ogrsf_frmts/sosi/ogr_sosi.h
index d2ea0ca..4f6449f 100644
--- a/ogr/ogrsf_frmts/sosi/ogr_sosi.h
+++ b/ogr/ogrsf_frmts/sosi/ogr_sosi.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_sosi.h 27959 2014-11-14 18:29:21Z rouault $
+ * $Id: ogr_sosi.h 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  SOSI Translator
  * Purpose:  Implements OGRSOSIDriver.
@@ -28,8 +28,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_SOSI_H_INCLUDED
-#define _OGR_SOSI_H_INCLUDED
+#ifndef OGR_SOSI_H_INCLUDED
+#define OGR_SOSI_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "fyba.h"
@@ -82,9 +82,9 @@ class OGRSOSIDataSource : public OGRDataSource {
     char                *pszName;
     OGRSOSILayer        **papoLayers;
     int                 nLayers;
-    
+
 #define MODE_READING 0
-#define MODE_WRITING 1    
+#define MODE_WRITING 1
     int                 nMode;
 
     void                buildOGRPoint(long nSerial);
@@ -123,4 +123,4 @@ public:
     int                 TestCapability( const char * );
 };
 
-#endif /* _OGR_SOSI_H_INCLUDED */
+#endif /* OGR_SOSI_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/sosi/ogrsosidatasource.cpp b/ogr/ogrsf_frmts/sosi/ogrsosidatasource.cpp
index 9f4b39f..c2bec21 100644
--- a/ogr/ogrsf_frmts/sosi/ogrsosidatasource.cpp
+++ b/ogr/ogrsf_frmts/sosi/ogrsosidatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsosidatasource.cpp 27794 2014-10-04 10:13:46Z rouault $
+ * $Id: ogrsosidatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  SOSI Data Source
  * Purpose:  Provide SOSI Data to OGR.
@@ -41,7 +41,7 @@
 /*                              utility methods                         */
 /************************************************************************/
 
-int epsg2sosi (int nEPSG) {
+static int epsg2sosi (int nEPSG) {
     int nSOSI = 23;
     switch (nEPSG) {
         case 27391: /* NGO 1984 Axis I-VIII */
@@ -78,14 +78,15 @@ int epsg2sosi (int nEPSG) {
             break;
         }
         default: {
-            CPLError( CE_Warning, CPLE_AppDefined, 
-                      "(Yet) unsupported coodinate system writing to SOSI file: %i. Defaulting to EPSG:4326/SOSI 84.", nEPSG);
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "(Yet) unsupported coordinate system writing to SOSI "
+                      "file: %i. Defaulting to EPSG:4326/SOSI 84.", nEPSG);
             }
     }
     return nSOSI;
 }
 
-int sosi2epsg (int nSOSI) {
+static int sosi2epsg (int nSOSI) {
     int nEPSG = 4326;
     switch (nSOSI) {
         case 1: /* NGO 1984 Axis I-VIII */
@@ -122,8 +123,9 @@ int sosi2epsg (int nSOSI) {
             break;
         }
         default: {
-            CPLError( CE_Warning, CPLE_AppDefined, 
-                      "(Yet) unsupported coodinate system in SOSI-file: %i. Defaulting to EPSG:4326.", nSOSI);
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "(Yet) unsupported coordinate system in SOSI-file: %i. "
+                      "Defaulting to EPSG:4326.", nSOSI);
         }
     }
     return nEPSG;
@@ -135,19 +137,19 @@ int sosi2epsg (int nSOSI) {
 
 OGRSOSIDataSource::OGRSOSIDataSource() {
     nLayers = 0;
-    
+
     poFileadm = NULL;
     poBaseadm = NULL;
     papoBuiltGeometries = NULL;
     papoLayers = NULL;
     pszName = NULL;
     poSRS = NULL;
-    
+
     poPolyHeaders = NULL;
     poTextHeaders = NULL;
     poPointHeaders = NULL;
     poCurveHeaders = NULL;
-    
+
     pszEncoding = CPL_ENC_UTF8;
     nMode = MODE_READING;
 }
@@ -169,9 +171,9 @@ OGRSOSIDataSource::~OGRSOSIDataSource() {
     }
 
     if (poPolyHeaders  != NULL) delete poPolyHeaders;
-    if (poTextHeaders  != NULL) delete poTextHeaders; 
+    if (poTextHeaders  != NULL) delete poTextHeaders;
     if (poPointHeaders != NULL) delete poPointHeaders;
-    if (poCurveHeaders != NULL) delete poCurveHeaders; 
+    if (poCurveHeaders != NULL) delete poCurveHeaders;
 
     if (nMode == MODE_WRITING) {
         if (poFileadm != NULL) LC_CloseSos  (poFileadm, RESET_IDX );
@@ -189,7 +191,7 @@ OGRSOSIDataSource::~OGRSOSIDataSource() {
         }
         CPLFree(papoLayers);
     }
-    
+
     if (poSRS != NULL) poSRS->Release();
     if (pszName != NULL) CPLFree(pszName);
 }
@@ -198,7 +200,7 @@ static
 OGRFeatureDefn *defineLayer(const char *szName, OGRwkbGeometryType szType, S2I *poHeaders) {
     OGRFeatureDefn *poFeatureDefn = new OGRFeatureDefn( szName );
     poFeatureDefn->SetGeomType( szType );
-    
+
     for (unsigned int n=0; n<poHeaders->size(); n++) { /* adding headers in the correct order again */
         for (S2I::iterator i=poHeaders->begin(); i!=poHeaders->end(); i++) {
             if (n==i->second) {
@@ -266,11 +268,9 @@ int  OGRSOSIDataSource::Open( const char *pszFilename, int bUpdate ) {
      * --------------------------------------------------------------------*/
 
     /* allocate room for one pointer per feature */
-    nNumFeatures = poFileadm->lAntGr;
-    void* mem = VSIMalloc2(nNumFeatures, sizeof(void*));
+    nNumFeatures = static_cast<unsigned int>(poFileadm->lAntGr);
+    void* mem = VSI_MALLOC2_VERBOSE(nNumFeatures, sizeof(void*));
     if (mem == NULL) {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Memory allocation for SOSI features failed." );
         return FALSE;
     } else {
         papoBuiltGeometries = (OGRGeometry**)mem;
@@ -311,42 +311,41 @@ int  OGRSOSIDataSource::Open( const char *pszFilename, int bUpdate ) {
             char *pszLine = LC_GetGi(i);      /* Get one header line */
             if ((pszLine[0] == ':')||(pszLine[0] == '(')) continue;  /* If we have a continued REF line, skip it. */
             if (pszLine[0] == '!') continue;  /* If we have a comment line, skip it. */
-            
+
             char *pszUTFLine = CPLRecode(pszLine, pszEncoding, CPL_ENC_UTF8); /* switch to UTF encoding here, if it is known. */
             char *pszUTFLineIter = pszUTFLine;
-			
             while (pszUTFLineIter[0] == '.') pszUTFLineIter++; /* Skipping the dots at the beginning of a SOSI line */
-            char *pszPos = strstr(pszUTFLineIter, " "); /* Split header and value */
-            if (pszPos != NULL) {
-                CPLString osKey = CPLString(std::string(pszUTFLineIter,pszPos)); /* FIXME: clean instantiation of CPLString? */
-                CPLString osValue = CPLString(pszPos+1);
-                
+            char *pszPos2 = strstr(pszUTFLineIter, " "); /* Split header and value */
+            if (pszPos2 != NULL) {
+                CPLString osKey = CPLString(std::string(pszUTFLineIter,pszPos2)); /* FIXME: clean instantiation of CPLString? */
+                CPLString osValue = CPLString(pszPos2+1);
+
                 oHeaders[osKey]=osValue;          /* Add to header map */
                 switch (nName) {             /* Add to header list for the corresponding layer, if it is not */
                 case L_FLATE: {            /* in there already */
                     if (poPolyHeaders->find(osKey) == poPolyHeaders->end()) {
-                        iH = poPolyHeaders->size();
+                        iH = static_cast<int>(poPolyHeaders->size());
                         (*poPolyHeaders)[osKey] = iH;
                     }
                     break;
                 }
                 case L_KURVE: {
                     if (poCurveHeaders->find(osKey) == poCurveHeaders->end()) {
-                        iH = poCurveHeaders->size();
+                        iH = static_cast<int>(poCurveHeaders->size());
                         (*poCurveHeaders)[osKey] = iH;
                     }
                     break;
                 }
                 case L_PUNKT: {
                     if (poPointHeaders->find(osKey) == poPointHeaders->end()) {
-                        iH = poPointHeaders->size();
+                        iH = static_cast<int>(poPointHeaders->size());
                         (*poPointHeaders)[osKey] = iH;
                     }
                     break;
                 }
                 case L_TEKST: {
                     if (poTextHeaders->find(osKey) == poTextHeaders->end()) {
-                        iH = poTextHeaders->size();
+                        iH = static_cast<int>(poTextHeaders->size());
                         (*poTextHeaders)[osKey] = iH;
                     }
                     break;
@@ -373,14 +372,14 @@ int  OGRSOSIDataSource::Open( const char *pszFilename, int bUpdate ) {
         case L_KURVE: {
             /* Pre-build a line feature. Activate line/curve layer. */
             bCurveLayer = TRUE;
-            buildOGRLineString(nNumCoo, oNextSerial.lNr);
+            buildOGRLineString(static_cast<int>(nNumCoo), oNextSerial.lNr);
             break;
         }
         case L_TEKST: {
             /* Pre-build a text line contour feature. Activate text layer. */
             /* Todo: observe only points 2ff if more than one point is given for follow mode */
             bTextLayer = TRUE;
-            buildOGRMultiPoint(nNumCoo, oNextSerial.lNr);
+            buildOGRMultiPoint(static_cast<int>(nNumCoo), oNextSerial.lNr);
             break;
         }
         case L_HODE: {
@@ -388,18 +387,18 @@ int  OGRSOSIDataSource::Open( const char *pszFilename, int bUpdate ) {
             unsigned short nMask = LC_TR_ALLT;
             LC_TRANSPAR oTrans;
             if (LC_GetTransEx(&nMask,&oTrans) == UT_FALSE) {
-                CPLError( CE_Failure, CPLE_OpenFailed, 
+                CPLError( CE_Failure, CPLE_OpenFailed,
                           "TRANSPAR section not found - No reference system information available.");
-                return NULL;
+                return FALSE;
             }
             poSRS = new OGRSpatialReference();
 
             /* Get coordinate system from SOSI header. */
             int nEPSG = sosi2epsg(oTrans.sKoordsys);
             if (poSRS->importFromEPSG(nEPSG) != OGRERR_NONE) {
-				CPLError( CE_Failure, CPLE_OpenFailed, 
+				CPLError( CE_Failure, CPLE_OpenFailed,
                           "OGR could not load coordinate system definition EPSG:%i.", nEPSG);
-                return NULL;
+                return FALSE;
             }
 
             /* Get character encoding from SOSI header. */
@@ -426,14 +425,19 @@ int  OGRSOSIDataSource::Open( const char *pszFilename, int bUpdate ) {
     /* -------------------------------------------------------------------- *
      *      Create a corresponding layers. One per geometry type            *
      * -------------------------------------------------------------------- */
-    int nLayers = 0;
-    if (bPolyLayer)  nLayers++;
-    if (bCurveLayer) nLayers++;
-    if (bPointLayer) nLayers++;
-    if (bTextLayer) nLayers++;
-    this->nLayers = nLayers;
+    int l_nLayers = 0;
+    if (bPolyLayer)  l_nLayers++;
+    if (bCurveLayer) l_nLayers++;
+    if (bPointLayer) l_nLayers++;
+    if (bTextLayer) l_nLayers++;
+    this->nLayers = l_nLayers;
     /* allocate some memory for up to three layers */
-    papoLayers = (OGRSOSILayer **) VSIMalloc2(sizeof(void*), nLayers);
+    papoLayers = (OGRSOSILayer **) VSI_MALLOC2_VERBOSE(sizeof(void*), l_nLayers);
+    if( papoLayers == NULL )
+    {
+        this->nLayers = 0;
+        return FALSE;
+    }
 
     /* Define each layer, using a proper feature definition, geometry type,
      * and adding every SOSI header encountered in the file as field. */
@@ -441,7 +445,7 @@ int  OGRSOSIDataSource::Open( const char *pszFilename, int bUpdate ) {
     if (bPolyLayer) {
 		OGRFeatureDefn *poFeatureDefn = defineLayer("polygons", wkbPolygon, poPolyHeaders);
         poFeatureDefn->Reference();
-        papoLayers[--nLayers] = new OGRSOSILayer( this, poFeatureDefn, poFileadm, poPolyHeaders );
+        papoLayers[--l_nLayers] = new OGRSOSILayer( this, poFeatureDefn, poFileadm, poPolyHeaders );
     } else {
         delete poPolyHeaders;
         poPolyHeaders = NULL;
@@ -449,7 +453,7 @@ int  OGRSOSIDataSource::Open( const char *pszFilename, int bUpdate ) {
     if (bCurveLayer) {
         OGRFeatureDefn *poFeatureDefn = defineLayer("lines", wkbLineString, poCurveHeaders);
         poFeatureDefn->Reference();
-        papoLayers[--nLayers] = new OGRSOSILayer( this, poFeatureDefn, poFileadm, poCurveHeaders );
+        papoLayers[--l_nLayers] = new OGRSOSILayer( this, poFeatureDefn, poFileadm, poCurveHeaders );
     } else {
         delete poCurveHeaders;
         poCurveHeaders = NULL;
@@ -457,7 +461,7 @@ int  OGRSOSIDataSource::Open( const char *pszFilename, int bUpdate ) {
     if (bPointLayer) {
         OGRFeatureDefn *poFeatureDefn = defineLayer("points", wkbPoint, poPointHeaders);
         poFeatureDefn->Reference();
-        papoLayers[--nLayers] = new OGRSOSILayer( this, poFeatureDefn, poFileadm, poPointHeaders );
+        papoLayers[--l_nLayers] = new OGRSOSILayer( this, poFeatureDefn, poFileadm, poPointHeaders );
     } else {
         delete poPointHeaders;
         poPointHeaders = NULL;
@@ -465,7 +469,7 @@ int  OGRSOSIDataSource::Open( const char *pszFilename, int bUpdate ) {
     if (bTextLayer) {
         OGRFeatureDefn *poFeatureDefn = defineLayer("text", wkbMultiPoint, poTextHeaders);
         poFeatureDefn->Reference();
-        papoLayers[--nLayers] = new OGRSOSILayer( this, poFeatureDefn, poFileadm, poTextHeaders );
+        papoLayers[--l_nLayers] = new OGRSOSILayer( this, poFeatureDefn, poFileadm, poTextHeaders );
     } else {
         delete poTextHeaders;
         poTextHeaders = NULL;
@@ -481,7 +485,7 @@ int  OGRSOSIDataSource::Open( const char *pszFilename, int bUpdate ) {
 int  OGRSOSIDataSource::Create( const char *pszFilename ) {
 	short nStatus;
 	short nDetStatus;
-	
+
     poBaseadm = LC_OpenBase(LC_KLADD);
     nStatus   = LC_OpenSos(pszFilename, LC_SEKV_SKRIV, LC_NY_IDX, LC_INGEN_STATUS,
                            &poFileadm, &nDetStatus);
@@ -489,11 +493,11 @@ int  OGRSOSIDataSource::Create( const char *pszFilename ) {
         CPLError( CE_Failure, CPLE_OpenFailed,
                   "Could not open SOSI file for writing (Status %i).", nDetStatus );
         return FALSE;
-	}
+    }
 
-    LC_NyttHode(); /* Create new file header, will be written to file when all 
+    LC_NyttHode(); /* Create new file header, will be written to file when all
                       header information elements are set. */
-                      
+
     return TRUE;
 }
 
@@ -501,7 +505,7 @@ int  OGRSOSIDataSource::Create( const char *pszFilename ) {
 /*                             ICreateLayer()                           */
 /************************************************************************/
 
-OGRLayer *OGRSOSIDataSource::ICreateLayer( const char *pszName,
+OGRLayer *OGRSOSIDataSource::ICreateLayer( const char *pszNameIn,
                                            OGRSpatialReference  *poSpatialRef,
                                            OGRwkbGeometryType eGType,
                                            CPL_UNUSED char **papszOptions ) {
@@ -510,7 +514,7 @@ OGRLayer *OGRSOSIDataSource::ICreateLayer( const char *pszName,
         if (poSpatialRef!=NULL) {
             poSRS = poSpatialRef;
             poSRS->Reference();
-        
+
             const char *pszKoosys = poSRS->GetAuthorityCode("PROJCS");
             if (pszKoosys == NULL) {
                 OGRErr err = poSRS->AutoIdentifyEPSG();
@@ -521,7 +525,7 @@ OGRLayer *OGRSOSIDataSource::ICreateLayer( const char *pszName,
                 }
                 pszKoosys = poSRS->GetAuthorityCode("PROJCS");
             }
-            
+
             if (pszKoosys != NULL) {
                 int nKoosys = epsg2sosi(atoi(pszKoosys));
                 CPLDebug( "[CreateLayer]","Projection set to SOSI %i", nKoosys);
@@ -537,17 +541,17 @@ OGRLayer *OGRSOSIDataSource::ICreateLayer( const char *pszName,
                     return NULL;
                 }
             }
-        } 
+        }
         LC_WsGr(poFileadm); /* Writing the header here! */
-    
+
     } else {
         if (!poSRS->IsSame(poSpatialRef)) {
           CPLError( CE_Failure, CPLE_AppDefined,
                     "SOSI driver does not support different spatial reference systems in one file.");
         }
     }
-    
-    OGRFeatureDefn *poFeatureDefn = new OGRFeatureDefn( pszName );
+
+    OGRFeatureDefn *poFeatureDefn = new OGRFeatureDefn( pszNameIn );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( eGType );
     OGRSOSILayer *poLayer = new OGRSOSILayer( this, poFeatureDefn, poFileadm, NULL /*poHeaderDefn*/);
@@ -591,7 +595,7 @@ void OGRSOSIDataSource::buildOGRLineString(int nNumCoo, long iSerial) {
     OGRLineString *poLS = new OGRLineString();
     poLS->setNumPoints(nNumCoo);
 
-    long i;
+    int i;
     double dfEast = 0, dfNorth = 0;
     for (i=1; i<=nNumCoo; i++) {
         LC_GetTK(i, &dfEast, &dfNorth);
@@ -611,7 +615,7 @@ void OGRSOSIDataSource::buildOGRPoint(long iSerial) {
 
 int OGRSOSIDataSource::TestCapability( const char * pszCap ) {
     if (strcmp("CreateLayer",pszCap) == 0) {
-        return TRUE; 
+        return TRUE;
     } else {
         CPLDebug( "[TestCapability]","Capability %s not supported by SOSI data source", pszCap);
     }
diff --git a/ogr/ogrsf_frmts/sosi/ogrsosidriver.cpp b/ogr/ogrsf_frmts/sosi/ogrsosidriver.cpp
index c31510a..a7ba5fc 100644
--- a/ogr/ogrsf_frmts/sosi/ogrsosidriver.cpp
+++ b/ogr/ogrsf_frmts/sosi/ogrsosidriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsosidriver.cpp 27794 2014-10-04 10:13:46Z rouault $
+ * $Id: ogrsosidriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  SOSI Translator
  * Purpose:  Implements OGRSOSIDriver.
@@ -79,7 +79,6 @@ static GDALDataset *OGRSOSIDriverCreate( const char * pszName,
                                          CPL_UNUSED int nYSize, CPL_UNUSED GDALDataType eDT,
                                          CPL_UNUSED char **papszOptions )
 {
-    
     if ( !bFYBAInit )
     {
         LC_Init();  /* Init FYBA */
@@ -98,23 +97,19 @@ static GDALDataset *OGRSOSIDriverCreate( const char * pszName,
 /************************************************************************/
 
 void RegisterOGRSOSI() {
-    GDALDriver  *poDriver;
-
     if( GDALGetDriverByName( "SOSI" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+        return;
 
-        poDriver->SetDescription( "SOSI" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Norwegian SOSI Standard" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_sosi.html" );
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->pfnOpen = OGRSOSIDriverOpen;
-        poDriver->pfnCreate = OGRSOSIDriverCreate;
-        poDriver->pfnUnloadDriver = OGRSOSIDriverUnload;
+    poDriver->SetDescription( "SOSI" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Norwegian SOSI Standard" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_sosi.html" );
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    poDriver->pfnOpen = OGRSOSIDriverOpen;
+    poDriver->pfnCreate = OGRSOSIDriverCreate;
+    poDriver->pfnUnloadDriver = OGRSOSIDriverUnload;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/sosi/ogrsosilayer.cpp b/ogr/ogrsf_frmts/sosi/ogrsosilayer.cpp
index 0f68c4b..051eb94 100644
--- a/ogr/ogrsf_frmts/sosi/ogrsosilayer.cpp
+++ b/ogr/ogrsf_frmts/sosi/ogrsosilayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsosilayer.cpp 27959 2014-11-14 18:29:21Z rouault $
+ * $Id: ogrsosilayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  SOSI Translator
  * Purpose:  Implements OGRSOSILayer.
@@ -42,7 +42,7 @@ OGRSOSILayer::OGRSOSILayer( OGRSOSIDataSource *poPar, OGRFeatureDefn *poFeatDefn
     poHeaderDefn  = poHeadDefn;
     nNextFID      = 0;
     poNextSerial  = NULL;
-    
+
     SetDescription( poFeatureDefn->GetName() );
     if( poFeatureDefn->GetGeomFieldCount() > 0 )
         poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poParent->poSRS);
@@ -76,9 +76,9 @@ OGRErr OGRSOSILayer::CreateField (OGRFieldDefn *poField, CPL_UNUSED int bApproxO
 /*                           ICreateFeature()                            */
 /************************************************************************/
 OGRErr OGRSOSILayer::ICreateFeature(OGRFeature *poFeature) {
-    short nNavn;
+    //short nNavn;
     long nSerial;
-    
+
     const char *pszSosi = NULL;
     switch (poFeatureDefn->GetGeomType()) {
         case wkbPoint: {
@@ -98,7 +98,7 @@ OGRErr OGRSOSILayer::ICreateFeature(OGRFeature *poFeature) {
             return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
         }
     }
-    nNavn = LC_NyGr(poFileadm, (char *)pszSosi, &oNextSerial, &nSerial);
+    /*nNavn = */ LC_NyGr(poFileadm, (char *)pszSosi, &oNextSerial, &nSerial);
     /* === WIP - Work in progress === */
     /* PutGI for all headers */
     char pszGi[255];
@@ -117,7 +117,7 @@ OGRErr OGRSOSILayer::ICreateFeature(OGRFeature *poFeature) {
     LC_WsGr(poFileadm); /* Writing the header here! */
     return OGRERR_NONE;
 }
-    
+
 /************************************************************************/
 /*                           GetNextFeature()                           */
 /************************************************************************/
@@ -126,8 +126,6 @@ OGRFeature *OGRSOSILayer::GetNextFeature() {
     long  nNumCoo;
     unsigned short nInfo;
 
-    typedef std::map<CPLString, CPLString> S2S;
-
     /* iterate through the SOSI groups*/
     while (LC_NextBgr(poNextSerial,LC_FRAMGR)) {
         nName = LC_RxGr(&oNextSerial, LES_OPTIMALT, &nNumLines, &nNumCoo, &nInfo);
@@ -172,20 +170,28 @@ OGRFeature *OGRSOSILayer::GetNextFeature() {
             long nRefCount;
             LC_GRF_STATUS oGrfStat;
 
-            LC_InitGetRefFlate(&oGrfStat); /* Iterate through all objects that constitute this area */
+            // Iterate through all objects that constitute this area.
+            LC_InitGetRefFlate(&oGrfStat);
             nRefCount = LC_GetRefFlate(&oGrfStat, GRF_YTRE, &nRefNr, &nRefStatus, 1);
             while (nRefCount > 0) {
-                if (poParent->papoBuiltGeometries[nRefNr] == NULL) { /* this shouldn't happen under normal operation */
-                    CPLError( CE_Fatal, CPLE_AppDefined, "Feature %li referenced by %li, but it was not initialized.", nRefNr, oNextSerial.lNr);
+                if (poParent->papoBuiltGeometries[nRefNr] == NULL) {
+                    // This should not happen under normal operation.
+                    CPLError( CE_Fatal, CPLE_AppDefined,
+                              "Feature %li referenced by %li, but it was not "
+                              "initialized.", nRefNr, oNextSerial.lNr);
                     return NULL;
                 }
-                OGRLineString *poCurve = (OGRLineString*)(poParent->papoBuiltGeometries[nRefNr]);
+                OGRLineString *poCurve
+                    = (OGRLineString*)(poParent->papoBuiltGeometries[nRefNr]);
                 if (nRefStatus == LC_MED_DIG) {         /* clockwise */
                     poOuter->addSubLineString(poCurve);
                 } else if (nRefStatus == LC_MOT_DIG) {  /* counter-clockwise */
                     poOuter->addSubLineString(poCurve,poCurve->getNumPoints()-1,0);
                 } else {
-                    CPLError( CE_Failure, CPLE_OpenFailed, "Island (OEY) encountered, but not yet supported.");
+                    CPLError( CE_Failure, CPLE_OpenFailed,
+                              "Island (OEY) encountered, "
+                              "but not yet supported.");
+                    delete poOuter;
                     return NULL;
                 }
                 nRefCount = LC_GetRefFlate(&oGrfStat, GRF_YTRE, &nRefNr, &nRefStatus, 1);
@@ -240,7 +246,7 @@ OGRFeature *OGRSOSILayer::GetNextFeature() {
 
         if (poGeom == NULL) continue;                         /* skipping L_HODE and unrecognized groups */
         if (oGType != poFeatureDefn->GetGeomType()) {
-            if (poGeom != NULL) delete poGeom;     
+            if (poGeom != NULL) delete poGeom;
             continue; /* skipping features that are not the correct geometry */
         }
 
@@ -255,7 +261,7 @@ OGRFeature *OGRSOSILayer::GetNextFeature() {
                 continue;
 			}
             if ((pszLine[0] == '\'')||(pszLine[0] == '\"')) { /* If the value is quoted, ignore these */
-                int nLen = strlen(pszLine);
+                int nLen = static_cast<int>(strlen(pszLine));
                 char *pszNline = (char*)CPLMalloc(nLen-1);
                 strncpy(pszNline, pszLine+1, nLen-2);
                 pszNline[nLen-2] = '\0';
@@ -265,7 +271,7 @@ OGRFeature *OGRSOSILayer::GetNextFeature() {
                 poFeature->SetField( iHNr, pszLine);
             }
         }
-        
+
         if( poGeom != NULL )
             poGeom->assignSpatialReference(poParent->poSRS);
 
diff --git a/ogr/ogrsf_frmts/sqlite/GNUmakefile b/ogr/ogrsf_frmts/sqlite/GNUmakefile
index fb795c5..c30042a 100644
--- a/ogr/ogrsf_frmts/sqlite/GNUmakefile
+++ b/ogr/ogrsf_frmts/sqlite/GNUmakefile
@@ -10,6 +10,10 @@ ifeq ($(HAVE_SPATIALITE),yes)
 CPPFLAGS +=  -DHAVE_SPATIALITE
 endif
 
+ifeq ($(HAVE_SPATIALITE),dlopen)
+CPPFLAGS +=  -DHAVE_SPATIALITE -DSPATIALITE_DLOPEN -DSPATIALITE_412_OR_LATER -DSPATIALITE_SONAME=\"$(SPATIALITE_SONAME)\"
+endif
+
 ifeq ($(SPATIALITE_AMALGAMATION),yes)
 CPPFLAGS +=  -DSPATIALITE_AMALGAMATION
 endif
diff --git a/ogr/ogrsf_frmts/sqlite/drv_sqlite.html b/ogr/ogrsf_frmts/sqlite/drv_sqlite.html
index 55991cd..ac3794c 100644
--- a/ogr/ogrsf_frmts/sqlite/drv_sqlite.html
+++ b/ogr/ogrsf_frmts/sqlite/drv_sqlite.html
@@ -9,7 +9,7 @@
 
 <p>OGR optionally supports spatial and non-spatial tables stored in SQLite 3.x
 database files.  SQLite is a "light weight" single file based RDBMS engine
-with fairly complete SQL semantics and respectible performance.</p>
+with fairly complete SQL semantics and respectable performance.</p>
 
 <p>The driver can handle "regular" SQLite databases, as well as Spatialite
 databases (spatial enabled SQLite databases).</p>
@@ -27,9 +27,9 @@ to operate only on SQLite files on a physical disk of the local system.</p>
 <p>SQLite is an optionally compiled in driver.  It is not compiled in by default.</p>
 
 <p>By default, SQL statements are passed directly to the SQLite database engine.
-It's also possible to request the driver to handle SQL commands 
-with <a href="/ogr/ogr_sql.html">OGR SQL</a> engine, 
-by passing <strong>"OGRSQL"</strong> string to the ExecuteSQL() 
+It's also possible to request the driver to handle SQL commands
+with <a href="ogr_sql.html">OGR SQL</a> engine,
+by passing <strong>"OGRSQL"</strong> string to the ExecuteSQL()
 method, as name of the SQL dialect.</p>
 
 <p>Starting with OGR 1.8.0, the OGR_SQLITE_SYNCHRONOUS configuration option has been added.
@@ -45,13 +45,13 @@ OGR_SQLITE_PRAGMA = "pragma_name=pragma_value[,pragma_name2=pragma_value2]*".</p
 
 <h2>"Regular" SQLite databases</h2>
 
-<p>The driver looks for a geometry_columns table layed out as defined
+<p>The driver looks for a geometry_columns table laid out as defined
 loosely according to OGC Simple Features standards, particularly as defined
 in <A href="http://trac.osgeo.org/fdo/wiki/FDORfc16">FDO RFC 16</a>.  If
 found it is used to map tables to layers.</P>
 
-<p>If geometry_columns is not found, each table is treated as a layer.  Layers 
-with a WKT_GEOMETRY field will be treated as spatial tables, and the 
+<p>If geometry_columns is not found, each table is treated as a layer.  Layers
+with a WKT_GEOMETRY field will be treated as spatial tables, and the
 WKT_GEOMETRY column will be read as Well Known Text geometry.</p>
 
 <p>If geometry_columns is found, it will be used to lookup spatial reference
@@ -59,8 +59,8 @@ systems in the spatial_ref_sys table.</P>
 
 <p>While the SQLite driver supports reading spatial data from records, there is
 no support for spatial indexing, so spatial queries will tend to be slow (use Spatialite for that).
-Attributes queries may be fast, especially if indexes are built for 
-appropriate attribute columns using the "CREATE INDEX <indexname> 
+Attributes queries may be fast, especially if indexes are built for
+appropriate attribute columns using the "CREATE INDEX <indexname>
 ON <tablename> ( <columnname> )" SQL command.</p>
 
 <p>Starting with GDAL 2.0, the driver also supports reading and writing the
@@ -78,7 +78,7 @@ modified or read, following new API described in <a href="http://trac.osgeo.org/
 <p>
 In GDAL 1.10, such support was read-only and there were as many OGR layers exposed
 as there are geometry columns. They were named "table_name(geometry_column_name)".
-Such syntax is still possible with GDAL 2.0 when explictely querying a layer
+Such syntax is still possible with GDAL 2.0 when explicitly querying a layer
 with GetLayerByName()</p>
 
 <h2>REGEXP operator</h2>
@@ -147,7 +147,7 @@ CREATE VIRTUAL TABLE table_name USING VirtualOGR(datasource_name, update_mode, l
 
 where :
 <ul>
-<li><i>datasource_name</i> is the connexion string to any OGR datasource.</li>
+<li><i>datasource_name</i> is the connetion string to any OGR datasource.</li>
 <li><i>update_mode</i> = 0 for read-only mode (default value) or 1 for update mode.</li>
 <li><i>layer_name</i> = the name of a layer of the opened datasource.</li>
 <li><i>expose_ogr_style</i> = 0 to prevent the OGR_STYLE special from being displayed (default value) or 1 to expose it.</li>
@@ -226,7 +226,7 @@ potential safety issues.<p>
 
 <ul>
 
-<li><p><b>METADATA=YES/NO</b>: This can be used to avoid creating the 
+<li><p><b>METADATA=YES/NO</b>: This can be used to avoid creating the
 geometry_columns and spatial_ref_sys tables in a new database.  By default
 these metadata tables are created when a new database is created.</p></li>
 
@@ -236,14 +236,14 @@ from OGC specifications. Implies <b>METADATA=YES</b>.<br>
 Please note: (Starting with GDAL 1.9.0) OGR must be linked against <i>libspatialite</i> in order to support
 insert/write on SpatiaLite; if not, <i>read-only</i> mode is enforced.<br>
 Attempting to perform any insert/write on SpatiaLite skipping the appropriate library support simply produces broken (corrupted) DB-files.<br>
-Important notice: when the underlaying <i>libspatialite</i> is v.2.3.1 (or any previous
+Important notice: when the underlying <i>libspatialite</i> is v.2.3.1 (or any previous
 version) any Geometry will be casted to 2D [XY], because earlier versions of this library
 are simply able to support 2D [XY] dimensions. Version 2.4.0 (or any subsequent) is required in order to support 2.5D [XYZ].</p></li>
 
 <li><p><b>INIT_WITH_EPSG=YES/NO</b>: (Starting with GDAL 1.8.0) Insert the content of the EPSG CSV files
 into the spatial_ref_sys table. Defaults to NO for regular SQLite databases</b>.<br>
-Please note: if <b>SPATIALITE=YES</b> and the underlaying <i>libspatialite</i> is v2.4 or v3.X,
-<b>INIT_WITH_EPSG</b> is ignored; those library versions will unconditionally load the EPSG 
+Please note: if <b>SPATIALITE=YES</b> and the underlying <i>libspatialite</i> is v2.4 or v3.X,
+<b>INIT_WITH_EPSG</b> is ignored; those library versions will unconditionally load the EPSG
 dataset into the spatial_ref_sys table when creating a new DB (<i>self-initialization</i>). Starting
 with libspatialite 4.0, INIT_WITH_EPSG defaults to YES, but can be set to NO.</p></li>
 
@@ -261,12 +261,12 @@ own binary format to store geometries and you can choose it as well. It will
 be selected automatically when SpatiaLite database is opened or created with
 <b>SPATIALITE=YES</b> option. SPATIALITE value is available starting with GDAL 1.7.0.</p></li>
 
-<li><p><b>GEOMETRY_NAME</b>: (Starting with GDAL 2.0) By default OGR creates new tables with the 
-geometry column named GEOMETRY (or WKT_GEOMETRY if FORMAT=WKT). If you wish to use a different name, 
+<li><p><b>GEOMETRY_NAME</b>: (Starting with GDAL 2.0) By default OGR creates new tables with the
+geometry column named GEOMETRY (or WKT_GEOMETRY if FORMAT=WKT). If you wish to use a different name,
 it can be supplied with the GEOMETRY_NAME layer creation option.</p></li>
 
-<li><p><b>LAUNDER=YES/NO</b>: Controls whether layer and field names will be 
-laundered for easier use in SQLite.  Laundered names will be convered to lower 
+<li><p><b>LAUNDER=YES/NO</b>: Controls whether layer and field names will be
+laundered for easier use in SQLite.  Laundered names will be converted to lower
 case and some special characters(' - #) will be changed to underscores. Default
 to YES.</p></li>
 
@@ -292,7 +292,7 @@ not be done : the specified SRID is used as such.</p></li>
 A list of (String) columns that must be compressed with ZLib DEFLATE algorithm. This might be beneficial
 for databases that have big string blobs. However, use with care, since the value of such columns
 will be seen as compressed binary content with other SQLite utilities (or previous OGR versions).
-With OGR, when inserting, modifying or queryings compressed columns, compression/decompression is done transparently.
+With OGR, when inserting, modifying or querying compressed columns, compression/decompression is done transparently.
 However, such columns cannot be (easily) queried with an attribute filter or WHERE clause.
 Note: in table definition, such columns have the "VARCHAR_deflate" declaration type.</p></li>
 
@@ -315,19 +315,19 @@ defining an even bigger <b>-gt 65536</b> ensures optimal performance while
 populating some table containing many hundredth thousand or million rows.<p>
 
 SQLite usually has a very minimal memory foot-print; just about 20MB of RAM are
-reserved to store the internal Page Cache [merely 2000 pages]. 
+reserved to store the internal Page Cache [merely 2000 pages].
 This value too may well be inappropriate under many circumstances, most notably when
 accessing some really huge DB-file containing many tables related to a corresponding
 Spatial Index.
 Explicitly setting a much more generously dimensioned internal Page Cache may often
 help to get a noticeably better performance.
-Starting since GDAL 1.9.0 you can explicitly set the internal Page Cache size using the 
+Starting since GDAL 1.9.0 you can explicitly set the internal Page Cache size using the
 configuration option <b>OGR_SQLITE_CACHE</b> <i>value</i> [<i>value</i> being measured in MB];
-if your HW has enough available RAM, defining a Cache size as big as 512MB (or even 1024MB) 
+if your HW has enough available RAM, defining a Cache size as big as 512MB (or even 1024MB)
 may sometimes help a lot in order to get better performance.<p>
 
 Setting the <b>OGR_SQLITE_SYNCHRONOUS</b> configuration option to <i>OFF</i> might also
-increase performance when creating SQLite databases (altough at the expense of integrity in case of
+increase performance when creating SQLite databases (although at the expense of integrity in case of
 interruption/crash ).<p>
 
 If many source files will be collected into the same Spatialite table, it
@@ -351,8 +351,8 @@ If a database has gone through editing operations, it might be useful to run a
 
 <h2>Credits</h2>
 <ul>
-<li>Development of the OGR SQLite driver was supported by 
-<a href="http://www.dmsolutions.ca/">DM Solutions Group</a> and 
+<li>Development of the OGR SQLite driver was supported by
+<a href="http://www.dmsolutions.ca/">DM Solutions Group</a> and
 <a href="http://www.gomoos.org/">GoMOOS</a>.</li>
 <li>Full support for SpatiaLite was contributed by A.Furieri, with funding from <a href="http://www.regione.toscana.it/">Regione Toscana<a>
 </ul>
diff --git a/ogr/ogrsf_frmts/sqlite/ogr_sqlite.h b/ogr/ogrsf_frmts/sqlite/ogr_sqlite.h
index 8a2931a..2fcd57b 100644
--- a/ogr/ogrsf_frmts/sqlite/ogr_sqlite.h
+++ b/ogr/ogrsf_frmts/sqlite/ogr_sqlite.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_sqlite.h 29330 2015-06-14 12:11:11Z rouault $
+ * $Id: ogr_sqlite.h 33821 2016-03-31 12:34:40Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/SQLite driver.
@@ -28,8 +28,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_SQLITE_H_INCLUDED
-#define _OGR_SQLITE_H_INCLUDED
+#ifndef OGR_SQLITE_H_INCLUDED
+#define OGR_SQLITE_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "gdal_pam.h"
@@ -42,8 +42,8 @@
     /*
     / using an AMALGAMATED version of SpatiaLite
     / a private internal copy of SQLite is included:
-    / so we are required including the SpatiaLite's 
-    / own header 
+    / so we are required including the SpatiaLite's
+    / own header
     /
     / IMPORTANT NOTICE: using AMALAGATION is only
     / useful on Windows (to skip DLL hell related oddities)
@@ -65,6 +65,8 @@
 #define HAVE_SQLITE3_PREPARE_V2
 #endif
 
+#ifndef DO_NOT_INCLUDE_SQLITE_CLASSES
+
 #define UNINITIALIZED_SRID  -2
 
 /************************************************************************/
@@ -102,7 +104,7 @@ enum OGRSpatialiteGeomType
     OGRSpliteMultiLineStringXYZ          = 1005,
     OGRSpliteMultiPolygonXYZ             = 1006,
     OGRSpliteGeometryCollectionXYZ       = 1007,
-// 2D with Measure [XYM] 
+// 2D with Measure [XYM]
     OGRSplitePointXYM                    = 2001,
     OGRSpliteLineStringXYM               = 2002,
     OGRSplitePolygonXYM                  = 2003,
@@ -152,13 +154,13 @@ enum OGRSpatialiteGeomType
 /*                        OGRSQLiteGeomFieldDefn                        */
 /************************************************************************/
 
-class OGRSQLiteGeomFieldDefn : public OGRGeomFieldDefn
+class OGRSQLiteGeomFieldDefn CPL_FINAL : public OGRGeomFieldDefn
 {
     public:
-        OGRSQLiteGeomFieldDefn( const char* pszName, int iGeomColIn ) :
-            OGRGeomFieldDefn(pszName, wkbUnknown), nSRSId(-1),
+        OGRSQLiteGeomFieldDefn( const char* pszNameIn, int iGeomColIn ) :
+            OGRGeomFieldDefn(pszNameIn, wkbUnknown), nSRSId(-1),
             iCol(iGeomColIn), bTriedAsSpatiaLite(FALSE), eGeomFormat(OSGF_None),
-            bHasM(FALSE), bCachedExtentIsValid(FALSE), bHasSpatialIndex(FALSE),
+            bCachedExtentIsValid(FALSE), bHasSpatialIndex(FALSE),
             bHasCheckedSpatialIndexTable(FALSE)
             {
             }
@@ -167,7 +169,6 @@ class OGRSQLiteGeomFieldDefn : public OGRGeomFieldDefn
         int iCol; /* ordinal of geometry field in SQL statement */
         int bTriedAsSpatiaLite;
         OGRSQLiteGeomFormat eGeomFormat;
-        int bHasM;
         OGREnvelope         oCachedExtent;
         int                 bCachedExtentIsValid;
         int                 bHasSpatialIndex;
@@ -179,7 +180,7 @@ class OGRSQLiteGeomFieldDefn : public OGRGeomFieldDefn
 /*                        OGRSQLiteFeatureDefn                          */
 /************************************************************************/
 
-class OGRSQLiteFeatureDefn : public OGRFeatureDefn
+class OGRSQLiteFeatureDefn CPL_FINAL : public OGRFeatureDefn
 {
     public:
         OGRSQLiteFeatureDefn( const char * pszName = NULL ) :
@@ -187,7 +188,7 @@ class OGRSQLiteFeatureDefn : public OGRFeatureDefn
         {
             SetGeomType(wkbNone);
         }
-            
+
         OGRSQLiteGeomFieldDefn* myGetGeomFieldDefn(int i)
         {
             return (OGRSQLiteGeomFieldDefn*) GetGeomFieldDefn(i);
@@ -203,6 +204,8 @@ class OGRSQLiteDataSource;
 class IOGRSQLiteGetSpatialWhere
 {
   public:
+    virtual              ~IOGRSQLiteGetSpatialWhere() {}
+
     virtual int           HasFastSpatialFilter(int iGeomCol) = 0;
     virtual CPLString     GetSpatialWhere(int iGeomCol,
                                           OGRGeometry* poFilterGeom) = 0;
@@ -221,17 +224,17 @@ class OGRSQLiteLayer : public OGRLayer, public IOGRSQLiteGetSpatialWhere
     static int          CanBeCompressedSpatialiteGeometry(const OGRGeometry *poGeometry);
 
     static int          ComputeSpatiaLiteGeometrySize(const OGRGeometry *poGeometry,
-                                                      int bHasM, int bSpatialite2D,
+                                                      int bSpatialite2D,
                                                       int bUseComprGeom );
 
     static int          GetSpatialiteGeometryCode(const OGRGeometry *poGeometry,
-                                                  int bHasM, int bSpatialite2D,
+                                                  int bSpatialite2D,
                                                   int bUseComprGeom,
                                                   int bAcceptMultiGeom);
 
     static int          ExportSpatiaLiteGeometryInternal(const OGRGeometry *poGeometry,
                                                         OGRwkbByteOrder eByteOrder,
-                                                        int bHasM, int bSpatialite2D,
+                                                        int bSpatialite2D,
                                                         int bUseComprGeom,
                                                         GByte* pabyData );
 
@@ -249,6 +252,8 @@ class OGRSQLiteLayer : public OGRLayer, public IOGRSQLiteGetSpatialWhere
 
     int                *panFieldOrdinals;
     int                 iFIDCol;
+    int                 iOGRNativeDataCol;
+    int                 iOGRNativeMediaTypeCol;
 
     int                 bIsVirtualShape;
 
@@ -285,7 +290,7 @@ class OGRSQLiteLayer : public OGRLayer, public IOGRSQLiteGetSpatialWhere
     virtual OGRFeature *GetNextFeature();
 
     virtual OGRFeature *GetFeature( GIntBig nFeatureId );
-    
+
     virtual OGRFeatureDefn *GetLayerDefn() { return poFeatureDefn; }
     virtual OGRSQLiteFeatureDefn *myGetLayerDefn() { return poFeatureDefn; }
 
@@ -313,7 +318,7 @@ class OGRSQLiteLayer : public OGRLayer, public IOGRSQLiteGetSpatialWhere
                                                   OGRGeometry **, int *pnSRID );
     static OGRErr       ExportSpatiaLiteGeometry( const OGRGeometry *,
                                                   GInt32, OGRwkbByteOrder,
-                                                  int, int, int bUseComprGeom, GByte **, int * );
+                                                  int, int bUseComprGeom, GByte **, int * );
 
 };
 
@@ -349,11 +354,12 @@ class OGRSQLiteTableLayer : public OGRSQLiteLayer
     OGRErr              RecomputeOrdinals();
 
     OGRErr              AddColumnAncientMethod( OGRFieldDefn& oField);
-    void                AddColumnDef(char* pszNewFieldList,
+    void                AddColumnDef(char* pszNewFieldList, size_t nBufLen,
                                      OGRFieldDefn* poFldDefn);
 
     void                InitFieldListForRecrerate(char* & pszNewFieldList,
                                                   char* & pszFieldListForSelect,
+                                                  size_t& nBufLenOut,
                                                   int nExtraSpace = 0);
     OGRErr              RecreateTable(const char* pszFieldListForSelect,
                                       const char* pszNewFieldList,
@@ -373,7 +379,7 @@ class OGRSQLiteTableLayer : public OGRSQLiteLayer
     void                LoadStatisticsSpatialite4DB();
 
     CPLString           FieldDefnToSQliteFieldDefn( OGRFieldDefn* poFieldDefn );
-    
+
     int                 bDeferredCreation;
     OGRErr              RunAddGeometryColumn( OGRSQLiteGeomFieldDefn *poGeomField,
                                               int bAddColumnsForNonSpatialite );
@@ -385,7 +391,7 @@ class OGRSQLiteTableLayer : public OGRSQLiteLayer
                         OGRSQLiteTableLayer( OGRSQLiteDataSource * );
                         ~OGRSQLiteTableLayer();
 
-    CPLErr              Initialize( const char *pszTableName, 
+    CPLErr              Initialize( const char *pszTableName,
                                     int bIsVirtualShapeIn,
                                     int bDeferredCreation);
     void                SetCreationParameters( const char *pszFIDColumnName,
@@ -428,7 +434,7 @@ class OGRSQLiteTableLayer : public OGRSQLiteLayer
                                          const char * pszDomain = "" );
 
     // follow methods are not base class overrides
-    void                SetLaunderFlag( int bFlag ) 
+    void                SetLaunderFlag( int bFlag )
                                 { bLaunderColumnNames = bFlag; }
     void                SetUseCompressGeom( int bFlag )
                                 { bUseComprGeom = bFlag; }
@@ -510,6 +516,8 @@ class OGRSQLiteViewLayer : public OGRSQLiteLayer
     virtual GIntBig     GetFeatureCount( int );
 
     virtual void        SetSpatialFilter( OGRGeometry * );
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+                { OGRSQLiteLayer::SetSpatialFilter(iGeomField, poGeom); }
     virtual OGRErr      SetAttributeFilter( const char * );
 
     virtual OGRFeature *GetFeature( GIntBig nFeatureId );
@@ -528,6 +536,8 @@ class OGRSQLiteViewLayer : public OGRSQLiteLayer
 class IOGRSQLiteSelectLayer
 {
     public:
+        virtual                     ~IOGRSQLiteSelectLayer() {}
+
         virtual char*&               GetAttrQueryString() = 0;
         virtual OGRFeatureQuery*&    GetFeatureQuery() = 0;
         virtual OGRGeometry*&        GetFilterGeom() = 0;
@@ -591,9 +601,9 @@ class OGRSQLiteSelectLayer : public OGRSQLiteLayer, public IOGRSQLiteSelectLayer
     OGRSQLiteSelectLayerCommonBehaviour* poBehaviour;
 
     virtual OGRErr      ResetStatement();
- 
+
   public:
-                        OGRSQLiteSelectLayer( OGRSQLiteDataSource *, 
+                        OGRSQLiteSelectLayer( OGRSQLiteDataSource *,
                                               CPLString osSQL,
                                               sqlite3_stmt *,
                                               int bUseStatementForGetNextFeature,
@@ -636,7 +646,7 @@ class OGRSQLiteSelectLayer : public OGRSQLiteLayer, public IOGRSQLiteSelectLayer
 /*                   OGRSQLiteSingleFeatureLayer                        */
 /************************************************************************/
 
-class OGRSQLiteSingleFeatureLayer : public OGRLayer
+class OGRSQLiteSingleFeatureLayer CPL_FINAL : public OGRLayer
 {
   private:
     int                 nVal;
@@ -687,13 +697,13 @@ class OGRSQLiteBaseDataSource : public GDALPamDataset
 
 #ifdef SPATIALITE_412_OR_LATER
     void               *hSpatialiteCtxt;
-    int                 InitNewSpatialite();
+    bool                InitNewSpatialite();
     void                FinishNewSpatialite();
 #endif
 
     int                 bUserTransactionActive;
     int                 nSoftTransactionLevel;
-    
+
     OGRErr              DoTransactionCommand(const char* pszCommand);
 
   public:
@@ -714,9 +724,11 @@ class OGRSQLiteBaseDataSource : public GDALPamDataset
     virtual OGRErr      StartTransaction(int bForce = FALSE);
     virtual OGRErr      CommitTransaction();
     virtual OGRErr      RollbackTransaction();
-    
+
     virtual int         TestCapability( const char * );
 
+    virtual void *GetInternalHandle( const char * );
+
     OGRErr              SoftStartTransaction();
     OGRErr              SoftCommitTransaction();
     OGRErr              SoftRollbackTransaction();
@@ -726,13 +738,13 @@ class OGRSQLiteBaseDataSource : public GDALPamDataset
 /*                         OGRSQLiteDataSource                          */
 /************************************************************************/
 
-class OGRSQLiteDataSource : public OGRSQLiteBaseDataSource
+class OGRSQLiteDataSource CPL_FINAL : public OGRSQLiteBaseDataSource
 {
     OGRSQLiteLayer    **papoLayers;
     int                 nLayers;
 
     // We maintain a list of known SRID to reduce the number of trips to
-    // the database to get SRSes. 
+    // the database to get SRSes.
     int                 nKnownSRID;
     int                *panSRID;
     OGRSpatialReference **papoSRS;
@@ -769,7 +781,7 @@ class OGRSQLiteDataSource : public OGRSQLiteBaseDataSource
     int                 Open( const char *, int bUpdateIn, char** papszOpenOptions );
     int                 Create( const char *, char **papszOptions );
 
-    int                 OpenTable( const char *pszTableName, 
+    int                 OpenTable( const char *pszTableName,
                                    int bIsVirtualShapeIn = FALSE );
     int                  OpenView( const char *pszViewName,
                                    const char *pszViewGeometry,
@@ -782,9 +794,9 @@ class OGRSQLiteDataSource : public OGRSQLiteBaseDataSource
     virtual OGRLayer   *GetLayerByName( const char* );
     virtual std::pair<OGRLayer*, IOGRSQLiteGetSpatialWhere*> GetLayerWithGetSpatialWhereByName( const char* pszName );
 
-    virtual OGRLayer    *ICreateLayer( const char *pszLayerName, 
-                                      OGRSpatialReference *poSRS, 
-                                      OGRwkbGeometryType eType, 
+    virtual OGRLayer    *ICreateLayer( const char *pszLayerName,
+                                      OGRSpatialReference *poSRS,
+                                      OGRwkbGeometryType eType,
                                       char **papszOptions );
     virtual OGRErr      DeleteLayer(int);
 
@@ -796,7 +808,7 @@ class OGRSQLiteDataSource : public OGRSQLiteBaseDataSource
     virtual void        ReleaseResultSet( OGRLayer * poLayer );
 
     virtual void        FlushCache();
-    
+
     virtual OGRErr      CommitTransaction();
     virtual OGRErr      RollbackTransaction();
 
@@ -825,6 +837,8 @@ class OGRSQLiteDataSource : public OGRSQLiteBaseDataSource
     void                ReloadLayers();
 };
 
+#endif /* DO_NOT_INCLUDE_SQLITE_CLASSES */
+
 /* To escape literals. The returned string doesn't contain the surrounding single quotes */
 CPLString OGRSQLiteEscape( const char *pszLiteral );
 
@@ -846,4 +860,6 @@ sqlite3_vfs* OGRSQLiteCreateVFS(pfnNotifyFileOpenedType pfn, void* pfnUserData);
 
 void OGRSQLiteRegisterInflateDeflate(sqlite3* hDB);
 
-#endif /* ndef _OGR_SQLITE_H_INCLUDED */
+void OGRSQLiteDriverUnload(GDALDriver*);
+
+#endif /* ndef OGR_SQLITE_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlite3ext.h b/ogr/ogrsf_frmts/sqlite/ogrsqlite3ext.h
index 3e7a40c..ea51a81 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlite3ext.h
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlite3ext.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqlite3ext.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: ogrsqlite3ext.h 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Custom version of sqlite3ext.h to workaround issues with Spatialite amalgamation
@@ -239,11 +239,11 @@ typedef struct sqlite3_backup ogr_sqlite3_backup;
 ** This header file defines the SQLite interface for use by
 ** shared libraries that want to be imported as extensions into
 ** an SQLite instance.  Shared libraries that intend to be loaded
-** as extensions by SQLite should #include this file instead of 
+** as extensions by SQLite should #include this file instead of
 ** sqlite3.h.
 */
-#ifndef _SQLITE3EXT_H_
-#define _SQLITE3EXT_H_
+#ifndef SQLITE3EXT_H_
+#define SQLITE3EXT_H_
 
 // Commented out to avoid reimporting the #define sqlite3_xxx macros
 //#include "sqlite3.h"
@@ -469,7 +469,7 @@ struct sqlite3_api_routines {
 
 /*
 ** The following macros redefine the API routines so that they are
-** redirected throught the global sqlite3_api structure.
+** redirected through the global sqlite3_api structure.
 **
 ** This header file is also used by the loadext.c source file
 ** (part of the main SQLite library - not an extension) so that
@@ -670,7 +670,7 @@ struct sqlite3_api_routines {
 #define sqlite3_vtab_on_conflict       sqlite3_api->vtab_on_conflict
 #endif /* SQLITE_CORE */
 
-#define SQLITE_EXTENSION_INIT1     const sqlite3_api_routines *sqlite3_api = 0;
+#define SQLITE_EXTENSION_INIT1     const sqlite3_api_routines *sqlite3_api = NULL;
 #define SQLITE_EXTENSION_INIT2(v)  sqlite3_api = v;
 
-#endif /* _SQLITE3EXT_H_ */
+#endif /* SQLITE3EXT_H_ */
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqliteapiroutines.c b/ogr/ogrsf_frmts/sqlite/ogrsqliteapiroutines.c
index c9ac266..76a2a70 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqliteapiroutines.c
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqliteapiroutines.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqliteapiroutines.c 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: ogrsqliteapiroutines.c 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Static registration of sqlite3 entry points
@@ -36,8 +36,8 @@
     /*
     / using an AMALGAMATED version of SpatiaLite
     / a private internal copy of SQLite is included:
-    / so we are required including the SpatiaLite's 
-    / own header 
+    / so we are required including the SpatiaLite's
+    / own header
     /
     / IMPORTANT NOTICE: using AMALAGATION is only
     / useful on Windows (to skip DLL hell related oddities)
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp
index 1d94574..09946a0 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqlitedatasource.cpp 29060 2015-04-29 21:49:46Z rouault $
+ * $Id: ogrsqlitedatasource.cpp 33821 2016-03-31 12:34:40Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteDataSource class.
@@ -9,7 +9,7 @@
  *
  * Contributor: Alessandro Furieri, a.furieri at lqt.it
  * Portions of this module properly supporting SpatiaLite Table/Geom creation
- * Developed for Faunalia ( http://www.faunalia.it) with funding from 
+ * Developed for Faunalia ( http://www.faunalia.it) with funding from
  * Regione Toscana - Settore SISTEMA INFORMATIVO TERRITORIALE ED AMBIENTALE
  *
  ******************************************************************************
@@ -40,9 +40,10 @@
 #include "cpl_string.h"
 #include "cpl_hash_set.h"
 #include "cpl_csv.h"
+#include "cpl_multiproc.h"
 #include "ogrsqlitevirtualogr.h"
 
-#ifdef HAVE_SPATIALITE
+#if defined(HAVE_SPATIALITE) && !defined(SPATIALITE_DLOPEN)
 #include "spatialite.h"
 #endif
 
@@ -50,7 +51,7 @@
 static int bSpatialiteGlobalLoaded = FALSE;
 #endif
 
-CPL_CVSID("$Id: ogrsqlitedatasource.cpp 29060 2015-04-29 21:49:46Z rouault $");
+CPL_CVSID("$Id: ogrsqlitedatasource.cpp 33821 2016-03-31 12:34:40Z rouault $");
 
 /************************************************************************/
 /*                      OGRSQLiteInitOldSpatialite()                    */
@@ -58,37 +59,137 @@ CPL_CVSID("$Id: ogrsqlitedatasource.cpp 29060 2015-04-29 21:49:46Z rouault $");
 
 #ifndef SPATIALITE_412_OR_LATER
 
+#ifdef HAVE_SPATIALITE
+static const char *(*pfn_spatialite_version) (void) = spatialite_version;
+#endif
+
 static int OGRSQLiteInitOldSpatialite()
 {
 /* -------------------------------------------------------------------- */
 /*      Try loading SpatiaLite.                                         */
 /* -------------------------------------------------------------------- */
 #ifdef HAVE_SPATIALITE
-    if (!bSpatialiteGlobalLoaded && CSLTestBoolean(CPLGetConfigOption("SPATIALITE_LOAD", "TRUE")))
+    if (!bSpatialiteGlobalLoaded && CPLTestBool(CPLGetConfigOption("SPATIALITE_LOAD", "TRUE")))
     {
         bSpatialiteGlobalLoaded = TRUE;
-        spatialite_init(CSLTestBoolean(CPLGetConfigOption("SPATIALITE_INIT_VERBOSE", "FALSE")));
+        spatialite_init(CPLTestBool(CPLGetConfigOption("SPATIALITE_INIT_VERBOSE", "FALSE")));
     }
 #endif
     return bSpatialiteGlobalLoaded;
 }
 
+/************************************************************************/
+/*                          OGRSQLiteDriverUnload()                     */
+/************************************************************************/
+
+void OGRSQLiteDriverUnload(GDALDriver*)
+{
+}
+
 #else
 
+#ifdef SPATIALITE_DLOPEN
+static CPLMutex* hMutexLoadSpatialiteSymbols = NULL;
+static void * (*pfn_spatialite_alloc_connection) (void) = NULL;
+static void (*pfn_spatialite_shutdown) (void) = NULL;
+static void (*pfn_spatialite_init_ex) (sqlite3*, const void *, int) = NULL;
+static void (*pfn_spatialite_cleanup_ex) (const void *) = NULL;
+static const char *(*pfn_spatialite_version) (void) = NULL;
+#else
+static void * (*pfn_spatialite_alloc_connection) (void) = spatialite_alloc_connection;
+static void (*pfn_spatialite_shutdown) (void) = spatialite_shutdown;
+static void (*pfn_spatialite_init_ex) (sqlite3*, const void *, int) = spatialite_init_ex;
+static void (*pfn_spatialite_cleanup_ex) (const void *) = spatialite_cleanup_ex;
+static const char *(*pfn_spatialite_version) (void) = spatialite_version;
+#endif
+
+#ifndef SPATIALITE_SONAME
+#define SPATIALITE_SONAME "libspatialite.so"
+#endif
+
+#ifdef SPATIALITE_DLOPEN
+static bool OGRSQLiteLoadSpatialiteSymbols()
+{
+    static bool bInitializationDone = false;
+    CPLMutexHolderD(&hMutexLoadSpatialiteSymbols);
+    if( bInitializationDone )
+      return pfn_spatialite_alloc_connection != NULL;
+    bInitializationDone = true;
+
+    const char *pszLibName = CPLGetConfigOption("SPATIALITESO",
+                                                SPATIALITE_SONAME);
+    CPLPushErrorHandler( CPLQuietErrorHandler );
+
+    /* coverity[tainted_string] */
+    pfn_spatialite_alloc_connection = (void* (*)(void))
+                    CPLGetSymbol( pszLibName, "spatialite_alloc_connection" );
+    CPLPopErrorHandler();
+
+    if( pfn_spatialite_alloc_connection == NULL )
+    {
+        CPLDebug("SQLITE", "Cannot find %s in %s", "spatialite_alloc_connection",
+                 pszLibName);
+        return false;
+    }
+
+    pfn_spatialite_shutdown = (void (*)(void))
+                    CPLGetSymbol( pszLibName, "spatialite_shutdown" );
+    pfn_spatialite_init_ex = (void (*)(sqlite3*, const void *, int))
+                    CPLGetSymbol( pszLibName, "spatialite_init_ex" );
+    pfn_spatialite_cleanup_ex = (void (*)(const void *))
+                    CPLGetSymbol( pszLibName, "spatialite_cleanup_ex" );
+    pfn_spatialite_version = (const char* (*)(void))
+                    CPLGetSymbol( pszLibName, "spatialite_version" );
+    if( pfn_spatialite_shutdown == NULL ||
+        pfn_spatialite_init_ex == NULL ||
+        pfn_spatialite_cleanup_ex == NULL ||
+        pfn_spatialite_version == NULL )
+    {
+        pfn_spatialite_shutdown = NULL;
+        pfn_spatialite_init_ex = NULL;
+        pfn_spatialite_cleanup_ex = NULL;
+        pfn_spatialite_version = NULL;
+        return false;
+    }
+    return true;
+}
+#endif
+
+/************************************************************************/
+/*                          OGRSQLiteDriverUnload()                     */
+/************************************************************************/
+
+void OGRSQLiteDriverUnload(GDALDriver*)
+{
+    if( pfn_spatialite_shutdown != NULL )
+        pfn_spatialite_shutdown();
+#ifdef SPATIALITE_DLOPEN
+    if( hMutexLoadSpatialiteSymbols != NULL )
+    {
+        CPLDestroyMutex(hMutexLoadSpatialiteSymbols);
+        hMutexLoadSpatialiteSymbols = NULL;
+    }
+#endif
+}
+
 /************************************************************************/
 /*                          InitNewSpatialite()                         */
 /************************************************************************/
 
-int OGRSQLiteBaseDataSource::InitNewSpatialite()
+bool OGRSQLiteBaseDataSource::InitNewSpatialite()
 {
-    if( CSLTestBoolean(CPLGetConfigOption("SPATIALITE_LOAD", "TRUE")) )
+    if( CPLTestBool(CPLGetConfigOption("SPATIALITE_LOAD", "TRUE")) )
     {
+#ifdef SPATIALITE_DLOPEN
+        if( !OGRSQLiteLoadSpatialiteSymbols() )
+            return false;
+#endif
         CPLAssert(hSpatialiteCtxt == NULL);
-        hSpatialiteCtxt = spatialite_alloc_connection();
+        hSpatialiteCtxt = pfn_spatialite_alloc_connection();
         if( hSpatialiteCtxt != NULL )
         {
-            spatialite_init_ex(hDB, hSpatialiteCtxt,
-                CSLTestBoolean(CPLGetConfigOption("SPATIALITE_INIT_VERBOSE", "FALSE")));
+            pfn_spatialite_init_ex(hDB, hSpatialiteCtxt,
+                CPLTestBool(CPLGetConfigOption("SPATIALITE_INIT_VERBOSE", "FALSE")));
         }
     }
     return hSpatialiteCtxt != NULL;
@@ -102,7 +203,7 @@ void OGRSQLiteBaseDataSource::FinishNewSpatialite()
 {
     if( hSpatialiteCtxt != NULL )
     {
-        spatialite_cleanup_ex(hSpatialiteCtxt);
+        pfn_spatialite_cleanup_ex(hSpatialiteCtxt);
         hSpatialiteCtxt = NULL;
     }
 }
@@ -132,7 +233,7 @@ int OGRSQLiteDataSource::GetSpatialiteVersionNumber()
 #ifdef HAVE_SPATIALITE
     if( IsSpatialiteLoaded() )
     {
-        v = (int)(( CPLAtof( spatialite_version() ) + 0.001 )  * 10.0);
+        v = (int)(( CPLAtof( pfn_spatialite_version() ) + 0.001 )  * 10.0);
     }
 #endif
     return v;
@@ -249,7 +350,7 @@ OGRSQLiteDataSource::~OGRSQLiteDataSource()
 
     for( i = 0; i < nLayers; i++ )
         delete papoLayers[i];
-    
+
     CPLFree( papoLayers );
 
     for( i = 0; i < nKnownSRID; i++ )
@@ -431,8 +532,10 @@ int OGRSQLiteBaseDataSource::SetCacheSize()
             sqlite3_free( pszErrMsg );
             return TRUE;
         }
-		
+
         /* computing the CacheSize as #Pages */
+        if( iSqlitePageSize == 0 )
+            return TRUE;
         iSqliteCachePages = iSqliteCacheBytes / iSqlitePageSize;
         if( iSqliteCachePages <= 0)
             return TRUE;
@@ -446,7 +549,6 @@ int OGRSQLiteBaseDataSource::SetCacheSize()
                       "Unrecognized value for PRAGMA cache_size : %s",
                       pszErrMsg );
             sqlite3_free( pszErrMsg );
-            rc = SQLITE_OK;
         }
     }
     return TRUE;
@@ -553,12 +655,12 @@ const struct sqlite3_mem_methods sDebugMemAlloc =
 /*                            OpenOrCreateDB()                          */
 /************************************************************************/
 
-int OGRSQLiteBaseDataSource::OpenOrCreateDB(int flags, int bRegisterOGR2SQLiteExtensions)
+int OGRSQLiteBaseDataSource::OpenOrCreateDB(int flagsIn, int bRegisterOGR2SQLiteExtensions)
 {
     int rc;
 
 #ifdef USE_SQLITE_DEBUG_MEMALLOC
-    if( CSLTestBoolean(CPLGetConfigOption("USE_SQLITE_DEBUG_MEMALLOC", "NO")) )
+    if( CPLTestBool(CPLGetConfigOption("USE_SQLITE_DEBUG_MEMALLOC", "NO")) )
         sqlite3_config(SQLITE_CONFIG_MALLOC, &sDebugMemAlloc);
 #endif
 
@@ -566,8 +668,20 @@ int OGRSQLiteBaseDataSource::OpenOrCreateDB(int flags, int bRegisterOGR2SQLiteEx
     if( bRegisterOGR2SQLiteExtensions )
         OGR2SQLITE_Register();
 
-    int bUseOGRVFS = CSLTestBoolean(CPLGetConfigOption("SQLITE_USE_OGR_VFS", "NO"));
-    if (bUseOGRVFS || strncmp(m_pszFilename, "/vsi", 4) == 0)
+    int flags = flagsIn;
+#ifdef SQLITE_OPEN_URI
+    // This code enables support for named memory databases in SQLite.
+    // SQLITE_USE_URI is checked only to enable backward compatibility, in
+    // case we accidentally hijacked some other format.
+    if( STARTS_WITH(m_pszFilename, "file:") &&
+        CPLTestBool(CPLGetConfigOption("SQLITE_USE_URI", "YES")) )
+    {
+        flags |= SQLITE_OPEN_URI;
+    }
+#endif
+
+    int bUseOGRVFS = CPLTestBool(CPLGetConfigOption("SQLITE_USE_OGR_VFS", "NO"));
+    if (bUseOGRVFS || STARTS_WITH(m_pszFilename, "/vsi"))
     {
         pMyVFS = OGRSQLiteCreateVFS(OGRSQLiteBaseDataSourceNotifyFileOpened, this);
         sqlite3_vfs_register(pMyVFS, 0);
@@ -603,9 +717,9 @@ int OGRSQLiteBaseDataSource::OpenOrCreateDB(int flags, int bRegisterOGR2SQLiteEx
 
     if( nRowCount > 0 )
     {
-        if( !CSLTestBoolean(CPLGetConfigOption("ALLOW_OGR_SQL_FUNCTIONS_FROM_TRIGGER_AND_VIEW", "NO")) )
+        if( !CPLTestBool(CPLGetConfigOption("ALLOW_OGR_SQL_FUNCTIONS_FROM_TRIGGER_AND_VIEW", "NO")) )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, "%s", 
+            CPLError( CE_Failure, CPLE_OpenFailed, "%s",
                 "A trigger and/or view calls a OGR extension SQL function that could be used to "
                 "steal data, or use network bandwidth, without your consent.\n"
                 "The database will not be opened unless the ALLOW_OGR_SQL_FUNCTIONS_FROM_TRIGGER_AND_VIEW "
@@ -618,8 +732,6 @@ int OGRSQLiteBaseDataSource::OpenOrCreateDB(int flags, int bRegisterOGR2SQLiteEx
     if (pszSqliteJournal != NULL)
     {
         char* pszErrMsg = NULL;
-        char **papszResult;
-        int nRowCount, nColCount;
 
         const char* pszSQL = CPLSPrintf("PRAGMA journal_mode = %s",
                                         pszSqliteJournal);
@@ -644,8 +756,6 @@ int OGRSQLiteBaseDataSource::OpenOrCreateDB(int flags, int bRegisterOGR2SQLiteEx
         for(int i=0; papszTokens[i] != NULL; i++ )
         {
             char* pszErrMsg = NULL;
-            char **papszResult;
-            int nRowCount, nColCount;
 
             const char* pszSQL = CPLSPrintf("PRAGMA %s", papszTokens[i]);
 
@@ -674,6 +784,18 @@ int OGRSQLiteBaseDataSource::OpenOrCreateDB(int flags, int bRegisterOGR2SQLiteEx
 }
 
 /************************************************************************/
+/*                          GetInternalHandle()                         */
+/************************************************************************/
+
+/* Used by MBTILES driver */
+void *OGRSQLiteBaseDataSource::GetInternalHandle( const char * pszKey )
+{
+    if( pszKey != NULL && EQUAL(pszKey, "SQLITE_HANDLE") )
+        return hDB;
+    return NULL;
+}
+
+/************************************************************************/
 /*                               Create()                               */
 /************************************************************************/
 
@@ -743,9 +865,9 @@ int OGRSQLiteDataSource::Create( const char * pszNameIn, char **papszOptions )
         / [by-passing InitSpatialMetadata() as absolutely required]
         / will severely [and irremediably] corrupt the DB !!!
         */
-        
+
         const char* pszVal = CSLFetchNameValue( papszOptions, "INIT_WITH_EPSG" );
-        if( pszVal != NULL && !CSLTestBoolean(pszVal) &&
+        if( pszVal != NULL && !CPLTestBool(pszVal) &&
             GetSpatialiteVersionNumber() >= 40 )
             osCommand =  "SELECT InitSpatialMetadata('NONE')";
         else
@@ -811,7 +933,7 @@ int OGRSQLiteDataSource::Create( const char * pszNameIn, char **papszOptions )
     }
 
 /* -------------------------------------------------------------------- */
-/*      Optionnaly initialize the content of the spatial_ref_sys table  */
+/*      Optionally initialize the content of the spatial_ref_sys table  */
 /*      with the EPSG database                                          */
 /* -------------------------------------------------------------------- */
     if ( (bSpatialite || bMetadata) &&
@@ -842,7 +964,7 @@ int OGRSQLiteDataSource::InitWithEPSG()
         if ( iSpatialiteVersion >= 24 )
             return TRUE;
     }
-    
+
     if( SoftStartTransaction() != OGRERR_NONE )
         return FALSE;
 
@@ -1072,21 +1194,21 @@ int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn,
     {
         nFileTimestamp = sStat.st_mtime;
     }
-    
+
     if( papszOpenOptionsIn )
     {
         CSLDestroy(papszOpenOptions);
         papszOpenOptions = CSLDuplicate(papszOpenOptionsIn);
     }
-    
-    int bListAllTables = CSLTestBoolean(CSLFetchNameValueDef(
+
+    int bListAllTables = CPLTestBool(CSLFetchNameValueDef(
         papszOpenOptions, "LIST_ALL_TABLES",
         CPLGetConfigOption("SQLITE_LIST_ALL_TABLES", "NO")));
 
     // Don't list by default: there might be some security implications
     // if a user is provided with a file and doesn't know that there are
     // virtual OGR tables in it.
-    int bListVirtualOGRLayers = CSLTestBoolean(CSLFetchNameValueDef(
+    int bListVirtualOGRLayers = CPLTestBool(CSLFetchNameValueDef(
         papszOpenOptions, "LIST_VIRTUAL_OGR",
         CPLGetConfigOption("OGR_SQLITE_LIST_VIRTUAL_OGR", "NO")));
 
@@ -1118,7 +1240,7 @@ int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn,
 
     CPLHashSet* hSet = CPLHashSetNew(CPLHashSetHashStr, CPLHashSetEqualStr, CPLFree);
 
-    rc = sqlite3_get_table( 
+    rc = sqlite3_get_table(
         hDB,
         "SELECT f_table_name, f_geometry_column, geometry_type, coord_dimension, geometry_format, srid"
         " FROM geometry_columns",
@@ -1127,7 +1249,7 @@ int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn,
     if( rc == SQLITE_OK )
     {
         CPLDebug("SQLITE", "OGR style SQLite DB found !");
-    
+
         bHaveGeometryColumns = TRUE;
 
         for ( iRow = 0; iRow < nRowCount; iRow++ )
@@ -1166,7 +1288,7 @@ int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn,
         {
             rc = sqlite3_get_table( hDB,
                                 "SELECT name, sql FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE %'",
-                                &papszResult, &nRowCount, 
+                                &papszResult, &nRowCount,
                                 &nColCount, &pszErrMsg );
 
             if ( rc == SQLITE_OK )
@@ -1190,8 +1312,8 @@ int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn,
             }
             else
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                        "Unable to fetch list of tables: %s", 
+                CPLError( CE_Failure, CPLE_AppDefined,
+                        "Unable to fetch list of tables: %s",
                         pszErrMsg );
                 sqlite3_free( pszErrMsg );
             }
@@ -1201,9 +1323,9 @@ int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn,
 
         if (bListAllTables)
             goto all_tables;
-            
+
         CPLHashSetDestroy(hSet);
-        
+
         return TRUE;
     }
 
@@ -1215,7 +1337,7 @@ int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn,
                             "SELECT f_table_name, f_geometry_column, "
                             "type, coord_dimension, srid, "
                             "spatial_index_enabled FROM geometry_columns",
-                            &papszResult, &nRowCount, 
+                            &papszResult, &nRowCount,
                             &nColCount, &pszErrMsg );
     if (rc != SQLITE_OK )
     {
@@ -1248,18 +1370,22 @@ int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn,
         }
         else if( bUpdate )
         {
-            CPLDebug("SQLITE", "SpatiaLite%s DB found, "
+            CPLError(CE_Failure, CPLE_AppDefined, "SpatiaLite%s DB found, "
                      "but updating tables disabled because no linking against spatialite library !",
                      (bSpatialite4Layout) ? " v4" : "");
-            bUpdate = FALSE;
+            sqlite3_free_table(papszResult);
+            CPLHashSetDestroy(hSet);
+            return FALSE;
         }
 
         if (bSpatialite4Layout && bUpdate && iSpatialiteVersion > 0 && iSpatialiteVersion < 40)
         {
-            CPLDebug("SQLITE", "SpatiaLite v4 DB found, "
+            CPLError(CE_Failure, CPLE_AppDefined, "SpatiaLite v4 DB found, "
                      "but updating tables disabled because runtime spatialite library is v%.1f !",
                      iSpatialiteVersion / 10.0);
-            bUpdate = FALSE;
+            sqlite3_free_table(papszResult);
+            CPLHashSetDestroy(hSet);
+            return FALSE;
         }
         else
         {
@@ -1294,13 +1420,14 @@ int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn,
         }
 
         sqlite3_free_table(papszResult);
+        papszResult = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Detect VirtualShape, VirtualXL and VirtualOGR layers            */
 /* -------------------------------------------------------------------- */
         rc = sqlite3_get_table( hDB,
                             "SELECT name, sql FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE %'",
-                            &papszResult, &nRowCount, 
+                            &papszResult, &nRowCount,
                             &nColCount, &pszErrMsg );
 
         if ( rc == SQLITE_OK )
@@ -1326,21 +1453,23 @@ int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn,
         }
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                    "Unable to fetch list of tables: %s", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                    "Unable to fetch list of tables: %s",
                     pszErrMsg );
             sqlite3_free( pszErrMsg );
         }
 
         sqlite3_free_table(papszResult);
+        papszResult = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Detect spatial views                                            */
 /* -------------------------------------------------------------------- */
+
         rc = sqlite3_get_table( hDB,
                                 "SELECT view_name, view_geometry, view_rowid, f_table_name, f_geometry_column FROM views_geometry_columns",
                                 &papszResult, &nRowCount,
-                                &nColCount, &pszErrMsg );
+                                &nColCount, NULL );
         if ( rc == SQLITE_OK )
         {
             for( iRow = 0; iRow < nRowCount; iRow++ )
@@ -1373,7 +1502,7 @@ int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn,
             goto all_tables;
 
         CPLHashSetDestroy(hSet);
-        
+
         return TRUE;
     }
 
@@ -1382,7 +1511,7 @@ int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn,
 /*      as non-spatial tables.                                          */
 /* -------------------------------------------------------------------- */
     sqlite3_free( pszErrMsg );
-    
+
 all_tables:
     rc = sqlite3_get_table( hDB,
                             "SELECT name FROM sqlite_master "
@@ -1391,26 +1520,26 @@ all_tables:
                             "SELECT name FROM sqlite_temp_master "
                             "WHERE type IN ('table','view') "
                             "ORDER BY 1",
-                            &papszResult, &nRowCount, 
+                            &papszResult, &nRowCount,
                             &nColCount, &pszErrMsg );
 
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Unable to fetch list of tables: %s", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Unable to fetch list of tables: %s",
                   pszErrMsg );
         sqlite3_free( pszErrMsg );
         CPLHashSetDestroy(hSet);
         return FALSE;
     }
-    
+
     for( iRow = 0; iRow < nRowCount; iRow++ )
     {
         const char* pszTableName = papszResult[iRow+1];
-        if (CPLHashSetLookup(hSet, pszTableName) == NULL)
+        if( pszTableName != NULL && CPLHashSetLookup(hSet, pszTableName) == NULL )
             OpenTable( pszTableName );
     }
-    
+
     sqlite3_free_table(papszResult);
     CPLHashSetDestroy(hSet);
 
@@ -1497,7 +1626,7 @@ int OGRSQLiteDataSource::OpenTable( const char *pszTableName,
     papoLayers = (OGRSQLiteLayer **)
         CPLRealloc( papoLayers,  sizeof(OGRSQLiteLayer *) * (nLayers+1) );
     papoLayers[nLayers++] = poLayer;
-    
+
     return TRUE;
 }
 
@@ -1549,6 +1678,8 @@ int OGRSQLiteDataSource::TestCapability( const char * pszCap )
         return bUpdate;
     else if( EQUAL(pszCap,ODsCCurveGeometries) )
         return !bIsSpatiaLiteDB;
+    else if( EQUAL(pszCap,ODsCMeasuredGeometries) )
+        return TRUE;
     else if EQUAL(pszCap,ODsCCreateGeomFieldAfterCreateLayer)
         return bUpdate;
     else
@@ -1643,7 +1774,7 @@ void OGRSQLiteDataSource::FlushCache()
 /*                             ExecuteSQL()                             */
 /************************************************************************/
 
-static const char* apszFuncsWithSideEffects[] =
+static const char* const apszFuncsWithSideEffects[] =
 {
     "InitSpatialMetaData",
     "AddGeometryColumn",
@@ -1673,14 +1804,14 @@ OGRLayer * OGRSQLiteDataSource::ExecuteSQL( const char *pszSQLCommand,
     }
 
     if( pszDialect != NULL && EQUAL(pszDialect,"OGRSQL") )
-        return GDALDataset::ExecuteSQL( pszSQLCommand, 
-                                          poSpatialFilter, 
+        return GDALDataset::ExecuteSQL( pszSQLCommand,
+                                          poSpatialFilter,
                                           pszDialect );
 
 /* -------------------------------------------------------------------- */
 /*      Special case DELLAYER: command.                                 */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszSQLCommand,"DELLAYER:",9) )
+    if( STARTS_WITH_CI(pszSQLCommand, "DELLAYER:") )
     {
         const char *pszLayerName = pszSQLCommand + 9;
 
@@ -1752,9 +1883,9 @@ OGRLayer * OGRSQLiteDataSource::ExecuteSQL( const char *pszSQLCommand,
             }
         }
     }
-    else if( !EQUALN(pszSQLCommand,"SELECT ",7) && !EQUAL(pszSQLCommand, "BEGIN")
+    else if( !STARTS_WITH_CI(pszSQLCommand, "SELECT ") && !EQUAL(pszSQLCommand, "BEGIN")
         && !EQUAL(pszSQLCommand, "COMMIT")
-        && !EQUALN(pszSQLCommand, "CREATE TABLE ", strlen("CREATE TABLE ")) )
+        && !STARTS_WITH_CI(pszSQLCommand, "CREATE TABLE ") )
     {
         for(int i = 0; i < nLayers; i++)
             papoLayers[i]->InvalidateCachedFeatureCountAndExtent();
@@ -1790,13 +1921,14 @@ OGRLayer * OGRSQLiteDataSource::ExecuteSQL( const char *pszSQLCommand,
         }
     }
 
-    rc = sqlite3_prepare( GetDB(), osSQLCommand.c_str(), osSQLCommand.size(),
+    rc = sqlite3_prepare( GetDB(), osSQLCommand.c_str(),
+                          static_cast<int>(osSQLCommand.size()),
                           &hSQLStmt, NULL );
 
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                "In ExecuteSQL(): sqlite3_prepare(%s):\n  %s", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                "In ExecuteSQL(): sqlite3_prepare(%s):\n  %s",
                 pszSQLCommand, sqlite3_errmsg(GetDB()) );
 
         if( hSQLStmt != NULL )
@@ -1815,15 +1947,15 @@ OGRLayer * OGRSQLiteDataSource::ExecuteSQL( const char *pszSQLCommand,
     {
         if ( rc != SQLITE_DONE )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                  "In ExecuteSQL(): sqlite3_step(%s):\n  %s", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                  "In ExecuteSQL(): sqlite3_step(%s):\n  %s",
                   pszSQLCommand, sqlite3_errmsg(GetDB()) );
 
             sqlite3_finalize( hSQLStmt );
             return NULL;
         }
 
-        if( EQUALN(pszSQLCommand, "CREATE ", 7) )
+        if( STARTS_WITH_CI(pszSQLCommand, "CREATE ") )
         {
             char **papszTokens = CSLTokenizeString( pszSQLCommand );
             if ( CSLCount(papszTokens) >= 4 &&
@@ -1838,7 +1970,7 @@ OGRLayer * OGRSQLiteDataSource::ExecuteSQL( const char *pszSQLCommand,
             return NULL;
         }
 
-        if( !EQUALN(pszSQLCommand, "SELECT ", 7) )
+        if( !STARTS_WITH_CI(pszSQLCommand, "SELECT ") )
         {
             sqlite3_finalize( hSQLStmt );
             return NULL;
@@ -1847,12 +1979,12 @@ OGRLayer * OGRSQLiteDataSource::ExecuteSQL( const char *pszSQLCommand,
         bUseStatementForGetNextFeature = FALSE;
         bEmptyLayer = TRUE;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Special case for some functions which must be run               */
 /*      only once                                                       */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszSQLCommand,"SELECT ",7) )
+    if( STARTS_WITH_CI(pszSQLCommand, "SELECT ") )
     {
         unsigned int i;
         for(i=0;i<sizeof(apszFuncsWithSideEffects)/
@@ -1879,14 +2011,14 @@ OGRLayer * OGRSQLiteDataSource::ExecuteSQL( const char *pszSQLCommand,
 /*      Create layer.                                                   */
 /* -------------------------------------------------------------------- */
     OGRSQLiteSelectLayer *poLayer = NULL;
-        
+
     CPLString osSQL = pszSQLCommand;
     poLayer = new OGRSQLiteSelectLayer( this, osSQL, hSQLStmt,
                                         bUseStatementForGetNextFeature, bEmptyLayer, TRUE );
 
     if( poSpatialFilter != NULL )
         poLayer->SetSpatialFilter( 0, poSpatialFilter );
-    
+
     return poLayer;
 }
 
@@ -1963,17 +2095,17 @@ OGRSQLiteDataSource::ICreateLayer( const char * pszLayerNameIn,
             pszGeomFormat = "SpatiaLite";
     }
 
-    if( !EQUAL(pszGeomFormat,"WKT") 
+    if( !EQUAL(pszGeomFormat,"WKT")
         && !EQUAL(pszGeomFormat,"WKB")
         && !EQUAL(pszGeomFormat, "SpatiaLite") )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
-                  "FORMAT=%s not recognised or supported.", 
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "FORMAT=%s not recognised or supported.",
                   pszGeomFormat );
         CPLFree( pszLayerName );
         return NULL;
     }
-    
+
     CPLString osGeometryName;
     const char* pszGeometryNameIn = CSLFetchNameValue( papszOptions, "GEOMETRY_NAME" );
     if( pszGeometryNameIn == NULL )
@@ -2001,8 +2133,8 @@ OGRSQLiteDataSource::ICreateLayer( const char * pszLayerNameIn,
         return NULL;
     }
 
-    /* Shouldn't happen since a spatialite DB should be opened in read-only mode */
-    /* if libspatialite isn't loaded */
+    // Should not happen since a spatialite DB should be opened in
+    // read-only mode if libspatialite is not loaded.
     if (bIsSpatiaLiteDB && !IsSpatialiteLoaded())
     {
         CPLError( CE_Failure, CPLE_NotSupported,
@@ -2029,7 +2161,7 @@ OGRSQLiteDataSource::ICreateLayer( const char * pszLayerNameIn,
             }
             else
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "Layer %s already exists, CreateLayer failed.\n"
                           "Use the layer creation option OVERWRITE=YES to "
                           "replace it.",
@@ -2067,7 +2199,7 @@ OGRSQLiteDataSource::ICreateLayer( const char * pszLayerNameIn,
     const char* pszSI = CSLFetchNameValue( papszOptions, "SPATIAL_INDEX" );
     if( bHaveGeometryColumns && eType != wkbNone )
     {
-        if ( pszSI != NULL && CSLTestBoolean(pszSI) &&
+        if ( pszSI != NULL && CPLTestBool(pszSI) &&
              (bIsSpatiaLiteDB || EQUAL(pszGeomFormat, "SpatiaLite")) && !IsSpatialiteLoaded() )
         {
             CPLError( CE_Warning, CPLE_OpenFailed,
@@ -2085,7 +2217,7 @@ OGRSQLiteDataSource::ICreateLayer( const char * pszLayerNameIn,
             {
                 bImmediateSpatialIndexCreation = TRUE;
             }
-            else if( pszSI == NULL || CSLTestBoolean(pszSI) )
+            else if( pszSI == NULL || CPLTestBool(pszSI) )
             {
                 bDeferredSpatialIndexCreation = TRUE;
             }
@@ -2094,7 +2226,7 @@ OGRSQLiteDataSource::ICreateLayer( const char * pszLayerNameIn,
     else if( bHaveGeometryColumns )
     {
 #ifdef HAVE_SPATIALITE
-        if( bIsSpatiaLiteDB && IsSpatialiteLoaded() && (pszSI == NULL || CSLTestBoolean(pszSI)) )
+        if( bIsSpatiaLiteDB && IsSpatialiteLoaded() && (pszSI == NULL || CPLTestBool(pszSI)) )
             bDeferredSpatialIndexCreation = TRUE;
 #endif
     }
@@ -2115,7 +2247,7 @@ OGRSQLiteDataSource::ICreateLayer( const char * pszLayerNameIn,
 /* -------------------------------------------------------------------- */
     papoLayers = (OGRSQLiteLayer **)
         CPLRealloc( papoLayers,  sizeof(OGRSQLiteLayer *) * (nLayers+1) );
-    
+
     papoLayers[nLayers++] = poLayer;
 
     poLayer->InitFeatureCount();
@@ -2162,7 +2294,7 @@ CPLString OGRSQLiteParamsUnquote(const char* pszVal)
     char chQuoteChar = pszVal[0];
     if( chQuoteChar != '\'' && chQuoteChar != '"' )
         return pszVal;
-    
+
     CPLString osRet;
     pszVal ++;
     while( *pszVal != '\0' )
@@ -2247,8 +2379,8 @@ void OGRSQLiteDataSource::DeleteLayer( const char *pszLayerName )
 
     if( iLayer == nLayers )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Attempt to delete layer '%s', but this layer is not known to OGR.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Attempt to delete layer '%s', but this layer is not known to OGR.",
                   pszLayerName );
         return;
     }
@@ -2280,7 +2412,7 @@ OGRErr OGRSQLiteDataSource::DeleteLayer(int iLayer)
     CPLDebug( "OGR_SQLITE", "DeleteLayer(%s)", osLayerName.c_str() );
 
     delete papoLayers[iLayer];
-    memmove( papoLayers + iLayer, papoLayers + iLayer + 1, 
+    memmove( papoLayers + iLayer, papoLayers + iLayer + 1,
              sizeof(void *) * (nLayers - iLayer - 1) );
     nLayers--;
 
@@ -2298,7 +2430,7 @@ OGRErr OGRSQLiteDataSource::DeleteLayer(int iLayer)
                        NULL, NULL, &pszErrMsg );
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to drop table %s: %s",
                   osLayerName.c_str(), pszErrMsg );
         sqlite3_free( pszErrMsg );
@@ -2312,15 +2444,15 @@ OGRErr OGRSQLiteDataSource::DeleteLayer(int iLayer)
     {
         CPLString osCommand;
 
-        osCommand.Printf( 
+        osCommand.Printf(
             "DELETE FROM geometry_columns WHERE f_table_name = '%s'",
             pszEscapedLayerName );
-        
+
         rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
         if( rc != SQLITE_OK )
         {
             CPLError( CE_Warning, CPLE_AppDefined,
-                      "Removal from geometry_columns failed.\n%s: %s", 
+                      "Removal from geometry_columns failed.\n%s: %s",
                       osCommand.c_str(), pszErrMsg );
             sqlite3_free( pszErrMsg );
             return OGRERR_FAILURE;
@@ -2333,19 +2465,19 @@ OGRErr OGRSQLiteDataSource::DeleteLayer(int iLayer)
         {
             osCommand.Printf( "DROP TABLE 'idx_%s_%s'", pszEscapedLayerName,
                               OGRSQLiteEscape(pszGeometryColumn).c_str());
-            rc = sqlite3_exec( hDB, osCommand, NULL, NULL, NULL );
+            CPL_IGNORE_RET_VAL(sqlite3_exec( hDB, osCommand, NULL, NULL, NULL ));
 
             osCommand.Printf( "DROP TABLE 'idx_%s_%s_node'", pszEscapedLayerName,
                               OGRSQLiteEscape(pszGeometryColumn).c_str());
-            rc = sqlite3_exec( hDB, osCommand, NULL, NULL, NULL );
+            CPL_IGNORE_RET_VAL(sqlite3_exec( hDB, osCommand, NULL, NULL, NULL ));
 
             osCommand.Printf( "DROP TABLE 'idx_%s_%s_parent'", pszEscapedLayerName,
                               OGRSQLiteEscape(pszGeometryColumn).c_str());
-            rc = sqlite3_exec( hDB, osCommand, NULL, NULL, NULL );
+            CPL_IGNORE_RET_VAL(sqlite3_exec( hDB, osCommand, NULL, NULL, NULL ));
 
             osCommand.Printf( "DROP TABLE 'idx_%s_%s_rowid'", pszEscapedLayerName,
                               OGRSQLiteEscape(pszGeometryColumn).c_str());
-            rc = sqlite3_exec( hDB, osCommand, NULL, NULL, NULL );
+            CPL_IGNORE_RET_VAL(sqlite3_exec( hDB, osCommand, NULL, NULL, NULL ));
         }
     }
     return OGRERR_NONE;
@@ -2475,7 +2607,7 @@ OGRErr OGRSQLiteBaseDataSource::SoftStartTransaction()
     {
         eErr = DoTransactionCommand("BEGIN");
     }
-    
+
     //CPLDebug("SQLite", "%p->SoftStartTransaction() : %d",
     //         this, nSoftTransactionLevel);
 
@@ -2558,7 +2690,7 @@ OGRErr OGRSQLiteBaseDataSource::DoTransactionCommand(const char* pszCommand)
     if( rc != SQLITE_OK )
     {
         nSoftTransactionLevel--;
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "%s transaction failed: %s",
                   pszCommand, pszErrMsg );
         sqlite3_free( pszErrMsg );
@@ -2710,7 +2842,7 @@ int OGRSQLiteDataSource::FetchSRSId( OGRSpatialReference * poSRS )
                               "auth_name = '%s' COLLATE NOCASE AND auth_srid = '%s'",
                               pszAuthorityName, pszAuthorityCode );
 
-            rc = sqlite3_get_table( hDB, osCommand, &papszResult, 
+            rc = sqlite3_get_table( hDB, osCommand, &papszResult,
                                     &nRowCount, &nColCount, &pszErrMsg );
             if( rc != SQLITE_OK )
             {
@@ -2721,7 +2853,7 @@ int OGRSQLiteDataSource::FetchSRSId( OGRSpatialReference * poSRS )
                                   "auth_name = '%s' AND auth_srid = '%s'",
                                   pszAuthorityName, pszAuthorityCode );
 
-                rc = sqlite3_get_table( hDB, osCommand, &papszResult, 
+                rc = sqlite3_get_table( hDB, osCommand, &papszResult,
                                         &nRowCount, &nColCount, &pszErrMsg );
 
                 /* Retry in lower case for SpatiaLite */
@@ -2739,7 +2871,7 @@ int OGRSQLiteDataSource::FetchSRSId( OGRSpatialReference * poSRS )
                                       "auth_name = 'epsg' AND auth_srid = '%s'",
                                       pszAuthorityCode );
 
-                    rc = sqlite3_get_table( hDB, osCommand, &papszResult, 
+                    rc = sqlite3_get_table( hDB, osCommand, &papszResult,
                                             &nRowCount, &nColCount, &pszErrMsg );
 
                     if( rc != SQLITE_OK )
@@ -2869,9 +3001,9 @@ int OGRSQLiteDataSource::FetchSRSId( OGRSpatialReference * poSRS )
         if( oSRS.exportToProj4( &pszProj4 ) == OGRERR_NONE )
         {
             osProj4 = pszProj4;
-            CPLFree( pszProj4 );
-            pszProj4 = NULL;
         }
+        CPLFree( pszProj4 );
+        pszProj4 = NULL;
     }
 
 /* -------------------------------------------------------------------- */
@@ -2884,7 +3016,7 @@ int OGRSQLiteDataSource::FetchSRSId( OGRSpatialReference * poSRS )
                           OGRSQLiteEscape(pszAuthorityCode).c_str() );
         rc = sqlite3_get_table( hDB, osCommand, &papszResult,
                                 &nRowCount, &nColCount, &pszErrMsg );
-        
+
         if( rc != SQLITE_OK )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -2917,10 +3049,10 @@ int OGRSQLiteDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 /* -------------------------------------------------------------------- */
     if ( nSRSId == nUndefinedSRID )
     {
-        rc = sqlite3_get_table( hDB, "SELECT MAX(srid) FROM spatial_ref_sys", 
+        rc = sqlite3_get_table( hDB, "SELECT MAX(srid) FROM spatial_ref_sys",
                                 &papszResult, &nRowCount, &nColCount,
                                 &pszErrMsg );
-        
+
         if( rc != SQLITE_OK )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -3049,7 +3181,7 @@ int OGRSQLiteDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 
     if( rc != SQLITE_OK && rc != SQLITE_DONE )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to insert SRID (%s): %s",
                   osCommand.c_str(), sqlite3_errmsg(hDB) );
 
@@ -3102,7 +3234,7 @@ OGRSpatialReference *OGRSQLiteDataSource::FetchSRS( int nId )
 
     osCommand.Printf( "SELECT srtext FROM spatial_ref_sys WHERE srid = %d",
                       nId );
-    rc = sqlite3_get_table( hDB, osCommand, 
+    rc = sqlite3_get_table( hDB, osCommand,
                             &papszResult, &nRowCount, &nColCount, &pszErrMsg );
 
     if ( rc == SQLITE_OK )
@@ -3152,7 +3284,7 @@ OGRSpatialReference *OGRSQLiteDataSource::FetchSRS( int nId )
         osCommand.Printf(
             "SELECT proj4text, auth_name, auth_srid%s FROM spatial_ref_sys WHERE srid = %d",
             (pszSRTEXTColName != NULL) ? osSRTEXTColNameWithCommaBefore.c_str() : "", nId );
-        rc = sqlite3_get_table( hDB, osCommand, 
+        rc = sqlite3_get_table( hDB, osCommand,
                                 &papszResult, &nRowCount,
                                 &nColCount, &pszErrMsg );
         if ( rc == SQLITE_OK )
@@ -3208,7 +3340,7 @@ OGRSpatialReference *OGRSQLiteDataSource::FetchSRS( int nId )
 /* -------------------------------------------------------------------- */
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "%s: %s", osCommand.c_str(), pszErrMsg );
             sqlite3_free( pszErrMsg );
             return NULL;
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitedriver.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitedriver.cpp
index b2ee957..1074d30 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitedriver.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitedriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqlitedriver.cpp 29265 2015-05-29 10:49:34Z rouault $
+ * $Id: ogrsqlitedriver.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteDriver class.
@@ -9,7 +9,7 @@
  *
  * Contributor: Alessandro Furieri, a.furieri at lqt.it
  * Portions of this module properly supporting SpatiaLite DB creation
- * Developed for Faunalia ( http://www.faunalia.it) with funding from 
+ * Developed for Faunalia ( http://www.faunalia.it) with funding from
  * Regione Toscana - Settore SISTEMA INFORMATIVO TERRITORIALE ED AMBIENTALE
  *
  ******************************************************************************
@@ -38,22 +38,7 @@
 #include "ogr_sqlite.h"
 #include "cpl_conv.h"
 
-#ifdef HAVE_SPATIALITE
-#include "spatialite.h"
-#endif
-
-CPL_CVSID("$Id: ogrsqlitedriver.cpp 29265 2015-05-29 10:49:34Z rouault $");
-
-/************************************************************************/
-/*                          OGRSQLiteDriverUnload()                     */
-/************************************************************************/
-
-static void OGRSQLiteDriverUnload(CPL_UNUSED GDALDriver* poDriver)
-{
-#ifdef SPATIALITE_412_OR_LATER
-    spatialite_shutdown();
-#endif
-}
+CPL_CVSID("$Id: ogrsqlitedriver.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                     OGRSQLiteDriverIdentify()                        */
@@ -63,7 +48,7 @@ static int OGRSQLiteDriverIdentify( GDALOpenInfo* poOpenInfo )
 
 {
     int nLen = (int) strlen(poOpenInfo->pszFilename);
-    if (EQUALN(poOpenInfo->pszFilename, "VirtualShape:", strlen( "VirtualShape:" )) &&
+    if (STARTS_WITH_CI(poOpenInfo->pszFilename, "VirtualShape:") &&
         nLen > 4 && EQUAL(poOpenInfo->pszFilename + nLen - 4, ".SHP"))
     {
         return TRUE;
@@ -71,6 +56,25 @@ static int OGRSQLiteDriverIdentify( GDALOpenInfo* poOpenInfo )
 
     if( EQUAL(poOpenInfo->pszFilename, ":memory:") )
         return TRUE;
+
+#ifdef SQLITE_OPEN_URI
+    // This code enables support for named memory databases in SQLite.
+    // Named memory databases use file name format
+    //   file:name?mode=memory&cache=shared
+    // SQLITE_USE_URI is checked only to enable backward compatibility, in case
+    // we accidentally hijacked some other format.
+    if( STARTS_WITH(poOpenInfo->pszFilename, "file:") &&
+        CPLTestBool(CPLGetConfigOption("SQLITE_USE_URI", "YES")) )
+    {
+        char * queryparams = strchr(poOpenInfo->pszFilename, '?');
+        if( queryparams )
+        {
+            if( strstr(queryparams, "mode=memory") != NULL )
+                return TRUE;
+        }
+    }
+#endif
+
 /* -------------------------------------------------------------------- */
 /*      Verify that the target is a real file, and has an               */
 /*      appropriate magic string at the beginning.                      */
@@ -78,9 +82,9 @@ static int OGRSQLiteDriverIdentify( GDALOpenInfo* poOpenInfo )
     if( poOpenInfo->nHeaderBytes < 16 )
         return FALSE;
 
-    if( strncmp( (const char*)poOpenInfo->pabyHeader, "SQLite format 3", 15 ) != 0 )
+    if( !STARTS_WITH((const char*)poOpenInfo->pabyHeader, "SQLite format 3") )
         return FALSE;
-    
+
     // Could be a Rasterlite file as well
     return -1;
 }
@@ -99,7 +103,7 @@ static GDALDataset *OGRSQLiteDriverOpen( GDALOpenInfo* poOpenInfo )
 /*      Check VirtualShape:xxx.shp syntax                               */
 /* -------------------------------------------------------------------- */
     int nLen = (int) strlen(poOpenInfo->pszFilename);
-    if (EQUALN(poOpenInfo->pszFilename, "VirtualShape:", strlen( "VirtualShape:" )) &&
+    if (STARTS_WITH_CI(poOpenInfo->pszFilename, "VirtualShape:") &&
         nLen > 4 && EQUAL(poOpenInfo->pszFilename + nLen - 4, ".SHP"))
     {
         OGRSQLiteDataSource     *poDS;
@@ -178,7 +182,7 @@ static GDALDataset *OGRSQLiteDriverCreate( const char * pszName,
 
     if( VSIStatL( pszName, &sStatBuf ) == 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "It seems a file system object called '%s' already exists.",
                   pszName );
 
@@ -205,7 +209,7 @@ static GDALDataset *OGRSQLiteDriverCreate( const char * pszName,
 /*                             Delete()                                 */
 /************************************************************************/
 
-CPLErr OGRSQLiteDriverDelete( const char *pszName )
+static CPLErr OGRSQLiteDriverDelete( const char *pszName )
 {
     if (VSIUnlink( pszName ) == 0)
         return CE_None;
@@ -220,29 +224,27 @@ CPLErr OGRSQLiteDriverDelete( const char *pszName )
 void RegisterOGRSQLite()
 
 {
-    if (! GDAL_CHECK_VERSION("SQLite driver"))
+    if( !GDAL_CHECK_VERSION("SQLite driver") )
         return;
-    GDALDriver  *poDriver;
 
-    if( GDALGetDriverByName( "SQLite" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    if( GDALGetDriverByName( "SQLite" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "SQLite" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "SQLite / Spatialite" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_sqlite.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "sqlite db" );
+    poDriver->SetDescription( "SQLite" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "SQLite / Spatialite" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_sqlite.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "sqlite db" );
 
-        poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
 "<OpenOptionList>"
 "  <Option name='LIST_ALL_TABLES' type='boolean' description='Whether all tables, including non-spatial ones, should be listed' default='NO'/>"
 "  <Option name='LIST_VIRTUAL_OGR' type='boolean' description='Whether VirtualOGR virtual tables should be listed. Should only be enabled on trusted datasources to avoid potential safety issues' default='NO'/>"
 "</OpenOptionList>");
 
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 #ifdef HAVE_SPATIALITE
 "  <Option name='SPATIALITE' type='boolean' description='Whether to create a Spatialite database' default='NO'/>"
@@ -251,7 +253,7 @@ void RegisterOGRSQLite()
 "  <Option name='INIT_WITH_EPSG' type='boolean' description='Whether to insert the content of the EPSG CSV files into the spatial_ref_sys table ' default='NO'/>"
 "</CreationOptionList>");
 
-        poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
 "<LayerCreationOptionList>"
 "  <Option name='FORMAT' type='string-select' description='Format of geometry columns'>"
 "    <Value>WKB</Value>"
@@ -271,20 +273,20 @@ void RegisterOGRSQLite()
 "  <Option name='OVERWRITE' type='boolean' description='Whether to overwrite an existing table with the layer name to be created' default='NO'/>"
 "  <Option name='FID' type='string' description='Name of the FID column to create' default='OGC_FID'/>"
 "</LayerCreationOptionList>");
-        
-        poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES, "Integer Integer64 Real String Date DateTime Time Binary" );
-        poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_FIELDS, "YES" );
-        poDriver->SetMetadataItem( GDAL_DCAP_DEFAULT_FIELDS, "YES" );
-        poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_GEOMFIELDS, "YES" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = OGRSQLiteDriverOpen;
-        poDriver->pfnIdentify = OGRSQLiteDriverIdentify;
-        poDriver->pfnCreate = OGRSQLiteDriverCreate;
-        poDriver->pfnDelete = OGRSQLiteDriverDelete;
-        poDriver->pfnUnloadDriver = OGRSQLiteDriverUnload;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
+                               "Integer Integer64 Real String Date DateTime "
+                               "Time Binary" );
+    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_FIELDS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_DEFAULT_FIELDS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_GEOMFIELDS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = OGRSQLiteDriverOpen;
+    poDriver->pfnIdentify = OGRSQLiteDriverIdentify;
+    poDriver->pfnCreate = OGRSQLiteDriverCreate;
+    poDriver->pfnDelete = OGRSQLiteDriverDelete;
+    poDriver->pfnUnloadDriver = OGRSQLiteDriverUnload;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.cpp
index 2f001e1..647148f 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqliteexecutesql.cpp 28612 2015-03-04 15:22:08Z rouault $
+ * $Id: ogrsqliteexecutesql.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Run SQL requests with SQLite SQL engine
@@ -57,18 +57,18 @@ class OGRSQLiteExecuteSQLLayer: public OGRSQLiteSelectLayer
 /*                         OGRSQLiteExecuteSQLLayer()                   */
 /************************************************************************/
 
-OGRSQLiteExecuteSQLLayer::OGRSQLiteExecuteSQLLayer(char* pszTmpDBName,
-                                                   OGRSQLiteDataSource* poDS,
+OGRSQLiteExecuteSQLLayer::OGRSQLiteExecuteSQLLayer(char* pszTmpDBNameIn,
+                                                   OGRSQLiteDataSource* poDSIn,
                                                    CPLString osSQL,
-                                                   sqlite3_stmt * hStmt,
+                                                   sqlite3_stmt * hStmtIn,
                                                    int bUseStatementForGetNextFeature,
                                                    int bEmptyLayer ) :
 
-                               OGRSQLiteSelectLayer(poDS, osSQL, hStmt,
+                               OGRSQLiteSelectLayer(poDSIn, osSQL, hStmtIn,
                                                     bUseStatementForGetNextFeature,
                                                     bEmptyLayer, TRUE)
 {
-    this->pszTmpDBName = pszTmpDBName;
+    this->pszTmpDBName = pszTmpDBNameIn;
 }
 
 /************************************************************************/
@@ -164,7 +164,7 @@ LayerDesc OGR2SQLITEExtractLayerDesc(const char **ppszSQLCommand)
     {
         oLayerDesc.osLayerName = osStr;
     }
-    
+
     oLayerDesc.osOriginalStr.resize(pszSQLCommand - pszOriginalStrStart);
 
     *ppszSQLCommand = pszSQLCommand;
@@ -191,7 +191,7 @@ static void OGR2SQLITEAddLayer( const char*& pszStart, int& nNum,
     {
         osTruncated = pszStart;
         osTruncated.resize(pszSQLCommand - pszStart);
-        osModifiedSQL += osTruncated; 
+        osModifiedSQL += osTruncated;
     }
     else
     {
@@ -220,7 +220,7 @@ static void OGR2SQLITEAddLayer( const char*& pszStart, int& nNum,
 /*                         StartsAsSQLITEKeyWord()                      */
 /************************************************************************/
 
-static const char* apszKeywords[] =  {
+static const char* const apszKeywords[] =  {
     "WHERE", "GROUP", "ORDER", "JOIN", "UNION", "INTERSECT", "EXCEPT", "LIMIT"
 };
 
@@ -283,7 +283,7 @@ static void OGR2SQLITEGetPotentialLayerNamesInternal(const char **ppszSQLCommand
             }
         }
 
-        else if( EQUALN(pszSQLCommand, "ogr_layer_", strlen("ogr_layer_"))  )
+        else if( STARTS_WITH_CI(pszSQLCommand, "ogr_layer_")  )
         {
             while( *pszSQLCommand != '\0' && *pszSQLCommand != '(' )
                 pszSQLCommand ++;
@@ -302,7 +302,7 @@ static void OGR2SQLITEGetPotentialLayerNamesInternal(const char **ppszSQLCommand
         }
 
         else if( bLookforFTableName &&
-                 EQUALN(pszSQLCommand, "f_table_name", strlen("f_table_name")) &&
+                 STARTS_WITH_CI(pszSQLCommand, "f_table_name") &&
                  (pszSQLCommand[strlen("f_table_name")] == '=' ||
                   isspace((int)pszSQLCommand[strlen("f_table_name")])) )
         {
@@ -324,7 +324,7 @@ static void OGR2SQLITEGetPotentialLayerNamesInternal(const char **ppszSQLCommand
             bLookforFTableName = FALSE;
         }
 
-        else if( EQUALN(pszSQLCommand, "FROM", strlen("FROM")) &&
+        else if( STARTS_WITH_CI(pszSQLCommand, "FROM") &&
                  isspace(pszSQLCommand[strlen("FROM")]) )
         {
             pszSQLCommand += strlen("FROM") + 1;
@@ -332,7 +332,7 @@ static void OGR2SQLITEGetPotentialLayerNamesInternal(const char **ppszSQLCommand
             while( isspace((int)*pszSQLCommand) )
                 pszSQLCommand ++;
 
-            if( EQUALN(pszSQLCommand, "SpatialIndex", strlen("SpatialIndex")) &&
+            if( STARTS_WITH_CI(pszSQLCommand, "SpatialIndex") &&
                 isspace((int)pszSQLCommand[strlen("SpatialIndex")]) )
             {
                 pszSQLCommand += strlen("SpatialIndex") + 1;
@@ -368,7 +368,7 @@ static void OGR2SQLITEGetPotentialLayerNamesInternal(const char **ppszSQLCommand
                     while( isspace((int)*pszSQLCommand) )
                         pszSQLCommand ++;
 
-                    if( EQUALN(pszSQLCommand, "AS", 2) )
+                    if( STARTS_WITH_CI(pszSQLCommand, "AS") )
                     {
                         pszSQLCommand += 2;
                         while( isspace((int)*pszSQLCommand) )
@@ -414,28 +414,28 @@ static void OGR2SQLITEGetPotentialLayerNamesInternal(const char **ppszSQLCommand
                     break;
             }
         }
-        else if ( EQUALN(pszSQLCommand, "JOIN", strlen("JOIN")) &&
+        else if ( STARTS_WITH_CI(pszSQLCommand, "JOIN") &&
                   isspace(pszSQLCommand[strlen("JOIN")]) )
         {
             pszSQLCommand += strlen("JOIN") + 1;
             OGR2SQLITEAddLayer(pszStart, nNum, pszSQLCommand,
                                oSetLayers, osModifiedSQL);
         }
-        else if( EQUALN(pszSQLCommand, "INTO", strlen("INTO")) &&
+        else if( STARTS_WITH_CI(pszSQLCommand, "INTO") &&
                  isspace(pszSQLCommand[strlen("INTO")]) )
         {
             pszSQLCommand += strlen("INTO") + 1;
             OGR2SQLITEAddLayer(pszStart, nNum, pszSQLCommand,
                                oSetLayers, osModifiedSQL);
         }
-        else if( EQUALN(pszSQLCommand, "UPDATE", strlen("UPDATE")) &&
+        else if( STARTS_WITH_CI(pszSQLCommand, "UPDATE") &&
                  isspace(pszSQLCommand[strlen("UPDATE")]) )
         {
             pszSQLCommand += strlen("UPDATE") + 1;
             OGR2SQLITEAddLayer(pszStart, nNum, pszSQLCommand,
                                oSetLayers, osModifiedSQL);
         }
-        else if ( EQUALN(pszSQLCommand, "DROP TABLE ", strlen("DROP TABLE ")) )
+        else if ( STARTS_WITH_CI(pszSQLCommand, "DROP TABLE ") )
         {
             pszSQLCommand += strlen("DROP TABLE") + 1;
             OGR2SQLITEAddLayer(pszStart, nNum, pszSQLCommand,
@@ -467,6 +467,7 @@ static void OGR2SQLITEGetPotentialLayerNames(const char *pszSQLCommand,
 /*               OGR2SQLITE_IgnoreAllFieldsExceptGeometry()             */
 /************************************************************************/
 
+#ifdef HAVE_SPATIALITE
 static
 void OGR2SQLITE_IgnoreAllFieldsExceptGeometry(OGRLayer* poLayer)
 {
@@ -481,11 +482,18 @@ void OGR2SQLITE_IgnoreAllFieldsExceptGeometry(OGRLayer* poLayer)
     poLayer->SetIgnoredFields((const char**)papszIgnored);
     CSLDestroy(papszIgnored);
 }
+#endif
 
 
 /************************************************************************/
 /*                  OGR2SQLITEDealWithSpatialColumn()                   */
 /************************************************************************/
+#if HAVE_SPATIALITE
+#  define WHEN_SPATIALITE(arg) arg
+#else
+#  define WHEN_SPATIALITE(arg)
+#endif
+
 static
 int OGR2SQLITEDealWithSpatialColumn(OGRLayer* poLayer,
                                     int iGeomCol,
@@ -494,12 +502,12 @@ int OGR2SQLITEDealWithSpatialColumn(OGRLayer* poLayer,
                                     OGRSQLiteDataSource* poSQLiteDS,
                                     sqlite3* hDB,
                                     int bSpatialiteDB,
-                                    const std::set<LayerDesc>& oSetLayers,
-                                    const std::set<CPLString>& oSetSpatialIndex
+                                    const std::set<LayerDesc>&
+                                        WHEN_SPATIALITE(oSetLayers),
+                                    const std::set<CPLString>&
+                                        WHEN_SPATIALITE(oSetSpatialIndex)
                                    )
 {
-    int rc;
-
     OGRGeomFieldDefn* poGeomField =
         poLayer->GetLayerDefn()->GetGeomFieldDefn(iGeomCol);
     CPLString osGeomColRaw;
@@ -528,7 +536,9 @@ int OGR2SQLITEDealWithSpatialColumn(OGRLayer* poLayer,
         nSRSId = poSQLiteDS->FetchSRSId(poSRS);
 
     CPLString osSQL;
-    int bCreateSpatialIndex = FALSE;
+#ifdef HAVE_SPATIALITE
+    bool bCreateSpatialIndex = false;
+#endif
     if( !bSpatialiteDB )
     {
         osSQL.Printf("INSERT INTO geometry_columns (f_table_name, "
@@ -547,7 +557,7 @@ int OGR2SQLITEDealWithSpatialColumn(OGRLayer* poLayer,
         /* We detect the need for creating a spatial index by 2 means : */
 
         /* 1) if there's an explicit reference to a 'idx_layername_geometrycolumn' */
-        /*   table in the SQL --> old/traditionnal way of requesting spatial indices */
+        /*   table in the SQL --> old/traditional way of requesting spatial indices */
         /*   with spatialite. */
 
         std::set<LayerDesc>::const_iterator oIter2 = oSetLayers.begin();
@@ -556,7 +566,7 @@ int OGR2SQLITEDealWithSpatialColumn(OGRLayer* poLayer,
             const LayerDesc& oLayerDescIter = *oIter2;
             if( EQUAL(oLayerDescIter.osLayerName, osIdxNameRaw) )
             {
-                    bCreateSpatialIndex = TRUE;
+                    bCreateSpatialIndex = true;
                     break;
             }
         }
@@ -570,7 +580,7 @@ int OGR2SQLITEDealWithSpatialColumn(OGRLayer* poLayer,
                 const CPLString& osNameIter = *oIter3;
                 if( EQUAL(osNameIter, oLayerDesc.osLayerName) )
                 {
-                    bCreateSpatialIndex = TRUE;
+                    bCreateSpatialIndex = true;
                     break;
                 }
             }
@@ -593,7 +603,7 @@ int OGR2SQLITEDealWithSpatialColumn(OGRLayer* poLayer,
                         pszLayerNameEscaped,
                         pszGeomColEscaped, nGeomType,
                         nCoordDimension,
-                        nSRSId, bCreateSpatialIndex );
+                        nSRSId, static_cast<int>(bCreateSpatialIndex) );
         }
         else
         {
@@ -608,11 +618,11 @@ int OGR2SQLITEDealWithSpatialColumn(OGRLayer* poLayer,
                         pszLayerNameEscaped,
                         pszGeomColEscaped, pszGeometryType,
                         wkbHasZ( poLayer->GetGeomType() ) ? "XYZ" : "XY",
-                        nSRSId, bCreateSpatialIndex );
+                        nSRSId, static_cast<int>(bCreateSpatialIndex) );
         }
     }
 #endif // HAVE_SPATIALITE
-    rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, NULL );
+    int rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, NULL );
 
 #ifdef HAVE_SPATIALITE
 /* -------------------------------------------------------------------- */
@@ -634,9 +644,9 @@ int OGR2SQLITEDealWithSpatialColumn(OGRLayer* poLayer,
     rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, NULL );
     if( rc != SQLITE_OK )
     {
-        CPLDebug("SQLITE",
-                    "Error occured during spatial index creation : %s",
-                    sqlite3_errmsg(hDB));
+        CPLDebug( "SQLITE",
+                  "Error occurred during spatial index creation : %s",
+                  sqlite3_errmsg(hDB));
     }
 #else //  ENABLE_VIRTUAL_OGR_SPATIAL_INDEX
     rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, NULL );
@@ -690,9 +700,9 @@ int OGR2SQLITEDealWithSpatialColumn(OGRLayer* poLayer,
         rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL, NULL );
     else
     {
-        CPLDebug("SQLITE",
-                    "Error occured during spatial index creation : %s",
-                    sqlite3_errmsg(hDB));
+        CPLDebug( "SQLITE",
+                  "Error occurred during spatial index creation : %s",
+                  sqlite3_errmsg(hDB));
         rc = sqlite3_exec( hDB, "ROLLBACK", NULL, NULL, NULL );
     }
 #endif //  ENABLE_VIRTUAL_OGR_SPATIAL_INDEX
@@ -712,7 +722,7 @@ OGRLayer * OGRSQLiteExecuteSQL( GDALDataset* poDS,
                                 CPL_UNUSED const char *pszDialect )
 {
     char* pszTmpDBName = (char*) CPLMalloc(256);
-    sprintf(pszTmpDBName, "/vsimem/ogr2sqlite/temp_%p.db", pszTmpDBName);
+    snprintf(pszTmpDBName, 256, "/vsimem/ogr2sqlite/temp_%p.db", pszTmpDBName);
 
     OGRSQLiteDataSource* poSQLiteDS = NULL;
     int nRet;
@@ -733,23 +743,24 @@ OGRLayer * OGRSQLiteExecuteSQL( GDALDataset* poDS,
 #ifdef HAVE_SPATIALITE
 
 /* -------------------------------------------------------------------- */
-/*      Creating an empty spatialite DB (with spatial_ref_sys populated */
-/*      has a non-neglectable cost. So at the first attempt, let's make */
+/*      Creating an empty SpatiaLite DB (with spatial_ref_sys populated */
+/*      has a significant cost. So at the first attempt, let's make     */
 /*      one and cache it for later use.                                 */
 /* -------------------------------------------------------------------- */
 #if 1
-    static vsi_l_offset nEmptyDBSize = 0;
+    static size_t nEmptyDBSize = 0;
     static GByte* pabyEmptyDB = NULL;
     {
         static CPLMutex* hMutex = NULL;
         CPLMutexHolder oMutexHolder(&hMutex);
         static int bTried = FALSE;
         if( !bTried &&
-            CSLTestBoolean(CPLGetConfigOption("OGR_SQLITE_DIALECT_USE_SPATIALITE", "YES")) )
+            CPLTestBool(CPLGetConfigOption("OGR_SQLITE_DIALECT_USE_SPATIALITE", "YES")) )
         {
             bTried = TRUE;
             char* pszCachedFilename = (char*) CPLMalloc(256);
-            sprintf(pszCachedFilename, "/vsimem/ogr2sqlite/reference_%p.db",pszCachedFilename);
+            snprintf(pszCachedFilename, 256, "/vsimem/ogr2sqlite/reference_%p.db",
+                    pszCachedFilename);
             char** papszOptions = CSLAddString(NULL, "SPATIALITE=YES");
             OGRSQLiteDataSource* poCachedDS = new OGRSQLiteDataSource();
             nRet = poCachedDS->Create( pszCachedFilename, papszOptions );
@@ -757,17 +768,21 @@ OGRLayer * OGRSQLiteExecuteSQL( GDALDataset* poDS,
             papszOptions = NULL;
             delete poCachedDS;
             if( nRet )
+            {
                 /* Note: the reference file keeps the ownership of the data, so that */
                 /* it gets released with VSICleanupFileManager() */
-                pabyEmptyDB = VSIGetMemFileBuffer( pszCachedFilename, &nEmptyDBSize, FALSE );
+                vsi_l_offset nEmptyDBSizeLarge = 0;
+                pabyEmptyDB = VSIGetMemFileBuffer( pszCachedFilename, &nEmptyDBSizeLarge, FALSE );
+                nEmptyDBSize = static_cast<size_t>(nEmptyDBSizeLarge);
+            }
             CPLFree( pszCachedFilename );
         }
     }
 
     /* The following configuration option is useful mostly for debugging/testing */
-    if( pabyEmptyDB != NULL && CSLTestBoolean(CPLGetConfigOption("OGR_SQLITE_DIALECT_USE_SPATIALITE", "YES")) )
+    if( pabyEmptyDB != NULL && CPLTestBool(CPLGetConfigOption("OGR_SQLITE_DIALECT_USE_SPATIALITE", "YES")) )
     {
-        GByte* pabyEmptyDBClone = (GByte*)VSIMalloc(nEmptyDBSize);
+        GByte* pabyEmptyDBClone = (GByte*)VSI_MALLOC_VERBOSE(nEmptyDBSize);
         if( pabyEmptyDBClone == NULL )
         {
             CPLFree(pszTmpDBName);
@@ -810,7 +825,7 @@ OGRLayer * OGRSQLiteExecuteSQL( GDALDataset* poDS,
         delete poSQLiteDS;
         poSQLiteDS = NULL;
 #else // HAVE_SPATIALITE
-    if( TRUE )
+    if( true )
     {
 #endif // HAVE_SPATIALITE
         poSQLiteDS = new OGRSQLiteDataSource();
@@ -851,6 +866,7 @@ OGRLayer * OGRSQLiteExecuteSQL( GDALDataset* poDS,
 /* -------------------------------------------------------------------- */
 /*      For each of those tables, create a Virtual Table.               */
 /* -------------------------------------------------------------------- */
+    OGRLayer* poSingleSrcLayer = NULL;
     for(; oIter != oSetLayers.end(); ++oIter)
     {
         const LayerDesc& oLayerDesc = *oIter;
@@ -889,7 +905,7 @@ OGRLayer * OGRSQLiteExecuteSQL( GDALDataset* poDS,
                 CPLFree(pszTmpDBName);
                 return NULL;
             }
-            
+
             poLayer = poOtherDS->GetLayerByName(oLayerDesc.osLayerName);
             if( poLayer == NULL )
             {
@@ -909,11 +925,15 @@ OGRLayer * OGRSQLiteExecuteSQL( GDALDataset* poDS,
             nExtraDS = OGR2SQLITE_AddExtraDS(poModule, poOtherDS);
         }
 
-        osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" USING VirtualOGR(%d,'%s',%d)",
+        if( oSetLayers.size() == 1 )
+            poSingleSrcLayer = poLayer;
+
+        osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" USING VirtualOGR(%d,'%s',%d,%d)",
                 OGRSQLiteEscapeName(osTableName).c_str(),
                 nExtraDS,
                 OGRSQLiteEscape(oLayerDesc.osLayerName).c_str(),
-                bFoundOGRStyle);
+                bFoundOGRStyle,
+                TRUE/*bExposeOGRNativeData*/);
 
         char* pszErrMsg = NULL;
         int rc = sqlite3_exec( hDB, osSQL.c_str(),
@@ -952,7 +972,7 @@ OGRLayer * OGRSQLiteExecuteSQL( GDALDataset* poDS,
 
     sqlite3_stmt *hSQLStmt = NULL;
     int rc = sqlite3_prepare( hDB,
-                              pszStatement, strlen(pszStatement),
+                              pszStatement, -1,
                               &hSQLStmt, NULL );
 
     if( rc != SQLITE_OK )
@@ -994,7 +1014,7 @@ OGRLayer * OGRSQLiteExecuteSQL( GDALDataset* poDS,
             return NULL;
         }
 
-        if( !EQUALN(pszStatement, "SELECT ", 7) )
+        if( !STARTS_WITH_CI(pszStatement, "SELECT ") )
         {
 
             sqlite3_finalize( hSQLStmt );
@@ -1022,6 +1042,10 @@ OGRLayer * OGRSQLiteExecuteSQL( GDALDataset* poDS,
     if( poSpatialFilter != NULL )
         poLayer->SetSpatialFilter( 0, poSpatialFilter );
 
+    if( poSingleSrcLayer != NULL )
+        poLayer->SetMetadata( poSingleSrcLayer->GetMetadata( "NATIVE_DATA" ),
+                              "NATIVE_DATA" );
+
     return poLayer;
 }
 
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.h b/ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.h
index fa34bc8..4cdb798 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.h
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqliteexecutesql.h 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogrsqliteexecutesql.h 31777 2015-11-26 14:14:41Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Run SQL requests with SQLite SQL engine
@@ -28,8 +28,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_SQLITE_EXECUTE_SQL_H_INCLUDED
-#define _OGR_SQLITE_EXECUTE_SQL_H_INCLUDED
+#ifndef OGR_SQLITE_EXECUTE_SQL_H_INCLUDED
+#define OGR_SQLITE_EXECUTE_SQL_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include <set>
@@ -62,6 +62,6 @@ class LayerDesc
 
 std::set<LayerDesc> OGRSQLiteGetReferencedLayers(const char* pszStatement);
 
-#endif /* ndef _OGR_SQLITE_EXECUTE_SQL_H_INCLUDED */
+#endif /* ndef OGR_SQLITE_EXECUTE_SQL_H_INCLUDED */
 
 
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitelayer.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitelayer.cpp
index 4eb5f85..d2e52c8 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitelayer.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitelayer.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: ogrsqlitelayer.cpp 29080 2015-04-30 15:30:33Z rouault $
+ * $Id: ogrsqlitelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
- * Purpose:  Implements OGRSQLiteLayer class, code shared between 
+ * Purpose:  Implements OGRSQLiteLayer class, code shared between
  *           the direct table access, and the generic SQL results.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -11,7 +11,7 @@
  * Contributor: Alessandro Furieri, a.furieri at lqt.it
  * Portions of this module supporting SpatiaLite's own 3D geometries
  * [XY, XYM, XYZ and XYZM] available since v.2.4.0
- * Developed for Faunalia ( http://www.faunalia.it) with funding from 
+ * Developed for Faunalia ( http://www.faunalia.it) with funding from
  * Regione Toscana - Settore SISTEMA INFORMATIVO TERRITORIALE ED AMBIENTALE
  *
  ******************************************************************************
@@ -42,7 +42,7 @@
 #include "ogr_sqlite.h"
 #include <cassert>
 
-CPL_CVSID("$Id: ogrsqlitelayer.cpp 29080 2015-04-30 15:30:33Z rouault $");
+CPL_CVSID("$Id: ogrsqlitelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                           OGRSQLiteLayer()                           */
@@ -63,10 +63,12 @@ OGRSQLiteLayer::OGRSQLiteLayer()
 
     panFieldOrdinals = NULL;
     iFIDCol = -1;
+    iOGRNativeDataCol = -1;
+    iOGRNativeMediaTypeCol = -1;
 
     bIsVirtualShape = FALSE;
 
-    bUseComprGeom = CSLTestBoolean(CPLGetConfigOption("COMPRESS_GEOM", "FALSE"));
+    bUseComprGeom = CPLTestBool(CPLGetConfigOption("COMPRESS_GEOM", "FALSE"));
 
     papszCompressedColumns = NULL;
 
@@ -96,7 +98,7 @@ void OGRSQLiteLayer::Finalize()
     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     {
         CPLDebug( "SQLite", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
+                  (int) m_nFeaturesRead,
                   poFeatureDefn->GetName() );
     }
 
@@ -148,7 +150,7 @@ int OGRIsBinaryGeomCol( sqlite3_stmt *hStmt,
     {
         eGeomFormat = OSGF_WKB;
     }
-    else if( OGRGeometryFactory::createFromFgf( 
+    else if( OGRGeometryFactory::createFromFgf(
             (GByte*)sqlite3_column_blob( hStmt, iCol ),
             NULL, &poGeometry, nBytes, NULL ) == OGRERR_NONE )
     {
@@ -172,7 +174,7 @@ int OGRIsBinaryGeomCol( sqlite3_stmt *hStmt,
 /************************************************************************/
 
 void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
-                                       sqlite3_stmt *hStmt,
+                                       sqlite3_stmt *hStmtIn,
                                        const std::set<CPLString>& aosGeomCols,
                                        const std::set<CPLString>& aosIgnoredCols )
 
@@ -181,14 +183,14 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
     poFeatureDefn->SetGeomType(wkbNone);
     poFeatureDefn->Reference();
 
-    int    nRawColumns = sqlite3_column_count( hStmt );
+    int    nRawColumns = sqlite3_column_count( hStmtIn );
 
     panFieldOrdinals = (int *) CPLMalloc( sizeof(int) * nRawColumns );
 
     int iCol;
     for( iCol = 0; iCol < nRawColumns; iCol++ )
     {
-        OGRFieldDefn    oField( OGRSQLiteParamsUnquote(sqlite3_column_name( hStmt, iCol )),
+        OGRFieldDefn    oField( OGRSQLiteParamsUnquote(sqlite3_column_name( hStmtIn, iCol )),
                                 OFTString );
 
         // In some cases, particularly when there is a real name for
@@ -197,6 +199,18 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
         if( poFeatureDefn->GetFieldIndex( oField.GetNameRef() ) != -1 )
             continue;
 
+        if( EQUAL(oField.GetNameRef(), "OGR_NATIVE_DATA") )
+        {
+            iOGRNativeDataCol = iCol;
+            continue;
+        }
+
+        if( EQUAL(oField.GetNameRef(), "OGR_NATIVE_MEDIA_TYPE") )
+        {
+            iOGRNativeMediaTypeCol = iCol;
+            continue;
+        }
+
         /* In the case of Spatialite VirtualShape, the PKUID */
         /* should be considered as a primary key */
         if( bIsVirtualShape && EQUAL(oField.GetNameRef(), "PKUID") )
@@ -222,16 +236,16 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
             continue;
         }
 
-        int nColType = sqlite3_column_type( hStmt, iCol );
+        int nColType = sqlite3_column_type( hStmtIn, iCol );
         switch( nColType )
         {
           case SQLITE_INTEGER:
-            if( CSLTestBoolean(CPLGetConfigOption("OGR_PROMOTE_TO_INTEGER64", "FALSE")) )
+            if( CPLTestBool(CPLGetConfigOption("OGR_PROMOTE_TO_INTEGER64", "FALSE")) )
                 oField.SetType( OFTInteger64 );
             else
             {
-                GIntBig nVal = sqlite3_column_int64(hStmt, iCol);
-                if( (GIntBig)(int)nVal == nVal )
+                GIntBig nVal = sqlite3_column_int64(hStmtIn, iCol);
+                if( CPL_INT64_FITS_ON_INT32(nVal) )
                     oField.SetType( OFTInteger );
                 else
                     oField.SetType( OFTInteger64 );
@@ -249,8 +263,8 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
           default:
             /* leave it as OFTString */;
         }
-        
-        const char * pszDeclType = sqlite3_column_decltype(hStmt, iCol);
+
+        const char * pszDeclType = sqlite3_column_decltype(hStmtIn, iCol);
         //CPLDebug("SQLITE", "decltype(%s) = %s",
         //         oField.GetNameRef(), pszDeclType ? pszDeclType : "null");
         OGRFieldType eFieldType = OFTString;
@@ -286,7 +300,7 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
             {
                 oField.SetType(OFTInteger64);
             }
-            else if (EQUALN(pszDeclType, "INTEGER", strlen("INTEGER")))
+            else if (STARTS_WITH_CI(pszDeclType, "INTEGER"))
             {
                 oField.SetType(OFTInteger);
             }
@@ -300,7 +314,7 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
             {
                 oField.SetType(OFTReal);
             }
-            else if (EQUALN(pszDeclType, "BLOB", 4))
+            else if (STARTS_WITH_CI(pszDeclType, "BLOB"))
             {
                 oField.SetType( OFTBinary );
                 /* Parse format like BLOB_POINT_25D_4326 created by */
@@ -327,8 +341,12 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
 
                         OGRwkbGeometryType eGeomType =
                             OGRFromOGCGeomType(pszGeomType);
-                        if( EQUAL(pszCoordDimension, "25D") )
+                        if( EQUAL(pszCoordDimension, "XYZ") )
                             eGeomType = wkbSetZ(eGeomType);
+                        else if( EQUAL(pszCoordDimension, "XYM") )
+                            eGeomType = wkbSetM(eGeomType);
+                        else if( EQUAL(pszCoordDimension, "XYZM") )
+                            eGeomType = wkbSetM(wkbSetZ(eGeomType));
                         OGRSpatialReference* poSRS = poDS->FetchSRS(nSRID);
                         OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
                             new OGRSQLiteGeomFieldDefn(oField.GetNameRef(), iCol);
@@ -343,7 +361,7 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
                 }
             }
             else if (EQUAL(pszDeclType, "TEXT") ||
-                     EQUALN(pszDeclType, "VARCHAR", 7))
+                     STARTS_WITH_CI(pszDeclType, "VARCHAR"))
             {
                 oField.SetType( OFTString );
                 if( strstr(pszDeclType, "_deflate") != NULL )
@@ -369,31 +387,31 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
                 eFieldType = OFTTime;
         }
         else if( nColType == SQLITE_TEXT &&
-                 (EQUALN(oField.GetNameRef(), "MIN(", 4) ||
-                  EQUALN(oField.GetNameRef(), "MAX(", 4)) &&
-                 sqlite3_column_text( hStmt, iCol ) != NULL )
+                 (STARTS_WITH_CI(oField.GetNameRef(), "MIN(") ||
+                  STARTS_WITH_CI(oField.GetNameRef(), "MAX(")) &&
+                 sqlite3_column_text( hStmtIn, iCol ) != NULL )
         {
             int nRet = OGRSQLITEStringToDateTimeField(NULL, 0,
-                              (const char*)sqlite3_column_text( hStmt, iCol ));
+                              (const char*)sqlite3_column_text( hStmtIn, iCol ));
             if( nRet > 0 )
                 eFieldType = (OGRFieldType) nRet;
         }
 
         // Recognise some common geometry column names.
-        if( (EQUAL(oField.GetNameRef(),"wkt_geometry") 
+        if( (EQUAL(oField.GetNameRef(),"wkt_geometry")
              || EQUAL(oField.GetNameRef(),"geometry")
-             || EQUALN(oField.GetNameRef(), "asbinary(", 9)
-             || EQUALN(oField.GetNameRef(), "astext(", 7)
-             || (EQUALN(oField.GetNameRef(), "st_", 3) && nColType == SQLITE_BLOB ) )
+             || STARTS_WITH_CI(oField.GetNameRef(), "asbinary(")
+             || STARTS_WITH_CI(oField.GetNameRef(), "astext(")
+             || (STARTS_WITH_CI(oField.GetNameRef(), "st_") && nColType == SQLITE_BLOB ) )
             && (bAllowMultipleGeomFields || poFeatureDefn->GetGeomFieldCount() == 0) )
         {
             if( nColType == SQLITE_BLOB )
             {
-                const int nBytes = sqlite3_column_bytes( hStmt, iCol );
+                const int nBytes = sqlite3_column_bytes( hStmtIn, iCol );
                 if( nBytes > 0 )
                 {
                     OGRSQLiteGeomFormat eGeomFormat = OSGF_None;
-                    if( OGRIsBinaryGeomCol( hStmt, iCol, oField, eGeomFormat ) )
+                    if( OGRIsBinaryGeomCol( hStmtIn, iCol, oField, eGeomFormat ) )
                     {
                         OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
                             new OGRSQLiteGeomFieldDefn(oField.GetNameRef(), iCol);
@@ -416,13 +434,13 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
             }
             else if( nColType == SQLITE_TEXT )
             {
-                char* pszText = (char*) sqlite3_column_text( hStmt, iCol );
+                char* pszText = (char*) sqlite3_column_text( hStmtIn, iCol );
                 if( pszText != NULL )
                 {
                     OGRSQLiteGeomFormat eGeomFormat = OSGF_None;
                     CPLPushErrorHandler(CPLQuietErrorHandler);
                     OGRGeometry* poGeometry = NULL;
-                    if( OGRGeometryFactory::createFromWkt( 
+                    if( OGRGeometryFactory::createFromWkt(
                         &pszText, NULL, &poGeometry ) == OGRERR_NONE )
                     {
                         eGeomFormat = OSGF_WKT;
@@ -449,7 +467,7 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
         }
 
         // SpatialLite / Gaia
-        if( EQUAL(oField.GetNameRef(),"GaiaGeometry") 
+        if( EQUAL(oField.GetNameRef(),"GaiaGeometry")
             && (bAllowMultipleGeomFields || poFeatureDefn->GetGeomFieldCount() == 0) )
         {
             OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
@@ -461,12 +479,12 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
 
         // Recognize a geometry column from trying to build the geometry
         // Useful for OGRSQLiteSelectLayer
-        if( nColType == SQLITE_BLOB && 
+        if( nColType == SQLITE_BLOB &&
             (bAllowMultipleGeomFields || poFeatureDefn->GetGeomFieldCount() == 0) )
         {
-            const int nBytes = sqlite3_column_bytes( hStmt, iCol );
+            const int nBytes = sqlite3_column_bytes( hStmtIn, iCol );
             OGRSQLiteGeomFormat eGeomFormat = OSGF_None;
-            if( nBytes > 0 && OGRIsBinaryGeomCol( hStmt, iCol, oField,
+            if( nBytes > 0 && OGRIsBinaryGeomCol( hStmtIn, iCol, oField,
                                                   eGeomFormat ) )
             {
                 OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
@@ -485,10 +503,10 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
         if( EQUAL(oField.GetNameRef(),"OGC_FID") )
             continue;
 
-        /* config option just in case we wouldn't want that in some cases */
+        /* Config option just in case we would not want that in some cases */
         if( (eFieldType == OFTTime || eFieldType == OFTDate ||
              eFieldType == OFTDateTime) &&
-            CSLTestBoolean(
+            CPLTestBool(
                 CPLGetConfigOption("OGR_SQLITE_ENABLE_DATETIME", "YES")) )
         {
             oField.SetType( eFieldType );
@@ -502,7 +520,7 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
     {
         for( iCol = 0; iCol < nRawColumns; iCol++ )
         {
-            if( EQUAL(OGRSQLiteParamsUnquote(sqlite3_column_name(hStmt,iCol)).c_str(),
+            if( EQUAL(OGRSQLiteParamsUnquote(sqlite3_column_name(hStmtIn,iCol)).c_str(),
                       pszFIDColumn) )
             {
                 iFIDCol = iCol;
@@ -516,7 +534,7 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
 /*                            GetFIDColumn()                            */
 /************************************************************************/
 
-const char *OGRSQLiteLayer::GetFIDColumn() 
+const char *OGRSQLiteLayer::GetFIDColumn()
 
 {
     GetLayerDefn();
@@ -544,7 +562,7 @@ void OGRSQLiteLayer::ResetReading()
 OGRFeature *OGRSQLiteLayer::GetNextFeature()
 
 {
-    for( ; TRUE; )
+    while( true )
     {
         OGRFeature      *poFeature;
 
@@ -636,11 +654,8 @@ OGRFeature *OGRSQLiteLayer::GetNextRawFeature()
 
                 pszWKT = (char *) sqlite3_column_text( hStmt, poGeomFieldDefn->iCol );
                 pszWKTCopy = pszWKT;
-                if( OGRGeometryFactory::createFromWkt( 
-                        &pszWKTCopy, NULL, &poGeometry ) == OGRERR_NONE )
-                {
-                    poFeature->SetGeomFieldDirectly( iField, poGeometry );
-                }
+                OGRGeometryFactory::createFromWkt(
+                        &pszWKTCopy, NULL, &poGeometry );
             }
             else if ( poGeomFieldDefn->eGeomFormat == OSGF_WKB )
             {
@@ -652,49 +667,45 @@ OGRFeature *OGRSQLiteLayer::GetNextRawFeature()
                 {
                     /* If the layer is the result of a sql select, we cannot be sure if it is */
                     /* WKB or SpatialLite format */
-                    if( ImportSpatiaLiteGeometry( 
+                    if( ImportSpatiaLiteGeometry(
                         (GByte*)sqlite3_column_blob( hStmt, poGeomFieldDefn->iCol ), nBytes,
                         &poGeometry ) == OGRERR_NONE )
                     {
-                        poFeature->SetGeomFieldDirectly( iField, poGeometry );
                         poGeomFieldDefn->eGeomFormat = OSGF_SpatiaLite;
                     }
                     poGeomFieldDefn->bTriedAsSpatiaLite = TRUE;
                 }
 
-                if( poGeomFieldDefn->eGeomFormat == OSGF_WKB &&
-                    OGRGeometryFactory::createFromWkb( 
-                        (GByte*)sqlite3_column_blob( hStmt, poGeomFieldDefn->iCol ),
-                        NULL, &poGeometry, nBytes ) == OGRERR_NONE )
+                if( poGeomFieldDefn->eGeomFormat == OSGF_WKB )
                 {
-                    poFeature->SetGeomFieldDirectly( iField, poGeometry );
+                    CPL_IGNORE_RET_VAL(OGRGeometryFactory::createFromWkb(
+                        (GByte*)sqlite3_column_blob( hStmt, poGeomFieldDefn->iCol ),
+                        NULL, &poGeometry, nBytes ));
                 }
             }
             else if ( poGeomFieldDefn->eGeomFormat == OSGF_FGF )
             {
                 const int nBytes = sqlite3_column_bytes( hStmt, poGeomFieldDefn->iCol );
 
-                if( OGRGeometryFactory::createFromFgf( 
+                OGRGeometryFactory::createFromFgf(
                         (GByte*)sqlite3_column_blob( hStmt, poGeomFieldDefn->iCol ),
-                        NULL, &poGeometry, nBytes, NULL ) == OGRERR_NONE )
-                {
-                    poFeature->SetGeomFieldDirectly( iField, poGeometry );
-                }
+                        NULL, &poGeometry, nBytes, NULL );
             }
             else if ( poGeomFieldDefn->eGeomFormat == OSGF_SpatiaLite )
             {
                 const int nBytes = sqlite3_column_bytes( hStmt, poGeomFieldDefn->iCol );
 
-                if( ImportSpatiaLiteGeometry( 
+                CPL_IGNORE_RET_VAL(ImportSpatiaLiteGeometry(
                         (GByte*)sqlite3_column_blob( hStmt, poGeomFieldDefn->iCol ), nBytes,
-                        &poGeometry ) == OGRERR_NONE )
-                {
-                    poFeature->SetGeomFieldDirectly( iField, poGeometry );
-                }
+                        &poGeometry ));
             }
 
-            if (poGeometry != NULL && poGeomFieldDefn->GetSpatialRef() != NULL)
-                poGeometry->assignSpatialReference(poGeomFieldDefn->GetSpatialRef());
+            if (poGeometry != NULL )
+            {
+                if( poGeomFieldDefn->GetSpatialRef() != NULL)
+                    poGeometry->assignSpatialReference(poGeomFieldDefn->GetSpatialRef());
+                poFeature->SetGeomFieldDirectly( iField, poGeometry );
+            }
         }
     }
 
@@ -720,10 +731,10 @@ OGRFeature *OGRSQLiteLayer::GetNextRawFeature()
         {
             /* Possible since SQLite3 has no strong typing */
             if( nSQLite3Type == SQLITE_TEXT )
-                poFeature->SetField( iField, 
+                poFeature->SetField( iField,
                         (const char *)sqlite3_column_text( hStmt, iRawField ) );
             else
-                poFeature->SetField( iField, 
+                poFeature->SetField( iField,
                     sqlite3_column_int64( hStmt, iRawField ) );
             break;
         }
@@ -732,10 +743,10 @@ OGRFeature *OGRSQLiteLayer::GetNextRawFeature()
         {
             /* Possible since SQLite3 has no strong typing */
             if( nSQLite3Type == SQLITE_TEXT )
-                poFeature->SetField( iField, 
+                poFeature->SetField( iField,
                         (const char *)sqlite3_column_text( hStmt, iRawField ) );
             else
-                poFeature->SetField( iField, 
+                poFeature->SetField( iField,
                     sqlite3_column_double( hStmt, iRawField ) );
             break;
         }
@@ -769,15 +780,15 @@ OGRFeature *OGRSQLiteLayer::GetNextRawFeature()
                 }
                 else
                 {
-                    poFeature->SetField( iField, 
-                        (const char *) 
+                    poFeature->SetField( iField,
+                        (const char *)
                         sqlite3_column_text( hStmt, iRawField ) );
                 }
             }
             else
             {
-                poFeature->SetField( iField, 
-                    (const char *) 
+                poFeature->SetField( iField,
+                    (const char *)
                     sqlite3_column_text( hStmt, iRawField ) );
             }
             break;
@@ -789,7 +800,7 @@ OGRFeature *OGRSQLiteLayer::GetNextRawFeature()
         {
             if( sqlite3_column_type( hStmt, iRawField ) == SQLITE_TEXT )
             {
-                const char* pszValue = (const char *) 
+                const char* pszValue = (const char *)
                     sqlite3_column_text( hStmt, iRawField );
                 OGRSQLITEStringToDateTimeField( poFeature, iField, pszValue );
             }
@@ -815,6 +826,20 @@ OGRFeature *OGRSQLiteLayer::GetNextRawFeature()
         }
     }
 
+/* -------------------------------------------------------------------- */
+/*      Set native data if found                                        */
+/* -------------------------------------------------------------------- */
+    if( iOGRNativeDataCol >= 0 &&
+        sqlite3_column_type( hStmt, iOGRNativeDataCol ) == SQLITE_TEXT )
+    {
+        poFeature->SetNativeData( (const char*)sqlite3_column_text( hStmt, iOGRNativeDataCol ) );
+    }
+    if( iOGRNativeMediaTypeCol >= 0 &&
+        sqlite3_column_type( hStmt, iOGRNativeMediaTypeCol ) == SQLITE_TEXT )
+    {
+        poFeature->SetNativeMediaType( (const char*)sqlite3_column_text( hStmt, iOGRNativeMediaTypeCol ) );
+    }
+
     return poFeature;
 }
 
@@ -852,7 +877,6 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                                                     int* pnBytesConsumed,
                                                     int nRecLevel)
 {
-    OGRErr      eErr = OGRERR_NONE;
     OGRGeometry *poGeom = NULL;
     GInt32       nGType;
     GInt32       compressedSize;
@@ -863,8 +887,9 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
     if( nRecLevel == 32 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                    "Too many recursiong level (%d) while parsing Spatialite geometry.",
-                    nRecLevel );
+                  "Too many recursion levels (%d) while parsing "
+                  "Spatialite geometry.",
+                  nRecLevel );
         return OGRERR_CORRUPT_DATA;
     }
 
@@ -878,21 +903,21 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
     if (NEED_SWAP_SPATIALITE())
         CPL_SWAP32PTR( &nGType );
 
-    if( ( nGType >= OGRSplitePointXY && 
+    if( ( nGType >= OGRSplitePointXY &&
           nGType <= OGRSpliteGeometryCollectionXY ) ||       // XY types
-        ( nGType >= OGRSplitePointXYZ && 
+        ( nGType >= OGRSplitePointXYZ &&
           nGType <= OGRSpliteGeometryCollectionXYZ ) ||      // XYZ types
-        ( nGType >= OGRSplitePointXYM && 
+        ( nGType >= OGRSplitePointXYM &&
           nGType <= OGRSpliteGeometryCollectionXYM ) ||      // XYM types
-        ( nGType >= OGRSplitePointXYZM && 
+        ( nGType >= OGRSplitePointXYZM &&
           nGType <= OGRSpliteGeometryCollectionXYZM ) ||     // XYZM types
-        ( nGType >= OGRSpliteComprLineStringXY && 
+        ( nGType >= OGRSpliteComprLineStringXY &&
           nGType <= OGRSpliteComprGeometryCollectionXY ) ||  // XY compressed
-        ( nGType >= OGRSpliteComprLineStringXYZ && 
+        ( nGType >= OGRSpliteComprLineStringXYZ &&
           nGType <= OGRSpliteComprGeometryCollectionXYZ ) || // XYZ compressed
-        ( nGType >= OGRSpliteComprLineStringXYM && 
+        ( nGType >= OGRSpliteComprLineStringXYM &&
           nGType <= OGRSpliteComprGeometryCollectionXYM ) || // XYM compressed
-        ( nGType >= OGRSpliteComprLineStringXYZM && 
+        ( nGType >= OGRSpliteComprLineStringXYZM &&
           nGType <= OGRSpliteComprGeometryCollectionXYZM ) ) // XYZM compressed
         ;
     else
@@ -962,7 +987,9 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
             CPL_SWAP64PTR( adfTuple + 2 );
         }
 
-        poGeom = new OGRPoint( adfTuple[0], adfTuple[1] );
+        OGRPoint* poPoint = new OGRPoint( adfTuple[0], adfTuple[1] );
+        poPoint->setM( adfTuple[2] );
+        poGeom = poPoint;
 
         if( pnBytesConsumed )
             *pnBytesConsumed = 4 + 3 * 8;
@@ -987,7 +1014,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
             CPL_SWAP64PTR( adfTuple + 3 );
         }
 
-        poGeom = new OGRPoint( adfTuple[0], adfTuple[1], adfTuple[2] );
+        poGeom = new OGRPoint( adfTuple[0], adfTuple[1], adfTuple[2], adfTuple[3] );
 
         if( pnBytesConsumed )
             *pnBytesConsumed = 4 + 4 * 8;
@@ -1116,7 +1143,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                 CPL_SWAP64PTR( adfTuple + 2 );
             }
 
-            poLS->setPoint( iPoint, adfTuple[0], adfTuple[1] );
+            poLS->setPointM( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
         }
 
         if( pnBytesConsumed )
@@ -1160,7 +1187,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                 CPL_SWAP64PTR( adfTuple + 3 );
             }
 
-            poLS->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
+            poLS->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2], adfTuple[3] );
         }
 
         if( pnBytesConsumed )
@@ -1190,7 +1217,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         if( nPointCount < 0 || nPointCount - 2 > (INT_MAX - 16 * 2) / 8)
             return OGRERR_CORRUPT_DATA;
 
-        compressedSize = 16 * 2;                  // first and last Points 
+        compressedSize = 16 * 2;                  // first and last Points
         compressedSize += 8 * (nPointCount - 2);  // intermediate Points
 
         if (nBytes - 8 < compressedSize )
@@ -1202,15 +1229,15 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         nNextByte = 8;
         adfTupleBase[0] = 0.0;
         adfTupleBase[1] = 0.0;
-		
+
         for( iPoint = 0; iPoint < nPointCount; iPoint++ )
         {
             if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
             {
-                // first and last Points are uncompressed 
+                // first and last Points are uncompressed
                 memcpy( adfTuple, pabyData + nNextByte, 2*8 );
                 nNextByte += 2 * 8;
-			
+
                 if (NEED_SWAP_SPATIALITE())
                 {
                     CPL_SWAP64PTR( adfTuple );
@@ -1277,12 +1304,12 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         adfTupleBase[0] = 0.0;
         adfTupleBase[1] = 0.0;
         adfTupleBase[2] = 0.0;
-		
+
         for( iPoint = 0; iPoint < nPointCount; iPoint++ )
         {
             if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
             {
-                // first and last Points are uncompressed 
+                // first and last Points are uncompressed
                 memcpy( adfTuple, pabyData + nNextByte, 3*8 );
                 nNextByte += 3 * 8;
 
@@ -1295,7 +1322,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
             }
             else
             {
-                // any other intermediate Point is compressed 
+                // any other intermediate Point is compressed
                 memcpy( asfTuple, pabyData + nNextByte, 3*4 );
                 nNextByte += 3 * 4;
 
@@ -1325,7 +1352,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 /* -------------------------------------------------------------------- */
     else if( nGType == OGRSpliteComprLineStringXYM )
     {
-        double adfTuple[2];
+        double adfTuple[3];
         double adfTupleBase[2];
         float asfTuple[2];
         GInt32 nPointCount;
@@ -1355,37 +1382,40 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         nNextByte = 8;
         adfTupleBase[0] = 0.0;
         adfTupleBase[1] = 0.0;
-		
+
         for( iPoint = 0; iPoint < nPointCount; iPoint++ )
         {
             if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
             {
-                // first and last Points are uncompressed 
-                memcpy( adfTuple, pabyData + nNextByte, 2*8 );
+                // first and last Points are uncompressed
+                memcpy( adfTuple, pabyData + nNextByte, 3*8 );
                 nNextByte += 3 * 8;
 
                 if (NEED_SWAP_SPATIALITE())
                 {
                     CPL_SWAP64PTR( adfTuple );
                     CPL_SWAP64PTR( adfTuple + 1 );
+                    CPL_SWAP64PTR( adfTuple + 2 );
                 }
             }
             else
             {
                 // any other intermediate Point is compressed
                 memcpy( asfTuple, pabyData + nNextByte, 2*4 );
+                memcpy( adfTuple + 2, pabyData + nNextByte + 2*4, 8 );
                 nNextByte += 2 * 4 + 8;
 
                 if (NEED_SWAP_SPATIALITE())
                 {
                     CPL_SWAP32PTR( asfTuple );
                     CPL_SWAP32PTR( asfTuple + 1 );
+                    CPL_SWAP64PTR( adfTuple + 2 ); /* adfTuple and not asfTuple is intended */
                 }
                 adfTuple[0] = asfTuple[0] + adfTupleBase[0];
                 adfTuple[1] = asfTuple[1] + adfTupleBase[1];
             }
 
-            poLS->setPoint( iPoint, adfTuple[0], adfTuple[1] );
+            poLS->setPointM( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
             adfTupleBase[0] = adfTuple[0];
             adfTupleBase[1] = adfTuple[1];
         }
@@ -1399,7 +1429,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 /* -------------------------------------------------------------------- */
     else if( nGType == OGRSpliteComprLineStringXYZM )
     {
-        double adfTuple[3];
+        double adfTuple[4];
         double adfTupleBase[3];
         float asfTuple[3];
         GInt32 nPointCount;
@@ -1431,13 +1461,13 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         adfTupleBase[0] = 0.0;
         adfTupleBase[1] = 0.0;
         adfTupleBase[2] = 0.0;
-		
+
         for( iPoint = 0; iPoint < nPointCount; iPoint++ )
         {
             if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
             {
                 // first and last Points are uncompressed
-                memcpy( adfTuple, pabyData + nNextByte, 3*8 );
+                memcpy( adfTuple, pabyData + nNextByte, 4*8 );
                 nNextByte += 4 * 8;
 
                 if (NEED_SWAP_SPATIALITE())
@@ -1445,12 +1475,14 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                     CPL_SWAP64PTR( adfTuple );
                     CPL_SWAP64PTR( adfTuple + 1 );
                     CPL_SWAP64PTR( adfTuple + 2 );
+                    CPL_SWAP64PTR( adfTuple + 3 );
                 }
             }
             else
             {
                 // any other intermediate Point is compressed
                 memcpy( asfTuple, pabyData + nNextByte, 3*4 );
+                memcpy( adfTuple + 3, pabyData + nNextByte + 3*4, 8 );
                 nNextByte += 3 * 4 + 8;
 
                 if (NEED_SWAP_SPATIALITE())
@@ -1458,13 +1490,14 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                     CPL_SWAP32PTR( asfTuple );
                     CPL_SWAP32PTR( asfTuple + 1 );
                     CPL_SWAP32PTR( asfTuple + 2 );
+                    CPL_SWAP64PTR( adfTuple + 3 ); /* adfTuple and not asfTuple is intended */
                 }
                 adfTuple[0] = asfTuple[0] + adfTupleBase[0];
                 adfTuple[1] = asfTuple[1] + adfTupleBase[1];
                 adfTuple[2] = asfTuple[2] + adfTupleBase[2];
             }
 
-            poLS->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
+            poLS->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2], adfTuple[3] );
             adfTupleBase[0] = adfTuple[0];
             adfTupleBase[1] = adfTuple[1];
             adfTupleBase[2] = adfTuple[2];
@@ -1497,12 +1530,12 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         if (nRingCount < 0 || nRingCount > INT_MAX / 4)
             return OGRERR_CORRUPT_DATA;
 
-        // Each ring has a minimum of 4 bytes 
+        // Each ring has a minimum of 4 bytes
         if (nBytes - 8 < nRingCount * 4)
             return OGRERR_NOT_ENOUGH_DATA;
 
         nNextByte = 8;
-        
+
         poGeom = poPoly = new OGRPolygon();
 
         for( iRing = 0; iRing < nRingCount; iRing++ )
@@ -1585,7 +1618,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
             return OGRERR_NOT_ENOUGH_DATA;
 
         nNextByte = 8;
-        
+
         poGeom = poPoly = new OGRPolygon();
 
         for( iRing = 0; iRing < nRingCount; iRing++ )
@@ -1616,7 +1649,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 
             poLR = new OGRLinearRing();
             poLR->setNumPoints( nPointCount, FALSE );
-            
+
             for( iPoint = 0; iPoint < nPointCount; iPoint++ )
             {
                 memcpy( adfTuple, pabyData + nNextByte, 3*8 );
@@ -1662,12 +1695,12 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         if (nRingCount < 0 || nRingCount > INT_MAX / 4)
             return OGRERR_CORRUPT_DATA;
 
-        // Each ring has a minimum of 4 bytes 
+        // Each ring has a minimum of 4 bytes
         if (nBytes - 8 < nRingCount * 4)
             return OGRERR_NOT_ENOUGH_DATA;
 
         nNextByte = 8;
-        
+
         poGeom = poPoly = new OGRPolygon();
 
         for( iRing = 0; iRing < nRingCount; iRing++ )
@@ -1698,7 +1731,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 
             poLR = new OGRLinearRing();
             poLR->setNumPoints( nPointCount, FALSE );
-            
+
             for( iPoint = 0; iPoint < nPointCount; iPoint++ )
             {
                 memcpy( adfTuple, pabyData + nNextByte, 3*8 );
@@ -1711,7 +1744,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                     CPL_SWAP64PTR( adfTuple + 2 );
                 }
 
-                poLR->setPoint( iPoint, adfTuple[0], adfTuple[1] );
+                poLR->setPointM( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
             }
 
             poPoly->addRingDirectly( poLR );
@@ -1744,12 +1777,12 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         if (nRingCount < 0 || nRingCount > INT_MAX / 4)
             return OGRERR_CORRUPT_DATA;
 
-        // Each ring has a minimum of 4 bytes 
+        // Each ring has a minimum of 4 bytes
         if (nBytes - 8 < nRingCount * 4)
             return OGRERR_NOT_ENOUGH_DATA;
 
         nNextByte = 8;
-        
+
         poGeom = poPoly = new OGRPolygon();
 
         for( iRing = 0; iRing < nRingCount; iRing++ )
@@ -1780,7 +1813,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 
             poLR = new OGRLinearRing();
             poLR->setNumPoints( nPointCount, FALSE );
-            
+
             for( iPoint = 0; iPoint < nPointCount; iPoint++ )
             {
                 memcpy( adfTuple, pabyData + nNextByte, 4*8 );
@@ -1794,7 +1827,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                     CPL_SWAP64PTR( adfTuple + 3 );
                 }
 
-                poLR->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
+                poLR->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2], adfTuple[3] );
             }
 
             poPoly->addRingDirectly( poLR );
@@ -1834,7 +1867,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
             return OGRERR_NOT_ENOUGH_DATA;
 
         nNextByte = 8;
-        
+
         poGeom = poPoly = new OGRPolygon();
 
         for( iRing = 0; iRing < nRingCount; iRing++ )
@@ -1870,12 +1903,12 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 
             poLR = new OGRLinearRing();
             poLR->setNumPoints( nPointCount, FALSE );
-            
+
             for( iPoint = 0; iPoint < nPointCount; iPoint++ )
             {
                 if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
                 {
-                    // first and last Points are uncompressed 
+                    // first and last Points are uncompressed
                     memcpy( adfTuple, pabyData + nNextByte, 2*8 );
                     nNextByte += 2 * 8;
 
@@ -1942,7 +1975,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
             return OGRERR_NOT_ENOUGH_DATA;
 
         nNextByte = 8;
-        
+
         poGeom = poPoly = new OGRPolygon();
 
         for( iRing = 0; iRing < nRingCount; iRing++ )
@@ -1979,12 +2012,12 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 
             poLR = new OGRLinearRing();
             poLR->setNumPoints( nPointCount, FALSE );
-            
+
             for( iPoint = 0; iPoint < nPointCount; iPoint++ )
             {
                 if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
                 {
-                    // first and last Points are uncompressed 
+                    // first and last Points are uncompressed
                     memcpy( adfTuple, pabyData + nNextByte, 3*8 );
                     nNextByte += 3 * 8;
 
@@ -2030,8 +2063,8 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 /* -------------------------------------------------------------------- */
     else if( nGType == OGRSpliteComprPolygonXYM )
     {
-        double adfTuple[2];
-        double adfTupleBase[3];
+        double adfTuple[3];
+        double adfTupleBase[2];
         float asfTuple[2];
         GInt32 nPointCount;
         GInt32 nRingCount;
@@ -2055,7 +2088,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
             return OGRERR_NOT_ENOUGH_DATA;
 
         nNextByte = 8;
-        
+
         poGeom = poPoly = new OGRPolygon();
 
         for( iRing = 0; iRing < nRingCount; iRing++ )
@@ -2092,37 +2125,40 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 
             poLR = new OGRLinearRing();
             poLR->setNumPoints( nPointCount, FALSE );
-            
+
             for( iPoint = 0; iPoint < nPointCount; iPoint++ )
             {
                 if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
                 {
-                    // first and last Points are uncompressed 
-                    memcpy( adfTuple, pabyData + nNextByte, 2*8 );
-                    nNextByte += 2 * 8;
+                    // first and last Points are uncompressed
+                    memcpy( adfTuple, pabyData + nNextByte, 3*8 );
+                    nNextByte += 3 * 8;
 
                     if (NEED_SWAP_SPATIALITE())
                     {
                         CPL_SWAP64PTR( adfTuple );
                         CPL_SWAP64PTR( adfTuple + 1 );
+                        CPL_SWAP64PTR( adfTuple + 2 );
                     }
                 }
                 else
                 {
                     // any other intermediate Point is compressed
                     memcpy( asfTuple, pabyData + nNextByte, 2*4 );
+                    memcpy( adfTuple + 2, pabyData + nNextByte + 2*4, 8 );
                     nNextByte += 2 * 4 + 8;
 
                     if (NEED_SWAP_SPATIALITE())
                     {
                         CPL_SWAP32PTR( asfTuple );
                         CPL_SWAP32PTR( asfTuple + 1 );
+                        CPL_SWAP64PTR( adfTuple + 2 ); /* adfTuple and not asfTuple is intended */
                     }
                     adfTuple[0] = asfTuple[0] + adfTupleBase[0];
                     adfTuple[1] = asfTuple[1] + adfTupleBase[1];
                 }
 
-                poLR->setPoint( iPoint, adfTuple[0], adfTuple[1] );
+                poLR->setPointM( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
                 adfTupleBase[0] = adfTuple[0];
                 adfTupleBase[1] = adfTuple[1];
             }
@@ -2139,7 +2175,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 /* -------------------------------------------------------------------- */
     else if( nGType == OGRSpliteComprPolygonXYZM )
     {
-        double adfTuple[3];
+        double adfTuple[4];
         double adfTupleBase[3];
         float asfTuple[3];
         GInt32 nPointCount;
@@ -2159,12 +2195,12 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         if (nRingCount < 0 || nRingCount > INT_MAX / 4)
             return OGRERR_CORRUPT_DATA;
 
-        // Each ring has a minimum of 4 bytes 
+        // Each ring has a minimum of 4 bytes
         if (nBytes - 8 < nRingCount * 4)
             return OGRERR_NOT_ENOUGH_DATA;
 
         nNextByte = 8;
-        
+
         poGeom = poPoly = new OGRPolygon();
 
         for( iRing = 0; iRing < nRingCount; iRing++ )
@@ -2202,13 +2238,13 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 
             poLR = new OGRLinearRing();
             poLR->setNumPoints( nPointCount, FALSE );
-            
+
             for( iPoint = 0; iPoint < nPointCount; iPoint++ )
             {
                 if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
                 {
                     // first and last Points are uncompressed
-                    memcpy( adfTuple, pabyData + nNextByte, 3*8 );
+                    memcpy( adfTuple, pabyData + nNextByte, 4*8 );
                     nNextByte += 4 * 8;
 
                     if (NEED_SWAP_SPATIALITE())
@@ -2216,12 +2252,14 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                         CPL_SWAP64PTR( adfTuple );
                         CPL_SWAP64PTR( adfTuple + 1 );
                         CPL_SWAP64PTR( adfTuple + 2 );
+                        CPL_SWAP64PTR( adfTuple + 3 );
                     }
                 }
                 else
                 {
-                    // any other intermediate Point is compressed 
+                    // any other intermediate Point is compressed
                     memcpy( asfTuple, pabyData + nNextByte, 3*4 );
+                    memcpy( adfTuple + 3, pabyData + nNextByte + 3*4, 8 );
                     nNextByte += 3 * 4 + 8;
 
                     if (NEED_SWAP_SPATIALITE())
@@ -2229,13 +2267,14 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                         CPL_SWAP32PTR( asfTuple );
                         CPL_SWAP32PTR( asfTuple + 1 );
                         CPL_SWAP32PTR( asfTuple + 2 );
+                        CPL_SWAP64PTR( adfTuple + 3 ); /* adfTuple and not asfTuple is intended */
                     }
                     adfTuple[0] = asfTuple[0] + adfTupleBase[0];
                     adfTuple[1] = asfTuple[1] + adfTupleBase[1];
                     adfTuple[2] = asfTuple[2] + adfTupleBase[2];
                 }
 
-                poLR->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
+                poLR->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2], adfTuple[3] );
                 adfTupleBase[0] = adfTuple[0];
                 adfTupleBase[1] = adfTuple[1];
                 adfTupleBase[2] = adfTuple[2];
@@ -2256,7 +2295,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
              ( nGType >= OGRSpliteMultiPointXYZ &&
                nGType <= OGRSpliteGeometryCollectionXYZ ) ||      // XYZ types
              ( nGType >= OGRSpliteMultiPointXYM &&
-               nGType <= OGRSpliteGeometryCollectionXYM ) ||      // XYM types 
+               nGType <= OGRSpliteGeometryCollectionXYM ) ||      // XYM types
              ( nGType >= OGRSpliteMultiPointXYZM &&
                nGType <= OGRSpliteGeometryCollectionXYZM ) ||     // XYZM types
              ( nGType >= OGRSpliteComprMultiLineStringXY &&
@@ -2271,43 +2310,58 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         OGRGeometryCollection *poGC = NULL;
         GInt32 nGeomCount = 0;
         int iGeom = 0;
-        int nBytesUsed = 0;
+
+        if( nBytes < 8 )
+            return OGRERR_NOT_ENOUGH_DATA;
+
+        memcpy( &nGeomCount, pabyData + 4, 4 );
+        if (NEED_SWAP_SPATIALITE())
+            CPL_SWAP32PTR( &nGeomCount );
+
+        if (nGeomCount < 0 || nGeomCount > INT_MAX / 9)
+            return OGRERR_CORRUPT_DATA;
+
+        // Each sub geometry takes at least 9 bytes
+        if (nBytes - 8 < nGeomCount * 9)
+            return OGRERR_NOT_ENOUGH_DATA;
+
+        int nBytesUsed = 8;
 
         switch ( nGType )
         {
             case OGRSpliteMultiPointXY:
-            case OGRSpliteMultiPointXYZ: 
-            case OGRSpliteMultiPointXYM: 
+            case OGRSpliteMultiPointXYZ:
+            case OGRSpliteMultiPointXYM:
             case OGRSpliteMultiPointXYZM:
                 poGC = new OGRMultiPoint();
                 break;
-            case OGRSpliteMultiLineStringXY: 
-            case OGRSpliteMultiLineStringXYZ: 
-            case OGRSpliteMultiLineStringXYM: 
+            case OGRSpliteMultiLineStringXY:
+            case OGRSpliteMultiLineStringXYZ:
+            case OGRSpliteMultiLineStringXYM:
             case OGRSpliteMultiLineStringXYZM:
-            case OGRSpliteComprMultiLineStringXY: 
-            case OGRSpliteComprMultiLineStringXYZ: 
-            case OGRSpliteComprMultiLineStringXYM: 
+            case OGRSpliteComprMultiLineStringXY:
+            case OGRSpliteComprMultiLineStringXYZ:
+            case OGRSpliteComprMultiLineStringXYM:
             case OGRSpliteComprMultiLineStringXYZM:
                 poGC = new OGRMultiLineString();
                 break;
-            case OGRSpliteMultiPolygonXY: 
-            case OGRSpliteMultiPolygonXYZ: 
-            case OGRSpliteMultiPolygonXYM: 
+            case OGRSpliteMultiPolygonXY:
+            case OGRSpliteMultiPolygonXYZ:
+            case OGRSpliteMultiPolygonXYM:
             case OGRSpliteMultiPolygonXYZM:
-            case OGRSpliteComprMultiPolygonXY: 
-            case OGRSpliteComprMultiPolygonXYZ: 
-            case OGRSpliteComprMultiPolygonXYM: 
+            case OGRSpliteComprMultiPolygonXY:
+            case OGRSpliteComprMultiPolygonXYZ:
+            case OGRSpliteComprMultiPolygonXYM:
             case OGRSpliteComprMultiPolygonXYZM:
                 poGC = new OGRMultiPolygon();
                 break;
-            case OGRSpliteGeometryCollectionXY: 
-            case OGRSpliteGeometryCollectionXYZ: 
-            case OGRSpliteGeometryCollectionXYM: 
+            case OGRSpliteGeometryCollectionXY:
+            case OGRSpliteGeometryCollectionXYZ:
+            case OGRSpliteGeometryCollectionXYM:
             case OGRSpliteGeometryCollectionXYZM:
-            case OGRSpliteComprGeometryCollectionXY: 
-            case OGRSpliteComprGeometryCollectionXYZ: 
-            case OGRSpliteComprGeometryCollectionXYM: 
+            case OGRSpliteComprGeometryCollectionXY:
+            case OGRSpliteComprGeometryCollectionXYZ:
+            case OGRSpliteComprGeometryCollectionXYM:
             case OGRSpliteComprGeometryCollectionXYZM:
                 poGC = new OGRGeometryCollection();
                 break;
@@ -2315,22 +2369,6 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 
         assert(NULL != poGC);
 
-        if( nBytes < 8 )
-            return OGRERR_NOT_ENOUGH_DATA;
-
-        memcpy( &nGeomCount, pabyData + 4, 4 );
-        if (NEED_SWAP_SPATIALITE())
-            CPL_SWAP32PTR( &nGeomCount );
-
-        if (nGeomCount < 0 || nGeomCount > INT_MAX / 9)
-            return OGRERR_CORRUPT_DATA;
-
-        // Each sub geometry takes at least 9 bytes
-        if (nBytes - 8 < nGeomCount * 9)
-            return OGRERR_NOT_ENOUGH_DATA;
-
-        nBytesUsed = 8;
-
         for( iGeom = 0; iGeom < nGeomCount; iGeom++ )
         {
             int nThisGeomSize;
@@ -2350,7 +2388,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 
             nBytesUsed ++;
 
-            eErr = createFromSpatialiteInternal( pabyData + nBytesUsed,
+            OGRErr eErr = createFromSpatialiteInternal( pabyData + nBytesUsed,
                                                  &poThisGeom, nBytes - nBytesUsed,
                                                  eByteOrder, &nThisGeomSize, nRecLevel + 1);
             if( eErr != OGRERR_NONE )
@@ -2381,19 +2419,8 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Assign spatial reference system.                                */
-/* -------------------------------------------------------------------- */
-    if( eErr == OGRERR_NONE )
-    {
-        *ppoReturn = poGeom;
-    }
-    else
-    {
-        delete poGeom;
-    }
-
-    return eErr;
+    *ppoReturn = poGeom;
+    return OGRERR_NONE;
 }
 
 /************************************************************************/
@@ -2457,11 +2484,15 @@ OGRErr OGRSQLiteLayer::ImportSpatiaLiteGeometry( const GByte *pabyData,
             eErr = OGRGeometryFactory::createFromWkb(
                     (unsigned char*)(pabyData + 39 + nBytesConsumed + 1),
                     NULL, &poOriginalGeometry, nBytes - (39 + nBytesConsumed + 1 + 1));
+            delete *ppoGeometry;
             if( eErr == OGRERR_NONE )
             {
-                delete *ppoGeometry;
                 *ppoGeometry = poOriginalGeometry;
             }
+            else
+            {
+                *ppoGeometry = NULL;
+            }
         }
     }
     return eErr;
@@ -2525,7 +2556,7 @@ int OGRSQLiteLayer::CanBeCompressedSpatialiteGeometry(const OGRGeometry *poGeome
 /************************************************************************/
 
 int OGRSQLiteLayer::ComputeSpatiaLiteGeometrySize(const OGRGeometry *poGeometry,
-                                                  int bHasM, int bSpatialite2D,
+                                                  int bSpatialite2D,
                                                   int bUseComprGeom)
 {
     switch (wkbFlatten(poGeometry->getGeometryType()))
@@ -2533,20 +2564,7 @@ int OGRSQLiteLayer::ComputeSpatiaLiteGeometrySize(const OGRGeometry *poGeometry,
         case wkbPoint:
             if ( bSpatialite2D == TRUE )
                 return 16;
-            else if (poGeometry->getCoordinateDimension() == 3)
-            {
-                if (bHasM == TRUE)
-                    return 32;
-                else
-                    return 24;
-            }
-            else
-            {
-                if (bHasM == TRUE)
-                    return 24;
-                else
-                    return 16;
-            }
+            return 8 * poGeometry->CoordinateDimension();
 
         case wkbLineString:
         case wkbLinearRing:
@@ -2555,10 +2573,11 @@ int OGRSQLiteLayer::ComputeSpatiaLiteGeometrySize(const OGRGeometry *poGeometry,
             int nDimension;
             int nPointsDouble = nPoints;
             int nPointsFloat = 0;
+            bool bHasM = CPL_TO_BOOL(poGeometry->IsMeasured());
             if ( bSpatialite2D == TRUE )
             {
                 nDimension = 2;
-                bHasM = FALSE;
+                bHasM = false;
             }
             else
             {
@@ -2567,7 +2586,7 @@ int OGRSQLiteLayer::ComputeSpatiaLiteGeometrySize(const OGRGeometry *poGeometry,
                     nPointsDouble = 2;
                     nPointsFloat = nPoints - 2;
                 }
-                nDimension = poGeometry->getCoordinateDimension();
+                nDimension = poGeometry->Is3D() ? 3 : 2;
             }
             return 4 + nDimension * (8 * nPointsDouble + 4 * nPointsFloat) + ((bHasM) ? nPoints * 8 : 0);
         }
@@ -2580,12 +2599,12 @@ int OGRSQLiteLayer::ComputeSpatiaLiteGeometrySize(const OGRGeometry *poGeometry,
             if (poPoly->getExteriorRing() != NULL)
             {
                 nSize += ComputeSpatiaLiteGeometrySize(poPoly->getExteriorRing(),
-                                                       bHasM, bSpatialite2D, bUseComprGeom);
+                                                       bSpatialite2D, bUseComprGeom);
 
                 int nInteriorRingCount = poPoly->getNumInteriorRings();
                 for(int i=0;i<nInteriorRingCount;i++)
                     nSize += ComputeSpatiaLiteGeometrySize(poPoly->getInteriorRing(i),
-                                                           bHasM, bSpatialite2D, bUseComprGeom );
+                                                           bSpatialite2D, bUseComprGeom );
             }
             return nSize;
         }
@@ -2600,7 +2619,7 @@ int OGRSQLiteLayer::ComputeSpatiaLiteGeometrySize(const OGRGeometry *poGeometry,
             int nParts = poGeomCollection->getNumGeometries();
             for(int i=0;i<nParts;i++)
                 nSize += 5 + ComputeSpatiaLiteGeometrySize(poGeomCollection->getGeometryRef(i),
-                                                           bHasM, bSpatialite2D, bUseComprGeom );
+                                                           bSpatialite2D, bUseComprGeom );
             return nSize;
         }
 
@@ -2615,7 +2634,7 @@ int OGRSQLiteLayer::ComputeSpatiaLiteGeometrySize(const OGRGeometry *poGeometry,
 /************************************************************************/
 
 int OGRSQLiteLayer::GetSpatialiteGeometryCode(const OGRGeometry *poGeometry,
-                                              int bHasM, int bSpatialite2D,
+                                              int bSpatialite2D,
                                               int bUseComprGeom,
                                               int bAcceptMultiGeom)
 {
@@ -2625,16 +2644,16 @@ int OGRSQLiteLayer::GetSpatialiteGeometryCode(const OGRGeometry *poGeometry,
         case wkbPoint:
             if ( bSpatialite2D == TRUE )
                 return OGRSplitePointXY;
-            else if (poGeometry->getCoordinateDimension() == 3)
+            else if (poGeometry->Is3D())
             {
-                if (bHasM == TRUE)
+                if (poGeometry->IsMeasured())
                     return OGRSplitePointXYZM;
                 else
                     return OGRSplitePointXYZ;
              }
              else
              {
-                if (bHasM == TRUE)
+                if (poGeometry->IsMeasured())
                     return OGRSplitePointXYM;
                 else
                     return OGRSplitePointXY;
@@ -2645,16 +2664,16 @@ int OGRSQLiteLayer::GetSpatialiteGeometryCode(const OGRGeometry *poGeometry,
         case wkbLinearRing:
             if ( bSpatialite2D == TRUE )
                 return OGRSpliteLineStringXY;
-            else if (poGeometry->getCoordinateDimension() == 3)
+            else if (poGeometry->Is3D())
             {
-                if (bHasM == TRUE)
+                if (poGeometry->IsMeasured())
                     return (bUseComprGeom) ? OGRSpliteComprLineStringXYZM : OGRSpliteLineStringXYZM;
                 else
                     return (bUseComprGeom) ? OGRSpliteComprLineStringXYZ : OGRSpliteLineStringXYZ;
             }
             else
             {
-                if (bHasM == TRUE)
+                if (poGeometry->IsMeasured())
                     return (bUseComprGeom) ? OGRSpliteComprLineStringXYM : OGRSpliteLineStringXYM;
                 else
                     return (bUseComprGeom) ? OGRSpliteComprLineStringXY : OGRSpliteLineStringXY;
@@ -2664,16 +2683,16 @@ int OGRSQLiteLayer::GetSpatialiteGeometryCode(const OGRGeometry *poGeometry,
         case wkbPolygon:
             if ( bSpatialite2D == TRUE )
                 return OGRSplitePolygonXY;
-            else if (poGeometry->getCoordinateDimension() == 3)
+            else if (poGeometry->Is3D())
             {
-                if (bHasM == TRUE)
+                if (poGeometry->IsMeasured())
                     return (bUseComprGeom) ? OGRSpliteComprPolygonXYZM : OGRSplitePolygonXYZM;
                 else
                     return (bUseComprGeom) ? OGRSpliteComprPolygonXYZ : OGRSplitePolygonXYZ;
             }
             else
             {
-                if (bHasM == TRUE)
+                if (poGeometry->IsMeasured())
                     return (bUseComprGeom) ? OGRSpliteComprPolygonXYM : OGRSplitePolygonXYM;
                 else
                     return (bUseComprGeom) ? OGRSpliteComprPolygonXY : OGRSplitePolygonXY;
@@ -2695,16 +2714,16 @@ int OGRSQLiteLayer::GetSpatialiteGeometryCode(const OGRGeometry *poGeometry,
         case wkbMultiPoint:
             if ( bSpatialite2D == TRUE )
                 return OGRSpliteMultiPointXY;
-            else if (poGeometry->getCoordinateDimension() == 3)
+            else if (poGeometry->Is3D())
             {
-                if (bHasM == TRUE)
+                if (poGeometry->IsMeasured())
                     return OGRSpliteMultiPointXYZM;
                 else
                     return OGRSpliteMultiPointXYZ;
             }
             else
             {
-                if (bHasM == TRUE)
+                if (poGeometry->IsMeasured())
                     return OGRSpliteMultiPointXYM;
                 else
                     return OGRSpliteMultiPointXY;
@@ -2714,16 +2733,16 @@ int OGRSQLiteLayer::GetSpatialiteGeometryCode(const OGRGeometry *poGeometry,
         case wkbMultiLineString:
             if ( bSpatialite2D == TRUE )
                 return OGRSpliteMultiLineStringXY;
-            else if (poGeometry->getCoordinateDimension() == 3)
+            else if (poGeometry->Is3D())
             {
-                if (bHasM == TRUE)
+                if (poGeometry->IsMeasured())
                     return /*(bUseComprGeom) ? OGRSpliteComprMultiLineStringXYZM :*/ OGRSpliteMultiLineStringXYZM;
                 else
                     return /*(bUseComprGeom) ? OGRSpliteComprMultiLineStringXYZ :*/ OGRSpliteMultiLineStringXYZ;
             }
             else
             {
-                if (bHasM == TRUE)
+                if (poGeometry->IsMeasured())
                     return /*(bUseComprGeom) ? OGRSpliteComprMultiLineStringXYM :*/ OGRSpliteMultiLineStringXYM;
                 else
                     return /*(bUseComprGeom) ? OGRSpliteComprMultiLineStringXY :*/ OGRSpliteMultiLineStringXY;
@@ -2733,16 +2752,16 @@ int OGRSQLiteLayer::GetSpatialiteGeometryCode(const OGRGeometry *poGeometry,
         case wkbMultiPolygon:
             if ( bSpatialite2D == TRUE )
                 return OGRSpliteMultiPolygonXY;
-            else if (poGeometry->getCoordinateDimension() == 3)
+            else if (poGeometry->Is3D())
             {
-                if (bHasM == TRUE)
+                if (poGeometry->IsMeasured())
                     return /*(bUseComprGeom) ? OGRSpliteComprMultiPolygonXYZM :*/ OGRSpliteMultiPolygonXYZM;
                 else
                     return /*(bUseComprGeom) ? OGRSpliteComprMultiPolygonXYZ :*/ OGRSpliteMultiPolygonXYZ;
             }
             else
             {
-                if (bHasM == TRUE)
+                if (poGeometry->IsMeasured())
                     return /*(bUseComprGeom) ? OGRSpliteComprMultiPolygonXYM :*/ OGRSpliteMultiPolygonXYM;
                 else
                     return /*(bUseComprGeom) ? OGRSpliteComprMultiPolygonXY :*/ OGRSpliteMultiPolygonXY;
@@ -2753,16 +2772,16 @@ int OGRSQLiteLayer::GetSpatialiteGeometryCode(const OGRGeometry *poGeometry,
         case wkbGeometryCollection:
             if ( bSpatialite2D == TRUE )
                 return OGRSpliteGeometryCollectionXY;
-            else if (poGeometry->getCoordinateDimension() == 3)
+            else if (poGeometry->Is3D())
             {
-                if (bHasM == TRUE)
+                if (poGeometry->IsMeasured())
                     return /*(bUseComprGeom) ? OGRSpliteComprGeometryCollectionXYZM :*/ OGRSpliteGeometryCollectionXYZM;
                 else
                     return /*(bUseComprGeom) ? OGRSpliteComprGeometryCollectionXYZ :*/ OGRSpliteGeometryCollectionXYZ;
             }
             else
             {
-                if (bHasM == TRUE)
+                if (poGeometry->IsMeasured())
                     return /*(bUseComprGeom) ? OGRSpliteComprGeometryCollectionXYM :*/ OGRSpliteGeometryCollectionXYM;
                 else
                     return /*(bUseComprGeom) ? OGRSpliteComprGeometryCollectionXY :*/ OGRSpliteGeometryCollectionXY;
@@ -2776,12 +2795,12 @@ int OGRSQLiteLayer::GetSpatialiteGeometryCode(const OGRGeometry *poGeometry,
 }
 
 /************************************************************************/
-/*                      ExportSpatiaLiteGeometry()                      */
+/*                    ExportSpatiaLiteGeometryInternal()                */
 /************************************************************************/
 
 int OGRSQLiteLayer::ExportSpatiaLiteGeometryInternal(const OGRGeometry *poGeometry,
                                                      OGRwkbByteOrder eByteOrder,
-                                                     int bHasM, int bSpatialite2D,
+                                                     int bSpatialite2D,
                                                      int bUseComprGeom,
                                                      GByte* pabyData )
 {
@@ -2801,15 +2820,15 @@ int OGRSQLiteLayer::ExportSpatiaLiteGeometryInternal(const OGRGeometry *poGeomet
             }
             if ( bSpatialite2D == TRUE )
                 return 16;
-            else if (poGeometry->getCoordinateDimension() == 3)
+            else if (poGeometry->Is3D())
             {
                 double z = poPoint->getZ();
                 memcpy(pabyData + 16, &z, 8);
                 if (NEED_SWAP_SPATIALITE())
                     CPL_SWAP64PTR( pabyData + 16 );
-                if (bHasM == TRUE)
+                if( poGeometry->IsMeasured() )
                 {
-                    double m = 0.0;
+                    double m = poPoint->getM();
                     memcpy(pabyData + 24, &m, 8);
                     if (NEED_SWAP_SPATIALITE())
                         CPL_SWAP64PTR( pabyData + 24 );
@@ -2820,9 +2839,9 @@ int OGRSQLiteLayer::ExportSpatiaLiteGeometryInternal(const OGRGeometry *poGeomet
             }
             else
             {
-                if (bHasM == TRUE)
+                if( poGeometry->IsMeasured() )
                 {
-                    double m = 0.0;
+                    double m = poPoint->getM();
                     memcpy(pabyData + 16, &m, 8);
                     if (NEED_SWAP_SPATIALITE())
                         CPL_SWAP64PTR( pabyData + 16 );
@@ -2843,6 +2862,14 @@ int OGRSQLiteLayer::ExportSpatiaLiteGeometryInternal(const OGRGeometry *poGeomet
             if (NEED_SWAP_SPATIALITE())
                 CPL_SWAP32PTR( pabyData );
 
+            if( !bUseComprGeom && !NEED_SWAP_SPATIALITE() &&
+                poGeometry->CoordinateDimension() == 2 )
+            {
+                poLineString->getPoints((OGRRawPoint*)(pabyData + 4), NULL);
+                nTotalSize += nPointCount * 16;
+                return nTotalSize;
+            }
+
             for(int i=0;i<nPointCount;i++)
             {
                 double x = poLineString->getX(i);
@@ -2857,15 +2884,15 @@ int OGRSQLiteLayer::ExportSpatiaLiteGeometryInternal(const OGRGeometry *poGeomet
                         CPL_SWAP64PTR( pabyData + nTotalSize );
                         CPL_SWAP64PTR( pabyData + nTotalSize + 8 );
                     }
-                    if (!bSpatialite2D && poGeometry->getCoordinateDimension() == 3)
+                    if (!bSpatialite2D && poGeometry->Is3D())
                     {
                         double z = poLineString->getZ(i);
                         memcpy(pabyData + nTotalSize + 16, &z, 8);
                         if (NEED_SWAP_SPATIALITE())
                             CPL_SWAP64PTR( pabyData + nTotalSize + 16 );
-                        if (bHasM == TRUE)
+                        if( poGeometry->IsMeasured() )
                         {
-                            double m = 0.0;
+                            double m = poLineString->getM(i);
                             memcpy(pabyData + nTotalSize + 24, &m, 8);
                             if (NEED_SWAP_SPATIALITE())
                                 CPL_SWAP64PTR( pabyData + nTotalSize + 24 );
@@ -2876,9 +2903,9 @@ int OGRSQLiteLayer::ExportSpatiaLiteGeometryInternal(const OGRGeometry *poGeomet
                     }
                     else
                     {
-                        if (bHasM == TRUE)
+                        if( poGeometry->IsMeasured() )
                         {
-                            double m = 0.0;
+                            double m = poLineString->getM(i);
                             memcpy(pabyData + nTotalSize + 16, &m, 8);
                             if (NEED_SWAP_SPATIALITE())
                                 CPL_SWAP64PTR( pabyData + nTotalSize + 16 );
@@ -2899,16 +2926,16 @@ int OGRSQLiteLayer::ExportSpatiaLiteGeometryInternal(const OGRGeometry *poGeomet
                         CPL_SWAP32PTR( pabyData + nTotalSize );
                         CPL_SWAP32PTR( pabyData + nTotalSize + 4 );
                     }
-                    if (poGeometry->getCoordinateDimension() == 3)
+                    if (poGeometry->Is3D())
                     {
                         double z = poLineString->getZ(i);
                         float deltaz = (float)(z - poLineString->getZ(i-1));
                         memcpy(pabyData + nTotalSize + 8, &deltaz, 4);
                         if (NEED_SWAP_SPATIALITE())
                             CPL_SWAP32PTR( pabyData + nTotalSize + 8 );
-                        if (bHasM == TRUE)
+                        if( poGeometry->IsMeasured() )
                         {
-                            double m = 0.0;
+                            double m = poLineString->getM(i);
                             memcpy(pabyData + nTotalSize + 12, &m, 8);
                             if (NEED_SWAP_SPATIALITE())
                                 CPL_SWAP64PTR( pabyData + nTotalSize + 12 );
@@ -2919,9 +2946,9 @@ int OGRSQLiteLayer::ExportSpatiaLiteGeometryInternal(const OGRGeometry *poGeomet
                     }
                     else
                     {
-                        if (bHasM == TRUE)
+                        if( poGeometry->IsMeasured() )
                         {
-                            double m = 0.0;
+                            double m = poLineString->getM(i);
                             memcpy(pabyData + nTotalSize + 8, &m, 8);
                             if (NEED_SWAP_SPATIALITE())
                                 CPL_SWAP64PTR( pabyData + nTotalSize + 8 );
@@ -2950,7 +2977,7 @@ int OGRSQLiteLayer::ExportSpatiaLiteGeometryInternal(const OGRGeometry *poGeomet
 
                 nTotalSize += ExportSpatiaLiteGeometryInternal(poPoly->getExteriorRing(),
                                                               eByteOrder,
-                                                              bHasM, bSpatialite2D,
+                                                              bSpatialite2D,
                                                               bUseComprGeom,
                                                               pabyData + nTotalSize);
 
@@ -2958,7 +2985,7 @@ int OGRSQLiteLayer::ExportSpatiaLiteGeometryInternal(const OGRGeometry *poGeomet
                 {
                     nTotalSize += ExportSpatiaLiteGeometryInternal(poPoly->getInteriorRing(i),
                                                                    eByteOrder,
-                                                                   bHasM, bSpatialite2D,
+                                                                   bSpatialite2D,
                                                                    bUseComprGeom,
                                                                    pabyData + nTotalSize);
                 }
@@ -2987,7 +3014,7 @@ int OGRSQLiteLayer::ExportSpatiaLiteGeometryInternal(const OGRGeometry *poGeomet
                 pabyData[nTotalSize] = 0x69;
                 nTotalSize ++;
                 int nCode = GetSpatialiteGeometryCode(poGeomCollection->getGeometryRef(i),
-                                                      bHasM, bSpatialite2D,
+                                                      bSpatialite2D,
                                                       bUseComprGeom, FALSE);
                 if (nCode == 0)
                     return 0;
@@ -2997,7 +3024,7 @@ int OGRSQLiteLayer::ExportSpatiaLiteGeometryInternal(const OGRGeometry *poGeomet
                 nTotalSize += 4;
                 nTotalSize += ExportSpatiaLiteGeometryInternal(poGeomCollection->getGeometryRef(i),
                                                                eByteOrder,
-                                                               bHasM, bSpatialite2D,
+                                                               bSpatialite2D,
                                                                bUseComprGeom,
                                                                pabyData + nTotalSize);
             }
@@ -3013,10 +3040,10 @@ int OGRSQLiteLayer::ExportSpatiaLiteGeometryInternal(const OGRGeometry *poGeomet
 OGRErr OGRSQLiteLayer::ExportSpatiaLiteGeometry( const OGRGeometry *poGeometry,
                                                  GInt32 nSRID,
                                                  OGRwkbByteOrder eByteOrder,
-                                                 int bHasM, int bSpatialite2D,
+                                                 int bSpatialite2D,
                                                  int bUseComprGeom,
                                                  GByte **ppabyData,
-                                                 int *pnDataLenght )
+                                                 int *pnDataLength )
 
 {
     /* Spatialite does not support curve geometries */
@@ -3025,11 +3052,10 @@ OGRErr OGRSQLiteLayer::ExportSpatiaLiteGeometry( const OGRGeometry *poGeometry,
         poWorkGeom = poGeometry->getLinearGeometry();
     else
         poWorkGeom = poGeometry;
-    
+
     bUseComprGeom = bUseComprGeom && !bSpatialite2D && CanBeCompressedSpatialiteGeometry(poWorkGeom);
 
     int     nDataLen = 44 + ComputeSpatiaLiteGeometrySize( poWorkGeom,
-                                                           bHasM, 
                                                            bSpatialite2D,
                                                            bUseComprGeom );
     OGREnvelope sEnvelope;
@@ -3052,21 +3078,21 @@ OGRErr OGRSQLiteLayer::ExportSpatiaLiteGeometry( const OGRGeometry *poGeometry,
     (*ppabyData)[38] = 0x7C;
 
     int nCode = GetSpatialiteGeometryCode(poWorkGeom,
-                                          bHasM, bSpatialite2D,
+                                          bSpatialite2D,
                                           bUseComprGeom, TRUE);
     if (nCode == 0)
     {
         CPLFree(*ppabyData);
         *ppabyData = NULL;
-        *pnDataLenght = 0;
+        *pnDataLength = 0;
         if( poWorkGeom != poGeometry ) delete poWorkGeom;
-        return CE_Failure;
+        return OGRERR_FAILURE;
     }
     memcpy( *ppabyData + 39, &nCode, 4 );
 
-    int nWritten = ExportSpatiaLiteGeometryInternal(poWorkGeom, 
-                                                    eByteOrder, 
-                                                    bHasM, bSpatialite2D,
+    int nWritten = ExportSpatiaLiteGeometryInternal(poWorkGeom,
+                                                    eByteOrder,
+                                                    bSpatialite2D,
                                                     bUseComprGeom,
                                                     *ppabyData + 43);
     if( poWorkGeom != poGeometry ) delete poWorkGeom;
@@ -3075,8 +3101,8 @@ OGRErr OGRSQLiteLayer::ExportSpatiaLiteGeometry( const OGRGeometry *poGeometry,
     {
         CPLFree(*ppabyData);
         *ppabyData = NULL;
-        *pnDataLenght = 0;
-        return CE_Failure;
+        *pnDataLength = 0;
+        return OGRERR_FAILURE;
     }
 
     (*ppabyData)[nDataLen - 1] = 0xFE;
@@ -3091,9 +3117,9 @@ OGRErr OGRSQLiteLayer::ExportSpatiaLiteGeometry( const OGRGeometry *poGeometry,
         CPL_SWAP32PTR( *ppabyData + 39 );
     }
 
-    *pnDataLenght = nDataLen;
+    *pnDataLength = nDataLen;
 
-    return CE_None;
+    return OGRERR_NONE;
 }
 
 /************************************************************************/
@@ -3113,12 +3139,12 @@ int OGRSQLiteLayer::TestCapability( const char * pszCap )
         return FALSE;
 
     else if( EQUAL(pszCap,OLCIgnoreFields) )
-        return TRUE; 
+        return TRUE;
 
     else if( EQUAL(pszCap,OLCTransactions) )
         return TRUE;
 
-    else 
+    else
         return FALSE;
 }
 
@@ -3174,16 +3200,19 @@ void OGRSQLiteLayer::ClearStatement()
 int OGRSQLITEStringToDateTimeField( OGRFeature* poFeature, int iField,
                                     const char* pszValue )
 {
-    int nYear = 0, nMonth = 0, nDay = 0,
-        nHour = 0, nMinute = 0;
-    float fSecond = 0;
-
-    /* YYYY-MM-DD HH:MM:SS or YYYY-MM-DD HH:MM:SS.SSS */
-    nYear = 0; nMonth = 0; nDay = 0; nHour = 0;
-    nMinute = 0; fSecond = 0;
+    int nYear = 0;
+    int nMonth = 0;
+    int nDay = 0;
+    int nHour = 0;
+    int nMinute = 0;
+    float fSecond = 0.0f;
+
+    /* YYYY-MM-DD HH:MM:SS.SSS */
     if( sscanf(pszValue, "%04d-%02d-%02d %02d:%02d:%f",
                 &nYear, &nMonth, &nDay, &nHour, &nMinute, &fSecond) == 6 ||
         sscanf(pszValue, "%04d/%02d/%02d %02d:%02d:%f",
+                &nYear, &nMonth, &nDay, &nHour, &nMinute, &fSecond) == 6 ||
+        sscanf(pszValue, "%04d-%02d-%02dT%02d:%02d:%f",
                 &nYear, &nMonth, &nDay, &nHour, &nMinute, &fSecond) == 6 )
     {
         if( poFeature )
@@ -3193,11 +3222,11 @@ int OGRSQLITEStringToDateTimeField( OGRFeature* poFeature, int iField,
     }
 
     /* YYYY-MM-DD HH:MM */
-    nYear = 0; nMonth = 0; nDay = 0; nHour = 0;
-    nMinute = 0;
     if( sscanf(pszValue, "%04d-%02d-%02d %02d:%02d",
                 &nYear, &nMonth, &nDay, &nHour, &nMinute) == 5 ||
         sscanf(pszValue, "%04d/%02d/%02d %02d:%02d",
+                &nYear, &nMonth, &nDay, &nHour, &nMinute) == 5 ||
+        sscanf(pszValue, "%04d-%02d-%02dT%02d:%02d",
                 &nYear, &nMonth, &nDay, &nHour, &nMinute) == 5 )
     {
         if( poFeature )
@@ -3206,32 +3235,7 @@ int OGRSQLITEStringToDateTimeField( OGRFeature* poFeature, int iField,
         return OFTDateTime;
     }
 
-    /*  YYYY-MM-DDTHH:MM:SS or YYYY-MM-DDTHH:MM:SS.SSS */
-    nYear = 0; nMonth = 0; nDay = 0; nHour = 0;
-    nMinute = 0; fSecond = 0;
-    if( sscanf(pszValue, "%04d-%02d-%02dT%02d:%02d:%f",
-                &nYear, &nMonth, &nDay, &nHour, &nMinute, &fSecond) == 6 )
-    {
-        if( poFeature )
-            poFeature->SetField( iField, nYear, nMonth, nDay,
-                                 nHour, nMinute, fSecond, 0);
-        return OFTDateTime;
-    }
-
-    /* YYYY-MM-DDTHH:MM */
-    nYear = 0; nMonth = 0; nDay = 0; nHour = 0;
-    nMinute = 0;
-    if( sscanf(pszValue, "%04d-%02d-%02dT%02d:%02d",
-                &nYear, &nMonth, &nDay, &nHour, &nMinute) == 5 )
-    {
-        if( poFeature )
-            poFeature->SetField( iField, nYear, nMonth, nDay,
-                                 nHour, nMinute, 0, 0);
-        return OFTDateTime;
-    }
-
     /* YYYY-MM-DD */
-    nYear = 0; nMonth = 0; nDay = 0;
     if( sscanf(pszValue, "%04d-%02d-%02d",
                 &nYear, &nMonth, &nDay) == 3 ||
         sscanf(pszValue, "%04d/%02d/%02d",
@@ -3243,8 +3247,7 @@ int OGRSQLITEStringToDateTimeField( OGRFeature* poFeature, int iField,
         return OFTDate;
     }
 
-    /*  HH:MM:SS or HH:MM:SS.SSS */
-    nDay = 0; nHour = 0; fSecond = 0;
+    /*  HH:MM:SS.SSS */
     if( sscanf(pszValue, "%02d:%02d:%f",
         &nHour, &nMinute, &fSecond) == 3 )
     {
@@ -3255,7 +3258,6 @@ int OGRSQLITEStringToDateTimeField( OGRFeature* poFeature, int iField,
     }
 
     /*  HH:MM */
-    nHour = 0; nMinute = 0;
     if( sscanf(pszValue, "%02d:%02d", &nHour, &nMinute) == 2 )
     {
         if( poFeature )
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqliteregexp.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqliteregexp.cpp
index 19a9366..76632ff 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqliteregexp.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqliteregexp.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqliteregexp.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogrsqliteregexp.cpp 32982 2016-01-14 16:53:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  SQLite REGEXP function
@@ -156,7 +156,7 @@ void OGRSQLiteREGEXPFunction(sqlite3_context *ctx, CPL_UNUSED int argc, sqlite3_
 
     int rc;
     CPLAssert(p);
-    rc = pcre_exec(p, e, str, strlen(str), 0, 0, NULL, 0);
+    rc = pcre_exec(p, e, str, static_cast<int>(strlen(str)), 0, 0, NULL, 0);
     sqlite3_result_int(ctx, rc >= 0);
 }
 
@@ -167,12 +167,16 @@ void OGRSQLiteREGEXPFunction(sqlite3_context *ctx, CPL_UNUSED int argc, sqlite3_
 /************************************************************************/
 
 static
-void* OGRSQLiteRegisterRegExpFunction(sqlite3* hDB)
+void* OGRSQLiteRegisterRegExpFunction(sqlite3*
+#ifdef HAVE_PCRE
+                                       hDB
+#endif
+                                      )
 {
 #ifdef HAVE_PCRE
 
     /* For debugging purposes mostly */
-    if( !CSLTestBoolean(CPLGetConfigOption("OGR_SQLITE_REGEXP", "YES")) )
+    if( !CPLTestBool(CPLGetConfigOption("OGR_SQLITE_REGEXP", "YES")) )
         return NULL;
 
     /* Check if we really need to define our own REGEXP function */
@@ -201,7 +205,11 @@ void* OGRSQLiteRegisterRegExpFunction(sqlite3* hDB)
 /************************************************************************/
 
 static
-void OGRSQLiteFreeRegExpCache(void* hRegExpCache)
+void OGRSQLiteFreeRegExpCache(void*
+#ifdef HAVE_PCRE
+                              hRegExpCache
+#endif
+                              )
 {
 #ifdef HAVE_PCRE
     if( hRegExpCache == NULL )
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqliteregexp.h b/ogr/ogrsf_frmts/sqlite/ogrsqliteregexp.h
index 585e10b..09840e6 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqliteregexp.h
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqliteregexp.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqliteregexp.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: ogrsqliteregexp.h 31777 2015-11-26 14:14:41Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  SQLite REGEXP function
@@ -27,12 +27,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_SQLITE_REGEXP_INCLUDED
-#define _OGR_SQLITE_REGEXP_INCLUDED
+#ifndef OGR_SQLITE_REGEXP_INCLUDED
+#define OGR_SQLITE_REGEXP_INCLUDED
 
 #include "ogr_sqlite.h"
 
 static void* OGRSQLiteRegisterRegExpFunction(sqlite3* hDB);
 static void OGRSQLiteFreeRegExpCache(void* hRegExpCache);
 
-#endif // _OGR_SQLITE_REGEXP_INCLUDED
+#endif // OGR_SQLITE_REGEXP_INCLUDED
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqliteselectlayer.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqliteselectlayer.cpp
index a3f1f24..11ccb46 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqliteselectlayer.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqliteselectlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqliteselectlayer.cpp 30272 2015-09-11 07:58:08Z rouault $
+ * $Id: ogrsqliteselectlayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteSelectLayer class, layer access to the results
@@ -34,18 +34,18 @@
 #include "swq.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrsqliteselectlayer.cpp 30272 2015-09-11 07:58:08Z rouault $");
+CPL_CVSID("$Id: ogrsqliteselectlayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                   OGRSQLiteSelectLayerCommonBehaviour()              */
 /************************************************************************/
 
-OGRSQLiteSelectLayerCommonBehaviour::OGRSQLiteSelectLayerCommonBehaviour(OGRSQLiteBaseDataSource* poDS,
-                                            IOGRSQLiteSelectLayer* poLayer,
-                                            CPLString osSQL,
-                                            int bEmptyLayer) :
-            poDS(poDS), poLayer(poLayer), osSQLBase(osSQL),
-            bEmptyLayer(bEmptyLayer), osSQLCurrent(osSQL)
+OGRSQLiteSelectLayerCommonBehaviour::OGRSQLiteSelectLayerCommonBehaviour(OGRSQLiteBaseDataSource* poDSIn,
+                                            IOGRSQLiteSelectLayer* poLayerIn,
+                                            CPLString osSQLIn,
+                                            int bEmptyLayerIn) :
+            poDS(poDSIn), poLayer(poLayerIn), osSQLBase(osSQLIn),
+            bEmptyLayer(bEmptyLayerIn), osSQLCurrent(osSQLIn)
 {
     bAllowResetReadingEvenIfIndexAtZero = FALSE;
     bSpatialFilterInSQL = TRUE;
@@ -60,13 +60,13 @@ OGRSQLiteSelectLayer::OGRSQLiteSelectLayer( OGRSQLiteDataSource *poDSIn,
                                             sqlite3_stmt *hStmtIn,
                                             int bUseStatementForGetNextFeature,
                                             int bEmptyLayer,
-                                            int bAllowMultipleGeomFields )
+                                            int bAllowMultipleGeomFieldsIn )
 
 {
     poBehaviour = new OGRSQLiteSelectLayerCommonBehaviour(poDSIn, this, osSQLIn, bEmptyLayer);
     poDS = poDSIn;
 
-    this->bAllowMultipleGeomFields = bAllowMultipleGeomFields;
+    this->bAllowMultipleGeomFields = bAllowMultipleGeomFieldsIn;
 
     std::set<CPLString> aosEmpty;
     BuildFeatureDefn( "SELECT", hStmtIn, aosEmpty, aosEmpty );
@@ -266,7 +266,7 @@ GIntBig OGRSQLiteSelectLayerCommonBehaviour::GetFeatureCount( int bForce )
         return 0;
 
     if( poLayer->GetFeatureQuery() == NULL &&
-        EQUALN(osSQLCurrent, "SELECT COUNT(*) FROM", strlen("SELECT COUNT(*) FROM")) &&
+        STARTS_WITH_CI(osSQLCurrent, "SELECT COUNT(*) FROM") &&
         osSQLCurrent.ifind(" GROUP BY ") == std::string::npos &&
         osSQLCurrent.ifind(" UNION ") == std::string::npos &&
         osSQLCurrent.ifind(" INTERSECT ") == std::string::npos &&
@@ -290,7 +290,7 @@ GIntBig OGRSQLiteSelectLayerCommonBehaviour::GetFeatureCount( int bForce )
     int nRowCount, nColCount;
     int nResult = -1;
 
-    if( sqlite3_get_table( poDS->GetDB(), osFeatureCountSQL, &papszResult, 
+    if( sqlite3_get_table( poDS->GetDB(), osFeatureCountSQL, &papszResult,
                            &nRowCount, &nColCount, &pszErrMsg ) != SQLITE_OK )
     {
         CPLDebug("SQLITE", "Error: %s", pszErrMsg);
@@ -326,7 +326,8 @@ OGRErr OGRSQLiteSelectLayer::ResetStatement()
     CPLDebug( "OGR_SQLITE", "prepare(%s)", poBehaviour->osSQLCurrent.c_str() );
 #endif
 
-    rc = sqlite3_prepare( poDS->GetDB(), poBehaviour->osSQLCurrent, poBehaviour->osSQLCurrent.size(),
+    rc = sqlite3_prepare( poDS->GetDB(), poBehaviour->osSQLCurrent,
+                          static_cast<int>(poBehaviour->osSQLCurrent.size()),
                           &hStmt, NULL );
 
     if( rc == SQLITE_OK )
@@ -335,8 +336,8 @@ OGRErr OGRSQLiteSelectLayer::ResetStatement()
     }
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "In ResetStatement(): sqlite3_prepare(%s):\n  %s", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "In ResetStatement(): sqlite3_prepare(%s):\n  %s",
                   poBehaviour->osSQLCurrent.c_str(), sqlite3_errmsg(poDS->GetDB()) );
         hStmt = NULL;
         return OGRERR_FAILURE;
@@ -534,7 +535,7 @@ int OGRSQLiteSelectLayerCommonBehaviour::BuildSQL()
     while (i < osSQLBase.size() && osSQLBase[i] == ' ')
         i ++;
 
-    if (i < osSQLBase.size() && EQUALN(osSQLBase.c_str() + i, "WHERE ", 6))
+    if (i < osSQLBase.size() && STARTS_WITH_CI(osSQLBase.c_str() + i, "WHERE "))
     {
         osSQLCurrent = osSQLBase.substr(0, i + 6);
         osSQLCurrent += osCustomWhere;
@@ -559,9 +560,9 @@ int OGRSQLiteSelectLayerCommonBehaviour::BuildSQL()
         }
     }
     else if (i < osSQLBase.size() &&
-             (EQUALN(osSQLBase.c_str() + i, "GROUP ", 6) ||
-              EQUALN(osSQLBase.c_str() + i, "ORDER ", 6) ||
-              EQUALN(osSQLBase.c_str() + i, "LIMIT ", 6)))
+             (STARTS_WITH_CI(osSQLBase.c_str() + i, "GROUP ") ||
+              STARTS_WITH_CI(osSQLBase.c_str() + i, "ORDER ") ||
+              STARTS_WITH_CI(osSQLBase.c_str() + i, "LIMIT ")))
     {
         osSQLCurrent = osSQLBase.substr(0, i);
         osSQLCurrent += " WHERE ";
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitesinglefeaturelayer.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitesinglefeaturelayer.cpp
index b204536..71873ae 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitesinglefeaturelayer.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitesinglefeaturelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqlitesinglefeaturelayer.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogrsqlitesinglefeaturelayer.cpp 32011 2015-12-06 10:19:18Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteSingleFeatureLayer class.
@@ -31,7 +31,7 @@
 #include "cpl_string.h"
 #include "ogr_sqlite.h"
 
-CPL_CVSID("$Id: ogrsqlitesinglefeaturelayer.cpp 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: ogrsqlitesinglefeaturelayer.cpp 32011 2015-12-06 10:19:18Z rouault $");
 
 /************************************************************************/
 /*                    OGRSQLiteSingleFeatureLayer()                     */
@@ -39,7 +39,7 @@ CPL_CVSID("$Id: ogrsqlitesinglefeaturelayer.cpp 27384 2014-05-24 12:28:12Z rouau
 
 OGRSQLiteSingleFeatureLayer::OGRSQLiteSingleFeatureLayer(
                                                      const char* pszLayerName,
-                                                     int nVal )
+                                                     int nValIn )
 {
     poFeatureDefn = new OGRFeatureDefn( "SELECT" );
     SetDescription( poFeatureDefn->GetName() );
@@ -48,7 +48,7 @@ OGRSQLiteSingleFeatureLayer::OGRSQLiteSingleFeatureLayer(
     poFeatureDefn->AddFieldDefn( &oField );
 
     iNextShapeId = 0;
-    this->nVal = nVal;
+    this->nVal = nValIn;
     pszVal = NULL;
 }
 
@@ -58,7 +58,7 @@ OGRSQLiteSingleFeatureLayer::OGRSQLiteSingleFeatureLayer(
 
 OGRSQLiteSingleFeatureLayer::OGRSQLiteSingleFeatureLayer(
                                                      const char* pszLayerName,
-                                                     const char *pszVal )
+                                                     const char *pszValIn )
 {
     poFeatureDefn = new OGRFeatureDefn( "SELECT" );
     poFeatureDefn->Reference();
@@ -67,7 +67,7 @@ OGRSQLiteSingleFeatureLayer::OGRSQLiteSingleFeatureLayer(
 
     iNextShapeId = 0;
     nVal = 0;
-    this->pszVal = CPLStrdup(pszVal);
+    this->pszVal = CPLStrdup(pszValIn);
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitesqlfunctions.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitesqlfunctions.cpp
index d3bfab1..241ffa6 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitesqlfunctions.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitesqlfunctions.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqlitesqlfunctions.cpp 28382 2015-01-30 15:29:41Z rouault $
+ * $Id: ogrsqlitesqlfunctions.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Extension SQL functions
@@ -62,7 +62,7 @@ class OGRSQLiteExtensionData
 
     OGRGeocodingSessionH         GetGeocodingSession() { return hGeocodingSession; }
     void                         SetGeocodingSession(OGRGeocodingSessionH hGeocodingSessionIn) { hGeocodingSession = hGeocodingSessionIn; }
-    
+
     void                         SetRegExpCache(void* hRegExpCacheIn) { hRegExpCache = hRegExpCacheIn; }
 };
 
@@ -94,7 +94,7 @@ OGRSQLiteExtensionData::~OGRSQLiteExtensionData()
         delete oIter->second;
 
     OGRSQLiteFreeRegExpCache(hRegExpCache);
-    
+
     OGRGeocodeDestroySession(hGeocodingSession);
 }
 
@@ -192,11 +192,11 @@ void OGR2SQLITE_Transform(sqlite3_context* pContext,
     int nBLOBLen = sqlite3_value_bytes (argv[0]);
     OGRGeometry* poGeom = NULL;
     if( OGRSQLiteLayer::ImportSpatiaLiteGeometry(
-                    pabySLBLOB, nBLOBLen, &poGeom ) == CE_None &&
+                    pabySLBLOB, nBLOBLen, &poGeom ) == OGRERR_NONE &&
         poGeom->transform(poCT) == OGRERR_NONE &&
         OGRSQLiteLayer::ExportSpatiaLiteGeometry(
                     poGeom, nDstSRSId, wkbNDR, FALSE,
-                    FALSE, FALSE, &pabySLBLOB, &nBLOBLen ) == CE_None )
+                    FALSE, &pabySLBLOB, &nBLOBLen ) == OGRERR_NONE )
     {
         sqlite3_result_blob(pContext, pabySLBLOB, nBLOBLen, CPLFree);
     }
@@ -248,13 +248,13 @@ void OGR2SQLITE_ogr_deflate(sqlite3_context* pContext,
     }
     if( pOut != NULL )
     {
-        sqlite3_result_blob (pContext, pOut, nOutBytes, VSIFree);
+        sqlite3_result_blob (pContext, pOut, static_cast<int>(nOutBytes), VSIFree);
     }
     else
     {
         sqlite3_result_null (pContext);
     }
- 
+
     return;
 }
 
@@ -266,7 +266,7 @@ static
 void OGR2SQLITE_ogr_inflate(sqlite3_context* pContext,
                             int argc, sqlite3_value** argv)
 {
-    if( argc != 1 || 
+    if( argc != 1 ||
         sqlite3_value_type (argv[0]) != SQLITE_BLOB )
     {
         sqlite3_result_null (pContext);
@@ -282,7 +282,7 @@ void OGR2SQLITE_ogr_inflate(sqlite3_context* pContext,
 
     if( pOut != NULL )
     {
-        sqlite3_result_blob (pContext, pOut, nOutBytes, VSIFree);
+        sqlite3_result_blob (pContext, pOut, static_cast<int>(nOutBytes), VSIFree);
     }
     else
     {
@@ -317,9 +317,9 @@ void OGR2SQLITE_ogr_geocode_set_result(sqlite3_context* pContext,
             GByte* pabyGeomBLOB = NULL;
             int nGeomBLOBLen = 0;
             if( OGRSQLiteLayer::ExportSpatiaLiteGeometry(
-                    poFeature->GetGeometryRef(), 4326, wkbNDR, FALSE, FALSE, FALSE,
+                    poFeature->GetGeometryRef(), 4326, wkbNDR, FALSE, FALSE,
                     &pabyGeomBLOB,
-                    &nGeomBLOBLen ) != CE_None )
+                    &nGeomBLOBLen ) != OGRERR_NONE )
             {
                 sqlite3_result_null (pContext);
             }
@@ -456,8 +456,10 @@ static OGRGeometry* OGR2SQLITE_GetGeom(CPL_UNUSED sqlite3_context* pContext,
     int nBLOBLen = sqlite3_value_bytes (argv[0]);
     OGRGeometry* poGeom = NULL;
     if( OGRSQLiteLayer::ImportSpatiaLiteGeometry(
-                        pabySLBLOB, nBLOBLen, &poGeom, pnSRSId) != CE_None )
+                        pabySLBLOB, nBLOBLen, &poGeom, pnSRSId) != OGRERR_NONE )
     {
+        if( poGeom != NULL )
+            delete poGeom;
         return NULL;
     }
 
@@ -490,7 +492,7 @@ void OGR2SQLITE_ogr_geocode_reverse(sqlite3_context* pContext,
     {
         iAfterGeomIdx = 2;
     }
-    else if( argc >= 2 && 
+    else if( argc >= 2 &&
              sqlite3_value_type (argv[0]) == SQLITE_BLOB &&
              sqlite3_value_type (argv[1]) == SQLITE_TEXT )
     {
@@ -652,7 +654,7 @@ void OGR2SQLITE_ogr_GetConfigOption(sqlite3_context* pContext,
         sqlite3_result_null (pContext);
         return;
     }
-    
+
     const char* pszKey = (const char*)sqlite3_value_text(argv[0]);
     const char* pszVal = CPLGetConfigOption(pszKey, NULL);
     if( pszVal == NULL )
@@ -725,7 +727,7 @@ void OGR2SQLITE_ST_AsBinary(sqlite3_context* pContext,
     if( poGeom != NULL )
     {
         int nBLOBLen = poGeom->WkbSize();
-        GByte* pabyGeomBLOB = (GByte*) VSIMalloc(nBLOBLen);
+        GByte* pabyGeomBLOB = (GByte*) VSI_MALLOC_VERBOSE(nBLOBLen);
         if( pabyGeomBLOB != NULL )
         {
             if( poGeom->exportToWkb(wkbNDR, pabyGeomBLOB) == OGRERR_NONE )
@@ -755,8 +757,8 @@ static void OGR2SQLITE_SetGeom_AndDestroy(sqlite3_context* pContext,
     GByte* pabySLBLOB = NULL;
     int nBLOBLen = 0;
     if( poGeom != NULL && OGRSQLiteLayer::ExportSpatiaLiteGeometry(
-                    poGeom, nSRSId, wkbNDR, FALSE,
-                    FALSE, FALSE, &pabySLBLOB, &nBLOBLen ) == CE_None )
+                    poGeom, nSRSId, wkbNDR,
+                    FALSE, FALSE, &pabySLBLOB, &nBLOBLen ) == OGRERR_NONE )
     {
         sqlite3_result_blob(pContext, pabySLBLOB, nBLOBLen, CPLFree);
     }
@@ -1127,12 +1129,12 @@ void* OGRSQLiteRegisterSQLFunctions(sqlite3* hDB)
 #ifdef MINIMAL_SPATIAL_FUNCTIONS
     /* Check if spatialite is available */
     int rc = sqlite3_exec(hDB, "SELECT spatialite_version()", NULL, NULL, NULL);
-    
+
     /* Reset error flag */
     sqlite3_exec(hDB, "SELECT 1", NULL, NULL, NULL);
-    
+
     if( rc != SQLITE_OK &&
-        CSLTestBoolean(CPLGetConfigOption("OGR_SQLITE_SPATIAL_FUNCTIONS", "YES")) )
+        CPLTestBool(CPLGetConfigOption("OGR_SQLITE_SPATIAL_FUNCTIONS", "YES")) )
     {
         CPLDebug("SQLITE",
                  "Spatialite not available. Implementing a few functions");
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitesqlfunctions.h b/ogr/ogrsf_frmts/sqlite/ogrsqlitesqlfunctions.h
index da04f76..7092be3 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitesqlfunctions.h
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitesqlfunctions.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqlitesqlfunctions.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: ogrsqlitesqlfunctions.h 31777 2015-11-26 14:14:41Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Extension SQL functions
@@ -27,12 +27,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_SQLITE_SQL_FUNCTIONS_INCLUDED
-#define _OGR_SQLITE_SQL_FUNCTIONS_INCLUDED
+#ifndef OGR_SQLITE_SQL_FUNCTIONS_INCLUDED
+#define OGR_SQLITE_SQL_FUNCTIONS_INCLUDED
 
 #include "ogr_sqlite.h"
 
 static void* OGRSQLiteRegisterSQLFunctions(sqlite3* hDB);
 static void OGRSQLiteUnregisterSQLFunctions(void* hHandle);
 
-#endif // _OGR_SQLITE_SQL_FUNCTIONS_INCLUDED
+#endif // OGR_SQLITE_SQL_FUNCTIONS_INCLUDED
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp
index 0690d42..8eadd09 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqlitetablelayer.cpp 30254 2015-09-10 15:40:33Z rouault $
+ * $Id: ogrsqlitetablelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteTableLayer class, access to an existing table.
@@ -37,7 +37,7 @@
 
 #define UNSUPPORTED_OP_READ_ONLY "%s : unsupported operation on a read-only datasource."
 
-CPL_CVSID("$Id: ogrsqlitetablelayer.cpp 30254 2015-09-10 15:40:33Z rouault $");
+CPL_CVSID("$Id: ogrsqlitetablelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                        OGRSQLiteTableLayer()                         */
@@ -71,7 +71,7 @@ OGRSQLiteTableLayer::OGRSQLiteTableLayer( OGRSQLiteDataSource *poDSIn )
     bStatisticsNeedsToBeFlushed = FALSE;
     nFeatureCount = -1;
 
-    int bDisableInsertTriggers = CSLTestBoolean(CPLGetConfigOption(
+    int bDisableInsertTriggers = CPLTestBool(CPLGetConfigOption(
                             "OGR_SQLITE_DISABLE_INSERT_TRIGGERS", "YES"));
     bHasCheckedTriggers = !bDisableInsertTriggers;
     bDeferredCreation = FALSE;
@@ -89,7 +89,6 @@ OGRSQLiteTableLayer::~OGRSQLiteTableLayer()
     ClearStatement();
     ClearInsertStmt();
 
-    char* pszErrMsg = NULL;
     int nGeomFieldCount = (poFeatureDefn) ? poFeatureDefn->GetGeomFieldCount() : 0;
     for(int i=0;i<nGeomFieldCount; i++)
     {
@@ -101,14 +100,11 @@ OGRSQLiteTableLayer::~OGRSQLiteTableLayer()
                      poGeomFieldDefn->aosDisabledTriggers[j].first.c_str());
             // This may fail since CreateSpatialIndex() reinstalls triggers, so
             // don't check result
-            sqlite3_exec( poDS->GetDB(),
+            CPL_IGNORE_RET_VAL(sqlite3_exec( poDS->GetDB(),
                           poGeomFieldDefn->aosDisabledTriggers[j].second.c_str(),
-                          NULL, NULL, &pszErrMsg );
-            if( pszErrMsg )
-                sqlite3_free( pszErrMsg );
-            pszErrMsg = NULL;
+                          NULL, NULL, NULL ));
         }
-    
+
         // Update geometry_columns_time
         if( poGeomFieldDefn->aosDisabledTriggers.size() != 0 )
         {
@@ -116,10 +112,8 @@ OGRSQLiteTableLayer::~OGRSQLiteTableLayer()
                 "UPDATE geometry_columns_time SET last_insert = strftime('%%Y-%%m-%%dT%%H:%%M:%%fZ', 'now') "
                 "WHERE Lower(f_table_name) = Lower('%q') AND Lower(f_geometry_column) = Lower('%q')",
                 pszTableName, poGeomFieldDefn->GetNameRef());
-            sqlite3_exec( poDS->GetDB(), pszSQL3, NULL, NULL, &pszErrMsg );
-            if( pszErrMsg )
-                sqlite3_free( pszErrMsg );
-            pszErrMsg = NULL;
+            CPL_IGNORE_RET_VAL(sqlite3_exec( poDS->GetDB(), pszSQL3, NULL, NULL, NULL ));
+            sqlite3_free( pszSQL3 );
         }
     }
 
@@ -160,15 +154,15 @@ void OGRSQLiteTableLayer::ClearInsertStmt()
 /*                             Initialize()                             */
 /************************************************************************/
 
-CPLErr OGRSQLiteTableLayer::Initialize( const char *pszTableName, 
+CPLErr OGRSQLiteTableLayer::Initialize( const char *pszTableNameIn,
                                         int bIsVirtualShapeIn,
-                                        int bDeferredCreation )
+                                        int bDeferredCreationIn )
 {
-    SetDescription( pszTableName );
+    SetDescription( pszTableNameIn );
 
     this->bIsVirtualShape = bIsVirtualShapeIn;
-    this->pszTableName = CPLStrdup(pszTableName);
-    this->bDeferredCreation = bDeferredCreation;
+    this->pszTableName = CPLStrdup(pszTableNameIn);
+    this->bDeferredCreation = bDeferredCreationIn;
     pszEscapedTableName = CPLStrdup(OGRSQLiteEscape(pszTableName));
 
     if( strchr(pszTableName, '(') != NULL &&
@@ -181,7 +175,7 @@ CPLErr OGRSQLiteTableLayer::Initialize( const char *pszTableName,
                                         pszEscapedTableName);
         int rc = sqlite3_get_table( poDS->GetDB(),
                                 pszSQL,
-                                &papszResult, &nRowCount, 
+                                &papszResult, &nRowCount,
                                 &nColCount, &pszErrMsg );
         int bFound = ( rc == SQLITE_OK && nRowCount == 1 );
         sqlite3_free_table(papszResult);
@@ -192,7 +186,6 @@ CPLErr OGRSQLiteTableLayer::Initialize( const char *pszTableName,
             char* pszGeomCol = CPLStrdup(strchr(pszTableName, '(')+1);
             pszGeomCol[strlen(pszGeomCol)-1] = 0;
             *strchr(this->pszTableName, '(') = 0;
-            pszTableName = this->pszTableName;
             CPLFree(pszEscapedTableName),
             pszEscapedTableName = CPLStrdup(OGRSQLiteEscape(pszTableName));
             EstablishFeatureDefn(pszGeomCol);
@@ -306,21 +299,21 @@ CPLErr OGRSQLiteTableLayer::EstablishFeatureDefn(const char* pszGeomCol)
     pszSQL = CPLSPrintf( "SELECT _rowid_, * FROM '%s' LIMIT 1",
                                      pszEscapedTableName );
 
-    rc = sqlite3_prepare( hDB, pszSQL, strlen(pszSQL), &hColStmt, NULL ); 
+    rc = sqlite3_prepare( hDB, pszSQL, -1, &hColStmt, NULL );
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to query table %s for column definitions : %s.",
                   pszTableName, sqlite3_errmsg(hDB) );
-        
+
         return CE_Failure;
     }
 
     rc = sqlite3_step( hColStmt );
     if ( rc != SQLITE_DONE && rc != SQLITE_ROW )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "In Initialize(): sqlite3_step(%s):\n  %s", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "In Initialize(): sqlite3_step(%s):\n  %s",
                   pszSQL, sqlite3_errmsg(hDB) );
         sqlite3_finalize( hColStmt );
         return CE_Failure;
@@ -365,7 +358,7 @@ CPLErr OGRSQLiteTableLayer::EstablishFeatureDefn(const char* pszGeomCol)
                         OGRSQLiteEscape(pszFIDColumn).c_str(),
                         pszEscapedTableName);
     hColStmt = NULL;
-    rc = sqlite3_prepare( hDB, pszSQL, strlen(pszSQL), &hColStmt, NULL ); 
+    rc = sqlite3_prepare( hDB, pszSQL, -1, &hColStmt, NULL );
     if( rc == SQLITE_OK )
     {
         rc = sqlite3_step( hColStmt );
@@ -377,7 +370,7 @@ CPLErr OGRSQLiteTableLayer::EstablishFeatureDefn(const char* pszGeomCol)
         }
     }
     sqlite3_finalize( hColStmt );
-        
+
 /* -------------------------------------------------------------------- */
 /*      Set the properties of the geometry column.                      */
 /* -------------------------------------------------------------------- */
@@ -414,7 +407,7 @@ CPLErr OGRSQLiteTableLayer::EstablishFeatureDefn(const char* pszGeomCol)
         char** papszResult = NULL;
         rc = sqlite3_get_table( hDB,
                                 pszSQL,
-                                &papszResult, &nRowCount, 
+                                &papszResult, &nRowCount,
                                 &nColCount, &pszErrMsg );
         OGRwkbGeometryType eGeomType = wkbUnknown;
         OGRSQLiteGeomFormat eGeomFormat = OSGF_None;
@@ -430,7 +423,6 @@ CPLErr OGRSQLiteTableLayer::EstablishFeatureDefn(const char* pszGeomCol)
                 poGeomFieldDefn->nSRSId = atoi(papszRow[0]);
             if( poDS->IsSpatialiteDB() )
             {
-                int bHasM = FALSE;
                 if( papszRow[3] != NULL )
                     poGeomFieldDefn->bHasSpatialIndex = atoi(papszRow[3]);
                 if( poDS->HasSpatialite4Layout() )
@@ -442,30 +434,22 @@ CPLErr OGRSQLiteTableLayer::EstablishFeatureDefn(const char* pszGeomCol)
                     else if( nGeomType >= 1000 && nGeomType <= 1007 ) /* XYZ */
                         eGeomType = wkbSetZ(wkbFlatten(nGeomType));
                     else if( nGeomType >= 2000 && nGeomType <= 2007 ) /* XYM */
-                    {
-                        eGeomType = wkbFlatten(nGeomType);
-                        bHasM = TRUE;
-                    }
+                        eGeomType = wkbSetM(wkbFlatten(nGeomType));
                     else if( nGeomType >= 3000 && nGeomType <= 3007 ) /* XYZM */
-                    {
-                        eGeomType = wkbSetZ(wkbFlatten(nGeomType));
-                        bHasM = TRUE;
-                    }
+                        eGeomType = wkbSetM(wkbSetZ(wkbFlatten(nGeomType)));
                 }
                 else
                 {
                     eGeomType = OGRFromOGCGeomType(papszRow[1]);
 
                     if( strcmp ( papszRow[2], "XYZ" ) == 0 ||
-                        strcmp ( papszRow[2], "XYZM" ) == 0 ||
                         strcmp ( papszRow[2], "3" ) == 0) // SpatiaLite's own 3D geometries
                         eGeomType = wkbSetZ(eGeomType);
-
-                    if( strcmp ( papszRow[2], "XYM" ) == 0 ||
-                        strcmp ( papszRow[2], "XYZM" ) == 0 ) // M coordinate declared
-                        bHasM = TRUE;
+                    else if( strcmp ( papszRow[2], "XYM" ) == 0 )
+                        eGeomType = wkbSetM(eGeomType);
+                    else if( strcmp ( papszRow[2], "XYZM" ) == 0 ) // M coordinate declared
+                        eGeomType = wkbSetM(wkbSetZ(eGeomType));
                 }
-                poGeomFieldDefn->bHasM = bHasM;
                 eGeomFormat = OSGF_SpatiaLite;
             }
             else
@@ -493,7 +477,7 @@ CPLErr OGRSQLiteTableLayer::EstablishFeatureDefn(const char* pszGeomCol)
     {
         // we need to test version required by Spatialite TRIGGERs
         // hColStmt = NULL;
-        const char *pszSQL = CPLSPrintf( "SELECT sql FROM sqlite_master WHERE type = 'trigger' AND tbl_name = '%s' AND sql LIKE '%%RTreeAlign%%'",
+        pszSQL = CPLSPrintf( "SELECT sql FROM sqlite_master WHERE type = 'trigger' AND tbl_name = '%s' AND sql LIKE '%%RTreeAlign%%'",
             pszEscapedTableName );
 
         int nRowTriggerCount, nColTriggerCount;
@@ -544,7 +528,7 @@ CPLErr OGRSQLiteTableLayer::EstablishFeatureDefn(const char* pszGeomCol)
                         OGRFieldDefn* poFieldDefn =  poFeatureDefn->GetFieldDefn(idx);
                         if( poFieldDefn->GetType() == OFTString &&
                             !EQUAL(pszDefault, "NULL") &&
-                            !EQUALN(pszDefault, "CURRENT_", strlen("CURRENT_")) &&
+                            !STARTS_WITH_CI(pszDefault, "CURRENT_") &&
                             pszDefault[0] != '(' &&
                             pszDefault[0] != '\'' &&
                             CPLGetValueType(pszDefault) == CPL_VALUE_STRING )
@@ -558,7 +542,7 @@ CPLErr OGRSQLiteTableLayer::EstablishFeatureDefn(const char* pszGeomCol)
                         }
                         else if( (poFieldDefn->GetType() == OFTDate || poFieldDefn->GetType() == OFTDateTime) &&
                              !EQUAL(pszDefault, "NULL") &&
-                             !EQUALN(pszDefault, "CURRENT_", strlen("CURRENT_")) &&
+                             !STARTS_WITH_CI(pszDefault, "CURRENT_") &&
                              pszDefault[0] != '(' &&
                              pszDefault[0] != '\'' &&
                              !(pszDefault[0] >= '0' && pszDefault[0] <= '9') &&
@@ -611,24 +595,24 @@ OGRErr OGRSQLiteTableLayer::RecomputeOrdinals()
     pszSQL = CPLSPrintf( "SELECT _rowid_, * FROM '%s' LIMIT 1",
                                      pszEscapedTableName );
 
-    rc = sqlite3_prepare( hDB, pszSQL, strlen(pszSQL), &hColStmt, NULL ); 
+    rc = sqlite3_prepare( hDB, pszSQL, -1, &hColStmt, NULL );
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to query table %s for column definitions : %s.",
                   pszTableName, sqlite3_errmsg(hDB) );
-        
-        return CE_Failure;
+
+        return OGRERR_FAILURE;
     }
 
     rc = sqlite3_step( hColStmt );
     if ( rc != SQLITE_DONE && rc != SQLITE_ROW )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "In Initialize(): sqlite3_step(%s):\n  %s", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "In Initialize(): sqlite3_step(%s):\n  %s",
                   pszSQL, sqlite3_errmsg(hDB) );
         sqlite3_finalize( hColStmt );
-        return CE_Failure;
+        return OGRERR_FAILURE;
     }
 
     int    nRawColumns = sqlite3_column_count( hColStmt );
@@ -714,7 +698,7 @@ OGRErr OGRSQLiteTableLayer::ResetStatement()
 {
     int rc;
     CPLString osSQL;
-    
+
     if( bDeferredCreation ) RunDeferredCreationIfNecessary();
 
     ClearStatement();
@@ -722,7 +706,7 @@ OGRErr OGRSQLiteTableLayer::ResetStatement()
     iNextShapeId = 0;
 
     osSQL.Printf( "SELECT _rowid_, * FROM '%s' %s",
-                    pszEscapedTableName, 
+                    pszEscapedTableName,
                     osWHERE.c_str() );
 
 
@@ -730,8 +714,7 @@ OGRErr OGRSQLiteTableLayer::ResetStatement()
 //    rc = sqlite3_prepare_v2( poDS->GetDB(), osSQL, osSQL.size(),
 //                  &hStmt, NULL );
 //#else
-    rc = sqlite3_prepare( poDS->GetDB(), osSQL, osSQL.size(),
-		          &hStmt, NULL );
+    rc = sqlite3_prepare( poDS->GetDB(), osSQL, -1, &hStmt, NULL );
 //#endif
 
     if( rc == SQLITE_OK )
@@ -740,8 +723,8 @@ OGRErr OGRSQLiteTableLayer::ResetStatement()
     }
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "In ResetStatement(): sqlite3_prepare(%s):\n  %s", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "In ResetStatement(): sqlite3_prepare(%s):\n  %s",
                   osSQL.c_str(), sqlite3_errmsg(poDS->GetDB()) );
         hStmt = NULL;
         return OGRERR_FAILURE;
@@ -800,17 +783,18 @@ OGRFeature *OGRSQLiteTableLayer::GetFeature( GIntBig nFeatureId )
     iNextShapeId = nFeatureId;
 
     osSQL.Printf( "SELECT _rowid_, * FROM '%s' WHERE \"%s\" = " CPL_FRMT_GIB,
-                  pszEscapedTableName, 
+                  pszEscapedTableName,
                   OGRSQLiteEscape(pszFIDColumn).c_str(), nFeatureId );
 
     CPLDebug( "OGR_SQLITE", "exec(%s)", osSQL.c_str() );
 
-    rc = sqlite3_prepare( poDS->GetDB(), osSQL, osSQL.size(), 
+    rc = sqlite3_prepare( poDS->GetDB(), osSQL,
+                          static_cast<int>(osSQL.size()),
                           &hStmt, NULL );
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "In GetFeature(): sqlite3_prepare(%s):\n  %s", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "In GetFeature(): sqlite3_prepare(%s):\n  %s",
                   osSQL.c_str(), sqlite3_errmsg(poDS->GetDB()) );
 
         return NULL;
@@ -998,7 +982,7 @@ void OGRSQLiteTableLayer::BuildWhere()
             osWHERE = "WHERE ";
             osWHERE += osQuery;
         }
-        else	
+        else
         {
             osWHERE += " AND (";
             osWHERE += osQuery;
@@ -1029,7 +1013,7 @@ int OGRSQLiteTableLayer::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCRandomRead) )
         return pszFIDColumn != NULL;
 
-    else if( EQUAL(pszCap,OLCSequentialWrite) 
+    else if( EQUAL(pszCap,OLCSequentialWrite)
              || EQUAL(pszCap,OLCRandomWrite) )
     {
         return poDS->GetUpdate();
@@ -1056,7 +1040,9 @@ int OGRSQLiteTableLayer::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCCurveGeometries) )
         return poDS->TestCapability(ODsCCurveGeometries);
 
-    else 
+    else if( EQUAL(pszCap,OLCMeasuredGeometries) )
+        return poDS->TestCapability(ODsCMeasuredGeometries);
+    else
         return OGRSQLiteLayer::TestCapability( pszCap );
 }
 
@@ -1114,7 +1100,7 @@ GIntBig OGRSQLiteTableLayer::GetFeatureCount( int bForce )
     int nRowCount, nColCount;
     GIntBig nResult = -1;
 
-    if( sqlite3_get_table( poDS->GetDB(), pszSQL, &papszResult, 
+    if( sqlite3_get_table( poDS->GetDB(), pszSQL, &papszResult,
                            &nRowCount, &nColCount, &pszErrMsg ) != SQLITE_OK )
         return -1;
 
@@ -1171,7 +1157,7 @@ OGRErr OGRSQLiteTableLayer::GetExtent(int iGeomField, OGREnvelope *psExtent, int
     }
 
     if (CheckSpatialIndexTable(iGeomField) &&
-        !CSLTestBoolean(CPLGetConfigOption("OGR_SQLITE_EXACT_EXTENT", "NO")))
+        !CPLTestBool(CPLGetConfigOption("OGR_SQLITE_EXACT_EXTENT", "NO")))
     {
         const char* pszSQL;
 
@@ -1242,9 +1228,9 @@ CPLString OGRSQLiteFieldDefnToSQliteFieldDefn( OGRFieldDefn* poFieldDefn,
     switch( poFieldDefn->GetType() )
     {
         case OFTInteger:
-            if (poFieldDefn->GetSubType() == OFSTBoolean) 
+            if (poFieldDefn->GetSubType() == OFSTBoolean)
                 return "INTEGER_BOOLEAN";
-            else if (poFieldDefn->GetSubType() == OFSTInt16 ) 
+            else if (poFieldDefn->GetSubType() == OFSTInt16 )
                 return "INTEGER_INT16";
             else
                 return "INTEGER";
@@ -1252,7 +1238,7 @@ CPLString OGRSQLiteFieldDefnToSQliteFieldDefn( OGRFieldDefn* poFieldDefn,
         case OFTInteger64:
             return "BIGINT";
         case OFTReal:
-            if (bSQLiteDialectInternalUse && poFieldDefn->GetSubType() == OFSTFloat32) 
+            if (bSQLiteDialectInternalUse && poFieldDefn->GetSubType() == OFSTFloat32)
                 return "FLOAT_FLOAT32";
             else
                 return "FLOAT";
@@ -1330,7 +1316,7 @@ OGRErr OGRSQLiteTableLayer::CreateField( OGRFieldDefn *poFieldIn,
                   "CreateField");
         return OGRERR_FAILURE;
     }
-    
+
     if( pszFIDColumn != NULL &&
         EQUAL( oField.GetNameRef(), pszFIDColumn ) &&
         oField.GetType() != OFTInteger &&
@@ -1338,11 +1324,11 @@ OGRErr OGRSQLiteTableLayer::CreateField( OGRFieldDefn *poFieldIn,
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Wrong field type for %s",
                  oField.GetNameRef());
-        return CE_Failure;
+        return OGRERR_FAILURE;
     }
 
     ClearInsertStmt();
-    
+
     if( poDS->IsSpatialiteDB() && EQUAL( oField.GetNameRef(), "ROWID") )
     {
         CPLError(CE_Warning, CPLE_AppDefined,
@@ -1366,7 +1352,7 @@ OGRErr OGRSQLiteTableLayer::CreateField( OGRFieldDefn *poFieldIn,
 
     if( (oField.GetType() == OFTTime || oField.GetType() == OFTDate ||
          oField.GetType() == OFTDateTime) &&
-        !(CSLTestBoolean(
+        !(CPLTestBool(
             CPLGetConfigOption("OGR_SQLITE_ENABLE_DATETIME", "YES"))) )
     {
         oField.SetType(OFTString);
@@ -1374,8 +1360,8 @@ OGRErr OGRSQLiteTableLayer::CreateField( OGRFieldDefn *poFieldIn,
 
     if( !bDeferredCreation )
     {
-        /* ADD COLUMN only avaliable since sqlite 3.1.3 */
-        if (CSLTestBoolean(CPLGetConfigOption("OGR_SQLITE_USE_ADD_COLUMN", "YES")) &&
+        /* ADD COLUMN only available since SQLite 3.1.3 */
+        if (CPLTestBool(CPLGetConfigOption("OGR_SQLITE_USE_ADD_COLUMN", "YES")) &&
             sqlite3_libversion_number() > 3 * 1000000 + 1 * 1000 + 3)
         {
             int rc;
@@ -1415,7 +1401,7 @@ OGRErr OGRSQLiteTableLayer::CreateField( OGRFieldDefn *poFieldIn,
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
                         "Failed to add field %s to table %s:\n %s",
-                        oField.GetNameRef(), poFeatureDefn->GetName(), 
+                        oField.GetNameRef(), poFeatureDefn->GetName(),
                         pszErrMsg );
                 sqlite3_free( pszErrMsg );
                 return OGRERR_FAILURE;
@@ -1460,7 +1446,7 @@ OGRErr OGRSQLiteTableLayer::CreateGeomField( OGRGeomFieldDefn *poGeomFieldIn,
                  "Cannot create geometry field of type wkbNone");
         return OGRERR_FAILURE;
     }
-    
+
     OGRSQLiteGeomFieldDefn *poGeomField =
         new OGRSQLiteGeomFieldDefn( poGeomFieldIn->GetNameRef(), -1 );
     if( EQUAL(poGeomField->GetNameRef(), "") )
@@ -1546,12 +1532,12 @@ OGRErr OGRSQLiteTableLayer::RunAddGeometryColumn( OGRSQLiteGeomFieldDefn *poGeom
                                pszEscapedTableName );
         if( poGeomFieldDefn->eGeomFormat == OSGF_WKT )
         {
-            osCommand += CPLSPrintf(" '%s' VARCHAR", 
+            osCommand += CPLSPrintf(" '%s' VARCHAR",
                 OGRSQLiteEscape(poGeomFieldDefn->GetNameRef()).c_str() );
         }
         else
         {
-            osCommand += CPLSPrintf(" '%s' BLOB", 
+            osCommand += CPLSPrintf(" '%s' BLOB",
                 OGRSQLiteEscape(poGeomFieldDefn->GetNameRef()).c_str() );
         }
         if( !poGeomFieldDefn->IsNullable() )
@@ -1564,7 +1550,7 @@ OGRErr OGRSQLiteTableLayer::RunAddGeometryColumn( OGRSQLiteGeomFieldDefn *poGeom
         int rc = sqlite3_exec( poDS->GetDB(), osCommand, NULL, NULL, &pszErrMsg );
         if( rc != SQLITE_OK )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Unable to geometry field:\n%s",
                       pszErrMsg );
             sqlite3_free( pszErrMsg );
@@ -1592,17 +1578,24 @@ OGRErr OGRSQLiteTableLayer::RunAddGeometryColumn( OGRSQLiteGeomFieldDefn *poGeom
         / is found we'll unconditionally activate 2D casting mode
         */
         int iSpatialiteVersion = poDS->GetSpatialiteVersionNumber();
+        const char* pszCoordDim = "2";
         if ( iSpatialiteVersion < 24 && nCoordDim == 3 )
         {
             CPLDebug("SQLITE", "Spatialite < 2.4.0 --> 2.5D geometry not supported. Casting to 2D");
-            nCoordDim = 2;
         }
-
+        else if( OGR_GT_HasM( eType ) )
+        {
+            pszCoordDim = ( OGR_GT_HasZ( eType ) ) ? "'XYZM'" : "'XYM'";
+        }
+        else if( OGR_GT_HasZ( eType ) )
+        {
+            pszCoordDim = "3";
+        }
         osCommand.Printf( "SELECT AddGeometryColumn("
-                        "'%s', '%s', %d, '%s', %d",
+                        "'%s', '%s', %d, '%s', %s",
                         pszEscapedTableName,
                         OGRSQLiteEscape(pszGeomCol).c_str(), nSRSId,
-                        pszType, nCoordDim );
+                        pszType, pszCoordDim );
         if( iSpatialiteVersion >= 30 && !poGeomFieldDefn->IsNullable() )
             osCommand += ", 1";
         osCommand += ")";
@@ -1620,7 +1613,7 @@ OGRErr OGRSQLiteTableLayer::RunAddGeometryColumn( OGRSQLiteGeomFieldDefn *poGeom
                 "INSERT INTO geometry_columns "
                 "(f_table_name, f_geometry_column, geometry_format, "
                 "geometry_type, coord_dimension, srid) VALUES "
-                "('%s','%s','%s', %d, %d, %d)", 
+                "('%s','%s','%s', %d, %d, %d)",
                 pszEscapedTableName,
                 OGRSQLiteEscape(pszGeomCol).c_str(), pszGeomFormat,
                 (int) wkbFlatten(eType), nCoordDim, nSRSId );
@@ -1645,13 +1638,13 @@ OGRErr OGRSQLiteTableLayer::RunAddGeometryColumn( OGRSQLiteGeomFieldDefn *poGeom
     int rc = sqlite3_exec( poDS->GetDB(), osCommand, NULL, NULL, &pszErrMsg );
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to geometry field:\n%s",
                   pszErrMsg );
         sqlite3_free( pszErrMsg );
         return OGRERR_FAILURE;
     }
-    
+
     return OGRERR_NONE;
 }
 
@@ -1661,9 +1654,11 @@ OGRErr OGRSQLiteTableLayer::RunAddGeometryColumn( OGRSQLiteGeomFieldDefn *poGeom
 
 void OGRSQLiteTableLayer::InitFieldListForRecrerate(char* & pszNewFieldList,
                                                     char* & pszFieldListForSelect,
+                                                    size_t& nBufLenOut,
                                                     int nExtraSpace)
 {
-    int iField, nFieldListLen = 100 + 2 * nExtraSpace;
+    int iField;
+    size_t nFieldListLen = 100 + 2 * nExtraSpace;
 
     for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     {
@@ -1680,14 +1675,15 @@ void OGRSQLiteTableLayer::InitFieldListForRecrerate(char* & pszNewFieldList,
         nFieldListLen += 70 + 2 * strlen(poFeatureDefn->GetGeomFieldDefn(iField)->GetNameRef());
     }
 
+    nBufLenOut = nFieldListLen;
     pszFieldListForSelect = (char *) CPLCalloc(1,nFieldListLen);
     pszNewFieldList = (char *) CPLCalloc(1,nFieldListLen);
 
 /* -------------------------------------------------------------------- */
 /*      Build list of old fields, and the list of new fields.           */
 /* -------------------------------------------------------------------- */
-    sprintf( pszFieldListForSelect, "\"%s\"", pszFIDColumn ? OGRSQLiteEscapeName(pszFIDColumn).c_str() : "OGC_FID" );
-    sprintf( pszNewFieldList, "\"%s\" INTEGER PRIMARY KEY",pszFIDColumn ? OGRSQLiteEscapeName(pszFIDColumn).c_str() : "OGC_FID" );
+    snprintf( pszFieldListForSelect, nFieldListLen, "\"%s\"", pszFIDColumn ? OGRSQLiteEscapeName(pszFIDColumn).c_str() : "OGC_FID" );
+    snprintf( pszNewFieldList, nFieldListLen, "\"%s\" INTEGER PRIMARY KEY",pszFIDColumn ? OGRSQLiteEscapeName(pszFIDColumn).c_str() : "OGC_FID" );
 
     for( iField = 0; iField < poFeatureDefn->GetGeomFieldCount(); iField++ )
     {
@@ -1698,7 +1694,7 @@ void OGRSQLiteTableLayer::InitFieldListForRecrerate(char* & pszNewFieldList,
         strcat( pszFieldListForSelect, "\"");
         strcat( pszFieldListForSelect, OGRSQLiteEscapeName(poGeomFieldDefn->GetNameRef()) );
         strcat( pszFieldListForSelect, "\"");
-        
+
         strcat( pszNewFieldList, "\"");
         strcat( pszNewFieldList, OGRSQLiteEscapeName(poGeomFieldDefn->GetNameRef()) );
         strcat( pszNewFieldList, "\"");
@@ -1716,17 +1712,19 @@ void OGRSQLiteTableLayer::InitFieldListForRecrerate(char* & pszNewFieldList,
 /*                         AddColumnDef()                               */
 /************************************************************************/
 
-void OGRSQLiteTableLayer::AddColumnDef(char* pszNewFieldList,
+void OGRSQLiteTableLayer::AddColumnDef(char* pszNewFieldList, size_t nBufLen,
                                        OGRFieldDefn* poFldDefn)
 {
-    sprintf( pszNewFieldList+strlen(pszNewFieldList), 
+    snprintf( pszNewFieldList+strlen(pszNewFieldList), nBufLen-strlen(pszNewFieldList),
              ", '%s' %s", OGRSQLiteEscape(poFldDefn->GetNameRef()).c_str(),
              FieldDefnToSQliteFieldDefn(poFldDefn).c_str() );
     if( !poFldDefn->IsNullable() )
-        sprintf( pszNewFieldList+strlen(pszNewFieldList), " NOT NULL" );
+        snprintf( pszNewFieldList+strlen(pszNewFieldList),
+                 nBufLen-strlen(pszNewFieldList), " NOT NULL" );
     if( poFldDefn->GetDefault() != NULL && !poFldDefn->IsDefaultDriverSpecific() )
     {
-        sprintf( pszNewFieldList+strlen(pszNewFieldList), " DEFAULT %s",
+        snprintf( pszNewFieldList+strlen(pszNewFieldList),
+                 nBufLen-strlen(pszNewFieldList), " DEFAULT %s",
                  poFldDefn->GetDefault() );
     }
 }
@@ -1737,15 +1735,16 @@ void OGRSQLiteTableLayer::AddColumnDef(char* pszNewFieldList,
 
 OGRErr OGRSQLiteTableLayer::AddColumnAncientMethod( OGRFieldDefn& oField)
 {
-    
+
 /* -------------------------------------------------------------------- */
 /*      How much space do we need for the list of fields.               */
 /* -------------------------------------------------------------------- */
     int iField;
     char *pszOldFieldList, *pszNewFieldList;
+    size_t nBufLen = 0;
 
-    InitFieldListForRecrerate(pszNewFieldList, pszOldFieldList,
-                              strlen( oField.GetNameRef() ));
+    InitFieldListForRecrerate(pszNewFieldList, pszOldFieldList,nBufLen,
+                              static_cast<int>(strlen( oField.GetNameRef() )));
 
 /* -------------------------------------------------------------------- */
 /*      Build list of old fields, and the list of new fields.           */
@@ -1763,10 +1762,10 @@ OGRErr OGRSQLiteTableLayer::AddColumnAncientMethod( OGRFieldDefn& oField)
         if( EQUAL(poFldDefn->GetNameRef(),pszFIDColumn ? pszFIDColumn : "OGC_FID") )
             continue;
 
-        sprintf( pszOldFieldList+strlen(pszOldFieldList), 
+        snprintf( pszOldFieldList+strlen(pszOldFieldList), nBufLen-strlen(pszOldFieldList),
                  ", \"%s\"", OGRSQLiteEscapeName(poFldDefn->GetNameRef()).c_str() );
 
-        AddColumnDef(pszNewFieldList, poFldDefn);
+        AddColumnDef(pszNewFieldList, nBufLen, poFldDefn);
 
         iNextOrdinal++;
     }
@@ -1774,7 +1773,7 @@ OGRErr OGRSQLiteTableLayer::AddColumnAncientMethod( OGRFieldDefn& oField)
 /* -------------------------------------------------------------------- */
 /*      Add the new field.                                              */
 /* -------------------------------------------------------------------- */
-    AddColumnDef(pszNewFieldList, &oField);
+    AddColumnDef(pszNewFieldList, nBufLen, &oField);
 
 /* ==================================================================== */
 /*      Backup, destroy, recreate and repopulate the table.  SQLite     */
@@ -1800,7 +1799,7 @@ OGRErr OGRSQLiteTableLayer::AddColumnAncientMethod( OGRFieldDefn& oField)
 
     int nRowTriggerIndexCount, nColTriggerIndexCount;
     char **papszTriggerIndexResult = NULL;
-    rc = sqlite3_get_table( hDB, osSQL.c_str(), &papszTriggerIndexResult, 
+    rc = sqlite3_get_table( hDB, osSQL.c_str(), &papszTriggerIndexResult,
                             &nRowTriggerIndexCount, &nColTriggerIndexCount, &pszErrMsg );
 
 /* -------------------------------------------------------------------- */
@@ -1808,15 +1807,15 @@ OGRErr OGRSQLiteTableLayer::AddColumnAncientMethod( OGRFieldDefn& oField)
 /* -------------------------------------------------------------------- */
 
     if( rc == SQLITE_OK )
-        rc = sqlite3_exec( hDB, 
+        rc = sqlite3_exec( hDB,
                        CPLSPrintf( "CREATE TEMPORARY TABLE t1_back(%s)",
                                    pszOldFieldList ),
                        NULL, NULL, &pszErrMsg );
 
     if( rc == SQLITE_OK )
-        rc = sqlite3_exec( hDB, 
+        rc = sqlite3_exec( hDB,
                            CPLSPrintf( "INSERT INTO t1_back SELECT %s FROM '%s'",
-                                       pszOldFieldList, 
+                                       pszOldFieldList,
                                        pszEscapedTableName ),
                            NULL, NULL, &pszErrMsg );
 
@@ -1825,18 +1824,18 @@ OGRErr OGRSQLiteTableLayer::AddColumnAncientMethod( OGRFieldDefn& oField)
 /*      Drop the original table, and recreate with new field.           */
 /* -------------------------------------------------------------------- */
     if( rc == SQLITE_OK )
-        rc = sqlite3_exec( hDB, 
-                           CPLSPrintf( "DROP TABLE '%s'", 
+        rc = sqlite3_exec( hDB,
+                           CPLSPrintf( "DROP TABLE '%s'",
                                        pszEscapedTableName ),
                            NULL, NULL, &pszErrMsg );
 
     if( rc == SQLITE_OK )
     {
-        const char *pszCmd = 
-            CPLSPrintf( "CREATE TABLE '%s' (%s)", 
+        const char *pszCmd =
+            CPLSPrintf( "CREATE TABLE '%s' (%s)",
                         pszEscapedTableName,
                         pszNewFieldList );
-        rc = sqlite3_exec( hDB, pszCmd, 
+        rc = sqlite3_exec( hDB, pszCmd,
                            NULL, NULL, &pszErrMsg );
 
         CPLDebug( "OGR_SQLITE", "exec(%s)", pszCmd );
@@ -1845,9 +1844,9 @@ OGRErr OGRSQLiteTableLayer::AddColumnAncientMethod( OGRFieldDefn& oField)
 /* -------------------------------------------------------------------- */
 /*      Copy backup field values into new table.                        */
 /* -------------------------------------------------------------------- */
-    
+
     if( rc == SQLITE_OK )
-        rc = sqlite3_exec( hDB, 
+        rc = sqlite3_exec( hDB,
                            CPLSPrintf( "INSERT INTO '%s' SELECT %s, NULL FROM t1_back",
                                        pszEscapedTableName,
                                        pszOldFieldList ),
@@ -1859,9 +1858,9 @@ OGRErr OGRSQLiteTableLayer::AddColumnAncientMethod( OGRFieldDefn& oField)
 /* -------------------------------------------------------------------- */
 /*      Cleanup backup table.                                           */
 /* -------------------------------------------------------------------- */
-    
+
     if( rc == SQLITE_OK )
-        rc = sqlite3_exec( hDB, 
+        rc = sqlite3_exec( hDB,
                            CPLSPrintf( "DROP TABLE t1_back" ),
                            NULL, NULL, &pszErrMsg );
 
@@ -1876,14 +1875,14 @@ OGRErr OGRSQLiteTableLayer::AddColumnAncientMethod( OGRFieldDefn& oField)
         for(i = 1; i <= nRowTriggerIndexCount && nColTriggerIndexCount == 1 && rc == SQLITE_OK; i++)
         {
             if (papszTriggerIndexResult[i] != NULL && papszTriggerIndexResult[i][0] != '\0')
-                rc = sqlite3_exec( hDB, 
+                rc = sqlite3_exec( hDB,
                             papszTriggerIndexResult[i],
                             NULL, NULL, &pszErrMsg );
         }
     }
 
 /* -------------------------------------------------------------------- */
-/*      COMMIT on success or ROLLBACK on failuire.                      */
+/*      COMMIT on success or ROLLBACK on failure.                       */
 /* -------------------------------------------------------------------- */
 
     sqlite3_free_table( papszTriggerIndexResult );
@@ -1894,9 +1893,9 @@ OGRErr OGRSQLiteTableLayer::AddColumnAncientMethod( OGRFieldDefn& oField)
     }
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Failed to add field %s to table %s:\n %s",
-                  oField.GetNameRef(), poFeatureDefn->GetName(), 
+                  oField.GetNameRef(), poFeatureDefn->GetName(),
                   pszErrMsg );
         sqlite3_free( pszErrMsg );
 
@@ -1994,7 +1993,7 @@ OGRErr OGRSQLiteTableLayer::RecreateTable(const char* pszFieldListForSelect,
     }
 
 /* -------------------------------------------------------------------- */
-/*      COMMIT on success or ROLLBACK on failuire.                      */
+/*      COMMIT on success or ROLLBACK on failure.                       */
 /* -------------------------------------------------------------------- */
 
     sqlite3_free_table( papszTriggerIndexResult );
@@ -2050,7 +2049,9 @@ OGRErr OGRSQLiteTableLayer::DeleteField( int iFieldToDelete )
 /* -------------------------------------------------------------------- */
     int iField;
     char *pszNewFieldList, *pszFieldListForSelect;
-    InitFieldListForRecrerate(pszNewFieldList, pszFieldListForSelect);
+    size_t nBufLen = 0;
+
+    InitFieldListForRecrerate(pszNewFieldList, pszFieldListForSelect, nBufLen);
 
     for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     {
@@ -2059,10 +2060,11 @@ OGRErr OGRSQLiteTableLayer::DeleteField( int iFieldToDelete )
         if (iField == iFieldToDelete)
             continue;
 
-        sprintf( pszFieldListForSelect+strlen(pszFieldListForSelect),
+        snprintf( pszFieldListForSelect+strlen(pszFieldListForSelect),
+                  nBufLen-strlen(pszFieldListForSelect),
                  ", \"%s\"", OGRSQLiteEscapeName(poFldDefn->GetNameRef()).c_str() );
 
-        AddColumnDef(pszNewFieldList, poFldDefn);
+        AddColumnDef(pszNewFieldList, nBufLen, poFldDefn);
     }
 
 /* -------------------------------------------------------------------- */
@@ -2097,7 +2099,7 @@ OGRErr OGRSQLiteTableLayer::DeleteField( int iFieldToDelete )
 /*                           AlterFieldDefn()                           */
 /************************************************************************/
 
-OGRErr OGRSQLiteTableLayer::AlterFieldDefn( int iFieldToAlter, OGRFieldDefn* poNewFieldDefn, int nFlags )
+OGRErr OGRSQLiteTableLayer::AlterFieldDefn( int iFieldToAlter, OGRFieldDefn* poNewFieldDefn, int nFlagsIn )
 {
     if (HasLayerDefnError())
         return OGRERR_FAILURE;
@@ -2125,61 +2127,69 @@ OGRErr OGRSQLiteTableLayer::AlterFieldDefn( int iFieldToAlter, OGRFieldDefn* poN
 /* -------------------------------------------------------------------- */
     int iField;
     char *pszNewFieldList, *pszFieldListForSelect;
+    size_t nBufLen = 0;
+
     InitFieldListForRecrerate(pszNewFieldList, pszFieldListForSelect,
-                              strlen(poNewFieldDefn->GetNameRef()) +
+                              nBufLen,
+                              static_cast<int>(strlen(poNewFieldDefn->GetNameRef())) +
                               50 +
-                              (poNewFieldDefn->GetDefault() ? strlen(poNewFieldDefn->GetDefault()) : 0)
+                              (poNewFieldDefn->GetDefault() ? static_cast<int>(strlen(poNewFieldDefn->GetDefault())) : 0)
                               );
 
     for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     {
         OGRFieldDefn *poFldDefn = poFeatureDefn->GetFieldDefn(iField);
 
-        sprintf( pszFieldListForSelect+strlen(pszFieldListForSelect),
+        snprintf( pszFieldListForSelect+strlen(pszFieldListForSelect),
+                 nBufLen-strlen(pszFieldListForSelect),
                  ", \"%s\"", OGRSQLiteEscapeName(poFldDefn->GetNameRef()).c_str() );
 
         if (iField == iFieldToAlter)
         {
             OGRFieldDefn oTmpFieldDefn(poFldDefn);
-            if( (nFlags & ALTER_NAME_FLAG) )
+            if( (nFlagsIn & ALTER_NAME_FLAG) )
                 oTmpFieldDefn.SetName(poNewFieldDefn->GetNameRef());
-            if( (nFlags & ALTER_TYPE_FLAG) )
+            if( (nFlagsIn & ALTER_TYPE_FLAG) )
                 oTmpFieldDefn.SetType(poNewFieldDefn->GetType());
-            if (nFlags & ALTER_WIDTH_PRECISION_FLAG)
+            if (nFlagsIn & ALTER_WIDTH_PRECISION_FLAG)
             {
                 oTmpFieldDefn.SetWidth(poNewFieldDefn->GetWidth());
                 oTmpFieldDefn.SetPrecision(poNewFieldDefn->GetPrecision());
             }
-            if( (nFlags & ALTER_NULLABLE_FLAG) )
+            if( (nFlagsIn & ALTER_NULLABLE_FLAG) )
             {
                 oTmpFieldDefn.SetNullable(poNewFieldDefn->IsNullable());
             }
-            if( (nFlags & ALTER_DEFAULT_FLAG) )
+            if( (nFlagsIn & ALTER_DEFAULT_FLAG) )
             {
                 oTmpFieldDefn.SetDefault(poNewFieldDefn->GetDefault());
             }
 
-            sprintf( pszNewFieldList+strlen(pszNewFieldList),
+            snprintf( pszNewFieldList+strlen(pszNewFieldList),
+                      nBufLen-strlen(pszNewFieldList),
                     ", '%s' %s",
                     OGRSQLiteEscape(oTmpFieldDefn.GetNameRef()).c_str(),
                     FieldDefnToSQliteFieldDefn(&oTmpFieldDefn).c_str() );
-            if ( (nFlags & ALTER_NAME_FLAG) &&
+            if ( (nFlagsIn & ALTER_NAME_FLAG) &&
                  oTmpFieldDefn.GetType() == OFTString &&
                  CSLFindString(papszCompressedColumns, poFldDefn->GetNameRef()) >= 0 )
             {
-                sprintf( pszNewFieldList+strlen(pszNewFieldList), "_deflate");
+                snprintf( pszNewFieldList+strlen(pszNewFieldList),
+                         nBufLen-strlen(pszNewFieldList), "_deflate");
             }
             if( !oTmpFieldDefn.IsNullable() )
-                sprintf( pszNewFieldList+strlen(pszNewFieldList), " NOT NULL" );
+                snprintf( pszNewFieldList+strlen(pszNewFieldList),
+                          nBufLen-strlen(pszNewFieldList)," NOT NULL" );
             if( oTmpFieldDefn.GetDefault() )
             {
-                sprintf( pszNewFieldList+strlen(pszNewFieldList), " DEFAULT %s",
+                snprintf( pszNewFieldList+strlen(pszNewFieldList),
+                         nBufLen-strlen(pszNewFieldList)," DEFAULT %s",
                          oTmpFieldDefn.GetDefault());
             }
         }
         else
         {
-            AddColumnDef(pszNewFieldList, poFldDefn);
+            AddColumnDef(pszNewFieldList, nBufLen, poFldDefn);
         }
     }
 
@@ -2207,7 +2217,7 @@ OGRErr OGRSQLiteTableLayer::AlterFieldDefn( int iFieldToAlter, OGRFieldDefn* poN
 
     OGRFieldDefn* poFieldDefn = poFeatureDefn->GetFieldDefn(iFieldToAlter);
 
-    if (nFlags & ALTER_TYPE_FLAG)
+    if (nFlagsIn & ALTER_TYPE_FLAG)
     {
         int iIdx;
         if( poNewFieldDefn->GetType() != OFTString &&
@@ -2219,7 +2229,7 @@ OGRErr OGRSQLiteTableLayer::AlterFieldDefn( int iFieldToAlter, OGRFieldDefn* poN
         }
         poFieldDefn->SetType(poNewFieldDefn->GetType());
     }
-    if (nFlags & ALTER_NAME_FLAG)
+    if (nFlagsIn & ALTER_NAME_FLAG)
     {
         int iIdx;
         if( (iIdx = CSLFindString(papszCompressedColumns,
@@ -2231,14 +2241,14 @@ OGRErr OGRSQLiteTableLayer::AlterFieldDefn( int iFieldToAlter, OGRFieldDefn* poN
         }
         poFieldDefn->SetName(poNewFieldDefn->GetNameRef());
     }
-    if (nFlags & ALTER_WIDTH_PRECISION_FLAG)
+    if (nFlagsIn & ALTER_WIDTH_PRECISION_FLAG)
     {
         poFieldDefn->SetWidth(poNewFieldDefn->GetWidth());
         poFieldDefn->SetPrecision(poNewFieldDefn->GetPrecision());
     }
-    if (nFlags & ALTER_NULLABLE_FLAG)
+    if (nFlagsIn & ALTER_NULLABLE_FLAG)
         poFieldDefn->SetNullable(poNewFieldDefn->IsNullable());
-    if (nFlags & ALTER_DEFAULT_FLAG)
+    if (nFlagsIn & ALTER_DEFAULT_FLAG)
         poFieldDefn->SetDefault(poNewFieldDefn->GetDefault());
 
     return OGRERR_NONE;
@@ -2276,16 +2286,19 @@ OGRErr OGRSQLiteTableLayer::ReorderFields( int* panMap )
 /* -------------------------------------------------------------------- */
     int iField;
     char *pszNewFieldList, *pszFieldListForSelect;
-    InitFieldListForRecrerate(pszNewFieldList, pszFieldListForSelect);
+    size_t nBufLen;
+
+    InitFieldListForRecrerate(pszNewFieldList, pszFieldListForSelect, nBufLen);
 
     for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     {
         OGRFieldDefn *poFldDefn = poFeatureDefn->GetFieldDefn(panMap[iField]);
 
-        sprintf( pszFieldListForSelect+strlen(pszFieldListForSelect),
+        snprintf( pszFieldListForSelect+strlen(pszFieldListForSelect),
+                  nBufLen - strlen(pszFieldListForSelect),
                  ", \"%s\"", OGRSQLiteEscapeName(poFldDefn->GetNameRef()).c_str() );
 
-        AddColumnDef(pszNewFieldList, poFldDefn);
+        AddColumnDef(pszNewFieldList, nBufLen, poFldDefn);
     }
 
 /* -------------------------------------------------------------------- */
@@ -2324,7 +2337,7 @@ OGRErr OGRSQLiteTableLayer::ReorderFields( int* panMap )
 /* and to FALSE by CreateFeature() for INSERT statements; */
 
 OGRErr OGRSQLiteTableLayer::BindValues( OGRFeature *poFeature,
-                                        sqlite3_stmt* hStmt,
+                                        sqlite3_stmt* hStmtIn,
                                         int bBindNullValues )
 {
     int rc;
@@ -2350,7 +2363,7 @@ OGRErr OGRSQLiteTableLayer::BindValues( OGRFeature *poFeature,
             {
                 char *pszWKT = NULL;
                 poGeom->exportToWkt( &pszWKT );
-                rc = sqlite3_bind_text( hStmt, nBindField++, pszWKT, -1, CPLFree );
+                rc = sqlite3_bind_text( hStmtIn, nBindField++, pszWKT, -1, CPLFree );
             }
             else if( eGeomFormat == OSGF_WKB )
             {
@@ -2358,7 +2371,7 @@ OGRErr OGRSQLiteTableLayer::BindValues( OGRFeature *poFeature,
                 GByte *pabyWKB = (GByte *) CPLMalloc(nWKBLen + 1);
 
                 poGeom->exportToWkb( wkbNDR, pabyWKB );
-                rc = sqlite3_bind_blob( hStmt, nBindField++, pabyWKB, nWKBLen, CPLFree );
+                rc = sqlite3_bind_blob( hStmtIn, nBindField++, pabyWKB, nWKBLen, CPLFree );
             }
             else if ( eGeomFormat == OSGF_SpatiaLite )
             {
@@ -2366,22 +2379,22 @@ OGRErr OGRSQLiteTableLayer::BindValues( OGRFeature *poFeature,
                 GByte   *pabySLBLOB;
 
                 int nSRSId = poGeomFieldDefn->nSRSId;
-                int bHasM = poGeomFieldDefn->bHasM;
-                ExportSpatiaLiteGeometry( poGeom, nSRSId, wkbNDR, bHasM,
-                                        bSpatialite2D, bUseComprGeom, &pabySLBLOB, &nBLOBLen );
-                rc = sqlite3_bind_blob( hStmt, nBindField++, pabySLBLOB,
+                CPL_IGNORE_RET_VAL(ExportSpatiaLiteGeometry( poGeom, nSRSId, wkbNDR,
+                                        bSpatialite2D, bUseComprGeom, &pabySLBLOB, &nBLOBLen ));
+                rc = sqlite3_bind_blob( hStmtIn, nBindField++, pabySLBLOB,
                                         nBLOBLen, CPLFree );
             }
             else
             {
                 rc = SQLITE_OK;
+                CPL_IGNORE_RET_VAL(rc);
                 CPLAssert(0);
             }
         }
         else
         {
             if (bBindNullValues)
-                rc = sqlite3_bind_null( hStmt, nBindField++ );
+                rc = sqlite3_bind_null( hStmtIn, nBindField++ );
             else
                 rc = SQLITE_OK;
         }
@@ -2408,7 +2421,7 @@ OGRErr OGRSQLiteTableLayer::BindValues( OGRFeature *poFeature,
         if( !poFeature->IsFieldSet( iField ) )
         {
             if (bBindNullValues)
-                rc = sqlite3_bind_null( hStmt, nBindField++ );
+                rc = sqlite3_bind_null( hStmtIn, nBindField++ );
             else
                 rc = SQLITE_OK;
         }
@@ -2420,21 +2433,21 @@ OGRErr OGRSQLiteTableLayer::BindValues( OGRFeature *poFeature,
                 case OFTInteger:
                 {
                     int nFieldVal = poFeature->GetFieldAsInteger( iField );
-                    rc = sqlite3_bind_int(hStmt, nBindField++, nFieldVal);
+                    rc = sqlite3_bind_int(hStmtIn, nBindField++, nFieldVal);
                     break;
                 }
-                
+
                 case OFTInteger64:
                 {
                     GIntBig nFieldVal = poFeature->GetFieldAsInteger64( iField );
-                    rc = sqlite3_bind_int64(hStmt, nBindField++, nFieldVal);
+                    rc = sqlite3_bind_int64(hStmtIn, nBindField++, nFieldVal);
                     break;
                 }
 
                 case OFTReal:
                 {
                     double dfFieldVal = poFeature->GetFieldAsDouble( iField );
-                    rc = sqlite3_bind_double(hStmt, nBindField++, dfFieldVal);
+                    rc = sqlite3_bind_double(hStmtIn, nBindField++, dfFieldVal);
                     break;
                 }
 
@@ -2443,7 +2456,7 @@ OGRErr OGRSQLiteTableLayer::BindValues( OGRFeature *poFeature,
                     int nDataLength = 0;
                     GByte* pabyData =
                         poFeature->GetFieldAsBinary( iField, &nDataLength );
-                    rc = sqlite3_bind_blob(hStmt, nBindField++,
+                    rc = sqlite3_bind_blob(hStmtIn, nBindField++,
                                         pabyData, nDataLength, SQLITE_TRANSIENT);
                     break;
                 }
@@ -2451,7 +2464,7 @@ OGRErr OGRSQLiteTableLayer::BindValues( OGRFeature *poFeature,
                 case OFTDateTime:
                 {
                     char* pszStr = OGRGetXMLDateTime(poFeature->GetRawFieldRef(iField));
-                    rc = sqlite3_bind_text(hStmt, nBindField++,
+                    rc = sqlite3_bind_text(hStmtIn, nBindField++,
                                            pszStr, -1, SQLITE_TRANSIENT);
                     CPLFree(pszStr);
                     break;
@@ -2463,8 +2476,8 @@ OGRErr OGRSQLiteTableLayer::BindValues( OGRFeature *poFeature,
                     poFeature->GetFieldAsDateTime(iField, &nYear, &nMonth, &nDay,
                                                 &nHour, &nMinute, &nSecond, &nTZ);
                     char szBuffer[64];
-                    sprintf(szBuffer, "%04d-%02d-%02d", nYear, nMonth, nDay);
-                    rc = sqlite3_bind_text(hStmt, nBindField++,
+                    snprintf(szBuffer, sizeof(szBuffer), "%04d-%02d-%02d", nYear, nMonth, nDay);
+                    rc = sqlite3_bind_text(hStmtIn, nBindField++,
                                            szBuffer, -1, SQLITE_TRANSIENT);
                     break;
                 }
@@ -2477,10 +2490,10 @@ OGRErr OGRSQLiteTableLayer::BindValues( OGRFeature *poFeature,
                                                 &nHour, &nMinute, &fSecond, &nTZ );
                     char szBuffer[64];
                     if( OGR_GET_MS(fSecond) != 0 )
-                        sprintf(szBuffer, "%02d:%02d:%06.3f", nHour, nMinute, fSecond);
+                        snprintf(szBuffer, sizeof(szBuffer), "%02d:%02d:%06.3f", nHour, nMinute, fSecond);
                     else
-                        sprintf(szBuffer, "%02d:%02d:%02d", nHour, nMinute, (int)fSecond);
-                    rc = sqlite3_bind_text(hStmt, nBindField++,
+                        snprintf(szBuffer, sizeof(szBuffer), "%02d:%02d:%02d", nHour, nMinute, (int)fSecond);
+                    rc = sqlite3_bind_text(hStmtIn, nBindField++,
                                            szBuffer, -1, SQLITE_TRANSIENT);
                     break;
                 }
@@ -2497,7 +2510,7 @@ OGRErr OGRSQLiteTableLayer::BindValues( OGRFeature *poFeature,
                         osValue += papszValues[i];
                     }
                     osValue += ")";
-                    rc = sqlite3_bind_text(hStmt, nBindField++,
+                    rc = sqlite3_bind_text(hStmtIn, nBindField++,
                                                osValue.c_str(), -1, SQLITE_TRANSIENT);
                     break;
                 }
@@ -2515,9 +2528,9 @@ OGRErr OGRSQLiteTableLayer::BindValues( OGRFeature *poFeature,
                                                      &nBytesOut );
                         if( pOut != NULL )
                         {
-                            rc = sqlite3_bind_blob(hStmt, nBindField++,
+                            rc = sqlite3_bind_blob(hStmtIn, nBindField++,
                                                    pOut,
-                                                   nBytesOut,
+                                                   static_cast<int>(nBytesOut),
                                                    CPLFree);
                         }
                         else
@@ -2525,7 +2538,7 @@ OGRErr OGRSQLiteTableLayer::BindValues( OGRFeature *poFeature,
                     }
                     else
                     {
-                        rc = sqlite3_bind_text(hStmt, nBindField++,
+                        rc = sqlite3_bind_text(hStmtIn, nBindField++,
                                                pszRawValue, -1, SQLITE_TRANSIENT);
                     }
                     break;
@@ -2558,14 +2571,14 @@ OGRErr OGRSQLiteTableLayer::ISetFeature( OGRFeature *poFeature )
 
     if( pszFIDColumn == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "SetFeature() without any FID column." );
         return OGRERR_FAILURE;
     }
-    
+
     if( poFeature->GetFID() == OGRNullFID )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "SetFeature() with unset FID fails." );
         return OGRERR_FAILURE;
     }
@@ -2586,7 +2599,7 @@ OGRErr OGRSQLiteTableLayer::ISetFeature( OGRFeature *poFeature )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
                         "Inconsistent values of FID and field of same name");
-            return CE_Failure;
+            return OGRERR_FAILURE;
         }
     }
 
@@ -2704,7 +2717,7 @@ OGRErr OGRSQLiteTableLayer::ISetFeature( OGRFeature *poFeature )
         nFieldCount = poFeatureDefn->GetGeomFieldCount();
         for( iField = 0; iField < nFieldCount; iField++ )
         {
-            OGRSQLiteGeomFieldDefn* poGeomFieldDefn = 
+            OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
                 poFeatureDefn->myGetGeomFieldDefn(iField);
             OGRGeometry *poGeom = poFeature->GetGeomFieldRef(iField);
             if( poGeomFieldDefn->bCachedExtentIsValid &&
@@ -2800,8 +2813,7 @@ OGRErr OGRSQLiteTableLayer::ICreateFeature( OGRFeature *poFeature )
         {
             OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
                                         poFeatureDefn->myGetGeomFieldDefn(j);
-            if( !((bDeferredSpatialIndexCreation || !poGeomFieldDefn->bHasSpatialIndex) &&
-                  !poGeomFieldDefn->bHasM) )
+            if( !((bDeferredSpatialIndexCreation || !poGeomFieldDefn->bHasSpatialIndex)) )
                 continue;
             const char* pszGeomCol = poGeomFieldDefn->GetNameRef();
 
@@ -2812,8 +2824,8 @@ OGRErr OGRSQLiteTableLayer::ICreateFeature( OGRFeature *poFeature )
                 if( pszTriggerName!= NULL && pszTriggerSQL != NULL &&
                     CPLString(pszTriggerName).tolower().find(CPLString(pszGeomCol).tolower()) != std::string::npos )
                 {
-                    const char* pszExpectedTrigger = 0;
-                    if( strncmp(pszTriggerName, "ggi_", 4) == 0 )
+                    const char* pszExpectedTrigger = NULL;
+                    if( STARTS_WITH(pszTriggerName, "ggi_") )
                     {
                         pszExpectedTrigger = CPLSPrintf(
                         "CREATE TRIGGER \"ggi_%s_%s\" BEFORE INSERT ON \"%s\" "
@@ -2828,7 +2840,7 @@ OGRErr OGRSQLiteTableLayer::ICreateFeature( OGRFeature *poFeature )
                         pszTableName, pszGeomCol,
                         pszGeomCol);
                     }
-                    else if( strncmp(pszTriggerName, "tmi_", 4) == 0 )
+                    else if( STARTS_WITH(pszTriggerName, "tmi_") )
                     {
                         pszExpectedTrigger = CPLSPrintf(
                         "CREATE TRIGGER \"tmi_%s_%s\" AFTER INSERT ON \"%s\" "
@@ -2843,7 +2855,7 @@ OGRErr OGRSQLiteTableLayer::ICreateFeature( OGRFeature *poFeature )
                     /* that check there's no spatial index active */
                     /* A further potential optimization would be to rebuild the spatial index */
                     /* afterwards... */
-                    /*else if( strncmp(pszTriggerName, "gii_", 4) == 0 )
+                    /*else if( STARTS_WITH(pszTriggerName, "gii_") )
                     {
                         pszExpectedTrigger = CPLSPrintf(
                         "CREATE TRIGGER \"gii_%s_%s\" AFTER INSERT ON \"%s\" "
@@ -2859,7 +2871,7 @@ OGRErr OGRSQLiteTableLayer::ICreateFeature( OGRFeature *poFeature )
                         pszTableName, pszGeomCol, pszGeomCol);
                     }*/
 
-                    if( AreTriggersSimilar(pszExpectedTrigger, pszTriggerSQL) )
+                    if( pszExpectedTrigger != NULL && AreTriggersSimilar(pszExpectedTrigger, pszTriggerSQL) )
                     {
                         // And drop them
                         pszSQL3 = sqlite3_mprintf("DROP TRIGGER %s", pszTriggerName);
@@ -2947,7 +2959,7 @@ OGRErr OGRSQLiteTableLayer::ICreateFeature( OGRFeature *poFeature )
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
                             "Inconsistent values of FID and field of same name");
-                return CE_Failure;
+                return OGRERR_FAILURE;
             }
         }
     }
@@ -3090,8 +3102,8 @@ OGRErr OGRSQLiteTableLayer::ICreateFeature( OGRFeature *poFeature )
 
     if( rc != SQLITE_OK && rc != SQLITE_DONE )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "sqlite3_step() failed:\n  %s (%d)", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "sqlite3_step() failed:\n  %s (%d)",
                   sqlite3_errmsg(hDB), rc );
         sqlite3_reset( hInsertStmt );
         ClearInsertStmt();
@@ -3110,17 +3122,17 @@ OGRErr OGRSQLiteTableLayer::ICreateFeature( OGRFeature *poFeature )
     }
 
     sqlite3_reset( hInsertStmt );
-    
+
     if( bTemporaryStatement )
         ClearInsertStmt();
 
     nFieldCount = poFeatureDefn->GetGeomFieldCount();
     for( iField = 0; iField < nFieldCount; iField++ )
     {
-        OGRSQLiteGeomFieldDefn* poGeomFieldDefn = 
+        OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
             poFeatureDefn->myGetGeomFieldDefn(iField);
         OGRGeometry *poGeom = poFeature->GetGeomFieldRef(iField);
-        
+
         if( (poGeomFieldDefn->bCachedExtentIsValid || nFeatureCount == 0) &&
             poGeom != NULL && !poGeom->IsEmpty() )
         {
@@ -3197,7 +3209,7 @@ OGRErr OGRSQLiteTableLayer::DeleteFeature( GIntBig nFID )
         int nFieldCount = poFeatureDefn->GetGeomFieldCount();
         for( int iField = 0; iField < nFieldCount; iField++ )
         {
-            OGRSQLiteGeomFieldDefn* poGeomFieldDefn = 
+            OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
                 poFeatureDefn->myGetGeomFieldDefn(iField);
             poGeomFieldDefn->bCachedExtentIsValid = FALSE;
         }
@@ -3259,8 +3271,8 @@ OGRErr OGRSQLiteTableLayer::RunDeferredCreationIfNecessary()
     int rc;
     char *pszErrMsg;
     CPLString osCommand;
-    
-    osCommand.Printf( "CREATE TABLE '%s' ( %s INTEGER PRIMARY KEY", 
+
+    osCommand.Printf( "CREATE TABLE '%s' ( %s INTEGER PRIMARY KEY",
                       pszEscapedTableName,
                       pszFIDColumn );
 
@@ -3274,12 +3286,12 @@ OGRErr OGRSQLiteTableLayer::RunDeferredCreationIfNecessary()
 
             if( poGeomFieldDefn->eGeomFormat == OSGF_WKT )
             {
-                osCommand += CPLSPrintf(", '%s' VARCHAR", 
+                osCommand += CPLSPrintf(", '%s' VARCHAR",
                     OGRSQLiteEscape(poGeomFieldDefn->GetNameRef()).c_str() );
             }
             else
             {
-                osCommand += CPLSPrintf(", '%s' BLOB", 
+                osCommand += CPLSPrintf(", '%s' BLOB",
                     OGRSQLiteEscape(poGeomFieldDefn->GetNameRef()).c_str() );
             }
             if( !poGeomFieldDefn->IsNullable() )
@@ -3306,8 +3318,8 @@ OGRErr OGRSQLiteTableLayer::RunDeferredCreationIfNecessary()
         if( pszDefault != NULL &&
             (!poFieldDefn->IsDefaultDriverSpecific() ||
              (pszDefault[0] == '(' && pszDefault[strlen(pszDefault)-1] == ')' &&
-             (EQUALN(pszDefault+1, "strftime", strlen("strftime")) ||
-              EQUALN(pszDefault+1, " strftime", strlen(" strftime"))))) )
+             (STARTS_WITH_CI(pszDefault+1, "strftime") ||
+              STARTS_WITH_CI(pszDefault+1, " strftime")))) )
         {
             osCommand += " DEFAULT ";
             osCommand += poFieldDefn->GetDefault();
@@ -3322,7 +3334,7 @@ OGRErr OGRSQLiteTableLayer::RunDeferredCreationIfNecessary()
     rc = sqlite3_exec( poDS->GetDB(), osCommand, NULL, NULL, &pszErrMsg );
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to create table %s: %s",
                   pszLayerName, pszErrMsg );
         sqlite3_free( pszErrMsg );
@@ -3341,7 +3353,7 @@ OGRErr OGRSQLiteTableLayer::RunDeferredCreationIfNecessary()
         * an effort to clean out such cruft.
         */
         osCommand.Printf(
-            "DELETE FROM geometry_columns WHERE f_table_name = '%s'", 
+            "DELETE FROM geometry_columns WHERE f_table_name = '%s'",
             pszEscapedTableName );
 
 #ifdef DEBUG
@@ -3351,8 +3363,11 @@ OGRErr OGRSQLiteTableLayer::RunDeferredCreationIfNecessary()
         rc = sqlite3_exec( poDS->GetDB(), osCommand, NULL, NULL, &pszErrMsg );
         if( rc != SQLITE_OK )
         {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                  "Unable to run %s: %s",
+                  osCommand.c_str(), pszErrMsg );
             sqlite3_free( pszErrMsg );
-            return FALSE;
+            return OGRERR_FAILURE;
         }
 
         for(i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
@@ -3369,7 +3384,15 @@ OGRErr OGRSQLiteTableLayer::RunDeferredCreationIfNecessary()
     if( poDS->IsSpatialiteDB() && poDS->GetLayerCount() == 1)
     {
         /* To create the layer_statistics and spatialite_history tables */
-        sqlite3_exec( poDS->GetDB(), "SELECT UpdateLayerStatistics()", NULL, NULL, NULL );
+        rc = sqlite3_exec( poDS->GetDB(), "SELECT UpdateLayerStatistics()", NULL, NULL, &pszErrMsg );
+        if( rc != SQLITE_OK )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                  "Unable to run %s: %s",
+                  osCommand.c_str(), pszErrMsg );
+            sqlite3_free( pszErrMsg );
+            return OGRERR_FAILURE;
+        }
     }
 
     return OGRERR_NONE;
@@ -3384,8 +3407,8 @@ int OGRSQLiteTableLayer::HasSpatialIndex(int iGeomCol)
     GetLayerDefn();
     if( iGeomCol < 0 || iGeomCol >= poFeatureDefn->GetGeomFieldCount() )
         return FALSE;
-    OGRSQLiteGeomFieldDefn* poGeomFieldDefn = poFeatureDefn->myGetGeomFieldDefn(iGeomCol);    
-    
+    OGRSQLiteGeomFieldDefn* poGeomFieldDefn = poFeatureDefn->myGetGeomFieldDefn(iGeomCol);
+
     CreateSpatialIndexIfNecessary();
 
     return poGeomFieldDefn->bHasSpatialIndex;
@@ -3456,8 +3479,11 @@ void OGRSQLiteTableLayer::LoadStatisticsSpatialite4DB()
         CPLString osSQL;
         CPLString osLastEvtDate;
         osSQL.Printf("SELECT MAX(last_insert, last_update, last_delete) FROM geometry_columns_time WHERE "
-                    "f_table_name = '%s' AND f_geometry_column = '%s'",
-                    pszEscapedTableName, OGRSQLiteEscape(pszGeomCol).c_str());
+                    "(f_table_name = '%s' AND f_geometry_column = '%s')"
+#ifdef WORKAROUND_SQLITE3_BUGS
+                    " OR 0"
+#endif
+                    ,pszEscapedTableName, OGRSQLiteEscape(pszGeomCol).c_str());
 
         sqlite3 *hDB = poDS->GetDB();
         int nRowCount = 0, nColCount = 0;
@@ -3484,8 +3510,11 @@ void OGRSQLiteTableLayer::LoadStatisticsSpatialite4DB()
 
         osSQL.Printf("SELECT last_verified, row_count, extent_min_x, extent_min_y, "
                     "extent_max_x, extent_max_y FROM geometry_columns_statistics WHERE "
-                    "f_table_name = '%s' AND f_geometry_column = '%s'",
-                    pszEscapedTableName, OGRSQLiteEscape(pszGeomCol).c_str());
+                    "(f_table_name = '%s' AND f_geometry_column = '%s')"
+#ifdef WORKAROUND_SQLITE3_BUGS
+                    " OR 0"
+#endif
+                    ,pszEscapedTableName, OGRSQLiteEscape(pszGeomCol).c_str());
 
         nRowCount = 0;
         nColCount = 0;
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitevfs.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitevfs.cpp
index 5089e21..bcc2c47 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitevfs.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitevfs.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqlitevfs.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogrsqlitevfs.cpp 33410 2016-02-10 14:12:43Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements SQLite VFS
@@ -30,7 +30,7 @@
 #include "cpl_atomic_ops.h"
 #include "ogr_sqlite.h"
 
-CPL_CVSID("$Id: ogrsqlitevfs.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogrsqlitevfs.cpp 33410 2016-02-10 14:12:43Z rouault $");
 
 #ifdef DEBUG_IO
 # define DEBUG_ONLY
@@ -209,7 +209,17 @@ static const sqlite3_io_methods OGRSQLiteIOMethods =
     OGRSQLiteIOCheckReservedLock,
     OGRSQLiteIOFileControl,
     OGRSQLiteIOSectorSize,
-    OGRSQLiteIODeviceCharacteristics
+    OGRSQLiteIODeviceCharacteristics,
+#if SQLITE_VERSION_NUMBER >= 3007004L /* perhaps older too ? */
+    NULL,  // xShmMap
+    NULL,  // xShmLock
+    NULL,  // xShmBarrier
+    NULL,  // xShmUnmap
+#if SQLITE_VERSION_NUMBER >= 3008002L /* perhaps older too ? */
+    NULL,  // xFetch
+    NULL,  // xUnfetch
+#endif
+#endif
 };
 
 static int OGRSQLiteVFSOpen(sqlite3_vfs* pVFS,
@@ -289,7 +299,7 @@ static int OGRSQLiteVFSAccess (DEBUG_ONLY sqlite3_vfs* pVFS,
     if (flags == SQLITE_ACCESS_EXISTS)
     {
         /* Do not try to check the presence of a journal on /vsicurl ! */
-        if ( strncmp(zName, "/vsicurl/", 9) == 0 &&
+        if ( STARTS_WITH(zName, "/vsicurl/") &&
              strlen(zName) > strlen("-journal") &&
              strcmp(zName + strlen(zName) - strlen("-journal"), "-journal") == 0 )
             nRet = -1;
@@ -380,11 +390,51 @@ static int OGRSQLiteVFSSleep (sqlite3_vfs* pVFS, int microseconds)
     return pUnderlyingVFS->xSleep(pUnderlyingVFS, microseconds);
 }
 
-static int OGRSQLiteVFSCurrentTime (sqlite3_vfs* pVFS, double* p1)
+// Derived for sqlite3.c implementation of unixCurrentTime64 and winCurrentTime64
+#ifdef WIN32
+#include <windows.h>
+static int OGRSQLiteVFSCurrentTimeInt64 (sqlite3_vfs* /*pVFS*/, sqlite3_int64 *piNow)
 {
-    sqlite3_vfs* pUnderlyingVFS = GET_UNDERLYING_VFS(pVFS);
-    //CPLDebug("SQLITE", "OGRSQLiteVFSCurrentTime()");
-    return pUnderlyingVFS->xCurrentTime(pUnderlyingVFS, p1);
+    FILETIME ft;
+    static const sqlite3_int64 winFiletimeEpoch = 23058135*(sqlite3_int64)8640000;
+    static const sqlite3_int64 max32BitValue =
+      (sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 +
+      (sqlite3_int64)294967296;
+
+#if defined(_WIN32_WCE)
+    SYSTEMTIME time;
+    GetSystemTime(&time);
+    /* if SystemTimeToFileTime() fails, it returns zero. */
+    if (!SystemTimeToFileTime(&time,&ft)){
+        return SQLITE_ERROR;
+    }
+#else
+    GetSystemTimeAsFileTime( &ft );
+#endif
+    *piNow = winFiletimeEpoch +
+            ((((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) +
+               (sqlite3_int64)ft.dwLowDateTime)/(sqlite3_int64)10000;
+    return SQLITE_OK;
+}
+#else
+#include <sys/time.h>
+static int OGRSQLiteVFSCurrentTimeInt64 (sqlite3_vfs* /*pVFS*/, sqlite3_int64 *piNow)
+{
+    struct timeval sNow;
+    static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
+    (void)gettimeofday(&sNow, NULL);  /* Cannot fail given valid arguments */
+    *piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_usec/1000;
+
+    return SQLITE_OK;
+}
+#endif
+
+static int OGRSQLiteVFSCurrentTime (sqlite3_vfs* /*pVFS*/, double* p1)
+{
+    sqlite3_int64 i = 0;
+    int rc = OGRSQLiteVFSCurrentTimeInt64(NULL, &i);
+    *p1 = i/86400000.0;
+    return rc;
 }
 
 static int OGRSQLiteVFSGetLastError (sqlite3_vfs* pVFS, int p1, char *p2)
@@ -401,13 +451,17 @@ sqlite3_vfs* OGRSQLiteCreateVFS(pfnNotifyFileOpenedType pfn, void* pfnUserData)
 
     OGRSQLiteVFSAppDataStruct* pVFSAppData =
         (OGRSQLiteVFSAppDataStruct*) CPLCalloc(1, sizeof(OGRSQLiteVFSAppDataStruct));
-    sprintf(pVFSAppData->szVFSName, "OGRSQLITEVFS_%p", pVFSAppData);
+    snprintf(pVFSAppData->szVFSName, sizeof(pVFSAppData->szVFSName), "OGRSQLITEVFS_%p", pVFSAppData);
     pVFSAppData->pDefaultVFS = pDefaultVFS;
     pVFSAppData->pfn = pfn;
     pVFSAppData->pfnUserData = pfnUserData;
     pVFSAppData->nCounter = 0;
 
+#if SQLITE_VERSION_NUMBER >= 3008000L /* perhaps not the minimal version that defines xCurrentTimeInt64, but who cares */
+    pMyVFS->iVersion = 2;
+#else
     pMyVFS->iVersion = 1;
+#endif
     pMyVFS->szOsFile = sizeof(OGRSQLiteFileStruct);
     pMyVFS->mxPathname = pDefaultVFS->mxPathname;
     pMyVFS->zName = pVFSAppData->szVFSName;
@@ -424,6 +478,11 @@ sqlite3_vfs* OGRSQLiteCreateVFS(pfnNotifyFileOpenedType pfn, void* pfnUserData)
     pMyVFS->xSleep = OGRSQLiteVFSSleep;
     pMyVFS->xCurrentTime = OGRSQLiteVFSCurrentTime;
     pMyVFS->xGetLastError = OGRSQLiteVFSGetLastError;
+#if SQLITE_VERSION_NUMBER >= 3008000L /* perhaps not the minimal version that defines xCurrentTimeInt64, but who cares */
+    if( pMyVFS->iVersion >= 2 )
+        pMyVFS->xCurrentTimeInt64 = OGRSQLiteVFSCurrentTimeInt64;
+#endif
+
     return pMyVFS;
 }
 
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqliteviewlayer.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqliteviewlayer.cpp
index feb7108..d696463 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqliteviewlayer.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqliteviewlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqliteviewlayer.cpp 28386 2015-01-30 17:04:25Z rouault $
+ * $Id: ogrsqliteviewlayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteViewLayer class, access to an existing spatialite view.
@@ -32,7 +32,7 @@
 #include "ogr_sqlite.h"
 #include <string>
 
-CPL_CVSID("$Id: ogrsqliteviewlayer.cpp 28386 2015-01-30 17:04:25Z rouault $");
+CPL_CVSID("$Id: ogrsqliteviewlayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                        OGRSQLiteViewLayer()                         */
@@ -54,6 +54,8 @@ OGRSQLiteViewLayer::OGRSQLiteViewLayer( OGRSQLiteDataSource *poDSIn )
     bHasCheckedSpatialIndexTable = FALSE;
 
     bLayerDefnError = FALSE;
+    eGeomFormat = OSGF_None;
+    poUnderlyingLayer = NULL;
 }
 
 /************************************************************************/
@@ -73,14 +75,14 @@ OGRSQLiteViewLayer::~OGRSQLiteViewLayer()
 /*                             Initialize()                             */
 /************************************************************************/
 
-CPLErr OGRSQLiteViewLayer::Initialize( const char *pszViewName,
+CPLErr OGRSQLiteViewLayer::Initialize( const char *pszViewNameIn,
                                        const char *pszViewGeometry,
                                        const char *pszViewRowid,
                                        const char *pszUnderlyingTableName,
                                        const char *pszUnderlyingGeometryColumn)
 
 {
-    this->pszViewName = CPLStrdup(pszViewName);
+    this->pszViewName = CPLStrdup(pszViewNameIn);
     SetDescription( pszViewName );
 
     osGeomColumn = pszViewGeometry;
@@ -156,9 +158,9 @@ OGRwkbGeometryType OGRSQLiteViewLayer::GetGeomType()
     if (poFeatureDefn)
         return poFeatureDefn->GetGeomType();
 
-    OGRSQLiteLayer* poUnderlyingLayer = GetUnderlyingLayer();
-    if (poUnderlyingLayer)
-        return poUnderlyingLayer->GetGeomType();
+    OGRSQLiteLayer* l_poUnderlyingLayer = GetUnderlyingLayer();
+    if (l_poUnderlyingLayer)
+        return l_poUnderlyingLayer->GetGeomType();
 
     return wkbUnknown;
 }
@@ -174,15 +176,15 @@ CPLErr OGRSQLiteViewLayer::EstablishFeatureDefn()
     sqlite3_stmt *hColStmt = NULL;
     const char *pszSQL;
 
-    OGRSQLiteLayer* poUnderlyingLayer = GetUnderlyingLayer();
-    if (poUnderlyingLayer == NULL)
+    OGRSQLiteLayer* l_poUnderlyingLayer = GetUnderlyingLayer();
+    if (l_poUnderlyingLayer == NULL)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot find underlying layer %s for view %s",
                  osUnderlyingTableName.c_str(), pszViewName);
         return CE_Failure;
     }
-    if ( !poUnderlyingLayer->IsTableLayer() )
+    if ( !l_poUnderlyingLayer->IsTableLayer() )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Underlying layer %s for view %s is not a regular table",
@@ -191,7 +193,7 @@ CPLErr OGRSQLiteViewLayer::EstablishFeatureDefn()
     }
 
     int nUnderlyingLayerGeomFieldIndex =
-        poUnderlyingLayer->GetLayerDefn()->GetGeomFieldIndex(osUnderlyingGeometryColumn);
+        l_poUnderlyingLayer->GetLayerDefn()->GetGeomFieldIndex(osUnderlyingGeometryColumn);
     if ( nUnderlyingLayerGeomFieldIndex < 0 )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -201,7 +203,7 @@ CPLErr OGRSQLiteViewLayer::EstablishFeatureDefn()
         return CE_Failure;
     }
 
-    this->bHasSpatialIndex = poUnderlyingLayer->HasSpatialIndex(nUnderlyingLayerGeomFieldIndex);
+    this->bHasSpatialIndex = l_poUnderlyingLayer->HasSpatialIndex(nUnderlyingLayerGeomFieldIndex);
 
 /* -------------------------------------------------------------------- */
 /*      Get the column definitions for this table.                      */
@@ -211,21 +213,21 @@ CPLErr OGRSQLiteViewLayer::EstablishFeatureDefn()
                          OGRSQLiteEscapeName(pszFIDColumn).c_str(),
                          pszEscapedTableName );
 
-    rc = sqlite3_prepare( hDB, pszSQL, strlen(pszSQL), &hColStmt, NULL ); 
+    rc = sqlite3_prepare( hDB, pszSQL, -1, &hColStmt, NULL );
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to query table %s for column definitions : %s.",
                   pszViewName, sqlite3_errmsg(hDB) );
-        
+
         return CE_Failure;
     }
 
     rc = sqlite3_step( hColStmt );
     if ( rc != SQLITE_DONE && rc != SQLITE_ROW )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "In Initialize(): sqlite3_step(%s):\n  %s", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "In Initialize(): sqlite3_step(%s):\n  %s",
                   pszSQL, sqlite3_errmsg(hDB) );
         sqlite3_finalize( hColStmt );
         return CE_Failure;
@@ -246,7 +248,7 @@ CPLErr OGRSQLiteViewLayer::EstablishFeatureDefn()
     if( poFeatureDefn->GetGeomFieldCount() != 0 )
     {
         OGRSQLiteGeomFieldDefn* poSrcGeomFieldDefn =
-            poUnderlyingLayer->myGetLayerDefn()->myGetGeomFieldDefn(nUnderlyingLayerGeomFieldIndex);
+            l_poUnderlyingLayer->myGetLayerDefn()->myGetGeomFieldDefn(nUnderlyingLayerGeomFieldIndex);
         OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
             poFeatureDefn->myGetGeomFieldDefn(0);
         poGeomFieldDefn->SetType(poSrcGeomFieldDefn->GetType());
@@ -275,10 +277,10 @@ OGRErr OGRSQLiteViewLayer::ResetStatement()
 
     osSQL.Printf( "SELECT \"%s\", * FROM '%s' %s",
                   OGRSQLiteEscapeName(pszFIDColumn).c_str(),
-                  pszEscapedTableName, 
+                  pszEscapedTableName,
                   osWHERE.c_str() );
 
-    rc = sqlite3_prepare( poDS->GetDB(), osSQL, osSQL.size(),
+    rc = sqlite3_prepare( poDS->GetDB(), osSQL, static_cast<int>(osSQL.size()),
 		          &hStmt, NULL );
 
     if( rc == SQLITE_OK )
@@ -287,8 +289,8 @@ OGRErr OGRSQLiteViewLayer::ResetStatement()
     }
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "In ResetStatement(): sqlite3_prepare(%s):\n  %s", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "In ResetStatement(): sqlite3_prepare(%s):\n  %s",
                   osSQL.c_str(), sqlite3_errmsg(poDS->GetDB()) );
         hStmt = NULL;
         return OGRERR_FAILURE;
@@ -337,18 +339,18 @@ OGRFeature *OGRSQLiteViewLayer::GetFeature( GIntBig nFeatureId )
 
     osSQL.Printf( "SELECT \"%s\", * FROM '%s' WHERE \"%s\" = %d",
                   OGRSQLiteEscapeName(pszFIDColumn).c_str(),
-                  pszEscapedTableName, 
+                  pszEscapedTableName,
                   OGRSQLiteEscapeName(pszFIDColumn).c_str(),
                   (int) nFeatureId );
 
     CPLDebug( "OGR_SQLITE", "exec(%s)", osSQL.c_str() );
 
-    rc = sqlite3_prepare( poDS->GetDB(), osSQL, osSQL.size(), 
+    rc = sqlite3_prepare( poDS->GetDB(), osSQL, static_cast<int>(osSQL.size()),
                           &hStmt, NULL );
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "In GetFeature(): sqlite3_prepare(%s):\n  %s", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "In GetFeature(): sqlite3_prepare(%s):\n  %s",
                   osSQL.c_str(), sqlite3_errmsg(poDS->GetDB()) );
 
         return NULL;
@@ -530,7 +532,7 @@ int OGRSQLiteViewLayer::TestCapability( const char * pszCap )
     else if (EQUAL(pszCap,OLCFastSpatialFilter))
         return bHasSpatialIndex;
 
-    else 
+    else
         return OGRSQLiteLayer::TestCapability( pszCap );
 }
 
@@ -567,7 +569,7 @@ GIntBig OGRSQLiteViewLayer::GetFeatureCount( int bForce )
     int nRowCount, nColCount;
     int nResult = -1;
 
-    if( sqlite3_get_table( poDS->GetDB(), pszSQL, &papszResult, 
+    if( sqlite3_get_table( poDS->GetDB(), pszSQL, &papszResult,
                            &nColCount, &nRowCount, &pszErrMsg ) != SQLITE_OK )
         return -1;
 
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.cpp
index 9a66f00..1953c24 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqlitevirtualogr.cpp 28900 2015-04-14 09:40:34Z rouault $
+ * $Id: ogrsqlitevirtualogr.cpp 33554 2016-02-25 16:00:10Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  SQLite Virtual Table module using OGR layers
@@ -21,12 +21,12 @@
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, MAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
- 
+
 #include "ogrsqlitevirtualogr.h"
 #include "ogr_api.h"
 #include "swq.h"
@@ -58,11 +58,7 @@ void OGR2SQLITE_Register()
 #define VIRTUAL_OGR_DYNAMIC_EXTENSION_ENABLED
 //#define DEBUG_OGR2SQLITE
 
-#if defined(SPATIALITE_AMALGAMATION)
 #include "ogrsqlite3ext.h"
-#else
-#include "sqlite3ext.h"
-#endif
 
 /* Declaration of sqlite3_api structure */
 static SQLITE_EXTENSION_INIT1
@@ -163,10 +159,10 @@ void OGR2SQLITEModule::SetHandleSQLFunctions(void* hHandleSQLFunctionsIn)
 /*                            AddExtraDS()                              */
 /************************************************************************/
 
-int OGR2SQLITEModule::AddExtraDS(OGRDataSource* poDS)
+int OGR2SQLITEModule::AddExtraDS(OGRDataSource* poDSIn)
 {
     int nRet = (int)apoExtraDS.size();
-    apoExtraDS.push_back(poDS);
+    apoExtraDS.push_back(poDSIn);
     return nRet;
 }
 
@@ -407,7 +403,7 @@ static int OGR2SQLITEDetectSuspiciousUsage(sqlite3* hDB,
 
         if( nRowCount > 0 )
         {
-            if( !CSLTestBoolean(CPLGetConfigOption("ALLOW_VIRTUAL_OGR_FROM_TRIGGER_AND_VIEW", "NO")) )
+            if( !CPLTestBool(CPLGetConfigOption("ALLOW_VIRTUAL_OGR_FROM_TRIGGER_AND_VIEW", "NO")) )
             {
                 *pzErr = sqlite3_mprintf(
                     "A trigger and/or view might reference VirtualOGR table '%s'.\n"
@@ -443,6 +439,7 @@ int OGR2SQLITE_ConnectCreate(sqlite3* hDB, void *pAux,
     int bExposeOGR_STYLE = FALSE;
     int bCloseDS = FALSE;
     int bInternalUse = FALSE;
+    int bExposeOGRNativeData = FALSE;
     int i;
 
 #ifdef DEBUG_OGR2SQLITE
@@ -456,17 +453,10 @@ int OGR2SQLITE_ConnectCreate(sqlite3* hDB, void *pAux,
 /*      If called from ogrexecutesql.cpp                                */
 /* -------------------------------------------------------------------- */
     poDS = poModule->GetDS();
-    if( poDS != NULL && argc == 6 &&
+    if( poDS != NULL && (argc == 6 || argc == 7) &&
         CPLGetValueType(argv[3]) == CPL_VALUE_INTEGER )
     {
         bInternalUse = TRUE;
-        if( argc != 6 )
-        {
-            *pzErr = sqlite3_mprintf(
-                "Expected syntax: CREATE VIRTUAL TABLE xxx USING "
-                "VirtualOGR(ds_idx, layer_name, expose_ogr_style)");
-            return SQLITE_ERROR;
-        }
 
         int nDSIndex = atoi(argv[3]);
         if( nDSIndex >= 0 )
@@ -489,6 +479,7 @@ int OGR2SQLITE_ConnectCreate(sqlite3* hDB, void *pAux,
         }
 
         bExposeOGR_STYLE = atoi(OGRSQLiteParamsUnquote(argv[5]));
+        bExposeOGRNativeData = (argc == 7) ? atoi(OGRSQLiteParamsUnquote(argv[6])) : FALSE;
     }
 #ifdef VIRTUAL_OGR_DYNAMIC_EXTENSION_ENABLED
 /* -------------------------------------------------------------------- */
@@ -496,11 +487,11 @@ int OGR2SQLITE_ConnectCreate(sqlite3* hDB, void *pAux,
 /* -------------------------------------------------------------------- */
     else
     {
-        if( argc < 4 || argc > 7 )
+        if( argc < 4 || argc > 8 )
         {
             *pzErr = sqlite3_mprintf(
                 "Expected syntax: CREATE VIRTUAL TABLE xxx USING "
-                "VirtualOGR(datasource_name[, update_mode, [layer_name[, expose_ogr_style]]])");
+                "VirtualOGR(datasource_name[, update_mode, [layer_name[, expose_ogr_style[, expose_ogr_native_data]]]])");
             return SQLITE_ERROR;
         }
 
@@ -557,22 +548,27 @@ int OGR2SQLITE_ConnectCreate(sqlite3* hDB, void *pAux,
 
         if( poLayer == NULL )
         {
-            *pzErr = sqlite3_mprintf( "Cannot find layer '%s' in '%s'", osLayerName.c_str(), osDSName.c_str() );
+            *pzErr = sqlite3_mprintf( "Cannot find layer '%s' in '%s'",
+                                      osLayerName.c_str(), osDSName.c_str() );
             poDS->Release();
             return SQLITE_ERROR;
         }
 
-        if( argc == 7 )
+        if( argc >= 7 )
         {
             bExposeOGR_STYLE = atoi(OGRSQLiteParamsUnquote(argv[6]));
         }
-        
+        if( argc >= 8 )
+        {
+            bExposeOGRNativeData = atoi(OGRSQLiteParamsUnquote(argv[7]));
+        }
+
         bCloseDS = TRUE;
     }
 #endif // VIRTUAL_OGR_DYNAMIC_EXTENSION_ENABLED
     OGR2SQLITE_vtab* vtab =
                 (OGR2SQLITE_vtab*) CPLCalloc(1, sizeof(OGR2SQLITE_vtab));
-    /* We dont need to fill the non-extended fields */
+    /* We do not need to fill the non-extended fields */
     vtab->pszVTableName = CPLStrdup(OGRSQLiteEscapeName(argv[2]));
     vtab->poModule = poModule;
     vtab->poDS = poDS;
@@ -635,13 +631,16 @@ int OGR2SQLITE_ConnectCreate(sqlite3* hDB, void *pAux,
 
         /* We use a special column type, e.g. BLOB_POINT_25D_4326 */
         /* when the virtual table is created by OGRSQLiteExecuteSQL() */
-        /* and thus for interal use only. */
+        /* and thus for internal use only. */
         if( bInternalUse )
         {
             osSQL += "_";
             osSQL += OGRToOGCGeomType(poFieldDefn->GetType());
-            osSQL += "_";
-            osSQL += wkbHasZ(poFieldDefn->GetType()) ? "25D" : "2D";
+            osSQL += "_XY";
+            if( wkbHasZ(poFieldDefn->GetType()) )
+                osSQL += "Z";
+            if( wkbHasM(poFieldDefn->GetType()) )
+                osSQL += "M";
             OGRSpatialReference* poSRS = poFieldDefn->GetSpatialRef();
             if( poSRS == NULL && i == 0 )
                 poSRS = poLayer->GetSpatialRef();
@@ -654,6 +653,13 @@ int OGR2SQLITE_ConnectCreate(sqlite3* hDB, void *pAux,
         }
     }
 
+    osSQL += ", OGR_NATIVE_DATA VARCHAR";
+    if( !bExposeOGRNativeData )
+        osSQL += " HIDDEN";
+    osSQL += ", OGR_NATIVE_MEDIA_TYPE VARCHAR";
+    if( !bExposeOGRNativeData )
+        osSQL += " HIDDEN";
+
     osSQL += ")";
 
     CPLDebug("OGR2SQLITE", "sqlite3_declare_vtab(%s)", osSQL.c_str());
@@ -749,7 +755,7 @@ int OGR2SQLITE_BestIndex(sqlite3_vtab *pVTab, sqlite3_index_info* pIndex)
     if( nConstraints )
     {
         panConstraints = (int*)
-                    sqlite3_malloc( sizeof(int) * (1 + 2 * nConstraints) );
+                    sqlite3_malloc( (int)sizeof(int) * (1 + 2 * nConstraints) );
         panConstraints[0] = nConstraints;
 
         nConstraints = 0;
@@ -852,7 +858,7 @@ int OGR2SQLITE_Open(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor)
 
     OGR2SQLITE_vtab_cursor* pCursor = (OGR2SQLITE_vtab_cursor*)
                                 CPLCalloc(1, sizeof(OGR2SQLITE_vtab_cursor));
-    /* We dont need to fill the non-extended fields */
+    // We do not need to fill the non-extended fields.
     *ppCursor = (sqlite3_vtab_cursor *)pCursor;
 
     pCursor->poDupDataSource = poDupDataSource;
@@ -1133,9 +1139,9 @@ static void OGR2SQLITE_ExportGeometry(OGRGeometry* poGeom, int nSRSId,
                                       int& nGeomBLOBLen)
 {
     if( OGRSQLiteLayer::ExportSpatiaLiteGeometry(
-            poGeom, nSRSId, wkbNDR, FALSE, FALSE, FALSE,
+            poGeom, nSRSId, wkbNDR, FALSE, FALSE,
             &pabyGeomBLOB,
-            &nGeomBLOBLen ) != CE_None )
+            &nGeomBLOBLen ) != OGRERR_NONE )
     {
         nGeomBLOBLen = 0;
     }
@@ -1147,8 +1153,8 @@ static void OGR2SQLITE_ExportGeometry(OGRGeometry* poGeom, int nSRSId,
 
         pabyGeomBLOB = (GByte*) CPLRealloc(pabyGeomBLOB,
                                 nGeomBLOBLen + nWkbSize + 1);
-        poGeom->exportToWkb(wkbNDR, pabyGeomBLOB + nGeomBLOBLen);
-        /* Sheat a bit and add a end-of-blob spatialite marker */
+        poGeom->exportToWkb(wkbNDR, pabyGeomBLOB + nGeomBLOBLen, wkbVariantIso);
+        /* Cheat a bit and add a end-of-blob spatialite marker */
         pabyGeomBLOB[nGeomBLOBLen + nWkbSize] = 0xFE;
         nGeomBLOBLen += nWkbSize + 1;
     }
@@ -1252,7 +1258,21 @@ int OGR2SQLITE_Column(sqlite3_vtab_cursor* pCursor,
         }
         return SQLITE_OK;
     }
-    else if( nCol < 0 || nCol >= nFieldCount )
+    else if( nCol == nFieldCount + 1 + poFDefn->GetGeomFieldCount() )
+    {
+        sqlite3_result_text(pContext,
+                            poFeature->GetNativeData(),
+                            -1, SQLITE_TRANSIENT);
+        return SQLITE_OK;
+    }
+    else if( nCol == nFieldCount + 1 + poFDefn->GetGeomFieldCount() + 1 )
+    {
+        sqlite3_result_text(pContext,
+                            poFeature->GetNativeMediaType(),
+                            -1, SQLITE_TRANSIENT);
+        return SQLITE_OK;
+    }
+    else if( nCol < 0 || nCol >= nFieldCount + 1 + poFDefn->GetGeomFieldCount() + 2 )
     {
         return SQLITE_ERROR;
     }
@@ -1301,7 +1321,7 @@ int OGR2SQLITE_Column(sqlite3_vtab_cursor* pCursor,
             poFeature->GetFieldAsDateTime(nCol, &nYear, &nMonth, &nDay,
                                           &nHour, &nMinute, &nSecond, &nTZ);
             char szBuffer[64];
-            sprintf(szBuffer, "%04d-%02d-%02d", nYear, nMonth, nDay);
+            snprintf(szBuffer, sizeof(szBuffer), "%04d-%02d-%02d", nYear, nMonth, nDay);
             sqlite3_result_text(pContext,
                                 szBuffer,
                                 -1, SQLITE_TRANSIENT);
@@ -1316,9 +1336,9 @@ int OGR2SQLITE_Column(sqlite3_vtab_cursor* pCursor,
                                         &nHour, &nMinute, &fSecond, &nTZ );
             char szBuffer[64];
             if( OGR_GET_MS(fSecond) != 0 )
-                sprintf(szBuffer, "%02d:%02d:%06.3f", nHour, nMinute, fSecond);
+                snprintf(szBuffer, sizeof(szBuffer), "%02d:%02d:%06.3f", nHour, nMinute, fSecond);
             else
-                sprintf(szBuffer, "%02d:%02d:%02d", nHour, nMinute, (int)fSecond);
+                snprintf(szBuffer, sizeof(szBuffer), "%02d:%02d:%02d", nHour, nMinute, (int)fSecond);
             sqlite3_result_text(pContext,
                                 szBuffer,
                                 -1, SQLITE_TRANSIENT);
@@ -1397,10 +1417,10 @@ static OGRFeature* OGR2SQLITE_FeatureFromArgs(OGRLayer* poLayer,
     OGRFeatureDefn* poLayerDefn = poLayer->GetLayerDefn();
     int nFieldCount = poLayerDefn->GetFieldCount();
     int nGeomFieldCount = poLayerDefn->GetGeomFieldCount();
-    if( argc != 2 + nFieldCount + 1 + nGeomFieldCount)
+    if( argc != 2 + nFieldCount + 1 + nGeomFieldCount + 2)
     {
         CPLDebug("OGR2SQLITE", "Did not get expect argument count : %d, %d", argc,
-                    2 + nFieldCount + 1 + nGeomFieldCount);
+                    2 + nFieldCount + 1 + nGeomFieldCount + 2);
         return NULL;
     }
 
@@ -1463,7 +1483,7 @@ static OGRFeature* OGR2SQLITE_FeatureFromArgs(OGRLayer* poLayer,
             int nLen = sqlite3_value_bytes (argv[nGeomFieldIdx]);
             OGRGeometry* poGeom = NULL;
             if( OGRSQLiteLayer::ImportSpatiaLiteGeometry(
-                            pabyBlob, nLen, &poGeom ) == CE_None )
+                            pabyBlob, nLen, &poGeom ) == OGRERR_NONE )
             {
 /*                OGRwkbGeometryType eGeomFieldType =
                     poFeature->GetDefnRef()->GetGeomFieldDefn(i)->GetType();
@@ -1479,6 +1499,15 @@ static OGRFeature* OGR2SQLITE_FeatureFromArgs(OGRLayer* poLayer,
         }
     }
 
+    if( sqlite3_value_type(argv[2 + nFieldCount + 1 + nGeomFieldCount]) == SQLITE_TEXT )
+    {
+        poFeature->SetNativeData((const char*) sqlite3_value_text(argv[2 + nFieldCount + 1 + nGeomFieldCount]));
+    }
+
+    if( sqlite3_value_type(argv[2 + nFieldCount + 1 + nGeomFieldCount + 1]) == SQLITE_TEXT )
+    {
+        poFeature->SetNativeMediaType((const char*) sqlite3_value_text(argv[2 + nFieldCount + 1 + nGeomFieldCount + 1]));
+    }
     if( sqlite3_value_type(argv[1]) == SQLITE_INTEGER )
         poFeature->SetFID( sqlite3_value_int64(argv[1]) );
 
@@ -1571,7 +1600,12 @@ static const struct sqlite3_module sOGR2SQLITEModule =
     NULL, /* xCommit */
     NULL, /* xFindFunctionRollback */
     NULL, /* xFindFunction */  // OGR2SQLITE_FindFunction;
-    OGR2SQLITE_Rename
+    OGR2SQLITE_Rename,
+#if SQLITE_VERSION_NUMBER >= 3007007L /* should be the first version with the below symbols */
+    NULL,  // xSavepoint
+    NULL,  // xRelease
+    NULL,  // xRollbackTo
+#endif
 };
 
 /************************************************************************/
@@ -1672,8 +1706,8 @@ void OGR2SQLITE_ogr_layer_Extent(sqlite3_context* pContext,
     int nBLOBLen = 0;
     int nSRID = poModule->FetchSRSId(poLayer->GetSpatialRef());
     if( OGRSQLiteLayer::ExportSpatiaLiteGeometry(
-                    &oPoly, nSRID, wkbNDR, FALSE,
-                    FALSE, FALSE, &pabySLBLOB, &nBLOBLen ) == CE_None )
+                    &oPoly, nSRID, wkbNDR,
+                    FALSE, FALSE, &pabySLBLOB, &nBLOBLen ) == OGRERR_NONE )
     {
         sqlite3_result_blob(pContext, pabySLBLOB, nBLOBLen, CPLFree);
     }
@@ -1870,7 +1904,7 @@ int OGR2SQLITESpatialIndex_ConnectCreate(sqlite3* hDB, void *pAux,
 
     OGR2SQLITESpatialIndex_vtab* vtab =
                 (OGR2SQLITESpatialIndex_vtab*) CPLCalloc(1, sizeof(OGR2SQLITESpatialIndex_vtab));
-    /* We dont need to fill the non-extended fields */
+    // We do not need to fill the non-extended fields.
     vtab->pszVTableName = CPLStrdup(OGRSQLiteEscapeName(argv[2]));
     vtab->poModule = poModule;
     vtab->poDS = poDS;
@@ -2080,7 +2114,7 @@ int OGR2SQLITESpatialIndex_Open(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCur
 
     OGR2SQLITESpatialIndex_vtab_cursor* pCursor = (OGR2SQLITESpatialIndex_vtab_cursor*)
                                 CPLCalloc(1, sizeof(OGR2SQLITESpatialIndex_vtab_cursor));
-    /* We dont need to fill the non-extended fields */
+    // We do not need to fill the non-extended fields.
     *ppCursor = (sqlite3_vtab_cursor *)pCursor;
 
     pCursor->poDupDataSource = poDupDataSource;
@@ -2337,11 +2371,11 @@ static const struct sqlite3_module sOGR2SQLITESpatialIndex =
 /*                              Setup()                                 */
 /************************************************************************/
 
-int OGR2SQLITEModule::Setup(sqlite3* hDB)
+int OGR2SQLITEModule::Setup(sqlite3* hDBIn)
 {
     int rc;
 
-    this->hDB = hDB;
+    this->hDB = hDBIn;
 
     rc = sqlite3_create_module_v2(hDB, "VirtualOGR", &sOGR2SQLITEModule, this,
                                   OGR2SQLITEDestroyModule);
@@ -2459,10 +2493,10 @@ int OGR2SQLITE_static_register (sqlite3 * hDB, char **pzErrMsg, void * _pApi)
 
     /* The config option is turned off by ogrsqliteexecutesql.cpp that needs */
     /* to create a custom module */
-    if( CSLTestBoolean(CPLGetConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", "YES")) )
+    if( CPLTestBool(CPLGetConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", "YES")) )
     {
-        /* Can happen if sqlite is compiled with SQLITE_OMIT_LOAD_EXTENSION (with sqlite 3.6.10 for example) */
-        /* We return here OK since it is not vital for regular SQLite dababases */
+        /* Can happen if SQLite is compiled with SQLITE_OMIT_LOAD_EXTENSION (with SQLite 3.6.10 for example) */
+        /* We return here OK since it is not vital for regular SQLite databases */
         /* to load the OGR SQL functions */
         if( pApi->create_module == NULL )
             return SQLITE_OK;
@@ -2472,7 +2506,7 @@ int OGR2SQLITE_static_register (sqlite3 * hDB, char **pzErrMsg, void * _pApi)
     }
     else
     {
-        /* Can happen if sqlite is compiled with SQLITE_OMIT_LOAD_EXTENSION (with sqlite 3.6.10 for example) */
+        /* Can happen if SQLite is compiled with SQLITE_OMIT_LOAD_EXTENSION (with SQLite 3.6.10 for example) */
         /* We return fail since Setup() will later be called, and crash */
         /* if create_module isn't available */
         if( pApi->create_module == NULL )
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.h b/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.h
index 2bf1433..1c1b95f 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.h
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqlitevirtualogr.h 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogrsqlitevirtualogr.h 31777 2015-11-26 14:14:41Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  SQLite Virtual Table module using OGR layers
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_SQLITE_VIRTUAL_OGR_H_INCLUDED
-#define _OGR_SQLITE_VIRTUAL_OGR_H_INCLUDED
+#ifndef OGR_SQLITE_VIRTUAL_OGR_H_INCLUDED
+#define OGR_SQLITE_VIRTUAL_OGR_H_INCLUDED
 
 #include "ogr_sqlite.h"
 
@@ -47,4 +47,4 @@ CPLString OGR2SQLITE_GetNameForGeometryColumn(OGRLayer* poLayer);
 
 #endif // HAVE_SQLITE_VFS
 
-#endif // _OGR_SQLITE_VIRTUAL_OGR_H_INCLUDED
+#endif // OGR_SQLITE_VIRTUAL_OGR_H_INCLUDED
diff --git a/ogr/ogrsf_frmts/sqlite/test_load_virtual_ogr.c b/ogr/ogrsf_frmts/sqlite/test_load_virtual_ogr.c
index 4a936e8..571f833 100644
--- a/ogr/ogrsf_frmts/sqlite/test_load_virtual_ogr.c
+++ b/ogr/ogrsf_frmts/sqlite/test_load_virtual_ogr.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: test_load_virtual_ogr.c 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: test_load_virtual_ogr.c 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Test dynamic loading of SQLite Virtual Table module using OGR layers
@@ -32,8 +32,8 @@
     /*
     / using an AMALGAMATED version of SpatiaLite
     / a private internal copy of SQLite is included:
-    / so we are required including the SpatiaLite's 
-    / own header 
+    / so we are required including the SpatiaLite's
+    / own header
     /
     / IMPORTANT NOTICE: using AMALAGATION is only
     / useful on Windows (to skip DLL hell related oddities)
diff --git a/ogr/ogrsf_frmts/sua/drv_sua.html b/ogr/ogrsf_frmts/sua/drv_sua.html
index fe70712..9fce31f 100644
--- a/ogr/ogrsf_frmts/sua/drv_sua.html
+++ b/ogr/ogrsf_frmts/sua/drv_sua.html
@@ -14,7 +14,7 @@ This driver reads files describing Special Use Airspaces in the Tim Newport-Peac
 Airspace are returned as features of a single layer, with a geometry of type Polygon and the following fields :
 TYPE, CLASS, TITLE, TOPS, BASE.<p>
 
-Airspace geometries made of arcs will be tesselated.<p>
+Airspace geometries made of arcs will be tessellated.<p>
 
 <h3>See Also</h3>
 
diff --git a/ogr/ogrsf_frmts/sua/ogr_sua.h b/ogr/ogrsf_frmts/sua/ogr_sua.h
index a6b3a75..b0c384d 100644
--- a/ogr/ogrsf_frmts/sua/ogr_sua.h
+++ b/ogr/ogrsf_frmts/sua/ogr_sua.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_sua.h 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogr_sua.h 31777 2015-11-26 14:14:41Z rouault $
  *
  * Project:  SUA Translator
  * Purpose:  Definition of classes for OGR .sua driver.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_SUA_H_INCLUDED
-#define _OGR_SUA_H_INCLUDED
+#ifndef OGR_SUA_H_INCLUDED
+#define OGR_SUA_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 
@@ -88,4 +88,4 @@ class OGRSUADataSource : public OGRDataSource
     virtual int                 TestCapability( const char * );
 };
 
-#endif /* ndef _OGR_SUA_H_INCLUDED */
+#endif /* ndef OGR_SUA_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/sua/ogrsuadriver.cpp b/ogr/ogrsf_frmts/sua/ogrsuadriver.cpp
index 9e66592..13953c4 100644
--- a/ogr/ogrsf_frmts/sua/ogrsuadriver.cpp
+++ b/ogr/ogrsf_frmts/sua/ogrsuadriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsuadriver.cpp 29253 2015-05-27 08:49:16Z rouault $
+ * $Id: ogrsuadriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  SUA Translator
  * Purpose:  Implements OGRSUADriver.
@@ -30,7 +30,7 @@
 #include "ogr_sua.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrsuadriver.cpp 29253 2015-05-27 08:49:16Z rouault $");
+CPL_CVSID("$Id: ogrsuadriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
 
 extern "C" void RegisterOGRSUA();
 
@@ -106,24 +106,23 @@ static GDALDataset *OGRSUADriverOpen( GDALOpenInfo* poOpenInfo )
 void RegisterOGRSUA()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "SUA" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "SUA" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "SUA" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Tim Newport-Peace's Special Use Airspace Format" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_sua.html" );
+    poDriver->SetDescription( "SUA" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Tim Newport-Peace's Special Use Airspace "
+                               "Format" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "drv_sua.html" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = OGRSUADriverOpen;
+    poDriver->pfnOpen = OGRSUADriverOpen;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
 
diff --git a/ogr/ogrsf_frmts/sua/ogrsualayer.cpp b/ogr/ogrsf_frmts/sua/ogrsualayer.cpp
index a3df456..f27486f 100644
--- a/ogr/ogrsf_frmts/sua/ogrsualayer.cpp
+++ b/ogr/ogrsf_frmts/sua/ogrsualayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsualayer.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: ogrsualayer.cpp 31478 2015-11-14 19:13:16Z goatbar $
  *
  * Project:  SUA Translator
  * Purpose:  Implements OGRSUALayer class.
@@ -34,7 +34,7 @@
 #include "ogr_xplane_geo_utils.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ogrsualayer.cpp 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: ogrsualayer.cpp 31478 2015-11-14 19:13:16Z goatbar $");
 
 /************************************************************************/
 /*                            OGRSUALayer()                             */
@@ -106,7 +106,7 @@ OGRFeature *OGRSUALayer::GetNextFeature()
 {
     OGRFeature  *poFeature;
 
-    while(TRUE)
+    while( true )
     {
         poFeature = GetNextRawFeature();
         if (poFeature == NULL)
@@ -187,7 +187,7 @@ OGRFeature *OGRSUALayer::GetNextRawFeature()
     if (bEOF)
         return NULL;
 
-    while(TRUE)
+    while( true )
     {
         if (bFirst && bHasLastLine)
         {
@@ -211,29 +211,29 @@ OGRFeature *OGRSUALayer::GetNextRawFeature()
         if (pszLine[0] == '#' || pszLine[0] == '\0')
             continue;
 
-        if (EQUALN(pszLine, "TYPE=", 5))
+        if (STARTS_WITH_CI(pszLine, "TYPE="))
         {
             if (osTYPE.size() != 0)
                 break;
             osTYPE = pszLine + 5;
         }
-        else if (EQUALN(pszLine, "CLASS=", 6))
+        else if (STARTS_WITH_CI(pszLine, "CLASS="))
         {
             if (osCLASS.size() != 0)
                 break;
             osCLASS = pszLine + 6;
         }
-        else if (EQUALN(pszLine, "TITLE=", 6))
+        else if (STARTS_WITH_CI(pszLine, "TITLE="))
         {
             if (osTITLE.size() != 0)
                 break;
             osTITLE = pszLine + 6;
         }
-        else if (EQUALN(pszLine, "TOPS=", 5))
+        else if (STARTS_WITH_CI(pszLine, "TOPS="))
             osTOPS = pszLine + 5;
-        else if (EQUALN(pszLine, "BASE=", 5))
+        else if (STARTS_WITH_CI(pszLine, "BASE="))
             osBASE = pszLine + 5;
-        else if (EQUALN(pszLine, "POINT=", 6))
+        else if (STARTS_WITH_CI(pszLine, "POINT="))
         {
             pszLine += 6;
             if (strlen(pszLine) != 16)
@@ -247,12 +247,12 @@ OGRFeature *OGRSUALayer::GetNextRawFeature()
             dfLastLat = dfLat;
             dfLastLon = dfLon;
         }
-        else if (EQUALN(pszLine, "CLOCKWISE", 9) || EQUALN(pszLine, "ANTI-CLOCKWISE", 14))
+        else if (STARTS_WITH_CI(pszLine, "CLOCKWISE") || STARTS_WITH_CI(pszLine, "ANTI-CLOCKWISE"))
         {
             if (oLR.getNumPoints() == 0)
                 continue;
 
-            int bClockWise = EQUALN(pszLine, "CLOCKWISE", 9);
+            int bClockWise = STARTS_WITH_CI(pszLine, "CLOCKWISE");
 
             /*const char* pszRADIUS = strstr(pszLine, "RADIUS=");
             if (pszRADIUS == NULL)
@@ -303,7 +303,7 @@ OGRFeature *OGRSUALayer::GetNextRawFeature()
             dfLastLat = oLR.getY(oLR.getNumPoints() - 1);
             dfLastLon = oLR.getX(oLR.getNumPoints() - 1);
         }
-        else if (EQUALN(pszLine, "CIRCLE", 6))
+        else if (STARTS_WITH_CI(pszLine, "CIRCLE"))
         {
             const char* pszRADIUS = strstr(pszLine, "RADIUS=");
             if (pszRADIUS == NULL)
@@ -333,7 +333,7 @@ OGRFeature *OGRSUALayer::GetNextRawFeature()
             dfLastLat = oLR.getY(oLR.getNumPoints() - 1);
             dfLastLon = oLR.getX(oLR.getNumPoints() - 1);
         }
-        else if (EQUALN(pszLine, "INCLUDE", 7) || EQUALN(pszLine, "END", 3))
+        else if (STARTS_WITH_CI(pszLine, "INCLUDE") || STARTS_WITH_CI(pszLine, "END"))
         {
         }
         else
diff --git a/ogr/ogrsf_frmts/svg/ogr_svg.h b/ogr/ogrsf_frmts/svg/ogr_svg.h
index 5fe49ee..0c89ace 100644
--- a/ogr/ogrsf_frmts/svg/ogr_svg.h
+++ b/ogr/ogrsf_frmts/svg/ogr_svg.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_svg.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogr_svg.h 32177 2015-12-14 07:25:30Z goatbar $
  *
  * Project:  SVG Translator
  * Purpose:  Definition of classes for OGR .svg driver.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_SVG_H_INCLUDED
-#define _OGR_SVG_H_INCLUDED
+#ifndef OGR_SVG_H_INCLUDED
+#define OGR_SVG_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 
@@ -55,7 +55,7 @@ class OGRSVGLayer : public OGRLayer
     OGRSpatialReference *poSRS;
     OGRSVGDataSource*  poDS;
     CPLString          osLayerName;
-    
+
     SVGGeometryType    svgGeomType;
 
     int                nTotalFeatures;
@@ -106,14 +106,14 @@ class OGRSVGLayer : public OGRLayer
     virtual GIntBig             GetFeatureCount( int bForce = TRUE );
 
     virtual OGRFeatureDefn *    GetLayerDefn();
-    
+
     virtual int                 TestCapability( const char * );
 
 #ifdef HAVE_EXPAT
     void                startElementCbk(const char *pszName, const char **ppszAttr);
     void                endElementCbk(const char *pszName);
     void                dataHandlerCbk(const char *data, int nLen);
-    
+
     void                startElementLoadSchemaCbk(const char *pszName, const char **ppszAttr);
     void                endElementLoadSchemaCbk(const char *pszName);
     void                dataHandlerLoadSchemaCbk(const char *data, int nLen);
@@ -140,10 +140,7 @@ class OGRSVGDataSource : public OGRDataSource
 
 #ifdef HAVE_EXPAT
     OGRSVGValidity      eValidity;
-#endif
     int                 bIsCloudmade;
-
-#ifdef HAVE_EXPAT
     XML_Parser          oCurrentParser;
     int                 nDataHandlerCounter;
 #endif
@@ -161,11 +158,11 @@ class OGRSVGDataSource : public OGRDataSource
 
     virtual int                 TestCapability( const char * );
 
-    
+
 #ifdef HAVE_EXPAT
     void                startElementValidateCbk(const char *pszName, const char **ppszAttr);
     void                dataHandlerValidateCbk(const char *data, int nLen);
 #endif
 };
 
-#endif /* ndef _OGR_SVG_H_INCLUDED */
+#endif /* ndef OGR_SVG_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/svg/ogrsvgdatasource.cpp b/ogr/ogrsf_frmts/svg/ogrsvgdatasource.cpp
index 51a57f5..3bbb727 100644
--- a/ogr/ogrsf_frmts/svg/ogrsvgdatasource.cpp
+++ b/ogr/ogrsf_frmts/svg/ogrsvgdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsvgdatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogrsvgdatasource.cpp 32011 2015-12-06 10:19:18Z rouault $
  *
  * Project:  SVG Translator
  * Purpose:  Implements OGRSVGDataSource class
@@ -30,21 +30,24 @@
 #include "ogr_svg.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrsvgdatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogrsvgdatasource.cpp 32011 2015-12-06 10:19:18Z rouault $");
 
 /************************************************************************/
 /*                          OGRSVGDataSource()                          */
 /************************************************************************/
 
-OGRSVGDataSource::OGRSVGDataSource()
-
+OGRSVGDataSource::OGRSVGDataSource() :
+    pszName(NULL),
+    papoLayers(NULL),
+    nLayers(0)
+#ifdef HAVE_EXPAT
+    ,
+    eValidity(SVG_VALIDITY_UNKNOWN),
+    bIsCloudmade(false),
+    oCurrentParser(NULL),
+    nDataHandlerCounter(0)
+#endif
 {
-    papoLayers = NULL;
-    nLayers = 0;
-
-    bIsCloudmade = FALSE;
-
-    pszName = NULL;
 }
 
 /************************************************************************/
@@ -79,12 +82,12 @@ OGRLayer *OGRSVGDataSource::GetLayer( int iLayer )
 /*                startElementValidateCbk()                             */
 /************************************************************************/
 
-void OGRSVGDataSource::startElementValidateCbk(const char *pszName,
+void OGRSVGDataSource::startElementValidateCbk(const char *pszNameIn,
                                                const char **ppszAttr)
 {
     if (eValidity == SVG_VALIDITY_UNKNOWN)
     {
-        if (strcmp(pszName, "svg") == 0)
+        if (strcmp(pszNameIn, "svg") == 0)
         {
             int i;
             eValidity = SVG_VALIDITY_VALID;
@@ -93,7 +96,7 @@ void OGRSVGDataSource::startElementValidateCbk(const char *pszName,
                 if (strcmp(ppszAttr[i], "xmlns:cm") == 0 &&
                     strcmp(ppszAttr[i+1], "http://cloudmade.com/") == 0)
                 {
-                    bIsCloudmade = TRUE;
+                    bIsCloudmade = true;
                     break;
                 }
             }
@@ -161,7 +164,7 @@ int OGRSVGDataSource::Open( const char * pszFilename )
     VSILFILE* fp = VSIFOpenL(pszFilename, "r");
     if (fp == NULL)
         return FALSE;
-    
+
     eValidity = SVG_VALIDITY_UNKNOWN;
 
     XML_Parser oParser = OGRCreateExpatXMLParser();
@@ -169,12 +172,12 @@ int OGRSVGDataSource::Open( const char * pszFilename )
     XML_SetUserData(oParser, this);
     XML_SetElementHandler(oParser, ::startElementValidateCbk, NULL);
     XML_SetCharacterDataHandler(oParser, ::dataHandlerValidateCbk);
-    
+
     char aBuf[BUFSIZ];
     int nDone;
     unsigned int nLen;
     int nCount = 0;
-    
+
     /* Begin to parse the file and look for the <svg> element */
     /* It *MUST* be the first element of an XML file */
     /* So once we have read the first element, we know if we can */
diff --git a/ogr/ogrsf_frmts/svg/ogrsvgdriver.cpp b/ogr/ogrsf_frmts/svg/ogrsvgdriver.cpp
index fd929e3..516b2c4 100644
--- a/ogr/ogrsf_frmts/svg/ogrsvgdriver.cpp
+++ b/ogr/ogrsf_frmts/svg/ogrsvgdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsvgdriver.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogrsvgdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  SVG Translator
  * Purpose:  Implements OGRSVGDriver.
@@ -30,7 +30,7 @@
 #include "ogr_svg.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrsvgdriver.cpp 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: ogrsvgdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
 
 CPL_C_START
 void RegisterOGRSVG();
@@ -42,7 +42,7 @@ CPL_C_END
 /*                                Open()                                */
 /************************************************************************/
 
-GDALDataset *OGRSVGDriverOpen( GDALOpenInfo* poOpenInfo )
+static GDALDataset *OGRSVGDriverOpen( GDALOpenInfo* poOpenInfo )
 
 {
     if( poOpenInfo->eAccess == GA_Update || poOpenInfo->fpL == NULL )
@@ -69,27 +69,23 @@ GDALDataset *OGRSVGDriverOpen( GDALOpenInfo* poOpenInfo )
 void RegisterOGRSVG()
 
 {
-    if (! GDAL_CHECK_VERSION("OGR/SVG driver"))
+    if(! GDAL_CHECK_VERSION("OGR/SVG driver") )
         return;
-    GDALDriver  *poDriver;
 
-    if( GDALGetDriverByName( "SVG" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    if( GDALGetDriverByName( "SVG" ) != NULL )
+        return;
 
-        poDriver->SetDescription( "SVG" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Scalable Vector Graphics" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "svg" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_svg.html" );
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetDescription( "SVG" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Scalable Vector Graphics" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "svg" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_svg.html" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = OGRSVGDriverOpen;
+    poDriver->pfnOpen = OGRSVGDriverOpen;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
 
diff --git a/ogr/ogrsf_frmts/svg/ogrsvglayer.cpp b/ogr/ogrsf_frmts/svg/ogrsvglayer.cpp
index a6ef58f..5760dbe 100644
--- a/ogr/ogrsf_frmts/svg/ogrsvglayer.cpp
+++ b/ogr/ogrsf_frmts/svg/ogrsvglayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsvglayer.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrsvglayer.cpp 32177 2015-12-14 07:25:30Z goatbar $
  *
  * Project:  SVG Translator
  * Purpose:  Implements OGRSVGLayer class.
@@ -30,7 +30,7 @@
 #include "ogr_svg.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrsvglayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrsvglayer.cpp 32177 2015-12-14 07:25:30Z goatbar $");
 
 /************************************************************************/
 /*                            OGRSVGLayer()                             */
@@ -38,28 +38,42 @@ CPL_CVSID("$Id: ogrsvglayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
 
 OGRSVGLayer::OGRSVGLayer( const char* pszFilename,
                           const char* pszLayerName,
-                          SVGGeometryType svgGeomType,
-                          OGRSVGDataSource* poDS)
+                          SVGGeometryType svgGeomTypeIn,
+                          OGRSVGDataSource* poDSIn) :
+    poFeatureDefn(NULL),
+    poSRS(NULL),
+    poDS(NULL),
+    nTotalFeatures(0),
+    nNextFID(0),
+    fpSVG(NULL),
+#ifdef HAVE_EXPAT
+    oParser(NULL),
+    oSchemaParser(NULL),
+#endif
+    pszSubElementValue(NULL),
+    nSubElementValueLen(0),
+    iCurrentField(0),
+    poFeature(NULL),
+    ppoFeatureTab(NULL),
+    nFeatureTabLength(0),
+    nFeatureTabIndex(0),
+    depthLevel(0),
+    interestingDepthLevel(0),
+    inInterestingElement(FALSE),
+    bStopParsing(FALSE)
+#ifdef HAVE_EXPAT
+        ,
+    nWithoutEventCounter(0),
+    nDataHandlerCounter(0),
+    poCurLayer(NULL)
+#endif
 
 {
-    nNextFID = 0;
-
-    this->poDS = poDS;
-    this->svgGeomType = svgGeomType;
+    this->poDS = poDSIn;
+    this->svgGeomType = svgGeomTypeIn;
     osLayerName = pszLayerName;
     SetDescription( pszLayerName );
 
-    poFeatureDefn = NULL;
-
-    nTotalFeatures = 0;
-
-    ppoFeatureTab = NULL;
-    nFeatureTabIndex = 0;
-    nFeatureTabLength = 0;
-    pszSubElementValue = NULL;
-    nSubElementValueLen = 0;
-    bStopParsing = FALSE;
-
     poSRS = new OGRSpatialReference("PROJCS[\"WGS 84 / Pseudo-Mercator\","
     "GEOGCS[\"WGS 84\","
     "    DATUM[\"WGS_1984\","
@@ -83,12 +97,6 @@ OGRSVGLayer::OGRSVGLayer( const char* pszFilename,
     "AXIS[\"X\",EAST],"
     "AXIS[\"Y\",NORTH]]");
 
-    poFeature = NULL;
-
-#ifdef HAVE_EXPAT
-    oParser = NULL;
-#endif
-
     fpSVG = VSIFOpenL( pszFilename, "r" );
     if( fpSVG == NULL )
     {
@@ -112,7 +120,7 @@ OGRSVGLayer::~OGRSVGLayer()
 #endif
     if (poFeatureDefn)
         poFeatureDefn->Release();
-    
+
     if( poSRS != NULL )
         poSRS->Release();
 
@@ -226,7 +234,7 @@ static void OGRSVGParseD(OGRLineString* poLS, const char* pszD)
     int bRelativeLineto = FALSE;
     double dfX = 0, dfY = 0;
     int nPointCount = 0;
-    while(TRUE)
+    while( true )
     {
         ch = *(pszIter ++);
 
@@ -417,7 +425,7 @@ void OGRSVGLayer::startElementCbk(const char *pszName, const char **ppszAttr)
     }
     else if (inInterestingElement &&
              depthLevel == interestingDepthLevel + 1 &&
-             strncmp(pszName, "cm:", 3) == 0)
+             STARTS_WITH(pszName, "cm:"))
     {
         iCurrentField = poFeatureDefn->GetFieldIndex(pszName + 3);
     }
@@ -498,11 +506,10 @@ void OGRSVGLayer::dataHandlerCbk(const char *data, int nLen)
 
     if (iCurrentField >= 0)
     {
-        char* pszNewSubElementValue = (char*) VSIRealloc(pszSubElementValue,
+        char* pszNewSubElementValue = (char*) VSI_REALLOC_VERBOSE(pszSubElementValue,
                                            nSubElementValueLen + nLen + 1);
         if (pszNewSubElementValue == NULL)
         {
-            CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
             XML_StopParser(oParser, XML_FALSE);
             bStopParsing = TRUE;
             return;
@@ -540,12 +547,12 @@ OGRFeature *OGRSVGLayer::GetNextFeature()
     {
         return ppoFeatureTab[nFeatureTabIndex++];
     }
-    
+
     if (VSIFEofL(fpSVG))
         return NULL;
-    
+
     char aBuf[BUFSIZ];
-    
+
     CPLFree(ppoFeatureTab);
     ppoFeatureTab = NULL;
     nFeatureTabLength = 0;
@@ -734,7 +741,7 @@ void OGRSVGLayer::startElementLoadSchemaCbk(const char *pszName,
     else if (inInterestingElement)
     {
         if (depthLevel == interestingDepthLevel + 1 &&
-            strncmp(pszName, "cm:", 3) == 0)
+            STARTS_WITH(pszName, "cm:"))
         {
             pszName += 3;
             if (poCurLayer->poFeatureDefn->GetFieldIndex(pszName) < 0)
diff --git a/ogr/ogrsf_frmts/sxf/ogr_sxf.h b/ogr/ogrsf_frmts/sxf/ogr_sxf.h
index 4dcf01d..97ebd85 100644
--- a/ogr/ogrsf_frmts/sxf/ogr_sxf.h
+++ b/ogr/ogrsf_frmts/sxf/ogr_sxf.h
@@ -30,8 +30,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_SXF_H_INCLUDED
-#define _OGR_SXF_H_INCLUDED
+#ifndef OGR_SXF_H_INCLUDED
+#define OGR_SXF_H_INCLUDED
 
 #include <set>
 #include <vector>
@@ -40,7 +40,7 @@
 #include "ogrsf_frmts.h"
 #include "org_sxf_defs.h"
 
-#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))
+#define CHECK_BIT(var,pos) (((var) & (1<<(pos))) != 0)
 #define TO_DEGREES 57.2957795130823208766
 #define TO_RADIANS 0.017453292519943295769
 
@@ -88,6 +88,8 @@ public:
 
     virtual GIntBig     GetFeatureCount(int bForce = TRUE);
     virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
     virtual OGRSpatialReference *GetSpatialRef();
     virtual const char* GetFIDColumn();
 
@@ -110,7 +112,7 @@ class OGRSXFDataSource : public OGRDataSource
     OGRLayer**          papoLayers;
     size_t              nLayers;
 
-    VSILFILE* fpSXF;    
+    VSILFILE* fpSXF;
     CPLMutex  *hIOMutex;
     void FillLayers(void);
     void CreateLayers();
@@ -129,11 +131,11 @@ public:
 
     virtual const char*     GetName() { return pszName; }
 
-    virtual int             GetLayerCount() { return nLayers; }
+    virtual int             GetLayerCount() { return static_cast<int>(nLayers); }
     virtual OGRLayer*       GetLayer( int );
 
     virtual int             TestCapability( const char * );
-    void                    CloseFile(); 
+    void                    CloseFile();
 };
 
 /************************************************************************/
@@ -151,4 +153,4 @@ class OGRSXFDriver : public OGRSFDriver
     int             TestCapability(const char *);
 };
 
-#endif 
+#endif
diff --git a/ogr/ogrsf_frmts/sxf/ogrsxfdatasource.cpp b/ogr/ogrsf_frmts/sxf/ogrsxfdatasource.cpp
index be15e01..0c30140 100644
--- a/ogr/ogrsf_frmts/sxf/ogrsxfdatasource.cpp
+++ b/ogr/ogrsf_frmts/sxf/ogrsxfdatasource.cpp
@@ -121,7 +121,7 @@ OGRSXFDataSource::~OGRSXFDataSource()
 /*                     CloseFile()                                      */
 /************************************************************************/
 void  OGRSXFDataSource::CloseFile()
-{ 
+{
     if (NULL != fpSXF)
     {
         VSIFCloseL( fpSXF );
@@ -173,7 +173,7 @@ int OGRSXFDataSource::Open( const char * pszFilename, int bUpdateIn)
         CPLError(CE_Warning, CPLE_OpenFailed, "SXF open file %s failed", pszFilename);
         return FALSE;
     }
-    
+
     //read header
     nFileHeaderSize = sizeof(SXFHeader);
     SXFHeader stSXFFileHeader;
@@ -213,7 +213,7 @@ int OGRSXFDataSource::Open( const char * pszFilename, int bUpdateIn)
     }
 
 
-    //read flags 
+    //read flags
     if (ReadSXFInformationFlags(fpSXF, oSXFPassport) != OGRERR_NONE)
     {
         CPLError(CE_Failure, CPLE_NotSupported, "SXF. Wrong state of the data.");
@@ -224,7 +224,7 @@ int OGRSXFDataSource::Open( const char * pszFilename, int bUpdateIn)
     if (oSXFPassport.informationFlags.bProjectionDataCompliance == false)
     {
         CPLError( CE_Failure, CPLE_NotSupported,
-                  "SXF. Data are not corresponde to the projection." );
+                  "SXF. Data does not correspond to the projection." );
         CloseFile();
         return FALSE;
     }
@@ -274,7 +274,7 @@ int OGRSXFDataSource::Open( const char * pszFilename, int bUpdateIn)
     //1. Create layers from RSC file or create default set of layers from osm.rsc
 
     if (soRSCRileName.empty())
-    { 
+    {
         CPLError(CE_Warning, CPLE_None, "RSC file for %s not exist", pszFilename);
     }
     else
@@ -306,7 +306,7 @@ int OGRSXFDataSource::Open( const char * pszFilename, int bUpdateIn)
     return TRUE;
 }
 
-OGRErr OGRSXFDataSource::ReadSXFDescription(VSILFILE* fpSXF, SXFPassport& passport)
+OGRErr OGRSXFDataSource::ReadSXFDescription(VSILFILE* fpSXFIn, SXFPassport& passport)
 {
     /* int nObjectsRead; */
 
@@ -314,12 +314,12 @@ OGRErr OGRSXFDataSource::ReadSXFDescription(VSILFILE* fpSXF, SXFPassport& passpo
     {
         //78
         GByte buff[62];
-        /* nObjectsRead = */ VSIFReadL(&buff, 62, 1, fpSXF);
+        /* nObjectsRead = */ VSIFReadL(&buff, 62, 1, fpSXFIn);
         char date[3] = { 0 };
 
         //read year
         memcpy(date, buff, 2);
-        passport.dtCrateDate.nYear = atoi(date);
+        passport.dtCrateDate.nYear = static_cast<GUInt16>(atoi(date));
         if (passport.dtCrateDate.nYear < 50)
             passport.dtCrateDate.nYear += 2000;
         else
@@ -327,11 +327,11 @@ OGRErr OGRSXFDataSource::ReadSXFDescription(VSILFILE* fpSXF, SXFPassport& passpo
 
         memcpy(date, buff + 2, 2);
 
-        passport.dtCrateDate.nMonth = atoi(date);
+        passport.dtCrateDate.nMonth = static_cast<GUInt16>(atoi(date));
 
         memcpy(date, buff + 4, 2);
 
-        passport.dtCrateDate.nDay = atoi(date);
+        passport.dtCrateDate.nDay = static_cast<GUInt16>(atoi(date));
 
         char szName[26] = { 0 };
         memcpy(szName, buff + 8, 24);
@@ -353,28 +353,28 @@ OGRErr OGRSXFDataSource::ReadSXFDescription(VSILFILE* fpSXF, SXFPassport& passpo
     {
         //96
         GByte buff[80];
-        /* nObjectsRead = */ VSIFReadL(&buff, 80, 1, fpSXF);
+        /* nObjectsRead = */ VSIFReadL(&buff, 80, 1, fpSXFIn);
         char date[5] = { 0 };
 
         //read year
         memcpy(date, buff, 4);
-        passport.dtCrateDate.nYear = atoi(date);
+        passport.dtCrateDate.nYear = static_cast<GUInt16>(atoi(date));
 
         memset(date, 0, 5);
         memcpy(date, buff + 4, 2);
 
-        passport.dtCrateDate.nMonth = atoi(date);
+        passport.dtCrateDate.nMonth = static_cast<GUInt16>(atoi(date));
 
         memcpy(date, buff + 6, 2);
 
-        passport.dtCrateDate.nDay = atoi(date);
+        passport.dtCrateDate.nDay = static_cast<GUInt16>(atoi(date));
 
         char szName[32] = { 0 };
         memcpy(szName, buff + 12, 32);
         char* pszRecoded = CPLRecode(szName + 2, "CP1251", CPL_ENC_UTF8);
         passport.sMapSheet = pszRecoded; //TODO: check the encoding in SXF created in Linux
         CPLFree(pszRecoded);
-        
+
         memcpy(&passport.nScale, buff + 44, 4);
         CPL_LSBPTR32(&passport.nScale);
 
@@ -385,14 +385,23 @@ OGRErr OGRSXFDataSource::ReadSXFDescription(VSILFILE* fpSXF, SXFPassport& passpo
         CPLFree(pszRecoded);
     }
 
+    SetMetadataItem("SHEET", passport.sMapSheet);
+    SetMetadataItem("SHEET_NAME", passport.sMapSheetName);
+    SetMetadataItem("SHEET_CREATE_DATE", CPLSPrintf( "%.2u-%.2u-%.4u",
+                    passport.dtCrateDate.nDay,
+                    passport.dtCrateDate.nMonth,
+                    passport.dtCrateDate.nYear ));
+    SetMetadataItem("SXF_VERSION", CPLSPrintf("%u", passport.version));
+    SetMetadataItem("SCALE", CPLSPrintf("1 : %u", passport.nScale));
+
     return OGRERR_NONE;
 }
 
-OGRErr OGRSXFDataSource::ReadSXFInformationFlags(VSILFILE* fpSXF, SXFPassport& passport)
+OGRErr OGRSXFDataSource::ReadSXFInformationFlags(VSILFILE* fpSXFIn, SXFPassport& passport)
 {
     /* int nObjectsRead; */
     GByte val[4];
-    /* nObjectsRead = */ VSIFReadL(&val, 4, 1, fpSXF);
+    /* nObjectsRead = */ VSIFReadL(&val, 4, 1, fpSXFIn);
 
     if (!(CHECK_BIT(val[0], 0) && CHECK_BIT(val[0], 1)))
     {
@@ -471,10 +480,10 @@ OGRErr OGRSXFDataSource::ReadSXFInformationFlags(VSILFILE* fpSXF, SXFPassport& p
 
 void OGRSXFDataSource::SetVertCS(const long iVCS, SXFPassport& passport)
 {
-    if (!CSLTestBoolean(CPLGetConfigOption("SXF_SET_VERTCS", "NO")))
+    if (!CPLTestBool(CPLGetConfigOption("SXF_SET_VERTCS", "NO")))
         return;
 
-    const long nEPSG = aoVCS[iVCS];
+    const int nEPSG = static_cast<int>(aoVCS[iVCS]);
 
     if (nEPSG == 0)
     {
@@ -486,13 +495,13 @@ void OGRSXFDataSource::SetVertCS(const long iVCS, SXFPassport& passport)
     OGRErr eImportFromEPSGErr = sr->importFromEPSG(nEPSG);
     if (eImportFromEPSGErr != OGRERR_NONE)
     {
-        CPLError( CE_Warning, CPLE_None, "SXF. Vertical coordinate system (SXF index %ld, EPSG %ld) import from EPSG error", iVCS, nEPSG);
+        CPLError( CE_Warning, CPLE_None, "SXF. Vertical coordinate system (SXF index %ld, EPSG %d) import from EPSG error", iVCS, nEPSG);
         return;
     }
 
     if (sr->IsVertical() != 1)
     {
-        CPLError( CE_Warning, CPLE_None, "SXF. Coordinate system (SXF index %ld, EPSG %ld) is not Vertical", iVCS, nEPSG);
+        CPLError( CE_Warning, CPLE_None, "SXF. Coordinate system (SXF index %ld, EPSG %d) is not Vertical", iVCS, nEPSG);
         return;
     }
 
@@ -500,11 +509,11 @@ void OGRSXFDataSource::SetVertCS(const long iVCS, SXFPassport& passport)
     OGRErr eSetVertCSErr = passport.stMapDescription.pSpatRef->SetVertCS(sr->GetAttrValue("VERT_CS"), sr->GetAttrValue("VERT_DATUM"));
     if (eSetVertCSErr != OGRERR_NONE)
     {
-        CPLError(CE_Warning, CPLE_None, "SXF. Vertical coordinate system (SXF index %ld, EPSG %ld) set error", iVCS, nEPSG);
+        CPLError(CE_Warning, CPLE_None, "SXF. Vertical coordinate system (SXF index %ld, EPSG %d) set error", iVCS, nEPSG);
         return;
     }
 }
-OGRErr OGRSXFDataSource::ReadSXFMapDescription(VSILFILE* fpSXF, SXFPassport& passport)
+OGRErr OGRSXFDataSource::ReadSXFMapDescription(VSILFILE* fpSXFIn, SXFPassport& passport)
 {
     /* int nObjectsRead;*/
     int i;
@@ -519,15 +528,15 @@ OGRErr OGRSXFDataSource::ReadSXFMapDescription(VSILFILE* fpSXF, SXFPassport& pas
     if (passport.version == 3)
     {
         short nNoObjClass, nNoSemClass;
-        /* nObjectsRead = */ VSIFReadL(&nNoObjClass, 2, 1, fpSXF);
-        /* nObjectsRead = */ VSIFReadL(&nNoSemClass, 2, 1, fpSXF);
+        /* nObjectsRead = */ VSIFReadL(&nNoObjClass, 2, 1, fpSXFIn);
+        /* nObjectsRead = */ VSIFReadL(&nNoSemClass, 2, 1, fpSXFIn);
         GByte baMask[8];
-        /* nObjectsRead = */ VSIFReadL(&baMask, 8, 1, fpSXF);
+        /* nObjectsRead = */ VSIFReadL(&baMask, 8, 1, fpSXFIn);
 
         int nCorners[8];
 
         //get projected corner coords
-        /* nObjectsRead = */ VSIFReadL(&nCorners, 32, 1, fpSXF);
+        /* nObjectsRead = */ VSIFReadL(&nCorners, 32, 1, fpSXFIn);
 
         for (i = 0; i < 8; i++)
         {
@@ -549,7 +558,7 @@ OGRErr OGRSXFDataSource::ReadSXFMapDescription(VSILFILE* fpSXF, SXFPassport& pas
             bIsX = !bIsX;
         }
         //get geographic corner coords
-        /* nObjectsRead = */ VSIFReadL(&nCorners, 32, 1, fpSXF);
+        /* nObjectsRead = */ VSIFReadL(&nCorners, 32, 1, fpSXFIn);
 
         for (i = 0; i < 8; i++)
         {
@@ -559,7 +568,7 @@ OGRErr OGRSXFDataSource::ReadSXFMapDescription(VSILFILE* fpSXF, SXFPassport& pas
     else if (passport.version == 4)
     {
         int nEPSG;
-        /* nObjectsRead = */ VSIFReadL(&nEPSG, 4, 1, fpSXF);
+        /* nObjectsRead = */ VSIFReadL(&nEPSG, 4, 1, fpSXFIn);
 
         if (nEPSG != 0)
         {
@@ -568,7 +577,7 @@ OGRErr OGRSXFDataSource::ReadSXFMapDescription(VSILFILE* fpSXF, SXFPassport& pas
         }
 
         double dfCorners[8];
-        /* nObjectsRead = */ VSIFReadL(&dfCorners, 64, 1, fpSXF);
+        /* nObjectsRead = */ VSIFReadL(&dfCorners, 64, 1, fpSXFIn);
 
         for (i = 0; i < 8; i++)
         {
@@ -591,11 +600,11 @@ OGRErr OGRSXFDataSource::ReadSXFMapDescription(VSILFILE* fpSXF, SXFPassport& pas
 
         }
         //get geographic corner coords
-        /* nObjectsRead = */ VSIFReadL(&dfCorners, 64, 1, fpSXF);
+        /* nObjectsRead = */ VSIFReadL(&dfCorners, 64, 1, fpSXFIn);
 
         for (i = 0; i < 8; i++)
         {
-            passport.stMapDescription.stGeoCoords[i] = dfCorners[i] * TO_DEGREES; // to degree 
+            passport.stMapDescription.stGeoCoords[i] = dfCorners[i] * TO_DEGREES; // to degree
         }
 
     }
@@ -606,7 +615,7 @@ OGRErr OGRSXFDataSource::ReadSXFMapDescription(VSILFILE* fpSXF, SXFPassport& pas
     }
 
     GByte anData[8] = { 0 };
-    /* nObjectsRead = */ VSIFReadL(&anData, 8, 1, fpSXF);
+    /* nObjectsRead = */ VSIFReadL(&anData, 8, 1, fpSXFIn);
     long iEllips = anData[0];
     long iVCS = anData[1];
     long iProjSys = anData[2];
@@ -617,7 +626,7 @@ OGRErr OGRSXFDataSource::ReadSXFMapDescription(VSILFILE* fpSXF, SXFPassport& pas
 
     if (passport.version == 3)
     {
-        switch (anData[5])
+        switch (anData[4])
         {
         case 1:
             passport.stMapDescription.eUnitInPlan = SXF_COORD_MU_DECIMETRE;
@@ -640,20 +649,20 @@ OGRErr OGRSXFDataSource::ReadSXFMapDescription(VSILFILE* fpSXF, SXFPassport& pas
         }
 
 
-        VSIFSeekL(fpSXF, 212, SEEK_SET);
+        VSIFSeekL(fpSXFIn, 212, SEEK_SET);
         struct _buff{
             GUInt32 nRes;
             GInt16 anFrame[8];
             GUInt32 nFrameCode;
         } buff;
-        /* nObjectsRead = */ VSIFReadL(&buff, 20, 1, fpSXF);
+        /* nObjectsRead = */ VSIFReadL(&buff, 20, 1, fpSXFIn);
         passport.stMapDescription.nResolution = buff.nRes; //resolution
 
         for (i = 0; i < 8; i++)
             passport.stMapDescription.stFrameCoords[i] = buff.anFrame[i];
 
         int anParams[5];
-        /* nObjectsRead = */ VSIFReadL(&anParams, 20, 1, fpSXF);
+        /* nObjectsRead = */ VSIFReadL(&anParams, 20, 1, fpSXFIn);
 
         if (anParams[0] != -1)
             dfProjScale = double(anParams[0]) / 100000000.0;
@@ -672,7 +681,7 @@ OGRErr OGRSXFDataSource::ReadSXFMapDescription(VSILFILE* fpSXF, SXFPassport& pas
         passport.stMapDescription.dfFalseEasting = 0;
 
 
-        //adfPrjParams[0] = double(anParams[0]) / 100000000.0; // to radians  
+        //adfPrjParams[0] = double(anParams[0]) / 100000000.0; // to radians
         //adfPrjParams[1] = double(anParams[1]) / 100000000.0;
         //adfPrjParams[2] = double(anParams[2]) / 100000000.0;
         //adfPrjParams[3] = double(anParams[3]) / 100000000.0;
@@ -684,7 +693,7 @@ OGRErr OGRSXFDataSource::ReadSXFMapDescription(VSILFILE* fpSXF, SXFPassport& pas
     }
     else if (passport.version == 4)
     {
-        switch (anData[5])
+        switch (anData[4])
         {
         case 64:
             passport.stMapDescription.eUnitInPlan = SXF_COORD_MU_RADIAN;
@@ -697,16 +706,16 @@ OGRErr OGRSXFDataSource::ReadSXFMapDescription(VSILFILE* fpSXF, SXFPassport& pas
             break;
         }
 
-        VSIFSeekL(fpSXF, 312, SEEK_SET);
+        VSIFSeekL(fpSXFIn, 312, SEEK_SET);
         GUInt32 buff[10];
-        /* nObjectsRead = */ VSIFReadL(&buff, 40, 1, fpSXF);
+        /* nObjectsRead = */ VSIFReadL(&buff, 40, 1, fpSXFIn);
 
         passport.stMapDescription.nResolution = buff[0]; //resolution
         for (i = 0; i < 8; i++)
             passport.stMapDescription.stFrameCoords[i] = buff[1 + i];
 
         double adfParams[6];
-        /* nObjectsRead = */ VSIFReadL(&adfParams, 48, 1, fpSXF);
+        /* nObjectsRead = */ VSIFReadL(&adfParams, 48, 1, fpSXFIn);
 
         if (adfParams[1] != -1)
             dfProjScale = adfParams[1];
@@ -715,7 +724,7 @@ OGRErr OGRSXFDataSource::ReadSXFMapDescription(VSILFILE* fpSXF, SXFPassport& pas
         passport.stMapDescription.dfFalseNorthing = adfParams[4];
         passport.stMapDescription.dfFalseEasting = adfParams[5];
 
-        //adfPrjParams[0] = adfParams[0]; // to radians 
+        //adfPrjParams[0] = adfParams[0]; // to radians
         //adfPrjParams[1] = adfParams[1];
         //adfPrjParams[2] = adfParams[2];
         //adfPrjParams[3] = adfParams[3];
@@ -808,8 +817,16 @@ OGRErr OGRSXFDataSource::ReadSXFMapDescription(VSILFILE* fpSXF, SXFPassport& pas
         SetVertCS(iVCS, passport);
         return eErr;
     }
+    else if (iEllips == 9 && iProjSys == 33 &&
+        passport.stMapDescription.eUnitInPlan == SXF_COORD_MU_DEGREE)
+    {
+        passport.stMapDescription.pSpatRef = new OGRSpatialReference(SRS_WKT_WGS84);
+        OGRErr eErr = OGRERR_NONE;
+        SetVertCS(iVCS, passport);
+        return eErr;
+    }
 
-    //TODO: Need to normalise more SRS:
+    //TODO: Need to normalize more SRS:
     //PAN_PROJ_WAG1
     //PAN_PROJ_MERCAT
     //PAN_PROJ_PS
@@ -848,13 +865,13 @@ void OGRSXFDataSource::FillLayers()
     if (oSXFPassport.version == 3)
     {
         VSIFSeekL(fpSXF, 288, SEEK_SET);
-        nObjectsRead = VSIFReadL(&nRecordCountMax, 4, 1, fpSXF);
+        nObjectsRead = static_cast<int>(VSIFReadL(&nRecordCountMax, 4, 1, fpSXF));
         nOffset = 300;
     }
     else if (oSXFPassport.version == 4)
     {
         VSIFSeekL(fpSXF, 440, SEEK_SET);
-        nObjectsRead = VSIFReadL(&nRecordCountMax, 4, 1, fpSXF);
+        nObjectsRead = static_cast<int>(VSIFReadL(&nRecordCountMax, 4, 1, fpSXF));
         nOffset = 452;
     }
     /* else nOffset and nObjectsRead will be 0 */
@@ -870,7 +887,7 @@ void OGRSXFDataSource::FillLayers()
     for (nFID = 0; nFID < nRecordCountMax; nFID++)
     {
         GInt32 buff[6];
-        nObjectsRead = VSIFReadL(&buff, 24, 1, fpSXF);
+        nObjectsRead = static_cast<int>(VSIFReadL(&buff, 24, 1, fpSXF));
 
         if (nObjectsRead != 1 || buff[0] != IDSXFOBJ)
         {
@@ -949,7 +966,7 @@ void OGRSXFDataSource::CreateLayers()
     nLayers++;
 
     //default codes
-    for (size_t i = 1000000001; i < 1000000015; i++)
+    for (unsigned int i = 1000000001; i < 1000000015; i++)
     {
         pLayer->AddClassifyCode(i);
     }
@@ -1203,7 +1220,7 @@ void OGRSXFDataSource::CreateLayers(VSILFILE* fpRSC)
 
     RSCHeader stRSCFileHeader;
     int nFileHeaderSize = sizeof(stRSCFileHeader);
-    int nObjectsRead = VSIFReadL(&stRSCFileHeader, nFileHeaderSize, 1, fpRSC);
+    int nObjectsRead = static_cast<int>(VSIFReadL(&stRSCFileHeader, nFileHeaderSize, 1, fpRSC));
 
     if (nObjectsRead != 1)
     {
@@ -1218,7 +1235,7 @@ void OGRSXFDataSource::CreateLayers(VSILFILE* fpRSC)
         char szShortName[16];
         GByte nNo;
         GByte nPos;
-        GUInt16 nSematicCount;
+        GUInt16 nSemanticCount;
     };
 
     GUInt32 i;
@@ -1234,12 +1251,14 @@ void OGRSXFDataSource::CreateLayers(VSILFILE* fpRSC)
         VSIFReadL(&LAYER, nLayerStructSize, 1, fpRSC);
 
         papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
-        bool bLayerFullName = CSLTestBoolean(CPLGetConfigOption("SXF_LAYER_FULLNAME", "NO"));
+        bool bLayerFullName = CPLTestBool(CPLGetConfigOption("SXF_LAYER_FULLNAME", "NO"));
 
         char* pszRecoded;
         if (bLayerFullName)
         {
-            if (stRSCFileHeader.nFontEnc == 125)
+            if(LAYER.szName[0] == 0)
+                pszRecoded = CPLStrdup("Unnamed");
+            else if (stRSCFileHeader.nFontEnc == 125)
                 pszRecoded = CPLRecode(LAYER.szName, "KOI8-R", CPL_ENC_UTF8);
             else if (stRSCFileHeader.nFontEnc == 126)
                 pszRecoded = CPLRecode(LAYER.szName, "CP1251", CPL_ENC_UTF8);
@@ -1250,7 +1269,9 @@ void OGRSXFDataSource::CreateLayers(VSILFILE* fpRSC)
         }
         else
         {
-            if (stRSCFileHeader.nFontEnc == 125)
+            if(LAYER.szShortName[0] == 0)
+                pszRecoded = CPLStrdup("Unnamed");
+            else if (stRSCFileHeader.nFontEnc == 125)
                 pszRecoded = CPLRecode(LAYER.szShortName, "KOI8-R", CPL_ENC_UTF8);
             else if (stRSCFileHeader.nFontEnc == 126)
                 pszRecoded = CPLRecode(LAYER.szShortName, "CP1251", CPL_ENC_UTF8);
@@ -1289,7 +1310,7 @@ void OGRSXFDataSource::CreateLayers(VSILFILE* fpRSC)
     nOffset = stRSCFileHeader.Objects.nOffset;
     _object OBJECT;
 
-    for (unsigned i = 0; i < stRSCFileHeader.Objects.nRecordCount; ++i)
+    for (unsigned j = 0; j < stRSCFileHeader.Objects.nRecordCount; ++j)
     {
         VSIFReadL(&OBJECT, sizeof(_object), 1, fpRSC);
 
@@ -1297,12 +1318,15 @@ void OGRSXFDataSource::CreateLayers(VSILFILE* fpRSC)
         if (NULL != pLayer)
         {
             char* pszRecoded;
-            if (stRSCFileHeader.nFontEnc == 125)
+            if(OBJECT.szName[0] == 0)
+                pszRecoded = CPLStrdup("Unnamed");
+            else if (stRSCFileHeader.nFontEnc == 125)
                 pszRecoded = CPLRecode(OBJECT.szName, "KOI8-R", CPL_ENC_UTF8);
             else if (stRSCFileHeader.nFontEnc == 126)
                 pszRecoded = CPLRecode(OBJECT.szName, "CP1251", CPL_ENC_UTF8);
             else
                 pszRecoded = CPLStrdup(OBJECT.szName); //already in  CPL_ENC_UTF8
+
             pLayer->AddClassifyCode(OBJECT.nClassifyCode, pszRecoded);
             //printf("%d;%s\n", OBJECT.nClassifyCode, OBJECT.szName);
             CPLFree(pszRecoded);
diff --git a/ogr/ogrsf_frmts/sxf/ogrsxfdriver.cpp b/ogr/ogrsf_frmts/sxf/ogrsxfdriver.cpp
index 92a3a80..79c31b2 100644
--- a/ogr/ogrsf_frmts/sxf/ogrsxfdriver.cpp
+++ b/ogr/ogrsf_frmts/sxf/ogrsxfdriver.cpp
@@ -36,7 +36,7 @@
 CPL_CVSID("$Id: ogrsxfdriver.cpp  $");
 
 
-extern "C" void RegisterOGRSXF();  
+extern "C" void RegisterOGRSXF();
 
 /************************************************************************/
 /*                       ~OGRSXFDriver()                         */
@@ -71,7 +71,7 @@ OGRDataSource *OGRSXFDriver::Open( const char * pszFilename, int bUpdate )
     if (!EQUAL(CPLGetExtension(pszFilename), "sxf") ||
         VSIStatL(pszFilename, &sStatBuf) != 0 ||
         !VSI_ISREG(sStatBuf.st_mode))
-        return FALSE;
+        return NULL;
 
     OGRSXFDataSource   *poDS = new OGRSXFDataSource();
 
@@ -92,7 +92,7 @@ OGRErr OGRSXFDriver::DeleteDataSource(const char* pszName)
 {
     int iExt;
     //TODO: add more extensions if aplicable
-    static const char *apszExtensions[] = { "szf", "rsc", "SZF", "RSC", NULL };
+    static const char * const apszExtensions[] = { "szf", "rsc", "SZF", "RSC", NULL };
 
     VSIStatBufL sStatBuf;
     if (VSIStatL(pszName, &sStatBuf) != 0)
@@ -134,11 +134,12 @@ int OGRSXFDriver::TestCapability( const char * pszCap )
 void RegisterOGRSXF()
 {
     OGRSFDriver* poDriver = new OGRSXFDriver;
+
     poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                "Storage and eXchange Format" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                "drv_sxf.html" );
+                               "Storage and eXchange Format" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_sxf.html" );
     poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "sxf" );
+
     OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver(poDriver);
 }
 
diff --git a/ogr/ogrsf_frmts/sxf/ogrsxflayer.cpp b/ogr/ogrsf_frmts/sxf/ogrsxflayer.cpp
index 5459cc5..36a9f76 100644
--- a/ogr/ogrsf_frmts/sxf/ogrsxflayer.cpp
+++ b/ogr/ogrsf_frmts/sxf/ogrsxflayer.cpp
@@ -30,7 +30,6 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#define  _USE_MATH_DEFINES
 
 #include "ogr_sxf.h"
 #include "cpl_conv.h"
@@ -59,7 +58,7 @@ OGRSXFLayer::OGRSXFLayer(VSILFILE* fp, CPLMutex** hIOMutex, GByte nID, const cha
     poFeatureDefn = new OGRFeatureDefn(pszLayerName);
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
-    
+
     poFeatureDefn->SetGeomType(wkbUnknown);
     if (poFeatureDefn->GetGeomFieldCount() != 0)
         poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(stSXFMapDescription.pSpatRef);
@@ -68,22 +67,22 @@ OGRSXFLayer::OGRSXFLayer(VSILFILE* fp, CPLMutex** hIOMutex, GByte nID, const cha
     //oGeomFieldDefn.SetSpatialRef(stSXFMapDescription.pSpatRef);
     //poFeatureDefn->AddGeomFieldDefn(&oGeomFieldDefn);
 
-    OGRFieldDefn oFIDField = OGRFieldDefn(sFIDColumn_, OFTInteger);
+    OGRFieldDefn oFIDField(sFIDColumn_, OFTInteger);
     poFeatureDefn->AddFieldDefn(&oFIDField);
 
-    OGRFieldDefn oClCodeField = OGRFieldDefn( "CLCODE", OFTInteger );
+    OGRFieldDefn oClCodeField( "CLCODE", OFTInteger );
     oClCodeField.SetWidth(10);
     poFeatureDefn->AddFieldDefn( &oClCodeField );
 
-    OGRFieldDefn oClNameField = OGRFieldDefn( "CLNAME", OFTString );
+    OGRFieldDefn oClNameField( "CLNAME", OFTString );
     oClNameField.SetWidth(32);
     poFeatureDefn->AddFieldDefn( &oClNameField );
 
-    OGRFieldDefn oNumField = OGRFieldDefn( "OBJECTNUMB", OFTInteger );
+    OGRFieldDefn oNumField( "OBJECTNUMB", OFTInteger );
     oNumField.SetWidth(10);
     poFeatureDefn->AddFieldDefn( &oNumField );
 
-    OGRFieldDefn oAngField = OGRFieldDefn("ANGLE", OFTReal);
+    OGRFieldDefn oAngField("ANGLE", OFTReal);
     poFeatureDefn->AddFieldDefn(&oAngField);
 
     OGRFieldDefn  oTextField( "TEXT", OFTString );
@@ -130,7 +129,7 @@ int OGRSXFLayer::AddRecord(long nFID, unsigned nClassCode, vsi_l_offset nOffset,
     if (mnClassificators.empty() || mnClassificators.find(nClassCode) != mnClassificators.end())
     {
         mnRecordDesc[nFID] = nOffset;
-        //add addtionals semantics (attribute fields)
+        // Add additional semantics (attribute fields).
         if (bHasSemantic)
         {
             size_t offset = 0;
@@ -140,7 +139,7 @@ int OGRSXFLayer::AddRecord(long nFID, unsigned nClassCode, vsi_l_offset nOffset,
                 SXFRecordAttributeInfo stAttrInfo;
                 bool bAddField = false;
                 size_t nCurrOff = 0;
-                int nReadObj = VSIFReadL(&stAttrInfo, 4, 1, fpSXF);
+                int nReadObj = static_cast<int>(VSIFReadL(&stAttrInfo, 4, 1, fpSXF));
                 if (nReadObj == 1)
                 {
                     CPLString oFieldName;
@@ -250,7 +249,7 @@ int OGRSXFLayer::AddRecord(long nFID, unsigned nClassCode, vsi_l_offset nOffset,
                         }
                         GUInt32 scale2;
                         VSIFReadL(&scale2, sizeof(GUInt32), 1, fpSXF);
-                        CPL_LSBUINT32PTR(&scale2);
+                        CPL_LSBPTR32(&scale2);
 
                         offset += scale2;
                         nCurrOff = scale2;
@@ -292,7 +291,7 @@ OGRErr OGRSXFLayer::SetNextByIndex(GIntBig nIndex)
 
 OGRFeature *OGRSXFLayer::GetFeature(GIntBig nFID)
 {
-    std::map<long, vsi_l_offset>::const_iterator IT = mnRecordDesc.find(nFID);
+    std::map<long, vsi_l_offset>::const_iterator IT = mnRecordDesc.find(static_cast<long>(nFID));
     if (IT != mnRecordDesc.end())
     {
         VSIFSeekL(fpSXF, IT->second, SEEK_SET);
@@ -420,9 +419,9 @@ int OGRSXFLayer::TestCapability( const char * pszCap )
 /*                                TranslateXYH()                        */
 /************************************************************************/
 /****
- * TODO : Take into account informations given in the passport
- * like unit of mesurement, type and dimensions (integer, float, double) of coordinate,
- * the vector format ....
+ * TODO : Take into account information given in the passport
+ * like unit of measurement, type and dimensions (integer, float, double) of
+ * coordinate, the vector format, etc.
  */
 
 GUInt32 OGRSXFLayer::TranslateXYH(const SXFRecordDescription& certifInfo,
@@ -440,9 +439,9 @@ GUInt32 OGRSXFLayer::TranslateXYH(const SXFRecordDescription& certifInfo,
             return 0;
         GInt16 x, y;
         memcpy(&y, psBuff, 2);
-        CPL_LSBINT16PTR(&y);
+        CPL_LSBPTR16(&y);
         memcpy(&x, psBuff + 2, 2);
-        CPL_LSBINT16PTR(&x);
+        CPL_LSBPTR16(&x);
 
         if (stSXFMapDescription.bIsRealCoordinates)
         {
@@ -609,7 +608,7 @@ OGRFeature *OGRSXFLayer::GetNextRawFeature(long nFID)
     SXFRecordHeader stRecordHeader;
     int nObjectRead;
 
-    nObjectRead = VSIFReadL(&stRecordHeader, sizeof(SXFRecordHeader), 1, fpSXF);
+    nObjectRead = static_cast<int>(VSIFReadL(&stRecordHeader, sizeof(SXFRecordHeader), 1, fpSXF));
 
     if (nObjectRead != 1 || stRecordHeader.nID != IDSXFOBJ)
     {
@@ -680,6 +679,7 @@ OGRFeature *OGRSXFLayer::GetNextRawFeature(long nFID)
         eGeomType = SXF_GT_Point;
     else if (code == 0x03) // xxxx0011
         eGeomType = SXF_GT_Text;
+#ifdef not_possible_given_above_code /* see below code too if re-enabling this */
     //beginning 4.0
     else if (code == 0x04) // xxxx0100
     {
@@ -687,6 +687,7 @@ OGRFeature *OGRSXFLayer::GetNextRawFeature(long nFID)
             "SXF. Not support type.");
         eGeomType = SXF_GT_Vector;
     }
+#endif
     else if (code == 0x05) // xxxx0101
         eGeomType = SXF_GT_TextTemplate;
     else if (code == 0x21)
@@ -711,7 +712,7 @@ OGRFeature *OGRSXFLayer::GetNextRawFeature(long nFID)
     }
     stCertInfo.nSubObjectCount = stRecordHeader.nSubObjectCount;
 
-    bool bFloatType = 0, bBigType = 0;
+    bool bFloatType(false), bBigType(false);
     bool b3D(true);
     if (m_nSXFFormatVer == 3)
     {
@@ -764,10 +765,10 @@ OGRFeature *OGRSXFLayer::GetNextRawFeature(long nFID)
     OGRFeature *poFeature = NULL;
     if( stRecordHeader.nGeometryLength > 100 * 1024 * 1024 )
         return NULL;
-    char * recordCertifBuf = (char *)VSIMalloc(stRecordHeader.nGeometryLength);
+    char * recordCertifBuf = (char *)VSI_MALLOC_VERBOSE(stRecordHeader.nGeometryLength);
     if( recordCertifBuf == NULL )
         return NULL;
-    nObjectRead = VSIFReadL(recordCertifBuf, stRecordHeader.nGeometryLength, 1, fpSXF);
+    nObjectRead = static_cast<int>(VSIFReadL(recordCertifBuf, stRecordHeader.nGeometryLength, 1, fpSXF));
     if (nObjectRead != 1)
     {
         CPLError(CE_Failure, CPLE_FileIO,
@@ -793,6 +794,7 @@ OGRFeature *OGRSXFLayer::GetNextRawFeature(long nFID)
         poFeature = TranslateVetorAngle(stCertInfo, recordCertifBuf,
             stRecordHeader.nGeometryLength);
     }
+#ifdef not_possible_given_above_code
     else if (eGeomType == SXF_GT_Vector )
     {
       CPLError( CE_Warning, CPLE_NotSupported,
@@ -800,6 +802,7 @@ OGRFeature *OGRSXFLayer::GetNextRawFeature(long nFID)
       CPLFree(recordCertifBuf);
       return NULL;
     }
+#endif
     else if (eGeomType == SXF_GT_TextTemplate ) // TODO realise this
     {
       CPLError( CE_Warning, CPLE_NotSupported,
@@ -851,7 +854,7 @@ OGRFeature *OGRSXFLayer::GetNextRawFeature(long nFID)
             delete poFeature;
             return NULL;
         }
-        char * psSemanticsdBuf = (char *)VSIMalloc(nSemanticsSize);
+        char * psSemanticsdBuf = (char *)VSI_MALLOC_VERBOSE(nSemanticsSize);
         if( psSemanticsdBuf == NULL )
         {
             CPLFree(recordCertifBuf);
@@ -859,7 +862,7 @@ OGRFeature *OGRSXFLayer::GetNextRawFeature(long nFID)
             return NULL;
         }
         char * psSemanticsdBufOrig = psSemanticsdBuf;
-        nObjectRead = VSIFReadL(psSemanticsdBuf, nSemanticsSize, 1, fpSXF);
+        nObjectRead = static_cast<int>(VSIFReadL(psSemanticsdBuf, nSemanticsSize, 1, fpSXF));
         if (nObjectRead == 1)
         {
             size_t offset = 0;
@@ -1025,7 +1028,7 @@ OGRFeature *OGRSXFLayer::GetNextRawFeature(long nFID)
                         break;
                     }
                     memcpy(&scale2, psSemanticsdBuf + offset, sizeof(GUInt32));
-                    CPL_LSBUINT32PTR(&scale2);
+                    CPL_LSBPTR32(&scale2);
                     /* FIXME add ?: offset += sizeof(GUInt32); */
                     if( scale2 > nSemanticsSize - 1 || nSemanticsSize - (scale2 + 1) < offset )
                     {
@@ -1105,11 +1108,11 @@ OGRFeature *OGRSXFLayer::TranslatePoint(const SXFRecordDescription& certifInfo,
 
         GUInt16 nSubObj;
         memcpy(&nSubObj, psRecordBuf + nOffset, 2);
-        CPL_LSBUINT16PTR(&nSubObj);
+        CPL_LSBPTR16(&nSubObj);
 
         GUInt16 nCoords;
         memcpy(&nCoords, psRecordBuf + nOffset + 2, 2);
-        CPL_LSBUINT16PTR(&nCoords);
+        CPL_LSBPTR16(&nCoords);
 
         nOffset +=4;
 
@@ -1157,7 +1160,6 @@ OGRFeature *OGRSXFLayer::TranslateLine(const SXFRecordDescription& certifInfo,
     double dfY = 1.0;
     double dfZ = 0.0;
     GUInt32 nOffset = 0;
-    GUInt32 count;
     GUInt32 nDelta = 0;
 
     //OGRFeatureDefn *fd = poFeatureDefn->Clone();
@@ -1171,7 +1173,7 @@ OGRFeature *OGRSXFLayer::TranslateLine(const SXFRecordDescription& certifInfo,
 
     OGRLineString* poLS = new OGRLineString();
 
-    for(count=0 ; count <  certifInfo.nPointCount ; count++)
+    for(GUInt32 count=0 ; count <  certifInfo.nPointCount ; count++)
     {
         const char * psCoords = psRecordBuf + nOffset ;
 
@@ -1205,11 +1207,11 @@ OGRFeature *OGRSXFLayer::TranslateLine(const SXFRecordDescription& certifInfo,
 
         GUInt16 nSubObj;
         memcpy(&nSubObj, psRecordBuf + nOffset, 2);
-        CPL_LSBUINT16PTR(&nSubObj);
+        CPL_LSBPTR16(&nSubObj);
 
         GUInt16 nCoords;
         memcpy(&nCoords, psRecordBuf + nOffset + 2, 2);
-        CPL_LSBUINT16PTR(&nCoords);
+        CPL_LSBPTR16(&nCoords);
 
         nOffset +=4;
 
@@ -1328,7 +1330,6 @@ OGRFeature *OGRSXFLayer::TranslatePolygon(const SXFRecordDescription& certifInfo
     double dfY = 1.0;
     double dfZ = 0.0;
     GUInt32 nOffset = 0;
-    GUInt32 count;
     GUInt32 nDelta = 0;
 
     OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
@@ -1336,7 +1337,7 @@ OGRFeature *OGRSXFLayer::TranslatePolygon(const SXFRecordDescription& certifInfo
     OGRLineString* poLS = new OGRLineString();
 
 /*---------------------- Reading Primary Polygon --------------------------------*/
-    for(count=0 ; count <  certifInfo.nPointCount ; count++)
+    for(GUInt32 count=0 ; count <  certifInfo.nPointCount ; count++)
     {
         const char * psBuf = psRecordBuf + nOffset;
         if (certifInfo.bDim == 1)
@@ -1372,16 +1373,28 @@ OGRFeature *OGRSXFLayer::TranslatePolygon(const SXFRecordDescription& certifInfo
 
         GUInt16 nSubObj;
         memcpy(&nSubObj, psRecordBuf + nOffset, 2);
-        CPL_LSBUINT16PTR(&nSubObj);
+        CPL_LSBPTR16(&nSubObj);
 
         GUInt16 nCoords;
         memcpy(&nCoords, psRecordBuf + nOffset + 2, 2);
-        CPL_LSBUINT16PTR(&nCoords);
+        CPL_LSBPTR16(&nCoords);
+
+        // TODO: Is this really what the buffer size should be?
+        if (nCoords * nDelta != nBufLen - nOffset + 2  - 6)
+        {
+            CPLError(CE_Warning, CPLE_FileIO,
+                     "SXF raw feature size incorrect.  "
+                     "%d %d",
+                   nCoords * nDelta,
+                   nBufLen - nOffset + 2 - 6
+                   );
+            // TODO: How best to gracefully exit and report an issue?
+            // break; or cleanup and return NULL?
+        }
 
         nOffset +=4;
 
-        int i;
-        for (i=0; i < nCoords ; i++)
+        for (int i=0; i < nCoords ; i++)
         {
             const char * psCoords = psRecordBuf + nOffset ;
             if (certifInfo.bDim == 1)
@@ -1401,7 +1414,7 @@ OGRFeature *OGRSXFLayer::TranslatePolygon(const SXFRecordDescription& certifInfo
             poLS->addPoint( dfX, dfY, dfZ );
         }
 
-        OGRLinearRing *poLR = new OGRLinearRing();
+        poLR = new OGRLinearRing();
         poLR->addSubLineString( poLS, 0 );
 
         poPoly->addRingDirectly( poLR );
@@ -1411,8 +1424,8 @@ OGRFeature *OGRSXFLayer::TranslatePolygon(const SXFRecordDescription& certifInfo
     delete poLS;
 
 /*****
- * TODO : 
- *          - Translate graphics 
+ * TODO :
+ *          - Translate graphics
  *          - Translate 3D vector
  */
     return poFeature;
@@ -1460,7 +1473,7 @@ OGRFeature *OGRSXFLayer::TranslateText(const SXFRecordDescription& certifInfo,
 
 /*------------------     READING TEXT VALUE   ---------------------------------------*/
 
-    if ( certifInfo.nSubObjectCount == 0 && certifInfo.bHasTextSign == true)
+    if ( certifInfo.nSubObjectCount == 0 && certifInfo.bHasTextSign )
     {
         if( nOffset + 1 > nBufLen )
             return poFeature;
@@ -1475,15 +1488,17 @@ OGRFeature *OGRSXFLayer::TranslateText(const SXFRecordDescription& certifInfo,
         pszTextBuf[nTextL] = '\0';
 
         //TODO: Check encoding from sxf
-        poFeature->SetField("TEXT", pszTextBuf);
+        char* pszRecoded = CPLRecode(pszTextBuf, "CP1251", CPL_ENC_UTF8);
+        poFeature->SetField("TEXT", pszRecoded);
+        CPLFree(pszRecoded);
 
         CPLFree( pszTextBuf );
     }
 
 
 /*****
- * TODO : 
- *          - Translate graphics 
+ * TODO :
+ *          - Translate graphics
  *          - Translate 3D vector
  */
 
diff --git a/ogr/ogrsf_frmts/sxf/org_sxf_defs.h b/ogr/ogrsf_frmts/sxf/org_sxf_defs.h
index 22ddba2..9f2ea5b 100644
--- a/ogr/ogrsf_frmts/sxf/org_sxf_defs.h
+++ b/ogr/ogrsf_frmts/sxf/org_sxf_defs.h
@@ -2,7 +2,7 @@
  * $Id: org_sxf_defs.h  $
  *
  * Project:  SXF Translator
- * Purpose:  Include file defining Records Structures for file reading and 
+ * Purpose:  Include file defining Records Structures for file reading and
  *           basic constants.
  * Author:   Ben Ahmed Daho Ali, bidandou(at)yahoo(dot)fr
  *           Dmitry Baryshnikov, polimax at mail.ru
@@ -31,48 +31,48 @@
  * DEALINGS IN THE SOFTWARE.
  *
  ******************************************************************************
- * Structure of the SXF file : 
+ * Structure of the SXF file :
  * ----------------------
- *    - Header 
+ *    - Header
  *    - Passport
  *    - Descriptor of data
- *    - Records 
- *         - Title of the record 
- *         - The certificate of the object (the geomety)
+ *    - Records
+ *         - Title of the record
+ *         - The certificate of the object (the geometry)
  *             - sub-objects
  *             - The graphic description of object
  *             - The description of the vector of the tying of the 3d- model of object
  *         - Semantics of object
  *
- * Notes  : 
+ * Notes  :
  * -------
  * Note 1.  Flag of the state of data (2 bits):
  * xxxxxx11- given in the state e (size of the exchange of data).
  *
  * Note 2.  Flag of the correspondence to projection (1 bit):
- * xxxxx0xx - do not correspond to the projection (i.e. map it can have turning 
+ * xxxxx0xx - do not correspond to the projection (i.e. map it can have turning
  *                 relative to true position and certain deformation);
  * xxxxx1xx - correspond to projection.
  *
  * Note 3.  Flag of the presence of real coordinates (2 bits):
- * xxx00xxx - entire certificate of objects is represented in the conditional 
+ * xxx00xxx - entire certificate of objects is represented in the conditional
  *                                 system of coordinates (in the samples);
- * xxx11xxx - entire certificate of objects is represented in the real coordinates 
- *            in the locality in accordance with the specifications of sheet 
- *            (projection, the coordinate system, unit of measurement), 
- *            the data about the scale and the discretion of digitization bear 
+ * xxx11xxx - entire certificate of objects is represented in the real coordinates
+ *            in the locality in accordance with the specifications of sheet
+ *            (projection, the coordinate system, unit of measurement),
+ *            the data about the scale and the discretion of digitization bear
  *            reference nature.
  *
  * Note 4. Flag of the method of coding (2 bits):
- * x00xxxxx - the classification codes of objects and semantic characteristics 
- *          are represented by the decimal numbers, recorded in the binary 
- *          form (for example: the code of the object �32100000� will be written 
- *          down in the form 0x01E9CEA0, the code of semantics �253� - in the form 0x00FD).
+ * x00xxxxx - the classification codes of objects and semantic characteristics
+ *          are represented by the decimal numbers, recorded in the binary
+ *          form (for example: the code of the object "32100000" will be written
+ *          down in the form 0x01E9CEA0, the code of semantics "253" - in the form 0x00FD).
  *
  * Note 5. Table of generalization (1 bit):
- * 0xxxxxxx - the level of generalization is assigned according to the table of the 
+ * 0xxxxxxx - the level of generalization is assigned according to the table of the
  *           general maps (it is described in Table 2.4);
- * 1xxxxxxx - noload condition the level of generalization is assigned according to 
+ * 1xxxxxxx - noload condition the level of generalization is assigned according to
  *           the table of the large-scale maps (it is described in Table 2.5).
  *
  * Note 6.  Flag of coding the texts of the Texts objects (1 bytes):
@@ -81,10 +81,10 @@
  * 2- in the coding KOI-8 (Unix).
  *
  * Note 7.  Flag of the accuracy of coordinates (1 bytes):
- * 0 � are not established;
- * 1 � the increased accuracy of storage of coordinates (meters, radians or degrees);
- * 2 � of coordinate are recorded with an accuracy to centimeter (meters, 2 signs after comma);
- * 3 � coordinates are recorded with an accuracy to millimeter (meters, 3 sign after comma).
+ * 0 - are not established;
+ * 1 - the increased accuracy of storage of coordinates (meters, radians or degrees);
+ * 2 - of coordinate are recorded with an accuracy to centimeter (meters, 2 signs after comma);
+ * 3 - coordinates are recorded with an accuracy to millimeter (meters, 3 sign after comma).
  *
  * Note 8. Form of the framework (1 byte):
  * -1- it is not established;
@@ -103,25 +103,25 @@
  * 0001xxxx - western framework.
  *
  * Note 10. Size of the element of certificate (1 bit):
- * xxxxx0xx - 2 bytes (for the integer value); 
- *            4 bytes (for the floating point); 
- * xxxxx1xx - 4 bytes (for the integer value); 
+ * xxxxx0xx - 2 bytes (for the integer value);
+ *            4 bytes (for the floating point);
+ * xxxxx1xx - 4 bytes (for the integer value);
  *            8 bytes (for the floating point).
  *
- * Note 11. Sign of certificate with the text (1 bit): 
- * xxxx0xxx - certificate contains only the coordinates of points; 
- * xxxx1xxx - no-load condition certificate contains the text of signature, 
- *         is allowed only for the objects of the type "signature" or 
+ * Note 11. Sign of certificate with the text (1 bit):
+ * xxxx0xxx - certificate contains only the coordinates of points;
+ * xxxx1xxx - no-load condition certificate contains the text of signature,
+ *         is allowed only for the objects of the type "signature" or
  *         "the template of signature".
  *
  * Note 12. [Masshtabiruemost] of drawing (sign) (1 bit):
  * xx0xxxxx - arbitrary symbol of object not scaled;
  * xx1xxxxx - the arbitrary symbol of object is scaled during the mapping.
- * 
+ *
  * Note 13. Sign of the construction of spline on the certificate (2 bits):
- * 00xxxxxx � the construction of spline with the visualization is not carried out;
- * 01xxxxxx � smoothing out spline (cutting angles);
- * 10xxxxxx � enveloping spline (it penetrates all points of certificate).
+ * 00xxxxxx - the construction of spline with the visualization is not carried out;
+ * 01xxxxxx - smoothing out spline (cutting angles);
+ * 10xxxxxx - enveloping spline (it penetrates all points of certificate).
  ****************************************************************************/
 
 #ifndef SXF_DEFS_H
@@ -197,9 +197,9 @@ enum SXFCoordinateMeasUnit
 
 typedef struct
 {
-    long double stProjCoords[8]; //X(0) & Y(1) South West, X(2) & Y(3) North West, X(4) & Y(5) North East, X(6) & Y(7) South East
-    long double stGeoCoords[8];
-    long double stFrameCoords[8];
+    double stProjCoords[8]; //X(0) & Y(1) South West, X(2) & Y(3) North West, X(4) & Y(5) North East, X(6) & Y(7) South East
+    double stGeoCoords[8];
+    double stFrameCoords[8];
     OGREnvelope Env;
     OGRSpatialReference *pSpatRef;
     SXFCoordinateMeasUnit eUnitInPlan;
@@ -208,7 +208,7 @@ typedef struct
     double dfFalseNorthing;
     double dfFalseEasting;
     GUInt32 nResolution;
-    long double dfScale;
+    double dfScale;
     bool bIsRealCoordinates;
     SXFCoordinatesAccuracy stCoordAcc;
 
@@ -252,7 +252,7 @@ typedef struct
     SXFValueType eValType;      // size of values (Note 3)
     int bFormat;                 // Has 3D vector (Note 4) /* Format of the certificate (0- linear size, 1-vector format ) */
     GByte bDim;                 // Dimensionality of the idea (0- 2D, 1- 3D) (Note 6)
-    int bHasTextSign;           // Sign of certificate with the text (Note 8)
+    bool bHasTextSign;           // Sign of certificate with the text (Note 8)
     GUInt32 nPointCount;        // Point count
     GUInt16 nSubObjectCount;    // The sub object count
 
@@ -302,7 +302,7 @@ struct SXFPassport
 {
     GUInt32 version;
     SXFDate dtCrateDate;
-    CPLString sMapSheet;   
+    CPLString sMapSheet;
     GUInt32 nScale;
     CPLString sMapSheetName;
     SXFInformationFlags informationFlags;
@@ -327,7 +327,7 @@ typedef struct
 */
 typedef struct  {
     GUInt32 nOffset;      //RSC Section offset in bytes from the beginning of the RSC file
-    GUInt32 nLenght;      //RSC Section record length
+    GUInt32 nLength;      //RSC Section record length
     GUInt32 nRecordCount; //count of records in the section
 } RSCSection;
 
@@ -364,7 +364,7 @@ typedef struct{
     RSCSection ImageParams;
     RSCSection Tables;
     GByte nFlagKeysAsCodes;
-    GByte nFlagPalleteMods;
+    GByte nFlagPaletteMods;
     GByte Reserved[30];
     GUInt32 nFontEnc;
     GUInt32 nColorsInPalette;
diff --git a/ogr/ogrsf_frmts/tiger/drv_tiger.html b/ogr/ogrsf_frmts/tiger/drv_tiger.html
index 00c2adb..3c25dc9 100644
--- a/ogr/ogrsf_frmts/tiger/drv_tiger.html
+++ b/ogr/ogrsf_frmts/tiger/drv_tiger.html
@@ -11,14 +11,14 @@ TIGER/Line file sets are support for read access.  <p>
 
 TIGER/Line files are a digital database of geographic features, such as roads,
 railroads, rivers, lakes, political boundaries, census statistical boundaries,
-etc. covering the entire United States. The data base contains information 
-about these features such as their location in latitude and longitude, the 
-name, the type of feature, address ranges for most streets, the geographic 
-relationship to other features, and other related information. They are the 
-public product created from the Census Bureau's TIGER (Topologically 
-Integrated Geographic Encoding and Referencing) data base of geographic 
-information. TIGER was developed at the Census Bureau to support the mapping 
-and related geographic activities required by the decennial census and sample 
+etc. covering the entire United States. The data base contains information
+about these features such as their location in latitude and longitude, the
+name, the type of feature, address ranges for most streets, the geographic
+relationship to other features, and other related information. They are the
+public product created from the Census Bureau's TIGER (Topologically
+Integrated Geographic Encoding and Referencing) data base of geographic
+information. TIGER was developed at the Census Bureau to support the mapping
+and related geographic activities required by the decennial census and sample
 survey programs. <p>
 
 Note that the TIGER/Line product does not include census demographic
@@ -27,10 +27,10 @@ statistics.  Those are sold by the Census Bureau in a separate format
 census blocks in TIGER/Line files.<p>
 
 To open a TIGER/Line dataset, select the directory containing one or more
-sets of data files.   The regions are counties, or county equivelents.   Each
+sets of data files.   The regions are counties, or county equivalents.   Each
 county consists of a series of files with a common basename, and different
-extentions.  For instance, county 1 in state 26 (Michigan) consists of
-the following file set in Tiger98. <p>
+extensions.  For instance, county 1 in state 26 (Michigan) consists of
+the following file set in Tiger98.<p>
 
 <pre>
 TGR26001.RT1
@@ -52,7 +52,7 @@ TGR26001.RTS
 TGR26001.RTZ
 </pre>
 
-The TIGER/Line coordinate system is hardcoded to NAD83 lat/long degrees. 
+The TIGER/Line coordinate system is hardcoded to NAD83 lat/long degrees.
 This should be appropriate for all recent years of TIGER/Line production.<P>
 
 There is no update or creation support in the TIGER/Line driver.<p>
@@ -60,15 +60,15 @@ There is no update or creation support in the TIGER/Line driver.<p>
 The reader was implemented for TIGER/Line 1998 files, but some effort has
 gone into ensuring compatibility with 1992, 1995, 1997, 1999, 2000, 2002, 2003
 and 2004 TIGER/Line products as well.  The 2005 products have also been
-reported to work fine.  It is believe that any TIGER/Line 
-product from the 1990's should work with the reader, with the possible loss of 
+reported to work fine.  It is believe that any TIGER/Line
+product from the 1990's should work with the reader, with the possible loss of
 some version specific information.<p>
 
 
 <h3>Feature Representation</h3>
 
 With a few exceptions, a feature is created for each record of a
-TIGER/Line data file.  Each file (ie. .RT1, .RTA) is translated to an
+TIGER/Line data file.  Each file (i.e. .RT1, .RTA) is translated to an
 appropriate OGR feature type, with attribute names matching those in the
 TIGER/Line product manual.<p>
 
@@ -79,16 +79,16 @@ module from which the feature originated.  For some keys (such as LAND,
 POLYID, and CENID) this MODULE attribute is needed to make the key unique
 when the dataset (directory) consists of more than one county of data. <p>
 
-Following is a list of feature types, and their relationship to the 
+Following is a list of feature types, and their relationship to the
 TIGER/Line product.<p>
 
 <h4>CompleteChain</h4>
 
-A CompleteChain is a polyline with an associated TLID (TIGER/Line ID). 
+A CompleteChain is a polyline with an associated TLID (TIGER/Line ID).
 The CompleteChain features are established from a type 1 record
-(Complete Chain Basic Data Record), and if available it's associated 
+(Complete Chain Basic Data Record), and if available it's associated
 type 3 record (Complete Chain Geographic Entity Codes).   As well, any
-type 2 records (Complete Chain Shape Coordinates) available are used to 
+type 2 records (Complete Chain Shape Coordinates) available are used to
 fill in intermediate shape points on the arc.  The TLID is the primary
 key, and is unique within the entire national TIGER/Line coverage.<p>
 
@@ -105,7 +105,7 @@ ALT_FETYPE{}.  The ALT_FENAME{} is a list of feature names associated with
 the TLID on the AltName feature. <p>
 
 Note that zero, one or more AltName records may exist for a given TLID, and
-each AltName record can contain between one and four alternate names. 
+each AltName record can contain between one and four alternate names.
 Because it is still very difficult to utilize AltName features to relate
 altername names to CompleteChains, it is anticipated that the standard
 reader pipeline for TIGER/Line files will be upgraded in the future, resulting
@@ -116,16 +116,16 @@ These features have no associated geometry.<p>
 <h4>FeatureIds</h4>
 
 These features are derived from type 5 (Complete Chain Feature Identifiers)
-records.  Each feature contains a feature name (FENAME), and it's associated 
+records.  Each feature contains a feature name (FENAME), and it's associated
 feature id code (FEAT).  The FEAT attribute is the primary key, and is
-unique within the county module.  FeatureIds have a one to many relationship 
+unique within the county module.  FeatureIds have a one to many relationship
 with AltName features, and KeyFeatures features.<p>
 
 These features have no associated geometry.<p>
 
 <h4>ZipCodes</h4>
 
-These features are derived from type 6 (Additional Address Range and 
+These features are derived from type 6 (Additional Address Range and
 ZIP Code Data) records.  These features are intended to augment the
 ZIP Code information kept directly on CompleteChain features, and there
 is a many to one relationship between ZipCodes features and CompleteChain
@@ -147,15 +147,15 @@ to be collected (via the AreaLandmark feature) from a Polygon feature.<p>
 <h4>AreaLandmarks</h4>
 
 These features are derived from type 8 (Polygons Linked to Area Landmarks)
-records.  Each associates a Landmark feature (attribute LAND) with a 
-Polygon feature (attribute POLYID).  This feature has a many to many 
+records.  Each associates a Landmark feature (attribute LAND) with a
+Polygon feature (attribute POLYID).  This feature has a many to many
 relationship with Polygon features.<p>
 
 These features have no associated geometry.<p>
 
 <h4>KeyFeatures</h4>
 
-These features are derived from type 9 (Polygon Geographic Entity Codes) 
+These features are derived from type 9 (Polygon Geographic Entity Codes)
 records.  They may be associated with a FeatureIds feature (via the FEAT
 attribute), and a Polygon feature (via the POLYID attribute).  <p>
 
@@ -172,7 +172,7 @@ These features do not have any geometry associated with them as read by
 the OGR TIGER driver.  It needs to be externally related using the
 PolyChainLink.  The gdal/pymod/samples/tigerpoly.py script may be used
 to read a TIGER dataset and extract the polygon layer <b>with geometry</b>
-as a shapefile. 
+as a shapefile.
 
 <h4>EntityNames</h4>
 
@@ -201,7 +201,7 @@ These features have no associated geometry.<p>
 
 <h4>PIP</h4>
 
-These features are derived from type P (Polygon Internal Point) records. 
+These features are derived from type P (Polygon Internal Point) records.
 They relate to a Polygon feature via the POLYID attribute, and can be used
 to establish an internal point for Polygon features.<p>
 
@@ -209,7 +209,7 @@ These features have a point geometry.<p>
 
 <h4>ZipPlus4</h4>
 
-These features are derived from type Z (ZIP+4 Codes) records.  ZipPlus4 
+These features are derived from type Z (ZIP+4 Codes) records.  ZipPlus4
 features have a many to one relationship with CompleteChain features.
 <p>
 
@@ -220,7 +220,7 @@ These features have no associated geometry.
 
 <ul>
 
-<li> <a href="http://www.census.gov/geo/www/tiger/">http://www.census.gov/geo/www/tiger/</a>: More information on the TIGER/Line file format, and data 
+<li> <a href="http://www.census.gov/geo/www/tiger/">http://www.census.gov/geo/www/tiger/</a>: More information on the TIGER/Line file format, and data
 product can be found on this U.S. Census web page.<p.
 
 </ul>
diff --git a/ogr/ogrsf_frmts/tiger/ogr_tiger.h b/ogr/ogrsf_frmts/tiger/ogr_tiger.h
index a95ec09..118259b 100644
--- a/ogr/ogrsf_frmts/tiger/ogr_tiger.h
+++ b/ogr/ogrsf_frmts/tiger/ogr_tiger.h
@@ -1,6 +1,6 @@
 /*-*-C++-*-*/
 /******************************************************************************
- * $Id: ogr_tiger.h 28382 2015-01-30 15:29:41Z rouault $
+ * $Id: ogr_tiger.h 31777 2015-11-26 14:14:41Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Main declarations for Tiger translator.
@@ -29,8 +29,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_TIGER_H_INCLUDED
-#define _OGR_TIGER_H_INCLUDED
+#ifndef OGR_TIGER_H_INCLUDED
+#define OGR_TIGER_H_INCLUDED
 
 #include "cpl_conv.h"
 #include "ogrsf_frmts.h"
@@ -602,4 +602,4 @@ class OGRTigerDataSource : public OGRDataSource
                                       char ** = NULL );
 };
 
-#endif /* ndef _OGR_TIGER_H_INCLUDED */
+#endif /* ndef OGR_TIGER_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/tiger/ogrtigerdatasource.cpp b/ogr/ogrsf_frmts/tiger/ogrtigerdatasource.cpp
index ae5caf6..5380385 100644
--- a/ogr/ogrsf_frmts/tiger/ogrtigerdatasource.cpp
+++ b/ogr/ogrsf_frmts/tiger/ogrtigerdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrtigerdatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogrtigerdatasource.cpp 33710 2016-03-12 06:28:29Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements OGRTigerDataSource class
@@ -27,12 +27,13 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_tiger.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
-#include <ctype.h>
+#include "ogr_tiger.h"
+
+#include <cctype>
 
-CPL_CVSID("$Id: ogrtigerdatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogrtigerdatasource.cpp 33710 2016-03-12 06:28:29Z goatbar $");
 
 /************************************************************************/
 /*                        TigerClassifyVersion()                        */
@@ -47,15 +48,15 @@ TigerVersion TigerClassifyVersion( int nVersionCode )
 /*
 ** TIGER Versions
 **
-** 0000           TIGER/Line Precensus Files, 1990 
-** 0002           TIGER/Line Initial Voting District Codes Files, 1990 
-** 0003           TIGER/Line Files, 1990 
-** 0005           TIGER/Line Files, 1992 
-** 0021           TIGER/Line Files, 1994 
-** 0024           TIGER/Line Files, 1995 
-** 9706 to 9810   TIGER/Line Files, 1997 
-** 9812 to 9904   TIGER/Line Files, 1998 
-** 0006 to 0008   TIGER/Line Files, 1999 
+** 0000           TIGER/Line Precensus Files, 1990
+** 0002           TIGER/Line Initial Voting District Codes Files, 1990
+** 0003           TIGER/Line Files, 1990
+** 0005           TIGER/Line Files, 1992
+** 0021           TIGER/Line Files, 1994
+** 0024           TIGER/Line Files, 1995
+** 9706 to 9810   TIGER/Line Files, 1997
+** 9812 to 9904   TIGER/Line Files, 1998
+** 0006 to 0008   TIGER/Line Files, 1999
 ** 0010 to 0011   TIGER/Line Files, Redistricting Census 2000
 ** 0103 to 0108   TIGER/Line Files, Census 2000
 **
@@ -148,7 +149,7 @@ const char * TigerVersionString( TigerVersion nVersion )
 /*      based on this.                                                  */
 /************************************************************************/
 
-TigerVersion OGRTigerDataSource::TigerCheckVersion( TigerVersion nOldVersion, 
+TigerVersion OGRTigerDataSource::TigerCheckVersion( TigerVersion nOldVersion,
                                                     const char *pszFilename )
 
 {
@@ -161,8 +162,8 @@ TigerVersion OGRTigerDataSource::TigerCheckVersion( TigerVersion nOldVersion,
 
     if( fp == NULL )
         return nOldVersion;
-    
-    char        szHeader[115];
+
+    char szHeader[115];
 
     if( VSIFReadL( szHeader, sizeof(szHeader)-1, 1, fp ) < 1 )
     {
@@ -171,7 +172,7 @@ TigerVersion OGRTigerDataSource::TigerCheckVersion( TigerVersion nOldVersion,
     }
 
     VSIFCloseL( fp );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Is the record length 112?  If so, it is an older version        */
 /*      than 2002.                                                      */
@@ -181,31 +182,30 @@ TigerVersion OGRTigerDataSource::TigerCheckVersion( TigerVersion nOldVersion,
         CPLDebug( "TIGER", "Forcing version back to UA2000 since RTC records are short." );
         return TIGER_UA2000;
     }
-    else
-        return nOldVersion;
+
+    return nOldVersion;
 }
 
 /************************************************************************/
 /*                         OGRTigerDataSource()                         */
 /************************************************************************/
 
-OGRTigerDataSource::OGRTigerDataSource()
-
+OGRTigerDataSource::OGRTigerDataSource() :
+    pszName(NULL),
+    nLayers(0),
+    papoLayers(NULL),
+    papszOptions(NULL),
+    pszPath(NULL),
+    nModules(0),
+    papszModules(NULL),
+    nVersionCode(0),
+    nVersion(TIGER_Unknown),
+    bWriteMode(FALSE)
 {
-    bWriteMode = FALSE;
-
-    nLayers = 0;
-    papoLayers = NULL;
-
-    nModules = 0;
-    papszModules = NULL;
-
-    pszName = NULL;
-    pszPath = NULL;
-
-    papszOptions = NULL;
-
-    poSpatialRef = new OGRSpatialReference( "GEOGCS[\"NAD83\",DATUM[\"North_American_Datum_1983\",SPHEROID[\"GRS 1980\",6378137,298.257222101]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]]" );
+    poSpatialRef = new OGRSpatialReference(
+        "GEOGCS[\"NAD83\",DATUM[\"North_American_Datum_1983\","
+        "SPHEROID[\"GRS 1980\",6378137,298.257222101]],PRIMEM[\"Greenwich\",0],"
+        "UNIT[\"degree\",0.0174532925199433]]" );
 }
 
 /************************************************************************/
@@ -215,11 +215,9 @@ OGRTigerDataSource::OGRTigerDataSource()
 OGRTigerDataSource::~OGRTigerDataSource()
 
 {
-    int         i;
-
-    for( i = 0; i < nLayers; i++ )
+    for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
-    
+
     CPLFree( papoLayers );
 
     CPLFree( pszName );
@@ -240,9 +238,9 @@ void OGRTigerDataSource::AddLayer( OGRTigerLayer * poNewLayer )
 
 {
     poNewLayer->SetDescription( poNewLayer->GetName() );
-    papoLayers = (OGRTigerLayer **)
-        CPLRealloc( papoLayers, sizeof(void*) * ++nLayers );
-    
+    papoLayers = static_cast<OGRTigerLayer **>(
+        CPLRealloc( papoLayers, sizeof(void*) * ++nLayers ) );
+
     papoLayers[nLayers-1] = poNewLayer;
 }
 
@@ -255,8 +253,8 @@ OGRLayer *OGRTigerDataSource::GetLayer( int iLayer )
 {
     if( iLayer < 0 || iLayer >= nLayers )
         return NULL;
-    else
-        return papoLayers[iLayer];
+
+    return papoLayers[iLayer];
 }
 
 /************************************************************************/
@@ -293,16 +291,15 @@ int OGRTigerDataSource::Open( const char * pszFilename, int bTestOpen,
                               char ** papszLimitedFileList )
 
 {
-    VSIStatBufL     stat;
-    char            **papszFileList = NULL;
-    int             i;
-
     pszName = CPLStrdup( pszFilename );
 
 /* -------------------------------------------------------------------- */
 /*      Is the given path a directory or a regular file?                */
 /* -------------------------------------------------------------------- */
-    if( VSIStatExL( pszFilename, &stat, VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG ) != 0
+    VSIStatBufL stat;
+
+    if( VSIStatExL( pszFilename, &stat,
+                    VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG ) != 0
         || (!VSI_ISDIR(stat.st_mode) && !VSI_ISREG(stat.st_mode)) )
     {
         if( !bTestOpen )
@@ -312,14 +309,15 @@ int OGRTigerDataSource::Open( const char * pszFilename, int bTestOpen,
 
         return FALSE;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Build a list of filenames we figure are Tiger files.            */
 /* -------------------------------------------------------------------- */
+    char **papszFileList = NULL;
     if( VSI_ISREG(stat.st_mode) )
     {
         char       szModule[128];
-        
+
         if( strlen(CPLGetFilename(pszFilename)) == 0 )
         {
             return FALSE;
@@ -338,25 +336,24 @@ int OGRTigerDataSource::Open( const char * pszFilename, int bTestOpen,
     }
     else
     {
-        char      **candidateFileList = CPLReadDir( pszFilename );
-        int         i;
+        char **candidateFileList = VSIReadDir( pszFilename );
 
         pszPath = CPLStrdup( pszFilename );
 
-        for( i = 0; 
-             candidateFileList != NULL && candidateFileList[i] != NULL; 
-             i++ ) 
+        for( int i = 0;
+             candidateFileList != NULL && candidateFileList[i] != NULL;
+             i++ )
         {
-            int nCandidateLen = strlen(candidateFileList[i]);
+            size_t nCandidateLen = strlen(candidateFileList[i]);
 
-            if( papszLimitedFileList != NULL 
+            if( papszLimitedFileList != NULL
                 && CSLFindString(papszLimitedFileList,
                                  CPLGetBasename(candidateFileList[i])) == -1 )
             {
                 continue;
             }
 
-            if( nCandidateLen > 4 
+            if( nCandidateLen > 4
                 && candidateFileList[i][nCandidateLen-4] == '.'
                 && candidateFileList[i][nCandidateLen-1] == '1')
             {
@@ -380,7 +377,7 @@ int OGRTigerDataSource::Open( const char * pszFilename, int bTestOpen,
                           "No candidate Tiger files (TGR*.RT1) found in\n"
                           "directory: %s",
                           pszFilename );
-
+            CSLDestroy(papszFileList);
             return FALSE;
         }
     }
@@ -389,12 +386,12 @@ int OGRTigerDataSource::Open( const char * pszFilename, int bTestOpen,
 /*      Loop over all these files trying to open them.  In testopen     */
 /*      mode we first read the first 80 characters, to verify that      */
 /*      it looks like an Tiger file.  Note that we don't keep the file  */
-/*      open ... we don't want to occupy alot of file handles when      */
+/*      open ... we don't want to occupy a lot of file handles when      */
 /*      handling a whole directory.                                     */
 /* -------------------------------------------------------------------- */
     papszModules = NULL;
-    
-    for( i = 0; papszFileList[i] != NULL; i++ )
+
+    for( int i = 0; papszFileList[i] != NULL; i++ )
     {
         if( bTestOpen || i == 0 )
         {
@@ -402,16 +399,16 @@ int OGRTigerDataSource::Open( const char * pszFilename, int bTestOpen,
             VSILFILE    *fp;
             char        *pszRecStart = NULL;
             int         bIsGDT = FALSE;
-            char       *pszFilename;
+            char       *l_pszFilename;
 
-            pszFilename = BuildFilename( papszFileList[i], "1" );
+            l_pszFilename = BuildFilename( papszFileList[i], "1" );
 
-            fp = VSIFOpenL( pszFilename, "rb" );
-            CPLFree( pszFilename );
+            fp = VSIFOpenL( l_pszFilename, "rb" );
+            CPLFree( l_pszFilename );
 
             if( fp == NULL )
                 continue;
-            
+
             if( VSIFReadL( szHeader, sizeof(szHeader)-1, 1, fp ) < 1 )
             {
                 VSIFCloseL( fp );
@@ -423,20 +420,20 @@ int OGRTigerDataSource::Open( const char * pszFilename, int bTestOpen,
             pszRecStart = szHeader;
             szHeader[sizeof(szHeader)-1] = '\0';
 
-            if( EQUALN(pszRecStart,"Copyright (C)",13) 
+            if( STARTS_WITH_CI(pszRecStart, "Copyright (C)")
                 && strstr(pszRecStart,"Geographic Data Tech") != NULL )
             {
                 bIsGDT = TRUE;
 
-                while( *pszRecStart != '\0' 
-                       && *pszRecStart != 10 
+                while( *pszRecStart != '\0'
+                       && *pszRecStart != 10
                        && *pszRecStart != 13 )
                     pszRecStart++;
 
                 while( *pszRecStart == 10 || *pszRecStart == 13 )
                     pszRecStart++;
             }
-            
+
             if( pszRecStart[0] != '1' )
                 continue;
 
@@ -448,14 +445,14 @@ int OGRTigerDataSource::Open( const char * pszFilename, int bTestOpen,
             nVersion = TigerClassifyVersion( nVersionCode );
             nVersion = TigerCheckVersion( nVersion, papszFileList[i] );
 
-            CPLDebug( "OGR", "Tiger Version Code=%d, Classified as %s ", 
+            CPLDebug( "OGR", "Tiger Version Code=%d, Classified as %s ",
                       nVersionCode, TigerVersionString(nVersion) );
 
             if(    nVersionCode !=  0
                 && nVersionCode !=  2
                 && nVersionCode !=  3
                 && nVersionCode !=  5
-                && nVersionCode != 21 
+                && nVersionCode != 21
                 && nVersionCode != 24
                 && pszRecStart[3]  != '9'
                 && pszRecStart[3]  != '0'
@@ -472,7 +469,7 @@ int OGRTigerDataSource::Open( const char * pszFilename, int bTestOpen,
 
     nModules = CSLCount( papszModules );
 
-    if( nModules == 0 )
+    if( nModules == 0 || papszModules == NULL )
     {
         if( !bTestOpen )
         {
@@ -495,10 +492,10 @@ int OGRTigerDataSource::Open( const char * pszFilename, int bTestOpen,
 /* -------------------------------------------------------------------- */
     if( CPLGetConfigOption( "TIGER_VERSION", NULL ) != NULL )
     {
-        const char *pszRequestedVersion = 
+        const char *pszRequestedVersion =
             CPLGetConfigOption( "TIGER_VERSION", NULL );
 
-        if( EQUALN(pszRequestedVersion,"TIGER_",6) )
+        if( STARTS_WITH_CI(pszRequestedVersion, "TIGER_") )
         {
             int iCode;
 
@@ -514,13 +511,13 @@ int OGRTigerDataSource::Open( const char * pszFilename, int bTestOpen,
 
             if( iCode == TIGER_Unknown )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                          "Failed to recognise TIGER_VERSION setting: %s", 
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Failed to recognise TIGER_VERSION setting: %s",
                           pszRequestedVersion );
                 return FALSE;
-            }                          
+            }
 
-            CPLDebug( "OGR", "OVERRIDE Tiger Version %s ", 
+            CPLDebug( "OGR", "OVERRIDE Tiger Version %s ",
                       TigerVersionString(nVersion) );
         }
         else
@@ -528,8 +525,8 @@ int OGRTigerDataSource::Open( const char * pszFilename, int bTestOpen,
             nVersionCode = atoi(pszRequestedVersion);
             nVersion = TigerClassifyVersion( nVersionCode );
 
-            CPLDebug( "OGR", 
-                      "OVERRIDE Tiger Version Code=%d, Classified as %s ", 
+            CPLDebug( "OGR",
+                      "OVERRIDE Tiger Version Code=%d, Classified as %s ",
                       nVersionCode, TigerVersionString(nVersion) );
         }
     }
@@ -561,7 +558,7 @@ int OGRTigerDataSource::Open( const char * pszFilename, int bTestOpen,
     AddLayer( new OGRTigerLayer( this,
                                  new TigerLandmarks( this,
                                                      papszModules[0]) ));
-    
+
     // RT8
     AddLayer( new OGRTigerLayer( this,
                                  new TigerAreaLandmarks( this,
@@ -573,7 +570,7 @@ int OGRTigerDataSource::Open( const char * pszFilename, int bTestOpen,
                                    new TigerKeyFeatures( this,
                                                          papszModules[0]) ));
     }
-    
+
     // RTA, RTS
     AddLayer( new OGRTigerLayer( this,
                                  new TigerPolygon( this,
@@ -585,7 +582,7 @@ int OGRTigerDataSource::Open( const char * pszFilename, int bTestOpen,
                                    new TigerPolygonCorrections( this,
                                                                 papszModules[0]) ));
     }
-    
+
     // RTC
     AddLayer( new OGRTigerLayer( this,
                                  new TigerEntityNames( this,
@@ -602,27 +599,27 @@ int OGRTigerDataSource::Open( const char * pszFilename, int bTestOpen,
     AddLayer( new OGRTigerLayer( this,
                                  new TigerIDHistory( this,
                                                      papszModules[0]) ));
-    
+
     // RTI
     AddLayer( new OGRTigerLayer( this,
                                  new TigerPolyChainLink( this,
                                                        papszModules[0]) ));
-    
+
     // RTM
     AddLayer( new OGRTigerLayer( this,
                                  new TigerSpatialMetadata( this,
                                                            papszModules[0] ) ) );
-    
+
     // RTP
     AddLayer( new OGRTigerLayer( this,
                                  new TigerPIP( this,
                                                papszModules[0]) ));
-    
+
     // RTR
     AddLayer( new OGRTigerLayer( this,
                                  new TigerTLIDRange( this,
                                                      papszModules[0]) ));
-    
+
     // RTT
     if (nVersion >= TIGER_2002) {
       AddLayer( new OGRTigerLayer( this,
@@ -641,7 +638,7 @@ int OGRTigerDataSource::Open( const char * pszFilename, int bTestOpen,
     AddLayer( new OGRTigerLayer( this,
                                  new TigerZipPlus4( this,
                                                      papszModules[0]) ));
-    
+
     return TRUE;
 }
 
@@ -738,15 +735,16 @@ char *OGRTigerDataSource::BuildFilename( const char *pszModuleName,
 /* -------------------------------------------------------------------- */
 /*      Build the filename.                                             */
 /* -------------------------------------------------------------------- */
-    pszFilename = (char *) CPLMalloc(strlen(GetDirPath())
+    const size_t nFilenameLen = strlen(GetDirPath())
                                      + strlen(pszModuleName)
-                                     + strlen(pszExtension) + 10);
+                                     + strlen(pszExtension) + 10;
+    pszFilename = (char *) CPLMalloc(nFilenameLen);
 
     if( strlen(GetDirPath()) == 0 )
-        sprintf( pszFilename, "%s%s",
+        snprintf( pszFilename, nFilenameLen, "%s%s",
                  pszModuleName, pszExtension );
     else
-        sprintf( pszFilename, "%s/%s%s",
+        snprintf( pszFilename, nFilenameLen, "%s/%s%s",
                  GetDirPath(), pszModuleName, pszExtension );
 
     return pszFilename;
@@ -769,11 +767,11 @@ int OGRTigerDataSource::TestCapability( const char *pszCap )
 /*                               Create()                               */
 /************************************************************************/
 
-int OGRTigerDataSource::Create( const char *pszNameIn, char **papszOptions )
+int OGRTigerDataSource::Create( const char *pszNameIn, char **papszOptionsIn )
 
 {
     VSIStatBufL      stat;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Try to create directory if it doesn't already exist.            */
 /* -------------------------------------------------------------------- */
@@ -784,9 +782,9 @@ int OGRTigerDataSource::Create( const char *pszNameIn, char **papszOptions )
 
     if( VSIStatL( pszNameIn, &stat ) != 0 || !VSI_ISDIR(stat.st_mode) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "%s is not a directory, nor can be directly created as one.",
-                  pszName );
+                  pszNameIn );
         return FALSE;
     }
 
@@ -797,7 +795,7 @@ int OGRTigerDataSource::Create( const char *pszNameIn, char **papszOptions )
     pszName = CPLStrdup( pszNameIn );
     bWriteMode = TRUE;
 
-    SetOptionList( papszOptions );
+    SetOptionList( papszOptionsIn );
 
 /* -------------------------------------------------------------------- */
 /*      Work out the version.                                           */
@@ -822,7 +820,7 @@ int OGRTigerDataSource::Create( const char *pszNameIn, char **papszOptions )
 OGRLayer *OGRTigerDataSource::ICreateLayer( const char *pszLayerName,
                                             OGRSpatialReference *poSpatRef,
                                             CPL_UNUSED OGRwkbGeometryType eGType,
-                                            CPL_UNUSED char **papszOptions )
+                                            char ** /* papszOptions */ )
 {
     OGRTigerLayer       *poLayer = NULL;
 
@@ -834,8 +832,8 @@ OGRLayer *OGRTigerDataSource::ICreateLayer( const char *pszLayerName,
          || !EQUAL(poSpatRef->GetAttrValue("DATUM"),
                    "North_American_Datum_1983")) )
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
-                  "Requested coordinate system wrong for Tiger, " 
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Requested coordinate system wrong for Tiger, "
                   "forcing to GEOGCS NAD83." );
     }
 
@@ -942,7 +940,7 @@ OGRLayer *OGRTigerDataSource::ICreateLayer( const char *pszLayerName,
 
     if( poLayer == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to create layer %s, not a known TIGER/Line layer.",
                   pszLayerName );
     }
@@ -959,17 +957,17 @@ OGRLayer *OGRTigerDataSource::ICreateLayer( const char *pszLayerName,
 void OGRTigerDataSource::DeleteModuleFiles( const char *pszModule )
 
 {
-    char        **papszDirFiles = CPLReadDir( GetDirPath() );
+    char        **papszDirFiles = VSIReadDir( GetDirPath() );
     int         i, nCount = CSLCount(papszDirFiles);
-    
+
     for( i = 0; i < nCount; i++ )
     {
         if( EQUALN(pszModule,papszDirFiles[i],strlen(pszModule)) )
         {
             const char  *pszFilename;
 
-            pszFilename = CPLFormFilename( GetDirPath(), 
-                                           papszDirFiles[i], 
+            pszFilename = CPLFormFilename( GetDirPath(),
+                                           papszDirFiles[i],
                                            NULL );
             if( VSIUnlink( pszFilename ) != 0 )
             {
diff --git a/ogr/ogrsf_frmts/tiger/ogrtigerdriver.cpp b/ogr/ogrsf_frmts/tiger/ogrtigerdriver.cpp
index 9651160..7fb0e8b 100644
--- a/ogr/ogrsf_frmts/tiger/ogrtigerdriver.cpp
+++ b/ogr/ogrsf_frmts/tiger/ogrtigerdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrtigerdriver.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogrtigerdriver.cpp 33105 2016-01-23 15:27:32Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements OGRTigerDriver
@@ -30,7 +30,7 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrtigerdriver.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogrtigerdriver.cpp 33105 2016-01-23 15:27:32Z rouault $");
 
 /************************************************************************/
 /*                                Open()                                */
@@ -58,9 +58,9 @@ static GDALDataset *OGRTigerDriverOpen( GDALOpenInfo* poOpenInfo )
             }
         }
         if( !bFoundCompatibleFile )
-            return FALSE;
+            return NULL;
     }
- 
+
     OGRTigerDataSource  *poDS = new OGRTigerDataSource;
 
     if( !poDS->Open( poOpenInfo->pszFilename, TRUE ) )
@@ -105,30 +105,25 @@ static GDALDataset *OGRTigerDriverCreate( const char * pszName,
 }
 
 /************************************************************************/
-/*                           RegisterOGRTiger()                           */
+/*                           RegisterOGRTiger()                         */
 /************************************************************************/
 
 void RegisterOGRTiger()
 
 {
-    GDALDriver  *poDriver;
-
-    if( GDALGetDriverByName( "TIGER" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    if( GDALGetDriverByName( "TIGER" ) != NULL )
+        return;
 
-        poDriver->SetDescription( "TIGER" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "U.S. Census TIGER/Line" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_tiger.html" );
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetDescription( "TIGER" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "U.S. Census TIGER/Line" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_tiger.html" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = OGRTigerDriverOpen;
-        poDriver->pfnCreate = OGRTigerDriverCreate;
+    poDriver->pfnOpen = OGRTigerDriverOpen;
+    poDriver->pfnCreate = OGRTigerDriverCreate;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/tiger/ogrtigerlayer.cpp b/ogr/ogrsf_frmts/tiger/ogrtigerlayer.cpp
index adbfdae..ab71f12 100644
--- a/ogr/ogrsf_frmts/tiger/ogrtigerlayer.cpp
+++ b/ogr/ogrsf_frmts/tiger/ogrtigerlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrtigerlayer.cpp 28382 2015-01-30 15:29:41Z rouault $
+ * $Id: ogrtigerlayer.cpp 33706 2016-03-11 13:33:27Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements OGRTigerLayer class.
@@ -29,7 +29,7 @@
 
 #include "ogr_tiger.h"
 
-CPL_CVSID("$Id: ogrtigerlayer.cpp 28382 2015-01-30 15:29:41Z rouault $");
+CPL_CVSID("$Id: ogrtigerlayer.cpp 33706 2016-03-11 13:33:27Z goatbar $");
 
 /************************************************************************/
 /*                           OGRTigerLayer()                            */
@@ -57,9 +57,9 @@ OGRTigerLayer::OGRTigerLayer( OGRTigerDataSource *poDSIn,
 /* -------------------------------------------------------------------- */
     if( !poDS->GetWriteMode() )
     {
-        panModuleFCount = (int *) 
+        panModuleFCount = (int *)
             CPLCalloc(poDS->GetModuleCount(),sizeof(int));
-        panModuleOffset = (int *) 
+        panModuleOffset = (int *)
             CPLCalloc(poDS->GetModuleCount()+1,sizeof(int));
 
         nFeatureCount = 0;
@@ -93,7 +93,7 @@ OGRTigerLayer::~OGRTigerLayer()
     if( m_nFeaturesRead > 0 && poReader->GetFeatureDefn() != NULL )
     {
         CPLDebug( "TIGER", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
+                  (int) m_nFeaturesRead,
                   poReader->GetFeatureDefn()->GetName() );
     }
 
@@ -128,7 +128,7 @@ OGRFeature *OGRTigerLayer::GetFeature( GIntBig nFeatureId )
 /*      If we don't have the current module open for the requested      */
 /*      data, then open it now.                                         */
 /* -------------------------------------------------------------------- */
-    if( iLastModule == -1 
+    if( iLastModule == -1
         || nFeatureId <= panModuleOffset[iLastModule]
         || nFeatureId > panModuleOffset[iLastModule+1] )
     {
@@ -208,7 +208,7 @@ int OGRTigerLayer::TestCapability( const char * pszCap )
     if( EQUAL(pszCap,OLCRandomRead) )
         return TRUE;
 
-    else if( EQUAL(pszCap,OLCSequentialWrite) 
+    else if( EQUAL(pszCap,OLCSequentialWrite)
              || EQUAL(pszCap,OLCRandomWrite) )
         return FALSE;
 
@@ -221,7 +221,7 @@ int OGRTigerLayer::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCSequentialWrite) )
         return poDS->GetWriteMode();
 
-    else 
+    else
         return FALSE;
 }
 
diff --git a/ogr/ogrsf_frmts/tiger/tigeraltname.cpp b/ogr/ogrsf_frmts/tiger/tigeraltname.cpp
index 68ccdfe..f5dac78 100644
--- a/ogr/ogrsf_frmts/tiger/tigeraltname.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigeraltname.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigeraltname.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: tigeraltname.cpp 32177 2015-12-14 07:25:30Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerAltName, providing access to RT4 files.
@@ -30,7 +30,7 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigeraltname.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: tigeraltname.cpp 32177 2015-12-14 07:25:30Z goatbar $");
 
 #define FILE_CODE "4"
 
@@ -161,8 +161,8 @@ OGRErr TigerAltName::CreateFeature( OGRFeature *poFeature )
     for( int i = 0; i < nValueCount; i++ )
     {
         char    szWork[9];
-        
-        sprintf( szWork, "%8d", panValue[i] );
+
+        snprintf( szWork, sizeof(szWork), "%8d", panValue[i] );
         strncpy( szRecord + 18 + 8 * i, szWork, 8 );
     }
 
diff --git a/ogr/ogrsf_frmts/tiger/tigercompletechain.cpp b/ogr/ogrsf_frmts/tiger/tigercompletechain.cpp
index 4f349fb..4387ba2 100644
--- a/ogr/ogrsf_frmts/tiger/tigercompletechain.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigercompletechain.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigercompletechain.cpp 28382 2015-01-30 15:29:41Z rouault $
+ * $Id: tigercompletechain.cpp 33706 2016-03-11 13:33:27Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerCompleteChain, providing access to RT1 and
@@ -31,7 +31,7 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigercompletechain.cpp 28382 2015-01-30 15:29:41Z rouault $");
+CPL_CVSID("$Id: tigercompletechain.cpp 33706 2016-03-11 13:33:27Z goatbar $");
 
 static const TigerFieldInfo rt1_2002_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
@@ -125,7 +125,7 @@ static const TigerFieldInfo rt1_fields[] = {
   { "CTBNAR",     'L', 'N', OFTInteger,  177, 182,   6,       1,   1,     1 },
   { "BLKL",       'L', 'N', OFTString,   183, 186,   4,       1,   1,     1 },
   { "BLKR",       'L', 'N', OFTString,   187, 190,   4,       1,   1,     1 }
-}; 
+};
 static const TigerRecordInfo rt1_info =
   {
     rt1_fields,
@@ -198,7 +198,7 @@ static const TigerFieldInfo rt3_fields[] = {
   { "BLK90R",     'L', 'A', OFTString,     74,  77,   4,       1,   1,     1 },
   { "AIRL",       'L', 'N', OFTInteger,    78,  81,   4,       1,   1,     1 },
   { "AIRR",       'L', 'N', OFTInteger,    82,  85,   4,       1,   1,     1 },
- 
+
   { "VTDL",       'L', 'A', OFTString,    104, 107,   4,       1,   1,     1 },
   { "VTDR",       'L', 'A', OFTString,    108, 111,   4,       1,   1,     1 }
 
@@ -245,7 +245,7 @@ TigerCompleteChain::TigerCompleteChain( OGRTigerDataSource * poDSIn,
 
     panShapeRecordId = NULL;
     fpShape = NULL;
-    
+
     /* -------------------------------------------------------------------- */
     /*      Fields from type 1 record.                                      */
     /* -------------------------------------------------------------------- */
@@ -281,10 +281,10 @@ TigerCompleteChain::~TigerCompleteChain()
 /*                             SetModule()                              */
 /************************************************************************/
 
-int TigerCompleteChain::SetModule( const char * pszModule )
+int TigerCompleteChain::SetModule( const char * pszModuleIn )
 
 {
-    if( !OpenFile( pszModule, "1" ) )
+    if( !OpenFile( pszModuleIn, "1" ) )
         return FALSE;
 
     EstablishFeatureCount();
@@ -295,20 +295,20 @@ int TigerCompleteChain::SetModule( const char * pszModule )
 /*      first record.                                                   */
 /* -------------------------------------------------------------------- */
     nRT1RecOffset = 0;
-    if( pszModule )
+    if( pszModuleIn )
     {
         char achHeader[10];
-        
+
         VSIFSeekL( fpPrimary, 0, SEEK_SET );
         VSIFReadL( achHeader, sizeof(achHeader), 1, fpPrimary );
-        
-        if( EQUALN(achHeader,"Copyright",8) )
+
+        if( STARTS_WITH_CI(achHeader,"Copyright") )
         {
             nRT1RecOffset = 1;
             nFeatures--;
         }
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Open the RT3 file                                               */
 /* -------------------------------------------------------------------- */
@@ -320,18 +320,18 @@ int TigerCompleteChain::SetModule( const char * pszModule )
             fpRT3 = NULL;
         }
 
-        if( pszModule )
+        if( pszModuleIn )
         {
             char        *pszFilename;
-        
-            pszFilename = poDS->BuildFilename( pszModule, "3" );
+
+            pszFilename = poDS->BuildFilename( pszModuleIn, "3" );
 
             fpRT3 = VSIFOpenL( pszFilename, "rb" );
 
             CPLFree( pszFilename );
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Close the shape point file, if open and free the list of        */
 /*      record ids.                                                     */
@@ -341,21 +341,21 @@ int TigerCompleteChain::SetModule( const char * pszModule )
         VSIFCloseL( fpShape );
         fpShape = NULL;
     }
-    
+
     CPLFree( panShapeRecordId );
     panShapeRecordId = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Try to open the RT2 file corresponding to this RT1 file.        */
 /* -------------------------------------------------------------------- */
-    if( pszModule != NULL )
+    if( pszModuleIn != NULL )
     {
         char    *pszFilename;
 
-        pszFilename = poDS->BuildFilename( pszModule, "2" );
+        pszFilename = poDS->BuildFilename( pszModuleIn, "2" );
 
         fpShape = VSIFOpenL( pszFilename, "rb" );
-        
+
         if( fpShape == NULL )
         {
             if( nRT1RecOffset == 0 )
@@ -365,7 +365,7 @@ int TigerCompleteChain::SetModule( const char * pszModule )
         }
         else
             panShapeRecordId = (int *)CPLCalloc(sizeof(int),(size_t)GetFeatureCount());
-        
+
         CPLFree( pszFilename );
     }
 
@@ -395,7 +395,7 @@ OGRFeature *TigerCompleteChain::GetFeature( int nRecordId )
     if( fpPrimary == NULL )
         return NULL;
 
-    if( VSIFSeekL( fpPrimary, (nRecordId+nRT1RecOffset) * nRecordLength, 
+    if( VSIFSeekL( fpPrimary, (nRecordId+nRT1RecOffset) * nRecordLength,
                   SEEK_SET ) != 0 )
     {
         CPLError( CE_Failure, CPLE_FileIO,
@@ -465,7 +465,7 @@ OGRFeature *TigerCompleteChain::GetFeature( int nRecordId )
         delete poFeature;
         return NULL;
     }
-    
+
     poLine->addPoint(atoi(GetField(achRecord, 210, 219)) / 1000000.0,
                      atoi(GetField(achRecord, 220, 228)) / 1000000.0 );
 
@@ -489,7 +489,7 @@ int TigerCompleteChain::AddShapePoints( int nTLID, int nRecordId,
 
     nShapeRecId = GetShapeRecordId( nRecordId, nTLID );
 
-    // -2 means an error occured.
+    // -2 means an error occurred.
     if( nShapeRecId == -2 )
         return FALSE;
 
@@ -503,7 +503,7 @@ int TigerCompleteChain::AddShapePoints( int nTLID, int nRecordId,
     char        achShapeRec[OGR_TIGER_RECBUF_LEN];
     int         nShapeRecLen = psRT2Info->nRecordLength + nRecordLength - psRT1Info->nRecordLength;
 
-    for( ; TRUE; nShapeRecId++ )
+    for( ; true; nShapeRecId++ )
     {
         int  nBytesRead = 0;
 
@@ -516,15 +516,15 @@ int TigerCompleteChain::AddShapePoints( int nTLID, int nRecordId,
             return FALSE;
         }
 
-        nBytesRead = VSIFReadL( achShapeRec, 1, psRT2Info->nRecordLength, 
-                                fpShape );
+        nBytesRead = static_cast<int>(VSIFReadL( achShapeRec, 1, psRT2Info->nRecordLength,
+                                fpShape ));
 
-        /* 
+        /*
         ** Handle case where the last record in the file is full.  We will
         ** try to read another record but not find it.  We require that we
-        ** have found at least one shape record for this case though. 
+        ** have found at least one shape record for this case though.
         */
-        if( nBytesRead <= 0 && VSIFEofL( fpShape ) 
+        if( nBytesRead <= 0 && VSIFEofL( fpShape )
             && poLine->getNumPoints() > 0 )
             break;
 
@@ -581,19 +581,19 @@ int TigerCompleteChain::GetShapeRecordId( int nChainId, int nTLID )
 
     if( fpShape == NULL || panShapeRecordId == NULL )
         return -1;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Do we already have the answer?                                  */
 /* -------------------------------------------------------------------- */
     if( panShapeRecordId[nChainId] != 0 )
         return panShapeRecordId[nChainId];
-    
+
 /* -------------------------------------------------------------------- */
 /*      If we don't already have this value, then search from the       */
 /*      previous known record.                                          */
 /* -------------------------------------------------------------------- */
     int iTestChain, nWorkingRecId;
-        
+
     for( iTestChain = nChainId-1;
          iTestChain >= 0 && panShapeRecordId[iTestChain] <= 0;
          iTestChain-- ) {}
@@ -673,7 +673,7 @@ int TigerCompleteChain::GetShapeRecordId( int nChainId, int nTLID )
 /************************************************************************/
 /*                           SetWriteModule()                           */
 /************************************************************************/
-int TigerCompleteChain::SetWriteModule( const char *pszFileCode, int nRecLen, 
+int TigerCompleteChain::SetWriteModule( const char *pszFileCode, int nRecLen,
                                         OGRFeature *poFeature )
 
 {
@@ -697,7 +697,7 @@ int TigerCompleteChain::SetWriteModule( const char *pszFileCode, int nRecLen,
         if( pszModule )
         {
             char        *pszFilename;
-        
+
             pszFilename = poDS->BuildFilename( pszModule, "3" );
 
             fpRT3 = VSIFOpenL( pszFilename, "ab" );
@@ -705,7 +705,7 @@ int TigerCompleteChain::SetWriteModule( const char *pszFileCode, int nRecLen,
             CPLFree( pszFilename );
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Close the shape point file, if open and free the list of        */
 /*      record ids.                                                     */
@@ -715,15 +715,15 @@ int TigerCompleteChain::SetWriteModule( const char *pszFileCode, int nRecLen,
         VSIFCloseL( fpShape );
         fpShape = NULL;
     }
-    
+
     if( pszModule )
     {
         char        *pszFilename;
-        
+
         pszFilename = poDS->BuildFilename( pszModule, "2" );
-        
+
         fpShape = VSIFOpenL( pszFilename, "ab" );
-        
+
         CPLFree( pszFilename );
     }
 
@@ -740,7 +740,7 @@ OGRErr TigerCompleteChain::CreateFeature( OGRFeature *poFeature )
     char        szRecord[OGR_TIGER_RECBUF_LEN];
     OGRLineString *poLine = (OGRLineString *) poFeature->GetGeometryRef();
 
-    if( poLine == NULL 
+    if( poLine == NULL
         || (poLine->getGeometryType() != wkbLineString
             && poLine->getGeometryType() != wkbLineString25D) )
         return OGRERR_FAILURE;
@@ -753,8 +753,8 @@ OGRErr TigerCompleteChain::CreateFeature( OGRFeature *poFeature )
     memset( szRecord, ' ', psRT1Info->nRecordLength );
     WriteFields( psRT1Info, poFeature, szRecord );
     WritePoint( szRecord, 191, poLine->getX(0), poLine->getY(0) );
-    WritePoint( szRecord, 210, 
-                poLine->getX(poLine->getNumPoints()-1), 
+    WritePoint( szRecord, 210,
+                poLine->getX(poLine->getNumPoints()-1),
                 poLine->getY(poLine->getNumPoints()-1) );
     WriteRecord( szRecord, psRT1Info->nRecordLength, "1" );
 
@@ -783,21 +783,21 @@ OGRErr TigerCompleteChain::CreateFeature( OGRFeature *poFeature )
             memset( szRecord, ' ', psRT2Info->nRecordLength );
 
             WriteField( poFeature, "TLID", szRecord, 6, 15, 'R', 'N' );
-            
-            sprintf( szTemp, "%3d", nRTSQ );
+
+            snprintf( szTemp, sizeof(szTemp), "%3d", nRTSQ );
             strncpy( ((char *)szRecord) + 15, szTemp, 4 );
 
             for( i = 0; i < 10; i++ )
             {
                 if( iPoint < nPoints-1 )
-                    WritePoint( szRecord, 19+19*i, 
+                    WritePoint( szRecord, 19+19*i,
                                 poLine->getX(iPoint), poLine->getY(iPoint) );
                 else
                     WritePoint( szRecord, 19+19*i, 0.0, 0.0 );
 
                 iPoint++;
             }
-            
+
             WriteRecord( szRecord, psRT2Info->nRecordLength, "2", fpShape );
 
             nRTSQ++;
diff --git a/ogr/ogrsf_frmts/tiger/tigerfilebase.cpp b/ogr/ogrsf_frmts/tiger/tigerfilebase.cpp
index 15fe77e..5bb96e6 100644
--- a/ogr/ogrsf_frmts/tiger/tigerfilebase.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerfilebase.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigerfilebase.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: tigerfilebase.cpp 33706 2016-03-11 13:33:27Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerBaseFile class, providing common services to all
@@ -34,27 +34,26 @@
 #include "cpl_error.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: tigerfilebase.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: tigerfilebase.cpp 33706 2016-03-11 13:33:27Z goatbar $");
 
 /************************************************************************/
 /*                           TigerFileBase()                            */
 /************************************************************************/
 
 TigerFileBase::TigerFileBase( const TigerRecordInfo *psRTInfoIn,
-                              const char            *m_pszFileCodeIn )
-
-{
-    pszShortModule = NULL;
-    pszModule = NULL;
-    fpPrimary = NULL;
-    poFeatureDefn = NULL;
-    nFeatures = 0;
-    nVersionCode = 0;
-    nVersion = TIGER_Unknown;
-
-    psRTInfo = psRTInfoIn;
-    m_pszFileCode = m_pszFileCodeIn;
-}
+                              const char            *m_pszFileCodeIn ) :
+    poDS(NULL),
+    pszModule(NULL),
+    pszShortModule(NULL),
+    fpPrimary(NULL),
+    poFeatureDefn(NULL),
+    nFeatures(0),
+    nRecordLength(0),
+    nVersionCode(0),
+    nVersion(TIGER_Unknown),
+    psRTInfo(psRTInfoIn),
+    m_pszFileCode(m_pszFileCodeIn)
+{ }
 
 /************************************************************************/
 /*                           ~TigerFileBase()                           */
@@ -93,7 +92,7 @@ int TigerFileBase::OpenFile( const char * pszModuleToOpen,
     pszModule = NULL;
     CPLFree( pszShortModule );
     pszShortModule = NULL;
-    
+
     if( fpPrimary != NULL )
     {
         VSIFCloseL( fpPrimary );
@@ -154,7 +153,7 @@ int TigerFileBase::EstablishRecordLength( VSILFILE * fp )
 {
     char        chCurrent;
     int         nRecLen = 0;
-    
+
     if( fp == NULL || VSIFSeekL( fp, 0, SEEK_SET ) != 0 )
         return -1;
 
@@ -176,7 +175,7 @@ int TigerFileBase::EstablishRecordLength( VSILFILE * fp )
     {
         return -1;
     }
-    
+
     nRecLen++; /* for the 10 or 13 we encountered */
 
 /* -------------------------------------------------------------------- */
@@ -218,12 +217,12 @@ void TigerFileBase::EstablishFeatureCount()
 /*      (including line terminators).  Get the total file size, and     */
 /*      divide by this length to get the presumed number of records.    */
 /* -------------------------------------------------------------------- */
-    long        nFileSize;
-    
+    vsi_l_offset        nFileSize;
+
     VSIFSeekL( fpPrimary, 0, SEEK_END );
     nFileSize = VSIFTellL( fpPrimary );
 
-    if( (nFileSize % nRecordLength) != 0 )
+    if( (nFileSize % (vsi_l_offset)nRecordLength) != 0 )
     {
         CPLError( CE_Warning, CPLE_FileIO,
                   "TigerFileBase::EstablishFeatureCount(): "
@@ -231,7 +230,10 @@ void TigerFileBase::EstablishFeatureCount()
                   (int) nFileSize, (int) nRecordLength );
     }
 
-    nFeatures = nFileSize / nRecordLength;
+    if( nFileSize / (vsi_l_offset)nRecordLength > (vsi_l_offset)INT_MAX )
+        nFeatures = INT_MAX;
+    else
+        nFeatures = static_cast<int>(nFileSize / (vsi_l_offset)nRecordLength);
 }
 
 /************************************************************************/
@@ -244,7 +246,7 @@ const char* TigerFileBase::GetField( const char * pachRawDataRecord,
 {
     char         aszField[128];
     int                 nLength = nEndChar - nStartChar + 1;
-    
+
     CPLAssert( nEndChar - nStartChar + 2 < (int) sizeof(aszField) );
 
     strncpy( aszField, pachRawDataRecord + nStartChar - 1, nLength );
@@ -282,8 +284,8 @@ void TigerFileBase::SetField( OGRFeature *poFeature, const char *pszField,
 /*      formatting, or leave blank if not found.                        */
 /************************************************************************/
 
-int TigerFileBase::WriteField( OGRFeature *poFeature, const char *pszField, 
-                               char *pachRecord, int nStart, int nEnd, 
+int TigerFileBase::WriteField( OGRFeature *poFeature, const char *pszField,
+                               char *pachRecord, int nStart, int nEnd,
                                char chFormat, char chType )
 
 {
@@ -297,27 +299,27 @@ int TigerFileBase::WriteField( OGRFeature *poFeature, const char *pszField,
 
     if( chType == 'N' && chFormat == 'L' )
     {
-        sprintf( szFormat, "%%0%dd", nEnd - nStart + 1 );
-        sprintf( szValue, szFormat, poFeature->GetFieldAsInteger( iField ) );
+        snprintf( szFormat, sizeof(szFormat), "%%0%dd", nEnd - nStart + 1 );
+        snprintf( szValue, sizeof(szValue), szFormat, poFeature->GetFieldAsInteger( iField ) );
     }
     else if( chType == 'N' && chFormat == 'R' )
     {
-        sprintf( szFormat, "%%%dd", nEnd - nStart + 1 );
-        sprintf( szValue, szFormat, poFeature->GetFieldAsInteger( iField ) );
+        snprintf( szFormat, sizeof(szFormat), "%%%dd", nEnd - nStart + 1 );
+        snprintf( szValue, sizeof(szValue), szFormat, poFeature->GetFieldAsInteger( iField ) );
     }
     else if( chType == 'A' && chFormat == 'L' )
     {
-        strncpy( szValue, poFeature->GetFieldAsString( iField ), 
+        strncpy( szValue, poFeature->GetFieldAsString( iField ),
                  sizeof(szValue) - 1 );
         szValue[sizeof(szValue) - 1] = 0;
         if( (int) strlen(szValue) < nEnd - nStart + 1 )
-            memset( szValue + strlen(szValue), ' ', 
+            memset( szValue + strlen(szValue), ' ',
                     nEnd - nStart + 1 - strlen(szValue) );
     }
     else if( chType == 'A' && chFormat == 'R' )
     {
-        sprintf( szFormat, "%%%ds", nEnd - nStart + 1 );
-        sprintf( szValue, szFormat, poFeature->GetFieldAsString( iField ) );
+        snprintf( szFormat, sizeof(szFormat), "%%%ds", nEnd - nStart + 1 );
+        snprintf( szValue, sizeof(szValue), szFormat, poFeature->GetFieldAsString( iField ) );
     }
     else
     {
@@ -334,7 +336,7 @@ int TigerFileBase::WriteField( OGRFeature *poFeature, const char *pszField,
 /*                             WritePoint()                             */
 /************************************************************************/
 
-int TigerFileBase::WritePoint( char *pachRecord, int nStart, 
+int TigerFileBase::WritePoint( char *pachRecord, int nStart,
                                double dfX, double dfY )
 
 {
@@ -346,7 +348,7 @@ int TigerFileBase::WritePoint( char *pachRecord, int nStart,
     }
     else
     {
-        sprintf( szTemp, "%+10d%+9d", 
+        snprintf( szTemp, sizeof(szTemp), "%+10d%+9d",
                  (int) floor(dfX * 1000000 + 0.5),
                  (int) floor(dfY * 1000000 + 0.5) );
         strncpy( pachRecord + nStart - 1, szTemp, 19 );
@@ -359,7 +361,7 @@ int TigerFileBase::WritePoint( char *pachRecord, int nStart,
 /*                            WriteRecord()                             */
 /************************************************************************/
 
-int TigerFileBase::WriteRecord( char *pachRecord, int nRecLen, 
+int TigerFileBase::WriteRecord( char *pachRecord, int nRecLen,
                                 const char *pszType, VSILFILE * fp )
 
 {
@@ -378,7 +380,7 @@ int TigerFileBase::WriteRecord( char *pachRecord, int nRecLen,
          (!EQUAL(pszType, "5")) )
     {
         char    szVersion[5];
-        sprintf( szVersion, "%04d", poDS->GetVersionCode() );
+        snprintf( szVersion, sizeof(szVersion), "%04d", poDS->GetVersionCode() );
         strncpy( pachRecord + 1, szVersion, 4 );
     }
 
@@ -404,13 +406,13 @@ int TigerFileBase::SetWriteModule( const char *pszExtension,
     const char *pszTargetModule = poFeature->GetFieldAsString( "MODULE" );
     char        szFullModule[30];
 
-    /* TODO/notdef: eventually more logic based on FILE and STATE/COUNTY can 
+    /* TODO/notdef: eventually more logic based on FILE and STATE/COUNTY can
        be inserted here. */
 
     if( pszTargetModule == NULL )
         return FALSE;
 
-    sprintf( szFullModule, "%s.RT", pszTargetModule );
+    snprintf( szFullModule, sizeof(szFullModule), "%s.RT", pszTargetModule );
 
 /* -------------------------------------------------------------------- */
 /*      Is this our current module?                                     */
@@ -442,7 +444,7 @@ int TigerFileBase::SetWriteModule( const char *pszExtension,
         poDS->DeleteModuleFiles( szFullModule );
         poDS->AddModule( szFullModule );
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Does this file already exist?                                   */
 /* -------------------------------------------------------------------- */
@@ -463,27 +465,27 @@ int TigerFileBase::SetWriteModule( const char *pszExtension,
 /************************************************************************/
 /*                           AddFieldDefns()                            */
 /************************************************************************/
-void TigerFileBase::AddFieldDefns(const TigerRecordInfo *psRTInfo,
-                                  OGRFeatureDefn  *poFeatureDefn)
+void TigerFileBase::AddFieldDefns(const TigerRecordInfo *psRTInfoIn,
+                                  OGRFeatureDefn  *poFeatureDefnIn)
 {
     OGRFieldDefn        oField("",OFTInteger);
     int i, bLFieldHack;
 
-    bLFieldHack = 
-        CSLTestBoolean( CPLGetConfigOption( "TIGER_LFIELD_AS_STRING", "NO" ) );
-    
-    for (i=0; i<psRTInfo->nFieldCount; ++i) {
-        if (psRTInfo->pasFields[i].bDefine) {
-            OGRFieldType eFT = (OGRFieldType)psRTInfo->pasFields[i].OGRtype;
+    bLFieldHack =
+        CPLTestBool( CPLGetConfigOption( "TIGER_LFIELD_AS_STRING", "NO" ) );
+
+    for (i=0; i<psRTInfoIn->nFieldCount; ++i) {
+        if (psRTInfoIn->pasFields[i].bDefine) {
+            OGRFieldType eFT = (OGRFieldType)psRTInfoIn->pasFields[i].OGRtype;
 
-            if( bLFieldHack 
-                && psRTInfo->pasFields[i].cFmt == 'L' 
-                && psRTInfo->pasFields[i].cType == 'N' )
+            if( bLFieldHack
+                && psRTInfoIn->pasFields[i].cFmt == 'L'
+                && psRTInfoIn->pasFields[i].cType == 'N' )
                 eFT = OFTString;
 
-            oField.Set( psRTInfo->pasFields[i].pszFieldName, eFT, 
-                        psRTInfo->pasFields[i].nLen );
-            poFeatureDefn->AddFieldDefn( &oField );
+            oField.Set( psRTInfoIn->pasFields[i].pszFieldName, eFT,
+                        psRTInfoIn->pasFields[i].nLen );
+            poFeatureDefnIn->AddFieldDefn( &oField );
         }
     }
 }
@@ -492,18 +494,18 @@ void TigerFileBase::AddFieldDefns(const TigerRecordInfo *psRTInfo,
 /*                             SetFields()                              */
 /************************************************************************/
 
-void TigerFileBase::SetFields(const TigerRecordInfo *psRTInfo,
+void TigerFileBase::SetFields(const TigerRecordInfo *psRTInfoIn,
                               OGRFeature      *poFeature,
                               char            *achRecord)
 {
   int i;
-  for (i=0; i<psRTInfo->nFieldCount; ++i) {
-    if (psRTInfo->pasFields[i].bSet) {
+  for (i=0; i<psRTInfoIn->nFieldCount; ++i) {
+    if (psRTInfoIn->pasFields[i].bSet) {
       SetField( poFeature,
-                psRTInfo->pasFields[i].pszFieldName,
-                achRecord, 
-                psRTInfo->pasFields[i].nBeg,
-                psRTInfo->pasFields[i].nEnd );
+                psRTInfoIn->pasFields[i].pszFieldName,
+                achRecord,
+                psRTInfoIn->pasFields[i].nBeg,
+                psRTInfoIn->pasFields[i].nEnd );
     }
   }
 }
@@ -511,20 +513,20 @@ void TigerFileBase::SetFields(const TigerRecordInfo *psRTInfo,
 /************************************************************************/
 /*                             WriteField()                             */
 /************************************************************************/
-void TigerFileBase::WriteFields(const TigerRecordInfo *psRTInfo,
+void TigerFileBase::WriteFields(const TigerRecordInfo *psRTInfoIn,
                                 OGRFeature      *poFeature,
                                 char            *szRecord)
 {
   int i;
-  for (i=0; i<psRTInfo->nFieldCount; ++i) {
-    if (psRTInfo->pasFields[i].bWrite) {
+  for (i=0; i<psRTInfoIn->nFieldCount; ++i) {
+    if (psRTInfoIn->pasFields[i].bWrite) {
       WriteField( poFeature,
-                  psRTInfo->pasFields[i].pszFieldName,
-                  szRecord, 
-                  psRTInfo->pasFields[i].nBeg,
-                  psRTInfo->pasFields[i].nEnd,
-                  psRTInfo->pasFields[i].cFmt,
-                  psRTInfo->pasFields[i].cType );
+                  psRTInfoIn->pasFields[i].pszFieldName,
+                  szRecord,
+                  psRTInfoIn->pasFields[i].nBeg,
+                  psRTInfoIn->pasFields[i].nEnd,
+                  psRTInfoIn->pasFields[i].cFmt,
+                  psRTInfoIn->pasFields[i].cType );
     }
   }
 }
@@ -535,13 +537,13 @@ void TigerFileBase::WriteFields(const TigerRecordInfo *psRTInfo,
 /*                             SetModule()                              */
 /************************************************************************/
 
-int TigerFileBase::SetModule( const char * pszModule )
+int TigerFileBase::SetModule( const char * pszModuleIn )
 
 {
     if (m_pszFileCode == NULL)
         return FALSE;
 
-    if( !OpenFile( pszModule, m_pszFileCode ) )
+    if( !OpenFile( pszModuleIn, m_pszFileCode ) )
         return FALSE;
 
     EstablishFeatureCount();
diff --git a/ogr/ogrsf_frmts/tiger/tigerinfo.cpp b/ogr/ogrsf_frmts/tiger/tigerinfo.cpp
index 0213810..1e149b4 100644
--- a/ogr/ogrsf_frmts/tiger/tigerinfo.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerinfo.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigerinfo.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: tigerinfo.cpp 33706 2016-03-11 13:33:27Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Simple client for viewing OGR driver data.
@@ -33,7 +33,7 @@
 
 #include "ogr_tiger.h"
 
-CPL_CVSID("$Id: tigerinfo.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: tigerinfo.cpp 33706 2016-03-11 13:33:27Z goatbar $");
 
 int     bReadOnly = FALSE;
 int     bVerbose = TRUE;
@@ -51,7 +51,7 @@ int main( int nArgc, char ** papszArgv )
 {
     const char  *pszDataSource = NULL;
     char        **papszLayers = NULL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Register format(s).                                             */
 /* -------------------------------------------------------------------- */
@@ -102,7 +102,7 @@ int main( int nArgc, char ** papszArgv )
     if( poDS == NULL )
     {
         OGRSFDriverRegistrar    *poR = OGRSFDriverRegistrar::GetRegistrar();
-        
+
         printf( "FAILURE:\n"
                 "Unable to open datasource `%s' with the following drivers.\n",
                 pszDataSource );
@@ -123,12 +123,10 @@ int main( int nArgc, char ** papszArgv )
         printf( "INFO: Open of `%s'\n"
                 "using driver `%s' successful.\n",
                 pszDataSource, poDriver->GetName() );
-        printf("Tiger Version: %s\n", 
+        printf("Tiger Version: %s\n",
                TigerVersionString(((OGRTigerDataSource*)poDS)->GetVersion()));
     }
 
-
-
     if( bVerbose && !EQUAL(pszDataSource,poDS->GetName()) )
     {
         printf( "INFO: Internal data source name `%s'\n"
@@ -136,7 +134,6 @@ int main( int nArgc, char ** papszArgv )
                 poDS->GetName(), pszDataSource );
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Process each data source layer.                                 */
 /* -------------------------------------------------------------------- */
@@ -172,7 +169,7 @@ int main( int nArgc, char ** papszArgv )
 #ifdef DBMALLOC
     malloc_dump(1);
 #endif
-    
+
     return 0;
 }
 
@@ -197,7 +194,7 @@ static void ReportOnLayer( OGRLayer * poLayer )
     OGRFeatureDefn      *poDefn = poLayer->GetLayerDefn();
 
     printf( "\n" );
-    
+
     printf( "Layer name: %s\n", poDefn->GetName() );
 
     printf( "Feature Count: %d\n", poLayer->GetFeatureCount() );
@@ -205,7 +202,7 @@ static void ReportOnLayer( OGRLayer * poLayer )
     if( bVerbose )
     {
         char    *pszWKT;
-        
+
         if( poLayer->GetSpatialRef() == NULL )
             pszWKT = CPLStrdup( "(NULL)" );
         else
@@ -214,7 +211,7 @@ static void ReportOnLayer( OGRLayer * poLayer )
         printf( "Layer SRS WKT: %s\n", pszWKT );
         CPLFree( pszWKT );
     }
-    
+
     for( int iAttr = 0; iAttr < poDefn->GetFieldCount(); iAttr++ )
     {
         OGRFieldDefn    *poField = poDefn->GetFieldDefn( iAttr );
diff --git a/ogr/ogrsf_frmts/tiger/tigerlandmarks.cpp b/ogr/ogrsf_frmts/tiger/tigerlandmarks.cpp
index d5b8d32..1a4e6e9 100644
--- a/ogr/ogrsf_frmts/tiger/tigerlandmarks.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerlandmarks.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigerlandmarks.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: tigerlandmarks.cpp 33706 2016-03-11 13:33:27Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerLandmarks, providing access to .RT7 files.
@@ -30,7 +30,7 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerlandmarks.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: tigerlandmarks.cpp 33706 2016-03-11 13:33:27Z goatbar $");
 
 #define FILE_CODE "7"
 
@@ -102,6 +102,6 @@ OGRFeature *TigerLandmarks::GetFeature( int nRecordId )
 
 OGRErr TigerLandmarks::CreateFeature( OGRFeature *poFeature )
 {
-  return TigerPoint::CreateFeature( poFeature, 
+  return TigerPoint::CreateFeature( poFeature,
                                     55 );
 }
diff --git a/ogr/ogrsf_frmts/tiger/tigeroverunder.cpp b/ogr/ogrsf_frmts/tiger/tigeroverunder.cpp
index 62c109c..b28c7fa 100644
--- a/ogr/ogrsf_frmts/tiger/tigeroverunder.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigeroverunder.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigeroverunder.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: tigeroverunder.cpp 33706 2016-03-11 13:33:27Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerOverUnder, providing access to .RTU files.
@@ -30,7 +30,7 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigeroverunder.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: tigeroverunder.cpp 33706 2016-03-11 13:33:27Z goatbar $");
 
 #define FILE_CODE       "U"
 
@@ -81,6 +81,6 @@ OGRFeature *TigerOverUnder::GetFeature( int nRecordId )
 
 OGRErr TigerOverUnder::CreateFeature( OGRFeature *poFeature )
 {
-  return TigerPoint::CreateFeature( poFeature, 
+  return TigerPoint::CreateFeature( poFeature,
                                     62 );
 }
diff --git a/ogr/ogrsf_frmts/tiger/tigerpip.cpp b/ogr/ogrsf_frmts/tiger/tigerpip.cpp
index 9ab8312..1855a4e 100644
--- a/ogr/ogrsf_frmts/tiger/tigerpip.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerpip.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigerpip.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: tigerpip.cpp 33706 2016-03-11 13:33:27Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerPIP, providing access to .RTP files.
@@ -30,7 +30,7 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerpip.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: tigerpip.cpp 33706 2016-03-11 13:33:27Z goatbar $");
 
 #define FILE_CODE "P"
 
@@ -98,6 +98,6 @@ OGRFeature *TigerPIP::GetFeature( int nRecordId )
 
 OGRErr TigerPIP::CreateFeature( OGRFeature *poFeature )
 {
-  return TigerPoint::CreateFeature( poFeature, 
+  return TigerPoint::CreateFeature( poFeature,
                                     26 );
 }
diff --git a/ogr/ogrsf_frmts/tiger/tigerpoint.cpp b/ogr/ogrsf_frmts/tiger/tigerpoint.cpp
index dcede73..b6705b4 100644
--- a/ogr/ogrsf_frmts/tiger/tigerpoint.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerpoint.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigerpoint.cpp 23871 2012-02-02 03:24:07Z warmerdam $
+ * $Id: tigerpoint.cpp 33706 2016-03-11 13:33:27Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerPoint class.
@@ -30,15 +30,15 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerpoint.cpp 23871 2012-02-02 03:24:07Z warmerdam $");
+CPL_CVSID("$Id: tigerpoint.cpp 33706 2016-03-11 13:33:27Z goatbar $");
 
 /************************************************************************/
 /*                             TigerPoint()                             */
 /************************************************************************/
-TigerPoint::TigerPoint( int bRequireGeom, const TigerRecordInfo *psRTInfoIn,
+TigerPoint::TigerPoint( int bRequireGeomIn, const TigerRecordInfo *psRTInfoIn,
                         const char            *m_pszFileCodeIn ) : TigerFileBase(psRTInfoIn, m_pszFileCodeIn)
 {
-    this->bRequireGeom = bRequireGeom;
+    this->bRequireGeom = bRequireGeomIn;
 }
 
 /************************************************************************/
@@ -98,14 +98,14 @@ OGRFeature *TigerPoint::GetFeature( int nRecordId,
     if( dfX != 0.0 || dfY != 0.0 ) {
         poFeature->SetGeometryDirectly( new OGRPoint( dfX, dfY ) );
     }
-        
+
     return poFeature;
 }
 
 /************************************************************************/
 /*                           CreateFeature()                            */
 /************************************************************************/
-OGRErr TigerPoint::CreateFeature( OGRFeature *poFeature, 
+OGRErr TigerPoint::CreateFeature( OGRFeature *poFeature,
                                   int pointIndex)
 
 {
@@ -119,7 +119,7 @@ OGRErr TigerPoint::CreateFeature( OGRFeature *poFeature,
 
     WriteFields( psRTInfo, poFeature, szRecord );
 
-    if( poPoint != NULL 
+    if( poPoint != NULL
         && (poPoint->getGeometryType() == wkbPoint
             || poPoint->getGeometryType() == wkbPoint25D) ) {
         WritePoint( szRecord, pointIndex, poPoint->getX(), poPoint->getY() );
diff --git a/ogr/ogrsf_frmts/tiger/tigerpolygon.cpp b/ogr/ogrsf_frmts/tiger/tigerpolygon.cpp
index fcd3905..ff32180 100644
--- a/ogr/ogrsf_frmts/tiger/tigerpolygon.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerpolygon.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigerpolygon.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: tigerpolygon.cpp 33706 2016-03-11 13:33:27Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerPolygon, providing access to .RTA files.
@@ -31,7 +31,7 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerpolygon.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: tigerpolygon.cpp 33706 2016-03-11 13:33:27Z goatbar $");
 
 static const TigerFieldInfo rtA_2002_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
@@ -382,15 +382,16 @@ static const TigerRecordInfo rtS_info =
 /************************************************************************/
 
 TigerPolygon::TigerPolygon( OGRTigerDataSource * poDSIn,
-                            CPL_UNUSED const char * pszPrototypeModule )
+                            CPL_UNUSED const char * pszPrototypeModule ) :
+    fpRTS(NULL),
+    bUsingRTS(TRUE),
+    nRTSRecLen(0)
 {
     poDS = poDSIn;
     poFeatureDefn = new OGRFeatureDefn( "Polygon" );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbNone );
 
-    fpRTS = NULL;
-    bUsingRTS = TRUE;
 
     if( poDS->GetVersion() >= TIGER_2004 ) {
         psRTAInfo = &rtA_2004_info;
@@ -440,14 +441,14 @@ TigerPolygon::~TigerPolygon()
 /*                             SetModule()                              */
 /************************************************************************/
 
-int TigerPolygon::SetModule( const char * pszModule )
+int TigerPolygon::SetModule( const char * pszModuleIn )
 
 {
-    if( !OpenFile( pszModule, "A" ) )
+    if( !OpenFile( pszModuleIn, "A" ) )
         return FALSE;
 
     EstablishFeatureCount();
-    
+
 /* -------------------------------------------------------------------- */
 /*      Open the RTS file                                               */
 /* -------------------------------------------------------------------- */
@@ -459,11 +460,11 @@ int TigerPolygon::SetModule( const char * pszModule )
             fpRTS = NULL;
         }
 
-        if( pszModule )
+        if( pszModuleIn )
         {
             char        *pszFilename;
-        
-            pszFilename = poDS->BuildFilename( pszModule, "S" );
+
+            pszFilename = poDS->BuildFilename( pszModuleIn, "S" );
 
             fpRTS = VSIFOpenL( pszFilename, "rb" );
 
@@ -472,7 +473,7 @@ int TigerPolygon::SetModule( const char * pszModule )
             nRTSRecLen = EstablishRecordLength( fpRTS );
         }
     }
-    
+
     return TRUE;
 }
 
@@ -550,7 +551,7 @@ OGRFeature *TigerPolygon::GetFeature( int nRecordId )
         SetFields( psRTSInfo, poFeature, achRTSRec );
 
     }
-    
+
     return poFeature;
 }
 
@@ -558,7 +559,7 @@ OGRFeature *TigerPolygon::GetFeature( int nRecordId )
 /*                           SetWriteModule()                           */
 /************************************************************************/
 
-int TigerPolygon::SetWriteModule( const char *pszFileCode, int nRecLen, 
+int TigerPolygon::SetWriteModule( const char *pszFileCode, int nRecLen,
                                   OGRFeature *poFeature )
 
 {
@@ -582,7 +583,7 @@ int TigerPolygon::SetWriteModule( const char *pszFileCode, int nRecLen,
         if( pszModule )
         {
             char        *pszFilename;
-        
+
             pszFilename = poDS->BuildFilename( pszModule, "S" );
 
             fpRTS = VSIFOpenL( pszFilename, "ab" );
@@ -590,7 +591,7 @@ int TigerPolygon::SetWriteModule( const char *pszFileCode, int nRecLen,
             CPLFree( pszFilename );
         }
     }
-    
+
     return TRUE;
 }
 
diff --git a/ogr/ogrsf_frmts/tiger/tigerpolygoneconomic.cpp b/ogr/ogrsf_frmts/tiger/tigerpolygoneconomic.cpp
index c9e8fd1..8bba92b 100644
--- a/ogr/ogrsf_frmts/tiger/tigerpolygoneconomic.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerpolygoneconomic.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigerpolygoneconomic.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: tigerpolygoneconomic.cpp 33706 2016-03-11 13:33:27Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerPolygonEconomic, providing access to .RTE files.
@@ -30,13 +30,13 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerpolygoneconomic.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: tigerpolygoneconomic.cpp 33706 2016-03-11 13:33:27Z goatbar $");
 
 #define FILE_CODE       "E"
 
 /* I think this was the expected RTE format, but was never deployed, leaving
-   it in the code in case I am missing something. 
-   
+   it in the code in case I am missing something.
+
 static TigerFieldInfo rtE_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
diff --git a/ogr/ogrsf_frmts/vdv/GNUmakefile b/ogr/ogrsf_frmts/vdv/GNUmakefile
new file mode 100644
index 0000000..fe3c87a
--- /dev/null
+++ b/ogr/ogrsf_frmts/vdv/GNUmakefile
@@ -0,0 +1,14 @@
+
+
+include ../../../GDALmake.opt
+
+OBJ	=	ogrvdvdatasource.o
+
+CPPFLAGS	:=	-I.. -I../.. $(CPPFLAGS)
+
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+$(O_OBJ):	ogr_vdv.h
\ No newline at end of file
diff --git a/ogr/ogrsf_frmts/vdv/drv_vdv.html b/ogr/ogrsf_frmts/vdv/drv_vdv.html
new file mode 100644
index 0000000..49001eb
--- /dev/null
+++ b/ogr/ogrsf_frmts/vdv/drv_vdv.html
@@ -0,0 +1,80 @@
+<html>
+<head>
+<title>VDV - VDV-451/VDV-452/INTREST Data Format</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>VDV - VDV-451/VDV-452/INTREST Data Format</h1>
+
+(GDAL/OGR >= 2.1.0)<p>
+
+This driver can read and create text files following the VDV-451 file format, which is a text
+format similar to CSV files, potentially containing several layers within the same file.<p>
+
+It supports in particular reading 2 "profiles" :
+<ul>
+<li>(read/write) VDV-452 standard for route network / timetable</li>
+<li>(read/only) "INTREST Data format" used by the <a href="https://www.data.gv.at/katalog/dataset/3fefc838-791d-4dde-975b-a4131a54e7c5">
+Austrian official open government street graph</a></li>
+</ul>
+
+<p>
+The generic reader/writer for VDV-451/VDV-452 can support arbitrarily large files. For
+the INTREST data case, for combined layers in a single file, the driver ingests
+the whole file in memory to reconstruct the Link layer.</p>
+
+<p>Interleave reading among layers is supported in files with multiple layers.</p>
+
+<h2>Creations issues</h2>
+
+<p>The driver can create new layers (either in the same file, or in separate
+files in the same directory). It can append a new layer into an existing file, but
+it cannot append/edit/delete features to an existing layer, or modify the
+attribute structure of an existing layer after features have been written.</p>
+
+<p>The following dataset creation options are available:</p>
+<ul>
+<li><b>SINGLE_FILE</b>=YES/NO. Whether several layers should be put in the same
+file. If NO, the name is assumed to be a directory name. Defaults to YES.</li>
+</ul>
+
+<p>The following layer creation options are available:</p>
+<ul>
+<li><b>EXTENSION</b>=string. Extension used when creation files in separate layers,
+i.e. only for SINGLE_FILE=NO dataset creation option. Defaults to x10.</li>
+<li><b>PROFILE</b>=GENERIC/VDV-452/VDV-452-ENGLISH/VDV-452-GERMAN. Defaults to GENERIC.
+Describe which profile the writer should conform to. VDV-452 will restrict layer and field names
+to be the one allowed by the VDV-452 standard (either in English or German).
+VDV-452-ENGLISH and VDV-452-GERMAN will restrict the VDV-452 to the specified
+language. The configuration file describing VDV-452 table and field names is
+<a href="http://svn.osgeo.org/gdal/trunk/gdal/data/vdv452.xml">vdv452.xml</a>
+located in the GDAL_DATA directory.</li>
+<li><b>PROFILE_STRICT</b>=YES/NO. Whether checks of profile should be strict.
+In strict mode, unexpected layer or field names will be rejected. Defaults to NO.</li>
+<li><b>CREATE_ALL_FIELDS</b>=YES/NO. Whether all fields of predefined profiles
+should be created at layer creation. Defaults to YES.</li>
+<li><b>STANDARD_HEADER</b>=YES/NO. Whether to write standard header fields (i.e
+mod, src, chs, ver, ifv, dve, fft). If set to NO, only explicitly specified HEADER_xxx
+fields will be written. Defaults to YES.</li>
+<li><b>HEADER_SRC</b>=string: Value of the src header field. Defaults to UNKNOWN.</li>
+<li><b>HEADER_SRC_DATE</b>=string: Value of the date of the src header field as DD.MM.YYYY. Defaults to current date (in GMT).</li>
+<li><b>HEADER_SRC_TIME</b>=string: Value of the time of the src header field as HH.MM.SS. Defaults to current time (in GMT)</li>
+<li><b>HEADER_CHS</b>=string: Value of the chs header field. Defaults to ISO8859-1.</li>
+<li><b>HEADER_VER</b>=string: Value of the ver header field. Defaults to 1.4.</li>
+<li><b>HEADER_IFV</b>=string: Value of the ifv header field. Defaults to 1.4.</li>
+<li><b>HEADER_DVE</b>=string: Value of the dve header field. Defaults to 1.4.</li>
+<li><b>HEADER_FFT</b>=string: Value of the fft header field. Defaults to '' (empty string).</li>
+<li><b>HEADER_</b><i>xxx</i>=string: Value of the <i>xxx</i> (user defined) header field.</li>
+</ul>
+
+<h2>Links</h2>
+
+<ul>
+<li><a href="https://www.vdv.de/vdv-schrift-451.pdfx?forced=true">VDV-451 file format</a> (German)</li>
+<li><a href="https://www.vdv.de/452--sdsv15.pdfx?forced=true">VDV-452 data model</a> (German)</li>
+<li><a href="http://open.gip.gv.at/ogd/0_dokumentation_gipat_ogd.pdf">Austrian INTREST data format</a> (German)</li>
+</ul>
+
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/vdv/makefile.vc b/ogr/ogrsf_frmts/vdv/makefile.vc
new file mode 100644
index 0000000..b6578af
--- /dev/null
+++ b/ogr/ogrsf_frmts/vdv/makefile.vc
@@ -0,0 +1,15 @@
+
+OBJ	=	ogrvdvdatasource.obj
+EXTRAFLAGS =	-I.. -I..\..
+
+GDAL_ROOT	=	..\..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+default:	$(OBJ)
+
+clean:
+	-del *.obj *.pdb
+
+
+
diff --git a/ogr/ogrsf_frmts/vdv/ogr_vdv.h b/ogr/ogrsf_frmts/vdv/ogr_vdv.h
new file mode 100644
index 0000000..157737b
--- /dev/null
+++ b/ogr/ogrsf_frmts/vdv/ogr_vdv.h
@@ -0,0 +1,219 @@
+/******************************************************************************
+ * $Id: ogr_vdv.h 33713 2016-03-12 17:41:57Z goatbar $
+ *
+ * Project:  VDV Translator
+ * Purpose:  Implements OGRVDVDriver.
+ * Author:   Even Rouault, even.rouault at spatialys.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef OGR_VDV_H_INCLUDED
+#define OGR_VDV_H_INCLUDED
+
+#include "ogrsf_frmts.h"
+#include <vector>
+#include <map>
+
+class OGRVDVDataSource;
+
+/************************************************************************/
+/*                        OGRIDFDataSource                              */
+/************************************************************************/
+
+class OGRIDFDataSource : public GDALDataset
+{
+    VSILFILE*           m_fpL;
+    bool                m_bHasParsed;
+    GDALDataset        *m_poMemDS;
+
+    void                Parse();
+
+  public:
+                        OGRIDFDataSource(VSILFILE* fpL);
+                        ~OGRIDFDataSource();
+
+    virtual int                 GetLayerCount();
+    virtual OGRLayer*           GetLayer( int );
+};
+
+/************************************************************************/
+/*                          OGRVDVLayer                                 */
+/************************************************************************/
+
+class OGRVDVLayer: public OGRLayer
+{
+    VSILFILE*           m_fpL;
+    bool                m_bOwnFP;
+    bool                m_bRecodeFromLatin1;
+    vsi_l_offset        m_nStartOffset;
+    vsi_l_offset        m_nCurOffset;
+    GIntBig             m_nTotalFeatureCount;
+    GIntBig             m_nFID;
+    OGRFeatureDefn*     m_poFeatureDefn;
+    bool                m_bEOF;
+    int                 m_iLongitudeVDV452;
+    int                 m_iLatitudeVDV452;
+
+  public:
+                        OGRVDVLayer(const CPLString& osTableName,
+                                    VSILFILE* fpL,
+                                    bool bOwnFP,
+                                    bool bRecodeFromLatin1,
+                                    vsi_l_offset nStartOffset);
+                        ~OGRVDVLayer();
+
+        virtual void            ResetReading();
+        virtual OGRFeature     *GetNextFeature();
+        virtual GIntBig         GetFeatureCount(int bForce);
+        virtual OGRFeatureDefn *GetLayerDefn() { return m_poFeatureDefn; }
+        virtual int             TestCapability(const char* pszCap);
+
+        void                    SetFeatureCount(GIntBig nTotalFeatureCount)
+                            { m_nTotalFeatureCount = nTotalFeatureCount; }
+};
+
+
+class OGRVDV452Field
+{
+    public:
+        CPLString osEnglishName;
+        CPLString osGermanName;
+        CPLString osType;
+        int       nWidth;
+
+            OGRVDV452Field() : nWidth(0) {}
+};
+
+class OGRVDV452Table
+{
+    public:
+        CPLString osEnglishName;
+        CPLString osGermanName;
+        std::vector<OGRVDV452Field> aosFields;
+};
+
+class OGRVDV452Tables
+{
+    public:
+        std::vector<OGRVDV452Table*> aosTables;
+        std::map<CPLString, OGRVDV452Table*> oMapEnglish;
+        std::map<CPLString, OGRVDV452Table*> oMapGerman;
+
+            OGRVDV452Tables() {}
+            ~OGRVDV452Tables()
+            {
+                for(size_t i=0;i<aosTables.size();i++)
+                    delete aosTables[i];
+            }
+};
+
+/************************************************************************/
+/*                          OGRVDVWriterLayer                           */
+/************************************************************************/
+
+class OGRVDVWriterLayer: public OGRLayer
+{
+    OGRVDVDataSource*   m_poDS;
+    OGRFeatureDefn*     m_poFeatureDefn;
+    bool                m_bWritePossible;
+    VSILFILE*           m_fpL;
+    bool                m_bOwnFP;
+    GIntBig             m_nFeatureCount;
+    OGRVDV452Table     *m_poVDV452Table;
+    CPLString           m_osVDV452Lang;
+    bool                m_bProfileStrict;
+    int                 m_iLongitudeVDV452;
+    int                 m_iLatitudeVDV452;
+
+        bool                    WriteSchemaIfNeeded();
+
+  public:
+                        OGRVDVWriterLayer(OGRVDVDataSource *poDS,
+                                          const char* pszName,
+                                          VSILFILE* fpL,
+                                          bool bOwnFP,
+                                          OGRVDV452Table* poVDV452Table = NULL,
+                                          const CPLString& osVDV452Lang = "",
+                                          bool bProfileStrict = false
+                                          );
+                        ~OGRVDVWriterLayer();
+
+        virtual void            ResetReading();
+        virtual OGRFeature     *GetNextFeature();
+        virtual OGRFeatureDefn *GetLayerDefn() { return m_poFeatureDefn; }
+        virtual int             TestCapability(const char* pszCap);
+        virtual OGRErr          CreateField(OGRFieldDefn* poFieldDefn, int bApproxOK = TRUE);
+        virtual OGRErr          ICreateFeature(OGRFeature* poFeature);
+        virtual GIntBig         GetFeatureCount(int bForce = TRUE);
+
+        void                    StopAsCurrentLayer();
+};
+
+/************************************************************************/
+/*                        OGRVDVDataSource                              */
+/************************************************************************/
+
+class OGRVDVDataSource : public GDALDataset
+{
+    CPLString           m_osFilename;
+    VSILFILE*           m_fpL;
+    bool                m_bUpdate;
+    bool                m_bSingleFile;
+    bool                m_bNew;
+    bool                m_bLayersDetected;
+    int                 m_nLayerCount;
+    OGRLayer          **m_papoLayers;
+    OGRVDVWriterLayer  *m_poCurrentWriterLayer;
+    bool                m_bMustWriteEof;
+    bool                m_bVDV452Loaded;
+    OGRVDV452Tables     m_oVDV452Tables;
+
+    void                DetectLayers();
+
+  public:
+                        OGRVDVDataSource(const char* pszFilename,
+                                         VSILFILE* fpL,
+                                         bool bUpdate,
+                                         bool bSingleFile,
+                                         bool bNew);
+                        ~OGRVDVDataSource();
+
+    virtual int                 GetLayerCount();
+    virtual OGRLayer*           GetLayer( int );
+    virtual OGRLayer*           ICreateLayer( const char *pszLayerName,
+                                      OGRSpatialReference * /*poSpatialRef*/,
+                                      OGRwkbGeometryType /*eGType*/,
+                                      char ** papszOptions  );
+    virtual int                 TestCapability( const char * pszCap );
+
+    void                        SetCurrentWriterLayer(OGRVDVWriterLayer* poLayer);
+
+    static GDALDataset*    Open( GDALOpenInfo* poOpenInfo );
+    static GDALDataset*    Create( const char * pszName,
+                                        int /*nXSize*/, int /*nYSize*/, int /*nBands*/,
+                                        GDALDataType /*eType*/,
+                                        char ** papszOptions );
+};
+
+
+#endif /* ndef OGR_VDV_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/vdv/ogrvdvdatasource.cpp b/ogr/ogrsf_frmts/vdv/ogrvdvdatasource.cpp
new file mode 100644
index 0000000..1ae7c8b
--- /dev/null
+++ b/ogr/ogrsf_frmts/vdv/ogrvdvdatasource.cpp
@@ -0,0 +1,1863 @@
+/******************************************************************************
+ * $Id: ogrvdvdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
+ *
+ * Project:  VDV Translator
+ * Purpose:  Implements OGRVDVFDriver.
+ * Author:   Even Rouault, even.rouault at spatialys.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_vdv.h"
+#include "cpl_conv.h"
+#include "cpl_time.h"
+#include <map>
+
+CPL_CVSID("$Id: ogrvdvdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+
+#ifndef STARTS_WITH_CI
+#define STARTS_WITH(a,b)               (strncmp(a,b,strlen(b)) == 0)
+#define STARTS_WITH_CI(a,b)            EQUALN(a,b,strlen(b))
+#endif
+
+typedef enum
+{
+    LAYER_OTHER,
+    LAYER_NODE,
+    LAYER_LINK,
+    LAYER_LINKCOORDINATE
+} IDFLayerType;
+
+/************************************************************************/
+/*                          OGRVDVParseAtrFrm()                         */
+/************************************************************************/
+
+static void OGRVDVParseAtrFrm(OGRFeatureDefn* poFeatureDefn,
+                              char** papszAtr,
+                              char** papszFrm)
+{
+    for(int i=0; papszAtr[i]; i++)
+    {
+        OGRFieldType eType = OFTString;
+        int nWidth = 0;
+        OGRFieldSubType eSubType = OFSTNone;
+        if( STARTS_WITH_CI(papszFrm[i], "decimal") )
+        {
+            if( papszFrm[i][strlen("decimal")] == '(' )
+            {
+                if( strchr(papszFrm[i], ',') &&
+                    atoi(strchr(papszFrm[i], ',')+1) > 0 )
+                {
+                    eType = OFTReal;
+                }
+                else
+                {
+                    nWidth = atoi(papszFrm[i] + strlen("decimal") + 1);
+                    if( nWidth >= 10 )
+                        eType = OFTInteger64;
+                    else
+                        eType = OFTInteger;
+                }
+            }
+            else
+                eType = OFTInteger;
+        }
+        else if( STARTS_WITH_CI(papszFrm[i], "num") )
+        {
+            if( papszFrm[i][strlen("num")] == '[' )
+            {
+                if( strchr(papszFrm[i], '.') &&
+                    atoi(strchr(papszFrm[i], '.')+1) > 0 )
+                {
+                    eType = OFTReal;
+                }
+                else
+                {
+                    nWidth = atoi(papszFrm[i] + strlen("num") + 1);
+                    nWidth += 1; /* VDV-451 width is without sign */
+                    if( nWidth >= 10 )
+                        eType = OFTInteger64;
+                    else
+                        eType = OFTInteger;
+                }
+            }
+            else
+                eType = OFTInteger;
+        }
+        else if( STARTS_WITH_CI(papszFrm[i], "char") )
+        {
+            if( papszFrm[i][strlen("char")] == '[' )
+            {
+                nWidth = atoi(papszFrm[i] + strlen("char") + 1);
+            }
+        }
+        else if( STARTS_WITH_CI(papszFrm[i], "boolean") )
+        {
+            eType = OFTInteger;
+            eSubType = OFSTBoolean;
+        }
+        OGRFieldDefn oFieldDefn(papszAtr[i], eType);
+        oFieldDefn.SetSubType(eSubType);
+        oFieldDefn.SetWidth(nWidth);
+        poFeatureDefn->AddFieldDefn(&oFieldDefn);
+    }
+}
+
+/************************************************************************/
+/*                           OGRIDFDataSource()                         */
+/************************************************************************/
+
+OGRIDFDataSource::OGRIDFDataSource(VSILFILE* fpLIn) : m_fpL(fpLIn)
+{
+    m_bHasParsed = false;
+    m_poMemDS = NULL;
+}
+
+/************************************************************************/
+/*                          ~OGRIDFDataSource()                         */
+/************************************************************************/
+
+OGRIDFDataSource::~OGRIDFDataSource()
+{
+    delete m_poMemDS;
+    if( m_fpL )
+        VSIFCloseL(m_fpL);
+}
+
+/************************************************************************/
+/*                                Parse()                               */
+/************************************************************************/
+
+void OGRIDFDataSource::Parse()
+{
+    m_bHasParsed = true;
+    GDALDriver* poMemDRV = (GDALDriver*)GDALGetDriverByName("MEMORY");
+    if( poMemDRV == NULL )
+        return;
+    m_poMemDS = poMemDRV->Create("", 0, 0, 0, GDT_Unknown, NULL);
+    OGRLayer* poCurLayer = NULL;
+    std::map<GIntBig, std::pair<double,double> > oMapNode; // map from NODE_ID to (X,Y)
+    std::map<GIntBig, OGRLineString*> oMapLinkCoordinate; // map from LINK_ID to OGRLineString*
+    CPLString osTablename, osAtr, osFrm;
+    int iX = -1, iY = -1;
+    bool bAdvertizeUTF8 = false;
+    bool bRecodeFromLatin1 = false;
+    int iNodeID = -1;
+    int iLinkID = -1;
+    int iCount = -1;
+    int iFromNode = -1;
+    int iToNode = -1;
+    IDFLayerType eLayerType = LAYER_OTHER;
+
+    // We assume that layers are in the order Node, Link, LinkCoordinate
+
+    while( true )
+    {
+        const char* pszLine = CPLReadLineL(m_fpL);
+        if( pszLine == NULL )
+            break;
+
+        if( strcmp(pszLine, "chs;ISO_LATIN_1") == 0)
+        {
+            bAdvertizeUTF8 = true;
+            bRecodeFromLatin1 = true;
+        }
+        else if( STARTS_WITH(pszLine, "tbl;") )
+        {
+            poCurLayer = NULL;
+            osTablename = pszLine + 4;
+            osAtr = "";
+            osFrm = "";
+            iX = iY = iNodeID = iLinkID = iCount = iFromNode = iToNode = -1;
+            eLayerType = LAYER_OTHER;
+        }
+        else if( STARTS_WITH(pszLine, "atr;") )
+        {
+            osAtr = pszLine + 4;
+            osAtr.Trim();
+        }
+        else if( STARTS_WITH(pszLine, "frm;") )
+        {
+            osFrm = pszLine + 4;
+            osFrm.Trim();
+        }
+        else if( STARTS_WITH(pszLine, "rec;") )
+        {
+            if( poCurLayer == NULL )
+            {
+                char** papszAtr = CSLTokenizeString2(osAtr,";",
+                        CSLT_ALLOWEMPTYTOKENS|CSLT_STRIPLEADSPACES|CSLT_STRIPENDSPACES);
+                char** papszFrm = CSLTokenizeString2(osFrm,";",
+                        CSLT_ALLOWEMPTYTOKENS|CSLT_STRIPLEADSPACES|CSLT_STRIPENDSPACES);
+                char* apszOptions[2] = { NULL, NULL };
+                if( bAdvertizeUTF8 )
+                    apszOptions[0] = (char*)"ADVERTIZE_UTF8=YES";
+
+                if( EQUAL(osTablename, "Node") &&
+                    (iX = CSLFindString(papszAtr, "X")) >= 0 &&
+                    (iY = CSLFindString(papszAtr, "Y")) >= 0 )
+                {
+                    eLayerType = LAYER_NODE;
+                    iNodeID = CSLFindString(papszAtr, "NODE_ID");
+                    OGRSpatialReference* poSRS = new OGRSpatialReference(SRS_WKT_WGS84);
+                    poCurLayer = m_poMemDS->CreateLayer(osTablename, poSRS, wkbPoint, apszOptions);
+                    poSRS->Release();
+                }
+                else if( EQUAL(osTablename, "Link") &&
+                        (iLinkID = CSLFindString(papszAtr, "LINK_ID")) >= 0 &&
+                        ((iFromNode = CSLFindString(papszAtr, "FROM_NODE")) >= 0) &&
+                        ((iToNode = CSLFindString(papszAtr, "TO_NODE")) >= 0) )
+                {
+                    eLayerType = LAYER_LINK;
+                    OGRSpatialReference* poSRS = new OGRSpatialReference(SRS_WKT_WGS84);
+                    poCurLayer = m_poMemDS->CreateLayer(osTablename, poSRS, wkbLineString, apszOptions);
+                    poSRS->Release();
+                }
+                else if( EQUAL(osTablename, "LinkCoordinate") &&
+                        (iLinkID = CSLFindString(papszAtr, "LINK_ID")) >= 0 &&
+                        (iCount = CSLFindString(papszAtr, "COUNT")) >= 0 &&
+                        (iX = CSLFindString(papszAtr, "X")) >= 0 &&
+                        (iY = CSLFindString(papszAtr, "Y")) >= 0 )
+                {
+                    eLayerType = LAYER_LINKCOORDINATE;
+                    OGRSpatialReference* poSRS = new OGRSpatialReference(SRS_WKT_WGS84);
+                    poCurLayer = m_poMemDS->CreateLayer(osTablename, poSRS, wkbPoint, apszOptions);
+                    poSRS->Release();
+                }
+                else
+                {
+                    poCurLayer = m_poMemDS->CreateLayer(osTablename, NULL, wkbNone, apszOptions);
+                }
+
+                if( osAtr.size() && CSLCount(papszAtr) == CSLCount(papszFrm) )
+                {
+                    /* Note: we use AddFieldDefn() directly on the layer defn */
+                    /* This works with the current implementation of the MEM driver */
+                    /* but beware of future changes... */
+                    OGRVDVParseAtrFrm(poCurLayer->GetLayerDefn(), papszAtr, papszFrm);
+                }
+                CSLDestroy(papszAtr);
+                CSLDestroy(papszFrm);
+            }
+
+            OGRErr eErr = OGRERR_NONE;
+            char** papszTokens = CSLTokenizeStringComplex(pszLine + 4,";",TRUE,TRUE);
+            OGRFeatureDefn* poFDefn = poCurLayer->GetLayerDefn();
+            OGRFeature* poFeature = new OGRFeature(poFDefn);
+            for(int i=0; papszTokens[i] != NULL && i < poFDefn->GetFieldCount();i++)
+            {
+                if( papszTokens[i][0] )
+                {
+                    if( bRecodeFromLatin1 &&
+                        poFDefn->GetFieldDefn(i)->GetType() == OFTString )
+                    {
+                        char* pszRecoded = CPLRecode(papszTokens[i],
+                                            CPL_ENC_ISO8859_1, CPL_ENC_UTF8);
+                        poFeature->SetField(i, pszRecoded);
+                        CPLFree(pszRecoded);
+                    }
+                    else
+                    {
+                        poFeature->SetField(i, papszTokens[i]);
+                    }
+                }
+            }
+
+            if( eLayerType == LAYER_NODE )
+            {
+                double dfX = poFeature->GetFieldAsDouble(iX);
+                double dfY = poFeature->GetFieldAsDouble(iY);
+                oMapNode[ poFeature->GetFieldAsInteger64(iNodeID) ] =
+                                        std::pair<double,double>(dfX, dfY);
+                OGRGeometry* poGeom = new OGRPoint( dfX, dfY );
+                poGeom->assignSpatialReference(poFDefn->GetGeomFieldDefn(0)->GetSpatialRef());
+                poFeature->SetGeometryDirectly(poGeom);
+            }
+            else if( eLayerType == LAYER_LINK )
+            {
+                GIntBig nFromNode = poFeature->GetFieldAsInteger64(iFromNode);
+                GIntBig nToNode = poFeature->GetFieldAsInteger64(iToNode);
+                std::map<GIntBig, std::pair<double,double> >::iterator
+                                        oIterFrom = oMapNode.find(nFromNode);
+                std::map<GIntBig, std::pair<double,double> >::iterator
+                                        oIterTo = oMapNode.find(nToNode);
+                if( oIterFrom != oMapNode.end() && oIterTo != oMapNode.end() )
+                {
+                    OGRLineString* poLS = new OGRLineString();
+                    poLS->addPoint( oIterFrom->second.first, oIterFrom->second.second );
+                    poLS->addPoint( oIterTo->second.first, oIterTo->second.second );
+                    poLS->assignSpatialReference(poFDefn->GetGeomFieldDefn(0)->GetSpatialRef());
+                    poFeature->SetGeometryDirectly(poLS);
+                }
+            }
+            else if( eLayerType == LAYER_LINKCOORDINATE )
+            {
+                double dfX = poFeature->GetFieldAsDouble(iX);
+                double dfY = poFeature->GetFieldAsDouble(iY);
+                OGRGeometry* poGeom = new OGRPoint( dfX, dfY );
+                poGeom->assignSpatialReference(poFDefn->GetGeomFieldDefn(0)->GetSpatialRef());
+                poFeature->SetGeometryDirectly(poGeom);
+
+                GIntBig nCurLinkID = poFeature->GetFieldAsInteger64(iLinkID);
+                std::map<GIntBig, OGRLineString*>::iterator
+                    oMapLinkCoordinateIter = oMapLinkCoordinate.find(nCurLinkID);
+                if( oMapLinkCoordinateIter == oMapLinkCoordinate.end() )
+                {
+                    OGRLineString* poLS = new OGRLineString();
+                    poLS->addPoint(dfX, dfY);
+                    oMapLinkCoordinate[nCurLinkID] = poLS;
+                }
+                else
+                {
+                    oMapLinkCoordinateIter->second->addPoint(dfX, dfY);
+                }
+            }
+            eErr = poCurLayer->CreateFeature(poFeature);
+            delete poFeature;
+
+            CSLDestroy(papszTokens);
+
+            if( eErr == OGRERR_FAILURE )
+                break;
+        }
+    }
+
+    // Patch Link geometries with the intermediate points of LinkCoordinate
+    OGRLayer* poLinkLyr = m_poMemDS->GetLayerByName("Link");
+    if( poLinkLyr )
+    {
+        OGRFeature* poFeat;
+        iLinkID = poLinkLyr->GetLayerDefn()->GetFieldIndex("LINK_ID");
+        if( iLinkID >= 0 )
+        {
+            poLinkLyr->ResetReading();
+            OGRSpatialReference* poSRS =
+                poLinkLyr->GetLayerDefn()->GetGeomFieldDefn(0)->GetSpatialRef();
+            while( (poFeat = poLinkLyr->GetNextFeature()) != NULL )
+            {
+                GIntBig nLinkID = poFeat->GetFieldAsInteger64(iLinkID);
+                std::map<GIntBig, OGRLineString*>::iterator
+                    oMapLinkCoordinateIter = oMapLinkCoordinate.find(nLinkID);
+                OGRLineString* poLS = (OGRLineString*)poFeat->GetGeometryRef();
+                if( poLS != NULL && oMapLinkCoordinateIter != oMapLinkCoordinate.end() )
+                {
+                    OGRLineString* poLSIntermediate = oMapLinkCoordinateIter->second;
+                    OGRLineString* poLSNew = new OGRLineString();
+                    poLSNew->addPoint(poLS->getX(0), poLS->getY(0));
+                    for(int i=0;i<poLSIntermediate->getNumPoints();i++)
+                    {
+                        poLSNew->addPoint(poLSIntermediate->getX(i),
+                                          poLSIntermediate->getY(i));
+                    }
+                    poLSNew->addPoint(poLS->getX(1), poLS->getY(1));
+                    poLSNew->assignSpatialReference(poSRS);
+                    poFeat->SetGeometryDirectly(poLSNew);
+                    CPL_IGNORE_RET_VAL(poLinkLyr->SetFeature(poFeat));
+                }
+                delete poFeat;
+            }
+            poLinkLyr->ResetReading();
+        }
+    }
+
+    std::map<GIntBig, OGRLineString*>::iterator oMapLinkCoordinateIter =
+                                                    oMapLinkCoordinate.begin();
+    for(; oMapLinkCoordinateIter != oMapLinkCoordinate.end(); ++oMapLinkCoordinateIter)
+        delete oMapLinkCoordinateIter->second;
+}
+
+/************************************************************************/
+/*                           GetLayerCount()                            */
+/************************************************************************/
+
+int OGRIDFDataSource::GetLayerCount()
+{
+    if( !m_bHasParsed )
+        Parse();
+    if( m_poMemDS == NULL )
+        return 0;
+    return m_poMemDS->GetLayerCount();
+}
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer* OGRIDFDataSource::GetLayer( int iLayer )
+{
+    if( iLayer < 0 || iLayer >= GetLayerCount() )
+        return NULL;
+    if( m_poMemDS == NULL )
+        return NULL;
+    return m_poMemDS->GetLayer(iLayer);
+}
+
+/************************************************************************/
+/*                           OGRVDVDataSource()                         */
+/************************************************************************/
+
+OGRVDVDataSource::OGRVDVDataSource(const char* pszFilename,
+                                   VSILFILE* fpL,
+                                   bool bUpdate,
+                                   bool bSingleFile,
+                                   bool bNew) :
+    m_osFilename(pszFilename),
+    m_fpL(fpL),
+    m_bUpdate(bUpdate),
+    m_bSingleFile(bSingleFile),
+    m_bNew(bNew),
+    m_bLayersDetected(bNew || fpL == NULL),
+    m_nLayerCount(0),
+    m_papoLayers(NULL),
+    m_poCurrentWriterLayer(NULL),
+    m_bMustWriteEof(false),
+    m_bVDV452Loaded(false)
+{
+}
+
+/************************************************************************/
+/*                          ~OGRVDVDataSource()                         */
+/************************************************************************/
+
+OGRVDVDataSource::~OGRVDVDataSource()
+{
+    if( m_poCurrentWriterLayer )
+    {
+        m_poCurrentWriterLayer->StopAsCurrentLayer();
+        m_poCurrentWriterLayer = NULL;
+    }
+
+    for(int i=0;i<m_nLayerCount;i++)
+        delete m_papoLayers[i];
+    CPLFree(m_papoLayers);
+
+    // Close after destroying layers since they might use it (single file write)
+    if( m_fpL )
+    {
+        if( m_bMustWriteEof )
+        {
+            VSIFPrintfL( m_fpL, "eof; %d\n", m_nLayerCount );
+        }
+        VSIFCloseL(m_fpL);
+    }
+}
+
+/************************************************************************/
+/*                           GetLayerCount()                            */
+/************************************************************************/
+
+int OGRVDVDataSource::GetLayerCount()
+{
+    if( !m_bLayersDetected )
+        DetectLayers();
+    return m_nLayerCount;
+}
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer* OGRVDVDataSource::GetLayer( int iLayer )
+{
+    if( iLayer < 0 || iLayer >= GetLayerCount() )
+        return NULL;
+    return m_papoLayers[iLayer];
+}
+
+/************************************************************************/
+/*                         DetectLayers()                               */
+/************************************************************************/
+
+void OGRVDVDataSource::DetectLayers()
+{
+    m_bLayersDetected = true;
+
+    char szBuffer[1+1024+1];
+    char chNextExpected = 't';
+    char chNextExpected2 = 'r';
+    char chNextExpected3 = 'e';
+    bool bInTableName = false;
+    CPLString osTableName;
+    GIntBig nFeatureCount = 0;
+    vsi_l_offset nStartOffset = 0;
+    OGRVDVLayer* poLayer = NULL;
+    bool bFirstBuffer = true;
+    bool bRecodeFromLatin1 = false;
+
+    VSIFSeekL(m_fpL, 0, SEEK_SET);
+
+    while( true )
+    {
+        size_t nRead = VSIFReadL(szBuffer, 1, 1024, m_fpL);
+        szBuffer[nRead] = '\0';
+        if( bFirstBuffer )
+        {
+            const char* pszChs = strstr(szBuffer, "\nchs;");
+            if( pszChs )
+            {
+                pszChs += 5;
+                CPLString osChs;
+                for(; *pszChs != '\0' && *pszChs != '\r' && *pszChs != '\n';
+                    ++pszChs)
+                {
+                    if( *pszChs != ' ' && *pszChs != '"' )
+                        osChs += *pszChs;
+                }
+                bRecodeFromLatin1 = EQUAL(osChs, "ISO8859-1") ||
+                                    EQUAL(osChs, "ISO_LATIN_1");
+            }
+            bFirstBuffer = false;
+        }
+        for(size_t i=0;i<nRead;i++)
+        {
+            if( bInTableName )
+            {
+                if( szBuffer[i] == '\r' || szBuffer[i] == '\n' )
+                {
+                    bInTableName = false;
+                    poLayer = new OGRVDVLayer(osTableName,
+                                              m_fpL,
+                                              false,
+                                              bRecodeFromLatin1,
+                                              nStartOffset);
+                    m_papoLayers = static_cast<OGRLayer**>(CPLRealloc(
+                        m_papoLayers, sizeof(OGRLayer*) * (m_nLayerCount + 1) ));
+                    m_papoLayers[m_nLayerCount] = poLayer;
+                    m_nLayerCount ++;
+                }
+                else if( szBuffer[i] != ' ' )
+                {
+                    osTableName += szBuffer[i];
+                    continue;
+                }
+            }
+
+            // Reset state on end of line characters
+            if( szBuffer[i] == '\n' || szBuffer[i] == '\r' )
+            {
+                chNextExpected = szBuffer[i];
+                chNextExpected2 = szBuffer[i];
+                chNextExpected3 = szBuffer[i];
+            }
+
+            // Detect tbl;
+            if( szBuffer[i] == chNextExpected )
+            {
+                if( chNextExpected == '\n' || chNextExpected == '\r' )
+                    chNextExpected = 't';
+                else if( chNextExpected == 't' )
+                    chNextExpected = 'b';
+                else if( chNextExpected == 'b' )
+                    chNextExpected = 'l';
+                else if( chNextExpected == 'l' )
+                    chNextExpected = ';';
+                else if( chNextExpected == ';' )
+                {
+                    if( poLayer != NULL )
+                        poLayer->SetFeatureCount(nFeatureCount);
+                    poLayer = NULL;
+                    nFeatureCount = 0;
+                    nStartOffset = VSIFTellL(m_fpL) - nRead + i - 4 + 1;
+                    bInTableName = true;
+                    osTableName.resize(0);
+                    chNextExpected = 0;
+                }
+            }
+            else
+                chNextExpected = 0;
+
+            // Detect rec;
+            if( szBuffer[i] == chNextExpected2 )
+            {
+                if( chNextExpected2 == '\n' || chNextExpected2 == '\r' )
+                    chNextExpected2 = 'r';
+                else if( chNextExpected2 == 'r' )
+                    chNextExpected2 = 'e';
+                else if( chNextExpected2 == 'e' )
+                    chNextExpected2 = 'c';
+                else if( chNextExpected2 == 'c' )
+                    chNextExpected2 = ';';
+                else if( chNextExpected2 == ';' )
+                {
+                    nFeatureCount ++;
+                    chNextExpected2 = 0;
+                }
+            }
+            else
+                chNextExpected2 = 0;
+
+            // Detect end;
+            if( szBuffer[i] == chNextExpected3 )
+            {
+                if( chNextExpected3 == '\n' || chNextExpected3 == '\r' )
+                    chNextExpected3 = 'e';
+                else if( chNextExpected3 == 'e' )
+                    chNextExpected3 = 'n';
+                else if( chNextExpected3 == 'n' )
+                    chNextExpected3 = 'd';
+                else if( chNextExpected3 == 'd' )
+                    chNextExpected3 = ';';
+                else if( chNextExpected3 == ';' )
+                {
+                    if( poLayer != NULL )
+                        poLayer->SetFeatureCount(nFeatureCount);
+                    poLayer = NULL;
+                    chNextExpected3 = 0;
+                }
+            }
+            else
+                chNextExpected3 = 0;
+        }
+        if( nRead < 1024 )
+            break;
+    }
+    if( poLayer != NULL )
+        poLayer->SetFeatureCount(nFeatureCount);
+}
+
+/************************************************************************/
+/*                           OGRVDVLayer()                              */
+/************************************************************************/
+
+OGRVDVLayer::OGRVDVLayer(const CPLString& osTableName,
+                         VSILFILE* fpL,
+                         bool bOwnFP,
+                         bool bRecodeFromLatin1,
+                         vsi_l_offset nStartOffset) :
+    m_fpL(fpL),
+    m_bOwnFP(bOwnFP),
+    m_bRecodeFromLatin1(bRecodeFromLatin1),
+    m_nStartOffset(nStartOffset),
+    m_nCurOffset(0),
+    m_nTotalFeatureCount(0),
+    m_nFID(0),
+    m_bEOF(false),
+    m_iLongitudeVDV452(-1),
+    m_iLatitudeVDV452(-1)
+{
+    m_poFeatureDefn = new OGRFeatureDefn(osTableName);
+    m_poFeatureDefn->SetGeomType(wkbNone);
+    m_poFeatureDefn->Reference();
+    SetDescription(osTableName);
+    vsi_l_offset nCurOffset = VSIFTellL(fpL);
+    VSIFSeekL(m_fpL, m_nStartOffset, SEEK_SET);
+    CPLString osAtr, osFrm;
+
+    /* skip until first tbl; */
+    bool bFoundTbl = false;
+    for(int i=0;i<20;i++)
+    {
+        const char* pszLine = CPLReadLineL(m_fpL);
+        if( pszLine == NULL )
+            break;
+        if( STARTS_WITH(pszLine, "chs;") )
+        {
+            CPLString osChs(pszLine+4);
+            osChs.Trim();
+            if( osChs.size() >= 2 && osChs[0] == '"' && osChs[osChs.size()-1] == '"' )
+                osChs = osChs.substr(1, osChs.size()-2);
+            m_bRecodeFromLatin1 = EQUAL(osChs, "ISO8859-1") ||
+                                  EQUAL(osChs, "ISO_LATIN_1");
+        }
+        else if( STARTS_WITH(pszLine, "tbl;") )
+        {
+            if( bFoundTbl )
+                break; /* shouldn't happen in correctly formed files */
+            bFoundTbl = true;
+            m_nStartOffset = VSIFTellL(fpL);
+        }
+        else if( STARTS_WITH(pszLine, "atr;") )
+        {
+            osAtr = pszLine + 4;
+            osAtr.Trim();
+        }
+        else if( STARTS_WITH(pszLine, "frm;") )
+        {
+            osFrm = pszLine + 4;
+            osFrm.Trim();
+        }
+        else if( STARTS_WITH(pszLine, "rec;") ||
+                 STARTS_WITH(pszLine, "end;") )
+            break;
+    }
+    if( !bFoundTbl )
+        CPLDebug("VDV", "Didn't find tbl; line");
+
+    VSIFSeekL(m_fpL, nCurOffset, SEEK_SET);
+    if( osAtr.size() && osFrm.size() )
+    {
+        char** papszAtr = CSLTokenizeString2(osAtr,";",
+                    CSLT_ALLOWEMPTYTOKENS|CSLT_STRIPLEADSPACES|CSLT_STRIPENDSPACES);
+        char** papszFrm = CSLTokenizeString2(osFrm,";",
+                    CSLT_ALLOWEMPTYTOKENS|CSLT_STRIPLEADSPACES|CSLT_STRIPENDSPACES);
+        if( CSLCount(papszAtr) == CSLCount(papszFrm) )
+        {
+            OGRVDVParseAtrFrm(m_poFeatureDefn, papszAtr, papszFrm);
+        }
+        CSLDestroy(papszAtr);
+        CSLDestroy(papszFrm);
+    }
+
+    // Identify longitude, latitude columns of VDV-452 STOP table
+    if( EQUAL(osTableName, "STOP") ) /* English */
+    {
+        m_iLongitudeVDV452 = m_poFeatureDefn->GetFieldIndex("POINT_LONGITUDE");
+        m_iLatitudeVDV452 = m_poFeatureDefn->GetFieldIndex("POINT_LATITUDE");
+    }
+    else if( EQUAL(osTableName, "REC_ORT") ) /* German */
+    {
+        m_iLongitudeVDV452 = m_poFeatureDefn->GetFieldIndex("ORT_POS_LAENGE");
+        m_iLatitudeVDV452 = m_poFeatureDefn->GetFieldIndex("ORT_POS_BREITE");
+    }
+    if( m_iLongitudeVDV452 >= 0 && m_iLatitudeVDV452 >= 0 )
+    {
+        m_poFeatureDefn->SetGeomType(wkbPoint);
+        OGRSpatialReference* poSRS = new OGRSpatialReference(SRS_WKT_WGS84);
+        m_poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
+        poSRS->Release();
+    }
+    else
+        m_iLongitudeVDV452 = m_iLatitudeVDV452 = -1;
+}
+
+/************************************************************************/
+/*                          ~OGRVDVLayer()                              */
+/************************************************************************/
+
+OGRVDVLayer::~OGRVDVLayer()
+{
+    m_poFeatureDefn->Release();
+    if( m_bOwnFP )
+        VSIFCloseL(m_fpL);
+}
+
+/************************************************************************/
+/*                          ResetReading()                              */
+/************************************************************************/
+
+void OGRVDVLayer::ResetReading()
+{
+    VSIFSeekL(m_fpL, m_nStartOffset, SEEK_SET);
+    m_nCurOffset = m_nStartOffset;
+    m_nFID = 1;
+    m_bEOF = false;
+}
+
+/************************************************************************/
+/*                         OGRVDVUnescapeString()                       */
+/************************************************************************/
+
+static CPLString OGRVDVUnescapeString(const char* pszValue)
+{
+    CPLString osRet;
+    for(; *pszValue != '\0'; ++pszValue )
+    {
+        if( *pszValue == '"' && pszValue[1] == '"' )
+        {
+            osRet += '"';
+            ++pszValue;
+        }
+        else
+        {
+            osRet += *pszValue;
+        }
+    }
+    return osRet;
+}
+
+/************************************************************************/
+/*                          GetNextFeature()                            */
+/************************************************************************/
+
+OGRFeature* OGRVDVLayer::GetNextFeature()
+{
+    if( m_nFID == 0 )
+        ResetReading();
+    VSIFSeekL(m_fpL, m_nCurOffset, SEEK_SET);
+    OGRFeature* poFeature = NULL;
+    while( !m_bEOF )
+    {
+        const char* pszLine = CPLReadLineL(m_fpL);
+        if( pszLine == NULL )
+            break;
+        if( strncmp(pszLine, "end;", 4) == 0 ||
+            strncmp(pszLine, "tbl;", 4) == 0 )
+        {
+            m_bEOF = true;
+            break;
+        }
+        if( strncmp(pszLine, "rec;", 4) != 0 )
+            continue;
+
+        char** papszTokens = CSLTokenizeString2(pszLine+4,";",
+                CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES| CSLT_STRIPENDSPACES);
+        poFeature = new OGRFeature(m_poFeatureDefn);
+        poFeature->SetFID( m_nFID ++ );
+        for(int i=0; papszTokens[i] != NULL &&
+                     i < m_poFeatureDefn->GetFieldCount();i++)
+        {
+            if( papszTokens[i][0] && !EQUAL(papszTokens[i], "NULL") )
+            {
+                size_t nLen = strlen(papszTokens[i]);
+                CPLString osToken;
+                if( nLen >= 2 &&
+                    papszTokens[i][0] == '"' && papszTokens[i][nLen-1] == '"' )
+                {
+                    papszTokens[i][nLen-1] = 0;
+                    osToken = OGRVDVUnescapeString(papszTokens[i]+1);
+                }
+                else
+                    osToken = papszTokens[i];
+                // Strip trailing spaces
+                while( osToken.size() && osToken[osToken.size()-1] == ' ' )
+                    osToken.resize(osToken.size()-1);
+                OGRFieldType eFieldType = m_poFeatureDefn->GetFieldDefn(i)->GetType();
+                if( m_bRecodeFromLatin1 && eFieldType == OFTString )
+                {
+                    char* pszRecoded = CPLRecode(osToken,
+                                        CPL_ENC_ISO8859_1, CPL_ENC_UTF8);
+                    poFeature->SetField(i, pszRecoded);
+                    CPLFree(pszRecoded);
+                }
+                else if( eFieldType == OFTString || !EQUAL(osToken, "NULL") )
+                {
+                    poFeature->SetField(i, osToken);
+                }
+            }
+        }
+        CSLDestroy(papszTokens);
+
+        if( m_iLongitudeVDV452 >= 0 && m_iLatitudeVDV452 >= 0 )
+        {
+            int nLongDegMinMS = poFeature->GetFieldAsInteger(m_iLongitudeVDV452);
+            int nLongSign = 1;
+            if( nLongDegMinMS < 0 )
+            {
+                nLongSign = -1;
+                nLongDegMinMS = -nLongDegMinMS;
+            }
+            const int nLongDeg = nLongDegMinMS / (100 * 100000);
+            const int nLongMin = (nLongDegMinMS / 100000) % 100;
+            const int nLongMS = nLongDegMinMS % 100000;
+            const double dfLong =
+                (nLongDeg + nLongMin / 60.0 + nLongMS / (3600.0 * 1000.0)) * nLongSign;
+
+            int nLatDegMinMS = poFeature->GetFieldAsInteger(m_iLatitudeVDV452);
+            int nLatSign = 1;
+            if( nLatDegMinMS < 0 )
+            {
+                nLatSign = -1;
+                nLatDegMinMS = -nLatDegMinMS;
+            }
+            const int nLatDeg = nLatDegMinMS / (100 * 100000);
+            const int nLatMin = (nLatDegMinMS / 100000) % 100;
+            const int nLatMS = nLatDegMinMS % 100000;
+            const double dfLat =
+                (nLatDeg + nLatMin / 60.0 + nLatMS / (3600.0 * 1000.0)) * nLatSign;
+
+            if( dfLong != 0.0 || dfLat != 0.0 )
+            {
+                OGRPoint* poPoint = new OGRPoint(dfLong, dfLat);
+                poPoint->assignSpatialReference(
+                    m_poFeatureDefn->GetGeomFieldDefn(0)->GetSpatialRef());
+                poFeature->SetGeometryDirectly( poPoint );
+            }
+        }
+
+        if( (m_poFilterGeom == NULL
+            || FilterGeometry( poFeature->GetGeomFieldRef(m_iGeomFieldFilter) ) )
+            && (m_poAttrQuery == NULL
+                || m_poAttrQuery->Evaluate( poFeature )) )
+        {
+            break;
+        }
+        delete poFeature;
+        poFeature = NULL;
+    }
+    m_nCurOffset = VSIFTellL(m_fpL);
+    return poFeature;
+}
+
+/************************************************************************/
+/*                          TestCapability()                            */
+/************************************************************************/
+
+int OGRVDVLayer::TestCapability(const char* pszCap)
+{
+    if( EQUAL(pszCap, OLCFastFeatureCount) &&  m_nTotalFeatureCount > 0 &&
+        m_poFilterGeom == NULL && m_poAttrQuery == NULL )
+    {
+        return TRUE;
+    }
+    if( EQUAL(pszCap, OLCStringsAsUTF8) )
+    {
+        return m_bRecodeFromLatin1;
+    }
+    return FALSE;
+}
+
+/************************************************************************/
+/*                          GetFeatureCount()                           */
+/************************************************************************/
+
+GIntBig OGRVDVLayer::GetFeatureCount(int bForce)
+{
+    if( m_nTotalFeatureCount == 0 ||
+        m_poFilterGeom != NULL || m_poAttrQuery != NULL )
+    {
+        return OGRLayer::GetFeatureCount(bForce);
+    }
+    return m_nTotalFeatureCount;
+}
+
+/************************************************************************/
+/*                              Identify()                              */
+/************************************************************************/
+
+static int OGRVDVDriverIdentify( GDALOpenInfo* poOpenInfo )
+
+{
+    if( poOpenInfo->bIsDirectory )
+        return -1; /* perhaps... */
+    return (poOpenInfo->nHeaderBytes > 0 &&
+            (strstr((const char*)poOpenInfo->pabyHeader, "\ntbl;") != NULL ||
+             strncmp((const char*)poOpenInfo->pabyHeader, "tbl;", 4) == 0) &&
+            strstr((const char*)poOpenInfo->pabyHeader, "\natr;") != NULL &&
+            strstr((const char*)poOpenInfo->pabyHeader, "\nfrm;") != NULL);
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *OGRVDVDataSource::Open( GDALOpenInfo* poOpenInfo )
+
+{
+    if( !OGRVDVDriverIdentify(poOpenInfo) )
+    {
+        return NULL;
+    }
+    if( poOpenInfo->bIsDirectory )
+    {
+        char** papszFiles = VSIReadDir(poOpenInfo->pszFilename);
+
+        // Identify the extension with the most occurrences
+        std::map<CPLString, int> oMapOtherExtensions;
+        CPLString osMajorityExtension, osMajorityFile;
+        int nFiles = 0;
+        for(char** papszIter = papszFiles; papszIter && *papszIter; ++papszIter)
+        {
+            if( EQUAL(*papszIter, ".") || EQUAL(*papszIter, "..") )
+                continue;
+            nFiles ++;
+            CPLString osExtension(CPLGetExtension(*papszIter));
+            int nCount = ++oMapOtherExtensions[osExtension];
+            if( osMajorityExtension == "" ||
+                nCount > oMapOtherExtensions[osMajorityExtension] )
+            {
+                osMajorityExtension = osExtension;
+                osMajorityFile = *papszIter;
+            }
+        }
+
+        // Check it is at least 50% of the files in the directory
+        if( osMajorityExtension == "" ||
+            2 * oMapOtherExtensions[osMajorityExtension] < nFiles )
+        {
+            CSLDestroy(papszFiles);
+            return NULL;
+        }
+
+        // And check that one of those files is a VDV one if it isn't .x10
+        if( osMajorityExtension != "x10" )
+        {
+            GDALOpenInfo oOpenInfo( CPLFormFilename(poOpenInfo->pszFilename,
+                                                    osMajorityFile,
+                                                    NULL), GA_ReadOnly );
+            if( OGRVDVDriverIdentify(&oOpenInfo) != TRUE )
+            {
+                CSLDestroy(papszFiles);
+                return NULL;
+            }
+        }
+
+        OGRVDVDataSource* poDS = new OGRVDVDataSource(poOpenInfo->pszFilename,
+                                                      NULL, /* fp */
+                                                      poOpenInfo->eAccess == GA_Update,
+                                                      false, /* single file */
+                                                      false /* new */);
+
+        // Instantiate the layers.
+        for(char** papszIter = papszFiles; papszIter && *papszIter; ++papszIter)
+        {
+            if( !EQUAL(CPLGetExtension(*papszIter), osMajorityExtension) )
+                continue;
+            VSILFILE* fp = VSIFOpenL( CPLFormFilename(poOpenInfo->pszFilename,
+                                                      *papszIter,
+                                                      NULL), "rb");
+            if( fp == NULL )
+                continue;
+            poDS->m_papoLayers = static_cast<OGRLayer**>(CPLRealloc(
+                poDS->m_papoLayers, sizeof(OGRLayer*) * (poDS->m_nLayerCount + 1) ));
+            poDS->m_papoLayers[poDS->m_nLayerCount] = new OGRVDVLayer(
+                                                            CPLGetBasename(*papszIter),
+                                                            fp,
+                                                            true,
+                                                            false,
+                                                            0 );
+            poDS->m_nLayerCount ++;
+        }
+        CSLDestroy(papszFiles);
+
+        if( poDS->m_nLayerCount == 0 )
+        {
+            delete poDS;
+            poDS = NULL;
+        }
+        return poDS;
+    }
+
+    VSILFILE* fpL = poOpenInfo->fpL;
+    poOpenInfo->fpL = NULL;
+    const char* pszHeader = (const char*)poOpenInfo->pabyHeader;
+    if( strstr(pszHeader, "tbl;Node\r\natr;NODE_ID;") != NULL ||
+        strstr(pszHeader, "tbl;Node\natr;NODE_ID;") != NULL ||
+        strstr(pszHeader, "tbl;Link\r\natr;LINK_ID;") != NULL ||
+        strstr(pszHeader, "tbl;Link\natr;LINK_ID;") != NULL ||
+        strstr(pszHeader, "tbl;LinkCoordinate\r\natr;LINK_ID;") != NULL ||
+        strstr(pszHeader, "tbl;LinkCoordinate\natr;LINK_ID;") != NULL )
+    {
+        return new OGRIDFDataSource(fpL);
+    }
+    else
+    {
+        return new OGRVDVDataSource(poOpenInfo->pszFilename,
+                                    fpL,
+                                    poOpenInfo->eAccess == GA_Update,
+                                    true, /* single file */
+                                    false /* new */);
+    }
+}
+
+/************************************************************************/
+/*                         OGRVDVWriterLayer                            */
+/************************************************************************/
+
+OGRVDVWriterLayer::OGRVDVWriterLayer( OGRVDVDataSource *poDS,
+                                      const char* pszName,
+                                      VSILFILE* fpL,
+                                      bool bOwnFP,
+                                      OGRVDV452Table* poVDV452Table,
+                                      const CPLString& osVDV452Lang,
+                                      bool bProfileStrict):
+    m_poDS(poDS),
+    m_bWritePossible(true),
+    m_fpL(fpL),
+    m_bOwnFP(bOwnFP),
+    m_nFeatureCount(-1),
+    m_poVDV452Table(poVDV452Table),
+    m_osVDV452Lang(osVDV452Lang),
+    m_bProfileStrict(bProfileStrict),
+    m_iLongitudeVDV452(-1),
+    m_iLatitudeVDV452(-1)
+{
+    m_poFeatureDefn = new OGRFeatureDefn(pszName);
+    m_poFeatureDefn->SetGeomType(wkbNone);
+    m_poFeatureDefn->Reference();
+    SetDescription(pszName);
+}
+
+/************************************************************************/
+/*                        ~OGRVDVWriterLayer                            */
+/************************************************************************/
+
+OGRVDVWriterLayer::~OGRVDVWriterLayer()
+{
+    StopAsCurrentLayer();
+
+    m_poFeatureDefn->Release();
+    if( m_bOwnFP )
+    {
+        VSIFPrintfL( m_fpL, "eof; %d\n", 1 );
+        VSIFCloseL(m_fpL);
+    }
+}
+
+/************************************************************************/
+/*                          ResetReading()                              */
+/************************************************************************/
+
+void OGRVDVWriterLayer::ResetReading()
+{
+}
+
+/************************************************************************/
+/*                          GetNextFeature()                            */
+/************************************************************************/
+
+OGRFeature* OGRVDVWriterLayer::GetNextFeature()
+{
+    CPLError(CE_Failure, CPLE_NotSupported,
+             "GetNextFeature() not supported on write-only layer");
+    return NULL;
+}
+
+/************************************************************************/
+/*                         OGRVDVEscapeString()                         */
+/************************************************************************/
+
+static CPLString OGRVDVEscapeString(const char* pszValue)
+{
+    CPLString osRet;
+    for( ; *pszValue != '\0'; ++pszValue )
+    {
+        if( *pszValue == '"' )
+            osRet += "\"\"";
+        else
+            osRet += *pszValue;
+    }
+    return osRet;
+}
+
+/************************************************************************/
+/*                          WriteSchemaIfNeeded()                       */
+/************************************************************************/
+
+bool OGRVDVWriterLayer::WriteSchemaIfNeeded()
+{
+    if( m_nFeatureCount < 0 )
+    {
+        m_nFeatureCount = 0;
+
+        bool bOK = VSIFPrintfL(m_fpL, "tbl; %s\n", m_poFeatureDefn->GetName()) > 0;
+        bOK &= VSIFPrintfL(m_fpL, "atr;") > 0;
+        for( int i=0; i < m_poFeatureDefn->GetFieldCount(); i++ )
+        {
+            if( i > 0)
+                bOK &= VSIFPrintfL(m_fpL, ";") > 0;
+            bOK &= VSIFPrintfL(m_fpL, " %s",
+                               m_poFeatureDefn->GetFieldDefn(i)->GetNameRef()) > 0;
+        }
+        bOK &= VSIFPrintfL(m_fpL, "\n") > 0;
+        bOK &= VSIFPrintfL(m_fpL, "frm;") > 0;
+        for( int i=0; i < m_poFeatureDefn->GetFieldCount(); i++ )
+        {
+            if( i > 0)
+                bOK &= VSIFPrintfL(m_fpL, ";") > 0;
+            bOK &= VSIFPrintfL(m_fpL, " ") > 0;
+            int nWidth = m_poFeatureDefn->GetFieldDefn(i)->GetWidth();
+            const OGRFieldType eType = m_poFeatureDefn->GetFieldDefn(i)->GetType();
+            switch( eType )
+            {
+                case OFTInteger:
+                case OFTInteger64:
+                    if( m_poFeatureDefn->GetFieldDefn(i)->GetSubType() == OFSTBoolean )
+                    {
+                        bOK &= VSIFPrintfL(m_fpL, "boolean") > 0;
+                    }
+                    else
+                    {
+                        if( nWidth == 0 )
+                        {
+                            if( eType == OFTInteger )
+                                nWidth = 11;
+                            else
+                                nWidth = 20;
+                        }
+                        nWidth --; /* VDV 451 is without sign */
+                        bOK &= VSIFPrintfL(m_fpL, "num[%d.0]", nWidth) > 0;
+                    }
+                    break;
+
+                default:
+                    if( nWidth == 0 )
+                    {
+                        nWidth = 80;
+                    }
+                    bOK &= VSIFPrintfL(m_fpL, "char[%d]", nWidth) > 0;
+                    break;
+            }
+
+        }
+        bOK &= VSIFPrintfL(m_fpL, "\n") > 0;
+
+        if( !bOK )
+            return false;
+    }
+
+    return true;
+}
+
+/************************************************************************/
+/*                         ICreateFeature()                             */
+/************************************************************************/
+
+OGRErr OGRVDVWriterLayer::ICreateFeature(OGRFeature* poFeature)
+{
+    if( !m_bWritePossible )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Layer %s is no longer the active layer. "
+                 "Writing in it is no longer possible",
+                 m_poFeatureDefn->GetName());
+        return OGRERR_FAILURE;
+    }
+    m_poDS->SetCurrentWriterLayer(this);
+
+    WriteSchemaIfNeeded();
+
+    bool bOK = VSIFPrintfL(m_fpL, "rec; ") > 0;
+    for( int i=0; i < m_poFeatureDefn->GetFieldCount(); i++ )
+    {
+        if( i > 0)
+            bOK &= VSIFPrintfL(m_fpL, "; ") > 0;
+        if( poFeature->IsFieldSet(i) )
+        {
+            const OGRFieldType eType = m_poFeatureDefn->GetFieldDefn(i)->GetType();
+            if( eType == OFTInteger || eType == OFTInteger64 )
+            {
+                bOK &= VSIFPrintfL(m_fpL, CPL_FRMT_GIB,
+                                   poFeature->GetFieldAsInteger64(i)) > 0;
+            }
+            else
+            {
+                char* pszRecoded = CPLRecode(poFeature->GetFieldAsString(i),
+                                              CPL_ENC_UTF8, CPL_ENC_ISO8859_1);
+                bOK &= VSIFPrintfL(m_fpL, "\"%s\"",
+                                   OGRVDVEscapeString(pszRecoded).c_str()) > 0;
+                CPLFree(pszRecoded);
+            }
+        }
+        else if( i == m_iLongitudeVDV452 &&
+                 poFeature->GetGeometryRef() != NULL &&
+                 poFeature->GetGeometryRef()->getGeometryType() == wkbPoint )
+        {
+            OGRPoint* poPoint = static_cast<OGRPoint*>(poFeature->GetGeometryRef());
+            const double dfDeg = poPoint->getX();
+            const double dfAbsDeg = fabs(dfDeg);
+            const int nDeg = static_cast<int>(dfAbsDeg);
+            const int nMin = static_cast<int>((dfAbsDeg - nDeg) * 60);
+            const double dfSec = (dfAbsDeg - nDeg)*3600 - nMin * 60;
+            const int nSec = static_cast<int>(dfSec);
+            int nMS = static_cast<int>((dfSec - nSec) * 1000 + 0.5);
+            if( nMS == 1000 ) nMS = 999;
+            if( dfDeg < 0 )
+                bOK &= VSIFPrintfL(m_fpL, "-") > 0;
+            bOK &= VSIFPrintfL(m_fpL, "%03d%02d%02d%03d", nDeg, nMin, nSec, nMS) > 0;
+        }
+        else if( i == m_iLatitudeVDV452 &&
+                 poFeature->GetGeometryRef() != NULL &&
+                 poFeature->GetGeometryRef()->getGeometryType() == wkbPoint )
+        {
+            OGRPoint* poPoint = static_cast<OGRPoint*>(poFeature->GetGeometryRef());
+            const double dfDeg = poPoint->getY();
+            const double dfAbsDeg = fabs(dfDeg);
+            const int nDeg = static_cast<int>(dfAbsDeg);
+            const int nMin = static_cast<int>((dfAbsDeg - nDeg) * 60);
+            const double dfSec = (dfAbsDeg - nDeg)*3600 - nMin * 60;
+            const int nSec = static_cast<int>(dfSec);
+            int nMS = static_cast<int>((dfSec - nSec) * 1000 + 0.5);
+            if( nMS == 1000 ) nMS = 999;
+            if( dfDeg < 0 )
+                bOK &= VSIFPrintfL(m_fpL, "-") > 0;
+            bOK &= VSIFPrintfL(m_fpL, "%02d%02d%02d%03d", nDeg, nMin, nSec, nMS) > 0;
+        }
+        else
+        {
+            bOK &= VSIFPrintfL(m_fpL, "NULL") > 0;
+        }
+    }
+    bOK &= VSIFPrintfL(m_fpL, "\n") > 0;
+
+    if( !bOK )
+        return OGRERR_FAILURE;
+
+    m_nFeatureCount ++;
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                         GetFeatureCount()                            */
+/************************************************************************/
+
+GIntBig OGRVDVWriterLayer::GetFeatureCount( int )
+{
+    return m_nFeatureCount >= 0 ? m_nFeatureCount : 0;
+}
+
+/************************************************************************/
+/*                          CreateField()                               */
+/************************************************************************/
+
+OGRErr OGRVDVWriterLayer::CreateField(OGRFieldDefn* poFieldDefn, int /* bApprox */)
+{
+    if( m_nFeatureCount >= 0 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Fields can no longer by added to layer %s",m_poFeatureDefn->GetName());
+        return OGRERR_FAILURE;
+    }
+
+    if( m_poVDV452Table != NULL )
+    {
+        bool bFound = false;
+        for(size_t i=0;i<m_poVDV452Table->aosFields.size();i++)
+        {
+            const char* pszFieldName = poFieldDefn->GetNameRef();
+            if( (m_osVDV452Lang == "en" &&
+                 EQUAL(m_poVDV452Table->aosFields[i].osEnglishName, pszFieldName)) ||
+                (m_osVDV452Lang == "de" &&
+                 EQUAL(m_poVDV452Table->aosFields[i].osGermanName, pszFieldName)) )
+            {
+                bFound = true;
+                break;
+            }
+        }
+        if( !bFound )
+        {
+            CPLError(m_bProfileStrict ? CE_Failure : CE_Warning, CPLE_AppDefined,
+                     "Field %s is not an allowed field for table %s",
+                     poFieldDefn->GetNameRef(), m_poFeatureDefn->GetName());
+            if( m_bProfileStrict )
+                return OGRERR_FAILURE;
+        }
+        if( EQUAL(m_poFeatureDefn->GetName(), "STOP") ||
+            EQUAL(m_poFeatureDefn->GetName(), "REC_ORT") )
+        {
+            if( EQUAL(poFieldDefn->GetNameRef(), "POINT_LONGITUDE") ||
+                EQUAL(poFieldDefn->GetNameRef(), "ORT_POS_LAENGE") )
+            {
+                m_iLongitudeVDV452 = m_poFeatureDefn->GetFieldCount();
+            }
+            else if( EQUAL(poFieldDefn->GetNameRef(), "POINT_LATITUDE") ||
+                EQUAL(poFieldDefn->GetNameRef(), "ORT_POS_BREITE") )
+            {
+                m_iLatitudeVDV452 = m_poFeatureDefn->GetFieldCount();
+            }
+        }
+    }
+
+    m_poFeatureDefn->AddFieldDefn(poFieldDefn);
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                         TestCapability()                             */
+/************************************************************************/
+
+int OGRVDVWriterLayer::TestCapability(const char* pszCap)
+{
+    if( EQUAL(pszCap, OLCSequentialWrite) )
+        return m_bWritePossible;
+    if( EQUAL(pszCap, OLCCreateField) )
+        return m_nFeatureCount < 0;
+    return FALSE;
+}
+
+/************************************************************************/
+/*                         StopAsCurrentLayer()                         */
+/************************************************************************/
+
+void OGRVDVWriterLayer::StopAsCurrentLayer()
+{
+    if( m_bWritePossible )
+    {
+        m_bWritePossible = false;
+        if( m_fpL != NULL )
+        {
+            WriteSchemaIfNeeded();
+            VSIFPrintfL(m_fpL, "end; " CPL_FRMT_GIB "\n", m_nFeatureCount);
+        }
+    }
+}
+
+/************************************************************************/
+/*                         OGRVDVWriteHeader()                          */
+/************************************************************************/
+
+static bool OGRVDVWriteHeader(VSILFILE* fpL, char** papszOptions)
+{
+    bool bRet = true;
+    const bool bStandardHeader =
+            CSLFetchBoolean(papszOptions, "STANDARD_HEADER", TRUE) != FALSE;
+
+    struct tm tm;
+    CPLUnixTimeToYMDHMS(time(NULL), &tm);
+    const char* pszSrc = CSLFetchNameValueDef(papszOptions, "HEADER_SRC",
+        (bStandardHeader ) ? "UNKNOWN" : NULL);
+    const char* pszSrcDate = CSLFetchNameValueDef(papszOptions, "HEADER_SRC_DATE",
+        (pszSrc) ? CPLSPrintf("%02d.%02d.%04d", tm.tm_mday, tm.tm_mon + 1, tm.tm_year + 1900) : NULL);
+    const char* pszSrcTime = CSLFetchNameValueDef(papszOptions, "HEADER_SRC_TIME",
+        (pszSrc) ? CPLSPrintf("%02d.%02d.%02d", tm.tm_hour, tm.tm_min, tm.tm_sec) : NULL);
+
+    if( pszSrc && pszSrcDate && pszSrcTime )
+    {
+        bRet &= VSIFPrintfL(fpL, "mod; DD.MM.YYYY; HH:MM:SS; free\n") > 0;
+        bRet &= VSIFPrintfL(fpL, "src; \"%s\"; \"%s\"; \"%s\"\n",
+                            OGRVDVEscapeString(pszSrc).c_str(),
+                            OGRVDVEscapeString(pszSrcDate).c_str(),
+                            OGRVDVEscapeString(pszSrcTime).c_str()) > 0;
+    }
+
+    if( bStandardHeader)
+    {
+        const char* pszChs = CSLFetchNameValueDef(papszOptions, "HEADER_CHS", "ISO8859-1");
+        const char* pszVer = CSLFetchNameValueDef(papszOptions, "HEADER_VER", "1.4");
+        const char* pszIfv = CSLFetchNameValueDef(papszOptions, "HEADER_IFV", "1.4");
+        const char* pszDve = CSLFetchNameValueDef(papszOptions, "HEADER_DVE", "1.4");
+        const char* pszFft = CSLFetchNameValueDef(papszOptions, "HEADER_FFT", "");
+
+        bRet &= VSIFPrintfL(fpL, "chs; \"%s\"\n", OGRVDVEscapeString(pszChs).c_str()) > 0;
+        bRet &= VSIFPrintfL(fpL, "ver; \"%s\"\n", OGRVDVEscapeString(pszVer).c_str()) > 0;
+        bRet &= VSIFPrintfL(fpL, "ifv; \"%s\"\n", OGRVDVEscapeString(pszIfv).c_str()) > 0;
+        bRet &= VSIFPrintfL(fpL, "dve; \"%s\"\n", OGRVDVEscapeString(pszDve).c_str()) > 0;
+        bRet &= VSIFPrintfL(fpL, "fft; \"%s\"\n", OGRVDVEscapeString(pszFft).c_str()) > 0;
+    }
+
+
+    for(char** papszIter = papszOptions;
+               papszIter != NULL && *papszIter != NULL;
+               papszIter++)
+    {
+        if( STARTS_WITH_CI(*papszIter, "HEADER_") &&
+            !STARTS_WITH_CI(*papszIter, "HEADER_SRC") &&
+            (!bStandardHeader ||
+             (!EQUAL(*papszIter, "HEADER_CHS") &&
+              !EQUAL(*papszIter, "HEADER_VER") &&
+              !EQUAL(*papszIter, "HEADER_IFV") &&
+              !EQUAL(*papszIter, "HEADER_DVE") &&
+              !EQUAL(*papszIter, "HEADER_FFT"))) )
+        {
+            char* pszKey = NULL;
+            const char* pszValue = CPLParseNameValue(*papszIter, &pszKey);
+            if( pszKey && strlen(pszKey) > strlen("HEADER_") && pszValue )
+            {
+                bRet &= VSIFPrintfL(fpL, "%s; \"%s\"\n",
+                                    pszKey + strlen("HEADER_"),
+                                    OGRVDVEscapeString(pszValue).c_str()) > 0;
+            }
+            CPLFree(pszKey);
+        }
+    }
+
+    return bRet;
+}
+
+/************************************************************************/
+/*                      OGRVDVLoadVDV452Tables()                        */
+/************************************************************************/
+
+static bool OGRVDVLoadVDV452Tables(OGRVDV452Tables& oTables)
+{
+    const char* pszXMLDescFilename = CPLFindFile("gdal", "vdv452.xml");
+    if (pszXMLDescFilename == NULL)
+    {
+        CPLDebug("VDV", "Cannot find XML file : %s", "vdv452.xml");
+        return false;
+    }
+
+    CPLXMLNode* psRoot = CPLParseXMLFile(pszXMLDescFilename);
+    if( psRoot == NULL)
+    {
+        return false;
+    }
+    CPLXMLNode* psTables = CPLGetXMLNode(psRoot, "=Layers");
+    if( psTables != NULL )
+    {
+        for(CPLXMLNode* psTable = psTables->psChild;
+                        psTable != NULL; psTable = psTable->psNext )
+        {
+            if( psTable->eType != CXT_Element || strcmp(psTable->pszValue, "Layer") != 0 )
+                continue;
+            OGRVDV452Table* poTable = new OGRVDV452Table();
+            poTable->osEnglishName = CPLGetXMLValue(psTable, "name_en", "");
+            poTable->osGermanName = CPLGetXMLValue(psTable, "name_de", "");
+            oTables.aosTables.push_back(poTable);
+            oTables.oMapEnglish[poTable->osEnglishName] = poTable;
+            oTables.oMapGerman[poTable->osGermanName] = poTable;
+            for(CPLXMLNode* psField = psTable->psChild;
+                        psField != NULL; psField = psField->psNext )
+            {
+                if( psField->eType != CXT_Element || strcmp(psField->pszValue, "Field") != 0 )
+                    continue;
+                OGRVDV452Field oField;
+                oField.osEnglishName = CPLGetXMLValue(psField, "name_en", "");
+                oField.osGermanName = CPLGetXMLValue(psField, "name_de", "");
+                oField.osType = CPLGetXMLValue(psField, "type", "");
+                oField.nWidth = atoi(CPLGetXMLValue(psField, "width", "0"));
+                poTable->aosFields.push_back(oField);
+            }
+        }
+    }
+
+    CPLDestroyXMLNode(psRoot);
+    return true;
+}
+
+/************************************************************************/
+/*                           ICreateLayer()                             */
+/************************************************************************/
+
+OGRLayer *
+OGRVDVDataSource::ICreateLayer( const char *pszLayerName,
+                                OGRSpatialReference * /*poSpatialRef*/,
+                                OGRwkbGeometryType eGType,
+                                char ** papszOptions  )
+{
+    if( !m_bUpdate )
+        return NULL;
+
+    const char* pszProfile = CSLFetchNameValueDef(papszOptions, "PROFILE", "GENERIC");
+    if( STARTS_WITH_CI(pszProfile, "VDV-452") && !m_bVDV452Loaded )
+    {
+        m_bVDV452Loaded = true;
+        OGRVDVLoadVDV452Tables(m_oVDV452Tables);
+    }
+    const bool bProfileStrict =
+        CSLFetchBoolean(papszOptions, "PROFILE_STRICT", FALSE) != FALSE;
+    const bool bCreateAllFields =
+        CSLFetchBoolean(papszOptions, "CREATE_ALL_FIELDS", TRUE) != FALSE;
+
+    CPLString osUpperLayerName(pszLayerName);
+    osUpperLayerName.toupper();
+
+    OGRVDV452Table* poVDV452Table = NULL;
+    CPLString osVDV452Lang;
+    bool bOKTable = true;
+    if( EQUAL(pszProfile, "VDV-452") )
+    {
+        if( m_oVDV452Tables.oMapEnglish.find(osUpperLayerName) !=
+            m_oVDV452Tables.oMapEnglish.end() )
+        {
+            poVDV452Table = m_oVDV452Tables.oMapEnglish[osUpperLayerName];
+            osVDV452Lang = "en";
+        }
+        else if( m_oVDV452Tables.oMapGerman.find(osUpperLayerName) !=
+                 m_oVDV452Tables.oMapGerman.end() )
+        {
+            poVDV452Table = m_oVDV452Tables.oMapGerman[osUpperLayerName];
+            osVDV452Lang = "de";
+        }
+        else
+        {
+            bOKTable = false;
+        }
+    }
+    else if( EQUAL(pszProfile, "VDV-452-ENGLISH") )
+    {
+        if( m_oVDV452Tables.oMapEnglish.find(osUpperLayerName) !=
+            m_oVDV452Tables.oMapEnglish.end() )
+        {
+            poVDV452Table = m_oVDV452Tables.oMapEnglish[osUpperLayerName];
+            osVDV452Lang = "en";
+        }
+        else
+        {
+            bOKTable = false;
+        }
+    }
+    else if( EQUAL(pszProfile, "VDV-452-GERMAN") )
+    {
+        if( m_oVDV452Tables.oMapGerman.find(osUpperLayerName) !=
+            m_oVDV452Tables.oMapGerman.end() )
+        {
+            poVDV452Table = m_oVDV452Tables.oMapGerman[osUpperLayerName];
+            osVDV452Lang = "de";
+        }
+        else
+        {
+            bOKTable = false;
+        }
+    }
+    if( !bOKTable )
+    {
+        CPLError(bProfileStrict ? CE_Failure : CE_Warning,
+                 CPLE_AppDefined, "%s is not a VDV-452 table",
+                 pszLayerName);
+        if( bProfileStrict )
+            return NULL;
+    }
+
+    VSILFILE* fpL;
+    if( m_bSingleFile )
+    {
+        fpL = m_fpL;
+        if( !m_bNew && m_nLayerCount == 0 )
+        {
+            // Find last non-empty line in the file
+            VSIFSeekL(fpL, 0, SEEK_END);
+            vsi_l_offset nFileSize = VSIFTellL(fpL);
+            vsi_l_offset nOffset = nFileSize;
+            bool bTerminatingEOL = true;
+            while( nOffset > 0 )
+            {
+                VSIFSeekL(fpL, nOffset - 1, SEEK_SET);
+                char ch;
+                VSIFReadL(&ch, 1, 1, fpL);
+                if( bTerminatingEOL )
+                {
+                    if( !(ch == '\r' || ch == '\n') )
+                    {
+                        bTerminatingEOL = false;
+                    }
+                }
+                else
+                {
+                    if( ch == '\r' || ch == '\n' )
+                        break;
+                }
+                nOffset --;
+            }
+
+            // If it is "eof;..." then overwrite it with new content
+            const char* pszLine = CPLReadLineL(fpL);
+            if( pszLine != NULL && STARTS_WITH(pszLine, "eof;") )
+            {
+                VSIFSeekL(fpL, nOffset, SEEK_SET);
+                VSIFTruncateL(fpL, VSIFTellL(fpL));
+            }
+            else if( nFileSize > 0 )
+            {
+                // Otherwise make sure the file ends with an eol character
+                VSIFSeekL(fpL, nFileSize - 1, SEEK_SET);
+                char ch;
+                VSIFReadL(&ch, 1, 1, fpL);
+                VSIFSeekL(fpL, nFileSize, SEEK_SET);
+                if( !(ch == '\r' || ch == '\n') )
+                {
+                    ch = '\n';
+                    VSIFWriteL(&ch, 1, 1, fpL);
+                }
+            }
+        }
+    }
+    else
+    {
+        CPLString osExtension = CSLFetchNameValueDef(papszOptions, "EXTENSION", "x10");
+        CPLString osFilename = CPLFormFilename(m_osFilename, pszLayerName,
+                                               osExtension);
+        fpL = VSIFOpenL(osFilename, "wb");
+        if( fpL == NULL )
+        {
+            CPLError( CE_Failure, CPLE_FileIO, "Cannot create %s",
+                      osFilename.c_str() );
+            return NULL;
+        }
+    }
+
+    GetLayerCount();
+
+    if( m_nLayerCount == 0 || !m_bSingleFile )
+    {
+        if( !OGRVDVWriteHeader(fpL, papszOptions) )
+        {
+            if( !m_bSingleFile )
+                VSIFCloseL(fpL);
+            return NULL;
+        }
+    }
+
+    m_bMustWriteEof = true;
+
+    OGRVDVWriterLayer* poLayer = new OGRVDVWriterLayer(this,
+                                                       pszLayerName,
+                                                       fpL,
+                                                       !m_bSingleFile,
+                                                       poVDV452Table,
+                                                       osVDV452Lang,
+                                                       bProfileStrict);
+    m_papoLayers = static_cast<OGRLayer**>(CPLRealloc(
+                m_papoLayers, sizeof(OGRLayer*) * (m_nLayerCount + 1) ));
+    m_papoLayers[m_nLayerCount] = poLayer;
+    m_nLayerCount ++;
+
+    if( eGType == wkbPoint && poVDV452Table != NULL &&
+        (EQUAL(pszLayerName, "STOP") || EQUAL(pszLayerName, "REC_ORT")) )
+    {
+        poLayer->GetLayerDefn()->SetGeomType(wkbPoint);
+    }
+
+    if( bCreateAllFields && poVDV452Table != NULL )
+    {
+        for(size_t i=0; i<poVDV452Table->aosFields.size();i++)
+        {
+            const char* pszFieldName = (osVDV452Lang == "en") ?
+                            poVDV452Table->aosFields[i].osEnglishName.c_str() :
+                            poVDV452Table->aosFields[i].osGermanName.c_str();
+            OGRFieldType eType = OFTString;
+            int nWidth = poVDV452Table->aosFields[i].nWidth;
+            if( poVDV452Table->aosFields[i].osType == "num" ||
+                poVDV452Table->aosFields[i].osType == "boolean" )
+                eType = OFTInteger;
+            if( poVDV452Table->aosFields[i].osType == "num" )
+            {
+                /* VDV 451 is without sign */
+                nWidth ++;
+                if( nWidth >= 10 )
+                    eType = OFTInteger64;
+            }
+            OGRFieldDefn oField( pszFieldName, eType );
+            if( poVDV452Table->aosFields[i].osType == "boolean" )
+                oField.SetSubType(OFSTBoolean);
+            oField.SetWidth( nWidth );
+            poLayer->CreateField(&oField);
+        }
+    }
+
+    return poLayer;
+}
+
+/************************************************************************/
+/*                       SetCurrentWriterLayer()                        */
+/************************************************************************/
+
+void OGRVDVDataSource::SetCurrentWriterLayer(OGRVDVWriterLayer* poLayer)
+{
+    if( !m_bSingleFile )
+        return;
+    if( m_poCurrentWriterLayer != NULL && m_poCurrentWriterLayer != poLayer )
+    {
+        m_poCurrentWriterLayer->StopAsCurrentLayer();
+    }
+    m_poCurrentWriterLayer = poLayer;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRVDVDataSource::TestCapability( const char * pszCap )
+
+{
+    if( EQUAL(pszCap,ODsCCreateLayer) )
+        return m_bUpdate;
+    return FALSE;
+}
+
+/************************************************************************/
+/*                                 Create()                             */
+/************************************************************************/
+
+GDALDataset* OGRVDVDataSource::Create( const char * pszName,
+                                        int /*nXSize*/, int /*nYSize*/, int /*nBands*/,
+                                        GDALDataType /*eType*/,
+                                        char ** papszOptions )
+
+{
+/* -------------------------------------------------------------------- */
+/*      First, ensure there isn't any such file yet.                    */
+/* -------------------------------------------------------------------- */
+    VSIStatBufL sStatBuf;
+    if( VSIStatL( pszName, &sStatBuf ) == 0 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "It seems a file system object called '%s' already exists.",
+                  pszName );
+
+        return NULL;
+    }
+
+    bool bSingleFile = CPL_TO_BOOL(CSLFetchBoolean(papszOptions, "SINGLE_FILE", TRUE));
+    if( !bSingleFile )
+    {
+        if( VSIMkdir( pszName, 0755 ) != 0 )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Failed to create directory %s:\n%s",
+                      pszName, VSIStrerror( errno ) );
+            return NULL;
+        }
+    }
+
+    VSILFILE* fpL = NULL;
+    if( bSingleFile )
+    {
+        fpL = VSIFOpenL(pszName, "wb");
+        if( fpL == NULL )
+        {
+            CPLError( CE_Failure, CPLE_FileIO, "Cannot create %s", pszName );
+            return NULL;
+        }
+    }
+    OGRVDVDataSource* poDS = new OGRVDVDataSource(pszName, fpL, true,
+                                                  bSingleFile,
+                                                  true /* new */);
+    return poDS;
+}
+
+/************************************************************************/
+/*                         RegisterOGRVDV()                             */
+/************************************************************************/
+
+void RegisterOGRVDV()
+
+{
+    if( GDALGetDriverByName( "VDV" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "VDV" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "VDV-451/VDV-452/INTREST Data Format" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_vdv.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "txt x10");
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
+                               "Integer Integer64 String" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+"<CreationOptionList>"
+"  <Option name='SINGLE_FILE' type='boolean' description='Whether several layers "
+"should be put in the same file. If no, the name is assumed to be a directory name' default='YES'/>"
+"</CreationOptionList>");
+
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+"<LayerCreationOptionList>"
+"  <Option name='EXTENSION' type='string' description='Layer file extension. Only used for SINGLE_FILE=NO' default='x10'/>"
+"  <Option name='PROFILE' type='string-select' description='Profile' default='GENERIC'>"
+"       <Value>GENERIC</Value>"
+"       <Value>VDV-452</Value>"
+"       <Value>VDV-452-ENGLISH</Value>"
+"       <Value>VDV-452-GERMAN</Value>"
+"  </Option>"
+"  <Option name='PROFILE_STRICT' type='boolean' description='Whether checks of profile should be strict' default='NO'/>"
+"  <Option name='CREATE_ALL_FIELDS' type='boolean' description="
+    "'Whether all fields of predefined profiles should be created at layer creation' default='YES'/>"
+"  <Option name='STANDARD_HEADER' type='boolean' description='Whether to write standard header fields' default='YES'/>"
+"  <Option name='HEADER_SRC' type='string' description='Value of the src header field' default='UNKNOWN'/>"
+"  <Option name='HEADER_SRC_DATE' type='string' description='Value of the date of the src header field as DD.MM.YYYY'/>"
+"  <Option name='HEADER_SRC_TIME' type='string' description='Value of the time of the src header field as HH.MM.SS'/>"
+"  <Option name='HEADER_CHS' type='string' description='Value of the chs header field' default='ISO8859-1'/>"
+"  <Option name='HEADER_VER' type='string' description='Value of the ver header field' default='1.4'/>"
+"  <Option name='HEADER_IFV' type='string' description='Value of the ifv header field' default='1.4'/>"
+"  <Option name='HEADER_DVE' type='string' description='Value of the dve header field' default='1.4'/>"
+"  <Option name='HEADER_FFT' type='string' description='Value of the fft header field' default=''/>"
+"  <Option name='HEADER_*' type='string' description='Value of another header field'/>"
+"</LayerCreationOptionList>");
+    poDriver->pfnIdentify = OGRVDVDriverIdentify;
+    poDriver->pfnOpen = OGRVDVDataSource::Open;
+    poDriver->pfnCreate = OGRVDVDataSource::Create;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/ogr/ogrsf_frmts/vfk/drv_vfk.html b/ogr/ogrsf_frmts/vfk/drv_vfk.html
index 9fd5dee..bf00491 100644
--- a/ogr/ogrsf_frmts/vfk/drv_vfk.html
+++ b/ogr/ogrsf_frmts/vfk/drv_vfk.html
@@ -7,7 +7,7 @@
 
 <h1>VFK - Czech Cadastral Exchange Data Format</h1>
 
-This driver reads VFK files, ie. data in the <em>Czech cadastral
+This driver reads VFK files, i.e. data in the <em>Czech cadastral
 exchange data format</em>. The VFK file is recognized as an OGR
 datasource with zero or more OGR layers.
 
@@ -23,15 +23,15 @@ used. Feature types cannot be mixed in one layer.
 <h3>Configuration</h3>
 
 Starting with OGR 1.9, the driver reads and writes VFK data from/to
-internal SQLite database. Default name of the database is
-"input_vfk_file.db". Since OGR 1.10, you can define
-an alternative DB name with <b>OGR_VFK_DB_NAME</b> configuration
+internal SQLite database. Default name for the database is
+"input_vfk_file.db". Since OGR 1.10, you can define an
+alternative DB name with <b>OGR_VFK_DB_NAME</b> configuration
 option. If <b>OGR_VFK_DB_OVERWRITE=YES</b> configuration option is
 given, than the driver overwrites existing SQLite database and reads
-data from original input VFK file. By default, the internal SQLite
-database is not automatically deleted. Since OGR 1.11, the internal
-database is deleted if <b>OGR_VFK_DB_DELETE=YES</b> configuration
-option is given.
+data from original input VFK file into newly created DB. Since OGR
+1.11, if <b>OGR_VFK_DB_DELETE=YES</b> configuration option is given
+than the driver deletes the internal SQLite database when closing the
+data source.
 
 <p>
 Starting with OGR 1.10, resolved geometries are stored also in SQLite
diff --git a/ogr/ogrsf_frmts/vfk/ogr_vfk.h b/ogr/ogrsf_frmts/vfk/ogr_vfk.h
index a8bf048..91b6cd3 100644
--- a/ogr/ogrsf_frmts/vfk/ogr_vfk.h
+++ b/ogr/ogrsf_frmts/vfk/ogr_vfk.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_vfk.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogr_vfk.h 32177 2015-12-14 07:25:30Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/VFK driver.
@@ -61,11 +61,11 @@ private:
 
     /* get next feature */
     int                  m_iNextFeature;
-    
+
     /* private methods */
     OGRGeometry         *CreateGeometry(IVFKFeature *);
     OGRFeature          *GetFeature(IVFKFeature *);
-    
+
 public:
     OGRVFKLayer(const char *, OGRSpatialReference *,
                 OGRwkbGeometryType, OGRVFKDataSource *);
@@ -77,7 +77,7 @@ public:
     OGRFeatureDefn      *GetLayerDefn() { return poFeatureDefn; }
 
     void                 ResetReading();
-    
+
     int                  TestCapability(const char *);
 
     GIntBig              GetFeatureCount(int = TRUE);
@@ -92,9 +92,9 @@ private:
     /* list of available layers */
     OGRVFKLayer  **papoLayers;
     int            nLayers;
-    
+
     char *         pszName;
-    
+
     /* input related parameters */
     IVFKReader    *poReader;
 
@@ -106,9 +106,9 @@ public:
     ~OGRVFKDataSource();
 
     int            Open(const char *, int);
-    
+
     const char    *GetName() { return pszName; }
-    
+
     int            GetLayerCount() { return nLayers; }
     OGRLayer      *GetLayer(int);
 
diff --git a/ogr/ogrsf_frmts/vfk/ogrvfkdatasource.cpp b/ogr/ogrsf_frmts/vfk/ogrvfkdatasource.cpp
index acdd245..c05b6ec 100644
--- a/ogr/ogrsf_frmts/vfk/ogrvfkdatasource.cpp
+++ b/ogr/ogrsf_frmts/vfk/ogrvfkdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrvfkdatasource.cpp 26906 2014-01-31 16:28:21Z martinl $
+ * $Id: ogrvfkdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRVFKDatasource class.
@@ -33,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrvfkdatasource.cpp 26906 2014-01-31 16:28:21Z martinl $");
+CPL_CVSID("$Id: ogrvfkdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /*!
   \brief OGRVFKDataSource constructor
@@ -41,9 +41,9 @@ CPL_CVSID("$Id: ogrvfkdatasource.cpp 26906 2014-01-31 16:28:21Z martinl $");
 OGRVFKDataSource::OGRVFKDataSource()
 {
     pszName    = NULL;
-    
+
     poReader   = NULL;
-    
+
     papoLayers = NULL;
     nLayers    = 0;
 }
@@ -54,10 +54,10 @@ OGRVFKDataSource::OGRVFKDataSource()
 OGRVFKDataSource::~OGRVFKDataSource()
 {
     CPLFree(pszName);
-    
+
     if (poReader)
         delete poReader;
-    
+
     for(int i = 0; i < nLayers; i++)
         delete papoLayers[i];
 
@@ -76,19 +76,19 @@ int OGRVFKDataSource::Open(const char *pszNewName, int bTestOpen)
 {
     FILE * fp;
     char   szHeader[1000];
-    
+
     /* open the source file */
     fp = VSIFOpen(pszNewName, "r");
     if (fp == NULL) {
         if (!bTestOpen)
-            CPLError(CE_Failure, CPLE_OpenFailed, 
+            CPLError(CE_Failure, CPLE_OpenFailed,
                      "Failed to open VFK file `%s'",
                      pszNewName);
-        
+
         return FALSE;
     }
 
-   /* If we aren't sure it is VFK, load a header chunk and check    
+   /* If we aren't sure it is VFK, load a header chunk and check
       for signs it is VFK */
     if (bTestOpen) {
         size_t nRead = VSIFRead(szHeader, 1, sizeof(szHeader), fp);
@@ -97,12 +97,12 @@ int OGRVFKDataSource::Open(const char *pszNewName, int bTestOpen)
             return FALSE;
         }
         szHeader[MIN(nRead, sizeof(szHeader))-1] = '\0';
-        
+
         // TODO: improve check
-        if (strncmp(szHeader, "&H", 2) != 0) {
+        if (!STARTS_WITH(szHeader, "&H")) {
             VSIFClose(fp);
             return FALSE;
-        } 
+        }
     }
 
     /* We assume now that it is VFK. Close and instantiate a
@@ -110,29 +110,29 @@ int OGRVFKDataSource::Open(const char *pszNewName, int bTestOpen)
     VSIFClose(fp);
 
     pszName = CPLStrdup(pszNewName);
-    
+
     poReader = CreateVFKReader(pszNewName);
     if (poReader == NULL) {
-        CPLError(CE_Failure, CPLE_AppDefined, 
+        CPLError(CE_Failure, CPLE_AppDefined,
                  "File %s appears to be VFK but the VFK reader can't"
                  "be instantiated",
                  pszNewName);
         return FALSE;
     }
-   
+
     /* read data blocks, i.e. &B */
     poReader->ReadDataBlocks();
-    
+
     /* get list of layers */
     papoLayers = (OGRVFKLayer **) CPLCalloc(sizeof(OGRVFKLayer *), poReader->GetDataBlockCount());
-    
+
     for (int iLayer = 0; iLayer < poReader->GetDataBlockCount(); iLayer++) {
         papoLayers[iLayer] = CreateLayerFromBlock(poReader->GetDataBlock(iLayer));
         nLayers++;
     }
-    
+
     /* read data records if required */
-    if (CSLTestBoolean(CPLGetConfigOption("OGR_VFK_DB_READ_ALL_BLOCKS", "YES")))
+    if (CPLTestBool(CPLGetConfigOption("OGR_VFK_DB_READ_ALL_BLOCKS", "YES")))
         poReader->ReadDataRecords();
 
     return TRUE;
@@ -149,12 +149,12 @@ OGRLayer *OGRVFKDataSource::GetLayer(int iLayer)
 {
     if( iLayer < 0 || iLayer >= nLayers )
         return NULL;
-    
+
     return papoLayers[iLayer];
 }
 
 /*!
-  \brief Test datasource capabilies
+  \brief Test datasource capabilities
 
   \param pszCap capability
 
@@ -196,9 +196,9 @@ OGRVFKLayer *OGRVFKDataSource::CreateLayerFromBlock(const IVFKDataBlock *poDataB
             oField.SetWidth(poProperty->GetWidth());
         if(poProperty->GetPrecision() > 0)
             oField.SetPrecision(poProperty->GetPrecision());
-        
+
         poLayer->GetLayerDefn()->AddFieldDefn(&oField);
     }
-    
+
     return poLayer;
 }
diff --git a/ogr/ogrsf_frmts/vfk/ogrvfkdriver.cpp b/ogr/ogrsf_frmts/vfk/ogrvfkdriver.cpp
index 5c73bab..145ba51 100644
--- a/ogr/ogrsf_frmts/vfk/ogrvfkdriver.cpp
+++ b/ogr/ogrsf_frmts/vfk/ogrvfkdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrvfkdriver.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogrvfkdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRVFKDriver class.
@@ -33,13 +33,13 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrvfkdriver.cpp 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: ogrvfkdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
 
 static int OGRVFKDriverIdentify(GDALOpenInfo* poOpenInfo)
 {
     return ( poOpenInfo->fpL != NULL &&
              poOpenInfo->nHeaderBytes >= 2 &&
-             strncmp((const char*)poOpenInfo->pabyHeader, "&H", 2) == 0 );
+             STARTS_WITH((const char*)poOpenInfo->pabyHeader, "&H") );
 }
 
 /*
@@ -70,25 +70,23 @@ static GDALDataset *OGRVFKDriverOpen(GDALOpenInfo* poOpenInfo)
 */
 void RegisterOGRVFK()
 {
-    if (!GDAL_CHECK_VERSION("OGR/VFK driver"))
+    if( !GDAL_CHECK_VERSION("OGR/VFK driver") )
         return;
-    GDALDriver  *poDriver;
 
-    if( GDALGetDriverByName( "VFK" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    if( GDALGetDriverByName( "VFK" ) != NULL )
+        return;
 
-        poDriver->SetDescription( "VFK" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Czech Cadastral Exchange Data Format" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "vfk" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_vfk.html" );
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->pfnOpen = OGRVFKDriverOpen;
-        poDriver->pfnIdentify = OGRVFKDriverIdentify;
+    poDriver->SetDescription( "VFK" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Czech Cadastral Exchange Data Format" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "vfk" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_vfk.html" );
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    poDriver->pfnOpen = OGRVFKDriverOpen;
+    poDriver->pfnIdentify = OGRVFKDriverIdentify;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/vfk/ogrvfklayer.cpp b/ogr/ogrsf_frmts/vfk/ogrvfklayer.cpp
index 7cfce19..fdc6e8f 100644
--- a/ogr/ogrsf_frmts/vfk/ogrvfklayer.cpp
+++ b/ogr/ogrsf_frmts/vfk/ogrvfklayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrvfklayer.cpp 28382 2015-01-30 15:29:41Z rouault $
+ * $Id: ogrvfklayer.cpp 32177 2015-12-14 07:25:30Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRVFKLayer class.
@@ -33,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrvfklayer.cpp 28382 2015-01-30 15:29:41Z rouault $");
+CPL_CVSID("$Id: ogrvfklayer.cpp 32177 2015-12-14 07:25:30Z goatbar $");
 
 /*!
   \brief OGRVFKLayer constructor
@@ -41,12 +41,14 @@ CPL_CVSID("$Id: ogrvfklayer.cpp 28382 2015-01-30 15:29:41Z rouault $");
   \param pszName layer name
   \param poSRSIn spatial reference
   \param eReqType WKB geometry type
-  \param poDSIn  data source where to registrate OGR layer
+  \param poDSIn  data source where to register OGR layer
 */
 OGRVFKLayer::OGRVFKLayer(const char *pszName,
                          OGRSpatialReference *poSRSIn,
                          OGRwkbGeometryType eReqType,
-                         OGRVFKDataSource *poDSIn)
+                         OGRVFKDataSource *poDSIn) :
+    poDS(poDSIn),
+    m_iNextFeature(0)
 {
     /* set spatial reference */
     if( poSRSIn == NULL ) {
@@ -61,9 +63,6 @@ OGRVFKLayer::OGRVFKLayer(const char *pszName,
         poSRS = poSRSIn->Clone();
     }
 
-    /* layer datasource */
-    poDS = poDSIn;
-
     /* feature definition */
     poFeatureDefn = new OGRFeatureDefn(pszName);
     SetDescription( poFeatureDefn->GetName() );
@@ -98,13 +97,13 @@ int OGRVFKLayer::TestCapability(const char * pszCap)
     if (EQUAL(pszCap, OLCRandomRead)) {
         return TRUE; /* ? */
     }
-    
+
     return FALSE;
 }
 
 /*!
   \brief Reset reading
-  
+
   \todo To be implemented
 */
 void OGRVFKLayer::ResetReading()
@@ -158,33 +157,19 @@ GIntBig OGRVFKLayer::GetFeatureCount(CPL_UNUSED int bForce)
 */
 OGRFeature *OGRVFKLayer::GetNextFeature()
 {
-    VFKFeature  *poVFKFeature;
-    
-    OGRFeature  *poOGRFeature;
-    OGRGeometry *poOGRGeom;
-    
-    poOGRFeature = NULL;
-    poOGRGeom    = NULL;
-    
     /* loop till we find and translate a feature meeting all our
        requirements
     */
-    while (TRUE) {
-        /* cleanup last feature, and get a new raw vfk feature */
-        if (poOGRGeom != NULL) {
-            delete poOGRGeom;
-            poOGRGeom = NULL;
-        }
-        
-        poVFKFeature = (VFKFeature *) poDataBlock->GetNextFeature();
+    while( true ) {
+        IVFKFeature* poVFKFeature = poDataBlock->GetNextFeature();
         if (!poVFKFeature)
-            return NULL;        
-        
+            return NULL;
+
         /* skip feature with unknown geometry type */
         if (poVFKFeature->GetGeometryType() == wkbUnknown)
             continue;
-        
-        poOGRFeature = GetFeature(poVFKFeature);
+
+        OGRFeature* poOGRFeature = GetFeature(poVFKFeature);
         if (poOGRFeature)
             return poOGRFeature;
     }
@@ -202,55 +187,55 @@ OGRFeature *OGRVFKLayer::GetFeature(GIntBig nFID)
     IVFKFeature *poVFKFeature;
 
     poVFKFeature = poDataBlock->GetFeature(nFID);
-    
+
     if (!poVFKFeature)
         return NULL;
 
     CPLAssert(nFID == poVFKFeature->GetFID());
     CPLDebug("OGR-VFK", "OGRVFKLayer::GetFeature(): name=%s fid=" CPL_FRMT_GIB, GetName(), nFID);
-    
+
     return GetFeature(poVFKFeature);
 }
 
 /*!
   \brief Get feature (private)
-  
+
   \return pointer to OGRFeature or NULL not found
 */
 OGRFeature *OGRVFKLayer::GetFeature(IVFKFeature *poVFKFeature)
 {
     OGRGeometry *poGeom;
-    
+
     /* skip feature with unknown geometry type */
     if (poVFKFeature->GetGeometryType() == wkbUnknown)
         return NULL;
-    
+
     /* get features geometry */
     poGeom = CreateGeometry(poVFKFeature);
     if (poGeom != NULL)
         poGeom->assignSpatialReference(poSRS);
-    
+
     /* does it satisfy the spatial query, if there is one? */
     if (m_poFilterGeom != NULL && poGeom && !FilterGeometry(poGeom)) {
         return NULL;
     }
-    
+
     /* convert the whole feature into an OGRFeature */
     OGRFeature *poOGRFeature = new OGRFeature(GetLayerDefn());
     poOGRFeature->SetFID(poVFKFeature->GetFID());
     // poOGRFeature->SetFID(++m_iNextFeature);
-    
+
     poVFKFeature->LoadProperties(poOGRFeature);
-    
+
     /* test against the attribute query */
     if (m_poAttrQuery != NULL &&
         !m_poAttrQuery->Evaluate(poOGRFeature)) {
         delete poOGRFeature;
         return NULL;
     }
-    
+
     if (poGeom)
         poOGRFeature->SetGeometryDirectly(poGeom->clone());
-    
+
     return poOGRFeature;
 }
diff --git a/ogr/ogrsf_frmts/vfk/vfkdatablock.cpp b/ogr/ogrsf_frmts/vfk/vfkdatablock.cpp
index d65a66a..d2aa7ae 100644
--- a/ogr/ogrsf_frmts/vfk/vfkdatablock.cpp
+++ b/ogr/ogrsf_frmts/vfk/vfkdatablock.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vfkdatablock.cpp 28382 2015-01-30 15:29:41Z rouault $
+ * $Id: vfkdatablock.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  VFK Reader - Data block definition
  * Purpose:  Implements VFKDataBlock class.
@@ -43,27 +43,23 @@
 
   \param pszName data block name
 */
-IVFKDataBlock::IVFKDataBlock(const char *pszName, const IVFKReader *poReader)
+IVFKDataBlock::IVFKDataBlock(const char *pszName, const IVFKReader *poReader) :
+    m_nPropertyCount(0),
+    m_papoProperty(NULL),
+    m_bGeometry(false),   // geometry is not loaded by default
+    m_nGeometryType(wkbUnknown),
+    m_bGeometryPerBlock(true),    // load geometry per block/feature
+    m_nFeatureCount(-1),  // Load data on first request
+    m_iNextFeature(-1),
+    m_poReader(const_cast<IVFKReader *>(poReader))
 {
     m_pszName        = CPLStrdup(pszName);
-    
-    m_nPropertyCount = 0;
-    m_papoProperty   = NULL;
 
-    m_nFeatureCount  = -1; /* load data on first request */
     m_papoFeature    = NULL;
 
-    m_iNextFeature   = -1;
-
-    m_nGeometryType     = wkbUnknown;
-    m_bGeometry         = FALSE;   /* geometry is not loaded by default */
-    m_bGeometryPerBlock = TRUE;    /* load geometry per block/feature */
-
-    m_poReader       = (IVFKReader *) poReader;
-    
-    m_nRecordCount[RecordValid]      = 0L;      /* number of valid records */
-    m_nRecordCount[RecordSkipped]    = 0L;      /* number of skipped (invalid) records */
-    m_nRecordCount[RecordDuplicated] = 0L;      /* number of duplicated records */
+    m_nRecordCount[RecordValid]      = 0L;  /* number of valid records */
+    m_nRecordCount[RecordSkipped]    = 0L;  /* number of skipped (invalid) records */
+    m_nRecordCount[RecordDuplicated] = 0L;  /* number of duplicated records */
 }
 
 /*!
@@ -108,12 +104,8 @@ VFKPropertyDefn *IVFKDataBlock::GetProperty(int iIndex) const
 */
 void IVFKDataBlock::SetProperties(const char *poLine)
 {
-    const char *poChar, *poProp;
-    char *pszName, *pszType;
-    int   nLength;
-    
-    pszName = pszType = NULL;
-    
+    const char *poChar;
+
     /* skip data block name */
     for (poChar = poLine; *poChar != '0' && *poChar != ';'; poChar++)
         ;
@@ -123,14 +115,16 @@ void IVFKDataBlock::SetProperties(const char *poLine)
     poChar++;
 
     /* read property name/type */
-    poProp  = poChar;
-    nLength = 0;
+    const char *poProp  = poChar;
+    char *pszName = NULL;
+    char *pszType = NULL;
+    int nLength = 0;
     while(*poChar != '\0') {
         if (*poChar == ' ') {
             pszName = (char *) CPLRealloc(pszName, nLength + 1);
             strncpy(pszName, poProp, nLength);
             pszName[nLength] = '\0';
-            
+
             poProp = ++poChar;
             nLength = 0;
         }
@@ -138,12 +132,12 @@ void IVFKDataBlock::SetProperties(const char *poLine)
             pszType = (char *) CPLRealloc(pszType, nLength + 1);
             strncpy(pszType, poProp, nLength);
             pszType[nLength] = '\0';
-            
+
             /* add property */
             if (pszName && *pszName != '\0' &&
-                pszType && *pszType != '\0')
+                *pszType != '\0')
                 AddProperty(pszName, pszType);
-            
+
             poProp = ++poChar;
             nLength = 0;
         }
@@ -154,12 +148,12 @@ void IVFKDataBlock::SetProperties(const char *poLine)
     pszType = (char *) CPLRealloc(pszType, nLength + 1);
     strncpy(pszType, poProp, nLength);
     pszType[nLength] = '\0';
-    
+
     /* add property */
     if (pszName && *pszName != '\0' &&
-        pszType && *pszType != '\0')
+        *pszType != '\0')
         AddProperty(pszName, pszType);
-    
+
     CPLFree(pszName);
     CPLFree(pszType);
 }
@@ -178,7 +172,7 @@ int IVFKDataBlock::AddProperty(const char *pszName, const char *pszType)
                                                          m_poReader->IsLatin2());
 
     m_nPropertyCount++;
-    
+
     m_papoProperty = (VFKPropertyDefn **)
         CPLRealloc(m_papoProperty, sizeof (VFKPropertyDefn *) * m_nPropertyCount);
     m_papoProperty[m_nPropertyCount-1] = poNewProperty;
@@ -188,7 +182,7 @@ int IVFKDataBlock::AddProperty(const char *pszName, const char *pszType)
 
 /*!
   \brief Get number of features for given data block
-  
+
   \return number of features
 */
 GIntBig IVFKDataBlock::GetFeatureCount()
@@ -244,17 +238,17 @@ IVFKFeature *IVFKDataBlock::GetNextFeature()
     if (m_nFeatureCount < 0) {
         m_poReader->ReadDataRecords(this);
     }
-    
+
     if (m_bGeometryPerBlock && !m_bGeometry) {
         LoadGeometry();
     }
-    
+
     if (m_iNextFeature < 0)
         ResetReading();
 
     if (m_iNextFeature < 0 || m_iNextFeature >= m_nFeatureCount)
         return NULL;
-    
+
     return m_papoFeature[m_iNextFeature++];
 }
 
@@ -268,17 +262,17 @@ IVFKFeature *IVFKDataBlock::GetPreviousFeature()
     if (m_nFeatureCount < 0) {
         m_poReader->ReadDataRecords(this);
     }
-    
+
     if (m_bGeometryPerBlock && !m_bGeometry) {
        LoadGeometry();
     }
 
     if (m_iNextFeature < 0)
         ResetReading();
-    
+
     if (m_iNextFeature < 0 || m_iNextFeature >= m_nFeatureCount)
         return NULL;
-    
+
     return m_papoFeature[m_iNextFeature--];
 }
 
@@ -292,14 +286,14 @@ IVFKFeature *IVFKDataBlock::GetFirstFeature()
     if (m_nFeatureCount < 0) {
         m_poReader->ReadDataRecords(this);
     }
-        
+
     if (m_bGeometryPerBlock && !m_bGeometry) {
         LoadGeometry();
     }
-    
+
     if (m_nFeatureCount < 1)
         return NULL;
-    
+
     return m_papoFeature[0];
 }
 
@@ -313,14 +307,14 @@ IVFKFeature *IVFKDataBlock::GetLastFeature()
     if (m_nFeatureCount < 0) {
         m_poReader->ReadDataRecords(this);
     }
-    
+
     if (m_bGeometryPerBlock && !m_bGeometry) {
         LoadGeometry();
     }
-    
+
     if (m_nFeatureCount < 1)
         return NULL;
-    
+
     return m_papoFeature[m_nFeatureCount-1];
 }
 
@@ -336,7 +330,7 @@ int IVFKDataBlock::GetPropertyIndex(const char *pszName) const
     for (int i = 0; i < m_nPropertyCount; i++)
         if (EQUAL(pszName,m_papoProperty[i]->GetName()))
             return i;
-    
+
     return -1;
 }
 
@@ -348,7 +342,7 @@ int IVFKDataBlock::GetPropertyIndex(const char *pszName) const
 OGRwkbGeometryType IVFKDataBlock::SetGeometryType()
 {
     m_nGeometryType = wkbNone; /* pure attribute records */
-    
+
     if (EQUAL (m_pszName, "SOBR") ||
         EQUAL (m_pszName, "OBBP") ||
         EQUAL (m_pszName, "SPOL") ||
@@ -356,16 +350,16 @@ OGRwkbGeometryType IVFKDataBlock::SetGeometryType()
         EQUAL (m_pszName, "OP") ||
         EQUAL (m_pszName, "OBPEJ"))
         m_nGeometryType = wkbPoint;
-    
+
     else if (EQUAL (m_pszName, "SBP") ||
              EQUAL (m_pszName, "HP") ||
              EQUAL (m_pszName, "DPM"))
         m_nGeometryType = wkbLineString;
-    
+
     else if (EQUAL (m_pszName, "PAR") ||
              EQUAL (m_pszName, "BUD"))
         m_nGeometryType = wkbPolygon;
-    
+
     return m_nGeometryType;
 }
 
@@ -398,7 +392,7 @@ IVFKFeature *IVFKDataBlock::GetFeatureByIndex(int iIndex) const
   \brief Get feature by FID
 
   Modifies next feature id.
-  
+
   \param nFID feature id
 
   \return pointer to feature definition or NULL on failure (not found)
@@ -408,14 +402,14 @@ IVFKFeature *IVFKDataBlock::GetFeature(GIntBig nFID)
     if (m_nFeatureCount < 0) {
         m_poReader->ReadDataRecords(this);
     }
-    
+
     if (nFID < 1 || nFID > m_nFeatureCount)
         return NULL;
 
     if (m_bGeometryPerBlock && !m_bGeometry) {
         LoadGeometry();
     }
-    
+
     return GetFeatureByIndex(int (nFID) - 1); /* zero-based index */
 }
 
@@ -428,18 +422,14 @@ IVFKFeature *IVFKDataBlock::GetFeature(GIntBig nFID)
 */
 int IVFKDataBlock::LoadGeometry()
 {
-    int           nInvalid;
-#ifdef DEBUG_TIMING
-    clock_t       start, end;
-#endif
-
     if (m_bGeometry)
         return 0;
 
-    nInvalid    = 0;
+    int nInvalid = 0;
     m_bGeometry = TRUE;
+
 #ifdef DEBUG_TIMING
-    start       = clock();
+    const clock_t start       = clock();
 #endif
 
     if (m_nFeatureCount < 0) {
@@ -471,11 +461,11 @@ int IVFKDataBlock::LoadGeometry()
     }
 
 #ifdef DEBUG_TIMING
-    end = clock();
+    const clock_t end = clock();
 #endif
 
     if (nInvalid > 0) {
-        CPLError(CE_Warning, CPLE_AppDefined, 
+        CPLError(CE_Warning, CPLE_AppDefined,
                  "%s: %d features with invalid or empty geometry", m_pszName, nInvalid);
     }
 
@@ -491,7 +481,7 @@ int IVFKDataBlock::LoadGeometry()
   \brief Add linestring to a ring (private)
 
   \param[in,out] papoRing list of rings
-  \param poLine pointer to linestring to be added to a ring 
+  \param poLine pointer to linestring to be added to a ring
   \param bNewRing  create new ring
   \param bBackword allow backward direction
 
@@ -500,9 +490,6 @@ int IVFKDataBlock::LoadGeometry()
 bool IVFKDataBlock::AppendLineToRing(PointListArray *papoRing, const OGRLineString *poLine,
                                      bool bNewRing, bool bBackward)
 {
-    OGRPoint *poFirst, *poLast;
-    OGRPoint *poFirstNew, *poLastNew;
-
     OGRPoint  pt;
     PointList poList;
 
@@ -517,9 +504,12 @@ bool IVFKDataBlock::AppendLineToRing(PointListArray *papoRing, const OGRLineStri
         papoRing->push_back(new PointList(poList));
         return TRUE;
     }
-    
-    poFirstNew = &(poList.front());
-    poLastNew  = &(poList.back());
+
+    OGRPoint *poFirstNew = &(poList.front());
+    OGRPoint *poLastNew  = &(poList.back());
+
+    OGRPoint *poFirst, *poLast;
+
     for (PointListArray::const_iterator i = papoRing->begin(), e = papoRing->end();
          i != e; ++i) {
         PointList *ring = (*i);
@@ -533,19 +523,19 @@ bool IVFKDataBlock::AppendLineToRing(PointListArray *papoRing, const OGRLineStri
             ring->insert(ring->end(), poList.begin()+1, poList.end());
             return TRUE;
         }
-        
+
         if (bBackward && poFirstNew->Equals(poFirst)) {
             /* backward, skip last point */
             ring->insert(ring->begin(), poList.rbegin(), poList.rend()-1);
             return TRUE;
         }
-        
+
         if (poLastNew->Equals(poLast)) {
             /* backward, skip first point */
             ring->insert(ring->end(), poList.rbegin()+1, poList.rend());
             return TRUE;
         }
-        
+
         if (bBackward && poLastNew->Equals(poFirst)) {
             /* forward, skip last point */
             ring->insert(ring->begin(), poList.begin(), poList.end()-1);
@@ -583,7 +573,7 @@ int IVFKDataBlock::SetNextFeature(const IVFKFeature *poFeature)
 void IVFKDataBlock::AddFeature(IVFKFeature *poNewFeature)
 {
     m_nFeatureCount++;
-    
+
     m_papoFeature = (IVFKFeature **)
         CPLRealloc(m_papoFeature, sizeof (IVFKFeature *) * m_nFeatureCount);
     m_papoFeature[m_nFeatureCount-1] = poNewFeature;
@@ -613,9 +603,9 @@ void IVFKDataBlock::SetIncRecordCount(RecordType iRec)
 
 /*!
   \brief Get first found feature based on it's properties
-  
+
   Note: modifies next feature.
-  
+
   \param idx property index
   \param value property value
   \param poList list of features (NULL to loop all features)
@@ -648,16 +638,16 @@ VFKFeature *VFKDataBlock::GetFeature(int idx, GUIntBig value, VFKFeatureList *po
             }
         }
     }
-    
+
     return NULL;
 }
 
 /*!
   \brief Get features based on properties
-  
+
   \param idx property index
   \param value property value
-  
+
   \return list of features
 */
 VFKFeatureList VFKDataBlock::GetFeatures(int idx, GUIntBig value)
@@ -673,17 +663,17 @@ VFKFeatureList VFKDataBlock::GetFeatures(int idx, GUIntBig value)
             poResult.push_back(poVfkFeature);
         }
     }
-    
+
     return poResult;
 }
 
 /*!
   \brief Get features based on properties
-  
+
   \param idx1 property index
   \param idx2 property index
   \param value property value
-  
+
   \return list of features
 */
 VFKFeatureList VFKDataBlock::GetFeatures(int idx1, int idx2, GUIntBig value)
@@ -691,7 +681,7 @@ VFKFeatureList VFKDataBlock::GetFeatures(int idx1, int idx2, GUIntBig value)
     GUIntBig    iPropertyValue1, iPropertyValue2;
     VFKFeature *poVfkFeature;
     std::vector<VFKFeature *> poResult;
-    
+
     for (int i = 0; i < m_nFeatureCount; i++) {
         poVfkFeature = (VFKFeature *) GetFeatureByIndex(i);
         iPropertyValue1 = strtoul(poVfkFeature->GetProperty(idx1)->GetValueS(), NULL, 0);
@@ -707,7 +697,7 @@ VFKFeatureList VFKDataBlock::GetFeatures(int idx1, int idx2, GUIntBig value)
             }
         }
     }
-    
+
     return poResult;
 }
 
@@ -721,14 +711,12 @@ VFKFeatureList VFKDataBlock::GetFeatures(int idx1, int idx2, GUIntBig value)
 */
 GIntBig VFKDataBlock::GetFeatureCount(const char *pszName, const char *pszValue)
 {
-    int nfeatures, propIdx;
-    VFKFeature *poVFKFeature;
-
-    propIdx = GetPropertyIndex(pszName);
+    int propIdx = GetPropertyIndex(pszName);
     if (propIdx < 0)
         return -1;
-    
-    nfeatures = 0;
+
+    int nfeatures = 0;
+    VFKFeature *poVFKFeature;
     for (int i = 0; i < ((IVFKDataBlock *) this)->GetFeatureCount(); i++) {
         poVFKFeature = (VFKFeature *) ((IVFKDataBlock *) this)->GetFeature(i);
         if (!poVFKFeature)
@@ -747,31 +735,24 @@ GIntBig VFKDataBlock::GetFeatureCount(const char *pszName, const char *pszValue)
 */
 int VFKDataBlock::LoadGeometryPoint()
 {
-    /* -> wkbPoint */
-    long   nInvalid;
-    double x, y;
-    int    i_idxX, i_idxY;
-    
-    VFKFeature *poFeature;
-    
-    nInvalid = 0;
-    i_idxY = GetPropertyIndex("SOURADNICE_Y");
-    i_idxX = GetPropertyIndex("SOURADNICE_X");
+    int nInvalid = 0;
+    int i_idxY = GetPropertyIndex("SOURADNICE_Y");
+    int i_idxX = GetPropertyIndex("SOURADNICE_X");
     if (i_idxY < 0 || i_idxX < 0) {
-        CPLError(CE_Failure, CPLE_NotSupported, 
+        CPLError(CE_Failure, CPLE_NotSupported,
                  "Corrupted data (%s).\n", m_pszName);
         return nInvalid;
     }
-    
+
     for (int j = 0; j < ((IVFKDataBlock *) this)->GetFeatureCount(); j++) {
-        poFeature = (VFKFeature *) GetFeatureByIndex(j);
-        x = -1.0 * poFeature->GetProperty(i_idxY)->GetValueD();
-        y = -1.0 * poFeature->GetProperty(i_idxX)->GetValueD();
+        VFKFeature *poFeature = (VFKFeature *) GetFeatureByIndex(j);
+        double x = -1.0 * poFeature->GetProperty(i_idxY)->GetValueD();
+        double y = -1.0 * poFeature->GetProperty(i_idxX)->GetValueD();
         OGRPoint pt(x, y);
         if (!poFeature->SetGeometry(&pt))
             nInvalid++;
     }
-    
+
     return nInvalid;
 }
 
@@ -782,46 +763,38 @@ int VFKDataBlock::LoadGeometryPoint()
 */
 int VFKDataBlock::LoadGeometryLineStringSBP()
 {
-    int      idxId, idxBp_Id, idxPCB;
-    GUIntBig id, ipcb;
-    int      nInvalid;
-    
-    VFKDataBlock *poDataBlockPoints;
-    VFKFeature   *poFeature, *poPoint, *poLine;
-    
-    OGRLineString oOGRLine;
-    
-    nInvalid  = 0;
-    poLine    = NULL;
-    
-    poDataBlockPoints = (VFKDataBlock *) m_poReader->GetDataBlock("SOBR");
+    VFKDataBlock *poDataBlockPoints = (VFKDataBlock *) m_poReader->GetDataBlock("SOBR");
     if (NULL == poDataBlockPoints) {
-        CPLError(CE_Failure, CPLE_NotSupported, 
+        CPLError(CE_Failure, CPLE_NotSupported,
                  "Data block %s not found.\n", m_pszName);
-        return nInvalid;
+        return 0;
     }
-    
+
     poDataBlockPoints->LoadGeometry();
-    idxId    = poDataBlockPoints->GetPropertyIndex("ID");
-    idxBp_Id = GetPropertyIndex("BP_ID");
-    idxPCB   = GetPropertyIndex("PORADOVE_CISLO_BODU");
+    int idxId    = poDataBlockPoints->GetPropertyIndex("ID");
+    int idxBp_Id = GetPropertyIndex("BP_ID");
+    int idxPCB   = GetPropertyIndex("PORADOVE_CISLO_BODU");
     if (idxId < 0 || idxBp_Id < 0 || idxPCB < 0) {
-        CPLError(CE_Failure, CPLE_NotSupported, 
+        CPLError(CE_Failure, CPLE_NotSupported,
                  "Corrupted data (%s).\n", m_pszName);
-        return nInvalid;
+        return 0;
     }
-    
+
+    OGRLineString oOGRLine;
+    VFKFeature   *poLine = NULL;
+    int nInvalid = 0;
+
     for (int j = 0; j < ((IVFKDataBlock *) this)->GetFeatureCount(); j++) {
-        poFeature = (VFKFeature *) GetFeatureByIndex(j);
+        VFKFeature *poFeature = (VFKFeature *) GetFeatureByIndex(j);
         CPLAssert(NULL != poFeature);
-        
+
         poFeature->SetGeometry(NULL);
-        id   = strtoul(poFeature->GetProperty(idxBp_Id)->GetValueS(), NULL, 0);
-        ipcb = strtoul(poFeature->GetProperty(idxPCB)->GetValueS(), NULL, 0);
+        GUIntBig id   = strtoul(poFeature->GetProperty(idxBp_Id)->GetValueS(), NULL, 0);
+        GUIntBig ipcb = strtoul(poFeature->GetProperty(idxPCB)->GetValueS(), NULL, 0);
         if (ipcb == 1) {
             if (!oOGRLine.IsEmpty()) {
                 oOGRLine.setCoordinateDimension(2); /* force 2D */
-                if (!poLine->SetGeometry(&oOGRLine))
+                if (poLine != NULL && !poLine->SetGeometry(&oOGRLine))
                     nInvalid++;
                 oOGRLine.empty(); /* restore line */
             }
@@ -830,7 +803,7 @@ int VFKDataBlock::LoadGeometryLineStringSBP()
         else {
             poFeature->SetGeometryType(wkbUnknown);
         }
-        poPoint = poDataBlockPoints->GetFeature(idxId, id);
+        VFKFeature *poPoint = poDataBlockPoints->GetFeature(idxId, id);
         if (!poPoint)
             continue;
         OGRPoint *pt = (OGRPoint *) poPoint->GetGeometry();
@@ -854,42 +827,38 @@ int VFKDataBlock::LoadGeometryLineStringSBP()
 */
 int VFKDataBlock::LoadGeometryLineStringHP()
 {
-    long          nInvalid;
-    int           idxId, idxMy_Id, idxPCB;
-    GUIntBig      id;
-    
-    VFKDataBlock  *poDataBlockLines;
-    VFKFeature    *poFeature, *poLine;
-    VFKFeatureList poLineList;
-    
-    nInvalid = 0;
-    
-    poDataBlockLines = (VFKDataBlock *) m_poReader->GetDataBlock("SBP");
+    int nInvalid = 0;
+
+    VFKDataBlock  *poDataBlockLines
+        = (VFKDataBlock *) m_poReader->GetDataBlock("SBP");
     if (NULL == poDataBlockLines) {
-        CPLError(CE_Failure, CPLE_NotSupported, 
+        CPLError(CE_Failure, CPLE_NotSupported,
                  "Data block %s not found.\n", m_pszName);
         return nInvalid;
     }
-    
+
     poDataBlockLines->LoadGeometry();
-    idxId    = GetPropertyIndex("ID");
+    int idxId = GetPropertyIndex("ID");
+    int idxMy_Id;
     if (EQUAL (m_pszName, "HP"))
         idxMy_Id = poDataBlockLines->GetPropertyIndex("HP_ID");
     else
         idxMy_Id = poDataBlockLines->GetPropertyIndex("DPM_ID");
-    idxPCB   = poDataBlockLines->GetPropertyIndex("PORADOVE_CISLO_BODU");
+    int idxPCB   = poDataBlockLines->GetPropertyIndex("PORADOVE_CISLO_BODU");
     if (idxId < 0 || idxMy_Id < 0 || idxPCB < 0) {
-        CPLError(CE_Failure, CPLE_NotSupported, 
+        CPLError(CE_Failure, CPLE_NotSupported,
                  "Corrupted data (%s).\n", m_pszName);
         return nInvalid;
     }
-    
-    poLineList = poDataBlockLines->GetFeatures(idxPCB, 1); /* reduce to first segment */
+
+    VFKFeatureList poLineList
+        = poDataBlockLines->GetFeatures(idxPCB, 1); // reduce to first segment
     for (int i = 0; i < ((IVFKDataBlock *) this)->GetFeatureCount(); i++) {
-        poFeature = (VFKFeature *) GetFeatureByIndex(i);
+        VFKFeature *poFeature = (VFKFeature *) GetFeatureByIndex(i);
         CPLAssert(NULL != poFeature);
-        id = strtoul(poFeature->GetProperty(idxId)->GetValueS(), NULL, 0);
-        poLine = poDataBlockLines->GetFeature(idxMy_Id, id, &poLineList);
+        GUIntBig id = strtoul(poFeature->GetProperty(idxId)->GetValueS(), NULL, 0);
+        VFKFeature *poLine
+            = poDataBlockLines->GetFeature(idxMy_Id, id, &poLineList);
         if (!poLine || !poLine->GetGeometry())
             continue;
         if (!poFeature->SetGeometry(poLine->GetGeometry()))
@@ -907,24 +876,17 @@ int VFKDataBlock::LoadGeometryLineStringHP()
 */
 int VFKDataBlock::LoadGeometryPolygon()
 {
-    long nInvalid;
-    bool bIsPar, bNewRing, bFound;
-        
-    GUIntBig id, idOb;
-    int  nCount, nCountMax;
-    int idxId, idxPar1, idxPar2, idxBud, idxOb, idxIdOb;
-    
+    int nInvalid = 0;
+
+    GUIntBig id;
+    int idxBud = 0;
+    int idxOb = 0;
+    int idxIdOb = 0;
+
     VFKFeature   *poFeature;
     VFKDataBlock *poDataBlockLines1, *poDataBlockLines2;
-    
-    VFKFeatureList   poLineList;
-    PointListArray   poRingList; /* first is to be considered as exterior */
-    
-    OGRLinearRing ogrRing;
-    OGRPolygon    ogrPolygon;
-    
-    idxPar1 = idxPar2 = idxBud = idxOb = idxIdOb = 0;
-    nInvalid = 0;
+
+    bool bIsPar;
     if (EQUAL (m_pszName, "PAR")) {
         poDataBlockLines1 = (VFKDataBlock *) m_poReader->GetDataBlock("HP");
         poDataBlockLines2 = poDataBlockLines1;
@@ -936,25 +898,27 @@ int VFKDataBlock::LoadGeometryPolygon()
         bIsPar = FALSE;
     }
     if (NULL == poDataBlockLines1 || NULL == poDataBlockLines2) {
-        CPLError(CE_Failure, CPLE_NotSupported, 
+        CPLError(CE_Failure, CPLE_NotSupported,
                  "Data block %s not found.\n", m_pszName);
         return nInvalid;
     }
-    
+
     poDataBlockLines1->LoadGeometry();
     poDataBlockLines2->LoadGeometry();
-    idxId = GetPropertyIndex("ID");
+    int idxId = GetPropertyIndex("ID");
     if (idxId < 0) {
-        CPLError(CE_Failure, CPLE_NotSupported, 
+        CPLError(CE_Failure, CPLE_NotSupported,
                  "Corrupted data (%s).\n", m_pszName);
         return nInvalid;
     }
-    
+
+    int idxPar1 = 0;
+    int idxPar2 = 0;
     if (bIsPar) {
         idxPar1 = poDataBlockLines1->GetPropertyIndex("PAR_ID_1");
         idxPar2 = poDataBlockLines1->GetPropertyIndex("PAR_ID_2");
         if (idxPar1 < 0 || idxPar2 < 0) {
-            CPLError(CE_Failure, CPLE_NotSupported, 
+            CPLError(CE_Failure, CPLE_NotSupported,
                      "Corrupted data (%s).\n", m_pszName);
             return nInvalid;
         }
@@ -964,12 +928,17 @@ int VFKDataBlock::LoadGeometryPolygon()
         idxBud = poDataBlockLines1->GetPropertyIndex("BUD_ID");
         idxOb  = poDataBlockLines2->GetPropertyIndex("OB_ID");
         if (idxIdOb < 0 || idxBud < 0 || idxOb < 0) {
-            CPLError(CE_Failure, CPLE_NotSupported, 
+            CPLError(CE_Failure, CPLE_NotSupported,
                      "Corrupted data (%s).\n", m_pszName);
             return nInvalid;
         }
     }
-    
+
+    VFKFeatureList poLineList;
+    PointListArray poRingList; /* first is to be considered as exterior */
+    OGRLinearRing ogrRing;
+    OGRPolygon ogrPolygon;
+
     for (int i = 0; i < ((IVFKDataBlock *) this)->GetFeatureCount(); i++) {
         poFeature = (VFKFeature *) GetFeatureByIndex(i);
         CPLAssert(NULL != poFeature);
@@ -984,7 +953,7 @@ int VFKDataBlock::LoadGeometryPolygon()
             for (std::vector<VFKFeature *>::const_iterator iOb = poLineListOb.begin(), eOb = poLineListOb.end();
                  iOb != eOb; ++iOb) {
                 poLineOb = (*iOb);
-                idOb = strtoul(poLineOb->GetProperty(idxIdOb)->GetValueS(), NULL, 0);
+                GUIntBig idOb = strtoul(poLineOb->GetProperty(idxIdOb)->GetValueS(), NULL, 0);
                 poLineSbp = poDataBlockLines2->GetFeature(idxOb, idOb);
                 if (poLineSbp)
                     poLineList.push_back(poLineSbp);
@@ -992,18 +961,18 @@ int VFKDataBlock::LoadGeometryPolygon()
         }
         if (poLineList.size() < 1)
             continue;
-        
+
         /* clear */
         ogrPolygon.empty();
         poRingList.clear();
-        
+
         /* collect rings (points) */
-        bFound = FALSE;
-        nCount = 0;
-        nCountMax = poLineList.size() * 2;
+        bool bFound = false;
+        int nCount = 0;
+        int nCountMax = static_cast<int>(poLineList.size()) * 2;
         while (poLineList.size() > 0 && nCount < nCountMax) {
-            bNewRing = !bFound ? TRUE : FALSE;
-            bFound = FALSE;
+            bool bNewRing = !bFound;
+            bFound = false;
             for (VFKFeatureList::iterator iHp = poLineList.begin(), eHp = poLineList.end();
                  iHp != eHp; ++iHp) {
                 const OGRLineString *pLine = (OGRLineString *) (*iHp)->GetGeometry();
@@ -1031,7 +1000,7 @@ int VFKDataBlock::LoadGeometryPolygon()
         if (!poFeature->SetGeometry(&ogrPolygon))
             nInvalid++;
     }
-    
+
     /* free ring list */
     for (PointListArray::iterator iRing = poRingList.begin(),
              eRing = poRingList.end(); iRing != eRing; ++iRing) {
diff --git a/ogr/ogrsf_frmts/vfk/vfkdatablocksqlite.cpp b/ogr/ogrsf_frmts/vfk/vfkdatablocksqlite.cpp
index 3c073ac..fd24c6c 100644
--- a/ogr/ogrsf_frmts/vfk/vfkdatablocksqlite.cpp
+++ b/ogr/ogrsf_frmts/vfk/vfkdatablocksqlite.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vfkdatablocksqlite.cpp 28382 2015-01-30 15:29:41Z rouault $
+ * $Id: vfkdatablocksqlite.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  VFK Reader - Data block definition (SQLite)
  * Purpose:  Implements VFKDataBlockSQLite
@@ -75,7 +75,7 @@ int VFKDataBlockSQLite::LoadGeometryPoint()
         x = -1.0 * sqlite3_column_double(hStmt, 0); /* S-JTSK coordinate system expected */
         y = -1.0 * sqlite3_column_double(hStmt, 1);
 #ifdef DEBUG
-	const long iFID = sqlite3_column_double(hStmt, 2);
+	const GIntBig iFID = sqlite3_column_int64(hStmt, 2);
 #endif
 	rowId = sqlite3_column_int(hStmt, 3);
 
@@ -94,13 +94,13 @@ int VFKDataBlockSQLite::LoadGeometryPoint()
 	    SaveGeometryToDB(&pt, rowId) != OGRERR_FAILURE)
 	    nGeometries++;
     }
-    
+
     /* update number of geometries in VFK_DB_TABLE table */
     UpdateVfkBlocks(nGeometries);
 
     if (poReader->IsSpatial())
 	poReader->ExecuteSQL("COMMIT");
-    
+
     return bSkipInvalid ? 0 : nInvalid;
 }
 
@@ -127,7 +127,7 @@ bool VFKDataBlockSQLite::SetGeometryLineString(VFKFeatureSQLite *poLine, OGRLine
     /* check also VFK validity */
     if (bValid) {
         /* Feature types
-           
+
            - '3'    - line       (2 points)
            - '4'    - linestring (at least 2 points)
            - '11'   - curve      (at least 2 points)
@@ -143,31 +143,31 @@ bool VFKDataBlockSQLite::SetGeometryLineString(VFKFeatureSQLite *poLine, OGRLine
 
                bValid = FALSE;
             */
-            CPLDebug("OGR-VFK", 
+            CPLDebug("OGR-VFK",
                      "Line (fid=" CPL_FRMT_GIB ") defined by more than two vertices",
                      poLine->GetFID());
         }
-        else if (EQUAL(ftype, "11") && npoints < 2) { 
+        else if (EQUAL(ftype, "11") && npoints < 2) {
             bValid = FALSE;
-            CPLError(CE_Warning, CPLE_AppDefined, 
+            CPLError(CE_Warning, CPLE_AppDefined,
                      "Curve (fid=" CPL_FRMT_GIB ") defined by less than two vertices",
                      poLine->GetFID());
         }
         else if (EQUAL(ftype, "15") && npoints != 3) {
             bValid = FALSE;
-            CPLError(CE_Warning, CPLE_AppDefined, 
+            CPLError(CE_Warning, CPLE_AppDefined,
                      "Circle (fid=" CPL_FRMT_GIB ") defined by invalid number of vertices (%d)",
                      poLine->GetFID(), oOGRLine->getNumPoints());
         }
-        else if (strlen(ftype) > 2 && EQUALN(ftype, "15", 2) && npoints != 1) {
+        else if (strlen(ftype) > 2 && STARTS_WITH_CI(ftype, "15") && npoints != 1) {
             bValid = FALSE;
-            CPLError(CE_Warning, CPLE_AppDefined, 
+            CPLError(CE_Warning, CPLE_AppDefined,
                      "Circle (fid=" CPL_FRMT_GIB ") defined by invalid number of vertices (%d)",
                      poLine->GetFID(), oOGRLine->getNumPoints());
         }
         else if (EQUAL(ftype, "16") && npoints != 3) {
             bValid = FALSE;
-            CPLError(CE_Warning, CPLE_AppDefined, 
+            CPLError(CE_Warning, CPLE_AppDefined,
                      "Arc (fid=" CPL_FRMT_GIB ") defined by invalid number of vertices (%d)",
                      poLine->GetFID(), oOGRLine->getNumPoints());
         }
@@ -182,10 +182,10 @@ bool VFKDataBlockSQLite::SetGeometryLineString(VFKFeatureSQLite *poLine, OGRLine
     else {
         poLine->SetGeometry(NULL);
     }
-    
+
     /* update fid column */
-    UpdateFID(poLine->GetFID(), rowIdFeat);        
-    
+    UpdateFID(poLine->GetFID(), rowIdFeat);
+
     /* store also geometry in DB */
     CPLAssert(0 != rowIdFeat.size());
     if (bValid && poReader->IsSpatial() &&
@@ -208,31 +208,31 @@ int VFKDataBlockSQLite::LoadGeometryLineStringSBP()
 {
     int       nInvalid, nGeometries, rowId, iIdx;
     CPLString szFType, szFTypeLine;
-    
+
     GUIntBig id, ipcb;
     bool     bValid;
-    
+
     std::vector<int> rowIdFeat;
     CPLString     osSQL;
     sqlite3_stmt *hStmt;
-    
+
     VFKReaderSQLite    *poReader;
     VFKDataBlockSQLite *poDataBlockPoints;
     VFKFeatureSQLite   *poFeature, *poPoint, *poLine;
-    
+
     OGRLineString oOGRLine;
-    
+
     nInvalid  = nGeometries = 0;
     poReader  = (VFKReaderSQLite*) m_poReader;
     poLine    = NULL;
-    
+
     poDataBlockPoints = (VFKDataBlockSQLite *) m_poReader->GetDataBlock("SOBR");
     if (NULL == poDataBlockPoints) {
-        CPLError(CE_Failure, CPLE_FileIO, 
+        CPLError(CE_Failure, CPLE_FileIO,
                  "Data block %s not found.\n", m_pszName);
         return nInvalid;
     }
-    
+
     poDataBlockPoints->LoadGeometry();
 
     if (LoadGeometryFromDB()) /* try to load geometry from DB */
@@ -253,36 +253,40 @@ int VFKDataBlockSQLite::LoadGeometryLineStringSBP()
             osSQL.Printf("SELECT BP_ID,PORADOVE_CISLO_BODU,PARAMETRY_SPOJENI,_rowid_ FROM '%s' WHERE "
                          "OB_ID IS NULL AND HP_ID IS NULL AND DPM_ID IS NULL "
                          "ORDER BY ID,PORADOVE_CISLO_BODU", m_pszName);
-	
+
         hStmt = poReader->PrepareStatement(osSQL.c_str());
-    
+
 	if (poReader->IsSpatial())
 	    poReader->ExecuteSQL("BEGIN");
-	
+
         while(poReader->ExecuteSQL(hStmt) == OGRERR_NONE) {
             // read values
-            id    = sqlite3_column_double(hStmt, 0);
-            ipcb  = sqlite3_column_double(hStmt, 1);
+            id    = sqlite3_column_int64(hStmt, 0);
+            ipcb  = sqlite3_column_int64(hStmt, 1);
             szFType = (char *) sqlite3_column_text(hStmt, 2);
             rowId = sqlite3_column_int(hStmt, 3);
 
             if (ipcb == 1) {
                 poFeature = (VFKFeatureSQLite *) GetFeatureByIndex(iIdx);
-                CPLAssert(NULL != poFeature);
+                if( poFeature == NULL )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined, "Cannot retrieve feature %d", iIdx);
+                    break;
+                }
                 poFeature->SetRowId(rowId);
-                
+
                 /* set geometry & reset */
                 if (poLine && !SetGeometryLineString(poLine, &oOGRLine,
                                                      bValid, szFTypeLine, rowIdFeat, nGeometries)) {
                     nInvalid++;
                 }
-                
+
 		bValid = TRUE;
                 poLine = poFeature;
                 szFTypeLine = szFType;
                 iIdx++;
             }
-            
+
             poPoint = (VFKFeatureSQLite *) poDataBlockPoints->GetFeature("ID", id);
 	    if (poPoint) {
 		OGRPoint *pt = (OGRPoint *) poPoint->GetGeometry();
@@ -290,18 +294,18 @@ int VFKDataBlockSQLite::LoadGeometryLineStringSBP()
 		    oOGRLine.addPoint(pt);
 		}
 		else {
-		    CPLDebug("OGR-VFK", 
+		    CPLDebug("OGR-VFK",
 			     "Geometry (point ID = " CPL_FRMT_GUIB ") not valid", id);
 		    bValid = FALSE;
 		}
 	    }
 	    else {
-                CPLDebug("OGR-VFK", 
+                CPLDebug("OGR-VFK",
                          "Point ID = " CPL_FRMT_GUIB " not found (rowid = %d)",
                          id, rowId);
 		bValid = FALSE;
             }
-	    
+
 	    /* add vertex to the linestring */
 	    rowIdFeat.push_back(rowId);
         }
@@ -319,7 +323,7 @@ int VFKDataBlockSQLite::LoadGeometryLineStringSBP()
 
     /* update number of geometries in VFK_DB_TABLE table */
     UpdateVfkBlocks(nGeometries);
-    
+
     return nInvalid;
 }
 
@@ -333,51 +337,51 @@ int VFKDataBlockSQLite::LoadGeometryLineStringHP()
     int          nInvalid, nGeometries;
     int          rowId;
     long         iFID;
-    
+
     CPLString    osColumn, osSQL;
     const char  *vrColumn[2];
     GUIntBig     vrValue[2];
-    
+
     sqlite3_stmt *hStmt;
-    
+
     OGRGeometry        *poOgrGeometry;
     VFKReaderSQLite    *poReader;
     VFKDataBlockSQLite *poDataBlockLines;
     VFKFeatureSQLite   *poFeature, *poLine;
-    
+
     nInvalid = nGeometries = 0;
     poReader  = (VFKReaderSQLite*) m_poReader;
-    
+
     poDataBlockLines = (VFKDataBlockSQLite *) m_poReader->GetDataBlock("SBP");
     if (NULL == poDataBlockLines) {
-        CPLError(CE_Failure, CPLE_FileIO, 
+        CPLError(CE_Failure, CPLE_FileIO,
                  "Data block %s not found", m_pszName);
         return nInvalid;
     }
-    
+
     poDataBlockLines->LoadGeometry();
 
     if (LoadGeometryFromDB()) /* try to load geometry from DB */
 	return 0;
-    
+
     osColumn.Printf("%s_ID", m_pszName);
     vrColumn[0] = osColumn.c_str();
     vrColumn[1] = "PORADOVE_CISLO_BODU";
     vrValue[1]  = 1; /* reduce to first segment */
-    
+
     osSQL.Printf("SELECT ID,%s,rowid FROM %s", FID_COLUMN, m_pszName);
     /* TODO: handle points in DPM */
     if (EQUAL(m_pszName, "DPM"))
         osSQL += " WHERE SOURADNICE_X IS NULL";
     hStmt = poReader->PrepareStatement(osSQL.c_str());
-    
+
     if (poReader->IsSpatial())
 	poReader->ExecuteSQL("BEGIN");
 
     while(poReader->ExecuteSQL(hStmt) == OGRERR_NONE) {
         /* read values */
-        vrValue[0] = sqlite3_column_double(hStmt, 0);
-        iFID       = sqlite3_column_double(hStmt, 1);
+        vrValue[0] = sqlite3_column_int64(hStmt, 0);
+        iFID       = static_cast<long>(sqlite3_column_int64(hStmt, 1));
         rowId      = sqlite3_column_int(hStmt, 2);
 
         poFeature = (VFKFeatureSQLite *) GetFeatureByIndex(rowId - 1);
@@ -397,17 +401,17 @@ int VFKDataBlockSQLite::LoadGeometryLineStringHP()
 	    nInvalid++;
             continue;
         }
-	
+
 	/* store also geometry in DB */
 	if (poReader->IsSpatial() &&
 	    SaveGeometryToDB(poOgrGeometry, rowId) != OGRERR_FAILURE &&
 	    poOgrGeometry)
 	    nGeometries++;
     }
-    
+
     /* update number of geometries in VFK_DB_TABLE table */
     UpdateVfkBlocks(nGeometries);
-    
+
     if (poReader->IsSpatial())
 	poReader->ExecuteSQL("COMMIT");
 
@@ -426,14 +430,14 @@ int VFKDataBlockSQLite::LoadGeometryPolygon()
     size_t nLines;
     long iFID;
     bool bIsPar, bNewRing, bFound;
-        
+
     CPLString    osSQL;
     const char  *vrColumn[2];
     GUIntBig     vrValue[2];
     GUIntBig     id, idOb;
-    
+
     sqlite3_stmt *hStmt;
-    
+
     VFKReaderSQLite    *poReader;
     VFKDataBlockSQLite *poDataBlockLines1, *poDataBlockLines2;
     VFKFeatureSQLite   *poFeature;
@@ -441,14 +445,14 @@ int VFKDataBlockSQLite::LoadGeometryPolygon()
     VFKFeatureSQLiteList  poLineList;
     /* first is to be considered as exterior */
     PointListArray        poRingList;
-    
+
     std::vector<OGRLinearRing *> poLinearRingList;
     OGRPolygon     ogrPolygon;
     OGRLinearRing *poOgrRing;
 
     nInvalidNoLines = nInvalidNoRings = nGeometries = 0;
     poReader  = (VFKReaderSQLite*) m_poReader;
-    
+
     if (EQUAL (m_pszName, "PAR")) {
         poDataBlockLines1 = (VFKDataBlockSQLite *) m_poReader->GetDataBlock("HP");
         poDataBlockLines2 = poDataBlockLines1;
@@ -460,17 +464,17 @@ int VFKDataBlockSQLite::LoadGeometryPolygon()
         bIsPar = FALSE;
     }
     if (NULL == poDataBlockLines1 || NULL == poDataBlockLines2) {
-        CPLError(CE_Failure, CPLE_FileIO, 
+        CPLError(CE_Failure, CPLE_FileIO,
                  "Data block %s not found", m_pszName);
         return -1;
     }
-    
+
     poDataBlockLines1->LoadGeometry();
     poDataBlockLines2->LoadGeometry();
-    
+
     if (LoadGeometryFromDB()) /* try to load geometry from DB */
 	return 0;
-    
+
     if (bIsPar) {
         vrColumn[0] = "PAR_ID_1";
         vrColumn[1] = "PAR_ID_2";
@@ -483,18 +487,18 @@ int VFKDataBlockSQLite::LoadGeometryPolygon()
 
     osSQL.Printf("SELECT ID,%s,rowid FROM %s", FID_COLUMN, m_pszName);
     hStmt = poReader->PrepareStatement(osSQL.c_str());
-    
+
     if (poReader->IsSpatial())
 	poReader->ExecuteSQL("BEGIN");
 
     while(poReader->ExecuteSQL(hStmt) == OGRERR_NONE) {
         nBridges = 0;
-        
+
         /* read values */
-        id        = sqlite3_column_double(hStmt, 0);
-        iFID      = sqlite3_column_double(hStmt, 1);
+        id        = sqlite3_column_int64(hStmt, 0);
+        iFID      = static_cast<long>(sqlite3_column_int64(hStmt, 1));
         rowId     = sqlite3_column_int(hStmt, 2);
-        
+
         poFeature = (VFKFeatureSQLite *) GetFeatureByIndex(rowId - 1);
         CPLAssert(NULL != poFeature && poFeature->GetFID() == iFID);
 
@@ -506,19 +510,19 @@ int VFKDataBlockSQLite::LoadGeometryPolygon()
             VFKFeatureSQLite *poLineSbp;
             std::vector<VFKFeatureSQLite *> poLineListOb;
             sqlite3_stmt *hStmtOb;
-            
+
             osSQL.Printf("SELECT ID FROM %s WHERE BUD_ID = " CPL_FRMT_GUIB,
                          poDataBlockLines1->GetName(), id);
             if (poReader->IsSpatial()) {
                 CPLString osColumn;
-                
+
                 osColumn.Printf(" AND %s IS NULL", GEOM_COLUMN);
                 osSQL += osColumn;
             }
             hStmtOb = poReader->PrepareStatement(osSQL.c_str());
-            
+
             while(poReader->ExecuteSQL(hStmtOb) == OGRERR_NONE) {
-                idOb = sqlite3_column_double(hStmtOb, 0); 
+                idOb = sqlite3_column_int64(hStmtOb, 0);
                 vrValue[0] = idOb;
                 poLineSbp = poDataBlockLines2->GetFeature(vrColumn, vrValue, 2);
                 if (poLineSbp)
@@ -527,21 +531,21 @@ int VFKDataBlockSQLite::LoadGeometryPolygon()
         }
         nLines = poLineList.size();
         if (nLines < 1) {
-            CPLDebug("OGR-VFK", 
+            CPLDebug("OGR-VFK",
                      "%s: unable to collect rings for polygon fid = %ld (no lines)",
                      m_pszName, iFID);
             nInvalidNoLines++;
             continue;
         }
-        
+
         /* clear */
         ogrPolygon.empty();
         poRingList.clear();
-        
+
         /* collect rings from lines */
         bFound = FALSE;
         nCount = 0;
-        nCountMax = nLines * 2;
+        nCountMax = static_cast<int>(nLines) * 2;
 	while (poLineList.size() > 0 && nCount < nCountMax) {
             bNewRing = !bFound ? TRUE : FALSE;
             bFound = FALSE;
@@ -561,7 +565,7 @@ int VFKDataBlockSQLite::LoadGeometryPolygon()
                  iFID, (int)nLines, (int)poRingList.size());
 
         if (poLineList.size() > 0) {
-            CPLDebug("OGR-VFK", 
+            CPLDebug("OGR-VFK",
                      "%s: unable to collect rings for polygon fid = %ld",
                      m_pszName, iFID);
             nInvalidNoRings++;
@@ -575,11 +579,11 @@ int VFKDataBlockSQLite::LoadGeometryPolygon()
              iRing != eRing; ++iRing) {
 	    OGRPoint *poPoint;
             PointList *poList = *iRing;
-	    
+
             poLinearRingList.push_back(new OGRLinearRing());
 	    poOgrRing = poLinearRingList.back();
 	    CPLAssert(NULL != poOgrRing);
-	    
+
             for (PointList::iterator iPoint = poList->begin(), ePoint = poList->end();
                  iPoint != ePoint; ++iPoint) {
 		poPoint = &(*iPoint);
@@ -592,7 +596,7 @@ int VFKDataBlockSQLite::LoadGeometryPolygon()
 	if (poLinearRingList.size() > 1) {
 	    double dArea, dMaxArea;
 	    std::vector<OGRLinearRing *>::iterator exteriorRing;
-	    
+
 	    exteriorRing = poLinearRingList.begin();
 	    dMaxArea = -1.;
 	    for (std::vector<OGRLinearRing *>::iterator iRing = poLinearRingList.begin(),
@@ -600,7 +604,7 @@ int VFKDataBlockSQLite::LoadGeometryPolygon()
 		poOgrRing = *iRing;
 		if (!IsRingClosed(poOgrRing))
 		    continue; /* skip unclosed rings */
-		
+
 		dArea = poOgrRing->get_Area();
 		if (dArea > dMaxArea) {
 		    dMaxArea = dArea;
@@ -611,12 +615,12 @@ int VFKDataBlockSQLite::LoadGeometryPolygon()
 		std::swap(*poLinearRingList.begin(), *exteriorRing);
 	    }
 	}
-	
+
 	/* build polygon from rings */
         for (std::vector<OGRLinearRing *>::iterator iRing = poLinearRingList.begin(),
 		 eRing = poLinearRingList.end(); iRing != eRing; ++iRing) {
 	    poOgrRing = *iRing;
-	    
+
 	    /* check if ring is closed */
 	    if (IsRingClosed(poOgrRing)) {
 		ogrPolygon.addRing(poOgrRing);
@@ -644,23 +648,23 @@ int VFKDataBlockSQLite::LoadGeometryPolygon()
             nInvalidNoRings++;
             continue;
         }
-	
+
         /* store also geometry in DB */
-        if (poReader->IsSpatial() && 
+        if (poReader->IsSpatial() &&
 	    SaveGeometryToDB(&ogrPolygon, rowId) != OGRERR_FAILURE)
             nGeometries++;
     }
-    
+
     /* free ring list */
     for (PointListArray::iterator iRing = poRingList.begin(), eRing = poRingList.end();
          iRing != eRing; ++iRing) {
         delete (*iRing);
         *iRing = NULL;
     }
-    
+
     CPLDebug("OGR-VFK", "%s: nolines = %d norings = %d",
              m_pszName, nInvalidNoLines, nInvalidNoRings);
-    
+
     /* update number of geometries in VFK_DB_TABLE table */
     UpdateVfkBlocks(nGeometries);
 
@@ -674,7 +678,7 @@ int VFKDataBlockSQLite::LoadGeometryPolygon()
   \brief Get feature by FID
 
   Modifies next feature id.
-  
+
   \param nFID feature id
 
   \return pointer to feature definition or NULL on failure (not found)
@@ -684,22 +688,22 @@ IVFKFeature *VFKDataBlockSQLite::GetFeature(GIntBig nFID)
     int rowId;
     CPLString osSQL;
     VFKReaderSQLite  *poReader;
-    
+
     sqlite3_stmt *hStmt;
-         
+
     if (m_nFeatureCount < 0) {
         m_poReader->ReadDataRecords(this);
     }
-    
+
     if (nFID < 1 || nFID > m_nFeatureCount)
         return NULL;
 
     if (m_bGeometryPerBlock && !m_bGeometry) {
         LoadGeometry();
     }
-    
+
     poReader = (VFKReaderSQLite*) m_poReader;
-    
+
     osSQL.Printf("SELECT rowid FROM %s WHERE %s = " CPL_FRMT_GIB,
                  m_pszName, FID_COLUMN, nFID);
     if (EQUAL(m_pszName, "SBP")) {
@@ -712,17 +716,17 @@ IVFKFeature *VFKDataBlockSQLite::GetFeature(GIntBig nFID)
         rowId = sqlite3_column_int(hStmt, 0);
     }
     sqlite3_finalize(hStmt);
-    
+
     return GetFeatureByIndex(rowId - 1);
 }
 
 /*!
   \brief Get first found feature based on it's property
-  
+
   \param column property name
   \param value property value
   \param bGeom True to check also geometry != NULL
-    
+
   \return pointer to feature definition or NULL on failure (not found)
 */
 VFKFeatureSQLite *VFKDataBlockSQLite::GetFeature(const char *column, GUIntBig value,
@@ -733,25 +737,25 @@ VFKFeatureSQLite *VFKDataBlockSQLite::GetFeature(const char *column, GUIntBig va
     VFKReaderSQLite  *poReader;
 
     sqlite3_stmt *hStmt;
-    
+
     poReader = (VFKReaderSQLite*) m_poReader;
-    
+
     osSQL.Printf("SELECT %s from %s WHERE %s = " CPL_FRMT_GUIB,
                  FID_COLUMN, m_pszName, column, value);
     if (bGeom) {
         CPLString osColumn;
-        
+
         osColumn.Printf(" AND %s IS NOT NULL", GEOM_COLUMN);
         osSQL += osColumn;
     }
-    
+
     hStmt = poReader->PrepareStatement(osSQL.c_str());
     if (poReader->ExecuteSQL(hStmt) != OGRERR_NONE)
         return NULL;
-    
+
     idx = sqlite3_column_int(hStmt, 0) - 1;
     sqlite3_finalize(hStmt);
-    
+
     if (idx < 0 || idx >= m_nFeatureCount) // ? assert
         return NULL;
 
@@ -760,7 +764,7 @@ VFKFeatureSQLite *VFKDataBlockSQLite::GetFeature(const char *column, GUIntBig va
 
 /*!
   \brief Get first found feature based on it's properties (AND)
-  
+
   \param column array of property names
   \param value array of property values
   \param num number of array items
@@ -776,9 +780,9 @@ VFKFeatureSQLite *VFKDataBlockSQLite::GetFeature(const char **column, GUIntBig *
     VFKReaderSQLite  *poReader;
 
     sqlite3_stmt *hStmt;
-    
+
     poReader = (VFKReaderSQLite*) m_poReader;
-    
+
     osSQL.Printf("SELECT %s FROM %s WHERE ", FID_COLUMN, m_pszName);
     for (int i = 0; i < num; i++) {
         if (i > 0)
@@ -795,23 +799,23 @@ VFKFeatureSQLite *VFKDataBlockSQLite::GetFeature(const char **column, GUIntBig *
     hStmt = poReader->PrepareStatement(osSQL.c_str());
     if (poReader->ExecuteSQL(hStmt) != OGRERR_NONE)
         return NULL;
-    
+
     idx = sqlite3_column_int(hStmt, 0) - 1; /* rowid starts at 1 */
-    sqlite3_finalize(hStmt);    
+    sqlite3_finalize(hStmt);
 
     if (idx < 0 || idx >= m_nFeatureCount) // ? assert
         return NULL;
-    
+
     return (VFKFeatureSQLite *) GetFeatureByIndex(idx);
 }
 
 /*!
   \brief Get features based on properties
-  
+
   \param column array of property names
   \param value array of property values
   \param num number of array items
-  
+
   \return list of features
 */
 VFKFeatureSQLiteList VFKDataBlockSQLite::GetFeatures(const char **column, GUIntBig *value, int num)
@@ -821,11 +825,11 @@ VFKFeatureSQLiteList VFKDataBlockSQLite::GetFeatures(const char **column, GUIntB
 
     VFKReaderSQLite     *poReader;
     VFKFeatureSQLiteList fList;
-    
+
     sqlite3_stmt *hStmt;
-    
+
     poReader = (VFKReaderSQLite*) m_poReader;
-    
+
     osSQL.Printf("SELECT rowid from %s WHERE ", m_pszName);
     for (int i = 0; i < num; i++) {
         if (i > 0)
@@ -836,13 +840,13 @@ VFKFeatureSQLiteList VFKDataBlockSQLite::GetFeatures(const char **column, GUIntB
     }
     osSQL += " ORDER BY ";
     osSQL += FID_COLUMN;
-    
+
     hStmt = poReader->PrepareStatement(osSQL.c_str());
     while (poReader->ExecuteSQL(hStmt) == OGRERR_NONE) {
         iRowId = sqlite3_column_int(hStmt, 0);
         fList.push_back((VFKFeatureSQLite *)GetFeatureByIndex(iRowId - 1));
     }
-    
+
     return fList;
 }
 
@@ -870,15 +874,15 @@ OGRErr VFKDataBlockSQLite::SaveGeometryToDB(const OGRGeometry *poGeom, int iRowI
 	nWKBLen = poGeom->WkbSize();
 	pabyWKB = (GByte *) CPLMalloc(nWKBLen + 1);
 	poGeom->exportToWkb(wkbNDR, pabyWKB);
-        
+
 	osSQL.Printf("UPDATE %s SET %s = ? WHERE rowid = %d",
 		     m_pszName, GEOM_COLUMN, iRowId);
 	hStmt = poReader->PrepareStatement(osSQL.c_str());
-	
+
 	rc = sqlite3_bind_blob(hStmt, 1, pabyWKB, nWKBLen, CPLFree);
 	if (rc != SQLITE_OK) {
 	    sqlite3_finalize(hStmt);
-	    CPLError(CE_Failure, CPLE_AppDefined, 
+	    CPLError(CE_Failure, CPLE_AppDefined,
 		     "Storing geometry in DB failed");
 	    return OGRERR_FAILURE;
 	}
@@ -901,7 +905,7 @@ bool VFKDataBlockSQLite::LoadGeometryFromDB()
 {
     int nInvalid, nGeometries, nGeometriesCount, nBytes, rowId;
 #ifdef DEBUG
-    long iFID;
+    GIntBig iFID;
 #endif
     bool bSkipInvalid;
 
@@ -926,10 +930,10 @@ bool VFKDataBlockSQLite::LoadGeometryFromDB()
         return FALSE;
     nGeometries = sqlite3_column_int(hStmt, 0);
     sqlite3_finalize(hStmt);
-    
+
     if (nGeometries < 1)
 	return FALSE;
-    
+
     bSkipInvalid = EQUAL(m_pszName, "OB") || EQUAL(m_pszName, "OP") || EQUAL(m_pszName, "OBBP");
 
     /* load geometry from DB */
@@ -946,9 +950,8 @@ bool VFKDataBlockSQLite::LoadGeometryFromDB()
     while(poReader->ExecuteSQL(hStmt) == OGRERR_NONE) {
         rowId++; // =sqlite3_column_int(hStmt, 1);
 #ifdef DEBUG
-        iFID =
+        iFID = sqlite3_column_int64(hStmt, 2);
 #endif
-            sqlite3_column_double(hStmt, 2);
 
         poFeature = (VFKFeatureSQLite *) GetFeatureByIndex(rowId - 1);
         CPLAssert(NULL != poFeature && poFeature->GetFID() == iFID);
@@ -973,13 +976,13 @@ bool VFKDataBlockSQLite::LoadGeometryFromDB()
 	     m_pszName, nGeometriesCount);
 
     if (nGeometriesCount != nGeometries) {
-	CPLError(CE_Warning, CPLE_AppDefined, 
+	CPLError(CE_Warning, CPLE_AppDefined,
                  "%s: %d geometries loaded (should be %d)",
 		 m_pszName, nGeometriesCount, nGeometries);
     }
 
     if (nInvalid > 0 && !bSkipInvalid) {
-	CPLError(CE_Warning, CPLE_AppDefined, 
+	CPLError(CE_Warning, CPLE_AppDefined,
                  "%s: %d features with invalid or empty geometry",
 		 m_pszName, nInvalid);
     }
@@ -995,12 +998,12 @@ bool VFKDataBlockSQLite::LoadGeometryFromDB()
 void VFKDataBlockSQLite::UpdateVfkBlocks(int nGeometries) {
     int nFeatCount;
     CPLString osSQL;
-    
+
     VFKReaderSQLite  *poReader;
-    
+
     poReader = (VFKReaderSQLite*) m_poReader;
 
-    /* update number of features in VFK_DB_TABLE table */    
+    /* update number of features in VFK_DB_TABLE table */
     nFeatCount = (int)GetFeatureCount();
     if (nFeatCount > 0) {
         osSQL.Printf("UPDATE %s SET num_features = %d WHERE table_name = '%s'",
@@ -1008,12 +1011,12 @@ void VFKDataBlockSQLite::UpdateVfkBlocks(int nGeometries) {
         poReader->ExecuteSQL(osSQL.c_str());
     }
 
-    /* update number of geometries in VFK_DB_TABLE table */    
+    /* update number of geometries in VFK_DB_TABLE table */
     if (nGeometries > 0) {
-        CPLDebug("OGR-VFK", 
+        CPLDebug("OGR-VFK",
                  "VFKDataBlockSQLite::UpdateVfkBlocks(): name=%s -> "
                  "%d geometries saved to internal DB", m_pszName, nGeometries);
-        
+
 	osSQL.Printf("UPDATE %s SET num_geometries = %d WHERE table_name = '%s'",
 		     VFK_DB_TABLE, nGeometries, m_pszName);
 	poReader->ExecuteSQL(osSQL.c_str());
@@ -1030,9 +1033,9 @@ void VFKDataBlockSQLite::UpdateFID(GIntBig iFID, std::vector<int> rowId)
 {
     CPLString osSQL, osValue;
     VFKReaderSQLite  *poReader;
-    
+
     poReader = (VFKReaderSQLite*) m_poReader;
-    
+
     /* update number of geometries in VFK_DB_TABLE table */
     osSQL.Printf("UPDATE %s SET %s = " CPL_FRMT_GIB " WHERE rowid IN (",
                  m_pszName, FID_COLUMN, iFID);
@@ -1044,7 +1047,7 @@ void VFKDataBlockSQLite::UpdateFID(GIntBig iFID, std::vector<int> rowId)
 	osSQL += osValue;
     }
     osSQL += ")";
-    
+
     poReader->ExecuteSQL(osSQL.c_str());
 }
 
diff --git a/ogr/ogrsf_frmts/vfk/vfkfeature.cpp b/ogr/ogrsf_frmts/vfk/vfkfeature.cpp
index 1d39a34..555d20a 100644
--- a/ogr/ogrsf_frmts/vfk/vfkfeature.cpp
+++ b/ogr/ogrsf_frmts/vfk/vfkfeature.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vfkfeature.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: vfkfeature.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  VFK Reader - Feature definition
  * Purpose:  Implements IVFKFeature/VFKFeature class.
@@ -45,7 +45,7 @@ IVFKFeature::IVFKFeature(IVFKDataBlock *poDataBlock)
 {
     CPLAssert(NULL != poDataBlock);
     m_poDataBlock   = poDataBlock;
-    
+
     m_nFID          = -1;
     m_nGeometryType = poDataBlock->GetGeometryType();
     m_bGeometry     = FALSE;
@@ -60,7 +60,7 @@ IVFKFeature::~IVFKFeature()
 {
     if (m_paGeom)
         delete m_paGeom;
-    
+
     m_poDataBlock = NULL;
 }
 
@@ -76,7 +76,7 @@ void IVFKFeature::SetGeometryType(OGRwkbGeometryType nGeomType)
   \brief Set feature id
 
   FID: 0 for next, -1 for same
-  
+
   \param nFID feature id
 */
 void IVFKFeature::SetFID(GIntBig nFID)
@@ -118,7 +118,7 @@ bool IVFKFeature::SetGeometry(OGRGeometry *poGeom, const char *ftype)
                      m_poDataBlock->GetName(), m_nFID);
         m_bValid = FALSE;
     }
-    
+
     /* check coordinates */
     if (m_nGeometryType == wkbPoint) {
         double x, y;
@@ -148,28 +148,39 @@ bool IVFKFeature::SetGeometry(OGRGeometry *poGeom, const char *ftype)
             OGRPoint pt;
             OGRGeometry *poGeomCurved;
             OGRCircularString poGeomString;
-                
+
             poGeomCurved = NULL;
             if (EQUAL(ftype, "15") || EQUAL(ftype, "16")) {         /* -> circle or arc */
-                int npoints;
-                
-                npoints = ((OGRLineString *) poGeom)->getNumPoints();
+                int npoints = ((OGRLineString *) poGeom)->getNumPoints();
                 for (int i = 0; i < npoints; i++) {
                     ((OGRLineString *) poGeom)->getPoint(i, &pt);
                     poGeomString.addPoint(&pt);
                 }
                 if (EQUAL(ftype, "15")) {
+                    if (npoints < 3) {
+                      CPLError(CE_Warning, CPLE_AppDefined,
+                               "npoints is %d.  expected 3", npoints);
+                    }
+                    if (npoints > 3) {
+                        CPLError(CE_Warning, CPLE_AppDefined,
+                                 "npoints is %d.  Will overflow buffers.  "
+                                 "Cannot continue.", npoints);
+                        m_bValid = FALSE;
+                        return false;
+                    }
+
                     /* compute center and radius of a circle */
-                    double x[3], y[3];
+                    double x[3] = { 0.0, 0.0, 0.0 };
+                    double y[3] = { 0.0, 0.0, 0.0 };
                     double m1, n1, m2, n2, c1, c2, mx;
                     double c_x, c_y;
-                    
+
                     for (int i = 0; i < npoints; i++) {
                         ((OGRLineString *) poGeom)->getPoint(i, &pt);
                         x[i] = pt.getX();
                         y[i] = pt.getY();
                     }
-                                        
+
                     m1 = (x[0] + x[1]) / 2.0;
                     n1 = (y[0] + y[1]) / 2.0;
 
@@ -183,7 +194,7 @@ bool IVFKFeature::SetGeometry(OGRGeometry *poGeom, const char *ftype)
 
                     c_x = (c1 * (y[2] - y[0]) + c2 * (y[0] - y[1])) / mx;
                     c_y = (c1 * (x[0] - x[2]) + c2 * (x[1] - x[0])) / mx;
-   
+
                     /* compute a new intermediate point */
                     pt.setX(c_x - (x[1] - c_x));
                     pt.setY(c_y - (y[1] - c_y));
@@ -195,7 +206,7 @@ bool IVFKFeature::SetGeometry(OGRGeometry *poGeom, const char *ftype)
 
                 }
             }
-            else if (strlen(ftype) > 2 && EQUALN(ftype, "15", 2)) { /* -> circle with radius */
+            else if (strlen(ftype) > 2 && STARTS_WITH_CI(ftype, "15")) { /* -> circle with radius */
                 float r;
                 char s[3]; /* 15 */
 
@@ -207,7 +218,7 @@ bool IVFKFeature::SetGeometry(OGRGeometry *poGeom, const char *ftype)
                 }
                 else {
                     double c_x, c_y;
-                    
+
                     ((OGRLineString *) poGeom)->getPoint(0, &pt);
                     c_x = pt.getX();
                     c_y = pt.getY();
@@ -253,10 +264,10 @@ bool IVFKFeature::SetGeometry(OGRGeometry *poGeom, const char *ftype)
 
             if (!poGeomString.IsEmpty())
                 poGeomCurved = poGeomString.CurveToLine();
-            
+
             if (poGeomCurved) {
                 int npoints;
-                
+
                 npoints = ((OGRLineString *) poGeomCurved)->getNumPoints();
                 CPLDebug("OGR-VFK", "%s: curve (type=%s) to linestring (npoints=%d) fid = " CPL_FRMT_GIB,
                          m_poDataBlock->GetName(), ftype,
@@ -271,7 +282,7 @@ bool IVFKFeature::SetGeometry(OGRGeometry *poGeom, const char *ftype)
             /* check degenerated linestrings */
             if (m_nGeometryType == wkbLineString) {
                 int npoints;
-                
+
                 npoints = ((OGRLineString *) poGeom)->getNumPoints();
                 if (npoints < 2) {
                     CPLError(CE_Warning, CPLE_AppDefined,
@@ -311,12 +322,12 @@ OGRGeometry *IVFKFeature::GetGeometry()
 bool IVFKFeature::LoadGeometry()
 {
     const char *pszName;
-    
+
     if (m_bGeometry)
         return TRUE;
 
     pszName  = m_poDataBlock->GetName();
-    
+
     if (EQUAL (pszName, "SOBR") ||
         EQUAL (pszName, "OBBP") ||
         EQUAL (pszName, "SPOL") ||
@@ -324,7 +335,7 @@ bool IVFKFeature::LoadGeometry()
         EQUAL (pszName, "OP") ||
         EQUAL (pszName, "OBPEJ")) {
         /* -> wkbPoint */
-        
+
         return LoadGeometryPoint();
     }
     else if (EQUAL (pszName, "SBP")) {
@@ -370,11 +381,11 @@ bool VFKFeature::SetProperties(const char *pszLine)
     const char *poChar, *poProp;
     char* pszProp;
     bool inString;
-    
+
     std::vector<CPLString> oPropList;
-    
+
     pszProp = NULL;
-    
+
     for (poChar = pszLine; *poChar != '\0' && *poChar != ';'; poChar++)
         /* skip data block name */
         ;
@@ -388,13 +399,13 @@ bool VFKFeature::SetProperties(const char *pszLine)
     iIndex = nLength = 0;
     inString = FALSE;
     while(*poChar != '\0') {
-        if (*poChar == '"' && 
+        if (*poChar == '"' &&
             (*(poChar-1) == ';' || *(poChar+1) == ';' || *(poChar+1) == '\0')) {
             poChar++; /* skip '"' */
             inString = inString ? FALSE : TRUE;
             if (inString) {
                 poProp = poChar;
-                if (*poChar == '"' && (*(poChar+1) == ';' || *(poChar+1) == '\0')) { 
+                if (*poChar == '"' && (*(poChar+1) == ';' || *(poChar+1) == '\0')) {
                     poChar++;
                     inString = FALSE;
                 }
@@ -418,7 +429,7 @@ bool VFKFeature::SetProperties(const char *pszLine)
         }
     }
     /* append last property */
-    if (inString) {
+    if (inString && nLength > 0) {
         nLength--; /* ignore '"' */
     }
     pszProp = (char *) CPLRealloc(pszProp, nLength + 1);
@@ -430,10 +441,11 @@ bool VFKFeature::SetProperties(const char *pszLine)
     /* set properties from the list */
     if (oPropList.size() != (size_t) m_poDataBlock->GetPropertyCount()) {
         /* try to read also invalid records */
-        CPLError(CE_Warning, CPLE_AppDefined, 
+        CPLError(CE_Warning, CPLE_AppDefined,
                  "%s: invalid number of properties %d should be %d",
                  m_poDataBlock->GetName(),
 		 (int) oPropList.size(), m_poDataBlock->GetPropertyCount());
+        CPLFree(pszProp);
         return FALSE;
    }
     iIndex = 0;
@@ -441,8 +453,9 @@ bool VFKFeature::SetProperties(const char *pszLine)
 	 ip != oPropList.end(); ++ip) {
 	SetProperty(iIndex++, (*ip).c_str());
     }
-    
-    /* set fid 
+
+    // TODO(martinl): What was this block disabled?
+    /* set fid
     if (EQUAL(m_poDataBlock->GetName(), "SBP")) {
         GUIntBig id;
         const VFKProperty *poVfkProperty;
@@ -452,13 +465,13 @@ bool VFKFeature::SetProperties(const char *pszLine)
         {
             id = strtoul(poVfkProperty->GetValueS(), NULL, 0);
             if (id == 1)
-                SetFID(0); 
+                SetFID(0);
             else
-                SetFID(-1); 
+                SetFID(-1);
         }
     }
     else {
-        SetFID(0); 
+        SetFID(0);
     }
     */
     CPLFree(pszProp);
@@ -480,7 +493,7 @@ bool VFKFeature::SetProperty(int iIndex, const char *pszValue)
     if (iIndex < 0 || iIndex >= m_poDataBlock->GetPropertyCount() ||
 	size_t(iIndex) >= m_propertyList.size())
         return FALSE;
-    
+
     if (strlen(pszValue) < 1)
         m_propertyList[iIndex] = VFKProperty();
     else {
@@ -488,7 +501,7 @@ bool VFKFeature::SetProperty(int iIndex, const char *pszValue)
 
         const char *pszEncoding;
         char       *pszValueEnc;
-                
+
         fType = m_poDataBlock->GetProperty(iIndex)->GetType();
         switch (fType) {
         case OFTInteger:
@@ -527,7 +540,7 @@ const VFKProperty *VFKFeature::GetProperty(int iIndex) const
     if (iIndex < 0 || iIndex >= m_poDataBlock->GetPropertyCount() ||
 	size_t(iIndex) >= m_propertyList.size())
         return NULL;
-    
+
     const VFKProperty* poProperty = &m_propertyList[iIndex];
     return poProperty;
 }
@@ -549,7 +562,7 @@ const VFKProperty *VFKFeature::GetProperty(const char *pszName) const
   \brief Load geometry (point layers)
 
   \todo Really needed?
-  
+
   \return TRUE on success
   \return FALSE on failure
 */
@@ -557,17 +570,17 @@ bool VFKFeature::LoadGeometryPoint()
 {
     double x, y;
     int i_idxX, i_idxY;
-    
+
     i_idxY = m_poDataBlock->GetPropertyIndex("SOURADNICE_Y");
     i_idxX = m_poDataBlock->GetPropertyIndex("SOURADNICE_X");
     if (i_idxY < 0 || i_idxX < 0)
         return FALSE;
-    
+
     x = -1.0 * GetProperty(i_idxY)->GetValueD();
     y = -1.0 * GetProperty(i_idxX)->GetValueD();
     OGRPoint pt(x, y);
     SetGeometry(&pt);
-    
+
     return TRUE;
 }
 
@@ -581,24 +594,24 @@ bool VFKFeature::LoadGeometryPoint()
 bool VFKFeature::LoadGeometryLineStringSBP()
 {
     int id, idxId, idxBp_Id, idxPCB, ipcb;
-    
+
     VFKDataBlock *poDataBlockPoints;
     VFKFeature   *poPoint, *poLine;
-    
+
     OGRLineString OGRLine;
-    
+
     poDataBlockPoints = (VFKDataBlock *) m_poDataBlock->GetReader()->GetDataBlock("SOBR");
     if (!poDataBlockPoints)
         return FALSE;
-    
+
     idxId    = poDataBlockPoints->GetPropertyIndex("ID");
     idxBp_Id = m_poDataBlock->GetPropertyIndex("BP_ID");
     idxPCB   = m_poDataBlock->GetPropertyIndex("PORADOVE_CISLO_BODU");
     if (idxId < 0 || idxBp_Id < 0 || idxPCB < 0)
         return false;
-    
+
     poLine = this;
-    while (TRUE)
+    while( true )
     {
         id   = poLine->GetProperty(idxBp_Id)->GetValueI();
         ipcb = poLine->GetProperty(idxPCB)->GetValueI();
@@ -607,7 +620,7 @@ bool VFKFeature::LoadGeometryLineStringSBP()
             m_poDataBlock->GetPreviousFeature(); /* push back */
             break;
         }
-        
+
         poPoint = poDataBlockPoints->GetFeature(idxId, id);
         if (!poPoint)
         {
@@ -615,18 +628,18 @@ bool VFKFeature::LoadGeometryLineStringSBP()
         }
         OGRPoint *pt = (OGRPoint *) poPoint->GetGeometry();
         OGRLine.addPoint(pt);
-        
+
         poLine = (VFKFeature *) m_poDataBlock->GetNextFeature();
         if (!poLine)
             break;
     };
-    
+
     OGRLine.setCoordinateDimension(2); /* force 2D */
     SetGeometry(&OGRLine);
-    
+
     /* reset reading */
     poDataBlockPoints->ResetReading();
-    
+
     return TRUE;
 }
 
@@ -642,24 +655,24 @@ bool VFKFeature::LoadGeometryLineStringHP()
     int           id, idxId, idxHp_Id;
     VFKDataBlock *poDataBlockLines;
     VFKFeature   *poLine;
-    
+
     poDataBlockLines = (VFKDataBlock *) m_poDataBlock->GetReader()->GetDataBlock("SBP");
     if (!poDataBlockLines)
         return FALSE;
-    
+
     idxId    = m_poDataBlock->GetPropertyIndex("ID");
     idxHp_Id = poDataBlockLines->GetPropertyIndex("HP_ID");
     if (idxId < 0 || idxHp_Id < 0)
         return FALSE;
-    
+
     id = GetProperty(idxId)->GetValueI();
     poLine = poDataBlockLines->GetFeature(idxHp_Id, id);
     if (!poLine || !poLine->GetGeometry())
         return FALSE;
-    
+
     SetGeometry(poLine->GetGeometry());
     poDataBlockLines->ResetReading();
-    
+
     return TRUE;
 }
 
@@ -680,7 +693,7 @@ OGRErr VFKFeature::LoadProperties(OGRFeature *poFeature)
         if (GetProperty(iField)->IsNull())
             continue;
         OGRFieldType fType = poFeature->GetDefnRef()->GetFieldDefn(iField)->GetType();
-        if (fType == OFTInteger) 
+        if (fType == OFTInteger)
             poFeature->SetField(iField,
                                 GetProperty(iField)->GetValueI());
         else if (fType == OFTReal)
diff --git a/ogr/ogrsf_frmts/vfk/vfkfeaturesqlite.cpp b/ogr/ogrsf_frmts/vfk/vfkfeaturesqlite.cpp
index b666300..4b4cd21 100644
--- a/ogr/ogrsf_frmts/vfk/vfkfeaturesqlite.cpp
+++ b/ogr/ogrsf_frmts/vfk/vfkfeaturesqlite.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vfkfeaturesqlite.cpp 28382 2015-01-30 15:29:41Z rouault $
+ * $Id: vfkfeaturesqlite.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  VFK Reader - Feature definition (SQLite)
  * Purpose:  Implements VFKFeatureSQLite class.
@@ -52,7 +52,7 @@ VFKFeatureSQLite::VFKFeatureSQLite(IVFKDataBlock *poDataBlock) : IVFKFeature(poD
 }
 
 /*!
-  \brief VFKFeatureSQLite constructor 
+  \brief VFKFeatureSQLite constructor
 
   \param poDataBlock pointer to related IVFKDataBlock
   \param iRowId feature DB rowid (starts at 1)
@@ -71,16 +71,16 @@ VFKFeatureSQLite::VFKFeatureSQLite(IVFKDataBlock *poDataBlock, int iRowId, GIntB
 OGRErr VFKFeatureSQLite::SetFIDFromDB()
 {
     CPLString   osSQL;
-    
+
     osSQL.Printf("SELECT %s FROM %s WHERE rowid = %d",
                  FID_COLUMN, m_poDataBlock->GetName(), m_iRowId);
     if (ExecuteSQL(osSQL.c_str()) != OGRERR_NONE)
         return OGRERR_FAILURE;
 
     m_nFID = sqlite3_column_int(m_hStmt, 0);
-  
+
     FinalizeSQL();
-    
+
     return OGRERR_NONE;
 }
 
@@ -115,17 +115,17 @@ OGRErr VFKFeatureSQLite::ExecuteSQL(const char *pszSQLCommand)
     int rc;
 
     sqlite3  *poDB;
-    
+
     VFKReaderSQLite *poReader = (VFKReaderSQLite *) m_poDataBlock->GetReader();
     poDB = poReader->m_poDB;
-    
-    rc = sqlite3_prepare(poDB, pszSQLCommand, strlen(pszSQLCommand),
+
+    rc = sqlite3_prepare(poDB, pszSQLCommand, -1,
                          &m_hStmt, NULL);
     if (rc != SQLITE_OK) {
-        CPLError(CE_Failure, CPLE_AppDefined, 
+        CPLError(CE_Failure, CPLE_AppDefined,
                  "In ExecuteSQL(): sqlite3_prepare(%s):\n  %s",
                  pszSQLCommand, sqlite3_errmsg(poDB));
-        
+
         if(m_hStmt != NULL) {
             FinalizeSQL();
         }
@@ -133,14 +133,14 @@ OGRErr VFKFeatureSQLite::ExecuteSQL(const char *pszSQLCommand)
     }
     rc = sqlite3_step(m_hStmt);
     if (rc != SQLITE_ROW) {
-        CPLError(CE_Failure, CPLE_AppDefined, 
-                 "In ExecuteSQL(): sqlite3_step(%s):\n  %s", 
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "In ExecuteSQL(): sqlite3_step(%s):\n  %s",
                  pszSQLCommand, sqlite3_errmsg(poDB));
-        
+
         if (m_hStmt) {
             FinalizeSQL();
         }
-        
+
         return OGRERR_FAILURE;
     }
 
@@ -163,7 +163,7 @@ VFKFeatureSQLite::VFKFeatureSQLite(const VFKFeature *poVFKFeature) : IVFKFeature
   \brief Load geometry (point layers)
 
   \todo Implement (really needed?)
-  
+
   \return TRUE on success or FALSE on failure
 */
 bool VFKFeatureSQLite::LoadGeometryPoint()
diff --git a/ogr/ogrsf_frmts/vfk/vfkproperty.cpp b/ogr/ogrsf_frmts/vfk/vfkproperty.cpp
index d39d2e3..159d9bd 100644
--- a/ogr/ogrsf_frmts/vfk/vfkproperty.cpp
+++ b/ogr/ogrsf_frmts/vfk/vfkproperty.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vfkproperty.cpp 27995 2014-11-21 20:14:07Z rouault $
+ * $Id: vfkproperty.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  VFK Reader - Property definition
  * Purpose:  Implements VFKProperty class.
@@ -46,7 +46,7 @@ VFKProperty::VFKProperty()
 /*!
   \brief Set VFK property (integer)
 */
-VFKProperty::VFKProperty(int iValue) 
+VFKProperty::VFKProperty(int iValue)
     : m_bIsNull(FALSE), m_nValue(iValue), m_dValue(0.0)
 {
 }
@@ -63,7 +63,7 @@ VFKProperty::VFKProperty(double dValue)
   \brief Set VFK property (string)
 */
 VFKProperty::VFKProperty(const char *pszValue)
-    : m_bIsNull(FALSE), m_nValue(0), m_dValue(0.0), m_strValue(0 != pszValue ? pszValue : "")
+    : m_bIsNull(FALSE), m_nValue(0), m_dValue(0.0), m_strValue(NULL != pszValue ? pszValue : "")
 {
 }
 
@@ -107,9 +107,9 @@ VFKProperty& VFKProperty::operator=(VFKProperty const& other)
 
 /*!
   \brief Get string property
-  
+
   \param escape TRUE to escape characters for SQL
-  
+
   \return string buffer
 */
 const char *VFKProperty::GetValueS(bool escape) const
diff --git a/ogr/ogrsf_frmts/vfk/vfkpropertydefn.cpp b/ogr/ogrsf_frmts/vfk/vfkpropertydefn.cpp
index f15a071..8f35f4f 100644
--- a/ogr/ogrsf_frmts/vfk/vfkpropertydefn.cpp
+++ b/ogr/ogrsf_frmts/vfk/vfkpropertydefn.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vfkpropertydefn.cpp 25201 2012-11-04 11:11:31Z martinl $
+ * $Id: vfkpropertydefn.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  VFK Reader - Data block property definition
  * Purpose:  Implements VFKPropertyDefn class.
@@ -59,13 +59,13 @@ VFKPropertyDefn::VFKPropertyDefn(const char *pszName, const char *pszType,
     pszWidth = (char *) CPLMalloc(nLength+1);
     strncpy(pszWidth, poWidth, nLength);
     pszWidth[nLength] = '\0';
-    
+
     m_nWidth  = atoi(pszWidth);
     CPLFree(pszWidth);
-    
+
     /* precision */
     m_nPrecision = 0;
-    
+
     /* type */
     m_pszEncoding = NULL;
     if (*m_pszType == 'N') {
@@ -111,7 +111,7 @@ VFKPropertyDefn::~VFKPropertyDefn()
 }
 
 /*!
-  \brief Get SQL data type 
+  \brief Get SQL data type
 
   \return string with data type ("text" by default)
 */
diff --git a/ogr/ogrsf_frmts/vfk/vfkreader.cpp b/ogr/ogrsf_frmts/vfk/vfkreader.cpp
index 251a9e0..2429e80 100644
--- a/ogr/ogrsf_frmts/vfk/vfkreader.cpp
+++ b/ogr/ogrsf_frmts/vfk/vfkreader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vfkreader.cpp 27973 2014-11-16 17:40:22Z martinl $
+ * $Id: vfkreader.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  VFK Reader
  * Purpose:  Implements VFKReader class.
@@ -76,7 +76,7 @@ VFKReader::VFKReader(const char *pszFilename)
     m_pszFilename = CPLStrdup(pszFilename);
     m_poFD = VSIFOpen(m_pszFilename, "rb");
     if (m_poFD == NULL) {
-        CPLError(CE_Failure, CPLE_OpenFailed, 
+        CPLError(CE_Failure, CPLE_OpenFailed,
                  "Failed to open file %s.", m_pszFilename);
     }
 }
@@ -90,7 +90,7 @@ VFKReader::~VFKReader()
 
     if (m_poFD)
         VSIFClose(m_poFD);
-    
+
     /* clear data blocks */
     for (int i = 0; i < m_nDataBlockCount; i++)
         delete m_papoDataBlock[i];
@@ -118,7 +118,7 @@ char *GetDataBlockName(const char *pszLine)
 
 /*!
   \brief Read a line from file
- 
+
   \param bRecode do recoding
 
   \return a NULL terminated string which should be freed with CPLFree().
@@ -127,11 +127,11 @@ char *VFKReader::ReadLine(bool bRecode)
 {
     const char *pszRawLine;
     char *pszLine;
-    
+
     pszRawLine = CPLReadLine(m_poFD);
     if (pszRawLine == NULL)
         return NULL;
-    
+
     if (bRecode)
         pszLine = CPLRecode(pszRawLine,
                             m_bLatin2 ? "ISO-8859-2" : "WINDOWS-1250",
@@ -155,9 +155,9 @@ int VFKReader::ReadDataBlocks()
 {
     char       *pszLine, *pszBlockName;
     bool        bInHeader;
-    
+
     IVFKDataBlock *poNewDataBlock;
-    
+
     CPLAssert(NULL != m_pszFilename);
 
     VSIFSeek(m_poFD, 0, SEEK_SET);
@@ -173,8 +173,8 @@ int VFKReader::ReadDataBlocks()
                 bInHeader = FALSE; /* 'B' record closes the header section */
 
             pszBlockName = GetDataBlockName(pszLine);
-            if (pszBlockName == NULL) { 
-                CPLError(CE_Failure, CPLE_NotSupported, 
+            if (pszBlockName == NULL) {
+                CPLError(CE_Failure, CPLE_NotSupported,
                          "Corrupted data - line\n%s\n", pszLine);
                 CPLFree(pszLine);
                 return -1;
@@ -198,10 +198,10 @@ int VFKReader::ReadDataBlocks()
             /* process 'D' records in the header section */
             AddInfo(pszLine);
         }
-        
+
         CPLFree(pszLine);
     }
-    
+
     return m_nDataBlockCount;
 }
 
@@ -217,18 +217,8 @@ int VFKReader::ReadDataBlocks()
 */
 int VFKReader::ReadDataRecords(IVFKDataBlock *poDataBlock)
 {
-    const char *pszName;
-    char       *pszBlockName, *pszLine;
-    CPLString   osBlockNameLast;
-    int         nLength, iLine, nSkipped, nDupl, nRecords;
-    int         iDataBlock;
-    bool        bInHeader;
-    
-    IVFKDataBlock *poDataBlockCurrent;
-    
-    CPLString pszMultiLine;
-
-    VFKFeature *poNewFeature;
+    const char *pszName = NULL;
+    IVFKDataBlock *poDataBlockCurrent = NULL;
 
     if (poDataBlock) {  /* read only given data block */
         poDataBlockCurrent = poDataBlock;
@@ -236,28 +226,34 @@ int VFKReader::ReadDataRecords(IVFKDataBlock *poDataBlock)
         pszName = poDataBlockCurrent->GetName();
     }
     else {              /* read all data blocks */
-        pszName = NULL; 
-        for (iDataBlock = 0; iDataBlock < GetDataBlockCount(); iDataBlock++) {
+        for (int iDataBlock = 0; iDataBlock < GetDataBlockCount(); iDataBlock++) {
             poDataBlockCurrent = GetDataBlock(iDataBlock);
             poDataBlockCurrent->SetFeatureCount(0);
         }
         poDataBlockCurrent = NULL;
     }
-    
+
     VSIFSeek(m_poFD, 0, SEEK_SET);
-    iLine = nSkipped = nDupl = nRecords = 0;
-    bInHeader = TRUE;
+
+    int iLine = 0;
+    int nSkipped = 0;
+    int nDupl = 0;
+    int nRecords = 0;
+    bool bInHeader = true;
+    CPLString osBlockNameLast;
+    char *pszLine;
+
     while ((pszLine = ReadLine()) != NULL) {
         iLine++;
-        nLength = strlen(pszLine);
+        int nLength = static_cast<int>(strlen(pszLine));
         if (nLength < 2) {
             CPLFree(pszLine);
             continue;
         }
-        
+
         if (bInHeader && pszLine[1] == 'B')
-            bInHeader = FALSE; /* 'B' record closes the header section */
-        
+            bInHeader = false; /* 'B' record closes the header section */
+
         if (pszLine[1] == 'D') {
             if (bInHeader) {
                 /* skip 'D' records from the header section, already
@@ -266,8 +262,8 @@ int VFKReader::ReadDataRecords(IVFKDataBlock *poDataBlock)
                 continue;
             }
 
-            pszBlockName = GetDataBlockName(pszLine);
-            
+            char *pszBlockName = GetDataBlockName(pszLine);
+
             if (pszBlockName && (!pszName || EQUAL(pszBlockName, pszName))) {
                 /* merge lines if needed
 
@@ -277,29 +273,29 @@ int VFKReader::ReadDataRecords(IVFKDataBlock *poDataBlock)
                 if (pszLine[nLength - 1] == '\244') {
                     /* remove \244 (currency sign) from string */
                     pszLine[nLength - 1] = '\0';
-                    
-                    pszMultiLine.clear();
-                    pszMultiLine = pszLine;
+
+                    CPLString osMultiLine(pszLine);
                     CPLFree(pszLine);
-                    
+
                     while ((pszLine = ReadLine()) != NULL &&
                            pszLine[strlen(pszLine) - 1] == '\244') {
                         /* append line */
-                        pszMultiLine += pszLine;
+                        osMultiLine += pszLine;
                         /* remove 0244 (currency sign) from string */
-                        pszMultiLine.erase(pszMultiLine.size() - 1);
+                        osMultiLine.erase(osMultiLine.size() - 1);
 
                         CPLFree(pszLine);
-                    } 
-                    pszMultiLine += pszLine;
+                    }
+                    if( pszLine )
+                        osMultiLine += pszLine;
                     CPLFree(pszLine);
-                    
-                    nLength = pszMultiLine.size();
+
+                    nLength = static_cast<int>(osMultiLine.size());
                     pszLine = (char *) CPLMalloc(nLength + 1);
-                    strncpy(pszLine, pszMultiLine.c_str(), nLength);
+                    strncpy(pszLine, osMultiLine.c_str(), nLength);
                     pszLine[nLength] = '\0';
                 }
-                
+
                 if (!poDataBlock && pszBlockName) { /* read all data blocks */
                     if (osBlockNameLast.empty() ||
                         !EQUAL(pszBlockName, osBlockNameLast.c_str())) {
@@ -311,14 +307,15 @@ int VFKReader::ReadDataRecords(IVFKDataBlock *poDataBlock)
                     CPLFree(pszBlockName);
                     continue; // assert ?
                 }
-                
-                poNewFeature = new VFKFeature(poDataBlockCurrent,
-                                              poDataBlockCurrent->GetFeatureCount() + 1);
+
+                VFKFeature *poNewFeature = new VFKFeature(poDataBlockCurrent,
+                                                          poDataBlockCurrent->GetFeatureCount() + 1);
                 if (poNewFeature->SetProperties(pszLine)) {
                     if (AddFeature(poDataBlockCurrent, poNewFeature) != OGRERR_NONE) {
-                        CPLDebug("OGR-VFK", 
-                                 "%s: duplicated VFK data recored skipped (line %d).\n%s\n",
-                                 pszBlockName, iLine, pszLine);
+                        CPLDebug( "OGR-VFK",
+                                  "%s: duplicated VFK data record skipped "
+                                  "(line %d).\n%s\n",
+                                  pszBlockName, iLine, pszLine);
                         poDataBlockCurrent->SetIncRecordCount(RecordDuplicated);
                     }
                     else {
@@ -328,9 +325,10 @@ int VFKReader::ReadDataRecords(IVFKDataBlock *poDataBlock)
                     delete poNewFeature;
                 }
                 else {
-                    CPLDebug("OGR-VFK", 
+                    CPLDebug("OGR-VFK",
                              "Invalid VFK data record skipped (line %d).\n%s\n", iLine, pszLine);
                     poDataBlockCurrent->SetIncRecordCount(RecordSkipped);
+                    delete poNewFeature;
                 }
             }
             CPLFree(pszBlockName);
@@ -344,20 +342,20 @@ int VFKReader::ReadDataRecords(IVFKDataBlock *poDataBlock)
         CPLFree(pszLine);
     }
 
-    for (iDataBlock = 0; iDataBlock < GetDataBlockCount(); iDataBlock++) {
+    for (int iDataBlock = 0; iDataBlock < GetDataBlockCount(); iDataBlock++) {
         poDataBlockCurrent = GetDataBlock(iDataBlock);
 
         if (poDataBlock && poDataBlock != poDataBlockCurrent)
             continue;
-        
+
         nSkipped = poDataBlockCurrent->GetRecordCount(RecordSkipped);
         nDupl    = poDataBlockCurrent->GetRecordCount(RecordDuplicated);
         if (nSkipped > 0)
-            CPLError(CE_Warning, CPLE_AppDefined, 
+            CPLError(CE_Warning, CPLE_AppDefined,
                      "%s: %d invalid VFK data records skipped",
                      poDataBlockCurrent->GetName(), nSkipped);
         if (nDupl > 0)
-            CPLError(CE_Warning, CPLE_AppDefined, 
+            CPLError(CE_Warning, CPLE_AppDefined,
                      "%s: %d duplicated VFK data records skipped",
                      poDataBlockCurrent->GetName(), nDupl);
 
@@ -413,7 +411,7 @@ IVFKDataBlock *VFKReader::GetDataBlock(int i) const
 {
     if (i < 0 || i >= m_nDataBlockCount)
         return NULL;
-    
+
     return m_papoDataBlock[i];
 }
 
@@ -447,10 +445,10 @@ int VFKReader::LoadGeometry()
     for (int i = 0; i < m_nDataBlockCount; i++) {
         nfeatures += m_papoDataBlock[i]->LoadGeometry();
     }
-    
+
     CPLDebug("OGR_VFK", "VFKReader::LoadGeometry(): invalid=%ld", nfeatures);
-    
-    return nfeatures;
+
+    return static_cast<int>(nfeatures);
 }
 
 /*!
@@ -460,19 +458,15 @@ int VFKReader::LoadGeometry()
 */
 void VFKReader::AddInfo(const char *pszLine)
 {
-    int         i, iKeyLength, iValueLength;
-    int         nSkip, nOffset;
-    char       *pszKey, *pszValue, *pszValueEnc;
-    const char *poChar, *poKey;
-    CPLString   key, value;
-    
+    int         nOffset;
     if (pszLine[1] == 'H')
         nOffset = 2;
     else
         nOffset = 1; /* &DKATUZE */
-    
-    poChar = poKey = pszLine + nOffset; /* &H */
-    iKeyLength = 0;
+
+    const char *poKey = pszLine + nOffset; /* &H */
+    const char *poChar = poKey;
+    int iKeyLength = 0;
     while (*poChar != '\0' && *poChar != ';') {
         iKeyLength++;
         poChar ++;
@@ -480,28 +474,28 @@ void VFKReader::AddInfo(const char *pszLine)
     if (*poChar == '\0')
         return;
 
-    pszKey = (char *) CPLMalloc(iKeyLength + 1);
+    char *pszKey = (char *) CPLMalloc(iKeyLength + 1);
     strncpy(pszKey, poKey, iKeyLength);
     pszKey[iKeyLength] = '\0';
 
     poChar++; /* skip ; */
 
-    iValueLength = 0;
-    nSkip = 3; /* &H + ; */
+    int iValueLength = 0;
+    int nSkip = 3; /* &H + ; */
     while (*poChar != '\0') {
         if (*poChar == '"' && iValueLength == 0) {
             nSkip++;
         }
         else {
-            iValueLength++; 
+            iValueLength++;
         }
         poChar++;
     }
-    if (nSkip > 3)
+    if (nSkip > 3 && iValueLength > 0 )
         iValueLength--;
-    
-    pszValue = (char *) CPLMalloc(iValueLength + 1);
-    for (i = 0; i < iValueLength; i++) {
+
+    char *pszValue = (char *) CPLMalloc(iValueLength + 1);
+    for (int i = 0; i < iValueLength; i++) {
         pszValue[i] = pszLine[iKeyLength+nSkip+i];
         if (pszValue[i] == '"') {
             pszValue[i] = '\''; /* " -> ' */
@@ -510,38 +504,35 @@ void VFKReader::AddInfo(const char *pszLine)
 
     pszValue[iValueLength] = '\0';
 
-
     /* recode values, assuming Latin2 */
     if (EQUAL(pszKey, "CODEPAGE")) {
         if (!EQUAL(pszValue, "WE8ISO8859P2"))
             m_bLatin2 = FALSE;
     }
 
-    pszValueEnc = CPLRecode(pszValue,
+    char *pszValueEnc = CPLRecode(pszValue,
                             m_bLatin2 ? "ISO-8859-2" : "WINDOWS-1250",
                             CPL_ENC_UTF8);
     if (poInfo.find(pszKey) == poInfo.end() ) {
         poInfo[pszKey] = pszValueEnc;
     }
     else {
-        int nCount;
-        size_t iFound;
-        char *pszKeyUniq;
-        
         /* max. number of duplicated keys can be 101 */
-        pszKeyUniq = (char *) CPLMalloc(strlen(pszKey) + 5); 
+        const size_t nLen = strlen(pszKey) + 5;
+        char *pszKeyUniq = (char *) CPLMalloc(nLen);
 
-        nCount = 1; /* assuming at least one match */
+        int nCount = 1; /* assuming at least one match */
         for(std::map<CPLString, CPLString>::iterator i = poInfo.begin();
             i != poInfo.end(); ++i) {
-            iFound = i->first.find("_");
+            size_t iFound = i->first.find("_");
             if (iFound != std::string::npos &&
                 EQUALN(pszKey, i->first.c_str(), iFound))
                 nCount += 1;
         }
-        
-        sprintf(pszKeyUniq, "%s_%d", pszKey, nCount);
+
+        snprintf(pszKeyUniq, nLen, "%s_%d", pszKey, nCount);
         poInfo[pszKeyUniq] = pszValueEnc;
+        CPLFree(pszKeyUniq);
     }
 
     CPLFree(pszKey);
diff --git a/ogr/ogrsf_frmts/vfk/vfkreader.h b/ogr/ogrsf_frmts/vfk/vfkreader.h
index 99fc968..648294a 100644
--- a/ogr/ogrsf_frmts/vfk/vfkreader.h
+++ b/ogr/ogrsf_frmts/vfk/vfkreader.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vfkreader.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: vfkreader.h 32177 2015-12-14 07:25:30Z goatbar $
  *
  * Project:  VFK Reader
  * Purpose:  Public Declarations for OGR free VFK Reader code.
@@ -63,11 +63,11 @@ enum RecordType { RecordValid, RecordSkipped, RecordDuplicated };
 /************************************************************************/
 /*                              VFKProperty                             */
 /************************************************************************/
-class CPL_DLL VFKProperty
+class VFKProperty
 {
 private:
     bool                    m_bIsNull;
-    
+
     int                     m_nValue;
     double                  m_dValue;
     CPLString               m_strValue;
@@ -79,7 +79,7 @@ public:
     explicit VFKProperty(const char*);
     explicit VFKProperty(CPLString const&);
     virtual ~VFKProperty();
-    
+
     VFKProperty(VFKProperty const& other);
     VFKProperty& operator=(VFKProperty const& other);
 
@@ -92,7 +92,7 @@ public:
 /************************************************************************/
 /*                              IVFKFeature                              */
 /************************************************************************/
-class CPL_DLL IVFKFeature
+class IVFKFeature
 {
 protected:
     IVFKDataBlock            *m_poDataBlock;
@@ -116,7 +116,7 @@ public:
     void                 SetGeometryType(OGRwkbGeometryType);
 
     bool                 IsValid() const { return m_bValid; }
-    
+
     IVFKDataBlock       *GetDataBlock() const { return m_poDataBlock; }
     OGRwkbGeometryType   GetGeometryType() const { return m_nGeometryType; }
     bool                 SetGeometry(OGRGeometry *, const char * = NULL);
@@ -129,11 +129,11 @@ public:
 /************************************************************************/
 /*                              VFKFeature                              */
 /************************************************************************/
-class CPL_DLL VFKFeature : public IVFKFeature
+class VFKFeature : public IVFKFeature
 {
 private:
     typedef std::vector<VFKProperty> VFKPropertyList;
-    
+
     VFKPropertyList      m_propertyList;
 
     bool                 SetProperty(int, const char *);
@@ -147,7 +147,7 @@ private:
 
 public:
     VFKFeature(IVFKDataBlock *, GIntBig);
-    
+
     bool                 SetProperties(const char *);
     const VFKProperty   *GetProperty(int) const;
     const VFKProperty   *GetProperty(const char *) const;
@@ -160,7 +160,7 @@ public:
 /************************************************************************/
 /*                              VFKFeatureSQLite                        */
 /************************************************************************/
-class CPL_DLL VFKFeatureSQLite : public IVFKFeature
+class VFKFeatureSQLite : public IVFKFeature
 {
 private:
     int                  m_iRowId;           /* rowid in DB */
@@ -187,7 +187,7 @@ public:
 /************************************************************************/
 /*                              VFKPropertyDefn                         */
 /************************************************************************/
-class CPL_DLL VFKPropertyDefn
+class VFKPropertyDefn
 {
 private:
     char             *m_pszName;
@@ -215,14 +215,14 @@ public:
 /************************************************************************/
 /*                              IVFKDataBlock                           */
 /************************************************************************/
-class CPL_DLL IVFKDataBlock
+class IVFKDataBlock
 {
 private:
     IVFKFeature      **m_papoFeature;
 
     int                m_nPropertyCount;
     VFKPropertyDefn  **m_papoProperty;
-    
+
     int                AddProperty(const char *, const char *);
 
 protected:
@@ -235,16 +235,17 @@ protected:
     OGRwkbGeometryType m_nGeometryType;
     bool               m_bGeometryPerBlock;
 
-    int                m_nFeatureCount;    
+    int                m_nFeatureCount;
     int                m_iNextFeature;
 
+    // TODO: Make m_poReader const.
     IVFKReader        *m_poReader;
 
     GIntBig            m_nRecordCount[3];
-    
+
     bool               AppendLineToRing(PointListArray *, const OGRLineString *, bool, bool = FALSE);
     int                LoadData();
-    
+
     virtual int        LoadGeometryPoint() = 0;
     virtual int        LoadGeometryLineStringSBP() = 0;
     virtual int        LoadGeometryLineStringHP() = 0;
@@ -273,7 +274,7 @@ public:
     IVFKFeature       *GetFirstFeature();
     IVFKFeature       *GetLastFeature();
     int                SetNextFeature(const IVFKFeature *);
-    
+
     OGRwkbGeometryType SetGeometryType();
     OGRwkbGeometryType GetGeometryType() const;
 
@@ -287,7 +288,7 @@ public:
 /************************************************************************/
 /*                              VFKDataBlock                            */
 /************************************************************************/
-class CPL_DLL VFKDataBlock : public IVFKDataBlock
+class VFKDataBlock : public IVFKDataBlock
 {
 private:
     int                LoadGeometryPoint();
@@ -308,7 +309,7 @@ public:
 /************************************************************************/
 /*                              VFKDataBlockSQLite                      */
 /************************************************************************/
-class CPL_DLL VFKDataBlockSQLite : public IVFKDataBlock
+class VFKDataBlockSQLite : public IVFKDataBlock
 {
 private:
     bool                 SetGeometryLineString(VFKFeatureSQLite *, OGRLineString *,
@@ -340,7 +341,7 @@ public:
 /************************************************************************/
 /*                              IVFKReader                              */
 /************************************************************************/
-class CPL_DLL IVFKReader
+class IVFKReader
 {
 private:
     virtual void AddInfo(const char *) = 0;
@@ -352,7 +353,7 @@ protected:
 
 public:
     virtual ~IVFKReader();
-    
+
     virtual bool           IsLatin2() const = 0;
     virtual bool           IsSpatial() const = 0;
     virtual bool           IsPreProcessed() const = 0;
diff --git a/ogr/ogrsf_frmts/vfk/vfkreaderp.h b/ogr/ogrsf_frmts/vfk/vfkreaderp.h
index 4e8a9ac..632a96f 100644
--- a/ogr/ogrsf_frmts/vfk/vfkreaderp.h
+++ b/ogr/ogrsf_frmts/vfk/vfkreaderp.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vfkreaderp.h 26911 2014-02-01 11:46:09Z martinl $
+ * $Id: vfkreaderp.h 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  VFK Reader
  * Purpose:  Private Declarations for OGR free VFK Reader code.
@@ -45,14 +45,14 @@ class VFKReader;
 /************************************************************************/
 /*                              VFKReader                               */
 /************************************************************************/
-class VFKReader : public IVFKReader 
+class VFKReader : public IVFKReader
 {
 private:
     bool           m_bLatin2;
 
     FILE          *m_poFD;
     char          *ReadLine(bool = FALSE);
-    
+
     void          AddInfo(const char *);
 
 protected:
@@ -66,7 +66,7 @@ protected:
 
     /* metadata */
     std::map<CPLString, CPLString> poInfo;
-    
+
 public:
     VFKReader(const char *);
     virtual ~VFKReader();
@@ -77,7 +77,7 @@ public:
     int            ReadDataBlocks();
     int            ReadDataRecords(IVFKDataBlock * = NULL);
     int            LoadGeometry();
-    
+
     int            GetDataBlockCount() const { return m_nDataBlockCount; }
     IVFKDataBlock *GetDataBlock(int) const;
     IVFKDataBlock *GetDataBlock(const char *) const;
@@ -89,7 +89,7 @@ public:
 /*                              VFKReaderSQLite                         */
 /************************************************************************/
 
-class VFKReaderSQLite : public VFKReader 
+class VFKReaderSQLite : public VFKReader
 {
 private:
     char          *m_pszDBname;
@@ -104,7 +104,7 @@ private:
     void           StoreInfo2DB();
 
     void           CreateIndex(const char *, const char *, const char *, bool = TRUE);
-    
+
     friend class   VFKFeatureSQLite;
 public:
     VFKReaderSQLite(const char *);
diff --git a/ogr/ogrsf_frmts/vfk/vfkreadersqlite.cpp b/ogr/ogrsf_frmts/vfk/vfkreadersqlite.cpp
index c62ef9b..ecdde6f 100644
--- a/ogr/ogrsf_frmts/vfk/vfkreadersqlite.cpp
+++ b/ogr/ogrsf_frmts/vfk/vfkreadersqlite.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vfkreadersqlite.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: vfkreadersqlite.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  VFK Reader (SQLite)
  * Purpose:  Implements VFKReaderSQLite class.
@@ -52,55 +52,62 @@
 VFKReaderSQLite::VFKReaderSQLite(const char *pszFilename) : VFKReader(pszFilename)
 {
     const char *pszDbNameConf;
-    CPLString   pszDbName;
+    CPLString   osDbName;
     CPLString   osCommand;
     VSIStatBufL sStatBufDb, sStatBufVfk;
-    
+
     /* open tmp SQLite DB (re-use DB file if already exists) */
     pszDbNameConf = CPLGetConfigOption("OGR_VFK_DB_NAME", NULL);
     if (pszDbNameConf) {
-	pszDbName = pszDbNameConf;
+	osDbName = pszDbNameConf;
     }
     else {
-	pszDbName = CPLResetExtension(m_pszFilename, "db");
+	osDbName = CPLResetExtension(m_pszFilename, "db");
+    }
+    size_t nLen = osDbName.length();
+    if( nLen > 2048 )
+    {
+        nLen = 2048;
+        osDbName.resize(nLen);
     }
-    m_pszDBname = new char [pszDbName.length()+1];
-    std::strcpy(m_pszDBname, pszDbName.c_str());
+    m_pszDBname = new char [nLen+1];
+    std::strncpy(m_pszDBname, osDbName.c_str(), nLen);
+    m_pszDBname[nLen] = 0;
     CPLDebug("OGR-VFK", "Using internal DB: %s",
              m_pszDBname);
-    
-    if (CSLTestBoolean(CPLGetConfigOption("OGR_VFK_DB_SPATIAL", "YES")))
+
+    if (CPLTestBool(CPLGetConfigOption("OGR_VFK_DB_SPATIAL", "YES")))
 	m_bSpatial = TRUE;    /* build geometry from DB */
     else
 	m_bSpatial = FALSE;   /* store also geometry in DB */
-    
+
     m_bNewDb = TRUE;
-    if (VSIStatL(pszDbName, &sStatBufDb) == 0) {
-	if (CSLTestBoolean(CPLGetConfigOption("OGR_VFK_DB_OVERWRITE", "NO"))) {
+    if (VSIStatL(osDbName, &sStatBufDb) == 0) {
+	if (CPLTestBool(CPLGetConfigOption("OGR_VFK_DB_OVERWRITE", "NO"))) {
 	    m_bNewDb = TRUE;     /* overwrite existing DB */
             CPLDebug("OGR-VFK", "Internal DB (%s) already exists and will be overwritten",
                      m_pszDBname);
-	    VSIUnlink(pszDbName);
-	}
-	else {
+	    VSIUnlink(osDbName);
+        }
+        else {
             if (VSIStatL(pszFilename, &sStatBufVfk) == 0 &&
                 sStatBufVfk.st_mtime > sStatBufDb.st_mtime) {
                 CPLDebug("OGR-VFK",
                          "Found %s but ignoring because it appears\n"
                          "be older than the associated VFK file.",
-                         pszDbName.c_str());
+                         osDbName.c_str());
                 m_bNewDb = TRUE;
-                VSIUnlink(pszDbName);
+                VSIUnlink(osDbName);
             }
             else {
-                m_bNewDb = FALSE;    /* re-use exising DB */
+                m_bNewDb = FALSE;    /* re-use existing DB */
             }
-	}
+        }
     }
-    
+
     /*
     if (m_bNewDb) {
-      CPLError(CE_Warning, CPLE_AppDefined, 
+      CPLError(CE_Warning, CPLE_AppDefined,
                "INFO: No internal SQLite DB found. Reading VFK data may take some time...");
     }
     */
@@ -108,16 +115,16 @@ VFKReaderSQLite::VFKReaderSQLite(const char *pszFilename) : VFKReader(pszFilenam
     CPLDebug("OGR-VFK", "New DB: %s Spatial: %s",
 	     m_bNewDb ? "yes" : "no", m_bSpatial ? "yes" : "no");
 
-    if (SQLITE_OK != sqlite3_open(pszDbName, &m_poDB)) {
-        CPLError(CE_Failure, CPLE_AppDefined, 
+    if (SQLITE_OK != sqlite3_open(osDbName, &m_poDB)) {
+        CPLError(CE_Failure, CPLE_AppDefined,
                  "Creating SQLite DB failed");
     }
     else {
         char* pszErrMsg = NULL;
-        sqlite3_exec(m_poDB, "PRAGMA synchronous = OFF", NULL, NULL, &pszErrMsg);
+        CPL_IGNORE_RET_VAL(sqlite3_exec(m_poDB, "PRAGMA synchronous = OFF", NULL, NULL, &pszErrMsg));
         sqlite3_free(pszErrMsg);
     }
-    
+
     if (m_bNewDb) {
         /* new DB, create support metadata tables */
         osCommand.Printf("CREATE TABLE %s (file_name text, table_name text, num_records integer, "
@@ -138,19 +145,20 @@ VFKReaderSQLite::~VFKReaderSQLite()
 {
     /* close tmp SQLite DB */
     if (SQLITE_OK != sqlite3_close(m_poDB)) {
-        CPLError(CE_Failure, CPLE_AppDefined, 
+        CPLError(CE_Failure, CPLE_AppDefined,
                  "Closing SQLite DB failed\n  %s",
                  sqlite3_errmsg(m_poDB));
     }
     CPLDebug("OGR-VFK", "Internal DB (%s) closed",
              m_pszDBname);
-    
+
     /* delete tmp SQLite DB if requested */
-    if (CSLTestBoolean(CPLGetConfigOption("OGR_VFK_DB_DELETE", "NO"))) {
+    if (CPLTestBool(CPLGetConfigOption("OGR_VFK_DB_DELETE", "NO"))) {
         CPLDebug("OGR-VFK", "Internal DB (%s) deleted",
                  m_pszDBname);
         VSIUnlink(m_pszDBname);
     }
+    delete[] m_pszDBname;
 }
 
 /*!
@@ -166,9 +174,9 @@ int VFKReaderSQLite::ReadDataBlocks()
     CPLString osSQL;
     const char *pszName, *pszDefn;
     IVFKDataBlock *poNewDataBlock;
-    
+
     sqlite3_stmt *hStmt;
-    
+
     osSQL.Printf("SELECT table_name, table_defn FROM %s", VFK_DB_TABLE);
     hStmt = PrepareStatement(osSQL.c_str());
     while(ExecuteSQL(hStmt) == OGRERR_NONE) {
@@ -179,16 +187,16 @@ int VFKReaderSQLite::ReadDataBlocks()
         poNewDataBlock->SetProperties(pszDefn);
         VFKReader::AddDataBlock(poNewDataBlock, NULL);
     }
-    
+
     if (m_nDataBlockCount == 0) {
-        sqlite3_exec(m_poDB, "BEGIN", 0, 0, 0);  
+        CPL_IGNORE_RET_VAL(sqlite3_exec(m_poDB, "BEGIN", NULL, NULL, NULL));
         /* CREATE TABLE ... */
         nDataBlocks = VFKReader::ReadDataBlocks();
-        sqlite3_exec(m_poDB, "COMMIT", 0, 0, 0);
+        CPL_IGNORE_RET_VAL(sqlite3_exec(m_poDB, "COMMIT", NULL, NULL, NULL));
 
         StoreInfo2DB();
     }
-    
+
     return nDataBlocks;
 }
 
@@ -196,9 +204,9 @@ int VFKReaderSQLite::ReadDataBlocks()
   \brief Load data records (&D)
 
   Call VFKReader::OpenFile() before this function.
-  
+
   \param poDataBlock limit to selected data block or NULL for all
-  
+
   \return number of data records or -1 on error
 */
 int VFKReaderSQLite::ReadDataRecords(IVFKDataBlock *poDataBlock)
@@ -207,18 +215,17 @@ int VFKReaderSQLite::ReadDataRecords(IVFKDataBlock *poDataBlock)
     int         iDataBlock;
     const char *pszName;
     CPLString   osSQL;
-    
+
     IVFKDataBlock *poDataBlockCurrent;
-    
+
     sqlite3_stmt *hStmt;
-    
+
     pszName = NULL;
-    nDataRecords = 0;
-    
+
     if (poDataBlock) { /* read records only for selected data block */
         /* table name */
         pszName = poDataBlock->GetName();
-        
+
         /* check for existing records (re-use already inserted data) */
         osSQL.Printf("SELECT num_records FROM %s WHERE "
                      "table_name = '%s'",
@@ -232,7 +239,7 @@ int VFKReaderSQLite::ReadDataRecords(IVFKDataBlock *poDataBlock)
     }
     else {
                       /* read all data blocks */
-        
+
         /* check for existing records (re-use already inserted data) */
         osSQL.Printf("SELECT COUNT(*) FROM %s WHERE num_records = -1", VFK_DB_TABLE);
         hStmt = PrepareStatement(osSQL.c_str());
@@ -241,7 +248,7 @@ int VFKReaderSQLite::ReadDataRecords(IVFKDataBlock *poDataBlock)
             nDataRecords = 0;     /* -> read from DB */
         else
             nDataRecords = -1;    /* -> read from VFK file */
-        
+
         sqlite3_finalize(hStmt);
     }
 
@@ -254,12 +261,12 @@ int VFKReaderSQLite::ReadDataRecords(IVFKDataBlock *poDataBlock)
         poDataBlockCurrent = NULL;
         for (iDataBlock = 0; iDataBlock < GetDataBlockCount(); iDataBlock++) {
             poDataBlockCurrent = GetDataBlock(iDataBlock);
-           
+
             if (poDataBlock && poDataBlock != poDataBlockCurrent)
                 continue;
 
             poDataBlockCurrent->SetFeatureCount(0); /* avoid recursive call */
-            
+
             pszName = poDataBlockCurrent->GetName();
             CPLAssert(NULL != pszName);
 
@@ -288,7 +295,7 @@ int VFKReaderSQLite::ReadDataRecords(IVFKDataBlock *poDataBlock)
 
                 nFeatDB = sqlite3_column_int(hStmt, 0);
                 if (nFeatDB > 0 && nFeatDB != poDataBlockCurrent->GetFeatureCount())
-                    CPLError(CE_Failure, CPLE_AppDefined, 
+                    CPLError(CE_Failure, CPLE_AppDefined,
                              "%s: Invalid number of features " CPL_FRMT_GIB " (should be %d)",
                              pszName, poDataBlockCurrent->GetFeatureCount(), nFeatDB);
             }
@@ -298,30 +305,30 @@ int VFKReaderSQLite::ReadDataRecords(IVFKDataBlock *poDataBlock)
     else {                          /* read from VFK file and insert records into DB */
         /* begin transaction */
         ExecuteSQL("BEGIN");
-        
+
         /* INSERT ... */
         nDataRecords = VFKReader::ReadDataRecords(poDataBlock);
 
-        /* update VFK_DB_TABLE table */        
+        /* update VFK_DB_TABLE table */
         poDataBlockCurrent = NULL;
         for (iDataBlock = 0; iDataBlock < GetDataBlockCount(); iDataBlock++) {
             poDataBlockCurrent = GetDataBlock(iDataBlock);
-            
+
             if (poDataBlock && poDataBlock != poDataBlockCurrent)
                 continue;
-            
+
             osSQL.Printf("UPDATE %s SET num_records = %d WHERE "
                          "table_name = '%s'",
                          VFK_DB_TABLE, poDataBlockCurrent->GetRecordCount(),
                          poDataBlockCurrent->GetName());
-            
+
             ExecuteSQL(osSQL);
         }
-        
+
         /* commit transaction */
         ExecuteSQL("COMMIT");
     }
-    
+
     return nDataRecords;
 }
 
@@ -361,7 +368,7 @@ void VFKReaderSQLite::CreateIndex(const char *name, const char *table, const cha
                                   bool unique)
 {
     CPLString   osSQL;
-    
+
     if (unique) {
         osSQL.Printf("CREATE UNIQUE INDEX %s ON %s (%s)",
                      name, table, column);
@@ -384,7 +391,7 @@ void VFKReaderSQLite::CreateIndex(const char *name, const char *table, const cha
 */
 IVFKDataBlock *VFKReaderSQLite::CreateDataBlock(const char *pszBlockName)
 {
-    /* create new data block, ie. table in DB */
+    /* create new data block, i.e. table in DB */
     return new VFKDataBlockSQLite(pszBlockName, (IVFKReader *) this);
 }
 
@@ -399,24 +406,24 @@ void VFKReaderSQLite::AddDataBlock(IVFKDataBlock *poDataBlock, const char *pszDe
     const char *pszKey;
     CPLString   osCommand, osColumn;
     bool        bUnique;
-        
+
     VFKPropertyDefn *poPropertyDefn;
-    
+
     sqlite3_stmt *hStmt;
 
-    bUnique = !CSLTestBoolean(CPLGetConfigOption("OGR_VFK_DB_IGNORE_DUPLICATES", "NO"));
-    
+    bUnique = !CPLTestBool(CPLGetConfigOption("OGR_VFK_DB_IGNORE_DUPLICATES", "NO"));
+
     pszBlockName = poDataBlock->GetName();
-    
+
     /* register table in VFK_DB_TABLE */
     osCommand.Printf("SELECT COUNT(*) FROM %s WHERE "
                      "table_name = '%s'",
                      VFK_DB_TABLE, pszBlockName);
     hStmt = PrepareStatement(osCommand.c_str());
-    
+
     if (ExecuteSQL(hStmt) == OGRERR_NONE &&
         sqlite3_column_int(hStmt, 0) == 0) {
-        
+
         osCommand.Printf("CREATE TABLE '%s' (", pszBlockName);
         for (int i = 0; i < poDataBlock->GetPropertyCount(); i++) {
             poPropertyDefn = poDataBlock->GetProperty(i);
@@ -434,18 +441,18 @@ void VFKReaderSQLite::AddDataBlock(IVFKDataBlock *poDataBlock, const char *pszDe
 	}
 	osCommand += ")";
         ExecuteSQL(osCommand.c_str()); /* CREATE TABLE */
-        
-        /* create indeces */
+
+        /* create indices */
         osCommand.Printf("%s_%s", pszBlockName, FID_COLUMN);
         CreateIndex(osCommand.c_str(), pszBlockName, FID_COLUMN,
                     !EQUAL(pszBlockName, "SBP"));
-        
+
         pszKey = ((VFKDataBlockSQLite *) poDataBlock)->GetKey();
         if (pszKey) {
             osCommand.Printf("%s_%s", pszBlockName, pszKey);
             CreateIndex(osCommand.c_str(), pszBlockName, pszKey, bUnique);
         }
-        
+
         if (EQUAL(pszBlockName, "SBP")) {
             /* create extra indices for SBP */
             CreateIndex("SBP_OB",        pszBlockName, "OB_ID", FALSE);
@@ -465,24 +472,24 @@ void VFKReaderSQLite::AddDataBlock(IVFKDataBlock *poDataBlock, const char *pszDe
             /* create extra indices for OP */
             CreateIndex("OB_BUD",        pszBlockName, "BUD_ID", FALSE);
         }
-        
+
         /* update VFK_DB_TABLE meta-table */
         osCommand.Printf("INSERT INTO %s (file_name, table_name, "
                          "num_records, num_features, num_geometries, table_defn) VALUES "
 			 "('%s', '%s', -1, 0, 0, '%s')",
 			 VFK_DB_TABLE, m_pszFilename, pszBlockName, pszDefn);
-	
+
         ExecuteSQL(osCommand.c_str());
 
         sqlite3_finalize(hStmt);
     }
-        
+
     return VFKReader::AddDataBlock(poDataBlock, NULL);
 }
 
 /*!
   \brief Prepare SQL statement
-  
+
   \param pszSQLCommand SQL statement to be prepared
 
   \return pointer to sqlite3_stmt instance or NULL on error
@@ -491,21 +498,21 @@ sqlite3_stmt *VFKReaderSQLite::PrepareStatement(const char *pszSQLCommand)
 {
     int rc;
     sqlite3_stmt *hStmt = NULL;
-    
+
     CPLDebug("OGR-VFK", "VFKReaderSQLite::PrepareStatement(): %s", pszSQLCommand);
 
-    rc = sqlite3_prepare(m_poDB, pszSQLCommand, strlen(pszSQLCommand),
+    rc = sqlite3_prepare(m_poDB, pszSQLCommand, -1,
                          &hStmt, NULL);
-    
+
     if (rc != SQLITE_OK) {
-        CPLError(CE_Failure, CPLE_AppDefined, 
+        CPLError(CE_Failure, CPLE_AppDefined,
                  "In PrepareStatement(): sqlite3_prepare(%s):\n  %s",
                  pszSQLCommand, sqlite3_errmsg(m_poDB));
-        
+
         if(hStmt != NULL) {
             sqlite3_finalize(hStmt);
         }
-        
+
         return NULL;
     }
 
@@ -515,14 +522,14 @@ sqlite3_stmt *VFKReaderSQLite::PrepareStatement(const char *pszSQLCommand)
 /*!
   \brief Execute prepared SQL statement
 
-  \param hStmt pointer to sqlite3_stmt 
+  \param hStmt pointer to sqlite3_stmt
 
   \return OGRERR_NONE on success
 */
 OGRErr VFKReaderSQLite::ExecuteSQL(sqlite3_stmt *hStmt)
 {
     int rc;
-    
+
     // assert
 
     rc = sqlite3_step(hStmt);
@@ -531,15 +538,15 @@ OGRErr VFKReaderSQLite::ExecuteSQL(sqlite3_stmt *hStmt)
             sqlite3_finalize(hStmt);
             return OGRERR_NOT_ENOUGH_DATA;
         }
-        
-        CPLError(CE_Failure, CPLE_AppDefined, 
-                 "In ExecuteSQL(): sqlite3_step:\n  %s", 
+
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "In ExecuteSQL(): sqlite3_step:\n  %s",
                  sqlite3_errmsg(m_poDB));
         if (hStmt)
             sqlite3_finalize(hStmt);
         return OGRERR_FAILURE;
     }
-    
+
     return OGRERR_NONE;
 
 }
@@ -555,17 +562,17 @@ OGRErr VFKReaderSQLite::ExecuteSQL(sqlite3_stmt *hStmt)
 OGRErr VFKReaderSQLite::ExecuteSQL(const char *pszSQLCommand, bool bQuiet)
 {
     char *pszErrMsg = NULL;
-    
+
     if (SQLITE_OK != sqlite3_exec(m_poDB, pszSQLCommand, NULL, NULL, &pszErrMsg)) {
         if (!bQuiet)
-            CPLError(CE_Failure, CPLE_AppDefined, 
+            CPLError(CE_Failure, CPLE_AppDefined,
                      "In ExecuteSQL(%s): %s",
                      pszSQLCommand, pszErrMsg);
         else
-            CPLError(CE_Warning, CPLE_AppDefined, 
+            CPLError(CE_Warning, CPLE_AppDefined,
                      "In ExecuteSQL(%s): %s",
                      pszSQLCommand, pszErrMsg);
-        
+
         return  OGRERR_FAILURE;
     }
 
@@ -582,7 +589,7 @@ OGRErr VFKReaderSQLite::AddFeature(IVFKDataBlock *poDataBlock, VFKFeature *poFea
 {
     CPLString     osCommand;
     CPLString     osValue;
-    
+
     const char   *pszBlockName;
 
     OGRFieldType  ftype;
@@ -590,10 +597,10 @@ OGRErr VFKReaderSQLite::AddFeature(IVFKDataBlock *poDataBlock, VFKFeature *poFea
     const VFKProperty *poProperty;
 
     VFKFeatureSQLite *poNewFeature;
-    
+
     pszBlockName = poDataBlock->GetName();
     osCommand.Printf("INSERT INTO '%s' VALUES(", pszBlockName);
-    
+
     for (int i = 0; i < poDataBlock->GetPropertyCount(); i++) {
         ftype = poDataBlock->GetProperty(i)->GetType();
         poProperty = poFeature->GetProperty(i);
@@ -631,17 +638,21 @@ OGRErr VFKReaderSQLite::AddFeature(IVFKDataBlock *poDataBlock, VFKFeature *poFea
 
     if (ExecuteSQL(osCommand.c_str(), TRUE) != OGRERR_NONE)
         return OGRERR_FAILURE;
-    
+
     if (EQUAL(pszBlockName, "SBP")) {
         poProperty = poFeature->GetProperty("PORADOVE_CISLO_BODU");
-        CPLAssert(NULL != poProperty);
+        if( poProperty == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Cannot find property PORADOVE_CISLO_BODU");
+            return OGRERR_FAILURE;
+        }
         if (!EQUAL(poProperty->GetValueS(), "1"))
             return OGRERR_NONE;
     }
-        
+
     poNewFeature = new VFKFeatureSQLite(poDataBlock, poDataBlock->GetRecordCount(RecordValid) + 1,
                                         poFeature->GetFID());
     poDataBlock->AddFeature(poNewFeature);
-    
+
     return OGRERR_NONE;
 }
diff --git a/ogr/ogrsf_frmts/vrt/drv_vrt.html b/ogr/ogrsf_frmts/vrt/drv_vrt.html
index 258ecb1..3f6d7f9 100644
--- a/ogr/ogrsf_frmts/vrt/drv_vrt.html
+++ b/ogr/ogrsf_frmts/vrt/drv_vrt.html
@@ -12,7 +12,7 @@ drivers based on criteria specified in an XML control file.  It is primarily
 used to derive spatial layers from flat tables with spatial information in
 attribute columns.  It can also be used to associate coordinate system
 information with a datasource, merge layers from different datasources into
-a single data source, or even just to provide an anchor file for access to 
+a single data source, or even just to provide an anchor file for access to
 non-file oriented datasources.<p>
 
 The virtual files are currently normally prepared by hand.<p>
@@ -43,7 +43,7 @@ schema will be used to validate the VRT documents. Non-conformities will be repo
 warnings. That validation can be disabled by setting the GDAL_XML_VALIDATION configuration option to NO.<p>
 
 <p>
-<b>Metadata</b> (optional): (GDAL >= 2.0) This element contains a list of metadata name/value 
+<b>Metadata</b> (optional): (GDAL >= 2.0) This element contains a list of metadata name/value
 pairs associated with the dataset as a whole. It has
 <MDI> (metadata item) subelements which have a "key" attribute and the value
 as the data of the element. The Metadata element can be repeated multiple times,
@@ -70,7 +70,7 @@ options as child elements of the form <OOI key="key_name">value_name</O
 
 <br>
 
-<li> <b>Metadata</b> (optional): (GDAL >= 2.0) This element contains a list of metadata name/value 
+<li> <b>Metadata</b> (optional): (GDAL >= 2.0) This element contains a list of metadata name/value
 pairs associated with the layer as a whole. It has
 <MDI> (metadata item) subelements which have a "key" attribute and the value
 as the data of the element. The Metadata element can be repeated multiple times,
@@ -88,7 +88,7 @@ element isn't provided, then the SrcSQL element must be provided.</li>
 
 <li> <b>SrcSQL</b> (optional): An SQL statement to execute to generate the
 desired layer result.  This should be provided instead of the SrcLayer for
-statement derived results.   Some limitations may apply for SQL derived 
+statement derived results.   Some limitations may apply for SQL derived
 layers. Starting with OGR 1.10, an optional <b>dialect</b> attribute can be specified
 on the SrcSQL element to specify which SQL "dialect" should be used :
 possible values are currently <a href="ogr_sql.html">OGRSQL</a> or
@@ -97,7 +97,7 @@ the default dialect of the datasource will be used.</li>
 
 <br>
 
-<li> <b>FID</b> (optional): Name of the attribute column from which the 
+<li> <b>FID</b> (optional): Name of the attribute column from which the
 FID of features should be derived.  If not provided, the FID of the source
 features will be used directly. The layer will report the FID column name only
 if it is also reported as a regular field. Starting with GDAL 2.0, a "name"
@@ -106,19 +106,19 @@ always reported.</li>
 
 <br>
 
-<li> <b>Style</b> (optional): Name of the attribute column from which the 
+<li> <b>Style</b> (optional): Name of the attribute column from which the
 style of features should be derived.  If not provided, the style of the source
 features will be used directly.</li>
 
 <br>
 
-<li> <b>GeometryType</b> (optional): The geometry type to be assigned to the 
-layer. 
+<li> <b>GeometryType</b> (optional): The geometry type to be assigned to the
+layer.
 If not provided it will be taken from the source layer.  The value should
-be one of "wkbNone", "wkbUnknown", "wkbPoint", "wkbLineString", "wkbPolygon", 
-"wkbMultiPoint", 
-"wkbMultiLineString", "wkbMultiPolygon", or "wkbGeometryCollection".  
-Optionally "25D" may be appended to mark it as including Z coordinates.  
+be one of "wkbNone", "wkbUnknown", "wkbPoint", "wkbLineString", "wkbPolygon",
+"wkbMultiPoint",
+"wkbMultiLineString", "wkbMultiPolygon", or "wkbGeometryCollection".
+Optionally "25D" may be appended to mark it as including Z coordinates.
 Defaults to "wkbUnknown" indicating that any geometry type is allowed.</li>
 
 <br>
@@ -176,7 +176,7 @@ element to wkbNone.
 </p>
 <br>
 
-<li> <b>SrcRegion</b> (optionnal, from GDAL 1.7.0) : This element is used
+<li> <b>SrcRegion</b> (optional, from GDAL 1.7.0) : This element is used
 to define an initial spatial filter for the source features. This spatial
 filter will be combined with any spatial filter explicitly set on the VRT
 layer with the SetSpatialFilter() method. The value of the element must be
@@ -186,16 +186,16 @@ the source geometries are not modified.</li>
 
 <br>
 
-<li> <b>Field</b> (optional, from GDAL 1.7.0): One or more attribute fields 
-may be defined with Field elements.  If no Field elements are defined, the 
-fields of the source layer/sql will be defined on the VRT layer.  The Field 
+<li> <b>Field</b> (optional, from GDAL 1.7.0): One or more attribute fields
+may be defined with Field elements.  If no Field elements are defined, the
+fields of the source layer/sql will be defined on the VRT layer.  The Field
 may have the following attributes:
 <ul>
 <li> <b>name</b> (required): the name of the field.
-<li> <b>type</b>: the field type, one of "Integer", "IntegerList", 
-"Real", "RealList", "String", "StringList", "Binary", "Date", "Time", 
+<li> <b>type</b>: the field type, one of "Integer", "IntegerList",
+"Real", "RealList", "String", "StringList", "Binary", "Date", "Time",
 or "DateTime". Defaults to "String".
-<li> <b>subtype</b>: (GDAL >= 2.0) the field subtype, one of "None", "Boolean", 
+<li> <b>subtype</b>: (GDAL >= 2.0) the field subtype, one of "None", "Boolean",
 "Int16", "Float32". Defaults to "None".
 <li> <b>width</b>: the field width. Defaults to unknown.
 <li> <b>precision</b>: the field width. Defaults to zero.
@@ -309,18 +309,18 @@ the following sub-elements <b>GeometryType</b>, <b>SRS</b> and <b>Extent[X|Y][Mi
 <h2>Example: ODBC Point Layer</h2>
 
 In the following example (disease.ovf) the worms table from the ODBC
-database DISEASE is used to form a spatial layer.  The virtual file 
+database DISEASE is used to form a spatial layer.  The virtual file
 uses the "x" and "y" columns to get the spatial location.  It also marks
 the layer as a point layer, and as being in the WGS84 coordinate system.<p>
 
 <pre><OGRVRTDataSource>
 
     <OGRVRTLayer name="worms">
-        <SrcDataSource>ODBC:DISEASE,worms</SrcDataSource> 
- 	<SrcLayer>worms</SrcLayer> 
-	<GeometryType>wkbPoint</GeometryType> 
+        <SrcDataSource>ODBC:DISEASE,worms</SrcDataSource>
+ 	<SrcLayer>worms</SrcLayer>
+	<GeometryType>wkbPoint</GeometryType>
         <LayerSRS>WGS84</LayerSRS>
-	<GeometryField encoding="PointFromColumns" x="x" y="y"/> 
+	<GeometryField encoding="PointFromColumns" x="x" y="y"/>
     </OGRVRTLayer>
 
 </OGRVRTDataSource>
@@ -329,8 +329,8 @@ the layer as a point layer, and as being in the WGS84 coordinate system.<p>
 <h2>Example: Renaming attributes</h2>
 
 It can be useful in some circumstances to be able to rename the field names
-from a source layer to other names. This is particularly true when you want 
-to transcode to a format whose schema is fixed, such as GPX 
+from a source layer to other names. This is particularly true when you want
+to transcode to a format whose schema is fixed, such as GPX
 (<name>, <desc&gt, etc.).  This can be accomplished using
 SQL this way:<p>
 
@@ -405,12 +405,12 @@ and source2.shp.<p>
 
 The following example will return four different layers which are generated in a fly
 from the same polygon shapefile. The first one is the shapefile layer as it stands.
-The second layer gives simplified polygons by applying Spatialite function "Simplify"
+The second layer gives simplified polygons by applying SpatiaLite function "Simplify"
 with parameter tolerance=10. In the third layer the original geometries are replaced by
-their convace hulls. In the fourth layer Spatialite function PointOnSurface is used for
+their convex hulls. In the fourth layer SpatiaLite function PointOnSurface is used for
 replacing the original geometries by points which are inside the corresponding source
 polygons. Note that for using the last three layers of this VRT file GDAL must be
-compiled with SQLite and Spatialite.<p>
+compiled with SQLite and SpatiaLite.<p>
 
 <pre>
 <OGRVRTDataSource>
diff --git a/ogr/ogrsf_frmts/vrt/ogr_vrt.h b/ogr/ogrsf_frmts/vrt/ogr_vrt.h
index bd4ccfc..1d2d0ba 100644
--- a/ogr/ogrsf_frmts/vrt/ogr_vrt.h
+++ b/ogr/ogrsf_frmts/vrt/ogr_vrt.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_vrt.h 28522 2015-02-18 14:16:40Z rouault $
+ * $Id: ogr_vrt.h 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/VRT driver.
@@ -28,8 +28,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_VRT_H_INCLUDED
-#define _OGR_VRT_H_INCLUDED
+#ifndef OGR_VRT_H_INCLUDED
+#define OGR_VRT_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "cpl_error.h"
@@ -40,11 +40,11 @@
 #include <string>
 #include <set>
 
-typedef enum { 
+typedef enum {
     VGS_None,
     VGS_Direct,
-    VGS_PointFromColumns, 
-    VGS_WKT, 
+    VGS_PointFromColumns,
+    VGS_WKT,
     VGS_WKB,
     VGS_Shape
 } OGRVRTGeometryStyle;
@@ -75,7 +75,7 @@ class OGRVRTGeomFieldProps
         int                 bUseSpatialSubquery;
 
         OGREnvelope         sStaticEnvelope;
-        
+
         int                 bNullable;
 
                         OGRVRTGeomFieldProps();
@@ -111,7 +111,7 @@ class OGRVRTLayer : public OGRLayer
 
     char                *pszAttrFilter;
 
-    int                 iFIDField; // -1 means pass through. 
+    int                 iFIDField; // -1 means pass through.
     CPLString           osFIDFieldName;
     int                 iStyleField; // -1 means pass through.
 
@@ -154,7 +154,7 @@ class OGRVRTLayer : public OGRLayer
 /*      Caution : all the below methods should care of calling          */
 /*      FullInitialize() if not already done                            */
 /* -------------------------------------------------------------------- */
-    
+
     virtual void        ResetReading();
     virtual OGRFeature *GetNextFeature();
 
@@ -214,7 +214,7 @@ class OGRVRTDataSource : public OGRDataSource
     OGRLayer          **papoLayers;
     OGRLayerType       *paeLayerType;
     int                 nLayers;
-    
+
     char               *pszName;
 
     CPLXMLNode         *psTree;
@@ -223,11 +223,11 @@ class OGRVRTDataSource : public OGRDataSource
 
     std::set<std::string> aosOtherDSNameSet;
 
-    OGRLayer*           InstanciateWarpedLayer(CPLXMLNode *psLTree,
+    OGRLayer*           InstantiateWarpedLayer(CPLXMLNode *psLTree,
                                                const char *pszVRTDirectory,
                                                int bUpdate,
                                                int nRecLevel);
-    OGRLayer*           InstanciateUnionLayer(CPLXMLNode *psLTree,
+    OGRLayer*           InstantiateUnionLayer(CPLXMLNode *psLTree,
                                                const char *pszVRTDirectory,
                                                int bUpdate,
                                                int nRecLevel);
@@ -241,12 +241,14 @@ class OGRVRTDataSource : public OGRDataSource
                         OGRVRTDataSource(GDALDriver* poDriver);
                         ~OGRVRTDataSource();
 
-    OGRLayer*           InstanciateLayer(CPLXMLNode *psLTree,
+    virtual int         CloseDependentDatasets();
+
+    OGRLayer*           InstantiateLayer(CPLXMLNode *psLTree,
                                     const char *pszVRTDirectory,
                                     int bUpdate,
                                     int nRecLevel = 0);
 
-    OGRLayer*           InstanciateLayerInternal(CPLXMLNode *psLTree,
+    OGRLayer*           InstantiateLayerInternal(CPLXMLNode *psLTree,
                                             const char *pszVRTDirectory,
                                             int bUpdate,
                                             int nRecLevel);
@@ -279,6 +281,4 @@ class OGRVRTDataSource : public OGRDataSource
 
 OGRwkbGeometryType OGRVRTGetGeometryType(const char* pszGType, int* pbError);
 
-#endif /* ndef _OGR_VRT_H_INCLUDED */
-
-
+#endif /* ndef OGR_VRT_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/vrt/ogrvrtdatasource.cpp b/ogr/ogrsf_frmts/vrt/ogrvrtdatasource.cpp
index 9ff2349..98a3c24 100644
--- a/ogr/ogrsf_frmts/vrt/ogrvrtdatasource.cpp
+++ b/ogr/ogrsf_frmts/vrt/ogrvrtdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrvrtdatasource.cpp 28950 2015-04-18 23:24:49Z rouault $
+ * $Id: ogrvrtdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRVRTDataSource class.
@@ -34,7 +34,7 @@
 #include "ogrwarpedlayer.h"
 #include "ogrunionlayer.h"
 
-CPL_CVSID("$Id: ogrvrtdatasource.cpp 28950 2015-04-18 23:24:49Z rouault $");
+CPL_CVSID("$Id: ogrvrtdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 /************************************************************************/
 /*                       OGRVRTGetGeometryType()                        */
@@ -60,18 +60,20 @@ static const OGRGeomTypeName asGeomTypeNames[] = { /* 25D versions are implicit
     { wkbCurvePolygon, "wkbCurvePolygon" },
     { wkbGeometryCollection, "wkbMultiCurve" },
     { wkbMultiSurface, "wkbMultiSurface" },
+    { wkbCurve, "wkbCurve" },
+    { wkbSurface, "wkbSurface" },
     { wkbNone, "wkbNone" },
     { wkbNone, NULL }
 };
 
 OGRwkbGeometryType OGRVRTGetGeometryType(const char* pszGType, int* pbError)
 {
-    int iType;
-    OGRwkbGeometryType eGeomType = wkbUnknown;
-
     if (pbError)
         *pbError = FALSE;
 
+    OGRwkbGeometryType eGeomType = wkbUnknown;
+    int iType;
+
     for( iType = 0; asGeomTypeNames[iType].pszName != NULL; iType++ )
     {
         if( EQUALN(pszGType, asGeomTypeNames[iType].pszName,
@@ -81,6 +83,8 @@ OGRwkbGeometryType OGRVRTGetGeometryType(const char* pszGType, int* pbError)
 
             if( strstr(pszGType,"25D") != NULL || strstr(pszGType,"Z") != NULL )
                 eGeomType = wkbSetZ(eGeomType);
+            if( strstr(pszGType,"M") != NULL )
+                eGeomType = wkbSetM(eGeomType);
             break;
         }
     }
@@ -98,19 +102,18 @@ OGRwkbGeometryType OGRVRTGetGeometryType(const char* pszGType, int* pbError)
 /*                          OGRVRTDataSource()                          */
 /************************************************************************/
 
-OGRVRTDataSource::OGRVRTDataSource(GDALDriver* poDriver)
-
+OGRVRTDataSource::OGRVRTDataSource(GDALDriver* poDriverIn) :
+    papoLayers(NULL),
+    paeLayerType(NULL),
+    nLayers(0),
+    pszName(NULL),
+    psTree(NULL),
+    nCallLevel(0),
+    poLayerPool(NULL),
+    poParentDS(NULL),
+    bRecursionDetected(FALSE)
 {
-    pszName = NULL;
-    papoLayers = NULL;
-    paeLayerType = NULL;
-    nLayers = 0;
-    psTree = NULL;
-    nCallLevel = 0;
-    poLayerPool = NULL;
-    poParentDS = NULL;
-    bRecursionDetected = FALSE;
-    this->poDriver = poDriver;
+    this->poDriver = poDriverIn;
 }
 
 /************************************************************************/
@@ -120,14 +123,10 @@ OGRVRTDataSource::OGRVRTDataSource(GDALDriver* poDriver)
 OGRVRTDataSource::~OGRVRTDataSource()
 
 {
-    int         i;
-
     CPLFree( pszName );
 
-    for( i = 0; i < nLayers; i++ )
-        delete papoLayers[i];
-    
-    CPLFree( papoLayers );
+    CloseDependentDatasets();
+
     CPLFree( paeLayerType );
 
     if( psTree != NULL)
@@ -137,10 +136,27 @@ OGRVRTDataSource::~OGRVRTDataSource()
 }
 
 /************************************************************************/
-/*                        InstanciateWarpedLayer()                      */
+/*                        CloseDependentDatasets()                      */
+/************************************************************************/
+
+int OGRVRTDataSource::CloseDependentDatasets()
+{
+    int bHasClosedDependentDatasets = (nLayers > 0);
+    for( int i = 0; i < nLayers; i++ )
+    {
+        delete papoLayers[i];
+    }
+    CPLFree( papoLayers );
+    nLayers = 0;
+    papoLayers = NULL;
+    return bHasClosedDependentDatasets;
+}
+
+/************************************************************************/
+/*                        InstantiateWarpedLayer()                      */
 /************************************************************************/
 
-OGRLayer*  OGRVRTDataSource::InstanciateWarpedLayer(
+OGRLayer*  OGRVRTDataSource::InstantiateWarpedLayer(
                                         CPLXMLNode *psLTree,
                                         const char *pszVRTDirectory,
                                         int bUpdate,
@@ -149,17 +165,16 @@ OGRLayer*  OGRVRTDataSource::InstanciateWarpedLayer(
     if( !EQUAL(psLTree->pszValue,"OGRVRTWarpedLayer") )
         return NULL;
 
-    CPLXMLNode *psSubNode;
     OGRLayer* poSrcLayer = NULL;
 
-    for( psSubNode=psLTree->psChild;
+    for( CPLXMLNode *psSubNode=psLTree->psChild;
          psSubNode != NULL;
          psSubNode=psSubNode->psNext )
     {
         if( psSubNode->eType != CXT_Element )
             continue;
 
-        poSrcLayer = InstanciateLayer(psSubNode, pszVRTDirectory,
+        poSrcLayer = InstantiateLayer(psSubNode, pszVRTDirectory,
                                  bUpdate, nRecLevel + 1);
         if( poSrcLayer != NULL )
             break;
@@ -168,7 +183,7 @@ OGRLayer*  OGRVRTDataSource::InstanciateWarpedLayer(
     if( poSrcLayer == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Cannot instanciate source layer" );
+                  "Cannot instantiate source layer" );
         return NULL;
     }
 
@@ -195,15 +210,17 @@ OGRLayer*  OGRVRTDataSource::InstanciateWarpedLayer(
         }
     }
 
-    OGRSpatialReference* poSrcSRS;
-    OGRSpatialReference* poTargetSRS;
+    OGRSpatialReference* poSrcSRS = NULL;
     const char* pszSourceSRS = CPLGetXMLValue(psLTree, "SrcSRS", NULL);
 
     if( pszSourceSRS == NULL )
     {
-        poSrcSRS = poSrcLayer->GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetSpatialRef();
-        if( poSrcSRS != NULL)
-            poSrcSRS = poSrcSRS->Clone();
+        if( iGeomField < poSrcLayer->GetLayerDefn()->GetGeomFieldCount() )
+        {
+            poSrcSRS = poSrcLayer->GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetSpatialRef();
+            if( poSrcSRS != NULL)
+                poSrcSRS = poSrcSRS->Clone();
+        }
     }
     else
     {
@@ -223,7 +240,7 @@ OGRLayer*  OGRVRTDataSource::InstanciateWarpedLayer(
         return NULL;
     }
 
-    poTargetSRS = new OGRSpatialReference();
+    OGRSpatialReference* poTargetSRS = new OGRSpatialReference();
     if( poTargetSRS->SetFromUserInput(pszTargetSRS) != OGRERR_NONE )
     {
         delete poTargetSRS;
@@ -287,17 +304,15 @@ OGRLayer*  OGRVRTDataSource::InstanciateWarpedLayer(
 }
 
 /************************************************************************/
-/*                        InstanciateUnionLayer()                       */
+/*                        InstantiateUnionLayer()                       */
 /************************************************************************/
 
-OGRLayer*  OGRVRTDataSource::InstanciateUnionLayer(
+OGRLayer*  OGRVRTDataSource::InstantiateUnionLayer(
                                         CPLXMLNode *psLTree,
                                         const char *pszVRTDirectory,
                                         int bUpdate,
                                         int nRecLevel)
 {
-    CPLXMLNode *psSubNode;
-
     if( !EQUAL(psLTree->pszValue,"OGRVRTUnionLayer") )
         return NULL;
 
@@ -310,7 +325,7 @@ OGRLayer*  OGRVRTDataSource::InstanciateUnionLayer(
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Missing name attribute on OGRVRTUnionLayer" );
-        return FALSE;
+        return NULL;
     }
 
 /* -------------------------------------------------------------------- */
@@ -351,7 +366,7 @@ OGRLayer*  OGRVRTDataSource::InstanciateUnionLayer(
              {
                  CPLError( CE_Failure, CPLE_AppDefined,
                            "Failed to import LayerSRS `%s'.", pszLayerSRS );
-                 return FALSE;
+                 return NULL;
              }
              poGlobalSRS = oSRS.Clone();
          }
@@ -365,6 +380,7 @@ OGRLayer*  OGRVRTDataSource::InstanciateUnionLayer(
     OGRUnionLayerGeomFieldDefn** papoGeomFields = NULL;
     int nGeomFields = 0;
 
+    CPLXMLNode *psSubNode;
     for( psSubNode=psLTree->psChild;
          psSubNode != NULL;
          psSubNode=psSubNode->psNext )
@@ -377,15 +393,15 @@ OGRLayer*  OGRVRTDataSource::InstanciateUnionLayer(
 /* -------------------------------------------------------------------- */
 /*      Field name.                                                     */
 /* -------------------------------------------------------------------- */
-             const char *pszName = CPLGetXMLValue( psSubNode, "name", NULL );
-             if( pszName == NULL )
+             const char *l_pszName = CPLGetXMLValue( psSubNode, "name", NULL );
+             if( l_pszName == NULL )
              {
                  CPLError( CE_Failure, CPLE_AppDefined,
                            "Unable to identify Field name." );
                  break;
              }
 
-             OGRFieldDefn oFieldDefn( pszName, OFTString );
+             OGRFieldDefn oFieldDefn( l_pszName, OFTString );
 
 /* -------------------------------------------------------------------- */
 /*      Type                                                            */
@@ -423,7 +439,7 @@ OGRLayer*  OGRVRTDataSource::InstanciateUnionLayer(
              {
                 CPLError( CE_Failure, CPLE_IllegalArg,
                           "Invalid width for field %s.",
-                          pszName );
+                          l_pszName );
                 break;
              }
              oFieldDefn.SetWidth(nWidth);
@@ -433,7 +449,7 @@ OGRLayer*  OGRVRTDataSource::InstanciateUnionLayer(
              {
                 CPLError( CE_Failure, CPLE_IllegalArg,
                           "Invalid precision for field %s.",
-                          pszName );
+                          l_pszName );
                 break;
              }
              oFieldDefn.SetPrecision(nPrecision);
@@ -447,8 +463,8 @@ OGRLayer*  OGRVRTDataSource::InstanciateUnionLayer(
          else if( psSubNode->eType == CXT_Element &&
                   EQUAL(psSubNode->pszValue,"GeometryField") )
          {
-             const char *pszName = CPLGetXMLValue( psSubNode, "name", NULL );
-             if( pszName == NULL )
+             const char *l_pszName = CPLGetXMLValue( psSubNode, "name", NULL );
+             if( l_pszName == NULL )
              {
                  CPLError( CE_Failure, CPLE_AppDefined,
                            "Unable to identify GeometryField name." );
@@ -497,7 +513,7 @@ OGRLayer*  OGRVRTDataSource::InstanciateUnionLayer(
              }
 
              OGRUnionLayerGeomFieldDefn* poFieldDefn =
-                    new OGRUnionLayerGeomFieldDefn(pszName, eGeomType);
+                    new OGRUnionLayerGeomFieldDefn(l_pszName, eGeomType);
              if( poSRS != NULL )
              {
                 poFieldDefn->SetSpatialRef(poSRS);
@@ -583,7 +599,7 @@ OGRLayer*  OGRVRTDataSource::InstanciateUnionLayer(
         if( psSubNode->eType != CXT_Element )
             continue;
 
-        OGRLayer* poSrcLayer = InstanciateLayer(psSubNode, pszVRTDirectory,
+        OGRLayer* poSrcLayer = InstantiateLayer(psSubNode, pszVRTDirectory,
                                            bUpdate, nRecLevel + 1);
         if( poSrcLayer != NULL )
         {
@@ -629,7 +645,7 @@ OGRLayer*  OGRVRTDataSource::InstanciateUnionLayer(
     int bPreserveSrcFID = FALSE;
     const char* pszPreserveFID = CPLGetXMLValue( psLTree, "PreserveSrcFID", NULL );
     if( pszPreserveFID != NULL )
-        bPreserveSrcFID = CSLTestBoolean(pszPreserveFID);
+        bPreserveSrcFID = CPLTestBool(pszPreserveFID);
     poLayer->SetPreserveSrcFID(bPreserveSrcFID);
 
 /* -------------------------------------------------------------------- */
@@ -662,11 +678,11 @@ OGRLayer*  OGRVRTDataSource::InstanciateUnionLayer(
     poLayer->SetFields(eFieldStrategy, nFields, papoFields,
                        (nGeomFields == 0 && eGlobalGeomType == wkbNone) ? -1 : nGeomFields,
                        papoGeomFields);
-    int iField;
-    for(iField = 0; iField < nFields; iField++)
+
+    for(int iField = 0; iField < nFields; iField++)
         delete papoFields[iField];
     CPLFree(papoFields);
-    for(iField = 0; iField < nGeomFields; iField++)
+    for(int iField = 0; iField < nGeomFields; iField++)
         delete papoGeomFields[iField];
     CPLFree(papoGeomFields);
 
@@ -683,10 +699,10 @@ OGRLayer*  OGRVRTDataSource::InstanciateUnionLayer(
 }
 
 /************************************************************************/
-/*                     InstanciateLayerInternal()                       */
+/*                     InstantiateLayerInternal()                       */
 /************************************************************************/
 
-OGRLayer* OGRVRTDataSource::InstanciateLayerInternal(CPLXMLNode *psLTree,
+OGRLayer* OGRVRTDataSource::InstantiateLayerInternal(CPLXMLNode *psLTree,
                                                 const char *pszVRTDirectory,
                                                 int bUpdate,
                                                 int nRecLevel)
@@ -708,12 +724,12 @@ OGRLayer* OGRVRTDataSource::InstanciateLayerInternal(CPLXMLNode *psLTree,
     }
     else if( EQUAL(psLTree->pszValue,"OGRVRTWarpedLayer") && nRecLevel < 30 )
     {
-        return InstanciateWarpedLayer( psLTree, pszVRTDirectory,
+        return InstantiateWarpedLayer( psLTree, pszVRTDirectory,
                                        bUpdate, nRecLevel + 1 );
     }
     else if( EQUAL(psLTree->pszValue,"OGRVRTUnionLayer") && nRecLevel < 30 )
     {
-        return InstanciateUnionLayer( psLTree, pszVRTDirectory,
+        return InstantiateUnionLayer( psLTree, pszVRTDirectory,
                                       bUpdate, nRecLevel + 1 );
     }
     else
@@ -735,7 +751,7 @@ typedef struct
 static OGRLayer* OGRVRTOpenProxiedLayer(void* pUserData)
 {
     PooledInitData* pData = (PooledInitData*) pUserData;
-    return pData->poDS->InstanciateLayerInternal(pData->psNode,
+    return pData->poDS->InstantiateLayerInternal(pData->psNode,
                                             pData->pszVRTDirectory,
                                             pData->bUpdate,
                                             0);
@@ -753,10 +769,10 @@ static void OGRVRTFreeProxiedLayerUserData(void* pUserData)
 }
 
 /************************************************************************/
-/*                          InstanciateLayer()                          */
+/*                          InstantiateLayer()                          */
 /************************************************************************/
 
-OGRLayer* OGRVRTDataSource::InstanciateLayer(CPLXMLNode *psLTree,
+OGRLayer* OGRVRTDataSource::InstantiateLayer(CPLXMLNode *psLTree,
                                         const char *pszVRTDirectory,
                                         int bUpdate,
                                         int nRecLevel)
@@ -773,11 +789,9 @@ OGRLayer* OGRVRTDataSource::InstanciateLayer(CPLXMLNode *psLTree,
                                     OGRVRTFreeProxiedLayerUserData,
                                     pData);
     }
-    else
-    {
-        return InstanciateLayerInternal(psLTree, pszVRTDirectory,
+
+    return InstantiateLayerInternal(psLTree, pszVRTDirectory,
                                     bUpdate, nRecLevel);
-    }
 }
 
 /************************************************************************/
@@ -791,10 +805,9 @@ static int CountOGRVRTLayers(CPLXMLNode *psTree)
 
     int nCount = 0;
     if( EQUAL(psTree->pszValue, "OGRVRTLayer") )
-        nCount ++;
+        ++nCount;
 
-    CPLXMLNode* psNode;
-    for( psNode=psTree->psChild; psNode != NULL; psNode=psNode->psNext )
+    for( CPLXMLNode *psNode=psTree->psChild; psNode != NULL; psNode=psNode->psNext )
     {
         nCount += CountOGRVRTLayers(psNode);
     }
@@ -806,13 +819,13 @@ static int CountOGRVRTLayers(CPLXMLNode *psTree)
 /*                             Initialize()                             */
 /************************************************************************/
 
-int OGRVRTDataSource::Initialize( CPLXMLNode *psTree, const char *pszNewName,
+int OGRVRTDataSource::Initialize( CPLXMLNode *psTreeIn, const char *pszNewName,
                                   int bUpdate )
 
 {
     CPLAssert( nLayers == 0 );
 
-    this->psTree = psTree;
+    this->psTree = psTreeIn;
 
 /* -------------------------------------------------------------------- */
 /*      Set name, and capture the directory path so we can use it       */
@@ -829,7 +842,7 @@ int OGRVRTDataSource::Initialize( CPLXMLNode *psTree, const char *pszNewName,
     CPLXMLNode *psVRTDSXML = CPLGetXMLNode( psTree, "=OGRVRTDataSource" );
     if( psVRTDSXML == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Did not find the <OGRVRTDataSource> node in the root of the document,\n"
                   "this is not really an OGR VRT." );
         return FALSE;
@@ -854,9 +867,8 @@ int OGRVRTDataSource::Initialize( CPLXMLNode *psTree, const char *pszNewName,
 /* -------------------------------------------------------------------- */
 /*      Look for layers.                                                */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psLTree;
 
-    for( psLTree=psVRTDSXML->psChild; psLTree != NULL; psLTree=psLTree->psNext )
+    for( CPLXMLNode *psLTree=psVRTDSXML->psChild; psLTree != NULL; psLTree=psLTree->psNext )
     {
         if( psLTree->eType != CXT_Element )
             continue;
@@ -864,7 +876,7 @@ int OGRVRTDataSource::Initialize( CPLXMLNode *psTree, const char *pszNewName,
 /* -------------------------------------------------------------------- */
 /*      Create the layer object.                                        */
 /* -------------------------------------------------------------------- */
-        OGRLayer  *poLayer = InstanciateLayer(psLTree, osVRTDirectory, bUpdate);
+        OGRLayer  *poLayer = InstantiateLayer(psLTree, osVRTDirectory, bUpdate);
         if( poLayer == NULL )
             continue;
 
@@ -915,8 +927,8 @@ OGRLayer *OGRVRTDataSource::GetLayer( int iLayer )
 {
     if( iLayer < 0 || iLayer >= nLayers )
         return NULL;
-    else
-        return papoLayers[iLayer];
+
+    return papoLayers[iLayer];
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/vrt/ogrvrtdriver.cpp b/ogr/ogrsf_frmts/vrt/ogrvrtdriver.cpp
index 3f121ed..546031a 100644
--- a/ogr/ogrsf_frmts/vrt/ogrvrtdriver.cpp
+++ b/ogr/ogrsf_frmts/vrt/ogrvrtdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrvrtdriver.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogrvrtdriver.cpp 32982 2016-01-14 16:53:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRVRTDriver class.
@@ -31,14 +31,14 @@
 #include "ogr_vrt.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrvrtdriver.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogrvrtdriver.cpp 32982 2016-01-14 16:53:57Z goatbar $");
 
 /************************************************************************/
 /*                           OGRVRTErrorHandler()                       */
 /************************************************************************/
 
 static void CPL_STDCALL OGRVRTErrorHandler(CPL_UNUSED CPLErr eErr,
-                                           CPL_UNUSED int nType,
+                                           CPL_UNUSED CPLErrorNum nType,
                                            const char* pszMsg)
 {
     std::vector<CPLString>* paosErrors = (std::vector<CPLString>* )CPLGetErrorHandlerUserData();
@@ -60,7 +60,7 @@ static int OGRVRTDriverIdentify( GDALOpenInfo* poOpenInfo )
         const char *pszTestXML = poOpenInfo->pszFilename;
         while( *pszTestXML != '\0' && isspace( (unsigned char)*pszTestXML ) )
             pszTestXML++;
-        if( EQUALN(pszTestXML,"<OGRVRTDataSource>",18) )
+        if( STARTS_WITH_CI(pszTestXML, "<OGRVRTDataSource>") )
         {
             return TRUE;
         }
@@ -78,13 +78,9 @@ static int OGRVRTDriverIdentify( GDALOpenInfo* poOpenInfo )
 static GDALDataset *OGRVRTDriverOpen( GDALOpenInfo* poOpenInfo )
 
 {
-    OGRVRTDataSource     *poDS;
-
     if( !OGRVRTDriverIdentify(poOpenInfo) )
         return NULL;
 
-    char *pszXML = NULL;
-
 /* -------------------------------------------------------------------- */
 /*      Are we being passed the XML definition directly?                */
 /*      Skip any leading spaces/blanks.                                 */
@@ -93,7 +89,8 @@ static GDALDataset *OGRVRTDriverOpen( GDALOpenInfo* poOpenInfo )
     while( *pszTestXML != '\0' && isspace( (unsigned char)*pszTestXML ) )
         pszTestXML++;
 
-    if( EQUALN(pszTestXML,"<OGRVRTDataSource>",18) )
+    char *pszXML = NULL;
+    if( STARTS_WITH_CI(pszTestXML, "<OGRVRTDataSource>") )
     {
         pszXML = CPLStrdup(pszTestXML);
     }
@@ -116,7 +113,7 @@ static GDALDataset *OGRVRTDriverOpen( GDALOpenInfo* poOpenInfo )
 /* -------------------------------------------------------------------- */
         int nLen = (int) sStatBuf.st_size;
 
-        pszXML = (char *) VSIMalloc(nLen+1);
+        pszXML = (char *) VSI_MALLOC_VERBOSE(nLen+1);
         if (pszXML == NULL)
             return NULL;
 
@@ -145,7 +142,7 @@ static GDALDataset *OGRVRTDriverOpen( GDALOpenInfo* poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      XML Validation.                                                 */
 /* -------------------------------------------------------------------- */
-    if( CSLTestBoolean(CPLGetConfigOption("GDAL_XML_VALIDATION", "YES")) )
+    if( CPLTestBool(CPLGetConfigOption("GDAL_XML_VALIDATION", "YES")) )
     {
         const char* pszXSD = CPLFindFile( "gdal", "ogrvrt.xsd" );
         if( pszXSD != NULL )
@@ -173,7 +170,8 @@ static GDALDataset *OGRVRTDriverOpen( GDALOpenInfo* poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a virtual datasource configured based on this XML input. */
 /* -------------------------------------------------------------------- */
-    poDS = new OGRVRTDataSource((GDALDriver*)GDALGetDriverByName( "OGR_VRT" ));
+    OGRVRTDataSource *poDS
+        = new OGRVRTDataSource((GDALDriver*)GDALGetDriverByName( "OGR_VRT" ));
 
     /* psTree is owned by poDS */
     if( !poDS->Initialize( psTree, poOpenInfo->pszFilename,
@@ -193,25 +191,20 @@ static GDALDataset *OGRVRTDriverOpen( GDALOpenInfo* poOpenInfo )
 void RegisterOGRVRT()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "OGR_VRT" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "OGR_VRT" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-
-        poDriver->SetDescription( "OGR_VRT" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "VRT - Virtual Datasource" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "vrt" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_vrt.html" );
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetDescription( "OGR_VRT" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "VRT - Virtual Datasource" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "vrt" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_vrt.html" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnOpen = OGRVRTDriverOpen;
-        poDriver->pfnIdentify = OGRVRTDriverIdentify;
+    poDriver->pfnOpen = OGRVRTDriverOpen;
+    poDriver->pfnIdentify = OGRVRTDriverIdentify;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/vrt/ogrvrtlayer.cpp b/ogr/ogrsf_frmts/vrt/ogrvrtlayer.cpp
index be4f9df..a249ba5 100644
--- a/ogr/ogrsf_frmts/vrt/ogrvrtlayer.cpp
+++ b/ogr/ogrsf_frmts/vrt/ogrvrtlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrvrtlayer.cpp 32515 2015-12-29 10:09:08Z rouault $
+ * $Id: ogrvrtlayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRVRTLayer class.
@@ -34,7 +34,7 @@
 #include "ogrpgeogeometry.h"
 #include <string>
 
-CPL_CVSID("$Id: ogrvrtlayer.cpp 32515 2015-12-29 10:09:08Z rouault $");
+CPL_CVSID("$Id: ogrvrtlayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 #define UNSUPPORTED_OP_READ_ONLY "%s : unsupported operation on a read-only datasource."
 
@@ -43,18 +43,20 @@ CPL_CVSID("$Id: ogrvrtlayer.cpp 32515 2015-12-29 10:09:08Z rouault $");
 /*                       OGRVRTGeomFieldProps()                         */
 /************************************************************************/
 
-OGRVRTGeomFieldProps::OGRVRTGeomFieldProps()
-{
-    eGeomType = wkbUnknown;
-    bUseSpatialSubquery = FALSE;
-    eGeometryStyle = VGS_Direct;
-    poSRS = NULL;
-    iGeomField = iGeomXField = iGeomYField = iGeomZField = -1;
-    bSrcClip = FALSE;
-    poSrcRegion = NULL;
-    bReportSrcColumn = TRUE;
-    bNullable = TRUE;
-}
+OGRVRTGeomFieldProps::OGRVRTGeomFieldProps() :
+    eGeomType(wkbUnknown),
+    poSRS(NULL),
+    bSrcClip(FALSE),
+    poSrcRegion(NULL),
+    eGeometryStyle(VGS_Direct),
+    iGeomField(-1),
+    iGeomXField(-1),
+    iGeomYField(-1),
+    iGeomZField(-1),
+    bReportSrcColumn(TRUE),
+    bUseSpatialSubquery(FALSE),
+    bNullable(TRUE)
+{ }
 
 /************************************************************************/
 /*                      ~OGRVRTGeomFieldProps()                         */
@@ -72,33 +74,25 @@ OGRVRTGeomFieldProps::~OGRVRTGeomFieldProps()
 /*                            OGRVRTLayer()                             */
 /************************************************************************/
 
-OGRVRTLayer::OGRVRTLayer(OGRVRTDataSource* poDSIn)
-
-{
-    poDS = poDSIn;
-
-    bHasFullInitialized = FALSE;
-    psLTree = NULL;
-
-    poFeatureDefn = NULL;
-    poSrcLayer = NULL;
-    poSrcDS = NULL;
-    poSrcFeatureDefn = NULL;
-
-    iFIDField = -1;
-    iStyleField = -1;
-
-    pszAttrFilter = NULL;
-
-    bNeedReset = TRUE;
-    bSrcLayerFromSQL = FALSE;
-
-    bUpdate = FALSE;
-    bAttrFilterPassThrough = FALSE;
-
-    nFeatureCount = -1;
-    bError = FALSE;
-}
+OGRVRTLayer::OGRVRTLayer(OGRVRTDataSource* poDSIn) :
+    poDS(poDSIn),
+    bHasFullInitialized(FALSE),
+    psLTree(NULL),
+    poFeatureDefn(NULL),
+    poSrcDS(NULL),
+    poSrcLayer(NULL),
+    poSrcFeatureDefn(NULL),
+    bNeedReset(TRUE),
+    bSrcLayerFromSQL(FALSE),
+    bSrcDSShared(FALSE),
+    bAttrFilterPassThrough(FALSE),
+    pszAttrFilter(NULL),
+    iFIDField(-1),  // -1 means pass through.
+    iStyleField(-1),  // -1 means pass through.
+    bUpdate(FALSE),
+    nFeatureCount(-1),
+    bError(FALSE)
+{ }
 
 /************************************************************************/
 /*                            ~OGRVRTLayer()                            */
@@ -110,10 +104,10 @@ OGRVRTLayer::~OGRVRTLayer()
     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     {
         CPLDebug( "VRT", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
+                  (int) m_nFeaturesRead,
                   poFeatureDefn->GetName() );
     }
-    
+
     for(size_t i=0;i<apoGeomFieldProps.size();i++)
         delete apoGeomFieldProps[i];
 
@@ -157,12 +151,12 @@ OGRFeatureDefn* OGRVRTLayer::GetSrcLayerDefn()
 /*                         FastInitialize()                             */
 /************************************************************************/
 
-int OGRVRTLayer::FastInitialize( CPLXMLNode *psLTree, const char *pszVRTDirectory,
-                             int bUpdate)
+int OGRVRTLayer::FastInitialize( CPLXMLNode *psLTreeIn, const char *pszVRTDirectory,
+                             int bUpdateIn)
 
 {
-    this->psLTree = psLTree;
-    this->bUpdate = bUpdate;
+    this->psLTree = psLTreeIn;
+    this->bUpdate = bUpdateIn;
     osVRTDirectory = pszVRTDirectory;
 
     if( !EQUAL(psLTree->pszValue,"OGRVRTLayer") )
@@ -175,7 +169,7 @@ int OGRVRTLayer::FastInitialize( CPLXMLNode *psLTree, const char *pszVRTDirector
 
     if( pszLayerName == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Missing name attribute on OGRVRTLayer" );
         return FALSE;
     }
@@ -190,24 +184,22 @@ int OGRVRTLayer::FastInitialize( CPLXMLNode *psLTree, const char *pszVRTDirector
      const char *pszGType = CPLGetXMLValue( psLTree, "GeometryType", NULL );
      if( pszGType == NULL && psGeometryFieldNode != NULL )
          pszGType = CPLGetXMLValue( psGeometryFieldNode, "GeometryType", NULL );
-     OGRwkbGeometryType eGeomType = wkbUnknown;
      if( pszGType != NULL )
      {
-         int bError;
-         eGeomType = OGRVRTGetGeometryType(pszGType, &bError);
-         if( bError )
+         int l_bError;
+         OGRwkbGeometryType eGeomType = OGRVRTGetGeometryType(pszGType, &l_bError);
+         if( l_bError )
          {
              CPLError( CE_Failure, CPLE_AppDefined,
                        "GeometryType %s not recognised.",
                        pszGType );
              return FALSE;
          }
-     }
-
-     if( eGeomType != wkbNone )
-     {
-         apoGeomFieldProps.push_back(new OGRVRTGeomFieldProps());
-         apoGeomFieldProps[0]->eGeomType = eGeomType;
+         if( eGeomType != wkbNone )
+         {
+             apoGeomFieldProps.push_back(new OGRVRTGeomFieldProps());
+             apoGeomFieldProps[0]->eGeomType = eGeomType;
+         }
      }
 
 /* -------------------------------------------------------------------- */
@@ -216,8 +208,10 @@ int OGRVRTLayer::FastInitialize( CPLXMLNode *psLTree, const char *pszVRTDirector
      const char* pszLayerSRS = CPLGetXMLValue( psLTree, "LayerSRS", NULL );
      if( pszLayerSRS == NULL && psGeometryFieldNode != NULL )
          pszLayerSRS = CPLGetXMLValue( psGeometryFieldNode, "SRS", NULL );
-     if( apoGeomFieldProps.size() != 0 && pszLayerSRS != NULL )
+     if( pszLayerSRS != NULL )
      {
+         if( apoGeomFieldProps.size() == 0 )
+             apoGeomFieldProps.push_back(new OGRVRTGeomFieldProps());
          if( !(EQUAL(pszLayerSRS,"NULL")) )
          {
              OGRSpatialReference oSRS;
@@ -255,10 +249,11 @@ int OGRVRTLayer::FastInitialize( CPLXMLNode *psLTree, const char *pszVRTDirector
         pszExtentXMax = CPLGetXMLValue( psGeometryFieldNode, "ExtentXMax", NULL );
         pszExtentYMax = CPLGetXMLValue( psGeometryFieldNode, "ExtentYMax", NULL );
      }
-     if( apoGeomFieldProps.size() != 0 &&
-         pszExtentXMin != NULL && pszExtentYMin != NULL &&
+     if( pszExtentXMin != NULL && pszExtentYMin != NULL &&
          pszExtentXMax != NULL && pszExtentYMax != NULL )
      {
+         if( apoGeomFieldProps.size() == 0 )
+             apoGeomFieldProps.push_back(new OGRVRTGeomFieldProps());
          apoGeomFieldProps[0]->sStaticEnvelope.MinX = CPLAtof(pszExtentXMin);
          apoGeomFieldProps[0]->sStaticEnvelope.MinY = CPLAtof(pszExtentYMin);
          apoGeomFieldProps[0]->sStaticEnvelope.MaxX = CPLAtof(pszExtentXMax);
@@ -293,9 +288,9 @@ int OGRVRTLayer::ParseGeometryField(CPLXMLNode* psNode,
         pszGType = CPLGetXMLValue( psNodeParent, "GeometryType", NULL );
     if( pszGType != NULL )
     {
-        int bError;
-        poProps->eGeomType = OGRVRTGetGeometryType(pszGType, &bError);
-        if( bError )
+        int l_bError;
+        poProps->eGeomType = OGRVRTGetGeometryType(pszGType, &l_bError);
+        if( l_bError )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                      "GeometryType %s not recognised.",
@@ -322,9 +317,9 @@ int OGRVRTLayer::ParseGeometryField(CPLXMLNode* psNode,
     else if( EQUAL(pszEncoding,"PointFromColumns") )
     {
         poProps->eGeometryStyle = VGS_PointFromColumns;
-        poProps->bUseSpatialSubquery = 
-            CSLTestBoolean(
-                CPLGetXMLValue(psNode, 
+        poProps->bUseSpatialSubquery =
+            CPLTestBool(
+                CPLGetXMLValue(psNode,
                             "GeometryField.useSpatialSubquery",
                             "TRUE"));
 
@@ -337,7 +332,7 @@ int OGRVRTLayer::ParseGeometryField(CPLXMLNode* psNode,
 
         if( poProps->iGeomXField == -1 || poProps->iGeomYField == -1 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                     "Unable to identify source X or Y field for PointFromColumns encoding." );
             return FALSE;
         }
@@ -352,7 +347,7 @@ int OGRVRTLayer::ParseGeometryField(CPLXMLNode* psNode,
     }
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                 "encoding=\"%s\" not recognised.", pszEncoding );
         return FALSE;
     }
@@ -361,14 +356,14 @@ int OGRVRTLayer::ParseGeometryField(CPLXMLNode* psNode,
         || poProps->eGeometryStyle == VGS_WKB
         || poProps->eGeometryStyle == VGS_Shape )
     {
-        const char *pszFieldName = 
+        const char *pszFieldName =
             CPLGetXMLValue( psNode, "field", "missing" );
 
         poProps->iGeomField = GetSrcLayerDefn()->GetFieldIndex(pszFieldName);
 
         if( poProps->iGeomField == -1 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                     "Unable to identify source field '%s' for geometry.",
                     pszFieldName );
             return FALSE;
@@ -376,7 +371,7 @@ int OGRVRTLayer::ParseGeometryField(CPLXMLNode* psNode,
     }
     else if( poProps->eGeometryStyle == VGS_Direct )
     {
-        const char *pszFieldName = 
+        const char *pszFieldName =
             CPLGetXMLValue( psNode, "field", NULL );
 
         if( pszFieldName != NULL || GetSrcLayerDefn()->GetGeomFieldCount() > 1 )
@@ -387,7 +382,7 @@ int OGRVRTLayer::ParseGeometryField(CPLXMLNode* psNode,
 
             if( poProps->iGeomField == -1 )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                         "Unable to identify source geometry field '%s' for geometry.",
                         pszFieldName );
                 return FALSE;
@@ -399,14 +394,14 @@ int OGRVRTLayer::ParseGeometryField(CPLXMLNode* psNode,
         }
         else if( psNode != NULL )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                     "Unable to identify source geometry field." );
             return FALSE;
         }
     }
 
     poProps->bReportSrcColumn =
-        CSLTestBoolean(CPLGetXMLValue( psNode, "reportSrcColumn", "YES" ));
+        CPLTestBool(CPLGetXMLValue( psNode, "reportSrcColumn", "YES" ));
 
 /* -------------------------------------------------------------------- */
 /*      Guess geometry type if not explicitly provided (or computed)   */
@@ -478,7 +473,7 @@ int OGRVRTLayer::ParseGeometryField(CPLXMLNode* psNode,
             poProps->poSrcRegion = NULL;
         }
 
-        poProps->bSrcClip = CSLTestBoolean(CPLGetXMLValue( psNode, "SrcRegion.clip", "FALSE" ));
+        poProps->bSrcClip = CPLTestBool(CPLGetXMLValue( psNode, "SrcRegion.clip", "FALSE" ));
     }
 
 /* -------------------------------------------------------------------- */
@@ -497,7 +492,7 @@ int OGRVRTLayer::ParseGeometryField(CPLXMLNode* psNode,
          poProps->sStaticEnvelope.MaxY = CPLAtof(pszExtentYMax);
      }
 
-    poProps->bNullable = CSLTestBoolean(CPLGetXMLValue( psNode, "nullable", "TRUE" ));
+    poProps->bNullable = CPLTestBool(CPLGetXMLValue( psNode, "nullable", "TRUE" ));
 
     return TRUE;
 }
@@ -535,15 +530,15 @@ int OGRVRTLayer::FullInitialize()
 
     if( pszSrcDSName == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Missing SrcDataSource for layer %s.", osName.c_str() );
         goto error;
     }
 
-    if( CSLTestBoolean(CPLGetXMLValue( psLTree, "SrcDataSource.relativetoVRT", 
+    if( CPLTestBool(CPLGetXMLValue( psLTree, "SrcDataSource.relativetoVRT",
                                        "0")) )
     {
-        static const char* apszPrefixes[] = { "CSV:", "GPSBABEL:" };
+        static const char* const apszPrefixes[] = { "CSV:", "GPSBABEL:" };
         int bDone = FALSE;
         for( size_t i = 0; i < sizeof(apszPrefixes) / sizeof(apszPrefixes[0]); i ++)
         {
@@ -591,7 +586,7 @@ int OGRVRTLayer::FullInitialize()
             pszSharedSetting = "ON";
     }
 
-    bSrcDSShared = CSLTestBoolean( pszSharedSetting );
+    bSrcDSShared = CPLTestBool( pszSharedSetting );
 
     // update mode doesn't make sense if we have a SrcSQL element
     if (CPLGetXMLValue( psLTree, "SrcSQL", NULL ) != NULL)
@@ -621,9 +616,9 @@ try_again:
         else
         {
             char** papszOpenOptions = GDALDeserializeOpenOptionsFromXML(psLTree);
-            int nFlags = GDAL_OF_VECTOR | GDAL_OF_SHARED;
-            if( bUpdate ) nFlags |= GDAL_OF_UPDATE;
-            poSrcDS = (GDALDataset*) GDALOpenEx( pszSrcDSName, nFlags, NULL,
+            int l_nFlags = GDAL_OF_VECTOR | GDAL_OF_SHARED;
+            if( bUpdate ) l_nFlags |= GDAL_OF_UPDATE;
+            poSrcDS = (GDALDataset*) GDALOpenEx( pszSrcDSName, l_nFlags, NULL,
                                 (const char* const* )papszOpenOptions, NULL );
             CSLDestroy(papszOpenOptions);
             /* Is it a VRT datasource ? */
@@ -639,9 +634,9 @@ try_again:
         if (poDS->GetCallLevel() < 32)
         {
             char** papszOpenOptions = GDALDeserializeOpenOptionsFromXML(psLTree);
-            int nFlags = GDAL_OF_VECTOR;
-            if( bUpdate ) nFlags |= GDAL_OF_UPDATE;
-            poSrcDS = (GDALDataset*) GDALOpenEx( pszSrcDSName, nFlags, NULL,
+            int l_nFlags = GDAL_OF_VECTOR;
+            if( bUpdate ) l_nFlags |= GDAL_OF_UPDATE;
+            poSrcDS = (GDALDataset*) GDALOpenEx( pszSrcDSName, l_nFlags, NULL,
                                 (const char* const* )papszOpenOptions, NULL );
             CSLDestroy(papszOpenOptions);
             /* Is it a VRT datasource ? */
@@ -668,7 +663,7 @@ try_again:
         }
     }
 
-    if( poSrcDS == NULL ) 
+    if( poSrcDS == NULL )
     {
         if (bUpdate)
         {
@@ -679,8 +674,8 @@ try_again:
             goto try_again;
         }
         if( strlen(CPLGetLastErrorMsg()) == 0 )
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Failed to open datasource `%s'.", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Failed to open datasource `%s'.",
                       pszSrcDSName );
         goto error;
     }
@@ -716,14 +711,14 @@ try_again:
 /* -------------------------------------------------------------------- */
     if( poSrcLayer == NULL )
     {
-        const char *pszSrcLayerName = CPLGetXMLValue( psLTree, "SrcLayer", 
+        const char *pszSrcLayerName = CPLGetXMLValue( psLTree, "SrcLayer",
                                                       osName );
-        
+
         poSrcLayer = poSrcDS->GetLayerByName( pszSrcLayerName );
         if( poSrcLayer == NULL )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                  "Failed to find layer '%s' on datasource '%s'.", 
+                  "Failed to find layer '%s' on datasource '%s'.",
                       pszSrcLayerName, pszSrcDSName );
             goto error;
         }
@@ -735,91 +730,80 @@ try_again:
 /* -------------------------------------------------------------------- */
 /*      Search for GeometryField definitions                            */
 /* -------------------------------------------------------------------- */
-    if( apoGeomFieldProps.size() != 0 )
+
+    /* Create as many OGRVRTGeomFieldProps as there are */
+    /* GeometryField elements */
+    for( psChild = psLTree->psChild; psChild != NULL; psChild=psChild->psNext )
     {
-        /* First pass: create as many OGRVRTGeomFieldProps as there are */
-        /* GeometryField elements */
-        for( psChild = psLTree->psChild; psChild != NULL; psChild=psChild->psNext )
+        if( psChild->eType == CXT_Element &&
+            EQUAL(psChild->pszValue,"GeometryField") )
         {
-            if( psChild->eType == CXT_Element &&
-                EQUAL(psChild->pszValue,"GeometryField") )
+            if( !bFoundGeometryField )
             {
-                if( !bFoundGeometryField )
-                {
-                    bFoundGeometryField = TRUE;
-                }
-                else
-                    apoGeomFieldProps.push_back(new OGRVRTGeomFieldProps());
-            }
-        }
+                bFoundGeometryField = TRUE;
 
-        if( !bFoundGeometryField )
-        {
-            /* If no GeometryField is found but several source geometry fields */
-            /* exist, use them */
-            if( GetSrcLayerDefn()->GetGeomFieldCount() > 1 )
-            {
-                delete apoGeomFieldProps[0];
-                apoGeomFieldProps.resize(0);
-                for( int iGeomField = 0;
-                        iGeomField < GetSrcLayerDefn()->GetGeomFieldCount();
-                        iGeomField++ )
+                // Recreate the first one if already taken into account in FastInitialize()
+                if( apoGeomFieldProps.size() == 1 )
                 {
-                    OGRVRTGeomFieldProps* poProps;
-                    poProps = new OGRVRTGeomFieldProps();
-                    apoGeomFieldProps.push_back(poProps);
-                    OGRGeomFieldDefn* poFDefn =
-                        GetSrcLayerDefn()->GetGeomFieldDefn(iGeomField);
-                    poProps->osName = poFDefn->GetNameRef();
-                    poProps->eGeomType = poFDefn->GetType();
-                    if( poFDefn->GetSpatialRef() != NULL )
-                    poProps->poSRS = poFDefn->GetSpatialRef()->Clone();
-                    poProps->iGeomField = iGeomField;
-                    poProps->bNullable = poFDefn->IsNullable();
+                    delete apoGeomFieldProps[0];
+                    apoGeomFieldProps.resize(0);
                 }
             }
 
-            /* Otherwise use the top-level elements such as SrcRegion */
-            else
-            {
-            if( !ParseGeometryField(NULL, psLTree, apoGeomFieldProps[0] ) )
-                    goto error;
-            }
-        }
-        else
-        {
-            /* Second pass: fill the OGRVRTGeomFieldProps objects from the */
-            /* GeometryField definitions */
-        int iGeomField = 0;
-        for( psChild = psLTree->psChild; psChild != NULL; psChild=psChild->psNext )
-        {
-            if( psChild->eType == CXT_Element &&
-                EQUAL(psChild->pszValue,"GeometryField") )
+            apoGeomFieldProps.push_back(new OGRVRTGeomFieldProps());
+            if( !ParseGeometryField(psChild, psLTree,
+                                    apoGeomFieldProps[apoGeomFieldProps.size()-1] ) )
             {
-                if( !ParseGeometryField(psChild, psLTree,
-                                        apoGeomFieldProps[iGeomField] ) )
-                    goto error;
-                iGeomField ++;
+                goto error;
             }
         }
-        }
+    }
+
+    if( !bFoundGeometryField &&
+        CPLGetXMLValue( psLTree, "SrcRegion", NULL ) != NULL )
+    {
+        apoGeomFieldProps.push_back(new OGRVRTGeomFieldProps());
+    }
 
-        /* Instanciate real geometry fields from VRT properties */
-        poFeatureDefn->SetGeomType(wkbNone);
-        for( size_t i = 0; i < apoGeomFieldProps.size(); i ++ )
+    if( !bFoundGeometryField && apoGeomFieldProps.size() == 1 )
+    {
+        /* Otherwise use the top-level elements such as SrcRegion */
+        if( !ParseGeometryField(NULL, psLTree, apoGeomFieldProps[0] ) )
+            goto error;
+    }
+
+    if( apoGeomFieldProps.size() == 0 &&
+        CPLGetXMLValue( psLTree, "GeometryType", NULL ) == NULL )
+    {
+        /* If no GeometryField is found but source geometry fields */
+        /* exist, use them */
+        for( int iGeomField = 0;
+                iGeomField < GetSrcLayerDefn()->GetGeomFieldCount();
+                iGeomField++ )
         {
-            OGRGeomFieldDefn oFieldDefn( apoGeomFieldProps[i]->osName,
-                                        apoGeomFieldProps[i]->eGeomType );
-            oFieldDefn.SetSpatialRef( apoGeomFieldProps[i]->poSRS );
-            oFieldDefn.SetNullable( apoGeomFieldProps[i]->bNullable );
-            poFeatureDefn->AddGeomFieldDefn(&oFieldDefn);
+            OGRVRTGeomFieldProps* poProps;
+            poProps = new OGRVRTGeomFieldProps();
+            apoGeomFieldProps.push_back(poProps);
+            OGRGeomFieldDefn* poFDefn =
+                GetSrcLayerDefn()->GetGeomFieldDefn(iGeomField);
+            poProps->osName = poFDefn->GetNameRef();
+            poProps->eGeomType = poFDefn->GetType();
+            if( poFDefn->GetSpatialRef() != NULL )
+            poProps->poSRS = poFDefn->GetSpatialRef()->Clone();
+            poProps->iGeomField = iGeomField;
+            poProps->bNullable = poFDefn->IsNullable();
         }
-
-        poFeatureDefn->SetGeomType( apoGeomFieldProps[0]->eGeomType );
     }
-    else
+
+    /* Instantiate real geometry fields from VRT properties. */
+    poFeatureDefn->SetGeomType(wkbNone);
+    for( size_t i = 0; i < apoGeomFieldProps.size(); i ++ )
     {
-        poFeatureDefn->SetGeomType(wkbNone);
+        OGRGeomFieldDefn oFieldDefn( apoGeomFieldProps[i]->osName,
+                                    apoGeomFieldProps[i]->eGeomType );
+        oFieldDefn.SetSpatialRef( apoGeomFieldProps[i]->poSRS );
+        oFieldDefn.SetNullable( apoGeomFieldProps[i]->bNullable );
+        poFeatureDefn->AddGeomFieldDefn(&oFieldDefn);
     }
 
 /* -------------------------------------------------------------------- */
@@ -833,7 +817,7 @@ try_again:
              GetSrcLayerDefn()->GetFieldIndex( pszSrcFIDFieldName );
          if( iFIDField == -1 )
          {
-             CPLError( CE_Failure, CPLE_AppDefined, 
+             CPLError( CE_Failure, CPLE_AppDefined,
                        "Unable to identify FID field '%s'.",
                        pszSrcFIDFieldName );
              goto error;
@@ -855,7 +839,7 @@ try_again:
              GetSrcLayerDefn()->GetFieldIndex( pszStyleFieldName );
          if( iStyleField == -1 )
          {
-             CPLError( CE_Failure, CPLE_AppDefined, 
+             CPLError( CE_Failure, CPLE_AppDefined,
                        "Unable to identify Style field '%s'.",
                        pszStyleFieldName );
              goto error;
@@ -876,13 +860,13 @@ try_again:
              const char *pszName = CPLGetXMLValue( psChild, "name", NULL );
              if( pszName == NULL )
              {
-                 CPLError( CE_Failure, CPLE_AppDefined, 
+                 CPLError( CE_Failure, CPLE_AppDefined,
                            "Unable to identify Field name." );
                  goto error;
              }
 
              OGRFieldDefn oFieldDefn( pszName, OFTString );
-             
+
 /* -------------------------------------------------------------------- */
 /*      Type                                                            */
 /* -------------------------------------------------------------------- */
@@ -904,7 +888,7 @@ try_again:
 
                  if( iType > (int) OFTMaxType )
                  {
-                     CPLError( CE_Failure, CPLE_AppDefined, 
+                     CPLError( CE_Failure, CPLE_AppDefined,
                                "Unable to identify Field type '%s'.",
                                pszArg );
                      goto error;
@@ -932,7 +916,7 @@ try_again:
 
                  if( iType > (int) OFSTMaxSubType )
                  {
-                     CPLError( CE_Failure, CPLE_AppDefined, 
+                     CPLError( CE_Failure, CPLE_AppDefined,
                                "Unable to identify Field subtype '%s'.",
                                pszArg );
                      goto error;
@@ -940,7 +924,7 @@ try_again:
 
                  if( !OGR_AreTypeSubTypeCompatible(oFieldDefn.GetType(), eSubType) )
                  {
-                     CPLError( CE_Failure, CPLE_AppDefined, 
+                     CPLError( CE_Failure, CPLE_AppDefined,
                                "Invalid subtype '%s' for type '%s'.",
                                pszArg, OGRFieldDefn::GetFieldTypeName(oFieldDefn.GetType()) );
                      goto error;
@@ -975,7 +959,7 @@ try_again:
 /* -------------------------------------------------------------------- */
 /*      Nullable attribute.                                             */
 /* -------------------------------------------------------------------- */
-             int bNullable = CSLTestBoolean(CPLGetXMLValue( psChild, "nullable", "true" ));
+             int bNullable = CPLTestBool(CPLGetXMLValue( psChild, "nullable", "true" ));
              oFieldDefn.SetNullable(bNullable);
 
 /* -------------------------------------------------------------------- */
@@ -1000,7 +984,7 @@ try_again:
 
              if( pszArg != NULL )
              {
-                 iSrcField = 
+                 iSrcField =
                      GetSrcLayerDefn()->GetFieldIndex( pszArg );
                  if( iSrcField == -1 )
                  {
@@ -1103,7 +1087,7 @@ try_again:
 /* -------------------------------------------------------------------- */
      if( CPLGetXMLValue( psLTree, "attrFilterPassThrough", NULL ) != NULL )
          bAttrFilterPassThrough =
-             CSLTestBoolean(
+             CPLTestBool(
                  CPLGetXMLValue(psLTree, "attrFilterPassThrough",
                                 "TRUE") );
 
@@ -1252,13 +1236,13 @@ int OGRVRTLayer::ResetSourceReading()
 /*      Install spatial + attr filter query on source layer.            */
 /* -------------------------------------------------------------------- */
     if( pszFilter == NULL && pszAttrFilter == NULL )
-        bSuccess = (poSrcLayer->SetAttributeFilter( NULL ) == CE_None);
+        bSuccess = (poSrcLayer->SetAttributeFilter( NULL ) == OGRERR_NONE);
 
     else if( pszFilter != NULL && pszAttrFilter == NULL )
-        bSuccess = (poSrcLayer->SetAttributeFilter( pszFilter ) == CE_None);
+        bSuccess = (poSrcLayer->SetAttributeFilter( pszFilter ) == OGRERR_NONE);
 
     else if( pszFilter == NULL && pszAttrFilter != NULL )
-        bSuccess = (poSrcLayer->SetAttributeFilter( pszAttrFilter ) == CE_None);
+        bSuccess = (poSrcLayer->SetAttributeFilter( pszAttrFilter ) == OGRERR_NONE);
 
     else
     {
@@ -1268,7 +1252,7 @@ int OGRVRTLayer::ResetSourceReading()
         osMerged += pszAttrFilter;
         osMerged += ")";
 
-        bSuccess = (poSrcLayer->SetAttributeFilter(osMerged) == CE_None);
+        bSuccess = (poSrcLayer->SetAttributeFilter(osMerged) == OGRERR_NONE);
     }
 
     CPLFree( pszFilter );
@@ -1283,7 +1267,7 @@ int OGRVRTLayer::ResetSourceReading()
     {
         OGRGeometry* poSpatialGeom = NULL;
         OGRGeometry* poSrcRegion = apoGeomFieldProps[m_iGeomFieldFilter]->poSrcRegion;
-        int bToDelete = FALSE;
+        bool bToDelete = false;
 
         if (poSrcRegion == NULL)
             poSpatialGeom = m_poFilterGeom;
@@ -1316,7 +1300,7 @@ int OGRVRTLayer::ResetSourceReading()
                 if( bDoIntersection )
                 {
                     poSpatialGeom = m_poFilterGeom->Intersection(poSrcRegion);
-                    bToDelete = TRUE;
+                    bToDelete = true;
                 }
             }
         }
@@ -1340,8 +1324,10 @@ int OGRVRTLayer::ResetSourceReading()
 OGRFeature *OGRVRTLayer::GetNextFeature()
 
 {
-    if (!bHasFullInitialized) FullInitialize();
-    if (!poSrcLayer || poDS->GetRecursionDetected()) return NULL;
+    if (!bHasFullInitialized)
+        FullInitialize();
+    if (!poSrcLayer || poDS->GetRecursionDetected())
+        return NULL;
     if( bError )
         return NULL;
 
@@ -1351,14 +1337,13 @@ OGRFeature *OGRVRTLayer::GetNextFeature()
             return NULL;
     }
 
-    for( ; TRUE; )
+    for( ; true; )
     {
-        OGRFeature      *poSrcFeature, *poFeature;
-
-        poSrcFeature = poSrcLayer->GetNextFeature();
+        OGRFeature *poSrcFeature = poSrcLayer->GetNextFeature();
         if( poSrcFeature == NULL )
             return NULL;
 
+        OGRFeature *poFeature;
         if (poFeatureDefn == poSrcFeatureDefn)
         {
             poFeature = poSrcFeature;
@@ -1400,10 +1385,12 @@ void OGRVRTLayer::ClipAndAssignSRS(OGRFeature* poFeature)
             poGeom != NULL)
         {
             poGeom = poGeom->Intersection(apoGeomFieldProps[i]->poSrcRegion);
+            if (poGeom != NULL && apoGeomFieldProps[i]->poSRS != NULL)
+                poGeom->assignSpatialReference(apoGeomFieldProps[i]->poSRS);
+
             poFeature->SetGeomFieldDirectly(i, poGeom);
         }
-
-        if (poGeom != NULL && apoGeomFieldProps[i]->poSRS != NULL)
+        else if (poGeom != NULL && apoGeomFieldProps[i]->poSRS != NULL)
             poGeom->assignSpatialReference(apoGeomFieldProps[i]->poSRS);
     }
 }
@@ -1429,14 +1416,14 @@ retry:
         poDstFeat->SetFID( poSrcFeat->GetFID() );
     else
         poDstFeat->SetFID( poSrcFeat->GetFieldAsInteger64( iFIDField ) );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Handle style string.                                            */
 /* -------------------------------------------------------------------- */
     if( iStyleField != -1 )
     {
         if( poSrcFeat->IsFieldSet(iStyleField) )
-            poDstFeat->SetStyleString( 
+            poDstFeat->SetStyleString(
                 poSrcFeat->GetFieldAsString(iStyleField) );
     }
     else
@@ -1444,7 +1431,7 @@ retry:
         if( poSrcFeat->GetStyleString() != NULL )
             poDstFeat->SetStyleString(poSrcFeat->GetStyleString());
     }
-    
+
     for(int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
     {
         OGRVRTGeometryStyle eGeometryStyle = apoGeomFieldProps[i]->eGeometryStyle;
@@ -1462,7 +1449,7 @@ retry:
         {
             char *pszWKT = (char *) poSrcFeat->GetFieldAsString(
                 iGeomField );
-            
+
             if( pszWKT != NULL )
             {
                 OGRGeometry *poGeom = NULL;
@@ -1479,7 +1466,7 @@ retry:
         {
             int nBytes;
             GByte *pabyWKB;
-            int bNeedFree = FALSE;
+            bool bNeedFree = false;
 
             if( poSrcFeat->GetFieldDefnRef(iGeomField)->GetType() == OFTBinary )
             {
@@ -1490,9 +1477,9 @@ retry:
                 const char *pszWKT = poSrcFeat->GetFieldAsString( iGeomField );
 
                 pabyWKB = CPLHexToBinary( pszWKT, &nBytes );
-                bNeedFree = TRUE;
+                bNeedFree = true;
             }
-            
+
             if( pabyWKB != NULL )
             {
                 OGRGeometry *poGeom = NULL;
@@ -1522,7 +1509,7 @@ retry:
                 pabyWKB = CPLHexToBinary( pszWKT, &nBytes );
                 bNeedFree = TRUE;
             }
-            
+
             if( pabyWKB != NULL )
             {
                 OGRGeometry *poGeom = NULL;
@@ -1555,8 +1542,8 @@ retry:
             /* add other options here. */
         }
 
-        /* In the non direct case, we need to check that the geometry intersects the source */
-        /* region before an optionnal clipping */
+        // In the non-direct case, we need to check that the geometry
+        // intersects the source region before an optional clipping.
         if( bUseSrcRegion &&
             apoGeomFieldProps[i]->eGeometryStyle != VGS_Direct &&
             apoGeomFieldProps[i]->poSrcRegion != NULL )
@@ -1595,7 +1582,7 @@ retry:
         if( !poSrcFeat->IsFieldSet( anSrcField[iVRTField] ) || poDstDefn->IsIgnored() )
             continue;
 
-        if( abDirectCopy[iVRTField] 
+        if( abDirectCopy[iVRTField]
             && poDstDefn->GetType() == poSrcDefn->GetType() )
         {
             poDstFeat->SetField( iVRTField,
@@ -1606,10 +1593,10 @@ retry:
             /* Eventually we need to offer some more sophisticated translation
                options here for more esoteric types. */
             if (poDstDefn->GetType() == OFTReal)
-                poDstFeat->SetField( iVRTField, 
+                poDstFeat->SetField( iVRTField,
                                  poSrcFeat->GetFieldAsDouble(anSrcField[iVRTField]));
             else
-                poDstFeat->SetField( iVRTField, 
+                poDstFeat->SetField( iVRTField,
                                  poSrcFeat->GetFieldAsString(anSrcField[iVRTField]));
         }
     }
@@ -1636,28 +1623,28 @@ OGRFeature *OGRVRTLayer::GetFeature( GIntBig nFeatureId )
 /*      to setup an appropriate query to get it.                        */
 /* -------------------------------------------------------------------- */
     OGRFeature      *poSrcFeature, *poFeature;
-    
+
     if( iFIDField == -1 )
     {
         poSrcFeature = poSrcLayer->GetFeature( nFeatureId );
     }
-    else 
+    else
     {
         const char* pszFID = poSrcLayer->GetLayerDefn()->GetFieldDefn(iFIDField)->GetNameRef();
         char* pszFIDQuery = (char*)CPLMalloc(strlen(pszFID) + 64);
 
         poSrcLayer->ResetReading();
-        sprintf( pszFIDQuery, "%s = " CPL_FRMT_GIB, pszFID, nFeatureId );
+        snprintf( pszFIDQuery, strlen(pszFID) + 64, "%s = " CPL_FRMT_GIB, pszFID, nFeatureId );
         poSrcLayer->SetSpatialFilter( NULL );
         poSrcLayer->SetAttributeFilter( pszFIDQuery );
         CPLFree(pszFIDQuery);
-        
+
         poSrcFeature = poSrcLayer->GetNextFeature();
     }
 
     if( poSrcFeature == NULL )
         return NULL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Translate feature and return it.                                */
 /* -------------------------------------------------------------------- */
@@ -1721,7 +1708,7 @@ OGRFeature* OGRVRTLayer::TranslateVRTFeatureToSrcFeature( OGRFeature* poVRTFeatu
         if( poVRTFeature->GetStyleString() != NULL )
             poSrcFeat->SetStyleString(poVRTFeature->GetStyleString());
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Handle the geometry.  Eventually there will be several more     */
 /*      supported options.                                              */
@@ -1841,7 +1828,7 @@ OGRFeature* OGRVRTLayer::TranslateVRTFeatureToSrcFeature( OGRFeature* poVRTFeatu
         OGRFieldDefn *poVRTDefn = poFeatureDefn->GetFieldDefn( iVRTField );
         OGRFieldDefn *poSrcDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn( anSrcField[iVRTField] );
 
-        if( abDirectCopy[iVRTField] 
+        if( abDirectCopy[iVRTField]
             && poVRTDefn->GetType() == poSrcDefn->GetType() )
         {
             poSrcFeat->SetField( anSrcField[iVRTField],
@@ -1851,7 +1838,7 @@ OGRFeature* OGRVRTLayer::TranslateVRTFeatureToSrcFeature( OGRFeature* poVRTFeatu
         {
             /* Eventually we need to offer some more sophisticated translation
                options here for more esoteric types. */
-            poSrcFeat->SetField( anSrcField[iVRTField], 
+            poSrcFeat->SetField( anSrcField[iVRTField],
                                  poVRTFeature->GetFieldAsString(iVRTField));
         }
     }
@@ -1878,7 +1865,7 @@ OGRErr OGRVRTLayer::ICreateFeature( OGRFeature* poVRTFeature )
 
     if( iFIDField != -1 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
             "The CreateFeature() operation is not supported if the FID option is specified." );
         return OGRERR_FAILURE;
     }
@@ -1916,7 +1903,7 @@ OGRErr OGRVRTLayer::ISetFeature( OGRFeature* poVRTFeature )
 
     if( iFIDField != -1 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
             "The SetFeature() operation is not supported if the FID option is specified." );
         return OGRERR_FAILURE;
     }
@@ -1950,7 +1937,7 @@ OGRErr OGRVRTLayer::DeleteFeature( GIntBig nFID )
 
     if( iFIDField != -1 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
             "The DeleteFeature() operation is not supported if the FID option is specified." );
         return OGRERR_FAILURE;
     }
@@ -2046,7 +2033,7 @@ int OGRVRTLayer::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCRandomRead) )
         return iFIDField == -1 && poSrcLayer->TestCapability(pszCap);
 
-    else if( EQUAL(pszCap,OLCSequentialWrite) 
+    else if( EQUAL(pszCap,OLCSequentialWrite)
              || EQUAL(pszCap,OLCRandomWrite)
              || EQUAL(pszCap,OLCDeleteFeature) )
         return bUpdate && iFIDField == -1 && poSrcLayer->TestCapability(pszCap);
@@ -2057,12 +2044,11 @@ int OGRVRTLayer::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCTransactions) )
         return bUpdate && poSrcLayer->TestCapability(pszCap);
 
-    else if( EQUAL(pszCap,OLCIgnoreFields) )
+    else if( EQUAL(pszCap,OLCIgnoreFields) ||
+             EQUAL(pszCap,OLCCurveGeometries) ||
+             EQUAL(pszCap,OLCMeasuredGeometries) )
         return poSrcLayer->TestCapability(pszCap);
 
-    else if( EQUAL(pszCap,OLCCurveGeometries) )
-        return TRUE;
-
     return FALSE;
 }
 
@@ -2322,7 +2308,7 @@ OGRErr OGRVRTLayer::SetIgnoredFields( const char **papszFields )
 
     const char** papszIter = papszFields;
     char** papszFieldsSrc = NULL;
-    OGRFeatureDefn* poSrcFeatureDefn = poSrcLayer->GetLayerDefn();
+    poSrcLayer->GetLayerDefn();
 
     /* Translate explicitly ignored fields of VRT layers to their equivalent */
     /* source fields. */
diff --git a/ogr/ogrsf_frmts/walk/drv_walk.html b/ogr/ogrsf_frmts/walk/drv_walk.html
index 6dca633..4c17306 100644
--- a/ogr/ogrsf_frmts/walk/drv_walk.html
+++ b/ogr/ogrsf_frmts/walk/drv_walk.html
@@ -16,22 +16,22 @@
   <p>Walk .mdb are accessed by passing the file name of
   the .mdb file to be accessed as the data source name. On Windows,
   no ODBC DSN is required. On Linux, there are problems with DSN-less
-  connection due to incomplete or buggy implementation of this feature 
+  connection due to incomplete or buggy implementation of this feature
   in the <a href="http://mdbtools.sourceforge.net/" tppabs="http://mdbtools.sourceforge.net/">MDB Tools</a> package,
   So, it is required to configure Data Source Name (DSN) if the MDB
   Tools driver is used (check instructions below).</p>
-  
+
   <p>OGR treats all feature tables as layers. Most geometry types
   should be supported (arcs and circles are translated into line segments, while other curves are currently converted into straight lines). Coordinate system information should be properly
   associated with layers. Currently no effort is made to preserve  styles and annotations.</p>
   <p>Currently the OGR Walk driver does not take
   advantage of spatial indexes for fast spatial queries.</p>
 
-<p>By default, SQL statements are handled by <a href="ogr_sql.html" tppabs="http://www.gdal.org/ogr/ogr_sql.html">OGR SQL</a> engine. SQL commands can also be passed directly to the ODBC database engine when SQL dialect is not "OGRSQL". In that case, the queries will deal with  tables (such as "XXXXFeatures", where XXXX is the   name of a layer) instead of layers.</p>
+<p>By default, SQL statements are handled by <a href="ogr_sql.html" tppabs="http://www.gdal.org/ogr_sql.html">OGR SQL</a> engine. SQL commands can also be passed directly to the ODBC database engine when SQL dialect is not "OGRSQL". In that case, the queries will deal with  tables (such as "XXXXFeatures", where XXXX is the   name of a layer) instead of layers.</p>
 
   <h2>How to use Walk driver with unixODBC and MDB Tools (on Unix and Linux)</h2>
 
-  <p>Refer to the similar section of the <a href="drv_pgeo.html" tppabs="http://www.gdal.org/ogr/drv_pgeo.html">PGeo</a> driver. The prefix to use
+  <p>Refer to the similar section of the <a href="drv_pgeo.html" tppabs="http://www.gdal.org/drv_pgeo.html">PGeo</a> driver. The prefix to use
   for this driver is Walk:</p>
 
 </body>
diff --git a/ogr/ogrsf_frmts/walk/ogis_geometry_wkb_struct.h b/ogr/ogrsf_frmts/walk/ogis_geometry_wkb_struct.h
index 2d59465..a56b57e 100644
--- a/ogr/ogrsf_frmts/walk/ogis_geometry_wkb_struct.h
+++ b/ogr/ogrsf_frmts/walk/ogis_geometry_wkb_struct.h
@@ -35,14 +35,14 @@
 /* Building Blocks : Point, LinearRing                                    */
 /**************************************************************************/
 
-#ifndef _OGIS_GEOMETRY_WKB_STRUCT_H
-#define _OGIS_GEOMETRY_WKB_STRUCT_H
+#ifndef OGIS_GEOMETRY_WKB_STRUCT_H
+#define OGIS_GEOMETRY_WKB_STRUCT_H
 
 #define CPL_LSBPTRPOINT(p) \
 {                                                                 \
-    CPL_LSBPTR32(&p.x);                                           \
-    CPL_LSBPTR32(&p.y);                                           \
-    CPL_LSBPTR32(&p.z);                                           \
+    CPL_LSBPTR64(&p.x);                                           \
+    CPL_LSBPTR64(&p.y);                                           \
+    CPL_LSBPTR64(&p.z);                                           \
 }
 
 #ifdef CPL_MSB
@@ -83,7 +83,7 @@ typedef Point Vector;        //Space Vector    {dx, dy, dz}
 /* ones in the curve.                                                     */
 /* A LineString is a curve with linear interpolation between points. Each */
 /* consecutive pair of points defines a line segment.                     */
-/* Extention��LineString is composed of CurveSegment, but self-crossing   */
+/* Extension LineString is composed of CurveSegment, but self-crossing   */
 /* is not allowed.                                                        */
 /**************************************************************************/
 
@@ -184,7 +184,7 @@ struct WKBMultiLineString {
 /*    3. A MultiPolygon is defined as topologically closed.               */
 /*    4. A MultiPolygon may not have cut lines, spikes or punctures,      */
 /*       a MultiPolygon is a Regular, Closed point set:                   */
-/*    5. The interior of a MultiPolygon with more than 1 Polygon is not   */ 
+/*    5. The interior of a MultiPolygon with more than 1 Polygon is not   */
 /*       connected, the number of connected components of the interior    */
 /*       of a MultiPolygon is equal to the number of Polygons in the      */
 /*       MultiPolygon.                                                    */
@@ -192,7 +192,7 @@ struct WKBMultiLineString {
 /*       (LineStrings) corresponding to the boundaries of its element     */
 /*       Polygons. Each curve in the boundary of the MultiPolygon is in   */
 /*       the boundary of exactly 1 element Polygon, and every curve in    */
-/*       the boundary of an element Polygon is in the boundary of the     */ 
+/*       the boundary of an element Polygon is in the boundary of the     */
 /*       MultiPolygon.                                                    */
 /**************************************************************************/
 struct WKBMultiPolygon {
@@ -230,5 +230,3 @@ public:
 };
 
 #endif /* ndef OGIS_GEOMETRY_WKB_STRUCT_H */
-
-
diff --git a/ogr/ogrsf_frmts/walk/ogrwalk.h b/ogr/ogrsf_frmts/walk/ogrwalk.h
index 57be465..4c076c4 100644
--- a/ogr/ogrsf_frmts/walk/ogrwalk.h
+++ b/ogr/ogrsf_frmts/walk/ogrwalk.h
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGRWALK_H_INCLUDED
-#define _OGRWALK_H_INCLUDED
+#ifndef OGRWALK_H_INCLUDED
+#define OGRWALK_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "cpl_odbc.h"
@@ -85,10 +85,10 @@ public:
     OGRFeature *        GetNextRawFeature();
 
     OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
-    
+
     int         TestCapability( const char * ) { return FALSE; }
 
-    virtual const char * GetFIDColumn (); 
+    virtual const char * GetFIDColumn ();
     virtual const char * GetGeometryColumn ();
 };
 
@@ -111,7 +111,7 @@ public:
                         OGRWalkTableLayer( OGRWalkDataSource * );
                         ~OGRWalkTableLayer();
 
-    CPLErr              Initialize( const char *pszTableName, 
+    CPLErr              Initialize( const char *pszTableName,
                                     const char *pszGeomCol,
                                     double minE,
                                     double maxE,
@@ -124,10 +124,12 @@ public:
 
     virtual OGRErr      SetAttributeFilter( const char * );
     virtual OGRFeature *GetFeature( GIntBig nFeatureId );
-    
+
     virtual int         TestCapability( const char * );
 
     virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 };
 
 /************************************************************************/
@@ -144,13 +146,14 @@ class OGRWalkSelectLayer : public OGRWalkLayer
     virtual CPLODBCStatement *  GetStatement();
 
   public:
-                        OGRWalkSelectLayer( OGRWalkDataSource *, 
+                        OGRWalkSelectLayer( OGRWalkDataSource *,
                                            CPLODBCStatement * );
                         ~OGRWalkSelectLayer();
 
     virtual void        ResetReading();
     virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
-
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 };
 
 /************************************************************************/
@@ -161,7 +164,7 @@ class OGRWalkDataSource : public OGRDataSource
 {
     char               *pszName;
     OGRWalkLayer        **papoLayers;
-    int                 nLayers;   
+    int                 nLayers;
 
     int                 bDSUpdate;
     CPLODBCSession      oSession;
@@ -197,15 +200,15 @@ class OGRWalkDriver : public OGRODBCMDBDriver
 {
 public:
                 ~OGRWalkDriver();
-                
+
     const char    *GetName();
     OGRDataSource *Open( const char *, int );
 
     OGRDataSource *CreateDataSource( const char *, char ** );
-    
+
     int            TestCapability( const char * );
 };
 
 void RegisterOGRWalk();
 
-#endif /* ndef _OGRWALK_H_INCLUDED */
+#endif /* ndef OGRWALK_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/walk/ogrwalkdatasource.cpp b/ogr/ogrsf_frmts/walk/ogrwalkdatasource.cpp
index 3ad1726..fdf5eaf 100644
--- a/ogr/ogrsf_frmts/walk/ogrwalkdatasource.cpp
+++ b/ogr/ogrsf_frmts/walk/ogrwalkdatasource.cpp
@@ -34,13 +34,12 @@
 /*                         OGRWalkDataSource()                          */
 /************************************************************************/
 
-OGRWalkDataSource::OGRWalkDataSource()
-
-{
-    pszName = NULL;
-    papoLayers = NULL;
-    nLayers = 0;
-}
+OGRWalkDataSource::OGRWalkDataSource() :
+    pszName(NULL),
+    papoLayers(NULL),
+    nLayers(0),
+    bDSUpdate(FALSE)
+{ }
 
 /************************************************************************/
 /*                        ~OGRWalkDataSource()                          */
@@ -49,14 +48,11 @@ OGRWalkDataSource::OGRWalkDataSource()
 OGRWalkDataSource::~OGRWalkDataSource()
 
 {
-    int i;
-
     CPLFree( pszName );
 
-    for( i = 0; i < nLayers; i++ )
+    for( int i = 0; i < nLayers; i++ )
     {
         CPLAssert( NULL != papoLayers[i] );
-
         delete papoLayers[i];
     }
 
@@ -76,14 +72,16 @@ int OGRWalkDataSource::Open( const char * pszNewName, int bUpdate )
 /* -------------------------------------------------------------------- */
     char *pszDSN;
 
-    if( EQUALN(pszNewName,"WALK:",5) )
+    if( STARTS_WITH_CI(pszNewName, "WALK:") )
         pszDSN = CPLStrdup( pszNewName + 5 );
     else
     {
         const char *pszDSNStringTemplate = "DRIVER=Microsoft Access Driver (*.mdb);DBQ=%s";
         pszDSN = (char *) CPLMalloc(strlen(pszNewName)+strlen(pszDSNStringTemplate)+100);
 
-        sprintf( pszDSN, pszDSNStringTemplate,  pszNewName );
+        snprintf( pszDSN,
+                  strlen(pszNewName)+strlen(pszDSNStringTemplate)+100,
+                  pszDSNStringTemplate,  pszNewName );
     }
 
 /* -------------------------------------------------------------------- */
@@ -93,7 +91,7 @@ int OGRWalkDataSource::Open( const char * pszNewName, int bUpdate )
 
     if( !oSession.EstablishSession( pszDSN, NULL, NULL ) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to initialize ODBC connection to DSN for %s,\n"
                   "%s", pszDSN, oSession.GetLastError() );
         CPLFree( pszDSN );
@@ -116,17 +114,17 @@ int OGRWalkDataSource::Open( const char * pszNewName, int bUpdate )
 
     if( !oStmt.ExecuteSQL() )
     {
-        CPLDebug( "Walk", 
-                  "SELECT on WalkLayers fails, perhaps not a walk database?\n%s", 
+        CPLDebug( "Walk",
+                  "SELECT on WalkLayers fails, perhaps not a walk database?\n%s",
                   oSession.GetLastError() );
         return FALSE;
     }
 
     while( oStmt.Fetch() )
     {
-        int i, iNew = apapszGeomColumns.size();
+        int i, iNew = static_cast<int>(apapszGeomColumns.size());
         char **papszRecord = NULL;
-        
+
         for( i = 1; i < 7; i++ )
             papszRecord = CSLAddString( papszRecord, oStmt.GetColData(i) ); //Add LayerName, Extent and Memo
 
@@ -194,8 +192,8 @@ OGRLayer * OGRWalkDataSource::ExecuteSQL( const char *pszSQLCommand,
 /*      Use generic implementation for recognized dialects              */
 /* -------------------------------------------------------------------- */
     if( IsGenericSQLDialect(pszDialect) )
-        return OGRDataSource::ExecuteSQL( pszSQLCommand, 
-                                          poSpatialFilter, 
+        return OGRDataSource::ExecuteSQL( pszSQLCommand,
+                                          poSpatialFilter,
                                           pszDialect );
 
 /* -------------------------------------------------------------------- */
@@ -209,8 +207,9 @@ OGRLayer * OGRWalkDataSource::ExecuteSQL( const char *pszSQLCommand,
     poStmt->Append( pszSQLCommand );
     if( !poStmt->ExecuteSQL() )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", oSession.GetLastError() );
+        delete poStmt;
         return NULL;
     }
 
@@ -234,7 +233,7 @@ OGRLayer * OGRWalkDataSource::ExecuteSQL( const char *pszSQLCommand,
 
     if( poSpatialFilter != NULL )
         poLayer->SetSpatialFilter( poSpatialFilter );
-    
+
     return poLayer;
 }
 
diff --git a/ogr/ogrsf_frmts/walk/ogrwalkdriver.cpp b/ogr/ogrsf_frmts/walk/ogrwalkdriver.cpp
index 847310e..f72098d 100644
--- a/ogr/ogrsf_frmts/walk/ogrwalkdriver.cpp
+++ b/ogr/ogrsf_frmts/walk/ogrwalkdriver.cpp
@@ -56,13 +56,13 @@ const char *OGRWalkDriver::GetName()
 OGRDataSource *OGRWalkDriver::Open( const char * pszFilename, int bUpdate )
 {
 
-    if( EQUALN(pszFilename, "PGEO:", strlen("PGEO:")) )
+    if( STARTS_WITH_CI(pszFilename, "PGEO:") )
         return NULL;
 
-    if( EQUALN(pszFilename, "GEOMEDIA:", strlen("GEOMEDIA:")) )
+    if( STARTS_WITH_CI(pszFilename, "GEOMEDIA:") )
         return NULL;
 
-    if( !EQUALN(pszFilename,"WALK:", strlen("WALK:"))
+    if( !STARTS_WITH_CI(pszFilename, "WALK:")
         && !EQUAL(CPLGetExtension(pszFilename), "MDB") )
         return NULL;
 
@@ -81,7 +81,7 @@ OGRDataSource *OGRWalkDriver::Open( const char * pszFilename, int bUpdate )
     //
     if ( !InstallMdbDriver() )
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
+        CPLError( CE_Warning, CPLE_AppDefined,
                   "Unable to install MDB driver for ODBC, MDB access may not supported.\n" );
     }
     else
@@ -115,7 +115,7 @@ OGRDataSource *OGRWalkDriver::CreateDataSource( const char * pszName,
     if( !poDS->Open( pszName, TRUE ) )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
          "Walk driver doesn't currently support database creation.\n"
                   "Please create database with the `createdb' command." );
         return NULL;
diff --git a/ogr/ogrsf_frmts/walk/ogrwalklayer.cpp b/ogr/ogrsf_frmts/walk/ogrwalklayer.cpp
index d2bbd20..d7c7a3f 100644
--- a/ogr/ogrsf_frmts/walk/ogrwalklayer.cpp
+++ b/ogr/ogrsf_frmts/walk/ogrwalklayer.cpp
@@ -61,7 +61,7 @@ OGRWalkLayer::~OGRWalkLayer()
     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     {
         CPLDebug( "Walk", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
+                  (int) m_nFeaturesRead,
                   poFeatureDefn->GetName() );
     }
 
@@ -82,13 +82,13 @@ OGRWalkLayer::~OGRWalkLayer()
 /*      set on a statement.  Sift out geometry and FID fields.          */
 /************************************************************************/
 
-CPLErr OGRWalkLayer::BuildFeatureDefn( const char *pszLayerName, 
-                                    CPLODBCStatement *poStmt )
+CPLErr OGRWalkLayer::BuildFeatureDefn( const char *pszLayerName,
+                                    CPLODBCStatement *poStmtIn )
 
 {
     poFeatureDefn = new OGRFeatureDefn( pszLayerName );
     SetDescription( poFeatureDefn->GetName() );
-    int    nRawColumns = poStmt->GetColCount();
+    int    nRawColumns = poStmtIn->GetColCount();
 
     poFeatureDefn->Reference();
     poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
@@ -97,15 +97,15 @@ CPLErr OGRWalkLayer::BuildFeatureDefn( const char *pszLayerName,
 
     for( int iCol = 0; iCol < nRawColumns; iCol++ )
     {
-        OGRFieldDefn    oField( poStmt->GetColName(iCol), OFTString );
+        OGRFieldDefn    oField( poStmtIn->GetColName(iCol), OFTString );
 
-        oField.SetWidth( MAX(0,poStmt->GetColSize( iCol )) );
+        oField.SetWidth( MAX(0,poStmtIn->GetColSize( iCol )) );
 
-        if( pszGeomColumn != NULL 
-            && EQUAL(poStmt->GetColName(iCol),pszGeomColumn) )    //If Geometry Column, continue to next field
+        if( pszGeomColumn != NULL
+            && EQUAL(poStmtIn->GetColName(iCol),pszGeomColumn) )    //If Geometry Column, continue to next field
             continue;
 
-        switch( CPLODBCStatement::GetTypeMapping(poStmt->GetColType(iCol)) )
+        switch( CPLODBCStatement::GetTypeMapping(poStmtIn->GetColType(iCol)) )
         {
             case SQL_C_SSHORT:
             case SQL_C_USHORT:
@@ -125,7 +125,7 @@ CPLErr OGRWalkLayer::BuildFeatureDefn( const char *pszLayerName,
 
             case SQL_C_NUMERIC:
                 oField.SetType( OFTReal );
-                oField.SetPrecision( poStmt->GetColPrecision(iCol) );
+                oField.SetPrecision( poStmtIn->GetColPrecision(iCol) );
                 break;
 
             case SQL_C_FLOAT:
@@ -193,7 +193,7 @@ void OGRWalkLayer::ResetReading()
 OGRFeature *OGRWalkLayer::GetNextFeature()
 
 {
-    while( TRUE )
+    while( true )
     {
         OGRFeature      *poFeature;
 
@@ -230,11 +230,10 @@ OGRFeature *OGRWalkLayer::GetNextRawFeature()
 /* -------------------------------------------------------------------- */
 /*      Create a feature from the current result.                       */
 /* -------------------------------------------------------------------- */
-    int         iField;
     OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
 
     if( pszFIDColumn != NULL && poStmt->GetColId(pszFIDColumn) > -1 )
-        poFeature->SetFID( 
+        poFeature->SetFID(
             atoi(poStmt->GetColData(poStmt->GetColId(pszFIDColumn))) );
     else
         poFeature->SetFID( iNextShapeId );
@@ -245,7 +244,7 @@ OGRFeature *OGRWalkLayer::GetNextRawFeature()
 /* -------------------------------------------------------------------- */
 /*      Set the fields.                                                 */
 /* -------------------------------------------------------------------- */
-    for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
+    for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     {
         int iSrcField = panFieldOrdinals[iField]-1;
         const char *pszValue = poStmt->GetColData( iSrcField );
@@ -253,7 +252,7 @@ OGRFeature *OGRWalkLayer::GetNextRawFeature()
         if( pszValue == NULL )
             /* no value */;
         else if( poFeature->GetFieldDefnRef(iField)->GetType() == OFTBinary )
-            poFeature->SetField( iField, 
+            poFeature->SetField( iField,
                                  poStmt->GetColDataLength(iSrcField),
                                  (GByte *) pszValue );
         else
@@ -274,9 +273,12 @@ OGRFeature *OGRWalkLayer::GetNextRawFeature()
         if( pszGeomBin != NULL && bGeomColumnWKB )
         {
             WKBGeometry *WalkGeom = (WKBGeometry *)CPLMalloc(sizeof(WKBGeometry));
-            if( Binary2WkbGeom((unsigned char *)pszGeomBin, WalkGeom, nGeomLength) 
+            if( Binary2WkbGeom((unsigned char *)pszGeomBin, WalkGeom, nGeomLength)
                 != OGRERR_NONE )
+            {
+                CPLFree(WalkGeom);
                 return NULL;
+            }
             eErr = TranslateWalkGeom(&poGeom, WalkGeom);
 
             DeleteWKBGeometry(*WalkGeom);
@@ -354,10 +356,10 @@ void OGRWalkLayer::LookupSpatialRef( const char * pszMemo )
     if ( strlen(pszProj4) > 0 )
     {
         poSRS = new OGRSpatialReference();
-    
+
         if( poSRS->importFromProj4( pszProj4 ) != OGRERR_NONE )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "importFromProj4() failed on SRS '%s'.",
                       pszProj4);
             delete poSRS;
diff --git a/ogr/ogrsf_frmts/walk/ogrwalktablelayer.cpp b/ogr/ogrsf_frmts/walk/ogrwalktablelayer.cpp
index cb95a05..2d18c2e 100644
--- a/ogr/ogrsf_frmts/walk/ogrwalktablelayer.cpp
+++ b/ogr/ogrsf_frmts/walk/ogrwalktablelayer.cpp
@@ -62,7 +62,7 @@ OGRWalkTableLayer::~OGRWalkTableLayer()
 /*                             Initialize()                             */
 /************************************************************************/
 
-CPLErr OGRWalkTableLayer::Initialize( const char *pszLayerName, 
+CPLErr OGRWalkTableLayer::Initialize( const char *pszLayerName,
                                       const char *pszGeomCol,
                                       double minE,
                                       double maxE,
@@ -94,19 +94,19 @@ CPLErr OGRWalkTableLayer::Initialize( const char *pszLayerName,
 /* -------------------------------------------------------------------- */
     char* pszFeatureTableName = (char *) CPLMalloc(strlen(pszLayerName)+10);
 
-    sprintf(pszFeatureTableName, "%sFeatures", pszLayerName);
+    snprintf(pszFeatureTableName, strlen(pszLayerName)+10, "%sFeatures", pszLayerName);
 
 /* -------------------------------------------------------------------- */
 /*      Do we have a simple primary key?                                */
 /* -------------------------------------------------------------------- */
     CPLODBCStatement oGetKey( poSession );
-    
-    if( oGetKey.GetPrimaryKeys( pszFeatureTableName, NULL, NULL ) 
+
+    if( oGetKey.GetPrimaryKeys( pszFeatureTableName, NULL, NULL )
         && oGetKey.Fetch() )
     {
         pszFIDColumn = CPLStrdup(oGetKey.GetColData( 3 ));
-        
-        if( oGetKey.Fetch() ) // more than one field in key! 
+
+        if( oGetKey.Fetch() ) // more than one field in key!
         {
             CPLFree( pszFIDColumn );
             pszFIDColumn = NULL;
@@ -146,13 +146,13 @@ CPLErr OGRWalkTableLayer::Initialize( const char *pszLayerName,
 
     if( poFeatureDefn->GetFieldCount() == 0 )
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
-                  "No column definitions found for table '%s', layer not usable.", 
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "No column definitions found for table '%s', layer not usable.",
                   pszLayerName );
         CPLFree( pszFeatureTableName );
         return CE_Failure;
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      If we got a geometry column, does it exist?  Is it binary?      */
 /* -------------------------------------------------------------------- */
@@ -161,8 +161,8 @@ CPLErr OGRWalkTableLayer::Initialize( const char *pszLayerName,
         int iColumn = oGetCol.GetColId( pszGeomColumn );
         if( iColumn < 0 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Column %s requested for geometry, but it does not exist.", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Column %s requested for geometry, but it does not exist.",
                       pszGeomColumn );
             CPLFree( pszGeomColumn );
             pszGeomColumn = NULL;
@@ -283,19 +283,19 @@ OGRFeature *OGRWalkTableLayer::GetFeature( GIntBig nFeatureId )
 /*                         SetAttributeFilter()                         */
 /************************************************************************/
 
-OGRErr OGRWalkTableLayer::SetAttributeFilter( const char *pszQuery )
+OGRErr OGRWalkTableLayer::SetAttributeFilter( const char *pszQueryIn )
 
 {
     CPLFree(m_pszAttrQueryString);
-    m_pszAttrQueryString = (pszQuery) ? CPLStrdup(pszQuery) : NULL;
+    m_pszAttrQueryString = (pszQueryIn) ? CPLStrdup(pszQueryIn) : NULL;
 
-    if( (pszQuery == NULL && this->pszQuery == NULL)
-        || (pszQuery != NULL && this->pszQuery != NULL 
-            && EQUAL(pszQuery,this->pszQuery)) )
+    if( (pszQueryIn == NULL && this->pszQuery == NULL)
+        || (pszQueryIn != NULL && this->pszQuery != NULL
+            && EQUAL(pszQueryIn,this->pszQuery)) )
         return OGRERR_NONE;
 
     CPLFree( this->pszQuery );
-    this->pszQuery = (pszQuery != NULL ) ? CPLStrdup( pszQuery ) : NULL;
+    this->pszQuery = (pszQueryIn != NULL ) ? CPLStrdup( pszQueryIn ) : NULL;
 
     ClearStatement();
 
@@ -312,8 +312,8 @@ int OGRWalkTableLayer::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,OLCRandomRead) )
         return TRUE;
-        
-    else 
+
+    else
         return OGRWalkLayer::TestCapability( pszCap );
 }
 
@@ -342,7 +342,7 @@ GIntBig OGRWalkTableLayer::GetFeatureCount( int bForce )
 
     if( !oStmt.ExecuteSQL() || !oStmt.Fetch() )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "GetFeatureCount() failed on query %s.\n%s",
                   oStmt.GetCommand(), poDS->GetSession()->GetLastError() );
         return OGRWalkLayer::GetFeatureCount(bForce);
diff --git a/ogr/ogrsf_frmts/walk/ogrwalktool.cpp b/ogr/ogrsf_frmts/walk/ogrwalktool.cpp
index 2758688..8682ed2 100644
--- a/ogr/ogrsf_frmts/walk/ogrwalktool.cpp
+++ b/ogr/ogrsf_frmts/walk/ogrwalktool.cpp
@@ -29,22 +29,18 @@
 
 #include "ogrwalk.h"
 
-#ifndef PI
-#define PI  3.14159265358979323846
-#endif 
-
 /************************************************************************/
 /*                   OGRWalkArcCenterFromEdgePoints()                   */
 /*                                                                      */
 /*      Compute the center of an arc/circle from three edge points.     */
 /************************************************************************/
 
-static int 
+static int
 OGRWalkArcCenterFromEdgePoints( double x_c0, double y_c0,
-                               double x_c1, double y_c1, 
-                               double x_c2, double y_c2, 
+                               double x_c1, double y_c1,
+                               double x_c2, double y_c2,
                                double *x_center, double *y_center )
-    
+
 {
 /* -------------------------------------------------------------------- */
 /*      Compute the inverse of the slopes connecting the first and      */
@@ -85,10 +81,10 @@ OGRWalkArcCenterFromEdgePoints( double x_c0, double y_c0,
 
     b1 = -1.0;
     b2 = -1.0;
-    
+
     c1 = (y1 - m1*x1);
     c2 = (y2 - m2*x2);
-    
+
 /* -------------------------------------------------------------------- */
 /*      Compute the intersection of the two lines through the center    */
 /*      of the circle, using Kramers rule.                              */
@@ -109,11 +105,11 @@ OGRWalkArcCenterFromEdgePoints( double x_c0, double y_c0,
 /************************************************************************/
 /*                       OGRWalkArcToLineString()                       */
 /************************************************************************/
-static int 
+static int
 OGRWalkArcToLineString( double dfStartX, double dfStartY,
                         double dfAlongX, double dfAlongY,
                         double dfEndX, double dfEndY,
-                        double dfCenterX, double dfCenterY, 
+                        double dfCenterX, double dfCenterY,
                         double dfCenterZ, double dfRadius,
                         int nNumPoints, OGRLineString *poLS )
 {
@@ -122,15 +118,15 @@ OGRWalkArcToLineString( double dfStartX, double dfStartY,
 
     dfDeltaX = dfStartX - dfCenterX;
     dfDeltaY = dfStartY - dfCenterY;
-    dfStartAngle = -1 * atan2(dfDeltaY,dfDeltaX) * 180.0 / PI;
+    dfStartAngle = -1 * atan2(dfDeltaY,dfDeltaX) * 180.0 / M_PI;
 
     dfDeltaX = dfAlongX - dfCenterX;
     dfDeltaY = dfAlongY - dfCenterY;
-    dfAlongAngle = -1 * atan2(dfDeltaY,dfDeltaX) * 180.0 / PI;
+    dfAlongAngle = -1 * atan2(dfDeltaY,dfDeltaX) * 180.0 / M_PI;
 
     dfDeltaX = dfEndX - dfCenterX;
     dfDeltaY = dfEndY - dfCenterY;
-    dfEndAngle = -1 * atan2(dfDeltaY,dfDeltaX) * 180.0 / PI;
+    dfEndAngle = -1 * atan2(dfDeltaY,dfDeltaX) * 180.0 / M_PI;
 
     // Try positive (clockwise?) winding.
     while( dfAlongAngle < dfStartAngle )
@@ -162,10 +158,10 @@ OGRWalkArcToLineString( double dfStartX, double dfStartY,
     else
         return FALSE;
 
-    OGRLineString* poArcpoLS = 
+    OGRLineString* poArcpoLS =
         (OGRLineString*)OGRGeometryFactory::approximateArcAngles(
             dfCenterX, dfCenterY, dfCenterZ,
-            dfRadius, dfRadius, 0.0, 
+            dfRadius, dfRadius, 0.0,
             dfStartAngle, dfEndAngle, 0.0 );
 
     if( poArcpoLS == NULL )
@@ -180,7 +176,7 @@ OGRWalkArcToLineString( double dfStartX, double dfStartY,
 /************************************************************************/
 /*                       Binary2WkbMGeom()                              */
 /************************************************************************/
-OGRErr Binary2WkbMGeom(unsigned char *& p, WKBGeometry* geom, int nBytes)
+static OGRErr Binary2WkbMGeom(unsigned char *& p, WKBGeometry* geom, int nBytes)
 {
     GUInt32 i,j,k;
 
@@ -209,7 +205,7 @@ OGRErr Binary2WkbMGeom(unsigned char *& p, WKBGeometry* geom, int nBytes)
         p += 4;
 
         geom->linestring.segments = new CurveSegment[geom->linestring.numSegments];
-        
+
         for(i = 0; i < geom->linestring.numSegments; i++)
         {
             memcpy(&geom->linestring.segments[i].lineType, p, 4);
@@ -218,11 +214,11 @@ OGRErr Binary2WkbMGeom(unsigned char *& p, WKBGeometry* geom, int nBytes)
             memcpy(&geom->linestring.segments[i].numPoints, p, 4);
             CPL_LSBPTR32(&geom->linestring.segments[i].numPoints);
             p += 4;
-            geom->linestring.segments[i].points = 
+            geom->linestring.segments[i].points =
                 new Point[geom->linestring.segments[i].numPoints];
             memcpy(geom->linestring.segments[i].points, p,
                 sizeof(Point) * geom->linestring.segments[i].numPoints);
-            CPL_LSBPTRPOINTS(geom->linestring.segments[i].points, 
+            CPL_LSBPTRPOINTS(geom->linestring.segments[i].points,
                 geom->linestring.segments[i].numPoints);
             p += sizeof(Point) * geom->linestring.segments[i].numPoints;
         }
@@ -232,15 +228,15 @@ OGRErr Binary2WkbMGeom(unsigned char *& p, WKBGeometry* geom, int nBytes)
         CPL_LSBPTR32(&geom->polygon.numRings);
         p += 4;
         geom->polygon.rings = new LineString[geom->polygon.numRings];
-        
+
         for(i = 0; i < geom->polygon.numRings; i++)
         {
             memcpy(&geom->polygon.rings[i].numSegments, p, 4);
             CPL_LSBPTR32(&geom->polygon.rings[i].numSegments);
             p += 4;
-            geom->polygon.rings[i].segments = 
+            geom->polygon.rings[i].segments =
                 new CurveSegment[geom->polygon.rings[i].numSegments];
-            
+
             for(j = 0; j < geom->polygon.rings[i].numSegments; j++)
             {
                 memcpy(&geom->polygon.rings[i].segments[j].lineType, p, 4);
@@ -249,11 +245,11 @@ OGRErr Binary2WkbMGeom(unsigned char *& p, WKBGeometry* geom, int nBytes)
                 memcpy(&geom->polygon.rings[i].segments[j].numPoints, p, 4);
                 CPL_LSBPTR32(&geom->polygon.rings[i].segments[j].numPoints);
                 p += 4;
-                geom->polygon.rings[i].segments[j].points = 
+                geom->polygon.rings[i].segments[j].points =
                     new Point[geom->polygon.rings[i].segments[j].numPoints];
-                memcpy(geom->polygon.rings[i].segments[j].points, p, 
+                memcpy(geom->polygon.rings[i].segments[j].points, p,
                     sizeof(Point) * geom->polygon.rings[i].segments[j].numPoints);
-                CPL_LSBPTRPOINTS(geom->polygon.rings[i].segments[j].points, 
+                CPL_LSBPTRPOINTS(geom->polygon.rings[i].segments[j].points,
                     geom->polygon.rings[i].segments[j].numPoints);
                 p += sizeof(Point) * geom->polygon.rings[i].segments[j].numPoints;
             }
@@ -272,17 +268,17 @@ OGRErr Binary2WkbMGeom(unsigned char *& p, WKBGeometry* geom, int nBytes)
         memcpy(&geom->mlinestring.num_wkbLineStrings, p, 4);
         CPL_LSBPTR32(&geom->mlinestring.num_wkbLineStrings);
         p += 4;
-        geom->mlinestring.WKBLineStrings = 
+        geom->mlinestring.WKBLineStrings =
             new WKBLineString[geom->mlinestring.num_wkbLineStrings];
-        
+
         for(i = 0; i < geom->mlinestring.num_wkbLineStrings; i++)
         {
             memcpy(&geom->mlinestring.WKBLineStrings[i].numSegments, p, 4);
             CPL_LSBPTR32(&geom->mlinestring.WKBLineStrings[i].numSegments);
             p += 4;
-            geom->mlinestring.WKBLineStrings[i].segments = 
+            geom->mlinestring.WKBLineStrings[i].segments =
                 new CurveSegment[geom->mlinestring.WKBLineStrings[i].numSegments];
-            
+
             for(j = 0; j < geom->mlinestring.WKBLineStrings[i].numSegments; j++)
             {
                 memcpy(&geom->mlinestring.WKBLineStrings[i].segments[j].lineType, p, 4);
@@ -291,7 +287,7 @@ OGRErr Binary2WkbMGeom(unsigned char *& p, WKBGeometry* geom, int nBytes)
                 memcpy(&geom->mlinestring.WKBLineStrings[i].segments[j].numPoints, p, 4);
                 CPL_LSBPTR32(&geom->mlinestring.WKBLineStrings[i].segments[j].numPoints);
                 p += 4;
-                geom->mlinestring.WKBLineStrings[i].segments[j].points = 
+                geom->mlinestring.WKBLineStrings[i].segments[j].points =
                     new Point[geom->mlinestring.WKBLineStrings[i].segments[j].numPoints];
                 memcpy(geom->mlinestring.WKBLineStrings[i].segments[j].points, p,
                     sizeof(Point) * geom->mlinestring.WKBLineStrings[i].segments[j].numPoints);
@@ -306,7 +302,7 @@ OGRErr Binary2WkbMGeom(unsigned char *& p, WKBGeometry* geom, int nBytes)
         CPL_LSBPTR32(&geom->mpolygon.num_wkbPolygons);
         p += 4;
         geom->mpolygon.WKBPolygons = new WKBPolygon[geom->mpolygon.num_wkbPolygons];
-        
+
         for(i = 0; i < geom->mpolygon.num_wkbPolygons; i++)
         {
             memcpy(&geom->mpolygon.WKBPolygons[i].numRings, p, 4);
@@ -314,7 +310,7 @@ OGRErr Binary2WkbMGeom(unsigned char *& p, WKBGeometry* geom, int nBytes)
             p += 4;
             geom->mpolygon.WKBPolygons[i].rings =
                 new LineString[geom->mpolygon.WKBPolygons[i].numRings];
-            
+
             for(j = 0; j < geom->mpolygon.WKBPolygons[i].numRings; j++)
             {
                 memcpy(&geom->mpolygon.WKBPolygons[i].rings[j].numSegments, p, 4);
@@ -322,7 +318,7 @@ OGRErr Binary2WkbMGeom(unsigned char *& p, WKBGeometry* geom, int nBytes)
                 p += 4;
                 geom->mpolygon.WKBPolygons[i].rings[j].segments =
                     new CurveSegment[geom->mpolygon.WKBPolygons[i].rings[j].numSegments];
-                
+
                 for(k = 0; k < geom->mpolygon.WKBPolygons[i].rings[j].numSegments; k++)
                 {
                     memcpy(&geom->mpolygon.WKBPolygons[i].rings[j].segments[k].lineType, p, 4);
@@ -333,12 +329,12 @@ OGRErr Binary2WkbMGeom(unsigned char *& p, WKBGeometry* geom, int nBytes)
                     p += 4;
                     geom->mpolygon.WKBPolygons[i].rings[j].segments[k].points =
                         new Point[geom->mpolygon.WKBPolygons[i].rings[j].segments[k].numPoints];
-                    memcpy(geom->mpolygon.WKBPolygons[i].rings[j].segments[k].points, 
-                        p, sizeof(Point) * 
+                    memcpy(geom->mpolygon.WKBPolygons[i].rings[j].segments[k].points,
+                        p, sizeof(Point) *
                         geom->mpolygon.WKBPolygons[i].rings[j].segments[k].numPoints);
                     CPL_LSBPTRPOINTS(geom->mpolygon.WKBPolygons[i].rings[j].segments[k].points,
                         geom->mpolygon.WKBPolygons[i].rings[j].segments[k].numPoints);
-                    p += sizeof(Point) * 
+                    p += sizeof(Point) *
                         geom->mpolygon.WKBPolygons[i].rings[j].segments[k].numPoints;
                 }
             }
@@ -398,9 +394,9 @@ OGRErr Binary2WkbGeom(unsigned char *p, WKBGeometry* geom, int nBytes)
 /************************************************************************/
 /*                       TranslateWalkPoint()                           */
 /************************************************************************/
-OGRBoolean TranslateWalkPoint(OGRPoint *poPoint, WKBPoint* pWalkWkbPoint)
+static OGRBoolean TranslateWalkPoint(OGRPoint *poPoint, WKBPoint* pWalkWkbPoint)
 {
-    if ( poPoint == NULL || pWalkWkbPoint == NULL ) 
+    if ( poPoint == NULL || pWalkWkbPoint == NULL )
         return FALSE;
 
     poPoint->setX(pWalkWkbPoint->x);
@@ -412,7 +408,7 @@ OGRBoolean TranslateWalkPoint(OGRPoint *poPoint, WKBPoint* pWalkWkbPoint)
 /************************************************************************/
 /*                    TranslateCurveSegment()                           */
 /************************************************************************/
-OGRBoolean TranslateCurveSegment(OGRLineString *poLS, CurveSegment* pSegment)
+static OGRBoolean TranslateCurveSegment(OGRLineString *poLS, CurveSegment* pSegment)
 {
     if ( poLS == NULL || pSegment == NULL )
         return FALSE;
@@ -461,7 +457,7 @@ OGRBoolean TranslateCurveSegment(OGRLineString *poLS, CurveSegment* pSegment)
 /************************************************************************/
 /*                    TranslateWalkLineString()                         */
 /************************************************************************/
-OGRBoolean TranslateWalkLineString(OGRLineString *poLS, LineString* pLineString)
+static OGRBoolean TranslateWalkLineString(OGRLineString *poLS, LineString* pLineString)
 {
     if ( poLS == NULL || pLineString == NULL )
         return FALSE;
@@ -478,7 +474,7 @@ OGRBoolean TranslateWalkLineString(OGRLineString *poLS, LineString* pLineString)
 /************************************************************************/
 /*                    TranslateWalkLinearring()                         */
 /************************************************************************/
-OGRBoolean TranslateWalkLinearring(OGRLinearRing *poRing, LineString* pLineString)
+static OGRBoolean TranslateWalkLinearring(OGRLinearRing *poRing, LineString* pLineString)
 {
     if ( poRing == NULL || pLineString == NULL )
         return FALSE;
@@ -492,7 +488,7 @@ OGRBoolean TranslateWalkLinearring(OGRLinearRing *poRing, LineString* pLineStrin
 /************************************************************************/
 /*                    TranslateWalkPolygon()                            */
 /************************************************************************/
-OGRBoolean TranslateWalkPolygon(OGRPolygon *poPolygon, WKBPolygon* pWalkWkbPolgon)
+static OGRBoolean TranslateWalkPolygon(OGRPolygon *poPolygon, WKBPolygon* pWalkWkbPolgon)
 {
     if ( poPolygon == NULL || pWalkWkbPolgon == NULL )
         return FALSE;
@@ -516,7 +512,7 @@ OGRErr TranslateWalkGeom(OGRGeometry **ppoGeom, WKBGeometry* geom)
     if ( ppoGeom == NULL || geom == NULL )
         return OGRERR_NOT_ENOUGH_DATA;
 
-    OGRGeometry* poGeom = 
+    OGRGeometry* poGeom =
         OGRGeometryFactory::createGeometry(wkbFlatten(geom->wkbType));
 
     if ( poGeom == NULL )
@@ -527,19 +523,28 @@ OGRErr TranslateWalkGeom(OGRGeometry **ppoGeom, WKBGeometry* geom)
     case wkbPoint:
         {
             if (!TranslateWalkPoint((OGRPoint *)poGeom, &geom->point))
+            {
+                delete poGeom;
                 return OGRERR_CORRUPT_DATA;
+            }
         }
         break;
     case wkbLineString:
         {
             if (!TranslateWalkLineString((OGRLineString *)poGeom, &geom->linestring))
+            {
+                delete poGeom;
                 return OGRERR_CORRUPT_DATA;
+            }
         }
         break;
     case wkbPolygon:
         {
             if (!TranslateWalkPolygon((OGRPolygon *)poGeom, &geom->polygon))
+            {
+                delete poGeom;
                 return OGRERR_CORRUPT_DATA;
+            }
         }
         break;
     case wkbMultiPoint:
@@ -548,7 +553,11 @@ OGRErr TranslateWalkGeom(OGRGeometry **ppoGeom, WKBGeometry* geom)
             {
                 OGRPoint* poPoint = new OGRPoint();
                 if (!TranslateWalkPoint(poPoint, &geom->mpoint.WKBPoints[i]))
+                {
+                    delete poPoint;
+                    delete poGeom;
                     return OGRERR_CORRUPT_DATA;
+                }
                 ((OGRMultiPoint *)poGeom)->addGeometryDirectly(poPoint);
             }
         }
@@ -559,7 +568,11 @@ OGRErr TranslateWalkGeom(OGRGeometry **ppoGeom, WKBGeometry* geom)
             {
                 OGRLineString* poLS = new OGRLineString();
                 if (!TranslateWalkLineString(poLS, &geom->mlinestring.WKBLineStrings[i]))
+                {
+                    delete poLS;
+                    delete poGeom;
                     return OGRERR_CORRUPT_DATA;
+                }
                 ((OGRMultiLineString *)poGeom)->addGeometryDirectly(poLS);
             }
         }
@@ -570,7 +583,11 @@ OGRErr TranslateWalkGeom(OGRGeometry **ppoGeom, WKBGeometry* geom)
             {
                 OGRPolygon* poPolygon = new OGRPolygon();
                 if (!TranslateWalkPolygon(poPolygon, &geom->mpolygon.WKBPolygons[i]))
+                {
+                    delete poPolygon;
+                    delete poGeom;
                     return OGRERR_CORRUPT_DATA;
+                }
                 ((OGRMultiPolygon *)poGeom)->addGeometryDirectly(poPolygon);
             }
         }
@@ -586,7 +603,11 @@ OGRErr TranslateWalkGeom(OGRGeometry **ppoGeom, WKBGeometry* geom)
                         {
                             OGRPoint* poPoint = new OGRPoint();
                             if (!TranslateWalkPoint(poPoint, &sg->point))
+                            {
+                                delete poPoint;
+                                delete poGeom;
                                 return OGRERR_CORRUPT_DATA;
+                            }
                             ((OGRGeometryCollection *)poGeom)->addGeometryDirectly(poPoint);
                         }
                         break;
@@ -594,24 +615,37 @@ OGRErr TranslateWalkGeom(OGRGeometry **ppoGeom, WKBGeometry* geom)
                         {
                             OGRLineString* poLS = new OGRLineString();
                             if (!TranslateWalkLineString(poLS, &sg->linestring))
+                            {
+                                delete poLS;
+                                delete poGeom;
                                 return OGRERR_CORRUPT_DATA;
+                            }
                             ((OGRGeometryCollection *)poGeom)->addGeometryDirectly(poLS);
                         }
                         break;
                     case wkbPolygon:
                         {
-                            OGRPolygon* poPolygon = new OGRPolygon();    
+                            OGRPolygon* poPolygon = new OGRPolygon();
                             if (!TranslateWalkPolygon(poPolygon, &sg->polygon))
+                            {
+                                delete poPolygon;
+                                delete poGeom;
                                 return OGRERR_CORRUPT_DATA;
+                            }
                             ((OGRGeometryCollection *)poGeom)->addGeometryDirectly(poPolygon);
                         }
                         break;
-                    default: return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
-                }                
+                    default:
+                    {
+                        delete poGeom;
+                        return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
+                    }
+                }
             }
         }
         break;
     default:
+        delete poGeom;
         return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
     }
 
@@ -623,7 +657,7 @@ OGRErr TranslateWalkGeom(OGRGeometry **ppoGeom, WKBGeometry* geom)
 /************************************************************************/
 /*                      DeleteCurveSegment()                            */
 /************************************************************************/
-void DeleteCurveSegment(CurveSegment &obj)
+static void DeleteCurveSegment(CurveSegment &obj)
 {
     if(obj.numPoints)
         delete [] obj.points;
@@ -632,7 +666,7 @@ void DeleteCurveSegment(CurveSegment &obj)
 /************************************************************************/
 /*                      DeleteWKBMultiPoint()                           */
 /************************************************************************/
-void DeleteWKBMultiPoint(WKBMultiPoint &obj)
+static void DeleteWKBMultiPoint(WKBMultiPoint &obj)
 {
     if (obj.num_wkbPoints)
     {
@@ -644,7 +678,7 @@ void DeleteWKBMultiPoint(WKBMultiPoint &obj)
 /************************************************************************/
 /*                      DeleteWKBLineString()                           */
 /************************************************************************/
-void DeleteWKBLineString(WKBLineString &obj)
+static void DeleteWKBLineString(WKBLineString &obj)
 {
     if(obj.numSegments)
     {
@@ -658,7 +692,7 @@ void DeleteWKBLineString(WKBLineString &obj)
 /************************************************************************/
 /*                     DeleteWKBMultiLineString()                       */
 /************************************************************************/
-void DeleteWKBMultiLineString(WKBMultiLineString &obj)
+static void DeleteWKBMultiLineString(WKBMultiLineString &obj)
 {
     if (obj.num_wkbLineStrings)
     {
@@ -673,7 +707,7 @@ void DeleteWKBMultiLineString(WKBMultiLineString &obj)
 /************************************************************************/
 /*                        DeleteWKBPolygon()                            */
 /************************************************************************/
-void DeleteWKBPolygon(WKBPolygon &obj)
+static void DeleteWKBPolygon(WKBPolygon &obj)
 {
     if (obj.numRings)
     {
@@ -688,7 +722,7 @@ void DeleteWKBPolygon(WKBPolygon &obj)
 /************************************************************************/
 /*                      DeleteWKBMultiPolygon()                         */
 /************************************************************************/
-void DeleteWKBMultiPolygon(WKBMultiPolygon &obj)
+static void DeleteWKBMultiPolygon(WKBMultiPolygon &obj)
 {
     if (obj.num_wkbPolygons)
     {
@@ -703,7 +737,7 @@ void DeleteWKBMultiPolygon(WKBMultiPolygon &obj)
 /************************************************************************/
 /*                    DeleteWKBGeometryCollection()                     */
 /************************************************************************/
-void DeleteWKBGeometryCollection(WKBGeometryCollection &obj)
+static void DeleteWKBGeometryCollection(WKBGeometryCollection &obj)
 {
     if (obj.num_wkbSGeometries)
     {
@@ -750,4 +784,4 @@ void DeleteWKBGeometry(WKBGeometry &obj)
         break;
     }
     obj.wkbType = wkbUnknown;
-}
\ No newline at end of file
+}
diff --git a/ogr/ogrsf_frmts/wasp/GNUmakefile b/ogr/ogrsf_frmts/wasp/GNUmakefile
index 891ff22..47bf2b9 100644
--- a/ogr/ogrsf_frmts/wasp/GNUmakefile
+++ b/ogr/ogrsf_frmts/wasp/GNUmakefile
@@ -6,7 +6,6 @@ OBJ	=	ogrwaspdriver.o ogrwaspdatasource.o ogrwasplayer.o
 
 CPPFLAGS	:=	-I.. -I../..  $(CPPFLAGS)
 
-
 default:	$(O_OBJ:.o=.$(OBJ_EXT))
 
 clean:
diff --git a/ogr/ogrsf_frmts/wasp/drv_wasp.html b/ogr/ogrsf_frmts/wasp/drv_wasp.html
index 56633ce..4f45678 100644
--- a/ogr/ogrsf_frmts/wasp/drv_wasp.html
+++ b/ogr/ogrsf_frmts/wasp/drv_wasp.html
@@ -14,16 +14,16 @@ This driver writes .map files to be used with WAsP. The only allowed geometries
 <h3>Configuration options</h3>
 
 <ul>
-    <li>WASP_FIELDS : a coma separated list of fields. For elevation, the name of the height field. For rouhgness, the name of the left and right roughness fields resp.</li>
-    <li>WASP_MERGE : this may be set to "NO". Used only when generating roughness from polygons. All polygon boundaries will be output (including those with the same left and righ roughness). This is useful (along with option -skipfailures) for debugging incorect input geometries.</li>
+    <li>WASP_FIELDS : a comma separated list of fields. For elevation, the name of the height field. For roughness, the name of the left and right roughness fields resp.</li>
+    <li>WASP_MERGE : this may be set to "NO". Used only when generating roughness from polygons. All polygon boundaries will be output (including those with the same left and right roughness). This is useful (along with option -skipfailures) for debugging incorrect input geometries.</li>
     <li>WASP_GEOM_FIELD : in case input has several geometry columns and the first one (default) is not the right one.</li>
     <li>WASP_TOLERANCE : specify a tolerance for line simplification of output (calls geos).</li>
-    <li>WASP_ADJ_TOLER : points that are less than tolerance appart from previous point on x and on y are ommited.</li>
-    <li>WASP_POINT_TO_CIRCLE_RADIUS : lines that became points du to simplification are replaces by 8 point circles (octogons).</li>
+    <li>WASP_ADJ_TOLER : points that are less than tolerance apart from previous point on x and on y are omitted.</li>
+    <li>WASP_POINT_TO_CIRCLE_RADIUS : lines that became points due to simplification are replaces by 8 point circles (octagons).</li>
 </ul>
 
 <p>
-Note that if not option is specified, the layer is assumed to be an elevation layer where the elevation is the z-components of the linestrings' points. 
+Note that if not option is specified, the layer is assumed to be an elevation layer where the elevation is the z-components of the linestrings' points.
 </p>
 </body>
 </html>
diff --git a/ogr/ogrsf_frmts/wasp/ogrwasp.h b/ogr/ogrsf_frmts/wasp/ogrwasp.h
index 2bdd41e..9a773af 100644
--- a/ogr/ogrsf_frmts/wasp/ogrwasp.h
+++ b/ogr/ogrsf_frmts/wasp/ogrwasp.h
@@ -26,8 +26,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_WASP_H_INCLUDED
-#define _OGR_WASP_H_INCLUDED
+#ifndef OGR_WASP_H_INCLUDED
+#define OGR_WASP_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 
@@ -35,6 +35,12 @@
 #include <fstream>
 #include <vector>
 
+#if __cplusplus >= 201103L
+#define UNIQUEPTR       std::unique_ptr
+#else
+#define UNIQUEPTR       std::auto_ptr
+#endif
+
 /************************************************************************/
 /*                             OGRWAsPLayer                             */
 /************************************************************************/
@@ -73,7 +79,7 @@ class OGRWAsPLayer : public OGRLayer
     VSILFILE *            hFile;
 
     /* for roughness zone, two fields for linestrings (left/right), one for polygons */
-    /* for elevation, one fiels (height) */
+    /* for elevation, one field (height) */
     const CPLString       sFirstField;
     const CPLString       sSecondField;
     const CPLString       sGeomField;
@@ -89,9 +95,9 @@ class OGRWAsPLayer : public OGRLayer
     enum OpenMode {READ_ONLY, WRITE_ONLY};
     OpenMode              eMode;
 
-    std::auto_ptr<double> pdfTolerance;
-    std::auto_ptr<double> pdfAdjacentPointTolerance;
-    std::auto_ptr<double> pdfPointToCircleRadius;
+    UNIQUEPTR<double> pdfTolerance;
+    UNIQUEPTR<double> pdfAdjacentPointTolerance;
+    UNIQUEPTR<double> pdfPointToCircleRadius;
 
     OGRErr                WriteRoughness( OGRLineString *,
                                           const double & dfZleft,
@@ -110,24 +116,24 @@ class OGRWAsPLayer : public OGRLayer
     static double AvgZ( OGRGeometryCollection * poGeom );
     static double AvgZ( OGRGeometry * poGeom );
 
-    /* return a simplified line (caller is responsible for resource )
+    /* return a simplified line (caller is responsible for resource)
      *
-     * if pdfTolerance is not NULL, 
-     *     calls GEOS symplify
+     * if pdfTolerance is not NULL,
+     *     calls GEOS simplify
      *
-     * if pdfAdjacentPointTolerance is not NULL, 
-     *     remove consecutive points that are less than torelance appart 
+     * if pdfAdjacentPointTolerance is not NULL,
+     *     remove consecutive points that are less than tolerance apart
      *     in x and y
      *
      * if pdfPointToCircleRadius is not NULL,
      *     lines that have been simplified to a point are converted to a 8 pt circle
      * */
     OGRLineString * Simplify( const OGRLineString & line ) const;
-    
+
   public:
                         /* For writing */
                         /* Takes ownership of poTolerance */
-                        OGRWAsPLayer( const char * pszName, 
+                        OGRWAsPLayer( const char * pszName,
                                       VSILFILE * hFile,
                                       OGRSpatialReference * poSpatialRef,
                                       const CPLString & sFirstField,
@@ -139,7 +145,7 @@ class OGRWAsPLayer : public OGRLayer
                                       double * pdfPointToCircleRadius );
 
                         /* For reading */
-                        OGRWAsPLayer( const char * pszName, 
+                        OGRWAsPLayer( const char * pszName,
                                       VSILFILE * hFile,
                                       OGRSpatialReference * poSpatialRef );
 
@@ -172,15 +178,15 @@ class OGRWAsPDataSource : public OGRDataSource
 {
     CPLString                     sFilename;
     VSILFILE *                    hFile;
-    std::auto_ptr<OGRWAsPLayer>   oLayer;
+    UNIQUEPTR<OGRWAsPLayer>   oLayer;
 
-    void               GetOptions(CPLString & sFirstField, 
+    void               GetOptions(CPLString & sFirstField,
                                   CPLString & sSecondField,
                                   CPLString & sGeomField,
                                   bool &      bMerge) const;
   public:
                         /** @note takes ownership of hFile (i.e. responsibility for closing) */
-                        OGRWAsPDataSource( const char * pszName, 
+                        OGRWAsPDataSource( const char * pszName,
                                            VSILFILE * hFile );
                         ~OGRWAsPDataSource();
 
@@ -189,11 +195,11 @@ class OGRWAsPDataSource : public OGRDataSource
     virtual OGRLayer   *GetLayer( int );
     virtual OGRLayer   *GetLayerByName( const char * );
 
-    virtual OGRLayer   *ICreateLayer( const char *pszName, 
+    virtual OGRLayer   *ICreateLayer( const char *pszName,
                                      OGRSpatialReference *poSpatialRef = NULL,
                                      OGRwkbGeometryType eGType = wkbUnknown,
                                      char ** papszOptions = NULL );
-    
+
     virtual int        TestCapability( const char * );
     OGRErr             Load( bool bSilent = false );
 };
@@ -210,7 +216,7 @@ class OGRWAsPDriver : public OGRSFDriver
 
     virtual const char*         GetName() { return "WAsP"; }
     virtual OGRDataSource*      Open( const char *, int );
-    
+
     virtual OGRDataSource       *CreateDataSource( const char *pszName,
                                                    char ** = NULL );
 
@@ -220,4 +226,4 @@ class OGRWAsPDriver : public OGRSFDriver
 };
 
 
-#endif /* ndef _OGR_WASP_H_INCLUDED */
+#endif /* ndef OGR_WASP_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/wasp/ogrwaspdatasource.cpp b/ogr/ogrsf_frmts/wasp/ogrwaspdatasource.cpp
index 874aab9..7e5b563 100644
--- a/ogr/ogrsf_frmts/wasp/ogrwaspdatasource.cpp
+++ b/ogr/ogrsf_frmts/wasp/ogrwaspdatasource.cpp
@@ -38,7 +38,7 @@
 /*                          OGRWAsPDataSource()                          */
 /************************************************************************/
 
-OGRWAsPDataSource::OGRWAsPDataSource( const char * pszName, 
+OGRWAsPDataSource::OGRWAsPDataSource( const char * pszName,
                                       VSILFILE * hFileHandle )
     : sFilename( pszName )
     , hFile( hFileHandle )
@@ -74,8 +74,8 @@ int OGRWAsPDataSource::TestCapability( const char * pszCap )
 OGRLayer *OGRWAsPDataSource::GetLayerByName( const char * pszName )
 
 {
-    return ( oLayer.get() && EQUAL( pszName, oLayer->GetName() ) ) 
-        ? oLayer.get() 
+    return ( oLayer.get() && EQUAL( pszName, oLayer->GetName() ) )
+        ? oLayer.get()
         : NULL;
 }
 
@@ -92,7 +92,7 @@ OGRErr OGRWAsPDataSource::Load(bool bSilent)
         if (!bSilent) CPLError( CE_Failure, CPLE_NotSupported, "layer already loaded");
         return OGRERR_FAILURE;
     }
-    /* Parse the first line of the file in case it'a a spatial ref*/
+    /* Parse the first line of the file in case it's a spatial ref*/
     const char * pszLine = CPLReadLine2L( hFile, 1024, NULL );
     if ( !pszLine )
     {
@@ -114,20 +114,20 @@ OGRErr OGRWAsPDataSource::Load(bool bSilent)
     CPLReadLineL( hFile );
     CPLReadLineL( hFile );
 
-    oLayer.reset( new OGRWAsPLayer( CPLGetBasename(sFilename.c_str()), 
-                                    hFile, 
+    oLayer.reset( new OGRWAsPLayer( CPLGetBasename(sFilename.c_str()),
+                                    hFile,
                                     poSpatialRef ) );
     if (poSpatialRef) poSpatialRef->Release();
 
     const vsi_l_offset iOffset = VSIFTellL( hFile );
     pszLine = CPLReadLineL( hFile );
-    if ( !pszLine ) 
+    if ( !pszLine )
     {
         if (!bSilent) CPLError( CE_Failure, CPLE_FileIO, "no feature in file");
         oLayer.reset();
         return OGRERR_FAILURE;
     }
-    
+
     double dfValues[4];
     int iNumValues = 0;
     {
@@ -136,9 +136,9 @@ OGRErr OGRWAsPDataSource::Load(bool bSilent)
 
         if ( iNumValues < 2 )
         {
-            if (!bSilent && iNumValues) 
+            if (!bSilent && iNumValues)
                 CPLError(CE_Failure, CPLE_FileIO, "no enough values" );
-            else if (!bSilent) 
+            else if (!bSilent)
                 CPLError(CE_Failure, CPLE_FileIO, "no feature in file" );
 
             oLayer.reset();
@@ -159,7 +159,7 @@ OGRErr OGRWAsPDataSource::Load(bool bSilent)
         oLayer->CreateField( &height );
     }
 
-    VSIFSeekL( hFile, iOffset, SEEK_SET );	
+    VSIFSeekL( hFile, iOffset, SEEK_SET );
     return OGRERR_NONE;
 }
 
@@ -179,7 +179,7 @@ OGRLayer *OGRWAsPDataSource::GetLayer( int iLayer )
 /*                             ICreateLayer()                           */
 /************************************************************************/
 
-OGRLayer *OGRWAsPDataSource::ICreateLayer(const char *pszName, 
+OGRLayer *OGRWAsPDataSource::ICreateLayer(const char *pszName,
                                      OGRSpatialReference *poSpatialRef,
                                      OGRwkbGeometryType eGType,
                                      char ** papszOptions)
@@ -195,28 +195,28 @@ OGRLayer *OGRWAsPDataSource::ICreateLayer(const char *pszName,
       && eGType != wkbMultiPolygon
       && eGType != wkbMultiPolygon25D )
     {
-        CPLError( CE_Failure, 
-                CPLE_NotSupported, 
+        CPLError( CE_Failure,
+                CPLE_NotSupported,
                 "unsupported geometry type %s", OGRGeometryTypeToName( eGType ) );
         return NULL;
     }
 
-    if ( !OGRGeometryFactory::haveGEOS() 
+    if ( !OGRGeometryFactory::haveGEOS()
             && ( eGType == wkbPolygon
               || eGType == wkbPolygon25D
               || eGType == wkbMultiPolygon
               || eGType == wkbMultiPolygon25D ))
     {
-        CPLError( CE_Failure, 
-                CPLE_NotSupported, 
+        CPLError( CE_Failure,
+                CPLE_NotSupported,
                 "unsupported geometry type %s without GEOS support", OGRGeometryTypeToName( eGType ) );
         return NULL;
     }
 
     if ( oLayer.get() )
     {
-        CPLError( CE_Failure, 
-                CPLE_NotSupported, 
+        CPLError( CE_Failure,
+                CPLE_NotSupported,
                 "this data source does not support more than one layer" );
         return NULL;
     }
@@ -227,12 +227,12 @@ OGRLayer *OGRWAsPDataSource::ICreateLayer(const char *pszName,
     const CPLString sFields( pszFields ? pszFields : "" );
     if ( ! sFields.empty() )
     {
-        /* parse the coma separated list of fields */
-        const size_t iComa = sFields.find(',');
-        if ( std::string::npos != iComa )
+        /* parse the comma separated list of fields */
+        const size_t iComma = sFields.find(',');
+        if ( std::string::npos != iComma )
         {
-            sFirstField = sFields.substr(0, iComa); 
-            sSecondField = sFields.substr( iComa + 1 );
+            sFirstField = sFields.substr(0, iComma);
+            sSecondField = sFields.substr( iComma + 1 );
         }
         else
         {
@@ -243,9 +243,9 @@ OGRLayer *OGRWAsPDataSource::ICreateLayer(const char *pszName,
     const char *pszGeomField = CSLFetchNameValue( papszOptions, "WASP_GEOM_FIELD" );
     sGeomField = CPLString( pszGeomField ? pszGeomField : "" );
 
-    const bool bMerge = CSLTestBoolean(CSLFetchNameValueDef( papszOptions, "WASP_MERGE", "YES" ));
+    const bool bMerge = CPLTestBool(CSLFetchNameValueDef( papszOptions, "WASP_MERGE", "YES" ));
 
-    std::auto_ptr<double> pdfTolerance;
+    UNIQUEPTR<double> pdfTolerance;
     {
         const char *pszToler = CSLFetchNameValue( papszOptions, "WASP_TOLERANCE" );
 
@@ -253,8 +253,8 @@ OGRLayer *OGRWAsPDataSource::ICreateLayer(const char *pszName,
         {
             if ( !OGRGeometryFactory::haveGEOS() )
             {
-                CPLError( CE_Warning, 
-                        CPLE_IllegalArg, 
+                CPLError( CE_Warning,
+                        CPLE_IllegalArg,
                         "GEOS support not enabled, ignoring option WASP_TOLERANCE" );
             }
             else
@@ -262,8 +262,8 @@ OGRLayer *OGRWAsPDataSource::ICreateLayer(const char *pszName,
                 pdfTolerance.reset( new double );
                 if (!(std::istringstream( pszToler ) >> *pdfTolerance ))
                 {
-                    CPLError( CE_Failure, 
-                            CPLE_IllegalArg, 
+                    CPLError( CE_Failure,
+                            CPLE_IllegalArg,
                             "cannot set tolerance from %s", pszToler );
                     return NULL;
                 }
@@ -271,7 +271,7 @@ OGRLayer *OGRWAsPDataSource::ICreateLayer(const char *pszName,
         }
     }
 
-    std::auto_ptr<double> pdfAdjacentPointTolerance;
+    UNIQUEPTR<double> pdfAdjacentPointTolerance;
     {
         const char *pszAdjToler = CSLFetchNameValue( papszOptions, "WASP_ADJ_TOLER" );
         if ( pszAdjToler )
@@ -279,15 +279,15 @@ OGRLayer *OGRWAsPDataSource::ICreateLayer(const char *pszName,
             pdfAdjacentPointTolerance.reset( new double );
             if (!(std::istringstream( pszAdjToler ) >> *pdfAdjacentPointTolerance ))
             {
-                CPLError( CE_Failure, 
-                        CPLE_IllegalArg, 
+                CPLError( CE_Failure,
+                        CPLE_IllegalArg,
                         "cannot set tolerance from %s", pszAdjToler );
                 return NULL;
             }
         }
     }
 
-    std::auto_ptr<double> pdfPointToCircleRadius;
+    UNIQUEPTR<double> pdfPointToCircleRadius;
     {
         const char *pszPtToCircRad = CSLFetchNameValue( papszOptions, "WASP_POINT_TO_CIRCLE_RADIUS" );
         if ( pszPtToCircRad )
@@ -295,18 +295,18 @@ OGRLayer *OGRWAsPDataSource::ICreateLayer(const char *pszName,
             pdfPointToCircleRadius.reset( new double );
             if (!(std::istringstream( pszPtToCircRad ) >> *pdfPointToCircleRadius ))
             {
-                CPLError( CE_Failure, 
-                        CPLE_IllegalArg, 
+                CPLError( CE_Failure,
+                        CPLE_IllegalArg,
                         "cannot set tolerance from %s", pszPtToCircRad );
                 return NULL;
             }
         }
     }
 
-    oLayer.reset( new OGRWAsPLayer( CPLGetBasename(pszName), 
-                                    hFile, 
+    oLayer.reset( new OGRWAsPLayer( CPLGetBasename(pszName),
+                                    hFile,
                                     poSpatialRef,
-                                    sFirstField, 
+                                    sFirstField,
                                     sSecondField,
                                     sGeomField,
                                     bMerge,
@@ -315,21 +315,19 @@ OGRLayer *OGRWAsPDataSource::ICreateLayer(const char *pszName,
                                     pdfPointToCircleRadius.release() ) );
 
     char * ppszWktSpatialRef = NULL ;
-    if ( poSpatialRef 
+    if ( poSpatialRef
             && poSpatialRef->exportToProj4( &ppszWktSpatialRef ) == OGRERR_NONE )
     {
         VSIFPrintfL( hFile, "%s\n", ppszWktSpatialRef );
-        OGRFree( ppszWktSpatialRef );
     }
     else
     {
         VSIFPrintfL( hFile, "no spatial ref sys\n" );
     }
+    OGRFree( ppszWktSpatialRef );
 
     VSIFPrintfL( hFile, "  0.0 0.0 0.0 0.0\n" );
     VSIFPrintfL( hFile, "  1.0 0.0 1.0 0.0\n" );
     VSIFPrintfL( hFile, "  1.0 0.0\n" );
     return oLayer.get();
 }
-
-
diff --git a/ogr/ogrsf_frmts/wasp/ogrwaspdriver.cpp b/ogr/ogrsf_frmts/wasp/ogrwaspdriver.cpp
index d41b4d1..668e886 100644
--- a/ogr/ogrsf_frmts/wasp/ogrwaspdriver.cpp
+++ b/ogr/ogrsf_frmts/wasp/ogrwaspdriver.cpp
@@ -53,7 +53,7 @@ OGRDataSource *OGRWAsPDriver::Open( const char * pszFilename, int bUpdate )
         /*CPLError( CE_Failure, CPLE_FileIO, "cannot open file %s", pszFilename );*/
         return NULL;
     }
-    std::auto_ptr<OGRWAsPDataSource> pDataSource( new OGRWAsPDataSource( pszFilename, fh ));
+    UNIQUEPTR<OGRWAsPDataSource> pDataSource( new OGRWAsPDataSource( pszFilename, fh ));
 
     if ( pDataSource->Load(true) != OGRERR_NONE )
     {
@@ -69,7 +69,7 @@ OGRDataSource *OGRWAsPDriver::Open( const char * pszFilename, int bUpdate )
 int OGRWAsPDriver::TestCapability( const char * pszCap )
 
 {
-    return EQUAL(pszCap,ODrCCreateDataSource) 
+    return EQUAL(pszCap,ODrCCreateDataSource)
         || EQUAL(pszCap,ODrCDeleteDataSource);
 }
 
@@ -96,7 +96,7 @@ OGRDataSource * OGRWAsPDriver::CreateDataSource( const char *pszName, char ** )
 OGRErr OGRWAsPDriver::DeleteDataSource (const char *pszName)
 
 {
-    return VSIUnlink( pszName ) == 0 ? OGRERR_NONE : OGRERR_FAILURE;  	
+    return VSIUnlink( pszName ) == 0 ? OGRERR_NONE : OGRERR_FAILURE;
 }
 
 /************************************************************************/
@@ -107,13 +107,11 @@ void RegisterOGRWAsP()
 
 {
     OGRSFDriver* poDriver = new OGRWAsPDriver;
-    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                "WAsP .map format" );
-    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "map" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                "drv_wasp.html" );
 
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "WAsP .map format" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "map" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_wasp.html" );
     poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
     OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver(poDriver);
 }
-
diff --git a/ogr/ogrsf_frmts/wasp/ogrwasplayer.cpp b/ogr/ogrsf_frmts/wasp/ogrwasplayer.cpp
index 34891ab..fed9974 100644
--- a/ogr/ogrsf_frmts/wasp/ogrwasplayer.cpp
+++ b/ogr/ogrsf_frmts/wasp/ogrwasplayer.cpp
@@ -32,18 +32,14 @@
 #include "ogrsf_frmts.h"
 
 #include <cassert>
-#include <sstream>
 #include <map>
-
-#ifndef M_PI
-# define M_PI  3.1415926535897932384626433832795
-#endif
+#include <sstream>
 
 /************************************************************************/
 /*                            OGRWAsPLayer()                             */
 /************************************************************************/
 
-OGRWAsPLayer::OGRWAsPLayer( const char * pszName, 
+OGRWAsPLayer::OGRWAsPLayer( const char * pszName,
                             VSILFILE * hFileHandle,
                             OGRSpatialReference * poSpatialRef )
     : bMerge( false )
@@ -67,7 +63,7 @@ OGRWAsPLayer::OGRWAsPLayer( const char * pszName,
     if (poSpatialReference) poSpatialReference->Reference();
 }
 
-OGRWAsPLayer::OGRWAsPLayer( const char * pszName, 
+OGRWAsPLayer::OGRWAsPLayer( const char * pszName,
                             VSILFILE * hFileHandle,
                             OGRSpatialReference * poSpatialRef,
                             const CPLString & sFirstFieldParam,
@@ -105,7 +101,7 @@ OGRWAsPLayer::OGRWAsPLayer( const char * pszName,
 
 OGRWAsPLayer::~OGRWAsPLayer()
 
-{    
+{
     if ( bMerge )
     {
         /* If polygon where used, we have to merge lines before output */
@@ -120,14 +116,14 @@ OGRWAsPLayer::~OGRWAsPLayer()
 
         typedef std::map< std::pair<double,double>, std::vector<int> > PointMap;
         PointMap oMap;
-        for ( size_t i = 0; i < oBoundaries.size(); i++)
+        for ( int i = 0; i < static_cast<int>(oBoundaries.size()); i++)
         {
-            const Boundary & p = oBoundaries[i]; 
+            const Boundary & p = oBoundaries[i];
             OGRPoint startP, endP;
             p.poLine->StartPoint( &startP );
             p.poLine->EndPoint( &endP );
             oMap[ std::make_pair(startP.getX(), startP.getY()) ].push_back( i );
-            oMap[ std::make_pair(endP.getX(), endP.getY()) ].push_back( i ); 
+            oMap[ std::make_pair(endP.getX(), endP.getY()) ].push_back( i );
         }
 
         std::vector<int> endNeighbors( oBoundaries.size(), -1 );
@@ -138,11 +134,11 @@ OGRWAsPLayer::~OGRWAsPLayer()
             int i = it->second[0];
             int j = it->second[1];
 
-            const Boundary & p = oBoundaries[i]; 
+            const Boundary & p = oBoundaries[i];
             OGRPoint startP, endP;
             p.poLine->StartPoint( &startP );
             p.poLine->EndPoint( &endP );
-            const Boundary & q = oBoundaries[j]; 
+            const Boundary & q = oBoundaries[j];
             OGRPoint startQ, endQ;
             q.poLine->StartPoint( &startQ );
             q.poLine->EndPoint( &endQ );
@@ -267,24 +263,24 @@ OGRWAsPLayer::~OGRWAsPLayer()
 /************************************************************************/
 OGRLineString * OGRWAsPLayer::Simplify( const OGRLineString & line ) const
 {
-    if ( !line.getNumPoints() ) 
+    if ( !line.getNumPoints() )
         return  static_cast<OGRLineString *>( line.clone() );
 
-    std::auto_ptr< OGRLineString > poLine( 
+    UNIQUEPTR< OGRLineString > poLine(
         static_cast<OGRLineString *>(
             pdfTolerance.get() && *pdfTolerance > 0
-            ? line.Simplify( *pdfTolerance ) 
+            ? line.Simplify( *pdfTolerance )
             : line.clone() ) );
 
     OGRPoint startPt, endPt;
     poLine->StartPoint( &startPt );
     poLine->EndPoint( &endPt );
-    const bool isRing = startPt.Equals( &endPt );
+    const bool isRing = CPL_TO_BOOL(startPt.Equals( &endPt ));
 
     if ( pdfAdjacentPointTolerance.get() && *pdfAdjacentPointTolerance > 0)
     {
         /* remove consecutive points that are too close */
-        std::auto_ptr< OGRLineString > newLine( new OGRLineString );
+        UNIQUEPTR< OGRLineString > newLine( new OGRLineString );
         const double dist = *pdfAdjacentPointTolerance;
         OGRPoint pt;
         poLine->StartPoint( &pt );
@@ -316,34 +312,34 @@ OGRLineString * OGRWAsPLayer::Simplify( const OGRLineString & line ) const
     {
         const double radius = *pdfPointToCircleRadius;
 
-#undef WASP_EXPERIMENTAL_CODE      
+#undef WASP_EXPERIMENTAL_CODE
 #ifdef WASP_EXPERIMENTAL_CODE
         if ( 3 == poLine->getNumPoints() && isRing )
         {
             OGRPoint p0, p1;
             poLine->getPoint( 0, &p0 );
             poLine->getPoint( 1, &p1 );
-            const double dir[2] = { 
+            const double dir[2] = {
                 p1.getX() - p0.getX(),
                 p1.getY() - p0.getY() };
             const double dirNrm = sqrt( dir[0]*dir[0] + dir[1]*dir[1] );
             if ( dirNrm > radius )
-            { 
+            {
                 /* convert to rectangle by finding the direction */
                 /* and offsetting */
                 const double ortho[2] = {-radius*dir[1]/dirNrm, radius*dir[0]/dirNrm};
                 poLine->setNumPoints(5);
-                poLine->setPoint(0, p0.getX() - ortho[0], p0.getY() - ortho[1]);  
-                poLine->setPoint(1, p1.getX() - ortho[0], p1.getY() - ortho[1]);  
-                poLine->setPoint(2, p1.getX() + ortho[0], p1.getY() + ortho[1]);  
-                poLine->setPoint(3, p0.getX() + ortho[0], p0.getY() + ortho[1]);  
-                poLine->setPoint(4, p0.getX() - ortho[0], p0.getY() - ortho[1]);  
+                poLine->setPoint(0, p0.getX() - ortho[0], p0.getY() - ortho[1]);
+                poLine->setPoint(1, p1.getX() - ortho[0], p1.getY() - ortho[1]);
+                poLine->setPoint(2, p1.getX() + ortho[0], p1.getY() + ortho[1]);
+                poLine->setPoint(3, p0.getX() + ortho[0], p0.getY() + ortho[1]);
+                poLine->setPoint(4, p0.getX() - ortho[0], p0.getY() - ortho[1]);
             }
             else
             {
                 /* reduce to a point to be dealt with just after*/
                 poLine->setNumPoints(1);
-                poLine->setPoint(0, 
+                poLine->setPoint(0,
                         0.5*(p0.getX()+p1.getX()),
                         0.5*(p0.getY()+p1.getY()));
             }
@@ -361,8 +357,8 @@ OGRLineString * OGRWAsPLayer::Simplify( const OGRLineString & line ) const
                 /* the % is necessary to make sure the ring */
                 /* is really closed and not open due to     */
                 /* roundoff error of cos(2pi) and sin(2pi)  */
-                poLine->setPoint(v, 
-                        cx + radius*cos((v%nbPt)*(2*M_PI/nbPt)), 
+                poLine->setPoint(v,
+                        cx + radius*cos((v%nbPt)*(2*M_PI/nbPt)),
                         cy + radius*sin((v%nbPt)*(2*M_PI/nbPt)) );
             }
         }
@@ -379,8 +375,8 @@ OGRLineString * OGRWAsPLayer::Simplify( const OGRLineString & line ) const
 OGRErr OGRWAsPLayer::WriteElevation( OGRLineString * poGeom, const double & dfZ )
 
 {
-    std::auto_ptr< OGRLineString > poLine( Simplify( *poGeom ) );
-    
+    UNIQUEPTR< OGRLineString > poLine( Simplify( *poGeom ) );
+
     const int iNumPoints = poLine->getNumPoints();
     if ( !iNumPoints ) return OGRERR_NONE; /* empty geom */
 
@@ -415,10 +411,10 @@ OGRErr OGRWAsPLayer::WriteElevation( OGRGeometry * poGeom, const double & dfZ )
         }
         return OGRERR_NONE;
     }
-    default: 
+    default:
     {
         CPLError(CE_Failure, CPLE_NotSupported,
-                 "Cannot handle geometry of type %s", 
+                 "Cannot handle geometry of type %s",
                  OGRGeometryTypeToName( poGeom->getGeometryType() ) );
         break;
     }
@@ -445,7 +441,7 @@ OGRErr OGRWAsPLayer::WriteRoughness( OGRPolygon * poGeom, const double & dfZ )
     poGeom->getEnvelope( &oEnvelope );
     for ( size_t i=0; i<oZones.size(); i++)
     {
-        const bool bIntersects = oEnvelope.Intersects( oZones[i].oEnvelope );
+        const bool bIntersects = CPL_TO_BOOL(oEnvelope.Intersects( oZones[i].oEnvelope ));
         if ( bIntersects && ( !bMerge || !isEqual( dfZ, oZones[i].dfZ ) ) ) /* boundary */
         {
             OGRGeometry * poIntersection = oZones[i].poPolygon->Intersection( poGeom );
@@ -499,11 +495,11 @@ OGRErr OGRWAsPLayer::WriteRoughness( OGRPolygon * poGeom, const double & dfZ )
                 {
                             OGREnvelope oErrorRegion = oZones[i].oEnvelope;
                             oErrorRegion.Intersect( oEnvelope );
-                            CPLError(CE_Failure, CPLE_NotSupported, 
+                            CPLError(CE_Failure, CPLE_NotSupported,
                                     "Overlaping polygons in rectangle (%.16g %.16g, %.16g %.16g))",
-                                    oErrorRegion.MinX, 
-                                    oErrorRegion.MinY, 
-                                    oErrorRegion.MaxX, 
+                                    oErrorRegion.MinX,
+                                    oErrorRegion.MinY,
+                                    oErrorRegion.MaxX,
                                     oErrorRegion.MaxY );
                             err = OGRERR_FAILURE;
                 }
@@ -513,17 +509,17 @@ OGRErr OGRWAsPLayer::WriteRoughness( OGRPolygon * poGeom, const double & dfZ )
                 {
                     OGRGeometryCollection * collection = static_cast<OGRGeometryCollection *>(poIntersection);
                     for ( int j=0; j<collection->getNumGeometries(); j++ )
-                    {   
+                    {
                         const OGRwkbGeometryType eType = collection->getGeometryRef(j)->getGeometryType();
                         if ( wkbFlatten(eType) == wkbPolygon )
                         {
                             OGREnvelope oErrorRegion = oZones[i].oEnvelope;
                             oErrorRegion.Intersect( oEnvelope );
-                            CPLError(CE_Failure, CPLE_NotSupported, 
+                            CPLError(CE_Failure, CPLE_NotSupported,
                                     "Overlaping polygons in rectangle (%.16g %.16g, %.16g %.16g))",
-                                    oErrorRegion.MinX, 
-                                    oErrorRegion.MinY, 
-                                    oErrorRegion.MaxX, 
+                                    oErrorRegion.MinX,
+                                    oErrorRegion.MinY,
+                                    oErrorRegion.MaxX,
                                     oErrorRegion.MaxY );
                             err = OGRERR_FAILURE;
                         }
@@ -535,7 +531,7 @@ OGRErr OGRWAsPLayer::WriteRoughness( OGRPolygon * poGeom, const double & dfZ )
                     /* do nothing */
                 break;
                 default:
-                    CPLError(CE_Failure, CPLE_NotSupported, 
+                    CPLError(CE_Failure, CPLE_NotSupported,
                             "Unhandled polygon intersection of type %s",
                             OGRGeometryTypeToName( poIntersection->getGeometryType() ) );
                     err = OGRERR_FAILURE;
@@ -546,14 +542,14 @@ OGRErr OGRWAsPLayer::WriteRoughness( OGRPolygon * poGeom, const double & dfZ )
     }
 
     Zone oZ =  { oEnvelope, static_cast<OGRPolygon *>(poGeom->clone()), dfZ };
-    oZones.push_back( oZ ); 
+    oZones.push_back( oZ );
     return err;
 }
 
 OGRErr OGRWAsPLayer::WriteRoughness( OGRLineString * poGeom, const double & dfZleft,  const double & dfZright )
 
 {
-    std::auto_ptr< OGRLineString > poLine( Simplify( *poGeom ) );
+    UNIQUEPTR< OGRLineString > poLine( Simplify( *poGeom ) );
 
     const int iNumPoints = poLine->getNumPoints();
     if ( !iNumPoints ) return OGRERR_NONE; /* empty geom */
@@ -597,7 +593,7 @@ OGRErr OGRWAsPLayer::WriteRoughness( OGRGeometry * poGeom, const double & dfZlef
     default:
     {
         CPLError(CE_Failure, CPLE_NotSupported,
-                 "Cannot handle geometry of type %s", 
+                 "Cannot handle geometry of type %s",
                  OGRGeometryTypeToName( poGeom->getGeometryType() ) );
         break;
     }
@@ -653,7 +649,7 @@ OGRErr OGRWAsPLayer::ICreateFeature( OGRFeature * poFeature )
         {
             CPLError(CE_Failure, CPLE_NotSupported, "Field %d %s is NULL", iFirstFieldIdx, sFirstField.c_str() );
             return OGRERR_FAILURE;
-        } 
+        }
         z1 = poFeature->GetFieldAsDouble(iFirstFieldIdx);
     }
     else
@@ -676,7 +672,7 @@ OGRErr OGRWAsPLayer::ICreateFeature( OGRFeature * poFeature )
         {
             CPLError(CE_Failure, CPLE_NotSupported, "Field %d %s is NULL", iSecondFieldIdx, sSecondField.c_str() );
             return OGRERR_FAILURE;
-        } 
+        }
         z2 = poFeature->GetFieldAsDouble(iSecondFieldIdx);
     }
     else if ( bRoughness && !bPolygon )
@@ -741,7 +737,7 @@ OGRFeature *OGRWAsPLayer::GetNextFeature()
 
     GetLayerDefn();
 
-    while(TRUE)
+    while( true )
     {
         poFeature = GetNextRawFeature();
         if (poFeature == NULL)
@@ -788,15 +784,15 @@ OGRFeature *OGRWAsPLayer::GetNextRawFeature()
         return NULL;
     }
 
-    std::auto_ptr< OGRFeature > poFeature( new OGRFeature( poLayerDefn ) );
+    UNIQUEPTR< OGRFeature > poFeature( new OGRFeature( poLayerDefn ) );
     poFeature->SetFID( ++iFeatureCount );
     for ( int i=0; i<iNumValues-1; i++ ) poFeature->SetField( i, dfValues[i] );
 
-    const int iNumValuesToRead = 2*dfValues[iNumValues-1];
+    const int iNumValuesToRead = static_cast<int>(2*dfValues[iNumValues-1]);
     int iReadValues = 0;
     std::vector<double> values(iNumValuesToRead);
-    for ( pszLine = CPLReadLineL( hFile ); 
-            pszLine; 
+    for ( pszLine = CPLReadLineL( hFile );
+            pszLine;
             pszLine = iNumValuesToRead > iReadValues ? CPLReadLineL( hFile ) : NULL )
     {
         std::istringstream iss(pszLine);
@@ -807,7 +803,7 @@ OGRFeature *OGRWAsPLayer::GetNextRawFeature()
         CPLError(CE_Failure, CPLE_FileIO, "No enough values for linestring" );
         return NULL;
     }
-    std::auto_ptr< OGRLineString > poLine( new OGRLineString );
+    UNIQUEPTR< OGRLineString > poLine( new OGRLineString );
     poLine->setCoordinateDimension(3);
     poLine->assignSpatialReference( poSpatialReference );
     for ( int i=0; i<iNumValuesToRead; i+=2 )
@@ -839,7 +835,7 @@ int OGRWAsPLayer::TestCapability( const char * pszCap )
 void OGRWAsPLayer::ResetReading()
 {
     iFeatureCount = 0;
-    VSIFSeekL( hFile, iOffsetFeatureBegin, SEEK_SET );	
+    VSIFSeekL( hFile, iOffsetFeatureBegin, SEEK_SET );
 }
 
 
@@ -888,8 +884,8 @@ double OGRWAsPLayer::AvgZ( OGRGeometry * poGeom )
     case wkbMultiPolygon:
     case wkbMultiPolygon25D:
         return AvgZ( static_cast< OGRGeometryCollection * >(poGeom) );
-    default: 
-        CPLError( CE_Warning, CPLE_NotSupported, "Unsuported geometry type in OGRWAsPLayer::AvgZ()");
+    default:
+        CPLError( CE_Warning, CPLE_NotSupported, "Unsupported geometry type in OGRWAsPLayer::AvgZ()");
         break;
     }
     return 0; /* avoid warning */
@@ -910,7 +906,7 @@ double OGRWAsPLayer::AvgZ( OGRGeometry * poGeom )
 //    int end = length(PointList).
 //    for (int i = 1; i<end; i++)
 //    {
-//        const double d = shortestDistanceToSegment(PointList[i], Line(PointList[0], PointList[end])) 
+//        const double d = shortestDistanceToSegment(PointList[i], Line(PointList[0], PointList[end]))
 //        if ( d > dmax )
 //        {
 //            index = i
@@ -918,16 +914,16 @@ double OGRWAsPLayer::AvgZ( OGRGeometry * poGeom )
 //        }
 //    }
 //    // If max distance is greater than epsilon, recursively simplify
-//    if ( dmax > epsilon ) 
+//    if ( dmax > epsilon )
 //    {
 //        // Recursive call
 //        recResults1[] = DouglasPeucker(PointList[1...index], epsilon)
 //        recResults2[] = DouglasPeucker(PointList[index...end], epsilon)
-// 
+//
 //        // Build the result list
 //        ResultList[] = {recResults1[1...end-1] recResults2[1...end]}
-//    } 
-//    else 
+//    }
+//    else
 //    {
 //        ResultList[] = {PointList[1], PointList[end]}
 //    }
diff --git a/ogr/ogrsf_frmts/wfs/drv_wfs.html b/ogr/ogrsf_frmts/wfs/drv_wfs.html
index d9d206f..02f7fe3 100644
--- a/ogr/ogrsf_frmts/wfs/drv_wfs.html
+++ b/ogr/ogrsf_frmts/wfs/drv_wfs.html
@@ -29,7 +29,7 @@ It is also possible to specify the name of an XML file whose content matches the
 (the <OGRWFSDataSource&gt element must be the first bytes of the file):
 <pre>
 <OGRWFSDataSource>
-    <URL>http://path/to/WFS/service[?OPTIONAL_PARAMETER1=VALUE[&amp;OPTIONNAL_PARAMETER2=VALUE]]</URL>
+    <URL>http://path/to/WFS/service[?OPTIONAL_PARAMETER1=VALUE[&amp;OPTIONAL_PARAMETER2=VALUE]]</URL>
 </OGRWFSDataSource>
 </pre><p>
 
@@ -107,7 +107,7 @@ Note that those spatial functions are only supported as server-side filters.<p>
 <p>
 Starting with GDAL 2.0, and for WFS 2.0 servers that support joins, SELECT
 statements that involve joins will be run on server side. Spatial joins can
-also be done by using the above mentionned spatial functions, if the server
+also be done by using the above mentioned spatial functions, if the server
 supports spatial joins.</p>
 
 <p>There might be restrictions set by server on the complexity of the joins.
@@ -129,11 +129,14 @@ SELECT * FROM my_table AS t1 JOIN another_table AS t2 ON ST_Intersects(t1.geom,
 
 <h2>Write support / WFS-T</h2>
 
-The WFS-T protocol only eanbles the user to operate at feature level. No datasource, layer or field creations are possible.<p>
+The WFS-T protocol only enables the user to operate at feature
+level. No datasource, layer or field creations are possible.<p>
 
-Write support is only enabled when the datasource is opened in update mode.<p>
+Write support is only enabled when the datasource is opened in update
+mode.<p>
 
-The mapping between the operations of the WFS Transaction service and the OGR concepts is the following :
+The mapping between the operations of the WFS Transaction service and
+the OGR concepts is the following:
 <ul>
 <li>OGRFeature::CreateFeature() <==> WFS insert operation</li>
 <li>OGRFeature::SetFeature() <==> WFS update operation</li>
@@ -142,9 +145,11 @@ The mapping between the operations of the WFS Transaction service and the OGR co
 
 Lock operations (LockFeature service) are not available at that time.<p>
 
-There are a few caveouts to keep in mind. OGR feature ID (FID) is an integer based value, whereas WFS/GML
-gml:id attribute is a string. Thus it is not always possible to match both values. The WFS driver exposes
-then the gml:id attribute of a feature as a 'gml_id' field.<p>
+There are a few caveats to keep in mind. OGR feature ID (FID) is an
+integer based value, whereas WFS/GML gml:id attribute is a
+string. Thus it is not always possible to match both values. The WFS
+driver exposes then the gml:id attribute of a feature as a 'gml_id'
+field.<p>
 
 When inserting a new feature with CreateFeature(), and if the command is successful, OGR will fetch the
 returned gml:id and set the 'gml_id' field of the feature accordingly. It will also try to set the OGR FID
@@ -166,7 +171,7 @@ The drawback for CreateFeature() is that the user cannot know which gml:id have
 features. A special SQL statement has been introduced into the WFS driver to workaround this : by issuing
 the "SELECT _LAST_INSERTED_FIDS_ FROM layer_name" (where layer_name is to be replaced with the actual layer_name)
 command through the OGRDataSource::ExecuteSQL(), a layer will be returned with as many rows
-with a single attribue gml_id as the count of inserted features during the last commited transaction.<p>
+with a single attribute gml_id as the count of inserted features during the last committed transaction.<p>
 
 Note : currently, only CreateFeature() makes use of OGR transaction mechanism. SetFeature() and DeleteFeature()
 will still be issued immediately.
diff --git a/ogr/ogrsf_frmts/wfs/ogr_wfs.h b/ogr/ogrsf_frmts/wfs/ogr_wfs.h
index 8030072..c88be7f 100644
--- a/ogr/ogrsf_frmts/wfs/ogr_wfs.h
+++ b/ogr/ogrsf_frmts/wfs/ogr_wfs.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_wfs.h 29273 2015-06-02 08:08:38Z rouault $
+ * $Id: ogr_wfs.h 32177 2015-12-14 07:25:30Z goatbar $
  *
  * Project:  WFS Translator
  * Purpose:  Definition of classes for OGR WFS driver.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_WFS_H_INCLUDED
-#define _OGR_WFS_H_INCLUDED
+#ifndef OGR_WFS_H_INCLUDED
+#define OGR_WFS_H_INCLUDED
 
 #include <vector>
 #include <set>
@@ -64,8 +64,8 @@ class OGRWFSSortDesc
     public:
         CPLString osColumn;
         int       bAsc;
-        
-        OGRWFSSortDesc(const CPLString& osColumn, int bAsc) : osColumn(osColumn), bAsc(bAsc) {}
+
+        OGRWFSSortDesc(const CPLString& osColumnIn, int bAscIn) : osColumn(osColumnIn), bAsc(bAscIn) {}
         OGRWFSSortDesc(const OGRWFSSortDesc& other) : osColumn(other.osColumn), bAsc(other.bAsc) {}
 };
 
@@ -124,7 +124,7 @@ class OGRWFSLayer : public OGRLayer
     int                 nExpectedInserts;
     CPLString           osGlobalInsert;
     std::vector<CPLString> aosFIDList;
-    
+
     int                 bInTransaction;
 
     CPLString           GetPostHeader();
@@ -167,6 +167,8 @@ class OGRWFSLayer : public OGRLayer
     virtual int                 TestCapability( const char * );
 
     virtual void        SetSpatialFilter( OGRGeometry * );
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+                { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
 
     virtual OGRErr      SetAttributeFilter( const char * );
 
@@ -174,6 +176,8 @@ class OGRWFSLayer : public OGRLayer
 
     void                SetExtents(double dfMinX, double dfMinY, double dfMaxX, double dfMaxY);
     virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
     virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
     virtual OGRErr      ISetFeature( OGRFeature *poFeature );
@@ -200,7 +204,7 @@ class OGRWFSLayer : public OGRLayer
 
     void                SetOrderBy(const std::vector<OGRWFSSortDesc>& aoSortColumnsIn);
     int                 HasGotApproximateLayerDefn() { GetLayerDefn(); return bGotApproximateLayerDefn; }
-    
+
     const char*         GetNamespacePrefix() { return pszNS; }
     const char*         GetNamespaceName() { return pszNSVal; }
 };
@@ -230,9 +234,9 @@ class OGRWFSJoinLayer : public OGRLayer
     int                 nPagingStartIndex;
     int                 nFeatureRead;
     int                 nFeatureCountRequested;
-    
+
     std::vector<CPLString> aoSrcFieldNames, aoSrcGeomFieldNames;
-    
+
     CPLString           osFeatureTypes;
 
                         OGRWFSJoinLayer(OGRWFSDataSource* poDS,
@@ -254,10 +258,12 @@ class OGRWFSJoinLayer : public OGRLayer
     virtual OGRFeatureDefn *    GetLayerDefn();
 
     virtual int                 TestCapability( const char * );
-    
+
     virtual GIntBig             GetFeatureCount( int bForce = TRUE );
 
     virtual void        SetSpatialFilter( OGRGeometry * );
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+                { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
 
     virtual OGRErr      SetAttributeFilter( const char * );
 };
@@ -324,9 +330,9 @@ class OGRWFSDataSource : public OGRDataSource
     OGRLayer           *poLayerGetCapabilitiesLayer;
 
     int                 bKeepLayerNamePrefix;
-    
+
     int                 bEmptyAsNull;
-    
+
     int                 bInvertAxisOrderIfLatLong;
     CPLString           osConsiderEPSGAsURN;
     int                 bExposeGMLId;
@@ -390,15 +396,15 @@ class OGRWFSDataSource : public OGRDataSource
 
     int                         GetKeepLayerNamePrefix() { return bKeepLayerNamePrefix; }
     const CPLString&            GetBaseURL() { return osBaseURL; }
-    
+
     int                         IsEmptyAsNull() const { return bEmptyAsNull; }
     int                         InvertAxisOrderIfLatLong() const { return bInvertAxisOrderIfLatLong; }
     const CPLString&            GetConsiderEPSGAsURN() const { return osConsiderEPSGAsURN; }
-    
+
     int                         ExposeGMLId() const { return bExposeGMLId; }
 
     virtual char**              GetMetadataDomainList();
     virtual char**              GetMetadata( const char * pszDomain = "" );
 };
 
-#endif /* ndef _OGR_WFS_H_INCLUDED */
+#endif /* ndef OGR_WFS_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/wfs/ogrwfsdatasource.cpp b/ogr/ogrsf_frmts/wfs/ogrwfsdatasource.cpp
index 4fb5c97..b265bd0 100644
--- a/ogr/ogrsf_frmts/wfs/ogrwfsdatasource.cpp
+++ b/ogr/ogrsf_frmts/wfs/ogrwfsdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrwfsdatasource.cpp 29273 2015-06-02 08:08:38Z rouault $
+ * $Id: ogrwfsdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  WFS Translator
  * Purpose:  Implements OGRWFSDataSource class
@@ -37,7 +37,7 @@
 #include "swq.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrwfsdatasource.cpp 29273 2015-06-02 08:08:38Z rouault $");
+CPL_CVSID("$Id: ogrwfsdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 #define DEFAULT_BASE_START_INDEX     0
 #define DEFAULT_PAGE_SIZE            100
@@ -64,7 +64,7 @@ static const MetadataItem asMetadata[] =
 CPLXMLNode* WFSFindNode(CPLXMLNode* psXML, const char* pszRootName)
 {
     CPLXMLNode* psIter = psXML;
-    while(psIter)
+    do
     {
         if (psIter->eType == CXT_Element)
         {
@@ -78,7 +78,7 @@ CPLXMLNode* WFSFindNode(CPLXMLNode* psXML, const char* pszRootName)
             }
         }
         psIter = psIter->psNext;
-    }
+    } while(psIter);
 
     psIter = psXML->psChild;
     while(psIter)
@@ -109,10 +109,10 @@ class OGRWFSWrappedResultLayer : public OGRLayer
     OGRLayer      *poLayer;
 
     public:
-        OGRWFSWrappedResultLayer(GDALDataset* poDS, OGRLayer* poLayer)
+        OGRWFSWrappedResultLayer(GDALDataset* poDSIn, OGRLayer* poLayerIn)
         {
-            this->poDS = poDS;
-            this->poLayer = poLayer;
+            this->poDS = poDSIn;
+            this->poLayer = poLayerIn;
         }
         ~OGRWFSWrappedResultLayer()
         {
@@ -159,7 +159,7 @@ OGRWFSDataSource::OGRWFSDataSource()
     bUseHttp10 = FALSE;
     papszHttpOptions = NULL;
 
-    bPagingAllowed = CSLTestBoolean(CPLGetConfigOption("OGR_WFS_PAGING_ALLOWED", "OFF"));
+    bPagingAllowed = CPLTestBool(CPLGetConfigOption("OGR_WFS_PAGING_ALLOWED", "OFF"));
     nPageSize = DEFAULT_PAGE_SIZE;
     nBaseStartIndex = DEFAULT_BASE_START_INDEX;
     if (bPagingAllowed)
@@ -181,7 +181,7 @@ OGRWFSDataSource::OGRWFSDataSource()
 
     bStandardJoinsWFS2 = FALSE;
 
-    bLoadMultipleLayerDefn = CSLTestBoolean(CPLGetConfigOption("OGR_WFS_LOAD_MULTIPLE_LAYER_DEFN", "TRUE"));
+    bLoadMultipleLayerDefn = CPLTestBool(CPLGetConfigOption("OGR_WFS_LOAD_MULTIPLE_LAYER_DEFN", "TRUE"));
 
     poLayerMetadataDS = NULL;
     poLayerMetadataLayer = NULL;
@@ -193,7 +193,7 @@ OGRWFSDataSource::OGRWFSDataSource()
     apszGetCapabilities[0] = NULL;
     apszGetCapabilities[1] = NULL;
     bEmptyAsNull = TRUE;
-    
+
     bInvertAxisOrderIfLatLong = TRUE;
     bExposeGMLId = TRUE;
 }
@@ -256,12 +256,12 @@ OGRLayer *OGRWFSDataSource::GetLayer( int iLayer )
 /*                          GetLayerByName()                            */
 /************************************************************************/
 
-OGRLayer* OGRWFSDataSource::GetLayerByName(const char* pszName)
+OGRLayer* OGRWFSDataSource::GetLayerByName(const char* pszNameIn)
 {
-    if ( ! pszName )
+    if ( ! pszNameIn )
         return NULL;
 
-    if (EQUAL(pszName, "WFSLayerMetadata"))
+    if (EQUAL(pszNameIn, "WFSLayerMetadata"))
     {
         if (osLayerMetadataTmpFileName.size() != 0)
             return poLayerMetadataLayer;
@@ -278,7 +278,7 @@ OGRLayer* OGRWFSDataSource::GetLayerByName(const char* pszName)
             poLayerMetadataLayer = poLayerMetadataDS->GetLayer(0);
         return poLayerMetadataLayer;
     }
-    else if (EQUAL(pszName, "WFSGetCapabilities"))
+    else if (EQUAL(pszNameIn, "WFSGetCapabilities"))
     {
         if (poLayerGetCapabilitiesLayer != NULL)
             return poLayerGetCapabilitiesLayer;
@@ -296,13 +296,13 @@ OGRLayer* OGRWFSDataSource::GetLayerByName(const char* pszName)
         poLayerGetCapabilitiesLayer->CreateField(&oFDefn);
         OGRFeature* poFeature = new OGRFeature(poLayerGetCapabilitiesLayer->GetLayerDefn());
         poFeature->SetField(0, osGetCapabilities);
-        poLayerGetCapabilitiesLayer->CreateFeature(poFeature);
+        CPL_IGNORE_RET_VAL(poLayerGetCapabilitiesLayer->CreateFeature(poFeature));
         delete poFeature;
 
         return poLayerGetCapabilitiesLayer;
     }
 
-    int nIndex = GetLayerIndex(pszName);
+    int nIndex = GetLayerIndex(pszNameIn);
     if (nIndex < 0)
         return NULL;
     else
@@ -340,7 +340,7 @@ char** OGRWFSDataSource::GetMetadata( const char * pszDomain )
 /*                          GetLayerIndex()                             */
 /************************************************************************/
 
-int OGRWFSDataSource::GetLayerIndex(const char* pszName)
+int OGRWFSDataSource::GetLayerIndex(const char* pszNameIn)
 {
     int i;
     int  bHasFoundLayerWithColon = FALSE;
@@ -350,7 +350,7 @@ int OGRWFSDataSource::GetLayerIndex(const char* pszName)
     {
         OGRWFSLayer *poLayer = papoLayers[i];
 
-        if( strcmp( pszName, poLayer->GetName() ) == 0 )
+        if( strcmp( pszNameIn, poLayer->GetName() ) == 0 )
             return i;
 
         bHasFoundLayerWithColon |= (strchr( poLayer->GetName(), ':') != NULL);
@@ -361,19 +361,19 @@ int OGRWFSDataSource::GetLayerIndex(const char* pszName)
     {
         OGRWFSLayer *poLayer = papoLayers[i];
 
-        if( EQUAL( pszName, poLayer->GetName() ) )
+        if( EQUAL( pszNameIn, poLayer->GetName() ) )
             return i;
     }
 
     /* now try looking after the colon character */
-    if (!bKeepLayerNamePrefix && bHasFoundLayerWithColon && strchr(pszName, ':') == NULL)
+    if (!bKeepLayerNamePrefix && bHasFoundLayerWithColon && strchr(pszNameIn, ':') == NULL)
     {
         for( i = 0; i < nLayers; i++ )
         {
             OGRWFSLayer *poLayer = papoLayers[i];
 
             const char* pszAfterColon = strchr( poLayer->GetName(), ':');
-            if( pszAfterColon && EQUAL( pszName, pszAfterColon + 1 ) )
+            if( pszAfterColon && EQUAL( pszNameIn, pszAfterColon + 1 ) )
                 return i;
         }
     }
@@ -540,7 +540,7 @@ int OGRWFSDataSource::DetectTransactionSupport(CPLXMLNode* psRoot)
         bTransactionSupport = TRUE;
         return TRUE;
     }
-    
+
     CPLXMLNode* psOperationsMetadata =
         CPLGetXMLNode(psRoot, "OperationsMetadata");
     if (!psOperationsMetadata)
@@ -624,7 +624,7 @@ int OGRWFSDataSource::DetectTransactionSupport(CPLXMLNode* psRoot)
 int OGRWFSDataSource::DetectSupportPagingWFS2(CPLXMLNode* psRoot)
 {
     const char* pszPagingAllowed = CPLGetConfigOption("OGR_WFS_PAGING_ALLOWED", NULL);
-    if( pszPagingAllowed != NULL && !CSLTestBoolean(pszPagingAllowed) )
+    if( pszPagingAllowed != NULL && !CPLTestBool(pszPagingAllowed) )
         return FALSE;
 
     CPLXMLNode* psOperationsMetadata =
@@ -754,7 +754,7 @@ static int FindComparisonOperator(CPLXMLNode* psNode, const char* pszVal)
 
             /* For WFS 2.0.0 */
             const char* pszName = CPLGetXMLValue(psChild, "name", NULL);
-            if (pszName != NULL && strncmp(pszName, "PropertyIs", 10) == 0 &&
+            if (pszName != NULL && STARTS_WITH(pszName, "PropertyIs") &&
                 strcmp(pszName + 10, pszVal) == 0)
                 return TRUE;
         }
@@ -783,14 +783,14 @@ CPLXMLNode* OGRWFSDataSource::LoadFromFile( const char * pszFilename )
         return NULL;
 
     int nRead;
-    if( (nRead = VSIFReadL( achHeader, 1, sizeof(achHeader) - 1, fp )) == 0 )
+    if( (nRead = static_cast<int>(VSIFReadL( achHeader, 1, sizeof(achHeader) - 1, fp ))) == 0 )
     {
         VSIFCloseL( fp );
         return NULL;
     }
     achHeader[nRead] = 0;
 
-    if( !EQUALN(achHeader,"<OGRWFSDataSource>",18) &&
+    if( !STARTS_WITH_CI(achHeader, "<OGRWFSDataSource>") &&
         strstr(achHeader,"<WFS_Capabilities") == NULL &&
         strstr(achHeader,"<wfs:WFS_Capabilities") == NULL)
     {
@@ -807,7 +807,7 @@ CPLXMLNode* OGRWFSDataSource::LoadFromFile( const char * pszFilename )
     nLen = (int) VSIFTellL( fp );
     VSIFSeekL( fp, 0, SEEK_SET );
 
-    char* pszXML = (char *) VSIMalloc(nLen+1);
+    char* pszXML = (char *) VSI_MALLOC_VERBOSE(nLen+1);
     if (pszXML == NULL)
     {
         VSIFCloseL( fp );
@@ -891,7 +891,7 @@ CPLHTTPResult* OGRWFSDataSource::SendGetCapabilities(const char* pszBaseURL,
 /************************************************************************/
 
 int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
-                            char** papszOpenOptions )
+                            char** papszOpenOptionsIn )
 
 {
     bUpdate = bUpdateIn;
@@ -903,29 +903,29 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
     CPLString osTypeName;
     const char* pszBaseURL = NULL;
 
-    bEmptyAsNull = CSLFetchBoolean(papszOpenOptions, "EMPTY_AS_NULL", TRUE);
+    bEmptyAsNull = CSLFetchBoolean(papszOpenOptionsIn, "EMPTY_AS_NULL", TRUE);
 
     if (psXML == NULL)
     {
-        if (!EQUALN(pszFilename, "WFS:", 4) &&
+        if (!STARTS_WITH_CI(pszFilename, "WFS:") &&
             FindSubStringInsensitive(pszFilename, "SERVICE=WFS") == NULL)
         {
             return FALSE;
         }
 
-        pszBaseURL = CSLFetchNameValue(papszOpenOptions, "URL");
+        pszBaseURL = CSLFetchNameValue(papszOpenOptionsIn, "URL");
         if( pszBaseURL == NULL )
         {
             pszBaseURL = pszFilename;
-            if (EQUALN(pszFilename, "WFS:", 4))
+            if (STARTS_WITH_CI(pszFilename, "WFS:"))
                 pszBaseURL += 4;
         }
 
         osBaseURL = pszBaseURL;
 
-        if (strncmp(pszBaseURL, "http://", 7) != 0 &&
-            strncmp(pszBaseURL, "https://", 8) != 0 &&
-            strncmp(pszBaseURL, "/vsimem/", strlen("/vsimem/")) != 0)
+        if (!STARTS_WITH(pszBaseURL, "http://") &&
+            !STARTS_WITH(pszBaseURL, "https://") &&
+            !STARTS_WITH(pszBaseURL, "/vsimem/"))
             return FALSE;
 
         CPLString strOriginalTypeName = "";
@@ -1022,7 +1022,7 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
 
         pszParm = CPLGetXMLValue( psRoot, "PagingAllowed", NULL );
         if( pszParm )
-            bPagingAllowed = CSLTestBoolean(pszParm);
+            bPagingAllowed = CPLTestBool(pszParm);
 
         pszParm = CPLGetXMLValue( psRoot, "PageSize", NULL );
         if( pszParm )
@@ -1078,12 +1078,12 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
             CPLAddXMLChild(psXML, CPLCloneXMLTree(psWFSCapabilities));
 
             int bOK = CPLSerializeXMLTreeToFile(psXML, pszFilename);
-            
+
             CPLDestroyXMLNode( psXML );
             CPLDestroyXMLNode( psXML2 );
 
             if (bOK)
-                return Open(pszFilename, bUpdate, papszOpenOptions);
+                return Open(pszFilename, bUpdate, papszOpenOptionsIn);
             else
                 return FALSE;
         }
@@ -1102,15 +1102,15 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
     }
 
     bInvertAxisOrderIfLatLong =
-        CSLTestBoolean(CSLFetchNameValueDef(papszOpenOptions,
+        CPLTestBool(CSLFetchNameValueDef(papszOpenOptionsIn,
             "INVERT_AXIS_ORDER_IF_LAT_LONG",
             CPLGetConfigOption("GML_INVERT_AXIS_ORDER_IF_LAT_LONG", "YES")));
     osConsiderEPSGAsURN =
-        CSLFetchNameValueDef(papszOpenOptions,
+        CSLFetchNameValueDef(papszOpenOptionsIn,
             "CONSIDER_EPSG_AS_URN",
             CPLGetConfigOption("GML_CONSIDER_EPSG_AS_URN", "AUTO"));
     bExposeGMLId =
-        CSLTestBoolean(CSLFetchNameValueDef(papszOpenOptions,
+        CPLTestBool(CSLFetchNameValueDef(papszOpenOptionsIn,
             "EXPOSE_GML_ID",
             CPLGetConfigOption("GML_EXPOSE_GML_ID", "YES")));
 
@@ -1165,7 +1165,7 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
     else
     {
         /* Some servers happen to support RESULTTYPE=hits in 1.0.0, but there */
-        /* is no way to advertisze this */
+        /* is no way to advertises this */
         if (atoi(osVersion) >= 2)
             bGetFeatureSupportHits = TRUE;  /* WFS >= 2.0.0 supports hits */
         else
@@ -1181,7 +1181,7 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
         {
             osMaxFeatures = CPLURLGetValue(osBaseURL, "MAXFEATURES");
             if( osMaxFeatures.size() != 0 &&
-                CSLTestBoolean(CPLGetConfigOption("OGR_WFS_FIX_MAXFEATURES", "YES")) )
+                CPLTestBool(CPLGetConfigOption("OGR_WFS_FIX_MAXFEATURES", "YES")) )
             {
                 CPLDebug("WFS", "MAXFEATURES wrongly used for WFS 2.0. Using COUNT instead");
                 osBaseURL = CPLURLAddKVP(osBaseURL, "MAXFEATURES", NULL);
@@ -1271,19 +1271,19 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
         if (psChildIter->eType == CXT_Element &&
             strcmp(psChildIter->pszValue, "FeatureType") == 0)
         {
-            const char* pszName = CPLGetXMLValue(psChildIter, "Name", NULL);
-            if (pszName != NULL)
+            const char* l_pszName = CPLGetXMLValue(psChildIter, "Name", NULL);
+            if (l_pszName != NULL)
             {
-                const char* pszShortName = strchr(pszName, ':');
+                const char* pszShortName = strchr(l_pszName, ':');
                 if (pszShortName)
-                    pszName = pszShortName + 1;
-                if (aosSetLayerNames.find(pszName) != aosSetLayerNames.end())
+                    l_pszName = pszShortName + 1;
+                if (aosSetLayerNames.find(l_pszName) != aosSetLayerNames.end())
                 {
                     bKeepLayerNamePrefix = TRUE;
                     CPLDebug("WFS", "At least 2 layers have names that are only distinguishable by keeping the prefix");
                     break;
                 }
-                aosSetLayerNames.insert(pszName);
+                aosSetLayerNames.insert(l_pszName);
             }
         }
     }
@@ -1312,12 +1312,12 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
                 psFeatureTypeIter = psFeatureTypeIter->psNext;
             }
 
-            const char* pszName = CPLGetXMLValue(psChildIter, "Name", NULL);
+            const char* l_pszName = CPLGetXMLValue(psChildIter, "Name", NULL);
             const char* pszTitle = CPLGetXMLValue(psChildIter, "Title", NULL);
             const char* pszAbstract = CPLGetXMLValue(psChildIter, "Abstract", NULL);
-            if (pszName != NULL &&
+            if (l_pszName != NULL &&
                 (papszTypenames == NULL ||
-                 CSLFindString(papszTypenames, pszName) != -1))
+                 CSLFindString(papszTypenames, l_pszName) != -1))
             {
                 const char* pszDefaultSRS =
                         CPLGetXMLValue(psChildIter, "DefaultSRS", NULL);
@@ -1447,7 +1447,7 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
 
                 char* pszCSVEscaped;
 
-                pszCSVEscaped = CPLEscapeString(pszName, -1, CPLES_CSV);
+                pszCSVEscaped = CPLEscapeString(l_pszName, -1, CPLES_CSV);
                 osLayerMetadataCSV += pszCSVEscaped;
                 CPLFree(pszCSVEscaped);
 
@@ -1469,7 +1469,7 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
 
                 OGRWFSLayer* poLayer = new OGRWFSLayer(
                             this, poSRS, bAxisOrderAlreadyInverted,
-                            osBaseURL, pszName, pszNS, pszNSVal);
+                            osBaseURL, l_pszName, pszNS, pszNSVal);
                 if (osOutputFormat.size())
                     poLayer->SetRequiredOutputFormat(osOutputFormat);
 
@@ -1505,8 +1505,8 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
                     {
                         /* See http://trac.osgeo.org/gdal/ticket/4041 */
                         int bTrustBounds =
-                            CSLFetchBoolean(papszOpenOptions, "TRUST_CAPABILITIES_BOUNDS",
-                                CSLTestBoolean(CPLGetConfigOption("OGR_WFS_TRUST_CAPABILITIES_BOUNDS", "FALSE")));
+                            CSLFetchBoolean(papszOpenOptionsIn, "TRUST_CAPABILITIES_BOUNDS",
+                                CPLTestBool(CPLGetConfigOption("OGR_WFS_TRUST_CAPABILITIES_BOUNDS", "FALSE")));
 
                         if (((bTrustBounds || (dfMinX == -180 && dfMinY == -90 && dfMaxX == 180 && dfMaxY == 90)) &&
                             (strcmp(pszProj4, "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs ") == 0 ||
@@ -1581,7 +1581,7 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
                     {
                         if (psIter->eType == CXT_Element &&
                             EQUAL(psIter->pszValue, "OGRWFSLayer") &&
-                            strcmp(CPLGetXMLValue(psIter, "name", ""), pszName) == 0)
+                            strcmp(CPLGetXMLValue(psIter, "name", ""), l_pszName) == 0)
                         {
                             CPLXMLNode* psSchema = WFSFindNode( psIter->psChild, "schema" );
                             if (psSchema)
@@ -1653,17 +1653,17 @@ void OGRWFSDataSource::LoadMultipleLayerDefn(const char* pszLayerName,
         if (!papoLayers[i]->HasLayerDefn())
         {
             /* We must be careful to requests only layers with the same prefix/namespace */
-            const char* pszName = papoLayers[i]->GetName();
-            if (((pszPrefix[0] == 0 && strchr(pszName, ':') == NULL) ||
-                (pszPrefix[0] != 0 && strncmp(pszName, pszPrefix, strlen(pszPrefix)) == 0 &&
-                 pszName[strlen(pszPrefix)] == ':')) &&
+            const char* l_pszName = papoLayers[i]->GetName();
+            if (((pszPrefix[0] == 0 && strchr(l_pszName, ':') == NULL) ||
+                (pszPrefix[0] != 0 && strncmp(l_pszName, pszPrefix, strlen(pszPrefix)) == 0 &&
+                 l_pszName[strlen(pszPrefix)] == ':')) &&
                 ((pszRequiredOutputFormat == NULL && papoLayers[i]->GetRequiredOutputFormat() == NULL) ||
                  (pszRequiredOutputFormat != NULL && papoLayers[i]->GetRequiredOutputFormat() != NULL &&
                   strcmp(pszRequiredOutputFormat, papoLayers[i]->GetRequiredOutputFormat()) == 0)))
             {
-                if (aoSetAlreadyTriedLayers.find(pszName) != aoSetAlreadyTriedLayers.end())
+                if (aoSetAlreadyTriedLayers.find(l_pszName) != aoSetAlreadyTriedLayers.end())
                     continue;
-                aoSetAlreadyTriedLayers.insert(pszName);
+                aoSetAlreadyTriedLayers.insert(l_pszName);
 
 #if USE_GET_FOR_DESCRIBE_FEATURE_TYPE == 1
                 if (nLayersToFetch > 0)
@@ -1671,7 +1671,7 @@ void OGRWFSDataSource::LoadMultipleLayerDefn(const char* pszLayerName,
                 osLayerToFetch += papoLayers[i]->GetName();
 #else
                 osTypeNameToPost += "  <TypeName>";
-                osTypeNameToPost += pszName;
+                osTypeNameToPost += l_pszName;
                 osTypeNameToPost += "</TypeName>\n";
 #endif
                 nLayersToFetch ++;
@@ -1800,18 +1800,18 @@ void OGRWFSDataSource::LoadMultipleLayerDefn(const char* pszLayerName,
     CPLSerializeXMLTreeToFile(psSchema, osTmpFileName);
 
     std::vector<GMLFeatureClass*> aosClasses;
-    int bFullyUnderstood = FALSE;
+    bool bFullyUnderstood = false;
     GMLParseXSD( osTmpFileName, aosClasses, bFullyUnderstood );
 
     int nLayersFound = 0;
     if ((int)aosClasses.size() > 0)
     {
-        std::vector<GMLFeatureClass*>::const_iterator iter = aosClasses.begin();
-        std::vector<GMLFeatureClass*>::const_iterator eiter = aosClasses.end();
-        while (iter != eiter)
+        std::vector<GMLFeatureClass*>::const_iterator oIter = aosClasses.begin();
+        std::vector<GMLFeatureClass*>::const_iterator oEndIter = aosClasses.end();
+        while (oIter != oEndIter)
         {
-            GMLFeatureClass* poClass = *iter;
-            iter ++;
+            GMLFeatureClass* poClass = *oIter;
+            oIter ++;
 
             OGRWFSLayer* poLayer;
 
@@ -1843,14 +1843,14 @@ void OGRWFSDataSource::LoadMultipleLayerDefn(const char* pszLayerName,
                         if (psIter->eType == CXT_Element &&
                             strcmp(psIter->pszValue,"complexType") == 0)
                         {
-                            const char* pszName = CPLGetXMLValue(psIter, "name", "");
+                            const char* l_pszName = CPLGetXMLValue(psIter, "name", "");
                             CPLString osExpectedName(poLayer->GetShortName());
                             osExpectedName += "Type";
                             CPLString osExpectedName2(poLayer->GetShortName());
                             osExpectedName2 += "_Type";
-                            if (strcmp(pszName, osExpectedName) == 0 ||
-                                strcmp(pszName, osExpectedName2) == 0 ||
-                                strcmp(pszName, poLayer->GetShortName()) == 0)
+                            if (strcmp(l_pszName, osExpectedName) == 0 ||
+                                strcmp(l_pszName, osExpectedName2) == 0 ||
+                                strcmp(l_pszName, poLayer->GetShortName()) == 0)
                             {
                                 bFoundComplexType = TRUE;
                             }
@@ -1863,7 +1863,7 @@ void OGRWFSDataSource::LoadMultipleLayerDefn(const char* pszLayerName,
                         else if (psIter->eType == CXT_Element &&
                                 strcmp(psIter->pszValue,"element") == 0)
                         {
-                            const char* pszName = CPLGetXMLValue(psIter, "name", "");
+                            const char* l_pszName = CPLGetXMLValue(psIter, "name", "");
                             CPLString osExpectedName(poLayer->GetShortName());
                             osExpectedName += "Type";
                             CPLString osExpectedName2(poLayer->GetShortName());
@@ -1885,9 +1885,9 @@ void OGRWFSDataSource::LoadMultipleLayerDefn(const char* pszLayerName,
                             }
                             else if (*pszType == '\0' &&
                                      CPLGetXMLNode(psIter, "complexType") != NULL &&
-                                     (strcmp(pszName, osExpectedName) == 0 ||
-                                      strcmp(pszName, osExpectedName2) == 0 ||
-                                      strcmp(pszName, poLayer->GetShortName()) == 0) )
+                                     (strcmp(l_pszName, osExpectedName) == 0 ||
+                                      strcmp(l_pszName, osExpectedName2) == 0 ||
+                                      strcmp(l_pszName, poLayer->GetShortName()) == 0) )
                             {
                                 bFoundElement = TRUE;
                                 bFoundComplexType = TRUE;
@@ -1916,11 +1916,13 @@ void OGRWFSDataSource::LoadMultipleLayerDefn(const char* pszLayerName,
 
                     if (bFoundComplexType && bFoundElement)
                     {
-                        OGRFeatureDefn* poSrcFDefn = poLayer->ParseSchema(psSchemaForLayer);
+                        OGRFeatureDefn* poSrcFDefn
+                            = poLayer->ParseSchema(psSchemaForLayer);
                         if (poSrcFDefn)
                         {
                             poLayer->BuildLayerDefn(poSrcFDefn);
-                            SaveLayerSchema(poLayer->GetName(), psSchemaForLayer);
+                            SaveLayerSchema(poLayer->GetName(),
+                                            psSchemaForLayer);
                         }
                     }
 
@@ -1928,7 +1930,9 @@ void OGRWFSDataSource::LoadMultipleLayerDefn(const char* pszLayerName,
                 }
                 else
                 {
-                    CPLDebug("WFS", "Found several time schema for layer %s in server response. Shouldn't happen",
+                    CPLDebug( "WFS",
+                              "Found several time schema for layer %s in "
+                              "server response. Should not happen",
                              poClass->GetName());
                 }
             }
@@ -1938,7 +1942,9 @@ void OGRWFSDataSource::LoadMultipleLayerDefn(const char* pszLayerName,
 
     if (nLayersFound != nLayersToFetch)
     {
-        CPLDebug("WFS", "Turn off loading of multiple layer definitions at a single time");
+        CPLDebug( "WFS",
+                  "Turn off loading of multiple layer definitions at a "
+                  "single time");
         bLoadMultipleLayerDefn = FALSE;
     }
 
@@ -2003,7 +2009,8 @@ CPLString WFS_EscapeURL(const char* pszURL)
         else
         {
             char szPercentEncoded[10];
-            sprintf( szPercentEncoded, "%%%02X", ((unsigned char*)pszURL)[i] );
+            snprintf( szPercentEncoded, sizeof(szPercentEncoded),
+                      "%%%02X", ((unsigned char*)pszURL)[i] );
             osEscapedURL += szPercentEncoded;
         }
     }
@@ -2020,7 +2027,7 @@ CPLString WFS_DecodeURL(const CPLString &osSrc)
     CPLString ret;
     char ch;
     int ii;
-    for (size_t i=0; i<osSrc.length(); i++) 
+    for (size_t i=0; i<osSrc.length(); i++)
     {
         if (osSrc[i]=='%' && i+2 < osSrc.length())
         {
@@ -2029,7 +2036,7 @@ CPLString WFS_DecodeURL(const CPLString &osSrc)
             ret+=ch;
             i=i+2;
         }
-        else 
+        else
         {
             ret+=osSrc[i];
         }
@@ -2050,18 +2057,20 @@ CPLHTTPResult* OGRWFSDataSource::HTTPFetch( const char* pszURL, char** papszOpti
         papszNewOptions = CSLMerge(papszNewOptions, papszHttpOptions);
     CPLHTTPResult* psResult = CPLHTTPFetch( pszURL, papszNewOptions );
     CSLDestroy(papszNewOptions);
-    
+
     if (psResult == NULL)
     {
         return NULL;
     }
     if (psResult->nStatus != 0 || psResult->pszErrBuf != NULL)
     {
-        /* A few buggy servers return chunked data with errouneous remaining bytes value */
-        /* curl doesn't like this. Retry with HTTP 1.0 protocol instead that doesn't support */
-        /* chunked data */
+        // A few buggy servers return chunked data with erroneous
+        // remaining bytes value curl does not like this. Retry with
+        // HTTP 1.0 protocol instead that does not support chunked
+        // data.
         if (psResult->pszErrBuf &&
-            strstr(psResult->pszErrBuf, "transfer closed with outstanding read data remaining") &&
+            strstr(psResult->pszErrBuf,
+                   "transfer closed with outstanding read data remaining") &&
             !bUseHttp10)
         {
             CPLDebug("WFS", "Probably buggy remote server. Retrying with HTTP 1.0 protocol");
@@ -2112,7 +2121,7 @@ OGRLayer * OGRWFSDataSource::ExecuteSQL( const char *pszSQLCommand,
 /* -------------------------------------------------------------------- */
 /*      Deal with "SELECT _LAST_INSERTED_FIDS_ FROM layername" statement */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszSQLCommand, "SELECT _LAST_INSERTED_FIDS_ FROM ", 33) )
+    if( STARTS_WITH_CI(pszSQLCommand, "SELECT _LAST_INSERTED_FIDS_ FROM ") )
     {
         const char* pszIter = pszSQLCommand + 33;
         while(*pszIter && *pszIter != ' ')
@@ -2141,16 +2150,16 @@ OGRLayer * OGRWFSDataSource::ExecuteSQL( const char *pszSQLCommand,
         poMEMLayer->CreateField(&oFDefn);
 
         const std::vector<CPLString>& aosFIDList = poLayer->GetLastInsertedFIDList();
-        std::vector<CPLString>::const_iterator iter = aosFIDList.begin();
-        std::vector<CPLString>::const_iterator eiter = aosFIDList.end();
-        while (iter != eiter)
+        std::vector<CPLString>::const_iterator oIter = aosFIDList.begin();
+        std::vector<CPLString>::const_iterator oEndIter = aosFIDList.end();
+        while (oIter != oEndIter)
         {
-            const CPLString& osFID = *iter;
+            const CPLString& osFID = *oIter;
             OGRFeature* poFeature = new OGRFeature(poMEMLayer->GetLayerDefn());
             poFeature->SetField(0, osFID);
-            poMEMLayer->CreateFeature(poFeature);
+            CPL_IGNORE_RET_VAL(poMEMLayer->CreateFeature(poFeature));
             delete poFeature;
-            iter ++;
+            oIter ++;
         }
 
         OGRLayer* poResLayer = new OGRWFSWrappedResultLayer(poMEMDS, poMEMLayer);
@@ -2161,7 +2170,7 @@ OGRLayer * OGRWFSDataSource::ExecuteSQL( const char *pszSQLCommand,
 /* -------------------------------------------------------------------- */
 /*      Deal with "DELETE FROM layer_name WHERE expression" statement   */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszSQLCommand, "DELETE FROM ", 12) )
+    if( STARTS_WITH_CI(pszSQLCommand, "DELETE FROM ") )
     {
         const char* pszIter = pszSQLCommand + 12;
         while(*pszIter && *pszIter != ' ')
@@ -2184,7 +2193,7 @@ OGRLayer * OGRWFSDataSource::ExecuteSQL( const char *pszSQLCommand,
 
         while(*pszIter && *pszIter == ' ')
             pszIter ++;
-        if (!EQUALN(pszIter, "WHERE ", 5))
+        if (!STARTS_WITH_CI(pszIter, "WHERE "))
         {
             CPLError(CE_Failure, CPLE_AppDefined, "WHERE clause missing");
             return NULL;
@@ -2232,10 +2241,10 @@ OGRLayer * OGRWFSDataSource::ExecuteSQL( const char *pszSQLCommand,
 /* -------------------------------------------------------------------- */
 /*      Deal with "SELECT xxxx ORDER BY" statement                      */
 /* -------------------------------------------------------------------- */
-    if (EQUALN(pszSQLCommand, "SELECT", 6))
+    if (STARTS_WITH_CI(pszSQLCommand, "SELECT"))
     {
         swq_select* psSelectInfo = new swq_select();
-        if( psSelectInfo->preparse( pszSQLCommand, TRUE ) != CPLE_None )
+        if( psSelectInfo->preparse( pszSQLCommand, TRUE ) != CE_None )
         {
             delete psSelectInfo;
             return NULL;
@@ -2263,14 +2272,14 @@ OGRLayer * OGRWFSDataSource::ExecuteSQL( const char *pszSQLCommand,
                 const char* pszFieldName = poSrcLayer->GetLayerDefn()->
                     GetFieldDefn(nFieldIndex)->GetNameRef();
 
-                OGRWFSSortDesc oSortDesc(pszFieldName, 
+                OGRWFSSortDesc oSortDesc(pszFieldName,
                                     psSelectInfo->order_defs[i].ascending_flag);
                 aoSortColumns.push_back(oSortDesc);
             }
 
             if( i == psSelectInfo->order_specs )
             {
-                OGRWFSLayer* poDupLayer = poSrcLayer->Clone(); 
+                OGRWFSLayer* poDupLayer = poSrcLayer->Clone();
 
                 poDupLayer->SetOrderBy(aoSortColumns);
                 int nBackup = psSelectInfo->order_specs;
@@ -2285,13 +2294,13 @@ OGRLayer * OGRWFSDataSource::ExecuteSQL( const char *pszSQLCommand,
                 /* base ExecuteSQL(), so that the OGRGenSQLResultsLayer references */
                 /* that temporary layer */
                 papoLayers[iLayer] = poDupLayer;
-                
+
                 OGRLayer* poResLayer = GDALDataset::ExecuteSQL( pszSQLWithoutOrderBy,
                                                                 poSpatialFilter,
                                                                 pszDialect,
                                                                 &oParseOptions );
                 papoLayers[iLayer] = poSrcLayer;
-                
+
                 CPLFree(pszSQLWithoutOrderBy);
 
                 if (poResLayer != NULL)
diff --git a/ogr/ogrsf_frmts/wfs/ogrwfsdriver.cpp b/ogr/ogrsf_frmts/wfs/ogrwfsdriver.cpp
index e308a47..3246046 100644
--- a/ogr/ogrsf_frmts/wfs/ogrwfsdriver.cpp
+++ b/ogr/ogrsf_frmts/wfs/ogrwfsdriver.cpp
@@ -32,7 +32,7 @@
 
 // g++ -fPIC -g -Wall ogr/ogrsf_frmts/wfs/*.cpp -shared -o ogr_WFS.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/gml -Iogr/ogrsf_frmts/wfs -L. -lgdal
 
-CPL_CVSID("$Id: ogrwfsdriver.cpp 29273 2015-06-02 08:08:38Z rouault $");
+CPL_CVSID("$Id: ogrwfsdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
 
 extern "C" void RegisterOGRWFS();
 
@@ -43,11 +43,11 @@ extern "C" void RegisterOGRWFS();
 static int OGRWFSDriverIdentify( GDALOpenInfo* poOpenInfo )
 
 {
-    if( !EQUALN(poOpenInfo->pszFilename, "WFS:", 4) )
+    if( !STARTS_WITH_CI(poOpenInfo->pszFilename, "WFS:") )
     {
         if( poOpenInfo->fpL == NULL )
             return FALSE;
-        if( !EQUALN((const char*)poOpenInfo->pabyHeader,"<OGRWFSDataSource>",18) &&
+        if( !STARTS_WITH_CI((const char*)poOpenInfo->pabyHeader, "<OGRWFSDataSource>") &&
             strstr((const char*)poOpenInfo->pabyHeader,"<WFS_Capabilities") == NULL &&
             strstr((const char*)poOpenInfo->pabyHeader,"<wfs:WFS_Capabilities") == NULL)
         {
@@ -87,22 +87,20 @@ static GDALDataset *OGRWFSDriverOpen( GDALOpenInfo* poOpenInfo )
 void RegisterOGRWFS()
 
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName( "WFS" ) != NULL )
+        return;
 
-    if( GDALGetDriverByName( "WFS" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "WFS" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "OGC WFS (Web Feature Service)" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_wfs.html" );
+    poDriver->SetDescription( "WFS" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "OGC WFS (Web Feature Service)" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_wfs.html" );
 
-        poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, "WFS:" );
+    poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, "WFS:" );
 
-        poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
 "<OpenOptionList>"
 "  <Option name='URL' type='string' description='URL to the WFS server endpoint' required='true'/>"
 "  <Option name='TRUST_CAPABILITIES_BOUNDS' type='boolean' description='Whether to trust layer bounds declared in GetCapabilities response' default='NO'/>"
@@ -116,12 +114,11 @@ void RegisterOGRWFS()
 "  <Option name='EXPOSE_GML_ID' type='boolean' description='Whether to make feature gml:id as a gml_id attribute.' default='YES'/>"
 "</OpenOptionList>" );
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-        poDriver->pfnIdentify = OGRWFSDriverIdentify;
-        poDriver->pfnOpen = OGRWFSDriverOpen;
+    poDriver->pfnIdentify = OGRWFSDriverIdentify;
+    poDriver->pfnOpen = OGRWFSDriverOpen;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
 
diff --git a/ogr/ogrsf_frmts/wfs/ogrwfsfilter.cpp b/ogr/ogrsf_frmts/wfs/ogrwfsfilter.cpp
index cfb91b7..65f779f 100644
--- a/ogr/ogrsf_frmts/wfs/ogrwfsfilter.cpp
+++ b/ogr/ogrsf_frmts/wfs/ogrwfsfilter.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrwfsfilter.cpp 29029 2015-04-26 21:22:57Z rouault $
+ * $Id: ogrwfsfilter.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  WFS Translator
  * Purpose:  Implements OGR SQL into OGC Filter translation.
@@ -30,7 +30,7 @@
 #include "ogr_wfs.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrwfsfilter.cpp 29029 2015-04-26 21:22:57Z rouault $");
+CPL_CVSID("$Id: ogrwfsfilter.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 typedef struct
 {
@@ -228,7 +228,7 @@ static int WFS_ExprDumpAsOGCFilter(CPLString& osFilter,
                 }
             }
         }
-        
+
         if( psOptions->poFDefn == NULL && psOptions->poDS == NULL )
             pszFieldname = poExpr->string_value;
 
@@ -270,9 +270,9 @@ static int WFS_ExprDumpAsOGCFilter(CPLString& osFilter,
 
         return TRUE;
     }
-    
+
     if( poExpr->eNodeType != SNT_OPERATION )
-        return FALSE; /* shouldn't happen */
+        return FALSE; // Should not happen.
 
     if( poExpr->nOperation == SWQ_NOT )
     {
@@ -300,8 +300,8 @@ static int WFS_ExprDumpAsOGCFilter(CPLString& osFilter,
             return FALSE;
         osFilter += CPLSPrintf("<%sLiteral>", psOptions->pszNSPrefix);
 
-        /* Escape value according to above special characters */
-        /* For URL compatibility reason, we remap the OGR SQL '%' wildchard into '*' */
+        // Escape value according to above special characters.  For URL
+        // compatibility reason, we remap the OGR SQL '%' wildcard into '*'.
         i = 0;
         ch = poExpr->papoSubExpr[1]->string_value[i];
         if (ch == '\'' || ch == '"')
@@ -407,7 +407,7 @@ static int WFS_ExprDumpAsOGCFilter(CPLString& osFilter,
         osFilter += ">";
         return TRUE;
     }
-    
+
     if( poExpr->nOperation == SWQ_CUSTOM_FUNC &&
         EQUAL(poExpr->string_value, "ST_MakeEnvelope") )
     {
@@ -466,7 +466,7 @@ static int WFS_ExprDumpAsOGCFilter(CPLString& osFilter,
                     poPROJCS->StripNodes( "AXIS" );
             }
 
-            if( EQUALN(pszSRSName, "urn:ogc:def:crs:EPSG::", strlen("urn:ogc:def:crs:EPSG::")) )
+            if( STARTS_WITH_CI(pszSRSName, "urn:ogc:def:crs:EPSG::") )
                 papszOptions = CSLSetNameValue(papszOptions, "GML3_LONGSRS", "YES");
             else
                 papszOptions = CSLSetNameValue(papszOptions, "GML3_LONGSRS", "NO");
@@ -627,7 +627,7 @@ static swq_field_type OGRWFSSpatialBooleanPredicateChecker( swq_expr_node *op,
 /*                           OGRWFSCheckSRIDArg()                       */
 /************************************************************************/
 
-static int OGRWFSCheckSRIDArg( swq_expr_node *op, int iSubArgIndex ) 
+static int OGRWFSCheckSRIDArg( swq_expr_node *op, int iSubArgIndex )
 {
     if( op->papoSubExpr[iSubArgIndex]->field_type == SWQ_INTEGER )
     {
diff --git a/ogr/ogrsf_frmts/wfs/ogrwfsjoinlayer.cpp b/ogr/ogrsf_frmts/wfs/ogrwfsjoinlayer.cpp
index 3c655ec..2b4d76f 100644
--- a/ogr/ogrsf_frmts/wfs/ogrwfsjoinlayer.cpp
+++ b/ogr/ogrsf_frmts/wfs/ogrwfsjoinlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrwfsjoinlayer.cpp 29064 2015-04-30 08:04:34Z rouault $
+ * $Id: ogrwfsjoinlayer.cpp 32983 2016-01-14 18:32:10Z goatbar $
  *
  * Project:  WFS Translator
  * Purpose:  Implements OGRWFSJoinLayer class.
@@ -30,18 +30,18 @@
 #include "ogr_wfs.h"
 #include "../../frmts/wms/md5.h"
 
-CPL_CVSID("$Id: ogrwfsjoinlayer.cpp 29064 2015-04-30 08:04:34Z rouault $");
+CPL_CVSID("$Id: ogrwfsjoinlayer.cpp 32983 2016-01-14 18:32:10Z goatbar $");
 
 /************************************************************************/
 /*                          OGRWFSJoinLayer()                           */
 /************************************************************************/
 
-OGRWFSJoinLayer::OGRWFSJoinLayer(OGRWFSDataSource* poDS,
+OGRWFSJoinLayer::OGRWFSJoinLayer(OGRWFSDataSource* poDSIn,
                                  const swq_select* psSelectInfo,
-                                 const CPLString& osGlobalFilter)
+                                 const CPLString& osGlobalFilterIn)
 {
-    this->poDS = poDS;
-    this->osGlobalFilter = osGlobalFilter;
+    this->poDS = poDSIn;
+    this->osGlobalFilter = osGlobalFilterIn;
     poFeatureDefn = NULL;
     bPagingActive = FALSE;
     nPagingStartIndex = 0;
@@ -66,7 +66,7 @@ OGRWFSJoinLayer::OGRWFSJoinLayer(OGRWFSDataSource* poDS,
         apoLayers.push_back((OGRWFSLayer*)poDS->GetLayerByName(osLayerName));
         osName += osLayerName;
     }
-    
+
     osFeatureTypes = "(";
     for(int i=0;i<(int)apoLayers.size();i++)
     {
@@ -245,7 +245,7 @@ OGRWFSJoinLayer* OGRWFSJoinLayer::Build(OGRWFSDataSource* poDS,
                                         const swq_select* psSelectInfo)
 {
     CPLString osGlobalFilter;
-    
+
     for( int i = 0; i < psSelectInfo->result_columns; i++ )
     {
         swq_col_def *def = psSelectInfo->column_defs + i;
@@ -374,7 +374,7 @@ CPLString OGRWFSJoinLayer::MakeGetFeatureURL(int bRequestHits)
 
     CPLString osFilter;
     osFilter = "<Filter xmlns=\"http://www.opengis.net/fes/2.0\"";
-    
+
     std::map<CPLString, CPLString> oMapNS;
     for(int i=0;i<(int)apoLayers.size();i++)
     {
@@ -426,13 +426,13 @@ GDALDataset* OGRWFSJoinLayer::FetchGetFeature()
     /* that we are able to understand */
     CPLString osXSDFileName = CPLSPrintf("/vsimem/tempwfs_%p/file.xsd", this);
     VSIStatBufL sBuf;
-    if (CSLTestBoolean(CPLGetConfigOption("OGR_WFS_USE_STREAMING", "YES")) &&
+    if (CPLTestBool(CPLGetConfigOption("OGR_WFS_USE_STREAMING", "YES")) &&
         VSIStatL(osXSDFileName, &sBuf) == 0 && GDALGetDriverByName("GML") != NULL)
     {
         const char* pszStreamingName = CPLSPrintf("/vsicurl_streaming/%s",
                                                     osURL.c_str());
-        if( strncmp(osURL, "/vsimem/", strlen("/vsimem/")) == 0 &&
-            CSLTestBoolean(CPLGetConfigOption("CPL_CURL_ENABLE_VSIMEM", "FALSE")) )
+        if( STARTS_WITH(osURL, "/vsimem/") &&
+            CPLTestBool(CPLGetConfigOption("CPL_CURL_ENABLE_VSIMEM", "FALSE")) )
         {
             pszStreamingName = osURL.c_str();
         }
@@ -509,10 +509,10 @@ GDALDataset* OGRWFSJoinLayer::FetchGetFeature()
 
     CPLHTTPDestroyResult(psResult);
 
-    OGRDataSource* poDS;
+    OGRDataSource* l_poDS;
 
-    poDS = (OGRDataSource*) OGROpen(osTmpFileName, FALSE, NULL);
-    if (poDS == NULL)
+    l_poDS = (OGRDataSource*) OGROpen(osTmpFileName, FALSE, NULL);
+    if (l_poDS == NULL)
     {
         if( strstr((const char*)pabyData, "<wfs:FeatureCollection") == NULL &&
             strstr((const char*)pabyData, "<gml:FeatureCollection") == NULL)
@@ -525,14 +525,14 @@ GDALDataset* OGRWFSJoinLayer::FetchGetFeature()
         return NULL;
     }
 
-    OGRLayer* poLayer = poDS->GetLayer(0);
+    OGRLayer* poLayer = l_poDS->GetLayer(0);
     if (poLayer == NULL)
     {
-        OGRDataSource::DestroyDataSource(poDS);
+        OGRDataSource::DestroyDataSource(l_poDS);
         return NULL;
     }
 
-    return poDS;
+    return l_poDS;
 }
 
 /************************************************************************/
@@ -541,7 +541,7 @@ GDALDataset* OGRWFSJoinLayer::FetchGetFeature()
 
 OGRFeature* OGRWFSJoinLayer::GetNextFeature()
 {
-    while(TRUE)
+    while( true )
     {
         if (bPagingActive && nFeatureRead == nPagingStartIndex + nFeatureCountRequested)
         {
@@ -620,7 +620,7 @@ OGRFeature* OGRWFSJoinLayer::GetNextFeature()
                     else
                     {
                         const char* pszStr = poNewFeature->GetFieldAsString(i);
-                        cvs_MD5Update( &sMD5Context, (const GByte*)pszStr, strlen(pszStr));
+                        cvs_MD5Update( &sMD5Context, (const GByte*)pszStr, static_cast<int>(strlen(pszStr)));
                     }
                 }
             }
@@ -634,7 +634,6 @@ OGRFeature* OGRWFSJoinLayer::GetNextFeature()
                 if( poGeom )
                 {
                     poGeom->assignSpatialReference(poFeatureDefn->GetGeomFieldDefn(i)->GetSpatialRef());
-                    poNewFeature->SetGeomFieldDirectly(i, poGeom);
 
                     if( bDistinct )
                     {
@@ -644,6 +643,8 @@ OGRFeature* OGRWFSJoinLayer::GetNextFeature()
                         cvs_MD5Update( &sMD5Context, (const GByte*)pabyGeom, nSize);
                         CPLFree(pabyGeom);
                     }
+
+                    poNewFeature->SetGeomFieldDirectly(i, poGeom);
                 }
             }
         }
diff --git a/ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp b/ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp
index 2944bfd..b2cda9e 100644
--- a/ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp
+++ b/ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrwfslayer.cpp 29273 2015-06-02 08:08:38Z rouault $
+ * $Id: ogrwfslayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  WFS Translator
  * Purpose:  Implements OGRWFSLayer class.
@@ -34,7 +34,7 @@
 #include "cpl_http.h"
 #include "parsexsd.h"
 
-CPL_CVSID("$Id: ogrwfslayer.cpp 29273 2015-06-02 08:08:38Z rouault $");
+CPL_CVSID("$Id: ogrwfslayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 
 /************************************************************************/
@@ -47,7 +47,7 @@ void OGRWFSRecursiveUnlink( const char *pszName )
     char **papszFileList;
     int i;
 
-    papszFileList = CPLReadDir( pszName );
+    papszFileList = VSIReadDir( pszName );
 
     for( i = 0; papszFileList != NULL && papszFileList[i] != NULL; i++ )
     {
@@ -59,15 +59,16 @@ void OGRWFSRecursiveUnlink( const char *pszName )
         CPLString osFullFilename =
                  CPLFormFilename( pszName, papszFileList[i], NULL );
 
-        VSIStatL( osFullFilename, &sStatBuf );
-
-        if( VSI_ISREG( sStatBuf.st_mode ) )
-        {
-            VSIUnlink( osFullFilename );
-        }
-        else if( VSI_ISDIR( sStatBuf.st_mode ) )
+        if( VSIStatL( osFullFilename, &sStatBuf ) == 0 )
         {
-            OGRWFSRecursiveUnlink( osFullFilename );
+            if( VSI_ISREG( sStatBuf.st_mode ) )
+            {
+                VSIUnlink( osFullFilename );
+            }
+            else if( VSI_ISDIR( sStatBuf.st_mode ) )
+            {
+                OGRWFSRecursiveUnlink( osFullFilename );
+            }
         }
     }
 
@@ -80,22 +81,22 @@ void OGRWFSRecursiveUnlink( const char *pszName )
 /*                            OGRWFSLayer()                             */
 /************************************************************************/
 
-OGRWFSLayer::OGRWFSLayer( OGRWFSDataSource* poDS,
-                          OGRSpatialReference* poSRS,
-                          int bAxisOrderAlreadyInverted,
-                          const char* pszBaseURL,
-                          const char* pszName,
-                          const char* pszNS,
-                          const char* pszNSVal )
+OGRWFSLayer::OGRWFSLayer( OGRWFSDataSource* poDSIn,
+                          OGRSpatialReference* poSRSIn,
+                          int bAxisOrderAlreadyInvertedIn,
+                          const char* pszBaseURLIn,
+                          const char* pszNameIn,
+                          const char* pszNSIn,
+                          const char* pszNSValIn )
 
 {
-    this->poDS = poDS;
-    this->poSRS = poSRS;
-    this->bAxisOrderAlreadyInverted = bAxisOrderAlreadyInverted;
-    this->pszBaseURL = CPLStrdup(pszBaseURL);
-    this->pszName = CPLStrdup(pszName);
-    this->pszNS = pszNS ? CPLStrdup(pszNS) : NULL;
-    this->pszNSVal = pszNSVal ? CPLStrdup(pszNSVal) : NULL;
+    this->poDS = poDSIn;
+    this->poSRS = poSRSIn;
+    this->bAxisOrderAlreadyInverted = bAxisOrderAlreadyInvertedIn;
+    this->pszBaseURL = CPLStrdup(pszBaseURLIn);
+    this->pszName = CPLStrdup(pszNameIn);
+    this->pszNS = pszNSIn ? CPLStrdup(pszNSIn) : NULL;
+    this->pszNSVal = pszNSValIn ? CPLStrdup(pszNSValIn) : NULL;
 
     SetDescription( pszName );
 
@@ -286,8 +287,8 @@ OGRFeatureDefn* OGRWFSLayer::ParseSchema(CPLXMLNode* psSchema)
     CPLSerializeXMLTreeToFile(psSchema, osTmpFileName);
 
     std::vector<GMLFeatureClass*> aosClasses;
-    int bFullyUnderstood = FALSE;
-    int bHaveSchema = GMLParseXSD( osTmpFileName, aosClasses, bFullyUnderstood );
+    bool bFullyUnderstood = false;
+    bool bHaveSchema = GMLParseXSD( osTmpFileName, aosClasses, bFullyUnderstood );
 
     if (bHaveSchema && aosClasses.size() == 1)
     {
@@ -296,12 +297,12 @@ OGRFeatureDefn* OGRWFSLayer::ParseSchema(CPLXMLNode* psSchema)
     }
     else if (bHaveSchema)
     {
-        std::vector<GMLFeatureClass*>::const_iterator iter = aosClasses.begin();
-        std::vector<GMLFeatureClass*>::const_iterator eiter = aosClasses.end();
-        while (iter != eiter)
+        std::vector<GMLFeatureClass*>::const_iterator oIter = aosClasses.begin();
+        std::vector<GMLFeatureClass*>::const_iterator oEndIter = aosClasses.end();
+        while (oIter != oEndIter)
         {
-            GMLFeatureClass* poClass = *iter;
-            iter ++;
+            GMLFeatureClass* poClass = *oIter;
+            oIter ++;
             delete poClass;
         }
     }
@@ -367,7 +368,7 @@ OGRFeatureDefn* OGRWFSLayer::BuildLayerDefnFromFeatureClass(GMLFeatureClass* poC
             eFType = OFTString;
 
         OGRFieldDefn oField( poProperty->GetName(), eFType );
-        if ( EQUALN(oField.GetNameRef(), "ogr:", 4) )
+        if ( STARTS_WITH_CI(oField.GetNameRef(), "ogr:") )
             oField.SetName(poProperty->GetName()+4);
         if( poProperty->GetWidth() > 0 )
             oField.SetWidth( poProperty->GetWidth() );
@@ -376,9 +377,9 @@ OGRFeatureDefn* OGRWFSLayer::BuildLayerDefnFromFeatureClass(GMLFeatureClass* poC
         if( poProperty->GetType() == GMLPT_Boolean ||
             poProperty->GetType() == GMLPT_BooleanList )
             oField.SetSubType(OFSTBoolean);
-        else if( poProperty->GetType() == GMLPT_Short) 
+        else if( poProperty->GetType() == GMLPT_Short)
             oField.SetSubType(OFSTInt16);
-        else if( poProperty->GetType() == GMLPT_Float) 
+        else if( poProperty->GetType() == GMLPT_Float)
             oField.SetSubType(OFSTFloat32);
         if( !poDS->IsEmptyAsNull() )
             oField.SetNullable(poProperty->IsNullable());
@@ -565,7 +566,7 @@ CPLString OGRWFSLayer::MakeGetFeatureURL(int nRequestMaxFeatures, int bRequestHi
 
         osURL = CPLURLAddKVP(osURL, "FILTER", WFS_EscapeURL(osFilter));
     }
-        
+
     if (bRequestHits)
     {
         osURL = CPLURLAddKVP(osURL, "RESULTTYPE", "hits");
@@ -595,7 +596,7 @@ CPLString OGRWFSLayer::MakeGetFeatureURL(int nRequestMaxFeatures, int bRequestHi
     if (pszPropertyName[0] == 0 && poFeatureDefn != NULL)
     {
         int bHasIgnoredField = FALSE;
-        CPLString osPropertyName;
+        osPropertyName.clear();
         for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
         {
             if (EQUAL(poFeatureDefn->GetFieldDefn(iField)->GetNameRef(), "gml_id"))
@@ -642,18 +643,18 @@ CPLString OGRWFSLayer::MakeGetFeatureURL(int nRequestMaxFeatures, int bRequestHi
 /*               OGRWFSFetchContentDispositionFilename()                */
 /************************************************************************/
 
-const char* OGRWFSFetchContentDispositionFilename(char** papszHeaders)
+static const char* OGRWFSFetchContentDispositionFilename(char** papszHeaders)
 {
     char** papszIter = papszHeaders;
     while(papszIter && *papszIter)
     {
         /* For multipart, we have in raw format, but without end-of-line characters */
-        if (strncmp(*papszIter, "Content-Disposition: attachment; filename=", 42) == 0)
+        if (STARTS_WITH(*papszIter, "Content-Disposition: attachment; filename="))
         {
             return *papszIter + 42;
         }
         /* For single part, the headers are in KEY=VAL format, but with e-o-l ... */
-        else if (strncmp(*papszIter, "Content-Disposition=attachment; filename=", 41) == 0)
+        else if (STARTS_WITH(*papszIter, "Content-Disposition=attachment; filename="))
         {
             char* pszVal = (char*)(*papszIter + 41);
             char* pszEOL = strchr(pszVal, '\r');
@@ -729,14 +730,14 @@ GDALDataset* OGRWFSLayer::FetchGetFeature(int nRequestMaxFeatures)
     /* that we are able to understand */
     CPLString osXSDFileName = CPLSPrintf("/vsimem/tempwfs_%p/file.xsd", this);
     VSIStatBufL sBuf;
-    if (CSLTestBoolean(CPLGetConfigOption("OGR_WFS_USE_STREAMING", "YES")) &&
+    if (CPLTestBool(CPLGetConfigOption("OGR_WFS_USE_STREAMING", "YES")) &&
         (osOutputFormat.size() == 0 || osOutputFormat.ifind("GML") != std::string::npos) &&
         VSIStatL(osXSDFileName, &sBuf) == 0 && GDALGetDriverByName("GML") != NULL)
     {
         const char* pszStreamingName = CPLSPrintf("/vsicurl_streaming/%s",
                                                     osURL.c_str());
-        if( strncmp(osURL, "/vsimem/", strlen("/vsimem/")) == 0 &&
-            CSLTestBoolean(CPLGetConfigOption("CPL_CURL_ENABLE_VSIMEM", "FALSE")) )
+        if( STARTS_WITH(osURL, "/vsimem/") &&
+            CPLTestBool(CPLGetConfigOption("CPL_CURL_ENABLE_VSIMEM", "FALSE")) )
         {
             pszStreamingName = osURL.c_str();
         }
@@ -823,7 +824,7 @@ GDALDataset* OGRWFSLayer::FetchGetFeature(int nRequestMaxFeatures)
     GByte *pabyData = psResult->pabyData;
     int    nDataLen = psResult->nDataLen;
     int bIsMultiPart = FALSE;
-    const char* pszAttachementFilename = NULL;
+    const char* pszAttachmentFilename = NULL;
 
     if(strstr(pszContentType,"multipart")
         && CPLHTTPParseMultipartMime(psResult) )
@@ -835,16 +836,16 @@ GDALDataset* OGRWFSLayer::FetchGetFeature(int nRequestMaxFeatures)
         for(i=0;i<psResult->nMimePartCount;i++)
         {
             CPLString osTmpFileName = osTmpDirName + "/";
-            pszAttachementFilename =
+            pszAttachmentFilename =
                 OGRWFSFetchContentDispositionFilename(
                     psResult->pasMimePart[i].papszHeaders);
 
-            if (pszAttachementFilename)
-                osTmpFileName += pszAttachementFilename;
+            if (pszAttachmentFilename)
+                osTmpFileName += pszAttachmentFilename;
             else
                 osTmpFileName += CPLSPrintf("file_%d", i);
 
-            GByte* pData = (GByte*)VSIMalloc(psResult->pasMimePart[i].nDataLen);
+            GByte* pData = (GByte*)VSI_MALLOC_VERBOSE(psResult->pasMimePart[i].nDataLen);
             if (pData)
             {
                 memcpy(pData, psResult->pasMimePart[i].pabyData, psResult->pasMimePart[i].nDataLen);
@@ -856,7 +857,7 @@ GDALDataset* OGRWFSLayer::FetchGetFeature(int nRequestMaxFeatures)
         }
     }
     else
-        pszAttachementFilename =
+        pszAttachmentFilename =
                 OGRWFSFetchContentDispositionFilename(
                     psResult->papszHeaders);
 
@@ -934,12 +935,12 @@ GDALDataset* OGRWFSLayer::FetchGetFeature(int nRequestMaxFeatures)
         else if (bKMZ)
             osTmpFileName = osTmpDirName + "/file.kmz";
         /* GML is a special case. It needs the .xsd file that has been saved */
-        /* as file.xsd, so we cannot used the attachement filename */
-        else if (pszAttachementFilename &&
-                 !EQUAL(CPLGetExtension(pszAttachementFilename), "GML"))
+        /* as file.xsd, so we cannot used the attachment filename */
+        else if (pszAttachmentFilename &&
+                 !EQUAL(CPLGetExtension(pszAttachmentFilename), "GML"))
         {
             osTmpFileName = osTmpDirName + "/";
-            osTmpFileName += pszAttachementFilename;
+            osTmpFileName += pszAttachmentFilename;
         }
         else
         {
@@ -1008,7 +1009,7 @@ GDALDataset* OGRWFSLayer::FetchGetFeature(int nRequestMaxFeatures)
         {
             CPLString osFullFilename =
                     CPLFormFilename( osTmpFileName, papszFileList[i], NULL );
-            GDALDriverH hDrv = GDALIdentifyDriver(osFullFilename, NULL);
+            hDrv = GDALIdentifyDriver(osFullFilename, NULL);
             if( hDrv != NULL && hDrv == GDALGetDriverByName("GML") )
                 papszOpenOptions = apszGMLOpenOptions;
             poPageDS = (GDALDataset*) GDALOpenEx(osFullFilename,
@@ -1073,18 +1074,18 @@ OGRFeatureDefn * OGRWFSLayer::BuildLayerDefn(OGRFeatureDefn* poSrcFDefn)
     poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
     poFeatureDefn->Reference();
 
-    GDALDataset* poDS = NULL;
+    GDALDataset* l_poDS = NULL;
 
     if (poSrcFDefn == NULL)
         poSrcFDefn = DescribeFeatureType();
     if (poSrcFDefn == NULL)
     {
-        poDS = FetchGetFeature(1);
-        if (poDS == NULL)
+        l_poDS = FetchGetFeature(1);
+        if (l_poDS == NULL)
         {
             return poFeatureDefn;
         }
-        poSrcFDefn = poDS->GetLayer(0)->GetLayerDefn();
+        poSrcFDefn = l_poDS->GetLayer(0)->GetLayerDefn();
         bGotApproximateLayerDefn = TRUE;
         /* We cannot trust width and precision based on a single feature */
         bUnsetWidthPrecision = TRUE;
@@ -1119,8 +1120,8 @@ OGRFeatureDefn * OGRWFSLayer::BuildLayerDefn(OGRFeatureDefn* poSrcFDefn)
         }
     }
 
-    if (poDS)
-        GDALClose(poDS);
+    if (l_poDS)
+        GDALClose(l_poDS);
     else
         delete poSrcFDefn;
 
@@ -1161,7 +1162,7 @@ OGRFeature *OGRWFSLayer::GetNextFeature()
 {
     GetLayerDefn();
 
-    while(TRUE)
+    while( true )
     {
         if (bPagingActive && nFeatureRead == nPagingStartIndex + nFeatureCountRequested)
         {
@@ -1180,6 +1181,7 @@ OGRFeature *OGRWFSLayer::GetNextFeature()
         {
             bHasFetched = TRUE;
             poBaseDS = FetchGetFeature(0);
+            poBaseLayer = NULL;
             if (poBaseDS)
             {
                 poBaseLayer = poBaseDS->GetLayer(0);
@@ -1206,7 +1208,7 @@ OGRFeature *OGRWFSLayer::GetNextFeature()
                 }
             }
         }
-        if (!poBaseLayer)
+        if (poBaseDS == NULL || poBaseLayer == NULL)
             return NULL;
 
         OGRFeature* poSrcFeature = poBaseLayer->GetNextFeature();
@@ -1224,8 +1226,8 @@ OGRFeature *OGRWFSLayer::GetNextFeature()
             continue;
         }
 
-        /* Client-side attribue filtering with underlying layer defn */
-        /* identical to exposed layer defn */
+        /* Client-side attribute filtering with underlying layer defn */
+        /* identical to exposed layer defn. */
         if( !bGotApproximateLayerDefn &&
             osWFSWhere.size() == 0 &&
             m_poAttrQuery != NULL &&
@@ -1240,7 +1242,7 @@ OGRFeature *OGRWFSLayer::GetNextFeature()
         {
             poNewFeature->SetFrom(poSrcFeature);
 
-            /* Client-side attribue filtering */
+            /* Client-side attribute filtering. */
             if( m_poAttrQuery != NULL &&
                 osWFSWhere.size() == 0 &&
                 !m_poAttrQuery->Evaluate( poNewFeature ) )
@@ -1327,7 +1329,7 @@ OGRErr OGRWFSLayer::SetAttributeFilter( const char * pszFilter )
 
     delete m_poAttrQuery;
     m_poAttrQuery = NULL;
-    
+
     if( pszFilter != NULL )
     {
         m_poAttrQuery = new OGRFeatureQuery();
@@ -1341,7 +1343,7 @@ OGRErr OGRWFSLayer::SetAttributeFilter( const char * pszFilter )
             return eErr;
         }
     }
-    
+
     if (poDS->HasMinOperators() && m_poAttrQuery != NULL )
     {
         swq_expr_node* poNode = (swq_expr_node*) m_poAttrQuery->GetSWQExpr();
@@ -1468,7 +1470,7 @@ GIntBig OGRWFSLayer::ExecuteGetFeatureResultTypeHits()
 
         CPLString osZipTmpFileName("/vsizip/" + osTmpFileName);
 
-        char** papszDirContent = CPLReadDir(osZipTmpFileName);
+        char** papszDirContent = VSIReadDir(osZipTmpFileName);
         if (CSLCount(papszDirContent) != 1)
         {
             CPLError(CE_Failure, CPLE_AppDefined,
@@ -1483,17 +1485,18 @@ GIntBig OGRWFSLayer::ExecuteGetFeatureResultTypeHits()
         osFileInZipTmpFileName += papszDirContent[0];
 
         fp = VSIFOpenL(osFileInZipTmpFileName.c_str(), "rb");
-        if (fp == NULL)
+        VSIStatBufL sBuf;
+        if (fp == NULL || VSIStatL(osFileInZipTmpFileName.c_str(), &sBuf) != 0 )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
                      "Cannot parse result of RESULTTYPE=hits request : cannot open one file in zip");
             CSLDestroy(papszDirContent);
             CPLHTTPDestroyResult(psResult);
             VSIUnlink(osTmpFileName);
+            if( fp )
+                VSIFCloseL(fp);
             return -1;
         }
-        VSIStatBufL sBuf;
-        VSIStatL(osFileInZipTmpFileName.c_str(), &sBuf);
         pabyData = (char*) CPLMalloc((size_t)(sBuf.st_size + 1));
         pabyData[sBuf.st_size] = 0;
         VSIFReadL(pabyData, 1, (size_t)sBuf.st_size, fp);
@@ -1553,23 +1556,23 @@ GIntBig OGRWFSLayer::ExecuteGetFeatureResultTypeHits()
         CPLDestroyXMLNode( psXML );
         CPLHTTPDestroyResult(psResult);
         CPLFree(pabyData);
-        
+
         poDS->DisableSupportHits();
         return -1;
     }
 
-    GIntBig nFeatures = CPLAtoGIntBig(pszValue);
+    GIntBig l_nFeatures = CPLAtoGIntBig(pszValue);
     /* Hum, http://deegree3-testing.deegree.org:80/deegree-inspire-node/services?MAXFEATURES=10&SERVICE=WFS&VERSION=1.1.0&REQUEST=GetFeature&TYPENAME=ad:Address&OUTPUTFORMAT=text/xml;%20subtype=gml/3.2.1&RESULTTYPE=hits */
     /* returns more than MAXFEATURES features... So truncate to MAXFEATURES */
     CPLString osMaxFeatures = CPLURLGetValue(osURL, atoi(poDS->GetVersion()) >= 2 ? "COUNT" : "MAXFEATURES");
     if (osMaxFeatures.size() != 0)
     {
         GIntBig nMaxFeatures = CPLAtoGIntBig(osMaxFeatures);
-        if (nFeatures > nMaxFeatures)
+        if (l_nFeatures > nMaxFeatures)
         {
             CPLDebug("WFS", "Truncating result from " CPL_FRMT_GIB " to " CPL_FRMT_GIB,
-                     nFeatures, nMaxFeatures);
-            nFeatures = nMaxFeatures;
+                     l_nFeatures, nMaxFeatures);
+            l_nFeatures = nMaxFeatures;
         }
     }
 
@@ -1577,7 +1580,7 @@ GIntBig OGRWFSLayer::ExecuteGetFeatureResultTypeHits()
     CPLHTTPDestroyResult(psResult);
     CPLFree(pabyData);
 
-    return nFeatures;
+    return l_nFeatures;
 }
 /************************************************************************/
 /*              CanRunGetFeatureCountAndGetExtentTogether()             */
@@ -1649,12 +1652,12 @@ GIntBig OGRWFSLayer::GetFeatureCount( int bForce )
 /*                              SetExtent()                             */
 /************************************************************************/
 
-void OGRWFSLayer::SetExtents(double dfMinX, double dfMinY, double dfMaxX, double dfMaxY)
+void OGRWFSLayer::SetExtents(double dfMinXIn, double dfMinYIn, double dfMaxXIn, double dfMaxYIn)
 {
-    this->dfMinX = dfMinX;
-    this->dfMinY = dfMinY;
-    this->dfMaxX = dfMaxX;
-    this->dfMaxY = dfMaxY;
+    this->dfMinX = dfMinXIn;
+    this->dfMinY = dfMinYIn;
+    this->dfMaxX = dfMaxXIn;
+    this->dfMaxY = dfMaxYIn;
     bHasExtents = TRUE;
 }
 
@@ -1866,7 +1869,7 @@ OGRErr OGRWFSLayer::ICreateFeature( OGRFeature *poFeature )
         }
 
     }
-    
+
     osPost += "    </feature:"; osPost += pszShortName; osPost += ">\n";
 
     if (!bInTransaction)
@@ -2459,7 +2462,7 @@ OGRErr OGRWFSLayer::CommitTransaction()
 
         bInTransaction = FALSE;
         osGlobalInsert = "";
-        int nExpectedInserts = this->nExpectedInserts;
+        int l_nExpectedInserts = this->nExpectedInserts;
         this->nExpectedInserts = 0;
 
         CPLDebug("WFS", "Post : %s", osPost.c_str());
@@ -2535,11 +2538,11 @@ OGRErr OGRWFSLayer::CommitTransaction()
         else
         {
             int nGotInserted = atoi(CPLGetXMLValue(psRoot, "TransactionSummary.totalInserted", ""));
-            if (nGotInserted != nExpectedInserts)
+            if (nGotInserted != l_nExpectedInserts)
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
                         "Only %d features were inserted whereas %d where expected",
-                         nGotInserted, nExpectedInserts);
+                         nGotInserted, l_nExpectedInserts);
                 CPLDestroyXMLNode( psXML );
                 CPLHTTPDestroyResult(psResult);
                 return OGRERR_FAILURE;
diff --git a/ogr/ogrsf_frmts/xls/drv_xls.html b/ogr/ogrsf_frmts/xls/drv_xls.html
index 1a4f72b..7f43ff9 100644
--- a/ogr/ogrsf_frmts/xls/drv_xls.html
+++ b/ogr/ogrsf_frmts/xls/drv_xls.html
@@ -9,7 +9,7 @@
 
 (GDAL/OGR >= 1.9.0)<p>
 
-This driver reads spreadsheets in MS Excel format. GDAL/OGR must be built against the FreeXL library (GPL/LPL/MPL licenced),
+This driver reads spreadsheets in MS Excel format. GDAL/OGR must be built against the FreeXL library (GPL/LPL/MPL licensed),
 and the driver has the same restrictions as the FreeXL library itself as far as which and how Excel files are supported.
 (At the time of writing - with FreeXL 1.0.0a -, it means in particular that formulas are not supported.)<p>
 
@@ -20,7 +20,7 @@ Each sheet is presented as a OGR layer. No geometry support is available directl
 <ul>
 <li>OGR_XLS_HEADERS = FORCE / DISABLE / AUTO : By default, the driver will read the first lines of each sheet to detect if the
 first line might be the name of columns. If set to FORCE, the driver will consider the first line will be taken as the header line.
-If set to DISABLE, it will be considered as the first feature. Otherwise auto-dection will occur.</li>
+If set to DISABLE, it will be considered as the first feature. Otherwise auto-detection will occur.</li>
 <li>OGR_XLS_FIELD_TYPES = STRING / AUTO : By default, the driver will try to detect the data type of fields. If set to STRING,
 all fields will be of String type.</li>
 </ul>
diff --git a/ogr/ogrsf_frmts/xls/ogr_xls.h b/ogr/ogrsf_frmts/xls/ogr_xls.h
index 7e972f7..a5b3603 100644
--- a/ogr/ogrsf_frmts/xls/ogr_xls.h
+++ b/ogr/ogrsf_frmts/xls/ogr_xls.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_xls.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogr_xls.h 31777 2015-11-26 14:14:41Z rouault $
  *
  * Project:  XLS Translator
  * Purpose:  Definition of classes for OGR .xls driver.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_XLS_H_INCLUDED
-#define _OGR_XLS_H_INCLUDED
+#ifndef OGR_XLS_H_INCLUDED
+#define OGR_XLS_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 
@@ -126,4 +126,4 @@ class OGRXLSDriver : public OGRSFDriver
 };
 
 
-#endif /* ndef _OGR_XLS_H_INCLUDED */
+#endif /* ndef OGR_XLS_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/xls/ogrxlsdatasource.cpp b/ogr/ogrsf_frmts/xls/ogrxlsdatasource.cpp
index 23ec9cb..5d6f59c 100644
--- a/ogr/ogrsf_frmts/xls/ogrxlsdatasource.cpp
+++ b/ogr/ogrsf_frmts/xls/ogrxlsdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrxlsdatasource.cpp 28382 2015-01-30 15:29:41Z rouault $
+ * $Id: ogrxlsdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  XLS Translator
  * Purpose:  Implements OGRXLSDataSource class
@@ -37,7 +37,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrxlsdatasource.cpp 28382 2015-01-30 15:29:41Z rouault $");
+CPL_CVSID("$Id: ogrxlsdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                          OGRXLSDataSource()                          */
@@ -107,7 +107,7 @@ int OGRXLSDataSource::Open( const char * pszFilename, int bUpdateIn)
     }
 
 #ifdef _WIN32
-    if( CSLTestBoolean( CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
+    if( CPLTestBool( CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
         pszName = CPLRecode( pszFilename, CPL_ENC_UTF8, CPLString().Printf( "CP%d", GetACP() ) );
     else
         pszName = CPLStrdup( pszFilename );
@@ -115,7 +115,7 @@ int OGRXLSDataSource::Open( const char * pszFilename, int bUpdateIn)
     pszName = CPLStrdup( pszFilename );
 #endif
 
-// -------------------------------------------------------------------- 
+// --------------------------------------------------------------------
 //      Does this appear to be a .xls file?
 // --------------------------------------------------------------------
 
diff --git a/ogr/ogrsf_frmts/xls/ogrxlsdriver.cpp b/ogr/ogrsf_frmts/xls/ogrxlsdriver.cpp
index 9071ab1..8bb7ac0 100644
--- a/ogr/ogrsf_frmts/xls/ogrxlsdriver.cpp
+++ b/ogr/ogrsf_frmts/xls/ogrxlsdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrxlsdriver.cpp 27794 2014-10-04 10:13:46Z rouault $
+ * $Id: ogrxlsdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  XLS Translator
  * Purpose:  Implements OGRXLSDriver.
@@ -30,7 +30,7 @@
 #include "ogr_xls.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrxlsdriver.cpp 27794 2014-10-04 10:13:46Z rouault $");
+CPL_CVSID("$Id: ogrxlsdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
 
 /************************************************************************/
 /*                           ~OGRXLSDriver()                            */
@@ -97,11 +97,11 @@ void RegisterOGRXLS()
 
 {
     OGRSFDriver* poDriver = new OGRXLSDriver;
-    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                "MS Excel format" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "MS Excel format" );
     poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "xls" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                "drv_xls.html" );
-    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver(poDriver);
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_xls.html" );
+
+    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( poDriver );
 }
 
diff --git a/ogr/ogrsf_frmts/xls/ogrxlslayer.cpp b/ogr/ogrsf_frmts/xls/ogrxlslayer.cpp
index 1fdd936..61883ba 100644
--- a/ogr/ogrsf_frmts/xls/ogrxlslayer.cpp
+++ b/ogr/ogrsf_frmts/xls/ogrxlslayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrxlslayer.cpp 28382 2015-01-30 15:29:41Z rouault $
+ * $Id: ogrxlslayer.cpp 31478 2015-11-14 19:13:16Z goatbar $
  *
  * Project:  XLS Translator
  * Purpose:  Implements OGRXLSLayer class.
@@ -33,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrxlslayer.cpp 28382 2015-01-30 15:29:41Z rouault $");
+CPL_CVSID("$Id: ogrxlslayer.cpp 31478 2015-11-14 19:13:16Z goatbar $");
 
 /************************************************************************/
 /*                            OGRXLSLayer()                             */
@@ -289,7 +289,7 @@ OGRFeature *OGRXLSLayer::GetNextFeature()
 
     OGRFeature  *poFeature;
 
-    while(TRUE)
+    while( true )
     {
         poFeature = GetNextRawFeature();
         if (poFeature == NULL)
diff --git a/ogr/ogrsf_frmts/xlsx/drv_xlsx.html b/ogr/ogrsf_frmts/xlsx/drv_xlsx.html
index 956a468..9a3724f 100644
--- a/ogr/ogrsf_frmts/xlsx/drv_xlsx.html
+++ b/ogr/ogrsf_frmts/xlsx/drv_xlsx.html
@@ -30,7 +30,7 @@ not understood by OGR will be lost : the document is re-written from scratch fro
 <ul>
 <li>OGR_XLSX_HEADERS = FORCE / DISABLE / AUTO : By default, the driver will read the first lines of each sheet to detect if the
 first line might be the name of columns. If set to FORCE, the driver will consider the first line will be taken as the header line.
-If set to DISABLE, it will be considered as the first feature. Otherwise auto-dection will occur.</li>
+If set to DISABLE, it will be considered as the first feature. Otherwise auto-detection will occur.</li>
 <li>OGR_XLSX_FIELD_TYPES = STRING / AUTO : By default, the driver will try to detect the data type of fields. If set to STRING,
 all fields will be of String type.</li>
 </ul>
diff --git a/ogr/ogrsf_frmts/xlsx/ogr_xlsx.h b/ogr/ogrsf_frmts/xlsx/ogr_xlsx.h
index abefe67..ef6a3ce 100644
--- a/ogr/ogrsf_frmts/xlsx/ogr_xlsx.h
+++ b/ogr/ogrsf_frmts/xlsx/ogr_xlsx.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_xlsx.h 28900 2015-04-14 09:40:34Z rouault $
+ * $Id: ogr_xlsx.h 32062 2015-12-07 11:02:56Z rouault $
  *
  * Project:  XLSX Translator
  * Purpose:  Definition of classes for OGR OpenOfficeSpreadsheet .xlsx driver.
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_XLSX_H_INCLUDED
-#define _OGR_XLSX_H_INCLUDED
+#ifndef OGR_XLSX_H_INCLUDED
+#define OGR_XLSX_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 
@@ -39,6 +39,8 @@
 #include <string>
 #include <map>
 
+namespace OGRXLSX {
+
 /************************************************************************/
 /*                             OGRXLSXLayer                             */
 /************************************************************************/
@@ -101,8 +103,8 @@ class OGRXLSXLayer : public OGRMemLayer
     virtual OGRErr      ReorderFields( int* panMap )
     { Init(); SetUpdated(); return OGRMemLayer::ReorderFields(panMap); }
 
-    virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags )
-    { Init(); SetUpdated(); return OGRMemLayer::AlterFieldDefn(iField, poNewFieldDefn, nFlags); }
+    virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlagsIn )
+    { Init(); SetUpdated(); return OGRMemLayer::AlterFieldDefn(iField, poNewFieldDefn, nFlagsIn); }
 
     int                 TestCapability( const char * pszCap )
     { Init(); return OGRMemLayer::TestCapability(pszCap); }
@@ -142,9 +144,9 @@ public:
     int               bHasMS;
 
                     XLSXFieldTypeExtended() : eType(OFTMaxType), bHasMS(FALSE) {}
-                    XLSXFieldTypeExtended(OGRFieldType eType,
-                                          int bHasMS = FALSE) :
-                                    eType(eType), bHasMS(bHasMS) {}
+                    XLSXFieldTypeExtended(OGRFieldType eTypeIn,
+                                          int bHasMSIn = FALSE) :
+                                    eType(eTypeIn), bHasMS(bHasMSIn) {}
 };
 
 class OGRXLSXDataSource : public OGRDataSource
@@ -253,6 +255,8 @@ class OGRXLSXDataSource : public OGRDataSource
     void                SetUpdated() { bUpdated = TRUE; }
 };
 
+} /* end of OGRXLSX namespace */
+
 /************************************************************************/
 /*                             OGRXLSXDriver                             */
 /************************************************************************/
@@ -269,8 +273,6 @@ class OGRXLSXDriver : public OGRSFDriver
     virtual OGRDataSource *CreateDataSource( const char *pszName,
                                              char ** = NULL );
     virtual OGRErr      DeleteDataSource( const char *pszName );
-    
 };
 
-
-#endif /* ndef _OGR_XLSX_H_INCLUDED */
+#endif /* ndef OGR_XLSX_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/xlsx/ogrxlsxdatasource.cpp b/ogr/ogrsf_frmts/xlsx/ogrxlsxdatasource.cpp
index 8a6add2..65ad997 100644
--- a/ogr/ogrsf_frmts/xlsx/ogrxlsxdatasource.cpp
+++ b/ogr/ogrsf_frmts/xlsx/ogrxlsxdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrxlsxdatasource.cpp 28900 2015-04-14 09:40:34Z rouault $
+ * $Id: ogrxlsxdatasource.cpp 33437 2016-02-12 11:02:55Z rouault $
  *
  * Project:  XLSX Translator
  * Purpose:  Implements OGRXLSXDataSource class
@@ -32,7 +32,9 @@
 #include "cpl_conv.h"
 #include "cpl_time.h"
 
-CPL_CVSID("$Id: ogrxlsxdatasource.cpp 28900 2015-04-14 09:40:34Z rouault $");
+CPL_CVSID("$Id: ogrxlsxdatasource.cpp 33437 2016-02-12 11:02:55Z rouault $");
+
+namespace OGRXLSX {
 
 /************************************************************************/
 /*                            OGRXLSXLayer()                            */
@@ -289,13 +291,13 @@ int OGRXLSXDataSource::Create( const char * pszFilename,
 /*                           startElementCbk()                          */
 /************************************************************************/
 
-static void XMLCALL startElementCbk(void *pUserData, const char *pszName,
+static void XMLCALL startElementCbk(void *pUserData, const char *pszNameIn,
                                     const char **ppszAttr)
 {
-    ((OGRXLSXDataSource*)pUserData)->startElementCbk(pszName, ppszAttr);
+    ((OGRXLSXDataSource*)pUserData)->startElementCbk(pszNameIn, ppszAttr);
 }
 
-void OGRXLSXDataSource::startElementCbk(const char *pszName,
+void OGRXLSXDataSource::startElementCbk(const char *pszNameIn,
                                        const char **ppszAttr)
 {
     if (bStopParsing) return;
@@ -303,10 +305,10 @@ void OGRXLSXDataSource::startElementCbk(const char *pszName,
     nWithoutEventCounter = 0;
     switch(stateStack[nStackDepth].eVal)
     {
-        case STATE_DEFAULT: startElementDefault(pszName, ppszAttr); break;
-        case STATE_SHEETDATA:   startElementTable(pszName, ppszAttr); break;
-        case STATE_ROW:     startElementRow(pszName, ppszAttr); break;
-        case STATE_CELL:    startElementCell(pszName, ppszAttr); break;
+        case STATE_DEFAULT: startElementDefault(pszNameIn, ppszAttr); break;
+        case STATE_SHEETDATA:   startElementTable(pszNameIn, ppszAttr); break;
+        case STATE_ROW:     startElementRow(pszNameIn, ppszAttr); break;
+        case STATE_CELL:    startElementCell(pszNameIn, ppszAttr); break;
         case STATE_TEXTV:   break;
         default:            break;
     }
@@ -317,12 +319,12 @@ void OGRXLSXDataSource::startElementCbk(const char *pszName,
 /*                            endElementCbk()                           */
 /************************************************************************/
 
-static void XMLCALL endElementCbk(void *pUserData, const char *pszName)
+static void XMLCALL endElementCbk(void *pUserData, const char *pszNameIn)
 {
-    ((OGRXLSXDataSource*)pUserData)->endElementCbk(pszName);
+    ((OGRXLSXDataSource*)pUserData)->endElementCbk(pszNameIn);
 }
 
-void OGRXLSXDataSource::endElementCbk(const char *pszName)
+void OGRXLSXDataSource::endElementCbk(const char *pszNameIn)
 {
     if (bStopParsing) return;
 
@@ -332,9 +334,9 @@ void OGRXLSXDataSource::endElementCbk(const char *pszName)
     switch(stateStack[nStackDepth].eVal)
     {
         case STATE_DEFAULT: break;
-        case STATE_SHEETDATA:   endElementTable(pszName); break;
-        case STATE_ROW:     endElementRow(pszName); break;
-        case STATE_CELL:    endElementCell(pszName); break;
+        case STATE_SHEETDATA:   endElementTable(pszNameIn); break;
+        case STATE_ROW:     endElementRow(pszNameIn); break;
+        case STATE_CELL:    endElementCell(pszNameIn); break;
         case STATE_TEXTV:   break;
         default:            break;
     }
@@ -431,7 +433,7 @@ OGRFieldType OGRXLSXDataSource::GetOGRFieldType(const char* pszValue,
         else if (eValueType == CPL_VALUE_INTEGER)
         {
             GIntBig nVal = CPLAtoGIntBig(pszValue);
-            if( (GIntBig)(int)nVal != nVal )
+            if( !CPL_INT64_FITS_ON_INT32(nVal) )
                 return OFTInteger64;
             else
                 return OFTInteger;
@@ -488,7 +490,8 @@ static void SetField(OGRFeature* poFeature,
         {
             double fFracSec = fmod(fmod(dfNumberOfDaysSince1900,1) * 3600 * 24, 1);
             poFeature->SetField(i, sTm.tm_year + 1900, sTm.tm_mon + 1, sTm.tm_mday,
-                                sTm.tm_hour, sTm.tm_min, sTm.tm_sec + fFracSec, 0 );
+                                sTm.tm_hour, sTm.tm_min,
+                                static_cast<float>(sTm.tm_sec + fFracSec), 0 );
         }
         else if (strcmp(pszCellType, "time") == 0)
         {
@@ -505,7 +508,8 @@ static void SetField(OGRFeature* poFeature,
             double fFracSec = fmod(fmod(dfNumberOfDaysSince1900,1) * 3600 * 24, 1);
             poFeature->SetField(i,
                                 sTm.tm_year + 1900, sTm.tm_mon + 1, sTm.tm_mday,
-                                sTm.tm_hour, sTm.tm_min, sTm.tm_sec + fFracSec, 0);
+                                sTm.tm_hour, sTm.tm_min,
+                                static_cast<float>(sTm.tm_sec + fFracSec), 0);
         }
     }
     else
@@ -571,10 +575,10 @@ void OGRXLSXDataSource::DetectHeaderLine()
 /*                          startElementDefault()                       */
 /************************************************************************/
 
-void OGRXLSXDataSource::startElementDefault(const char *pszName,
+void OGRXLSXDataSource::startElementDefault(const char *pszNameIn,
                                             CPL_UNUSED const char **ppszAttr)
 {
-    if (strcmp(pszName, "sheetData") == 0)
+    if (strcmp(pszNameIn, "sheetData") == 0)
     {
         apoFirstLineValues.resize(0);
         apoFirstLineTypes.resize(0);
@@ -587,10 +591,10 @@ void OGRXLSXDataSource::startElementDefault(const char *pszName,
 /*                          startElementTable()                        */
 /************************************************************************/
 
-void OGRXLSXDataSource::startElementTable(const char *pszName,
+void OGRXLSXDataSource::startElementTable(const char *pszNameIn,
                                          const char **ppszAttr)
 {
-    if (strcmp(pszName, "row") == 0)
+    if (strcmp(pszNameIn, "row") == 0)
     {
         PushState(STATE_ROW);
 
@@ -613,11 +617,11 @@ void OGRXLSXDataSource::startElementTable(const char *pszName,
 /*                           endElementTable()                          */
 /************************************************************************/
 
-void OGRXLSXDataSource::endElementTable(CPL_UNUSED const char *pszName)
+void OGRXLSXDataSource::endElementTable(CPL_UNUSED const char *pszNameIn)
 {
     if (stateStack[nStackDepth].nBeginDepth == nDepth)
     {
-        CPLAssert(strcmp(pszName, "sheetData") == 0);
+        CPLAssert(strcmp(pszNameIn, "sheetData") == 0);
 
         if (nCurLine == 0 ||
             (nCurLine == 1 && apoFirstLineValues.size() == 0))
@@ -640,16 +644,16 @@ void OGRXLSXDataSource::endElementTable(CPL_UNUSED const char *pszName)
             OGRFeature* poFeature = new OGRFeature(poCurLayer->GetLayerDefn());
             for(i = 0; i < apoFirstLineValues.size(); i++)
             {
-                SetField(poFeature, i, apoFirstLineValues[i].c_str(),
+                SetField(poFeature, static_cast<int>(i), apoFirstLineValues[i].c_str(),
                          apoFirstLineTypes[i].c_str());
             }
-            poCurLayer->CreateFeature(poFeature);
+            CPL_IGNORE_RET_VAL(poCurLayer->CreateFeature(poFeature));
             delete poFeature;
         }
 
         if (poCurLayer)
         {
-            ((OGRMemLayer*)poCurLayer)->SetUpdatable(bUpdatable);
+            ((OGRMemLayer*)poCurLayer)->SetUpdatable(CPL_TO_BOOL(bUpdatable));
             ((OGRMemLayer*)poCurLayer)->SetAdvertizeUTF8(TRUE);
             ((OGRXLSXLayer*)poCurLayer)->SetUpdated(FALSE);
         }
@@ -662,10 +666,10 @@ void OGRXLSXDataSource::endElementTable(CPL_UNUSED const char *pszName)
 /*                            startElementRow()                         */
 /************************************************************************/
 
-void OGRXLSXDataSource::startElementRow(const char *pszName,
+void OGRXLSXDataSource::startElementRow(const char *pszNameIn,
                                        const char **ppszAttr)
 {
-    if (strcmp(pszName, "c") == 0)
+    if (strcmp(pszNameIn, "c") == 0)
     {
         PushState(STATE_CELL);
 
@@ -673,11 +677,16 @@ void OGRXLSXDataSource::startElementRow(const char *pszName,
         if (pszR)
         {
             /* Convert col number from base 26 */
+            /*
+            A Z   AA AZ   BA BZ   ZA   ZZ   AAA    ZZZ      AAAA
+            0 25  26 51   52 77   676  701  702    18277    18278
+            */
             int nNewCurCol = (pszR[0] - 'A');
             int i = 1;
             while(pszR[i] >= 'A' && pszR[i] <= 'Z')
             {
-                nNewCurCol = nNewCurCol * 26 + (pszR[i] - 'A');
+                // We wouldn't need the +1 if this was a proper base 26
+                nNewCurCol = (nNewCurCol + 1) * 26 + (pszR[i] - 'A');
                 i ++;
             }
             for(;nCurCol<nNewCurCol;nCurCol++)
@@ -723,11 +732,11 @@ void OGRXLSXDataSource::startElementRow(const char *pszName,
 /*                            endElementRow()                           */
 /************************************************************************/
 
-void OGRXLSXDataSource::endElementRow(CPL_UNUSED const char *pszName)
+void OGRXLSXDataSource::endElementRow(CPL_UNUSED const char *pszNameIn)
 {
     if (stateStack[nStackDepth].nBeginDepth == nDepth)
     {
-        CPLAssert(strcmp(pszName, "row") == 0);
+        CPLAssert(strcmp(pszNameIn, "row") == 0);
 
         OGRFeature* poFeature;
         size_t i;
@@ -788,10 +797,10 @@ void OGRXLSXDataSource::endElementRow(CPL_UNUSED const char *pszName)
                 poFeature = new OGRFeature(poCurLayer->GetLayerDefn());
                 for(i = 0; i < apoFirstLineValues.size(); i++)
                 {
-                    SetField(poFeature, i, apoFirstLineValues[i].c_str(),
+                    SetField(poFeature, static_cast<int>(i), apoFirstLineValues[i].c_str(),
                              apoFirstLineTypes[i].c_str());
                 }
-                poCurLayer->CreateFeature(poFeature);
+                CPL_IGNORE_RET_VAL(poCurLayer->CreateFeature(poFeature));
                 delete poFeature;
             }
         }
@@ -827,7 +836,7 @@ void OGRXLSXDataSource::endElementRow(CPL_UNUSED const char *pszName)
                                                 apoCurLineValues[i].c_str(),
                                                 apoCurLineTypes[i].c_str());
                         OGRFieldType eFieldType =
-                            poCurLayer->GetLayerDefn()->GetFieldDefn(i)->GetType();
+                            poCurLayer->GetLayerDefn()->GetFieldDefn(static_cast<int>(i))->GetType();
                         if (eFieldType == OFTDateTime &&
                             (eValType == OFTDate || eValType == OFTTime) )
                         {
@@ -844,7 +853,7 @@ void OGRXLSXDataSource::endElementRow(CPL_UNUSED const char *pszName)
                         else if (eFieldType != OFTString && eValType != eFieldType)
                         {
                             OGRFieldDefn oNewFieldDefn(
-                                poCurLayer->GetLayerDefn()->GetFieldDefn(i));
+                                poCurLayer->GetLayerDefn()->GetFieldDefn(static_cast<int>(i)));
                             if ((eFieldType == OFTDate || eFieldType == OFTTime) &&
                                    eValType == OFTDateTime)
                                 oNewFieldDefn.SetType(OFTDateTime);
@@ -855,7 +864,7 @@ void OGRXLSXDataSource::endElementRow(CPL_UNUSED const char *pszName)
                                 oNewFieldDefn.SetType(OFTInteger64);
                             else
                                 oNewFieldDefn.SetType(OFTString);
-                            poCurLayer->AlterFieldDefn(i, &oNewFieldDefn,
+                            poCurLayer->AlterFieldDefn(static_cast<int>(i), &oNewFieldDefn,
                                                        ALTER_TYPE_FLAG);
                         }
                     }
@@ -866,10 +875,10 @@ void OGRXLSXDataSource::endElementRow(CPL_UNUSED const char *pszName)
             poFeature = new OGRFeature(poCurLayer->GetLayerDefn());
             for(i = 0; i < apoCurLineValues.size(); i++)
             {
-                SetField(poFeature, i, apoCurLineValues[i].c_str(),
+                SetField(poFeature, static_cast<int>(i), apoCurLineValues[i].c_str(),
                          apoCurLineTypes[i].c_str());
             }
-            poCurLayer->CreateFeature(poFeature);
+            CPL_IGNORE_RET_VAL(poCurLayer->CreateFeature(poFeature));
             delete poFeature;
        }
 
@@ -881,14 +890,14 @@ void OGRXLSXDataSource::endElementRow(CPL_UNUSED const char *pszName)
 /*                           startElementCell()                         */
 /************************************************************************/
 
-void OGRXLSXDataSource::startElementCell(const char *pszName,
+void OGRXLSXDataSource::startElementCell(const char *pszNameIn,
                                          CPL_UNUSED const char **ppszAttr)
 {
-    if (osValue.size() == 0 && strcmp(pszName, "v") == 0)
+    if (osValue.size() == 0 && strcmp(pszNameIn, "v") == 0)
     {
         PushState(STATE_TEXTV);
     }
-    else if (osValue.size() == 0 && strcmp(pszName, "t") == 0)
+    else if (osValue.size() == 0 && strcmp(pszNameIn, "t") == 0)
     {
         PushState(STATE_TEXTV);
     }
@@ -898,11 +907,11 @@ void OGRXLSXDataSource::startElementCell(const char *pszName,
 /*                            endElementCell()                          */
 /************************************************************************/
 
-void OGRXLSXDataSource::endElementCell(CPL_UNUSED const char *pszName)
+void OGRXLSXDataSource::endElementCell(CPL_UNUSED const char *pszNameIn)
 {
     if (stateStack[nStackDepth].nBeginDepth == nDepth)
     {
-        CPLAssert(strcmp(pszName, "c") == 0);
+        CPLAssert(strcmp(pszNameIn, "c") == 0);
 
         if (osValueType == "stringLookup")
         {
@@ -948,8 +957,8 @@ void OGRXLSXDataSource::BuildLayer(OGRXLSXLayer* poLayer, int nSheetId)
     int bUpdatedBackup = bUpdated;
 
     oParser = OGRCreateExpatXMLParser();
-    XML_SetElementHandler(oParser, ::startElementCbk, ::endElementCbk);
-    XML_SetCharacterDataHandler(oParser, ::dataHandlerCbk);
+    XML_SetElementHandler(oParser, OGRXLSX::startElementCbk, OGRXLSX::endElementCbk);
+    XML_SetCharacterDataHandler(oParser, OGRXLSX::dataHandlerCbk);
     XML_SetUserData(oParser, this);
 
     VSIFSeekL( fp, 0, SEEK_SET );
@@ -1002,13 +1011,13 @@ void OGRXLSXDataSource::BuildLayer(OGRXLSXLayer* poLayer, int nSheetId)
 /*                          startElementSSCbk()                         */
 /************************************************************************/
 
-static void XMLCALL startElementSSCbk(void *pUserData, const char *pszName,
+static void XMLCALL startElementSSCbk(void *pUserData, const char *pszNameIn,
                                     const char **ppszAttr)
 {
-    ((OGRXLSXDataSource*)pUserData)->startElementSSCbk(pszName, ppszAttr);
+    ((OGRXLSXDataSource*)pUserData)->startElementSSCbk(pszNameIn, ppszAttr);
 }
 
-void OGRXLSXDataSource::startElementSSCbk(const char *pszName,
+void OGRXLSXDataSource::startElementSSCbk(const char *pszNameIn,
                                           CPL_UNUSED const char **ppszAttr)
 {
     if (bStopParsing) return;
@@ -1018,7 +1027,7 @@ void OGRXLSXDataSource::startElementSSCbk(const char *pszName,
     {
         case STATE_DEFAULT:
         {
-            if (strcmp(pszName,"t") == 0)
+            if (strcmp(pszNameIn,"t") == 0)
             {
                 PushState(STATE_T);
                 osCurrentString = "";
@@ -1035,12 +1044,12 @@ void OGRXLSXDataSource::startElementSSCbk(const char *pszName,
 /*                           endElementSSCbk()                          */
 /************************************************************************/
 
-static void XMLCALL endElementSSCbk(void *pUserData, const char *pszName)
+static void XMLCALL endElementSSCbk(void *pUserData, const char *pszNameIn)
 {
-    ((OGRXLSXDataSource*)pUserData)->endElementSSCbk(pszName);
+    ((OGRXLSXDataSource*)pUserData)->endElementSSCbk(pszNameIn);
 }
 
-void OGRXLSXDataSource::endElementSSCbk(CPL_UNUSED const char *pszName)
+void OGRXLSXDataSource::endElementSSCbk(CPL_UNUSED const char *pszNameIn)
 {
     if (bStopParsing) return;
 
@@ -1108,8 +1117,8 @@ void OGRXLSXDataSource::AnalyseSharedStrings(VSILFILE* fpSharedStrings)
         return;
 
     oParser = OGRCreateExpatXMLParser();
-    XML_SetElementHandler(oParser, ::startElementSSCbk, ::endElementSSCbk);
-    XML_SetCharacterDataHandler(oParser, ::dataHandlerSSCbk);
+    XML_SetElementHandler(oParser, OGRXLSX::startElementSSCbk, OGRXLSX::endElementSSCbk);
+    XML_SetCharacterDataHandler(oParser, OGRXLSX::dataHandlerSSCbk);
     XML_SetUserData(oParser, this);
 
     VSIFSeekL( fpSharedStrings, 0, SEEK_SET );
@@ -1162,19 +1171,19 @@ void OGRXLSXDataSource::AnalyseSharedStrings(VSILFILE* fpSharedStrings)
 /*                          startElementWBCbk()                         */
 /************************************************************************/
 
-static void XMLCALL startElementWBCbk(void *pUserData, const char *pszName,
+static void XMLCALL startElementWBCbk(void *pUserData, const char *pszNameIn,
                                     const char **ppszAttr)
 {
-    ((OGRXLSXDataSource*)pUserData)->startElementWBCbk(pszName, ppszAttr);
+    ((OGRXLSXDataSource*)pUserData)->startElementWBCbk(pszNameIn, ppszAttr);
 }
 
-void OGRXLSXDataSource::startElementWBCbk(const char *pszName,
+void OGRXLSXDataSource::startElementWBCbk(const char *pszNameIn,
                                        const char **ppszAttr)
 {
     if (bStopParsing) return;
 
     nWithoutEventCounter = 0;
-    if (strcmp(pszName,"sheet") == 0)
+    if (strcmp(pszNameIn,"sheet") == 0)
     {
         const char* pszSheetName = GetAttributeValue(ppszAttr, "name", NULL);
         /*const char* pszSheetId = GetAttributeValue(ppszAttr, "sheetId", NULL);*/
@@ -1195,7 +1204,7 @@ void OGRXLSXDataSource::startElementWBCbk(const char *pszName,
 void OGRXLSXDataSource::AnalyseWorkbook(VSILFILE* fpWorkbook)
 {
     oParser = OGRCreateExpatXMLParser();
-    XML_SetElementHandler(oParser, ::startElementWBCbk, NULL);
+    XML_SetElementHandler(oParser, OGRXLSX::startElementWBCbk, NULL);
     XML_SetUserData(oParser, this);
 
     VSIFSeekL( fpWorkbook, 0, SEEK_SET );
@@ -1243,19 +1252,19 @@ void OGRXLSXDataSource::AnalyseWorkbook(VSILFILE* fpWorkbook)
 /*                       startElementStylesCbk()                        */
 /************************************************************************/
 
-static void XMLCALL startElementStylesCbk(void *pUserData, const char *pszName,
+static void XMLCALL startElementStylesCbk(void *pUserData, const char *pszNameIn,
                                     const char **ppszAttr)
 {
-    ((OGRXLSXDataSource*)pUserData)->startElementStylesCbk(pszName, ppszAttr);
+    ((OGRXLSXDataSource*)pUserData)->startElementStylesCbk(pszNameIn, ppszAttr);
 }
 
-void OGRXLSXDataSource::startElementStylesCbk(const char *pszName,
+void OGRXLSXDataSource::startElementStylesCbk(const char *pszNameIn,
                                        const char **ppszAttr)
 {
     if (bStopParsing) return;
 
     nWithoutEventCounter = 0;
-    if (strcmp(pszName,"numFmt") == 0)
+    if (strcmp(pszNameIn,"numFmt") == 0)
     {
         const char* pszFormatCode = GetAttributeValue(ppszAttr, "formatCode", NULL);
         const char* pszNumFmtId = GetAttributeValue(ppszAttr, "numFmtId", "-1");
@@ -1276,11 +1285,11 @@ void OGRXLSXDataSource::startElementStylesCbk(const char *pszName,
                 apoMapStyleFormats[nNumFmtId] = XLSXFieldTypeExtended(OFTReal);
         }
     }
-    else if (strcmp(pszName,"cellXfs") == 0)
+    else if (strcmp(pszNameIn,"cellXfs") == 0)
     {
         bInCellXFS = TRUE;
     }
-    else if (bInCellXFS && strcmp(pszName,"xf") == 0)
+    else if (bInCellXFS && strcmp(pszNameIn,"xf") == 0)
     {
         const char* pszNumFmtId = GetAttributeValue(ppszAttr, "numFmtId", "-1");
         int nNumFmtId = atoi(pszNumFmtId);
@@ -1316,17 +1325,17 @@ void OGRXLSXDataSource::startElementStylesCbk(const char *pszName,
 /*                       endElementStylesCbk()                          */
 /************************************************************************/
 
-static void XMLCALL endElementStylesCbk(void *pUserData, const char *pszName)
+static void XMLCALL endElementStylesCbk(void *pUserData, const char *pszNameIn)
 {
-    ((OGRXLSXDataSource*)pUserData)->endElementStylesCbk(pszName);
+    ((OGRXLSXDataSource*)pUserData)->endElementStylesCbk(pszNameIn);
 }
 
-void OGRXLSXDataSource::endElementStylesCbk(const char *pszName)
+void OGRXLSXDataSource::endElementStylesCbk(const char *pszNameIn)
 {
     if (bStopParsing) return;
 
     nWithoutEventCounter = 0;
-    if (strcmp(pszName,"cellXfs") == 0)
+    if (strcmp(pszNameIn,"cellXfs") == 0)
     {
         bInCellXFS = FALSE;
     }
@@ -1342,7 +1351,7 @@ void OGRXLSXDataSource::AnalyseStyles(VSILFILE* fpStyles)
         return;
 
     oParser = OGRCreateExpatXMLParser();
-    XML_SetElementHandler(oParser, ::startElementStylesCbk, ::endElementStylesCbk);
+    XML_SetElementHandler(oParser, OGRXLSX::startElementStylesCbk, OGRXLSX::endElementStylesCbk);
     XML_SetUserData(oParser, this);
 
     VSIFSeekL( fpStyles, 0, SEEK_SET );
@@ -1654,7 +1663,9 @@ static void BuildColString(char szCol[5], int nCol)
     while(nCol >= 26)
     {
         nCol /= 26;
-        nCol --; /* We wouldn't need that if this was a proper base 26 numeration scheme ! */
+        // We would not need a decrement if this was a proper base 26
+        // numeration scheme.
+        nCol --;
         szCol[k++] = (nCol % 26) + 'A';
     }
     szCol[k] = 0;
@@ -1962,8 +1973,6 @@ static void WriteDotRels(const char* pszName)
 
 void OGRXLSXDataSource::FlushCache()
 {
-    int i;
-
     if (!bUpdated)
         return;
 
@@ -2006,7 +2015,7 @@ void OGRXLSXDataSource::FlushCache()
     std::vector<std::string> oStringList;
 
     //VSIMkdir(CPLSPrintf("/vsizip/%s/xl/worksheets", pszName),0755);
-    for(i=0;i<nLayers;i++)
+    for(int i=0;i<nLayers;i++)
     {
         WriteLayer(pszName, GetLayer(i), i, oStringMap, oStringList);
     }
@@ -2032,3 +2041,5 @@ void OGRXLSXDataSource::FlushCache()
 
     return;
 }
+
+} /* end of OGRXLSX namespace */
diff --git a/ogr/ogrsf_frmts/xlsx/ogrxlsxdriver.cpp b/ogr/ogrsf_frmts/xlsx/ogrxlsxdriver.cpp
index e37813f..1cda336 100644
--- a/ogr/ogrsf_frmts/xlsx/ogrxlsxdriver.cpp
+++ b/ogr/ogrsf_frmts/xlsx/ogrxlsxdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrxlsxdriver.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrxlsxdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  XLSX Translator
  * Purpose:  Implements OGRXLSXDriver.
@@ -30,10 +30,12 @@
 #include "ogr_xlsx.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrxlsxdriver.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrxlsxdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
 
 extern "C" void RegisterOGRXLSX();
 
+using namespace OGRXLSX;
+
 // g++ -DHAVE_EXPAT -g -Wall -fPIC ogr/ogrsf_frmts/xlsx/*.cpp -shared -o ogr_XLSX.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/mem -Iogr/ogrsf_frmts/xlsx -L. -lgdal
 
 /************************************************************************/
@@ -193,13 +195,16 @@ void RegisterOGRXLSX()
 
 {
     OGRSFDriver* poDriver = new OGRXLSXDriver;
+
     poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                "MS Office Open XML spreadsheet" );
+                               "MS Office Open XML spreadsheet" );
     poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "xlsx" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                "drv_xlsx.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_xlsx.html" );
     poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES, "Integer Integer64 Real String Date DateTime Time" );
-    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver(poDriver);
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
+                               "Integer Integer64 Real String Date DateTime "
+                               "Time" );
+
+    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( poDriver );
 }
 
diff --git a/ogr/ogrsf_frmts/xplane/drv_xplane.html b/ogr/ogrsf_frmts/xplane/drv_xplane.html
index 946018c..3b32b0a 100644
--- a/ogr/ogrsf_frmts/xplane/drv_xplane.html
+++ b/ogr/ogrsf_frmts/xplane/drv_xplane.html
@@ -21,18 +21,21 @@ The driver is able to read the following files :<p>
 
 <p>
 
-Each file will be reported as a set of layers whose data schema is given below.
-The data schema is generally as close as possible to the original schema data described
-in the X-Plane specificiation. However, please note that meters (or kilometers) are always used
-to report heights, elevations, distances (widths, lengths), etc., even if the original data
-are sometimes expressed in feet or nautical miles.<p>
-
-Data is reported as being expressed in WGS84 datum (latitude, longitude), altough the specificiation
-is not very clear on that subject.</p>
-
-The OGR_XPLANE_READ_WHOLE_FILE configuration option can be set to FALSE when reading a big file 
-in regards with the available RAM (especially true for apt.dat). This option forces the driver not to cache features in RAM,
-but just to fetch the features of the current layer. Of course, this will have a negative impact on performance.
+Each file will be reported as a set of layers whose data schema is given
+below.  The data schema is generally as close as possible to the original
+schema data described in the X-Plane specification. However, please note that
+meters (or kilometers) are always used to report heights, elevations,
+distances (widths, lengths), etc., even if the original data are sometimes
+expressed in feet or nautical miles.<p>
+
+Data is reported as being expressed in WGS84 datum (latitude, longitude),
+although the specification is not very clear on that subject.</p>
+
+The OGR_XPLANE_READ_WHOLE_FILE configuration option can be set to FALSE when
+reading a big file in regards with the available RAM (especially true for
+apt.dat). This option forces the driver not to cache features in RAM, but just
+to fetch the features of the current layer. Of course, this will have a
+negative impact on performance.
 
 <h2>Examples</h2>
 
@@ -88,8 +91,9 @@ that can serve as a foreign key.<p>
 
 <h3><a name="APT">APT layer</a></h3>
 
-Main description for an aiport. The position reported will be the position of the tower view point if present, otherwise the
-position of the first runway threshold found.<p>
+Main description for an airport. The position reported will be the
+position of the tower view point if present, otherwise the position of
+the first runway threshold found.<p>
 
 Fields:
 <ul>
@@ -115,7 +119,7 @@ the non-displaced threshold position (is_displaced=0), and another one at the di
 Fields:
 <ul>
 <li>apt_icao: String (5.0). ICAO code for the airport of this runway threshold.
-<li>rwy_num: String (3.0). Code for the runway, such as 18, 02L, etc... Unique for each aiport.
+<li>rwy_num: String (3.0). Code for the runway, such as 18, 02L, etc... Unique for each airport.
 <li>width_m: Real (3.0). Width in meters.
 <li>surface: String (0.0). Type of the <a name="surface">surface</a> among :
     <ul>
@@ -134,7 +138,7 @@ Fields:
         <li>None
         <li>Asphalt
         <li>Concrete
-    </ul> 
+    </ul>
 <li>smoothness: Real (4.2). Runway  <a name="smoothness">smoothness</a>. Percentage between 0.00 and 1.00. 0.25 is the default value.
 <li>centerline_lights: Integer (1.0). Set to 1 if the runway has centre-line lights
 <li>edge_lighting: String (0.0). Type of edge lighting among :
@@ -179,7 +183,7 @@ Fields:
 <li>REIL: String (0.0). Runway End Identifier Lights (REIL) among :
     <ul>
         <li>None
-        <li>Omni-directional 
+        <li>Omni-directional
         <li>Unidirectionnal
     </ul>
 <li>length_m: Real (5.0). (Computed field). Length in meters between the 2 thresholds at both ends of the runway. The displaced thresholds are not taken into account in this computation.
@@ -214,7 +218,7 @@ Fields:
 Fields:
 <ul>
 <li>apt_icao: String (5.0)
-<li>rwy_num: String (3.0). Code for the runway, such as 18. Unique for each aiport.
+<li>rwy_num: String (3.0). Code for the runway, such as 18. Unique for each airport.
 <li>width_m: Real (3.0)
 <li>has_buoys: Integer (1.0). Set to 1 if the runway should be marked with buoys bobbing in the water
 <li>length_m: Real (5.0). (Computed field) Length between the two ends of the water runway.
@@ -261,7 +265,7 @@ This layer contains the center of a helipad.
 Fields:
 <ul>
 <li>apt_icao: String (5.0)
-<li>helipad_name: String (5.0). Name of the helipad in the format "Hxx". Unique for each aiport.
+<li>helipad_name: String (5.0). Name of the helipad in the format "Hxx". Unique for each airport.
 <li>true_heading_deg: Real (6.2)
 <li>length_m: Real (5.0)
 <li>width_m: Real (3.0)
@@ -315,7 +319,7 @@ Fields:
 
 <h3><a name="APTBoundary">APTBoundary</a> (Polygon)</h3>
 
-This layer contains the boundary of the aiport. There is at the maximum one such feature per aiport.
+This layer contains the boundary of the airport. There is at the maximum one such feature per airport.
 The polygon may include holes. Bezier curves are discretized into linear pieces.<p>
 
 Fields:
@@ -418,7 +422,7 @@ Fields:
 <li>atc_type: String (4.0). Type of the frequency among (derived from the record type number) :
     <ul>
         <li>ATIS : AWOS (Automatic Weather Observation System), ASOS (Automatic Surface Observation System) or ATIS (Automated Terminal Information System)
-        <li>CTAF : Unicom or CTAF (USA), radio (UK) 
+        <li>CTAF : Unicom or CTAF (USA), radio (UK)
         <li>CLD  : Clearance delivery (CLD)
         <li>GND  : Ground
         <li>TWR  : Tower
@@ -448,7 +452,7 @@ The following layers are reported :<p>
 
 <h3><a name="ILS">ILS</a> (Point)</h3>
 
-Localiser that is part of a full ILS, or Stand-alone localiser (LOC), also including a LDA (Landing Directional Aid) or SDF (Simplified Directional Facility).<p>
+Localizer that is part of a full ILS, or Stand-alone localizer (LOC), also including a LDA (Landing Directional Aid) or SDF (Simplified Directional Facility).<p>
 
 Fields :
 <ul>
@@ -469,7 +473,7 @@ Fields :
 <li>elevation_m: Real (8.2). Elevation of nav-aid in meters.
 <li>freq_mhz: Real (7.3). Frequency of nav-aid in MHz.
 <li>range_km: Real (7.3). Range of nav-aid in km.
-<li>true_heading_deg: Real (6.2). True heading of the localiser in degree.
+<li>true_heading_deg: Real (6.2). True heading of the localizer in degree.
 </ul>
 
 <h3><a name="VOR">VOR</a> (Point)</h3>
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane.h b/ogr/ogrsf_frmts/xplane/ogr_xplane.h
index 8d74a35..517af57 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane.h
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane.h
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_XPLANE_H_INCLUDED
-#define _OGR_XPLANE_H_INCLUDED
+#ifndef OGR_XPLANE_H_INCLUDED
+#define OGR_XPLANE_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 
@@ -46,10 +46,10 @@ class OGRXPlaneLayer : public OGRLayer
     int                nFeatureArraySize;
     int                nFeatureArrayMaxSize;
     int                nFeatureArrayIndex;
-    
+
     OGRFeature**       papoFeatures;
     OGRSpatialReference *poSRS;
-    
+
     OGRXPlaneDataSource* poDS;
 
   protected:
@@ -61,7 +61,7 @@ class OGRXPlaneLayer : public OGRLayer
 
   public:
     virtual                   ~OGRXPlaneLayer();
-    
+
     void                      SetDataSource(OGRXPlaneDataSource* poDS);
 
     void                      SetReader(OGRXPlaneReader* poReader);
@@ -109,7 +109,7 @@ class OGRXPlaneDataSource : public OGRDataSource
     virtual const char* GetName() { return pszName; }
 
     virtual int         TestCapability( const char * pszCap );
-    
+
     void                ReadWholeFileIfNecessary();
 };
 
@@ -128,4 +128,4 @@ class OGRXPlaneDriver : public OGRSFDriver
 };
 
 
-#endif /* ndef _OGR_XPLANE_H_INCLUDED */
+#endif /* ndef OGR_XPLANE_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.cpp b/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.cpp
index 1f52934..ffb55ab 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.cpp
@@ -30,13 +30,14 @@
 #include "ogr_xplane_apt_reader.h"
 #include "ogr_xplane_geo_utils.h"
 
-CPL_CVSID("$Id: ogr_xplane_apt_reader.cpp 29366 2015-06-16 17:17:49Z rouault $");
+CPL_CVSID("$Id: ogr_xplane_apt_reader.cpp 32430 2015-12-22 13:56:42Z goatbar $");
 
 /************************************************************************/
 /*                   OGRXPlaneCreateAptFileReader                       */
 /************************************************************************/
 
-OGRXPlaneReader* OGRXPlaneCreateAptFileReader( OGRXPlaneDataSource* poDataSource )
+OGRXPlaneReader* OGRXPlaneCreateAptFileReader(
+    OGRXPlaneDataSource* poDataSource )
 {
     OGRXPlaneReader* poReader = new OGRXPlaneAptReader(poDataSource);
     return poReader;
@@ -45,31 +46,31 @@ OGRXPlaneReader* OGRXPlaneCreateAptFileReader( OGRXPlaneDataSource* poDataSource
 /************************************************************************/
 /*                         OGRXPlaneAptReader()                         */
 /************************************************************************/
-OGRXPlaneAptReader::OGRXPlaneAptReader()
-{
-    poDataSource = NULL;
-    nVersion = APT_V_UNKNOWN;
-
-    poAPTLayer = NULL;
-    poRunwayLayer = NULL;
-    poRunwayThresholdLayer = NULL;
-    poStopwayLayer = NULL;
-    poWaterRunwayLayer = NULL;
-    poWaterRunwayThresholdLayer = NULL;
-    poHelipadLayer = NULL;
-    poHelipadPolygonLayer = NULL;
-    poTaxiwayRectangleLayer =NULL;
-    poPavementLayer = NULL;
-    poAPTBoundaryLayer = NULL;
-    poAPTLinearFeatureLayer = NULL;
-    poATCFreqLayer = NULL;
-    poStartupLocationLayer = NULL;
-    poAPTLightBeaconLayer = NULL;
-    poAPTWindsockLayer = NULL;
-    poTaxiwaySignLayer = NULL;
-    poVASI_PAPI_WIGWAG_Layer = NULL;
-    poTaxiLocationLayer = NULL;
-    
+OGRXPlaneAptReader::OGRXPlaneAptReader() :
+    poDataSource(NULL),
+    poAPTLayer(NULL),
+    poRunwayLayer(NULL),
+    poStopwayLayer(NULL),
+    poRunwayThresholdLayer(NULL),
+    poWaterRunwayLayer(NULL),
+    poWaterRunwayThresholdLayer(NULL),
+    poHelipadLayer(NULL),
+    poHelipadPolygonLayer(NULL),
+    poTaxiwayRectangleLayer(NULL),
+    poPavementLayer(NULL),
+    poAPTBoundaryLayer(NULL),
+    poAPTLinearFeatureLayer(NULL),
+    poATCFreqLayer(NULL),
+    poStartupLocationLayer(NULL),
+    poAPTLightBeaconLayer(NULL),
+    poAPTWindsockLayer(NULL),
+    poTaxiwaySignLayer(NULL),
+    poVASI_PAPI_WIGWAG_Layer(NULL),
+    poTaxiLocationLayer(NULL),
+    nVersion(APT_V_UNKNOWN),
+    dfElevation(0.0),
+    bControlTower(false)
+{
     Rewind();
 }
 
@@ -77,31 +78,31 @@ OGRXPlaneAptReader::OGRXPlaneAptReader()
 /*                         OGRXPlaneAptReader()                         */
 /************************************************************************/
 
-OGRXPlaneAptReader::OGRXPlaneAptReader( OGRXPlaneDataSource* poDataSourceIn )
-{
-    poDataSource = poDataSourceIn;
-    nVersion = APT_V_UNKNOWN;
-
-    poAPTLayer = new OGRXPlaneAPTLayer();
-    poRunwayLayer = new OGRXPlaneRunwayLayer();
-    poRunwayThresholdLayer = new OGRXPlaneRunwayThresholdLayer();
-    poStopwayLayer = new OGRXPlaneStopwayLayer();
-    poWaterRunwayLayer = new OGRXPlaneWaterRunwayLayer();
-    poWaterRunwayThresholdLayer = new OGRXPlaneWaterRunwayThresholdLayer();
-    poHelipadLayer = new OGRXPlaneHelipadLayer();
-    poHelipadPolygonLayer = new OGRXPlaneHelipadPolygonLayer();
-    poTaxiwayRectangleLayer = new OGRXPlaneTaxiwayRectangleLayer();
-    poPavementLayer = new OGRXPlanePavementLayer();
-    poAPTBoundaryLayer = new OGRXPlaneAPTBoundaryLayer();
-    poAPTLinearFeatureLayer = new OGRXPlaneAPTLinearFeatureLayer();
-    poATCFreqLayer = new OGRXPlaneATCFreqLayer();
-    poStartupLocationLayer = new OGRXPlaneStartupLocationLayer();
-    poAPTLightBeaconLayer = new OGRXPlaneAPTLightBeaconLayer();
-    poAPTWindsockLayer = new OGRXPlaneAPTWindsockLayer();
-    poTaxiwaySignLayer = new OGRXPlaneTaxiwaySignLayer();
-    poVASI_PAPI_WIGWAG_Layer = new OGRXPlane_VASI_PAPI_WIGWAG_Layer();
-    poTaxiLocationLayer = NULL;
-
+OGRXPlaneAptReader::OGRXPlaneAptReader( OGRXPlaneDataSource* poDataSourceIn ) :
+    poDataSource(poDataSourceIn),
+    poAPTLayer(new OGRXPlaneAPTLayer()),
+    poRunwayLayer(new OGRXPlaneRunwayLayer()),
+    poStopwayLayer(new OGRXPlaneStopwayLayer()),
+    poRunwayThresholdLayer(new OGRXPlaneRunwayThresholdLayer()),
+    poWaterRunwayLayer(new OGRXPlaneWaterRunwayLayer()),
+    poWaterRunwayThresholdLayer(new OGRXPlaneWaterRunwayThresholdLayer()),
+    poHelipadLayer(new OGRXPlaneHelipadLayer()),
+    poHelipadPolygonLayer(new OGRXPlaneHelipadPolygonLayer()),
+    poTaxiwayRectangleLayer(new OGRXPlaneTaxiwayRectangleLayer()),
+    poPavementLayer(new OGRXPlanePavementLayer()),
+    poAPTBoundaryLayer(new OGRXPlaneAPTBoundaryLayer()),
+    poAPTLinearFeatureLayer(new OGRXPlaneAPTLinearFeatureLayer()),
+    poATCFreqLayer(new OGRXPlaneATCFreqLayer()),
+    poStartupLocationLayer(new OGRXPlaneStartupLocationLayer()),
+    poAPTLightBeaconLayer(new OGRXPlaneAPTLightBeaconLayer()),
+    poAPTWindsockLayer(new OGRXPlaneAPTWindsockLayer()),
+    poTaxiwaySignLayer(new OGRXPlaneTaxiwaySignLayer()),
+    poVASI_PAPI_WIGWAG_Layer(new OGRXPlane_VASI_PAPI_WIGWAG_Layer()),
+    poTaxiLocationLayer(NULL),
+    nVersion(APT_V_UNKNOWN),
+    dfElevation(0.0),
+    bControlTower(false)
+{
     poDataSource->RegisterLayer(poAPTLayer);
     poDataSource->RegisterLayer(poRunwayLayer);
     poDataSource->RegisterLayer(poRunwayThresholdLayer);
@@ -120,7 +121,7 @@ OGRXPlaneAptReader::OGRXPlaneAptReader( OGRXPlaneDataSource* poDataSourceIn )
     poDataSource->RegisterLayer(poAPTWindsockLayer);
     poDataSource->RegisterLayer(poTaxiwaySignLayer);
     poDataSource->RegisterLayer(poVASI_PAPI_WIGWAG_Layer);
-    
+
     Rewind();
 }
 
@@ -168,17 +169,17 @@ OGRXPlaneReader* OGRXPlaneAptReader::CloneForLayer(OGRXPlaneLayer* poLayer)
 
 void OGRXPlaneAptReader::Rewind()
 {
-    bAptHeaderFound = FALSE;
-    bTowerFound = FALSE;
+    bAptHeaderFound = false;
+    bTowerFound = false;
     dfLatTower = 0;
     dfLonTower = 0;
     dfHeightTower = 0;
-    bRunwayFound = FALSE;
+    bRunwayFound = false;
     dfLatFirstRwy = 0;
     dfLonFirstRwy = 0;
     nAPTType = -1;
 
-    bResumeLine = FALSE;
+    bResumeLine = false;
 
     OGRXPlaneReader::Rewind();
 }
@@ -190,11 +191,11 @@ void OGRXPlaneAptReader::Rewind()
 
 int OGRXPlaneAptReader::IsRecognizedVersion( const char* pszVersionString)
 {
-    if (EQUALN(pszVersionString, "810 Version", 11))
+    if (STARTS_WITH_CI(pszVersionString, "810 Version"))
         nVersion = APT_V_810;
-    else if (EQUALN(pszVersionString, "850 Version", 11))
+    else if (STARTS_WITH_CI(pszVersionString, "850 Version"))
         nVersion = APT_V_850;
-    else if (EQUALN(pszVersionString, "1000 Version", 12))
+    else if (STARTS_WITH_CI(pszVersionString, "1000 Version"))
         nVersion = APT_V_1000;
     else
         nVersion = APT_V_UNKNOWN;
@@ -217,42 +218,42 @@ int OGRXPlaneAptReader::IsRecognizedVersion( const char* pszVersionString)
 
 void OGRXPlaneAptReader::Read()
 {
-    const char* pszLine = NULL;
-
     if (!bResumeLine)
     {
         CPLAssert(papszTokens == NULL);
     }
 
+    const char* pszLine = NULL;
+
     while(bResumeLine || (pszLine = CPLReadLineL(fp)) != NULL)
     {
-        int nType;
         if (!bResumeLine)
         {
             papszTokens = CSLTokenizeString(pszLine);
             nTokens = CSLCount(papszTokens);
             nLineNumber ++;
-            bResumeLine = FALSE;
+            bResumeLine = false;
         }
 
         do
         {
-            bResumeLine = FALSE;
+            bResumeLine = false;
 
             if (nTokens == 1 && strcmp(papszTokens[0], "99") == 0)
             {
                 CSLDestroy(papszTokens);
                 papszTokens = NULL;
-                bEOF = TRUE;
+                bEOF = true;
                 if (bAptHeaderFound)
                 {
                     if (poAPTLayer)
                     {
-                        poAPTLayer->AddFeature(osAptICAO, osAptName, nAPTType, dfElevation,
-                                            bTowerFound || bRunwayFound,
-                                            (bTowerFound) ? dfLatTower : dfLatFirstRwy,
-                                            (bTowerFound) ? dfLonTower : dfLonFirstRwy, 
-                                            bTowerFound, dfHeightTower, osTowerName);
+                        poAPTLayer->AddFeature(
+                            osAptICAO, osAptName, nAPTType, dfElevation,
+                            bTowerFound || bRunwayFound,
+                            (bTowerFound) ? dfLatTower : dfLatFirstRwy,
+                            (bTowerFound) ? dfLonTower : dfLonFirstRwy,
+                            bTowerFound, dfHeightTower, osTowerName);
                     }
                 }
                 return;
@@ -262,7 +263,7 @@ void OGRXPlaneAptReader::Read()
                 break;
             }
 
-            nType = atoi(papszTokens[0]);
+            const int nType = atoi(papszTokens[0]);
             switch(nType)
             {
                 case APT_AIRPORT_HEADER:
@@ -270,14 +271,15 @@ void OGRXPlaneAptReader::Read()
                 case APT_HELIPORT_HEADER:
                     if (bAptHeaderFound)
                     {
-                        bAptHeaderFound = FALSE;
+                        bAptHeaderFound = false;
                         if (poAPTLayer)
                         {
-                            poAPTLayer->AddFeature(osAptICAO, osAptName, nAPTType, dfElevation,
-                                                    bTowerFound || bRunwayFound,
-                                                    (bTowerFound) ? dfLatTower : dfLatFirstRwy,
-                                                    (bTowerFound) ? dfLonTower : dfLonFirstRwy, 
-                                                    bTowerFound, dfHeightTower, osTowerName);
+                            poAPTLayer->AddFeature(
+                                osAptICAO, osAptName, nAPTType, dfElevation,
+                                bTowerFound || bRunwayFound,
+                                (bTowerFound) ? dfLatTower : dfLatFirstRwy,
+                                (bTowerFound) ? dfLonTower : dfLonFirstRwy,
+                                bTowerFound, dfHeightTower, osTowerName);
                         }
                     }
                     ParseAptHeaderRecord();
@@ -338,7 +340,8 @@ void OGRXPlaneAptReader::Read()
                     break;
 
                 case APT_RUNWAY:
-                    if (poAPTLayer || poRunwayLayer || poRunwayThresholdLayer || poStopwayLayer)
+                    if (poAPTLayer || poRunwayLayer || poRunwayThresholdLayer
+                        || poStopwayLayer)
                         ParseRunwayRecord();
                     break;
 
@@ -373,7 +376,8 @@ void OGRXPlaneAptReader::Read()
                     break;
 
                 default:
-                    CPLDebug("XPLANE", "Line %d, Unknown code : %d", nLineNumber, nType);
+                    CPLDebug( "XPLANE", "Line %d, Unknown code : %d",
+                              nLineNumber, nType);
                     break;
             }
         } while(bResumeLine);
@@ -385,7 +389,7 @@ void OGRXPlaneAptReader::Read()
             return;
     }
 
-    bEOF = TRUE;
+    bEOF = true;
 }
 
 
@@ -395,20 +399,21 @@ void OGRXPlaneAptReader::Read()
 
 void    OGRXPlaneAptReader::ParseAptHeaderRecord()
 {
-    bAptHeaderFound = FALSE;
-    bTowerFound = FALSE;
-    bRunwayFound = FALSE;
+    bAptHeaderFound = false;
+    bTowerFound = false;
+    bRunwayFound = false;
 
     RET_IF_FAIL(assertMinCol(6));
 
     /* feet to meter */
-    RET_IF_FAIL(readDoubleWithBoundsAndConversion(&dfElevation, 1, "elevation", FEET_TO_METER, -1000., 10000.));
+    RET_IF_FAIL(readDoubleWithBoundsAndConversion(
+        &dfElevation, 1, "elevation", FEET_TO_METER, -1000., 10000.));
     bControlTower = atoi(papszTokens[2]);
     // papszTokens[3] ignored
     osAptICAO = papszTokens[4];
     osAptName = readStringUntilEnd(5);
 
-    bAptHeaderFound = TRUE;
+    bAptHeaderFound = true;
 }
 
 /************************************************************************/
@@ -417,31 +422,36 @@ void    OGRXPlaneAptReader::ParseAptHeaderRecord()
 
 void    OGRXPlaneAptReader::ParseRunwayTaxiwayV810Record()
 {
-    double dfLat, dfLon, dfTrueHeading, dfLength, dfWidth;
-    double adfDisplacedThresholdLength[2];
-    double adfStopwayLength[2];
-    const char* pszRwyNum;
-    int /*aeVisualApproachLightingCode[2], */ aeRunwayLightingCode[2], aeApproachLightingCode[2];
-    int eSurfaceCode, eShoulderCode, eMarkings;
-    double dfSmoothness;
-    double adfVisualGlidePathAngle[2];
-    int bHasDistanceRemainingSigns;
+    // int aeVisualApproachLightingCode[2];
 
     RET_IF_FAIL(assertMinCol(15));
 
+    double dfLat;
+    double dfLon;
     RET_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
-    pszRwyNum = papszTokens[3];
+    const char* pszRwyNum = papszTokens[3];
+    double dfTrueHeading;
     RET_IF_FAIL(readTrueHeading(&dfTrueHeading, 4));
+    double dfLength;
     RET_IF_FAIL(readDouble(&dfLength, 5, "length"));
     dfLength *= FEET_TO_METER;
+    double adfDisplacedThresholdLength[2];
     adfDisplacedThresholdLength[0] = atoi(papszTokens[6]) * FEET_TO_METER;
     if (strchr(papszTokens[6], '.') != NULL)
         adfDisplacedThresholdLength[1] = atoi(strchr(papszTokens[6], '.') + 1) * FEET_TO_METER;
+    else
+        adfDisplacedThresholdLength[1] = 0;
+    double adfStopwayLength[2];
     adfStopwayLength[0] = atoi(papszTokens[7]) * FEET_TO_METER;
     if (strchr(papszTokens[7], '.') != NULL)
         adfStopwayLength[1] = atoi(strchr(papszTokens[7], '.') + 1) * FEET_TO_METER;
+    else
+        adfStopwayLength[1] = 0;
+    double dfWidth;
     RET_IF_FAIL(readDouble(&dfWidth, 8, "width"));
     dfWidth *= FEET_TO_METER;
+    int aeRunwayLightingCode[2];
+    int aeApproachLightingCode[2];
     if (strlen(papszTokens[9]) == 6)
     {
         /*aeVisualApproachLightingCode[0] = papszTokens[9][0] - '0'; */
@@ -458,11 +468,13 @@ void    OGRXPlaneAptReader::ParseRunwayTaxiwayV810Record()
         aeRunwayLightingCode[1] = 0;
         aeApproachLightingCode[1] = 0;
     }
-    eSurfaceCode = atoi(papszTokens[10]);
-    eShoulderCode = atoi(papszTokens[11]);
-    eMarkings = atoi(papszTokens[12]);
+    const int eSurfaceCode = atoi(papszTokens[10]);
+    const int eShoulderCode = atoi(papszTokens[11]);
+    const int eMarkings = atoi(papszTokens[12]);
+    double dfSmoothness;
     RET_IF_FAIL(readDoubleWithBounds(&dfSmoothness, 13, "runway smoothness", 0., 1.));
-    bHasDistanceRemainingSigns = atoi(papszTokens[14]);
+    bool bHasDistanceRemainingSigns = CPL_TO_BOOL(atoi(papszTokens[14]));
+    double adfVisualGlidePathAngle[2];
     if (nTokens == 16)
     {
         adfVisualGlidePathAngle[0] = atoi(papszTokens[15]) / 100.;
@@ -489,13 +501,10 @@ void    OGRXPlaneAptReader::ParseRunwayTaxiwayV810Record()
     else if (pszRwyNum[0] >= '0' && pszRwyNum[0] <= '9' && strlen(pszRwyNum) >= 2)
     {
         /* Runway */
-        double adfLat[2], adfLon[2];
         CPLString aosRwyNum[2];
-        OGRFeature* poFeature;
-        int abReil[2];
 
-        int num1 = atoi(pszRwyNum);
-        int num2 = (num1 > 18) ? num1 - 18 : num1 + 18;
+        const int num1 = atoi(pszRwyNum);
+        const int num2 = (num1 > 18) ? num1 - 18 : num1 + 18;
         if (pszRwyNum[2] == '0' || pszRwyNum[2] == 'x')
         {
             aosRwyNum[0].Printf("%02d", num1);
@@ -509,35 +518,39 @@ void    OGRXPlaneAptReader::ParseRunwayTaxiwayV810Record()
                                 (aosRwyNum[0][2] == 'R') ? 'L' : aosRwyNum[0][2]);
         }
 
-        OGRXPlane_ExtendPosition(dfLat, dfLon, dfLength / 2, dfTrueHeading + 180, &adfLat[0], &adfLon[0]);
-        OGRXPlane_ExtendPosition(dfLat, dfLon, dfLength / 2, dfTrueHeading, &adfLat[1], &adfLon[1]);
+        double adfLat[2];
+        double adfLon[2];
+        OGRXPlane_ExtendPosition(dfLat, dfLon, dfLength / 2,
+                                 dfTrueHeading + 180, &adfLat[0], &adfLon[0]);
+        OGRXPlane_ExtendPosition(dfLat, dfLon, dfLength / 2,
+                                 dfTrueHeading, &adfLat[1], &adfLon[1]);
 
+        int abReil[2];
         for(int i=0;i<2;i++)
-            abReil[i] = (aeRunwayLightingCode[i] >= 3 && aeRunwayLightingCode[i] <= 5) ;
+            abReil[i] = ( aeRunwayLightingCode[i] >= 3
+                          && aeRunwayLightingCode[i] <= 5 );
 
         if (!bRunwayFound)
         {
             dfLatFirstRwy = adfLat[0];
             dfLonFirstRwy = adfLon[0];
-            bRunwayFound = TRUE;
+            bRunwayFound = true;
         }
-        
+
         if (nAPTType == APT_SEAPLANE_HEADER || eSurfaceCode == 13)
         {
             /* Special case for water-runways. No special record in V8.10 */
             OGRFeature* apoWaterRunwayThreshold[2] = {NULL, NULL};
-            int bBuoys;
-            int i;
+            bool bBuoys = true;
 
-            bBuoys = TRUE;
-
-            for(i=0;i<2;i++)
+            for( int i=0; i < 2; i++ )
             {
                 if (poWaterRunwayThresholdLayer)
                 {
                     apoWaterRunwayThreshold[i] =
-                        poWaterRunwayThresholdLayer->AddFeature  
-                            (osAptICAO, aosRwyNum[i], adfLat[i], adfLon[i], dfWidth, bBuoys);
+                        poWaterRunwayThresholdLayer->AddFeature
+                            ( osAptICAO, aosRwyNum[i], adfLat[i], adfLon[i],
+                              dfWidth, bBuoys );
                 }
 
             }
@@ -563,9 +576,9 @@ void    OGRXPlaneAptReader::ParseRunwayTaxiwayV810Record()
             {
                 for(int i=0;i<2;i++)
                 {
-                    poFeature =
-                        poRunwayThresholdLayer->AddFeature  
-                            (osAptICAO, aosRwyNum[i],
+                    OGRFeature* poFeature
+                        = poRunwayThresholdLayer->AddFeature(
+                            osAptICAO, aosRwyNum[i],
                             adfLat[i], adfLon[i], dfWidth,
                             RunwaySurfaceEnumeration.GetText(eSurfaceCode),
                             RunwayShoulderEnumeration.GetText(eShoulderCode),
@@ -577,7 +590,7 @@ void    OGRXPlaneAptReader::ParseRunwayTaxiwayV810Record()
                             RunwayMarkingEnumeration.GetText(eMarkings),
                             RunwayApproachLightingEnumerationV810.GetText(aeApproachLightingCode[i]),
                             (aeRunwayLightingCode[i] == 5) /* bHasTouchdownLights */,
-                            (abReil[i] && abReil[i]) ? "Omni-directional" :
+                            (abReil[i] && abReil[1-i]) ? "Omni-directional" :
                             (abReil[i] && !abReil[1-i]) ? "Unidirectional" : "None" /* eReil */);
                     poRunwayThresholdLayer->SetRunwayLengthAndHeading(poFeature, dfLength,
                             (i == 0) ? dfTrueHeading : (dfTrueHeading < 180) ? dfTrueHeading + 180 : dfTrueHeading - 180);
@@ -598,7 +611,7 @@ void    OGRXPlaneAptReader::ParseRunwayTaxiwayV810Record()
                                         (aeRunwayLightingCode[0] >= 2 && aeRunwayLightingCode[0] <= 5) ? "Yes" : "None" /* pszEdgeLighting */,
                                         bHasDistanceRemainingSigns);
             }
-            
+
             if (poStopwayLayer)
             {
                 for(int i=0;i<2;i++)
@@ -638,9 +651,9 @@ void    OGRXPlaneAptReader::ParseRunwayTaxiwayV810Record()
         {
             dfLatFirstRwy = dfLat;
             dfLonFirstRwy = dfLon;
-            bRunwayFound = TRUE;
+            bRunwayFound = true;
         }
-        
+
         if (poHelipadLayer)
         {
             poHelipadLayer->AddFeature(osAptICAO, osHelipadName, dfLat, dfLon,
@@ -677,75 +690,75 @@ void    OGRXPlaneAptReader::ParseRunwayTaxiwayV810Record()
 
 void OGRXPlaneAptReader::ParseRunwayRecord()
 {
+    RET_IF_FAIL(assertMinCol(8 + 9 + 9));
+
     double dfWidth;
-    int eSurfaceCode, eShoulderCode;
+    RET_IF_FAIL(readDouble(&dfWidth, 1, "runway width"));
+
+    const int eSurfaceCode = atoi(papszTokens[2]);
+    const int eShoulderCode = atoi(papszTokens[3]);
     double dfSmoothness;
-    int bHasCenterLineLights, bHasDistanceRemainingSigns;
-    int eEdgeLighting;
-    int nCurToken;
-    int nRwy = 0;
-    double adfLat[2], adfLon[2];
-    OGRFeature* apoRunwayThreshold[2] = { NULL, NULL };
-    double dfLength;
+    RET_IF_FAIL(readDoubleWithBounds(&dfSmoothness, 4, "runway smoothness", 0., 1.));
+
+    const bool bHasCenterLineLights = CPL_TO_BOOL(atoi(papszTokens[5]));
+    const int eEdgeLighting = atoi(papszTokens[6]);
+    const bool bHasDistanceRemainingSigns = CPL_TO_BOOL(atoi(papszTokens[7]));
+    double adfLat[2];
+    double adfLon[2];
     CPLString aosRunwayId[2];
     double adfDisplacedThresholdLength[2];
     double adfStopwayLength[2];
 
-    RET_IF_FAIL(assertMinCol(8 + 9 + 9));
-
-    RET_IF_FAIL(readDouble(&dfWidth, 1, "runway width"));
-    eSurfaceCode = atoi(papszTokens[2]);
-    eShoulderCode = atoi(papszTokens[3]);
-    RET_IF_FAIL(readDoubleWithBounds(&dfSmoothness, 4, "runway smoothness", 0., 1.));
-    bHasCenterLineLights = atoi(papszTokens[5]);
-    eEdgeLighting = atoi(papszTokens[6]);
-    bHasDistanceRemainingSigns = atoi(papszTokens[7]);
-
-    for( nRwy=0, nCurToken = 8 ; nRwy<=1 ; nRwy++, nCurToken += 9 )
+    for( int nRwy=0; nRwy<=1 ; nRwy++ )
     {
-        double dfLat, dfLon;
-        int eMarkings, eApproachLightingCode, eREIL;
-        int bHasTouchdownLights;
-
-        aosRunwayId[nRwy] = papszTokens[nCurToken + 0]; /* for example : 08, 24R, or xxx */
-        RET_IF_FAIL(readLatLon(&dfLat, &dfLon, nCurToken + 1));
-        adfLat[nRwy] = dfLat; 
+        aosRunwayId[nRwy] = papszTokens[8 + 9*nRwy + 0]; /* for example : 08, 24R, or xxx */
+        double dfLat;
+        double dfLon;
+        RET_IF_FAIL(readLatLon(&dfLat, &dfLon, 8 + 9*nRwy + 1));
+        adfLat[nRwy] = dfLat;
         adfLon[nRwy] = dfLon;
-        RET_IF_FAIL(readDouble(&adfDisplacedThresholdLength[nRwy], nCurToken + 3, "displaced threshold length"));
-        RET_IF_FAIL(readDouble(&adfStopwayLength[nRwy], nCurToken + 4, "stopway/blastpad/over-run length"));
-        eMarkings = atoi(papszTokens[nCurToken + 5]);
-        eApproachLightingCode = atoi(papszTokens[nCurToken + 6]);
-        bHasTouchdownLights = atoi(papszTokens[nCurToken + 7]);
-        eREIL = atoi(papszTokens[nCurToken + 8]);
+        RET_IF_FAIL( readDouble( &adfDisplacedThresholdLength[nRwy],
+                                 8 + 9*nRwy + 3,
+                                 "displaced threshold length" ) );
+        RET_IF_FAIL( readDouble( &adfStopwayLength[nRwy],
+                                 8 + 9*nRwy + 4,
+                                 "stopway/blastpad/over-run length" ) );
 
         if (!bRunwayFound)
         {
             dfLatFirstRwy = dfLat;
             dfLonFirstRwy = dfLon;
-            bRunwayFound = TRUE;
-        }
-
-        if (poRunwayThresholdLayer)
-        {
-            apoRunwayThreshold[nRwy] =
-                poRunwayThresholdLayer->AddFeature  
-                    (osAptICAO, aosRunwayId[nRwy],
-                    dfLat, dfLon, dfWidth,
-                    RunwaySurfaceEnumeration.GetText(eSurfaceCode),
-                    RunwayShoulderEnumeration.GetText(eShoulderCode),
-                    dfSmoothness, bHasCenterLineLights,
-                    RunwayEdgeLightingEnumeration.GetText(eEdgeLighting), bHasDistanceRemainingSigns,
-                    adfDisplacedThresholdLength[nRwy], adfStopwayLength[nRwy],
-                    RunwayMarkingEnumeration.GetText(eMarkings),
-                    RunwayApproachLightingEnumeration.GetText(eApproachLightingCode),
-                    bHasTouchdownLights,
-                    RunwayREILEnumeration.GetText(eREIL));
+            bRunwayFound = true;
         }
     }
 
-    dfLength = OGRXPlane_Distance(adfLat[0], adfLon[0], adfLat[1], adfLon[1]);
+    const double dfLength
+        = OGRXPlane_Distance(adfLat[0], adfLon[0], adfLat[1], adfLon[1]);
     if (poRunwayThresholdLayer)
     {
+        OGRFeature* apoRunwayThreshold[2] = { NULL, NULL };
+        for( int nRwy=0; nRwy<=1 ; nRwy++ )
+        {
+            const int eMarkings = atoi(papszTokens[8 + 9*nRwy + 5]);
+            const int eApproachLightingCode = atoi(papszTokens[8 + 9*nRwy + 6]);
+            const bool bHasTouchdownLights = CPL_TO_BOOL(atoi(papszTokens[8 + 9*nRwy + 7]));
+            const int eREIL = atoi(papszTokens[8 + 9*nRwy + 8]);
+
+            apoRunwayThreshold[nRwy] =
+                poRunwayThresholdLayer->AddFeature
+                    ( osAptICAO, aosRunwayId[nRwy],
+                      adfLat[nRwy], adfLon[nRwy], dfWidth,
+                      RunwaySurfaceEnumeration.GetText(eSurfaceCode),
+                      RunwayShoulderEnumeration.GetText(eShoulderCode),
+                      dfSmoothness, bHasCenterLineLights,
+                      RunwayEdgeLightingEnumeration.GetText(eEdgeLighting),
+                      bHasDistanceRemainingSigns,
+                      adfDisplacedThresholdLength[nRwy], adfStopwayLength[nRwy],
+                      RunwayMarkingEnumeration.GetText(eMarkings),
+                      RunwayApproachLightingEnumeration.GetText(eApproachLightingCode),
+                      bHasTouchdownLights,
+                      RunwayREILEnumeration.GetText(eREIL) );
+        }
         poRunwayThresholdLayer->SetRunwayLengthAndHeading(apoRunwayThreshold[0], dfLength,
                                     OGRXPlane_Track(adfLat[0], adfLon[0], adfLat[1], adfLon[1]));
         poRunwayThresholdLayer->SetRunwayLengthAndHeading(apoRunwayThreshold[1], dfLength,
@@ -767,7 +780,7 @@ void OGRXPlaneAptReader::ParseRunwayRecord()
                                     RunwayEdgeLightingEnumeration.GetText(eEdgeLighting),
                                     bHasDistanceRemainingSigns);
     }
-            
+
     if (poStopwayLayer)
     {
         for(int i=0;i<2;i++)
@@ -789,36 +802,35 @@ void OGRXPlaneAptReader::ParseRunwayRecord()
 
 void OGRXPlaneAptReader::ParseWaterRunwayRecord()
 {
-    double adfLat[2], adfLon[2];
-    OGRFeature* apoWaterRunwayThreshold[2] = {NULL, NULL};
-    double dfWidth, dfLength;
-    int bBuoys;
-    CPLString aosRunwayId[2];
-    int i;
-
     RET_IF_FAIL(assertMinCol(9));
 
+    double dfWidth;
     RET_IF_FAIL(readDouble(&dfWidth, 1, "runway width"));
-    bBuoys = atoi(papszTokens[2]);
 
-    for(i=0;i<2;i++)
+    bool bBuoys = CPL_TO_BOOL(atoi(papszTokens[2]));
+    double adfLat[2];
+    double adfLon[2];
+    CPLString aosRunwayId[2];
+
+    for( int i=0; i < 2; i++ )
     {
         aosRunwayId[i] = papszTokens[3 + 3*i];
         RET_IF_FAIL(readLatLon(&adfLat[i], &adfLon[i], 4 + 3*i));
-
-        if (poWaterRunwayThresholdLayer)
-        {
-            apoWaterRunwayThreshold[i] =
-                poWaterRunwayThresholdLayer->AddFeature  
-                    (osAptICAO, aosRunwayId[i], adfLat[i], adfLon[i], dfWidth, bBuoys);
-        }
-
     }
 
-    dfLength = OGRXPlane_Distance(adfLat[0], adfLon[0], adfLat[1], adfLon[1]);
+    const double dfLength
+        = OGRXPlane_Distance(adfLat[0], adfLon[0], adfLat[1], adfLon[1]);
 
     if (poWaterRunwayThresholdLayer)
     {
+        OGRFeature* apoWaterRunwayThreshold[2] = {NULL, NULL};
+        for( int i=0; i < 2; i++ )
+        {
+            apoWaterRunwayThreshold[i] =
+                poWaterRunwayThresholdLayer->AddFeature
+                    ( osAptICAO, aosRunwayId[i], adfLat[i], adfLon[i], dfWidth,
+                      bBuoys );
+        }
         poWaterRunwayThresholdLayer->SetRunwayLengthAndHeading(apoWaterRunwayThreshold[0], dfLength,
                                     OGRXPlane_Track(adfLat[0], adfLon[0], adfLat[1], adfLon[1]));
         poWaterRunwayThresholdLayer->SetRunwayLengthAndHeading(apoWaterRunwayThreshold[1], dfLength,
@@ -839,22 +851,24 @@ void OGRXPlaneAptReader::ParseWaterRunwayRecord()
 
 void OGRXPlaneAptReader::ParseHelipadRecord()
 {
-    double dfLat, dfLon, dfTrueHeading, dfLength, dfWidth, dfSmoothness;
-    int eSurfaceCode, eMarkings, eShoulderCode, eEdgeLighting;
-    const char* pszHelipadName;
-
     RET_IF_FAIL(assertMinCol(12));
 
-    pszHelipadName = papszTokens[1];
+    const char* pszHelipadName = papszTokens[1];
+    double dfLat;
+    double dfLon;
     RET_IF_FAIL(readLatLon(&dfLat, &dfLon, 2));
+    double dfTrueHeading;
     RET_IF_FAIL(readTrueHeading(&dfTrueHeading, 4));
+    double dfLength;
     RET_IF_FAIL(readDouble(&dfLength, 5, "length"));
+    double dfWidth;
     RET_IF_FAIL(readDouble(&dfWidth, 6, "width"));
-    eSurfaceCode = atoi(papszTokens[7]);
-    eMarkings = atoi(papszTokens[8]);
-    eShoulderCode = atoi(papszTokens[9]);
+    const int eSurfaceCode = atoi(papszTokens[7]);
+    const int eMarkings = atoi(papszTokens[8]);
+    const int eShoulderCode = atoi(papszTokens[9]);
+    double dfSmoothness;
     RET_IF_FAIL(readDoubleWithBounds(&dfSmoothness, 10, "helipad smoothness", 0., 1.));
-    eEdgeLighting = atoi(papszTokens[11]);
+    const int eEdgeLighting = atoi(papszTokens[11]);
 
     if (poHelipadLayer)
     {
@@ -893,13 +907,12 @@ void OGRXPlaneAptReader::AddBezierCurve(OGRLineString& lineString,
                                         double dfSymCtrlPtLatB, double dfSymCtrlPtLonB,
                                         double dfLatB, double dfLonB)
 {
-    int step;
-    for(step = 0; step <= 10; step++)
+    for( int step = 0; step <= 10; step++ )
     {
-        double a = step / 10.;
-        double b = 1. - a;
-        double dfCtrlPtLonB = dfLonB - (dfSymCtrlPtLonB - dfLonB);
-        double dfCtrlPtLatB = dfLatB - (dfSymCtrlPtLatB - dfLatB);
+        const double a = step / 10.;
+        const double b = 1. - a;
+        const double dfCtrlPtLonB = dfLonB - (dfSymCtrlPtLonB - dfLonB);
+        const double dfCtrlPtLatB = dfLatB - (dfSymCtrlPtLatB - dfLatB);
         lineString.addPoint(CUBIC_INTERPOL(dfLonA, dfCtrPtLonA, dfCtrlPtLonB, dfLonB),
                             CUBIC_INTERPOL(dfLatA, dfCtrPtLatA, dfCtrlPtLatB, dfLatB));
     }
@@ -913,8 +926,7 @@ void OGRXPlaneAptReader::AddBezierCurve(OGRLineString& lineString,
                                         double dfCtrPtLat, double dfCtrPtLon,
                                         double dfLatB, double dfLonB)
 {
-    int step;
-    for(step = 0; step <= 10; step++)
+    for( int step = 0; step <= 10; step++ )
     {
         double a = step / 10.;
         double b = 1. - a;
@@ -925,7 +937,8 @@ void OGRXPlaneAptReader::AddBezierCurve(OGRLineString& lineString,
 
 static OGRGeometry* OGRXPlaneAptReaderSplitPolygon(OGRPolygon& polygon)
 {
-    OGRPolygon** papoPolygons = new OGRPolygon* [1 + polygon.getNumInteriorRings()];
+    OGRPolygon** papoPolygons
+        = new OGRPolygon* [1 + polygon.getNumInteriorRings()];
 
     papoPolygons[0] = new OGRPolygon();
     papoPolygons[0]->addRing(polygon.getExteriorRing());
@@ -936,10 +949,11 @@ static OGRGeometry* OGRXPlaneAptReaderSplitPolygon(OGRPolygon& polygon)
     }
 
     int bIsValid;
-    OGRGeometry* poGeom;
-    poGeom = OGRGeometryFactory::organizePolygons((OGRGeometry**)papoPolygons,
-                                                  1 + polygon.getNumInteriorRings(),
-                                                  &bIsValid, NULL);
+    OGRGeometry* poGeom
+        = OGRGeometryFactory::organizePolygons(
+            reinterpret_cast<OGRGeometry**>( papoPolygons ),
+            1 + polygon.getNumInteriorRings(),
+            &bIsValid, NULL);
 
     delete[] papoPolygons;
 
@@ -958,14 +972,14 @@ is on the edge of the external ring, or other topological anomalies.
 OGRGeometry* OGRXPlaneAptReader::FixPolygonTopology(OGRPolygon& polygon)
 {
     OGRPolygon* poPolygon = &polygon;
-    OGRPolygon* poPolygonTemp = NULL;
     OGRLinearRing* poExternalRing = poPolygon->getExteriorRing();
     if (poExternalRing->getNumPoints() < 4)
     {
         CPLDebug("XPLANE", "Discarded degenerated polygon at line %d", nLineNumber);
         return NULL;
     }
-        
+
+    OGRPolygon* poPolygonTemp = NULL;
     for(int i=0;i<poPolygon->getNumInteriorRings();i++)
     {
         OGRLinearRing* poInternalRing = poPolygon->getInteriorRing(i);
@@ -984,7 +998,7 @@ OGRGeometry* OGRXPlaneAptReader::FixPolygonTopology(OGRPolygon& polygon)
             i --;
             continue;
         }
-        
+
         int nOutside = 0;
         int jOutside = -1;
         for(int j=0;j<poInternalRing->getNumPoints();j++)
@@ -1004,17 +1018,17 @@ OGRGeometry* OGRXPlaneAptReader::FixPolygonTopology(OGRPolygon& polygon)
             OGRPoint pt;
             poInternalRing->getPoint(j, &pt);
             OGRPoint newPt;
-            int bSuccess = FALSE;
-            for(int k=-1;k<=1 && !bSuccess;k+=2)
+            bool bSuccess = false;
+            for( int k=-1; k<=1 && !bSuccess; k+=2 )
             {
-                for(int l=-1;l<=1 && !bSuccess;l+=2)
+                for( int l=-1; l<=1 && !bSuccess; l+=2 )
                 {
                     newPt.setX(pt.getX() + k * 1e-7);
                     newPt.setY(pt.getY() + l * 1e-7);
                     if (poExternalRing->isPointInRing(&newPt))
                     {
                         poInternalRing->setPoint(j, newPt.getX(), newPt.getY());
-                        bSuccess = TRUE;
+                        bSuccess = true;
                     }
                 }
             }
@@ -1061,11 +1075,11 @@ int OGRXPlaneAptReader::ParsePolygonalGeometry(OGRGeometry** ppoGeom)
     double dfLatBezier = 0., dfLonBezier = 0.;
     double dfFirstLatBezier = 0., dfFirstLonBezier = 0.;
     double dfLastLatBezier = 0., dfLastLonBezier = 0.;
-    int bIsFirst = TRUE;
-    int bFirstIsBezier = TRUE;
-    /* int bLastIsValid = FALSE; */
-    int bLastIsBezier = FALSE;
-    int bLastPartIsClosed = FALSE;
+    bool bIsFirst = true;
+    bool bFirstIsBezier = true;
+    // bool bLastIsValid = false;
+    bool bLastIsBezier = false;
+    bool bLastPartIsClosed = false;
     const char* pszLine;
     OGRPolygon polygon;
 
@@ -1093,7 +1107,7 @@ int OGRXPlaneAptReader::ParsePolygonalGeometry(OGRGeometry** ppoGeom)
                 *ppoGeom = FixPolygonTopology(polygon);
             }
 
-            return TRUE;
+            return true;
         }
         if (nTokens == 0 || assertMinCol(2) == FALSE)
         {
@@ -1118,8 +1132,8 @@ int OGRXPlaneAptReader::ParsePolygonalGeometry(OGRGeometry** ppoGeom)
             else
                 linearRing.addPoint(dfLon, dfLat);
 
-            bLastPartIsClosed = FALSE;
-            bLastIsBezier = FALSE;
+            bLastPartIsClosed = false;
+            bLastIsBezier = false;
         }
         else if (nType == APT_NODE_WITH_BEZIER)
         {
@@ -1145,8 +1159,8 @@ int OGRXPlaneAptReader::ParsePolygonalGeometry(OGRGeometry** ppoGeom)
                                dfLat, dfLon);
             }
 
-            bLastPartIsClosed = FALSE;
-            bLastIsBezier = TRUE;
+            bLastPartIsClosed = false;
+            bLastIsBezier = true;
             dfLastLatBezier = dfLatBezier;
             dfLastLonBezier = dfLonBezier;
         }
@@ -1158,7 +1172,7 @@ int OGRXPlaneAptReader::ParsePolygonalGeometry(OGRGeometry** ppoGeom)
             {
                 CPLDebug("XPlane", "Line %d : Unexpected token when reading a polygon : %d",
                         nLineNumber, nType);
-                return TRUE;
+                return true;
             }
 
             if (bLastIsBezier && !bIsFirst &&
@@ -1177,8 +1191,8 @@ int OGRXPlaneAptReader::ParsePolygonalGeometry(OGRGeometry** ppoGeom)
             polygon.addRing(&linearRing);
             linearRing.empty();
 
-            bLastPartIsClosed = TRUE;
-            bLastIsBezier = FALSE;
+            bLastPartIsClosed = true;
+            bLastIsBezier = false;
         }
         else if (nType == APT_NODE_CLOSE_WITH_BEZIER)
         {
@@ -1189,7 +1203,7 @@ int OGRXPlaneAptReader::ParsePolygonalGeometry(OGRGeometry** ppoGeom)
             {
                 CPLDebug("XPlane", "Line %d : Unexpected token when reading a polygon : %d",
                         nLineNumber, nType);
-                return TRUE;
+                return true;
             }
 
             if (bLastIsBezier)
@@ -1230,8 +1244,8 @@ int OGRXPlaneAptReader::ParsePolygonalGeometry(OGRGeometry** ppoGeom)
             polygon.addRing(&linearRing);
             linearRing.empty();
 
-            bLastPartIsClosed = TRUE;
-            bLastIsBezier = FALSE; /* we don't want to draw an arc between two parts */
+            bLastPartIsClosed = true;
+            bLastIsBezier = false; /* we don't want to draw an arc between two parts */
         }
         else
         {
@@ -1246,7 +1260,7 @@ int OGRXPlaneAptReader::ParsePolygonalGeometry(OGRGeometry** ppoGeom)
                 *ppoGeom = FixPolygonTopology(polygon);
             }
 
-            return TRUE;
+            return true;
         }
 
         if (bIsFirst)
@@ -1261,7 +1275,7 @@ int OGRXPlaneAptReader::ParsePolygonalGeometry(OGRGeometry** ppoGeom)
 
         dfLastLat = dfLat;
         dfLastLon = dfLon;
-        /* bLastIsValid = TRUE; */
+        /* bLastIsValid = true; */
 
         CSLDestroy(papszTokens);
     }
@@ -1270,7 +1284,7 @@ int OGRXPlaneAptReader::ParsePolygonalGeometry(OGRGeometry** ppoGeom)
 
     papszTokens = NULL;
 
-    return FALSE;
+    return false;
 }
 
 
@@ -1280,19 +1294,17 @@ int OGRXPlaneAptReader::ParsePolygonalGeometry(OGRGeometry** ppoGeom)
 
 void OGRXPlaneAptReader::ParsePavement()
 {
-    int eSurfaceCode;
-    double dfSmoothness, dfTextureHeading;
-    CPLString osPavementName;
-
     RET_IF_FAIL(assertMinCol(4));
 
-    eSurfaceCode = atoi(papszTokens[1]);
+    const int eSurfaceCode = atoi(papszTokens[1]);
 
+    double dfSmoothness;
     RET_IF_FAIL(readDoubleWithBounds(&dfSmoothness, 2, "pavement smoothness", 0., 1.));
 
+    double dfTextureHeading;
     RET_IF_FAIL(readTrueHeading(&dfTextureHeading, 3, "texture heading"));
 
-    osPavementName = readStringUntilEnd(4);
+    const CPLString osPavementName = readStringUntilEnd(4);
 
     CSLDestroy(papszTokens);
     papszTokens = NULL;
@@ -1306,11 +1318,12 @@ void OGRXPlaneAptReader::ParsePavement()
             poPavementLayer->AddFeature(osAptICAO, osPavementName,
                                         RunwaySurfaceEnumeration.GetText(eSurfaceCode),
                                         dfSmoothness, dfTextureHeading,
-                                        (OGRPolygon*)poGeom);
+                                        reinterpret_cast<OGRPolygon*>(poGeom) );
         }
         else
         {
-            OGRGeometryCollection* poGeomCollection = (OGRGeometryCollection*)poGeom;
+            OGRGeometryCollection* poGeomCollection
+                = reinterpret_cast<OGRGeometryCollection*>(poGeom);
             for(int i=0;i<poGeomCollection->getNumGeometries();i++)
             {
                 OGRGeometry* poSubGeom = poGeomCollection->getGeometryRef(i);
@@ -1338,11 +1351,10 @@ void OGRXPlaneAptReader::ParsePavement()
 
 void OGRXPlaneAptReader::ParseAPTBoundary()
 {
-    CPLString osBoundaryName;
 
     RET_IF_FAIL(assertMinCol(2));
 
-    osBoundaryName = readStringUntilEnd(2);
+    const CPLString osBoundaryName = readStringUntilEnd(2);
 
     CSLDestroy(papszTokens);
     papszTokens = NULL;
@@ -1353,12 +1365,14 @@ void OGRXPlaneAptReader::ParseAPTBoundary()
     {
         if (poGeom->getGeometryType() == wkbPolygon)
         {
-             poAPTBoundaryLayer->AddFeature(osAptICAO, osBoundaryName,
-                                        (OGRPolygon*)poGeom);
+             poAPTBoundaryLayer->AddFeature(
+                 osAptICAO, osBoundaryName,
+                 reinterpret_cast<OGRPolygon *>(poGeom) );
         }
         else
         {
-            OGRGeometryCollection* poGeomCollection = (OGRGeometryCollection*)poGeom;
+            OGRGeometryCollection* poGeomCollection
+                = reinterpret_cast<OGRGeometryCollection*>(poGeom);
             for(int i=0;i<poGeomCollection->getNumGeometries();i++)
             {
                 OGRGeometry* poSubGeom = poGeomCollection->getGeometryRef(i);
@@ -1391,11 +1405,11 @@ int OGRXPlaneAptReader::ParseLinearGeometry(OGRMultiLineString& multilinestring,
     double dfLatBezier = 0., dfLonBezier = 0.;
     double dfFirstLatBezier = 0., dfFirstLonBezier = 0.;
     double dfLastLatBezier = 0., dfLastLonBezier = 0.;
-    int bIsFirst = TRUE;
-    int bFirstIsBezier = TRUE;
-    /* int bLastIsValid = FALSE; */
-    int bLastIsBezier = FALSE;
-    int bLastPartIsClosedOrEnded = FALSE;
+    bool bIsFirst = true;
+    bool bFirstIsBezier = true;
+    // bool bLastIsValid = false;
+    bool bLastIsBezier = false;
+    bool bLastPartIsClosedOrEnded = false;
     const char* pszLine;
 
     OGRLineString lineString;
@@ -1410,7 +1424,7 @@ int OGRXPlaneAptReader::ParseLinearGeometry(OGRMultiLineString& multilinestring,
 
         if (nTokens == 1 && strcmp(papszTokens[0], "99") == 0)
         {
-            if (bLastPartIsClosedOrEnded == FALSE)
+            if( !bLastPartIsClosedOrEnded )
             {
                 CPLDebug("XPlane", "Line %d : Unexpected token when reading a linear feature : %d",
                         nLineNumber, nType);
@@ -1422,9 +1436,9 @@ int OGRXPlaneAptReader::ParseLinearGeometry(OGRMultiLineString& multilinestring,
             }
             else
             {
-                *pbIsValid = TRUE;
+                *pbIsValid = true;
             }
-            return TRUE;
+            return true;
         }
         if (nTokens == 0 || assertMinCol(2) == FALSE)
         {
@@ -1449,8 +1463,8 @@ int OGRXPlaneAptReader::ParseLinearGeometry(OGRMultiLineString& multilinestring,
             else
                 lineString.addPoint(dfLon, dfLat);
 
-            bLastPartIsClosedOrEnded = FALSE;
-            bLastIsBezier = FALSE;
+            bLastPartIsClosedOrEnded = false;
+            bLastIsBezier = false;
         }
         else if (nType == APT_NODE_WITH_BEZIER)
         {
@@ -1468,16 +1482,16 @@ int OGRXPlaneAptReader::ParseLinearGeometry(OGRMultiLineString& multilinestring,
             }
             else if (!bIsFirst && !(dfLastLat == dfLat && dfLastLon == dfLon))
             {
-                double dfCtrLatBezier = dfLat - (dfLatBezier - dfLat);
-                double dfCtrLonBezier = dfLon - (dfLonBezier - dfLon);
+                const double dfCtrLatBezier = dfLat - (dfLatBezier - dfLat);
+                const double dfCtrLonBezier = dfLon - (dfLonBezier - dfLon);
                 AddBezierCurve(lineString,
                                dfLastLat, dfLastLon,
                                dfCtrLatBezier, dfCtrLonBezier,
                                dfLat, dfLon);
             }
 
-            bLastPartIsClosedOrEnded = FALSE;
-            bLastIsBezier = TRUE;
+            bLastPartIsClosedOrEnded = false;
+            bLastIsBezier = true;
             dfLastLatBezier = dfLatBezier;
             dfLastLonBezier = dfLonBezier;
         }
@@ -1487,9 +1501,11 @@ int OGRXPlaneAptReader::ParseLinearGeometry(OGRMultiLineString& multilinestring,
             RET_FALSE_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
             if (bIsFirst)
             {
-                CPLDebug("XPlane", "Line %d : Unexpected token when reading a linear feature : %d",
-                        nLineNumber, nType);
-                return TRUE;
+                CPLDebug( "XPlane",
+                          "Line %d : Unexpected token when reading a linear "
+                          "feature : %d",
+                          nLineNumber, nType );
+                return true;
             }
 
             if (bLastIsBezier && !(dfLastLat == dfLat && dfLastLon == dfLon))
@@ -1507,8 +1523,9 @@ int OGRXPlaneAptReader::ParseLinearGeometry(OGRMultiLineString& multilinestring,
 
             if (lineString.getNumPoints() < 2)
             {
-                CPLDebug("XPlane", "Line %d : A linestring has less than 2 points",
-                         nLineNumber);
+                CPLDebug( "XPlane",
+                          "Line %d : A linestring has less than 2 points",
+                          nLineNumber);
             }
             else
             {
@@ -1516,19 +1533,22 @@ int OGRXPlaneAptReader::ParseLinearGeometry(OGRMultiLineString& multilinestring,
             }
             lineString.empty();
 
-            bLastPartIsClosedOrEnded = TRUE;
-            bLastIsBezier = FALSE;
+            bLastPartIsClosedOrEnded = true;
+            bLastIsBezier = false;
         }
-        else if (nType == APT_NODE_CLOSE_WITH_BEZIER || nType == APT_NODE_END_WITH_BEZIER)
+        else if (nType == APT_NODE_CLOSE_WITH_BEZIER
+                 || nType == APT_NODE_END_WITH_BEZIER)
         {
             RET_FALSE_IF_FAIL(assertMinCol(5));
             RET_FALSE_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
             RET_FALSE_IF_FAIL(readLatLon(&dfLatBezier, &dfLonBezier, 3));
             if (bIsFirst)
             {
-                CPLDebug("XPlane", "Line %d : Unexpected token when reading a linear feature : %d",
-                        nLineNumber, nType);
-                return TRUE;
+                CPLDebug( "XPlane",
+                          "Line %d : Unexpected token when reading a linear "
+                          "feature : %d",
+                          nLineNumber, nType );
+                return true;
             }
 
             if (bLastIsBezier)
@@ -1571,8 +1591,9 @@ int OGRXPlaneAptReader::ParseLinearGeometry(OGRMultiLineString& multilinestring,
 
             if (lineString.getNumPoints() < 2)
             {
-                CPLDebug("XPlane", "Line %d : A linestring has less than 2 points",
-                         nLineNumber);
+                CPLDebug( "XPlane",
+                          "Line %d : A linestring has less than 2 points",
+                          nLineNumber );
             }
             else
             {
@@ -1580,26 +1601,30 @@ int OGRXPlaneAptReader::ParseLinearGeometry(OGRMultiLineString& multilinestring,
             }
             lineString.empty();
 
-            bLastPartIsClosedOrEnded = TRUE;
-            bLastIsBezier = FALSE; /* we don't want to draw an arc between two parts */
+            bLastPartIsClosedOrEnded = true;
+            // Do not want to draw an arc between two parts.
+            bLastIsBezier = false;
         }
         else
         {
             if (bLastPartIsClosedOrEnded == FALSE)
             {
-                CPLDebug("XPlane", "Line %d : Unexpected token when reading a linear feature : %d",
-                        nLineNumber, nType);
+                CPLDebug( "XPlane",
+                          "Line %d : Unexpected token when reading a linear "
+                          "feature : %d",
+                          nLineNumber, nType );
             }
             else if (multilinestring.getNumGeometries() == 0)
             {
-                CPLDebug("XPlane", "Line %d : Linear geometry is invalid or empty",
-                         nLineNumber);
+                CPLDebug( "XPlane",
+                          "Line %d : Linear geometry is invalid or empty",
+                          nLineNumber );
             }
             else
             {
-                *pbIsValid = TRUE;
+                *pbIsValid = true;
             }
-            return TRUE;
+            return true;
         }
 
         if (bIsFirst)
@@ -1614,7 +1639,7 @@ int OGRXPlaneAptReader::ParseLinearGeometry(OGRMultiLineString& multilinestring,
 
         dfLastLat = dfLat;
         dfLastLon = dfLon;
-        /* bLastIsValid = TRUE; */
+        /* bLastIsValid = true; */
 
         CSLDestroy(papszTokens);
     }
@@ -1623,29 +1648,27 @@ int OGRXPlaneAptReader::ParseLinearGeometry(OGRMultiLineString& multilinestring,
 
     papszTokens = NULL;
 
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
 /*                      ParseAPTLinearFeature()                         */
 /************************************************************************/
 
-/* This function will eat records until the end of the linear feature definition */
-/* Return TRUE if the main parser must re-scan the current record */
+// This function will eat records until the end of the linear feature definition
+// Return TRUE if the main parser must re-scan the current record.
 
 void OGRXPlaneAptReader::ParseAPTLinearFeature()
 {
-    CPLString osLinearFeatureName;
-
     RET_IF_FAIL(assertMinCol(2));
 
-    osLinearFeatureName = readStringUntilEnd(2);
+    CPLString osLinearFeatureName = readStringUntilEnd(2);
 
     CSLDestroy(papszTokens);
     papszTokens = NULL;
 
     OGRMultiLineString multilinestring;
-    int bIsValid = FALSE;
+    int bIsValid = false;
     bResumeLine = ParseLinearGeometry(multilinestring, &bIsValid);
     if (bIsValid && poAPTLinearFeatureLayer)
     {
@@ -1665,13 +1688,14 @@ void OGRXPlaneAptReader::ParseTowerRecord()
     RET_IF_FAIL(readLatLon(&dfLatTower, &dfLonTower, 1));
 
     /* feet to meter */
-    RET_IF_FAIL(readDoubleWithBoundsAndConversion(&dfHeightTower, 3, "tower height", FEET_TO_METER, 0., 300.));
+    RET_IF_FAIL(readDoubleWithBoundsAndConversion(
+        &dfHeightTower, 3, "tower height", FEET_TO_METER, 0., 300. ) );
 
     // papszTokens[4] ignored
 
     osTowerName = readStringUntilEnd(5);
 
-    bTowerFound = TRUE;
+    bTowerFound = true;
 }
 
 
@@ -1681,15 +1705,13 @@ void OGRXPlaneAptReader::ParseTowerRecord()
 
 void OGRXPlaneAptReader::ParseATCRecord(int nType)
 {
-    double dfFrequency;
-    CPLString osFreqName;
-
     RET_IF_FAIL(assertMinCol(2));
 
+    double dfFrequency;
     RET_IF_FAIL(readDouble(&dfFrequency, 1, "frequency"));
     dfFrequency /= 100.;
 
-    osFreqName = readStringUntilEnd(2);
+    const CPLString osFreqName = readStringUntilEnd(2);
 
     if (poATCFreqLayer)
     {
@@ -1712,19 +1734,18 @@ void OGRXPlaneAptReader::ParseATCRecord(int nType)
 
 void OGRXPlaneAptReader::ParseStartupLocationRecord()
 {
-    double dfLat, dfLon, dfTrueHeading;
-    CPLString osName;
-
     RET_IF_FAIL(assertMinCol(4));
 
+    double dfLat, dfLon, dfTrueHeading;
     RET_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
 
     RET_IF_FAIL(readTrueHeading(&dfTrueHeading, 3));
 
-    osName = readStringUntilEnd(4);
+    const CPLString osName = readStringUntilEnd(4);
 
     if (poStartupLocationLayer)
-        poStartupLocationLayer->AddFeature(osAptICAO, osName, dfLat, dfLon, dfTrueHeading);
+        poStartupLocationLayer->AddFeature( osAptICAO, osName, dfLat, dfLon,
+                                            dfTrueHeading );
 }
 
 /************************************************************************/
@@ -1733,18 +1754,17 @@ void OGRXPlaneAptReader::ParseStartupLocationRecord()
 
 void OGRXPlaneAptReader::ParseLightBeaconRecord()
 {
-    double dfLat, dfLon;
-    int eColor;
-    CPLString osName;
-
     RET_IF_FAIL(assertMinCol(4));
+
+    double dfLat, dfLon;
     RET_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
-    eColor = atoi(papszTokens[3]);
-    osName = readStringUntilEnd(4);
+    const int eColor = atoi(papszTokens[3]);
+    const CPLString osName = readStringUntilEnd(4);
 
     if (poAPTLightBeaconLayer)
-        poAPTLightBeaconLayer->AddFeature(osAptICAO, osName, dfLat, dfLon,
-                                            APTLightBeaconColorEnumeration.GetText(eColor));
+        poAPTLightBeaconLayer->AddFeature(
+            osAptICAO, osName, dfLat, dfLon,
+            APTLightBeaconColorEnumeration.GetText(eColor));
 }
 
 /************************************************************************/
@@ -1753,19 +1773,17 @@ void OGRXPlaneAptReader::ParseLightBeaconRecord()
 
 void OGRXPlaneAptReader::ParseWindsockRecord()
 {
-    double dfLat, dfLon;
-    int bIsIllumnited;
-    CPLString osName;
-
     RET_IF_FAIL(assertMinCol(4));
 
+    double dfLat, dfLon;
     RET_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
-    bIsIllumnited = atoi(papszTokens[3]);
-    osName = readStringUntilEnd(4);
+
+    const bool bIsIllumnited = CPL_TO_BOOL(atoi(papszTokens[3]));
+    const CPLString osName = readStringUntilEnd(4);
 
     if (poAPTWindsockLayer)
         poAPTWindsockLayer->AddFeature(osAptICAO, osName, dfLat, dfLon,
-                                        bIsIllumnited);
+                                       bIsIllumnited);
 }
 
 /************************************************************************/
@@ -1774,18 +1792,15 @@ void OGRXPlaneAptReader::ParseWindsockRecord()
 
 void OGRXPlaneAptReader::ParseTaxiwaySignRecord()
 {
-    double dfLat, dfLon;
-    double dfTrueHeading;
-    int nSize;
-    CPLString osText;
-
     RET_IF_FAIL(assertMinCol(7));
 
+    double dfLat, dfLon;
     RET_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
+    double dfTrueHeading;
     RET_IF_FAIL(readTrueHeading(&dfTrueHeading, 3, "heading"));
     /* papszTokens[4] : ignored. Taxiway sign style */
-    nSize = atoi(papszTokens[5]);
-    osText = readStringUntilEnd(6);
+    const int nSize = atoi(papszTokens[5]);
+    const CPLString osText = readStringUntilEnd(6);
 
     if (poTaxiwaySignLayer)
         poTaxiwaySignLayer->AddFeature(osAptICAO, osText, dfLat, dfLon,
@@ -1798,24 +1813,24 @@ void OGRXPlaneAptReader::ParseTaxiwaySignRecord()
 
 void OGRXPlaneAptReader::ParseVasiPapiWigWagRecord()
 {
-    double dfLat, dfLon;
-    int eType;
-    double dfTrueHeading, dfVisualGlidePathAngle;
-    const char* pszRwyNum;
-
     RET_IF_FAIL(assertMinCol(7));
 
+    double dfLat, dfLon;
+
     RET_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
-    eType = atoi(papszTokens[3]);
+    const int eType = atoi(papszTokens[3]);
+    double dfTrueHeading;
     RET_IF_FAIL(readTrueHeading(&dfTrueHeading, 4, "heading"));
+    double dfVisualGlidePathAngle;
     RET_IF_FAIL(readDoubleWithBounds(&dfVisualGlidePathAngle, 5, "visual glidepath angle", 0, 90));
-    pszRwyNum = papszTokens[6];
+    const char* pszRwyNum = papszTokens[6];
     /* papszTokens[7] : ignored. Type of lighting object represented */
 
     if (poVASI_PAPI_WIGWAG_Layer)
-        poVASI_PAPI_WIGWAG_Layer->AddFeature(osAptICAO, pszRwyNum, VASI_PAPI_WIGWAG_Enumeration.GetText(eType),
-                                                dfLat, dfLon,
-                                                dfTrueHeading, dfVisualGlidePathAngle);
+        poVASI_PAPI_WIGWAG_Layer->AddFeature(
+            osAptICAO, pszRwyNum, VASI_PAPI_WIGWAG_Enumeration.GetText(eType),
+            dfLat, dfLon,
+            dfTrueHeading, dfVisualGlidePathAngle);
 }
 
 /************************************************************************/
@@ -1824,19 +1839,15 @@ void OGRXPlaneAptReader::ParseVasiPapiWigWagRecord()
 
 void OGRXPlaneAptReader::ParseTaxiLocation()
 {
-    double dfLat, dfLon;
-    double dfTrueHeading;
-    CPLString osLocationType;
-    CPLString osAirplaneTypes;
-    CPLString osName;
-
     RET_IF_FAIL(assertMinCol(7));
 
+    double dfLat, dfLon;
     RET_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
+    double dfTrueHeading;
     RET_IF_FAIL(readTrueHeading(&dfTrueHeading, 3, "heading"));
-    osLocationType = papszTokens[4];
-    osAirplaneTypes = papszTokens[5];
-    osName = readStringUntilEnd(6);
+    const CPLString osLocationType = papszTokens[4];
+    const CPLString osAirplaneTypes = papszTokens[5];
+    const CPLString osName = readStringUntilEnd(6);
 
     if (poTaxiLocationLayer)
         poTaxiLocationLayer->AddFeature(osAptICAO, dfLat, dfLon,
@@ -1863,7 +1874,7 @@ OGRXPlaneAPTLayer::OGRXPlaneAPTLayer() : OGRXPlaneLayer("APT")
     OGRFieldDefn oType("type", OFTInteger );
     oType.SetWidth( 1 );
     poFeatureDefn->AddFieldDefn( &oType );
-    
+
     OGRFieldDefn oFieldElev("elevation_m", OFTReal );
     oFieldElev.SetWidth( 8 );
     oFieldElev.SetPrecision( 2 );
@@ -1880,7 +1891,6 @@ OGRXPlaneAPTLayer::OGRXPlaneAPTLayer() : OGRXPlaneLayer("APT")
 
     OGRFieldDefn oFieldTowerName("tower_name", OFTString );
     poFeatureDefn->AddFieldDefn( &oFieldTowerName );
-
 }
 
 /************************************************************************/
@@ -1966,7 +1976,8 @@ OGRXPlaneRunwayThresholdLayer::OGRXPlaneRunwayThresholdLayer() : OGRXPlaneLayer(
     OGRFieldDefn oFieldEdgeLigthing("edge_lighting", OFTString );
     poFeatureDefn->AddFieldDefn( &oFieldEdgeLigthing );
 
-    OGRFieldDefn oFieldDistanceRemainingSigns("distance_remaining_signs", OFTInteger );
+    OGRFieldDefn oFieldDistanceRemainingSigns(
+        "distance_remaining_signs", OFTInteger );
     oFieldDistanceRemainingSigns.SetWidth( 1 );
     poFeatureDefn->AddFieldDefn( &oFieldDistanceRemainingSigns );
 
@@ -2041,7 +2052,7 @@ OGRFeature*
     poFeature->SetField( nCount++, pszEdgeLighting );
     poFeature->SetField( nCount++, bHasDistanceRemainingSigns );
     poFeature->SetField( nCount++, dfDisplacedThresholdLength );
-    poFeature->SetField( nCount++, FALSE);
+    poFeature->SetField( nCount++, false);
     poFeature->SetField( nCount++, dfStopwayLength );
     poFeature->SetField( nCount++, pszMarkings );
     poFeature->SetField( nCount++, pszApproachLightingCode );
@@ -2071,11 +2082,12 @@ OGRFeature* OGRXPlaneRunwayThresholdLayer::
 {
     OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
 
-    poFeature->SetFrom(poNonDisplacedThresholdFeature, FALSE);
+    poFeature->SetFrom(poNonDisplacedThresholdFeature, false);
 
-    double dfDisplacedThresholdLength = poFeature->GetFieldAsDouble("displaced_threshold_m");
-    double dfTrueHeading = poFeature->GetFieldAsDouble("true_heading_deg");
-    poFeature->SetField("is_displaced", TRUE);
+    const double dfDisplacedThresholdLength
+        = poFeature->GetFieldAsDouble("displaced_threshold_m");
+    const double dfTrueHeading = poFeature->GetFieldAsDouble("true_heading_deg");
+    poFeature->SetField("is_displaced", true);
     OGRPoint* poPoint = (OGRPoint*)poFeature->GetGeometryRef();
     double dfLatDisplaced, dfLonDisplaced;
     OGRXPlane_ExtendPosition(poPoint->getY(), poPoint->getX(),
@@ -2171,20 +2183,20 @@ OGRFeature*
     int nCount = 0;
     OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
 
-    double dfLength = OGRXPlane_Distance(dfLat1, dfLon1, dfLat2, dfLon2);
-    double dfTrack12 = OGRXPlane_Track(dfLat1, dfLon1, dfLat2, dfLon2);
-    double dfTrack21 = OGRXPlane_Track(dfLat2, dfLon2, dfLat1, dfLon1);
-    double adfLat[4], adfLon[4];
-    
+    const double dfLength = OGRXPlane_Distance(dfLat1, dfLon1, dfLat2, dfLon2);
+    const double dfTrack12 = OGRXPlane_Track(dfLat1, dfLon1, dfLat2, dfLon2);
+    const double dfTrack21 = OGRXPlane_Track(dfLat2, dfLon2, dfLat1, dfLon1);
+    double adfLat[4];
+    double adfLon[4];
+
     OGRXPlane_ExtendPosition(dfLat1, dfLon1, dfWidth / 2, dfTrack12 - 90, &adfLat[0], &adfLon[0]);
     OGRXPlane_ExtendPosition(dfLat2, dfLon2, dfWidth / 2, dfTrack21 + 90, &adfLat[1], &adfLon[1]);
     OGRXPlane_ExtendPosition(dfLat2, dfLon2, dfWidth / 2, dfTrack21 - 90, &adfLat[2], &adfLon[2]);
     OGRXPlane_ExtendPosition(dfLat1, dfLon1, dfWidth / 2, dfTrack12 + 90, &adfLat[3], &adfLon[3]);
-    
+
     OGRLinearRing* linearRing = new OGRLinearRing();
     linearRing->setNumPoints(5);
-    int i;
-    for(i=0;i<4;i++)
+    for( int i=0; i < 4; i++ )
         linearRing->setPoint(i, adfLon[i], adfLat[i]);
     linearRing->setPoint(4, adfLon[0], adfLat[0]);
     OGRPolygon* polygon = new OGRPolygon();
@@ -2256,18 +2268,22 @@ OGRFeature*
 
     double dfLat2, dfLon2;
     double adfLat[4], adfLon[4];
-    
-    OGRXPlane_ExtendPosition(dfLatThreshold, dfLonThreshold, dfStopwayLength, 180 + dfRunwayHeading, &dfLat2, &dfLon2);
-    
-    OGRXPlane_ExtendPosition(dfLatThreshold, dfLonThreshold, dfWidth / 2, dfRunwayHeading - 90, &adfLat[0], &adfLon[0]);
-    OGRXPlane_ExtendPosition(dfLat2, dfLon2, dfWidth / 2, dfRunwayHeading - 90, &adfLat[1], &adfLon[1]);
-    OGRXPlane_ExtendPosition(dfLat2, dfLon2, dfWidth / 2, dfRunwayHeading + 90, &adfLat[2], &adfLon[2]);
-    OGRXPlane_ExtendPosition(dfLatThreshold, dfLonThreshold, dfWidth / 2, dfRunwayHeading + 90, &adfLat[3], &adfLon[3]);
-    
+
+    OGRXPlane_ExtendPosition( dfLatThreshold, dfLonThreshold, dfStopwayLength,
+                              180 + dfRunwayHeading, &dfLat2, &dfLon2);
+
+    OGRXPlane_ExtendPosition( dfLatThreshold, dfLonThreshold, dfWidth / 2,
+                              dfRunwayHeading - 90, &adfLat[0], &adfLon[0]);
+    OGRXPlane_ExtendPosition( dfLat2, dfLon2, dfWidth / 2, dfRunwayHeading - 90,
+                              &adfLat[1], &adfLon[1]);
+    OGRXPlane_ExtendPosition( dfLat2, dfLon2, dfWidth / 2, dfRunwayHeading + 90,
+                              &adfLat[2], &adfLon[2]);
+    OGRXPlane_ExtendPosition( dfLatThreshold, dfLonThreshold, dfWidth / 2,
+                              dfRunwayHeading + 90, &adfLat[3], &adfLon[3]);
+
     OGRLinearRing* linearRing = new OGRLinearRing();
     linearRing->setNumPoints(5);
-    int i;
-    for(i=0;i<4;i++)
+    for( int i=0; i<4; i++ )
         linearRing->setPoint(i, adfLon[i], adfLat[i]);
     linearRing->setPoint(4, adfLon[0], adfLat[0]);
     OGRPolygon* polygon = new OGRPolygon();
@@ -2289,7 +2305,8 @@ OGRFeature*
 /************************************************************************/
 
 
-OGRXPlaneWaterRunwayThresholdLayer::OGRXPlaneWaterRunwayThresholdLayer() : OGRXPlaneLayer("WaterRunwayThreshold")
+OGRXPlaneWaterRunwayThresholdLayer::OGRXPlaneWaterRunwayThresholdLayer() :
+    OGRXPlaneLayer("WaterRunwayThreshold")
 {
     poFeatureDefn->SetGeomType( wkbPoint );
 
@@ -2344,9 +2361,10 @@ OGRFeature*
     return poFeature;
 }
 
-void OGRXPlaneWaterRunwayThresholdLayer::SetRunwayLengthAndHeading(OGRFeature* poFeature,
-                                                     double dfLength,
-                                                     double dfHeading)
+void OGRXPlaneWaterRunwayThresholdLayer::SetRunwayLengthAndHeading(
+    OGRFeature* poFeature,
+    double dfLength,
+    double dfHeading )
 {
     int nCount = 4;
     poFeature->SetField( nCount++, dfLength );
@@ -2360,7 +2378,8 @@ void OGRXPlaneWaterRunwayThresholdLayer::SetRunwayLengthAndHeading(OGRFeature* p
 
 
 
-OGRXPlaneWaterRunwayLayer::OGRXPlaneWaterRunwayLayer() : OGRXPlaneLayer("WaterRunwayPolygon")
+OGRXPlaneWaterRunwayLayer::OGRXPlaneWaterRunwayLayer() :
+    OGRXPlaneLayer("WaterRunwayPolygon")
 {
     poFeatureDefn->SetGeomType( wkbPolygon );
 
@@ -2409,29 +2428,32 @@ OGRFeature*
                                              double dfWidth,
                                              int bBuoys)
 {
-    int nCount = 0;
     OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
 
-    double dfLength = OGRXPlane_Distance(dfLat1, dfLon1, dfLat2, dfLon2);
-    double dfTrack12 = OGRXPlane_Track(dfLat1, dfLon1, dfLat2, dfLon2);
-    double dfTrack21 = OGRXPlane_Track(dfLat2, dfLon2, dfLat1, dfLon1);
+    const double dfLength = OGRXPlane_Distance(dfLat1, dfLon1, dfLat2, dfLon2);
+    const double dfTrack12 = OGRXPlane_Track(dfLat1, dfLon1, dfLat2, dfLon2);
+    const double dfTrack21 = OGRXPlane_Track(dfLat2, dfLon2, dfLat1, dfLon1);
     double adfLat[4], adfLon[4];
-    
-    OGRXPlane_ExtendPosition(dfLat1, dfLon1, dfWidth / 2, dfTrack12 - 90, &adfLat[0], &adfLon[0]);
-    OGRXPlane_ExtendPosition(dfLat2, dfLon2, dfWidth / 2, dfTrack21 + 90, &adfLat[1], &adfLon[1]);
-    OGRXPlane_ExtendPosition(dfLat2, dfLon2, dfWidth / 2, dfTrack21 - 90, &adfLat[2], &adfLon[2]);
-    OGRXPlane_ExtendPosition(dfLat1, dfLon1, dfWidth / 2, dfTrack12 + 90, &adfLat[3], &adfLon[3]);
-    
+
+    OGRXPlane_ExtendPosition( dfLat1, dfLon1, dfWidth / 2, dfTrack12 - 90,
+                              &adfLat[0], &adfLon[0]);
+    OGRXPlane_ExtendPosition( dfLat2, dfLon2, dfWidth / 2, dfTrack21 + 90,
+                              &adfLat[1], &adfLon[1]);
+    OGRXPlane_ExtendPosition( dfLat2, dfLon2, dfWidth / 2, dfTrack21 - 90,
+                              &adfLat[2], &adfLon[2]);
+    OGRXPlane_ExtendPosition( dfLat1, dfLon1, dfWidth / 2, dfTrack12 + 90,
+                              &adfLat[3], &adfLon[3]);
+
     OGRLinearRing* linearRing = new OGRLinearRing();
     linearRing->setNumPoints(5);
-    int i;
-    for(i=0;i<4;i++)
+    for( int i=0; i<4; i++ )
         linearRing->setPoint(i, adfLon[i], adfLat[i]);
     linearRing->setPoint(4, adfLon[0], adfLat[0]);
     OGRPolygon* polygon = new OGRPolygon();
      polygon->addRingDirectly( linearRing );
     poFeature->SetGeometryDirectly( polygon );
 
+    int nCount = 0;
     poFeature->SetField( nCount++, pszAptICAO );
     poFeature->SetField( nCount++, pszRwyNum1 );
     poFeature->SetField( nCount++, pszRwyNum2 );
@@ -2537,7 +2559,8 @@ OGRFeature*
 /************************************************************************/
 
 
-OGRXPlaneHelipadPolygonLayer::OGRXPlaneHelipadPolygonLayer() : OGRXPlaneLayer("HelipadPolygon")
+OGRXPlaneHelipadPolygonLayer::OGRXPlaneHelipadPolygonLayer() :
+    OGRXPlaneLayer("HelipadPolygon")
 {
     poFeatureDefn->SetGeomType( wkbPolygon );
 
@@ -2599,31 +2622,36 @@ OGRFeature*
                                                double dfSmoothness,
                                                const char* pszEdgeLighting)
 {
-    int nCount = 0;
     OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
 
     double dfBeforeLat, dfBeforeLon;
     double dfAfterLat, dfAfterLon;
     double adfLat[4], adfLon[4];
 
-    OGRXPlane_ExtendPosition(dfLat, dfLon, dfLength / 2, dfTrueHeading + 180, &dfBeforeLat, &dfBeforeLon);
-    OGRXPlane_ExtendPosition(dfLat, dfLon, dfLength / 2, dfTrueHeading, &dfAfterLat, &dfAfterLon);
+    OGRXPlane_ExtendPosition( dfLat, dfLon, dfLength / 2, dfTrueHeading + 180,
+                              &dfBeforeLat, &dfBeforeLon);
+    OGRXPlane_ExtendPosition( dfLat, dfLon, dfLength / 2, dfTrueHeading,
+                              &dfAfterLat, &dfAfterLon);
 
-    OGRXPlane_ExtendPosition(dfBeforeLat, dfBeforeLon, dfWidth / 2, dfTrueHeading - 90, &adfLat[0], &adfLon[0]);
-    OGRXPlane_ExtendPosition(dfAfterLat, dfAfterLon, dfWidth / 2, dfTrueHeading - 90, &adfLat[1], &adfLon[1]);
-    OGRXPlane_ExtendPosition(dfAfterLat, dfAfterLon, dfWidth / 2, dfTrueHeading + 90, &adfLat[2], &adfLon[2]);
-    OGRXPlane_ExtendPosition(dfBeforeLat, dfBeforeLon, dfWidth / 2, dfTrueHeading + 90, &adfLat[3], &adfLon[3]);
+    OGRXPlane_ExtendPosition( dfBeforeLat, dfBeforeLon, dfWidth / 2,
+                              dfTrueHeading - 90, &adfLat[0], &adfLon[0]);
+    OGRXPlane_ExtendPosition( dfAfterLat, dfAfterLon, dfWidth / 2,
+                              dfTrueHeading - 90, &adfLat[1], &adfLon[1]);
+    OGRXPlane_ExtendPosition( dfAfterLat, dfAfterLon, dfWidth / 2,
+                              dfTrueHeading + 90, &adfLat[2], &adfLon[2]);
+    OGRXPlane_ExtendPosition( dfBeforeLat, dfBeforeLon, dfWidth / 2,
+                              dfTrueHeading + 90, &adfLat[3], &adfLon[3]);
 
     OGRLinearRing* linearRing = new OGRLinearRing();
     linearRing->setNumPoints(5);
-    int i;
-    for(i=0;i<4;i++)
+    for( int i=0; i<4; i++ )
         linearRing->setPoint(i, adfLon[i], adfLat[i]);
     linearRing->setPoint(4, adfLon[0], adfLat[0]);
     OGRPolygon* polygon = new OGRPolygon();
      polygon->addRingDirectly( linearRing );
     poFeature->SetGeometryDirectly( polygon );
 
+    int nCount = 0;
     poFeature->SetField( nCount++, pszAptICAO );
     poFeature->SetField( nCount++, pszHelipadNum );
     poFeature->SetField( nCount++, dfTrueHeading );
@@ -2696,31 +2724,36 @@ OGRFeature*
                                                 double dfSmoothness,
                                                 int bBlueEdgeLights)
 {
-    int nCount = 0;
     OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
 
     double dfBeforeLat, dfBeforeLon;
     double dfAfterLat, dfAfterLon;
     double adfLat[4], adfLon[4];
 
-    OGRXPlane_ExtendPosition(dfLat, dfLon, dfLength / 2, dfTrueHeading + 180, &dfBeforeLat, &dfBeforeLon);
-    OGRXPlane_ExtendPosition(dfLat, dfLon, dfLength / 2, dfTrueHeading, &dfAfterLat, &dfAfterLon);
+    OGRXPlane_ExtendPosition( dfLat, dfLon, dfLength / 2, dfTrueHeading + 180,
+                              &dfBeforeLat, &dfBeforeLon);
+    OGRXPlane_ExtendPosition( dfLat, dfLon, dfLength / 2, dfTrueHeading,
+                              &dfAfterLat, &dfAfterLon);
 
-    OGRXPlane_ExtendPosition(dfBeforeLat, dfBeforeLon, dfWidth / 2, dfTrueHeading - 90, &adfLat[0], &adfLon[0]);
-    OGRXPlane_ExtendPosition(dfAfterLat, dfAfterLon, dfWidth / 2, dfTrueHeading - 90, &adfLat[1], &adfLon[1]);
-    OGRXPlane_ExtendPosition(dfAfterLat, dfAfterLon, dfWidth / 2, dfTrueHeading + 90, &adfLat[2], &adfLon[2]);
-    OGRXPlane_ExtendPosition(dfBeforeLat, dfBeforeLon, dfWidth / 2, dfTrueHeading + 90, &adfLat[3], &adfLon[3]);
+    OGRXPlane_ExtendPosition( dfBeforeLat, dfBeforeLon, dfWidth / 2,
+                              dfTrueHeading - 90, &adfLat[0], &adfLon[0]);
+    OGRXPlane_ExtendPosition( dfAfterLat, dfAfterLon, dfWidth / 2,
+                              dfTrueHeading - 90, &adfLat[1], &adfLon[1]);
+    OGRXPlane_ExtendPosition( dfAfterLat, dfAfterLon, dfWidth / 2,
+                              dfTrueHeading + 90, &adfLat[2], &adfLon[2]);
+    OGRXPlane_ExtendPosition( dfBeforeLat, dfBeforeLon, dfWidth / 2,
+                              dfTrueHeading + 90, &adfLat[3], &adfLon[3]);
 
     OGRLinearRing* linearRing = new OGRLinearRing();
     linearRing->setNumPoints(5);
-    int i;
-    for(i=0;i<4;i++)
+    for( int i=0; i<4; i++ )
         linearRing->setPoint(i, adfLon[i], adfLat[i]);
     linearRing->setPoint(4, adfLon[0], adfLat[0]);
     OGRPolygon* polygon = new OGRPolygon();
      polygon->addRingDirectly( linearRing );
     poFeature->SetGeometryDirectly( polygon );
 
+    int nCount = 0;
     poFeature->SetField( nCount++, pszAptICAO );
     poFeature->SetField( nCount++, dfTrueHeading );
     poFeature->SetField( nCount++, dfLength );
@@ -2778,11 +2811,11 @@ OGRFeature*
                                         double dfTextureHeading,
                                         OGRPolygon* poPolygon)
 {
-    int nCount = 0;
     OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
 
     poFeature->SetGeometry( poPolygon );
 
+    int nCount = 0;
     poFeature->SetField( nCount++, pszAptICAO );
     poFeature->SetField( nCount++, pszPavementName );
     poFeature->SetField( nCount++, pszSurfaceType );
@@ -2801,7 +2834,8 @@ OGRFeature*
 /************************************************************************/
 
 
-OGRXPlaneAPTBoundaryLayer::OGRXPlaneAPTBoundaryLayer() : OGRXPlaneLayer("APTBoundary")
+OGRXPlaneAPTBoundaryLayer::OGRXPlaneAPTBoundaryLayer() :
+    OGRXPlaneLayer("APTBoundary")
 {
     poFeatureDefn->SetGeomType( wkbPolygon );
 
@@ -2823,11 +2857,11 @@ OGRFeature*
                                            const char* pszBoundaryName,
                                            OGRPolygon* poPolygon)
 {
-    int nCount = 0;
     OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
 
     poFeature->SetGeometry( poPolygon );
 
+    int nCount = 0;
     poFeature->SetField( nCount++, pszAptICAO );
     poFeature->SetField( nCount++, pszBoundaryName );
 
@@ -2841,7 +2875,8 @@ OGRFeature*
 /************************************************************************/
 
 
-OGRXPlaneAPTLinearFeatureLayer::OGRXPlaneAPTLinearFeatureLayer() : OGRXPlaneLayer("APTLinearFeature")
+OGRXPlaneAPTLinearFeatureLayer::OGRXPlaneAPTLinearFeatureLayer() :
+    OGRXPlaneLayer("APTLinearFeature")
 {
     poFeatureDefn->SetGeomType( wkbMultiLineString );
 
@@ -2859,15 +2894,16 @@ OGRXPlaneAPTLinearFeatureLayer::OGRXPlaneAPTLinearFeatureLayer() : OGRXPlaneLaye
 /************************************************************************/
 
 OGRFeature*
-     OGRXPlaneAPTLinearFeatureLayer::AddFeature(const char* pszAptICAO,
-                                                const char* pszLinearFeatureName,
-                                                OGRMultiLineString* poMultilineString)
+     OGRXPlaneAPTLinearFeatureLayer::AddFeature(
+    const char* pszAptICAO,
+    const char* pszLinearFeatureName,
+    OGRMultiLineString* poMultilineString )
 {
-    int nCount = 0;
     OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
 
     poFeature->SetGeometry( poMultilineString );
 
+    int nCount = 0;
     poFeature->SetField( nCount++, pszAptICAO );
     poFeature->SetField( nCount++, pszLinearFeatureName );
 
@@ -2929,7 +2965,8 @@ OGRFeature*
 /*                     OGRXPlaneStartupLocationLayer()                  */
 /************************************************************************/
 
-OGRXPlaneStartupLocationLayer::OGRXPlaneStartupLocationLayer() : OGRXPlaneLayer("StartupLocation")
+OGRXPlaneStartupLocationLayer::OGRXPlaneStartupLocationLayer() :
+    OGRXPlaneLayer("StartupLocation")
 {
     poFeatureDefn->SetGeomType( wkbPoint );
 
@@ -2974,7 +3011,8 @@ OGRFeature*
 /*                      OGRXPlaneAPTLightBeaconLayer()                  */
 /************************************************************************/
 
-OGRXPlaneAPTLightBeaconLayer::OGRXPlaneAPTLightBeaconLayer() : OGRXPlaneLayer("APTLightBeacon")
+OGRXPlaneAPTLightBeaconLayer::OGRXPlaneAPTLightBeaconLayer() :
+    OGRXPlaneLayer("APTLightBeacon")
 {
     poFeatureDefn->SetGeomType( wkbPoint );
 
@@ -3016,7 +3054,8 @@ OGRFeature*
 /*                        OGRXPlaneAPTWindsockLayer()                   */
 /************************************************************************/
 
-OGRXPlaneAPTWindsockLayer::OGRXPlaneAPTWindsockLayer() : OGRXPlaneLayer("APTWindsock")
+OGRXPlaneAPTWindsockLayer::OGRXPlaneAPTWindsockLayer() :
+    OGRXPlaneLayer("APTWindsock")
 {
     poFeatureDefn->SetGeomType( wkbPoint );
 
@@ -3060,7 +3099,8 @@ OGRFeature*
 /*                        OGRXPlaneTaxiwaySignLayer()                   */
 /************************************************************************/
 
-OGRXPlaneTaxiwaySignLayer::OGRXPlaneTaxiwaySignLayer() : OGRXPlaneLayer("TaxiwaySign")
+OGRXPlaneTaxiwaySignLayer::OGRXPlaneTaxiwaySignLayer() :
+    OGRXPlaneLayer("TaxiwaySign")
 {
     poFeatureDefn->SetGeomType( wkbPoint );
 
@@ -3111,7 +3151,8 @@ OGRFeature*
 /*                   OGRXPlane_VASI_PAPI_WIGWAG_Layer()                 */
 /************************************************************************/
 
-OGRXPlane_VASI_PAPI_WIGWAG_Layer::OGRXPlane_VASI_PAPI_WIGWAG_Layer() : OGRXPlaneLayer("VASI_PAPI_WIGWAG")
+OGRXPlane_VASI_PAPI_WIGWAG_Layer::OGRXPlane_VASI_PAPI_WIGWAG_Layer() :
+    OGRXPlaneLayer("VASI_PAPI_WIGWAG")
 {
     poFeatureDefn->SetGeomType( wkbPoint );
 
@@ -3168,7 +3209,8 @@ OGRFeature*
 /*                       OGRXPlaneTaxiLocationLayer()                   */
 /************************************************************************/
 
-OGRXPlaneTaxiLocationLayer::OGRXPlaneTaxiLocationLayer() : OGRXPlaneLayer("TaxiLocation")
+OGRXPlaneTaxiLocationLayer::OGRXPlaneTaxiLocationLayer() :
+    OGRXPlaneLayer("TaxiLocation")
 {
     poFeatureDefn->SetGeomType( wkbPoint );
 
@@ -3186,7 +3228,7 @@ OGRXPlaneTaxiLocationLayer::OGRXPlaneTaxiLocationLayer() : OGRXPlaneLayer("TaxiL
 
     OGRFieldDefn oFieldAirplaneTypes("airplane_types", OFTString );
     poFeatureDefn->AddFieldDefn( &oFieldAirplaneTypes );
-    
+
     OGRFieldDefn oFieldName("name", OFTString );
     poFeatureDefn->AddFieldDefn( &oFieldName );
 }
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.h b/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.h
index 97d13c9..0272247 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.h
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.h
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_XPLANE_APT_READER_H_INCLUDED
-#define _OGR_XPLANE_APT_READER_H_INCLUDED
+#ifndef OGR_XPLANE_APT_READER_H_INCLUDED
+#define OGR_XPLANE_APT_READER_H_INCLUDED
 
 #include "ogr_xplane.h"
 #include "ogr_xplane_reader.h"
@@ -142,7 +142,7 @@ static const sEnumerationElement runwayREILType[] =
     { 2, "Unidirectional" }
 };
 
-static const sEnumerationElement runwayVisualApproachPathIndicatorTypeV810[] = 
+static const sEnumerationElement runwayVisualApproachPathIndicatorTypeV810[] =
 {
     { 1, "None" },
     { 2, "VASI" },
@@ -290,7 +290,7 @@ class OGRXPlaneWaterRunwayLayer : public OGRXPlaneLayer
 static const sEnumerationElement helipadEdgeLigthingType[] =
 {
     { 0, "None" },
-    { 1, "Yellow" }, 
+    { 1, "Yellow" },
     { 2, "White" }, /* proposed for V90x */
     { 3, "Red" } /* proposed for V90x */
 };
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.cpp b/ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.cpp
index 1c46aef..dd0dc27 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.cpp
@@ -29,7 +29,7 @@
 
 #include "ogr_xplane_awy_reader.h"
 
-CPL_CVSID("$Id: ogr_xplane_awy_reader.cpp 27044 2014-03-16 23:41:27Z rouault $");
+CPL_CVSID("$Id: ogr_xplane_awy_reader.cpp 32431 2015-12-22 14:06:59Z goatbar $");
 
 /************************************************************************/
 /*                   OGRXPlaneCreateAwyFileReader                       */
@@ -93,7 +93,7 @@ OGRXPlaneReader* OGRXPlaneAwyReader::CloneForLayer(OGRXPlaneLayer* poLayer)
 
 int OGRXPlaneAwyReader::IsRecognizedVersion( const char* pszVersionString)
 {
-    return EQUALN(pszVersionString, "640 Version", 11);
+    return STARTS_WITH_CI(pszVersionString, "640 Version");
 }
 
 
@@ -142,29 +142,26 @@ void OGRXPlaneAwyReader::Read()
 /*                            ParseRecord()                             */
 /************************************************************************/
 
-void    OGRXPlaneAwyReader::ParseRecord()
+void OGRXPlaneAwyReader::ParseRecord()
 {
-    const char* pszFirstPointName;
-    const char* pszSecondPointName;
-    const char* pszAirwaySegmentName;
     double dfLat1, dfLon1;
     double dfLat2, dfLon2;
-    int bIsHigh;
-    int nBaseFL, nTopFL;
 
-    pszFirstPointName = papszTokens[0];
+    const char* pszFirstPointName = papszTokens[0];
     RET_IF_FAIL(readLatLon(&dfLat1, &dfLon1, 1));
-    pszSecondPointName = papszTokens[3];
+    const char* pszSecondPointName = papszTokens[3];
     RET_IF_FAIL(readLatLon(&dfLat2, &dfLon2, 4));
-    bIsHigh = atoi(papszTokens[6]) == 2;
-    nBaseFL = atoi(papszTokens[7]);
-    nTopFL = atoi(papszTokens[8]);
-    pszAirwaySegmentName = papszTokens[9];
+    const bool bIsHigh = atoi(papszTokens[6]) == 2;
+    const int nBaseFL = atoi(papszTokens[7]);
+    const int nTopFL = atoi(papszTokens[8]);
+    const char* pszAirwaySegmentName = papszTokens[9];
 
     if (poAirwayIntersectionLayer)
     {
-        poAirwayIntersectionLayer->AddFeature(pszFirstPointName, dfLat1, dfLon1);
-        poAirwayIntersectionLayer->AddFeature(pszSecondPointName, dfLat2, dfLon2);
+        poAirwayIntersectionLayer->AddFeature(pszFirstPointName,
+                                              dfLat1, dfLon1);
+        poAirwayIntersectionLayer->AddFeature(pszSecondPointName,
+                                              dfLat2, dfLon2);
     }
 
     if (poAirwaySegmentLayer)
@@ -178,7 +175,9 @@ void    OGRXPlaneAwyReader::ParseRecord()
 */
         if (strchr(pszAirwaySegmentName, '-'))
         {
-            char** papszSegmentNames = CSLTokenizeString2( pszAirwaySegmentName, "-", CSLT_HONOURSTRINGS );
+            char** papszSegmentNames
+                = CSLTokenizeString2( pszAirwaySegmentName, "-",
+                                      CSLT_HONOURSTRINGS );
             int i = 0;
             while(papszSegmentNames[i])
             {
@@ -249,7 +248,6 @@ OGRFeature*
                                              int    nBaseFL,
                                              int    nTopFL)
 {
-    int nCount = 0;
     OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
     if (fabs(dfLon1 - dfLon2) < 270)
     {
@@ -283,6 +281,8 @@ OGRFeature*
         multiLineString->addGeometryDirectly( lineString2 );
         poFeature->SetGeometryDirectly( multiLineString );
     }
+
+    int nCount = 0;
     poFeature->SetField( nCount++, pszAirwaySegmentName );
     poFeature->SetField( nCount++, pszFirstPointName );
     poFeature->SetField( nCount++, pszSecondPointName );
@@ -334,9 +334,12 @@ static unsigned long OGRXPlaneAirwayHashDouble(const double& dfVal)
 
 static unsigned long HashAirwayIntersectionFeatureFunc(const void* _feature)
 {
-    OGRFeature* feature = (OGRFeature*)_feature;
-    OGRPoint* point = (OGRPoint*) feature->GetGeometryRef();
-    unsigned long hash = CPLHashSetHashStr((unsigned char*)feature->GetFieldAsString(0));
+    OGRFeature* feature = reinterpret_cast<OGRFeature *>(
+        const_cast<void *>(_feature));
+    OGRPoint* point = reinterpret_cast<OGRPoint *>( feature->GetGeometryRef() );
+    unsigned long hash = CPLHashSetHashStr(
+        reinterpret_cast<unsigned char*>(const_cast<char *>(
+            feature->GetFieldAsString(0))));
     const double x = point->getX();
     const double y = point->getY();
     return hash ^ OGRXPlaneAirwayHashDouble(x) ^ OGRXPlaneAirwayHashDouble(y);
@@ -348,7 +351,7 @@ static unsigned long HashAirwayIntersectionFeatureFunc(const void* _feature)
 
 static void FreeAirwayIntersectionFeatureFunc(void* _feature)
 {
-    delete (OGRFeature*)_feature;
+    delete reinterpret_cast<OGRFeature*>(_feature);
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.h b/ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.h
index 78f07fa..60089e6 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.h
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.h
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_XPLANE_AWY_READER_H_INCLUDED
-#define _OGR_XPLANE_AWY_READER_H_INCLUDED
+#ifndef OGR_XPLANE_AWY_READER_H_INCLUDED
+#define OGR_XPLANE_AWY_READER_H_INCLUDED
 
 #include "ogr_xplane.h"
 #include "ogr_xplane_reader.h"
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.cpp b/ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.cpp
index 373128e..4575d29 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.cpp
@@ -29,7 +29,7 @@
 
 #include "ogr_xplane_fix_reader.h"
 
-CPL_CVSID("$Id: ogr_xplane_fix_reader.cpp 27044 2014-03-16 23:41:27Z rouault $");
+CPL_CVSID("$Id: ogr_xplane_fix_reader.cpp 31120 2015-10-24 19:55:09Z rouault $");
 
 /************************************************************************/
 /*                   OGRXPlaneCreateFixFileReader                       */
@@ -88,7 +88,7 @@ OGRXPlaneReader* OGRXPlaneFixReader::CloneForLayer(OGRXPlaneLayer* poLayer)
 
 int OGRXPlaneFixReader::IsRecognizedVersion( const char* pszVersionString)
 {
-    return EQUALN(pszVersionString, "600 Version", 11);
+    return STARTS_WITH_CI(pszVersionString, "600 Version");
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.h b/ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.h
index 8772eda..5d9ec3e 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.h
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.h
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_XPLANE_FIX_READER_H_INCLUDED
-#define _OGR_XPLANE_FIX_READER_H_INCLUDED
+#ifndef OGR_XPLANE_FIX_READER_H_INCLUDED
+#define OGR_XPLANE_FIX_READER_H_INCLUDED
 
 #include "ogr_xplane.h"
 #include "ogr_xplane_reader.h"
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_geo_utils.cpp b/ogr/ogrsf_frmts/xplane/ogr_xplane_geo_utils.cpp
index 2727322..a9b9a82 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_geo_utils.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_geo_utils.cpp
@@ -28,14 +28,9 @@
  ****************************************************************************/
 
 #include "ogr_xplane_geo_utils.h"
-#include <math.h>
 #include "cpl_port.h"
 
-CPL_CVSID("$Id: ogr_xplane_geo_utils.cpp 27044 2014-03-16 23:41:27Z rouault $");
-
-#ifndef M_PI
-# define M_PI  3.1415926535897932384626433832795
-#endif
+CPL_CVSID("$Id: ogr_xplane_geo_utils.cpp 30726 2015-09-27 17:25:12Z goatbar $");
 
 #define RAD2METER            ((180./M_PI)*60.*1852.)
 #define METER2RAD            (1/RAD2METER)
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_geo_utils.h b/ogr/ogrsf_frmts/xplane/ogr_xplane_geo_utils.h
index 3220fd8..620dd62 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_geo_utils.h
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_geo_utils.h
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_XPLANE_GEO_UTILS_H_INCLUDED
-#define _OGR_XPLANE_GEO_UTILS_H_INCLUDED
+#ifndef OGR_XPLANE_GEO_UTILS_H_INCLUDED
+#define OGR_XPLANE_GEO_UTILS_H_INCLUDED
 
 double OGRXPlane_Distance(double dfLatA_deg, double dfLonA_deg,
                           double dfLatB_deg, double dfLonB_deg);
@@ -41,4 +41,4 @@ int OGRXPlane_ExtendPosition(double dfLatA_deg, double dfLonA_deg,
                              double* pdfLatB_deg, double* pdfLonB_deg);
 
 
-#endif /* ndef _OGR_XPLANE_GEO_UTILS_H_INCLUDED */
+#endif /* ndef OGR_XPLANE_GEO_UTILS_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.cpp b/ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.cpp
index d7e4046..5422085 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.cpp
@@ -29,7 +29,7 @@
 
 #include "ogr_xplane_nav_reader.h"
 
-CPL_CVSID("$Id: ogr_xplane_nav_reader.cpp 29366 2015-06-16 17:17:49Z rouault $");
+CPL_CVSID("$Id: ogr_xplane_nav_reader.cpp 31120 2015-10-24 19:55:09Z rouault $");
 
 /************************************************************************/
 /*                   OGRXPlaneCreateNavFileReader                       */
@@ -112,8 +112,8 @@ OGRXPlaneReader* OGRXPlaneNavReader::CloneForLayer(OGRXPlaneLayer* poLayer)
 
 int OGRXPlaneNavReader::IsRecognizedVersion( const char* pszVersionString)
 {
-    return EQUALN(pszVersionString, "810 Version", 11) ||
-           EQUALN(pszVersionString, "740 Version", 11);
+    return STARTS_WITH_CI(pszVersionString, "810 Version") ||
+           STARTS_WITH_CI(pszVersionString, "740 Version");
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.h b/ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.h
index 45b6d9b..affb42b 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.h
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.h
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_XPLANE_NAV_READER_H_INCLUDED
-#define _OGR_XPLANE_NAV_READER_H_INCLUDED
+#ifndef OGR_XPLANE_NAV_READER_H_INCLUDED
+#define OGR_XPLANE_NAV_READER_H_INCLUDED
 
 #include "ogr_xplane.h"
 #include "ogr_xplane_reader.h"
@@ -176,10 +176,10 @@ class OGRXPlaneDMELayer : public OGRXPlaneLayer
 
 enum
 {
-    NAVAID_NDB            = 2, 
+    NAVAID_NDB            = 2,
     NAVAID_VOR            = 3, /* VOR, VORTAC or VOR-DME.*/
-    NAVAID_LOC_ILS        = 4, /* Localiser that is part of a full ILS */
-    NAVAID_LOC_STANDALONE = 5, /* Stand-alone localiser (LOC), also including a LDA (Landing Directional Aid) or SDF (Simplified Directional Facility) */
+    NAVAID_LOC_ILS        = 4, /* Localizer that is part of a full ILS */
+    NAVAID_LOC_STANDALONE = 5, /* Stand-alone Localizer (LOC), also including a LDA (Landing Directional Aid) or SDF (Simplified Directional Facility) */
     NAVAID_GS             = 6, /* Glideslope */
     NAVAID_OM             = 7, /* Outer marker */
     NAVAID_MM             = 8, /* Middle marker */
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.cpp b/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.cpp
index 40aa20a..2bc03d3 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_xplane_reader.cpp 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: ogr_xplane_reader.cpp 32381 2015-12-20 21:37:32Z goatbar $
  *
  * Project:  X-Plane aeronautical data reader
  * Purpose:  Definition of classes for OGR X-Plane aeronautical data driver.
@@ -31,7 +31,7 @@
 
 #include "ogr_xplane_reader.h"
 
-CPL_CVSID("$Id: ogr_xplane_reader.cpp 27044 2014-03-16 23:41:27Z rouault $");
+CPL_CVSID("$Id: ogr_xplane_reader.cpp 32381 2015-12-20 21:37:32Z goatbar $");
 
 /***********************************************************************/
 /*                       OGRXPlaneReader()                             */
@@ -69,9 +69,9 @@ OGRXPlaneReader::~OGRXPlaneReader()
 /*                         StartParsing()                               */
 /************************************************************************/
 
-int OGRXPlaneReader::StartParsing( const char * pszFilename )
+int OGRXPlaneReader::StartParsing( const char * pszFilenameIn )
 {
-    fp = VSIFOpenL( pszFilename, "rb" );
+    fp = VSIFOpenL( pszFilenameIn, "rb" );
     if (fp == NULL)
         return FALSE;
 
@@ -95,7 +95,7 @@ int OGRXPlaneReader::StartParsing( const char * pszFilename )
     }
 
     CPLFree(this->pszFilename);
-    this->pszFilename = CPLStrdup(pszFilename);
+    this->pszFilename = CPLStrdup(pszFilenameIn);
 
     nLineNumber = 2;
     CPLDebug("XPlane", "Version/Copyright : %s", pszLine);
@@ -230,7 +230,6 @@ CPLString OGRXPlaneReader::readStringUntilEnd(int iFirstTokenIndice)
     CPLString osResult;
     if (nTokens > iFirstTokenIndice)
     {
-        int i;
         int nIDsToSum = nTokens - iFirstTokenIndice;
         const unsigned char* pszStr = (const unsigned char*)papszTokens[iFirstTokenIndice];
         for(int j=0;pszStr[j];j++)
@@ -240,7 +239,7 @@ CPLString OGRXPlaneReader::readStringUntilEnd(int iFirstTokenIndice)
             else
                 CPLDebug("XPlane", "Line %d : string with non ASCII characters", nLineNumber);
         }
-        for(i=1;i<nIDsToSum;i++)
+        for( int i=1; i < nIDsToSum; i++ )
         {
             osResult += " ";
             pszStr = (const unsigned char*)papszTokens[iFirstTokenIndice + i];
@@ -305,8 +304,7 @@ OGRXPlaneEnumeration::OGRXPlaneEnumeration(const char *pszEnumerationName,
 
 const char* OGRXPlaneEnumeration::GetText(int eValue)
 {
-    int i;
-    for(i=0;i<m_nElements;i++)
+    for( int i=0; i < m_nElements; i++ )
     {
         if (m_osElements[i].eValue == eValue)
             return m_osElements[i].pszText;
@@ -322,10 +320,9 @@ const char* OGRXPlaneEnumeration::GetText(int eValue)
 
 int OGRXPlaneEnumeration::GetValue(const char* pszText)
 {
-    int i;
     if (pszText != NULL)
     {
-        for(i=0;i<m_nElements;i++)
+        for( int i=0; i < m_nElements; i++ )
         {
             if (strcmp(m_osElements[i].pszText, pszText) == 0)
                 return m_osElements[i].eValue;
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.h b/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.h
index 5bbb7ef..2d42863 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.h
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.h
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OGR_XPLANE_READER_H_INCLUDED
-#define _OGR_XPLANE_READER_H_INCLUDED
+#ifndef OGR_XPLANE_READER_H_INCLUDED
+#define OGR_XPLANE_READER_H_INCLUDED
 
 #include "cpl_port.h"
 #include "cpl_string.h"
diff --git a/ogr/ogrsf_frmts/xplane/ogrxplanedatasource.cpp b/ogr/ogrsf_frmts/xplane/ogrxplanedatasource.cpp
index 0442ed7..59b102e 100644
--- a/ogr/ogrsf_frmts/xplane/ogrxplanedatasource.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogrxplanedatasource.cpp
@@ -30,7 +30,7 @@
 #include "ogr_xplane.h"
 #include "ogr_xplane_reader.h"
 
-CPL_CVSID("$Id: ogrxplanedatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogrxplanedatasource.cpp 32371 2015-12-20 20:05:48Z goatbar $");
 
 /************************************************************************/
 /*                          OGRXPlaneDataSource()                          */
@@ -109,12 +109,12 @@ void OGRXPlaneDataSource::RegisterLayer(OGRXPlaneLayer* poLayer)
 /*                                Open()                                */
 /************************************************************************/
 
-int OGRXPlaneDataSource::Open( const char * pszFilename, int bReadWholeFile )
+int OGRXPlaneDataSource::Open( const char * pszFilename, int bReadWholeFileIn )
 
 {
     Reset();
 
-    this->bReadWholeFile = bReadWholeFile;
+    this->bReadWholeFile = bReadWholeFileIn;
 
     const char* pszShortFilename = CPLGetFilename(pszFilename);
     if (EQUAL(pszShortFilename, "nav.dat") ||
@@ -137,7 +137,6 @@ int OGRXPlaneDataSource::Open( const char * pszFilename, int bReadWholeFile )
         poReader = OGRXPlaneCreateAwyFileReader(this);
     }
 
-    int bRet;
     if (poReader && poReader->StartParsing(pszFilename) == FALSE)
     {
         delete poReader;
@@ -152,12 +151,10 @@ int OGRXPlaneDataSource::Open( const char * pszFilename, int bReadWholeFile )
             for( int i = 0; i < nLayers; i++ )
                 papoLayers[i]->SetReader(poReader->CloneForLayer(papoLayers[i]));
         }
-        bRet = TRUE;
+        return true;
     }
-    else
-        bRet = FALSE;
 
-    return bRet;
+    return false;
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/xplane/ogrxplanedriver.cpp b/ogr/ogrsf_frmts/xplane/ogrxplanedriver.cpp
index 131e706..21e82cc 100644
--- a/ogr/ogrsf_frmts/xplane/ogrxplanedriver.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogrxplanedriver.cpp
@@ -57,7 +57,8 @@ OGRDataSource *OGRXPlaneDriver::Open( const char * pszFilename, int bUpdate )
 
     OGRXPlaneDataSource   *poDS = new OGRXPlaneDataSource();
 
-    int bReadWholeFile = CSLTestBoolean(CPLGetConfigOption("OGR_XPLANE_READ_WHOLE_FILE", "TRUE"));
+    bool bReadWholeFile = CPLTestBool(
+        CPLGetConfigOption("OGR_XPLANE_READ_WHOLE_FILE", "TRUE"));
 
     if( !poDS->Open( pszFilename, bReadWholeFile ) )
     {
@@ -85,11 +86,12 @@ void RegisterOGRXPlane()
 
 {
     OGRSFDriver* poDriver = new OGRXPlaneDriver;
+
     poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                "X-Plane/Flightgear aeronautical data" );
+                               "X-Plane/Flightgear aeronautical data" );
     poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "dat" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                "drv_xplane.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_xplane.html" );
     poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver(poDriver);
+
+    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/xplane/ogrxplanelayer.cpp b/ogr/ogrsf_frmts/xplane/ogrxplanelayer.cpp
index a742dbf..bf8fb8a 100644
--- a/ogr/ogrsf_frmts/xplane/ogrxplanelayer.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogrxplanelayer.cpp
@@ -31,7 +31,7 @@
 #include "ogr_xplane_geo_utils.h"
 #include "ogr_xplane_reader.h"
 
-CPL_CVSID("$Id: ogrxplanelayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrxplanelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 /************************************************************************/
 /*                            OGRXPlaneLayer()                          */
@@ -113,13 +113,13 @@ void OGRXPlaneLayer::ResetReading()
 /*                            SetReader()                               */
 /************************************************************************/
 
-void OGRXPlaneLayer::SetReader(OGRXPlaneReader* poReader)
+void OGRXPlaneLayer::SetReader(OGRXPlaneReader* poReaderIn)
 {
     if (this->poReader)
     {
         delete this->poReader;
     }
-    this->poReader = poReader;
+    this->poReader = poReaderIn;
 }
 
 /************************************************************************/
@@ -146,7 +146,7 @@ void  OGRXPlaneLayer::AutoAdjustColumnsWidth()
                 int nMaxLen = 0;
                 for(int i=0;i<nFeatureArraySize;i++)
                 {
-                    int nLen = strlen(papoFeatures[i]->GetFieldAsString(col));
+                    int nLen = static_cast<int>(strlen(papoFeatures[i]->GetFieldAsString(col)));
                     if (nLen > nMaxLen)
                         nMaxLen = nLen;
                 }
@@ -171,7 +171,7 @@ OGRFeature *OGRXPlaneLayer::GetNextFeature()
 
     if (poReader)
     {
-        while(TRUE)
+        while( true )
         {
             if ( nFeatureArrayIndex == nFeatureArraySize)
             {
@@ -213,7 +213,7 @@ OGRFeature *OGRXPlaneLayer::GetNextFeature()
               || FilterGeometry( poFeature->GetGeometryRef() ) )
             && (m_poAttrQuery == NULL
                 || m_poAttrQuery->Evaluate( poFeature )) )
-        {   
+        {
                 return poFeature->Clone();
         }
     }
@@ -225,16 +225,16 @@ OGRFeature *OGRXPlaneLayer::GetNextFeature()
 /*                           GetFeature()                               */
 /************************************************************************/
 
-OGRFeature *  OGRXPlaneLayer::GetFeature( GIntBig nFID )
+OGRFeature *  OGRXPlaneLayer::GetFeature( GIntBig nFIDIn )
 {
     if (poReader)
-        return OGRLayer::GetFeature(nFID);
+        return OGRLayer::GetFeature(nFIDIn);
     else
         poDS->ReadWholeFileIfNecessary();
 
-    if (nFID >= 0 && nFID < nFeatureArraySize)
+    if (nFIDIn >= 0 && nFIDIn < nFeatureArraySize)
     {
-        return papoFeatures[nFID]->Clone();
+        return papoFeatures[nFIDIn]->Clone();
     }
     else
     {
@@ -290,7 +290,7 @@ int  OGRXPlaneLayer::TestCapability( const char * pszCap )
         if (poReader == NULL && m_poFilterGeom == NULL && m_poAttrQuery == NULL)
             return TRUE;
     }
-            
+
     return FALSE;
 }
 
@@ -333,7 +333,7 @@ OGRFeatureDefn * OGRXPlaneLayer::GetLayerDefn()
 /*                        SetDataSource()                               */
 /************************************************************************/
 
-void OGRXPlaneLayer::SetDataSource(OGRXPlaneDataSource* poDS)
+void OGRXPlaneLayer::SetDataSource(OGRXPlaneDataSource* poDSIn)
 {
-    this->poDS = poDS;
+    this->poDS = poDSIn;
 }
diff --git a/ogr/ogrsf_frmts/xplane/test_geo_utils.cpp b/ogr/ogrsf_frmts/xplane/test_geo_utils.cpp
index 3bc62f6..85b9adc 100644
--- a/ogr/ogrsf_frmts/xplane/test_geo_utils.cpp
+++ b/ogr/ogrsf_frmts/xplane/test_geo_utils.cpp
@@ -8,13 +8,13 @@ int main(int argc, char* argv[])
   double latC, lonC;
   double heading;
   double distance;
-  
+
   heading = OGRXPlane_Track(latA, lonA, latB, lonB);
   distance = OGRXPlane_Distance(latA, lonA, latB, lonB);
   OGRXPlane_ExtendPosition(latA, lonA, distance, heading, &latC, &lonC);
   printf("heading=%f, distance=%f\n", heading, distance);
   printf("%.15f=%.15f, %.15f=%.15f\n", latB, latC, lonB, lonC);
-  
+
   heading = OGRXPlane_Track(latB, lonB, latA, lonA);
   distance = OGRXPlane_Distance(latB, lonB, latA, lonA);
   OGRXPlane_ExtendPosition(latB, lonB, distance, heading, &latC, &lonC);
diff --git a/ogr/ogrspatialreference.cpp b/ogr/ogrspatialreference.cpp
index 44627fa..d19030b 100644
--- a/ogr/ogrspatialreference.cpp
+++ b/ogr/ogrspatialreference.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrspatialreference.cpp 29104 2015-05-02 01:44:39Z rouault $
+ * $Id: ogrspatialreference.cpp 33432 2016-02-12 01:11:41Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRSpatialReference class.
@@ -28,49 +28,52 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_spatialref.h"
-#include "ogr_p.h"
+#include "cpl_atomic_ops.h"
 #include "cpl_csv.h"
 #include "cpl_http.h"
-#include "cpl_atomic_ops.h"
 #include "cpl_multiproc.h"
+#include "ogr_p.h"
+#include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: ogrspatialreference.cpp 29104 2015-05-02 01:44:39Z rouault $");
+CPL_CVSID("$Id: ogrspatialreference.cpp 33432 2016-02-12 01:11:41Z goatbar $");
 
 // The current opinion is that WKT longitudes like central meridian
-// should be relative to greenwich, not the prime meridian in use. 
+// should be relative to Greenwich, not the prime meridian in use.
 // Define the following if they should be relative to the prime meridian
 // of then geogcs.
 #undef WKT_LONGITUDE_RELATIVE_TO_PM
 
 /************************************************************************/
-/*                           OGRPrintDouble()                           */
+/*                           OGRsnPrintDouble()                         */
 /************************************************************************/
 
-void OGRPrintDouble( char * pszStrBuf, double dfValue )
+void OGRsnPrintDouble( char * pszStrBuf, size_t size, double dfValue );
+
+void OGRsnPrintDouble( char * pszStrBuf, size_t size, double dfValue )
 
 {
-    CPLsprintf( pszStrBuf, "%.16g", dfValue );
+    CPLsnprintf( pszStrBuf, size, "%.16g", dfValue );
 
-    int nLen = strlen(pszStrBuf);
+    const size_t nLen = strlen(pszStrBuf);
 
     // The following hack is intended to truncate some "precision" in cases
-    // that appear to be roundoff error. 
-    if( nLen > 15 
+    // that appear to be roundoff error.
+    if( nLen > 15
         && (strcmp(pszStrBuf+nLen-6,"999999") == 0
             || strcmp(pszStrBuf+nLen-6,"000001") == 0) )
     {
-        CPLsprintf( pszStrBuf, "%.15g", dfValue );
+        CPLsnprintf( pszStrBuf, size, "%.15g", dfValue );
     }
 
-    // force to user periods regardless of locale.
+    // Force to user periods regardless of locale.
     if( strchr( pszStrBuf, ',' ) != NULL )
     {
-        char *pszDelim = strchr( pszStrBuf, ',' );
+        char * const pszDelim = strchr( pszStrBuf, ',' );
         *pszDelim = '.';
     }
 }
 
+
 /************************************************************************/
 /*                        OGRSpatialReference()                         */
 /************************************************************************/
@@ -82,22 +85,23 @@ void OGRPrintDouble( char * pszStrBuf, double dfValue )
  * should be a WKT representation of an SRS.  Passing this is equivalent
  * to not passing it, and then calling importFromWkt() with the WKT string.
  *
- * Note that newly created objects are given a reference count of one. 
+ * Note that newly created objects are given a reference count of one.
  *
  * The C function OSRNewSpatialReference() does the same thing as this
- * constructor. 
+ * constructor.
  *
  * @param pszWKT well known text definition to which the object should
- * be initialized, or NULL (the default). 
+ * be initialized, or NULL (the default).
  */
 
-OGRSpatialReference::OGRSpatialReference( const char * pszWKT )
-
+OGRSpatialReference::OGRSpatialReference( const char * pszWKT ) :
+    dfFromGreenwich(0.0),
+    dfToMeter(0.0),
+    dfToDegrees(0.0),
+    poRoot(NULL),
+    nRefCount(1),
+    bNormInfoSet(FALSE)
 {
-    bNormInfoSet = FALSE;
-    nRefCount = 1;
-    poRoot = NULL;
-
     if( pszWKT != NULL )
         importFromWkt( (char **) &pszWKT );
 }
@@ -114,9 +118,7 @@ OGRSpatialReference::OGRSpatialReference( const char * pszWKT )
 OGRSpatialReferenceH CPL_STDCALL OSRNewSpatialReference( const char *pszWKT )
 
 {
-    OGRSpatialReference * poSRS;
-
-    poSRS = new OGRSpatialReference();
+    OGRSpatialReference * poSRS = new OGRSpatialReference();
 
     if( pszWKT != NULL && strlen(pszWKT) > 0 )
     {
@@ -127,7 +129,7 @@ OGRSpatialReferenceH CPL_STDCALL OSRNewSpatialReference( const char *pszWKT )
         }
     }
 
-    return (OGRSpatialReferenceH) poSRS;
+    return reinterpret_cast<OGRSpatialReferenceH>( poSRS );
 }
 
 /************************************************************************/
@@ -136,13 +138,14 @@ OGRSpatialReferenceH CPL_STDCALL OSRNewSpatialReference( const char *pszWKT )
 /*      Simple copy constructor.  See also Clone().                     */
 /************************************************************************/
 
-OGRSpatialReference::OGRSpatialReference(const OGRSpatialReference &oOther)
-
+OGRSpatialReference::OGRSpatialReference(const OGRSpatialReference &oOther) :
+    dfFromGreenwich(0.0),
+    dfToMeter(0.0),
+    dfToDegrees(0.0),
+    poRoot(NULL),
+    nRefCount(1),
+    bNormInfoSet(FALSE)
 {
-    bNormInfoSet = FALSE;
-    nRefCount = 1;
-    poRoot = NULL;
-
     if( oOther.poRoot != NULL )
         poRoot = oOther.poRoot->Clone();
 }
@@ -152,10 +155,10 @@ OGRSpatialReference::OGRSpatialReference(const OGRSpatialReference &oOther)
 /************************************************************************/
 
 /**
- * \brief OGRSpatialReference destructor. 
+ * \brief OGRSpatialReference destructor.
  *
  * The C function OSRDestroySpatialReference() does the same thing as this
- * method. Preferred C++ method : OGRSpatialReference::DestroySpatialReference() 
+ * method. Preferred C++ method : OGRSpatialReference::DestroySpatialReference()
   *
  * @deprecated
  */
@@ -172,12 +175,12 @@ OGRSpatialReference::~OGRSpatialReference()
 /************************************************************************/
 
 /**
- * \brief OGRSpatialReference destructor. 
+ * \brief OGRSpatialReference destructor.
  *
  * This static method will destroy a OGRSpatialReference.  It is
  * equivalent to calling delete on the object, but it ensures that the
  * deallocation is properly executed within the OGR libraries heap on
- * platforms where this can matter (win32).  
+ * platforms where this can matter (win32).
  *
  * This function is the same as OSRDestroySpatialReference()
  *
@@ -185,7 +188,7 @@ OGRSpatialReference::~OGRSpatialReference()
  *
  * @since GDAL 1.7.0
  */
- 
+
 void OGRSpatialReference::DestroySpatialReference(OGRSpatialReference* poSRS)
 {
     delete poSRS;
@@ -196,7 +199,7 @@ void OGRSpatialReference::DestroySpatialReference(OGRSpatialReference* poSRS)
 /************************************************************************/
 
 /**
- * \brief OGRSpatialReference destructor. 
+ * \brief OGRSpatialReference destructor.
  *
  * This function is the same as OGRSpatialReference::~OGRSpatialReference()
  * and OGRSpatialReference::DestroySpatialReference()
@@ -206,7 +209,7 @@ void OGRSpatialReference::DestroySpatialReference(OGRSpatialReference* poSRS)
 void CPL_STDCALL OSRDestroySpatialReference( OGRSpatialReferenceH hSRS )
 
 {
-    delete ((OGRSpatialReference *) hSRS);
+    delete reinterpret_cast<OGRSpatialReference *>(hSRS);
 }
 
 /************************************************************************/
@@ -216,7 +219,7 @@ void CPL_STDCALL OSRDestroySpatialReference( OGRSpatialReferenceH hSRS )
 /**
  * \brief Wipe current definition.
  *
- * Returns OGRSpatialReference to a state with no definition, as it 
+ * Returns OGRSpatialReference to a state with no definition, as it
  * exists when first created.  It does not affect reference counts.
  */
 
@@ -243,7 +246,7 @@ OGRSpatialReference::operator=(const OGRSpatialReference &oSource)
 
 {
     Clear();
-    
+
     if( oSource.poRoot != NULL )
         poRoot = oSource.poRoot->Clone();
 
@@ -260,7 +263,7 @@ OGRSpatialReference::operator=(const OGRSpatialReference &oSource)
  * The reference count is used keep track of the number of OGRGeometry objects
  * referencing this SRS.
  *
- * The method does the same thing as the C function OSRReference(). 
+ * The method does the same thing as the C function OSRReference().
  *
  * @return the updated reference count.
  */
@@ -285,7 +288,7 @@ int OSRReference( OGRSpatialReferenceH hSRS )
 {
     VALIDATE_POINTER1( hSRS, "OSRReference", 0 );
 
-    return ((OGRSpatialReference *) hSRS)->Reference();
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->Reference();
 }
 
 /************************************************************************/
@@ -295,7 +298,7 @@ int OSRReference( OGRSpatialReferenceH hSRS )
 /**
  * \brief Decrements the reference count by one.
  *
- * The method does the same thing as the C function OSRDereference(). 
+ * The method does the same thing as the C function OSRDereference().
  *
  * @return the updated reference count.
  */
@@ -304,9 +307,9 @@ int OGRSpatialReference::Dereference()
 
 {
     if( nRefCount <= 0 )
-        CPLDebug( "OSR", 
+        CPLDebug( "OSR",
                   "Dereference() called on an object with refcount %d,"
-                  "likely already destroyed!", 
+                  "likely already destroyed!",
                   nRefCount );
     return CPLAtomicDec(&nRefCount);
 }
@@ -325,7 +328,7 @@ int OSRDereference( OGRSpatialReferenceH hSRS )
 {
     VALIDATE_POINTER1( hSRS, "OSRDereference", 0 );
 
-    return ((OGRSpatialReference *) hSRS)->Dereference();
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->Dereference();
 }
 
 /************************************************************************/
@@ -347,7 +350,7 @@ int OSRDereference( OGRSpatialReferenceH hSRS )
 /**
  * \brief Decrements the reference count by one, and destroy if zero.
  *
- * The method does the same thing as the C function OSRRelease(). 
+ * The method does the same thing as the C function OSRRelease().
  */
 
 void OGRSpatialReference::Release()
@@ -355,7 +358,7 @@ void OGRSpatialReference::Release()
 {
     CPLAssert( NULL != this );
 
-    if( Dereference() <= 0 ) 
+    if( Dereference() <= 0 )
         delete this;
 }
 
@@ -373,7 +376,7 @@ void OSRRelease( OGRSpatialReferenceH hSRS )
 {
     VALIDATE_POINTER0( hSRS, "OSRRelease" );
 
-    ((OGRSpatialReference *) hSRS)->Release();
+    reinterpret_cast<OGRSpatialReference *>(hSRS)->Release();
 }
 
 /************************************************************************/
@@ -413,7 +416,7 @@ void OGRSpatialReference::SetRoot( OGR_SRSNode * poNewRoot )
  *
  * If a node appears more than once in the tree (such as UNIT for instance),
  * the first encountered will be returned.  Use GetNode() on a subtree to be
- * more specific. 
+ * more specific.
  *
  * @param pszNodePath the name of the node to search for.  May contain multiple
  * components such as "GEOGCS|UNIT".
@@ -424,10 +427,8 @@ void OGRSpatialReference::SetRoot( OGR_SRSNode * poNewRoot )
 OGR_SRSNode *OGRSpatialReference::GetAttrNode( const char * pszNodePath )
 
 {
-    char        **papszPathTokens;
-    OGR_SRSNode *poNode;
-
-    papszPathTokens = CSLTokenizeStringComplex(pszNodePath, "|", TRUE, FALSE);
+    char **papszPathTokens =
+        CSLTokenizeStringComplex(pszNodePath, "|", TRUE, FALSE);
 
     if( CSLCount( papszPathTokens ) < 1 )
     {
@@ -435,7 +436,7 @@ OGR_SRSNode *OGRSpatialReference::GetAttrNode( const char * pszNodePath )
         return NULL;
     }
 
-    poNode = GetRoot();
+    OGR_SRSNode *poNode = GetRoot();
     for( int i = 0; poNode != NULL && papszPathTokens[i] != NULL; i++ )
     {
         poNode = poNode->GetNode( papszPathTokens[i] );
@@ -450,9 +451,8 @@ const OGR_SRSNode *
 OGRSpatialReference::GetAttrNode( const char * pszNodePath ) const
 
 {
-    OGR_SRSNode *poNode;
-
-    poNode = ((OGRSpatialReference *) this)->GetAttrNode(pszNodePath);
+    OGR_SRSNode *poNode =
+        const_cast<OGRSpatialReference *>(this)->GetAttrNode(pszNodePath);
 
     return poNode;
 }
@@ -474,16 +474,14 @@ OGRSpatialReference::GetAttrNode( const char * pszNodePath ) const
  * @param pszNodeName the tree node to look for (case insensitive).
  * @param iAttr the child of the node to fetch (zero based).
  *
- * @return the requested value, or NULL if it fails for any reason. 
+ * @return the requested value, or NULL if it fails for any reason.
  */
 
 const char *OGRSpatialReference::GetAttrValue( const char * pszNodeName,
                                                int iAttr ) const
 
 {
-    const OGR_SRSNode *poNode;
-
-    poNode = GetAttrNode( pszNodeName );
+    const OGR_SRSNode *poNode = GetAttrNode( pszNodeName );
     if( poNode == NULL )
         return NULL;
 
@@ -508,7 +506,8 @@ const char * CPL_STDCALL OSRGetAttrValue( OGRSpatialReferenceH hSRS,
 {
     VALIDATE_POINTER1( hSRS, "OSRGetAttrValue", NULL );
 
-    return ((OGRSpatialReference *) hSRS)->GetAttrValue( pszKey, iChild );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
+        GetAttrValue( pszKey, iChild );
 }
 
 /************************************************************************/
@@ -526,9 +525,7 @@ const char * CPL_STDCALL OSRGetAttrValue( OGRSpatialReferenceH hSRS,
 OGRSpatialReference *OGRSpatialReference::Clone() const
 
 {
-    OGRSpatialReference *poNewRef;
-
-    poNewRef = new OGRSpatialReference();
+    OGRSpatialReference *poNewRef = new OGRSpatialReference();
 
     if( poRoot != NULL )
         poNewRef->poRoot = poRoot->Clone();
@@ -550,7 +547,8 @@ OGRSpatialReferenceH CPL_STDCALL OSRClone( OGRSpatialReferenceH hSRS )
 {
     VALIDATE_POINTER1( hSRS, "OSRClone", NULL );
 
-    return (OGRSpatialReferenceH) ((OGRSpatialReference *) hSRS)->Clone();
+    return reinterpret_cast<OGRSpatialReferenceH>(
+        reinterpret_cast<OGRSpatialReference *>(hSRS)->Clone() );
 }
 
 /************************************************************************/
@@ -574,7 +572,7 @@ void OGRSpatialReference::dumpReadable()
 /************************************************************************/
 
 /**
- * Convert this SRS into a a nicely formatted WKT string for display to a person.
+ * Convert this SRS into a nicely formatted WKT string for display to a person.
  *
  * Note that the returned WKT string should be freed with OGRFree() or
  * CPLFree() when no longer needed.  It is the responsibility of the caller.
@@ -582,13 +580,14 @@ void OGRSpatialReference::dumpReadable()
  * This method is the same as the C function OSRExportToPrettyWkt().
  *
  * @param ppszResult the resulting string is returned in this pointer.
- * @param bSimplify TRUE if the AXIS, AUTHORITY and EXTENSION nodes should be stripped off
+ * @param bSimplify TRUE if the AXIS, AUTHORITY and EXTENSION nodes should be
+ *   stripped off.
  *
  * @return currently OGRERR_NONE is always returned, but the future it
- * is possible error conditions will develop. 
+ * is possible error conditions will develop.
  */
 
-OGRErr OGRSpatialReference::exportToPrettyWkt( char ** ppszResult, 
+OGRErr OGRSpatialReference::exportToPrettyWkt( char ** ppszResult,
                                                int bSimplify ) const
 
 {
@@ -601,17 +600,17 @@ OGRErr OGRSpatialReference::exportToPrettyWkt( char ** ppszResult,
     if( bSimplify )
     {
         OGRSpatialReference *poSimpleClone = Clone();
-        OGRErr eErr;
 
         poSimpleClone->GetRoot()->StripNodes( "AXIS" );
         poSimpleClone->GetRoot()->StripNodes( "AUTHORITY" );
         poSimpleClone->GetRoot()->StripNodes( "EXTENSION" );
-        eErr = poSimpleClone->GetRoot()->exportToPrettyWkt( ppszResult, 1 );
+        const OGRErr eErr =
+            poSimpleClone->GetRoot()->exportToPrettyWkt( ppszResult, 1 );
         delete poSimpleClone;
         return eErr;
     }
-    else
-        return poRoot->exportToPrettyWkt( ppszResult, 1 );
+
+    return poRoot->exportToPrettyWkt( ppszResult, 1 );
 }
 
 /************************************************************************/
@@ -620,7 +619,8 @@ OGRErr OGRSpatialReference::exportToPrettyWkt( char ** ppszResult,
 
 
 /**
- * \brief Convert this SRS into a a nicely formatted WKT string for display to a person.
+ * \brief Convert this SRS into a nicely formatted WKT string for display to a
+ * person.
  *
  * This function is the same as OGRSpatialReference::exportToPrettyWkt().
  */
@@ -629,12 +629,12 @@ OGRErr CPL_STDCALL OSRExportToPrettyWkt( OGRSpatialReferenceH hSRS, char ** ppsz
                              int bSimplify)
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRExportToPrettyWkt", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRExportToPrettyWkt", OGRERR_FAILURE );
 
     *ppszReturn = NULL;
 
-    return ((OGRSpatialReference *) hSRS)->exportToPrettyWkt( ppszReturn,
-                                                              bSimplify );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
+        exportToPrettyWkt( ppszReturn, bSimplify );
 }
 
 /************************************************************************/
@@ -652,9 +652,9 @@ OGRErr CPL_STDCALL OSRExportToPrettyWkt( OGRSpatialReferenceH hSRS, char ** ppsz
  * @param ppszResult the resulting string is returned in this pointer.
  *
  * @return currently OGRERR_NONE is always returned, but the future it
- * is possible error conditions will develop. 
+ * is possible error conditions will develop.
  */
- 
+
 OGRErr OGRSpatialReference::exportToWkt( char ** ppszResult ) const
 
 {
@@ -663,17 +663,15 @@ OGRErr OGRSpatialReference::exportToWkt( char ** ppszResult ) const
         *ppszResult = CPLStrdup("");
         return OGRERR_NONE;
     }
-    else
-    {
-        return poRoot->exportToWkt(ppszResult);
-    }
+
+    return poRoot->exportToWkt(ppszResult);
 }
 
 /************************************************************************/
 /*                           OSRExportToWkt()                           */
 /************************************************************************/
 
-/** 
+/**
  * \brief Convert this SRS into WKT format.
  *
  * This function is the same as OGRSpatialReference::exportToWkt().
@@ -683,11 +681,11 @@ OGRErr CPL_STDCALL OSRExportToWkt( OGRSpatialReferenceH hSRS,
                                    char ** ppszReturn )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRExportToWkt", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRExportToWkt", OGRERR_FAILURE );
 
     *ppszReturn = NULL;
 
-    return ((OGRSpatialReference *) hSRS)->exportToWkt( ppszReturn );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->exportToWkt( ppszReturn );
 }
 
 /************************************************************************/
@@ -722,7 +720,7 @@ OGRErr OGRSpatialReference::importFromWkt( char ** ppszInput )
 
     poRoot = new OGR_SRSNode();
 
-    OGRErr eErr = poRoot->importFromWkt( ppszInput ); 
+    OGRErr eErr = poRoot->importFromWkt( ppszInput );
     if (eErr != OGRERR_NONE)
         return eErr;
 
@@ -758,9 +756,9 @@ OGRErr OGRSpatialReference::importFromWkt( char ** ppszInput )
 OGRErr OSRImportFromWkt( OGRSpatialReferenceH hSRS, char **ppszInput )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRImportFromWkt", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRImportFromWkt", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->importFromWkt( ppszInput );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->importFromWkt( ppszInput );
 }
 
 /************************************************************************/
@@ -771,44 +769,44 @@ OGRErr OSRImportFromWkt( OGRSpatialReferenceH hSRS, char **ppszInput )
  * \brief Set attribute value in spatial reference.
  *
  * Missing intermediate nodes in the path will be created if not already
- * in existance.  If the attribute has no children one will be created and
+ * in existence.  If the attribute has no children one will be created and
  * assigned the value otherwise the zeroth child will be assigned the value.
  *
- * This method does the same as the C function OSRSetAttrValue(). 
+ * This method does the same as the C function OSRSetAttrValue().
  *
  * @param pszNodePath full path to attribute to be set.  For instance
  * "PROJCS|GEOGCS|UNIT".
- * 
- * @param pszNewNodeValue value to be assigned to node, such as "meter". 
+ *
+ * @param pszNewNodeValue value to be assigned to node, such as "meter".
  * This may be NULL if you just want to force creation of the intermediate
  * path.
  *
- * @return OGRERR_NONE on success. 
+ * @return OGRERR_NONE on success.
  */
 
 OGRErr OGRSpatialReference::SetNode( const char * pszNodePath,
                                      const char * pszNewNodeValue )
 
 {
-    char        **papszPathTokens;
-    int         i;
-    OGR_SRSNode *poNode;
-
-    papszPathTokens = CSLTokenizeStringComplex(pszNodePath, "|", TRUE, FALSE);
+    char **papszPathTokens =
+        CSLTokenizeStringComplex(pszNodePath, "|", TRUE, FALSE);
 
     if( CSLCount( papszPathTokens ) < 1 )
+    {
+        CSLDestroy(papszPathTokens);
         return OGRERR_FAILURE;
+    }
 
     if( GetRoot() == NULL || !EQUAL(papszPathTokens[0],GetRoot()->GetValue()) )
     {
         SetRoot( new OGR_SRSNode( papszPathTokens[0] ) );
     }
 
-    poNode = GetRoot();
-    for( i = 1; papszPathTokens[i] != NULL; i++ )
+    OGR_SRSNode *poNode = GetRoot();
+    for( int i = 1; papszPathTokens[i] != NULL; i++ )
     {
-        int     j;
-        
+        int j;
+
         for( j = 0; j < poNode->GetChildCount(); j++ )
         {
             if( EQUAL(poNode->GetChild( j )->GetValue(),papszPathTokens[i]) )
@@ -849,13 +847,14 @@ OGRErr OGRSpatialReference::SetNode( const char * pszNodePath,
  *
  * This function is the same as OGRSpatialReference::SetNode()
  */
-OGRErr CPL_STDCALL OSRSetAttrValue( OGRSpatialReferenceH hSRS, 
+OGRErr CPL_STDCALL OSRSetAttrValue( OGRSpatialReferenceH hSRS,
                         const char * pszPath, const char * pszValue )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetAttrValue", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetAttrValue", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetNode( pszPath, pszValue );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
+        SetNode( pszPath, pszValue );
 }
 
 /************************************************************************/
@@ -866,12 +865,12 @@ OGRErr OGRSpatialReference::SetNode( const char *pszNodePath,
                                      double dfValue )
 
 {
-    char        szValue[64];
+    char szValue[64] = { '\0' };
 
-    if( ABS(dfValue - (int) dfValue) == 0.0 )
-        sprintf( szValue, "%d", (int) dfValue );
+    if( ABS(dfValue - static_cast<int>(dfValue)) == 0.0 )
+        snprintf( szValue, sizeof(szValue), "%d", static_cast<int>(dfValue) );
     else
-        OGRPrintDouble( szValue, dfValue );
+        OGRsnPrintDouble( szValue, sizeof(szValue), dfValue );
 
     return SetNode( pszNodePath, szValue );
 }
@@ -884,16 +883,16 @@ OGRErr OGRSpatialReference::SetNode( const char *pszNodePath,
  * \brief Set the angular units for the geographic coordinate system.
  *
  * This method creates a UNIT subnode with the specified values as a
- * child of the GEOGCS node. 
+ * child of the GEOGCS node.
  *
- * This method does the same as the C function OSRSetAngularUnits(). 
+ * This method does the same as the C function OSRSetAngularUnits().
  *
  * @param pszUnitsName the units name to be used.  Some preferred units
- * names can be found in ogr_srs_api.h such as SRS_UA_DEGREE. 
+ * names can be found in ogr_srs_api.h such as SRS_UA_DEGREE.
  *
  * @param dfInRadians the value to multiple by an angle in the indicated
  * units to transform to radians.  Some standard conversion factors can
- * be found in ogr_srs_api.h. 
+ * be found in ogr_srs_api.h.
  *
  * @return OGRERR_NONE on success.
  */
@@ -902,19 +901,17 @@ OGRErr OGRSpatialReference::SetAngularUnits( const char * pszUnitsName,
                                              double dfInRadians )
 
 {
-    OGR_SRSNode *poCS;
-    OGR_SRSNode *poUnits;
-    char        szValue[128];
-
     bNormInfoSet = FALSE;
 
-    poCS = GetAttrNode( "GEOGCS" );
+    OGR_SRSNode *poCS = GetAttrNode( "GEOGCS" );
 
     if( poCS == NULL )
         return OGRERR_FAILURE;
 
-    OGRPrintDouble( szValue, dfInRadians );
+    char szValue[128] = { '\0' };
+    OGRsnPrintDouble( szValue, sizeof(szValue), dfInRadians );
 
+    OGR_SRSNode *poUnits = NULL;
     if( poCS->FindChild( "UNIT" ) >= 0 )
     {
         poUnits = poCS->GetChild( poCS->FindChild( "UNIT" ) );
@@ -928,7 +925,7 @@ OGRErr OGRSpatialReference::SetAngularUnits( const char * pszUnitsName,
         poUnits = new OGR_SRSNode( "UNIT" );
         poUnits->AddChild( new OGR_SRSNode( pszUnitsName ) );
         poUnits->AddChild( new OGR_SRSNode( szValue ) );
-        
+
         poCS->AddChild( poUnits );
     }
 
@@ -944,14 +941,14 @@ OGRErr OGRSpatialReference::SetAngularUnits( const char * pszUnitsName,
  *
  * This function is the same as OGRSpatialReference::SetAngularUnits()
  */
-OGRErr OSRSetAngularUnits( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetAngularUnits( OGRSpatialReferenceH hSRS,
                            const char * pszUnits, double dfInRadians )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetAngularUnits", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetAngularUnits", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetAngularUnits( pszUnits, 
-                                                            dfInRadians );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
+        SetAngularUnits( pszUnits, dfInRadians );
 }
 
 /************************************************************************/
@@ -961,18 +958,18 @@ OGRErr OSRSetAngularUnits( OGRSpatialReferenceH hSRS,
 /**
  * \brief Fetch angular geographic coordinate system units.
  *
- * If no units are available, a value of "degree" and SRS_UA_DEGREE_CONV 
+ * If no units are available, a value of "degree" and SRS_UA_DEGREE_CONV
  * will be assumed.  This method only checks directly under the GEOGCS node
  * for units.
  *
  * This method does the same thing as the C function OSRGetAngularUnits().
  *
- * @param ppszName a pointer to be updated with the pointer to the 
- * units name.  The returned value remains internal to the OGRSpatialReference
- * and shouldn't be freed, or modified.  It may be invalidated on the next
- * OGRSpatialReference call. 
+ * @param ppszName a pointer to be updated with the pointer to the units name.
+ * The returned value remains internal to the OGRSpatialReference and should
+ * not be freed, or modified.  It may be invalidated on the next
+ * OGRSpatialReference call.
  *
- * @return the value to multiply by angular distances to transform them to 
+ * @return the value to multiply by angular distances to transform them to
  * radians.
  */
 
@@ -983,20 +980,21 @@ double OGRSpatialReference::GetAngularUnits( char ** ppszName ) const
 
     if( ppszName != NULL )
         *ppszName = (char* ) "degree";
-        
+
     if( poCS == NULL )
         return CPLAtof(SRS_UA_DEGREE_CONV);
 
     for( int iChild = 0; iChild < poCS->GetChildCount(); iChild++ )
     {
-        const OGR_SRSNode     *poChild = poCS->GetChild(iChild);
-        
+        const OGR_SRSNode *poChild = poCS->GetChild(iChild);
+
         if( EQUAL(poChild->GetValue(),"UNIT")
             && poChild->GetChildCount() >= 2 )
         {
             if( ppszName != NULL )
-                *ppszName = (char *) poChild->GetChild(0)->GetValue();
-            
+              *ppszName =
+                  const_cast<char *>(poChild->GetChild(0)->GetValue());
+
             return CPLAtof( poChild->GetChild(1)->GetValue() );
         }
     }
@@ -1014,11 +1012,12 @@ double OGRSpatialReference::GetAngularUnits( char ** ppszName ) const
  * This function is the same as OGRSpatialReference::GetAngularUnits()
  */
 double OSRGetAngularUnits( OGRSpatialReferenceH hSRS, char ** ppszName )
-    
+
 {
     VALIDATE_POINTER1( hSRS, "OSRGetAngularUnits", 0 );
 
-    return ((OGRSpatialReference *) hSRS)->GetAngularUnits( ppszName );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
+        GetAngularUnits( ppszName );
 }
 
 /************************************************************************/
@@ -1031,15 +1030,15 @@ double OSRGetAngularUnits( OGRSpatialReferenceH hSRS, char ** ppszName )
  * This method creates a UNIT subnode with the specified values as a
  * child of the PROJCS or LOCAL_CS node.   It works the same as the
  * SetLinearUnits() method, but it also updates all existing linear
- * projection parameter values from the old units to the new units. 
+ * projection parameter values from the old units to the new units.
  *
  * @param pszName the units name to be used.  Some preferred units
- * names can be found in ogr_srs_api.h such as SRS_UL_METER, SRS_UL_FOOT 
- * and SRS_UL_US_FOOT. 
+ * names can be found in ogr_srs_api.h such as SRS_UL_METER, SRS_UL_FOOT
+ * and SRS_UL_US_FOOT.
  *
  * @param dfInMeters the value to multiple by a length in the indicated
  * units to transform to meters.  Some standard conversion factors can
- * be found in ogr_srs_api.h. 
+ * be found in ogr_srs_api.h.
  *
  * @return OGRERR_NONE on success.
  */
@@ -1048,29 +1047,29 @@ OGRErr OGRSpatialReference::SetLinearUnitsAndUpdateParameters(
     const char *pszName, double dfInMeters )
 
 {
-    double dfOldInMeters = GetLinearUnits();
-    OGR_SRSNode *poPROJCS = GetAttrNode( "PROJCS" );
-
     if( dfInMeters == 0.0 )
         return OGRERR_FAILURE;
 
+    const double dfOldInMeters = GetLinearUnits();
+    OGR_SRSNode *poPROJCS = GetAttrNode( "PROJCS" );
+
     if( dfInMeters == dfOldInMeters || poPROJCS == NULL )
         return SetLinearUnits( pszName, dfInMeters );
 
     for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
     {
-        const OGR_SRSNode     *poChild = poPROJCS->GetChild(iChild);
-        
+        const OGR_SRSNode *poChild = poPROJCS->GetChild(iChild);
+
         if( EQUAL(poChild->GetValue(),"PARAMETER")
             && poChild->GetChildCount() > 1 )
         {
-            char *pszParmName = CPLStrdup(poChild->GetChild(0)->GetValue());
-            
+            char * const pszParmName = CPLStrdup(poChild->GetChild(0)->GetValue());
+
             if( IsLinearParameter( pszParmName ) )
             {
-                double dfOldValue = GetProjParm( pszParmName );
+                const double dfOldValue = GetProjParm( pszParmName );
 
-                SetProjParm( pszParmName, 
+                SetProjParm( pszParmName,
                              dfOldValue * dfOldInMeters / dfInMeters );
             }
 
@@ -1088,17 +1087,18 @@ OGRErr OGRSpatialReference::SetLinearUnitsAndUpdateParameters(
 /**
  * \brief Set the linear units for the projection.
  *
- * This function is the same as OGRSpatialReference::SetLinearUnitsAndUpdateParameters()
+ * This function is the same as
+ *   OGRSpatialReference::SetLinearUnitsAndUpdateParameters()
  */
-OGRErr OSRSetLinearUnitsAndUpdateParameters( OGRSpatialReferenceH hSRS, 
-                                             const char * pszUnits, 
+OGRErr OSRSetLinearUnitsAndUpdateParameters( OGRSpatialReferenceH hSRS,
+                                             const char * pszUnits,
                                              double dfInMeters )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetLinearUnitsAndUpdateParameters", 
-                       CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetLinearUnitsAndUpdateParameters",
+                       OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
         SetLinearUnitsAndUpdateParameters( pszUnits, dfInMeters );
 }
 
@@ -1110,17 +1110,17 @@ OGRErr OSRSetLinearUnitsAndUpdateParameters( OGRSpatialReferenceH hSRS,
  * \brief Set the linear units for the projection.
  *
  * This method creates a UNIT subnode with the specified values as a
- * child of the PROJCS, GEOCCS or LOCAL_CS node. 
+ * child of the PROJCS, GEOCCS or LOCAL_CS node.
  *
- * This method does the same as the C function OSRSetLinearUnits(). 
+ * This method does the same as the C function OSRSetLinearUnits().
  *
  * @param pszUnitsName the units name to be used.  Some preferred units
- * names can be found in ogr_srs_api.h such as SRS_UL_METER, SRS_UL_FOOT 
- * and SRS_UL_US_FOOT. 
+ * names can be found in ogr_srs_api.h such as SRS_UL_METER, SRS_UL_FOOT
+ * and SRS_UL_US_FOOT.
  *
  * @param dfInMeters the value to multiple by a length in the indicated
  * units to transform to meters.  Some standard conversion factors can
- * be found in ogr_srs_api.h. 
+ * be found in ogr_srs_api.h.
  *
  * @return OGRERR_NONE on success.
  */
@@ -1141,14 +1141,14 @@ OGRErr OGRSpatialReference::SetLinearUnits( const char * pszUnitsName,
  *
  * This function is the same as OGRSpatialReference::SetLinearUnits()
  */
-OGRErr OSRSetLinearUnits( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetLinearUnits( OGRSpatialReferenceH hSRS,
                           const char * pszUnits, double dfInMeters )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetLinearUnits", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetLinearUnits", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetLinearUnits( pszUnits, 
-                                                           dfInMeters );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
+        SetLinearUnits( pszUnits, dfInMeters );
 }
 
 /************************************************************************/
@@ -1159,19 +1159,20 @@ OGRErr OSRSetLinearUnits( OGRSpatialReferenceH hSRS,
  * \brief Set the linear units for the projection.
  *
  * This method creates a UNIT subnode with the specified values as a
- * child of the target node. 
+ * child of the target node.
  *
- * This method does the same as the C function OSRSetTargetLinearUnits(). 
+ * This method does the same as the C function OSRSetTargetLinearUnits().
  *
- * @param pszTargetKey the keyword to set the linear units for.  ie. "PROJCS" or "VERT_CS"
+ * @param pszTargetKey the keyword to set the linear units for.
+ * i.e. "PROJCS" or "VERT_CS"
  *
  * @param pszUnitsName the units name to be used.  Some preferred units
- * names can be found in ogr_srs_api.h such as SRS_UL_METER, SRS_UL_FOOT 
- * and SRS_UL_US_FOOT. 
+ * names can be found in ogr_srs_api.h such as SRS_UL_METER, SRS_UL_FOOT
+ * and SRS_UL_US_FOOT.
  *
  * @param dfInMeters the value to multiple by a length in the indicated
  * units to transform to meters.  Some standard conversion factors can
- * be found in ogr_srs_api.h. 
+ * be found in ogr_srs_api.h.
  *
  * @return OGRERR_NONE on success.
  *
@@ -1183,12 +1184,9 @@ OGRErr OGRSpatialReference::SetTargetLinearUnits( const char *pszTargetKey,
                                                   double dfInMeters )
 
 {
-    OGR_SRSNode *poCS;
-    OGR_SRSNode *poUnits;
-    char        szValue[128];
-
     bNormInfoSet = FALSE;
 
+    OGR_SRSNode *poCS = NULL;
     if( pszTargetKey == NULL )
     {
         poCS = GetAttrNode( "PROJCS" );
@@ -1206,11 +1204,13 @@ OGRErr OGRSpatialReference::SetTargetLinearUnits( const char *pszTargetKey,
     if( poCS == NULL )
         return OGRERR_FAILURE;
 
+    char szValue[128] = { '\0' };
     if( dfInMeters == (int) dfInMeters )
-        sprintf( szValue, "%d", (int) dfInMeters );
+        snprintf( szValue, sizeof(szValue), "%d", static_cast<int>(dfInMeters) );
     else
-        OGRPrintDouble( szValue, dfInMeters );
+        OGRsnPrintDouble( szValue, sizeof(szValue), dfInMeters );
 
+    OGR_SRSNode *poUnits = NULL;
     if( poCS->FindChild( "UNIT" ) >= 0 )
     {
         poUnits = poCS->GetChild( poCS->FindChild( "UNIT" ) );
@@ -1226,7 +1226,7 @@ OGRErr OGRSpatialReference::SetTargetLinearUnits( const char *pszTargetKey,
         poUnits = new OGR_SRSNode( "UNIT" );
         poUnits->AddChild( new OGR_SRSNode( pszUnitsName ) );
         poUnits->AddChild( new OGR_SRSNode( szValue ) );
-        
+
         poCS->AddChild( poUnits );
     }
 
@@ -1244,12 +1244,12 @@ OGRErr OGRSpatialReference::SetTargetLinearUnits( const char *pszTargetKey,
  *
  * @since OGR 1.9.0
  */
-OGRErr OSRSetTargetLinearUnits( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetTargetLinearUnits( OGRSpatialReferenceH hSRS,
                                 const char *pszTargetKey,
                                 const char * pszUnits, double dfInMeters )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetTargetLinearUnits", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetTargetLinearUnits", OGRERR_FAILURE );
 
     return ((OGRSpatialReference *) hSRS)->
         SetTargetLinearUnits( pszTargetKey, pszUnits, dfInMeters );
@@ -1260,20 +1260,20 @@ OGRErr OSRSetTargetLinearUnits( OGRSpatialReferenceH hSRS,
 /************************************************************************/
 
 /**
- * \brief Fetch linear projection units. 
+ * \brief Fetch linear projection units.
  *
  * If no units are available, a value of "Meters" and 1.0 will be assumed.
- * This method only checks directly under the PROJCS, GEOCCS or LOCAL_CS node 
+ * This method only checks directly under the PROJCS, GEOCCS or LOCAL_CS node
  * for units.
  *
  * This method does the same thing as the C function OSRGetLinearUnits()/
  *
- * @param ppszName a pointer to be updated with the pointer to the 
- * units name.  The returned value remains internal to the OGRSpatialReference
- * and shouldn't be freed, or modified.  It may be invalidated on the next
- * OGRSpatialReference call. 
+ * @param ppszName a pointer to be updated with the pointer to the units name.
+ * The returned value remains internal to the OGRSpatialReference and should
+ * not be freed, or modified.  It may be invalidated on the next
+ * OGRSpatialReference call.
  *
- * @return the value to multiply by linear distances to transform them to 
+ * @return the value to multiply by linear distances to transform them to
  * meters.
  */
 
@@ -1288,16 +1288,16 @@ double OGRSpatialReference::GetLinearUnits( char ** ppszName ) const
 /************************************************************************/
 
 /**
- * \brief Fetch linear projection units. 
+ * \brief Fetch linear projection units.
  *
  * This function is the same as OGRSpatialReference::GetLinearUnits()
  */
 double OSRGetLinearUnits( OGRSpatialReferenceH hSRS, char ** ppszName )
-    
+
 {
     VALIDATE_POINTER1( hSRS, "OSRGetLinearUnits", 0 );
 
-    return ((OGRSpatialReference *) hSRS)->GetLinearUnits( ppszName );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->GetLinearUnits( ppszName );
 }
 
 /************************************************************************/
@@ -1305,19 +1305,19 @@ double OSRGetLinearUnits( OGRSpatialReferenceH hSRS, char ** ppszName )
 /************************************************************************/
 
 /**
- * \brief Fetch linear units for target. 
+ * \brief Fetch linear units for target.
  *
  * If no units are available, a value of "Meters" and 1.0 will be assumed.
  *
  * This method does the same thing as the C function OSRGetTargetLinearUnits()/
  *
- * @param pszTargetKey the key to look on. ie. "PROJCS" or "VERT_CS".
- * @param ppszName a pointer to be updated with the pointer to the 
- * units name.  The returned value remains internal to the OGRSpatialReference
- * and shouldn't be freed, or modified.  It may be invalidated on the next
- * OGRSpatialReference call. 
+ * @param pszTargetKey the key to look on. i.e. "PROJCS" or "VERT_CS".  @param
+ * ppszName a pointer to be updated with the pointer to the units name.  The
+ * returned value remains internal to the OGRSpatialReference and should not
+ * be freed, or modified.  It may be invalidated on the next
+ * OGRSpatialReference call.
  *
- * @return the value to multiply by linear distances to transform them to 
+ * @return the value to multiply by linear distances to transform them to
  * meters.
  *
  * @since OGR 1.9.0
@@ -1327,7 +1327,7 @@ double OGRSpatialReference::GetTargetLinearUnits( const char *pszTargetKey,
                                                   char ** ppszName ) const
 
 {
-    const OGR_SRSNode *poCS;
+    const OGR_SRSNode *poCS = NULL;
 
     if( pszTargetKey == NULL )
     {
@@ -1345,20 +1345,20 @@ double OGRSpatialReference::GetTargetLinearUnits( const char *pszTargetKey,
 
     if( ppszName != NULL )
         *ppszName = (char*) "unknown";
-        
+
     if( poCS == NULL )
         return 1.0;
 
     for( int iChild = 0; iChild < poCS->GetChildCount(); iChild++ )
     {
-        const OGR_SRSNode     *poChild = poCS->GetChild(iChild);
-        
+        const OGR_SRSNode *poChild = poCS->GetChild(iChild);
+
         if( EQUAL(poChild->GetValue(),"UNIT")
             && poChild->GetChildCount() >= 2 )
         {
             if( ppszName != NULL )
-                *ppszName = (char *) poChild->GetChild(0)->GetValue();
-            
+              *ppszName = const_cast<char *>(poChild->GetChild(0)->GetValue());
+
             return CPLAtof( poChild->GetChild(1)->GetValue() );
         }
     }
@@ -1371,21 +1371,21 @@ double OGRSpatialReference::GetTargetLinearUnits( const char *pszTargetKey,
 /************************************************************************/
 
 /**
- * \brief Fetch linear projection units. 
+ * \brief Fetch linear projection units.
  *
  * This function is the same as OGRSpatialReference::GetTargetLinearUnits()
  *
  * @since OGR 1.9.0
  */
-double OSRGetTargetLinearUnits( OGRSpatialReferenceH hSRS, 
-                                const char *pszTargetKey, 
+double OSRGetTargetLinearUnits( OGRSpatialReferenceH hSRS,
+                                const char *pszTargetKey,
                                 char ** ppszName )
-    
+
 {
     VALIDATE_POINTER1( hSRS, "OSRGetTargetLinearUnits", 0 );
 
-    return ((OGRSpatialReference *) hSRS)->GetTargetLinearUnits( pszTargetKey,
-                                                                 ppszName );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
+        GetTargetLinearUnits( pszTargetKey, ppszName );
 }
 
 /************************************************************************/
@@ -1413,19 +1413,19 @@ double OSRGetTargetLinearUnits( OGRSpatialReferenceH hSRS,
  * degrees.
  */
 
-double OGRSpatialReference::GetPrimeMeridian( char **ppszName ) const 
+double OGRSpatialReference::GetPrimeMeridian( char **ppszName ) const
 
 {
     const OGR_SRSNode *poPRIMEM = GetAttrNode( "PRIMEM" );
 
-    if( poPRIMEM != NULL && poPRIMEM->GetChildCount() >= 2 
+    if( poPRIMEM != NULL && poPRIMEM->GetChildCount() >= 2
         && CPLAtof(poPRIMEM->GetChild(1)->GetValue()) != 0.0 )
     {
         if( ppszName != NULL )
-            *ppszName = (char *) poPRIMEM->GetChild(0)->GetValue();
+            *ppszName = const_cast<char *>(poPRIMEM->GetChild(0)->GetValue());
         return CPLAtof(poPRIMEM->GetChild(1)->GetValue());
     }
-    
+
     if( ppszName != NULL )
         *ppszName = (char*) SRS_PM_GREENWICH;
 
@@ -1446,7 +1446,8 @@ double OSRGetPrimeMeridian( OGRSpatialReferenceH hSRS, char **ppszName )
 {
     VALIDATE_POINTER1( hSRS, "OSRGetPrimeMeridian", 0 );
 
-    return ((OGRSpatialReference *) hSRS)->GetPrimeMeridian( ppszName );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
+        GetPrimeMeridian( ppszName );
 }
 
 /************************************************************************/
@@ -1454,42 +1455,42 @@ double OSRGetPrimeMeridian( OGRSpatialReferenceH hSRS, char **ppszName )
 /************************************************************************/
 
 /**
- * \brief Set geographic coordinate system. 
+ * \brief Set geographic coordinate system.
  *
  * This method is used to set the datum, ellipsoid, prime meridian and
  * angular units for a geographic coordinate system.  It can be used on it's
- * own to establish a geographic spatial reference, or applied to a 
- * projected coordinate system to establish the underlying geographic 
- * coordinate system. 
+ * own to establish a geographic spatial reference, or applied to a
+ * projected coordinate system to establish the underlying geographic
+ * coordinate system.
  *
- * This method does the same as the C function OSRSetGeogCS(). 
+ * This method does the same as the C function OSRSetGeogCS().
  *
  * @param pszGeogName user visible name for the geographic coordinate system
  * (not to serve as a key).
- * 
- * @param pszDatumName key name for this datum.  The OpenGIS specification 
+ *
+ * @param pszDatumName key name for this datum.  The OpenGIS specification
  * lists some known values, and otherwise EPSG datum names with a standard
- * transformation are considered legal keys. 
- * 
+ * transformation are considered legal keys.
+ *
  * @param pszSpheroidName user visible spheroid name (not to serve as a key)
  *
  * @param dfSemiMajor the semi major axis of the spheroid.
- * 
+ *
  * @param dfInvFlattening the inverse flattening for the spheroid.
- * This can be computed from the semi minor axis as 
+ * This can be computed from the semi minor axis as
  * 1/f = 1.0 / (1.0 - semiminor/semimajor).
  *
- * @param pszPMName the name of the prime merdidian (not to serve as a key)
- * If this is NULL a default value of "Greenwich" will be used. 
- * 
- * @param dfPMOffset the longitude of greenwich relative to this prime
+ * @param pszPMName the name of the prime meridian (not to serve as a key)
+ * If this is NULL a default value of "Greenwich" will be used.
+ *
+ * @param dfPMOffset the longitude of Greenwich relative to this prime
  * meridian.
  *
  * @param pszAngularUnits the angular units name (see ogr_srs_api.h for some
- * standard names).  If NULL a value of "degrees" will be assumed. 
- * 
+ * standard names).  If NULL a value of "degrees" will be assumed.
+ *
  * @param dfConvertToRadians value to multiply angular units by to transform
- * them to radians.  A value of SRS_UL_DEGREE_CONV will be used if
+ * them to radians.  A value of SRS_UA_DEGREE_CONV will be used if
  * pszAngularUnits is NULL.
  *
  * @return OGRERR_NONE on success.
@@ -1518,11 +1519,11 @@ OGRSpatialReference::SetGeogCS( const char * pszGeogName,
         OGRSpatialReference oGCS;
 
         oGCS.SetGeogCS( pszGeogName, pszDatumName, pszSpheroidName,
-                        dfSemiMajor, dfInvFlattening, 
-                        pszPMName, dfPMOffset, 
+                        dfSemiMajor, dfInvFlattening,
+                        pszPMName, dfPMOffset,
                         pszAngularUnits, dfConvertToRadians );
         return CopyGeogCSFrom( &oGCS );
-    }        
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Do we already have a GEOGCS?  If so, blow it away so it can     */
@@ -1530,7 +1531,7 @@ OGRSpatialReference::SetGeogCS( const char * pszGeogName,
 /* -------------------------------------------------------------------- */
     if( GetAttrNode( "GEOGCS" ) != NULL )
     {
-        OGR_SRSNode *poCS;
+        OGR_SRSNode *poCS = NULL;
 
         if( EQUAL(GetRoot()->GetValue(),"GEOGCS") )
             Clear();
@@ -1565,28 +1566,26 @@ OGRSpatialReference::SetGeogCS( const char * pszGeogName,
 /* -------------------------------------------------------------------- */
 /*      Build the GEOGCS object.                                        */
 /* -------------------------------------------------------------------- */
-    char                szValue[128];
-    OGR_SRSNode         *poGeogCS, *poSpheroid, *poDatum, *poPM, *poUnits;
-
-    poGeogCS = new OGR_SRSNode( "GEOGCS" );
+    OGR_SRSNode *poGeogCS = new OGR_SRSNode( "GEOGCS" );
     poGeogCS->AddChild( new OGR_SRSNode( pszGeogName ) );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Setup the spheroid.                                             */
 /* -------------------------------------------------------------------- */
-    poSpheroid = new OGR_SRSNode( "SPHEROID" );
+    OGR_SRSNode *poSpheroid = new OGR_SRSNode( "SPHEROID" );
     poSpheroid->AddChild( new OGR_SRSNode( pszSpheroidName ) );
 
-    OGRPrintDouble( szValue, dfSemiMajor );
+    char szValue[128];
+    OGRsnPrintDouble( szValue, sizeof(szValue), dfSemiMajor );
     poSpheroid->AddChild( new OGR_SRSNode(szValue) );
 
-    OGRPrintDouble( szValue, dfInvFlattening );
+    OGRsnPrintDouble( szValue, sizeof(szValue), dfInvFlattening );
     poSpheroid->AddChild( new OGR_SRSNode(szValue) );
 
 /* -------------------------------------------------------------------- */
 /*      Setup the Datum.                                                */
 /* -------------------------------------------------------------------- */
-    poDatum = new OGR_SRSNode( "DATUM" );
+    OGR_SRSNode *poDatum = new OGR_SRSNode( "DATUM" );
     poDatum->AddChild( new OGR_SRSNode(pszDatumName) );
     poDatum->AddChild( poSpheroid );
 
@@ -1596,21 +1595,21 @@ OGRSpatialReference::SetGeogCS( const char * pszGeogName,
     if( dfPMOffset == 0.0 )
         strcpy( szValue, "0" );
     else
-        OGRPrintDouble( szValue, dfPMOffset );
-    
-    poPM = new OGR_SRSNode( "PRIMEM" );
+      OGRsnPrintDouble( szValue, sizeof(szValue), dfPMOffset );
+
+    OGR_SRSNode *poPM = new OGR_SRSNode( "PRIMEM" );
     poPM->AddChild( new OGR_SRSNode( pszPMName ) );
     poPM->AddChild( new OGR_SRSNode( szValue ) );
 
 /* -------------------------------------------------------------------- */
 /*      Setup the rotational units.                                     */
 /* -------------------------------------------------------------------- */
-    OGRPrintDouble( szValue, dfConvertToRadians );
-    
-    poUnits = new OGR_SRSNode( "UNIT" );
+    OGRsnPrintDouble( szValue, sizeof(szValue), dfConvertToRadians );
+
+    OGR_SRSNode *poUnits = new OGR_SRSNode( "UNIT" );
     poUnits->AddChild( new OGR_SRSNode(pszAngularUnits) );
     poUnits->AddChild( new OGR_SRSNode(szValue) );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Complete the GeogCS                                             */
 /* -------------------------------------------------------------------- */
@@ -1634,7 +1633,7 @@ OGRSpatialReference::SetGeogCS( const char * pszGeogName,
 /************************************************************************/
 
 /**
- * \brief Set geographic coordinate system. 
+ * \brief Set geographic coordinate system.
  *
  * This function is the same as OGRSpatialReference::SetGeogCS()
  */
@@ -1648,13 +1647,12 @@ OGRErr OSRSetGeogCS( OGRSpatialReferenceH hSRS,
                      double dfConvertToRadians )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetGeogCS", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetGeogCS", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetGeogCS( 
-        pszGeogName, pszDatumName, 
-        pszSpheroidName, dfSemiMajor, dfInvFlattening, 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetGeogCS(
+        pszGeogName, pszDatumName,
+        pszSpheroidName, dfSemiMajor, dfInvFlattening,
         pszPMName, dfPMOffset, pszAngularUnits, dfConvertToRadians );
-                                                      
 }
 
 /************************************************************************/
@@ -1665,9 +1663,9 @@ OGRErr OSRSetGeogCS( OGRSpatialReferenceH hSRS,
  * \brief Set a GeogCS based on well known name.
  *
  * This may be called on an empty OGRSpatialReference to make a geographic
- * coordinate system, or on something with an existing PROJCS node to 
+ * coordinate system, or on something with an existing PROJCS node to
  * set the underlying geographic coordinate system of a projected coordinate
- * system. 
+ * system.
  *
  * The following well known text values are currently supported:
  * <ul>
@@ -1677,25 +1675,23 @@ OGRErr OSRSetGeogCS( OGRSpatialReferenceH hSRS,
  * <li> "NAD83": same as "EPSG:4269" but has no dependence on EPSG data files.
  * <li> "EPSG:n": same as doing an ImportFromEPSG(n).
  * </ul>
- * 
+ *
  * @param pszName name of well known geographic coordinate system.
  * @return OGRERR_NONE on success, or OGRERR_FAILURE if the name isn't
  * recognised, the target object is already initialized, or an EPSG value
  * can't be successfully looked up.
- */ 
+ */
 
 OGRErr OGRSpatialReference::SetWellKnownGeogCS( const char * pszName )
 
 {
-    OGRSpatialReference   oSRS2;
-    OGRErr eErr;
-
 /* -------------------------------------------------------------------- */
 /*      Check for EPSG authority numbers.                               */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszName, "EPSG:",5) )
+    if( STARTS_WITH_CI(pszName, "EPSG:") )
     {
-        eErr = oSRS2.importFromEPSG( atoi(pszName+5) );
+        OGRSpatialReference oSRS2;
+        const OGRErr eErr = oSRS2.importFromEPSG( atoi(pszName+5) );
         if( eErr != OGRERR_NONE )
             return eErr;
 
@@ -1708,9 +1704,10 @@ OGRErr OGRSpatialReference::SetWellKnownGeogCS( const char * pszName )
 /* -------------------------------------------------------------------- */
 /*      Check for EPSGA authority numbers.                               */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszName, "EPSGA:",6) )
+    if( STARTS_WITH_CI(pszName, "EPSGA:") )
     {
-        eErr = oSRS2.importFromEPSGA( atoi(pszName+6) );
+        OGRSpatialReference oSRS2;
+        const OGRErr eErr = oSRS2.importFromEPSGA( atoi(pszName+6) );
         if( eErr != OGRERR_NONE )
             return eErr;
 
@@ -1723,19 +1720,22 @@ OGRErr OGRSpatialReference::SetWellKnownGeogCS( const char * pszName )
 /* -------------------------------------------------------------------- */
 /*      Check for simple names.                                         */
 /* -------------------------------------------------------------------- */
-    char        *pszWKT = NULL;
+    char *pszWKT = NULL;
 
     if( EQUAL(pszName, "WGS84") || EQUAL(pszName,"CRS84") || EQUAL(pszName,"CRS:84") )
         pszWKT = (char* ) SRS_WKT_WGS84;
 
     else if( EQUAL(pszName, "WGS72") )
-        pszWKT = (char* ) "GEOGCS[\"WGS 72\",DATUM[\"WGS_1972\",SPHEROID[\"WGS 72\",6378135,298.26,AUTHORITY[\"EPSG\",\"7043\"]],TOWGS84[0,0,4.5,0,0,0.554,0.2263],AUTHORITY[\"EPSG\",\"6322\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9108\"]],AUTHORITY[\"EPSG\",\"4322\"]]";
+        pszWKT = const_cast<char *>(
+            "GEOGCS[\"WGS 72\",DATUM[\"WGS_1972\",SPHEROID[\"WGS 72\",6378135,298.26,AUTHORITY[\"EPSG\",\"7043\"]],TOWGS84[0,0,4.5,0,0,0.554,0.2263],AUTHORITY[\"EPSG\",\"6322\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4322\"]]" );
 
     else if( EQUAL(pszName, "NAD27") || EQUAL(pszName, "CRS27") || EQUAL(pszName,"CRS:27") )
-        pszWKT = (char* ) "GEOGCS[\"NAD27\",DATUM[\"North_American_Datum_1927\",SPHEROID[\"Clarke 1866\",6378206.4,294.978698213898,AUTHORITY[\"EPSG\",\"7008\"]],AUTHORITY[\"EPSG\",\"6267\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9108\"]],AUTHORITY[\"EPSG\",\"4267\"]]";
-        
+      pszWKT = const_cast<char *>(
+          "GEOGCS[\"NAD27\",DATUM[\"North_American_Datum_1927\",SPHEROID[\"Clarke 1866\",6378206.4,294.9786982138982,AUTHORITY[\"EPSG\",\"7008\"]],AUTHORITY[\"EPSG\",\"6267\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4267\"]]" );
+
     else if( EQUAL(pszName, "NAD83") || EQUAL(pszName,"CRS83") || EQUAL(pszName,"CRS:83") )
-        pszWKT = (char* ) "GEOGCS[\"NAD83\",DATUM[\"North_American_Datum_1983\",SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6269\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9108\"]],AUTHORITY[\"EPSG\",\"4269\"]]";
+      pszWKT = const_cast<char *>(
+          "GEOGCS[\"NAD83\",DATUM[\"North_American_Datum_1983\",SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6269\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4269\"]]" );
 
     else
         return OGRERR_FAILURE;
@@ -1743,7 +1743,8 @@ OGRErr OGRSpatialReference::SetWellKnownGeogCS( const char * pszName )
 /* -------------------------------------------------------------------- */
 /*      Import the WKT                                                  */
 /* -------------------------------------------------------------------- */
-    eErr = oSRS2.importFromWkt( &pszWKT );
+    OGRSpatialReference oSRS2;
+    const OGRErr eErr = oSRS2.importFromWkt( &pszWKT );
     if( eErr != OGRERR_NONE )
         return eErr;
 
@@ -1765,9 +1766,10 @@ OGRErr OGRSpatialReference::SetWellKnownGeogCS( const char * pszName )
 OGRErr OSRSetWellKnownGeogCS( OGRSpatialReferenceH hSRS, const char *pszName )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetWellKnownGeogCS", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetWellKnownGeogCS", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetWellKnownGeogCS( pszName );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
+        SetWellKnownGeogCS( pszName );
 }
 
 /************************************************************************/
@@ -1780,19 +1782,17 @@ OGRErr OSRSetWellKnownGeogCS( OGRSpatialReferenceH hSRS, const char *pszName )
  * The GEOGCS information is copied into this OGRSpatialReference from another.
  * If this object has a PROJCS root already, the GEOGCS is installed within
  * it, otherwise it is installed as the root.
- * 
+ *
  * @param poSrcSRS the spatial reference to copy the GEOGCS information from.
- * 
+ *
  * @return OGRERR_NONE on success or an error code.
  */
 
 
-OGRErr OGRSpatialReference::CopyGeogCSFrom( 
+OGRErr OGRSpatialReference::CopyGeogCSFrom(
     const OGRSpatialReference * poSrcSRS )
 
 {
-    const OGR_SRSNode  *poGeogCS = NULL;
-
     bNormInfoSet = FALSE;
 
 /* -------------------------------------------------------------------- */
@@ -1811,12 +1811,11 @@ OGRErr OGRSpatialReference::CopyGeogCSFrom(
 
         if( poDatum == NULL || poPrimeM == NULL )
             return OGRERR_FAILURE;
-        
+
         poRoot->InsertChild( poDatum->Clone(), 1 );
         poRoot->InsertChild( poPrimeM->Clone(), 2 );
 
         return OGRERR_NONE;
-        
     }
 
 /* -------------------------------------------------------------------- */
@@ -1825,7 +1824,7 @@ OGRErr OGRSpatialReference::CopyGeogCSFrom(
 /* -------------------------------------------------------------------- */
     if( GetAttrNode( "GEOGCS" ) != NULL )
     {
-        OGR_SRSNode *poPROJCS;
+        OGR_SRSNode *poPROJCS = NULL;
 
         if( EQUAL(GetRoot()->GetValue(),"GEOGCS") )
             Clear();
@@ -1839,7 +1838,7 @@ OGRErr OGRSpatialReference::CopyGeogCSFrom(
 /* -------------------------------------------------------------------- */
 /*      Find the GEOGCS node on the source.                             */
 /* -------------------------------------------------------------------- */
-    poGeogCS = poSrcSRS->GetAttrNode( "GEOGCS" );
+    const OGR_SRSNode  *poGeogCS = poSrcSRS->GetAttrNode( "GEOGCS" );
     if( poGeogCS == NULL )
         return OGRERR_FAILURE;
 
@@ -1863,15 +1862,15 @@ OGRErr OGRSpatialReference::CopyGeogCSFrom(
  *
  * This function is the same as OGRSpatialReference::CopyGeogCSFrom()
  */
-OGRErr OSRCopyGeogCSFrom( OGRSpatialReferenceH hSRS, 
-                          OGRSpatialReferenceH hSrcSRS )
+OGRErr OSRCopyGeogCSFrom( OGRSpatialReferenceH hSRS,
+                          const OGRSpatialReferenceH hSrcSRS )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRCopyGeogCSFrom", CE_Failure );
-    VALIDATE_POINTER1( hSrcSRS, "OSRCopyGeogCSFrom", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRCopyGeogCSFrom", OGRERR_FAILURE );
+    VALIDATE_POINTER1( hSrcSRS, "OSRCopyGeogCSFrom", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->CopyGeogCSFrom( 
-        (const OGRSpatialReference *) hSrcSRS );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->CopyGeogCSFrom(
+        reinterpret_cast<const OGRSpatialReference *>(hSrcSRS) );
 }
 
 /************************************************************************/
@@ -1887,14 +1886,14 @@ OGRErr OSRCopyGeogCSFrom( OGRSpatialReferenceH hSRS,
  *
  * <ol>
  * <li> Well Known Text definition - passed on to importFromWkt().
- * <li> "EPSG:n" - number passed on to importFromEPSG(). 
- * <li> "EPSGA:n" - number passed on to importFromEPSGA(). 
+ * <li> "EPSG:n" - number passed on to importFromEPSG().
+ * <li> "EPSGA:n" - number passed on to importFromEPSGA().
  * <li> "AUTO:proj_id,unit_id,lon0,lat0" - WMS auto projections.
  * <li> "urn:ogc:def:crs:EPSG::n" - ogc urns
  * <li> PROJ.4 definitions - passed on to importFromProj4().
  * <li> filename - file read for WKT, XML or PROJ.4 definition.
  * <li> well known name accepted by SetWellKnownGeogCS(), such as NAD27, NAD83,
- * WGS84 or WGS72. 
+ * WGS84 or WGS72.
  * <li> WKT (directly or in a file) in ESRI format should be prefixed with
  * ESRI:: to trigger an automatic morphFromESRI().
  * <li> "IGNF:xxx" - "+init=IGNF:xxx" passed on to importFromProj4().
@@ -1902,69 +1901,68 @@ OGRErr OSRCopyGeogCSFrom( OGRSpatialReferenceH hSRS,
  *
  * It is expected that this method will be extended in the future to support
  * XML and perhaps a simplified "minilanguage" for indicating common UTM and
- * State Plane definitions. 
+ * State Plane definitions.
  *
- * This method is intended to be flexible, but by it's nature it is 
+ * This method is intended to be flexible, but by it's nature it is
  * imprecise as it must guess information about the format intended.  When
  * possible applications should call the specific method appropriate if the
- * input is known to be in a particular format. 
+ * input is known to be in a particular format.
  *
  * This method does the same thing as the OSRSetFromUserInput() function.
- * 
+ *
  * @param pszDefinition text definition to try to deduce SRS from.
  *
  * @return OGRERR_NONE on success, or an error code if the name isn't
- * recognised, the definition is corrupt, or an EPSG value can't be 
+ * recognised, the definition is corrupt, or an EPSG value can't be
  * successfully looked up.
- */ 
+ */
 
 OGRErr OGRSpatialReference::SetFromUserInput( const char * pszDefinition )
 
 {
-    int     bESRI = FALSE;
-    OGRErr  err;
+    bool bESRI = false;
 
-    if( EQUALN(pszDefinition,"ESRI::",6) )
+    if( STARTS_WITH_CI(pszDefinition, "ESRI::") )
     {
-        bESRI = TRUE;
+        bESRI = true;
         pszDefinition += 6;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Is it a recognised syntax?                                      */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszDefinition,"PROJCS",6)
-        || EQUALN(pszDefinition,"GEOGCS",6)
-        || EQUALN(pszDefinition,"COMPD_CS",8)
-        || EQUALN(pszDefinition,"GEOCCS",6)
-        || EQUALN(pszDefinition,"VERT_CS",7)
-        || EQUALN(pszDefinition,"LOCAL_CS",8) )
+    if( STARTS_WITH_CI(pszDefinition, "PROJCS")
+        || STARTS_WITH_CI(pszDefinition, "GEOGCS")
+        || STARTS_WITH_CI(pszDefinition, "COMPD_CS")
+        || STARTS_WITH_CI(pszDefinition, "GEOCCS")
+        || STARTS_WITH_CI(pszDefinition, "VERT_CS")
+        || STARTS_WITH_CI(pszDefinition, "LOCAL_CS") )
     {
-        err = importFromWkt( (char **) &pszDefinition );
+        OGRErr err = importFromWkt( (char **) &pszDefinition );
         if( err == OGRERR_NONE && bESRI )
             err = morphFromESRI();
 
         return err;
     }
 
-    if( EQUALN(pszDefinition,"EPSG:",5) 
-        || EQUALN(pszDefinition,"EPSGA:",6) )
+    if( STARTS_WITH_CI(pszDefinition, "EPSG:")
+        || STARTS_WITH_CI(pszDefinition, "EPSGA:") )
     {
-        OGRErr eStatus; 
+        OGRErr eStatus = OGRERR_NONE;
 
-        if( EQUALN(pszDefinition,"EPSG:",5) )
+        if( STARTS_WITH_CI(pszDefinition, "EPSG:") )
             eStatus = importFromEPSG( atoi(pszDefinition+5) );
-        
-        else /* if( EQUALN(pszDefinition,"EPSGA:",6) ) */
+
+        else /* if( STARTS_WITH_CI(pszDefinition, "EPSGA:") ) */
             eStatus = importFromEPSGA( atoi(pszDefinition+6) );
-        
+
         // Do we want to turn this into a compound definition
         // with a vertical datum?
         if( eStatus == OGRERR_NONE && strchr( pszDefinition, '+' ) != NULL )
         {
             OGRSpatialReference oVertSRS;
 
-            eStatus = oVertSRS.importFromEPSG( 
+            eStatus = oVertSRS.importFromEPSG(
                 atoi(strchr(pszDefinition,'+')+1) );
             if( eStatus == OGRERR_NONE )
             {
@@ -1980,43 +1978,42 @@ OGRErr OGRSpatialReference::SetFromUserInput( const char * pszDefinition )
                 GetRoot()->AddChild( poHorizSRS );
                 GetRoot()->AddChild( oVertSRS.GetRoot()->Clone() );
             }
-            
-            return eStatus;
         }
-        else
-            return eStatus;
+
+        return eStatus;
     }
 
-    if( EQUALN(pszDefinition,"urn:ogc:def:crs:",16)
-        || EQUALN(pszDefinition,"urn:ogc:def:crs,crs:",20)
-        || EQUALN(pszDefinition,"urn:x-ogc:def:crs:",18)
-        || EQUALN(pszDefinition,"urn:opengis:crs:",16)
-        || EQUALN(pszDefinition,"urn:opengis:def:crs:",20))
+    if( STARTS_WITH_CI(pszDefinition, "urn:ogc:def:crs:")
+        || STARTS_WITH_CI(pszDefinition, "urn:ogc:def:crs,crs:")
+        || STARTS_WITH_CI(pszDefinition, "urn:x-ogc:def:crs:")
+        || STARTS_WITH_CI(pszDefinition, "urn:opengis:crs:")
+        || STARTS_WITH_CI(pszDefinition, "urn:opengis:def:crs:"))
         return importFromURN( pszDefinition );
 
-    if( EQUALN(pszDefinition,"http://opengis.net/def/crs",26)
-        || EQUALN(pszDefinition,"http://www.opengis.net/def/crs",30)
-        || EQUALN(pszDefinition,"www.opengis.net/def/crs",23))
+    if( STARTS_WITH_CI(pszDefinition, "http://opengis.net/def/crs")
+        || STARTS_WITH_CI(pszDefinition, "http://www.opengis.net/def/crs")
+        || STARTS_WITH_CI(pszDefinition, "www.opengis.net/def/crs"))
         return importFromCRSURL( pszDefinition );
 
-    if( EQUALN(pszDefinition,"AUTO:",5) )
+    if( STARTS_WITH_CI(pszDefinition, "AUTO:") )
         return importFromWMSAUTO( pszDefinition );
 
-    if( EQUALN(pszDefinition,"OGC:",4) )  // WMS/WCS OGC codes like OGC:CRS84
+    // WMS/WCS OGC codes like OGC:CRS84.
+    if( STARTS_WITH_CI(pszDefinition, "OGC:") )
         return SetWellKnownGeogCS( pszDefinition+4 );
 
-    if( EQUALN(pszDefinition,"CRS:",4) )
+    if( STARTS_WITH_CI(pszDefinition, "CRS:") )
         return SetWellKnownGeogCS( pszDefinition );
 
-    if( EQUALN(pszDefinition,"DICT:",5) 
+    if( STARTS_WITH_CI(pszDefinition, "DICT:")
         && strstr(pszDefinition,",") )
     {
         char *pszFile = CPLStrdup(pszDefinition+5);
         char *pszCode = strstr(pszFile,",") + 1;
-        
+
         pszCode[-1] = '\0';
 
-        err = importFromDict( pszFile, pszCode );
+        OGRErr err = importFromDict( pszFile, pszCode );
         CPLFree( pszFile );
 
         if( err == OGRERR_NONE && bESRI )
@@ -2025,31 +2022,31 @@ OGRErr OGRSpatialReference::SetFromUserInput( const char * pszDefinition )
         return err;
     }
 
-    if( EQUAL(pszDefinition,"NAD27") 
-        || EQUAL(pszDefinition,"NAD83") 
-        || EQUAL(pszDefinition,"WGS84") 
+    if( EQUAL(pszDefinition,"NAD27")
+        || EQUAL(pszDefinition,"NAD83")
+        || EQUAL(pszDefinition,"WGS84")
         || EQUAL(pszDefinition,"WGS72") )
     {
         Clear();
         return SetWellKnownGeogCS( pszDefinition );
     }
 
-    if( strstr(pszDefinition,"+proj") != NULL 
+    if( strstr(pszDefinition,"+proj") != NULL
              || strstr(pszDefinition,"+init") != NULL )
         return importFromProj4( pszDefinition );
 
-    if( EQUALN(pszDefinition,"IGNF:", 5) )
+    if( STARTS_WITH_CI(pszDefinition, "IGNF:") )
     {
         char* pszProj4Str = (char*) CPLMalloc(6 + strlen(pszDefinition) + 1);
         strcpy(pszProj4Str, "+init=");
         strcat(pszProj4Str, pszDefinition);
-        err = importFromProj4( pszProj4Str );
+        const OGRErr err = importFromProj4( pszProj4Str );
         CPLFree(pszProj4Str);
 
         return err;
     }
 
-    if( EQUALN(pszDefinition,"http://",7) )
+    if( STARTS_WITH_CI(pszDefinition, "http://") )
     {
         return importFromUrl (pszDefinition);
     }
@@ -2062,22 +2059,18 @@ OGRErr OGRSpatialReference::SetFromUserInput( const char * pszDefinition )
 /* -------------------------------------------------------------------- */
 /*      Try to open it as a file.                                       */
 /* -------------------------------------------------------------------- */
-    FILE        *fp;
-    int         nBufMax = 100000;
-    char        *pszBufPtr, *pszBuffer;
-    int         nBytes;
-
-    fp = VSIFOpen( pszDefinition, "rt" );
+    VSILFILE * const fp = VSIFOpenL( pszDefinition, "rt" );
     if( fp == NULL )
         return OGRERR_CORRUPT_DATA;
 
-    pszBuffer = (char *) CPLMalloc(nBufMax);
-    nBytes = VSIFRead( pszBuffer, 1, nBufMax-1, fp );
-    VSIFClose( fp );
+    const size_t nBufMax = 100000;
+    char * const pszBuffer = static_cast<char *>( CPLMalloc(nBufMax) );
+    const size_t nBytes = VSIFReadL( pszBuffer, 1, nBufMax-1, fp );
+    VSIFCloseL( fp );
 
     if( nBytes == nBufMax-1 )
     {
-        CPLDebug( "OGR", 
+        CPLDebug( "OGR",
                   "OGRSpatialReference::SetFromUserInput(%s), opened file\n"
                   "but it is to large for our generous buffer.  Is it really\n"
                   "just a WKT definition?", pszDefinition );
@@ -2087,25 +2080,27 @@ OGRErr OGRSpatialReference::SetFromUserInput( const char * pszDefinition )
 
     pszBuffer[nBytes] = '\0';
 
-    pszBufPtr = pszBuffer;
+    char *pszBufPtr = pszBuffer;
     while( pszBufPtr[0] == ' ' || pszBufPtr[0] == '\n' )
         pszBufPtr++;
 
+    OGRErr err = OGRERR_NONE;
     if( pszBufPtr[0] == '<' )
         err = importFromXML( pszBufPtr );
-    else if( (strstr(pszBuffer,"+proj") != NULL  
+    else if( (strstr(pszBuffer,"+proj") != NULL
               || strstr(pszBuffer,"+init") != NULL)
              && (strstr(pszBuffer,"EXTENSION") == NULL
                  && strstr(pszBuffer,"extension") == NULL) )
         err = importFromProj4( pszBufPtr );
     else
     {
-        if( EQUALN(pszBufPtr,"ESRI::",6) )
+        if( STARTS_WITH_CI(pszBufPtr, "ESRI::") )
         {
-            bESRI = TRUE;
+            bESRI = true;
             pszBufPtr += 6;
         }
 
+        /* coverity[tainted_data] */
         err = importFromWkt( &pszBufPtr );
         if( err == OGRERR_NONE && bESRI )
             err = morphFromESRI();
@@ -2125,13 +2120,13 @@ OGRErr OGRSpatialReference::SetFromUserInput( const char * pszDefinition )
  *
  * This function is the same as OGRSpatialReference::SetFromUserInput()
  */
-OGRErr CPL_STDCALL OSRSetFromUserInput( OGRSpatialReferenceH hSRS, 
+OGRErr CPL_STDCALL OSRSetFromUserInput( OGRSpatialReferenceH hSRS,
                                         const char *pszDef )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetFromUserInput", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetFromUserInput", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetFromUserInput( pszDef );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetFromUserInput( pszDef );
 }
 
 
@@ -2142,25 +2137,23 @@ OGRErr CPL_STDCALL OSRSetFromUserInput( OGRSpatialReferenceH hSRS,
 /**
  * \brief Set spatial reference from a URL.
  *
- * This method will download the spatial reference at a given URL and 
- * feed it into SetFromUserInput for you.  
+ * This method will download the spatial reference at a given URL and
+ * feed it into SetFromUserInput for you.
  *
  * This method does the same thing as the OSRImportFromUrl() function.
- * 
+ *
  * @param pszUrl text definition to try to deduce SRS from.
  *
- * @return OGRERR_NONE on success, or an error code with the curl 
+ * @return OGRERR_NONE on success, or an error code with the curl
  * error message if it is unable to dowload data.
- */ 
+ */
 
 OGRErr OGRSpatialReference::importFromUrl( const char * pszUrl )
 
 {
-
-
-    if( !EQUALN(pszUrl,"http://",7) )
+    if( !STARTS_WITH_CI(pszUrl, "http://") )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "The given string is not recognized as a URL"
                   "starting with 'http://' -- %s", pszUrl );
         return OGRERR_FAILURE;
@@ -2173,12 +2166,12 @@ OGRErr OGRSpatialReference::importFromUrl( const char * pszUrl )
 
     const char* pszHeaders = "HEADERS=Accept: application/x-ogcwkt";
     const char* pszTimeout = "TIMEOUT=10";
-    char *apszOptions[] = { 
-        (char *) pszHeaders,
-        (char *) pszTimeout,
-        NULL 
+    char *apszOptions[] = {
+        const_cast<char *>(pszHeaders),
+        const_cast<char *>(pszTimeout),
+        NULL
     };
-        
+
     CPLHTTPResult *psResult = CPLHTTPFetch( pszUrl, apszOptions );
 
 /* -------------------------------------------------------------------- */
@@ -2187,29 +2180,29 @@ OGRErr OGRSpatialReference::importFromUrl( const char * pszUrl )
 
     if ( psResult == NULL)
         return OGRERR_FAILURE;
-    if( psResult->nDataLen == 0 
+    if( psResult->nDataLen == 0
         || CPLGetLastErrorNo() != 0 || psResult->pabyData == NULL  )
     {
         if (CPLGetLastErrorNo() == 0)
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                     "No data was returned from the given URL" );
         }
         CPLHTTPDestroyResult( psResult );
         return OGRERR_FAILURE;
     }
 
-    if (psResult->nStatus != 0) 
+    if (psResult->nStatus != 0)
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Curl reports error: %d: %s", psResult->nStatus, psResult->pszErrBuf );
         CPLHTTPDestroyResult( psResult );
-        return OGRERR_FAILURE;        
+        return OGRERR_FAILURE;
     }
 
-    if( EQUALN( (const char*) psResult->pabyData,"http://",7) )
+    if( STARTS_WITH_CI((const char*) psResult->pabyData, "http://") )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "The data that was downloaded also starts with 'http://' "
                   "and cannot be passed into SetFromUserInput.  Is this "
                   "really a spatial reference definition? ");
@@ -2217,7 +2210,7 @@ OGRErr OGRSpatialReference::importFromUrl( const char * pszUrl )
         return OGRERR_FAILURE;
     }
     if( OGRERR_NONE != SetFromUserInput( (const char *) psResult->pabyData )) {
-        CPLHTTPDestroyResult( psResult );        
+        CPLHTTPDestroyResult( psResult );
         return OGRERR_FAILURE;
     }
 
@@ -2237,9 +2230,9 @@ OGRErr OGRSpatialReference::importFromUrl( const char * pszUrl )
 OGRErr OSRImportFromUrl( OGRSpatialReferenceH hSRS, const char *pszUrl )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRImportFromUrl", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRImportFromUrl", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->importFromUrl( pszUrl );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->importFromUrl( pszUrl );
 }
 
 /************************************************************************/
@@ -2249,55 +2242,53 @@ OGRErr OGRSpatialReference::importFromURNPart(const char* pszAuthority,
                                               const char* pszCode,
                                               const char* pszURN)
 {
-
 /* -------------------------------------------------------------------- */
 /*      Is this an EPSG code? Note that we import it with EPSG          */
 /*      preferred axis ordering for geographic coordinate systems!      */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszAuthority,"EPSG",4) )
+    if( STARTS_WITH_CI(pszAuthority, "EPSG") )
         return importFromEPSGA( atoi(pszCode) );
 
 /* -------------------------------------------------------------------- */
 /*      Is this an IAU code?  Lets try for the IAU2000 dictionary.      */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszAuthority,"IAU",3) )
+    if( STARTS_WITH_CI(pszAuthority, "IAU") )
         return importFromDict( "IAU2000.wkt", pszCode );
 
 /* -------------------------------------------------------------------- */
 /*      Is this an OGC code?                                            */
 /* -------------------------------------------------------------------- */
-    if( !EQUALN(pszAuthority,"OGC",3) )
+    if( !STARTS_WITH_CI(pszAuthority, "OGC") )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "URN %s has unrecognised authority.",
+                  "URN %s has unrecognized authority.",
                   pszURN );
         return OGRERR_FAILURE;
     }
 
-    if( EQUALN(pszCode,"CRS84",5) )
+    if( STARTS_WITH_CI(pszCode, "CRS84") )
         return SetWellKnownGeogCS( pszCode );
-    else if( EQUALN(pszCode,"CRS83",5) )
+    else if( STARTS_WITH_CI(pszCode, "CRS83") )
         return SetWellKnownGeogCS( pszCode );
-    else if( EQUALN(pszCode,"CRS27",5) )
+    else if( STARTS_WITH_CI(pszCode, "CRS27") )
         return SetWellKnownGeogCS( pszCode );
-    else if( EQUALN(pszCode,"84",2) ) /* urn:ogc:def:crs:OGC:2:84 */
+    else if( STARTS_WITH_CI(pszCode, "84") ) /* urn:ogc:def:crs:OGC:2:84 */
         return SetWellKnownGeogCS( "CRS84" );
 
 /* -------------------------------------------------------------------- */
 /*      Handle auto codes.  We need to convert from format              */
 /*      AUTO42001:99:8888 to format AUTO:42001,99,8888.                 */
 /* -------------------------------------------------------------------- */
-    else if( EQUALN(pszCode,"AUTO",4) )
+    else if( STARTS_WITH_CI(pszCode, "AUTO") )
     {
-        char szWMSAuto[100];
-        int i;
+      char szWMSAuto[100] = { '\0' };
 
         if( strlen(pszCode) > sizeof(szWMSAuto)-2 )
             return OGRERR_FAILURE;
 
         strcpy( szWMSAuto, "AUTO:" );
         strcpy( szWMSAuto + 5, pszCode + 4 );
-        for( i = 5; szWMSAuto[i] != '\0'; i++ )
+        for( int i = 5; szWMSAuto[i] != '\0'; i++ )
         {
             if( szWMSAuto[i] == ':' )
                 szWMSAuto[i] = ',';
@@ -2323,17 +2314,17 @@ OGRErr OGRSpatialReference::importFromURNPart(const char* pszAuthority,
 /************************************************************************/
 
 /**
- * \brief Initialize from OGC URN. 
+ * \brief Initialize from OGC URN.
  *
  * Initializes this spatial reference from a coordinate system defined
- * by an OGC URN prefixed with "urn:ogc:def:crs:" per recommendation 
- * paper 06-023r1.  Currently EPSG and OGC authority values are supported, 
- * including OGC auto codes, but not including CRS1 or CRS88 (NAVD88). 
+ * by an OGC URN prefixed with "urn:ogc:def:crs:" per recommendation
+ * paper 06-023r1.  Currently EPSG and OGC authority values are supported,
+ * including OGC auto codes, but not including CRS1 or CRS88 (NAVD88).
  *
  * This method is also support through SetFromUserInput() which can
  * normally be used for URNs.
- * 
- * @param pszURN the urn string. 
+ *
+ * @param pszURN the urn string.
  *
  * @return OGRERR_NONE on success or an error code.
  */
@@ -2341,21 +2332,21 @@ OGRErr OGRSpatialReference::importFromURNPart(const char* pszAuthority,
 OGRErr OGRSpatialReference::importFromURN( const char *pszURN )
 
 {
-    const char *pszCur;
+    const char *pszCur = NULL;
 
-    if( EQUALN(pszURN,"urn:ogc:def:crs:",16) )
+    if( STARTS_WITH_CI(pszURN, "urn:ogc:def:crs:") )
         pszCur = pszURN + 16;
-    else if( EQUALN(pszURN,"urn:ogc:def:crs,crs:",20) )
+    else if( STARTS_WITH_CI(pszURN, "urn:ogc:def:crs,crs:") )
         pszCur = pszURN + 20;
-    else if( EQUALN(pszURN,"urn:x-ogc:def:crs:",18) )
+    else if( STARTS_WITH_CI(pszURN, "urn:x-ogc:def:crs:") )
         pszCur = pszURN + 18;
-    else if( EQUALN(pszURN,"urn:opengis:crs:",16) )
+    else if( STARTS_WITH_CI(pszURN, "urn:opengis:crs:") )
         pszCur = pszURN + 16;
-    else if( EQUALN(pszURN,"urn:opengis:def:crs:",20) )
+    else if( STARTS_WITH_CI(pszURN, "urn:opengis:def:crs:") )
         pszCur = pszURN + 20;
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "URN %s not a supported format.", pszURN );
         return OGRERR_FAILURE;
     }
@@ -2389,9 +2380,10 @@ OGRErr OGRSpatialReference::importFromURN( const char *pszURN )
     if( *pszCur == ':' )
         pszCur++;
     else
-        /* We come here in the case, the content to parse is authority:code (instead of authority::code) */
-        /* which is probably illegal according to http://www.opengeospatial.org/ogcUrnPolicy */
-        /* but such content is found for example in what is returned by GeoServer */
+        // We come here in the case, the content to parse is authority:code
+        // (instead of authority::code) which is probably illegal according to
+        // http://www.opengeospatial.org/ogcUrnPolicy but such content is found
+        // for example in what is returned by GeoServer.
         pszCur = pszBeforeVersion;
 
     const char *pszCode = pszCur;
@@ -2400,10 +2392,9 @@ OGRErr OGRSpatialReference::importFromURN( const char *pszURN )
     if (pszComma == NULL)
         return importFromURNPart(pszAuthority, pszCode, pszURN);
 
-
     /* There's a second part with the vertical SRS */
     pszCur = pszComma + 1;
-    if (strncmp(pszCur, "crs:", 4) != 0)
+    if (!STARTS_WITH(pszCur, "crs:"))
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "URN %s not a supported format.", pszURN );
@@ -2419,54 +2410,51 @@ OGRErr OGRSpatialReference::importFromURN( const char *pszURN )
 
     // Do we want to turn this into a compound definition
     // with a vertical datum?
-    if( eStatus == OGRERR_NONE )
-    {
-        OGRSpatialReference oVertSRS;
+    if( eStatus != OGRERR_NONE )
+        return eStatus;
 
     /* -------------------------------------------------------------------- */
     /*      Find code (ignoring version) out of string like:                */
     /*                                                                      */
     /*      authority:[version]:code                                        */
     /* -------------------------------------------------------------------- */
-        pszAuthority = pszCur;
-
-        // skip authority
-        while( *pszCur != ':' && *pszCur )
-            pszCur++;
-        if( *pszCur == ':' )
-            pszCur++;
-
-        // skip version
-        pszBeforeVersion = pszCur;
-        while( *pszCur != ':' && *pszCur )
-            pszCur++;
-        if( *pszCur == ':' )
-            pszCur++;
-        else
-            pszCur = pszBeforeVersion;
+    pszAuthority = pszCur;
 
-        pszCode = pszCur;
+    // skip authority
+    while( *pszCur != ':' && *pszCur )
+        pszCur++;
+    if( *pszCur == ':' )
+        pszCur++;
 
-        eStatus = oVertSRS.importFromURNPart(pszAuthority, pszCode, pszURN);
-        if( eStatus == OGRERR_NONE )
-        {
-            OGR_SRSNode *poHorizSRS = GetRoot()->Clone();
+    // skip version
+    pszBeforeVersion = pszCur;
+    while( *pszCur != ':' && *pszCur )
+        pszCur++;
+    if( *pszCur == ':' )
+        pszCur++;
+    else
+        pszCur = pszBeforeVersion;
 
-            Clear();
+    pszCode = pszCur;
 
-            CPLString osName = poHorizSRS->GetChild(0)->GetValue();
-            osName += " + ";
-            osName += oVertSRS.GetRoot()->GetChild(0)->GetValue();
+    OGRSpatialReference oVertSRS;
+    eStatus = oVertSRS.importFromURNPart(pszAuthority, pszCode, pszURN);
+    if( eStatus == OGRERR_NONE )
+    {
+        OGR_SRSNode *poHorizSRS = GetRoot()->Clone();
 
-            SetNode( "COMPD_CS", osName );
-            GetRoot()->AddChild( poHorizSRS );
-            GetRoot()->AddChild( oVertSRS.GetRoot()->Clone() );
-        }
+        Clear();
 
-        return eStatus;
+        CPLString osName = poHorizSRS->GetChild(0)->GetValue();
+        osName += " + ";
+        osName += oVertSRS.GetRoot()->GetChild(0)->GetValue();
+
+        SetNode( "COMPD_CS", osName );
+        GetRoot()->AddChild( poHorizSRS );
+        GetRoot()->AddChild( oVertSRS.GetRoot()->Clone() );
     }
-    else
-        return eStatus;
+
+    return eStatus;
 }
 
 /************************************************************************/
@@ -2476,17 +2464,17 @@ OGRErr OGRSpatialReference::importFromURN( const char *pszURN )
 /************************************************************************/
 
 /**
- * \brief Initialize from OGC URL. 
+ * \brief Initialize from OGC URL.
  *
  * Initializes this spatial reference from a coordinate system defined
- * by an OGC URL prefixed with "http://opengis.net/def/crs" per best practice 
- * paper 11-135.  Currently EPSG and OGC authority values are supported, 
- * including OGC auto codes, but not including CRS1 or CRS88 (NAVD88). 
+ * by an OGC URL prefixed with "http://opengis.net/def/crs" per best practice
+ * paper 11-135.  Currently EPSG and OGC authority values are supported,
+ * including OGC auto codes, but not including CRS1 or CRS88 (NAVD88).
  *
  * This method is also supported through SetFromUserInput() which can
  * normally be used for URLs.
- * 
- * @param pszURL the URL string. 
+ *
+ * @param pszURL the URL string.
  *
  * @return OGRERR_NONE on success or an error code.
  */
@@ -2494,17 +2482,17 @@ OGRErr OGRSpatialReference::importFromURN( const char *pszURN )
 OGRErr OGRSpatialReference::importFromCRSURL( const char *pszURL )
 
 {
-    const char *pszCur;
-    
-    if( EQUALN(pszURL,"http://opengis.net/def/crs",26) )
+    const char *pszCur = NULL;
+
+    if( STARTS_WITH_CI(pszURL, "http://opengis.net/def/crs") )
         pszCur = pszURL + 26;
-    else if( EQUALN(pszURL,"http://www.opengis.net/def/crs",30) )
+    else if( STARTS_WITH_CI(pszURL, "http://www.opengis.net/def/crs") )
         pszCur = pszURL + 30;
-    else if( EQUALN(pszURL,"www.opengis.net/def/crs",23) )
+    else if( STARTS_WITH_CI(pszURL, "www.opengis.net/def/crs") )
         pszCur = pszURL + 23;
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "URL %s not a supported format.", pszURL );
         return OGRERR_FAILURE;
     }
@@ -2518,7 +2506,7 @@ OGRErr OGRSpatialReference::importFromCRSURL( const char *pszURL )
         poRoot = NULL;
     }
 
-    if( EQUALN(pszCur, "-compound?1=", 12) )
+    if( STARTS_WITH_CI(pszCur, "-compound?1=") )
     {
 /* -------------------------------------------------------------------- */
 /*      It's a compound CRS, of the form:                               */
@@ -2526,30 +2514,30 @@ OGRErr OGRSpatialReference::importFromCRSURL( const char *pszURL )
 /*      http://opengis.net/def/crs-compound?1=URL1&2=URL2&3=URL3&..     */
 /* -------------------------------------------------------------------- */
         pszCur += 12;
-        
+
         // extract each component CRS URL
         int iComponentUrl = 2;
 
         CPLString osName = "";
         Clear();
-        
+
         while (iComponentUrl != -1)
         {
             char searchStr[5];
-            sprintf(searchStr, "&%d=", iComponentUrl);
-            
+            snprintf(searchStr, sizeof(searchStr), "&%d=", iComponentUrl);
+
             const char* pszUrlEnd = strstr(pszCur, searchStr);
-            
+
             // figure out the next component URL
             char* pszComponentUrl;
-            
+
             if( pszUrlEnd )
             {
                 size_t nLen = pszUrlEnd - pszCur;
                 pszComponentUrl = (char*) CPLMalloc(nLen + 1);
                 strncpy(pszComponentUrl, pszCur, nLen);
                 pszComponentUrl[nLen] = '\0';
-                
+
                 ++iComponentUrl;
                 pszCur += nLen + strlen(searchStr);
             }
@@ -2557,7 +2545,7 @@ OGRErr OGRSpatialReference::importFromCRSURL( const char *pszURL )
             {
                 if( iComponentUrl == 2 )
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined, 
+                    CPLError( CE_Failure, CPLE_AppDefined,
                               "Compound CRS URLs must have at least two component CRSs." );
                     return OGRERR_FAILURE;
                 }
@@ -2568,13 +2556,13 @@ OGRErr OGRSpatialReference::importFromCRSURL( const char *pszURL )
                     iComponentUrl = -1;
                 }
             }
-            
+
             OGRSpatialReference oComponentSRS;
             OGRErr eStatus = oComponentSRS.importFromCRSURL( pszComponentUrl );
 
             CPLFree(pszComponentUrl);
             pszComponentUrl = NULL;
-            
+
             if( eStatus == OGRERR_NONE )
             {
                 if( osName.length() != 0 )
@@ -2588,37 +2576,33 @@ OGRErr OGRSpatialReference::importFromCRSURL( const char *pszURL )
             else
                 return eStatus;
         }
-        
-        
+
         return OGRERR_NONE;
     }
-    else
-    {
+
 /* -------------------------------------------------------------------- */
 /*      It's a normal CRS URL, of the form:                             */
 /*                                                                      */
 /*      http://opengis.net/def/crs/AUTHORITY/VERSION/CODE               */
 /* -------------------------------------------------------------------- */
-        ++pszCur;
-        const char *pszAuthority = pszCur;
-
-        // skip authority
-        while( *pszCur != '/' && *pszCur )
-            pszCur++;
-        if( *pszCur == '/' )
-            pszCur++;
-        
-
-        // skip version
-        while( *pszCur != '/' && *pszCur )
-            pszCur++;
-        if( *pszCur == '/' )
-            pszCur++;
-        
-        const char *pszCode = pszCur;
-        
-        return importFromURNPart( pszAuthority, pszCode, pszURL );
-    }
+    ++pszCur;
+    const char *pszAuthority = pszCur;
+
+    // skip authority
+    while( *pszCur != '/' && *pszCur )
+        pszCur++;
+    if( *pszCur == '/' )
+        pszCur++;
+
+    // skip version
+    while( *pszCur != '/' && *pszCur )
+        pszCur++;
+    if( *pszCur == '/' )
+        pszCur++;
+
+    const char *pszCode = pszCur;
+
+    return importFromURNPart( pszAuthority, pszCode, pszURL );
 }
 
 /************************************************************************/
@@ -2639,17 +2623,17 @@ OGRErr OGRSpatialReference::importFromCRSURL( const char *pszURL )
 OGRErr OGRSpatialReference::importFromWMSAUTO( const char * pszDefinition )
 
 {
-    char **papszTokens;
     int nProjId, nUnitsId;
     double dfRefLong, dfRefLat = 0.0;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Tokenize                                                        */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(pszDefinition,"AUTO:",5) )
+    if( STARTS_WITH_CI(pszDefinition, "AUTO:") )
         pszDefinition += 5;
 
-    papszTokens = CSLTokenizeStringComplex( pszDefinition, ",", FALSE, TRUE );
+    char **papszTokens =
+        CSLTokenizeStringComplex( pszDefinition, ",", FALSE, TRUE );
 
     if( CSLCount(papszTokens) == 4 )
     {
@@ -2673,7 +2657,7 @@ OGRErr OGRSpatialReference::importFromWMSAUTO( const char * pszDefinition )
         dfRefLat = CPLAtof(papszTokens[2]);
 
     }
-    else if( CSLCount(papszTokens) == 2 && atoi(papszTokens[0]) == 42005 ) 
+    else if( CSLCount(papszTokens) == 2 && atoi(papszTokens[0]) == 42005 )
     {
         nProjId = atoi(papszTokens[0]);
         nUnitsId = 9001;
@@ -2682,7 +2666,7 @@ OGRErr OGRSpatialReference::importFromWMSAUTO( const char * pszDefinition )
     else
     {
         CSLDestroy( papszTokens );
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "AUTO projection has wrong number of arguments, expected\n"
                   "AUTO:proj_id,units_id,ref_long,ref_lat or"
                   "AUTO:proj_id,ref_long,ref_lat" );
@@ -2690,6 +2674,7 @@ OGRErr OGRSpatialReference::importFromWMSAUTO( const char * pszDefinition )
     }
 
     CSLDestroy( papszTokens );
+    papszTokens = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Build coordsys.                                                 */
@@ -2699,12 +2684,12 @@ OGRErr OGRSpatialReference::importFromWMSAUTO( const char * pszDefinition )
     switch( nProjId )
     {
       case 42001: // Auto UTM
-        SetUTM( (int) floor( (dfRefLong + 180.0) / 6.0 ) + 1, 
+        SetUTM( (int) floor( (dfRefLong + 180.0) / 6.0 ) + 1,
                 dfRefLat >= 0.0 );
         break;
 
       case 42002: // Auto TM (strangely very UTM-like).
-        SetTM( 0, dfRefLong, 0.9996, 
+        SetTM( 0, dfRefLong, 0.9996,
                500000.0, (dfRefLat >= 0.0) ? 0.0 : 10000000.0 );
         break;
 
@@ -2722,7 +2707,7 @@ OGRErr OGRSpatialReference::importFromWMSAUTO( const char * pszDefinition )
 
       default:
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unsupported projection id in importFromWMSAUTO(): %d", 
+                  "Unsupported projection id in importFromWMSAUTO(): %d",
                   nProjId );
         return OGRERR_FAILURE;
     }
@@ -2746,13 +2731,13 @@ OGRErr OGRSpatialReference::importFromWMSAUTO( const char * pszDefinition )
         break;
 
       default:
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Unsupported units code (%d).", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Unsupported units code (%d).",
                   nUnitsId );
         return OGRERR_FAILURE;
         break;
     }
-    
+
     SetAuthority( "PROJCS|UNIT", "EPSG", nUnitsId );
 
 /* -------------------------------------------------------------------- */
@@ -2773,7 +2758,7 @@ OGRErr OGRSpatialReference::importFromWMSAUTO( const char * pszDefinition )
  * This method does the same thing as the C function OSRGetSemiMajor().
  *
  * @param pnErr if non-NULL set to OGRERR_FAILURE if semi major axis
- * can be found. 
+ * can be found.
  *
  * @return semi-major axis, or SRS_WGS84_SEMIMAJOR if it can't be found.
  */
@@ -2782,7 +2767,7 @@ double OGRSpatialReference::GetSemiMajor( OGRErr * pnErr ) const
 
 {
     const OGR_SRSNode *poSpheroid = GetAttrNode( "SPHEROID" );
-    
+
     if( pnErr != NULL )
         *pnErr = OGRERR_NONE;
 
@@ -2790,13 +2775,11 @@ double OGRSpatialReference::GetSemiMajor( OGRErr * pnErr ) const
     {
         return CPLAtof( poSpheroid->GetChild(1)->GetValue() );
     }
-    else
-    {
-        if( pnErr != NULL )
-            *pnErr = OGRERR_FAILURE;
 
-        return SRS_WGS84_SEMIMAJOR;
-    }
+    if( pnErr != NULL )
+        *pnErr = OGRERR_FAILURE;
+
+    return SRS_WGS84_SEMIMAJOR;
 }
 
 /************************************************************************/
@@ -2813,7 +2796,7 @@ double OSRGetSemiMajor( OGRSpatialReferenceH hSRS, OGRErr *pnErr )
 {
     VALIDATE_POINTER1( hSRS, "OSRGetSemiMajor", 0 );
 
-    return ((OGRSpatialReference *) hSRS)->GetSemiMajor( pnErr );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->GetSemiMajor( pnErr );
 }
 
 /************************************************************************/
@@ -2825,8 +2808,8 @@ double OSRGetSemiMajor( OGRSpatialReferenceH hSRS, OGRErr *pnErr )
  *
  * This method does the same thing as the C function OSRGetInvFlattening().
  *
- * @param pnErr if non-NULL set to OGRERR_FAILURE if no inverse flattening 
- * can be found. 
+ * @param pnErr if non-NULL set to OGRERR_FAILURE if no inverse flattening
+ * can be found.
  *
  * @return inverse flattening, or SRS_WGS84_INVFLATTENING if it can't be found.
  */
@@ -2835,7 +2818,7 @@ double OGRSpatialReference::GetInvFlattening( OGRErr * pnErr ) const
 
 {
     const OGR_SRSNode *poSpheroid = GetAttrNode( "SPHEROID" );
-    
+
     if( pnErr != NULL )
         *pnErr = OGRERR_NONE;
 
@@ -2843,13 +2826,11 @@ double OGRSpatialReference::GetInvFlattening( OGRErr * pnErr ) const
     {
         return CPLAtof( poSpheroid->GetChild(2)->GetValue() );
     }
-    else
-    {
-        if( pnErr != NULL )
-            *pnErr = OGRERR_FAILURE;
 
-        return SRS_WGS84_INVFLATTENING;
-    }
+    if( pnErr != NULL )
+        *pnErr = OGRERR_FAILURE;
+
+    return SRS_WGS84_INVFLATTENING;
 }
 
 /************************************************************************/
@@ -2866,7 +2847,7 @@ double OSRGetInvFlattening( OGRSpatialReferenceH hSRS, OGRErr *pnErr )
 {
     VALIDATE_POINTER1( hSRS, "OSRGetInvFlattening", 0 );
 
-    return ((OGRSpatialReference *) hSRS)->GetInvFlattening( pnErr );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->GetInvFlattening( pnErr );
 }
 
 /************************************************************************/
@@ -2879,7 +2860,7 @@ double OSRGetInvFlattening( OGRSpatialReferenceH hSRS, OGRErr *pnErr )
  * This method does the same thing as the C function OSRGetSemiMinor().
  *
  * @param pnErr if non-NULL set to OGRERR_FAILURE if semi minor axis
- * can be found. 
+ * can be found.
  *
  * @return semi-minor axis, or WGS84 semi minor if it can't be found.
  */
@@ -2887,10 +2868,8 @@ double OSRGetInvFlattening( OGRSpatialReferenceH hSRS, OGRErr *pnErr )
 double OGRSpatialReference::GetSemiMinor( OGRErr * pnErr ) const
 
 {
-    double      dfInvFlattening, dfSemiMajor;
-
-    dfSemiMajor = GetSemiMajor( pnErr );
-    dfInvFlattening = GetInvFlattening( pnErr );
+    const double dfSemiMajor = GetSemiMajor( pnErr );
+    const double dfInvFlattening = GetInvFlattening( pnErr );
 
     return OSRCalcSemiMinorFromInvFlattening(dfSemiMajor, dfInvFlattening);
 }
@@ -2909,7 +2888,7 @@ double OSRGetSemiMinor( OGRSpatialReferenceH hSRS, OGRErr *pnErr )
 {
     VALIDATE_POINTER1( hSRS, "OSRGetSemiMinor", 0 );
 
-    return ((OGRSpatialReference *) hSRS)->GetSemiMinor( pnErr );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->GetSemiMinor( pnErr );
 }
 
 /************************************************************************/
@@ -2919,34 +2898,32 @@ double OSRGetSemiMinor( OGRSpatialReferenceH hSRS, OGRErr *pnErr )
 /**
  * \brief Set the user visible LOCAL_CS name.
  *
- * This method is the same as the C function OSRSetLocalCS(). 
+ * This method is the same as the C function OSRSetLocalCS().
  *
  * This method will ensure a LOCAL_CS node is created as the root,
  * and set the provided name on it.  It must be used before SetLinearUnits().
  *
  * @param pszName the user visible name to assign.  Not used as a key.
- * 
+ *
  * @return OGRERR_NONE on success.
  */
 
 OGRErr OGRSpatialReference::SetLocalCS( const char * pszName )
 
 {
-    OGR_SRSNode *poCS = GetAttrNode( "LOCAL_CS" );
+    const OGR_SRSNode * const poCS = GetAttrNode( "LOCAL_CS" );
 
     if( poCS == NULL && GetRoot() != NULL )
     {
-        CPLDebug( "OGR", 
+        CPLDebug( "OGR",
                   "OGRSpatialReference::SetLocalCS(%s) failed.\n"
-               "It appears an incompatible root node (%s) already exists.\n",
+                  "It appears an incompatible root node (%s) already exists.\n",
                   pszName, GetRoot()->GetValue() );
         return OGRERR_FAILURE;
     }
-    else
-    {
-        SetNode( "LOCAL_CS", pszName );
-        return OGRERR_NONE;
-    }
+
+    SetNode( "LOCAL_CS", pszName );
+    return OGRERR_NONE;
 }
 
 /************************************************************************/
@@ -2961,9 +2938,9 @@ OGRErr OGRSpatialReference::SetLocalCS( const char * pszName )
 OGRErr OSRSetLocalCS( OGRSpatialReferenceH hSRS, const char * pszName )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetLocalCS", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetLocalCS", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetLocalCS( pszName );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetLocalCS( pszName );
 }
 
 /************************************************************************/
@@ -2973,15 +2950,15 @@ OGRErr OSRSetLocalCS( OGRSpatialReferenceH hSRS, const char * pszName )
 /**
  * \brief Set the user visible GEOCCS name.
  *
- * This method is the same as the C function OSRSetGeocCS(). 
+ * This method is the same as the C function OSRSetGeocCS().
 
  * This method will ensure a GEOCCS node is created as the root,
- * and set the provided name on it.  If used on a GEOGCS coordinate system, 
- * the DATUM and PRIMEM nodes from the GEOGCS will be tarnsferred over to 
- * the GEOGCS. 
+ * and set the provided name on it.  If used on a GEOGCS coordinate system,
+ * the DATUM and PRIMEM nodes from the GEOGCS will be transferred over to
+ * the GEOGCS.
  *
  * @param pszName the user visible name to assign.  Not used as a key.
- * 
+ *
  * @return OGRERR_NONE on success.
  *
  * @since OGR 1.9.0
@@ -3001,9 +2978,9 @@ OGRErr OGRSpatialReference::SetGeocCS( const char * pszName )
 
     if( poGeocCS == NULL && GetRoot() != NULL )
     {
-        CPLDebug( "OGR", 
+        CPLDebug( "OGR",
                   "OGRSpatialReference::SetGeocCS(%s) failed.\n"
-               "It appears an incompatible root node (%s) already exists.\n",
+                  "It appears an incompatible root node (%s) already exists.\n",
                   pszName, GetRoot()->GetValue() );
         return OGRERR_FAILURE;
     }
@@ -3014,7 +2991,7 @@ OGRErr OGRSpatialReference::SetGeocCS( const char * pszName )
     {
         OGR_SRSNode *poDatum = poGeogCS->GetNode( "DATUM" );
         OGR_SRSNode *poPRIMEM = poGeogCS->GetNode( "PRIMEM" );
-        if ( poDatum != NULL && poPRIMEM != NULL )
+        if ( poRoot != NULL && poDatum != NULL && poPRIMEM != NULL )
         {
             poRoot->InsertChild( poDatum->Clone(), 1 );
             poRoot->InsertChild( poPRIMEM->Clone(), 2 );
@@ -3039,9 +3016,9 @@ OGRErr OGRSpatialReference::SetGeocCS( const char * pszName )
 OGRErr OSRSetGeocCS( OGRSpatialReferenceH hSRS, const char * pszName )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetGeocCS", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetGeocCS", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetGeocCS( pszName );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetGeocCS( pszName );
 }
 
 /************************************************************************/
@@ -3051,7 +3028,7 @@ OGRErr OSRSetGeocCS( OGRSpatialReferenceH hSRS, const char * pszName )
 /**
  * \brief Set the user visible VERT_CS name.
  *
- * This method is the same as the C function OSRSetVertCS(). 
+ * This method is the same as the C function OSRSetVertCS().
 
  * This method will ensure a VERT_CS node is created if needed.  If the
  * existing coordinate system is GEOGCS or PROJCS rooted, then it will be
@@ -3059,12 +3036,12 @@ OGRErr OSRSetGeocCS( OGRSpatialReferenceH hSRS, const char * pszName )
  *
  * @param pszVertCSName the user visible name of the vertical coordinate
  * system. Not used as a key.
- *  
+ *
  * @param pszVertDatumName the user visible name of the vertical datum.  It
  * is helpful if this matches the EPSG name.
- * 
- * @param nVertDatumType the OGC vertical datum type, usually 2005. 
- * 
+ *
+ * @param nVertDatumType the OGC vertical datum type, usually 2005.
+ *
  * @return OGRERR_NONE on success.
  *
  * @since OGR 1.9.0
@@ -3094,7 +3071,7 @@ OGRErr OGRSpatialReference::SetVertCS( const char * pszVertCSName,
 /*      otherwise create the VERT_CS now.                               */
 /* -------------------------------------------------------------------- */
     OGR_SRSNode *poVertCS = GetAttrNode( "VERT_CS" );
-    
+
     if( poVertCS != NULL )
     {
         poVertCS->ClearChildren();
@@ -3113,20 +3090,19 @@ OGRErr OGRSpatialReference::SetVertCS( const char * pszVertCSName,
 /* -------------------------------------------------------------------- */
 /*      Set the name, datumname, and type.                              */
 /* -------------------------------------------------------------------- */
-    OGR_SRSNode *poVertDatum;
 
     poVertCS->AddChild( new OGR_SRSNode( pszVertCSName ) );
-    
-    poVertDatum = new OGR_SRSNode( "VERT_DATUM" );
+
+    OGR_SRSNode *poVertDatum = new OGR_SRSNode( "VERT_DATUM" );
     poVertCS->AddChild( poVertDatum );
-        
+
     poVertDatum->AddChild( new OGR_SRSNode( pszVertDatumName ) );
 
     CPLString osVertDatumType;
     osVertDatumType.Printf( "%d", nVertDatumType );
     poVertDatum->AddChild( new OGR_SRSNode( osVertDatumType ) );
 
-    // add default axis node.
+    // Add default axis node.
     OGR_SRSNode *poAxis = new OGR_SRSNode( "AXIS" );
 
     poAxis->AddChild( new OGR_SRSNode( "Up" ) );
@@ -3154,11 +3130,10 @@ OGRErr OSRSetVertCS( OGRSpatialReferenceH hSRS,
                      int nVertDatumType )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetVertCS", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetVertCS", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetVertCS( pszVertCSName,
-                                                      pszVertDatumName,
-                                                      nVertDatumType );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
+        SetVertCS( pszVertCSName, pszVertDatumName, nVertDatumType );
 }
 
 /************************************************************************/
@@ -3168,21 +3143,21 @@ OGRErr OSRSetVertCS( OGRSpatialReferenceH hSRS,
 /**
  * \brief Setup a compound coordinate system.
  *
- * This method is the same as the C function OSRSetCompoundCS(). 
+ * This method is the same as the C function OSRSetCompoundCS().
 
  * This method is replace the current SRS with a COMPD_CS coordinate system
  * consisting of the passed in horizontal and vertical coordinate systems.
  *
- * @param pszName the name of the compound coordinate system. 
- * 
+ * @param pszName the name of the compound coordinate system.
+ *
  * @param poHorizSRS the horizontal SRS (PROJCS or GEOGCS).
- *  
+ *
  * @param poVertSRS the vertical SRS (VERT_CS).
- * 
+ *
  * @return OGRERR_NONE on success.
  */
 
-OGRErr 
+OGRErr
 OGRSpatialReference::SetCompoundCS( const char *pszName,
                                     const OGRSpatialReference *poHorizSRS,
                                     const OGRSpatialReference *poVertSRS )
@@ -3192,16 +3167,16 @@ OGRSpatialReference::SetCompoundCS( const char *pszName,
 /*      Verify these are legal horizontal and vertical coordinate       */
 /*      systems.                                                        */
 /* -------------------------------------------------------------------- */
-    if( !poVertSRS->IsVertical() ) 
+    if( !poVertSRS->IsVertical() )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "SetCompoundCS() fails, vertical component is not VERT_CS." );
         return OGRERR_FAILURE;
     }
-    if( !poHorizSRS->IsProjected() 
+    if( !poHorizSRS->IsProjected()
         && !poHorizSRS->IsGeographic() )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "SetCompoundCS() fails, horizontal component is not PROJCS or GEOGCS." );
         return OGRERR_FAILURE;
     }
@@ -3215,7 +3190,7 @@ OGRSpatialReference::SetCompoundCS( const char *pszName,
     poRoot->AddChild( new OGR_SRSNode( pszName ) );
     poRoot->AddChild( poHorizSRS->GetRoot()->Clone() );
     poRoot->AddChild( poVertSRS->GetRoot()->Clone() );
-    
+
     return OGRERR_NONE;
 }
 
@@ -3234,14 +3209,14 @@ OGRErr OSRSetCompoundCS( OGRSpatialReferenceH hSRS,
                          OGRSpatialReferenceH hVertSRS )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetCompoundCS", CE_Failure );
-    VALIDATE_POINTER1( hHorizSRS, "OSRSetCompoundCS", CE_Failure );
-    VALIDATE_POINTER1( hVertSRS, "OSRSetCompoundCS", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetCompoundCS", OGRERR_FAILURE );
+    VALIDATE_POINTER1( hHorizSRS, "OSRSetCompoundCS", OGRERR_FAILURE );
+    VALIDATE_POINTER1( hVertSRS, "OSRSetCompoundCS", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
         SetCompoundCS( pszName,
-                       (OGRSpatialReference *) hHorizSRS,
-                       (OGRSpatialReference *) hVertSRS );
+                       reinterpret_cast<OGRSpatialReference *>(hHorizSRS),
+                       reinterpret_cast<OGRSpatialReference *>(hVertSRS) );
 }
 
 /************************************************************************/
@@ -3251,14 +3226,14 @@ OGRErr OSRSetCompoundCS( OGRSpatialReferenceH hSRS,
 /**
  * \brief Set the user visible PROJCS name.
  *
- * This method is the same as the C function OSRSetProjCS(). 
+ * This method is the same as the C function OSRSetProjCS().
  *
  * This method will ensure a PROJCS node is created as the root,
- * and set the provided name on it.  If used on a GEOGCS coordinate system, 
+ * and set the provided name on it.  If used on a GEOGCS coordinate system,
  * the GEOGCS node will be demoted to be a child of the new PROJCS root.
  *
  * @param pszName the user visible name to assign.  Not used as a key.
- * 
+ *
  * @return OGRERR_NONE on success.
  */
 
@@ -3276,16 +3251,16 @@ OGRErr OGRSpatialReference::SetProjCS( const char * pszName )
 
     if( poProjCS == NULL && GetRoot() != NULL )
     {
-        CPLDebug( "OGR", 
+        CPLDebug( "OGR",
                   "OGRSpatialReference::SetProjCS(%s) failed.\n"
-               "It appears an incompatible root node (%s) already exists.\n",
+                  "It appears an incompatible root node (%s) already exists.\n",
                   pszName, GetRoot()->GetValue() );
         return OGRERR_FAILURE;
     }
 
     SetNode( "PROJCS", pszName );
 
-    if( poGeogCS != NULL )
+    if( poRoot != NULL && poGeogCS != NULL )
         poRoot->InsertChild( poGeogCS, 1 );
 
     return OGRERR_NONE;
@@ -3303,9 +3278,9 @@ OGRErr OGRSpatialReference::SetProjCS( const char * pszName )
 OGRErr OSRSetProjCS( OGRSpatialReferenceH hSRS, const char * pszName )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetProjCS", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetProjCS", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetProjCS( pszName );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetProjCS( pszName );
 }
 
 /************************************************************************/
@@ -3318,7 +3293,7 @@ OGRErr OSRSetProjCS( OGRSpatialReferenceH hSRS, const char * pszName )
  * This method is the same as the C function OSRSetProjection().
  *
  * @param pszProjection the projection name, which should be selected from
- * the macros in ogr_srs_api.h, such as SRS_PT_TRANSVERSE_MERCATOR. 
+ * the macros in ogr_srs_api.h, such as SRS_PT_TRANSVERSE_MERCATOR.
  *
  * @return OGRERR_NONE on success.
  */
@@ -3327,7 +3302,6 @@ OGRErr OGRSpatialReference::SetProjection( const char * pszProjection )
 
 {
     OGR_SRSNode *poGeogCS = NULL;
-    OGRErr eErr;
 
     if( poRoot != NULL && EQUAL(poRoot->GetValue(),"GEOGCS") )
     {
@@ -3340,7 +3314,7 @@ OGRErr OGRSpatialReference::SetProjection( const char * pszProjection )
         SetNode( "PROJCS", "unnamed" );
     }
 
-    eErr = SetNode( "PROJCS|PROJECTION", pszProjection );
+    const OGRErr eErr = SetNode( "PROJCS|PROJECTION", pszProjection );
     if( eErr != OGRERR_NONE )
         return eErr;
 
@@ -3363,9 +3337,10 @@ OGRErr OSRSetProjection( OGRSpatialReferenceH hSRS,
                          const char * pszProjection )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetProjection", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetProjection", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetProjection( pszProjection );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
+        SetProjection( pszProjection );
 }
 
 /************************************************************************/
@@ -3382,12 +3357,12 @@ OGRErr OSRSetProjection( OGRSpatialReferenceH hSRS,
  * Please check http://www.remotesensing.org/geotiff/proj_list pages for
  * legal parameter names for specific projections.
  *
- * 
+ *
  * @param pszParmName the parameter name, which should be selected from
- * the macros in ogr_srs_api.h, such as SRS_PP_CENTRAL_MERIDIAN. 
+ * the macros in ogr_srs_api.h, such as SRS_PP_CENTRAL_MERIDIAN.
+ *
+ * @param dfValue value to assign.
  *
- * @param dfValue value to assign. 
- * 
  * @return OGRERR_NONE on success.
  */
 
@@ -3396,30 +3371,30 @@ OGRErr OGRSpatialReference::SetProjParm( const char * pszParmName,
 
 {
     OGR_SRSNode *poPROJCS = GetAttrNode( "PROJCS" );
-    OGR_SRSNode *poParm;
-    char        szValue[64];
 
     if( poPROJCS == NULL )
         return OGRERR_FAILURE;
 
-    OGRPrintDouble( szValue, dfValue );
+    char szValue[64] = { '\0' };
+    OGRsnPrintDouble( szValue, sizeof(szValue), dfValue );
 
 /* -------------------------------------------------------------------- */
 /*      Try to find existing parameter with this name.                  */
 /* -------------------------------------------------------------------- */
+    OGR_SRSNode *poParm = NULL;
     for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
     {
         poParm = poPROJCS->GetChild( iChild );
 
         if( EQUAL(poParm->GetValue(),"PARAMETER")
-            && poParm->GetChildCount() == 2 
+            && poParm->GetChildCount() == 2
             && EQUAL(poParm->GetChild(0)->GetValue(),pszParmName) )
         {
             poParm->GetChild(1)->SetValue( szValue );
             return OGRERR_NONE;
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Otherwise create a new parameter and append.                    */
 /* -------------------------------------------------------------------- */
@@ -3441,13 +3416,14 @@ OGRErr OGRSpatialReference::SetProjParm( const char * pszParmName,
  *
  * This function is the same as OGRSpatialReference::SetProjParm()
  */
-OGRErr OSRSetProjParm( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetProjParm( OGRSpatialReferenceH hSRS,
                        const char * pszParmName, double dfValue )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetProjParm", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetProjParm", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetProjParm( pszParmName, dfValue );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
+        SetProjParm( pszParmName, dfValue );
 }
 
 /************************************************************************/
@@ -3468,8 +3444,6 @@ int OGRSpatialReference::FindProjParm( const char *pszParameter,
                                        const OGR_SRSNode *poPROJCS ) const
 
 {
-    const OGR_SRSNode *poParameter = NULL;
-
     if( poPROJCS == NULL )
         poPROJCS = GetAttrNode( "PROJCS" );
 
@@ -3479,14 +3453,12 @@ int OGRSpatialReference::FindProjParm( const char *pszParameter,
 /* -------------------------------------------------------------------- */
 /*      Search for requested parameter.                                 */
 /* -------------------------------------------------------------------- */
-    int iChild;
-
-    for( iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
+    for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
     {
-        poParameter = poPROJCS->GetChild(iChild);
-        
+        const OGR_SRSNode *poParameter = poPROJCS->GetChild(iChild);
+
         if( EQUAL(poParameter->GetValue(),"PARAMETER")
-            && poParameter->GetChildCount() == 2 
+            && poParameter->GetChildCount() == 2
             && EQUAL(poPROJCS->GetChild(iChild)->GetChild(0)->GetValue(),
                      pszParameter) )
         {
@@ -3497,20 +3469,20 @@ int OGRSpatialReference::FindProjParm( const char *pszParameter,
 /* -------------------------------------------------------------------- */
 /*      Try similar names, for selected parameters.                     */
 /* -------------------------------------------------------------------- */
-    iChild = -1;
-
     if( EQUAL(pszParameter,SRS_PP_LATITUDE_OF_ORIGIN) )
     {
-        iChild = FindProjParm( SRS_PP_LATITUDE_OF_CENTER, poPROJCS );
+        return FindProjParm( SRS_PP_LATITUDE_OF_CENTER, poPROJCS );
     }
-    else if( EQUAL(pszParameter,SRS_PP_CENTRAL_MERIDIAN) )
+
+    if( EQUAL(pszParameter,SRS_PP_CENTRAL_MERIDIAN) )
     {
-        iChild = FindProjParm(SRS_PP_LONGITUDE_OF_CENTER, poPROJCS );
+        int iChild = FindProjParm(SRS_PP_LONGITUDE_OF_CENTER, poPROJCS );
         if( iChild == -1 )
             iChild = FindProjParm(SRS_PP_LONGITUDE_OF_ORIGIN, poPROJCS );
+        return iChild;
     }
 
-    return iChild;
+    return -1;
 }
 
 /************************************************************************/
@@ -3525,7 +3497,7 @@ int OGRSpatialReference::FindProjParm( const char *pszParameter,
  *
  * This method is the same as the C function OSRGetProjParm().
  *
- * @param pszName the name of the parameter to fetch, from the set of 
+ * @param pszName the name of the parameter to fetch, from the set of
  * SRS_PP codes in ogr_srs_api.h.
  *
  * @param dfDefaultValue the value to return if this parameter doesn't exist.
@@ -3540,30 +3512,30 @@ double OGRSpatialReference::GetProjParm( const char * pszName,
                                          OGRErr *pnErr ) const
 
 {
-    const OGR_SRSNode *poPROJCS = GetAttrNode( "PROJCS" );
-
     if( pnErr != NULL )
         *pnErr = OGRERR_NONE;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Find the desired parameter.                                     */
 /* -------------------------------------------------------------------- */
-    int iChild = FindProjParm( pszName, poPROJCS );
-
-    if( iChild != -1 )
+    const OGR_SRSNode *poPROJCS = GetAttrNode( "PROJCS" );
+    if ( poPROJCS == NULL )
     {
-        const OGR_SRSNode *poParameter = NULL;
-        poParameter = poPROJCS->GetChild(iChild);
-        return CPLAtof(poParameter->GetChild(1)->GetValue());
+        if( pnErr != NULL )
+            *pnErr = OGRERR_FAILURE;
+        return dfDefaultValue;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Return default value on failure.                                */
-/* -------------------------------------------------------------------- */
-    if( pnErr != NULL )
-        *pnErr = OGRERR_FAILURE;
+    const int iChild = FindProjParm( pszName, poPROJCS );
+    if( iChild == -1 )
+    {
+        if( pnErr != NULL )
+            *pnErr = OGRERR_FAILURE;
+        return dfDefaultValue;
+    }
 
-    return dfDefaultValue;
+    const OGR_SRSNode *poParameter = poPROJCS->GetChild(iChild);
+    return CPLAtof(poParameter->GetChild(1)->GetValue());
 }
 
 /************************************************************************/
@@ -3581,7 +3553,7 @@ double OSRGetProjParm( OGRSpatialReferenceH hSRS, const char *pszName,
 {
     VALIDATE_POINTER1( hSRS, "OSRGetProjParm", 0 );
 
-    return ((OGRSpatialReference *) hSRS)->
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
         GetProjParm(pszName, dfDefaultValue, pnErr);
 }
 
@@ -3593,12 +3565,12 @@ double OSRGetProjParm( OGRSpatialReferenceH hSRS, const char *pszName,
  * \brief Fetch a normalized projection parameter value.
  *
  * This method is the same as GetProjParm() except that the value of
- * the parameter is "normalized" into degrees or meters depending on 
+ * the parameter is "normalized" into degrees or meters depending on
  * whether it is linear or angular.
  *
  * This method is the same as the C function OSRGetNormProjParm().
  *
- * @param pszName the name of the parameter to fetch, from the set of 
+ * @param pszName the name of the parameter to fetch, from the set of
  * SRS_PP codes in ogr_srs_api.h.
  *
  * @param dfDefaultValue the value to return if this parameter doesn't exist.
@@ -3613,18 +3585,15 @@ double OGRSpatialReference::GetNormProjParm( const char * pszName,
                                              OGRErr *pnErr ) const
 
 {
-    double dfRawResult;
-    OGRErr nError;
-
-    if( pnErr == NULL )
-        pnErr = &nError;
-
     GetNormInfo();
 
-    dfRawResult = GetProjParm( pszName, dfDefaultValue, pnErr );
+    OGRErr nError = OGRERR_NONE;
+    double dfRawResult = GetProjParm( pszName, dfDefaultValue, &nError );
+    if( pnErr != NULL )
+        *pnErr = nError;
 
     // If we got the default just return it unadjusted.
-    if( *pnErr != OGRERR_NONE )
+    if( nError != OGRERR_NONE )
         return dfRawResult;
 
     if( dfToDegrees != 1.0 && IsAngularParameter(pszName) )
@@ -3636,8 +3605,8 @@ double OGRSpatialReference::GetNormProjParm( const char * pszName,
     else if( dfFromGreenwich != 0.0 && IsLongitudeParameter( pszName ) )
         return dfRawResult + dfFromGreenwich;
 #endif
-    else
-        return dfRawResult;
+
+    return dfRawResult;
 }
 
 /************************************************************************/
@@ -3655,7 +3624,7 @@ double OSRGetNormProjParm( OGRSpatialReferenceH hSRS, const char *pszName,
 {
     VALIDATE_POINTER1( hSRS, "OSRGetNormProjParm", 0 );
 
-    return ((OGRSpatialReference *) hSRS)->
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
         GetNormProjParm(pszName, dfDefaultValue, pnErr);
 }
 
@@ -3668,16 +3637,16 @@ double OSRGetNormProjParm( OGRSpatialReferenceH hSRS, const char *pszName,
  *
  * This method is the same as SetProjParm() except that the value of
  * the parameter passed in is assumed to be in "normalized" form (decimal
- * degrees for angular values, meters for linear values.  The values are 
+ * degrees for angular values, meters for linear values.  The values are
  * converted in a form suitable for the GEOGCS and linear units in effect.
  *
  * This method is the same as the C function OSRSetNormProjParm().
  *
  * @param pszName the parameter name, which should be selected from
- * the macros in ogr_srs_api.h, such as SRS_PP_CENTRAL_MERIDIAN. 
+ * the macros in ogr_srs_api.h, such as SRS_PP_CENTRAL_MERIDIAN.
+ *
+ * @param dfValue value to assign.
  *
- * @param dfValue value to assign. 
- * 
  * @return OGRERR_NONE on success.
  */
 
@@ -3687,7 +3656,7 @@ OGRErr OGRSpatialReference::SetNormProjParm( const char * pszName,
 {
     GetNormInfo();
 
-    if( (dfToDegrees != 1.0 || dfFromGreenwich != 0.0) 
+    if( (dfToDegrees != 1.0 || dfFromGreenwich != 0.0)
         && IsAngularParameter(pszName) )
     {
 #ifdef WKT_LONGITUDE_RELATIVE_TO_PM
@@ -3712,13 +3681,13 @@ OGRErr OGRSpatialReference::SetNormProjParm( const char * pszName,
  *
  * This function is the same as OGRSpatialReference::SetNormProjParm()
  */
-OGRErr OSRSetNormProjParm( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetNormProjParm( OGRSpatialReferenceH hSRS,
                            const char * pszParmName, double dfValue )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetNormProjParm", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetNormProjParm", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
         SetNormProjParm( pszParmName, dfValue );
 }
 
@@ -3746,18 +3715,18 @@ OGRErr OGRSpatialReference::SetTM( double dfCenterLat, double dfCenterLong,
 /*                              OSRSetTM()                              */
 /************************************************************************/
 
-OGRErr OSRSetTM( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetTM( OGRSpatialReferenceH hSRS,
                  double dfCenterLat, double dfCenterLong,
                  double dfScale,
                  double dfFalseEasting,
                  double dfFalseNorthing )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetTM", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetTM", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetTM( 
-        dfCenterLat, dfCenterLong, 
-        dfScale, 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetTM(
+        dfCenterLat, dfCenterLong,
+        dfScale,
         dfFalseEasting, dfFalseNorthing );
 }
 
@@ -3765,7 +3734,7 @@ OGRErr OSRSetTM( OGRSpatialReferenceH hSRS,
 /*                            SetTMVariant()                            */
 /************************************************************************/
 
-OGRErr OGRSpatialReference::SetTMVariant( 
+OGRErr OGRSpatialReference::SetTMVariant(
     const char *pszVariantName,
     double dfCenterLat, double dfCenterLong,
     double dfScale,
@@ -3787,7 +3756,7 @@ OGRErr OGRSpatialReference::SetTMVariant(
 /*                          OSRSetTMVariant()                           */
 /************************************************************************/
 
-OGRErr OSRSetTMVariant( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetTMVariant( OGRSpatialReferenceH hSRS,
                         const char *pszVariantName,
                         double dfCenterLat, double dfCenterLong,
                         double dfScale,
@@ -3795,12 +3764,12 @@ OGRErr OSRSetTMVariant( OGRSpatialReferenceH hSRS,
                         double dfFalseNorthing )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetTMVariant", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetTMVariant", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetTMVariant( 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetTMVariant(
         pszVariantName,
-        dfCenterLat, dfCenterLong, 
-        dfScale, 
+        dfCenterLat, dfCenterLong,
+        dfScale,
         dfFalseEasting, dfFalseNorthing );
 }
 
@@ -3828,7 +3797,7 @@ OGRErr OGRSpatialReference::SetTMSO( double dfCenterLat, double dfCenterLong,
 /*                              SetTPED()                               */
 /************************************************************************/
 
-OGRErr OGRSpatialReference::SetTPED( double dfLat1, double dfLong1, 
+OGRErr OGRSpatialReference::SetTPED( double dfLat1, double dfLong1,
                                      double dfLat2, double dfLong2,
                                      double dfFalseEasting,
                                      double dfFalseNorthing )
@@ -3855,9 +3824,9 @@ OGRErr OSRSetTPED( OGRSpatialReferenceH hSRS,
                    double dfFalseEasting, double dfFalseNorthing )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetTPED", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetTPED", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetTPED( 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetTPED(
         dfLat1, dfLong1, dfLat2, dfLong2,
         dfFalseEasting, dfFalseNorthing );
 }
@@ -3866,18 +3835,18 @@ OGRErr OSRSetTPED( OGRSpatialReferenceH hSRS,
 /*                             OSRSetTMSO()                             */
 /************************************************************************/
 
-OGRErr OSRSetTMSO( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetTMSO( OGRSpatialReferenceH hSRS,
                  double dfCenterLat, double dfCenterLong,
                  double dfScale,
                  double dfFalseEasting,
                  double dfFalseNorthing )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetTMSO", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetTMSO", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetTMSO( 
-        dfCenterLat, dfCenterLong, 
-        dfScale, 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetTMSO(
+        dfCenterLat, dfCenterLong,
+        dfScale,
         dfFalseEasting, dfFalseNorthing );
 }
 
@@ -3885,10 +3854,10 @@ OGRErr OSRSetTMSO( OGRSpatialReferenceH hSRS,
 /*                               SetTMG()                               */
 /************************************************************************/
 
-OGRErr 
+OGRErr
 OGRSpatialReference::SetTMG( double dfCenterLat, double dfCenterLong,
                              double dfFalseEasting, double dfFalseNorthing )
-    
+
 {
     SetProjection( SRS_PT_TUNISIA_MINING_GRID );
     SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, dfCenterLat );
@@ -3903,16 +3872,16 @@ OGRSpatialReference::SetTMG( double dfCenterLat, double dfCenterLong,
 /*                             OSRSetTMG()                              */
 /************************************************************************/
 
-OGRErr OSRSetTMG( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetTMG( OGRSpatialReferenceH hSRS,
                  double dfCenterLat, double dfCenterLong,
                  double dfFalseEasting,
                  double dfFalseNorthing )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetTMG", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetTMG", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetTMG( 
-        dfCenterLat, dfCenterLong, 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetTMG(
+        dfCenterLat, dfCenterLong,
         dfFalseEasting, dfFalseNorthing );
 }
 
@@ -3941,18 +3910,18 @@ OGRErr OGRSpatialReference::SetACEA( double dfStdP1, double dfStdP2,
 /*                             OSRSetACEA()                             */
 /************************************************************************/
 
-OGRErr OSRSetACEA( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetACEA( OGRSpatialReferenceH hSRS,
                    double dfStdP1, double dfStdP2,
                    double dfCenterLat, double dfCenterLong,
                    double dfFalseEasting,
                    double dfFalseNorthing )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetACEA", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetACEA", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetACEA( 
-        dfStdP1, dfStdP2, 
-        dfCenterLat, dfCenterLong, 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetACEA(
+        dfStdP1, dfStdP2,
+        dfCenterLat, dfCenterLong,
         dfFalseEasting, dfFalseNorthing );
 }
 
@@ -3978,16 +3947,16 @@ OGRErr OGRSpatialReference::SetAE( double dfCenterLat, double dfCenterLong,
 /*                              OSRSetAE()                              */
 /************************************************************************/
 
-OGRErr OSRSetAE( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetAE( OGRSpatialReferenceH hSRS,
                  double dfCenterLat, double dfCenterLong,
                  double dfFalseEasting,
                  double dfFalseNorthing )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetACEA", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetACEA", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetAE( 
-        dfCenterLat, dfCenterLong, 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetAE(
+        dfCenterLat, dfCenterLong,
         dfFalseEasting, dfFalseNorthing );
 }
 
@@ -3995,7 +3964,7 @@ OGRErr OSRSetAE( OGRSpatialReferenceH hSRS,
 /*                              SetBonne()                              */
 /************************************************************************/
 
-OGRErr OGRSpatialReference::SetBonne( 
+OGRErr OGRSpatialReference::SetBonne(
     double dfStdP1, double dfCentralMeridian,
     double dfFalseEasting, double dfFalseNorthing )
 
@@ -4013,14 +3982,14 @@ OGRErr OGRSpatialReference::SetBonne(
 /*                            OSRSetBonne()                             */
 /************************************************************************/
 
-OGRErr OSRSetBonne( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetBonne( OGRSpatialReferenceH hSRS,
                     double dfStdP1, double dfCentralMeridian,
                     double dfFalseEasting, double dfFalseNorthing )
-    
+
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetBonne", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetBonne", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetBonne( 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetBonne(
         dfStdP1, dfCentralMeridian,
         dfFalseEasting, dfFalseNorthing );
 }
@@ -4047,14 +4016,14 @@ OGRErr OGRSpatialReference::SetCEA( double dfStdP1, double dfCentralMeridian,
 /*                             OSRSetCEA()                              */
 /************************************************************************/
 
-OGRErr OSRSetCEA( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetCEA( OGRSpatialReferenceH hSRS,
                   double dfStdP1, double dfCentralMeridian,
                   double dfFalseEasting, double dfFalseNorthing )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetCEA", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetCEA", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetCEA( 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetCEA(
         dfStdP1, dfCentralMeridian,
         dfFalseEasting, dfFalseNorthing );
 }
@@ -4081,16 +4050,16 @@ OGRErr OGRSpatialReference::SetCS( double dfCenterLat, double dfCenterLong,
 /*                              OSRSetCS()                              */
 /************************************************************************/
 
-OGRErr OSRSetCS( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetCS( OGRSpatialReferenceH hSRS,
                  double dfCenterLat, double dfCenterLong,
                  double dfFalseEasting,
                  double dfFalseNorthing )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetCS", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetCS", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetCS( 
-        dfCenterLat, dfCenterLong, 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetCS(
+        dfCenterLat, dfCenterLong,
         dfFalseEasting, dfFalseNorthing );
 }
 
@@ -4119,18 +4088,18 @@ OGRErr OGRSpatialReference::SetEC( double dfStdP1, double dfStdP2,
 /*                              OSRSetEC()                              */
 /************************************************************************/
 
-OGRErr OSRSetEC( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetEC( OGRSpatialReferenceH hSRS,
                  double dfStdP1, double dfStdP2,
                  double dfCenterLat, double dfCenterLong,
                  double dfFalseEasting,
                  double dfFalseNorthing )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetEC", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetEC", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetEC( 
-        dfStdP1, dfStdP2, 
-        dfCenterLat, dfCenterLong, 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetEC(
+        dfStdP1, dfStdP2,
+        dfCenterLat, dfCenterLong,
         dfFalseEasting, dfFalseNorthing );
 }
 
@@ -4158,8 +4127,8 @@ OGRErr OGRSpatialReference::SetEckert( int nVariation /* 1-6 */,
         SetProjection( SRS_PT_ECKERT_VI );
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Unsupported Eckert variation (%d).", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Unsupported Eckert variation (%d).",
                   nVariation );
         return OGRERR_UNSUPPORTED_SRS;
     }
@@ -4175,16 +4144,16 @@ OGRErr OGRSpatialReference::SetEckert( int nVariation /* 1-6 */,
 /*                            OSRSetEckert()                            */
 /************************************************************************/
 
-OGRErr OSRSetEckert( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetEckert( OGRSpatialReferenceH hSRS,
                      int nVariation,
                      double dfCentralMeridian,
                      double dfFalseEasting,
                      double dfFalseNorthing )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetEckert", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetEckert", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetEckert( 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetEckert(
         nVariation, dfCentralMeridian,
         dfFalseEasting, dfFalseNorthing );
 }
@@ -4212,15 +4181,15 @@ OGRErr OGRSpatialReference::SetEckertIV( double dfCentralMeridian,
 /*                           OSRSetEckertIV()                           */
 /************************************************************************/
 
-OGRErr OSRSetEckertIV( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetEckertIV( OGRSpatialReferenceH hSRS,
                        double dfCentralMeridian,
                        double dfFalseEasting,
                        double dfFalseNorthing )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetEckertIV", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetEckertIV", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetEckertIV( 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetEckertIV(
         dfCentralMeridian,
         dfFalseEasting, dfFalseNorthing );
 }
@@ -4248,15 +4217,15 @@ OGRErr OGRSpatialReference::SetEckertVI( double dfCentralMeridian,
 /*                           OSRSetEckertVI()                           */
 /************************************************************************/
 
-OGRErr OSRSetEckertVI( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetEckertVI( OGRSpatialReferenceH hSRS,
                        double dfCentralMeridian,
                        double dfFalseEasting,
                        double dfFalseNorthing )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetEckertVI", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetEckertVI", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetEckertVI( 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetEckertVI(
         dfCentralMeridian,
         dfFalseEasting, dfFalseNorthing );
 }
@@ -4284,16 +4253,16 @@ OGRErr OGRSpatialReference::SetEquirectangular(
 /*                       OSRSetEquirectangular()                        */
 /************************************************************************/
 
-OGRErr OSRSetEquirectangular( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetEquirectangular( OGRSpatialReferenceH hSRS,
                               double dfCenterLat, double dfCenterLong,
                               double dfFalseEasting,
                               double dfFalseNorthing )
-    
+
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetEquirectangular", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetEquirectangular", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetEquirectangular( 
-        dfCenterLat, dfCenterLong, 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetEquirectangular(
+        dfCenterLat, dfCenterLong,
         dfFalseEasting, dfFalseNorthing );
 }
 
@@ -4323,17 +4292,17 @@ OGRErr OGRSpatialReference::SetEquirectangular2(
 /*                       OSRSetEquirectangular2()                       */
 /************************************************************************/
 
-OGRErr OSRSetEquirectangular2( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetEquirectangular2( OGRSpatialReferenceH hSRS,
                                double dfCenterLat, double dfCenterLong,
                                double dfStdParallel1,
                                double dfFalseEasting,
                                double dfFalseNorthing )
-    
+
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetEquirectangular2", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetEquirectangular2", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetEquirectangular2( 
-        dfCenterLat, dfCenterLong, 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetEquirectangular2(
+        dfCenterLat, dfCenterLong,
         dfStdParallel1,
         dfFalseEasting, dfFalseNorthing );
 }
@@ -4359,15 +4328,15 @@ OGRErr OGRSpatialReference::SetGS( double dfCentralMeridian,
 /*                              OSRSetGS()                              */
 /************************************************************************/
 
-OGRErr OSRSetGS( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetGS( OGRSpatialReferenceH hSRS,
                  double dfCentralMeridian,
                  double dfFalseEasting,
                  double dfFalseNorthing )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetGS", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetGS", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetGS( 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetGS(
         dfCentralMeridian,
         dfFalseEasting, dfFalseNorthing );
 }
@@ -4393,15 +4362,15 @@ OGRErr OGRSpatialReference::SetGH( double dfCentralMeridian,
 /*                              OSRSetGH()                              */
 /************************************************************************/
 
-OGRErr OSRSetGH( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetGH( OGRSpatialReferenceH hSRS,
                  double dfCentralMeridian,
                  double dfFalseEasting,
                  double dfFalseNorthing )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetGH", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetGH", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetGH( 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetGH(
         dfCentralMeridian,
         dfFalseEasting, dfFalseNorthing );
 }
@@ -4425,9 +4394,9 @@ OGRErr OGRSpatialReference::SetIGH()
 OGRErr OSRSetIGH( OGRSpatialReferenceH hSRS )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetIGH", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetIGH", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetIGH();
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetIGH();
 }
 
 /************************************************************************/
@@ -4453,16 +4422,16 @@ OGRErr OGRSpatialReference::SetGEOS( double dfCentralMeridian,
 /*                              OSRSetGEOS()                             */
 /************************************************************************/
 
-OGRErr OSRSetGEOS( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetGEOS( OGRSpatialReferenceH hSRS,
                    double dfCentralMeridian,
                    double dfSatelliteHeight,
                    double dfFalseEasting,
                    double dfFalseNorthing )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetGEOS", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetGEOS", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetGEOS( 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetGEOS(
         dfCentralMeridian, dfSatelliteHeight,
         dfFalseEasting, dfFalseNorthing );
 }
@@ -4499,9 +4468,9 @@ OGRErr OSRSetGaussSchreiberTMercator( OGRSpatialReferenceH hSRS,
                                       double dfFalseNorthing )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetGaussSchreiberTMercator", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetGaussSchreiberTMercator", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetGaussSchreiberTMercator(
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetGaussSchreiberTMercator(
         dfCenterLat, dfCenterLong, dfScale,
         dfFalseEasting, dfFalseNorthing );
 }
@@ -4529,16 +4498,16 @@ OGRErr OGRSpatialReference::SetGnomonic(
 /*                           OSRSetGnomonic()                           */
 /************************************************************************/
 
-OGRErr OSRSetGnomonic( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetGnomonic( OGRSpatialReferenceH hSRS,
                        double dfCenterLat, double dfCenterLong,
                        double dfFalseEasting,
                        double dfFalseNorthing )
-    
+
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetGnomonic", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetGnomonic", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetGnomonic( 
-        dfCenterLat, dfCenterLong, 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetGnomonic(
+        dfCenterLat, dfCenterLong,
         dfFalseEasting, dfFalseNorthing );
 }
 
@@ -4547,10 +4516,10 @@ OGRErr OSRSetGnomonic( OGRSpatialReferenceH hSRS,
 /************************************************************************/
 
 /**
- * \brief Set an Hotine Oblique Mercator Azimuth Center projection using 
+ * \brief Set an Hotine Oblique Mercator Azimuth Center projection using
  * azimuth angle.
  *
- * This projection corresponds to EPSG projection method 9815, also 
+ * This projection corresponds to EPSG projection method 9815, also
  * sometimes known as hotine oblique mercator (variant B).
  *
  * This method does the same thing as the C function OSRSetHOMAC().
@@ -4565,7 +4534,7 @@ OGRErr OSRSetGnomonic( OGRSpatialReferenceH hSRS,
  * @param dfFalseNorthing False northing.
  *
  * @return OGRERR_NONE on success.
- */ 
+ */
 
 OGRErr OGRSpatialReference::SetHOMAC( double dfCenterLat, double dfCenterLong,
                                       double dfAzimuth, double dfRectToSkew,
@@ -4595,19 +4564,19 @@ OGRErr OGRSpatialReference::SetHOMAC( double dfCenterLat, double dfCenterLong,
  *
  * This is the same as the C++ method OGRSpatialReference::SetHOMAC()
  */
-OGRErr OSRSetHOMAC( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetHOMAC( OGRSpatialReferenceH hSRS,
                     double dfCenterLat, double dfCenterLong,
-                    double dfAzimuth, double dfRectToSkew, 
+                    double dfAzimuth, double dfRectToSkew,
                     double dfScale,
                     double dfFalseEasting,
                     double dfFalseNorthing )
-    
+
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetHOMAC", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetHOMAC", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetHOMAC( 
-        dfCenterLat, dfCenterLong, 
-        dfAzimuth, dfRectToSkew, 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetHOMAC(
+        dfCenterLat, dfCenterLong,
+        dfAzimuth, dfRectToSkew,
         dfScale,
         dfFalseEasting, dfFalseNorthing );
 }
@@ -4619,7 +4588,7 @@ OGRErr OSRSetHOMAC( OGRSpatialReferenceH hSRS,
 /**
  * \brief Set a Hotine Oblique Mercator projection using azimuth angle.
  *
- * This projection corresponds to EPSG projection method 9812, also 
+ * This projection corresponds to EPSG projection method 9812, also
  * sometimes known as hotine oblique mercator (variant A)..
  *
  * This method does the same thing as the C function OSRSetHOM().
@@ -4634,7 +4603,7 @@ OGRErr OSRSetHOMAC( OGRSpatialReferenceH hSRS,
  * @param dfFalseNorthing False northing.
  *
  * @return OGRERR_NONE on success.
- */ 
+ */
 
 OGRErr OGRSpatialReference::SetHOM( double dfCenterLat, double dfCenterLong,
                                     double dfAzimuth, double dfRectToSkew,
@@ -4663,19 +4632,19 @@ OGRErr OGRSpatialReference::SetHOM( double dfCenterLat, double dfCenterLong,
  *
  * This is the same as the C++ method OGRSpatialReference::SetHOM()
  */
-OGRErr OSRSetHOM( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetHOM( OGRSpatialReferenceH hSRS,
                   double dfCenterLat, double dfCenterLong,
-                  double dfAzimuth, double dfRectToSkew, 
+                  double dfAzimuth, double dfRectToSkew,
                   double dfScale,
                   double dfFalseEasting,
                   double dfFalseNorthing )
-    
+
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetHOM", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetHOM", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetHOM( 
-        dfCenterLat, dfCenterLong, 
-        dfAzimuth, dfRectToSkew, 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetHOM(
+        dfCenterLat, dfCenterLong,
+        dfAzimuth, dfRectToSkew,
         dfScale,
         dfFalseEasting, dfFalseNorthing );
 }
@@ -4700,7 +4669,7 @@ OGRErr OSRSetHOM( OGRSpatialReferenceH hSRS,
  * @param dfFalseNorthing False northing.
  *
  * @return OGRERR_NONE on success.
- */ 
+ */
 
 OGRErr OGRSpatialReference::SetHOM2PNO( double dfCenterLat,
                                         double dfLat1, double dfLong1,
@@ -4732,17 +4701,17 @@ OGRErr OGRSpatialReference::SetHOM2PNO( double dfCenterLat,
  *
  * This is the same as the C++ method OGRSpatialReference::SetHOM2PNO()
  */
-OGRErr OSRSetHOM2PNO( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetHOM2PNO( OGRSpatialReferenceH hSRS,
                       double dfCenterLat,
                       double dfLat1, double dfLong1,
                       double dfLat2, double dfLong2,
                       double dfScale,
                       double dfFalseEasting, double dfFalseNorthing )
-    
+
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetHOM2PNO", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetHOM2PNO", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetHOM2PNO( 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetHOM2PNO(
         dfCenterLat,
         dfLat1, dfLong1,
         dfLat2, dfLong2,
@@ -4774,16 +4743,16 @@ OGRErr OGRSpatialReference::SetIWMPolyconic(
 /*                          OSRSetIWMPolyconic()                        */
 /************************************************************************/
 
-OGRErr OSRSetIWMPolyconic( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetIWMPolyconic( OGRSpatialReferenceH hSRS,
                            double dfLat1, double dfLat2,
                            double dfCenterLong,
                            double dfFalseEasting, double dfFalseNorthing )
-    
+
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetIWMPolyconic", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetIWMPolyconic", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetIWMPolyconic( 
-        dfLat1, dfLat2, dfCenterLong, 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetIWMPolyconic(
+        dfLat1, dfLat2, dfCenterLong,
         dfFalseEasting, dfFalseNorthing );
 }
 
@@ -4792,7 +4761,7 @@ OGRErr OSRSetIWMPolyconic( OGRSpatialReferenceH hSRS,
 /************************************************************************/
 
 OGRErr OGRSpatialReference::SetKrovak( double dfCenterLat, double dfCenterLong,
-                                       double dfAzimuth, 
+                                       double dfAzimuth,
                                        double dfPseudoStdParallel1,
                                        double dfScale,
                                        double dfFalseEasting,
@@ -4815,18 +4784,18 @@ OGRErr OGRSpatialReference::SetKrovak( double dfCenterLat, double dfCenterLong,
 /*                            OSRSetKrovak()                            */
 /************************************************************************/
 
-OGRErr OSRSetKrovak( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetKrovak( OGRSpatialReferenceH hSRS,
                      double dfCenterLat, double dfCenterLong,
                      double dfAzimuth, double dfPseudoStdParallel1,
                      double dfScale,
                      double dfFalseEasting,
                      double dfFalseNorthing )
-    
+
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetKrovak", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetKrovak", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetKrovak( 
-        dfCenterLat, dfCenterLong, 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetKrovak(
+        dfCenterLat, dfCenterLong,
         dfAzimuth, dfPseudoStdParallel1,
         dfScale,
         dfFalseEasting, dfFalseNorthing );
@@ -4854,15 +4823,15 @@ OGRErr OGRSpatialReference::SetLAEA( double dfCenterLat, double dfCenterLong,
 /*                             OSRSetLAEA()                             */
 /************************************************************************/
 
-OGRErr OSRSetLAEA( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetLAEA( OGRSpatialReferenceH hSRS,
                    double dfCenterLat, double dfCenterLong,
                    double dfFalseEasting, double dfFalseNorthing )
-    
+
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetLAEA", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetLAEA", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetLAEA( 
-        dfCenterLat, dfCenterLong, 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetLAEA(
+        dfCenterLat, dfCenterLong,
         dfFalseEasting, dfFalseNorthing );
 }
 
@@ -4891,17 +4860,17 @@ OGRErr OGRSpatialReference::SetLCC( double dfStdP1, double dfStdP2,
 /*                             OSRSetLCC()                              */
 /************************************************************************/
 
-OGRErr OSRSetLCC( OGRSpatialReferenceH hSRS, 
-                  double dfStdP1, double dfStdP2, 
+OGRErr OSRSetLCC( OGRSpatialReferenceH hSRS,
+                  double dfStdP1, double dfStdP2,
                   double dfCenterLat, double dfCenterLong,
                   double dfFalseEasting, double dfFalseNorthing )
-    
+
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetLCC", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetLCC", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetLCC( 
-        dfStdP1, dfStdP2, 
-        dfCenterLat, dfCenterLong, 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetLCC(
+        dfStdP1, dfStdP2,
+        dfCenterLat, dfCenterLong,
         dfFalseEasting, dfFalseNorthing );
 }
 
@@ -4929,16 +4898,16 @@ OGRErr OGRSpatialReference::SetLCC1SP( double dfCenterLat, double dfCenterLong,
 /*                            OSRSetLCC1SP()                            */
 /************************************************************************/
 
-OGRErr OSRSetLCC1SP( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetLCC1SP( OGRSpatialReferenceH hSRS,
                      double dfCenterLat, double dfCenterLong,
                      double dfScale,
                      double dfFalseEasting, double dfFalseNorthing )
-    
+
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetLCC1SP", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetLCC1SP", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetLCC1SP( 
-        dfCenterLat, dfCenterLong, 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetLCC1SP(
+        dfCenterLat, dfCenterLong,
         dfScale,
         dfFalseEasting, dfFalseNorthing );
 }
@@ -4968,17 +4937,17 @@ OGRErr OGRSpatialReference::SetLCCB( double dfStdP1, double dfStdP2,
 /*                             OSRSetLCCB()                             */
 /************************************************************************/
 
-OGRErr OSRSetLCCB( OGRSpatialReferenceH hSRS, 
-                   double dfStdP1, double dfStdP2, 
+OGRErr OSRSetLCCB( OGRSpatialReferenceH hSRS,
+                   double dfStdP1, double dfStdP2,
                    double dfCenterLat, double dfCenterLong,
                    double dfFalseEasting, double dfFalseNorthing )
-    
+
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetLCCB", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetLCCB", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetLCCB( 
-        dfStdP1, dfStdP2, 
-        dfCenterLat, dfCenterLong, 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetLCCB(
+        dfStdP1, dfStdP2,
+        dfCenterLat, dfCenterLong,
         dfFalseEasting, dfFalseNorthing );
 }
 
@@ -5004,15 +4973,15 @@ OGRErr OGRSpatialReference::SetMC( double dfCenterLat, double dfCenterLong,
 /*                              OSRSetMC()                              */
 /************************************************************************/
 
-OGRErr OSRSetMC( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetMC( OGRSpatialReferenceH hSRS,
                  double dfCenterLat, double dfCenterLong,
                  double dfFalseEasting, double dfFalseNorthing )
-    
+
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetMC", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetMC", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetMC( 
-        dfCenterLat, dfCenterLong, 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetMC(
+        dfCenterLat, dfCenterLong,
         dfFalseEasting, dfFalseNorthing );
 }
 
@@ -5043,16 +5012,16 @@ OGRErr OGRSpatialReference::SetMercator( double dfCenterLat, double dfCenterLong
 /*                           OSRSetMercator()                           */
 /************************************************************************/
 
-OGRErr OSRSetMercator( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetMercator( OGRSpatialReferenceH hSRS,
                        double dfCenterLat, double dfCenterLong,
                        double dfScale,
                        double dfFalseEasting, double dfFalseNorthing )
-    
+
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetMercator", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetMercator", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetMercator( 
-        dfCenterLat, dfCenterLong, 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetMercator(
+        dfCenterLat, dfCenterLong,
         dfScale,
         dfFalseEasting, dfFalseNorthing );
 }
@@ -5061,8 +5030,8 @@ OGRErr OSRSetMercator( OGRSpatialReferenceH hSRS,
 /*                           SetMercator2SP()                           */
 /************************************************************************/
 
-OGRErr OGRSpatialReference::SetMercator2SP( 
-    double dfStdP1, 
+OGRErr OGRSpatialReference::SetMercator2SP(
+    double dfStdP1,
     double dfCenterLat, double dfCenterLong,
     double dfFalseEasting,
     double dfFalseNorthing )
@@ -5085,17 +5054,17 @@ OGRErr OGRSpatialReference::SetMercator2SP(
 /*                         OSRSetMercator2SP()                          */
 /************************************************************************/
 
-OGRErr OSRSetMercator2SP( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetMercator2SP( OGRSpatialReferenceH hSRS,
                           double dfStdP1,
                           double dfCenterLat, double dfCenterLong,
                           double dfFalseEasting, double dfFalseNorthing )
-    
+
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetMercator2SP", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetMercator2SP", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetMercator2SP( 
-        dfStdP1, 
-        dfCenterLat, dfCenterLong, 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetMercator2SP(
+        dfStdP1,
+        dfCenterLat, dfCenterLong,
         dfFalseEasting, dfFalseNorthing );
 }
 
@@ -5120,14 +5089,14 @@ OGRErr OGRSpatialReference::SetMollweide( double dfCentralMeridian,
 /*                          OSRSetMollweide()                           */
 /************************************************************************/
 
-OGRErr OSRSetMollweide( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetMollweide( OGRSpatialReferenceH hSRS,
                         double dfCentralMeridian,
                         double dfFalseEasting, double dfFalseNorthing )
-    
+
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetMollweide", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetMollweide", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetMollweide( 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetMollweide(
         dfCentralMeridian,
         dfFalseEasting, dfFalseNorthing );
 }
@@ -5154,15 +5123,15 @@ OGRErr OGRSpatialReference::SetNZMG( double dfCenterLat, double dfCenterLong,
 /*                             OSRSetNZMG()                             */
 /************************************************************************/
 
-OGRErr OSRSetNZMG( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetNZMG( OGRSpatialReferenceH hSRS,
                    double dfCenterLat, double dfCenterLong,
                    double dfFalseEasting, double dfFalseNorthing )
-    
+
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetNZMG", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetNZMG", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetNZMG( 
-        dfCenterLat, dfCenterLong, 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetNZMG(
+        dfCenterLat, dfCenterLong,
         dfFalseEasting, dfFalseNorthing );
 }
 
@@ -5190,15 +5159,15 @@ OGRErr OGRSpatialReference::SetOS( double dfOriginLat, double dfCMeridian,
 /*                              OSRSetOS()                              */
 /************************************************************************/
 
-OGRErr OSRSetOS( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetOS( OGRSpatialReferenceH hSRS,
                  double dfOriginLat, double dfCMeridian,
                  double dfScale,
                  double dfFalseEasting, double dfFalseNorthing )
-    
+
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetOS", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetOS", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetOS( 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetOS(
         dfOriginLat, dfCMeridian,
         dfScale,
         dfFalseEasting, dfFalseNorthing );
@@ -5226,15 +5195,15 @@ OGRErr OGRSpatialReference::SetOrthographic(
 /*                         OSRSetOrthographic()                         */
 /************************************************************************/
 
-OGRErr OSRSetOrthographic( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetOrthographic( OGRSpatialReferenceH hSRS,
                            double dfCenterLat, double dfCenterLong,
                            double dfFalseEasting, double dfFalseNorthing )
-    
+
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetOrthographic", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetOrthographic", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetOrthographic( 
-        dfCenterLat, dfCenterLong, 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetOrthographic(
+        dfCenterLat, dfCenterLong,
         dfFalseEasting, dfFalseNorthing );
 }
 
@@ -5249,7 +5218,7 @@ OGRErr OGRSpatialReference::SetPolyconic(
 {
     // note: it seems that by some definitions this should include a
     //       scale_factor parameter.
-    
+
     SetProjection( SRS_PT_POLYCONIC );
     SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, dfCenterLat );
     SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCenterLong );
@@ -5263,15 +5232,15 @@ OGRErr OGRSpatialReference::SetPolyconic(
 /*                          OSRSetPolyconic()                           */
 /************************************************************************/
 
-OGRErr OSRSetPolyconic( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetPolyconic( OGRSpatialReferenceH hSRS,
                         double dfCenterLat, double dfCenterLong,
                         double dfFalseEasting, double dfFalseNorthing )
-    
+
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetPolyconic", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetPolyconic", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetPolyconic( 
-        dfCenterLat, dfCenterLong, 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetPolyconic(
+        dfCenterLat, dfCenterLong,
         dfFalseEasting, dfFalseNorthing );
 }
 
@@ -5299,16 +5268,16 @@ OGRErr OGRSpatialReference::SetPS(
 /*                              OSRSetPS()                              */
 /************************************************************************/
 
-OGRErr OSRSetPS( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetPS( OGRSpatialReferenceH hSRS,
                  double dfCenterLat, double dfCenterLong,
                  double dfScale,
                  double dfFalseEasting, double dfFalseNorthing )
-    
+
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetPS", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetPS", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetPS( 
-        dfCenterLat, dfCenterLong, 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetPS(
+        dfCenterLat, dfCenterLong,
         dfScale,
         dfFalseEasting, dfFalseNorthing );
 }
@@ -5334,15 +5303,15 @@ OGRErr OGRSpatialReference::SetRobinson( double dfCenterLong,
 /*                           OSRSetRobinson()                           */
 /************************************************************************/
 
-OGRErr OSRSetRobinson( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetRobinson( OGRSpatialReferenceH hSRS,
                         double dfCenterLong,
                         double dfFalseEasting, double dfFalseNorthing )
-    
+
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetRobinson", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetRobinson", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetRobinson( 
-        dfCenterLong, 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetRobinson(
+        dfCenterLong,
         dfFalseEasting, dfFalseNorthing );
 }
 
@@ -5367,15 +5336,15 @@ OGRErr OGRSpatialReference::SetSinusoidal( double dfCenterLong,
 /*                          OSRSetSinusoidal()                          */
 /************************************************************************/
 
-OGRErr OSRSetSinusoidal( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetSinusoidal( OGRSpatialReferenceH hSRS,
                          double dfCenterLong,
                          double dfFalseEasting, double dfFalseNorthing )
-    
+
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetSinusoidal", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetSinusoidal", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetSinusoidal( 
-        dfCenterLong, 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetSinusoidal(
+        dfCenterLong,
         dfFalseEasting, dfFalseNorthing );
 }
 
@@ -5404,15 +5373,15 @@ OGRErr OGRSpatialReference::SetStereographic(
 /*                        OSRSetStereographic()                         */
 /************************************************************************/
 
-OGRErr OSRSetStereographic( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetStereographic( OGRSpatialReferenceH hSRS,
                             double dfOriginLat, double dfCMeridian,
                             double dfScale,
                             double dfFalseEasting, double dfFalseNorthing )
-    
+
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetStereographic", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetStereographic", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetStereographic( 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetStereographic(
         dfOriginLat, dfCMeridian,
         dfScale,
         dfFalseEasting, dfFalseNorthing );
@@ -5428,7 +5397,7 @@ OGRErr OSRSetStereographic( OGRSpatialReferenceH hSRS,
 /*      EPSG:2056 and Bug 423.                                          */
 /************************************************************************/
 
-OGRErr OGRSpatialReference::SetSOC( double dfLatitudeOfOrigin, 
+OGRErr OGRSpatialReference::SetSOC( double dfLatitudeOfOrigin,
                                     double dfCentralMeridian,
                                     double dfFalseEasting,
                                     double dfFalseNorthing )
@@ -5447,14 +5416,14 @@ OGRErr OGRSpatialReference::SetSOC( double dfLatitudeOfOrigin,
 /*                             OSRSetSOC()                              */
 /************************************************************************/
 
-OGRErr OSRSetSOC( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetSOC( OGRSpatialReferenceH hSRS,
                   double dfLatitudeOfOrigin, double dfCentralMeridian,
                   double dfFalseEasting, double dfFalseNorthing )
-    
+
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetSOC", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetSOC", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetSOC( 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetSOC(
         dfLatitudeOfOrigin, dfCentralMeridian,
         dfFalseEasting, dfFalseNorthing );
 }
@@ -5480,14 +5449,14 @@ OGRErr OGRSpatialReference::SetVDG( double dfCMeridian,
 /*                             OSRSetVDG()                              */
 /************************************************************************/
 
-OGRErr OSRSetVDG( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetVDG( OGRSpatialReferenceH hSRS,
                   double dfCentralMeridian,
                   double dfFalseEasting, double dfFalseNorthing )
-    
+
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetVDG", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetVDG", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetVDG( 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetVDG(
         dfCentralMeridian,
         dfFalseEasting, dfFalseNorthing );
 }
@@ -5499,24 +5468,29 @@ OGRErr OSRSetVDG( OGRSpatialReferenceH hSRS,
 /**
  * \brief Set UTM projection definition.
  *
- * This will generate a projection definition with the full set of 
+ * This will generate a projection definition with the full set of
  * transverse mercator projection parameters for the given UTM zone.
  * If no PROJCS[] description is set yet, one will be set to look
- * like "UTM Zone %d, {Northern, Southern} Hemisphere". 
+ * like "UTM Zone %d, {Northern, Southern} Hemisphere".
  *
  * This method is the same as the C function OSRSetUTM().
  *
  * @param nZone UTM zone.
  *
- * @param bNorth TRUE for northern hemisphere, or FALSE for southern 
- * hemisphere. 
- * 
- * @return OGRERR_NONE on success. 
+ * @param bNorth TRUE for northern hemisphere, or FALSE for southern
+ * hemisphere.
+ *
+ * @return OGRERR_NONE on success.
  */
 
 OGRErr OGRSpatialReference::SetUTM( int nZone, int bNorth )
 
 {
+    if( nZone < 0 || nZone > 60 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Invalid zone: %d", nZone);
+        return OGRERR_FAILURE;
+    }
     SetProjection( SRS_PT_TRANSVERSE_MERCATOR );
     SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0 );
     SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, nZone * 6 - 183 );
@@ -5533,9 +5507,9 @@ OGRErr OGRSpatialReference::SetUTM( int nZone, int bNorth )
         char    szUTMName[128];
 
         if( bNorth )
-            sprintf( szUTMName, "UTM Zone %d, Northern Hemisphere", nZone );
+            snprintf( szUTMName, sizeof(szUTMName), "UTM Zone %d, Northern Hemisphere", nZone );
         else
-            sprintf( szUTMName, "UTM Zone %d, Southern Hemisphere", nZone );
+            snprintf( szUTMName, sizeof(szUTMName), "UTM Zone %d, Southern Hemisphere", nZone );
 
         SetNode( "PROJCS", szUTMName );
     }
@@ -5557,9 +5531,9 @@ OGRErr OGRSpatialReference::SetUTM( int nZone, int bNorth )
 OGRErr OSRSetUTM( OGRSpatialReferenceH hSRS, int nZone, int bNorth )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetUTM", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetUTM", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetUTM( nZone, bNorth );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetUTM( nZone, bNorth );
 }
 
 /************************************************************************/
@@ -5573,14 +5547,14 @@ OGRErr OSRSetUTM( OGRSpatialReferenceH hSRS, int nZone, int bNorth )
  *
  * This is the same as the C function OSRGetUTMZone().
  *
- * In SWIG bindings (Python, Java, etc) the GetUTMZone() method returns a 
- * zone which is negative in the southern hemisphere instead of having the 
+ * In SWIG bindings (Python, Java, etc) the GetUTMZone() method returns a
+ * zone which is negative in the southern hemisphere instead of having the
  * pbNorth flag used in the C and C++ interface.
  *
  * @param pbNorth pointer to in to set to TRUE if northern hemisphere, or
- * FALSE if southern. 
- * 
- * @return UTM zone number or zero if this isn't a UTM definition. 
+ * FALSE if southern.
+ *
+ * @return UTM zone number or zero if this isn't a UTM definition.
  */
 
 int OGRSpatialReference::GetUTMZone( int * pbNorth ) const
@@ -5597,20 +5571,20 @@ int OGRSpatialReference::GetUTMZone( int * pbNorth ) const
 
     if( GetProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) != 0.9996 )
         return 0;
-          
+
     if( fabs(GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 )-500000.0) > 0.001 )
         return 0;
 
     double      dfFalseNorthing = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0);
 
-    if( dfFalseNorthing != 0.0 
+    if( dfFalseNorthing != 0.0
         && fabs(dfFalseNorthing-10000000.0) > 0.001 )
         return 0;
 
     if( pbNorth != NULL )
         *pbNorth = (dfFalseNorthing == 0);
 
-    double      dfCentralMeridian = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
+    double      dfCentralMeridian = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
                                                      0.0);
     double      dfZone = ( dfCentralMeridian + 186.0 ) / 6.0;
 
@@ -5636,7 +5610,7 @@ int OSRGetUTMZone( OGRSpatialReferenceH hSRS, int *pbNorth )
 {
     VALIDATE_POINTER1( hSRS, "OSRGetUTMZone", 0 );
 
-    return ((OGRSpatialReference *) hSRS)->GetUTMZone( pbNorth );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->GetUTMZone( pbNorth );
 }
 
 /************************************************************************/
@@ -5668,7 +5642,7 @@ OGRErr OGRSpatialReference::SetWagner( int nVariation /* 1 -- 7 */,
         SetProjection( SRS_PT_WAGNER_VII );
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unsupported Wagner variation (%d).", nVariation );
         return OGRERR_UNSUPPORTED_SRS;
     }
@@ -5683,15 +5657,15 @@ OGRErr OGRSpatialReference::SetWagner( int nVariation /* 1 -- 7 */,
 /*                            OSRSetWagner()                            */
 /************************************************************************/
 
-OGRErr OSRSetWagner( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetWagner( OGRSpatialReferenceH hSRS,
                      int nVariation, double dfCenterLat,
                      double dfFalseEasting,
                      double dfFalseNorthing )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetWagner", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetWagner", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetWagner( 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetWagner(
         nVariation, dfCenterLat, dfFalseEasting, dfFalseNorthing );
 }
 
@@ -5717,13 +5691,45 @@ OGRErr OSRSetQSC( OGRSpatialReferenceH hSRS,
                        double dfCenterLat, double dfCenterLong )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetQSC", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetQSC", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetQSC(
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetQSC(
         dfCenterLat, dfCenterLong );
 }
 
 /************************************************************************/
+/*                            SetSCH()                     */
+/************************************************************************/
+
+OGRErr OGRSpatialReference::SetSCH( double dfPegLat, double dfPegLong,
+                                    double dfPegHeading, double dfPegHgt)
+
+{
+    SetProjection( SRS_PT_SCH );
+    SetNormProjParm( SRS_PP_PEG_POINT_LATITUDE, dfPegLat );
+    SetNormProjParm( SRS_PP_PEG_POINT_LONGITUDE, dfPegLong );
+    SetNormProjParm( SRS_PP_PEG_POINT_HEADING, dfPegHeading );
+    SetNormProjParm( SRS_PP_PEG_POINT_HEIGHT, dfPegHgt);
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           OSRSetSCH()                   */
+/************************************************************************/
+
+OGRErr OSRSetSCH( OGRSpatialReferenceH hSRS,
+                       double dfPegLat, double dfPegLong,
+                       double dfPegHeading, double dfPegHgt)
+
+{
+    VALIDATE_POINTER1( hSRS, "OSRSetSCH", OGRERR_FAILURE );
+
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetSCH(
+        dfPegLat, dfPegLong, dfPegHeading, dfPegHgt );
+}
+
+/************************************************************************/
 /*                            SetAuthority()                            */
 /************************************************************************/
 
@@ -5732,8 +5738,8 @@ OGRErr OSRSetQSC( OGRSpatialReferenceH hSRS,
  *
  * This method is the same as the C function OSRSetAuthority().
  *
- * @param pszTargetKey the partial or complete path to the node to 
- * set an authority on.  ie. "PROJCS", "GEOGCS" or "GEOGCS|UNIT".
+ * @param pszTargetKey the partial or complete path to the node to
+ * set an authority on.  i.e. "PROJCS", "GEOGCS" or "GEOGCS|UNIT".
  *
  * @param pszAuthority authority name, such as "EPSG".
  *
@@ -5743,7 +5749,7 @@ OGRErr OSRSetQSC( OGRSpatialReferenceH hSRS,
  */
 
 OGRErr OGRSpatialReference::SetAuthority( const char *pszTargetKey,
-                                          const char * pszAuthority, 
+                                          const char * pszAuthority,
                                           int nCode )
 
 {
@@ -5769,12 +5775,12 @@ OGRErr OGRSpatialReference::SetAuthority( const char *pszTargetKey,
     char   szCode[32];
     OGR_SRSNode *poAuthNode;
 
-    sprintf( szCode, "%d", nCode );
+    snprintf( szCode, sizeof(szCode), "%d", nCode );
 
     poAuthNode = new OGR_SRSNode( "AUTHORITY" );
     poAuthNode->AddChild( new OGR_SRSNode( pszAuthority ) );
     poAuthNode->AddChild( new OGR_SRSNode( szCode ) );
-    
+
     poNode->AddChild( poAuthNode );
 
     return OGRERR_NONE;
@@ -5789,15 +5795,15 @@ OGRErr OGRSpatialReference::SetAuthority( const char *pszTargetKey,
  *
  * This function is the same as OGRSpatialReference::SetAuthority().
  */
-OGRErr OSRSetAuthority( OGRSpatialReferenceH hSRS, 
+OGRErr OSRSetAuthority( OGRSpatialReferenceH hSRS,
                         const char *pszTargetKey,
-                        const char * pszAuthority, 
+                        const char * pszAuthority,
                         int nCode )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetAuthority", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetAuthority", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetAuthority( pszTargetKey, 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetAuthority( pszTargetKey,
                                                          pszAuthority,
                                                          nCode );
 }
@@ -5809,16 +5815,16 @@ OGRErr OSRSetAuthority( OGRSpatialReferenceH hSRS,
 /**
  * \brief Get the authority code for a node.
  *
- * This method is used to query an AUTHORITY[] node from within the 
- * WKT tree, and fetch the code value.  
+ * This method is used to query an AUTHORITY[] node from within the
+ * WKT tree, and fetch the code value.
  *
  * While in theory values may be non-numeric, for the EPSG authority all
  * code values should be integral.
  *
  * This method is the same as the C function OSRGetAuthorityCode().
  *
- * @param pszTargetKey the partial or complete path to the node to 
- * get an authority from.  ie. "PROJCS", "GEOGCS", "GEOGCS|UNIT" or NULL to 
+ * @param pszTargetKey the partial or complete path to the node to
+ * get an authority from.  i.e. "PROJCS", "GEOGCS", "GEOGCS|UNIT" or NULL to
  * search for an authority node on the root element.
  *
  * @return value code from authority node, or NULL on failure.  The value
@@ -5847,7 +5853,7 @@ OGRSpatialReference::GetAuthorityCode( const char *pszTargetKey ) const
 /* -------------------------------------------------------------------- */
     if( poNode->FindChild("AUTHORITY") == -1 )
         return NULL;
-        
+
     poNode = poNode->GetChild(poNode->FindChild("AUTHORITY"));
 
 /* -------------------------------------------------------------------- */
@@ -5868,13 +5874,14 @@ OGRSpatialReference::GetAuthorityCode( const char *pszTargetKey ) const
  *
  * This function is the same as OGRSpatialReference::GetAuthorityCode().
  */
-const char *OSRGetAuthorityCode( OGRSpatialReferenceH hSRS, 
+const char *OSRGetAuthorityCode( OGRSpatialReferenceH hSRS,
                                  const char *pszTargetKey )
 
 {
     VALIDATE_POINTER1( hSRS, "OSRGetAuthorityCode", NULL );
 
-    return ((OGRSpatialReference *) hSRS)->GetAuthorityCode( pszTargetKey );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
+        GetAuthorityCode( pszTargetKey );
 }
 
 /************************************************************************/
@@ -5884,15 +5891,15 @@ const char *OSRGetAuthorityCode( OGRSpatialReferenceH hSRS,
 /**
  * \brief Get the authority name for a node.
  *
- * This method is used to query an AUTHORITY[] node from within the 
- * WKT tree, and fetch the authority name value.  
+ * This method is used to query an AUTHORITY[] node from within the
+ * WKT tree, and fetch the authority name value.
  *
  * The most common authority is "EPSG".
  *
  * This method is the same as the C function OSRGetAuthorityName().
  *
- * @param pszTargetKey the partial or complete path to the node to 
- * get an authority from.  ie. "PROJCS", "GEOGCS", "GEOGCS|UNIT" or NULL to 
+ * @param pszTargetKey the partial or complete path to the node to
+ * get an authority from.  i.e. "PROJCS", "GEOGCS", "GEOGCS|UNIT" or NULL to
  * search for an authority node on the root element.
  *
  * @return value code from authority node, or NULL on failure. The value
@@ -5906,12 +5913,13 @@ OGRSpatialReference::GetAuthorityName( const char *pszTargetKey ) const
 /* -------------------------------------------------------------------- */
 /*      Find the node below which the authority should be put.          */
 /* -------------------------------------------------------------------- */
-    const OGR_SRSNode  *poNode;
+    const OGR_SRSNode  *poNode = NULL;
 
     if( pszTargetKey == NULL )
         poNode = poRoot;
     else
-        poNode= ((OGRSpatialReference *) this)->GetAttrNode( pszTargetKey );
+        poNode = const_cast<OGRSpatialReference *>(this)->
+            GetAttrNode( pszTargetKey );
 
     if( poNode == NULL )
         return NULL;
@@ -5921,7 +5929,7 @@ OGRSpatialReference::GetAuthorityName( const char *pszTargetKey ) const
 /* -------------------------------------------------------------------- */
     if( poNode->FindChild("AUTHORITY") == -1 )
         return NULL;
-        
+
     poNode = poNode->GetChild(poNode->FindChild("AUTHORITY"));
 
 /* -------------------------------------------------------------------- */
@@ -5942,13 +5950,14 @@ OGRSpatialReference::GetAuthorityName( const char *pszTargetKey ) const
  *
  * This function is the same as OGRSpatialReference::GetAuthorityName().
  */
-const char *OSRGetAuthorityName( OGRSpatialReferenceH hSRS, 
+const char *OSRGetAuthorityName( OGRSpatialReferenceH hSRS,
                                  const char *pszTargetKey )
 
 {
     VALIDATE_POINTER1( hSRS, "OSRGetAuthorityName", NULL );
 
-    return ((OGRSpatialReference *) hSRS)->GetAuthorityName( pszTargetKey );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
+        GetAuthorityName( pszTargetKey );
 }
 
 /************************************************************************/
@@ -5958,9 +5967,9 @@ const char *OSRGetAuthorityName( OGRSpatialReferenceH hSRS,
 /**
  * \brief Convert a compound cs into a horizontal CS.
  *
- * If this SRS is of type COMPD_CS[] then the vertical CS and the root COMPD_CS 
+ * If this SRS is of type COMPD_CS[] then the vertical CS and the root COMPD_CS
  * nodes are stripped resulting and only the horizontal coordinate system
- * portion remains (normally PROJCS, GEOGCS or LOCAL_CS). 
+ * portion remains (normally PROJCS, GEOGCS or LOCAL_CS).
  *
  * If this is not a compound coordinate system then nothing is changed.
  *
@@ -5970,7 +5979,7 @@ const char *OSRGetAuthorityName( OGRSpatialReferenceH hSRS,
 OGRErr OGRSpatialReference::StripVertical()
 
 {
-    if( GetRoot() == NULL 
+    if( GetRoot() == NULL
         || !EQUAL(GetRoot()->GetValue(),"COMPD_CS") )
         return OGRERR_NONE;
 
@@ -5986,12 +5995,12 @@ OGRErr OGRSpatialReference::StripVertical()
 /*                            StripCTParms()                            */
 /************************************************************************/
 
-/** 
+/**
  * \brief Strip OGC CT Parameters.
  *
  * This method will remove all components of the coordinate system
  * that are specific to the OGC CT Specification.  That is it will attempt
- * to strip it down to being compatible with the Simple Features 1.0 
+ * to strip it down to being compatible with the Simple Features 1.0
  * specification.
  *
  * This method is the same as the C function OSRStripCTParms().
@@ -6020,9 +6029,6 @@ OGRErr OGRSpatialReference::StripCTParms( OGR_SRSNode * poCurrent )
 
         return OGRERR_NONE;
     }
-    
-    if( poCurrent == NULL )
-        return OGRERR_NONE;
 
     poCurrent->StripNodes( "AUTHORITY" );
     poCurrent->StripNodes( "TOWGS84" );
@@ -6036,7 +6042,7 @@ OGRErr OGRSpatialReference::StripCTParms( OGR_SRSNode * poCurrent )
 /*                          OSRStripCTParms()                           */
 /************************************************************************/
 
-/** 
+/**
  * \brief Strip OGC CT Parameters.
  *
  * This function is the same as OGRSpatialReference::StripCTParms().
@@ -6044,9 +6050,9 @@ OGRErr OGRSpatialReference::StripCTParms( OGR_SRSNode * poCurrent )
 OGRErr OSRStripCTParms( OGRSpatialReferenceH hSRS )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRStripCTParms", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRStripCTParms", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->StripCTParms( NULL );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->StripCTParms( NULL );
 }
 
 /************************************************************************/
@@ -6074,17 +6080,17 @@ int OGRSpatialReference::IsCompound() const
 /*                           OSRIsCompound()                            */
 /************************************************************************/
 
-/** 
+/**
  * \brief Check if the coordinate system is compound.
  *
  * This function is the same as OGRSpatialReference::IsCompound().
  */
-int OSRIsCompound( OGRSpatialReferenceH hSRS ) 
+int OSRIsCompound( OGRSpatialReferenceH hSRS )
 
 {
     VALIDATE_POINTER1( hSRS, "OSRIsCompound", 0 );
 
-    return ((OGRSpatialReference *) hSRS)->IsCompound();
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->IsCompound();
 }
 
 /************************************************************************/
@@ -6096,8 +6102,8 @@ int OSRIsCompound( OGRSpatialReferenceH hSRS )
  *
  * This method is the same as the C function OSRIsProjected().
  *
- * @return TRUE if this contains a PROJCS node indicating a it is a 
- * projected coordinate system. 
+ * @return TRUE if this contains a PROJCS node indicating a it is a
+ * projected coordinate system.
  */
 
 int OGRSpatialReference::IsProjected() const
@@ -6110,24 +6116,24 @@ int OGRSpatialReference::IsProjected() const
         return TRUE;
     else if( EQUAL(poRoot->GetValue(),"COMPD_CS") )
         return GetAttrNode( "PROJCS" ) != NULL;
-    else 
+    else
         return FALSE;
 }
 
 /************************************************************************/
 /*                           OSRIsProjected()                           */
 /************************************************************************/
-/** 
+/**
  * \brief Check if projected coordinate system.
  *
  * This function is the same as OGRSpatialReference::IsProjected().
  */
-int OSRIsProjected( OGRSpatialReferenceH hSRS ) 
+int OSRIsProjected( OGRSpatialReferenceH hSRS )
 
 {
     VALIDATE_POINTER1( hSRS, "OSRIsProjected", 0 );
 
-    return ((OGRSpatialReference *) hSRS)->IsProjected();
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->IsProjected();
 }
 
 /************************************************************************/
@@ -6139,7 +6145,7 @@ int OSRIsProjected( OGRSpatialReferenceH hSRS )
  *
  * This method is the same as the C function OSRIsGeocentric().
  *
- * @return TRUE if this contains a GEOCCS node indicating a it is a 
+ * @return TRUE if this contains a GEOCCS node indicating a it is a
  * geocentric coordinate system.
  *
  * @since OGR 1.9.0
@@ -6153,26 +6159,26 @@ int OGRSpatialReference::IsGeocentric() const
 
     if( EQUAL(poRoot->GetValue(),"GEOCCS") )
         return TRUE;
-    else 
-        return FALSE;
+
+    return FALSE;
 }
 
 /************************************************************************/
 /*                           OSRIsGeocentric()                          */
 /************************************************************************/
-/** 
+/**
  * \brief Check if geocentric coordinate system.
  *
  * This function is the same as OGRSpatialReference::IsGeocentric().
  *
  * @since OGR 1.9.0
  */
-int OSRIsGeocentric( OGRSpatialReferenceH hSRS ) 
+int OSRIsGeocentric( OGRSpatialReferenceH hSRS )
 
 {
     VALIDATE_POINTER1( hSRS, "OSRIsGeocentric", 0 );
 
-    return ((OGRSpatialReference *) hSRS)->IsGeocentric();
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->IsGeocentric();
 }
 
 /************************************************************************/
@@ -6184,8 +6190,8 @@ int OSRIsGeocentric( OGRSpatialReferenceH hSRS )
  *
  * This method is the same as the C function OSRIsGeographic().
  *
- * @return TRUE if this spatial reference is geographic ... that is the 
- * root is a GEOGCS node. 
+ * @return TRUE if this spatial reference is geographic ... that is the
+ * root is a GEOGCS node.
  */
 
 int OGRSpatialReference::IsGeographic() const
@@ -6196,17 +6202,18 @@ int OGRSpatialReference::IsGeographic() const
 
     if( EQUAL(poRoot->GetValue(),"GEOGCS") )
         return TRUE;
-    else if( EQUAL(poRoot->GetValue(),"COMPD_CS") )
-        return GetAttrNode( "GEOGCS" ) != NULL 
+
+    if( EQUAL(poRoot->GetValue(),"COMPD_CS") )
+        return GetAttrNode( "GEOGCS" ) != NULL
             && GetAttrNode( "PROJCS" ) == NULL;
-    else 
-        return FALSE;
+
+    return FALSE;
 }
 
 /************************************************************************/
 /*                          OSRIsGeographic()                           */
 /************************************************************************/
-/** 
+/**
  * \brief Check if geographic coordinate system.
  *
  * This function is the same as OGRSpatialReference::IsGeographic().
@@ -6216,7 +6223,7 @@ int OSRIsGeographic( OGRSpatialReferenceH hSRS )
 {
     VALIDATE_POINTER1( hSRS, "OSRIsGeographic", 0 );
 
-    return ((OGRSpatialReference *) hSRS)->IsGeographic();
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->IsGeographic();
 }
 
 /************************************************************************/
@@ -6228,8 +6235,8 @@ int OSRIsGeographic( OGRSpatialReferenceH hSRS )
  *
  * This method is the same as the C function OSRIsLocal().
  *
- * @return TRUE if this spatial reference is local ... that is the 
- * root is a LOCAL_CS node. 
+ * @return TRUE if this spatial reference is local ... that is the
+ * root is a LOCAL_CS node.
  */
 
 int OGRSpatialReference::IsLocal() const
@@ -6244,7 +6251,7 @@ int OGRSpatialReference::IsLocal() const
 /************************************************************************/
 /*                          OSRIsLocal()                                */
 /************************************************************************/
-/** 
+/**
  * \brief Check if local coordinate system.
  *
  * This function is the same as OGRSpatialReference::IsLocal().
@@ -6254,7 +6261,7 @@ int OSRIsLocal( OGRSpatialReferenceH hSRS )
 {
     VALIDATE_POINTER1( hSRS, "OSRIsLocal", 0 );
 
-    return ((OGRSpatialReference *) hSRS)->IsLocal();
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->IsLocal();
 }
 
 /************************************************************************/
@@ -6266,7 +6273,7 @@ int OSRIsLocal( OGRSpatialReferenceH hSRS )
  *
  * This method is the same as the C function OSRIsVertical().
  *
- * @return TRUE if this contains a VERT_CS node indicating a it is a 
+ * @return TRUE if this contains a VERT_CS node indicating a it is a
  * vertical coordinate system.
  *
  * @since OGR 1.8.0
@@ -6280,28 +6287,29 @@ int OGRSpatialReference::IsVertical() const
 
     if( EQUAL(poRoot->GetValue(),"VERT_CS") )
         return TRUE;
-    else if( EQUAL(poRoot->GetValue(),"COMPD_CS") )
+
+    if( EQUAL(poRoot->GetValue(),"COMPD_CS") )
         return GetAttrNode( "VERT_CS" ) != NULL;
-    else 
-        return FALSE;
+
+    return FALSE;
 }
 
 /************************************************************************/
 /*                           OSRIsVertical()                            */
 /************************************************************************/
-/** 
+/**
  * \brief Check if vertical coordinate system.
  *
  * This function is the same as OGRSpatialReference::IsVertical().
  *
  * @since OGR 1.8.0
  */
-int OSRIsVertical( OGRSpatialReferenceH hSRS ) 
+int OSRIsVertical( OGRSpatialReferenceH hSRS )
 
 {
     VALIDATE_POINTER1( hSRS, "OSRIsVertical", 0 );
 
-    return ((OGRSpatialReference *) hSRS)->IsVertical();
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->IsVertical();
 }
 
 /************************************************************************/
@@ -6311,13 +6319,12 @@ int OSRIsVertical( OGRSpatialReferenceH hSRS )
 /**
  * \brief Make a duplicate of the GEOGCS node of this OGRSpatialReference object.
  *
- * @return a new SRS, which becomes the responsibility of the caller. 
+ * @return a new SRS, which becomes the responsibility of the caller.
  */
 OGRSpatialReference *OGRSpatialReference::CloneGeogCS() const
 
 {
-    const OGR_SRSNode *poGeogCS;
-    OGRSpatialReference * poNewSRS;
+    OGRSpatialReference * poNewSRS = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      We have to reconstruct the GEOGCS node for geocentric           */
@@ -6327,11 +6334,11 @@ OGRSpatialReference *OGRSpatialReference::CloneGeogCS() const
     {
         const OGR_SRSNode *poDatum = GetAttrNode( "DATUM" );
         const OGR_SRSNode *poPRIMEM = GetAttrNode( "PRIMEM" );
-        OGR_SRSNode *poGeogCS;
-        
+        OGR_SRSNode *poGeogCS = NULL;
+
         if( poDatum == NULL || poPRIMEM == NULL )
             return NULL;
-        
+
         poGeogCS = new OGR_SRSNode( "GEOGCS" );
         poGeogCS->AddChild( new OGR_SRSNode( "unnamed" ) );
         poGeogCS->AddChild( poDatum->Clone() );
@@ -6348,7 +6355,7 @@ OGRSpatialReference *OGRSpatialReference::CloneGeogCS() const
 /* -------------------------------------------------------------------- */
 /*      For all others we just search the tree, and duplicate.          */
 /* -------------------------------------------------------------------- */
-    poGeogCS = GetAttrNode( "GEOGCS" );
+    const OGR_SRSNode *poGeogCS = GetAttrNode( "GEOGCS" );
     if( poGeogCS == NULL )
         return NULL;
 
@@ -6371,8 +6378,8 @@ OGRSpatialReferenceH CPL_STDCALL OSRCloneGeogCS( OGRSpatialReferenceH hSource )
 {
     VALIDATE_POINTER1( hSource, "OSRCloneGeogCS", NULL );
 
-    return (OGRSpatialReferenceH) 
-        ((OGRSpatialReference *) hSource)->CloneGeogCS();
+    return reinterpret_cast<OGRSpatialReferenceH>(
+        reinterpret_cast<OGRSpatialReference *>(hSource)->CloneGeogCS() );
 }
 
 /************************************************************************/
@@ -6384,9 +6391,9 @@ OGRSpatialReferenceH CPL_STDCALL OSRCloneGeogCS( OGRSpatialReferenceH hSource )
  *
  * This method is the same as the C function OSRIsSameGeogCS().
  *
- * @param poOther the SRS being compared against. 
+ * @param poOther the SRS being compared against.
  *
- * @return TRUE if they are the same or FALSE otherwise. 
+ * @return TRUE if they are the same or FALSE otherwise.
  */
 
 int OGRSpatialReference::IsSameGeogCS( const OGRSpatialReference *poOther ) const
@@ -6401,20 +6408,20 @@ int OGRSpatialReference::IsSameGeogCS( const OGRSpatialReference *poOther ) cons
     pszThisValue = this->GetAttrValue( "DATUM" );
     pszOtherValue = poOther->GetAttrValue( "DATUM" );
 
-    if( pszThisValue != NULL && pszOtherValue != NULL 
+    if( pszThisValue != NULL && pszOtherValue != NULL
         && !EQUAL(pszThisValue,pszOtherValue) )
         return FALSE;
 
 /* -------------------------------------------------------------------- */
 /*      Do the datum TOWGS84 values match if present?                   */
 /* -------------------------------------------------------------------- */
-    double adfTOWGS84[7], adfOtherTOWGS84[7];
-    int i;
+    double adfTOWGS84[7] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
+    double adfOtherTOWGS84[7] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
 
     this->GetTOWGS84( adfTOWGS84, 7 );
     poOther->GetTOWGS84( adfOtherTOWGS84, 7 );
 
-    for( i = 0; i < 7; i++ )
+    for( int i = 0; i < 7; i++ )
     {
         if( fabs(adfTOWGS84[i] - adfOtherTOWGS84[i]) > 0.00001 )
             return FALSE;
@@ -6433,7 +6440,7 @@ int OGRSpatialReference::IsSameGeogCS( const OGRSpatialReference *poOther ) cons
 
     if( CPLAtof(pszOtherValue) != CPLAtof(pszThisValue) )
         return FALSE;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Do the units match?                                             */
 /* -------------------------------------------------------------------- */
@@ -6454,16 +6461,16 @@ int OGRSpatialReference::IsSameGeogCS( const OGRSpatialReference *poOther ) cons
 /* -------------------------------------------------------------------- */
     pszThisValue = this->GetAttrValue( "SPHEROID", 1 );
     pszOtherValue = poOther->GetAttrValue( "SPHEROID", 1 );
-    if( pszThisValue != NULL && pszOtherValue != NULL 
+    if( pszThisValue != NULL && pszOtherValue != NULL
         && ABS(CPLAtof(pszThisValue) - CPLAtof(pszOtherValue)) > 0.01 )
         return FALSE;
 
     pszThisValue = this->GetAttrValue( "SPHEROID", 2 );
     pszOtherValue = poOther->GetAttrValue( "SPHEROID", 2 );
-    if( pszThisValue != NULL && pszOtherValue != NULL 
+    if( pszThisValue != NULL && pszOtherValue != NULL
         && ABS(CPLAtof(pszThisValue) - CPLAtof(pszOtherValue)) > 0.0001 )
         return FALSE;
-    
+
     return TRUE;
 }
 
@@ -6471,7 +6478,7 @@ int OGRSpatialReference::IsSameGeogCS( const OGRSpatialReference *poOther ) cons
 /*                          OSRIsSameGeogCS()                           */
 /************************************************************************/
 
-/** 
+/**
  * \brief Do the GeogCS'es match?
  *
  * This function is the same as OGRSpatialReference::IsSameGeogCS().
@@ -6482,8 +6489,8 @@ int OSRIsSameGeogCS( OGRSpatialReferenceH hSRS1, OGRSpatialReferenceH hSRS2 )
     VALIDATE_POINTER1( hSRS1, "OSRIsSameGeogCS", 0 );
     VALIDATE_POINTER1( hSRS2, "OSRIsSameGeogCS", 0 );
 
-    return ((OGRSpatialReference *) hSRS1)->IsSameGeogCS( 
-        (OGRSpatialReference *) hSRS2 );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS1)->IsSameGeogCS(
+        reinterpret_cast<OGRSpatialReference *>(hSRS2) );
 }
 
 /************************************************************************/
@@ -6495,23 +6502,21 @@ int OSRIsSameGeogCS( OGRSpatialReferenceH hSRS1, OGRSpatialReferenceH hSRS2 )
  *
  * This method is the same as the C function OSRIsSameVertCS().
  *
- * @param poOther the SRS being compared against. 
+ * @param poOther the SRS being compared against.
  *
- * @return TRUE if they are the same or FALSE otherwise. 
+ * @return TRUE if they are the same or FALSE otherwise.
  */
 
 int OGRSpatialReference::IsSameVertCS( const OGRSpatialReference *poOther ) const
 
 {
-    const char *pszThisValue, *pszOtherValue;
-
 /* -------------------------------------------------------------------- */
 /*      Does the datum name match?                                      */
 /* -------------------------------------------------------------------- */
-    pszThisValue = this->GetAttrValue( "VERT_DATUM" );
-    pszOtherValue = poOther->GetAttrValue( "VERT_DATUM" );
+    const char *pszThisValue = this->GetAttrValue( "VERT_DATUM" );
+    const char *pszOtherValue = poOther->GetAttrValue( "VERT_DATUM" );
 
-    if( pszThisValue == NULL || pszOtherValue == NULL 
+    if( pszThisValue == NULL || pszOtherValue == NULL
         || !EQUAL(pszThisValue, pszOtherValue) )
         return FALSE;
 
@@ -6536,7 +6541,7 @@ int OGRSpatialReference::IsSameVertCS( const OGRSpatialReference *poOther ) cons
 /*                          OSRIsSameVertCS()                           */
 /************************************************************************/
 
-/** 
+/**
  * \brief Do the VertCS'es match?
  *
  * This function is the same as OGRSpatialReference::IsSameVertCS().
@@ -6547,8 +6552,8 @@ int OSRIsSameVertCS( OGRSpatialReferenceH hSRS1, OGRSpatialReferenceH hSRS2 )
     VALIDATE_POINTER1( hSRS1, "OSRIsSameVertCS", 0 );
     VALIDATE_POINTER1( hSRS2, "OSRIsSameVertCS", 0 );
 
-    return ((OGRSpatialReference *) hSRS1)->IsSameVertCS( 
-        (OGRSpatialReference *) hSRS2 );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS1)->IsSameVertCS(
+        reinterpret_cast<OGRSpatialReference *>(hSRS2) );
 }
 
 /************************************************************************/
@@ -6560,7 +6565,7 @@ int OSRIsSameVertCS( OGRSpatialReferenceH hSRS1, OGRSpatialReferenceH hSRS2 )
  *
  * @param poOtherSRS the SRS being compared to.
  *
- * @return TRUE if equivalent or FALSE otherwise. 
+ * @return TRUE if equivalent or FALSE otherwise.
  */
 
 int OGRSpatialReference::IsSame( const OGRSpatialReference * poOtherSRS ) const
@@ -6568,7 +6573,8 @@ int OGRSpatialReference::IsSame( const OGRSpatialReference * poOtherSRS ) const
 {
     if( GetRoot() == NULL && poOtherSRS->GetRoot() == NULL )
         return TRUE;
-    else if( GetRoot() == NULL || poOtherSRS->GetRoot() == NULL )
+
+    if( GetRoot() == NULL || poOtherSRS->GetRoot() == NULL )
         return FALSE;
 
 /* -------------------------------------------------------------------- */
@@ -6578,7 +6584,7 @@ int OGRSpatialReference::IsSame( const OGRSpatialReference * poOtherSRS ) const
         return FALSE;
 
 /* -------------------------------------------------------------------- */
-/*      Do the have the same root types?  Ie. is one PROJCS and one     */
+/*      Do the have the same root types?  i.e. is one PROJCS and one    */
 /*      GEOGCS or perhaps LOCALCS?                                      */
 /* -------------------------------------------------------------------- */
     if( !EQUAL(GetRoot()->GetValue(),poOtherSRS->GetRoot()->GetValue()) )
@@ -6587,23 +6593,19 @@ int OGRSpatialReference::IsSame( const OGRSpatialReference * poOtherSRS ) const
 /* -------------------------------------------------------------------- */
 /*      Compare projected coordinate system.                            */
 /* -------------------------------------------------------------------- */
-    if( IsProjected() )
+    const OGR_SRSNode *poPROJCS = GetAttrNode( "PROJCS" );
+    if( poPROJCS != NULL )
     {
-        const char *pszValue1, *pszValue2;
-        const OGR_SRSNode *poPROJCS = GetAttrNode( "PROJCS" );
-
-        pszValue1 = this->GetAttrValue( "PROJECTION" );
-        pszValue2 = poOtherSRS->GetAttrValue( "PROJECTION" );
+        const char *pszValue1 = this->GetAttrValue( "PROJECTION" );
+        const char *pszValue2 = poOtherSRS->GetAttrValue( "PROJECTION" );
         if( pszValue1 == NULL || pszValue2 == NULL
             || !EQUAL(pszValue1,pszValue2) )
             return FALSE;
 
         for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
         {
-            const OGR_SRSNode    *poNode;
-
-            poNode = poPROJCS->GetChild( iChild );
-            if( !EQUAL(poNode->GetValue(),"PARAMETER") 
+            const OGR_SRSNode *poNode = poPROJCS->GetChild( iChild );
+            if( !EQUAL(poNode->GetValue(),"PARAMETER")
                 || poNode->GetChildCount() != 2 )
                 continue;
 
@@ -6621,9 +6623,8 @@ int OGRSpatialReference::IsSame( const OGRSpatialReference * poOtherSRS ) const
     {
         if( GetLinearUnits() != 0.0 )
         {
-            double      dfRatio;
-
-            dfRatio = poOtherSRS->GetLinearUnits() / GetLinearUnits();
+            const double dfRatio =
+                poOtherSRS->GetLinearUnits() / GetLinearUnits();
             if( dfRatio < 0.9999999999 || dfRatio > 1.000000001 )
                 return FALSE;
         }
@@ -6642,7 +6643,7 @@ int OGRSpatialReference::IsSame( const OGRSpatialReference * poOtherSRS ) const
 /*                             OSRIsSame()                              */
 /************************************************************************/
 
-/** 
+/**
  * \brief Do these two spatial references describe the same system ?
  *
  * This function is the same as OGRSpatialReference::IsSame().
@@ -6653,8 +6654,8 @@ int OSRIsSame( OGRSpatialReferenceH hSRS1, OGRSpatialReferenceH hSRS2 )
     VALIDATE_POINTER1( hSRS1, "OSRIsSame", 0 );
     VALIDATE_POINTER1( hSRS2, "OSRIsSame", 0 );
 
-    return ((OGRSpatialReference *) hSRS1)->IsSame( 
-        (OGRSpatialReference *) hSRS2 );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS1)->IsSame(
+        reinterpret_cast<OGRSpatialReference *>(hSRS2) );
 }
 
 /************************************************************************/
@@ -6662,18 +6663,18 @@ int OSRIsSame( OGRSpatialReferenceH hSRS1, OGRSpatialReferenceH hSRS2 )
 /************************************************************************/
 
 /**
- * \brief Set the Bursa-Wolf conversion to WGS84. 
- * 
+ * \brief Set the Bursa-Wolf conversion to WGS84.
+ *
  * This will create the TOWGS84 node as a child of the DATUM.  It will fail
  * if there is no existing DATUM node.  Unlike most OGRSpatialReference
  * methods it will insert itself in the appropriate order, and will replace
- * an existing TOWGS84 node if there is one. 
+ * an existing TOWGS84 node if there is one.
  *
  * The parameters have the same meaning as EPSG transformation 9606
- * (Position Vector 7-param. transformation). 
- * 
+ * (Position Vector 7-param. transformation).
+ *
  * This method is the same as the C function OSRSetTOWGS84().
- * 
+ *
  * @param dfDX X child in meters.
  * @param dfDY Y child in meters.
  * @param dfDZ Z child in meters.
@@ -6681,53 +6682,50 @@ int OSRIsSame( OGRSpatialReferenceH hSRS1, OGRSpatialReferenceH hSRS2 )
  * @param dfEY Y rotation in arc seconds (optional, defaults to zero).
  * @param dfEZ Z rotation in arc seconds (optional, defaults to zero).
  * @param dfPPM scaling factor (parts per million).
- * 
- * @return OGRERR_NONE on success. 
- */ 
+ *
+ * @return OGRERR_NONE on success.
+ */
 
 OGRErr OGRSpatialReference::SetTOWGS84( double dfDX, double dfDY, double dfDZ,
-                                        double dfEX, double dfEY, double dfEZ, 
+                                        double dfEX, double dfEY, double dfEZ,
                                         double dfPPM )
 
 {
-    OGR_SRSNode     *poDatum, *poTOWGS84;
-    int             iPosition;
-    char            szValue[64];
-
-    poDatum = GetAttrNode( "DATUM" );
+    OGR_SRSNode *poDatum = GetAttrNode( "DATUM" );
     if( poDatum == NULL )
         return OGRERR_FAILURE;
-    
+
     if( poDatum->FindChild( "TOWGS84" ) != -1 )
         poDatum->DestroyChild( poDatum->FindChild( "TOWGS84" ) );
 
-    iPosition = poDatum->GetChildCount();
+    int iPosition = poDatum->GetChildCount();
     if( poDatum->FindChild("AUTHORITY") != -1 )
     {
         iPosition = poDatum->FindChild("AUTHORITY");
     }
 
-    poTOWGS84 = new OGR_SRSNode("TOWGS84");
+    OGR_SRSNode *poTOWGS84 = new OGR_SRSNode("TOWGS84");
+    char szValue[64] = { '\0' };
 
-    OGRPrintDouble( szValue, dfDX );
+    OGRsnPrintDouble( szValue, sizeof(szValue), dfDX );
     poTOWGS84->AddChild( new OGR_SRSNode( szValue ) );
 
-    OGRPrintDouble( szValue, dfDY );
+    OGRsnPrintDouble( szValue, sizeof(szValue), dfDY );
     poTOWGS84->AddChild( new OGR_SRSNode( szValue ) );
 
-    OGRPrintDouble( szValue, dfDZ );
+    OGRsnPrintDouble( szValue, sizeof(szValue), dfDZ );
     poTOWGS84->AddChild( new OGR_SRSNode( szValue ) );
 
-    OGRPrintDouble( szValue, dfEX );
+    OGRsnPrintDouble( szValue, sizeof(szValue), dfEX );
     poTOWGS84->AddChild( new OGR_SRSNode( szValue ) );
 
-    OGRPrintDouble( szValue, dfEY );
+    OGRsnPrintDouble( szValue, sizeof(szValue), dfEY );
     poTOWGS84->AddChild( new OGR_SRSNode( szValue ) );
 
-    OGRPrintDouble( szValue, dfEZ );
+    OGRsnPrintDouble( szValue, sizeof(szValue), dfEZ );
     poTOWGS84->AddChild( new OGR_SRSNode( szValue ) );
 
-    OGRPrintDouble( szValue, dfPPM );
+    OGRsnPrintDouble( szValue, sizeof(szValue), dfPPM );
     poTOWGS84->AddChild( new OGR_SRSNode( szValue ) );
 
     poDatum->InsertChild( poTOWGS84, iPosition );
@@ -6739,22 +6737,21 @@ OGRErr OGRSpatialReference::SetTOWGS84( double dfDX, double dfDY, double dfDZ,
 /*                           OSRSetTOWGS84()                            */
 /************************************************************************/
 
-/** 
- * \brief Set the Bursa-Wolf conversion to WGS84. 
+/**
+ * \brief Set the Bursa-Wolf conversion to WGS84.
  *
  * This function is the same as OGRSpatialReference::SetTOWGS84().
  */
-OGRErr OSRSetTOWGS84( OGRSpatialReferenceH hSRS, 
-                      double dfDX, double dfDY, double dfDZ, 
-                      double dfEX, double dfEY, double dfEZ, 
+OGRErr OSRSetTOWGS84( OGRSpatialReferenceH hSRS,
+                      double dfDX, double dfDY, double dfDZ,
+                      double dfEX, double dfEY, double dfEZ,
                       double dfPPM )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetTOWGS84", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetTOWGS84", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetTOWGS84( dfDX, dfDY, dfDZ, 
-                                                       dfEX, dfEY, dfEZ, 
-                                                       dfPPM );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
+        SetTOWGS84( dfDX, dfDY, dfDZ, dfEX, dfEY, dfEZ, dfPPM );
 }
 
 /************************************************************************/
@@ -6762,20 +6759,20 @@ OGRErr OSRSetTOWGS84( OGRSpatialReferenceH hSRS,
 /************************************************************************/
 
 /**
- * \brief Fetch TOWGS84 parameters, if available. 
- * 
+ * \brief Fetch TOWGS84 parameters, if available.
+ *
  * @param padfCoeff array into which up to 7 coefficients are placed.
  * @param nCoeffCount size of padfCoeff - defaults to 7.
- * 
+ *
  * @return OGRERR_NONE on success, or OGRERR_FAILURE if there is no
- * TOWGS84 node available. 
+ * TOWGS84 node available.
  */
 
-OGRErr OGRSpatialReference::GetTOWGS84( double * padfCoeff, 
+OGRErr OGRSpatialReference::GetTOWGS84( double * padfCoeff,
                                         int nCoeffCount ) const
 
 {
-    const OGR_SRSNode   *poNode = GetAttrNode( "TOWGS84" );
+    const OGR_SRSNode *poNode = GetAttrNode( "TOWGS84" );
 
     memset( padfCoeff, 0, sizeof(double) * nCoeffCount );
 
@@ -6794,18 +6791,19 @@ OGRErr OGRSpatialReference::GetTOWGS84( double * padfCoeff,
 /*                           OSRGetTOWGS84()                            */
 /************************************************************************/
 
-/** 
- * \brief Fetch TOWGS84 parameters, if available. 
+/**
+ * \brief Fetch TOWGS84 parameters, if available.
  *
  * This function is the same as OGRSpatialReference::GetTOWGS84().
  */
-OGRErr OSRGetTOWGS84( OGRSpatialReferenceH hSRS, 
+OGRErr OSRGetTOWGS84( OGRSpatialReferenceH hSRS,
                       double * padfCoeff, int nCoeffCount )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRGetTOWGS84", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRGetTOWGS84", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->GetTOWGS84( padfCoeff, nCoeffCount);
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
+        GetTOWGS84( padfCoeff, nCoeffCount);
 }
 
 /************************************************************************/
@@ -6817,15 +6815,15 @@ OGRErr OSRGetTOWGS84( OGRSpatialReferenceH hSRS,
 int OGRSpatialReference::IsAngularParameter( const char *pszParameterName )
 
 {
-    if( EQUALN(pszParameterName,"long",4)
-        || EQUALN(pszParameterName,"lati",4)
+    if( STARTS_WITH_CI(pszParameterName, "long")
+        || STARTS_WITH_CI(pszParameterName, "lati")
         || EQUAL(pszParameterName,SRS_PP_CENTRAL_MERIDIAN)
-        || EQUALN(pszParameterName,"standard_parallel",17)
+        || STARTS_WITH_CI(pszParameterName, "standard_parallel")
         || EQUAL(pszParameterName,SRS_PP_AZIMUTH)
         || EQUAL(pszParameterName,SRS_PP_RECTIFIED_GRID_ANGLE) )
         return TRUE;
-    else
-        return FALSE;
+
+    return FALSE;
 }
 
 /************************************************************************/
@@ -6838,11 +6836,11 @@ int OGRSpatialReference::IsAngularParameter( const char *pszParameterName )
 int OGRSpatialReference::IsLongitudeParameter( const char *pszParameterName )
 
 {
-    if( EQUALN(pszParameterName,"long",4)
+    if( STARTS_WITH_CI(pszParameterName, "long")
         || EQUAL(pszParameterName,SRS_PP_CENTRAL_MERIDIAN) )
         return TRUE;
-    else
-        return FALSE;
+
+    return FALSE;
 }
 
 /************************************************************************/
@@ -6855,11 +6853,11 @@ int OGRSpatialReference::IsLongitudeParameter( const char *pszParameterName )
 int OGRSpatialReference::IsLinearParameter( const char *pszParameterName )
 
 {
-    if( EQUALN(pszParameterName,"false_",6) 
+    if( STARTS_WITH_CI(pszParameterName, "false_")
         || EQUAL(pszParameterName,SRS_PP_SATELLITE_HEIGHT) )
         return TRUE;
-    else
-        return FALSE;
+
+    return FALSE;
 }
 
 /************************************************************************/
@@ -6903,8 +6901,8 @@ void OGRSpatialReference::GetNormInfo(void) const
  *
  * This method is the same as the C function OSRFixupOrdering().
  *
- * @return OGRERR_NONE on success or an error code if something goes 
- * wrong.  
+ * @return OGRERR_NONE on success or an error code if something goes
+ * wrong.
  */
 
 OGRErr OGRSpatialReference::FixupOrdering()
@@ -6912,15 +6910,15 @@ OGRErr OGRSpatialReference::FixupOrdering()
 {
     if( GetRoot() != NULL )
         return GetRoot()->FixupOrdering();
-    else
-        return OGRERR_NONE;
+
+    return OGRERR_NONE;
 }
 
 /************************************************************************/
 /*                          OSRFixupOrdering()                          */
 /************************************************************************/
 
-/** 
+/**
  * \brief Correct parameter ordering to match CT Specification.
  *
  * This function is the same as OGRSpatialReference::FixupOrdering().
@@ -6928,9 +6926,9 @@ OGRErr OGRSpatialReference::FixupOrdering()
 OGRErr OSRFixupOrdering( OGRSpatialReferenceH hSRS )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRFixupOrdering", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRFixupOrdering", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->FixupOrdering();
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->FixupOrdering();
 }
 
 /************************************************************************/
@@ -6944,21 +6942,21 @@ OGRErr OSRFixupOrdering( OGRSpatialReferenceH hSRS )
  * imported WKT, are not valid according to the OGC CT specification.  This
  * method attempts to fill in any missing defaults that are required, and
  * fixup ordering problems (using OSRFixupOrdering()) so that the resulting
- * WKT is valid. 
+ * WKT is valid.
  *
  * This method should be expected to evolve over time to as problems are
- * discovered.  The following are amoung the fixup actions this method will
+ * discovered.  The following are among the fixup actions this method will
  * take:
  *
  * - Fixup the ordering of nodes to match the BNF WKT ordering, using
- * the FixupOrdering() method. 
+ * the FixupOrdering() method.
  *
- * - Add missing linear or angular units nodes.  
+ * - Add missing linear or angular units nodes.
  *
  * This method is the same as the C function OSRFixup().
  *
- * @return OGRERR_NONE on success or an error code if something goes 
- * wrong.  
+ * @return OGRERR_NONE on success or an error code if something goes
+ * wrong.
  */
 
 OGRErr OGRSpatialReference::Fixup()
@@ -6993,7 +6991,7 @@ OGRErr OGRSpatialReference::Fixup()
 /*                              OSRFixup()                              */
 /************************************************************************/
 
-/** 
+/**
  * \brief Fixup as needed.
  *
  * This function is the same as OGRSpatialReference::Fixup().
@@ -7001,9 +6999,9 @@ OGRErr OGRSpatialReference::Fixup()
 OGRErr OSRFixup( OGRSpatialReferenceH hSRS )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRFixup", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRFixup", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->Fixup();
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->Fixup();
 }
 
 /************************************************************************/
@@ -7023,8 +7021,8 @@ OGRErr OSRFixup( OGRSpatialReferenceH hSRS )
  * @return node value if successful or pszDefault on failure.
  */
 
-const char *OGRSpatialReference::GetExtension( const char *pszTargetKey, 
-                                               const char *pszName, 
+const char *OGRSpatialReference::GetExtension( const char *pszTargetKey,
+                                               const char *pszName,
                                                const char *pszDefault ) const
 
 {
@@ -7036,7 +7034,7 @@ const char *OGRSpatialReference::GetExtension( const char *pszTargetKey,
     if( pszTargetKey == NULL )
         poNode = poRoot;
     else
-        poNode= ((OGRSpatialReference *) this)->GetAttrNode( pszTargetKey );
+        poNode = const_cast<OGRSpatialReference *>(this)->GetAttrNode( pszTargetKey );
 
     if( poNode == NULL )
         return NULL;
@@ -7048,7 +7046,7 @@ const char *OGRSpatialReference::GetExtension( const char *pszTargetKey,
     {
         const OGR_SRSNode *poChild = poNode->GetChild(i);
 
-        if( EQUAL(poChild->GetValue(),"EXTENSION") 
+        if( EQUAL(poChild->GetValue(),"EXTENSION")
             && poChild->GetChildCount() >= 2 )
         {
             if( EQUAL(poChild->GetChild(0)->GetValue(),pszName) )
@@ -7075,20 +7073,20 @@ const char *OGRSpatialReference::GetExtension( const char *pszTargetKey,
  * @return OGRERR_NONE on success
  */
 
-OGRErr OGRSpatialReference::SetExtension( const char *pszTargetKey, 
-                                          const char *pszName, 
+OGRErr OGRSpatialReference::SetExtension( const char *pszTargetKey,
+                                          const char *pszName,
                                           const char *pszValue )
 
 {
 /* -------------------------------------------------------------------- */
 /*      Find the target node.                                           */
 /* -------------------------------------------------------------------- */
-    OGR_SRSNode  *poNode;
+    OGR_SRSNode  *poNode = NULL;
 
     if( pszTargetKey == NULL )
         poNode = poRoot;
     else
-        poNode= ((OGRSpatialReference *) this)->GetAttrNode( pszTargetKey );
+        poNode = const_cast<OGRSpatialReference *>(this)->GetAttrNode( pszTargetKey );
 
     if( poNode == NULL )
         return OGRERR_FAILURE;
@@ -7099,8 +7097,8 @@ OGRErr OGRSpatialReference::SetExtension( const char *pszTargetKey,
     for( int i = poNode->GetChildCount()-1; i >= 0; i-- )
     {
         OGR_SRSNode *poChild = poNode->GetChild(i);
-        
-        if( EQUAL(poChild->GetValue(),"EXTENSION") 
+
+        if( EQUAL(poChild->GetValue(),"EXTENSION")
             && poChild->GetChildCount() >= 2 )
         {
             if( EQUAL(poChild->GetChild(0)->GetValue(),pszName) )
@@ -7114,12 +7112,10 @@ OGRErr OGRSpatialReference::SetExtension( const char *pszTargetKey,
 /* -------------------------------------------------------------------- */
 /*      Create a new EXTENSION node.                                    */
 /* -------------------------------------------------------------------- */
-    OGR_SRSNode *poAuthNode;
-
-    poAuthNode = new OGR_SRSNode( "EXTENSION" );
+    OGR_SRSNode *poAuthNode = new OGR_SRSNode( "EXTENSION" );
     poAuthNode->AddChild( new OGR_SRSNode( pszName ) );
     poAuthNode->AddChild( new OGR_SRSNode( pszValue ) );
-    
+
     poNode->AddChild( poAuthNode );
 
     return OGRERR_NONE;
@@ -7129,7 +7125,7 @@ OGRErr OGRSpatialReference::SetExtension( const char *pszTargetKey,
 /*                             OSRCleanup()                             */
 /************************************************************************/
 
-CPL_C_START 
+CPL_C_START
 void CleanupESRIDatumMappingTable();
 CPL_C_END
 static void CleanupSRSWGS84Thread();
@@ -7138,7 +7134,7 @@ static void CleanupSRSWGS84Thread();
  * \brief Cleanup cached SRS related memory.
  *
  * This function will attempt to cleanup any cache spatial reference
- * related information, such as cached tables of coordinate systems. 
+ * related information, such as cached tables of coordinate systems.
  */
 void OSRCleanup( void )
 
@@ -7156,23 +7152,23 @@ void OSRCleanup( void )
 /**
  * \brief Fetch the orientation of one axis.
  *
- * Fetches the the request axis (iAxis - zero based) from the
+ * Fetches the request axis (iAxis - zero based) from the
  * indicated portion of the coordinate system (pszTargetKey) which
- * should be either "GEOGCS" or "PROJCS". 
+ * should be either "GEOGCS" or "PROJCS".
  *
  * No CPLError is issued on routine failures (such as not finding the AXIS).
  *
  * This method is equivalent to the C function OSRGetAxis().
  *
  * @param pszTargetKey the coordinate system part to query ("PROJCS" or "GEOGCS").
- * @param iAxis the axis to query (0 for first, 1 for second). 
+ * @param iAxis the axis to query (0 for first, 1 for second).
  * @param peOrientation location into which to place the fetch orientation, may be NULL.
  *
  * @return the name of the axis or NULL on failure.
  */
 
 const char *
-OGRSpatialReference::GetAxis( const char *pszTargetKey, int iAxis, 
+OGRSpatialReference::GetAxis( const char *pszTargetKey, int iAxis,
                               OGRAxisOrientation *peOrientation ) const
 
 {
@@ -7182,12 +7178,12 @@ OGRSpatialReference::GetAxis( const char *pszTargetKey, int iAxis,
 /* -------------------------------------------------------------------- */
 /*      Find the target node.                                           */
 /* -------------------------------------------------------------------- */
-    OGR_SRSNode  *poNode;
+    OGR_SRSNode  *poNode = NULL;
 
     if( pszTargetKey == NULL )
         poNode = poRoot;
     else
-        poNode= ((OGRSpatialReference *) this)->GetAttrNode( pszTargetKey );
+        poNode = const_cast<OGRSpatialReference *>(this)->GetAttrNode( pszTargetKey );
 
     if( poNode == NULL )
         return NULL;
@@ -7196,9 +7192,9 @@ OGRSpatialReference::GetAxis( const char *pszTargetKey, int iAxis,
 /*      Find desired child AXIS.                                        */
 /* -------------------------------------------------------------------- */
     OGR_SRSNode *poAxis = NULL;
-    int iChild, nChildCount = poNode->GetChildCount();
+    const int nChildCount = poNode->GetChildCount();
 
-    for( iChild = 0; iChild < nChildCount; iChild++ )
+    for( int iChild = 0; iChild < nChildCount; iChild++ )
     {
         OGR_SRSNode *poChild = poNode->GetChild( iChild );
 
@@ -7242,7 +7238,7 @@ OGRSpatialReference::GetAxis( const char *pszTargetKey, int iAxis,
             *peOrientation = OAO_Other;
         else
         {
-            CPLDebug( "OSR", "Unrecognised orientation value '%s'.",
+            CPLDebug( "OSR", "Unrecognized orientation value '%s'.",
                       pszOrientation );
         }
     }
@@ -7260,14 +7256,14 @@ OGRSpatialReference::GetAxis( const char *pszTargetKey, int iAxis,
  * This method is the equivalent of the C++ method OGRSpatialReference::GetAxis
  */
 const char *OSRGetAxis( OGRSpatialReferenceH hSRS,
-                        const char *pszTargetKey, int iAxis, 
+                        const char *pszTargetKey, int iAxis,
                         OGRAxisOrientation *peOrientation )
 
 {
     VALIDATE_POINTER1( hSRS, "OSRGetAxis", NULL );
 
-    return ((OGRSpatialReference *) hSRS)->GetAxis( pszTargetKey, iAxis,
-                                                    peOrientation );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->GetAxis( pszTargetKey, iAxis,
+                                                              peOrientation );
 }
 
 /************************************************************************/
@@ -7309,37 +7305,38 @@ const char *OSRAxisEnumToName( OGRAxisOrientation eOrientation )
 /**
  * \brief Set the axes for a coordinate system.
  *
- * Set the names, and orientations of the axes for either a projected 
- * (PROJCS) or geographic (GEOGCS) coordinate system.  
+ * Set the names, and orientations of the axes for either a projected
+ * (PROJCS) or geographic (GEOGCS) coordinate system.
  *
  * This method is equivalent to the C function OSRSetAxes().
  *
  * @param pszTargetKey either "PROJCS" or "GEOGCS", must already exist in SRS.
- * @param pszXAxisName name of first axis, normally "Long" or "Easting". 
+ * @param pszXAxisName name of first axis, normally "Long" or "Easting".
  * @param eXAxisOrientation normally OAO_East.
- * @param pszYAxisName name of second axis, normally "Lat" or "Northing". 
- * @param eYAxisOrientation normally OAO_North. 
- * 
+ * @param pszYAxisName name of second axis, normally "Lat" or "Northing".
+ * @param eYAxisOrientation normally OAO_North.
+ *
  * @return OGRERR_NONE on success or an error code.
  */
 
-OGRErr 
-OGRSpatialReference::SetAxes( const char *pszTargetKey, 
-                              const char *pszXAxisName, 
+OGRErr
+OGRSpatialReference::SetAxes( const char *pszTargetKey,
+                              const char *pszXAxisName,
                               OGRAxisOrientation eXAxisOrientation,
-                              const char *pszYAxisName, 
+                              const char *pszYAxisName,
                               OGRAxisOrientation eYAxisOrientation )
 
 {
 /* -------------------------------------------------------------------- */
 /*      Find the target node.                                           */
 /* -------------------------------------------------------------------- */
-    OGR_SRSNode  *poNode;
+    OGR_SRSNode *poNode = NULL;
 
     if( pszTargetKey == NULL )
         poNode = poRoot;
     else
-        poNode= ((OGRSpatialReference *) this)->GetAttrNode( pszTargetKey );
+        poNode = reinterpret_cast<OGRSpatialReference *>(this)->
+            GetAttrNode( pszTargetKey );
 
     if( poNode == NULL )
         return OGRERR_FAILURE;
@@ -7359,7 +7356,7 @@ OGRSpatialReference::SetAxes( const char *pszTargetKey,
     poAxis->AddChild( new OGR_SRSNode( OSRAxisEnumToName(eXAxisOrientation) ));
 
     poNode->AddChild( poAxis );
-    
+
     poAxis = new OGR_SRSNode( "AXIS" );
 
     poAxis->AddChild( new OGR_SRSNode( pszYAxisName ) );
@@ -7379,18 +7376,18 @@ OGRSpatialReference::SetAxes( const char *pszTargetKey,
  * This method is the equivalent of the C++ method OGRSpatialReference::SetAxes
  */
 OGRErr OSRSetAxes( OGRSpatialReferenceH hSRS,
-                   const char *pszTargetKey, 
-                   const char *pszXAxisName, 
+                   const char *pszTargetKey,
+                   const char *pszXAxisName,
                    OGRAxisOrientation eXAxisOrientation,
-                   const char *pszYAxisName, 
+                   const char *pszYAxisName,
                    OGRAxisOrientation eYAxisOrientation )
 {
     VALIDATE_POINTER1( hSRS, "OSRSetAxes", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->SetAxes( pszTargetKey,
-                                                    pszXAxisName, 
-                                                    eXAxisOrientation,
-                                                    pszYAxisName, 
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetAxes( pszTargetKey,
+                                                              pszXAxisName,
+                                                              eXAxisOrientation,
+                                                              pszYAxisName,
                                                     eYAxisOrientation );
 }
 
@@ -7410,11 +7407,11 @@ OGRSpatialReference CPL_DLL * MITABCoordSys2SpatialRef( const char * );
 OGRErr OSRExportToMICoordSys( OGRSpatialReferenceH hSRS, char ** ppszReturn )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRExportToMICoordSys", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRExportToMICoordSys", OGRERR_FAILURE );
 
     *ppszReturn = NULL;
 
-    return ((OGRSpatialReference *) hSRS)->exportToMICoordSys( ppszReturn );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->exportToMICoordSys( ppszReturn );
 }
 
 /************************************************************************/
@@ -7435,7 +7432,7 @@ OGRErr OSRExportToMICoordSys( OGRSpatialReferenceH hSRS, char ** ppszReturn )
  * @return  OGRERR_NONE on success, OGRERR_FAILURE on failure,
  * OGRERR_UNSUPPORTED_OPERATION if MITAB library was not linked in.
  */
- 
+
 OGRErr OGRSpatialReference::exportToMICoordSys( char **ppszResult ) const
 
 {
@@ -7443,14 +7440,14 @@ OGRErr OGRSpatialReference::exportToMICoordSys( char **ppszResult ) const
     *ppszResult = MITABSpatialRef2CoordSys( (OGRSpatialReference *) this );
     if( *ppszResult != NULL && strlen(*ppszResult) > 0 )
         return OGRERR_NONE;
-    else
-        return OGRERR_FAILURE;
+
+    return OGRERR_FAILURE;
 #else
     CPLError( CE_Failure, CPLE_NotSupported,
               "MITAB not available, CoordSys support disabled." );
 
     return OGRERR_UNSUPPORTED_OPERATION;
-#endif    
+#endif
 }
 
 /************************************************************************/
@@ -7466,9 +7463,9 @@ OGRErr OSRImportFromMICoordSys( OGRSpatialReferenceH hSRS,
                                 const char *pszCoordSys )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRImportFromMICoordSys", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRImportFromMICoordSys", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *)hSRS)->importFromMICoordSys( pszCoordSys );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->importFromMICoordSys( pszCoordSys );
 }
 
 /************************************************************************/
@@ -7496,7 +7493,7 @@ OGRErr OGRSpatialReference::importFromMICoordSys( const char *pszCoordSys )
 
     if( poResult == NULL )
         return OGRERR_FAILURE;
-    
+
     *this = *poResult;
     delete poResult;
 
@@ -7506,7 +7503,7 @@ OGRErr OGRSpatialReference::importFromMICoordSys( const char *pszCoordSys )
               "MITAB not available, CoordSys support disabled." );
 
     return OGRERR_UNSUPPORTED_OPERATION;
-#endif    
+#endif
 }
 
 /************************************************************************/
@@ -7527,14 +7524,14 @@ double OSRCalcInvFlattening( double dfSemiMajor, double dfSemiMinor )
 {
     if( fabs(dfSemiMajor-dfSemiMinor) < 1e-1 )
         return 0;
-    else if( dfSemiMajor <= 0 || dfSemiMinor <= 0 || dfSemiMinor > dfSemiMajor )
+    if( dfSemiMajor <= 0 || dfSemiMinor <= 0 || dfSemiMinor > dfSemiMajor )
     {
         CPLError(CE_Failure, CPLE_IllegalArg,
                  "OSRCalcInvFlattening(): Wrong input values");
         return 0;
     }
-    else
-        return dfSemiMajor / (dfSemiMajor - dfSemiMinor);
+
+    return dfSemiMajor / (dfSemiMajor - dfSemiMinor);
 }
 
 /************************************************************************/
@@ -7555,14 +7552,14 @@ double OSRCalcSemiMinorFromInvFlattening( double dfSemiMajor, double dfInvFlatte
 {
     if( fabs(dfInvFlattening) < 0.000000000001 )
         return dfSemiMajor;
-    else if( dfSemiMajor <= 0.0 || dfInvFlattening <= 1.0 )
+    if( dfSemiMajor <= 0.0 || dfInvFlattening <= 1.0 )
     {
         CPLError(CE_Failure, CPLE_IllegalArg,
                  "OSRCalcSemiMinorFromInvFlattening(): Wrong input values");
         return dfSemiMajor;
     }
-    else
-        return dfSemiMajor * (1.0 - 1.0/dfInvFlattening);
+
+    return dfSemiMajor * (1.0 - 1.0/dfInvFlattening);
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsurface.cpp b/ogr/ogrsurface.cpp
index ee0b99d..9bbf4a9 100644
--- a/ogr/ogrsurface.cpp
+++ b/ogr/ogrsurface.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsurface.cpp 27959 2014-11-14 18:29:21Z rouault $
+ * $Id: ogrsurface.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRSurface class.
@@ -36,7 +36,7 @@
  * \brief Get the area of the surface object.
  *
  * For polygons the area is computed as the area of the outer ring less
- * the area of all internal rings. 
+ * the area of all internal rings.
  *
  * This method relates to the SFCOM ISurface::get_Area() method.
  *
@@ -51,9 +51,9 @@
  *
  * NOTE: Only implemented when GEOS included in build.
  *
- * @param poPoint point to be set with an internal point. 
+ * @param poPoint point to be set with an internal point.
  *
- * @return OGRERR_NONE if it succeeds or OGRERR_FAILURE otherwise. 
+ * @return OGRERR_NONE if it succeeds or OGRERR_FAILURE otherwise.
  */
 
 /************************************************************************/
@@ -65,7 +65,7 @@
  *
  * The passed in geometry is consumed and a new one returned (or NULL in case
  * of failure)
- * 
+ *
  * @param poSurface the input geometry - ownership is passed to the method.
  * @return new geometry.
  */
@@ -85,7 +85,7 @@ OGRPolygon* OGRSurface::CastToPolygon(OGRSurface* poSurface)
  *
  * The passed in geometry is consumed and a new one returned (or NULL in case
  * of failure)
- * 
+ *
  * @param poSurface the input geometry - ownership is passed to the method.
  * @return new geometry.
  */
diff --git a/ogr/ogrutils.cpp b/ogr/ogrutils.cpp
index 54215e7..b841cde 100644
--- a/ogr/ogrutils.cpp
+++ b/ogr/ogrutils.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrutils.cpp 28900 2015-04-14 09:40:34Z rouault $
+ * $Id: ogrutils.cpp 33757 2016-03-20 20:22:33Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Utility functions for OGR classes, including some related to
@@ -37,22 +37,37 @@
 #include "ogr_geometry.h"
 #include "ogr_p.h"
 
-#ifdef OGR_ENABLED
 # include "ogrsf_frmts.h"
-#endif /* OGR_ENABLED */
 
-CPL_CVSID("$Id: ogrutils.cpp 28900 2015-04-14 09:40:34Z rouault $");
+CPL_CVSID("$Id: ogrutils.cpp 33757 2016-03-20 20:22:33Z goatbar $");
 
 /************************************************************************/
 /*                        OGRFormatDouble()                             */
 /************************************************************************/
 
-void OGRFormatDouble( char *pszBuffer, int nBufferLen, double dfVal, char chDecimalSep, int nPrecision )
+void OGRFormatDouble( char *pszBuffer, int nBufferLen, double dfVal,
+                      char chDecimalSep, int nPrecision, char chConversionSpecifier )
 {
     int i;
     int nTruncations = 0;
     char szFormat[16];
-    sprintf(szFormat, "%%.%df", nPrecision);
+
+    // So to have identical cross platform representation
+    if( CPLIsInf(dfVal) )
+    {
+        if( dfVal > 0 )
+            CPLsnprintf(pszBuffer, nBufferLen, "%s", "inf");
+        else
+            CPLsnprintf(pszBuffer, nBufferLen, "%s", "-inf");
+        return;
+    }
+    if( CPLIsNan(dfVal) )
+    {
+        CPLsnprintf(pszBuffer, nBufferLen, "%s", "nan");
+        return;
+    }
+
+    snprintf(szFormat, sizeof(szFormat), "%%.%d%c", nPrecision, chConversionSpecifier);
 
     int ret = CPLsnprintf(pszBuffer, nBufferLen, szFormat, dfVal);
     /* Windows CRT doesn't conform with C99 and return -1 when buffer is truncated */
@@ -62,6 +77,9 @@ void OGRFormatDouble( char *pszBuffer, int nBufferLen, double dfVal, char chDeci
         return;
     }
 
+    if( chConversionSpecifier == 'g' && strchr(pszBuffer, 'e') )
+        return;
+
     while(nPrecision > 0)
     {
         i = 0;
@@ -69,7 +87,7 @@ void OGRFormatDouble( char *pszBuffer, int nBufferLen, double dfVal, char chDeci
         int iDotPos = -1;
         while( pszBuffer[i] != '\0' )
         {
-            if ((pszBuffer[i] == '.' || pszBuffer[i] == ',') && chDecimalSep != '\0')
+            if (pszBuffer[i] == '.' && chDecimalSep != '\0')
             {
                 iDotPos = i;
                 pszBuffer[i] = chDecimalSep;
@@ -78,26 +96,28 @@ void OGRFormatDouble( char *pszBuffer, int nBufferLen, double dfVal, char chDeci
                 nCountBeforeDot ++;
             i++;
         }
+        if( iDotPos < 0 )
+            break;
 
     /* -------------------------------------------------------------------- */
     /*      Trim trailing 00000x's as they are likely roundoff error.       */
     /* -------------------------------------------------------------------- */
-        if( i > 10 && iDotPos >=0 )
+        if( i > 10 )
         {
             if (/* && pszBuffer[i-1] == '1' &&*/
-                pszBuffer[i-2] == '0' 
-                && pszBuffer[i-3] == '0' 
-                && pszBuffer[i-4] == '0' 
-                && pszBuffer[i-5] == '0' 
+                pszBuffer[i-2] == '0'
+                && pszBuffer[i-3] == '0'
+                && pszBuffer[i-4] == '0'
+                && pszBuffer[i-5] == '0'
                 && pszBuffer[i-6] == '0' )
             {
                 pszBuffer[--i] = '\0';
             }
             else if( i - 8 > iDotPos && /* pszBuffer[i-1] == '1' */
                   /* && pszBuffer[i-2] == '0' && */
-                    (nCountBeforeDot >= 4 || pszBuffer[i-3] == '0') 
-                    && (nCountBeforeDot >= 5 || pszBuffer[i-4] == '0') 
-                    && (nCountBeforeDot >= 6 || pszBuffer[i-5] == '0') 
+                    (nCountBeforeDot >= 4 || pszBuffer[i-3] == '0')
+                    && (nCountBeforeDot >= 5 || pszBuffer[i-4] == '0')
+                    && (nCountBeforeDot >= 6 || pszBuffer[i-5] == '0')
                     && (nCountBeforeDot >= 7 || pszBuffer[i-6] == '0')
                     && (nCountBeforeDot >= 8 || pszBuffer[i-7] == '0')
                     && pszBuffer[i-8] == '0'
@@ -120,27 +140,28 @@ void OGRFormatDouble( char *pszBuffer, int nBufferLen, double dfVal, char chDeci
     /*      Detect trailing 99999X's as they are likely roundoff error.     */
     /* -------------------------------------------------------------------- */
         if( i > 10 &&
-            iDotPos >= 0 &&
             nPrecision + nTruncations >= 15)
         {
             if (/*pszBuffer[i-1] == '9' && */
-                 pszBuffer[i-2] == '9' 
-                && pszBuffer[i-3] == '9' 
-                && pszBuffer[i-4] == '9' 
-                && pszBuffer[i-5] == '9' 
+                 pszBuffer[i-2] == '9'
+                && pszBuffer[i-3] == '9'
+                && pszBuffer[i-4] == '9'
+                && pszBuffer[i-5] == '9'
                 && pszBuffer[i-6] == '9' )
             {
                 nPrecision --;
                 nTruncations ++;
-                sprintf(szFormat, "%%.%df", nPrecision);
+                snprintf(szFormat, sizeof(szFormat), "%%.%d%c", nPrecision, chConversionSpecifier);
                 CPLsnprintf(pszBuffer, nBufferLen, szFormat, dfVal);
+                if( chConversionSpecifier == 'g' && strchr(pszBuffer, 'e') )
+                    return;
                 continue;
             }
             else if (i - 9 > iDotPos && /*pszBuffer[i-1] == '9' && */
                      /*pszBuffer[i-2] == '9' && */
-                    (nCountBeforeDot >= 4 || pszBuffer[i-3] == '9') 
-                    && (nCountBeforeDot >= 5 || pszBuffer[i-4] == '9') 
-                    && (nCountBeforeDot >= 6 || pszBuffer[i-5] == '9') 
+                    (nCountBeforeDot >= 4 || pszBuffer[i-3] == '9')
+                    && (nCountBeforeDot >= 5 || pszBuffer[i-4] == '9')
+                    && (nCountBeforeDot >= 6 || pszBuffer[i-5] == '9')
                     && (nCountBeforeDot >= 7 || pszBuffer[i-6] == '9')
                     && (nCountBeforeDot >= 8 || pszBuffer[i-7] == '9')
                     && pszBuffer[i-8] == '9'
@@ -148,8 +169,10 @@ void OGRFormatDouble( char *pszBuffer, int nBufferLen, double dfVal, char chDeci
             {
                 nPrecision --;
                 nTruncations ++;
-                sprintf(szFormat, "%%.%df", nPrecision);
+                snprintf(szFormat, sizeof(szFormat), "%%.%d%c", nPrecision, chConversionSpecifier);
                 CPLsnprintf(pszBuffer, nBufferLen, szFormat, dfVal);
+                if( chConversionSpecifier == 'g' && strchr(pszBuffer, 'e') )
+                    return;
                 continue;
             }
         }
@@ -170,12 +193,14 @@ void OGRFormatDouble( char *pszBuffer, int nBufferLen, double dfVal, char chDeci
 /*      characters barring the X or Y value being extremely large.      */
 /************************************************************************/
 
-void OGRMakeWktCoordinate( char *pszTarget, double x, double y, double z, 
+void OGRMakeWktCoordinate( char *pszTarget, double x, double y, double z,
                            int nDimension )
 
 {
     const size_t bufSize = 75;
     const size_t maxTargetSize = 75; /* Assumed max length of the target buffer. */
+    const char chDecimalSep = '.';
+    const int nPrecision = 15;
 
     char szX[bufSize];
     char szY[bufSize];
@@ -183,17 +208,27 @@ void OGRMakeWktCoordinate( char *pszTarget, double x, double y, double z,
 
     szZ[0] = '\0';
 
-    int nLenX, nLenY;
+    size_t nLenX, nLenY;
 
-    if( x == (int) x && y == (int) y )
+    if( CPL_IS_DOUBLE_A_INT(x) && CPL_IS_DOUBLE_A_INT(y) )
     {
         snprintf( szX, bufSize, "%d", (int) x );
         snprintf( szY, bufSize, "%d", (int) y );
     }
     else
     {
-        OGRFormatDouble( szX, bufSize, x, '.' );
-        OGRFormatDouble( szY, bufSize, y, '.' );
+        OGRFormatDouble( szX, bufSize, x, chDecimalSep, nPrecision, fabs(x) < 1 ? 'f' : 'g' );
+        if( CPLIsFinite(x) && strchr(szX, '.') == NULL &&
+            strchr(szX, 'e') == NULL && strlen(szX) < bufSize - 2 )
+        {
+            strcat(szX, ".0");
+        }
+        OGRFormatDouble( szY, bufSize, y, chDecimalSep, nPrecision, fabs(y) < 1 ? 'f' : 'g' );
+        if( CPLIsFinite(y) && strchr(szY, '.') == NULL &&
+            strchr(szY, 'e') == NULL && strlen(szY) < bufSize - 2 )
+        {
+            strcat(szY, ".0");
+        }
     }
 
     nLenX = strlen(szX);
@@ -201,22 +236,22 @@ void OGRMakeWktCoordinate( char *pszTarget, double x, double y, double z,
 
     if( nDimension == 3 )
     {
-        if( z == (int) z )
+        if( CPL_IS_DOUBLE_A_INT(z) )
         {
             snprintf( szZ, bufSize, "%d", (int) z );
         }
         else
         {
-            OGRFormatDouble( szZ, bufSize, z, '.' );
+            OGRFormatDouble( szZ, bufSize, z, chDecimalSep, nPrecision, 'g' );
         }
     }
 
     if( nLenX + 1 + nLenY + ((nDimension == 3) ? (1 + strlen(szZ)) : 0) >= maxTargetSize )
     {
 #ifdef DEBUG
-        CPLDebug( "OGR", 
+        CPLDebug( "OGR",
                   "Yow!  Got this big result in OGRMakeWktCoordinate()\n"
-                  "%s %s %s", 
+                  "%s %s %s",
                   szX, szY, szZ );
 #endif
         if( nDimension == 3 )
@@ -242,9 +277,132 @@ void OGRMakeWktCoordinate( char *pszTarget, double x, double y, double z,
 }
 
 /************************************************************************/
+/*                        OGRMakeWktCoordinateM()                       */
+/*                                                                      */
+/*      Format a well known text coordinate, trying to keep the         */
+/*      ASCII representation compact, but accurate.  These rules        */
+/*      will have to tighten up in the future.                          */
+/*                                                                      */
+/*      Currently a new point should require no more than 64            */
+/*      characters barring the X or Y value being extremely large.      */
+/************************************************************************/
+
+void OGRMakeWktCoordinateM( char *pszTarget, double x, double y, double z, double m,
+                            OGRBoolean hasZ, OGRBoolean hasM )
+
+{
+    const size_t bufSize = 75;
+    const size_t maxTargetSize = 75; /* Assumed max length of the target buffer. */
+    const char chDecimalSep = '.';
+    const int nPrecision = 15;
+
+    char szX[bufSize];
+    char szY[bufSize];
+    char szZ[bufSize];
+    char szM[bufSize];
+
+    szZ[0] = '\0';
+    szM[0] = '\0';
+
+    size_t nLen, nLenX, nLenY;
+
+    if( CPL_IS_DOUBLE_A_INT(x) && CPL_IS_DOUBLE_A_INT(y) )
+    {
+        snprintf( szX, bufSize, "%d", (int) x );
+        snprintf( szY, bufSize, "%d", (int) y );
+    }
+    else
+    {
+        OGRFormatDouble( szX, bufSize, x, chDecimalSep, nPrecision, fabs(x) < 1 ? 'f' : 'g' );
+        if( CPLIsFinite(x) && strchr(szX, '.') == NULL &&
+            strchr(szX, 'e') == NULL && strlen(szX) < bufSize - 2 )
+        {
+            strcat(szX, ".0");
+        }
+        OGRFormatDouble( szY, bufSize, y, chDecimalSep, nPrecision, fabs(y) < 1 ? 'f' : 'g' );
+        if( CPLIsFinite(y) && strchr(szY, '.') == NULL &&
+            strchr(szY, 'e') == NULL && strlen(szY) < bufSize - 2 )
+        {
+            strcat(szY, ".0");
+        }
+    }
+
+    nLenX = strlen(szX);
+    nLenY = strlen(szY);
+    nLen = nLenX + nLenY + 1;
+
+    if( hasZ )
+    {
+        if( CPL_IS_DOUBLE_A_INT(z) )
+        {
+            snprintf( szZ, bufSize, "%d", (int) z );
+        }
+        else
+        {
+            OGRFormatDouble( szZ, bufSize, z, chDecimalSep, nPrecision, 'g' );
+        }
+        nLen += strlen(szZ) + 1;
+    }
+
+    if( hasM )
+    {
+        if( CPL_IS_DOUBLE_A_INT(m) )
+        {
+            snprintf( szM, bufSize, "%d", (int) m );
+        }
+        else
+        {
+            OGRFormatDouble( szM, bufSize, m, chDecimalSep, nPrecision, 'g' );
+        }
+        nLen += strlen(szM) + 1;
+    }
+
+    if( nLen >= maxTargetSize )
+    {
+#ifdef DEBUG
+        CPLDebug( "OGR",
+                  "Yow!  Got this big result in OGRMakeWktCoordinate()\n"
+                  "%s %s %s %s",
+                  szX, szY, szZ, szM );
+#endif
+        if( hasZ && hasM )
+            strcpy( pszTarget, "0 0 0 0");
+        else if( hasZ || hasM )
+            strcpy( pszTarget, "0 0 0");
+        else
+            strcpy( pszTarget, "0 0");
+    }
+    else
+    {
+        char *target = pszTarget;
+        strcpy( target, szX );
+        target += nLenX;
+        *target = ' ';
+        target++;
+        strcpy( target, szY );
+        target += nLenY;
+        if( hasZ )
+        {
+            *target = ' ';
+            target++;
+            strcpy( target, szZ );
+            target += strlen(szZ);
+        }
+        if( hasM )
+        {
+            *target = ' ';
+            target++;
+            strcpy( target, szM );
+            target += strlen(szM);
+        }
+        *target = '\0';
+    }
+}
+
+/************************************************************************/
 /*                          OGRWktReadToken()                           */
 /*                                                                      */
-/*      Read one token or delimeter and put into token buffer.  Pre     */
+/*      Read one token or delimiter and put into token buffer.  Pre     */
 /*      and post white space is swallowed.                              */
 /************************************************************************/
 
@@ -253,7 +411,7 @@ const char *OGRWktReadToken( const char * pszInput, char * pszToken )
 {
     if( pszInput == NULL )
         return NULL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Swallow pre-white space.                                        */
 /* -------------------------------------------------------------------- */
@@ -261,13 +419,13 @@ const char *OGRWktReadToken( const char * pszInput, char * pszToken )
         pszInput++;
 
 /* -------------------------------------------------------------------- */
-/*      If this is a delimeter, read just one character.                */
+/*      If this is a delimiter, read just one character.                */
 /* -------------------------------------------------------------------- */
     if( *pszInput == '(' || *pszInput == ')' || *pszInput == ',' )
     {
         pszToken[0] = *pszInput;
         pszToken[1] = '\0';
-        
+
         pszInput++;
     }
 
@@ -278,13 +436,13 @@ const char *OGRWktReadToken( const char * pszInput, char * pszToken )
     else
     {
         int             iChar = 0;
-        
+
         while( iChar < OGR_WKT_TOKEN_MAX-1
                && ((*pszInput >= 'a' && *pszInput <= 'z')
                    || (*pszInput >= 'A' && *pszInput <= 'Z')
                    || (*pszInput >= '0' && *pszInput <= '9')
-                   || *pszInput == '.' 
-                   || *pszInput == '+' 
+                   || *pszInput == '.'
+                   || *pszInput == '+'
                    || *pszInput == '-') )
         {
             pszToken[iChar++] = *(pszInput++);
@@ -320,7 +478,7 @@ const char * OGRWktReadPoints( const char * pszInput,
 
     if( pszInput == NULL )
         return NULL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Eat any leading white space.                                    */
 /* -------------------------------------------------------------------- */
@@ -335,7 +493,7 @@ const char * OGRWktReadPoints( const char * pszInput,
         CPLDebug( "OGR",
                   "Expected '(', but got %s in OGRWktReadPoints().\n",
                   pszInput );
-                  
+
         return pszInput;
     }
 
@@ -347,7 +505,7 @@ const char * OGRWktReadPoints( const char * pszInput,
 /*      encountered.                                                    */
 /* ==================================================================== */
     char        szDelim[OGR_WKT_TOKEN_MAX];
-    
+
     do {
 /* -------------------------------------------------------------------- */
 /*      Read the X and Y values, verify they are numeric.               */
@@ -402,7 +560,7 @@ const char * OGRWktReadPoints( const char * pszInput,
         }
         else if ( *ppadfZ != NULL )
             (*ppadfZ)[*pnPointsRead] = 0.0;
-        
+
         (*pnPointsRead)++;
 
 /* -------------------------------------------------------------------- */
@@ -413,9 +571,9 @@ const char * OGRWktReadPoints( const char * pszInput,
         {
             pszInput = OGRWktReadToken( pszInput, szDelim );
         }
-        
+
 /* -------------------------------------------------------------------- */
-/*      Read next delimeter ... it should be a comma if there are       */
+/*      Read next delimiter ... it should be a comma if there are       */
 /*      more points.                                                    */
 /* -------------------------------------------------------------------- */
         if( szDelim[0] != ')' && szDelim[0] != ',' )
@@ -426,7 +584,218 @@ const char * OGRWktReadPoints( const char * pszInput,
                       szDelim, pszInput, pszOrigInput );
             return NULL;
         }
-        
+
+    } while( szDelim[0] == ',' );
+
+    return pszInput;
+}
+
+/************************************************************************/
+/*                          OGRWktReadPointsM()                         */
+/*                                                                      */
+/*      Read a point string.  The point list must be contained in       */
+/*      brackets and each point pair separated by a comma.              */
+/************************************************************************/
+
+const char * OGRWktReadPointsM( const char * pszInput,
+                                OGRRawPoint ** ppaoPoints, double **ppadfZ, double **ppadfM,
+                                int * flags,
+                                int * pnMaxPoints,
+                                int * pnPointsRead )
+
+{
+    const char *pszOrigInput = pszInput;
+    int no_flags = !(*flags & OGRGeometry::OGR_G_3D) && !(*flags & OGRGeometry::OGR_G_MEASURED);
+    *pnPointsRead = 0;
+
+    if( pszInput == NULL )
+        return NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Eat any leading white space.                                    */
+/* -------------------------------------------------------------------- */
+    while( *pszInput == ' ' || *pszInput == '\t' )
+        pszInput++;
+
+/* -------------------------------------------------------------------- */
+/*      If this isn't an opening bracket then we have a problem!        */
+/* -------------------------------------------------------------------- */
+    if( *pszInput != '(' )
+    {
+        CPLDebug( "OGR",
+                  "Expected '(', but got %s in OGRWktReadPointsM().\n",
+                  pszInput );
+
+        return pszInput;
+    }
+
+    pszInput++;
+
+/* ==================================================================== */
+/*      This loop reads a single point.  It will continue till we       */
+/*      run out of well formed points, or a closing bracket is          */
+/*      encountered.                                                    */
+/* ==================================================================== */
+    char        szDelim[OGR_WKT_TOKEN_MAX];
+
+    do {
+/* -------------------------------------------------------------------- */
+/*      Read the X and Y values, verify they are numeric.               */
+/* -------------------------------------------------------------------- */
+        char    szTokenX[OGR_WKT_TOKEN_MAX];
+        char    szTokenY[OGR_WKT_TOKEN_MAX];
+
+        pszInput = OGRWktReadToken( pszInput, szTokenX );
+        pszInput = OGRWktReadToken( pszInput, szTokenY );
+
+        if( (!isdigit(szTokenX[0]) && szTokenX[0] != '-' && szTokenX[0] != '.' )
+            || (!isdigit(szTokenY[0]) && szTokenY[0] != '-' && szTokenY[0] != '.') )
+            return NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Do we need to grow the point list to hold this point?           */
+/* -------------------------------------------------------------------- */
+        if( *pnPointsRead == *pnMaxPoints )
+        {
+            *pnMaxPoints = *pnMaxPoints * 2 + 10;
+            *ppaoPoints = (OGRRawPoint *)
+                CPLRealloc(*ppaoPoints, sizeof(OGRRawPoint) * *pnMaxPoints);
+
+            if( *ppadfZ != NULL )
+            {
+                *ppadfZ = (double *)
+                    CPLRealloc(*ppadfZ, sizeof(double) * *pnMaxPoints);
+            }
+
+            if( *ppadfM != NULL )
+            {
+                *ppadfM = (double *)
+                    CPLRealloc(*ppadfM, sizeof(double) * *pnMaxPoints);
+            }
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Add point to list.                                              */
+/* -------------------------------------------------------------------- */
+        (*ppaoPoints)[*pnPointsRead].x = CPLAtof(szTokenX);
+        (*ppaoPoints)[*pnPointsRead].y = CPLAtof(szTokenY);
+
+/* -------------------------------------------------------------------- */
+/*      Read the next token.                                            */
+/* -------------------------------------------------------------------- */
+        pszInput = OGRWktReadToken( pszInput, szDelim );
+
+/* -------------------------------------------------------------------- */
+/*      If there are unexpectedly more coordinates, they are Z.         */
+/* -------------------------------------------------------------------- */
+
+        if( !(*flags & OGRGeometry::OGR_G_3D) && !(*flags & OGRGeometry::OGR_G_MEASURED) &&
+            (isdigit(szDelim[0]) || szDelim[0] == '-' || szDelim[0] == '.' ))
+        {
+            *flags |= OGRGeometry::OGR_G_3D;
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Get Z if flag says so.                                          */
+/*      Zero out possible remains from earlier strings.                 */
+/* -------------------------------------------------------------------- */
+
+        if( *flags & OGRGeometry::OGR_G_3D )
+        {
+            if( *ppadfZ == NULL )
+            {
+                *ppadfZ = (double *) CPLCalloc(sizeof(double),*pnMaxPoints);
+            }
+            if( isdigit(szDelim[0]) || szDelim[0] == '-' || szDelim[0] == '.' )
+            {
+                (*ppadfZ)[*pnPointsRead] = CPLAtof(szDelim);
+                pszInput = OGRWktReadToken( pszInput, szDelim );
+            }
+            else {
+                (*ppadfZ)[*pnPointsRead] = 0.0;
+            }
+        }
+        else if ( *ppadfZ != NULL )
+            (*ppadfZ)[*pnPointsRead] = 0.0;
+
+/* -------------------------------------------------------------------- */
+/*      If there are unexpectedly even more coordinates,                */
+/*      they are discarded unless there were no flags originally.       */
+/*      This is for backwards compatibility. Should this be an error?   */
+/* -------------------------------------------------------------------- */
+
+        if( !(*flags & OGRGeometry::OGR_G_MEASURED) &&
+            (isdigit(szDelim[0]) || szDelim[0] == '-' || szDelim[0] == '.' ) )
+        {
+            if( no_flags )
+            {
+                *flags |= OGRGeometry::OGR_G_MEASURED;
+            }
+            else
+            {
+                pszInput = OGRWktReadToken( pszInput, szDelim );
+            }
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Get M if flag says so.                                          */
+/*      Zero out possible remains from earlier strings.                 */
+/* -------------------------------------------------------------------- */
+
+        if( *flags & OGRGeometry::OGR_G_MEASURED )
+        {
+            if( *ppadfM == NULL )
+            {
+                *ppadfM = (double *) CPLCalloc(sizeof(double),*pnMaxPoints);
+            }
+            if( isdigit(szDelim[0]) || szDelim[0] == '-' || szDelim[0] == '.' )
+            {
+                (*ppadfM)[*pnPointsRead] = CPLAtof(szDelim);
+                pszInput = OGRWktReadToken( pszInput, szDelim );
+            }
+            else {
+                (*ppadfM)[*pnPointsRead] = 0.0;
+            }
+        }
+        else if ( *ppadfM != NULL )
+            (*ppadfM)[*pnPointsRead] = 0.0;
+
+/* -------------------------------------------------------------------- */
+/*      If there are still more coordinates and we do not have Z        */
+/*      then we have a case of flags == M and four coordinates.         */
+/*      This is allowed in BNF.                                         */
+/* -------------------------------------------------------------------- */
+
+        if( !(*flags & OGRGeometry::OGR_G_3D) &&
+            (isdigit(szDelim[0]) || szDelim[0] == '-' || szDelim[0] == '.') )
+        {
+            *flags |= OGRGeometry::OGR_G_3D;
+            if( *ppadfZ == NULL )
+            {
+                *ppadfZ = (double *) CPLCalloc(sizeof(double),*pnMaxPoints);
+            }
+            (*ppadfZ)[*pnPointsRead] = (*ppadfM)[*pnPointsRead];
+            (*ppadfM)[*pnPointsRead] = CPLAtof(szDelim);
+            pszInput = OGRWktReadToken( pszInput, szDelim );
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Increase points index.                                          */
+/* -------------------------------------------------------------------- */
+        (*pnPointsRead)++;
+
+/* -------------------------------------------------------------------- */
+/*      The next delimiter should be a comma or an ending bracket.      */
+/* -------------------------------------------------------------------- */
+        if( szDelim[0] != ')' && szDelim[0] != ',' )
+        {
+            CPLDebug( "OGR",
+                      "Corrupt input in OGRWktReadPointsM()\n"
+                      "Got `%s' when expecting `,' or `)', near `%s' in %s.\n",
+                      szDelim, pszInput, pszOrigInput );
+            return NULL;
+        }
+
     } while( szDelim[0] == ',' );
 
     return pszInput;
@@ -483,28 +852,28 @@ void OGRFree( void * pMemory )
 /**
  * General utility option processing.
  *
- * This function is intended to provide a variety of generic commandline 
+ * This function is intended to provide a variety of generic commandline
  * options for all OGR commandline utilities.  It takes care of the following
  * commandline options:
- *  
- *  --version: report version of GDAL in use. 
+ *
+ *  --version: report version of GDAL in use.
  *  --license: report GDAL license info.
- *  --format [format]: report details of one format driver. 
+ *  --format [format]: report details of one format driver.
  *  --formats: report all format drivers configured.
- *  --optfile filename: expand an option file into the argument list. 
- *  --config key value: set system configuration option. 
+ *  --optfile filename: expand an option file into the argument list.
+ *  --config key value: set system configuration option.
  *  --debug [on/off/value]: set debug level.
  *  --pause: Pause for user input (allows time to attach debugger)
  *  --locale [locale]: Install a locale using setlocale() (debugging)
- *  --help-general: report detailed help on general options. 
+ *  --help-general: report detailed help on general options.
  *
- * The argument array is replaced "in place" and should be freed with 
+ * The argument array is replaced "in place" and should be freed with
  * CSLDestroy() when no longer needed.  The typical usage looks something
  * like the following.  Note that the formats should be registered so that
  * the --formats option will work properly.
  *
  *  int main( int argc, char ** argv )
- *  { 
+ *  {
  *    OGRRegisterAll();
  *
  *    argc = OGRGeneralCmdLineProcessor( argc, &argv, 0 );
@@ -512,10 +881,10 @@ void OGRFree( void * pMemory )
  *        exit( -argc );
  *
  * @param nArgc number of values in the argument list.
- * @param ppapszArgv pointer to the argument list array (will be updated in place). 
+ * @param ppapszArgv pointer to the argument list array (will be updated in place).
  * @param nOptions unused.
  *
- * @return updated nArgc argument count.  Return of 0 requests terminate 
+ * @return updated nArgc argument count.  Return of 0 requests terminate
  * without error, return of -1 requests exit with error code.
  */
 
@@ -536,18 +905,18 @@ int OGRGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
  * Parse date string.
  *
  * This function attempts to parse a date string in a variety of formats
- * into the OGRField.Date format suitable for use with OGR.  Generally 
+ * into the OGRField.Date format suitable for use with OGR.  Generally
  * speaking this function is expecting values like:
- * 
+ *
  *   YYYY-MM-DD HH:MM:SS[.sss]+nn
  *   or YYYY-MM-DDTHH:MM:SS[.sss]Z (ISO 8601 format)
  *
  * The seconds may also have a decimal portion (which is ignored).  And
- * just dates (YYYY-MM-DD) or just times (HH:MM:SS[.sss]) are also supported. 
+ * just dates (YYYY-MM-DD) or just times (HH:MM:SS[.sss]) are also supported.
  * The date may also be in YYYY/MM/DD format.  If the year is less than 100
  * and greater than 30 a "1900" century value will be set.  If it is less than
- * 30 and greater than -1 then a "2000" century value will be set.  In 
- * the future this function may be generalized, and additional control 
+ * 30 and greater than -1 then a "2000" century value will be set.  In
+ * the future this function may be generalized, and additional control
  * provided through nOptions, but an nOptions value of "0" should always do
  * a reasonable default form of processing.
  *
@@ -565,7 +934,7 @@ int OGRParseDate( const char *pszInput,
                   OGRField *psField,
                   CPL_UNUSED int nOptions )
 {
-    int bGotSomething = FALSE;
+    bool bGotSomething = false;
 
     psField->Date.Year = 0;
     psField->Date.Month = 0;
@@ -581,7 +950,7 @@ int OGRParseDate( const char *pszInput,
 /* -------------------------------------------------------------------- */
     while( *pszInput == ' ' )
         pszInput++;
-    
+
     if( strstr(pszInput,"-") != NULL || strstr(pszInput,"/") != NULL )
     {
         int nYear = atoi(pszInput);
@@ -597,22 +966,22 @@ int OGRParseDate( const char *pszInput,
         else if( psField->Date.Year < 30 && psField->Date.Year >= 0 )
             psField->Date.Year += 2000;
 
-        while( *pszInput >= '0' && *pszInput <= '9' ) 
+        while( *pszInput >= '0' && *pszInput <= '9' )
             pszInput++;
         if( *pszInput != '-' && *pszInput != '/' )
             return FALSE;
-        else 
+        else
             pszInput++;
 
         psField->Date.Month = (GByte)atoi(pszInput);
         if( psField->Date.Month > 12 )
             return FALSE;
 
-        while( *pszInput >= '0' && *pszInput <= '9' ) 
+        while( *pszInput >= '0' && *pszInput <= '9' )
             pszInput++;
         if( *pszInput != '-' && *pszInput != '/' )
             return FALSE;
-        else 
+        else
             pszInput++;
 
         psField->Date.Day = (GByte)atoi(pszInput);
@@ -622,8 +991,8 @@ int OGRParseDate( const char *pszInput,
         while( *pszInput >= '0' && *pszInput <= '9' )
             pszInput++;
 
-        bGotSomething = TRUE;
-        
+        bGotSomething = true;
+
         /* If ISO 8601 format */
         if( *pszInput == 'T' )
             pszInput ++;
@@ -634,25 +1003,25 @@ int OGRParseDate( const char *pszInput,
 /* -------------------------------------------------------------------- */
     while( *pszInput == ' ' )
         pszInput++;
-    
+
     if( strstr(pszInput,":") != NULL )
     {
         psField->Date.Hour = (GByte)atoi(pszInput);
         if( psField->Date.Hour > 23 )
             return FALSE;
 
-        while( *pszInput >= '0' && *pszInput <= '9' ) 
+        while( *pszInput >= '0' && *pszInput <= '9' )
             pszInput++;
         if( *pszInput != ':' )
             return FALSE;
-        else 
+        else
             pszInput++;
 
         psField->Date.Minute = (GByte)atoi(pszInput);
         if( psField->Date.Minute > 59 )
             return FALSE;
 
-        while( *pszInput >= '0' && *pszInput <= '9' ) 
+        while( *pszInput >= '0' && *pszInput <= '9' )
             pszInput++;
         if( *pszInput == ':' )
         {
@@ -675,7 +1044,7 @@ int OGRParseDate( const char *pszInput,
             }
         }
 
-        bGotSomething = TRUE;
+        bGotSomething = true;
     }
 
     // No date or time!
@@ -687,7 +1056,7 @@ int OGRParseDate( const char *pszInput,
 /* -------------------------------------------------------------------- */
     while( *pszInput == ' ' )
         pszInput++;
-    
+
     if( *pszInput == '-' || *pszInput == '+' )
     {
         // +HH integral offset
@@ -697,7 +1066,7 @@ int OGRParseDate( const char *pszInput,
         else if( pszInput[3] == ':'  // +HH:MM offset
                  && atoi(pszInput+4) % 15 == 0 )
         {
-            psField->Date.TZFlag = (GByte)(100 
+            psField->Date.TZFlag = (GByte)(100
                 + atoi(pszInput+1) * 4
                 + (atoi(pszInput+4) / 15));
 
@@ -707,7 +1076,7 @@ int OGRParseDate( const char *pszInput,
         else if( isdigit(pszInput[3]) && isdigit(pszInput[4])  // +HHMM offset
                  && atoi(pszInput+3) % 15 == 0 )
         {
-            psField->Date.TZFlag = (GByte)(100 
+            psField->Date.TZFlag = (GByte)(100
                 + static_cast<GByte>(CPLScanLong(pszInput+1,2)) * 4
                 + (atoi(pszInput+3) / 15));
 
@@ -717,7 +1086,7 @@ int OGRParseDate( const char *pszInput,
         else if( isdigit(pszInput[3]) && pszInput[4] == '\0'  // +HMM offset
                  && atoi(pszInput+2) % 15 == 0 )
         {
-            psField->Date.TZFlag = (GByte)(100 
+            psField->Date.TZFlag = (GByte)(100
                 + static_cast<GByte>(CPLScanLong(pszInput+1,1)) * 4
                 + (atoi(pszInput+2) / 15));
 
@@ -792,7 +1161,7 @@ int OGRParseXMLDateTime( const char* pszXMLDateTime,
 /*                      OGRParseRFC822DateTime()                        */
 /************************************************************************/
 
-static const char* aszMonthStr[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+static const char* const aszMonthStr[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
                                      "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
 
 int OGRParseRFC822DateTime( const char* pszRFC822DateTime, OGRField* psField )
@@ -883,7 +1252,7 @@ int OGRParseRFC822DateTime( const char* pszRFC822DateTime, OGRField* psField )
             psField->Date.Day = (GByte)day;
             psField->Date.Hour = (GByte)hour;
             psField->Date.Minute = (GByte)minute;
-            psField->Date.Second = second;
+            psField->Date.Second = static_cast<float>(second);
             psField->Date.TZFlag = (GByte)TZ;
             psField->Date.Reserved = 0;
         }
@@ -1009,10 +1378,10 @@ char* OGRGetXML_UTF8_EscapedString(const char* pszString)
     if (!CPLIsUTF8(pszString, -1) &&
          CSLTestBoolean(CPLGetConfigOption("OGR_FORCE_ASCII", "YES")))
     {
-        static int bFirstTime = TRUE;
+        static bool bFirstTime = true;
         if (bFirstTime)
         {
-            bFirstTime = FALSE;
+            bFirstTime = false;
             CPLError(CE_Warning, CPLE_AppDefined,
                     "%s is not a valid UTF-8 string. Forcing it to ASCII.\n"
                     "If you still want the original string and change the XML file encoding\n"
@@ -1108,23 +1477,23 @@ double OGRCallAtofOnShortString(const char* pszStr)
 /** Same contract as CPLAtof, except than it doesn't always call the
  *  system CPLAtof() that may be slow on some platforms. For simple but
  *  common strings, it'll use a faster implementation (up to 20x faster
- *  than CPLAtof() on MS runtime libraries) that has no garanty to return
+ *  than CPLAtof() on MS runtime libraries) that has no guaranty to return
  *  exactly the same floating point number.
  */
- 
+
 double OGRFastAtof(const char* pszStr)
 {
     double dfVal = 0;
     double dfSign = 1.0;
     const char* p = pszStr;
-    
+
     static const double adfTenPower[] =
     {
         1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10,
         1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20,
         1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29, 1e30, 1e31
     };
-        
+
     while(*p == ' ' || *p == '\t')
         p++;
 
@@ -1135,8 +1504,8 @@ double OGRFastAtof(const char* pszStr)
         dfSign = -1.0;
         p++;
     }
-    
-    while(TRUE)
+
+    while( true )
     {
         if (*p >= '0' && *p <= '9')
         {
@@ -1153,9 +1522,9 @@ double OGRFastAtof(const char* pszStr)
         else
             return dfSign * dfVal;
     }
-    
+
     unsigned int countFractionnal = 0;
-    while(TRUE)
+    while( true )
     {
         if (*p >= '0' && *p <= '9')
         {
@@ -1212,48 +1581,46 @@ OGRErr OGRCheckPermutation(int* panPermutation, int nSize)
 
 
 OGRErr OGRReadWKBGeometryType( unsigned char * pabyData, OGRwkbVariant eWkbVariant,
-                               OGRwkbGeometryType *peGeometryType, OGRBoolean *pbIs3D )
+                               OGRwkbGeometryType *peGeometryType )
 {
-    if ( ! (peGeometryType && pbIs3D) )
+    if ( !peGeometryType )
         return OGRERR_FAILURE;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Get the byte order byte.                                        */
 /* -------------------------------------------------------------------- */
-    OGRwkbByteOrder eByteOrder = DB2_V72_FIX_BYTE_ORDER((OGRwkbByteOrder) *pabyData);
-    if (!( eByteOrder == wkbXDR || eByteOrder == wkbNDR ))
+    int nByteOrder = DB2_V72_FIX_BYTE_ORDER(*pabyData);
+    if (!( nByteOrder == wkbXDR || nByteOrder == wkbNDR ))
         return OGRERR_CORRUPT_DATA;
+    OGRwkbByteOrder eByteOrder = (OGRwkbByteOrder) nByteOrder;
 
 /* -------------------------------------------------------------------- */
-/*      Get the geometry feature type.  For now we assume that          */
-/*      geometry type is between 0 and 255 so we only have to fetch     */
-/*      one byte.                                                       */
+/*      Get the geometry type.                                          */
 /* -------------------------------------------------------------------- */
     int bIs3D = FALSE;
+    int bIsMeasured = FALSE;
     int iRawType;
-    
+
     memcpy(&iRawType, pabyData + 1, 4);
     if ( OGR_SWAP(eByteOrder))
     {
         CPL_SWAP32PTR(&iRawType);
     }
-    
-    /* Old-style OGC z-bit is flipped? */
+
+    /* Test for M bit in PostGIS WKB, see ogrgeometry.cpp:4956 */
+    if ( 0x40000000 & iRawType )
+    {
+        iRawType &= ~0x40000000;
+        bIsMeasured = TRUE;
+    }
+    /* Old-style OGC z-bit is flipped? Tests also Z bit in PostGIS WKB */
     if ( wkb25DBitInternalUse & iRawType )
     {
         /* Clean off top 3 bytes */
         iRawType &= 0x000000FF;
-        bIs3D = TRUE;        
-    }
-    
-    /* ISO SQL/MM style Z types (between 1001 and 1012)? */
-    if ( iRawType >= 1001 && iRawType <= (int)wkbMultiSurfaceZ )
-    {
-        /* Remove the ISO padding */
-        iRawType -= 1000;
         bIs3D = TRUE;
     }
-    
+
     /*  ISO SQL/MM Part3 draft -> Deprecated */
     /* See http://jtc1sc32.org/doc/N1101-1150/32N1107-WD13249-3--spatial.pdf  */
     if (iRawType == 1000001)
@@ -1266,75 +1633,87 @@ OGRErr OGRReadWKBGeometryType( unsigned char * pabyData, OGRwkbVariant eWkbVaria
         iRawType = wkbMultiCurve;
     else if (iRawType == 1000005)
         iRawType = wkbMultiSurface;
+    else if (iRawType == 2000001)
+        iRawType = wkbPointZM;
+    else if (iRawType == 2000002)
+        iRawType = wkbLineStringZM;
+    else if (iRawType == 2000003)
+        iRawType = wkbCircularStringZM;
+    else if (iRawType == 2000004)
+        iRawType = wkbCompoundCurveZM;
+    else if (iRawType == 2000005)
+        iRawType = wkbPolygonZM;
+    else if (iRawType == 2000006)
+        iRawType = wkbCurvePolygonZM;
+    else if (iRawType == 2000007)
+        iRawType = wkbMultiPointZM;
+    else if (iRawType == 2000008)
+        iRawType = wkbMultiCurveZM;
+    else if (iRawType == 2000009)
+        iRawType = wkbMultiLineStringZM;
+    else if (iRawType == 2000010)
+        iRawType = wkbMultiSurfaceZM;
+    else if (iRawType == 2000011)
+        iRawType = wkbMultiPolygonZM;
+    else if (iRawType == 2000012)
+        iRawType = wkbGeometryCollectionZM;
     else if (iRawType == 3000001)
-    {
-        iRawType = wkbPoint;
-        bIs3D = TRUE;
-    }
+        iRawType = wkbPoint25D;
     else if (iRawType == 3000002)
-    {
-        iRawType = wkbLineString;
-        bIs3D = TRUE;
-    }
+        iRawType = wkbLineString25D;
     else if (iRawType == 3000003)
-    {
-        iRawType = wkbCircularString;
-        bIs3D = TRUE;
-    }
+        iRawType = wkbCircularStringZ;
     else if (iRawType == 3000004)
-    {
-        iRawType = wkbCompoundCurve;
-        bIs3D = TRUE;
-    }
+        iRawType = wkbCompoundCurveZ;
     else if (iRawType == 3000005)
-    {
-        iRawType = wkbPolygon;
-        bIs3D = TRUE;
-    }
+        iRawType = wkbPolygon25D;
     else if (iRawType == 3000006)
-    {
-        iRawType = wkbCurvePolygon;
-        bIs3D = TRUE;
-    }
+        iRawType = wkbCurvePolygonZ;
     else if (iRawType == 3000007)
-    {
-        iRawType = wkbMultiPoint;
-        bIs3D = TRUE;
-    }
+        iRawType = wkbMultiPoint25D;
     else if (iRawType == 3000008)
-    {
-        iRawType = wkbMultiCurve;
-        bIs3D = TRUE;
-    }
+        iRawType = wkbMultiCurveZ;
     else if (iRawType == 3000009)
-    {
-        iRawType = wkbMultiLineString;
-        bIs3D = TRUE;
-    }
+        iRawType = wkbMultiLineString25D;
     else if (iRawType == 3000010)
-    {
-        iRawType = wkbMultiSurface;
-        bIs3D = TRUE;
-    }
+        iRawType = wkbMultiSurfaceZ;
     else if (iRawType == 3000011)
-    {
-        iRawType = wkbMultiPolygon;
-        bIs3D = TRUE;
-    }
+        iRawType = wkbMultiPolygon25D;
     else if (iRawType == 3000012)
-    {
-        iRawType = wkbGeometryCollection;
-        bIs3D = TRUE;
-    }
-    
+        iRawType = wkbGeometryCollection25D;
+    else if (iRawType == 4000001)
+        iRawType = wkbPointM;
+    else if (iRawType == 4000002)
+        iRawType = wkbLineStringM;
+    else if (iRawType == 4000003)
+        iRawType = wkbCircularStringM;
+    else if (iRawType == 4000004)
+        iRawType = wkbCompoundCurveM;
+    else if (iRawType == 4000005)
+        iRawType = wkbPolygonM;
+    else if (iRawType == 4000006)
+        iRawType = wkbCurvePolygonM;
+    else if (iRawType == 4000007)
+        iRawType = wkbMultiPointM;
+    else if (iRawType == 4000008)
+        iRawType = wkbMultiCurveM;
+    else if (iRawType == 4000009)
+        iRawType = wkbMultiLineStringM;
+    else if (iRawType == 4000010)
+        iRawType = wkbMultiSurfaceM;
+    else if (iRawType == 4000011)
+        iRawType = wkbMultiPolygonM;
+    else if (iRawType == 4000012)
+        iRawType = wkbGeometryCollectionM;
+
     /* Sometimes the Z flag is in the 2nd byte? */
     if ( iRawType & (wkb25DBitInternalUse >> 16) )
     {
         /* Clean off top 3 bytes */
         iRawType &= 0x000000FF;
-        bIs3D = TRUE;        
+        bIs3D = TRUE;
     }
-    
+
     if( eWkbVariant == wkbVariantPostGIS1 )
     {
         if( iRawType == POSTGIS15_CURVEPOLYGON )
@@ -1345,17 +1724,33 @@ OGRErr OGRReadWKBGeometryType( unsigned char * pabyData, OGRwkbVariant eWkbVaria
             iRawType = wkbMultiSurface;
     }
 
-    /* Nothing left but (hopefully) basic 2D types */
+    if( bIs3D )
+    {
+        iRawType += 1000;
+    }
+    if( bIsMeasured )
+    {
+        iRawType += 2000;
+    }
 
-    /* What if what we have is still out of range? */
-    if ( iRawType < 1 || iRawType > (int)wkbMultiSurface )
+    /* ISO SQL/MM style types are between 1-16, 1001-1016, 2001-2016, and 3001-3016 */
+    if ( !((iRawType > 0 && iRawType <= 16) ||
+           (iRawType > 1000 && iRawType <= 1016) ||
+           (iRawType > 2000 && iRawType <= 2016) ||
+           (iRawType > 3000 && iRawType <= 3016)) )
     {
-        CPLError(CE_Failure, CPLE_NotSupported, "Unsupported WKB type %d", iRawType);            
+        CPLError(CE_Failure, CPLE_NotSupported, "Unsupported WKB type %d", iRawType);
         return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
     }
 
-    *pbIs3D = bIs3D;
+    /* convert to OGRwkbGeometryType value */
+    if( iRawType >= 1001 && iRawType <= 1007 )
+    {
+        iRawType -= 1000;
+        iRawType |= wkb25DBitInternalUse;
+    }
+
     *peGeometryType = (OGRwkbGeometryType)iRawType;
-    
+
     return OGRERR_NONE;
 }
diff --git a/ogr/osr_cs_wkt.c b/ogr/osr_cs_wkt.c
index f84d4bf..8a4fe29 100644
--- a/ogr/osr_cs_wkt.c
+++ b/ogr/osr_cs_wkt.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: osr_cs_wkt.c 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: osr_cs_wkt.c 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  CS WKT parser
@@ -30,7 +30,6 @@
 #include <stdio.h>
 #include <string.h>
 
-#define EQUALN_CST(x,y)  (strncmp(x, y, strlen(y)) == 0)
 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
 
@@ -46,9 +45,9 @@ void osr_cs_wkt_error( osr_cs_wkt_parse_context *context, const char *msg )
 {
     int i, n;
     char* szPtr;
-    sprintf(context->szErrorMsg,
-            "Parsing error : %s. Error occured around:\n", msg );
-    n = context->pszLastSuccess - context->pszInput;
+    snprintf( context->szErrorMsg, sizeof(context->szErrorMsg),
+             "Parsing error : %s. Error occurred around:\n", msg );
+    n = (int)(context->pszLastSuccess - context->pszInput);
 
     szPtr = context->szErrorMsg + strlen(context->szErrorMsg);
     for( i = MAX(0,n-40); i < n + 40 && context->pszInput[i]; i ++ )
@@ -119,7 +118,7 @@ int osr_cs_wkt_lex(CPL_UNUSED YYSTYPE* pNode,
     if( *pszInput == '\0' )
     {
         context->pszNext = pszInput;
-        return EOF; 
+        return EOF;
     }
 
 /* -------------------------------------------------------------------- */
@@ -127,7 +126,7 @@ int osr_cs_wkt_lex(CPL_UNUSED YYSTYPE* pNode,
 /* -------------------------------------------------------------------- */
     for(i = 0; i < sizeof(tokens) / sizeof(tokens[0]); i++)
     {
-        if( EQUALN_CST(pszInput, tokens[i].pszToken) )
+        if( STARTS_WITH_CI(pszInput, tokens[i].pszToken) )
         {
             context->pszNext = pszInput + strlen(tokens[i].pszToken);
             return tokens[i].nTokenVal;
@@ -145,7 +144,7 @@ int osr_cs_wkt_lex(CPL_UNUSED YYSTYPE* pNode,
         if(  *pszInput == '\0' )
         {
             context->pszNext = pszInput;
-            return EOF; 
+            return EOF;
         }
         context->pszNext = pszInput + 1;
         return T_STRING;
diff --git a/ogr/osr_cs_wkt.h b/ogr/osr_cs_wkt.h
index 4e3decc..d895c3c 100644
--- a/ogr/osr_cs_wkt.h
+++ b/ogr/osr_cs_wkt.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: osr_cs_wkt.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: osr_cs_wkt.h 31777 2015-11-26 14:14:41Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  CS WKT parser
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _OSR_CS_WKT_H_INCLUDED_
-#define _OSR_CS_WKT_H_INCLUDED_
+#ifndef OSR_CS_WKT_H_INCLUDED_
+#define OSR_CS_WKT_H_INCLUDED_
 
 #ifdef __cplusplus
 extern "C" {
@@ -52,4 +52,4 @@ int osr_cs_wkt_parse(osr_cs_wkt_parse_context *context);
 }
 #endif
 
-#endif /*  _OSR_CS_WKT_H_INCLUDED_ */
+#endif /*  OSR_CS_WKT_H_INCLUDED_ */
diff --git a/ogr/osr_cs_wkt_parser.c b/ogr/osr_cs_wkt_parser.c
index 68dacd3..b1cb423 100644
--- a/ogr/osr_cs_wkt_parser.c
+++ b/ogr/osr_cs_wkt_parser.c
@@ -71,7 +71,7 @@
 
 
 /******************************************************************************
- * $Id: osr_cs_wkt_parser.c 27975 2014-11-17 12:37:48Z rouault $
+ * $Id: osr_cs_wkt_parser.c 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  CS WKT parser grammar
@@ -926,7 +926,7 @@ static YYSIZE_T
 yystrlen (const char *yystr)
 {
   YYSIZE_T yylen;
-  for (yylen = 0; yystr[yylen]; yylen++)
+  for (yylen = 0; yystr != YY_NULL && yystr[yylen]; yylen++)
     continue;
   return yylen;
 }
@@ -1243,7 +1243,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
   yyssp++;
 
  yysetstate:
-  *yyssp = yystate;
+  *yyssp = (yytype_int16)yystate;
 
   if (yyss + yystacksize - 1 <= yyssp)
     {
@@ -1410,8 +1410,6 @@ yyreduce:
   YY_REDUCE_PRINT (yyn);
   switch (yyn)
     {
-      
-
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -1525,6 +1523,7 @@ yyerrlab:
 /*---------------------------------------------------.
 | yyerrorlab -- error raised explicitly by YYERROR.  |
 `---------------------------------------------------*/
+#if 0
 yyerrorlab:
 
   /* Pacify compilers like GCC when the user code never invokes
@@ -1545,6 +1544,7 @@ yyerrorlab:
 /*-------------------------------------------------------------.
 | yyerrlab1 -- common code for both syntax error and YYERROR.  |
 `-------------------------------------------------------------*/
+#endif
 yyerrlab1:
   yyerrstatus = 3;      /* Each real token shifted decrements this.  */
 
diff --git a/ogr/osr_tutorial.dox b/ogr/osr_tutorial.dox
index 4565afa..1df8380 100644
--- a/ogr/osr_tutorial.dox
+++ b/ogr/osr_tutorial.dox
@@ -4,7 +4,7 @@
 
 The OGRSpatialReference, and OGRCoordinateTransformation classes provide
 services to represent coordinate systems (projections and datums) and to
-transform between them.  These services are loosely modelled on the 
+transform between them.  These services are loosely modeled on the 
 OpenGIS Coordinate Transformations specification, and use the same 
 Well Known Text format for describing coordinate systems. 
 
@@ -255,10 +255,10 @@ if any of the points fail to transform.  The point array is
 left in an indeterminate state on error.
 
 Though not shown above, the coordinate transformation service can
-take 3D points, and will adjust elevations for elevation differents
+take 3D points, and will adjust elevations for elevation differences
 in spheroids, and datums.  At some point in the future shifts 
 between different vertical datums may also be applied.  If no Z is
-passed, it is assume that the point is on the geoide. 
+passed, it is assume that the point is on the geoid. 
 
 The following example shows how to conveniently create a lat/long coordinate
 system using the same geographic coordinate system as a projected coordinate
diff --git a/ogr/swq.cpp b/ogr/swq.cpp
index 3949526..cd7fa75 100644
--- a/ogr/swq.cpp
+++ b/ogr/swq.cpp
@@ -3,7 +3,7 @@
  * Component: OGDI Driver Support Library
  * Purpose: Generic SQL WHERE Expression Implementation.
  * Author: Frank Warmerdam <warmerdam at pobox.com>
- * 
+ *
  ******************************************************************************
  * Copyright (C) 2001 Information Interoperability Institute (3i)
  * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
@@ -12,8 +12,8 @@
  * its documentation for any purpose and without fee is hereby granted,
  * provided that the above copyright notice appear in all copies, that
  * both the copyright notice and this permission notice appear in
- * supporting documentation, and that the name of 3i not be used 
- * in advertising or publicity pertaining to distribution of the software 
+ * supporting documentation, and that the name of 3i not be used
+ * in advertising or publicity pertaining to distribution of the software
  * without specific, written prior permission.  3i makes no
  * representations about the suitability of this software for any purpose.
  * It is provided "as is" without express or implied warranty.
@@ -36,15 +36,15 @@
 void swqerror( swq_parse_context *context, const char *msg )
 {
     CPLString osMsg;
-    osMsg.Printf( "SQL Expression Parsing Error: %s. Occured around :\n", msg );
+    osMsg.Printf( "SQL Expression Parsing Error: %s. Occurred around :\n",
+                  msg );
 
-    int i;
-    int n = context->pszLastValid - context->pszInput;
+    int n = static_cast<int>(context->pszLastValid - context->pszInput);
 
-    for( i = MAX(0,n-40); i < n + 40 && context->pszInput[i] != '\0'; i ++ )
+    for( int i = MAX(0,n-40); i < n + 40 && context->pszInput[i] != '\0'; i ++ )
         osMsg += context->pszInput[i];
     osMsg += "\n";
-    for(i=0;i<MIN(n, 40);i++)
+    for( int i=0;i<MIN(n, 40);i++ )
         osMsg += " ";
     osMsg += "^";
 
@@ -86,7 +86,7 @@ int swqlex( YYSTYPE *ppNode, swq_parse_context *context )
     if( *pszInput == '\0' )
     {
         context->pszNext = pszInput;
-        return EOF; 
+        return EOF;
     }
 
 /* -------------------------------------------------------------------- */
@@ -97,7 +97,7 @@ int swqlex( YYSTYPE *ppNode, swq_parse_context *context )
         char *token;
         int i_token;
         char chQuote = *pszInput;
-        int bFoundEndQuote = FALSE;
+        bool bFoundEndQuote = false;
 
         int nRet = *pszInput == '"' ? SWQT_IDENTIFIER : SWQT_STRING;
 
@@ -117,10 +117,10 @@ int swqlex( YYSTYPE *ppNode, swq_parse_context *context )
             else if( *pszInput == chQuote )
             {
                 pszInput++;
-                bFoundEndQuote = TRUE;
+                bFoundEndQuote = true;
                 break;
             }
-            
+
             token[i_token++] = *(pszInput++);
         }
         token[i_token] = '\0';
@@ -175,8 +175,8 @@ int swqlex( YYSTYPE *ppNode, swq_parse_context *context )
 
         context->pszNext = pszNext;
 
-        if( strstr(osToken,".") 
-            || strstr(osToken,"e") 
+        if( strstr(osToken,".")
+            || strstr(osToken,"e")
             || strstr(osToken,"E") )
         {
             *ppNode = new swq_expr_node( CPLAtof(osToken) );
@@ -185,7 +185,7 @@ int swqlex( YYSTYPE *ppNode, swq_parse_context *context )
         else
         {
             GIntBig nVal = CPLAtoGIntBig(osToken);
-            if( (GIntBig)(int)nVal == nVal )
+            if( CPL_INT64_FITS_ON_INT32(nVal) )
                 *ppNode = new swq_expr_node( (int)nVal );
             else
                 *ppNode = new swq_expr_node( nVal );
@@ -205,7 +205,7 @@ int swqlex( YYSTYPE *ppNode, swq_parse_context *context )
         osToken += *pszInput;
 
         // collect text characters
-        while( isalnum( *pszNext ) || *pszNext == '_' 
+        while( isalnum( *pszNext ) || *pszNext == '_'
                || ((unsigned char) *pszNext) > 127 )
             osToken += *(pszNext++);
 
@@ -292,7 +292,7 @@ int swqlex( YYSTYPE *ppNode, swq_parse_context *context )
 /************************************************************************/
 
 const char *
-swq_select_summarize( swq_select *select_info, 
+swq_select_summarize( swq_select *select_info,
                       int dest_column, const char *value )
 
 {
@@ -317,14 +317,12 @@ swq_select_summarize( swq_select *select_info,
 /* -------------------------------------------------------------------- */
     if( select_info->column_summary == NULL )
     {
-        int i;
-
-        select_info->column_summary = (swq_summary *) 
+        select_info->column_summary = (swq_summary *)
             CPLMalloc(sizeof(swq_summary) * select_info->result_columns);
-        memset( select_info->column_summary, 0, 
+        memset( select_info->column_summary, 0,
                 sizeof(swq_summary) * select_info->result_columns );
 
-        for( i = 0; i < select_info->result_columns; i++ )
+        for( int i = 0; i < select_info->result_columns; i++ )
         {
             select_info->column_summary[i].min = 1e20;
             select_info->column_summary[i].max = -1e20;
@@ -337,7 +335,7 @@ swq_select_summarize( swq_select *select_info,
 /*      If distinct processing is on, process that now.                 */
 /* -------------------------------------------------------------------- */
     summary = select_info->column_summary + dest_column;
-    
+
     if( def->distinct_flag )
     {
         GIntBig  i;
@@ -355,16 +353,19 @@ swq_select_summarize( swq_select *select_info,
                      strcmp(value,summary->distinct_list[i]) == 0 )
                 break;
         }
-        
+
         if( i == summary->count )
         {
             char  **old_list = summary->distinct_list;
-            
-            summary->distinct_list = (char **) 
+
+            summary->distinct_list = (char **)
                 CPLMalloc(sizeof(char *) * (size_t)(summary->count+1));
-            memcpy( summary->distinct_list, old_list, 
-                    sizeof(char *) * (size_t)summary->count );
-            summary->distinct_list[(summary->count)++] = 
+            if( summary->count )
+            {
+                memcpy( summary->distinct_list, old_list,
+                        sizeof(char *) * (size_t)summary->count );
+            }
+            summary->distinct_list[(summary->count)++] =
                 (value != NULL) ? CPLStrdup( value ) : NULL;
 
             CPLFree(old_list);
@@ -479,8 +480,6 @@ swq_select_summarize( swq_select *select_info,
 
 static int FORCE_CDECL swq_compare_int( const void *item1, const void *item2 )
 {
-    GIntBig  v1, v2;
-
     const char* pszStr1 = *((const char **) item1);
     const char* pszStr2 = *((const char **) item2);
     if (pszStr1 == NULL)
@@ -488,8 +487,8 @@ static int FORCE_CDECL swq_compare_int( const void *item1, const void *item2 )
     else if (pszStr2 == NULL)
         return 1;
 
-    v1 = CPLAtoGIntBig(pszStr1);
-    v2 = CPLAtoGIntBig(pszStr2);
+    const GIntBig v1 = CPLAtoGIntBig(pszStr1);
+    const GIntBig v2 = CPLAtoGIntBig(pszStr2);
 
     if( v1 < v2 )
         return -1;
@@ -501,8 +500,6 @@ static int FORCE_CDECL swq_compare_int( const void *item1, const void *item2 )
 
 static int FORCE_CDECL swq_compare_real( const void *item1, const void *item2 )
 {
-    double  v1, v2;
-
     const char* pszStr1 = *((const char **) item1);
     const char* pszStr2 = *((const char **) item2);
     if (pszStr1 == NULL)
@@ -510,8 +507,8 @@ static int FORCE_CDECL swq_compare_real( const void *item1, const void *item2 )
     else if (pszStr2 == NULL)
         return 1;
 
-    v1 = CPLAtof(pszStr1);
-    v2 = CPLAtof(pszStr2);
+    const double v1 = CPLAtof(pszStr1);
+    const double v2 = CPLAtof(pszStr2);
 
     if( v1 < v2 )
         return -1;
@@ -547,14 +544,14 @@ const char *swq_select_finish_summarize( swq_select *select_info )
     GIntBig count = 0;
     char **distinct_list = NULL;
 
-    if( select_info->query_mode != SWQM_DISTINCT_LIST 
+    if( select_info->query_mode != SWQM_DISTINCT_LIST
         || select_info->order_specs == 0 )
         return NULL;
 
     if( select_info->order_specs > 1 )
         return "Can't ORDER BY a DISTINCT list by more than one key.";
 
-    if( select_info->order_defs[0].field_index != 
+    if( select_info->order_defs[0].field_index !=
         select_info->column_defs[0].field_index )
         return "Only selected DISTINCT field can be used for ORDER BY.";
 
@@ -579,12 +576,9 @@ const char *swq_select_finish_summarize( swq_select *select_info )
 /* -------------------------------------------------------------------- */
     if( !select_info->order_defs[0].ascending_flag )
     {
-        char *saved;
-        GIntBig i;
-
-        for( i = 0; i < count/2; i++ )
+        for( GIntBig i = 0; i < count/2; i++ )
         {
-            saved = distinct_list[i];
+            char *saved = distinct_list[i];
             distinct_list[i] = distinct_list[count-i-1];
             distinct_list[count-i-1] = saved;
         }
@@ -594,24 +588,14 @@ const char *swq_select_finish_summarize( swq_select *select_info )
 }
 
 /************************************************************************/
-/*                          swq_select_free()                           */
-/************************************************************************/
-
-void swq_select_free( swq_select *select_info )
-
-{
-    delete select_info;
-}
-
-/************************************************************************/
 /*                         swq_identify_field()                         */
 /************************************************************************/
-int swq_identify_field_internal( const char* table_name, const char *field_token, 
+int swq_identify_field_internal( const char* table_name, const char *field_token,
                                  swq_field_list *field_list,
                                  swq_field_type *this_type, int *table_id,
                                  int bOneMoreTimeOK );
 
-int swq_identify_field( const char* table_name, const char *field_token, 
+int swq_identify_field( const char* table_name, const char *field_token,
                                  swq_field_list *field_list,
                                  swq_field_type *this_type, int *table_id )
 
@@ -620,16 +604,16 @@ int swq_identify_field( const char* table_name, const char *field_token,
                                        this_type, table_id, TRUE);
 }
 
-int swq_identify_field_internal( const char* table_name, const char *field_token, 
+int swq_identify_field_internal( const char* table_name, const char *field_token,
                                  swq_field_list *field_list,
                                  swq_field_type *this_type, int *table_id,
                                  int bOneMoreTimeOK )
 
 {
-    int i;
-    if( table_name == NULL ) table_name = "";
+    if( table_name == NULL )
+        table_name = "";
 
-    int   tables_enabled;
+    int tables_enabled;
 
     if( field_list->table_count > 0 && field_list->table_ids != NULL )
         tables_enabled = TRUE;
@@ -639,7 +623,7 @@ int swq_identify_field_internal( const char* table_name, const char *field_token
 /* -------------------------------------------------------------------- */
 /*      Search for matching field.                                      */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < field_list->count; i++ )
+    for( int i = 0; i < field_list->count; i++ )
     {
         int  t_id = 0;
 
@@ -650,7 +634,7 @@ int swq_identify_field_internal( const char* table_name, const char *field_token
         if( tables_enabled )
         {
             t_id = field_list->table_ids[i];
-            if( table_name[0] != '\0' 
+            if( table_name[0] != '\0'
                 && !EQUAL(table_name,field_list->table_defs[t_id].table_alias))
                 continue;
 
@@ -668,7 +652,7 @@ int swq_identify_field_internal( const char* table_name, const char *field_token
             else
                 *this_type = SWQ_OTHER;
         }
-        
+
         if( table_id != NULL )
             *table_id = t_id;
 
@@ -689,6 +673,7 @@ int swq_identify_field_internal( const char* table_name, const char *field_token
 
             // Check there's no table called table_name, or a field called with
             // the aggregated name
+            int i;
             for( i = 0; i < field_list->count; i++ )
             {
                 if( tables_enabled )
@@ -701,7 +686,7 @@ int swq_identify_field_internal( const char* table_name, const char *field_token
             if( i == field_list->count )
             {
                 int ret = swq_identify_field_internal( NULL,
-                                            osAggregatedName, 
+                                            osAggregatedName,
                                             field_list,
                                             this_type, table_id, FALSE );
                 if( ret >= 0 )
@@ -716,7 +701,7 @@ int swq_identify_field_internal( const char* table_name, const char *field_token
         }
         else
         {
-            // If the fieldname is a.b (and there's no . in b), then 
+            // If the fieldname is a.b (and there's no . in b), then
             // it might be an error in providing it as being quoted where it should
             // not have been quoted.
             const char* pszDot = strchr(field_token, '.');
@@ -727,7 +712,7 @@ int swq_identify_field_internal( const char* table_name, const char *field_token
                 CPLString osFieldName(pszDot + 1);
 
                 int ret = swq_identify_field_internal( osTableName,
-                                            osFieldName, 
+                                            osFieldName,
                                             field_list,
                                             this_type, table_id, FALSE );
                 if( ret >= 0 )
@@ -760,8 +745,8 @@ int swq_identify_field_internal( const char* table_name, const char *field_token
 
 CPLErr swq_expr_compile( const char *where_clause,
                          int field_count,
-                         char **field_names, 
-                         swq_field_type *field_types, 
+                         char **field_names,
+                         swq_field_type *field_types,
                          int bCheck,
                          swq_custom_func_registrar* poCustomFuncRegistrar,
                          swq_expr_node **expr_out )
@@ -774,7 +759,7 @@ CPLErr swq_expr_compile( const char *where_clause,
     field_list.types = field_types;
     field_list.table_ids = NULL;
     field_list.ids = NULL;
-    
+
     field_list.table_count = 0;
     field_list.table_defs = NULL;
 
@@ -787,14 +772,13 @@ CPLErr swq_expr_compile( const char *where_clause,
 /*                         swq_expr_compile2()                          */
 /************************************************************************/
 
-CPLErr swq_expr_compile2( const char *where_clause, 
+CPLErr swq_expr_compile2( const char *where_clause,
                           swq_field_list *field_list,
                           int bCheck,
                           swq_custom_func_registrar* poCustomFuncRegistrar,
                           swq_expr_node **expr_out )
 
 {
-
     swq_parse_context context;
 
     context.pszInput = where_clause;
@@ -802,8 +786,8 @@ CPLErr swq_expr_compile2( const char *where_clause,
     context.pszLastValid = where_clause;
     context.nStartToken = SWQT_VALUE_START;
     context.bAcceptCustomFuncs = poCustomFuncRegistrar != NULL;
-    
-    if( swqparse( &context ) == 0 
+
+    if( swqparse( &context ) == 0
         && bCheck && context.poRoot->Check( field_list, FALSE, FALSE, poCustomFuncRegistrar ) != SWQ_ERROR )
     {
         *expr_out = context.poRoot;
@@ -822,7 +806,7 @@ CPLErr swq_expr_compile2( const char *where_clause,
 /*                        swq_is_reserved_keyword()                     */
 /************************************************************************/
 
-static const char* apszSQLReservedKeywords[] = {
+static const char* const apszSQLReservedKeywords[] = {
     "OR",
     "AND",
     "NOT",
diff --git a/ogr/swq.h b/ogr/swq.h
index d46a78a..e954865 100644
--- a/ogr/swq.h
+++ b/ogr/swq.h
@@ -3,7 +3,7 @@
  * Component: OGDI Driver Support Library
  * Purpose: Generic SQL WHERE Expression Evaluator Declarations.
  * Author: Frank Warmerdam <warmerdam at pobox.com>
- * 
+ *
  ******************************************************************************
  * Copyright (C) 2001 Information Interoperability Institute (3i)
  * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
@@ -11,24 +11,22 @@
  * its documentation for any purpose and without fee is hereby granted,
  * provided that the above copyright notice appear in all copies, that
  * both the copyright notice and this permission notice appear in
- * supporting documentation, and that the name of 3i not be used 
- * in advertising or publicity pertaining to distribution of the software 
+ * supporting documentation, and that the name of 3i not be used
+ * in advertising or publicity pertaining to distribution of the software
  * without specific, written prior permission.  3i makes no
  * representations about the suitability of this software for any purpose.
  * It is provided "as is" without express or implied warranty.
  ****************************************************************************/
 
-#ifndef _SWQ_H_INCLUDED_
-#define _SWQ_H_INCLUDED_
+#ifndef SWQ_H_INCLUDED_
+#define SWQ_H_INCLUDED_
 
 #include "cpl_conv.h"
 #include "cpl_string.h"
 #include "ogr_core.h"
 
-#if defined(_WIN32) && !defined(_WIN32_WCE)
+#if defined(_WIN32) && !defined(strcasecmp)
 #  define strcasecmp stricmp
-#elif defined(_WIN32_WCE)
-#  define strcasecmp _stricmp
 #endif
 
 typedef enum {
@@ -67,7 +65,7 @@ typedef enum {
     SWQ_INTEGER,
     SWQ_INTEGER64,
     SWQ_FLOAT,
-    SWQ_STRING, 
+    SWQ_STRING,
     SWQ_BOOLEAN,  // integer
     SWQ_DATE,     // string
     SWQ_TIME,     // string
@@ -82,7 +80,7 @@ typedef enum {
 
 typedef enum {
     SNT_CONSTANT,
-    SNT_COLUMN, 
+    SNT_COLUMN,
     SNT_OPERATION
 } swq_node_type;
 
@@ -105,12 +103,12 @@ class swq_expr_node {
 public:
     swq_expr_node();
 
-    swq_expr_node( const char * );
-    swq_expr_node( int );
-    swq_expr_node( GIntBig );
-    swq_expr_node( double );
-    swq_expr_node( OGRGeometry* );
-    swq_expr_node( swq_op );
+    explicit swq_expr_node( const char * );
+    explicit swq_expr_node( int );
+    explicit swq_expr_node( GIntBig );
+    explicit swq_expr_node( double );
+    explicit swq_expr_node( OGRGeometry* );
+    explicit swq_expr_node( swq_op );
 
     ~swq_expr_node();
 
@@ -121,7 +119,7 @@ public:
     swq_field_type Check( swq_field_list *, int bAllowFieldsInSecondaryTables,
                           int bAllowMismatchTypeOnFieldComparison,
                           swq_custom_func_registrar* poCustomFuncRegistrar );
-    swq_expr_node* Evaluate( swq_field_fetcher pfnFetcher, 
+    swq_expr_node* Evaluate( swq_field_fetcher pfnFetcher,
                              void *record );
     swq_expr_node* Clone();
 
@@ -147,12 +145,11 @@ public:
     GIntBig     int_value;
     double      float_value;
     OGRGeometry *geometry_value;
-    
+
     /* shared by SNT_COLUMN, SNT_CONSTANT and also possibly SNT_OPERATION when */
     /* nOperation == SWQ_CUSTOM_FUNC */
     char        *string_value; /* column name when SNT_COLUMN */
 
-
     static CPLString   QuoteIfNecessary( const CPLString &, char chQuote = '\'' );
     static CPLString   Quote( const CPLString &, char chQuote = '\'' );
 };
@@ -214,8 +211,8 @@ public:
 };
 
 /* Compile an SQL WHERE clause into an internal form.  The field_list is
-** the list of fields in the target 'table', used to render where into 
-** field numbers instead of names. 
+** the list of fields in the target 'table', used to render where into
+** field numbers instead of names.
 */
 int swqparse( swq_parse_context *context );
 int swqlex( swq_expr_node **ppNode, swq_parse_context *context );
@@ -225,7 +222,7 @@ int swq_identify_field( const char* table_name,
                         const char *token, swq_field_list *field_list,
                         swq_field_type *this_type, int *table_id );
 
-CPLErr swq_expr_compile( const char *where_clause, 
+CPLErr swq_expr_compile( const char *where_clause,
                          int field_count,
                          char **field_list,
                          swq_field_type *field_types,
@@ -233,8 +230,8 @@ CPLErr swq_expr_compile( const char *where_clause,
                          swq_custom_func_registrar* poCustomFuncRegistrar,
                          swq_expr_node **expr_root );
 
-CPLErr swq_expr_compile2( const char *where_clause, 
-                          swq_field_list *field_list, 
+CPLErr swq_expr_compile2( const char *where_clause,
+                          swq_field_list *field_list,
                           int bCheck,
                           swq_custom_func_registrar* poCustomFuncRegistrar,
                           swq_expr_node **expr_root );
@@ -288,7 +285,7 @@ typedef struct {
 
 typedef struct {
     GIntBig     count;
-    
+
     char        **distinct_list; /* items of the list can be NULL */
     double      sum;
     double      min;
@@ -381,12 +378,12 @@ CPLErr swq_select_parse( swq_select *select_info,
                          int parse_flags );
 
 const char *swq_select_finish_summarize( swq_select *select_info );
-const char *swq_select_summarize( swq_select *select_info, 
-                                  int dest_column, 
+const char *swq_select_summarize( swq_select *select_info,
+                                  int dest_column,
                                   const char *value );
 
 int swq_is_reserved_keyword(const char* pszStr);
 
 char* OGRHStoreGetValue(const char* pszHStore, const char* pszSearchedKey);
 
-#endif /* def _SWQ_H_INCLUDED_ */
+#endif /* def SWQ_H_INCLUDED_ */
diff --git a/ogr/swq_expr_node.cpp b/ogr/swq_expr_node.cpp
index c1fa528..ab47891 100644
--- a/ogr/swq_expr_node.cpp
+++ b/ogr/swq_expr_node.cpp
@@ -4,7 +4,7 @@
  * Purpose: Implementation of the swq_expr_node class used to represent a
  *          node in an SQL expression.
  * Author: Frank Warmerdam <warmerdam at pobox.com>
- * 
+ *
  ******************************************************************************
  * Copyright (C) 2010 Frank Warmerdam <warmerdam at pobox.com>
  * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
@@ -120,7 +120,7 @@ swq_expr_node::swq_expr_node( swq_op eOp )
     Initialize();
 
     eNodeType = SNT_OPERATION;
-    
+
     nOperation = (int) eOp;
     nSubExprCount = 0;
     papoSubExpr = NULL;
@@ -133,16 +133,21 @@ swq_expr_node::swq_expr_node( swq_op eOp )
 void swq_expr_node::Initialize()
 
 {
+    nOperation = 0;
+    nSubExprCount = 0;
+    papoSubExpr = NULL;
+
+    field_index = 0;
+    table_index = 0;
+    table_name = NULL;
     eNodeType = SNT_CONSTANT;
     field_type = SWQ_INTEGER;
-    int_value = 0;
 
     is_null = FALSE;
-    table_name = NULL;
     string_value = NULL;
+    int_value = 0;
+    float_value = 0;
     geometry_value = NULL;
-    papoSubExpr = NULL;
-    nSubExprCount = 0;
 }
 
 /************************************************************************/
@@ -155,8 +160,7 @@ swq_expr_node::~swq_expr_node()
     CPLFree( table_name );
     CPLFree( string_value );
 
-    int i;
-    for( i = 0; i < nSubExprCount; i++ )
+    for( int i = 0; i < nSubExprCount; i++ )
         delete papoSubExpr[i];
     CPLFree( papoSubExpr );
     delete geometry_value;
@@ -170,9 +174,9 @@ void swq_expr_node::PushSubExpression( swq_expr_node *child )
 
 {
     nSubExprCount++;
-    papoSubExpr = (swq_expr_node **) 
+    papoSubExpr = (swq_expr_node **)
         CPLRealloc( papoSubExpr, sizeof(void*) * nSubExprCount );
-    
+
     papoSubExpr[nSubExprCount-1] = child;
 }
 
@@ -183,8 +187,7 @@ void swq_expr_node::PushSubExpression( swq_expr_node *child )
 void swq_expr_node::ReverseSubExpressions()
 
 {
-    int i;
-    for( i = 0; i < nSubExprCount / 2; i++ )
+    for( int i = 0; i < nSubExprCount / 2; i++ )
     {
         swq_expr_node *temp;
 
@@ -218,18 +221,18 @@ swq_field_type swq_expr_node::Check( swq_field_list *poFieldList,
 /* -------------------------------------------------------------------- */
     if( eNodeType == SNT_COLUMN && field_index == -1 )
     {
-        field_index = 
+        field_index =
             swq_identify_field( table_name, string_value, poFieldList,
                                 &field_type, &table_index );
-        
+
         if( field_index < 0 )
         {
             if( table_name )
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                       "\"%s\".\"%s\" not recognised as an available field.",
                       table_name, string_value );
             else
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                       "\"%s\" not recognised as an available field.",
                       string_value );
 
@@ -244,14 +247,14 @@ swq_field_type swq_expr_node::Check( swq_field_list *poFieldList,
             return SWQ_ERROR;
         }
     }
-    
+
     if( eNodeType == SNT_COLUMN )
         return field_type;
-    
+
 /* -------------------------------------------------------------------- */
 /*      We are dealing with an operation - fetch the definition.        */
 /* -------------------------------------------------------------------- */
-    const swq_operation *poOp = 
+    const swq_operation *poOp =
         (nOperation == SWQ_CUSTOM_FUNC && poCustomFuncRegistrar != NULL ) ?
             poCustomFuncRegistrar->GetOperator(string_value) :
             swq_op_registrar::GetOperator((swq_op)nOperation);
@@ -272,16 +275,14 @@ swq_field_type swq_expr_node::Check( swq_field_list *poFieldList,
 /* -------------------------------------------------------------------- */
 /*      Check subexpressions first.                                     */
 /* -------------------------------------------------------------------- */
-    int i;
-
-    for( i = 0; i < nSubExprCount; i++ )
+    for( int i = 0; i < nSubExprCount; i++ )
     {
         if( papoSubExpr[i]->Check(poFieldList, bAllowFieldsInSecondaryTables,
                                   bAllowMismatchTypeOnFieldComparison,
                                   poCustomFuncRegistrar) == SWQ_ERROR )
             return SWQ_ERROR;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Check this node.                                                */
 /* -------------------------------------------------------------------- */
@@ -336,7 +337,7 @@ void swq_expr_node::Dump( FILE * fp, int depth )
 
     CPLAssert( eNodeType == SNT_OPERATION );
 
-    const swq_operation *op_def = 
+    const swq_operation *op_def =
         swq_op_registrar::GetOperator( (swq_op) nOperation );
     if( op_def )
         fprintf( fp, "%s%s\n", spaces, op_def->pszName );
@@ -347,7 +348,7 @@ void swq_expr_node::Dump( FILE * fp, int depth )
         papoSubExpr[i]->Dump( fp, depth+1 );
 }
 
-        
+
 /************************************************************************/
 /*                       QuoteIfNecessary()                             */
 /*                                                                      */
@@ -375,7 +376,7 @@ CPLString swq_expr_node::QuoteIfNecessary( const CPLString &osExpr, char chQuote
     {
         return Quote(osExpr, chQuote);
     }
-    
+
     return osExpr;
 }
 
@@ -389,11 +390,10 @@ CPLString swq_expr_node::Quote( const CPLString &osTarget, char chQuote )
 
 {
     CPLString osNew;
-    int i;
 
     osNew += chQuote;
 
-    for( i = 0; i < (int) osTarget.size(); i++ )
+    for( int i = 0; i < (int) osTarget.size(); i++ )
     {
         if( osTarget[i] == chQuote )
         {
@@ -437,11 +437,11 @@ char *swq_expr_node::Unparse( swq_field_list *field_list, char chColumnQuote )
                 strchr(osExpr, 'E') == NULL)
                 osExpr += '.';
         }
-        else 
+        else
         {
             osExpr = Quote( string_value );
         }
-        
+
         return CPLStrdup(osExpr);
     }
 
@@ -460,8 +460,8 @@ char *swq_expr_node::Unparse( swq_field_list *field_list, char chColumnQuote )
                 osExpr.Printf( "%s",
                                QuoteIfNecessary(string_value, chColumnQuote).c_str() );
         }
-        else if( field_index != -1 
-            && table_index < field_list->table_count 
+        else if( field_index != -1
+            && table_index < field_list->table_count
             && table_index > 0 )
         {
             for(int i = 0; i < field_list->count; i++ )
@@ -502,17 +502,16 @@ char *swq_expr_node::Unparse( swq_field_list *field_list, char chColumnQuote )
 /*      Operation - start by unparsing all the subexpressions.          */
 /* -------------------------------------------------------------------- */
     std::vector<char*> apszSubExpr;
-    int i;
 
-    for( i = 0; i < nSubExprCount; i++ )
+    for( int i = 0; i < nSubExprCount; i++ )
         apszSubExpr.push_back( papoSubExpr[i]->Unparse(field_list, chColumnQuote) );
 
     osExpr = UnparseOperationFromUnparsedSubExpr(&apszSubExpr[0]);
-    
+
 /* -------------------------------------------------------------------- */
 /*      cleanup subexpressions.                                         */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < nSubExprCount; i++ )
+    for( int i = 0; i < nSubExprCount; i++ )
         CPLFree( apszSubExpr[i] );
 
     return CPLStrdup( osExpr.c_str() );
@@ -524,13 +523,12 @@ char *swq_expr_node::Unparse( swq_field_list *field_list, char chColumnQuote )
 
 CPLString swq_expr_node::UnparseOperationFromUnparsedSubExpr(char** apszSubExpr)
 {
-    int i;
     CPLString osExpr;
 
 /* -------------------------------------------------------------------- */
 /*      Put things together in a fashion depending on the operator.     */
 /* -------------------------------------------------------------------- */
-    const swq_operation *poOp = 
+    const swq_operation *poOp =
         swq_op_registrar::GetOperator( (swq_op) nOperation );
 
     if( poOp == NULL && nOperation != SWQ_CUSTOM_FUNC )
@@ -590,15 +588,15 @@ CPLString swq_expr_node::UnparseOperationFromUnparsedSubExpr(char** apszSubExpr)
         CPLAssert( nSubExprCount == 1 );
         osExpr.Printf( "NOT (%s)", apszSubExpr[0] );
         break;
-        
+
       case SWQ_ISNULL:
         CPLAssert( nSubExprCount == 1 );
         osExpr.Printf( "%s IS NULL", apszSubExpr[0] );
         break;
-        
+
       case SWQ_IN:
         osExpr.Printf( "%s IN (", apszSubExpr[0] );
-        for( i = 1; i < nSubExprCount; i++ )
+        for( int i = 1; i < nSubExprCount; i++ )
         {
             if( i > 1 )
                 osExpr += ",";
@@ -620,7 +618,7 @@ CPLString swq_expr_node::UnparseOperationFromUnparsedSubExpr(char** apszSubExpr)
 
       case SWQ_CAST:
         osExpr = "CAST(";
-        for( i = 0; i < nSubExprCount; i++ )
+        for( int i = 0; i < nSubExprCount; i++ )
         {
             if( i == 1 )
                 osExpr += " AS ";
@@ -651,7 +649,7 @@ CPLString swq_expr_node::UnparseOperationFromUnparsedSubExpr(char** apszSubExpr)
             osExpr.Printf( "%s(", poOp->pszName );
         else
             osExpr.Printf( "%s(", string_value );
-        for( i = 0; i < nSubExprCount; i++ )
+        for( int i = 0; i < nSubExprCount; i++ )
         {
             if( i > 0 )
                 osExpr += ",";
@@ -662,7 +660,7 @@ CPLString swq_expr_node::UnparseOperationFromUnparsedSubExpr(char** apszSubExpr)
         osExpr += ")";
         break;
     }
-    
+
     return osExpr;
 }
 
@@ -680,7 +678,7 @@ swq_expr_node *swq_expr_node::Clone()
     {
         poRetNode->nOperation = nOperation;
         poRetNode->nSubExprCount = nSubExprCount;
-        poRetNode->papoSubExpr = (swq_expr_node **) 
+        poRetNode->papoSubExpr = (swq_expr_node **)
                 CPLMalloc( sizeof(void*) * nSubExprCount );
         for(int i=0;i<nSubExprCount;i++)
             poRetNode->papoSubExpr[i] = papoSubExpr[i]->Clone();
@@ -737,9 +735,9 @@ swq_expr_node *swq_expr_node::Evaluate( swq_field_fetcher pfnFetcher,
 /* -------------------------------------------------------------------- */
     std::vector<swq_expr_node*> apoValues;
     std::vector<int> anValueNeedsFree;
-    int i, bError = FALSE;
+    bool bError = false;
 
-    for( i = 0; i < nSubExprCount && !bError; i++ )
+    for( int i = 0; i < nSubExprCount && !bError; i++ )
     {
         if( papoSubExpr[i]->eNodeType == SNT_CONSTANT )
         {
@@ -751,7 +749,7 @@ swq_expr_node *swq_expr_node::Evaluate( swq_field_fetcher pfnFetcher,
         {
             swq_expr_node* poSubExprVal = papoSubExpr[i]->Evaluate(pfnFetcher,pRecord);
             if( poSubExprVal == NULL )
-                bError = TRUE;
+                bError = true;
             else
             {
                 apoValues.push_back(poSubExprVal);
@@ -765,7 +763,7 @@ swq_expr_node *swq_expr_node::Evaluate( swq_field_fetcher pfnFetcher,
 /* -------------------------------------------------------------------- */
     if( !bError )
     {
-        const swq_operation *poOp = 
+        const swq_operation *poOp =
             swq_op_registrar::GetOperator( (swq_op) nOperation );
         if( poOp == NULL )
         {
@@ -786,7 +784,7 @@ swq_expr_node *swq_expr_node::Evaluate( swq_field_fetcher pfnFetcher,
 /* -------------------------------------------------------------------- */
 /*      Cleanup                                                         */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < (int) apoValues.size(); i++ )
+    for( int i = 0; i < (int) apoValues.size(); i++ )
     {
         if( anValueNeedsFree[i] )
             delete apoValues[i];
@@ -817,7 +815,7 @@ void swq_expr_node::ReplaceBetweenByGEAndLERecurse()
     swq_expr_node* poExpr0 = papoSubExpr[0];
     swq_expr_node* poExpr1 = papoSubExpr[1];
     swq_expr_node* poExpr2 = papoSubExpr[2];
-    
+
     nSubExprCount = 2;
     nOperation = SWQ_AND;
     papoSubExpr[0] = new swq_expr_node(SWQ_GE);
diff --git a/ogr/swq_op_general.cpp b/ogr/swq_op_general.cpp
index bef9f5e..4e809da 100644
--- a/ogr/swq_op_general.cpp
+++ b/ogr/swq_op_general.cpp
@@ -1,11 +1,11 @@
 /******************************************************************************
  *
  * Component: OGR SQL Engine
- * Purpose: Implementation of SWQGeneralEvaluator and SWQGeneralChecker 
+ * Purpose: Implementation of SWQGeneralEvaluator and SWQGeneralChecker
  *          functions used to represent functions during evaluation and
  *          parsing.
  * Author: Frank Warmerdam <warmerdam at pobox.com>
- * 
+ *
  ******************************************************************************
  * Copyright (C) 2010 Frank Warmerdam <warmerdam at pobox.com>
  * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
@@ -39,7 +39,7 @@
 /*      Does input match pattern?                                       */
 /************************************************************************/
 
-int swq_test_like( const char *input, const char *pattern, char chEscape )
+static int swq_test_like( const char *input, const char *pattern, char chEscape )
 
 {
     if( input == NULL || pattern == NULL )
@@ -139,7 +139,7 @@ static char* OGRHStoreGetNextString(char* pszIter,
                                     int bIsKey)
 {
     char ch;
-    int bInString = FALSE;
+    bool bInString = false;
     char* pszOut = NULL;
     *ppszOut = NULL;
     for( ; (ch = *pszIter) != '\0'; pszIter ++ )
@@ -189,7 +189,7 @@ static char* OGRHStoreGetNextString(char* pszIter,
             else if( ch == '"' )
             {
                 pszOut = *ppszOut = pszIter + 1;
-                bInString = TRUE;
+                bInString = true;
             }
             else if( pszOut == NULL )
                 pszOut = *ppszOut = pszIter;
@@ -219,7 +219,7 @@ char* OGRHStoreGetValue(const char* pszHStore, const char* pszSearchedKey)
     char* pszHStoreIter = pszHStoreDup;
     char* pszRet = NULL;
 
-    while( TRUE )
+    while( true )
     {
         char* pszKey, *pszValue;
         pszHStoreIter = OGRHStoreGetNextKeyValue(pszHStoreIter, &pszKey, &pszValue);
@@ -254,10 +254,9 @@ swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
 /* -------------------------------------------------------------------- */
 /*      Floating point operations.                                      */
 /* -------------------------------------------------------------------- */
-    if( sub_node_values[0]->field_type == SWQ_FLOAT 
-        || (node->nSubExprCount > 1 
+    if( sub_node_values[0]->field_type == SWQ_FLOAT
+        || (node->nSubExprCount > 1
             && sub_node_values[1]->field_type == SWQ_FLOAT) )
-            
     {
         poRet = new swq_expr_node(0);
         poRet->field_type = node->field_type;
@@ -300,32 +299,32 @@ swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
         switch( (swq_op) node->nOperation )
         {
           case SWQ_EQ:
-            poRet->int_value = sub_node_values[0]->float_value 
+            poRet->int_value = sub_node_values[0]->float_value
                 == sub_node_values[1]->float_value;
             break;
 
           case SWQ_NE:
-            poRet->int_value = sub_node_values[0]->float_value 
+            poRet->int_value = sub_node_values[0]->float_value
                 != sub_node_values[1]->float_value;
             break;
 
           case SWQ_GT:
-            poRet->int_value = sub_node_values[0]->float_value 
+            poRet->int_value = sub_node_values[0]->float_value
                 > sub_node_values[1]->float_value;
             break;
 
           case SWQ_LT:
-            poRet->int_value = sub_node_values[0]->float_value 
+            poRet->int_value = sub_node_values[0]->float_value
                 < sub_node_values[1]->float_value;
             break;
 
           case SWQ_GE:
-            poRet->int_value = sub_node_values[0]->float_value 
+            poRet->int_value = sub_node_values[0]->float_value
                 >= sub_node_values[1]->float_value;
             break;
 
           case SWQ_LE:
-            poRet->int_value = sub_node_values[0]->float_value 
+            poRet->int_value = sub_node_values[0]->float_value
                 <= sub_node_values[1]->float_value;
             break;
 
@@ -335,7 +334,7 @@ swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
               poRet->int_value = 0;
               for( i = 1; i < node->nSubExprCount; i++ )
               {
-                  if( sub_node_values[0]->float_value 
+                  if( sub_node_values[0]->float_value
                       == sub_node_values[i]->float_value )
                   {
                       poRet->int_value = 1;
@@ -357,28 +356,28 @@ swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
             break;
 
           case SWQ_ADD:
-            poRet->float_value = sub_node_values[0]->float_value 
+            poRet->float_value = sub_node_values[0]->float_value
                 + sub_node_values[1]->float_value;
             break;
-            
+
           case SWQ_SUBTRACT:
-            poRet->float_value = sub_node_values[0]->float_value 
+            poRet->float_value = sub_node_values[0]->float_value
                 - sub_node_values[1]->float_value;
             break;
-            
+
           case SWQ_MULTIPLY:
-            poRet->float_value = sub_node_values[0]->float_value 
+            poRet->float_value = sub_node_values[0]->float_value
                 * sub_node_values[1]->float_value;
             break;
-            
+
           case SWQ_DIVIDE:
             if( sub_node_values[1]->float_value == 0 )
                 poRet->float_value = INT_MAX;
             else
-                poRet->float_value = sub_node_values[0]->float_value 
+                poRet->float_value = sub_node_values[0]->float_value
                     / sub_node_values[1]->float_value;
             break;
-            
+
           case SWQ_MODULUS:
           {
             GIntBig nRight = (GIntBig) sub_node_values[1]->float_value;
@@ -431,56 +430,55 @@ swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
         switch( (swq_op) node->nOperation )
         {
           case SWQ_AND:
-            poRet->int_value = sub_node_values[0]->int_value 
+            poRet->int_value = sub_node_values[0]->int_value
                 && sub_node_values[1]->int_value;
             break;
-            
+
           case SWQ_OR:
-            poRet->int_value = sub_node_values[0]->int_value 
+            poRet->int_value = sub_node_values[0]->int_value
                 || sub_node_values[1]->int_value;
             break;
-            
+
           case SWQ_NOT:
             poRet->int_value = !sub_node_values[0]->int_value;
             break;
-            
+
           case SWQ_EQ:
-            poRet->int_value = sub_node_values[0]->int_value 
+            poRet->int_value = sub_node_values[0]->int_value
                 == sub_node_values[1]->int_value;
             break;
 
           case SWQ_NE:
-            poRet->int_value = sub_node_values[0]->int_value 
+            poRet->int_value = sub_node_values[0]->int_value
                 != sub_node_values[1]->int_value;
             break;
 
           case SWQ_GT:
-            poRet->int_value = sub_node_values[0]->int_value 
+            poRet->int_value = sub_node_values[0]->int_value
                 > sub_node_values[1]->int_value;
             break;
 
           case SWQ_LT:
-            poRet->int_value = sub_node_values[0]->int_value 
+            poRet->int_value = sub_node_values[0]->int_value
                 < sub_node_values[1]->int_value;
             break;
 
           case SWQ_GE:
-            poRet->int_value = sub_node_values[0]->int_value 
+            poRet->int_value = sub_node_values[0]->int_value
                 >= sub_node_values[1]->int_value;
             break;
 
           case SWQ_LE:
-            poRet->int_value = sub_node_values[0]->int_value 
+            poRet->int_value = sub_node_values[0]->int_value
                 <= sub_node_values[1]->int_value;
             break;
 
           case SWQ_IN:
           {
-              int i;
               poRet->int_value = 0;
-              for( i = 1; i < node->nSubExprCount; i++ )
+              for( int i = 1; i < node->nSubExprCount; i++ )
               {
-                  if( sub_node_values[0]->int_value 
+                  if( sub_node_values[0]->int_value
                       == sub_node_values[i]->int_value )
                   {
                       poRet->int_value = 1;
@@ -502,28 +500,28 @@ swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
             break;
 
           case SWQ_ADD:
-            poRet->int_value = sub_node_values[0]->int_value 
+            poRet->int_value = sub_node_values[0]->int_value
                 + sub_node_values[1]->int_value;
             break;
-            
+
           case SWQ_SUBTRACT:
-            poRet->int_value = sub_node_values[0]->int_value 
+            poRet->int_value = sub_node_values[0]->int_value
                 - sub_node_values[1]->int_value;
             break;
-            
+
           case SWQ_MULTIPLY:
-            poRet->int_value = sub_node_values[0]->int_value 
+            poRet->int_value = sub_node_values[0]->int_value
                 * sub_node_values[1]->int_value;
             break;
-            
+
           case SWQ_DIVIDE:
             if( sub_node_values[1]->int_value == 0 )
                 poRet->int_value = INT_MAX;
             else
-                poRet->int_value = sub_node_values[0]->int_value 
+                poRet->int_value = sub_node_values[0]->int_value
                     / sub_node_values[1]->int_value;
             break;
-            
+
           case SWQ_MODULUS:
             if( sub_node_values[1]->int_value == 0 )
                 poRet->int_value = INT_MAX;
@@ -531,7 +529,7 @@ swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
                 poRet->int_value = sub_node_values[0]->int_value
                     % sub_node_values[1]->int_value;
             break;
-            
+
           default:
             CPLAssert( FALSE );
             delete poRet;
@@ -584,7 +582,7 @@ swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
                 (strcmp(sub_node_values[0]->string_value + strlen(sub_node_values[0]->string_value)-3, "+00") == 0 &&
                  sub_node_values[1]->string_value[strlen(sub_node_values[1]->string_value)-3] == ':') )
             {
-                poRet->int_value = 
+                poRet->int_value =
                     EQUALN(sub_node_values[0]->string_value,
                            sub_node_values[1]->string_value,
                            strlen(sub_node_values[1]->string_value));
@@ -598,14 +596,14 @@ swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
                      (sub_node_values[0]->string_value[strlen(sub_node_values[0]->string_value)-3] == ':')  &&
                       strcmp(sub_node_values[1]->string_value + strlen(sub_node_values[1]->string_value)-3, "+00") == 0)
             {
-                poRet->int_value = 
+                poRet->int_value =
                     EQUALN(sub_node_values[0]->string_value,
                            sub_node_values[1]->string_value,
                            strlen(sub_node_values[0]->string_value));
             }
             else
             {
-                poRet->int_value = 
+                poRet->int_value =
                     strcasecmp(sub_node_values[0]->string_value,
                             sub_node_values[1]->string_value) == 0;
             }
@@ -613,31 +611,31 @@ swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
           }
 
           case SWQ_NE:
-            poRet->int_value = 
+            poRet->int_value =
                 strcasecmp(sub_node_values[0]->string_value,
                            sub_node_values[1]->string_value) != 0;
             break;
 
           case SWQ_GT:
-            poRet->int_value = 
+            poRet->int_value =
                 strcasecmp(sub_node_values[0]->string_value,
                            sub_node_values[1]->string_value) > 0;
             break;
 
           case SWQ_LT:
-            poRet->int_value = 
+            poRet->int_value =
                 strcasecmp(sub_node_values[0]->string_value,
                            sub_node_values[1]->string_value) < 0;
             break;
 
           case SWQ_GE:
-            poRet->int_value = 
+            poRet->int_value =
                 strcasecmp(sub_node_values[0]->string_value,
                            sub_node_values[1]->string_value) >= 0;
             break;
 
           case SWQ_LE:
-            poRet->int_value = 
+            poRet->int_value =
                 strcasecmp(sub_node_values[0]->string_value,
                            sub_node_values[1]->string_value) <= 0;
             break;
@@ -685,16 +683,15 @@ swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
           case SWQ_ADD:
           {
               CPLString osResult = sub_node_values[0]->string_value;
-              int i;
 
-              for( i = 1; i < node->nSubExprCount; i++ )
+              for( int i = 1; i < node->nSubExprCount; i++ )
                   osResult += sub_node_values[i]->string_value;
-              
+
               poRet->string_value = CPLStrdup(osResult);
               poRet->is_null = sub_node_values[0]->is_null;
               break;
           }
-            
+
           case SWQ_SUBSTR:
           {
               int nOffset, nSize;
@@ -703,7 +700,7 @@ swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
               if( SWQ_IS_INTEGER(sub_node_values[1]->field_type) )
                   nOffset = (int)sub_node_values[1]->int_value;
               else if( sub_node_values[1]->field_type == SWQ_FLOAT )
-                  nOffset = (int) sub_node_values[1]->float_value; 
+                  nOffset = (int) sub_node_values[1]->float_value;
               else
                   nOffset = 0;
 
@@ -712,7 +709,7 @@ swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
               else if( SWQ_IS_INTEGER(sub_node_values[2]->field_type) )
                   nSize = (int)sub_node_values[2]->int_value;
               else if( sub_node_values[2]->field_type == SWQ_FLOAT )
-                  nSize = (int) sub_node_values[2]->float_value; 
+                  nSize = (int) sub_node_values[2]->float_value;
               else
                   nSize = 0;
 
@@ -744,7 +741,7 @@ swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
               CPLString osResult = pszSrcStr + nOffset;
               if( (int)osResult.size() > nSize )
                   osResult.resize( nSize );
-              
+
               poRet->string_value = CPLStrdup(osResult);
               poRet->is_null = sub_node_values[0]->is_null;
               break;
@@ -782,12 +779,11 @@ static void SWQAutoPromoteIntegerToInteger64OrFloat( swq_expr_node *poNode )
         return;
 
     swq_field_type eArgType = poNode->papoSubExpr[0]->field_type;
-    int i;
 
     // We allow mixes of integer, integer64 and float, and string and dates.
-    // When encountered, we promote integers/integer64 to floats, 
+    // When encountered, we promote integers/integer64 to floats,
     // integer to integer64 and strings to dates.  We do that now.
-    for( i = 1; i < poNode->nSubExprCount; i++ )
+    for( int i = 1; i < poNode->nSubExprCount; i++ )
     {
         swq_expr_node *poSubNode = poNode->papoSubExpr[i];
         if( SWQ_IS_INTEGER(eArgType)
@@ -797,8 +793,8 @@ static void SWQAutoPromoteIntegerToInteger64OrFloat( swq_expr_node *poNode )
                  && poSubNode->field_type == SWQ_INTEGER64 )
             eArgType = SWQ_INTEGER64;
     }
-    
-    for( i = 0; i < poNode->nSubExprCount; i++ )
+
+    for( int i = 0; i < poNode->nSubExprCount; i++ )
     {
         swq_expr_node *poSubNode = poNode->papoSubExpr[i];
 
@@ -832,12 +828,11 @@ static void SWQAutoPromoteStringToDateTime( swq_expr_node *poNode )
         return;
 
     swq_field_type eArgType = poNode->papoSubExpr[0]->field_type;
-    int i;
 
     // We allow mixes of integer and float, and string and dates.
     // When encountered, we promote integers to floats, and strings to
     // dates.  We do that now.
-    for( i = 1; i < poNode->nSubExprCount; i++ )
+    for( int i = 1; i < poNode->nSubExprCount; i++ )
     {
         swq_expr_node *poSubNode = poNode->papoSubExpr[i];
 
@@ -847,13 +842,13 @@ static void SWQAutoPromoteStringToDateTime( swq_expr_node *poNode )
                 || poSubNode->field_type == SWQ_TIMESTAMP) )
             eArgType = SWQ_TIMESTAMP;
     }
-    
-    for( i = 0; i < poNode->nSubExprCount; i++ )
+
+    for( int i = 0; i < poNode->nSubExprCount; i++ )
     {
         swq_expr_node *poSubNode = poNode->papoSubExpr[i];
 
         if( eArgType == SWQ_TIMESTAMP
-            && (poSubNode->field_type == SWQ_STRING 
+            && (poSubNode->field_type == SWQ_STRING
                 || poSubNode->field_type == SWQ_DATE
                 || poSubNode->field_type == SWQ_TIME) )
         {
@@ -879,9 +874,8 @@ static void SWQAutoConvertStringToNumeric( swq_expr_node *poNode )
         return;
 
     swq_field_type eArgType = poNode->papoSubExpr[0]->field_type;
-    int i;
 
-    for( i = 1; i < poNode->nSubExprCount; i++ )
+    for( int i = 1; i < poNode->nSubExprCount; i++ )
     {
         swq_expr_node *poSubNode = poNode->papoSubExpr[i];
 
@@ -896,8 +890,8 @@ static void SWQAutoConvertStringToNumeric( swq_expr_node *poNode )
             break;
         }
     }
-    
-    for( i = 0; i < poNode->nSubExprCount; i++ )
+
+    for( int i = 0; i < poNode->nSubExprCount; i++ )
     {
         swq_expr_node *poSubNode = poNode->papoSubExpr[i];
 
@@ -929,18 +923,18 @@ static void SWQAutoConvertStringToNumeric( swq_expr_node *poNode )
 /*                   SWQCheckSubExprAreNotGeometries()                  */
 /************************************************************************/
 
-static int SWQCheckSubExprAreNotGeometries( swq_expr_node *poNode )
+static bool SWQCheckSubExprAreNotGeometries( swq_expr_node *poNode )
 {
     for( int i = 0; i < poNode->nSubExprCount; i++ )
     {
         if( poNode->papoSubExpr[i]->field_type == SWQ_GEOMETRY )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                         "Cannot use geometry field in this operation." );
-            return FALSE;
+            return false;
         }
     }
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -954,10 +948,10 @@ static int SWQCheckSubExprAreNotGeometries( swq_expr_node *poNode )
 swq_field_type SWQGeneralChecker( swq_expr_node *poNode,
                                   int bAllowMismatchTypeOnFieldComparison  )
 
-{									
+{
     swq_field_type eRetType = SWQ_ERROR;
     swq_field_type eArgType = SWQ_OTHER;
-    int nArgCount = -1;
+    // int nArgCount = -1;
 
     switch( (swq_op) poNode->nOperation )
     {
@@ -1045,17 +1039,17 @@ swq_field_type SWQGeneralChecker( swq_expr_node *poNode,
         eRetType = SWQ_STRING;
         if( poNode->nSubExprCount > 3 || poNode->nSubExprCount < 2 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Expected 2 or 3 arguments to SUBSTR(), but got %d.",
                       poNode->nSubExprCount );
             return SWQ_ERROR;
         }
-        if( poNode->papoSubExpr[0]->field_type != SWQ_STRING 
+        if( poNode->papoSubExpr[0]->field_type != SWQ_STRING
             || poNode->papoSubExpr[1]->field_type != SWQ_INTEGER
-            || (poNode->nSubExprCount > 2 
+            || (poNode->nSubExprCount > 2
                 && poNode->papoSubExpr[2]->field_type != SWQ_INTEGER) )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Wrong argument type for SUBSTR(), expected SUBSTR(string,int,int) or SUBSTR(string,int)." );
             return SWQ_ERROR;
         }
@@ -1067,25 +1061,25 @@ swq_field_type SWQGeneralChecker( swq_expr_node *poNode,
         eRetType = SWQ_STRING;
         if( poNode->nSubExprCount != 2 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Expected 2 arguments to hstore_get_value(), but got %d.",
                       poNode->nSubExprCount );
             return SWQ_ERROR;
         }
-        if( poNode->papoSubExpr[0]->field_type != SWQ_STRING 
+        if( poNode->papoSubExpr[0]->field_type != SWQ_STRING
             || poNode->papoSubExpr[1]->field_type != SWQ_STRING )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Wrong argument type for hstore_get_value(), expected hstore_get_value(string,string)." );
             return SWQ_ERROR;
         }
         break;
-        
+
       default:
       {
-          const swq_operation *poOp = 
+          const swq_operation *poOp =
               swq_op_registrar::GetOperator((swq_op)poNode->nOperation);
-          
+
           CPLError( CE_Failure, CPLE_AppDefined,
                     "SWQGeneralChecker() called on unsupported operation %s.",
                     poOp->pszName);
@@ -1097,12 +1091,10 @@ swq_field_type SWQGeneralChecker( swq_expr_node *poNode,
 /* -------------------------------------------------------------------- */
     if( eArgType != SWQ_OTHER )
     {
-        int i;
-
         if( SWQ_IS_INTEGER(eArgType) || eArgType == SWQ_BOOLEAN )
             eArgType = SWQ_FLOAT;
 
-        for( i = 0; i < poNode->nSubExprCount; i++ )
+        for( int i = 0; i < poNode->nSubExprCount; i++ )
         {
             swq_field_type eThisArgType = poNode->papoSubExpr[i]->field_type;
             if( SWQ_IS_INTEGER(eThisArgType) ||  eThisArgType == SWQ_BOOLEAN )
@@ -1110,7 +1102,7 @@ swq_field_type SWQGeneralChecker( swq_expr_node *poNode,
 
             if( eArgType != eThisArgType )
             {
-                // Conveniency for join. We allow comparing numeric columns
+                // Convenience for join. We allow comparing numeric columns
                 // and string columns, by casting string columns to numeric
                 if( bAllowMismatchTypeOnFieldComparison &&
                     poNode->nSubExprCount == 2 &&
@@ -1141,10 +1133,10 @@ swq_field_type SWQGeneralChecker( swq_expr_node *poNode,
                     break;
                 }
 
-                const swq_operation *poOp = 
+                const swq_operation *poOp =
                     swq_op_registrar::GetOperator((swq_op)poNode->nOperation);
-                
-                CPLError( CE_Failure, CPLE_AppDefined, 
+
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "Type mismatch or improper type of arguments to %s operator.",
                           poOp->pszName );
                 return SWQ_ERROR;
@@ -1155,19 +1147,22 @@ swq_field_type SWQGeneralChecker( swq_expr_node *poNode,
 /* -------------------------------------------------------------------- */
 /*      Validate the arg count if requested.                            */
 /* -------------------------------------------------------------------- */
-    if( nArgCount != -1 
+#if 0
+    // nArgCount was always -1, so this block was never executed.
+    if( nArgCount != -1
         && nArgCount != poNode->nSubExprCount )
     {
-        const swq_operation *poOp = 
+        const swq_operation *poOp =
             swq_op_registrar::GetOperator((swq_op)poNode->nOperation);
-                
-        CPLError( CE_Failure, CPLE_AppDefined, 
+
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Expected %d arguments to %s, but got %d arguments.",
                   nArgCount,
                   poOp->pszName,
                   poNode->nSubExprCount );
         return SWQ_ERROR;
     }
+#endif
 
     return eRetType;
 }
@@ -1212,7 +1207,7 @@ swq_expr_node *SWQCastEvaluator( swq_expr_node *node,
             }
         }
         break;
-        
+
         case SWQ_INTEGER64:
         {
             poRetNode = new swq_expr_node( 0 );
@@ -1328,7 +1323,7 @@ swq_expr_node *SWQCastEvaluator( swq_expr_node *node,
                     osRet = poSrcNode->string_value;
                     break;
             }
-         
+
             if( node->nSubExprCount > 2 )
             {
                 int nWidth;
@@ -1353,7 +1348,7 @@ swq_expr_node *SWQCastEvaluator( swq_expr_node *node,
 swq_field_type SWQCastChecker( swq_expr_node *poNode,
                                CPL_UNUSED int bAllowMismatchTypeOnFieldComparison )
 
-{									
+{
     swq_field_type eType = SWQ_ERROR;
     const char *pszTypeName = poNode->papoSubExpr[1]->string_value;
 
diff --git a/ogr/swq_op_registrar.cpp b/ogr/swq_op_registrar.cpp
index b5445dc..57c57b0 100644
--- a/ogr/swq_op_registrar.cpp
+++ b/ogr/swq_op_registrar.cpp
@@ -1,10 +1,10 @@
 /******************************************************************************
  *
  * Component: OGR SQL Engine
- * Purpose: Implementation of the swq_op_registrar class used to 
+ * Purpose: Implementation of the swq_op_registrar class used to
  *          represent operations possible in an SQL expression.
  * Author: Frank Warmerdam <warmerdam at pobox.com>
- * 
+ *
  ******************************************************************************
  * Copyright (C) 2010 Frank Warmerdam <warmerdam at pobox.com>
  * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
diff --git a/ogr/swq_parser.cpp b/ogr/swq_parser.cpp
index 4371b13..bd100d1 100644
--- a/ogr/swq_parser.cpp
+++ b/ogr/swq_parser.cpp
@@ -76,7 +76,7 @@
  * Purpose: expression and select parser grammar.
  *          Requires Bison 2.4.0 or newer to process.  Use "make parser" target.
  * Author: Frank Warmerdam <warmerdam at pobox.com>
- * 
+ *
  ******************************************************************************
  * Copyright (C) 2010 Frank Warmerdam <warmerdam at pobox.com>
  *
@@ -101,17 +101,18 @@
 
 
 #include "cpl_conv.h"
+#include "cpl_port.h"
 #include "cpl_string.h"
 #include "ogr_geometry.h"
 #include "swq.h"
 
 #define YYSTYPE  swq_expr_node*
 
-/* Defining YYSTYPE_IS_TRIVIAL is needed because the parser is generated as a C++ file. */ 
-/* See http://www.gnu.org/s/bison/manual/html_node/Memory-Management.html that suggests */ 
-/* increase YYINITDEPTH instead, but this will consume memory. */ 
-/* Setting YYSTYPE_IS_TRIVIAL overcomes this limitation, but might be fragile because */ 
-/* it appears to be a non documented feature of Bison */ 
+/* Defining YYSTYPE_IS_TRIVIAL is needed because the parser is generated as a C++ file. */
+/* See http://www.gnu.org/s/bison/manual/html_node/Memory-Management.html that suggests */
+/* increase YYINITDEPTH instead, but this will consume memory. */
+/* Setting YYSTYPE_IS_TRIVIAL overcomes this limitation, but might be fragile because */
+/* it appears to be a non documented feature of Bison */
 #define YYSTYPE_IS_TRIVIAL 1
 
 
@@ -1001,6 +1002,7 @@ yytnamerr (char *yyres, const char *yystr)
             if (*++yyp != '\\')
               goto do_not_strip_quotes;
             /* Fall through.  */
+            // CPL_FALLTHROUGH
           default:
             if (yyres)
               yyres[yyn] = *yyp;
@@ -1329,7 +1331,7 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
   yyssp++;
 
  yysetstate:
-  *yyssp = yystate;
+  *yyssp = (yytype_int16)yystate;
 
   if (yyss + yystacksize - 1 <= yyssp)
     {
@@ -1729,7 +1731,7 @@ yyreduce:
             in->nOperation = SWQ_IN;
             in->PushSubExpression( (yyvsp[-5]) );
             in->ReverseSubExpressions();
-            
+
             (yyval) = new swq_expr_node( SWQ_NOT );
             (yyval)->field_type = SWQ_BOOLEAN;
             (yyval)->PushSubExpression( in );
@@ -1954,7 +1956,7 @@ yyreduce:
   case 44:
 #line 449 "swq_parser.y" /* yacc.c:1646  */
     {
-            const swq_operation *poOp = 
+            const swq_operation *poOp =
                     swq_op_registrar::GetOperator( (yyvsp[-3])->string_value );
 
             if( poOp == NULL )
@@ -1970,7 +1972,7 @@ yyreduce:
                 }
                 else
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined, 
+                    CPLError( CE_Failure, CPLE_AppDefined,
                                     "Undefined function '%s' used.",
                                     (yyvsp[-3])->string_value );
                     delete (yyvsp[-3]);
@@ -2034,9 +2036,9 @@ yyreduce:
 #line 515 "swq_parser.y" /* yacc.c:1646  */
     {
         OGRwkbGeometryType eType = OGRFromOGCGeomType((yyvsp[-1])->string_value);
-        if( !EQUAL((yyvsp[-3])->string_value,"GEOMETRY") || 
+        if( !EQUAL((yyvsp[-3])->string_value,"GEOMETRY") ||
             (wkbFlatten(eType) == wkbUnknown &&
-            !EQUALN((yyvsp[-1])->string_value, "GEOMETRY", strlen("GEOMETRY"))) )
+            !STARTS_WITH_CI((yyvsp[-1])->string_value, "GEOMETRY")) )
         {
             yyerror (context, "syntax error");
             delete (yyvsp[-3]);
@@ -2054,9 +2056,9 @@ yyreduce:
 #line 533 "swq_parser.y" /* yacc.c:1646  */
     {
         OGRwkbGeometryType eType = OGRFromOGCGeomType((yyvsp[-3])->string_value);
-        if( !EQUAL((yyvsp[-5])->string_value,"GEOMETRY") || 
+        if( !EQUAL((yyvsp[-5])->string_value,"GEOMETRY") ||
             (wkbFlatten(eType) == wkbUnknown &&
-            !EQUALN((yyvsp[-3])->string_value, "GEOMETRY", strlen("GEOMETRY"))) )
+            !STARTS_WITH_CI((yyvsp[-3])->string_value, "GEOMETRY")) )
         {
             yyerror (context, "syntax error");
             delete (yyvsp[-5]);
@@ -2174,7 +2176,7 @@ yyreduce:
             if( !EQUAL((yyvsp[-3])->string_value,"COUNT") )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
-                        "Syntax Error with %s(*).", 
+                        "Syntax Error with %s(*).",
                         (yyvsp[-3])->string_value );
                 delete (yyvsp[-3]);
                 YYERROR;
@@ -2182,7 +2184,7 @@ yyreduce:
 
             delete (yyvsp[-3]);
             (yyvsp[-3]) = NULL;
-                    
+
             swq_expr_node *poNode = new swq_expr_node();
             poNode->eNodeType = SNT_COLUMN;
             poNode->string_value = CPLStrdup( "*" );
@@ -2207,7 +2209,7 @@ yyreduce:
             if( !EQUAL((yyvsp[-4])->string_value,"COUNT") )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
-                        "Syntax Error with %s(*).", 
+                        "Syntax Error with %s(*).",
                         (yyvsp[-4])->string_value );
                 delete (yyvsp[-4]);
                 delete (yyvsp[0]);
@@ -2251,10 +2253,10 @@ yyreduce:
             }
 
             delete (yyvsp[-4]);
-            
+
             swq_expr_node *count = new swq_expr_node( SWQ_COUNT );
             count->PushSubExpression( (yyvsp[-1]) );
-                
+
             if( !context->poCurSelect->PushField( count, NULL, TRUE ) )
             {
                 delete count;
@@ -2315,7 +2317,7 @@ yyreduce:
   case 73:
 #line 772 "swq_parser.y" /* yacc.c:1646  */
     {
-            context->poCurSelect->PushJoin( (yyvsp[-3])->int_value,
+            context->poCurSelect->PushJoin( static_cast<int>((yyvsp[-3])->int_value),
                                             (yyvsp[-1]) );
             delete (yyvsp[-3]);
         }
@@ -2325,7 +2327,7 @@ yyreduce:
   case 74:
 #line 778 "swq_parser.y" /* yacc.c:1646  */
     {
-            context->poCurSelect->PushJoin( (yyvsp[-3])->int_value,
+            context->poCurSelect->PushJoin( static_cast<int>((yyvsp[-3])->int_value),
                                             (yyvsp[-1]) );
             delete (yyvsp[-3]);
 	    }
@@ -2408,7 +2410,7 @@ yyreduce:
     {
         int iTable;
         iTable = context->poCurSelect->PushTableDef( (yyvsp[-3])->string_value,
-                                                     (yyvsp[-1])->string_value, 
+                                                     (yyvsp[-1])->string_value,
                                                      (yyvsp[0])->string_value );
         delete (yyvsp[-3]);
         delete (yyvsp[-1]);
@@ -2438,7 +2440,7 @@ yyreduce:
     {
         int iTable;
         iTable = context->poCurSelect->PushTableDef( (yyvsp[-3])->string_value,
-                                                     (yyvsp[-1])->string_value, 
+                                                     (yyvsp[-1])->string_value,
                                                      (yyvsp[0])->string_value );
         delete (yyvsp[-3]);
         delete (yyvsp[-1]);
diff --git a/ogr/swq_parser.y b/ogr/swq_parser.y
index 28f10df..f970f65 100644
--- a/ogr/swq_parser.y
+++ b/ogr/swq_parser.y
@@ -5,7 +5,7 @@
  * Purpose: expression and select parser grammar.
  *          Requires Bison 2.4.0 or newer to process.  Use "make parser" target.
  * Author: Frank Warmerdam <warmerdam at pobox.com>
- * 
+ *
  ******************************************************************************
  * Copyright (C) 2010 Frank Warmerdam <warmerdam at pobox.com>
  *
@@ -36,11 +36,11 @@
 
 #define YYSTYPE  swq_expr_node*
 
-/* Defining YYSTYPE_IS_TRIVIAL is needed because the parser is generated as a C++ file. */ 
-/* See http://www.gnu.org/s/bison/manual/html_node/Memory-Management.html that suggests */ 
-/* increase YYINITDEPTH instead, but this will consume memory. */ 
-/* Setting YYSTYPE_IS_TRIVIAL overcomes this limitation, but might be fragile because */ 
-/* it appears to be a non documented feature of Bison */ 
+/* Defining YYSTYPE_IS_TRIVIAL is needed because the parser is generated as a C++ file. */
+/* See http://www.gnu.org/s/bison/manual/html_node/Memory-Management.html that suggests */
+/* increase YYINITDEPTH instead, but this will consume memory. */
+/* Setting YYSTYPE_IS_TRIVIAL overcomes this limitation, but might be fragile because */
+/* it appears to be a non documented feature of Bison */
 #define YYSTYPE_IS_TRIVIAL 1
 
 %}
@@ -109,7 +109,7 @@
 
 %%
 
-input:  
+input:
     | SWQT_VALUE_START value_expr
         {
             context->poRoot = $2;
@@ -121,12 +121,12 @@ input:
         }
 
 value_expr:
-    value_expr_non_logical 
+    value_expr_non_logical
         {
             $$ = $1;
         }
 
-    | value_expr SWQT_AND value_expr 
+    | value_expr SWQT_AND value_expr
         {
             $$ = new swq_expr_node( SWQ_AND );
             $$->field_type = SWQ_BOOLEAN;
@@ -283,7 +283,7 @@ value_expr:
             in->nOperation = SWQ_IN;
             in->PushSubExpression( $1 );
             in->ReverseSubExpressions();
-            
+
             $$ = new swq_expr_node( SWQ_NOT );
             $$->field_type = SWQ_BOOLEAN;
             $$->PushSubExpression( in );
@@ -365,12 +365,12 @@ field_value:
         }
 
 value_expr_non_logical:
-    SWQT_INTEGER_NUMBER 
+    SWQT_INTEGER_NUMBER
         {
             $$ = $1;
         }
 
-    | SWQT_FLOAT_NUMBER 
+    | SWQT_FLOAT_NUMBER
         {
             $$ = $1;
         }
@@ -447,7 +447,7 @@ value_expr_non_logical:
 
     | SWQT_IDENTIFIER '(' value_expr_list ')'
         {
-            const swq_operation *poOp = 
+            const swq_operation *poOp =
                     swq_op_registrar::GetOperator( $1->string_value );
 
             if( poOp == NULL )
@@ -463,7 +463,7 @@ value_expr_non_logical:
                 }
                 else
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined, 
+                    CPLError( CE_Failure, CPLE_AppDefined,
                                     "Undefined function '%s' used.",
                                     $1->string_value );
                     delete $1;
@@ -495,14 +495,14 @@ type_def:
         $$->PushSubExpression( $1 );
     }
 
-    | SWQT_IDENTIFIER '(' SWQT_INTEGER_NUMBER ')' 
+    | SWQT_IDENTIFIER '(' SWQT_INTEGER_NUMBER ')'
     {
         $$ = new swq_expr_node( SWQ_CAST );
         $$->PushSubExpression( $3 );
         $$->PushSubExpression( $1 );
     }
 
-    | SWQT_IDENTIFIER '(' SWQT_INTEGER_NUMBER ',' SWQT_INTEGER_NUMBER ')' 
+    | SWQT_IDENTIFIER '(' SWQT_INTEGER_NUMBER ',' SWQT_INTEGER_NUMBER ')'
     {
         $$ = new swq_expr_node( SWQ_CAST );
         $$->PushSubExpression( $5 );
@@ -511,12 +511,12 @@ type_def:
     }
 
     /* e.g. GEOMETRY(POINT) */
-    | SWQT_IDENTIFIER '(' SWQT_IDENTIFIER ')' 
+    | SWQT_IDENTIFIER '(' SWQT_IDENTIFIER ')'
     {
         OGRwkbGeometryType eType = OGRFromOGCGeomType($3->string_value);
-        if( !EQUAL($1->string_value,"GEOMETRY") || 
+        if( !EQUAL($1->string_value,"GEOMETRY") ||
             (wkbFlatten(eType) == wkbUnknown &&
-            !EQUALN($3->string_value, "GEOMETRY", strlen("GEOMETRY"))) )
+            !STARTS_WITH_CI($3->string_value, "GEOMETRY")) )
         {
             yyerror (context, "syntax error");
             delete $1;
@@ -529,12 +529,12 @@ type_def:
     }
 
     /* e.g. GEOMETRY(POINT,4326) */
-    | SWQT_IDENTIFIER '(' SWQT_IDENTIFIER ',' SWQT_INTEGER_NUMBER ')' 
+    | SWQT_IDENTIFIER '(' SWQT_IDENTIFIER ',' SWQT_INTEGER_NUMBER ')'
     {
         OGRwkbGeometryType eType = OGRFromOGCGeomType($3->string_value);
-        if( !EQUAL($1->string_value,"GEOMETRY") || 
+        if( !EQUAL($1->string_value,"GEOMETRY") ||
             (wkbFlatten(eType) == wkbUnknown &&
-            !EQUALN($3->string_value, "GEOMETRY", strlen("GEOMETRY"))) )
+            !STARTS_WITH_CI($3->string_value, "GEOMETRY")) )
         {
             yyerror (context, "syntax error");
             delete $1;
@@ -548,7 +548,7 @@ type_def:
         $$->PushSubExpression( $1 );
     }
 
-select_statement: 
+select_statement:
     select_core opt_union_all
     | '(' select_core ')' opt_union_all
 
@@ -578,7 +578,7 @@ select_field_list:
     column_spec
     | column_spec ',' select_field_list
 
-column_spec: 
+column_spec:
     value_expr
         {
             if( !context->poCurSelect->PushField( $1 ) )
@@ -641,7 +641,7 @@ column_spec:
             if( !EQUAL($1->string_value,"COUNT") )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
-                        "Syntax Error with %s(*).", 
+                        "Syntax Error with %s(*).",
                         $1->string_value );
                 delete $1;
                 YYERROR;
@@ -649,7 +649,7 @@ column_spec:
 
             delete $1;
             $1 = NULL;
-                    
+
             swq_expr_node *poNode = new swq_expr_node();
             poNode->eNodeType = SNT_COLUMN;
             poNode->string_value = CPLStrdup( "*" );
@@ -671,7 +671,7 @@ column_spec:
             if( !EQUAL($1->string_value,"COUNT") )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
-                        "Syntax Error with %s(*).", 
+                        "Syntax Error with %s(*).",
                         $1->string_value );
                 delete $1;
                 delete $5;
@@ -712,10 +712,10 @@ column_spec:
             }
 
             delete $1;
-            
+
             swq_expr_node *count = new swq_expr_node( SWQ_COUNT );
             count->PushSubExpression( $4 );
-                
+
             if( !context->poCurSelect->PushField( count, NULL, TRUE ) )
             {
                 delete count;
@@ -761,7 +761,7 @@ as_clause:
     | SWQT_IDENTIFIER
 
 
-opt_where:  
+opt_where:
     | SWQT_WHERE value_expr
         {
             context->poCurSelect->where_expr = $2;
@@ -770,13 +770,13 @@ opt_where:
 opt_joins:
     | SWQT_JOIN table_def SWQT_ON value_expr opt_joins
         {
-            context->poCurSelect->PushJoin( $2->int_value,
+            context->poCurSelect->PushJoin( static_cast<int>($2->int_value),
                                             $4 );
             delete $2;
         }
     | SWQT_LEFT SWQT_JOIN table_def SWQT_ON value_expr opt_joins
         {
-            context->poCurSelect->PushJoin( $3->int_value,
+            context->poCurSelect->PushJoin( static_cast<int>($3->int_value),
                                             $5 );
             delete $3;
 	    }
@@ -786,7 +786,7 @@ opt_order_by:
 
 sort_spec_list:
     sort_spec ',' sort_spec_list
-    | sort_spec 
+    | sort_spec
 
 sort_spec:
     field_value
@@ -845,7 +845,7 @@ table_def:
     {
         int iTable;
         iTable = context->poCurSelect->PushTableDef( $1->string_value,
-                                                     $3->string_value, 
+                                                     $3->string_value,
                                                      $4->string_value );
         delete $1;
         delete $3;
@@ -869,7 +869,7 @@ table_def:
     {
         int iTable;
         iTable = context->poCurSelect->PushTableDef( $1->string_value,
-                                                     $3->string_value, 
+                                                     $3->string_value,
                                                      $4->string_value );
         delete $1;
         delete $3;
diff --git a/ogr/swq_select.cpp b/ogr/swq_select.cpp
index c731547..df3606a 100644
--- a/ogr/swq_select.cpp
+++ b/ogr/swq_select.cpp
@@ -3,7 +3,7 @@
  * Component: OGR SQL Engine
  * Purpose: swq_select class implementation.
  * Author: Frank Warmerdam <warmerdam at pobox.com>
- * 
+ *
  ******************************************************************************
  * Copyright (C) 2010 Frank Warmerdam <warmerdam at pobox.com>
  * Copyright (c) 2010-2014, Even Rouault <even dot rouault at mines-paris dot org>
@@ -35,29 +35,21 @@
 /*                             swq_select()                             */
 /************************************************************************/
 
-swq_select::swq_select()
-
-{
-    query_mode = 0;
-    raw_select = NULL;
-
-    result_columns = 0;
-    column_defs = NULL;
-    column_summary = NULL;
-    
-    table_count = 0;
-    table_defs = NULL;
-    
-    join_count = 0;
-    join_defs = NULL;
-    
-    where_expr = NULL;
-
-    order_specs = 0;
-    order_defs = NULL;
-
-    poOtherSelect = NULL;
-}
+swq_select::swq_select() :
+    query_mode(0),
+    raw_select(NULL),
+    result_columns(0),
+    column_defs(NULL),
+    column_summary(NULL),
+    table_count(0),
+    table_defs(NULL),
+    join_count(0),
+    join_defs(NULL),
+    where_expr(NULL),
+    order_specs(0),
+    order_defs(NULL),
+    poOtherSelect(NULL)
+{ }
 
 /************************************************************************/
 /*                            ~swq_select()                             */
@@ -66,12 +58,10 @@ swq_select::swq_select()
 swq_select::~swq_select()
 
 {
-    int i;
-
     delete where_expr;
     CPLFree( raw_select );
 
-    for( i = 0; i < table_count; i++ )
+    for( int i = 0; i < table_count; i++ )
     {
         swq_table_def *table_def = table_defs + i;
 
@@ -82,7 +72,7 @@ swq_select::~swq_select()
     if( table_defs != NULL )
         CPLFree( table_defs );
 
-    for( i = 0; i < result_columns; i++ )
+    for( int i = 0; i < result_columns; i++ )
     {
         CPLFree( column_defs[i].table_name );
         CPLFree( column_defs[i].field_name );
@@ -90,12 +80,10 @@ swq_select::~swq_select()
 
         delete column_defs[i].expr;
 
-        if( column_summary != NULL 
+        if( column_summary != NULL
             && column_summary[i].distinct_list != NULL )
         {
-            int j;
-            
-            for( j = 0; j < column_summary[i].count; j++ )
+            for( int j = 0; j < column_summary[i].count; j++ )
                 CPLFree( column_summary[i].distinct_list[j] );
 
             CPLFree( column_summary[i].distinct_list );
@@ -106,15 +94,15 @@ swq_select::~swq_select()
 
     CPLFree( column_summary );
 
-    for( i = 0; i < order_specs; i++ )
+    for( int i = 0; i < order_specs; i++ )
     {
         CPLFree( order_defs[i].table_name );
         CPLFree( order_defs[i].field_name );
     }
-    
+
     CPLFree( order_defs );
 
-    for( i = 0; i < join_count; i++ )
+    for( int i = 0; i < join_count; i++ )
     {
         delete join_defs[i].poExpr;
     }
@@ -169,8 +157,7 @@ void swq_select::postpreparse()
 /* -------------------------------------------------------------------- */
 /*      Reorder the joins in the order they appear in the SQL string.   */
 /* -------------------------------------------------------------------- */
-    int i;
-    for(i = 0; i < join_count / 2; i++)
+    for(int i = 0; i < join_count / 2; i++)
     {
         swq_join_def sTmp;
         memcpy(&sTmp, &join_defs[i], sizeof(swq_join_def));
@@ -179,7 +166,7 @@ void swq_select::postpreparse()
     }
 
     /* We make that strong assumption in ogr_gensql */
-    for(i = 0; i < join_count; i++)
+    for(int i = 0; i < join_count; i++)
     {
         CPLAssert(join_defs[i].secondary_table == i + 1);
     }
@@ -195,8 +182,6 @@ void swq_select::postpreparse()
 void swq_select::Dump( FILE *fp )
 
 {
-    int i;
-
     fprintf( fp, "SELECT Statement:\n" );
 
 /* -------------------------------------------------------------------- */
@@ -215,7 +200,7 @@ void swq_select::Dump( FILE *fp )
 /*      column_defs                                                     */
 /* -------------------------------------------------------------------- */
     fprintf( fp, "  Result Columns:\n" );
-    for( i = 0; i < result_columns; i++ )
+    for( int i = 0; i < result_columns; i++ )
     {
         swq_col_def *def = column_defs + i;
 
@@ -236,7 +221,7 @@ void swq_select::Dump( FILE *fp )
         else if( def->col_func == SWQCF_COUNT )
             fprintf( fp, "    Function: COUNT\n" );
         else if( def->col_func == SWQCF_SUM )
-            fprintf( fp, "    Function: SUM\n" ); 
+            fprintf( fp, "    Function: SUM\n" );
         else if( def->col_func == SWQCF_CUSTOM )
             fprintf( fp, "    Function: CUSTOM\n" );
         else
@@ -245,7 +230,7 @@ void swq_select::Dump( FILE *fp )
         if( def->distinct_flag )
             fprintf( fp, "    DISTINCT flag set\n" );
 
-        fprintf( fp, "    Field Index: %d, Table Index: %d\n", 
+        fprintf( fp, "    Field Index: %d, Table Index: %d\n",
                  def->field_index, def->table_index );
 
         fprintf( fp, "    Field Type: %d\n", def->field_type );
@@ -265,7 +250,7 @@ void swq_select::Dump( FILE *fp )
 /*      table_defs                                                      */
 /* -------------------------------------------------------------------- */
     fprintf( fp, "  Table Defs: %d\n", table_count );
-    for( i = 0; i < table_count; i++ )
+    for( int i = 0; i < table_count; i++ )
     {
         fprintf( fp, "    datasource=%s, table_name=%s, table_alias=%s\n",
                  table_defs[i].data_source,
@@ -279,11 +264,11 @@ void swq_select::Dump( FILE *fp )
     if( join_count > 0 )
         fprintf( fp, "  joins:\n" );
 
-    for( i = 0; i < join_count; i++ )
+    for( int i = 0; i < join_count; i++ )
     {
         fprintf( fp, "  %d:\n", i );
         join_defs[i].poExpr->Dump( fp, 4 );
-        fprintf( fp, "    Secondary Table: %d\n", 
+        fprintf( fp, "    Secondary Table: %d\n",
                  join_defs[i].secondary_table );
     }
 
@@ -300,7 +285,7 @@ void swq_select::Dump( FILE *fp )
 /*      Order by                                                        */
 /* -------------------------------------------------------------------- */
 
-    for( i = 0; i < order_specs; i++ )
+    for( int i = 0; i < order_specs; i++ )
     {
         fprintf( fp, "  ORDER BY: %s (%d/%d)",
                  order_defs[i].field_name,
@@ -319,12 +304,11 @@ void swq_select::Dump( FILE *fp )
 
 char* swq_select::Unparse()
 {
-    int i;
     CPLString osSelect("SELECT ");
     if( query_mode == SWQM_DISTINCT_LIST )
         osSelect += "DISTINCT ";
 
-    for( i = 0; i < result_columns; i++ )
+    for( int i = 0; i < result_columns; i++ )
     {
         swq_col_def *def = column_defs + i;
 
@@ -372,7 +356,7 @@ char* swq_select::Unparse()
         if( def->col_func != SWQCF_NONE )
             osSelect += ")";
     }
-    
+
     osSelect += " FROM ";
     if( table_defs[0].data_source != NULL )
     {
@@ -388,7 +372,7 @@ char* swq_select::Unparse()
         osSelect += swq_expr_node::QuoteIfNecessary(table_defs[0].table_alias, '"');
     }
 
-    for( i = 0; i < join_count; i++ )
+    for( int i = 0; i < join_count; i++ )
     {
         int iTable = join_defs[i].secondary_table;
         osSelect += " JOIN ";
@@ -419,7 +403,7 @@ char* swq_select::Unparse()
         CPLFree(pszTmp);
     }
 
-    for( i = 0; i < order_specs; i++ )
+    for( int i = 0; i < order_specs; i++ )
     {
         osSelect += " ORDER BY ";
         osSelect += swq_expr_node::QuoteIfNecessary(order_defs[i].field_name, '"');
@@ -451,7 +435,7 @@ int swq_select::PushField( swq_expr_node *poExpr, const char *pszAlias,
 /* -------------------------------------------------------------------- */
     result_columns++;
 
-    column_defs = (swq_col_def *) 
+    column_defs = (swq_col_def *)
         CPLRealloc( column_defs, sizeof(swq_col_def) * result_columns );
 
     swq_col_def *col_def = column_defs + result_columns - 1;
@@ -463,9 +447,9 @@ int swq_select::PushField( swq_expr_node *poExpr, const char *pszAlias,
 /* -------------------------------------------------------------------- */
     if( poExpr->eNodeType == SNT_COLUMN )
     {
-        col_def->table_name = 
+        col_def->table_name =
             CPLStrdup(poExpr->table_name ? poExpr->table_name : "");
-        col_def->field_name = 
+        col_def->field_name =
             CPLStrdup(poExpr->string_value);
     }
     else if( poExpr->eNodeType == SNT_OPERATION
@@ -475,10 +459,10 @@ int swq_select::PushField( swq_expr_node *poExpr, const char *pszAlias,
              && poExpr->nSubExprCount >= 1
              && poExpr->papoSubExpr[0]->eNodeType == SNT_COLUMN )
     {
-        col_def->table_name = 
+        col_def->table_name =
             CPLStrdup(poExpr->papoSubExpr[0]->table_name ?
                         poExpr->papoSubExpr[0]->table_name : "");
-        col_def->field_name = 
+        col_def->field_name =
             CPLStrdup(poExpr->papoSubExpr[0]->string_value);
     }
     else
@@ -494,14 +478,14 @@ int swq_select::PushField( swq_expr_node *poExpr, const char *pszAlias,
         col_def->field_alias = CPLStrdup( pszAlias );
     else if( pszAlias == NULL && poExpr->eNodeType == SNT_OPERATION
              && poExpr->nSubExprCount >= 1
-             && ( poExpr->nOperation == SWQ_CONCAT ||
-                  poExpr->nOperation == SWQ_SUBSTR )
+             && ( static_cast<swq_op>(poExpr->nOperation) == SWQ_CONCAT ||
+                  static_cast<swq_op>(poExpr->nOperation) == SWQ_SUBSTR )
              && poExpr->papoSubExpr[0]->eNodeType == SNT_COLUMN )
     {
-        const swq_operation *op = swq_op_registrar::GetOperator( 
-                (swq_op) poExpr->nOperation );
+        const swq_operation *op = swq_op_registrar::GetOperator(
+            static_cast<swq_op>(poExpr->nOperation) );
 
-        col_def->field_alias = CPLStrdup( CPLSPrintf("%s_%s", op->pszName, 
+        col_def->field_alias = CPLStrdup( CPLSPrintf("%s_%s", op->pszName,
                                     poExpr->papoSubExpr[0]->string_value));
     }
 
@@ -517,7 +501,7 @@ int swq_select::PushField( swq_expr_node *poExpr, const char *pszAlias,
 /* -------------------------------------------------------------------- */
 /*      Do we have a CAST operator in play?                             */
 /* -------------------------------------------------------------------- */
-    if( poExpr->eNodeType == SNT_OPERATION 
+    if( poExpr->eNodeType == SNT_OPERATION
         && poExpr->nOperation == SWQ_CAST )
     {
         const char *pszTypeName = poExpr->papoSubExpr[1]->string_value;
@@ -573,7 +557,7 @@ int swq_select::PushField( swq_expr_node *poExpr, const char *pszAlias,
         else
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "Unrecognized typename %s in CAST operator.", 
+                      "Unrecognized typename %s in CAST operator.",
                       pszTypeName );
             CPLFree(col_def->table_name);
             col_def->table_name = NULL;
@@ -584,8 +568,8 @@ int swq_select::PushField( swq_expr_node *poExpr, const char *pszAlias,
             result_columns--;
             return FALSE;
         }
-        
-        if( col_def->target_type == SWQ_GEOMETRY ) 
+
+        if( col_def->target_type == SWQ_GEOMETRY )
         {
             if( poExpr->nSubExprCount > 2 )
             {
@@ -652,16 +636,16 @@ int swq_select::PushField( swq_expr_node *poExpr, const char *pszAlias,
 /* -------------------------------------------------------------------- */
 /*      Do we have a special column function in play?                   */
 /* -------------------------------------------------------------------- */
-    if( poExpr->eNodeType == SNT_OPERATION 
-        && poExpr->nOperation >= SWQ_AVG
-        && poExpr->nOperation <= SWQ_SUM )
+    if( poExpr->eNodeType == SNT_OPERATION
+        && static_cast<swq_op>(poExpr->nOperation) >= SWQ_AVG
+        && static_cast<swq_op>(poExpr->nOperation) <= SWQ_SUM )
     {
         if( poExpr->nSubExprCount != 1 )
         {
-            const swq_operation *poOp = 
+            const swq_operation *poOp =
                     swq_op_registrar::GetOperator( (swq_op)poExpr->nOperation );
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "Column Summary Function '%s' has wrong number of arguments.", 
+                      "Column Summary Function '%s' has wrong number of arguments.",
                       poOp->pszName );
             CPLFree(col_def->table_name);
             col_def->table_name = NULL;
@@ -674,10 +658,10 @@ int swq_select::PushField( swq_expr_node *poExpr, const char *pszAlias,
         }
         else if( poExpr->papoSubExpr[0]->eNodeType != SNT_COLUMN )
         {
-            const swq_operation *poOp = 
+            const swq_operation *poOp =
                     swq_op_registrar::GetOperator( (swq_op)poExpr->nOperation );
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "Argument of column Summary Function '%s' should be a column.", 
+                      "Argument of column Summary Function '%s' should be a column.",
                       poOp->pszName );
             CPLFree(col_def->table_name);
             col_def->table_name = NULL;
@@ -690,11 +674,11 @@ int swq_select::PushField( swq_expr_node *poExpr, const char *pszAlias,
         }
         else
         {
-            col_def->col_func = 
+            col_def->col_func =
                 (swq_col_func) poExpr->nOperation;
 
             swq_expr_node *poSubExpr = poExpr->papoSubExpr[0];
-        
+
             poExpr->papoSubExpr[0] = NULL;
             poExpr->nSubExprCount = 0;
             delete poExpr;
@@ -719,7 +703,7 @@ int swq_select::PushTableDef( const char *pszDataSource,
 {
     table_count++;
 
-    table_defs = (swq_table_def *) 
+    table_defs = (swq_table_def *)
         CPLRealloc( table_defs, sizeof(swq_table_def) * table_count );
 
     if( pszDataSource != NULL )
@@ -745,7 +729,7 @@ void swq_select::PushOrderBy( const char* pszTableName, const char *pszFieldName
 
 {
     order_specs++;
-    order_defs = (swq_order_def *) 
+    order_defs = (swq_order_def *)
         CPLRealloc( order_defs, sizeof(swq_order_def) * order_specs );
 
     order_defs[order_specs-1].table_name = CPLStrdup(pszTableName ? pszTableName : "");
@@ -763,7 +747,7 @@ void swq_select::PushJoin( int iSecondaryTable, swq_expr_node* poExpr )
 
 {
     join_count++;
-    join_defs = (swq_join_def *) 
+    join_defs = (swq_join_def *)
         CPLRealloc( join_defs, sizeof(swq_join_def) * join_count );
 
     join_defs[join_count-1].secondary_table = iSecondaryTable;
@@ -794,16 +778,14 @@ CPLErr swq_select::expand_wildcard( swq_field_list *field_list,
                                     int bAlwaysPrefixWithTableName )
 
 {
-    int isrc;
-
 /* ==================================================================== */
 /*      Check each pre-expansion field.                                 */
 /* ==================================================================== */
-    for( isrc = 0; isrc < result_columns; isrc++ )
+    for( int isrc = 0; isrc < result_columns; isrc++ )
     {
         const char *src_tablename = column_defs[isrc].table_name;
         const char *src_fieldname = column_defs[isrc].field_name;
-        int itable, new_fields, i, iout;
+        int itable, new_fields, iout;
 
         if( *src_fieldname == '\0'
             || src_fieldname[strlen(src_fieldname)-1] != '*' )
@@ -830,18 +812,18 @@ CPLErr swq_select::expand_wildcard( swq_field_list *field_list,
                         field_list->table_defs[itable].table_alias ) == 0 )
                     break;
             }
-            
+
             if( itable == field_list->table_count )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
-                         "Table %s not recognised from %s.%s definition.", 
+                         "Table %s not recognised from %s.%s definition.",
                          src_tablename, src_tablename, src_fieldname );
                 return CE_Failure;
             }
 
             /* count the number of fields in this table. */
             new_fields = 0;
-            for( i = 0; i < field_list->count; i++ )
+            for( int i = 0; i < field_list->count; i++ )
             {
                 if( field_list->table_ids[i] == itable )
                     new_fields++;
@@ -857,9 +839,9 @@ CPLErr swq_select::expand_wildcard( swq_field_list *field_list,
             CPLFree( column_defs[isrc].field_name );
             delete column_defs[isrc].expr;
 
-            column_defs = (swq_col_def *) 
-                CPLRealloc( column_defs, 
-                            sizeof(swq_col_def) * 
+            column_defs = (swq_col_def *)
+                CPLRealloc( column_defs,
+                            sizeof(swq_col_def) *
                             (result_columns + new_fields - 1 ) );
 
 /* -------------------------------------------------------------------- */
@@ -868,7 +850,7 @@ CPLErr swq_select::expand_wildcard( swq_field_list *field_list,
 /* -------------------------------------------------------------------- */
             if (new_fields != 1)
             {
-                for( i = result_columns-1; i > isrc; i-- )
+                for( int i = result_columns-1; i > isrc; i-- )
                 {
                     memcpy( column_defs + i + new_fields - 1,
                             column_defs + i,
@@ -881,7 +863,7 @@ CPLErr swq_select::expand_wildcard( swq_field_list *field_list,
 /* -------------------------------------------------------------------- */
 /*      Zero out all the stuff in the target column definitions.        */
 /* -------------------------------------------------------------------- */
-            memset( column_defs + isrc, 0, 
+            memset( column_defs + isrc, 0,
                     new_fields * sizeof(swq_col_def) );
         }
         else
@@ -904,8 +886,8 @@ CPLErr swq_select::expand_wildcard( swq_field_list *field_list,
 /*      Assign the selected fields.                                     */
 /* -------------------------------------------------------------------- */
         iout = isrc;
-        
-        for( i = 0; i < field_list->count; i++ )
+
+        for( int i = 0; i < field_list->count; i++ )
         {
             swq_col_def *def;
             int compose = (itable != -1) || bAlwaysPrefixWithTableName;
@@ -916,12 +898,12 @@ CPLErr swq_select::expand_wildcard( swq_field_list *field_list,
 
             /* set up some default values. */
             def = column_defs + iout;
-            def->field_precision = -1; 
+            def->field_precision = -1;
             def->target_type = SWQ_OTHER;
             def->target_subtype = OFSTNone;
 
             /* does this field duplicate an earlier one? */
-            if( field_list->table_ids[i] != 0 
+            if( field_list->table_ids[i] != 0
                 && !compose )
             {
                 int other;
@@ -937,10 +919,10 @@ CPLErr swq_select::expand_wildcard( swq_field_list *field_list,
                 }
             }
 
-            int itable = field_list->table_ids[i];
+            int field_itable = field_list->table_ids[i];
             const char *field_name = field_list->names[i];
-            const char *table_alias = 
-                field_list->table_defs[itable].table_alias;
+            const char *table_alias =
+                field_list->table_defs[field_itable].table_alias;
 
             def->table_name = CPLStrdup(table_alias);
             def->field_name = CPLStrdup(field_name);
@@ -967,13 +949,13 @@ CPLErr swq_select::expand_wildcard( swq_field_list *field_list,
 /*                       CheckCompatibleJoinExpr()                      */
 /************************************************************************/
 
-static int CheckCompatibleJoinExpr( swq_expr_node* poExpr,
+static bool CheckCompatibleJoinExpr( swq_expr_node* poExpr,
                                     int secondary_table,
                                     swq_field_list* field_list )
 {
     if( poExpr->eNodeType == SNT_CONSTANT )
-        return TRUE;
-    
+        return true;
+
     if( poExpr->eNodeType == SNT_COLUMN )
     {
         CPLAssert( poExpr->field_index != -1 );
@@ -981,18 +963,18 @@ static int CheckCompatibleJoinExpr( swq_expr_node* poExpr,
         if( poExpr->table_index != 0 && poExpr->table_index != secondary_table )
         {
             if( poExpr->table_name )
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                        "Field %s.%s in JOIN clause does not correspond to the primary table nor the joint (secondary) table.", 
+                CPLError( CE_Failure, CPLE_AppDefined,
+                        "Field %s.%s in JOIN clause does not correspond to the primary table nor the joint (secondary) table.",
                         poExpr->table_name,
                         poExpr->string_value );
             else
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                        "Field %s in JOIN clause does not correspond to the primary table nor the joint (secondary) table.", 
+                CPLError( CE_Failure, CPLE_AppDefined,
+                        "Field %s in JOIN clause does not correspond to the primary table nor the joint (secondary) table.",
                         poExpr->string_value );
-            return FALSE;
+            return false;
         }
 
-        return TRUE;
+        return true;
     }
 
     if( poExpr->eNodeType == SNT_OPERATION )
@@ -1002,12 +984,12 @@ static int CheckCompatibleJoinExpr( swq_expr_node* poExpr,
             if( !CheckCompatibleJoinExpr( poExpr->papoSubExpr[i],
                                           secondary_table,
                                           field_list ) )
-                return FALSE;
+                return false;
         }
-        return TRUE;
+        return true;
     }
-    
-    return FALSE;
+
+    return false;
 }
 
 /************************************************************************/
@@ -1019,12 +1001,9 @@ static int CheckCompatibleJoinExpr( swq_expr_node* poExpr,
 CPLErr swq_select::parse( swq_field_list *field_list,
                           swq_select_parse_options* poParseOptions )
 {
-    int  i;
-    CPLErr eError;
-
     int bAlwaysPrefixWithTableName = poParseOptions &&
                                      poParseOptions->bAlwaysPrefixWithTableName;
-    eError = expand_wildcard( field_list, bAlwaysPrefixWithTableName );
+    CPLErr eError = expand_wildcard( field_list, bAlwaysPrefixWithTableName );
     if( eError != CE_None )
         return eError;
 
@@ -1035,7 +1014,7 @@ CPLErr swq_select::parse( swq_field_list *field_list,
 /* -------------------------------------------------------------------- */
 /*      Identify field information.                                     */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < result_columns; i++ )
+    for( int i = 0; i < result_columns; i++ )
     {
         swq_col_def *def = column_defs + i;
 
@@ -1046,7 +1025,7 @@ CPLErr swq_select::parse( swq_field_list *field_list,
 
             if( def->expr->Check( field_list, TRUE, FALSE, poCustomFuncRegistrar ) == SWQ_ERROR )
                 return CE_Failure;
-                
+
             def->field_type = def->expr->field_type;
         }
         else
@@ -1056,23 +1035,25 @@ CPLErr swq_select::parse( swq_field_list *field_list,
             /* identify field */
             def->field_index = swq_identify_field( def->table_name,
                                                    def->field_name, field_list,
-                                                   &this_type, 
+                                                   &this_type,
                                                    &(def->table_index) );
-            
+
             /* record field type */
             def->field_type = this_type;
-            
+
             if( def->field_index == -1 && def->col_func != SWQCF_COUNT )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                          "Unrecognised field name %s.", 
-                          def->table_name[0] ? CPLSPrintf("%s.%s", def->table_name, def->field_name) : def->field_name );
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Unrecognized field name %s.",
+                          def->table_name[0] ?
+                          CPLSPrintf("%s.%s", def->table_name, def->field_name)
+                          : def->field_name );
                 return CE_Failure;
             }
         }
 
         /* identify column function if present */
-        if( (def->col_func == SWQCF_MIN 
+        if( (def->col_func == SWQCF_MIN
              || def->col_func == SWQCF_MAX
              || def->col_func == SWQCF_AVG
              || def->col_func == SWQCF_SUM)
@@ -1080,10 +1061,10 @@ CPLErr swq_select::parse( swq_field_list *field_list,
                 def->field_type == SWQ_GEOMETRY) )
         {
             // possibly this is already enforced by the checker?
-            const swq_operation *op = swq_op_registrar::GetOperator( 
+            const swq_operation *op = swq_op_registrar::GetOperator(
                 (swq_op) def->col_func );
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Use of field function %s() on %s field %s illegal.", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Use of field function %s() on %s field %s illegal.",
                       op->pszName,
                       SWQFieldTypeToString(def->field_type),
                       def->field_name );
@@ -1107,7 +1088,7 @@ CPLErr swq_select::parse( swq_field_list *field_list,
             return CE_Failure;
     }
 
-    for( i = 0; i < result_columns; i++ )
+    for( int i = 0; i < result_columns; i++ )
     {
         swq_col_def *def = column_defs + i;
         int this_indicator = -1;
@@ -1124,7 +1105,7 @@ CPLErr swq_select::parse( swq_field_list *field_list,
             }
         }
 
-        if( def->col_func == SWQCF_MIN 
+        if( def->col_func == SWQCF_MIN
             || def->col_func == SWQCF_MAX
             || def->col_func == SWQCF_AVG
             || def->col_func == SWQCF_SUM
@@ -1172,7 +1153,7 @@ CPLErr swq_select::parse( swq_field_list *field_list,
 /* -------------------------------------------------------------------- */
 /*      Process column names in JOIN specs.                             */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < join_count; i++ )
+    for( int i = 0; i < join_count; i++ )
     {
         swq_join_def *def = join_defs + i;
         if( def->poExpr->Check( field_list, TRUE, TRUE, poCustomFuncRegistrar ) == SWQ_ERROR )
@@ -1184,7 +1165,7 @@ CPLErr swq_select::parse( swq_field_list *field_list,
 /* -------------------------------------------------------------------- */
 /*      Process column names in order specs.                            */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < order_specs; i++ )
+    for( int i = 0; i < order_specs; i++ )
     {
         swq_order_def *def = order_defs + i;
 
@@ -1195,9 +1176,11 @@ CPLErr swq_select::parse( swq_field_list *field_list,
                                                &field_type, &(def->table_index) );
         if( def->field_index == -1 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Unrecognised field name %s in ORDER BY.", 
-                      def->table_name[0] ? CPLSPrintf("%s.%s", def->table_name, def->field_name) : def->field_name );
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Unrecognized field name %s in ORDER BY.",
+                      def->table_name[0] ?
+                      CPLSPrintf("%s.%s", def->table_name, def->field_name)
+                      : def->field_name );
             return CE_Failure;
         }
 
@@ -1225,11 +1208,11 @@ CPLErr swq_select::parse( swq_field_list *field_list,
     int bAllowFieldsInSecondaryTablesInWhere = FALSE;
     if( poParseOptions != NULL )
         bAllowFieldsInSecondaryTablesInWhere = poParseOptions->bAllowFieldsInSecondaryTablesInWhere;
-    if( where_expr != NULL 
+    if( where_expr != NULL
         && where_expr->Check( field_list, bAllowFieldsInSecondaryTablesInWhere, FALSE, poCustomFuncRegistrar ) == SWQ_ERROR )
     {
         return CE_Failure;
     }
-    
+
     return CE_None;
 }
diff --git a/port/GNUmakefile b/port/GNUmakefile
index e9949d2..53f10b8 100644
--- a/port/GNUmakefile
+++ b/port/GNUmakefile
@@ -7,11 +7,11 @@ else
 include GDALmake.opt
 endif
 
-ifeq ($(LIBZ_SETTING),internal) 
-XTRA_OPT =      -I../frmts/zlib 
-else 
-XTRA_OPT = 
-endif 
+ifeq ($(LIBZ_SETTING),internal)
+XTRA_OPT =      -I../frmts/zlib
+else
+XTRA_OPT =
+endif
 
 CPPFLAGS	:= $(CPPFLAGS)	$(CURL_INC) $(XTRA_OPT)
 
@@ -26,7 +26,8 @@ OBJ =	cpl_conv.o cpl_error.o cpl_string.o cplgetsymbol.o cplstringlist.o \
 	cpl_vsil_tar.o cpl_vsil_stdin.o cpl_vsil_buffered_reader.o \
 	cpl_base64.o cpl_vsil_curl.o cpl_vsil_curl_streaming.o \
 	cpl_vsil_cache.o cpl_xml_validate.o cpl_spawn.o \
-	cpl_google_oauth2.o cpl_progress.o cpl_virtualmem.o
+	cpl_google_oauth2.o cpl_progress.o cpl_virtualmem.o cpl_worker_thread_pool.o \
+	cpl_vsil_crypt.o cpl_sha256.o cpl_aws.o cpl_vsi_error.o
 
 ifeq ($(ODBC_SETTING),yes)
 OBJ	:= 	$(OBJ) cpl_odbc.o
@@ -47,6 +48,14 @@ ifeq ($(HAVE_LIBXML2),yes)
 CPPFLAGS	:=	$(CPPFLAGS) $(LIBXML2_INC) -DHAVE_LIBXML2
 endif
 
+ifeq ($(HAVE_CRYPTOPP),yes)
+CPPFLAGS	:=	$(CPPFLAGS) -DHAVE_CRYPTOPP
+endif
+
+ifeq ($(USE_ONLY_CRYPTODLL_ALG),yes)
+CPPFLAGS	:=	$(CPPFLAGS) -DUSE_ONLY_CRYPTODLL_ALG
+endif
+
 default:	$(OBJ:.o=.$(OBJ_EXT))
 
 $(OBJ): cpl_vsi_virtual.h
@@ -57,5 +66,5 @@ clean:
 install:
 	for f in *.h ; do $(INSTALL_DATA) $$f $(DESTDIR)$(INST_INCLUDE) ; done
 
-xmlreformat:	xmlreformat.o 
+xmlreformat:	xmlreformat.o
 	$(CXX) $(CXXFLAGS) xmlreformat.o $(CONFIG_LIBS) -o xmlreformat
diff --git a/port/cpl_atomic_ops.cpp b/port/cpl_atomic_ops.cpp
index 76965be..089d1a6 100644
--- a/port/cpl_atomic_ops.cpp
+++ b/port/cpl_atomic_ops.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_atomic_ops.cpp 28459 2015-02-12 13:48:21Z rouault $
+ * $Id: cpl_atomic_ops.cpp 33646 2016-03-05 15:54:03Z goatbar $
  *
  * Name:     cpl_atomic_ops.cpp
  * Project:  CPL - Common Portability Library
@@ -15,21 +15,23 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
 #include "cpl_atomic_ops.h"
 
+// TODO: If C++11, use #include <atomic>.
+
 #if defined(__MACH__) && defined(__APPLE__)
 
 #include <libkern/OSAtomic.h>
@@ -39,6 +41,11 @@ int CPLAtomicAdd(volatile int* ptr, int increment)
   return OSAtomicAdd32(increment, (int*)(ptr));
 }
 
+int CPLAtomicCompareAndExchange(volatile int* ptr, int oldval, int newval)
+{
+  return OSAtomicCompareAndSwap32(oldval, newval, (int*)(ptr));
+}
+
 #elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
 
 #include <windows.h>
@@ -52,6 +59,11 @@ int CPLAtomicAdd(volatile int* ptr, int increment)
 #endif
 }
 
+int CPLAtomicCompareAndExchange(volatile int* ptr, int oldval, int newval)
+{
+  return (LONG)InterlockedCompareExchange((volatile LONG*)(ptr), (LONG)newval, (LONG)oldval) == (LONG)oldval;
+}
+
 #elif defined(__MINGW32__) && defined(__i386__)
 
 #include <windows.h>
@@ -61,6 +73,11 @@ int CPLAtomicAdd(volatile int* ptr, int increment)
   return InterlockedExchangeAdd((LONG*)(ptr), (LONG)(increment)) + increment;
 }
 
+int CPLAtomicCompareAndExchange(volatile int* ptr, int oldval, int newval)
+{
+  return (LONG)InterlockedCompareExchange((LONG*)(ptr), (LONG)newval, (LONG)oldval) == (LONG)oldval;
+}
+
 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
 
 int CPLAtomicAdd(volatile int* ptr, int increment)
@@ -72,6 +89,20 @@ int CPLAtomicAdd(volatile int* ptr, int increment)
   return temp + increment;
 }
 
+int CPLAtomicCompareAndExchange(volatile int* ptr, int oldval, int newval)
+{
+    unsigned char ret;
+
+    __asm__ __volatile__ (
+    " lock; cmpxchgl %2,%1\n"
+    " sete %0\n"
+    : "=q" (ret), "=m" (*ptr)
+    : "r" (newval), "m" (*ptr), "a" (oldval)
+    : "memory");
+
+    return (int) ret;
+}
+
 #elif defined(HAVE_GCC_ATOMIC_BUILTINS)
 /* Starting with GCC 4.1.0, built-in functions for atomic memory access are provided. */
 /* see http://gcc.gnu.org/onlinedocs/gcc-4.1.0/gcc/Atomic-Builtins.html */
@@ -82,8 +113,13 @@ int CPLAtomicAdd(volatile int* ptr, int increment)
 {
   if (increment > 0)
     return __sync_add_and_fetch(ptr, increment);
-  else
-    return __sync_sub_and_fetch(ptr, -increment);
+
+  return __sync_sub_and_fetch(ptr, -increment);
+}
+
+int CPLAtomicCompareAndExchange(volatile int* ptr, int oldval, int newval)
+{
+    return __sync_bool_compare_and_swap (ptr, oldval, newval);
 }
 
 #elif !defined(CPL_MULTIPROC_PTHREAD)
@@ -95,18 +131,40 @@ int CPLAtomicAdd(volatile int* ptr, int increment)
     (*ptr) += increment;
     return *ptr;
 }
+
+int CPLAtomicCompareAndExchange(volatile int* ptr, int oldval, int newval)
+{
+    if( *ptr == oldval )
+    {
+        *ptr = newval;
+        return TRUE;
+    }
+    return FALSE;
+}
+
 #else
 
 #include "cpl_multiproc.h"
 
-static CPLMutex *hAtomicOpMutex = NULL;
+static CPLLock *hAtomicOpLock = NULL;
 
-/* Slow, but safe, implemenation using a mutex */
+// Slow, but safe, implementation using a mutex.
 int CPLAtomicAdd(volatile int* ptr, int increment)
 {
-    CPLMutexHolder oMutex(&hAtomicOpMutex);
+    CPLLockHolderD(&hAtomicOpLock, LOCK_SPIN);
     (*ptr) += increment;
     return *ptr;
 }
 
+int CPLAtomicCompareAndExchange(volatile int* ptr, int oldval, int newval)
+{
+    CPLLockHolderD(&hAtomicOpLock, LOCK_SPIN);
+    if( *ptr == oldval )
+    {
+        *ptr = newval;
+        return TRUE;
+    }
+    return FALSE;
+}
+
 #endif
diff --git a/port/cpl_atomic_ops.h b/port/cpl_atomic_ops.h
index efe9193..6a07d2c 100644
--- a/port/cpl_atomic_ops.h
+++ b/port/cpl_atomic_ops.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_atomic_ops.h 27869 2014-10-17 02:22:42Z rouault $
+ * $Id: cpl_atomic_ops.h 33666 2016-03-07 05:21:07Z goatbar $
  *
  * Name:     cpl_atomic_ops.h
  * Project:  CPL - Common Portability Library
@@ -15,21 +15,21 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _CPL_ATOMIC_OPS_INCLUDED
-#define _CPL_ATOMIC_OPS_INCLUDED
+#ifndef CPL_ATOMIC_OPS_INCLUDED
+#define CPL_ATOMIC_OPS_INCLUDED
 
 #include "cpl_port.h"
 
@@ -67,7 +67,7 @@ int CPL_DLL CPLAtomicAdd(volatile int* ptr, int increment);
   *      operation
   *
   * @param ptr a pointer to an integer to increment
-  * @return the pointed value AFTER the opeation: *ptr + 1
+  * @return the pointed value AFTER the operation: *ptr + 1
   */
 #define CPLAtomicInc(ptr) CPLAtomicAdd(ptr, 1)
 
@@ -78,10 +78,29 @@ int CPL_DLL CPLAtomicAdd(volatile int* ptr, int increment);
   *      operation
   *
   * @param ptr a pointer to an integer to decrement
-  * @return the pointed value AFTER the opeation: *ptr - 1
+  * @return the pointed value AFTER the operation: *ptr - 1
   */
 #define CPLAtomicDec(ptr) CPLAtomicAdd(ptr, -1)
 
+
+/** Compares *ptr with oldval. If *ptr == oldval, then *ptr is assigned
+  * newval and TRUE is returned. Otherwise nothing is done, and FALSE is returned.
+  *
+  * Current platforms/architectures where an efficient implementation
+  * exists are MacOSX, MS Windows, i386/x86_64 with GCC and platforms
+  * supported by GCC 4.1 or higher. For other platforms supporting
+  * the pthread library, and when GDAL is configured with thread-support,
+  * the atomicity will be done with a mutex, but with
+  * reduced efficiently. For the remaining platforms, a simple addition
+  * with no locking will be done...
+  *
+  * @param ptr a pointer to an integer (aligned on 32bit boundary).
+  * @param oldval old value
+  * @param newval new value
+  * @return TRUE if the exchange has been done
+  */
+int CPLAtomicCompareAndExchange(volatile int* ptr, int oldval, int newval);
+
 CPL_C_END
 
-#endif /* _CPL_ATOMIC_OPS_INCLUDED */
+#endif /* CPL_ATOMIC_OPS_INCLUDED */
diff --git a/port/cpl_aws.cpp b/port/cpl_aws.cpp
new file mode 100644
index 0000000..75e203d
--- /dev/null
+++ b/port/cpl_aws.cpp
@@ -0,0 +1,643 @@
+/**********************************************************************
+ * $Id: cpl_aws.cpp 33758 2016-03-21 09:06:22Z rouault $
+ *
+ * Name:     cpl_aws.cpp
+ * Project:  CPL - Common Portability Library
+ * Purpose:  Amazon Web Services routines
+ * Author:   Even Rouault <even.rouault at spatialys.com>
+ *
+ **********************************************************************
+ * Copyright (c) 2015, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_aws.h"
+#include "cpl_vsi_error.h"
+#include "cpl_sha256.h"
+#include "cpl_time.h"
+#include "cpl_minixml.h"
+#include <algorithm>
+
+CPL_CVSID("$Id: cpl_aws.cpp 33758 2016-03-21 09:06:22Z rouault $");
+
+//#define DEBUG_VERBOSE 1
+
+/************************************************************************/
+/*                         CPLGetLowerCaseHex()                         */
+/************************************************************************/
+
+static CPLString CPLGetLowerCaseHex( const GByte *pabyData, size_t nBytes )
+
+{
+    CPLString osRet;
+    osRet.resize(nBytes * 2);
+
+    static const char achHex[] = "0123456789abcdef";
+
+    for( size_t i = 0; i < nBytes; ++i )
+    {
+        int nLow = pabyData[i] & 0x0f;
+        int nHigh = (pabyData[i] & 0xf0) >> 4;
+
+        osRet[i*2] = achHex[nHigh];
+        osRet[i*2+1] = achHex[nLow];
+    }
+
+    return osRet;
+}
+
+/************************************************************************/
+/*                       CPLGetLowerCaseHexSHA256()                     */
+/************************************************************************/
+
+CPLString CPLGetLowerCaseHexSHA256( const void *pabyData, size_t nBytes )
+{
+    GByte hash[CPL_SHA256_HASH_SIZE];
+    CPL_SHA256((const GByte*)pabyData, nBytes, hash);
+    return CPLGetLowerCaseHex(hash, CPL_SHA256_HASH_SIZE);
+}
+
+/************************************************************************/
+/*                       CPLGetLowerCaseHexSHA256()                     */
+/************************************************************************/
+
+CPLString CPLGetLowerCaseHexSHA256( const CPLString& osStr )
+{
+    return CPLGetLowerCaseHexSHA256(osStr.c_str(), osStr.size());
+}
+
+/************************************************************************/
+/*                       CPLAWSURLEncode()                              */
+/************************************************************************/
+
+CPLString CPLAWSURLEncode(const CPLString& osURL, bool bEncodeSlash)
+{
+    CPLString osRet;
+    for( size_t i = 0; i < osURL.size(); i++ )
+    {
+        char ch = osURL[i];
+        if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') ||
+            (ch >= '0' && ch <= '9') || ch == '_' || ch == '-' || ch == '~' || ch == '.')
+        {
+            osRet += ch;
+        }
+        else if (ch == '/')
+        {
+            if( bEncodeSlash )
+                osRet += "%2F";
+            else
+                osRet += ch;
+        }
+        else
+        {
+            osRet += CPLSPrintf("%02X", ch);
+        }
+    }
+    return osRet;
+}
+
+/************************************************************************/
+/*                CPLGetAWS_SIGN4_Authorization()                       */
+/************************************************************************/
+
+/* See http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html */
+CPLString CPLGetAWS_SIGN4_Authorization(const CPLString& osSecretAccessKey,
+                                           const CPLString& osAccessKeyId,
+                                           const CPLString& osAccessToken,
+                                           const CPLString& osAWSRegion,
+                                           const CPLString& osService,
+                                           const CPLString& osVerb,
+                                           const CPLString& osHost,
+                                           const CPLString& osCanonicalURI,
+                                           const CPLString& osCanonicalQueryString,
+                                           const CPLString& osXAMZContentSHA256,
+                                           const CPLString& osTimestamp)
+{
+/* -------------------------------------------------------------------- */
+/*      Compute canonical request string.                               */
+/* -------------------------------------------------------------------- */
+    CPLString osCanonicalRequest;
+    osCanonicalRequest = osVerb + "\n";
+
+    osCanonicalRequest += osCanonicalURI + "\n";
+
+    osCanonicalRequest += osCanonicalQueryString + "\n";
+
+    CPLString osCanonicalHeaders;
+    osCanonicalHeaders += "host:";
+    osCanonicalHeaders += osHost;
+    osCanonicalHeaders += "\n";
+    osCanonicalHeaders += "x-amz-content-sha256:";
+    osCanonicalHeaders += osXAMZContentSHA256;
+    osCanonicalHeaders += "\n";
+    osCanonicalHeaders += "x-amz-date:";
+    osCanonicalHeaders += osTimestamp;
+    osCanonicalHeaders += "\n";
+    if( osAccessToken.size() )
+    {
+        osCanonicalHeaders += "x-amz-security-token:";
+        osCanonicalHeaders += osAccessToken;
+        osCanonicalHeaders += "\n";
+    }
+
+    osCanonicalRequest += osCanonicalHeaders + "\n";
+
+    CPLString osSignedHeaders = "host;x-amz-content-sha256;x-amz-date";
+    if( osAccessToken.size() )
+        osSignedHeaders += ";x-amz-security-token";
+    osCanonicalRequest += osSignedHeaders + "\n";
+
+    osCanonicalRequest += osXAMZContentSHA256;
+
+#ifdef DEBUG_VERBOSE
+    CPLDebug("S3", "osCanonicalRequest='%s'\n", osCanonicalRequest.c_str());
+#endif
+
+/* -------------------------------------------------------------------- */
+/*      Compute StringToSign .                                          */
+/* -------------------------------------------------------------------- */
+    CPLString osStringToSign = "AWS4-HMAC-SHA256\n";
+    osStringToSign += osTimestamp + "\n";
+
+    CPLString osYYMMDD(osTimestamp);
+    osYYMMDD.resize(8);
+
+    CPLString osScope = osYYMMDD + "/";
+    osScope += osAWSRegion;
+    osScope += "/";
+    osScope += osService;
+    osScope += "/aws4_request";
+    osStringToSign += osScope + "\n";
+    osStringToSign += CPLGetLowerCaseHexSHA256(osCanonicalRequest);
+
+#ifdef DEBUG_VERBOSE
+    CPLDebug("S3", "osStringToSign='%s'\n", osStringToSign.c_str());
+#endif
+
+/* -------------------------------------------------------------------- */
+/*      Compute signing key.                                            */
+/* -------------------------------------------------------------------- */
+    GByte abySigningKeyIn[CPL_SHA256_HASH_SIZE];
+    GByte abySigningKeyOut[CPL_SHA256_HASH_SIZE];
+
+    CPLString osFirstKey(CPLString("AWS4") + osSecretAccessKey);
+    CPL_HMAC_SHA256( osFirstKey.c_str(), osFirstKey.size(),
+                     osYYMMDD, osYYMMDD.size(),
+                     abySigningKeyOut );
+    memcpy(abySigningKeyIn, abySigningKeyOut, CPL_SHA256_HASH_SIZE);
+
+    CPL_HMAC_SHA256( abySigningKeyIn, CPL_SHA256_HASH_SIZE,
+                     osAWSRegion.c_str(), osAWSRegion.size(),
+                     abySigningKeyOut );
+    memcpy(abySigningKeyIn, abySigningKeyOut, CPL_SHA256_HASH_SIZE);
+
+    CPL_HMAC_SHA256( abySigningKeyIn, CPL_SHA256_HASH_SIZE,
+                     osService.c_str(), osService.size(),
+                     abySigningKeyOut );
+    memcpy(abySigningKeyIn, abySigningKeyOut, CPL_SHA256_HASH_SIZE);
+
+    CPL_HMAC_SHA256( abySigningKeyIn, CPL_SHA256_HASH_SIZE,
+                     "aws4_request", strlen("aws4_request"),
+                     abySigningKeyOut );
+    memcpy(abySigningKeyIn, abySigningKeyOut, CPL_SHA256_HASH_SIZE);
+
+#ifdef DEBUG_VERBOSE
+    CPLString osSigningKey(CPLGetLowerCaseHex(abySigningKeyIn, CPL_SHA256_HASH_SIZE));
+    CPLDebug("S3", "osSigningKey='%s'\n", osSigningKey.c_str());
+#endif
+
+/* -------------------------------------------------------------------- */
+/*      Compute signature.                                              */
+/* -------------------------------------------------------------------- */
+    GByte abySignature[CPL_SHA256_HASH_SIZE];
+    CPL_HMAC_SHA256( abySigningKeyIn, CPL_SHA256_HASH_SIZE,
+                     osStringToSign, osStringToSign.size(),
+                     abySignature);
+    CPLString osSignature(CPLGetLowerCaseHex(abySignature, CPL_SHA256_HASH_SIZE));
+
+#ifdef DEBUG_VERBOSE
+    CPLDebug("S3", "osSignature='%s'\n", osSignature.c_str());
+#endif
+
+/* -------------------------------------------------------------------- */
+/*      Build authorization header.                                     */
+/* -------------------------------------------------------------------- */
+    CPLString osAuthorization;
+    osAuthorization = "AWS4-HMAC-SHA256 Credential=";
+    osAuthorization += osAccessKeyId;
+    osAuthorization += "/";
+    osAuthorization += osYYMMDD;
+    osAuthorization += "/";
+    osAuthorization += osAWSRegion;
+    osAuthorization += "/";
+    osAuthorization += osService;
+    osAuthorization += "/";
+    osAuthorization += "aws4_request";
+    osAuthorization += ",";
+    osAuthorization += "SignedHeaders=";
+    osAuthorization += osSignedHeaders;
+    osAuthorization += ",";
+    osAuthorization += "Signature=";
+    osAuthorization += osSignature;
+
+#ifdef DEBUG_VERBOSE
+    CPLDebug("S3", "osAuthorization='%s'\n", osAuthorization.c_str());
+#endif
+
+    return osAuthorization;
+}
+
+/************************************************************************/
+/*                        CPLGetAWS_SIGN4_Timestamp()                   */
+/************************************************************************/
+
+CPLString CPLGetAWS_SIGN4_Timestamp()
+{
+    struct tm brokenDown;
+    CPLUnixTimeToYMDHMS(time(NULL), &brokenDown);
+
+    char szTimeStamp[4+2+2+1+2+2+2+1+1];
+    snprintf(szTimeStamp, sizeof(szTimeStamp), "%04d%02d%02dT%02d%02d%02dZ",
+            brokenDown.tm_year + 1900,
+            brokenDown.tm_mon + 1,
+            brokenDown.tm_mday,
+            brokenDown.tm_hour,
+            brokenDown.tm_min,
+            brokenDown.tm_sec);
+    return szTimeStamp;
+}
+
+#ifdef HAVE_CURL
+
+/************************************************************************/
+/*                         VSIS3HandleHelper()                          */
+/************************************************************************/
+
+VSIS3HandleHelper::VSIS3HandleHelper(   const CPLString& osSecretAccessKey,
+                                        const CPLString& osAccessKeyId,
+                                        const CPLString& osSessionToken,
+                                        const CPLString& osAWSS3Endpoint,
+                                        const CPLString& osAWSRegion,
+                                        const CPLString& osBucket,
+                                        const CPLString& osObjectKey,
+                                        bool bUseHTTPS, bool bUseVirtualHosting) :
+        m_osURL(BuildURL(osAWSS3Endpoint, osBucket, osObjectKey, bUseHTTPS, bUseVirtualHosting)),
+        m_osSecretAccessKey(osSecretAccessKey),
+        m_osAccessKeyId(osAccessKeyId),
+        m_osSessionToken(osSessionToken),
+        m_osAWSS3Endpoint(osAWSS3Endpoint),
+        m_osAWSRegion(osAWSRegion),
+        m_osBucket(osBucket),
+        m_osObjectKey(osObjectKey),
+        m_bUseHTTPS(bUseHTTPS),
+        m_bUseVirtualHosting(bUseVirtualHosting)
+{
+}
+
+/************************************************************************/
+/*                        ~VSIS3HandleHelper()                          */
+/************************************************************************/
+
+VSIS3HandleHelper::~VSIS3HandleHelper()
+{
+    for(size_t i=0;i<m_osSecretAccessKey.size();i++)
+        m_osSecretAccessKey[i] = 0;
+}
+
+/************************************************************************/
+/*                           BuildURL()                                 */
+/************************************************************************/
+
+CPLString VSIS3HandleHelper::BuildURL(const CPLString& osAWSS3Endpoint,
+                                      const CPLString& osBucket,
+                                      const CPLString& osObjectKey,
+                                      bool bUseHTTPS, bool bUseVirtualHosting)
+{
+    if( bUseVirtualHosting )
+        return CPLSPrintf("%s://%s.%s/%s", (bUseHTTPS) ? "https" : "http",
+                                        osBucket.c_str(),
+                                        osAWSS3Endpoint.c_str(),
+                                        osObjectKey.c_str());
+    else
+        return CPLSPrintf("%s://%s/%s/%s", (bUseHTTPS) ? "https" : "http",
+                                        osAWSS3Endpoint.c_str(),
+                                        osBucket.c_str(),
+                                        osObjectKey.c_str());
+}
+
+/************************************************************************/
+/*                           RebuildURL()                               */
+/************************************************************************/
+
+void VSIS3HandleHelper::RebuildURL()
+{
+    m_osURL = BuildURL(m_osAWSS3Endpoint, m_osBucket, m_osObjectKey, m_bUseHTTPS, m_bUseVirtualHosting);
+    std::map<CPLString, CPLString>::iterator oIter = m_oMapQueryParameters.begin();
+    for( ; oIter != m_oMapQueryParameters.end(); ++oIter )
+    {
+        if( oIter == m_oMapQueryParameters.begin() )
+            m_osURL += "?";
+        else
+            m_osURL += "&";
+        m_osURL += oIter->first;
+        if( oIter->second.size() )
+        {
+            m_osURL += "=";
+            m_osURL += oIter->second;
+        }
+    }
+}
+
+/************************************************************************/
+/*                        GetBucketAndObjectKey()                       */
+/************************************************************************/
+
+bool VSIS3HandleHelper::GetBucketAndObjectKey(const char* pszURI, const char* pszFSPrefix,
+                                              bool bAllowNoObject,
+                                              CPLString &osBucket, CPLString &osObjectKey)
+{
+    osBucket = pszURI;
+    if( osBucket.size() == 0 )
+    {
+        return false;
+    }
+    size_t nPos = osBucket.find('/');
+    if( nPos == std::string::npos )
+    {
+        if( bAllowNoObject )
+        {
+            osObjectKey = "";
+            return true;
+        }
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Filename should be of the form %sbucket/key", pszFSPrefix);
+        return false;
+    }
+    osBucket.resize(nPos);
+    osObjectKey = pszURI + nPos + 1;
+    return true;
+}
+
+/************************************************************************/
+/*                          BuildFromURI()                              */
+/************************************************************************/
+
+VSIS3HandleHelper* VSIS3HandleHelper::BuildFromURI(const char* pszURI,
+                                                   const char* pszFSPrefix,
+                                                   bool bAllowNoObject)
+{
+    CPLString osSecretAccessKey = CPLGetConfigOption("AWS_SECRET_ACCESS_KEY", "");
+    if( osSecretAccessKey.size() == 0 )
+    {
+        VSIError(VSIE_AWSInvalidCredentials,
+                 "AWS_SECRET_ACCESS_KEY configuration option not defined");
+        return NULL;
+    }
+    CPLString osAccessKeyId = CPLGetConfigOption("AWS_ACCESS_KEY_ID", "");
+    if( osAccessKeyId.size() == 0 )
+    {
+        VSIError(VSIE_AWSInvalidCredentials,
+                 "AWS_ACCESS_KEY_ID configuration option not defined");
+        return NULL;
+    }
+    CPLString osSessionToken = CPLGetConfigOption("AWS_SESSION_TOKEN", "");
+    CPLString osAWSS3Endpoint = CPLGetConfigOption("AWS_S3_ENDPOINT", "s3.amazonaws.com");
+    CPLString osAWSRegion = CPLGetConfigOption("AWS_REGION", "us-east-1");
+    CPLString osBucket, osObjectKey;
+    if( !GetBucketAndObjectKey(pszURI, pszFSPrefix, bAllowNoObject, osBucket, osObjectKey) )
+    {
+        return NULL;
+    }
+    bool bUseHTTPS = CPL_TO_BOOL(CSLTestBoolean(CPLGetConfigOption("AWS_HTTPS", "YES")));
+    bool bIsValidNameForVirtualHosting = (osBucket.find('.') == std::string::npos);
+    bool bUseVirtualHosting = CPL_TO_BOOL(CSLTestBoolean(
+            CPLGetConfigOption("AWS_VIRTUAL_HOSTING",
+                               bIsValidNameForVirtualHosting ? "TRUE" : "FALSE")));
+    return new VSIS3HandleHelper(osSecretAccessKey, osAccessKeyId, osSessionToken,
+                                    osAWSS3Endpoint, osAWSRegion,
+                                    osBucket, osObjectKey, bUseHTTPS, bUseVirtualHosting);
+}
+
+/************************************************************************/
+/*                       ResetQueryParameters()                         */
+/************************************************************************/
+
+void VSIS3HandleHelper::ResetQueryParameters()
+{
+    m_oMapQueryParameters.clear();
+    RebuildURL();
+}
+
+/************************************************************************/
+/*                         AddQueryParameter()                          */
+/************************************************************************/
+
+void VSIS3HandleHelper::AddQueryParameter(const CPLString& osKey, const CPLString& osValue)
+{
+    m_oMapQueryParameters[osKey] = osValue;
+    RebuildURL();
+}
+
+/************************************************************************/
+/*                           GetCurlHeaders()                           */
+/************************************************************************/
+
+struct curl_slist* VSIS3HandleHelper::GetCurlHeaders(const CPLString& osVerb,
+                                                     const void *pabyDataContent,
+                                                     size_t nBytesContent)
+{
+    CPLString osXAMZDate = CPLGetConfigOption("AWS_TIMESTAMP", "");
+    if( osXAMZDate.size() == 0 )
+        osXAMZDate = CPLGetAWS_SIGN4_Timestamp();
+
+    CPLString osXAMZContentSHA256 = CPLGetLowerCaseHexSHA256(pabyDataContent, nBytesContent);
+
+    CPLString osCanonicalQueryString;
+    std::map<CPLString, CPLString>::iterator oIter = m_oMapQueryParameters.begin();
+    for( ; oIter != m_oMapQueryParameters.end(); ++oIter )
+    {
+        if( osCanonicalQueryString.size() )
+            osCanonicalQueryString += "&";
+        osCanonicalQueryString += oIter->first;
+        osCanonicalQueryString += "=";
+        osCanonicalQueryString += CPLAWSURLEncode(oIter->second);
+    }
+
+    CPLString osAuthorization = CPLGetAWS_SIGN4_Authorization(
+            m_osSecretAccessKey,
+            m_osAccessKeyId,
+            m_osSessionToken,
+            m_osAWSRegion,
+            "s3",
+            osVerb,
+            (m_bUseVirtualHosting) ? m_osBucket + "." + m_osAWSS3Endpoint : m_osAWSS3Endpoint,
+            (m_bUseVirtualHosting) ? ("/" + m_osObjectKey).c_str() : ("/" + m_osBucket + "/" + m_osObjectKey).c_str(),
+            osCanonicalQueryString,
+            osXAMZContentSHA256,
+            osXAMZDate);
+
+    struct curl_slist *headers=NULL;
+    headers = curl_slist_append(headers,
+                                CPLSPrintf("x-amz-date: %s", osXAMZDate.c_str()));
+    headers = curl_slist_append(headers,
+                                CPLSPrintf("x-amz-content-sha256: %s", osXAMZContentSHA256.c_str()));
+    if( m_osSessionToken.size() )
+        headers = curl_slist_append(headers,
+                                CPLSPrintf("X-Amz-Security-Token: %s", m_osSessionToken.c_str()));
+    headers = curl_slist_append(headers,
+                                CPLSPrintf("Authorization: %s", osAuthorization.c_str()));
+    return headers;
+}
+
+/************************************************************************/
+/*                          CanRestartOnError()                         */
+/************************************************************************/
+
+bool VSIS3HandleHelper::CanRestartOnError(const char* pszErrorMsg, bool bSetError)
+{
+#ifdef DEBUG_VERBOSE
+    CPLDebug("S3", "%s", pszErrorMsg);
+#endif
+
+    if( !STARTS_WITH(pszErrorMsg, "<?xml") )
+    {
+        if(bSetError) { VSIError(VSIE_AWSError, "Invalid AWS response: %s", pszErrorMsg); }
+        return false;
+    }
+
+    CPLXMLNode* psTree = CPLParseXMLString(pszErrorMsg);
+    if( psTree == NULL )
+    {
+        if(bSetError) { VSIError(VSIE_AWSError, "Malformed AWS XML repsonse: %s", pszErrorMsg); }
+        return false;
+    }
+
+    const char* pszCode = CPLGetXMLValue(psTree, "=Error.Code", NULL);
+    if( pszCode == NULL )
+    {
+        CPLDestroyXMLNode(psTree);
+        if(bSetError) { VSIError(VSIE_AWSError, "Malformed AWS XML repsonse: %s", pszErrorMsg); }
+        return false;
+    }
+
+    if( EQUAL(pszCode, "AuthorizationHeaderMalformed") )
+    {
+        const char* pszRegion = CPLGetXMLValue(psTree, "=Error.Region", NULL);
+        if( pszRegion == NULL )
+        {
+            CPLDestroyXMLNode(psTree);
+            if(bSetError) { VSIError(VSIE_AWSError, "Malformed AWS XML repsonse: %s", pszErrorMsg); }
+            return false;
+        }
+        SetAWSRegion(pszRegion);
+        CPLDebug("S3", "Switching to region %s", m_osAWSRegion.c_str());
+        CPLDestroyXMLNode(psTree);
+        return true;
+    }
+
+    if( EQUAL(pszCode, "PermanentRedirect") )
+    {
+        const char* pszEndpoint = CPLGetXMLValue(psTree, "=Error.Endpoint", NULL);
+        if( pszEndpoint == NULL ||
+            (m_bUseVirtualHosting && (strncmp(pszEndpoint, m_osBucket.c_str(), m_osBucket.size()) != 0 ||
+                                    pszEndpoint[m_osBucket.size()] != '.')) )
+        {
+            CPLDestroyXMLNode(psTree);
+            if(bSetError) { VSIError(VSIE_AWSError, "Malformed AWS XML repsonse: %s", pszErrorMsg); }
+            return false;
+        }
+        if( !m_bUseVirtualHosting &&
+            strncmp(pszEndpoint, m_osBucket.c_str(), m_osBucket.size()) == 0 &&
+            pszEndpoint[m_osBucket.size()] == '.' )
+        {
+            m_bUseVirtualHosting = true;
+            CPLDebug("S3", "Switching to virtual hosting");
+        }
+        SetAWSS3Endpoint((m_bUseVirtualHosting) ? pszEndpoint + m_osBucket.size() + 1 : pszEndpoint);
+        CPLDebug("S3", "Switching to endpoint %s", m_osAWSS3Endpoint.c_str());
+        CPLDestroyXMLNode(psTree);
+        return true;
+    }
+
+    if(bSetError) {
+        /*
+         * Translate AWS errors into VSI errors
+         */
+        const char* pszMessage = CPLGetXMLValue(psTree, "=Error.Message", NULL);
+
+        if( pszMessage == NULL ) {
+            VSIError(VSIE_AWSError, "%s", pszErrorMsg);
+        } else if( EQUAL(pszCode, "AccessDenied") ) {
+            VSIError(VSIE_AWSAccessDenied, "%s", pszMessage);
+        } else if( EQUAL(pszCode, "NoSuchBucket") ) {
+            VSIError(VSIE_AWSBucketNotFound, "%s", pszMessage);
+        } else if( EQUAL(pszCode, "NoSuchKey") ) {
+            VSIError(VSIE_AWSObjectNotFound, "%s", pszMessage);
+        } else if( EQUAL(pszCode, "SignatureDoesNotMatch") ) {
+            VSIError(VSIE_AWSSignatureDoesNotMatch, "%s", pszMessage);
+        } else {
+            VSIError(VSIE_AWSError, "%s", pszMessage);
+        }
+    }
+
+    CPLDestroyXMLNode(psTree);
+
+    return false;
+}
+
+/************************************************************************/
+/*                          SetAWSS3Endpoint()                          */
+/************************************************************************/
+
+void VSIS3HandleHelper::SetAWSS3Endpoint(const CPLString &osStr)
+{
+    m_osAWSS3Endpoint = osStr;
+    RebuildURL();
+}
+
+/************************************************************************/
+/*                           SetAWSRegion()                             */
+/************************************************************************/
+
+void VSIS3HandleHelper::SetAWSRegion(const CPLString &osStr)
+{
+    m_osAWSRegion = osStr;
+}
+/************************************************************************/
+/*                         SetVirtualHosting()                          */
+/************************************************************************/
+
+void VSIS3HandleHelper::SetVirtualHosting(bool b)
+{
+    m_bUseVirtualHosting = b;
+    RebuildURL();
+}
+
+/************************************************************************/
+/*                           SetObjectKey()                             */
+/************************************************************************/
+
+void VSIS3HandleHelper::SetObjectKey(const CPLString &osStr)
+{
+    m_osObjectKey = osStr;
+    RebuildURL();
+}
+
+#endif
diff --git a/port/cpl_aws.h b/port/cpl_aws.h
new file mode 100644
index 0000000..854ada6
--- /dev/null
+++ b/port/cpl_aws.h
@@ -0,0 +1,136 @@
+/**********************************************************************
+ * $Id: cpl_aws.h 33758 2016-03-21 09:06:22Z rouault $
+ *
+ * Name:     cpl_aws.h
+ * Project:  CPL - Common Portability Library
+ * Purpose:  Amazon Web Services routines
+ * Author:   Even Rouault <even.rouault at spatialys.com>
+ *
+ **********************************************************************
+ * Copyright (c) 2015, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef CPL_AWS_INCLUDED_H
+#define CPL_AWS_INCLUDED_H
+
+#include "cpl_string.h"
+
+CPLString CPLGetAWS_SIGN4_Authorization(const CPLString& osSecretAccessKey,
+                                        const CPLString& osAccessKeyId,
+                                        const CPLString& osAccessToken,
+                                        const CPLString& osAWSRegion,
+                                        const CPLString& osService,
+                                        const CPLString& osVerb,
+                                        const CPLString& osHost,
+                                        const CPLString& osCanonicalURI,
+                                        const CPLString& osCanonicalQueryString,
+                                        const CPLString& osXAMZContentSHA256,
+                                        const CPLString& osTimestamp);
+
+CPLString CPLGetLowerCaseHexSHA256( const void *pabyData, size_t nBytes );
+CPLString CPLGetLowerCaseHexSHA256( const CPLString& osStr );
+
+CPLString CPLGetAWS_SIGN4_Timestamp();
+
+CPLString CPLAWSURLEncode(const CPLString& osURL, bool bEncodeSlash = true);
+
+#ifdef HAVE_CURL
+
+#include <curl/curl.h>
+#include <map>
+
+class VSIS3HandleHelper
+{
+        CPLString m_osURL;
+        CPLString m_osSecretAccessKey;
+        CPLString m_osAccessKeyId;
+        CPLString m_osSessionToken;
+        CPLString m_osAWSS3Endpoint;
+        CPLString m_osAWSRegion;
+        CPLString m_osBucket;
+        CPLString m_osObjectKey;
+        bool m_bUseHTTPS;
+        bool m_bUseVirtualHosting;
+        std::map<CPLString, CPLString> m_oMapQueryParameters;
+
+        static bool GetBucketAndObjectKey(const char* pszURI, const char* pszFSPrefix,
+                                          bool bAllowNoObject,
+                                          CPLString &osBucketOut, CPLString &osObjectKeyOut);
+        void RebuildURL();
+
+  protected:
+
+    public:
+        VSIS3HandleHelper(const CPLString& osSecretAccessKey,
+                    const CPLString& osAccessKeyId,
+                    const CPLString& osSessionToken,
+                    const CPLString& osAWSS3Endpoint,
+                    const CPLString& osAWSRegion,
+                    const CPLString& osBucket,
+                    const CPLString& osObjectKey,
+                    bool bUseHTTPS, bool bUseVirtualHosting);
+       ~VSIS3HandleHelper();
+
+        static VSIS3HandleHelper* BuildFromURI(const char* pszURI, const char* pszFSPrefix,
+                                               bool bAllowNoObject);
+        static CPLString BuildURL(const CPLString& osAWSS3Endpoint,
+                                  const CPLString& osBucket,
+                                  const CPLString& osObjectKey,
+                                  bool bUseHTTPS, bool bUseVirtualHosting);
+
+        void ResetQueryParameters();
+        void AddQueryParameter(const CPLString& osKey, const CPLString& osValue);
+        struct curl_slist* GetCurlHeaders(const CPLString& osVerb,
+                                          const void *pabyDataContent = NULL,
+                                          size_t nBytesContent = 0);
+        bool CanRestartOnError(const char* pszErrorMsg) { return CanRestartOnError(pszErrorMsg, false); }
+        bool CanRestartOnError(const char*, bool bSetError);
+
+        const CPLString& GetURL() const { return m_osURL; }
+        const CPLString& GetBucket() const { return m_osBucket; }
+        const CPLString& GetObjectKey() const { return m_osObjectKey; }
+        const CPLString& GetAWSS3Endpoint()const  { return m_osAWSS3Endpoint; }
+        const CPLString& GetAWSRegion() const { return m_osAWSRegion; }
+        bool GetVirtualHosting() const { return m_bUseVirtualHosting; }
+        void SetAWSS3Endpoint(const CPLString &osStr);
+        void SetAWSRegion(const CPLString &osStr);
+        void SetVirtualHosting(bool b);
+        void SetObjectKey(const CPLString &osStr);
+};
+
+class VSIS3UpdateParams
+{
+    public:
+        CPLString m_osAWSRegion;
+        CPLString m_osAWSS3Endpoint;
+        bool m_bUseVirtualHosting;
+
+        VSIS3UpdateParams(const CPLString& osAWSRegion = "",
+                          const CPLString& osAWSS3Endpoint = "",
+                          bool bUseVirtualHosting = false) :
+            m_osAWSRegion(osAWSRegion),
+            m_osAWSS3Endpoint(osAWSS3Endpoint),
+            m_bUseVirtualHosting(bUseVirtualHosting) {}
+};
+
+#endif /* HAVE_CURL */
+
+#endif /* CPL_AWS_INCLUDED_H */
diff --git a/port/cpl_base64.cpp b/port/cpl_base64.cpp
index b3946bc..5969997 100644
--- a/port/cpl_base64.cpp
+++ b/port/cpl_base64.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_base64.cpp 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: cpl_base64.cpp 31561 2015-11-17 15:51:25Z goatbar $
  *
  * Project:  Common Portability Library
  * Purpose:  Encoding/Decoding Base64 strings
@@ -36,7 +36,7 @@
 
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: cpl_base64.cpp 27044 2014-03-16 23:41:27Z rouault $");
+CPL_CVSID("$Id: cpl_base64.cpp 31561 2015-11-17 15:51:25Z goatbar $");
 
 /* Derived from MapServer's mappostgis.c */
 
@@ -63,7 +63,8 @@ static const unsigned char CPLBase64DecodeChar[256] = {
     /* not Base64 characters */
     64,64,64,64,64,64,
     /* a-z */
-    26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,
+    26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,
+    51,
     /* not Base64 characters */
     64,64,64,64,64,
     /* not Base64 characters (upper 128 characters) */
@@ -87,63 +88,55 @@ static const unsigned char CPLBase64DecodeChar[256] = {
 int CPLBase64DecodeInPlace(GByte* pszBase64)
 {
     if (pszBase64 && *pszBase64) {
-
         unsigned char *p = pszBase64;
-        int i, j, k;
+        int offset_1 = 0;
+        int offset_2 = 0;
 
         /* Drop illegal chars first */
-        for (i=0, j=0; pszBase64[i]; i++) {
-            unsigned char c = pszBase64[i];
+        for ( ; pszBase64[offset_1]; ++offset_1) {
+            unsigned char c = pszBase64[offset_1];
             if ( (CPLBase64DecodeChar[c] != 64) || (c == '=') ) {
-                pszBase64[j++] = c;
+                pszBase64[offset_2++] = c;
             }
         }
 
-        for (k=0; k<j; k+=4) {
-            register unsigned char b1, b2, b3, b4, c3, c4;
-
-            b1 = CPLBase64DecodeChar[pszBase64[k]];
-
-            if (k+3<j) {
-                b2 = CPLBase64DecodeChar[pszBase64[k+1]];
-                c3 = pszBase64[k+2];
-                c4 = pszBase64[k+3];
-            }
-            else if (k+2<j) {
-                b2 = CPLBase64DecodeChar[pszBase64[k+1]];
-                c3 = pszBase64[k+2];
-                c4 = 'A';
-            }
-            else if (k+1<j) {
-                b2 = CPLBase64DecodeChar[pszBase64[k+1]];
-                c3 = 'A';
-                c4 = 'A';
-            }
-            else
-            {
-                b2 = 0;
+        for (int idx = 0; idx < offset_2; idx += 4) {
+            unsigned char b1 = CPLBase64DecodeChar[pszBase64[idx]];
+            unsigned char b2 = 0;
+            unsigned char c3 = 'A';
+            unsigned char c4 = 'A';
+
+            if (idx + 3 < offset_2) {
+                b2 = CPLBase64DecodeChar[pszBase64[idx+1]];
+                c3 = pszBase64[idx+2];
+                c4 = pszBase64[idx+3];
+            } else if (idx + 2 < offset_2) {
+                b2 = CPLBase64DecodeChar[pszBase64[idx+1]];
+                c3 = pszBase64[idx+2];
+            } else if (idx + 1 < offset_2) {
+                b2 = CPLBase64DecodeChar[pszBase64[idx+1]];
                 c3 = 'A';
-                c4 = 'A';
-            }
+            }  // Else: Use the default values.
+
 
-            b3 = CPLBase64DecodeChar[c3];
-            b4 = CPLBase64DecodeChar[c4];
+            const unsigned char b3 = CPLBase64DecodeChar[c3];
+            const unsigned char b4 = CPLBase64DecodeChar[c4];
 
-            *p++=((b1<<2)|(b2>>4) );
-            if( p - pszBase64 == i )
+            *p++ = ( (b1 << 2) | (b2 >> 4) );
+            if (p - pszBase64 == offset_1)
                 break;
             if (c3 != '=') {
-                *p++=(((b2&0xf)<<4)|(b3>>2) );
-                if( p - pszBase64 == i )
+                *p++ = ( ((b2 & 0xf) << 4) | (b3 >> 2) );
+                if (p - pszBase64 == offset_1)
                     break;
             }
             if (c4 != '=') {
-                *p++=(((b3&0x3)<<6)|b4 );
-                if( p - pszBase64 == i )
+                *p++ = ( ((b3 & 0x3) << 6) | b4);
+                if (p - pszBase64 == offset_1)
                     break;
             }
         }
-        return(p-pszBase64);
+        return static_cast<int>(p-pszBase64);
     }
     return 0;
 }
@@ -151,7 +144,8 @@ int CPLBase64DecodeInPlace(GByte* pszBase64)
 /*
  * This function was extracted from the base64 cpp utility published by
  * René Nyffenegger. The code was modified into a form suitable for use in
- * CPL.  The original code can be found at 
+ * CPL.  The original code can be found at:
+ *
  * http://www.adp-gmbh.ch/cpp/common/base64.html.
  *
  * The following is the original notice of this function.
@@ -169,9 +163,9 @@ int CPLBase64DecodeInPlace(GByte* pszBase64)
  *  freely, subject to the following restrictions:
  *
  *  1. The origin of this source code must not be misrepresented; you must not
- *     claim that you wrote the original source code. If you use this source code
- *     in a product, an acknowledgment in the product documentation would be
- *     appreciated but is not required.
+ *     claim that you wrote the original source code. If you use this source
+ *     code in a product, an acknowledgment in the product documentation would
+ *     be appreciated but is not required.
  *
  *  2. Altered source versions must be plainly marked as such, and must not be
  *     misrepresented as being the original source code.
@@ -185,58 +179,57 @@ int CPLBase64DecodeInPlace(GByte* pszBase64)
 /*                          CPLBase64Encode()                           */
 /************************************************************************/
 
-char *CPLBase64Encode( int nDataLen, const GByte *pabyBytesToEncode )
+char *CPLBase64Encode(int nDataLen, const GByte *pabyBytesToEncode) {
+    static const char base64Chars[] =
+        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
-{
-    static const std::string base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+    const int kCharArray3Size = 3;
+    const int kCharArray4Size = 4;
+    unsigned char charArray3[kCharArray3Size];
 
-    int           i = 0;
-    int           j = 0;
-    std::string   result("");
-    unsigned char charArray3[3];
-    unsigned char charArray4[4];
+    std::string result("");
+    int array3_idx = 0;
+    while (nDataLen--) {
+        charArray3[array3_idx++] = *(pabyBytesToEncode++);
 
-    while( nDataLen-- )
-    {
-        charArray3[i++] = *(pabyBytesToEncode++);
+        if (array3_idx == kCharArray3Size) {
+            unsigned char charArray4[kCharArray4Size];
 
-        if( i == 3 )
-        {
             charArray4[0] = (charArray3[0] & 0xfc) >> 2;
-            charArray4[1] = ((charArray3[0] & 0x03) << 4) + ((charArray3[1] & 0xf0) >> 4);
-            charArray4[2] = ((charArray3[1] & 0x0f) << 2) + ((charArray3[2] & 0xc0) >> 6);
+            charArray4[1] = ((charArray3[0] & 0x03) << 4)
+                + ((charArray3[1] & 0xf0) >> 4);
+            charArray4[2] = ((charArray3[1] & 0x0f) << 2)
+                + ((charArray3[2] & 0xc0) >> 6);
             charArray4[3] = charArray3[2] & 0x3f;
 
-            for( i = 0; i < 4; i++ )
-            {
-                result += base64Chars[charArray4[i]];
+            for (int idx = 0; idx < kCharArray4Size; ++idx) {
+                result += base64Chars[charArray4[idx]];
             }
 
-            i = 0;
+            array3_idx = 0;
         }
     }
 
-    if( i )
-    {
-        for( j = i; j < 3; j++ )
-        {
-            charArray3[j] = '\0';
+    if (array3_idx) {
+        for (int idx = array3_idx; idx < kCharArray3Size; ++idx) {
+            charArray3[idx] = '\0';
         }
 
+        unsigned char charArray4[kCharArray4Size];
         charArray4[0] = (charArray3[0]  & 0xfc) >> 2;
-        charArray4[1] = ((charArray3[0] & 0x03) << 4) + ((charArray3[1] & 0xf0) >> 4);
-        charArray4[2] = ((charArray3[1] & 0x0f) << 2) + ((charArray3[2] & 0xc0) >> 6);
+        charArray4[1] = ((charArray3[0] & 0x03) << 4)
+            + ((charArray3[1] & 0xf0) >> 4);
+        charArray4[2] = ((charArray3[1] & 0x0f) << 2)
+            + ((charArray3[2] & 0xc0) >> 6);
         charArray4[3] = charArray3[2] & 0x3f;
 
-        for ( j = 0; j < (i + 1); j++ )
-        {
-            result += base64Chars[charArray4[j]];
+        for (int idx = 0; idx < (array3_idx + 1); ++idx) {
+            result += base64Chars[charArray4[idx]];
         }
 
-        while( i++ < 3 )
+        while (array3_idx++ < kCharArray3Size)
             result += '=';
     }
 
-    return (CPLStrdup(result.c_str()));
+    return CPLStrdup(result.c_str());
 }
-
diff --git a/port/cpl_config.h.in b/port/cpl_config.h.in
index 313729f..1795d08 100644
--- a/port/cpl_config.h.in
+++ b/port/cpl_config.h.in
@@ -58,7 +58,7 @@
 /* Define if you have the iconv() function and it works. */
 #undef HAVE_ICONV
 
-/* Define as 0 or 1 according to the floating point format suported by the
+/* Define as 0 or 1 according to the floating point format supported by the
    machine */
 #undef HAVE_IEEEFP
 
@@ -149,6 +149,12 @@
 /* Define to 1 if you have the `vfork' function. */
 #undef HAVE_VFORK
 
+/* Define to 1 if you have the `mmap' function. */
+#undef HAVE_MMAP
+
+/* Define to 1 if you have the statvfs' function. */
+#undef HAVE_STATVFS
+
 /* Define to 1 if you have the `lstat' function. */
 #undef HAVE_LSTAT
 
@@ -227,6 +233,9 @@
 #undef HAVE_SC_PHYS_PAGES
 
 /* Use this file to override settings in instances where you're doing FAT compiles
-   on Apple.  It is currently off by default because it doesn't seem to work with 
-   newish ( XCode >= 3/28/11) XCodes */
+   on Apple.  It is currently off by default because it doesn't seem to work with
+   XCode >= 3/28/11 */
 /* #include "cpl_config_extras.h" */
+
+/* Define to 1 if you have the `uselocale' function. */
+#undef HAVE_USELOCALE
diff --git a/port/cpl_config.h.vc b/port/cpl_config.h.vc
index 8fd4641..fe7b82a 100644
--- a/port/cpl_config.h.vc
+++ b/port/cpl_config.h.vc
@@ -1,5 +1,5 @@
 
-/* We define this here in general so that a VC++ build will publically
+/* We define this here in general so that a VC++ build will publicly
    declare STDCALL interfaces even if an application is built against it
    using MinGW */
 
@@ -88,7 +88,7 @@
 /* Set the native cpu bit order */
 #define HOST_FILLORDER FILLORDER_LSB2MSB
 
-/* Define as 0 or 1 according to the floating point format suported by the
+/* Define as 0 or 1 according to the floating point format supported by the
    machine */
 #define HAVE_IEEEFP 1
 
diff --git a/port/cpl_config.h.wince b/port/cpl_config.h.wince
deleted file mode 100644
index f856d5e..0000000
--- a/port/cpl_config.h.wince
+++ /dev/null
@@ -1,161 +0,0 @@
-/* $Id: cpl_config.h.wince 14805 2008-07-04 18:55:42Z mloskot $/
-
-/*
- * cpl_config.h with definitions for Windows CE platform.
- */
-#ifndef _WIN32_WCE
-# error This version of cpl_config.h header is dedicated for Windows CE platform!
-#endif
-
-/* Define if you don't have vprintf but do have _doprnt.  */
-#undef HAVE_DOPRNT
-
-/* Define if you have the snprintf function.  */
-#define HAVE_SNPRINTF
-#define snprintf _snprintf
-
-/* Define if you have the vprintf function.  */
-#define HAVE_VPRINTF
-#define HAVE_VSNPRINTF
-#define vsnprintf _vsnprintf
-
-/* Windows CE does not support getcwd function. */
-#undef HAVE_GETCWD
-/* #define getcwd _getcwd */
-
-/* Define if you have the stdicmp function.  */
-#define HAVE_STRICMP
-#define stricmp _stricmp
-
-/* Define if you have the strnicmp function.  */
-#define HAVE_STRNICMP
-#define strnicmp _strnicmp
-
-/* Define if you have the strdup function.  */
-#define HAVE_STRDUP
-#define strdup _strdup
-
-/* Define if you have the strerror function.  */
-#define HAVE_STRERROR
-#define strerror wceex_strerror /* defined in cpl_wince.h */
-
-/* Define if you have the rewind function.  */
-#define HAVE_REWIND
-#define rewind wceex_rewind /* defined in cpl_wince.h */
-
-/* Define if you have the stat function.  */
-#define HAVE_STAT
-#define stat wceex_stat
-
-/* Define if you have the unlink function.  */
-#define HAVE_UNLINK
-#define unlink wceex_unlink
-
-/* Define if you have the mkdir function.  */
-#define HAVE_MKDIR
-#define mkdir wceex_mkdir
-
-/* Define if you have the rmdir function.  */
-#define HAVE_RMDIR
-#define rmdir wceex_rmdir
-
-/* Define if you have the rename function.  */
-#define HAVE_RENAME
-#define rename wceex_rename
-
-/* Define if you have the abort function.  */
-#define HAVE_ABORT
-#define abort wceex_abort
-
-/* Define if you have the _findfirst function.  */
-#define HAVE_FINDFIRST
-#define _findfirst wceex_findfirst
-
-/* Define if you have the _findnext function.  */
-#define HAVE_FINDNEXT
-#define _findnext wceex_findnext
-
-/* Define if you have the _findclose function.  */
-#define HAVE_FINDNEXT
-#define _findclose wceex_findclose
-
-/* Define if you have the time function.  */
-#define HAVE_TIME
-#define time wceex_time /* XXX - mloskot */
-
-/* Define if you have the time function.  */
-#define HAVE_GMTIME
-#define gmtime wceex_gmtime
-
-/* Define if you have the localtime function.  */
-#define HAVE_LOCALTIME
-#define localtime wceex_localtime
-
-/* Define if you have the ctime function.  */
-#define HAVE_CTIME
-#define ctime wceex_ctime
-
-/* Define if you have the ctime function.  */
-/* wceex_setlocale provides ONLY dummy implementation. */
-#define HAVE_SETLOCALE
-#define setlocale wceex_setlocale
-
-/* Define to 1 if you have the `bsearch' function. */
-#define HAVE_BSEARCH
-#define bsearch wceex_bsearch
-
-/* Define to 1 if you have the `lfind' function. */
-#define HAVE_LFIND
-#define lfind wceex_lfind
-
-/* Define if you have the ANSI C header files.  */
-#ifndef STDC_HEADERS
-#  define STDC_HEADERS
-#endif
-
-/* Windows CE is not have errno.h file: */
-#if defined(_WIN32_WCE) && !defined(NO_ERRNO_H)
-#  undef HAVE_ERRNO_H
-#endif
-
-/* Define to 1 if you have the <search.h> header file. */
-#define HAVE_SEARCH_H 1
-
-/* Define to 1 if you have the <fcntl.h> header file. */
-#define  HAVE_FCNTL_H 1
-
-/* Define if you have the <unistd.h> header file.  */
-#undef HAVE_UNISTD_H
-
-/* Define if you have the <stdint.h> header file.  */
-#undef HAVE_STDINT_H
-
-/* Define if you have the <time.h> header file.  */
-#undef HAVE_TIME_H
-
-/* Define if you have the <sql.h> header file. */
-#undef HAVE_SQL_H
-
-/* Define if you have the <sqlext.h> header file. */
-#undef HAVE_SQLEXT_H
-
-#undef HAVE_LIBDL 
-
-#undef HAVE_DLFCN_H
-#undef HAVE_DBMALLOC_H
-#undef HAVE_LIBDBMALLOC
-#undef WORDS_BIGENDIAN
-
-/* The size of a `int', as computed by sizeof. */
-#define SIZEOF_INT 4
-
-/* The size of a `long', as computed by sizeof. */
-#define SIZEOF_LONG 4
-
-/* #define CPL_DISABLE_DLL */
-/* #define CPL_DISABLE_STDCALL */
-
-/* Enable VSIStat64 for Windows CE (temporarily) */
-/* TODO: To be removed as specified in Ticket #2452 */
-#define VSI_STAT64 stat
-
diff --git a/port/cpl_conv.cpp b/port/cpl_conv.cpp
index 5fbffff..d8f0708 100644
--- a/port/cpl_conv.cpp
+++ b/port/cpl_conv.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_conv.cpp 28601 2015-03-03 11:06:40Z rouault $
+ * $Id: cpl_conv.cpp 33769 2016-03-22 18:20:04Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Convenience functions.
@@ -27,21 +27,40 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
+
+// For uselocale
+#ifdef _XOPEN_SOURCE
+#undef _XOPEN_SOURCE
+#endif
+#define _XOPEN_SOURCE 700
+
+// For atoll (at least for NetBSD)
+#define _ISOC99_SOURCE
+
 #ifdef MSVC_USE_VLD
 #include <vld.h>
 #endif
 #include "cpl_conv.h"
+#include "cpl_multiproc.h"
 #include "cpl_string.h"
 #include "cpl_vsi.h"
-#include "cpl_multiproc.h"
-#include <errno.h>
 
-CPL_CVSID("$Id: cpl_conv.cpp 28601 2015-03-03 11:06:40Z rouault $");
+#include <cerrno>
+#include <clocale>
+#include <cstring>
+
+/* Uncomment to get list of options that have been fetched and set */
+//#define DEBUG_CONFIG_OPTIONS
+
+#ifdef DEBUG_CONFIG_OPTIONS
+
+#include <set>
+#include "cpl_multiproc.h"
 
-#if defined(WIN32CE)
-#  include "cpl_wince.h"
 #endif
 
+CPL_CVSID("$Id: cpl_conv.cpp 33769 2016-03-22 18:20:04Z goatbar $");
+
 static CPLMutex *hConfigMutex = NULL;
 static volatile char **papszConfigOptions = NULL;
 
@@ -87,12 +106,10 @@ static volatile CPLSharedFileInfoExtra *pasSharedFileListExtra = NULL;
 void *CPLCalloc( size_t nCount, size_t nSize )
 
 {
-    void        *pReturn;
-
     if( nSize * nCount == 0 )
         return NULL;
-    
-    pReturn = CPLMalloc( nCount * nSize );
+
+    void *pReturn = CPLMalloc( nCount * nSize );
     memset( pReturn, 0, nCount * nSize );
     return pReturn;
 }
@@ -119,37 +136,32 @@ void *CPLCalloc( size_t nCount, size_t nSize )
 void *CPLMalloc( size_t nSize )
 
 {
-    void        *pReturn;
-
-    CPLVerifyConfiguration();
-
     if( nSize == 0 )
         return NULL;
 
-    if( long(nSize) < 0 )
+    CPLVerifyConfiguration();
+
+    if( static_cast<long>(nSize) < 0 )
     {
+        /* coverity[dead_error_begin] */
         CPLError( CE_Failure, CPLE_AppDefined,
                   "CPLMalloc(%ld): Silly size requested.\n",
-                  (long) nSize );
+                  static_cast<long>(nSize) );
         return NULL;
     }
-    
-    pReturn = VSIMalloc( nSize );
+
+    void *pReturn = VSIMalloc( nSize );
     if( pReturn == NULL )
     {
         if( nSize > 0 && nSize < 2000 )
         {
-            char szSmallMsg[60];
-
-            sprintf( szSmallMsg, 
-                     "CPLMalloc(): Out of memory allocating %ld bytes.", 
-                     (long) nSize );
-            CPLEmergencyError( szSmallMsg ); 
+            CPLEmergencyError( "CPLMalloc(): Out of memory allocating a small "
+                               "number of bytes." );
         }
-        else
-            CPLError( CE_Fatal, CPLE_OutOfMemory,
-                      "CPLMalloc(): Out of memory allocating %ld bytes.\n",
-                      (long) nSize );
+
+        CPLError( CE_Fatal, CPLE_OutOfMemory,
+                  "CPLMalloc(): Out of memory allocating %ld bytes.\n",
+                  static_cast<long>(nSize) );
     }
 
     return pReturn;
@@ -182,42 +194,43 @@ void *CPLMalloc( size_t nSize )
 void * CPLRealloc( void * pData, size_t nNewSize )
 
 {
-    void        *pReturn;
-
     if ( nNewSize == 0 )
     {
         VSIFree(pData);
         return NULL;
     }
 
-    if( long(nNewSize) < 0 )
+    if( static_cast<long>(nNewSize) < 0 )
     {
+        /* coverity[dead_error_begin] */
         CPLError( CE_Failure, CPLE_AppDefined,
                   "CPLRealloc(%ld): Silly size requested.\n",
-                  (long) nNewSize );
+                  static_cast<long>( nNewSize ) );
         return NULL;
     }
-    
+
+    void *pReturn = NULL;
+
     if( pData == NULL )
         pReturn = VSIMalloc( nNewSize );
     else
         pReturn = VSIRealloc( pData, nNewSize );
-    
+
     if( pReturn == NULL )
     {
         if( nNewSize > 0 && nNewSize < 2000 )
         {
             char szSmallMsg[60];
 
-            sprintf( szSmallMsg, 
-                     "CPLRealloc(): Out of memory allocating %ld bytes.", 
-                     (long) nNewSize );
-            CPLEmergencyError( szSmallMsg ); 
+            snprintf( szSmallMsg, sizeof(szSmallMsg),
+                      "CPLRealloc(): Out of memory allocating %ld bytes.",
+                      static_cast<long>( nNewSize ) );
+            CPLEmergencyError( szSmallMsg );
         }
         else
             CPLError( CE_Fatal, CPLE_OutOfMemory,
                       "CPLRealloc(): Out of memory allocating %ld bytes.\n",
-                      (long) nNewSize );
+                      static_cast<long>( nNewSize ) );
     }
 
     return pReturn;
@@ -248,22 +261,20 @@ void * CPLRealloc( void * pData, size_t nNewSize )
 char *CPLStrdup( const char * pszString )
 
 {
-    char        *pszReturn;
-
     if( pszString == NULL )
         pszString = "";
 
-    pszReturn = (char *) CPLMalloc(strlen(pszString)+1);
+    char *pszReturn
+        = reinterpret_cast<char *>( CPLMalloc(strlen(pszString) + 1 ) );
     if( pszReturn == NULL )
     {
         CPLError( CE_Fatal, CPLE_OutOfMemory,
                   "CPLStrdup(): Out of memory allocating %ld bytes.\n",
-                  (long) strlen(pszString) );
-        
+                  static_cast<long>( strlen(pszString) ) );
     }
 
     strcpy( pszReturn, pszString );
-    return( pszReturn );
+    return pszReturn;
 }
 
 /************************************************************************/
@@ -283,15 +294,15 @@ char *CPLStrdup( const char * pszString )
 char *CPLStrlwr( char *pszString )
 
 {
-    if (pszString)
-    {
-        char *pszTemp = pszString;
+    if( pszString == NULL )
+        return NULL;
 
-        while (*pszTemp)
-        {
-            *pszTemp = (char) tolower (*pszTemp);
-            pszTemp++;
-        }
+    char *pszTemp = pszString;
+
+    while (*pszTemp)
+    {
+        *pszTemp = static_cast<char>( tolower (*pszTemp) );
+        pszTemp++;
     }
 
     return pszString;
@@ -315,7 +326,7 @@ char *CPLStrlwr( char *pszString )
  *
  * @param pszBuffer pointer to the targeting character buffer.
  * @param nBufferSize maximum size of the string to read (not including
- * termonating '\\0').
+ * terminating '\\0').
  * @param fp file pointer to read from.
  * @return pointer to the pszBuffer containing a string read
  * from the file or NULL if the error or end of file was encountered.
@@ -324,8 +335,6 @@ char *CPLStrlwr( char *pszString )
 char *CPLFGets( char *pszBuffer, int nBufferSize, FILE * fp )
 
 {
-    int nActuallyRead, nOriginalOffset;
-
     if ( nBufferSize == 0 || pszBuffer == NULL || fp == NULL )
         return NULL;
 
@@ -336,11 +345,11 @@ char *CPLFGets( char *pszBuffer, int nBufferSize, FILE * fp )
 /*      just the newline (LF).  If it is in binary mode it may well     */
 /*      have both.                                                      */
 /* -------------------------------------------------------------------- */
-    nOriginalOffset = VSIFTell( fp );
+    const long nOriginalOffset = VSIFTell( fp );
     if( VSIFGets( pszBuffer, nBufferSize, fp ) == NULL )
         return NULL;
-    
-    nActuallyRead = strlen(pszBuffer);
+
+    int nActuallyRead = static_cast<int>( strlen(pszBuffer) );
     if ( nActuallyRead == 0 )
         return NULL;
 
@@ -351,12 +360,15 @@ char *CPLFGets( char *pszBuffer, int nBufferSize, FILE * fp )
     if( nBufferSize == nActuallyRead+1
         && pszBuffer[nActuallyRead-1] == 13 )
     {
-        int chCheck;
-        chCheck = fgetc( fp );
+        const int chCheck = fgetc( fp );
         if( chCheck != 10 )
         {
             // unget the character.
-            VSIFSeek( fp, nOriginalOffset+nActuallyRead, SEEK_SET );
+            if (VSIFSeek( fp, nOriginalOffset+nActuallyRead, SEEK_SET ) == -1)
+            {
+                CPLError( CE_Failure, CPLE_FileIO,
+                          "Unable to unget a character");
+            }
         }
     }
 
@@ -364,13 +376,13 @@ char *CPLFGets( char *pszBuffer, int nBufferSize, FILE * fp )
 /*      Trim off \n, \r or \r\n if it appears at the end.  We don't     */
 /*      need to do any "seeking" since we want the newline eaten.       */
 /* -------------------------------------------------------------------- */
-    if( nActuallyRead > 1 
-        && pszBuffer[nActuallyRead-1] == 10 
+    if( nActuallyRead > 1
+        && pszBuffer[nActuallyRead-1] == 10
         && pszBuffer[nActuallyRead-2] == 13 )
     {
         pszBuffer[nActuallyRead-2] = '\0';
     }
-    else if( pszBuffer[nActuallyRead-1] == 10 
+    else if( pszBuffer[nActuallyRead-1] == 10
              || pszBuffer[nActuallyRead-1] == 13 )
     {
         pszBuffer[nActuallyRead-1] = '\0';
@@ -382,33 +394,34 @@ char *CPLFGets( char *pszBuffer, int nBufferSize, FILE * fp )
 /*      and seek back.                                                  */
 /* -------------------------------------------------------------------- */
     char *pszExtraNewline = strchr( pszBuffer, 13 );
-    
+
     if( pszExtraNewline != NULL )
     {
-        int chCheck;
+        nActuallyRead = static_cast<int>(pszExtraNewline - pszBuffer + 1);
 
-        nActuallyRead = pszExtraNewline - pszBuffer + 1;
-        
         *pszExtraNewline = '\0';
-        VSIFSeek( fp, nOriginalOffset + nActuallyRead - 1, SEEK_SET );
+        if( VSIFSeek( fp, nOriginalOffset + nActuallyRead - 1, SEEK_SET ) != 0)
+            return NULL;
 
-        /* 
+        /*
          * This hackery is necessary to try and find our correct
-         * spot on win32 systems with text mode line translation going 
+         * spot on win32 systems with text mode line translation going
          * on.  Sometimes the fseek back overshoots, but it doesn't
          * "realize it" till a character has been read. Try to read till
-         * we get to the right spot and get our CR. 
-         */ 
-        chCheck = fgetc( fp );
+         * we get to the right spot and get our CR.
+         */
+        int chCheck = fgetc( fp );
         while( (chCheck != 13 && chCheck != EOF)
                || VSIFTell(fp) < nOriginalOffset + nActuallyRead )
         {
-            static volatile int bWarned = FALSE;
+            static bool bWarned = false;
 
             if( !bWarned )
             {
-                bWarned = TRUE;
-                CPLDebug( "CPL", "CPLFGets() correcting for DOS text mode translation seek problem." );
+                bWarned = true;
+                CPLDebug( "CPL",
+                          "CPLFGets() correcting for DOS text mode translation "
+                          "seek problem." );
             }
             chCheck = fgetc( fp );
         }
@@ -430,15 +443,17 @@ char *CPLFGets( char *pszBuffer, int nBufferSize, FILE * fp )
 static char *CPLReadLineBuffer( int nRequiredSize )
 
 {
-    
+
 /* -------------------------------------------------------------------- */
 /*      A required size of -1 means the buffer should be freed.         */
 /* -------------------------------------------------------------------- */
     if( nRequiredSize == -1 )
     {
-        if( CPLGetTLS( CTLS_RLBUFFERINFO ) != NULL )
+        int bMemoryError = FALSE;
+        void* pRet = CPLGetTLSEx( CTLS_RLBUFFERINFO, &bMemoryError );
+        if( pRet != NULL )
         {
-            CPLFree( CPLGetTLS( CTLS_RLBUFFERINFO ) );
+            CPLFree( pRet );
             CPLSetTLS( CTLS_RLBUFFERINFO, NULL, FALSE );
         }
         return NULL;
@@ -447,11 +462,17 @@ static char *CPLReadLineBuffer( int nRequiredSize )
 /* -------------------------------------------------------------------- */
 /*      If the buffer doesn't exist yet, create it.                     */
 /* -------------------------------------------------------------------- */
-    GUInt32 *pnAlloc = (GUInt32 *) CPLGetTLS( CTLS_RLBUFFERINFO );
+    int bMemoryError = FALSE;
+    GUInt32 *pnAlloc = reinterpret_cast<GUInt32 *>(
+        CPLGetTLSEx( CTLS_RLBUFFERINFO, &bMemoryError ) );
+    if( bMemoryError )
+        return NULL;
 
     if( pnAlloc == NULL )
     {
-        pnAlloc = (GUInt32 *) CPLMalloc(200);
+        pnAlloc = reinterpret_cast<GUInt32 *>( VSI_MALLOC_VERBOSE(200) );
+        if( pnAlloc == NULL )
+            return NULL;
         *pnAlloc = 196;
         CPLSetTLS( CTLS_RLBUFFERINFO, pnAlloc, TRUE );
     }
@@ -459,7 +480,7 @@ static char *CPLReadLineBuffer( int nRequiredSize )
 /* -------------------------------------------------------------------- */
 /*      If it is too small, grow it bigger.                             */
 /* -------------------------------------------------------------------- */
-    if( ((int) *pnAlloc) -1 < nRequiredSize )
+    if( static_cast<int>( *pnAlloc ) - 1 < nRequiredSize )
     {
         int nNewSize = nRequiredSize + 4 + 500;
         if (nNewSize <= 0)
@@ -467,27 +488,26 @@ static char *CPLReadLineBuffer( int nRequiredSize )
             VSIFree( pnAlloc );
             CPLSetTLS( CTLS_RLBUFFERINFO, NULL, FALSE );
             CPLError( CE_Failure, CPLE_OutOfMemory,
-                      "CPLReadLineBuffer(): Trying to allocate more than 2 GB." );
+                      "CPLReadLineBuffer(): Trying to allocate more than "
+                      "2 GB." );
             return NULL;
         }
 
-        GUInt32* pnAllocNew = (GUInt32 *) VSIRealloc(pnAlloc,nNewSize);
+        GUInt32* pnAllocNew = reinterpret_cast<GUInt32 *>(
+            VSI_REALLOC_VERBOSE( pnAlloc, nNewSize ) );
         if( pnAllocNew == NULL )
         {
             VSIFree( pnAlloc );
             CPLSetTLS( CTLS_RLBUFFERINFO, NULL, FALSE );
-            CPLError( CE_Failure, CPLE_OutOfMemory,
-                      "CPLReadLineBuffer(): Out of memory allocating %ld bytes.",
-                      (long) nNewSize );
             return NULL;
         }
         pnAlloc = pnAllocNew;
-            
+
         *pnAlloc = nNewSize - 4;
         CPLSetTLS( CTLS_RLBUFFERINFO, pnAlloc, TRUE );
     }
 
-    return (char *) (pnAlloc+1);
+    return reinterpret_cast<char *>( pnAlloc + 1 );
 }
 
 /************************************************************************/
@@ -496,18 +516,18 @@ static char *CPLReadLineBuffer( int nRequiredSize )
 
 /**
  * Simplified line reading from text file.
- * 
+ *
  * Read a line of text from the given file handle, taking care
- * to capture CR and/or LF and strip off ... equivelent of
+ * to capture CR and/or LF and strip off ... equivalent of
  * DKReadLine().  Pointer to an internal buffer is returned.
  * The application shouldn't free it, or depend on it's value
  * past the next call to CPLReadLine().
- * 
+ *
  * Note that CPLReadLine() uses VSIFGets(), so any hooking of VSI file
  * services should apply to CPLReadLine() as well.
  *
- * CPLReadLine() maintains an internal buffer, which will appear as a 
- * single block memory leak in some circumstances.  CPLReadLine() may 
+ * CPLReadLine() maintains an internal buffer, which will appear as a
+ * single block memory leak in some circumstances.  CPLReadLine() may
  * be called with a NULL FILE * at any time to free this working buffer.
  *
  * @param fp file pointer opened with VSIFOpen().
@@ -519,9 +539,6 @@ static char *CPLReadLineBuffer( int nRequiredSize )
 const char *CPLReadLine( FILE * fp )
 
 {
-    char *pszRLBuffer = CPLReadLineBuffer(1);
-    int         nReadSoFar = 0;
-
 /* -------------------------------------------------------------------- */
 /*      Cleanup case.                                                   */
 /* -------------------------------------------------------------------- */
@@ -535,7 +552,9 @@ const char *CPLReadLine( FILE * fp )
 /*      Loop reading chunks of the line till we get to the end of       */
 /*      the line.                                                       */
 /* -------------------------------------------------------------------- */
-    int nBytesReadThisTime;
+    size_t nBytesReadThisTime = 0;
+    char* pszRLBuffer = NULL;
+    size_t nReadSoFar = 0;
 
     do {
 /* -------------------------------------------------------------------- */
@@ -544,15 +563,16 @@ const char *CPLReadLine( FILE * fp )
 /*      instance for a _very large_ file with no newlines).             */
 /* -------------------------------------------------------------------- */
         if( nReadSoFar > 100 * 1024 * 1024 )
-            return NULL; /* it is dubious that we need to read a line longer than 100 MB ! */
-        pszRLBuffer = CPLReadLineBuffer( nReadSoFar + 129 );
+             // It is dubious that we need to read a line longer than 100 MB.
+            return NULL;
+        pszRLBuffer = CPLReadLineBuffer( static_cast<int>(nReadSoFar) + 129 );
         if( pszRLBuffer == NULL )
             return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Do the actual read.                                             */
 /* -------------------------------------------------------------------- */
-        if( CPLFGets( pszRLBuffer+nReadSoFar, 128, fp ) == NULL 
+        if( CPLFGets( pszRLBuffer+nReadSoFar, 128, fp ) == NULL
             && nReadSoFar == 0 )
             return NULL;
 
@@ -563,7 +583,7 @@ const char *CPLReadLine( FILE * fp )
              && pszRLBuffer[nReadSoFar-1] != 13
              && pszRLBuffer[nReadSoFar-1] != 10 );
 
-    return( pszRLBuffer );
+    return pszRLBuffer;
 }
 
 /************************************************************************/
@@ -572,7 +592,7 @@ const char *CPLReadLine( FILE * fp )
 
 /**
  * Simplified line reading from text file.
- * 
+ *
  * Similar to CPLReadLine(), but reading from a large file API handle.
  *
  * @param fp file pointer opened with VSIFOpenL().
@@ -592,7 +612,7 @@ const char *CPLReadLineL( VSILFILE * fp )
 
 /**
  * Simplified line reading from text file.
- * 
+ *
  * Similar to CPLReadLine(), but reading from a large file API handle.
  *
  * @param fp file pointer opened with VSIFOpenL().
@@ -601,16 +621,15 @@ const char *CPLReadLineL( VSILFILE * fp )
 
  * @return pointer to an internal buffer containing a line of text read
  * from the file or NULL if the end of file was encountered or the maximum
- * number of characters allowed readched.
+ * number of characters allowed reached.
  *
  * @since GDAL 1.7.0
  */
 
-const char *CPLReadLine2L( VSILFILE * fp, int nMaxCars, char** papszOptions )
+const char *CPLReadLine2L( VSILFILE * fp, int nMaxCars,
+                           char** /*papszOptions */ )
 
 {
-    (void) papszOptions;
-
 /* -------------------------------------------------------------------- */
 /*      Cleanup case.                                                   */
 /* -------------------------------------------------------------------- */
@@ -624,19 +643,21 @@ const char *CPLReadLine2L( VSILFILE * fp, int nMaxCars, char** papszOptions )
 /*      Loop reading chunks of the line till we get to the end of       */
 /*      the line.                                                       */
 /* -------------------------------------------------------------------- */
-    char *pszRLBuffer;
+    char *pszRLBuffer = NULL;
     const size_t nChunkSize = 40;
     char szChunk[nChunkSize];
     size_t nChunkBytesRead = 0;
     int nBufLength = 0;
     size_t nChunkBytesConsumed = 0;
 
-    while( TRUE )
+    szChunk[0] = 0;
+
+    while( true )
     {
 /* -------------------------------------------------------------------- */
 /*      Read a chunk from the input file.                               */
 /* -------------------------------------------------------------------- */
-        if ( nBufLength > INT_MAX - (int)nChunkSize - 1 )
+        if ( nBufLength > INT_MAX - static_cast<int>(nChunkSize) - 1 )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Too big line : more than 2 billion characters!." );
@@ -644,7 +665,7 @@ const char *CPLReadLine2L( VSILFILE * fp, int nMaxCars, char** papszOptions )
             return NULL;
         }
 
-        pszRLBuffer = CPLReadLineBuffer( nBufLength + nChunkSize + 1 );
+        pszRLBuffer = CPLReadLineBuffer( static_cast<int>(nBufLength + nChunkSize + 1) );
         if( pszRLBuffer == NULL )
             return NULL;
 
@@ -667,15 +688,15 @@ const char *CPLReadLine2L( VSILFILE * fp, int nMaxCars, char** papszOptions )
             {
                 if( nBufLength == 0 )
                     return NULL;
-                else
-                    break;
+
+                break;
             }
         }
-        
+
 /* -------------------------------------------------------------------- */
 /*      copy over characters watching for end-of-line.                  */
 /* -------------------------------------------------------------------- */
-        int bBreak = FALSE;
+        bool bBreak = false;
         while( nChunkBytesConsumed < nChunkBytesRead-1 && !bBreak )
         {
             if( (szChunk[nChunkBytesConsumed] == 13
@@ -684,13 +705,13 @@ const char *CPLReadLine2L( VSILFILE * fp, int nMaxCars, char** papszOptions )
                     && szChunk[nChunkBytesConsumed+1] == 13) )
             {
                 nChunkBytesConsumed += 2;
-                bBreak = TRUE;
+                bBreak = true;
             }
             else if( szChunk[nChunkBytesConsumed] == 10
                      || szChunk[nChunkBytesConsumed] == 13 )
             {
                 nChunkBytesConsumed += 1;
-                bBreak = TRUE;
+                bBreak = true;
             }
             else
             {
@@ -698,7 +719,7 @@ const char *CPLReadLine2L( VSILFILE * fp, int nMaxCars, char** papszOptions )
                 if (nMaxCars >= 0 && nBufLength == nMaxCars)
                 {
                     CPLError( CE_Failure, CPLE_AppDefined,
-                             "Maximum number of characters allowed reached.");
+                              "Maximum number of characters allowed reached." );
                     return NULL;
                 }
             }
@@ -712,7 +733,7 @@ const char *CPLReadLine2L( VSILFILE * fp, int nMaxCars, char** papszOptions )
 /*      consume it.  If it is a newline, but we are clearly at the      */
 /*      end of the file then consume it.                                */
 /* -------------------------------------------------------------------- */
-        if( nChunkBytesConsumed == nChunkBytesRead-1 
+        if( nChunkBytesConsumed == nChunkBytesRead-1
             && nChunkBytesRead < nChunkSize )
         {
             if( szChunk[nChunkBytesConsumed] == 10
@@ -733,14 +754,15 @@ const char *CPLReadLine2L( VSILFILE * fp, int nMaxCars, char** papszOptions )
 /* -------------------------------------------------------------------- */
     if( nChunkBytesConsumed < nChunkBytesRead )
     {
-        size_t nBytesToPush = nChunkBytesRead - nChunkBytesConsumed;
-        
-        VSIFSeekL( fp, VSIFTellL( fp ) - nBytesToPush, SEEK_SET );
+        const size_t nBytesToPush = nChunkBytesRead - nChunkBytesConsumed;
+
+        if( VSIFSeekL( fp, VSIFTellL( fp ) - nBytesToPush, SEEK_SET ) != 0 )
+            return NULL;
     }
 
     pszRLBuffer[nBufLength] = '\0';
 
-    return( pszRLBuffer );
+    return pszRLBuffer;
 }
 
 /************************************************************************/
@@ -762,7 +784,7 @@ const char *CPLReadLine2L( VSILFILE * fp, int nMaxCars, char** papszOptions )
  *
  * @param bNormalize If TRUE, replace ':' symbol with the '_'. It is needed if
  * resulting string will be used in CPL dictionaries.
- * 
+ *
  * @return Pointer to the resulting string buffer. Caller responsible to free
  * this buffer with CPLFree().
  */
@@ -770,15 +792,13 @@ const char *CPLReadLine2L( VSILFILE * fp, int nMaxCars, char** papszOptions )
 char *CPLScanString( const char *pszString, int nMaxLength,
                      int bTrimSpaces, int bNormalize )
 {
-    char    *pszBuffer;
-
     if ( !pszString )
         return NULL;
 
     if ( !nMaxLength )
         return CPLStrdup( "" );
 
-    pszBuffer = (char *)CPLMalloc( nMaxLength + 1 );
+    char *pszBuffer = reinterpret_cast<char *>( CPLMalloc( nMaxLength + 1 ) );
     if ( !pszBuffer )
         return NULL;
 
@@ -787,14 +807,14 @@ char *CPLScanString( const char *pszString, int nMaxLength,
 
     if ( bTrimSpaces )
     {
-        size_t  i = strlen( pszBuffer );
+        size_t i = strlen( pszBuffer );
         while ( i-- > 0 && isspace((unsigned char)pszBuffer[i]) )
             pszBuffer[i] = '\0';
     }
 
     if ( bNormalize )
     {
-        size_t  i = strlen( pszBuffer );
+        size_t i = strlen( pszBuffer );
         while ( i-- > 0 )
         {
             if ( pszBuffer[i] == ':' )
@@ -819,28 +839,18 @@ char *CPLScanString( const char *pszString, int nMaxLength,
  * @param nMaxLength The maximum number of character to consider as part
  * of the number. Less characters will be considered if a null character
  * is encountered.
- * 
+ *
  * @return Long value, converted from its ASCII form.
  */
 
 long CPLScanLong( const char *pszString, int nMaxLength )
 {
-    long    iValue;
-    char    *pszValue = (char *)CPLMalloc( nMaxLength + 1);
-
-/* -------------------------------------------------------------------- */
-/*      Compute string into local buffer, and terminate it.             */
-/* -------------------------------------------------------------------- */
-    strncpy( pszValue, pszString, nMaxLength );
-    pszValue[nMaxLength] = '\0';
-
-/* -------------------------------------------------------------------- */
-/*      Use atol() to fetch out the result                              */
-/* -------------------------------------------------------------------- */
-    iValue = atol( pszValue );
-
-    CPLFree( pszValue );
-    return iValue;
+    CPLAssert( nMaxLength >= 0 );
+    if( pszString == NULL )
+        return 0;
+    const size_t nLength = CPLStrnlen(pszString, nMaxLength);
+    const std::string osValue( pszString, nLength );
+    return atol( osValue.c_str() );
 }
 
 
@@ -858,28 +868,18 @@ long CPLScanLong( const char *pszString, int nMaxLength )
  * @param nMaxLength The maximum number of character to consider as part
  * of the number. Less characters will be considered if a null character
  * is encountered.
- * 
+ *
  * @return Unsigned long value, converted from its ASCII form.
  */
 
 unsigned long CPLScanULong( const char *pszString, int nMaxLength )
 {
-    unsigned long    uValue;
-    char    *pszValue = (char *)CPLMalloc( nMaxLength + 1);
-
-/* -------------------------------------------------------------------- */
-/*      Compute string into local buffer, and terminate it.             */
-/* -------------------------------------------------------------------- */
-    strncpy( pszValue, pszString, nMaxLength );
-    pszValue[nMaxLength] = '\0';
-
-/* -------------------------------------------------------------------- */
-/*      Use strtoul() to fetch out the result                           */
-/* -------------------------------------------------------------------- */
-    uValue = strtoul( pszValue, NULL, 10 );
-
-    CPLFree( pszValue );
-    return uValue;
+    CPLAssert( nMaxLength >= 0 );
+    if( pszString == NULL )
+        return 0;
+    const size_t nLength = CPLStrnlen(pszString, nMaxLength);
+    const std::string osValue( pszString, nLength );
+    return strtoul( osValue.c_str(), NULL, 10 );
 }
 
 /************************************************************************/
@@ -890,7 +890,7 @@ unsigned long CPLScanULong( const char *pszString, int nMaxLength )
  * Extract big integer from string.
  *
  * Scan up to a maximum number of characters from a string and convert
- * the result to a GUIntBig. 
+ * the result to a GUIntBig.
  *
  * @param pszString String containing characters to be scanned. It may be
  * terminated with a null character.
@@ -898,34 +898,28 @@ unsigned long CPLScanULong( const char *pszString, int nMaxLength )
  * @param nMaxLength The maximum number of character to consider as part
  * of the number. Less characters will be considered if a null character
  * is encountered.
- * 
+ *
  * @return GUIntBig value, converted from its ASCII form.
  */
 
 GUIntBig CPLScanUIntBig( const char *pszString, int nMaxLength )
 {
-    GUIntBig    iValue;
-    char        *pszValue = (char *)CPLMalloc( nMaxLength + 1);
-
-/* -------------------------------------------------------------------- */
-/*      Compute string into local buffer, and terminate it.             */
-/* -------------------------------------------------------------------- */
-    strncpy( pszValue, pszString, nMaxLength );
-    pszValue[nMaxLength] = '\0';
+    CPLAssert( nMaxLength >= 0 );
+    if( pszString == NULL )
+        return 0;
+    const size_t nLength = CPLStrnlen(pszString, nMaxLength);
+    const std::string osValue( pszString, nLength );
 
 /* -------------------------------------------------------------------- */
 /*      Fetch out the result                                            */
 /* -------------------------------------------------------------------- */
 #if defined(__MSVCRT__) || (defined(WIN32) && defined(_MSC_VER))
-    iValue = (GUIntBig)_atoi64( pszValue );
+    return static_cast<GUIntBig>( _atoi64( osValue.c_str() ) );
 # elif HAVE_ATOLL
-    iValue = atoll( pszValue );
+    return atoll( osValue.c_str() );
 #else
-    iValue = atol( pszValue );
+    return = atol( osValue.c_str() );
 #endif
-
-    CPLFree( pszValue );
-    return iValue;
 }
 
 /************************************************************************/
@@ -934,7 +928,7 @@ GUIntBig CPLScanUIntBig( const char *pszString, int nMaxLength )
 
 /**
  * Convert a string to a 64 bit signed integer.
- * 
+ *
  * @param pszString String containing 64 bit signed integer.
  * @return 64 bit signed integer.
  * @since GDAL 2.0
@@ -951,10 +945,10 @@ GIntBig CPLAtoGIntBig( const char* pszString )
 #endif
 }
 
-#if defined(__MINGW32__)
+#if defined(__MINGW32__) || defined(__sun__)
 
 // mingw atoll() doesn't return ERANGE in case of overflow
-int CPLAtoGIntBigExHasOverflow(const char* pszString, GIntBig nVal)
+static int CPLAtoGIntBigExHasOverflow(const char* pszString, GIntBig nVal)
 {
     if( strlen(pszString) <= 18 )
         return FALSE;
@@ -963,7 +957,15 @@ int CPLAtoGIntBigExHasOverflow(const char* pszString, GIntBig nVal)
     if( *pszString == '+' )
         pszString ++;
     char szBuffer[32];
-    sprintf(szBuffer, CPL_FRMT_GIB, nVal);
+/* x86_64-w64-mingw32-g++ (GCC) 4.8.2 annoyingly warns */
+#ifdef HAVE_GCC_DIAGNOSTIC_PUSH
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat"
+#endif
+    snprintf(szBuffer, sizeof(szBuffer), CPL_FRMT_GIB, nVal);
+#ifdef HAVE_GCC_DIAGNOSTIC_PUSH
+#pragma GCC diagnostic pop
+#endif
     return strcmp(szBuffer, pszString) != 0;
 }
 
@@ -975,27 +977,26 @@ int CPLAtoGIntBigExHasOverflow(const char* pszString, GIntBig nVal)
 
 /**
  * Convert a string to a 64 bit signed integer.
- * 
+ *
  * @param pszString String containing 64 bit signed integer.
  * @param bWarn Issue a warning if an overflow occurs during conversion
- * @param pbOverflow Pointer to an integer to store if an overflow occured, or NULL
+ * @param pbOverflow Pointer to an integer to store if an overflow occurred, or NULL
  * @return 64 bit signed integer.
  * @since GDAL 2.0
  */
 
 GIntBig CPLAtoGIntBigEx( const char* pszString, int bWarn, int *pbOverflow )
 {
-    GIntBig nVal;
     errno = 0;
 #if defined(__MSVCRT__) || (defined(WIN32) && defined(_MSC_VER))
-    nVal = _atoi64( pszString );
+    GIntBig nVal = _atoi64( pszString );
 # elif HAVE_ATOLL
-    nVal = atoll( pszString );
+    GIntBig nVal = atoll( pszString );
 #else
-    nVal = atol( pszString );
+    GIntBig nVal = atol( pszString );
 #endif
     if( errno == ERANGE
-#if defined(__MINGW32__)
+#if defined(__MINGW32__) || defined(__sun__)
         || CPLAtoGIntBigExHasOverflow(pszString, nVal)
 #endif
         )
@@ -1023,7 +1024,7 @@ GIntBig CPLAtoGIntBigEx( const char* pszString, int bWarn, int *pbOverflow )
  * Extract pointer from string.
  *
  * Scan up to a maximum number of characters from a string and convert
- * the result to a pointer. 
+ * the result to a pointer.
  *
  * @param pszString String containing characters to be scanned. It may be
  * terminated with a null character.
@@ -1031,20 +1032,19 @@ GIntBig CPLAtoGIntBigEx( const char* pszString, int bWarn, int *pbOverflow )
  * @param nMaxLength The maximum number of character to consider as part
  * of the number. Less characters will be considered if a null character
  * is encountered.
- * 
+ *
  * @return pointer value, converted from its ASCII form.
  */
 
 void *CPLScanPointer( const char *pszString, int nMaxLength )
 {
-    void  *pResult;
     char  szTemp[128];
 
 /* -------------------------------------------------------------------- */
 /*      Compute string into local buffer, and terminate it.             */
 /* -------------------------------------------------------------------- */
-    if( nMaxLength > (int) sizeof(szTemp)-1 )
-        nMaxLength = sizeof(szTemp)-1;
+    if( nMaxLength > static_cast<int>( sizeof(szTemp) ) - 1 )
+        nMaxLength = sizeof(szTemp) - 1;
 
     strncpy( szTemp, pszString, nMaxLength );
     szTemp[nMaxLength] = '\0';
@@ -1053,9 +1053,9 @@ void *CPLScanPointer( const char *pszString, int nMaxLength )
 /*      On MSVC we have to scanf pointer values without the 0x          */
 /*      prefix.                                                         */
 /* -------------------------------------------------------------------- */
-    if( EQUALN(szTemp,"0x",2) )
+    if( STARTS_WITH_CI(szTemp, "0x") )
     {
-        pResult = NULL;
+        void *pResult = NULL;
 
 #if defined(__MSVCRT__) || (defined(WIN32) && defined(_MSC_VER))
         sscanf( szTemp+2, "%p", &pResult );
@@ -1068,18 +1068,14 @@ void *CPLScanPointer( const char *pszString, int nMaxLength )
             sscanf( szTemp+2, "%p", &pResult );
         }
 #endif
+        return pResult;
     }
-    
-    else
-    {
+
 #if SIZEOF_VOIDP == 8
-        pResult = (void *) CPLScanUIntBig( szTemp, nMaxLength );
+    return reinterpret_cast<void *>( CPLScanUIntBig( szTemp, nMaxLength ) );
 #else
-        pResult = (void *) CPLScanULong( szTemp, nMaxLength );
+    return reinterpret_cast<void *>( CPLScanULong( szTemp, nMaxLength ) );
 #endif
-    }
-
-    return pResult;
 }
 
 /************************************************************************/
@@ -1099,15 +1095,19 @@ void *CPLScanPointer( const char *pszString, int nMaxLength )
  * @param nMaxLength The maximum number of character to consider as part
  * of the number. Less characters will be considered if a null character
  * is encountered.
- * 
+ *
  * @return Double value, converted from its ASCII form.
  */
 
 double CPLScanDouble( const char *pszString, int nMaxLength )
 {
-    int     i;
-    double  dfValue;
-    char    *pszValue = (char *)CPLMalloc( nMaxLength + 1);
+    char        szValue[32];
+    char        *pszValue;
+
+    if( nMaxLength + 1 < static_cast<int>( sizeof(szValue) ) )
+        pszValue = szValue;
+    else
+        pszValue = reinterpret_cast<char *>( CPLMalloc( nMaxLength + 1 ) );
 
 /* -------------------------------------------------------------------- */
 /*      Compute string into local buffer, and terminate it.             */
@@ -1118,16 +1118,17 @@ double CPLScanDouble( const char *pszString, int nMaxLength )
 /* -------------------------------------------------------------------- */
 /*      Make a pass through converting 'D's to 'E's.                    */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < nMaxLength; i++ )
+    for( int i = 0; i < nMaxLength; i++ )
         if ( pszValue[i] == 'd' || pszValue[i] == 'D' )
             pszValue[i] = 'E';
 
 /* -------------------------------------------------------------------- */
 /*      The conversion itself.                                          */
 /* -------------------------------------------------------------------- */
-    dfValue = CPLAtof( pszValue );
+    const double dfValue = CPLAtof( pszValue );
 
-    CPLFree( pszValue );
+    if( pszValue != szValue )
+        CPLFree( pszValue );
     return dfValue;
 }
 
@@ -1143,18 +1144,15 @@ double CPLScanDouble( const char *pszString, int nMaxLength )
  * large enough to hold the resulting string.
  *
  * @param pszSrc Pointer to the source buffer.
- * 
+ *
  * @param nMaxLen Maximum length of the resulting string. If string length
  * is greater than nMaxLen, it will be truncated.
- * 
+ *
  * @return Number of characters printed.
  */
 
 int CPLPrintString( char *pszDest, const char *pszSrc, int nMaxLen )
 {
-    char    *pszTemp = pszDest;
-    int     nChars = 0;
-
     if ( !pszDest )
         return 0;
 
@@ -1164,6 +1162,9 @@ int CPLPrintString( char *pszDest, const char *pszSrc, int nMaxLen )
         return 1;
     }
 
+    int  nChars = 0;
+    char *pszTemp = pszDest;
+
     while ( nChars < nMaxLen && *pszSrc )
     {
         *pszTemp++ = *pszSrc++;
@@ -1187,17 +1188,15 @@ int CPLPrintString( char *pszDest, const char *pszSrc, int nMaxLen )
  * large enough to hold the resulting string.
  *
  * @param pszSrc Pointer to the source buffer.
- * 
+ *
  * @param nMaxLen Maximum length of the resulting string. If string length
  * is greater than nMaxLen, it will be truncated.
- * 
+ *
  * @return Number of characters printed.
  */
 
 int CPLPrintStringFill( char *pszDest, const char *pszSrc, int nMaxLen )
 {
-    char    *pszTemp = pszDest;
-
     if ( !pszDest )
         return 0;
 
@@ -1207,6 +1206,7 @@ int CPLPrintStringFill( char *pszDest, const char *pszSrc, int nMaxLen )
         return nMaxLen;
     }
 
+    char *pszTemp = pszDest;
     while ( nMaxLen && *pszSrc )
     {
         *pszTemp++ = *pszSrc++;
@@ -1232,27 +1232,27 @@ int CPLPrintStringFill( char *pszDest, const char *pszSrc, int nMaxLen )
  * not be NULL-terminated, so user should do this himself, if needed.
  *
  * @param iValue Numerical value to print.
- * 
+ *
  * @param nMaxLen Maximum length of the resulting string. If string length
  * is greater than nMaxLen, it will be truncated.
- * 
+ *
  * @return Number of characters printed.
  */
 
 int CPLPrintInt32( char *pszBuffer, GInt32 iValue, int nMaxLen )
 {
-    char    szTemp[64];
-
     if ( !pszBuffer )
         return 0;
 
     if ( nMaxLen >= 64 )
         nMaxLen = 63;
 
+    char    szTemp[64];
+
 #if UINT_MAX == 65535
-    sprintf( szTemp, "%*ld", nMaxLen, iValue );
+    snprintf( szTemp, sizeof(szTemp), "%*ld", nMaxLen, iValue );
 #else
-    sprintf( szTemp, "%*d", nMaxLen, iValue );
+    snprintf( szTemp, sizeof(szTemp), "%*d", nMaxLen, iValue );
 #endif
 
     return CPLPrintString( pszBuffer, szTemp, nMaxLen );
@@ -1271,30 +1271,39 @@ int CPLPrintInt32( char *pszBuffer, GInt32 iValue, int nMaxLen )
  * not be NULL-terminated, so user should do this himself, if needed.
  *
  * @param iValue Numerical value to print.
- * 
+ *
  * @param nMaxLen Maximum length of the resulting string. If string length
  * is greater than nMaxLen, it will be truncated.
- * 
+ *
  * @return Number of characters printed.
  */
 
 int CPLPrintUIntBig( char *pszBuffer, GUIntBig iValue, int nMaxLen )
 {
-    char    szTemp[64];
-
     if ( !pszBuffer )
         return 0;
 
     if ( nMaxLen >= 64 )
         nMaxLen = 63;
 
+    char szTemp[64];
+
 #if defined(__MSVCRT__) || (defined(WIN32) && defined(_MSC_VER))
-    sprintf( szTemp, "%*I64d", nMaxLen, iValue );
+/* x86_64-w64-mingw32-g++ (GCC) 4.8.2 annoyingly warns */
+#ifdef HAVE_GCC_DIAGNOSTIC_PUSH
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat"
+#pragma GCC diagnostic ignored "-Wformat-extra-args"
+#endif
+    snprintf( szTemp, sizeof(szTemp), "%*I64d", nMaxLen, iValue );
+#ifdef HAVE_GCC_DIAGNOSTIC_PUSH
+#pragma GCC diagnostic pop
+#endif
 # elif HAVE_LONG_LONG
-    sprintf( szTemp, "%*lld", nMaxLen, (long long) iValue );
+    snprintf( szTemp, sizeof(szTemp), "%*lld", nMaxLen, (long long) iValue );
 //    sprintf( szTemp, "%*Ld", nMaxLen, (long long) iValue );
 #else
-    sprintf( szTemp, "%*ld", nMaxLen, iValue );
+    snprintf( szTemp, sizeof(szTemp), "%*ld", nMaxLen, iValue );
 #endif
 
     return CPLPrintString( pszBuffer, szTemp, nMaxLen );
@@ -1313,31 +1322,31 @@ int CPLPrintUIntBig( char *pszBuffer, GUIntBig iValue, int nMaxLen )
  * not be NULL-terminated, so user should do this himself, if needed.
  *
  * @param pValue Pointer to ASCII encode.
- * 
+ *
  * @param nMaxLen Maximum length of the resulting string. If string length
  * is greater than nMaxLen, it will be truncated.
- * 
+ *
  * @return Number of characters printed.
  */
 
 int CPLPrintPointer( char *pszBuffer, void *pValue, int nMaxLen )
 {
-    char    szTemp[64];
-
     if ( !pszBuffer )
         return 0;
 
     if ( nMaxLen >= 64 )
         nMaxLen = 63;
 
-    sprintf( szTemp, "%p", pValue );
+    char szTemp[64];
+
+    snprintf( szTemp, sizeof(szTemp), "%p", pValue );
 
     // On windows, and possibly some other platforms the sprintf("%p")
     // does not prefix things with 0x so it is hard to know later if the
-    // value is hex encoded.  Fix this up here. 
+    // value is hex encoded.  Fix this up here.
 
-    if( !EQUALN(szTemp,"0x",2) )
-        sprintf( szTemp, "0x%p", pValue );
+    if( !STARTS_WITH_CI(szTemp, "0x") )
+        snprintf( szTemp, sizeof(szTemp), "0x%p", pValue );
 
     return CPLPrintString( pszBuffer, szTemp, nMaxLen );
 }
@@ -1358,7 +1367,7 @@ int CPLPrintPointer( char *pszBuffer, void *pValue, int nMaxLen )
  * @param pszFormat Format specifier (for example, "%16.9E").
  *
  * @param dfValue Numerical value to print.
- * 
+ *
  * @param pszLocale Pointer to a character string containing locale name
  * ("C", "POSIX", "us_US", "ru_RU.KOI8-R" etc.). If NULL we will not
  * manipulate with locale settings and current process locale will be used for
@@ -1370,7 +1379,7 @@ int CPLPrintPointer( char *pszBuffer, void *pValue, int nMaxLen )
  */
 
 int CPLPrintDouble( char *pszBuffer, const char *pszFormat,
-                    double dfValue, CPL_UNUSED const char *pszLocale )
+                    double dfValue, const char * /* pszLocale */ )
 {
     if ( !pszBuffer )
         return 0;
@@ -1378,11 +1387,7 @@ int CPLPrintDouble( char *pszBuffer, const char *pszFormat,
     const int double_buffer_size = 64;
     char szTemp[double_buffer_size];
 
-#if defined(HAVE_SNPRINTF)
     CPLsnprintf( szTemp, double_buffer_size, pszFormat, dfValue );
-#else
-    CPLsprintf( szTemp, pszFormat, dfValue );
-#endif
     szTemp[double_buffer_size - 1] = '\0';
 
     for( int i = 0; szTemp[i] != '\0'; i++ )
@@ -1401,19 +1406,19 @@ int CPLPrintDouble( char *pszBuffer, const char *pszFormat,
 /**
  * Print specified time value accordingly to the format options and
  * specified locale name. This function does following:
- * 
+ *
  *  - if locale parameter is not NULL, the current locale setting will be
  *  stored and replaced with the specified one;
  *  - format time value with the strftime(3) function;
  *  - restore back current locale, if was saved.
- * 
+ *
  * @param pszBuffer Pointer to the destination string buffer. Should be
  * large enough to hold the resulting string. Note, that the string will
  * not be NULL-terminated, so user should do this himself, if needed.
  *
  * @param nMaxLen Maximum length of the resulting string. If string length is
  * greater than nMaxLen, it will be truncated.
- * 
+ *
  * @param pszFormat Controls the output format. Options are the same as
  * for strftime(3) function.
  *
@@ -1425,19 +1430,17 @@ int CPLPrintDouble( char *pszBuffer, const char *pszFormat,
  * manipulate with locale settings and current process locale will be used for
  * printing. Be aware that it may be unsuitable to use current locale for
  * printing time, because all names will be printed in your native language,
- * as well as time format settings also may be ajusted differently from the
- * C/POSIX defaults. To solve these problems this option was introdiced.
+ * as well as time format settings also may be adjusted differently from the
+ * C/POSIX defaults. To solve these problems this option was introduced.
  *
  * @return Number of characters printed.
  */
 
-#ifndef WIN32CE /* XXX - mloskot - strftime is not available yet. */
-
 int CPLPrintTime( char *pszBuffer, int nMaxLen, const char *pszFormat,
                   const struct tm *poBrokenTime, const char *pszLocale )
 {
-    char    *pszTemp = (char *)CPLMalloc( (nMaxLen + 1) * sizeof(char) );
-    int     nChars;
+    char *pszTemp = reinterpret_cast<char *>(
+        CPLMalloc( (nMaxLen + 1) * sizeof(char) ) );
 
 #if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE)
     char        *pszCurLocale = NULL;
@@ -1452,7 +1455,7 @@ int CPLPrintTime( char *pszBuffer, int nMaxLen, const char *pszFormat,
 #else
     (void) pszLocale;
 #endif
-    
+
     if ( !strftime( pszTemp, nMaxLen + 1, pszFormat, poBrokenTime ) )
         memset( pszTemp, 0, nMaxLen + 1);
 
@@ -1462,15 +1465,13 @@ int CPLPrintTime( char *pszBuffer, int nMaxLen, const char *pszFormat,
         CPLsetlocale( LC_ALL, pszCurLocale );
 #endif
 
-    nChars = CPLPrintString( pszBuffer, pszTemp, nMaxLen );
+    const int nChars = CPLPrintString( pszBuffer, pszTemp, nMaxLen );
 
     CPLFree( pszTemp );
 
     return nChars;
 }
 
-#endif
-
 /************************************************************************/
 /*                       CPLVerifyConfiguration()                       */
 /************************************************************************/
@@ -1478,43 +1479,36 @@ int CPLPrintTime( char *pszBuffer, int nMaxLen, const char *pszFormat,
 void CPLVerifyConfiguration()
 
 {
+    static bool verified = false;
+    if (!verified) {
+        return;
+    }
+    verified = true;
+
 /* -------------------------------------------------------------------- */
 /*      Verify data types.                                              */
 /* -------------------------------------------------------------------- */
-    CPLAssert( sizeof(GInt32) == 4 );
-    CPLAssert( sizeof(GInt16) == 2 );
-    CPLAssert( sizeof(GByte) == 1 );
-
-    if( sizeof(GInt32) != 4 )
-        CPLError( CE_Fatal, CPLE_AppDefined, 
-                  "sizeof(GInt32) == %d ... yow!\n", 
-                  (int) sizeof(GInt32) );
+    CPL_STATIC_ASSERT( sizeof(GInt32) == 4 );
+    CPL_STATIC_ASSERT( sizeof(GInt16) == 2 );
+    CPL_STATIC_ASSERT( sizeof(GByte) == 1 );
 
 /* -------------------------------------------------------------------- */
 /*      Verify byte order                                               */
 /* -------------------------------------------------------------------- */
-    GInt32   nTest;
-
-    nTest = 1;
+    GInt32   nTest = 1;
 
 #ifdef CPL_LSB
-    if( ((GByte *) &nTest)[0] != 1 )
+    if( reinterpret_cast<GByte *>( &nTest )[0] != 1 )
 #endif
 #ifdef CPL_MSB
-    if( ((GByte *) &nTest)[3] != 1 )
-#endif    
-        CPLError( CE_Fatal, CPLE_AppDefined, 
+    if( reinterpret_cast<GByte *>( &nTest )[3] != 1 )
+#endif
+        CPLError( CE_Fatal, CPLE_AppDefined,
                   "CPLVerifyConfiguration(): byte order set wrong.\n" );
 }
 
-/* Uncomment to get list of options that have been fetched and set */
-//#define DEBUG_CONFIG_OPTIONS
-
 #ifdef DEBUG_CONFIG_OPTIONS
 
-#include <set>
-#include "cpl_multiproc.h"
-
 static void* hRegisterConfigurationOptionMutex = 0;
 static std::set<CPLString>* paoGetKeys = NULL;
 static std::set<CPLString>* paoSetKeys = NULL;
@@ -1554,7 +1548,7 @@ static void CPLShowAccessedOptions()
 /*                       CPLAccessConfigOption()                        */
 /************************************************************************/
 
-static void CPLAccessConfigOption(const char* pszKey, int bGet)
+static void CPLAccessConfigOption(const char* pszKey, bool bGet)
 {
     CPLMutexHolderD(&hRegisterConfigurationOptionMutex);
     if (paoGetKeys == NULL)
@@ -1563,7 +1557,7 @@ static void CPLAccessConfigOption(const char* pszKey, int bGet)
         paoSetKeys = new std::set<CPLString>;
         atexit(CPLShowAccessedOptions);
     }
-    if (bGet)
+    if( bGet )
         paoGetKeys->insert(pszKey);
     else
         paoSetKeys->insert(pszKey);
@@ -1576,17 +1570,17 @@ static void CPLAccessConfigOption(const char* pszKey, int bGet)
 
 /**
   * Get the value of a configuration option.
-  * 
-  * The value is the value of a (key, value) option set with CPLSetConfigOption().
-  * If the given option was no defined with CPLSetConfigOption(), it tries to find
-  * it in environment variables.
   *
-  * Note: the string returned by CPLGetConfigOption() might be short-lived, and in
-  * particular it will become invalid after a call to CPLSetConfigOption() with the
-  * same key.
+  * The value is the value of a (key, value) option set with
+  * CPLSetConfigOption().  If the given option was no defined with
+  * CPLSetConfigOption(), it tries to find it in environment variables.
   *
-  * To override temporary a potentially existing option with a new value, you can
-  * use the following snippet :
+  * Note: the string returned by CPLGetConfigOption() might be short-lived, and
+  * in particular it will become invalid after a call to CPLSetConfigOption()
+  * with the same key.
+  *
+  * To override temporary a potentially existing option with a new value, you
+  * can use the following snippet :
   * <pre>
   *     // backup old value
   *     const char* pszOldValTmp = CPLGetConfigOption(pszKey, NULL);
@@ -1600,7 +1594,8 @@ static void CPLAccessConfigOption(const char* pszKey, int bGet)
   * </pre>
   *
   * @param pszKey the key of the option to retrieve
-  * @param pszDefault a default value if the key does not match existing defined options (may be NULL)
+  * @param pszDefault a default value if the key does not match existing defined
+  *     options (may be NULL)
   * @return the value associated to the key, or the default value if not found
   *
   * @see CPLSetConfigOption(), http://trac.osgeo.org/gdal/wiki/ConfigOptions
@@ -1615,7 +1610,9 @@ CPLGetConfigOption( const char *pszKey, const char *pszDefault )
 
     const char *pszResult = NULL;
 
-    char **papszTLConfigOptions = (char **) CPLGetTLS( CTLS_CONFIGOPTIONS );
+    int bMemoryError = FALSE;
+    char **papszTLConfigOptions = reinterpret_cast<char **>(
+        CPLGetTLSEx( CTLS_CONFIGOPTIONS, &bMemoryError ) );
     if( papszTLConfigOptions != NULL )
         pszResult = CSLFetchNameValue( papszTLConfigOptions, pszKey );
 
@@ -1626,15 +1623,39 @@ CPLGetConfigOption( const char *pszKey, const char *pszDefault )
         pszResult = CSLFetchNameValue( (char **) papszConfigOptions, pszKey );
     }
 
-#if !defined(WIN32CE) 
     if( pszResult == NULL )
         pszResult = getenv( pszKey );
+
+    if( pszResult == NULL )
+        return pszDefault;
+
+    return pszResult;
+}
+
+/************************************************************************/
+/*                   CPLGetThreadLocalConfigOption()                    */
+/************************************************************************/
+
+const char * CPL_STDCALL
+CPLGetThreadLocalConfigOption( const char *pszKey, const char *pszDefault )
+
+{
+#ifdef DEBUG_CONFIG_OPTIONS
+    CPLAccessConfigOption(pszKey, TRUE);
 #endif
-    
+
+    const char *pszResult = NULL;
+
+    int bMemoryError = FALSE;
+    char **papszTLConfigOptions = reinterpret_cast<char **>(
+        CPLGetTLSEx( CTLS_CONFIGOPTIONS, &bMemoryError ) );
+    if( papszTLConfigOptions != NULL )
+        pszResult = CSLFetchNameValue( papszTLConfigOptions, pszKey );
+
     if( pszResult == NULL )
         return pszDefault;
-    else
-        return pszResult;
+
+    return pszResult;
 }
 
 /************************************************************************/
@@ -1664,10 +1685,10 @@ CPLGetConfigOption( const char *pszKey, const char *pszDefault )
   *
   * @param pszKey the key of the option
   * @param pszValue the value of the option, or NULL to clear a setting.
-  * 
+  *
   * @see http://trac.osgeo.org/gdal/wiki/ConfigOptions
   */
-void CPL_STDCALL 
+void CPL_STDCALL
 CPLSetConfigOption( const char *pszKey, const char *pszValue )
 
 {
@@ -1676,8 +1697,8 @@ CPLSetConfigOption( const char *pszKey, const char *pszValue )
 #endif
     CPLMutexHolderD( &hConfigMutex );
 
-    papszConfigOptions = (volatile char **) 
-        CSLSetNameValue( (char **) papszConfigOptions, pszKey, pszValue );
+    papszConfigOptions = (volatile char **)
+      CSLSetNameValue( (char **) papszConfigOptions, pszKey, pszValue );
 }
 
 /************************************************************************/
@@ -1687,7 +1708,7 @@ CPLSetConfigOption( const char *pszKey, const char *pszValue )
 /* non-stdcall wrapper function for CSLDestroy() (#5590) */
 static void CPLSetThreadLocalTLSFreeFunc( void* pData )
 {
-    CSLDestroy( (char**) pData );
+    CSLDestroy( reinterpret_cast<char**>( pData ) );
 }
 
 /************************************************************************/
@@ -1698,7 +1719,7 @@ static void CPLSetThreadLocalTLSFreeFunc( void* pData )
   * Set a configuration option for GDAL/OGR use.
   *
   * Those options are defined as a (key, value) couple. The value corresponding
-  * to a key can be got later with the CPLGetConfigOption() method.  
+  * to a key can be got later with the CPLGetConfigOption() method.
   *
   * This function sets the configuration option that only applies in the
   * current thread, as opposed to CPLSetConfigOption() which sets an option
@@ -1712,7 +1733,7 @@ static void CPLSetThreadLocalTLSFreeFunc( void* pData )
   * @param pszValue the value of the option, or NULL to clear a setting.
   */
 
-void CPL_STDCALL 
+void CPL_STDCALL
 CPLSetThreadLocalConfigOption( const char *pszKey, const char *pszValue )
 
 {
@@ -1720,9 +1741,13 @@ CPLSetThreadLocalConfigOption( const char *pszKey, const char *pszValue )
     CPLAccessConfigOption(pszKey, FALSE);
 #endif
 
-    char **papszTLConfigOptions = (char **) CPLGetTLS( CTLS_CONFIGOPTIONS );
+    int bMemoryError = FALSE;
+    char **papszTLConfigOptions = reinterpret_cast<char **>(
+        CPLGetTLSEx( CTLS_CONFIGOPTIONS, &bMemoryError ) );
+    if( bMemoryError )
+        return;
 
-    papszTLConfigOptions = 
+    papszTLConfigOptions =
         CSLSetNameValue( papszTLConfigOptions, pszKey, pszValue );
 
     CPLSetTLSWithFreeFunc( CTLS_CONFIGOPTIONS, papszTLConfigOptions,
@@ -1741,8 +1766,10 @@ void CPL_STDCALL CPLFreeConfig()
 
         CSLDestroy( (char **) papszConfigOptions);
         papszConfigOptions = NULL;
-        
-        char **papszTLConfigOptions = (char **) CPLGetTLS( CTLS_CONFIGOPTIONS );
+
+        int bMemoryError = FALSE;
+        char **papszTLConfigOptions = reinterpret_cast<char **>(
+            CPLGetTLSEx( CTLS_CONFIGOPTIONS, &bMemoryError ) );
         if( papszTLConfigOptions != NULL )
         {
             CSLDestroy( papszTLConfigOptions );
@@ -1765,27 +1792,21 @@ int CPLStat( const char *pszPath, VSIStatBuf *psStatBuf )
 {
     if( strlen(pszPath) == 2 && pszPath[1] == ':' )
     {
-        char    szAltPath[4];
-        
-        szAltPath[0] = pszPath[0];
-        szAltPath[1] = pszPath[1];
-        szAltPath[2] = '\\';
-        szAltPath[3] = '\0';
+        char szAltPath[4] = { pszPath[0], pszPath[1], '\\', '\0' };
         return VSIStat( szAltPath, psStatBuf );
     }
-    else
-        return VSIStat( pszPath, psStatBuf );
+
+    return VSIStat( pszPath, psStatBuf );
 }
 
 /************************************************************************/
 /*                            proj_strtod()                             */
 /************************************************************************/
 static double
-proj_strtod(char *nptr, char **endptr) 
+proj_strtod(char *nptr, char **endptr)
 
 {
     char c, *cp = nptr;
-    double result;
 
     /*
      * Scan for characters which cause problems with VC++ strtod()
@@ -1798,7 +1819,7 @@ proj_strtod(char *nptr, char **endptr)
              * then restore it and return
              */
             *cp = '\0';
-            result = CPLStrtod(nptr, endptr);
+            const double result = CPLStrtod(nptr, endptr);
             *cp = c;
             return result;
         }
@@ -1820,23 +1841,33 @@ static const double vm[] = { 1.0, 0.0166666666667, 0.00027777778 };
 double CPLDMSToDec( const char *is )
 
 {
-    int sign, n, nl;
-    char *p, *s, work[64];
-    double v, tv;
+    int sign = 0;
 
     /* copy sting into work space */
-    while (isspace((unsigned char)(sign = *is))) ++is;
-    for (n = sizeof(work), s = work, p = (char *)is; isgraph(*p) && --n ; )
+    while (isspace(static_cast<unsigned char>(sign = *is)))
+        ++is;
+
+    char *p = const_cast<char *>( is );
+    char work[64];
+    char *s = work;
+    int n = sizeof(work);
+    for( ;
+         isgraph(*p) && --n ; )
         *s++ = *p++;
     *s = '\0';
     /* it is possible that a really odd input (like lots of leading
        zeros) could be truncated in copying into work.  But ... */
     sign = *(s = work);
+
     if (sign == '+' || sign == '-') s++;
     else sign = '+';
-    for (v = 0., nl = 0 ; nl < 3 ; nl = n + 1 ) {
+
+    int nl = 0;
+    double v = 0.0;
+    for ( ; nl < 3 ; nl = n + 1 ) {
         if (!(isdigit(*s) || *s == '.')) break;
-        if ((tv = proj_strtod(s, &s)) == HUGE_VAL)
+        const double tv = proj_strtod(s, &s);
+        if( tv == HUGE_VAL )
             return tv;
         switch (*s) {
           case 'D': case 'd':
@@ -1888,28 +1919,24 @@ const char *CPLDecToDMS( double dfAngle, const char * pszAxis,
 {
     VALIDATE_POINTER1( pszAxis, "CPLDecToDMS", "" );
 
-    int         nDegrees, nMinutes;
-    double      dfSeconds, dfABSAngle, dfEpsilon;
-    char        szFormat[30];
-    const char  *pszHemisphere;
-    static CPL_THREADLOCAL char szBuffer[50] = { 0 };
-    
-    
-    dfEpsilon = (0.5/3600.0) * pow(0.1,nPrecision);
+    if( CPLIsNan(dfAngle) )
+        return "Invalid angle";
 
-    dfABSAngle = ABS(dfAngle) + dfEpsilon;
+    const double dfEpsilon = (0.5/3600.0) * pow(0.1,nPrecision);
+    const double dfABSAngle = ABS(dfAngle) + dfEpsilon;
     if (dfABSAngle > 361)
     {
         return "Invalid angle";
     }
 
-    nDegrees = (int) dfABSAngle;
-    nMinutes = (int) ((dfABSAngle - nDegrees) * 60);
-    dfSeconds = dfABSAngle * 3600 - nDegrees*3600 - nMinutes*60;
+    const int nDegrees = (int) dfABSAngle;
+    const int nMinutes = (int) ((dfABSAngle - nDegrees) * 60);
+    double dfSeconds = dfABSAngle * 3600 - nDegrees*3600 - nMinutes*60;
 
     if( dfSeconds > dfEpsilon * 3600.0 )
         dfSeconds -= dfEpsilon * 3600.0;
 
+    const char  *pszHemisphere;
     if( EQUAL(pszAxis,"Long") && dfAngle < 0.0 )
         pszHemisphere = "W";
     else if( EQUAL(pszAxis,"Long") )
@@ -1919,10 +1946,17 @@ const char *CPLDecToDMS( double dfAngle, const char * pszAxis,
     else
         pszHemisphere = "N";
 
-    CPLsprintf( szFormat, "%%3dd%%2d\'%%%d.%df\"%s", nPrecision+3, nPrecision, pszHemisphere );
-    CPLsprintf( szBuffer, szFormat, nDegrees, nMinutes, dfSeconds );
+    char szFormat[30];
+    CPLsnprintf( szFormat, sizeof(szFormat),
+                 "%%3dd%%2d\'%%%d.%df\"%s",
+                 nPrecision+3, nPrecision, pszHemisphere );
 
-    return( szBuffer );
+    static CPL_THREADLOCAL char szBuffer[50] = { 0 };
+    CPLsnprintf( szBuffer, sizeof(szBuffer),
+                 szFormat,
+                 nDegrees, nMinutes, dfSeconds );
+
+    return szBuffer;
 }
 
 /************************************************************************/
@@ -1931,29 +1965,29 @@ const char *CPLDecToDMS( double dfAngle, const char * pszAxis,
 
 /**
  * Convert a packed DMS value (DDDMMMSSS.SS) into decimal degrees.
- * 
+ *
  * This function converts a packed DMS angle to seconds. The standard
  * packed DMS format is:
  *
  *  degrees * 1000000 + minutes * 1000 + seconds
  *
- * Example:     ang = 120025045.25 yields
+ * Example:     angle = 120025045.25 yields
  *              deg = 120
  *              min = 25
  *              sec = 45.25
- * 
+ *
  * The algorithm used for the conversion is as follows:
  *
  * 1.  The absolute value of the angle is used.
  *
  * 2.  The degrees are separated out:
- *     deg = ang/1000000                    (fractional portion truncated)
+ *     deg = angle/1000000                    (fractional portion truncated)
  *
  * 3.  The minutes are separated out:
- *     min = (ang - deg * 1000000) / 1000   (fractional portion truncated)
+ *     min = (angle - deg * 1000000) / 1000   (fractional portion truncated)
  *
  * 4.  The seconds are then computed:
- *     sec = ang - deg * 1000000 - min * 1000
+ *     sec = angle - deg * 1000000 - min * 1000
  *
  * 5.  The total angle in seconds is computed:
  *     sec = deg * 3600.0 + min * 60.0 + sec
@@ -1969,20 +2003,18 @@ const char *CPLDecToDMS( double dfAngle, const char * pszAxis,
  * @param dfPacked Angle in packed DMS format.
  *
  * @return Angle in decimal degrees.
- * 
+ *
  */
 
 double CPLPackedDMSToDec( double dfPacked )
 {
-    double  dfDegrees, dfMinutes, dfSeconds, dfSign;
+    const double dfSign = ( dfPacked < 0.0 )? -1 : 1;
 
-    dfSign = ( dfPacked < 0.0 )? -1 : 1;
-        
-    dfSeconds = ABS( dfPacked );
-    dfDegrees = floor(dfSeconds / 1000000.0);
-    dfSeconds = dfSeconds - dfDegrees * 1000000.0;
-    dfMinutes = floor(dfSeconds / 1000.0);
-    dfSeconds = dfSeconds - dfMinutes * 1000.0;
+    double dfSeconds = ABS( dfPacked );
+    double dfDegrees = floor(dfSeconds / 1000000.0);
+    dfSeconds -= dfDegrees * 1000000.0;
+    double dfMinutes = floor(dfSeconds / 1000.0);
+    dfSeconds -= dfMinutes * 1000.0;
     dfSeconds = dfSign * ( dfDegrees * 3600.0 + dfMinutes * 60.0 + dfSeconds);
     dfDegrees = dfSeconds / 3600.0;
 
@@ -1994,7 +2026,7 @@ double CPLPackedDMSToDec( double dfPacked )
 /************************************************************************/
 /**
  * Convert decimal degrees into packed DMS value (DDDMMMSSS.SS).
- * 
+ *
  * This function converts a value, specified in decimal degrees into
  * packed DMS angle. The standard packed DMS format is:
  *
@@ -2005,19 +2037,17 @@ double CPLPackedDMSToDec( double dfPacked )
  * @param dfDec Angle in decimal degrees.
  *
  * @return Angle in packed DMS format.
- * 
+ *
  */
 
 double CPLDecToPackedDMS( double dfDec )
 {
-    double  dfDegrees, dfMinutes, dfSeconds, dfSign;
-
-    dfSign = ( dfDec < 0.0 )? -1 : 1;
+    const double dfSign = ( dfDec < 0.0 ) ? -1 : 1;
 
     dfDec = ABS( dfDec );
-    dfDegrees = floor( dfDec );
-    dfMinutes = floor( ( dfDec - dfDegrees ) * 60.0 );
-    dfSeconds = ( dfDec - dfDegrees ) * 3600.0 - dfMinutes * 60.0;
+    const double dfDegrees = floor( dfDec );
+    const double dfMinutes = floor( ( dfDec - dfDegrees ) * 60.0 );
+    const double dfSeconds = ( dfDec - dfDegrees ) * 3600.0 - dfMinutes * 60.0;
 
     return dfSign * (dfDegrees * 1000000.0 + dfMinutes * 1000.0 + dfSeconds);
 }
@@ -2026,20 +2056,22 @@ double CPLDecToPackedDMS( double dfDec )
 /*                         CPLStringToComplex()                         */
 /************************************************************************/
 
-void CPL_DLL CPLStringToComplex( const char *pszString, 
+void CPL_DLL CPLStringToComplex( const char *pszString,
                                  double *pdfReal, double *pdfImag )
 
 {
-    int  i;
-    int  iPlus = -1, iImagEnd = -1;
-
     while( *pszString == ' ' )
         pszString++;
 
     *pdfReal = CPLAtof(pszString);
     *pdfImag = 0.0;
 
-    for( i = 0; pszString[i] != '\0' && pszString[i] != ' ' && i < 100; i++ )
+    int iPlus = -1;
+    int iImagEnd = -1;
+
+    for( int i = 0;
+         pszString[i] != '\0' && pszString[i] != ' ' && i < 100;
+         i++ )
     {
         if( pszString[i] == '+' && i > 0 )
             iPlus = i;
@@ -2062,47 +2094,45 @@ void CPL_DLL CPLStringToComplex( const char *pszString,
 /************************************************************************/
 
 /**
- * Open a shared file handle. 
+ * Open a shared file handle.
  *
  * Some operating systems have limits on the number of file handles that can
  * be open at one time.  This function attempts to maintain a registry of
  * already open file handles, and reuse existing ones if the same file
- * is requested by another part of the application. 
+ * is requested by another part of the application.
  *
- * Note that access is only shared for access types "r", "rb", "r+" and 
+ * Note that access is only shared for access types "r", "rb", "r+" and
  * "rb+".  All others will just result in direct VSIOpen() calls.  Keep in
- * mind that a file is only reused if the file name is exactly the same. 
- * Different names referring to the same file will result in different 
- * handles.  
+ * mind that a file is only reused if the file name is exactly the same.
+ * Different names referring to the same file will result in different
+ * handles.
  *
- * The VSIFOpen() or VSIFOpenL() function is used to actually open the file, 
- * when an existing file handle can't be shared. 
+ * The VSIFOpen() or VSIFOpenL() function is used to actually open the file,
+ * when an existing file handle can't be shared.
  *
  * @param pszFilename the name of the file to open.
  * @param pszAccess the normal fopen()/VSIFOpen() style access string.
  * @param bLarge If TRUE VSIFOpenL() (for large files) will be used instead of
- * VSIFOpen(). 
+ * VSIFOpen().
  *
- * @return a file handle or NULL if opening fails. 
+ * @return a file handle or NULL if opening fails.
  */
 
 FILE *CPLOpenShared( const char *pszFilename, const char *pszAccess,
                      int bLarge )
 
 {
-    int i;
-    int bReuse;
     CPLMutexHolderD( &hSharedFileMutex );
-    GIntBig nPID = CPLGetPID();
+    const GIntBig nPID = CPLGetPID();
 
 /* -------------------------------------------------------------------- */
 /*      Is there an existing file we can use?                           */
 /* -------------------------------------------------------------------- */
-    bReuse = EQUAL(pszAccess,"rb") || EQUAL(pszAccess, "rb+");
+    const bool bReuse = EQUAL(pszAccess,"rb") || EQUAL(pszAccess, "rb+");
 
-    for( i = 0; bReuse && i < nSharedFileCount; i++ )
+    for( int i = 0; bReuse && i < nSharedFileCount; i++ )
     {
-        if( strcmp(pasSharedFileList[i].pszFilename,pszFilename) == 0 
+        if( strcmp(pasSharedFileList[i].pszFilename,pszFilename) == 0
             && !bLarge == !pasSharedFileList[i].bLarge
             && EQUAL(pasSharedFileList[i].pszAccess,pszAccess)
             && nPID == pasSharedFileListExtra[i].nPID)
@@ -2118,7 +2148,7 @@ FILE *CPLOpenShared( const char *pszFilename, const char *pszAccess,
     FILE *fp;
 
     if( bLarge )
-        fp = (FILE*) VSIFOpenL( pszFilename, pszAccess );
+        fp = reinterpret_cast<FILE *>( VSIFOpenL( pszFilename, pszAccess ) );
     else
         fp = VSIFOpen( pszFilename, pszAccess );
 
@@ -2130,12 +2160,12 @@ FILE *CPLOpenShared( const char *pszFilename, const char *pszAccess,
 /* -------------------------------------------------------------------- */
     nSharedFileCount++;
 
-    pasSharedFileList = (CPLSharedFileInfo *)
-        CPLRealloc( (void *) pasSharedFileList, 
-                    sizeof(CPLSharedFileInfo) * nSharedFileCount );
-    pasSharedFileListExtra = (CPLSharedFileInfoExtra *)
-        CPLRealloc( (void *) pasSharedFileListExtra, 
-                    sizeof(CPLSharedFileInfoExtra) * nSharedFileCount );
+    pasSharedFileList = reinterpret_cast<CPLSharedFileInfo *>(
+        CPLRealloc( (void *) pasSharedFileList,
+                    sizeof(CPLSharedFileInfo) * nSharedFileCount ) );
+    pasSharedFileListExtra = reinterpret_cast<CPLSharedFileInfoExtra *>(
+        CPLRealloc( (void *) pasSharedFileListExtra,
+                    sizeof(CPLSharedFileInfoExtra) * nSharedFileCount ) );
 
     pasSharedFileList[nSharedFileCount-1].fp = fp;
     pasSharedFileList[nSharedFileCount-1].nRefCount = 1;
@@ -2165,16 +2195,16 @@ void CPLCloseShared( FILE * fp )
 
 {
     CPLMutexHolderD( &hSharedFileMutex );
-    int i;
 
 /* -------------------------------------------------------------------- */
 /*      Search for matching information.                                */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < nSharedFileCount && fp != pasSharedFileList[i].fp; i++ ){}
+    int i = 0;
+    for( ; i < nSharedFileCount && fp != pasSharedFileList[i].fp; i++ ){}
 
     if( i == nSharedFileCount )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to find file handle %p in CPLCloseShared().",
                   fp );
         return;
@@ -2190,7 +2220,13 @@ void CPLCloseShared( FILE * fp )
 /*      Close the file, and remove the information.                     */
 /* -------------------------------------------------------------------- */
     if( pasSharedFileList[i].bLarge )
-        VSIFCloseL( (VSILFILE*) pasSharedFileList[i].fp );
+    {
+        if( VSIFCloseL( reinterpret_cast<VSILFILE *>( pasSharedFileList[i].fp ) ) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "Error while closing %s",
+                     pasSharedFileList[i].pszFilename );
+        }
+    }
     else
         VSIFClose( pasSharedFileList[i].fp );
 
@@ -2198,11 +2234,11 @@ void CPLCloseShared( FILE * fp )
     CPLFree( pasSharedFileList[i].pszAccess );
 
     nSharedFileCount --;
-    memmove( (void *) (pasSharedFileList + i), 
-             (void *) (pasSharedFileList + nSharedFileCount), 
+    memmove( (void *) (pasSharedFileList + i),
+             (void *) (pasSharedFileList + nSharedFileCount),
              sizeof(CPLSharedFileInfo) );
-    memmove( (void *) (pasSharedFileListExtra + i), 
-             (void *) (pasSharedFileListExtra + nSharedFileCount), 
+    memmove( (void *) (pasSharedFileListExtra + i),
+             (void *) (pasSharedFileListExtra + nSharedFileCount),
              sizeof(CPLSharedFileInfoExtra) );
 
     if( nSharedFileCount == 0 )
@@ -2235,9 +2271,9 @@ void CPLCleanupSharedFileMutex()
 /**
  * Fetch list of open shared files.
  *
- * @param pnCount place to put the count of entries. 
+ * @param pnCount place to put the count of entries.
  *
- * @return the pointer to the first in the array of shared file info 
+ * @return the pointer to the first in the array of shared file info
  * structures.
  */
 
@@ -2246,7 +2282,7 @@ CPLSharedFileInfo *CPLGetSharedList( int *pnCount )
 {
     if( pnCount != NULL )
         *pnCount = nSharedFileCount;
-        
+
     return (CPLSharedFileInfo *) pasSharedFileList;
 }
 
@@ -2258,7 +2294,7 @@ CPLSharedFileInfo *CPLGetSharedList( int *pnCount )
  * Report open shared files.
  *
  * Dumps all open shared files to the indicated file handle.  If the
- * file handle is NULL information is sent via the CPLDebug() call. 
+ * file handle is NULL information is sent via the CPLDebug() call.
  *
  * @param fp File handle to write to.
  */
@@ -2266,8 +2302,6 @@ CPLSharedFileInfo *CPLGetSharedList( int *pnCount )
 void CPLDumpSharedList( FILE *fp )
 
 {
-    int i;
-
     if( nSharedFileCount > 0 )
     {
         if( fp == NULL )
@@ -2276,18 +2310,18 @@ void CPLDumpSharedList( FILE *fp )
             fprintf( fp, "%d Shared files open.", nSharedFileCount );
     }
 
-    for( i = 0; i < nSharedFileCount; i++ )
+    for( int i = 0; i < nSharedFileCount; i++ )
     {
         if( fp == NULL )
-            CPLDebug( "CPL", 
-                      "%2d %d %4s %s", 
-                      pasSharedFileList[i].nRefCount, 
+            CPLDebug( "CPL",
+                      "%2d %d %4s %s",
+                      pasSharedFileList[i].nRefCount,
                       pasSharedFileList[i].bLarge,
                       pasSharedFileList[i].pszAccess,
                       pasSharedFileList[i].pszFilename );
         else
-            fprintf( fp, "%2d %d %4s %s", 
-                     pasSharedFileList[i].nRefCount, 
+            fprintf( fp, "%2d %d %4s %s",
+                     pasSharedFileList[i].nRefCount,
                      pasSharedFileList[i].bLarge,
                      pasSharedFileList[i].pszAccess,
                      pasSharedFileList[i].pszFilename );
@@ -2312,7 +2346,7 @@ int CPLUnlinkTree( const char *pszPath )
 
     if( VSIStatL( pszPath, &sStatBuf ) != 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "It seems no file system object called '%s' exists.",
                   pszPath );
 
@@ -2326,13 +2360,13 @@ int CPLUnlinkTree( const char *pszPath )
     {
         if( VSIUnlink( pszPath ) != 0 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, "Failed to unlink %s.", 
+            CPLError( CE_Failure, CPLE_AppDefined, "Failed to unlink %s.",
                       pszPath );
 
             return -1;
         }
-        else
-            return 0;
+
+        return 0;
     }
 
 /* -------------------------------------------------------------------- */
@@ -2340,21 +2374,17 @@ int CPLUnlinkTree( const char *pszPath )
 /* -------------------------------------------------------------------- */
     else if( VSI_ISDIR( sStatBuf.st_mode ) )
     {
-        char **papszItems = CPLReadDir( pszPath );
-        int  i;
+        char **papszItems = VSIReadDir( pszPath );
 
-        for( i = 0; papszItems != NULL && papszItems[i] != NULL; i++ )
+        for( int i = 0; papszItems != NULL && papszItems[i] != NULL; i++ )
         {
-            char *pszSubPath;
-            int nErr;
-
             if( EQUAL(papszItems[i],".") || EQUAL(papszItems[i],"..") )
                 continue;
 
-            pszSubPath = CPLStrdup(
+            char *pszSubPath = CPLStrdup(
                 CPLFormFilename( pszPath, papszItems[i], NULL ) );
 
-            nErr = CPLUnlinkTree( pszSubPath );
+            const int nErr = CPLUnlinkTree( pszSubPath );
             CPLFree( pszSubPath );
 
             if( nErr != 0 )
@@ -2363,30 +2393,27 @@ int CPLUnlinkTree( const char *pszPath )
                 return nErr;
             }
         }
-        
+
         CSLDestroy( papszItems );
 
         if( VSIRmdir( pszPath ) != 0 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, "Failed to unlink %s.", 
+            CPLError( CE_Failure, CPLE_AppDefined, "Failed to unlink %s.",
                       pszPath );
 
             return -1;
         }
-        else
-            return 0;
+
+        return 0;
     }
 
 /* -------------------------------------------------------------------- */
 /*      otherwise report an error.                                      */
 /* -------------------------------------------------------------------- */
-    else
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Failed to unlink %s.\nUnrecognised filesystem object.",
-                  pszPath );
-        return 1000;
-    }
+    CPLError( CE_Failure, CPLE_AppDefined,
+              "Failed to unlink %s.\nUnrecognised filesystem object.",
+              pszPath );
+    return 1000;
 }
 
 /************************************************************************/
@@ -2396,36 +2423,39 @@ int CPLUnlinkTree( const char *pszPath )
 int CPLCopyFile( const char *pszNewPath, const char *pszOldPath )
 
 {
-    VSILFILE *fpOld, *fpNew;
-    GByte *pabyBuffer;
-    size_t nBufferSize;
-    size_t nBytesRead;
-    int nRet = 0;
-
 /* -------------------------------------------------------------------- */
 /*      Open old and new file.                                          */
 /* -------------------------------------------------------------------- */
-    fpOld = VSIFOpenL( pszOldPath, "rb" );
+    VSILFILE *fpOld = VSIFOpenL( pszOldPath, "rb" );
     if( fpOld == NULL )
         return -1;
 
-    fpNew = VSIFOpenL( pszNewPath, "wb" );
+    VSILFILE *fpNew = VSIFOpenL( pszNewPath, "wb" );
     if( fpNew == NULL )
     {
-        VSIFCloseL( fpOld );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fpOld ));
         return -1;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Prepare buffer.                                                 */
 /* -------------------------------------------------------------------- */
-    nBufferSize = 1024 * 1024;
-    pabyBuffer = (GByte *) CPLMalloc(nBufferSize);
+    const size_t nBufferSize = 1024 * 1024;
+    GByte *pabyBuffer
+        = reinterpret_cast<GByte *>( VSI_MALLOC_VERBOSE(nBufferSize) );
+    if( pabyBuffer == NULL )
+    {
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fpNew ));
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fpOld ));
+        return -1;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Copy file over till we run out of stuff.                        */
 /* -------------------------------------------------------------------- */
-    do { 
+    size_t nBytesRead = 0;
+    int nRet = 0;
+    do {
         nBytesRead = VSIFReadL( pabyBuffer, 1, nBufferSize, fpOld );
         if( long(nBytesRead) < 0 )
             nRet = -1;
@@ -2438,8 +2468,9 @@ int CPLCopyFile( const char *pszNewPath, const char *pszOldPath )
 /* -------------------------------------------------------------------- */
 /*      Cleanup                                                         */
 /* -------------------------------------------------------------------- */
-    VSIFCloseL( fpNew );
-    VSIFCloseL( fpOld );
+    if( VSIFCloseL( fpNew ) != 0 )
+        nRet = -1;
+    CPL_IGNORE_RET_VAL(VSIFCloseL( fpOld ));
 
     CPLFree( pabyBuffer );
 
@@ -2457,7 +2488,7 @@ int CPLCopyTree( const char *pszNewPath, const char *pszOldPath )
 
     if( VSIStatL( pszOldPath, &sStatBuf ) != 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "It seems no file system object called '%s' exists.",
                   pszOldPath );
 
@@ -2465,7 +2496,7 @@ int CPLCopyTree( const char *pszNewPath, const char *pszOldPath )
     }
     if( VSIStatL( pszNewPath, &sStatBuf ) == 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "It seems that a file system object called '%s' already exists.",
                   pszNewPath );
 
@@ -2476,31 +2507,26 @@ int CPLCopyTree( const char *pszNewPath, const char *pszOldPath )
     {
         if( VSIMkdir( pszNewPath, 0755 ) != 0 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                     "Cannot create directory '%s'.",
                     pszNewPath );
 
             return -1;
         }
 
-        char **papszItems = CPLReadDir( pszOldPath );
-        int  i;
+        char **papszItems = VSIReadDir( pszOldPath );
 
-        for( i = 0; papszItems != NULL && papszItems[i] != NULL; i++ )
+        for( int i = 0; papszItems != NULL && papszItems[i] != NULL; i++ )
         {
-            char *pszNewSubPath;
-            char *pszOldSubPath;
-            int nErr;
-
             if( EQUAL(papszItems[i],".") || EQUAL(papszItems[i],"..") )
                 continue;
 
-            pszNewSubPath = CPLStrdup(
+            char *pszNewSubPath = CPLStrdup(
                 CPLFormFilename( pszNewPath, papszItems[i], NULL ) );
-            pszOldSubPath = CPLStrdup(
+            char *pszOldSubPath = CPLStrdup(
                 CPLFormFilename( pszOldPath, papszItems[i], NULL ) );
 
-            nErr = CPLCopyTree( pszNewSubPath, pszOldSubPath );
+            const int nErr = CPLCopyTree( pszNewSubPath, pszOldSubPath );
 
             CPLFree( pszNewSubPath );
             CPLFree( pszOldSubPath );
@@ -2521,8 +2547,8 @@ int CPLCopyTree( const char *pszNewPath, const char *pszOldPath )
     }
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Unrecognised filesystem object : '%s'.",
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Unrecognized filesystem object : '%s'.",
                   pszOldPath );
         return -1;
     }
@@ -2538,44 +2564,58 @@ int CPLMoveFile( const char *pszNewPath, const char *pszOldPath )
     if( VSIRename( pszOldPath, pszNewPath ) == 0 )
         return 0;
 
-    int nRet = CPLCopyFile( pszNewPath, pszOldPath );
+    const int nRet = CPLCopyFile( pszNewPath, pszOldPath );
 
     if( nRet == 0 )
         VSIUnlink( pszOldPath );
-    
     return nRet;
 }
 
 /************************************************************************/
+/*                             CPLSymlink()                             */
+/************************************************************************/
+
+int CPLSymlink( const char*
+#ifndef WIN32
+                pszOldPath
+#endif
+                , const char*
+#ifndef WIN32
+                pszNewPath
+#endif
+                , char** /* papszOptions */)
+{
+#ifdef WIN32
+    return -1;
+#else
+    return symlink(pszOldPath, pszNewPath);
+#endif
+}
+
+/************************************************************************/
 /* ==================================================================== */
 /*                              CPLLocaleC                              */
 /* ==================================================================== */
 /************************************************************************/
 
-#include <locale.h>
-
 /************************************************************************/
 /*                             CPLLocaleC()                             */
 /************************************************************************/
 
-CPLLocaleC::CPLLocaleC()
-
+CPLLocaleC::CPLLocaleC() :
+    pszOldLocale(NULL)
 {
     if( CSLTestBoolean(CPLGetConfigOption("GDAL_DISABLE_CPLLOCALEC","NO")) )
+        return;
+
+    pszOldLocale = CPLStrdup(CPLsetlocale(LC_NUMERIC,NULL));
+    if( EQUAL(pszOldLocale,"C")
+        || EQUAL(pszOldLocale,"POSIX")
+        || CPLsetlocale(LC_NUMERIC,"C") == NULL )
     {
+        CPLFree( pszOldLocale );
         pszOldLocale = NULL;
     }
-    else
-    {
-        pszOldLocale = CPLStrdup(CPLsetlocale(LC_NUMERIC,NULL));
-        if( EQUAL(pszOldLocale,"C")
-            || EQUAL(pszOldLocale,"POSIX")
-            || CPLsetlocale(LC_NUMERIC,"C") == NULL )
-        {
-            CPLFree( pszOldLocale );
-            pszOldLocale = NULL;
-        }
-    }
 }
 
 /************************************************************************/
@@ -2585,11 +2625,73 @@ CPLLocaleC::CPLLocaleC()
 CPLLocaleC::~CPLLocaleC()
 
 {
+    if( pszOldLocale == NULL )
+        return;
+
+    CPLsetlocale( LC_NUMERIC, pszOldLocale );
+    CPLFree( pszOldLocale );
+}
+
+
+/************************************************************************/
+/*                        CPLThreadLocaleC()                            */
+/************************************************************************/
+
+CPLThreadLocaleC::CPLThreadLocaleC()
+
+{
+#ifdef HAVE_USELOCALE
+    nNewLocale = newlocale (LC_NUMERIC_MASK, "C", NULL);
+    nOldLocale = uselocale(nNewLocale);
+#else
+
+#if defined(_MSC_VER)
+    nOldValConfigThreadLocale = _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
+    pszOldLocale = setlocale(LC_NUMERIC, "C");
+    if( pszOldLocale )
+        pszOldLocale = CPLStrdup(pszOldLocale);
+#else
+    pszOldLocale = CPLStrdup(CPLsetlocale(LC_NUMERIC,NULL));
+    if( EQUAL(pszOldLocale,"C")
+        || EQUAL(pszOldLocale,"POSIX")
+        || CPLsetlocale(LC_NUMERIC,"C") == NULL )
+    {
+        CPLFree( pszOldLocale );
+        pszOldLocale = NULL;
+    }
+#endif
+
+#endif
+}
+
+/************************************************************************/
+/*                       ~CPLThreadLocaleC()                            */
+/************************************************************************/
+
+CPLThreadLocaleC::~CPLThreadLocaleC()
+
+{
+#ifdef HAVE_USELOCALE
+    uselocale(nOldLocale);
+    freelocale(nNewLocale);
+#else
+
+#if defined(_MSC_VER)
+    if( pszOldLocale != NULL )
+    {
+        setlocale(LC_NUMERIC, pszOldLocale);
+        CPLFree( pszOldLocale );
+    }
+    _configthreadlocale(nOldValConfigThreadLocale);
+#else
     if( pszOldLocale != NULL )
     {
         CPLsetlocale( LC_NUMERIC, pszOldLocale );
         CPLFree( pszOldLocale );
     }
+#endif
+
+#endif
 }
 
 
@@ -2600,7 +2702,7 @@ CPLLocaleC::~CPLLocaleC()
 /**
  * Prevents parallel executions of setlocale().
  *
- * Calling setlocale() concurrently from two or more threads is a 
+ * Calling setlocale() concurrently from two or more threads is a
  * potential data race. A mutex is used to provide a critical region so
  * that only one thread at a time can be executing setlocale().
  *
@@ -2618,7 +2720,9 @@ char* CPLsetlocale (int category, const char* locale)
     char* pszRet = setlocale(category, locale);
     if( pszRet == NULL )
         return pszRet;
-    return (char*)CPLSPrintf("%s", pszRet); /* to make it thread-locale storage */
+
+    // Make it thread-locale storage.
+    return const_cast<char*>( CPLSPrintf("%s", pszRet) );
 }
 
 
@@ -2638,23 +2742,24 @@ void CPLCleanupSetlocaleMutex(void)
 /************************************************************************/
 
 /**
- * Check for file existance.
+ * Check for file existence.
  *
  * The function checks if a named file exists in the filesystem, hopefully
  * in an efficient fashion if a sibling file list is available.   It exists
  * primarily to do faster file checking for functions like GDAL open methods
- * that get a list of files from the target directory. 
+ * that get a list of files from the target directory.
  *
  * If the sibling file list exists (is not NULL) it is assumed to be a list
  * of files in the same directory as the target file, and it will be checked
  * (case insensitively) for a match.  If a match is found, pszFilename is
- * updated with the correct case and TRUE is returned. 
+ * updated with the correct case and TRUE is returned.
  *
  * If papszSiblingFiles is NULL, a VSIStatL() is used to test for the files
- * existance, and no case insensitive testing is done. 
+ * existence, and no case insensitive testing is done.
  *
- * @param pszFilename name of file to check for - filename case updated in some cases.
- * @param papszSiblingFiles a list of files in the same directory as 
+ * @param pszFilename name of file to check for - filename case updated in
+ * some cases.
+ * @param papszSiblingFiles a list of files in the same directory as
  * pszFilename if available, or NULL. This list should have no path components.
  *
  * @return TRUE if a match is found, or FALSE if not.
@@ -2677,14 +2782,13 @@ int CPLCheckForFile( char *pszFilename, char **papszSiblingFiles )
 /*      We have sibling files, compare the non-path filename portion    */
 /*      of pszFilename too all entries.                                 */
 /* -------------------------------------------------------------------- */
-    CPLString osFileOnly = CPLGetFilename( pszFilename );
-    int i;
+    const CPLString osFileOnly = CPLGetFilename( pszFilename );
 
-    for( i = 0; papszSiblingFiles[i] != NULL; i++ )
+    for( int i = 0; papszSiblingFiles[i] != NULL; i++ )
     {
         if( EQUAL(papszSiblingFiles[i],osFileOnly) )
         {
-            strcpy( pszFilename + strlen(pszFilename) - strlen(osFileOnly), 
+            strcpy( pszFilename + strlen(pszFilename) - strlen(osFileOnly),
                     papszSiblingFiles[i] );
             return TRUE;
         }
@@ -2707,7 +2811,7 @@ void *CPLCreateZip( const char *pszZipFilename, char **papszOptions )
     return NULL;
 }
 
-CPLErr CPLCreateFileInZip( void *hZip, const char *pszFilename, 
+CPLErr CPLCreateFileInZip( void *hZip, const char *pszFilename,
                            char **papszOptions )
 
 {
diff --git a/port/cpl_conv.h b/port/cpl_conv.h
index 45ca021..2e3d883 100644
--- a/port/cpl_conv.h
+++ b/port/cpl_conv.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_conv.h 28601 2015-03-03 11:06:40Z rouault $
+ * $Id: cpl_conv.h 33666 2016-03-07 05:21:07Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Convenience functions declarations.
@@ -52,8 +52,10 @@ void CPL_DLL CPLVerifyConfiguration(void);
 
 const char CPL_DLL * CPL_STDCALL
 CPLGetConfigOption( const char *, const char * ) CPL_WARN_UNUSED_RESULT;
+const char CPL_DLL * CPL_STDCALL
+CPLGetThreadLocalConfigOption( const char *, const char * ) CPL_WARN_UNUSED_RESULT;
 void CPL_DLL CPL_STDCALL CPLSetConfigOption( const char *, const char * );
-void CPL_DLL CPL_STDCALL CPLSetThreadLocalConfigOption( const char *pszKey, 
+void CPL_DLL CPL_STDCALL CPLSetThreadLocalConfigOption( const char *pszKey,
                                                         const char *pszValue );
 void CPL_DLL CPL_STDCALL CPLFreeConfig(void);
 
@@ -64,7 +66,7 @@ void CPL_DLL CPL_STDCALL CPLFreeConfig(void);
 void CPL_DLL *CPLMalloc( size_t ) CPL_WARN_UNUSED_RESULT;
 void CPL_DLL *CPLCalloc( size_t, size_t ) CPL_WARN_UNUSED_RESULT;
 void CPL_DLL *CPLRealloc( void *, size_t ) CPL_WARN_UNUSED_RESULT;
-char CPL_DLL *CPLStrdup( const char * ) CPL_WARN_UNUSED_RESULT;
+char CPL_DLL *CPLStrdup( const char * ) CPL_WARN_UNUSED_RESULT CPL_RETURNS_NONNULL;
 char CPL_DLL *CPLStrlwr( char *);
 
 #define CPLFree VSIFree
@@ -78,7 +80,7 @@ const char CPL_DLL *CPLReadLineL( VSILFILE * );
 const char CPL_DLL *CPLReadLine2L( VSILFILE * , int nMaxCols, char** papszOptions);
 
 /* -------------------------------------------------------------------- */
-/*      Convert ASCII string to floationg point number                  */
+/*      Convert ASCII string to floating point number                  */
 /*      (THESE FUNCTIONS ARE NOT LOCALE AWARE!).                        */
 /* -------------------------------------------------------------------- */
 double CPL_DLL CPLAtof(const char *);
@@ -90,7 +92,7 @@ float CPL_DLL CPLStrtofDelim(const char *, char **, char);
 
 /* -------------------------------------------------------------------- */
 /*      Convert number to string.  This function is locale agnostic     */
-/*      (ie. it will support "," or "." regardless of current locale)   */
+/*      (i.e. it will support "," or "." regardless of current locale)  */
 /* -------------------------------------------------------------------- */
 double CPL_DLL CPLAtofM(const char *);
 
@@ -132,39 +134,39 @@ int CPL_DLL CPLGetExecPath( char *pszPathBuf, int nMaxLength );
 /* -------------------------------------------------------------------- */
 /*      Filename handling functions.                                    */
 /* -------------------------------------------------------------------- */
-const char CPL_DLL *CPLGetPath( const char * );
-const char CPL_DLL *CPLGetDirname( const char * );
-const char CPL_DLL *CPLGetFilename( const char * );
-const char CPL_DLL *CPLGetBasename( const char * );
-const char CPL_DLL *CPLGetExtension( const char * );
+const char CPL_DLL *CPLGetPath( const char * ) CPL_WARN_UNUSED_RESULT CPL_RETURNS_NONNULL;
+const char CPL_DLL *CPLGetDirname( const char * ) CPL_WARN_UNUSED_RESULT CPL_RETURNS_NONNULL;
+const char CPL_DLL *CPLGetFilename( const char * ) CPL_WARN_UNUSED_RESULT CPL_RETURNS_NONNULL;
+const char CPL_DLL *CPLGetBasename( const char * ) CPL_WARN_UNUSED_RESULT CPL_RETURNS_NONNULL;
+const char CPL_DLL *CPLGetExtension( const char * ) CPL_WARN_UNUSED_RESULT CPL_RETURNS_NONNULL;
 char       CPL_DLL *CPLGetCurrentDir(void);
 const char CPL_DLL *CPLFormFilename( const char *pszPath,
                                      const char *pszBasename,
-                                     const char *pszExtension );
+                                     const char *pszExtension ) CPL_WARN_UNUSED_RESULT CPL_RETURNS_NONNULL;
 const char CPL_DLL *CPLFormCIFilename( const char *pszPath,
                                        const char *pszBasename,
-                                       const char *pszExtension );
-const char CPL_DLL *CPLResetExtension( const char *, const char * );
-const char CPL_DLL *CPLProjectRelativeFilename( const char *pszProjectDir, 
-                                            const char *pszSecondaryFilename );
+                                       const char *pszExtension ) CPL_WARN_UNUSED_RESULT CPL_RETURNS_NONNULL;
+const char CPL_DLL *CPLResetExtension( const char *, const char * ) CPL_WARN_UNUSED_RESULT CPL_RETURNS_NONNULL;
+const char CPL_DLL *CPLProjectRelativeFilename( const char *pszProjectDir,
+                                            const char *pszSecondaryFilename ) CPL_WARN_UNUSED_RESULT CPL_RETURNS_NONNULL;
 int CPL_DLL CPLIsFilenameRelative( const char *pszFilename );
-const char CPL_DLL *CPLExtractRelativePath(const char *, const char *, int *);
-const char CPL_DLL *CPLCleanTrailingSlash( const char * );
-char CPL_DLL      **CPLCorrespondingPaths( const char *pszOldFilename, 
-                                           const char *pszNewFilename, 
-                                           char **papszFileList );
+const char CPL_DLL *CPLExtractRelativePath(const char *, const char *, int *) CPL_WARN_UNUSED_RESULT CPL_RETURNS_NONNULL;
+const char CPL_DLL *CPLCleanTrailingSlash( const char * ) CPL_WARN_UNUSED_RESULT CPL_RETURNS_NONNULL;
+char CPL_DLL      **CPLCorrespondingPaths( const char *pszOldFilename,
+                                           const char *pszNewFilename,
+                                           char **papszFileList ) CPL_WARN_UNUSED_RESULT;
 int CPL_DLL CPLCheckForFile( char *pszFilename, char **papszSiblingList );
 
-const char CPL_DLL *CPLGenerateTempFilename( const char *pszStem );
+const char CPL_DLL *CPLGenerateTempFilename( const char *pszStem ) CPL_WARN_UNUSED_RESULT CPL_RETURNS_NONNULL;
 
 /* -------------------------------------------------------------------- */
 /*      Find File Function                                              */
 /* -------------------------------------------------------------------- */
 typedef const char *(*CPLFileFinder)(const char *, const char *);
 
-const char    CPL_DLL *CPLFindFile(const char *pszClass, 
+const char    CPL_DLL *CPLFindFile(const char *pszClass,
                                    const char *pszBasename);
-const char    CPL_DLL *CPLDefaultFindFile(const char *pszClass, 
+const char    CPL_DLL *CPLDefaultFindFile(const char *pszClass,
                                           const char *pszBasename);
 void          CPL_DLL CPLPushFileFinder( CPLFileFinder pfnFinder );
 CPLFileFinder CPL_DLL CPLPopFileFinder(void);
@@ -175,7 +177,7 @@ void          CPL_DLL CPLFinderClean(void);
 /* -------------------------------------------------------------------- */
 /*      Safe version of stat() that works properly on stuff like "C:".  */
 /* -------------------------------------------------------------------- */
-int CPL_DLL     CPLStat( const char *, VSIStatBuf * );
+int CPL_DLL     CPLStat( const char *, VSIStatBuf * ) CPL_WARN_UNUSED_RESULT;
 
 /* -------------------------------------------------------------------- */
 /*      Reference counted file handle manager.  Makes sharing file      */
@@ -204,7 +206,7 @@ const char CPL_DLL *CPLDecToDMS( double dfAngle, const char * pszAxis,
 double CPL_DLL CPLPackedDMSToDec( double );
 double CPL_DLL CPLDecToPackedDMS( double dfDec );
 
-void CPL_DLL CPLStringToComplex( const char *pszString, 
+void CPL_DLL CPLStringToComplex( const char *pszString,
                                  double *pdfReal, double *pdfImag );
 
 /* -------------------------------------------------------------------- */
@@ -214,13 +216,14 @@ int CPL_DLL CPLUnlinkTree( const char * );
 int CPL_DLL CPLCopyFile( const char *pszNewPath, const char *pszOldPath );
 int CPL_DLL CPLCopyTree( const char *pszNewPath, const char *pszOldPath );
 int CPL_DLL CPLMoveFile( const char *pszNewPath, const char *pszOldPath );
+int CPL_DLL CPLSymlink( const char* pszOldPath, const char* pszNewPath, char** papszOptions );
 
 /* -------------------------------------------------------------------- */
 /*      ZIP Creation.                                                   */
 /* -------------------------------------------------------------------- */
 #define CPL_ZIP_API_OFFERED
 void CPL_DLL  *CPLCreateZip( const char *pszZipFilename, char **papszOptions );
-CPLErr CPL_DLL CPLCreateFileInZip( void *hZip, const char *pszFilename, 
+CPLErr CPL_DLL CPLCreateFileInZip( void *hZip, const char *pszFilename,
                                    char **papszOptions );
 CPLErr CPL_DLL CPLWriteFileInZip( void *hZip, const void *pBuffer, int nBufferSize );
 CPLErr CPL_DLL CPLCloseFileInZip( void *hZip );
@@ -243,7 +246,7 @@ void CPL_DLL *CPLZLibInflate( const void* ptr, size_t nBytes,
 int CPL_DLL CPLValidateXML(const char* pszXMLFilename,
                            const char* pszXSDFilename,
                            char** papszOptions);
-						   
+
 /* -------------------------------------------------------------------- */
 /*      Locale handling. Prevents parallel executions of setlocale().   */
 /* -------------------------------------------------------------------- */
@@ -253,7 +256,7 @@ void CPLCleanupSetlocaleMutex(void);
 CPL_C_END
 
 /* -------------------------------------------------------------------- */
-/*      C++ object for temporariliy forcing a LC_NUMERIC locale to "C". */
+/*      C++ object for temporarily forcing a LC_NUMERIC locale to "C".  */
 /* -------------------------------------------------------------------- */
 
 #if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS)
@@ -268,8 +271,34 @@ private:
     char *pszOldLocale;
 
     /* Make it non-copyable */
-    CPLLocaleC(CPLLocaleC&);
-    CPLLocaleC& operator=(CPLLocaleC&);
+    CPLLocaleC(const CPLLocaleC&);
+    CPLLocaleC& operator=(const CPLLocaleC&);
+};
+
+// Does the same as CPLLocaleC except that, when available, it tries to
+// only affect the current thread. But code that would be dependent of
+// setlocale(LC_NUMERIC, NULL) returning "C", such as current proj.4 versions,
+// will not work depending on the actual implementation
+class CPL_DLL CPLThreadLocaleC
+{
+public:
+    CPLThreadLocaleC();
+    ~CPLThreadLocaleC();
+
+private:
+#ifdef HAVE_USELOCALE
+    locale_t nNewLocale;
+    locale_t nOldLocale;
+#else
+#if defined(_MSC_VER)
+    int   nOldValConfigThreadLocale;
+#endif
+    char *pszOldLocale;
+#endif
+
+    /* Make it non-copyable */
+    CPLThreadLocaleC(const CPLThreadLocaleC&);
+    CPLThreadLocaleC& operator=(const CPLThreadLocaleC&);
 };
 
 #endif /* def __cplusplus */
diff --git a/port/cpl_csv.cpp b/port/cpl_csv.cpp
index 29ee2cf..ef44a4e 100644
--- a/port/cpl_csv.cpp
+++ b/port/cpl_csv.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_csv.cpp 29330 2015-06-14 12:11:11Z rouault $
+ * $Id: cpl_csv.cpp 33724 2016-03-16 17:14:11Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  CSV (comma separated value) file access.
@@ -33,45 +33,39 @@
 #include "cpl_multiproc.h"
 #include "gdal_csv.h"
 
-CPL_CVSID("$Id: cpl_csv.cpp 29330 2015-06-14 12:11:11Z rouault $");
+CPL_CVSID("$Id: cpl_csv.cpp 33724 2016-03-16 17:14:11Z goatbar $");
 
 /* ==================================================================== */
-/*      The CSVTable is a persistant set of info about an open CSV      */
+/*      The CSVTable is a persistent set of info about an open CSV      */
 /*      table.  While it doesn't currently maintain a record index,     */
 /*      or in-memory copy of the table, it could be changed to do so    */
 /*      in the future.                                                  */
 /* ==================================================================== */
 typedef struct ctb {
-    FILE        *fp;
-
+    VSILFILE   *fp;
     struct ctb *psNext;
-
-    char        *pszFilename;
-
-    char        **papszFieldNames;
-
-    char        **papszRecFields;
-
+    char       *pszFilename;
+    char      **papszFieldNames;
+    char      **papszRecFields;
     int         iLastLine;
-
     int         bNonUniqueKey;
 
     /* Cache for whole file */
     int         nLineCount;
-    char        **papszLines;
-    int         *panLineIndex;
-    char        *pszRawData;
+    char      **papszLines;
+    int        *panLineIndex;
+    char       *pszRawData;
 } CSVTable;
 
-
-static void CSVDeaccessInternal( CSVTable **ppsCSVTableList, int bCanUseTLS, const char * pszFilename );
+static void CSVDeaccessInternal( CSVTable **ppsCSVTableList, int bCanUseTLS,
+                                 const char * pszFilename );
 
 /************************************************************************/
 /*                            CSVFreeTLS()                              */
 /************************************************************************/
-static void CSVFreeTLS(void* pData)
+static void CSVFreeTLS( void* pData )
 {
-    CSVDeaccessInternal( (CSVTable **)pData, FALSE, NULL );
+    CSVDeaccessInternal( reinterpret_cast<CSVTable **>( pData ), FALSE, NULL );
     CPLFree(pData);
 }
 
@@ -92,44 +86,45 @@ static void CSVFreeTLS(void* pData)
 static CSVTable *CSVAccess( const char * pszFilename )
 
 {
-    CSVTable    *psTable;
-    FILE        *fp;
-
 /* -------------------------------------------------------------------- */
 /*      Fetch the table, and allocate the thread-local pointer to it    */
 /*      if there isn't already one.                                     */
 /* -------------------------------------------------------------------- */
-    CSVTable **ppsCSVTableList;
-
-    ppsCSVTableList = (CSVTable **) CPLGetTLS( CTLS_CSVTABLEPTR );
+    int bMemoryError = FALSE;
+    CSVTable **ppsCSVTableList = reinterpret_cast<CSVTable **>(
+        CPLGetTLSEx( CTLS_CSVTABLEPTR, &bMemoryError ) );
+    if( bMemoryError )
+        return NULL;
     if( ppsCSVTableList == NULL )
     {
-        ppsCSVTableList = (CSVTable **) CPLCalloc(1,sizeof(CSVTable*));
+        ppsCSVTableList = reinterpret_cast<CSVTable **>(
+            VSI_CALLOC_VERBOSE( 1, sizeof(CSVTable*) ) );
+        if( ppsCSVTableList == NULL )
+            return NULL;
         CPLSetTLSWithFreeFunc( CTLS_CSVTABLEPTR, ppsCSVTableList, CSVFreeTLS );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Is the table already in the list.                               */
 /* -------------------------------------------------------------------- */
-    for( psTable = *ppsCSVTableList; 
-         psTable != NULL; 
+    for( CSVTable *psTable = *ppsCSVTableList;
+         psTable != NULL;
          psTable = psTable->psNext )
     {
-        if( EQUAL(psTable->pszFilename,pszFilename) )
+        if( EQUAL(psTable->pszFilename, pszFilename) )
         {
             /*
              * Eventually we should consider promoting to the front of
              * the list to accelerate frequently accessed tables.
              */
-
-            return( psTable );
+            return psTable;
         }
     }
 
 /* -------------------------------------------------------------------- */
 /*      If not, try to open it.                                         */
 /* -------------------------------------------------------------------- */
-    fp = VSIFOpen( pszFilename, "rb" );
+    VSILFILE *fp = VSIFOpenL( pszFilename, "rb" );
     if( fp == NULL )
         return NULL;
 
@@ -137,52 +132,65 @@ static CSVTable *CSVAccess( const char * pszFilename )
 /*      Create an information structure about this table, and add to    */
 /*      the front of the list.                                          */
 /* -------------------------------------------------------------------- */
-    psTable = (CSVTable *) CPLCalloc(sizeof(CSVTable),1);
+    CSVTable * const psTable = reinterpret_cast<CSVTable *>(
+        VSI_CALLOC_VERBOSE( sizeof(CSVTable), 1 ) );
+    if( psTable == NULL )
+    {
+        VSIFCloseL(fp);
+        return NULL;
+    }
 
     psTable->fp = fp;
-    psTable->pszFilename = CPLStrdup( pszFilename );
+    psTable->pszFilename = VSI_STRDUP_VERBOSE( pszFilename );
+    if( psTable->pszFilename == NULL )
+    {
+        VSIFree(psTable);
+        VSIFCloseL(fp);
+        return NULL;
+    }
     psTable->bNonUniqueKey = FALSE; /* as far as we know now */
     psTable->psNext = *ppsCSVTableList;
-    
+
     *ppsCSVTableList = psTable;
 
 /* -------------------------------------------------------------------- */
 /*      Read the table header record containing the field names.        */
 /* -------------------------------------------------------------------- */
-    psTable->papszFieldNames = CSVReadParseLine( fp );
+    psTable->papszFieldNames = CSVReadParseLineL( fp );
 
-    return( psTable );
+    return psTable;
 }
 
 /************************************************************************/
 /*                            CSVDeaccess()                             */
 /************************************************************************/
 
-static void CSVDeaccessInternal( CSVTable **ppsCSVTableList, int bCanUseTLS, const char * pszFilename )
+static void CSVDeaccessInternal( CSVTable **ppsCSVTableList, int bCanUseTLS,
+                                 const char * pszFilename )
 
 {
-    CSVTable    *psLast, *psTable;
-    
     if( ppsCSVTableList == NULL )
         return;
-    
+
 /* -------------------------------------------------------------------- */
 /*      A NULL means deaccess all tables.                               */
 /* -------------------------------------------------------------------- */
     if( pszFilename == NULL )
     {
         while( *ppsCSVTableList != NULL )
-            CSVDeaccessInternal( ppsCSVTableList, bCanUseTLS, (*ppsCSVTableList)->pszFilename );
-        
+            CSVDeaccessInternal( ppsCSVTableList, bCanUseTLS,
+                                 (*ppsCSVTableList)->pszFilename );
+
         return;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Find this table.                                                */
 /* -------------------------------------------------------------------- */
-    psLast = NULL;
-    for( psTable = *ppsCSVTableList;
-         psTable != NULL && !EQUAL(psTable->pszFilename,pszFilename);
+    CSVTable *psLast = NULL;
+    CSVTable *psTable = *ppsCSVTableList;
+    for( ;
+         psTable != NULL && !EQUAL(psTable->pszFilename, pszFilename);
          psTable = psTable->psNext )
     {
         psLast = psTable;
@@ -207,7 +215,7 @@ static void CSVDeaccessInternal( CSVTable **ppsCSVTableList, int bCanUseTLS, con
 /*      Free the table.                                                 */
 /* -------------------------------------------------------------------- */
     if( psTable->fp != NULL )
-        VSIFClose( psTable->fp );
+        VSIFCloseL( psTable->fp );
 
     CSLDestroy( psTable->papszFieldNames );
     CSLDestroy( psTable->papszRecFields );
@@ -224,12 +232,13 @@ static void CSVDeaccessInternal( CSVTable **ppsCSVTableList, int bCanUseTLS, con
 
 void CSVDeaccess( const char * pszFilename )
 {
-    CSVTable **ppsCSVTableList;
 /* -------------------------------------------------------------------- */
 /*      Fetch the table, and allocate the thread-local pointer to it    */
 /*      if there isn't already one.                                     */
 /* -------------------------------------------------------------------- */
-    ppsCSVTableList = (CSVTable **) CPLGetTLS( CTLS_CSVTABLEPTR );
+    int bMemoryError = FALSE;
+    CSVTable **ppsCSVTableList = reinterpret_cast<CSVTable **>(
+        CPLGetTLSEx( CTLS_CSVTABLEPTR, &bMemoryError ) );
 
     CSVDeaccessInternal(ppsCSVTableList, TRUE, pszFilename);
 }
@@ -246,30 +255,30 @@ void CSVDeaccess( const char * pszFilename )
 static char **CSVSplitLine( const char *pszString, char chDelimiter )
 
 {
-    char        **papszRetList = NULL;
-    char        *pszToken;
-    int         nTokenMax, nTokenLen;
 
-    pszToken = (char *) CPLCalloc(10,1);
-    nTokenMax = 10;
-    
+    char *pszToken = reinterpret_cast<char *>( VSI_CALLOC_VERBOSE( 10, 1 ) );
+    if( pszToken == NULL )
+        return NULL;
+
+    int nTokenMax = 10;
+    char **papszRetList = NULL;
+
     while( pszString != NULL && *pszString != '\0' )
     {
-        int     bInString = FALSE;
+        bool bInString = false;
+        int nTokenLen = 0;
 
-        nTokenLen = 0;
-        
-        /* Try to find the next delimeter, marking end of token */
+        /* Try to find the next delimiter, marking end of token */
         for( ; *pszString != '\0'; pszString++ )
         {
 
-            /* End if this is a delimeter skip it and break. */
+            /* End if this is a delimiter skip it and break. */
             if( !bInString && *pszString == chDelimiter )
             {
                 pszString++;
                 break;
             }
-            
+
             if( *pszString == '"' )
             {
                 if( !bInString || pszString[1] != '"' )
@@ -286,7 +295,15 @@ static char **CSVSplitLine( const char *pszString, char chDelimiter )
             if( nTokenLen >= nTokenMax-2 )
             {
                 nTokenMax = nTokenMax * 2 + 10;
-                pszToken = (char *) CPLRealloc( pszToken, nTokenMax );
+                char* pszTokenNew = reinterpret_cast<char *>(
+                    VSI_REALLOC_VERBOSE( pszToken, nTokenMax ) );
+                if( pszTokenNew == NULL )
+                {
+                    VSIFree(pszToken);
+                    CSLDestroy(papszRetList);
+                    return NULL;
+                }
+                pszToken = pszTokenNew;
             }
 
             pszToken[nTokenLen] = *pszString;
@@ -294,21 +311,32 @@ static char **CSVSplitLine( const char *pszString, char chDelimiter )
         }
 
         pszToken[nTokenLen] = '\0';
-        papszRetList = CSLAddString( papszRetList, pszToken );
+        char** papszRetListNew = CSLAddStringMayFail( papszRetList, pszToken );
+        if( papszRetListNew == NULL )
+        {
+            VSIFree(pszToken);
+            CSLDestroy(papszRetList);
+            return NULL;
+        }
+        papszRetList = papszRetListNew;
 
         /* If the last token is an empty token, then we have to catch
-         * it now, otherwise we won't reenter the loop and it will be lost. 
+         * it now, otherwise we won't reenter the loop and it will be lost.
          */
         if ( *pszString == '\0' && *(pszString-1) == chDelimiter )
         {
-            papszRetList = CSLAddString( papszRetList, "" );
+            papszRetListNew = CSLAddStringMayFail( papszRetList, "" );
+            if( papszRetListNew == NULL )
+            {
+                VSIFree(pszToken);
+                CSLDestroy(papszRetList);
+                return NULL;
+            }
+            papszRetList = papszRetListNew;
         }
     }
 
-    if( papszRetList == NULL )
-        papszRetList = (char **) CPLCalloc(sizeof(char *),1);
-
-    CPLFree( pszToken );
+    VSIFree( pszToken );
 
     return papszRetList;
 }
@@ -325,9 +353,9 @@ static char **CSVSplitLine( const char *pszString, char chDelimiter )
 static char *CSVFindNextLine( char *pszThisLine )
 
 {
-    int  nQuoteCount = 0, i;
+    int i = 0;  // i is used after the for loop.
 
-    for( i = 0; pszThisLine[i] != '\0'; i++ )
+    for( int nQuoteCount = 0; pszThisLine[i] != '\0'; i++ )
     {
         if( pszThisLine[i] == '\"'
             && (i == 0 || pszThisLine[i-1] != '\\') )
@@ -343,8 +371,8 @@ static char *CSVFindNextLine( char *pszThisLine )
 
     if( pszThisLine[i] == '\0' )
         return NULL;
-    else
-        return pszThisLine + i;
+
+    return pszThisLine + i;
 }
 
 /************************************************************************/
@@ -353,12 +381,17 @@ static char *CSVFindNextLine( char *pszThisLine )
 /*      Load entire file into memory and setup index if possible.       */
 /************************************************************************/
 
+// TODO(schwehr): Clean up all the casting in CSVIngest.
 static void CSVIngest( const char *pszFilename )
 
 {
     CSVTable *psTable = CSVAccess( pszFilename );
-    int       nFileLen, i, nMaxLineCount, iLine = 0;
-    char *pszThisLine;
+    if( psTable == NULL )
+    {
+        CPLError( CE_Failure, CPLE_FileIO, "Failed to open file: %s",
+                  pszFilename );
+        return;
+    }
 
     if( psTable->pszRawData != NULL )
         return;
@@ -366,18 +399,35 @@ static void CSVIngest( const char *pszFilename )
 /* -------------------------------------------------------------------- */
 /*      Ingest whole file.                                              */
 /* -------------------------------------------------------------------- */
-    VSIFSeek( psTable->fp, 0, SEEK_END );
-    nFileLen = VSIFTell( psTable->fp );
-    VSIRewind( psTable->fp );
+    if( VSIFSeekL( psTable->fp, 0, SEEK_END ) != 0 )
+    {
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Failed using seek end and tell to get file length: %s",
+                  pszFilename );
+        return;
+    }
+    const vsi_l_offset nFileLen = VSIFTellL( psTable->fp );
+    if( static_cast<long>(nFileLen) == -1 )
+    {
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Failed using seek end and tell to get file length: %s",
+                  pszFilename );
+        return;
+    }
+    VSIRewindL( psTable->fp );
 
-    psTable->pszRawData = (char *) CPLMalloc(nFileLen+1);
-    if( (int) VSIFRead( psTable->pszRawData, 1, nFileLen, psTable->fp ) 
-        != nFileLen )
+    psTable->pszRawData = reinterpret_cast<char *>(
+        VSI_MALLOC_VERBOSE( static_cast<size_t>(nFileLen) + 1) );
+    if( psTable->pszRawData == NULL )
+        return;
+    if( VSIFReadL( psTable->pszRawData, 1,
+                   static_cast<size_t>(nFileLen), psTable->fp )
+        != static_cast<size_t>(nFileLen) )
     {
         CPLFree( psTable->pszRawData );
         psTable->pszRawData = NULL;
 
-        CPLError( CE_Failure, CPLE_FileIO, "Read of file %s failed.", 
+        CPLError( CE_Failure, CPLE_FileIO, "Read of file %s failed.",
                   psTable->pszFilename );
         return;
     }
@@ -387,23 +437,27 @@ static void CSVIngest( const char *pszFilename )
 /* -------------------------------------------------------------------- */
 /*      Get count of newlines so we can allocate line array.            */
 /* -------------------------------------------------------------------- */
-    nMaxLineCount = 0;
-    for( i = 0; i < nFileLen; i++ )
+    int nMaxLineCount = 0;
+    for( int i = 0; i < static_cast<int>(nFileLen); i++ )
     {
         if( psTable->pszRawData[i] == 10 )
             nMaxLineCount++;
     }
 
-    psTable->papszLines = (char **) CPLCalloc(sizeof(char*),nMaxLineCount);
-    
+    psTable->papszLines = reinterpret_cast<char **>(
+        VSI_CALLOC_VERBOSE( sizeof(char*), nMaxLineCount ) );
+    if( psTable->papszLines == NULL )
+        return;
+
 /* -------------------------------------------------------------------- */
 /*      Build a list of record pointers into the raw data buffer        */
 /*      based on line terminators.  Zero terminate the line             */
 /*      strings.                                                        */
 /* -------------------------------------------------------------------- */
     /* skip header line */
-    pszThisLine = CSVFindNextLine( psTable->pszRawData );
+    char *pszThisLine = CSVFindNextLine( psTable->pszRawData );
 
+    int iLine = 0;
     while( pszThisLine != NULL && iLine < nMaxLineCount )
     {
         psTable->papszLines[iLine++] = pszThisLine;
@@ -417,8 +471,12 @@ static void CSVIngest( const char *pszFilename )
 /*      ascending order so that binary searches can be done on the      */
 /*      array.                                                          */
 /* -------------------------------------------------------------------- */
-    psTable->panLineIndex = (int *) CPLMalloc(sizeof(int)*psTable->nLineCount);
-    for( i = 0; i < psTable->nLineCount; i++ )
+    psTable->panLineIndex = reinterpret_cast<int *>(
+        VSI_MALLOC_VERBOSE( sizeof(int) * psTable->nLineCount ) );
+    if( psTable->panLineIndex == NULL )
+        return;
+
+    for( int i = 0; i < psTable->nLineCount; i++ )
     {
         psTable->panLineIndex[i] = atoi(psTable->papszLines[i]);
 
@@ -435,7 +493,7 @@ static void CSVIngest( const char *pszFilename )
 /* -------------------------------------------------------------------- */
 /*      We should never need the file handle against, so close it.      */
 /* -------------------------------------------------------------------- */
-    VSIFClose( psTable->fp );
+    VSIFCloseL( psTable->fp );
     psTable->fp = NULL;
 }
 
@@ -452,27 +510,31 @@ static void CSVIngest( const char *pszFilename )
  */
 char CSVDetectSeperator (const char* pszLine)
 {
-    int     bInString = FALSE;
+    bool    bInString = false;
     char    chDelimiter = '\0';
     int     nCountSpace = 0;
 
     for( ; *pszLine != '\0'; pszLine++ )
     {
-        if( !bInString && (*pszLine == ',' || *pszLine == ';' || *pszLine == '\t'))
+        if( !bInString && ( *pszLine == ',' || *pszLine == ';'
+                            || *pszLine == '\t'))
         {
             if (chDelimiter == '\0')
                 chDelimiter = *pszLine;
             else if (chDelimiter != *pszLine)
             {
                 /* The separator is not consistent on the line. */
-                CPLDebug("CSV", "Inconsistent separator. '%c' and '%c' found. Using ',' as default",
-                         chDelimiter, *pszLine);
+                CPLDebug( "CSV", "Inconsistent separator. '%c' and '%c' found. "
+                          "Using ',' as default",
+                          chDelimiter, *pszLine);
                 chDelimiter = ',';
                 break;
             }
         }
         else if( !bInString && *pszLine == ' ' )
-            nCountSpace ++;
+        {
+            nCountSpace++;
+        }
         else if( *pszLine == '"' )
         {
             if( !bInString || pszLine[1] != '"' )
@@ -503,6 +565,8 @@ char CSVDetectSeperator (const char* pszLine)
 /*                                                                      */
 /*      Read one line, and return split into fields.  The return        */
 /*      result is a stringlist, in the sense of the CSL functions.      */
+/*                                                                      */
+/*      Deprecated.  Replaced by CSVReadParseLineL().                   */
 /************************************************************************/
 
 char **CSVReadParseLine( FILE * fp )
@@ -513,17 +577,13 @@ char **CSVReadParseLine( FILE * fp )
 char **CSVReadParseLine2( FILE * fp, char chDelimiter )
 
 {
-    const char  *pszLine;
-    char        *pszWorkLine;
-    char        **papszReturn;
-
     CPLAssert( fp != NULL );
     if( fp == NULL )
-        return( NULL );
-    
-    pszLine = CPLReadLine( fp );
+        return NULL;
+
+    const char  *pszLine = CPLReadLine( fp );
     if( pszLine == NULL )
-        return( NULL );
+        return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      If there are no quotes, then this is the simple case.           */
@@ -536,12 +596,13 @@ char **CSVReadParseLine2( FILE * fp, char chDelimiter )
 /*      We must now count the quotes in our working string, and as      */
 /*      long as it is odd, keep adding new lines.                       */
 /* -------------------------------------------------------------------- */
-    pszWorkLine = CPLStrdup( pszLine );
+    char *pszWorkLine = CPLStrdup( pszLine );
 
-    int i = 0, nCount = 0;
-    int nWorkLineLength = strlen(pszWorkLine);
+    int i = 0;
+    int nCount = 0;
+    size_t nWorkLineLength = strlen(pszWorkLine);
 
-    while( TRUE )
+    while( true )
     {
         for( ; pszWorkLine[i] != '\0'; i++ )
         {
@@ -557,21 +618,104 @@ char **CSVReadParseLine2( FILE * fp, char chDelimiter )
         if( pszLine == NULL )
             break;
 
-        int nLineLen = strlen(pszLine);
+        const size_t nLineLen = strlen(pszLine);
+
+        char* pszWorkLineTmp = reinterpret_cast<char *>(
+            VSIRealloc(pszWorkLine,
+                       nWorkLineLength + nLineLen + 2) );
+        if (pszWorkLineTmp == NULL)
+            break;
+        pszWorkLine = pszWorkLineTmp;
+        // The newline gets lost in CPLReadLine().
+        strcat( pszWorkLine + nWorkLineLength, "\n" );
+        strcat( pszWorkLine + nWorkLineLength, pszLine );
+
+        nWorkLineLength += nLineLen + 1;
+    }
+
+    char **papszReturn = CSVSplitLine( pszWorkLine, chDelimiter );
+
+    CPLFree( pszWorkLine );
+
+    return papszReturn;
+}
+
+/************************************************************************/
+/*                          CSVReadParseLineL()                         */
+/*                                                                      */
+/*      Read one line, and return split into fields.  The return        */
+/*      result is a stringlist, in the sense of the CSL functions.      */
+/*                                                                      */
+/*      Replaces CSVReadParseLine().  These functions use the VSI       */
+/*      layer to allow reading from other file containers.              */
+/************************************************************************/
+
+char **CSVReadParseLineL( VSILFILE * fp )
+{
+    return CSVReadParseLine2L(fp, ',');
+}
+
+char **CSVReadParseLine2L( VSILFILE * fp, char chDelimiter )
+
+{
+    CPLAssert( fp != NULL );
+    if( fp == NULL )
+        return NULL;
+
+    const char  *pszLine = CPLReadLineL( fp );
+    if( pszLine == NULL )
+        return NULL;
+
+/* -------------------------------------------------------------------- */
+/*      If there are no quotes, then this is the simple case.           */
+/*      Parse, and return tokens.                                       */
+/* -------------------------------------------------------------------- */
+    if( strchr(pszLine,'\"') == NULL )
+        return CSVSplitLine( pszLine, chDelimiter );
+
+/* -------------------------------------------------------------------- */
+/*      We must now count the quotes in our working string, and as      */
+/*      long as it is odd, keep adding new lines.                       */
+/* -------------------------------------------------------------------- */
+    char *pszWorkLine = CPLStrdup( pszLine );
+
+    int i = 0;
+    int nCount = 0;
+    size_t nWorkLineLength = strlen(pszWorkLine);
+
+    while( true )
+    {
+        for( ; pszWorkLine[i] != '\0'; i++ )
+        {
+            if( pszWorkLine[i] == '\"'
+                && (i == 0 || pszWorkLine[i-1] != '\\') )
+                nCount++;
+        }
+
+        if( nCount % 2 == 0 )
+            break;
+
+        pszLine = CPLReadLineL( fp );
+        if( pszLine == NULL )
+            break;
+
+        const size_t nLineLen = strlen(pszLine);
 
-        char* pszWorkLineTmp = (char *)
+        char* pszWorkLineTmp = static_cast<char *>(
             VSIRealloc(pszWorkLine,
-                       nWorkLineLength + nLineLen + 2);
+                       nWorkLineLength + nLineLen + 2) );
         if (pszWorkLineTmp == NULL)
             break;
+
         pszWorkLine = pszWorkLineTmp;
-        strcat( pszWorkLine + nWorkLineLength, "\n" ); // This gets lost in CPLReadLine().
+        // The newline gets lost in CPLReadLine().
+        strcat( pszWorkLine + nWorkLineLength, "\n" );
         strcat( pszWorkLine + nWorkLineLength, pszLine );
 
         nWorkLineLength += nLineLen + 1;
     }
-    
-    papszReturn = CSVSplitLine( pszWorkLine, chDelimiter );
+
+    char **papszReturn = CSVSplitLine( pszWorkLine, chDelimiter );
 
     CPLFree( pszWorkLine );
 
@@ -585,7 +729,7 @@ char **CSVReadParseLine2( FILE * fp, char chDelimiter )
 /*      criteria.                                                       */
 /************************************************************************/
 
-static int CSVCompare( const char * pszFieldValue, const char * pszTarget,
+static bool CSVCompare( const char * pszFieldValue, const char * pszTarget,
                        CSVCompareCriteria eCriteria )
 
 {
@@ -595,14 +739,14 @@ static int CSVCompare( const char * pszFieldValue, const char * pszTarget,
     }
     else if( eCriteria == CC_ApproxString )
     {
-        return( EQUAL( pszFieldValue, pszTarget ) );
+        return EQUAL( pszFieldValue, pszTarget );
     }
     else if( eCriteria == CC_Integer )
     {
         return( atoi(pszFieldValue) == atoi(pszTarget) );
     }
 
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
@@ -611,25 +755,26 @@ static int CSVCompare( const char * pszFieldValue, const char * pszTarget,
 /*      Read the file scanline for lines where the key field equals     */
 /*      the indicated value with the suggested comparison criteria.     */
 /*      Return the first matching line split into fields.               */
+/*                                                                      */
+/*      Deprecated.  Replaced by CSVScanLinesL().                       */
 /************************************************************************/
 
 char **CSVScanLines( FILE *fp, int iKeyField, const char * pszValue,
                      CSVCompareCriteria eCriteria )
 
 {
-    char        **papszFields = NULL;
-    int         bSelected = FALSE, nTestValue;
-
     CPLAssert( pszValue != NULL );
     CPLAssert( iKeyField >= 0 );
     CPLAssert( fp != NULL );
-    
-    nTestValue = atoi(pszValue);
-    
+
+    bool bSelected = false;
+    const int nTestValue = atoi(pszValue);
+    char **papszFields = NULL;
+
     while( !bSelected ) {
         papszFields = CSVReadParseLine( fp );
         if( papszFields == NULL )
-            return( NULL );
+            return NULL;
 
         if( CSLCount( papszFields ) < iKeyField+1 )
         {
@@ -638,7 +783,7 @@ char **CSVScanLines( FILE *fp, int iKeyField, const char * pszValue,
         else if( eCriteria == CC_Integer
                  && atoi(papszFields[iKeyField]) == nTestValue )
         {
-            bSelected = TRUE;
+            bSelected = true;
         }
         else
         {
@@ -652,8 +797,58 @@ char **CSVScanLines( FILE *fp, int iKeyField, const char * pszValue,
             papszFields = NULL;
         }
     }
-    
-    return( papszFields );
+
+    return papszFields;
+}
+
+/************************************************************************/
+/*                            CSVScanLinesL()                           */
+/*                                                                      */
+/*      Read the file scanline for lines where the key field equals     */
+/*      the indicated value with the suggested comparison criteria.     */
+/*      Return the first matching line split into fields.               */
+/************************************************************************/
+
+char **CSVScanLinesL( VSILFILE *fp, int iKeyField, const char * pszValue,
+                      CSVCompareCriteria eCriteria )
+
+{
+    CPLAssert( pszValue != NULL );
+    CPLAssert( iKeyField >= 0 );
+    CPLAssert( fp != NULL );
+
+    bool bSelected = false;
+    const int nTestValue = atoi(pszValue);
+    char **papszFields = NULL;
+
+    while( !bSelected ) {
+        papszFields = CSVReadParseLineL( fp );
+        if( papszFields == NULL )
+            return NULL;
+
+        if( CSLCount( papszFields ) < iKeyField+1 )
+        {
+            /* not selected */
+        }
+        else if( eCriteria == CC_Integer
+                 && atoi(papszFields[iKeyField]) == nTestValue )
+        {
+            bSelected = true;
+        }
+        else
+        {
+            bSelected = CSVCompare( papszFields[iKeyField], pszValue,
+                                    eCriteria );
+        }
+
+        if( !bSelected )
+        {
+            CSLDestroy( papszFields );
+            papszFields = NULL;
+        }
+    }
+
+    return papszFields;
 }
 
 /************************************************************************/
@@ -668,19 +863,18 @@ static char **
 CSVScanLinesIndexed( CSVTable *psTable, int nKeyValue )
 
 {
-    int         iTop, iBottom, iMiddle, iResult = -1;
-
     CPLAssert( psTable->panLineIndex != NULL );
 
 /* -------------------------------------------------------------------- */
 /*      Find target record with binary search.                          */
 /* -------------------------------------------------------------------- */
-    iTop = psTable->nLineCount-1;
-    iBottom = 0;
+    int iTop = psTable->nLineCount-1;
+    int iBottom = 0;
+    int iResult = -1;
 
     while( iTop >= iBottom )
     {
-        iMiddle = (iTop + iBottom) / 2;
+        const int iMiddle = (iTop + iBottom) / 2;
         if( psTable->panLineIndex[iMiddle] > nKeyValue )
             iTop = iMiddle - 1;
         else if( psTable->panLineIndex[iMiddle] < nKeyValue )
@@ -689,10 +883,10 @@ CSVScanLinesIndexed( CSVTable *psTable, int nKeyValue )
         {
             iResult = iMiddle;
             // if a key is not unique, select the first instance of it.
-            while( iResult > 0 
+            while( iResult > 0
                    && psTable->panLineIndex[iResult-1] == nKeyValue )
             {
-                psTable->bNonUniqueKey = TRUE; 
+                psTable->bNonUniqueKey = TRUE;
                 iResult--;
             }
             break;
@@ -706,7 +900,7 @@ CSVScanLinesIndexed( CSVTable *psTable, int nKeyValue )
 /*      Parse target line, and update iLastLine indicator.              */
 /* -------------------------------------------------------------------- */
     psTable->iLastLine = iResult;
-    
+
     return CSVSplitLine( psTable->papszLines[iResult], ',' );
 }
 
@@ -723,27 +917,28 @@ CSVScanLinesIngested( CSVTable *psTable, int iKeyField, const char * pszValue,
                       CSVCompareCriteria eCriteria )
 
 {
-    char        **papszFields = NULL;
-    int         bSelected = FALSE, nTestValue;
-
     CPLAssert( pszValue != NULL );
     CPLAssert( iKeyField >= 0 );
 
-    nTestValue = atoi(pszValue);
-    
+    const int nTestValue = atoi(pszValue);
+
 /* -------------------------------------------------------------------- */
 /*      Short cut for indexed files.                                    */
 /* -------------------------------------------------------------------- */
-    if( iKeyField == 0 && eCriteria == CC_Integer 
+    if( iKeyField == 0 && eCriteria == CC_Integer
         && psTable->panLineIndex != NULL )
         return CSVScanLinesIndexed( psTable, nTestValue );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Scan from in-core lines.                                        */
 /* -------------------------------------------------------------------- */
+    char **papszFields = NULL;
+    bool bSelected = false;
+
     while( !bSelected && psTable->iLastLine+1 < psTable->nLineCount ) {
         psTable->iLastLine++;
-        papszFields = CSVSplitLine( psTable->papszLines[psTable->iLastLine], ',' );
+        papszFields = CSVSplitLine( psTable->papszLines[psTable->iLastLine],
+                                    ',' );
 
         if( CSLCount( papszFields ) < iKeyField+1 )
         {
@@ -752,7 +947,7 @@ CSVScanLinesIngested( CSVTable *psTable, int iKeyField, const char * pszValue,
         else if( eCriteria == CC_Integer
                  && atoi(papszFields[iKeyField]) == nTestValue )
         {
-            bSelected = TRUE;
+            bSelected = true;
         }
         else
         {
@@ -766,8 +961,8 @@ CSVScanLinesIngested( CSVTable *psTable, int iKeyField, const char * pszValue,
             papszFields = NULL;
         }
     }
-    
-    return( papszFields );
+
+    return papszFields;
 }
 
 /************************************************************************/
@@ -781,22 +976,21 @@ CSVScanLinesIngested( CSVTable *psTable, int iKeyField, const char * pszValue,
 char **CSVGetNextLine( const char *pszFilename )
 
 {
-    CSVTable *psTable;
 
 /* -------------------------------------------------------------------- */
 /*      Get access to the table.                                        */
 /* -------------------------------------------------------------------- */
     CPLAssert( pszFilename != NULL );
 
-    psTable = CSVAccess( pszFilename );
+    CSVTable * const psTable = CSVAccess( pszFilename );
     if( psTable == NULL )
         return NULL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      If we use CSVGetNextLine() we can pretty much assume we have    */
 /*      a non-unique key.                                               */
 /* -------------------------------------------------------------------- */
-    psTable->bNonUniqueKey = TRUE; 
+    psTable->bNonUniqueKey = TRUE;
 
 /* -------------------------------------------------------------------- */
 /*      Do we have a next line available?  This only works for          */
@@ -807,7 +1001,7 @@ char **CSVGetNextLine( const char *pszFilename )
 
     psTable->iLastLine++;
     CSLDestroy( psTable->papszRecFields );
-    psTable->papszRecFields = 
+    psTable->papszRecFields =
         CSVSplitLine( psTable->papszLines[psTable->iLastLine], ',' );
 
     return psTable->papszRecFields;
@@ -824,8 +1018,6 @@ char **CSVScanFile( const char * pszFilename, int iKeyField,
                     const char * pszValue, CSVCompareCriteria eCriteria )
 
 {
-    CSVTable    *psTable;
-
 /* -------------------------------------------------------------------- */
 /*      Get access to the table.                                        */
 /* -------------------------------------------------------------------- */
@@ -834,10 +1026,10 @@ char **CSVScanFile( const char * pszFilename, int iKeyField,
     if( iKeyField < 0 )
         return NULL;
 
-    psTable = CSVAccess( pszFilename );
+    CSVTable * const psTable = CSVAccess( pszFilename );
     if( psTable == NULL )
         return NULL;
-    
+
     CSVIngest( pszFilename );
 
 /* -------------------------------------------------------------------- */
@@ -860,18 +1052,18 @@ char **CSVScanFile( const char * pszFilename, int iKeyField,
     CSLDestroy( psTable->papszRecFields );
 
     if( psTable->pszRawData != NULL )
-        psTable->papszRecFields = 
+        psTable->papszRecFields =
             CSVScanLinesIngested( psTable, iKeyField, pszValue, eCriteria );
     else
     {
-        VSIRewind( psTable->fp );
-        CPLReadLine( psTable->fp );         /* throw away the header line */
-    
+        VSIRewindL( psTable->fp );
+        CPLReadLineL( psTable->fp );         /* throw away the header line */
+
         psTable->papszRecFields =
-            CSVScanLines( psTable->fp, iKeyField, pszValue, eCriteria );
+            CSVScanLinesL( psTable->fp, iKeyField, pszValue, eCriteria );
     }
 
-    return( psTable->papszRecFields );
+    return psTable->papszRecFields;
 }
 
 /************************************************************************/
@@ -883,20 +1075,52 @@ char **CSVScanFile( const char * pszFilename, int iKeyField,
 /*      insensitive, but otherwise exact.  After this function has      */
 /*      been called the file pointer will be positioned just after      */
 /*      the first record.                                               */
+/*                                                                      */
+/*      Deprecated.  Replaced by CPLGetFieldIdL().                      */
 /************************************************************************/
 
 int CSVGetFieldId( FILE * fp, const char * pszFieldName )
 
 {
-    char        **papszFields;
-    int         i;
-    
     CPLAssert( fp != NULL && pszFieldName != NULL );
 
     VSIRewind( fp );
 
-    papszFields = CSVReadParseLine( fp );
-    for( i = 0; papszFields != NULL && papszFields[i] != NULL; i++ )
+    char **papszFields = CSVReadParseLine( fp );
+    for( int i = 0; papszFields != NULL && papszFields[i] != NULL; i++ )
+    {
+        if( EQUAL(papszFields[i],pszFieldName) )
+        {
+            CSLDestroy( papszFields );
+            return i;
+        }
+    }
+
+    CSLDestroy( papszFields );
+
+    return -1;
+}
+
+/************************************************************************/
+/*                           CPLGetFieldIdL()                           */
+/*                                                                      */
+/*      Read the first record of a CSV file (rewinding to be sure),     */
+/*      and find the field with the indicated name.  Returns -1 if      */
+/*      it fails to find the field name.  Comparison is case            */
+/*      insensitive, but otherwise exact.  After this function has      */
+/*      been called the file pointer will be positioned just after      */
+/*      the first record.                                               */
+/************************************************************************/
+
+int CSVGetFieldIdL( VSILFILE * fp, const char * pszFieldName )
+
+{
+    CPLAssert( fp != NULL && pszFieldName != NULL );
+
+    VSIRewindL( fp );
+
+    char **papszFields = CSVReadParseLineL( fp );
+    for( int i = 0; papszFields != NULL && papszFields[i] != NULL; i++ )
     {
         if( EQUAL(papszFields[i],pszFieldName) )
         {
@@ -920,22 +1144,19 @@ int CSVGetFieldId( FILE * fp, const char * pszFieldName )
 int CSVGetFileFieldId( const char * pszFilename, const char * pszFieldName )
 
 {
-    CSVTable    *psTable;
-    int         i;
-    
 /* -------------------------------------------------------------------- */
 /*      Get access to the table.                                        */
 /* -------------------------------------------------------------------- */
     CPLAssert( pszFilename != NULL );
 
-    psTable = CSVAccess( pszFilename );
+    CSVTable * const psTable = CSVAccess( pszFilename );
     if( psTable == NULL )
         return -1;
 
 /* -------------------------------------------------------------------- */
 /*      Find the requested field.                                       */
 /* -------------------------------------------------------------------- */
-    for( i = 0;
+    for( int i = 0;
          psTable->papszFieldNames != NULL
              && psTable->papszFieldNames[i] != NULL;
          i++ )
@@ -962,13 +1183,11 @@ char **CSVScanFileByName( const char * pszFilename,
                           const char * pszValue, CSVCompareCriteria eCriteria )
 
 {
-    int         iKeyField;
-
-    iKeyField = CSVGetFileFieldId( pszFilename, pszKeyFieldName );
+    const int iKeyField = CSVGetFileFieldId( pszFilename, pszKeyFieldName );
     if( iKeyField == -1 )
         return NULL;
 
-    return( CSVScanFile( pszFilename, iKeyField, pszValue, eCriteria ) );
+    return CSVScanFile( pszFilename, iKeyField, pszValue, eCriteria );
 }
 
 /************************************************************************/
@@ -988,37 +1207,34 @@ const char *CSVGetField( const char * pszFilename,
                          const char * pszTargetField )
 
 {
-    CSVTable    *psTable;
-    char        **papszRecord;
-    int         iTargetField;
-    
 /* -------------------------------------------------------------------- */
 /*      Find the table.                                                 */
 /* -------------------------------------------------------------------- */
-    psTable = CSVAccess( pszFilename );
+    CSVTable * const psTable = CSVAccess( pszFilename );
     if( psTable == NULL )
         return "";
 
 /* -------------------------------------------------------------------- */
 /*      Find the correct record.                                        */
 /* -------------------------------------------------------------------- */
-    papszRecord = CSVScanFileByName( pszFilename, pszKeyFieldName,
-                                     pszKeyFieldValue, eCriteria );
-
+    char **papszRecord = CSVScanFileByName( pszFilename, pszKeyFieldName,
+                                            pszKeyFieldValue, eCriteria );
     if( papszRecord == NULL )
         return "";
 
 /* -------------------------------------------------------------------- */
 /*      Figure out which field we want out of this.                     */
 /* -------------------------------------------------------------------- */
-    iTargetField = CSVGetFileFieldId( pszFilename, pszTargetField );
+    const int iTargetField = CSVGetFileFieldId( pszFilename, pszTargetField );
     if( iTargetField < 0 )
         return "";
 
-    if( iTargetField >= CSLCount( papszRecord ) )
-        return "";
-
-    return( papszRecord[iTargetField] );
+    for(int i=0; papszRecord[i] != NULL; ++i)
+    {
+        if( i == iTargetField )
+            return papszRecord[iTargetField];
+    }
+    return "";
 }
 
 /************************************************************************/
@@ -1039,23 +1255,22 @@ const char * GDALDefaultCSVFilename( const char *pszBasename )
 /*      Do we already have this file accessed?  If so, just return      */
 /*      the existing path without any further probing.                  */
 /* -------------------------------------------------------------------- */
-    CSVTable **ppsCSVTableList;
-
-    ppsCSVTableList = (CSVTable **) CPLGetTLS( CTLS_CSVTABLEPTR );
+    int bMemoryError = FALSE;
+    CSVTable **ppsCSVTableList = reinterpret_cast<CSVTable **>(
+      CPLGetTLSEx( CTLS_CSVTABLEPTR, &bMemoryError ) );
     if( ppsCSVTableList != NULL )
     {
-        CSVTable *psTable;
-        int nBasenameLen = strlen(pszBasename);
+        const size_t nBasenameLen = strlen(pszBasename);
 
-        for( psTable = *ppsCSVTableList; 
-             psTable != NULL; 
+        for( const CSVTable *psTable = *ppsCSVTableList;
+             psTable != NULL;
              psTable = psTable->psNext )
         {
-            int nFullLen = strlen(psTable->pszFilename);
+            const size_t nFullLen = strlen(psTable->pszFilename);
 
-            if( nFullLen > nBasenameLen 
+            if( nFullLen > nBasenameLen
                 && strcmp(psTable->pszFilename+nFullLen-nBasenameLen,
-                          pszBasename) == 0 
+                          pszBasename) == 0
                 && strchr("/\\",psTable->pszFilename[+nFullLen-nBasenameLen-1])
                           != NULL )
             {
@@ -1063,22 +1278,24 @@ const char * GDALDefaultCSVFilename( const char *pszBasename )
             }
         }
     }
-                
+
 /* -------------------------------------------------------------------- */
 /*      Otherwise we need to look harder for it.                        */
 /* -------------------------------------------------------------------- */
     DefaultCSVFileNameTLS* pTLSData =
-            (DefaultCSVFileNameTLS *) CPLGetTLS( CTLS_CSVDEFAULTFILENAME );
-    if (pTLSData == NULL)
+        reinterpret_cast<DefaultCSVFileNameTLS *>(
+            CPLGetTLSEx( CTLS_CSVDEFAULTFILENAME, &bMemoryError ) );
+    if (pTLSData == NULL && !bMemoryError)
     {
-        pTLSData = (DefaultCSVFileNameTLS*) CPLCalloc(1, sizeof(DefaultCSVFileNameTLS));
-        CPLSetTLS( CTLS_CSVDEFAULTFILENAME, pTLSData, TRUE );
+        pTLSData = reinterpret_cast<DefaultCSVFileNameTLS *>(
+            VSI_CALLOC_VERBOSE( 1, sizeof(DefaultCSVFileNameTLS) ) );
+        if( pTLSData )
+            CPLSetTLS( CTLS_CSVDEFAULTFILENAME, pTLSData, TRUE );
     }
+    if( pTLSData == NULL )
+        return "/not_existing_dir/not_existing_path";
 
-    FILE    *fp = NULL;
-    const char *pszResult;
-
-    pszResult = CPLFindFile( "epsg_csv", pszBasename );
+    const char *pszResult = CPLFindFile( "epsg_csv", pszBasename );
 
     if( pszResult != NULL )
         return pszResult;
@@ -1111,13 +1328,15 @@ const char * GDALDefaultCSVFilename( const char *pszBasename )
     strcpy( pTLSData->szPath, "/usr/local/share/epsg_csv/" );
     CPLStrlcat( pTLSData->szPath, pszBasename, sizeof(pTLSData->szPath) );
 #endif
-    if( (fp = fopen( pTLSData->szPath, "rt" )) == NULL )
+
+    VSILFILE *fp = VSIFOpenL( pTLSData->szPath, "rt" );
+    if( fp == NULL )
         CPLStrlcpy( pTLSData->szPath, pszBasename, sizeof(pTLSData->szPath) );
 
     if( fp != NULL )
-        fclose( fp );
+        VSIFCloseL( fp );
 
-    return( pTLSData->szPath );
+    return pTLSData->szPath;
 }
 
 /************************************************************************/
@@ -1136,8 +1355,8 @@ const char * CSVFilename( const char *pszBasename )
 {
     if( pfnCSVFilenameHook == NULL )
         return GDALDefaultCSVFilename( pszBasename );
-    else
-        return( pfnCSVFilenameHook( pszBasename ) );
+
+    return pfnCSVFilenameHook( pszBasename );
 }
 
 /************************************************************************/
@@ -1152,11 +1371,14 @@ const char * CSVFilename( const char *pszBasename )
  *
  * @param pfnNewHook The pointer to a function which will return the
  * full path for a given filename.
-  *
+ *
 
-This function allows an application to override how the GTIFGetDefn() and related function find the CSV (Comma Separated
-Value) values required. The pfnHook argument should be a pointer to a function that will take in a CSV filename and return a
-full path to the file. The returned string should be to an internal static buffer so that the caller doesn't have to free the result.
+This function allows an application to override how the GTIFGetDefn()
+and related function find the CSV (Comma Separated Value) values
+required. The pfnHook argument should be a pointer to a function that
+will take in a CSV filename and return a full path to the file. The
+returned string should be to an internal static buffer so that the
+caller doesn't have to free the result.
 
 <b>Example:</b><br>
 
@@ -1167,13 +1389,9 @@ put into CSVDirName).  <p>
 <pre>
 
     ...
-
-
     SetCSVFilenameHook( CSVFileOverride );
-
     ...
 
-
 static const char *CSVFileOverride( const char * pszInput )
 
 {
@@ -1181,11 +1399,11 @@ static const char *CSVFileOverride( const char * pszInput )
 
 #ifdef WIN32
     sprintf( szPath, "%s\\%s", CSVDirName, pszInput );
-#else    
+#else
     sprintf( szPath, "%s/%s", CSVDirName, pszInput );
-#endif    
+#endif
 
-    return( szPath );
+    return szPath;
 }
 </pre>
 
diff --git a/port/cpl_csv.h b/port/cpl_csv.h
index 24e41ad..6337431 100644
--- a/port/cpl_csv.h
+++ b/port/cpl_csv.h
@@ -1,9 +1,9 @@
 /******************************************************************************
- * $Id: cpl_csv.h 16759 2009-04-09 21:32:43Z rouault $
+ * $Id: cpl_csv.h 33844 2016-04-01 08:42:13Z rouault $
  *
  * Project:  Common Portability Library
- * Purpose:  Functions for reading and scaning CSV (comma separated,
- *           variable length text files holding tables) files.  
+ * Purpose:  Functions for reading and scanning CSV (comma separated,
+ *           variable length text files holding tables) files.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -49,13 +49,19 @@ char CPL_DLL CSVDetectSeperator( const char *pszLine );
 
 char CPL_DLL  **CSVReadParseLine( FILE *fp);
 char CPL_DLL  **CSVReadParseLine2( FILE *fp, char chDelimiter );
+
+char CPL_DLL  **CSVReadParseLineL( VSILFILE *fp);
+char CPL_DLL  **CSVReadParseLine2L( VSILFILE *fp, char chDelimiter );
+
 char CPL_DLL **CSVScanLines( FILE *, int, const char *, CSVCompareCriteria );
+char CPL_DLL **CSVScanLinesL( VSILFILE *, int, const char *, CSVCompareCriteria );
 char CPL_DLL **CSVScanFile( const char *, int, const char *,
                             CSVCompareCriteria );
 char CPL_DLL **CSVScanFileByName( const char *, const char *, const char *,
                                   CSVCompareCriteria );
 char CPL_DLL **CSVGetNextLine( const char * );
 int CPL_DLL CSVGetFieldId( FILE *, const char * );
+int CPL_DLL CSVGetFieldIdL( VSILFILE *, const char * );
 int CPL_DLL CSVGetFileFieldId( const char *, const char * );
 
 void CPL_DLL CSVDeaccess( const char * );
@@ -68,4 +74,3 @@ void CPL_DLL SetCSVFilenameHook( const char *(*)(const char *) );
 CPL_C_END
 
 #endif /* ndef CPL_CSV_H_INCLUDED */
-
diff --git a/port/cpl_error.cpp b/port/cpl_error.cpp
index 32dc396..ae28958 100644
--- a/port/cpl_error.cpp
+++ b/port/cpl_error.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_error.cpp 29330 2015-06-14 12:11:11Z rouault $
+ * $Id: cpl_error.cpp 33844 2016-04-01 08:42:13Z rouault $
  *
  * Name:     cpl_error.cpp
  * Project:  CPL - Common Portability Library
@@ -16,16 +16,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
@@ -35,35 +35,34 @@
 #include "cpl_conv.h"
 #include "cpl_multiproc.h"
 
-#if defined(WIN32CE)
-#  include "cpl_wince.h"
-#  include <wce_stdlib.h>
-#endif
- 
 #define TIMESTAMP_DEBUG
 //#define MEMORY_DEBUG
 
-CPL_CVSID("$Id: cpl_error.cpp 29330 2015-06-14 12:11:11Z rouault $");
+CPL_CVSID("$Id: cpl_error.cpp 33844 2016-04-01 08:42:13Z rouault $");
 
 static CPLMutex *hErrorMutex = NULL;
-static void *pErrorHandlerUserData = NULL; 
+static void *pErrorHandlerUserData = NULL;
 static CPLErrorHandler pfnErrorHandler = CPLDefaultErrorHandler;
+static bool gbCatchDebug = false;
 
+static const int DEFAULT_LAST_ERR_MSG_SIZE =
 #if !defined(HAVE_VSNPRINTF)
-#  define DEFAULT_LAST_ERR_MSG_SIZE 20000
+  20000
 #else
-#  define DEFAULT_LAST_ERR_MSG_SIZE 500
+  500
 #endif
+  ;
 
 typedef struct errHandler
 {
     struct errHandler   *psNext;
     void                *pUserData;
     CPLErrorHandler     pfnHandler;
+    bool                bCatchDebug;
 } CPLErrorHandlerNode;
 
 typedef struct {
-    int     nLastErrNo;
+    CPLErrorNum nLastErrNo;
     CPLErr  eLastErrType;
     CPLErrorHandlerNode *psHandlerStack;
     int     nLastErrMsgMax;
@@ -72,6 +71,38 @@ typedef struct {
     /* Do not add anything here. szLastErrMsg must be the last field. See CPLRealloc() below */
 } CPLErrorContext;
 
+static const CPLErrorContext sNoErrorContext =
+{
+    0,
+    CE_None,
+    NULL,
+    0,
+    0,
+    ""
+};
+
+static const CPLErrorContext sWarningContext =
+{
+    0,
+    CE_Warning,
+    NULL,
+    0,
+    0,
+    "A warning was emitted"
+};
+
+static const CPLErrorContext sFailureContext =
+{
+    0,
+    CE_Warning,
+    NULL,
+    0,
+    0,
+    "A failure was emitted"
+};
+
+#define IS_PREFEFINED_ERROR_CTX(psCtxt) ( psCtx == &sNoErrorContext || psCtx == &sWarningContext || psCtxt == &sFailureContext )
+
 /************************************************************************/
 /*                         CPLGetErrorContext()                         */
 /************************************************************************/
@@ -79,14 +110,20 @@ typedef struct {
 static CPLErrorContext *CPLGetErrorContext()
 
 {
-    CPLErrorContext *psCtx = 
-        (CPLErrorContext *) CPLGetTLS( CTLS_ERRORCONTEXT );
+    int bError = FALSE;
+    CPLErrorContext *psCtx =
+        reinterpret_cast<CPLErrorContext *>(
+            CPLGetTLSEx( CTLS_ERRORCONTEXT, &bError ) );
+    if( bError )
+        return NULL;
 
     if( psCtx == NULL )
     {
-        psCtx = (CPLErrorContext *) VSICalloc(sizeof(CPLErrorContext),1);
+      psCtx = reinterpret_cast<CPLErrorContext *>(
+          VSICalloc( sizeof(CPLErrorContext), 1) );
         if (psCtx == NULL) {
-            CPLEmergencyError("Out of memory attempting to report error");
+            fprintf(stderr, "Out of memory attempting to report error.\n");
+            return NULL;
         }
         psCtx->eLastErrType = CE_None;
         psCtx->nLastErrMsgMax = sizeof(psCtx->szLastErrMsg);
@@ -103,12 +140,12 @@ static CPLErrorContext *CPLGetErrorContext()
 /**
  * Fetch the user data for the error context
  *
- * Fetches the user data for the current error context.  You can 
- * set the user data for the error context when you add your handler by 
- * issuing CPLSetErrorHandlerEx() and CPLPushErrorHandlerEx().  Note that 
+ * Fetches the user data for the current error context.  You can
+ * set the user data for the error context when you add your handler by
+ * issuing CPLSetErrorHandlerEx() and CPLPushErrorHandlerEx().  Note that
  * user data is primarily intended for providing context within error handlers
- * themselves, but they could potentially be abused in other useful ways with the usual 
- * caveat emptor understanding.
+ * themselves, but they could potentially be abused in other useful ways with
+ * the usual caveat emptor understanding.
  *
  * @return the user data pointer for the error context
  */
@@ -116,7 +153,11 @@ static CPLErrorContext *CPLGetErrorContext()
 void* CPL_STDCALL CPLGetErrorHandlerUserData(void)
 {
     CPLErrorContext *psCtx = CPLGetErrorContext();
-    return (void*) psCtx->psHandlerStack ? psCtx->psHandlerStack->pUserData : pErrorHandlerUserData;
+    if( psCtx == NULL || IS_PREFEFINED_ERROR_CTX(psCtx) )
+        abort();
+    return reinterpret_cast<void*>(
+        psCtx->psHandlerStack ?
+        psCtx->psHandlerStack->pUserData : pErrorHandlerUserData );
 }
 
 /**********************************************************************
@@ -135,8 +176,8 @@ void* CPL_STDCALL CPLGetErrorHandlerUserData(void)
  * The eErrClass argument can have the value CE_Warning indicating that the
  * message is an informational warning, CE_Failure indicating that the
  * action failed, but that normal recover mechanisms will be used or
- * CE_Fatal meaning that a fatal error has occured, and that CPLError()
- * should not return.  
+ * CE_Fatal meaning that a fatal error has occurred, and that CPLError()
+ * should not return.
  *
  * The default behaviour of CPLError() is to report errors to stderr,
  * and to abort() after reporting a CE_Fatal error.  It is expected that
@@ -155,12 +196,11 @@ void* CPL_STDCALL CPLGetErrorHandlerUserData(void)
  * similar to printf().
  */
 
-void    CPLError(CPLErr eErrClass, int err_no, const char *fmt, ...)
+void    CPLError(CPLErr eErrClass, CPLErrorNum err_no, const char *fmt, ...)
 {
     va_list args;
 
-    /* Expand the error message 
-     */
+    // Expand the error message
     va_start(args, fmt);
     CPLErrorV( eErrClass, err_no, fmt, args );
     va_end(args);
@@ -170,9 +210,41 @@ void    CPLError(CPLErr eErrClass, int err_no, const char *fmt, ...)
 /*                             CPLErrorV()                              */
 /************************************************************************/
 
-void    CPLErrorV(CPLErr eErrClass, int err_no, const char *fmt, va_list args )
+void    CPLErrorV( CPLErr eErrClass, CPLErrorNum err_no, const char *fmt,
+                   va_list args )
 {
     CPLErrorContext *psCtx = CPLGetErrorContext();
+    if( psCtx == NULL || IS_PREFEFINED_ERROR_CTX(psCtx) )
+    {
+        int bMemoryError = FALSE;
+        if( eErrClass == CE_Warning )
+        {
+            CPLSetTLSWithFreeFuncEx(
+                CTLS_ERRORCONTEXT,
+                reinterpret_cast<void*>(
+                    const_cast<CPLErrorContext *>( &sWarningContext ) ),
+                NULL, &bMemoryError );
+        }
+        else if( eErrClass == CE_Failure )
+        {
+            CPLSetTLSWithFreeFuncEx(
+                CTLS_ERRORCONTEXT,
+                reinterpret_cast<void*>(
+                    const_cast<CPLErrorContext *>( &sFailureContext ) ),
+                NULL, &bMemoryError );
+        }
+
+        // TODO: Is it possible to move the entire szShortMessage under the if
+        // pfnErrorHandler?
+        char szShortMessage[80];
+        szShortMessage[0] = '\0';
+        CPLvsnprintf( szShortMessage, sizeof(szShortMessage), fmt, args );
+
+        CPLMutexHolderD( &hErrorMutex );
+        if( pfnErrorHandler != NULL )
+            pfnErrorHandler(eErrClass, err_no, szShortMessage);
+        return;
+    }
 
     if (psCtx->nFailureIntoWarning > 0 && eErrClass == CE_Failure)
         eErrClass = CE_Warning;
@@ -182,7 +254,6 @@ void    CPLErrorV(CPLErr eErrClass, int err_no, const char *fmt, va_list args )
 /* -------------------------------------------------------------------- */
 #if defined(HAVE_VSNPRINTF)
     {
-        int nPR;
         va_list wrk_args;
 
 #ifdef va_copy
@@ -199,14 +270,17 @@ void    CPLErrorV(CPLErr eErrClass, int err_no, const char *fmt, va_list args )
         if ( psCtx->psHandlerStack != NULL &&
              EQUAL(CPLGetConfigOption( "CPL_ACCUM_ERROR_MSG", "" ), "ON"))
         {
-            nPreviousSize = strlen(psCtx->szLastErrMsg);
+            nPreviousSize = static_cast<int>(strlen(psCtx->szLastErrMsg));
             if (nPreviousSize)
             {
                 if (nPreviousSize + 1 + 1 >= psCtx->nLastErrMsgMax)
                 {
                     psCtx->nLastErrMsgMax *= 3;
-                    psCtx = (CPLErrorContext *) 
-                        CPLRealloc(psCtx, sizeof(CPLErrorContext) - DEFAULT_LAST_ERR_MSG_SIZE + psCtx->nLastErrMsgMax + 1);
+                    psCtx = static_cast<CPLErrorContext *> (
+                        CPLRealloc( psCtx,
+                                    sizeof(CPLErrorContext)
+                                    - DEFAULT_LAST_ERR_MSG_SIZE
+                                    + psCtx->nLastErrMsgMax + 1));
                     CPLSetTLS( CTLS_ERRORCONTEXT, psCtx, TRUE );
                 }
                 psCtx->szLastErrMsg[nPreviousSize] = '\n';
@@ -215,8 +289,10 @@ void    CPLErrorV(CPLErr eErrClass, int err_no, const char *fmt, va_list args )
             }
         }
 
-        while( ((nPR = CPLvsnprintf( psCtx->szLastErrMsg+nPreviousSize, 
-                                 psCtx->nLastErrMsgMax-nPreviousSize, fmt, wrk_args )) == -1
+        int nPR = 0;
+        while( ((nPR = CPLvsnprintf(
+                     psCtx->szLastErrMsg+nPreviousSize,
+                     psCtx->nLastErrMsgMax-nPreviousSize, fmt, wrk_args )) == -1
                 || nPR >= psCtx->nLastErrMsgMax-nPreviousSize-1)
                && psCtx->nLastErrMsgMax < 1000000 )
         {
@@ -227,8 +303,11 @@ void    CPLErrorV(CPLErr eErrClass, int err_no, const char *fmt, va_list args )
             wrk_args = args;
 #endif
             psCtx->nLastErrMsgMax *= 3;
-            psCtx = (CPLErrorContext *) 
-                CPLRealloc(psCtx, sizeof(CPLErrorContext) - DEFAULT_LAST_ERR_MSG_SIZE + psCtx->nLastErrMsgMax + 1);
+            psCtx = static_cast<CPLErrorContext *> (
+                CPLRealloc( psCtx,
+                            sizeof(CPLErrorContext)
+                            - DEFAULT_LAST_ERR_MSG_SIZE
+                            + psCtx->nLastErrMsgMax + 1) );
             CPLSetTLS( CTLS_ERRORCONTEXT, psCtx, TRUE );
         }
 
@@ -269,7 +348,7 @@ void    CPLErrorV(CPLErr eErrClass, int err_no, const char *fmt, va_list args )
 /* -------------------------------------------------------------------- */
     if( psCtx->psHandlerStack != NULL )
     {
-        psCtx->psHandlerStack->pfnHandler(eErrClass, err_no, 
+        psCtx->psHandlerStack->pfnHandler(eErrClass, err_no,
                                           psCtx->szLastErrMsg);
     }
     else
@@ -288,13 +367,13 @@ void    CPLErrorV(CPLErr eErrClass, int err_no, const char *fmt, va_list args )
 /************************************************************************/
 
 /**
- * Fatal error when things are bad. 
+ * Fatal error when things are bad.
  *
  * This function should be called in an emergency situation where
- * it is unlikely that a regular error report would work.  This would 
- * include in the case of heap exhaustion for even small allocations, 
- * or any failure in the process of reporting an error (such as TLS 
- * allocations). 
+ * it is unlikely that a regular error report would work.  This would
+ * include in the case of heap exhaustion for even small allocations,
+ * or any failure in the process of reporting an error (such as TLS
+ * allocations).
  *
  * This function should never return.  After the error message has been
  * reported as best possible, the application will abort() similarly to how
@@ -305,19 +384,19 @@ void    CPLErrorV(CPLErr eErrClass, int err_no, const char *fmt, va_list args )
 
 void CPLEmergencyError( const char *pszMessage )
 {
-    CPLErrorContext *psCtx = NULL;
-    static int bInEmergencyError = FALSE;
+    static bool bInEmergencyError = false;
 
-    // If we are already in emergency error then one of the 
+    // If we are already in emergency error then one of the
     // following failed, so avoid them the second time through.
     if( !bInEmergencyError )
     {
-        bInEmergencyError = TRUE;
-        psCtx = (CPLErrorContext *) CPLGetTLS( CTLS_ERRORCONTEXT );
+        bInEmergencyError = true;
+        CPLErrorContext *psCtx
+            = static_cast<CPLErrorContext *>( CPLGetTLS( CTLS_ERRORCONTEXT ) );
 
         if( psCtx != NULL && psCtx->psHandlerStack != NULL )
         {
-            psCtx->psHandlerStack->pfnHandler( CE_Fatal, CPLE_AppDefined, 
+            psCtx->psHandlerStack->pfnHandler( CE_Fatal, CPLE_AppDefined,
                                                pszMessage );
         }
         else if( pfnErrorHandler != NULL )
@@ -348,7 +427,7 @@ static int CPLGetProcessMemorySize()
     char szLine[128];
     while (fgets(szLine, sizeof(szLine), fp) != NULL)
     {
-        if (strncmp(szLine, "VmSize:", 7) == 0)
+        if (STARTS_WITH(szLine, "VmSize:"))
         {
             const char* pszPtr = szLine;
             while( !(*pszPtr == '\0' || (*pszPtr >= '0' && *pszPtr <= '9')) )
@@ -379,28 +458,26 @@ static int CPLGetProcessMemorySize()
  * are emitted (use CPLError(CE_Warning,...) to ensure messages are displayed).
  * If CPL_DEBUG is set, but is an empty string or the word "ON" then all
  * debug messages are shown.  Otherwise only messages whose category appears
- * somewhere within the CPL_DEBUG value are displayed (as determinted by
+ * somewhere within the CPL_DEBUG value are displayed (as determined by
  * strstr()).
  *
  * Categories are usually an identifier for the subsystem producing the
  * error.  For instance "GDAL" might be used for the GDAL core, and "TIFF"
- * for messages from the TIFF translator.  
+ * for messages from the TIFF translator.
  *
  * @param pszCategory name of the debugging message category.
  * @param pszFormat printf() style format string for message to display.
  *        Remaining arguments are assumed to be for format.
- */ 
+ */
 
 void CPLDebug( const char * pszCategory, const char * pszFormat, ... )
 
 {
     CPLErrorContext *psCtx = CPLGetErrorContext();
-    char        *pszMessage;
-    va_list     args;
+    if( psCtx == NULL || IS_PREFEFINED_ERROR_CTX(psCtx) )
+        return;
     const char  *pszDebug = CPLGetConfigOption("CPL_DEBUG",NULL);
 
-#define ERROR_MAX 25000
-
 /* -------------------------------------------------------------------- */
 /*      Does this message pass our current criteria?                    */
 /* -------------------------------------------------------------------- */
@@ -424,10 +501,11 @@ void CPLDebug( const char * pszCategory, const char * pszFormat, ... )
 /* -------------------------------------------------------------------- */
 /*    Allocate a block for the error.                                   */
 /* -------------------------------------------------------------------- */
-    pszMessage = (char *) VSIMalloc( ERROR_MAX );
+    const int ERROR_MAX = 25000;
+    char *pszMessage = static_cast<char *>( VSIMalloc( ERROR_MAX ) );
     if( pszMessage == NULL )
         return;
-        
+
 /* -------------------------------------------------------------------- */
 /*      Dal -- always log a timestamp as the first part of the line     */
 /*      to ensure one is looking at what one should be looking at!      */
@@ -438,8 +516,8 @@ void CPLDebug( const char * pszCategory, const char * pszFormat, ... )
     if( CPLGetConfigOption( "CPL_TIMESTAMP", NULL ) != NULL )
     {
         strcpy( pszMessage, VSICTime( VSITime(NULL) ) );
-        
-        // On windows anyway, ctime puts a \n at the end, but I'm not 
+
+        // On windows anyway, ctime puts a \n at the end, but I'm not
         // convinced this is standard behaviour, so we'll get rid of it
         // carefully
 
@@ -467,13 +545,14 @@ void CPLDebug( const char * pszCategory, const char * pszFormat, ... )
 /* -------------------------------------------------------------------- */
     strcat( pszMessage, pszCategory );
     strcat( pszMessage, ": " );
-    
+
 /* -------------------------------------------------------------------- */
 /*      Format the application provided portion of the debug message.   */
 /* -------------------------------------------------------------------- */
+    va_list     args;
     va_start(args, pszFormat);
 
-    CPLvsnprintf(pszMessage+strlen(pszMessage), ERROR_MAX - strlen(pszMessage), 
+    CPLvsnprintf(pszMessage+strlen(pszMessage), ERROR_MAX - strlen(pszMessage),
               pszFormat, args);
 
     va_end(args);
@@ -498,13 +577,42 @@ void CPLDebug( const char * pszCategory, const char * pszFormat, ... )
 /* -------------------------------------------------------------------- */
     if( psCtx->psHandlerStack != NULL )
     {
-        psCtx->psHandlerStack->pfnHandler( CE_Debug, CPLE_None, pszMessage );
+        if( psCtx->psHandlerStack->bCatchDebug )
+        {
+            psCtx->psHandlerStack->pfnHandler( CE_Debug, CPLE_None, pszMessage );
+        }
+        else
+        {
+            CPLErrorHandlerNode *psNode = psCtx->psHandlerStack->psNext;
+            while( psNode != NULL )
+            {
+                if( psNode->bCatchDebug )
+                {
+                    psNode->pfnHandler( CE_Debug, CPLE_None, pszMessage );
+                    break;
+                }
+                psNode = psNode->psNext;
+            }
+            if( psNode == NULL )
+            {
+                CPLMutexHolderD( &hErrorMutex );
+                if( gbCatchDebug )
+                    pfnErrorHandler( CE_Debug, CPLE_None, pszMessage );
+                else
+                    CPLDefaultErrorHandler( CE_Debug, CPLE_None, pszMessage );
+            }
+        }
     }
     else
     {
         CPLMutexHolderD( &hErrorMutex );
         if( pfnErrorHandler != NULL )
-            pfnErrorHandler( CE_Debug, CPLE_None, pszMessage );
+        {
+            if( gbCatchDebug )
+                pfnErrorHandler( CE_Debug, CPLE_None, pszMessage );
+            else
+                CPLDefaultErrorHandler( CE_Debug, CPLE_None, pszMessage );
+        }
     }
 
     VSIFree( pszMessage );
@@ -524,6 +632,18 @@ void CPLDebug( const char * pszCategory, const char * pszFormat, ... )
 void CPL_STDCALL CPLErrorReset()
 {
     CPLErrorContext *psCtx = CPLGetErrorContext();
+    if( psCtx == NULL )
+        return;
+    if( IS_PREFEFINED_ERROR_CTX(psCtx) )
+    {
+        int bMemoryError = FALSE;
+        CPLSetTLSWithFreeFuncEx(
+            CTLS_ERRORCONTEXT,
+            reinterpret_cast<void*>(
+                const_cast<CPLErrorContext *>( &sNoErrorContext ) ),
+            NULL, &bMemoryError );
+        return;
+    }
 
     psCtx->nLastErrNo = CPLE_None;
     psCtx->szLastErrMsg[0] = '\0';
@@ -543,13 +663,41 @@ void CPL_STDCALL CPLErrorReset()
  * @since GDAL 2.0
  */
 
-void CPL_DLL CPLErrorSetState( CPLErr eErrClass, int err_no, const char* pszMsg )
+void CPL_DLL CPLErrorSetState( CPLErr eErrClass, CPLErrorNum err_no,
+                               const char* pszMsg )
 {
     CPLErrorContext *psCtx = CPLGetErrorContext();
+    if( psCtx == NULL )
+        return;
+    if( IS_PREFEFINED_ERROR_CTX(psCtx) )
+    {
+        int bMemoryError = FALSE;
+        if( eErrClass == CE_None )
+            CPLSetTLSWithFreeFuncEx(
+                CTLS_ERRORCONTEXT,
+                reinterpret_cast<void*>(
+                    const_cast<CPLErrorContext *>( &sNoErrorContext ) ),
+                NULL, &bMemoryError );
+        else if( eErrClass == CE_Warning )
+            CPLSetTLSWithFreeFuncEx(
+                CTLS_ERRORCONTEXT,
+                reinterpret_cast<void*>(
+                    const_cast<CPLErrorContext *>( &sWarningContext ) ),
+                NULL, &bMemoryError );
+        else if( eErrClass == CE_Failure )
+            CPLSetTLSWithFreeFuncEx(
+                CTLS_ERRORCONTEXT,
+                reinterpret_cast<void*>(
+                    const_cast<CPLErrorContext *>( &sFailureContext ) ),
+                NULL, &bMemoryError );
+        return;
+    }
 
     psCtx->nLastErrNo = err_no;
     strncpy(psCtx->szLastErrMsg, pszMsg, psCtx->nLastErrMsgMax);
-    psCtx->szLastErrMsg[MAX(psCtx->nLastErrMsgMax-1, (int)strlen(pszMsg))] = '\0';
+    psCtx->szLastErrMsg[
+        MAX(psCtx->nLastErrMsgMax-1,
+            static_cast<int>( strlen(pszMsg) ))] = '\0';
     psCtx->eLastErrType = eErrClass;
 }
 
@@ -561,15 +709,18 @@ void CPL_DLL CPLErrorSetState( CPLErr eErrClass, int err_no, const char* pszMsg
  * Fetch the last error number.
  *
  * Fetches the last error number posted with CPLError(), that hasn't
- * been cleared by CPLErrorReset().  This is the error number, not the error class.
+ * been cleared by CPLErrorReset().  This is the error number, not the error
+ * class.
  *
  * @return the error number of the last error to occur, or CPLE_None (0)
  * if there are no posted errors.
  */
 
-int CPL_STDCALL CPLGetLastErrorNo()
+CPLErrorNum CPL_STDCALL CPLGetLastErrorNo()
 {
     CPLErrorContext *psCtx = CPLGetErrorContext();
+    if( psCtx == NULL )
+        return 0;
 
     return psCtx->nLastErrNo;
 }
@@ -582,7 +733,8 @@ int CPL_STDCALL CPLGetLastErrorNo()
  * Fetch the last error type.
  *
  * Fetches the last error type posted with CPLError(), that hasn't
- * been cleared by CPLErrorReset().  This is the error class, not the error number.
+ * been cleared by CPLErrorReset().  This is the error class, not the error
+ * number.
  *
  * @return the error type of the last error to occur, or CE_None (0)
  * if there are no posted errors.
@@ -591,6 +743,8 @@ int CPL_STDCALL CPLGetLastErrorNo()
 CPLErr CPL_STDCALL CPLGetLastErrorType()
 {
     CPLErrorContext *psCtx = CPLGetErrorContext();
+    if( psCtx == NULL )
+        return CE_None;
 
     return psCtx->eLastErrType;
 }
@@ -613,6 +767,8 @@ CPLErr CPL_STDCALL CPLGetLastErrorType()
 const char* CPL_STDCALL CPLGetLastErrorMsg()
 {
     CPLErrorContext *psCtx = CPLGetErrorContext();
+    if( psCtx == NULL )
+        return "";
 
     return psCtx->szLastErrMsg;
 }
@@ -621,12 +777,10 @@ const char* CPL_STDCALL CPLGetLastErrorMsg()
 /*                       CPLDefaultErrorHandler()                       */
 /************************************************************************/
 
-void CPL_STDCALL CPLDefaultErrorHandler( CPLErr eErrClass, int nError, 
+void CPL_STDCALL CPLDefaultErrorHandler( CPLErr eErrClass, CPLErrorNum nError,
                              const char * pszErrorMsg )
 
 {
-    static int       bLogInit = FALSE;
-    static FILE *    fpLog = stderr;
     static int       nCount = 0;
     static int       nMaxErrors = -1;
 
@@ -634,7 +788,7 @@ void CPL_STDCALL CPLDefaultErrorHandler( CPLErr eErrClass, int nError,
     {
         if( nMaxErrors == -1 )
         {
-            nMaxErrors = 
+            nMaxErrors =
                 atoi(CPLGetConfigOption( "CPL_MAX_ERROR_REPORTS", "1000" ));
         }
 
@@ -643,9 +797,12 @@ void CPL_STDCALL CPLDefaultErrorHandler( CPLErr eErrClass, int nError,
             return;
     }
 
+    static FILE *fpLog = stderr;
+
+    static bool bLogInit = false;
     if( !bLogInit )
     {
-        bLogInit = TRUE;
+        bLogInit = true;
 
         fpLog = stderr;
         if( CPLGetConfigOption( "CPL_LOG", NULL ) != NULL )
@@ -666,13 +823,13 @@ void CPL_STDCALL CPLDefaultErrorHandler( CPLErr eErrClass, int nError,
     else
         fprintf( fpLog, "ERROR %d: %s\n", nError, pszErrorMsg );
 
-    if (eErrClass != CE_Debug 
-        && nMaxErrors > 0 
+    if (eErrClass != CE_Debug
+        && nMaxErrors > 0
         && nCount == nMaxErrors )
     {
-        fprintf( fpLog, 
+        fprintf( fpLog,
                  "More than %d errors or warnings have been reported. "
-                 "No more will be reported from now.\n", 
+                 "No more will be reported from now.\n",
                  nMaxErrors );
     }
 
@@ -683,7 +840,7 @@ void CPL_STDCALL CPLDefaultErrorHandler( CPLErr eErrClass, int nError,
 /*                        CPLQuietErrorHandler()                        */
 /************************************************************************/
 
-void CPL_STDCALL CPLQuietErrorHandler( CPLErr eErrClass , int nError, 
+void CPL_STDCALL CPLQuietErrorHandler( CPLErr eErrClass , CPLErrorNum nError,
                            const char * pszErrorMsg )
 
 {
@@ -695,22 +852,20 @@ void CPL_STDCALL CPLQuietErrorHandler( CPLErr eErrClass , int nError,
 /*                       CPLLoggingErrorHandler()                       */
 /************************************************************************/
 
-void CPL_STDCALL CPLLoggingErrorHandler( CPLErr eErrClass, int nError, 
+void CPL_STDCALL CPLLoggingErrorHandler( CPLErr eErrClass, CPLErrorNum nError,
                              const char * pszErrorMsg )
 
 {
-    static int       bLogInit = FALSE;
+    static bool      bLogInit = false;
     static FILE *    fpLog = stderr;
 
     if( !bLogInit )
     {
-        const char *cpl_log = NULL;
+        bLogInit = true;
 
         CPLSetConfigOption( "CPL_TIMESTAMP", "ON" );
 
-        bLogInit = TRUE;
-
-        cpl_log = CPLGetConfigOption("CPL_LOG", NULL );
+        const char *cpl_log = CPLGetConfigOption("CPL_LOG", NULL );
 
         fpLog = stderr;
         if( cpl_log != NULL && EQUAL(cpl_log,"OFF") )
@@ -719,20 +874,20 @@ void CPL_STDCALL CPLLoggingErrorHandler( CPLErr eErrClass, int nError,
         }
         else if( cpl_log != NULL )
         {
-            char*     pszPath;
-            int       i = 0;
-
-            pszPath = (char*)CPLMalloc(strlen(cpl_log) + 20);
+            size_t nPathLen = strlen(cpl_log) + 20;
+            char* pszPath
+                = static_cast<char *>( CPLMalloc(nPathLen) );
             strcpy(pszPath, cpl_log);
 
-            while( (fpLog = fopen( pszPath, "rt" )) != NULL ) 
+            int i = 0;
+            while( (fpLog = fopen( pszPath, "rt" )) != NULL )
             {
                 fclose( fpLog );
 
                 /* generate sequenced log file names, inserting # before ext.*/
                 if (strrchr(cpl_log, '.') == NULL)
                 {
-                    CPLsprintf( pszPath, "%s_%d%s", cpl_log, i++,
+                    snprintf( pszPath, nPathLen, "%s_%d%s", cpl_log, i++,
                              ".log" );
                 }
                 else
@@ -744,7 +899,7 @@ void CPL_STDCALL CPLLoggingErrorHandler( CPLErr eErrClass, int nError,
                     {
                         cpl_log_base[pos] = '\0';
                     }
-                    CPLsprintf( pszPath, "%s_%d%s", cpl_log_base,
+                    snprintf( pszPath, nPathLen, "%s_%d%s", cpl_log_base,
                              i++, ".log" );
                     CPLFree(cpl_log_base);
                 }
@@ -772,13 +927,19 @@ void CPL_STDCALL CPLLoggingErrorHandler( CPLErr eErrClass, int nError,
  *                      CPLTurnFailureIntoWarning()                   *
  **********************************************************************/
 
-void CPLTurnFailureIntoWarning(int bOn )
+void CPLTurnFailureIntoWarning( int bOn )
 {
     CPLErrorContext *psCtx = CPLGetErrorContext();
+    if( psCtx == NULL || IS_PREFEFINED_ERROR_CTX(psCtx) )
+    {
+        fprintf(stderr, "CPLTurnFailureIntoWarning() failed.\n");
+        return;
+    }
     psCtx->nFailureIntoWarning += (bOn) ? 1 : -1;
     if (psCtx->nFailureIntoWarning < 0)
     {
-        CPLDebug("CPL", "Wrong nesting of CPLTurnFailureIntoWarning(TRUE) / CPLTurnFailureIntoWarning(FALSE)");
+        CPLDebug( "CPL", "Wrong nesting of CPLTurnFailureIntoWarning(TRUE) / "
+                  "CPLTurnFailureIntoWarning(FALSE)" );
     }
 }
 
@@ -787,41 +948,46 @@ void CPLTurnFailureIntoWarning(int bOn )
  **********************************************************************/
 
 /**
- * Install custom error handle with user's data. This method is 
- * essentially CPLSetErrorHandler with an added pointer to pUserData.  
- * The pUserData is not returned in the CPLErrorHandler, however, and 
+ * Install custom error handle with user's data. This method is
+ * essentially CPLSetErrorHandler with an added pointer to pUserData.
+ * The pUserData is not returned in the CPLErrorHandler, however, and
  * must be fetched via CPLGetLastErrorUserData
  *
  * @param pfnErrorHandlerNew new error handler function.
  * @param pUserData User data to carry along with the error context.
  * @return returns the previously installed error handler.
- */ 
+ */
 
-CPLErrorHandler CPL_STDCALL 
-CPLSetErrorHandlerEx( CPLErrorHandler pfnErrorHandlerNew, 
+CPLErrorHandler CPL_STDCALL
+CPLSetErrorHandlerEx( CPLErrorHandler pfnErrorHandlerNew,
                       void* pUserData )
 {
-    CPLErrorHandler     pfnOldHandler = pfnErrorHandler;
     CPLErrorContext *psCtx = CPLGetErrorContext();
+    if( psCtx == NULL || IS_PREFEFINED_ERROR_CTX(psCtx) )
+    {
+        fprintf(stderr, "CPLSetErrorHandlerEx() failed.\n");
+        return NULL;
+    }
 
     if( psCtx->psHandlerStack != NULL )
     {
-        CPLDebug( "CPL", 
+        CPLDebug( "CPL",
                   "CPLSetErrorHandler() called with an error handler on\n"
-                  "the local stack.  New error handler will not be used immediately.\n" );
+                  "the local stack.  New error handler will not be used "
+                  "immediately.\n" );
     }
 
-
+    CPLErrorHandler pfnOldHandler;
     {
         CPLMutexHolderD( &hErrorMutex );
 
         pfnOldHandler = pfnErrorHandler;
-        
+
         if( pfnErrorHandler == NULL )
             pfnErrorHandler = CPLDefaultErrorHandler;
         else
             pfnErrorHandler = pfnErrorHandlerNew;
-            
+
         pErrorHandlerUserData = pUserData;
     }
 
@@ -844,7 +1010,7 @@ CPLSetErrorHandlerEx( CPLErrorHandler pfnErrorHandlerNew,
  * </pre>
  *
  * Pass NULL to come back to the default behavior.  The default behaviour
- * (CPLDefaultErrorHandler()) is to write the message to stderr. 
+ * (CPLDefaultErrorHandler()) is to write the message to stderr.
  *
  * The msg will be a partially formatted error message not containing the
  * "ERROR %d:" portion emitted by the default handler.  Message formatting
@@ -860,18 +1026,18 @@ CPLSetErrorHandlerEx( CPLErrorHandler pfnErrorHandlerNew,
  *
  * Note that error handlers set with CPLSetErrorHandler() apply to all
  * threads in an application, while error handlers set with CPLPushErrorHandler
- * are thread-local.  However, any error handlers pushed with 
- * CPLPushErrorHandler (and not removed with CPLPopErrorHandler) take 
- * precidence over the global error handlers set with CPLSetErrorHandler(). 
+ * are thread-local.  However, any error handlers pushed with
+ * CPLPushErrorHandler (and not removed with CPLPopErrorHandler) take
+ * precedence over the global error handlers set with CPLSetErrorHandler().
  * Generally speaking CPLSetErrorHandler() would be used to set a desired
  * global error handler, while CPLPushErrorHandler() would be used to install
  * a temporary local error handler, such as CPLQuietErrorHandler() to suppress
- * error reporting in a limited segment of code. 
+ * error reporting in a limited segment of code.
  *
  * @param pfnErrorHandlerNew new error handler function.
  * @return returns the previously installed error handler.
- */ 
-CPLErrorHandler CPL_STDCALL 
+ */
+CPLErrorHandler CPL_STDCALL
 CPLSetErrorHandler( CPLErrorHandler pfnErrorHandlerNew )
 {
     return CPLSetErrorHandlerEx(pfnErrorHandlerNew, NULL);
@@ -887,7 +1053,7 @@ CPLSetErrorHandler( CPLErrorHandler pfnErrorHandlerNew )
  * This pushes a new error handler on the thread-local error handler
  * stack.  This handler will be used until removed with CPLPopErrorHandler().
  *
- * The CPLSetErrorHandler() docs have further information on how 
+ * The CPLSetErrorHandler() docs have further information on how
  * CPLError handlers work.
  *
  * @param pfnErrorHandlerNew new error handler function.
@@ -908,26 +1074,33 @@ void CPL_STDCALL CPLPushErrorHandler( CPLErrorHandler pfnErrorHandlerNew )
  * Push a new CPLError handler with user data on the error context.
  *
  * This pushes a new error handler on the thread-local error handler
- * stack.  This handler will be used until removed with CPLPopErrorHandler(). 
+ * stack.  This handler will be used until removed with CPLPopErrorHandler().
  * Obtain the user data back by using CPLGetErrorContext().
  *
- * The CPLSetErrorHandler() docs have further information on how 
+ * The CPLSetErrorHandler() docs have further information on how
  * CPLError handlers work.
  *
  * @param pfnErrorHandlerNew new error handler function.
- * @param pUserData User data to put on the error context. 
+ * @param pUserData User data to put on the error context.
  */
-void CPL_STDCALL CPLPushErrorHandlerEx( CPLErrorHandler pfnErrorHandlerNew, 
+void CPL_STDCALL CPLPushErrorHandlerEx( CPLErrorHandler pfnErrorHandlerNew,
                                         void* pUserData )
 
 {
     CPLErrorContext *psCtx = CPLGetErrorContext();
-    CPLErrorHandlerNode         *psNode;
 
-    psNode = (CPLErrorHandlerNode *) CPLMalloc(sizeof(CPLErrorHandlerNode));
+    if( psCtx == NULL || IS_PREFEFINED_ERROR_CTX(psCtx) )
+    {
+        fprintf(stderr, "CPLPushErrorHandlerEx() failed.\n");
+        return;
+    }
+
+    CPLErrorHandlerNode *psNode = static_cast<CPLErrorHandlerNode *>(
+        CPLMalloc( sizeof(CPLErrorHandlerNode) ) );
     psNode->psNext = psCtx->psHandlerStack;
     psNode->pfnHandler = pfnErrorHandlerNew;
     psNode->pUserData = pUserData;
+    psNode->bCatchDebug = true;
     psCtx->psHandlerStack = psNode;
 }
 
@@ -938,17 +1111,23 @@ void CPL_STDCALL CPLPushErrorHandlerEx( CPLErrorHandler pfnErrorHandlerNew,
 /**
  * Pop error handler off stack.
  *
- * Discards the current error handler on the error handler stack, and restores 
+ * Discards the current error handler on the error handler stack, and restores
  * the one in use before the last CPLPushErrorHandler() call.  This method
  * has no effect if there are no error handlers on the current threads error
- * handler stack. 
- */ 
+ * handler stack.
+ */
 
 void CPL_STDCALL CPLPopErrorHandler()
 
 {
     CPLErrorContext *psCtx = CPLGetErrorContext();
 
+    if( psCtx == NULL || IS_PREFEFINED_ERROR_CTX(psCtx) )
+    {
+        fprintf(stderr, "CPLPopErrorHandler() failed.\n");
+        return;
+    }
+
     if( psCtx->psHandlerStack != NULL )
     {
         CPLErrorHandlerNode     *psNode = psCtx->psHandlerStack;
@@ -959,6 +1138,40 @@ void CPL_STDCALL CPLPopErrorHandler()
 }
 
 /************************************************************************/
+/*                 CPLSetCurrentErrorHandlerCatchDebug()                */
+/************************************************************************/
+
+/**
+ * Set if the current error handler should intercept debug messages, or if
+ * they should be processed by the previous handler.
+ *
+ * By default when installing a custom error handler, this one intercepts
+ * debug messages. In some cases, this might not be desirable and the user
+ * would prefer that the previous installed handler (or the default one if no
+ * previous installed handler exists in the stack) deal with it. In which
+ * case, this function should be called with bCatchDebug.
+ *
+ * @param bCatchDebug FALSE if the current error handler should not intercept debug messages
+ * @since GDAL 2.1
+ */
+
+void CPL_STDCALL CPLSetCurrentErrorHandlerCatchDebug( int bCatchDebug )
+{
+    CPLErrorContext *psCtx = CPLGetErrorContext();
+
+    if( psCtx == NULL || IS_PREFEFINED_ERROR_CTX(psCtx) )
+    {
+        fprintf(stderr, "CPLSetCurrentErrorHandlerCatchDebug() failed.\n");
+        return;
+    }
+
+    if( psCtx->psHandlerStack != NULL )
+        psCtx->psHandlerStack->bCatchDebug = CPL_TO_BOOL(bCatchDebug);
+    else
+        gbCatchDebug = CPL_TO_BOOL(bCatchDebug);
+}
+
+/************************************************************************/
 /*                             _CPLAssert()                             */
 /*                                                                      */
 /*      This function is called only when an assertion fails.           */
@@ -984,6 +1197,9 @@ void CPL_STDCALL _CPLAssert( const char * pszExpression, const char * pszFile,
               "Assertion `%s' failed\n"
               "in file `%s', line %d\n",
               pszExpression, pszFile, iLine );
+
+    // Just to please compiler so it is aware the function does not return.
+    abort();
 }
 
 
diff --git a/port/cpl_error.h b/port/cpl_error.h
index 4938960..3ddad1a 100644
--- a/port/cpl_error.h
+++ b/port/cpl_error.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_error.h 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: cpl_error.h 33842 2016-04-01 08:37:32Z rouault $
  *
  * Name:     cpl_error.h
  * Project:  CPL - Common Portability Library
@@ -15,16 +15,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
@@ -42,7 +42,7 @@
  *
  * CPL error handling services.
  */
-  
+
 CPL_C_START
 
 typedef enum
@@ -54,32 +54,94 @@ typedef enum
     CE_Fatal = 4
 } CPLErr;
 
-void CPL_DLL CPLError(CPLErr eErrClass, int err_no, const char *fmt, ...)  CPL_PRINT_FUNC_FORMAT (3, 4);
-void CPL_DLL CPLErrorV(CPLErr, int, const char *, va_list );
-void CPL_DLL CPLEmergencyError( const char * );
+/* ==================================================================== */
+/*      Well known error codes.                                         */
+/* ==================================================================== */
+
+#ifdef STRICT_CPLERRORNUM_TYPE
+
+/* This is not appropriate for the general case, as there are parts */
+/* of GDAL which use custom error codes, but this can help diagnose confusions */
+/* between CPLErr and CPLErrorNum */
+typedef enum
+{
+  CPLE_None,
+  CPLE_AppDefined,
+  CPLE_OutOfMemory,
+  CPLE_FileIO,
+  CPLE_OpenFailed,
+  CPLE_IllegalArg,
+  CPLE_NotSupported,
+  CPLE_AssertionFailed,
+  CPLE_NoWriteAccess,
+  CPLE_UserInterrupt,
+  CPLE_ObjectNull,
+  CPLE_HttpResponse,
+  CPLE_HttpResponse,
+  CPLE_AWSBucketNotFound,
+  CPLE_AWSObjectNotFound,
+  CPLE_AWSAccessDenied,
+  CPLE_AWSInvalidCredentials,
+  CPLE_AWSSignatureDoesNotMatch,
+} CPLErrorNum;
+
+#else
+
+typedef int CPLErrorNum;
+
+#define CPLE_None                       0
+#define CPLE_AppDefined                 1
+#define CPLE_OutOfMemory                2
+#define CPLE_FileIO                     3
+#define CPLE_OpenFailed                 4
+#define CPLE_IllegalArg                 5
+#define CPLE_NotSupported               6
+#define CPLE_AssertionFailed            7
+#define CPLE_NoWriteAccess              8
+#define CPLE_UserInterrupt              9
+#define CPLE_ObjectNull                 10
+
+/*
+ * Filesystem-specific errors
+ */
+#define CPLE_HttpResponse               11
+#define CPLE_AWSBucketNotFound          12
+#define CPLE_AWSObjectNotFound          13
+#define CPLE_AWSAccessDenied            14
+#define CPLE_AWSInvalidCredentials      15
+#define CPLE_AWSSignatureDoesNotMatch    16
+
+/* 100 - 299 reserved for GDAL */
+
+#endif
+
+void CPL_DLL CPLError(CPLErr eErrClass, CPLErrorNum err_no, const char *fmt, ...)  CPL_PRINT_FUNC_FORMAT (3, 4);
+void CPL_DLL CPLErrorV(CPLErr, CPLErrorNum, const char *, va_list );
+void CPL_DLL CPLEmergencyError( const char * ) CPL_NO_RETURN;
 void CPL_DLL CPL_STDCALL CPLErrorReset( void );
-int CPL_DLL CPL_STDCALL CPLGetLastErrorNo( void );
+CPLErrorNum CPL_DLL CPL_STDCALL CPLGetLastErrorNo( void );
 CPLErr CPL_DLL CPL_STDCALL CPLGetLastErrorType( void );
 const char CPL_DLL * CPL_STDCALL CPLGetLastErrorMsg( void );
 void CPL_DLL * CPL_STDCALL CPLGetErrorHandlerUserData(void);
-void CPL_DLL CPLErrorSetState( CPLErr eErrClass, int err_no, const char* pszMsg );
+void CPL_DLL CPLErrorSetState( CPLErr eErrClass, CPLErrorNum err_no, const char* pszMsg );
 void CPL_DLL CPLCleanupErrorMutex( void );
 
-typedef void (CPL_STDCALL *CPLErrorHandler)(CPLErr, int, const char*);
+typedef void (CPL_STDCALL *CPLErrorHandler)(CPLErr, CPLErrorNum, const char*);
 
-void CPL_DLL CPL_STDCALL CPLLoggingErrorHandler( CPLErr, int, const char * );
-void CPL_DLL CPL_STDCALL CPLDefaultErrorHandler( CPLErr, int, const char * );
-void CPL_DLL CPL_STDCALL CPLQuietErrorHandler( CPLErr, int, const char * );
+void CPL_DLL CPL_STDCALL CPLLoggingErrorHandler( CPLErr, CPLErrorNum, const char * );
+void CPL_DLL CPL_STDCALL CPLDefaultErrorHandler( CPLErr, CPLErrorNum, const char * );
+void CPL_DLL CPL_STDCALL CPLQuietErrorHandler( CPLErr, CPLErrorNum, const char * );
 void CPLTurnFailureIntoWarning(int bOn );
 
 CPLErrorHandler CPL_DLL CPL_STDCALL CPLSetErrorHandler(CPLErrorHandler);
 CPLErrorHandler CPL_DLL CPL_STDCALL CPLSetErrorHandlerEx(CPLErrorHandler, void*);
 void CPL_DLL CPL_STDCALL CPLPushErrorHandler( CPLErrorHandler );
 void CPL_DLL CPL_STDCALL CPLPushErrorHandlerEx( CPLErrorHandler, void* );
+void CPL_DLL CPL_STDCALL CPLSetCurrentErrorHandlerCatchDebug( int bCatchDebug );
 void CPL_DLL CPL_STDCALL CPLPopErrorHandler(void);
 
 void CPL_DLL CPL_STDCALL CPLDebug( const char *, const char *, ... )  CPL_PRINT_FUNC_FORMAT (2, 3);
-void CPL_DLL CPL_STDCALL _CPLAssert( const char *, const char *, int );
+void CPL_DLL CPL_STDCALL _CPLAssert( const char *, const char *, int ) CPL_NO_RETURN;
 
 #ifdef DEBUG
 #  define CPLAssert(expr)  ((expr) ? (void)(0) : _CPLAssert(#expr,__FILE__,__LINE__))
@@ -114,22 +176,4 @@ CPL_C_END
            "Pointer \'%s\' is NULL in \'%s\'.\n", #ptr, (func)); \
         return (rc); }} while(0)
 
-/* ==================================================================== */
-/*      Well known error codes.                                         */
-/* ==================================================================== */
-
-#define CPLE_None                       0
-#define CPLE_AppDefined                 1
-#define CPLE_OutOfMemory                2
-#define CPLE_FileIO                     3
-#define CPLE_OpenFailed                 4
-#define CPLE_IllegalArg                 5
-#define CPLE_NotSupported               6
-#define CPLE_AssertionFailed            7
-#define CPLE_NoWriteAccess              8
-#define CPLE_UserInterrupt              9
-#define CPLE_ObjectNull                 10
-
-/* 100 - 299 reserved for GDAL */
-
 #endif /* CPL_ERROR_H_INCLUDED */
diff --git a/port/cpl_findfile.cpp b/port/cpl_findfile.cpp
index e7416f8..bf1eea3 100644
--- a/port/cpl_findfile.cpp
+++ b/port/cpl_findfile.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_findfile.cpp 27547 2014-07-23 16:27:50Z goatbar $
+ * $Id: cpl_findfile.cpp 33724 2016-03-16 17:14:11Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Generic data file location finder, with application hooking.
@@ -31,8 +31,9 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 #include "cpl_multiproc.h"
+#include "cpl_vsi.h"
 
-CPL_CVSID("$Id: cpl_findfile.cpp 27547 2014-07-23 16:27:50Z goatbar $");
+CPL_CVSID("$Id: cpl_findfile.cpp 33724 2016-03-16 17:14:11Z goatbar $");
 
 typedef struct
 {
@@ -52,8 +53,8 @@ static CPLFileFinder CPLPopFileFinderInternal(FindFileTLS* pTLSData);
 
 static void CPLFindFileFreeTLS(void* pData)
 {
-    FindFileTLS* pTLSData = (FindFileTLS*) pData;
-    if( pTLSData->bFinderInitialized )
+    FindFileTLS* pTLSData = reinterpret_cast<FindFileTLS *>( pData );
+    if( pTLSData != NULL && pTLSData->bFinderInitialized )
     {
         while( pTLSData->papszFinderLocations != NULL )
             CPLPopFinderLocationInternal(pTLSData);
@@ -70,11 +71,18 @@ static void CPLFindFileFreeTLS(void* pData)
 
 static FindFileTLS* CPLGetFindFileTLS()
 {
+    int bMemoryError = FALSE;
     FindFileTLS* pTLSData =
-            (FindFileTLS *) CPLGetTLS( CTLS_FINDFILE );
+        reinterpret_cast<FindFileTLS *>(
+            CPLGetTLSEx( CTLS_FINDFILE, &bMemoryError ) );
+    if( bMemoryError )
+        return NULL;
     if (pTLSData == NULL)
     {
-        pTLSData = (FindFileTLS*) CPLCalloc(1, sizeof(FindFileTLS));
+        pTLSData = static_cast<FindFileTLS *>(
+            VSI_CALLOC_VERBOSE(1, sizeof(FindFileTLS) ) );
+        if( pTLSData == NULL )
+            return NULL;
         CPLSetTLSWithFreeFunc( CTLS_FINDFILE, pTLSData, CPLFindFileFreeTLS );
     }
     return pTLSData;
@@ -88,7 +96,7 @@ static FindFileTLS* CPLFinderInit()
 
 {
     FindFileTLS* pTLSData = CPLGetFindFileTLS();
-    if( !pTLSData->bFinderInitialized )
+    if( pTLSData != NULL && !pTLSData->bFinderInitialized )
     {
         pTLSData->bFinderInitialized = TRUE;
         CPLPushFileFinder( CPLDefaultFindFile );
@@ -124,34 +132,37 @@ void CPLFinderClean()
 {
     FindFileTLS* pTLSData = CPLGetFindFileTLS();
     CPLFindFileFreeTLS(pTLSData);
-    CPLSetTLS( CTLS_FINDFILE, NULL, FALSE );
+    int bMemoryError = FALSE;
+    CPLSetTLSWithFreeFuncEx( CTLS_FINDFILE, NULL, NULL, &bMemoryError );
+    // TODO: if( bMemoryError )
+    // {
+    // }
 }
 
 /************************************************************************/
 /*                         CPLDefaultFindFile()                         */
 /************************************************************************/
 
-const char *CPLDefaultFindFile( const char *pszClass, 
+const char *CPLDefaultFindFile( const char * /* pszClass */,
                                 const char *pszBasename )
 
 {
     FindFileTLS* pTLSData = CPLGetFindFileTLS();
-    int         i, nLocations = CSLCount( pTLSData->papszFinderLocations );
-
-    (void) pszClass;
+    if( pTLSData == NULL )
+        return NULL;
+    const int nLocations = CSLCount( pTLSData->papszFinderLocations );
 
-    for( i = nLocations-1; i >= 0; i-- )
+    for( int i = nLocations-1; i >= 0; i-- )
     {
-        const char  *pszResult;
-        VSIStatBuf  sStat;
-
-        pszResult = CPLFormFilename( pTLSData->papszFinderLocations[i], pszBasename, 
-                                     NULL );
+        const char  *pszResult
+            = CPLFormFilename( pTLSData->papszFinderLocations[i], pszBasename,
+                               NULL );
 
-        if( VSIStat( pszResult, &sStat ) == 0 )
+        VSIStatBufL  sStat;
+        if( VSIStatL( pszResult, &sStat ) == 0 )
             return pszResult;
     }
-    
+
     return NULL;
 }
 
@@ -162,15 +173,14 @@ const char *CPLDefaultFindFile( const char *pszClass,
 const char *CPLFindFile( const char *pszClass, const char *pszBasename )
 
 {
-    int         i;
-
     FindFileTLS* pTLSData = CPLFinderInit();
+    if( pTLSData == NULL )
+        return NULL;
 
-    for( i = pTLSData->nFileFinders-1; i >= 0; i-- )
+    for( int i = pTLSData->nFileFinders-1; i >= 0; i-- )
     {
-        const char * pszResult;
-
-        pszResult = (pTLSData->papfnFinders[i])( pszClass, pszBasename );
+        const char * pszResult
+            = (pTLSData->papfnFinders[i])( pszClass, pszBasename );
         if( pszResult != NULL )
             return pszResult;
     }
@@ -186,9 +196,12 @@ void CPLPushFileFinder( CPLFileFinder pfnFinder )
 
 {
     FindFileTLS* pTLSData = CPLFinderInit();
+    if (pTLSData == NULL )
+        return;
 
-    pTLSData->papfnFinders = (CPLFileFinder *) 
-        CPLRealloc(pTLSData->papfnFinders,  sizeof(void*) * ++pTLSData->nFileFinders);
+    pTLSData->papfnFinders = static_cast<CPLFileFinder *>(
+        CPLRealloc(pTLSData->papfnFinders,
+            sizeof(CPLFileFinder) * ++pTLSData->nFileFinders) );
     pTLSData->papfnFinders[pTLSData->nFileFinders-1] = pfnFinder;
 }
 
@@ -199,12 +212,10 @@ void CPLPushFileFinder( CPLFileFinder pfnFinder )
 CPLFileFinder CPLPopFileFinderInternal(FindFileTLS* pTLSData)
 
 {
-    CPLFileFinder pfnReturn;
-
-    if( pTLSData->nFileFinders == 0 )
+    if( pTLSData == NULL || pTLSData->nFileFinders == 0 )
         return NULL;
 
-    pfnReturn = pTLSData->papfnFinders[--pTLSData->nFileFinders];
+    CPLFileFinder pfnReturn = pTLSData->papfnFinders[--pTLSData->nFileFinders];
 
     if( pTLSData->nFileFinders == 0)
     {
@@ -229,9 +240,11 @@ void CPLPushFinderLocation( const char *pszLocation )
 
 {
     FindFileTLS* pTLSData = CPLFinderInit();
-
-    pTLSData->papszFinderLocations  = CSLAddString( pTLSData->papszFinderLocations, 
-                                          pszLocation );
+    if( pTLSData == NULL )
+        return;
+    pTLSData->papszFinderLocations
+        = CSLAddStringMayFail( pTLSData->papszFinderLocations,
+                                   pszLocation );
 }
 
 
@@ -242,12 +255,10 @@ void CPLPushFinderLocation( const char *pszLocation )
 static void CPLPopFinderLocationInternal(FindFileTLS* pTLSData)
 
 {
-    int      nCount;
-
-    if( pTLSData->papszFinderLocations == NULL )
+    if( pTLSData == NULL || pTLSData->papszFinderLocations == NULL )
         return;
 
-    nCount = CSLCount(pTLSData->papszFinderLocations);
+    const int nCount = CSLCount(pTLSData->papszFinderLocations);
     if( nCount == 0 )
         return;
 
diff --git a/port/cpl_getexecpath.cpp b/port/cpl_getexecpath.cpp
index cea3977..9e076a5 100644
--- a/port/cpl_getexecpath.cpp
+++ b/port/cpl_getexecpath.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_getexecpath.cpp 27721 2014-09-22 12:42:28Z goatbar $
+ * $Id: cpl_getexecpath.cpp 33646 2016-03-05 15:54:03Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement CPLGetExecPath().
@@ -14,33 +14,29 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: cpl_getexecpath.cpp 27721 2014-09-22 12:42:28Z goatbar $");
+CPL_CVSID("$Id: cpl_getexecpath.cpp 33646 2016-03-05 15:54:03Z goatbar $");
 
-#if defined(WIN32) || defined(WIN32CE)
+#if defined(WIN32)
 
 #define HAVE_IMPLEMENTATION 1
 
-#if defined(WIN32CE)
-#  include "cpl_win32ce_api.h"
-#else
-#  include <windows.h>
-#endif
+#include <windows.h>
 
 /************************************************************************/
 /*                           CPLGetExecPath()                           */
@@ -48,7 +44,6 @@ CPL_CVSID("$Id: cpl_getexecpath.cpp 27721 2014-09-22 12:42:28Z goatbar $");
 
 int CPLGetExecPath( char *pszPathBuf, int nMaxLength )
 {
-#ifndef WIN32CE
     if( CSLTestBoolean(
             CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
     {
@@ -62,7 +57,7 @@ int CPLGetExecPath( char *pszPathBuf, int nMaxLength )
         }
         else
         {
-            char *pszDecoded = 
+            char *pszDecoded =
                 CPLRecodeFromWChar(pwszPathBuf,CPL_ENC_UCS2,CPL_ENC_UTF8);
 
             strncpy( pszPathBuf, pszDecoded, nMaxLength );
@@ -78,12 +73,6 @@ int CPLGetExecPath( char *pszPathBuf, int nMaxLength )
         else
             return TRUE;
     }
-#else
-    if( CE_GetModuleFileNameA( NULL, pszPathBuf, nMaxLength ) == 0 )
-        return FALSE;
-    else
-        return TRUE;
-#endif
 }
 
 #endif
@@ -102,10 +91,9 @@ int CPLGetExecPath( char *pszPathBuf, int nMaxLength )
 {
     long nPID = getpid();
     CPLString osExeLink;
-    ssize_t nResultLen;
 
     osExeLink.Printf( "/proc/%ld/exe", nPID );
-    nResultLen = readlink( osExeLink, pszPathBuf, nMaxLength );
+    ssize_t nResultLen = readlink( osExeLink, pszPathBuf, nMaxLength );
     if( nResultLen >= 0 )
         pszPathBuf[nResultLen] = '\0';
     else
@@ -121,10 +109,10 @@ int CPLGetExecPath( char *pszPathBuf, int nMaxLength )
 /************************************************************************/
 
 /**
- * Fetch path of executable. 
+ * Fetch path of executable.
  *
  * The path to the executable currently running is returned.  This path
- * includes the name of the executable.   Currently this only works on 
+ * includes the name of the executable.   Currently this only works on
  * win32 and linux platforms.  The returned path is UTF-8 encoded.
  *
  * @param pszPathBuf the buffer into which the path is placed.
@@ -141,4 +129,3 @@ int CPLGetExecPath( CPL_UNUSED char *pszPathBuf, CPL_UNUSED int nMaxLength )
 }
 
 #endif
-
diff --git a/port/cpl_google_oauth2.cpp b/port/cpl_google_oauth2.cpp
index 32ecaf6..cc38de7 100644
--- a/port/cpl_google_oauth2.cpp
+++ b/port/cpl_google_oauth2.cpp
@@ -6,7 +6,7 @@
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
- * Copyright (c) 2013, Frank Warmerdam 
+ * Copyright (c) 2013, Frank Warmerdam
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -66,9 +66,9 @@ static CPLStringList ParseSimpleJson(const char *pszJson)
 {
 /* -------------------------------------------------------------------- */
 /*      We are expecting simple documents like the following with no    */
-/*      heirarchy or complex structure.                                 */
+/*      hierarchy or complex structure.                                 */
 /* -------------------------------------------------------------------- */
-/*    
+/*
     {
         "access_token":"1/fFBGRNJru1FQd44AzqT3Zg",
         "expires_in":3920,
@@ -84,7 +84,7 @@ static CPLStringList ParseSimpleJson(const char *pszJson)
     {
         oNameValue.SetNameValue( oWords[i], oWords[i+1] );
     }
-    
+
     return oNameValue;
 }
 
@@ -93,24 +93,24 @@ static CPLStringList ParseSimpleJson(const char *pszJson)
 /************************************************************************/
 
 /**
- * Return authorization url for a given scope. 
+ * Return authorization url for a given scope.
  *
  * Returns the URL that a user should visit, and use for authentication
- * in order to get an "auth token" indicating their willingness to use a 
- * service. 
+ * in order to get an "auth token" indicating their willingness to use a
+ * service.
  *
  * Note that when the user visits this url they will be asked to login
- * (using a google/gmail/etc) account, and to authorize use of the 
- * requested scope for the application "GDAL/OGR".  Once they have done 
+ * (using a google/gmail/etc) account, and to authorize use of the
+ * requested scope for the application "GDAL/OGR".  Once they have done
  * so, they will be presented with a lengthy string they should "enter
  * into their application".  This is the "auth token" to be passed to
- * GOA2GetRefreshToken().  The "auth token" can only be used once. 
- * 
- * This function should never fail. 
+ * GOA2GetRefreshToken().  The "auth token" can only be used once.
+ *
+ * This function should never fail.
+ *
+ * @param pszScope the service being requested, not yet URL encoded, such as
+ * "https://www.googleapis.com/auth/fusiontables".
  *
- * @param pszScope the service being requested, not yet URL encoded, such as 
- * "https://www.googleapis.com/auth/fusiontables". 
- * 
  * @return the URL to visit - should be freed with CPLFree().
  */
 
@@ -123,7 +123,7 @@ char *GOA2GetAuthorizationURL(const char *pszScope)
     osScope.Seize(CPLEscapeString(pszScope, -1, CPLES_URL));
     osURL.Printf( "%s/auth?scope=%s&redirect_uri=urn:ietf:wg:oauth:2.0:oob&response_type=code&client_id=%s",
                   GOOGLE_AUTH_URL,
-                  osScope.c_str(), 
+                  osScope.c_str(),
                   CPLGetConfigOption("GOA2_CLIENT_ID", GDAL_CLIENT_ID));
     return CPLStrdup(osURL);
 }
@@ -133,19 +133,19 @@ char *GOA2GetAuthorizationURL(const char *pszScope)
 /************************************************************************/
 
 /**
- * Turn Auth Token into a Refresh Token. 
- * 
- * A one time "auth token" provided by the user is turned into a 
+ * Turn Auth Token into a Refresh Token.
+ *
+ * A one time "auth token" provided by the user is turned into a
  * reusable "refresh token" using a google oauth2 web service.
  *
  * A CPLError will be reported if the translation fails for some reason.
  * Common reasons include the auth token already having been used before,
- * it not being appropriate for the passed scope and configured client api 
+ * it not being appropriate for the passed scope and configured client api
  * or http connection problems.  NULL is returned on error.
  *
- * @param pszAuthToken the authorization token from the user. 
- * @param pszScope the scope for which it is valid. 
- * 
+ * @param pszAuthToken the authorization token from the user.
+ * @param pszScope the scope for which it is valid.
+ *
  * @return refresh token, to be freed with CPLFree(), null on failure.
  */
 
@@ -168,16 +168,16 @@ char CPL_DLL *GOA2GetRefreshToken( const char *pszAuthToken,
         "&client_id=%s"
         "&client_secret=%s"
         "&redirect_uri=urn:ietf:wg:oauth:2.0:oob"
-        "&grant_type=authorization_code", 
+        "&grant_type=authorization_code",
         pszAuthToken,
-        CPLGetConfigOption("GOA2_CLIENT_ID", GDAL_CLIENT_ID), 
+        CPLGetConfigOption("GOA2_CLIENT_ID", GDAL_CLIENT_ID),
         CPLGetConfigOption("GOA2_CLIENT_SECRET", GDAL_CLIENT_SECRET));
     oOptions.AddString(osItem);
 
 /* -------------------------------------------------------------------- */
 /*      Submit request by HTTP.                                         */
 /* -------------------------------------------------------------------- */
-    CPLHTTPResult * psResult = 
+    CPLHTTPResult * psResult =
         CPLHTTPFetch( GOOGLE_AUTH_URL "/token", oOptions);
 
     if (psResult == NULL)
@@ -188,7 +188,7 @@ char CPL_DLL *GOA2GetRefreshToken( const char *pszAuthToken,
 /*      After the first use it will return invalid_grant.               */
 /* -------------------------------------------------------------------- */
     if( psResult->pabyData != NULL
-        && strstr((const char *) psResult->pabyData,"invalid_grant") != NULL) 
+        && strstr((const char *) psResult->pabyData,"invalid_grant") != NULL)
     {
         CPLString osURL;
         osURL.Seize( GOA2GetAuthorizationURL(pszScope) );
@@ -214,7 +214,7 @@ char CPL_DLL *GOA2GetRefreshToken( const char *pszAuthToken,
         return NULL;
     }
 
-    CPLDebug( "GOA2", "Access Token Response:\n%s", 
+    CPLDebug( "GOA2", "Access Token Response:\n%s",
               (const char *) psResult->pabyData );
 
 /* -------------------------------------------------------------------- */
@@ -237,13 +237,13 @@ char CPL_DLL *GOA2GetRefreshToken( const char *pszAuthToken,
     CPLDebug("GOA2", "Access Token : '%s'", osAccessToken.c_str());
     CPLDebug("GOA2", "Refresh Token : '%s'", osRefreshToken.c_str());
 
-    if( osRefreshToken.size() == 0) 
+    if( osRefreshToken.size() == 0)
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to identify a refresh token in the OAuth2 response.");
         return NULL;
     }
-    else 
+    else
     {
         // Currently we discard the access token and just return the refresh token
         return CPLStrdup(osRefreshToken);
@@ -256,17 +256,17 @@ char CPL_DLL *GOA2GetRefreshToken( const char *pszAuthToken,
 
 /**
  * Fetch access token using refresh token.
- * 
+ *
  * The permanent refresh token is used to fetch a temporary (usually one
- * hour) access token using Google OAuth2 web services. 
+ * hour) access token using Google OAuth2 web services.
  *
  * A CPLError will be reported if the request fails for some reason.
  * Common reasons include the refresh token having been revoked by the
  * user or http connection problems.
  *
  * @param pszRefreshToken the refresh token from GOA2GetRefreshToken().
- * @param pszScope the scope for which it is valid. 
- * 
+ * @param pszScope the scope for which it is valid.
+ *
  * @return access token, to be freed with CPLFree(), null on failure.
  */
 
@@ -287,9 +287,9 @@ char *GOA2GetAccessToken( const char *pszRefreshToken,
         "refresh_token=%s"
         "&client_id=%s"
         "&client_secret=%s"
-        "&grant_type=refresh_token", 
+        "&grant_type=refresh_token",
         pszRefreshToken,
-        CPLGetConfigOption("GOA2_CLIENT_ID", GDAL_CLIENT_ID), 
+        CPLGetConfigOption("GOA2_CLIENT_ID", GDAL_CLIENT_ID),
         CPLGetConfigOption("GOA2_CLIENT_SECRET", GDAL_CLIENT_SECRET));
     oOptions.AddString(osItem);
 
@@ -315,7 +315,7 @@ char *GOA2GetAccessToken( const char *pszRefreshToken,
         return NULL;
     }
 
-    CPLDebug( "GOA2", "Refresh Token Response:\n%s", 
+    CPLDebug( "GOA2", "Refresh Token Response:\n%s",
               (const char *) psResult->pabyData );
 
 /* -------------------------------------------------------------------- */
@@ -336,12 +336,12 @@ char *GOA2GetAccessToken( const char *pszRefreshToken,
 
     CPLDebug("GOA2", "Access Token : '%s'", osAccessToken.c_str());
 
-    if (osAccessToken.size() == 0) 
+    if (osAccessToken.size() == 0)
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to identify an access token in the OAuth2 response.");
         return NULL;
     }
-    else 
+    else
         return CPLStrdup(osAccessToken);
 }
diff --git a/port/cpl_hash_set.cpp b/port/cpl_hash_set.cpp
index 01c1804..01dd7ff 100644
--- a/port/cpl_hash_set.cpp
+++ b/port/cpl_hash_set.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_hash_set.cpp 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: cpl_hash_set.cpp 33724 2016-03-16 17:14:11Z goatbar $
  *
  * Name:     cpl_hash_set.cpp
  * Project:  CPL - Common Portability Library
@@ -15,16 +15,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
@@ -41,12 +41,15 @@ struct _CPLHashSet
     int                   nSize;
     int                   nIndiceAllocatedSize;
     int                   nAllocatedSize;
+    CPLList              *psRecyclingList;
+    int                   nRecyclingListSize;
+    int                   bRehash;
 #ifdef HASH_DEBUG
     int                   nCollisions;
 #endif
 };
 
-static const int anPrimes[] = 
+static const int anPrimes[] =
 { 53, 97, 193, 389, 769, 1543, 3079, 6151,
   12289, 24593, 49157, 98317, 196613, 393241,
   786433, 1572869, 3145739, 6291469, 12582917,
@@ -59,7 +62,7 @@ static const int anPrimes[] =
 
 /**
  * Creates a new hash set
- * 
+ *
  * The hash function must return a hash value for the elements to insert.
  * If fnHashFunc is NULL, CPLHashSetHashPointer will be used.
  *
@@ -89,6 +92,9 @@ CPLHashSet* CPLHashSetNew(CPLHashSetHashFunc fnHashFunc,
     set->tabList = (CPLList**) CPLCalloc(sizeof(CPLList*), 53);
     set->nIndiceAllocatedSize = 0;
     set->nAllocatedSize = 53;
+    set->psRecyclingList = NULL;
+    set->nRecyclingListSize = 0;
+    set->bRehash = FALSE;
 #ifdef HASH_DEBUG
     set->nCollisions = 0;
 #endif
@@ -102,7 +108,7 @@ CPLHashSet* CPLHashSetNew(CPLHashSetHashFunc fnHashFunc,
 
 /**
  * Returns the number of elements inserted in the hash set
- * 
+ *
  * Note: this is not the internal size of the hash set
  *
  * @param set the hash set
@@ -117,6 +123,68 @@ int CPLHashSetSize(const CPLHashSet* set)
 }
 
 /************************************************************************/
+/*                       CPLHashSetGetNewListElt()                      */
+/************************************************************************/
+
+static CPLList* CPLHashSetGetNewListElt(CPLHashSet* set)
+{
+    if( set->psRecyclingList )
+    {
+        CPLList* psRet = set->psRecyclingList;
+        psRet->pData = NULL;
+        set->nRecyclingListSize --;
+        set->psRecyclingList = psRet->psNext;
+        return psRet;
+    }
+    else
+        return (CPLList*) CPLMalloc(sizeof(CPLList));
+}
+
+/************************************************************************/
+/*                       CPLHashSetReturnListElt()                      */
+/************************************************************************/
+
+static void CPLHashSetReturnListElt(CPLHashSet* set, CPLList* psList)
+{
+    if( set->nRecyclingListSize < 128 )
+    {
+        psList->psNext = set->psRecyclingList;
+        set->psRecyclingList = psList;
+        set->nRecyclingListSize ++;
+    }
+    else
+    {
+        CPLFree(psList);
+    }
+}
+
+/************************************************************************/
+/*                   CPLHashSetClearInternal()                          */
+/************************************************************************/
+
+static void CPLHashSetClearInternal(CPLHashSet* set, int bFinalize)
+{
+    CPLAssert(set != NULL);
+    for(int i=0;i<set->nAllocatedSize;i++)
+    {
+        CPLList* cur = set->tabList[i];
+        while(cur)
+        {
+            if (set->fnFreeEltFunc)
+                set->fnFreeEltFunc(cur->pData);
+            CPLList* psNext = cur->psNext;
+            if( bFinalize )
+                CPLFree(cur);
+            else
+                CPLHashSetReturnListElt(set, cur);
+            cur = psNext;
+        }
+        set->tabList[i] = NULL;
+    }
+    set->bRehash = FALSE;
+}
+
+/************************************************************************/
 /*                        CPLHashSetDestroy()                           */
 /************************************************************************/
 
@@ -125,31 +193,45 @@ int CPLHashSetSize(const CPLHashSet* set)
  *
  * This function also frees the elements if a free function was
  * provided at the creation of the hash set.
- * 
+ *
  * @param set the hash set
  */
 
 void CPLHashSetDestroy(CPLHashSet* set)
 {
-    CPLAssert(set != NULL);
-    for(int i=0;i<set->nAllocatedSize;i++)
-    {
-        if (set->fnFreeEltFunc)
-        {
-            CPLList* cur = set->tabList[i];
-            while(cur)
-            {
-                set->fnFreeEltFunc(cur->pData);
-                cur = cur->psNext;
-            }
-        }
-        CPLListDestroy(set->tabList[i]);
-    }
+    CPLHashSetClearInternal(set, TRUE);
     CPLFree(set->tabList);
+    CPLListDestroy(set->psRecyclingList);
     CPLFree(set);
 }
 
 /************************************************************************/
+/*                        CPLHashSetClear()                             */
+/************************************************************************/
+
+/**
+ * Clear all elements from a hash set.
+ *
+ * This function also frees the elements if a free function was
+ * provided at the creation of the hash set.
+ *
+ * @param set the hash set
+ * @since GDAL 2.1
+ */
+
+void CPLHashSetClear(CPLHashSet* set)
+{
+    CPLHashSetClearInternal(set, FALSE);
+    set->tabList = (CPLList**) CPLRealloc(set->tabList, sizeof(CPLList*) * 53);
+    set->nIndiceAllocatedSize = 0;
+    set->nAllocatedSize = 53;
+#ifdef HASH_DEBUG
+    set->nCollisions = 0;
+#endif
+    set->nSize = 0;
+}
+
+/************************************************************************/
 /*                       CPLHashSetForeach()                            */
 /************************************************************************/
 
@@ -164,7 +246,7 @@ void CPLHashSetDestroy(CPLHashSet* set)
  *
  * Note : the structure of the hash set must *NOT* be modified during the
  * walk.
- * 
+ *
  * @param set the hash set.
  * @param fnIterFunc the function called on each element.
  * @param user_data the user data provided to the function.
@@ -213,14 +295,16 @@ static void CPLHashSetRehash(CPLHashSet* set)
             if (newTabList[nNewHashVal])
                 set->nCollisions ++;
 #endif
-            newTabList[nNewHashVal] = CPLListInsert(newTabList[nNewHashVal], cur->pData, 0);
-            cur = cur->psNext;
+            CPLList* psNext = cur->psNext;
+            cur->psNext = newTabList[nNewHashVal];
+            newTabList[nNewHashVal] = cur;
+            cur = psNext;
         }
-        CPLListDestroy(set->tabList[i]);
     }
     CPLFree(set->tabList);
     set->tabList = newTabList;
     set->nAllocatedSize = nNewAllocatedSize;
+    set->bRehash = FALSE;
 }
 
 
@@ -251,7 +335,7 @@ static void** CPLHashSetFindPtr(CPLHashSet* set, const void* elt)
  * If the element was already inserted in the hash set, the previous
  * element is replaced by the new element. If a free function was provided,
  * it is used to free the previously inserted element
- * 
+ *
  * @param set the hash set
  * @param elt the new element to insert in the hash set
  *
@@ -271,7 +355,8 @@ int CPLHashSetInsert(CPLHashSet* set, void* elt)
         return FALSE;
     }
 
-    if (set->nSize >= 2 * set->nAllocatedSize / 3)
+    if( set->nSize >= 2 * set->nAllocatedSize / 3 ||
+        (set->bRehash && set->nIndiceAllocatedSize > 0 && set->nSize <= set->nAllocatedSize / 2) )
     {
         set->nIndiceAllocatedSize++;
         CPLHashSetRehash(set);
@@ -282,7 +367,11 @@ int CPLHashSetInsert(CPLHashSet* set, void* elt)
     if (set->tabList[nHashVal])
         set->nCollisions ++;
 #endif
-    set->tabList[nHashVal] = CPLListInsert(set->tabList[nHashVal], (void*) elt, 0);
+
+    CPLList* new_elt = CPLHashSetGetNewListElt(set);
+    new_elt->pData = (void*) elt;
+    new_elt->psNext = set->tabList[nHashVal];
+    set->tabList[nHashVal] = new_elt;
     set->nSize++;
 
     return TRUE;
@@ -295,7 +384,7 @@ int CPLHashSetInsert(CPLHashSet* set, void* elt)
 /**
  * Returns the element found in the hash set corresponding to the element to look up
  * The element must not be modified.
- * 
+ *
  * @param set the hash set
  * @param elt the element to look up in the hash set
  *
@@ -313,28 +402,23 @@ void* CPLHashSetLookup(CPLHashSet* set, const void* elt)
 }
 
 /************************************************************************/
-/*                         CPLHashSetRemove()                           */
+/*                     CPLHashSetRemoveInternal()                       */
 /************************************************************************/
 
-/**
- * Removes an element from a hash set
- * 
- * @param set the hash set
- * @param elt the new element to remove from the hash set
- *
- * @return TRUE if the element was in the hash set
- */
-
-int CPLHashSetRemove(CPLHashSet* set, const void* elt)
+static
+int CPLHashSetRemoveInternal(CPLHashSet* set, const void* elt, int bDeferRehash)
 {
     CPLAssert(set != NULL);
     if (set->nIndiceAllocatedSize > 0 && set->nSize <= set->nAllocatedSize / 2)
     {
         set->nIndiceAllocatedSize--;
-        CPLHashSetRehash(set);
+        if( bDeferRehash )
+            set->bRehash = TRUE;
+        else
+            CPLHashSetRehash(set);
     }
 
-    int nHashVal = set->fnHashFunc(elt) % set->nAllocatedSize;
+    int nHashVal = static_cast<int>(set->fnHashFunc(elt) % set->nAllocatedSize);
     CPLList* cur = set->tabList[nHashVal];
     CPLList* prev = NULL;
     while(cur)
@@ -349,7 +433,7 @@ int CPLHashSetRemove(CPLHashSet* set, const void* elt)
             if (set->fnFreeEltFunc)
                 set->fnFreeEltFunc(cur->pData);
 
-            CPLFree(cur);
+            CPLHashSetReturnListElt(set, cur);
 #ifdef HASH_DEBUG
             if (set->tabList[nHashVal])
                 set->nCollisions --;
@@ -364,6 +448,45 @@ int CPLHashSetRemove(CPLHashSet* set, const void* elt)
     return FALSE;
 }
 
+/************************************************************************/
+/*                         CPLHashSetRemove()                           */
+/************************************************************************/
+
+/**
+ * Removes an element from a hash set
+ *
+ * @param set the hash set
+ * @param elt the new element to remove from the hash set
+ *
+ * @return TRUE if the element was in the hash set
+ */
+
+int CPLHashSetRemove(CPLHashSet* set, const void* elt)
+{
+    return CPLHashSetRemoveInternal(set, elt, FALSE);
+}
+
+/************************************************************************/
+/*                     CPLHashSetRemoveDeferRehash()                    */
+/************************************************************************/
+
+/**
+ * Removes an element from a hash set.
+ *
+ * This will defer potential rehashing of the set to later calls to
+ * CPLHashSetInsert() or CPLHashSetRemove().
+ *
+ * @param set the hash set
+ * @param elt the new element to remove from the hash set
+ *
+ * @return TRUE if the element was in the hash set
+ * @since GDAL 2.1
+ */
+
+int CPLHashSetRemoveDeferRehash(CPLHashSet* set, const void* elt)
+{
+    return CPLHashSetRemoveInternal(set, elt, TRUE);
+}
 
 /************************************************************************/
 /*                    CPLHashSetHashPointer()                           */
@@ -371,7 +494,7 @@ int CPLHashSetRemove(CPLHashSet* set, const void* elt)
 
 /**
  * Hash function for an arbitrary pointer
- * 
+ *
  * @param elt the arbitrary pointer to hash
  *
  * @return the hash value of the pointer
@@ -388,7 +511,7 @@ unsigned long CPLHashSetHashPointer(const void* elt)
 
 /**
  * Equality function for arbitrary pointers
- * 
+ *
  * @param elt1 the first arbitrary pointer to compare
  * @param elt2 the second arbitrary pointer to compare
  *
@@ -406,7 +529,7 @@ int CPLHashSetEqualPointer(const void* elt1, const void* elt2)
 
 /**
  * Hash function for a zero-terminated string
- * 
+ *
  * @param elt the string to hash. May be NULL.
  *
  * @return the hash value of the string
@@ -416,11 +539,11 @@ unsigned long CPLHashSetHashStr(const void *elt)
 {
     unsigned char* pszStr = (unsigned char*)elt;
     unsigned long hash = 0;
-    int c;
 
     if (pszStr == NULL)
         return 0;
 
+    int c = 0;
     while ((c = *pszStr++) != '\0')
         hash = c + (hash << 6) + (hash << 16) - hash;
 
@@ -433,7 +556,7 @@ unsigned long CPLHashSetHashStr(const void *elt)
 
 /**
  * Equality function for strings
- * 
+ *
  * @param elt1 the first string to compare. May be NULL.
  * @param elt2 the second string to compare. May be NULL.
  *
diff --git a/port/cpl_hash_set.h b/port/cpl_hash_set.h
index fad62fe..37b68d8 100644
--- a/port/cpl_hash_set.h
+++ b/port/cpl_hash_set.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_hash_set.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: cpl_hash_set.h 33666 2016-03-07 05:21:07Z goatbar $
  *
  * Name:     cpl_hash_set.h
  * Project:  CPL - Common Portability Library
@@ -15,21 +15,21 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _CPL_HASH_SET_H_INCLUDED
-#define _CPL_HASH_SET_H_INCLUDED
+#ifndef CPL_HASH_SET_H_INCLUDED
+#define CPL_HASH_SET_H_INCLUDED
 
 #include "cpl_port.h"
 
@@ -66,6 +66,8 @@ CPLHashSet CPL_DLL * CPLHashSetNew(CPLHashSetHashFunc fnHashFunc,
 
 void         CPL_DLL CPLHashSetDestroy(CPLHashSet* set);
 
+void         CPL_DLL CPLHashSetClear(CPLHashSet* set);
+
 int          CPL_DLL CPLHashSetSize(const CPLHashSet* set);
 
 void         CPL_DLL CPLHashSetForeach(CPLHashSet* set,
@@ -77,6 +79,7 @@ int          CPL_DLL CPLHashSetInsert(CPLHashSet* set, void* elt);
 void         CPL_DLL * CPLHashSetLookup(CPLHashSet* set, const void* elt);
 
 int          CPL_DLL CPLHashSetRemove(CPLHashSet* set, const void* elt);
+int          CPL_DLL CPLHashSetRemoveDeferRehash(CPLHashSet* set, const void* elt);
 
 unsigned long CPL_DLL CPLHashSetHashPointer(const void* elt);
 
@@ -88,5 +91,4 @@ int          CPL_DLL CPLHashSetEqualStr(const void* pszStr1, const void* pszStr2
 
 CPL_C_END
 
-#endif /* _CPL_HASH_SET_H_INCLUDED */
-
+#endif /* CPL_HASH_SET_H_INCLUDED */
diff --git a/port/cpl_http.cpp b/port/cpl_http.cpp
index 13dadf6..bc79823 100644
--- a/port/cpl_http.cpp
+++ b/port/cpl_http.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_http.cpp 29152 2015-05-04 11:45:44Z rouault $
+ * $Id: cpl_http.cpp 33646 2016-03-05 15:54:03Z goatbar $
  *
  * Project:  libcurl based HTTP client
  * Purpose:  libcurl based HTTP client
@@ -44,9 +44,9 @@ void CPLHTTPSetOptions(CURL *http_handle, char** papszOptions);
 
 #endif
 
-CPL_CVSID("$Id: cpl_http.cpp 29152 2015-05-04 11:45:44Z rouault $");
+CPL_CVSID("$Id: cpl_http.cpp 33646 2016-03-05 15:54:03Z goatbar $");
 
-// list of named persistent http sessions 
+// list of named persistent http sessions
 
 #ifdef HAVE_CURL
 static std::map<CPLString,CURL*>* poSessionMap = NULL;
@@ -61,14 +61,14 @@ static CPLMutex *hSessionMapMutex = NULL;
 /************************************************************************/
 
 #ifdef HAVE_CURL
-static size_t 
+static size_t
 CPLWriteFct(void *buffer, size_t size, size_t nmemb, void *reqInfo)
 
 {
     CPLHTTPResult *psResult = (CPLHTTPResult *) reqInfo;
-    int  nNewSize;
 
-    nNewSize = psResult->nDataLen + nmemb*size + 1;
+    int nBytesToWrite = static_cast<int>(nmemb)*static_cast<int>(size);
+    int nNewSize = psResult->nDataLen + nBytesToWrite + 1;
     if( nNewSize > psResult->nDataAlloc )
     {
         psResult->nDataAlloc = (int) (nNewSize * 1.25 + 100);
@@ -86,10 +86,9 @@ CPLWriteFct(void *buffer, size_t size, size_t nmemb, void *reqInfo)
         psResult->pabyData = pabyNewData;
     }
 
-    memcpy( psResult->pabyData + psResult->nDataLen, buffer,
-            nmemb * size );
+    memcpy( psResult->pabyData + psResult->nDataLen, buffer, nBytesToWrite );
 
-    psResult->nDataLen += nmemb * size;
+    psResult->nDataLen += nBytesToWrite;
     psResult->pabyData[psResult->nDataLen] = 0;
 
     return nmemb;
@@ -103,13 +102,13 @@ static size_t CPLHdrWriteFct(void *buffer, size_t size, size_t nmemb, void *reqI
     CPLHTTPResult *psResult = (CPLHTTPResult *) reqInfo;
     // copy the buffer to a char* and initialize with zeros (zero terminate as well)
     char* pszHdr = (char*)CPLCalloc(nmemb + 1, size);
-    CPLPrintString(pszHdr, (char *)buffer, nmemb * size);
+    CPLPrintString(pszHdr, (char *)buffer, static_cast<int>(nmemb) * static_cast<int>(size));
     char *pszKey = NULL;
     const char *pszValue = CPLParseNameValue(pszHdr, &pszKey );
     psResult->papszHeaders = CSLSetNameValue(psResult->papszHeaders, pszKey, pszValue);
     CPLFree(pszHdr);
     CPLFree(pszKey);
-    return nmemb; 
+    return nmemb;
 }
 
 #endif /* def HAVE_CURL */
@@ -125,7 +124,13 @@ static size_t CPLHdrWriteFct(void *buffer, size_t size, size_t nmemb, void *reqI
  * @param papszOptions option list as a NULL-terminated array of strings. May be NULL.
  *                     The following options are handled :
  * <ul>
- * <li>TIMEOUT=val, where val is in seconds</li>
+ * <li>TIMEOUT=val, where val is in seconds. This is the maximum delay for the whole
+ *     request to complete before being aborted.</li>
+ * <li>LOW_SPEED_TIME=val, where val is in seconds. This is the maximum time where the
+ *      transfer speed should be below the LOW_SPEED_LIMIT (if not specified 1b/s),
+ *      before the transfer to be considered too slow and aborted. (GDAL >= 2.1)</li>
+ * <li>LOW_SPEED_LIMIT=val, where val is in bytes/second. See LOW_SPEED_TIME. Has only
+ *     effect if LOW_SPEED_TIME is specified too. (GDAL >= 2.1)</li>
  * <li>HEADERS=val, where val is an extra header to use when getting a web page.
  *                  For example "Accept: application/x-ogcwkt"
  * <li>HTTPAUTH=[BASIC/NTLM/GSSNEGOTIATE/ANY] to specify an authentication scheme to use.
@@ -145,22 +150,30 @@ static size_t CPLHdrWriteFct(void *buffer, size_t size, size_t nmemb, void *reqI
  *                 Default is 30. (GDAL >= 2.0)
  * </ul>
  *
- * Alternatively, if not defined in the papszOptions arguments, the PROXY,  
- * PROXYUSERPWD, PROXYAUTH, NETRC, MAX_RETRY and RETRY_DELAY values are searched in the configuration 
- * options named GDAL_HTTP_PROXY, GDAL_HTTP_PROXYUSERPWD, GDAL_PROXY_AUTH, 
+ * Alternatively, if not defined in the papszOptions arguments, the TIMEOUT,
+ * LOW_SPEED_TIME, LOW_SPEED_LIMIT, PROXY, PROXYUSERPWD, PROXYAUTH, NETRC,
+ * MAX_RETRY and RETRY_DELAY values are searched in the configuration
+ * options named GDAL_HTTP_TIMEOUT, GDAL_HTTP_LOW_SPEED_TIME, GDAL_HTTP_LOW_SPEED_LIMIT,
+ * GDAL_HTTP_PROXY, GDAL_HTTP_PROXYUSERPWD, GDAL_PROXY_AUTH,
  * GDAL_HTTP_NETRC, GDAL_HTTP_MAX_RETRY and GDAL_HTTP_RETRY_DELAY.
  *
- * @return a CPLHTTPResult* structure that must be freed by 
+ * @return a CPLHTTPResult* structure that must be freed by
  * CPLHTTPDestroyResult(), or NULL if libcurl support is disabled
  */
 CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
 
 {
-    if( strncmp(pszURL, "/vsimem/", strlen("/vsimem/")) == 0 &&
+    if( STARTS_WITH(pszURL, "/vsimem/") &&
         /* Disabled by default for potential security issues */
         CSLTestBoolean(CPLGetConfigOption("CPL_CURL_ENABLE_VSIMEM", "FALSE")) )
     {
         CPLString osURL(pszURL);
+        const char* pszCustomRequest = CSLFetchNameValue( papszOptions, "CUSTOMREQUEST" );
+        if( pszCustomRequest != NULL )
+        {
+            osURL += "&CUSTOMREQUEST=";
+            osURL += pszCustomRequest;
+        }
         const char* pszPost = CSLFetchNameValue( papszOptions, "POSTFIELDS" );
         if( pszPost != NULL ) /* Hack: we append post content to filename */
         {
@@ -179,26 +192,24 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
         }
         else if( nLength != 0 )
         {
-            psResult->nDataLen = (size_t)nLength;
+            psResult->nDataLen = static_cast<int>(nLength);
             psResult->pabyData = (GByte*) CPLMalloc((size_t)nLength + 1);
             memcpy(psResult->pabyData, pabyData, (size_t)nLength);
             psResult->pabyData[(size_t)nLength] = 0;
         }
 
         if( psResult->pabyData != NULL &&
-            strncmp((const char*)psResult->pabyData, "Content-Type: ",
-                    strlen("Content-Type: ")) == 0 )
-        {
+            STARTS_WITH((const char*)psResult->pabyData, "Content-Type: ") )        {
             const char* pszContentType = (const char*)psResult->pabyData + strlen("Content-type: ");
             const char* pszEOL = strchr(pszContentType, '\r');
             if( pszEOL )
                 pszEOL = strchr(pszContentType, '\n');
             if( pszEOL )
             {
-                int nLength = pszEOL - pszContentType;
-                psResult->pszContentType = (char*)CPLMalloc(nLength + 1);
-                memcpy(psResult->pszContentType, pszContentType, nLength);
-                psResult->pszContentType[nLength] = 0;
+                size_t nContentLength = pszEOL - pszContentType;
+                psResult->pszContentType = (char*)CPLMalloc(nContentLength + 1);
+                memcpy(psResult->pszContentType, pszContentType, nContentLength);
+                psResult->pszContentType[nContentLength] = 0;
             }
         }
 
@@ -284,7 +295,7 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
 /* -------------------------------------------------------------------- */
     char szCurlErrBuf[CURL_ERROR_SIZE+1];
     CPLHTTPResult *psResult;
-    struct curl_slist *headers=NULL; 
+    struct curl_slist *headers=NULL;
 
     const char* pszArobase = strchr(pszURL, '@');
     const char* pszSlash = strchr(pszURL, '/');
@@ -323,17 +334,17 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
     const char* pszNoBody = NULL;
     if ((pszNoBody = CSLFetchNameValue( papszOptions, "NO_BODY" )) != NULL)
     {
-        if (CSLTestBoolean(pszNoBody)) 
+        if (CSLTestBoolean(pszNoBody))
         {
             CPLDebug ("HTTP", "HEAD Request: %s", pszURL);
-            curl_easy_setopt(http_handle, CURLOPT_NOBODY, 1L);           
+            curl_easy_setopt(http_handle, CURLOPT_NOBODY, 1L);
         }
     }
 
     // capture response headers
     curl_easy_setopt(http_handle, CURLOPT_HEADERDATA, psResult);
     curl_easy_setopt(http_handle, CURLOPT_HEADERFUNCTION, CPLHdrWriteFct);
- 
+
     curl_easy_setopt(http_handle, CURLOPT_WRITEDATA, psResult );
     curl_easy_setopt(http_handle, CURLOPT_WRITEFUNCTION, CPLWriteFct );
 
@@ -341,23 +352,23 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
 
     curl_easy_setopt(http_handle, CURLOPT_ERRORBUFFER, szCurlErrBuf );
 
-    static int bHasCheckVersion = FALSE;
-    static int bSupportGZip = FALSE;
+    static bool bHasCheckVersion = false;
+    static bool bSupportGZip = false;
     if (!bHasCheckVersion)
     {
         bSupportGZip = strstr(curl_version(), "zlib/") != NULL;
-        bHasCheckVersion = TRUE;
+        bHasCheckVersion = true;
     }
-    int bGZipRequested = FALSE;
+    int bGZipRequested = false;
     if (bSupportGZip && CSLTestBoolean(CPLGetConfigOption("CPL_CURL_GZIP", "YES")))
     {
-        bGZipRequested = TRUE;
+        bGZipRequested = true;
         curl_easy_setopt(http_handle, CURLOPT_ENCODING, "gzip");
     }
 
 /* -------------------------------------------------------------------- */
-/*      If 502, 503 or 504 status code retry this HTTP call until max        */
-/*      retry has been rearched                                         */
+/*      If 502, 503 or 504 status code retry this HTTP call until max   */
+/*      retry has been reached                                          */
 /* -------------------------------------------------------------------- */
     const char *pszRetryDelay = CSLFetchNameValue( papszOptions, "RETRY_DELAY" );
     if( pszRetryDelay == NULL )
@@ -372,7 +383,7 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
 
     do
     {
-        bRequestRetry = FALSE;
+        bRequestRetry = false;
 
 /* -------------------------------------------------------------------- */
 /*      Execute the request, waiting for results.                       */
@@ -393,7 +404,7 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
 /* -------------------------------------------------------------------- */
         if( strlen(szCurlErrBuf) > 0 )
         {
-            int bSkipError = FALSE;
+            bool bSkipError = false;
 
             /* Some servers such as http://115.113.193.14/cgi-bin/world/qgis_mapserv.fcgi?VERSION=1.1.1&SERVICE=WMS&REQUEST=GetCapabilities */
             /* invalidly return Content-Length as the uncompressed size, with makes curl to wait for more data */
@@ -416,7 +427,7 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
                                  pszURL);
                     }
                     psResult->nStatus = 0;
-                    bSkipError = TRUE;
+                    bSkipError = true;
                 }
             }
             if (!bSkipError)
@@ -453,7 +464,7 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
                     psResult->nDataLen = 0;
                     psResult->nDataAlloc = 0;
 
-                    bRequestRetry = TRUE;
+                    bRequestRetry = true;
                 }
                 else
                 {
@@ -510,7 +521,7 @@ void CPLHTTPSetOptions(CURL *http_handle, char** papszOptions)
     else
     {
         CPLError( CE_Warning, CPLE_AppDefined,
-                  "Unsupported HTTPAUTH value '%s', ignored.", 
+                  "Unsupported HTTPAUTH value '%s', ignored.",
                   pszHttpAuth );
     }
 #else
@@ -567,7 +578,7 @@ void CPLHTTPSetOptions(CURL *http_handle, char** papszOptions)
     else
     {
         CPLError( CE_Warning, CPLE_AppDefined,
-                  "Unsupported PROXYAUTH value '%s', ignored.", 
+                  "Unsupported PROXYAUTH value '%s', ignored.",
                   pszProxyAuth );
     }
 #else
@@ -581,7 +592,7 @@ void CPLHTTPSetOptions(CURL *http_handle, char** papszOptions)
     /* Enable following redirections.  Requires libcurl 7.10.1 at least */
     curl_easy_setopt(http_handle, CURLOPT_FOLLOWLOCATION, 1 );
     curl_easy_setopt(http_handle, CURLOPT_MAXREDIRS, 10 );
-    
+
     /* Set timeout.*/
     const char *pszTimeout = CSLFetchNameValue( papszOptions, "TIMEOUT" );
     if (pszTimeout == NULL)
@@ -589,6 +600,20 @@ void CPLHTTPSetOptions(CURL *http_handle, char** papszOptions)
     if( pszTimeout != NULL )
         curl_easy_setopt(http_handle, CURLOPT_TIMEOUT, atoi(pszTimeout) );
 
+    /* Set low speed time and limit.*/
+    const char *pszLowSpeedTime = CSLFetchNameValue( papszOptions, "LOW_SPEED_TIME" );
+    if (pszLowSpeedTime == NULL)
+        pszLowSpeedTime = CPLGetConfigOption("GDAL_HTTP_LOW_SPEED_TIME", NULL);
+    if( pszLowSpeedTime != NULL )
+    {
+        curl_easy_setopt(http_handle, CURLOPT_LOW_SPEED_TIME, atoi(pszLowSpeedTime) );
+
+        const char *pszLowSpeedLimit = CSLFetchNameValue( papszOptions, "LOW_SPEED_LIMIT" );
+        if (pszLowSpeedLimit == NULL)
+            pszLowSpeedLimit = CPLGetConfigOption("GDAL_HTTP_LOW_SPEED_LIMIT", "1");
+        curl_easy_setopt(http_handle, CURLOPT_LOW_SPEED_LIMIT, atoi(pszLowSpeedLimit) );
+    }
+
     /* Disable some SSL verification */
     const char *pszUnsafeSSL = CSLFetchNameValue( papszOptions, "UNSAFESSL" );
     if (pszUnsafeSSL == NULL)
@@ -633,7 +658,7 @@ void CPLHTTPSetOptions(CURL *http_handle, char** papszOptions)
     {
         curl_easy_setopt(http_handle, CURLOPT_CUSTOMREQUEST, pszCustomRequest );
     }
-    
+
     const char* pszCookie = CSLFetchNameValue(papszOptions, "COOKIE");
     if (pszCookie == NULL)
         pszCookie = CPLGetConfigOption("GDAL_HTTP_COOKIE", NULL);
@@ -689,7 +714,7 @@ void CPLHTTPCleanup()
         }
     }
 
-    // not quite a safe sequence. 
+    // not quite a safe sequence.
     CPLDestroyMutex( hSessionMapMutex );
     hSessionMapMutex = NULL;
 #endif
@@ -714,13 +739,12 @@ void CPLHTTPDestroyResult( CPLHTTPResult *psResult )
         CPLFree( psResult->pszContentType );
         CSLDestroy( psResult->papszHeaders );
 
-        int i;
-        for(i=0;i<psResult->nMimePartCount;i++)
+        for(int i=0;i<psResult->nMimePartCount;i++)
         {
             CSLDestroy( psResult->pasMimePart[i].papszHeaders );
         }
         CPLFree(psResult->pasMimePart);
-        
+
         CPLFree( psResult );
     }
 }
@@ -730,7 +754,7 @@ void CPLHTTPDestroyResult( CPLHTTPResult *psResult )
 /************************************************************************/
 
 /**
- * \brief Parses a a MIME multipart message
+ * \brief Parses a MIME multipart message.
  *
  * This function will iterate over each part and put it in a separate
  * element of the pasMimePart array of the provided psResult structure.
@@ -763,8 +787,8 @@ int CPLHTTPParseMultipartMime( CPLHTTPResult *psResult )
     }
 
     CPLString osBoundary;
-    char **papszTokens = 
-        CSLTokenizeStringComplex( pszBound + 9, "\n ;", 
+    char **papszTokens =
+        CSLTokenizeStringComplex( pszBound + 9, "\n ;",
                                   TRUE, FALSE );
 
     if( CSLCount(papszTokens) == 0 || strlen(papszTokens[0]) == 0 )
@@ -774,7 +798,7 @@ int CPLHTTPParseMultipartMime( CPLHTTPResult *psResult )
         CSLDestroy( papszTokens );
         return FALSE;
     }
-    
+
     osBoundary = "--";
     osBoundary += papszTokens[0];
     CSLDestroy( papszTokens );
@@ -782,10 +806,9 @@ int CPLHTTPParseMultipartMime( CPLHTTPResult *psResult )
 /* -------------------------------------------------------------------- */
 /*      Find the start of the first chunk.                              */
 /* -------------------------------------------------------------------- */
-    char *pszNext;
-    pszNext = (char *) 
+    char *pszNext = (char *)
         strstr((const char *) psResult->pabyData,osBoundary.c_str());
-    
+
     if( pszNext == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined, "No parts found." );
@@ -803,7 +826,7 @@ int CPLHTTPParseMultipartMime( CPLHTTPResult *psResult )
 /* -------------------------------------------------------------------- */
 /*      Loop over parts...                                              */
 /* -------------------------------------------------------------------- */
-    while( TRUE )
+    while( true )
     {
         psResult->nMimePartCount++;
         psResult->pasMimePart = (CPLMimePart *)
@@ -829,18 +852,18 @@ int CPLHTTPParseMultipartMime( CPLHTTPResult *psResult )
             }
 
             *pszEOL = '\0';
-            int bRestoreAntislashR = FALSE;
+            bool bRestoreAntislashR = false;
             if (pszEOL - pszNext > 1 && pszEOL[-1] == '\r')
             {
-                bRestoreAntislashR = TRUE;
+                bRestoreAntislashR = true;
                 pszEOL[-1] = '\0';
             }
-            psPart->papszHeaders = 
+            psPart->papszHeaders =
                 CSLAddString( psPart->papszHeaders, pszNext );
             if (bRestoreAntislashR)
                 pszEOL[-1] = '\r';
             *pszEOL = '\n';
-            
+
             pszNext = pszEOL + 1;
         }
 
@@ -848,23 +871,23 @@ int CPLHTTPParseMultipartMime( CPLHTTPResult *psResult )
             pszNext++;
         if( *pszNext == '\n' )
             pszNext++;
-            
+
 /* -------------------------------------------------------------------- */
 /*      Work out the data block size.                                   */
 /* -------------------------------------------------------------------- */
         psPart->pabyData = (GByte *) pszNext;
 
-        int nBytesAvail = psResult->nDataLen - 
-            (pszNext - (const char *) psResult->pabyData);
+        int nBytesAvail = psResult->nDataLen -
+            static_cast<int>(pszNext - (const char *) psResult->pabyData);
 
         while( nBytesAvail > 0
-               && (*pszNext != '-' 
+               && (*pszNext != '-'
                    || strncmp(pszNext,osBoundary,strlen(osBoundary)) != 0) )
         {
             pszNext++;
             nBytesAvail--;
         }
-        
+
         if( nBytesAvail == 0 )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
@@ -872,10 +895,10 @@ int CPLHTTPParseMultipartMime( CPLHTTPResult *psResult )
             return FALSE;
         }
 
-        psPart->nDataLen = pszNext - (const char *) psPart->pabyData;
+        psPart->nDataLen = static_cast<int>(pszNext - (const char *) psPart->pabyData);
         pszNext += strlen(osBoundary);
 
-        if( strncmp(pszNext,"--",2) == 0 )
+        if( STARTS_WITH(pszNext, "--") )
         {
             break;
         }
diff --git a/port/cpl_http.h b/port/cpl_http.h
index 6747853..071ed11 100644
--- a/port/cpl_http.h
+++ b/port/cpl_http.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_http.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: cpl_http.h 33666 2016-03-07 05:21:07Z goatbar $
  *
  * Project:  Common Portability Library
  * Purpose:  Function wrapper for libcurl HTTP access.
@@ -46,36 +46,36 @@ CPL_C_START
 /*! Describe a part of a multipart message */
 typedef struct {
     /*! NULL terminated array of headers */ char **papszHeaders;
-    
+
     /*! Buffer with data of the part     */ GByte *pabyData;
     /*! Buffer length                    */ int    nDataLen;
 } CPLMimePart;
 
 /*! Describe the result of a CPLHTTPFetch() call */
 typedef struct {
-    /*! cURL error code : 0=success, non-zero if request failed */ 
+    /*! cURL error code : 0=success, non-zero if request failed */
     int     nStatus;
 
-    /*! Content-Type of the response */                                
+    /*! Content-Type of the response */
     char    *pszContentType;
 
-    /*! Error message from curl, or NULL */                            
+    /*! Error message from curl, or NULL */
     char    *pszErrBuf;
 
-    /*! Length of the pabyData buffer */                               
+    /*! Length of the pabyData buffer */
     int     nDataLen;
     int     nDataAlloc;
 
-    /*! Buffer with downloaded data */                                 
+    /*! Buffer with downloaded data */
     GByte   *pabyData;
 
     /*! Headers returned */
     char    **papszHeaders;
 
-    /*! Number of parts in a multipart message */                      
+    /*! Number of parts in a multipart message */
     int     nMimePartCount;
 
-    /*! Array of parts (resolved by CPLHTTPParseMultipartMime()) */    
+    /*! Array of parts (resolved by CPLHTTPParseMultipartMime()) */
     CPLMimePart *pasMimePart;
 
 } CPLHTTPResult;
diff --git a/port/cpl_list.cpp b/port/cpl_list.cpp
index 5059317..7859b4d 100644
--- a/port/cpl_list.cpp
+++ b/port/cpl_list.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_list.cpp 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: cpl_list.cpp 33671 2016-03-07 18:39:06Z goatbar $
  *
  * Name:     cpl_list.cpp
  * Project:  CPL - Common Portability Library
@@ -16,23 +16,23 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_list.h"
 #include "cpl_conv.h"
+#include "cpl_list.h"
 
-CPL_CVSID("$Id: cpl_list.cpp 27044 2014-03-16 23:41:27Z rouault $");
+CPL_CVSID("$Id: cpl_list.cpp 33671 2016-03-07 18:39:06Z goatbar $");
 
 /*=====================================================================
                     List manipulation functions.
@@ -45,7 +45,7 @@ CPL_CVSID("$Id: cpl_list.cpp 27044 2014-03-16 23:41:27Z rouault $");
 /**
  * Append an object list and return a pointer to the modified list.
  * If the input list is NULL, then a new list is created.
- * 
+ *
  * @param psList pointer to list head.
  * @param pData pointer to inserted data object. May be NULL.
  *
@@ -54,17 +54,19 @@ CPL_CVSID("$Id: cpl_list.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 CPLList *CPLListAppend( CPLList *psList, void *pData )
 {
-    CPLList *psLast;
-    
+    CPLList *psLast = NULL;
+
     /* Allocate room for the new object */
     if ( psList == NULL )
     {
-        psLast = psList = (CPLList *)CPLMalloc( sizeof(CPLList) );
+      psLast = static_cast<CPLList *>( CPLMalloc( sizeof(CPLList) ) );
+      psList = psLast;
     }
     else
     {
         psLast = CPLListGetLast( psList );
-        psLast = psLast->psNext = (CPLList *)CPLMalloc( sizeof(CPLList) );
+        psLast = psLast->psNext = static_cast<CPLList *>(
+            CPLMalloc( sizeof(CPLList) ) );
     }
 
     /* Append object to the end of list */
@@ -81,7 +83,7 @@ CPLList *CPLListAppend( CPLList *psList, void *pData )
 /**
  * Insert an object into list at specified position (zero based).
  * If the input list is NULL, then a new list is created.
- * 
+ *
  * @param psList pointer to list head.
  * @param pData pointer to inserted data object. May be NULL.
  * @param nPosition position number to insert an object.
@@ -91,26 +93,25 @@ CPLList *CPLListAppend( CPLList *psList, void *pData )
 
 CPLList *CPLListInsert( CPLList *psList, void *pData, int nPosition )
 {
-    CPLList *psCurrent;
-    int     i, nCount;
-    
     if ( nPosition < 0 )
         return psList;      /* Nothing to do!*/
 
-    nCount = CPLListCount( psList );
-
     if ( nPosition == 0)
     {
-        CPLList *psNew = (CPLList *)CPLMalloc( sizeof(CPLList) );
+        CPLList *psNew = static_cast<CPLList *>( CPLMalloc( sizeof(CPLList) ) );
         psNew->pData = pData;
         psNew->psNext = psList;
         psList = psNew;
+        return psList;
     }
-    else if ( nCount < nPosition )
+
+    const int nCount = CPLListCount( psList );
+
+    if ( nCount < nPosition )
     {
         /* Allocate room for the new object */
         CPLList* psLast = CPLListGetLast(psList);
-        for ( i = nCount; i <= nPosition - 1; i++ )
+        for ( int i = nCount; i <= nPosition - 1; i++ )
         {
             psLast = CPLListAppend( psLast, NULL );
             if (psList == NULL)
@@ -121,19 +122,20 @@ CPLList *CPLListInsert( CPLList *psList, void *pData, int nPosition )
         psLast = CPLListAppend( psLast, pData );
         if (psList == NULL)
             psList = psLast;
-    }
-    else
-    {
-        CPLList *psNew = (CPLList *)CPLMalloc( sizeof(CPLList) );
-        psNew->pData = pData;
 
-        psCurrent = psList;
-        for ( i = 0; i < nPosition - 1; i++ )
-            psCurrent = psCurrent->psNext;
-        psNew->psNext = psCurrent->psNext;
-        psCurrent->psNext = psNew;
+        /* coverity[leaked_storage] */
+        return psList;
     }
 
+    CPLList *psNew = static_cast<CPLList *>( CPLMalloc( sizeof(CPLList) ) );
+    psNew->pData = pData;
+
+    CPLList *psCurrent = psList;
+    for ( int i = 0; i < nPosition - 1; i++ )
+        psCurrent = psCurrent->psNext;
+    psNew->psNext = psCurrent->psNext;
+    psCurrent->psNext = psNew;
+
     return psList;
 }
 
@@ -143,19 +145,18 @@ CPLList *CPLListInsert( CPLList *psList, void *pData, int nPosition )
 
 /**
  * Return the pointer to last element in a list.
- * 
+ *
  * @param psList pointer to list head.
  *
  * @return pointer to last element in a list.
  */
 
-CPLList *CPLListGetLast( CPLList *psList )
+CPLList *CPLListGetLast( CPLList * const psList )
 {
-    CPLList *psCurrent = psList;
-
     if ( psList == NULL )
         return NULL;
 
+    CPLList * psCurrent = psList;
     while ( psCurrent->psNext )
         psCurrent = psCurrent->psNext;
 
@@ -168,7 +169,7 @@ CPLList *CPLListGetLast( CPLList *psList )
 
 /**
  * Return the pointer to the specified element in a list.
- * 
+ *
  * @param psList pointer to list head.
  * @param nPosition the index of the element in the list, 0 being the first element
  *
@@ -177,12 +178,11 @@ CPLList *CPLListGetLast( CPLList *psList )
 
 CPLList *CPLListGet( CPLList *psList, int nPosition )
 {
-    int     iItem = 0;
-    CPLList *psCurrent = psList;
-
     if ( nPosition < 0 )
         return NULL;
 
+    CPLList *psCurrent = psList;
+    int     iItem = 0;
     while ( iItem < nPosition && psCurrent )
     {
         psCurrent = psCurrent->psNext;
@@ -198,16 +198,16 @@ CPLList *CPLListGet( CPLList *psList, int nPosition )
 
 /**
  * Return the number of elements in a list.
- * 
+ *
  * @param psList pointer to list head.
  *
  * @return number of elements in a list.
  */
 
-int CPLListCount( CPLList *psList )
+int CPLListCount( const CPLList *psList )
 {
-    int     nItems = 0;
-    CPLList *psCurrent = psList;
+    int nItems = 0;
+    const CPLList *psCurrent = psList;
 
     while ( psCurrent )
     {
@@ -225,49 +225,44 @@ int CPLListCount( CPLList *psList )
 /**
  * Remove the element from the specified position (zero based) in a list. Data
  * object contained in removed element must be freed by the caller first.
- * 
+ *
  * @param psList pointer to list head.
- * @param nPosition position number to delet an element.
+ * @param nPosition position number to delete an element.
  *
  * @return pointer to the head of modified list.
  */
 
 CPLList *CPLListRemove( CPLList *psList, int nPosition )
 {
-    CPLList *psCurrent, *psRemoved;
-    int     i;
 
     if ( psList == NULL)
-    {
         return NULL;
-    }
-    else if ( nPosition < 0)
-    {
-        return psList;      /* Nothing to do!*/
-    }
-    else if ( nPosition == 0 )
+
+    if ( nPosition < 0)
+        return psList;      /* Nothing to do. */
+
+    if ( nPosition == 0 )
     {
-        psCurrent = psList->psNext;
+        CPLList *psCurrent = psList->psNext;
         CPLFree( psList );
         psList = psCurrent;
+        return psList;
     }
-    else
+
+    CPLList *psCurrent = psList;
+    for ( int i = 0; i < nPosition - 1; i++ )
     {
-        psCurrent = psList;
-        for ( i = 0; i < nPosition - 1; i++ )
-        {
-            psCurrent = psCurrent->psNext;
-            /* psCurrent == NULL if nPosition >= CPLListCount(psList) */
-            if (psCurrent == NULL)
-                return psList;
-        }
-        psRemoved = psCurrent->psNext;
-        /* psRemoved == NULL if nPosition >= CPLListCount(psList) */
-        if (psRemoved == NULL)
+        psCurrent = psCurrent->psNext;
+        /* psCurrent == NULL if nPosition >= CPLListCount(psList) */
+        if (psCurrent == NULL)
             return psList;
-        psCurrent->psNext = psRemoved->psNext;
-        CPLFree( psRemoved );
     }
+    CPLList *psRemoved = psCurrent->psNext;
+    /* psRemoved == NULL if nPosition >= CPLListCount(psList) */
+    if (psRemoved == NULL)
+        return psList;
+    psCurrent->psNext = psRemoved->psNext;
+    CPLFree( psRemoved );
 
     return psList;
 }
@@ -279,19 +274,18 @@ CPLList *CPLListRemove( CPLList *psList, int nPosition )
 /**
  * Destroy a list. Caller responsible for freeing data objects contained in
  * list elements.
- * 
+ *
  * @param psList pointer to list head.
  *
  */
 
 void CPLListDestroy( CPLList *psList )
 {
-    CPLList *psNext;
     CPLList *psCurrent = psList;
 
     while ( psCurrent )
     {
-        psNext = psCurrent->psNext;
+        CPLList * const psNext = psCurrent->psNext;
         CPLFree( psCurrent );
         psCurrent = psNext;
     }
@@ -303,18 +297,18 @@ void CPLListDestroy( CPLList *psList )
 
 /**
  * Return the pointer to next element in a list.
- * 
+ *
  * @param psElement pointer to list element.
  *
  * @return pointer to the list element preceded by the given element.
  */
 
-CPLList *CPLListGetNext( CPLList *psElement )
+CPLList *CPLListGetNext( const CPLList *psElement )
 {
     if ( psElement == NULL )
         return NULL;
-    else
-        return psElement->psNext;
+
+    return psElement->psNext;
 }
 
 /************************************************************************/
@@ -323,17 +317,16 @@ CPLList *CPLListGetNext( CPLList *psElement )
 
 /**
  * Return pointer to the data object contained in given list element.
- * 
+ *
  * @param psElement pointer to list element.
  *
  * @return pointer to the data object contained in given list element.
  */
 
-void *CPLListGetData( CPLList *psElement )
+void *CPLListGetData( const CPLList *psElement )
 {
     if ( psElement == NULL )
         return NULL;
-    else
-        return psElement->pData;
-}
 
+    return psElement->pData;
+}
diff --git a/port/cpl_list.h b/port/cpl_list.h
index be0f724..a6e64d8 100644
--- a/port/cpl_list.h
+++ b/port/cpl_list.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_list.h 26927 2014-02-11 15:54:59Z goatbar $
+ * $Id: cpl_list.h 33671 2016-03-07 18:39:06Z goatbar $
  *
  * Name:     cpl_list.h
  * Project:  CPL - Common Portability Library
@@ -15,21 +15,21 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _CPL_LIST_H_INCLUDED
-#define _CPL_LIST_H_INCLUDED
+#ifndef CPL_LIST_H_INCLUDED
+#define CPL_LIST_H_INCLUDED
 
 #include "cpl_port.h"
 
@@ -57,16 +57,16 @@ typedef struct _CPLList
     struct _CPLList    *psNext;
 } CPLList;
 
-CPLList CPL_DLL *CPLListAppend( CPLList *psList, void *pData );
-CPLList CPL_DLL *CPLListInsert( CPLList *psList, void *pData, int nPosition );
+CPLList CPL_DLL *CPLListAppend( CPLList *psList, void * pData );
+CPLList CPL_DLL *CPLListInsert( CPLList *psList, void * pData, int nPosition );
 CPLList CPL_DLL *CPLListGetLast( CPLList *psList );
-CPLList CPL_DLL *CPLListGet( CPLList *psList, int nPosition );
-int CPL_DLL CPLListCount( CPLList *psList );
+CPLList CPL_DLL *CPLListGet( CPLList * const psList, int nPosition );
+int CPL_DLL CPLListCount( const CPLList *psList );
 CPLList CPL_DLL *CPLListRemove( CPLList *psList, int nPosition );
 void CPL_DLL CPLListDestroy( CPLList *psList );
-CPLList CPL_DLL *CPLListGetNext( CPLList *psElement );
-void CPL_DLL *CPLListGetData( CPLList *psElement );
+CPLList CPL_DLL *CPLListGetNext( const CPLList *psElement );
+void CPL_DLL *CPLListGetData( const CPLList *psElement );
 
 CPL_C_END
 
-#endif /* _CPL_LIST_H_INCLUDED */
+#endif /* CPL_LIST_H_INCLUDED */
diff --git a/port/cpl_minixml.cpp b/port/cpl_minixml.cpp
index 63eb55a..8b15696 100644
--- a/port/cpl_minixml.cpp
+++ b/port/cpl_minixml.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_minixml.cpp 29087 2015-05-01 09:51:50Z rouault $
+ * $Id: cpl_minixml.cpp 33724 2016-03-16 17:14:11Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implementation of MiniXML Parser and handling.
@@ -15,26 +15,26 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
  * Independent Security Audit 2003/04/05 Andrey Kiselev:
  *   Completed audit of this module. Any documents may be parsed without
  *   buffer overflows and stack corruptions.
- * 
+ *
  * Security Audit 2003/03/28 warmerda:
- *   Completed security audit.  I believe that this module may be safely used 
- *   to parse, and serialize arbitrary documents provided by a potentially 
+ *   Completed security audit.  I believe that this module may be safely used
+ *   to parse, and serialize arbitrary documents provided by a potentially
  *   hostile source.
  *
  */
@@ -45,12 +45,12 @@
 #include "cpl_string.h"
 #include <ctype.h>
 
-CPL_CVSID("$Id: cpl_minixml.cpp 29087 2015-05-01 09:51:50Z rouault $");
+CPL_CVSID("$Id: cpl_minixml.cpp 33724 2016-03-16 17:14:11Z goatbar $");
 
 typedef enum {
     TNone,
-    TString, 
-    TOpen, 
+    TString,
+    TOpen,
     TClose,
     TEqual,
     TToken,
@@ -84,7 +84,7 @@ typedef struct {
     CPLXMLNode *psLastNode;
 } ParseContext;
 
-static CPLXMLNode *_CPLCreateXMLNode( CPLXMLNode *poParent, CPLXMLNodeType eType, 
+static CPLXMLNode *_CPLCreateXMLNode( CPLXMLNode *poParent, CPLXMLNodeType eType,
                                       const char *pszText );
 
 /************************************************************************/
@@ -94,15 +94,13 @@ static CPLXMLNode *_CPLCreateXMLNode( CPLXMLNode *poParent, CPLXMLNodeType eType
 static CPL_INLINE char ReadChar( ParseContext *psContext )
 
 {
-    char        chReturn;
-
-    chReturn = psContext->pszInput[psContext->nInputOffset++];
+    const char chReturn = psContext->pszInput[psContext->nInputOffset++];
 
     if( chReturn == '\0' )
         psContext->nInputOffset--;
     else if( chReturn == 10 )
         psContext->nInputLine++;
-    
+
     return chReturn;
 }
 
@@ -114,26 +112,22 @@ static CPL_INLINE void UnreadChar( ParseContext *psContext, char chToUnread )
 
 {
     if( chToUnread == '\0' )
-    {
-        /* do nothing */
-    }
-    else
-    {
-        CPLAssert( chToUnread 
-                   == psContext->pszInput[psContext->nInputOffset-1] );
+        return;
 
-        psContext->nInputOffset--;
+    CPLAssert( chToUnread
+               == psContext->pszInput[psContext->nInputOffset-1] );
 
-        if( chToUnread == 10 )
-            psContext->nInputLine--;
-    }
+    psContext->nInputOffset--;
+
+    if( chToUnread == 10 )
+        psContext->nInputLine--;
 }
 
 /************************************************************************/
 /*                           ReallocToken()                             */
 /************************************************************************/
 
-static int ReallocToken( ParseContext *psContext )
+static bool ReallocToken( ParseContext *psContext )
 {
     if (psContext->nTokenMaxSize > INT_MAX / 2)
     {
@@ -141,11 +135,11 @@ static int ReallocToken( ParseContext *psContext )
                  "Out of memory allocating %d*2 bytes", (int)psContext->nTokenMaxSize);
         VSIFree(psContext->pszToken);
         psContext->pszToken = NULL;
-        return FALSE;
+        return false;
     }
 
     psContext->nTokenMaxSize *= 2;
-    char* pszToken = (char *) 
+    char* pszToken = (char *)
         VSIRealloc(psContext->pszToken,psContext->nTokenMaxSize);
     if (pszToken == NULL)
     {
@@ -153,28 +147,28 @@ static int ReallocToken( ParseContext *psContext )
                  "Out of memory allocating %d bytes", (int)psContext->nTokenMaxSize);
         VSIFree(psContext->pszToken);
         psContext->pszToken = NULL;
-        return FALSE;
+        return false;
     }
     psContext->pszToken = pszToken;
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                             AddToToken()                             */
 /************************************************************************/
 
-static CPL_INLINE int _AddToToken( ParseContext *psContext, char chNewChar )
+static CPL_INLINE bool _AddToToken( ParseContext *psContext, char chNewChar )
 
 {
     if( psContext->nTokenSize >= psContext->nTokenMaxSize - 2 )
     {
         if (!ReallocToken(psContext))
-            return FALSE;
+            return false;
     }
 
     psContext->pszToken[psContext->nTokenSize++] = chNewChar;
     psContext->pszToken[psContext->nTokenSize] = '\0';
-    return TRUE;
+    return true;
 }
 
 #define AddToToken(psContext, chNewChar) if (!_AddToToken(psContext, chNewChar)) goto fail;
@@ -186,20 +180,18 @@ static CPL_INLINE int _AddToToken( ParseContext *psContext, char chNewChar )
 static XMLTokenType ReadToken( ParseContext *psContext )
 
 {
-    char        chNext;
-
     psContext->nTokenSize = 0;
     psContext->pszToken[0] = '\0';
-    
-    chNext = ReadChar( psContext );
+
+    char chNext = ReadChar( psContext );
     while( isspace((unsigned char)chNext) )
         chNext = ReadChar( psContext );
 
 /* -------------------------------------------------------------------- */
 /*      Handle comments.                                                */
 /* -------------------------------------------------------------------- */
-    if( chNext == '<' 
-        && EQUALN(psContext->pszInput+psContext->nInputOffset,"!--",3) )
+    if( chNext == '<'
+        && STARTS_WITH_CI(psContext->pszInput+psContext->nInputOffset, "!--") )
     {
         psContext->eTokenType = TComment;
 
@@ -208,7 +200,7 @@ static XMLTokenType ReadToken( ParseContext *psContext )
         ReadChar(psContext);
         ReadChar(psContext);
 
-        while( !EQUALN(psContext->pszInput+psContext->nInputOffset,"-->",3)
+        while( !STARTS_WITH_CI(psContext->pszInput+psContext->nInputOffset, "-->")
                && (chNext = ReadChar(psContext)) != '\0' )
             AddToToken( psContext, chNext );
 
@@ -220,25 +212,25 @@ static XMLTokenType ReadToken( ParseContext *psContext )
 /* -------------------------------------------------------------------- */
 /*      Handle DOCTYPE.                                                 */
 /* -------------------------------------------------------------------- */
-    else if( chNext == '<' 
-          && EQUALN(psContext->pszInput+psContext->nInputOffset,"!DOCTYPE",8) )
+    else if( chNext == '<'
+          && STARTS_WITH_CI(psContext->pszInput+psContext->nInputOffset, "!DOCTYPE") )
     {
-        int   bInQuotes = FALSE;
+        bool bInQuotes = false;
         psContext->eTokenType = TLiteral;
-        
+
         AddToToken( psContext, '<' );
-        do { 
+        do {
             chNext = ReadChar(psContext);
             if( chNext == '\0' )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "Parse error in DOCTYPE on or before line %d, "
-                          "reached end of file without '>'.", 
+                          "reached end of file without '>'.",
                           psContext->nInputLine );
-                
+
                 break;
             }
-            
+
             /* The markup declaration block within a DOCTYPE tag consists of:
              * - a left square bracket [
              * - a list of declarations
@@ -258,13 +250,13 @@ static XMLTokenType ReadToken( ParseContext *psContext )
                     AddToToken( psContext, chNext );
                 }
                 while( chNext != '\0'
-                    && !EQUALN(psContext->pszInput+psContext->nInputOffset,"]>", 2) );
-                    
+                    && !STARTS_WITH_CI(psContext->pszInput+psContext->nInputOffset, "]>") );
+
                 if (chNext == '\0')
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined, 
+                    CPLError( CE_Failure, CPLE_AppDefined,
                           "Parse error in DOCTYPE on or before line %d, "
-                          "reached end of file without ']'.", 
+                          "reached end of file without ']'.",
                           psContext->nInputLine );
                     break;
                 }
@@ -290,13 +282,13 @@ static XMLTokenType ReadToken( ParseContext *psContext )
             }
 
             AddToToken( psContext, chNext );
-        } while( TRUE );
+        } while( true );
     }
 /* -------------------------------------------------------------------- */
 /*      Handle CDATA.                                                   */
 /* -------------------------------------------------------------------- */
-    else if( chNext == '<' 
-          && EQUALN(psContext->pszInput+psContext->nInputOffset,"![CDATA[",8) )
+    else if( chNext == '<'
+          && STARTS_WITH_CI(psContext->pszInput+psContext->nInputOffset, "![CDATA[") )
     {
         psContext->eTokenType = TString;
 
@@ -310,7 +302,7 @@ static XMLTokenType ReadToken( ParseContext *psContext )
         ReadChar( psContext );
         ReadChar( psContext );
 
-        while( !EQUALN(psContext->pszInput+psContext->nInputOffset,"]]>",3)
+        while( !STARTS_WITH_CI(psContext->pszInput+psContext->nInputOffset, "]]>")
                && (chNext = ReadChar(psContext)) != '\0' )
             AddToToken( psContext, chNext );
 
@@ -343,7 +335,7 @@ static XMLTokenType ReadToken( ParseContext *psContext )
 /* -------------------------------------------------------------------- */
 /*      Handle the /> token terminator.                                 */
 /* -------------------------------------------------------------------- */
-    else if( chNext == '/' && psContext->bInElement 
+    else if( chNext == '/' && psContext->bInElement
              && psContext->pszInput[psContext->nInputOffset] == '>' )
     {
         chNext = ReadChar( psContext );
@@ -355,11 +347,11 @@ static XMLTokenType ReadToken( ParseContext *psContext )
 /* -------------------------------------------------------------------- */
 /*      Handle the ?> token terminator.                                 */
 /* -------------------------------------------------------------------- */
-    else if( chNext == '?' && psContext->bInElement 
+    else if( chNext == '?' && psContext->bInElement
              && psContext->pszInput[psContext->nInputOffset] == '>' )
     {
         chNext = ReadChar( psContext );
-        
+
         CPLAssert( chNext == '>' );
 
         psContext->eTokenType = TQuestionClose;
@@ -373,23 +365,23 @@ static XMLTokenType ReadToken( ParseContext *psContext )
     {
         psContext->eTokenType = TString;
 
-        while( (chNext = ReadChar(psContext)) != '"' 
+        while( (chNext = ReadChar(psContext)) != '"'
                && chNext != '\0' )
             AddToToken( psContext, chNext );
-        
+
         if( chNext != '"' )
         {
             psContext->eTokenType = TNone;
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Parse error on line %d, reached EOF before closing quote.", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                  "Parse error on line %d, reached EOF before closing quote.",
                       psContext->nInputLine );
         }
 
         /* Do we need to unescape it? */
         if( strchr(psContext->pszToken,'&') != NULL )
         {
-            int  nLength;
-            char *pszUnescaped = CPLUnescapeString( psContext->pszToken, 
+            int nLength = 0;
+            char *pszUnescaped = CPLUnescapeString( psContext->pszToken,
                                                     &nLength, CPLES_XML );
             strcpy( psContext->pszToken, pszUnescaped );
             CPLFree( pszUnescaped );
@@ -401,23 +393,23 @@ static XMLTokenType ReadToken( ParseContext *psContext )
     {
         psContext->eTokenType = TString;
 
-        while( (chNext = ReadChar(psContext)) != '\'' 
+        while( (chNext = ReadChar(psContext)) != '\''
                && chNext != '\0' )
             AddToToken( psContext, chNext );
-        
+
         if( chNext != '\'' )
         {
             psContext->eTokenType = TNone;
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Parse error on line %d, reached EOF before closing quote.", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                  "Parse error on line %d, reached EOF before closing quote.",
                       psContext->nInputLine );
         }
 
         /* Do we need to unescape it? */
         if( strchr(psContext->pszToken,'&') != NULL )
         {
-            int  nLength;
-            char *pszUnescaped = CPLUnescapeString( psContext->pszToken, 
+            int nLength = 0;
+            char *pszUnescaped = CPLUnescapeString( psContext->pszToken,
                                                     &nLength, CPLES_XML );
             strcpy( psContext->pszToken, pszUnescaped );
             CPLFree( pszUnescaped );
@@ -434,7 +426,7 @@ static XMLTokenType ReadToken( ParseContext *psContext )
         psContext->eTokenType = TString;
 
         AddToToken( psContext, chNext );
-        while( (chNext = ReadChar(psContext)) != '<' 
+        while( (chNext = ReadChar(psContext)) != '<'
                && chNext != '\0' )
             AddToToken( psContext, chNext );
         UnreadChar( psContext, chNext );
@@ -442,15 +434,15 @@ static XMLTokenType ReadToken( ParseContext *psContext )
         /* Do we need to unescape it? */
         if( strchr(psContext->pszToken,'&') != NULL )
         {
-            int  nLength;
-            char *pszUnescaped = CPLUnescapeString( psContext->pszToken, 
+            int nLength = 0;
+            char *pszUnescaped = CPLUnescapeString( psContext->pszToken,
                                                     &nLength, CPLES_XML );
             strcpy( psContext->pszToken, pszUnescaped );
             CPLFree( pszUnescaped );
             psContext->nTokenSize = strlen(psContext->pszToken );
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Collect a regular token terminated by white space, or           */
 /*      special character(s) like an equal sign.                        */
@@ -462,7 +454,7 @@ static XMLTokenType ReadToken( ParseContext *psContext )
         /* add the first character to the token regardless of what it is */
         AddToToken( psContext, chNext );
 
-        for( chNext = ReadChar(psContext); 
+        for( chNext = ReadChar(psContext);
              (chNext >= 'A' && chNext <= 'Z')
                  || (chNext >= 'a' && chNext <= 'z')
                  || chNext == '-'
@@ -470,14 +462,14 @@ static XMLTokenType ReadToken( ParseContext *psContext )
                  || chNext == '.'
                  || chNext == ':'
                  || (chNext >= '0' && chNext <= '9');
-             chNext = ReadChar(psContext) ) 
+             chNext = ReadChar(psContext) )
         {
             AddToToken( psContext, chNext );
         }
 
         UnreadChar(psContext, chNext);
     }
-    
+
     return psContext->eTokenType;
 
 fail:
@@ -489,23 +481,24 @@ fail:
 /*                              PushNode()                              */
 /************************************************************************/
 
-static int PushNode( ParseContext *psContext, CPLXMLNode *psNode )
+static bool PushNode( ParseContext *psContext, CPLXMLNode *psNode )
 
 {
     if( psContext->nStackMaxSize <= psContext->nStackSize )
     {
-        psContext->nStackMaxSize += 10;
-
-        if (psContext->nStackMaxSize >= (int)(INT_MAX / sizeof(StackContext)))
+        /* Somewhat arbitrary number... */
+        if (psContext->nStackMaxSize >= 10000)
         {
-            CPLError(CE_Failure, CPLE_OutOfMemory,
-                 "Out of memory allocating %d*%d bytes", (int)sizeof(StackContext), psContext->nStackMaxSize);
+            CPLError(CE_Failure, CPLE_NotSupported,
+                 "XML element depth beyond 10000. Giving up");
             VSIFree(psContext->papsStack);
             psContext->papsStack = NULL;
-            return FALSE;
+            return false;
         }
+        psContext->nStackMaxSize += 10;
+
         StackContext* papsStack;
-        papsStack = (StackContext *)VSIRealloc(psContext->papsStack, 
+        papsStack = (StackContext *)VSIRealloc(psContext->papsStack,
                     sizeof(StackContext) * psContext->nStackMaxSize);
         if (papsStack == NULL)
         {
@@ -513,17 +506,22 @@ static int PushNode( ParseContext *psContext, CPLXMLNode *psNode )
                  "Out of memory allocating %d bytes", (int)(sizeof(StackContext) * psContext->nStackMaxSize));
             VSIFree(psContext->papsStack);
             psContext->papsStack = NULL;
-            return FALSE;
+            return false;
         }
         psContext->papsStack = papsStack;
     }
+#ifdef DEBUG
+    // To make Coverity happy, but cannot happen
+    if( psContext->papsStack == NULL )
+        return false;
+#endif
 
     psContext->papsStack[psContext->nStackSize].psFirstNode = psNode;
     psContext->papsStack[psContext->nStackSize].psLastChild = NULL;
     psContext->nStackSize ++;
-    return TRUE;
+    return true;
 }
-    
+
 /************************************************************************/
 /*                             AttachNode()                             */
 /*                                                                      */
@@ -545,14 +543,16 @@ static void AttachNode( ParseContext *psContext, CPLXMLNode *psNode )
         psContext->psLastNode->psNext = psNode;
         psContext->psLastNode = psNode;
     }
-    else if( psContext->papsStack[psContext->nStackSize-1].psFirstNode->psChild == NULL )
-    {
-        psContext->papsStack[psContext->nStackSize-1].psFirstNode->psChild = psNode;
-        psContext->papsStack[psContext->nStackSize-1].psLastChild = psNode;
-    }
     else
     {
-        psContext->papsStack[psContext->nStackSize-1].psLastChild->psNext = psNode;
+        if( psContext->papsStack[psContext->nStackSize-1].psFirstNode->psChild == NULL )
+        {
+            psContext->papsStack[psContext->nStackSize-1].psFirstNode->psChild = psNode;
+        }
+        else
+        {
+            psContext->papsStack[psContext->nStackSize-1].psLastChild->psNext = psNode;
+        }
         psContext->papsStack[psContext->nStackSize-1].psLastChild = psNode;
     }
 }
@@ -564,36 +564,34 @@ static void AttachNode( ParseContext *psContext, CPLXMLNode *psNode )
 /**
  * \brief Parse an XML string into tree form.
  *
- * The passed document is parsed into a CPLXMLNode tree representation. 
+ * The passed document is parsed into a CPLXMLNode tree representation.
  * If the document is not well formed XML then NULL is returned, and errors
  * are reported via CPLError().  No validation beyond wellformedness is
  * done.  The CPLParseXMLFile() convenience function can be used to parse
- * from a file. 
+ * from a file.
  *
- * The returned document tree is is owned by the caller and should be freed
+ * The returned document tree is owned by the caller and should be freed
  * with CPLDestroyXMLNode() when no longer needed.
  *
- * If the document has more than one "root level" element then those after the 
+ * If the document has more than one "root level" element then those after the
  * first will be attached to the first as siblings (via the psNext pointers)
  * even though there is no common parent.  A document with no XML structure
- * (no angle brackets for instance) would be considered well formed, and 
- * returned as a single CXT_Text node.  
- * 
- * @param pszString the document to parse. 
+ * (no angle brackets for instance) would be considered well formed, and
+ * returned as a single CXT_Text node.
  *
- * @return parsed tree or NULL on error. 
+ * @param pszString the document to parse.
+ *
+ * @return parsed tree or NULL on error.
  */
 
 CPLXMLNode *CPLParseXMLString( const char *pszString )
 
 {
-    ParseContext sContext;
-
     CPLErrorReset();
 
     if( pszString == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "CPLParseXMLString() called with NULL pointer." );
         return NULL;
     }
@@ -616,6 +614,7 @@ CPLXMLNode *CPLParseXMLString( const char *pszString )
 /* -------------------------------------------------------------------- */
 /*      Initialize parse context.                                       */
 /* -------------------------------------------------------------------- */
+    ParseContext sContext;
     sContext.pszInput = pszString;
     sContext.nInputOffset = 0;
     sContext.nInputLine = 0;
@@ -642,16 +641,15 @@ CPLXMLNode *CPLParseXMLString( const char *pszString )
 /* -------------------------------------------------------------------- */
         if( sContext.eTokenType == TOpen )
         {
-            CPLXMLNode *psElement;
-
             if( ReadToken(&sContext) != TToken )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "Line %d: Didn't find element token after open angle bracket.",
                           sContext.nInputLine );
                 break;
             }
 
+            CPLXMLNode *psElement;
             if( sContext.pszToken[0] != '/' )
             {
                 psElement = _CPLCreateXMLNode( NULL, CXT_Element,
@@ -661,17 +659,34 @@ CPLXMLNode *CPLParseXMLString( const char *pszString )
                 if (!PushNode( &sContext, psElement ))
                     break;
             }
-            else 
+            else
             {
                 if( sContext.nStackSize == 0
                     || !EQUAL(sContext.pszToken+1,
                          sContext.papsStack[sContext.nStackSize-1].psFirstNode->pszValue) )
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined, 
-                              "Line %d: <%.500s> doesn't have matching <%.500s>.",
-                              sContext.nInputLine,
-                              sContext.pszToken, sContext.pszToken+1 );
-                    break;
+#ifdef DEBUG
+                    /* Makes life of fuzzers easier if we accept somewhat corrupted XML */
+                    /* like <foo> ... </not_foo> */
+                    if( CPLTestBool(CPLGetConfigOption("CPL_MINIXML_RELAXED", "FALSE")) )
+                    {
+                        CPLError( CE_Warning, CPLE_AppDefined,
+                                "Line %d: <%.500s> doesn't have matching <%.500s>.",
+                                sContext.nInputLine,
+                                sContext.pszToken, sContext.pszToken+1 );
+                        if( sContext.nStackSize == 0 )
+                            break;
+                        goto end_processing_close;
+                    }
+                    else
+#endif
+                    {
+                        CPLError( CE_Failure, CPLE_AppDefined,
+                                "Line %d: <%.500s> doesn't have matching <%.500s>.",
+                                sContext.nInputLine,
+                                sContext.pszToken, sContext.pszToken+1 );
+                        break;
+                    }
                 }
                 else
                 {
@@ -688,10 +703,12 @@ CPLXMLNode *CPLParseXMLString( const char *pszString )
                                 sContext.papsStack[sContext.nStackSize-1].psFirstNode->pszValue,
                                 sContext.pszToken );
                     }
-
+#ifdef DEBUG
+end_processing_close:
+#endif
                     if( ReadToken(&sContext) != TClose )
                     {
-                        CPLError( CE_Failure, CPLE_AppDefined, 
+                        CPLError( CE_Failure, CPLE_AppDefined,
                                   "Line %d: Missing close angle bracket after <%.500s.",
                                   sContext.nInputLine,
                                   sContext.pszToken );
@@ -709,15 +726,31 @@ CPLXMLNode *CPLParseXMLString( const char *pszString )
 /* -------------------------------------------------------------------- */
         else if( sContext.eTokenType == TToken )
         {
-            CPLXMLNode *psAttr;
-
-            psAttr = _CPLCreateXMLNode(NULL, CXT_Attribute, sContext.pszToken);
+            CPLXMLNode *psAttr = _CPLCreateXMLNode(NULL, CXT_Attribute, sContext.pszToken);
             if (!psAttr) break;
             AttachNode( &sContext, psAttr );
-            
+
             if( ReadToken(&sContext) != TEqual )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                // Parse stuff like <?valbuddy_schematron ../wmtsSimpleGetCapabilities.sch?>
+                if( sContext.nStackSize > 0 &&
+                    sContext.papsStack[sContext.nStackSize-1].psFirstNode->pszValue[0] == '?' &&
+                    sContext.papsStack[sContext.nStackSize-1].psFirstNode->psChild == psAttr )
+                {
+                    CPLDestroyXMLNode(psAttr);
+                    sContext.papsStack[sContext.nStackSize-1].psFirstNode->psChild = NULL;
+                    sContext.papsStack[sContext.nStackSize-1].psLastChild = NULL;
+
+                    sContext.papsStack[sContext.nStackSize-1].psFirstNode->pszValue = (char*)CPLRealloc(
+                        sContext.papsStack[sContext.nStackSize-1].psFirstNode->pszValue,
+                        strlen(sContext.papsStack[sContext.nStackSize-1].psFirstNode->pszValue) + 1 + strlen(sContext.pszToken) + 1);
+                    strcat(sContext.papsStack[sContext.nStackSize-1].psFirstNode->pszValue, " ");
+                    strcat(sContext.papsStack[sContext.nStackSize-1].psFirstNode->pszValue, sContext.pszToken);
+
+                    continue;
+                }
+
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "Line %d: Didn't find expected '=' for value of attribute '%.500s'.",
                           sContext.nInputLine, psAttr->pszValue );
                 break;
@@ -735,7 +768,7 @@ CPLXMLNode *CPLParseXMLString( const char *pszString )
             }
             else if( sContext.eTokenType != TString )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "Line %d: Didn't find expected attribute value.",
                           sContext.nInputLine );
                 break;
@@ -751,7 +784,7 @@ CPLXMLNode *CPLParseXMLString( const char *pszString )
         {
             if( sContext.nStackSize == 0 )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "Line %d: Found unbalanced '>'.",
                           sContext.nInputLine );
                 break;
@@ -766,7 +799,7 @@ CPLXMLNode *CPLParseXMLString( const char *pszString )
         {
             if( sContext.nStackSize == 0 )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "Line %d: Found unbalanced '/>'.",
                           sContext.nInputLine );
                 break;
@@ -783,14 +816,14 @@ CPLXMLNode *CPLParseXMLString( const char *pszString )
         {
             if( sContext.nStackSize == 0 )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "Line %d: Found unbalanced '?>'.",
                           sContext.nInputLine );
                 break;
             }
             else if( sContext.papsStack[sContext.nStackSize-1].psFirstNode->pszValue[0] != '?' )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "Line %d: Found '?>' without matching '<?'.",
                           sContext.nInputLine );
                 break;
@@ -806,9 +839,7 @@ CPLXMLNode *CPLParseXMLString( const char *pszString )
 /* -------------------------------------------------------------------- */
         else if( sContext.eTokenType == TComment )
         {
-            CPLXMLNode *psValue;
-
-            psValue = _CPLCreateXMLNode(NULL, CXT_Comment, sContext.pszToken);
+            CPLXMLNode *psValue = _CPLCreateXMLNode(NULL, CXT_Comment, sContext.pszToken);
             if (!psValue) break;
             AttachNode( &sContext, psValue );
         }
@@ -818,9 +849,7 @@ CPLXMLNode *CPLParseXMLString( const char *pszString )
 /* -------------------------------------------------------------------- */
         else if( sContext.eTokenType == TLiteral )
         {
-            CPLXMLNode *psValue;
-
-            psValue = _CPLCreateXMLNode(NULL, CXT_Literal, sContext.pszToken);
+            CPLXMLNode *psValue = _CPLCreateXMLNode(NULL, CXT_Literal, sContext.pszToken);
             if (!psValue) break;
             AttachNode( &sContext, psValue );
         }
@@ -830,9 +859,7 @@ CPLXMLNode *CPLParseXMLString( const char *pszString )
 /* -------------------------------------------------------------------- */
         else if( sContext.eTokenType == TString && !sContext.bInElement )
         {
-            CPLXMLNode *psValue;
-
-            psValue = _CPLCreateXMLNode(NULL, CXT_Text, sContext.pszToken);
+            CPLXMLNode *psValue = _CPLCreateXMLNode(NULL, CXT_Text, sContext.pszToken);
             if (!psValue) break;
             AttachNode( &sContext, psValue );
         }
@@ -841,8 +868,8 @@ CPLXMLNode *CPLParseXMLString( const char *pszString )
 /* -------------------------------------------------------------------- */
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Parse error at line %d, unexpected token:%.500s\n", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Parse error at line %d, unexpected token:%.500s\n",
                       sContext.nInputLine, sContext.pszToken );
             break;
         }
@@ -851,12 +878,27 @@ CPLXMLNode *CPLParseXMLString( const char *pszString )
 /* -------------------------------------------------------------------- */
 /*      Did we pop all the way out of our stack?                        */
 /* -------------------------------------------------------------------- */
-    if( CPLGetLastErrorType() != CE_Failure && sContext.nStackSize != 0 )
+    if( CPLGetLastErrorType() != CE_Failure && sContext.nStackSize > 0 &&
+        sContext.papsStack != NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Parse error at EOF, not all elements have been closed,\n"
-                  "starting with %.500s\n", 
-                  sContext.papsStack[sContext.nStackSize-1].psFirstNode->pszValue );
+#ifdef DEBUG
+        /* Makes life of fuzzers easier if we accept somewhat corrupted XML */
+        /* like <x> ... */
+        if( CPLTestBool(CPLGetConfigOption("CPL_MINIXML_RELAXED", "FALSE")) )
+        {
+            CPLError( CE_Warning, CPLE_AppDefined,
+                    "Parse error at EOF, not all elements have been closed,\n"
+                    "starting with %.500s\n",
+                    sContext.papsStack[sContext.nStackSize-1].psFirstNode->pszValue );
+        }
+        else
+#endif
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                    "Parse error at EOF, not all elements have been closed,\n"
+                    "starting with %.500s\n",
+                    sContext.papsStack[sContext.nStackSize-1].psFirstNode->pszValue );
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -880,38 +922,43 @@ CPLXMLNode *CPLParseXMLString( const char *pszString )
 /*                            _GrowBuffer()                             */
 /************************************************************************/
 
-static void _GrowBuffer( size_t nNeeded, 
-                         char **ppszText, unsigned int *pnMaxLength )
+static bool _GrowBuffer( size_t nNeeded,
+                         char **ppszText, size_t *pnMaxLength )
 
 {
     if( nNeeded+1 >= *pnMaxLength )
     {
         *pnMaxLength = MAX(*pnMaxLength * 2,nNeeded+1);
-        *ppszText = (char *) CPLRealloc(*ppszText, *pnMaxLength);
+        char* pszTextNew = (char *) VSIRealloc(*ppszText, *pnMaxLength);
+        if( pszTextNew == NULL )
+            return false;
+        *ppszText = pszTextNew;
     }
+    return true;
 }
 
 /************************************************************************/
 /*                        CPLSerializeXMLNode()                         */
 /************************************************************************/
 
-static void
+static bool
 CPLSerializeXMLNode( const CPLXMLNode *psNode, int nIndent,
-                     char **ppszText, unsigned int *pnLength, 
-                     unsigned int *pnMaxLength )
+                     char **ppszText, size_t *pnLength,
+                     size_t *pnMaxLength )
 
 {
     if( psNode == NULL )
-        return;
-    
+        return true;
+
 /* -------------------------------------------------------------------- */
 /*      Ensure the buffer is plenty large to hold this additional       */
 /*      string.                                                         */
 /* -------------------------------------------------------------------- */
     *pnLength += strlen(*ppszText + *pnLength);
-    _GrowBuffer( strlen(psNode->pszValue) + *pnLength + 40 + nIndent, 
-                 ppszText, pnMaxLength );
-    
+    if( !_GrowBuffer( strlen(psNode->pszValue) + *pnLength + 40 + nIndent,
+                      ppszText, pnMaxLength ) )
+        return false;
+
 /* -------------------------------------------------------------------- */
 /*      Text is just directly emitted.                                  */
 /* -------------------------------------------------------------------- */
@@ -922,8 +969,12 @@ CPLSerializeXMLNode( const CPLXMLNode *psNode, int nIndent,
         CPLAssert( psNode->psChild == NULL );
 
         /* Escaped text might be bigger than expected. */
-        _GrowBuffer( strlen(pszEscaped) + *pnLength,
-                     ppszText, pnMaxLength );
+        if( !_GrowBuffer( strlen(pszEscaped) + *pnLength,
+                          ppszText, pnMaxLength ) )
+        {
+            CPLFree( pszEscaped );
+            return false;
+        }
         strcat( *ppszText + *pnLength, pszEscaped );
 
         CPLFree( pszEscaped );
@@ -934,22 +985,27 @@ CPLSerializeXMLNode( const CPLXMLNode *psNode, int nIndent,
 /* -------------------------------------------------------------------- */
     else if( psNode->eType == CXT_Attribute )
     {
-        CPLAssert( psNode->psChild != NULL 
+        CPLAssert( psNode->psChild != NULL
                    && psNode->psChild->eType == CXT_Text );
 
-        sprintf( *ppszText + *pnLength, " %s=\"", psNode->pszValue );
+        snprintf( *ppszText + *pnLength, *pnMaxLength - *pnLength, " %s=\"", psNode->pszValue );
         *pnLength += strlen(*ppszText + *pnLength);
 
         char *pszEscaped = CPLEscapeString( psNode->psChild->pszValue, -1, CPLES_XML );
 
-        _GrowBuffer( strlen(pszEscaped) + *pnLength,
-                     ppszText, pnMaxLength );
+        if( !_GrowBuffer( strlen(pszEscaped) + *pnLength,
+                          ppszText, pnMaxLength ) )
+        {
+            CPLFree( pszEscaped );
+            return false;
+        }
         strcat( *ppszText + *pnLength, pszEscaped );
 
         CPLFree( pszEscaped );
 
         *pnLength += strlen(*ppszText + *pnLength);
-        _GrowBuffer( 3 + *pnLength, ppszText, pnMaxLength );
+        if( !_GrowBuffer( 3 + *pnLength, ppszText, pnMaxLength ) )
+            return false;
         strcat( *ppszText + *pnLength, "\"" );
     }
 
@@ -958,14 +1014,12 @@ CPLSerializeXMLNode( const CPLXMLNode *psNode, int nIndent,
 /* -------------------------------------------------------------------- */
     else if( psNode->eType == CXT_Comment )
     {
-        int     i;
-
         CPLAssert( psNode->psChild == NULL );
 
-        for( i = 0; i < nIndent; i++ )
+        for( int i = 0; i < nIndent; i++ )
             (*ppszText)[(*pnLength)++] = ' ';
 
-        sprintf( *ppszText + *pnLength, "<!--%s-->\n", 
+        snprintf( *ppszText + *pnLength, *pnMaxLength - *pnLength, "<!--%s-->\n",
                  psNode->pszValue );
     }
 
@@ -974,11 +1028,9 @@ CPLSerializeXMLNode( const CPLXMLNode *psNode, int nIndent,
 /* -------------------------------------------------------------------- */
     else if( psNode->eType == CXT_Literal )
     {
-        int     i;
-
         CPLAssert( psNode->psChild == NULL );
 
-        for( i = 0; i < nIndent; i++ )
+        for( int i = 0; i < nIndent; i++ )
             (*ppszText)[(*pnLength)++] = ' ';
 
         strcpy( *ppszText + *pnLength, psNode->pszValue );
@@ -991,31 +1043,36 @@ CPLSerializeXMLNode( const CPLXMLNode *psNode, int nIndent,
 /* -------------------------------------------------------------------- */
     else if( psNode->eType == CXT_Element )
     {
-        int             bHasNonAttributeChildren = FALSE;
-        CPLXMLNode      *psChild;
-        
-        memset( *ppszText + *pnLength, ' ', nIndent );
+        bool bHasNonAttributeChildren = false;
+
+        if( nIndent )
+            memset( *ppszText + *pnLength, ' ', nIndent );
         *pnLength += nIndent;
         (*ppszText)[*pnLength] = '\0';
 
-        sprintf( *ppszText + *pnLength, "<%s", psNode->pszValue );
+        snprintf( *ppszText + *pnLength, *pnMaxLength - *pnLength, "<%s", psNode->pszValue );
 
         /* Serialize *all* the attribute children, regardless of order */
-        for( psChild = psNode->psChild; 
-             psChild != NULL; 
+        CPLXMLNode *psChild;
+        for( psChild = psNode->psChild;
+             psChild != NULL;
              psChild = psChild->psNext )
         {
             if( psChild->eType == CXT_Attribute )
-                CPLSerializeXMLNode( psChild, 0, ppszText, pnLength, 
-                                     pnMaxLength );
+            {
+                if( !CPLSerializeXMLNode( psChild, 0, ppszText, pnLength,
+                                          pnMaxLength ) )
+                    return false;
+            }
             else
-                bHasNonAttributeChildren = TRUE;
+                bHasNonAttributeChildren = true;
         }
-        
+
         if( !bHasNonAttributeChildren )
         {
-            _GrowBuffer( *pnLength + 40,
-                         ppszText, pnMaxLength );
+            if( !_GrowBuffer( *pnLength + 40,
+                              ppszText, pnMaxLength ) )
+                return false;
 
             if( psNode->pszValue[0] == '?' )
                 strcat( *ppszText + *pnLength, "?>\n" );
@@ -1024,12 +1081,12 @@ CPLSerializeXMLNode( const CPLXMLNode *psNode, int nIndent,
         }
         else
         {
-            int         bJustText = TRUE;
+            bool bJustText = true;
 
             strcat( *ppszText + *pnLength, ">" );
 
-            for( psChild = psNode->psChild; 
-                 psChild != NULL; 
+            for( psChild = psNode->psChild;
+                 psChild != NULL;
                  psChild = psChild->psNext )
             {
                 if( psChild->eType == CXT_Attribute )
@@ -1037,31 +1094,36 @@ CPLSerializeXMLNode( const CPLXMLNode *psNode, int nIndent,
 
                 if( psChild->eType != CXT_Text && bJustText )
                 {
-                    bJustText = FALSE;
+                    bJustText = false;
                     strcat( *ppszText + *pnLength, "\n" );
                 }
 
-                CPLSerializeXMLNode( psChild, nIndent + 2, ppszText, pnLength, 
-                                     pnMaxLength );
+                if( !CPLSerializeXMLNode( psChild, nIndent + 2, ppszText, pnLength,
+                                          pnMaxLength ) )
+                    return false;
             }
-        
+
             *pnLength += strlen(*ppszText + *pnLength);
-            _GrowBuffer( strlen(psNode->pszValue) + *pnLength + 40 + nIndent, 
-                         ppszText, pnMaxLength );
+            if( !_GrowBuffer( strlen(psNode->pszValue) + *pnLength + 40 + nIndent,
+                              ppszText, pnMaxLength ) )
+                return false;
 
             if( !bJustText )
             {
-                memset( *ppszText + *pnLength, ' ', nIndent );
+                if( nIndent )
+                    memset( *ppszText + *pnLength, ' ', nIndent );
                 *pnLength += nIndent;
                 (*ppszText)[*pnLength] = '\0';
             }
 
             *pnLength += strlen(*ppszText + *pnLength);
-            sprintf( *ppszText + *pnLength, "</%s>\n", psNode->pszValue );
+            snprintf( *ppszText + *pnLength, *pnMaxLength - *pnLength, "</%s>\n", psNode->pszValue );
         }
     }
+
+    return true;
 }
-                                
+
 /************************************************************************/
 /*                        CPLSerializeXMLTree()                         */
 /************************************************************************/
@@ -1071,27 +1133,35 @@ CPLSerializeXMLNode( const CPLXMLNode *psNode, int nIndent,
  *
  * This function converts a CPLXMLNode tree representation of a document
  * into a flat string representation.  White space indentation is used
- * visually preserve the tree structure of the document.  The returned 
+ * visually preserve the tree structure of the document.  The returned
  * document becomes owned by the caller and should be freed with CPLFree()
  * when no longer needed.
  *
  * @param psNode the node to serialize.
  *
- * @return the document on success or NULL on failure. 
+ * @return the document on success or NULL on failure.
  */
 
 char *CPLSerializeXMLTree( const CPLXMLNode *psNode )
 
 {
-    unsigned int nMaxLength = 100, nLength = 0;
-    char *pszText = NULL;
-    const CPLXMLNode *psThis;
-
-    pszText = (char *) CPLMalloc(nMaxLength);
+    size_t nMaxLength = 100;
+    char *pszText =  (char *) VSIMalloc(nMaxLength);
+    if( pszText == NULL )
+        return NULL;
     pszText[0] = '\0';
 
-    for( psThis = psNode; psThis != NULL; psThis = psThis->psNext )
-        CPLSerializeXMLNode( psThis, 0, &pszText, &nLength, &nMaxLength );
+    size_t nLength = 0;
+    for( const CPLXMLNode *psThis = psNode;
+         psThis != NULL;
+         psThis = psThis->psNext )
+    {
+        if( !CPLSerializeXMLNode( psThis, 0, &pszText, &nLength, &nMaxLength ) )
+        {
+            VSIFree(pszText);
+            return NULL;
+        }
+    }
 
     return pszText;
 }
@@ -1100,31 +1170,35 @@ char *CPLSerializeXMLTree( const CPLXMLNode *psNode )
 /*                          CPLCreateXMLNode()                          */
 /************************************************************************/
 
+#ifdef DEBUG
+static CPLXMLNode* psDummyStaticNode;
+#endif
+
 /**
  * \brief Create an document tree item.
  *
  * Create a single CPLXMLNode object with the desired value and type, and
- * attach it as a child of the indicated parent.  
+ * attach it as a child of the indicated parent.
  *
- * @param poParent the parent to which this node should be attached as a 
- * child.  May be NULL to keep as free standing. 
+ * @param poParent the parent to which this node should be attached as a
+ * child.  May be NULL to keep as free standing.
  * @param eType the type of the newly created node
  * @param pszText the value of the newly created node
  *
  * @return the newly created node, now owned by the caller (or parent node).
  */
 
-CPLXMLNode *CPLCreateXMLNode( CPLXMLNode *poParent, CPLXMLNodeType eType, 
+CPLXMLNode *CPLCreateXMLNode( CPLXMLNode *poParent, CPLXMLNodeType eType,
                               const char *pszText )
 
 {
-    CPLXMLNode  *psNode;
 
 /* -------------------------------------------------------------------- */
 /*      Create new node.                                                */
 /* -------------------------------------------------------------------- */
-    psNode = (CPLXMLNode *) CPLCalloc(sizeof(CPLXMLNode),1);
-    
+    CPLXMLNode *psNode
+        = (CPLXMLNode *) CPLCalloc(sizeof(CPLXMLNode),1);
+
     psNode->eType = eType;
     psNode->pszValue = CPLStrdup( pszText );
 
@@ -1145,7 +1219,17 @@ CPLXMLNode *CPLCreateXMLNode( CPLXMLNode *poParent, CPLXMLNodeType eType,
             psLink->psNext = psNode;
         }
     }
-    
+#ifdef DEBUG
+    else
+    {
+        // Coverity sometimes doesn't realize that this function is passed
+        // with a non NULL parent and thinks that this branch is taken, leading
+        // to creating object being leak by caller. This ugly hack hopefully
+        // makes it believe that someone will reference it...
+        psDummyStaticNode = psNode;
+    }
+#endif
+
     return psNode;
 }
 
@@ -1156,22 +1240,22 @@ CPLXMLNode *CPLCreateXMLNode( CPLXMLNode *poParent, CPLXMLNodeType eType,
 /* Same as CPLCreateXMLNode() but can return NULL in case of out-of-memory */
 /* situation */
 
-static CPLXMLNode *_CPLCreateXMLNode( CPLXMLNode *poParent, CPLXMLNodeType eType, 
-                               const char *pszText )
+static CPLXMLNode *_CPLCreateXMLNode( CPLXMLNode *poParent, CPLXMLNodeType eType,
+                                      const char *pszText )
 
 {
-    CPLXMLNode  *psNode;
 
 /* -------------------------------------------------------------------- */
 /*      Create new node.                                                */
 /* -------------------------------------------------------------------- */
-    psNode = (CPLXMLNode *) VSICalloc(sizeof(CPLXMLNode),1);
+    CPLXMLNode  *psNode
+        = (CPLXMLNode *) VSICalloc(sizeof(CPLXMLNode),1);
     if (psNode == NULL)
     {
         CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate CPLXMLNode");
         return NULL;
     }
-    
+
     psNode->eType = eType;
     psNode->pszValue = VSIStrdup( pszText );
     if (psNode->pszValue == NULL)
@@ -1198,7 +1282,7 @@ static CPLXMLNode *_CPLCreateXMLNode( CPLXMLNode *poParent, CPLXMLNodeType eType
             psLink->psNext = psNode;
         }
     }
-    
+
     return psNode;
 }
 
@@ -1207,10 +1291,10 @@ static CPLXMLNode *_CPLCreateXMLNode( CPLXMLNode *poParent, CPLXMLNodeType eType
 /************************************************************************/
 
 /**
- * \brief Destroy a tree. 
+ * \brief Destroy a tree.
  *
  * This function frees resources associated with a CPLXMLNode and all its
- * children nodes.  
+ * children nodes.
  *
  * @param psNode the tree to free.
  */
@@ -1258,38 +1342,37 @@ void CPLDestroyXMLNode( CPLXMLNode *psNode )
  * siblings as well as children, prefix the pszElement name with an equal
  * sign.  This function does an in-order traversal of the document tree.
  * So it will first match against the current node, then it's first child,
- * that childs first child, and so on. 
+ * that child's first child, and so on.
  *
  * Use CPLGetXMLNode() to find a specific child, or along a specific
- * node path. 
+ * node path.
  *
  * @param psRoot the subtree to search.  This should be a node of type
- * CXT_Element.  NULL is safe. 
+ * CXT_Element.  NULL is safe.
  *
  * @param pszElement the name of the element or attribute to search for.
  *
- * @return The matching node or NULL on failure. 
+ * @return The matching node or NULL on failure.
  */
 
 CPLXMLNode *CPLSearchXMLNode( CPLXMLNode *psRoot, const char *pszElement )
 
 {
-    int         bSideSearch = FALSE;
-    CPLXMLNode *psChild, *psResult;
-
     if( psRoot == NULL || pszElement == NULL )
         return NULL;
 
+    bool bSideSearch = false;
+
     if( *pszElement == '=' )
     {
-        bSideSearch = TRUE;
+        bSideSearch = true;
         pszElement++;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Does this node match?                                           */
 /* -------------------------------------------------------------------- */
-    if( (psRoot->eType == CXT_Element 
+    if( (psRoot->eType == CXT_Element
          || psRoot->eType == CXT_Attribute)
         && EQUAL(pszElement,psRoot->pszValue) )
         return psRoot;
@@ -1297,16 +1380,17 @@ CPLXMLNode *CPLSearchXMLNode( CPLXMLNode *psRoot, const char *pszElement )
 /* -------------------------------------------------------------------- */
 /*      Search children.                                                */
 /* -------------------------------------------------------------------- */
+    CPLXMLNode *psChild;
     for( psChild = psRoot->psChild; psChild != NULL; psChild = psChild->psNext)
     {
-        if( (psChild->eType == CXT_Element 
+        if( (psChild->eType == CXT_Element
              || psChild->eType == CXT_Attribute)
             && EQUAL(pszElement,psChild->pszValue) )
             return psChild;
 
         if( psChild->psChild != NULL )
         {
-            psResult = CPLSearchXMLNode( psChild, pszElement );
+            CPLXMLNode *psResult = CPLSearchXMLNode( psChild, pszElement );
             if( psResult != NULL )
                 return psResult;
         }
@@ -1319,12 +1403,12 @@ CPLXMLNode *CPLSearchXMLNode( CPLXMLNode *psRoot, const char *pszElement )
     {
         for( psRoot = psRoot->psNext; psRoot != NULL; psRoot = psRoot->psNext )
         {
-            psResult = CPLSearchXMLNode( psRoot, pszElement );
+            CPLXMLNode *psResult = CPLSearchXMLNode( psRoot, pszElement );
             if( psResult != NULL )
                 return psResult;
         }
     }
-    
+
     return NULL;
 }
 
@@ -1335,45 +1419,45 @@ CPLXMLNode *CPLSearchXMLNode( CPLXMLNode *psRoot, const char *pszElement )
 /**
  * \brief Find node by path.
  *
- * Searches the document or subdocument indicated by psRoot for an element 
+ * Searches the document or subdocument indicated by psRoot for an element
  * (or attribute) with the given path.  The path should consist of a set of
- * element names separated by dots, not including the name of the root 
+ * element names separated by dots, not including the name of the root
  * element (psRoot).  If the requested element is not found NULL is returned.
  *
- * Attribute names may only appear as the last item in the path. 
+ * Attribute names may only appear as the last item in the path.
  *
  * The search is done from the root nodes children, but all intermediate
- * nodes in the path must be specified.  Seaching for "name" would only find
+ * nodes in the path must be specified.  Searching for "name" would only find
  * a name element or attribute if it is a direct child of the root, not at any
- * level in the subdocument. 
+ * level in the subdocument.
  *
  * If the pszPath is prefixed by "=" then the search will begin with the
  * root node, and it's siblings, instead of the root nodes children.  This
  * is particularly useful when searching within a whole document which is
  * often prefixed by one or more "junk" nodes like the <?xml> declaration.
  *
- * @param psRoot the subtree in which to search.  This should be a node of 
- * type CXT_Element.  NULL is safe. 
+ * @param psRoot the subtree in which to search.  This should be a node of
+ * type CXT_Element.  NULL is safe.
  *
- * @param pszPath the list of element names in the path (dot separated). 
+ * @param pszPath the list of element names in the path (dot separated).
  *
- * @return the requested element node, or NULL if not found. 
+ * @return the requested element node, or NULL if not found.
  */
 
 CPLXMLNode *CPLGetXMLNode( CPLXMLNode *psRoot, const char *pszPath )
 
 {
+    if( psRoot == NULL || pszPath == NULL )
+        return NULL;
+
     char        *apszTokens[2];
     char        **papszTokens;
     int         iToken = 0;
-    int         bSideSearch = FALSE;
-
-    if( psRoot == NULL || pszPath == NULL )
-        return NULL;
+    bool        bSideSearch = false;
 
     if( *pszPath == '=' )
     {
-        bSideSearch = TRUE;
+        bSideSearch = true;
         pszPath++;
     }
 
@@ -1395,14 +1479,14 @@ CPLXMLNode *CPLGetXMLNode( CPLXMLNode *psRoot, const char *pszPath )
         if( bSideSearch )
         {
             psChild = psRoot;
-            bSideSearch = FALSE;
+            bSideSearch = false;
         }
         else
             psChild = psRoot->psChild;
 
-        for( ; psChild != NULL; psChild = psChild->psNext ) 
+        for( ; psChild != NULL; psChild = psChild->psNext )
         {
-            if( psChild->eType != CXT_Text 
+            if( psChild->eType != CXT_Text
                 && EQUAL(papszTokens[iToken],psChild->pszValue) )
                 break;
         }
@@ -1427,21 +1511,21 @@ CPLXMLNode *CPLGetXMLNode( CPLXMLNode *psRoot, const char *pszPath )
 /************************************************************************/
 
 /**
- * \brief Fetch element/attribute value. 
+ * \brief Fetch element/attribute value.
  *
  * Searches the document for the element/attribute value associated with
  * the path.  The corresponding node is internally found with CPLGetXMLNode()
- * (see there for details on path handling).  Once found, the value is 
+ * (see there for details on path handling).  Once found, the value is
  * considered to be the first CXT_Text child of the node.
  *
- * If the attribute/element search fails, or if the found node has not
- * value then the passed default value is returned. 
+ * If the attribute/element search fails, or if the found node has no
+ * value then the passed default value is returned.
  *
  * The returned value points to memory within the document tree, and should
- * not be altered or freed. 
+ * not be altered or freed.
  *
- * @param psRoot the subtree in which to search.  This should be a node of 
- * type CXT_Element.  NULL is safe. 
+ * @param psRoot the subtree in which to search.  This should be a node of
+ * type CXT_Element.  NULL is safe.
  *
  * @param pszPath the list of element names in the path (dot separated).  An
  * empty path means get the value of the psRoot node.
@@ -1452,7 +1536,7 @@ CPLXMLNode *CPLGetXMLNode( CPLXMLNode *psRoot, const char *pszPath )
  * @return the requested value or pszDefault if not found.
  */
 
-const char *CPLGetXMLValue( CPLXMLNode *psRoot, const char *pszPath, 
+const char *CPLGetXMLValue( CPLXMLNode *psRoot, const char *pszPath,
                             const char *pszDefault )
 
 {
@@ -1468,7 +1552,7 @@ const char *CPLGetXMLValue( CPLXMLNode *psRoot, const char *pszPath,
 
     if( psTarget->eType == CXT_Attribute )
     {
-        CPLAssert( psTarget->psChild != NULL 
+        CPLAssert( psTarget->psChild != NULL
                    && psTarget->psChild->eType == CXT_Text );
 
         return psTarget->psChild->pszValue;
@@ -1476,7 +1560,7 @@ const char *CPLGetXMLValue( CPLXMLNode *psRoot, const char *pszPath,
 
     if( psTarget->eType == CXT_Element )
     {
-        // Find first non-attribute child, and verify it is a single text 
+        // Find first non-attribute child, and verify it is a single text
         // with no siblings
 
         psTarget = psTarget->psChild;
@@ -1484,7 +1568,7 @@ const char *CPLGetXMLValue( CPLXMLNode *psRoot, const char *pszPath,
         while( psTarget != NULL && psTarget->eType == CXT_Attribute )
             psTarget = psTarget->psNext;
 
-        if( psTarget != NULL 
+        if( psTarget != NULL
             && psTarget->eType == CXT_Text
             && psTarget->psNext == NULL )
             return psTarget->pszValue;
@@ -1498,7 +1582,7 @@ const char *CPLGetXMLValue( CPLXMLNode *psRoot, const char *pszPath,
 /************************************************************************/
 
 /**
- * \brief Add child node to parent. 
+ * \brief Add child node to parent.
  *
  * The passed child is added to the list of children of the indicated
  * parent.  Normally the child is added at the end of the parents child
@@ -1506,19 +1590,17 @@ const char *CPLGetXMLValue( CPLXMLNode *psRoot, const char *pszPath,
  * attributes but before any other element type.  Ownership of the child
  * node is effectively assumed by the parent node.   If the child has
  * siblings (it's psNext is not NULL) they will be trimmed, but if the child
- * has children they are carried with it. 
+ * has children they are carried with it.
  *
  * @param psParent the node to attach the child to.  May not be NULL.
  *
- * @param psChild the child to add to the parent.  May not be NULL.  Should 
- * not be a child of any other parent. 
+ * @param psChild the child to add to the parent.  May not be NULL.  Should
+ * not be a child of any other parent.
  */
 
 void CPLAddXMLChild( CPLXMLNode *psParent, CPLXMLNode *psChild )
 
 {
-    CPLXMLNode *psSib;
-
     if( psParent->psChild == NULL )
     {
         psParent->psChild = psChild;
@@ -1526,7 +1608,7 @@ void CPLAddXMLChild( CPLXMLNode *psParent, CPLXMLNode *psChild )
     }
 
     // Insert at head of list if first child is not attribute.
-    if( psChild->eType == CXT_Attribute 
+    if( psChild->eType == CXT_Attribute
         && psParent->psChild->eType != CXT_Attribute )
     {
         psChild->psNext = psParent->psChild;
@@ -1535,13 +1617,14 @@ void CPLAddXMLChild( CPLXMLNode *psParent, CPLXMLNode *psChild )
     }
 
     // Search for end of list.
-    for( psSib = psParent->psChild; 
-         psSib->psNext != NULL; 
-         psSib = psSib->psNext ) 
+    CPLXMLNode *psSib;
+    for( psSib = psParent->psChild;
+         psSib->psNext != NULL;
+         psSib = psSib->psNext )
     {
         // Insert attributes if the next node is not an attribute.
-        if( psChild->eType == CXT_Attribute 
-            && psSib->psNext != NULL 
+        if( psChild->eType == CXT_Attribute
+            && psSib->psNext != NULL
             && psSib->psNext->eType != CXT_Attribute )
         {
             psChild->psNext = psSib->psNext;
@@ -1558,7 +1641,7 @@ void CPLAddXMLChild( CPLXMLNode *psParent, CPLXMLNode *psChild )
 /************************************************************************/
 
 /**
- * \brief Remove child node from parent. 
+ * \brief Remove child node from parent.
  *
  * The passed child is removed from the child list of the passed parent,
  * but the child is not destroyed.  The child retains ownership of it's
@@ -1574,20 +1657,19 @@ void CPLAddXMLChild( CPLXMLNode *psParent, CPLXMLNode *psChild )
 int CPLRemoveXMLChild( CPLXMLNode *psParent, CPLXMLNode *psChild )
 
 {
-    CPLXMLNode *psLast = NULL, *psThis;
-
     if( psParent == NULL )
         return FALSE;
 
-    for( psThis = psParent->psChild; 
-         psThis != NULL; 
+    CPLXMLNode *psLast = NULL, *psThis;
+    for( psThis = psParent->psChild;
+         psThis != NULL;
          psLast = psThis, psThis = psThis->psNext )
     {
         if( psThis == psChild )
         {
             if( psLast == NULL )
                 psParent->psChild = psThis->psNext;
-            else 
+            else
                 psLast->psNext = psThis->psNext;
 
             psThis->psNext = NULL;
@@ -1605,14 +1687,14 @@ int CPLRemoveXMLChild( CPLXMLNode *psParent, CPLXMLNode *psChild )
 /**
  * \brief Add new sibling.
  *
- * The passed psNewSibling is added to the end of siblings of the 
+ * The passed psNewSibling is added to the end of siblings of the
  * psOlderSibling node.  That is, it is added to the end of the psNext
- * chain.  There is no special handling if psNewSibling is an attribute. 
- * If this is required, use CPLAddXMLChild(). 
+ * chain.  There is no special handling if psNewSibling is an attribute.
+ * If this is required, use CPLAddXMLChild().
  *
  * @param psOlderSibling the node to attach the sibling after.
  *
- * @param psNewSibling the node to add at the end of psOlderSiblings psNext 
+ * @param psNewSibling the node to add at the end of psOlderSiblings psNext
  * chain.
  */
 
@@ -1643,7 +1725,7 @@ void CPLAddXMLSibling( CPLXMLNode *psOlderSibling, CPLXMLNode *psNewSibling )
  *
  *     psElementNode = CPLCreateXMLNode( psParent, CXT_Element, pszName );
  *     psTextNode = CPLCreateXMLNode( psElementNode, CXT_Text, pszValue );
- * 
+ *
  *     return psElementNode;
  * \endcode
  *
@@ -1651,22 +1733,21 @@ void CPLAddXMLSibling( CPLXMLNode *psOlderSibling, CPLXMLNode *psNewSibling )
  * attaches the element to the passed parent.
  *
  * @param psParent the parent node to which the resulting node should
- * be attached.  May be NULL to keep as freestanding. 
+ * be attached.  May be NULL to keep as freestanding.
  *
  * @param pszName the element name to create.
- * @param pszValue the text to attach to the element. Must not be NULL. 
+ * @param pszValue the text to attach to the element. Must not be NULL.
  *
  * @return the pointer to the new element node.
  */
 
-CPLXMLNode *CPLCreateXMLElementAndValue( CPLXMLNode *psParent, 
-                                         const char *pszName, 
+CPLXMLNode *CPLCreateXMLElementAndValue( CPLXMLNode *psParent,
+                                         const char *pszName,
                                          const char *pszValue )
 
 {
-    CPLXMLNode *psElementNode;
-
-    psElementNode = CPLCreateXMLNode( psParent, CXT_Element, pszName );
+    CPLXMLNode *psElementNode
+        = CPLCreateXMLNode( psParent, CXT_Element, pszName );
     CPLCreateXMLNode( psElementNode, CXT_Text, pszValue );
 
     return psElementNode;
@@ -1692,10 +1773,9 @@ CPLXMLNode *CPLCreateXMLElementAndValue( CPLXMLNode *psParent,
  * attaches the element to the passed parent.
  *
  * @param psParent the parent node to which the resulting node should
- * be attached.  May be NULL to keep as freestanding. 
- *
+ * be attached.  Must not be NULL.
  * @param pszName the attribute name to create.
- * @param pszValue the text to attach to the attribute. Must not be NULL. 
+ * @param pszValue the text to attach to the attribute. Must not be NULL.
  *
  * @since GDAL 2.0
  */
@@ -1704,9 +1784,9 @@ void CPLAddXMLAttributeAndValue( CPLXMLNode *psParent,
                                  const char *pszName,
                                  const char *pszValue )
 {
-    CPLXMLNode *psAttributeNode;
-
-    psAttributeNode = CPLCreateXMLNode( psParent, CXT_Attribute, pszName );
+    CPLAssert(psParent != NULL);
+    CPLXMLNode *psAttributeNode
+        = CPLCreateXMLNode( psParent, CXT_Attribute, pszName );
     CPLCreateXMLNode( psAttributeNode, CXT_Text, pszValue );
 }
 
@@ -1717,11 +1797,11 @@ void CPLAddXMLAttributeAndValue( CPLXMLNode *psParent,
 /**
  * \brief Copy tree.
  *
- * Creates a deep copy of a CPLXMLNode tree.  
+ * Creates a deep copy of a CPLXMLNode tree.
  *
- * @param psTree the tree to duplicate. 
+ * @param psTree the tree to duplicate.
  *
- * @return a copy of the whole tree. 
+ * @return a copy of the whole tree.
  */
 
 CPLXMLNode *CPLCloneXMLTree( CPLXMLNode *psTree )
@@ -1732,9 +1812,8 @@ CPLXMLNode *CPLCloneXMLTree( CPLXMLNode *psTree )
 
     while( psTree != NULL )
     {
-        CPLXMLNode *psCopy;
-
-        psCopy = CPLCreateXMLNode( NULL, psTree->eType, psTree->pszValue );
+        CPLXMLNode *psCopy
+            = CPLCreateXMLNode( NULL, psTree->eType, psTree->pszValue );
         if( psReturn == NULL )
             psReturn = psCopy;
         if( psPrevious != NULL )
@@ -1755,14 +1834,14 @@ CPLXMLNode *CPLCloneXMLTree( CPLXMLNode *psTree )
 /************************************************************************/
 
 /**
- * \brief Set element value by path. 
+ * \brief Set element value by path.
  *
  * Find (or create) the target element or attribute specified in the
- * path, and assign it the indicated value. 
+ * path, and assign it the indicated value.
  *
  * Any path elements that do not already exist will be created.  The target
  * nodes value (the first CXT_Text child) will be replaced with the provided
- * value.  
+ * value.
  *
  * If the target node is an attribute instead of an element, the name
  * should be prefixed with a #.
@@ -1771,11 +1850,11 @@ CPLXMLNode *CPLCloneXMLTree( CPLXMLNode *psTree )
  *   CPLSetXMLValue( "Citation.Id.Description", "DOQ dataset" );
  *   CPLSetXMLValue( "Citation.Id.Description.#name", "doq" );
  *
- * @param psRoot the subdocument to be updated. 
+ * @param psRoot the subdocument to be updated.
  *
- * @param pszPath the dot seperated path to the target element/attribute.
+ * @param pszPath the dot separated path to the target element/attribute.
  *
- * @param pszValue the text value to assign. 
+ * @param pszValue the text value to assign.
  *
  * @return TRUE on success.
  */
@@ -1784,30 +1863,31 @@ int CPLSetXMLValue( CPLXMLNode *psRoot,  const char *pszPath,
                     const char *pszValue )
 
 {
-    char        **papszTokens;
-    int         iToken = 0;
-
-    papszTokens = CSLTokenizeStringComplex( pszPath, ".", FALSE, FALSE );
+    char **papszTokens = CSLTokenizeStringComplex( pszPath, ".", FALSE, FALSE );
+    int iToken = 0;
 
-    while( papszTokens[iToken] != NULL && psRoot != NULL )
+    while( papszTokens[iToken] != NULL )
     {
-        CPLXMLNode *psChild;
-        int        bIsAttribute = FALSE;
+        bool        bIsAttribute = false;
         const char *pszName = papszTokens[iToken];
 
         if( pszName[0] == '#' )
         {
-            bIsAttribute = TRUE;
+            bIsAttribute = true;
             pszName++;
         }
 
         if( psRoot->eType != CXT_Element )
+        {
+            CSLDestroy( papszTokens );
             return FALSE;
+        }
 
-        for( psChild = psRoot->psChild; psChild != NULL; 
-             psChild = psChild->psNext ) 
+        CPLXMLNode *psChild;
+        for( psChild = psRoot->psChild; psChild != NULL;
+             psChild = psChild->psNext )
         {
-            if( psChild->eType != CXT_Text 
+            if( psChild->eType != CXT_Text
                 && EQUAL(pszName,psChild->pszValue) )
                 break;
         }
@@ -1837,10 +1917,10 @@ int CPLSetXMLValue( CPLXMLNode *psRoot,  const char *pszPath,
 /* -------------------------------------------------------------------- */
 /*      Now set a value node under this node.                           */
 /* -------------------------------------------------------------------- */
-    
+
     if( psTextChild == NULL )
         CPLCreateXMLNode( psRoot, CXT_Text, pszValue );
-    else 
+    else
     {
         CPLFree( psTextChild->pszValue );
         psTextChild->pszValue = CPLStrdup( pszValue );
@@ -1854,16 +1934,16 @@ int CPLSetXMLValue( CPLXMLNode *psRoot,  const char *pszPath,
 /************************************************************************/
 
 /**
- * \brief Strip indicated namespaces. 
+ * \brief Strip indicated namespaces.
  *
  * The subdocument (psRoot) is recursively examined, and any elements
  * with the indicated namespace prefix will have the namespace prefix
  * stripped from the element names.  If the passed namespace is NULL, then
- * all namespace prefixes will be stripped. 
+ * all namespace prefixes will be stripped.
  *
  * Nodes other than elements should remain unaffected.  The changes are
- * made "in place", and should not alter any node locations, only the 
- * pszValue field of affected nodes. 
+ * made "in place", and should not alter any node locations, only the
+ * pszValue field of affected nodes.
  *
  * @param psRoot the document to operate on.
  * @param pszNamespace the name space prefix (not including colon), or NULL.
@@ -1871,8 +1951,8 @@ int CPLSetXMLValue( CPLXMLNode *psRoot,  const char *pszPath,
  * operate on the passed node.
  */
 
-void CPLStripXMLNamespace( CPLXMLNode *psRoot, 
-                           const char *pszNamespace, 
+void CPLStripXMLNamespace( CPLXMLNode *psRoot,
+                           const char *pszNamespace,
                            int bRecurse )
 
 {
@@ -1885,7 +1965,7 @@ void CPLStripXMLNamespace( CPLXMLNode *psRoot,
         {
             if( pszNamespace != NULL )
             {
-                if( EQUALN(pszNamespace,psRoot->pszValue,nNameSpaceLen) 
+                if( EQUALN(pszNamespace,psRoot->pszValue,nNameSpaceLen)
                     && psRoot->pszValue[nNameSpaceLen] == ':' )
                 {
                     memmove(psRoot->pszValue, psRoot->pszValue+nNameSpaceLen+1,
@@ -1928,12 +2008,12 @@ void CPLStripXMLNamespace( CPLXMLNode *psRoot,
  *
  * The named file is opened, loaded into memory as a big string, and
  * parsed with CPLParseXMLString().  Errors in reading the file or parsing
- * the XML will be reported by CPLError(). 
+ * the XML will be reported by CPLError().
  *
  * The "large file" API is used, so XML files can come from virtualized
- * files. 
+ * files.
  *
- * @param pszFilename the file to open. 
+ * @param pszFilename the file to open.
  *
  * @return NULL on failure, or the document tree on success.
  */
@@ -1941,21 +2021,19 @@ void CPLStripXMLNamespace( CPLXMLNode *psRoot,
 CPLXMLNode *CPLParseXMLFile( const char *pszFilename )
 
 {
-    GByte           *pabyOut = NULL;
-    char            *pszDoc;
-    CPLXMLNode      *psTree;
-
 /* -------------------------------------------------------------------- */
 /*      Ingest the file.                                                */
 /* -------------------------------------------------------------------- */
+    GByte *pabyOut = NULL;
     if( !VSIIngestFile( NULL, pszFilename, &pabyOut, NULL, -1 ) )
         return NULL;
-    pszDoc = (char*) pabyOut;
+
+    char *pszDoc = (char*) pabyOut;
 
 /* -------------------------------------------------------------------- */
 /*      Parse it.                                                       */
 /* -------------------------------------------------------------------- */
-    psTree = CPLParseXMLString( pszDoc );
+    CPLXMLNode *psTree = CPLParseXMLString( pszDoc );
     CPLFree( pszDoc );
 
     return psTree;
@@ -1966,41 +2044,37 @@ CPLXMLNode *CPLParseXMLFile( const char *pszFilename )
 /************************************************************************/
 
 /**
- * \brief Write document tree to a file. 
+ * \brief Write document tree to a file.
  *
- * The passed document tree is converted into one big string (with 
+ * The passed document tree is converted into one big string (with
  * CPLSerializeXMLTree()) and then written to the named file.  Errors writing
  * the file will be reported by CPLError().  The source document tree is
- * not altered.  If the output file already exists it will be overwritten. 
+ * not altered.  If the output file already exists it will be overwritten.
  *
- * @param psTree the document tree to write. 
- * @param pszFilename the name of the file to write to. 
+ * @param psTree the document tree to write.
+ * @param pszFilename the name of the file to write to.
  * @return TRUE on success, FALSE otherwise.
  */
 
 int CPLSerializeXMLTreeToFile( const CPLXMLNode *psTree, const char *pszFilename )
 
 {
-    char    *pszDoc;
-    VSILFILE    *fp;
-    vsi_l_offset nLength;
-
 /* -------------------------------------------------------------------- */
 /*      Serialize document.                                             */
 /* -------------------------------------------------------------------- */
-    pszDoc = CPLSerializeXMLTree( psTree );
+    char *pszDoc = CPLSerializeXMLTree( psTree );
     if( pszDoc == NULL )
         return FALSE;
 
-    nLength = strlen(pszDoc);
+    vsi_l_offset nLength = strlen(pszDoc);
 
 /* -------------------------------------------------------------------- */
 /*      Create file.                                                    */
 /* -------------------------------------------------------------------- */
-    fp = VSIFOpenL( pszFilename, "wt" );
+    VSILFILE *fp = VSIFOpenL( pszFilename, "wt" );
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "Failed to open %.500s to write.", pszFilename );
         CPLFree( pszDoc );
         return FALSE;
@@ -2011,10 +2085,10 @@ int CPLSerializeXMLTreeToFile( const CPLXMLNode *psTree, const char *pszFilename
 /* -------------------------------------------------------------------- */
     if( VSIFWriteL( pszDoc, 1, (size_t)nLength, fp ) != nLength )
     {
-        CPLError( CE_Failure, CPLE_FileIO, 
+        CPLError( CE_Failure, CPLE_FileIO,
                   "Failed to write whole XML document (%.500s).",
                   pszFilename );
-        VSIFCloseL( fp );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
         CPLFree( pszDoc );
         return FALSE;
     }
@@ -2022,10 +2096,16 @@ int CPLSerializeXMLTreeToFile( const CPLXMLNode *psTree, const char *pszFilename
 /* -------------------------------------------------------------------- */
 /*      Cleanup                                                         */
 /* -------------------------------------------------------------------- */
-    VSIFCloseL( fp );
+    int bRet = VSIFCloseL( fp ) == 0;
+    if( !bRet )
+    {
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Failed to write whole XML document (%.500s).",
+                  pszFilename );
+    }
     CPLFree( pszDoc );
 
-    return TRUE;
+    return bRet;
 }
 
 /************************************************************************/
@@ -2035,15 +2115,15 @@ int CPLSerializeXMLTreeToFile( const CPLXMLNode *psTree, const char *pszFilename
 /**
  * \brief Make string into safe XML token.
  *
- * Modififies a string in place to try and make it into a legal
+ * Modifies a string in place to try and make it into a legal
  * XML token that can be used as an element name.   This is accomplished
- * by changing any characters not legal in a token into an underscore. 
- * 
- * NOTE: This function should implement the rules in section 2.3 of 
+ * by changing any characters not legal in a token into an underscore.
+ *
+ * NOTE: This function should implement the rules in section 2.3 of
  * http://www.w3.org/TR/xml11/ but it doesn't yet do that properly.  We
  * only do a rough approximation of that.
  *
- * @param pszTarget the string to be adjusted.  It is altered in place. 
+ * @param pszTarget the string to be adjusted.  It is altered in place.
  */
 
 void CPLCleanXMLElementName( char *pszTarget )
diff --git a/port/cpl_minixml.h b/port/cpl_minixml.h
index 731c8d7..3b53e13 100644
--- a/port/cpl_minixml.h
+++ b/port/cpl_minixml.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_minixml.h 28690 2015-03-08 20:06:12Z rouault $
+ * $Id: cpl_minixml.h 33666 2016-03-07 05:21:07Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Declarations for MiniXML Handler.
@@ -14,21 +14,21 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _CPL_MINIXML_H_INCLUDED
-#define _CPL_MINIXML_H_INCLUDED
+#ifndef CPL_MINIXML_H_INCLUDED
+#define CPL_MINIXML_H_INCLUDED
 
 #include "cpl_port.h"
 
@@ -40,94 +40,94 @@
 
 CPL_C_START
 
-typedef enum 
+typedef enum
 {
     /*! Node is an element */           CXT_Element = 0,
     /*! Node is a raw text value */     CXT_Text = 1,
-    /*! Node is attribute */            CXT_Attribute = 2,  
-    /*! Node is an XML comment. */      CXT_Comment = 3,    
-    /*! Node is a special literal */    CXT_Literal = 4     
+    /*! Node is attribute */            CXT_Attribute = 2,
+    /*! Node is an XML comment. */      CXT_Comment = 3,
+    /*! Node is a special literal */    CXT_Literal = 4
 } CPLXMLNodeType;
 
 /**
- * Document node structure. 
+ * Document node structure.
  *
- * This C structure is used to hold a single text fragment representing a 
+ * This C structure is used to hold a single text fragment representing a
  * component of the document when parsed.   It should be allocated with the
  * appropriate CPL function, and freed with CPLDestroyXMLNode().  The structure
  * contents should not normally be altered by application code, but may be
  * freely examined by application code.
  *
- * Using the psChild and psNext pointers, a heirarchical tree structure
- * for a document can be represented as a tree of CPLXMLNode structures. 
+ * Using the psChild and psNext pointers, a hierarchical tree structure
+ * for a document can be represented as a tree of CPLXMLNode structures.
  */
 
 typedef struct CPLXMLNode
 {
-    /** 
+    /**
      * \brief Node type
      *
-     * One of CXT_Element, CXT_Text, CXT_Attribute, CXT_Comment, 
+     * One of CXT_Element, CXT_Text, CXT_Attribute, CXT_Comment,
      * or CXT_Literal.
      */
-    CPLXMLNodeType      eType;       
-    
-    /** 
+    CPLXMLNodeType      eType;
+
+    /**
      * \brief Node value
      *
      * For CXT_Element this is the name of the element, without the angle
      * brackets.  Note there is a single CXT_Element even when the document
-     * contains a start and end element tag.  The node represents the pair. 
+     * contains a start and end element tag.  The node represents the pair.
      * All text or other elements between the start and end tag will appear
-     * as children nodes of this CXT_Element node. 
+     * as children nodes of this CXT_Element node.
      *
-     * For CXT_Attribute the pszValue is the attribute name.  The value of 
-     * the attribute will be a CXT_Text child. 
+     * For CXT_Attribute the pszValue is the attribute name.  The value of
+     * the attribute will be a CXT_Text child.
      *
-     * For CXT_Text this is the text itself (value of an attribute, or a 
-     * text fragment between an element start and end tags. 
+     * For CXT_Text this is the text itself (value of an attribute, or a
+     * text fragment between an element start and end tags.
      *
      * For CXT_Literal it is all the literal text.  Currently this is just
-     * used for !DOCTYPE lines, and the value would be the entire line. 
+     * used for !DOCTYPE lines, and the value would be the entire line.
      *
-     * For CXT_Comment the value is all the literal text within the comment, 
-     * but not including the comment start/end indicators ("<--" and "-->"). 
+     * For CXT_Comment the value is all the literal text within the comment,
+     * but not including the comment start/end indicators ("<--" and "-->").
      */
-    char                *pszValue;   
+    char                *pszValue;
 
-    /** 
-     * \brief Next sibling. 
+    /**
+     * \brief Next sibling.
      *
      * Pointer to next sibling, that is the next node appearing after this
      * one that has the same parent as this node.  NULL if this node is the
-     * last child of the parent element. 
+     * last child of the parent element.
      */
-    struct CPLXMLNode  *psNext;     
+    struct CPLXMLNode  *psNext;
 
-    /** 
+    /**
      * \brief Child node.
      *
      * Pointer to first child node, if any.  Only CXT_Element and CXT_Attribute
      * nodes should have children.  For CXT_Attribute it should be a single
-     * CXT_Text value node, while CXT_Element can have any kind of child. 
-     * The full list of children for a node are identified by walking the 
-     * psNext's starting with the psChild node. 
+     * CXT_Text value node, while CXT_Element can have any kind of child.
+     * The full list of children for a node are identified by walking the
+     * psNext's starting with the psChild node.
      */
 
-    struct CPLXMLNode  *psChild;    
+    struct CPLXMLNode  *psChild;
 } CPLXMLNode;
 
 
 CPLXMLNode CPL_DLL *CPLParseXMLString( const char * );
 void       CPL_DLL  CPLDestroyXMLNode( CPLXMLNode * );
-CPLXMLNode CPL_DLL *CPLGetXMLNode( CPLXMLNode *poRoot, 
+CPLXMLNode CPL_DLL *CPLGetXMLNode( CPLXMLNode *poRoot,
                                    const char *pszPath );
-CPLXMLNode CPL_DLL *CPLSearchXMLNode( CPLXMLNode *poRoot, 
+CPLXMLNode CPL_DLL *CPLSearchXMLNode( CPLXMLNode *poRoot,
                                       const char *pszTarget );
-const char CPL_DLL *CPLGetXMLValue( CPLXMLNode *poRoot, 
-                                    const char *pszPath, 
+const char CPL_DLL *CPLGetXMLValue( CPLXMLNode *poRoot,
+                                    const char *pszPath,
                                     const char *pszDefault );
-CPLXMLNode CPL_DLL *CPLCreateXMLNode( CPLXMLNode *poParent, 
+CPLXMLNode CPL_DLL *CPLCreateXMLNode( CPLXMLNode *poParent,
                                       CPLXMLNodeType eType,
                                       const char *pszText );
 char       CPL_DLL *CPLSerializeXMLTree( const CPLXMLNode *psNode );
@@ -146,8 +146,8 @@ void       CPL_DLL CPLAddXMLAttributeAndValue( CPLXMLNode *psParent,
 CPLXMLNode CPL_DLL *CPLCloneXMLTree( CPLXMLNode *psTree );
 int        CPL_DLL CPLSetXMLValue( CPLXMLNode *psRoot,  const char *pszPath,
                                    const char *pszValue );
-void       CPL_DLL CPLStripXMLNamespace( CPLXMLNode *psRoot, 
-                                         const char *pszNameSpace, 
+void       CPL_DLL CPLStripXMLNamespace( CPLXMLNode *psRoot,
+                                         const char *pszNameSpace,
                                          int bRecurse );
 void       CPL_DLL CPLCleanXMLElementName( char * );
 
@@ -157,4 +157,25 @@ int        CPL_DLL CPLSerializeXMLTreeToFile( const CPLXMLNode *psTree,
 
 CPL_C_END
 
-#endif /* _CPL_MINIXML_H_INCLUDED */
+#ifdef __cplusplus
+// Manage a tree of XML nodes so that all nodes are freed when the instance goes
+// out of scope.  Only the top level node should be in a CPLXMLTreeCloser.
+class CPLXMLTreeCloser {
+ public:
+  explicit CPLXMLTreeCloser(CPLXMLNode* data) { the_data_ = data; }
+
+  ~CPLXMLTreeCloser() {
+    if (the_data_) CPLDestroyXMLNode(the_data_);
+  }
+
+  // Modifying the contents pointed to by the return is allowed.
+  CPLXMLNode* get() const { return the_data_; }
+
+  CPLXMLNode* operator->() const { return get(); }
+
+ private:
+  CPLXMLNode* the_data_;
+};
+#endif /* __cplusplus */
+
+#endif /* CPL_MINIXML_H_INCLUDED */
diff --git a/port/cpl_minizip_ioapi.cpp b/port/cpl_minizip_ioapi.cpp
index 189692e..8ba44d1 100644
--- a/port/cpl_minizip_ioapi.cpp
+++ b/port/cpl_minizip_ioapi.cpp
@@ -20,56 +20,13 @@
 
 #include "cpl_vsi.h"
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
 
 #include "zlib.h"
 #include "cpl_minizip_ioapi.h"
 
-
-static
-voidpf ZCALLBACK fopen_file_func OF((
-   voidpf opaque,
-   const char* filename,
-   int mode));
-
-static
-uLong ZCALLBACK fread_file_func OF((
-   voidpf opaque,
-   voidpf stream,
-   void* buf,
-   uLong size));
-
-static
-uLong ZCALLBACK fwrite_file_func OF((
-   voidpf opaque,
-   voidpf stream,
-   const void* buf,
-   uLong size));
-
-static
-uLong64 ZCALLBACK ftell_file_func OF((
-   voidpf opaque,
-   voidpf stream));
-
-static
-long ZCALLBACK fseek_file_func OF((
-   voidpf opaque,
-   voidpf stream,
-   uLong64 offset,
-   int origin));
-
-static
-int ZCALLBACK fclose_file_func OF((
-   voidpf opaque,
-   voidpf stream));
-
-static
-int ZCALLBACK ferror_file_func OF((
-   voidpf opaque,
-   voidpf stream));
-
 static
 voidpf ZCALLBACK fopen_file_func (CPL_UNUSED voidpf opaque, const char* filename, int mode)
 {
@@ -117,7 +74,6 @@ static
 long ZCALLBACK fseek_file_func (CPL_UNUSED voidpf  opaque, voidpf stream, uLong64 offset, int origin)
 {
     int fseek_origin=0;
-    long ret;
     switch (origin)
     {
     case ZLIB_FILEFUNC_SEEK_CUR :
@@ -131,27 +87,23 @@ long ZCALLBACK fseek_file_func (CPL_UNUSED voidpf  opaque, voidpf stream, uLong6
         break;
     default: return -1;
     }
-    ret = 0;
-    VSIFSeekL((VSILFILE *)stream, offset, fseek_origin);
-    return ret;
+    return VSIFSeekL((VSILFILE *)stream, offset, fseek_origin);
 }
 
 static
 int ZCALLBACK fclose_file_func (CPL_UNUSED voidpf opaque, voidpf stream)
 {
-    int ret;
-    ret = VSIFCloseL((VSILFILE *)stream);
-    return ret;
+    return VSIFCloseL((VSILFILE *)stream);
 }
 
 static
 int ZCALLBACK ferror_file_func (CPL_UNUSED voidpf opaque,
                                 CPL_UNUSED voidpf stream)
 {
-    int ret;
-    ret = 0; // FIXME
+    // int ret;
+    // ret = 0; // FIXME
     //ret = ferror((FILE *)stream);
-    return ret;
+    return 0;
 }
 
 void cpl_fill_fopen_filefunc (zlib_filefunc_def*  pzlib_filefunc_def)
diff --git a/port/cpl_minizip_ioapi.h b/port/cpl_minizip_ioapi.h
index 35156d2..15f188d 100644
--- a/port/cpl_minizip_ioapi.h
+++ b/port/cpl_minizip_ioapi.h
@@ -21,12 +21,6 @@
 #include "cpl_vsi.h"
 #define uLong64 vsi_l_offset
 
-/* Gentoo removed OF from their copy of zconf.h (https://bugs.gentoo.org/show_bug.cgi?id=383179) */
-/* but our copy of minizip needs it. */
-#ifndef OF
-#define OF(args) args
-#endif
-
 #define ZLIB_FILEFUNC_SEEK_CUR (1)
 #define ZLIB_FILEFUNC_SEEK_END (2)
 #define ZLIB_FILEFUNC_SEEK_SET (0)
@@ -51,13 +45,13 @@
 extern "C" {
 #endif
 
-typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode));
-typedef uLong  (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size));
-typedef uLong  (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
-typedef uLong64   (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream));
-typedef long   (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong64 offset, int origin));
-typedef int    (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream));
-typedef int    (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream));
+typedef voidpf (ZCALLBACK *open_file_func) (voidpf opaque, const char* filename, int mode);
+typedef uLong  (ZCALLBACK *read_file_func) (voidpf opaque, voidpf stream, void* buf, uLong size);
+typedef uLong  (ZCALLBACK *write_file_func) (voidpf opaque, voidpf stream, const void* buf, uLong size);
+typedef uLong64   (ZCALLBACK *tell_file_func) (voidpf opaque, voidpf stream);
+typedef long   (ZCALLBACK *seek_file_func) (voidpf opaque, voidpf stream, uLong64 offset, int origin);
+typedef int    (ZCALLBACK *close_file_func) (voidpf opaque, voidpf stream);
+typedef int    (ZCALLBACK *testerror_file_func) (voidpf opaque, voidpf stream);
 
 typedef struct zlib_filefunc_def_s
 {
@@ -71,9 +65,7 @@ typedef struct zlib_filefunc_def_s
     voidpf              opaque;
 } zlib_filefunc_def;
 
-
-
-void cpl_fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
+void cpl_fill_fopen_filefunc (zlib_filefunc_def* pzlib_filefunc_def);
 
 #define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size))
 #define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size))
diff --git a/port/cpl_minizip_unzip.cpp b/port/cpl_minizip_unzip.cpp
index 20670ef..d8c56b8 100644
--- a/port/cpl_minizip_unzip.cpp
+++ b/port/cpl_minizip_unzip.cpp
@@ -51,39 +51,28 @@ woven in by Terry Thorsen 1/2003.
  */
 
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
 
 #include "zlib.h"
 #include "cpl_minizip_unzip.h"
 #include "cpl_string.h"
 
-#ifdef STDC
-#  include <stddef.h>
-#  include <string.h>
-#  include <stdlib.h>
-#endif
+#include <cstddef>
+
 #ifdef NO_ERRNO_H
     extern int errno;
 #else
 #   include <errno.h>
 #endif
 
-
-#ifndef local
-#  define local static
-#endif
-/* compile with -Dlocal if your debugger can't find static symbols */
-
-
 #ifndef CASESENSITIVITYDEFAULT_NO
 #  if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
 #    define CASESENSITIVITYDEFAULT_NO
 #  endif
 #endif
 
-
 #ifndef UNZ_BUFSIZE
 #define UNZ_BUFSIZE (16384)
 #endif
@@ -106,7 +95,7 @@ woven in by Terry Thorsen 1/2003.
 const char unz_copyright[] =
    " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
 
-/* unz_file_info_interntal contain internal info about a file in zipfile*/
+/* unz_file_info_internal contain internal info about a file in zipfile */
 typedef struct unz_file_info_internal_s
 {
     uLong64 offset_curfile;/* relative offset of local header 4 bytes */
@@ -120,19 +109,19 @@ typedef struct
     char  *read_buffer;         /* internal buffer for compressed data */
     z_stream stream;            /* zLib stream structure for inflate */
 
-    uLong64 pos_in_zipfile;       /* position in byte on the zipfile, for fseek*/
-    uLong stream_initialised;   /* flag set if stream structure is initialised*/
+    uLong64 pos_in_zipfile;       /* position in byte on the zipfile, for fseek */
+    uLong stream_initialised;   /* flag set if stream structure is initialized */
 
     uLong64 offset_local_extrafield;/* offset of the local extra field */
     uInt  size_local_extrafield;/* size of the local extra field */
-    uLong64 pos_local_extrafield;   /* position in the local extra field in read*/
+    uLong64 pos_local_extrafield;   /* position in the local extra field in read */
 
     uLong crc32;                /* crc32 of all data uncompressed */
     uLong crc32_wait;           /* crc32 we must obtain after decompress all */
     uLong64 rest_read_compressed; /* number of byte to be decompressed */
-    uLong64 rest_read_uncompressed;/*number of byte to be obtained after decomp*/
+    uLong64 rest_read_uncompressed;/*number of byte to be obtained after decomp */
     zlib_filefunc_def z_filefunc;
-    voidpf filestream;        /* io structore of the zipfile */
+    voidpf filestream;        /* IO structure of the zipfile */
     uLong compression_method;   /* compression method (0==store) */
     uLong64 byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
     int   raw;
@@ -144,7 +133,7 @@ typedef struct
 typedef struct
 {
     zlib_filefunc_def z_filefunc;
-    voidpf filestream;        /* io structore of the zipfile */
+    voidpf filestream;        /* IO structure of the zipfile */
     unz_global_info gi;       /* public global information */
     uLong64 byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
     uLong64 num_file;             /* number of the current file in the zipfile*/
@@ -178,18 +167,13 @@ typedef struct
 /* ===========================================================================
      Read a byte from a gz_stream; update next_in and avail_in. Return EOF
    for end of file.
-   IN assertion: the stream s has been sucessfully opened for reading.
+   IN assertion: the stream s has been successfully opened for reading.
 */
 
 
-local int unzlocal_getByte OF((
-    const zlib_filefunc_def* pzlib_filefunc_def,
-    voidpf filestream,
-    int *pi));
-
-local int unzlocal_getByte(const zlib_filefunc_def* pzlib_filefunc_def, voidpf filestream, int *pi)
+static int unzlocal_getByte(const zlib_filefunc_def* pzlib_filefunc_def, voidpf filestream, int *pi)
 {
-    unsigned char c;
+    unsigned char c = 0;
     int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
     if (err==1)
     {
@@ -209,20 +193,13 @@ local int unzlocal_getByte(const zlib_filefunc_def* pzlib_filefunc_def, voidpf f
 /* ===========================================================================
    Reads a long in LSB order from the given gz_stream. Sets
 */
-local int unzlocal_getShort OF((
-    const zlib_filefunc_def* pzlib_filefunc_def,
-    voidpf filestream,
-    uLong *pX));
-
-local int unzlocal_getShort (const zlib_filefunc_def* pzlib_filefunc_def,
+static int unzlocal_getShort (const zlib_filefunc_def* pzlib_filefunc_def,
                              voidpf filestream,
                              uLong *pX)
 {
     uLong x ;
-    int i;
-    int err;
-
-    err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
+    int i = 0;
+    int err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
     x = (uLong)i;
 
     if (err==UNZ_OK)
@@ -236,20 +213,13 @@ local int unzlocal_getShort (const zlib_filefunc_def* pzlib_filefunc_def,
     return err;
 }
 
-local int unzlocal_getLong OF((
-    const zlib_filefunc_def* pzlib_filefunc_def,
-    voidpf filestream,
-    uLong *pX));
-
-local int unzlocal_getLong (const zlib_filefunc_def* pzlib_filefunc_def,
+static int unzlocal_getLong (const zlib_filefunc_def* pzlib_filefunc_def,
                             voidpf filestream,
                             uLong *pX)
 {
     uLong x ;
-    int i;
-    int err;
-
-    err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
+    int i = 0;
+    int err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
     x = (uLong)i;
 
     if (err==UNZ_OK)
@@ -271,21 +241,13 @@ local int unzlocal_getLong (const zlib_filefunc_def* pzlib_filefunc_def,
     return err;
 }
 
-local int unzlocal_getLong64 OF((
-    const zlib_filefunc_def* pzlib_filefunc_def,
-    voidpf filestream,
-    uLong64 *pX));
-
-
-local int unzlocal_getLong64 (const zlib_filefunc_def* pzlib_filefunc_def,
+static int unzlocal_getLong64 (const zlib_filefunc_def* pzlib_filefunc_def,
                             voidpf filestream,
                             uLong64 *pX)
 {
     uLong64 x ;
-    int i;
-    int err;
-
-    err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
+    int i = 0;
+    int err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
     x = (uLong64)i;
 
     if (err==UNZ_OK)
@@ -324,7 +286,7 @@ local int unzlocal_getLong64 (const zlib_filefunc_def* pzlib_filefunc_def,
 }
 
 /* My own strcmpi / strcasecmp */
-local int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2)
+static int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2)
 {
     for (;;)
     {
@@ -358,10 +320,10 @@ local int strcmpcasenosensitive_internal (const char* fileName1, const char* fil
 
 /*
    Compare two filename (fileName1,fileName2).
-   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
-   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
-                                                                or strcasecmp)
-   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
+   If iCaseSenisivity = 1, comparison is case sensitivity (like strcmp)
+   If iCaseSenisivity = 2, comparison is not case sensitivity (like strcmpi
+                                                               or strcasecmp)
+   If iCaseSenisivity = 0, case sensitivity is default of your operating system
         (like 1 on Unix, 2 on Windows)
 
 */
@@ -387,11 +349,7 @@ extern int ZEXPORT cpl_unzStringFileNameCompare (const char*  fileName1,
   Locate the Central directory of a zipfile (at the end, just before
     the global comment)
 */
-local uLong64 unzlocal_SearchCentralDir OF((
-    const zlib_filefunc_def* pzlib_filefunc_def,
-    voidpf filestream));
-
-local uLong64 unzlocal_SearchCentralDir(const zlib_filefunc_def* pzlib_filefunc_def,
+static uLong64 unzlocal_SearchCentralDir(const zlib_filefunc_def* pzlib_filefunc_def,
                                       voidpf filestream)
 {
     unsigned char* buf;
@@ -418,7 +376,6 @@ local uLong64 unzlocal_SearchCentralDir(const zlib_filefunc_def* pzlib_filefunc_
     {
         uLong uReadSize;
         uLong64 uReadPos ;
-        int i;
         if (uBackRead+BUFREADCOMMENT>uMaxBack)
             uBackRead = uMaxBack;
         else
@@ -433,7 +390,7 @@ local uLong64 unzlocal_SearchCentralDir(const zlib_filefunc_def* pzlib_filefunc_
         if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
             break;
 
-        for (i=(int)uReadSize-3; (i--)>0;)
+        for( int i=(int)uReadSize-3; (i--)>0;)
             if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
                 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
             {
@@ -453,11 +410,7 @@ local uLong64 unzlocal_SearchCentralDir(const zlib_filefunc_def* pzlib_filefunc_
   Locate the Central directory 64 of a zipfile (at the end, just before
     the global comment)
 */
-local uLong64 unzlocal_SearchCentralDir64 OF((
-    const zlib_filefunc_def* pzlib_filefunc_def,
-    voidpf filestream));
-
-local uLong64 unzlocal_SearchCentralDir64(const zlib_filefunc_def* pzlib_filefunc_def,
+static uLong64 unzlocal_SearchCentralDir64(const zlib_filefunc_def* pzlib_filefunc_def,
                                       voidpf filestream)
 {
     unsigned char* buf;
@@ -485,7 +438,6 @@ local uLong64 unzlocal_SearchCentralDir64(const zlib_filefunc_def* pzlib_filefun
     {
         uLong uReadSize;
         uLong64 uReadPos;
-        int i;
         if (uBackRead+BUFREADCOMMENT>uMaxBack)
             uBackRead = uMaxBack;
         else
@@ -500,7 +452,7 @@ local uLong64 unzlocal_SearchCentralDir64(const zlib_filefunc_def* pzlib_filefun
         if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
             break;
 
-        for (i=(int)uReadSize-3; (i--)>0;)
+        for( int i=(int)uReadSize-3; (i--)>0; )
             if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
                 ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07))
             {
@@ -574,7 +526,7 @@ extern unzFile ZEXPORT cpl_unzOpen2 (const char *path,
 
     uLong number_disk;          /* number of the current dist, used for
                                    spaning ZIP, unsupported, always 0*/
-    uLong number_disk_with_CD;  /* number the the disk with central dir, used
+    uLong number_disk_with_CD;  /* number the disk with central dir, used
                                    for spaning ZIP, unsupported, always 0*/
     uLong64 number_entry_CD;      /* total number of entries in
                                    the central dir
@@ -729,7 +681,9 @@ extern unzFile ZEXPORT cpl_unzOpen2 (const char *path,
     us.central_pos = central_pos;
     us.pfile_in_zip_read = NULL;
     us.encrypted = 0;
-
+    us.num_file = 0;
+    us.pos_in_central_dir = 0;
+    us.current_file_ok = 0;
 
     s=(unz_s*)ALLOC(sizeof(unz_s));
     *s=us;
@@ -780,9 +734,9 @@ extern int ZEXPORT cpl_unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_
 
 
 /*
-   Translate date/time from Dos format to tm_unz (readable more easilty)
+   Translate date/time from Dos format to tm_unz (readable more easily).
 */
-local void unzlocal_DosDateToTmuDate (uLong64 ulDosDate, tm_unz* ptm)
+static void unzlocal_DosDateToTmuDate (uLong64 ulDosDate, tm_unz* ptm)
 {
     uLong64 uDate;
     uDate = (uLong64)(ulDosDate>>16);
@@ -798,18 +752,7 @@ local void unzlocal_DosDateToTmuDate (uLong64 ulDosDate, tm_unz* ptm)
 /*
   Get Info about the current file in the zipfile, with internal only info
 */
-local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
-                                                  unz_file_info *pfile_info,
-                                                  unz_file_info_internal
-                                                  *pfile_info_internal,
-                                                  char *szFileName,
-                                                  uLong fileNameBufferSize,
-                                                  void *extraField,
-                                                  uLong extraFieldBufferSize,
-                                                  char *szComment,
-                                                  uLong commentBufferSize));
-
-local int unzlocal_GetCurrentFileInfoInternal (unzFile file,
+static int unzlocal_GetCurrentFileInfoInternal (unzFile file,
                                                unz_file_info *pfile_info,
                                                unz_file_info_internal
                                                *pfile_info_internal,
@@ -827,7 +770,7 @@ local int unzlocal_GetCurrentFileInfoInternal (unzFile file,
     uLong uMagic;
     long lSeek=0;
     uLong uL;
-    int bHasUTF8Filename = FALSE;
+    bool bHasUTF8Filename = false;
 
     if (file==NULL)
         return UNZ_PARAMERROR;
@@ -947,7 +890,10 @@ local int unzlocal_GetCurrentFileInfoInternal (unzFile file,
         if (lSeek!=0)
         {
             if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
+            {
                 lSeek=0;
+                CPL_IGNORE_RET_VAL(lSeek);
+            }
             else
                 err=UNZ_ERRNO;
         }
@@ -992,10 +938,10 @@ local int unzlocal_GetCurrentFileInfoInternal (unzFile file,
                 /* Disk Start Number */
                 if( file_info.disk_num_start == 0xFFFF )
                 {
-                    uLong uL;
-                    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
+                    uLong uLstart;
+                    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uLstart) != UNZ_OK)
                         err=UNZ_ERRNO;
-                    file_info.disk_num_start = uL;
+                    file_info.disk_num_start = uLstart;
                 }
             }
             /* Info-ZIP Unicode Path Extra Field (0x7075) */
@@ -1003,7 +949,7 @@ local int unzlocal_GetCurrentFileInfoInternal (unzFile file,
                      file_info.size_filename<=fileNameBufferSize &&
                      szFileName != NULL )
             {
-                int version;
+                int version = 0;
                 if (unzlocal_getByte(&s->z_filefunc, s->filestream,&version) != UNZ_OK)
                     err=UNZ_ERRNO;
                 if( version != 1 )
@@ -1019,12 +965,12 @@ local int unzlocal_GetCurrentFileInfoInternal (unzFile file,
                         err=UNZ_ERRNO;
 
                     /* Check expected CRC for filename */
-                    if( nameCRC32 == crc32(0, (const Bytef*)szFileName, file_info.size_filename) )
+                    if( nameCRC32 == crc32(0, (const Bytef*)szFileName, static_cast<uInt>(file_info.size_filename)) )
                     {
                         uLong utf8Size = dataSize - 1 - 4;
                         uLong uSizeRead ;
 
-                        bHasUTF8Filename = TRUE;
+                        bHasUTF8Filename = true;
 
                         if (utf8Size<fileNameBufferSize)
                         {
@@ -1059,13 +1005,13 @@ local int unzlocal_GetCurrentFileInfoInternal (unzFile file,
             acc += 2 + 2 + dataSize;
         }
     }
-    
+
     if( !bHasUTF8Filename && szFileName != NULL &&
         (file_info.flag & (1 << 11)) == 0 &&
         file_info.size_filename<fileNameBufferSize )
     {
         const char* pszSrcEncoding = CPLGetConfigOption("CPL_ZIP_ENCODING",
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(HAVE_ICONV)
                                                         "CP_OEMCP"
 #else
                                                         "CP437"
@@ -1164,7 +1110,6 @@ extern int ZEXPORT cpl_unzGoToFirstFile (unzFile file)
 extern int ZEXPORT cpl_unzGoToNextFile (unzFile  file)
 {
     unz_s* s;
-    int err;
 
     if (file==NULL)
         return UNZ_PARAMERROR;
@@ -1178,7 +1123,7 @@ extern int ZEXPORT cpl_unzGoToNextFile (unzFile  file)
     s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
             s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
     s->num_file++;
-    err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+    int err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
                                                &s->cur_file_info_internal,
                                                NULL,0,NULL,0,NULL,0);
     s->current_file_ok = (err == UNZ_OK);
@@ -1197,7 +1142,6 @@ extern int ZEXPORT cpl_unzGoToNextFile (unzFile  file)
 extern int ZEXPORT cpl_unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity)
 {
     unz_s* s;
-    int err;
 
     /* We remember the 'current' position in the file so that we can jump
      * back there if we fail.
@@ -1224,7 +1168,7 @@ extern int ZEXPORT cpl_unzLocateFile (unzFile file, const char *szFileName, int
     cur_file_infoSaved = s->cur_file_info;
     cur_file_info_internalSaved = s->cur_file_info_internal;
 
-    err = cpl_unzGoToFirstFile(file);
+    int err = cpl_unzGoToFirstFile(file);
 
     while (err == UNZ_OK)
     {
@@ -1289,7 +1233,6 @@ extern int ZEXPORT cpl_unzGetFilePos(unzFile file, unz_file_pos*  file_pos)
 extern int ZEXPORT cpl_unzGoToFilePos(unzFile file, unz_file_pos* file_pos)
 {
     unz_s* s;
-    int err;
 
     if (file==NULL || file_pos==NULL)
         return UNZ_PARAMERROR;
@@ -1300,9 +1243,9 @@ extern int ZEXPORT cpl_unzGoToFilePos(unzFile file, unz_file_pos* file_pos)
     s->num_file           = file_pos->num_of_file;
 
     /* set the current file */
-    err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
-                                               &s->cur_file_info_internal,
-                                               NULL,0,NULL,0,NULL,0);
+    int err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+                                                  &s->cur_file_info_internal,
+                                                  NULL,0,NULL,0,NULL,0);
     /* return results */
     s->current_file_ok = (err == UNZ_OK);
     return err;
@@ -1320,7 +1263,7 @@ extern int ZEXPORT cpl_unzGoToFilePos(unzFile file, unz_file_pos* file_pos)
   store in *piSizeVar the size of extra info in local header
         (filename and size of extra field data)
 */
-local int unzlocal_CheckCurrentFileCoherencyHeader (unz_s* s, uInt* piSizeVar,
+static int unzlocal_CheckCurrentFileCoherencyHeader (unz_s* s, uInt* piSizeVar,
                                                     uLong64 * poffset_local_extrafield,
                                                     uInt  * psize_local_extrafield)
 {
@@ -1470,9 +1413,9 @@ extern int ZEXPORT cpl_unzOpenCurrentFile3 (unzFile file, int* method,
         }
     }
 
-    if ((s->cur_file_info.compression_method!=0) &&
+    /*if ((s->cur_file_info.compression_method!=0) &&
         (s->cur_file_info.compression_method!=Z_DEFLATED))
-        err=UNZ_BADZIPFILE;
+        err=UNZ_BADZIPFILE;*/
 
     pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
     pfile_in_zip_read_info->crc32=0;
@@ -1487,10 +1430,10 @@ extern int ZEXPORT cpl_unzOpenCurrentFile3 (unzFile file, int* method,
     if ((s->cur_file_info.compression_method==Z_DEFLATED) &&
         (!raw))
     {
-      pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
-      pfile_in_zip_read_info->stream.zfree = (free_func)0;
-      pfile_in_zip_read_info->stream.opaque = (voidpf)0;
-      pfile_in_zip_read_info->stream.next_in = 0;
+      pfile_in_zip_read_info->stream.zalloc = (alloc_func)NULL;
+      pfile_in_zip_read_info->stream.zfree = (free_func)NULL;
+      pfile_in_zip_read_info->stream.opaque = (voidpf)NULL;
+      pfile_in_zip_read_info->stream.next_in = NULL;
       pfile_in_zip_read_info->stream.avail_in = 0;
 
       err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
@@ -1526,7 +1469,6 @@ extern int ZEXPORT cpl_unzOpenCurrentFile3 (unzFile file, int* method,
 #    ifndef NOUNCRYPT
     if (password != NULL)
     {
-        int i;
         s->pcrc_32_tab = get_crc_table();
         init_keys(password,s->keys,s->pcrc_32_tab);
         if (ZSEEK(s->z_filefunc, s->filestream,
@@ -1537,7 +1479,7 @@ extern int ZEXPORT cpl_unzOpenCurrentFile3 (unzFile file, int* method,
         if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12)
             return UNZ_INTERNALERROR;
 
-        for (i = 0; i<12; i++)
+        for( int i = 0; i<12; i++ )
             zdecode(s->keys,s->pcrc_32_tab,source[i]);
 
         s->pfile_in_zip_read->pos_in_zipfile+=12;
@@ -1587,7 +1529,7 @@ extern uLong64 ZEXPORT cpl_unzGetCurrentFileZStreamPos( unzFile file)
   buf contain buffer where data must be copied
   len the size of buf.
 
-  return the number of byte copied if somes bytes are copied
+  return the number of byte copied if some bytes are copied
   return 0 if the end of file was reached
   return <0 with error code if there is an error
     (UNZ_ERRNO for IO error, or zLib error for uncompress error)
@@ -1938,7 +1880,6 @@ extern uLong64 ZEXPORT cpl_unzGetOffset (unzFile file)
 extern int ZEXPORT cpl_unzSetOffset (unzFile file, uLong64 pos)
 {
     unz_s* s;
-    int err;
 
     if (file==NULL)
         return UNZ_PARAMERROR;
@@ -1946,9 +1887,9 @@ extern int ZEXPORT cpl_unzSetOffset (unzFile file, uLong64 pos)
 
     s->pos_in_central_dir = pos;
     s->num_file = s->gi.number_entry;      /* hack */
-    err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
-                                              &s->cur_file_info_internal,
-                                              NULL,0,NULL,0,NULL,0);
+    int err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+                                                  &s->cur_file_info_internal,
+                                                  NULL,0,NULL,0,NULL,0);
     s->current_file_ok = (err == UNZ_OK);
     return err;
 }
diff --git a/port/cpl_minizip_unzip.h b/port/cpl_minizip_unzip.h
index f60d617..b02d830 100644
--- a/port/cpl_minizip_unzip.h
+++ b/port/cpl_minizip_unzip.h
@@ -138,20 +138,20 @@ typedef struct unz_file_info_s
     tm_unz tmu_date;
 } unz_file_info;
 
-extern int ZEXPORT cpl_unzStringFileNameCompare OF ((const char* fileName1,
+extern int ZEXPORT cpl_unzStringFileNameCompare (const char* fileName1,
                                                  const char* fileName2,
-                                                 int iCaseSensitivity));
+                                                 int iCaseSensitivity);
 /*
    Compare two filename (fileName1,fileName2).
-   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
-   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
+   If iCaseSenisivity = 1, comparison is case sensitivity (like strcmp)
+   If iCaseSenisivity = 2, comparison is not case sensitivity (like strcmpi
                                 or strcasecmp)
-   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
+   If iCaseSenisivity = 0, case sensitivity is default of your operating system
     (like 1 on Unix, 2 on Windows)
 */
 
 
-extern unzFile ZEXPORT cpl_unzOpen OF((const char *path));
+extern unzFile ZEXPORT cpl_unzOpen (const char *path);
 /*
   Open a Zip file. path contain the full pathname (by example,
      on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer
@@ -162,31 +162,31 @@ extern unzFile ZEXPORT cpl_unzOpen OF((const char *path));
        of this unzip package.
 */
 
-extern unzFile ZEXPORT cpl_unzOpen2 OF((const char *path,
-                                    zlib_filefunc_def* pzlib_filefunc_def));
+extern unzFile ZEXPORT cpl_unzOpen2 (const char *path,
+                                     zlib_filefunc_def* pzlib_filefunc_def);
 /*
    Open a Zip file, like unzOpen, but provide a set of file low level API
       for read/write the zip file (see ioapi.h)
 */
 
-extern int ZEXPORT cpl_unzClose OF((unzFile file));
+extern int ZEXPORT cpl_unzClose (unzFile file);
 /*
   Close a ZipFile opened with unzipOpen.
   If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
     these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
   return UNZ_OK if there is no problem. */
 
-extern int ZEXPORT cpl_unzGetGlobalInfo OF((unzFile file,
-                                        unz_global_info *pglobal_info));
+extern int ZEXPORT cpl_unzGetGlobalInfo (unzFile file,
+                                         unz_global_info *pglobal_info);
 /*
   Write info about the ZipFile in the *pglobal_info structure.
   No preparation of the structure is needed
   return UNZ_OK if there is no problem. */
 
 
-extern int ZEXPORT cpl_unzGetGlobalComment OF((unzFile file,
-                                           char *szComment,
-                                           uLong uSizeBuf));
+extern int ZEXPORT cpl_unzGetGlobalComment (unzFile file,
+                                            char *szComment,
+                                            uLong uSizeBuf);
 /*
   Get the global comment string of the ZipFile, in the szComment buffer.
   uSizeBuf is the size of the szComment buffer.
@@ -197,22 +197,22 @@ extern int ZEXPORT cpl_unzGetGlobalComment OF((unzFile file,
 /***************************************************************************/
 /* Unzip package allow you browse the directory of the zipfile */
 
-extern int ZEXPORT cpl_unzGoToFirstFile OF((unzFile file));
+extern int ZEXPORT cpl_unzGoToFirstFile (unzFile file);
 /*
   Set the current file of the zipfile to the first file.
   return UNZ_OK if there is no problem
 */
 
-extern int ZEXPORT cpl_unzGoToNextFile OF((unzFile file));
+extern int ZEXPORT cpl_unzGoToNextFile (unzFile file);
 /*
   Set the current file of the zipfile to the next file.
   return UNZ_OK if there is no problem
   return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
 */
 
-extern int ZEXPORT cpl_unzLocateFile OF((unzFile file,
-                     const char *szFileName,
-                     int iCaseSensitivity));
+extern int ZEXPORT cpl_unzLocateFile (unzFile file,
+                                      const char *szFileName,
+                                      int iCaseSensitivity);
 /*
   Try locate the file szFileName in the zipfile.
   For the iCaseSensitivity signification, see unzStringFileNameCompare
@@ -242,19 +242,19 @@ extern int ZEXPORT cpl_unzGoToFilePos(
 
 /* ****************************************** */
 
-extern int ZEXPORT cpl_unzGetCurrentFileInfo OF((unzFile file,
-                         unz_file_info *pfile_info,
-                         char *szFileName,
-                         uLong fileNameBufferSize,
-                         void *extraField,
-                         uLong extraFieldBufferSize,
-                         char *szComment,
-                         uLong commentBufferSize));
+extern int ZEXPORT cpl_unzGetCurrentFileInfo (unzFile file,
+                                              unz_file_info *pfile_info,
+                                              char *szFileName,
+                                              uLong fileNameBufferSize,
+                                              void *extraField,
+                                              uLong extraFieldBufferSize,
+                                              char *szComment,
+                                              uLong commentBufferSize);
 /*
   Get Info about the current file
-  if pfile_info!=NULL, the *pfile_info structure will contain somes info about
+  if pfile_info!=NULL, the *pfile_info structure will contain some info about
         the current file
-  if szFileName!=NULL, the filemane string will be copied in szFileName
+  if szFileName!=NULL, the filename string will be copied in szFileName
             (fileNameBufferSize is the size of the buffer)
   if extraField!=NULL, the extra field information will be copied in extraField
             (extraFieldBufferSize is the size of the buffer).
@@ -266,7 +266,7 @@ extern int ZEXPORT cpl_unzGetCurrentFileInfo OF((unzFile file,
 
 /** Addition for GDAL : START */
 
-extern uLong64 ZEXPORT cpl_unzGetCurrentFileZStreamPos OF(( unzFile file));
+extern uLong64 ZEXPORT cpl_unzGetCurrentFileZStreamPos (unzFile file);
 
 /** Addition for GDAL : END */
 
@@ -276,24 +276,24 @@ extern uLong64 ZEXPORT cpl_unzGetCurrentFileZStreamPos OF(( unzFile file));
    from it, and close it (you can close it before reading all the file)
    */
 
-extern int ZEXPORT cpl_unzOpenCurrentFile OF((unzFile file));
+extern int ZEXPORT cpl_unzOpenCurrentFile (unzFile file);
 /*
   Open for reading data the current file in the zipfile.
   If there is no error, the return value is UNZ_OK.
 */
 
-extern int ZEXPORT cpl_unzOpenCurrentFilePassword OF((unzFile file,
-                                                  const char* password));
+extern int ZEXPORT cpl_unzOpenCurrentFilePassword (unzFile file,
+                                                   const char* password);
 /*
   Open for reading data the current file in the zipfile.
   password is a crypting password
   If there is no error, the return value is UNZ_OK.
 */
 
-extern int ZEXPORT cpl_unzOpenCurrentFile2 OF((unzFile file,
-                                           int* method,
-                                           int* level,
-                                           int raw));
+extern int ZEXPORT cpl_unzOpenCurrentFile2 (unzFile file,
+                                            int* method,
+                                            int* level,
+                                            int raw);
 /*
   Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
     if raw==1
@@ -303,11 +303,11 @@ extern int ZEXPORT cpl_unzOpenCurrentFile2 OF((unzFile file,
          but you CANNOT set method parameter as NULL
 */
 
-extern int ZEXPORT cpl_unzOpenCurrentFile3 OF((unzFile file,
-                                           int* method,
-                                           int* level,
-                                           int raw,
-                                           const char* password));
+extern int ZEXPORT cpl_unzOpenCurrentFile3 (unzFile file,
+                                            int* method,
+                                            int* level,
+                                            int raw,
+                                            const char* password);
 /*
   Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
     if raw==1
@@ -318,39 +318,39 @@ extern int ZEXPORT cpl_unzOpenCurrentFile3 OF((unzFile file,
 */
 
 
-extern int ZEXPORT cpl_unzCloseCurrentFile OF((unzFile file));
+extern int ZEXPORT cpl_unzCloseCurrentFile (unzFile file);
 /*
   Close the file in zip opened with unzOpenCurrentFile
   Return UNZ_CRCERROR if all the file was read but the CRC is not good
 */
 
-extern int ZEXPORT cpl_unzReadCurrentFile OF((unzFile file,
-                      voidp buf,
-                      unsigned len));
+extern int ZEXPORT cpl_unzReadCurrentFile (unzFile file,
+                                           voidp buf,
+                                           unsigned len);
 /*
   Read bytes from the current file (opened by unzOpenCurrentFile)
   buf contain buffer where data must be copied
   len the size of buf.
 
-  return the number of byte copied if somes bytes are copied
+  return the number of byte copied if some bytes are copied
   return 0 if the end of file was reached
   return <0 with error code if there is an error
     (UNZ_ERRNO for IO error, or zLib error for uncompress error)
 */
 
-extern z_off_t ZEXPORT cpl_unztell OF((unzFile file));
+extern z_off_t ZEXPORT cpl_unztell (unzFile file);
 /*
   Give the current position in uncompressed data
 */
 
-extern int ZEXPORT cpl_unzeof OF((unzFile file));
+extern int ZEXPORT cpl_unzeof (unzFile file);
 /*
   return 1 if the end of file was reached, 0 elsewhere
 */
 
-extern int ZEXPORT cpl_unzGetLocalExtrafield OF((unzFile file,
-                                             voidp buf,
-                                             unsigned len));
+extern int ZEXPORT cpl_unzGetLocalExtrafield (unzFile file,
+                                              voidp buf,
+                                              unsigned len);
 /*
   Read extra field from the current file (opened by unzOpenCurrentFile)
   This is the local-header version of the extra field (sometimes, there is
diff --git a/port/cpl_minizip_zip.cpp b/port/cpl_minizip_zip.cpp
index b5c94e7..fda7b88 100644
--- a/port/cpl_minizip_zip.cpp
+++ b/port/cpl_minizip_zip.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_minizip_zip.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: cpl_minizip_zip.cpp 33724 2016-03-16 17:14:11Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Author:   Frank Warmerdam, warmerdam at pobox.com
@@ -11,7 +11,7 @@
  *   - Remove old C style function prototypes
  *   - Added CPL* simplified API at bottom.
  *
- *   Original licence available in port/LICENCE_minizip
+ *   Original license available in port/LICENCE_minizip
  *
  *****************************************************************************/
 
@@ -28,44 +28,32 @@
 */
 
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
 #include "zlib.h"
 #include "cpl_conv.h"
 #include "cpl_minizip_zip.h"
 #include "cpl_port.h"
 #include "cpl_string.h"
 
-#ifdef STDC
-#  include <stddef.h>
-#  include <string.h>
-#  include <stdlib.h>
-#endif
+#include <cstddef>
+
 #ifdef NO_ERRNO_H
     extern int errno;
 #else
 #   include <errno.h>
 #endif
 
-#ifndef local
-#  define local static
-#endif
-/* compile with -Dlocal if your debugger can't find static symbols */
-
 #ifndef VERSIONMADEBY
-# define VERSIONMADEBY   (0x0) /* platform depedent */
+# define VERSIONMADEBY   (0x0) /* platform dependent */
 #endif
 
 #ifndef Z_BUFSIZE
 #define Z_BUFSIZE (16384)
 #endif
 
-#ifndef Z_MAXFILENAMEINZIP
-#define Z_MAXFILENAMEINZIP (256)
-#endif
-
 #ifndef ALLOC
 # define ALLOC(size) (malloc(size))
 #endif
@@ -78,7 +66,7 @@
 #define SIZEZIPLOCALHEADER (0x1e)
 */
 
-/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
+/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined... */
 
 #ifndef SEEK_CUR
 #define SEEK_CUR    1
@@ -120,7 +108,7 @@ typedef struct linkedlist_datablock_internal_s
   struct linkedlist_datablock_internal_s* next_datablock;
   uLong  avail_in_this_block;
   uLong  filled_in_this_block;
-  uLong  unused; /* for future use and alignement */
+  uLong  unused;  // For future use and alignment.
   unsigned char data[SIZEDATA_INDATABLOCK];
 } linkedlist_datablock_internal;
 
@@ -138,14 +126,16 @@ typedef struct
     uInt pos_in_buffered_data;  /* last written byte in buffered_data */
 
     uLong pos_local_header;     /* offset of the local header of the file
-                                     currenty writing */
+                                     currently writing */
     char* central_header;       /* central header data for the current file */
     uLong size_centralheader;   /* size of the central header for cur file */
     uLong flag;                 /* flag of the file currently writing */
 
-    int  method;                /* compression method of file currenty wr.*/
+    // TODO: What is "wr"?  "to"?
+    int  method;                /* compression method of file currently wr.*/
     int  raw;                   /* 1 for directly writing raw data */
-    Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/
+    Byte buffered_data[Z_BUFSIZE]; /* buffer contain compressed data to be
+                                        written. */
     uLong dosDate;
     uLong crc32;
     int  encrypt;
@@ -159,13 +149,13 @@ typedef struct
 typedef struct
 {
     zlib_filefunc_def z_filefunc;
-    voidpf filestream;        /* io structore of the zipfile */
+    voidpf filestream;        /* IO structure of the zipfile */
     linkedlist_data central_dir;/* datablock with central dir in construction*/
     int  in_opened_file_inzip;  /* 1 if a file in the zip is currently writ.*/
-    curfile_info ci;            /* info on the file curretly writing */
+    curfile_info ci;            /* info on the file currently writing */
 
     uLong begin_pos;            /* position of the beginning of the zipfile */
-    uLong add_position_when_writting_offset;
+    uLong add_position_when_writing_offset;
     uLong number_entry;
 #ifndef NO_ADDFILEINEXISTINGZIP
     char *globalcomment;
@@ -179,7 +169,7 @@ typedef struct
 #include "crypt.h"
 #endif
 
-local linkedlist_datablock_internal* allocate_new_datablock()
+static linkedlist_datablock_internal* allocate_new_datablock()
 {
     linkedlist_datablock_internal* ldi;
     ldi = (linkedlist_datablock_internal*)
@@ -193,7 +183,7 @@ local linkedlist_datablock_internal* allocate_new_datablock()
     return ldi;
 }
 
-local void free_datablock(linkedlist_datablock_internal*ldi)
+static void free_datablock(linkedlist_datablock_internal*ldi)
 {
     while (ldi!=NULL)
     {
@@ -203,12 +193,12 @@ local void free_datablock(linkedlist_datablock_internal*ldi)
     }
 }
 
-local void init_linkedlist(linkedlist_data*ll)
+static void init_linkedlist(linkedlist_data*ll)
 {
     ll->first_block = ll->last_block = NULL;
 }
 
-local int add_data_in_datablock(linkedlist_data*ll,
+static int add_data_in_datablock(linkedlist_data*ll,
                                 const void *buf, uLong len)
 {
     linkedlist_datablock_internal* ldi;
@@ -270,22 +260,18 @@ local int add_data_in_datablock(linkedlist_data*ll,
    nbByte == 1, 2 or 4 (byte, short or long)
 */
 
-local int ziplocal_putValue OF((const zlib_filefunc_def* pzlib_filefunc_def,
-                                voidpf filestream, uLong x, int nbByte));
-
-local int ziplocal_putValue (const zlib_filefunc_def*pzlib_filefunc_def, 
-                             voidpf filestream, uLong x, int nbByte)
+static int ziplocal_putValue (const zlib_filefunc_def*pzlib_filefunc_def,
+                              voidpf filestream, uLong x, int nbByte)
 {
     unsigned char buf[4];
-    int n;
-    for (n = 0; n < nbByte; n++)
+    for (int n = 0; n < nbByte; n++)
     {
         buf[n] = (unsigned char)(x & 0xff);
         x >>= 8;
     }
     if (x != 0)
       {     /* data overflow - hack for ZIP64 (X Roche) */
-      for (n = 0; n < nbByte; n++)
+      for (int n = 0; n < nbByte; n++)
         {
           buf[n] = 0xff;
         }
@@ -297,19 +283,17 @@ local int ziplocal_putValue (const zlib_filefunc_def*pzlib_filefunc_def,
         return ZIP_OK;
 }
 
-local void ziplocal_putValue_inmemory OF((void* dest, uLong x, int nbByte));
-local void ziplocal_putValue_inmemory (void *dest, uLong x, int nbByte)
+static void ziplocal_putValue_inmemory (void *dest, uLong x, int nbByte)
 {
     unsigned char* buf=(unsigned char*)dest;
-    int n;
-    for (n = 0; n < nbByte; n++) {
+    for (int n = 0; n < nbByte; n++) {
         buf[n] = (unsigned char)(x & 0xff);
         x >>= 8;
     }
 
     if (x != 0)
     {     /* data overflow - hack for ZIP64 */
-       for (n = 0; n < nbByte; n++)
+       for (int n = 0; n < nbByte; n++)
        {
           buf[n] = 0xff;
        }
@@ -319,7 +303,7 @@ local void ziplocal_putValue_inmemory (void *dest, uLong x, int nbByte)
 /****************************************************************************/
 
 
-local uLong ziplocal_TmzDateToDosDate(const tm_zip *ptm,
+static uLong ziplocal_TmzDateToDosDate(const tm_zip *ptm,
                                       CPL_UNUSED uLong dosDate)
 {
     uLong year = (uLong)ptm->tm_year;
@@ -335,15 +319,10 @@ local uLong ziplocal_TmzDateToDosDate(const tm_zip *ptm,
 
 /****************************************************************************/
 
-local int ziplocal_getByte OF((
-    const zlib_filefunc_def* pzlib_filefunc_def,
-    voidpf filestream,
-    int *pi));
-
-local int ziplocal_getByte(const zlib_filefunc_def* pzlib_filefunc_def,
-                           voidpf filestream, int *pi)
+static int ziplocal_getByte(const zlib_filefunc_def* pzlib_filefunc_def,
+                            voidpf filestream, int *pi)
 {
-    unsigned char c;
+    unsigned char c = 0;
     int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
     if (err==1)
     {
@@ -363,20 +342,12 @@ local int ziplocal_getByte(const zlib_filefunc_def* pzlib_filefunc_def,
 /* ===========================================================================
    Reads a long in LSB order from the given gz_stream. Sets
 */
-local int ziplocal_getShort OF((
-    const zlib_filefunc_def* pzlib_filefunc_def,
-    voidpf filestream,
-    uLong *pX));
-
-local int ziplocal_getShort (const zlib_filefunc_def* pzlib_filefunc_def,
-                             voidpf filestream, uLong *pX)
+static int ziplocal_getShort (const zlib_filefunc_def* pzlib_filefunc_def,
+                              voidpf filestream, uLong *pX)
 {
-    uLong x ;
-    int i;
-    int err;
-
-    err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
-    x = (uLong)i;
+    int i = 0;
+    int err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
+    uLong x = (uLong)i;
 
     if (err==ZIP_OK)
         err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
@@ -389,22 +360,14 @@ local int ziplocal_getShort (const zlib_filefunc_def* pzlib_filefunc_def,
     return err;
 }
 
-local int ziplocal_getLong OF((
-    const zlib_filefunc_def* pzlib_filefunc_def,
-    voidpf filestream,
-    uLong *pX));
-
-local int ziplocal_getLong (
+static int ziplocal_getLong (
     const zlib_filefunc_def* pzlib_filefunc_def,
     voidpf filestream,
     uLong *pX )
 {
-    uLong x ;
-    int i;
-    int err;
-
-    err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
-    x = (uLong)i;
+    int i = 0;
+    int err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
+    uLong x = (uLong)i;
 
     if (err==ZIP_OK)
         err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
@@ -432,45 +395,35 @@ local int ziplocal_getLong (
   Locate the Central directory of a zipfile (at the end, just before
     the global comment)
 */
-local uLong ziplocal_SearchCentralDir OF((
-    const zlib_filefunc_def* pzlib_filefunc_def,
-    voidpf filestream));
-
-local uLong ziplocal_SearchCentralDir(
+static uLong ziplocal_SearchCentralDir(
     const zlib_filefunc_def* pzlib_filefunc_def,
     voidpf filestream )
 {
-    unsigned char* buf;
-    uLong uSizeFile;
-    uLong uBackRead;
     uLong uMaxBack=0xffff; /* maximum size of global comment */
     uLong uPosFound=0;
 
     if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
         return 0;
 
-
-    uSizeFile = (uLong) ZTELL(*pzlib_filefunc_def,filestream);
+    uLong uSizeFile = (uLong) ZTELL(*pzlib_filefunc_def,filestream);
 
     if (uMaxBack>uSizeFile)
         uMaxBack = uSizeFile;
 
-    buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
+    unsigned char* buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
     if (buf==NULL)
         return 0;
 
-    uBackRead = 4;
+    uLong uBackRead = 4;
     while (uBackRead<uMaxBack)
     {
-        uLong uReadSize,uReadPos ;
-        int i;
         if (uBackRead+BUFREADCOMMENT>uMaxBack)
             uBackRead = uMaxBack;
         else
             uBackRead+=BUFREADCOMMENT;
-        uReadPos = uSizeFile-uBackRead ;
+        uLong uReadPos = uSizeFile-uBackRead ;
 
-        uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
+        uLong uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
                      (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
         if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
             break;
@@ -478,7 +431,7 @@ local uLong ziplocal_SearchCentralDir(
         if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
             break;
 
-        for (i=(int)uReadSize-3; (i--)>0;)
+        for (int i=(int)uReadSize-3; (i--)>0;)
             if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
                 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
             {
@@ -502,9 +455,6 @@ extern zipFile ZEXPORT cpl_zipOpen2 (
     zlib_filefunc_def* pzlib_filefunc_def )
 {
     zip_internal ziinit;
-    zip_internal* zi;
-    int err=ZIP_OK;
-
 
     if (pzlib_filefunc_def==NULL)
         cpl_fill_fopen_filefunc(&ziinit.z_filefunc);
@@ -524,11 +474,10 @@ extern zipFile ZEXPORT cpl_zipOpen2 (
     ziinit.in_opened_file_inzip = 0;
     ziinit.ci.stream_initialised = 0;
     ziinit.number_entry = 0;
-    ziinit.add_position_when_writting_offset = 0;
+    ziinit.add_position_when_writing_offset = 0;
     init_linkedlist(&(ziinit.central_dir));
 
-
-    zi = (zip_internal*)ALLOC(sizeof(zip_internal));
+    zip_internal* zi = (zip_internal*)ALLOC(sizeof(zip_internal));
     if (zi==NULL)
     {
         ZCLOSE(ziinit.z_filefunc,ziinit.filestream);
@@ -538,6 +487,8 @@ extern zipFile ZEXPORT cpl_zipOpen2 (
     /* now we add file in a zipfile */
 #    ifndef NO_ADDFILEINEXISTINGZIP
     ziinit.globalcomment = NULL;
+
+    int err=ZIP_OK;
     if (append == APPEND_STATUS_ADDINZIP)
     {
         uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
@@ -548,7 +499,7 @@ extern zipFile ZEXPORT cpl_zipOpen2 (
 
         uLong number_disk;          /* number of the current dist, used for
                                     spaning ZIP, unsupported, always 0*/
-        uLong number_disk_with_CD;  /* number the the disk with central dir, used
+        uLong number_disk_with_CD;  /* number the disk with central dir, used
                                     for spaning ZIP, unsupported, always 0*/
         uLong number_entry;
         uLong number_entry_CD;      /* total number of entries in
@@ -609,6 +560,7 @@ extern zipFile ZEXPORT cpl_zipOpen2 (
         if (err!=ZIP_OK)
         {
             ZCLOSE(ziinit.z_filefunc, ziinit.filestream);
+            TRYFREE(zi);
             return NULL;
         }
 
@@ -624,7 +576,7 @@ extern zipFile ZEXPORT cpl_zipOpen2 (
 
         byte_before_the_zipfile = central_pos -
                                 (offset_central_dir+size_central_dir);
-        ziinit.add_position_when_writting_offset = byte_before_the_zipfile;
+        ziinit.add_position_when_writing_offset = byte_before_the_zipfile;
 
         {
             uLong size_central_dir_to_read = size_central_dir;
@@ -754,8 +706,10 @@ extern int ZEXPORT cpl_zipOpenNewFileInZip3 (
       zi->ci.flag |= 4;
     if (level==1)
       zi->ci.flag |= 6;
+#ifndef NOCRYPT
     if (password != NULL)
       zi->ci.flag |= 1;
+#endif
 
     zi->ci.crc32 = 0;
     zi->ci.method = method;
@@ -793,7 +747,7 @@ extern int ZEXPORT cpl_zipOpenNewFileInZip3 (
     else
         ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4);
 
-    ziplocal_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header- zi->add_position_when_writting_offset,4);
+    ziplocal_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header- zi->add_position_when_writing_offset,4);
 
     for (i=0;i<size_filename;i++)
         *(zi->ci.central_header+SIZECENTRALHEADER+i) = *(filename+i);
@@ -852,9 +806,9 @@ extern int ZEXPORT cpl_zipOpenNewFileInZip3 (
 
     if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
     {
-        zi->ci.stream.zalloc = (alloc_func)0;
-        zi->ci.stream.zfree = (free_func)0;
-        zi->ci.stream.opaque = (voidpf)0;
+        zi->ci.stream.zalloc = (alloc_func)NULL;
+        zi->ci.stream.zfree = (free_func)NULL;
+        zi->ci.stream.opaque = (voidpf)NULL;
 
         if (windowBits>0)
             windowBits = -windowBits;
@@ -870,7 +824,7 @@ extern int ZEXPORT cpl_zipOpenNewFileInZip3 (
     if ((err==Z_OK) && (password != NULL))
     {
         unsigned char bufHead[RAND_HEAD_LEN];
-        unsigned int sizeHead;
+        unsigned int sizeHead = 0;
         zi->ci.encrypt = 1;
         zi->ci.pcrc_32_tab = get_crc_table();
         /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/
@@ -927,7 +881,7 @@ extern int ZEXPORT cpl_zipOpenNewFileInZip (
                                  comment, method, level, 0);
 }
 
-local int zipFlushWriteBuffer(
+static int zipFlushWriteBuffer(
     zip_internal* zi )
 {
     int err=ZIP_OK;
@@ -935,9 +889,8 @@ local int zipFlushWriteBuffer(
     if (zi->ci.encrypt != 0)
     {
 #ifndef NOCRYPT
-        uInt i;
-        int t;
-        for (i=0;i<zi->ci.pos_in_buffered_data;i++)
+        int t = 0;
+        for (uInt i=0;i<zi->ci.pos_in_buffered_data;i++)
             zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab,
                                        zi->ci.buffered_data[i],t);
 #endif
@@ -954,12 +907,10 @@ extern int ZEXPORT cpl_zipWriteInFileInZip (
     const void* buf,
     unsigned len )
 {
-    zip_internal* zi;
-    int err=ZIP_OK;
-
     if (file == NULL)
         return ZIP_PARAMERROR;
-    zi = (zip_internal*)file;
+
+    zip_internal* zi = (zip_internal*)file;
 
     if (zi->in_opened_file_inzip == 0)
         return ZIP_PARAMERROR;
@@ -968,6 +919,7 @@ extern int ZEXPORT cpl_zipWriteInFileInZip (
     zi->ci.stream.avail_in = len;
     zi->ci.crc32 = crc32(zi->ci.crc32,(const Bytef *) buf,len);
 
+    int err=ZIP_OK;
     while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0))
     {
         if (zi->ci.stream.avail_out == 0)
@@ -991,12 +943,12 @@ extern int ZEXPORT cpl_zipWriteInFileInZip (
         }
         else
         {
-            uInt copy_this,i;
+            uInt copy_this;
             if (zi->ci.stream.avail_in < zi->ci.stream.avail_out)
                 copy_this = zi->ci.stream.avail_in;
             else
                 copy_this = zi->ci.stream.avail_out;
-            for (i=0;i<copy_this;i++)
+            for (uInt i=0;i<copy_this;i++)
                 *(((char*)zi->ci.stream.next_out)+i) =
                     *(((const char*)zi->ci.stream.next_in)+i);
             {
@@ -1019,32 +971,34 @@ extern int ZEXPORT cpl_zipCloseFileInZipRaw (
     uLong uncompressed_size,
     uLong crc32 )
 {
-    zip_internal* zi;
-    uLong compressed_size;
-    int err=ZIP_OK;
-
     if (file == NULL)
         return ZIP_PARAMERROR;
-    zi = (zip_internal*)file;
+
+    zip_internal* zi = (zip_internal*)file;
 
     if (zi->in_opened_file_inzip == 0)
         return ZIP_PARAMERROR;
     zi->ci.stream.avail_in = 0;
 
+    int err=ZIP_OK;
     if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
-        while (err==ZIP_OK)
     {
-        uLong uTotalOutBefore;
-        if (zi->ci.stream.avail_out == 0)
+        while (err==ZIP_OK)
         {
-            if (zipFlushWriteBuffer(zi) == ZIP_ERRNO)
-                err = ZIP_ERRNO;
-            zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
-            zi->ci.stream.next_out = zi->ci.buffered_data;
+            if (zi->ci.stream.avail_out == 0)
+            {
+                if (zipFlushWriteBuffer(zi) == ZIP_ERRNO)
+                {
+                    err = ZIP_ERRNO;
+                    break;
+                }
+                zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
+                zi->ci.stream.next_out = zi->ci.buffered_data;
+            }
+            uLong uTotalOutBefore = zi->ci.stream.total_out;
+            err=deflate(&zi->ci.stream,  Z_FINISH);
+            zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
         }
-        uTotalOutBefore = zi->ci.stream.total_out;
-        err=deflate(&zi->ci.stream,  Z_FINISH);
-        zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
     }
 
     if (err==Z_STREAM_END)
@@ -1065,10 +1019,10 @@ extern int ZEXPORT cpl_zipCloseFileInZipRaw (
         crc32 = (uLong)zi->ci.crc32;
         uncompressed_size = (uLong)zi->ci.stream.total_in;
     }
-    compressed_size = (uLong)zi->ci.stream.total_out;
-#    ifndef NOCRYPT
+    uLong compressed_size = (uLong)zi->ci.stream.total_out;
+#ifndef NOCRYPT
     compressed_size += zi->ci.crypt_header_size;
-#    endif
+#endif
 
     ziplocal_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/
     ziplocal_putValue_inmemory(zi->ci.central_header+20,
@@ -1120,14 +1074,15 @@ extern int ZEXPORT cpl_zipClose (
     zipFile file,
     const char* global_comment)
 {
-    zip_internal* zi;
     int err = 0;
     uLong size_centraldir = 0;
     uLong centraldir_pos_inzip;
     uInt size_global_comment;
+
     if (file == NULL)
         return ZIP_PARAMERROR;
-    zi = (zip_internal*)file;
+
+    zip_internal* zi = (zip_internal*)file;
 
     if (zi->in_opened_file_inzip == 1)
     {
@@ -1182,7 +1137,7 @@ extern int ZEXPORT cpl_zipClose (
     if (err==ZIP_OK) /* offset of start of central directory with respect to the
                             starting disk number */
         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,
-                                (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4);
+                                (uLong)(centraldir_pos_inzip - zi->add_position_when_writing_offset),4);
 
     if (err==ZIP_OK) /* zipfile comment length */
         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2);
@@ -1226,9 +1181,7 @@ typedef struct
 void *CPLCreateZip( const char *pszZipFilename, char **papszOptions )
 
 {
-    (void) papszOptions;
-
-    int bAppend = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "APPEND", "FALSE"));
+    bool bAppend = CPL_TO_BOOL(CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "APPEND", "FALSE")));
     char** papszFilenames = NULL;
 
     if( bAppend )
@@ -1259,7 +1212,7 @@ void *CPLCreateZip( const char *pszZipFilename, char **papszOptions )
         CSLDestroy(papszFilenames);
         return NULL;
     }
-    
+
     CPLZip* psZip = (CPLZip*)CPLMalloc(sizeof(CPLZip));
     psZip->hZip = hZip;
     psZip->papszFilenames = papszFilenames;
@@ -1270,17 +1223,14 @@ void *CPLCreateZip( const char *pszZipFilename, char **papszOptions )
 /*                         CPLCreateFileInZip()                         */
 /************************************************************************/
 
-CPLErr CPLCreateFileInZip( void *hZip, const char *pszFilename, 
+CPLErr CPLCreateFileInZip( void *hZip, const char *pszFilename,
                            char **papszOptions )
 
 {
-    int  nErr;
+    if( hZip == NULL )
+        return CE_Failure;
 
-    (void) papszOptions;
-    
     CPLZip* psZip = (CPLZip*)hZip;
-    if( psZip == NULL )
-        return CE_Failure;
 
     if( CSLFindString(psZip->papszFilenames, pszFilename ) >= 0)
     {
@@ -1291,17 +1241,15 @@ CPLErr CPLCreateFileInZip( void *hZip, const char *pszFilename,
 
     int bCompressed = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "COMPRESSED", "TRUE"));
 
-    nErr = cpl_zipOpenNewFileInZip( psZip->hZip, pszFilename, NULL, 
-                                    NULL, 0, NULL, 0, "", 
+    int nErr = cpl_zipOpenNewFileInZip( psZip->hZip, pszFilename, NULL,
+                                    NULL, 0, NULL, 0, "",
                                     bCompressed ? Z_DEFLATED : 0, bCompressed ? Z_DEFAULT_COMPRESSION : 0 );
 
     if( nErr != ZIP_OK )
         return CE_Failure;
-    else
-    {
-        psZip->papszFilenames = CSLAddString(psZip->papszFilenames, pszFilename);
-        return CE_None;
-    }
+
+    psZip->papszFilenames = CSLAddString(psZip->papszFilenames, pszFilename);
+    return CE_None;
 }
 
 /************************************************************************/
@@ -1311,19 +1259,18 @@ CPLErr CPLCreateFileInZip( void *hZip, const char *pszFilename,
 CPLErr CPLWriteFileInZip( void *hZip, const void *pBuffer, int nBufferSize )
 
 {
-    int nErr;
+    if( hZip == NULL )
+        return CE_Failure;
 
     CPLZip* psZip = (CPLZip*)hZip;
-    if( psZip == NULL )
-        return CE_Failure;
 
-    nErr = cpl_zipWriteInFileInZip( psZip->hZip, pBuffer, 
+    int nErr = cpl_zipWriteInFileInZip( psZip->hZip, pBuffer,
                                     (unsigned int) nBufferSize );
 
     if( nErr != ZIP_OK )
         return CE_Failure;
-    else
-        return CE_None;
+
+    return CE_None;
 }
 
 /************************************************************************/
@@ -1333,18 +1280,17 @@ CPLErr CPLWriteFileInZip( void *hZip, const void *pBuffer, int nBufferSize )
 CPLErr CPLCloseFileInZip( void *hZip )
 
 {
-    int nErr;
+    if( hZip == NULL )
+        return CE_Failure;
 
     CPLZip* psZip = (CPLZip*)hZip;
-    if( psZip == NULL )
-        return CE_Failure;
 
-    nErr = cpl_zipCloseFileInZip( psZip->hZip );
+    int nErr = cpl_zipCloseFileInZip( psZip->hZip );
 
     if( nErr != ZIP_OK )
         return CE_Failure;
-    else
-        return CE_None;
+
+    return CE_None;
 }
 
 /************************************************************************/
@@ -1354,13 +1300,12 @@ CPLErr CPLCloseFileInZip( void *hZip )
 CPLErr CPLCloseZip( void *hZip )
 
 {
-    int nErr;
+    if( hZip == NULL )
+        return CE_Failure;
 
     CPLZip* psZip = (CPLZip*)hZip;
-    if( psZip == NULL )
-        return CE_Failure;
 
-    nErr = cpl_zipClose(psZip->hZip, NULL);
+    int nErr = cpl_zipClose(psZip->hZip, NULL);
 
     psZip->hZip = NULL;
     CSLDestroy(psZip->papszFilenames);
@@ -1369,6 +1314,6 @@ CPLErr CPLCloseZip( void *hZip )
 
     if( nErr != ZIP_OK )
         return CE_Failure;
-    else
-        return CE_None;
+
+    return CE_None;
 }
diff --git a/port/cpl_minizip_zip.h b/port/cpl_minizip_zip.h
index f5dae03..b086990 100644
--- a/port/cpl_minizip_zip.h
+++ b/port/cpl_minizip_zip.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_minizip_zip.h 20794 2010-10-08 16:58:27Z warmerdam $
+ * $Id: cpl_minizip_zip.h 31826 2015-11-29 15:39:57Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Author:   Frank Warmerdam, warmerdam at pobox.com
@@ -135,7 +135,7 @@ typedef const char* zipcharpc;
 #define APPEND_STATUS_CREATEAFTER   (1)
 #define APPEND_STATUS_ADDINZIP      (2)
 
-extern zipFile ZEXPORT cpl_zipOpen OF((const char *pathname, int append));
+extern zipFile ZEXPORT cpl_zipOpen (const char *pathname, int append);
 /*
   Create a zipfile.
      pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on
@@ -150,72 +150,72 @@ extern zipFile ZEXPORT cpl_zipOpen OF((const char *pathname, int append));
        of this zip package.
 */
 
-/* Note : there is no delete function into a zipfile.
-   If you want delete file into a zipfile, you must open a zipfile, and create another
-   Of couse, you can use RAW reading and writing to copy the file you did not want delte
+/* Note : there is no delete function for a zipfile.
+   If you want delete file in a zipfile, you must open a zipfile, and create another.
+   Of course, you can use RAW reading and writing to copy the file you did not want delete.
 */
 
-extern zipFile ZEXPORT cpl_zipOpen2 OF((const char *pathname,
-                                   int append,
-                                   zipcharpc* globalcomment,
-                                   zlib_filefunc_def* pzlib_filefunc_def));
-
-extern int ZEXPORT cpl_zipOpenNewFileInZip OF((zipFile file,
-                       const char* filename,
-                       const zip_fileinfo* zipfi,
-                       const void* extrafield_local,
-                       uInt size_extrafield_local,
-                       const void* extrafield_global,
-                       uInt size_extrafield_global,
-                       const char* comment,
-                       int method,
-                       int level));
+extern zipFile ZEXPORT cpl_zipOpen2 (const char *pathname,
+                                     int append,
+                                     zipcharpc* globalcomment,
+                                     zlib_filefunc_def* pzlib_filefunc_def);
+
+extern int ZEXPORT cpl_zipOpenNewFileInZip (zipFile file,
+                                            const char* filename,
+                                            const zip_fileinfo* zipfi,
+                                            const void* extrafield_local,
+                                            uInt size_extrafield_local,
+                                            const void* extrafield_global,
+                                            uInt size_extrafield_global,
+                                            const char* comment,
+                                            int method,
+                                            int level);
 /*
   Open a file in the ZIP for writing.
   filename : the filename in zip (if NULL, '-' without quote will be used
   *zipfi contain supplemental information
   if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local
-    contains the extrafield data the the local header
+    contains the extrafield data the local header
   if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global
-    contains the extrafield data the the local header
+    contains the extrafield data the local header
   if comment != NULL, comment contain the comment string
   method contain the compression method (0 for store, Z_DEFLATED for deflate)
   level contain the level of compression (can be Z_DEFAULT_COMPRESSION)
 */
 
 
-extern int ZEXPORT cpl_zipOpenNewFileInZip2 OF((zipFile file,
-                                            const char* filename,
-                                            const zip_fileinfo* zipfi,
-                                            const void* extrafield_local,
-                                            uInt size_extrafield_local,
-                                            const void* extrafield_global,
-                                            uInt size_extrafield_global,
-                                            const char* comment,
-                                            int method,
-                                            int level,
-                                            int raw));
+extern int ZEXPORT cpl_zipOpenNewFileInZip2 (zipFile file,
+                                             const char* filename,
+                                             const zip_fileinfo* zipfi,
+                                             const void* extrafield_local,
+                                             uInt size_extrafield_local,
+                                             const void* extrafield_global,
+                                             uInt size_extrafield_global,
+                                             const char* comment,
+                                             int method,
+                                             int level,
+                                             int raw);
 
 /*
   Same than zipOpenNewFileInZip, except if raw=1, we write raw file
  */
 
-extern int ZEXPORT cpl_zipOpenNewFileInZip3 OF((zipFile file,
-                                            const char* filename,
-                                            const zip_fileinfo* zipfi,
-                                            const void* extrafield_local,
-                                            uInt size_extrafield_local,
-                                            const void* extrafield_global,
-                                            uInt size_extrafield_global,
-                                            const char* comment,
-                                            int method,
-                                            int level,
-                                            int raw,
-                                            int windowBits,
-                                            int memLevel,
-                                            int strategy,
-                                            const char* password,
-                                            uLong crcForCtypting));
+extern int ZEXPORT cpl_zipOpenNewFileInZip3 (zipFile file,
+                                             const char* filename,
+                                             const zip_fileinfo* zipfi,
+                                             const void* extrafield_local,
+                                             uInt size_extrafield_local,
+                                             const void* extrafield_global,
+                                             uInt size_extrafield_global,
+                                             const char* comment,
+                                             int method,
+                                             int level,
+                                             int raw,
+                                             int windowBits,
+                                             int memLevel,
+                                             int strategy,
+                                             const char* password,
+                                             uLong crcForCtypting);
 
 /*
   Same than zipOpenNewFileInZip2, except
@@ -225,29 +225,29 @@ extern int ZEXPORT cpl_zipOpenNewFileInZip3 OF((zipFile file,
  */
 
 
-extern int ZEXPORT cpl_zipWriteInFileInZip OF((zipFile file,
-                       const void* buf,
-                       unsigned len));
+extern int ZEXPORT cpl_zipWriteInFileInZip (zipFile file,
+                                            const void* buf,
+                                            unsigned len);
 /*
   Write data in the zipfile
 */
 
-extern int ZEXPORT cpl_zipCloseFileInZip OF((zipFile file));
+extern int ZEXPORT cpl_zipCloseFileInZip (zipFile file);
 /*
   Close the current file in the zipfile
 */
 
-extern int ZEXPORT cpl_zipCloseFileInZipRaw OF((zipFile file,
-                                            uLong uncompressed_size,
-                                            uLong crc32));
+extern int ZEXPORT cpl_zipCloseFileInZipRaw (zipFile file,
+                                             uLong uncompressed_size,
+                                             uLong crc32);
 /*
-  Close the current file in the zipfile, for fiel opened with
+  Close the current file in the zipfile, for file opened with
     parameter raw=1 in zipOpenNewFileInZip2
   uncompressed_size and crc32 are value for the uncompressed size
 */
 
-extern int ZEXPORT cpl_zipClose OF((zipFile file,
-                const char* global_comment));
+extern int ZEXPORT cpl_zipClose (zipFile file,
+                                 const char* global_comment);
 /*
   Close the zipfile
 */
diff --git a/port/cpl_multiproc.cpp b/port/cpl_multiproc.cpp
index 87c8149..4ea484b 100644
--- a/port/cpl_multiproc.cpp
+++ b/port/cpl_multiproc.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_multiproc.cpp 29304 2015-06-05 16:44:41Z rouault $
+ * $Id: cpl_multiproc.cpp 33817 2016-03-30 17:35:37Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  CPL Multi-Threading, and process handling portability functions.
@@ -15,16 +15,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
@@ -36,13 +36,10 @@
 
 #include "cpl_conv.h"
 
-#if !defined(WIN32CE)
-#  include <time.h>
-#else
-#  include <wce_time.h>
-#endif
+#include <time.h>
+#include <assert.h>
 
-CPL_CVSID("$Id: cpl_multiproc.cpp 29304 2015-06-05 16:44:41Z rouault $");
+CPL_CVSID("$Id: cpl_multiproc.cpp 33817 2016-03-30 17:35:37Z rouault $");
 
 #if defined(CPL_MULTIPROC_STUB) && !defined(DEBUG)
 #  define MUTEX_NONE
@@ -59,7 +56,7 @@ typedef struct _CPLSpinLock CPLSpinLock;
 struct _CPLLock
 {
     CPLLockType eType;
-    union 
+    union
     {
         CPLMutex        *hMutex;
         CPLSpinLock     *hSpinLock;
@@ -107,7 +104,7 @@ void CPLFinalizeTLS();
 /************************************************************************/
 
 CPLMutexHolder::CPLMutexHolder( CPLMutex **phMutex, double dfWaitInSeconds,
-                                const char *pszFileIn, 
+                                const char *pszFileIn,
                                 int nLineIn,
                                 int nOptions )
 
@@ -116,6 +113,13 @@ CPLMutexHolder::CPLMutexHolder( CPLMutex **phMutex, double dfWaitInSeconds,
     pszFile = pszFileIn;
     nLine = nLineIn;
 
+    if( phMutex == NULL )
+    {
+        fprintf( stderr, "CPLMutexHolder: phMutex )) NULL !\n" );
+        hMutex = NULL;
+        return;
+    }
+
 #ifdef DEBUG_MUTEX
     /*
      * XXX: There is no way to use CPLDebug() here because it works with
@@ -123,7 +127,7 @@ CPLMutexHolder::CPLMutexHolder( CPLMutex **phMutex, double dfWaitInSeconds,
      * fprintf() will do the job right.
      */
     fprintf( stderr,
-             "CPLMutexHolder: Request %p for pid %ld at %d/%s.\n", 
+             "CPLMutexHolder: Request %p for pid %ld at %d/%s.\n",
              *phMutex, (long) CPLGetPID(), nLine, pszFile );
 #endif
 
@@ -136,7 +140,7 @@ CPLMutexHolder::CPLMutexHolder( CPLMutex **phMutex, double dfWaitInSeconds,
     {
 #ifdef DEBUG_MUTEX
         fprintf( stderr,
-                 "CPLMutexHolder: Acquired %p for pid %ld at %d/%s.\n", 
+                 "CPLMutexHolder: Acquired %p for pid %ld at %d/%s.\n",
                  *phMutex, (long) CPLGetPID(), nLine, pszFile );
 #endif
 
@@ -150,7 +154,7 @@ CPLMutexHolder::CPLMutexHolder( CPLMutex **phMutex, double dfWaitInSeconds,
 /************************************************************************/
 
 CPLMutexHolder::CPLMutexHolder( CPLMutex *hMutexIn, double dfWaitInSeconds,
-                                const char *pszFileIn, 
+                                const char *pszFileIn,
                                 int nLineIn )
 
 {
@@ -180,7 +184,7 @@ CPLMutexHolder::~CPLMutexHolder()
     {
 #ifdef DEBUG_MUTEX
         fprintf( stderr,
-                 "~CPLMutexHolder: Release %p for pid %ld at %d/%s.\n", 
+                 "~CPLMutexHolder: Release %p for pid %ld at %d/%s.\n",
                  hMutex, (long) CPLGetPID(), nLine, pszFile );
 #endif
         CPLReleaseMutex( hMutex );
@@ -213,7 +217,7 @@ int CPLCreateOrAcquireMutexEx( CPLMutex **phMutex, double dfWaitInSeconds, int n
     /*
     ** ironically, creation of this initial mutex is not threadsafe
     ** even though we use it to ensure that creation of other mutexes
-    ** is threadsafe. 
+    ** is threadsafe.
     */
     if( hCOAMutex == NULL )
     {
@@ -262,7 +266,7 @@ int CPLCreateOrAcquireMutexInternal( CPLLock **phLock, double dfWaitInSeconds,
     /*
     ** ironically, creation of this initial mutex is not threadsafe
     ** even though we use it to ensure that creation of other mutexes
-    ** is threadsafe. 
+    ** is threadsafe.
     */
     if( hCOAMutex == NULL )
     {
@@ -308,22 +312,22 @@ int CPLCreateOrAcquireMutexInternal( CPLLock **phLock, double dfWaitInSeconds,
 
 #endif /* CPL_MULTIPROC_PTHREAD */
 
-/************************************************************************/ 
-/*                      CPLCleanupMasterMutex()                         */ 
-/************************************************************************/ 
- 
-void CPLCleanupMasterMutex() 
-{ 
-#ifndef CPL_MULTIPROC_PTHREAD 
-#ifndef MUTEX_NONE 
-    if( hCOAMutex != NULL ) 
-    { 
-        CPLDestroyMutex( hCOAMutex ); 
-        hCOAMutex = NULL; 
-    } 
-#endif 
-#endif 
-} 
+/************************************************************************/
+/*                      CPLCleanupMasterMutex()                         */
+/************************************************************************/
+
+void CPLCleanupMasterMutex()
+{
+#ifndef CPL_MULTIPROC_PTHREAD
+#ifndef MUTEX_NONE
+    if( hCOAMutex != NULL )
+    {
+        CPLDestroyMutex( hCOAMutex );
+        hCOAMutex = NULL;
+    }
+#endif
+#endif
+}
 
 /************************************************************************/
 /*                        CPLCleanupTLSList()                           */
@@ -335,14 +339,14 @@ void CPLCleanupMasterMutex()
 static void CPLCleanupTLSList( void **papTLSList )
 
 {
-    int i;
+#ifdef DEBUG_VERBOSE
+    printf( "CPLCleanupTLSList(%p)\n", papTLSList );
+#endif
 
-//    printf( "CPLCleanupTLSList(%p)\n", papTLSList );
-    
     if( papTLSList == NULL )
         return;
 
-    for( i = 0; i < CTLS_MAX; i++ )
+    for( int i = 0; i < CTLS_MAX; i++ )
     {
         if( papTLSList[i] != NULL && papTLSList[i+CTLS_MAX] != NULL )
         {
@@ -394,6 +398,8 @@ CPLMutex *CPLCreateMutex()
 {
 #ifndef MUTEX_NONE
     unsigned char *pabyMutex = (unsigned char *) malloc( 4 );
+    if( pabyMutex == NULL )
+        return NULL;
 
     pabyMutex[0] = 1;
     pabyMutex[1] = 'r';
@@ -403,7 +409,7 @@ CPLMutex *CPLCreateMutex()
     return (CPLMutex *) pabyMutex;
 #else
     return (CPLMutex *) 0xdeadbeef;
-#endif 
+#endif
 }
 
 CPLMutex *CPLCreateMutexEx(CPL_UNUSED int nOptions)
@@ -422,7 +428,7 @@ int CPLAcquireMutex( CPLMutex *hMutex,
 #ifndef MUTEX_NONE
     unsigned char *pabyMutex = (unsigned char *) hMutex;
 
-    CPLAssert( pabyMutex[1] == 'r' && pabyMutex[2] == 'e' 
+    CPLAssert( pabyMutex[1] == 'r' && pabyMutex[2] == 'e'
                && pabyMutex[3] == 'd' );
 
     pabyMutex[0] += 1;
@@ -443,11 +449,11 @@ void CPLReleaseMutex( CPLMutex *hMutex )
 #ifndef MUTEX_NONE
     unsigned char *pabyMutex = (unsigned char *) hMutex;
 
-    CPLAssert( pabyMutex[1] == 'r' && pabyMutex[2] == 'e' 
+    CPLAssert( pabyMutex[1] == 'r' && pabyMutex[2] == 'e'
                && pabyMutex[3] == 'd' );
 
     if( pabyMutex[0] < 1 )
-        CPLDebug( "CPLMultiProc", 
+        CPLDebug( "CPLMultiProc",
                   "CPLReleaseMutex() called on mutex with %d as ref count!",
                   pabyMutex[0] );
 
@@ -465,7 +471,7 @@ void CPLDestroyMutex( CPLMutex *hMutex )
 #ifndef MUTEX_NONE
     unsigned char *pabyMutex = (unsigned char *) hMutex;
 
-    CPLAssert( pabyMutex[1] == 'r' && pabyMutex[2] == 'e' 
+    CPLAssert( pabyMutex[1] == 'r' && pabyMutex[2] == 'e'
                && pabyMutex[3] == 'd' );
 
     free( pabyMutex );
@@ -532,7 +538,7 @@ void *CPLLockFile( const char *pszPath, double dfWaitInSeconds )
 {
     FILE      *fpLock;
     char      *pszLockFilename;
-    
+
 /* -------------------------------------------------------------------- */
 /*      We use a lock file with a name derived from the file we want    */
 /*      to lock to represent the file being locked.  Note that for      */
@@ -540,7 +546,7 @@ void *CPLLockFile( const char *pszPath, double dfWaitInSeconds )
 /*      to exist to be locked.                                          */
 /* -------------------------------------------------------------------- */
     pszLockFilename = (char *) CPLMalloc(strlen(pszPath) + 30);
-    sprintf( pszLockFilename, "%s.lock", pszPath );
+    snprintf( pszLockFilename, strlen(pszPath) + 30, "%s.lock", pszPath );
 
     fpLock = fopen( pszLockFilename, "r" );
     while( fpLock != NULL && dfWaitInSeconds > 0.0 )
@@ -551,7 +557,7 @@ void *CPLLockFile( const char *pszPath, double dfWaitInSeconds )
 
         fpLock = fopen( pszLockFilename, "r" );
     }
-        
+
     if( fpLock != NULL )
     {
         fclose( fpLock );
@@ -584,9 +590,9 @@ void CPLUnlockFile( void *hLock )
 
     if( hLock == NULL )
         return;
-    
+
     VSIUnlink( pszLockFilename );
-    
+
     CPLFree( pszLockFilename );
 }
 
@@ -637,14 +643,13 @@ void CPLJoinThread(CPL_UNUSED CPLJoinableThread* hJoinableThread)
 void CPLSleep( double dfWaitInSeconds )
 {
     time_t  ltime;
-    time_t  ttime;
 
     time( &ltime );
-    ttime = ltime + (int) (dfWaitInSeconds+0.5);
+    time_t ttime = ltime + (int) (dfWaitInSeconds+0.5);
 
     for( ; ltime < ttime; time(&ltime) )
     {
-        /* currently we just busy wait.  Perhaps we could at least block on 
+        /* currently we just busy wait.  Perhaps we could at least block on
            io? */
     }
 }
@@ -655,14 +660,24 @@ void CPLSleep( double dfWaitInSeconds )
 
 static void **papTLSList = NULL;
 
-static void **CPLGetTLSList()
+static void **CPLGetTLSList(int *pbMemoryErrorOccurred)
 
 {
+    if( pbMemoryErrorOccurred )
+        *pbMemoryErrorOccurred = FALSE;
     if( papTLSList == NULL )
     {
         papTLSList = (void **) VSICalloc(sizeof(void*),CTLS_MAX*2);
         if( papTLSList == NULL )
+        {
+            if( pbMemoryErrorOccurred )
+            {
+                *pbMemoryErrorOccurred = TRUE;
+                fprintf(stderr, "CPLGetTLSList() failed to allocate TLS list!\n");
+                return NULL;
+            }
             CPLEmergencyError("CPLGetTLSList() failed to allocate TLS list!");
+        }
     }
 
     return papTLSList;
@@ -702,16 +717,11 @@ void CPLCleanupTLS()
   /************************************************************************/
 
 /* InitializeCriticalSectionAndSpinCount requires _WIN32_WINNT >= 0x403 */
+#undef _WIN32_WINNT
 #define _WIN32_WINNT 0x0500
 
 #include <windows.h>
 
-/* windows.h header must be included above following lines. */
-#if defined(WIN32CE)
-#  include "cpl_win32ce_api.h"
-#  define TLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF)
-#endif
-
 /************************************************************************/
 /*                             CPLGetNumCPUs()                          */
 /************************************************************************/
@@ -780,10 +790,9 @@ int CPLAcquireMutex( CPLMutex *hMutexIn, double dfWaitInSeconds )
 {
 #ifdef USE_WIN32_MUTEX
     HANDLE hMutex = (HANDLE) hMutexIn;
-    DWORD  hr;
+    const DWORD hr =
+        WaitForSingleObject( hMutex, (int) (dfWaitInSeconds * 1000) );
 
-    hr = WaitForSingleObject( hMutex, (int) (dfWaitInSeconds * 1000) );
-    
     return hr != WAIT_TIMEOUT;
 #else
     CRITICAL_SECTION *pcs = (CRITICAL_SECTION *)hMutexIn;
@@ -920,7 +929,7 @@ void  CPLCondWait( CPLCond *hCond, CPLMutex* hClientMutex )
     /* Release the client mutex before waiting for the event being signaled */
     CPLReleaseMutex(hClientMutex);
 
-    // Ideally we would check that we do not get WAIT_FAILED but it is hard 
+    // Ideally we would check that we do not get WAIT_FAILED but it is hard
     // to report a failure.
     WaitForSingleObject(hEvent, INFINITE);
 
@@ -994,14 +1003,11 @@ void  CPLDestroyCond( CPLCond *hCond )
 void *CPLLockFile( const char *pszPath, double dfWaitInSeconds )
 
 {
-    char      *pszLockFilename;
-    HANDLE    hLockFile;
-    
-    pszLockFilename = (char *) CPLMalloc(strlen(pszPath) + 30);
-    sprintf( pszLockFilename, "%s.lock", pszPath );
+    char *pszLockFilename = (char *) CPLMalloc(strlen(pszPath) + 30);
+    snprintf( pszLockFilename, strlen(pszPath) + 30, "%s.lock", pszPath );
 
-    hLockFile = 
-        CreateFile( pszLockFilename, GENERIC_WRITE, 0, NULL,CREATE_NEW, 
+    HANDLE hLockFile =
+        CreateFile( pszLockFilename, GENERIC_WRITE, 0, NULL,CREATE_NEW,
                     FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE, NULL );
 
     while( GetLastError() == ERROR_ALREADY_EXISTS
@@ -1011,9 +1017,9 @@ void *CPLLockFile( const char *pszPath, double dfWaitInSeconds )
         CPLSleep( MIN(dfWaitInSeconds,0.125) );
         dfWaitInSeconds -= 0.125;
 
-        hLockFile = 
-            CreateFile( pszLockFilename, GENERIC_WRITE, 0, NULL, CREATE_NEW, 
-                        FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE, 
+        hLockFile =
+            CreateFile( pszLockFilename, GENERIC_WRITE, 0, NULL, CREATE_NEW,
+                        FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE,
                         NULL );
     }
 
@@ -1089,8 +1095,6 @@ static DWORD WINAPI CPLStdCallThreadJacket( void *pData )
 int CPLCreateThread( CPLThreadFunc pfnMain, void *pThreadArg )
 
 {
-    HANDLE hThread;
-    DWORD  nThreadId;
     CPLStdCallThreadInfo *psInfo;
 
     psInfo = (CPLStdCallThreadInfo*) CPLCalloc(sizeof(CPLStdCallThreadInfo),1);
@@ -1098,8 +1102,9 @@ int CPLCreateThread( CPLThreadFunc pfnMain, void *pThreadArg )
     psInfo->pfnMain = pfnMain;
     psInfo->hThread = NULL;
 
-    hThread = CreateThread( NULL, 0, CPLStdCallThreadJacket, psInfo, 
-                            0, &nThreadId );
+    DWORD nThreadId = 0;
+    HANDLE hThread = CreateThread( NULL, 0, CPLStdCallThreadJacket, psInfo,
+                                   0, &nThreadId );
 
     if( hThread == NULL )
         return -1;
@@ -1116,20 +1121,19 @@ int CPLCreateThread( CPLThreadFunc pfnMain, void *pThreadArg )
 CPLJoinableThread* CPLCreateJoinableThread( CPLThreadFunc pfnMain, void *pThreadArg )
 
 {
-    HANDLE hThread;
-    DWORD  nThreadId;
     CPLStdCallThreadInfo *psInfo;
 
     psInfo = (CPLStdCallThreadInfo*) CPLCalloc(sizeof(CPLStdCallThreadInfo),1);
     psInfo->pAppData = pThreadArg;
     psInfo->pfnMain = pfnMain;
 
-    hThread = CreateThread( NULL, 0, CPLStdCallThreadJacket, psInfo, 
-                            0, &nThreadId );
+    DWORD nThreadId = 0;
+    HANDLE hThread = CreateThread( NULL, 0, CPLStdCallThreadJacket, psInfo,
+                                   0, &nThreadId );
 
     if( hThread == NULL )
         return NULL;
-        
+
     psInfo->hThread = hThread;
     return (CPLJoinableThread*) psInfo;
 }
@@ -1141,7 +1145,7 @@ CPLJoinableThread* CPLCreateJoinableThread( CPLThreadFunc pfnMain, void *pThread
 void CPLJoinThread(CPLJoinableThread* hJoinableThread)
 {
     CPLStdCallThreadInfo *psInfo = (CPLStdCallThreadInfo *) hJoinableThread;
-    
+
     WaitForSingleObject(psInfo->hThread, INFINITE);
     CloseHandle( psInfo->hThread );
     CPLFree( psInfo );
@@ -1157,26 +1161,34 @@ void CPLSleep( double dfWaitInSeconds )
     Sleep( (DWORD) (dfWaitInSeconds * 1000.0) );
 }
 
-static int           bTLSKeySetup = FALSE;
-static DWORD         nTLSKey;
+static bool          bTLSKeySetup = false;
+static DWORD nTLSKey = 0;
 
 /************************************************************************/
 /*                           CPLGetTLSList()                            */
 /************************************************************************/
 
-static void **CPLGetTLSList()
+static void **CPLGetTLSList(int *pbMemoryErrorOccurred)
 
 {
     void **papTLSList;
 
+    if( pbMemoryErrorOccurred )
+        *pbMemoryErrorOccurred = FALSE;
     if( !bTLSKeySetup )
     {
         nTLSKey = TlsAlloc();
         if( nTLSKey == TLS_OUT_OF_INDEXES )
         {
+            if( pbMemoryErrorOccurred )
+            {
+                *pbMemoryErrorOccurred = TRUE;
+                fprintf(stderr, "CPLGetTLSList(): TlsAlloc() failed!\n" );
+                return NULL;
+            }
             CPLEmergencyError( "CPLGetTLSList(): TlsAlloc() failed!" );
         }
-        bTLSKeySetup = TRUE;
+        bTLSKeySetup = true;
     }
 
     papTLSList = (void **) TlsGetValue( nTLSKey );
@@ -1184,9 +1196,23 @@ static void **CPLGetTLSList()
     {
         papTLSList = (void **) VSICalloc(sizeof(void*),CTLS_MAX*2);
         if( papTLSList == NULL )
+        {
+            if( pbMemoryErrorOccurred )
+            {
+                *pbMemoryErrorOccurred = TRUE;
+                fprintf(stderr, "CPLGetTLSList() failed to allocate TLS list!\n" );
+                return NULL;
+            }
             CPLEmergencyError("CPLGetTLSList() failed to allocate TLS list!");
+        }
         if( TlsSetValue( nTLSKey, papTLSList ) == 0 )
         {
+            if( pbMemoryErrorOccurred )
+            {
+                *pbMemoryErrorOccurred = TRUE;
+                fprintf(stderr, "CPLGetTLSList(): TlsSetValue() failed!\n" );
+                return NULL;
+            }
             CPLEmergencyError( "CPLGetTLSList(): TlsSetValue() failed!" );
         }
     }
@@ -1347,17 +1373,28 @@ static MutexLinkedElt* psMutexList = NULL;
 
 static void CPLInitMutex(MutexLinkedElt* psItem)
 {
-    /* When an adaptive mutex is required, we can safely fallback to recursive */
+    if( psItem->nOptions == CPL_MUTEX_REGULAR )
+    {
+        pthread_mutex_t tmp_mutex = PTHREAD_MUTEX_INITIALIZER;
+        psItem->sMutex = tmp_mutex;
+        return;
+    }
+
+    /* When an adaptive mutex is required, we can safely fallback to regular */
     /* mutex if we don't have HAVE_PTHREAD_MUTEX_ADAPTIVE_NP */
-#if defined(HAVE_PTHREAD_MUTEX_ADAPTIVE_NP)
     if( psItem->nOptions == CPL_MUTEX_ADAPTIVE )
     {
+#if defined(HAVE_PTHREAD_MUTEX_ADAPTIVE_NP)
         pthread_mutexattr_t  attr;
         pthread_mutexattr_init( &attr );
         pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_ADAPTIVE_NP );
         pthread_mutex_init( &(psItem->sMutex), &attr );
-    }
+#else
+        pthread_mutex_t tmp_mutex = PTHREAD_MUTEX_INITIALIZER;
+        psItem->sMutex = tmp_mutex;
 #endif
+        return;
+    }
 
 #if defined(PTHREAD_MUTEX_RECURSIVE) || defined(HAVE_PTHREAD_MUTEX_RECURSIVE)
     {
@@ -1379,7 +1416,7 @@ static void CPLInitMutex(MutexLinkedElt* psItem)
     pthread_mutex_t tmp_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
     psItem->sMutex = tmp_mutex;
 #else
-#error "Recursive mutexes apparently unsupported, configure --without-threads" 
+#error "Recursive mutexes apparently unsupported, configure --without-threads"
 #endif
 }
 
@@ -1387,7 +1424,10 @@ static CPLMutex *CPLCreateMutexInternal(int bAlreadyInGlobalLock, int nOptions)
 {
     MutexLinkedElt* psItem = (MutexLinkedElt *) malloc(sizeof(MutexLinkedElt));
     if (psItem == NULL)
+    {
+        fprintf(stderr, "CPLCreateMutexInternal() failed.\n");
         return NULL;
+    }
 
     if( !bAlreadyInGlobalLock )
         pthread_mutex_lock(&global_mutex);
@@ -1424,12 +1464,11 @@ CPLMutex *CPLCreateMutexEx(int nOptions)
 
 int CPLAcquireMutex( CPLMutex *hMutexIn, CPL_UNUSED double dfWaitInSeconds )
 {
-    int err;
 
     /* we need to add timeout support */
     MutexLinkedElt* psItem = (MutexLinkedElt *) hMutexIn;
-    err =  pthread_mutex_lock( &(psItem->sMutex) );
-    
+    const int err = pthread_mutex_lock( &(psItem->sMutex) );
+
     if( err != 0 )
     {
         if( err == EDEADLK )
@@ -1500,9 +1539,11 @@ void CPLReinitAllMutex()
 CPLCond  *CPLCreateCond()
 {
     pthread_cond_t* pCond = (pthread_cond_t* )malloc(sizeof(pthread_cond_t));
-    if (pCond)
-        pthread_cond_init(pCond, NULL);
-    return (CPLCond*) pCond;
+    if (pCond && pthread_cond_init(pCond, NULL) == 0 )
+        return (CPLCond*) pCond;
+    fprintf(stderr, "CPLCreateCond() failed.\n");
+    free(pCond);
+    return NULL;
 }
 
 /************************************************************************/
@@ -1560,15 +1601,16 @@ void *CPLLockFile( const char *pszPath, double dfWaitInSeconds )
 {
     FILE      *fpLock;
     char      *pszLockFilename;
-    
+
 /* -------------------------------------------------------------------- */
 /*      We use a lock file with a name derived from the file we want    */
 /*      to lock to represent the file being locked.  Note that for      */
 /*      the stub implementation the target file does not even need      */
 /*      to exist to be locked.                                          */
 /* -------------------------------------------------------------------- */
-    pszLockFilename = (char *) CPLMalloc(strlen(pszPath) + 30);
-    sprintf( pszLockFilename, "%s.lock", pszPath );
+    const size_t nLen = strlen(pszPath) + 30;
+    pszLockFilename = (char *) CPLMalloc(nLen);
+    snprintf( pszLockFilename, nLen, "%s.lock", pszPath );
 
     fpLock = fopen( pszLockFilename, "r" );
     while( fpLock != NULL && dfWaitInSeconds > 0.0 )
@@ -1579,7 +1621,7 @@ void *CPLLockFile( const char *pszPath, double dfWaitInSeconds )
 
         fpLock = fopen( pszLockFilename, "r" );
     }
-        
+
     if( fpLock != NULL )
     {
         fclose( fpLock );
@@ -1612,9 +1654,9 @@ void CPLUnlockFile( void *hLock )
 
     if( hLock == NULL )
         return;
-    
+
     VSIUnlink( pszLockFilename );
-    
+
     CPLFree( pszLockFilename );
 }
 
@@ -1628,6 +1670,74 @@ GIntBig CPLGetPID()
     return (GIntBig) pthread_self();
 }
 
+static pthread_key_t  oTLSKey;
+static pthread_once_t oTLSKeySetup = PTHREAD_ONCE_INIT;
+
+/************************************************************************/
+/*                             CPLMake_key()                            */
+/************************************************************************/
+
+static void CPLMake_key()
+
+{
+    if( pthread_key_create( &oTLSKey, (void (*)(void*)) CPLCleanupTLSList ) != 0 )
+    {
+        CPLError( CE_Fatal, CPLE_AppDefined, "pthread_key_create() failed!" );
+    }
+}
+
+/************************************************************************/
+/*                           CPLGetTLSList()                            */
+/************************************************************************/
+
+static void **CPLGetTLSList(int* pbMemoryErrorOccurred)
+
+{
+    void **papTLSList;
+
+    if( pbMemoryErrorOccurred )
+        *pbMemoryErrorOccurred = FALSE;
+    if ( pthread_once(&oTLSKeySetup, CPLMake_key) != 0 )
+    {
+        if( pbMemoryErrorOccurred )
+        {
+            fprintf(stderr, "CPLGetTLSList(): pthread_once() failed!\n" );
+            *pbMemoryErrorOccurred = TRUE;
+            return NULL;
+        }
+        CPLEmergencyError( "CPLGetTLSList(): pthread_once() failed!" );
+    }
+
+    papTLSList = (void **) pthread_getspecific( oTLSKey );
+    if( papTLSList == NULL )
+    {
+        papTLSList = (void **) VSICalloc(sizeof(void*),CTLS_MAX*2);
+        if( papTLSList == NULL )
+        {
+            if( pbMemoryErrorOccurred )
+            {
+                fprintf(stderr, "CPLGetTLSList() failed to allocate TLS list!\n" );
+                *pbMemoryErrorOccurred = TRUE;
+                return NULL;
+            }
+            CPLEmergencyError("CPLGetTLSList() failed to allocate TLS list!");
+        }
+        if( pthread_setspecific( oTLSKey, papTLSList ) != 0 )
+        {
+            if( pbMemoryErrorOccurred )
+            {
+                fprintf(stderr, "CPLGetTLSList(): pthread_setspecific() failed!\n" );
+                *pbMemoryErrorOccurred = TRUE;
+                return NULL;
+            }
+            CPLEmergencyError(
+                "CPLGetTLSList(): pthread_setspecific() failed!" );
+        }
+    }
+
+    return papTLSList;
+}
+
 /************************************************************************/
 /*                       CPLStdCallThreadJacket()                       */
 /************************************************************************/
@@ -1636,7 +1746,13 @@ typedef struct {
     void *pAppData;
     CPLThreadFunc pfnMain;
     pthread_t hThread;
-    int bJoinable;
+    bool bJoinable;
+#ifdef CHECK_THREAD_CAN_ALLOCATE_TLS
+    bool bInitSucceeded;
+    bool bInitDone;
+    pthread_mutex_t sMutex;
+    pthread_cond_t sCond;
+#endif
 } CPLStdCallThreadInfo;
 
 static void *CPLStdCallThreadJacket( void *pData )
@@ -1644,12 +1760,34 @@ static void *CPLStdCallThreadJacket( void *pData )
 {
     CPLStdCallThreadInfo *psInfo = (CPLStdCallThreadInfo *) pData;
 
+#ifdef CHECK_THREAD_CAN_ALLOCATE_TLS
+    int bMemoryError = FALSE;
+    CPLGetTLSList(&bMemoryError);
+    if( bMemoryError )
+        goto error;
+
+    assert( pthread_mutex_lock( &(psInfo->sMutex) ) == 0);
+    psInfo->bInitDone = true;
+    assert( pthread_cond_signal( &(psInfo->sCond) ) == 0);
+    assert( pthread_mutex_unlock( &(psInfo->sMutex) ) == 0);
+#endif
+
     psInfo->pfnMain( psInfo->pAppData );
 
     if (!psInfo->bJoinable)
         CPLFree( psInfo );
 
     return NULL;
+
+#ifdef CHECK_THREAD_CAN_ALLOCATE_TLS
+error:
+    assert( pthread_mutex_lock( &(psInfo->sMutex) ) == 0);
+    psInfo->bInitSucceeded = false;
+    psInfo->bInitDone = true;
+    assert( pthread_cond_signal( &(psInfo->sCond) ) == 0);
+    assert( pthread_mutex_unlock( &(psInfo->sMutex) ) == 0);
+    return NULL;
+#endif
 }
 
 /************************************************************************/
@@ -1667,19 +1805,61 @@ int CPLCreateThread( CPLThreadFunc pfnMain, void *pThreadArg )
     CPLStdCallThreadInfo *psInfo;
     pthread_attr_t hThreadAttr;
 
-    psInfo = (CPLStdCallThreadInfo*) CPLCalloc(sizeof(CPLStdCallThreadInfo),1);
+    psInfo = (CPLStdCallThreadInfo*) VSI_CALLOC_VERBOSE(sizeof(CPLStdCallThreadInfo),1);
+    if( psInfo == NULL )
+        return -1;
     psInfo->pAppData = pThreadArg;
     psInfo->pfnMain = pfnMain;
-    psInfo->bJoinable = FALSE;
+    psInfo->bJoinable = false;
+#ifdef CHECK_THREAD_CAN_ALLOCATE_TLS
+    psInfo->bInitSucceeded = true;
+    psInfo->bInitDone = false;
+    pthread_mutex_t sMutex = PTHREAD_MUTEX_INITIALIZER;
+    psInfo->sMutex = sMutex;
+    if( pthread_cond_init(&(psInfo->sCond), NULL) != 0 )
+    {
+        CPLFree( psInfo );
+        fprintf(stderr, "CPLCreateThread() failed.\n");
+        return -1;
+    }
+#endif
 
     pthread_attr_init( &hThreadAttr );
     pthread_attr_setdetachstate( &hThreadAttr, PTHREAD_CREATE_DETACHED );
-    if( pthread_create( &(psInfo->hThread), &hThreadAttr, 
+    if( pthread_create( &(psInfo->hThread), &hThreadAttr,
                         CPLStdCallThreadJacket, (void *) psInfo ) != 0 )
     {
+#ifdef CHECK_THREAD_CAN_ALLOCATE_TLS
+        pthread_cond_destroy(&(psInfo->sCond));
+#endif
+        CPLFree( psInfo );
+        fprintf(stderr, "CPLCreateThread() failed.\n");
+        return -1;
+    }
+
+#ifdef CHECK_THREAD_CAN_ALLOCATE_TLS
+    bool bInitSucceeded;
+    while( true )
+    {
+        assert(pthread_mutex_lock( &(psInfo->sMutex) ) == 0);
+        bool bInitDone = psInfo->bInitDone;
+        if( !bInitDone )
+            assert(pthread_cond_wait( &(psInfo->sCond),  &(psInfo->sMutex)  ) == 0);
+        bInitSucceeded = psInfo->bInitSucceeded;
+        assert(pthread_mutex_unlock( &(psInfo->sMutex) ) == 0);
+        if( bInitDone )
+            break;
+    }
+
+    pthread_cond_destroy(&(psInfo->sCond));
+
+    if( !bInitSucceeded )
+    {
         CPLFree( psInfo );
+        fprintf(stderr, "CPLCreateThread() failed.\n");
         return -1;
     }
+#endif
 
     return 1; /* can we return the actual thread pid? */
 }
@@ -1694,20 +1874,64 @@ CPLJoinableThread* CPLCreateJoinableThread( CPLThreadFunc pfnMain, void *pThread
     CPLStdCallThreadInfo *psInfo;
     pthread_attr_t hThreadAttr;
 
-    psInfo = (CPLStdCallThreadInfo*) CPLCalloc(sizeof(CPLStdCallThreadInfo),1);
+    psInfo = (CPLStdCallThreadInfo*) VSI_CALLOC_VERBOSE(sizeof(CPLStdCallThreadInfo),1);
+    if( psInfo == NULL )
+        return NULL;
     psInfo->pAppData = pThreadArg;
     psInfo->pfnMain = pfnMain;
-    psInfo->bJoinable = TRUE;
+    psInfo->bJoinable = true;
+#ifdef CHECK_THREAD_CAN_ALLOCATE_TLS
+    psInfo->bInitSucceeded = true;
+    psInfo->bInitDone = false;
+    pthread_mutex_t sMutex = PTHREAD_MUTEX_INITIALIZER;
+    psInfo->sMutex = sMutex;
+    if( pthread_cond_init(&(psInfo->sCond), NULL) != 0 )
+    {
+        CPLFree( psInfo );
+        fprintf(stderr, "CPLCreateJoinableThread() failed.\n");
+        return NULL;
+    }
+#endif
 
     pthread_attr_init( &hThreadAttr );
     pthread_attr_setdetachstate( &hThreadAttr, PTHREAD_CREATE_JOINABLE );
     if( pthread_create( &(psInfo->hThread), &hThreadAttr,
                         CPLStdCallThreadJacket, (void *) psInfo ) != 0 )
     {
+#ifdef CHECK_THREAD_CAN_ALLOCATE_TLS
+        pthread_cond_destroy(&(psInfo->sCond));
+#endif
         CPLFree( psInfo );
+        fprintf(stderr, "CPLCreateJoinableThread() failed.\n");
         return NULL;
     }
 
+#ifdef CHECK_THREAD_CAN_ALLOCATE_TLS
+    bool bInitSucceeded;
+    while( true )
+    {
+        assert(pthread_mutex_lock( &(psInfo->sMutex) ) == 0);
+        bool bInitDone = psInfo->bInitDone;
+        if( !bInitDone )
+            assert(pthread_cond_wait( &(psInfo->sCond),  &(psInfo->sMutex)  ) == 0);
+        bInitSucceeded = psInfo->bInitSucceeded;
+        assert(pthread_mutex_unlock( &(psInfo->sMutex) ) == 0);
+        if( bInitDone )
+            break;
+    }
+
+    pthread_cond_destroy(&(psInfo->sCond));
+
+    if( !bInitSucceeded )
+    {
+        void* status;
+        pthread_join( psInfo->hThread, &status);
+        CPLFree( psInfo );
+        fprintf(stderr, "CPLCreateJoinableThread() failed.\n");
+        return NULL;
+    }
+#endif
+
     return (CPLJoinableThread*) psInfo;
 }
 
@@ -1718,6 +1942,8 @@ CPLJoinableThread* CPLCreateJoinableThread( CPLThreadFunc pfnMain, void *pThread
 void CPLJoinThread(CPLJoinableThread* hJoinableThread)
 {
     CPLStdCallThreadInfo *psInfo = (CPLStdCallThreadInfo*) hJoinableThread;
+    if( psInfo == NULL )
+        return;
 
     void* status;
     pthread_join( psInfo->hThread, &status);
@@ -1739,22 +1965,6 @@ void CPLSleep( double dfWaitInSeconds )
     nanosleep( &sRequest, &sRemain );
 }
 
-static pthread_key_t  oTLSKey;
-static pthread_once_t oTLSKeySetup = PTHREAD_ONCE_INIT;
-
-/************************************************************************/
-/*                             CPLMake_key()                            */
-/************************************************************************/
-
-static void CPLMake_key()
-
-{
-    if( pthread_key_create( &oTLSKey, (void (*)(void*)) CPLCleanupTLSList ) != 0 )
-    {
-        CPLError( CE_Fatal, CPLE_AppDefined, "pthread_key_create() failed!" );
-    }
-}
-
 /************************************************************************/
 /*                             CPLFinalizeTLS()                         */
 /************************************************************************/
@@ -1785,36 +1995,6 @@ void CPLCleanupTLS()
 }
 
 /************************************************************************/
-/*                           CPLGetTLSList()                            */
-/************************************************************************/
-
-static void **CPLGetTLSList()
-
-{
-    void **papTLSList;
-
-    if ( pthread_once(&oTLSKeySetup, CPLMake_key) != 0 )
-    {
-        CPLEmergencyError( "CPLGetTLSList(): pthread_once() failed!" );
-    }
-
-    papTLSList = (void **) pthread_getspecific( oTLSKey );
-    if( papTLSList == NULL )
-    {
-        papTLSList = (void **) VSICalloc(sizeof(void*),CTLS_MAX*2);
-        if( papTLSList == NULL )
-            CPLEmergencyError("CPLGetTLSList() failed to allocate TLS list!");
-        if( pthread_setspecific( oTLSKey, papTLSList ) != 0 )
-        {
-            CPLEmergencyError( 
-                "CPLGetTLSList(): pthread_setspecific() failed!" );
-        }
-    }
-
-    return papTLSList;
-}
-
-/************************************************************************/
 /*                          CPLCreateSpinLock()                         */
 /************************************************************************/
 
@@ -1829,12 +2009,14 @@ struct _CPLSpinLock
 CPLSpinLock  *CPLCreateSpinLock( void )
 {
     CPLSpinLock* psSpin = (CPLSpinLock*)malloc(sizeof(CPLSpinLock));
-    if( pthread_spin_init(&(psSpin->spin), PTHREAD_PROCESS_PRIVATE) == 0 )
+    if( psSpin != NULL &&
+        pthread_spin_init(&(psSpin->spin), PTHREAD_PROCESS_PRIVATE) == 0 )
     {
         return psSpin;
     }
     else
     {
+        fprintf(stderr, "CPLCreateSpinLock() failed.\n");
         free(psSpin);
         return NULL;
     }
@@ -1871,6 +2053,7 @@ int  CPLCreateOrAcquireSpinLockInternal( CPLLock** ppsLock )
         }
     }
     pthread_mutex_unlock(&global_mutex);
+    /* coverity[missing_unlock] */
     return( *ppsLock != NULL && CPLAcquireSpinLock( (*ppsLock)->u.hSpinLock ) );
 }
 
@@ -1903,7 +2086,23 @@ void  CPLDestroySpinLock( CPLSpinLock* psSpin )
 void *CPLGetTLS( int nIndex )
 
 {
-    void** papTLSList = CPLGetTLSList();
+    void** papTLSList = CPLGetTLSList(NULL);
+
+    CPLAssert( nIndex >= 0 && nIndex < CTLS_MAX );
+
+    return papTLSList[nIndex];
+}
+
+/************************************************************************/
+/*                            CPLGetTLSEx()                             */
+/************************************************************************/
+
+void *CPLGetTLSEx( int nIndex, int* pbMemoryErrorOccurred )
+
+{
+    void** papTLSList = CPLGetTLSList(pbMemoryErrorOccurred);
+    if( papTLSList == NULL )
+        return NULL;
 
     CPLAssert( nIndex >= 0 && nIndex < CTLS_MAX );
 
@@ -1929,7 +2128,7 @@ void CPLSetTLS( int nIndex, void *pData, int bFreeOnExit )
 void CPLSetTLSWithFreeFunc( int nIndex, void *pData, CPLTLSFreeFunc pfnFree )
 
 {
-    void **papTLSList = CPLGetTLSList();
+    void **papTLSList = CPLGetTLSList(NULL);
 
     CPLAssert( nIndex >= 0 && nIndex < CTLS_MAX );
 
@@ -1937,6 +2136,23 @@ void CPLSetTLSWithFreeFunc( int nIndex, void *pData, CPLTLSFreeFunc pfnFree )
     papTLSList[CTLS_MAX + nIndex] = (void*) pfnFree;
 }
 
+/************************************************************************/
+/*                      CPLSetTLSWithFreeFuncEx()                       */
+/************************************************************************/
+
+/* Warning : the CPLTLSFreeFunc must not in any case directly or indirectly */
+/* use or fetch any TLS data, or a terminating thread will hang ! */
+void CPLSetTLSWithFreeFuncEx( int nIndex, void *pData,
+                              CPLTLSFreeFunc pfnFree, int* pbMemoryErrorOccurred  )
+
+{
+    void **papTLSList = CPLGetTLSList(pbMemoryErrorOccurred);
+
+    CPLAssert( nIndex >= 0 && nIndex < CTLS_MAX );
+
+    papTLSList[nIndex] = pData;
+    papTLSList[CTLS_MAX + nIndex] = (void*) pfnFree;
+}
 #ifndef HAVE_SPINLOCK_IMPL
 
 /* No spinlock specific API ? Fallback to mutex */
@@ -2009,6 +2225,12 @@ CPLLock *CPLCreateLock( CPLLockType eType )
                 return NULL;
             CPLReleaseMutex(hMutex);
             CPLLock* psLock = (CPLLock*)malloc(sizeof(CPLLock));
+            if( psLock == NULL )
+            {
+                fprintf(stderr, "CPLCreateLock() failed.\n");
+                CPLDestroyMutex(hMutex);
+                return NULL;
+            }
             psLock->eType = eType;
             psLock->u.hMutex = hMutex;
 #ifdef DEBUG_CONTENTION
@@ -2022,6 +2244,12 @@ CPLLock *CPLCreateLock( CPLLockType eType )
             if( !hSpinLock )
                 return NULL;
             CPLLock* psLock = (CPLLock*)malloc(sizeof(CPLLock));
+            if( psLock == NULL )
+            {
+                fprintf(stderr, "CPLCreateLock() failed.\n");
+                CPLDestroySpinLock(hSpinLock);
+                return NULL;
+            }
             psLock->eType = eType;
             psLock->u.hSpinLock = hSpinLock;
 #ifdef DEBUG_CONTENTION
@@ -2041,12 +2269,13 @@ CPLLock *CPLCreateLock( CPLLockType eType )
 
 int   CPLCreateOrAcquireLock( CPLLock** ppsLock, CPLLockType eType )
 {
-    int ret;
 #ifdef DEBUG_CONTENTION
     GUIntBig nStartTime = 0;
     if( (*ppsLock) && (*ppsLock)->bDebugPerf )
         nStartTime = CPLrdtsc();
 #endif
+    int ret = 0;
+
     switch( eType )
     {
         case LOCK_RECURSIVE_MUTEX:
@@ -2146,22 +2375,25 @@ void  CPLDestroyLock( CPLLock* psLock )
 /*                       CPLLockSetDebugPerf()                          */
 /************************************************************************/
 
-void CPLLockSetDebugPerf( CPLLock* psLock, int bEnableIn )
-{
 #ifdef DEBUG_CONTENTION
+void CPLLockSetDebugPerf(CPLLock* psLock, int bEnableIn)
+{
     psLock->bDebugPerf = bEnableIn;
+}
 #else
-    if( bEnableIn )
+void CPLLockSetDebugPerf(CPLLock* /* psLock */, int bEnableIn)
+{
+    if( !bEnableIn )
+        return;
+
+    static bool bOnce = false;
+    if( !bOnce )
     {
-        static int bOnce = FALSE;
-        if( !bOnce )
-        {
-            bOnce = TRUE;
-            CPLDebug("LOCK", "DEBUG_CONTENTION not available");
-        }
+        bOnce = true;
+        CPLDebug("LOCK", "DEBUG_CONTENTION not available");
     }
-#endif
 }
+#endif
 
 /************************************************************************/
 /*                           CPLLockHolder()                            */
@@ -2169,7 +2401,7 @@ void CPLLockSetDebugPerf( CPLLock* psLock, int bEnableIn )
 
 CPLLockHolder::CPLLockHolder( CPLLock **phLock,
                               CPLLockType eType,
-                              const char *pszFileIn, 
+                              const char *pszFileIn,
                               int nLineIn )
 
 {
@@ -2184,7 +2416,7 @@ CPLLockHolder::CPLLockHolder( CPLLock **phLock,
      * fprintf() will do the job right.
      */
     fprintf( stderr,
-             "CPLLockHolder: Request %p for pid %ld at %d/%s.\n", 
+             "CPLLockHolder: Request %p for pid %ld at %d/%s.\n",
              *phLock, (long) CPLGetPID(), nLine, pszFile );
 #endif
 
@@ -2197,7 +2429,7 @@ CPLLockHolder::CPLLockHolder( CPLLock **phLock,
     {
 #ifdef DEBUG_MUTEX
         fprintf( stderr,
-                 "CPLLockHolder: Acquired %p for pid %ld at %d/%s.\n", 
+                 "CPLLockHolder: Acquired %p for pid %ld at %d/%s.\n",
                  *phLock, (long) CPLGetPID(), nLine, pszFile );
 #endif
 
@@ -2211,7 +2443,7 @@ CPLLockHolder::CPLLockHolder( CPLLock **phLock,
 /************************************************************************/
 
 CPLLockHolder::CPLLockHolder( CPLLock *hLockIn,
-                              const char *pszFileIn, 
+                              const char *pszFileIn,
                               int nLineIn )
 
 {
@@ -2243,10 +2475,33 @@ CPLLockHolder::~CPLLockHolder()
     {
 #ifdef DEBUG_MUTEX
         fprintf( stderr,
-                 "~CPLLockHolder: Release %p for pid %ld at %d/%s.\n", 
+                 "~CPLLockHolder: Release %p for pid %ld at %d/%s.\n",
                  hLock, (long) CPLGetPID(), nLine, pszFile );
 #endif
         CPLReleaseLock( hLock );
     }
 #endif /* ndef MUTEX_NONE */
 }
+
+/************************************************************************/
+/*                       CPLGetCurrentProcessID()                       */
+/************************************************************************/
+
+#ifdef CPL_MULTIPROC_WIN32
+
+int CPLGetCurrentProcessID()
+{
+    return GetCurrentProcessId();
+}
+
+#else
+
+#include <sys/types.h>
+#include <unistd.h>
+
+int CPLGetCurrentProcessID()
+{
+    return getpid();
+}
+
+#endif
diff --git a/port/cpl_multiproc.h b/port/cpl_multiproc.h
index 0b39b93..0a3cfba 100644
--- a/port/cpl_multiproc.h
+++ b/port/cpl_multiproc.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_multiproc.h 28470 2015-02-12 21:01:32Z rouault $
+ * $Id: cpl_multiproc.h 33817 2016-03-30 17:35:37Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  CPL Multi-Threading, and process handling portability functions.
@@ -15,21 +15,21 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _CPL_MULTIPROC_H_INCLUDED_
-#define _CPL_MULTIPROC_H_INCLUDED_
+#ifndef CPL_MULTIPROC_H_INCLUDED_
+#define CPL_MULTIPROC_H_INCLUDED_
 
 #include "cpl_port.h"
 
@@ -72,6 +72,7 @@ typedef struct _CPLJoinableThread CPLJoinableThread;
 /* Options for CPLCreateMutexEx() and CPLCreateOrAcquireMutexEx() */
 #define CPL_MUTEX_RECURSIVE         0
 #define CPL_MUTEX_ADAPTIVE          1
+#define CPL_MUTEX_REGULAR           2
 
 CPLMutex CPL_DLL *CPLCreateMutex( void ); /* returned acquired */
 CPLMutex CPL_DLL *CPLCreateMutexEx( int nOptions ); /* returned acquired */
@@ -88,10 +89,12 @@ void  CPL_DLL  CPLCondSignal( CPLCond *hCond );
 void  CPL_DLL  CPLCondBroadcast( CPLCond *hCond );
 void  CPL_DLL  CPLDestroyCond( CPLCond *hCond );
 
+/** Contrary to what its name suggests, CPLGetPID() actually returns the thread id */
 GIntBig CPL_DLL CPLGetPID( void );
+int CPL_DLL CPLGetCurrentProcessID( void );
 int   CPL_DLL CPLCreateThread( CPLThreadFunc pfnMain, void *pArg );
 CPLJoinableThread  CPL_DLL* CPLCreateJoinableThread( CPLThreadFunc pfnMain, void *pArg );
-void  CPL_DLL CPLJoinThread(CPLJoinableThread* hJoinableThread); 
+void  CPL_DLL CPLJoinThread(CPLJoinableThread* hJoinableThread);
 void  CPL_DLL CPLSleep( double dfWaitInSeconds );
 
 const char CPL_DLL *CPLGetThreadingModel( void );
@@ -123,14 +126,14 @@ CPL_C_END
 
 #ifdef __cplusplus
 
-/* Instanciates the mutex if not already done. The parameter x should be a (void**)  */
+/* Instantiates the mutex if not already done. The parameter x should be a (void**). */
 #define CPLMutexHolderD(x)  CPLMutexHolder oHolder(x,1000.0,__FILE__,__LINE__);
 
-/* Instanciates the mutex with options if not already done. */
-/* The parameter x should be a (void**)  */
+/* Instantiates the mutex with options if not already done. */
+/* The parameter x should be a (void**). */
 #define CPLMutexHolderExD(x, nOptions)  CPLMutexHolder oHolder(x,1000.0,__FILE__,__LINE__,nOptions);
 
-/* This variant assumes the the mutex has already been created. If not, it will */
+/* This variant assumes the mutex has already been created. If not, it will */
 /* be a no-op. The parameter x should be a (void*) */
 #define CPLMutexHolderOptionalLockD(x)  CPLMutexHolder oHolder(x,1000.0,__FILE__,__LINE__);
 
@@ -143,13 +146,13 @@ class CPL_DLL CPLMutexHolder
 
   public:
 
-    /* Instanciates the mutex if not already done */
+    /* Instantiates the mutex if not already done. */
     CPLMutexHolder( CPLMutex **phMutex, double dfWaitInSeconds = 1000.0,
                     const char *pszFile = __FILE__,
                     int nLine = __LINE__,
                     int nOptions = CPL_MUTEX_RECURSIVE);
 
-    /* This variant assumes the the mutex has already been created. If not, it will */
+    /* This variant assumes the mutex has already been created. If not, it will */
     /* be a no-op */
     CPLMutexHolder( CPLMutex* hMutex, double dfWaitInSeconds = 1000.0,
                     const char *pszFile = __FILE__,
@@ -158,10 +161,10 @@ class CPL_DLL CPLMutexHolder
     ~CPLMutexHolder();
 };
 
-/* Instanciates the lock if not already done. The parameter x should be a (CPLLock**) */
+/* Instantiates the lock if not already done. The parameter x should be a (CPLLock**). */
 #define CPLLockHolderD(x, eType)  CPLLockHolder oHolder(x,eType,__FILE__,__LINE__);
 
-/* This variant assumes the the lock has already been created. If not, it will */
+/* This variant assumes the lock has already been created. If not, it will */
 /* be a no-op. The parameter should be (CPLLock*) */
 #define CPLLockHolderOptionalLockD(x)  CPLLockHolder oHolder(x,__FILE__,__LINE__);
 
@@ -174,12 +177,12 @@ class CPL_DLL CPLLockHolder
 
   public:
 
-    /* Instanciates the lock if not already done */
+    /* Instantiates the lock if not already done. */
     CPLLockHolder( CPLLock **phSpin, CPLLockType eType,
                     const char *pszFile = __FILE__,
                     int nLine = __LINE__);
 
-    /* This variant assumes the the lock has already been created. If not, it will */
+    /* This variant assumes the lock has already been created. If not, it will */
     /* be a no-op */
     CPLLockHolder( CPLLock* hSpin,
                     const char *pszFile = __FILE__,
@@ -195,34 +198,37 @@ class CPL_DLL CPLLockHolder
 /*      Thread local storage.                                           */
 /* -------------------------------------------------------------------- */
 
-#define CTLS_RLBUFFERINFO     		1         /* cpl_conv.cpp */
-#define CTLS_WIN32_COND                 2         /* cpl_multiproc.cpp */
-#define CTLS_CSVTABLEPTR                3         /* cpl_csv.cpp */
-#define CTLS_CSVDEFAULTFILENAME         4         /* cpl_csv.cpp */
-#define CTLS_ERRORCONTEXT               5         /* cpl_error.cpp */
+#define CTLS_RLBUFFERINFO                1         /* cpl_conv.cpp */
+#define CTLS_WIN32_COND                  2         /* cpl_multiproc.cpp */
+#define CTLS_CSVTABLEPTR                 3         /* cpl_csv.cpp */
+#define CTLS_CSVDEFAULTFILENAME          4         /* cpl_csv.cpp */
+#define CTLS_ERRORCONTEXT                5         /* cpl_error.cpp */
 #define CTLS_GDALDATASET_REC_PROTECT_MAP 6        /* gdaldataset.cpp */
-#define CTLS_PATHBUF                    7         /* cpl_path.cpp */
-#define CTLS_UNUSED3                    8
-#define CTLS_UNUSED4                    9
-#define CTLS_CPLSPRINTF                10         /* cpl_string.h */
-#define CTLS_RESPONSIBLEPID            11         /* gdaldataset.cpp */
-#define CTLS_VERSIONINFO               12         /* gdal_misc.cpp */
-#define CTLS_VERSIONINFO_LICENCE       13         /* gdal_misc.cpp */
-#define CTLS_CONFIGOPTIONS             14         /* cpl_conv.cpp */
-#define CTLS_FINDFILE                  15         /* cpl_findfile.cpp */
-
-#define CTLS_MAX                       32         
+#define CTLS_PATHBUF                     7         /* cpl_path.cpp */
+#define CTLS_UNUSED3                     8
+#define CTLS_UNUSED4                     9
+#define CTLS_CPLSPRINTF                 10         /* cpl_string.h */
+#define CTLS_RESPONSIBLEPID             11         /* gdaldataset.cpp */
+#define CTLS_VERSIONINFO                12         /* gdal_misc.cpp */
+#define CTLS_VERSIONINFO_LICENCE        13         /* gdal_misc.cpp */
+#define CTLS_CONFIGOPTIONS              14         /* cpl_conv.cpp */
+#define CTLS_FINDFILE                   15         /* cpl_findfile.cpp */
+#define CTLS_VSIERRORCONTEXT            16         /* cpl_vsi_error.cpp */
+
+#define CTLS_MAX                        32
 
 CPL_C_START
 void CPL_DLL * CPLGetTLS( int nIndex );
+void CPL_DLL * CPLGetTLSEx( int nIndex, int* pbMemoryErrorOccurred );
 void CPL_DLL CPLSetTLS( int nIndex, void *pData, int bFreeOnExit );
 
 /* Warning : the CPLTLSFreeFunc must not in any case directly or indirectly */
 /* use or fetch any TLS data, or a terminating thread will hang ! */
 typedef void (*CPLTLSFreeFunc)( void* pData );
 void CPL_DLL CPLSetTLSWithFreeFunc( int nIndex, void *pData, CPLTLSFreeFunc pfnFree );
+void CPL_DLL CPLSetTLSWithFreeFuncEx( int nIndex, void *pData, CPLTLSFreeFunc pfnFree, int* pbMemoryErrorOccurred );
 
 void CPL_DLL CPLCleanupTLS( void );
 CPL_C_END
 
-#endif /* _CPL_MULTIPROC_H_INCLUDED_ */
+#endif /* CPL_MULTIPROC_H_INCLUDED_ */
diff --git a/port/cpl_odbc.cpp b/port/cpl_odbc.cpp
index 0dbb4a8..b3acd18 100644
--- a/port/cpl_odbc.cpp
+++ b/port/cpl_odbc.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_odbc.cpp 29027 2015-04-26 18:29:41Z tamas $
+ * $Id: cpl_odbc.cpp 33807 2016-03-29 19:06:42Z tamas $
  *
  * Project:  OGR ODBC Driver
  * Purpose:  Declarations for ODBC Access Cover API.
@@ -34,11 +34,9 @@
 #include "cpl_error.h"
 
 
-#ifndef WIN32CE /* ODBC is not supported on Windows CE. */
+CPL_CVSID("$Id: cpl_odbc.cpp 33807 2016-03-29 19:06:42Z tamas $");
 
-CPL_CVSID("$Id: cpl_odbc.cpp 29027 2015-04-26 18:29:41Z tamas $");
-
-#ifndef SQLColumns_TABLE_CAT 
+#ifndef SQLColumns_TABLE_CAT
 #define SQLColumns_TABLE_CAT 1
 #define SQLColumns_TABLE_SCHEM 2
 #define SQLColumns_TABLE_NAME 3
@@ -63,8 +61,9 @@ CPL_CVSID("$Id: cpl_odbc.cpp 29027 2015-04-26 18:29:41Z tamas $");
 /*                           CPLODBCDriverInstaller()                   */
 /************************************************************************/
 
-CPLODBCDriverInstaller::CPLODBCDriverInstaller()
-    : m_nUsageCount(0)
+CPLODBCDriverInstaller::CPLODBCDriverInstaller() :
+    m_nErrorCode(0),
+    m_nUsageCount(0)
 {
     memset( m_szPathOut, '\0', ODBC_FILENAME_MAX );
     memset( m_szError, '\0', SQL_MAX_MESSAGE_LENGTH );
@@ -102,11 +101,13 @@ int CPLODBCDriverInstaller::InstallDriver( const char* pszDriver,
             CPLDebug( "ODBC", "HOME=%s", pszEnvHome );
 
             // Set ODBCSYSINI variable pointing to HOME location
-            pszEnvIni = (char *)CPLMalloc( strlen(pszEnvHome) + 12 );
+            const size_t nLen = strlen(pszEnvHome) + 12;
+            pszEnvIni = (char *)CPLMalloc( nLen );
 
-            sprintf( pszEnvIni, "ODBCSYSINI=%s", pszEnvHome );
+            snprintf( pszEnvIni, nLen, "ODBCSYSINI=%s", pszEnvHome );
             /* a 'man putenv' shows that we cannot free pszEnvIni */
             /* because the pointer is used directly by putenv in old glibc */
+            /* coverity[tainted_string] */
             putenv( pszEnvIni );
 
             CPLDebug( "ODBC", "%s", pszEnvIni );
@@ -136,7 +137,7 @@ int CPLODBCDriverInstaller::InstallDriver( const char* pszDriver,
 
 int CPLODBCDriverInstaller::RemoveDriver( const char* pszDriverName, int fRemoveDSN )
 {
-    CPLAssert( NULL != pszDriverName ); 
+    CPLAssert( NULL != pszDriverName );
 
     if ( FALSE == SQLRemoveDriver( pszDriverName, fRemoveDSN, &m_nUsageCount ) )
     {
@@ -184,7 +185,7 @@ CPLODBCSession::~CPLODBCSession()
 int CPLODBCSession::CloseSession()
 
 {
-    if( m_hDBC!=NULL ) 
+    if( m_hDBC!=NULL )
     {
         if ( IsInTransaction() )
             CPLError( CE_Warning, CPLE_AppDefined, "Closing session with active transactions." );
@@ -193,7 +194,7 @@ int CPLODBCSession::CloseSession()
         SQLFreeConnect( m_hDBC );
         m_hDBC = NULL;
     }
-    
+
     if( m_hEnv!=NULL )
     {
         SQLFreeEnv( m_hEnv );
@@ -295,12 +296,11 @@ int CPLODBCSession::RollbackTransaction()
 
     if (m_bInTransaction)
     {
+        /* Rollback should not hide the previous error so Failed() is not called. */
+        int nRetCode = SQLEndTran( SQL_HANDLE_DBC, m_hDBC, SQL_ROLLBACK );
         m_bInTransaction = FALSE;
 
-        if( Failed( SQLEndTran( SQL_HANDLE_DBC, m_hDBC, SQL_ROLLBACK ) ) )
-        {
-            return FALSE;
-        }
+        return (nRetCode == SQL_SUCCESS || nRetCode == SQL_SUCCESS_WITH_INFO );
     }
 
 #endif
@@ -327,7 +327,7 @@ int CPLODBCSession::Failed( int nRetCode, HSTMT hStmt )
         return FALSE;
 
     SQLError( m_hEnv, m_hDBC, hStmt, achSQLState, &nNativeError,
-              (SQLCHAR *) m_szLastError, sizeof(m_szLastError)-1, 
+              (SQLCHAR *) m_szLastError, sizeof(m_szLastError)-1,
               &nTextLength );
     m_szLastError[nTextLength] = '\0';
 
@@ -348,22 +348,22 @@ int CPLODBCSession::Failed( int nRetCode, HSTMT hStmt )
  * optional.
  *
  * @param pszUserid the userid to logon as, may be NULL if not not required,
- * or provided by the DSN. 
+ * or provided by the DSN.
  *
  * @param pszPassword the password to logon with.   May be NULL if not required
  * or provided by the DSN.
  *
  * @return TRUE on success or FALSE on failure.  Call GetLastError() to get
- * details on failure. 
+ * details on failure.
  */
 
-int CPLODBCSession::EstablishSession( const char *pszDSN, 
-                                      const char *pszUserid, 
+int CPLODBCSession::EstablishSession( const char *pszDSN,
+                                      const char *pszUserid,
                                       const char *pszPassword )
 
 {
     CloseSession();
-    
+
     if( Failed( SQLAllocEnv( &m_hEnv ) ) )
         return FALSE;
 
@@ -373,14 +373,21 @@ int CPLODBCSession::EstablishSession( const char *pszDSN,
         return FALSE;
     }
 
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable : 4996 )  /*  warning C4996: 'SQLSetConnectOption': ODBC API: SQLSetConnectOption is deprecated. Please use SQLSetConnectAttr instead */
+#endif
     SQLSetConnectOption( m_hDBC,SQL_LOGIN_TIMEOUT,30 );
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
 
     if( pszUserid == NULL )
         pszUserid = "";
     if( pszPassword == NULL )
         pszPassword = "";
 
-    int bFailed;
+    int bFailed = FALSE;
     if( strstr(pszDSN,"=") != NULL )
     {
         SQLCHAR szOutConnString[1024];
@@ -388,17 +395,17 @@ int CPLODBCSession::EstablishSession( const char *pszDSN,
 
         CPLDebug( "ODBC", "SQLDriverConnect(%s)", pszDSN );
         bFailed = Failed(
-            SQLDriverConnect( m_hDBC, NULL, 
-                              (SQLCHAR *) pszDSN, (SQLSMALLINT)strlen(pszDSN), 
-                              szOutConnString, sizeof(szOutConnString), 
+            SQLDriverConnect( m_hDBC, NULL,
+                              (SQLCHAR *) pszDSN, (SQLSMALLINT)strlen(pszDSN),
+                              szOutConnString, sizeof(szOutConnString),
                               &nOutConnStringLen, SQL_DRIVER_NOPROMPT ) );
     }
     else
     {
         CPLDebug( "ODBC", "SQLConnect(%s)", pszDSN );
         bFailed = Failed(
-            SQLConnect( m_hDBC, (SQLCHAR *) pszDSN, SQL_NTS, 
-                        (SQLCHAR *) pszUserid, SQL_NTS, 
+            SQLConnect( m_hDBC, (SQLCHAR *) pszDSN, SQL_NTS,
+                        (SQLCHAR *) pszUserid, SQL_NTS,
                         (SQLCHAR *) pszPassword, SQL_NTS ) );
     }
 
@@ -419,7 +426,7 @@ int CPLODBCSession::EstablishSession( const char *pszDSN,
 /**
  * Returns the last ODBC error message.
  *
- * @return pointer to an internal buffer with the error message in it. 
+ * @return pointer to an internal buffer with the error message in it.
  * Do not free or alter.  Will be an empty (but not NULL) string if there is
  * no pending error info.
  */
@@ -445,13 +452,6 @@ CPLODBCStatement::CPLODBCStatement( CPLODBCSession *poSession )
 {
     m_poSession = poSession;
 
-    if( Failed( 
-            SQLAllocStmt( poSession->GetConnection(), &m_hStmt ) ) )
-    {
-        m_hStmt = NULL;
-        return;
-    }
-
     m_nColCount = 0;
     m_papszColNames = NULL;
     m_panColType = NULL;
@@ -467,6 +467,13 @@ CPLODBCStatement::CPLODBCStatement( CPLODBCSession *poSession )
     m_pszStatement = NULL;
     m_nStatementMax = 0;
     m_nStatementLen = 0;
+
+    if( Failed(
+            SQLAllocStmt( poSession->GetConnection(), &m_hStmt ) ) )
+    {
+        m_hStmt = NULL;
+        return;
+    }
 }
 
 /************************************************************************/
@@ -489,13 +496,13 @@ CPLODBCStatement::~CPLODBCStatement()
 /**
  * Execute an SQL statement.
  *
- * This method will execute the passed (or stored) SQL statement, 
- * and initialize information about the resultset if there is one. 
+ * This method will execute the passed (or stored) SQL statement,
+ * and initialize information about the resultset if there is one.
  * If a NULL statement is passed, the internal stored statement that
- * has been previously set via Append() or Appendf() calls will be used. 
+ * has been previously set via Append() or Appendf() calls will be used.
  *
  * @param pszStatement the SQL statement to execute, or NULL if the
- * internally saved one should be used. 
+ * internally saved one should be used.
  *
  * @return TRUE on success or FALSE if there is an error.  Error details
  * can be fetched with OGRODBCSession::GetLastError().
@@ -526,7 +533,9 @@ int CPLODBCStatement::ExecuteSQL( const char *pszStatement )
 
 #endif
 
-    if( Failed( 
+    /* SQL_NTS=-3 is a valid value for SQLExecDirect */
+    /* coverity[negative_returns] */
+    if( Failed(
             SQLExecDirect( m_hStmt, (SQLCHAR *) m_pszStatement, SQL_NTS ) ) )
         return FALSE;
 
@@ -554,11 +563,11 @@ int CPLODBCStatement::CollectResultsInfo()
 /* -------------------------------------------------------------------- */
     m_papszColNames = (char **) CPLCalloc(sizeof(char *),(m_nColCount+1));
     m_papszColValues = (char **) CPLCalloc(sizeof(char *),(m_nColCount+1));
-    m_panColValueLengths = (_SQLLEN *) CPLCalloc(sizeof(_SQLLEN),(m_nColCount+1));
+    m_panColValueLengths = (CPL_SQLLEN *) CPLCalloc(sizeof(CPL_SQLLEN),(m_nColCount+1));
 
     m_panColType = (SQLSMALLINT *) CPLCalloc(sizeof(SQLSMALLINT),m_nColCount);
     m_papszColTypeNames = (char **) CPLCalloc(sizeof(char *),(m_nColCount+1));
-    m_panColSize = (_SQLULEN *) CPLCalloc(sizeof(_SQLULEN),m_nColCount);
+    m_panColSize = (CPL_SQLULEN *) CPLCalloc(sizeof(CPL_SQLULEN),m_nColCount);
     m_panColPrecision = (SQLSMALLINT *) CPLCalloc(sizeof(SQLSMALLINT),m_nColCount);
     m_panColNullable = (SQLSMALLINT *) CPLCalloc(sizeof(SQLSMALLINT),m_nColCount);
     m_papszColColumnDef = (char **) CPLCalloc(sizeof(char *),(m_nColCount+1));
@@ -571,7 +580,7 @@ int CPLODBCStatement::CollectResultsInfo()
         SQLCHAR     szName[256];
         SQLSMALLINT nNameLength = 0;
 
-        if ( Failed( SQLDescribeCol(m_hStmt, iCol+1, 
+        if ( Failed( SQLDescribeCol(m_hStmt, iCol+1,
                                     szName, sizeof(szName), &nNameLength,
                                     m_panColType + iCol,
                                     m_panColSize + iCol,
@@ -593,7 +602,7 @@ int CPLODBCStatement::CollectResultsInfo()
         szName[nNameLength] = '\0';  // Paranoid
         m_papszColTypeNames[iCol] = CPLStrdup((const char*)szName);
 
-//        CPLDebug( "ODBC", "%s %s %d", m_papszColNames[iCol], 
+//        CPLDebug( "ODBC", "%s %s %d", m_papszColNames[iCol],
 //                  szName, m_panColType[iCol] );
     }
 
@@ -608,7 +617,7 @@ int CPLODBCStatement::GetRowCountAffected()
 {
     SQLLEN nResultCount=0;
     SQLRowCount( m_hStmt, &nResultCount );
-    
+
     return (int)nResultCount;
 }
 
@@ -617,7 +626,7 @@ int CPLODBCStatement::GetRowCountAffected()
 /************************************************************************/
 
 /**
- * Fetch the resultset column count. 
+ * Fetch the resultset column count.
  *
  * @return the column count, or zero if there is no resultset.
  */
@@ -638,7 +647,7 @@ int CPLODBCStatement::GetColCount()
  * @param iCol the zero based column index.
  *
  * @return NULL on failure (out of bounds column), or a pointer to an
- * internal copy of the column name. 
+ * internal copy of the column name.
  */
 
 const char *CPLODBCStatement::GetColName( int iCol )
@@ -657,9 +666,9 @@ const char *CPLODBCStatement::GetColName( int iCol )
 /**
  * Fetch a column data type.
  *
- * The return type code is a an ODBC SQL_ code, one of SQL_UNKNOWN_TYPE, 
+ * The return type code is a an ODBC SQL_ code, one of SQL_UNKNOWN_TYPE,
  * SQL_CHAR, SQL_NUMERIC, SQL_DECIMAL, SQL_INTEGER, SQL_SMALLINT, SQL_FLOAT,
- * SQL_REAL, SQL_DOUBLE, SQL_DATETIME, SQL_VARCHAR, SQL_TYPE_DATE, 
+ * SQL_REAL, SQL_DOUBLE, SQL_DATETIME, SQL_VARCHAR, SQL_TYPE_DATE,
  * SQL_TYPE_TIME, SQL_TYPE_TIMESTAMPT.
  *
  * @param iCol the zero based column index.
@@ -732,7 +741,7 @@ short CPLODBCStatement::GetColSize( int iCol )
  * @param iCol the zero based column index.
  *
  * @return column precision, may be zero or the same as column size for
- * columns to which it does not apply. 
+ * columns to which it does not apply.
  */
 
 short CPLODBCStatement::GetColPrecision( int iCol )
@@ -799,16 +808,16 @@ const char *CPLODBCStatement::GetColColumnDef( int iCol )
  * Requests the next row in the current resultset using the SQLFetchScroll()
  * call.  Note that many ODBC drivers only support the default forward
  * fetching one record at a time.  Only SQL_FETCH_NEXT (the default) should
- * be considered reliable on all drivers. 
+ * be considered reliable on all drivers.
  *
  * Currently it isn't clear how to determine whether an error or a normal
- * out of data condition has occured if Fetch() fails. 
+ * out of data condition has occurred if Fetch() fails.
  *
  * @param nOrientation One of SQL_FETCH_NEXT, SQL_FETCH_LAST, SQL_FETCH_PRIOR,
  * SQL_FETCH_ABSOLUTE, or SQL_FETCH_RELATIVE (default is SQL_FETCH_NEXT).
  *
- * @param nOffset the offset (number of records), ignored for some 
- * orientations.  
+ * @param nOffset the offset (number of records), ignored for some
+ * orientations.
  *
  * @return TRUE if a new row is successfully fetched, or FALSE if not.
  */
@@ -860,11 +869,11 @@ int CPLODBCStatement::Fetch( int nOrientation, int nOffset )
 /*      Pull out all the column values.                                 */
 /* -------------------------------------------------------------------- */
     SQLSMALLINT iCol;
-    
+
     for( iCol = 0; iCol < m_nColCount; iCol++ )
     {
         char szWrkData[513];
-        _SQLLEN cbDataLen;
+        CPL_SQLLEN cbDataLen;
         SQLSMALLINT nFetchType = GetTypeMapping( m_panColType[iCol] );
 
         // Handle values other than WCHAR and BINARY as CHAR.
@@ -875,7 +884,7 @@ int CPLODBCStatement::Fetch( int nOrientation, int nOffset )
         szWrkData[sizeof(szWrkData)-1] = '\0';
 
         nRetCode = SQLGetData( m_hStmt, iCol + 1, nFetchType,
-                               szWrkData, sizeof(szWrkData)-1, 
+                               szWrkData, sizeof(szWrkData)-1,
                                &cbDataLen );
 
 /* SQLGetData() is giving garbage values in the first 4 bytes of cbDataLen *
@@ -901,34 +910,34 @@ int CPLODBCStatement::Fetch( int nOrientation, int nOffset )
         }
 
         // assume big result: should check for state=SQLSATE 01004.
-        else if( nRetCode == SQL_SUCCESS_WITH_INFO  ) 
+        else if( nRetCode == SQL_SUCCESS_WITH_INFO  )
         {
-            if( cbDataLen >= (_SQLLEN)(sizeof(szWrkData)-1) )
+            if( cbDataLen >= (CPL_SQLLEN)(sizeof(szWrkData)-1) )
             {
-                cbDataLen = (_SQLLEN)(sizeof(szWrkData)-1);
-                if (nFetchType == SQL_C_CHAR) 
-                    while ((cbDataLen > 1) && (szWrkData[cbDataLen - 1] == 0)) 
+                cbDataLen = (CPL_SQLLEN)(sizeof(szWrkData)-1);
+                if (nFetchType == SQL_C_CHAR)
+                    while ((cbDataLen > 1) && (szWrkData[cbDataLen - 1] == 0))
                         --cbDataLen; // trimming the extra terminators: bug 990
                 else if (nFetchType == SQL_C_WCHAR)
                     while ((cbDataLen > 1) && (szWrkData[cbDataLen - 1] == 0)
-                        && (szWrkData[cbDataLen - 2] == 0)) 
+                        && (szWrkData[cbDataLen - 2] == 0))
                         cbDataLen -= 2; // trimming the extra terminators
 
             }
-			
+
             m_papszColValues[iCol] = (char *) CPLMalloc(cbDataLen+2);
             memcpy( m_papszColValues[iCol], szWrkData, cbDataLen );
             m_papszColValues[iCol][cbDataLen] = '\0';
             m_papszColValues[iCol][cbDataLen+1] = '\0';
             m_panColValueLengths[iCol] = cbDataLen;
 
-            while( TRUE )
+            while( true )
             {
-                _SQLLEN nChunkLen;
+                CPL_SQLLEN nChunkLen;
 
-                nRetCode = SQLGetData( m_hStmt, (SQLUSMALLINT) iCol+1, 
+                nRetCode = SQLGetData( m_hStmt, (SQLUSMALLINT) iCol+1,
                                        nFetchType,
-                                       szWrkData, sizeof(szWrkData)-1, 
+                                       szWrkData, sizeof(szWrkData)-1,
                                        &cbDataLen );
                 if( nRetCode == SQL_NO_DATA )
                     break;
@@ -944,7 +953,7 @@ int CPLODBCStatement::Fetch( int nOrientation, int nOffset )
                     || cbDataLen == SQL_NO_TOTAL )
                 {
                     nChunkLen = sizeof(szWrkData)-1;
-                    if (nFetchType == SQL_C_CHAR) 
+                    if (nFetchType == SQL_C_CHAR)
                         while ( (nChunkLen > 1)
                                 && (szWrkData[nChunkLen - 1] == 0) )
                             --nChunkLen;  // trimming the extra terminators
@@ -958,10 +967,10 @@ int CPLODBCStatement::Fetch( int nOrientation, int nOffset )
                     nChunkLen = cbDataLen;
                 szWrkData[nChunkLen] = '\0';
 
-                m_papszColValues[iCol] = (char *) 
-                    CPLRealloc( m_papszColValues[iCol], 
+                m_papszColValues[iCol] = (char *)
+                    CPLRealloc( m_papszColValues[iCol],
                                 m_panColValueLengths[iCol] + nChunkLen + 2 );
-                memcpy( m_papszColValues[iCol] + m_panColValueLengths[iCol], 
+                memcpy( m_papszColValues[iCol] + m_panColValueLengths[iCol],
                         szWrkData, nChunkLen );
                 m_panColValueLengths[iCol] += nChunkLen;
                 m_papszColValues[iCol][m_panColValueLengths[iCol]] = '\0';
@@ -988,12 +997,12 @@ int CPLODBCStatement::Fetch( int nOrientation, int nOffset )
         }
 
         // Convert WCHAR to UTF-8, assuming the WCHAR is UCS-2.
-        if( nFetchType == SQL_C_WCHAR && m_papszColValues[iCol] != NULL 
+        if( nFetchType == SQL_C_WCHAR && m_papszColValues[iCol] != NULL
             && m_panColValueLengths[iCol] > 0 )
         {
             wchar_t *pwszSrc = (wchar_t *) m_papszColValues[iCol];
 
-            m_papszColValues[iCol] = 
+            m_papszColValues[iCol] =
                 CPLRecodeFromWChar( pwszSrc, CPL_ENC_UCS2, CPL_ENC_UTF8 );
             m_panColValueLengths[iCol] = strlen(m_papszColValues[iCol]);
 
@@ -1009,14 +1018,14 @@ int CPLODBCStatement::Fetch( int nOrientation, int nOffset )
 /************************************************************************/
 
 /**
- * Fetch column data. 
+ * Fetch column data.
  *
  * Fetches the data contents of the requested column for the currently loaded
- * row.  The result is returned as a string regardless of the column type.  
+ * row.  The result is returned as a string regardless of the column type.
  * NULL is returned if an illegal column is given, or if the actual column
- * is "NULL". 
- * 
- * @param iCol the zero based column to fetch. 
+ * is "NULL".
+ *
+ * @param iCol the zero based column to fetch.
  *
  * @param pszDefault the value to return if the column does not exist, or is
  * NULL.  Defaults to NULL.
@@ -1040,13 +1049,13 @@ const char *CPLODBCStatement::GetColData( int iCol, const char *pszDefault )
 /************************************************************************/
 
 /**
- * Fetch column data. 
+ * Fetch column data.
  *
  * Fetches the data contents of the requested column for the currently loaded
- * row.  The result is returned as a string regardless of the column type.  
+ * row.  The result is returned as a string regardless of the column type.
  * NULL is returned if an illegal column is given, or if the actual column
- * is "NULL". 
- * 
+ * is "NULL".
+ *
  * @param pszColName the name of the column requested.
  *
  * @param pszDefault the value to return if the column does not exist, or is
@@ -1055,7 +1064,7 @@ const char *CPLODBCStatement::GetColData( int iCol, const char *pszDefault )
  * @return pointer to internal column data or NULL on failure.
  */
 
-const char *CPLODBCStatement::GetColData( const char *pszColName, 
+const char *CPLODBCStatement::GetColData( const char *pszColName,
                                           const char *pszDefault )
 
 {
@@ -1090,9 +1099,9 @@ int CPLODBCStatement::GetColDataLength( int iCol )
  * Fetch column index.
  *
  * Gets the column index corresponding with the passed name.  The
- * name comparisons are case insensitive. 
+ * name comparisons are case insensitive.
  *
- * @param pszColName the name to search for. 
+ * @param pszColName the name to search for.
  *
  * @return the column index, or -1 if not found.
  */
@@ -1103,7 +1112,7 @@ int CPLODBCStatement::GetColId( const char *pszColName )
     for( SQLSMALLINT iCol = 0; iCol < m_nColCount; iCol++ )
         if( EQUAL(pszColName, m_papszColNames[iCol]) )
             return iCol;
-    
+
     return -1;
 }
 
@@ -1147,7 +1156,7 @@ int CPLODBCStatement::Failed( int nResultCode )
 /**
  * Append text to internal command.
  *
- * The passed text is appended to the internal SQL command text. 
+ * The passed text is appended to the internal SQL command text.
  *
  * @param pszText text to append.
  */
@@ -1182,9 +1191,9 @@ void CPLODBCStatement::Append( const char *pszText )
 /**
  * Append text to internal command.
  *
- * The passed text is appended to the internal SQL command text after 
+ * The passed text is appended to the internal SQL command text after
  * escaping any special characters so it can be used as a character string
- * in an SQL statement. 
+ * in an SQL statement.
  *
  * @param pszText text to append.
  */
@@ -1232,9 +1241,9 @@ void CPLODBCStatement::AppendEscaped( const char *pszText )
 void CPLODBCStatement::Append( int nValue )
 
 {
-    char szFormattedValue[100];
+    char szFormattedValue[32];
 
-    sprintf( szFormattedValue, "%d", nValue );
+    snprintf( szFormattedValue, sizeof(szFormattedValue), "%d", nValue );
     Append( szFormattedValue );
 }
 
@@ -1255,7 +1264,7 @@ void CPLODBCStatement::Append( double dfValue )
 {
     char szFormattedValue[100];
 
-    sprintf( szFormattedValue, "%24g", dfValue );
+    snprintf( szFormattedValue, sizeof(szFormattedValue), "%24g", dfValue );
     Append( szFormattedValue );
 }
 
@@ -1271,24 +1280,28 @@ void CPLODBCStatement::Append( double dfValue )
  * properly, and should be appended with the direct Append() methods.
  *
  * @param pszFormat printf() style format string.
- * 
- * @return FALSE if formatting fails dueto result being too large.
+ *
+ * @return FALSE if formatting fails due to result being too large.
  */
 
 int CPLODBCStatement::Appendf( const char *pszFormat, ... )
 
 {
     va_list args;
-    char    szFormattedText[8000];
-    int     bSuccess;
 
     va_start( args, pszFormat );
+
+    char szFormattedText[8000];  // TODO: Move this off the stack.
+    szFormattedText[0] = '\0';
+
 #if defined(HAVE_VSNPRINTF)
-    bSuccess = vsnprintf( szFormattedText, sizeof(szFormattedText)-1, 
-                          pszFormat, args ) < (int) sizeof(szFormattedText)-1;
+    const bool bSuccess =
+        vsnprintf( szFormattedText, sizeof(szFormattedText)-1,
+                   pszFormat, args )
+        < static_cast<int>( sizeof(szFormattedText) - 1 );
 #else
     vsprintf( szFormattedText, pszFormat, args );
-    bSuccess = TRUE;
+    const bool bSuccess = true;
 #endif
     va_end( args );
 
@@ -1297,7 +1310,7 @@ int CPLODBCStatement::Appendf( const char *pszFormat, ... )
 
     return bSuccess;
 }
-                                
+
 /************************************************************************/
 /*                               Clear()                                */
 /************************************************************************/
@@ -1312,7 +1325,7 @@ void CPLODBCStatement::Clear()
     /* Closing the cursor if opened */
     if( m_hStmt != NULL )
         SQLFreeStmt( m_hStmt, SQL_CLOSE );
-    
+
     ClearColumnData();
 
     if( m_pszStatement != NULL )
@@ -1366,7 +1379,7 @@ void CPLODBCStatement::Clear()
  * Fetch column definitions for a table.
  *
  * The SQLColumn() method is used to fetch the definitions for the columns
- * of a table (or other queriable object such as a view).  The column
+ * of a table (or other queryable object such as a view).  The column
  * definitions are digested and used to populate the CPLODBCStatement
  * column definitions essentially as if a "SELECT * FROM tablename" had
  * been done; however, no resultset will be available.
@@ -1375,15 +1388,15 @@ void CPLODBCStatement::Clear()
  * should not be empty.
  *
  * @param pszCatalog the catalog to find the table in, use NULL (the
- * default) if no catalog is available. 
+ * default) if no catalog is available.
  *
  * @param pszSchema the schema to find the table in, use NULL (the
- * default) if no schema is available. 
+ * default) if no schema is available.
  *
- * @return TRUE on success or FALSE on failure. 
+ * @return TRUE on success or FALSE on failure.
  */
 
-int CPLODBCStatement::GetColumns( const char *pszTable, 
+int CPLODBCStatement::GetColumns( const char *pszTable,
                                   const char *pszCatalog,
                                   const char *pszSchema )
 
@@ -1407,7 +1420,7 @@ int CPLODBCStatement::GetColumns( const char *pszTable,
 /* -------------------------------------------------------------------- */
 /*      Fetch columns resultset for this table.                         */
 /* -------------------------------------------------------------------- */
-    if( Failed( SQLColumns( m_hStmt, 
+    if( Failed( SQLColumns( m_hStmt,
                             (SQLCHAR *) pszCatalog, SQL_NTS,
                             (SQLCHAR *) pszSchema, SQL_NTS,
                             (SQLCHAR *) pszTable, SQL_NTS,
@@ -1432,13 +1445,13 @@ int CPLODBCStatement::GetColumns( const char *pszTable,
 #endif
 
     m_nColCount = 500;
-    
+
     m_papszColNames = (char **) CPLCalloc(sizeof(char *),(m_nColCount+1));
     m_papszColValues = (char **) CPLCalloc(sizeof(char *),(m_nColCount+1));
 
     m_panColType = (SQLSMALLINT *) CPLCalloc(sizeof(SQLSMALLINT),m_nColCount);
     m_papszColTypeNames = (char **) CPLCalloc(sizeof(char *),(m_nColCount+1));
-    m_panColSize = (_SQLULEN *) CPLCalloc(sizeof(_SQLULEN),m_nColCount);
+    m_panColSize = (CPL_SQLULEN *) CPLCalloc(sizeof(CPL_SQLULEN),m_nColCount);
     m_panColPrecision = (SQLSMALLINT *) CPLCalloc(sizeof(SQLSMALLINT),m_nColCount);
     m_panColNullable = (SQLSMALLINT *) CPLCalloc(sizeof(SQLSMALLINT),m_nColCount);
     m_papszColColumnDef = (char **) CPLCalloc(sizeof(char *),(m_nColCount+1));
@@ -1451,7 +1464,7 @@ int CPLODBCStatement::GetColumns( const char *pszTable,
     for( iCol = 0; iCol < m_nColCount; iCol++ )
     {
         char szWrkData[8193];
-        _SQLLEN cbDataLen;
+        CPL_SQLLEN cbDataLen;
 
         if( Failed( SQLFetch( m_hStmt ) ) )
         {
@@ -1512,15 +1525,15 @@ int CPLODBCStatement::GetColumns( const char *pszTable,
  * should not be empty.
  *
  * @param pszCatalog the catalog to find the table in, use NULL (the
- * default) if no catalog is available. 
+ * default) if no catalog is available.
  *
  * @param pszSchema the schema to find the table in, use NULL (the
- * default) if no schema is available. 
+ * default) if no schema is available.
  *
- * @return TRUE on success or FALSE on failure. 
+ * @return TRUE on success or FALSE on failure.
  */
 
-int CPLODBCStatement::GetPrimaryKeys( const char *pszTable, 
+int CPLODBCStatement::GetPrimaryKeys( const char *pszTable,
                                       const char *pszCatalog,
                                       const char *pszSchema )
 
@@ -1543,7 +1556,7 @@ int CPLODBCStatement::GetPrimaryKeys( const char *pszTable,
 /* -------------------------------------------------------------------- */
 /*      Fetch columns resultset for this table.                         */
 /* -------------------------------------------------------------------- */
-    if( Failed( SQLPrimaryKeys( m_hStmt, 
+    if( Failed( SQLPrimaryKeys( m_hStmt,
                                 (SQLCHAR *) pszCatalog, SQL_NTS,
                                 (SQLCHAR *) pszSchema, SQL_NTS,
                                 (SQLCHAR *) pszTable, SQL_NTS ) ) )
@@ -1562,15 +1575,15 @@ int CPLODBCStatement::GetPrimaryKeys( const char *pszTable,
  * The SQLTables() function is used to fetch a list tables in the
  * database.    The result is returned as a result set matching
  * the SQLTables() function result set.  The 3rd column in the result
- * set is the table name.  Only tables of type "TABLE" are returned. 
+ * set is the table name.  Only tables of type "TABLE" are returned.
  *
  * @param pszCatalog the catalog to find the table in, use NULL (the
- * default) if no catalog is available. 
+ * default) if no catalog is available.
  *
  * @param pszSchema the schema to find the table in, use NULL (the
- * default) if no schema is available. 
+ * default) if no schema is available.
  *
- * @return TRUE on success or FALSE on failure. 
+ * @return TRUE on success or FALSE on failure.
  */
 
 int CPLODBCStatement::GetTables( const char *pszCatalog,
@@ -1593,7 +1606,7 @@ int CPLODBCStatement::GetTables( const char *pszCatalog,
 /* -------------------------------------------------------------------- */
 /*      Fetch columns resultset for this table.                         */
 /* -------------------------------------------------------------------- */
-    if( Failed( SQLTables( m_hStmt, 
+    if( Failed( SQLTables( m_hStmt,
                            (SQLCHAR *) pszCatalog, SQL_NTS,
                            (SQLCHAR *) pszSchema, SQL_NTS,
                            (SQLCHAR *) NULL, SQL_NTS,
@@ -1612,9 +1625,9 @@ int CPLODBCStatement::GetTables( const char *pszCatalog,
  *
  * The contents of the current resultset are dumped in a simply formatted
  * form to the provided file.  If requested, the schema definition will
- * be written first. 
+ * be written first.
  *
- * @param fp the file to write to.  stdout or stderr are acceptable. 
+ * @param fp the file to write to.  stdout or stderr are acceptable.
  *
  * @param bShowSchema TRUE to force writing schema information for the rowset
  * before the rowset data itself.  Default is FALSE.
@@ -1623,20 +1636,18 @@ int CPLODBCStatement::GetTables( const char *pszCatalog,
 void CPLODBCStatement::DumpResult( FILE *fp, int bShowSchema )
 
 {
-    int iCol;
-
 /* -------------------------------------------------------------------- */
 /*      Display schema                                                  */
 /* -------------------------------------------------------------------- */
     if( bShowSchema )
     {
         fprintf( fp, "Column Definitions:\n" );
-        for( iCol = 0; iCol < GetColCount(); iCol++ )
+        for( int iCol = 0; iCol < GetColCount(); iCol++ )
         {
             fprintf( fp, " %2d: %-24s ", iCol, GetColName(iCol) );
-            if( GetColPrecision(iCol) > 0 
+            if( GetColPrecision(iCol) > 0
                 && GetColPrecision(iCol) != GetColSize(iCol) )
-                fprintf( fp, " Size:%3d.%d", 
+                fprintf( fp, " Size:%3d.%d",
                          GetColSize(iCol), GetColPrecision(iCol) );
             else
                 fprintf( fp, " Size:%5d", GetColSize(iCol) );
@@ -1657,8 +1668,8 @@ void CPLODBCStatement::DumpResult( FILE *fp, int bShowSchema )
     while( Fetch() )
     {
         fprintf( fp, "Record %d\n", iRecord++ );
-        
-        for( iCol = 0; iCol < GetColCount(); iCol++ )
+
+        for( int iCol = 0; iCol < GetColCount(); iCol++ )
         {
             fprintf( fp, "  %s: %s\n", GetColName(iCol), GetColData(iCol) );
         }
@@ -1677,7 +1688,7 @@ void CPLODBCStatement::DumpResult( FILE *fp, int bShowSchema )
  *
  * @param nTypeCode the SQL_ code, such as SQL_CHAR.
  *
- * @return internal string, "UNKNOWN" if code not recognised. 
+ * @return internal string, "UNKNOWN" if code not recognised.
  */
 
 CPLString CPLODBCStatement::GetTypeName( int nTypeCode )
@@ -1687,29 +1698,28 @@ CPLString CPLODBCStatement::GetTypeName( int nTypeCode )
     {
       case SQL_CHAR:
         return "CHAR";
-        
+
       case SQL_NUMERIC:
         return "NUMERIC";
-        
+
       case SQL_DECIMAL:
         return "DECIMAL";
-        
+
       case SQL_INTEGER:
         return "INTEGER";
-        
+
       case SQL_SMALLINT:
         return "SMALLINT";
 
-        
       case SQL_FLOAT:
         return "FLOAT";
-        
+
       case SQL_REAL:
         return "REAL";
 
       case SQL_DOUBLE:
         return "DOUBLE";
-        
+
       case SQL_DATETIME:
         return "DATETIME";
 
@@ -1721,7 +1731,7 @@ CPLString CPLODBCStatement::GetTypeName( int nTypeCode )
 
       case SQL_TYPE_TIME:
         return "TIME";
-        
+
       case SQL_TYPE_TIMESTAMP:
         return "TIMESTAMP";
 
@@ -1818,11 +1828,10 @@ SQLSMALLINT CPLODBCStatement::GetTypeMapping( SQLSMALLINT nTypeCode )
         case SQL_BINARY:
         case SQL_VARBINARY:
         case SQL_LONGVARBINARY:
+        case -151: /*SQL_SS_UDT*/
             return SQL_C_BINARY;
 
         default:
             return SQL_C_CHAR;
     }
 }
-
-#endif /* #ifndef WIN32CE */
diff --git a/port/cpl_odbc.h b/port/cpl_odbc.h
index 6ada6ce..a97f0f1 100644
--- a/port/cpl_odbc.h
+++ b/port/cpl_odbc.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_odbc.h 29025 2015-04-26 11:50:20Z tamas $
+ * $Id: cpl_odbc.h 33666 2016-03-07 05:21:07Z goatbar $
  *
  * Project:  OGR ODBC Driver
  * Purpose:  Declarations for ODBC Access Cover API.
@@ -32,8 +32,6 @@
 
 #include "cpl_port.h"
 
-#ifndef WIN32CE /* ODBC is not supported on Windows CE. */
-
 #ifdef WIN32
 #  include <windows.h>
 #endif
@@ -49,7 +47,7 @@
 #  define ODBC_FILENAME_MAX (255 + 1) /* Max path length */
 #endif
 
- 
+
 /**
  * \file cpl_odbc.h
  *
@@ -67,7 +65,7 @@ class CPL_DLL CPLODBCDriverInstaller
     DWORD m_nUsageCount;
 
   public:
-    
+
     // Default constructor.
     CPLODBCDriverInstaller();
 
@@ -75,7 +73,7 @@ class CPL_DLL CPLODBCDriverInstaller
     /**
      * Installs ODBC driver or updates definition of already installed driver.
      * Interanally, it calls ODBC's SQLInstallDriverEx function.
-     * 
+     *
      * @param pszDriver - The driver definition as a list of keyword-value
      * pairs describing the driver (See ODBC API Reference).
      *
@@ -98,10 +96,10 @@ class CPL_DLL CPLODBCDriverInstaller
      *
      * @param pszDriverName - The name of the driver as registered in
      * the Odbcinst.ini key of the system information.
-     * 
-     * @param fRemoveDSN - TRUE: Remove DSNs associated with the driver 
+     *
+     * @param fRemoveDSN - TRUE: Remove DSNs associated with the driver
      * specified in lpszDriver. FALSE: Do not remove DSNs associated
-     * with the driver specified in lpszDriver. 
+     * with the driver specified in lpszDriver.
      *
      * @return The function returns TRUE if it is successful,
      * FALSE if it fails. If no entry exists in the system information
@@ -117,7 +115,7 @@ class CPL_DLL CPLODBCDriverInstaller
 
     // Path of the target directory where the driver should be installed.
     // For details, see ODBC API Reference and lpszPathOut
-    // parameter of SQLInstallDriverEx 
+    // parameter of SQLInstallDriverEx
     const char* GetPathOut() const { return m_szPathOut; }
 
 
@@ -125,7 +123,6 @@ class CPL_DLL CPLODBCDriverInstaller
     // error message can be obtained by calling this function.
     // Internally, it calls ODBC's SQLInstallerError function.
     const char* GetLastError() const { return m_szError; }
-   
 
     // If InstallDriver returns FALSE, then GetLastErrorCode then
     // error code can be obtained by calling this function.
@@ -136,7 +133,7 @@ class CPL_DLL CPLODBCDriverInstaller
 
 class CPLODBCStatement;
 
-/* On MSVC SQLULEN is missing in some cases (ie. VC6)
+/* On MSVC SQLULEN is missing in some cases (i.e. VC6)
 ** but it is always a #define so test this way.   On Unix
 ** it is a typedef so we can't always do this.
 */
@@ -146,16 +143,16 @@ class CPLODBCStatement;
 
 #if !defined(MISSING_SQLULEN)
 /* ODBC types to support 64 bit compilation */
-#  define _SQLULEN SQLULEN
-#  define _SQLLEN  SQLLEN
+#  define CPL_SQLULEN SQLULEN
+#  define CPL_SQLLEN  SQLLEN
 #else
-#  define _SQLULEN SQLUINTEGER
-#  define _SQLLEN  SQLINTEGER
+#  define CPL_SQLULEN SQLUINTEGER
+#  define CPL_SQLLEN  SQLINTEGER
 #endif	/* ifdef SQLULEN */
 
 
 /**
- * A class representing an ODBC database session. 
+ * A class representing an ODBC database session.
  *
  * Includes error collection services.
  */
@@ -171,8 +168,8 @@ class CPL_DLL CPLODBCSession {
     CPLODBCSession();
     ~CPLODBCSession();
 
-    int         EstablishSession( const char *pszDSN, 
-                                  const char *pszUserid, 
+    int         EstablishSession( const char *pszDSN,
+                                  const char *pszUserid,
                                   const char *pszPassword );
     const char  *GetLastError();
 
@@ -184,7 +181,7 @@ class CPL_DLL CPLODBCSession {
     int         RollbackTransaction();
     int         IsInTransaction() { return m_bInTransaction; }
 
-    // Essentially internal. 
+    // Essentially internal.
 
     int         CloseSession();
 
@@ -211,14 +208,14 @@ class CPL_DLL CPLODBCStatement {
     char         **m_papszColNames;
     SQLSMALLINT   *m_panColType;
     char         **m_papszColTypeNames;
-    _SQLULEN      *m_panColSize;
+    CPL_SQLULEN      *m_panColSize;
     SQLSMALLINT   *m_panColPrecision;
     SQLSMALLINT   *m_panColNullable;
     char         **m_papszColColumnDef;
 
     char         **m_papszColValues;
-    _SQLLEN       *m_panColValueLengths;
-    
+    CPL_SQLLEN       *m_panColValueLengths;
+
     int            Failed( int );
 
     char          *m_pszStatement;
@@ -243,7 +240,7 @@ class CPL_DLL CPLODBCStatement {
     int            ExecuteSQL( const char * = NULL );
 
     // Results fetching
-    int            Fetch( int nOrientation = SQL_FETCH_NEXT, 
+    int            Fetch( int nOrientation = SQL_FETCH_NEXT,
                           int nOffset = 0 );
     void           ClearColumnData();
 
@@ -263,10 +260,10 @@ class CPL_DLL CPLODBCStatement {
     int            GetRowCountAffected();
 
     // Fetch special metadata.
-    int            GetColumns( const char *pszTable, 
+    int            GetColumns( const char *pszTable,
                                const char *pszCatalog = NULL,
                                const char *pszSchema = NULL );
-    int            GetPrimaryKeys( const char *pszTable, 
+    int            GetPrimaryKeys( const char *pszTable,
                                    const char *pszCatalog = NULL,
                                    const char *pszSchema = NULL );
 
@@ -281,8 +278,4 @@ class CPL_DLL CPLODBCStatement {
     int            CollectResultsInfo();
 };
 
-#endif /* #ifndef WIN32CE */
-
 #endif
-
-
diff --git a/port/cpl_path.cpp b/port/cpl_path.cpp
index 023a203..f9e5485 100644
--- a/port/cpl_path.cpp
+++ b/port/cpl_path.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_path.cpp 32986 2016-01-14 20:40:01Z rouault $
+ * $Id: cpl_path.cpp 33817 2016-03-30 17:35:37Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Portable filename/path parsing, and forming ala "Glob API".
@@ -15,41 +15,41 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_atomic_ops.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: cpl_path.cpp 32986 2016-01-14 20:40:01Z rouault $");
-
+CPL_CVSID("$Id: cpl_path.cpp 33817 2016-03-30 17:35:37Z rouault $");
 
 /* should be size of larged possible filename */
-#define CPL_PATH_BUF_SIZE 2048
-#define CPL_PATH_BUF_COUNT  10
+static const int CPL_PATH_BUF_SIZE = 2048;
+static const int CPL_PATH_BUF_COUNT = 10;
 
-#if defined(WIN32) || defined(WIN32CE)
-#define SEP_CHAR '\\'
-#define SEP_STRING "\\"
+#if defined(WIN32)
+static const char SEP_STRING[] = "\\";
 #else
-#define SEP_CHAR '/'
-#define SEP_STRING "/"
+static const char SEP_STRING[] = "/";
 #endif
 
 static const char* CPLStaticBufferTooSmall(char *pszStaticResult)
 {
     CPLError(CE_Failure, CPLE_AppDefined, "Destination buffer too small");
+    if( pszStaticResult == NULL )
+        return "";
     strcpy( pszStaticResult, "" );
     return pszStaticResult;
 }
@@ -61,10 +61,18 @@ static const char* CPLStaticBufferTooSmall(char *pszStaticResult)
 static char *CPLGetStaticResult()
 
 {
-    char *pachBufRingInfo = (char *) CPLGetTLS( CTLS_PATHBUF );
+    int bMemoryError = FALSE;
+    char *pachBufRingInfo
+        = static_cast<char *>( CPLGetTLSEx( CTLS_PATHBUF, &bMemoryError ) );
+    if( bMemoryError )
+        return NULL;
     if( pachBufRingInfo == NULL )
     {
-        pachBufRingInfo = (char *) CPLCalloc(1, sizeof(int) + CPL_PATH_BUF_SIZE * CPL_PATH_BUF_COUNT);
+      pachBufRingInfo = static_cast<char *>(
+          VSI_CALLOC_VERBOSE(
+              1, sizeof(int) + CPL_PATH_BUF_SIZE * CPL_PATH_BUF_COUNT ) );
+        if( pachBufRingInfo == NULL )
+            return NULL;
         CPLSetTLS( CTLS_PATHBUF, pachBufRingInfo, TRUE );
     }
 
@@ -72,8 +80,9 @@ static char *CPLGetStaticResult()
 /*      Work out which string in the "ring" we want to use this         */
 /*      time.                                                           */
 /* -------------------------------------------------------------------- */
-    int *pnBufIndex = (int *) pachBufRingInfo;
-    int nOffset = sizeof(int) + *pnBufIndex * CPL_PATH_BUF_SIZE;
+    int *pnBufIndex = reinterpret_cast<int *>( pachBufRingInfo );
+    size_t nOffset
+        = sizeof(int) + static_cast<size_t>( *pnBufIndex * CPL_PATH_BUF_SIZE );
     char *pachBuffer = pachBufRingInfo + nOffset;
 
     *pnBufIndex = (*pnBufIndex + 1) % CPL_PATH_BUF_COUNT;
@@ -89,15 +98,15 @@ static char *CPLGetStaticResult()
 static int CPLFindFilenameStart( const char * pszFilename )
 
 {
-    size_t  iFileStart;
+    size_t iFileStart = strlen(pszFilename);
 
-    for( iFileStart = strlen(pszFilename);
+    for( ;
          iFileStart > 0
              && pszFilename[iFileStart-1] != '/'
              && pszFilename[iFileStart-1] != '\\';
          iFileStart-- ) {}
 
-    return (int)iFileStart;
+    return static_cast<int>( iFileStart );
 }
 
 /************************************************************************/
@@ -129,13 +138,14 @@ static int CPLFindFilenameStart( const char * pszFilename )
 const char *CPLGetPath( const char *pszFilename )
 
 {
-    int         iFileStart = CPLFindFilenameStart(pszFilename);
+    const int iFileStart = CPLFindFilenameStart(pszFilename);
     char       *pszStaticResult = CPLGetStaticResult();
 
-    if( iFileStart >= CPL_PATH_BUF_SIZE )
+    if( pszStaticResult == NULL || iFileStart >= CPL_PATH_BUF_SIZE )
         return CPLStaticBufferTooSmall(pszStaticResult);
 
-    CPLAssert( ! (pszFilename >= pszStaticResult && pszFilename < pszStaticResult + CPL_PATH_BUF_SIZE) );
+    CPLAssert( ! (pszFilename >= pszStaticResult
+                  && pszFilename < pszStaticResult + CPL_PATH_BUF_SIZE) );
 
     if( iFileStart == 0 )
     {
@@ -143,7 +153,8 @@ const char *CPLGetPath( const char *pszFilename )
         return pszStaticResult;
     }
 
-    CPLStrlcpy( pszStaticResult, pszFilename, iFileStart+1 );
+    CPLStrlcpy( pszStaticResult, pszFilename,
+                static_cast<size_t>( iFileStart ) + 1 );
 
     if( iFileStart > 1
         && (pszStaticResult[iFileStart-1] == '/'
@@ -182,13 +193,14 @@ const char *CPLGetPath( const char *pszFilename )
 const char *CPLGetDirname( const char *pszFilename )
 
 {
-    int         iFileStart = CPLFindFilenameStart(pszFilename);
+    const int iFileStart = CPLFindFilenameStart(pszFilename);
     char       *pszStaticResult = CPLGetStaticResult();
 
-    if( iFileStart >= CPL_PATH_BUF_SIZE )
+    if( pszStaticResult == NULL || iFileStart >= CPL_PATH_BUF_SIZE )
         return CPLStaticBufferTooSmall(pszStaticResult);
 
-    CPLAssert( ! (pszFilename >= pszStaticResult && pszFilename < pszStaticResult + CPL_PATH_BUF_SIZE) );
+    CPLAssert( ! (pszFilename >= pszStaticResult
+                  && pszFilename < pszStaticResult + CPL_PATH_BUF_SIZE) );
 
     if( iFileStart == 0 )
     {
@@ -196,7 +208,8 @@ const char *CPLGetDirname( const char *pszFilename )
         return pszStaticResult;
     }
 
-    CPLStrlcpy( pszStaticResult, pszFilename, iFileStart+1 );
+    CPLStrlcpy( pszStaticResult, pszFilename,
+                static_cast<size_t>( iFileStart ) + 1 );
 
     if( iFileStart > 1
         && (pszStaticResult[iFileStart-1] == '/'
@@ -225,13 +238,14 @@ const char *CPLGetDirname( const char *pszFilename )
  *
  * @param pszFullFilename the full filename potentially including a path.
  *
- *  @return just the non-directory portion of the path (points back into original string).
+ * @return just the non-directory portion of the path (points back into
+ * original string).
  */
 
 const char *CPLGetFilename( const char *pszFullFilename )
 
 {
-    int iFileStart = CPLFindFilenameStart( pszFullFilename );
+    const int iFileStart = CPLFindFilenameStart( pszFullFilename );
 
     return pszFullFilename + iFileStart;
 }
@@ -263,22 +277,26 @@ const char *CPLGetFilename( const char *pszFullFilename )
 const char *CPLGetBasename( const char *pszFullFilename )
 
 {
-    size_t  iFileStart = CPLFindFilenameStart( pszFullFilename );
-    size_t  iExtStart, nLength;
+    const size_t iFileStart
+        = static_cast<size_t>( CPLFindFilenameStart( pszFullFilename ) );
     char    *pszStaticResult = CPLGetStaticResult();
+    if( pszStaticResult == NULL )
+        return CPLStaticBufferTooSmall(pszStaticResult);
 
-    CPLAssert( ! (pszFullFilename >= pszStaticResult && pszFullFilename < pszStaticResult + CPL_PATH_BUF_SIZE) );
+    CPLAssert( ! ( pszFullFilename >= pszStaticResult
+                   && pszFullFilename < pszStaticResult + CPL_PATH_BUF_SIZE ) );
 
-    for( iExtStart = strlen(pszFullFilename);
+    size_t iExtStart = strlen(pszFullFilename);
+    for( ;
          iExtStart > iFileStart && pszFullFilename[iExtStart] != '.';
          iExtStart-- ) {}
 
     if( iExtStart == iFileStart )
         iExtStart = strlen(pszFullFilename);
 
-    nLength = iExtStart - iFileStart;
+    const size_t nLength = iExtStart - iFileStart;
 
-    if (nLength >= CPL_PATH_BUF_SIZE)
+    if( nLength >= static_cast<size_t>( CPL_PATH_BUF_SIZE ) )
         return CPLStaticBufferTooSmall(pszStaticResult);
 
     CPLStrlcpy( pszStaticResult, pszFullFilename + iFileStart, nLength + 1 );
@@ -294,7 +312,7 @@ const char *CPLGetBasename( const char *pszFullFilename )
 /**
  * Extract filename extension from full filename.
  *
- * Returns a string containing the extention portion of the passed
+ * Returns a string containing the extension portion of the passed
  * name.  If there is no extension (the filename has no dot) an empty string
  * is returned.  The returned extension will not include the period.
  *
@@ -313,20 +331,26 @@ const char *CPLGetBasename( const char *pszFullFilename )
 const char *CPLGetExtension( const char *pszFullFilename )
 
 {
-    size_t  iFileStart = CPLFindFilenameStart( pszFullFilename );
-    size_t  iExtStart;
+    size_t iFileStart
+        = static_cast<size_t>( CPLFindFilenameStart( pszFullFilename ) );
     char    *pszStaticResult = CPLGetStaticResult();
+    if( pszStaticResult == NULL )
+        return CPLStaticBufferTooSmall(pszStaticResult);
 
-    CPLAssert( ! (pszFullFilename >= pszStaticResult && pszFullFilename < pszStaticResult + CPL_PATH_BUF_SIZE) );
+    CPLAssert( ! ( pszFullFilename >= pszStaticResult
+                   && pszFullFilename < pszStaticResult + CPL_PATH_BUF_SIZE ) );
 
-    for( iExtStart = strlen(pszFullFilename);
+    size_t  iExtStart = strlen(pszFullFilename);
+    for( ;
          iExtStart > iFileStart && pszFullFilename[iExtStart] != '.';
          iExtStart-- ) {}
 
     if( iExtStart == iFileStart )
         iExtStart = strlen(pszFullFilename)-1;
 
-    if (CPLStrlcpy( pszStaticResult, pszFullFilename+iExtStart+1, CPL_PATH_BUF_SIZE ) >= CPL_PATH_BUF_SIZE)
+    if (CPLStrlcpy( pszStaticResult, pszFullFilename+iExtStart+1,
+                    CPL_PATH_BUF_SIZE )
+        >= static_cast<size_t>( CPL_PATH_BUF_SIZE ) )
         return CPLStaticBufferTooSmall(pszStaticResult);
 
     return pszStaticResult;
@@ -348,18 +372,15 @@ const char *CPLGetExtension( const char *pszFullFilename )
 char *CPLGetCurrentDir()
 
 {
-    size_t  nPathMax;
-    char    *pszDirPath;
-
-# ifdef _MAX_PATH
-    nPathMax = _MAX_PATH;
-# elif PATH_MAX
-    nPathMax = PATH_MAX;
-# else
-    nPathMax = 8192;
-# endif
-
-    pszDirPath = (char*)CPLMalloc( nPathMax );
+#ifdef _MAX_PATH
+    const size_t nPathMax = _MAX_PATH;
+#elif PATH_MAX
+    const size_t nPathMax = PATH_MAX;
+#else
+    const size_t nPathMax = 8192;
+#endif
+
+    char *pszDirPath = static_cast<char *>( VSI_MALLOC_VERBOSE( nPathMax ) );
     if ( !pszDirPath )
         return NULL;
 
@@ -389,19 +410,22 @@ const char *CPLResetExtension( const char *pszPath, const char *pszExt )
 
 {
     char    *pszStaticResult = CPLGetStaticResult();
-    size_t  i;
+    if( pszStaticResult == NULL )
+        return CPLStaticBufferTooSmall(pszStaticResult);
 
-    CPLAssert( ! (pszPath >= pszStaticResult && pszPath < pszStaticResult + CPL_PATH_BUF_SIZE) );
+    CPLAssert( ! ( pszPath >= pszStaticResult
+                   && pszPath < pszStaticResult + CPL_PATH_BUF_SIZE ) );
 
 /* -------------------------------------------------------------------- */
 /*      First, try and strip off any existing extension.                */
 /* -------------------------------------------------------------------- */
-    if (CPLStrlcpy( pszStaticResult, pszPath, CPL_PATH_BUF_SIZE ) >= CPL_PATH_BUF_SIZE)
+    if ( CPLStrlcpy( pszStaticResult, pszPath, CPL_PATH_BUF_SIZE )
+         >= static_cast<size_t>( CPL_PATH_BUF_SIZE ) )
         return CPLStaticBufferTooSmall(pszStaticResult);
 
     if (*pszStaticResult)
     {
-        for( i = strlen(pszStaticResult) - 1; i > 0; i-- )
+        for( size_t i = strlen(pszStaticResult) - 1; i > 0; i-- )
         {
             if( pszStaticResult[i] == '.' )
             {
@@ -409,7 +433,7 @@ const char *CPLResetExtension( const char *pszPath, const char *pszExt )
                 break;
             }
 
-            if( pszStaticResult[i] == '/' || pszStaticResult[i] == '\\' 
+            if( pszStaticResult[i] == '/' || pszStaticResult[i] == '\\'
                 || pszStaticResult[i] == ':' )
                 break;
         }
@@ -418,9 +442,13 @@ const char *CPLResetExtension( const char *pszPath, const char *pszExt )
 /* -------------------------------------------------------------------- */
 /*      Append the new extension.                                       */
 /* -------------------------------------------------------------------- */
-    if (CPLStrlcat( pszStaticResult, ".", CPL_PATH_BUF_SIZE) >= CPL_PATH_BUF_SIZE ||
-        CPLStrlcat( pszStaticResult, pszExt, CPL_PATH_BUF_SIZE) >= CPL_PATH_BUF_SIZE)
+    if( CPLStrlcat( pszStaticResult, ".", CPL_PATH_BUF_SIZE)
+        >= static_cast<size_t>( CPL_PATH_BUF_SIZE ) ||
+        CPLStrlcat( pszStaticResult, pszExt, CPL_PATH_BUF_SIZE)
+        >= static_cast<size_t>( CPL_PATH_BUF_SIZE ) )
+    {
         return CPLStaticBufferTooSmall(pszStaticResult);
+    }
 
     return pszStaticResult;
 }
@@ -447,7 +475,7 @@ const char *CPLResetExtension( const char *pszPath, const char *pszExt )
  * not.  May be NULL.
  *
  * @param pszBasename file basename.  May optionally have path and/or
- * extension.  Must *NOT* be NULL. 
+ * extension.  Must *NOT* be NULL.
  *
  * @param pszExtension file extension, optionally including the period.  May
  * be NULL.
@@ -463,27 +491,62 @@ const char *CPLFormFilename( const char * pszPath,
 
 {
     char *pszStaticResult = CPLGetStaticResult();
-    const char  *pszAddedPathSep = "";
-    const char  *pszAddedExtSep = "";
+    if( pszStaticResult == NULL )
+        return CPLStaticBufferTooSmall(pszStaticResult);
 
-    CPLAssert( ! (pszPath >= pszStaticResult && pszPath < pszStaticResult + CPL_PATH_BUF_SIZE) );
-    CPLAssert( ! (pszBasename >= pszStaticResult && pszBasename < pszStaticResult + CPL_PATH_BUF_SIZE) );
+    CPLAssert( ! ( pszPath >= pszStaticResult
+                   && pszPath < pszStaticResult + CPL_PATH_BUF_SIZE ) );
+    CPLAssert( ! ( pszBasename >= pszStaticResult
+                   && pszBasename < pszStaticResult + CPL_PATH_BUF_SIZE ) );
 
     if( pszBasename[0] == '.' && pszBasename[1] == '/' )
         pszBasename += 2;
 
+    const char  *pszAddedPathSep = "";
+    const char  *pszAddedExtSep = "";
+
     if( pszPath == NULL )
         pszPath = "";
-    else if( strlen(pszPath) > 0
-             && pszPath[strlen(pszPath)-1] != '/'
-             && pszPath[strlen(pszPath)-1] != '\\' )
+    size_t nLenPath = strlen(pszPath);
+    if( !CPLIsFilenameRelative(pszPath) &&
+        strcmp(pszBasename, "..") == 0 )
+    {
+        /* /a/b + .. --> /a */
+        if( pszPath[nLenPath-1] == '\\' || pszPath[nLenPath-1] == '/' )
+            nLenPath --;
+        size_t nLenPathOri = nLenPath;
+        while( nLenPath > 0 && pszPath[nLenPath-1] != '\\' &&
+               pszPath[nLenPath-1] != '/')
+        {
+            nLenPath --;
+        }
+        if( nLenPath == 1 && pszPath[0] == '/' )
+        {
+            pszBasename = "";
+        }
+        else if( (nLenPath > 1 && pszPath[0] == '/') ||
+                 (nLenPath > 2 && pszPath[1] == ':') ||
+                 (nLenPath > 6 && strncmp(pszPath, "\\\\$\\", 4) == 0) )
+        {
+            nLenPath --;
+            pszBasename = "";
+        }
+        else
+        {
+            nLenPath = nLenPathOri;
+            pszAddedPathSep = SEP_STRING;
+        }
+    }
+    else if( nLenPath > 0
+             && pszPath[nLenPath-1] != '/'
+             && pszPath[nLenPath-1] != '\\' )
     {
         /* FIXME? would be better to ask the filesystems what they */
         /* prefer as directory separator */
-        if (strncmp(pszPath, "/vsicurl/", 9) == 0 ||
-            strncmp(pszPath, "/vsicurl_streaming/", strlen("/vsicurl_streaming/")) == 0)
+        if (STARTS_WITH(pszPath, "/vsicurl/") ||
+            STARTS_WITH(pszPath, "/vsicurl_streaming/"))
             pszAddedPathSep = "/";
-        else if (strncmp(pszPath, "/vsizip/", 8) == 0)
+        else if (STARTS_WITH(pszPath, "/vsizip/"))
             pszAddedPathSep = "/";
         else
             pszAddedPathSep = SEP_STRING;
@@ -494,12 +557,19 @@ const char *CPLFormFilename( const char * pszPath,
     else if( pszExtension[0] != '.' && strlen(pszExtension) > 0 )
         pszAddedExtSep = ".";
 
-    if (CPLStrlcpy( pszStaticResult, pszPath, CPL_PATH_BUF_SIZE) >= CPL_PATH_BUF_SIZE ||
-        CPLStrlcat( pszStaticResult, pszAddedPathSep, CPL_PATH_BUF_SIZE) >= CPL_PATH_BUF_SIZE ||
-        CPLStrlcat( pszStaticResult, pszBasename, CPL_PATH_BUF_SIZE) >= CPL_PATH_BUF_SIZE ||
-        CPLStrlcat( pszStaticResult, pszAddedExtSep, CPL_PATH_BUF_SIZE) >= CPL_PATH_BUF_SIZE ||
-        CPLStrlcat( pszStaticResult, pszExtension, CPL_PATH_BUF_SIZE) >= CPL_PATH_BUF_SIZE)
+    if( CPLStrlcpy( pszStaticResult, pszPath, MIN(nLenPath+1, static_cast<size_t>(CPL_PATH_BUF_SIZE)) )
+        >= static_cast<size_t>( CPL_PATH_BUF_SIZE ) ||
+        CPLStrlcat( pszStaticResult, pszAddedPathSep, CPL_PATH_BUF_SIZE)
+        >= static_cast<size_t>( CPL_PATH_BUF_SIZE ) ||
+        CPLStrlcat( pszStaticResult, pszBasename, CPL_PATH_BUF_SIZE)
+        >= static_cast<size_t>( CPL_PATH_BUF_SIZE ) ||
+        CPLStrlcat( pszStaticResult, pszAddedExtSep, CPL_PATH_BUF_SIZE)
+        >= static_cast<size_t>( CPL_PATH_BUF_SIZE ) ||
+        CPLStrlcat( pszStaticResult, pszExtension, CPL_PATH_BUF_SIZE)
+        >= static_cast<size_t>( CPL_PATH_BUF_SIZE ) )
+    {
         return CPLStaticBufferTooSmall(pszStaticResult);
+    }
 
     return pszStaticResult;
 }
@@ -509,12 +579,12 @@ const char *CPLFormFilename( const char * pszPath,
 /************************************************************************/
 
 /**
- * Case insensitive file searching, returing full path.
+ * Case insensitive file searching, returning full path.
  *
  * This function tries to return the path to a file regardless of
  * whether the file exactly matches the basename, and extension case, or
- * is all upper case, or all lower case.  The path is treated as case 
- * sensitive.  This function is equivelent to CPLFormFilename() on 
+ * is all upper case, or all lower case.  The path is treated as case
+ * sensitive.  This function is equivalent to CPLFormFilename() on
  * case insensitive file systems (like Windows).
  *
  * @param pszPath directory path to the directory containing the file.  This
@@ -522,7 +592,7 @@ const char *CPLFormFilename( const char * pszPath,
  * not.  May be NULL.
  *
  * @param pszBasename file basename.  May optionally have path and/or
- * extension.  May not be NULL. 
+ * extension.  May not be NULL.
  *
  * @param pszExtension file extension, optionally including the period.  May
  * be NULL.
@@ -543,33 +613,32 @@ const char *CPLFormCIFilename( const char * pszPath,
         return CPLFormFilename( pszPath, pszBasename, pszExtension );
 
     const char  *pszAddedExtSep = "";
-    char        *pszFilename;
-    const char  *pszFullPath;
-    int         nLen = strlen(pszBasename)+2, i;
-    VSIStatBufL sStatBuf;
-    int         nStatRet;
+    size_t       nLen = strlen(pszBasename)+2;
 
     if( pszExtension != NULL )
         nLen += strlen(pszExtension);
 
-    pszFilename = (char *) CPLMalloc(nLen);
+    char *pszFilename = static_cast<char *>( VSI_MALLOC_VERBOSE(nLen) );
+    if( pszFilename == NULL )
+        return "";
 
     if( pszExtension == NULL )
         pszExtension = "";
     else if( pszExtension[0] != '.' && strlen(pszExtension) > 0 )
         pszAddedExtSep = ".";
 
-    sprintf( pszFilename, "%s%s%s", 
+    snprintf( pszFilename, nLen, "%s%s%s",
              pszBasename, pszAddedExtSep, pszExtension );
 
-    pszFullPath = CPLFormFilename( pszPath, pszFilename, NULL );
-    nStatRet = VSIStatExL( pszFullPath, &sStatBuf, VSI_STAT_EXISTS_FLAG );
+    const char *pszFullPath = CPLFormFilename( pszPath, pszFilename, NULL );
+    VSIStatBufL sStatBuf;
+    int nStatRet = VSIStatExL( pszFullPath, &sStatBuf, VSI_STAT_EXISTS_FLAG );
     if( nStatRet != 0 )
     {
-        for( i = 0; pszFilename[i] != '\0'; i++ )
+        for( size_t i = 0; pszFilename[i] != '\0'; i++ )
         {
             if( islower(pszFilename[i]) )
-                pszFilename[i] = (char) toupper(pszFilename[i]);
+                pszFilename[i] = static_cast<char>( toupper(pszFilename[i]) );
         }
 
         pszFullPath = CPLFormFilename( pszPath, pszFilename, NULL );
@@ -578,10 +647,10 @@ const char *CPLFormCIFilename( const char * pszPath,
 
     if( nStatRet != 0 )
     {
-        for( i = 0; pszFilename[i] != '\0'; i++ )
+        for( size_t i = 0; pszFilename[i] != '\0'; i++ )
         {
             if( isupper(pszFilename[i]) )
-                pszFilename[i] = (char) tolower(pszFilename[i]);
+                pszFilename[i] = static_cast<char>( tolower(pszFilename[i]) );
         }
 
         pszFullPath = CPLFormFilename( pszPath, pszFilename, NULL );
@@ -601,13 +670,13 @@ const char *CPLFormCIFilename( const char * pszPath,
 /************************************************************************/
 
 /**
- * Find a file relative to a project file. 
+ * Find a file relative to a project file.
  *
  * Given the path to a "project" directory, and a path to a secondary file
  * referenced from that project, build a path to the secondary file
  * that the current application can use.  If the secondary path is already
- * absolute, rather than relative, then it will be returned unaltered. 
- * 
+ * absolute, rather than relative, then it will be returned unaltered.
+ *
  * Examples:
  * <pre>
  * CPLProjectRelativeFilename("abc/def","tmp/abc.gif") == "abc/def/tmp/abc.gif"
@@ -617,24 +686,29 @@ const char *CPLFormCIFilename( const char * pszPath,
  * CPLProjectRelativeFilename("C:\WIN","abc.gif") == "C:\WIN\abc.gif"
  * </pre>
  *
- * @param pszProjectDir the directory relative to which the secondary files 
+ * @param pszProjectDir the directory relative to which the secondary files
  * path should be interpreted.
  * @param pszSecondaryFilename the filename (potentially with path) that
  * is to be interpreted relative to the project directory.
  *
  * @return a composed path to the secondary file.  The returned string is
  * internal and should not be altered, freed, or depending on past the next
- * CPL call. 
+ * CPL call.
  */
 
-const char *CPLProjectRelativeFilename( const char *pszProjectDir, 
+const char *CPLProjectRelativeFilename( const char *pszProjectDir,
                                         const char *pszSecondaryFilename )
 
 {
     char *pszStaticResult = CPLGetStaticResult();
+    if( pszStaticResult == NULL )
+        return CPLStaticBufferTooSmall(pszStaticResult);
 
-    CPLAssert( ! (pszProjectDir >= pszStaticResult && pszProjectDir < pszStaticResult + CPL_PATH_BUF_SIZE) );
-    CPLAssert( ! (pszSecondaryFilename >= pszStaticResult && pszSecondaryFilename < pszStaticResult + CPL_PATH_BUF_SIZE) );
+    CPLAssert( ! ( pszProjectDir >= pszStaticResult
+                   && pszProjectDir < pszStaticResult + CPL_PATH_BUF_SIZE ) );
+    CPLAssert( ! ( pszSecondaryFilename >= pszStaticResult
+                   && pszSecondaryFilename
+                   < pszStaticResult + CPL_PATH_BUF_SIZE) );
 
     if( !CPLIsFilenameRelative( pszSecondaryFilename ) )
         return pszSecondaryFilename;
@@ -642,29 +716,30 @@ const char *CPLProjectRelativeFilename( const char *pszProjectDir,
     if( pszProjectDir == NULL || strlen(pszProjectDir) == 0 )
         return pszSecondaryFilename;
 
-    if (CPLStrlcpy( pszStaticResult, pszProjectDir, CPL_PATH_BUF_SIZE ) >= CPL_PATH_BUF_SIZE)
-        goto error;
+    if( CPLStrlcpy( pszStaticResult, pszProjectDir, CPL_PATH_BUF_SIZE )
+        >= static_cast<size_t>( CPL_PATH_BUF_SIZE ) )
+        return CPLStaticBufferTooSmall(pszStaticResult);
 
-    if( pszProjectDir[strlen(pszProjectDir)-1] != '/' 
+    if( pszProjectDir[strlen(pszProjectDir)-1] != '/'
         && pszProjectDir[strlen(pszProjectDir)-1] != '\\' )
     {
         /* FIXME? would be better to ask the filesystems what they */
         /* prefer as directory separator */
         const char* pszAddedPathSep;
-        if (strncmp(pszStaticResult, "/vsicurl/", 9) == 0)
+        if (STARTS_WITH(pszStaticResult, "/vsicurl/"))
             pszAddedPathSep = "/";
         else
             pszAddedPathSep = SEP_STRING;
-        if (CPLStrlcat( pszStaticResult, pszAddedPathSep, CPL_PATH_BUF_SIZE ) >= CPL_PATH_BUF_SIZE)
-            goto error;
+        if( CPLStrlcat( pszStaticResult, pszAddedPathSep, CPL_PATH_BUF_SIZE )
+            >= static_cast<size_t>( CPL_PATH_BUF_SIZE ) )
+            return CPLStaticBufferTooSmall(pszStaticResult);
     }
 
-    if (CPLStrlcat( pszStaticResult, pszSecondaryFilename, CPL_PATH_BUF_SIZE ) >= CPL_PATH_BUF_SIZE)
-        goto error;
+    if( CPLStrlcat( pszStaticResult, pszSecondaryFilename, CPL_PATH_BUF_SIZE )
+        >= static_cast<size_t>( CPL_PATH_BUF_SIZE ) )
+        return CPLStaticBufferTooSmall(pszStaticResult);
 
     return pszStaticResult;
-error:
-    return CPLStaticBufferTooSmall(pszStaticResult);
 }
 
 
@@ -677,24 +752,25 @@ error:
  *
  * The test is filesystem convention agnostic.  That is it will test for
  * Unix style and windows style path conventions regardless of the actual
- * system in use.  
+ * system in use.
  *
  * @param pszFilename the filename with path to test.
  *
- * @return TRUE if the filename is relative or FALSE if it is absolute. 
+ * @return TRUE if the filename is relative or FALSE if it is absolute.
  */
 
 int CPLIsFilenameRelative( const char *pszFilename )
 
 {
-    if( (strlen(pszFilename) > 2
-         && (strncmp(pszFilename+1,":\\",2) == 0
-             || strncmp(pszFilename+1,":/",2) == 0))
+    if( (pszFilename[0] != '\0'
+         && (STARTS_WITH(pszFilename+1, ":\\")
+             || STARTS_WITH(pszFilename+1, ":/")))
+        || STARTS_WITH(pszFilename, "\\\\?\\") /* Windows extended Length Path */
         || pszFilename[0] == '\\'
         || pszFilename[0] == '/' )
         return FALSE;
-    else
-        return TRUE;
+
+    return TRUE;
 }
 
 /************************************************************************/
@@ -704,33 +780,31 @@ int CPLIsFilenameRelative( const char *pszFilename )
 /**
  * Get relative path from directory to target file.
  *
- * Computes a relative path for pszTarget relative to pszBaseDir. 
+ * Computes a relative path for pszTarget relative to pszBaseDir.
  * Currently this only works if they share a common base path.  The returned
  * path is normally into the pszTarget string.  It should only be considered
- * valid as long as pszTarget is valid or till the next call to 
- * this function, whichever comes first. 
+ * valid as long as pszTarget is valid or till the next call to
+ * this function, whichever comes first.
  *
- * @param pszBaseDir the name of the directory relative to which the path 
+ * @param pszBaseDir the name of the directory relative to which the path
  * should be computed.  pszBaseDir may be NULL in which case the original
- * target is returned without relitivizing.
- * 
+ * target is returned without relativizing.
+ *
  * @param pszTarget the filename to be changed to be relative to pszBaseDir.
  *
- * @param pbGotRelative Pointer to location in which a flag is placed 
+ * @param pbGotRelative Pointer to location in which a flag is placed
  * indicating that the returned path is relative to the basename (TRUE) or
  * not (FALSE).  This pointer may be NULL if flag is not desired.
  *
  * @return an adjusted path or the original if it could not be made relative
- * to the pszBaseFile's path. 
+ * to the pszBaseFile's path.
  **/
 
-const char *CPLExtractRelativePath( const char *pszBaseDir, 
+const char *CPLExtractRelativePath( const char *pszBaseDir,
                                     const char *pszTarget,
                                     int *pbGotRelative )
 
 {
-    size_t nBasePathLen;
-
 /* -------------------------------------------------------------------- */
 /*      If we don't have a basedir, then we can't relativize the path.  */
 /* -------------------------------------------------------------------- */
@@ -742,7 +816,7 @@ const char *CPLExtractRelativePath( const char *pszBaseDir,
         return pszTarget;
     }
 
-    nBasePathLen = strlen(pszBaseDir);
+    const size_t nBasePathLen = strlen(pszBaseDir);
 
 /* -------------------------------------------------------------------- */
 /*      One simple case is when the base dir is '.' and the target      */
@@ -773,8 +847,8 @@ const char *CPLExtractRelativePath( const char *pszBaseDir,
 /*      If we don't have a common path prefix, then we can't get a      */
 /*      relative path.                                                  */
 /* -------------------------------------------------------------------- */
-    if( !EQUALN(pszBaseDir,pszTarget,nBasePathLen) 
-        || (pszTarget[nBasePathLen] != '\\' 
+    if( !EQUALN(pszBaseDir,pszTarget,nBasePathLen)
+        || (pszTarget[nBasePathLen] != '\\'
             && pszTarget[nBasePathLen] != '/') )
     {
         if( pbGotRelative != NULL )
@@ -798,10 +872,10 @@ const char *CPLExtractRelativePath( const char *pszBaseDir,
 /************************************************************************/
 
 /**
- * Remove trailing forward/backward slash from the path for unix/windows resp.
+ * Remove trailing forward/backward slash from the path for UNIX/Windows resp.
  *
- * Returns a string containing the portion of the passed path string with 
- * trailing slash removed. If there is no path in the passed filename 
+ * Returns a string containing the portion of the passed path string with
+ * trailing slash removed. If there is no path in the passed filename
  * an empty string will be returned (not NULL).
  *
  * <pre>
@@ -814,7 +888,7 @@ const char *CPLExtractRelativePath( const char *pszBaseDir,
  *
  * @param pszPath the path to be cleaned up
  *
- *  @return Path in an internal string which must not be freed.  The string
+ * @return Path in an internal string which must not be freed.  The string
  * may be destroyed by the next CPL filename handling call.
  */
 
@@ -822,17 +896,19 @@ const char *CPLCleanTrailingSlash( const char *pszPath )
 
 {
     char       *pszStaticResult = CPLGetStaticResult();
-    int        iPathLength = strlen(pszPath);
-
-    CPLAssert( ! (pszPath >= pszStaticResult && pszPath < pszStaticResult + CPL_PATH_BUF_SIZE) );
+    if( pszStaticResult == NULL )
+        return CPLStaticBufferTooSmall(pszStaticResult);
+    CPLAssert( ! ( pszPath >= pszStaticResult
+                   && pszPath < pszStaticResult + CPL_PATH_BUF_SIZE) );
 
-    if (iPathLength >= CPL_PATH_BUF_SIZE)
+    const size_t iPathLength = strlen(pszPath);
+    if (iPathLength >= static_cast<size_t>( CPL_PATH_BUF_SIZE ) )
         return CPLStaticBufferTooSmall(pszStaticResult);
 
     CPLStrlcpy( pszStaticResult, pszPath, iPathLength+1 );
 
-    if( iPathLength > 0 
-        && (pszStaticResult[iPathLength-1] == '\\' 
+    if( iPathLength > 0
+        && (pszStaticResult[iPathLength-1] == '\\'
             || pszStaticResult[iPathLength-1] == '/'))
         pszStaticResult[iPathLength-1] = '\0';
 
@@ -848,36 +924,30 @@ const char *CPLCleanTrailingSlash( const char *pszPath )
  *
  * Given a prototype old and new filename this function will attempt
  * to determine corresponding names for a set of other old filenames that
- * will rename them in a similar manner.  This correspondance assumes there
- * are two possibly kinds of renaming going on.  A change of path, and a 
- * change of filename stem. 
- * 
+ * will rename them in a similar manner.  This correspondence assumes there
+ * are two possibly kinds of renaming going on.  A change of path, and a
+ * change of filename stem.
+ *
  * If a consistent renaming cannot be established for all the files this
- * function will return indicating an error.  
+ * function will return indicating an error.
  *
  * The returned file list becomes owned by the caller and should be destroyed
- * with CSLDestroy(). 
+ * with CSLDestroy().
  *
- * @param pszOldFilename path to old prototype file. 
- * @param pszNewFilename path to new prototype file. 
- * @param papszFileList list of other files associated with pszOldFilename to 
+ * @param pszOldFilename path to old prototype file.
+ * @param pszNewFilename path to new prototype file.
+ * @param papszFileList list of other files associated with pszOldFilename to
  * rename similarly.
- * 
- * @return a list of files corresponding to papszFileList but renamed to 
+ *
+ * @return a list of files corresponding to papszFileList but renamed to
  * correspond to pszNewFilename.
  */
 
-char **CPLCorrespondingPaths( const char *pszOldFilename, 
-                              const char *pszNewFilename, 
+char **CPLCorrespondingPaths( const char *pszOldFilename,
+                              const char *pszNewFilename,
                               char **papszFileList )
 
 {
-    CPLString osOldPath = CPLGetPath( pszOldFilename );
-    CPLString osNewPath = CPLGetPath( pszNewFilename );
-    CPLString osOldBasename = CPLGetBasename( pszOldFilename );
-    CPLString osNewBasename = CPLGetBasename( pszNewFilename );
-    int i;
-
     if( CSLCount(papszFileList) == 0 )
         return NULL;
 
@@ -885,33 +955,35 @@ char **CPLCorrespondingPaths( const char *pszOldFilename,
 /*      There is a special case for a one item list which exactly       */
 /*      matches the old name, to rename to the new name.                */
 /* -------------------------------------------------------------------- */
-    if( CSLCount(papszFileList) == 1 
+    if( CSLCount(papszFileList) == 1
         && strcmp(pszOldFilename,papszFileList[0]) == 0 )
     {
         return CSLAddString( NULL, pszNewFilename );
     }
 
+    const CPLString osOldPath = CPLGetPath( pszOldFilename );
+    const CPLString osOldBasename = CPLGetBasename( pszOldFilename );
+    const CPLString osNewBasename = CPLGetBasename( pszNewFilename );
+
 /* -------------------------------------------------------------------- */
 /*      If the basename is changing, verify that all source files       */
 /*      have the same starting basename.                                */
 /* -------------------------------------------------------------------- */
     if( osOldBasename != osNewBasename )
     {
-        for( i=0; papszFileList[i] != NULL; i++ )
+        for( int i=0; papszFileList[i] != NULL; i++ )
         {
             if( osOldBasename == CPLGetBasename( papszFileList[i] ) )
                 continue;
 
-            CPLString osFilePath, osFileName;
-
-            osFilePath = CPLGetPath( papszFileList[i] );
-            osFileName = CPLGetFilename( papszFileList[i] );
+            const CPLString osFilePath = CPLGetPath( papszFileList[i] );
+            const CPLString osFileName = CPLGetFilename( papszFileList[i] );
 
             if( !EQUALN(osFileName,osOldBasename,osOldBasename.size())
                 || !EQUAL(osFilePath,osOldPath)
                 || osFileName[osOldBasename.size()] != '.' )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
+                CPLError( CE_Failure, CPLE_AppDefined,
                           "Unable to rename fileset due irregular basenames.");
                 return NULL;
             }
@@ -924,15 +996,16 @@ char **CPLCorrespondingPaths( const char *pszOldFilename,
 /* -------------------------------------------------------------------- */
     if( osOldBasename != osNewBasename )
     {
-        CPLString osOldExtra = CPLGetFilename(pszOldFilename) 
+        const CPLString osOldExtra = CPLGetFilename(pszOldFilename)
             + strlen(osOldBasename);
-        CPLString osNewExtra = CPLGetFilename(pszNewFilename) 
+        const CPLString osNewExtra = CPLGetFilename(pszNewFilename)
             + strlen(osNewBasename);
 
         if( osOldExtra != osNewExtra )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Unable to rename fileset due to irregular filename correspondence." );
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Unable to rename fileset due to irregular filename "
+                      "correspondence." );
             return NULL;
         }
     }
@@ -941,18 +1014,19 @@ char **CPLCorrespondingPaths( const char *pszOldFilename,
 /*      Generate the new filenames.                                     */
 /* -------------------------------------------------------------------- */
     char **papszNewList = NULL;
+    const CPLString osNewPath = CPLGetPath( pszNewFilename );
 
-    for( i=0; papszFileList[i] != NULL; i++ )
+    for( int i=0; papszFileList[i] != NULL; i++ )
     {
         CPLString osNewFilename;
-        CPLString osOldFilename = CPLGetFilename( papszFileList[i] );
+        const CPLString osOldFilename = CPLGetFilename( papszFileList[i] );
 
         if( osOldBasename == osNewBasename )
-            osNewFilename = 
+            osNewFilename =
                 CPLFormFilename( osNewPath, osOldFilename, NULL );
         else
-            osNewFilename = 
-                CPLFormFilename( osNewPath, osNewBasename, 
+            osNewFilename =
+                CPLFormFilename( osNewPath, osNewBasename,
                                  osOldFilename.c_str()+strlen(osOldBasename));
 
         papszNewList = CSLAddString( papszNewList, osNewFilename );
@@ -967,13 +1041,13 @@ char **CPLCorrespondingPaths( const char *pszOldFilename,
 
 /**
  * Generate temporary file name.
- * 
+ *
  * Returns a filename that may be used for a temporary file.  The location
  * of the file tries to follow operating system semantics but may be
- * forced via the CPL_TMPDIR configuration option.  
+ * forced via the CPL_TMPDIR configuration option.
  *
  * @param pszStem if non-NULL this will be part of the filename.
- * 
+ *
  * @return a filename which is valid till the next CPL call in this thread.
  */
 
@@ -981,7 +1055,6 @@ const char *CPLGenerateTempFilename( const char *pszStem )
 
 {
     const char *pszDir = CPLGetConfigOption( "CPL_TMPDIR", NULL );
-    static volatile int nTempFileCounter = 0;
 
     if( pszDir == NULL )
         pszDir = CPLGetConfigOption( "TMPDIR", NULL );
@@ -992,13 +1065,15 @@ const char *CPLGenerateTempFilename( const char *pszStem )
     if( pszDir == NULL )
         pszDir = ".";
 
-    CPLString osFilename;
-
     if( pszStem == NULL )
         pszStem = "";
 
-    osFilename.Printf( "%s%u_%d", pszStem, 
-                       (int) CPLGetPID(), nTempFileCounter++ );
+    static int nTempFileCounter = 0;
+    CPLString osFilename;
+    osFilename.Printf( "%s_%d_%d",
+                       pszStem,
+                       CPLGetCurrentProcessID(),
+                       CPLAtomicInc( &nTempFileCounter ) );
 
     return CPLFormFilename( pszDir, osFilename, NULL );
 }
diff --git a/port/cpl_port.h b/port/cpl_port.h
index 69b65dd..4ac75b5 100644
--- a/port/cpl_port.h
+++ b/port/cpl_port.h
@@ -1,10 +1,10 @@
 /******************************************************************************
- * $Id: cpl_port.h 29925 2015-08-30 12:05:05Z rouault $
+ * $Id: cpl_port.h 33609 2016-03-01 22:54:50Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Author:   Frank Warmerdam, warmerdam at pobox.com
- * Purpose:  Include file providing low level portability services for CPL.  
- *           This should be the first include file for any CPL based code.  
+ * Purpose:  Include file providing low level portability services for CPL.
+ *           This should be the first include file for any CPL based code.
  *
  ******************************************************************************
  * Copyright (c) 1998, 2005, Frank Warmerdam <warmerdam at pobox.com>
@@ -40,31 +40,16 @@
  */
 
 /* ==================================================================== */
-/*      We will use macos_pre10 to indicate compilation with MacOS      */
-/*      versions before MacOS X.                                        */
-/* ==================================================================== */
-#ifdef macintosh
-#  define macos_pre10
-#endif
-
-/* ==================================================================== */
 /*      We will use WIN32 as a standard windows define.                 */
 /* ==================================================================== */
-#if defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE)
+#if defined(_WIN32) && !defined(WIN32)
 #  define WIN32
 #endif
 
-#if defined(_WINDOWS) && !defined(WIN32) && !defined(_WIN32_WCE)
+#if defined(_WINDOWS) && !defined(WIN32)
 #  define WIN32
 #endif
 
-/* ==================================================================== */
-/*      We will use WIN32CE as a standard Windows CE (Mobile) define.   */
-/* ==================================================================== */
-#if defined(_WIN32_WCE)
-#  define WIN32CE
-#endif
-
 /* -------------------------------------------------------------------- */
 /*      The following apparently allow you to use strcpy() and other    */
 /*      functions judged "unsafe" by microsoft in VS 8 (2005).          */
@@ -105,7 +90,6 @@
 
 #ifdef unix
 #  undef WIN32
-#  undef WIN32CE
 #endif
 
 #if defined(VSI_NEED_LARGEFILE64_SOURCE) && !defined(_LARGEFILE64_SOURCE)
@@ -149,17 +133,11 @@
 #include <ctype.h>
 #include <limits.h>
 
-#if !defined(WIN32CE)
-#  include <time.h>
-#else
-#  include <wce_time.h>
-#  include <wce_errno.h>
-#endif
-
+#include <time.h>
 
 #if defined(HAVE_ERRNO_H)
 #  include <errno.h>
-#endif 
+#endif
 
 #ifdef HAVE_LOCALE_H
 #  include <locale.h>
@@ -169,7 +147,7 @@
 #  include <direct.h>
 #endif
 
-#if !(defined(WIN32) || defined(WIN32CE))
+#if !defined(WIN32)
 #  include <strings.h>
 #endif
 
@@ -221,6 +199,7 @@ typedef unsigned __int64 GUIntBig;
 
 #define GINTBIG_MIN     ((GIntBig)(0x80000000) << 32)
 #define GINTBIG_MAX     (((GIntBig)(0x7FFFFFFF) << 32) | 0xFFFFFFFFU)
+#define GUINTBIG_MAX     (((GUIntBig)(0xFFFFFFFFU) << 32) | 0xFFFFFFFFU)
 
 #elif HAVE_LONG_LONG
 
@@ -229,6 +208,7 @@ typedef unsigned long long GUIntBig;
 
 #define GINTBIG_MIN     ((GIntBig)(0x80000000) << 32)
 #define GINTBIG_MAX     (((GIntBig)(0x7FFFFFFF) << 32) | 0xFFFFFFFFU)
+#define GUINTBIG_MAX     (((GUIntBig)(0xFFFFFFFFU) << 32) | 0xFFFFFFFFU)
 
 #else
 
@@ -237,6 +217,7 @@ typedef unsigned long    GUIntBig;
 
 #define GINTBIG_MIN     INT_MIN
 #define GINTBIG_MAX     INT_MAX
+#define GUINTBIG_MAX     UINT_MAX
 #endif
 
 #if SIZEOF_VOIDP == 8
@@ -263,6 +244,12 @@ typedef int              GPtrDiff_t;
 #define GUINTBIG_TO_DOUBLE(x) (double)(x)
 #endif
 
+#ifdef COMPAT_WITH_ICC_CONVERSION_CHECK
+#define CPL_INT64_FITS_ON_INT32(x) ((x) >= INT_MIN && (x) <= INT_MAX)
+#else
+#define CPL_INT64_FITS_ON_INT32(x) (((GIntBig)(int)(x)) == (x))
+#endif
+
 /* ==================================================================== */
 /*      Other standard services.                                        */
 /* ==================================================================== */
@@ -304,7 +291,7 @@ typedef int              GPtrDiff_t;
 #ifdef _MSC_VER
 #  define FORCE_CDECL  __cdecl
 #else
-#  define FORCE_CDECL 
+#  define FORCE_CDECL
 #endif
 
 /* TODO : support for other compilers needed */
@@ -318,17 +305,50 @@ typedef int              GPtrDiff_t;
 #define CPL_INLINE
 #endif
 
+// Define NULL_AS_NULLPTR together with -std=c++11 -Wzero-as-null-pointer-constant with GCC
+// to detect misuses of NULL
+#if defined(NULL_AS_NULLPTR) && defined(__cplusplus) && __cplusplus >= 201103L
+
+#ifdef __GNUC__
+// We need to include all that bunch of system headers, otherwise
+// as they include <stddef.h> with __need_NULL, this overrides our #define NULL nullptr
+// with #define NULL __null
+#include <locale.h>
+#include <unistd.h>
+#include <sys/types.h>
+#ifdef HAVE_ICONV
+#include <iconv.h>
+#endif
+#ifdef HAVE_MMAP
+#include <sys/mman.h>
+#endif
+#include <signal.h>
+#ifndef _WIN32
+#include <dlfcn.h>
+#include <netdb.h>
+#include <fcntl.h>
+#endif
+
+extern "C++" {
+#include <string>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <cstddef>
+#include <ostream>
+#include <iostream>
+#include <sstream>
+}
+#endif /* __GNUC__ */
+
+#undef NULL
+#define NULL nullptr
+#else /* defined(NULL_AS_NULLPTR) && defined(__cplusplus) && __cplusplus >= 201103L */
 #ifndef NULL
 #  define NULL  0
 #endif
+#endif /* defined(NULL_AS_NULLPTR) && defined(__cplusplus) && __cplusplus >= 201103L */
 
-#ifndef FALSE
-#  define FALSE 0
-#endif
-
-#ifndef TRUE
-#  define TRUE  1
-#endif
 
 #ifndef MAX
 #  define MIN(a,b)      ((a<b) ? a : b)
@@ -340,7 +360,8 @@ typedef int              GPtrDiff_t;
 #endif
 
 #ifndef M_PI
-# define M_PI		3.14159265358979323846	/* pi */
+# define M_PI		3.14159265358979323846
+/* 3.1415926535897932384626433832795 */
 #endif
 
 /* -------------------------------------------------------------------- */
@@ -356,7 +377,128 @@ typedef int              GPtrDiff_t;
 /*      Provide macros for case insensitive string comparisons.         */
 /* -------------------------------------------------------------------- */
 #ifndef EQUAL
-#  if defined(WIN32) || defined(WIN32CE)
+
+#if defined(AFL_FRIENDLY) && defined(__GNUC__)
+
+static inline int CPL_afl_friendly_memcmp(const void* ptr1, const void* ptr2, size_t len)
+        __attribute__((always_inline));
+
+static inline int CPL_afl_friendly_memcmp(const void* ptr1, const void* ptr2, size_t len)
+{
+    const unsigned char* bptr1 = (const unsigned char*)ptr1;
+    const unsigned char* bptr2 = (const unsigned char*)ptr2;
+    while( len-- )
+    {
+        unsigned char b1 = *(bptr1++);
+        unsigned char b2 = *(bptr2++);
+        if( b1 != b2 ) return b1 - b2;
+    }
+    return 0;
+}
+
+static inline int CPL_afl_friendly_strcmp(const char* ptr1, const char* ptr2)
+        __attribute__((always_inline));
+
+static inline int CPL_afl_friendly_strcmp(const char* ptr1, const char* ptr2)
+{
+    const unsigned char* usptr1 = (const unsigned char*)ptr1;
+    const unsigned char* usptr2 = (const unsigned char*)ptr2;
+    while( 1 )
+    {
+        unsigned char ch1 = *(usptr1++);
+        unsigned char ch2 = *(usptr2++);
+        if( ch1 == 0 || ch1 != ch2 ) return ch1 - ch2;
+    }
+}
+
+static inline int CPL_afl_friendly_strncmp(const char* ptr1, const char* ptr2, size_t len)
+        __attribute__((always_inline));
+
+static inline int CPL_afl_friendly_strncmp(const char* ptr1, const char* ptr2, size_t len)
+{
+    const unsigned char* usptr1 = (const unsigned char*)ptr1;
+    const unsigned char* usptr2 = (const unsigned char*)ptr2;
+    while( len -- )
+    {
+        unsigned char ch1 = *(usptr1++);
+        unsigned char ch2 = *(usptr2++);
+        if( ch1 == 0 || ch1 != ch2 ) return ch1 - ch2;
+    }
+    return 0;
+}
+
+static inline int CPL_afl_friendly_strcasecmp(const char* ptr1, const char* ptr2)
+        __attribute__((always_inline));
+
+static inline int CPL_afl_friendly_strcasecmp(const char* ptr1, const char* ptr2)
+{
+    const unsigned char* usptr1 = (const unsigned char*)ptr1;
+    const unsigned char* usptr2 = (const unsigned char*)ptr2;
+    while( 1 )
+    {
+        unsigned char ch1 = *(usptr1++);
+        unsigned char ch2 = *(usptr2++);
+        ch1 = (unsigned char)toupper(ch1);
+        ch2 = (unsigned char)toupper(ch2);
+        if( ch1 == 0 || ch1 != ch2 ) return ch1 - ch2;
+    }
+}
+
+static inline int CPL_afl_friendly_strncasecmp(const char* ptr1, const char* ptr2, size_t len)
+        __attribute__((always_inline));
+
+static inline int CPL_afl_friendly_strncasecmp(const char* ptr1, const char* ptr2, size_t len)
+{
+    const unsigned char* usptr1 = (const unsigned char*)ptr1;
+    const unsigned char* usptr2 = (const unsigned char*)ptr2;
+    while( len-- )
+    {
+        unsigned char ch1 = *(usptr1++);
+        unsigned char ch2 = *(usptr2++);
+        ch1 = (unsigned char)toupper(ch1);
+        ch2 = (unsigned char)toupper(ch2);
+        if( ch1 == 0 || ch1 != ch2 ) return ch1 - ch2;
+    }
+    return 0;
+}
+
+static inline char* CPL_afl_friendly_strstr(const char* haystack, const char* needle)
+        __attribute__((always_inline));
+
+static inline char* CPL_afl_friendly_strstr(const char* haystack, const char* needle)
+{
+    const char* ptr_haystack = haystack;
+    while( 1 )
+    {
+        const char* ptr_haystack2 = ptr_haystack;
+        const char* ptr_needle = needle;
+        while( 1 )
+        {
+            char ch1 = *(ptr_haystack2++);
+            char ch2 = *(ptr_needle++);
+            if( ch2 == 0 )
+                return (char*)ptr_haystack;
+            if( ch1 != ch2 )
+                break;
+        }
+        if( *ptr_haystack == 0 )
+            return NULL;
+        ptr_haystack ++;
+    }
+}
+
+#undef strcmp
+#undef strncmp
+#define memcmp CPL_afl_friendly_memcmp
+#define strcmp CPL_afl_friendly_strcmp
+#define strncmp CPL_afl_friendly_strncmp
+#define strcasecmp CPL_afl_friendly_strcasecmp
+#define strncasecmp CPL_afl_friendly_strncasecmp
+#define strstr CPL_afl_friendly_strstr
+
+#endif /* defined(AFL_FRIENDLY) && defined(__GNUC__) */
+
+#  if defined(WIN32)
 #    define STRCASECMP(a,b)         (stricmp(a,b))
 #    define STRNCASECMP(a,b,n)      (strnicmp(a,b,n))
 #  else
@@ -367,10 +509,13 @@ typedef int              GPtrDiff_t;
 #  define EQUAL(a,b)              (STRCASECMP(a,b)==0)
 #endif
 
-#ifdef macos_pre10
-int strcasecmp(char * str1, char * str2);
-int strncasecmp(char * str1, char * str2, int len);
-char * strdup (char *instr);
+/*---------------------------------------------------------------------
+ * Does a string "a" start with string "b".  Search is case-sensitive or,
+ * with CI, it is a case-insensitive comparison.
+ *--------------------------------------------------------------------- */
+#ifndef STARTS_WITH_CI
+#define STARTS_WITH(a,b)               (strncmp(a,b,strlen(b)) == 0)
+#define STARTS_WITH_CI(a,b)            EQUALN(a,b,strlen(b))
 #endif
 
 #ifndef CPL_THREADLOCAL
@@ -380,7 +525,7 @@ char * strdup (char *instr);
 /* -------------------------------------------------------------------- */
 /*      Handle isnan() and isinf().  Note that isinf() and isnan()      */
 /*      are supposed to be macros according to C99, defined in math.h   */
-/*      Some systems (ie. Tru64) don't have isinf() at all, so if       */
+/*      Some systems (i.e. Tru64) don't have isinf() at all, so if      */
 /*      the macro is not defined we just assume nothing is infinite.    */
 /*      This may mean we have no real CPLIsInf() on systems with isinf()*/
 /*      function but no corresponding macro, but I can live with        */
@@ -393,19 +538,23 @@ char * strdup (char *instr);
 #  define CPLIsFinite(x) _finite(x)
 #else
 #  define CPLIsNan(x) isnan(x)
-#  ifdef isinf 
+#  ifdef isinf
 #    define CPLIsInf(x) isinf(x)
 #    define CPLIsFinite(x) (!isnan(x) && !isinf(x))
+#  elif defined(__sun__)
+#    include <ieeefp.h>
+#    define CPLIsInf(x)    (!finite(x) && !isnan(x))
+#    define CPLIsFinite(x) finite(x)
 #  else
-#    define CPLIsInf(x)    FALSE
+#    define CPLIsInf(x)    (0)
 #    define CPLIsFinite(x) (!isnan(x))
 #  endif
 #endif
 
 /*---------------------------------------------------------------------
  *                         CPL_LSB and CPL_MSB
- * Only one of these 2 macros should be defined and specifies the byte 
- * ordering for the current platform.  
+ * Only one of these 2 macros should be defined and specifies the byte
+ * ordering for the current platform.
  * This should be defined in the Makefile, but if it is not then
  * the default is CPL_LSB (Intel ordering, LSB first).
  *--------------------------------------------------------------------*/
@@ -423,6 +572,27 @@ char * strdup (char *instr);
 #  define CPL_IS_LSB 0
 #endif
 
+#ifdef __cplusplus
+
+extern "C++" {
+
+template <bool b> struct CPLStaticAssert {};
+template<> struct CPLStaticAssert<true>
+{
+    static void my_function() {}
+};
+
+} /* extern "C++" */
+
+#define CPL_STATIC_ASSERT(x) CPLStaticAssert<x>::my_function()
+#define CPL_STATIC_ASSERT_IF_AVAILABLE(x) CPL_STATIC_ASSERT(x)
+
+#else  /* __cplusplus */
+
+#define CPL_STATIC_ASSERT_IF_AVAILABLE(x)
+
+#endif  /* __cplusplus */
+
 /*---------------------------------------------------------------------
  *        Little endian <==> big endian byte swap macros.
  *--------------------------------------------------------------------*/
@@ -435,12 +605,13 @@ char * strdup (char *instr);
 #define CPL_SWAP16PTR(x) \
 {                                                                 \
     GByte       byTemp, *_pabyDataT = (GByte *) (x);              \
+    CPL_STATIC_ASSERT_IF_AVAILABLE(sizeof(*(x)) == 1 || sizeof(*(x)) == 2); \
                                                                   \
     byTemp = _pabyDataT[0];                                       \
     _pabyDataT[0] = _pabyDataT[1];                                \
     _pabyDataT[1] = byTemp;                                       \
-}                                                                    
-                                                            
+}
+
 #define CPL_SWAP32(x) \
         ((GUInt32)( \
             (((GUInt32)(x) & (GUInt32)0x000000ffUL) << 24) | \
@@ -451,6 +622,7 @@ char * strdup (char *instr);
 #define CPL_SWAP32PTR(x) \
 {                                                                 \
     GByte       byTemp, *_pabyDataT = (GByte *) (x);              \
+    CPL_STATIC_ASSERT_IF_AVAILABLE(sizeof(*(x)) == 1 || sizeof(*(x)) == 4);  \
                                                                   \
     byTemp = _pabyDataT[0];                                       \
     _pabyDataT[0] = _pabyDataT[3];                                \
@@ -458,11 +630,12 @@ char * strdup (char *instr);
     byTemp = _pabyDataT[1];                                       \
     _pabyDataT[1] = _pabyDataT[2];                                \
     _pabyDataT[2] = byTemp;                                       \
-}                                                                    
-                                                            
+}
+
 #define CPL_SWAP64PTR(x) \
 {                                                                 \
     GByte       byTemp, *_pabyDataT = (GByte *) (x);              \
+    CPL_STATIC_ASSERT_IF_AVAILABLE(sizeof(*(x)) == 1 || sizeof(*(x)) == 8); \
                                                                   \
     byTemp = _pabyDataT[0];                                       \
     _pabyDataT[0] = _pabyDataT[7];                                \
@@ -476,8 +649,8 @@ char * strdup (char *instr);
     byTemp = _pabyDataT[3];                                       \
     _pabyDataT[3] = _pabyDataT[4];                                \
     _pabyDataT[4] = byTemp;                                       \
-}                                                                    
-                                                            
+}
+
 
 /* Until we have a safe 64 bits integer data type defined, we'll replace
  * this version of the CPL_SWAP64() macro with a less efficient one.
@@ -502,22 +675,22 @@ char * strdup (char *instr);
 #  define CPL_LSBWORD16(x)      CPL_SWAP16(x)
 #  define CPL_MSBWORD32(x)      (x)
 #  define CPL_LSBWORD32(x)      CPL_SWAP32(x)
-#  define CPL_MSBPTR16(x)       
+#  define CPL_MSBPTR16(x)       CPL_STATIC_ASSERT_IF_AVAILABLE(sizeof(*(x)) == 1 || sizeof(*(x)) == 2)
 #  define CPL_LSBPTR16(x)       CPL_SWAP16PTR(x)
-#  define CPL_MSBPTR32(x)       
+#  define CPL_MSBPTR32(x)       CPL_STATIC_ASSERT_IF_AVAILABLE(sizeof(*(x)) == 1 || sizeof(*(x)) == 4)
 #  define CPL_LSBPTR32(x)       CPL_SWAP32PTR(x)
-#  define CPL_MSBPTR64(x)       
+#  define CPL_MSBPTR64(x)       CPL_STATIC_ASSERT_IF_AVAILABLE(sizeof(*(x)) == 1 || sizeof(*(x)) == 8)
 #  define CPL_LSBPTR64(x)       CPL_SWAP64PTR(x)
 #else
 #  define CPL_LSBWORD16(x)      (x)
 #  define CPL_MSBWORD16(x)      CPL_SWAP16(x)
 #  define CPL_LSBWORD32(x)      (x)
 #  define CPL_MSBWORD32(x)      CPL_SWAP32(x)
-#  define CPL_LSBPTR16(x)       
+#  define CPL_LSBPTR16(x)       CPL_STATIC_ASSERT_IF_AVAILABLE(sizeof(*(x)) == 1 || sizeof(*(x)) == 2)
 #  define CPL_MSBPTR16(x)       CPL_SWAP16PTR(x)
-#  define CPL_LSBPTR32(x)       
+#  define CPL_LSBPTR32(x)       CPL_STATIC_ASSERT_IF_AVAILABLE(sizeof(*(x)) == 1 || sizeof(*(x)) == 4)
 #  define CPL_MSBPTR32(x)       CPL_SWAP32PTR(x)
-#  define CPL_LSBPTR64(x)       
+#  define CPL_LSBPTR64(x)       CPL_STATIC_ASSERT_IF_AVAILABLE(sizeof(*(x)) == 1 || sizeof(*(x)) == 8)
 #  define CPL_MSBPTR64(x)       CPL_SWAP64PTR(x)
 #endif
 
@@ -542,7 +715,7 @@ char * strdup (char *instr);
 
 
 /* Utility macro to explicitly mark intentionally unreferenced parameters. */
-#ifndef UNREFERENCED_PARAM 
+#ifndef UNREFERENCED_PARAM
 #  ifdef UNREFERENCED_PARAMETER /* May be defined by Windows API */
 #    define UNREFERENCED_PARAM(param) UNREFERENCED_PARAMETER(param)
 #  else
@@ -552,7 +725,7 @@ char * strdup (char *instr);
 
 /***********************************************************************
  * Define CPL_CVSID() macro.  It can be disabled during a build by
- * defining DISABLE_CPLID in the compiler options.
+ * defining DISABLE_CVSID in the compiler options.
  *
  * The cvsid_aw() function is just there to prevent reports of cpl_cvsid()
  * being unused.
@@ -560,17 +733,18 @@ char * strdup (char *instr);
 
 #ifndef DISABLE_CVSID
 #if defined(__GNUC__) && __GNUC__ >= 4
-#  define CPL_CVSID(string)     static char cpl_cvsid[] __attribute__((used)) = string;
+#  define CPL_CVSID(string)     static const char cpl_cvsid[] __attribute__((used)) = string;
 #else
-#  define CPL_CVSID(string)     static char cpl_cvsid[] = string; \
-static char *cvsid_aw() { return( cvsid_aw() ? ((char *) NULL) : cpl_cvsid ); }
+#  define CPL_CVSID(string)     static const char cpl_cvsid[] = string; \
+static const char *cvsid_aw() { return( cvsid_aw() ? NULL : cpl_cvsid ); }
 #endif
 #else
 #  define CPL_CVSID(string)
 #endif
 
 /* Null terminated variadic */
-#if defined(__GNUC__) && __GNUC__ >= 4 && !defined(DOXYGEN_SKIP)
+/* We exclude mingw64 4.6 which seems to be broken regarding this */
+#if defined(__GNUC__) && __GNUC__ >= 4 && !defined(DOXYGEN_SKIP) && !(defined(__MINGW64__) && __GNUC__ == 4 && __GNUC_MINOR__ == 6)
 #   define CPL_NULL_TERMINATED     __attribute__((__sentinel__))
 #else
 #   define CPL_NULL_TERMINATED
@@ -578,8 +752,10 @@ static char *cvsid_aw() { return( cvsid_aw() ? ((char *) NULL) : cpl_cvsid ); }
 
 #if defined(__GNUC__) && __GNUC__ >= 3 && !defined(DOXYGEN_SKIP)
 #define CPL_PRINT_FUNC_FORMAT( format_idx, arg_idx )  __attribute__((__format__ (__printf__, format_idx, arg_idx)))
+#define CPL_SCAN_FUNC_FORMAT( format_idx, arg_idx )  __attribute__((__format__ (__scanf__, format_idx, arg_idx)))
 #else
 #define CPL_PRINT_FUNC_FORMAT( format_idx, arg_idx )
+#define CPL_SCAN_FUNC_FORMAT( format_idx, arg_idx )
 #endif
 
 #if defined(__GNUC__) && __GNUC__ >= 4 && !defined(DOXYGEN_SKIP)
@@ -601,6 +777,45 @@ static char *cvsid_aw() { return( cvsid_aw() ? ((char *) NULL) : cpl_cvsid ); }
 #define CPL_NO_RETURN
 #endif
 
+/* Clang __has_attribute */
+#ifndef __has_attribute
+  #define __has_attribute(x) 0  // Compatibility with non-clang compilers.
+#endif
+
+#if ((defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9))) || __has_attribute(returns_nonnull)) && !defined(DOXYGEN_SKIP)
+#  define CPL_RETURNS_NONNULL __attribute__((returns_nonnull))
+#else
+#  define CPL_RETURNS_NONNULL
+#endif
+
+
+#if defined(__GNUC__) && __GNUC__ >= 4 && !defined(DOXYGEN_SKIP)
+#define CPL_RESTRICT __restrict__
+#else
+#define CPL_RESTRICT
+#endif
+
+/* Helper to remove the copy and assignment constructors so that the compiler
+   will not generate the default versions.
+
+   Must be placed in the private section of a class and should be at the end.
+*/
+#ifdef __cplusplus
+
+#if __cplusplus >= 201103L
+#define CPL_FINAL final
+#define CPL_DISALLOW_COPY_ASSIGN(ClassName) \
+    ClassName( const ClassName & ) = delete; \
+    ClassName &operator=( const ClassName & ) = delete;
+#else
+#define CPL_FINAL
+#define CPL_DISALLOW_COPY_ASSIGN(ClassName) \
+    ClassName( const ClassName & ); \
+    ClassName &operator=( const ClassName & );
+#endif
+
+#endif /* __cplusplus */
+
 #if !defined(DOXYGEN_SKIP)
 #if defined(__has_extension)
   #if __has_extension(attribute_deprecated_with_message)
@@ -616,10 +831,133 @@ static char *cvsid_aw() { return( cvsid_aw() ? ((char *) NULL) : cpl_cvsid ); }
 #endif
 #endif
 
+#if !defined(_MSC_VER) && !defined(__APPLE__)
+CPL_C_START
 #ifdef WARN_STANDARD_PRINTF
 int vsnprintf(char *str, size_t size, const char* fmt, va_list args) CPL_WARN_DEPRECATED("Use CPLvsnprintf() instead");
 int snprintf(char *str, size_t size, const char* fmt, ...) CPL_PRINT_FUNC_FORMAT(3,4) CPL_WARN_DEPRECATED("Use CPLsnprintf() instead");
-int sprintf(char *str, const char* fmt, ...) CPL_PRINT_FUNC_FORMAT(2, 3) CPL_WARN_DEPRECATED("Use CPLsprintf() instead");
+int sprintf(char *str, const char* fmt, ...) CPL_PRINT_FUNC_FORMAT(2, 3) CPL_WARN_DEPRECATED("Use CPLsnprintf() instead");
+#elif defined(GDAL_COMPILATION) && !defined(DONT_DEPRECATE_SPRINTF)
+int sprintf(char *str, const char* fmt, ...) CPL_PRINT_FUNC_FORMAT(2, 3) CPL_WARN_DEPRECATED("Use snprintf() or CPLsnprintf() instead");
 #endif
+CPL_C_END
+#endif /* !defined(_MSC_VER) && !defined(__APPLE__) */
+
+#if defined(MAKE_SANITIZE_HAPPY) || !(defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64))
+#define CPL_CPU_REQUIRES_ALIGNED_ACCESS
+#define CPL_IS_DOUBLE_A_INT(d)  ( (d) >= INT_MIN && (d) <= INT_MAX && (double)(int)(d) == (d) )
+#else
+/* This is technically unspecified behaviour if the double is out of range, but works OK on x86 */
+#define CPL_IS_DOUBLE_A_INT(d)  ( (double)(int)(d) == (d) )
+#endif
+
+#ifdef __cplusplus
+/* The size of C style arrays. */
+#define CPL_ARRAYSIZE(array) \
+  ((sizeof(array) / sizeof(*(array))) / \
+  static_cast<size_t>(!(sizeof(array) % sizeof(*(array)))))
+
+extern "C++" {
+template<class T> static void CPL_IGNORE_RET_VAL(T) {}
+inline static bool CPL_TO_BOOL(int x) { return x != 0; }
+} /* extern "C++" */
+
+#endif  /* __cplusplus */
+
+#if (((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) || (defined(__clang__) && __clang_major__ >= 3)) && !defined(_MSC_VER))
+#define HAVE_GCC_DIAGNOSTIC_PUSH
+#endif
+
+#if ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) && !defined(_MSC_VER))
+#define HAVE_GCC_SYSTEM_HEADER
+#endif
+
+#if defined(__clang__)
+#  define CPL_FALLTHROUGH [[clang::fallthrough]];
+#else
+#  define CPL_FALLTHROUGH
+#endif
+
+// Define DEBUG_BOOL to compile in "MSVC mode", ie error out when
+// a integer is assigned to a bool
+// WARNING: use only at compilation time, since it is know to not work
+//  at runtime for unknown reasons (crash in MongoDB driver for example)
+#if defined(__cplusplus) && defined(DEBUG_BOOL) && !defined(DO_NOT_USE_DEBUG_BOOL)
+extern "C++" {
+class MSVCPedanticBool
+{
+
+        friend bool operator== (const bool& one, const MSVCPedanticBool& other);
+        friend bool operator!= (const bool& one, const MSVCPedanticBool& other);
+
+        bool b;
+        MSVCPedanticBool(int bIn);
+
+    public:
+        /* b not initialized on purpose in default ctor to flag use. */
+        /* cppcheck-suppress uninitMemberVar */
+        MSVCPedanticBool() {}
+        MSVCPedanticBool(bool bIn) : b(bIn) {}
+        MSVCPedanticBool(const MSVCPedanticBool& other) : b(other.b) {}
+
+        MSVCPedanticBool& operator= (const MSVCPedanticBool& other) { b = other.b; return *this; }
+        MSVCPedanticBool& operator&= (const MSVCPedanticBool& other) { b &= other.b; return *this; }
+        MSVCPedanticBool& operator|= (const MSVCPedanticBool& other) { b |= other.b; return *this; }
+
+        bool operator== (const bool& other) const { return b == other; }
+        bool operator!= (const bool& other) const { return b != other; }
+        bool operator== (const MSVCPedanticBool& other) const { return b == other.b; }
+        bool operator!= (const MSVCPedanticBool& other) const { return b != other.b; }
+
+        bool operator! () const { return !b; }
+        operator bool() const { return b; }
+        operator int() const { return b; }
+};
+
+inline bool operator== (const bool& one, const MSVCPedanticBool& other) { return one == other.b; }
+inline bool operator!= (const bool& one, const MSVCPedanticBool& other) { return one != other.b; }
+
+/* We must include all C++ stuff before to avoid issues with templates that use bool */
+#include <vector>
+#include <map>
+#include <set>
+#include <string>
+#include <cstddef>
+#include <limits>
+#include <sstream>
+#include <fstream>
+#include <algorithm>
+
+} /* extern C++ */
+
+#undef FALSE
+#define FALSE false
+#undef TRUE
+#define TRUE true
+
+/* In the very few cases we really need a "simple" type, fallback to bool */
+#define EMULATED_BOOL int
+
+/* Use our class instead of bool */
+#define bool MSVCPedanticBool
+
+/* "volatile bool" with the below substitution doesn't really work. */
+/* Just for the sake of the debug, we don't really need volatile */
+#define VOLATILE_BOOL bool
+
+#else /* defined(__cplusplus) && defined(DEBUG_BOOL) */
+
+#ifndef FALSE
+#  define FALSE 0
+#endif
+
+#ifndef TRUE
+#  define TRUE  1
+#endif
+
+#define EMULATED_BOOL bool
+#define VOLATILE_BOOL volatile bool
+
+#endif /* defined(__cplusplus) && defined(DEBUG_BOOL) */
 
 #endif /* ndef CPL_BASE_H_INCLUDED */
diff --git a/port/cpl_progress.cpp b/port/cpl_progress.cpp
index 8fe7714..a1828df 100644
--- a/port/cpl_progress.cpp
+++ b/port/cpl_progress.cpp
@@ -30,6 +30,10 @@
 #include "cpl_progress.h"
 #include "cpl_conv.h"
 
+#include <cmath>
+
+#include <algorithm>
+
 CPL_CVSID("$Id: gdal_misc.cpp 25494 2013-01-13 12:55:17Z etourigny $");
 
 /************************************************************************/
@@ -45,9 +49,9 @@ CPL_CVSID("$Id: gdal_misc.cpp 25494 2013-01-13 12:55:17Z etourigny $");
  * to use one of the other progress functions that actually do something.
  */
 
-int CPL_STDCALL GDALDummyProgress( CPL_UNUSED double dfComplete,
-                                   CPL_UNUSED const char *pszMessage,
-                                   CPL_UNUSED void *pData )
+int CPL_STDCALL GDALDummyProgress( double /* dfComplete */ ,
+                                   const char * /* pszMessage */ ,
+                                   void * /* pData */ )
 {
     return TRUE;
 }
@@ -73,9 +77,11 @@ int CPL_STDCALL GDALScaledProgress( double dfComplete, const char *pszMessage,
                                     void *pData )
 
 {
-    GDALScaledProgressInfo *psInfo = (GDALScaledProgressInfo *) pData;
-    
-    /* optimization if GDALCreateScaledProgress() provided with GDALDummyProgress */
+    GDALScaledProgressInfo *psInfo
+        = reinterpret_cast<GDALScaledProgressInfo *>( pData );
+
+    // Optimization if GDALCreateScaledProgress() provided with
+    // GDALDummyProgress.
     if( psInfo == NULL )
         return TRUE;
 
@@ -133,19 +139,18 @@ int CPL_STDCALL GDALScaledProgress( double dfComplete, const char *pszMessage,
  */
 
 void * CPL_STDCALL GDALCreateScaledProgress( double dfMin, double dfMax,
-                                GDALProgressFunc pfnProgress,
-                                void * pData )
+                                             GDALProgressFunc pfnProgress,
+                                             void * pData )
 
 {
-    GDALScaledProgressInfo *psInfo;
-    
     if( pfnProgress == NULL || pfnProgress == GDALDummyProgress )
         return NULL;
 
-    psInfo = (GDALScaledProgressInfo *)
-        CPLCalloc(sizeof(GDALScaledProgressInfo),1);
+    GDALScaledProgressInfo *psInfo
+        = static_cast<GDALScaledProgressInfo *>(
+            CPLCalloc( sizeof(GDALScaledProgressInfo), 1 ) );
 
-    if( ABS(dfMin-dfMax) < 0.0000001 )
+    if( std::abs(dfMin-dfMax) < 0.0000001 )
         dfMax = dfMin + 0.01;
 
     psInfo->pData = pData;
@@ -153,7 +158,7 @@ void * CPL_STDCALL GDALCreateScaledProgress( double dfMin, double dfMax,
     psInfo->dfMin = dfMin;
     psInfo->dfMax = dfMax;
 
-    return (void *) psInfo;
+    return static_cast<void *>( psInfo );
 }
 
 /************************************************************************/
@@ -197,7 +202,7 @@ void CPL_STDCALL GDALDestroyScaledProgress( void * pData )
  *
  * The GDALTermProgress() function maintains an internal memory of the
  * last percentage complete reported in a static variable, and this makes
- * it unsuitable to have multiple GDALTermProgress()'s active eithin a
+ * it unsuitable to have multiple GDALTermProgress()'s active either in a
  * single thread or across multiple threads.
  *
  * @param dfComplete completion ratio from 0.0 to 1.0.
@@ -209,16 +214,13 @@ void CPL_STDCALL GDALDestroyScaledProgress( void * pData )
 
 int CPL_STDCALL GDALTermProgress( CPL_UNUSED double dfComplete,
                                   CPL_UNUSED const char *pszMessage,
-                                  void * pProgressArg )
+                                  void * /* pProgressArg */ )
 {
-    static int nLastTick = -1;
-    int nThisTick = (int) (dfComplete * 40.0);
-
-    (void) pProgressArg;
-
-    nThisTick = MIN(40,MAX(0,nThisTick));
+    int nThisTick = std::min(40, std::max(0,
+        static_cast<int>(dfComplete * 40.0) ));
 
     // Have we started a new progress run?
+    static int nLastTick = -1;
     if( nThisTick < nLastTick && nLastTick >= 39 )
         nLastTick = -1;
 
@@ -227,7 +229,7 @@ int CPL_STDCALL GDALTermProgress( CPL_UNUSED double dfComplete,
 
     while( nThisTick > nLastTick )
     {
-        nLastTick++;
+        ++nLastTick;
         if( nLastTick % 4 == 0 )
             fprintf( stdout, "%d", (nLastTick / 4) * 10 );
         else
diff --git a/port/cpl_quad_tree.cpp b/port/cpl_quad_tree.cpp
index 4cb4512..09963a6 100644
--- a/port/cpl_quad_tree.cpp
+++ b/port/cpl_quad_tree.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_quad_tree.cpp 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: cpl_quad_tree.cpp 33199 2016-01-29 15:48:41Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implementation of quadtree building and searching functions.
@@ -29,16 +29,15 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ******************************************************************************
- *
  */
 
 #include "cpl_conv.h"
 #include "cpl_quad_tree.h"
 
-CPL_CVSID("$Id: cpl_quad_tree.cpp 27044 2014-03-16 23:41:27Z rouault $");
+CPL_CVSID("$Id: cpl_quad_tree.cpp 33199 2016-01-29 15:48:41Z rouault $");
 
-#define MAX_DEFAULT_TREE_DEPTH 12
-#define MAX_SUBNODES 4
+static const int MAX_DEFAULT_TREE_DEPTH = 12;
+static const int MAX_SUBNODES = 4;
 
 typedef struct _QuadTreeNode QuadTreeNode;
 
@@ -79,29 +78,31 @@ static void CPLQuadTreeAddFeatureInternal(CPLQuadTree *hQuadTree,
 /*      prevent small objects on a boundary from shifting too high      */
 /*      up the hQuadTree.                                                    */
 /* -------------------------------------------------------------------- */
-#define DEFAULT_SPLIT_RATIO  0.55
+static const double DEFAULT_SPLIT_RATIO = 0.55;
 
 /*
 ** Returns TRUE if rectangle a is contained in rectangle b
 */
-static CPL_INLINE int CPL_RectContained(const CPLRectObj *a, const CPLRectObj *b)
+static CPL_INLINE bool CPL_RectContained( const CPLRectObj *a,
+                                          const CPLRectObj *b )
 {
   if(a->minx >= b->minx && a->maxx <= b->maxx)
     if(a->miny >= b->miny && a->maxy <= b->maxy)
-      return(TRUE);
-  return(FALSE);  
+      return(true);
+  return(false);
 }
 
 /*
 ** Returns TRUE if rectangles a and b overlap
 */
-static CPL_INLINE int CPL_RectOverlap(const CPLRectObj *a, const CPLRectObj *b)
+static CPL_INLINE bool CPL_RectOverlap( const CPLRectObj *a,
+                                        const CPLRectObj *b )
 {
-  if(a->minx > b->maxx) return(FALSE);
-  if(a->maxx < b->minx) return(FALSE);
-  if(a->miny > b->maxy) return(FALSE);
-  if(a->maxy < b->miny) return(FALSE);
-  return(TRUE);
+  if(a->minx > b->maxx) return(false);
+  if(a->maxx < b->minx) return(false);
+  if(a->miny > b->maxy) return(false);
+  if(a->maxy < b->miny) return(false);
+  return(true);
 }
 
 /************************************************************************/
@@ -110,9 +111,8 @@ static CPL_INLINE int CPL_RectOverlap(const CPLRectObj *a, const CPLRectObj *b)
 
 static QuadTreeNode *CPLQuadTreeNodeCreate(const CPLRectObj* pRect)
 {
-    QuadTreeNode	*psNode;
-
-    psNode = (QuadTreeNode *) CPLMalloc(sizeof(QuadTreeNode));
+    QuadTreeNode *psNode
+        = static_cast<QuadTreeNode *>( CPLMalloc( sizeof(QuadTreeNode) ) );
 
     psNode->nFeatures = 0;
     psNode->pahFeatures = NULL;
@@ -131,7 +131,7 @@ static QuadTreeNode *CPLQuadTreeNodeCreate(const CPLRectObj* pRect)
 
 /**
  * Create a new quadtree
- * 
+ *
  * @param pGlobalBounds a pointer to the global extent of all
  *                      the elements that will be inserted
  * @param pfnGetBounds  a user provided function to get the bounding box of
@@ -143,16 +143,16 @@ static QuadTreeNode *CPLQuadTreeNodeCreate(const CPLRectObj* pRect)
  * @return a newly allocated quadtree
  */
 
-CPLQuadTree *CPLQuadTreeCreate(const CPLRectObj* pGlobalBounds, CPLQuadTreeGetBoundsFunc pfnGetBounds)
+CPLQuadTree *CPLQuadTreeCreate( const CPLRectObj* pGlobalBounds,
+                                CPLQuadTreeGetBoundsFunc pfnGetBounds )
 {
-    CPLQuadTree *hQuadTree;
-
     CPLAssert(pGlobalBounds);
 
     /* -------------------------------------------------------------------- */
     /*      Allocate the hQuadTree object                                   */
     /* -------------------------------------------------------------------- */
-    hQuadTree = (CPLQuadTree *) CPLMalloc(sizeof(CPLQuadTree));
+    CPLQuadTree *hQuadTree
+        = static_cast<CPLQuadTree *>( CPLMalloc(sizeof(CPLQuadTree)) );
 
     hQuadTree->nFeatures = 0;
     hQuadTree->pfnGetBounds = pfnGetBounds;
@@ -175,8 +175,9 @@ CPLQuadTree *CPLQuadTreeCreate(const CPLRectObj* pGlobalBounds, CPLQuadTreeGetBo
 
 /**
  * Returns the optimal depth of a quadtree to hold nExpectedFeatures
- * 
- * @param nExpectedFeatures the expected maximum number of elements to be inserted
+ *
+ * @param nExpectedFeatures the expected maximum number of elements to be
+ * inserted.
  *
  * @return the optimal depth of a quadtree to hold nExpectedFeatures
  */
@@ -197,8 +198,8 @@ int CPLQuadTreeGetAdvisedMaxDepth(int nExpectedFeatures)
     }
 
     CPLDebug( "CPLQuadTree",
-                "Estimated spatial index tree depth: %d",
-                nMaxDepth );
+              "Estimated spatial index tree depth: %d",
+              nMaxDepth );
 
     /* NOTE: Due to problems with memory allocation for deep trees,
         * automatically estimated depth is limited up to 12 levels.
@@ -209,8 +210,9 @@ int CPLQuadTreeGetAdvisedMaxDepth(int nExpectedFeatures)
         nMaxDepth = MAX_DEFAULT_TREE_DEPTH;
 
         CPLDebug( "CPLQuadTree",
-                    "Falling back to max number of allowed index tree levels (%d).",
-                    MAX_DEFAULT_TREE_DEPTH );
+                  "Falling back to max number of allowed index tree "
+                  "levels (%d).",
+                  MAX_DEFAULT_TREE_DEPTH );
 
     }
 
@@ -224,7 +226,7 @@ int CPLQuadTreeGetAdvisedMaxDepth(int nExpectedFeatures)
 /**
  * Set the maximum depth of a quadtree. By default, quad trees have
  * no maximum depth, but a maximum bucket capacity.
- * 
+ *
  * @param hQuadTree the quad tree
  * @param nMaxDepth the maximum depth allowed
  */
@@ -242,9 +244,9 @@ void CPLQuadTreeSetMaxDepth(CPLQuadTree *hQuadTree, int nMaxDepth)
  * Set the maximum capacity of a node of a quadtree. The default value is 8.
  * Note that the maximum capacity will only be honoured if the features
  * inserted have a point geometry. Otherwise it may be exceeded.
- * 
+ *
  * @param hQuadTree the quad tree
- * @param nBucketCapacity the maximum capactiy of a node of a quadtree
+ * @param nBucketCapacity the maximum capacity of a node of a quadtree
  */
 
 void CPLQuadTreeSetBucketCapacity(CPLQuadTree *hQuadTree, int nBucketCapacity)
@@ -259,14 +261,13 @@ void CPLQuadTreeSetBucketCapacity(CPLQuadTree *hQuadTree, int nBucketCapacity)
 
 /**
  * Insert a feature into a quadtree
- * 
+ *
  * @param hQuadTree the quad tree
  * @param hFeature the feature to insert
  */
 
 void CPLQuadTreeInsert(CPLQuadTree * hQuadTree, void* hFeature)
 {
-    CPLRectObj bounds;
     if( hQuadTree->pfnGetBounds == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -274,6 +275,7 @@ void CPLQuadTreeInsert(CPLQuadTree * hQuadTree, void* hFeature)
         return;
     }
     hQuadTree->nFeatures ++;
+    CPLRectObj bounds;
     hQuadTree->pfnGetBounds(hFeature, &bounds);
     CPLQuadTreeAddFeatureInternal(hQuadTree, hFeature, &bounds);
 }
@@ -284,7 +286,7 @@ void CPLQuadTreeInsert(CPLQuadTree * hQuadTree, void* hFeature)
 
 /**
  * Insert a feature into a quadtree
- * 
+ *
  * @param hQuadTree the quad tree
  * @param hFeature the feature to insert
  * @param psBounds bounds of the feature
@@ -303,11 +305,9 @@ void CPLQuadTreeInsertWithBounds(CPLQuadTree *hQuadTree,
 
 static void CPLQuadTreeNodeDestroy(QuadTreeNode *psNode)
 {
-    int i;
-
-    for(i=0; i<psNode->nNumSubNodes; i++ )
+    for(int i=0; i<psNode->nNumSubNodes; i++ )
     {
-        if(psNode->apSubNode[i]) 
+        if(psNode->apSubNode[i])
             CPLQuadTreeNodeDestroy(psNode->apSubNode[i]);
     }
 
@@ -327,7 +327,7 @@ static void CPLQuadTreeNodeDestroy(QuadTreeNode *psNode)
 
 /**
  * Destroy a quadtree
- * 
+ *
  * @param hQuadTree the quad tree to destroy
  */
 
@@ -349,21 +349,19 @@ static void CPLQuadTreeSplitBounds( double dfSplitRatio,
                                       CPLRectObj *out1,
                                       CPLRectObj *out2)
 {
-  double range;
-
   /* -------------------------------------------------------------------- */
   /*      The output bounds will be very similar to the input bounds,     */
   /*      so just copy over to start.                                     */
   /* -------------------------------------------------------------------- */
   memcpy(out1, in, sizeof(CPLRectObj));
   memcpy(out2, in, sizeof(CPLRectObj));
-  
+
   /* -------------------------------------------------------------------- */
   /*      Split in X direction.                                           */
   /* -------------------------------------------------------------------- */
   if((in->maxx - in->minx) > (in->maxy - in->miny)) {
-    range = in->maxx - in->minx;
-    
+    const double range = in->maxx - in->minx;
+
     out1->maxx = in->minx + range * dfSplitRatio;
     out2->minx = in->maxx - range * dfSplitRatio;
   }
@@ -372,8 +370,8 @@ static void CPLQuadTreeSplitBounds( double dfSplitRatio,
   /*      Otherwise split in Y direction.                                 */
   /* -------------------------------------------------------------------- */
   else {
-    range = in->maxy - in->miny;
-    
+    const double range = in->maxy - in->miny;
+
     out1->maxy = in->miny + range * dfSplitRatio;
     out2->miny = in->maxy - range * dfSplitRatio;
   }
@@ -388,7 +386,6 @@ static void CPLQuadTreeNodeAddFeatureAlg1( CPLQuadTree* hQuadTree,
                                            void* hFeature,
                                            const CPLRectObj* pRect)
 {
-    int i;
     if (psNode->nNumSubNodes == 0)
     {
         /* If we have reached the max bucket capacity, try to insert */
@@ -397,9 +394,12 @@ static void CPLQuadTreeNodeAddFeatureAlg1( CPLQuadTree* hQuadTree,
         {
             CPLRectObj half1, half2, quad1, quad2, quad3, quad4;
 
-            CPLQuadTreeSplitBounds(hQuadTree->dfSplitRatio, &psNode->rect, &half1, &half2);
-            CPLQuadTreeSplitBounds(hQuadTree->dfSplitRatio, &half1, &quad1, &quad2);
-            CPLQuadTreeSplitBounds(hQuadTree->dfSplitRatio, &half2, &quad3, &quad4);
+            CPLQuadTreeSplitBounds( hQuadTree->dfSplitRatio, &psNode->rect,
+                                    &half1, &half2);
+            CPLQuadTreeSplitBounds( hQuadTree->dfSplitRatio, &half1,
+                                    &quad1, &quad2);
+            CPLQuadTreeSplitBounds( hQuadTree->dfSplitRatio, &half2,
+                                    &quad3, &quad4);
 
             if (memcmp(&psNode->rect, &quad1, sizeof(CPLRectObj)) != 0 &&
                 memcmp(&psNode->rect, &quad2, sizeof(CPLRectObj)) != 0 &&
@@ -416,7 +416,7 @@ static void CPLQuadTreeNodeAddFeatureAlg1( CPLQuadTree* hQuadTree,
                 psNode->apSubNode[2] = CPLQuadTreeNodeCreate(&quad3);
                 psNode->apSubNode[3] = CPLQuadTreeNodeCreate(&quad4);
 
-                int oldNumFeatures = psNode->nFeatures;
+                const int oldNumFeatures = psNode->nFeatures;
                 void** oldFeatures = psNode->pahFeatures;
                 CPLRectObj* pasOldBounds = psNode->pasBounds;
                 psNode->nFeatures = 0;
@@ -424,16 +424,19 @@ static void CPLQuadTreeNodeAddFeatureAlg1( CPLQuadTree* hQuadTree,
                 psNode->pasBounds = NULL;
 
                 /* redispatch existing pahFeatures in apSubNodes */
-                int i;
-                for(i=0;i<oldNumFeatures;i++)
+                for(int i=0;i<oldNumFeatures;i++)
                 {
                     if( hQuadTree->pfnGetBounds == NULL )
-                        CPLQuadTreeNodeAddFeatureAlg1(hQuadTree, psNode, oldFeatures[i], &pasOldBounds[i]);
+                        CPLQuadTreeNodeAddFeatureAlg1( hQuadTree, psNode,
+                                                       oldFeatures[i],
+                                                       &pasOldBounds[i]);
                     else
                     {
                         CPLRectObj bounds;
                         hQuadTree->pfnGetBounds(oldFeatures[i], &bounds);
-                        CPLQuadTreeNodeAddFeatureAlg1(hQuadTree, psNode, oldFeatures[i], &bounds);
+                        CPLQuadTreeNodeAddFeatureAlg1( hQuadTree, psNode,
+                                                       oldFeatures[i],
+                                                       &bounds );
                     }
                 }
 
@@ -441,7 +444,8 @@ static void CPLQuadTreeNodeAddFeatureAlg1( CPLQuadTree* hQuadTree,
                 CPLFree(pasOldBounds);
 
                 /* recurse back on this psNode now that it has apSubNodes */
-                CPLQuadTreeNodeAddFeatureAlg1(hQuadTree, psNode, hFeature, pRect);
+                CPLQuadTreeNodeAddFeatureAlg1( hQuadTree, psNode, hFeature,
+                                               pRect );
                 return;
             }
         }
@@ -452,11 +456,12 @@ static void CPLQuadTreeNodeAddFeatureAlg1( CPLQuadTree* hQuadTree,
     /*      If there are apSubNodes, then consider whether this object        */
     /*      will fit in them.                                               */
     /* -------------------------------------------------------------------- */
-        for(i=0; i<psNode->nNumSubNodes; i++ )
+        for(int i=0; i<psNode->nNumSubNodes; i++ )
         {
             if( CPL_RectContained(pRect, &psNode->apSubNode[i]->rect))
             {
-                CPLQuadTreeNodeAddFeatureAlg1( hQuadTree, psNode->apSubNode[i], hFeature, pRect);
+                CPLQuadTreeNodeAddFeatureAlg1( hQuadTree, psNode->apSubNode[i],
+                                               hFeature, pRect );
                 return;
             }
         }
@@ -470,15 +475,21 @@ static void CPLQuadTreeNodeAddFeatureAlg1( CPLQuadTree* hQuadTree,
     if( psNode->nFeatures == 1 )
     {
         CPLAssert( psNode->pahFeatures == NULL );
-        psNode->pahFeatures = (void**) CPLMalloc( hQuadTree->nBucketCapacity * sizeof(void*) );
+        psNode->pahFeatures = static_cast<void **>(
+            CPLMalloc( hQuadTree->nBucketCapacity * sizeof(void*) ) );
         if( hQuadTree->pfnGetBounds == NULL )
-            psNode->pasBounds = (CPLRectObj*) CPLMalloc( hQuadTree->nBucketCapacity * sizeof(CPLRectObj) );
+            psNode->pasBounds = static_cast<CPLRectObj *>(
+                CPLMalloc( hQuadTree->nBucketCapacity * sizeof(CPLRectObj) ) );
     }
     else if( psNode->nFeatures > hQuadTree->nBucketCapacity )
     {
-        psNode->pahFeatures = (void**) CPLRealloc( psNode->pahFeatures, sizeof(void*) * psNode->nFeatures );
+        psNode->pahFeatures = static_cast<void **>(
+            CPLRealloc( psNode->pahFeatures,
+                        sizeof(void*) * psNode->nFeatures ) );
         if( hQuadTree->pfnGetBounds == NULL )
-            psNode->pasBounds = (CPLRectObj*) CPLRealloc( psNode->pasBounds, sizeof(CPLRectObj) * psNode->nFeatures );
+            psNode->pasBounds = static_cast<CPLRectObj *>(
+                CPLRealloc( psNode->pasBounds,
+                            sizeof(CPLRectObj) * psNode->nFeatures ) );
     }
     psNode->pahFeatures[psNode->nFeatures-1] = hFeature;
     if( hQuadTree->pfnGetBounds == NULL )
@@ -498,15 +509,13 @@ static void CPLQuadTreeNodeAddFeatureAlg2( CPLQuadTree *hQuadTree,
                                            const CPLRectObj* pRect,
                                            int nMaxDepth)
 {
-    int i;
-
   /* -------------------------------------------------------------------- */
   /*      If there are apSubNodes, then consider whether this object        */
   /*      will fit in them.                                               */
   /* -------------------------------------------------------------------- */
     if( nMaxDepth > 1 && psNode->nNumSubNodes > 0 )
     {
-        for(i=0; i<psNode->nNumSubNodes; i++ )
+        for(int i=0; i<psNode->nNumSubNodes; i++ )
         {
             if( CPL_RectContained(pRect, &psNode->apSubNode[i]->rect))
             {
@@ -525,7 +534,8 @@ static void CPLQuadTreeNodeAddFeatureAlg2( CPLQuadTree *hQuadTree,
     {
         CPLRectObj half1, half2, quad1, quad2, quad3, quad4;
 
-        CPLQuadTreeSplitBounds(hQuadTree->dfSplitRatio, &psNode->rect, &half1, &half2);
+        CPLQuadTreeSplitBounds(hQuadTree->dfSplitRatio, &psNode->rect,
+                               &half1, &half2);
         CPLQuadTreeSplitBounds(hQuadTree->dfSplitRatio, &half1, &quad1, &quad2);
         CPLQuadTreeSplitBounds(hQuadTree->dfSplitRatio, &half2, &quad3, &quad4);
 
@@ -545,24 +555,27 @@ static void CPLQuadTreeNodeAddFeatureAlg2( CPLQuadTree *hQuadTree,
             psNode->apSubNode[3] = CPLQuadTreeNodeCreate(&quad4);
 
             /* recurse back on this psNode now that it has apSubNodes */
-            CPLQuadTreeNodeAddFeatureAlg2(hQuadTree, psNode, hFeature, pRect, nMaxDepth);
+            CPLQuadTreeNodeAddFeatureAlg2( hQuadTree, psNode, hFeature,
+                                           pRect, nMaxDepth);
             return;
         }
     }
 
+
 /* -------------------------------------------------------------------- */
 /*      If none of that worked, just add it to this psNodes list.         */
 /* -------------------------------------------------------------------- */
     psNode->nFeatures++;
 
     psNode->pahFeatures =
-            (void**) CPLRealloc( psNode->pahFeatures,
-                                 sizeof(void*) * psNode->nFeatures );
+        static_cast<void **>( CPLRealloc( psNode->pahFeatures,
+                                          sizeof(void*) * psNode->nFeatures ) );
     if( hQuadTree->pfnGetBounds == NULL )
     {
         psNode->pasBounds =
-            (CPLRectObj*) CPLRealloc( psNode->pasBounds,
-                                 sizeof(CPLRectObj) * psNode->nFeatures );
+          static_cast<CPLRectObj*>(
+              CPLRealloc( psNode->pasBounds,
+                          sizeof(CPLRectObj) * psNode->nFeatures ) );
     }
     psNode->pahFeatures[psNode->nFeatures-1] = hFeature;
     if( hQuadTree->pfnGetBounds == NULL )
@@ -603,29 +616,27 @@ static void CPLQuadTreeCollectFeatures(const CPLQuadTree *hQuadTree,
                                        int* pnMaxFeatures,
                                        void*** pppFeatureList)
 {
-  int i;
-
   /* -------------------------------------------------------------------- */
-  /*      Does this psNode overlap the area of interest at all?  If not,    */
+  /*      Does this psNode overlap the area of interest at all?  If not,  */
   /*      return without adding to the list at all.                       */
   /* -------------------------------------------------------------------- */
   if(!CPL_RectOverlap(&psNode->rect, pAoi))
      return;
 
-/* -------------------------------------------------------------------- */
-/*      Grow the list to hold the features on this psNode.              */
-/* -------------------------------------------------------------------- */
-    if( *pnFeatureCount + psNode->nFeatures > *pnMaxFeatures )
-    {
-        *pnMaxFeatures = (*pnFeatureCount + psNode->nFeatures) * 2 + 20;
-        *pppFeatureList = (void**)
-            CPLRealloc(*pppFeatureList,sizeof(void*) * *pnMaxFeatures);
-    }
+  /* -------------------------------------------------------------------- */
+  /*      Grow the list to hold the features on this psNode.              */
+  /* -------------------------------------------------------------------- */
+  if( *pnFeatureCount + psNode->nFeatures > *pnMaxFeatures )
+  {
+      *pnMaxFeatures = (*pnFeatureCount + psNode->nFeatures) * 2 + 20;
+      *pppFeatureList = static_cast<void **>(
+          CPLRealloc(*pppFeatureList,sizeof(void*) * *pnMaxFeatures) );
+  }
 
   /* -------------------------------------------------------------------- */
   /*      Add the local features to the list.                             */
   /* -------------------------------------------------------------------- */
-  for(i=0; i<psNode->nFeatures; i++)
+  for(int i=0; i<psNode->nFeatures; i++)
   {
       if( hQuadTree->pfnGetBounds == NULL )
       {
@@ -640,15 +651,16 @@ static void CPLQuadTreeCollectFeatures(const CPLQuadTree *hQuadTree,
             (*pppFeatureList)[(*pnFeatureCount)++] = psNode->pahFeatures[i];
       }
   }
-  
+
   /* -------------------------------------------------------------------- */
   /*      Recurse to subnodes if they exist.                              */
   /* -------------------------------------------------------------------- */
-  for(i=0; i<psNode->nNumSubNodes; i++)
+  for(int i=0; i<psNode->nNumSubNodes; i++)
   {
       if(psNode->apSubNode[i])
-        CPLQuadTreeCollectFeatures(hQuadTree, psNode->apSubNode[i], pAoi,
-                                   pnFeatureCount, pnMaxFeatures, pppFeatureList);
+        CPLQuadTreeCollectFeatures( hQuadTree, psNode->apSubNode[i], pAoi,
+                                    pnFeatureCount, pnMaxFeatures,
+                                    pppFeatureList );
   }
 }
 
@@ -659,7 +671,7 @@ static void CPLQuadTreeCollectFeatures(const CPLQuadTree *hQuadTree,
 /**
  * Returns all the elements inserted whose bounding box intersects the
  * provided area of interest
- * 
+ *
  * @param hQuadTree the quad tree
  * @param pAoi the pointer to the area of interest
  * @param pnFeatureCount the user data provided to the function.
@@ -671,45 +683,44 @@ void** CPLQuadTreeSearch(const CPLQuadTree *hQuadTree,
                          const CPLRectObj* pAoi,
                          int* pnFeatureCount)
 {
-  void** ppFeatureList = NULL;
-  int nMaxFeatures = 0;
-  int nFeatureCount = 0;
-
   CPLAssert(hQuadTree);
   CPLAssert(pAoi);
 
+  int nFeatureCount = 0;
   if (pnFeatureCount == NULL)
       pnFeatureCount = &nFeatureCount;
 
   *pnFeatureCount = 0;
+
+  int nMaxFeatures = 0;
+  void** ppFeatureList = NULL;
   CPLQuadTreeCollectFeatures(hQuadTree, hQuadTree->psRoot, pAoi,
                             pnFeatureCount, &nMaxFeatures, &ppFeatureList);
 
-  return(ppFeatureList);
+  return ppFeatureList;
 }
 
 /************************************************************************/
 /*                    CPLQuadTreeNodeForeach()                          */
 /************************************************************************/
 
-static int CPLQuadTreeNodeForeach(const QuadTreeNode *psNode,
+static bool CPLQuadTreeNodeForeach(const QuadTreeNode *psNode,
                                   CPLQuadTreeForeachFunc pfnForeach,
                                   void* pUserData)
 {
-    int i;
-    for(i=0; i<psNode->nNumSubNodes; i++ )
+    for(int i=0; i<psNode->nNumSubNodes; i++ )
     {
-        if (CPLQuadTreeNodeForeach(psNode->apSubNode[i], pfnForeach, pUserData) == FALSE)
-            return FALSE;
+        if( !CPLQuadTreeNodeForeach(psNode->apSubNode[i], pfnForeach, pUserData) )
+            return false;
     }
 
-    for(i=0; i<psNode->nFeatures; i++)
+    for(int i=0; i<psNode->nFeatures; i++)
     {
         if (pfnForeach(psNode->pahFeatures[i], pUserData) == FALSE)
-            return FALSE;
+            return false;
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -726,7 +737,7 @@ static int CPLQuadTreeNodeForeach(const QuadTreeNode *psNode,
  *
  * Note : the structure of the quadtree must *NOT* be modified during the
  * walk.
- * 
+ *
  * @param hQuadTree the quad tree
  * @param pfnForeach the function called on each element.
  * @param pUserData the user data provided to the function.
@@ -750,16 +761,14 @@ static void CPLQuadTreeDumpNode(const QuadTreeNode *psNode,
                                 CPLQuadTreeDumpFeatureFunc pfnDumpFeatureFunc,
                                 void* pUserData)
 {
-    int i;
-    int count;
     if (psNode->nNumSubNodes)
     {
-        for(count=nIndentLevel;--count>=0;)
+        for(int count=nIndentLevel;--count>=0;)
             printf("  ");
         printf("SubhQuadTrees :\n");
-        for(i=0; i<psNode->nNumSubNodes; i++ )
+        for(int i=0; i<psNode->nNumSubNodes; i++ )
         {
-            for(count=nIndentLevel+1;--count>=0;)
+            for(int count=nIndentLevel+1;--count>=0;)
                 printf("  ");
             printf("SubhQuadTree %d :\n", i+1);
             CPLQuadTreeDumpNode(psNode->apSubNode[i], nIndentLevel + 2,
@@ -768,17 +777,17 @@ static void CPLQuadTreeDumpNode(const QuadTreeNode *psNode,
     }
     if (psNode->nFeatures)
     {
-        for(count=nIndentLevel;--count>=0;)
+        for(int count=nIndentLevel;--count>=0;)
             printf("  ");
         printf("Leaves (%d):\n", psNode->nFeatures);
-        for(i=0; i<psNode->nFeatures; i++)
+        for(int i=0; i<psNode->nFeatures; i++)
         {
             if (pfnDumpFeatureFunc)
                 pfnDumpFeatureFunc(psNode->pahFeatures[i], nIndentLevel + 2,
                                    pUserData);
             else
             {
-                for(count=nIndentLevel + 1;--count>=0;)
+                for(int count=nIndentLevel + 1;--count>=0;)
                     printf("  ");
                 printf("%p\n", psNode->pahFeatures[i]);
             }
@@ -808,13 +817,13 @@ void CPLQuadTreeGetStatsNode(const QuadTreeNode *psNode,
                              int* pnMaxDepth,
                              int* pnMaxBucketCapacity)
 {
-    int i;
     (*pnNodeCount) ++;
     if (nDepthLevel > *pnMaxDepth)
         *pnMaxDepth = nDepthLevel;
     if (psNode->nFeatures > *pnMaxBucketCapacity)
         *pnMaxBucketCapacity = psNode->nFeatures;
-    for(i=0; i<psNode->nNumSubNodes; i++ )
+
+    for(int i=0; i<psNode->nNumSubNodes; i++ )
     {
         CPLQuadTreeGetStatsNode(psNode->apSubNode[i], nDepthLevel + 1,
                                 pnNodeCount, pnMaxDepth, pnMaxBucketCapacity);
@@ -848,5 +857,6 @@ void CPLQuadTreeGetStats(const CPLQuadTree *hQuadTree,
     *pnMaxDepth = 1;
     *pnMaxBucketCapacity = 0;
 
-    CPLQuadTreeGetStatsNode(hQuadTree->psRoot, 0, pnNodeCount, pnMaxDepth, pnMaxBucketCapacity);
+    CPLQuadTreeGetStatsNode( hQuadTree->psRoot, 0, pnNodeCount, pnMaxDepth,
+                             pnMaxBucketCapacity );
 }
diff --git a/port/cpl_quad_tree.h b/port/cpl_quad_tree.h
index 7b6bfc2..c02831a 100644
--- a/port/cpl_quad_tree.h
+++ b/port/cpl_quad_tree.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_quad_tree.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: cpl_quad_tree.h 33666 2016-03-07 05:21:07Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implementation of quadtree building and searching functions.
@@ -17,21 +17,21 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _CPL_QUAD_TREE_H_INCLUDED
-#define _CPL_QUAD_TREE_H_INCLUDED
+#ifndef CPL_QUAD_TREE_H_INCLUDED
+#define CPL_QUAD_TREE_H_INCLUDED
 
 #include "cpl_port.h"
 
diff --git a/port/cpl_recode.cpp b/port/cpl_recode.cpp
index 2a8e6aa..13f5abd 100644
--- a/port/cpl_recode.cpp
+++ b/port/cpl_recode.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_recode.cpp 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: cpl_recode.cpp 33724 2016-03-16 17:14:11Z goatbar $
  *
  * Name:     cpl_recode.cpp
  * Project:  CPL - Common Portability Library
@@ -26,11 +26,11 @@
 
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: cpl_recode.cpp 27044 2014-03-16 23:41:27Z rouault $");
+CPL_CVSID("$Id: cpl_recode.cpp 33724 2016-03-16 17:14:11Z goatbar $");
 
 #ifdef CPL_RECODE_ICONV
 extern void CPLClearRecodeIconvWarningFlags();
-extern char *CPLRecodeIconv( const char *, const char *, const char * );
+extern char *CPLRecodeIconv( const char *, const char *, const char * ) CPL_RETURNS_NONNULL;
 extern char *CPLRecodeFromWCharIconv( const wchar_t *,
                                       const char *, const char * );
 extern wchar_t *CPLRecodeToWCharIconv( const char *,
@@ -38,7 +38,7 @@ extern wchar_t *CPLRecodeToWCharIconv( const char *,
 #endif /* CPL_RECODE_ICONV */
 
 extern void CPLClearRecodeStubWarningFlags();
-extern char *CPLRecodeStub( const char *, const char *, const char * );
+extern char *CPLRecodeStub( const char *, const char *, const char * ) CPL_RETURNS_NONNULL;
 extern char *CPLRecodeFromWCharStub( const wchar_t *,
                                      const char *, const char * );
 extern wchar_t *CPLRecodeToWCharStub( const char *,
@@ -60,7 +60,7 @@ extern int CPLIsUTF8Stub( const char *, int );
  *  <li>CPL_ENC_UTF8 -> CPL_ENC_ISO8859_1</li>
  * </ul>
  *
- * If an error occurs an error may, or may not be posted with CPLError(). 
+ * If an error occurs an error may, or may not be posted with CPLError().
  *
  * @param pszSource a NULL terminated string.
  * @param pszSrcEncoding the source encoding.
@@ -82,15 +82,15 @@ char CPL_DLL *CPLRecode( const char *pszSource,
     if ( EQUAL(pszSrcEncoding, pszDstEncoding) )
         return CPLStrdup(pszSource);
 
-    if ( EQUAL(pszSrcEncoding, CPL_ENC_ASCII) 
-        && ( EQUAL(pszDstEncoding, CPL_ENC_UTF8) 
+    if ( EQUAL(pszSrcEncoding, CPL_ENC_ASCII)
+        && ( EQUAL(pszDstEncoding, CPL_ENC_UTF8)
              || EQUAL(pszDstEncoding, CPL_ENC_ISO8859_1) ) )
         return CPLStrdup(pszSource);
 
 #ifdef CPL_RECODE_ICONV
 /* -------------------------------------------------------------------- */
 /*      CPL_ENC_ISO8859_1 -> CPL_ENC_UTF8                               */
-/*      and CPL_ENC_UTF8 -> CPL_ENC_ISO8859_1 conversions are hadled    */
+/*      and CPL_ENC_UTF8 -> CPL_ENC_ISO8859_1 conversions are handled   */
 /*      very well by the stub implementation which is faster than the   */
 /*      iconv() route. Use a stub for these two ones and iconv()        */
 /*      everything else.                                                */
@@ -116,25 +116,25 @@ char CPL_DLL *CPLRecode( const char *pszSource,
 /************************************************************************/
 
 /**
- * Convert wchar_t string to UTF-8. 
+ * Convert wchar_t string to UTF-8.
  *
  * Convert a wchar_t string into a multibyte utf-8 string.  The only
  * guaranteed supported source encoding is CPL_ENC_UCS2, and the only
  * guaranteed supported destination encodings are CPL_ENC_UTF8, CPL_ENC_ASCII
- * and CPL_ENC_ISO8859_1.  In some cases (ie. using iconv()) other encodings 
+ * and CPL_ENC_ISO8859_1.  In some cases (i.e. using iconv()) other encodings
  * may also be supported.
  *
  * Note that the wchar_t type varies in size on different systems. On
- * win32 it is normally 2 bytes, and on unix 4 bytes.
+ * win32 it is normally 2 bytes, and on UNIX 4 bytes.
  *
- * If an error occurs an error may, or may not be posted with CPLError(). 
+ * If an error occurs an error may, or may not be posted with CPLError().
  *
  * @param pwszSource the source wchar_t string, terminated with a 0 wchar_t.
  * @param pszSrcEncoding the source encoding, typically CPL_ENC_UCS2.
  * @param pszDstEncoding the destination encoding, typically CPL_ENC_UTF8.
  *
- * @return a zero terminated multi-byte string which should be freed with 
- * CPLFree(), or NULL if an error occurs. 
+ * @return a zero terminated multi-byte string which should be freed with
+ * CPLFree(), or NULL if an error occurs.
  *
  * @since GDAL 1.6.0
  */
@@ -158,11 +158,10 @@ char CPL_DLL *CPLRecodeFromWChar( const wchar_t *pwszSource,
         return CPLRecodeFromWCharStub( pwszSource,
                                        pszSrcEncoding, pszDstEncoding );
     }
-    else
-    {
-        return CPLRecodeFromWCharIconv( pwszSource,
-                                        pszSrcEncoding, pszDstEncoding );
-    }
+
+    return CPLRecodeFromWCharIconv( pwszSource,
+                                    pszSrcEncoding, pszDstEncoding );
+
 #else /* CPL_RECODE_STUB */
     return CPLRecodeFromWCharStub( pwszSource,
                                    pszSrcEncoding, pszDstEncoding );
@@ -181,16 +180,16 @@ char CPL_DLL *CPLRecodeFromWChar( const wchar_t *pwszSource,
  * are CPL_ENC_UTF8, CPL_ENC_ASCII and CPL_ENC_ISO8869_1 (LATIN1).  The only
  * guaranteed supported destination encoding is CPL_ENC_UCS2.  Other source
  * and destination encodings may be supported depending on the underlying
- * implementation. 
+ * implementation.
  *
  * Note that the wchar_t type varies in size on different systems. On
- * win32 it is normally 2 bytes, and on unix 4 bytes.
+ * win32 it is normally 2 bytes, and on UNIX 4 bytes.
  *
- * If an error occurs an error may, or may not be posted with CPLError(). 
+ * If an error occurs an error may, or may not be posted with CPLError().
  *
  * @param pszSource input multi-byte character string.
  * @param pszSrcEncoding source encoding, typically CPL_ENC_UTF8.
- * @param pszDstEncoding destination encoding, typically CPL_ENC_UCS2. 
+ * @param pszDstEncoding destination encoding, typically CPL_ENC_UCS2.
  *
  * @return the zero terminated wchar_t string (to be freed with CPLFree()) or
  * NULL on error.
@@ -209,7 +208,8 @@ wchar_t CPL_DLL *CPLRecodeToWChar( const char *pszSource,
 /*      from CPL_ENC_UTF8, CPL_ENC_ISO8859_1 and CPL_ENC_ASCII are well */
 /*      handled by the stub implementation.                             */
 /* -------------------------------------------------------------------- */
-    if ( (EQUAL(pszDstEncoding, CPL_ENC_UCS2) || EQUAL(pszDstEncoding, "WCHAR_T"))
+    if ( (EQUAL(pszDstEncoding, CPL_ENC_UCS2)
+          || EQUAL(pszDstEncoding, "WCHAR_T"))
          && ( EQUAL(pszSrcEncoding, CPL_ENC_UTF8)
               || EQUAL(pszSrcEncoding, CPL_ENC_ASCII)
               || EQUAL(pszSrcEncoding, CPL_ENC_ISO8859_1) ) )
@@ -217,11 +217,10 @@ wchar_t CPL_DLL *CPLRecodeToWChar( const char *pszSource,
         return CPLRecodeToWCharStub( pszSource,
                                      pszSrcEncoding, pszDstEncoding );
     }
-    else
-    {
-        return CPLRecodeToWCharIconv( pszSource,
-                                      pszSrcEncoding, pszDstEncoding );
-    }
+
+    return CPLRecodeToWCharIconv( pszSource,
+                                  pszSrcEncoding, pszDstEncoding );
+
 #else /* CPL_RECODE_STUB */
     return CPLRecodeToWCharStub( pszSource, pszSrcEncoding, pszDstEncoding );
 #endif /* CPL_RECODE_ICONV */
@@ -265,20 +264,21 @@ int CPLIsUTF8(const char* pabyData, int nLen)
  *
  * @since GDAL 1.7.0
  */
-char CPL_DLL *CPLForceToASCII(const char* pabyData, int nLen, char chReplacementChar)
+char CPL_DLL *CPLForceToASCII( const char* pabyData, int nLen,
+                               char chReplacementChar)
 {
     if (nLen < 0)
-        nLen = strlen(pabyData);
-    char* pszOutputString = (char*)CPLMalloc(nLen + 1);
-    int i;
-    for(i=0;i<nLen;i++)
+        nLen = static_cast<int>(strlen(pabyData));
+    char* pszOutputString = static_cast<char *>( CPLMalloc(nLen + 1) );
+    for( int i=0;i < nLen; i++ )
     {
-        if (((unsigned char*)pabyData)[i] > 127)
+        if( reinterpret_cast<unsigned char *>(
+                const_cast<char *>( pabyData ) ) [i] > 127 )
             pszOutputString[i] = chReplacementChar;
         else
             pszOutputString[i] = pabyData[i];
     }
-    pszOutputString[i] = '\0';
+    pszOutputString[nLen] = '\0';
     return pszOutputString;
 }
 
@@ -293,17 +293,17 @@ char CPL_DLL *CPLForceToASCII(const char* pabyData, int nLen, char chReplacement
  * in this encoding.  For fixed width encodings (ASCII, UCS-2, UCS-4) this
  * is straight forward.  For encodings like UTF8 and UTF16 which represent
  * some characters as a sequence of atomic character sizes the function
- * still returns the atomic character size (1 for UTF8, 2 for UTF16). 
+ * still returns the atomic character size (1 for UTF8, 2 for UTF16).
  *
  * This function will return the correct value for well known encodings
  * with corresponding CPL_ENC_ values.  It may not return the correct value
- * for other encodings even if they are supported by the underlying iconv 
+ * for other encodings even if they are supported by the underlying iconv
  * or windows transliteration services.  Hopefully it will improve over time.
  *
  * @param pszEncoding the name of the encoding.
  *
- * @return the size of a minimal character in bytes or -1 if the size is 
- * unknown. 
+ * @return the size of a minimal character in bytes or -1 if the size is
+ * unknown.
  */
 
 int CPLEncodingCharSize( const char *pszEncoding )
@@ -319,10 +319,10 @@ int CPLEncodingCharSize( const char *pszEncoding )
         return 4;
     else if( EQUAL(pszEncoding,CPL_ENC_ASCII) )
         return 1;
-    else if( EQUALN(pszEncoding,"ISO-8859-",9) )
+    else if( STARTS_WITH_CI(pszEncoding, "ISO-8859-") )
         return 1;
-    else
-        return -1;
+
+    return -1;
 }
 
 /************************************************************************/
@@ -349,15 +349,15 @@ void CPLClearRecodeWarningFlags()
  *
  * @param pszUTF8Str a nul-terminated UTF-8 string
  *
- * @return the number of UTF-8 characters. 
+ * @return the number of UTF-8 characters.
  */
 
 int CPLStrlenUTF8(const char *pszUTF8Str) {
-    int i = 0, j = 0;
-    while (pszUTF8Str[i]) {
-        if ((pszUTF8Str[i] & 0xc0) != 0x80) j++;
-        i++;
+    int nCharacterCount = 0;
+    for( int i = 0; pszUTF8Str[i] != '\0'; ++i )
+    {
+        if( (pszUTF8Str[i] & 0xc0) != 0x80 )
+            ++nCharacterCount;
     }
-    return j;
+    return nCharacterCount;
 }
-
diff --git a/port/cpl_recode_iconv.cpp b/port/cpl_recode_iconv.cpp
index 9ed6b07..bd602f0 100644
--- a/port/cpl_recode_iconv.cpp
+++ b/port/cpl_recode_iconv.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_recode_iconv.cpp 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: cpl_recode_iconv.cpp 33724 2016-03-16 17:14:11Z goatbar $
  *
  * Name:     cpl_recode_iconv.cpp
  * Project:  CPL - Common Portability Library
@@ -26,7 +26,7 @@
 
 #include "cpl_port.h"
 
-CPL_CVSID("$Id: cpl_recode_iconv.cpp 27044 2014-03-16 23:41:27Z rouault $");
+CPL_CVSID("$Id: cpl_recode_iconv.cpp 33724 2016-03-16 17:14:11Z goatbar $");
 
 #ifdef CPL_RECODE_ICONV
 
@@ -39,17 +39,25 @@ CPL_CVSID("$Id: cpl_recode_iconv.cpp 27044 2014-03-16 23:41:27Z rouault $");
 
 #define CPL_RECODE_DSTBUF_SIZE 32768
 
+ /* used by cpl_recode.cpp */
+extern void CPLClearRecodeIconvWarningFlags();
+extern char *CPLRecodeIconv( const char *, const char *, const char * ) CPL_RETURNS_NONNULL;
+extern char *CPLRecodeFromWCharIconv( const wchar_t *,
+                                      const char *, const char * );
+extern wchar_t *CPLRecodeToWCharIconv( const char *,
+                                       const char *, const char * );
+
 /************************************************************************/
 /*                 CPLClearRecodeIconvWarningFlags()                    */
 /************************************************************************/
 
-static int bHaveWarned1 = FALSE;
-static int bHaveWarned2 = FALSE;
+static bool bHaveWarned1 = false;
+static bool bHaveWarned2 = false;
 
 void CPLClearRecodeIconvWarningFlags()
 {
-    bHaveWarned1 = FALSE;
-    bHaveWarned2 = FALSE;
+    bHaveWarned1 = false;
+    bHaveWarned2 = false;
 }
 
 /************************************************************************/
@@ -60,7 +68,7 @@ void CPLClearRecodeIconvWarningFlags()
  * Convert a string from a source encoding to a destination encoding
  * using the iconv() function.
  *
- * If an error occurs an error may, or may not be posted with CPLError(). 
+ * If an error occurs an error may, or may not be posted with CPLError().
  *
  * @param pszSource a NULL terminated string.
  * @param pszSrcEncoding the source encoding.
@@ -69,8 +77,8 @@ void CPLClearRecodeIconvWarningFlags()
  * @return a NULL terminated string which should be freed with CPLFree().
  */
 
-char *CPLRecodeIconv( const char *pszSource, 
-                      const char *pszSrcEncoding, 
+char *CPLRecodeIconv( const char *pszSource,
+                      const char *pszSrcEncoding,
                       const char *pszDstEncoding )
 
 {
@@ -80,8 +88,8 @@ char *CPLRecodeIconv( const char *pszSource,
 
     if ( sConv == (iconv_t)-1 )
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
-                  "Recode from %s to %s failed with the error: \"%s\".", 
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Recode from %s to %s failed with the error: \"%s\".",
                   pszSrcEncoding, pszDstEncoding, strerror(errno) );
 
         return CPLStrdup(pszSource);
@@ -112,7 +120,7 @@ char *CPLRecodeIconv( const char *pszSource,
                 // Skip the invalid sequence in the input string.
                 if (!bHaveWarned1)
                 {
-                    bHaveWarned1 = TRUE;
+                    bHaveWarned1 = true;
                     CPLError(CE_Warning, CPLE_AppDefined,
                             "One or several characters couldn't be converted correctly from %s to %s.\n"
                             "This warning will not be emitted anymore",
@@ -152,7 +160,7 @@ char *CPLRecodeIconv( const char *pszSource,
 /************************************************************************/
 
 /**
- * Convert wchar_t string to UTF-8. 
+ * Convert wchar_t string to UTF-8.
  *
  * Convert a wchar_t string into a multibyte utf-8 string
  * using the iconv() function.
@@ -160,18 +168,18 @@ char *CPLRecodeIconv( const char *pszSource,
  * Note that the wchar_t type varies in size on different systems. On
  * win32 it is normally 2 bytes, and on unix 4 bytes.
  *
- * If an error occurs an error may, or may not be posted with CPLError(). 
+ * If an error occurs an error may, or may not be posted with CPLError().
  *
  * @param pwszSource the source wchar_t string, terminated with a 0 wchar_t.
  * @param pszSrcEncoding the source encoding, typically CPL_ENC_UCS2.
  * @param pszDstEncoding the destination encoding, typically CPL_ENC_UTF8.
  *
- * @return a zero terminated multi-byte string which should be freed with 
- * CPLFree(), or NULL if an error occurs. 
+ * @return a zero terminated multi-byte string which should be freed with
+ * CPLFree(), or NULL if an error occurs.
  */
 
-char *CPLRecodeFromWCharIconv( const wchar_t *pwszSource, 
-                               const char *pszSrcEncoding, 
+char *CPLRecodeFromWCharIconv( const wchar_t *pwszSource,
+                               const char *pszSrcEncoding,
                                const char *pszDstEncoding )
 
 {
@@ -202,9 +210,8 @@ char *CPLRecodeFromWCharIconv( const wchar_t *pwszSource,
     }
 
     GByte *pszIconvSrcBuf = (GByte*) CPLCalloc((nSrcLen+1),nTargetCharWidth);
-    unsigned int iSrc;
 
-    for( iSrc = 0; iSrc <= nSrcLen; iSrc++ )
+    for( unsigned int iSrc = 0; iSrc <= nSrcLen; iSrc++ )
     {
         if( nTargetCharWidth == 1 )
             pszIconvSrcBuf[iSrc] = (GByte) pwszSource[iSrc];
@@ -224,8 +231,8 @@ char *CPLRecodeFromWCharIconv( const wchar_t *pwszSource,
     if ( sConv == (iconv_t)-1 )
     {
         CPLFree( pszIconvSrcBuf );
-        CPLError( CE_Warning, CPLE_AppDefined, 
-                  "Recode from %s to %s failed with the error: \"%s\".", 
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Recode from %s to %s failed with the error: \"%s\".",
                   pszSrcEncoding, pszDstEncoding, strerror(errno) );
 
         return CPLStrdup( "" );
@@ -264,7 +271,7 @@ char *CPLRecodeFromWCharIconv( const wchar_t *pwszSource,
                 pszSrcBuf += sizeof(wchar_t);
                 if (!bHaveWarned2)
                 {
-                    bHaveWarned2 = TRUE;
+                    bHaveWarned2 = true;
                     CPLError(CE_Warning, CPLE_AppDefined,
                             "One or several characters couldn't be converted correctly from %s to %s.\n"
                             "This warning will not be emitted anymore",
@@ -313,18 +320,18 @@ char *CPLRecodeFromWCharIconv( const wchar_t *pwszSource,
  * Note that the wchar_t type varies in size on different systems. On
  * win32 it is normally 2 bytes, and on unix 4 bytes.
  *
- * If an error occurs an error may, or may not be posted with CPLError(). 
+ * If an error occurs an error may, or may not be posted with CPLError().
  *
  * @param pszSource input multi-byte character string.
  * @param pszSrcEncoding source encoding, typically CPL_ENC_UTF8.
- * @param pszDstEncoding destination encoding, typically CPL_ENC_UCS2. 
+ * @param pszDstEncoding destination encoding, typically CPL_ENC_UCS2.
  *
  * @return the zero terminated wchar_t string (to be freed with CPLFree()) or
  * NULL on error.
  */
 
 wchar_t *CPLRecodeToWCharIconv( const char *pszSource,
-                                const char *pszSrcEncoding, 
+                                const char *pszSrcEncoding,
                                 const char *pszDstEncoding )
 
 {
diff --git a/port/cpl_recode_stub.cpp b/port/cpl_recode_stub.cpp
index 34840a5..1d4ce3a 100644
--- a/port/cpl_recode_stub.cpp
+++ b/port/cpl_recode_stub.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_recode_stub.cpp 29121 2015-05-02 22:53:48Z rouault $
+ * $Id: cpl_recode_stub.cpp 33724 2016-03-16 17:14:11Z goatbar $
  *
  * Name:     cpl_recode_stub.cpp
  * Project:  CPL - Common Portability Library
@@ -11,7 +11,7 @@
  * The bulk of this code is derived from the utf.c module from FLTK. It
  * was originally downloaded from:
  *    http://svn.easysw.com/public/fltk/fltk/trunk/src/utf.c
- * 
+ *
  **********************************************************************
  * Copyright (c) 2008, Frank Warmerdam
  * Copyright 2006 by Bill Spitzak and others.
@@ -32,9 +32,9 @@
 
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: cpl_recode_stub.cpp 29121 2015-05-02 22:53:48Z rouault $");
+CPL_CVSID("$Id: cpl_recode_stub.cpp 33724 2016-03-16 17:14:11Z goatbar $");
 
-#ifdef CPL_RECODE_STUB 
+#ifdef CPL_RECODE_STUB
 
 static unsigned utf8decode(const char* p, const char* end, int* len);
 static unsigned utf8towc(const char* src, unsigned srclen,
@@ -53,7 +53,7 @@ static int utf8test(const char* src, unsigned srclen);
 #include <winnls.h>
 
 static char* CPLWin32Recode( const char* src,
-                             unsigned src_code_page, unsigned dst_code_page );
+                             unsigned src_code_page, unsigned dst_code_page ) CPL_RETURNS_NONNULL;
 #endif
 
 #ifdef FUTURE_NEEDS
@@ -63,18 +63,27 @@ static int utf8encode(unsigned ucs, char* buf);
 static int utf8bytes(unsigned ucs);
 #endif /* def FUTURE_NEEDS */
 
+/* used by cpl_recode.cpp */
+extern void CPLClearRecodeStubWarningFlags();
+extern char *CPLRecodeStub( const char *, const char *, const char * ) CPL_RETURNS_NONNULL;
+extern char *CPLRecodeFromWCharStub( const wchar_t *,
+                                     const char *, const char * );
+extern wchar_t *CPLRecodeToWCharStub( const char *,
+                                      const char *, const char * );
+extern int CPLIsUTF8Stub( const char *, int );
+
 /************************************************************************/
 /* ==================================================================== */
 /*	Stub Implementation not depending on iconv() or WIN32 API.	*/
 /* ==================================================================== */
 /************************************************************************/
 
-static int bHaveWarned1 = FALSE;
-static int bHaveWarned2 = FALSE;
-static int bHaveWarned3 = FALSE;
-static int bHaveWarned4 = FALSE;
-static int bHaveWarned5 = FALSE;
-static int bHaveWarned6 = FALSE;
+static bool bHaveWarned1 = false;
+static bool bHaveWarned2 = false;
+static bool bHaveWarned3 = false;
+static bool bHaveWarned4 = false;
+static bool bHaveWarned5 = false;
+static bool bHaveWarned6 = false;
 
 /************************************************************************/
 /*                 CPLClearRecodeStubWarningFlags()                     */
@@ -82,12 +91,12 @@ static int bHaveWarned6 = FALSE;
 
 void CPLClearRecodeStubWarningFlags()
 {
-    bHaveWarned1 = FALSE;
-    bHaveWarned2 = FALSE;
-    bHaveWarned3 = FALSE;
-    bHaveWarned4 = FALSE;
-    bHaveWarned5 = FALSE;
-    bHaveWarned6 = FALSE;
+    bHaveWarned1 = false;
+    bHaveWarned2 = false;
+    bHaveWarned3 = false;
+    bHaveWarned4 = false;
+    bHaveWarned5 = false;
+    bHaveWarned6 = false;
 }
 
 /************************************************************************/
@@ -105,7 +114,7 @@ void CPLClearRecodeStubWarningFlags()
  *  <li>CPL_ENC_UTF8 -> CPL_ENC_ISO8859_1</li>
  * </ul>
  *
- * If an error occurs an error may, or may not be posted with CPLError(). 
+ * If an error occurs an error may, or may not be posted with CPLError().
  *
  * @param pszSource a NULL terminated string.
  * @param pszSrcEncoding the source encoding.
@@ -114,8 +123,8 @@ void CPLClearRecodeStubWarningFlags()
  * @return a NULL terminated string which should be freed with CPLFree().
  */
 
-char *CPLRecodeStub( const char *pszSource, 
-                     const char *pszSrcEncoding, 
+char *CPLRecodeStub( const char *pszSource,
+                     const char *pszSrcEncoding,
                      const char *pszDstEncoding )
 
 {
@@ -134,28 +143,28 @@ char *CPLRecodeStub( const char *pszSource,
 /* -------------------------------------------------------------------- */
 /*      ISO8859 to UTF8                                                 */
 /* -------------------------------------------------------------------- */
-    if( strcmp(pszSrcEncoding,CPL_ENC_ISO8859_1) == 0 
+    if( strcmp(pszSrcEncoding,CPL_ENC_ISO8859_1) == 0
         && strcmp(pszDstEncoding,CPL_ENC_UTF8) == 0 )
     {
-        int nCharCount = strlen(pszSource);
+        int nCharCount = static_cast<int>(strlen(pszSource));
         char *pszResult = (char *) CPLCalloc(1,nCharCount*2+1);
-        
+
         utf8froma( pszResult, nCharCount*2+1, pszSource, nCharCount );
-        
+
         return pszResult;
     }
 
 /* -------------------------------------------------------------------- */
 /*      UTF8 to ISO8859                                                 */
 /* -------------------------------------------------------------------- */
-    if( strcmp(pszSrcEncoding,CPL_ENC_UTF8) == 0 
+    if( strcmp(pszSrcEncoding,CPL_ENC_UTF8) == 0
         && strcmp(pszDstEncoding,CPL_ENC_ISO8859_1) == 0 )
     {
-        int nCharCount = strlen(pszSource);
+        int nCharCount = static_cast<int>(strlen(pszSource));
         char *pszResult = (char *) CPLCalloc(1,nCharCount+1);
-        
+
         utf8toa( pszSource, nCharCount, pszResult, nCharCount+1 );
-        
+
         return pszResult;
     }
 
@@ -163,7 +172,7 @@ char *CPLRecodeStub( const char *pszSource,
 /* ---------------------------------------------------------------------*/
 /*      CPXXX to UTF8                                                   */
 /* ---------------------------------------------------------------------*/
-    if( strncmp(pszSrcEncoding,"CP",2) == 0
+    if( STARTS_WITH(pszSrcEncoding, "CP")
         && strcmp(pszDstEncoding,CPL_ENC_UTF8) == 0 )
     {
         int nCode = atoi( pszSrcEncoding + 2 );
@@ -178,7 +187,7 @@ char *CPLRecodeStub( const char *pszSource,
 /*      UTF8 to CPXXX                                                   */
 /* ---------------------------------------------------------------------*/
     if( strcmp(pszSrcEncoding,CPL_ENC_UTF8) == 0
-        && strncmp(pszDstEncoding,"CP",2) == 0 )
+        && STARTS_WITH(pszDstEncoding, "CP") )
     {
          int nCode = atoi( pszDstEncoding + 2 );
          if( nCode > 0 ) {
@@ -193,19 +202,38 @@ char *CPLRecodeStub( const char *pszSource,
 /* -------------------------------------------------------------------- */
     if( strcmp(pszDstEncoding,CPL_ENC_UTF8) == 0 )
     {
-        int nCharCount = strlen(pszSource);
+        int nCharCount = static_cast<int>(strlen(pszSource));
         char *pszResult = (char *) CPLCalloc(1,nCharCount*2+1);
 
+        if( EQUAL( pszSrcEncoding, "CP437") ) /* For ZIP file handling */
+        {
+            bool bIsAllPrintableASCII = true;
+            for(int i=0;i<nCharCount;i++)
+            {
+                if( pszSource[i] < 32 || pszSource[i] > 126 )
+                {
+                    bIsAllPrintableASCII = false;
+                    break;
+                }
+            }
+            if( bIsAllPrintableASCII )
+            {
+                if( nCharCount )
+                    memcpy( pszResult, pszSource, nCharCount );
+                return pszResult;
+            }
+        }
+
         if( !bHaveWarned1 )
         {
-            bHaveWarned1 = 1;
-            CPLError( CE_Warning, CPLE_AppDefined, 
-                      "Recode from %s to UTF-8 not supported, treated as ISO8859-1 to UTF-8.", 
+            bHaveWarned1 = true;
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Recode from %s to UTF-8 not supported, treated as ISO8859-1 to UTF-8.",
                       pszSrcEncoding );
         }
 
         utf8froma( pszResult, nCharCount*2+1, pszSource, nCharCount );
-        
+
         return pszResult;
     }
 
@@ -213,22 +241,22 @@ char *CPLRecodeStub( const char *pszSource,
 /*      UTF-8 to anything else is treated as UTF-8 to ISO-8859-1        */
 /*      with a warning.                                                 */
 /* -------------------------------------------------------------------- */
-    if( strcmp(pszSrcEncoding,CPL_ENC_UTF8) == 0 
+    if( strcmp(pszSrcEncoding,CPL_ENC_UTF8) == 0
         && strcmp(pszDstEncoding,CPL_ENC_ISO8859_1) == 0 )
     {
-        int nCharCount = strlen(pszSource);
+        int nCharCount = static_cast<int>(strlen(pszSource));
         char *pszResult = (char *) CPLCalloc(1,nCharCount+1);
 
         if( !bHaveWarned2 )
         {
-            bHaveWarned2 = 1;
-            CPLError( CE_Warning, CPLE_AppDefined, 
-                      "Recode from UTF-8 to %s not supported, treated as UTF-8 to ISO8859-1.", 
+            bHaveWarned2 = true;
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Recode from UTF-8 to %s not supported, treated as UTF-8 to ISO8859-1.",
                       pszDstEncoding );
         }
-        
+
         utf8toa( pszSource, nCharCount, pszResult, nCharCount+1 );
-        
+
         return pszResult;
     }
 
@@ -238,12 +266,12 @@ char *CPLRecodeStub( const char *pszSource,
     {
         if( !bHaveWarned3 )
         {
-            bHaveWarned3 = 1;
-            CPLError( CE_Warning, CPLE_AppDefined, 
-                      "Recode from %s to %s not supported, no change applied.", 
+            bHaveWarned3 = true;
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Recode from %s to %s not supported, no change applied.",
                       pszSrcEncoding, pszDstEncoding );
         }
-        
+
         return CPLStrdup(pszSource);
     }
 }
@@ -253,29 +281,29 @@ char *CPLRecodeStub( const char *pszSource,
 /************************************************************************/
 
 /**
- * Convert wchar_t string to UTF-8. 
+ * Convert wchar_t string to UTF-8.
  *
  * Convert a wchar_t string into a multibyte utf-8 string.  The only
  * guaranteed supported source encoding is CPL_ENC_UCS2, and the only
  * guaranteed supported destination encodings are CPL_ENC_UTF8, CPL_ENC_ASCII
- * and CPL_ENC_ISO8859_1.  In some cases (ie. using iconv()) other encodings 
+ * and CPL_ENC_ISO8859_1.  In some cases (i.e. using iconv()) other encodings
  * may also be supported.
  *
  * Note that the wchar_t type varies in size on different systems. On
  * win32 it is normally 2 bytes, and on unix 4 bytes.
  *
- * If an error occurs an error may, or may not be posted with CPLError(). 
+ * If an error occurs an error may, or may not be posted with CPLError().
  *
  * @param pwszSource the source wchar_t string, terminated with a 0 wchar_t.
  * @param pszSrcEncoding the source encoding, typically CPL_ENC_UCS2.
  * @param pszDstEncoding the destination encoding, typically CPL_ENC_UTF8.
  *
- * @return a zero terminated multi-byte string which should be freed with 
- * CPLFree(), or NULL if an error occurs. 
+ * @return a zero terminated multi-byte string which should be freed with
+ * CPLFree(), or NULL if an error occurs.
  */
 
-char *CPLRecodeFromWCharStub( const wchar_t *pwszSource, 
-                              const char *pszSrcEncoding, 
+char *CPLRecodeFromWCharStub( const wchar_t *pwszSource,
+                              const char *pszSrcEncoding,
                               const char *pszDstEncoding )
 
 {
@@ -291,7 +319,7 @@ char *CPLRecodeFromWCharStub( const wchar_t *pwszSource,
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Stub recoding implementation does not support\n"
-                  "CPLRecodeFromWCharStub(...,%s,%s)", 
+                  "CPLRecodeFromWCharStub(...,%s,%s)",
                   pszSrcEncoding, pszDstEncoding );
         return NULL;
     }
@@ -325,7 +353,7 @@ char *CPLRecodeFromWCharStub( const wchar_t *pwszSource,
     nDstLen = utf8fromwc( pszResult, nDstBufSize, pwszSource, nSrcLen );
     if( nDstLen >= nDstBufSize )
     {
-        CPLAssert( FALSE ); // too small!
+        CPLAssert( false ); // too small!
         return NULL;
     }
 
@@ -335,11 +363,11 @@ char *CPLRecodeFromWCharStub( const wchar_t *pwszSource,
     if( strcmp(pszDstEncoding,CPL_ENC_UTF8) == 0 )
         return pszResult;
 
-    char *pszFinalResult = 
+    char *pszFinalResult =
         CPLRecodeStub( pszResult, CPL_ENC_UTF8, pszDstEncoding );
 
     CPLFree( pszResult );
-    
+
     return pszFinalResult;
 }
 
@@ -355,16 +383,16 @@ char *CPLRecodeFromWCharStub( const wchar_t *pwszSource,
  * are CPL_ENC_UTF8, CPL_ENC_ASCII and CPL_ENC_ISO8869_1 (LATIN1).  The only
  * guaranteed supported destination encoding is CPL_ENC_UCS2.  Other source
  * and destination encodings may be supported depending on the underlying
- * implementation. 
+ * implementation.
  *
  * Note that the wchar_t type varies in size on different systems. On
  * win32 it is normally 2 bytes, and on unix 4 bytes.
  *
- * If an error occurs an error may, or may not be posted with CPLError(). 
+ * If an error occurs an error may, or may not be posted with CPLError().
  *
  * @param pszSource input multi-byte character string.
  * @param pszSrcEncoding source encoding, typically CPL_ENC_UTF8.
- * @param pszDstEncoding destination encoding, typically CPL_ENC_UCS2. 
+ * @param pszDstEncoding destination encoding, typically CPL_ENC_UCS2.
  *
  * @return the zero terminated wchar_t string (to be freed with CPLFree()) or
  * NULL on error.
@@ -373,13 +401,13 @@ char *CPLRecodeFromWCharStub( const wchar_t *pwszSource,
  */
 
 wchar_t *CPLRecodeToWCharStub( const char *pszSource,
-                               const char *pszSrcEncoding, 
+                               const char *pszSrcEncoding,
                                const char *pszDstEncoding )
 
 {
     char *pszUTF8Source = (char *) pszSource;
 
-    if( strcmp(pszSrcEncoding,CPL_ENC_UTF8) != 0 
+    if( strcmp(pszSrcEncoding,CPL_ENC_UTF8) != 0
         && strcmp(pszSrcEncoding,CPL_ENC_ASCII) != 0 )
     {
         pszUTF8Source = CPLRecodeStub( pszSource, pszSrcEncoding, CPL_ENC_UTF8 );
@@ -393,20 +421,22 @@ wchar_t *CPLRecodeToWCharStub( const char *pszSource,
 /* -------------------------------------------------------------------- */
     if( strcmp(pszDstEncoding,"WCHAR_T") != 0
         && strcmp(pszDstEncoding,CPL_ENC_UCS2) != 0
-        && strcmp(pszDstEncoding,CPL_ENC_UCS4) != 0 
+        && strcmp(pszDstEncoding,CPL_ENC_UCS4) != 0
         && strcmp(pszDstEncoding,CPL_ENC_UTF16) != 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Stub recoding implementation does not support\n"
-                  "CPLRecodeToWCharStub(...,%s,%s)", 
+                  "CPLRecodeToWCharStub(...,%s,%s)",
                   pszSrcEncoding, pszDstEncoding );
+        if( pszUTF8Source != pszSource )
+            CPLFree( pszUTF8Source );
         return NULL;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Do the UTF-8 to UCS-2 recoding.                                 */
 /* -------------------------------------------------------------------- */
-    int nSrcLen = strlen(pszUTF8Source);
+    int nSrcLen = static_cast<int>(strlen(pszUTF8Source));
     wchar_t *pwszResult = (wchar_t *) CPLCalloc(sizeof(wchar_t),nSrcLen+1);
 
     utf8towc( pszUTF8Source, nSrcLen, pwszResult, nSrcLen+1 );
@@ -435,7 +465,7 @@ wchar_t *CPLRecodeToWCharStub( const char *pszSource,
 int CPLIsUTF8Stub(const char* pabyData, int nLen)
 {
     if (nLen < 0)
-        nLen = strlen(pabyData);
+        nLen = static_cast<int>(strlen(pabyData));
     return utf8test(pabyData, (unsigned)nLen) != 0;
 }
 
@@ -474,7 +504,7 @@ int CPLIsUTF8Stub(const char* pabyData, int nLen)
 #if ERRORS_TO_CP1252
 // Codes 0x80..0x9f from the Microsoft CP1252 character set, translated
 // to Unicode:
-static unsigned short cp1252[32] = {
+static const unsigned short cp1252[32] = {
   0x20ac, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
   0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x017d, 0x008f,
   0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
@@ -489,7 +519,7 @@ static unsigned short cp1252[32] = {
 /*
     Decode a single UTF-8 encoded character starting at \e p. The
     resulting Unicode value (in the range 0-0x10ffff) is returned,
-    and \e len is set the the number of bytes in the UTF-8 encoding
+    and \e len is set the number of bytes in the UTF-8 encoding
     (adding \e len to \e p will point at the next character).
 
     If \a p points at an illegal UTF-8 encoding, including one that
@@ -611,7 +641,7 @@ static unsigned utf8decode(const char* p, const char* end, int* len)
   This function is for moving a pointer that was jumped to the
   middle of a string, such as when doing a binary search for
   a position. You should use either this or utf8back() depending
-  on which direction your algorithim can handle the pointer
+  on which direction your algorithm can handle the pointer
   moving. Do not use this to scan strings, use utf8decode()
   instead.
 */
@@ -620,7 +650,6 @@ static unsigned utf8decode(const char* p, const char* end, int* len)
 static const char* utf8fwd(const char* p, const char* start, const char* end)
 {
   const char* a;
-  int len;
   // if we are not pointing at a continuation character, we are done:
   if ((*p&0xc0) != 0x80) return p;
   // search backwards for a 0xc0 starting the character:
@@ -629,6 +658,7 @@ static const char* utf8fwd(const char* p, const char* start, const char* end)
     if (!(a[0]&0x80)) return p;
     if ((a[0]&0x40)) break;
   }
+  int len = 0;
   utf8decode(a,end,&len);
   a += len;
   if (a > p) return a;
@@ -659,7 +689,6 @@ static const char* utf8fwd(const char* p, const char* start, const char* end)
 static const char* utf8back(const char* p, const char* start, const char* end)
 {
   const char* a;
-  int len;
   // if we are not pointing at a continuation character, we are done:
   if ((*p&0xc0) != 0x80) return p;
   // search backwards for a 0xc0 starting the character:
@@ -668,6 +697,7 @@ static const char* utf8back(const char* p, const char* start, const char* end)
     if (!(a[0]&0x80)) return p;
     if ((a[0]&0x40)) break;
   }
+  int len = 0;
   utf8decode(a,end,&len);
   if (a+len > p) return a;
   return p;
@@ -792,7 +822,8 @@ static unsigned utf8towc(const char* src, unsigned srclen,
     if (!(*p & 0x80)) { // ascii
       dst[count] = *p++;
     } else {
-      int len; unsigned ucs = utf8decode(p,e,&len);
+      int len = 0;
+      unsigned ucs = utf8decode(p,e,&len);
       p += len;
 #ifdef _WIN32
       if (ucs < 0x10000) {
@@ -814,11 +845,13 @@ static unsigned utf8towc(const char* src, unsigned srclen,
     if (!(*p & 0x80)) p++;
     else {
 #ifdef _WIN32
-      int len; unsigned ucs = utf8decode(p,e,&len);
+      int len = 0;
+      unsigned ucs = utf8decode(p,e,&len);
       p += len;
       if (ucs >= 0x10000) ++count;
 #else
-      int len; utf8decode(p,e,&len);
+      int len = 0;
+      utf8decode(p,e,&len);
       p += len;
 #endif
     }
@@ -857,21 +890,21 @@ static unsigned utf8toa(const char* src, unsigned srclen,
   const char* e = src+srclen;
   unsigned count = 0;
   if (dstlen) for (;;) {
-    unsigned char c;
     if (p >= e) {dst[count] = 0; return count;}
-    c = *(unsigned char*)p;
+    unsigned char c = *(unsigned char*)p;
     if (c < 0xC2) { // ascii or bad code
       dst[count] = c;
       p++;
     } else {
-      int len; unsigned ucs = utf8decode(p,e,&len);
+      int len = 0;
+      unsigned ucs = utf8decode(p,e,&len);
       p += len;
       if (ucs < 0x100) dst[count] = (char)ucs;
       else
       {
           if (!bHaveWarned4)
           {
-              bHaveWarned4 = TRUE;
+              bHaveWarned4 = true;
               CPLError(CE_Warning, CPLE_AppDefined,
                        "One or several characters couldn't be converted correctly from UTF-8 to ISO-8859-1.\n"
                        "This warning will not be emitted anymore.");
@@ -885,7 +918,7 @@ static unsigned utf8toa(const char* src, unsigned srclen,
   while (p < e) {
     if (!(*p & 0x80)) p++;
     else {
-      int len;
+      int len = 0;
       utf8decode(p,e,&len);
       p += len;
     }
@@ -909,7 +942,7 @@ static unsigned utf8toa(const char* src, unsigned srclen,
     needed.
 
     \a srclen is the number of words in \a src to convert. On Windows
-    this is not necessairly the number of characters, due to there
+    this is not necessarily the number of characters, due to there
     possibly being "surrogate pairs" in the UTF-16 encoding used.
     On Unix wchar_t is 32 bits and each location is a character.
 
@@ -997,7 +1030,7 @@ static unsigned utf8fromwc(char* dst, unsigned dstlen,
 /*                             utf8froma()                              */
 /************************************************************************/
 
-/* Convert an ISO-8859-1 (ie normal c-string) byte stream to UTF-8.
+/* Convert an ISO-8859-1 (i.e. normal c-string) byte stream to UTF-8.
 
     It is possible this should convert Microsoft's CP1252 to UTF-8
     instead. This would translate the codes in the range 0x80-0x9f
@@ -1023,9 +1056,8 @@ static unsigned utf8froma(char* dst, unsigned dstlen,
   const char* e = src+srclen;
   unsigned count = 0;
   if (dstlen) for (;;) {
-    unsigned char ucs;
     if (p >= e) {dst[count] = 0; return count;}
-    ucs = *(unsigned char*)p++;
+    unsigned char ucs = *(unsigned char*)p++;
     if (ucs < 0x80U) {
       dst[count++] = ucs;
       if (count >= dstlen) {dst[count-1] = 0; break;}
@@ -1053,8 +1085,8 @@ static unsigned utf8froma(char* dst, unsigned dstlen,
 /*                            CPLWin32Recode()                          */
 /************************************************************************/
 
-/* Convert an CODEPAGE (ie normal c-string) byte stream
-     to another CODEPAGE (ie normal c-string) byte stream.
+/* Convert an CODEPAGE (i.e. normal c-string) byte stream
+     to another CODEPAGE (i.e. normal c-string) byte stream.
 
     \a src is target c-string byte stream (including a null terminator).
     \a src_code_page is target c-string byte code page.
@@ -1114,7 +1146,7 @@ char* CPLWin32Recode( const char* src, unsigned src_code_page, unsigned dst_code
     {
         if (!bHaveWarned5)
         {
-            bHaveWarned5 = TRUE;
+            bHaveWarned5 = true;
             CPLError(CE_Warning, CPLE_AppDefined,
                     "One or several characters could not be translated from CP%d. "
                     "This warning will not be emitted anymore.", src_code_page);
@@ -1133,7 +1165,7 @@ char* CPLWin32Recode( const char* src, unsigned src_code_page, unsigned dst_code
 
     /* Compute the length in chars */
     BOOL bUsedDefaultChar = FALSE;
-    int len;
+    int len = 0;
     if ( dst_code_page == CP_UTF7 || dst_code_page == CP_UTF8 )
         len = WideCharToMultiByte( dst_code_page, 0, tbuf, -1, 0, 0, 0, NULL );
     else
@@ -1142,7 +1174,7 @@ char* CPLWin32Recode( const char* src, unsigned src_code_page, unsigned dst_code
     {
         if (!bHaveWarned6)
         {
-            bHaveWarned6 = TRUE;
+            bHaveWarned6 = true;
             CPLError(CE_Warning, CPLE_AppDefined,
                     "One or several characters could not be translated to CP%d. "
                     "This warning will not be emitted anymore.", dst_code_page);
@@ -1165,11 +1197,11 @@ char* CPLWin32Recode( const char* src, unsigned src_code_page, unsigned dst_code
 
 
 /*
-** For now we disable the rest which is locale() related.  We may need 
-** parts of it later. 
+** For now we disable the rest which is locale() related.  We may need
+** parts of it later.
 */
 
-#ifdef notdef 
+#ifdef notdef
 
 #ifdef _WIN32
 # include <windows.h>
@@ -1185,7 +1217,7 @@ char* CPLWin32Recode( const char* src, unsigned src_code_page, unsigned dst_code
     to a string containing the letters "utf" or "UTF" in it, or by
     deleting all $LC* and $LANG environment variables. In the future
     it is likely that all non-Asian Unix systems will return true,
-    due to the compatability of UTF-8 with ISO-8859-1.
+    due to the compatibility of UTF-8 with ISO-8859-1.
 */
 int utf8locale(void) {
   static int ret = 2;
@@ -1207,7 +1239,7 @@ int utf8locale(void) {
 
 /*! Convert the UTF-8 used by FLTK to the locale-specific encoding
     used for filenames (and sometimes used for data in files).
-    Unfortunatley due to stupid design you will have to do this as
+    Unfortunately due to stupid design you will have to do this as
     needed for filenames. This is a bug on both Unix and Windows.
 
     Up to \a dstlen bytes are written to \a dst, including a null
@@ -1251,11 +1283,11 @@ unsigned utf8tomb(const char* src, unsigned srclen,
     wchar_t lbuf[1024];
     wchar_t* buf = lbuf;
     unsigned length = utf8towc(src, srclen, buf, 1024);
-    int ret;
     if (length >= 1024) {
       buf = (wchar_t*)(malloc((length+1)*sizeof(wchar_t)));
       utf8towc(src, srclen, buf, length+1);
     }
+    int ret = 0;
     if (dstlen) {
       ret = wcstombs(dst, buf, dstlen);
       if (ret >= dstlen-1) ret = wcstombs(0,buf,0);
@@ -1318,9 +1350,8 @@ unsigned utf8frommb(char* dst, unsigned dstlen,
 #else
     wchar_t lbuf[1024];
     wchar_t* buf = lbuf;
-    int length;
     unsigned ret;
-    length = mbstowcs(buf, src, 1024);
+    int length = mbstowcs(buf, src, 1024);
     if (length >= 1024) {
       length = mbstowcs(0, src, 0)+1;
       buf = (wchar_t*)(malloc(length*sizeof(unsigned short)));
@@ -1352,7 +1383,7 @@ unsigned utf8frommb(char* dst, unsigned dstlen,
     - Returns 0 if there is any illegal UTF-8 sequences, using the
       same rules as utf8decode(). Note that some UCS values considered
       illegal by RFC 3629, such as 0xffff, are considered legal by this.
-    - Returns 1 if there are only single-byte characters (ie no bytes
+    - Returns 1 if there are only single-byte characters (i.e. no bytes
       have the high bit set). This is legal UTF-8, but also indicates
       plain ASCII. It also returns 1 if \a srclen is zero.
     - Returns 2 if there are only characters less than 0x800.
@@ -1374,7 +1405,8 @@ static int utf8test(const char* src, unsigned srclen) {
   const char* e = src+srclen;
   while (p < e) {
     if (*p & 0x80) {
-      int len; utf8decode(p,e,&len);
+      int len = 0;
+      utf8decode(p,e,&len);
       if (len < 2) return 0;
       if (len > ret) ret = len;
       p += len;
diff --git a/port/cpl_sha256.cpp b/port/cpl_sha256.cpp
new file mode 100644
index 0000000..dc61a3c
--- /dev/null
+++ b/port/cpl_sha256.cpp
@@ -0,0 +1,472 @@
+/* $Id: cpl_sha256.cpp 33724 2016-03-16 17:14:11Z goatbar $ */
+
+/* CPL_SHA256* functions derived from http://code.google.com/p/ulib/source/browse/trunk/src/base/sha256sum.c?r=39 */
+
+/* The MIT License
+
+   Copyright (C) 2011 Zilong Tan (tzlloch at gmail.com)
+   Copyright (C) 2015 Even Rouault <even.rouault at spatialys.com>
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   "Software"), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be
+   included in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+   BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+   ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+   SOFTWARE.
+*/
+
+/*
+ *  Original code is derived from the author:
+ *  Allan Saddi
+ */
+
+#include <string.h>
+#include "cpl_sha256.h"
+
+CPL_CVSID("$Id: cpl_sha256.cpp 33724 2016-03-16 17:14:11Z goatbar $");
+
+#define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+#define ROTR(x, n) (((x) >> (n)) | ((x) << (32 - (n))))
+
+#define Ch(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
+#define Maj(x, y, z) (((x) & ((y) | (z))) | ((y) & (z)))
+#define SIGMA0(x) (ROTR((x), 2) ^ ROTR((x), 13) ^ ROTR((x), 22))
+#define SIGMA1(x) (ROTR((x), 6) ^ ROTR((x), 11) ^ ROTR((x), 25))
+#define sigma0(x) (ROTR((x), 7) ^ ROTR((x), 18) ^ ((x) >> 3))
+#define sigma1(x) (ROTR((x), 17) ^ ROTR((x), 19) ^ ((x) >> 10))
+
+#define DO_ROUND() {                                                    \
+                t1 = h + SIGMA1(e) + Ch(e, f, g) + *(Kp++) + *(W++);    \
+                t2 = SIGMA0(a) + Maj(a, b, c);                          \
+                h = g;                                                  \
+                g = f;                                                  \
+                f = e;                                                  \
+                e = d + t1;                                             \
+                d = c;                                                  \
+                c = b;                                                  \
+                b = a;                                                  \
+                a = t1 + t2;                                            \
+        }
+
+static const GUInt32 K[64] = {
+        0x428a2f98U, 0x71374491U, 0xb5c0fbcfU, 0xe9b5dba5U,
+        0x3956c25bU, 0x59f111f1U, 0x923f82a4U, 0xab1c5ed5U,
+        0xd807aa98U, 0x12835b01U, 0x243185beU, 0x550c7dc3U,
+        0x72be5d74U, 0x80deb1feU, 0x9bdc06a7U, 0xc19bf174U,
+        0xe49b69c1U, 0xefbe4786U, 0x0fc19dc6U, 0x240ca1ccU,
+        0x2de92c6fU, 0x4a7484aaU, 0x5cb0a9dcU, 0x76f988daU,
+        0x983e5152U, 0xa831c66dU, 0xb00327c8U, 0xbf597fc7U,
+        0xc6e00bf3U, 0xd5a79147U, 0x06ca6351U, 0x14292967U,
+        0x27b70a85U, 0x2e1b2138U, 0x4d2c6dfcU, 0x53380d13U,
+        0x650a7354U, 0x766a0abbU, 0x81c2c92eU, 0x92722c85U,
+        0xa2bfe8a1U, 0xa81a664bU, 0xc24b8b70U, 0xc76c51a3U,
+        0xd192e819U, 0xd6990624U, 0xf40e3585U, 0x106aa070U,
+        0x19a4c116U, 0x1e376c08U, 0x2748774cU, 0x34b0bcb5U,
+        0x391c0cb3U, 0x4ed8aa4aU, 0x5b9cca4fU, 0x682e6ff3U,
+        0x748f82eeU, 0x78a5636fU, 0x84c87814U, 0x8cc70208U,
+        0x90befffaU, 0xa4506cebU, 0xbef9a3f7U, 0xc67178f2U
+};
+
+#ifdef WORDS_BIGENDIAN
+
+#define BYTESWAP(x) (x)
+#define BYTESWAP64(x) (x)
+
+#else                           /* WORDS_BIGENDIAN */
+
+#define BYTESWAP(x) ((ROTR((x), 8) & 0xff00ff00U) |     \
+                     (ROTL((x), 8) & 0x00ff00ffU))
+#define BYTESWAP64(x) _byteswap64(x)
+
+static inline GUInt64 _byteswap64(GUInt64 x)
+{
+        GUInt32 a = (GUInt32) (x >> 32);
+        GUInt32 b = (GUInt32) x;
+        return ((GUInt64) BYTESWAP(b) << 32) | (GUInt64) BYTESWAP(a);
+}
+
+#endif /* !(WORDS_BIGENDIAN) */
+
+static const GByte padding[64] = {
+        0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+void CPL_SHA256Init(CPL_SHA256Context * sc)
+{
+        sc->totalLength = 0;
+        sc->hash[0] = 0x6a09e667U;
+        sc->hash[1] = 0xbb67ae85U;
+        sc->hash[2] = 0x3c6ef372U;
+        sc->hash[3] = 0xa54ff53aU;
+        sc->hash[4] = 0x510e527fU;
+        sc->hash[5] = 0x9b05688cU;
+        sc->hash[6] = 0x1f83d9abU;
+        sc->hash[7] = 0x5be0cd19U;
+        sc->bufferLength = 0U;
+}
+
+static GUInt32 burnStack(int size)
+{
+        GByte buf[128];
+        GUInt32 ret = 0;
+
+        memset(buf, (GByte)(size & 0xff), sizeof(buf));
+        for( size_t i = 0; i < sizeof(buf); i++ )
+            ret += ret * buf[i];
+        size -= sizeof(buf);
+        if (size > 0)
+                ret += burnStack(size);
+        return ret;
+}
+
+static void CPL_SHA256Guts(CPL_SHA256Context * sc, const GUInt32 * cbuf)
+{
+        GUInt32 buf[64];
+        GUInt32 *W, *W2, *W7, *W15, *W16;
+        GUInt32 a, b, c, d, e, f, g, h;
+        GUInt32 t1, t2;
+        const GUInt32 *Kp;
+
+        W = buf;
+
+        for ( int i = 15; i >= 0; i-- ) {
+                *(W++) = BYTESWAP(*cbuf);
+                cbuf++;
+        }
+
+        W16 = &buf[0];
+        W15 = &buf[1];
+        W7 = &buf[9];
+        W2 = &buf[14];
+
+        for ( int i = 47; i >= 0; i-- ) {
+                *(W++) = sigma1(*W2) + *(W7++) + sigma0(*W15) + *(W16++);
+                W2++;
+                W15++;
+        }
+
+        a = sc->hash[0];
+        b = sc->hash[1];
+        c = sc->hash[2];
+        d = sc->hash[3];
+        e = sc->hash[4];
+        f = sc->hash[5];
+        g = sc->hash[6];
+        h = sc->hash[7];
+
+        Kp = K;
+        W = buf;
+
+#ifndef CPL_SHA256_UNROLL
+#define CPL_SHA256_UNROLL 1
+#endif                          /* !CPL_SHA256_UNROLL */
+
+#if CPL_SHA256_UNROLL == 1
+        for ( int i = 63; i >= 0; i-- )
+                DO_ROUND();
+#elif CPL_SHA256_UNROLL == 2
+        for ( int i = 31; i >= 0; i-- ) {
+                DO_ROUND();
+                DO_ROUND();
+        }
+#elif CPL_SHA256_UNROLL == 4
+        for ( int i = 15; i >= 0; i-- ) {
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+        }
+#elif CPL_SHA256_UNROLL == 8
+        for ( int i = 7; i >= 0; i-- ) {
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+        }
+#elif CPL_SHA256_UNROLL == 16
+        for ( int i = 3; i >= 0; i-- ) {
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+        }
+#elif CPL_SHA256_UNROLL == 32
+        for ( int i = 1; i >= 0; i-- ) {
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+                DO_ROUND();
+        }
+#elif CPL_SHA256_UNROLL == 64
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+        DO_ROUND();
+#else
+#error "CPL_SHA256_UNROLL must be 1, 2, 4, 8, 16, 32, or 64!"
+#endif
+
+        sc->hash[0] += a;
+        sc->hash[1] += b;
+        sc->hash[2] += c;
+        sc->hash[3] += d;
+        sc->hash[4] += e;
+        sc->hash[5] += f;
+        sc->hash[6] += g;
+        sc->hash[7] += h;
+}
+
+void CPL_SHA256Update(CPL_SHA256Context * sc, const void *data, size_t len)
+{
+        GUInt32 bufferBytesLeft;
+        GUInt32 bytesToCopy;
+        int needBurn = 0;
+
+        if (sc->bufferLength) {
+                bufferBytesLeft = 64U - sc->bufferLength;
+
+                bytesToCopy = bufferBytesLeft;
+                if (bytesToCopy > len)
+                        bytesToCopy = (GUInt32)len;
+
+                memcpy(&sc->buffer.bytes[sc->bufferLength], data, bytesToCopy);
+
+                sc->totalLength += bytesToCopy * 8U;
+
+                sc->bufferLength += bytesToCopy;
+                data = ((GByte *) data) + bytesToCopy;
+                len -= bytesToCopy;
+
+                if (sc->bufferLength == 64U) {
+                        CPL_SHA256Guts(sc, sc->buffer.words);
+                        needBurn = 1;
+                        sc->bufferLength = 0U;
+                }
+        }
+
+        while (len > 63U) {
+                sc->totalLength += 512U;
+
+                CPL_SHA256Guts(sc, (const GUInt32 *)data);
+                needBurn = 1;
+
+                data = ((GByte *) data) + 64U;
+                len -= 64U;
+        }
+
+        if (len) {
+                memcpy(&sc->buffer.bytes[sc->bufferLength], data, len);
+
+                sc->totalLength += (GUInt32)len * 8U;
+
+                sc->bufferLength += (GUInt32)len;
+        }
+
+        if (needBurn)
+        {
+                // Clean stack state of CPL_SHA256Guts()
+                // We add dummy side effects to avoid burnStack() to be optimized away (#6157)
+                static GUInt32 accumulator = 0;
+                accumulator += burnStack( static_cast<int>(
+                        sizeof(GUInt32[74]) + sizeof(GUInt32 *[6]) +
+                        sizeof(int) + ((len%2) ? sizeof(int) : 0)) );
+                if( accumulator == 0xDEADBEEF )
+                    fprintf(stderr, "%s", "");
+        }
+}
+
+void CPL_SHA256Final(CPL_SHA256Context * sc, GByte hash[CPL_SHA256_HASH_SIZE])
+{
+        GUInt32 bytesToPad;
+        GUInt64 lengthPad;
+
+        bytesToPad = 120U - sc->bufferLength;
+        if (bytesToPad > 64U)
+                bytesToPad -= 64U;
+
+        lengthPad = BYTESWAP64(sc->totalLength);
+
+        CPL_SHA256Update(sc, padding, bytesToPad);
+        CPL_SHA256Update(sc, &lengthPad, 8U);
+
+        if (hash) {
+            for ( int i = 0; i < CPL_SHA256_HASH_WORDS; i++ ) {
+                *((GUInt32 *) hash) = BYTESWAP(sc->hash[i]);
+                hash += 4;
+            }
+        }
+}
+
+void CPL_SHA256(const void *data, size_t len, GByte hash[CPL_SHA256_HASH_SIZE])
+{
+    CPL_SHA256Context sSHA256Ctxt;
+    CPL_SHA256Init(&sSHA256Ctxt);
+    CPL_SHA256Update(&sSHA256Ctxt, data, len);
+    CPL_SHA256Final(&sSHA256Ctxt, hash);
+    memset(&sSHA256Ctxt, 0, sizeof(sSHA256Ctxt));
+}
+
+#define CPL_HMAC_SHA256_BLOCKSIZE 64U
+
+/* See https://en.wikipedia.org/wiki/Hash-based_message_authentication_code#Implementation */
+void CPL_HMAC_SHA256(const void *pKey, size_t nKeyLen,
+                     const void *pabyMessage, size_t nMessageLen,
+                     GByte abyDigest[CPL_SHA256_HASH_SIZE])
+{
+    GByte abyPad[CPL_HMAC_SHA256_BLOCKSIZE];
+    memset(abyPad, 0, CPL_HMAC_SHA256_BLOCKSIZE);
+    if( nKeyLen > CPL_HMAC_SHA256_BLOCKSIZE )
+    {
+        CPL_SHA256(pKey, nKeyLen, abyPad);
+    }
+    else
+    {
+        memcpy(abyPad, pKey, nKeyLen);
+    }
+
+    /* Compute ipad */
+    for( size_t i = 0; i < CPL_HMAC_SHA256_BLOCKSIZE; i++ )
+        abyPad[i] = 0x36 ^ abyPad[i];
+
+    CPL_SHA256Context sSHA256Ctxt;
+    CPL_SHA256Init(&sSHA256Ctxt);
+    CPL_SHA256Update(&sSHA256Ctxt, abyPad, CPL_HMAC_SHA256_BLOCKSIZE);
+    CPL_SHA256Update(&sSHA256Ctxt, pabyMessage, nMessageLen);
+    CPL_SHA256Final(&sSHA256Ctxt, abyDigest);
+
+    /* Compute opad */
+    for( size_t i = 0; i < CPL_HMAC_SHA256_BLOCKSIZE; i++ )
+        abyPad[i] = (0x36 ^ 0x5C) ^ abyPad[i];
+
+    CPL_SHA256Init(&sSHA256Ctxt);
+    CPL_SHA256Update(&sSHA256Ctxt, abyPad, CPL_HMAC_SHA256_BLOCKSIZE);
+    CPL_SHA256Update(&sSHA256Ctxt, abyDigest, CPL_SHA256_HASH_SIZE);
+    CPL_SHA256Final(&sSHA256Ctxt, abyDigest);
+
+    memset(&sSHA256Ctxt, 0, sizeof(sSHA256Ctxt));
+    memset(abyPad, 0, CPL_HMAC_SHA256_BLOCKSIZE);
+}
diff --git a/port/cpl_sha256.h b/port/cpl_sha256.h
new file mode 100644
index 0000000..0868cf9
--- /dev/null
+++ b/port/cpl_sha256.h
@@ -0,0 +1,68 @@
+/* $Id: cpl_sha256.h 31777 2015-11-26 14:14:41Z rouault $ */
+
+/* The MIT License
+
+   Copyright (C) 2011 Zilong Tan (tzlloch at gmail.com)
+   Copyright (C) 2015 Even Rouault <even.rouault at spatialys.com>
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   "Software"), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be
+   included in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+   BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+   ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+   SOFTWARE.
+*/
+
+#ifndef CPL_SHA256_INCLUDED_H
+#define CPL_SHA256_INCLUDED_H
+
+#include "cpl_port.h"
+
+#define CPL_SHA256_HASH_SIZE 32     /* 256 bit */
+#define CPL_SHA256_HASH_WORDS 8
+
+#ifndef GUInt64
+#define GUInt64 GUIntBig
+#endif
+
+CPL_C_START
+
+struct _CPL_SHA256Context {
+        GUInt64 totalLength;
+        GUInt32 hash[CPL_SHA256_HASH_WORDS];
+        GUInt32 bufferLength;
+        union {
+                GUInt32 words[16];
+                GByte bytes[64];
+        } buffer;
+};
+typedef struct _CPL_SHA256Context CPL_SHA256Context;
+
+void CPL_DLL CPL_SHA256Init(CPL_SHA256Context * sc);
+
+void CPL_DLL CPL_SHA256Update(CPL_SHA256Context * sc, const void *data, size_t len);
+
+void CPL_DLL CPL_SHA256Final(CPL_SHA256Context * sc, GByte hash[CPL_SHA256_HASH_SIZE]);
+
+void CPL_DLL CPL_SHA256(const void *data, size_t len, GByte hash[CPL_SHA256_HASH_SIZE]);
+
+void CPL_DLL CPL_HMAC_SHA256(const void *pKey, size_t nKeyLen,
+                             const void *pabyMessage, size_t nMessageLen,
+                             GByte abyDigest[CPL_SHA256_HASH_SIZE]);
+
+CPL_C_END
+
+#endif  /* CPL_SHA256_INCLUDED_H */
diff --git a/port/cpl_spawn.cpp b/port/cpl_spawn.cpp
index 6b8f54c..b375ebb 100644
--- a/port/cpl_spawn.cpp
+++ b/port/cpl_spawn.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_spawn.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: cpl_spawn.cpp 33726 2016-03-16 18:48:51Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement CPLSystem().
@@ -14,32 +14,56 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
 #include "cpl_spawn.h"
 
-#include "cpl_error.h"
 #include "cpl_conv.h"
-#include "cpl_string.h"
+#include "cpl_error.h"
 #include "cpl_multiproc.h"
+#include "cpl_string.h"
+
+#if defined(WIN32)
+#include <windows.h>
+#else
+#include <cerrno>
+#include <csignal>
+#include <cstdio>
+#include <cstdlib>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#ifdef HAVE_POSIX_SPAWNP
+    #include <spawn.h>
+    #ifdef __APPLE__
+        #include <TargetConditionals.h>
+    #endif
+    #if defined(__APPLE__) && (!defined(TARGET_OS_IPHONE) || TARGET_OS_IPHONE==0)
+        #include <crt_externs.h>
+        #define environ (*_NSGetEnviron())
+    #else
+        extern char** environ;
+    #endif
+#endif
+#endif
 
-#define PIPE_BUFFER_SIZE    4096
+static const int PIPE_BUFFER_SIZE = 4096;
 
-#define IN_FOR_PARENT   0
-#define OUT_FOR_PARENT  1
+static const int IN_FOR_PARENT = 0;
+static const int OUT_FOR_PARENT = 1;
 
-CPL_CVSID("$Id: cpl_spawn.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: cpl_spawn.cpp 33726 2016-03-16 18:48:51Z goatbar $");
 
 static void FillFileFromPipe(CPL_FILE_HANDLE pipe_fd, VSILFILE* fout);
 
@@ -52,9 +76,10 @@ static void FillFileFromPipe(CPL_FILE_HANDLE pipe_fd, VSILFILE* fout);
 static void FillPipeFromFile(VSILFILE* fin, CPL_FILE_HANDLE pipe_fd)
 {
     char buf[PIPE_BUFFER_SIZE];
-    while(TRUE)
+    while(true)
     {
-        int nRead = (int)VSIFReadL(buf, 1, PIPE_BUFFER_SIZE, fin);
+        const int nRead
+            = static_cast<int>( VSIFReadL(buf, 1, PIPE_BUFFER_SIZE, fin) );
         if( nRead <= 0 )
             break;
         if (!CPLPipeWrite(pipe_fd, buf, nRead))
@@ -114,12 +139,14 @@ int CPLSpawn(const char * const papszArgv[], VSILFILE* fin, VSILFILE* fout,
     FillFileFromPipe(err_child, ferr);
     CPLSpawnAsyncCloseErrorFileHandle(sp);
 
-    VSIFCloseL(ferr);
+    CPL_IGNORE_RET_VAL(VSIFCloseL(ferr));
     vsi_l_offset nDataLength = 0;
     GByte* pData = VSIGetMemFileBuffer(osName.c_str(), &nDataLength, TRUE);
     if( nDataLength > 0 )
         pData[nDataLength-1] = '\0';
-    if( pData && strstr((const char*)pData, "An error occured while forking process") != NULL )
+    if( pData && strstr(
+            const_cast<const char *>( reinterpret_cast<char *>( pData ) ),
+            "An error occurred while forking process") != NULL )
         bDisplayErr = TRUE;
     if( pData && bDisplayErr )
         CPLError(CE_Failure, CPLE_AppDefined, "[%s error] %s", papszArgv[0], pData);
@@ -130,8 +157,6 @@ int CPLSpawn(const char * const papszArgv[], VSILFILE* fin, VSILFILE* fout,
 
 #if defined(WIN32)
 
-#include <windows.h>
-
 #if 0
 /************************************************************************/
 /*                            CPLSystem()                               */
@@ -148,8 +173,8 @@ int CPLSystem( const char* pszApplicationName, const char* pszCommandLine )
 
     char* pszDupedCommandLine = (pszCommandLine) ? CPLStrdup(pszCommandLine) : NULL;
 
-    if( !CreateProcess( pszApplicationName, 
-                        pszDupedCommandLine, 
+    if( !CreateProcess( pszApplicationName,
+                        pszDupedCommandLine,
                         NULL,
                         NULL,
                         FALSE,
@@ -167,7 +192,7 @@ int CPLSystem( const char* pszApplicationName, const char* pszCommandLine )
     {
         WaitForSingleObject( processInfo.hProcess, INFINITE );
 
-        DWORD exitCode;
+        DWORD exitCode = 0;
 
         // Get the exit code.
         int err = GetExitCodeProcess(processInfo.hProcess, &exitCode);
@@ -187,7 +212,7 @@ int CPLSystem( const char* pszApplicationName, const char* pszCommandLine )
 
     return nRet;
 }
-#endif
+#endif  // if 0
 
 /************************************************************************/
 /*                          CPLPipeRead()                               */
@@ -195,7 +220,7 @@ int CPLSystem( const char* pszApplicationName, const char* pszCommandLine )
 
 int CPLPipeRead(CPL_FILE_HANDLE fin, void* data, int length)
 {
-    GByte* pabyData = (GByte*)data;
+    GByte* pabyData = reinterpret_cast<GByte *>( data );
     int nRemain = length;
     while( nRemain > 0 )
     {
@@ -234,9 +259,9 @@ int CPLPipeWrite(CPL_FILE_HANDLE fout, const void* data, int length)
 static void FillFileFromPipe(CPL_FILE_HANDLE pipe_fd, VSILFILE* fout)
 {
     char buf[PIPE_BUFFER_SIZE];
-    while(TRUE)
+    while(true)
     {
-        DWORD nRead;
+        DWORD nRead = 0;
         if (!ReadFile( pipe_fd, buf, PIPE_BUFFER_SIZE, &nRead, NULL))
             break;
         if (nRead <= 0)
@@ -261,12 +286,12 @@ struct _CPLSpawnedProcess
 /*                            CPLSpawnAsync()                           */
 /************************************************************************/
 
-CPLSpawnedProcess* CPLSpawnAsync(int (*pfnMain)(CPL_FILE_HANDLE, CPL_FILE_HANDLE),
+CPLSpawnedProcess* CPLSpawnAsync(CPL_UNUSED int (*pfnMain)(CPL_FILE_HANDLE, CPL_FILE_HANDLE),
                                  const char * const papszArgv[],
                                  int bCreateInputPipe,
                                  int bCreateOutputPipe,
                                  int bCreateErrorPipe,
-                                 char** papszOptions)
+                                 CPL_UNUSED char** papszOptions)
 {
     HANDLE pipe_in[2] = {NULL, NULL};
     HANDLE pipe_out[2] = {NULL, NULL};
@@ -275,7 +300,6 @@ CPLSpawnedProcess* CPLSpawnAsync(int (*pfnMain)(CPL_FILE_HANDLE, CPL_FILE_HANDLE
     PROCESS_INFORMATION piProcInfo;
     STARTUPINFO siStartInfo;
     CPLString osCommandLine;
-    int i;
     CPLSpawnedProcess* p = NULL;
 
     if( papszArgv == NULL )
@@ -318,13 +342,13 @@ CPLSpawnedProcess* CPLSpawnAsync(int (*pfnMain)(CPL_FILE_HANDLE, CPL_FILE_HANDLE
 
     memset(&piProcInfo, 0, sizeof(PROCESS_INFORMATION));
     memset(&siStartInfo, 0, sizeof(STARTUPINFO));
-    siStartInfo.cb = sizeof(STARTUPINFO); 
+    siStartInfo.cb = sizeof(STARTUPINFO);
     siStartInfo.hStdInput = (bCreateInputPipe) ? pipe_in[IN_FOR_PARENT] : GetStdHandle(STD_INPUT_HANDLE);
     siStartInfo.hStdOutput = (bCreateOutputPipe) ? pipe_out[OUT_FOR_PARENT] : GetStdHandle(STD_OUTPUT_HANDLE);
     siStartInfo.hStdError = (bCreateErrorPipe) ? pipe_err[OUT_FOR_PARENT] : GetStdHandle(STD_ERROR_HANDLE);
     siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
 
-    for(i=0;papszArgv[i] != NULL;i++)
+    for( int i=0; papszArgv[i] != NULL; i++ )
     {
         if (i > 0)
             osCommandLine += " ";
@@ -340,14 +364,14 @@ CPLSpawnedProcess* CPLSpawnAsync(int (*pfnMain)(CPL_FILE_HANDLE, CPL_FILE_HANDLE
             osCommandLine += papszArgv[i];
     }
 
-    if (!CreateProcess(NULL, 
+    if (!CreateProcess(NULL,
                        (CHAR*)osCommandLine.c_str(),
-                       NULL,          // process security attributes 
-                       NULL,          // primary thread security attributes 
-                       TRUE,          // handles are inherited 
-                       CREATE_NO_WINDOW|NORMAL_PRIORITY_CLASS,             // creation flags 
-                       NULL,          // use parent's environment 
-                       NULL,          // use parent's current directory 
+                       NULL,          // process security attributes
+                       NULL,          // primary thread security attributes
+                       TRUE,          // handles are inherited
+                       CREATE_NO_WINDOW|NORMAL_PRIORITY_CLASS,             // creation flags
+                       NULL,          // use parent's environment
+                       NULL,          // use parent's current directory
                        &siStartInfo,
                        &piProcInfo))
     {
@@ -376,7 +400,7 @@ CPLSpawnedProcess* CPLSpawnAsync(int (*pfnMain)(CPL_FILE_HANDLE, CPL_FILE_HANDLE
 err_pipe:
     CPLError(CE_Failure, CPLE_AppDefined, "Could not create pipe");
 err:
-    for(i=0;i<2;i++)
+    for( int i=0; i < 2; i++ )
     {
         if (pipe_in[i] != NULL)
             CloseHandle(pipe_in[i]);
@@ -402,7 +426,7 @@ CPL_PID CPLSpawnAsyncGetChildProcessId(CPLSpawnedProcess* p)
 /*                        CPLSpawnAsyncFinish()                         */
 /************************************************************************/
 
-int CPLSpawnAsyncFinish(CPLSpawnedProcess* p, int bWait, int bKill)
+int CPLSpawnAsyncFinish(CPLSpawnedProcess* p, int bWait, CPL_UNUSED int bKill)
 {
     // Get the exit code.
     DWORD exitCode = -1;
@@ -459,27 +483,7 @@ void CPLSpawnAsyncCloseErrorFileHandle(CPLSpawnedProcess* p)
     p->ferr = NULL;
 }
 
-#else
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <errno.h>
-#include <signal.h>
-#ifdef HAVE_POSIX_SPAWNP
-    #include <spawn.h>
-    #ifdef __APPLE__
-        #include <TargetConditionals.h>
-    #endif
-    #if defined(__APPLE__) && (!defined(TARGET_OS_IPHONE) || TARGET_OS_IPHONE==0)
-        #include <crt_externs.h>
-        #define environ (*_NSGetEnviron())
-    #else
-        extern char** environ;
-    #endif
-#endif
+#else  // Not WIN32
 
 #if 0
 /************************************************************************/
@@ -497,7 +501,7 @@ void CPLSpawnAsyncCloseErrorFileHandle(CPLSpawnedProcess* p)
  *
  * @param pszApplicationName the lpApplicationName for Windows (might be NULL),
  *                           or ignored on other platforms.
- * @param pszCommandLine the command line, starting with the executable name 
+ * @param pszCommandLine the command line, starting with the executable name
  *
  * @return the exit code of the spawned process, or -1 in case of error.
  *
@@ -527,13 +531,13 @@ int CPLSystem( const char* pszApplicationName, const char* pszCommandLine )
  */
 int CPLPipeRead(CPL_FILE_HANDLE fin, void* data, int length)
 {
-    GByte* pabyData = (GByte*)data;
+    GByte* pabyData = reinterpret_cast<GByte*>( data );
     int nRemain = length;
     while( nRemain > 0 )
     {
-        while(TRUE)
+        while(true)
         {
-            int n = read(fin, pabyData, nRemain);
+            const int n = static_cast<int>(read(fin, pabyData, nRemain));
             if( n < 0 )
             {
                 if( errno == EINTR )
@@ -568,13 +572,13 @@ int CPLPipeRead(CPL_FILE_HANDLE fin, void* data, int length)
  */
 int CPLPipeWrite(CPL_FILE_HANDLE fout, const void* data, int length)
 {
-    const GByte* pabyData = (const GByte*)data;
+    const GByte* pabyData = reinterpret_cast<const GByte*>( data );
     int nRemain = length;
     while( nRemain > 0 )
     {
-        while(TRUE)
+        while(true)
         {
-            int n = write(fout, pabyData, nRemain);
+            const int n = static_cast<int>(write(fout, pabyData, nRemain));
             if( n < 0 )
             {
                 if( errno == EINTR )
@@ -597,12 +601,13 @@ int CPLPipeWrite(CPL_FILE_HANDLE fout, const void* data, int length)
 static void FillFileFromPipe(CPL_FILE_HANDLE pipe_fd, VSILFILE* fout)
 {
     char buf[PIPE_BUFFER_SIZE];
-    while(TRUE)
+    while(true)
     {
-        int nRead = read(pipe_fd, buf, PIPE_BUFFER_SIZE);
+        const int nRead = static_cast<int>(read(pipe_fd, buf, PIPE_BUFFER_SIZE));
         if (nRead <= 0)
             break;
-        int nWritten = (int)VSIFWriteL(buf, 1, nRead, fout);
+        const int nWritten = static_cast<int>(
+            VSIFWriteL(buf, 1, nRead, fout) );
         if (nWritten < nRead)
             break;
     }
@@ -655,20 +660,22 @@ CPLSpawnedProcess* CPLSpawnAsync(int (*pfnMain)(CPL_FILE_HANDLE, CPL_FILE_HANDLE
                                  int bCreateErrorPipe,
                                  CPL_UNUSED char** papszOptions)
 {
-    pid_t pid;
     int pipe_in[2] = { -1, -1 };
     int pipe_out[2] = { -1, -1 };
     int pipe_err[2] = { -1, -1 };
-    int i;
-    char** papszArgvDup = CSLDuplicate((char**)papszArgv);
-    int bDup2In = bCreateInputPipe,
-        bDup2Out = bCreateOutputPipe,
-        bDup2Err = bCreateErrorPipe;
+    bool bDup2In = CPL_TO_BOOL(bCreateInputPipe);
+    bool bDup2Out = CPL_TO_BOOL(bCreateOutputPipe);
+    bool bDup2Err = CPL_TO_BOOL(bCreateErrorPipe);
 
     if ((bCreateInputPipe && pipe(pipe_in)) ||
         (bCreateOutputPipe && pipe(pipe_out)) ||
         (bCreateErrorPipe && pipe(pipe_err)))
-        goto err_pipe;
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Could not create pipe");
+        return NULL;
+    }
+
+    char** papszArgvDup = CSLDuplicate( const_cast<char **>( papszArgv ) );
 
     /* If we don't do any file actions, posix_spawnp() might be implemented */
     /* efficiently as a vfork()/exec() pair (or if it is not available, we */
@@ -676,28 +683,28 @@ CPLSpawnedProcess* CPLSpawnAsync(int (*pfnMain)(CPL_FILE_HANDLE, CPL_FILE_HANDLE
     /* we pass the pipe handles as commandline arguments */
     if( papszArgv != NULL )
     {
-        for(i=0; papszArgvDup[i] != NULL; i++)
+        for( int i=0; papszArgvDup[i] != NULL; i++ )
         {
             if( bCreateInputPipe && strcmp(papszArgvDup[i], "{pipe_in}") == 0 )
             {
                 CPLFree(papszArgvDup[i]);
                 papszArgvDup[i] = CPLStrdup(CPLSPrintf("%d,%d",
                     pipe_in[IN_FOR_PARENT], pipe_in[OUT_FOR_PARENT]));
-                bDup2In = FALSE;
+                bDup2In = false;
             }
             else if( bCreateOutputPipe && strcmp(papszArgvDup[i], "{pipe_out}") == 0 )
             {
                 CPLFree(papszArgvDup[i]);
                 papszArgvDup[i] = CPLStrdup(CPLSPrintf("%d,%d",
                     pipe_out[OUT_FOR_PARENT], pipe_out[IN_FOR_PARENT]));
-                bDup2Out = FALSE;
+                bDup2Out = false;
             }
             else if( bCreateErrorPipe && strcmp(papszArgvDup[i], "{pipe_err}") == 0 )
             {
                 CPLFree(papszArgvDup[i]);
                 papszArgvDup[i] = CPLStrdup(CPLSPrintf("%d,%d",
                     pipe_err[OUT_FOR_PARENT], pipe_err[IN_FOR_PARENT]));
-                bDup2Err = FALSE;
+                bDup2Err = false;
             }
         }
     }
@@ -705,7 +712,7 @@ CPLSpawnedProcess* CPLSpawnAsync(int (*pfnMain)(CPL_FILE_HANDLE, CPL_FILE_HANDLE
 #ifdef HAVE_POSIX_SPAWNP
     if( papszArgv != NULL )
     {
-        int bHasActions = FALSE;
+        bool bHasActions = false;
         posix_spawn_file_actions_t actions;
 
         if( bDup2In )
@@ -713,7 +720,7 @@ CPLSpawnedProcess* CPLSpawnAsync(int (*pfnMain)(CPL_FILE_HANDLE, CPL_FILE_HANDLE
             if( !bHasActions ) posix_spawn_file_actions_init(&actions);
             posix_spawn_file_actions_adddup2(&actions, pipe_in[IN_FOR_PARENT], fileno(stdin));
             posix_spawn_file_actions_addclose(&actions, pipe_in[OUT_FOR_PARENT]);
-            bHasActions = TRUE;
+            bHasActions = true;
         }
 
         if( bDup2Out )
@@ -721,7 +728,7 @@ CPLSpawnedProcess* CPLSpawnAsync(int (*pfnMain)(CPL_FILE_HANDLE, CPL_FILE_HANDLE
             if( !bHasActions ) posix_spawn_file_actions_init(&actions);
             posix_spawn_file_actions_adddup2(&actions, pipe_out[OUT_FOR_PARENT], fileno(stdout));
             posix_spawn_file_actions_addclose(&actions, pipe_out[IN_FOR_PARENT]);
-            bHasActions = TRUE;
+            bHasActions = true;
         }
 
         if( bDup2Err )
@@ -729,13 +736,14 @@ CPLSpawnedProcess* CPLSpawnAsync(int (*pfnMain)(CPL_FILE_HANDLE, CPL_FILE_HANDLE
             if( !bHasActions ) posix_spawn_file_actions_init(&actions);
             posix_spawn_file_actions_adddup2(&actions, pipe_err[OUT_FOR_PARENT], fileno(stderr));
             posix_spawn_file_actions_addclose(&actions, pipe_err[IN_FOR_PARENT]);
-            bHasActions = TRUE;
+            bHasActions = true;
         }
 
+        pid_t pid;
         if( posix_spawnp(&pid, papszArgvDup[0],
                          bHasActions ? &actions : NULL,
                          NULL,
-                         (char* const*) papszArgvDup,
+                         reinterpret_cast<char* const*>( papszArgvDup ),
                          environ) != 0 )
         {
             if( bHasActions )
@@ -756,9 +764,10 @@ CPLSpawnedProcess* CPLSpawnAsync(int (*pfnMain)(CPL_FILE_HANDLE, CPL_FILE_HANDLE
 
         /* Ignore SIGPIPE */
     #ifdef SIGPIPE
-        signal (SIGPIPE, SIG_IGN);
+        std::signal( SIGPIPE, SIG_IGN );
     #endif
-        CPLSpawnedProcess* p = (CPLSpawnedProcess*)CPLMalloc(sizeof(CPLSpawnedProcess));
+        CPLSpawnedProcess *p = static_cast<CPLSpawnedProcess *>(
+            CPLMalloc( sizeof(CPLSpawnedProcess) ) );
         if( bHasActions )
             memcpy(&p->actions, &actions, sizeof(actions));
         p->bFreeActions = bHasActions;
@@ -770,9 +779,15 @@ CPLSpawnedProcess* CPLSpawnAsync(int (*pfnMain)(CPL_FILE_HANDLE, CPL_FILE_HANDLE
     }
 #endif // #ifdef HAVE_POSIX_SPAWNP
 
+    pid_t pid;
 #ifdef HAVE_VFORK
+    /* coverity[dead_error_line] */
     if( papszArgv != NULL && !bDup2In && !bDup2Out && !bDup2Err )
-        pid = vfork();
+    {
+        /* Workaround clang static analyzer warning about unsafe use of vfork */
+        pid_t (*p_vfork)(void) = vfork;
+        pid = p_vfork();
+    }
     else
 #endif
         pid = fork();
@@ -827,9 +842,10 @@ CPLSpawnedProcess* CPLSpawnAsync(int (*pfnMain)(CPL_FILE_HANDLE, CPL_FILE_HANDLE
 
         /* Ignore SIGPIPE */
 #ifdef SIGPIPE
-        signal (SIGPIPE, SIG_IGN);
+        std::signal( SIGPIPE, SIG_IGN );
 #endif
-        CPLSpawnedProcess* p = (CPLSpawnedProcess*)CPLMalloc(sizeof(CPLSpawnedProcess));
+        CPLSpawnedProcess* p = static_cast<CPLSpawnedProcess *>(
+            CPLMalloc( sizeof(CPLSpawnedProcess) ) );
 #ifdef HAVE_POSIX_SPAWNP
         p->bFreeActions = FALSE;
 #endif
@@ -845,11 +861,9 @@ CPLSpawnedProcess* CPLSpawnAsync(int (*pfnMain)(CPL_FILE_HANDLE, CPL_FILE_HANDLE
         goto err;
     }
 
-err_pipe:
-    CPLError(CE_Failure, CPLE_AppDefined, "Could not create pipe");
 err:
     CSLDestroy(papszArgvDup);
-    for(i=0;i<2;i++)
+    for( int i = 0; i < 2; i++ )
     {
         if (pipe_in[i] >= 0)
             close(pipe_in[i]);
@@ -896,7 +910,7 @@ int CPLSpawnAsyncFinish(CPLSpawnedProcess* p, int bWait, CPL_UNUSED int bKill)
         while(1)
         {
             status = -1;
-            int ret = waitpid (p->pid, &status, 0);
+            const int ret = waitpid (p->pid, &status, 0);
             if (ret < 0)
             {
                 if (errno != EINTR)
@@ -908,8 +922,7 @@ int CPLSpawnAsyncFinish(CPLSpawnedProcess* p, int bWait, CPL_UNUSED int bKill)
                 break;
         }
     }
-    else
-        bWait = FALSE;
+
     CPLSpawnAsyncCloseInputFileHandle(p);
     CPLSpawnAsyncCloseOutputFileHandle(p);
     CPLSpawnAsyncCloseErrorFileHandle(p);
diff --git a/port/cpl_spawn.h b/port/cpl_spawn.h
index 37036ba..5d50eac 100644
--- a/port/cpl_spawn.h
+++ b/port/cpl_spawn.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_spawn.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: cpl_spawn.h 31287 2015-11-01 18:29:27Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement CPLSystem().
@@ -14,16 +14,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
@@ -76,4 +76,3 @@ int CPL_DLL CPLPipeWrite(CPL_FILE_HANDLE fout, const void* data, int length);
 CPL_C_END
 
 #endif // CPL_SPAWN_H_INCLUDED
-
diff --git a/port/cpl_string.cpp b/port/cpl_string.cpp
index 6c04a8a..3a740ef 100644
--- a/port/cpl_string.cpp
+++ b/port/cpl_string.cpp
@@ -1,5 +1,6 @@
+
 /**********************************************************************
- * $Id: cpl_string.cpp 32962 2016-01-13 09:11:55Z rouault $
+ * $Id: cpl_string.cpp 33786 2016-03-25 22:27:50Z goatbar $
  *
  * Name:     cpl_string.cpp
  * Project:  CPL - Common Portability Library
@@ -16,16 +17,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
  *
@@ -33,31 +34,26 @@
  *   Completed audit of this module. All functions may be used without buffer
  *   overflows and stack corruptions with any kind of input data strings with
  *   except of CPLSPrintf() and CSLAppendPrintf() (see note below).
- * 
+ *
  * Security Audit 2003/03/28 warmerda:
- *   Completed security audit.  I believe that this module may be safely used 
+ *   Completed security audit.  I believe that this module may be safely used
  *   to parse tokenize arbitrary input strings, assemble arbitrary sets of
  *   names values into string lists, unescape and escape text even if provided
- *   by a potentially hostile source.   
+ *   by a potentially hostile source.
  *
- *   CPLSPrintf() and CSLAppendPrintf() may not be safely invoked on 
- *   arbitrary length inputs since it has a fixed size output buffer on system 
- *   without vsnprintf(). 
+ *   CPLSPrintf() and CSLAppendPrintf() may not be safely invoked on
+ *   arbitrary length inputs since it has a fixed size output buffer on system
+ *   without vsnprintf().
  *
  **********************************************************************/
 
 #undef WARN_STANDARD_PRINTF
 
+#include "cpl_multiproc.h"
 #include "cpl_string.h"
 #include "cpl_vsi.h"
-#include "cpl_multiproc.h"
 
-#if defined(WIN32CE)
-#  include <wce_errno.h>
-#  include <wce_string.h>
-#endif
-
-CPL_CVSID("$Id: cpl_string.cpp 32962 2016-01-13 09:11:55Z rouault $");
+CPL_CVSID("$Id: cpl_string.cpp 33786 2016-03-25 22:27:50Z goatbar $");
 
 /*=====================================================================
                     StringList manipulation functions.
@@ -70,30 +66,49 @@ CPL_CVSID("$Id: cpl_string.cpp 32962 2016-01-13 09:11:55Z rouault $");
  * StringList.
  * If the input StringList is NULL, then a new StringList is created.
  * Note that CSLAddString performance when building a list is in O(n^2)
- * which can cause noticable slow down when n > 10000.
+ * which can cause noticeable slow down when n > 10000.
  **********************************************************************/
 char **CSLAddString(char **papszStrList, const char *pszNewString)
 {
-    int nItems=0;
+    char** papszRet = CSLAddStringMayFail(papszStrList, pszNewString);
+    if( papszRet == NULL && pszNewString != NULL )
+        abort();
+    return papszRet;
+}
 
+char **CSLAddStringMayFail(char **papszStrList, const char *pszNewString)
+{
     if (pszNewString == NULL)
         return papszStrList;    /* Nothing to do!*/
 
+    char* pszDup = VSI_STRDUP_VERBOSE(pszNewString);
+    if( pszDup == NULL )
+        return NULL;
+
     /* Allocate room for the new string */
+    char** papszStrListNew = NULL;
+    int nItems = 0;
+
     if (papszStrList == NULL)
-        papszStrList = (char**) CPLCalloc(2,sizeof(char*));
+        papszStrListNew = static_cast<char**>(
+            VSI_CALLOC_VERBOSE( 2, sizeof(char*) ) );
     else
     {
         nItems = CSLCount(papszStrList);
-        papszStrList = (char**)CPLRealloc(papszStrList, 
-                                          (nItems+2)*sizeof(char*));
+        papszStrListNew = static_cast<char**>(
+            VSI_REALLOC_VERBOSE( papszStrList, (nItems+2)*sizeof(char*) ) );
+    }
+    if( papszStrListNew == NULL )
+    {
+        VSIFree(pszDup);
+        return NULL;
     }
 
     /* Copy the string in the list */
-    papszStrList[nItems] = CPLStrdup(pszNewString);
-    papszStrList[nItems+1] = NULL;
+    papszStrListNew[nItems] = pszDup;
+    papszStrListNew[nItems+1] = NULL;
 
-    return papszStrList;
+    return papszStrListNew;
 }
 
 /************************************************************************/
@@ -103,36 +118,35 @@ char **CSLAddString(char **papszStrList, const char *pszNewString)
 /**
  * Return number of items in a string list.
  *
- * Returns the number of items in a string list, not counting the 
+ * Returns the number of items in a string list, not counting the
  * terminating NULL.  Passing in NULL is safe, and will result in a count
- * of zero.  
+ * of zero.
  *
  * Lists are counted by iterating through them so long lists will
  * take more time than short lists.  Care should be taken to avoid using
  * CSLCount() as an end condition for loops as it will result in O(n^2)
- * behavior. 
+ * behavior.
  *
  * @param papszStrList the string list to count.
- * 
+ *
  * @return the number of entries.
  */
-int CSLCount(char **papszStrList)
+int CSLCount(const char * const *papszStrList)
 {
+    if (!papszStrList)
+        return 0;
+
     int nItems=0;
 
-    if (papszStrList)
+    while(*papszStrList != NULL)
     {
-        while(*papszStrList != NULL)
-        {
-            nItems++;
-            papszStrList++;
-        }
+        ++nItems;
+        ++papszStrList;
     }
 
     return nItems;
 }
 
-
 /************************************************************************/
 /*                            CSLGetField()                             */
 /*                                                                      */
@@ -142,15 +156,13 @@ int CSLCount(char **papszStrList)
 /*      necessarily last long.                                          */
 /************************************************************************/
 
-const char * CSLGetField( char ** papszStrList, int iField )
+const char *CSLGetField( char ** papszStrList, int iField )
 
 {
-    int         i;
-
     if( papszStrList == NULL || iField < 0 )
         return( "" );
 
-    for( i = 0; i < iField+1; i++ )
+    for( int i = 0; i < iField+1; i++ )
     {
         if( papszStrList[i] == NULL )
             return "";
@@ -165,27 +177,23 @@ const char * CSLGetField( char ** papszStrList, int iField )
 
 /**
  * Free string list.
- * 
+ *
  * Frees the passed string list (null terminated array of strings).
- * It is safe to pass NULL. 
+ * It is safe to pass NULL.
  *
  * @param papszStrList the list to free.
  */
 void CPL_STDCALL CSLDestroy(char **papszStrList)
 {
-    char **papszPtr;
+    if (!papszStrList)
+        return;
 
-    if (papszStrList)
+    for( char **papszPtr = papszStrList; *papszPtr != NULL; ++papszPtr )
     {
-        papszPtr = papszStrList;
-        while(*papszPtr != NULL)
-        {
-            CPLFree(*papszPtr);
-            papszPtr++;
-        }
-
-        CPLFree(papszStrList);
+        CPLFree(*papszPtr);
     }
+
+    CPLFree(papszStrList);
 }
 
 /************************************************************************/
@@ -199,30 +207,27 @@ void CPL_STDCALL CSLDestroy(char **papszStrList)
  * owned by the caller and should be freed with CSLDestroy().
  *
  * @param papszStrList the input string list.
- * 
+ *
  * @return newly allocated copy.
  */
 
 char **CSLDuplicate(char **papszStrList)
 {
-    char **papszNewList, **papszSrc, **papszDst;
-    int  nLines;
-
-    nLines = CSLCount(papszStrList);
+    const int nLines = CSLCount(papszStrList);
 
     if (nLines == 0)
         return NULL;
 
-    papszNewList = (char **)CPLMalloc((nLines+1)*sizeof(char*));
-    papszSrc = papszStrList;
-    papszDst = papszNewList;
+    char **papszSrc = papszStrList;
 
-    while(*papszSrc != NULL)
+    char **papszNewList = static_cast<char**>(
+        CPLMalloc( (nLines + 1) * sizeof(char*) ) );
+
+    char **papszDst = papszNewList;
+
+    for( ; *papszSrc != NULL; ++papszSrc, ++papszDst)
     {
         *papszDst = CPLStrdup(*papszSrc);
-
-        papszSrc++;
-        papszDst++;
     }
     *papszDst = NULL;
 
@@ -237,7 +242,7 @@ char **CSLDuplicate(char **papszStrList)
  * \brief Merge two lists.
  *
  * The two lists are merged, ensuring that if any keys appear in both
- * that the value from the second (papszOverride) list take precidence.
+ * that the value from the second (papszOverride) list take precedence.
  *
  * @param papszOrig the original list, being modified.
  * @param papszOverride the list of items being merged in.  This list
@@ -249,15 +254,13 @@ char **CSLDuplicate(char **papszStrList)
 char **CSLMerge( char **papszOrig, char **papszOverride )
 
 {
-    int i;
-
     if( papszOrig == NULL && papszOverride != NULL )
         return CSLDuplicate( papszOverride );
-    
+
     if( papszOverride == NULL )
         return papszOrig;
 
-    for( i = 0; papszOverride[i] != NULL; i++ )
+    for( int i = 0; papszOverride[i] != NULL; ++i )
     {
         char *pszKey = NULL;
         const char *pszValue = CPLParseNameValue( papszOverride[i], &pszKey );
@@ -279,7 +282,7 @@ char **CSLMerge( char **papszOrig, char **papszOverride )
  * The VSI*L API is used, so VSIFOpenL() supported objects that aren't
  * physical files can also be accessed.  Files are returned as a string list,
  * with one item in the string list per line.  End of line markers are
- * stripped (by CPLReadLineL()). 
+ * stripped (by CPLReadLineL()).
  *
  * If reading the file fails a CPLError() will be issued and NULL returned.
  *
@@ -287,68 +290,68 @@ char **CSLMerge( char **papszOrig, char **papszOverride )
  * @param nMaxLines maximum number of lines to read before stopping, or -1 for no limit.
  * @param nMaxCols  maximum number of characters in a line before stopping, or -1 for no limit.
  * @param papszOptions NULL-terminated array of options. Unused for now.
- * 
+ *
  * @return a string list with the files lines, now owned by caller. To be freed with CSLDestroy()
  *
  * @since GDAL 1.7.0
  */
 
-char **CSLLoad2(const char *pszFname, int nMaxLines, int nMaxCols, char** papszOptions)
+char **CSLLoad2( const char *pszFname, int nMaxLines, int nMaxCols,
+                 char** papszOptions )
 {
-    VSILFILE    *fp;
-    const char  *pszLine;
+    VSILFILE *fp = VSIFOpenL(pszFname, "rb");
+
+    if (!fp)
+    {
+        if( CSLFetchBoolean( papszOptions, "EMIT_ERROR_IF_CANNOT_OPEN_FILE",
+                             TRUE ) )
+        {
+            /* Unable to open file */
+            CPLError( CE_Failure, CPLE_OpenFailed,
+                    "CSLLoad2(\"%s\") failed: unable to open file.",
+                    pszFname );
+        }
+        return NULL;
+    }
+
     char        **papszStrList=NULL;
     int          nLines = 0;
     int          nAllocatedLines = 0;
 
-    fp = VSIFOpenL(pszFname, "rb");
-
-    if (fp)
+    CPLErrorReset();
+    while(!VSIFEofL(fp) && (nMaxLines == -1 || nLines < nMaxLines))
     {
-        CPLErrorReset();
-        while(!VSIFEofL(fp) && (nMaxLines == -1 || nLines < nMaxLines))
+        const char  *pszLine = CPLReadLine2L(fp, nMaxCols, papszOptions);
+        if (pszLine == NULL)
+            break;
+
+        if (nLines + 1 >= nAllocatedLines)
         {
-            if ( (pszLine = CPLReadLine2L(fp, nMaxCols, papszOptions)) != NULL )
+            nAllocatedLines = 16 + nAllocatedLines * 2;
+            char** papszStrListNew
+                = static_cast<char**>(
+                    VSIRealloc( papszStrList,
+                                nAllocatedLines * sizeof(char*) ) );
+            if (papszStrListNew == NULL)
             {
-                if (nLines + 1 >= nAllocatedLines)
-                {
-                    char** papszStrListNew;
-                    nAllocatedLines = 16 + nAllocatedLines * 2;
-                    papszStrListNew = (char**) VSIRealloc(papszStrList,
-                                                nAllocatedLines * sizeof(char*));
-                    if (papszStrListNew == NULL)
-                    {
-                        VSIFCloseL(fp);
-                        CPLReadLineL( NULL );
-                        CPLError( CE_Failure, CPLE_OutOfMemory,
-                             "CSLLoad2(\"%s\") failed: not enough memory to allocate lines.",
-                            pszFname );
-                        return papszStrList;
-                    }
-                    papszStrList = papszStrListNew;
-                }
-                papszStrList[nLines] = CPLStrdup(pszLine);
-                papszStrList[nLines + 1] = NULL;
-                nLines ++;
+                CPL_IGNORE_RET_VAL( VSIFCloseL(fp) );
+                CPLReadLineL( NULL );
+                CPLError( CE_Failure, CPLE_OutOfMemory,  "CSLLoad2(\"%s\") "
+                          "failed: not enough memory to allocate lines.",
+                          pszFname );
+                return papszStrList;
             }
-            else
-                break;
+            papszStrList = papszStrListNew;
         }
+        papszStrList[nLines] = CPLStrdup(pszLine);
+        papszStrList[nLines + 1] = NULL;
+        ++nLines;
+    }
 
-        VSIFCloseL(fp);
+    CPL_IGNORE_RET_VAL( VSIFCloseL(fp) );
 
-        CPLReadLineL( NULL );
-    }
-    else
-    {
-        if (CSLFetchBoolean(papszOptions, "EMIT_ERROR_IF_CANNOT_OPEN_FILE", TRUE))
-        {
-            /* Unable to open file */
-            CPLError( CE_Failure, CPLE_OpenFailed,
-                    "CSLLoad2(\"%s\") failed: unable to open file.",
-                    pszFname );
-        }
-    }
+    // Free the internal thread local line buffer.
+    CPLReadLineL( NULL );
 
     return papszStrList;
 }
@@ -363,15 +366,16 @@ char **CSLLoad2(const char *pszFname, int nMaxLines, int nMaxCols, char** papszO
  * The VSI*L API is used, so VSIFOpenL() supported objects that aren't
  * physical files can also be accessed.  Files are returned as a string list,
  * with one item in the string list per line.  End of line markers are
- * stripped (by CPLReadLineL()). 
+ * stripped (by CPLReadLineL()).
  *
  * If reading the file fails a CPLError() will be issued and NULL returned.
  *
  * @param pszFname the name of the file to read.
- * 
- * @return a string list with the files lines, now owned by caller. To be freed with CSLDestroy()
+ *
+ * @return a string list with the files lines, now owned by caller. To be freed
+ * with CSLDestroy()
  */
- 
+
 char **CSLLoad(const char *pszFname)
 {
     return CSLLoad2(pszFname, -1, -1, NULL);
@@ -380,43 +384,46 @@ char **CSLLoad(const char *pszFname)
 /**********************************************************************
  *                       CSLSave()
  *
- * Write a stringlist to a text file.
+ * Write a StringList to a text file.
  *
- * Returns the number of lines written, or 0 if the file could not 
+ * Returns the number of lines written, or 0 if the file could not
  * be written.
  **********************************************************************/
-int  CSLSave(char **papszStrList, const char *pszFname)
+int CSLSave(char **papszStrList, const char *pszFname)
 {
-    VSILFILE *fp;
-    int     nLines = 0;
+    if( papszStrList == NULL )
+        return 0;
 
-    if (papszStrList)
+    VSILFILE *fp = VSIFOpenL( pszFname, "wt" );
+    if (fp == NULL)
     {
-        if ((fp = VSIFOpenL(pszFname, "wt")) != NULL)
-        {
-            while(*papszStrList != NULL)
-            {
-                if( VSIFPrintfL( fp, "%s\n", *papszStrList ) < 1 )
-                {
-                    CPLError( CE_Failure, CPLE_FileIO,
-                    "CSLSave(\"%s\") failed: unable to write to output file.",
-                              pszFname );
-                    break;  /* A Problem happened... abort */
-                }
-
-                nLines++;
-                papszStrList++;
-            }
+        // Unable to open file.
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "CSLSave(\"%s\") failed: unable to open output file.",
+                  pszFname );
+        return 0;
+    }
 
-            VSIFCloseL(fp);
-        }
-        else
+    int nLines = 0;
+    while( *papszStrList != NULL )
+    {
+        if( VSIFPrintfL( fp, "%s\n", *papszStrList ) < 1 )
         {
-            /* Unable to open file */
-            CPLError( CE_Failure, CPLE_OpenFailed,
-                      "CSLSave(\"%s\") failed: unable to open output file.",
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "CSLSave(\"%s\") failed: unable to write to output file.",
                       pszFname );
+            break;  // A Problem happened... abort.
         }
+
+        ++nLines;
+        ++papszStrList;
+    }
+
+    if( VSIFCloseL(fp) != 0 )
+    {
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "CSLSave(\"%s\") failed: unable to write to output file.",
+                  pszFname );
     }
 
     return nLines;
@@ -430,124 +437,118 @@ int  CSLSave(char **papszStrList, const char *pszFname)
  *
  * Returns the number of lines printed.
  **********************************************************************/
-int  CSLPrint(char **papszStrList, FILE *fpOut)
+int CSLPrint( char **papszStrList, FILE *fpOut )
 {
-    int     nLines=0;
+    if (!papszStrList)
+        return 0;
 
     if (fpOut == NULL)
         fpOut = stdout;
 
-    if (papszStrList)
+    int nLines=0;
+
+    while(*papszStrList != NULL)
     {
-        while(*papszStrList != NULL)
-        {
-            VSIFPrintf(fpOut, "%s\n", *papszStrList);
-            nLines++;
-            papszStrList++;
-        }
+        if( VSIFPrintf(fpOut, "%s\n", *papszStrList) < 0 )
+            return nLines;
+        ++nLines;
+        ++papszStrList;
     }
 
     return nLines;
 }
 
-
 /**********************************************************************
  *                       CSLInsertStrings()
  *
- * Copies the contents of a StringList inside another StringList 
+ * Copies the contents of a StringList inside another StringList
  * before the specified line.
  *
  * nInsertAtLineNo is a 0-based line index before which the new strings
- * should be inserted.  If this value is -1 or is larger than the actual 
+ * should be inserted.  If this value is -1 or is larger than the actual
  * number of strings in the list then the strings are added at the end
  * of the source StringList.
  *
  * Returns the modified StringList.
  **********************************************************************/
-char **CSLInsertStrings(char **papszStrList, int nInsertAtLineNo, 
+char **CSLInsertStrings(char **papszStrList, int nInsertAtLineNo,
                         char **papszNewLines)
 {
-    int     i, nSrcLines, nDstLines, nToInsert;
-    char    **ppszSrc, **ppszDst;
+    if( papszNewLines == NULL )
+        return papszStrList;  // Nothing to do!
 
-    if (papszNewLines == NULL ||
-        ( nToInsert = CSLCount(papszNewLines) ) == 0)
-        return papszStrList;    /* Nothing to do!*/
+    const int nToInsert = CSLCount(papszNewLines);
+    if( nToInsert == 0 )
+        return papszStrList;  // Nothing to do!
 
-    nSrcLines = CSLCount(papszStrList);
-    nDstLines = nSrcLines + nToInsert;
+    const int nSrcLines = CSLCount(papszStrList);
+    const int nDstLines = nSrcLines + nToInsert;
 
     /* Allocate room for the new strings */
-    papszStrList = (char**)CPLRealloc(papszStrList, 
-                                      (nDstLines+1)*sizeof(char*));
+    papszStrList = reinterpret_cast<char**>(
+        CPLRealloc( papszStrList, (nDstLines+1) * sizeof(char*) ) );
 
     /* Make sure the array is NULL-terminated... it may not be if
      * papszStrList was NULL before Realloc()
      */
     papszStrList[nSrcLines] = NULL;
 
-    /* Make some room in the original list at the specified location 
+    /* Make some room in the original list at the specified location
      * Note that we also have to move the NULL pointer at the end of
      * the source StringList.
      */
     if (nInsertAtLineNo == -1 || nInsertAtLineNo > nSrcLines)
         nInsertAtLineNo = nSrcLines;
 
-    ppszSrc = papszStrList + nSrcLines;
-    ppszDst = papszStrList + nDstLines;
+    char **ppszSrc = papszStrList + nSrcLines;
+    char **ppszDst = papszStrList + nDstLines;
 
-    for (i=nSrcLines; i>=nInsertAtLineNo; i--)
+    for (int i=nSrcLines; i>=nInsertAtLineNo; --i)
     {
         *ppszDst = *ppszSrc;
-        ppszDst--;
-        ppszSrc--;
+        --ppszDst;
+        --ppszSrc;
     }
 
     /* Copy the strings to the list */
     ppszSrc = papszNewLines;
     ppszDst = papszStrList + nInsertAtLineNo;
 
-    for (; *ppszSrc != NULL; ppszSrc++, ppszDst++)
+    for (; *ppszSrc != NULL; ++ppszSrc, ++ppszDst)
     {
         *ppszDst = CPLStrdup(*ppszSrc);
     }
-    
+
     return papszStrList;
 }
 
 /**********************************************************************
  *                       CSLInsertString()
  *
- * Insert a string at a given line number inside a StringList 
+ * Insert a string at a given line number inside a StringList
  *
  * nInsertAtLineNo is a 0-based line index before which the new string
- * should be inserted.  If this value is -1 or is larger than the actual 
+ * should be inserted.  If this value is -1 or is larger than the actual
  * number of strings in the list then the string is added at the end
  * of the source StringList.
  *
  * Returns the modified StringList.
  **********************************************************************/
-char **CSLInsertString(char **papszStrList, int nInsertAtLineNo, 
+char **CSLInsertString(char **papszStrList, int nInsertAtLineNo,
                        const char *pszNewLine)
 {
-    char *apszList[2];
-
-    /* Create a temporary StringList and call CSLInsertStrings()
-     */
-    apszList[0] = (char *) pszNewLine;
-    apszList[1] = NULL;
+    char *apszList[2] = {const_cast<char *>(pszNewLine), NULL};
 
     return CSLInsertStrings(papszStrList, nInsertAtLineNo, apszList);
 }
 
-
 /**********************************************************************
  *                       CSLRemoveStrings()
  *
- * Remove strings inside a StringList 
+ * Remove strings inside a StringList
  *
- * nFirstLineToDelete is the 0-based line index of the first line to 
- * remove. If this value is -1 or is larger than the actual 
+ * nFirstLineToDelete is the 0-based line index of the first line to
+ * remove. If this value is -1 or is larger than the actual
  * number of strings in list then the nNumToRemove last strings are
  * removed.
  *
@@ -560,11 +561,7 @@ char **CSLInsertString(char **papszStrList, int nInsertAtLineNo,
 char **CSLRemoveStrings(char **papszStrList, int nFirstLineToDelete,
                         int nNumToRemove, char ***ppapszRetStrings)
 {
-    int     i, nSrcLines, nDstLines;
-    char    **ppszSrc, **ppszDst;
-
-    nSrcLines = CSLCount(papszStrList);
-    nDstLines = nSrcLines - nNumToRemove;
+    const int nSrcLines = CSLCount(papszStrList);
 
     if (nNumToRemove < 1 || nSrcLines == 0)
         return papszStrList;    /* Nothing to do!*/
@@ -572,24 +569,24 @@ char **CSLRemoveStrings(char **papszStrList, int nFirstLineToDelete,
     /* If operation will result in an empty StringList then don't waste
      * time here!
      */
+    const int nDstLines = nSrcLines - nNumToRemove;
     if (nDstLines < 1)
     {
         CSLDestroy(papszStrList);
         return NULL;
     }
 
-    
     /* Remove lines from the source StringList...
      * Either free() each line or store them to a new StringList depending on
      * the caller's choice.
      */
-    ppszDst = papszStrList + nFirstLineToDelete;
+    char **ppszDst = papszStrList + nFirstLineToDelete;
 
     if (ppapszRetStrings == NULL)
     {
         /* free() all the strings that will be removed.
          */
-        for (i=0; i < nNumToRemove; i++)
+        for (int i=0; i < nNumToRemove; ++i)
         {
             CPLFree(*ppszDst);
             *ppszDst = NULL;
@@ -599,31 +596,31 @@ char **CSLRemoveStrings(char **papszStrList, int nFirstLineToDelete,
     {
         /* Store the strings to remove in a new StringList
          */
-        *ppapszRetStrings = (char **)CPLCalloc(nNumToRemove+1, sizeof(char*));
+        *ppapszRetStrings = static_cast<char **>(
+            CPLCalloc( nNumToRemove+1, sizeof(char*) ) );
 
-        for (i=0; i < nNumToRemove; i++)
+        for (int i=0; i < nNumToRemove; ++i)
         {
             (*ppapszRetStrings)[i] = *ppszDst;
             *ppszDst = NULL;
-            ppszDst++;
+            ++ppszDst;
         }
     }
 
-
     /* Shift down all the lines that follow the lines to remove.
      */
     if (nFirstLineToDelete == -1 || nFirstLineToDelete > nSrcLines)
         nFirstLineToDelete = nDstLines;
 
-    ppszSrc = papszStrList + nFirstLineToDelete + nNumToRemove;
+    char **ppszSrc = papszStrList + nFirstLineToDelete + nNumToRemove;
     ppszDst = papszStrList + nFirstLineToDelete;
 
-    for ( ; *ppszSrc != NULL; ppszSrc++, ppszDst++)
+    for ( ; *ppszSrc != NULL; ++ppszSrc, ++ppszDst)
     {
         *ppszDst = *ppszSrc;
     }
     /* Move the NULL pointer at the end of the StringList     */
-    *ppszDst = *ppszSrc; 
+    *ppszDst = *ppszSrc;
 
     /* At this point, we could realloc() papszStrList to a smaller size, but
      * since this array will likely grow again in further operations on the
@@ -640,25 +637,23 @@ char **CSLRemoveStrings(char **papszStrList, int nFirstLineToDelete,
 /**
  * Find a string within a string list (case insensitive).
  *
- * Returns the index of the entry in the string list that contains the 
+ * Returns the index of the entry in the string list that contains the
  * target string.  The string in the string list must be a full match for
- * the target, but the search is case insensitive. 
- * 
+ * the target, but the search is case insensitive.
+ *
  * @param papszList the string list to be searched.
- * @param pszTarget the string to be searched for. 
- * 
+ * @param pszTarget the string to be searched for.
+ *
  * @return the index of the string within the list or -1 on failure.
  */
 
 int CSLFindString( char ** papszList, const char * pszTarget )
 
 {
-    int         i;
-
     if( papszList == NULL )
         return -1;
 
-    for( i = 0; papszList[i] != NULL; i++ )
+    for( int i = 0; papszList[i] != NULL; ++i )
     {
         if( EQUAL(papszList[i],pszTarget) )
             return i;
@@ -674,13 +669,13 @@ int CSLFindString( char ** papszList, const char * pszTarget )
 /**
  * Find a string within a string list(case sensitive)
  *
- * Returns the index of the entry in the string list that contains the 
+ * Returns the index of the entry in the string list that contains the
  * target string.  The string in the string list must be a full match for
- * the target. 
- * 
+ * the target.
+ *
  * @param papszList the string list to be searched.
- * @param pszTarget the string to be searched for. 
- * 
+ * @param pszTarget the string to be searched for.
+ *
  * @return the index of the string within the list or -1 on failure.
  *
  * @since GDAL 2.0
@@ -689,12 +684,10 @@ int CSLFindString( char ** papszList, const char * pszTarget )
 int CSLFindStringCaseSensitive( char ** papszList, const char * pszTarget )
 
 {
-    int         i;
-
     if( papszList == NULL )
         return -1;
 
-    for( i = 0; papszList[i] != NULL; i++ )
+    for( int i = 0; papszList[i] != NULL; ++i )
     {
         if( strcmp(papszList[i],pszTarget) == 0 )
             return i;
@@ -710,39 +703,37 @@ int CSLFindStringCaseSensitive( char ** papszList, const char * pszTarget )
 /**
  * Find a substring within a string list.
  *
- * Returns the index of the entry in the string list that contains the 
- * target string as a substring.  The search is case sensitive (unlike 
- * CSLFindString()). 
- * 
+ * Returns the index of the entry in the string list that contains the
+ * target string as a substring.  The search is case sensitive (unlike
+ * CSLFindString()).
+ *
  * @param papszHaystack the string list to be searched.
- * @param pszNeedle the substring to be searched for. 
- * 
+ * @param pszNeedle the substring to be searched for.
+ *
  * @return the index of the string within the list or -1 on failure.
  */
 
 int CSLPartialFindString( char **papszHaystack, const char * pszNeedle )
 {
-    int i;
     if (papszHaystack == NULL || pszNeedle == NULL)
         return -1;
 
-    for (i = 0; papszHaystack[i] != NULL; i++) 
+    for (int i = 0; papszHaystack[i] != NULL; ++i)
     {
-        if (strstr(papszHaystack[i],pszNeedle))
+        if (strstr(papszHaystack[i], pszNeedle))
             return i;
     }
 
     return -1;
 }
 
-
 /**********************************************************************
  *                       CSLTokenizeString()
  *
  * Tokenizes a string and returns a StringList with one string for
  * each token.
  **********************************************************************/
-char    **CSLTokenizeString( const char *pszString )
+char **CSLTokenizeString( const char *pszString )
 {
     return CSLTokenizeString2( pszString, " ", CSLT_HONOURSTRINGS );
 }
@@ -756,9 +747,8 @@ char    **CSLTokenizeString( const char *pszString )
 char ** CSLTokenizeStringComplex( const char * pszString,
                                   const char * pszDelimiters,
                                   int bHonourStrings, int bAllowEmptyTokens )
-
 {
-    int         nFlags = 0;
+    int nFlags = 0;
 
     if( bHonourStrings )
         nFlags |= CSLT_HONOURSTRINGS;
@@ -773,51 +763,49 @@ char ** CSLTokenizeStringComplex( const char * pszString,
 /************************************************************************/
 
 /**
- * Tokenize a string. 
+ * Tokenize a string.
  *
  * This function will split a string into tokens based on specified'
- * delimeter(s) with a variety of options.  The returned result is a
+ * delimiter(s) with a variety of options.  The returned result is a
  * string list that should be freed with CSLDestroy() when no longer
  * needed.
- * 
+ *
  * The available parsing options are:
- * 
- * - CSLT_ALLOWEMPTYTOKENS: allow the return of empty tokens when two 
- * delimiters in a row occur with no other text between them.  If not set, 
+ *
+ * - CSLT_ALLOWEMPTYTOKENS: allow the return of empty tokens when two
+ * delimiters in a row occur with no other text between them.  If not set,
  * empty tokens will be discarded;
  * - CSLT_STRIPLEADSPACES: strip leading space characters from the token (as
  * reported by isspace());
  * - CSLT_STRIPENDSPACES: strip ending space characters from the token (as
  * reported by isspace());
- * - CSLT_HONOURSTRINGS: double quotes can be used to hold values that should 
- * not be broken into multiple tokens; 
+ * - CSLT_HONOURSTRINGS: double quotes can be used to hold values that should
+ * not be broken into multiple tokens;
  * - CSLT_PRESERVEQUOTES: string quotes are carried into the tokens when this
  * is set, otherwise they are removed;
- * - CSLT_PRESERVEESCAPES: if set backslash escapes (for backslash itself, 
+ * - CSLT_PRESERVEESCAPES: if set backslash escapes (for backslash itself,
  * and for literal double quotes) will be preserved in the tokens, otherwise
  * the backslashes will be removed in processing.
  *
  * \b Example:
- * 
- * Parse a string into tokens based on various white space (space, newline, 
- * tab) and then print out results and cleanup.  Quotes may be used to hold 
+ *
+ * Parse a string into tokens based on various white space (space, newline,
+ * tab) and then print out results and cleanup.  Quotes may be used to hold
  * white space in tokens.
 
 \code
-    char **papszTokens;
-    int i;
-
-    papszTokens = 
-        CSLTokenizeString2( pszCommand, " \t\n", 
+    char **papszTokens =
+        CSLTokenizeString2( pszCommand, " \t\n",
                             CSLT_HONOURSTRINGS | CSLT_ALLOWEMPTYTOKENS );
 
-    for( i = 0; papszTokens != NULL && papszTokens[i] != NULL; i++ )
+    for( int i = 0; papszTokens != NULL && papszTokens[i] != NULL; ++i )
         printf( "arg %d: '%s'", papszTokens[i] );
+
     CSLDestroy( papszTokens );
 \endcode
 
  * @param pszString the string to be split into tokens.
- * @param pszDelimiters one or more characters to be used as token delimeters.
+ * @param pszDelimiters one or more characters to be used as token delimiters.
  * @param nCSLTFlags an ORing of one or more of the CSLT_ flag values.
  *
  * @return a string list of tokens owned by the caller.
@@ -826,39 +814,46 @@ char ** CSLTokenizeStringComplex( const char * pszString,
 char ** CSLTokenizeString2( const char * pszString,
                             const char * pszDelimiters,
                             int nCSLTFlags )
-
 {
     if( pszString == NULL )
-        return (char **) CPLCalloc(sizeof(char *),1);
+        return static_cast<char **>(
+            CPLCalloc(sizeof(char *),1));
+
     CPLStringList oRetList;
-    char        *pszToken;
-    int         nTokenMax, nTokenLen;
-    int         bHonourStrings = (nCSLTFlags & CSLT_HONOURSTRINGS);
-    int         bAllowEmptyTokens = (nCSLTFlags & CSLT_ALLOWEMPTYTOKENS);
-    int         bStripLeadSpaces = (nCSLTFlags & CSLT_STRIPLEADSPACES);
-    int         bStripEndSpaces = (nCSLTFlags & CSLT_STRIPENDSPACES);
-
-    pszToken = (char *) CPLCalloc(10,1);
-    nTokenMax = 10;
-    
-    while( pszString != NULL && *pszString != '\0' )
+    const bool bHonourStrings = (nCSLTFlags & CSLT_HONOURSTRINGS) != 0;
+    const bool bAllowEmptyTokens = (nCSLTFlags & CSLT_ALLOWEMPTYTOKENS) != 0;
+    const bool bStripLeadSpaces = (nCSLTFlags & CSLT_STRIPLEADSPACES) != 0;
+    const bool bStripEndSpaces = (nCSLTFlags & CSLT_STRIPENDSPACES) != 0;
+
+    char *pszToken = reinterpret_cast<char *>( CPLCalloc(10,1) );
+    int nTokenMax = 10;
+
+    while( *pszString != '\0' )
     {
-        int     bInString = FALSE;
-        int     bStartString = TRUE;
+        bool bInString = false;
+        bool bStartString = true;
+        int nTokenLen = 0;
 
-        nTokenLen = 0;
-        
-        /* Try to find the next delimeter, marking end of token */
-        for( ; *pszString != '\0'; pszString++ )
+        /* Try to find the next delimiter, marking end of token */
+        for( ; *pszString != '\0'; ++pszString )
         {
+            /*
+             * Extend token buffer if we are running close to its end.
+             */
+            if( nTokenLen >= nTokenMax-3 )
+            {
+                nTokenMax = nTokenMax * 2 + 10;
+                pszToken = static_cast<char *>(
+                    CPLRealloc( pszToken, nTokenMax ));
+            }
 
-            /* End if this is a delimeter skip it and break. */
+            /* End if this is a delimiter skip it and break. */
             if( !bInString && strchr(pszDelimiters, *pszString) != NULL )
             {
-                pszString++;
+                ++pszString;
                 break;
             }
-            
+
             /* If this is a quote, and we are honouring constant
                strings, then process the constant strings, with out delim
                but don't copy over the quotes */
@@ -867,19 +862,11 @@ char ** CSLTokenizeString2( const char * pszString,
                 if( nCSLTFlags & CSLT_PRESERVEQUOTES )
                 {
                     pszToken[nTokenLen] = *pszString;
-                    nTokenLen++;
+                    ++nTokenLen;
                 }
 
-                if( bInString )
-                {
-                    bInString = FALSE;
-                    continue;
-                }
-                else
-                {
-                    bInString = TRUE;
-                    continue;
-                }
+                bInString = !bInString;
+                continue;
             }
 
             /*
@@ -894,10 +881,10 @@ char ** CSLTokenizeString2( const char * pszString,
                     if( nCSLTFlags & CSLT_PRESERVEESCAPES )
                     {
                         pszToken[nTokenLen] = *pszString;
-                        nTokenLen++;
+                        ++nTokenLen;
                     }
 
-                    pszString++;
+                    ++pszString;
                 }
             }
 
@@ -905,22 +892,14 @@ char ** CSLTokenizeString2( const char * pszString,
              * Strip spaces at the token start if requested.
              */
             if ( !bInString && bStripLeadSpaces
-                 && bStartString && isspace((unsigned char)*pszString) )
+                 && bStartString
+                 && isspace(static_cast<unsigned char>( *pszString )) )
                 continue;
 
-            bStartString = FALSE;
-
-            /*
-             * Extend token buffer if we are running close to its end.
-             */
-            if( nTokenLen >= nTokenMax-3 )
-            {
-                nTokenMax = nTokenMax * 2 + 10;
-                pszToken = (char *) CPLRealloc( pszToken, nTokenMax );
-            }
+            bStartString = false;
 
             pszToken[nTokenLen] = *pszString;
-            nTokenLen++;
+            ++nTokenLen;
         }
 
         /*
@@ -928,7 +907,9 @@ char ** CSLTokenizeString2( const char * pszString,
          */
         if ( !bInString && bStripEndSpaces )
         {
-            while ( nTokenLen && isspace((unsigned char)pszToken[nTokenLen - 1]) )
+            while ( nTokenLen
+                    && isspace(
+                        static_cast<unsigned char>( pszToken[nTokenLen - 1]) ) )
                 nTokenLen--;
         }
 
@@ -945,7 +926,7 @@ char ** CSLTokenizeString2( const char * pszString,
      * If the last token was empty, then we need to capture
      * it now, as the loop would skip it.
      */
-    if( *pszString == '\0' && bAllowEmptyTokens && oRetList.Count() > 0 
+    if( *pszString == '\0' && bAllowEmptyTokens && oRetList.Count() > 0
         && strchr(pszDelimiters,*(pszString-1)) != NULL )
     {
         oRetList.AddString( "" );
@@ -955,9 +936,10 @@ char ** CSLTokenizeString2( const char * pszString,
 
     if( oRetList.List() == NULL )
     {
-        // we prefer to return empty lists as a pointer to 
+        // we prefer to return empty lists as a pointer to
         // a null pointer since some client code might depend on this.
-        oRetList.Assign( (char**) CPLCalloc(sizeof(char*),1) );
+        oRetList.Assign(
+            reinterpret_cast<char **>( CPLCalloc(sizeof(char*),1) ) );
     }
 
     return oRetList.StealList();
@@ -969,14 +951,14 @@ char ** CSLTokenizeString2( const char * pszString,
  * My own version of CPLSPrintf() that works with 10 static buffer.
  *
  * It returns a ref. to a static buffer that should not be freed and
- * is valid only until the next call to CPLSPrintf(). 
+ * is valid only until the next call to CPLSPrintf().
  *
- * NOTE: This function should move to cpl_conv.cpp. 
+ * NOTE: This function should move to cpl_conv.cpp.
  **********************************************************************/
 /* For now, assume that a 8000 chars buffer will be enough.
  */
-#define CPLSPrintf_BUF_SIZE 8000
-#define CPLSPrintf_BUF_Count 10
+static const int CPLSPrintf_BUF_SIZE = 8000;
+static const int CPLSPrintf_BUF_Count = 10;
 
 const char *CPLSPrintf(const char *fmt, ...)
 {
@@ -985,12 +967,12 @@ const char *CPLSPrintf(const char *fmt, ...)
 /* -------------------------------------------------------------------- */
 /*      Get the thread local buffer ring data.                          */
 /* -------------------------------------------------------------------- */
-    char *pachBufRingInfo = (char *) CPLGetTLS( CTLS_CPLSPRINTF );
+    char *pachBufRingInfo = static_cast<char *>( CPLGetTLS( CTLS_CPLSPRINTF ) );
 
     if( pachBufRingInfo == NULL )
     {
-        pachBufRingInfo = (char *) 
-            CPLCalloc(1,sizeof(int)+CPLSPrintf_BUF_Count*CPLSPrintf_BUF_SIZE);
+        pachBufRingInfo = static_cast<char *>(
+            CPLCalloc(1,sizeof(int)+CPLSPrintf_BUF_Count*CPLSPrintf_BUF_SIZE));
         CPLSetTLS( CTLS_CPLSPRINTF, pachBufRingInfo, TRUE );
     }
 
@@ -998,8 +980,8 @@ const char *CPLSPrintf(const char *fmt, ...)
 /*      Work out which string in the "ring" we want to use this         */
 /*      time.                                                           */
 /* -------------------------------------------------------------------- */
-    int *pnBufIndex = (int *) pachBufRingInfo;
-    int nOffset = sizeof(int) + *pnBufIndex * CPLSPrintf_BUF_SIZE;
+    int *pnBufIndex = reinterpret_cast<int *>( pachBufRingInfo );
+    const size_t nOffset = sizeof(int) + *pnBufIndex * CPLSPrintf_BUF_SIZE;
     char *pachBuffer = pachBufRingInfo + nOffset;
 
     *pnBufIndex = (*pnBufIndex + 1) % CPLSPrintf_BUF_Count;
@@ -1010,14 +992,15 @@ const char *CPLSPrintf(const char *fmt, ...)
 
     va_start(args, fmt);
 
-    int ret = CPLvsnprintf(pachBuffer, CPLSPrintf_BUF_SIZE-1, fmt, args);
+    const int ret = CPLvsnprintf(pachBuffer, CPLSPrintf_BUF_SIZE-1, fmt, args);
     if( ret < 0 || ret >= CPLSPrintf_BUF_SIZE-1 )
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "CPLSPrintf() called with too big string. Output will be truncated !");
+        CPLError( CE_Failure, CPLE_AppDefined, "CPLSPrintf() called with too "
+                  "big string. Output will be truncated !" );
     }
 
     va_end(args);
-    
+
     return pachBuffer;
 }
 
@@ -1030,10 +1013,10 @@ const char *CPLSPrintf(const char *fmt, ...)
  **********************************************************************/
 char **CSLAppendPrintf(char **papszStrList, const char *fmt, ...)
 {
-    CPLString osWork;
     va_list args;
 
     va_start( args, fmt );
+    CPLString osWork;
     osWork.vPrintf( fmt, args );
     va_end( args );
 
@@ -1043,8 +1026,8 @@ char **CSLAppendPrintf(char **papszStrList, const char *fmt, ...)
 /************************************************************************/
 /*                            CPLVASPrintf()                            */
 /*                                                                      */
-/*      This is intended to serve as an easy to use C callabable        */
-/*      vasprintf() alternative.  Used in the geojson library for       */
+/*      This is intended to serve as an easy to use C callable          */
+/*      vasprintf() alternative.  Used in the GeoJSON library for       */
 /*      instance.                                                       */
 /************************************************************************/
 
@@ -1058,7 +1041,7 @@ int CPLVASPrintf( char **buf, const char *fmt, va_list ap )
     if( buf )
         *buf = CPLStrdup(osWork.c_str());
 
-    return strlen(osWork);
+    return static_cast<int>(strlen(osWork));
 }
 
 /************************************************************************/
@@ -1069,7 +1052,7 @@ static const char* CPLvsnprintf_get_end_of_formatting(const char* fmt)
 {
     char ch;
     /*flag */
-    for( ; (ch = *fmt) != '\0'; fmt ++ )
+    for( ; (ch = *fmt) != '\0'; ++fmt )
     {
         if( ch == '\'' )
             continue; /* bad idea as this is locale specific */
@@ -1077,9 +1060,9 @@ static const char* CPLvsnprintf_get_end_of_formatting(const char* fmt)
             continue;
         break;
     }
-    
+
     /* field width */
-    for( ; (ch = *fmt) != '\0'; fmt ++ )
+    for( ; (ch = *fmt) != '\0'; ++fmt )
     {
         if( ch == '$' )
             return NULL; /* we don't want to support this */
@@ -1091,8 +1074,8 @@ static const char* CPLvsnprintf_get_end_of_formatting(const char* fmt)
     /* precision */
     if( ch == '.' )
     {
-        fmt ++;
-        for( ; (ch = *fmt) != '\0'; fmt ++ )
+        ++fmt;
+        for( ; (ch = *fmt) != '\0'; ++fmt )
         {
             if( ch == '$' )
                 return NULL; /* we don't want to support this */
@@ -1103,7 +1086,7 @@ static const char* CPLvsnprintf_get_end_of_formatting(const char* fmt)
     }
 
     /* length modifier */
-    for( ; (ch = *fmt) != '\0'; fmt ++ )
+    for( ; (ch = *fmt) != '\0'; ++fmt )
     {
         if( ch == 'h' || ch == 'l' || ch == 'j' || ch == 'z' ||
             ch == 't' || ch == 'L' )
@@ -1134,34 +1117,36 @@ static const char* CPLvsnprintf_get_end_of_formatting(const char* fmt)
   * @param size size of the output buffer (including space for terminating nul)
   * @param fmt formatting string
   * @param args arguments
-  * @return the number of characters (excluding terminating nul) that would be written if size is big enough
+  * @return the number of characters (excluding terminating nul) that would be
+  * written if size is big enough
   * @since GDAL 2.0
   */
 int CPLvsnprintf(char *str, size_t size, const char* fmt, va_list args)
 {
-    const char* fmt_ori = fmt;
-    size_t offset_out = 0;
-    va_list wrk_args;
-    char ch;
-    int bFormatUnknown = FALSE;
-
     if( size == 0 )
         return vsnprintf(str, size, fmt, args);
 
+    va_list wrk_args;
+
 #ifdef va_copy
     va_copy( wrk_args, args );
 #else
     wrk_args = args;
 #endif
 
-    for( ; (ch = *fmt) != '\0'; fmt ++ )
+    const char* fmt_ori = fmt;
+    size_t offset_out = 0;
+    char ch;
+    bool bFormatUnknown = false;
+
+    for( ; (ch = *fmt) != '\0'; ++fmt )
     {
         if( ch == '%' )
         {
             const char* ptrend = CPLvsnprintf_get_end_of_formatting(fmt+1);
             if( ptrend == NULL || ptrend - fmt >= 20 )
             {
-                bFormatUnknown = TRUE;
+                bFormatUnknown = true;
                 break;
             }
             char end = *ptrend;
@@ -1171,7 +1156,7 @@ int CPLvsnprintf(char *str, size_t size, const char* fmt, va_list args)
             memcpy(localfmt, fmt, ptrend - fmt + 1);
             localfmt[ptrend-fmt+1] = '\0';
 
-            int local_ret;
+            int local_ret = 0;
             if( end == '%' )
             {
                 if( offset_out == size-1 )
@@ -1194,7 +1179,7 @@ int CPLvsnprintf(char *str, size_t size, const char* fmt, va_list args)
                 else if( (end_m1 >= 'a' && end_m1 <= 'z') ||
                          (end_m1 >= 'A' && end_m1 <= 'Z') )
                 {
-                    bFormatUnknown = TRUE;
+                    bFormatUnknown = true;
                     break;
                 }
                 else
@@ -1215,7 +1200,7 @@ int CPLvsnprintf(char *str, size_t size, const char* fmt, va_list args)
                 else if( (end_m1 >= 'a' && end_m1 <= 'z') ||
                          (end_m1 >= 'A' && end_m1 <= 'Z') )
                 {
-                    bFormatUnknown = TRUE;
+                    bFormatUnknown = true;
                     break;
                 }
                 else
@@ -1233,7 +1218,7 @@ int CPLvsnprintf(char *str, size_t size, const char* fmt, va_list args)
                 /* MSVC vsnprintf() returns -1... */
                 if( local_ret <  0 || offset_out + local_ret >= size )
                     break;
-                for( int j = 0; j < local_ret; j ++ )
+                for( int j = 0; j < local_ret; ++j )
                 {
                     if( str[offset_out + j] == ',' )
                     {
@@ -1244,7 +1229,9 @@ int CPLvsnprintf(char *str, size_t size, const char* fmt, va_list args)
             }
             else if( end == 's' )
             {
-                call_native_snprintf(char*);
+                const char* pszPtr = va_arg(wrk_args, const char*);
+                CPLAssert(pszPtr);
+                local_ret = snprintf(str + offset_out, size - offset_out, localfmt, pszPtr);
             }
             else if( end == 'p' )
             {
@@ -1252,7 +1239,7 @@ int CPLvsnprintf(char *str, size_t size, const char* fmt, va_list args)
             }
             else
             {
-                bFormatUnknown = TRUE;
+                bFormatUnknown = true;
                 break;
             }
             /* MSVC vsnprintf() returns -1... */
@@ -1274,7 +1261,8 @@ int CPLvsnprintf(char *str, size_t size, const char* fmt, va_list args)
     {
         if( bFormatUnknown )
         {
-            CPLDebug("CPL", "CPLvsnprintf() called with unsupported formatting string: %s", fmt_ori);
+            CPLDebug( "CPL", "CPLvsnprintf() called with unsupported "
+                      "formatting string: %s", fmt_ori);
         }
 #ifdef va_copy
         va_end( wrk_args );
@@ -1293,7 +1281,7 @@ int CPLvsnprintf(char *str, size_t size, const char* fmt, va_list args)
     va_end( wrk_args );
 #endif
 
-    return (int)offset_out;
+    return static_cast<int>( offset_out );
 }
 
 /************************************************************************/
@@ -1310,16 +1298,16 @@ int CPLvsnprintf(char *str, size_t size, const char* fmt, va_list args)
   * @param size size of the output buffer (including space for terminating nul)
   * @param fmt formatting string
   * @param ... arguments
-  * @return the number of characters (excluding terminating nul) that would be written if size is big enough
+  * @return the number of characters (excluding terminating nul) that would be
+  * written if size is big enough
   * @since GDAL 2.0
   */
 int CPLsnprintf(char *str, size_t size, const char* fmt, ...)
 {
-    int ret;
     va_list args;
 
     va_start( args, fmt );
-    ret = CPLvsnprintf( str, size, fmt, args );
+    const int ret = CPLvsnprintf( str, size, fmt, args );
     va_end( args );
     return ret;
 }
@@ -1337,16 +1325,16 @@ int CPLsnprintf(char *str, size_t size, const char* fmt, ...)
   * @param str output buffer (must be large enough to hold the result)
   * @param fmt formatting string
   * @param ... arguments
-  * @return the number of characters (excluding terminating nul) written in output buffer.
+  * @return the number of characters (excluding terminating nul) written in
+` * output buffer.
   * @since GDAL 2.0
   */
 int CPLsprintf(char *str, const char* fmt, ...)
 {
-    int ret;
     va_list args;
 
     va_start( args, fmt );
-    ret = CPLvsnprintf( str, INT_MAX, fmt, args );
+    const int ret = CPLvsnprintf( str, INT_MAX, fmt, args );
     va_end( args );
     return ret;
 }
@@ -1363,13 +1351,12 @@ int CPLsprintf(char *str, const char* fmt, ...)
   *
   * @param fmt formatting string
   * @param ... arguments
-  * @return the number of characters (excluding terminating nul) written in output buffer.
+  * @return the number of characters (excluding terminating nul) written in
+  * output buffer.
   * @since GDAL 2.0
   */
 int CPLprintf(const char* fmt, ...)
 {
-    char szBuffer[4096];
-    int ret;
     va_list wrk_args, args;
 
     va_start( args, fmt );
@@ -1380,22 +1367,33 @@ int CPLprintf(const char* fmt, ...)
     wrk_args = args;
 #endif
 
-    ret = CPLvsnprintf( szBuffer, sizeof(szBuffer), fmt, wrk_args );
+    char szBuffer[4096];
+    // Quiet coverity by staring off nul terminated.
+    szBuffer[0] = '\0';
+    int ret = CPLvsnprintf( szBuffer, sizeof(szBuffer), fmt, wrk_args );
+
+#ifdef va_copy
+    va_end( wrk_args );
+#endif
 
-    if( ret < (int)sizeof(szBuffer)-1 )
+    if( ret < int(sizeof(szBuffer))-1 )
         ret = printf("%s", szBuffer);
     else
     {
 #ifdef va_copy
-        va_end( wrk_args );
         va_copy( wrk_args, args );
 #else
         wrk_args = args;
 #endif
+
         ret = vfprintf(stdout, fmt, wrk_args);
+
+#ifdef va_copy
+        va_end( wrk_args );
+#endif
     }
 
-    va_end( wrk_args );
+    va_end( args );
 
     return ret;
 }
@@ -1421,13 +1419,13 @@ int CPLprintf(const char* fmt, ...)
   */
 int CPL_DLL CPLsscanf(const char* str, const char* fmt, ...)
 {
-    int error = FALSE;
+    bool error = false;
     int ret = 0;
     const char* fmt_ori = fmt;
     va_list args;
 
     va_start( args, fmt );
-    for( ; *fmt != '\0' && *str != '\0'; fmt++ )
+    for( ; *fmt != '\0' && *str != '\0'; ++fmt )
     {
         if( *fmt == '%' )
         {
@@ -1438,7 +1436,7 @@ int CPL_DLL CPLsscanf(const char* str, const char* fmt, ...)
                 *(va_arg(args, double*)) = CPLStrtod(str, &end);
                 if( end > str )
                 {
-                    ret ++;
+                    ++ret;
                     str = end;
                 }
                 else
@@ -1446,14 +1444,14 @@ int CPL_DLL CPLsscanf(const char* str, const char* fmt, ...)
             }
             else
             {
-                error = TRUE;
+                error = true;
                 break;
             }
         }
         else if( *str != *fmt )
             break;
         else
-            str ++;
+            ++str;
     }
     va_end( args );
 
@@ -1468,6 +1466,29 @@ int CPL_DLL CPLsscanf(const char* str, const char* fmt, ...)
 }
 
 /************************************************************************/
+/*                         CPLTestBool()                                */
+/************************************************************************/
+
+/**
+ * Test what boolean value contained in the string.
+ *
+ * If pszValue is "NO", "FALSE", "OFF" or "0" will be returned false.
+ * Otherwise, true will be returned.
+ *
+ * @param pszValue the string should be tested.
+ *
+ * @return true or false.
+ */
+
+bool CPLTestBool( const char *pszValue )
+{
+  return !( EQUAL(pszValue,"NO")
+            || EQUAL(pszValue,"FALSE")
+            || EQUAL(pszValue,"OFF")
+            || EQUAL(pszValue,"0") );
+}
+
+/************************************************************************/
 /*                         CSLTestBoolean()                             */
 /************************************************************************/
 
@@ -1477,70 +1498,117 @@ int CPL_DLL CPLsscanf(const char* str, const char* fmt, ...)
  * If pszValue is "NO", "FALSE", "OFF" or "0" will be returned FALSE.
  * Otherwise, TRUE will be returned.
  *
+ * Deprecated.  Removed in GDAL 3.x.
+ *
+ * Use CPLTestBoolean() for C and CPLTestBool() for C++.
+ *
  * @param pszValue the string should be tested.
- * 
+ *
  * @return TRUE or FALSE.
  */
 
 int CSLTestBoolean( const char *pszValue )
 {
-    if( EQUAL(pszValue,"NO")
-        || EQUAL(pszValue,"FALSE") 
-        || EQUAL(pszValue,"OFF") 
-        || EQUAL(pszValue,"0") )
-        return FALSE;
-    else
-        return TRUE;
+    return CPLTestBool( pszValue ) ? TRUE : FALSE;
+}
+
+/************************************************************************/
+/*                         CPLTestBoolean()                             */
+/************************************************************************/
+
+/**
+ * Test what boolean value contained in the string.
+ *
+ * If pszValue is "NO", "FALSE", "OFF" or "0" will be returned FALSE.
+ * Otherwise, TRUE will be returned.
+ *
+ * Use this only in C code.  In C++, prefer CPLTestBool().
+ *
+ * @param pszValue the string should be tested.
+ *
+ * @return TRUE or FALSE.
+ */
+
+int CPLTestBoolean( const char *pszValue )
+{
+    return CPLTestBool( pszValue ) ? TRUE : FALSE;
 }
 
+
 /**********************************************************************
- *                       CSLFetchBoolean()
+ *                       CPLFetchBool()
  *
  * Check for boolean key value.
  *
  * In a StringList of "Name=Value" pairs, look to see if there is a key
  * with the given name, and if it can be interpreted as being TRUE.  If
- * the key appears without any "=Value" portion it will be considered true. 
+ * the key appears without any "=Value" portion it will be considered true.
  * If the value is NO, FALSE or 0 it will be considered FALSE otherwise
  * if the key appears in the list it will be considered TRUE.  If the key
- * doesn't appear at all, the indicated default value will be returned. 
- * 
+ * doesn't appear at all, the indicated default value will be returned.
+ *
  * @param papszStrList the string list to search.
  * @param pszKey the key value to look for (case insensitive).
- * @param bDefault the value to return if the key isn't found at all. 
- * 
- * @return TRUE or FALSE 
+ * @param bDefault the value to return if the key isn't found at all.
+ *
+ * @return true or false
  **********************************************************************/
 
-int CSLFetchBoolean( char **papszStrList, const char *pszKey, int bDefault )
+bool CPLFetchBool( const char **papszStrList, const char *pszKey,
+                   bool bDefault )
 
 {
-    const char *pszValue;
+    if( CSLFindString( const_cast<char **>(papszStrList), pszKey ) != -1 )
+        return true;
 
-    if( CSLFindString( papszStrList, pszKey ) != -1 )
-        return TRUE;
-
-    pszValue = CSLFetchNameValue(papszStrList, pszKey );
+    const char * const pszValue =
+        CSLFetchNameValue( const_cast<char **>(papszStrList), pszKey );
     if( pszValue == NULL )
         return bDefault;
-    else 
-        return CSLTestBoolean( pszValue );
+
+    return CPLTestBool( pszValue );
+}
+
+/**********************************************************************
+ *                       CSLFetchBoolean()
+ *
+ * DEPRECATED.  Check for boolean key value.
+ *
+ * In a StringList of "Name=Value" pairs, look to see if there is a key
+ * with the given name, and if it can be interpreted as being TRUE.  If
+ * the key appears without any "=Value" portion it will be considered true.
+ * If the value is NO, FALSE or 0 it will be considered FALSE otherwise
+ * if the key appears in the list it will be considered TRUE.  If the key
+ * doesn't appear at all, the indicated default value will be returned.
+ *
+ * @param papszStrList the string list to search.
+ * @param pszKey the key value to look for (case insensitive).
+ * @param bDefault the value to return if the key isn't found at all.
+ *
+ * @return TRUE or FALSE
+ **********************************************************************/
+
+int CSLFetchBoolean( char **papszStrList, const char *pszKey, int bDefault )
+
+{
+    return CPLFetchBool( const_cast<const char **>(papszStrList),
+                         pszKey, CPL_TO_BOOL(bDefault) );
 }
 
 /************************************************************************/
 /*                     CSLFetchNameValueDefaulted()                     */
 /************************************************************************/
 
-const char *CSLFetchNameValueDef( char **papszStrList, 
+const char *CSLFetchNameValueDef( char **papszStrList,
                                   const char *pszName,
                                   const char *pszDefault )
 
 {
     const char *pszResult = CSLFetchNameValue( papszStrList, pszName );
-    if( pszResult )
+    if( pszResult != NULL )
         return pszResult;
-    else
-        return pszDefault;
+
+    return pszDefault;
 }
 
 /**********************************************************************
@@ -1551,7 +1619,7 @@ const char *CSLFetchNameValueDef( char **papszStrList,
  * case sensitive.
  * ("Name:Value" pairs are also supported for backward compatibility
  * with older stuff.)
- * 
+ *
  * Returns a reference to the value in the StringList that the caller
  * should not attempt to free.
  *
@@ -1559,21 +1627,19 @@ const char *CSLFetchNameValueDef( char **papszStrList,
  **********************************************************************/
 const char *CSLFetchNameValue(char **papszStrList, const char *pszName)
 {
-    size_t nLen;
-
     if (papszStrList == NULL || pszName == NULL)
         return NULL;
 
-    nLen = strlen(pszName);
-    while(*papszStrList != NULL)
+    const size_t nLen = strlen(pszName);
+    while( *papszStrList != NULL )
     {
         if (EQUALN(*papszStrList, pszName, nLen)
-            && ( (*papszStrList)[nLen] == '=' || 
+            && ( (*papszStrList)[nLen] == '=' ||
                  (*papszStrList)[nLen] == ':' ) )
         {
-            return (*papszStrList)+nLen+1;
+            return (*papszStrList) + nLen + 1;
         }
-        papszStrList++;
+        ++papszStrList;
     }
     return NULL;
 }
@@ -1588,29 +1654,27 @@ const char *CSLFetchNameValue(char **papszStrList, const char *pszName)
  * @param papszStrList the string list to search.
  * @param pszName the key value to look for (case insensitive).
  *
- * @return -1 on failure or the list index of the first occurance 
+ * @return -1 on failure or the list index of the first occurrence
  * matching the given key.
  */
 
 int CSLFindName(char **papszStrList, const char *pszName)
 {
-    size_t nLen;
-    int    iIndex = 0;
-
     if (papszStrList == NULL || pszName == NULL)
         return -1;
 
-    nLen = strlen(pszName);
+    const size_t nLen = strlen(pszName);
+    int iIndex = 0;
     while(*papszStrList != NULL)
     {
         if (EQUALN(*papszStrList, pszName, nLen)
-            && ( (*papszStrList)[nLen] == '=' || 
+            && ( (*papszStrList)[nLen] == '=' ||
                  (*papszStrList)[nLen] == ':' ) )
         {
             return iIndex;
         }
-        iIndex++;
-        papszStrList++;
+        ++iIndex;
+        ++papszStrList;
     }
     return -1;
 }
@@ -1625,40 +1689,37 @@ int CSLFindName(char **papszStrList, const char *pszName)
  * Note that if ppszKey is non-NULL, the key (or name) portion will be
  * allocated using VSIMalloc(), and returned in that pointer.  It is the
  * applications responsibility to free this string, but the application should
- * not modify or free the returned value portion. 
+ * not modify or free the returned value portion.
  *
  * This function also support "NAME:VALUE" strings and will strip white
- * space from around the delimeter when forming name and value strings.
+ * space from around the delimiter when forming name and value strings.
+ *
+ * Eventually CSLFetchNameValue() and friends may be modified to use
+ * CPLParseNameValue().
  *
- * Eventually CSLFetchNameValue() and friends may be modified to use 
- * CPLParseNameValue(). 
- * 
- * @param pszNameValue string in "NAME=VALUE" format. 
+ * @param pszNameValue string in "NAME=VALUE" format.
  * @param ppszKey optional pointer though which to return the name
- * portion. 
- * @return the value portion (pointing into original string). 
+ * portion.
+ *
+ * @return the value portion (pointing into original string).
  */
 
 const char *CPLParseNameValue(const char *pszNameValue, char **ppszKey )
-
 {
-    int  i;
-    const char *pszValue;
-
-    for( i = 0; pszNameValue[i] != '\0'; i++ )
+    for( int i = 0; pszNameValue[i] != '\0'; ++i )
     {
         if( pszNameValue[i] == '=' || pszNameValue[i] == ':' )
         {
-            pszValue = pszNameValue + i + 1;
+            const char *pszValue = pszNameValue + i + 1;
             while( *pszValue == ' ' || *pszValue == '\t' )
-                pszValue++;
+                ++pszValue;
 
             if( ppszKey != NULL )
             {
-                *ppszKey = (char *) CPLMalloc(i+1);
+                *ppszKey = reinterpret_cast<char *>( CPLMalloc(i+1) );
                 strncpy( *ppszKey, pszNameValue, i );
                 (*ppszKey)[i] = '\0';
-                while( i > 0 && 
+                while( i > 0 &&
                        ( (*ppszKey)[i] == ' ' || (*ppszKey)[i] == '\t') )
                 {
                     (*ppszKey)[i] = '\0';
@@ -1681,62 +1742,58 @@ const char *CPLParseNameValue(const char *pszNameValue, char **ppszKey )
  * sensitive.
  * ("Name:Value" pairs are also supported for backward compatibility
  * with older stuff.)
- * 
- * Returns stringlist with one entry for each occurence of the
- * specified name.  The stringlist should eventually be destroyed
+ *
+ * Returns StringList with one entry for each occurrence of the
+ * specified name.  The StringList should eventually be destroyed
  * by calling CSLDestroy().
  *
  * Returns NULL if the name is not found.
  **********************************************************************/
 char **CSLFetchNameValueMultiple(char **papszStrList, const char *pszName)
 {
-    size_t nLen;
-    char **papszValues = NULL;
-
     if (papszStrList == NULL || pszName == NULL)
         return NULL;
 
-    nLen = strlen(pszName);
+    const size_t nLen = strlen(pszName);
+    char **papszValues = NULL;
     while(*papszStrList != NULL)
     {
         if (EQUALN(*papszStrList, pszName, nLen)
-            && ( (*papszStrList)[nLen] == '=' || 
+            && ( (*papszStrList)[nLen] == '=' ||
                  (*papszStrList)[nLen] == ':' ) )
         {
-            papszValues = CSLAddString(papszValues, 
-                                          (*papszStrList)+nLen+1);
+            papszValues = CSLAddString(papszValues,
+                                       (*papszStrList)+nLen+1);
         }
-        papszStrList++;
+        ++papszStrList;
     }
 
     return papszValues;
 }
 
-
 /**********************************************************************
  *                       CSLAddNameValue()
  *
  * Add a new entry to a StringList of "Name=Value" pairs,
  * ("Name:Value" pairs are also supported for backward compatibility
  * with older stuff.)
- * 
+ *
  * This function does not check if a "Name=Value" pair already exists
- * for that name and can generate multiple entryes for the same name.
+ * for that name and can generate multiple entries for the same name.
  * Use CSLSetNameValue() if you want each name to have only one value.
  *
- * Returns the modified stringlist.
+ * Returns the modified StringList.
  **********************************************************************/
-char **CSLAddNameValue(char **papszStrList, 
-                    const char *pszName, const char *pszValue)
+char **CSLAddNameValue(char **papszStrList,
+                       const char *pszName, const char *pszValue)
 {
-    char *pszLine;
-
     if (pszName == NULL || pszValue==NULL)
         return papszStrList;
 
-    pszLine = (char *) CPLMalloc(strlen(pszName)+strlen(pszValue)+2);
-    CPLsprintf( pszLine, "%s=%s", pszName, pszValue );
-    papszStrList = CSLAddString(papszStrList, pszLine);
+    const size_t nLen = strlen(pszName)+strlen(pszValue)+2;
+    char *pszLine = static_cast<char *>(CPLMalloc(nLen) );
+    snprintf( pszLine, nLen, "%s=%s", pszName, pszValue );
+    papszStrList = CSLAddString( papszStrList, pszLine );
     CPLFree( pszLine );
 
     return papszStrList;
@@ -1752,46 +1809,42 @@ char **CSLAddNameValue(char **papszStrList,
  * Set the value for a given name in a StringList of "Name=Value" pairs
  * ("Name:Value" pairs are also supported for backward compatibility
  * with older stuff.)
- * 
+ *
  * If there is already a value for that name in the list then the value
  * is changed, otherwise a new "Name=Value" pair is added.
  *
  * @param papszList the original list, the modified version is returned.
  * @param pszName the name to be assigned a value.  This should be a well
- * formed token (no spaces or very special characters). 
+ * formed token (no spaces or very special characters).
  * @param pszValue the value to assign to the name.  This should not contain
  * any newlines (CR or LF) but is otherwise pretty much unconstrained.  If
  * NULL any corresponding value will be removed.
  *
- * @return modified stringlist.
+ * @return modified StringList.
  */
 
-char **CSLSetNameValue(char **papszList, 
-                       const char *pszName, const char *pszValue)
+char **CSLSetNameValue( char **papszList,
+                        const char *pszName, const char *pszValue )
 {
-    char **papszPtr;
-    size_t nLen;
-
-    if (pszName == NULL )
+    if( pszName == NULL )
         return papszList;
 
-    nLen = strlen(pszName);
-    papszPtr = papszList;
+    const size_t nLen = strlen(pszName);
+    char **papszPtr = papszList;
     while(papszPtr && *papszPtr != NULL)
     {
         if (EQUALN(*papszPtr, pszName, nLen)
-            && ( (*papszPtr)[nLen] == '=' || 
+            && ( (*papszPtr)[nLen] == '=' ||
                  (*papszPtr)[nLen] == ':' ) )
         {
-            /* Found it!  
+            /* Found it!
              * Change the value... make sure to keep the ':' or '='
              */
-            char cSep;
-            cSep = (*papszPtr)[nLen];
+            const char cSep = (*papszPtr)[nLen];
 
             CPLFree(*papszPtr);
 
-            /* 
+            /*
              * If the value is NULL, remove this entry completely/
              */
             if( pszValue == NULL )
@@ -1799,7 +1852,7 @@ char **CSLSetNameValue(char **papszList,
                 while( papszPtr[1] != NULL )
                 {
                     *papszPtr = papszPtr[1];
-                    papszPtr++;
+                    ++papszPtr;
                 }
                 *papszPtr = NULL;
             }
@@ -1809,12 +1862,13 @@ char **CSLSetNameValue(char **papszList,
              */
             else
             {
-                *papszPtr = (char *) CPLMalloc(strlen(pszName)+strlen(pszValue)+2);
-                CPLsprintf( *papszPtr, "%s%c%s", pszName, cSep, pszValue );
+                const size_t nLen2 = strlen(pszName)+strlen(pszValue)+2;
+                *papszPtr = static_cast<char *>(CPLMalloc(nLen2) );
+                snprintf( *papszPtr, nLen2, "%s%c%s", pszName, cSep, pszValue );
             }
             return papszList;
         }
-        papszPtr++;
+        ++papszPtr;
     }
 
     if( pszValue == NULL )
@@ -1831,41 +1885,38 @@ char **CSLSetNameValue(char **papszList,
 
 /**
  * Replace the default separator (":" or "=") with the passed separator
- * in the given name/value list. 
+ * in the given name/value list.
  *
  * Note that if a separator other than ":" or "=" is used, the resulting
- * list will not be manipulatable by the CSL name/value functions any more.
+ * list will not be manipulable by the CSL name/value functions any more.
  *
- * The CPLParseNameValue() function is used to break the existing lines, 
+ * The CPLParseNameValue() function is used to break the existing lines,
  * and it also strips white space from around the existing delimiter, thus
  * the old separator, and any white space will be replaced by the new
- * separator.  For formatting purposes it may be desireable to include some
- * white space in the new separator.  eg. ": " or " = ".
- * 
+ * separator.  For formatting purposes it may be desirable to include some
+ * white space in the new separator.  e.g. ": " or " = ".
+ *
  * @param papszList the list to update.  Component strings may be freed
  * but the list array will remain at the same location.
  *
- * @param pszSeparator the new separator string to insert.  
- *
+ * @param pszSeparator the new separator string to insert.
  */
 
 void CSLSetNameValueSeparator( char ** papszList, const char *pszSeparator )
 
 {
-    int         nLines = CSLCount(papszList), iLine;
+    const int nLines = CSLCount(papszList);
 
-    for( iLine = 0; iLine < nLines; iLine++ )
+    for( int iLine = 0; iLine < nLines; ++iLine )
     {
-        char        *pszKey = NULL;
-        const char  *pszValue;
-        char        *pszNewLine;
-
-        pszValue = CPLParseNameValue( papszList[iLine], &pszKey );
+        char *pszKey = NULL;
+        const char *pszValue = CPLParseNameValue( papszList[iLine], &pszKey );
         if( pszValue == NULL || pszKey == NULL )
             continue;
-        
-        pszNewLine = (char *) CPLMalloc( strlen(pszValue) + strlen(pszKey)
-                                         + strlen(pszSeparator) + 1 );
+
+        char *pszNewLine = static_cast<char *>(
+            CPLMalloc( strlen(pszValue) + strlen(pszKey)
+                       + strlen(pszSeparator) + 1 ) );
         strcpy( pszNewLine, pszKey );
         strcat( pszNewLine, pszSeparator );
         strcat( pszNewLine, pszValue );
@@ -1885,60 +1936,58 @@ void CSLSetNameValueSeparator( char ** papszList, const char *pszSeparator )
  * This function will "escape" a variety of special characters
  * to make the string suitable to embed within a string constant
  * or to write within a text stream but in a form that can be
- * reconstitued to it's original form.  The escaping will even preserve
+ * reconstituted to it's original form.  The escaping will even preserve
  * zero bytes allowing preservation of raw binary data.
  *
- * CPLES_BackslashQuotable(0): This scheme turns a binary string into 
+ * CPLES_BackslashQuotable(0): This scheme turns a binary string into
  * a form suitable to be placed within double quotes as a string constant.
- * The backslash, quote, '\\0' and newline characters are all escaped in 
- * the usual C style. 
+ * The backslash, quote, '\\0' and newline characters are all escaped in
+ * the usual C style.
  *
  * CPLES_XML(1): This scheme converts the '<', '>', '"' and '&' characters into
- * their XML/HTML equivelent (<, >, " and &) making a string safe
- * to embed as CDATA within an XML element.  The '\\0' is not escaped and 
+ * their XML/HTML equivalent (<, >, " and &) making a string safe
+ * to embed as CDATA within an XML element.  The '\\0' is not escaped and
  * should not be included in the input.
  *
- * CPLES_URL(2): Everything except alphanumerics and the underscore are 
+ * CPLES_URL(2): Everything except alphanumerics and the characters
+ * '$', '-', '_', '.', '+', '!', '*', ''', '(', ')' and ',' (see RFC1738) are
  * converted to a percent followed by a two digit hex encoding of the character
  * (leading zero supplied if needed).  This is the mechanism used for encoding
  * values to be passed in URLs.
  *
- * CPLES_SQL(3): All single quotes are replaced with two single quotes.  
+ * CPLES_SQL(3): All single quotes are replaced with two single quotes.
  * Suitable for use when constructing literal values for SQL commands where
  * the literal will be enclosed in single quotes.
  *
- * CPLES_CSV(4): If the values contains commas, semicolons, tabs, double quotes, or newlines it 
- * placed in double quotes, and double quotes in the value are doubled.
- * Suitable for use when constructing field values for .csv files.  Note that
- * CPLUnescapeString() currently does not support this format, only 
- * CPLEscapeString().  See cpl_csv.cpp for csv parsing support.
+ * CPLES_CSV(4): If the values contains commas, semicolons, tabs, double quotes,
+ * or newlines it placed in double quotes, and double quotes in the value are
+ * doubled. Suitable for use when constructing field values for .csv files.
+ * Note that CPLUnescapeString() currently does not support this format, only
+ * CPLEscapeString().  See cpl_csv.cpp for CSV parsing support.
  *
- * @param pszInput the string to escape.  
+ * @param pszInput the string to escape.
  * @param nLength The number of bytes of data to preserve.  If this is -1
  * the strlen(pszString) function will be used to compute the length.
- * @param nScheme the encoding scheme to use.  
+ * @param nScheme the encoding scheme to use.
  *
- * @return an escaped, zero terminated string that should be freed with 
+ * @return an escaped, zero terminated string that should be freed with
  * CPLFree() when no longer needed.
  */
 
-char *CPLEscapeString( const char *pszInput, int nLength, 
+char *CPLEscapeString( const char *pszInput, int nLength,
                        int nScheme )
-
 {
-    char        *pszOutput;
-    char        *pszShortOutput;
-
     if( nLength == -1 )
-        nLength = strlen(pszInput);
+        nLength = static_cast<int>(strlen(pszInput));
+
+    const size_t nSizeAlloc = nLength * 6 + 1;
+    char *pszOutput = static_cast<char *>( CPLMalloc( nSizeAlloc ) );
 
-    pszOutput = (char *) CPLMalloc( nLength * 6 + 1 );
-    
     if( nScheme == CPLES_BackslashQuotable )
     {
-        int iOut = 0, iIn;
+        int iOut = 0;
 
-        for( iIn = 0; iIn < nLength; iIn++ )
+        for( int iIn = 0; iIn < nLength; iIn++ )
         {
             if( pszInput[iIn] == '\0' )
             {
@@ -1965,32 +2014,11 @@ char *CPLEscapeString( const char *pszInput, int nLength,
         }
         pszOutput[iOut] = '\0';
     }
-    else if( nScheme == CPLES_URL ) /* Untested at implementation */
-    {
-        int iOut = 0, iIn;
-
-        for( iIn = 0; iIn < nLength; iIn++ )
-        {
-            if( (pszInput[iIn] >= 'a' && pszInput[iIn] <= 'z')
-                || (pszInput[iIn] >= 'A' && pszInput[iIn] <= 'Z')
-                || (pszInput[iIn] >= '0' && pszInput[iIn] <= '9')
-                || pszInput[iIn] == '_' || pszInput[iIn] == '.' )
-            {
-                pszOutput[iOut++] = pszInput[iIn];
-            }
-            else
-            {
-                CPLsprintf( pszOutput+iOut, "%%%02X", ((unsigned char*)pszInput)[iIn] );
-                iOut += 3;
-            }
-        }
-        pszOutput[iOut] = '\0';
-    }
     else if( nScheme == CPLES_XML || nScheme == CPLES_XML_BUT_QUOTES )
     {
-        int iOut = 0, iIn;
+        int iOut = 0;
 
-        for( iIn = 0; iIn < nLength; iIn++ )
+        for( int iIn = 0; iIn < nLength; ++iIn )
         {
             if( pszInput[iIn] == '<' )
             {
@@ -2023,11 +2051,11 @@ char *CPLEscapeString( const char *pszInput, int nLength,
                 pszOutput[iOut++] = 't';
                 pszOutput[iOut++] = ';';
             }
-            /* Python 2 doesn't like displaying the UTF-8 character corresponding */
-            /* to BOM, so escape it */
-            else if( ((GByte*)pszInput)[iIn] == 0xEF &&
-                     ((GByte*)pszInput)[iIn+1] == 0xBB &&
-                     ((GByte*)pszInput)[iIn+2] == 0xBF )
+            /* Python 2 does not display the UTF-8 character corresponding */
+            /* to the byte-order mark (BOM), so escape it */
+            else if( (reinterpret_cast<const unsigned char*>(pszInput))[iIn] == 0xEF &&
+                     (reinterpret_cast<const unsigned char*>(pszInput))[iIn+1] == 0xBB &&
+                     (reinterpret_cast<const unsigned char*>(pszInput))[iIn+2] == 0xBF )
             {
                 pszOutput[iOut++] = '&';
                 pszOutput[iOut++] = '#';
@@ -2039,12 +2067,12 @@ char *CPLEscapeString( const char *pszInput, int nLength,
                 pszOutput[iOut++] = ';';
                 iIn += 2;
             }
-            else if( ((GByte*)pszInput)[iIn] < 0x20 
+            else if( (reinterpret_cast<const unsigned char*>(pszInput))[iIn] < 0x20
                      && pszInput[iIn] != 0x9
-                     && pszInput[iIn] != 0xA 
-                     && pszInput[iIn] != 0xD ) 
+                     && pszInput[iIn] != 0xA
+                     && pszInput[iIn] != 0xD )
             {
-                // These control characters are unrepresentable in XML format, 
+                // These control characters are unrepresentable in XML format,
                 // so we just drop them.  #4117
             }
             else
@@ -2052,11 +2080,38 @@ char *CPLEscapeString( const char *pszInput, int nLength,
         }
         pszOutput[iOut] = '\0';
     }
-    else if( nScheme == CPLES_SQL )
+    else if( nScheme == CPLES_URL ) /* Untested at implementation */
     {
         int iOut = 0, iIn;
 
-        for( iIn = 0; iIn < nLength; iIn++ )
+        for( iIn = 0; iIn < nLength; ++iIn )
+        {
+            if( (pszInput[iIn] >= 'a' && pszInput[iIn] <= 'z')
+                || (pszInput[iIn] >= 'A' && pszInput[iIn] <= 'Z')
+                || (pszInput[iIn] >= '0' && pszInput[iIn] <= '9')
+                || pszInput[iIn] == '$' || pszInput[iIn] == '-'
+                || pszInput[iIn] == '_' || pszInput[iIn] == '.'
+                || pszInput[iIn] == '+' || pszInput[iIn] == '!'
+                || pszInput[iIn] == '*' || pszInput[iIn] == '\''
+                || pszInput[iIn] == '(' || pszInput[iIn] == ')'
+                || pszInput[iIn] == '"' || pszInput[iIn] == ',' )
+            {
+                pszOutput[iOut++] = pszInput[iIn];
+            }
+            else
+            {
+                snprintf( pszOutput+iOut, nSizeAlloc - iOut, "%%%02X",
+                            static_cast<unsigned char>( pszInput[iIn] ) );
+                iOut += 3;
+            }
+        }
+        pszOutput[iOut] = '\0';
+    }
+    else if( nScheme == CPLES_SQL )
+    {
+        int iOut = 0;
+
+        for( int iIn = 0; iIn < nLength; ++iIn )
         {
             if( pszInput[iIn] == '\'' )
             {
@@ -2074,18 +2129,18 @@ char *CPLEscapeString( const char *pszInput, int nLength,
             && strchr( pszInput, ',') == NULL
             && strchr( pszInput, ';') == NULL
             && strchr( pszInput, '\t') == NULL
-            && strchr( pszInput, 10) == NULL 
-            && strchr( pszInput, 13) == NULL )
+            && strchr( pszInput, 10) == NULL  // \n
+            && strchr( pszInput, 13) == NULL )  // \r
         {
             strcpy( pszOutput, pszInput );
         }
         else
         {
-            int iOut = 1, iIn;
+            int iOut = 1;
 
             pszOutput[0] = '\"';
 
-            for( iIn = 0; iIn < nLength; iIn++ )
+            for( int iIn = 0; iIn < nLength; ++iIn )
             {
                 if( pszInput[iIn] == '\"' )
                 {
@@ -2102,12 +2157,13 @@ char *CPLEscapeString( const char *pszInput, int nLength,
     else
     {
         pszOutput[0] = '\0';
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Undefined escaping scheme (%d) in CPLEscapeString()",
                   nScheme );
     }
 
-    pszShortOutput = CPLStrdup( pszOutput );
+    // TODO: Was pszShortOutput supposed to start part way through pszOutput?
+    char *pszShortOutput = CPLStrdup( pszOutput );
     CPLFree( pszOutput );
 
     return pszShortOutput;
@@ -2122,69 +2178,90 @@ char *CPLEscapeString( const char *pszInput, int nLength,
  *
  * This function does the opposite of CPLEscapeString().  Given a string
  * with special values escaped according to some scheme, it will return a
- * new copy of the string returned to it's original form. 
+ * new copy of the string returned to it's original form.
  *
  * @param pszInput the input string.  This is a zero terminated string.
- * @param pnLength location to return the length of the unescaped string, 
+ * @param pnLength location to return the length of the unescaped string,
  * which may in some cases include embedded '\\0' characters.
  * @param nScheme the escaped scheme to undo (see CPLEscapeString() for a
- * list). 
- * 
- * @return a copy of the unescaped string that should be freed by the 
+ * list).  Does not yet support CSV.
+ *
+ * @return a copy of the unescaped string that should be freed by the
  * application using CPLFree() when no longer needed.
  */
 
 char *CPLUnescapeString( const char *pszInput, int *pnLength, int nScheme )
 
 {
-    char *pszOutput;
-    int iOut=0, iIn;
+    int iOut=0;
 
-    pszOutput = (char *) CPLMalloc(4 * strlen(pszInput)+1);
+    // TODO: Why times 4?
+    char *pszOutput = reinterpret_cast<char *>(
+        CPLMalloc(4 * strlen(pszInput) + 1) );
     pszOutput[0] = '\0';
 
-    if( nScheme == CPLES_XML || nScheme == CPLES_XML_BUT_QUOTES  )
+    if( nScheme == CPLES_BackslashQuotable )
+    {
+        for( int iIn = 0; pszInput[iIn] != '\0'; ++iIn )
+        {
+            if( pszInput[iIn] == '\\' )
+            {
+                ++iIn;
+                if( pszInput[iIn] == 'n' )
+                    pszOutput[iOut++] = '\n';
+                else if( pszInput[iIn] == '0' )
+                    pszOutput[iOut++] = '\0';
+                else
+                    pszOutput[iOut++] = pszInput[iIn];
+            }
+            else
+            {
+                pszOutput[iOut++] = pszInput[iIn];
+            }
+        }
+    }
+    else if( nScheme == CPLES_XML || nScheme == CPLES_XML_BUT_QUOTES  )
     {
         char ch;
-        for( iIn = 0; (ch = pszInput[iIn]) != '\0'; iIn++ )
+        for( int iIn = 0; (ch = pszInput[iIn]) != '\0'; ++iIn )
         {
             if( ch != '&' )
             {
                 pszOutput[iOut++] = ch;
             }
-            else if( EQUALN(pszInput+iIn,"<",4) )
+            else if( STARTS_WITH_CI(pszInput+iIn, "<") )
             {
                 pszOutput[iOut++] = '<';
                 iIn += 3;
             }
-            else if( EQUALN(pszInput+iIn,">",4) )
+            else if( STARTS_WITH_CI(pszInput+iIn, ">") )
             {
                 pszOutput[iOut++] = '>';
                 iIn += 3;
             }
-            else if( EQUALN(pszInput+iIn,"&",5) )
+            else if( STARTS_WITH_CI(pszInput+iIn, "&") )
             {
                 pszOutput[iOut++] = '&';
                 iIn += 4;
             }
-            else if( EQUALN(pszInput+iIn,"'",6) )
+            else if( STARTS_WITH_CI(pszInput+iIn, "'") )
             {
                 pszOutput[iOut++] = '\'';
                 iIn += 5;
             }
-            else if( EQUALN(pszInput+iIn,""",6) )
+            else if( STARTS_WITH_CI(pszInput+iIn, """) )
             {
                 pszOutput[iOut++] = '"';
                 iIn += 5;
             }
-            else if( EQUALN(pszInput+iIn,"&#x",3) )
+            else if( STARTS_WITH_CI(pszInput+iIn, "&#x") )
             {
                 wchar_t anVal[2] = {0 , 0};
                 iIn += 3;
 
-                while(TRUE)
+                while(true)
                 {
-                    ch = pszInput[iIn ++];
+                    ch = pszInput[iIn++];
                     if (ch >= 'a' && ch <= 'f')
                         anVal[0] = anVal[0] * 16 + ch - 'a' + 10;
                     else if (ch >= 'A' && ch <= 'F')
@@ -2199,18 +2276,17 @@ char *CPLUnescapeString( const char *pszInput, int *pnLength, int nScheme )
                 iIn --;
 
                 char * pszUTF8 = CPLRecodeFromWChar( anVal, "WCHAR_T", CPL_ENC_UTF8);
-                int nLen = strlen(pszUTF8);
+                int nLen = static_cast<int>(strlen(pszUTF8));
                 memcpy(pszOutput + iOut, pszUTF8, nLen);
                 CPLFree(pszUTF8);
                 iOut += nLen;
             }
-            else if( EQUALN(pszInput+iIn,"&#",2) )
+            else if( STARTS_WITH_CI(pszInput+iIn, "&#") )
             {
-                char ch;
                 wchar_t anVal[2] = {0 , 0};
                 iIn += 2;
 
-                while(TRUE)
+                while(true)
                 {
                     ch = pszInput[iIn ++];
                     if (ch >= '0' && ch <= '9')
@@ -2223,7 +2299,7 @@ char *CPLUnescapeString( const char *pszInput, int *pnLength, int nScheme )
                 iIn --;
 
                 char * pszUTF8 = CPLRecodeFromWChar( anVal, "WCHAR_T", CPL_ENC_UTF8);
-                int nLen = strlen(pszUTF8);
+                int nLen = static_cast<int>(strlen(pszUTF8));
                 memcpy(pszOutput + iOut, pszUTF8, nLen);
                 CPLFree(pszUTF8);
                 iOut += nLen;
@@ -2232,17 +2308,18 @@ char *CPLUnescapeString( const char *pszInput, int *pnLength, int nScheme )
             {
                 /* illegal escape sequence */
                 CPLDebug( "CPL",
-                          "Error unescaping CPLES_XML text, '&' character followed by unhandled escape sequence." );
+                          "Error unescaping CPLES_XML text, '&' character "
+                          "followed by unhandled escape sequence." );
                 break;
             }
         }
     }
     else if( nScheme == CPLES_URL )
     {
-        for( iIn = 0; pszInput[iIn] != '\0'; iIn++ )
+        for( int iIn = 0; pszInput[iIn] != '\0'; ++iIn )
         {
-            if( pszInput[iIn] == '%' 
-                && pszInput[iIn+1] != '\0' 
+            if( pszInput[iIn] == '%'
+                && pszInput[iIn+1] != '\0'
                 && pszInput[iIn+2] != '\0' )
             {
                 int nHexChar = 0;
@@ -2254,10 +2331,10 @@ char *CPLUnescapeString( const char *pszInput, int *pnLength, int nScheme )
                 else if( pszInput[iIn+1] >= '0' && pszInput[iIn+1] <= '9' )
                     nHexChar += 16 * (pszInput[iIn+1] - '0');
                 else
-                    CPLDebug( "CPL", 
+                    CPLDebug( "CPL",
                               "Error unescaping CPLES_URL text, percent not "
                               "followed by two hex digits." );
-                    
+
                 if( pszInput[iIn+2] >= 'A' && pszInput[iIn+2] <= 'F' )
                     nHexChar += pszInput[iIn+2] - 'A' + 10;
                 else if( pszInput[iIn+2] >= 'a' && pszInput[iIn+2] <= 'f' )
@@ -2265,17 +2342,17 @@ char *CPLUnescapeString( const char *pszInput, int *pnLength, int nScheme )
                 else if( pszInput[iIn+2] >= '0' && pszInput[iIn+2] <= '9' )
                     nHexChar += pszInput[iIn+2] - '0';
                 else
-                    CPLDebug( "CPL", 
+                    CPLDebug( "CPL",
                               "Error unescaping CPLES_URL text, percent not "
                               "followed by two hex digits." );
 
-                pszOutput[iOut++] = (char) nHexChar;
+                pszOutput[iOut++] = static_cast<char>( nHexChar );
                 iIn += 2;
             }
             else if( pszInput[iIn] == '+' )
             {
                 pszOutput[iOut++] = ' ';
-            }   
+            }
             else
             {
                 pszOutput[iOut++] = pszInput[iIn];
@@ -2284,11 +2361,11 @@ char *CPLUnescapeString( const char *pszInput, int *pnLength, int nScheme )
     }
     else if( nScheme == CPLES_SQL )
     {
-        for( iIn = 0; pszInput[iIn] != '\0'; iIn++ )
+        for( int iIn = 0; pszInput[iIn] != '\0'; ++iIn )
         {
             if( pszInput[iIn] == '\'' && pszInput[iIn+1] == '\'' )
             {
-                iIn++;
+                ++iIn;
                 pszOutput[iOut++] = pszInput[iIn];
             }
             else
@@ -2297,25 +2374,15 @@ char *CPLUnescapeString( const char *pszInput, int *pnLength, int nScheme )
             }
         }
     }
-    else /* if( nScheme == CPLES_BackslashQuoteable ) */
+    else if( nScheme == CPLES_CSV )
     {
-        for( iIn = 0; pszInput[iIn] != '\0'; iIn++ )
-        {
-            if( pszInput[iIn] == '\\' )
-            {
-                iIn++;
-                if( pszInput[iIn] == 'n' )
-                    pszOutput[iOut++] = '\n';
-                else if( pszInput[iIn] == '0' )
-                    pszOutput[iOut++] = '\0';
-                else 
-                    pszOutput[iOut++] = pszInput[iIn];
-            }
-            else
-            {
-                pszOutput[iOut++] = pszInput[iIn];
-            }
-        }
+        CPLError( CE_Fatal, CPLE_NotSupported,
+                  "CSV Unescaping not yet implemented.");
+    }
+    else
+    {
+        CPLError( CE_Fatal, CPLE_NotSupported,
+                  "Unknown escaping style.");
     }
 
     pszOutput[iOut] = '\0';
@@ -2334,21 +2401,20 @@ char *CPLUnescapeString( const char *pszInput, int *pnLength, int nScheme )
  * Binary to hexadecimal translation.
  *
  * @param nBytes number of bytes of binary data in pabyData.
- * @param pabyData array of data bytes to translate. 
- * 
+ * @param pabyData array of data bytes to translate.
+ *
  * @return hexadecimal translation, zero terminated.  Free with CPLFree().
  */
 
 char *CPLBinaryToHex( int nBytes, const GByte *pabyData )
 
 {
-    char *pszHex = (char *) CPLMalloc(nBytes * 2 + 1 );
-    int i;
-    static const char achHex[] = "0123456789ABCDEF";
-
+    char *pszHex = reinterpret_cast<char *>( CPLMalloc(nBytes * 2 + 1 ) );
     pszHex[nBytes*2] = '\0';
 
-    for( i = 0; i < nBytes; i++ )
+    static const char achHex[] = "0123456789ABCDEF";
+
+    for( int i = 0; i < nBytes; ++i )
     {
         int nLow = pabyData[i] & 0x0f;
         int nHigh = (pabyData[i] & 0xf0) >> 4;
@@ -2400,26 +2466,22 @@ static const unsigned char hex2char[256] = {
 
 GByte *CPLHexToBinary( const char *pszHex, int *pnBytes )
 {
-    size_t  nHexLen = strlen(pszHex);
-    size_t i;
-    register unsigned char h1, h2;
-    GByte *pabyWKB; 
-
-    pabyWKB = (GByte *) CPLMalloc(nHexLen / 2 + 2);
-            
-    for( i = 0; i < nHexLen/2; i++ )
+    const size_t nHexLen = strlen(pszHex);
+
+    GByte *pabyWKB = static_cast<GByte *>( CPLMalloc(nHexLen / 2 + 2) );
+
+    for( size_t i = 0; i < nHexLen/2; ++i )
     {
-        h1 = hex2char[(int)pszHex[2*i]];
-        h2 = hex2char[(int)pszHex[2*i+1]];
+        unsigned char h1 = hex2char[static_cast<int>( pszHex[2*i] )];
+        unsigned char h2 = hex2char[static_cast<int>( pszHex[2*i+1] )];
 
         /* First character is high bits, second is low bits */
-        pabyWKB[i] = (GByte)((h1 << 4) | h2);
+        pabyWKB[i] = static_cast<GByte>( (h1 << 4) | h2 );
     }
     pabyWKB[nHexLen/2] = 0;
-    *pnBytes = nHexLen/2;
-    
-    return pabyWKB;
+    *pnBytes = static_cast<int>(nHexLen/2);
 
+    return pabyWKB;
 }
 
 /************************************************************************/
@@ -2559,12 +2621,13 @@ CPLValueType CPLGetValueType(const char* pszValue)
 \verbatim
 char szDest[5];
 if (CPLStrlcpy(szDest, "abcde", sizeof(szDest)) >= sizeof(szDest))
-    fprintf(stderr, "truncation occured !\n");
+    fprintf(stderr, "truncation occurred !\n");
 \endverbatim
 
  * @param pszDest   destination buffer
  * @param pszSrc    source string. Must be NUL terminated
- * @param nDestSize size of destination buffer (including space for the NUL terminator character)
+ * @param nDestSize size of destination buffer (including space for the NUL
+ *     terminator character)
  *
  * @return the length of the source string (=strlen(pszSrc))
  *
@@ -2572,19 +2635,19 @@ if (CPLStrlcpy(szDest, "abcde", sizeof(szDest)) >= sizeof(szDest))
  */
 size_t CPLStrlcpy(char* pszDest, const char* pszSrc, size_t nDestSize)
 {
-    char* pszDestIter = pszDest;
-    const char* pszSrcIter = pszSrc;
-
     if (nDestSize == 0)
         return strlen(pszSrc);
 
-    nDestSize --;
+    char* pszDestIter = pszDest;
+    const char* pszSrcIter = pszSrc;
+
+    --nDestSize;
     while(nDestSize != 0 && *pszSrcIter != '\0')
     {
         *pszDestIter = *pszSrcIter;
-        pszDestIter ++;
-        pszSrcIter ++;
-        nDestSize --;
+        ++pszDestIter;
+        ++pszSrcIter;
+        --nDestSize;
     }
     *pszDestIter = '\0';
     return pszSrcIter - pszSrc + strlen(pszSrcIter);
@@ -2611,16 +2674,19 @@ size_t CPLStrlcpy(char* pszDest, const char* pszSrc, size_t nDestSize)
 char szDest[5];
 CPLStrlcpy(szDest, "ab", sizeof(szDest));
 if (CPLStrlcat(szDest, "cde", sizeof(szDest)) >= sizeof(szDest))
-    fprintf(stderr, "truncation occured !\n");
+    fprintf(stderr, "truncation occurred !\n");
 \endverbatim
 
- * @param pszDest   destination buffer. Must be NUL terminated before running CPLStrlcat
+ * @param pszDest   destination buffer. Must be NUL terminated before
+ *         running CPLStrlcat
  * @param pszSrc    source string. Must be NUL terminated
- * @param nDestSize size of destination buffer (including space for the NUL terminator character)
+ * @param nDestSize size of destination buffer (including space for the
+ *         NUL terminator character)
  *
- * @return the thoretical length of the destination string after concatenation
+ * @return the theoretical length of the destination string after concatenation
  *         (=strlen(pszDest_before) + strlen(pszSrc)).
- *         If strlen(pszDest_before) >= nDestSize, then it returns nDestSize + strlen(pszSrc)
+ *         If strlen(pszDest_before) >= nDestSize, then it returns
+ *         nDestSize + strlen(pszSrc)
  *
  * @since GDAL 1.7.0
  */
@@ -2630,8 +2696,8 @@ size_t CPLStrlcat(char* pszDest, const char* pszSrc, size_t nDestSize)
 
     while(nDestSize != 0 && *pszDestIter != '\0')
     {
-        pszDestIter ++;
-        nDestSize --;
+        ++pszDestIter;
+        --nDestSize;
     }
 
     return pszDestIter - pszDest + CPLStrlcpy(pszDestIter, pszSrc, nDestSize);
@@ -2658,14 +2724,32 @@ size_t CPLStrlcat(char* pszDest, const char* pszSrc, size_t nDestSize)
  *
  * @since GDAL 1.7.0
  */
- 
+
 size_t CPLStrnlen (const char *pszStr, size_t nMaxLen)
 {
     size_t nLen = 0;
     while(nLen < nMaxLen && *pszStr != '\0')
     {
-        nLen ++;
-        pszStr ++;
+        ++nLen;
+        ++pszStr;
     }
     return nLen;
 }
+
+/************************************************************************/
+/*                            CSLParseCommandLine()                     */
+/************************************************************************/
+
+/**
+ * Tokenize command line arguments in a list of strings.
+ *
+ * @param pszCommandLine  command line
+ *
+ * @return NULL terminated list of strings to free with CSLDestroy()
+ *
+ * @since GDAL 2.1
+ */
+char CPL_DLL ** CSLParseCommandLine(const char* pszCommandLine)
+{
+    return CSLTokenizeString(pszCommandLine);
+}
diff --git a/port/cpl_string.h b/port/cpl_string.h
index 956352f..c57b467 100644
--- a/port/cpl_string.h
+++ b/port/cpl_string.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_string.h 28025 2014-11-28 00:01:32Z rouault $
+ * $Id: cpl_string.h 33788 2016-03-26 00:45:58Z goatbar $
  *
  * Name:     cpl_string.h
  * Project:  CPL - Common Portability Library
@@ -16,30 +16,30 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _CPL_STRING_H_INCLUDED
-#define _CPL_STRING_H_INCLUDED
+#ifndef CPL_STRING_H_INCLUDED
+#define CPL_STRING_H_INCLUDED
 
-#include "cpl_vsi.h"
 #include "cpl_error.h"
 #include "cpl_conv.h"
+#include "cpl_vsi.h"
 
 /**
  * \file cpl_string.h
  *
- * Various convenience functions for working with strings and string lists. 
+ * Various convenience functions for working with strings and string lists.
  *
  * A StringList is just an array of strings with the last pointer being
  * NULL.  An empty StringList may be either a NULL pointer, or a pointer to
@@ -48,7 +48,7 @@
  * A common convention for StringLists is to use them to store name/value
  * lists.  In this case the contents are treated like a dictionary of
  * name/value pairs.  The actual data is formatted with each string having
- * the format "<name>:<value>" (though "=" is also an acceptable separator). 
+ * the format "<name>:<value>" (though "=" is also an acceptable separator).
  * A number of the functions in the file operate on name/value style
  * string lists (such as CSLSetNameValue(), and CSLFetchNameValue()).
  *
@@ -60,19 +60,27 @@
 
 CPL_C_START
 
-char CPL_DLL **CSLAddString(char **papszStrList, const char *pszNewString) CPL_WARN_UNUSED_RESULT;
-int CPL_DLL CSLCount(char **papszStrList);
+char CPL_DLL **CSLAddString(char **papszStrList,
+                            const char *pszNewString) CPL_WARN_UNUSED_RESULT;
+char CPL_DLL **CSLAddStringMayFail(
+    char **papszStrList, const char *pszNewString) CPL_WARN_UNUSED_RESULT;
+#ifdef __cplusplus
+  int CPL_DLL CSLCount(const char * const *papszStrList);
+#else
+  int CPL_DLL CSLCount(char **papszStrList);
+#endif
 const char CPL_DLL *CSLGetField( char **, int );
 void CPL_DLL CPL_STDCALL CSLDestroy(char **papszStrList);
 char CPL_DLL **CSLDuplicate(char **papszStrList) CPL_WARN_UNUSED_RESULT;
-char CPL_DLL **CSLMerge( char **papszOrig, char **papszOverride ) CPL_WARN_UNUSED_RESULT;
+char CPL_DLL **CSLMerge( char **papszOrig,
+                         char **papszOverride ) CPL_WARN_UNUSED_RESULT;
 
 char CPL_DLL **CSLTokenizeString(const char *pszString ) CPL_WARN_UNUSED_RESULT;
-char CPL_DLL **CSLTokenizeStringComplex(const char *pszString,
+char CPL_DLL **CSLTokenizeStringComplex(
+    const char *pszString, const char *pszDelimiter, int bHonourStrings,
+    int bAllowEmptyTokens ) CPL_WARN_UNUSED_RESULT;
+char CPL_DLL **CSLTokenizeString2( const char *pszString,
                                    const char *pszDelimiter,
-                                   int bHonourStrings, int bAllowEmptyTokens ) CPL_WARN_UNUSED_RESULT;
-char CPL_DLL **CSLTokenizeString2( const char *pszString, 
-                                   const char *pszDelimeter, 
                                    int nCSLTFlags ) CPL_WARN_UNUSED_RESULT;
 
 #define CSLT_HONOURSTRINGS      0x0001
@@ -84,24 +92,46 @@ char CPL_DLL **CSLTokenizeString2( const char *pszString,
 
 int CPL_DLL CSLPrint(char **papszStrList, FILE *fpOut);
 char CPL_DLL **CSLLoad(const char *pszFname) CPL_WARN_UNUSED_RESULT;
-char CPL_DLL **CSLLoad2(const char *pszFname, int nMaxLines, int nMaxCols, char** papszOptions) CPL_WARN_UNUSED_RESULT;
+char CPL_DLL **CSLLoad2(const char *pszFname, int nMaxLines, int nMaxCols,
+                        char** papszOptions) CPL_WARN_UNUSED_RESULT;
 int CPL_DLL CSLSave(char **papszStrList, const char *pszFname);
 
-char CPL_DLL **CSLInsertStrings(char **papszStrList, int nInsertAtLineNo, 
+char CPL_DLL **CSLInsertStrings(char **papszStrList, int nInsertAtLineNo,
                          char **papszNewLines) CPL_WARN_UNUSED_RESULT;
-char CPL_DLL **CSLInsertString(char **papszStrList, int nInsertAtLineNo, 
+char CPL_DLL **CSLInsertString(char **papszStrList, int nInsertAtLineNo,
                                const char *pszNewLine) CPL_WARN_UNUSED_RESULT;
-char CPL_DLL **CSLRemoveStrings(char **papszStrList, int nFirstLineToDelete,
-                         int nNumToRemove, char ***ppapszRetStrings) CPL_WARN_UNUSED_RESULT;
+char CPL_DLL **CSLRemoveStrings(
+    char **papszStrList, int nFirstLineToDelete,
+    int nNumToRemove, char ***ppapszRetStrings) CPL_WARN_UNUSED_RESULT;
 int CPL_DLL CSLFindString( char **, const char * );
 int CPL_DLL CSLFindStringCaseSensitive( char **, const char * );
-int CPL_DLL CSLPartialFindString( char **papszHaystack, 
-	const char * pszNeedle );
+int CPL_DLL CSLPartialFindString( char **papszHaystack,
+                                  const char * pszNeedle );
 int CPL_DLL CSLFindName(char **papszStrList, const char *pszName);
-int CPL_DLL CSLTestBoolean( const char *pszValue );
-int CPL_DLL CSLFetchBoolean( char **papszStrList, const char *pszKey, 
+int CPL_DLL CSLFetchBoolean( char **papszStrList, const char *pszKey,
                              int bDefault );
 
+/* TODO: Deprecate CSLTestBoolean.  Remove in GDAL 3.x. */
+int CPL_DLL CSLTestBoolean( const char *pszValue );
+int CPL_DLL CPLTestBoolean( const char *pszValue );
+
+#ifdef __cplusplus
+#ifdef DO_NOT_USE_DEBUG_BOOL
+#define CPLTestBool(x) CPL_TO_BOOL(CPLTestBoolean(x))
+#else
+/* Prefer these for C++ code. */
+#ifdef DEBUG_BOOL
+extern "C++" {
+#endif
+bool CPL_DLL CPLTestBool( const char *pszValue );
+#ifdef DEBUG_BOOL
+}
+#endif
+#endif
+bool CPL_DLL CPLFetchBool( const char **papszStrList, const char *pszKey,
+                           bool bDefault );
+#endif  /* __cplusplus */
+
 const char CPL_DLL *
       CPLParseNameValue(const char *pszNameValue, char **ppszKey );
 const char CPL_DLL *
@@ -112,14 +142,18 @@ const char CPL_DLL *
 char CPL_DLL **
       CSLFetchNameValueMultiple(char **papszStrList, const char *pszName);
 char CPL_DLL **
-      CSLAddNameValue(char **papszStrList, 
-                      const char *pszName, const char *pszValue) CPL_WARN_UNUSED_RESULT;
+      CSLAddNameValue(char **papszStrList,
+                      const char *pszName,
+                      const char *pszValue) CPL_WARN_UNUSED_RESULT;
 char CPL_DLL **
-      CSLSetNameValue(char **papszStrList, 
-                      const char *pszName, const char *pszValue) CPL_WARN_UNUSED_RESULT;
-void CPL_DLL CSLSetNameValueSeparator( char ** papszStrList, 
+      CSLSetNameValue(char **papszStrList,
+                      const char *pszName,
+                      const char *pszValue) CPL_WARN_UNUSED_RESULT;
+void CPL_DLL CSLSetNameValueSeparator( char ** papszStrList,
                                        const char *pszSeparator );
 
+char CPL_DLL ** CSLParseCommandLine(const char* pszCommandLine);
+
 #define CPLES_BackslashQuotable 0
 #define CPLES_XML               1
 #define CPLES_URL               2
@@ -127,16 +161,19 @@ void CPL_DLL CSLSetNameValueSeparator( char ** papszStrList,
 #define CPLES_CSV               4
 #define CPLES_XML_BUT_QUOTES    5
 
-char CPL_DLL *CPLEscapeString( const char *pszString, int nLength, 
+char CPL_DLL *CPLEscapeString( const char *pszString, int nLength,
                                int nScheme ) CPL_WARN_UNUSED_RESULT;
 char CPL_DLL *CPLUnescapeString( const char *pszString, int *pnLength,
                                  int nScheme ) CPL_WARN_UNUSED_RESULT;
 
-char CPL_DLL *CPLBinaryToHex( int nBytes, const GByte *pabyData ) CPL_WARN_UNUSED_RESULT;
-GByte CPL_DLL *CPLHexToBinary( const char *pszHex, int *pnBytes ) CPL_WARN_UNUSED_RESULT;
+char CPL_DLL *CPLBinaryToHex( int nBytes,
+                              const GByte *pabyData ) CPL_WARN_UNUSED_RESULT;
+GByte CPL_DLL *CPLHexToBinary( const char *pszHex,
+                               int *pnBytes ) CPL_WARN_UNUSED_RESULT;
 
-char CPL_DLL *CPLBase64Encode( int nBytes, const GByte *pabyData ) CPL_WARN_UNUSED_RESULT;
-int CPL_DLL CPLBase64DecodeInPlace(GByte* pszBase64);
+char CPL_DLL *CPLBase64Encode( int nBytes,
+                               const GByte *pabyData ) CPL_WARN_UNUSED_RESULT;
+int CPL_DLL CPLBase64DecodeInPlace( GByte* pszBase64 );
 
 typedef enum
 {
@@ -149,20 +186,33 @@ CPLValueType CPL_DLL CPLGetValueType(const char* pszValue);
 
 size_t CPL_DLL CPLStrlcpy(char* pszDest, const char* pszSrc, size_t nDestSize);
 size_t CPL_DLL CPLStrlcat(char* pszDest, const char* pszSrc, size_t nDestSize);
-size_t CPL_DLL CPLStrnlen (const char *pszStr, size_t nMaxLen);
+size_t CPL_DLL CPLStrnlen(const char *pszStr, size_t nMaxLen);
 
 /* -------------------------------------------------------------------- */
-/*      Locale independant formatting functions.                        */
+/*      Locale independent formatting functions.                        */
 /* -------------------------------------------------------------------- */
-int CPL_DLL CPLvsnprintf(char *str, size_t size, const char* fmt, va_list args);
-int CPL_DLL CPLsnprintf(char *str, size_t size, const char* fmt, ...) CPL_PRINT_FUNC_FORMAT(3,4);
-int CPL_DLL CPLsprintf(char *str, const char* fmt, ...) CPL_PRINT_FUNC_FORMAT(2, 3);
+int CPL_DLL CPLvsnprintf(char *str, size_t size, const char* fmt,
+                         va_list args) CPL_PRINT_FUNC_FORMAT (3, 0);
+int CPL_DLL CPLsnprintf(char *str, size_t size,
+                        const char* fmt, ...) CPL_PRINT_FUNC_FORMAT(3,4);
+#if defined(GDAL_COMPILATION) && !defined(DONT_DEPRECATE_SPRINTF)
+int CPL_DLL CPLsprintf(char *str, const char* fmt, ...)
+    CPL_PRINT_FUNC_FORMAT(2, 3) CPL_WARN_DEPRECATED("Use CPLsnprintf instead");
+#else
+int CPL_DLL CPLsprintf(char *str, const char* fmt, ...)
+    CPL_PRINT_FUNC_FORMAT(2, 3);
+#endif
 int CPL_DLL CPLprintf(const char* fmt, ...) CPL_PRINT_FUNC_FORMAT(1, 2);
-int CPL_DLL CPLsscanf(const char* str, const char* fmt, ...); /* caution: only works with limited number of formats */
+/* caution: only works with limited number of formats */
+int CPL_DLL CPLsscanf(const char* str, const char* fmt, ...)
+    CPL_SCAN_FUNC_FORMAT(2, 3);
 
-const char CPL_DLL *CPLSPrintf(const char *fmt, ...) CPL_PRINT_FUNC_FORMAT(1, 2);
-char CPL_DLL **CSLAppendPrintf(char **papszStrList, const char *fmt, ...) CPL_PRINT_FUNC_FORMAT(2, 3) CPL_WARN_UNUSED_RESULT;
-int CPL_DLL CPLVASPrintf(char **buf, const char *fmt, va_list args );
+const char CPL_DLL *CPLSPrintf(const char *fmt, ...)
+    CPL_PRINT_FUNC_FORMAT(1, 2) CPL_WARN_UNUSED_RESULT;
+char CPL_DLL **CSLAppendPrintf(char **papszStrList, const char *fmt, ...)
+    CPL_PRINT_FUNC_FORMAT(2, 3) CPL_WARN_UNUSED_RESULT;
+int CPL_DLL CPLVASPrintf(char **buf, const char *fmt, va_list args )
+    CPL_PRINT_FUNC_FORMAT(2, 0);
 
 /* -------------------------------------------------------------------- */
 /*      RFC 23 character set conversion/recoding API (cpl_recode.cpp).  */
@@ -177,17 +227,19 @@ int CPL_DLL CPLVASPrintf(char **buf, const char *fmt, va_list args );
 
 int CPL_DLL  CPLEncodingCharSize( const char *pszEncoding );
 void CPL_DLL  CPLClearRecodeWarningFlags( void );
-char CPL_DLL *CPLRecode( const char *pszSource, 
-                         const char *pszSrcEncoding, 
-                         const char *pszDstEncoding ) CPL_WARN_UNUSED_RESULT;
-char CPL_DLL *CPLRecodeFromWChar( const wchar_t *pwszSource, 
-                                  const char *pszSrcEncoding, 
-                                  const char *pszDstEncoding ) CPL_WARN_UNUSED_RESULT;
-wchar_t CPL_DLL *CPLRecodeToWChar( const char *pszSource,
-                                   const char *pszSrcEncoding, 
-                                   const char *pszDstEncoding ) CPL_WARN_UNUSED_RESULT;
+char CPL_DLL *CPLRecode(
+    const char *pszSource, const char *pszSrcEncoding,
+    const char *pszDstEncoding ) CPL_WARN_UNUSED_RESULT CPL_RETURNS_NONNULL;
+char CPL_DLL *CPLRecodeFromWChar(
+    const wchar_t *pwszSource, const char *pszSrcEncoding,
+    const char *pszDstEncoding ) CPL_WARN_UNUSED_RESULT;
+wchar_t CPL_DLL *CPLRecodeToWChar(
+    const char *pszSource, const char *pszSrcEncoding,
+    const char *pszDstEncoding ) CPL_WARN_UNUSED_RESULT;
 int CPL_DLL CPLIsUTF8(const char* pabyData, int nLen);
-char CPL_DLL *CPLForceToASCII(const char* pabyData, int nLen, char chReplacementChar) CPL_WARN_UNUSED_RESULT;
+char CPL_DLL *CPLForceToASCII(
+    const char* pabyData, int nLen,
+    char chReplacementChar) CPL_WARN_UNUSED_RESULT;
 int CPL_DLL CPLStrlenUTF8(const char *pszUTF8Str);
 
 CPL_C_END
@@ -213,9 +265,9 @@ CPL_C_END
  * 1200 - VC++ 6.0
  * 1200-1202 - eVC++ 4.0
  */
-#if defined(_MSC_VER) 
-# if (_MSC_VER <= 1202) 
-#  define MSVC_OLD_STUPID_BEHAVIOUR 
+#if defined(_MSC_VER)
+# if (_MSC_VER <= 1202)
+#  define MSVC_OLD_STUPID_BEHAVIOUR
 # endif
 #endif
 
@@ -225,11 +277,6 @@ CPL_C_END
 # define gdal_std_string string
 #else
 # define gdal_std_string std::string
-#endif 
-
-/* Remove annoying warnings in Microsoft eVC++ and Microsoft Visual C++ */
-#if defined(WIN32CE)
-#  pragma warning(disable:4251 4275 4786)
 #endif
 
 //! Convenient string class based on std::string.
@@ -237,18 +284,17 @@ class CPL_DLL CPLString : public gdal_std_string
 {
 public:
 
-    
     CPLString(void) {}
     CPLString( const std::string &oStr ) : gdal_std_string( oStr ) {}
     CPLString( const char *pszStr ) : gdal_std_string( pszStr ) {}
-    
+
     operator const char* (void) const { return c_str(); }
 
     char& operator[](std::string::size_type i)
     {
         return gdal_std_string::operator[](i);
     }
-    
+
     const char& operator[](std::string::size_type i) const
     {
         return gdal_std_string::operator[](i);
@@ -256,18 +302,20 @@ public:
 
     char& operator[](int i)
     {
-        return gdal_std_string::operator[](static_cast<std::string::size_type>(i));
+        return gdal_std_string::operator[](
+            static_cast<std::string::size_type>(i));
     }
 
     const char& operator[](int i) const
     {
-        return gdal_std_string::operator[](static_cast<std::string::size_type>(i));
+        return gdal_std_string::operator[](
+            static_cast<std::string::size_type>(i));
     }
 
     void Clear() { resize(0); }
 
     // NULL safe assign and free.
-    void Seize(char *pszValue) 
+    void Seize(char *pszValue)
     {
         if (pszValue == NULL )
             Clear();
@@ -278,9 +326,12 @@ public:
         }
     }
 
-    /* There seems to be a bug in the way the compiler count indices... Should be CPL_PRINT_FUNC_FORMAT (1, 2) */
-    CPLString &Printf( const char *pszFormat, ... ) CPL_PRINT_FUNC_FORMAT (2, 3);
-    CPLString &vPrintf( const char *pszFormat, va_list args );
+    /* There seems to be a bug in the way the compiler count indices...
+     * Should be CPL_PRINT_FUNC_FORMAT (1, 2) */
+    CPLString &Printf(
+        const char *pszFormat, ... ) CPL_PRINT_FUNC_FORMAT (2, 3);
+    CPLString &vPrintf(
+        const char *pszFormat, va_list args ) CPL_PRINT_FUNC_FORMAT(2, 0);
     CPLString &FormatC( double dfValue, const char *pszFormat = NULL );
     CPLString &Trim();
     CPLString &Recode( const char *pszSrcEncoding, const char *pszDstEncoding );
@@ -293,7 +344,8 @@ public:
 };
 
 CPLString CPLOPrintf(const char *pszFormat, ... ) CPL_PRINT_FUNC_FORMAT (1, 2);
-CPLString CPLOvPrintf(const char *pszFormat, va_list args);
+CPLString CPLOvPrintf(
+    const char *pszFormat, va_list args) CPL_PRINT_FUNC_FORMAT (1, 0);
 
 /* -------------------------------------------------------------------- */
 /*      URL processing functions, here since they depend on CPLString.  */
@@ -312,14 +364,14 @@ class CPL_DLL CPLStringList
     char **papszList;
     mutable int nCount;
     mutable int nAllocation;
-    int    bOwnList;
-    int    bIsSorted;
+    bool   bOwnList;
+    bool   bIsSorted;
 
     void   Initialize();
     void   MakeOurOwnCopy();
     void   EnsureAllocation( int nMaxLength );
     int    FindSortedInsertionPoint( const char *pszLine );
-    
+
   public:
     CPLStringList();
     CPLStringList( char **papszList, int bTakeOwnership=TRUE );
@@ -337,30 +389,35 @@ class CPL_DLL CPLStringList
     CPLStringList &InsertString( int nInsertAtLineNo, const char *pszNewLine )
     { return InsertStringDirectly( nInsertAtLineNo, CPLStrdup(pszNewLine) ); }
     CPLStringList &InsertStringDirectly( int nInsertAtLineNo, char *pszNewLine);
-    
-//    CPLStringList &InsertStrings( int nInsertAtLineNo, char **papszNewLines );
-//    CPLStringList &RemoveStrings( int nFirstLineToDelete, int nNumToRemove=1 );
-    
+
+    // CPLStringList &InsertStrings( int nInsertAtLineNo, char **papszNewLines );
+    // CPLStringList &RemoveStrings( int nFirstLineToDelete, int nNumToRemove=1 );
+
     int    FindString( const char *pszTarget ) const
     { return CSLFindString( papszList, pszTarget ); }
     int    PartialFindString( const char *pszNeedle ) const
     { return CSLPartialFindString( papszList, pszNeedle ); }
 
     int    FindName( const char *pszName ) const;
+    bool   FetchBool( const char *pszKey, bool bDefault ) const;
+    // Deprecated.
     int    FetchBoolean( const char *pszKey, int bDefault ) const;
     const char *FetchNameValue( const char *pszKey ) const;
-    const char *FetchNameValueDef( const char *pszKey, const char *pszDefault ) const;
+    const char *FetchNameValueDef(
+        const char *pszKey, const char *pszDefault ) const;
     CPLStringList &AddNameValue( const char *pszKey, const char *pszValue );
     CPLStringList &SetNameValue( const char *pszKey, const char *pszValue );
 
     CPLStringList &Assign( char **papszListIn, int bTakeOwnership=TRUE );
-    CPLStringList &operator=(char **papszListIn) { return Assign( papszListIn, TRUE ); }
+    CPLStringList &operator=(char **papszListIn) {
+      return Assign( papszListIn, TRUE ); }
     CPLStringList &operator=(const CPLStringList& oOther);
 
     char * operator[](int i);
-    char * operator[](size_t i) { return (*this)[(int)i]; }
+    char * operator[](size_t i) { return (*this)[static_cast<int>(i)]; }
     const char * operator[](int i) const;
-    const char * operator[](size_t i) const { return (*this)[(int)i]; }
+    const char * operator[](size_t i) const {
+      return (*this)[static_cast<int>(i)]; }
 
     char **List() { return papszList; }
     char **StealList();
@@ -373,4 +430,4 @@ class CPL_DLL CPLStringList
 
 #endif /* def __cplusplus && !CPL_SUPRESS_CPLUSPLUS */
 
-#endif /* _CPL_STRING_H_INCLUDED */
+#endif /* CPL_STRING_H_INCLUDED */
diff --git a/port/cpl_strtod.cpp b/port/cpl_strtod.cpp
index a077e63..a0e6b50 100644
--- a/port/cpl_strtod.cpp
+++ b/port/cpl_strtod.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_strtod.cpp 29252 2015-05-26 10:00:08Z rouault $
+ * $Id: cpl_strtod.cpp 33679 2016-03-07 22:02:50Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Functions to convert ASCII string to floating point number.
@@ -29,12 +29,14 @@
  ****************************************************************************/
 
 #include <locale.h>
-#include <errno.h>
-#include <stdlib.h>
+
+#include <cerrno>
+#include <cstdlib>
+#include <limits>
 
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: cpl_strtod.cpp 29252 2015-05-26 10:00:08Z rouault $");
+CPL_CVSID("$Id: cpl_strtod.cpp 33679 2016-03-07 22:02:50Z goatbar $");
 
 // XXX: with GCC 2.95 strtof() function is only available when in c99 mode.
 // Fix it here not touching the compiler options.
@@ -44,40 +46,6 @@ extern float strtof(const char *nptr, char **endptr);
 }
 #endif
 
-#ifndef NAN
-#  ifdef HUGE_VAL
-#    define NAN (HUGE_VAL * 0.0)
-#  else
-
-static float CPLNaN(void)
-{
-    float fNan;
-    int nNan = 0x7FC00000;
-    memcpy(&fNan, &nNan, 4);
-    return fNan;
-}
-
-#    define NAN CPLNan()
-#  endif
-#endif
-
-#ifndef INFINITY
-    static CPL_INLINE double CPLInfinity(void)
-    {
-        static double ZERO = 0;
-        return 1.0 / ZERO; /* MSVC doesn't like 1.0 / 0.0 */
-    }
-    #define INFINITY CPLInfinity()
-    static CPL_INLINE double CPLNegInfinity(void)
-    {
-        static double ZERO = 0;
-        return -1.0 / ZERO; /* MSVC doesn't like -1.0 / 0.0 */
-    }
-    #define NEG_INFINITY CPLNegInfinity()
-#else
-    #define NEG_INFINITY (-INFINITY)
-#endif
-
 /************************************************************************/
 /*                            CPLAtofDelim()                            */
 /************************************************************************/
@@ -102,7 +70,7 @@ static float CPLNaN(void)
  */
 double CPLAtofDelim(const char *nptr, char point)
 {
-  return CPLStrtodDelim(nptr, 0, point);
+  return CPLStrtodDelim(nptr, NULL, point);
 }
 
 /************************************************************************/
@@ -144,7 +112,7 @@ double CPLAtofDelim(const char *nptr, char point)
  */
 double CPLAtof(const char *nptr)
 {
-  return CPLStrtod(nptr, 0);
+  return CPLStrtod(nptr, NULL);
 }
 
 /************************************************************************/
@@ -157,9 +125,9 @@ double CPLAtof(const char *nptr)
  * This function converts the initial portion of the string pointed to
  * by nptr to double floating point representation. This function does the
  * same as standard atof(), but it allows a variety of locale representations.
- * That is it supports numeric values with either a comma or a period for 
- * the decimal delimiter. 
- * 
+ * That is it supports numeric values with either a comma or a period for
+ * the decimal delimiter.
+ *
  * PS. The M stands for Multi-lingual.
  *
  * @param nptr The string to convert.
@@ -170,18 +138,17 @@ double CPLAtof(const char *nptr)
 double CPLAtofM( const char *nptr )
 
 {
-    int i;
-    const static int nMaxSearch = 50;
+    const int nMaxSearch = 50;
 
-    for( i = 0; i < nMaxSearch; i++ )
+    for( int i = 0; i < nMaxSearch; i++ )
     {
         if( nptr[i] == ',' )
-            return CPLStrtodDelim( nptr, 0, ',' );
-        else if( nptr[i] == '.' || nptr[i] == '\0' )
-            return CPLStrtodDelim( nptr, 0, '.' );
+            return CPLStrtodDelim( nptr, NULL, ',' );
+        if( nptr[i] == '.' || nptr[i] == '\0' )
+            return CPLStrtodDelim( nptr, NULL, '.' );
     }
 
-    return CPLStrtodDelim( nptr, 0, '.' );
+    return CPLStrtodDelim( nptr, NULL, '.' );
 }
 
 /************************************************************************/
@@ -190,12 +157,12 @@ double CPLAtofM( const char *nptr )
 
 static char* CPLReplacePointByLocalePoint(const char* pszNumber, char point)
 {
-#if defined(WIN32CE) || defined(__ANDROID__)
+#if defined(__ANDROID__)
     static char byPoint = 0;
     if (byPoint == 0)
     {
         char szBuf[16];
-        sprintf(szBuf, "%.1f", 1.0);
+        snprintf(szBuf, sizeof(szBuf), "%.1f", 1.0);
         byPoint = szBuf[1];
     }
     if (point != byPoint)
@@ -208,13 +175,13 @@ static char* CPLReplacePointByLocalePoint(const char* pszNumber, char point)
             return pszNew;
         }
     }
-#else
+#else  // ndef __ANDROID__
     struct lconv *poLconv = localeconv();
     if ( poLconv
          && poLconv->decimal_point
          && poLconv->decimal_point[0] != '\0' )
     {
-        char    byPoint = poLconv->decimal_point[0];
+        char byPoint = poLconv->decimal_point[0];
 
         if (point != byPoint)
         {
@@ -231,8 +198,9 @@ static char* CPLReplacePointByLocalePoint(const char* pszNumber, char point)
             }
         }
     }
-#endif
-    return (char*) pszNumber;
+#endif  // __ANDROID__
+
+    return const_cast<char*>( pszNumber );
 }
 
 /************************************************************************/
@@ -267,14 +235,17 @@ double CPLStrtodDelim(const char *nptr, char **endptr, char point)
             strcmp(nptr, "-1.#IND") == 0)
         {
             if( endptr ) *endptr = (char*)nptr + strlen(nptr);
-            return NAN;
+            // While it is possible on some platforms to flip the sign
+            // of NAN to negative, this function will always return a positive
+            // quiet (non-signalling) NaN.
+            return std::numeric_limits<double>::quiet_NaN();
         }
 
         if (strcmp(nptr,"-inf") == 0 ||
-            EQUALN (nptr,"-1.#INF",strlen("-1.#INF")))
+            STARTS_WITH_CI(nptr, "-1.#INF"))
         {
             if( endptr ) *endptr = (char*)nptr + strlen(nptr);
-            return NEG_INFINITY;
+            return -std::numeric_limits<double>::infinity();
         }
     }
     else if (nptr[0] == '1')
@@ -282,23 +253,23 @@ double CPLStrtodDelim(const char *nptr, char **endptr, char point)
         if (strcmp(nptr, "1.#QNAN") == 0)
         {
             if( endptr ) *endptr = (char*)nptr + strlen(nptr);
-            return NAN;
+            return std::numeric_limits<double>::quiet_NaN();
         }
-        if( EQUALN (nptr,"1.#INF",strlen("1.#INF")) )
+        if( STARTS_WITH_CI(nptr, "1.#INF") )
         {
             if( endptr ) *endptr = (char*)nptr + strlen(nptr);
-            return INFINITY;
+            return std::numeric_limits<double>::infinity();
         }
     }
     else if (nptr[0] == 'i' && strcmp(nptr,"inf") == 0)
     {
         if( endptr ) *endptr = (char*)nptr + strlen(nptr);
-        return INFINITY;
+        return std::numeric_limits<double>::infinity();
     }
     else if (nptr[0] == 'n' && strcmp(nptr,"nan") == 0)
     {
         if( endptr ) *endptr = (char*)nptr + strlen(nptr);
-        return NAN;
+        return std::numeric_limits<double>::quiet_NaN();
     }
 
 /* -------------------------------------------------------------------- */
@@ -307,13 +278,10 @@ double CPLStrtodDelim(const char *nptr, char **endptr, char point)
 /*  with the one, taken from locale settings and use standard strtod()  */
 /*  on that buffer.                                                     */
 /* -------------------------------------------------------------------- */
-    double      dfValue;
-    int         nError;
-
-    char*       pszNumber = CPLReplacePointByLocalePoint(nptr, point);
+    char* pszNumber = CPLReplacePointByLocalePoint(nptr, point);
 
-    dfValue = strtod( pszNumber, endptr );
-    nError = errno;
+    const double dfValue = strtod( pszNumber, endptr );
+    const int nError = errno;
 
     if ( endptr )
         *endptr = (char *)nptr + (*endptr - pszNumber);
@@ -381,19 +349,14 @@ float CPLStrtofDelim(const char *nptr, char **endptr, char point)
 /*  with the one, taken from locale settings and use standard strtof()  */
 /*  on that buffer.                                                     */
 /* -------------------------------------------------------------------- */
-
-    double      dfValue;
-    int         nError;
-
-    char*       pszNumber = CPLReplacePointByLocalePoint(nptr, point);
-
-    dfValue = strtof( pszNumber, endptr );
-    nError = errno;
+    char * const pszNumber = CPLReplacePointByLocalePoint(nptr, point);
+    double dfValue = strtof( pszNumber, endptr );
+    const int nError = errno;
 
     if ( endptr )
-        *endptr = (char *)nptr + (*endptr - pszNumber);
+        *endptr = const_cast<char *>(nptr) + (*endptr - pszNumber);
 
-    if (pszNumber != (char*) nptr)
+    if (pszNumber != nptr)
         CPLFree( pszNumber );
 
     errno = nError;
@@ -401,9 +364,9 @@ float CPLStrtofDelim(const char *nptr, char **endptr, char point)
 
 #else
 
-    return (float)CPLStrtodDelim(nptr, endptr, point);
+    return static_cast<float>( CPLStrtodDelim(nptr, endptr, point) );
 
-#endif /* HAVE_STRTOF */
+#endif  // HAVE_STRTOF
 }
 
 /************************************************************************/
@@ -431,5 +394,3 @@ float CPLStrtof(const char *nptr, char **endptr)
 {
     return CPLStrtofDelim(nptr, endptr, '.');
 }
-
-/* END OF FILE */
diff --git a/port/cpl_time.cpp b/port/cpl_time.cpp
index 713cff9..d7e0131 100644
--- a/port/cpl_time.cpp
+++ b/port/cpl_time.cpp
@@ -1,153 +1,180 @@
-/**********************************************************************
- * $Id: cpl_time.cpp 18063 2009-11-21 21:11:49Z warmerdam $
- *
- * Name:     cpl_time.cpp
- * Project:  CPL - Common Portability Library
- * Purpose:  Time functions.
- * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
- *
- **********************************************************************
- *
- * CPLUnixTimeToYMDHMS() is derived from timesub() in localtime.c from openbsd/freebsd/netbsd.
- * CPLYMDHMSToUnixTime() has been implemented by Even Rouault and is in the public domain
- *
- * Cf http://svn.freebsd.org/viewvc/base/stable/7/lib/libc/stdtime/localtime.c?revision=178142&view=markup
- * localtime.c comes with the following header :
- *
- * This file is in the public domain, so clarified as of
- * 1996-06-05 by Arthur David Olson (arthur_david_olson at nih.gov).
- */
-
-#include "cpl_time.h"
-
-#define SECSPERMIN      60L
-#define MINSPERHOUR     60L
-#define HOURSPERDAY     24L
-#define SECSPERHOUR     (SECSPERMIN * MINSPERHOUR)
-#define SECSPERDAY      (SECSPERHOUR * HOURSPERDAY)
-#define DAYSPERWEEK     7
-#define MONSPERYEAR     12
-
-#define EPOCH_YEAR      1970
-#define EPOCH_WDAY      4
-#define TM_YEAR_BASE    1900
-#define DAYSPERNYEAR    365
-#define DAYSPERLYEAR    366
-
-#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
-#define LEAPS_THRU_END_OF(y)	((y) / 4 - (y) / 100 + (y) / 400)
-
-static const int mon_lengths[2][MONSPERYEAR] = {
-  {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
-  {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
-} ;
-
-
-static const int	year_lengths[2] = {
-	DAYSPERNYEAR, DAYSPERLYEAR
-};
-
-/************************************************************************/
-/*                   CPLUnixTimeToYMDHMS()                              */
-/************************************************************************/
-
-/** Converts a time value since the Epoch (aka "unix" time) to a broken-down UTC time.
- *
- * This function is similar to gmtime_r().
- * This function will always set tm_isdst to 0.
- *
- * @param unixTime number of seconds since the Epoch.
- * @param pRet address of the return structure.
- *
- * @return the structure pointed by pRet filled with a broken-down UTC time.
- */
-
-struct tm * CPLUnixTimeToYMDHMS(GIntBig unixTime, struct tm* pRet)
-{
-    GIntBig days = unixTime / SECSPERDAY;
-    GIntBig rem = unixTime % SECSPERDAY;
-    
-    while (rem < 0) {
-        rem += SECSPERDAY;
-        --days;
-    }
-    
-    pRet->tm_hour = (int) (rem / SECSPERHOUR);
-    rem = rem % SECSPERHOUR;
-    pRet->tm_min = (int) (rem / SECSPERMIN);
-    /*
-    ** A positive leap second requires a special
-    ** representation.  This uses "... ??:59:60" et seq.
-    */
-    pRet->tm_sec = (int) (rem % SECSPERMIN);
-    pRet->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
-    if (pRet->tm_wday < 0)
-        pRet->tm_wday += DAYSPERWEEK;
-    GIntBig y = EPOCH_YEAR;
-    int yleap;
-    while (days < 0 || days >= (GIntBig) year_lengths[yleap = isleap(y)])
-    {
-        GIntBig	newy;
-
-        newy = y + days / DAYSPERNYEAR;
-        if (days < 0)
-            --newy;
-        days -= (newy - y) * DAYSPERNYEAR +
-            LEAPS_THRU_END_OF(newy - 1) -
-            LEAPS_THRU_END_OF(y - 1);
-        y = newy;
-    }
-    pRet->tm_year = (int) (y - TM_YEAR_BASE);
-    pRet->tm_yday = (int) days;
-    const int* ip = mon_lengths[yleap];
-    for (pRet->tm_mon = 0; days >= (GIntBig) ip[pRet->tm_mon]; ++(pRet->tm_mon))
-        days = days - (GIntBig) ip[pRet->tm_mon];
-    pRet->tm_mday = (int) (days + 1);
-    pRet->tm_isdst = 0;
-    
-    return pRet;
-}
-
-/************************************************************************/
-/*                      CPLYMDHMSToUnixTime()                           */
-/************************************************************************/
-
-/** Converts a broken-down UTC time into time since the Epoch (aka "unix" time).
- *
- * This function is similar to mktime(), but the passed structure is not modified.
- * This function ignores the tm_wday, tm_yday and tm_isdst fields of the passed value.
- * No timezone shift will be applied. This function returns 0 for the 1/1/1970 00:00:00
- *
- * @param brokendowntime broken-downtime UTC time.
- *
- * @return a number of seconds since the Epoch encoded as a value of type GIntBig,
- *         or -1 if the time cannot be represented.
- */
-
-GIntBig CPLYMDHMSToUnixTime(const struct tm *brokendowntime)
-{
-  GIntBig days;
-  int mon;
-  
-  if (brokendowntime->tm_mon < 0 || brokendowntime->tm_mon >= 12)
-    return -1;
-    
-  /* Number of days of the current month */
-  days = brokendowntime->tm_mday - 1;
-  
-  /* Add the number of days of the current year */
-  const int* ip = mon_lengths[isleap(TM_YEAR_BASE + brokendowntime->tm_year)];
-  for(mon=0;mon<brokendowntime->tm_mon;mon++)
-      days += ip [mon];
-
-  /* Add the number of days of the other years */
-  days += (TM_YEAR_BASE + (GIntBig)brokendowntime->tm_year - EPOCH_YEAR) * DAYSPERNYEAR +
-          LEAPS_THRU_END_OF(TM_YEAR_BASE + (GIntBig)brokendowntime->tm_year - 1) -
-          LEAPS_THRU_END_OF(EPOCH_YEAR - 1);
-
-  /* Now add the secondes, minutes and hours to the number of days since EPOCH */
-  return brokendowntime->tm_sec +
-         brokendowntime->tm_min * SECSPERMIN +
-         brokendowntime->tm_hour * SECSPERHOUR +
-         days * SECSPERDAY;
-}
+
+/**********************************************************************
+ * $Id: cpl_time.cpp 33783 2016-03-24 13:45:22Z goatbar $
+ *
+ * Name:     cpl_time.cpp
+ * Project:  CPL - Common Portability Library
+ * Purpose:  Time functions.
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ **********************************************************************
+ *
+ * CPLUnixTimeToYMDHMS() is derived from timesub() in localtime.c from
+ * openbsd/freebsd/netbsd.
+ *
+ * CPLYMDHMSToUnixTime() has been implemented by Even Rouault and is in the
+ * public domain.
+ *
+ * c.f. http://svn.freebsd.org/viewvc/base/stable/7/lib/libc/stdtime/localtime.c?revision=178142&view=markup
+ * localtime.c comes with the following header :
+ *
+ * This file is in the public domain, so clarified as of
+ * 1996-06-05 by Arthur David Olson (arthur_david_olson at nih.gov).
+ */
+
+#include "cpl_time.h"
+#include "cpl_error.h"
+
+static const int SECSPERMIN = 60;
+static const int MINSPERHOUR = 60;
+static const int HOURSPERDAY = 24;
+static const int SECSPERHOUR = SECSPERMIN * MINSPERHOUR;
+static const int SECSPERDAY = SECSPERHOUR * HOURSPERDAY;
+static const int DAYSPERWEEK = 7;
+static const int MONSPERYEAR = 12;
+
+static const int EPOCH_YEAR = 1970;
+static const int EPOCH_WDAY = 4;
+static const int TM_YEAR_BASE = 1900;
+static const int DAYSPERNYEAR = 365;
+static const int DAYSPERLYEAR = 366;
+
+static bool isleap(int y) {
+  return ((y % 4) == 0 && (y % 100) != 0) || (y % 400) == 0;
+}
+
+static int LEAPS_THROUGH_END_OF(int y) {
+  return y / 4 - y / 100 + y / 400;
+}
+
+static const int mon_lengths[2][MONSPERYEAR] = {
+  {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
+  {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
+} ;
+
+static const int year_lengths[2] = { DAYSPERNYEAR, DAYSPERLYEAR };
+
+/************************************************************************/
+/*                   CPLUnixTimeToYMDHMS()                              */
+/************************************************************************/
+
+/** Converts a time value since the Epoch (aka "unix" time) to a broken-down
+ *  UTC time.
+ *
+ * This function is similar to gmtime_r().
+ * This function will always set tm_isdst to 0.
+ *
+ * @param unixTime number of seconds since the Epoch.
+ * @param pRet address of the return structure.
+ *
+ * @return the structure pointed by pRet filled with a broken-down UTC time.
+ */
+
+struct tm * CPLUnixTimeToYMDHMS(GIntBig unixTime, struct tm* pRet)
+{
+    GIntBig days = unixTime / SECSPERDAY;
+    GIntBig rem = unixTime % SECSPERDAY;
+
+    if( unixTime < -(GIntBig)10000 * SECSPERDAY * DAYSPERLYEAR ||
+        unixTime > (GIntBig)10000 * SECSPERDAY * DAYSPERLYEAR )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Invalid unixTime = " CPL_FRMT_GIB,
+                 unixTime);
+        memset(pRet, 0, sizeof(*pRet));
+        return pRet;
+    }
+
+    while (rem < 0) {
+        rem += SECSPERDAY;
+        --days;
+    }
+
+    pRet->tm_hour = static_cast<int>( rem / SECSPERHOUR );
+    rem = rem % SECSPERHOUR;
+    pRet->tm_min = static_cast<int>( rem / SECSPERMIN );
+    /*
+    ** A positive leap second requires a special
+    ** representation.  This uses "... ??:59:60" et seq.
+    */
+    pRet->tm_sec = static_cast<int>( rem % SECSPERMIN );
+    pRet->tm_wday = static_cast<int>( (EPOCH_WDAY + days) % DAYSPERWEEK );
+    if (pRet->tm_wday < 0)
+        pRet->tm_wday += DAYSPERWEEK;
+
+    int y = EPOCH_YEAR;
+    int yleap = 0;
+    while ( days < 0
+            || days >= static_cast<GIntBig>( year_lengths[yleap = isleap(y)] ) )
+    {
+        int newy = y + static_cast<int>( days / DAYSPERNYEAR );
+        if (days < 0)
+            --newy;
+        days -= (newy - y) * DAYSPERNYEAR +
+            LEAPS_THROUGH_END_OF(newy - 1) -
+            LEAPS_THROUGH_END_OF(y - 1);
+        y = newy;
+    }
+
+    pRet->tm_year = static_cast<int>( y - TM_YEAR_BASE );
+    pRet->tm_yday = static_cast<int>( days );
+    const int* ip = mon_lengths[yleap];
+
+    for (pRet->tm_mon = 0;
+         days >= static_cast<GIntBig>( ip[pRet->tm_mon] );
+         ++(pRet->tm_mon) )
+        days = days - static_cast<GIntBig>( ip[pRet->tm_mon] );
+
+    pRet->tm_mday = static_cast<int>( (days + 1) );
+    pRet->tm_isdst = 0;
+
+    return pRet;
+}
+
+/************************************************************************/
+/*                      CPLYMDHMSToUnixTime()                           */
+/************************************************************************/
+
+/** Converts a broken-down UTC time into time since the Epoch (aka "unix" time).
+ *
+ * This function is similar to mktime(), but the passed structure is not
+ * modified.  This function ignores the tm_wday, tm_yday and tm_isdst fields of
+ * the passed value.  No timezone shift will be applied. This function
+ * returns 0 for the 1/1/1970 00:00:00
+ *
+ * @param brokendowntime broken-downtime UTC time.
+ *
+ * @return a number of seconds since the Epoch encoded as a value of type
+ *         GIntBig, or -1 if the time cannot be represented.
+ */
+
+GIntBig CPLYMDHMSToUnixTime(const struct tm *brokendowntime)
+{
+
+  if (brokendowntime->tm_mon < 0 || brokendowntime->tm_mon >= 12)
+    return -1;
+
+  /* Number of days of the current month */
+  GIntBig days = brokendowntime->tm_mday - 1;
+
+  /* Add the number of days of the current year */
+  const int* ip = mon_lengths[static_cast<int>(isleap(TM_YEAR_BASE + brokendowntime->tm_year))];
+  for( int mon = 0; mon < brokendowntime->tm_mon; mon++ )
+      days += ip[mon];
+
+  /* Add the number of days of the other years */
+  days +=
+      ( TM_YEAR_BASE
+        + static_cast<GIntBig>( brokendowntime->tm_year )
+        - EPOCH_YEAR ) * DAYSPERNYEAR
+      + LEAPS_THROUGH_END_OF( static_cast<int> (TM_YEAR_BASE )
+                           + static_cast<int>( brokendowntime->tm_year )
+                           - static_cast<int>( 1 ) )
+      - LEAPS_THROUGH_END_OF( EPOCH_YEAR - 1 );
+
+  /* Now add the secondes, minutes and hours to the number of days since EPOCH */
+  return brokendowntime->tm_sec +
+         brokendowntime->tm_min * SECSPERMIN +
+         brokendowntime->tm_hour * SECSPERHOUR +
+         days * SECSPERDAY;
+}
diff --git a/port/cpl_time.h b/port/cpl_time.h
index 7db61a0..7b57f4a 100644
--- a/port/cpl_time.h
+++ b/port/cpl_time.h
@@ -1,41 +1,41 @@
-/**********************************************************************
- * $Id: cpl_time.h 29469 2015-07-04 11:42:30Z rouault $
- *
- * Name:     cpl_time.h
- * Project:  CPL - Common Portability Library
- * Purpose:  Time functions.
- * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
- *
- **********************************************************************
- * Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- * 
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#ifndef _CPL_TIME_H_INCLUDED
-#define _CPL_TIME_H_INCLUDED
-
-#include <time.h>
-
-#include "cpl_port.h"
-
-struct tm CPL_DLL * CPLUnixTimeToYMDHMS(GIntBig unixTime, struct tm* pRet);
-GIntBig CPL_DLL CPLYMDHMSToUnixTime(const struct tm *brokendowntime);
-
-#endif // _CPL_TIME_H_INCLUDED
+/**********************************************************************
+ * $Id: cpl_time.h 33783 2016-03-24 13:45:22Z goatbar $
+ *
+ * Name:     cpl_time.h
+ * Project:  CPL - Common Portability Library
+ * Purpose:  Time functions.
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ **********************************************************************
+ * Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef CPL_TIME_H_INCLUDED
+#define CPL_TIME_H_INCLUDED
+
+#include <time.h>
+
+#include "cpl_port.h"
+
+struct tm CPL_DLL * CPLUnixTimeToYMDHMS(GIntBig unixTime, struct tm* pRet);
+GIntBig CPL_DLL CPLYMDHMSToUnixTime(const struct tm *brokendowntime);
+
+#endif // CPL_TIME_H_INCLUDED
diff --git a/port/cpl_virtualmem.cpp b/port/cpl_virtualmem.cpp
index 3af2010..e230499 100644
--- a/port/cpl_virtualmem.cpp
+++ b/port/cpl_virtualmem.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_virtualmem.cpp 29330 2015-06-14 12:11:11Z rouault $
+ * $Id: cpl_virtualmem.cpp 33724 2016-03-16 17:14:11Z goatbar $
  *
  * Name:     cpl_virtualmem.cpp
  * Project:  CPL - Common Portability Library
@@ -15,16 +15,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
@@ -32,28 +32,78 @@
 #define _GNU_SOURCE
 #endif
 
+// to have off_t on 64bit possibly
+#ifndef _FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 64
+#endif
+
 #include "cpl_virtualmem.h"
 #include "cpl_error.h"
 #include "cpl_multiproc.h"
 #include "cpl_atomic_ops.h"
 #include "cpl_conv.h"
 
+#include <cassert>
+
+#ifdef NDEBUG
+/* Non NDEBUG: we ignore the result */
+#define IGNORE_OR_ASSERT_IN_DEBUG(expr) CPL_IGNORE_RET_VAL((expr))
+#else
+/* Debug: assert */
+#define IGNORE_OR_ASSERT_IN_DEBUG(expr) assert((expr))
+#endif
+
 #if defined(__linux) && defined(CPL_MULTIPROC_PTHREAD)
+#define HAVE_VIRTUAL_MEM_VMA
+#endif
 
+#if defined(HAVE_MMAP) || defined(HAVE_VIRTUAL_MEM_VMA)
+#include <unistd.h>     /* read, write, close, pipe, sysconf */
 #include <sys/mman.h>   /* mmap, munmap, mremap */
+#endif
+
+typedef enum
+{
+    VIRTUAL_MEM_TYPE_FILE_MEMORY_MAPPED,
+    VIRTUAL_MEM_TYPE_VMA
+} CPLVirtualMemType;
+
+struct CPLVirtualMem
+{
+    CPLVirtualMemType eType;
+
+    struct CPLVirtualMem *pVMemBase;
+    int                   nRefCount;
+
+    CPLVirtualMemAccessMode eAccessMode;
+
+    size_t       nPageSize;
+    void        *pData;        // aligned on nPageSize
+    void        *pDataToFree;  // returned by mmap(), potentially lower than pData
+    size_t       nSize;        // requested size (unrounded)
+
+    int          bSingleThreadUsage;
+
+    void                         *pCbkUserData;
+    CPLVirtualMemFreeUserData     pfnFreeUserData;
+};
+
+#ifdef HAVE_VIRTUAL_MEM_VMA
+
 #include <sys/select.h> /* select */
 #include <sys/stat.h>   /* open() */
 #include <sys/types.h>  /* open() */
-#include <assert.h>
 #include <errno.h>
 #include <fcntl.h>      /* open() */
 #include <signal.h>     /* sigaction */
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>     /* read, write, close, pipe */
 #include <pthread.h>
 
+// FIXME? gcore/virtualmem.py tests fail/crash when HAVE_5ARGS_MREMAP
+// is not defined
+
 #ifndef HAVE_5ARGS_MREMAP
 #include "cpl_atomic_ops.h"
 #endif
@@ -61,17 +111,19 @@
 /* Linux specific (i.e. non POSIX compliant) features used :
    - returning from a SIGSEGV handler is clearly a POSIX violation, but in
      practice most POSIX systems should be happy.
-   - mremap() with 5 args is Linux specific. It is used when the user callback is invited
-     to fill a page, we currently mmap() a writable page, let it filled it,
-     and afterwards mremap() that temporary page onto the location where the
-     fault occured.
+   - mremap() with 5 args is Linux specific. It is used when the user
+     callback is invited to fill a page, we currently mmap() a
+     writable page, let it filled it, and afterwards mremap() that
+     temporary page onto the location where the fault occurred.
      If we have no mremap(), the workaround is to pause other threads that
      consume the current view while we are updating the faulted page, otherwise
      a non-paused thread could access a page that is in the middle of being
      filled... The way we pause those threads is quite original : we send them
      a SIGUSR1 and wait that they are stuck in the temporary SIGUSR1 handler...
-   - MAP_ANONYMOUS isn't documented in Posix, but very commonly found (sometimes called MAP_ANON)
-   - dealing with the limitation of number of memory mapping regions, and the 65536 limit.
+   - MAP_ANONYMOUS isn't documented in POSIX, but very commonly found
+     (sometimes called MAP_ANON)
+   - dealing with the limitation of number of memory mapping regions,
+     and the 65536 limit.
    - other things I've not identified
 */
 
@@ -102,18 +154,9 @@ typedef enum
     OP_UNKNOWN
 } OpType;
 
-struct CPLVirtualMem
+typedef struct
 {
-    struct CPLVirtualMem *pVMemBase;
-    int          nRefCount;
-
-    int          bFileMemoryMapped; /* if TRUE, only eAccessMode, pData, pDataToFree, nSize and nPageSize are valid */
-    CPLVirtualMemAccessMode eAccessMode;
-
-    size_t       nPageSize;
-    void        *pData;                  /* aligned on nPageSize */
-    void        *pDataToFree;            /* returned by mmap(), potentially lower than pData */
-    size_t       nSize;                  /* requested size (unrounded) */
+    CPLVirtualMem sBase;
 
     GByte       *pabitMappedPages;
     GByte       *pabitRWMappedPages;
@@ -121,28 +164,25 @@ struct CPLVirtualMem
     int          nCacheMaxSizeInPages;   /* maximum size of page array */
     int         *panLRUPageIndices;      /* array with indices of cached pages */
     int          iLRUStart;              /* index in array where to write next page index */
-    int          nLRUSize;               /* current isze of the array */
+    int          nLRUSize;               /* current size of the array */
 
     int          iLastPage;              /* last page accessed */
     int          nRetry;                 /* number of consecutive retries to that last page */
-    
-    int          bSingleThreadUsage;
 
     CPLVirtualMemCachePageCbk     pfnCachePage;       /* called when a page is mapped */
     CPLVirtualMemUnCachePageCbk   pfnUnCachePage;     /* called when a (writable) page is unmapped */
-    void                   *pCbkUserData;
-    CPLVirtualMemFreeUserData     pfnFreeUserData;
+
 #ifndef HAVE_5ARGS_MREMAP
     CPLMutex               *hMutexThreadArray;
     int                     nThreads;
     pthread_t              *pahThreads;
 #endif
-};
+} CPLVirtualMemVMA;
 
 typedef struct
 {
     /* hVirtualMemManagerMutex protects the 2 following variables */
-    CPLVirtualMem        **pasVirtualMem;
+    CPLVirtualMemVMA **pasVirtualMem;
     int              nVirtualMemCount;
 
     int              pipefd_to_thread[2];
@@ -160,10 +200,11 @@ typedef struct
     pthread_t        hRequesterThread;
 } CPLVirtualMemMsgToWorkerThread;
 
+// TODO: Singletons.
 static CPLVirtualMemManager* pVirtualMemManager = NULL;
 static CPLMutex* hVirtualMemManagerMutex = NULL;
 
-static void CPLVirtualMemManagerInit();
+static bool CPLVirtualMemManagerInit();
 
 #ifdef DEBUG_VIRTUALMEM
 
@@ -179,14 +220,14 @@ static void fprintfstderr(const char* fmt, ...)
     vsnprintf(buffer, sizeof(buffer), fmt, ap);
     va_end(ap);
     int offset = 0;
-    while(TRUE)
+    while(true)
     {
         int ret = write(2, buffer + offset, strlen(buffer + offset));
         if( ret < 0 && errno == EINTR )
             ;
         else
         {
-            if( ret == (int)strlen(buffer + offset) )
+            if( ret == static_cast<int>(strlen(buffer + offset)) )
                 break;
             offset += ret;
         }
@@ -196,40 +237,39 @@ static void fprintfstderr(const char* fmt, ...)
 #endif
 
 /************************************************************************/
-/*                         CPLGetPageSize()                             */
-/************************************************************************/
-
-size_t CPLGetPageSize(void)
-{
-    return (size_t) sysconf(_SC_PAGESIZE);
-}
-
-/************************************************************************/
 /*              CPLVirtualMemManagerRegisterVirtualMem()                */
 /************************************************************************/
 
-static void CPLVirtualMemManagerRegisterVirtualMem(CPLVirtualMem* ctxt)
+static bool CPLVirtualMemManagerRegisterVirtualMem(CPLVirtualMemVMA* ctxt)
 {
-    CPLVirtualMemManagerInit();
+    if( !CPLVirtualMemManagerInit() )
+        return false;
 
-    assert(ctxt);
+    bool bSuccess = true;
+    IGNORE_OR_ASSERT_IN_DEBUG(ctxt);
     CPLAcquireMutex(hVirtualMemManagerMutex, 1000.0);
-    pVirtualMemManager->pasVirtualMem = (CPLVirtualMem**) CPLRealloc(
-        pVirtualMemManager->pasVirtualMem, sizeof(CPLVirtualMem*) * (pVirtualMemManager->nVirtualMemCount + 1) );
-    pVirtualMemManager->pasVirtualMem[pVirtualMemManager->nVirtualMemCount] = ctxt;
-    pVirtualMemManager->nVirtualMemCount ++;
+    CPLVirtualMemVMA** pasVirtualMemNew = (CPLVirtualMemVMA**) VSI_REALLOC_VERBOSE(
+        pVirtualMemManager->pasVirtualMem, sizeof(CPLVirtualMemVMA*) * (pVirtualMemManager->nVirtualMemCount + 1) );
+    if( pasVirtualMemNew == NULL )
+        bSuccess = false;
+    else
+    {
+        pVirtualMemManager->pasVirtualMem = pasVirtualMemNew;
+        pVirtualMemManager->pasVirtualMem[pVirtualMemManager->nVirtualMemCount] = ctxt;
+        pVirtualMemManager->nVirtualMemCount ++;
+    }
     CPLReleaseMutex(hVirtualMemManagerMutex);
+    return bSuccess;
 }
 
 /************************************************************************/
 /*               CPLVirtualMemManagerUnregisterVirtualMem()             */
 /************************************************************************/
 
-static void CPLVirtualMemManagerUnregisterVirtualMem(CPLVirtualMem* ctxt)
+static void CPLVirtualMemManagerUnregisterVirtualMem(CPLVirtualMemVMA* ctxt)
 {
-    int i;
     CPLAcquireMutex(hVirtualMemManagerMutex, 1000.0);
-    for(i=0;i<pVirtualMemManager->nVirtualMemCount;i++)
+    for( int i=0; i < pVirtualMemManager->nVirtualMemCount; i++ )
     {
         if( pVirtualMemManager->pasVirtualMem[i] == ctxt )
         {
@@ -250,6 +290,8 @@ static void CPLVirtualMemManagerUnregisterVirtualMem(CPLVirtualMem* ctxt)
 /*                           CPLVirtualMemNew()                         */
 /************************************************************************/
 
+static void CPLVirtualMemFreeFileMemoryMapped(CPLVirtualMemVMA* ctxt);
+
 CPLVirtualMem* CPLVirtualMemNew(size_t nSize,
                                 size_t nCacheSize,
                                 size_t nPageSizeHint,
@@ -260,17 +302,16 @@ CPLVirtualMem* CPLVirtualMemNew(size_t nSize,
                                 CPLVirtualMemFreeUserData pfnFreeUserData,
                                 void *pCbkUserData)
 {
-    CPLVirtualMem* ctxt;
+    CPLVirtualMemVMA* ctxt;
     void* pData;
     size_t nMinPageSize = CPLGetPageSize();
     size_t nPageSize = DEFAULT_PAGE_SIZE;
-    size_t nCacheMaxSizeInPages;
     size_t nRoundedMappingSize;
     FILE* f;
     int nMappings = 0;
 
-    assert(nSize > 0);
-    assert(pfnCachePage != NULL);
+    IGNORE_OR_ASSERT_IN_DEBUG(nSize > 0);
+    IGNORE_OR_ASSERT_IN_DEBUG(pfnCachePage != NULL);
 
     if( nPageSizeHint >= nMinPageSize && nPageSizeHint <= MAXIMUM_PAGE_SIZE )
     {
@@ -280,11 +321,11 @@ CPLVirtualMem* CPLVirtualMemNew(size_t nSize,
         {
             int nbits = 0;
             nPageSize = (size_t)nPageSizeHint;
-            while(nPageSize > 0)
+            do
             {
                 nPageSize >>= 1;
                 nbits ++;
-            }
+            } while(nPageSize > 0);
             nPageSize = (size_t)1 << (nbits - 1);
             if( nPageSize < (size_t)nPageSizeHint )
                 nPageSize <<= 1;
@@ -310,7 +351,8 @@ CPLVirtualMem* CPLVirtualMemNew(size_t nSize,
         fclose(f);
     }
 
-    while(TRUE)
+    size_t nCacheMaxSizeInPages = 0;
+    while(true)
     {
         /* /proc/self/maps must not have more than 65K lines */
         nCacheMaxSizeInPages = (nCacheSize + 2 * nPageSize - 1) / nPageSize;
@@ -327,283 +369,111 @@ CPLVirtualMem* CPLVirtualMemNew(size_t nSize,
         perror("mmap");
         return NULL;
     }
-    ctxt = (CPLVirtualMem* )CPLCalloc(1, sizeof(CPLVirtualMem));
-    ctxt->nRefCount = 1;
-    ctxt->bFileMemoryMapped = FALSE;
-    ctxt->eAccessMode = eAccessMode;
-    ctxt->pDataToFree = pData;
-    ctxt->pData = ALIGN_UP(pData, nPageSize);
-    ctxt->nPageSize = nPageSize;
-    ctxt->pabitMappedPages = (GByte*)CPLCalloc(1, (nRoundedMappingSize / nPageSize + 7) / 8);
-    assert(ctxt->pabitMappedPages);
-    ctxt->pabitRWMappedPages = (GByte*)CPLCalloc(1, (nRoundedMappingSize / nPageSize + 7) / 8);
-    assert(ctxt->pabitRWMappedPages);
+    ctxt = (CPLVirtualMemVMA* )VSI_CALLOC_VERBOSE(1, sizeof(CPLVirtualMemVMA));
+    if( ctxt == NULL )
+        return NULL;
+    ctxt->sBase.nRefCount = 1;
+    ctxt->sBase.eType = VIRTUAL_MEM_TYPE_VMA;
+    ctxt->sBase.eAccessMode = eAccessMode;
+    ctxt->sBase.pDataToFree = pData;
+    ctxt->sBase.pData = ALIGN_UP(pData, nPageSize);
+    ctxt->sBase.nPageSize = nPageSize;
+    ctxt->sBase.nSize = nSize;
+    ctxt->sBase.bSingleThreadUsage = bSingleThreadUsage;
+    ctxt->sBase.pfnFreeUserData = pfnFreeUserData;
+    ctxt->sBase.pCbkUserData = pCbkUserData;
+
+    ctxt->pabitMappedPages = (GByte*)VSI_CALLOC_VERBOSE(1, (nRoundedMappingSize / nPageSize + 7) / 8);
+    if( ctxt->pabitMappedPages == NULL )
+    {
+        CPLVirtualMemFreeFileMemoryMapped(ctxt);
+        CPLFree(ctxt);
+        return NULL;
+    }
+    ctxt->pabitRWMappedPages = (GByte*)VSI_CALLOC_VERBOSE(1, (nRoundedMappingSize / nPageSize + 7) / 8);
+    if( ctxt->pabitRWMappedPages == NULL )
+    {
+        CPLVirtualMemFreeFileMemoryMapped(ctxt);
+        CPLFree(ctxt);
+        return NULL;
+    }
     /* we need at least 2 pages in case for a rep movs instruction */
     /* that operate in the view */
-    ctxt->nCacheMaxSizeInPages = nCacheMaxSizeInPages;
-    ctxt->panLRUPageIndices = (int*)CPLMalloc(ctxt->nCacheMaxSizeInPages * sizeof(int));
-    assert(ctxt->panLRUPageIndices);
-    ctxt->nSize = nSize;
+    ctxt->nCacheMaxSizeInPages = static_cast<int>(nCacheMaxSizeInPages);
+    ctxt->panLRUPageIndices = static_cast<int*>(VSI_MALLOC_VERBOSE(ctxt->nCacheMaxSizeInPages * sizeof(int)));
+    if( ctxt->panLRUPageIndices == NULL )
+    {
+        CPLVirtualMemFreeFileMemoryMapped(ctxt);
+        CPLFree(ctxt);
+        return NULL;
+    }
     ctxt->iLRUStart = 0;
     ctxt->nLRUSize = 0;
     ctxt->iLastPage = -1;
     ctxt->nRetry = 0;
-    ctxt->bSingleThreadUsage = bSingleThreadUsage;
     ctxt->pfnCachePage = pfnCachePage;
     ctxt->pfnUnCachePage = pfnUnCachePage;
-    ctxt->pfnFreeUserData = pfnFreeUserData;
-    ctxt->pCbkUserData = pCbkUserData;
+
 #ifndef HAVE_5ARGS_MREMAP
-    if( !ctxt->bSingleThreadUsage )
+    if( !ctxt->sBase.bSingleThreadUsage )
     {
         ctxt->hMutexThreadArray = CPLCreateMutex();
-        assert(ctxt->hMutexThreadArray != NULL);
+        IGNORE_OR_ASSERT_IN_DEBUG(ctxt->hMutexThreadArray != NULL);
         CPLReleaseMutex(ctxt->hMutexThreadArray);
         ctxt->nThreads = 0;
         ctxt->pahThreads = NULL;
     }
 #endif
 
-    CPLVirtualMemManagerRegisterVirtualMem(ctxt);
-
-    return ctxt;
-}
-
-/************************************************************************/
-/*                   CPLIsVirtualMemFileMapAvailable()                  */
-/************************************************************************/
-
-int CPLIsVirtualMemFileMapAvailable(void)
-{
-    return TRUE;
-}
-
-/************************************************************************/
-/*                       CPLVirtualMemFileMapNew()                      */
-/************************************************************************/
-
-CPLVirtualMem *CPLVirtualMemFileMapNew( VSILFILE* fp,
-                                        vsi_l_offset nOffset,
-                                        vsi_l_offset nLength,
-                                        CPLVirtualMemAccessMode eAccessMode,
-                                        CPLVirtualMemFreeUserData pfnFreeUserData,
-                                        void *pCbkUserData )
-{
-#if SIZEOF_VOIDP == 4
-    if( nLength != (size_t)nLength )
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "nLength = " CPL_FRMT_GUIB " incompatible with 32 bit architecture",
-                 nLength);
-        return NULL;
-    }
-#endif
-
-    int fd = (int) (size_t) VSIFGetNativeFileDescriptorL(fp);
-    if( fd == 0 )
+    if( !CPLVirtualMemManagerRegisterVirtualMem(ctxt) )
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "Cannot operate on a virtual file");
-        return NULL;
-    }
-
-    off_t nAlignedOffset = (nOffset / CPLGetPageSize()) * CPLGetPageSize();
-    size_t nAligment = nOffset - nAlignedOffset;
-    size_t nMappingSize = nLength + nAligment;
-
-    /* We need to ensure that the requested extent fits into the file size */
-    /* otherwise SIGBUS errors will occur when using the mapping */
-    vsi_l_offset nCurPos = VSIFTellL(fp);
-    VSIFSeekL(fp, 0, SEEK_END);
-    vsi_l_offset nFileSize = VSIFTellL(fp);
-    if( nFileSize < nOffset + nLength )
-    {
-        if( eAccessMode != VIRTUALMEM_READWRITE )
-        {
-            CPLError(CE_Failure, CPLE_AppDefined, "Trying to map an extent outside of the file");
-            VSIFSeekL(fp, nCurPos, SEEK_SET);
-            return NULL;
-        }
-        else
-        {
-            char ch = 0;
-            if( VSIFSeekL(fp, nOffset + nLength - 1, SEEK_SET) != 0 ||
-                VSIFWriteL(&ch, 1, 1, fp) != 1 )
-            {
-                CPLError(CE_Failure, CPLE_AppDefined, "Cannot extend file to mapping size");
-                VSIFSeekL(fp, nCurPos, SEEK_SET);
-                return NULL;
-            }
-        }
-    }
-    VSIFSeekL(fp, nCurPos, SEEK_SET);
-
-    void* addr = mmap(NULL, nMappingSize,
-                      (eAccessMode == VIRTUALMEM_READWRITE) ? PROT_READ | PROT_WRITE : PROT_READ,
-                      MAP_SHARED, fd, nAlignedOffset);
-    if( addr == MAP_FAILED )
-    {
-        int myerrno = errno;
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "mmap() failed : %s", strerror(myerrno));
+        CPLVirtualMemFreeFileMemoryMapped(ctxt);
+        CPLFree(ctxt);
         return NULL;
     }
 
-    CPLVirtualMem* ctxt = (CPLVirtualMem* )CPLCalloc(1, sizeof(CPLVirtualMem));
-    ctxt->nRefCount = 1;
-    ctxt->eAccessMode = eAccessMode;
-    ctxt->bFileMemoryMapped = TRUE;
-    ctxt->pData = (GByte*) addr + nAligment;
-    ctxt->pDataToFree = addr;
-    ctxt->nSize = nLength;
-    ctxt->nPageSize = CPLGetPageSize();
-    ctxt->bSingleThreadUsage = FALSE;
-    ctxt->pfnFreeUserData = pfnFreeUserData;
-    ctxt->pCbkUserData = pCbkUserData;
-
-    return ctxt;
+    return (CPLVirtualMem*) ctxt;
 }
 
 /************************************************************************/
-/*                       CPLVirtualMemDerivedNew()                      */
+/*                       CPLVirtualMemFreeVMA()                         */
 /************************************************************************/
 
-CPLVirtualMem *CPLVirtualMemDerivedNew(CPLVirtualMem* pVMemBase,
-                                       vsi_l_offset nOffset,
-                                       vsi_l_offset nSize,
-                                       CPLVirtualMemFreeUserData pfnFreeUserData,
-                                       void *pCbkUserData)
+static void CPLVirtualMemFreeFileMemoryMapped(CPLVirtualMemVMA* ctxt)
 {
-    if( nOffset + nSize > pVMemBase->nSize )
-        return NULL;
-
-    CPLVirtualMem* ctxt = (CPLVirtualMem* )CPLCalloc(1, sizeof(CPLVirtualMem));
-    ctxt->nRefCount = 1;
-    ctxt->pVMemBase = pVMemBase;
-    pVMemBase->nRefCount ++;
-    ctxt->eAccessMode = pVMemBase->eAccessMode;
-    ctxt->bFileMemoryMapped = pVMemBase->bFileMemoryMapped;
-    ctxt->pData = (GByte*) pVMemBase->pData + nOffset;
-    ctxt->pDataToFree = NULL;
-    ctxt->nSize = nSize;
-    ctxt->nPageSize = pVMemBase->nPageSize;
-    ctxt->bSingleThreadUsage = pVMemBase->bSingleThreadUsage;
-    ctxt->pfnFreeUserData = pfnFreeUserData;
-    ctxt->pCbkUserData = pCbkUserData;
-
-    return ctxt;
-}
-
-/************************************************************************/
-/*                        CPLVirtualMemFree()                           */
-/************************************************************************/
-
-void CPLVirtualMemFree(CPLVirtualMem* ctxt)
-{
-    size_t nRoundedMappingSize;
-
-    if( ctxt == NULL || --(ctxt->nRefCount) > 0 )
-        return;
-
-    if( ctxt->pVMemBase != NULL )
-    {
-        CPLVirtualMemFree(ctxt->pVMemBase);
-        if( ctxt->pfnFreeUserData != NULL )
-            ctxt->pfnFreeUserData(ctxt->pCbkUserData);
-        CPLFree(ctxt);
-        return;
-    }
-
-    if( ctxt->bFileMemoryMapped )
-    {
-        size_t nMappingSize = ctxt->nSize + (GByte*)ctxt->pData - (GByte*)ctxt->pDataToFree;
-        assert(munmap(ctxt->pDataToFree, nMappingSize) == 0);
-        if( ctxt->pfnFreeUserData != NULL )
-            ctxt->pfnFreeUserData(ctxt->pCbkUserData);
-        CPLFree(ctxt);
-        return;
-    }
-
     CPLVirtualMemManagerUnregisterVirtualMem(ctxt);
 
-    nRoundedMappingSize = ((ctxt->nSize + 2 * ctxt->nPageSize - 1) /
-                                            ctxt->nPageSize) * ctxt->nPageSize;
-    if( ctxt->eAccessMode == VIRTUALMEM_READWRITE &&
+    size_t nRoundedMappingSize = ((ctxt->sBase.nSize + 2 * ctxt->sBase.nPageSize - 1) /
+                                            ctxt->sBase.nPageSize) * ctxt->sBase.nPageSize;
+    if( ctxt->sBase.eAccessMode == VIRTUALMEM_READWRITE &&
+        ctxt->pabitRWMappedPages != NULL &&
         ctxt->pfnUnCachePage != NULL )
     {
-        size_t i;
-        for(i = 0; i < nRoundedMappingSize / ctxt->nPageSize; i++)
+        for( size_t i = 0; i < nRoundedMappingSize / ctxt->sBase.nPageSize; i++ )
         {
             if( TEST_BIT(ctxt->pabitRWMappedPages, i) )
             {
-                void* addr = (char*)ctxt->pData + i * ctxt->nPageSize;
-                ctxt->pfnUnCachePage(ctxt,
-                                 i * ctxt->nPageSize,
+                void* addr = (char*)ctxt->sBase.pData + i * ctxt->sBase.nPageSize;
+                ctxt->pfnUnCachePage((CPLVirtualMem*)ctxt,
+                                 i * ctxt->sBase.nPageSize,
                                  addr,
-                                 ctxt->nPageSize,
-                                 ctxt->pCbkUserData);
+                                 ctxt->sBase.nPageSize,
+                                 ctxt->sBase.pCbkUserData);
             }
         }
     }
-    assert(munmap(ctxt->pDataToFree, nRoundedMappingSize) == 0);
+    int nRet = munmap(ctxt->sBase.pDataToFree, nRoundedMappingSize);
+    IGNORE_OR_ASSERT_IN_DEBUG(nRet == 0);
     CPLFree(ctxt->pabitMappedPages);
     CPLFree(ctxt->pabitRWMappedPages);
     CPLFree(ctxt->panLRUPageIndices);
 #ifndef HAVE_5ARGS_MREMAP
-    if( !ctxt->bSingleThreadUsage )
+    if( !ctxt->sBase.bSingleThreadUsage )
     {
         CPLFree(ctxt->pahThreads);
         CPLDestroyMutex(ctxt->hMutexThreadArray);
     }
 #endif
-    if( ctxt->pfnFreeUserData != NULL )
-        ctxt->pfnFreeUserData(ctxt->pCbkUserData);
-
-    CPLFree(ctxt);
-}
-
-/************************************************************************/
-/*                      CPLVirtualMemGetAddr()                          */
-/************************************************************************/
-
-void* CPLVirtualMemGetAddr(CPLVirtualMem* ctxt)
-{
-    return ctxt->pData;
-}
-
-/************************************************************************/
-/*                     CPLVirtualMemIsFileMapping()                     */
-/************************************************************************/
-
-int CPLVirtualMemIsFileMapping(CPLVirtualMem* ctxt)
-{
-    return ctxt->bFileMemoryMapped;
-}
-
-/************************************************************************/
-/*                     CPLVirtualMemGetAccessMode()                     */
-/************************************************************************/
-
-CPLVirtualMemAccessMode CPLVirtualMemGetAccessMode(CPLVirtualMem* ctxt)
-{
-    return ctxt->eAccessMode;
-}
-
-/************************************************************************/
-/*                      CPLVirtualMemGetPageSize()                      */
-/************************************************************************/
-
-size_t CPLVirtualMemGetPageSize(CPLVirtualMem* ctxt)
-{
-    return ctxt->nPageSize;
-}
-
-/************************************************************************/
-/*                        CPLVirtualMemGetSize()                        */
-/************************************************************************/
-
-size_t CPLVirtualMemGetSize(CPLVirtualMem* ctxt)
-{
-    return ctxt->nSize;
 }
 
 #ifndef HAVE_5ARGS_MREMAP
@@ -615,31 +485,23 @@ static volatile int nWaitHelperThread = 0;
 /*                   CPLVirtualMemSIGUSR1Handler()                      */
 /************************************************************************/
 
-static void CPLVirtualMemSIGUSR1Handler(int signum_unused, 
-                                     siginfo_t* the_info_unused,
-                                     void* the_ctxt_unused)
+static void CPLVirtualMemSIGUSR1Handler( int /* signum_unused */,
+                                         siginfo_t* /* the_info_unused */,
+                                         void* /* the_ctxt_unused */)
 {
-    /* fprintfstderr("entering CPLVirtualMemSIGUSR1Handler %X\n", pthread_self()); */
-    (void)signum_unused;
-    (void)the_info_unused;
-    (void)the_ctxt_unused;
+#if defined DEBUG_VIRTUALMEM && defined DEBUG_VERBOSE
+    fprintfstderr("entering CPLVirtualMemSIGUSR1Handler %X\n", pthread_self());
+#endif
     /* I guess this is only POSIX correct if it is implemented by an intrinsic */
     CPLAtomicInc(&nCountThreadsInSigUSR1);
     while( nWaitHelperThread )
         usleep(1); /* not explicitly indicated as signal-async-safe, but hopefully ok */
     CPLAtomicDec(&nCountThreadsInSigUSR1);
-    /* fprintfstderr("leaving CPLVirtualMemSIGUSR1Handler %X\n", pthread_self()); */
-}
+#if defined DEBUG_VIRTUALMEM && defined DEBUG_VERBOSE
+    fprintfstderr("leaving CPLVirtualMemSIGUSR1Handler %X\n", pthread_self());
 #endif
-
-/************************************************************************/
-/*                   CPLVirtualMemIsAccessThreadSafe()                  */
-/************************************************************************/
-
-int CPLVirtualMemIsAccessThreadSafe(CPLVirtualMem* ctxt)
-{
-    return !ctxt->bSingleThreadUsage;
 }
+#endif
 
 /************************************************************************/
 /*                      CPLVirtualMemDeclareThread()                    */
@@ -647,17 +509,18 @@ int CPLVirtualMemIsAccessThreadSafe(CPLVirtualMem* ctxt)
 
 void CPLVirtualMemDeclareThread(CPLVirtualMem* ctxt)
 {
-    if( ctxt->bFileMemoryMapped )
+    if( ctxt->eType == VIRTUAL_MEM_TYPE_FILE_MEMORY_MAPPED )
         return;
 #ifndef HAVE_5ARGS_MREMAP
-    assert( !ctxt->bSingleThreadUsage );
-    CPLAcquireMutex(ctxt->hMutexThreadArray, 1000.0);
-    ctxt->pahThreads = (pthread_t*) CPLRealloc(ctxt->pahThreads,
-                                (ctxt->nThreads + 1) * sizeof(pthread_t));
-    ctxt->pahThreads[ctxt->nThreads] = pthread_self();
-    ctxt->nThreads ++;
-
-    CPLReleaseMutex(ctxt->hMutexThreadArray);
+    CPLVirtualMemVMA* ctxtVMA = (CPLVirtualMemVMA* )ctxt;
+    IGNORE_OR_ASSERT_IN_DEBUG( !ctxt->bSingleThreadUsage );
+    CPLAcquireMutex(ctxtVMA->hMutexThreadArray, 1000.0);
+    ctxtVMA->pahThreads = (pthread_t*) CPLRealloc(ctxtVMA->pahThreads,
+                                (ctxtVMA->nThreads + 1) * sizeof(pthread_t));
+    ctxtVMA->pahThreads[ctxtVMA->nThreads] = pthread_self();
+    ctxtVMA->nThreads ++;
+
+    CPLReleaseMutex(ctxtVMA->hMutexThreadArray);
 #endif
 }
 
@@ -667,27 +530,27 @@ void CPLVirtualMemDeclareThread(CPLVirtualMem* ctxt)
 
 void CPLVirtualMemUnDeclareThread(CPLVirtualMem* ctxt)
 {
-    if( ctxt->bFileMemoryMapped )
+    if( ctxt->eType == VIRTUAL_MEM_TYPE_FILE_MEMORY_MAPPED )
         return;
 #ifndef HAVE_5ARGS_MREMAP
-    int i;
+    CPLVirtualMemVMA* ctxtVMA = (CPLVirtualMemVMA* )ctxt;
     pthread_t self = pthread_self();
-    assert( !ctxt->bSingleThreadUsage );
-    CPLAcquireMutex(ctxt->hMutexThreadArray, 1000.0);
-    for(i = 0; i < ctxt->nThreads; i++)
+    IGNORE_OR_ASSERT_IN_DEBUG( !ctxt->bSingleThreadUsage );
+    CPLAcquireMutex(ctxtVMA->hMutexThreadArray, 1000.0);
+    for( int i = 0; i < ctxtVMA->nThreads; i++ )
     {
-        if( ctxt->pahThreads[i] == self )
+        if( ctxtVMA->pahThreads[i] == self )
         {
-            if( i < ctxt->nThreads - 1 )
-                memmove(ctxt->pahThreads + i + 1,
-                        ctxt->pahThreads + i,
-                        (ctxt->nThreads - 1 - i) * sizeof(pthread_t));
-            ctxt->nThreads --;
+            if( i < ctxtVMA->nThreads - 1 )
+                memmove(ctxtVMA->pahThreads + i + 1,
+                        ctxtVMA->pahThreads + i,
+                        (ctxtVMA->nThreads - 1 - i) * sizeof(pthread_t));
+            ctxtVMA->nThreads --;
             break;
         }
     }
 
-    CPLReleaseMutex(ctxt->hMutexThreadArray);
+    CPLReleaseMutex(ctxtVMA->hMutexThreadArray);
 #endif
 }
 
@@ -698,14 +561,17 @@ void CPLVirtualMemUnDeclareThread(CPLVirtualMem* ctxt)
 
 /* Must be paired with CPLVirtualMemAddPage */
 static
-void* CPLVirtualMemGetPageToFill(CPLVirtualMem* ctxt, void* start_page_addr)
+void* CPLVirtualMemGetPageToFill(CPLVirtualMemVMA* ctxt, void* start_page_addr)
 {
     void* pPageToFill;
 
-    if( ctxt->bSingleThreadUsage )
+    if( ctxt->sBase.bSingleThreadUsage )
     {
         pPageToFill = start_page_addr;
-        assert(mprotect(pPageToFill, ctxt->nPageSize, PROT_READ | PROT_WRITE) == 0);
+        const int nRet =
+            mprotect( pPageToFill, ctxt->sBase.nPageSize,
+                      PROT_READ | PROT_WRITE );
+        IGNORE_OR_ASSERT_IN_DEBUG(nRet == 0);
     }
     else
     {
@@ -714,17 +580,20 @@ void* CPLVirtualMemGetPageToFill(CPLVirtualMem* ctxt, void* start_page_addr)
         if( ctxt->nThreads == 1 )
         {
             pPageToFill = start_page_addr;
-            assert(mprotect(pPageToFill, ctxt->nPageSize, PROT_READ | PROT_WRITE) == 0);
+            const int nRet =
+                mprotect( pPageToFill, ctxt->sBase.nPageSize,
+                          PROT_READ | PROT_WRITE );
+            IGNORE_OR_ASSERT_IN_DEBUG(nRet == 0);
         }
         else
 #endif
         {
             /* Allocate a temporary writable page that the user */
             /* callback can fill */
-            pPageToFill = mmap(NULL, ctxt->nPageSize,
+            pPageToFill = mmap(NULL, ctxt->sBase.nPageSize,
                                 PROT_READ | PROT_WRITE,
                                 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-            assert(pPageToFill != MAP_FAILED);
+            IGNORE_OR_ASSERT_IN_DEBUG(pPageToFill != MAP_FAILED);
         }
     }
     return pPageToFill;
@@ -735,36 +604,39 @@ void* CPLVirtualMemGetPageToFill(CPLVirtualMem* ctxt, void* start_page_addr)
 /************************************************************************/
 
 static
-void CPLVirtualMemAddPage(CPLVirtualMem* ctxt, void* target_addr, void* pPageToFill,
+void CPLVirtualMemAddPage(CPLVirtualMemVMA* ctxt, void* target_addr, void* pPageToFill,
                        OpType opType, pthread_t hRequesterThread)
 {
-    size_t iPage = (int)(((char*)target_addr - (char*)ctxt->pData) / ctxt->nPageSize);
+    int iPage = static_cast<int>(((char*)target_addr - (char*)ctxt->sBase.pData) / ctxt->sBase.nPageSize);
     if( ctxt->nLRUSize == ctxt->nCacheMaxSizeInPages )
     {
-        /* fprintfstderr("uncaching page %d\n", iPage); */
+#if defined DEBUG_VIRTUALMEM && defined DEBUG_VERBOSE
+        fprintfstderr("uncaching page %d\n", iPage);
+#endif
         int nOldPage = ctxt->panLRUPageIndices[ctxt->iLRUStart];
-        void* addr = (char*)ctxt->pData + nOldPage * ctxt->nPageSize;
-        if( ctxt->eAccessMode == VIRTUALMEM_READWRITE &&
+        void* addr = (char*)ctxt->sBase.pData + nOldPage * ctxt->sBase.nPageSize;
+        if( ctxt->sBase.eAccessMode == VIRTUALMEM_READWRITE &&
             ctxt->pfnUnCachePage != NULL &&
             TEST_BIT(ctxt->pabitRWMappedPages, nOldPage) )
         {
-            size_t nToBeEvicted = ctxt->nPageSize;
-            if( (char*)addr + nToBeEvicted >= (char*) ctxt->pData + ctxt->nSize )
-                nToBeEvicted = (char*) ctxt->pData + ctxt->nSize - (char*)addr;
+            size_t nToBeEvicted = ctxt->sBase.nPageSize;
+            if( (char*)addr + nToBeEvicted >= (char*) ctxt->sBase.pData + ctxt->sBase.nSize )
+                nToBeEvicted = (char*) ctxt->sBase.pData + ctxt->sBase.nSize - (char*)addr;
 
-            ctxt->pfnUnCachePage(ctxt,
-                                 nOldPage * ctxt->nPageSize,
+            ctxt->pfnUnCachePage((CPLVirtualMem*)ctxt,
+                                 nOldPage * ctxt->sBase.nPageSize,
                                  addr,
                                  nToBeEvicted,
-                                 ctxt->pCbkUserData);
+                                 ctxt->sBase.pCbkUserData);
         }
         /* "Free" the least recently used page */
         UNSET_BIT(ctxt->pabitMappedPages, nOldPage);
         UNSET_BIT(ctxt->pabitRWMappedPages, nOldPage);
         /* Free the old page */
         /* Not sure how portable it is to do that that way... */
-        assert(mmap(addr, ctxt->nPageSize, PROT_NONE,
-                    MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == addr);
+        const void * const pRet = mmap(addr, ctxt->sBase.nPageSize, PROT_NONE,
+                    MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+        IGNORE_OR_ASSERT_IN_DEBUG(pRet == addr);
     }
     ctxt->panLRUPageIndices[ctxt->iLRUStart] = iPage;
     ctxt->iLRUStart = (ctxt->iLRUStart + 1) % ctxt->nCacheMaxSizeInPages;
@@ -774,17 +646,19 @@ void CPLVirtualMemAddPage(CPLVirtualMem* ctxt, void* target_addr, void* pPageToF
     }
     SET_BIT(ctxt->pabitMappedPages, iPage);
 
-    if( ctxt->bSingleThreadUsage )
+    if( ctxt->sBase.bSingleThreadUsage )
     {
-        if( opType == OP_STORE && ctxt->eAccessMode == VIRTUALMEM_READWRITE )
+        if( opType == OP_STORE && ctxt->sBase.eAccessMode == VIRTUALMEM_READWRITE )
         {
             /* let (and mark) the page writable since the instruction that triggered */
             /* the fault is a store */
             SET_BIT(ctxt->pabitRWMappedPages, iPage);
         }
-        else if( ctxt->eAccessMode != VIRTUALMEM_READONLY )
+        else if( ctxt->sBase.eAccessMode != VIRTUALMEM_READONLY )
         {
-            assert(mprotect(target_addr, ctxt->nPageSize, PROT_READ) == 0);
+            const int nRet =
+                mprotect(target_addr, ctxt->sBase.nPageSize, PROT_READ);
+            IGNORE_OR_ASSERT_IN_DEBUG(nRet == 0);
         }
     }
     else
@@ -792,27 +666,28 @@ void CPLVirtualMemAddPage(CPLVirtualMem* ctxt, void* target_addr, void* pPageToF
 #ifdef HAVE_5ARGS_MREMAP
         (void)hRequesterThread;
 
-        if( opType == OP_STORE && ctxt->eAccessMode == VIRTUALMEM_READWRITE )
+        if( opType == OP_STORE && ctxt->sBase.eAccessMode == VIRTUALMEM_READWRITE )
         {
             /* let (and mark) the page writable since the instruction that triggered */
             /* the fault is a store */
             SET_BIT(ctxt->pabitRWMappedPages, iPage);
         }
-        else if( ctxt->eAccessMode != VIRTUALMEM_READONLY )
+        else if( ctxt->sBase.eAccessMode != VIRTUALMEM_READONLY )
         {
             /* Turn the temporary page read-only before remapping it. We will only turn it */
             /* writtable when a new fault occurs (and that the mapping is writable) */
-            assert(mprotect(pPageToFill, ctxt->nPageSize, PROT_READ) == 0);
+            int nRet = mprotect(pPageToFill, ctxt->sBase.nPageSize, PROT_READ);
+            IGNORE_OR_ASSERT_IN_DEBUG(nRet == 0);
         }
         /* Can now remap the pPageToFill onto the target page */
-        assert(mremap(pPageToFill, ctxt->nPageSize, ctxt->nPageSize,
-                    MREMAP_MAYMOVE | MREMAP_FIXED, target_addr) == target_addr);
+        const void * const pRet =
+            mremap( pPageToFill, ctxt->sBase.nPageSize, ctxt->sBase.nPageSize,
+                    MREMAP_MAYMOVE | MREMAP_FIXED, target_addr );
+        IGNORE_OR_ASSERT_IN_DEBUG(pRet == target_addr);
 
 #else
         if (ctxt->nThreads > 1 )
         {
-            int i;
-
             /* Pause threads that share this mem view */
             CPLAtomicInc(&nWaitHelperThread);
 
@@ -822,16 +697,19 @@ void CPLVirtualMemAddPage(CPLVirtualMem* ctxt, void* target_addr, void* pPageToF
             sigemptyset (&act.sa_mask);
             /* We don't want the sigsegv handler to be called when we are */
             /* running the sigusr1 handler */
-            assert(sigaddset(&act.sa_mask, SIGSEGV) == 0);
+            IGNORE_OR_ASSERT_IN_DEBUG(sigaddset(&act.sa_mask, SIGSEGV) == 0);
             act.sa_flags = 0;
-            assert(sigaction(SIGUSR1, &act, &oldact) == 0);
+            IGNORE_OR_ASSERT_IN_DEBUG(sigaction(SIGUSR1, &act, &oldact) == 0);
 
-            for(i = 0; i < ctxt->nThreads; i++)
+            for( int i = 0; i < ctxt->nThreads; i++)
             {
                 if( ctxt->pahThreads[i] != hRequesterThread )
                 {
-                    /* fprintfstderr("stopping thread %X\n", ctxt->pahThreads[i]); */
-                    assert(pthread_kill( ctxt->pahThreads[i], SIGUSR1 ) == 0);
+#if defined DEBUG_VIRTUALMEM && defined DEBUG_VERBOSE
+                    fprintfstderr("stopping thread %X\n", ctxt->pahThreads[i]); */
+#endif
+                    IGNORE_OR_ASSERT_IN_DEBUG(
+                        pthread_kill( ctxt->pahThreads[i], SIGUSR1 ) == 0);
                 }
             }
 
@@ -840,13 +718,17 @@ void CPLVirtualMemAddPage(CPLVirtualMem* ctxt, void* target_addr, void* pPageToF
                 usleep(1);
 
             /* Restore old SIGUSR1 signal handler */
-            assert(sigaction(SIGUSR1, &oldact, NULL) == 0);
+            IGNORE_OR_ASSERT_IN_DEBUG(sigaction(SIGUSR1, &oldact, NULL) == 0);
 
-            assert(mprotect(target_addr, ctxt->nPageSize, PROT_READ | PROT_WRITE) == 0);
-            /*fprintfstderr("memcpying page %d\n", iPage);*/
-            memcpy(target_addr, pPageToFill, ctxt->nPageSize);
-            
-            if( opType == OP_STORE && ctxt->eAccessMode == VIRTUALMEM_READWRITE )
+            int nRet = mprotect( target_addr, ctxt->sBase.nPageSize,
+                                 PROT_READ | PROT_WRITE );
+            IGNORE_OR_ASSERT_IN_DEBUG(nRet == 0);
+#if defined DEBUG_VIRTUALMEM && defined DEBUG_VERBOSE
+            fprintfstderr("memcpying page %d\n", iPage);
+#endif
+            memcpy(target_addr, pPageToFill, ctxt->sBase.nPageSize);
+
+            if( opType == OP_STORE && ctxt->sBase.eAccessMode == VIRTUALMEM_READWRITE )
             {
                 /* let (and mark) the page writable since the instruction that triggered */
                 /* the fault is a store */
@@ -854,7 +736,8 @@ void CPLVirtualMemAddPage(CPLVirtualMem* ctxt, void* target_addr, void* pPageToF
             }
             else
             {
-                assert(mprotect(target_addr, ctxt->nPageSize, PROT_READ) == 0);
+                nRet = mprotect(target_addr, ctxt->sBase.nPageSize, PROT_READ);
+                IGNORE_OR_ASSERT_IN_DEBUG(nRet == 0);
             }
 
             /* Wake up sleeping threads */
@@ -862,19 +745,22 @@ void CPLVirtualMemAddPage(CPLVirtualMem* ctxt, void* target_addr, void* pPageToF
             while( nCountThreadsInSigUSR1 != 0 )
                 usleep(1);
 
-            assert(munmap(pPageToFill, ctxt->nPageSize) == 0);
+            IGNORE_OR_ASSERT_IN_DEBUG(
+                munmap(pPageToFill, ctxt->sBase.nPageSize) == 0);
         }
         else
         {
-            if( opType == OP_STORE && ctxt->eAccessMode == VIRTUALMEM_READWRITE )
+            if( opType == OP_STORE && ctxt->sBase.eAccessMode == VIRTUALMEM_READWRITE )
             {
                 /* let (and mark) the page writable since the instruction that triggered */
                 /* the fault is a store */
                 SET_BIT(ctxt->pabitRWMappedPages, iPage);
             }
-            else if( ctxt->eAccessMode != VIRTUALMEM_READONLY )
+            else if( ctxt->sBase.eAccessMode != VIRTUALMEM_READONLY )
             {
-                assert(mprotect(target_addr, ctxt->nPageSize, PROT_READ) == 0);
+                const int nRet2 =
+                    mprotect(target_addr, ctxt->sBase.nPageSize, PROT_READ);
+                IGNORE_OR_ASSERT_IN_DEBUG(nRet2 == 0);
             }
         }
 
@@ -921,6 +807,7 @@ static OpType CPLVirtualMemGetOpTypeImm(GByte val_rip)
 /* if the fault occurs on a store operation, then we can directly put */
 /* the page in writable mode if the mapping allows it */
 
+#if defined(__x86_64__) || defined(__i386__)
 static OpType CPLVirtualMemGetOpType(const GByte* rip)
 {
     OpType opType = OP_UNKNOWN;
@@ -1575,6 +1462,7 @@ static OpType CPLVirtualMemGetOpType(const GByte* rip)
 #endif
     return opType;
 }
+#endif
 
 /************************************************************************/
 /*                    CPLVirtualMemManagerPinAddrInternal()             */
@@ -1586,31 +1474,40 @@ static int CPLVirtualMemManagerPinAddrInternal(CPLVirtualMemMsgToWorkerThread* m
     char response_buf[4];
 
     /* Wait for the helper thread to be ready to process another request */
-    while(TRUE)
+    while(true)
     {
-        int ret = read(pVirtualMemManager->pipefd_wait_thread[0], &wait_ready, 1);
+        const int ret =
+            static_cast<int>(read( pVirtualMemManager->pipefd_wait_thread[0],
+                                   &wait_ready, 1 ));
         if( ret < 0 && errno == EINTR )
-            ;
+        {
+            // NOP
+        }
         else
         {
-            assert(ret == 1);
+            IGNORE_OR_ASSERT_IN_DEBUG(ret == 1);
             break;
         }
     }
 
     /* Pass the address that caused the fault to the helper thread */
-    assert(write(pVirtualMemManager->pipefd_to_thread[1], msg, sizeof(*msg))
-            == sizeof(*msg));
+    const ssize_t nRetWrite =
+        write(pVirtualMemManager->pipefd_to_thread[1], msg, sizeof(*msg));
+    IGNORE_OR_ASSERT_IN_DEBUG(nRetWrite == sizeof(*msg));
 
     /* Wait that the helper thread has fixed the fault */
-    while(TRUE)
+    while(true)
     {
-        int ret = read(pVirtualMemManager->pipefd_from_thread[0], response_buf, 4);
+        const int ret =
+            static_cast<int>(read(pVirtualMemManager->pipefd_from_thread[0],
+                                  response_buf, 4));
         if( ret < 0 && errno == EINTR )
-            ;
+        {
+            // NOP
+        }
         else
         {
-            assert(ret == 4);
+            IGNORE_OR_ASSERT_IN_DEBUG(ret == 4);
             break;
         }
     }
@@ -1628,7 +1525,7 @@ static int CPLVirtualMemManagerPinAddrInternal(CPLVirtualMemMsgToWorkerThread* m
 void CPLVirtualMemPin(CPLVirtualMem* ctxt,
                       void* pAddr, size_t nSize, int bWriteOp)
 {
-    if( ctxt->bFileMemoryMapped )
+    if( ctxt->eType == VIRTUAL_MEM_TYPE_FILE_MEMORY_MAPPED )
         return;
 
     CPLVirtualMemMsgToWorkerThread msg;
@@ -1679,32 +1576,40 @@ static void CPLVirtualMemManagerSIGSEGVHandler(int the_signal,
     ucontext_t* the_ucontext = (ucontext_t* )the_ctxt;
     const GByte* rip = (const GByte*)the_ucontext->uc_mcontext.gregs[REG_IP];
     msg.opType = CPLVirtualMemGetOpType(rip);
-    /*fprintfstderr("at rip %p, bytes: %02x %02x %02x %02x\n",
-                          rip, rip[0], rip[1], rip[2], rip[3]);*/
+#if defined DEBUG_VIRTUALMEM && defined DEBUG_VERBOSE
+    fprintfstderr("at rip %p, bytes: %02x %02x %02x %02x\n",
+                  rip, rip[0], rip[1], rip[2], rip[3]);
+#endif
     if( msg.opType == OP_MOVS_RSI_RDI )
     {
         void* rsi = (void*)the_ucontext->uc_mcontext.gregs[REG_SI];
         void* rdi = (void*)the_ucontext->uc_mcontext.gregs[REG_DI];
 
-        /*fprintfstderr("fault=%p rsi=%p rsi=%p\n", msg.pFaultAddr, rsi, rdi);*/
+#if defined DEBUG_VIRTUALMEM && defined DEBUG_VERBOSE
+        fprintfstderr("fault=%p rsi=%p rsi=%p\n", msg.pFaultAddr, rsi, rdi);
+#endif
         if( msg.pFaultAddr == rsi )
         {
-            /*fprintfstderr("load\n");*/
+#if defined DEBUG_VIRTUALMEM && defined DEBUG_VERBOSE
+            fprintfstderr("load\n");
+#endif
             msg.opType = OP_LOAD;
         }
         else if( msg.pFaultAddr == rdi )
         {
-            /*fprintfstderr("store\n");*/
+#if defined DEBUG_VIRTUALMEM && defined DEBUG_VERBOSE
+            fprintfstderr("store\n");
+#endif
             msg.opType = OP_STORE;
         }
     }
 #ifdef DEBUG_VIRTUALMEM
     else if( msg.opType == OP_UNKNOWN )
     {
-        static int bHasWarned = FALSE;
+        static bool bHasWarned = false;
         if( !bHasWarned )
         {
-            bHasWarned = TRUE;
+            bHasWarned = true;
             fprintfstderr("at rip %p, unknown bytes: %02x %02x %02x %02x\n",
                           rip, rip[0], rip[1], rip[2], rip[3]);
         }
@@ -1712,7 +1617,9 @@ static void CPLVirtualMemManagerSIGSEGVHandler(int the_signal,
 #endif
 #endif
 
-    /*fprintfstderr("entering handler for %X (addr=%p)\n", pthread_self(), the_info->si_addr); */
+#if defined DEBUG_VIRTUALMEM && defined DEBUG_VERBOSE
+    fprintfstderr("entering handler for %X (addr=%p)\n", pthread_self(), the_info->si_addr);
+#endif
 
     if( the_info->si_code != SEGV_ACCERR )
     {
@@ -1728,7 +1635,9 @@ static void CPLVirtualMemManagerSIGSEGVHandler(int the_signal,
         pVirtualMemManager->oldact.sa_sigaction(the_signal, the_info, the_ctxt);
     }
 
-    /*fprintfstderr("leaving handler for %X (addr=%p)\n", pthread_self(), the_info->si_addr);*/
+#if defined DEBUG_VIRTUALMEM && defined DEBUG_VERBOSE
+    fprintfstderr("leaving handler for %X (addr=%p)\n", pthread_self(), the_info->si_addr);
+#endif
 }
 
 /************************************************************************/
@@ -1739,20 +1648,23 @@ static void CPLVirtualMemManagerThread(void* unused_param)
 {
     (void)unused_param;
 
-    while(TRUE)
+    while(true)
     {
         char i_m_ready = 1;
-        int i;
-        CPLVirtualMem* ctxt = NULL;
-        int bMappingFound = FALSE;
+        CPLVirtualMemVMA* ctxt = NULL;
+        bool bMappingFound = false;
         CPLVirtualMemMsgToWorkerThread msg;
 
         /* Signal that we are ready to process a new request */
-        assert(write(pVirtualMemManager->pipefd_wait_thread[1], &i_m_ready, 1) == 1);
+        ssize_t nRetWrite =
+            write(pVirtualMemManager->pipefd_wait_thread[1], &i_m_ready, 1);
+        IGNORE_OR_ASSERT_IN_DEBUG(nRetWrite == 1);
 
         /* Fetch the address to process */
-        assert(read(pVirtualMemManager->pipefd_to_thread[0], &msg,
-                    sizeof(msg)) == sizeof(msg));
+        const ssize_t nRetRead =
+            read(pVirtualMemManager->pipefd_to_thread[0], &msg,
+                 sizeof(msg));
+        IGNORE_OR_ASSERT_IN_DEBUG(nRetRead == sizeof(msg));
 
         /* If CPLVirtualMemManagerTerminate() is called, it will use BYEBYE_ADDR as a */
         /* means to ask for our termination */
@@ -1761,13 +1673,13 @@ static void CPLVirtualMemManagerThread(void* unused_param)
 
         /* Lookup for a mapping that contains addr */
         CPLAcquireMutex(hVirtualMemManagerMutex, 1000.0);
-        for(i=0;i<pVirtualMemManager->nVirtualMemCount;i++)
+        for( int i=0; i < pVirtualMemManager->nVirtualMemCount; i++ )
         {
             ctxt = pVirtualMemManager->pasVirtualMem[i];
-            if( (char*)msg.pFaultAddr >= (char*) ctxt->pData &&
-                (char*)msg.pFaultAddr < (char*) ctxt->pData + ctxt->nSize )
+            if( (char*)msg.pFaultAddr >= (char*) ctxt->sBase.pData &&
+                (char*)msg.pFaultAddr < (char*) ctxt->sBase.pData + ctxt->sBase.nSize )
             {
-                bMappingFound = TRUE;
+                bMappingFound = true;
                 break;
             }
         }
@@ -1775,9 +1687,12 @@ static void CPLVirtualMemManagerThread(void* unused_param)
 
         if( bMappingFound )
         {
-            char* start_page_addr = (char*)ALIGN_DOWN(msg.pFaultAddr, ctxt->nPageSize);
-            int iPage = (int)
-                (((char*)start_page_addr - (char*)ctxt->pData) / ctxt->nPageSize);
+            char * const start_page_addr =
+                reinterpret_cast<char*>(
+                    ALIGN_DOWN(msg.pFaultAddr, ctxt->sBase.nPageSize));
+            const int iPage = static_cast<int>(
+                ((char*)start_page_addr -
+                 (char*)ctxt->sBase.pData) / ctxt->sBase.nPageSize);
 
             if( iPage == ctxt->iLastPage )
             {
@@ -1791,24 +1706,33 @@ static void CPLVirtualMemManagerThread(void* unused_param)
                 /* at least the number of concurrent threads. 100 seems */
                 /* to be really safe ! */
                 ctxt->nRetry ++;
-                /* fprintfstderr("retry on page %d : %d\n", (int)iPage, ctxt->nRetry); */
+#if defined DEBUG_VIRTUALMEM && defined DEBUG_VERBOSE
+                fprintfstderr("retry on page %d : %d\n",
+                              iPage, ctxt->nRetry);
+#endif
                 if( ctxt->nRetry >= 100 )
                 {
                     CPLError(CE_Failure, CPLE_AppDefined,
                              "CPLVirtualMemManagerThread: trying to "
                              "write into read-only mapping");
-                    assert(write(pVirtualMemManager->pipefd_from_thread[1],
-                                    MAPPING_NOT_FOUND, 4) == 4);
+                    nRetWrite = write(pVirtualMemManager->pipefd_from_thread[1],
+                                    MAPPING_NOT_FOUND, 4);
+                    IGNORE_OR_ASSERT_IN_DEBUG(nRetWrite == 4);
                     break;
                 }
                 else if( msg.opType != OP_LOAD &&
-                         ctxt->eAccessMode == VIRTUALMEM_READWRITE &&
+                         ctxt->sBase.eAccessMode == VIRTUALMEM_READWRITE &&
                          !TEST_BIT(ctxt->pabitRWMappedPages, iPage) )
                 {
-                    /* fprintfstderr("switching page %d to write mode\n", (int)iPage); */
+#if defined DEBUG_VIRTUALMEM && defined DEBUG_VERBOSE
+                    fprintfstderr("switching page %d to write mode\n",
+                                  iPage);
+#endif
                     SET_BIT(ctxt->pabitRWMappedPages, iPage);
-                    assert(mprotect(start_page_addr, ctxt->nPageSize,
-                                    PROT_READ | PROT_WRITE) == 0);
+                    const int nRet =
+                        mprotect(start_page_addr, ctxt->sBase.nPageSize,
+                                 PROT_READ | PROT_WRITE);
+                    IGNORE_OR_ASSERT_IN_DEBUG(nRet == 0);
                 }
             }
             else
@@ -1819,37 +1743,42 @@ static void CPLVirtualMemManagerThread(void* unused_param)
                 if( TEST_BIT(ctxt->pabitMappedPages, iPage) )
                 {
                     if( msg.opType != OP_LOAD &&
-                        ctxt->eAccessMode == VIRTUALMEM_READWRITE &&
+                        ctxt->sBase.eAccessMode == VIRTUALMEM_READWRITE &&
                         !TEST_BIT(ctxt->pabitRWMappedPages, iPage) )
                     {
-                        /*fprintfstderr("switching page %d to write mode\n",
-                                iPage);*/
+#if defined DEBUG_VIRTUALMEM && defined DEBUG_VERBOSE
+                        fprintfstderr("switching page %d to write mode\n",
+                                      iPage);
+#endif
                         SET_BIT(ctxt->pabitRWMappedPages, iPage);
-                        assert(mprotect(start_page_addr, ctxt->nPageSize,
-                                        PROT_READ | PROT_WRITE) == 0);
+                        const int nRet =
+                            mprotect(start_page_addr, ctxt->sBase.nPageSize,
+                                     PROT_READ | PROT_WRITE);
+                        IGNORE_OR_ASSERT_IN_DEBUG(nRet == 0);
                     }
                     else
                     {
-                        /*fprintfstderr("unexpected case for page %d\n",
-                                iPage);*/
+#if defined DEBUG_VIRTUALMEM && defined DEBUG_VERBOSE
+                        fprintfstderr("unexpected case for page %d\n",
+                                      iPage);
+#endif
                     }
                 }
                 else
                 {
-                    void* pPageToFill;
-                    size_t nToFill;
-                    pPageToFill = CPLVirtualMemGetPageToFill(ctxt, start_page_addr);
+                    void * const pPageToFill =
+                        CPLVirtualMemGetPageToFill(ctxt, start_page_addr);
 
-                    nToFill = ctxt->nPageSize;
-                    if( start_page_addr + nToFill >= (char*) ctxt->pData + ctxt->nSize )
-                        nToFill = (char*) ctxt->pData + ctxt->nSize - start_page_addr;
+                    size_t nToFill = ctxt->sBase.nPageSize;
+                    if( start_page_addr + nToFill >= (char*) ctxt->sBase.pData + ctxt->sBase.nSize )
+                        nToFill = (char*) ctxt->sBase.pData + ctxt->sBase.nSize - start_page_addr;
 
                     ctxt->pfnCachePage(
-                            ctxt,
-                            start_page_addr - (char*) ctxt->pData,
+                            (CPLVirtualMem*)ctxt,
+                            start_page_addr - (char*) ctxt->sBase.pData,
                             pPageToFill,
                             nToFill,
-                            ctxt->pCbkUserData);
+                            ctxt->sBase.pCbkUserData);
 
                     /* Now remap this page to its target address and */
                     /* register it in the LRU */
@@ -1859,18 +1788,20 @@ static void CPLVirtualMemManagerThread(void* unused_param)
             }
 
             /* Warn the segfault handler that we have finished our job */
-            assert(write(pVirtualMemManager->pipefd_from_thread[1],
-                            MAPPING_FOUND, 4) == 4);
+            nRetWrite = write(pVirtualMemManager->pipefd_from_thread[1],
+                            MAPPING_FOUND, 4);
+            IGNORE_OR_ASSERT_IN_DEBUG(nRetWrite == 4);
         }
         else
         {
-            /* Warn the segfault handler that we have finished our job */
-            /* but that the fault didn't occur in a memory range that is under */
-            /* our responsability */
+            // Warn the segfault handler that we have finished our job
+            // but that the fault didn't occur in a memory range that
+            // is under our responsibility.
             CPLError(CE_Failure, CPLE_AppDefined,
                      "CPLVirtualMemManagerThread: no mapping found");
-            assert(write(pVirtualMemManager->pipefd_from_thread[1],
-                         MAPPING_NOT_FOUND, 4) == 4);
+            nRetWrite = write(pVirtualMemManager->pipefd_from_thread[1],
+                         MAPPING_NOT_FOUND, 4);
+            IGNORE_OR_ASSERT_IN_DEBUG(nRetWrite == 4);
         }
     }
 }
@@ -1879,30 +1810,43 @@ static void CPLVirtualMemManagerThread(void* unused_param)
 /*                       CPLVirtualMemManagerInit()                     */
 /************************************************************************/
 
-static void CPLVirtualMemManagerInit(void)
+static bool CPLVirtualMemManagerInit(void)
 {
     CPLMutexHolderD(&hVirtualMemManagerMutex);
     if( pVirtualMemManager != NULL )
-        return;
+        return true;
 
     struct sigaction act;
-    pVirtualMemManager = (CPLVirtualMemManager*) CPLMalloc(sizeof(CPLVirtualMemManager));
+    pVirtualMemManager = static_cast<CPLVirtualMemManager *>(
+        VSI_MALLOC_VERBOSE(sizeof(CPLVirtualMemManager)) );
+    if( pVirtualMemManager == NULL )
+        return false;
     pVirtualMemManager->pasVirtualMem = NULL;
     pVirtualMemManager->nVirtualMemCount = 0;
-    assert(pipe(pVirtualMemManager->pipefd_to_thread) == 0);
-    assert(pipe(pVirtualMemManager->pipefd_from_thread) == 0);
-    assert(pipe(pVirtualMemManager->pipefd_wait_thread) == 0);
+    int nRet = pipe(pVirtualMemManager->pipefd_to_thread);
+    IGNORE_OR_ASSERT_IN_DEBUG(nRet == 0);
+    nRet = pipe(pVirtualMemManager->pipefd_from_thread);
+    IGNORE_OR_ASSERT_IN_DEBUG(nRet == 0);
+    nRet = pipe(pVirtualMemManager->pipefd_wait_thread);
+    IGNORE_OR_ASSERT_IN_DEBUG(nRet == 0);
 
     /* Install our custom SIGSEGV handler */
     act.sa_sigaction = CPLVirtualMemManagerSIGSEGVHandler;
     sigemptyset (&act.sa_mask);
     act.sa_flags = SA_SIGINFO;
-    assert(sigaction(SIGSEGV, &act, &pVirtualMemManager->oldact) == 0);
+    nRet = sigaction(SIGSEGV, &act, &pVirtualMemManager->oldact);
+    IGNORE_OR_ASSERT_IN_DEBUG(nRet == 0);
 
     /* Starts the helper thread */
     pVirtualMemManager->hHelperThread =
             CPLCreateJoinableThread(CPLVirtualMemManagerThread, NULL);
-    assert(pVirtualMemManager->hHelperThread != NULL);
+    if( pVirtualMemManager->hHelperThread == NULL )
+    {
+        VSIFree(pVirtualMemManager);
+        pVirtualMemManager = NULL;
+        return false;
+    }
+    return true;
 }
 
 /************************************************************************/
@@ -1911,29 +1855,31 @@ static void CPLVirtualMemManagerInit(void)
 
 void CPLVirtualMemManagerTerminate(void)
 {
-    char wait_ready;
-    CPLVirtualMemMsgToWorkerThread msg;
-
     if( pVirtualMemManager == NULL )
         return;
 
+    CPLVirtualMemMsgToWorkerThread msg;
     msg.pFaultAddr = BYEBYE_ADDR;
     msg.opType = OP_UNKNOWN;
     memset(&msg.hRequesterThread, 0, sizeof(msg.hRequesterThread));
 
     /* Wait for the helper thread to be ready */
-    assert(read(pVirtualMemManager->pipefd_wait_thread[0],
-                &wait_ready, 1) == 1);
+    char wait_ready;
+    const ssize_t nRetRead =
+        read(pVirtualMemManager->pipefd_wait_thread[0], &wait_ready, 1);
+    IGNORE_OR_ASSERT_IN_DEBUG(nRetRead == 1);
 
     /* Ask it to terminate */
-    assert(write(pVirtualMemManager->pipefd_to_thread[1], &msg, sizeof(msg)) == sizeof(msg));
+    const ssize_t nRetWrite =
+        write(pVirtualMemManager->pipefd_to_thread[1], &msg, sizeof(msg));
+    IGNORE_OR_ASSERT_IN_DEBUG(nRetWrite == sizeof(msg));
 
     /* Wait for its termination */
     CPLJoinThread(pVirtualMemManager->hHelperThread);
 
     /* Cleanup everything */
     while(pVirtualMemManager->nVirtualMemCount > 0)
-        CPLVirtualMemFree(pVirtualMemManager->pasVirtualMem[pVirtualMemManager->nVirtualMemCount - 1]);
+        CPLVirtualMemFree((CPLVirtualMem*)pVirtualMemManager->pasVirtualMem[pVirtualMemManager->nVirtualMemCount - 1]);
     CPLFree(pVirtualMemManager->pasVirtualMem);
 
     close(pVirtualMemManager->pipefd_to_thread[0]);
@@ -1953,107 +1899,321 @@ void CPLVirtualMemManagerTerminate(void)
     hVirtualMemManagerMutex = NULL;
 }
 
-#else /* defined(__linux) && defined(CPL_MULTIPROC_PTHREAD) */
-
-size_t CPLGetPageSize(void)
-{
-    return 0;
-}
-
-CPLVirtualMem *CPLVirtualMemNew(CPL_UNUSED size_t nSize,
-                                CPL_UNUSED size_t nCacheSize,
-                                CPL_UNUSED size_t nPageSizeHint,
-                                CPL_UNUSED int bSingleThreadUsage,
-                                CPL_UNUSED CPLVirtualMemAccessMode eAccessMode,
-                                CPL_UNUSED CPLVirtualMemCachePageCbk pfnCachePage,
-                                CPL_UNUSED CPLVirtualMemUnCachePageCbk pfnUnCachePage,
-                                CPL_UNUSED CPLVirtualMemFreeUserData pfnFreeUserData,
-                                CPL_UNUSED void *pCbkUserData)
+#else /* HAVE_VIRTUAL_MEM_VMA */
+
+CPLVirtualMem *CPLVirtualMemNew( size_t /* nSize */,
+                                 size_t /* nCacheSize */,
+                                 size_t /* nPageSizeHint */,
+                                 int /* bSingleThreadUsage */,
+                                 CPLVirtualMemAccessMode /* eAccessMode */,
+                                 CPLVirtualMemCachePageCbk /* pfnCachePage */,
+                                 CPLVirtualMemUnCachePageCbk /* pfnUnCachePage */,
+                                 CPLVirtualMemFreeUserData /* pfnFreeUserData */,
+                                 void * /* pCbkUserData  */)
 {
     CPLError(CE_Failure, CPLE_NotSupported,
-             "CPLVirtualMemNew() unsupported on this operating system / configuration");
+             "CPLVirtualMemNew() unsupported on "
+             "this operating system / configuration");
     return NULL;
 }
 
-int CPLIsVirtualMemFileMapAvailable(void)
+void CPLVirtualMemDeclareThread( CPLVirtualMem* /* ctxt */ ) {}
+
+void CPLVirtualMemUnDeclareThread( CPLVirtualMem* /* ctxt */ ) {}
+
+void CPLVirtualMemPin( CPLVirtualMem* /* ctxt */,
+                       void* /* pAddr */,
+                       size_t /* nSize */,
+                       int /* bWriteOp */)
+{}
+
+void CPLVirtualMemManagerTerminate(void) {}
+
+#endif /* HAVE_VIRTUAL_MEM_VMA */
+
+
+#ifdef HAVE_MMAP
+
+/************************************************************************/
+/*                     CPLVirtualMemFreeFileMemoryMapped()              */
+/************************************************************************/
+
+static void CPLVirtualMemFreeFileMemoryMapped(CPLVirtualMem* ctxt)
 {
-    return FALSE;
+    const size_t nMappingSize =
+        ctxt->nSize + (GByte*)ctxt->pData - (GByte*)ctxt->pDataToFree;
+    const int nRet = munmap(ctxt->pDataToFree, nMappingSize);
+    IGNORE_OR_ASSERT_IN_DEBUG(nRet == 0);
 }
 
-CPLVirtualMem *CPLVirtualMemFileMapNew(CPL_UNUSED VSILFILE* fp,
-                                       CPL_UNUSED vsi_l_offset nOffset,
-                                       CPL_UNUSED vsi_l_offset nLength,
-                                       CPL_UNUSED CPLVirtualMemAccessMode eAccessMode,
-                                       CPL_UNUSED CPLVirtualMemFreeUserData pfnFreeUserData,
-                                       CPL_UNUSED void *pCbkUserData)
+/************************************************************************/
+/*                       CPLVirtualMemFileMapNew()                      */
+/************************************************************************/
+
+CPLVirtualMem *CPLVirtualMemFileMapNew( VSILFILE* fp,
+                                        vsi_l_offset nOffset,
+                                        vsi_l_offset nLength,
+                                        CPLVirtualMemAccessMode eAccessMode,
+                                        CPLVirtualMemFreeUserData pfnFreeUserData,
+                                        void *pCbkUserData )
 {
-    CPLError(CE_Failure, CPLE_NotSupported,
-             "CPLVirtualMemFileMapNew() unsupported on this operating system / configuration");
-    return NULL;
+#if SIZEOF_VOIDP == 4
+    if( nLength != (size_t)nLength )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "nLength = " CPL_FRMT_GUIB " incompatible with 32 bit architecture",
+                 nLength);
+        return NULL;
+    }
+    if( nOffset + CPLGetPageSize() !=
+        static_cast<vsi_l_offset>(
+            static_cast<off_t>(nOffset + CPLGetPageSize())) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "nOffset = " CPL_FRMT_GUIB
+                 " incompatible with 32 bit architecture",
+                 nOffset);
+        return NULL;
+    }
+#endif
+
+    int fd = (int) (size_t) VSIFGetNativeFileDescriptorL(fp);
+    if( fd == 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot operate on a virtual file");
+        return NULL;
+    }
+
+    const off_t nAlignedOffset =
+        static_cast<off_t>((nOffset / CPLGetPageSize()) * CPLGetPageSize());
+    size_t nAligment = static_cast<size_t>(nOffset - nAlignedOffset);
+    size_t nMappingSize = static_cast<size_t>(nLength + nAligment);
+
+    /* We need to ensure that the requested extent fits into the file size */
+    /* otherwise SIGBUS errors will occur when using the mapping */
+    vsi_l_offset nCurPos = VSIFTellL(fp);
+    if( VSIFSeekL(fp, 0, SEEK_END) != 0 )
+        return NULL;
+    vsi_l_offset nFileSize = VSIFTellL(fp);
+    if( nFileSize < nOffset + nLength )
+    {
+        if( eAccessMode != VIRTUALMEM_READWRITE )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Trying to map an extent outside of the file");
+            CPL_IGNORE_RET_VAL(VSIFSeekL(fp, nCurPos, SEEK_SET));
+            return NULL;
+        }
+        else
+        {
+            char ch = 0;
+            if( VSIFSeekL(fp, nOffset + nLength - 1, SEEK_SET) != 0 ||
+                VSIFWriteL(&ch, 1, 1, fp) != 1 )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Cannot extend file to mapping size");
+                CPL_IGNORE_RET_VAL(VSIFSeekL(fp, nCurPos, SEEK_SET));
+                return NULL;
+            }
+        }
+    }
+    if( VSIFSeekL(fp, nCurPos, SEEK_SET) != 0 )
+        return NULL;
+
+    CPLVirtualMem* ctxt = static_cast<CPLVirtualMem *>(
+        VSI_CALLOC_VERBOSE(1, sizeof(CPLVirtualMem)));
+    if( ctxt == NULL )
+        return NULL;
+
+    void* addr = mmap(NULL, nMappingSize,
+                      (eAccessMode == VIRTUALMEM_READWRITE) ? PROT_READ | PROT_WRITE : PROT_READ,
+                      MAP_SHARED, fd, nAlignedOffset);
+    if( addr == MAP_FAILED )
+    {
+        int myerrno = errno;
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "mmap() failed : %s", strerror(myerrno));
+        VSIFree(ctxt);
+        return NULL;
+    }
+
+    ctxt->eType = VIRTUAL_MEM_TYPE_FILE_MEMORY_MAPPED;
+    ctxt->nRefCount = 1;
+    ctxt->eAccessMode = eAccessMode;
+    ctxt->pData = (GByte*) addr + nAligment;
+    ctxt->pDataToFree = addr;
+    ctxt->nSize = static_cast<size_t>(nLength);
+    ctxt->nPageSize = CPLGetPageSize();
+    ctxt->bSingleThreadUsage = FALSE;
+    ctxt->pfnFreeUserData = pfnFreeUserData;
+    ctxt->pCbkUserData = pCbkUserData;
+
+    return ctxt;
 }
 
-CPLVirtualMem *CPLVirtualMemDerivedNew(CPL_UNUSED CPLVirtualMem* pVMemBase,
-                                       CPL_UNUSED vsi_l_offset nOffset,
-                                       CPL_UNUSED vsi_l_offset nSize,
-                                       CPL_UNUSED CPLVirtualMemFreeUserData pfnFreeUserData,
-                                       CPL_UNUSED void *pCbkUserData)
+#else /* HAVE_MMAP */
+
+
+CPLVirtualMem *CPLVirtualMemFileMapNew( VSILFILE* /* fp */,
+                                        vsi_l_offset /* nOffset */,
+                                        vsi_l_offset /* nLength */,
+                                        CPLVirtualMemAccessMode /* eAccessMode */,
+                                        CPLVirtualMemFreeUserData /* pfnFreeUserData */,
+                                        void * /* pCbkUserData */)
 {
     CPLError(CE_Failure, CPLE_NotSupported,
-             "CPLVirtualMemDerivedNew() unsupported on this operating system / configuration");
+             "CPLVirtualMemFileMapNew() unsupported on this "
+             "operating system / configuration");
     return NULL;
 }
 
-void CPLVirtualMemFree(CPL_UNUSED CPLVirtualMem* ctxt)
-{
-}
 
-void* CPLVirtualMemGetAddr(CPL_UNUSED CPLVirtualMem* ctxt)
-{
-    return NULL;
-}
+#endif /* HAVE_MMAP */
+
+/************************************************************************/
+/*                         CPLGetPageSize()                             */
+/************************************************************************/
 
-size_t CPLVirtualMemGetSize(CPL_UNUSED CPLVirtualMem* ctxt)
+size_t CPLGetPageSize(void)
 {
+#if defined(HAVE_MMAP) || defined(HAVE_VIRTUAL_MEM_VMA)
+    return static_cast<size_t>( sysconf(_SC_PAGESIZE) );
+#else
     return 0;
+#endif
 }
 
-int CPLVirtualMemIsFileMapping(CPL_UNUSED CPLVirtualMem* ctxt)
+/************************************************************************/
+/*                   CPLIsVirtualMemFileMapAvailable()                  */
+/************************************************************************/
+
+int CPLIsVirtualMemFileMapAvailable(void)
 {
+#ifdef HAVE_MMAP
+    return TRUE;
+#else
     return FALSE;
+#endif
 }
 
-CPLVirtualMemAccessMode CPLVirtualMemGetAccessMode(CPL_UNUSED CPLVirtualMem* ctxt)
+/************************************************************************/
+/*                        CPLVirtualMemFree()                           */
+/************************************************************************/
+
+void CPLVirtualMemFree(CPLVirtualMem* ctxt)
 {
-    return VIRTUALMEM_READONLY;
+    if( ctxt == NULL || --(ctxt->nRefCount) > 0 )
+        return;
+
+    if( ctxt->pVMemBase != NULL )
+    {
+        CPLVirtualMemFree(ctxt->pVMemBase);
+        if( ctxt->pfnFreeUserData != NULL )
+            ctxt->pfnFreeUserData(ctxt->pCbkUserData);
+        CPLFree(ctxt);
+        return;
+    }
+
+#ifdef HAVE_MMAP
+    if( ctxt->eType == VIRTUAL_MEM_TYPE_FILE_MEMORY_MAPPED )
+        CPLVirtualMemFreeFileMemoryMapped(ctxt);
+#endif
+#ifdef HAVE_VIRTUAL_MEM_VMA
+    if( ctxt->eType == VIRTUAL_MEM_TYPE_VMA )
+      CPLVirtualMemFreeFileMemoryMapped(
+          reinterpret_cast<CPLVirtualMemVMA*>(ctxt));
+#endif
+
+    if( ctxt->pfnFreeUserData != NULL )
+        ctxt->pfnFreeUserData(ctxt->pCbkUserData);
+    CPLFree(ctxt);
 }
 
-size_t CPLVirtualMemGetPageSize(CPL_UNUSED CPLVirtualMem* ctxt)
+/************************************************************************/
+/*                      CPLVirtualMemGetAddr()                          */
+/************************************************************************/
+
+void* CPLVirtualMemGetAddr(CPLVirtualMem* ctxt)
 {
-    return 0;
+    return ctxt->pData;
 }
 
-int CPLVirtualMemIsAccessThreadSafe(CPL_UNUSED CPLVirtualMem* ctxt)
+/************************************************************************/
+/*                     CPLVirtualMemIsFileMapping()                     */
+/************************************************************************/
+
+int CPLVirtualMemIsFileMapping(CPLVirtualMem* ctxt)
 {
-    return FALSE;
+    return ctxt->eType == VIRTUAL_MEM_TYPE_FILE_MEMORY_MAPPED;
 }
 
-void CPLVirtualMemDeclareThread(CPL_UNUSED CPLVirtualMem* ctxt)
+/************************************************************************/
+/*                     CPLVirtualMemGetAccessMode()                     */
+/************************************************************************/
+
+CPLVirtualMemAccessMode CPLVirtualMemGetAccessMode(CPLVirtualMem* ctxt)
 {
+    return ctxt->eAccessMode;
 }
 
-void CPLVirtualMemUnDeclareThread(CPL_UNUSED CPLVirtualMem* ctxt)
+/************************************************************************/
+/*                      CPLVirtualMemGetPageSize()                      */
+/************************************************************************/
+
+size_t CPLVirtualMemGetPageSize(CPLVirtualMem* ctxt)
 {
+    return ctxt->nPageSize;
 }
 
-void CPLVirtualMemPin(CPL_UNUSED CPLVirtualMem* ctxt,
-                      CPL_UNUSED void* pAddr,
-                      CPL_UNUSED size_t nSize,
-                      CPL_UNUSED int bWriteOp)
+/************************************************************************/
+/*                        CPLVirtualMemGetSize()                        */
+/************************************************************************/
+
+size_t CPLVirtualMemGetSize(CPLVirtualMem* ctxt)
 {
+    return ctxt->nSize;
 }
 
-void CPLVirtualMemManagerTerminate(void)
+/************************************************************************/
+/*                   CPLVirtualMemIsAccessThreadSafe()                  */
+/************************************************************************/
+
+int CPLVirtualMemIsAccessThreadSafe(CPLVirtualMem* ctxt)
 {
+    return !ctxt->bSingleThreadUsage;
 }
 
-#endif /* defined(__linux) && defined(CPL_MULTIPROC_PTHREAD) */
+/************************************************************************/
+/*                       CPLVirtualMemDerivedNew()                      */
+/************************************************************************/
+
+CPLVirtualMem *CPLVirtualMemDerivedNew(CPLVirtualMem* pVMemBase,
+                                       vsi_l_offset nOffset,
+                                       vsi_l_offset nSize,
+                                       CPLVirtualMemFreeUserData pfnFreeUserData,
+                                       void *pCbkUserData)
+{
+    if( nOffset + nSize > pVMemBase->nSize )
+        return NULL;
+
+    CPLVirtualMem* ctxt = static_cast<CPLVirtualMem *>(
+        VSI_CALLOC_VERBOSE(1, sizeof(CPLVirtualMem)));
+    if( ctxt == NULL )
+        return NULL;
+
+    ctxt->eType = pVMemBase->eType;
+    ctxt->nRefCount = 1;
+    ctxt->pVMemBase = pVMemBase;
+    pVMemBase->nRefCount ++;
+    ctxt->eAccessMode = pVMemBase->eAccessMode;
+    ctxt->pData = static_cast<GByte *>(pVMemBase->pData) + nOffset;
+    ctxt->pDataToFree = NULL;
+    ctxt->nSize = static_cast<size_t>(nSize);
+    ctxt->nPageSize = pVMemBase->nPageSize;
+    ctxt->bSingleThreadUsage = pVMemBase->bSingleThreadUsage;
+    ctxt->pfnFreeUserData = pfnFreeUserData;
+    ctxt->pCbkUserData = pCbkUserData;
+
+    return ctxt;
+}
diff --git a/port/cpl_virtualmem.h b/port/cpl_virtualmem.h
index 2d6ed45..271c583 100644
--- a/port/cpl_virtualmem.h
+++ b/port/cpl_virtualmem.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_virtualmem.h 29330 2015-06-14 12:11:11Z rouault $
+ * $Id: cpl_virtualmem.h 33666 2016-03-07 05:21:07Z goatbar $
  *
  * Name:     cpl_virtualmem.h
  * Project:  CPL - Common Portability Library
@@ -15,21 +15,21 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef _CPL_VIRTUAL_MEM_INCLUDED
-#define _CPL_VIRTUAL_MEM_INCLUDED
+#ifndef CPL_VIRTUAL_MEM_INCLUDED
+#define CPL_VIRTUAL_MEM_INCLUDED
 
 #include "cpl_port.h"
 #include "cpl_vsi.h"
@@ -102,7 +102,7 @@ typedef enum
     /*! The mapping is meant at being read-only, but writes will not be prevented.
         Note that any content written will be lost. */
     VIRTUALMEM_READONLY,
-    /*! The mapping is meant at being read-only, and this will be enforced 
+    /*! The mapping is meant at being read-only, and this will be enforced
         through the operating system page protection mechanism. */
     VIRTUALMEM_READONLY_ENFORCED,
     /*! The mapping is meant at being read-write, and modified pages can be saved
@@ -192,7 +192,8 @@ int CPL_DLL CPLIsVirtualMemFileMapAvailable(void);
  * On Linux AMD64 platforms, the maximum value for nLength is 128 TB.
  * On Linux x86 platforms, the maximum value for nLength is 2 GB.
  *
- * Only supported on Linux for now.
+ * Supported on Linux only in GDAL <= 2.0, and all POSIX systems supporting
+ * mmap() in GDAL >= 2.1
  *
  * @param  fp       Virtual file handle.
  * @param  nOffset  Offset in the file to start the mapping from.
@@ -277,10 +278,10 @@ void CPL_DLL *CPLVirtualMemGetAddr(CPLVirtualMem* ctxt);
  */
 size_t CPL_DLL CPLVirtualMemGetSize(CPLVirtualMem* ctxt);
 
-/** Return if the virtal memory mapping is a direct file mapping.
+/** Return if the virtual memory mapping is a direct file mapping.
  *
  * @param ctxt context returned by CPLVirtualMemNew().
- * @return TRUE if the virtal memory mapping is a direct file mapping.
+ * @return TRUE if the virtual memory mapping is a direct file mapping.
  *
  * @since GDAL 1.11
  */
@@ -386,4 +387,4 @@ void CPL_DLL CPLVirtualMemManagerTerminate(void);
 
 CPL_C_END
 
-#endif /* _CPL_VIRTUAL_MEM_INCLUDED */
+#endif /* CPL_VIRTUAL_MEM_INCLUDED */
diff --git a/port/cpl_vsi.h b/port/cpl_vsi.h
index 23b3596..16768a2 100644
--- a/port/cpl_vsi.h
+++ b/port/cpl_vsi.h
@@ -1,10 +1,10 @@
 /******************************************************************************
- * $Id: cpl_vsi.h 28476 2015-02-13 14:40:11Z rouault $
+ * $Id: cpl_vsi.h 33758 2016-03-21 09:06:22Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  * Purpose:  Include file defining Virtual File System (VSI) functions, a
- *           layer over POSIX file and other system services. 
+ *           layer over POSIX file and other system services.
  *
  ******************************************************************************
  * Copyright (c) 1998, Frank Warmerdam
@@ -45,34 +45,32 @@
  * and reporting can be interested.  The memory access API is aliased
  * so that special application memory management services can be used.
  *
- * Is is intended that each of these functions retains exactly the same
+ * It is intended that each of these functions retains exactly the same
  * calling pattern as the original Standard C functions they relate to.
  * This means we don't have to provide custom documentation, and also means
  * that the default implementation is very simple.
  */
 
-
 /* -------------------------------------------------------------------- */
 /*      We need access to ``struct stat''.                              */
 /* -------------------------------------------------------------------- */
 
 /* Unix */
-#if !defined(_WIN32) && !defined(_WIN32_WCE)
+#if !defined(_WIN32)
 #  include <unistd.h>
 #endif
 
 /* Windows */
-#if !defined(macos_pre10) && !defined(_WIN32_WCE)
-#  include <sys/stat.h>
-#endif
-
-/* Windows CE */
-#if defined(_WIN32_WCE)
-#  include <wce_stat.h>
-#endif
+#include <sys/stat.h>
 
 CPL_C_START
 
+#ifdef ENABLE_EXPERIMENTAL_CPL_WARN_UNUSED_RESULT
+#define EXPERIMENTAL_CPL_WARN_UNUSED_RESULT CPL_WARN_UNUSED_RESULT
+#else
+#define EXPERIMENTAL_CPL_WARN_UNUSED_RESULT
+#endif
+
 /* ==================================================================== */
 /*      stdio file access functions.  These may not support large       */
 /*      files, and don't necessarily go through the virtualization      */
@@ -81,28 +79,28 @@ CPL_C_START
 
 FILE CPL_DLL *  VSIFOpen( const char *, const char * ) CPL_WARN_UNUSED_RESULT;
 int CPL_DLL     VSIFClose( FILE * );
-int CPL_DLL     VSIFSeek( FILE *, long, int );
-long CPL_DLL    VSIFTell( FILE * );
+int CPL_DLL     VSIFSeek( FILE *, long, int ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT;
+long CPL_DLL    VSIFTell( FILE * ) CPL_WARN_UNUSED_RESULT;
 void CPL_DLL    VSIRewind( FILE * );
 void CPL_DLL    VSIFFlush( FILE * );
 
-size_t CPL_DLL  VSIFRead( void *, size_t, size_t, FILE * );
-size_t CPL_DLL  VSIFWrite( const void *, size_t, size_t, FILE * );
-char CPL_DLL   *VSIFGets( char *, int, FILE * );
-int CPL_DLL     VSIFPuts( const char *, FILE * );
-int CPL_DLL     VSIFPrintf( FILE *, const char *, ... ) CPL_PRINT_FUNC_FORMAT(2, 3);
+size_t CPL_DLL  VSIFRead( void *, size_t, size_t, FILE * ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT;
+size_t CPL_DLL  VSIFWrite( const void *, size_t, size_t, FILE * ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT;
+char CPL_DLL   *VSIFGets( char *, int, FILE * ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT;
+int CPL_DLL     VSIFPuts( const char *, FILE * ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT;
+int CPL_DLL     VSIFPrintf( FILE *, const char *, ... ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT CPL_PRINT_FUNC_FORMAT(2, 3);
 
-int CPL_DLL     VSIFGetc( FILE * );
-int CPL_DLL     VSIFPutc( int, FILE * );
-int CPL_DLL     VSIUngetc( int, FILE * );
-int CPL_DLL     VSIFEof( FILE * );
+int CPL_DLL     VSIFGetc( FILE * ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT;
+int CPL_DLL     VSIFPutc( int, FILE * ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT;
+int CPL_DLL     VSIUngetc( int, FILE * ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT;
+int CPL_DLL     VSIFEof( FILE * ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT;
 
 /* ==================================================================== */
 /*      VSIStat() related.                                              */
 /* ==================================================================== */
 
 typedef struct stat VSIStatBuf;
-int CPL_DLL VSIStat( const char *, VSIStatBuf * );
+int CPL_DLL VSIStat( const char *, VSIStatBuf * ) CPL_WARN_UNUSED_RESULT;
 
 #ifdef _WIN32
 #  define VSI_ISLNK(x)  ( 0 )            /* N/A on Windows */
@@ -120,10 +118,11 @@ int CPL_DLL VSIStat( const char *, VSIStatBuf * );
 
 /* ==================================================================== */
 /*      64bit stdio file access functions.  If we have a big size       */
-/*      defined, then provide protypes for the large file API,          */
+/*      defined, then provide prototypes for the large file API,        */
 /*      otherwise redefine to use the regular api.                      */
 /* ==================================================================== */
 typedef GUIntBig vsi_l_offset;
+#define VSI_L_OFFSET_MAX GUINTBIG_MAX
 
 /* Make VSIL_STRICT_ENFORCE active in DEBUG builds */
 #ifdef DEBUG
@@ -137,24 +136,25 @@ typedef FILE VSILFILE;
 #endif
 
 VSILFILE CPL_DLL *  VSIFOpenL( const char *, const char * ) CPL_WARN_UNUSED_RESULT;
-int CPL_DLL     VSIFCloseL( VSILFILE * );
-int CPL_DLL     VSIFSeekL( VSILFILE *, vsi_l_offset, int );
-vsi_l_offset CPL_DLL VSIFTellL( VSILFILE * );
+VSILFILE CPL_DLL *  VSIFOpenExL( const char *, const char *, int ) CPL_WARN_UNUSED_RESULT;
+int CPL_DLL     VSIFCloseL( VSILFILE * ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT;
+int CPL_DLL     VSIFSeekL( VSILFILE *, vsi_l_offset, int ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT;
+vsi_l_offset CPL_DLL VSIFTellL( VSILFILE * ) CPL_WARN_UNUSED_RESULT;
 void CPL_DLL    VSIRewindL( VSILFILE * );
-size_t CPL_DLL  VSIFReadL( void *, size_t, size_t, VSILFILE * );
-int CPL_DLL     VSIFReadMultiRangeL( int nRanges, void ** ppData, const vsi_l_offset* panOffsets, const size_t* panSizes, VSILFILE * );
-size_t CPL_DLL  VSIFWriteL( const void *, size_t, size_t, VSILFILE * );
-int CPL_DLL     VSIFEofL( VSILFILE * );
-int CPL_DLL     VSIFTruncateL( VSILFILE *, vsi_l_offset );
-int CPL_DLL     VSIFFlushL( VSILFILE * );
-int CPL_DLL     VSIFPrintfL( VSILFILE *, const char *, ... ) CPL_PRINT_FUNC_FORMAT(2, 3);
-int CPL_DLL     VSIFPutcL( int, VSILFILE * );
+size_t CPL_DLL  VSIFReadL( void *, size_t, size_t, VSILFILE * ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT;
+int CPL_DLL     VSIFReadMultiRangeL( int nRanges, void ** ppData, const vsi_l_offset* panOffsets, const size_t* panSizes, VSILFILE * ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT;
+size_t CPL_DLL  VSIFWriteL( const void *, size_t, size_t, VSILFILE * ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT;
+int CPL_DLL     VSIFEofL( VSILFILE * ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT;
+int CPL_DLL     VSIFTruncateL( VSILFILE *, vsi_l_offset ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT;
+int CPL_DLL     VSIFFlushL( VSILFILE * ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT;
+int CPL_DLL     VSIFPrintfL( VSILFILE *, const char *, ... ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT CPL_PRINT_FUNC_FORMAT(2, 3);
+int CPL_DLL     VSIFPutcL( int, VSILFILE * ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT;
 
 int CPL_DLL     VSIIngestFile( VSILFILE* fp,
                                const char* pszFilename,
                                GByte** ppabyRet,
                                vsi_l_offset* pnSize,
-                               GIntBig nMaxSize );
+                               GIntBig nMaxSize ) CPL_WARN_UNUSED_RESULT;
 
 #if defined(VSI_STAT64_T)
 typedef struct VSI_STAT64_T VSIStatBufL;
@@ -162,13 +162,14 @@ typedef struct VSI_STAT64_T VSIStatBufL;
 #define VSIStatBufL    VSIStatBuf
 #endif
 
-int CPL_DLL     VSIStatL( const char *, VSIStatBufL * );
+int CPL_DLL     VSIStatL( const char *, VSIStatBufL * ) CPL_WARN_UNUSED_RESULT;
 
-#define VSI_STAT_EXISTS_FLAG    0x1
-#define VSI_STAT_NATURE_FLAG    0x2
-#define VSI_STAT_SIZE_FLAG      0x4
+#define VSI_STAT_EXISTS_FLAG         0x1
+#define VSI_STAT_NATURE_FLAG         0x2
+#define VSI_STAT_SIZE_FLAG           0x4
+#define VSI_STAT_SET_ERROR_FLAG      0x8
 
-int CPL_DLL     VSIStatExL( const char * pszFilename, VSIStatBufL * psStatBuf, int nFlags );
+int CPL_DLL     VSIStatExL( const char * pszFilename, VSIStatBufL * psStatBuf, int nFlags ) CPL_WARN_UNUSED_RESULT;
 
 int CPL_DLL     VSIIsCaseSensitiveFS( const char * pszFilename );
 
@@ -202,6 +203,26 @@ void CPL_DLL *VSIMalloc2( size_t nSize1, size_t nSize2 ) CPL_WARN_UNUSED_RESULT;
 */
 void CPL_DLL *VSIMalloc3( size_t nSize1, size_t nSize2, size_t nSize3 ) CPL_WARN_UNUSED_RESULT;
 
+
+void CPL_DLL   *VSIMallocVerbose( size_t nSize, const char* pszFile, int nLine ) CPL_WARN_UNUSED_RESULT;
+#define VSI_MALLOC_VERBOSE( size ) VSIMallocVerbose(size,__FILE__,__LINE__)
+
+void CPL_DLL   *VSIMalloc2Verbose( size_t nSize1, size_t nSize2, const char* pszFile, int nLine ) CPL_WARN_UNUSED_RESULT;
+#define VSI_MALLOC2_VERBOSE( nSize1, nSize2 ) VSIMalloc2Verbose(nSize1,nSize2,__FILE__,__LINE__)
+
+void CPL_DLL   *VSIMalloc3Verbose( size_t nSize1, size_t nSize2, size_t nSize3, const char* pszFile, int nLine ) CPL_WARN_UNUSED_RESULT;
+#define VSI_MALLOC3_VERBOSE( nSize1, nSize2, nSize3 ) VSIMalloc3Verbose(nSize1,nSize2,nSize3,__FILE__,__LINE__)
+
+void CPL_DLL   *VSICallocVerbose(  size_t nCount, size_t nSize, const char* pszFile, int nLine ) CPL_WARN_UNUSED_RESULT;
+#define VSI_CALLOC_VERBOSE( nCount, nSize ) VSICallocVerbose(nCount,nSize,__FILE__,__LINE__)
+
+void CPL_DLL   *VSIReallocVerbose(  void* pOldPtr, size_t nNewSize, const char* pszFile, int nLine ) CPL_WARN_UNUSED_RESULT;
+#define VSI_REALLOC_VERBOSE( pOldPtr, nNewSize ) VSIReallocVerbose(pOldPtr,nNewSize,__FILE__,__LINE__)
+
+char CPL_DLL   *VSIStrdupVerbose(  const char* pszStr, const char* pszFile, int nLine ) CPL_WARN_UNUSED_RESULT;
+#define VSI_STRDUP_VERBOSE( pszStr ) VSIStrdupVerbose(pszStr,__FILE__,__LINE__)
+
+
 GIntBig CPL_DLL CPLGetPhysicalRAM(void);
 GIntBig CPL_DLL CPLGetUsablePhysicalRAM(void);
 
@@ -212,11 +233,13 @@ GIntBig CPL_DLL CPLGetUsablePhysicalRAM(void);
 #define CPLReadDir VSIReadDir
 char CPL_DLL **VSIReadDir( const char * );
 char CPL_DLL **VSIReadDirRecursive( const char *pszPath );
+char CPL_DLL **VSIReadDirEx( const char *pszPath, int nMaxFiles );
 int CPL_DLL VSIMkdir( const char * pathname, long mode );
 int CPL_DLL VSIRmdir( const char * pathname );
 int CPL_DLL VSIUnlink( const char * pathname );
 int CPL_DLL VSIRename( const char * oldpath, const char * newpath );
 char CPL_DLL *VSIStrerror( int );
+GIntBig CPL_DLL VSIGetDiskFreeSpace(const char *pszDirname);
 
 /* ==================================================================== */
 /*      Install special file access handlers.                           */
@@ -226,27 +249,31 @@ void CPL_DLL VSIInstallLargeFileHandler(void);
 void CPL_DLL VSIInstallSubFileHandler(void);
 void VSIInstallCurlFileHandler(void);
 void VSIInstallCurlStreamingFileHandler(void);
+void VSIInstallS3FileHandler(void);
+void VSIInstallS3StreamingFileHandler(void);
 void VSIInstallGZipFileHandler(void); /* No reason to export that */
 void VSIInstallZipFileHandler(void); /* No reason to export that */
 void VSIInstallStdinHandler(void); /* No reason to export that */
 void VSIInstallStdoutHandler(void); /* No reason to export that */
 void CPL_DLL VSIInstallSparseFileHandler(void);
 void VSIInstallTarFileHandler(void); /* No reason to export that */
+void CPL_DLL VSIInstallCryptFileHandler(void);
+void CPL_DLL VSISetCryptKey(const GByte* pabyKey, int nKeySize);
 void CPL_DLL VSICleanupFileManager(void);
 
 VSILFILE CPL_DLL *VSIFileFromMemBuffer( const char *pszFilename,
-                                    GByte *pabyData, 
+                                    GByte *pabyData,
                                     vsi_l_offset nDataLength,
-                                    int bTakeOwnership );
-GByte CPL_DLL *VSIGetMemFileBuffer( const char *pszFilename, 
-                                    vsi_l_offset *pnDataLength, 
+                                    int bTakeOwnership ) CPL_WARN_UNUSED_RESULT;
+GByte CPL_DLL *VSIGetMemFileBuffer( const char *pszFilename,
+                                    vsi_l_offset *pnDataLength,
                                     int bUnlinkAndSeize );
 
 typedef size_t (*VSIWriteFunction)(const void* ptr, size_t size, size_t nmemb, FILE* stream);
 void CPL_DLL VSIStdoutSetRedirection( VSIWriteFunction pFct, FILE* stream );
 
 /* ==================================================================== */
-/*      Time quering.                                                   */
+/*      Time querying.                                                  */
 /* ==================================================================== */
 
 unsigned long CPL_DLL VSITime( unsigned long * );
diff --git a/port/cpl_vsi_error.cpp b/port/cpl_vsi_error.cpp
new file mode 100644
index 0000000..60b3b95
--- /dev/null
+++ b/port/cpl_vsi_error.cpp
@@ -0,0 +1,295 @@
+/******************************************************************************
+ * $Id: cpl_vsi_error.cpp 33763 2016-03-21 16:31:17Z rouault $
+ *
+ * Project:  VSI Virtual File System
+ * Purpose:  Implement an error system for reporting file system errors.
+ *           Filesystem errors need to be handled separately from the
+ *           CPLError architecture because they are potentially ignored.
+ * Author:   Rob Emanuele, rdemanuele at gmail.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Rob Emanuele <rdemanuele at gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_vsi_error.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "cpl_conv.h"
+#include "cpl_multiproc.h"
+
+#if !defined(WIN32)
+#include <string.h>
+#endif
+
+
+#define TIMESTAMP_DEBUG
+//#define MEMORY_DEBUG
+
+CPL_CVSID("$Id: cpl_vsi_error.cpp 33763 2016-03-21 16:31:17Z rouault $");
+
+static const int DEFAULT_LAST_ERR_MSG_SIZE =
+#if !defined(HAVE_VSNPRINTF)
+  20000
+#else
+  500
+#endif
+  ;
+
+typedef struct {
+    VSIErrorNum nLastErrNo;
+    int     nLastErrMsgMax;
+    char    szLastErrMsg[DEFAULT_LAST_ERR_MSG_SIZE];
+    /* Do not add anything here. szLastErrMsg must be the last field. See CPLRealloc() below */
+} VSIErrorContext;
+
+static void VSIErrorV(VSIErrorNum, const char *, va_list );
+
+/************************************************************************/
+/*                         CPLGetErrorContext()                         */
+/************************************************************************/
+
+static VSIErrorContext *VSIGetErrorContext()
+
+{
+    int bError;
+    VSIErrorContext *psCtx =
+        reinterpret_cast<VSIErrorContext *>(
+            CPLGetTLSEx( CTLS_VSIERRORCONTEXT, &bError ) );
+    if( bError )
+        return NULL;
+
+    if( psCtx == NULL )
+    {
+      psCtx = reinterpret_cast<VSIErrorContext *>(
+          VSICalloc( sizeof(VSIErrorContext), 1) );
+        if (psCtx == NULL) {
+            fprintf(stderr, "Out of memory attempting to record a VSI error.\n");
+            return NULL;
+        }
+        psCtx->nLastErrNo = VSIE_None;
+        psCtx->nLastErrMsgMax = sizeof(psCtx->szLastErrMsg);
+        CPLSetTLS( CTLS_VSIERRORCONTEXT, psCtx, TRUE );
+    }
+
+    return psCtx;
+}
+
+/**********************************************************************
+ *                          VSIError()
+ **********************************************************************/
+
+/**
+ * Report an VSI filesystem error.
+ *
+ * This function records an error in the filesystem that may or may not be
+ * used in the future, for example converted into a CPLError. This allows
+ * filesystem errors to be available to error handling functionality, but
+ * reported only when necessary.
+ *
+ * @param err_no the error number (VSIE_*) from cpl_vsi_error.h.
+ * @param fmt a printf() style format string.  Any additional arguments
+ * will be treated as arguments to fill in this format in a manner
+ * similar to printf().
+ */
+
+void    VSIError(VSIErrorNum err_no, const char *fmt, ...)
+{
+    va_list args;
+
+    // Expand the error message
+    va_start(args, fmt);
+    VSIErrorV( err_no, fmt, args );
+    va_end(args);
+}
+
+/************************************************************************/
+/*                             VSIErrorV()                              */
+/************************************************************************/
+
+void    VSIErrorV( VSIErrorNum err_no, const char *fmt, va_list args )
+{
+    VSIErrorContext *psCtx = VSIGetErrorContext();
+    if( psCtx == NULL )
+      return;
+
+/* -------------------------------------------------------------------- */
+/*      Expand the error message                                        */
+/* -------------------------------------------------------------------- */
+#if defined(HAVE_VSNPRINTF)
+    {
+        va_list wrk_args;
+
+#ifdef va_copy
+        va_copy( wrk_args, args );
+#else
+        wrk_args = args;
+#endif
+
+        int nPreviousSize = 0;
+        int nPR;
+        while( ((nPR = CPLvsnprintf(
+                     psCtx->szLastErrMsg+nPreviousSize,
+                     psCtx->nLastErrMsgMax-nPreviousSize, fmt, wrk_args )) == -1
+                || nPR >= psCtx->nLastErrMsgMax-nPreviousSize-1)
+               && psCtx->nLastErrMsgMax < 1000000 )
+        {
+#ifdef va_copy
+            va_end( wrk_args );
+            va_copy( wrk_args, args );
+#else
+            wrk_args = args;
+#endif
+            psCtx->nLastErrMsgMax *= 3;
+            psCtx = static_cast<VSIErrorContext *> (
+                CPLRealloc( psCtx,
+                            sizeof(VSIErrorContext)
+                            - DEFAULT_LAST_ERR_MSG_SIZE
+                            + psCtx->nLastErrMsgMax + 1) );
+            CPLSetTLS( CTLS_ERRORCONTEXT, psCtx, TRUE );
+        }
+
+        va_end( wrk_args );
+    }
+#else
+    // !HAVE_VSNPRINTF
+    CPLvsnprintf( psCtx->szLastErrMsg, psCtx->nLastErrMsgMax, fmt, args);
+#endif
+
+    psCtx->nLastErrNo = err_no;
+}
+
+/**********************************************************************
+ *                          VSIErrorReset()
+ **********************************************************************/
+
+/**
+ * Erase any traces of previous errors.
+ *
+ * This is used to clear out the latest file system error when it is either translated
+ * into a CPLError call or when it is determined to be ignorable.
+ */
+
+void CPL_STDCALL VSIErrorReset()
+{
+    VSIErrorContext *psCtx = VSIGetErrorContext();
+    if( psCtx == NULL )
+        return;
+
+    psCtx->nLastErrNo = VSIE_None;
+    psCtx->szLastErrMsg[0] = '\0';
+}
+
+/**********************************************************************
+ *                          VSIGetLastErrorNo()
+ **********************************************************************/
+
+/**
+ * Fetch the last error number.
+ *
+ * Fetches the last error number posted with VSIError(), that hasn't
+ * been cleared by VSIErrorReset().  This is the error number, not the error
+ * class.
+ *
+ * @return the error number of the last error to occur, or VSIE_None (0)
+ * if there are no posted errors.
+ */
+
+VSIErrorNum CPL_STDCALL VSIGetLastErrorNo()
+{
+    VSIErrorContext *psCtx = VSIGetErrorContext();
+    if( psCtx == NULL )
+        return 0;
+
+    return psCtx->nLastErrNo;
+}
+
+/**********************************************************************
+ *                          VSIGetLastErrorMsg()
+ **********************************************************************/
+
+/**
+ * Get the last error message.
+ *
+ * Fetches the last error message posted with VSIError(), that hasn't
+ * been cleared by VSIErrorReset().  The returned pointer is to an internal
+ * string that should not be altered or freed.
+ *
+ * @return the last error message, or NULL if there is no posted error
+ * message.
+ */
+
+const char* CPL_STDCALL VSIGetLastErrorMsg()
+{
+    VSIErrorContext *psCtx = VSIGetErrorContext();
+    if( psCtx == NULL )
+        return "";
+
+    return psCtx->szLastErrMsg;
+}
+
+/**********************************************************************
+ *                          VSItoCPLError()
+ **********************************************************************/
+
+/**
+ * Translate the VSI error into a CPLError call
+ *
+ * If there is a VSIError that is set, translate it to a CPLError call
+ * with the given CPLErr error class, and either an appropriate CPLErrorNum
+ * given the VSIErrorNum, or the given default CPLErrorNum.
+ *
+ * @return TRUE if a CPLError was issued, or FALSE if not.
+ */
+
+int CPL_DLL CPL_STDCALL VSIToCPLError(CPLErr eErrClass, CPLErrorNum eDefaultErrorNo) {
+    int err = VSIGetLastErrorNo();
+    switch(err) {
+        case VSIE_None:
+            return FALSE;
+        case VSIE_FileError:
+            CPLError(eErrClass, eDefaultErrorNo, "%s", VSIGetLastErrorMsg());
+            break;
+        case VSIE_HttpError:
+            CPLError(eErrClass, CPLE_HttpResponse, "%s", VSIGetLastErrorMsg());
+            break;
+        case VSIE_AWSAccessDenied:
+            CPLError(eErrClass, CPLE_AWSAccessDenied, "%s", VSIGetLastErrorMsg());
+            break;
+        case VSIE_AWSBucketNotFound:
+            CPLError(eErrClass, CPLE_AWSBucketNotFound, "%s", VSIGetLastErrorMsg());
+            break;
+        case VSIE_AWSObjectNotFound:
+            CPLError(eErrClass, CPLE_AWSObjectNotFound, "%s", VSIGetLastErrorMsg());
+            break;
+        case VSIE_AWSInvalidCredentials:
+            CPLError(eErrClass, CPLE_AWSInvalidCredentials, "%s", VSIGetLastErrorMsg());
+            break;
+        case VSIE_AWSSignatureDoesNotMatch:
+            CPLError(eErrClass, CPLE_AWSSignatureDoesNotMatch, "%s", VSIGetLastErrorMsg());
+            break;
+        default:
+            CPLError(eErrClass, CPLE_HttpResponse, "A filesystem error with code %d occurred", err);
+            break;
+    }
+
+    return TRUE;
+}
diff --git a/port/cpl_vsi_error.h b/port/cpl_vsi_error.h
new file mode 100644
index 0000000..85f880f
--- /dev/null
+++ b/port/cpl_vsi_error.h
@@ -0,0 +1,67 @@
+/******************************************************************************
+ * $Id: cpl_vsi_error.h 33758 2016-03-21 09:06:22Z rouault $
+ *
+ * Project:  VSI Virtual File System
+ * Purpose:  Implement an error system for reporting file system errors.
+ *           Filesystem errors need to be handled separately from the
+ *           CPLError architecture because they are potentially ignored.
+ * Author:   Rob Emanuele, rdemanuele at gmail.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Rob Emanuele <rdemanuele at gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef CPL_VSI_ERROR_H_INCLUDED
+#define CPL_VSI_ERROR_H_INCLUDED
+
+#include "cpl_port.h"
+#include "cpl_error.h"
+
+/* ====================================================================
+        Filesystem error codes.
+   ==================================================================== */
+
+CPL_C_START
+
+typedef int VSIErrorNum;
+
+#define VSIE_None                       0
+#define VSIE_FileError                  1
+#define VSIE_HttpError                  2
+
+#define VSIE_AWSError                   5
+#define VSIE_AWSAccessDenied            6
+#define VSIE_AWSBucketNotFound          7
+#define VSIE_AWSObjectNotFound          8
+#define VSIE_AWSInvalidCredentials      9
+#define VSIE_AWSSignatureDoesNotMatch   10
+
+void CPL_DLL VSIError(VSIErrorNum err_no, const char *fmt, ...)  CPL_PRINT_FUNC_FORMAT (2, 3);
+
+void CPL_DLL CPL_STDCALL VSIErrorReset( void );
+VSIErrorNum CPL_DLL CPL_STDCALL VSIGetLastErrorNo( void );
+const char CPL_DLL * CPL_STDCALL VSIGetLastErrorMsg( void );
+
+int CPL_DLL CPL_STDCALL VSIToCPLError(CPLErr eErrClass, CPLErrorNum eDefaultErrorNo);
+
+CPL_C_END
+
+#endif /* CPL_VSI_ERROR_H_INCLUDED */
diff --git a/port/cpl_vsi_mem.cpp b/port/cpl_vsi_mem.cpp
index 65ca776..7fa4334 100644
--- a/port/cpl_vsi_mem.cpp
+++ b/port/cpl_vsi_mem.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsi_mem.cpp 29581 2015-07-27 20:06:02Z rouault $
+ * $Id: cpl_vsi_mem.cpp 33758 2016-03-21 09:06:22Z rouault $
  *
  * Project:  VSI Virtual File System
  * Purpose:  Implementation of Memory Buffer virtual IO functions.
@@ -28,29 +28,19 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-/* Remove annoying warnings in eVC++ and VC++ 6.0 */
-#if defined(WIN32CE)
-#  pragma warning(disable:4786)
-#endif
-
 #include "cpl_vsi_virtual.h"
 #include "cpl_string.h"
 #include "cpl_multiproc.h"
 #include <time.h>
 #include <map>
 
-#if defined(WIN32CE)
-#  include <wce_errno.h>
-#endif
-
-
-CPL_CVSID("$Id: cpl_vsi_mem.cpp 29581 2015-07-27 20:06:02Z rouault $");
+CPL_CVSID("$Id: cpl_vsi_mem.cpp 33758 2016-03-21 09:06:22Z rouault $");
 
 /*
 ** Notes on Multithreading:
 **
 ** VSIMemFilesystemHandler: This class maintains a mutex to protect
-** access and update of the oFileList array which has all the "files" in 
+** access and update of the oFileList array which has all the "files" in
 ** the memory filesystem area.  It is expected that multiple threads would
 ** want to create and read different files at the same time and so might
 ** collide access oFileList without the mutex.
@@ -61,17 +51,17 @@ CPL_CVSID("$Id: cpl_vsi_mem.cpp 29581 2015-07-27 20:06:02Z rouault $");
 ** here), which means we don't need to do any protection of this class.
 **
 ** VSIMemHandle: This is essentially a "current location" representing
-** on accessor to a file, and is inherently intended only to be used in 
-** a single thread. 
+** on accessor to a file, and is inherently intended only to be used in
+** a single thread.
 **
 ** In General:
 **
 ** Multiple threads accessing the memory filesystem are ok as long as
-**  1) A given VSIMemHandle (ie. FILE * at app level) isn't used by multiple 
-**     threads at once. 
+**  1) A given VSIMemHandle (i.e. FILE * at app level) isn't used by multiple
+**     threads at once.
 **  2) A given memory file isn't accessed by more than one thread unless
 **     all threads are just reading.
-*/ 
+*/
 
 /************************************************************************/
 /* ==================================================================== */
@@ -106,16 +96,16 @@ public:
 /* ==================================================================== */
 /************************************************************************/
 
-class VSIMemHandle : public VSIVirtualHandle
-{ 
+class VSIMemHandle CPL_FINAL : public VSIVirtualHandle
+{
   public:
     VSIMemFile    *poFile;
-    vsi_l_offset  nOffset;
+    vsi_l_offset  m_nOffset;
     int           bUpdate;
     int           bEOF;
     int           bExtendFileAtNextWrite;
-    
-                      VSIMemHandle() : poFile(NULL), nOffset(0), bUpdate(0),
+
+                      VSIMemHandle() : poFile(NULL), m_nOffset(0), bUpdate(0),
                                        bEOF(0), bExtendFileAtNextWrite(0) {}
 
     virtual int       Seek( vsi_l_offset nOffset, int nWhence );
@@ -133,7 +123,7 @@ class VSIMemHandle : public VSIVirtualHandle
 /* ==================================================================== */
 /************************************************************************/
 
-class VSIMemFilesystemHandler : public VSIFilesystemHandler 
+class VSIMemFilesystemHandler CPL_FINAL : public VSIFilesystemHandler
 {
 public:
     std::map<CPLString,VSIMemFile*>   oFileList;
@@ -142,14 +132,18 @@ public:
                      VSIMemFilesystemHandler();
     virtual          ~VSIMemFilesystemHandler();
 
-    virtual VSIVirtualHandle *Open( const char *pszFilename, 
-                                    const char *pszAccess);
+    using VSIFilesystemHandler::Open;
+
+    virtual VSIVirtualHandle *Open( const char *pszFilename,
+                                    const char *pszAccess,
+                                    bool bSetError );
     virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags );
     virtual int      Unlink( const char *pszFilename );
     virtual int      Mkdir( const char *pszDirname, long nMode );
     virtual int      Rmdir( const char *pszDirname );
-    virtual char   **ReadDir( const char *pszDirname );
+    virtual char   **ReadDirEx( const char *pszDirname, int nMaxFiles );
     virtual int      Rename( const char *oldpath, const char *newpath );
+    virtual GIntBig  GetDiskFreeSpace( const char* pszDirname );
 
     static  void     NormalizePath( CPLString & );
 
@@ -166,15 +160,14 @@ public:
 /*                             VSIMemFile()                             */
 /************************************************************************/
 
-VSIMemFile::VSIMemFile()
-
+VSIMemFile::VSIMemFile() :
+    nRefCount(0),
+    bIsDirectory(FALSE),
+    bOwnData(TRUE),
+    pabyData(NULL),
+    nLength(0),
+    nAllocLength(0)
 {
-    nRefCount = 0;
-    bIsDirectory = FALSE;
-    bOwnData = TRUE;
-    pabyData = NULL;
-    nLength = 0;
-    nAllocLength = 0;
     time(&mTime);
 }
 
@@ -215,9 +208,9 @@ bool VSIMemFile::SetLength( vsi_l_offset nNewLength )
                      "Cannot extended in-memory file whose ownership was not transferred");
             return false;
         }
-        
+
         GByte *pabyNewData;
-        vsi_l_offset nNewAlloc = (nNewLength + nNewLength / 10) + 5000;
+        const vsi_l_offset nNewAlloc = (nNewLength + nNewLength / 10) + 5000;
         if( (vsi_l_offset)(size_t)nNewAlloc != nNewAlloc )
             pabyNewData = NULL;
         else
@@ -229,9 +222,9 @@ bool VSIMemFile::SetLength( vsi_l_offset nNewLength )
                      nNewAlloc);
             return false;
         }
-            
+
         /* Clear the new allocated part of the buffer */
-        memset(pabyNewData + nAllocLength, 0, 
+        memset(pabyNewData + nAllocLength, 0,
                (size_t) (nNewAlloc - nAllocLength));
 
         pabyData = pabyNewData;
@@ -275,11 +268,11 @@ int VSIMemHandle::Seek( vsi_l_offset nOffset, int nWhence )
 {
     bExtendFileAtNextWrite = FALSE;
     if( nWhence == SEEK_CUR )
-        this->nOffset += nOffset;
+        m_nOffset += nOffset;
     else if( nWhence == SEEK_SET )
-        this->nOffset = nOffset;
+        m_nOffset = nOffset;
     else if( nWhence == SEEK_END )
-        this->nOffset = poFile->nLength + nOffset;
+        m_nOffset = poFile->nLength + nOffset;
     else
     {
         errno = EINVAL;
@@ -288,20 +281,20 @@ int VSIMemHandle::Seek( vsi_l_offset nOffset, int nWhence )
 
     bEOF = FALSE;
 
-    if( this->nOffset > poFile->nLength )
+    if( m_nOffset > poFile->nLength )
     {
         if( !bUpdate ) // Read-only files cannot be extended by seek.
         {
-            CPLDebug( "VSIMemHandle", 
+            CPLDebug( "VSIMemHandle",
                       "Attempt to extend read-only file '%s' to length " CPL_FRMT_GUIB " from " CPL_FRMT_GUIB ".",
-                      poFile->osFilename.c_str(), 
-                      this->nOffset, poFile->nLength );
+                      poFile->osFilename.c_str(),
+                      m_nOffset, poFile->nLength );
 
-            this->nOffset = poFile->nLength;
+            m_nOffset = poFile->nLength;
             errno = EACCES;
             return -1;
         }
-        else // Writeable files are zero-extended by seek past end.
+        else // Writable files are zero-extended by seek past end.
         {
             bExtendFileAtNextWrite = TRUE;
         }
@@ -317,7 +310,7 @@ int VSIMemHandle::Seek( vsi_l_offset nOffset, int nWhence )
 vsi_l_offset VSIMemHandle::Tell()
 
 {
-    return nOffset;
+    return m_nOffset;
 }
 
 /************************************************************************/
@@ -328,23 +321,24 @@ size_t VSIMemHandle::Read( void * pBuffer, size_t nSize, size_t nCount )
 
 {
     // FIXME: Integer overflow check should be placed here:
-    size_t nBytesToRead = nSize * nCount; 
+    size_t nBytesToRead = nSize * nCount;
 
-    if( nBytesToRead + nOffset > poFile->nLength )
+    if( nBytesToRead + m_nOffset > poFile->nLength )
     {
-        if (poFile->nLength < nOffset)
+        if (poFile->nLength < m_nOffset)
         {
             bEOF = TRUE;
             return 0;
         }
 
-        nBytesToRead = (size_t)(poFile->nLength - nOffset);
+        nBytesToRead = (size_t)(poFile->nLength - m_nOffset);
         nCount = nBytesToRead / nSize;
         bEOF = TRUE;
     }
 
-    memcpy( pBuffer, poFile->pabyData + nOffset, (size_t)nBytesToRead );
-    nOffset += nBytesToRead;
+    if( nBytesToRead )
+        memcpy( pBuffer, poFile->pabyData + m_nOffset, (size_t)nBytesToRead );
+    m_nOffset += nBytesToRead;
 
     return nCount;
 }
@@ -364,23 +358,22 @@ size_t VSIMemHandle::Write( const void * pBuffer, size_t nSize, size_t nCount )
     if( bExtendFileAtNextWrite )
     {
         bExtendFileAtNextWrite = FALSE;
-        if( !poFile->SetLength( nOffset ) )
+        if( !poFile->SetLength( m_nOffset ) )
             return 0;
     }
 
     // FIXME: Integer overflow check should be placed here:
-    size_t nBytesToWrite = nSize * nCount; 
-    //if( CSLTestBoolean(CPLGetConfigOption("VERBOSE_IO", "FALSE")) )
-    //    CPLDebug("MEM", "Write(%d bytes in [%d,%d[)", (int)nBytesToWrite, (int)nOffset, (int)(nOffset+nBytesToWrite));
+    const size_t nBytesToWrite = nSize * nCount;
 
-    if( nBytesToWrite + nOffset > poFile->nLength )
+    if( nBytesToWrite + m_nOffset > poFile->nLength )
     {
-        if( !poFile->SetLength( nBytesToWrite + nOffset ) )
+        if( !poFile->SetLength( nBytesToWrite + m_nOffset ) )
             return 0;
     }
 
-    memcpy( poFile->pabyData + nOffset, pBuffer, nBytesToWrite );
-    nOffset += nBytesToWrite;
+    if( nBytesToWrite )
+        memcpy( poFile->pabyData + m_nOffset, pBuffer, nBytesToWrite );
+    m_nOffset += nBytesToWrite;
 
     time(&poFile->mTime);
 
@@ -426,11 +419,9 @@ int VSIMemHandle::Truncate( vsi_l_offset nNewSize )
 /*                      VSIMemFilesystemHandler()                       */
 /************************************************************************/
 
-VSIMemFilesystemHandler::VSIMemFilesystemHandler()
-
-{
-    hMutex = NULL;
-}
+VSIMemFilesystemHandler::VSIMemFilesystemHandler() :
+    hMutex(NULL)
+{ }
 
 /************************************************************************/
 /*                      ~VSIMemFilesystemHandler()                      */
@@ -439,9 +430,9 @@ VSIMemFilesystemHandler::VSIMemFilesystemHandler()
 VSIMemFilesystemHandler::~VSIMemFilesystemHandler()
 
 {
-    std::map<CPLString,VSIMemFile*>::const_iterator iter;
-
-    for( iter = oFileList.begin(); iter != oFileList.end(); ++iter )
+    for( std::map<CPLString,VSIMemFile*>::const_iterator iter = oFileList.begin();
+         iter != oFileList.end();
+         ++iter )
     {
         iter->second->nRefCount--;
         delete iter->second;
@@ -457,42 +448,47 @@ VSIMemFilesystemHandler::~VSIMemFilesystemHandler()
 /************************************************************************/
 
 VSIVirtualHandle *
-VSIMemFilesystemHandler::Open( const char *pszFilename, 
-                               const char *pszAccess )
+VSIMemFilesystemHandler::Open( const char *pszFilename,
+                               const char *pszAccess,
+                               bool bSetError )
 
 {
     CPLMutexHolder oHolder( &hMutex );
-    VSIMemFile *poFile;
     CPLString osFilename = pszFilename;
     NormalizePath( osFilename );
 
 /* -------------------------------------------------------------------- */
 /*      Get the filename we are opening, create if needed.              */
 /* -------------------------------------------------------------------- */
+    VSIMemFile *poFile;
     if( oFileList.find(osFilename) == oFileList.end() )
         poFile = NULL;
     else
         poFile = oFileList[osFilename];
 
-    if( strstr(pszAccess,"w") == NULL 
-	&& strstr(pszAccess, "a") == NULL
-	&& poFile == NULL )
+    // If no file and opening in read, error out
+    if( strstr(pszAccess,"w") == NULL
+        && strstr(pszAccess, "a") == NULL
+        && poFile == NULL )
     {
+        if(bSetError) { VSIError(VSIE_FileError, "No such file or directory"); }
         errno = ENOENT;
         return NULL;
     }
 
-    // Overwrite
-    if (poFile && strstr(pszAccess, "w"))
-	poFile->SetLength(0);
-
     // Create
-    if (!poFile && (strstr(pszAccess, "w") || strstr(pszAccess, "a"))) {
-	poFile = new VSIMemFile;
-	poFile->osFilename = osFilename;
-	oFileList[poFile->osFilename] = poFile;
-	poFile->nRefCount++; // for file list
-    } 
+    if( poFile == NULL )
+    {
+        poFile = new VSIMemFile;
+        poFile->osFilename = osFilename;
+        oFileList[poFile->osFilename] = poFile;
+        poFile->nRefCount++; // for file list
+    }
+    // Overwrite
+    else if( strstr(pszAccess, "w") )
+    {
+        poFile->SetLength(0);
+    }
 
     if( poFile->bIsDirectory )
     {
@@ -506,9 +502,9 @@ VSIMemFilesystemHandler::Open( const char *pszFilename,
     VSIMemHandle *poHandle = new VSIMemHandle;
 
     poHandle->poFile = poFile;
-    poHandle->nOffset = 0;
+    poHandle->m_nOffset = 0;
     poHandle->bEOF = FALSE;
-    if( strstr(pszAccess,"w") || strstr(pszAccess,"+") 
+    if( strstr(pszAccess,"w") || strstr(pszAccess,"+")
         || strstr(pszAccess,"a") )
         poHandle->bUpdate = TRUE;
     else
@@ -517,7 +513,7 @@ VSIMemFilesystemHandler::Open( const char *pszFilename,
     poFile->nRefCount++;
 
     if( strstr(pszAccess,"a") )
-        poHandle->nOffset = poFile->nLength;
+        poHandle->m_nOffset = poFile->nLength;
 
     return poHandle;
 }
@@ -526,13 +522,11 @@ VSIMemFilesystemHandler::Open( const char *pszFilename,
 /*                                Stat()                                */
 /************************************************************************/
 
-int VSIMemFilesystemHandler::Stat( const char * pszFilename, 
+int VSIMemFilesystemHandler::Stat( const char * pszFilename,
                                    VSIStatBufL * pStatBuf,
-                                   int nFlags )
-    
-{
-    (void) nFlags;
+                                   int /* nFlags */ )
 
+{
     CPLMutexHolder oHolder( &hMutex );
 
     CPLString osFilename = pszFilename;
@@ -593,24 +587,21 @@ int VSIMemFilesystemHandler::Unlink_unlocked( const char * pszFilename )
     CPLString osFilename = pszFilename;
     NormalizePath( osFilename );
 
-    VSIMemFile *poFile;
 
     if( oFileList.find(osFilename) == oFileList.end() )
     {
         errno = ENOENT;
         return -1;
     }
-    else
-    {
-        poFile = oFileList[osFilename];
 
-        if( --(poFile->nRefCount) == 0 )
-            delete poFile;
+    VSIMemFile *poFile = oFileList[osFilename];
 
-        oFileList.erase( oFileList.find(osFilename) );
+    if( --(poFile->nRefCount) == 0 )
+        delete poFile;
 
-        return 0;
-    }
+    oFileList.erase( oFileList.find(osFilename) );
+
+    return 0;
 }
 
 /************************************************************************/
@@ -618,11 +609,9 @@ int VSIMemFilesystemHandler::Unlink_unlocked( const char * pszFilename )
 /************************************************************************/
 
 int VSIMemFilesystemHandler::Mkdir( const char * pszPathname,
-                                    long nMode )
+                                    long /* nMode */ )
 
 {
-    (void) nMode;
-
     CPLMutexHolder oHolder( &hMutex );
 
     CPLString osPathname = pszPathname;
@@ -656,10 +645,11 @@ int VSIMemFilesystemHandler::Rmdir( const char * pszPathname )
 }
 
 /************************************************************************/
-/*                              ReadDir()                               */
+/*                             ReadDirEx()                              */
 /************************************************************************/
 
-char **VSIMemFilesystemHandler::ReadDir( const char *pszPath )
+char **VSIMemFilesystemHandler::ReadDirEx( const char *pszPath,
+                                           int nMaxFiles )
 
 {
     CPLMutexHolder oHolder( &hMutex );
@@ -670,9 +660,9 @@ char **VSIMemFilesystemHandler::ReadDir( const char *pszPath )
 
     std::map<CPLString,VSIMemFile*>::const_iterator iter;
     char **papszDir = NULL;
-    int nPathLen = strlen(osPath);
+    size_t nPathLen = strlen(osPath);
 
-    if( osPath[nPathLen-1] == '/' )
+    if( nPathLen > 0 && osPath[nPathLen-1] == '/' )
         nPathLen--;
 
     /* In case of really big number of files in the directory, CSLAddString */
@@ -684,7 +674,7 @@ char **VSIMemFilesystemHandler::ReadDir( const char *pszPath )
     {
         const char *pszFilePath = iter->second->osFilename.c_str();
         if( EQUALN(osPath,pszFilePath,nPathLen)
-            && pszFilePath[nPathLen] == '/' 
+            && pszFilePath[nPathLen] == '/'
             && strstr(pszFilePath+nPathLen+1,"/") == NULL )
         {
             if (nItems == 0)
@@ -695,7 +685,7 @@ char **VSIMemFilesystemHandler::ReadDir( const char *pszPath )
             else if (nItems >= nAllocatedItems)
             {
                 nAllocatedItems = nAllocatedItems * 2;
-                papszDir = (char**)CPLRealloc(papszDir, 
+                papszDir = (char**)CPLRealloc(papszDir,
                                               (nAllocatedItems+2)*sizeof(char*));
             }
 
@@ -703,6 +693,8 @@ char **VSIMemFilesystemHandler::ReadDir( const char *pszPath )
             papszDir[nItems+1] = NULL;
 
             nItems++;
+            if( nMaxFiles > 0 && nItems > nMaxFiles )
+                break;
         }
     }
 
@@ -733,25 +725,23 @@ int VSIMemFilesystemHandler::Rename( const char *pszOldPath,
         errno = ENOENT;
         return -1;
     }
-    else
+
+    std::map<CPLString,VSIMemFile*>::iterator it = oFileList.find(osOldPath);
+    while (it != oFileList.end() && it->first.ifind(osOldPath) == 0)
     {
-        std::map<CPLString,VSIMemFile*>::iterator it = oFileList.find(osOldPath);
-        while (it != oFileList.end() && it->first.ifind(osOldPath) == 0)
+        const CPLString osRemainder = it->first.substr(osOldPath.size());
+        if (osRemainder.empty() || osRemainder[0] == '/')
         {
-            const CPLString osRemainder = it->first.substr(osOldPath.size());
-            if (osRemainder.empty() || osRemainder[0] == '/')
-            {
-                const CPLString osNewFullPath = osNewPath + osRemainder;
-                Unlink_unlocked(osNewFullPath);
-                oFileList[osNewFullPath] = it->second;
-                it->second->osFilename = osNewFullPath;
-                oFileList.erase(it++);
-            }
-            else ++it;
+            const CPLString osNewFullPath = osNewPath + osRemainder;
+            Unlink_unlocked(osNewFullPath);
+            oFileList[osNewFullPath] = it->second;
+            it->second->osFilename = osNewFullPath;
+            oFileList.erase(it++);
         }
-
-        return 0;
+        else ++it;
     }
+
+    return 0;
 }
 
 /************************************************************************/
@@ -761,9 +751,9 @@ int VSIMemFilesystemHandler::Rename( const char *pszOldPath,
 void VSIMemFilesystemHandler::NormalizePath( CPLString &oPath )
 
 {
-    int  i, nSize = oPath.size();
+    const size_t nSize = oPath.size();
 
-    for( i = 0; i < nSize; i++ )
+    for( size_t i = 0; i < nSize; i++ )
     {
         if( oPath[i] == '\\' )
             oPath[i] = '/';
@@ -772,35 +762,47 @@ void VSIMemFilesystemHandler::NormalizePath( CPLString &oPath )
 }
 
 /************************************************************************/
+/*                        GetDiskFreeSpace()                            */
+/************************************************************************/
+
+GIntBig VSIMemFilesystemHandler::GetDiskFreeSpace( const char* /*pszDirname*/ )
+{
+    GIntBig nRet = CPLGetUsablePhysicalRAM();
+    if( nRet <= 0 )
+        nRet = -1;
+    return nRet;
+}
+
+/************************************************************************/
 /*                     VSIInstallLargeFileHandler()                     */
 /************************************************************************/
 
 /**
- * \brief Install "memory" file system handler. 
+ * \brief Install "memory" file system handler.
  *
  * A special file handler is installed that allows block of memory to be
  * treated as files.   All portions of the file system underneath the base
- * path "/vsimem/" will be handled by this driver.  
+ * path "/vsimem/" will be handled by this driver.
  *
  * Normal VSI*L functions can be used freely to create and destroy memory
  * arrays treating them as if they were real file system objects.  Some
  * additional methods exist to efficient create memory file system objects
  * without duplicating original copies of the data or to "steal" the block
- * of memory associated with a memory file. 
+ * of memory associated with a memory file.
  *
  * At this time the memory handler does not properly handle directory
  * semantics for the memory portion of the filesystem.  The VSIReadDir()
- * function is not supported though this will be corrected in the future. 
+ * function is not supported though this will be corrected in the future.
  *
  * Calling this function repeatedly should do no harm, though it is not
- * necessary.  It is already called the first time a virtualizable 
- * file access function (ie. VSIFOpenL(), VSIMkDir(), etc) is called. 
+ * necessary.  It is already called the first time a virtualizable
+ * file access function (i.e. VSIFOpenL(), VSIMkDir(), etc) is called.
  *
  * This code example demonstrates using GDAL to translate from one memory
  * buffer to another.
  *
  * \code
- * GByte *ConvertBufferFormat( GByte *pabyInData, vsi_l_offset nInDataLength, 
+ * GByte *ConvertBufferFormat( GByte *pabyInData, vsi_l_offset nInDataLength,
  *                             vsi_l_offset *pnOutDataLength )
  * {
  *     // create memory file system object from buffer.
@@ -809,15 +811,15 @@ void VSIMemFilesystemHandler::NormalizePath( CPLString &oPath )
  *
  *     // Open memory buffer for read.
  *     GDALDatasetH hDS = GDALOpen( "/vsimem/work.dat", GA_ReadOnly );
- * 
- *     // Get output format driver. 
+ *
+ *     // Get output format driver.
  *     GDALDriverH hDriver = GDALGetDriverByName( "GTiff" );
  *     GDALDatasetH hOutDS;
  *
- *     hOutDS = GDALCreateCopy( hDriver, "/vsimem/out.tif", hDS, TRUE, NULL, 
+ *     hOutDS = GDALCreateCopy( hDriver, "/vsimem/out.tif", hDS, TRUE, NULL,
  *                              NULL, NULL );
- * 
- *     // close source file, and "unlink" it.  
+ *
+ *     // close source file, and "unlink" it.
  *     GDALClose( hDS );
  *     VSIUnlink( "/vsimem/work.dat" );
  *
@@ -842,33 +844,33 @@ void VSIInstallMemFileHandler()
  *
  * A virtual memory file is created from the passed buffer with the indicated
  * filename.  Under normal conditions the filename would need to be absolute
- * and within the /vsimem/ portion of the filesystem.  
+ * and within the /vsimem/ portion of the filesystem.
  *
  * If bTakeOwnership is TRUE, then the memory file system handler will take
  * ownership of the buffer, freeing it when the file is deleted.  Otherwise
  * it remains the responsibility of the caller, but should not be freed as
  * long as it might be accessed as a file.  In no circumstances does this
- * function take a copy of the pabyData contents. 
+ * function take a copy of the pabyData contents.
  *
  * @param pszFilename the filename to be created.
- * @param pabyData the data buffer for the file. 
+ * @param pabyData the data buffer for the file.
  * @param nDataLength the length of buffer in bytes.
- * @param bTakeOwnership TRUE to transfer "ownership" of buffer or FALSE. 
+ * @param bTakeOwnership TRUE to transfer "ownership" of buffer or FALSE.
  *
- * @return open file handle on created file (see VSIFOpenL()). 
+ * @return open file handle on created file (see VSIFOpenL()).
  */
 
 VSILFILE *VSIFileFromMemBuffer( const char *pszFilename,
-                          GByte *pabyData, 
+                          GByte *pabyData,
                           vsi_l_offset nDataLength,
                           int bTakeOwnership )
 
 {
-    if( VSIFileManager::GetHandler("") 
+    if( VSIFileManager::GetHandler("")
         == VSIFileManager::GetHandler("/vsimem/") )
         VSIInstallMemFileHandler();
 
-    VSIMemFilesystemHandler *poHandler = (VSIMemFilesystemHandler *) 
+    VSIMemFilesystemHandler *poHandler = (VSIMemFilesystemHandler *)
         VSIFileManager::GetHandler("/vsimem/");
 
     if (pszFilename == NULL)
@@ -900,12 +902,12 @@ VSILFILE *VSIFileFromMemBuffer( const char *pszFilename,
 /************************************************************************/
 
 /**
- * \brief Fetch buffer underlying memory file. 
+ * \brief Fetch buffer underlying memory file.
  *
- * This function returns a pointer to the memory buffer underlying a 
+ * This function returns a pointer to the memory buffer underlying a
  * virtual "in memory" file.  If bUnlinkAndSeize is TRUE the filesystem
- * object will be deleted, and ownership of the buffer will pass to the 
- * caller otherwise the underlying file will remain in existance. 
+ * object will be deleted, and ownership of the buffer will pass to the
+ * caller otherwise the underlying file will remain in existence.
  *
  * @param pszFilename the name of the file to grab the buffer of.
  * @param pnDataLength (file) length returned in this variable.
@@ -914,12 +916,12 @@ VSILFILE *VSIFileFromMemBuffer( const char *pszFilename,
  * @return pointer to memory buffer or NULL on failure.
  */
 
-GByte *VSIGetMemFileBuffer( const char *pszFilename, 
+GByte *VSIGetMemFileBuffer( const char *pszFilename,
                             vsi_l_offset *pnDataLength,
                             int bUnlinkAndSeize )
 
 {
-    VSIMemFilesystemHandler *poHandler = (VSIMemFilesystemHandler *) 
+    VSIMemFilesystemHandler *poHandler = (VSIMemFilesystemHandler *)
         VSIFileManager::GetHandler("/vsimem/");
 
     if (pszFilename == NULL)
@@ -934,16 +936,14 @@ GByte *VSIGetMemFileBuffer( const char *pszFilename,
         return NULL;
 
     VSIMemFile *poFile = poHandler->oFileList[osFilename];
-    GByte *pabyData;
-
-    pabyData = poFile->pabyData;
+    GByte *pabyData = poFile->pabyData;
     if( pnDataLength != NULL )
         *pnDataLength = poFile->nLength;
-    
+
     if( bUnlinkAndSeize )
     {
         if( !poFile->bOwnData )
-            CPLDebug( "VSIMemFile", 
+            CPLDebug( "VSIMemFile",
                       "File doesn't own data in VSIGetMemFileBuffer!" );
         else
             poFile->bOwnData = FALSE;
@@ -955,4 +955,3 @@ GByte *VSIGetMemFileBuffer( const char *pszFilename,
 
     return pabyData;
 }
-                            
diff --git a/port/cpl_vsi_virtual.h b/port/cpl_vsi_virtual.h
index 4348dbf..66ccc60 100644
--- a/port/cpl_vsi_virtual.h
+++ b/port/cpl_vsi_virtual.h
@@ -1,10 +1,10 @@
 /******************************************************************************
- * $Id: cpl_vsi_virtual.h 29388 2015-06-17 18:28:29Z rouault $
+ * $Id: cpl_vsi_virtual.h 33759 2016-03-21 09:33:06Z rouault $
  *
  * Project:  VSI Virtual File System
  * Purpose:  Declarations for classes related to the virtual filesystem.
- *           These would only be normally required by applications implmenting
- *           their own virtual file system classes which should be rare.  
+ *           These would only be normally required by applications implementing
+ *           their own virtual file system classes which should be rare.
  *           The class interface may be fragile through versions.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -35,15 +35,10 @@
 #define CPL_VSI_VIRTUAL_H_INCLUDED
 
 #include "cpl_vsi.h"
+#include "cpl_vsi_error.h"
 #include "cpl_string.h"
 #include "cpl_multiproc.h"
 
-#if defined(WIN32CE)
-#  include "cpl_wince.h"
-#  include <wce_errno.h>
-#  pragma warning(disable:4786) /* Remove annoying warnings in eVC++ and VC++ 6.0 */
-#endif
-
 #include <map>
 #include <vector>
 #include <string>
@@ -52,7 +47,7 @@
 /*                           VSIVirtualHandle                           */
 /************************************************************************/
 
-class CPL_DLL VSIVirtualHandle { 
+class CPL_DLL VSIVirtualHandle {
   public:
     virtual int       Seek( vsi_l_offset nOffset, int nWhence ) = 0;
     virtual vsi_l_offset Tell() = 0;
@@ -77,28 +72,35 @@ public:
 
     virtual ~VSIFilesystemHandler() {}
 
-    virtual VSIVirtualHandle *Open( const char *pszFilename, 
-                                    const char *pszAccess) = 0;
+    VSIVirtualHandle *Open( const char *pszFilename,
+                            const char *pszAccess );
+
+    virtual VSIVirtualHandle *Open( const char *pszFilename,
+                                    const char *pszAccess,
+                                    bool bSetError ) = 0;
     virtual int Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags) = 0;
     virtual int Unlink( const char *pszFilename )
                       { (void) pszFilename; errno=ENOENT; return -1; }
-    virtual int Mkdir( const char *pszDirname, long nMode ) 
+    virtual int Mkdir( const char *pszDirname, long nMode )
                       {(void)pszDirname; (void)nMode; errno=ENOENT; return -1;}
-    virtual int Rmdir( const char *pszDirname ) 
+    virtual int Rmdir( const char *pszDirname )
                       { (void) pszDirname; errno=ENOENT; return -1; }
-    virtual char **ReadDir( const char *pszDirname ) 
+    virtual char **ReadDir( const char *pszDirname )
                       { (void) pszDirname; return NULL; }
+    virtual char **ReadDirEx( const char *pszDirname, int /* nMaxFiles */ )
+                      { return ReadDir(pszDirname); }
     virtual int Rename( const char *oldpath, const char *newpath )
                       { (void) oldpath; (void)newpath; errno=ENOENT; return -1; }
     virtual int IsCaseSensitive( const char* pszFilename )
                       { (void) pszFilename; return TRUE; }
+    virtual GIntBig GetDiskFreeSpace( const char* /* pszDirname */ ) { return -1; }
 };
 
 /************************************************************************/
 /*                            VSIFileManager                            */
 /************************************************************************/
 
-class CPL_DLL VSIFileManager 
+class CPL_DLL VSIFileManager
 {
 private:
     VSIFilesystemHandler *poDefaultHandler;
@@ -112,7 +114,7 @@ public:
     ~VSIFileManager();
 
     static VSIFilesystemHandler *GetHandler( const char * );
-    static void InstallHandler( const std::string& osPrefix, 
+    static void InstallHandler( const std::string& osPrefix,
                                 VSIFilesystemHandler * );
     /* RemoveHandler is never defined. */
     /* static void RemoveHandler( const std::string& osPrefix ); */
@@ -140,13 +142,17 @@ typedef struct
     GIntBig       nModifiedTime;
 } VSIArchiveEntry;
 
-typedef struct
+class VSIArchiveContent
 {
+public:
     time_t       mTime;
     vsi_l_offset nFileSize;
     int nEntries;
     VSIArchiveEntry* entries;
-} VSIArchiveContent;
+
+    VSIArchiveContent() : mTime(0), nFileSize(0), nEntries(0), entries(NULL) {}
+    ~VSIArchiveContent();
+};
 
 class VSIArchiveReader
 {
@@ -162,11 +168,11 @@ class VSIArchiveReader
         virtual int GotoFileOffset(VSIArchiveEntryFileOffset* pOffset) = 0;
 };
 
-class VSIArchiveFilesystemHandler : public VSIFilesystemHandler 
+class VSIArchiveFilesystemHandler : public VSIFilesystemHandler
 {
 protected:
     CPLMutex* hMutex;
-    /* We use a cache that contains the list of files containes in a VSIArchive file as */
+    /* We use a cache that contains the list of files contained in a VSIArchive file as */
     /* unarchive.c is quite inefficient in listing them. This speeds up access to VSIArchive files */
     /* containing ~1000 files like a CADRG product */
     std::map<CPLString,VSIArchiveContent*>   oFileList;
@@ -184,7 +190,7 @@ public:
     virtual int      Rename( const char *oldpath, const char *newpath );
     virtual int      Mkdir( const char *pszDirname, long nMode );
     virtual int      Rmdir( const char *pszDirname );
-    virtual char   **ReadDir( const char *pszDirname );
+    virtual char   **ReadDirEx( const char *pszDirname, int nMaxFiles );
 
     virtual const VSIArchiveContent* GetContentOfArchive(const char* archiveFilename, VSIArchiveReader* poReader = NULL);
     virtual char* SplitFilename(const char *pszFilename, CPLString &osFileInArchive, int bCheckMainFileExists);
@@ -195,7 +201,7 @@ public:
 VSIVirtualHandle CPL_DLL *VSICreateBufferedReaderHandle(VSIVirtualHandle* poBaseHandle);
 VSIVirtualHandle* VSICreateBufferedReaderHandle(VSIVirtualHandle* poBaseHandle,
                                                 const GByte* pabyBeginningContent,
-                                                vsi_l_offset nSheatFileSize);
+                                                vsi_l_offset nCheatFileSize);
 VSIVirtualHandle* VSICreateCachedFile( VSIVirtualHandle* poBaseHandle, size_t nChunkSize = 32768, size_t nCacheSize = 0 );
 VSIVirtualHandle CPL_DLL *VSICreateGZipWritable( VSIVirtualHandle* poBaseHandle, int bRegularZLibIn, int bAutoCloseBaseHandle );
 
diff --git a/port/cpl_vsil.cpp b/port/cpl_vsil.cpp
index 45af62b..0d3f3a9 100644
--- a/port/cpl_vsil.cpp
+++ b/port/cpl_vsil.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsil.cpp 28849 2015-04-05 14:05:18Z goatbar $
+ * $Id: cpl_vsil.cpp 33759 2016-03-21 09:33:06Z rouault $
  *
  * Project:  VSI Virtual File System
  * Purpose:  Implementation VSI*L File API and other file system access
@@ -29,12 +29,14 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_vsi_virtual.h"
 #include "cpl_multiproc.h"
 #include "cpl_string.h"
+#include "cpl_vsi_virtual.h"
+
+#include <cassert>
 #include <string>
 
-CPL_CVSID("$Id: cpl_vsil.cpp 28849 2015-04-05 14:05:18Z goatbar $");
+CPL_CVSID("$Id: cpl_vsil.cpp 33759 2016-03-21 09:33:06Z rouault $");
 
 /************************************************************************/
 /*                             VSIReadDir()                             */
@@ -50,11 +52,11 @@ CPL_CVSID("$Id: cpl_vsil.cpp 28849 2015-04-05 14:05:18Z goatbar $");
  *
  * Note that no error is issued via CPLError() if the directory path is
  * invalid, though NULL is returned.
- * 
- * This function used to be known as CPLReadDir(), but the old name is now 
- * deprecated. 
  *
- * @param pszPath the relative, or absolute path of a directory to read.  
+ * This function used to be known as CPLReadDir(), but the old name is now
+ * deprecated.
+ *
+ * @param pszPath the relative, or absolute path of a directory to read.
  * UTF-8 encoded.
  * @return The list of entries in the directory, or NULL if the directory
  * doesn't exist.  Filenames are returned in UTF-8 encoding.
@@ -62,10 +64,43 @@ CPL_CVSID("$Id: cpl_vsil.cpp 28849 2015-04-05 14:05:18Z goatbar $");
 
 char **VSIReadDir(const char *pszPath)
 {
-    VSIFilesystemHandler *poFSHandler = 
+    return VSIReadDirEx(pszPath, 0);
+}
+
+/************************************************************************/
+/*                             VSIReadDir()                             */
+/************************************************************************/
+
+/**
+ * \brief Read names in a directory.
+ *
+ * This function abstracts access to directory contains.  It returns a
+ * list of strings containing the names of files, and directories in this
+ * directory.  The resulting string list becomes the responsibility of the
+ * application and should be freed with CSLDestroy() when no longer needed.
+ *
+ * Note that no error is issued via CPLError() if the directory path is
+ * invalid, though NULL is returned.
+ *
+ * If nMaxFiles is set to a positive number, directory listing will stop after
+ * that limit has been reached. Note that to indicate truncate, at least one
+ * element more than the nMaxFiles limit will be returned. If CSLCount() on the
+ * result is lesser or equal to nMaxFiles, then no truncation occurred.
+ *
+ * @param pszPath the relative, or absolute path of a directory to read.
+ * UTF-8 encoded.
+ * @param nMaxFiles maximum number of files after which to stop, or 0 for no limit.
+ * @return The list of entries in the directory, or NULL if the directory
+ * doesn't exist.  Filenames are returned in UTF-8 encoding.
+ * @since GDAL 2.1
+ */
+
+char **VSIReadDirEx(const char *pszPath, int nMaxFiles)
+{
+    VSIFilesystemHandler *poFSHandler =
         VSIFileManager::GetHandler( pszPath );
 
-    return poFSHandler->ReadDir( pszPath );
+    return poFSHandler->ReadDirEx( pszPath, nMaxFiles );
 }
 
 /************************************************************************/
@@ -85,19 +120,19 @@ typedef struct
  * \brief Read names in a directory recursively.
  *
  * This function abstracts access to directory contents and subdirectories.
- * It returns a list of strings containing the names of files and directories 
+ * It returns a list of strings containing the names of files and directories
  * in this directory and all subdirectories.  The resulting string list becomes
  * the responsibility of the application and should be freed with CSLDestroy()
  *  when no longer needed.
  *
  * Note that no error is issued via CPLError() if the directory path is
  * invalid, though NULL is returned.
- * 
- * @param pszPathIn the relative, or absolute path of a directory to read.  
+ *
+ * @param pszPathIn the relative, or absolute path of a directory to read.
  * UTF-8 encoded.
  *
- * @return The list of entries in the directory and subdirectories 
- * or NULL if the directory doesn't exist.  Filenames are returned in UTF-8 
+ * @return The list of entries in the directory and subdirectories
+ * or NULL if the directory doesn't exist.  Filenames are returned in UTF-8
  * encoding.
  * @since GDAL 1.10.0
  *
@@ -108,7 +143,8 @@ char **VSIReadDirRecursive( const char *pszPathIn )
     CPLStringList oFiles = NULL;
     char **papszFiles = NULL;
     VSIStatBufL psStatBuf;
-    CPLString osTemp1, osTemp2;
+    CPLString osTemp1;
+    CPLString osTemp2;
     int i = 0;
     int nCount = -1;
 
@@ -116,7 +152,7 @@ char **VSIReadDirRecursive( const char *pszPathIn )
     char* pszPath = CPLStrdup(pszPathIn);
     char* pszDisplayedPath = NULL;
 
-    while(TRUE)
+    while(true)
     {
         if( nCount < 0 )
         {
@@ -181,7 +217,7 @@ char **VSIReadDirRecursive( const char *pszPathIn )
                 CPLFree(pszPath);
                 pszPath = CPLStrdup( osTemp1.c_str() );
 
-                char* pszDisplayedPathNew;
+                char* pszDisplayedPathNew = NULL;
                 if( pszDisplayedPath )
                     pszDisplayedPathNew = CPLStrdup( CPLSPrintf("%s/%s", pszDisplayedPath, papszFiles[i]) );
                 else
@@ -203,7 +239,7 @@ char **VSIReadDirRecursive( const char *pszPathIn )
 
             if( aoStack.size() )
             {
-                int iLast = (int)aoStack.size() - 1;
+                int iLast = static_cast<int>(aoStack.size()) - 1;
                 CPLFree(pszPath);
                 CPLFree(pszDisplayedPath);
                 nCount = aoStack[iLast].nCount;
@@ -229,7 +265,7 @@ char **VSIReadDirRecursive( const char *pszPathIn )
 /************************************************************************/
 /*                             CPLReadDir()                             */
 /*                                                                      */
-/*      This is present only to provide ABI compatability with older    */
+/*      This is present only to provide ABI compatibility with older    */
 /*      versions.                                                       */
 /************************************************************************/
 #undef CPLReadDir
@@ -240,7 +276,7 @@ CPL_C_END
 
 char **CPLReadDir( const char *pszPath )
 {
-    return VSIReadDir(pszPath);
+    return VSIReadDir( pszPath );
 }
 
 /************************************************************************/
@@ -248,8 +284,8 @@ char **CPLReadDir( const char *pszPath )
 /************************************************************************/
 
 /**
- * \brief Create a directory. 
- * 
+ * \brief Create a directory.
+ *
  * Create a new directory with the indicated mode.  The mode is ignored
  * on some platforms.  A reasonable default mode value would be 0666.
  * This method goes through the VSIFileHandler virtualization and may
@@ -266,7 +302,7 @@ char **CPLReadDir( const char *pszPath )
 int VSIMkdir( const char *pszPathname, long mode )
 
 {
-    VSIFilesystemHandler *poFSHandler = 
+    VSIFilesystemHandler *poFSHandler =
         VSIFileManager::GetHandler( pszPathname );
 
     return poFSHandler->Mkdir( pszPathname, mode );
@@ -274,13 +310,13 @@ int VSIMkdir( const char *pszPathname, long mode )
 
 /************************************************************************/
 /*                             VSIUnlink()                              */
-/*************************a***********************************************/
+/************************************************************************/
 
 /**
  * \brief Delete a file.
- * 
- * Deletes a file object from the file system. 
- * 
+ *
+ * Deletes a file object from the file system.
+ *
  * This method goes through the VSIFileHandler virtualization and may
  * work on unusual filesystems such as in memory.
  *
@@ -294,7 +330,7 @@ int VSIMkdir( const char *pszPathname, long mode )
 int VSIUnlink( const char * pszFilename )
 
 {
-    VSIFilesystemHandler *poFSHandler = 
+    VSIFilesystemHandler *poFSHandler =
         VSIFileManager::GetHandler( pszFilename );
 
     return poFSHandler->Unlink( pszFilename );
@@ -306,11 +342,11 @@ int VSIUnlink( const char * pszFilename )
 
 /**
  * \brief Rename a file.
- * 
+ *
  * Renames a file object in the file system.  It should be possible
- * to rename a file onto a new filesystem, but it is safest if this 
+ * to rename a file onto a new filesystem, but it is safest if this
  * function is only used to rename files that remain in the same directory.
- * 
+ *
  * This method goes through the VSIFileHandler virtualization and may
  * work on unusual filesystems such as in memory.
  *
@@ -325,7 +361,7 @@ int VSIUnlink( const char * pszFilename )
 int VSIRename( const char * oldpath, const char * newpath )
 
 {
-    VSIFilesystemHandler *poFSHandler = 
+    VSIFilesystemHandler *poFSHandler =
         VSIFileManager::GetHandler( oldpath );
 
     return poFSHandler->Rename( oldpath, newpath );
@@ -337,10 +373,10 @@ int VSIRename( const char * oldpath, const char * newpath )
 
 /**
  * \brief Delete a directory.
- * 
+ *
  * Deletes a directory object from the file system.  On some systems
  * the directory must be empty before it can be deleted.
- * 
+ *
  * This method goes through the VSIFileHandler virtualization and may
  * work on unusual filesystems such as in memory.
  *
@@ -354,7 +390,7 @@ int VSIRename( const char * oldpath, const char * newpath )
 int VSIRmdir( const char * pszDirname )
 
 {
-    VSIFilesystemHandler *poFSHandler = 
+    VSIFilesystemHandler *poFSHandler =
         VSIFileManager::GetHandler( pszDirname );
 
     return poFSHandler->Rmdir( pszDirname );
@@ -366,20 +402,20 @@ int VSIRmdir( const char * pszDirname )
 
 /**
  * \brief Get filesystem object info.
- * 
+ *
  * Fetches status information about a filesystem object (file, directory, etc).
  * The returned information is placed in the VSIStatBufL structure.   For
  * portability, only use the st_size (size in bytes) and st_mode (file type).
- * This method is similar to VSIStat(), but will work on large files on 
- * systems where this requires special calls. 
- * 
+ * This method is similar to VSIStat(), but will work on large files on
+ * systems where this requires special calls.
+ *
  * This method goes through the VSIFileHandler virtualization and may
  * work on unusual filesystems such as in memory.
  *
  * Analog of the POSIX stat() function.
  *
  * @param pszFilename the path of the filesystem object to be queried.  UTF-8 encoded.
- * @param psStatBuf the structure to load with information. 
+ * @param psStatBuf the structure to load with information.
  *
  * @return 0 on success or -1 on an error.
  */
@@ -424,7 +460,7 @@ int VSIStatL( const char * pszFilename, VSIStatBufL *psStatBuf )
 int VSIStatExL( const char * pszFilename, VSIStatBufL *psStatBuf, int nFlags )
 
 {
-    char    szAltPath[4];
+    char    szAltPath[4] = { '\0' };
     /* enable to work on "C:" as if it were "C:\" */
     if( strlen(pszFilename) == 2 && pszFilename[1] == ':' )
     {
@@ -440,7 +476,8 @@ int VSIStatExL( const char * pszFilename, VSIStatBufL *psStatBuf, int nFlags )
         VSIFileManager::GetHandler( pszFilename );
 
     if (nFlags == 0)
-        nFlags = VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG | VSI_STAT_SIZE_FLAG;
+        nFlags = VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG |
+            VSI_STAT_SIZE_FLAG;
 
     return poFSHandler->Stat( pszFilename, psStatBuf, nFlags );
 }
@@ -471,7 +508,7 @@ int VSIIsCaseSensitiveFS( const char * pszFilename )
 {
     VSIFilesystemHandler *poFSHandler =
         VSIFileManager::GetHandler( pszFilename );
-        
+
     return poFSHandler->IsCaseSensitive( pszFilename );
 }
 
@@ -486,13 +523,13 @@ int VSIIsCaseSensitiveFS( const char * pszFilename )
  * than 2GB) should be supported.  Binary access is always implied and
  * the "b" does not need to be included in the pszAccess string.
  *
- * Note that the "VSILFILE *" returned since GDAL 1.8.0 by this function is 
- * *NOT* a standard C library FILE *, and cannot be used with any functions 
+ * Note that the "VSILFILE *" returned since GDAL 1.8.0 by this function is
+ * *NOT* a standard C library FILE *, and cannot be used with any functions
  * other than the "VSI*L" family of functions.  They aren't "real" FILE objects.
  *
- * On windows it is possible to define the configuration option 
+ * On windows it is possible to define the configuration option
  * GDAL_FILE_IS_UTF8 to have pszFilename treated as being in the local
- * encoding instead of UTF-8, retoring the pre-1.8.0 behavior of VSIFOpenL().
+ * encoding instead of UTF-8, restoring the pre-1.8.0 behavior of VSIFOpenL().
  *
  * This method goes through the VSIFileHandler virtualization and may
  * work on unusual filesystems such as in memory.
@@ -500,7 +537,7 @@ int VSIIsCaseSensitiveFS( const char * pszFilename )
  * Analog of the POSIX fopen() function.
  *
  * @param pszFilename the file to open.  UTF-8 encoded.
- * @param pszAccess access requested (ie. "r", "r+", "w".  
+ * @param pszAccess access requested (i.e. "r", "r+", "w")
  *
  * @return NULL on failure, or the file handle.
  */
@@ -508,13 +545,63 @@ int VSIIsCaseSensitiveFS( const char * pszFilename )
 VSILFILE *VSIFOpenL( const char * pszFilename, const char * pszAccess )
 
 {
-    VSIFilesystemHandler *poFSHandler = 
+    return VSIFOpenExL(pszFilename, pszAccess, false);
+}
+
+/************************************************************************/
+/*                               Open()                                 */
+/************************************************************************/
+
+VSIVirtualHandle *VSIFilesystemHandler::Open( const char *pszFilename,
+                                          const char *pszAccess )
+{
+    return Open(pszFilename, pszAccess, false);
+}
+
+/************************************************************************/
+/*                             VSIFOpenExL()                              */
+/************************************************************************/
+
+/**
+ * \brief Open file.
+ *
+ * This function opens a file with the desired access.  Large files (larger
+ * than 2GB) should be supported.  Binary access is always implied and
+ * the "b" does not need to be included in the pszAccess string.
+ *
+ * Note that the "VSILFILE *" returned by this function is
+ * *NOT* a standard C library FILE *, and cannot be used with any functions
+ * other than the "VSI*L" family of functions.  They aren't "real" FILE objects.
+ *
+ * On windows it is possible to define the configuration option
+ * GDAL_FILE_IS_UTF8 to have pszFilename treated as being in the local
+ * encoding instead of UTF-8, restoring the pre-1.8.0 behavior of VSIFOpenL().
+ *
+ * This method goes through the VSIFileHandler virtualization and may
+ * work on unusual filesystems such as in memory.
+ *
+ * Analog of the POSIX fopen() function.
+ *
+ * @param pszFilename the file to open.  UTF-8 encoded.
+ * @param pszAccess access requested (i.e. "r", "r+", "w")
+ * @param bSetError flag determining whether or not this open call should set VSIErrors on failure.
+ *
+ * @return NULL on failure, or the file handle.
+ *
+ * @since GDAL 2.1
+ */
+
+VSILFILE *VSIFOpenExL( const char * pszFilename, const char * pszAccess, int bSetError )
+
+{
+    VSIFilesystemHandler *poFSHandler =
         VSIFileManager::GetHandler( pszFilename );
-        
-    VSILFILE* fp = (VSILFILE *) poFSHandler->Open( pszFilename, pszAccess );
 
-    VSIDebug3( "VSIFOpenL(%s,%s) = %p", pszFilename, pszAccess, fp );
-        
+    VSILFILE* fp = reinterpret_cast<VSILFILE *>(
+        poFSHandler->Open( pszFilename, pszAccess, CPL_TO_BOOL(bSetError) ) );
+
+    VSIDebug4( "VSIFOpenExL(%s,%s,%d) = %p", pszFilename, pszAccess, bSetError, fp );
+
     return fp;
 }
 
@@ -532,7 +619,8 @@ VSILFILE *VSIFOpenL( const char * pszFilename, const char * pszAccess )
  *
  * Analog of the POSIX fclose() function.
  *
- * @param fp file handle opened with VSIFOpenL().
+ * @param fp file handle opened with VSIFOpenL().  Passing a nullptr produces
+ * undefined behavior.
  *
  * @return 0 on success or -1 on failure.
  */
@@ -540,12 +628,12 @@ VSILFILE *VSIFOpenL( const char * pszFilename, const char * pszAccess )
 int VSIFCloseL( VSILFILE * fp )
 
 {
-    VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
-    
-    VSIDebug1( "VSICloseL(%p)", fp );
-    
-    int nResult = poFileHandle->Close();
-    
+    VSIVirtualHandle *poFileHandle = reinterpret_cast<VSIVirtualHandle *>( fp );
+
+    VSIDebug1( "VSIFCloseL(%p)", fp );
+
+    const int nResult = poFileHandle->Close();
+
     delete poFileHandle;
 
     return nResult;
@@ -558,14 +646,14 @@ int VSIFCloseL( VSILFILE * fp )
 /**
  * \brief Seek to requested offset.
  *
- * Seek to the desired offset (nOffset) in the indicated file. 
+ * Seek to the desired offset (nOffset) in the indicated file.
  *
  * This method goes through the VSIFileHandler virtualization and may
  * work on unusual filesystems such as in memory.
  *
  * Analog of the POSIX fseek() call.
  *
- * @param fp file handle opened with VSIFOpenL(). 
+ * @param fp file handle opened with VSIFOpenL().
  * @param nOffset offset in bytes.
  * @param nWhence one of SEEK_SET, SEEK_CUR or SEEK_END.
  *
@@ -576,7 +664,7 @@ int VSIFSeekL( VSILFILE * fp, vsi_l_offset nOffset, int nWhence )
 
 {
     VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
-    
+
     return poFileHandle->Seek( nOffset, nWhence );
 }
 
@@ -588,14 +676,14 @@ int VSIFSeekL( VSILFILE * fp, vsi_l_offset nOffset, int nWhence )
  * \brief Tell current file offset.
  *
  * Returns the current file read/write offset in bytes from the beginning of
- * the file. 
+ * the file.
  *
  * This method goes through the VSIFileHandler virtualization and may
  * work on unusual filesystems such as in memory.
  *
  * Analog of the POSIX ftell() call.
  *
- * @param fp file handle opened with VSIFOpenL(). 
+ * @param fp file handle opened with VSIFOpenL().
  *
  * @return file offset in bytes.
  */
@@ -603,8 +691,8 @@ int VSIFSeekL( VSILFILE * fp, vsi_l_offset nOffset, int nWhence )
 vsi_l_offset VSIFTellL( VSILFILE * fp )
 
 {
-    VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
-    
+    VSIVirtualHandle *poFileHandle = reinterpret_cast<VSIVirtualHandle *>( fp );
+
     return poFileHandle->Tell();
 }
 
@@ -612,10 +700,20 @@ vsi_l_offset VSIFTellL( VSILFILE * fp )
 /*                             VSIRewindL()                             */
 /************************************************************************/
 
+/**
+ * \brief Rewind the file pointer to the beginning of the file.
+ *
+ * This is equivalent to VSIFSeekL( fp, 0, SEEK_SET )
+ *
+ * Analog of the POSIX rewind() call.
+ *
+ * @param fp file handle opened with VSIFOpenL().
+ */
+
 void VSIRewindL( VSILFILE * fp )
 
 {
-    VSIFSeekL( fp, 0, SEEK_SET );
+    CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 0, SEEK_SET ));
 }
 
 /************************************************************************/
@@ -633,7 +731,7 @@ void VSIRewindL( VSILFILE * fp )
  *
  * Analog of the POSIX fflush() call.
  *
- * @param fp file handle opened with VSIFOpenL(). 
+ * @param fp file handle opened with VSIFOpenL().
  *
  * @return 0 on success or -1 on error.
  */
@@ -641,8 +739,8 @@ void VSIRewindL( VSILFILE * fp )
 int VSIFFlushL( VSILFILE * fp )
 
 {
-    VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
-    
+    VSIVirtualHandle *poFileHandle = reinterpret_cast<VSIVirtualHandle *>( fp );
+
     return poFileHandle->Flush();
 }
 
@@ -662,19 +760,19 @@ int VSIFFlushL( VSILFILE * fp )
  * Analog of the POSIX fread() call.
  *
  * @param pBuffer the buffer into which the data should be read (at least
- * nCount * nSize bytes in size. 
+ * nCount * nSize bytes in size.
  * @param nSize size of objects to read in bytes.
  * @param nCount number of objects to read.
- * @param fp file handle opened with VSIFOpenL(). 
+ * @param fp file handle opened with VSIFOpenL().
  *
- * @return number of objects successfully read. 
+ * @return number of objects successfully read.
  */
 
 size_t VSIFReadL( void * pBuffer, size_t nSize, size_t nCount, VSILFILE * fp )
 
 {
-    VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
-    
+    VSIVirtualHandle *poFileHandle = reinterpret_cast<VSIVirtualHandle *>( fp );
+
     return poFileHandle->Read( pBuffer, nSize, nCount );
 }
 
@@ -731,10 +829,10 @@ int VSIFReadMultiRangeL( int nRanges, void ** ppData,
  * Analog of the POSIX fwrite() call.
  *
  * @param pBuffer the buffer from which the data should be written (at least
- * nCount * nSize bytes in size. 
+ * nCount * nSize bytes in size.
  * @param nSize size of objects to read in bytes.
  * @param nCount number of objects to read.
- * @param fp file handle opened with VSIFOpenL(). 
+ * @param fp file handle opened with VSIFOpenL().
  *
  * @return number of objects successfully written.
  */
@@ -742,8 +840,8 @@ int VSIFReadMultiRangeL( int nRanges, void ** ppData,
 size_t VSIFWriteL( const void *pBuffer, size_t nSize, size_t nCount, VSILFILE *fp )
 
 {
-    VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
-    
+    VSIVirtualHandle *poFileHandle = reinterpret_cast<VSIVirtualHandle *>( fp );
+
     return poFileHandle->Write( pBuffer, nSize, nCount );
 }
 
@@ -754,7 +852,7 @@ size_t VSIFWriteL( const void *pBuffer, size_t nSize, size_t nCount, VSILFILE *f
 /**
  * \brief Test for end of file.
  *
- * Returns TRUE (non-zero) if an end-of-file condition occured during the
+ * Returns TRUE (non-zero) if an end-of-file condition occurred during the
  * previous read operation. The end-of-file flag is cleared by a successful
  * VSIFSeekL() call.
  *
@@ -763,7 +861,7 @@ size_t VSIFWriteL( const void *pBuffer, size_t nSize, size_t nCount, VSILFILE *f
  *
  * Analog of the POSIX feof() call.
  *
- * @param fp file handle opened with VSIFOpenL(). 
+ * @param fp file handle opened with VSIFOpenL().
  *
  * @return TRUE if at EOF else FALSE.
  */
@@ -771,8 +869,8 @@ size_t VSIFWriteL( const void *pBuffer, size_t nSize, size_t nCount, VSILFILE *f
 int VSIFEofL( VSILFILE * fp )
 
 {
-    VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
-    
+    VSIVirtualHandle *poFileHandle = reinterpret_cast<VSIVirtualHandle *>( fp );
+
     return poFileHandle->Eof();
 }
 
@@ -798,7 +896,7 @@ int VSIFEofL( VSILFILE * fp )
 int VSIFTruncateL( VSILFILE * fp, vsi_l_offset nNewSize )
 
 {
-    VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
+  VSIVirtualHandle *poFileHandle = reinterpret_cast<VSIVirtualHandle *>( fp );
 
     return poFileHandle->Truncate(nNewSize);
 }
@@ -811,13 +909,13 @@ int VSIFTruncateL( VSILFILE * fp, vsi_l_offset nNewSize )
  * \brief Formatted write to file.
  *
  * Provides fprintf() style formatted output to a VSI*L file.  This formats
- * an internal buffer which is written using VSIFWriteL(). 
+ * an internal buffer which is written using VSIFWriteL().
  *
  * Analog of the POSIX fprintf() call.
  *
- * @param fp file handle opened with VSIFOpenL(). 
- * @param pszFormat the printf style format string. 
- * 
+ * @param fp file handle opened with VSIFOpenL().
+ * @param pszFormat the printf style format string.
+ *
  * @return the number of bytes written or -1 on an error.
  */
 
@@ -825,24 +923,43 @@ int VSIFPrintfL( VSILFILE *fp, const char *pszFormat, ... )
 
 {
     va_list args;
-    CPLString osResult;
 
     va_start( args, pszFormat );
+    CPLString osResult;
     osResult.vPrintf( pszFormat, args );
     va_end( args );
 
-    return VSIFWriteL( osResult.c_str(), 1, osResult.length(), fp );
+    return static_cast<int>(
+        VSIFWriteL( osResult.c_str(), 1, osResult.length(), fp ));
 }
 
 /************************************************************************/
 /*                              VSIFPutcL()                              */
 /************************************************************************/
 
+// TODO: should we put in conformance with POSIX regarding the return
+// value. As of today (2015-08-29), no code in GDAL sources actually
+// check the return value.
+
+/**
+ * \brief Write a single byte to the file
+ *
+ * Writes the character nChar, cast to an unsigned char, to file.
+ *
+ * Almost an analog of the POSIX fputc() call, except that it returns
+ * the number of character written (1 or 0), and not the (cast) character itself or EOF.
+ *
+ * @param nChar character to write.
+ * @param fp file handle opened with VSIFOpenL().
+ *
+ * @return 1 in case of success, 0 on error.
+ */
+
 int VSIFPutcL( int nChar, VSILFILE * fp )
 
 {
-    unsigned char cChar = (unsigned char)nChar;
-    return VSIFWriteL(&cChar, 1, 1, fp);
+    unsigned char cChar = static_cast<unsigned char>(nChar);
+    return static_cast<int>(VSIFWriteL(&cChar, 1, 1, fp));
 }
 
 /************************************************************************/
@@ -868,7 +985,7 @@ int VSIFPutcL( int nChar, VSILFILE * fp )
  * @param pnSize pointer to variable to store the file size. May be NULL.
  * @param nMaxSize maximum size of file allowed. If no limit, set to a negative
  *                 value.
- * 
+ *
  * @return TRUE in case of success.
  *
  * @since GDAL 1.11
@@ -880,9 +997,6 @@ int VSIIngestFile( VSILFILE* fp,
                    vsi_l_offset* pnSize,
                    GIntBig nMaxSize)
 {
-    vsi_l_offset nDataLen = 0;
-    int bFreeFP = FALSE;
-
     if( fp == NULL && pszFilename == NULL )
         return FALSE;
     if( ppabyRet == NULL )
@@ -892,6 +1006,7 @@ int VSIIngestFile( VSILFILE* fp,
     if( pnSize != NULL )
         *pnSize = 0;
 
+    bool bFreeFP = false;
     if( NULL == fp )
     {
         fp = VSIFOpenL( pszFilename, "rb" );
@@ -901,17 +1016,27 @@ int VSIIngestFile( VSILFILE* fp,
                       "Cannot open file '%s'", pszFilename );
             return FALSE;
         }
-        bFreeFP = TRUE;
+        bFreeFP = true;
     }
     else
-        VSIFSeekL(fp, 0, SEEK_SET);
+    {
+        if( VSIFSeekL(fp, 0, SEEK_SET) != 0 )
+            return FALSE;
+    }
+
+    vsi_l_offset nDataLen = 0;
 
     if( pszFilename == NULL ||
         strcmp(pszFilename, "/vsistdin/") == 0 )
     {
         vsi_l_offset nDataAlloc = 0;
-        VSIFSeekL( fp, 0, SEEK_SET );
-        while(TRUE)
+        if( VSIFSeekL( fp, 0, SEEK_SET ) != 0 )
+        {
+            if( bFreeFP )
+                CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
+            return FALSE;
+        }
+        while(true)
         {
             if( nDataLen + 8192 + 1 > nDataAlloc )
             {
@@ -923,10 +1048,11 @@ int VSIIngestFile( VSILFILE* fp,
                     VSIFree( *ppabyRet );
                     *ppabyRet = NULL;
                     if( bFreeFP )
-                        VSIFCloseL( fp );
+                        CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
                     return FALSE;
                 }
-                GByte* pabyNew = (GByte*)VSIRealloc(*ppabyRet, (size_t)nDataAlloc);
+                GByte* pabyNew = static_cast<GByte *>(
+                    VSIRealloc(*ppabyRet, (size_t)nDataAlloc) );
                 if( pabyNew == NULL )
                 {
                     CPLError( CE_Failure, CPLE_OutOfMemory,
@@ -935,12 +1061,13 @@ int VSIIngestFile( VSILFILE* fp,
                     VSIFree( *ppabyRet );
                     *ppabyRet = NULL;
                     if( bFreeFP )
-                        VSIFCloseL( fp );
+                        CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
                     return FALSE;
                 }
                 *ppabyRet = pabyNew;
             }
-            int nRead = (int)VSIFReadL( *ppabyRet + nDataLen, 1, 8192, fp );
+            const int nRead = static_cast<int>(
+                VSIFReadL( *ppabyRet + nDataLen, 1, 8192, fp ) );
             nDataLen += nRead;
 
             if ( nMaxSize >= 0 && nDataLen > (vsi_l_offset)nMaxSize )
@@ -952,7 +1079,7 @@ int VSIIngestFile( VSILFILE* fp,
                 if( pnSize != NULL )
                     *pnSize = 0;
                 if( bFreeFP )
-                    VSIFCloseL( fp );
+                    CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
                 return FALSE;
             }
 
@@ -965,31 +1092,42 @@ int VSIIngestFile( VSILFILE* fp,
     }
     else
     {
-        VSIFSeekL( fp, 0, SEEK_END );
+        if( VSIFSeekL( fp, 0, SEEK_END ) != 0 )
+        {
+            if( bFreeFP )
+                CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
+            return FALSE;
+        }
         nDataLen = VSIFTellL( fp );
 
-        // With "large" VSI I/O API we can read data chunks larger than VSIMalloc
-        // could allocate. Catch it here.
+        // With "large" VSI I/O API we can read data chunks larger than
+        // VSIMalloc could allocate. Catch it here.
         if ( nDataLen > (vsi_l_offset)(size_t)nDataLen ||
              (nMaxSize >= 0 && nDataLen > (vsi_l_offset)nMaxSize) )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Input file too large to be opened" );
             if( bFreeFP )
-                VSIFCloseL( fp );
+                CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
             return FALSE;
         }
 
-        VSIFSeekL( fp, 0, SEEK_SET );
+        if( VSIFSeekL( fp, 0, SEEK_SET ) != 0 )
+        {
+            if( bFreeFP )
+                CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
+            return FALSE;
+        }
 
-        *ppabyRet = (GByte*)VSIMalloc((size_t)(nDataLen + 1));
+        *ppabyRet = static_cast<GByte *>(
+            VSIMalloc((size_t)(nDataLen + 1)) );
         if( NULL == *ppabyRet )
         {
             CPLError( CE_Failure, CPLE_OutOfMemory,
                       "Cannot allocated " CPL_FRMT_GIB " bytes",
                       nDataLen + 1 );
             if( bFreeFP )
-                VSIFCloseL( fp );
+                CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
             return FALSE;
         }
 
@@ -1002,14 +1140,14 @@ int VSIIngestFile( VSILFILE* fp,
             VSIFree( *ppabyRet );
             *ppabyRet = NULL;
             if( bFreeFP )
-                VSIFCloseL( fp );
+                CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
             return FALSE;
         }
         if( pnSize != NULL )
             *pnSize = nDataLen;
     }
     if( bFreeFP )
-        VSIFCloseL( fp );
+        CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
     return TRUE;
 }
 
@@ -1026,18 +1164,39 @@ int VSIIngestFile( VSILFILE* fp,
  * On POSIX systems, this will be a integer value ("fd") cast as a void*.
  * On Windows systems, this will be the HANDLE.
  *
- * @param fp file handle opened with VSIFOpenL(). 
- * 
+ * @param fp file handle opened with VSIFOpenL().
+ *
  * @return the native file descriptor, or NULL.
  */
 
 void *VSIFGetNativeFileDescriptorL( VSILFILE* fp )
 {
-    VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
-    
+    VSIVirtualHandle *poFileHandle = reinterpret_cast<VSIVirtualHandle *>( fp );
+
     return poFileHandle->GetNativeFileDescriptor();
 }
 
+/************************************************************************/
+/*                      VSIGetDiskFreeSpace()                           */
+/************************************************************************/
+
+/**
+ * \brief Return free disk space available on the filesystem.
+ *
+ * This function returns the free disk space available on the filesystem.
+ *
+ * @param pszDirname a directory of the filesystem to query.
+ * @return The free space in bytes. Or -1 in case of error.
+ * @since GDAL 2.1
+ */
+
+GIntBig VSIGetDiskFreeSpace(const char *pszDirname)
+{
+    VSIFilesystemHandler *poFSHandler =
+        VSIFileManager::GetHandler( pszDirname );
+
+    return poFSHandler->GetDiskFreeSpace( pszDirname );
+}
 
 /************************************************************************/
 /* ==================================================================== */
@@ -1050,18 +1209,16 @@ void *VSIFGetNativeFileDescriptorL( VSILFILE* fp )
 **
 ** The VSIFileManager maintains a list of file type handlers (mem, large
 ** file, etc).  It should be thread safe as long as all the handlers are
-** instantiated before multiple threads begin to operate. 
+** instantiated before multiple threads begin to operate.
 **/
 
 /************************************************************************/
 /*                           VSIFileManager()                           */
 /************************************************************************/
 
-VSIFileManager::VSIFileManager()
-
-{
-    poDefaultHandler = NULL;
-}
+VSIFileManager::VSIFileManager() :
+    poDefaultHandler(NULL)
+{}
 
 /************************************************************************/
 /*                          ~VSIFileManager()                           */
@@ -1069,7 +1226,7 @@ VSIFileManager::VSIFileManager()
 
 VSIFileManager::~VSIFileManager()
 {
-    std::map<std::string,VSIFilesystemHandler*>::const_iterator iter;
+    std::map<std::string, VSIFilesystemHandler*>::const_iterator iter;
 
     for( iter = oHandlers.begin();
          iter != oHandlers.end();
@@ -1092,20 +1249,22 @@ static CPLMutex* hVSIFileManagerMutex = NULL;
 VSIFileManager *VSIFileManager::Get()
 
 {
-    static volatile int nConstructerPID = 0;
+    static volatile GPtrDiff_t nConstructerPID = 0;
     if( poManager != NULL )
     {
         if( nConstructerPID != 0 )
         {
-            int nCurrentPID = (int)CPLGetPID();
+            GPtrDiff_t nCurrentPID = static_cast<GPtrDiff_t>(CPLGetPID());
             if( nConstructerPID != nCurrentPID )
             {
-                //printf("Thread %d: Waiting for VSIFileManager to be finished by other thread.\n", nCurrentPID);
                 {
                     CPLMutexHolder oHolder( &hVSIFileManagerMutex );
                 }
-                //printf("Thread %d: End of wait for VSIFileManager construction to be finished\n", nCurrentPID);
-                CPLAssert(nConstructerPID == 0);
+                if ( nConstructerPID != 0 )
+                {
+                    VSIDebug1( "nConstructerPID != 0: %d", nConstructerPID);
+                    assert(false);
+                }
             }
         }
         return poManager;
@@ -1114,8 +1273,10 @@ VSIFileManager *VSIFileManager::Get()
     CPLMutexHolder oHolder2( &hVSIFileManagerMutex );
     if( poManager == NULL )
     {
-        nConstructerPID = (int)CPLGetPID();
-        //printf("Thread %d: VSIFileManager in construction\n", nConstructerPID);
+        nConstructerPID = static_cast<GPtrDiff_t>(CPLGetPID());
+#ifdef DEBUG_VERBOSE
+        printf("Thread %d: VSIFileManager in construction\n", nConstructerPID);
+#endif
         poManager = new VSIFileManager;
         VSIInstallLargeFileHandler();
         VSIInstallSubFileHandler();
@@ -1127,15 +1288,19 @@ VSIFileManager *VSIFileManager::Get()
 #ifdef HAVE_CURL
         VSIInstallCurlFileHandler();
         VSIInstallCurlStreamingFileHandler();
+        VSIInstallS3FileHandler();
+        VSIInstallS3StreamingFileHandler();
 #endif
         VSIInstallStdinHandler();
         VSIInstallStdoutHandler();
         VSIInstallSparseFileHandler();
         VSIInstallTarFileHandler();
+        VSIInstallCryptFileHandler();
+
         //printf("Thread %d: VSIFileManager construction finished\n", nConstructerPID);
         nConstructerPID = 0;
     }
-    
+
     return poManager;
 }
 
@@ -1148,14 +1313,14 @@ VSIFilesystemHandler *VSIFileManager::GetHandler( const char *pszPath )
 {
     VSIFileManager *poThis = Get();
     std::map<std::string,VSIFilesystemHandler*>::const_iterator iter;
-    int nPathLen = strlen(pszPath);
+    size_t nPathLen = strlen(pszPath);
 
     for( iter = poThis->oHandlers.begin();
          iter != poThis->oHandlers.end();
          ++iter )
     {
         const char* pszIterKey = iter->first.c_str();
-        int nIterKeyLen = iter->first.size();
+        size_t nIterKeyLen = iter->first.size();
         if( strncmp(pszPath,pszIterKey,nIterKeyLen) == 0 )
             return iter->second;
 
@@ -1167,11 +1332,11 @@ VSIFilesystemHandler *VSIFileManager::GetHandler( const char *pszPath )
             return iter->second;
 
         /* /vsimem should be treated as a match for /vsimem/ */
-        if( nPathLen == nIterKeyLen - 1
-            && strncmp(pszPath,pszIterKey,nIterKeyLen-1) == 0 )
+        if( nPathLen + 1 == nIterKeyLen
+            && strncmp(pszPath,pszIterKey,nPathLen) == 0 )
             return iter->second;
     }
-    
+
     return poThis->poDefaultHandler;
 }
 
@@ -1218,8 +1383,8 @@ int VSIVirtualHandle::ReadMultiRange( int nRanges, void ** ppData,
                                       const size_t* panSizes )
 {
     int nRet = 0;
-    vsi_l_offset nCurOffset = Tell();
-    for(int i=0;i<nRanges;i++)
+    const vsi_l_offset nCurOffset = Tell();
+    for( int i=0; i<nRanges; i++ )
     {
         if (Seek(panOffsets[i], SEEK_SET) < 0)
         {
diff --git a/port/cpl_vsil_abstract_archive.cpp b/port/cpl_vsil_abstract_archive.cpp
index c2b98b4..deab69a 100644
--- a/port/cpl_vsil_abstract_archive.cpp
+++ b/port/cpl_vsil_abstract_archive.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsil_abstract_archive.cpp 29388 2015-06-17 18:28:29Z rouault $
+ * $Id: cpl_vsil_abstract_archive.cpp 33724 2016-03-16 17:14:11Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for archive files.
@@ -35,7 +35,7 @@
 
 #define ENABLE_DEBUG 0
 
-CPL_CVSID("$Id: cpl_vsil_abstract_archive.cpp 29388 2015-06-17 18:28:29Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_abstract_archive.cpp 33724 2016-03-16 17:14:11Z goatbar $");
 
 /************************************************************************/
 /*                    ~VSIArchiveEntryFileOffset()                      */
@@ -54,6 +54,20 @@ VSIArchiveReader::~VSIArchiveReader()
 }
 
 /************************************************************************/
+/*                        ~VSIArchiveContent()                          */
+/************************************************************************/
+
+VSIArchiveContent::~VSIArchiveContent()
+{
+    for(int i=0;i<nEntries;i++)
+    {
+        delete entries[i].file_pos;
+        CPLFree(entries[i].fileName);
+    }
+    CPLFree(entries);
+}
+
+/************************************************************************/
 /*                   VSIArchiveFilesystemHandler()                      */
 /************************************************************************/
 
@@ -73,15 +87,7 @@ VSIArchiveFilesystemHandler::~VSIArchiveFilesystemHandler()
 
     for( iter = oFileList.begin(); iter != oFileList.end(); ++iter )
     {
-        VSIArchiveContent* content = iter->second;
-        int i;
-        for(i=0;i<content->nEntries;i++)
-        {
-            delete content->entries[i].file_pos;
-            CPLFree(content->entries[i].fileName);
-        }
-        CPLFree(content->entries);
-        delete content;
+        delete iter->second;
     }
 
     if( hMutex != NULL )
@@ -104,7 +110,7 @@ const VSIArchiveContent* VSIArchiveFilesystemHandler::GetContentOfArchive
     if (oFileList.find(archiveFilename) != oFileList.end() )
     {
         VSIArchiveContent* content = oFileList[archiveFilename];
-        if( sStat.st_mtime > content->mTime ||
+        if( (time_t)sStat.st_mtime > content->mTime ||
             (vsi_l_offset)sStat.st_size != content->nFileSize)
         {
             CPLDebug("VSIArchive", "The content of %s has changed since it was cached",
@@ -245,8 +251,7 @@ int VSIArchiveFilesystemHandler::FindFileInArchive(const char* archiveFilename,
     const VSIArchiveContent* content = GetContentOfArchive(archiveFilename);
     if (content)
     {
-        int i;
-        for(i=0;i<content->nEntries;i++)
+        for( int i = 0; i < content->nEntries; i++ )
         {
             if (strcmp(fileInArchiveName, content->entries[i].fileName) == 0)
             {
@@ -273,10 +278,10 @@ char* VSIArchiveFilesystemHandler::SplitFilename(const char *pszFilename,
         return NULL;
 
     /* Allow natural chaining of VSI drivers without requiring double slash */
-    
+
     CPLString osDoubleVsi(GetPrefix());
     osDoubleVsi += "/vsi";
-    
+
     if (strncmp(pszFilename, osDoubleVsi.c_str(), osDoubleVsi.size()) == 0)
         pszFilename += strlen(GetPrefix());
     else
@@ -293,16 +298,24 @@ char* VSIArchiveFilesystemHandler::SplitFilename(const char *pszFilename,
             const CPLString& osExtension = *iter;
             if (EQUALN(pszFilename + i, osExtension.c_str(), strlen(osExtension.c_str())))
             {
-                nToSkip = strlen(osExtension.c_str());
+                nToSkip = static_cast<int>(strlen(osExtension.c_str()));
                 break;
             }
         }
 
+#ifdef DEBUG
+        /* For AFL, so that .cur_input is detected as the archive filename */
+        if( EQUALN( pszFilename + i, ".cur_input", strlen(".cur_input") ) )
+        {
+            nToSkip = static_cast<int>(strlen(".cur_input"));
+        }
+#endif
+
         if (nToSkip != 0)
         {
             VSIStatBufL statBuf;
             char* archiveFilename = CPLStrdup(pszFilename);
-            int bArchiveFileExists = FALSE;
+            bool bArchiveFileExists = false;
 
             if (archiveFilename[i + nToSkip] == '/' ||
                 archiveFilename[i + nToSkip] == '\\')
@@ -312,7 +325,7 @@ char* VSIArchiveFilesystemHandler::SplitFilename(const char *pszFilename,
 
             if (!bCheckMainFileExists)
             {
-                bArchiveFileExists = TRUE;
+                bArchiveFileExists = true;
             }
             else
             {
@@ -320,19 +333,19 @@ char* VSIArchiveFilesystemHandler::SplitFilename(const char *pszFilename,
 
                 if (oFileList.find(archiveFilename) != oFileList.end() )
                 {
-                    bArchiveFileExists = TRUE;
+                    bArchiveFileExists = true;
                 }
             }
 
             if (!bArchiveFileExists)
             {
-                VSIFilesystemHandler *poFSHandler = 
+                VSIFilesystemHandler *poFSHandler =
                     VSIFileManager::GetHandler( archiveFilename );
                 if (poFSHandler->Stat(archiveFilename, &statBuf,
                                       VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG) == 0 &&
                     !VSI_ISDIR(statBuf.st_mode))
                 {
-                    bArchiveFileExists = TRUE;
+                    bArchiveFileExists = true;
                 }
             }
 
@@ -344,7 +357,7 @@ char* VSIArchiveFilesystemHandler::SplitFilename(const char *pszFilename,
                     char* pszArchiveInFileName = CPLStrdup(pszFilename + i + nToSkip + 1);
 
                     /* Replace a/../b by b and foo/a/../b by foo/b */
-                    while(TRUE)
+                    while(true)
                     {
                         char* pszPrevDir = strstr(pszArchiveInFileName, "/../");
                         if (pszPrevDir == NULL || pszPrevDir == pszArchiveInFileName)
@@ -387,7 +400,7 @@ char* VSIArchiveFilesystemHandler::SplitFilename(const char *pszFilename,
 /*                           OpenArchiveFile()                          */
 /************************************************************************/
 
-VSIArchiveReader* VSIArchiveFilesystemHandler::OpenArchiveFile(const char* archiveFilename, 
+VSIArchiveReader* VSIArchiveFilesystemHandler::OpenArchiveFile(const char* archiveFilename,
                                                                const char* fileInArchiveName)
 {
     VSIArchiveReader* poReader = CreateReader(archiveFilename);
@@ -405,7 +418,7 @@ VSIArchiveReader* VSIArchiveFilesystemHandler::OpenArchiveFile(const char* archi
             return NULL;
         }
 
-        /* Skip optionnal leading subdir */
+        /* Skip optional leading subdir */
         CPLString osFileName = poReader->GetFileName();
         const char* fileName = osFileName.c_str();
         if (fileName[strlen(fileName)-1] == '/' || fileName[strlen(fileName)-1] == '\\')
@@ -425,9 +438,8 @@ VSIArchiveReader* VSIArchiveFilesystemHandler::OpenArchiveFile(const char* archi
             const VSIArchiveContent* content = GetContentOfArchive(archiveFilename, poReader);
             if (content)
             {
-                int i;
                 msg += "\nYou could try one of the following :\n";
-                for(i=0;i<content->nEntries;i++)
+                for( int i=0; i < content->nEntries; i++ )
                 {
                     msg += CPLString().Printf("  %s/%s/%s\n", GetPrefix(), archiveFilename, content->entries[i].fileName);
                 }
@@ -500,7 +512,7 @@ int VSIArchiveFilesystemHandler::Stat( const char *pszFilename,
 
         if (poReader != NULL && poReader->GotoFirstFile())
         {
-            /* Skip optionnal leading subdir */
+            /* Skip optional leading subdir */
             CPLString osFileName = poReader->GetFileName();
             const char* fileName = osFileName.c_str();
             if (fileName[strlen(fileName)-1] == '/' || fileName[strlen(fileName)-1] == '\\')
@@ -575,19 +587,20 @@ int VSIArchiveFilesystemHandler::Rmdir( CPL_UNUSED const char *pszDirname )
 }
 
 /************************************************************************/
-/*                             ReadDir()                                */
+/*                             ReadDirEx()                              */
 /************************************************************************/
 
-char** VSIArchiveFilesystemHandler::ReadDir( const char *pszDirname )
+char** VSIArchiveFilesystemHandler::ReadDirEx( const char *pszDirname,
+                                               int nMaxFiles )
 {
     CPLString osInArchiveSubDir;
     char* archiveFilename = SplitFilename(pszDirname, osInArchiveSubDir, TRUE);
     if (archiveFilename == NULL)
         return NULL;
-    int lenInArchiveSubDir = strlen(osInArchiveSubDir);
+    int lenInArchiveSubDir = static_cast<int>(strlen(osInArchiveSubDir));
+
+    CPLStringList oDir;
 
-    char **papszDir = NULL;
-    
     const VSIArchiveContent* content = GetContentOfArchive(archiveFilename);
     if (!content)
     {
@@ -596,8 +609,7 @@ char** VSIArchiveFilesystemHandler::ReadDir( const char *pszDirname )
     }
 
     if (ENABLE_DEBUG) CPLDebug("VSIArchive", "Read dir %s", pszDirname);
-    int i;
-    for(i=0;i<content->nEntries;i++)
+    for( int i=0; i < content->nEntries; i++ )
     {
         const char* fileName = content->entries[i].fileName;
         /* Only list entries at the same level of inArchiveSubDir */
@@ -619,7 +631,7 @@ char** VSIArchiveFilesystemHandler::ReadDir( const char *pszDirname )
                 if (ENABLE_DEBUG)
                     CPLDebug("VSIArchive", "Add %s as in directory %s\n",
                             tmpFileName + lenInArchiveSubDir + 1, pszDirname);
-                papszDir = CSLAddString(papszDir, tmpFileName + lenInArchiveSubDir + 1);
+                oDir.AddString(tmpFileName + lenInArchiveSubDir + 1);
                 CPLFree(tmpFileName);
             }
         }
@@ -628,10 +640,13 @@ char** VSIArchiveFilesystemHandler::ReadDir( const char *pszDirname )
         {
             /* Only list toplevel files and directories */
             if (ENABLE_DEBUG) CPLDebug("VSIArchive", "Add %s as in directory %s\n", fileName, pszDirname);
-            papszDir = CSLAddString(papszDir, fileName);
+            oDir.AddString(fileName);
         }
+
+        if( nMaxFiles > 0 && oDir.Count() > nMaxFiles )
+            break;
     }
 
     CPLFree(archiveFilename);
-    return papszDir;
+    return oDir.StealList();
 }
diff --git a/port/cpl_vsil_buffered_reader.cpp b/port/cpl_vsil_buffered_reader.cpp
index 6124c38..35ba4dd 100644
--- a/port/cpl_vsil_buffered_reader.cpp
+++ b/port/cpl_vsil_buffered_reader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsil_buffered_reader.cpp 28493 2015-02-16 09:49:16Z rouault $
+ * $Id: cpl_vsil_buffered_reader.cpp 33646 2016-03-05 15:54:03Z goatbar $
  *
  * Project:  VSI Virtual File System
  * Purpose:  Implementation of buffered reader IO functions.
@@ -39,19 +39,19 @@
 
 #define MAX_BUFFER_SIZE 65536
 
-CPL_CVSID("$Id: cpl_vsil_buffered_reader.cpp 28493 2015-02-16 09:49:16Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_buffered_reader.cpp 33646 2016-03-05 15:54:03Z goatbar $");
 
-class VSIBufferedReaderHandle : public VSIVirtualHandle
+class VSIBufferedReaderHandle CPL_FINAL : public VSIVirtualHandle
 {
-    VSIVirtualHandle* poBaseHandle;
+    VSIVirtualHandle* m_poBaseHandle;
     GByte*            pabyBuffer;
     GUIntBig          nBufferOffset;
     int               nBufferSize;
     GUIntBig          nCurOffset;
     int               bNeedBaseHandleSeek;
     int               bEOF;
-    vsi_l_offset      nSheatFileSize;
-    
+    vsi_l_offset      nCheatFileSize;
+
     int               SeekBaseTo(vsi_l_offset nTargetOffset);
 
   public:
@@ -59,7 +59,7 @@ class VSIBufferedReaderHandle : public VSIVirtualHandle
     VSIBufferedReaderHandle(VSIVirtualHandle* poBaseHandle);
     VSIBufferedReaderHandle(VSIVirtualHandle* poBaseHandle,
                             const GByte* pabyBeginningContent,
-                            vsi_l_offset nSheatFileSizeIn);
+                            vsi_l_offset nCheatFileSizeIn);
     ~VSIBufferedReaderHandle();
 
     virtual int       Seek( vsi_l_offset nOffset, int nWhence );
@@ -82,11 +82,11 @@ VSIVirtualHandle* VSICreateBufferedReaderHandle(VSIVirtualHandle* poBaseHandle)
 
 VSIVirtualHandle* VSICreateBufferedReaderHandle(VSIVirtualHandle* poBaseHandle,
                                                 const GByte* pabyBeginningContent,
-                                                vsi_l_offset nSheatFileSizeIn)
+                                                vsi_l_offset nCheatFileSizeIn)
 {
     return new VSIBufferedReaderHandle(poBaseHandle,
                                        pabyBeginningContent,
-                                       nSheatFileSizeIn);
+                                       nCheatFileSizeIn);
 }
 
 /************************************************************************/
@@ -95,21 +95,21 @@ VSIVirtualHandle* VSICreateBufferedReaderHandle(VSIVirtualHandle* poBaseHandle,
 
 VSIBufferedReaderHandle::VSIBufferedReaderHandle(VSIVirtualHandle* poBaseHandle)
 {
-    this->poBaseHandle = poBaseHandle;
+    m_poBaseHandle = poBaseHandle;
     pabyBuffer = (GByte*)CPLMalloc(MAX_BUFFER_SIZE);
     nBufferOffset = 0;
     nBufferSize = 0;
     nCurOffset = 0;
     bNeedBaseHandleSeek = FALSE;
     bEOF = FALSE;
-    nSheatFileSize = 0;
+    nCheatFileSize = 0;
 }
 
 VSIBufferedReaderHandle::VSIBufferedReaderHandle(VSIVirtualHandle* poBaseHandle,
                                                  const GByte* pabyBeginningContent,
-                                                 vsi_l_offset nSheatFileSizeIn)
+                                                 vsi_l_offset nCheatFileSizeIn)
 {
-    this->poBaseHandle = poBaseHandle;
+    m_poBaseHandle = poBaseHandle;
     nBufferOffset = 0;
     nBufferSize = (int)poBaseHandle->Tell();
     pabyBuffer = (GByte*)CPLMalloc(MAX(MAX_BUFFER_SIZE,nBufferSize));
@@ -117,7 +117,7 @@ VSIBufferedReaderHandle::VSIBufferedReaderHandle(VSIVirtualHandle* poBaseHandle,
     nCurOffset = 0;
     bNeedBaseHandleSeek = TRUE;
     bEOF = FALSE;
-    nSheatFileSize = nSheatFileSizeIn;
+    nCheatFileSize = nCheatFileSizeIn;
 }
 
 /************************************************************************/
@@ -126,7 +126,7 @@ VSIBufferedReaderHandle::VSIBufferedReaderHandle(VSIVirtualHandle* poBaseHandle,
 
 VSIBufferedReaderHandle::~VSIBufferedReaderHandle()
 {
-    delete poBaseHandle;
+    delete m_poBaseHandle;
     CPLFree(pabyBuffer);
 }
 
@@ -142,17 +142,17 @@ int VSIBufferedReaderHandle::Seek( vsi_l_offset nOffset, int nWhence )
         nCurOffset += nOffset;
     else if (nWhence == SEEK_END)
     {
-        if( nSheatFileSize )
-            nCurOffset = nSheatFileSize;
+        if( nCheatFileSize )
+            nCurOffset = nCheatFileSize;
         else
         {
-            poBaseHandle->Seek(nOffset, nWhence);
-            nCurOffset = poBaseHandle->Tell();
+            m_poBaseHandle->Seek(nOffset, nWhence);
+            nCurOffset = m_poBaseHandle->Tell();
             bNeedBaseHandleSeek = TRUE;
         }
     }
     else
-        nCurOffset = nOffset;   
+        nCurOffset = nOffset;
 
     return 0;
 }
@@ -173,17 +173,17 @@ vsi_l_offset VSIBufferedReaderHandle::Tell()
 
 int VSIBufferedReaderHandle::SeekBaseTo(vsi_l_offset nTargetOffset)
 {
-    if( poBaseHandle->Seek(nTargetOffset, SEEK_SET) == 0 )
+    if( m_poBaseHandle->Seek(nTargetOffset, SEEK_SET) == 0 )
         return TRUE;
 
-    nCurOffset = poBaseHandle->Tell();
+    nCurOffset = m_poBaseHandle->Tell();
     if( nCurOffset > nTargetOffset )
         return FALSE;
     char abyTemp[8192];
-    while(TRUE)
+    while( true )
     {
         int nToRead = (int) MIN(8192, nTargetOffset - nCurOffset);
-        int nRead = (int)poBaseHandle->Read(abyTemp, 1, nToRead );
+        int nRead = (int)m_poBaseHandle->Read(abyTemp, 1, nToRead );
         nCurOffset += nRead;
 
         if (nRead < nToRead)
@@ -213,12 +213,12 @@ size_t VSIBufferedReaderHandle::Read( void *pBuffer, size_t nSize, size_t nMemb
         nCurOffset >= nBufferOffset && nCurOffset <= nBufferOffset + nBufferSize)
     {
         /* We try to read from an offset located within the buffer */
-        const int nReadInBuffer = (int) MIN(nTotalToRead, nBufferOffset + nBufferSize - nCurOffset);
+        const size_t nReadInBuffer = static_cast<size_t>( MIN(nTotalToRead, nBufferOffset + nBufferSize - nCurOffset) );
         memcpy(pBuffer, pabyBuffer + nCurOffset - nBufferOffset, nReadInBuffer);
-        const int nToReadInFile = nTotalToRead - nReadInBuffer;
+        const size_t nToReadInFile = nTotalToRead - nReadInBuffer;
         if (nToReadInFile > 0)
         {
-            /* The beginning of the the data to read is located in the buffer */
+            /* The beginning of the data to read is located in the buffer */
             /* but the end must be read from the file */
             if (bNeedBaseHandleSeek)
             {
@@ -229,20 +229,20 @@ size_t VSIBufferedReaderHandle::Read( void *pBuffer, size_t nSize, size_t nMemb
                 }
             }
             bNeedBaseHandleSeek = FALSE;
-            //CPLAssert(poBaseHandle->Tell() == nBufferOffset + nBufferSize);
+            //CPLAssert(m_poBaseHandle->Tell() == nBufferOffset + nBufferSize);
 
-            const int nReadInFile = poBaseHandle->Read((GByte*)pBuffer + nReadInBuffer, 1, nToReadInFile);
-            const int nRead = nReadInBuffer + nReadInFile;
+            const size_t nReadInFile = m_poBaseHandle->Read((GByte*)pBuffer + nReadInBuffer, 1, nToReadInFile);
+            const size_t nRead = nReadInBuffer + nReadInFile;
 
-            nBufferSize = MIN(nRead, MAX_BUFFER_SIZE);
+            nBufferSize = static_cast<int>( MIN(nRead, MAX_BUFFER_SIZE) );
             nBufferOffset = nCurOffset + nRead - nBufferSize;
             memcpy(pabyBuffer, (GByte*)pBuffer + nRead - nBufferSize, nBufferSize);
 
             nCurOffset += nRead;
-            //CPLAssert(poBaseHandle->Tell() == nBufferOffset + nBufferSize);
-            //CPLAssert(poBaseHandle->Tell() == nCurOffset);
+            //CPLAssert(m_poBaseHandle->Tell() == nBufferOffset + nBufferSize);
+            //CPLAssert(m_poBaseHandle->Tell() == nCurOffset);
 
-            bEOF = poBaseHandle->Eof();
+            bEOF = m_poBaseHandle->Eof();
 
             return nRead / nSize;
         }
@@ -259,16 +259,16 @@ size_t VSIBufferedReaderHandle::Read( void *pBuffer, size_t nSize, size_t nMemb
         if( !SeekBaseTo(nCurOffset) )
             return 0;
         bNeedBaseHandleSeek = FALSE;
-        const int nReadInFile = poBaseHandle->Read(pBuffer, 1, nTotalToRead);
-        nBufferSize = MIN(nReadInFile, MAX_BUFFER_SIZE);
+        const size_t nReadInFile = m_poBaseHandle->Read(pBuffer, 1, nTotalToRead);
+        nBufferSize = static_cast<int>( MIN(nReadInFile, MAX_BUFFER_SIZE) );
         nBufferOffset = nCurOffset + nReadInFile - nBufferSize;
         memcpy(pabyBuffer, (GByte*)pBuffer + nReadInFile - nBufferSize, nBufferSize);
 
         nCurOffset += nReadInFile;
-        //CPLAssert(poBaseHandle->Tell() == nBufferOffset + nBufferSize);
-        //CPLAssert(poBaseHandle->Tell() == nCurOffset);
+        //CPLAssert(m_poBaseHandle->Tell() == nBufferOffset + nBufferSize);
+        //CPLAssert(m_poBaseHandle->Tell() == nCurOffset);
 
-        bEOF = poBaseHandle->Eof();
+        bEOF = m_poBaseHandle->Eof();
 
         return nReadInFile / nSize;
     }
@@ -313,11 +313,11 @@ int VSIBufferedReaderHandle::Flush()
 
 int VSIBufferedReaderHandle::Close()
 {
-    if (poBaseHandle)
+    if (m_poBaseHandle)
     {
-        poBaseHandle->Close();
-        delete poBaseHandle;
-        poBaseHandle = NULL;
+        m_poBaseHandle->Close();
+        delete m_poBaseHandle;
+        m_poBaseHandle = NULL;
     }
     return 0;
 }
diff --git a/port/cpl_vsil_cache.cpp b/port/cpl_vsil_cache.cpp
index c050e09..16161f6 100644
--- a/port/cpl_vsil_cache.cpp
+++ b/port/cpl_vsil_cache.cpp
@@ -29,6 +29,7 @@
  ****************************************************************************/
 
 #include "cpl_vsi_virtual.h"
+#include <map>
 
 CPL_CVSID("$Id$");
 
@@ -41,13 +42,14 @@ CPL_CVSID("$Id$");
 class VSICacheChunk
 {
 public:
-    VSICacheChunk() 
-    { 
-        poLRUPrev = poLRUNext = NULL;
-        nDataFilled = 0;
-        bDirty = FALSE;
-        pabyData = NULL;
-    }
+  VSICacheChunk() :
+      bDirty(FALSE),
+      iBlock(0),
+      poLRUPrev(NULL),
+      poLRUNext(NULL),
+      nDataFilled(0),
+      pabyData(NULL)
+    { }
 
     virtual ~VSICacheChunk()
     {
@@ -77,33 +79,33 @@ public:
 /* ==================================================================== */
 /************************************************************************/
 
-class VSICachedFile : public VSIVirtualHandle
-{ 
+class VSICachedFile CPL_FINAL : public VSIVirtualHandle
+{
   public:
-    VSICachedFile( VSIVirtualHandle *poBaseHandle, 
+    VSICachedFile( VSIVirtualHandle *poBaseHandle,
                    size_t nChunkSize,
                    size_t nCacheSize );
     ~VSICachedFile() { Close(); }
 
     void          FlushLRU();
-    int           LoadBlocks( vsi_l_offset nStartBlock, size_t nBlockCount, 
+    int           LoadBlocks( vsi_l_offset nStartBlock, size_t nBlockCount,
                               void *pBuffer, size_t nBufferSize );
     void          Demote( VSICacheChunk * );
 
     VSIVirtualHandle *poBase;
-    
+
     vsi_l_offset  nOffset;
     vsi_l_offset  nFileSize;
 
     GUIntBig      nCacheUsed;
     GUIntBig      nCacheMax;
 
-    size_t        nChunkSize;
+    size_t        m_nChunkSize;
 
     VSICacheChunk *poLRUStart;
     VSICacheChunk *poLRUEnd;
 
-    std::vector<VSICacheChunk*> apoCache;
+    std::map<vsi_l_offset, VSICacheChunk*> oMapOffsetToCache;
 
     int            bEOF;
 
@@ -125,11 +127,11 @@ VSICachedFile::VSICachedFile( VSIVirtualHandle *poBaseHandle, size_t nChunkSize,
 
 {
     poBase = poBaseHandle;
-    this->nChunkSize = nChunkSize;
+    m_nChunkSize = nChunkSize;
 
     nCacheUsed = 0;
     if ( nCacheSize == 0 )
-        nCacheMax = CPLScanUIntBig( 
+        nCacheMax = CPLScanUIntBig(
              CPLGetConfigOption( "VSI_CACHE_SIZE", "25000000" ), 40 );
     else
         nCacheMax = nCacheSize;
@@ -151,11 +153,12 @@ VSICachedFile::VSICachedFile( VSIVirtualHandle *poBaseHandle, size_t nChunkSize,
 int VSICachedFile::Close()
 
 {
-    size_t i;
-    for( i = 0; i < apoCache.size(); i++ )
-        delete apoCache[i];
-
-    apoCache.resize( 0 );
+    for( std::map<vsi_l_offset, VSICacheChunk*>::iterator oIter = oMapOffsetToCache.begin();
+         oIter != oMapOffsetToCache.end(); ++oIter )
+    {
+        delete oIter->second;
+    }
+    oMapOffsetToCache.clear();
 
     poLRUStart = NULL;
     poLRUEnd = NULL;
@@ -225,7 +228,7 @@ void VSICachedFile::FlushLRU()
     CPLAssert( nCacheUsed >= poBlock->nDataFilled );
 
     nCacheUsed -= poBlock->nDataFilled;
-    
+
     poLRUStart = poBlock->poLRUNext;
     if( poLRUEnd == poBlock )
         poLRUEnd = NULL;
@@ -235,7 +238,7 @@ void VSICachedFile::FlushLRU()
 
     CPLAssert( !poBlock->bDirty );
 
-    apoCache[poBlock->iBlock] = NULL;
+    oMapOffsetToCache[poBlock->iBlock] = NULL;
 
     delete poBlock;
 }
@@ -254,7 +257,7 @@ void VSICachedFile::Demote( VSICacheChunk *poBlock )
     // already at end?
     if( poLRUEnd == poBlock )
         return;
-    
+
     if( poLRUStart == poBlock )
         poLRUStart = poBlock->poLRUNext;
 
@@ -270,7 +273,7 @@ void VSICachedFile::Demote( VSICacheChunk *poBlock )
     if( poLRUEnd != NULL )
         poLRUEnd->poLRUNext = poBlock;
     poLRUEnd = poBlock;
-    
+
     if( poLRUStart == NULL )
         poLRUStart = poBlock;
 }
@@ -289,31 +292,28 @@ int VSICachedFile::LoadBlocks( vsi_l_offset nStartBlock, size_t nBlockCount,
     if( nBlockCount == 0 )
         return 1;
 
-    if( apoCache.size() < nStartBlock + nBlockCount )
-        apoCache.resize( nStartBlock + nBlockCount );
-
 /* -------------------------------------------------------------------- */
 /*      When we want to load only one block, we can directly load it    */
 /*      into the target buffer with no concern about intermediaries.    */
 /* -------------------------------------------------------------------- */
     if( nBlockCount == 1 )
     {
-        poBase->Seek( (vsi_l_offset)nStartBlock * nChunkSize, SEEK_SET );
+        poBase->Seek( (vsi_l_offset)nStartBlock * m_nChunkSize, SEEK_SET );
 
         VSICacheChunk *poBlock = new VSICacheChunk();
-        if ( !poBlock || !poBlock->Allocate( nChunkSize ) )
+        if ( !poBlock || !poBlock->Allocate( m_nChunkSize ) )
         {
             delete poBlock;
             return 0;
         }
 
-        apoCache[nStartBlock] = poBlock;
+        oMapOffsetToCache[nStartBlock] = poBlock;
 
         poBlock->iBlock = nStartBlock;
-        poBlock->nDataFilled = poBase->Read( poBlock->pabyData, 1, nChunkSize );
+        poBlock->nDataFilled = poBase->Read( poBlock->pabyData, 1, m_nChunkSize );
         nCacheUsed += poBlock->nDataFilled;
 
-        // Merges into the LRU list. 
+        // Merges into the LRU list.
         Demote( poBlock );
 
         return 1;
@@ -325,8 +325,8 @@ int VSICachedFile::LoadBlocks( vsi_l_offset nStartBlock, size_t nBlockCount,
 /*      io request in two in order to avoid allocating a large          */
 /*      temporary buffer.                                               */
 /* -------------------------------------------------------------------- */
-    if( nBufferSize > nChunkSize * 20 
-        && nBufferSize < nBlockCount * nChunkSize )
+    if( nBufferSize > m_nChunkSize * 20
+        && nBufferSize < nBlockCount * m_nChunkSize )
     {
         if( !LoadBlocks( nStartBlock, 2, pBuffer, nBufferSize ) )
             return 0;
@@ -334,29 +334,30 @@ int VSICachedFile::LoadBlocks( vsi_l_offset nStartBlock, size_t nBlockCount,
         return LoadBlocks( nStartBlock+2, nBlockCount-2, pBuffer, nBufferSize );
     }
 
+    if( poBase->Seek( (vsi_l_offset)nStartBlock * m_nChunkSize, SEEK_SET ) != 0 )
+        return 0;
+
 /* -------------------------------------------------------------------- */
 /*      Do we need to allocate our own buffer?                          */
 /* -------------------------------------------------------------------- */
     GByte *pabyWorkBuffer = (GByte *) pBuffer;
 
-    if( nBufferSize < nChunkSize * nBlockCount )
-        pabyWorkBuffer = (GByte *) CPLMalloc(nChunkSize * nBlockCount);
+    if( nBufferSize < m_nChunkSize * nBlockCount )
+        pabyWorkBuffer = (GByte *) CPLMalloc(m_nChunkSize * nBlockCount);
 
 /* -------------------------------------------------------------------- */
 /*      Read the whole request into the working buffer.                 */
 /* -------------------------------------------------------------------- */
-    if( poBase->Seek( (vsi_l_offset)nStartBlock * nChunkSize, SEEK_SET ) != 0 )
-        return 0;
 
-    size_t nDataRead = poBase->Read( pabyWorkBuffer, 1, nBlockCount*nChunkSize);
+    size_t nDataRead = poBase->Read( pabyWorkBuffer, 1, nBlockCount*m_nChunkSize);
 
-    if( nBlockCount * nChunkSize > nDataRead + nChunkSize - 1 )
-        nBlockCount = (nDataRead + nChunkSize - 1) / nChunkSize;
+    if( nBlockCount * m_nChunkSize > nDataRead + m_nChunkSize - 1 )
+        nBlockCount = (nDataRead + m_nChunkSize - 1) / m_nChunkSize;
 
     for( size_t i = 0; i < nBlockCount; i++ )
     {
         VSICacheChunk *poBlock = new VSICacheChunk();
-        if ( !poBlock || !poBlock->Allocate( nChunkSize ) )
+        if ( !poBlock || !poBlock->Allocate( m_nChunkSize ) )
         {
             delete poBlock;
             return 0;
@@ -364,21 +365,21 @@ int VSICachedFile::LoadBlocks( vsi_l_offset nStartBlock, size_t nBlockCount,
 
         poBlock->iBlock = nStartBlock + i;
 
-        CPLAssert( apoCache[i+nStartBlock] == NULL );
+        CPLAssert( oMapOffsetToCache[i+nStartBlock] == NULL );
 
-        apoCache[i + nStartBlock] = poBlock;
+        oMapOffsetToCache[i + nStartBlock] = poBlock;
 
-        if( nDataRead >= (i+1) * nChunkSize )
-            poBlock->nDataFilled = nChunkSize;
+        if( nDataRead >= (i+1) * m_nChunkSize )
+            poBlock->nDataFilled = m_nChunkSize;
         else
-            poBlock->nDataFilled = nDataRead - i*nChunkSize;
+            poBlock->nDataFilled = nDataRead - i*m_nChunkSize;
 
-        memcpy( poBlock->pabyData, pabyWorkBuffer + i*nChunkSize,
+        memcpy( poBlock->pabyData, pabyWorkBuffer + i*m_nChunkSize,
                 (size_t) poBlock->nDataFilled );
 
         nCacheUsed += poBlock->nDataFilled;
 
-        // Merges into the LRU list. 
+        // Merges into the LRU list.
         Demote( poBlock );
     }
 
@@ -404,23 +405,22 @@ size_t VSICachedFile::Read( void * pBuffer, size_t nSize, size_t nCount )
 /* ==================================================================== */
 /*      Make sure the cache is loaded for the whole request region.     */
 /* ==================================================================== */
-    vsi_l_offset nStartBlock = nOffset / nChunkSize;
-    vsi_l_offset nEndBlock = (nOffset + nSize * nCount - 1) / nChunkSize;
+    vsi_l_offset nStartBlock = nOffset / m_nChunkSize;
+    vsi_l_offset nEndBlock = (nOffset + nSize * nCount - 1) / m_nChunkSize;
 
     for( vsi_l_offset iBlock = nStartBlock; iBlock <= nEndBlock; iBlock++ )
     {
-        if( apoCache.size() <= iBlock || apoCache[iBlock] == NULL )
+        if( oMapOffsetToCache[iBlock] == NULL )
         {
             size_t nBlocksToLoad = 1;
             while( iBlock + nBlocksToLoad <= nEndBlock
-                   && (apoCache.size() <= iBlock+nBlocksToLoad 
-                       || apoCache[iBlock+nBlocksToLoad] == NULL) )
+                   && (oMapOffsetToCache[iBlock+nBlocksToLoad] == NULL) )
                 nBlocksToLoad++;
 
             LoadBlocks( iBlock, nBlocksToLoad, pBuffer, nSize * nCount );
         }
     }
-    
+
 /* ==================================================================== */
 /*      Copy data into the target buffer to the extent possible.        */
 /* ==================================================================== */
@@ -428,24 +428,23 @@ size_t VSICachedFile::Read( void * pBuffer, size_t nSize, size_t nCount )
 
     while( nAmountCopied < nSize * nCount )
     {
-        vsi_l_offset iBlock = (nOffset + nAmountCopied) / nChunkSize;
-        size_t nThisCopy;
-        VSICacheChunk *poBlock = apoCache[iBlock];
+        vsi_l_offset iBlock = (nOffset + nAmountCopied) / m_nChunkSize;
+        VSICacheChunk *poBlock = oMapOffsetToCache[iBlock];
         if( poBlock == NULL )
         {
             /* We can reach that point when the amount to read exceeds */
             /* the cache size */
             LoadBlocks( iBlock, 1, ((GByte *) pBuffer) + nAmountCopied,
-                        MIN(nSize * nCount - nAmountCopied, nChunkSize) );
-            poBlock = apoCache[iBlock];
+                        MIN(nSize * nCount - nAmountCopied, m_nChunkSize) );
+            poBlock = oMapOffsetToCache[iBlock];
             CPLAssert(poBlock != NULL);
         }
 
-        vsi_l_offset nStartOffset = (vsi_l_offset)iBlock * nChunkSize;
-        nThisCopy = (size_t)
-            ((nStartOffset + poBlock->nDataFilled) 
+        vsi_l_offset nStartOffset = (vsi_l_offset)iBlock * m_nChunkSize;
+        size_t nThisCopy = (size_t)
+            ((nStartOffset + poBlock->nDataFilled)
              - nAmountCopied - nOffset);
-        
+
         if( nThisCopy > nSize * nCount - nAmountCopied )
             nThisCopy = nSize * nCount - nAmountCopied;
 
@@ -453,13 +452,13 @@ size_t VSICachedFile::Read( void * pBuffer, size_t nSize, size_t nCount )
             break;
 
         memcpy( ((GByte *) pBuffer) + nAmountCopied,
-                poBlock->pabyData 
-                + (nOffset + nAmountCopied) - nStartOffset, 
+                poBlock->pabyData
+                + (nOffset + nAmountCopied) - nStartOffset,
                 nThisCopy );
 
         nAmountCopied += nThisCopy;
     }
-    
+
     nOffset += nAmountCopied;
 
 /* -------------------------------------------------------------------- */
@@ -478,9 +477,9 @@ size_t VSICachedFile::Read( void * pBuffer, size_t nSize, size_t nCount )
 /*                               Write()                                */
 /************************************************************************/
 
-size_t VSICachedFile::Write( CPL_UNUSED const void * pBuffer,
-                             CPL_UNUSED size_t nSize,
-                             CPL_UNUSED size_t nCount )
+size_t VSICachedFile::Write( const void * /* pBuffer */,
+                             size_t /*nSize */ ,
+                             size_t /* nCount */ )
 {
     return 0;
 }
diff --git a/port/cpl_vsil_crypt.cpp b/port/cpl_vsil_crypt.cpp
new file mode 100644
index 0000000..926e4fd
--- /dev/null
+++ b/port/cpl_vsil_crypt.cpp
@@ -0,0 +1,1934 @@
+/**********************************************************************
+ * $Id: cpl_vsil_crypt.cpp 33758 2016-03-21 09:06:22Z rouault $
+ *
+ * Project:  CPL - Common Portability Library
+ * Purpose:  Implement VSI large file api for encrypted files.
+ * Author:   Even Rouault, even.rouault at spatialys.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifdef DEBUG_BOOL
+#undef DEBUG_BOOL
+#endif
+
+#include "cpl_vsi_virtual.h"
+
+CPL_C_START
+void CPL_DLL VSIInstallCryptFileHandler(void);
+void CPL_DLL VSISetCryptKey(const GByte* pabyKey, int nKeySize);
+CPL_C_END
+
+CPL_CVSID("$Id: cpl_vsil_crypt.cpp 33758 2016-03-21 09:06:22Z rouault $");
+
+static const char VSICRYPT_PREFIX[] = "/vsicrypt/";
+
+#if defined(HAVE_CRYPTOPP) || defined(DOXYGEN_SKIP)
+
+/* Increase Major in case of backward incompatible changes */
+static const int VSICRYPT_CURRENT_MAJOR = 1;
+static const int VSICRYPT_CURRENT_MINOR = 0;
+static const char VSICRYPT_SIGNATURE[] = "VSICRYPT";  // Must be 8 chars.
+
+static const char VSICRYPT_PREFIX_WITHOUT_SLASH[] = "/vsicrypt";
+
+static const unsigned int VSICRYPT_READ = 0x1;
+static const unsigned int VSICRYPT_WRITE = 0x2;
+
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable : 4505 )
+#endif
+
+/* Begin of crypto++ headers */
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable : 4189 )
+#pragma warning( disable : 4512 )
+#pragma warning( disable : 4244 )
+#endif
+
+#ifdef USE_ONLY_CRYPTODLL_ALG
+#include "cryptopp/dll.h"
+#else
+#include "cryptopp/aes.h"
+#include "cryptopp/blowfish.h"
+#include "cryptopp/camellia.h"
+#include "cryptopp/cast.h"
+#include "cryptopp/des.h"
+#include "cryptopp/mars.h"
+#include "cryptopp/idea.h"
+#include "cryptopp/rc5.h"
+#include "cryptopp/rc6.h"
+#include "cryptopp/serpent.h"
+#include "cryptopp/shacal2.h"
+#include "cryptopp/skipjack.h"
+#include "cryptopp/tea.h"
+#include "cryptopp/twofish.h"
+#endif
+
+#include "cryptopp/filters.h"
+#include "cryptopp/modes.h"
+#include "cryptopp/osrng.h"
+
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
+/* End of crypto++ headers */
+
+// I don't really understand why this is necessary, especially
+// when cryptopp.dll and GDAL have been compiled with the same
+// VC version and /MD. But otherwise you'll get crashes
+// Borrowed from dlltest.cpp of crypto++
+#if defined(WIN32) && defined(USE_ONLY_CRYPTODLL_ALG)
+
+static CryptoPP::PNew s_pNew = NULL;
+static CryptoPP::PDelete s_pDelete = NULL;
+
+extern "C" __declspec(dllexport)
+void __cdecl SetNewAndDeleteFromCryptoPP(CryptoPP::PNew pNew,
+                                         CryptoPP::PDelete pDelete,
+                                         CryptoPP::PSetNewHandler pSetNewHandler)
+{
+	s_pNew = pNew;
+	s_pDelete = pDelete;
+}
+
+void * __cdecl operator new (size_t size)
+{
+	return s_pNew(size);
+}
+
+void __cdecl operator delete (void * p)
+{
+	s_pDelete(p);
+}
+
+#endif //  defined(WIN32) && defined(USE_ONLY_CRYPTODLL_ALG)
+
+static GByte* pabyGlobalKey = NULL;
+static int nGlobalKeySize = 0;
+
+typedef enum
+{
+    ALG_AES,
+    ALG_Blowfish,
+    ALG_Camellia,
+    //ALG_CAST128, (obsolete)
+    ALG_CAST256,
+    //ALG_DES, (obsolete)
+    ALG_DES_EDE2,
+    ALG_DES_EDE3,
+    //ALG_DES_XEX3, (obsolete)
+    //ALG_Gost, (obsolete)
+    ALG_MARS,
+    ALG_IDEA,
+    //ALG_RC2, (obsolete)
+    ALG_RC5,
+    ALG_RC6,
+    //ALG_SAFER_K, (obsolete)
+    //ALG_SAFER_SK, (obsolete)
+    ALG_Serpent,
+    ALG_SHACAL2,
+    //ALG_SHARK, (obsolete)
+    ALG_SKIPJACK,
+    ALG_Twofish,
+    //ALG_ThreeWay, (obsolete)
+    ALG_XTEA,
+    ALG_MAX = ALG_XTEA
+} VSICryptAlg;
+
+typedef enum
+{
+    MODE_CBC,
+    MODE_CFB,
+    MODE_OFB,
+    MODE_CTR,
+    MODE_CBC_CTS,
+    MODE_MAX = MODE_CBC_CTS
+} VSICryptMode;
+
+/************************************************************************/
+/*                          VSISetCryptKey()                            */
+/************************************************************************/
+
+/** Installs the encryption/decryption key.
+ *
+ * By passing a NULL key, the previously installed key will be cleared.
+ * Note, however, that it is not guaranteed that there won't be trace of it
+ * in other places in memory or in on-disk temporary file.
+ *
+ * @param pabyKey key. Might be NULL to clear previously set key.
+ * @param nKeySize length of the key in bytes. Might be 0 to clear previously set key.
+ *
+ * @see VSIInstallCryptFileHandler() for documentation on /vsicrypt/
+ */
+void VSISetCryptKey(const GByte* pabyKey, int nKeySize)
+{
+    CPLAssert( (pabyKey != NULL && nKeySize != 0) ||
+               (pabyKey == NULL && nKeySize == 0) );
+    if( pabyGlobalKey )
+    {
+        // Make some effort to clear the memory, although it could have leaked
+        // elsewhere...
+        memset( pabyGlobalKey, 0, nGlobalKeySize );
+        CPLFree(pabyGlobalKey);
+        pabyGlobalKey = NULL;
+        nGlobalKeySize = 0;
+    }
+    if( pabyKey )
+    {
+        pabyGlobalKey = (GByte*) CPLMalloc(nKeySize);
+        memcpy(pabyGlobalKey, pabyKey, nKeySize);
+        nGlobalKeySize = nKeySize;
+    }
+}
+
+/************************************************************************/
+/*                             GetAlg()                                 */
+/************************************************************************/
+
+#undef CASE_ALG
+#define CASE_ALG(alg)   if( EQUAL(pszName, #alg) ) return ALG_##alg;
+
+static VSICryptAlg GetAlg(const char* pszName)
+{
+    CASE_ALG(AES)
+    CASE_ALG(Blowfish)
+    CASE_ALG(Camellia)
+    //CASE_ALG(CAST128) (obsolete)
+    CASE_ALG(CAST256)
+    //CASE_ALG(DES) (obsolete)
+    CASE_ALG(DES_EDE2)
+    CASE_ALG(DES_EDE3)
+    //CASE_ALG(DES_XEX3) (obsolete)
+    //CASE_ALG(Gost) (obsolete)
+    CASE_ALG(MARS)
+    CASE_ALG(IDEA)
+    //CASE_ALG(RC2) (obsolete)
+    CASE_ALG(RC5)
+    CASE_ALG(RC6)
+    //CASE_ALG(SAFER_K) (obsolete)
+    //CASE_ALG(SAFER_SK) (obsolete)
+    CASE_ALG(Serpent)
+    CASE_ALG(SHACAL2)
+    //CASE_ALG(SHARK) (obsolete)
+    CASE_ALG(SKIPJACK)
+    //CASE_ALG(ThreeWay) (obsolete)
+    CASE_ALG(Twofish)
+    CASE_ALG(XTEA)
+
+    CPLError(CE_Warning, CPLE_NotSupported,
+                "Unsupported cipher algorithm: %s. Using AES instead", pszName);
+    return ALG_AES;
+}
+
+/************************************************************************/
+/*                          GetEncBlockCipher()                         */
+/************************************************************************/
+
+#undef CASE_ALG
+#define CASE_ALG(alg)   case ALG_##alg: return new CryptoPP::alg::Encryption();
+
+static CryptoPP::BlockCipher* GetEncBlockCipher(VSICryptAlg eAlg)
+{
+    switch( eAlg )
+    {
+        CASE_ALG(AES)
+#ifndef USE_ONLY_CRYPTODLL_ALG
+        CASE_ALG(Blowfish)
+        CASE_ALG(Camellia)
+        //CASE_ALG(CAST128) (obsolete)
+        CASE_ALG(CAST256)
+#endif
+        //CASE_ALG(DES) (obsolete)
+        CASE_ALG(DES_EDE2)
+        CASE_ALG(DES_EDE3)
+        //CASE_ALG(DES_XEX3) (obsolete)
+#ifndef USE_ONLY_CRYPTODLL_ALG
+        //CASE_ALG(Gost) (obsolete)
+        CASE_ALG(MARS)
+        CASE_ALG(IDEA)
+        //CASE_ALG(RC2) (obsolete)
+        CASE_ALG(RC5)
+        CASE_ALG(RC6)
+        //CASE_ALG(SAFER_K) (obsolete)
+        //CASE_ALG(SAFER_SK) (obsolete)
+        CASE_ALG(Serpent)
+        CASE_ALG(SHACAL2)
+        //CASE_ALG(SHARK) (obsolete)
+#endif
+        CASE_ALG(SKIPJACK)
+#ifndef USE_ONLY_CRYPTODLL_ALG
+        //CASE_ALG(ThreeWay) (obsolete)
+        CASE_ALG(Twofish)
+        CASE_ALG(XTEA)
+#endif
+        default: return NULL;
+    }
+}
+
+/************************************************************************/
+/*                          GetDecBlockCipher()                         */
+/************************************************************************/
+
+#undef CASE_ALG
+#define CASE_ALG(alg)   case ALG_##alg: return new CryptoPP::alg::Decryption();
+
+static CryptoPP::BlockCipher* GetDecBlockCipher(VSICryptAlg eAlg)
+{
+    switch( eAlg )
+    {
+        CASE_ALG(AES)
+#ifndef USE_ONLY_CRYPTODLL_ALG
+        CASE_ALG(Blowfish)
+        CASE_ALG(Camellia)
+        //CASE_ALG(CAST128) (obsolete)
+        CASE_ALG(CAST256)
+#endif
+        //CASE_ALG(DES) (obsolete)
+        CASE_ALG(DES_EDE2)
+        CASE_ALG(DES_EDE3)
+        //CASE_ALG(DES_XEX3) (obsolete)
+#ifndef USE_ONLY_CRYPTODLL_ALG
+        //CASE_ALG(Gost) (obsolete)
+        CASE_ALG(MARS)
+        CASE_ALG(IDEA)
+        //CASE_ALG(RC2) (obsolete)
+        CASE_ALG(RC5)
+        CASE_ALG(RC6)
+        //CASE_ALG(SAFER_K) (obsolete)
+        //CASE_ALG(SAFER_SK) (obsolete)
+        CASE_ALG(Serpent)
+        CASE_ALG(SHACAL2)
+        //CASE_ALG(SHARK) (obsolete)
+#endif
+        CASE_ALG(SKIPJACK)
+#ifndef USE_ONLY_CRYPTODLL_ALG
+        //CASE_ALG(ThreeWay) (obsolete)
+        CASE_ALG(Twofish)
+        CASE_ALG(XTEA)
+#endif
+        default: return NULL;
+    }
+}
+
+/************************************************************************/
+/*                             GetMode()                                */
+/************************************************************************/
+
+static VSICryptMode GetMode(const char* pszName)
+{
+    if( EQUAL(pszName, "CBC") )
+        return MODE_CBC;
+    if( EQUAL(pszName, "CFB") )
+        return MODE_CFB;
+    if( EQUAL(pszName, "OFB") )
+        return MODE_OFB;
+    if( EQUAL(pszName, "CTR") )
+        return MODE_CTR;
+    if( EQUAL(pszName, "CBC_CTS") )
+        return MODE_CBC_CTS;
+
+    CPLError(CE_Warning, CPLE_NotSupported,
+                "Unsupported cipher block mode: %s. Using CBC instead", pszName);
+    return MODE_CBC;
+}
+
+/************************************************************************/
+/*                          VSICryptFileHeader                          */
+/************************************************************************/
+
+class VSICryptFileHeader
+{
+        std::string             CryptKeyCheck(CryptoPP::BlockCipher* poEncCipher);
+
+    public:
+        VSICryptFileHeader() : nHeaderSize(0),
+                               nMajorVersion(0),
+                               nMinorVersion(0),
+                               nSectorSize(512),
+                               eAlg(ALG_AES),
+                               eMode(MODE_CBC),
+                               bAddKeyCheck(FALSE),
+                               nPayloadFileSize(0)  {}
+
+        int ReadFromFile(VSIVirtualHandle* fp, const CPLString& osKey);
+        int WriteToFile(VSIVirtualHandle* fp, CryptoPP::BlockCipher* poEncCipher);
+
+        GUInt16 nHeaderSize;
+        GByte nMajorVersion;
+        GByte nMinorVersion;
+        GUInt16 nSectorSize;
+        VSICryptAlg eAlg;
+        VSICryptMode eMode;
+        CPLString osIV;
+        int bAddKeyCheck;
+        GUIntBig nPayloadFileSize;
+        CPLString osFreeText;
+        CPLString osExtraContent;
+};
+
+/************************************************************************/
+/*                         VSICryptReadError()                          */
+/************************************************************************/
+
+static bool VSICryptReadError()
+{
+    CPLError(CE_Failure, CPLE_FileIO, "Cannot read header");
+    return false;
+}
+
+/************************************************************************/
+/*                       VSICryptGenerateSectorIV()                     */
+/************************************************************************/
+
+static std::string VSICryptGenerateSectorIV(const std::string& osIV,
+                                            vsi_l_offset nOffset)
+{
+    std::string osSectorIV(osIV);
+    size_t nLength = MIN(sizeof(vsi_l_offset), osSectorIV.size());
+    for( size_t i=0; i < nLength; i++ )
+    {
+        osSectorIV[i] = (char)((osSectorIV[i] ^ nOffset) & 0xff);
+        nOffset >>= 8;
+    }
+    return osSectorIV;
+}
+
+/************************************************************************/
+/*                          CryptKeyCheck()                             */
+/************************************************************************/
+
+std::string VSICryptFileHeader::CryptKeyCheck(CryptoPP::BlockCipher* poEncCipher)
+{
+    std::string osKeyCheckRes;
+
+    CPLAssert( osIV.size() == poEncCipher->BlockSize() );
+    // Generate a unique IV with a sector offset of 0xFFFFFFFFFFFFFFFF
+    std::string osCheckIV(VSICryptGenerateSectorIV(osIV, ~((vsi_l_offset)0)));
+    CryptoPP::StringSink* poSink = new CryptoPP::StringSink(osKeyCheckRes);
+    CryptoPP::StreamTransformation* poMode = new CryptoPP::CBC_Mode_ExternalCipher::Encryption(*poEncCipher, (const byte*)osCheckIV.c_str() );
+    CryptoPP::StreamTransformationFilter* poEnc = new CryptoPP::StreamTransformationFilter(*poMode, poSink, CryptoPP::StreamTransformationFilter::NO_PADDING);
+    /* Not sure if it is add extra security, but pick up something that is unlikely to be a plain text (random number) */
+    poEnc->Put((const byte*)"\xDB\x31\xB9\x1B\xD3\x1C\xFA\x3E\x84\x06\xC1\x42\xC3\xEC\xCD\x9A\x02\x36\x22\x15\x58\x88\x74\x65\x00\x2F\x98\xBC\x69\x22\xE1\x63",
+               MIN(32, poEncCipher->BlockSize()));
+    poEnc->MessageEnd();
+    delete poEnc;
+    delete poMode;
+
+    return osKeyCheckRes;
+}
+
+/************************************************************************/
+/*                          ReadFromFile()                              */
+/************************************************************************/
+
+int VSICryptFileHeader::ReadFromFile(VSIVirtualHandle* fp, const CPLString& osKey)
+{
+    GByte abySignature[8];
+    fp->Seek(0, SEEK_SET);
+    CPL_STATIC_ASSERT(sizeof(VSICRYPT_SIGNATURE) == 8+1);
+    if( fp->Read(abySignature, 8, 1) == 0 ||
+        memcmp(abySignature, VSICRYPT_SIGNATURE, 8) != 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Invalid signature");
+        return FALSE;
+    }
+
+    if( fp->Read(&nHeaderSize, 2, 1) == 0 )
+        return VSICryptReadError();
+    nHeaderSize = CPL_LSBWORD16(nHeaderSize);
+    if( nHeaderSize < 8 + 2 + 1 + 1 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Invalid header size : %d", nHeaderSize);
+        return FALSE;
+    }
+
+    if( fp->Read(&nMajorVersion, 1, 1) == 0 )
+        return VSICryptReadError();
+    if( fp->Read(&nMinorVersion, 1, 1) == 0 )
+        return VSICryptReadError();
+
+    if( nMajorVersion != VSICRYPT_CURRENT_MAJOR )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unhandled major version : %d", nMajorVersion);
+        return FALSE;
+    }
+    if( nMinorVersion != VSICRYPT_CURRENT_MINOR )
+    {
+        CPLDebug("VSICRYPT", "Minor version in file is %d", nMinorVersion);
+    }
+
+    if( fp->Read(&nSectorSize, 2, 1) == 0 )
+        return VSICryptReadError();
+    nSectorSize = CPL_LSBWORD16(nSectorSize);
+
+    GByte nAlg, nMode;
+    if( fp->Read(&nAlg, 1, 1) == 0 ||
+        fp->Read(&nMode, 1, 1) == 0 )
+        return VSICryptReadError();
+    if( nAlg > ALG_MAX )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Unsupported cipher algorithm %d",
+                 nAlg);
+        return FALSE;
+    }
+    if( nMode > MODE_MAX )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Unsupported cipher block mode %d",
+                 nMode);
+        return FALSE;
+    }
+    eAlg = (VSICryptAlg)nAlg;
+    eMode = (VSICryptMode)nMode;
+
+    GByte nIVSize;
+    if( fp->Read(&nIVSize, 1, 1) == 0 )
+        return VSICryptReadError();
+
+    osIV.resize(nIVSize);
+    if( fp->Read((void*)osIV.c_str(), 1, nIVSize) != nIVSize )
+        return VSICryptReadError();
+
+    GUInt16 nFreeTextSize;
+    if( fp->Read(&nFreeTextSize, 2, 1) == 0 )
+        return VSICryptReadError();
+
+    osFreeText.resize(nFreeTextSize);
+    if( fp->Read((void*)osFreeText.c_str(), 1, nFreeTextSize) != nFreeTextSize )
+        return VSICryptReadError();
+
+    GByte nKeyCheckSize;
+    if( fp->Read(&nKeyCheckSize, 1, 1) == 0 )
+        return VSICryptReadError();
+    bAddKeyCheck = (nKeyCheckSize != 0);
+    if( nKeyCheckSize )
+    {
+        CPLString osKeyCheck;
+        osKeyCheck.resize(nKeyCheckSize);
+        if( fp->Read((void*)osKeyCheck.c_str(), 1, nKeyCheckSize) != nKeyCheckSize )
+            return VSICryptReadError();
+
+        if( osKey.size() == 0 && pabyGlobalKey == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                    "Encryption key not defined as key/key_b64 parameter, "
+                    "VSICRYPT_KEY/VSICRYPT_KEY_B64 configuration option or VSISetCryptKey() API");
+            return FALSE;
+        }
+
+        CryptoPP::BlockCipher* poEncCipher = GetEncBlockCipher(eAlg);
+        if( poEncCipher == NULL )
+            return FALSE;
+
+        if( osIV.size() != poEncCipher->BlockSize() )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Inconsistent initial vector" );
+            delete poEncCipher;
+            return FALSE;
+        }
+
+        int nMaxKeySize = static_cast<int>(poEncCipher->MaxKeyLength());
+
+        try
+        {
+            if( osKey.size() )
+            {
+                int nKeySize = MIN(nMaxKeySize, (int)osKey.size());
+                poEncCipher->SetKey((const byte*)osKey.c_str(), nKeySize);
+            }
+            else if( pabyGlobalKey )
+            {
+                int nKeySize = MIN(nMaxKeySize, nGlobalKeySize);
+                poEncCipher->SetKey(pabyGlobalKey, nKeySize);
+            }
+        }
+        catch( const std::exception& e )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                    "CryptoPP exception: %s", e.what());
+            return FALSE;
+        }
+
+        std::string osKeyCheckRes = CryptKeyCheck(poEncCipher);
+
+        delete poEncCipher;
+
+        if( osKeyCheck.size() != osKeyCheckRes.size() ||
+            memcmp(osKeyCheck.c_str(), osKeyCheckRes.c_str(), osKeyCheck.size()) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Bad key");
+            return FALSE;
+        }
+    }
+
+    if( fp->Read(&nPayloadFileSize, 8, 1) == 0 )
+        return VSICryptReadError();
+    CPL_LSBPTR64(&nPayloadFileSize);
+#ifdef VERBOSE_VSICRYPT
+    CPLDebug("VSICRYPT", "nPayloadFileSize read = " CPL_FRMT_GUIB,
+             nPayloadFileSize);
+#endif
+
+    GUInt16 nExtraContentSize;
+    if( fp->Read(&nExtraContentSize, 2, 1) == 0 )
+        return VSICryptReadError();
+    nExtraContentSize = CPL_LSBWORD16(nExtraContentSize);
+
+    osExtraContent.resize(nExtraContentSize);
+    if( fp->Read((void*)osExtraContent.c_str(), 1, nExtraContentSize) != nExtraContentSize )
+        return VSICryptReadError();
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                          WriteToFile()                               */
+/************************************************************************/
+
+int VSICryptFileHeader::WriteToFile(VSIVirtualHandle* fp, CryptoPP::BlockCipher* poEncCipher)
+{
+    int bRet = TRUE;
+
+    fp->Seek(0, SEEK_SET);
+
+    bRet &= (fp->Write(VSICRYPT_SIGNATURE, 8, 1) == 1);
+
+    std::string osKeyCheckRes;
+    if( bAddKeyCheck )
+    {
+        osKeyCheckRes = CryptKeyCheck(poEncCipher);
+    }
+
+    GUInt16 nHeaderSizeNew = static_cast<GUInt16>(8 + /* signature */
+                            2 + /* header size */
+                            1 + /* major version */
+                            1 + /* minor version */
+                            2 + /* sector size */
+                            1 + /* alg */
+                            1 + /* mode */
+                            1 + osIV.size() + /* IV */
+                            2 + osFreeText.size() + /* free text */
+                            1 + osKeyCheckRes.size() + /* key check */
+                            8 + /* payload size */
+                            2 + osExtraContent.size()); /* extra content */
+    if( nHeaderSize != 0 )
+        CPLAssert( nHeaderSizeNew == nHeaderSize );
+    else
+        nHeaderSize = nHeaderSizeNew;
+
+    GUInt16 nHeaderSizeToWrite = CPL_LSBWORD16(nHeaderSizeNew);
+    bRet &= (fp->Write(&nHeaderSizeToWrite, 2, 1) == 1);
+
+    GByte nMajorVersionToWrite = VSICRYPT_CURRENT_MAJOR;
+    bRet &= (fp->Write(&nMajorVersionToWrite, 1, 1) == 1);
+
+    GByte nMinorVersionToWrite = VSICRYPT_CURRENT_MINOR;
+    bRet &= (fp->Write(&nMinorVersionToWrite, 1, 1) == 1);
+
+    GUInt16 nSectorSizeToWrite = CPL_LSBWORD16(nSectorSize);
+    bRet &= (fp->Write(&nSectorSizeToWrite, 2, 1) == 1);
+
+    GByte nAlg = (GByte)eAlg;
+    bRet &= (fp->Write(&nAlg, 1, 1) == 1);
+
+    GByte nMode = (GByte)eMode;
+    bRet &= (fp->Write(&nMode, 1, 1) == 1);
+
+    GByte nIVSizeToWrite = (GByte)osIV.size();
+    CPLAssert(nIVSizeToWrite == osIV.size());
+    bRet &= (fp->Write(&nIVSizeToWrite, 1, 1) == 1);
+    bRet &= (fp->Write(osIV.c_str(), 1, osIV.size()) == osIV.size());
+
+    GUInt16 nFreeTextSizeToWrite = CPL_LSBWORD16((GUInt16)osFreeText.size());
+    bRet &= (fp->Write(&nFreeTextSizeToWrite, 2, 1) == 1);
+    bRet &= (fp->Write(osFreeText.c_str(), 1, osFreeText.size()) == osFreeText.size());
+
+    GByte nSize = (GByte)osKeyCheckRes.size();
+    bRet &= (fp->Write(&nSize, 1, 1) == 1);
+    bRet &= (fp->Write(osKeyCheckRes.c_str(), 1, osKeyCheckRes.size()) == osKeyCheckRes.size());
+
+    GUIntBig nPayloadFileSizeToWrite = nPayloadFileSize;
+    CPL_LSBPTR64(&nPayloadFileSizeToWrite);
+    bRet &= (fp->Write(&nPayloadFileSizeToWrite, 8, 1) == 1);
+
+    GUInt16 nExtraContentSizeToWrite = CPL_LSBWORD16((GUInt16)osExtraContent.size());
+    bRet &= (fp->Write(&nExtraContentSizeToWrite, 2, 1) == 1);
+    bRet &= (fp->Write(osExtraContent.c_str(), 1, osExtraContent.size()) == osExtraContent.size());
+
+    CPLAssert( fp->Tell() == nHeaderSize) ;
+
+    return bRet;
+}
+
+/************************************************************************/
+/*                          VSICryptFileHandle                          */
+/************************************************************************/
+
+class VSICryptFileHandle CPL_FINAL : public VSIVirtualHandle
+{
+  private:
+        CPLString           osBaseFilename;
+        int                 nPerms;
+        VSIVirtualHandle   *poBaseHandle;
+        VSICryptFileHeader *poHeader;
+        int                 bUpdateHeader;
+        vsi_l_offset        nCurPos;
+        int                 bEOF;
+
+        CryptoPP::BlockCipher* poEncCipher;
+        CryptoPP::BlockCipher* poDecCipher;
+        int                 nBlockSize;
+
+        vsi_l_offset        nWBOffset;
+        GByte*              pabyWB;
+        int                 nWBSize;
+        int                 bWBDirty;
+
+        int                 bLastSectorWasModified;
+
+        void                 EncryptBlock(GByte* pabyData, vsi_l_offset nOffset);
+        int                  DecryptBlock(GByte* pabyData, vsi_l_offset nOffset);
+        int                  FlushDirty();
+
+  public:
+
+    VSICryptFileHandle(CPLString osBaseFilename,
+                       VSIVirtualHandle* poBaseHandle,
+                       VSICryptFileHeader* poHeader,
+                       int nPerms);
+    ~VSICryptFileHandle();
+
+    int                  Init(const CPLString& osKey, int bWriteHeader = FALSE);
+
+    virtual int          Seek( vsi_l_offset nOffset, int nWhence );
+    virtual vsi_l_offset Tell();
+    virtual size_t       Read( void *pBuffer, size_t nSize, size_t nMemb );
+    virtual size_t       Write( const void *pBuffer, size_t nSize, size_t nMemb );
+    virtual int          Eof();
+    virtual int          Flush();
+    virtual int          Close();
+    virtual int          Truncate( vsi_l_offset nNewSize );
+};
+
+/************************************************************************/
+/*                          VSICryptFileHandle()                        */
+/************************************************************************/
+
+VSICryptFileHandle::VSICryptFileHandle(CPLString osBaseFilenameIn,
+                                       VSIVirtualHandle* poBaseHandleIn,
+                                       VSICryptFileHeader* poHeaderIn,
+                                       int nPermsIn) :
+        osBaseFilename(osBaseFilenameIn), nPerms(nPermsIn),
+        poBaseHandle(poBaseHandleIn), poHeader(poHeaderIn), bUpdateHeader(FALSE),
+        nCurPos(0), bEOF(FALSE), poEncCipher(NULL), poDecCipher(NULL), nBlockSize(0),
+        nWBOffset(0), pabyWB(NULL), nWBSize(0), bWBDirty(FALSE), bLastSectorWasModified(FALSE)
+{
+
+}
+
+/************************************************************************/
+/*                         ~VSICryptFileHandle()                        */
+/************************************************************************/
+
+VSICryptFileHandle::~VSICryptFileHandle()
+{
+    Close();
+    delete poHeader;
+    delete poEncCipher;
+    delete poDecCipher;
+    CPLFree(pabyWB);
+}
+
+/************************************************************************/
+/*                               Init()                                 */
+/************************************************************************/
+
+int VSICryptFileHandle::Init(const CPLString& osKey, int bWriteHeader)
+{
+    poEncCipher = GetEncBlockCipher(poHeader->eAlg);
+    if( poEncCipher == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                    "Cipher algorithm not supported in this build: %d",
+                    (int)poHeader->eAlg);
+        return FALSE;
+    }
+
+    if( poHeader->osIV.size() != poEncCipher->BlockSize() )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Inconsistent initial vector" );
+        return FALSE;
+    }
+
+    poDecCipher = GetDecBlockCipher(poHeader->eAlg);
+    nBlockSize = poEncCipher->BlockSize();
+    int nMaxKeySize = static_cast<int>(poEncCipher->MaxKeyLength());
+
+    try
+    {
+        if( osKey.size() )
+        {
+            int nKeySize = MIN(nMaxKeySize, (int)osKey.size());
+            poEncCipher->SetKey((const byte*)osKey.c_str(), nKeySize);
+            poDecCipher->SetKey((const byte*)osKey.c_str(), nKeySize);
+        }
+        else if( pabyGlobalKey )
+        {
+            int nKeySize = MIN(nMaxKeySize, nGlobalKeySize);
+            poEncCipher->SetKey(pabyGlobalKey, nKeySize);
+            poDecCipher->SetKey(pabyGlobalKey, nKeySize);
+        }
+        else
+            return FALSE;
+    }
+    catch( const std::exception& e )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                "CryptoPP exception: %s", e.what());
+        return FALSE;
+    }
+
+    pabyWB = (GByte*)CPLCalloc(1, poHeader->nSectorSize);
+
+    if( (poHeader->nSectorSize % nBlockSize) != 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Sector size (%d) is not a multiple of block size (%d)",
+                 poHeader->nSectorSize, nBlockSize);
+        return FALSE;
+    }
+    if( poHeader->eMode == MODE_CBC_CTS && poHeader->nSectorSize < 2 * nBlockSize )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Sector size (%d) should be at least twice larger than the block size (%d) in CBC_CTS.",
+                 poHeader->nSectorSize, nBlockSize);
+        return FALSE;
+    }
+
+    if( bWriteHeader && !poHeader->WriteToFile(poBaseHandle, poEncCipher) )
+    {
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                          EncryptBlock()                              */
+/************************************************************************/
+
+void VSICryptFileHandle::EncryptBlock(GByte* pabyData, vsi_l_offset nOffset)
+{
+    std::string osRes;
+    std::string osIV(VSICryptGenerateSectorIV(poHeader->osIV, nOffset));
+    CPLAssert( (int)osIV.size() == nBlockSize );
+
+    CryptoPP::StringSink* poSink = new CryptoPP::StringSink(osRes);
+    CryptoPP::StreamTransformation* poMode;
+    if( poHeader->eMode == MODE_CBC )
+        poMode = new CryptoPP::CBC_Mode_ExternalCipher::Encryption(*poEncCipher, (const byte*)osIV.c_str() );
+    else if( poHeader->eMode == MODE_CFB )
+        poMode = new CryptoPP::CFB_Mode_ExternalCipher::Encryption(*poEncCipher, (const byte*)osIV.c_str() );
+    else if( poHeader->eMode == MODE_OFB )
+        poMode = new CryptoPP::OFB_Mode_ExternalCipher::Encryption(*poEncCipher, (const byte*)osIV.c_str() );
+    else if( poHeader->eMode == MODE_CTR )
+        poMode = new CryptoPP::CTR_Mode_ExternalCipher::Encryption(*poEncCipher, (const byte*)osIV.c_str() );
+    else
+        poMode = new CryptoPP::CBC_CTS_Mode_ExternalCipher::Encryption(*poEncCipher, (const byte*)osIV.c_str() );
+    CryptoPP::StreamTransformationFilter* poEnc = new CryptoPP::StreamTransformationFilter(*poMode, poSink, CryptoPP::StreamTransformationFilter::NO_PADDING);
+    poEnc->Put((const byte*)pabyData, poHeader->nSectorSize);
+    poEnc->MessageEnd();
+    delete poEnc;
+
+    delete poMode;
+
+    CPLAssert( (int)osRes.length() == poHeader->nSectorSize );
+    memcpy( pabyData, osRes.c_str(), osRes.length() );
+}
+
+/************************************************************************/
+/*                          DecryptBlock()                              */
+/************************************************************************/
+
+int VSICryptFileHandle::DecryptBlock(GByte* pabyData, vsi_l_offset nOffset)
+{
+    std::string osRes;
+    std::string osIV(VSICryptGenerateSectorIV(poHeader->osIV, nOffset));
+    CPLAssert( (int)osIV.size() == nBlockSize );
+    CryptoPP::StringSink* poSink = new CryptoPP::StringSink(osRes);
+    CryptoPP::StreamTransformation* poMode = NULL;
+    CryptoPP::StreamTransformationFilter* poDec = NULL;
+
+    try
+    {
+        /* Yes, some modes need the encryption cipher */
+        if( poHeader->eMode == MODE_CBC )
+            poMode = new CryptoPP::CBC_Mode_ExternalCipher::Decryption(*poDecCipher, (const byte*)osIV.c_str() );
+        else if( poHeader->eMode == MODE_CFB )
+            poMode = new CryptoPP::CFB_Mode_ExternalCipher::Decryption(*poEncCipher, (const byte*)osIV.c_str() );
+        else if( poHeader->eMode == MODE_OFB )
+            poMode = new CryptoPP::OFB_Mode_ExternalCipher::Decryption(*poEncCipher, (const byte*)osIV.c_str() );
+        else if( poHeader->eMode == MODE_CTR )
+            poMode = new CryptoPP::CTR_Mode_ExternalCipher::Decryption(*poEncCipher, (const byte*)osIV.c_str() );
+        else
+            poMode = new CryptoPP::CBC_CTS_Mode_ExternalCipher::Decryption(*poDecCipher, (const byte*)osIV.c_str() );
+        poDec = new CryptoPP::StreamTransformationFilter(*poMode, poSink, CryptoPP::StreamTransformationFilter::NO_PADDING);
+        poDec->Put((const byte*)pabyData, poHeader->nSectorSize);
+        poDec->MessageEnd();
+        delete poDec;
+        delete poMode;
+    }
+    catch( const std::exception& e )
+    {
+        delete poDec;
+        delete poMode;
+
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "CryptoPP exception: %s", e.what());
+        return FALSE;
+    }
+
+    CPLAssert( (int)osRes.length() == poHeader->nSectorSize );
+    memcpy( pabyData, osRes.c_str(), osRes.length() );
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                             FlushDirty()                             */
+/************************************************************************/
+
+int VSICryptFileHandle::FlushDirty()
+{
+    if( !bWBDirty )
+        return TRUE;
+    bWBDirty = FALSE;
+
+    EncryptBlock(pabyWB, nWBOffset);
+    poBaseHandle->Seek( poHeader->nHeaderSize + nWBOffset, SEEK_SET );
+
+    nWBOffset = 0;
+    nWBSize = 0;
+
+    if( poBaseHandle->Write( pabyWB, poHeader->nSectorSize, 1 ) != 1 )
+        return FALSE;
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                                Seek()                                */
+/************************************************************************/
+
+int VSICryptFileHandle::Seek( vsi_l_offset nOffset, int nWhence )
+{
+#ifdef VERBOSE_VSICRYPT
+    CPLDebug("VSICRYPT", "Seek(nOffset=" CPL_FRMT_GUIB ", nWhence=%d)", nOffset, nWhence);
+#endif
+
+    bEOF = FALSE;
+
+    if( nWhence == SEEK_SET )
+        nCurPos = nOffset;
+    else if( nWhence == SEEK_CUR )
+        nCurPos += nOffset;
+    else
+        nCurPos = poHeader->nPayloadFileSize;
+    return 0;
+}
+
+/************************************************************************/
+/*                                  Tell()                              */
+/************************************************************************/
+
+vsi_l_offset VSICryptFileHandle::Tell()
+{
+#ifdef VERBOSE_VSICRYPT
+    CPLDebug("VSICRYPT", "Tell()=" CPL_FRMT_GUIB, nCurPos);
+#endif
+    return nCurPos;
+}
+
+/************************************************************************/
+/*                                Read()                                */
+/************************************************************************/
+
+size_t VSICryptFileHandle::Read( void *pBuffer, size_t nSize, size_t nMemb )
+{
+    size_t nToRead = nSize * nMemb;
+    GByte* pabyBuffer = (GByte*)pBuffer;
+
+#ifdef VERBOSE_VSICRYPT
+    CPLDebug("VSICRYPT", "Read(nCurPos=" CPL_FRMT_GUIB ", nToRead=%d)", nCurPos, (int)nToRead);
+#endif
+
+    if( (nPerms & VSICRYPT_READ) == 0 )
+        return 0;
+
+    if( nCurPos >= poHeader->nPayloadFileSize )
+    {
+        bEOF = TRUE;
+        return 0;
+    }
+
+    if( !FlushDirty() )
+        return 0;
+
+    while(nToRead > 0)
+    {
+        if( nCurPos >= nWBOffset && nCurPos < nWBOffset + nWBSize )
+        {
+            int nToCopy = MIN(static_cast<int>(nToRead),
+                              static_cast<int>(nWBSize - (nCurPos - nWBOffset)));
+            if( nCurPos + nToCopy > poHeader->nPayloadFileSize )
+            {
+                bEOF = TRUE;
+                nToCopy = static_cast<int>(poHeader->nPayloadFileSize - nCurPos);
+            }
+            memcpy(pabyBuffer, pabyWB + nCurPos - nWBOffset, nToCopy);
+            pabyBuffer += nToCopy;
+            nToRead -= nToCopy;
+            nCurPos += nToCopy;
+            if( bEOF || nToRead == 0 )
+                break;
+            CPLAssert( (nCurPos % poHeader->nSectorSize) == 0 );
+        }
+
+        vsi_l_offset nSectorOffset = (nCurPos / poHeader->nSectorSize) * poHeader->nSectorSize;
+        poBaseHandle->Seek( poHeader->nHeaderSize + nSectorOffset, SEEK_SET );
+        if( poBaseHandle->Read( pabyWB, poHeader->nSectorSize, 1 ) != 1 )
+        {
+            bEOF = TRUE;
+            break;
+        }
+        if( !DecryptBlock( pabyWB, nSectorOffset) )
+        {
+            break;
+        }
+        if( (nPerms & VSICRYPT_WRITE) &&
+            nSectorOffset + poHeader->nSectorSize > poHeader->nPayloadFileSize )
+        {
+            // If the last sector was padded with random values, decrypt it to 0 in case of update scenarios
+            CPLAssert( nSectorOffset < poHeader->nPayloadFileSize );
+            memset( pabyWB + poHeader->nPayloadFileSize - nSectorOffset, 0,
+                    nSectorOffset + poHeader->nSectorSize - poHeader->nPayloadFileSize );
+        }
+        nWBOffset = nSectorOffset;
+        nWBSize = poHeader->nSectorSize;
+    }
+
+    int nRet = static_cast<int>( (nSize * nMemb - nToRead) / nSize );
+#ifdef VERBOSE_VSICRYPT
+    CPLDebug("VSICRYPT", "Read ret = %d (nMemb = %d)", nRet, (int)nMemb);
+#endif
+    return nRet;
+}
+
+/************************************************************************/
+/*                                Write()                               */
+/************************************************************************/
+
+size_t VSICryptFileHandle::Write( const void *pBuffer, size_t nSize, size_t nMemb )
+{
+    size_t nToWrite = nSize * nMemb;
+    const GByte* pabyBuffer = (const GByte*)pBuffer;
+
+#ifdef VERBOSE_VSICRYPT
+    CPLDebug("VSICRYPT", "Write(nCurPos=" CPL_FRMT_GUIB ", nToWrite=%d,"
+             "nPayloadFileSize=" CPL_FRMT_GUIB ",bWBDirty=%d,nWBOffset=" CPL_FRMT_GUIB ",nWBSize=%d)",
+             nCurPos, (int)nToWrite, poHeader->nPayloadFileSize, bWBDirty, nWBOffset, nWBSize);
+#endif
+
+    if( (nPerms & VSICRYPT_WRITE) == 0 )
+        return 0;
+
+    if( nCurPos >= (poHeader->nPayloadFileSize / poHeader->nSectorSize) * poHeader->nSectorSize )
+        bLastSectorWasModified = TRUE;
+
+    // If seeking past end of file, we need to explicitly encrypt the
+    // padding zeroes.
+    if( nCurPos > poHeader->nPayloadFileSize && nCurPos > nWBOffset + nWBSize )
+    {
+        if( !FlushDirty() )
+            return 0;
+        vsi_l_offset nOffset = (poHeader->nPayloadFileSize + poHeader->nSectorSize - 1) / poHeader->nSectorSize * poHeader->nSectorSize;
+        vsi_l_offset nEndOffset = nCurPos / poHeader->nSectorSize * poHeader->nSectorSize;
+        for( ; nOffset < nEndOffset; nOffset += poHeader->nSectorSize )
+        {
+            memset( pabyWB, 0, poHeader->nSectorSize );
+            EncryptBlock( pabyWB, nOffset );
+            poBaseHandle->Seek( poHeader->nHeaderSize + nOffset, SEEK_SET );
+            if( poBaseHandle->Write( pabyWB, poHeader->nSectorSize, 1 ) != 1 )
+                return 0;
+            poHeader->nPayloadFileSize = nOffset + poHeader->nSectorSize;
+            bUpdateHeader = TRUE;
+        }
+    }
+
+    while( nToWrite > 0 )
+    {
+        if( nCurPos >= nWBOffset && nCurPos < nWBOffset + nWBSize )
+        {
+            bWBDirty = TRUE;
+            int nToCopy = MIN(static_cast<int>(nToWrite),
+                              static_cast<int>(nWBSize - (nCurPos - nWBOffset)));
+            memcpy(pabyWB + nCurPos - nWBOffset, pabyBuffer, nToCopy);
+            pabyBuffer += nToCopy;
+            nToWrite -= nToCopy;
+            nCurPos += nToCopy;
+            if( nCurPos > poHeader->nPayloadFileSize )
+            {
+                bUpdateHeader = TRUE;
+                poHeader->nPayloadFileSize = nCurPos;
+            }
+            if( nToWrite == 0 )
+                break;
+            CPLAssert( (nCurPos % poHeader->nSectorSize) == 0 );
+        }
+        else if( (nCurPos % poHeader->nSectorSize) == 0 && nToWrite >= (size_t)poHeader->nSectorSize )
+        {
+            if( !FlushDirty() )
+                break;
+
+            bWBDirty = TRUE;
+            nWBOffset = nCurPos;
+            nWBSize = poHeader->nSectorSize;
+            memcpy( pabyWB, pabyBuffer, poHeader->nSectorSize );
+            pabyBuffer += poHeader->nSectorSize;
+            nToWrite -= poHeader->nSectorSize;
+            nCurPos += poHeader->nSectorSize;
+            if( nCurPos > poHeader->nPayloadFileSize )
+            {
+                bUpdateHeader = TRUE;
+                poHeader->nPayloadFileSize = nCurPos;
+            }
+        }
+        else
+        {
+            if( !FlushDirty() )
+                break;
+
+            vsi_l_offset nSectorOffset = (nCurPos / poHeader->nSectorSize) * poHeader->nSectorSize;
+            vsi_l_offset nLastSectorOffset = (poHeader->nPayloadFileSize / poHeader->nSectorSize) * poHeader->nSectorSize;
+            if( nSectorOffset > nLastSectorOffset &&
+                (poHeader->nPayloadFileSize % poHeader->nSectorSize) != 0 )
+            {
+                if( poBaseHandle->Seek( poHeader->nHeaderSize + nLastSectorOffset, 0) == 0 &&
+                    poBaseHandle->Read( pabyWB, poHeader->nSectorSize, 1 ) == 1 &&
+                    DecryptBlock( pabyWB, nLastSectorOffset) )
+                {
+                    // Fill with 0
+#ifdef VERBOSE_VSICRYPT
+                    CPLDebug("VSICRYPT", "Filling %d trailing bytes with 0",
+                            (int)(poHeader->nSectorSize - (poHeader->nPayloadFileSize - nLastSectorOffset )));
+#endif
+                    memset(
+                        (byte*)(pabyWB + poHeader->nPayloadFileSize - nLastSectorOffset),
+                        0,
+                        (int)(poHeader->nSectorSize - (poHeader->nPayloadFileSize - nLastSectorOffset )));
+
+                    if( poBaseHandle->Seek( poHeader->nHeaderSize + nLastSectorOffset, 0) == 0)
+                    {
+                        EncryptBlock( pabyWB, nLastSectorOffset);
+                        poBaseHandle->Write( pabyWB, poHeader->nSectorSize, 1 );
+                    }
+                }
+            }
+            poBaseHandle->Seek( poHeader->nHeaderSize + nSectorOffset, SEEK_SET );
+            if( poBaseHandle->Read( pabyWB, poHeader->nSectorSize, 1 ) == 0 ||
+                !DecryptBlock( pabyWB, nSectorOffset) )
+            {
+                memset( pabyWB, 0, poHeader->nSectorSize );
+            }
+            else if( nSectorOffset + poHeader->nSectorSize > poHeader->nPayloadFileSize )
+            {
+                // If the last sector was padded with random values, decrypt it to 0 in case of update scenarios
+                CPLAssert( nSectorOffset < poHeader->nPayloadFileSize );
+                memset( pabyWB + poHeader->nPayloadFileSize - nSectorOffset, 0,
+                        nSectorOffset + poHeader->nSectorSize - poHeader->nPayloadFileSize );
+            }
+            nWBOffset = nSectorOffset;
+            nWBSize = poHeader->nSectorSize;
+        }
+    }
+
+    int nRet = static_cast<int>( (nSize * nMemb - nToWrite) / nSize );
+#ifdef VERBOSE_VSICRYPT
+    CPLDebug("VSICRYPT", "Write ret = %d (nMemb = %d)", nRet, (int)nMemb);
+#endif
+    return nRet;
+}
+
+/************************************************************************/
+/*                             Truncate()                               */
+/************************************************************************/
+
+int VSICryptFileHandle::Truncate( vsi_l_offset nNewSize )
+{
+#ifdef VERBOSE_VSICRYPT
+    CPLDebug("VSICRYPT", "Truncate(" CPL_FRMT_GUIB ")", nNewSize);
+#endif
+    if( (nPerms & VSICRYPT_WRITE) == 0 )
+        return -1;
+
+    if( !FlushDirty() )
+        return -1;
+    if( poBaseHandle->Truncate( poHeader->nHeaderSize +
+            ((nNewSize + poHeader->nSectorSize - 1) / poHeader->nSectorSize) * poHeader->nSectorSize ) != 0 )
+        return -1;
+    bUpdateHeader = TRUE;
+    poHeader->nPayloadFileSize = nNewSize;
+    return 0;
+}
+
+/************************************************************************/
+/*                                Eof()                                 */
+/************************************************************************/
+
+int VSICryptFileHandle::Eof()
+{
+#ifdef VERBOSE_VSICRYPT
+    CPLDebug("VSICRYPT", "Eof() = %d", bEOF);
+#endif
+    return bEOF;
+}
+
+/************************************************************************/
+/*                                 Flush()                              */
+/************************************************************************/
+
+int VSICryptFileHandle::Flush()
+{
+#ifdef VERBOSE_VSICRYPT
+    CPLDebug("VSICRYPT", "Flush()");
+#endif
+    if( !FlushDirty() )
+    {
+        return -1;
+    }
+    if( (nPerms & VSICRYPT_WRITE) )
+    {
+        if( bLastSectorWasModified && (poHeader->nPayloadFileSize % poHeader->nSectorSize) != 0 )
+        {
+            vsi_l_offset nLastSectorOffset = (poHeader->nPayloadFileSize / poHeader->nSectorSize) * poHeader->nSectorSize;
+            if( poBaseHandle->Seek( poHeader->nHeaderSize + nLastSectorOffset, 0) == 0 &&
+                poBaseHandle->Read( pabyWB, poHeader->nSectorSize, 1 ) == 1 &&
+                DecryptBlock( pabyWB, nLastSectorOffset) )
+            {
+                // Fill with random
+#ifdef VERBOSE_VSICRYPT
+                CPLDebug("VSICRYPT", "Filling %d trailing bytes with random",
+                         (int)(poHeader->nSectorSize - (poHeader->nPayloadFileSize - nLastSectorOffset )));
+#endif
+                CryptoPP::OS_GenerateRandomBlock(false /* we do not need cryptographic randomness */,
+                    (byte*)(pabyWB + poHeader->nPayloadFileSize - nLastSectorOffset),
+                    (int)(poHeader->nSectorSize - (poHeader->nPayloadFileSize - nLastSectorOffset )));
+
+                if( poBaseHandle->Seek( poHeader->nHeaderSize + nLastSectorOffset, 0) == 0)
+                {
+                    EncryptBlock( pabyWB, nLastSectorOffset);
+                    poBaseHandle->Write( pabyWB, poHeader->nSectorSize, 1 );
+                }
+            }
+        }
+        bLastSectorWasModified = FALSE;
+        if( poBaseHandle->Flush() != 0 )
+            return -1;
+    }
+    if( bUpdateHeader )
+    {
+#ifdef VERBOSE_VSICRYPT
+        CPLDebug("VSICRYPT", "nPayloadFileSize = " CPL_FRMT_GUIB,
+                 poHeader->nPayloadFileSize);
+#endif
+        if( !poHeader->WriteToFile(poBaseHandle, poEncCipher) )
+            return -1;
+    }
+
+    return 0;
+}
+
+/************************************************************************/
+/*                                  Close()                             */
+/************************************************************************/
+
+int VSICryptFileHandle::Close()
+{
+    int nRet = 0;
+    if( poBaseHandle != NULL && poHeader != NULL )
+    {
+        if( Flush() != 0 )
+            return -1;
+        nRet = poBaseHandle->Close();
+        delete poBaseHandle;
+        poBaseHandle = NULL;
+    }
+#ifdef VERBOSE_VSICRYPT
+    CPLDebug("VSICRYPT", "Close(%s)", osBaseFilename.c_str());
+#endif
+    return nRet;
+}
+
+/************************************************************************/
+/*                   VSICryptFilesystemHandler                          */
+/************************************************************************/
+
+class VSICryptFilesystemHandler CPL_FINAL : public VSIFilesystemHandler
+{
+public:
+    VSICryptFilesystemHandler();
+    ~VSICryptFilesystemHandler();
+
+    using VSIFilesystemHandler::Open;
+
+    virtual VSIVirtualHandle *Open( const char *pszFilename,
+                                    const char *pszAccess,
+                                    bool bSetError );
+    virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags );
+    virtual int      Unlink( const char *pszFilename );
+    virtual int      Rename( const char *oldpath, const char *newpath );
+    virtual char**   ReadDirEx( const char *pszDirname, int nMaxFiles );
+};
+
+/************************************************************************/
+/*                   VSICryptFilesystemHandler()                        */
+/************************************************************************/
+
+VSICryptFilesystemHandler::VSICryptFilesystemHandler()
+{
+}
+
+/************************************************************************/
+/*                    ~VSICryptFilesystemHandler()                      */
+/************************************************************************/
+
+VSICryptFilesystemHandler::~VSICryptFilesystemHandler()
+{
+}
+
+/************************************************************************/
+/*                             GetFilename()                            */
+/************************************************************************/
+
+static CPLString GetFilename(const char* pszFilename)
+{
+    if( strcmp(pszFilename, VSICRYPT_PREFIX_WITHOUT_SLASH) == 0 )
+        pszFilename = VSICRYPT_PREFIX;
+
+    CPLAssert( strncmp(pszFilename, VSICRYPT_PREFIX, strlen(VSICRYPT_PREFIX)) == 0 );
+    pszFilename += strlen(VSICRYPT_PREFIX);
+    const char* pszFileArg = strstr(pszFilename, "file=");
+    if( pszFileArg == NULL )
+        return pszFilename;
+    CPLString osRet(pszFileArg + strlen("file="));
+    return osRet;
+}
+
+/************************************************************************/
+/*                             GetArgument()                            */
+/************************************************************************/
+
+static CPLString GetArgument(const char* pszFilename, const char* pszParamName,
+                             const char* pszDefault = "")
+{
+    CPLString osParamName(pszParamName);
+    osParamName += "=";
+
+    const char* pszNeedle = strstr(pszFilename, osParamName);
+    if( pszNeedle == NULL )
+        return pszDefault;
+
+    CPLString osRet(pszNeedle + osParamName.size());
+    size_t nCommaPos = osRet.find(",");
+    if( nCommaPos != std::string::npos )
+        osRet.resize(nCommaPos);
+    return osRet;
+}
+
+/************************************************************************/
+/*                               GetKey()                               */
+/************************************************************************/
+
+static CPLString GetKey(const char* pszFilename)
+{
+    CPLString osKey = GetArgument(pszFilename, "key");
+    if( osKey.size() == 0 )
+        osKey = CPLGetConfigOption("VSICRYPT_KEY", "");
+    if( osKey.size() == 0 || EQUAL(osKey, "GENERATE_IT") )
+    {
+        CPLString osKeyB64(GetArgument(pszFilename, "key_b64"));
+        if( osKeyB64.size() == 0 )
+            osKeyB64 = CPLGetConfigOption("VSICRYPT_KEY_B64", "");
+        if( osKeyB64.size() )
+        {
+            GByte* key = (GByte*)CPLStrdup(osKeyB64);
+            int nLength = CPLBase64DecodeInPlace(key);
+            osKey.assign((const char*)key, nLength);
+            memset(key, 0, osKeyB64.size());
+            CPLFree(key);
+        }
+        memset((void*)osKeyB64.c_str(), 0, osKeyB64.size());
+    }
+    return osKey;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+VSIVirtualHandle *VSICryptFilesystemHandler::Open( const char *pszFilename,
+                                                   const char *pszAccess,
+                                                   bool /* bSetError */ )
+{
+#ifdef VERBOSE_VSICRYPT
+    CPLDebug("VSICRYPT", "Open(%s, %s)", pszFilename, pszAccess);
+#endif
+    CPLString osFilename(GetFilename(pszFilename));
+
+    CPLString osKey(GetKey(pszFilename));
+    if( osKey.size() == 0 && pabyGlobalKey == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                "Encryption key not defined as key/key_b64 parameter, "
+                "VSICRYPT_KEY/VSICRYPT_KEY_B64 configuration option or VSISetCryptKey() API");
+        return NULL;
+    }
+
+    if( strchr(pszAccess, 'r') )
+    {
+        CPLString osAccess(pszAccess);
+        if( strchr(pszAccess, 'b') == NULL )
+            osAccess += "b";
+        VSIVirtualHandle* fpBase = (VSIVirtualHandle*)VSIFOpenL(osFilename, osAccess);
+        if( fpBase == NULL )
+            return NULL;
+        VSICryptFileHeader* poHeader = new VSICryptFileHeader();
+        if( !poHeader->ReadFromFile(fpBase, osKey) )
+        {
+            memset((void*)osKey.c_str(), 0, osKey.size());
+            fpBase->Close();
+            delete fpBase;
+            delete poHeader;
+            return NULL;
+        }
+
+        VSICryptFileHandle* poHandle = new VSICryptFileHandle( osFilename, fpBase, poHeader,
+                    strchr(pszAccess, '+') ? VSICRYPT_READ | VSICRYPT_WRITE : VSICRYPT_READ);
+        if( !poHandle->Init(osKey, FALSE) )
+        {
+            memset((void*)osKey.c_str(), 0, osKey.size());
+            delete poHandle;
+            poHandle = NULL;
+        }
+        memset((void*)osKey.c_str(), 0, osKey.size());
+        return poHandle;
+    }
+    else if( strchr(pszAccess, 'w' ) )
+    {
+        CPLString osAlg(GetArgument(pszFilename, "alg",
+                                              CPLGetConfigOption("VSICRYPT_ALG", "AES")));
+        VSICryptAlg eAlg = GetAlg(osAlg);
+
+        VSICryptMode eMode = GetMode(GetArgument(pszFilename, "mode",
+                                              CPLGetConfigOption("VSICRYPT_MODE", "CBC")));
+
+        CPLString osFreeText = GetArgument(pszFilename, "freetext",
+                                           CPLGetConfigOption("VSICRYPT_FREETEXT", ""));
+
+        CPLString osIV = GetArgument(pszFilename, "iv",
+                                           CPLGetConfigOption("VSICRYPT_IV", ""));
+
+        int nSectorSize = atoi(GetArgument(pszFilename, "sector_size",
+                                           CPLGetConfigOption("VSICRYPT_SECTOR_SIZE", "512")));
+        if( nSectorSize <= 0 || nSectorSize >= 65535 )
+        {
+            CPLError(CE_Warning, CPLE_NotSupported, "Invalid value for sector_size. Defaulting to 512.");
+            nSectorSize = 512;
+        }
+
+        int bAddKeyCheck = CSLTestBoolean(GetArgument(pszFilename, "add_key_check",
+                                           CPLGetConfigOption("VSICRYPT_ADD_KEY_CHECK", "NO")));
+
+        /* Generate random initial vector */
+        CryptoPP::BlockCipher* poBlock = GetEncBlockCipher(eAlg);
+        if( poBlock == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Cipher algorithm not supported in this build: %s",
+                     osAlg.c_str());
+            memset((void*)osKey.c_str(), 0, osKey.size());
+            return NULL;
+        }
+        int nMinKeySize = static_cast<int>(poBlock->MinKeyLength());
+        int nMaxKeySize = static_cast<int>(poBlock->MaxKeyLength());
+        int nBlockSize = static_cast<int>(poBlock->BlockSize());
+        delete poBlock;
+
+        if( osIV.size() != 0 )
+        {
+            if( (int)osIV.size() != nBlockSize )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "IV should be %d byte large",
+                         nBlockSize);
+                memset((void*)osKey.c_str(), 0, osKey.size());
+                return NULL;
+            }
+        }
+        else
+        {
+            osIV.resize(nBlockSize);
+            CryptoPP::OS_GenerateRandomBlock(false /* we do not need cryptographic randomness */,
+                                            (byte*)osIV.c_str(), osIV.size());
+        }
+
+        if( EQUAL(osKey, "GENERATE_IT") )
+        {
+            osKey.resize(nMaxKeySize);
+            CPLDebug("VSICRYPT", "Generating key. This might take some time...");
+            CryptoPP::OS_GenerateRandomBlock(
+                /* we need cryptographic randomness (config option for speeding tests) */
+                CSLTestBoolean(CPLGetConfigOption("VSICRYPT_CRYPTO_RANDOM", "TRUE")) != FALSE,
+                (byte*)osKey.c_str(), osKey.size());
+
+            char* pszB64 = CPLBase64Encode(static_cast<int>(osKey.size()), (const GByte*)osKey.c_str());
+            if( CSLTestBoolean(CPLGetConfigOption("VSICRYPT_DISPLAY_GENERATED_KEY", "TRUE")) )
+            {
+                fprintf(stderr, "BASE64 key '%s' has been generated, and installed in "
+                        "the VSICRYPT_KEY_B64 configuration option.\n", pszB64);
+            }
+            CPLSetConfigOption("VSICRYPT_KEY_B64", pszB64);
+            CPLFree(pszB64);
+        }
+
+        int nKeyLength = ( osKey.size() ) ? (int)osKey.size() : nGlobalKeySize;
+        if( nKeyLength < nMinKeySize )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Key is too short: %d bytes. Should be at least %d bytes",
+                     nKeyLength, nMinKeySize);
+            memset((void*)osKey.c_str(), 0, osKey.size());
+            return NULL;
+        }
+
+        VSIVirtualHandle* fpBase = (VSIVirtualHandle*)VSIFOpenL(osFilename, "wb+");
+        if( fpBase == NULL )
+        {
+            memset((void*)osKey.c_str(), 0, osKey.size());
+            return NULL;
+        }
+
+        VSICryptFileHeader* poHeader = new VSICryptFileHeader();
+        poHeader->osIV = osIV;
+        poHeader->eAlg = eAlg;
+        poHeader->eMode = eMode;
+        poHeader->nSectorSize = static_cast<GUInt16>(nSectorSize);
+        poHeader->osFreeText = osFreeText;
+        poHeader->bAddKeyCheck = bAddKeyCheck;
+
+        VSICryptFileHandle* poHandle = new VSICryptFileHandle( osFilename, fpBase, poHeader,
+                    strchr(pszAccess, '+') ? VSICRYPT_READ | VSICRYPT_WRITE : VSICRYPT_WRITE);
+        if( !poHandle->Init(osKey, TRUE) )
+        {
+            memset((void*)osKey.c_str(), 0, osKey.size());
+            delete poHandle;
+            poHandle = NULL;
+        }
+        memset((void*)osKey.c_str(), 0, osKey.size());
+        return poHandle;
+    }
+    else if( strchr(pszAccess, 'a') )
+    {
+        VSIVirtualHandle* fpBase = (VSIVirtualHandle*)VSIFOpenL(osFilename, "rb+");
+        if( fpBase == NULL )
+        {
+            memset((void*)osKey.c_str(), 0, osKey.size());
+            return Open(pszFilename, "wb+");
+        }
+        VSICryptFileHeader* poHeader = new VSICryptFileHeader();
+        if( !poHeader->ReadFromFile(fpBase, osKey) )
+        {
+            memset((void*)osKey.c_str(), 0, osKey.size());
+            fpBase->Close();
+            delete fpBase;
+            delete poHeader;
+            return NULL;
+        }
+
+        VSICryptFileHandle* poHandle = new VSICryptFileHandle( osFilename, fpBase, poHeader,
+                                                               VSICRYPT_READ | VSICRYPT_WRITE );
+        if( !poHandle->Init(osKey) )
+        {
+            delete poHandle;
+            poHandle = NULL;
+        }
+        memset((void*)osKey.c_str(), 0, osKey.size());
+        if( poHandle != NULL )
+            poHandle->Seek(0, SEEK_END);
+        return poHandle;
+    }
+
+    return NULL;
+}
+
+/************************************************************************/
+/*                                Stat()                                */
+/************************************************************************/
+
+int VSICryptFilesystemHandler::Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags )
+{
+#ifdef VERBOSE_VSICRYPT
+    CPLDebug("VSICRYPT", "Stat(%s)", pszFilename);
+#endif
+    CPLString osFilename(GetFilename(pszFilename));
+    if( VSIStatExL( osFilename, pStatBuf, nFlags ) != 0 )
+        return -1;
+    VSIVirtualHandle* fp = (VSIVirtualHandle*)VSIFOpenL(osFilename, "rb");
+    if( fp == NULL )
+        return -1;
+    VSICryptFileHeader* poHeader = new VSICryptFileHeader();
+    CPLString osKey(GetKey(pszFilename));
+    if( !poHeader->ReadFromFile(fp, osKey) )
+    {
+        memset((void*)osKey.c_str(), 0, osKey.size());
+        fp->Close();
+        delete fp;
+        delete poHeader;
+        return -1;
+    }
+    memset((void*)osKey.c_str(), 0, osKey.size());
+    fp->Close();
+    delete fp;
+    if( poHeader )
+    {
+        pStatBuf->st_size = poHeader->nPayloadFileSize;
+        delete poHeader;
+        return 0;
+    }
+    else
+        return -1;
+}
+
+/************************************************************************/
+/*                               Unlink()                               */
+/************************************************************************/
+
+int VSICryptFilesystemHandler::Unlink( const char *pszFilename )
+{
+    return VSIUnlink(GetFilename(pszFilename));
+}
+
+/************************************************************************/
+/*                               Rename()                               */
+/************************************************************************/
+
+int VSICryptFilesystemHandler::Rename( const char *oldpath, const char* newpath )
+{
+    CPLString osNewPath;
+    if( strncmp(newpath, VSICRYPT_PREFIX, strlen(VSICRYPT_PREFIX)) == 0 )
+        osNewPath = GetFilename(newpath);
+    else
+        osNewPath = newpath;
+
+    return VSIRename(GetFilename(oldpath), osNewPath);
+}
+
+/************************************************************************/
+/*                               ReadDirEx()                            */
+/************************************************************************/
+
+char** VSICryptFilesystemHandler::ReadDirEx( const char *pszDirname,
+                                             int nMaxFiles )
+{
+#ifdef VERBOSE_VSICRYPT
+    CPLDebug("VSICRYPT", "ReadDir(%s)", pszDirname);
+#endif
+    return VSIReadDirEx(GetFilename(pszDirname), nMaxFiles);
+}
+
+#ifdef VSICRYPT_DRIVER
+
+#include "gdal_priv.h"
+
+/**
+ * \brief Evaluate if this is a crypt file.
+ *
+ * The function signature must match GDALDataset::Identify.
+ *
+ * @param poOpenInfo The header bytes used for file identification.
+ *
+ * @return 1 if this is a crypt file or 0 otherwise.
+ */
+
+static int VSICryptIdentify(GDALOpenInfo* poOpenInfo)
+{
+    return poOpenInfo->nHeaderBytes > 8 &&
+           memcmp(poOpenInfo->pabyHeader, VSICRYPT_SIGNATURE, 8) == 0;
+}
+
+static GDALDataset* VSICryptOpen(GDALOpenInfo* poOpenInfo)
+{
+    if( !VSICryptIdentify(poOpenInfo) )
+        return NULL;
+    return (GDALDataset*)GDALOpen( (CPLString(VSICRYPT_PREFIX) + poOpenInfo->pszFilename).c_str(),
+                     poOpenInfo->eAccess );
+}
+
+#endif
+
+/************************************************************************/
+/*                   VSIInstallCryptFileHandler()                       */
+/************************************************************************/
+
+/**
+ * \brief Install /vsicrypt/ encrypted file system handler (requires <a href="http://www.cryptopp.com/">libcrypto++</a>)
+ *
+ * A special file handler is installed that allows reading/creating/update encrypted
+ * files on the fly, with random access capabilities.
+ *
+ * The cryptographic algorithms used are
+ * <a href="https://en.wikipedia.org/wiki/Block_cipher">block ciphers</a>, with symmetric key.
+ *
+ * In their simplest form, recognized filenames are of the form /vsicrypt//absolute_path/to/file,
+ * /vsicrypt/c:/absolute_path/to/file or /vsicrypt/relative/path/to/file.
+ *
+ * Options can also be used with the following format :
+ * /vsicrypt/option1=val1,option2=val2,...,file=/path/to/file
+ *
+ * They can also be passed as configuration option/environment variable, because
+ * in some use cases, the syntax with option in the filename might not properly work with some drivers.
+ *
+ * In all modes, the encryption key must be provided. There are several ways
+ * of doing so :
+ * <ul>
+ * <li>By adding a key= parameter to the filename, like /vsicrypt/key=my_secret_key,file=/path/to/file.
+ *     Note that this restricts the key to be in text format, whereas at its full power,
+ *     it can be binary content.</li>
+ * <li>By adding a key_b64= parameter to the filename, to specify a binary key expressed
+ *     in Base64 encoding, like /vsicrypt/key_b64=th1sl00kslikebase64=,file=/path/to/file.</li>
+ * <li>By setting the VSICRYPT_KEY configuration option. The key should be in text format.</li>
+ * <li>By setting the VSICRYPT_KEY_B64 configuration option. The key should be encoded in Base64.</li>
+ * <li>By using the VSISetCryptKey() C function.</li>
+ * </ul>
+ *
+ * When creating a file, if key=GENERATE_IT or VSICRYPT_KEY=GENERATE_IT is passed,
+ * the encryption key will be generated from the pseudo-random number generator of the
+ * operating system. The key will be displayed on the standard error stream in a Base64 form
+ * (unless the VSICRYPT_DISPLAY_GENERATED_KEY configuration option is set to OFF),
+ * and the VSICRYPT_KEY_B64 configuration option will also be set with the Base64 form
+ * of the key (so that CPLGetConfigOption("VSICRYPT_KEY_B64", NULL) can be used to get it back).
+ *
+ * The available options are :
+ * <ul>
+ * <li>alg=AES/Blowfish/Camellia/CAST256/DES_EDE2/DES_EDE3/MARS/IDEA/RC5/RC6/Serpent/SHACAL2/SKIPJACK/Twofish/XTEA:
+ *     to specify the <a href="https://en.wikipedia.org/wiki/Block_cipher">block cipher</a> algorithm.
+ *     The default is AES.
+ *     Only used on creation. Ignored otherwise.
+ *     Note: depending on how GDAL is build, if linked against the DLL version of libcrypto++,
+ *     only a subset of those algorithms will be available, namely AES, DES_EDE2, DES_EDE3 and SKIPJACK.
+ *     Also available as VSICRYPT_ALG configuration option.</li>
+ * <li>mode=CBC/CFB/OFB/CTR/CBC_CTS: to specify the <a href="https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation">block cipher mode of operation</a>.
+ *     The default is CBC.
+ *     Only used on creation. Ignored otherwise.
+ *     Also available as VSICRYPT_MODE configuration option.</li>
+ * <li>key=text_key: see above.</li>
+ * <li>key_b64=base64_encoded_key: see above.</li>
+ * <li>freetext=some_text: to specify a text content that will be written *unencrypted*
+ *     in the file header, for informational purposes. Default to empty.
+ *     Only used on creation. Ignored otherwise.
+ *     Also available as VSICRYPT_FREETEXT configuration option.</li>
+ * <li>sector_size=int_value: to specify the size of the "sector", which is the
+ *     unit chunk of information that is encrypted/decrypted. Default to 512 bytes.
+ *     The valid values depend on the algorithm and block cipher mode of operation.
+ *     Only used on creation. Ignored otherwise.
+ *     Also available as VSICRYPT_SECTOR_SIZE configuration option.</li>
+ * <li>iv=initial_vector_as_text: to specify the Initial Vector. This is an
+ *     advanced option that should generally *NOT* be used. It is only useful
+ *     to get completely deterministic output
+ *     given the plaintext, key and other parameters, which in general *NOT* what
+ *     you want to do. By default, a random initial vector of the appropriate size
+ *     will be generated for each new file created.
+ *     Only used on creation. Ignored otherwise.
+ *     Also available as VSICRYPT_IV configuration option.</li>
+ * <li>add_key_check=YES/NO: whether a special value should be encrypted in the header,
+ *     so as to be quickly able to determine if the decryption key is correct.
+ *     Defaults to NO.
+ *     Only used on creation. Ignored otherwise.
+ *     Also available as VSICRYPT_ADD_KEY_CHECK configuration option.</li>
+ * <li>file=filename. To specify the filename. This must be the last option put in the
+ *     option list (so as to make it possible to use filenames with comma in them. )
+ * </ul>
+ *
+ * This special file handler can be combined with other virtual filesystems handlers,
+ * such as /vsizip. For example, /vsicrypt//vsicurl/path/to/remote/encrypted/file.tif
+ *
+ * Implementation details:
+ *
+ * The structure of encrypted files is the following: a header, immediately
+ * followed by the encrypted payload (by sectors, i.e. chunks of sector_size bytes).
+ *
+ * The header structure is the following :
+ * <ol>
+ * <li>8 bytes. Signature. Fixed value: VSICRYPT.</li>
+ * <li>UINT16_LE. Header size (including previous signature bytes).</li>
+ * <li>UINT8. Format major version. Current value: 1.</li>
+ * <li>UINT8. Format minor version. Current value: 0.</li>
+ * <li>UINT16. Sector size.</li>
+ * <li>UINT8. Cipher algorithm. Valid values are: 0 = AES (Rijndael), 1 = Blowfish, 2 = Camellia, 3 = CAST256,
+ *     4 = DES_EDE2, 5 = DES_EDE3, 6 = MARS, 7 = IDEA, 8 = RC5, 9 = RC6, 10 = Serpent, 11 = SHACAL2,
+ *     12 = SKIPJACK, 13 = Twofish, 14 = XTEA.</li>
+ * <li>UINT8. Block cipher mode of operation. Valid values are: 0 = CBC, 1 = CFB, 2 = OFB, 3 = CTR, 4 = CBC_CTS.</li>
+ * <li>UINT8. Size in bytes of the Initial Vector.</li>
+ * <li>N bytes with the content of the Initial Vector, where N is the value of the previous field.</li>
+ * <li>UINT16_LE. Size in bytes of the free text.</li>
+ * <li>N bytes with the content of the free text, where N is the value of the previous field.</li>
+ * <li>UINT8. Size in bytes of encrypted content (key check), or 0 if key check is absent.</li>
+ * <li>N bytes with encrypted content (key check), where N is the value of the previous field.</li>
+ * <li>UINT64_LE. Size of the unencrypted file, in bytes.</li>
+ * <li>UINT16_LE. Size in bytes of extra content (of unspecified semantics). For v1.0, fixed value of 0</li>
+ * <li>N bytes with extra content (of unspecified semantics), where N is the value of the previous field.</li>
+ * </ol>
+ *
+ * This design does not provide any means of authentication or integrity check.
+ *
+ * Each sector is encrypted/decrypted independently of other sectors.
+ * For that, the Initial Vector contained in the header is XOR'ed with the file offset
+ * (relative to plain text file) of the start of the sector being processed, as a 8-byte integer.
+ * More precisely, the first byte of the main IV is XOR'ed with the 8 least-significant
+ * bits of the sector offset, the second byte of the main IV is XOR'ed with the following
+ * 8 bits of the sector offset, etc... until the 8th byte.
+ *
+ * This design could potentially be prone to chosen-plaintext attack, for example
+ * if the attacker managed to get (part of) an existing encrypted file to be encrypted from
+ * plaintext he might have selected.
+ *
+ * Note: if "hostile" code can explore process content, or attach to it with a
+ * debugger, it might be relatively easy to retrieve the encryption key.
+ * A GDAL plugin could for example get the content of configuration options, or
+ * list opened datasets and see the key/key_b64 values, so disabling plugin loading
+ * might be a first step, as well as linking statically GDAL to application code.
+ * If plugin loading is enabled or GDAL dynamically linked, using VSISetCryptKey()
+ * to set the key might make it a bit more complicated to spy the key.
+ * But, as said initially, this is in no way a perfect protection.
+ *
+ * @since GDAL 2.1.0
+ */
+void VSIInstallCryptFileHandler(void)
+
+{
+    VSIFileManager::InstallHandler( VSICRYPT_PREFIX, new VSICryptFilesystemHandler );
+
+#ifdef VSICRYPT_DRIVER
+    if( GDALGetDriverByName( "VSICRYPT" ) == NULL )
+    {
+        GDALDriver      *poDriver = new GDALDriver();
+
+        poDriver->SetDescription( "VSICRYPT" );
+#ifdef GDAL_DCAP_RASTER
+        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+#endif
+        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                                   CPLSPrintf("Wrapper for %s files", VSICRYPT_PREFIX) );
+
+        poDriver->pfnOpen = VSICryptOpen;
+        poDriver->pfnIdentify = VSICryptIdentify;
+
+        GetGDALDriverManager()->RegisterDriver( poDriver );
+    }
+#endif
+}
+
+//#ifdef _MSC_VER
+//#pragma warning( pop ) /* 5105 */
+//#endif
+
+#else /* HAVE_CRYPTOPP */
+
+class VSIDummyCryptFilesystemHandler : public VSIFilesystemHandler
+{
+public:
+    VSIDummyCryptFilesystemHandler() {}
+
+    virtual VSIVirtualHandle *Open( CPL_UNUSED const char *pszFilename,
+                                    CPL_UNUSED const char *pszAccess,
+                                    bool)
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "%s support not available in this build", VSICRYPT_PREFIX);
+        return NULL;
+    }
+
+    virtual int Stat( CPL_UNUSED const char *pszFilename,
+                      CPL_UNUSED VSIStatBufL *pStatBuf, CPL_UNUSED int nFlags )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "%s support not available in this build", VSICRYPT_PREFIX);
+        return -1;
+    }
+};
+
+void VSIInstallCryptFileHandler(void)
+{
+    VSIFileManager::InstallHandler( VSICRYPT_PREFIX, new VSIDummyCryptFilesystemHandler );
+}
+
+void VSISetCryptKey(CPL_UNUSED const GByte* pabyKey, CPL_UNUSED int nKeySize)
+{
+    /* not supported */
+}
+
+#endif /* HAVE_CRYPTOPP */
+
+/* Below is only useful if using as a plugin over GDAL 1.11 or GDAL 2.0 */
+#ifdef VSICRYPT_AUTOLOAD
+
+CPL_C_START
+void CPL_DLL GDALRegisterMe();
+CPL_C_END
+
+void GDALRegisterMe()
+{
+    if( VSIFileManager::GetHandler(VSICRYPT_PREFIX) == VSIFileManager::GetHandler(".") )
+        VSIInstallCryptFileHandler();
+}
+
+#ifndef GDAL_DCAP_RASTER
+CPL_C_START
+void CPL_DLL RegisterOGRCRYPT();
+CPL_C_END
+
+void RegisterOGRCRYPT()
+{
+    if( VSIFileManager::GetHandler(VSICRYPT_PREFIX) == VSIFileManager::GetHandler(".") )
+        VSIInstallCryptFileHandler();
+}
+#endif
+
+#endif /* VSICRYPT_AUTOLOAD */
diff --git a/port/cpl_vsil_curl.cpp b/port/cpl_vsil_curl.cpp
index 5b14bb1..6dda348 100644
--- a/port/cpl_vsil_curl.cpp
+++ b/port/cpl_vsil_curl.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: cpl_vsil_curl.cpp 28798 2015-03-27 19:37:50Z rouault $
+ * $Id: cpl_vsil_curl.cpp 33758 2016-03-21 09:06:22Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for HTTP/FTP files
  * Author:   Even Rouault, even.rouault at mines-paris.org
  *
  ******************************************************************************
- * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ * Copyright (c) 2010-2015, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,8 +33,10 @@
 #include "cpl_hash_set.h"
 #include "cpl_time.h"
 #include "cpl_vsil_curl_priv.h"
+#include "cpl_aws.h"
+#include "cpl_minixml.h"
 
-CPL_CVSID("$Id: cpl_vsil_curl.cpp 28798 2015-03-27 19:37:50Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_curl.cpp 33758 2016-03-21 09:06:22Z rouault $");
 
 #ifndef HAVE_CURL
 
@@ -43,6 +45,11 @@ void VSIInstallCurlFileHandler(void)
     /* not supported */
 }
 
+void VSIInstallS3FileHandler(void)
+{
+    /* not supported */
+}
+
 /************************************************************************/
 /*                      VSICurlInstallReadCbk()                         */
 /************************************************************************/
@@ -76,9 +83,10 @@ void VSICurlSetOptions(CURL* hCurlHandle, const char* pszURL);
 
 #define ENABLE_DEBUG 1
 
-#define N_MAX_REGIONS       1000
+static const int N_MAX_REGIONS = 1000;
+static const int DOWNLOAD_CHUNK_SIZE = 16384;
 
-#define DOWNLOAD_CHUNCK_SIZE    16384
+namespace {
 
 typedef enum
 {
@@ -90,15 +98,15 @@ typedef enum
 typedef struct
 {
     ExistStatus     eExists;
-    int             bHastComputedFileSize;
+    bool            bHasComputedFileSize;
     vsi_l_offset    fileSize;
-    int             bIsDirectory;
+    bool            bIsDirectory;
     time_t          mTime;
 } CachedFileProp;
 
 typedef struct
 {
-    int             bGotFileList;
+    bool            bGotFileList;
     char**          papszFileList; /* only file name without path */
 } CachedDirList;
 
@@ -110,6 +118,28 @@ typedef struct
     char           *pData;
 } CachedRegion;
 
+typedef struct
+{
+    char*           pBuffer;
+    size_t          nSize;
+    bool            bIsHTTP;
+    bool            bIsInHeader;
+    bool            bMultiRange;
+    vsi_l_offset    nStartOffset;
+    vsi_l_offset    nEndOffset;
+    int             nHTTPCode;
+    vsi_l_offset    nContentLength;
+    bool            bFoundContentRange;
+    bool            bError;
+    bool            bDownloadHeaderOnly;
+
+    VSILFILE           *fp;
+    VSICurlReadCbkFunc  pfnReadCbk;
+    void               *pReadCbkUserData;
+    bool                bInterrupted;
+} WriteFuncStruct;
+
+} /* end of anoymous namespace */
 
 static const char* VSICurlGetCacheFileName()
 {
@@ -124,12 +154,10 @@ static int VSICurlFindStringSensitiveExceptEscapeSequences( char ** papszList,
                                                             const char * pszTarget )
 
 {
-    int         i;
-
     if( papszList == NULL )
         return -1;
 
-    for( i = 0; papszList[i] != NULL; i++ )
+    for( int i = 0; papszList[i] != NULL; i++ )
     {
         const char* pszIter1 = papszList[i];
         const char* pszIter2 = pszTarget;
@@ -137,7 +165,7 @@ static int VSICurlFindStringSensitiveExceptEscapeSequences( char ** papszList,
         /* The comparison is case-sensitive, escape for escaped */
         /* sequences where letters of the hexadecimal sequence */
         /* can be uppercase or lowercase depending on the quoting algorithm */
-        while(TRUE)
+        while(true)
         {
             ch1 = *pszIter1;
             ch2 = *pszIter2;
@@ -194,11 +222,10 @@ typedef struct
     CURL           *hCurlHandle;
 } CachedConnection;
 
+class VSICurlHandle;
 
-class VSICurlFilesystemHandler : public VSIFilesystemHandler 
+class VSICurlFilesystemHandler : public VSIFilesystemHandler
 {
-    CPLMutex       *hMutex;
-
     CachedRegion  **papsRegions;
     int             nRegions;
 
@@ -210,24 +237,47 @@ class VSICurlFilesystemHandler : public VSIFilesystemHandler
     /* Per-thread Curl connection cache */
     std::map<GIntBig, CachedConnection*> mapConnections;
 
-    char** GetFileList(const char *pszFilename, int* pbGotFileList);
 
     char**              ParseHTMLFileList(const char* pszFilename,
+                                          int nMaxFiles,
                                           char* pszData,
-                                          int* pbGotFileList);
+                                          bool* pbGotFileList);
+
+protected:
+    CPLMutex       *hMutex;
+
+    virtual CPLString GetFSPrefix() { return "/vsicurl/"; }
+    virtual VSICurlHandle* CreateFileHandle(const char* pszURL);
+    virtual char** GetFileList(const char *pszFilename,
+                               int nMaxFiles,
+                               bool* pbGotFileList);
+    virtual CPLString GetURLFromDirname( const CPLString& osDirname );
+
+    void AnalyseS3FileList( const CPLString& osBaseURL,
+                            const char* pszXML,
+                            CPLStringList& osFileList,
+                            int nMaxFiles,
+                            bool& bIsTruncated,
+                            CPLString& osNextMarker );
+
 public:
     VSICurlFilesystemHandler();
     ~VSICurlFilesystemHandler();
 
-    virtual VSIVirtualHandle *Open( const char *pszFilename, 
-                                    const char *pszAccess);
+    using VSIFilesystemHandler::Open;
+
+    virtual VSIVirtualHandle *Open( const char *pszFilename,
+                                    const char *pszAccess,
+                                    bool bSetError );
+
     virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags );
     virtual int      Unlink( const char *pszFilename );
     virtual int      Rename( const char *oldpath, const char *newpath );
     virtual int      Mkdir( const char *pszDirname, long nMode );
     virtual int      Rmdir( const char *pszDirname );
-    virtual char   **ReadDir( const char *pszDirname );
-    virtual char   **ReadDir( const char *pszDirname, int* pbGotFileList );
+    virtual char   **ReadDirEx( const char *pszDirname, int nMaxFiles );
+            char   **ReadDirInternal( const char *pszDirname, int nMaxFiles, bool* pbGotFileList );
+            void     InvalidateDirContent( const char *pszDirname );
 
 
     const CachedRegion* GetRegion(const char*     pszURL,
@@ -239,6 +289,7 @@ public:
                                   const char     *pData);
 
     CachedFileProp*     GetCachedFileProp(const char*     pszURL);
+    void                InvalidateCachedFileProp(const char*     pszURL);
 
     void                AddRegionToCacheDisk(CachedRegion* psRegion);
     const CachedRegion* GetRegionFromCacheDisk(const char*     pszURL,
@@ -253,28 +304,39 @@ public:
 
 class VSICurlHandle : public VSIVirtualHandle
 {
-  private:
+
+  protected:
     VSICurlFilesystemHandler* poFS;
 
+    vsi_l_offset    fileSize;
+    bool            bHasComputedFileSize;
+    ExistStatus     eExists;
+    bool            bIsDirectory;
+
+  private:
     char*           pszURL;
 
     vsi_l_offset    curOffset;
-    vsi_l_offset    fileSize;
-    int             bHastComputedFileSize;
-    ExistStatus     eExists;
-    int             bIsDirectory;
     time_t          mTime;
 
     vsi_l_offset    lastDownloadedOffset;
     int             nBlocksToDownload;
-    int             bEOF;
+    bool            bEOF;
 
-    int             DownloadRegion(vsi_l_offset startOffset, int nBlocks);
+    bool            DownloadRegion(vsi_l_offset startOffset, int nBlocks);
 
     VSICurlReadCbkFunc  pfnReadCbk;
     void               *pReadCbkUserData;
-    int                 bStopOnInterrruptUntilUninstall;
-    int                 bInterrupted;
+    bool                bStopOnInterrruptUntilUninstall;
+    bool                bInterrupted;
+
+  protected:
+    virtual struct curl_slist* GetCurlHeaders(const CPLString& ) { return NULL; }
+    bool CanRestartOnError(const char* pszErrorMsg) { return CanRestartOnError(pszErrorMsg, false); }
+    virtual bool CanRestartOnError(const char*, bool) { return false; }
+    virtual bool UseLimitRangeGetInsteadOfHead() { return false; }
+    virtual void ProcessGetFileSizeResult(const char* /* pszContent */ ) {}
+    void SetURL(const char* pszURL);
 
   public:
 
@@ -291,10 +353,11 @@ class VSICurlHandle : public VSIVirtualHandle
     virtual int          Flush();
     virtual int          Close();
 
-    int                  IsKnownFileSize() const { return bHastComputedFileSize; }
-    vsi_l_offset         GetFileSize();
-    int                  Exists();
-    int                  IsDirectory() const { return bIsDirectory; }
+    bool                 IsKnownFileSize() const { return bHasComputedFileSize; }
+    vsi_l_offset         GetFileSize() { return GetFileSize(false); }
+    vsi_l_offset         GetFileSize(bool bSetError);
+    bool                 Exists(bool bSetError);
+    bool                 IsDirectory() const { return bIsDirectory; }
     time_t               GetMTime() const { return mTime; }
 
     int                  InstallReadCbk(VSICurlReadCbkFunc pfnReadCbk,
@@ -307,28 +370,24 @@ class VSICurlHandle : public VSIVirtualHandle
 /*                           VSICurlHandle()                            */
 /************************************************************************/
 
-VSICurlHandle::VSICurlHandle(VSICurlFilesystemHandler* poFS, const char* pszURL)
+VSICurlHandle::VSICurlHandle(VSICurlFilesystemHandler* poFSIn, const char* pszURLIn) :
+    poFS(poFSIn),
+    curOffset(0),
+    lastDownloadedOffset(VSI_L_OFFSET_MAX),
+    nBlocksToDownload(1),
+    bEOF(false),
+    pfnReadCbk(NULL),
+    pReadCbkUserData(NULL),
+    bStopOnInterrruptUntilUninstall(false),
+    bInterrupted(false)
 {
-    this->poFS = poFS;
-    this->pszURL = CPLStrdup(pszURL);
-
-    curOffset = 0;
-
+    pszURL = CPLStrdup(pszURLIn);
     CachedFileProp* cachedFileProp = poFS->GetCachedFileProp(pszURL);
     eExists = cachedFileProp->eExists;
     fileSize = cachedFileProp->fileSize;
-    bHastComputedFileSize = cachedFileProp->bHastComputedFileSize;
+    bHasComputedFileSize = cachedFileProp->bHasComputedFileSize;
     bIsDirectory = cachedFileProp->bIsDirectory;
     mTime = cachedFileProp->mTime;
-
-    lastDownloadedOffset = -1;
-    nBlocksToDownload = 1;
-    bEOF = FALSE;
-
-    pfnReadCbk = NULL;
-    pReadCbkUserData = NULL;
-    bStopOnInterrruptUntilUninstall = FALSE;
-    bInterrupted = FALSE;
 }
 
 /************************************************************************/
@@ -341,6 +400,16 @@ VSICurlHandle::~VSICurlHandle()
 }
 
 /************************************************************************/
+/*                            SetURL()                                  */
+/************************************************************************/
+
+void VSICurlHandle::SetURL(const char* pszURLIn)
+{
+    CPLFree(pszURL);
+    pszURL = CPLStrdup(pszURLIn);
+}
+
+/************************************************************************/
 /*                          InstallReadCbk()                            */
 /************************************************************************/
 
@@ -353,8 +422,8 @@ int   VSICurlHandle::InstallReadCbk(VSICurlReadCbkFunc pfnReadCbkIn,
 
     pfnReadCbk = pfnReadCbkIn;
     pReadCbkUserData = pfnUserDataIn;
-    bStopOnInterrruptUntilUninstall = bStopOnInterrruptUntilUninstallIn;
-    bInterrupted = FALSE;
+    bStopOnInterrruptUntilUninstall = CPL_TO_BOOL(bStopOnInterrruptUntilUninstallIn);
+    bInterrupted = false;
     return TRUE;
 }
 
@@ -369,8 +438,8 @@ int VSICurlHandle::UninstallReadCbk()
 
     pfnReadCbk = NULL;
     pReadCbkUserData = NULL;
-    bStopOnInterrruptUntilUninstall = FALSE;
-    bInterrupted = FALSE;
+    bStopOnInterrruptUntilUninstall = false;
+    bInterrupted = false;
     return TRUE;
 }
 
@@ -392,7 +461,7 @@ int VSICurlHandle::Seek( vsi_l_offset nOffset, int nWhence )
     {
         curOffset = GetFileSize() + nOffset;
     }
-    bEOF = FALSE;
+    bEOF = false;
     return 0;
 }
 
@@ -419,7 +488,7 @@ void VSICurlSetOptions(CURL* hCurlHandle, const char* pszURL)
 #endif
 
     curl_easy_setopt(hCurlHandle, CURLOPT_NOBODY, 0);
-    curl_easy_setopt(hCurlHandle, CURLOPT_HTTPGET, 1); 
+    curl_easy_setopt(hCurlHandle, CURLOPT_HTTPGET, 1);
     curl_easy_setopt(hCurlHandle, CURLOPT_HEADER, 0);
 
 /* 7.16.4 */
@@ -433,28 +502,6 @@ void VSICurlSetOptions(CURL* hCurlHandle, const char* pszURL)
     curl_easy_setopt(hCurlHandle, CURLOPT_HEADERFUNCTION, NULL);
 }
 
-
-typedef struct
-{
-    char*           pBuffer;
-    size_t          nSize;
-    int             bIsHTTP;
-    int             bIsInHeader;
-    int             bMultiRange;
-    vsi_l_offset    nStartOffset;
-    vsi_l_offset    nEndOffset;
-    int             nHTTPCode;
-    vsi_l_offset    nContentLength;
-    int             bFoundContentRange;
-    int             bError;
-    int             bDownloadHeaderOnly;
-
-    VSILFILE           *fp; 
-    VSICurlReadCbkFunc  pfnReadCbk;
-    void               *pReadCbkUserData;
-    int                 bInterrupted;
-} WriteFuncStruct;
-
 /************************************************************************/
 /*                    VSICURLInitWriteFuncStruct()                      */
 /************************************************************************/
@@ -466,31 +513,31 @@ static void VSICURLInitWriteFuncStruct(WriteFuncStruct   *psStruct,
 {
     psStruct->pBuffer = NULL;
     psStruct->nSize = 0;
-    psStruct->bIsHTTP = FALSE;
-    psStruct->bIsInHeader = TRUE;
-    psStruct->bMultiRange = FALSE;
+    psStruct->bIsHTTP = false;
+    psStruct->bIsInHeader = true;
+    psStruct->bMultiRange = false;
     psStruct->nStartOffset = 0;
     psStruct->nEndOffset = 0;
     psStruct->nHTTPCode = 0;
     psStruct->nContentLength = 0;
-    psStruct->bFoundContentRange = FALSE;
-    psStruct->bError = FALSE;
-    psStruct->bDownloadHeaderOnly = FALSE;
+    psStruct->bFoundContentRange = false;
+    psStruct->bError = false;
+    psStruct->bDownloadHeaderOnly = false;
 
     psStruct->fp = fp;
     psStruct->pfnReadCbk = pfnReadCbk;
     psStruct->pReadCbkUserData = pReadCbkUserData;
-    psStruct->bInterrupted = FALSE;
+    psStruct->bInterrupted = false;
 }
 
 /************************************************************************/
 /*                       VSICurlHandleWriteFunc()                       */
 /************************************************************************/
 
-static int VSICurlHandleWriteFunc(void *buffer, size_t count, size_t nmemb, void *req)
+static size_t VSICurlHandleWriteFunc(void *buffer, size_t count, size_t nmemb, void *req)
 {
     WriteFuncStruct* psStruct = (WriteFuncStruct*) req;
-    size_t nSize = count * nmemb;
+    const size_t nSize = count * nmemb;
 
     char* pNewBuffer = (char*) VSIRealloc(psStruct->pBuffer,
                                           psStruct->nSize + nSize + 1);
@@ -502,14 +549,14 @@ static int VSICurlHandleWriteFunc(void *buffer, size_t count, size_t nmemb, void
         if (psStruct->bIsHTTP && psStruct->bIsInHeader)
         {
             char* pszLine = psStruct->pBuffer + psStruct->nSize;
-            if (EQUALN(pszLine, "HTTP/1.0 ", 9) ||
-                EQUALN(pszLine, "HTTP/1.1 ", 9))
+            if (STARTS_WITH_CI(pszLine, "HTTP/1.0 ") ||
+                STARTS_WITH_CI(pszLine, "HTTP/1.1 "))
                 psStruct->nHTTPCode = atoi(pszLine + 9);
-            else if (EQUALN(pszLine, "Content-Length: ", 16))
+            else if (STARTS_WITH_CI(pszLine, "Content-Length: "))
                 psStruct->nContentLength = CPLScanUIntBig(pszLine + 16,
-                                                          strlen(pszLine + 16));
-            else if (EQUALN(pszLine, "Content-Range: ", 15))
-                psStruct->bFoundContentRange = TRUE;
+                                                          static_cast<int>(strlen(pszLine + 16)));
+            else if (STARTS_WITH_CI(pszLine, "Content-Range: "))
+                psStruct->bFoundContentRange = true;
 
             /*if (nSize > 2 && pszLine[nSize - 2] == '\r' &&
                 pszLine[nSize - 1] == '\n')
@@ -529,7 +576,7 @@ static int VSICurlHandleWriteFunc(void *buffer, size_t count, size_t nmemb, void
                 }
                 else
                 {
-                    psStruct->bIsInHeader = FALSE;
+                    psStruct->bIsInHeader = false;
 
                     /* Detect servers that don't support range downloading */
                     if (psStruct->nHTTPCode == 200 &&
@@ -540,7 +587,7 @@ static int VSICurlHandleWriteFunc(void *buffer, size_t count, size_t nmemb, void
                     {
                         CPLError(CE_Failure, CPLE_AppDefined,
                                 "Range downloading not supported by this server !");
-                        psStruct->bError = TRUE;
+                        psStruct->bError = true;
                         return 0;
                     }
                 }
@@ -553,7 +600,7 @@ static int VSICurlHandleWriteFunc(void *buffer, size_t count, size_t nmemb, void
                 if ( ! psStruct->pfnReadCbk(psStruct->fp, buffer, nSize,
                                             psStruct->pReadCbkUserData) )
                 {
-                    psStruct->bInterrupted = TRUE;
+                    psStruct->bInterrupted = true;
                     return 0;
                 }
             }
@@ -572,15 +619,15 @@ static int VSICurlHandleWriteFunc(void *buffer, size_t count, size_t nmemb, void
 /*                           GetFileSize()                              */
 /************************************************************************/
 
-vsi_l_offset VSICurlHandle::GetFileSize()
+vsi_l_offset VSICurlHandle::GetFileSize(bool bSetError)
 {
     WriteFuncStruct sWriteFuncData;
     WriteFuncStruct sWriteFuncHeaderData;
 
-    if (bHastComputedFileSize)
+    if (bHasComputedFileSize)
         return fileSize;
 
-    bHastComputedFileSize = TRUE;
+    bHasComputedFileSize = true;
 
     /* Consider that only the files whose extension ends up with one that is */
     /* listed in CPL_VSIL_CURL_ALLOWED_EXTENSIONS exist on the server */
@@ -594,23 +641,24 @@ vsi_l_offset VSICurlHandle::GetFileSize()
     if (pszAllowedExtensions)
     {
         char** papszExtensions = CSLTokenizeString2( pszAllowedExtensions, ", ", 0 );
-        int nURLLen = strlen(pszURL);
-        int bFound = FALSE;
+        const size_t nURLLen = strlen(pszURL);
+        bool bFound = false;
         for(int i=0;papszExtensions[i] != NULL;i++)
         {
-            int nExtensionLen = strlen(papszExtensions[i]);
+            const size_t nExtensionLen = strlen(papszExtensions[i]);
             if( EQUAL(papszExtensions[i], "{noext}") )
             {
-                if( nURLLen > 4 && strchr(pszURL + nURLLen - 4, '.') == NULL )
+                const char* pszLastSlash = strrchr(pszURL, '/');
+                if( pszLastSlash != NULL && strchr(pszLastSlash, '.') == NULL )
                 {
-                    bFound = TRUE;
+                    bFound = true;
                     break;
                 }
             }
             else if (nURLLen > nExtensionLen &&
                 EQUAL(pszURL + nURLLen - nExtensionLen, papszExtensions[i]))
             {
-                bFound = TRUE;
+                bFound = true;
                 break;
             }
         }
@@ -621,7 +669,7 @@ vsi_l_offset VSICurlHandle::GetFileSize()
             fileSize = 0;
 
             CachedFileProp* cachedFileProp = poFS->GetCachedFileProp(pszURL);
-            cachedFileProp->bHastComputedFileSize = TRUE;
+            cachedFileProp->bHasComputedFileSize = true;
             cachedFileProp->fileSize = fileSize;
             cachedFileProp->eExists = eExists;
 
@@ -644,29 +692,42 @@ vsi_l_offset VSICurlHandle::GetFileSize()
 
     VSICURLInitWriteFuncStruct(&sWriteFuncHeaderData, NULL, NULL, NULL);
 
+    /* We need that otherwise OSGEO4W's libcurl issue a dummy range request */
+    /* when doing a HEAD when recycling connections */
+    curl_easy_setopt(hCurlHandle, CURLOPT_RANGE, NULL);
+
     /* HACK for mbtiles driver: proper fix would be to auto-detect servers that don't accept HEAD */
     /* http://a.tiles.mapbox.com/v3/ doesn't accept HEAD, so let's start a GET */
     /* and interrupt is as soon as the header is found */
-    if (strstr(pszURL, ".tiles.mapbox.com/") != NULL
+    CPLString osVerb;
+    if( UseLimitRangeGetInsteadOfHead() )
+    {
+        curl_easy_setopt(hCurlHandle, CURLOPT_HEADERDATA, &sWriteFuncHeaderData);
+        curl_easy_setopt(hCurlHandle, CURLOPT_HEADERFUNCTION, VSICurlHandleWriteFunc);
+
+        sWriteFuncHeaderData.bIsHTTP = STARTS_WITH(pszURL, "http");
+        osVerb = "GET";
+
+        curl_easy_setopt(hCurlHandle, CURLOPT_RANGE, "0-4095");
+    }
+    else if (strstr(pszURL, ".tiles.mapbox.com/") != NULL
 	|| !CSLTestBoolean(CPLGetConfigOption("CPL_VSIL_CURL_USE_HEAD", "YES")))
     {
         curl_easy_setopt(hCurlHandle, CURLOPT_HEADERDATA, &sWriteFuncHeaderData);
         curl_easy_setopt(hCurlHandle, CURLOPT_HEADERFUNCTION, VSICurlHandleWriteFunc);
 
-        sWriteFuncHeaderData.bIsHTTP = strncmp(pszURL, "http", 4) == 0;
-        sWriteFuncHeaderData.bDownloadHeaderOnly = TRUE;
+        sWriteFuncHeaderData.bIsHTTP = STARTS_WITH(pszURL, "http");
+        sWriteFuncHeaderData.bDownloadHeaderOnly = true;
+        osVerb = "GET";
     }
     else
     {
         curl_easy_setopt(hCurlHandle, CURLOPT_NOBODY, 1);
         curl_easy_setopt(hCurlHandle, CURLOPT_HTTPGET, 0);
         curl_easy_setopt(hCurlHandle, CURLOPT_HEADER, 1);
+        osVerb = "HEAD";
     }
 
-    /* We need that otherwise OSGEO4W's libcurl issue a dummy range request */
-    /* when doing a HEAD when recycling connections */
-    curl_easy_setopt(hCurlHandle, CURLOPT_RANGE, NULL);
-
     /* Bug with older curl versions (<=7.16.4) and FTP. See http://curl.haxx.se/mail/lib-2007-08/0312.html */
     VSICURLInitWriteFuncStruct(&sWriteFuncData, NULL, NULL, NULL);
     curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, &sWriteFuncData);
@@ -676,25 +737,32 @@ vsi_l_offset VSICurlHandle::GetFileSize()
     szCurlErrBuf[0] = '\0';
     curl_easy_setopt(hCurlHandle, CURLOPT_ERRORBUFFER, szCurlErrBuf );
 
-    double dfSize = 0;
+    struct curl_slist* headers = GetCurlHeaders(osVerb);
+    if( headers != NULL )
+        curl_easy_setopt(hCurlHandle, CURLOPT_HTTPHEADER, headers);
+
     curl_easy_perform(hCurlHandle);
 
+    if( headers != NULL )
+        curl_slist_free_all(headers);
+
     eExists = EXIST_UNKNOWN;
 
-    if (strncmp(pszURL, "ftp", 3) == 0)
+    if (STARTS_WITH(pszURL, "ftp"))
     {
         if (sWriteFuncData.pBuffer != NULL &&
-            strncmp(sWriteFuncData.pBuffer, "Content-Length: ", strlen( "Content-Length: ")) == 0)
+            STARTS_WITH(sWriteFuncData.pBuffer, "Content-Length: "))
         {
             const char* pszBuffer = sWriteFuncData.pBuffer + strlen("Content-Length: ");
             eExists = EXIST_YES;
-            fileSize = CPLScanUIntBig(pszBuffer, sWriteFuncData.nSize - strlen("Content-Length: "));
+            fileSize = CPLScanUIntBig(pszBuffer, static_cast<int>(sWriteFuncData.nSize - strlen("Content-Length: ")));
             if (ENABLE_DEBUG)
                 CPLDebug("VSICURL", "GetFileSize(%s)=" CPL_FRMT_GUIB,
                         pszURL, fileSize);
         }
     }
-    
+
+    double dfSize = 0;
     if (eExists != EXIST_YES)
     {
         CURLcode code = curl_easy_getinfo(hCurlHandle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &dfSize );
@@ -715,11 +783,55 @@ vsi_l_offset VSICurlHandle::GetFileSize()
 
         long response_code = 0;
         curl_easy_getinfo(hCurlHandle, CURLINFO_HTTP_CODE, &response_code);
-        if (response_code != 200)
+
+        if( UseLimitRangeGetInsteadOfHead() && response_code == 206 )
+        {
+            eExists = EXIST_NO;
+            fileSize = 0;
+            if( sWriteFuncHeaderData.pBuffer != NULL )
+            {
+                const char* pszContentRange = strstr((const char*)sWriteFuncHeaderData.pBuffer, "Content-Range: bytes ");
+                if( pszContentRange )
+                    pszContentRange = strchr(pszContentRange, '/');
+                if( pszContentRange )
+                {
+                    eExists = EXIST_YES;
+                    fileSize = (GUIntBig)CPLAtoGIntBig(pszContentRange+1);
+                }
+            }
+        }
+        else if( response_code != 200 )
         {
+            if( UseLimitRangeGetInsteadOfHead() && sWriteFuncData.pBuffer != NULL &&
+                CanRestartOnError((const char*)sWriteFuncData.pBuffer, bSetError) )
+            {
+                bHasComputedFileSize = false;
+                CPLFree(sWriteFuncData.pBuffer);
+                CPLFree(sWriteFuncHeaderData.pBuffer);
+                return GetFileSize(bSetError);
+            }
+
+            // If there was no VSI error thrown in the process,
+            // fail by reporting the HTTP response code.
+            if(bSetError && VSIGetLastErrorNo() == 0) {
+                if(strlen(szCurlErrBuf) > 0) {
+                    if(response_code == 0) {
+                        VSIError(VSIE_HttpError, "CURL error: %s", szCurlErrBuf);
+                    } else {
+                        VSIError(VSIE_HttpError, "HTTP response code: %d - %s", (int)response_code, szCurlErrBuf);
+                    }
+                } else {
+                    VSIError(VSIE_HttpError, "HTTP response code: %d", (int)response_code);
+                }
+            }
+
             eExists = EXIST_NO;
             fileSize = 0;
         }
+        else if( sWriteFuncData.pBuffer != NULL )
+        {
+            ProcessGetFileSizeResult( (const char*)sWriteFuncData.pBuffer );
+        }
 
         /* Try to guess if this is a directory. Generally if this is a directory, */
         /* curl will retry with an URL with slash added */
@@ -730,7 +842,7 @@ vsi_l_offset VSICurlHandle::GetFileSize()
         {
             eExists = EXIST_YES;
             fileSize = 0;
-            bIsDirectory = TRUE;
+            bIsDirectory = true;
         }
 
         if (ENABLE_DEBUG)
@@ -742,7 +854,7 @@ vsi_l_offset VSICurlHandle::GetFileSize()
     CPLFree(sWriteFuncHeaderData.pBuffer);
 
     CachedFileProp* cachedFileProp = poFS->GetCachedFileProp(pszURL);
-    cachedFileProp->bHastComputedFileSize = TRUE;
+    cachedFileProp->bHasComputedFileSize = true;
     cachedFileProp->fileSize = fileSize;
     cachedFileProp->eExists = eExists;
     cachedFileProp->bIsDirectory = bIsDirectory;
@@ -754,10 +866,11 @@ vsi_l_offset VSICurlHandle::GetFileSize()
 /*                                 Exists()                             */
 /************************************************************************/
 
-int VSICurlHandle::Exists()
+bool VSICurlHandle::Exists(bool bSetError)
 {
-    if (eExists == EXIST_UNKNOWN)
-        GetFileSize();
+  if (eExists == EXIST_UNKNOWN) {
+        GetFileSize(bSetError);
+  }
     return eExists == EXIST_YES;
 }
 
@@ -774,17 +887,17 @@ vsi_l_offset VSICurlHandle::Tell()
 /*                          DownloadRegion()                            */
 /************************************************************************/
 
-int VSICurlHandle::DownloadRegion(vsi_l_offset startOffset, int nBlocks)
+bool VSICurlHandle::DownloadRegion(vsi_l_offset startOffset, int nBlocks)
 {
     WriteFuncStruct sWriteFuncData;
     WriteFuncStruct sWriteFuncHeaderData;
 
     if (bInterrupted && bStopOnInterrruptUntilUninstall)
-        return FALSE;
+        return false;
 
     CachedFileProp* cachedFileProp = poFS->GetCachedFileProp(pszURL);
     if (cachedFileProp->eExists == EXIST_NO)
-        return FALSE;
+        return false;
 
     CURL* hCurlHandle = poFS->GetCurlHandleFor(pszURL);
     VSICurlSetOptions(hCurlHandle, pszURL);
@@ -796,18 +909,19 @@ int VSICurlHandle::DownloadRegion(vsi_l_offset startOffset, int nBlocks)
     VSICURLInitWriteFuncStruct(&sWriteFuncHeaderData, NULL, NULL, NULL);
     curl_easy_setopt(hCurlHandle, CURLOPT_HEADERDATA, &sWriteFuncHeaderData);
     curl_easy_setopt(hCurlHandle, CURLOPT_HEADERFUNCTION, VSICurlHandleWriteFunc);
-    sWriteFuncHeaderData.bIsHTTP = strncmp(pszURL, "http", 4) == 0;
+    sWriteFuncHeaderData.bIsHTTP = STARTS_WITH(pszURL, "http");
     sWriteFuncHeaderData.nStartOffset = startOffset;
-    sWriteFuncHeaderData.nEndOffset = startOffset + nBlocks * DOWNLOAD_CHUNCK_SIZE - 1;
+    sWriteFuncHeaderData.nEndOffset = startOffset + nBlocks * DOWNLOAD_CHUNK_SIZE - 1;
     /* Some servers don't like we try to read after end-of-file (#5786) */
-    if( cachedFileProp->bHastComputedFileSize && 
+    if( cachedFileProp->bHasComputedFileSize &&
         sWriteFuncHeaderData.nEndOffset >= cachedFileProp->fileSize )
     {
         sWriteFuncHeaderData.nEndOffset = cachedFileProp->fileSize - 1;
     }
 
     char rangeStr[512];
-    sprintf(rangeStr, CPL_FRMT_GUIB "-" CPL_FRMT_GUIB, startOffset,
+    snprintf(rangeStr, sizeof(rangeStr),
+             CPL_FRMT_GUIB "-" CPL_FRMT_GUIB, startOffset,
             sWriteFuncHeaderData.nEndOffset);
 
     if (ENABLE_DEBUG)
@@ -819,8 +933,15 @@ int VSICurlHandle::DownloadRegion(vsi_l_offset startOffset, int nBlocks)
     szCurlErrBuf[0] = '\0';
     curl_easy_setopt(hCurlHandle, CURLOPT_ERRORBUFFER, szCurlErrBuf );
 
+    struct curl_slist* headers = GetCurlHeaders("GET");
+    if( headers != NULL )
+        curl_easy_setopt(hCurlHandle, CURLOPT_HTTPHEADER, headers);
+
     curl_easy_perform(hCurlHandle);
 
+    if( headers != NULL )
+        curl_slist_free_all(headers);
+
     curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, NULL);
     curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION, NULL);
     curl_easy_setopt(hCurlHandle, CURLOPT_HEADERDATA, NULL);
@@ -828,26 +949,34 @@ int VSICurlHandle::DownloadRegion(vsi_l_offset startOffset, int nBlocks)
 
     if (sWriteFuncData.bInterrupted)
     {
-        bInterrupted = TRUE;
+        bInterrupted = true;
 
         CPLFree(sWriteFuncData.pBuffer);
         CPLFree(sWriteFuncHeaderData.pBuffer);
 
-        return FALSE;
+        return false;
     }
 
     long response_code = 0;
     curl_easy_getinfo(hCurlHandle, CURLINFO_HTTP_CODE, &response_code);
 
-    char *content_type = 0;
+    char *content_type = NULL;
     curl_easy_getinfo(hCurlHandle, CURLINFO_CONTENT_TYPE, &content_type);
 
     if (ENABLE_DEBUG)
-        CPLDebug("VSICURL", "Got reponse_code=%ld", response_code);
+        CPLDebug("VSICURL", "Got response_code=%ld", response_code);
 
     if ((response_code != 200 && response_code != 206 &&
          response_code != 225 && response_code != 226 && response_code != 426) || sWriteFuncHeaderData.bError)
     {
+        if( sWriteFuncData.pBuffer != NULL &&
+            CanRestartOnError((const char*)sWriteFuncData.pBuffer) )
+        {
+            CPLFree(sWriteFuncData.pBuffer);
+            CPLFree(sWriteFuncHeaderData.pBuffer);
+            return DownloadRegion(startOffset, nBlocks);
+        }
+
         if (response_code >= 400 && szCurlErrBuf[0] != '\0')
         {
             if (strcmp(szCurlErrBuf, "Couldn't use REST") == 0)
@@ -857,18 +986,18 @@ int VSICurlHandle::DownloadRegion(vsi_l_offset startOffset, int nBlocks)
             else
                 CPLError(CE_Failure, CPLE_AppDefined, "%d: %s", (int)response_code, szCurlErrBuf);
         }
-        if (!bHastComputedFileSize && startOffset == 0)
+        if (!bHasComputedFileSize && startOffset == 0)
         {
-            cachedFileProp->bHastComputedFileSize = bHastComputedFileSize = TRUE;
+            cachedFileProp->bHasComputedFileSize = bHasComputedFileSize = true;
             cachedFileProp->fileSize = fileSize = 0;
             cachedFileProp->eExists = eExists = EXIST_NO;
         }
         CPLFree(sWriteFuncData.pBuffer);
         CPLFree(sWriteFuncHeaderData.pBuffer);
-        return FALSE;
+        return false;
     }
 
-    if (!bHastComputedFileSize && sWriteFuncHeaderData.pBuffer)
+    if (!bHasComputedFileSize && sWriteFuncHeaderData.pBuffer)
     {
         /* Try to retrieve the filesize from the HTTP headers */
         /* if in the form : "Content-Range: bytes x-y/filesize" */
@@ -886,11 +1015,11 @@ int VSICurlHandle::DownloadRegion(vsi_l_offset startOffset, int nBlocks)
                 if (pszSlash)
                 {
                     pszSlash ++;
-                    fileSize = CPLScanUIntBig(pszSlash, strlen(pszSlash));
+                    fileSize = CPLScanUIntBig(pszSlash, static_cast<int>(strlen(pszSlash)));
                 }
             }
         }
-        else if (strncmp(pszURL, "ftp", 3) == 0)
+        else if (STARTS_WITH(pszURL, "ftp"))
         {
             /* Parse 213 answer for FTP protocol */
             char* pszSize = strstr(sWriteFuncHeaderData.pBuffer, "213 ");
@@ -905,7 +1034,7 @@ int VSICurlHandle::DownloadRegion(vsi_l_offset startOffset, int nBlocks)
                     if (pszEOL)
                         *pszEOL = 0;
 
-                    fileSize = CPLScanUIntBig(pszSize, strlen(pszSize));
+                    fileSize = CPLScanUIntBig(pszSize, static_cast<int>(strlen(pszSize)));
                 }
             }
         }
@@ -918,50 +1047,52 @@ int VSICurlHandle::DownloadRegion(vsi_l_offset startOffset, int nBlocks)
                 CPLDebug("VSICURL", "GetFileSize(%s)=" CPL_FRMT_GUIB "  response_code=%d",
                         pszURL, fileSize, (int)response_code);
 
-            bHastComputedFileSize = cachedFileProp->bHastComputedFileSize = TRUE;
+            bHasComputedFileSize = cachedFileProp->bHasComputedFileSize = true;
             cachedFileProp->fileSize = fileSize;
             cachedFileProp->eExists = eExists;
         }
     }
 
-    lastDownloadedOffset = startOffset + nBlocks * DOWNLOAD_CHUNCK_SIZE;
+    lastDownloadedOffset = startOffset + nBlocks * DOWNLOAD_CHUNK_SIZE;
 
     char* pBuffer = sWriteFuncData.pBuffer;
-    int nSize = sWriteFuncData.nSize;
+    size_t nSize = sWriteFuncData.nSize;
 
-    if (nSize > nBlocks * DOWNLOAD_CHUNCK_SIZE)
+    if (nSize > static_cast<size_t>(nBlocks) * DOWNLOAD_CHUNK_SIZE)
     {
         if (ENABLE_DEBUG)
-            CPLDebug("VSICURL", "Got more data than expected : %d instead of %d",
-                     nSize, nBlocks * DOWNLOAD_CHUNCK_SIZE);
+            CPLDebug("VSICURL", "Got more data than expected : %u instead of %d",
+                     static_cast<unsigned int>(nSize), nBlocks * DOWNLOAD_CHUNK_SIZE);
     }
-    
+
     while(nSize > 0)
     {
         //if (ENABLE_DEBUG)
-        //    CPLDebug("VSICURL", "Add region %d - %d", startOffset, MIN(DOWNLOAD_CHUNCK_SIZE, nSize));
-        poFS->AddRegion(pszURL, startOffset, MIN(DOWNLOAD_CHUNCK_SIZE, nSize), pBuffer);
-        startOffset += DOWNLOAD_CHUNCK_SIZE;
-        pBuffer += DOWNLOAD_CHUNCK_SIZE;
-        nSize -= DOWNLOAD_CHUNCK_SIZE;
+        //    CPLDebug("VSICURL", "Add region %d - %d", startOffset, MIN(DOWNLOAD_CHUNK_SIZE, nSize));
+        size_t nChunkSize = MIN((size_t)DOWNLOAD_CHUNK_SIZE, nSize);
+        poFS->AddRegion(pszURL, startOffset, nChunkSize, pBuffer);
+        startOffset += nChunkSize;
+        pBuffer += nChunkSize;
+        nSize -= nChunkSize;
     }
 
     CPLFree(sWriteFuncData.pBuffer);
     CPLFree(sWriteFuncHeaderData.pBuffer);
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                                Read()                                */
 /************************************************************************/
 
-size_t VSICurlHandle::Read( void *pBuffer, size_t nSize, size_t nMemb )
+size_t VSICurlHandle::Read( void * const pBufferIn, size_t const  nSize, size_t const  nMemb )
 {
+    void* pBuffer = pBufferIn;
     size_t nBufferRequestSize = nSize * nMemb;
     if (nBufferRequestSize == 0)
         return 0;
-        
+
     //CPLDebug("VSICURL", "offset=%d, size=%d", (int)curOffset, (int)nBufferRequestSize);
 
     vsi_l_offset iterOffset = curOffset;
@@ -971,8 +1102,8 @@ size_t VSICurlHandle::Read( void *pBuffer, size_t nSize, size_t nMemb )
         if (psRegion == NULL)
         {
             vsi_l_offset nOffsetToDownload =
-                (iterOffset / DOWNLOAD_CHUNCK_SIZE) * DOWNLOAD_CHUNCK_SIZE;
-            
+                (iterOffset / DOWNLOAD_CHUNK_SIZE) * DOWNLOAD_CHUNK_SIZE;
+
             if (nOffsetToDownload == lastDownloadedOffset)
             {
                 /* In case of consecutive reads (of small size), we use a */
@@ -991,17 +1122,16 @@ size_t VSICurlHandle::Read( void *pBuffer, size_t nSize, size_t nMemb )
             /* Ensure that we will request at least the number of blocks */
             /* to satisfy the remaining buffer size to read */
             vsi_l_offset nEndOffsetToDownload =
-                ((iterOffset + nBufferRequestSize) / DOWNLOAD_CHUNCK_SIZE) * DOWNLOAD_CHUNCK_SIZE;
+                ((iterOffset + nBufferRequestSize) / DOWNLOAD_CHUNK_SIZE) * DOWNLOAD_CHUNK_SIZE;
             int nMinBlocksToDownload = 1 + (int)
-                ((nEndOffsetToDownload - nOffsetToDownload) / DOWNLOAD_CHUNCK_SIZE);
+                ((nEndOffsetToDownload - nOffsetToDownload) / DOWNLOAD_CHUNK_SIZE);
             if (nBlocksToDownload < nMinBlocksToDownload)
                 nBlocksToDownload = nMinBlocksToDownload;
-                
-            int i;
+
             /* Avoid reading already cached data */
-            for(i=1;i<nBlocksToDownload;i++)
+            for( int i=1; i < nBlocksToDownload; i++ )
             {
-                if (poFS->GetRegion(pszURL, nOffsetToDownload + i * DOWNLOAD_CHUNCK_SIZE) != NULL)
+                if (poFS->GetRegion(pszURL, nOffsetToDownload + i * DOWNLOAD_CHUNK_SIZE) != NULL)
                 {
                     nBlocksToDownload = i;
                     break;
@@ -1011,17 +1141,17 @@ size_t VSICurlHandle::Read( void *pBuffer, size_t nSize, size_t nMemb )
             if( nBlocksToDownload > N_MAX_REGIONS )
                 nBlocksToDownload = N_MAX_REGIONS;
 
-            if (DownloadRegion(nOffsetToDownload, nBlocksToDownload) == FALSE)
+            if (DownloadRegion(nOffsetToDownload, nBlocksToDownload) == false)
             {
                 if (!bInterrupted)
-                    bEOF = TRUE;
+                    bEOF = true;
                 return 0;
             }
             psRegion = poFS->GetRegion(pszURL, iterOffset);
         }
         if (psRegion == NULL || psRegion->pData == NULL)
         {
-            bEOF = TRUE;
+            bEOF = true;
             return 0;
         }
         int nToCopy = (int) MIN(nBufferRequestSize, psRegion->nSize - (iterOffset - psRegion->nFileOffsetStart));
@@ -1030,7 +1160,7 @@ size_t VSICurlHandle::Read( void *pBuffer, size_t nSize, size_t nMemb )
         pBuffer = (char*) pBuffer + nToCopy;
         iterOffset += nToCopy;
         nBufferRequestSize -= nToCopy;
-        if (psRegion->nSize != DOWNLOAD_CHUNCK_SIZE && nBufferRequestSize != 0)
+        if (psRegion->nSize != (size_t)DOWNLOAD_CHUNK_SIZE && nBufferRequestSize != 0)
         {
             break;
         }
@@ -1038,7 +1168,7 @@ size_t VSICurlHandle::Read( void *pBuffer, size_t nSize, size_t nMemb )
 
     size_t ret = (size_t) ((iterOffset - curOffset) / nSize);
     if (ret != nMemb)
-        bEOF = TRUE;
+        bEOF = true;
 
     curOffset = iterOffset;
 
@@ -1050,9 +1180,9 @@ size_t VSICurlHandle::Read( void *pBuffer, size_t nSize, size_t nMemb )
 /*                           ReadMultiRange()                           */
 /************************************************************************/
 
-int VSICurlHandle::ReadMultiRange( int nRanges, void ** ppData,
-                                   const vsi_l_offset* panOffsets,
-                                   const size_t* panSizes )
+int VSICurlHandle::ReadMultiRange( int const nRanges, void ** const ppData,
+                                   const vsi_l_offset* const panOffsets,
+                                   const size_t* const panSizes )
 {
     WriteFuncStruct sWriteFuncData;
     WriteFuncStruct sWriteFuncHeaderData;
@@ -1065,10 +1195,9 @@ int VSICurlHandle::ReadMultiRange( int nRanges, void ** ppData,
         return -1;
 
     CPLString osRanges, osFirstRange, osLastRange;
-    int i;
     int nMergedRanges = 0;
     vsi_l_offset nTotalReqSize = 0;
-    for(i=0;i<nRanges;i++)
+    for( int i=0; i < nRanges; i++ )
     {
         CPLString osCurRange;
         if (i != 0)
@@ -1113,7 +1242,7 @@ int VSICurlHandle::ReadMultiRange( int nRanges, void ** ppData,
     VSICURLInitWriteFuncStruct(&sWriteFuncHeaderData, NULL, NULL, NULL);
     curl_easy_setopt(hCurlHandle, CURLOPT_HEADERDATA, &sWriteFuncHeaderData);
     curl_easy_setopt(hCurlHandle, CURLOPT_HEADERFUNCTION, VSICurlHandleWriteFunc);
-    sWriteFuncHeaderData.bIsHTTP = strncmp(pszURL, "http", 4) == 0;
+    sWriteFuncHeaderData.bIsHTTP = STARTS_WITH(pszURL, "http");
     sWriteFuncHeaderData.bMultiRange = nMergedRanges > 1;
     if (nMergedRanges == 1)
     {
@@ -1136,8 +1265,15 @@ int VSICurlHandle::ReadMultiRange( int nRanges, void ** ppData,
     szCurlErrBuf[0] = '\0';
     curl_easy_setopt(hCurlHandle, CURLOPT_ERRORBUFFER, szCurlErrBuf );
 
+    struct curl_slist* headers = GetCurlHeaders("GET");
+    if( headers != NULL )
+        curl_easy_setopt(hCurlHandle, CURLOPT_HTTPHEADER, headers);
+
     curl_easy_perform(hCurlHandle);
 
+    if( headers != NULL )
+        curl_slist_free_all(headers);
+
     curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, NULL);
     curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION, NULL);
     curl_easy_setopt(hCurlHandle, CURLOPT_HEADERDATA, NULL);
@@ -1145,18 +1281,18 @@ int VSICurlHandle::ReadMultiRange( int nRanges, void ** ppData,
 
     if (sWriteFuncData.bInterrupted)
     {
-        bInterrupted = TRUE;
+        bInterrupted = true;
 
         CPLFree(sWriteFuncData.pBuffer);
         CPLFree(sWriteFuncHeaderData.pBuffer);
 
         return -1;
     }
-    
+
     long response_code = 0;
     curl_easy_getinfo(hCurlHandle, CURLINFO_HTTP_CODE, &response_code);
 
-    char *content_type = 0;
+    char *content_type = NULL;
     curl_easy_getinfo(hCurlHandle, CURLINFO_CONTENT_TYPE, &content_type);
 
     if ((response_code != 200 && response_code != 206 &&
@@ -1172,9 +1308,9 @@ int VSICurlHandle::ReadMultiRange( int nRanges, void ** ppData,
                 CPLError(CE_Failure, CPLE_AppDefined, "%d: %s", (int)response_code, szCurlErrBuf);
         }
         /*
-        if (!bHastComputedFileSize && startOffset == 0)
+        if (!bHasComputedFileSize && startOffset == 0)
         {
-            cachedFileProp->bHastComputedFileSize = bHastComputedFileSize = TRUE;
+            cachedFileProp->bHasComputedFileSize = bHasComputedFileSize = true;
             cachedFileProp->fileSize = fileSize = 0;
             cachedFileProp->eExists = eExists = EXIST_NO;
         }
@@ -1185,7 +1321,7 @@ int VSICurlHandle::ReadMultiRange( int nRanges, void ** ppData,
     }
 
     char* pBuffer = sWriteFuncData.pBuffer;
-    int nSize = sWriteFuncData.nSize;
+    size_t nSize = sWriteFuncData.nSize;
 
     int nRet = -1;
     char* pszBoundary;
@@ -1201,11 +1337,11 @@ int VSICurlHandle::ReadMultiRange( int nRanges, void ** ppData,
 
     if (nMergedRanges == 1)
     {
-        int nAccSize = 0;
+        size_t nAccSize = 0;
         if ((vsi_l_offset)nSize < nTotalReqSize)
             goto end;
 
-        for(i=0;i<nRanges;i++)
+        for( int i=0; i < nRanges; i++ )
         {
             memcpy(ppData[i], pBuffer + nAccSize, panSizes[i]);
             nAccSize += panSizes[i];
@@ -1227,7 +1363,7 @@ int VSICurlHandle::ReadMultiRange( int nRanges, void ** ppData,
                   "Content-Type: multipart/byteranges; boundary=" );
         goto end;
     }
-    
+
     pszBoundary += strlen( "Content-Type: multipart/byteranges; boundary=" );
 
     pszEOL = strchr(pszBoundary, '\r');
@@ -1275,11 +1411,11 @@ int VSICurlHandle::ReadMultiRange( int nRanges, void ** ppData,
 /* -------------------------------------------------------------------- */
 /*      Collect headers.                                                */
 /* -------------------------------------------------------------------- */
-        int bExpectedRange = FALSE;
+        bool bExpectedRange = false;
 
         while( *pszNext != '\n' && *pszNext != '\r' && *pszNext != '\0' )
         {
-            char *pszEOL = strstr(pszNext,"\n");
+            pszEOL = strstr(pszNext,"\n");
 
             if( pszEOL == NULL )
             {
@@ -1289,16 +1425,16 @@ int VSICurlHandle::ReadMultiRange( int nRanges, void ** ppData,
             }
 
             *pszEOL = '\0';
-            int bRestoreAntislashR = FALSE;
+            bool bRestoreAntislashR = false;
             if (pszEOL - pszNext > 1 && pszEOL[-1] == '\r')
             {
-                bRestoreAntislashR = TRUE;
+                bRestoreAntislashR = true;
                 pszEOL[-1] = '\0';
             }
 
-            if (EQUALN(pszNext, "Content-Range: bytes ", strlen("Content-Range: bytes ")))
+            if (STARTS_WITH_CI(pszNext, "Content-Range: bytes "))
             {
-                bExpectedRange = TRUE; /* FIXME */
+                bExpectedRange = true; /* FIXME */
             }
 
             if (bRestoreAntislashR)
@@ -1325,7 +1461,7 @@ int VSICurlHandle::ReadMultiRange( int nRanges, void ** ppData,
 /* -------------------------------------------------------------------- */
         size_t nBytesAvail = nSize - (pszNext - pBuffer);
 
-        while(TRUE)
+        while(true)
         {
             if (nBytesAvail < panSizes[iRange])
             {
@@ -1365,7 +1501,7 @@ int VSICurlHandle::ReadMultiRange( int nRanges, void ** ppData,
         }
 
         pszNext += strlen(osBoundary);
-        if( strncmp(pszNext,"--",2) == 0 )
+        if( STARTS_WITH(pszNext, "--") )
         {
             /* End of multipart */
             break;
@@ -1456,8 +1592,7 @@ VSICurlFilesystemHandler::VSICurlFilesystemHandler()
 
 VSICurlFilesystemHandler::~VSICurlFilesystemHandler()
 {
-    int i;
-    for(i=0;i<nRegions;i++)
+    for( int i=0; i < nRegions; i++ )
     {
         CPLFree(papsRegions[i]->pData);
         CPLFree(papsRegions[i]);
@@ -1523,7 +1658,7 @@ CURL* VSICurlFilesystemHandler::GetCurlHandleFor(CPLString osURL)
             pszEndOfServ = strchr(pszEndOfServ, '/');
         if (pszEndOfServ == NULL)
             pszURL = pszURL + strlen(pszURL);
-        int bReinitConnection = strncmp(psCachedConnection->osURL,
+        bool bReinitConnection = strncmp(psCachedConnection->osURL,
                                         pszURL, pszEndOfServ-pszURL) != 0;
 
         if (bReinitConnection)
@@ -1543,24 +1678,26 @@ CURL* VSICurlFilesystemHandler::GetCurlHandleFor(CPLString osURL)
 /*                   GetRegionFromCacheDisk()                           */
 /************************************************************************/
 
-const CachedRegion* 
+const CachedRegion*
 VSICurlFilesystemHandler::GetRegionFromCacheDisk(const char* pszURL,
                                                  vsi_l_offset nFileOffsetStart)
 {
-    nFileOffsetStart = (nFileOffsetStart / DOWNLOAD_CHUNCK_SIZE) * DOWNLOAD_CHUNCK_SIZE;
+    nFileOffsetStart = (nFileOffsetStart / DOWNLOAD_CHUNK_SIZE) * DOWNLOAD_CHUNK_SIZE;
     VSILFILE* fp = VSIFOpenL(VSICurlGetCacheFileName(), "rb");
     if (fp)
     {
         unsigned long   pszURLHash = CPLHashSetHashStr(pszURL);
-        unsigned long   pszURLHashCached;
         vsi_l_offset    nFileOffsetStartCached;
-        size_t          nSizeCached;
-        while(TRUE)
+        while(true)
         {
-            if (VSIFReadL(&pszURLHashCached, 1, sizeof(unsigned long), fp) == 0)
+            unsigned long pszURLHashCached = 0;
+            if (VSIFReadL(&pszURLHashCached, sizeof(unsigned long), 1, fp) == 0)
+                break;
+            if( VSIFReadL(&nFileOffsetStartCached, sizeof(vsi_l_offset), 1, fp) == 0)
+                break;
+            size_t nSizeCached = 0;
+            if( VSIFReadL(&nSizeCached, sizeof(size_t), 1, fp) == 0)
                 break;
-            VSIFReadL(&nFileOffsetStartCached, 1, sizeof(vsi_l_offset), fp);
-            VSIFReadL(&nSizeCached, 1, sizeof(size_t), fp);
             if (pszURLHash == pszURLHashCached &&
                 nFileOffsetStart == nFileOffsetStartCached)
             {
@@ -1569,7 +1706,11 @@ VSICurlFilesystemHandler::GetRegionFromCacheDisk(const char* pszURL,
                 if (nSizeCached)
                 {
                     char* pBuffer = (char*) CPLMalloc(nSizeCached);
-                    VSIFReadL(pBuffer, 1, nSizeCached, fp);
+                    if( VSIFReadL(pBuffer, 1, nSizeCached, fp) != nSizeCached )
+                    {
+                        CPLFree(pBuffer);
+                        break;
+                    }
                     AddRegion(pszURL, nFileOffsetStart, nSizeCached, pBuffer);
                     CPLFree(pBuffer);
                 }
@@ -1577,15 +1718,16 @@ VSICurlFilesystemHandler::GetRegionFromCacheDisk(const char* pszURL,
                 {
                     AddRegion(pszURL, nFileOffsetStart, 0, NULL);
                 }
-                VSIFCloseL(fp);
+                CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
                 return GetRegion(pszURL, nFileOffsetStart);
             }
             else
             {
-                VSIFSeekL(fp, nSizeCached, SEEK_CUR);
+                if( VSIFSeekL(fp, nSizeCached, SEEK_CUR) != 0 )
+                    break;
             }
         }
-        VSIFCloseL(fp);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
     }
     return NULL;
 }
@@ -1600,25 +1742,28 @@ void VSICurlFilesystemHandler::AddRegionToCacheDisk(CachedRegion* psRegion)
     VSILFILE* fp = VSIFOpenL(VSICurlGetCacheFileName(), "r+b");
     if (fp)
     {
-        unsigned long   pszURLHashCached;
-        vsi_l_offset    nFileOffsetStartCached;
-        size_t          nSizeCached;
-        while(TRUE)
+        while(true)
         {
+            unsigned long pszURLHashCached = 0;
             if (VSIFReadL(&pszURLHashCached, 1, sizeof(unsigned long), fp) == 0)
                 break;
-            VSIFReadL(&nFileOffsetStartCached, 1, sizeof(vsi_l_offset), fp);
-            VSIFReadL(&nSizeCached, 1, sizeof(size_t), fp);
+            vsi_l_offset nFileOffsetStartCached = 0;
+            if( VSIFReadL(&nFileOffsetStartCached, sizeof(vsi_l_offset), 1, fp) == 0 )
+                break;
+            size_t nSizeCached = 0;
+            if( VSIFReadL(&nSizeCached, sizeof(size_t), 1, fp) == 0 )
+                break;
             if (psRegion->pszURLHash == pszURLHashCached &&
                 psRegion->nFileOffsetStart == nFileOffsetStartCached)
             {
                 CPLAssert(psRegion->nSize == nSizeCached);
-                VSIFCloseL(fp);
+                CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
                 return;
             }
             else
             {
-                VSIFSeekL(fp, nSizeCached, SEEK_CUR);
+                if( VSIFSeekL(fp, nSizeCached, SEEK_CUR) != 0 )
+                    break;
             }
         }
     }
@@ -1630,13 +1775,13 @@ void VSICurlFilesystemHandler::AddRegionToCacheDisk(CachedRegion* psRegion)
     {
         if (ENABLE_DEBUG)
              CPLDebug("VSICURL", "Write data at offset " CPL_FRMT_GUIB " to disk" , psRegion->nFileOffsetStart);
-        VSIFWriteL(&psRegion->pszURLHash, 1, sizeof(unsigned long), fp);
-        VSIFWriteL(&psRegion->nFileOffsetStart, 1, sizeof(vsi_l_offset), fp);
-        VSIFWriteL(&psRegion->nSize, 1, sizeof(size_t), fp);
+        CPL_IGNORE_RET_VAL(VSIFWriteL(&psRegion->pszURLHash, 1, sizeof(unsigned long), fp));
+        CPL_IGNORE_RET_VAL(VSIFWriteL(&psRegion->nFileOffsetStart, 1, sizeof(vsi_l_offset), fp));
+        CPL_IGNORE_RET_VAL(VSIFWriteL(&psRegion->nSize, 1, sizeof(size_t), fp));
         if (psRegion->nSize)
-            VSIFWriteL(psRegion->pData, 1, psRegion->nSize, fp);
+            CPL_IGNORE_RET_VAL(VSIFWriteL(psRegion->pData, 1, psRegion->nSize, fp));
 
-        VSIFCloseL(fp);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
     }
     return;
 }
@@ -1653,9 +1798,9 @@ const CachedRegion* VSICurlFilesystemHandler::GetRegion(const char* pszURL,
 
     unsigned long   pszURLHash = CPLHashSetHashStr(pszURL);
 
-    nFileOffsetStart = (nFileOffsetStart / DOWNLOAD_CHUNCK_SIZE) * DOWNLOAD_CHUNCK_SIZE;
-    int i;
-    for(i=0;i<nRegions;i++)
+    nFileOffsetStart = (nFileOffsetStart / DOWNLOAD_CHUNK_SIZE) * DOWNLOAD_CHUNK_SIZE;
+
+    for( int i=0; i < nRegions; i++ )
     {
         CachedRegion* psRegion = papsRegions[i];
         if (psRegion->pszURLHash == pszURLHash &&
@@ -1725,9 +1870,9 @@ CachedFileProp*  VSICurlFilesystemHandler::GetCachedFileProp(const char* pszURL)
     {
         cachedFileProp = (CachedFileProp*) CPLMalloc(sizeof(CachedFileProp));
         cachedFileProp->eExists = EXIST_UNKNOWN;
-        cachedFileProp->bHastComputedFileSize = FALSE;
+        cachedFileProp->bHasComputedFileSize = false;
         cachedFileProp->fileSize = 0;
-        cachedFileProp->bIsDirectory = FALSE;
+        cachedFileProp->bIsDirectory = false;
         cacheFileSize[pszURL] = cachedFileProp;
     }
 
@@ -1735,11 +1880,37 @@ CachedFileProp*  VSICurlFilesystemHandler::GetCachedFileProp(const char* pszURL)
 }
 
 /************************************************************************/
+/*                    InvalidateCachedFileProp()                        */
+/************************************************************************/
+
+void VSICurlFilesystemHandler::InvalidateCachedFileProp(const char* pszURL)
+{
+    CPLMutexHolder oHolder( &hMutex );
+
+    std::map<CPLString, CachedFileProp*>::iterator oIter = cacheFileSize.find(pszURL);
+    if( oIter != cacheFileSize.end() )
+    {
+        CPLFree(oIter->second);
+        cacheFileSize.erase(oIter);
+    }
+}
+
+/************************************************************************/
+/*                          CreateFileHandle()                          */
+/************************************************************************/
+
+VSICurlHandle* VSICurlFilesystemHandler::CreateFileHandle(const char* pszURL)
+{
+    return new VSICurlHandle(this, pszURL);
+}
+
+/************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
 
-VSIVirtualHandle* VSICurlFilesystemHandler::Open( const char *pszFilename, 
-                                                  const char *pszAccess)
+VSIVirtualHandle* VSICurlFilesystemHandler::Open( const char *pszFilename,
+                                                  const char *pszAccess,
+                                                  bool bSetError )
 {
     if (strchr(pszAccess, 'w') != NULL ||
         strchr(pszAccess, '+') != NULL)
@@ -1751,16 +1922,16 @@ VSIVirtualHandle* VSICurlFilesystemHandler::Open( const char *pszFilename,
 
     const char* pszOptionVal =
         CPLGetConfigOption( "GDAL_DISABLE_READDIR_ON_OPEN", "NO" );
-    int bSkipReadDir = EQUAL(pszOptionVal, "EMPTY_DIR") ||
-                       CSLTestBoolean(pszOptionVal);
+    const bool bSkipReadDir = EQUAL(pszOptionVal, "EMPTY_DIR") ||
+                              CSLTestBoolean(pszOptionVal);
 
     CPLString osFilename(pszFilename);
-    int bGotFileList = TRUE;
+    bool bGotFileList = true;
     if (strchr(CPLGetFilename(osFilename), '.') != NULL &&
-        strncmp(CPLGetExtension(osFilename), "zip", 3) != 0 && !bSkipReadDir)
+        !STARTS_WITH(CPLGetExtension(osFilename), "zip") && !bSkipReadDir)
     {
-        char** papszFileList = ReadDir(CPLGetDirname(osFilename), &bGotFileList);
-        int bFound = (VSICurlIsFileInList(papszFileList, CPLGetFilename(osFilename)) != -1);
+        char** papszFileList = ReadDirInternal(CPLGetDirname(osFilename), 0, &bGotFileList);
+        const bool bFound = (VSICurlIsFileInList(papszFileList, CPLGetFilename(osFilename)) != -1);
         CSLDestroy(papszFileList);
         if (bGotFileList && !bFound)
         {
@@ -1768,14 +1939,16 @@ VSIVirtualHandle* VSICurlFilesystemHandler::Open( const char *pszFilename,
         }
     }
 
-    VSICurlHandle* poHandle = new VSICurlHandle( this, osFilename + strlen("/vsicurl/"));
+    VSICurlHandle* poHandle = CreateFileHandle(osFilename + strlen(GetFSPrefix()));
+    if( poHandle == NULL )
+        return NULL;
     if (!bGotFileList)
     {
         /* If we didn't get a filelist, check that the file really exists */
-        if (!poHandle->Exists())
+        if (!poHandle->Exists(bSetError))
         {
             delete poHandle;
-            poHandle = NULL;
+            return NULL;
         }
     }
 
@@ -1796,12 +1969,12 @@ VSIVirtualHandle* VSICurlFilesystemHandler::Open( const char *pszFilename,
 static char *VSICurlParserFindEOL( char *pszData )
 
 {
-    while( *pszData != '\0' && *pszData != '\n' && !EQUALN(pszData,"<br>",4) )
+    while( *pszData != '\0' && *pszData != '\n' && !STARTS_WITH_CI(pszData, "<br>") )
         pszData++;
 
     if( *pszData == '\0' )
         return NULL;
-    else 
+    else
         return pszData;
 }
 
@@ -1815,13 +1988,12 @@ static const char* const apszMonths[] = { "January", "February", "March",
                                           "August", "September", "October",
                                           "November", "December" };
 
-static int VSICurlParseHTMLDateTimeFileSize(const char* pszStr,
+static bool VSICurlParseHTMLDateTimeFileSize(const char* pszStr,
                                             struct tm& brokendowntime,
                                             GUIntBig& nFileSize,
                                             GIntBig& mTime)
 {
-    int iMonth;
-    for(iMonth=0;iMonth<12;iMonth++)
+    for(int iMonth=0;iMonth<12;iMonth++)
     {
         char szMonth[32];
         szMonth[0] = '-';
@@ -1851,10 +2023,10 @@ static int VSICurlParseHTMLDateTimeFileSize(const char* pszStr,
                     brokendowntime.tm_min = nMin;
                     mTime = CPLYMDHMSToUnixTime(&brokendowntime);
 
-                    return TRUE;
+                    return true;
                 }
             }
-            return FALSE;
+            return false;
         }
 
         /* Microsoft IIS */
@@ -1864,7 +2036,7 @@ static int VSICurlParseHTMLDateTimeFileSize(const char* pszStr,
         pszMonthFound = strstr(pszStr, szMonth);
         if (pszMonthFound)
         {
-            int nLenMonth = strlen(apszMonths[iMonth]);
+            int nLenMonth = static_cast<int>(strlen(apszMonths[iMonth]));
             if (pszMonthFound - pszStr > 2 &&
                 pszMonthFound[-1] != ',' &&
                 pszMonthFound[-2] != ' ' &&
@@ -1884,9 +2056,9 @@ static int VSICurlParseHTMLDateTimeFileSize(const char* pszStr,
                     nCurOffset += 2 + 1;
                 int nMin = atoi(pszMonthFound + nCurOffset);
                 nCurOffset += 2 + 1;
-                if (strncmp(pszMonthFound + nCurOffset, "p.m.", 4) == 0)
+                if (STARTS_WITH(pszMonthFound + nCurOffset, "p.m."))
                     nHour += 12;
-                else if (strncmp(pszMonthFound + nCurOffset, "a.m.", 4) != 0)
+                else if (!STARTS_WITH(pszMonthFound + nCurOffset, "a.m."))
                     nHour = -1;
                 nCurOffset += 4;
 
@@ -1894,7 +2066,7 @@ static int VSICurlParseHTMLDateTimeFileSize(const char* pszStr,
                 while(*pszFilesize == ' ')
                     pszFilesize ++;
                 if (*pszFilesize >= '1' && *pszFilesize <= '9')
-                    nFileSize = CPLScanUIntBig(pszFilesize, strlen(pszFilesize));
+                    nFileSize = CPLScanUIntBig(pszFilesize, static_cast<int>(strlen(pszFilesize)));
 
                 if (nDay >= 1 && nDay <= 31 && nYear >= 1900 &&
                     nHour >= 0 && nHour <= 24 && nMin >= 0 && nMin < 60)
@@ -1906,7 +2078,7 @@ static int VSICurlParseHTMLDateTimeFileSize(const char* pszStr,
                     brokendowntime.tm_min = nMin;
                     mTime = CPLYMDHMSToUnixTime(&brokendowntime);
 
-                    return TRUE;
+                    return true;
                 }
                 nFileSize = 0;
             }
@@ -1926,9 +2098,9 @@ static int VSICurlParseHTMLDateTimeFileSize(const char* pszStr,
                 nCurOffset += 2 + 1;
                 int nMin = atoi(pszMonthFound + nCurOffset);
                 nCurOffset += 2 + 1;
-                if (strncmp(pszMonthFound + nCurOffset, "PM", 2) == 0)
+                if (STARTS_WITH(pszMonthFound + nCurOffset, "PM"))
                     nHour += 12;
-                else if (strncmp(pszMonthFound + nCurOffset, "AM", 2) != 0)
+                else if (!STARTS_WITH(pszMonthFound + nCurOffset, "AM"))
                     nHour = -1;
                 nCurOffset += 2;
 
@@ -1936,7 +2108,7 @@ static int VSICurlParseHTMLDateTimeFileSize(const char* pszStr,
                 while(*pszFilesize == ' ')
                     pszFilesize ++;
                 if (*pszFilesize >= '1' && *pszFilesize <= '9')
-                    nFileSize = CPLScanUIntBig(pszFilesize, strlen(pszFilesize));
+                    nFileSize = CPLScanUIntBig(pszFilesize, static_cast<int>(strlen(pszFilesize)));
 
                 if (nDay >= 1 && nDay <= 31 && nYear >= 1900 &&
                     nHour >= 0 && nHour <= 24 && nMin >= 0 && nMin < 60)
@@ -1948,15 +2120,15 @@ static int VSICurlParseHTMLDateTimeFileSize(const char* pszStr,
                     brokendowntime.tm_min = nMin;
                     mTime = CPLYMDHMSToUnixTime(&brokendowntime);
 
-                    return TRUE;
+                    return true;
                 }
                 nFileSize = 0;
             }
-            return FALSE;
+            return false;
         }
     }
 
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
@@ -1966,45 +2138,36 @@ static int VSICurlParseHTMLDateTimeFileSize(const char* pszStr,
 /************************************************************************/
 
 char** VSICurlFilesystemHandler::ParseHTMLFileList(const char* pszFilename,
-                                       char* pszData,
-                                       int* pbGotFileList)
+                                                   int nMaxFiles,
+                                                   char* pszData,
+                                                   bool* pbGotFileList)
 {
-    CPLStringList oFileList;
-    char* pszLine = pszData;
-    char* c;
-    int nCount = 0;
-    int bIsHTMLDirList = FALSE;
-    CPLString osExpectedString;
-    CPLString osExpectedString2;
-    CPLString osExpectedString3;
-    CPLString osExpectedString4;
-    CPLString osExpectedString_unescaped;
-    
-    *pbGotFileList = FALSE;
+    *pbGotFileList = false;
 
     const char* pszDir;
-    if (EQUALN(pszFilename, "/vsicurl/http://", strlen("/vsicurl/http://")))
+    if (STARTS_WITH_CI(pszFilename, "/vsicurl/http://"))
         pszDir = strchr(pszFilename + strlen("/vsicurl/http://"), '/');
-    else if (EQUALN(pszFilename, "/vsicurl/https://", strlen("/vsicurl/https://")))
+    else if (STARTS_WITH_CI(pszFilename, "/vsicurl/https://"))
         pszDir = strchr(pszFilename + strlen("/vsicurl/https://"), '/');
     else
         pszDir = strchr(pszFilename + strlen("/vsicurl/ftp://"), '/');
     if (pszDir == NULL)
         pszDir = "";
+
     /* Apache */
-    osExpectedString = "<title>Index of ";
+    CPLString osExpectedString = "<title>Index of ";
     osExpectedString += pszDir;
     osExpectedString += "</title>";
     /* shttpd */
-    osExpectedString2 = "<title>Index of ";
+    CPLString osExpectedString2 = "<title>Index of ";
     osExpectedString2 += pszDir;
     osExpectedString2 += "/</title>";
     /* FTP */
-    osExpectedString3 = "FTP Listing of ";
+    CPLString osExpectedString3 = "FTP Listing of ";
     osExpectedString3 += pszDir;
     osExpectedString3 += "/";
     /* Apache 1.3.33 */
-    osExpectedString4 = "<TITLE>Index of ";
+    CPLString osExpectedString4 = "<TITLE>Index of ";
     osExpectedString4 += pszDir;
     osExpectedString4 += "</TITLE>";
 
@@ -2012,6 +2175,7 @@ char** VSICurlFilesystemHandler::ParseHTMLFileList(const char* pszFilename,
     /* has "<title>Index of /srtm/SRTM_image_sample/picture examples</title>" so we must */
     /* try unescaped %20 also */
     /* Similar with http://datalib.usask.ca/gis/Data/Central_America_goodbutdoweown%3f/ */
+    CPLString osExpectedString_unescaped;
     if (strchr(pszDir, '%'))
     {
         char* pszUnescapedDir = CPLUnescapeString(pszDir, NULL, CPLES_URL);
@@ -2021,8 +2185,13 @@ char** VSICurlFilesystemHandler::ParseHTMLFileList(const char* pszFilename,
         CPLFree(pszUnescapedDir);
     }
 
+    char* c;
+    int nCount = 0;
     int nCountTable = 0;
-    
+    CPLStringList oFileList;
+    char* pszLine = pszData;
+    bool bIsHTMLDirList = false;
+
     while( (c = VSICurlParserFindEOL( pszLine )) != NULL )
     {
         *c = 0;
@@ -2034,7 +2203,7 @@ char** VSICurlFilesystemHandler::ParseHTMLFileList(const char* pszFilename,
             nCountTable ++;
             if (nCountTable == 2)
             {
-                *pbGotFileList = FALSE;
+                *pbGotFileList = false;
                 return NULL;
             }
         }
@@ -2046,8 +2215,8 @@ char** VSICurlFilesystemHandler::ParseHTMLFileList(const char* pszFilename,
              strstr(pszLine, osExpectedString4.c_str()) ||
              (osExpectedString_unescaped.size() != 0 && strstr(pszLine, osExpectedString_unescaped.c_str()))))
         {
-            bIsHTMLDirList = TRUE;
-            *pbGotFileList = TRUE;
+            bIsHTMLDirList = true;
+            *pbGotFileList = true;
         }
         /* Subversion HTTP listing */
         /* or Microsoft-IIS/6.0 listing (e.g. http://ortho.linz.govt.nz/tifs/2005_06/) */
@@ -2071,8 +2240,8 @@ char** VSICurlFilesystemHandler::ParseHTMLFileList(const char* pszFilename,
                         *pszTmp = 0;
                     if (strstr(pszDir, pszSubDir))
                     {
-                        bIsHTMLDirList = TRUE;
-                        *pbGotFileList = TRUE;
+                        bIsHTMLDirList = true;
+                        *pbGotFileList = true;
                     }
                 }
             }
@@ -2087,7 +2256,7 @@ char** VSICurlFilesystemHandler::ParseHTMLFileList(const char* pszFilename,
                 beginFilename = strstr(pszLine, "<A HREF=\"");
             beginFilename += strlen("<a href=\"");
             char *endQuote = strchr(beginFilename, '"');
-            if (endQuote && strncmp(beginFilename, "?C=", 3) != 0 && strncmp(beginFilename, "?N=", 3) != 0)
+            if (endQuote && !STARTS_WITH(beginFilename, "?C=") && !STARTS_WITH(beginFilename, "?N="))
             {
                 struct tm brokendowntime;
                 memset(&brokendowntime, 0, sizeof(brokendowntime));
@@ -2103,13 +2272,13 @@ char** VSICurlFilesystemHandler::ParseHTMLFileList(const char* pszFilename,
 
                 /* Remove trailing slash, that are returned for directories by */
                 /* Apache */
-                int bIsDirectory = FALSE;
+                bool bIsDirectory = false;
                 if (endQuote[-1] == '/')
                 {
-                    bIsDirectory = TRUE;
+                    bIsDirectory = true;
                     endQuote[-1] = 0;
                 }
-                
+
                 /* shttpd links include slashes from the root directory. Skip them */
                 while(strchr(beginFilename, '/'))
                     beginFilename = strchr(beginFilename, '/') + 1;
@@ -2122,17 +2291,20 @@ char** VSICurlFilesystemHandler::ParseHTMLFileList(const char* pszFilename,
                     CachedFileProp* cachedFileProp = GetCachedFileProp(osCachedFilename);
                     cachedFileProp->eExists = EXIST_YES;
                     cachedFileProp->bIsDirectory = bIsDirectory;
-                    cachedFileProp->mTime = mTime;
-                    cachedFileProp->bHastComputedFileSize = nFileSize > 0;
+                    cachedFileProp->mTime = static_cast<time_t>(mTime);
+                    cachedFileProp->bHasComputedFileSize = nFileSize > 0;
                     cachedFileProp->fileSize = nFileSize;
 
                     oFileList.AddString( beginFilename );
                     if (ENABLE_DEBUG)
                         CPLDebug("VSICURL", "File[%d] = %s, is_dir = %d, size = " CPL_FRMT_GUIB ", time = %04d/%02d/%02d %02d:%02d:%02d",
-                                nCount, beginFilename, bIsDirectory, nFileSize,
+                                nCount, beginFilename, bIsDirectory ? 1 : 0, nFileSize,
                                 brokendowntime.tm_year + 1900, brokendowntime.tm_mon + 1, brokendowntime.tm_mday,
                                 brokendowntime.tm_hour, brokendowntime.tm_min, brokendowntime.tm_sec);
                     nCount ++;
+
+                    if( nMaxFiles > 0 && oFileList.Count() > nMaxFiles )
+                        break;
                 }
             }
         }
@@ -2142,6 +2314,101 @@ char** VSICurlFilesystemHandler::ParseHTMLFileList(const char* pszFilename,
     return oFileList.StealList();
 }
 
+/************************************************************************/
+/*                          AnalyseS3FileList()                         */
+/************************************************************************/
+
+#include "cpl_minixml.h"
+void VSICurlFilesystemHandler::AnalyseS3FileList( const CPLString& osBaseURL,
+                                        const char* pszXML,
+                                        CPLStringList& osFileList,
+                                        int nMaxFiles,
+                                        bool& bIsTruncated,
+                                        CPLString& osNextMarker )
+{
+    //CPLDebug("S3", "%s", pszXML);
+    osNextMarker = "";
+    bIsTruncated = false;
+    CPLXMLNode* psTree = CPLParseXMLString(pszXML);
+    if( psTree == NULL )
+        return;
+    CPLXMLNode* psListBucketResult = CPLGetXMLNode(psTree, "=ListBucketResult");
+    if( psListBucketResult )
+    {
+        CPLString osPrefix = CPLGetXMLValue(psListBucketResult, "Prefix", "");
+        CPLXMLNode* psIter = psListBucketResult->psChild;
+        for( ; psIter != NULL; psIter = psIter->psNext )
+        {
+            if( psIter->eType != CXT_Element )
+                continue;
+            if( strcmp(psIter->pszValue, "Contents") == 0 )
+            {
+                const char* pszKey = CPLGetXMLValue(psIter, "Key", NULL);
+                if( pszKey && strlen(pszKey) > osPrefix.size() )
+                {
+                    CPLString osCachedFilename = osBaseURL + pszKey;
+                    //CPLDebug("S3", "Cache %s", osCachedFilename.c_str());
+
+                    CachedFileProp* cachedFileProp = GetCachedFileProp(osCachedFilename);
+                    cachedFileProp->eExists = EXIST_YES;
+                    cachedFileProp->bHasComputedFileSize = true;
+                    cachedFileProp->fileSize = (GUIntBig)CPLAtoGIntBig(CPLGetXMLValue(psIter, "Size", "0"));
+                    cachedFileProp->bIsDirectory = false;
+                    cachedFileProp->mTime = 0;
+
+                    int nYear, nMonth, nDay, nHour, nMin, nSec;
+                    if( sscanf( CPLGetXMLValue(psIter, "LastModified", ""),
+                                "%04d-%02d-%02dT%02d:%02d:%02d",
+                                &nYear, &nMonth, &nDay, &nHour, &nMin, &nSec ) == 6 )
+                    {
+                        struct tm brokendowntime;
+                        brokendowntime.tm_year = nYear - 1900;
+                        brokendowntime.tm_mon = nMonth - 1;
+                        brokendowntime.tm_mday = nDay;
+                        brokendowntime.tm_hour = nHour;
+                        brokendowntime.tm_min = nMin;
+                        brokendowntime.tm_sec = nSec;
+                        cachedFileProp->mTime = static_cast<time_t>(CPLYMDHMSToUnixTime(&brokendowntime));
+                    }
+
+                    osFileList.AddString(pszKey + osPrefix.size());
+                }
+            }
+            else if( strcmp(psIter->pszValue, "CommonPrefixes") == 0 )
+            {
+                const char* pszKey = CPLGetXMLValue(psIter, "Prefix", NULL);
+                if( pszKey && strncmp(pszKey, osPrefix, osPrefix.size()) == 0  )
+                {
+                    CPLString osKey = pszKey;
+                    if( osKey.size() && osKey[osKey.size()-1] == '/' )
+                        osKey.resize(osKey.size()-1);
+                    if( osKey.size() > osPrefix.size() )
+                    {
+                        CPLString osCachedFilename = osBaseURL + osKey;
+                        //CPLDebug("S3", "Cache %s", osCachedFilename.c_str());
+
+                        CachedFileProp* cachedFileProp = GetCachedFileProp(osCachedFilename);
+                        cachedFileProp->eExists = EXIST_YES;
+                        cachedFileProp->bIsDirectory = true;
+                        cachedFileProp->mTime = 0;
+
+                        osFileList.AddString(osKey.c_str() + osPrefix.size());
+                    }
+                }
+            }
+
+            if( nMaxFiles > 0 && osFileList.Count() > nMaxFiles )
+                break;
+        }
+
+        if( !(nMaxFiles > 0 && osFileList.Count() > nMaxFiles) )
+        {
+            osNextMarker = CPLGetXMLValue(psListBucketResult, "NextMarker", "");
+            bIsTruncated = CPL_TO_BOOL(CSLTestBoolean(CPLGetXMLValue(psListBucketResult, "IsTruncated", "false")));
+        }
+    }
+    CPLDestroyXMLNode(psTree);
+}
 
 /************************************************************************/
 /*                         VSICurlGetToken()                            */
@@ -2185,46 +2452,46 @@ lrwxrwxrwx    1 ftp      ftp            28 Jun 14 14:13 MPlayer -> mirrors/mplay
 drwxr-xr-x  280 1003  1003  6656 Aug 26 04:17 gnu
 */
 
-static int VSICurlParseFullFTPLine(char* pszLine,
+static bool VSICurlParseFullFTPLine(char* pszLine,
                                    char*& pszFilename,
-                                   int& bSizeValid,
+                                   bool& bSizeValid,
                                    GUIntBig& nSize,
-                                   int& bIsDirectory,
+                                   bool& bIsDirectory,
                                    GIntBig& nUnixTime)
 {
     char* pszNextToken = pszLine;
     char* pszPermissions = VSICurlGetToken(pszNextToken, &pszNextToken);
     if (pszPermissions == NULL || strlen(pszPermissions) != 10)
-        return FALSE;
+        return false;
     bIsDirectory = (pszPermissions[0] == 'd');
 
-    int i;
-    for(i = 0; i < 3; i++)
+    for(int i = 0; i < 3; i++)
     {
         if (VSICurlGetToken(pszNextToken, &pszNextToken) == NULL)
-            return FALSE;
+            return false;
     }
 
     char* pszSize = VSICurlGetToken(pszNextToken, &pszNextToken);
     if (pszSize == NULL)
-        return FALSE;
+        return false;
 
     if (pszPermissions[0] == '-')
     {
         /* Regular file */
-        bSizeValid = TRUE;
-        nSize = CPLScanUIntBig(pszSize, strlen(pszSize));
+        bSizeValid = true;
+        nSize = CPLScanUIntBig(pszSize, static_cast<int>(strlen(pszSize)));
     }
 
     struct tm brokendowntime;
     memset(&brokendowntime, 0, sizeof(brokendowntime));
-    int bBrokenDownTimeValid = TRUE;
+    bool bBrokenDownTimeValid = true;
 
     char* pszMonth = VSICurlGetToken(pszNextToken, &pszNextToken);
     if (pszMonth == NULL || strlen(pszMonth) != 3)
-        return FALSE;
+        return false;
 
-    for(i = 0; i < 12; i++)
+    int i = 0;  // Used after for.
+    for( ; i < 12; i++ )
     {
         if (EQUALN(pszMonth, apszMonths[i], 3))
             break;
@@ -2232,20 +2499,20 @@ static int VSICurlParseFullFTPLine(char* pszLine,
     if (i < 12)
         brokendowntime.tm_mon = i;
     else
-        bBrokenDownTimeValid = FALSE;
+        bBrokenDownTimeValid = false;
 
     char* pszDay = VSICurlGetToken(pszNextToken, &pszNextToken);
     if (pszDay == NULL || (strlen(pszDay) != 1 && strlen(pszDay) != 2))
-        return FALSE;
+        return false;
     int nDay = atoi(pszDay);
     if (nDay >= 1 && nDay <= 31)
         brokendowntime.tm_mday = nDay;
     else
-        bBrokenDownTimeValid = FALSE;
+        bBrokenDownTimeValid = false;
 
     char* pszHourOrYear = VSICurlGetToken(pszNextToken, &pszNextToken);
     if (pszHourOrYear == NULL || (strlen(pszHourOrYear) != 4 && strlen(pszHourOrYear) != 5))
-        return FALSE;
+        return false;
     if (strlen(pszHourOrYear) == 4)
     {
         brokendowntime.tm_year = atoi(pszHourOrYear) - 1900;
@@ -2267,7 +2534,7 @@ static int VSICurlParseFullFTPLine(char* pszLine,
         nUnixTime = 0;
 
     if (pszNextToken == NULL)
-        return FALSE;
+        return false;
 
     pszFilename = pszNextToken;
 
@@ -2275,7 +2542,7 @@ static int VSICurlParseFullFTPLine(char* pszLine,
     while( *pszCurPtr != '\0')
     {
         /* In case of a link, stop before the pointed part of the link */
-        if (pszPermissions[0] == 'l' && strncmp(pszCurPtr, " -> ", 4) == 0)
+        if (pszPermissions[0] == 'l' && STARTS_WITH(pszCurPtr, " -> "))
         {
             break;
         }
@@ -2283,25 +2550,36 @@ static int VSICurlParseFullFTPLine(char* pszLine,
     }
     *pszCurPtr = '\0';
 
-    return TRUE;
+    return true;
+}
+
+/************************************************************************/
+/*                          GetURLFromDirname()                         */
+/************************************************************************/
+
+CPLString VSICurlFilesystemHandler::GetURLFromDirname( const CPLString& osDirname )
+{
+    return osDirname.substr(GetFSPrefix().size());
 }
 
 /************************************************************************/
 /*                          GetFileList()                               */
 /************************************************************************/
 
-char** VSICurlFilesystemHandler::GetFileList(const char *pszDirname, int* pbGotFileList)
+char** VSICurlFilesystemHandler::GetFileList(const char *pszDirname,
+                                             int nMaxFiles,
+                                             bool* pbGotFileList)
 {
     if (ENABLE_DEBUG)
         CPLDebug("VSICURL", "GetFileList(%s)" , pszDirname);
 
-    *pbGotFileList = FALSE;
+    *pbGotFileList = false;
 
     /* HACK (optimization in fact) for MBTiles driver */
     if (strstr(pszDirname, ".tiles.mapbox.com") != NULL)
         return NULL;
 
-    if (strncmp(pszDirname, "/vsicurl/ftp", strlen("/vsicurl/ftp")) == 0)
+    if (STARTS_WITH(pszDirname, "/vsicurl/ftp"))
     {
         WriteFuncStruct sWriteFuncData;
         sWriteFuncData.pBuffer = NULL;
@@ -2317,7 +2595,7 @@ char** VSICurlFilesystemHandler::GetFileList(const char *pszDirname, int* pbGotF
             VSICurlSetOptions(hCurlHandle, osDirname.c_str());
 
             /* On the first pass, we want to try fetching all the possible */
-            /* informations (filename, file/directory, size). If that */
+            /* information (filename, file/directory, size). If that */
             /* does not work, then try again with CURLOPT_DIRLISTONLY set */
             if (iTry == 1)
             {
@@ -2346,10 +2624,11 @@ char** VSICurlFilesystemHandler::GetFileList(const char *pszDirname, int* pbGotF
             char* c;
             int nCount = 0;
 
-            if (EQUALN(pszLine, "<!DOCTYPE HTML", strlen("<!DOCTYPE HTML")) ||
-                EQUALN(pszLine, "<HTML>", 6))
+            if (STARTS_WITH_CI(pszLine, "<!DOCTYPE HTML") ||
+                STARTS_WITH_CI(pszLine, "<HTML>"))
             {
                 papszFileList = ParseHTMLFileList(pszDirname,
+                                                  nMaxFiles,
                                                   sWriteFuncData.pBuffer,
                                                   pbGotFileList);
                 break;
@@ -2357,7 +2636,7 @@ char** VSICurlFilesystemHandler::GetFileList(const char *pszDirname, int* pbGotF
             else if (iTry == 0)
             {
                 CPLStringList oFileList;
-                *pbGotFileList = TRUE;
+                *pbGotFileList = true;
 
                 while( (c = strchr(pszLine, '\n')) != NULL)
                 {
@@ -2366,9 +2645,9 @@ char** VSICurlFilesystemHandler::GetFileList(const char *pszDirname, int* pbGotF
                         c[-1] = 0;
 
                     char* pszFilename = NULL;
-                    int bSizeValid = FALSE;
+                    bool bSizeValid = false;
                     GUIntBig nFileSize = 0;
-                    int bIsDirectory = FALSE;
+                    bool bIsDirectory = false;
                     GIntBig mUnixTime = 0;
                     if (!VSICurlParseFullFTPLine(pszLine, pszFilename,
                                                  bSizeValid, nFileSize,
@@ -2382,10 +2661,10 @@ char** VSICurlFilesystemHandler::GetFileList(const char *pszDirname, int* pbGotF
                             CPLSPrintf("%s/%s", pszDirname + strlen("/vsicurl/"), pszFilename);
                         CachedFileProp* cachedFileProp = GetCachedFileProp(osCachedFilename);
                         cachedFileProp->eExists = EXIST_YES;
-                        cachedFileProp->bHastComputedFileSize = bSizeValid;
+                        cachedFileProp->bHasComputedFileSize = bSizeValid;
                         cachedFileProp->fileSize = nFileSize;
                         cachedFileProp->bIsDirectory = bIsDirectory;
-                        cachedFileProp->mTime = mUnixTime;
+                        cachedFileProp->mTime = static_cast<time_t>(mUnixTime);
 
                         oFileList.AddString(pszFilename);
                         if (ENABLE_DEBUG)
@@ -2393,12 +2672,15 @@ char** VSICurlFilesystemHandler::GetFileList(const char *pszDirname, int* pbGotF
                             struct tm brokendowntime;
                             CPLUnixTimeToYMDHMS(mUnixTime, &brokendowntime);
                             CPLDebug("VSICURL", "File[%d] = %s, is_dir = %d, size = " CPL_FRMT_GUIB ", time = %04d/%02d/%02d %02d:%02d:%02d",
-                                    nCount, pszFilename, bIsDirectory, nFileSize,
+                                    nCount, pszFilename, bIsDirectory ? 1 : 0, nFileSize,
                                     brokendowntime.tm_year + 1900, brokendowntime.tm_mon + 1, brokendowntime.tm_mday,
                                     brokendowntime.tm_hour, brokendowntime.tm_min, brokendowntime.tm_sec);
                         }
 
                         nCount ++;
+
+                        if( nMaxFiles > 0 && oFileList.Count() > nMaxFiles )
+                            break;
                     }
 
                     pszLine = c + 1;
@@ -2413,7 +2695,7 @@ char** VSICurlFilesystemHandler::GetFileList(const char *pszDirname, int* pbGotF
             else
             {
                 CPLStringList oFileList;
-                *pbGotFileList = TRUE;
+                *pbGotFileList = true;
 
                 while( (c = strchr(pszLine, '\n')) != NULL)
                 {
@@ -2447,8 +2729,8 @@ char** VSICurlFilesystemHandler::GetFileList(const char *pszDirname, int* pbGotF
 
     /* Try to recognize HTML pages that list the content of a directory */
     /* Currently this supports what Apache and shttpd can return */
-    else if (strncmp(pszDirname, "/vsicurl/http://", strlen("/vsicurl/http://")) == 0 ||
-             strncmp(pszDirname, "/vsicurl/https://", strlen("/vsicurl/https://")) == 0)
+    else if (STARTS_WITH(pszDirname, "/vsicurl/http://") ||
+             STARTS_WITH(pszDirname, "/vsicurl/https://"))
     {
         WriteFuncStruct sWriteFuncData;
 
@@ -2478,10 +2760,36 @@ char** VSICurlFilesystemHandler::GetFileList(const char *pszDirname, int* pbGotF
 
         if (sWriteFuncData.pBuffer == NULL)
             return NULL;
-            
-        char** papszFileList = ParseHTMLFileList(pszDirname,
-                                                 sWriteFuncData.pBuffer,
-                                                 pbGotFileList);
+
+        char** papszFileList = NULL;
+        if( STARTS_WITH_CI((const char*)sWriteFuncData.pBuffer, "<?xml") &&
+            strstr((const char*)sWriteFuncData.pBuffer, "<ListBucketResult") != NULL )
+        {
+            CPLString osNextMarker;
+            CPLStringList osFileList;
+            CPLString osBaseURL(pszDirname);
+            osBaseURL += "/";
+            bool bIsTruncated = true;
+            AnalyseS3FileList( osBaseURL,
+                               (const char*)sWriteFuncData.pBuffer,
+                               osFileList,
+                               nMaxFiles,
+                               bIsTruncated,
+                               osNextMarker );
+            // If the list is truncated, then don't report it
+            if( !bIsTruncated )
+            {
+                papszFileList = osFileList.StealList();
+                *pbGotFileList = true;
+            }
+        }
+        else
+        {
+            papszFileList = ParseHTMLFileList(pszDirname,
+                                              nMaxFiles,
+                                              sWriteFuncData.pBuffer,
+                                              pbGotFileList);
+        }
 
         CPLFree(sWriteFuncData.pBuffer);
         return papszFileList;
@@ -2497,20 +2805,20 @@ char** VSICurlFilesystemHandler::GetFileList(const char *pszDirname, int* pbGotF
 int VSICurlFilesystemHandler::Stat( const char *pszFilename, VSIStatBufL *pStatBuf,
                                     int nFlags )
 {
-    CPLString osFilename(pszFilename);
-    
+    const CPLString osFilename(pszFilename);
+
     memset(pStatBuf, 0, sizeof(VSIStatBufL));
 
     const char* pszOptionVal =
         CPLGetConfigOption( "GDAL_DISABLE_READDIR_ON_OPEN", "NO" );
-    int bSkipReadDir = EQUAL(pszOptionVal, "EMPTY_DIR") ||
-                       CSLTestBoolean(pszOptionVal);
+    const bool bSkipReadDir = EQUAL(pszOptionVal, "EMPTY_DIR") ||
+                              CSLTestBoolean(pszOptionVal);
 
     /* Does it look like a FTP directory ? */
-    if (strncmp(osFilename, "/vsicurl/ftp", strlen("/vsicurl/ftp")) == 0 &&
+    if (STARTS_WITH(osFilename, "/vsicurl/ftp") &&
         pszFilename[strlen(osFilename) - 1] == '/' && !bSkipReadDir)
     {
-        char** papszFileList = ReadDir(osFilename);
+        char** papszFileList = ReadDirEx(osFilename, 0);
         if (papszFileList)
         {
             pStatBuf->st_mode = S_IFDIR;
@@ -2523,14 +2831,14 @@ int VSICurlFilesystemHandler::Stat( const char *pszFilename, VSIStatBufL *pStatB
         return -1;
     }
     else if (strchr(CPLGetFilename(osFilename), '.') != NULL &&
-             !EQUALN(CPLGetExtension(osFilename), "zip", 3) &&
+             !STARTS_WITH_CI(CPLGetExtension(osFilename), "zip") &&
              strstr(osFilename, ".zip.") != NULL &&
              strstr(osFilename, ".ZIP.") != NULL &&
              !bSkipReadDir)
     {
-        int bGotFileList;
-        char** papszFileList = ReadDir(CPLGetDirname(osFilename), &bGotFileList);
-        int bFound = (VSICurlIsFileInList(papszFileList, CPLGetFilename(osFilename)) != -1);
+        bool bGotFileList;
+        char** papszFileList = ReadDirInternal(CPLGetDirname(osFilename), 0, &bGotFileList);
+        const bool bFound = (VSICurlIsFileInList(papszFileList, CPLGetFilename(osFilename)) != -1);
         CSLDestroy(papszFileList);
         if (bGotFileList && !bFound)
         {
@@ -2538,16 +2846,19 @@ int VSICurlFilesystemHandler::Stat( const char *pszFilename, VSIStatBufL *pStatB
         }
     }
 
-    VSICurlHandle oHandle( this, osFilename + strlen("/vsicurl/"));
+    VSICurlHandle* poHandle = CreateFileHandle( osFilename + strlen(GetFSPrefix()) );
+    if( poHandle == NULL )
+        return -1;
 
-    if ( oHandle.IsKnownFileSize() ||
-         ((nFlags & VSI_STAT_SIZE_FLAG) && !oHandle.IsDirectory() &&
+    if ( poHandle->IsKnownFileSize() ||
+         ((nFlags & VSI_STAT_SIZE_FLAG) && !poHandle->IsDirectory() &&
            CSLTestBoolean(CPLGetConfigOption("CPL_VSIL_CURL_SLOW_GET_SIZE", "YES"))) )
-        pStatBuf->st_size = oHandle.GetFileSize();
+        pStatBuf->st_size = poHandle->GetFileSize();
 
-    int nRet = (oHandle.Exists()) ? 0 : -1;
-    pStatBuf->st_mtime = oHandle.GetMTime();
-    pStatBuf->st_mode = oHandle.IsDirectory() ? S_IFDIR : S_IFREG;
+    int nRet = poHandle->Exists((nFlags & VSI_STAT_SET_ERROR_FLAG) > 0) ? 0 : -1;
+    pStatBuf->st_mtime = poHandle->GetMTime();
+    pStatBuf->st_mode = poHandle->IsDirectory() ? S_IFDIR : S_IFREG;
+    delete poHandle;
     return nRet;
 }
 
@@ -2589,10 +2900,12 @@ int VSICurlFilesystemHandler::Rmdir( CPL_UNUSED const char *pszDirname )
 }
 
 /************************************************************************/
-/*                             ReadDir()                                */
+/*                             ReadDirInternal()                        */
 /************************************************************************/
 
-char** VSICurlFilesystemHandler::ReadDir( const char *pszDirname, int* pbGotFileList )
+char** VSICurlFilesystemHandler::ReadDirInternal( const char *pszDirname,
+                                          int nMaxFiles,
+                                          bool* pbGotFileList )
 {
     CPLString osDirname(pszDirname);
     while (osDirname[strlen(osDirname) - 1] == '/')
@@ -2601,7 +2914,7 @@ char** VSICurlFilesystemHandler::ReadDir( const char *pszDirname, int* pbGotFile
     const char* pszUpDir = strstr(osDirname, "/..");
     if (pszUpDir != NULL)
     {
-        int pos = pszUpDir - osDirname.c_str() - 1;
+        int pos = static_cast<int>(pszUpDir - osDirname.c_str() - 1);
         while(pos >= 0 && osDirname[pos] != '/')
             pos --;
         if (pos >= 1)
@@ -2610,14 +2923,21 @@ char** VSICurlFilesystemHandler::ReadDir( const char *pszDirname, int* pbGotFile
         }
     }
 
+    if( osDirname.size() <= GetFSPrefix().size() )
+    {
+        if (pbGotFileList)
+            *pbGotFileList = true;
+        return NULL;
+    }
+
     CPLMutexHolder oHolder( &hMutex );
 
     /* If we know the file exists and is not a directory, then don't try to list its content */
-    CachedFileProp* cachedFileProp = GetCachedFileProp(osDirname.c_str() + strlen("/vsicurl/"));
+    CachedFileProp* cachedFileProp = GetCachedFileProp(GetURLFromDirname(osDirname));
     if (cachedFileProp->eExists == EXIST_YES && !cachedFileProp->bIsDirectory)
     {
         if (pbGotFileList)
-            *pbGotFileList = TRUE;
+            *pbGotFileList = true;
         return NULL;
     }
 
@@ -2625,7 +2945,8 @@ char** VSICurlFilesystemHandler::ReadDir( const char *pszDirname, int* pbGotFile
     if (psCachedDirList == NULL)
     {
         psCachedDirList = (CachedDirList*) CPLMalloc(sizeof(CachedDirList));
-        psCachedDirList->papszFileList = GetFileList(osDirname, &psCachedDirList->bGotFileList);
+        psCachedDirList->papszFileList = GetFileList(osDirname, nMaxFiles,
+                                                     &psCachedDirList->bGotFileList);
         cacheDirList[osDirname] = psCachedDirList;
     }
 
@@ -2636,12 +2957,30 @@ char** VSICurlFilesystemHandler::ReadDir( const char *pszDirname, int* pbGotFile
 }
 
 /************************************************************************/
-/*                             ReadDir()                                */
+/*                        InvalidateDirContent()                        */
+/************************************************************************/
+
+void VSICurlFilesystemHandler::InvalidateDirContent( const char *pszDirname )
+{
+    CPLMutexHolder oHolder( &hMutex );
+    std::map<CPLString, CachedDirList*>::iterator oIter =
+        cacheDirList.find(pszDirname);
+    if( oIter != cacheDirList.end() )
+    {
+        CSLDestroy( oIter->second->papszFileList );
+        CPLFree( oIter->second );
+        cacheDirList.erase(oIter);
+    }
+}
+
+/************************************************************************/
+/*                             ReadDirEx()                              */
 /************************************************************************/
 
-char** VSICurlFilesystemHandler::ReadDir( const char *pszDirname )
+char** VSICurlFilesystemHandler::ReadDirEx( const char *pszDirname,
+                                            int nMaxFiles )
 {
-    return ReadDir(pszDirname, NULL);
+    return ReadDirInternal(pszDirname, nMaxFiles, NULL);
 }
 
 /************************************************************************/
@@ -2651,8 +2990,8 @@ char** VSICurlFilesystemHandler::ReadDir( const char *pszDirname )
 /**
  * \brief Install /vsicurl/ HTTP/FTP file system handler (requires libcurl)
  *
- * A special file handler is installed that allows reading on-the-fly of files
- * available through HTTP/FTP web protocols, without downloading the entire file.
+ * A special file handler is installed that allows on-the-fly random reading of files
+ * available through HTTP/FTP web protocols, without prior download of the entire file.
  *
  * Recognized filenames are of the form /vsicurl/http://path/to/remote/resource or
  * /vsicurl/ftp://path/to/remote/resource where path/to/remote/resource is the
@@ -2711,4 +3050,1057 @@ int VSICurlUninstallReadCbk(VSILFILE* fp)
     return ((VSICurlHandle*)fp)->UninstallReadCbk();
 }
 
+
+/************************************************************************/
+/*                         VSIS3FSHandler                               */
+/************************************************************************/
+
+class VSIS3FSHandler CPL_FINAL : public VSICurlFilesystemHandler
+{
+    std::map< CPLString, VSIS3UpdateParams > oMapBucketsToS3Params;
+
+protected:
+    virtual CPLString GetFSPrefix() { return "/vsis3/"; }
+    virtual VSICurlHandle* CreateFileHandle(const char* pszURL);
+    virtual char** GetFileList(const char *pszFilename,
+                               int nMaxFiles,
+                               bool* pbGotFileList);
+    virtual CPLString GetURLFromDirname( const CPLString& osDirname );
+
+public:
+        VSIS3FSHandler() {}
+
+        virtual VSIVirtualHandle *Open( const char *pszFilename,
+                                        const char *pszAccess,
+                                        bool bSetError );
+        virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags );
+        virtual int      Unlink( const char *pszFilename );
+
+        void UpdateMapFromHandle(VSIS3HandleHelper * poS3HandleHelper);
+        void UpdateHandleFromMap(VSIS3HandleHelper * poS3HandleHelper);
+};
+
+/************************************************************************/
+/*                            VSIS3Handle                               */
+/************************************************************************/
+
+class VSIS3Handle CPL_FINAL : public VSICurlHandle
+{
+    VSIS3HandleHelper* m_poS3HandleHelper;
+
+  protected:
+        virtual struct curl_slist* GetCurlHeaders(const CPLString& osVerb);
+        virtual bool CanRestartOnError(const char*, bool);
+        virtual bool UseLimitRangeGetInsteadOfHead() { return true; }
+        virtual void ProcessGetFileSizeResult(const char* pszContent);
+
+    public:
+        VSIS3Handle(VSIS3FSHandler* poFS,
+                    VSIS3HandleHelper* poS3HandleHelper);
+        ~VSIS3Handle();
+};
+
+/************************************************************************/
+/*                            VSIS3WriteHandle                          */
+/************************************************************************/
+
+class VSIS3WriteHandle CPL_FINAL : public VSIVirtualHandle
+{
+    VSIS3FSHandler     *m_poFS;
+    CPLString           m_osFilename;
+    VSIS3HandleHelper  *m_poS3HandleHelper;
+    vsi_l_offset        m_nCurOffset;
+    int                 m_nBufferOff;
+    int                 m_nBufferSize;
+    int                 m_nBufferOffReadCallback;
+    bool                m_bClosed;
+    GByte              *m_pabyBuffer;
+    CPLString           m_osUploadID;
+    int                 m_nPartNumber;
+    std::vector<CPLString> m_aosEtags;
+    CPLString           m_osXML;
+    int                 m_nOffsetInXML;
+    bool                m_bError;
+
+    static size_t       ReadCallBackBuffer( char *buffer, size_t size,
+                                            size_t nitems, void *instream );
+    bool                InitiateMultipartUpload();
+    bool                UploadPart();
+    static size_t       ReadCallBackXML( char *buffer, size_t size,
+                                         size_t nitems, void *instream );
+    bool                CompleteMultipart();
+    bool                AbortMultipart();
+    bool                DoSinglePartPUT();
+
+    public:
+        VSIS3WriteHandle(VSIS3FSHandler* poFS,
+                         const char* pszFilename,
+                         VSIS3HandleHelper* poS3HandleHelper);
+        ~VSIS3WriteHandle();
+
+        virtual int       Seek( vsi_l_offset nOffset, int nWhence );
+        virtual vsi_l_offset Tell();
+        virtual size_t    Read( void *pBuffer, size_t nSize, size_t nMemb );
+        virtual size_t    Write( const void *pBuffer, size_t nSize
+                                 ,size_t nMemb );
+        virtual int       Eof();
+        virtual int       Close();
+
+        bool              IsOK() { return m_pabyBuffer != NULL; }
+};
+
+/************************************************************************/
+/*                         VSIS3WriteHandle()                           */
+/************************************************************************/
+
+VSIS3WriteHandle::VSIS3WriteHandle(VSIS3FSHandler* poFS,
+                                   const char* pszFilename,
+                                   VSIS3HandleHelper* poS3HandleHelper) :
+        m_poFS(poFS), m_osFilename(pszFilename),
+        m_poS3HandleHelper(poS3HandleHelper),
+        m_nCurOffset(0),
+        m_nBufferOff(0),
+        m_nBufferOffReadCallback(0),
+        m_bClosed(false),
+        m_nPartNumber(0),
+        m_nOffsetInXML(0),
+        m_bError(false)
+{
+    int nChunkSizeMB = atoi(CPLGetConfigOption("VSIS3_CHUNK_SIZE", "50"));
+    if( nChunkSizeMB <= 0 || nChunkSizeMB > 1000 )
+        m_nBufferSize = 0;
+    else
+        m_nBufferSize = nChunkSizeMB * 1024 * 1024;
+    m_pabyBuffer = (GByte*)VSIMalloc(m_nBufferSize);
+    if( m_pabyBuffer == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot allocate working buffer for /vsis3");
+    }
+}
+
+/************************************************************************/
+/*                        ~VSIS3WriteHandle()                           */
+/************************************************************************/
+
+VSIS3WriteHandle::~VSIS3WriteHandle()
+{
+    Close();
+    delete m_poS3HandleHelper;
+    CPLFree(m_pabyBuffer);
+}
+
+/************************************************************************/
+/*                               Seek()                                 */
+/************************************************************************/
+
+int VSIS3WriteHandle::Seek( vsi_l_offset nOffset, int nWhence )
+{
+    if( (nWhence == SEEK_SET && nOffset != m_nCurOffset) ||
+        nOffset != 0 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                    "Seek not supported on writable /vsis3 files");
+        m_bError = true;
+        return -1;
+    }
+    return 0;
+}
+
+/************************************************************************/
+/*                               Tell()                                 */
+/************************************************************************/
+
+vsi_l_offset VSIS3WriteHandle::Tell()
+{
+    return m_nCurOffset;
+}
+
+/************************************************************************/
+/*                               Read()                                 */
+/************************************************************************/
+
+size_t VSIS3WriteHandle::Read( void * /* pBuffer */, size_t /* nSize */,
+                               size_t /* nMemb */ )
+{
+    CPLError(CE_Failure, CPLE_NotSupported,
+             "Read not supported on writable /vsis3 files");
+    m_bError = true;
+    return 0;
+}
+
+/************************************************************************/
+/*                        InitiateMultipartUpload()                     */
+/************************************************************************/
+
+bool VSIS3WriteHandle::InitiateMultipartUpload()
+{
+    bool bSuccess = true;
+    bool bGoOn;
+    do
+    {
+        bGoOn = false;
+        CURL* hCurlHandle = curl_easy_init();
+        m_poS3HandleHelper->AddQueryParameter("uploads", "");
+        curl_easy_setopt(hCurlHandle, CURLOPT_URL, m_poS3HandleHelper->GetURL().c_str());
+        CPLHTTPSetOptions(hCurlHandle, NULL);
+        curl_easy_setopt(hCurlHandle, CURLOPT_CUSTOMREQUEST, "POST");
+
+        struct curl_slist* headers = m_poS3HandleHelper->GetCurlHeaders("POST");
+        curl_easy_setopt(hCurlHandle, CURLOPT_HTTPHEADER, headers);
+
+        m_poS3HandleHelper->ResetQueryParameters();
+
+        WriteFuncStruct sWriteFuncData;
+        VSICURLInitWriteFuncStruct(&sWriteFuncData, NULL, NULL, NULL);
+        curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, &sWriteFuncData);
+        curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION, VSICurlHandleWriteFunc);
+
+        curl_easy_perform(hCurlHandle);
+
+        curl_slist_free_all(headers);
+
+        long response_code = 0;
+        curl_easy_getinfo(hCurlHandle, CURLINFO_HTTP_CODE, &response_code);
+        if( response_code != 200 || sWriteFuncData.pBuffer == NULL )
+        {
+            if( sWriteFuncData.pBuffer != NULL &&
+                m_poS3HandleHelper->CanRestartOnError( (const char*)sWriteFuncData.pBuffer) )
+            {
+                m_poFS->UpdateMapFromHandle(m_poS3HandleHelper);
+                bGoOn = true;
+            }
+            else
+            {
+                CPLDebug("S3", "%s", (sWriteFuncData.pBuffer) ? (const char*)sWriteFuncData.pBuffer : "(null)");
+                CPLError(CE_Failure, CPLE_AppDefined, "InitiateMultipartUpload of %s failed",
+                            m_osFilename.c_str());
+                bSuccess = false;
+            }
+        }
+        else
+        {
+            m_poFS->InvalidateCachedFileProp( m_poS3HandleHelper->GetURL().c_str() );
+            m_poFS->InvalidateDirContent( CPLGetDirname(m_osFilename) );
+
+            CPLXMLNode* psNode = CPLParseXMLString( (const char*)sWriteFuncData.pBuffer );
+            if( psNode )
+            {
+                m_osUploadID = CPLGetXMLValue(psNode, "=InitiateMultipartUploadResult.UploadId", "");
+                CPLDebug("S3", "UploadId: %s", m_osUploadID.c_str());
+                CPLDestroyXMLNode(psNode);
+            }
+            if( m_osUploadID.size() == 0 )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "InitiateMultipartUpload of %s failed: cannot get UploadId",
+                         m_osFilename.c_str());
+                bSuccess = false;
+            }
+        }
+
+        CPLFree(sWriteFuncData.pBuffer);
+
+        curl_easy_cleanup(hCurlHandle);
+    }
+    while( bGoOn );
+    return bSuccess;
+}
+
+/************************************************************************/
+/*                         ReadCallBackBuffer()                         */
+/************************************************************************/
+
+size_t VSIS3WriteHandle::ReadCallBackBuffer( char *buffer, size_t size,
+                                             size_t nitems, void *instream)
+{
+    VSIS3WriteHandle* poThis = (VSIS3WriteHandle*)instream;
+    int nSizeMax = (int)(size * nitems);
+    int nSizeToWrite = MIN(nSizeMax, poThis->m_nBufferOff - poThis->m_nBufferOffReadCallback);
+    memcpy(buffer, poThis->m_pabyBuffer + poThis->m_nBufferOffReadCallback,
+           nSizeToWrite);
+    poThis->m_nBufferOffReadCallback += nSizeToWrite;
+    return nSizeToWrite;
+}
+
+/************************************************************************/
+/*                           UploadPart()                               */
+/************************************************************************/
+
+bool VSIS3WriteHandle::UploadPart()
+{
+    ++ m_nPartNumber;
+    if( m_nPartNumber > 10000 )
+    {
+        m_bError = true;
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "10000 parts have been uploaded for %s failed. This is the maximum. "
+                 "Increase VSIS3_CHUNK_SIZE to a higher value (e.g. 500 for 500 MB)",
+                 m_osFilename.c_str());
+        return false;
+    }
+
+    bool bSuccess = true;
+
+    m_nBufferOffReadCallback = 0;
+    CURL* hCurlHandle = curl_easy_init();
+    m_poS3HandleHelper->AddQueryParameter("partNumber", CPLSPrintf("%d", m_nPartNumber));
+    m_poS3HandleHelper->AddQueryParameter("uploadId", m_osUploadID);
+    curl_easy_setopt(hCurlHandle, CURLOPT_URL, m_poS3HandleHelper->GetURL().c_str());
+    CPLHTTPSetOptions(hCurlHandle, NULL);
+    curl_easy_setopt(hCurlHandle, CURLOPT_UPLOAD, 1L);
+    curl_easy_setopt(hCurlHandle, CURLOPT_READFUNCTION, ReadCallBackBuffer);
+    curl_easy_setopt(hCurlHandle, CURLOPT_READDATA, this);
+    curl_easy_setopt(hCurlHandle, CURLOPT_INFILESIZE, m_nBufferOff);
+
+    struct curl_slist* headers = m_poS3HandleHelper->GetCurlHeaders("PUT",
+                                                                    m_pabyBuffer,
+                                                                    m_nBufferOff);
+    curl_easy_setopt(hCurlHandle, CURLOPT_HTTPHEADER, headers);
+
+    m_poS3HandleHelper->ResetQueryParameters();
+
+    WriteFuncStruct sWriteFuncData;
+    VSICURLInitWriteFuncStruct(&sWriteFuncData, NULL, NULL, NULL);
+    curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, &sWriteFuncData);
+    curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION, VSICurlHandleWriteFunc);
+
+    WriteFuncStruct sWriteFuncHeaderData;
+    VSICURLInitWriteFuncStruct(&sWriteFuncHeaderData, NULL, NULL, NULL);
+    curl_easy_setopt(hCurlHandle, CURLOPT_HEADERDATA, &sWriteFuncHeaderData);
+    curl_easy_setopt(hCurlHandle, CURLOPT_HEADERFUNCTION, VSICurlHandleWriteFunc);
+
+    curl_easy_perform(hCurlHandle);
+
+    curl_slist_free_all(headers);
+
+    long response_code = 0;
+    curl_easy_getinfo(hCurlHandle, CURLINFO_HTTP_CODE, &response_code);
+    if( response_code != 200 || sWriteFuncHeaderData.pBuffer == NULL )
+    {
+        CPLDebug("S3", "%s", (sWriteFuncData.pBuffer) ? (const char*)sWriteFuncData.pBuffer : "(null)");
+        CPLError(CE_Failure, CPLE_AppDefined, "UploadPart(%d) of %s failed",
+                    m_nPartNumber, m_osFilename.c_str());
+        bSuccess = false;
+    }
+    else
+    {
+        const char* pszEtag = strstr((const char*)sWriteFuncHeaderData.pBuffer, "ETag: ");
+        if( pszEtag != NULL )
+        {
+            CPLString osEtag = pszEtag + strlen("ETag: ");
+            size_t nPos = osEtag.find("\r");
+            if( nPos != std::string::npos )
+                osEtag.resize(nPos);
+            CPLDebug("S3", "Etag for part %d is %s", m_nPartNumber, osEtag.c_str());
+            m_aosEtags.push_back(osEtag);
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "UploadPart(%d) of %s (uploadId = %s) failed",
+                        m_nPartNumber, m_osFilename.c_str(), m_osUploadID.c_str());
+            bSuccess = false;
+        }
+    }
+
+    CPLFree(sWriteFuncData.pBuffer);
+    CPLFree(sWriteFuncHeaderData.pBuffer);
+
+    curl_easy_cleanup(hCurlHandle);
+
+    return bSuccess;
+}
+
+/************************************************************************/
+/*                               Write()                                */
+/************************************************************************/
+
+size_t VSIS3WriteHandle::Write( const void *pBuffer, size_t nSize,size_t nMemb)
+{
+    size_t nBytesToWrite = nSize * nMemb;
+
+    if( m_bError )
+        return false;
+
+    while( nBytesToWrite > 0 )
+    {
+        int nToWriteInBuffer = (int)MIN((size_t)(m_nBufferSize - m_nBufferOff), nBytesToWrite);
+        memcpy(m_pabyBuffer + m_nBufferOff, pBuffer, nToWriteInBuffer);
+        m_nBufferOff += nToWriteInBuffer;
+        m_nCurOffset += nToWriteInBuffer;
+        nBytesToWrite -= nToWriteInBuffer;
+        if( m_nBufferOff == m_nBufferSize )
+        {
+            if( m_nCurOffset == (vsi_l_offset)m_nBufferSize )
+            {
+                if( !InitiateMultipartUpload() )
+                {
+                    m_bError = true;
+                    return 0;
+                }
+            }
+            if( !UploadPart() )
+            {
+                m_bError = true;
+                return 0;
+            }
+            m_nBufferOff = 0;
+        }
+    }
+    return nMemb;
+}
+
+/************************************************************************/
+/*                                Eof()                                 */
+/************************************************************************/
+
+int VSIS3WriteHandle::Eof()
+{
+    return FALSE;
+}
+
+/************************************************************************/
+/*                           DoSinglePartPUT()                          */
+/************************************************************************/
+
+bool VSIS3WriteHandle::DoSinglePartPUT()
+{
+    bool bSuccess = true;
+    bool bGoOn;
+    do
+    {
+        bGoOn = false;
+        m_nBufferOffReadCallback = 0;
+        CURL* hCurlHandle = curl_easy_init();
+        curl_easy_setopt(hCurlHandle, CURLOPT_URL, m_poS3HandleHelper->GetURL().c_str());
+        CPLHTTPSetOptions(hCurlHandle, NULL);
+        curl_easy_setopt(hCurlHandle, CURLOPT_UPLOAD, 1L);
+        curl_easy_setopt(hCurlHandle, CURLOPT_READFUNCTION, ReadCallBackBuffer);
+        curl_easy_setopt(hCurlHandle, CURLOPT_READDATA, this);
+        curl_easy_setopt(hCurlHandle, CURLOPT_INFILESIZE, m_nBufferOff);
+
+        struct curl_slist* headers = m_poS3HandleHelper->GetCurlHeaders("PUT",
+                                                                        m_pabyBuffer,
+                                                                        m_nBufferOff);
+        curl_easy_setopt(hCurlHandle, CURLOPT_HTTPHEADER, headers);
+
+        WriteFuncStruct sWriteFuncData;
+        VSICURLInitWriteFuncStruct(&sWriteFuncData, NULL, NULL, NULL);
+        curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, &sWriteFuncData);
+        curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION, VSICurlHandleWriteFunc);
+
+        curl_easy_perform(hCurlHandle);
+
+        curl_slist_free_all(headers);
+
+        long response_code = 0;
+        curl_easy_getinfo(hCurlHandle, CURLINFO_HTTP_CODE, &response_code);
+        if( response_code != 200 )
+        {
+            if( sWriteFuncData.pBuffer != NULL &&
+                m_poS3HandleHelper->CanRestartOnError( (const char*)sWriteFuncData.pBuffer) )
+            {
+                m_poFS->UpdateMapFromHandle(m_poS3HandleHelper);
+                bGoOn = true;
+            }
+            else
+            {
+                CPLDebug("S3", "%s", (sWriteFuncData.pBuffer) ? (const char*)sWriteFuncData.pBuffer : "(null)");
+                CPLError(CE_Failure, CPLE_AppDefined, "DoSinglePartPUT of %s failed",
+                            m_osFilename.c_str());
+                bSuccess = false;
+            }
+        }
+        else
+        {
+            m_poFS->InvalidateCachedFileProp( m_poS3HandleHelper->GetURL().c_str() );
+            m_poFS->InvalidateDirContent( CPLGetDirname(m_osFilename) );
+        }
+
+        CPLFree(sWriteFuncData.pBuffer);
+
+        curl_easy_cleanup(hCurlHandle);
+    }
+    while( bGoOn );
+    return bSuccess;
+}
+
+/************************************************************************/
+/*                            ReadCallBackXML()                         */
+/************************************************************************/
+
+size_t VSIS3WriteHandle::ReadCallBackXML(char *buffer, size_t size, size_t nitems, void *instream)
+{
+    VSIS3WriteHandle* poThis = (VSIS3WriteHandle*)instream;
+    int nSizeMax = (int)(size * nitems);
+    int nSizeToWrite = MIN(nSizeMax, (int)poThis->m_osXML.size() - poThis->m_nOffsetInXML);
+    memcpy(buffer, poThis->m_osXML.c_str() + poThis->m_nOffsetInXML,
+           nSizeToWrite);
+    poThis->m_nOffsetInXML += nSizeToWrite;
+    return nSizeToWrite;
+}
+
+/************************************************************************/
+/*                        CompleteMultipart()                           */
+/************************************************************************/
+
+bool VSIS3WriteHandle::CompleteMultipart()
+{
+    bool bSuccess = true;
+
+    m_osXML = "<CompleteMultipartUpload>\n";
+    for(size_t i=0;i<m_aosEtags.size();i++)
+    {
+        m_osXML += "<Part>\n";
+        m_osXML += CPLSPrintf("<PartNumber>%d</PartNumber>", (int)(i+1));
+        m_osXML += "<ETag>" + m_aosEtags[i] + "</ETag>";
+        m_osXML += "</Part>\n";
+    }
+    m_osXML += "</CompleteMultipartUpload>\n";
+
+    m_nOffsetInXML = 0;
+    CURL* hCurlHandle = curl_easy_init();
+    m_poS3HandleHelper->AddQueryParameter("uploadId", m_osUploadID);
+    curl_easy_setopt(hCurlHandle, CURLOPT_URL, m_poS3HandleHelper->GetURL().c_str());
+    CPLHTTPSetOptions(hCurlHandle, NULL);
+    curl_easy_setopt(hCurlHandle, CURLOPT_UPLOAD, 1L);
+    curl_easy_setopt(hCurlHandle, CURLOPT_READFUNCTION, ReadCallBackXML);
+    curl_easy_setopt(hCurlHandle, CURLOPT_READDATA, this);
+    curl_easy_setopt(hCurlHandle, CURLOPT_INFILESIZE, (int)m_osXML.size());
+    curl_easy_setopt(hCurlHandle, CURLOPT_CUSTOMREQUEST, "POST");
+
+    struct curl_slist* headers = m_poS3HandleHelper->GetCurlHeaders("POST",
+                                                                    m_osXML.c_str(),
+                                                                    m_osXML.size());
+    curl_easy_setopt(hCurlHandle, CURLOPT_HTTPHEADER, headers);
+
+    m_poS3HandleHelper->ResetQueryParameters();
+
+    WriteFuncStruct sWriteFuncData;
+    VSICURLInitWriteFuncStruct(&sWriteFuncData, NULL, NULL, NULL);
+    curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, &sWriteFuncData);
+    curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION, VSICurlHandleWriteFunc);
+
+    curl_easy_perform(hCurlHandle);
+
+    curl_slist_free_all(headers);
+
+    long response_code = 0;
+    curl_easy_getinfo(hCurlHandle, CURLINFO_HTTP_CODE, &response_code);
+    if( response_code != 200 )
+    {
+        CPLDebug("S3", "%s", (sWriteFuncData.pBuffer) ? (const char*)sWriteFuncData.pBuffer : "(null)");
+        CPLError(CE_Failure, CPLE_AppDefined, "CompleteMultipart of %s (uploadId=%s) failed",
+                    m_osFilename.c_str(), m_osUploadID.c_str());
+        bSuccess = false;
+    }
+
+    CPLFree(sWriteFuncData.pBuffer);
+
+    curl_easy_cleanup(hCurlHandle);
+
+    return bSuccess;
+}
+
+/************************************************************************/
+/*                          AbortMultipart()                            */
+/************************************************************************/
+
+bool VSIS3WriteHandle::AbortMultipart()
+{
+    bool bSuccess = true;
+
+    CURL* hCurlHandle = curl_easy_init();
+    m_poS3HandleHelper->AddQueryParameter("uploadId", m_osUploadID);
+    curl_easy_setopt(hCurlHandle, CURLOPT_URL, m_poS3HandleHelper->GetURL().c_str());
+    CPLHTTPSetOptions(hCurlHandle, NULL);
+    curl_easy_setopt(hCurlHandle, CURLOPT_CUSTOMREQUEST, "DELETE");
+
+    struct curl_slist* headers = m_poS3HandleHelper->GetCurlHeaders("DELETE");
+    curl_easy_setopt(hCurlHandle, CURLOPT_HTTPHEADER, headers);
+
+    m_poS3HandleHelper->ResetQueryParameters();
+
+    WriteFuncStruct sWriteFuncData;
+    VSICURLInitWriteFuncStruct(&sWriteFuncData, NULL, NULL, NULL);
+    curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, &sWriteFuncData);
+    curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION, VSICurlHandleWriteFunc);
+
+    curl_easy_perform(hCurlHandle);
+
+    curl_slist_free_all(headers);
+
+    long response_code = 0;
+    curl_easy_getinfo(hCurlHandle, CURLINFO_HTTP_CODE, &response_code);
+    if( response_code != 204 )
+    {
+        CPLDebug("S3", "%s", (sWriteFuncData.pBuffer) ? (const char*)sWriteFuncData.pBuffer : "(null)");
+        CPLError(CE_Failure, CPLE_AppDefined, "AbortMultipart of %s (uploadId=%s) failed",
+                    m_osFilename.c_str(), m_osUploadID.c_str());
+        bSuccess = false;
+    }
+
+    CPLFree(sWriteFuncData.pBuffer);
+
+    curl_easy_cleanup(hCurlHandle);
+
+    return bSuccess;
+}
+
+/************************************************************************/
+/*                                 Close()                              */
+/************************************************************************/
+
+int VSIS3WriteHandle::Close()
+{
+    int nRet = 0;
+    if( !m_bClosed )
+    {
+        m_bClosed = true;
+        if( m_osUploadID.size() == 0 )
+        {
+            if( !m_bError && !DoSinglePartPUT() )
+                nRet = -1;
+        }
+        else
+        {
+            if( m_bError )
+            {
+                if( !AbortMultipart() )
+                    nRet = -1;
+            }
+            else if( m_nBufferOff > 0 && !UploadPart() )
+                nRet = -1;
+            else if( !CompleteMultipart() )
+                nRet = -1;
+        }
+    }
+    return nRet;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+VSIVirtualHandle* VSIS3FSHandler::Open( const char *pszFilename,
+                                        const char *pszAccess,
+                                        bool bSetError)
+{
+    if (strchr(pszAccess, 'w') != NULL )
+    {
+        /*if( strchr(pszAccess, '+') != NULL)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                    "w+ not supported for /vsis3. Only w");
+            return NULL;
+        }*/
+        VSIS3HandleHelper* poS3HandleHelper =
+            VSIS3HandleHelper::BuildFromURI(pszFilename + GetFSPrefix().size(),
+                                            GetFSPrefix().c_str(), false);
+        if( poS3HandleHelper == NULL )
+            return NULL;
+        UpdateHandleFromMap(poS3HandleHelper);
+        VSIS3WriteHandle* poHandle = new VSIS3WriteHandle(this, pszFilename, poS3HandleHelper);
+        if( !poHandle->IsOK() )
+        {
+            delete poHandle;
+            poHandle = NULL;
+        }
+        return poHandle;
+    }
+    else
+    {
+        return VSICurlFilesystemHandler::Open(pszFilename, pszAccess, bSetError);
+    }
+}
+
+/************************************************************************/
+/*                                Stat()                                */
+/************************************************************************/
+
+int VSIS3FSHandler::Stat( const char *pszFilename, VSIStatBufL *pStatBuf,
+                          int nFlags )
+{
+    CPLString osFilename(pszFilename);
+    if( osFilename.find('/', GetFSPrefix().size()) == std::string::npos )
+        osFilename += "/";
+    return VSICurlFilesystemHandler::Stat(osFilename, pStatBuf, nFlags);
+}
+
+/************************************************************************/
+/*                          CreateFileHandle()                          */
+/************************************************************************/
+
+VSICurlHandle* VSIS3FSHandler::CreateFileHandle(const char* pszURL)
+{
+    VSIS3HandleHelper* poS3HandleHelper =
+            VSIS3HandleHelper::BuildFromURI(pszURL, GetFSPrefix().c_str(), false);
+    if( poS3HandleHelper )
+    {
+        UpdateHandleFromMap(poS3HandleHelper);
+        return new VSIS3Handle(this, poS3HandleHelper);
+    }
+    return NULL;
+}
+
+/************************************************************************/
+/*                          GetURLFromDirname()                         */
+/************************************************************************/
+
+CPLString VSIS3FSHandler::GetURLFromDirname( const CPLString& osDirname )
+{
+    CPLString osDirnameWithoutPrefix = osDirname.substr(GetFSPrefix().size());
+
+    VSIS3HandleHelper* poS3HandleHelper =
+            VSIS3HandleHelper::BuildFromURI(osDirnameWithoutPrefix, GetFSPrefix().c_str(), true);
+    if( poS3HandleHelper == NULL )
+    {
+        return "";
+    }
+    UpdateHandleFromMap(poS3HandleHelper);
+    CPLString osBaseURL(poS3HandleHelper->GetURL());
+    if( osBaseURL.size() && osBaseURL[osBaseURL.size()-1] == '/' )
+        osBaseURL.resize(osBaseURL.size()-1);
+    delete poS3HandleHelper;
+
+    return osBaseURL;
+}
+
+/************************************************************************/
+/*                               Unlink()                               */
+/************************************************************************/
+
+int VSIS3FSHandler::Unlink( const char *pszFilename )
+{
+    CPLString osNameWithoutPrefix = pszFilename + GetFSPrefix().size();
+    VSIS3HandleHelper* poS3HandleHelper =
+            VSIS3HandleHelper::BuildFromURI(osNameWithoutPrefix, GetFSPrefix().c_str(), false);
+    if( poS3HandleHelper == NULL )
+    {
+        return -1;
+    }
+    UpdateHandleFromMap(poS3HandleHelper);
+
+    int nRet = 0;
+
+    bool bGoOn;
+    do
+    {
+        bGoOn = false;
+        CURL* hCurlHandle = curl_easy_init();
+        curl_easy_setopt(hCurlHandle, CURLOPT_URL, poS3HandleHelper->GetURL().c_str());
+        CPLHTTPSetOptions(hCurlHandle, NULL);
+        curl_easy_setopt(hCurlHandle, CURLOPT_CUSTOMREQUEST, "DELETE");
+
+        struct curl_slist* headers = poS3HandleHelper->GetCurlHeaders("DELETE");
+        curl_easy_setopt(hCurlHandle, CURLOPT_HTTPHEADER, headers);
+
+        WriteFuncStruct sWriteFuncData;
+        VSICURLInitWriteFuncStruct(&sWriteFuncData, NULL, NULL, NULL);
+        curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, &sWriteFuncData);
+        curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION, VSICurlHandleWriteFunc);
+
+        curl_easy_perform(hCurlHandle);
+
+        curl_slist_free_all(headers);
+
+        long response_code = 0;
+        curl_easy_getinfo(hCurlHandle, CURLINFO_HTTP_CODE, &response_code);
+        if( response_code != 204 )
+        {
+            if( sWriteFuncData.pBuffer != NULL &&
+                poS3HandleHelper->CanRestartOnError( (const char*)sWriteFuncData.pBuffer) )
+            {
+                UpdateMapFromHandle(poS3HandleHelper);
+                bGoOn = true;
+            }
+            else
+            {
+                CPLDebug("S3", "%s", (sWriteFuncData.pBuffer) ? (const char*)sWriteFuncData.pBuffer : "(null)");
+                CPLError(CE_Failure, CPLE_AppDefined, "Delete of %s failed",
+                         pszFilename);
+                nRet = -1;
+            }
+        }
+        else
+        {
+            InvalidateCachedFileProp(poS3HandleHelper->GetURL().c_str());
+            InvalidateDirContent( CPLGetDirname(pszFilename) );
+        }
+
+        CPLFree(sWriteFuncData.pBuffer);
+
+        curl_easy_cleanup(hCurlHandle);
+    }
+    while( bGoOn );
+
+    delete poS3HandleHelper;
+    return nRet;
+}
+
+/************************************************************************/
+/*                           GetFileList()                              */
+/************************************************************************/
+
+char** VSIS3FSHandler::GetFileList( const char *pszDirname,
+                                    int nMaxFiles,
+                                    bool* pbGotFileList )
+{
+    // TODO: to implement
+    if (ENABLE_DEBUG)
+        CPLDebug("S3", "GetFileList(%s)" , pszDirname);
+    *pbGotFileList = false;
+    CPLString osDirnameWithoutPrefix = pszDirname + GetFSPrefix().size();
+
+
+    VSIS3HandleHelper* poS3HandleHelper =
+            VSIS3HandleHelper::BuildFromURI(osDirnameWithoutPrefix, GetFSPrefix().c_str(), true);
+    if( poS3HandleHelper == NULL )
+    {
+        return NULL;
+    }
+    UpdateHandleFromMap(poS3HandleHelper);
+
+    CPLString osObjectKey = poS3HandleHelper->GetObjectKey();
+    poS3HandleHelper->SetObjectKey("");
+
+    WriteFuncStruct sWriteFuncData;
+
+    CPLStringList osFileList;
+    CPLString osNextMarker;
+
+    CPLString osMaxKeys = CPLGetConfigOption("AWS_MAX_KEYS", "");
+
+    while(true)
+    {
+        poS3HandleHelper->ResetQueryParameters();
+        CPLString osBaseURL(poS3HandleHelper->GetURL());
+
+    #if LIBCURL_VERSION_NUM < 0x070B00
+        /* Curl 7.10.X doesn't manage to unset the CURLOPT_RANGE that would have been */
+        /* previously set, so we have to reinit the connection handle */
+        GetCurlHandleFor("");
+    #endif
+
+        CURL* hCurlHandle = GetCurlHandleFor(osBaseURL);
+
+        poS3HandleHelper->AddQueryParameter("delimiter", "/");
+        if( osNextMarker.size() )
+            poS3HandleHelper->AddQueryParameter("marker", osNextMarker);
+        if( osMaxKeys.size() )
+             poS3HandleHelper->AddQueryParameter("max-keys", osMaxKeys);
+        if( osObjectKey.size() )
+             poS3HandleHelper->AddQueryParameter("prefix", osObjectKey + "/");
+
+        VSICurlSetOptions(hCurlHandle, poS3HandleHelper->GetURL());
+
+        curl_easy_setopt(hCurlHandle, CURLOPT_RANGE, NULL);
+
+        VSICURLInitWriteFuncStruct(&sWriteFuncData, NULL, NULL, NULL);
+        curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, &sWriteFuncData);
+        curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION, VSICurlHandleWriteFunc);
+
+        char szCurlErrBuf[CURL_ERROR_SIZE+1];
+        szCurlErrBuf[0] = '\0';
+        curl_easy_setopt(hCurlHandle, CURLOPT_ERRORBUFFER, szCurlErrBuf );
+
+        struct curl_slist* headers = poS3HandleHelper->GetCurlHeaders("GET");
+        if( headers != NULL )
+            curl_easy_setopt(hCurlHandle, CURLOPT_HTTPHEADER, headers);
+
+        curl_easy_perform(hCurlHandle);
+
+        if( headers != NULL )
+            curl_slist_free_all(headers);
+
+        if (sWriteFuncData.pBuffer == NULL)
+        {
+            delete poS3HandleHelper;
+            return NULL;
+        }
+
+        long response_code = 0;
+        curl_easy_getinfo(hCurlHandle, CURLINFO_HTTP_CODE, &response_code);
+        if( response_code != 200 )
+        {
+            if( sWriteFuncData.pBuffer != NULL &&
+                poS3HandleHelper->CanRestartOnError( (const char*)sWriteFuncData.pBuffer) )
+            {
+                UpdateMapFromHandle(poS3HandleHelper);
+                CPLFree(sWriteFuncData.pBuffer);
+            }
+            else
+            {
+                CPLDebug("S3", "%s", sWriteFuncData.pBuffer ? (const char*)sWriteFuncData.pBuffer : "(null)");
+                CPLFree(sWriteFuncData.pBuffer);
+                delete poS3HandleHelper;
+                return NULL;
+            }
+        }
+        else
+        {
+            *pbGotFileList = true;
+            bool bIsTrucated;
+            AnalyseS3FileList( osBaseURL,
+                               (const char*)sWriteFuncData.pBuffer,
+                               osFileList,
+                               nMaxFiles,
+                               bIsTrucated,
+                               osNextMarker );
+
+            CPLFree(sWriteFuncData.pBuffer);
+
+            if( osNextMarker.size() == 0 )
+            {
+                delete poS3HandleHelper;
+                return osFileList.StealList();
+            }
+        }
+    }
+}
+
+/************************************************************************/
+/*                         UpdateMapFromHandle()                        */
+/************************************************************************/
+
+void VSIS3FSHandler::UpdateMapFromHandle(VSIS3HandleHelper * poS3HandleHelper)
+{
+    CPLMutexHolder oHolder( &hMutex );
+
+    oMapBucketsToS3Params[ poS3HandleHelper->GetBucket() ] =
+        VSIS3UpdateParams ( poS3HandleHelper->GetAWSRegion(),
+                      poS3HandleHelper->GetAWSS3Endpoint(),
+                      poS3HandleHelper->GetVirtualHosting() );
+}
+
+/************************************************************************/
+/*                         UpdateHandleFromMap()                        */
+/************************************************************************/
+
+void VSIS3FSHandler::UpdateHandleFromMap(VSIS3HandleHelper * poS3HandleHelper)
+{
+    CPLMutexHolder oHolder( &hMutex );
+
+    std::map< CPLString, VSIS3UpdateParams>::iterator oIter =
+        oMapBucketsToS3Params.find(poS3HandleHelper->GetBucket());
+    if( oIter != oMapBucketsToS3Params.end() )
+    {
+        poS3HandleHelper->SetAWSRegion( oIter->second.m_osAWSRegion );
+        poS3HandleHelper->SetAWSS3Endpoint( oIter->second.m_osAWSS3Endpoint );
+        poS3HandleHelper->SetVirtualHosting( oIter->second.m_bUseVirtualHosting );
+    }
+}
+
+/************************************************************************/
+/*                             VSIS3Handle()                            */
+/************************************************************************/
+
+VSIS3Handle::VSIS3Handle(VSIS3FSHandler* poFSIn, VSIS3HandleHelper* poS3HandleHelper) :
+        VSICurlHandle(poFSIn, poS3HandleHelper->GetURL()),
+        m_poS3HandleHelper(poS3HandleHelper)
+{
+}
+
+/************************************************************************/
+/*                            ~VSIS3Handle()                            */
+/************************************************************************/
+
+VSIS3Handle::~VSIS3Handle()
+{
+    delete m_poS3HandleHelper;
+}
+
+/************************************************************************/
+/*                           GetCurlHeaders()                           */
+/************************************************************************/
+
+struct curl_slist* VSIS3Handle::GetCurlHeaders(const CPLString& osVerb)
+{
+    return m_poS3HandleHelper->GetCurlHeaders(osVerb);
+}
+
+/************************************************************************/
+/*                          CanRestartOnError()                         */
+/************************************************************************/
+
+bool VSIS3Handle::CanRestartOnError(const char* pszErrorMsg, bool bSetError)
+{
+    if( m_poS3HandleHelper->CanRestartOnError(pszErrorMsg, bSetError) )
+    {
+        ((VSIS3FSHandler*) poFS)->UpdateMapFromHandle(m_poS3HandleHelper);
+
+        SetURL(m_poS3HandleHelper->GetURL());
+        return true;
+    }
+    return false;
+}
+
+/************************************************************************/
+/*                    ProcessGetFileSizeResult()                        */
+/************************************************************************/
+
+void VSIS3Handle::ProcessGetFileSizeResult(const char* pszContent)
+{
+    bIsDirectory = strstr(pszContent, "ListBucketResult") != NULL;
+}
+
+/************************************************************************/
+/*                      VSIInstallS3FileHandler()                       */
+/************************************************************************/
+
+/**
+ * \brief Install /vsis3/ Amazon S3 file system handler (requires libcurl)
+ *
+ * A special file handler is installed that allows on-the-fly random reading of files
+ * available in AWS S3 buckets, without prior download of the entire file.
+ * It also allows sequential writing of files (no seeks or read operations are then
+ * allowed).
+ *
+ * Recognized filenames are of the form /vsis3/bucket/key where
+ * bucket is the name of the S3 bucket and key the S3 object "key", i.e.
+ * a filename potentially containing subdirectories.
+ *
+ * Partial downloads are done with a 16 KB granularity by default.
+ * If the driver detects sequential reading
+ * it will progressively increase the chunk size up to 2 MB to improve download
+ * performance.
+ *
+ * The AWS_SECRET_ACCESS_KEY and AWS_ACCESS_KEY_ID configuration options *must* be
+ * set.
+ * The AWS_SESSION_TOKEN configuration option must be set when temporary credentials
+ * are used.
+ * The AWS_REGION configuration option may be set to one of the supported
+ * <a href="http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region">S3 regions</a>
+ * and defaults to 'us-east-1'
+ * The AWS_S3_ENDPOINT configuration option defaults to s3.amazonaws.com.
+ *
+ * The GDAL_HTTP_PROXY, GDAL_HTTP_PROXYUSERPWD and GDAL_PROXY_AUTH configuration options can be
+ * used to define a proxy server. The syntax to use is the one of Curl CURLOPT_PROXY,
+ * CURLOPT_PROXYUSERPWD and CURLOPT_PROXYAUTH options.
+ *
+ * On reading, the file can be cached in RAM by setting the configuration option
+ * VSI_CACHE to TRUE. The cache size defaults to 25 MB, but can be modified by setting
+ * the configuration option VSI_CACHE_SIZE (in bytes).
+ *
+ * On writing, the file is uploaded using the S3 <a href="http://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadInitiate.html">multipart upload API</a>.
+ * The size of chunks is set to 50 MB by default, allowing creating files up to
+ * 500 GB (10000 parts of 50 MB each). If larger files are needed, then increase the
+ * value of the VSIS3_CHUNK_SIZE config option to a larger value (expressed in MB).
+ * In case the process is killed and the file not properly closed, the multipart upload
+ * will remain open, causing Amazon to charge you for the parts storage. You'll have to
+ * abort yourself with other means such "ghost" uploads
+ * (e.g. with the <a href="http://s3tools.org/s3cmd">s3cmd</a> utility)
+ * For files smaller than the chunk size, a simple PUT request is used instead
+ * of the multipart upload API.
+ *
+ * VSIStatL() will return the size in st_size member.
+ *
+ * @since GDAL 2.1
+ */
+void VSIInstallS3FileHandler(void)
+{
+    VSIFileManager::InstallHandler( "/vsis3/", new VSIS3FSHandler );
+}
+
+
+
 #endif /* HAVE_CURL */
diff --git a/port/cpl_vsil_curl_priv.h b/port/cpl_vsil_curl_priv.h
index 86a7107..259dfac 100644
--- a/port/cpl_vsil_curl_priv.h
+++ b/port/cpl_vsil_curl_priv.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsil_curl_priv.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: cpl_vsil_curl_priv.h 31749 2015-11-25 02:32:55Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Private API for VSICurl
@@ -40,7 +40,7 @@ typedef int (*VSICurlReadCbkFunc) (VSILFILE* fp, void *pabyBuffer, size_t nBuffe
 
 /* fp must be a VSICurl file handle, otherwise bad things will happen ! */
 /* bStopOnInterrruptUntilUninstall must be set to TRUE if all downloads */
-/* must be cancelled after a first one has been stopped by the callback function. */
+/* must be canceled after a first one has been stopped by the callback function. */
 /* In that case, downloads will restart after uninstalling the callback. */
 int VSICurlInstallReadCbk(VSILFILE* fp, VSICurlReadCbkFunc pfnReadCbk, void* pfnUserData,
                           int bStopOnInterrruptUntilUninstall);
diff --git a/port/cpl_vsil_curl_streaming.cpp b/port/cpl_vsil_curl_streaming.cpp
index 5c91c79..ff02056 100644
--- a/port/cpl_vsil_curl_streaming.cpp
+++ b/port/cpl_vsil_curl_streaming.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: cpl_vsil_curl_streaming.cpp 28459 2015-02-12 13:48:21Z rouault $
+ * $Id: cpl_vsil_curl_streaming.cpp 33758 2016-03-21 09:06:22Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for HTTP/FTP files in streaming mode
  * Author:   Even Rouault <even dot rouault at mines dash paris.org>
  *
  ******************************************************************************
- * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ * Copyright (c) 2012-2015, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,8 +32,9 @@
 #include "cpl_multiproc.h"
 #include "cpl_hash_set.h"
 #include "cpl_time.h"
+#include "cpl_aws.h"
 
-CPL_CVSID("$Id: cpl_vsil_curl_streaming.cpp 28459 2015-02-12 13:48:21Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_curl_streaming.cpp 33758 2016-03-21 09:06:22Z rouault $");
 
 #if !defined(HAVE_CURL) || defined(CPL_MULTIPROC_STUB)
 
@@ -42,6 +43,11 @@ void VSIInstallCurlStreamingFileHandler(void)
     /* not supported */
 }
 
+void VSIInstallS3StreamingFileHandler(void)
+{
+    /* not supported */
+}
+
 #else
 
 #include <curl/curl.h>
@@ -130,6 +136,8 @@ void RingBuffer::Read(void* pBuffer, size_t nSize)
 
 /************************************************************************/
 
+namespace {
+
 typedef enum
 {
     EXIST_UNKNOWN = -1,
@@ -140,7 +148,7 @@ typedef enum
 typedef struct
 {
     ExistStatus     eExists;
-    int             bHastComputedFileSize;
+    int             bHasComputedFileSize;
     vsi_l_offset    fileSize;
     int             bIsDirectory;
 #ifdef notdef
@@ -148,22 +156,43 @@ typedef struct
 #endif
 } CachedFileProp;
 
+typedef struct
+{
+    char*           pBuffer;
+    size_t          nSize;
+    int             bIsHTTP;
+    int             bIsInHeader;
+    int             nHTTPCode;
+    int             bDownloadHeaderOnly;
+} WriteFuncStruct;
+
+} /* end of anoymous namespace */
+
 /************************************************************************/
 /*                       VSICurlStreamingFSHandler                      */
 /************************************************************************/
 
+class VSICurlStreamingHandle;
+
 class VSICurlStreamingFSHandler : public VSIFilesystemHandler
 {
+    std::map<CPLString, CachedFileProp*>   cacheFileSize;
+
+protected:
     CPLMutex           *hMutex;
 
-    std::map<CPLString, CachedFileProp*>   cacheFileSize;
+    virtual CPLString GetFSPrefix() { return "/vsicurl_streaming/"; }
+    virtual VSICurlStreamingHandle* CreateFileHandle(const char* pszURL);
 
 public:
     VSICurlStreamingFSHandler();
     ~VSICurlStreamingFSHandler();
 
+    using VSIFilesystemHandler::Open;
+
     virtual VSIVirtualHandle *Open( const char *pszFilename,
-                                    const char *pszAccess);
+                                    const char *pszAccess,
+                                    bool bSetError );
     virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags );
 
     void                AcquireMutex();
@@ -178,20 +207,22 @@ public:
 
 class VSICurlStreamingHandle : public VSIVirtualHandle
 {
+  protected:
+    VSICurlStreamingFSHandler* m_poFS;
+
   private:
-    VSICurlStreamingFSHandler* poFS;
 
-    char*           pszURL;
+    char*           m_pszURL;
 
 #ifdef notdef
     unsigned int    nRecomputedChecksumOfFirst1024Bytes;
 #endif
     vsi_l_offset    curOffset;
     vsi_l_offset    fileSize;
-    int             bHastComputedFileSize;
+    int             bHasComputedFileSize;
     ExistStatus     eExists;
     int             bIsDirectory;
-    
+
     int             bCanTrustCandidateFileSize;
     int             bHasCandidateFileSize;
     vsi_l_offset    nCandidateFileSize;
@@ -227,6 +258,15 @@ class VSICurlStreamingHandle : public VSIVirtualHandle
     void                AddRegion( vsi_l_offset    nFileOffsetStart,
                                    size_t          nSize,
                                    GByte          *pData );
+
+  protected:
+    virtual struct curl_slist* GetCurlHeaders(const CPLString& ) { return NULL; }
+    virtual bool StopReceivingBytesOnError() { return true; }
+    bool CanRestartOnError(const char* pszErrorMsg) { return CanRestartOnError(pszErrorMsg, false); }
+    virtual bool CanRestartOnError(const char*, bool) { return false; }
+    virtual bool InterpretRedirect() { return true; }
+    void SetURL(const char* pszURL);
+
   public:
 
     VSICurlStreamingHandle(VSICurlStreamingFSHandler* poFS, const char* pszURL);
@@ -241,23 +281,24 @@ class VSICurlStreamingHandle : public VSIVirtualHandle
     virtual int          Close();
 
     void                 DownloadInThread();
-    int                  ReceivedBytes(GByte *buffer, size_t count, size_t nmemb);
-    int                  ReceivedBytesHeader(GByte *buffer, size_t count, size_t nmemb);
+    size_t               ReceivedBytes(GByte *buffer, size_t count, size_t nmemb);
+    size_t               ReceivedBytesHeader(GByte *buffer, size_t count, size_t nmemb);
 
-    int                  IsKnownFileSize() const { return bHastComputedFileSize; }
+    int                  IsKnownFileSize() const { return bHasComputedFileSize; }
     vsi_l_offset         GetFileSize();
     int                  Exists();
     int                  IsDirectory() const { return bIsDirectory; }
 };
 
+
 /************************************************************************/
 /*                       VSICurlStreamingHandle()                       */
 /************************************************************************/
 
 VSICurlStreamingHandle::VSICurlStreamingHandle(VSICurlStreamingFSHandler* poFS, const char* pszURL)
 {
-    this->poFS = poFS;
-    this->pszURL = CPLStrdup(pszURL);
+    m_poFS = poFS;
+    m_pszURL = CPLStrdup(pszURL);
 
 #ifdef notdef
     nRecomputedChecksumOfFirst1024Bytes = 0;
@@ -268,7 +309,7 @@ VSICurlStreamingHandle::VSICurlStreamingHandle(VSICurlStreamingFSHandler* poFS,
     CachedFileProp* cachedFileProp = poFS->GetCachedFileProp(pszURL);
     eExists = cachedFileProp->eExists;
     fileSize = cachedFileProp->fileSize;
-    bHastComputedFileSize = cachedFileProp->bHastComputedFileSize;
+    bHasComputedFileSize = cachedFileProp->bHasComputedFileSize;
     bIsDirectory = cachedFileProp->bIsDirectory;
     poFS->ReleaseMutex();
 
@@ -308,7 +349,7 @@ VSICurlStreamingHandle::~VSICurlStreamingHandle()
 {
     StopDownload();
 
-    CPLFree(pszURL);
+    CPLFree(m_pszURL);
     if (hCurlHandle != NULL)
         curl_easy_cleanup(hCurlHandle);
 
@@ -322,6 +363,16 @@ VSICurlStreamingHandle::~VSICurlStreamingHandle()
 }
 
 /************************************************************************/
+/*                            SetURL()                                  */
+/************************************************************************/
+
+void VSICurlStreamingHandle::SetURL(const char* pszURLIn)
+{
+    CPLFree(m_pszURL);
+    m_pszURL = CPLStrdup(pszURLIn);
+}
+
+/************************************************************************/
 /*                         AcquireMutex()                               */
 /************************************************************************/
 
@@ -353,7 +404,7 @@ int VSICurlStreamingHandle::Seek( vsi_l_offset nOffset, int nWhence )
         pCachedData = NULL;
         nCachedSize = 0;
         AcquireMutex();
-        bHastComputedFileSize = FALSE;
+        bHasComputedFileSize = FALSE;
         fileSize = 0;
         ReleaseMutex();
     }
@@ -374,16 +425,6 @@ int VSICurlStreamingHandle::Seek( vsi_l_offset nOffset, int nWhence )
     return 0;
 }
 
-typedef struct
-{
-    char*           pBuffer;
-    size_t          nSize;
-    int             bIsHTTP;
-    int             bIsInHeader;
-    int             nHTTPCode;
-    int             bDownloadHeaderOnly;
-} WriteFuncStruct;
-
 /************************************************************************/
 /*                  VSICURLStreamingInitWriteFuncStruct()                */
 /************************************************************************/
@@ -402,7 +443,7 @@ static void VSICURLStreamingInitWriteFuncStruct(WriteFuncStruct   *psStruct)
 /*                 VSICurlStreamingHandleWriteFuncForHeader()           */
 /************************************************************************/
 
-static int VSICurlStreamingHandleWriteFuncForHeader(void *buffer, size_t count, size_t nmemb, void *req)
+static size_t VSICurlStreamingHandleWriteFuncForHeader(void *buffer, size_t count, size_t nmemb, void *req)
 {
     WriteFuncStruct* psStruct = (WriteFuncStruct*) req;
     size_t nSize = count * nmemb;
@@ -417,8 +458,8 @@ static int VSICurlStreamingHandleWriteFuncForHeader(void *buffer, size_t count,
         if (psStruct->bIsHTTP && psStruct->bIsInHeader)
         {
             char* pszLine = psStruct->pBuffer + psStruct->nSize;
-            if (EQUALN(pszLine, "HTTP/1.0 ", 9) ||
-                EQUALN(pszLine, "HTTP/1.1 ", 9))
+            if (STARTS_WITH_CI(pszLine, "HTTP/1.0 ") ||
+                STARTS_WITH_CI(pszLine, "HTTP/1.1 "))
                 psStruct->nHTTPCode = atoi(pszLine + 9);
 
             if (pszLine[0] == '\r' || pszLine[0] == '\n')
@@ -455,7 +496,7 @@ vsi_l_offset VSICurlStreamingHandle::GetFileSize()
     WriteFuncStruct sWriteFuncHeaderData;
 
     AcquireMutex();
-    if (bHastComputedFileSize)
+    if (bHasComputedFileSize)
     {
         vsi_l_offset nRet = fileSize;
         ReleaseMutex();
@@ -475,28 +516,35 @@ vsi_l_offset VSICurlStreamingHandle::GetFileSize()
 
     CURL* hLocalHandle = curl_easy_init();
 
-    VSICurlSetOptions(hLocalHandle, pszURL);
+    VSICurlSetOptions(hLocalHandle, m_pszURL);
 
     VSICURLStreamingInitWriteFuncStruct(&sWriteFuncHeaderData);
 
     /* HACK for mbtiles driver: proper fix would be to auto-detect servers that don't accept HEAD */
     /* http://a.tiles.mapbox.com/v3/ doesn't accept HEAD, so let's start a GET */
     /* and interrupt is as soon as the header is found */
-    if (strstr(pszURL, ".tiles.mapbox.com/") != NULL)
+    CPLString osVerb;
+    if (strstr(m_pszURL, ".tiles.mapbox.com/") != NULL)
     {
         curl_easy_setopt(hLocalHandle, CURLOPT_HEADERDATA, &sWriteFuncHeaderData);
         curl_easy_setopt(hLocalHandle, CURLOPT_HEADERFUNCTION, VSICurlStreamingHandleWriteFuncForHeader);
 
-        sWriteFuncHeaderData.bIsHTTP = strncmp(pszURL, "http", 4) == 0;
+        sWriteFuncHeaderData.bIsHTTP = STARTS_WITH(m_pszURL, "http");
         sWriteFuncHeaderData.bDownloadHeaderOnly = TRUE;
+        osVerb = "GET";
     }
     else
     {
         curl_easy_setopt(hLocalHandle, CURLOPT_NOBODY, 1);
         curl_easy_setopt(hLocalHandle, CURLOPT_HTTPGET, 0);
         curl_easy_setopt(hLocalHandle, CURLOPT_HEADER, 1);
+        osVerb = "HEAD";
     }
 
+    struct curl_slist* headers = GetCurlHeaders(osVerb);
+    if( headers != NULL )
+        curl_easy_setopt(hLocalHandle, CURLOPT_HTTPHEADER, headers);
+
     /* We need that otherwise OSGEO4W's libcurl issue a dummy range request */
     /* when doing a HEAD when recycling connections */
     curl_easy_setopt(hLocalHandle, CURLOPT_RANGE, NULL);
@@ -512,23 +560,25 @@ vsi_l_offset VSICurlStreamingHandle::GetFileSize()
 
     double dfSize = 0;
     curl_easy_perform(hLocalHandle);
+    if( headers != NULL )
+        curl_slist_free_all(headers);
 
     AcquireMutex();
 
     eExists = EXIST_UNKNOWN;
-    bHastComputedFileSize = TRUE;
+    bHasComputedFileSize = TRUE;
 
-    if (strncmp(pszURL, "ftp", 3) == 0)
+    if (STARTS_WITH(m_pszURL, "ftp"))
     {
         if (sWriteFuncData.pBuffer != NULL &&
-            strncmp(sWriteFuncData.pBuffer, "Content-Length: ", strlen( "Content-Length: ")) == 0)
+            STARTS_WITH(sWriteFuncData.pBuffer, "Content-Length: "))
         {
             const char* pszBuffer = sWriteFuncData.pBuffer + strlen("Content-Length: ");
             eExists = EXIST_YES;
-            fileSize = CPLScanUIntBig(pszBuffer, sWriteFuncData.nSize - strlen("Content-Length: "));
+            fileSize = CPLScanUIntBig(pszBuffer, static_cast<int>(sWriteFuncData.nSize - strlen("Content-Length: ")));
             if (ENABLE_DEBUG)
                 CPLDebug("VSICURL", "GetFileSize(%s)=" CPL_FRMT_GUIB,
-                        pszURL, fileSize);
+                        m_pszURL, fileSize);
         }
     }
 
@@ -564,8 +614,8 @@ vsi_l_offset VSICurlStreamingHandle::GetFileSize()
         char *pszEffectiveURL = NULL;
         curl_easy_getinfo(hLocalHandle, CURLINFO_EFFECTIVE_URL, &pszEffectiveURL);
         if (pszEffectiveURL != NULL &&
-            strncmp(pszURL, pszEffectiveURL, strlen(pszURL)) == 0 &&
-            pszEffectiveURL[strlen(pszURL)] == '/')
+            strncmp(m_pszURL, pszEffectiveURL, strlen(m_pszURL)) == 0 &&
+            pszEffectiveURL[strlen(m_pszURL)] == '/')
         {
             eExists = EXIST_YES;
             fileSize = 0;
@@ -574,22 +624,22 @@ vsi_l_offset VSICurlStreamingHandle::GetFileSize()
 
         if (ENABLE_DEBUG)
             CPLDebug("VSICURL", "GetFileSize(%s)=" CPL_FRMT_GUIB "  response_code=%d",
-                    pszURL, fileSize, (int)response_code);
+                    m_pszURL, fileSize, (int)response_code);
     }
 
     CPLFree(sWriteFuncData.pBuffer);
     CPLFree(sWriteFuncHeaderData.pBuffer);
 
-    poFS->AcquireMutex();
-    CachedFileProp* cachedFileProp = poFS->GetCachedFileProp(pszURL);
-    cachedFileProp->bHastComputedFileSize = TRUE;
+    m_poFS->AcquireMutex();
+    CachedFileProp* cachedFileProp = m_poFS->GetCachedFileProp(m_pszURL);
+    cachedFileProp->bHasComputedFileSize = TRUE;
 #ifdef notdef
     cachedFileProp->nChecksumOfFirst1024Bytes = nRecomputedChecksumOfFirst1024Bytes;
 #endif
     cachedFileProp->fileSize = fileSize;
     cachedFileProp->eExists = eExists;
     cachedFileProp->bIsDirectory = bIsDirectory;
-    poFS->ReleaseMutex();
+    m_poFS->ReleaseMutex();
 
     vsi_l_offset nRet = fileSize;
     ReleaseMutex();
@@ -621,15 +671,15 @@ int VSICurlStreamingHandle::Exists()
         if (pszAllowedExtensions)
         {
             char** papszExtensions = CSLTokenizeString2( pszAllowedExtensions, ", ", 0 );
-            int nURLLen = strlen(pszURL);
-            int bFound = FALSE;
+            size_t nURLLen = strlen(m_pszURL);
+            bool bFound = false;
             for(int i=0;papszExtensions[i] != NULL;i++)
             {
-                int nExtensionLen = strlen(papszExtensions[i]);
+                size_t nExtensionLen = strlen(papszExtensions[i]);
                 if (nURLLen > nExtensionLen &&
-                    EQUAL(pszURL + nURLLen - nExtensionLen, papszExtensions[i]))
+                    EQUAL(m_pszURL + nURLLen - nExtensionLen, papszExtensions[i]))
                 {
-                    bFound = TRUE;
+                    bFound = true;
                     break;
                 }
             }
@@ -639,12 +689,12 @@ int VSICurlStreamingHandle::Exists()
                 eExists = EXIST_NO;
                 fileSize = 0;
 
-                poFS->AcquireMutex();
-                CachedFileProp* cachedFileProp = poFS->GetCachedFileProp(pszURL);
-                cachedFileProp->bHastComputedFileSize = TRUE;
+                m_poFS->AcquireMutex();
+                CachedFileProp* cachedFileProp = m_poFS->GetCachedFileProp(m_pszURL);
+                cachedFileProp->bHasComputedFileSize = TRUE;
                 cachedFileProp->fileSize = fileSize;
                 cachedFileProp->eExists = eExists;
-                poFS->ReleaseMutex();
+                m_poFS->ReleaseMutex();
 
                 CSLDestroy(papszExtensions);
 
@@ -658,10 +708,10 @@ int VSICurlStreamingHandle::Exists()
         int bExists = (Read(&chFirstByte, 1, 1) == 1);
 
         AcquireMutex();
-        poFS->AcquireMutex();
-        CachedFileProp* cachedFileProp = poFS->GetCachedFileProp(pszURL);
+        m_poFS->AcquireMutex();
+        CachedFileProp* cachedFileProp = m_poFS->GetCachedFileProp(m_pszURL);
         cachedFileProp->eExists = eExists = bExists ? EXIST_YES : EXIST_NO;
-        poFS->ReleaseMutex();
+        m_poFS->ReleaseMutex();
         ReleaseMutex();
 
         Seek(0, SEEK_SET);
@@ -683,7 +733,7 @@ vsi_l_offset VSICurlStreamingHandle::Tell()
 /*                         ReceivedBytes()                              */
 /************************************************************************/
 
-int VSICurlStreamingHandle::ReceivedBytes(GByte *buffer, size_t count, size_t nmemb)
+size_t VSICurlStreamingHandle::ReceivedBytes(GByte *buffer, size_t count, size_t nmemb)
 {
     size_t nSize = count * nmemb;
     nBodySize += nSize;
@@ -691,32 +741,32 @@ int VSICurlStreamingHandle::ReceivedBytes(GByte *buffer, size_t count, size_t nm
     if (ENABLE_DEBUG)
         CPLDebug("VSICURL", "Receiving %d bytes...", (int)nSize);
 
-    if( bHasCandidateFileSize && bCanTrustCandidateFileSize && !bHastComputedFileSize )
+    if( bHasCandidateFileSize && bCanTrustCandidateFileSize && !bHasComputedFileSize )
     {
-        poFS->AcquireMutex();
-        CachedFileProp* cachedFileProp = poFS->GetCachedFileProp(pszURL);
+        m_poFS->AcquireMutex();
+        CachedFileProp* cachedFileProp = m_poFS->GetCachedFileProp(m_pszURL);
         cachedFileProp->fileSize = fileSize = nCandidateFileSize;
-        cachedFileProp->bHastComputedFileSize = bHastComputedFileSize = TRUE;
+        cachedFileProp->bHasComputedFileSize = bHasComputedFileSize = TRUE;
         if (ENABLE_DEBUG)
             CPLDebug("VSICURL", "File size = " CPL_FRMT_GUIB, fileSize);
-        poFS->ReleaseMutex();
+        m_poFS->ReleaseMutex();
     }
 
     AcquireMutex();
     if (eExists == EXIST_UNKNOWN)
     {
-        poFS->AcquireMutex();
-        CachedFileProp* cachedFileProp = poFS->GetCachedFileProp(pszURL);
+        m_poFS->AcquireMutex();
+        CachedFileProp* cachedFileProp = m_poFS->GetCachedFileProp(m_pszURL);
         cachedFileProp->eExists = eExists = EXIST_YES;
-        poFS->ReleaseMutex();
+        m_poFS->ReleaseMutex();
     }
-    else if (eExists == EXIST_NO)
+    else if (eExists == EXIST_NO && StopReceivingBytesOnError() )
     {
         ReleaseMutex();
         return 0;
     }
 
-    while(TRUE)
+    while(true)
     {
         size_t nFree = oRingBuffer.GetCapacity() - oRingBuffer.GetSize();
         if (nSize <= nFree)
@@ -773,7 +823,7 @@ int VSICurlStreamingHandle::ReceivedBytes(GByte *buffer, size_t count, size_t nm
 /*                 VSICurlStreamingHandleReceivedBytes()                */
 /************************************************************************/
 
-static int VSICurlStreamingHandleReceivedBytes(void *buffer, size_t count, size_t nmemb, void *req)
+static size_t VSICurlStreamingHandleReceivedBytes(void *buffer, size_t count, size_t nmemb, void *req)
 {
     return ((VSICurlStreamingHandle*)req)->ReceivedBytes((GByte*)buffer, count, nmemb);
 }
@@ -785,16 +835,16 @@ static int VSICurlStreamingHandleReceivedBytes(void *buffer, size_t count, size_
 
 #define HEADER_SIZE 32768
 
-int VSICurlStreamingHandle::ReceivedBytesHeader(GByte *buffer, size_t count, size_t nmemb)
+size_t VSICurlStreamingHandle::ReceivedBytesHeader(GByte *buffer, size_t count, size_t nmemb)
 {
     size_t nSize = count * nmemb;
     if (ENABLE_DEBUG)
         CPLDebug("VSICURL", "Receiving %d bytes for header...", (int)nSize);
 
     /* Reset buffer if we have followed link after a redirect */
-    if (nSize >=9 && (nHTTPCode == 301 || nHTTPCode == 302) &&
-        (EQUALN((const char*)buffer, "HTTP/1.0 ", 9) ||
-         EQUALN((const char*)buffer, "HTTP/1.1 ", 9)))
+    if (nSize >=9 && InterpretRedirect() && (nHTTPCode == 301 || nHTTPCode == 302) &&
+        (STARTS_WITH_CI((const char*)buffer, "HTTP/1.0 ") ||
+         STARTS_WITH_CI((const char*)buffer, "HTTP/1.1 ")))
     {
         nHeaderSize = 0;
         nHTTPCode = 0;
@@ -813,24 +863,24 @@ int VSICurlStreamingHandle::ReceivedBytesHeader(GByte *buffer, size_t count, siz
 
         if (eExists == EXIST_UNKNOWN && nHTTPCode == 0 &&
             strchr((const char*)pabyHeaderData, '\n') != NULL &&
-            (EQUALN((const char*)pabyHeaderData, "HTTP/1.0 ", 9) ||
-                EQUALN((const char*)pabyHeaderData, "HTTP/1.1 ", 9)))
+            (STARTS_WITH_CI((const char*)pabyHeaderData, "HTTP/1.0 ") ||
+                STARTS_WITH_CI((const char*)pabyHeaderData, "HTTP/1.1 ")))
         {
             nHTTPCode = atoi((const char*)pabyHeaderData + 9);
             if (ENABLE_DEBUG)
                 CPLDebug("VSICURL", "HTTP code = %d", nHTTPCode);
 
             /* If moved permanently/temporarily, go on */
-            if( !(nHTTPCode == 301 || nHTTPCode == 302) )
+            if( !(InterpretRedirect() && (nHTTPCode == 301 || nHTTPCode == 302)) )
             {
-                poFS->AcquireMutex();
-                CachedFileProp* cachedFileProp = poFS->GetCachedFileProp(pszURL);
+                m_poFS->AcquireMutex();
+                CachedFileProp* cachedFileProp = m_poFS->GetCachedFileProp(m_pszURL);
                 cachedFileProp->eExists = eExists = (nHTTPCode == 200) ? EXIST_YES : EXIST_NO;
-                poFS->ReleaseMutex();
+                m_poFS->ReleaseMutex();
             }
         }
 
-        if ( !(nHTTPCode == 301 || nHTTPCode == 302) && !bHastComputedFileSize)
+        if ( !(InterpretRedirect() && (nHTTPCode == 301 || nHTTPCode == 302)) && !bHasComputedFileSize)
         {
             /* Caution: when gzip compression is enabled, the content-length is the compressed */
             /* size, which we are not interested in, so we must not take it into account. */
@@ -841,7 +891,7 @@ int VSICurlStreamingHandle::ReceivedBytesHeader(GByte *buffer, size_t count, siz
             {
                 const char* pszVal = pszContentLength + strlen("Content-Length: ");
                 bHasCandidateFileSize = TRUE;
-                nCandidateFileSize = CPLScanUIntBig(pszVal, pszEndOfLine - pszVal);
+                nCandidateFileSize = CPLScanUIntBig(pszVal, static_cast<int>(pszEndOfLine - pszVal));
                 if (ENABLE_DEBUG)
                     CPLDebug("VSICURL", "Has found candidate file size = " CPL_FRMT_GUIB, nCandidateFileSize);
             }
@@ -851,7 +901,7 @@ int VSICurlStreamingHandle::ReceivedBytesHeader(GByte *buffer, size_t count, siz
             if( bHasCandidateFileSize && pszEndOfLine != NULL )
             {
                 const char* pszVal = pszContentEncoding + strlen("Content-Encoding: ");
-                if( strncmp(pszVal, "gzip", 4) == 0 )
+                if( STARTS_WITH(pszVal, "gzip") )
                 {
                     if (ENABLE_DEBUG)
                         CPLDebug("VSICURL", "GZip compression enabled --> cannot trust candidate file size");
@@ -870,24 +920,28 @@ int VSICurlStreamingHandle::ReceivedBytesHeader(GByte *buffer, size_t count, siz
 /*                 VSICurlStreamingHandleReceivedBytesHeader()          */
 /************************************************************************/
 
-static int VSICurlStreamingHandleReceivedBytesHeader(void *buffer, size_t count, size_t nmemb, void *req)
+static size_t VSICurlStreamingHandleReceivedBytesHeader(void *buffer, size_t count, size_t nmemb, void *req)
 {
     return ((VSICurlStreamingHandle*)req)->ReceivedBytesHeader((GByte*)buffer, count, nmemb);
 }
+
 /************************************************************************/
 /*                       DownloadInThread()                             */
 /************************************************************************/
 
 void VSICurlStreamingHandle::DownloadInThread()
 {
-    VSICurlSetOptions(hCurlHandle, pszURL);
+    VSICurlSetOptions(hCurlHandle, m_pszURL);
+    struct curl_slist* headers = GetCurlHeaders("GET");
+    if( headers != NULL )
+        curl_easy_setopt(hCurlHandle, CURLOPT_HTTPHEADER, headers);
 
-    static int bHasCheckVersion = FALSE;
-    static int bSupportGZip = FALSE;
+    static bool bHasCheckVersion = false;
+    static bool bSupportGZip = false;
     if (!bHasCheckVersion)
     {
         bSupportGZip = strstr(curl_version(), "zlib/") != NULL;
-        bHasCheckVersion = TRUE;
+        bHasCheckVersion = true;
     }
     if (bSupportGZip && CSLTestBoolean(CPLGetConfigOption("CPL_CURL_GZIP", "YES")))
     {
@@ -911,6 +965,8 @@ void VSICurlStreamingHandle::DownloadInThread()
     curl_easy_setopt(hCurlHandle, CURLOPT_ERRORBUFFER, szCurlErrBuf );
 
     CURLcode eRet = curl_easy_perform(hCurlHandle);
+    if( headers != NULL )
+        curl_slist_free_all(headers);
 
     curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, NULL);
     curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION, NULL);
@@ -918,15 +974,15 @@ void VSICurlStreamingHandle::DownloadInThread()
     curl_easy_setopt(hCurlHandle, CURLOPT_HEADERFUNCTION, NULL);
 
     AcquireMutex();
-    if (!bAskDownloadEnd && eRet == 0 && !bHastComputedFileSize)
+    if (!bAskDownloadEnd && eRet == 0 && !bHasComputedFileSize)
     {
-        poFS->AcquireMutex();
-        CachedFileProp* cachedFileProp = poFS->GetCachedFileProp(pszURL);
+        m_poFS->AcquireMutex();
+        CachedFileProp* cachedFileProp = m_poFS->GetCachedFileProp(m_pszURL);
         cachedFileProp->fileSize = fileSize = nBodySize;
-        cachedFileProp->bHastComputedFileSize = bHastComputedFileSize = TRUE;
+        cachedFileProp->bHasComputedFileSize = bHasComputedFileSize = TRUE;
         if (ENABLE_DEBUG)
             CPLDebug("VSICURL", "File size = " CPL_FRMT_GUIB, fileSize);
-        poFS->ReleaseMutex();
+        m_poFS->ReleaseMutex();
     }
 
     bDownloadInProgress = FALSE;
@@ -952,7 +1008,9 @@ void VSICurlStreamingHandle::StartDownload()
         return;
 
     //if (ENABLE_DEBUG)
-        CPLDebug("VSICURL", "Start download for %s", pszURL);
+    {
+        CPLDebug("VSICURL", "Start download for %s", m_pszURL);
+    }
 
     if (hCurlHandle == NULL)
         hCurlHandle = curl_easy_init();
@@ -971,7 +1029,9 @@ void VSICurlStreamingHandle::StopDownload()
     if (hThread)
     {
         //if (ENABLE_DEBUG)
-            CPLDebug("VSICURL", "Stop download for %s", pszURL);
+        {
+            CPLDebug("VSICURL", "Stop download for %s", m_pszURL);
+        }
 
         AcquireMutex();
         /* Signal to the producer that we ask for download interruption */
@@ -1032,20 +1092,22 @@ void VSICurlStreamingHandle::PutRingBufferInCache()
 /*                                Read()                                */
 /************************************************************************/
 
-size_t VSICurlStreamingHandle::Read( void *pBuffer, size_t nSize, size_t nMemb )
+size_t VSICurlStreamingHandle::Read( void * const pBuffer, size_t const nSize, size_t const nMemb )
 {
     GByte* pabyBuffer = (GByte*)pBuffer;
-    size_t nBufferRequestSize = nSize * nMemb;
+    const size_t nBufferRequestSize = nSize * nMemb;
+    const vsi_l_offset curOffsetOri = curOffset;
+    const vsi_l_offset nRingBufferFileOffsetOri = nRingBufferFileOffset;
     if (nBufferRequestSize == 0)
         return 0;
     size_t nRemaining = nBufferRequestSize;
 
     AcquireMutex();
-    int bHastComputedFileSizeLocal = bHastComputedFileSize;
-    vsi_l_offset fileSizeLocal = fileSize;
+    const int bHasComputedFileSizeLocal = bHasComputedFileSize;
+    const vsi_l_offset fileSizeLocal = fileSize;
     ReleaseMutex();
 
-    if (bHastComputedFileSizeLocal && curOffset >= fileSizeLocal)
+    if (bHasComputedFileSizeLocal && curOffset >= fileSizeLocal)
     {
         CPLDebug("VSICURL", "Read attempt beyond end of file");
         bEOF = TRUE;
@@ -1058,7 +1120,7 @@ size_t VSICurlStreamingHandle::Read( void *pBuffer, size_t nSize, size_t nMemb )
 
     if (ENABLE_DEBUG)
         CPLDebug("VSICURL", "Read [" CPL_FRMT_GUIB ", " CPL_FRMT_GUIB "[ in %s",
-                 curOffset, curOffset + nBufferRequestSize, pszURL);
+                 curOffset, curOffset + nBufferRequestSize, m_pszURL);
 
 #ifdef notdef
     if( pCachedData != NULL && nCachedSize >= 1024 &&
@@ -1066,12 +1128,12 @@ size_t VSICurlStreamingHandle::Read( void *pBuffer, size_t nSize, size_t nMemb )
     {
         for(size_t i = 0; i < 1024 / sizeof(int); i ++)
         {
-            int nVal;
+          int nVal = 0;
             memcpy(&nVal, pCachedData + i * sizeof(int), sizeof(int));
             nRecomputedChecksumOfFirst1024Bytes += nVal;
         }
 
-        if( bHastComputedFileSizeLocal )
+        if( bHasComputedFileSizeLocal )
         {
             poFS->AcquireMutex();
             CachedFileProp* cachedFileProp = poFS->GetCachedFileProp(pszURL);
@@ -1083,8 +1145,8 @@ size_t VSICurlStreamingHandle::Read( void *pBuffer, size_t nSize, size_t nMemb )
             {
                 CPLDebug("VSICURL", "Invalidating previously cached file size. First bytes of file have changed!");
                 AcquireMutex();
-                bHastComputedFileSize = FALSE;
-                cachedFileProp->bHastComputedFileSize = FALSE;
+                bHasComputedFileSize = FALSE;
+                cachedFileProp->bHasComputedFileSize = FALSE;
                 cachedFileProp->nChecksumOfFirst1024Bytes = 0;
                 ReleaseMutex();
             }
@@ -1099,7 +1161,7 @@ size_t VSICurlStreamingHandle::Read( void *pBuffer, size_t nSize, size_t nMemb )
         size_t nSz = MIN(nRemaining, (size_t)(nCachedSize - curOffset));
         if (ENABLE_DEBUG)
             CPLDebug("VSICURL", "Using cache for [%d, %d[ in %s",
-                     (int)curOffset, (int)(curOffset + nSz), pszURL);
+                     (int)curOffset, (int)(curOffset + nSz), m_pszURL);
         memcpy(pabyBuffer, pCachedData + curOffset, nSz);
         pabyBuffer += nSz;
         curOffset += nSz;
@@ -1107,7 +1169,7 @@ size_t VSICurlStreamingHandle::Read( void *pBuffer, size_t nSize, size_t nMemb )
     }
 
     /* Is the request partially covered by the cache and going beyond file size ? */
-    if ( pCachedData != NULL && bHastComputedFileSizeLocal &&
+    if ( pCachedData != NULL && bHasComputedFileSizeLocal &&
          curOffset <= nCachedSize &&
          curOffset + nRemaining > fileSizeLocal &&
          fileSize == nCachedSize )
@@ -1115,7 +1177,7 @@ size_t VSICurlStreamingHandle::Read( void *pBuffer, size_t nSize, size_t nMemb )
         size_t nSz = (size_t) (nCachedSize - curOffset);
         if (ENABLE_DEBUG && nSz != 0)
             CPLDebug("VSICURL", "Using cache for [%d, %d[ in %s",
-                    (int)curOffset, (int)(curOffset + nSz), pszURL);
+                    (int)curOffset, (int)(curOffset + nSz), m_pszURL);
         memcpy(pabyBuffer, pCachedData + curOffset, nSz);
         pabyBuffer += nSz;
         curOffset += nSz;
@@ -1233,6 +1295,49 @@ size_t VSICurlStreamingHandle::Read( void *pBuffer, size_t nSize, size_t nMemb )
     if (nRet < nMemb)
         bEOF = TRUE;
 
+    /* Give a chance to specialized filesystem to deal with errors to redirect */
+    /* elsewhere */
+    if( curOffsetOri == 0 && nRingBufferFileOffsetOri == 0 &&
+        !StopReceivingBytesOnError() &&
+        eExists == EXIST_NO && nRemaining < nBufferRequestSize )
+    {
+        const size_t nErrorBufferMaxSize = 4096;
+        GByte* pabyErrorBuffer = (GByte*)CPLMalloc(nErrorBufferMaxSize + 1);
+        size_t nRead = nBufferRequestSize - nRemaining;
+        size_t nErrorBufferSize = MIN(nErrorBufferMaxSize, nRead);
+        memcpy( pabyErrorBuffer, pBuffer, nErrorBufferSize );
+        if( nRead < nErrorBufferMaxSize )
+            nErrorBufferSize += Read( pabyErrorBuffer + nRead, 1, nErrorBufferMaxSize - nRead );
+        pabyErrorBuffer[nErrorBufferSize] = 0;
+        StopDownload();
+        if( CanRestartOnError((const char*)pabyErrorBuffer, true) )
+        {
+            curOffset = 0;
+            nRingBufferFileOffset = 0;
+            bEOF = FALSE;
+            AcquireMutex();
+            eExists = EXIST_UNKNOWN;
+            bHasComputedFileSize = FALSE;
+            fileSize = 0;
+            ReleaseMutex();
+            nCachedSize = 0;
+            m_poFS->AcquireMutex();
+            CachedFileProp* cachedFileProp = m_poFS->GetCachedFileProp(m_pszURL);
+            cachedFileProp->bHasComputedFileSize = FALSE;
+            cachedFileProp->fileSize = 0;
+            cachedFileProp->eExists = EXIST_UNKNOWN;
+            m_poFS->ReleaseMutex();
+            nRet = Read(pBuffer, nSize, nMemb);
+        }
+        else
+        {
+            CPLDebug("VSICURL", "Error buffer: %s", (const char*)pabyErrorBuffer);
+            nRet = 0;
+        }
+
+        CPLFree(pabyErrorBuffer);
+    }
+
     return nRet;
 }
 
@@ -1247,8 +1352,8 @@ void  VSICurlStreamingHandle::AddRegion( vsi_l_offset    nFileOffsetStart,
     if (nFileOffsetStart >= BKGND_BUFFER_SIZE)
         return;
 
-        if (pCachedData == NULL)
-            pCachedData = (GByte*) CPLMalloc(BKGND_BUFFER_SIZE);
+    if (pCachedData == NULL)
+        pCachedData = (GByte*) CPLMalloc(BKGND_BUFFER_SIZE);
 
     if (nFileOffsetStart <= nCachedSize &&
         nFileOffsetStart + nSize > nCachedSize)
@@ -1256,7 +1361,7 @@ void  VSICurlStreamingHandle::AddRegion( vsi_l_offset    nFileOffsetStart,
         size_t nSz = MIN(nSize, (size_t) (BKGND_BUFFER_SIZE - nFileOffsetStart));
         if (ENABLE_DEBUG)
             CPLDebug("VSICURL", "Writing [%d, %d[ in cache for %s",
-                     (int)nFileOffsetStart, (int)(nFileOffsetStart + nSz), pszURL);
+                     (int)nFileOffsetStart, (int)(nFileOffsetStart + nSz), m_pszURL);
         memcpy(pCachedData + nFileOffsetStart, pData, nSz);
         nCachedSize = (size_t) (nFileOffsetStart + nSz);
     }
@@ -1361,7 +1466,7 @@ CachedFileProp*  VSICurlStreamingFSHandler::GetCachedFileProp(const char* pszURL
     {
         cachedFileProp = (CachedFileProp*) CPLMalloc(sizeof(CachedFileProp));
         cachedFileProp->eExists = EXIST_UNKNOWN;
-        cachedFileProp->bHastComputedFileSize = FALSE;
+        cachedFileProp->bHasComputedFileSize = FALSE;
         cachedFileProp->fileSize = 0;
         cachedFileProp->bIsDirectory = FALSE;
 #ifdef notdef
@@ -1374,27 +1479,36 @@ CachedFileProp*  VSICurlStreamingFSHandler::GetCachedFileProp(const char* pszURL
 }
 
 /************************************************************************/
+/*                          CreateFileHandle()                          */
+/************************************************************************/
+
+VSICurlStreamingHandle* VSICurlStreamingFSHandler::CreateFileHandle(const char* pszURL)
+{
+    return new VSICurlStreamingHandle(this, pszURL);
+}
+
+/************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
 
 VSIVirtualHandle* VSICurlStreamingFSHandler::Open( const char *pszFilename,
-                                                   const char *pszAccess )
+                                                   const char *pszAccess,
+                                                   bool /* bSetError */ )
 {
     if (strchr(pszAccess, 'w') != NULL ||
         strchr(pszAccess, '+') != NULL)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
-                 "Only read-only mode is supported for /vsicurl_streaming");
+                 "Only read-only mode is supported for %s", GetFSPrefix().c_str());
         return NULL;
     }
 
-    VSICurlStreamingHandle* poHandle = new VSICurlStreamingHandle(
-        this, pszFilename + strlen("/vsicurl_streaming/"));
+    VSICurlStreamingHandle* poHandle = CreateFileHandle(pszFilename + GetFSPrefix().size());
     /* If we didn't get a filelist, check that the file really exists */
-    if (!poHandle->Exists())
+    if (poHandle == NULL || !poHandle->Exists())
     {
         delete poHandle;
-        poHandle = NULL;
+        return NULL;
     }
 
     if( CSLTestBoolean( CPLGetConfigOption( "VSI_CACHE", "FALSE" ) ) )
@@ -1415,15 +1529,20 @@ int VSICurlStreamingFSHandler::Stat( const char *pszFilename,
 
     memset(pStatBuf, 0, sizeof(VSIStatBufL));
 
-    VSICurlStreamingHandle oHandle( this, osFilename + strlen("/vsicurl_streaming/"));
-
-    if ( oHandle.IsKnownFileSize() ||
-         ((nFlags & VSI_STAT_SIZE_FLAG) && !oHandle.IsDirectory() &&
+    VSICurlStreamingHandle* poHandle = CreateFileHandle(pszFilename + GetFSPrefix().size());
+    if( poHandle == NULL )
+    {
+        return -1;
+    }
+    if ( poHandle->IsKnownFileSize() ||
+         ((nFlags & VSI_STAT_SIZE_FLAG) && !poHandle->IsDirectory() &&
            CSLTestBoolean(CPLGetConfigOption("CPL_VSIL_CURL_SLOW_GET_SIZE", "YES"))) )
-        pStatBuf->st_size = oHandle.GetFileSize();
+        pStatBuf->st_size = poHandle->GetFileSize();
 
-    int nRet = (oHandle.Exists()) ? 0 : -1;
-    pStatBuf->st_mode = oHandle.IsDirectory() ? S_IFDIR : S_IFREG;
+    int nRet = (poHandle->Exists()) ? 0 : -1;
+    pStatBuf->st_mode = poHandle->IsDirectory() ? S_IFDIR : S_IFREG;
+
+    delete poHandle;
     return nRet;
 }
 
@@ -1434,9 +1553,9 @@ int VSICurlStreamingFSHandler::Stat( const char *pszFilename,
 /**
  * \brief Install /vsicurl_streaming/ HTTP/FTP file system handler (requires libcurl)
  *
- * A special file handler is installed that allows on-the-fly reading of files
+ * A special file handler is installed that allows on-the-fly sequential reading of files
  * streamed through HTTP/FTP web protocols (typically dynamically generated files),
- * without downloading the entire file.
+ * without prior download of the entire file.
  *
  * Although this file handler is able seek to random offsets in the file, this will not
  * be efficient. If you need efficient random access and that the server supports range
@@ -1465,14 +1584,178 @@ void VSIInstallCurlStreamingFileHandler(void)
     VSIFileManager::InstallHandler( "/vsicurl_streaming/", new VSICurlStreamingFSHandler );
 }
 
-#ifdef AS_PLUGIN
-CPL_C_START
-void CPL_DLL GDALRegisterMe();
-void GDALRegisterMe()
+
+/************************************************************************/
+/*                       VSIS3StreamingFSHandler                        */
+/************************************************************************/
+
+class VSIS3StreamingFSHandler CPL_FINAL: public VSICurlStreamingFSHandler
 {
-    VSIInstallCurlStreamingFileHandler();
+    std::map< CPLString, VSIS3UpdateParams > oMapBucketsToS3Params;
+
+protected:
+    virtual CPLString GetFSPrefix() { return "/vsis3_streaming/"; }
+    virtual VSICurlStreamingHandle* CreateFileHandle(const char* pszURL);
+
+public:
+        VSIS3StreamingFSHandler() {}
+
+        void UpdateMapFromHandle(VSIS3HandleHelper * poS3HandleHelper);
+        void UpdateHandleFromMap(VSIS3HandleHelper * poS3HandleHelper);
+};
+
+/************************************************************************/
+/*                         UpdateMapFromHandle()                        */
+/************************************************************************/
+
+void VSIS3StreamingFSHandler::UpdateMapFromHandle(VSIS3HandleHelper * poS3HandleHelper)
+{
+    CPLMutexHolder oHolder( &hMutex );
+
+    oMapBucketsToS3Params[ poS3HandleHelper->GetBucket() ] =
+        VSIS3UpdateParams ( poS3HandleHelper->GetAWSRegion(),
+                      poS3HandleHelper->GetAWSS3Endpoint(),
+                      poS3HandleHelper->GetVirtualHosting() );
 }
-CPL_C_END
-#endif
+
+/************************************************************************/
+/*                         UpdateHandleFromMap()                        */
+/************************************************************************/
+
+void VSIS3StreamingFSHandler::UpdateHandleFromMap(VSIS3HandleHelper * poS3HandleHelper)
+{
+    CPLMutexHolder oHolder( &hMutex );
+
+    std::map< CPLString, VSIS3UpdateParams>::iterator oIter =
+        oMapBucketsToS3Params.find(poS3HandleHelper->GetBucket());
+    if( oIter != oMapBucketsToS3Params.end() )
+    {
+        poS3HandleHelper->SetAWSRegion( oIter->second.m_osAWSRegion );
+        poS3HandleHelper->SetAWSS3Endpoint( oIter->second.m_osAWSS3Endpoint );
+        poS3HandleHelper->SetVirtualHosting( oIter->second.m_bUseVirtualHosting );
+    }
+}
+
+/************************************************************************/
+/*                            VSIS3StreamingHandle                      */
+/************************************************************************/
+
+class VSIS3StreamingHandle CPL_FINAL: public VSICurlStreamingHandle
+{
+    VSIS3HandleHelper* m_poS3HandleHelper;
+
+  protected:
+        virtual struct curl_slist* GetCurlHeaders(const CPLString& osVerb);
+        virtual bool StopReceivingBytesOnError() { return false; }
+        virtual bool CanRestartOnError(const char*, bool);
+        virtual bool InterpretRedirect() { return false; }
+
+    public:
+        VSIS3StreamingHandle(VSIS3StreamingFSHandler* poFS,
+                             VSIS3HandleHelper* poS3HandleHelper);
+        ~VSIS3StreamingHandle();
+};
+
+/************************************************************************/
+/*                          CreateFileHandle()                          */
+/************************************************************************/
+
+VSICurlStreamingHandle* VSIS3StreamingFSHandler::CreateFileHandle(const char* pszURL)
+{
+    VSIS3HandleHelper* poS3HandleHelper =
+            VSIS3HandleHelper::BuildFromURI(pszURL, GetFSPrefix().c_str(), false);
+    if( poS3HandleHelper )
+    {
+        UpdateHandleFromMap(poS3HandleHelper);
+        return new VSIS3StreamingHandle(this, poS3HandleHelper);
+    }
+    return NULL;
+}
+
+/************************************************************************/
+/*                        VSIS3StreamingHandle()                        */
+/************************************************************************/
+
+VSIS3StreamingHandle::VSIS3StreamingHandle(VSIS3StreamingFSHandler* poFS,
+                                           VSIS3HandleHelper* poS3HandleHelper) :
+        VSICurlStreamingHandle(poFS, poS3HandleHelper->GetURL()),
+        m_poS3HandleHelper(poS3HandleHelper)
+{
+}
+
+/************************************************************************/
+/*                       ~VSIS3StreamingHandle()                        */
+/************************************************************************/
+
+VSIS3StreamingHandle::~VSIS3StreamingHandle()
+{
+    delete m_poS3HandleHelper;
+}
+
+/************************************************************************/
+/*                           GetCurlHeaders()                           */
+/************************************************************************/
+
+struct curl_slist* VSIS3StreamingHandle::GetCurlHeaders(const CPLString& osVerb)
+{
+    return m_poS3HandleHelper->GetCurlHeaders(osVerb);
+}
+
+/************************************************************************/
+/*                          CanRestartOnError()                         */
+/************************************************************************/
+
+bool VSIS3StreamingHandle::CanRestartOnError(const char* pszErrorMsg, bool bSetError)
+{
+    if( m_poS3HandleHelper->CanRestartOnError(pszErrorMsg, bSetError) )
+    {
+        ((VSIS3StreamingFSHandler*) m_poFS)->UpdateMapFromHandle(m_poS3HandleHelper);
+
+        SetURL(m_poS3HandleHelper->GetURL());
+        return true;
+    }
+    return false;
+}
+
+/************************************************************************/
+/*                   VSIInstallS3StreamingFileHandler()                 */
+/************************************************************************/
+
+/**
+ * \brief Install /vsis3_streaming/ Amazon S3 file system handler (requires libcurl)
+ *
+ * A special file handler is installed that allows on-the-fly sequential reading of files
+ * streamed from AWS S3 buckets without prior download of the entire file.
+ *
+ * Recognized filenames are of the form /vsis3_streaming/bucket/key where
+ * bucket is the name of the S3 bucket and resource the S3 object "key", i.e.
+ * a filename potentially containing subdirectories.
+ *
+ * The AWS_SECRET_ACCESS_KEY and AWS_ACCESS_KEY_ID configuration options *must* be
+ * set.
+ * The AWS_SESSION_TOKEN configuration option must be set when temporary credentials
+ * are used.
+ * The AWS_REGION configuration option may be set to one of the supported
+ * <a href="http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region">S3 regions</a>
+ * and defaults to 'us-east-1'
+ * The AWS_S3_ENDPOINT configuration option defaults to s3.amazonaws.com.
+ *
+ * The GDAL_HTTP_PROXY, GDAL_HTTP_PROXYUSERPWD and GDAL_PROXY_AUTH configuration options can be
+ * used to define a proxy server. The syntax to use is the one of Curl CURLOPT_PROXY,
+ * CURLOPT_PROXYUSERPWD and CURLOPT_PROXYAUTH options.
+ *
+ * The file can be cached in RAM by setting the configuration option
+ * VSI_CACHE to TRUE. The cache size defaults to 25 MB, but can be modified by setting
+ * the configuration option VSI_CACHE_SIZE (in bytes).
+ *
+ * VSIStatL() will return the size in st_size member.
+ *
+ * @since GDAL 2.1
+ */
+void VSIInstallS3StreamingFileHandler(void)
+{
+    VSIFileManager::InstallHandler( "/vsis3_streaming/", new VSIS3StreamingFSHandler );
+}
+
 
 #endif /*  !defined(HAVE_CURL) || defined(CPL_MULTIPROC_STUB) */
diff --git a/port/cpl_vsil_gzip.cpp b/port/cpl_vsil_gzip.cpp
index 91bfb6c..5ff47c8 100644
--- a/port/cpl_vsil_gzip.cpp
+++ b/port/cpl_vsil_gzip.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsil_gzip.cpp 29033 2015-04-27 10:47:22Z rouault $
+ * $Id: cpl_vsil_gzip.cpp 33758 2016-03-21 09:06:22Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for gz/zip files (.gz and .zip).
@@ -62,7 +62,7 @@
    API. It also adds the capability to seek at the end of the file, which is not
    implemented in original gzSeek. It also implements a concept of in-memory "snapshots",
    that are a way of improving efficiency while seeking GZip files. Snapshots are
-   ceated regularly when decompressing  the data a snapshot of the gzip state.
+   created regularly when decompressing  the data a snapshot of the gzip state.
    Later we can seek directly in the compressed data to the closest snapshot in order to
    reduce the amount of data to uncompress again.
 
@@ -84,7 +84,7 @@
 #include "cpl_minizip_unzip.h"
 #include "cpl_time.h"
 
-CPL_CVSID("$Id: cpl_vsil_gzip.cpp 29033 2015-04-27 10:47:22Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_gzip.cpp 33758 2016-03-21 09:06:22Z rouault $");
 
 #define Z_BUFSIZE 65536  /* original size is 16384 */
 static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
@@ -121,16 +121,16 @@ typedef struct
     vsi_l_offset  out;
 } GZipSnapshot;
 
-class VSIGZipHandle : public VSIVirtualHandle
+class VSIGZipHandle CPL_FINAL : public VSIVirtualHandle
 {
-    VSIVirtualHandle* poBaseHandle;
-    vsi_l_offset      offset;
-    vsi_l_offset      compressed_size;
-    vsi_l_offset      uncompressed_size;
+    VSIVirtualHandle* m_poBaseHandle;
+    vsi_l_offset      m_offset;
+    vsi_l_offset      m_compressed_size;
+    vsi_l_offset      m_uncompressed_size;
     vsi_l_offset      offsetEndCompressedData;
-    unsigned int      expected_crc;
-    char             *pszBaseFileName; /* optional */
-    int               bCanSaveInfo;
+    uLong             m_expected_crc;
+    char             *m_pszBaseFileName; /* optional */
+    int               m_bCanSaveInfo;
 
     /* Fields from gz_stream structure */
     z_stream stream;
@@ -139,12 +139,12 @@ class VSIGZipHandle : public VSIVirtualHandle
     Byte     *inbuf;  /* input buffer */
     Byte     *outbuf; /* output buffer */
     uLong    crc;     /* crc32 of uncompressed data */
-    int      transparent; /* 1 if input file is not a .gz file */
+    int      m_transparent; /* 1 if input file is not a .gz file */
     vsi_l_offset  startOff;   /* startOff of compressed data in file (header skipped) */
     vsi_l_offset  in;      /* bytes into deflate or inflate */
     vsi_l_offset  out;     /* bytes out of deflate or inflate */
-    vsi_l_offset  nLastReadOffset;
-    
+    vsi_l_offset  m_nLastReadOffset;
+
     GZipSnapshot* snapshots;
     vsi_l_offset snapshot_byte_interval; /* number of compressed bytes at which we create a "snapshot" */
 
@@ -161,10 +161,12 @@ class VSIGZipHandle : public VSIVirtualHandle
                   vsi_l_offset offset = 0,
                   vsi_l_offset compressed_size = 0,
                   vsi_l_offset uncompressed_size = 0,
-                  unsigned int expected_crc = 0,
+                  uLong expected_crc = 0,
                   int transparent = 0);
     ~VSIGZipHandle();
 
+    bool              IsInitOK() const { return inbuf != NULL; }
+
     virtual int       Seek( vsi_l_offset nOffset, int nWhence );
     virtual vsi_l_offset Tell();
     virtual size_t    Read( void *pBuffer, size_t nSize, size_t nMemb );
@@ -174,37 +176,40 @@ class VSIGZipHandle : public VSIVirtualHandle
     virtual int       Close();
 
     VSIGZipHandle*    Duplicate();
-    void              CloseBaseHandle();
+    bool              CloseBaseHandle();
+
+    vsi_l_offset      GetLastReadOffset() { return m_nLastReadOffset; }
+    const char*       GetBaseFileName() { return m_pszBaseFileName; }
 
-    vsi_l_offset      GetLastReadOffset() { return nLastReadOffset; }
-    const char*       GetBaseFileName() { return pszBaseFileName; }
+    void              SetUncompressedSize(vsi_l_offset nUncompressedSize) { m_uncompressed_size = nUncompressedSize; }
+    vsi_l_offset      GetUncompressedSize() { return m_uncompressed_size; }
 
-    void              SetUncompressedSize(vsi_l_offset nUncompressedSize) { uncompressed_size = nUncompressedSize; }
-    vsi_l_offset      GetUncompressedSize() { return uncompressed_size; }
-    
     void              SaveInfo_unlocked();
 };
 
 
-class VSIGZipFilesystemHandler : public VSIFilesystemHandler 
+class VSIGZipFilesystemHandler CPL_FINAL : public VSIFilesystemHandler
 {
     CPLMutex* hMutex;
     VSIGZipHandle* poHandleLastGZipFile;
-    
+
 public:
     VSIGZipFilesystemHandler();
     ~VSIGZipFilesystemHandler();
 
-    virtual VSIVirtualHandle *Open( const char *pszFilename, 
-                                    const char *pszAccess);
-    VSIGZipHandle *OpenGZipReadOnly( const char *pszFilename, 
-                                     const char *pszAccess);
+    using VSIFilesystemHandler::Open;
+
+    virtual VSIVirtualHandle *Open( const char *pszFilename,
+                                    const char *pszAccess,
+                                    bool bSetError );
+    VSIGZipHandle *OpenGZipReadOnly( const char *pszFilename,
+                                     const char *pszAccess );
     virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags );
     virtual int      Unlink( const char *pszFilename );
     virtual int      Rename( const char *oldpath, const char *newpath );
     virtual int      Mkdir( const char *pszDirname, long nMode );
     virtual int      Rmdir( const char *pszDirname );
-    virtual char   **ReadDir( const char *pszDirname );
+    virtual char   **ReadDirEx( const char *pszDirname, int nMaxFiles );
 
     void  SaveInfo( VSIGZipHandle* poHandle );
     void  SaveInfo_unlocked( VSIGZipHandle* poHandle );
@@ -217,31 +222,35 @@ public:
 
 VSIGZipHandle* VSIGZipHandle::Duplicate()
 {
-    CPLAssert (offset == 0);
-    CPLAssert (compressed_size != 0);
-    CPLAssert (pszBaseFileName != NULL);
+    CPLAssert (m_offset == 0);
+    CPLAssert (m_compressed_size != 0);
+    CPLAssert (m_pszBaseFileName != NULL);
 
-    VSIFilesystemHandler *poFSHandler = 
-        VSIFileManager::GetHandler( pszBaseFileName );
+    VSIFilesystemHandler *poFSHandler =
+        VSIFileManager::GetHandler( m_pszBaseFileName );
 
     VSIVirtualHandle* poNewBaseHandle =
-        poFSHandler->Open( pszBaseFileName, "rb" );
+        poFSHandler->Open( m_pszBaseFileName, "rb" );
 
     if (poNewBaseHandle == NULL)
         return NULL;
 
     VSIGZipHandle* poHandle = new VSIGZipHandle(poNewBaseHandle,
-                                                pszBaseFileName,
+                                                m_pszBaseFileName,
                                                 0,
-                                                compressed_size,
-                                                uncompressed_size);
+                                                m_compressed_size,
+                                                m_uncompressed_size);
+    if( !(poHandle->IsInitOK()) )
+    {
+        delete poHandle;
+        return NULL;
+    }
 
-    poHandle->nLastReadOffset = nLastReadOffset;
+    poHandle->m_nLastReadOffset = m_nLastReadOffset;
 
     /* Most important : duplicate the snapshots ! */
 
-    unsigned int i;
-    for(i=0;i<compressed_size / snapshot_byte_interval + 1;i++)
+    for(unsigned int i=0;i<m_compressed_size / snapshot_byte_interval + 1;i++)
     {
         if (snapshots[i].uncompressed_pos == 0)
             break;
@@ -261,11 +270,13 @@ VSIGZipHandle* VSIGZipHandle::Duplicate()
 /*                     CloseBaseHandle()                                */
 /************************************************************************/
 
-void  VSIGZipHandle::CloseBaseHandle()
+bool  VSIGZipHandle::CloseBaseHandle()
 {
-    if (poBaseHandle)
-        VSIFCloseL((VSILFILE*)poBaseHandle);
-    poBaseHandle = NULL;
+    bool bRet = true;
+    if (m_poBaseHandle)
+        bRet = VSIFCloseL((VSILFILE*)m_poBaseHandle) == 0;
+    m_poBaseHandle = NULL;
+    return bRet;
 }
 
 /************************************************************************/
@@ -277,42 +288,47 @@ VSIGZipHandle::VSIGZipHandle(VSIVirtualHandle* poBaseHandle,
                              vsi_l_offset offset,
                              vsi_l_offset compressed_size,
                              vsi_l_offset uncompressed_size,
-                             unsigned int expected_crc,
-                             int transparent)
-{
-    this->poBaseHandle = poBaseHandle;
-    this->expected_crc = expected_crc;
-    this->pszBaseFileName = (pszBaseFileName) ? CPLStrdup(pszBaseFileName) : NULL;
-    bCanSaveInfo = TRUE;
-    this->offset = offset;
+                             uLong expected_crc,
+                             int transparent) :
+    snapshot_byte_interval(0)
+{
+    m_poBaseHandle = poBaseHandle;
+    m_expected_crc = expected_crc;
+    m_pszBaseFileName = (pszBaseFileName) ? CPLStrdup(pszBaseFileName) : NULL;
+    m_bCanSaveInfo = TRUE;
+    m_offset = offset;
     if (compressed_size || transparent)
     {
-        this->compressed_size = compressed_size;
+        m_compressed_size = compressed_size;
     }
     else
     {
-        VSIFSeekL((VSILFILE*)poBaseHandle, 0, SEEK_END);
-        this->compressed_size = VSIFTellL((VSILFILE*)poBaseHandle) - offset;
-        compressed_size = this->compressed_size;
+        if( VSIFSeekL((VSILFILE*)poBaseHandle, 0, SEEK_END) != 0 )
+            CPLError(CE_Failure, CPLE_FileIO, "Seek() failed");
+        m_compressed_size = VSIFTellL((VSILFILE*)poBaseHandle) - offset;
+        compressed_size = m_compressed_size;
     }
-    this->uncompressed_size = uncompressed_size;
+    m_uncompressed_size = uncompressed_size;
     offsetEndCompressedData = offset + compressed_size;
 
-    VSIFSeekL((VSILFILE*)poBaseHandle, offset, SEEK_SET);
+    if( VSIFSeekL((VSILFILE*)poBaseHandle, offset, SEEK_SET) != 0 )
+        CPLError(CE_Failure, CPLE_FileIO, "Seek() failed");
 
-    nLastReadOffset = 0;
-    stream.zalloc = (alloc_func)0;
-    stream.zfree = (free_func)0;
-    stream.opaque = (voidpf)0;
-    stream.next_in = inbuf = Z_NULL;
-    stream.next_out = outbuf = Z_NULL;
+    m_nLastReadOffset = 0;
+    stream.zalloc = (alloc_func)NULL;
+    stream.zfree = (free_func)NULL;
+    stream.opaque = (voidpf)NULL;
+    stream.next_in = inbuf = NULL;
+    stream.next_out = outbuf = NULL;
     stream.avail_in = stream.avail_out = 0;
     z_err = Z_OK;
     z_eof = 0;
     in = 0;
     out = 0;
-    crc = crc32(0L, Z_NULL, 0);
-    this->transparent = transparent;
+    crc = crc32(0L, NULL, 0);
+    m_transparent = transparent;
+    startOff = 0;
+    snapshots = NULL;
 
     stream.next_in  = inbuf = (Byte*)ALLOC(Z_BUFSIZE);
 
@@ -323,8 +339,11 @@ VSIGZipHandle::VSIGZipHandle(VSIVirtualHandle* poBaseHandle,
         * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
         * present after the compressed stream.
         */
-    if (err != Z_OK || inbuf == Z_NULL) {
+    if (err != Z_OK || inbuf == NULL) {
         CPLError(CE_Failure, CPLE_NotSupported, "inflateInit2 init failed");
+        TRYFREE(inbuf);
+        inbuf = NULL;
+        return;
     }
     stream.avail_out = Z_BUFSIZE;
 
@@ -336,10 +355,6 @@ VSIGZipHandle::VSIGZipHandle(VSIVirtualHandle* poBaseHandle,
         snapshot_byte_interval = MAX(Z_BUFSIZE, compressed_size / 100);
         snapshots = (GZipSnapshot*)CPLCalloc(sizeof(GZipSnapshot), (size_t) (compressed_size / snapshot_byte_interval + 1));
     }
-    else
-    {
-        snapshots = NULL;
-    }
 }
 
 /************************************************************************/
@@ -348,12 +363,12 @@ VSIGZipHandle::VSIGZipHandle(VSIVirtualHandle* poBaseHandle,
 
 void VSIGZipHandle::SaveInfo_unlocked()
 {
-    if (pszBaseFileName && bCanSaveInfo)
+    if (m_pszBaseFileName && m_bCanSaveInfo)
     {
-        VSIFilesystemHandler *poFSHandler = 
+        VSIFilesystemHandler *poFSHandler =
             VSIFileManager::GetHandler( "/vsigzip/" );
         ((VSIGZipFilesystemHandler*)poFSHandler)->SaveInfo_unlocked(this);
-        bCanSaveInfo = FALSE;
+        m_bCanSaveInfo = FALSE;
     }
 }
 
@@ -363,14 +378,13 @@ void VSIGZipHandle::SaveInfo_unlocked()
 
 VSIGZipHandle::~VSIGZipHandle()
 {
-    
-    if (pszBaseFileName && bCanSaveInfo)
+    if (m_pszBaseFileName && m_bCanSaveInfo)
     {
-        VSIFilesystemHandler *poFSHandler = 
+        VSIFilesystemHandler *poFSHandler =
             VSIFileManager::GetHandler( "/vsigzip/" );
         ((VSIGZipFilesystemHandler*)poFSHandler)->SaveInfo(this);
     }
-    
+
     if (stream.state != NULL) {
         inflateEnd(&(stream));
     }
@@ -380,8 +394,7 @@ VSIGZipHandle::~VSIGZipHandle()
 
     if (snapshots != NULL)
     {
-        unsigned int i;
-        for(i=0;i<compressed_size / snapshot_byte_interval + 1;i++)
+        for(size_t i=0;i<m_compressed_size / snapshot_byte_interval + 1;i++)
         {
             if (snapshots[i].uncompressed_pos)
             {
@@ -390,10 +403,10 @@ VSIGZipHandle::~VSIGZipHandle()
         }
         CPLFree(snapshots);
     }
-    CPLFree(pszBaseFileName);
+    CPLFree(m_pszBaseFileName);
 
-    if (poBaseHandle)
-        VSIFCloseL((VSILFILE*)poBaseHandle);
+    if (m_poBaseHandle)
+        CPL_IGNORE_RET_VAL(VSIFCloseL((VSILFILE*)m_poBaseHandle));
 }
 
 /************************************************************************/
@@ -402,35 +415,31 @@ VSIGZipHandle::~VSIGZipHandle()
 
 void VSIGZipHandle::check_header()
 {
-    int method; /* method byte */
-    int flags;  /* flags byte */
-    uInt len;
-    int c;
-
     /* Assure two bytes in the buffer so we can peek ahead -- handle case
     where first byte of header is at the end of the buffer after the last
     gzip segment */
-    len = stream.avail_in;
+    uInt len = stream.avail_in;
     if (len < 2) {
         if (len) inbuf[0] = stream.next_in[0];
         errno = 0;
-        len = (uInt)VSIFReadL(inbuf + len, 1, Z_BUFSIZE >> len, (VSILFILE*)poBaseHandle);
+        len = (uInt)VSIFReadL(inbuf + len, 1, Z_BUFSIZE >> len, (VSILFILE*)m_poBaseHandle);
         if (ENABLE_DEBUG) CPLDebug("GZIP", CPL_FRMT_GUIB " " CPL_FRMT_GUIB,
-                                    VSIFTellL((VSILFILE*)poBaseHandle), offsetEndCompressedData);
-        if (VSIFTellL((VSILFILE*)poBaseHandle) > offsetEndCompressedData)
+                                    VSIFTellL((VSILFILE*)m_poBaseHandle), offsetEndCompressedData);
+        if (VSIFTellL((VSILFILE*)m_poBaseHandle) > offsetEndCompressedData)
         {
-            len = len + (uInt) (offsetEndCompressedData - VSIFTellL((VSILFILE*)poBaseHandle));
-            VSIFSeekL((VSILFILE*)poBaseHandle, offsetEndCompressedData, SEEK_SET);
+            len = len + (uInt) (offsetEndCompressedData - VSIFTellL((VSILFILE*)m_poBaseHandle));
+            if(VSIFSeekL((VSILFILE*)m_poBaseHandle, offsetEndCompressedData, SEEK_SET) != 0)
+                z_err = Z_DATA_ERROR;
         }
         if (len == 0 /* && ferror(file)*/)
         {
-            if (VSIFTellL((VSILFILE*)poBaseHandle) != offsetEndCompressedData)
+            if (VSIFTellL((VSILFILE*)m_poBaseHandle) != offsetEndCompressedData)
                 z_err = Z_ERRNO;
         }
         stream.avail_in += len;
         stream.next_in = inbuf;
         if (stream.avail_in < 2) {
-            transparent = stream.avail_in;
+            m_transparent = stream.avail_in;
             return;
         }
     }
@@ -438,15 +447,15 @@ void VSIGZipHandle::check_header()
     /* Peek ahead to check the gzip magic header */
     if (stream.next_in[0] != gz_magic[0] ||
         stream.next_in[1] != gz_magic[1]) {
-        transparent = 1;
+        m_transparent = 1;
         return;
     }
     stream.avail_in -= 2;
     stream.next_in += 2;
 
     /* Check the rest of the gzip header */
-    method = get_byte();
-    flags = get_byte();
+    const int method = get_byte();
+    const int flags = get_byte();
     if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
         z_err = Z_DATA_ERROR;
         return;
@@ -461,6 +470,8 @@ void VSIGZipHandle::check_header()
         /* len is garbage if EOF but the loop below will quit anyway */
         while (len-- != 0 && get_byte() != EOF) ;
     }
+
+    int c = 0;
     if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
         while ((c = get_byte()) != 0 && c != EOF) ;
     }
@@ -482,17 +493,18 @@ int VSIGZipHandle::get_byte()
     if (z_eof) return EOF;
     if (stream.avail_in == 0) {
         errno = 0;
-        stream.avail_in = (uInt)VSIFReadL(inbuf, 1, Z_BUFSIZE, (VSILFILE*)poBaseHandle);
+        stream.avail_in = (uInt)VSIFReadL(inbuf, 1, Z_BUFSIZE, (VSILFILE*)m_poBaseHandle);
         if (ENABLE_DEBUG) CPLDebug("GZIP", CPL_FRMT_GUIB " " CPL_FRMT_GUIB,
-                                   VSIFTellL((VSILFILE*)poBaseHandle), offsetEndCompressedData);
-        if (VSIFTellL((VSILFILE*)poBaseHandle) > offsetEndCompressedData)
+                                   VSIFTellL((VSILFILE*)m_poBaseHandle), offsetEndCompressedData);
+        if (VSIFTellL((VSILFILE*)m_poBaseHandle) > offsetEndCompressedData)
         {
-            stream.avail_in = stream.avail_in + (uInt) (offsetEndCompressedData - VSIFTellL((VSILFILE*)poBaseHandle));
-            VSIFSeekL((VSILFILE*)poBaseHandle, offsetEndCompressedData, SEEK_SET);
+            stream.avail_in = stream.avail_in + (uInt) (offsetEndCompressedData - VSIFTellL((VSILFILE*)m_poBaseHandle));
+            if( VSIFSeekL((VSILFILE*)m_poBaseHandle, offsetEndCompressedData, SEEK_SET) != 0 )
+                return EOF;
         }
         if (stream.avail_in == 0) {
             z_eof = 1;
-            if (VSIFTellL((VSILFILE*)poBaseHandle) != offsetEndCompressedData)
+            if (VSIFTellL((VSILFILE*)m_poBaseHandle) != offsetEndCompressedData)
                 z_err = Z_ERRNO;
             /*if (ferror(file)) z_err = Z_ERRNO;*/
             return EOF;
@@ -513,11 +525,11 @@ int VSIGZipHandle::gzrewind ()
     z_eof = 0;
     stream.avail_in = 0;
     stream.next_in = inbuf;
-    crc = crc32(0L, Z_NULL, 0);
-    if (!transparent) (void)inflateReset(&stream);
+    crc = crc32(0L, NULL, 0);
+    if (!m_transparent) (void)inflateReset(&stream);
     in = 0;
     out = 0;
-    return VSIFSeekL((VSILFILE*)poBaseHandle, startOff, SEEK_SET);
+    return VSIFSeekL((VSILFILE*)m_poBaseHandle, startOff, SEEK_SET);
 }
 
 /************************************************************************/
@@ -539,19 +551,19 @@ int VSIGZipHandle::Seek( vsi_l_offset nOffset, int nWhence )
 
 int VSIGZipHandle::gzseek( vsi_l_offset offset, int whence )
 {
-    vsi_l_offset original_offset = offset;
-    int original_nWhence = whence;
+    const vsi_l_offset original_offset = offset;
+    const int original_nWhence = whence;
 
     z_eof = 0;
     if (ENABLE_DEBUG) CPLDebug("GZIP", "Seek(" CPL_FRMT_GUIB ",%d)", offset, whence);
 
-    if (transparent)
+    if (m_transparent)
     {
         stream.avail_in = 0;
         stream.next_in = inbuf;
         if (whence == SEEK_CUR)
         {
-            if (out + offset > compressed_size)
+            if (out + offset > m_compressed_size)
             {
                 CPL_VSIL_GZ_RETURN(-1);
                 return -1L;
@@ -561,7 +573,7 @@ int VSIGZipHandle::gzseek( vsi_l_offset offset, int whence )
         }
         else if (whence == SEEK_SET)
         {
-            if (offset > compressed_size)
+            if (offset > m_compressed_size)
             {
                 CPL_VSIL_GZ_RETURN(-1);
                 return -1L;
@@ -579,14 +591,14 @@ int VSIGZipHandle::gzseek( vsi_l_offset offset, int whence )
                 return -1L;
             }
 
-            offset = startOff + compressed_size - offset;
+            offset = startOff + m_compressed_size - offset;
         }
         else
         {
             CPL_VSIL_GZ_RETURN(-1);
             return -1L;
         }
-        if (VSIFSeekL((VSILFILE*)poBaseHandle, offset, SEEK_SET) < 0)
+        if (VSIFSeekL((VSILFILE*)m_poBaseHandle, offset, SEEK_SET) < 0)
         {
             CPL_VSIL_GZ_RETURN(-1);
             return -1L;
@@ -594,7 +606,7 @@ int VSIGZipHandle::gzseek( vsi_l_offset offset, int whence )
 
         in = out = offset - startOff;
         if (ENABLE_DEBUG) CPLDebug("GZIP", "return " CPL_FRMT_GUIB, in);
-        return (int) in;
+        return (in > INT_MAX) ? INT_MAX : (int) in;
     }
 
     /* whence == SEEK_END is unsuppored in original gzseek. */
@@ -602,21 +614,21 @@ int VSIGZipHandle::gzseek( vsi_l_offset offset, int whence )
     {
         /* If we known the uncompressed size, we can fake a jump to */
         /* the end of the stream */
-        if (offset == 0 && uncompressed_size != 0)
+        if (offset == 0 && m_uncompressed_size != 0)
         {
-            out = uncompressed_size;
+            out = m_uncompressed_size;
             return 1;
         }
 
         /* We don't know the uncompressed size. This is unfortunate. Let's do the slow version... */
         static int firstWarning = 1;
-        if (compressed_size > 10 * 1024 * 1024 && firstWarning)
+        if (m_compressed_size > 10 * 1024 * 1024 && firstWarning)
         {
             CPLError(CE_Warning, CPLE_AppDefined,
                         "VSIFSeekL(xxx, SEEK_END) may be really slow on GZip streams.");
             firstWarning = 0;
         }
-        
+
         whence = SEEK_CUR;
         offset = 1024 * 1024 * 1024;
         offset *= 1024 * 1024;
@@ -642,14 +654,13 @@ int VSIGZipHandle::gzseek( vsi_l_offset offset, int whence )
             CPL_VSIL_GZ_RETURN(-1);
             return -1L;
     }
-    
-    unsigned int i;
-    for(i=0;i<compressed_size / snapshot_byte_interval + 1;i++)
+
+    for(unsigned int i=0;i<m_compressed_size / snapshot_byte_interval + 1;i++)
     {
         if (snapshots[i].uncompressed_pos == 0)
             break;
         if (snapshots[i].out <= out + offset &&
-            (i == compressed_size / snapshot_byte_interval || snapshots[i+1].out == 0 || snapshots[i+1].out > out+offset))
+            (i == m_compressed_size / snapshot_byte_interval || snapshots[i+1].out == 0 || snapshots[i+1].out > out+offset))
         {
             if (out >= snapshots[i].out)
                 break;
@@ -662,11 +673,12 @@ int VSIGZipHandle::gzseek( vsi_l_offset offset, int whence )
                                                         " offset=" CPL_FRMT_GUIB,
                          i, snapshots[i].uncompressed_pos, snapshots[i].in, snapshots[i].out, out, offset);
             offset = out + offset - snapshots[i].out;
-            VSIFSeekL((VSILFILE*)poBaseHandle, snapshots[i].uncompressed_pos, SEEK_SET);
+            if( VSIFSeekL((VSILFILE*)m_poBaseHandle, snapshots[i].uncompressed_pos, SEEK_SET) != 0 )
+                CPLError(CE_Failure, CPLE_FileIO, "Seek() failed");
             inflateEnd(&stream);
             inflateCopy(&stream, &snapshots[i].stream);
             crc = snapshots[i].crc;
-            transparent = snapshots[i].transparent;
+            m_transparent = snapshots[i].transparent;
             in = snapshots[i].in;
             out = snapshots[i].out;
             break;
@@ -675,9 +687,9 @@ int VSIGZipHandle::gzseek( vsi_l_offset offset, int whence )
 
     /* offset is now the number of bytes to skip. */
 
-    if (offset != 0 && outbuf == Z_NULL) {
+    if (offset != 0 && outbuf == NULL) {
         outbuf = (Byte*)ALLOC(Z_BUFSIZE);
-        if (outbuf == Z_NULL) {
+        if (outbuf == NULL) {
             CPL_VSIL_GZ_RETURN(-1);
             return -1L;
         }
@@ -693,7 +705,7 @@ int VSIGZipHandle::gzseek( vsi_l_offset offset, int whence )
         int size = Z_BUFSIZE;
         if (offset < Z_BUFSIZE) size = (int)offset;
 
-        int read_size = Read(outbuf, 1, (uInt)size);
+        int read_size = static_cast<int>(Read(outbuf, 1, (uInt)size));
         if (read_size == 0) {
             //CPL_VSIL_GZ_RETURN(-1);
             return -1L;
@@ -712,11 +724,11 @@ int VSIGZipHandle::gzseek( vsi_l_offset offset, int whence )
 
     if (original_offset == 0 && original_nWhence == SEEK_END)
     {
-        uncompressed_size = out;
+        m_uncompressed_size = out;
 
-        if (pszBaseFileName)
+        if (m_pszBaseFileName)
         {
-            CPLString osCacheFilename (pszBaseFileName);
+            CPLString osCacheFilename (m_pszBaseFileName);
             osCacheFilename += ".properties";
 
             /* Write a .properties file to avoid seeking next time */
@@ -727,17 +739,17 @@ int VSIGZipHandle::gzseek( vsi_l_offset offset, int whence )
                 char szBuffer[32];
                 szBuffer[31] = 0;
 
-                CPLPrintUIntBig(szBuffer, compressed_size, 31);
+                CPLPrintUIntBig(szBuffer, m_compressed_size, 31);
                 pszFirstNonSpace = szBuffer;
                 while (*pszFirstNonSpace == ' ') pszFirstNonSpace ++;
-                VSIFPrintfL(fpCacheLength, "compressed_size=%s\n", pszFirstNonSpace);
+                CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCacheLength, "compressed_size=%s\n", pszFirstNonSpace));
 
-                CPLPrintUIntBig(szBuffer, uncompressed_size, 31);
+                CPLPrintUIntBig(szBuffer, m_uncompressed_size, 31);
                 pszFirstNonSpace = szBuffer;
                 while (*pszFirstNonSpace == ' ') pszFirstNonSpace ++;
-                VSIFPrintfL(fpCacheLength, "uncompressed_size=%s\n", pszFirstNonSpace);
+                CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCacheLength, "uncompressed_size=%s\n", pszFirstNonSpace));
 
-                VSIFCloseL(fpCacheLength);
+                CPL_IGNORE_RET_VAL(VSIFCloseL(fpCacheLength));
             }
         }
     }
@@ -759,15 +771,10 @@ vsi_l_offset VSIGZipHandle::Tell()
 /*                              Read()                                  */
 /************************************************************************/
 
-size_t VSIGZipHandle::Read( void *buf, size_t nSize, size_t nMemb )
+size_t VSIGZipHandle::Read( void * const buf, size_t const nSize, size_t const nMemb )
 {
     if (ENABLE_DEBUG) CPLDebug("GZIP", "Read(%p, %d, %d)", buf, (int)nSize, (int)nMemb);
 
-    unsigned len = nSize * nMemb;
-
-    Bytef *pStart = (Bytef*)buf; /* startOffing point for crc computation */
-    Byte  *next_out; /* == stream.next_out but not forced far (for MSDOS) */
-
     if  (z_err == Z_DATA_ERROR || z_err == Z_ERRNO)
     {
         z_eof = 1; /* to avoid infinite loop in reader code */
@@ -783,13 +790,16 @@ size_t VSIGZipHandle::Read( void *buf, size_t nSize, size_t nMemb )
         return 0;  /* EOF */
     }
 
+    const unsigned len = static_cast<unsigned int>(nSize) * static_cast<unsigned int>(nMemb);
+    Bytef *pStart = (Bytef*)buf; /* startOffing point for crc computation */
+    Byte  *next_out; /* == stream.next_out but not forced far (for MSDOS) */
     next_out = (Byte*)buf;
     stream.next_out = (Bytef*)buf;
     stream.avail_out = len;
 
     while  (stream.avail_out != 0) {
 
-        if  (transparent) {
+        if  (m_transparent) {
             /* Copy first the lookahead bytes: */
             uInt nRead = 0;
             uInt n = stream.avail_in;
@@ -804,9 +814,9 @@ size_t VSIGZipHandle::Read( void *buf, size_t nSize, size_t nMemb )
                 nRead += n;
             }
             if  (stream.avail_out > 0) {
-                uInt nToRead = (uInt) MIN(compressed_size - (in + nRead), stream.avail_out);
+                uInt nToRead = (uInt) MIN(m_compressed_size - (in + nRead), stream.avail_out);
                 uInt nReadFromFile =
-                    (uInt)VSIFReadL(next_out, 1, nToRead, (VSILFILE*)poBaseHandle);
+                    (uInt)VSIFReadL(next_out, 1, nToRead, (VSILFILE*)m_poBaseHandle);
                 stream.avail_out -= nReadFromFile;
                 nRead += nReadFromFile;
             }
@@ -818,7 +828,7 @@ size_t VSIGZipHandle::Read( void *buf, size_t nSize, size_t nMemb )
         }
         if  (stream.avail_in == 0 && !z_eof)
         {
-            vsi_l_offset uncompressed_pos = VSIFTellL((VSILFILE*)poBaseHandle);
+            vsi_l_offset uncompressed_pos = VSIFTellL((VSILFILE*)m_poBaseHandle);
             GZipSnapshot* snapshot = &snapshots[(uncompressed_pos - startOff) / snapshot_byte_interval];
             if (snapshot->uncompressed_pos == 0)
             {
@@ -833,29 +843,30 @@ size_t VSIGZipHandle::Read( void *buf, size_t nSize, size_t nMemb )
                           uncompressed_pos, in, out, (unsigned int)snapshot->crc);
                 snapshot->uncompressed_pos = uncompressed_pos;
                 inflateCopy(&snapshot->stream, &stream);
-                snapshot->transparent = transparent;
+                snapshot->transparent = m_transparent;
                 snapshot->in = in;
                 snapshot->out = out;
 
-                if (out > nLastReadOffset)
-                    nLastReadOffset = out;
+                if (out > m_nLastReadOffset)
+                    m_nLastReadOffset = out;
             }
 
             errno = 0;
-            stream.avail_in = (uInt)VSIFReadL(inbuf, 1, Z_BUFSIZE, (VSILFILE*)poBaseHandle);
+            stream.avail_in = (uInt)VSIFReadL(inbuf, 1, Z_BUFSIZE, (VSILFILE*)m_poBaseHandle);
             if (ENABLE_DEBUG)
                 CPLDebug("GZIP", CPL_FRMT_GUIB " " CPL_FRMT_GUIB,
-                                 VSIFTellL((VSILFILE*)poBaseHandle), offsetEndCompressedData);
-            if (VSIFTellL((VSILFILE*)poBaseHandle) > offsetEndCompressedData)
+                                 VSIFTellL((VSILFILE*)m_poBaseHandle), offsetEndCompressedData);
+            if (VSIFTellL((VSILFILE*)m_poBaseHandle) > offsetEndCompressedData)
             {
                 if (ENABLE_DEBUG) CPLDebug("GZIP", "avail_in before = %d", stream.avail_in);
-                stream.avail_in = stream.avail_in + (uInt) (offsetEndCompressedData - VSIFTellL((VSILFILE*)poBaseHandle));
-                VSIFSeekL((VSILFILE*)poBaseHandle, offsetEndCompressedData, SEEK_SET);
+                stream.avail_in = stream.avail_in + (uInt) (offsetEndCompressedData - VSIFTellL((VSILFILE*)m_poBaseHandle));
+                if( VSIFSeekL((VSILFILE*)m_poBaseHandle, offsetEndCompressedData, SEEK_SET) != 0 )
+                    CPLError(CE_Failure, CPLE_FileIO, "Seek() failed");
                 if (ENABLE_DEBUG) CPLDebug("GZIP", "avail_in after = %d", stream.avail_in);
             }
             if  (stream.avail_in == 0) {
                 z_eof = 1;
-                if (VSIFTellL((VSILFILE*)poBaseHandle) != offsetEndCompressedData)
+                if (VSIFTellL((VSILFILE*)m_poBaseHandle) != offsetEndCompressedData)
                 {
                     z_err = Z_ERRNO;
                     break;
@@ -873,25 +884,25 @@ size_t VSIGZipHandle::Read( void *buf, size_t nSize, size_t nMemb )
         in -= stream.avail_in;
         out -= stream.avail_out;
 
-        if  (z_err == Z_STREAM_END && compressed_size != 2 ) {
+        if  (z_err == Z_STREAM_END && m_compressed_size != 2 ) {
             /* Check CRC and original size */
             crc = crc32 (crc, pStart, (uInt) (stream.next_out - pStart));
             pStart = stream.next_out;
-            if (expected_crc)
+            if (m_expected_crc)
             {
-                if (ENABLE_DEBUG) CPLDebug("GZIP", "Computed CRC = %X. Expected CRC = %X", (unsigned int)crc, expected_crc);
+                if (ENABLE_DEBUG) CPLDebug("GZIP", "Computed CRC = %X. Expected CRC = %X", static_cast<unsigned int>(crc), static_cast<unsigned int>(m_expected_crc));
             }
-            if (expected_crc != 0 && expected_crc != crc)
+            if (m_expected_crc != 0 && m_expected_crc != crc)
             {
-                CPLError(CE_Failure, CPLE_FileIO, "CRC error. Got %X instead of %X", (unsigned int)crc, expected_crc);
+                CPLError(CE_Failure, CPLE_FileIO, "CRC error. Got %X instead of %X", static_cast<unsigned int>(crc), static_cast<unsigned int>(m_expected_crc));
                 z_err = Z_DATA_ERROR;
             }
-            else if (expected_crc == 0)
+            else if (m_expected_crc == 0)
             {
-                unsigned int read_crc = getLong();
+                uLong read_crc = (unsigned long)getLong();
                 if (read_crc != crc)
                 {
-                    CPLError(CE_Failure, CPLE_FileIO, "CRC error. Got %X instead of %X", (unsigned int)crc, read_crc);
+                    CPLError(CE_Failure, CPLE_FileIO, "CRC error. Got %X instead of %X", static_cast<unsigned int>(crc), static_cast<unsigned int>(read_crc));
                     z_err = Z_DATA_ERROR;
                 }
                 else
@@ -904,7 +915,7 @@ size_t VSIGZipHandle::Read( void *buf, size_t nSize, size_t nMemb )
                     check_header();
                     if  (z_err == Z_OK) {
                         inflateReset(& (stream));
-                        crc = crc32(0L, Z_NULL, 0);
+                        crc = crc32(0L, NULL, 0);
                     }
                 }
             }
@@ -934,13 +945,17 @@ size_t VSIGZipHandle::Read( void *buf, size_t nSize, size_t nMemb )
 uLong VSIGZipHandle::getLong ()
 {
     uLong x = (uLong)get_byte();
-    int c;
 
     x += ((uLong)get_byte())<<8;
     x += ((uLong)get_byte())<<16;
-    c = get_byte();
-    if (c == EOF) z_err = Z_DATA_ERROR;
+    const int c = get_byte();
+    if (c == EOF)
+    {
+        z_err = Z_DATA_ERROR;
+        return 0;
+    }
     x += ((uLong)c)<<24;
+    /* coverity[overflow_sink] */
     return x;
 }
 
@@ -992,15 +1007,15 @@ int VSIGZipHandle::Close()
 /* ==================================================================== */
 /************************************************************************/
 
-class VSIGZipWriteHandle : public VSIVirtualHandle
+class VSIGZipWriteHandle CPL_FINAL : public VSIVirtualHandle
 {
-    VSIVirtualHandle*  poBaseHandle;
+    VSIVirtualHandle*  m_poBaseHandle;
     z_stream           sStream;
     Byte              *pabyInBuf;
     Byte              *pabyOutBuf;
     bool               bCompressActive;
     vsi_l_offset       nCurOffset;
-    GUInt32            nCRC;
+    uLong              nCRC;
     int                bRegularZLib;
     int                bAutoCloseBaseHandle;
 
@@ -1030,16 +1045,16 @@ VSIGZipWriteHandle::VSIGZipWriteHandle( VSIVirtualHandle *poBaseHandle,
 {
     nCurOffset = 0;
 
-    this->poBaseHandle = poBaseHandle;
+    m_poBaseHandle = poBaseHandle;
     bRegularZLib = bRegularZLibIn;
     bAutoCloseBaseHandle = bAutoCloseBaseHandleIn;
 
-    nCRC = crc32(0L, Z_NULL, 0);
-    sStream.zalloc = (alloc_func)0;
-    sStream.zfree = (free_func)0;
-    sStream.opaque = (voidpf)0;
-    sStream.next_in = Z_NULL;
-    sStream.next_out = Z_NULL;
+    nCRC = crc32(0L, NULL, 0);
+    sStream.zalloc = (alloc_func)NULL;
+    sStream.zfree = (free_func)NULL;
+    sStream.opaque = (voidpf)NULL;
+    sStream.next_in = NULL;
+    sStream.next_out = NULL;
     sStream.avail_in = sStream.avail_out = 0;
 
     pabyInBuf = (Byte *) CPLMalloc( Z_BUFSIZE );
@@ -1059,10 +1074,11 @@ VSIGZipWriteHandle::VSIGZipWriteHandle( VSIVirtualHandle *poBaseHandle,
 
             /* Write a very simple .gz header:
             */
-            sprintf( header, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
+            snprintf( header, sizeof(header),
+                      "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
                     Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/,
                     0x03 );
-            poBaseHandle->Write( header, 1, 10 );
+            m_poBaseHandle->Write( header, 1, 10 );
         }
 
         bCompressActive = true;
@@ -1101,6 +1117,7 @@ VSIGZipWriteHandle::~VSIGZipWriteHandle()
 int VSIGZipWriteHandle::Close()
 
 {
+    int nRet = 0;
     if( bCompressActive )
     {
         sStream.next_out = pabyOutBuf;
@@ -1110,7 +1127,7 @@ int VSIGZipWriteHandle::Close()
 
         size_t nOutBytes = Z_BUFSIZE - sStream.avail_out;
 
-        if( poBaseHandle->Write( pabyOutBuf, 1, nOutBytes ) < nOutBytes )
+        if( m_poBaseHandle->Write( pabyOutBuf, 1, nOutBytes ) < nOutBytes )
             return EOF;
 
         deflateEnd( &sStream );
@@ -1119,23 +1136,23 @@ int VSIGZipWriteHandle::Close()
         {
             GUInt32 anTrailer[2];
 
-            anTrailer[0] = CPL_LSBWORD32( nCRC );
+            anTrailer[0] = CPL_LSBWORD32( static_cast<GUInt32>(nCRC) );
             anTrailer[1] = CPL_LSBWORD32( (GUInt32) nCurOffset );
 
-            poBaseHandle->Write( anTrailer, 1, 8 );
+            m_poBaseHandle->Write( anTrailer, 1, 8 );
         }
 
         if( bAutoCloseBaseHandle )
         {
-            poBaseHandle->Close();
+            nRet = m_poBaseHandle->Close();
 
-            delete poBaseHandle;
+            delete m_poBaseHandle;
         }
 
         bCompressActive = false;
     }
 
-    return 0;
+    return nRet;
 }
 
 /************************************************************************/
@@ -1154,14 +1171,12 @@ size_t VSIGZipWriteHandle::Read( CPL_UNUSED void *pBuffer,
 /*                               Write()                                */
 /************************************************************************/
 
-size_t VSIGZipWriteHandle::Write( const void *pBuffer, 
-                                  size_t nSize, size_t nMemb )
+size_t VSIGZipWriteHandle::Write( const void * const pBuffer,
+                                  size_t const nSize, size_t const nMemb )
 
 {
-    int  nBytesToWrite, nNextByte;
-
-    nBytesToWrite = (int) (nSize * nMemb);
-    nNextByte = 0;
+    int nBytesToWrite = (int) (nSize * nMemb);
+    int nNextByte = 0;
 
     nCRC = crc32(nCRC, (const Bytef *)pBuffer, nBytesToWrite);
 
@@ -1178,20 +1193,20 @@ size_t VSIGZipWriteHandle::Write( const void *pBuffer,
 
         int nNewBytesToWrite = MIN((int) (Z_BUFSIZE-sStream.avail_in),
                                    nBytesToWrite - nNextByte);
-        memcpy( pabyInBuf + sStream.avail_in, 
-                ((Byte *) pBuffer) + nNextByte, 
+        memcpy( pabyInBuf + sStream.avail_in,
+                ((Byte *) pBuffer) + nNextByte,
                 nNewBytesToWrite );
-        
+
         sStream.next_in = pabyInBuf;
         sStream.avail_in += nNewBytesToWrite;
 
         deflate( &sStream, Z_NO_FLUSH );
 
-        size_t nOutBytes = Z_BUFSIZE - sStream.avail_out;
+        const size_t nOutBytes = Z_BUFSIZE - sStream.avail_out;
 
         if( nOutBytes > 0 )
         {
-            if( poBaseHandle->Write( pabyOutBuf, 1, nOutBytes ) < nOutBytes )
+            if( m_poBaseHandle->Write( pabyOutBuf, 1, nOutBytes ) < nOutBytes )
                 return 0;
         }
 
@@ -1239,7 +1254,7 @@ int VSIGZipWriteHandle::Seek( vsi_l_offset nOffset, int nWhence )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "Seeking on writable compressed data streams not supported." );
-               
+
         return -1;
     }
 }
@@ -1334,10 +1349,11 @@ void VSIGZipFilesystemHandler::SaveInfo_unlocked(  VSIGZipHandle* poHandle )
 /*                                Open()                                */
 /************************************************************************/
 
-VSIVirtualHandle* VSIGZipFilesystemHandler::Open( const char *pszFilename, 
-                                                  const char *pszAccess)
+VSIVirtualHandle* VSIGZipFilesystemHandler::Open( const char *pszFilename,
+                                                  const char *pszAccess,
+                                                  bool /* bSetError */ )
 {
-    VSIFilesystemHandler *poFSHandler = 
+    VSIFilesystemHandler *poFSHandler =
         VSIFileManager::GetHandler( pszFilename + strlen("/vsigzip/"));
 
 /* -------------------------------------------------------------------- */
@@ -1382,10 +1398,10 @@ VSIVirtualHandle* VSIGZipFilesystemHandler::Open( const char *pszFilename,
 /*                          OpenGZipReadOnly()                          */
 /************************************************************************/
 
-VSIGZipHandle* VSIGZipFilesystemHandler::OpenGZipReadOnly( const char *pszFilename, 
+VSIGZipHandle* VSIGZipFilesystemHandler::OpenGZipReadOnly( const char *pszFilename,
                                                       const char *pszAccess)
 {
-    VSIFilesystemHandler *poFSHandler = 
+    VSIFilesystemHandler *poFSHandler =
         VSIFileManager::GetHandler( pszFilename + strlen("/vsigzip/"));
 
     CPLMutexHolder oHolder(&hMutex);
@@ -1421,7 +1437,13 @@ VSIGZipHandle* VSIGZipFilesystemHandler::OpenGZipReadOnly( const char *pszFilena
         poHandleLastGZipFile = NULL;
     }
 
-    return new VSIGZipHandle(poVirtualHandle, pszFilename + strlen("/vsigzip/"));
+    VSIGZipHandle* poHandle = new VSIGZipHandle(poVirtualHandle, pszFilename + strlen("/vsigzip/"));
+    if( !(poHandle->IsInitOK()) )
+    {
+        delete poHandle;
+        return NULL;
+    }
+    return poHandle;
 }
 
 /************************************************************************/
@@ -1464,21 +1486,21 @@ int VSIGZipFilesystemHandler::Stat( const char *pszFilename,
             GUIntBig nUncompressedSize = 0;
             while ((pszLine = CPLReadLineL(fpCacheLength)) != NULL)
             {
-                if (EQUALN(pszLine, "compressed_size=", strlen("compressed_size=")))
+                if (STARTS_WITH_CI(pszLine, "compressed_size="))
                 {
                     const char* pszBuffer = pszLine + strlen("compressed_size=");
-                    nCompressedSize = 
-                            CPLScanUIntBig(pszBuffer, strlen(pszBuffer));
+                    nCompressedSize =
+                            CPLScanUIntBig(pszBuffer, static_cast<int>(strlen(pszBuffer)));
                 }
-                else if (EQUALN(pszLine, "uncompressed_size=", strlen("uncompressed_size=")))
+                else if (STARTS_WITH_CI(pszLine, "uncompressed_size="))
                 {
                     const char* pszBuffer = pszLine + strlen("uncompressed_size=");
                     nUncompressedSize =
-                             CPLScanUIntBig(pszBuffer, strlen(pszBuffer));
+                             CPLScanUIntBig(pszBuffer, static_cast<int>(strlen(pszBuffer)));
                 }
             }
 
-            VSIFCloseL(fpCacheLength);
+            CPL_IGNORE_RET_VAL(VSIFCloseL(fpCacheLength));
 
             if (nCompressedSize == (GUIntBig) pStatBuf->st_size)
             {
@@ -1503,9 +1525,8 @@ int VSIGZipFilesystemHandler::Stat( const char *pszFilename,
                 VSIGZipFilesystemHandler::OpenGZipReadOnly(pszFilename, "rb");
         if (poHandle)
         {
-            GUIntBig uncompressed_size;
             poHandle->Seek(0, SEEK_END);
-            uncompressed_size = (GUIntBig) poHandle->Tell();
+            const GUIntBig uncompressed_size = (GUIntBig) poHandle->Tell();
             poHandle->Seek(0, SEEK_SET);
 
             /* Patch with the uncompressed size */
@@ -1560,10 +1581,11 @@ int VSIGZipFilesystemHandler::Rmdir( CPL_UNUSED const char *pszDirname )
 }
 
 /************************************************************************/
-/*                             ReadDir()                                */
+/*                             ReadDirEx()                                */
 /************************************************************************/
 
-char** VSIGZipFilesystemHandler::ReadDir( CPL_UNUSED const char *pszDirname )
+char** VSIGZipFilesystemHandler::ReadDirEx( const char * /*pszDirname*/,
+                                            int /* nMaxFiles */ )
 {
     return NULL;
 }
@@ -1574,9 +1596,9 @@ char** VSIGZipFilesystemHandler::ReadDir( CPL_UNUSED const char *pszDirname )
 
 
 /**
- * \brief Install GZip file system handler. 
+ * \brief Install GZip file system handler.
  *
- * A special file handler is installed that allows reading on-the-fly and 
+ * A special file handler is installed that allows reading on-the-fly and
  * writing in GZip (.gz) files.
  *
  * All portions of the file system underneath the base
@@ -1599,15 +1621,15 @@ void VSIInstallGZipFileHandler(void)
 /* ==================================================================== */
 /************************************************************************/
 
-class VSIZipEntryFileOffset : public VSIArchiveEntryFileOffset
+class VSIZipEntryFileOffset CPL_FINAL : public VSIArchiveEntryFileOffset
 {
 public:
-        unz_file_pos file_pos;
+        unz_file_pos m_file_pos;
 
         VSIZipEntryFileOffset(unz_file_pos file_pos)
         {
-            this->file_pos.pos_in_zip_directory = file_pos.pos_in_zip_directory;
-            this->file_pos.num_of_file = file_pos.num_of_file;
+            m_file_pos.pos_in_zip_directory = file_pos.pos_in_zip_directory;
+            m_file_pos.num_of_file = file_pos.num_of_file;
         }
 };
 
@@ -1617,7 +1639,7 @@ public:
 /* ==================================================================== */
 /************************************************************************/
 
-class VSIZipReader : public VSIArchiveReader
+class VSIZipReader CPL_FINAL : public VSIArchiveReader
 {
     private:
         unzFile unzF;
@@ -1650,11 +1672,13 @@ class VSIZipReader : public VSIArchiveReader
 /*                           VSIZipReader()                             */
 /************************************************************************/
 
-VSIZipReader::VSIZipReader(const char* pszZipFileName)
+VSIZipReader::VSIZipReader(const char* pszZipFileName) :
+    nNextFileSize(0),
+    nModifiedTime(0)
 {
     unzF = cpl_unzOpen(pszZipFileName);
-    nNextFileSize = 0;
-    nModifiedTime = 0;
+    file_pos.pos_in_zip_directory = 0;
+    file_pos.num_of_file = 0;
 }
 
 /************************************************************************/
@@ -1726,7 +1750,7 @@ int VSIZipReader::GotoFirstFile()
 int VSIZipReader::GotoFileOffset(VSIArchiveEntryFileOffset* pOffset)
 {
     VSIZipEntryFileOffset* pZipEntryOffset = (VSIZipEntryFileOffset*)pOffset;
-    if( cpl_unzGoToFilePos(unzF, &(pZipEntryOffset->file_pos)) != UNZ_OK )
+    if( cpl_unzGoToFilePos(unzF, &(pZipEntryOffset->m_file_pos)) != UNZ_OK )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "GotoFileOffset failed");
         return FALSE;
@@ -1745,7 +1769,7 @@ int VSIZipReader::GotoFileOffset(VSIArchiveEntryFileOffset* pOffset)
 
 class VSIZipWriteHandle;
 
-class VSIZipFilesystemHandler : public VSIArchiveFilesystemHandler 
+class VSIZipFilesystemHandler CPL_FINAL : public VSIArchiveFilesystemHandler
 {
     std::map<CPLString, VSIZipWriteHandle*> oMapZipWriteHandles;
     VSIVirtualHandle *OpenForWrite_unlocked( const char *pszFilename,
@@ -1753,19 +1777,22 @@ class VSIZipFilesystemHandler : public VSIArchiveFilesystemHandler
 
 public:
     virtual ~VSIZipFilesystemHandler();
-    
+
     virtual const char* GetPrefix() { return "/vsizip"; }
     virtual std::vector<CPLString> GetExtensions();
     virtual VSIArchiveReader* CreateReader(const char* pszZipFileName);
 
-    virtual VSIVirtualHandle *Open( const char *pszFilename, 
-                                    const char *pszAccess);
+    using VSIFilesystemHandler::Open;
+
+    virtual VSIVirtualHandle *Open( const char *pszFilename,
+                                    const char *pszAccess,
+                                    bool bSetError );
 
     virtual VSIVirtualHandle *OpenForWrite( const char *pszFilename,
                                             const char *pszAccess );
 
     virtual int      Mkdir( const char *pszDirname, long nMode );
-    virtual char   **ReadDir( const char *pszDirname );
+    virtual char   **ReadDirEx( const char *pszDirname, int nMaxFiles );
     virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags );
 
     void RemoveFromMap(VSIZipWriteHandle* poHandle);
@@ -1777,12 +1804,12 @@ public:
 /* ==================================================================== */
 /************************************************************************/
 
-class VSIZipWriteHandle : public VSIVirtualHandle
+class VSIZipWriteHandle CPL_FINAL : public VSIVirtualHandle
 {
-   VSIZipFilesystemHandler *poFS;
-   void                    *hZIP;
+   VSIZipFilesystemHandler *m_poFS;
+   void                    *m_hZIP;
    VSIZipWriteHandle       *poChildInWriting;
-   VSIZipWriteHandle       *poParent;
+   VSIZipWriteHandle       *m_poParent;
    int                      bAutoDeleteParent;
    vsi_l_offset             nCurOffset;
 
@@ -1804,7 +1831,7 @@ class VSIZipWriteHandle : public VSIVirtualHandle
 
     void  StartNewFile(VSIZipWriteHandle* poSubFile);
     void  StopCurrentFile();
-    void* GetHandle() { return hZIP; }
+    void* GetHandle() { return m_hZIP; }
     VSIZipWriteHandle* GetChildInWriting() { return poChildInWriting; };
     void SetAutoDeleteParent() { bAutoDeleteParent = TRUE; }
 };
@@ -1882,10 +1909,10 @@ VSIArchiveReader* VSIZipFilesystemHandler::CreateReader(const char* pszZipFileNa
 /*                                 Open()                               */
 /************************************************************************/
 
-VSIVirtualHandle* VSIZipFilesystemHandler::Open( const char *pszFilename, 
-                                                 const char *pszAccess)
+VSIVirtualHandle* VSIZipFilesystemHandler::Open( const char *pszFilename,
+                                                 const char *pszAccess,
+                                                 bool /* bSetError */ )
 {
-    char* zipFilename;
     CPLString osZipInFileName;
 
     if (strchr(pszAccess, 'w') != NULL)
@@ -1900,7 +1927,8 @@ VSIVirtualHandle* VSIZipFilesystemHandler::Open( const char *pszFilename,
         return NULL;
     }
 
-    zipFilename = SplitFilename(pszFilename, osZipInFileName, TRUE);
+    char* zipFilename
+        = SplitFilename(pszFilename, osZipInFileName, TRUE);
     if (zipFilename == NULL)
         return NULL;
 
@@ -1922,7 +1950,7 @@ VSIVirtualHandle* VSIZipFilesystemHandler::Open( const char *pszFilename,
         return NULL;
     }
 
-    VSIFilesystemHandler *poFSHandler = 
+    VSIFilesystemHandler *poFSHandler =
         VSIFileManager::GetHandler( zipFilename);
 
     VSIVirtualHandle* poVirtualHandle =
@@ -1968,6 +1996,12 @@ VSIVirtualHandle* VSIZipFilesystemHandler::Open( const char *pszFilename,
                              file_info.uncompressed_size,
                              file_info.crc,
                              file_info.compression_method == 0);
+    if( !(poGZIPHandle->IsInitOK()) )
+    {
+        delete poGZIPHandle;
+        return NULL;
+    }
+
     /* Wrap the VSIGZipHandle inside a buffered reader that will */
     /* improve dramatically performance when doing small backward */
     /* seeks */
@@ -1991,10 +2025,11 @@ int VSIZipFilesystemHandler::Mkdir( const char *pszDirname, CPL_UNUSED long nMod
 }
 
 /************************************************************************/
-/*                                ReadDir()                             */
+/*                               ReadDirEx()                            */
 /************************************************************************/
 
-char **VSIZipFilesystemHandler::ReadDir( const char *pszDirname )
+char **VSIZipFilesystemHandler::ReadDirEx( const char *pszDirname,
+                                           int nMaxFiles )
 {
     CPLString osInArchiveSubDir;
     char* zipFilename = SplitFilename(pszDirname, osInArchiveSubDir, TRUE);
@@ -2014,7 +2049,7 @@ char **VSIZipFilesystemHandler::ReadDir( const char *pszDirname )
     }
     CPLFree(zipFilename);
 
-    return VSIArchiveFilesystemHandler::ReadDir(pszDirname);
+    return VSIArchiveFilesystemHandler::ReadDirEx(pszDirname, nMaxFiles);
 }
 
 
@@ -2084,10 +2119,9 @@ VSIVirtualHandle* VSIZipFilesystemHandler::OpenForWrite( const char *pszFilename
 VSIVirtualHandle* VSIZipFilesystemHandler::OpenForWrite_unlocked( const char *pszFilename,
                                                          const char *pszAccess)
 {
-    char* zipFilename;
     CPLString osZipInFileName;
-    
-    zipFilename = SplitFilename(pszFilename, osZipInFileName, FALSE);
+
+    char* zipFilename = SplitFilename(pszFilename, osZipInFileName, FALSE);
     if (zipFilename == NULL)
         return NULL;
     CPLString osZipFilename = zipFilename;
@@ -2098,15 +2132,7 @@ VSIVirtualHandle* VSIZipFilesystemHandler::OpenForWrite_unlocked( const char *ps
     std::map<CPLString,VSIArchiveContent*>::iterator iter = oFileList.find(osZipFilename);
     if (iter != oFileList.end())
     {
-        VSIArchiveContent* content = iter->second;
-        int i;
-        for(i=0;i<content->nEntries;i++)
-        {
-            delete content->entries[i].file_pos;
-            CPLFree(content->entries[i].fileName);
-        }
-        CPLFree(content->entries);
-        delete content;
+        delete iter->second;
 
         oFileList.erase(iter);
     }
@@ -2198,9 +2224,9 @@ VSIZipWriteHandle::VSIZipWriteHandle(VSIZipFilesystemHandler* poFS,
                                      void* hZIP,
                                      VSIZipWriteHandle* poParent)
 {
-    this->poFS = poFS;
-    this->hZIP = hZIP;
-    this->poParent = poParent;
+    m_poFS = poFS;
+    m_hZIP = hZIP;
+    m_poParent = poParent;
     poChildInWriting = NULL;
     bAutoDeleteParent = FALSE;
     nCurOffset = 0;
@@ -2259,14 +2285,14 @@ size_t VSIZipWriteHandle::Read( CPL_UNUSED void *pBuffer,
 
 size_t    VSIZipWriteHandle::Write( const void *pBuffer, size_t nSize, size_t nMemb )
 {
-    if (poParent == NULL)
+    if (m_poParent == NULL)
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "VSIFWriteL() is not supported on main Zip file or closed subfiles");
         return 0;
     }
 
-    if (CPLWriteFileInZip( poParent->hZIP, pBuffer, (int)(nSize * nMemb) ) != CE_None)
+    if (CPLWriteFileInZip( m_poParent->m_hZIP, pBuffer, (int)(nSize * nMemb) ) != CE_None)
         return 0;
 
     nCurOffset +=(int) (nSize * nMemb);
@@ -2302,25 +2328,25 @@ int VSIZipWriteHandle::Flush()
 
 int VSIZipWriteHandle::Close()
 {
-    if (poParent)
+    if (m_poParent)
     {
-        CPLCloseFileInZip(poParent->hZIP);
-        poParent->poChildInWriting = NULL;
+        CPLCloseFileInZip(m_poParent->m_hZIP);
+        m_poParent->poChildInWriting = NULL;
         if (bAutoDeleteParent)
-            delete poParent;
-        poParent = NULL;
+            delete m_poParent;
+        m_poParent = NULL;
     }
     if (poChildInWriting)
     {
         poChildInWriting->Close();
         poChildInWriting = NULL;
     }
-    if (hZIP)
+    if (m_hZIP)
     {
-        CPLCloseZip(hZIP);
-        hZIP = NULL;
+        CPLCloseZip(m_hZIP);
+        m_hZIP = NULL;
 
-        poFS->RemoveFromMap(this);
+        m_poFS->RemoveFromMap(this);
     }
 
     return 0;
@@ -2352,7 +2378,7 @@ void  VSIZipWriteHandle::StartNewFile(VSIZipWriteHandle* poSubFile)
 
 
 /**
- * \brief Install ZIP file system handler. 
+ * \brief Install ZIP file system handler.
  *
  * A special file handler is installed that allows reading on-the-fly in ZIP
  * (.zip) archives.
@@ -2363,13 +2389,13 @@ void  VSIZipWriteHandle::StartNewFile(VSIZipWriteHandle* poSubFile)
  * The syntax to open a file inside a zip file is /vsizip/path/to/the/file.zip/path/inside/the/zip/file
  * were path/to/the/file.zip is relative or absolute and path/inside/the/zip/file
  * is the relative path to the file inside the archive.
- * 
+ *
  * If the path is absolute, it should begin with a / on a Unix-like OS (or C:\ on Windows),
  * so the line looks like /vsizip//home/gdal/...
  * For example gdalinfo /vsizip/myarchive.zip/subdir1/file1.tif
  *
- * Syntaxic sugar : if the .zip file contains only one file located at its root,
- * just mentionning "/vsizip/path/to/the/file.zip" will work
+ * Syntactic sugar : if the .zip file contains only one file located at its
+ * root, just mentioning "/vsizip/path/to/the/file.zip" will work
  *
  * VSIStatL() will return the uncompressed size in st_size member and file
  * nature- file or directory - in st_mode member.
@@ -2421,9 +2447,9 @@ void* CPLZLibDeflate( const void* ptr,
                       size_t* pnOutBytes )
 {
     z_stream strm;
-    strm.zalloc = Z_NULL;
-    strm.zfree = Z_NULL;
-    strm.opaque = Z_NULL;
+    strm.zalloc = NULL;
+    strm.zfree = NULL;
+    strm.opaque = NULL;
     int ret = deflateInit(&strm, Z_DEFAULT_COMPRESSION);
     if (ret != Z_OK)
     {
@@ -2432,7 +2458,7 @@ void* CPLZLibDeflate( const void* ptr,
         return NULL;
     }
 
-    size_t nTmpSize;
+    size_t nTmpSize = 0;
     void* pTmp;
     if( outptr == NULL )
     {
@@ -2452,9 +2478,9 @@ void* CPLZLibDeflate( const void* ptr,
         nTmpSize = nOutAvailableBytes;
     }
 
-    strm.avail_in = nBytes;
+    strm.avail_in = static_cast<uInt>(nBytes);
     strm.next_in = (Bytef*) ptr;
-    strm.avail_out = nTmpSize;
+    strm.avail_out = static_cast<uInt>(nTmpSize);
     strm.next_out = (Bytef*) pTmp;
     ret = deflate(&strm, Z_FINISH);
     if( ret != Z_STREAM_END )
@@ -2496,10 +2522,10 @@ void* CPLZLibInflate( const void* ptr, size_t nBytes,
                       size_t* pnOutBytes )
 {
     z_stream strm;
-    strm.zalloc = Z_NULL;
-    strm.zfree = Z_NULL;
-    strm.opaque = Z_NULL;
-    strm.avail_in = nBytes;
+    strm.zalloc = NULL;
+    strm.zfree = NULL;
+    strm.opaque = NULL;
+    strm.avail_in = static_cast<uInt>(nBytes);
     strm.next_in = (Bytef*) ptr;
     int ret = inflateInit(&strm);
     if (ret != Z_OK)
@@ -2509,7 +2535,7 @@ void* CPLZLibInflate( const void* ptr, size_t nBytes,
         return NULL;
     }
 
-    size_t nTmpSize;
+    size_t nTmpSize = 0;
     char* pszTmp;
     if( outptr == NULL )
     {
@@ -2529,10 +2555,10 @@ void* CPLZLibInflate( const void* ptr, size_t nBytes,
         nTmpSize = nOutAvailableBytes;
     }
 
-    strm.avail_out = nTmpSize;
+    strm.avail_out = static_cast<uInt>(nTmpSize);
     strm.next_out = (Bytef*) pszTmp;
 
-    while(TRUE)
+    while(true)
     {
         ret = inflate(&strm, Z_FINISH);
         if( ret == Z_BUF_ERROR )
@@ -2557,7 +2583,7 @@ void* CPLZLibInflate( const void* ptr, size_t nBytes,
                 return NULL;
             }
             pszTmp = pszTmpNew;
-            strm.avail_out = nTmpSize - nAlreadyWritten;
+            strm.avail_out = static_cast<uInt>(nTmpSize - nAlreadyWritten);
             strm.next_out = (Bytef*) (pszTmp + nAlreadyWritten);
         }
         else
diff --git a/port/cpl_vsil_sparsefile.cpp b/port/cpl_vsil_sparsefile.cpp
index 19bfd87..74be14c 100644
--- a/port/cpl_vsil_sparsefile.cpp
+++ b/port/cpl_vsil_sparsefile.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsil_sparsefile.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: cpl_vsil_sparsefile.cpp 33758 2016-03-21 09:06:22Z rouault $
  *
  * Project:  VSI Virtual File System
  * Purpose:  Implementation of sparse file virtual io driver.
@@ -34,15 +34,11 @@
 #include "cpl_minixml.h"
 #include <map>
 
-#if defined(WIN32CE)
-#  include <wce_errno.h>
-#endif
+CPL_CVSID("$Id: cpl_vsil_sparsefile.cpp 33758 2016-03-21 09:06:22Z rouault $");
 
-CPL_CVSID("$Id: cpl_vsil_sparsefile.cpp 27745 2014-09-27 16:38:57Z goatbar $");
-
-class SFRegion { 
+class SFRegion {
 public:
-    SFRegion() : fp(NULL), nDstOffset(0), nSrcOffset(0), nLength(0), 
+    SFRegion() : fp(NULL), nDstOffset(0), nSrcOffset(0), nLength(0),
                  byValue(0), bTriedOpen(FALSE) {}
 
     CPLString     osFilename;
@@ -63,11 +59,11 @@ public:
 class VSISparseFileFilesystemHandler;
 
 class VSISparseFileHandle : public VSIVirtualHandle
-{ 
-    VSISparseFileFilesystemHandler* poFS;
+{
+    VSISparseFileFilesystemHandler* m_poFS;
 
   public:
-    VSISparseFileHandle(VSISparseFileFilesystemHandler* poFS) : poFS(poFS), nOverallLength(0), nCurOffset(0) {}
+    VSISparseFileHandle(VSISparseFileFilesystemHandler* poFS) : m_poFS(poFS), nOverallLength(0), nCurOffset(0) {}
 
     GUIntBig           nOverallLength;
     GUIntBig           nCurOffset;
@@ -88,7 +84,7 @@ class VSISparseFileHandle : public VSIVirtualHandle
 /* ==================================================================== */
 /************************************************************************/
 
-class VSISparseFileFilesystemHandler : public VSIFilesystemHandler 
+class VSISparseFileFilesystemHandler : public VSIFilesystemHandler
 {
     std::map<GIntBig, int> oRecOpenCount;
 
@@ -96,19 +92,22 @@ public:
                      VSISparseFileFilesystemHandler();
     virtual          ~VSISparseFileFilesystemHandler();
 
-    int              DecomposePath( const char *pszPath, 
-                                    CPLString &osFilename, 
+    int              DecomposePath( const char *pszPath,
+                                    CPLString &osFilename,
                                     vsi_l_offset &nSparseFileOffset,
                                     vsi_l_offset &nSparseFileSize );
 
-    virtual VSIVirtualHandle *Open( const char *pszFilename, 
-                                    const char *pszAccess);
+    using VSIFilesystemHandler::Open;
+
+    virtual VSIVirtualHandle *Open( const char *pszFilename,
+                                    const char *pszAccess,
+                                    bool bSetError );
     virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags );
     virtual int      Unlink( const char *pszFilename );
     virtual int      Mkdir( const char *pszDirname, long nMode );
     virtual int      Rmdir( const char *pszDirname );
     virtual char   **ReadDir( const char *pszDirname );
-    
+
     int              GetRecCounter() { return oRecOpenCount[CPLGetPID()]; }
     void             IncRecCounter() { oRecOpenCount[CPLGetPID()] ++; }
     void             DecRecCounter() { oRecOpenCount[CPLGetPID()] --; }
@@ -127,12 +126,10 @@ public:
 int VSISparseFileHandle::Close()
 
 {
-    unsigned int i;
-
-    for( i = 0; i < aoRegions.size(); i++ )
+    for( unsigned int i = 0; i < aoRegions.size(); i++ )
     {
         if( aoRegions[i].fp != NULL )
-            VSIFCloseL( aoRegions[i].fp );
+            CPL_IGNORE_RET_VAL(VSIFCloseL( aoRegions[i].fp ));
     }
 
     return 0;
@@ -211,18 +208,18 @@ size_t VSISparseFileHandle::Read( void * pBuffer, size_t nSize, size_t nCount )
 /* -------------------------------------------------------------------- */
     size_t nReturnCount = nCount;
     GUIntBig nBytesRequested = nSize * nCount;
-    GUIntBig nBytesAvailable = 
+    GUIntBig nBytesAvailable =
         aoRegions[iRegion].nDstOffset + aoRegions[iRegion].nLength;
 
     if( nCurOffset + nBytesRequested > nBytesAvailable )
     {
-        size_t nExtraBytes = 
+        size_t nExtraBytes =
             (size_t) (nCurOffset + nBytesRequested - nBytesAvailable);
         // Recurse to get the rest of the request.
-        
+
         GUIntBig nCurOffsetSave = nCurOffset;
         nCurOffset += nBytesRequested - nExtraBytes;
-        size_t nBytesRead = 
+        size_t nBytesRead =
             this->Read( ((char *) pBuffer) + nBytesRequested - nExtraBytes,
                         1, nExtraBytes );
         nCurOffset = nCurOffsetSave;
@@ -238,7 +235,7 @@ size_t VSISparseFileHandle::Read( void * pBuffer, size_t nSize, size_t nCount )
 /* -------------------------------------------------------------------- */
     if( aoRegions[iRegion].osFilename.size() == 0 )
     {
-        memset( pBuffer, aoRegions[iRegion].byValue, 
+        memset( pBuffer, aoRegions[iRegion].byValue,
                 (size_t) nBytesRequested );
     }
 
@@ -251,11 +248,11 @@ size_t VSISparseFileHandle::Read( void * pBuffer, size_t nSize, size_t nCount )
         {
             if( !aoRegions[iRegion].bTriedOpen )
             {
-                aoRegions[iRegion].fp = 
+                aoRegions[iRegion].fp =
                     VSIFOpenL( aoRegions[iRegion].osFilename, "r" );
                 if( aoRegions[iRegion].fp == NULL )
                 {
-                    CPLDebug( "/vsisparse/", "Failed to open '%s'.", 
+                    CPLDebug( "/vsisparse/", "Failed to open '%s'.",
                               aoRegions[iRegion].osFilename.c_str() );
                 }
                 aoRegions[iRegion].bTriedOpen = TRUE;
@@ -266,17 +263,17 @@ size_t VSISparseFileHandle::Read( void * pBuffer, size_t nSize, size_t nCount )
             }
         }
 
-        if( VSIFSeekL( aoRegions[iRegion].fp, 
-                       nCurOffset 
-                       - aoRegions[iRegion].nDstOffset 
+        if( VSIFSeekL( aoRegions[iRegion].fp,
+                       nCurOffset
+                       - aoRegions[iRegion].nDstOffset
                        + aoRegions[iRegion].nSrcOffset,
                        SEEK_SET ) != 0 )
             return 0;
 
-        poFS->IncRecCounter();
-        size_t nBytesRead = VSIFReadL( pBuffer, 1, (size_t) nBytesRequested, 
+        m_poFS->IncRecCounter();
+        size_t nBytesRead = VSIFReadL( pBuffer, 1, (size_t) nBytesRequested,
                                        aoRegions[iRegion].fp );
-        poFS->DecRecCounter();
+        m_poFS->DecRecCounter();
 
         if( nBytesAvailable < nBytesRequested )
             nReturnCount = nBytesRead / nSize;
@@ -338,11 +335,12 @@ VSISparseFileFilesystemHandler::~VSISparseFileFilesystemHandler()
 /************************************************************************/
 
 VSIVirtualHandle *
-VSISparseFileFilesystemHandler::Open( const char *pszFilename, 
-                                      const char *pszAccess )
+VSISparseFileFilesystemHandler::Open( const char *pszFilename,
+                                      const char *pszAccess,
+                                      bool /* bSetError */)
 
 {
-    CPLAssert( EQUALN(pszFilename,"/vsisparse/", 11) );
+    CPLAssert( STARTS_WITH_CI(pszFilename, "/vsisparse/") );
 
     if( !EQUAL(pszAccess,"r") && !EQUAL(pszAccess,"rb") )
     {
@@ -362,7 +360,7 @@ VSISparseFileFilesystemHandler::Open( const char *pszFilename,
     VSILFILE *fp = VSIFOpenL( osSparseFilePath, "r" );
     if( fp == NULL )
         return NULL;
-    VSIFCloseL( fp );
+    CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
 
 /* -------------------------------------------------------------------- */
 /*      Read the XML file.                                              */
@@ -403,14 +401,14 @@ VSISparseFileFilesystemHandler::Open( const char *pszFilename,
                                                   oRegion.osFilename, NULL );
         }
 
-        oRegion.nDstOffset = 
+        oRegion.nDstOffset =
             CPLScanUIntBig( CPLGetXMLValue(psRegion,"DestinationOffset","0" ),
                             32 );
-                            
-        oRegion.nSrcOffset = 
+
+        oRegion.nSrcOffset =
             CPLScanUIntBig( CPLGetXMLValue(psRegion,"SourceOffset","0" ), 32);
 
-        oRegion.nLength = 
+        oRegion.nLength =
             CPLScanUIntBig( CPLGetXMLValue(psRegion,"RegionLength","0" ), 32);
 
         oRegion.byValue = (GByte) atoi(CPLGetXMLValue(psRegion,"Value","0" ));
@@ -422,13 +420,11 @@ VSISparseFileFilesystemHandler::Open( const char *pszFilename,
 /*      Get sparse file length, use maximum bound of regions if not     */
 /*      explicit in file.                                               */
 /* -------------------------------------------------------------------- */
-    poHandle->nOverallLength = 
+    poHandle->nOverallLength =
         CPLScanUIntBig( CPLGetXMLValue(psXMLRoot,"Length","0" ), 32);
     if( poHandle->nOverallLength == 0 )
     {
-        unsigned int i;
-
-        for( i = 0; i < poHandle->aoRegions.size(); i++ )
+        for( unsigned int i = 0; i < poHandle->aoRegions.size(); i++ )
         {
             poHandle->nOverallLength = MAX(poHandle->nOverallLength,
                                            poHandle->aoRegions[i].nDstOffset
@@ -445,10 +441,10 @@ VSISparseFileFilesystemHandler::Open( const char *pszFilename,
 /*                                Stat()                                */
 /************************************************************************/
 
-int VSISparseFileFilesystemHandler::Stat( const char * pszFilename, 
+int VSISparseFileFilesystemHandler::Stat( const char * pszFilename,
                                           VSIStatBufL * psStatBuf,
                                           int nFlags )
-    
+
 {
     VSIVirtualHandle *poFile = Open( pszFilename, "r" );
 
@@ -461,7 +457,7 @@ int VSISparseFileFilesystemHandler::Stat( const char * pszFilename,
     size_t nLength = (size_t) poFile->Tell();
     delete poFile;
 
-    int nResult = VSIStatExL( pszFilename + strlen("/vsisparse/"), 
+    int nResult = VSIStatExL( pszFilename + strlen("/vsisparse/"),
                             psStatBuf, nFlags );
 
     psStatBuf->st_size = nLength;
@@ -515,7 +511,7 @@ char **VSISparseFileFilesystemHandler::ReadDir( CPL_UNUSED const char *pszPath )
 /************************************************************************/
 
 /**
- * Install /vsisparse/ virtual file handler. 
+ * Install /vsisparse/ virtual file handler.
  *
  * The sparse virtual file handler allows a virtual file to be composed
  * from chunks of data in other files, potentially with large spaces in
@@ -523,13 +519,13 @@ char **VSISparseFileFilesystemHandler::ReadDir( CPL_UNUSED const char *pszPath )
  * test some sorts of operations on what seems to be a large file with
  * image data set to a constant value.  It is also helpful when wanting to
  * add test files to the test suite that are too large, but for which most
- * of the data can be ignored.  It could, in theory, also be used to 
- * treat several files on different file systems as one large virtual file. 
+ * of the data can be ignored.  It could, in theory, also be used to
+ * treat several files on different file systems as one large virtual file.
  *
- * The file referenced by /vsisparse/ should be an XML control file 
+ * The file referenced by /vsisparse/ should be an XML control file
  * formatted something like:
  *
- * 
+ *
 \verbatim
 <VSISparseFile>
   <Length>87629264</Length>
@@ -562,14 +558,13 @@ char **VSISparseFileFilesystemHandler::ReadDir( CPL_UNUSED const char *pszPath )
 </VSISparseFile>
 \endverbatim
  *
- * Hopefully the values and semantics are fairly obvious. 
+ * Hopefully the values and semantics are fairly obvious.
  *
- * This driver is installed by default. 
+ * This driver is installed by default.
  */
 
 void VSIInstallSparseFileHandler()
 {
-    VSIFileManager::InstallHandler( "/vsisparse/", 
+    VSIFileManager::InstallHandler( "/vsisparse/",
                                     new VSISparseFileFilesystemHandler );
 }
-                            
diff --git a/port/cpl_vsil_stdin.cpp b/port/cpl_vsil_stdin.cpp
index 2b0ddd7..9e8d754 100644
--- a/port/cpl_vsil_stdin.cpp
+++ b/port/cpl_vsil_stdin.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_vsil_stdin.cpp 29616 2015-08-06 10:07:50Z rouault $
+ * $Id: cpl_vsil_stdin.cpp 33758 2016-03-21 09:06:22Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for stdin
@@ -14,16 +14,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
@@ -37,7 +37,7 @@
 #include <fcntl.h>
 #endif
 
-CPL_CVSID("$Id: cpl_vsil_stdin.cpp 29616 2015-08-06 10:07:50Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_stdin.cpp 33758 2016-03-21 09:06:22Z rouault $");
 
 /* We buffer the first 1MB of standard input to enable drivers */
 /* to autodetect data. In the first MB, backward and forward seeking */
@@ -69,14 +69,17 @@ static void VSIStdinInit()
 /* ==================================================================== */
 /************************************************************************/
 
-class VSIStdinFilesystemHandler : public VSIFilesystemHandler
+class VSIStdinFilesystemHandler CPL_FINAL : public VSIFilesystemHandler
 {
 public:
                               VSIStdinFilesystemHandler();
     virtual                  ~VSIStdinFilesystemHandler();
 
-    virtual VSIVirtualHandle *Open( const char *pszFilename, 
-                                    const char *pszAccess);
+    using VSIFilesystemHandler::Open;
+
+    virtual VSIVirtualHandle *Open( const char *pszFilename,
+                                    const char *pszAccess,
+                                    bool bSetError );
     virtual int               Stat( const char *pszFilename,
                                     VSIStatBufL *pStatBuf, int nFlags );
 };
@@ -87,7 +90,7 @@ public:
 /* ==================================================================== */
 /************************************************************************/
 
-class VSIStdinHandle : public VSIVirtualHandle
+class VSIStdinHandle CPL_FINAL : public VSIVirtualHandle
 {
   private:
     GUIntBig nCurOff;
@@ -131,7 +134,7 @@ int VSIStdinHandle::ReadAndCache( void* pBuffer, int nToRead )
 {
     CPLAssert(nCurOff == nRealPos);
 
-    int nRead = fread(pBuffer, 1, nToRead, stdin);
+    int nRead = static_cast<int>(fread(pBuffer, 1, nToRead, stdin));
 
     if (nRealPos < BUFFER_SIZE)
     {
@@ -160,7 +163,7 @@ int VSIStdinHandle::Seek( vsi_l_offset nOffset, int nWhence )
     if (nRealPos < BUFFER_SIZE )
     {
         nRealPos += fread(pabyBuffer + nRealPos, 1, BUFFER_SIZE - (int)nRealPos, stdin);
-        nBufferLen = nRealPos;
+        nBufferLen = static_cast<int>(nRealPos);
     }
 
     if (nWhence == SEEK_END)
@@ -207,7 +210,7 @@ int VSIStdinHandle::Seek( vsi_l_offset nOffset, int nWhence )
 
     char abyTemp[8192];
     nCurOff = nRealPos;
-    while(TRUE)
+    while(true)
     {
         int nToRead = (int) MIN(8192, nOffset - nCurOff);
         int nRead = ReadAndCache( abyTemp, nToRead );
@@ -330,8 +333,9 @@ VSIStdinFilesystemHandler::~VSIStdinFilesystemHandler()
 /************************************************************************/
 
 VSIVirtualHandle *
-VSIStdinFilesystemHandler::Open( const char *pszFilename, 
-                                 const char *pszAccess )
+VSIStdinFilesystemHandler::Open( const char *pszFilename,
+                                 const char *pszAccess,
+                                 bool /* bSetError */ )
 
 {
     if (strcmp(pszFilename, "/vsistdin/") != 0)
@@ -366,7 +370,7 @@ int VSIStdinFilesystemHandler::Stat( const char * pszFilename,
     {
         VSIStdinInit();
         if (nBufferLen == 0)
-            nRealPos = nBufferLen = fread(pabyBuffer, 1, BUFFER_SIZE, stdin);
+            nRealPos = nBufferLen = static_cast<int>(fread(pabyBuffer, 1, BUFFER_SIZE, stdin));
 
         pStatBuf->st_size = nBufferLen;
     }
diff --git a/port/cpl_vsil_stdout.cpp b/port/cpl_vsil_stdout.cpp
index 3019fcd..708415e 100644
--- a/port/cpl_vsil_stdout.cpp
+++ b/port/cpl_vsil_stdout.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_vsil_stdout.cpp 30996 2015-10-13 16:57:03Z rouault $
+ * $Id: cpl_vsil_stdout.cpp 33758 2016-03-21 09:06:22Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for stdout
@@ -14,16 +14,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
@@ -37,7 +37,7 @@
 #include <fcntl.h>
 #endif
 
-CPL_CVSID("$Id: cpl_vsil_stdout.cpp 30996 2015-10-13 16:57:03Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_stdout.cpp 33758 2016-03-21 09:06:22Z rouault $");
 
 static VSIWriteFunction pWriteFunction = fwrite;
 static FILE* pWriteStream = stdout;
@@ -48,10 +48,10 @@ static FILE* pWriteStream = stdout;
 
 /** Set an alternative write function and output file handle instead of
  *  fwrite() / stdout.
- * 
+ *
  * @param pFct Function with same signature as fwrite()
  * @param stream File handle on which to output. Passed to pFct.
- * 
+ *
  * @since GDAL 2.0
  */
 void VSIStdoutSetRedirection( VSIWriteFunction pFct, FILE* stream )
@@ -67,11 +67,14 @@ void VSIStdoutSetRedirection( VSIWriteFunction pFct, FILE* stream )
 /* ==================================================================== */
 /************************************************************************/
 
-class VSIStdoutFilesystemHandler : public VSIFilesystemHandler
+class VSIStdoutFilesystemHandler CPL_FINAL : public VSIFilesystemHandler
 {
 public:
-    virtual VSIVirtualHandle *Open( const char *pszFilename, 
-                                    const char *pszAccess);
+    using VSIFilesystemHandler::Open;
+
+    virtual VSIVirtualHandle *Open( const char *pszFilename,
+                                    const char *pszAccess,
+                                    bool bSetError );
     virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags );
 };
 
@@ -81,12 +84,12 @@ public:
 /* ==================================================================== */
 /************************************************************************/
 
-class VSIStdoutHandle : public VSIVirtualHandle
+class VSIStdoutHandle CPL_FINAL : public VSIVirtualHandle
 {
-    vsi_l_offset      nOffset;
+    vsi_l_offset      m_nOffset;
 
   public:
-                      VSIStdoutHandle() : nOffset(0) {}
+                      VSIStdoutHandle() : m_nOffset(0) {}
 
     virtual int       Seek( vsi_l_offset nOffset, int nWhence );
     virtual vsi_l_offset Tell();
@@ -118,7 +121,7 @@ int VSIStdoutHandle::Seek( vsi_l_offset nOffset, int nWhence )
 
 vsi_l_offset VSIStdoutHandle::Tell()
 {
-    return nOffset;
+    return m_nOffset;
 }
 
 /************************************************************************/
@@ -150,12 +153,12 @@ size_t VSIStdoutHandle::Read( CPL_UNUSED void * pBuffer,
 /*                               Write()                                */
 /************************************************************************/
 
-size_t VSIStdoutHandle::Write( const void * pBuffer, size_t nSize, 
-                                  size_t nCount )
+size_t VSIStdoutHandle::Write( const void * pBuffer, size_t nSize,
+                               size_t nCount )
 
 {
     size_t nRet = pWriteFunction(pBuffer, nSize, nCount, pWriteStream);
-    nOffset += nSize * nRet;
+    m_nOffset += nSize * nRet;
     return nRet;
 }
 
@@ -191,7 +194,8 @@ int VSIStdoutHandle::Close()
 
 VSIVirtualHandle *
 VSIStdoutFilesystemHandler::Open( CPL_UNUSED const char *pszFilename,
-                                  const char *pszAccess )
+                                  const char *pszAccess,
+                                  bool /* bSetError */ )
 {
     if ( strchr(pszAccess, 'r') != NULL ||
          strchr(pszAccess, '+') != NULL )
@@ -231,11 +235,14 @@ int VSIStdoutFilesystemHandler::Stat( CPL_UNUSED const char * pszFilename,
 /* ==================================================================== */
 /************************************************************************/
 
-class VSIStdoutRedirectFilesystemHandler : public VSIFilesystemHandler
+class VSIStdoutRedirectFilesystemHandler CPL_FINAL : public VSIFilesystemHandler
 {
 public:
+    using VSIFilesystemHandler::Open;
+
     virtual VSIVirtualHandle *Open( const char *pszFilename,
-                                    const char *pszAccess);
+                                    const char *pszAccess,
+                                    bool bSetError );
     virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags );
 };
 
@@ -245,9 +252,9 @@ public:
 /* ==================================================================== */
 /************************************************************************/
 
-class VSIStdoutRedirectHandle : public VSIVirtualHandle
+class VSIStdoutRedirectHandle CPL_FINAL : public VSIVirtualHandle
 {
-    VSIVirtualHandle* poHandle;
+    VSIVirtualHandle* m_poHandle;
   public:
                       VSIStdoutRedirectHandle(VSIVirtualHandle* poHandle);
                      ~VSIStdoutRedirectHandle();
@@ -267,7 +274,7 @@ class VSIStdoutRedirectHandle : public VSIVirtualHandle
 
 VSIStdoutRedirectHandle::VSIStdoutRedirectHandle(VSIVirtualHandle* poHandle)
 {
-    this->poHandle = poHandle;
+    m_poHandle = poHandle;
 }
 
 /************************************************************************/
@@ -276,7 +283,7 @@ VSIStdoutRedirectHandle::VSIStdoutRedirectHandle(VSIVirtualHandle* poHandle)
 
 VSIStdoutRedirectHandle::~VSIStdoutRedirectHandle()
 {
-    delete poHandle;
+    delete m_poHandle;
 }
 
 /************************************************************************/
@@ -296,7 +303,7 @@ int VSIStdoutRedirectHandle::Seek( CPL_UNUSED vsi_l_offset nOffset,
 
 vsi_l_offset VSIStdoutRedirectHandle::Tell()
 {
-    return poHandle->Tell();
+    return m_poHandle->Tell();
 }
 
 /************************************************************************/
@@ -306,7 +313,7 @@ vsi_l_offset VSIStdoutRedirectHandle::Tell()
 int VSIStdoutRedirectHandle::Flush()
 
 {
-    return poHandle->Flush();
+    return m_poHandle->Flush();
 }
 
 /************************************************************************/
@@ -329,7 +336,7 @@ size_t VSIStdoutRedirectHandle::Write( const void * pBuffer, size_t nSize,
                                   size_t nCount )
 
 {
-    return poHandle->Write(pBuffer, nSize, nCount);
+    return m_poHandle->Write(pBuffer, nSize, nCount);
 }
 
 /************************************************************************/
@@ -339,7 +346,7 @@ size_t VSIStdoutRedirectHandle::Write( const void * pBuffer, size_t nSize,
 int VSIStdoutRedirectHandle::Eof()
 
 {
-    return poHandle->Eof();
+    return m_poHandle->Eof();
 }
 
 /************************************************************************/
@@ -349,7 +356,7 @@ int VSIStdoutRedirectHandle::Eof()
 int VSIStdoutRedirectHandle::Close()
 
 {
-    return poHandle->Close();
+    return m_poHandle->Close();
 }
 
 /************************************************************************/
@@ -364,7 +371,8 @@ int VSIStdoutRedirectHandle::Close()
 
 VSIVirtualHandle *
 VSIStdoutRedirectFilesystemHandler::Open( const char *pszFilename,
-                                          const char *pszAccess )
+                                          const char *pszAccess,
+                                          bool /* bSetError */ )
 
 {
     if ( strchr(pszAccess, 'r') != NULL ||
diff --git a/port/cpl_vsil_subfile.cpp b/port/cpl_vsil_subfile.cpp
index 6aed7a5..10050e8 100644
--- a/port/cpl_vsil_subfile.cpp
+++ b/port/cpl_vsil_subfile.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsil_subfile.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: cpl_vsil_subfile.cpp 33758 2016-03-21 09:06:22Z rouault $
  *
  * Project:  VSI Virtual File System
  * Purpose:  Implementation of subfile virtual IO functions.
@@ -33,11 +33,7 @@
 #include "cpl_multiproc.h"
 #include <map>
 
-#if defined(WIN32CE)
-#  include <wce_errno.h>
-#endif
-
-CPL_CVSID("$Id: cpl_vsil_subfile.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: cpl_vsil_subfile.cpp 33758 2016-03-21 09:06:22Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -46,7 +42,7 @@ CPL_CVSID("$Id: cpl_vsil_subfile.cpp 27745 2014-09-27 16:38:57Z goatbar $");
 /************************************************************************/
 
 class VSISubFileHandle : public VSIVirtualHandle
-{ 
+{
   public:
     VSILFILE     *fp;
     vsi_l_offset  nSubregionOffset;
@@ -69,19 +65,22 @@ class VSISubFileHandle : public VSIVirtualHandle
 /* ==================================================================== */
 /************************************************************************/
 
-class VSISubFileFilesystemHandler : public VSIFilesystemHandler 
+class VSISubFileFilesystemHandler : public VSIFilesystemHandler
 {
 public:
                      VSISubFileFilesystemHandler();
     virtual          ~VSISubFileFilesystemHandler();
 
-    int              DecomposePath( const char *pszPath, 
-                                    CPLString &osFilename, 
+    int              DecomposePath( const char *pszPath,
+                                    CPLString &osFilename,
                                     vsi_l_offset &nSubFileOffset,
                                     vsi_l_offset &nSubFileSize );
 
-    virtual VSIVirtualHandle *Open( const char *pszFilename, 
-                                    const char *pszAccess);
+    using VSIFilesystemHandler::Open;
+
+    virtual VSIVirtualHandle *Open( const char *pszFilename,
+                                    const char *pszAccess,
+                                    bool bSetError );
     virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags );
     virtual int      Unlink( const char *pszFilename );
     virtual int      Mkdir( const char *pszDirname, long nMode );
@@ -102,10 +101,10 @@ public:
 int VSISubFileHandle::Close()
 
 {
-    VSIFCloseL( fp );
+    int nRet = VSIFCloseL( fp );
     fp = NULL;
 
-    return 0;
+    return nRet;
 }
 
 /************************************************************************/
@@ -256,24 +255,22 @@ VSISubFileFilesystemHandler::~VSISubFileFilesystemHandler()
 /*      offset (1000), a size (2000) and a path (data/abc.tif).         */
 /************************************************************************/
 
-int 
-VSISubFileFilesystemHandler::DecomposePath( const char *pszPath, 
-                                            CPLString &osFilename, 
+int
+VSISubFileFilesystemHandler::DecomposePath( const char *pszPath,
+                                            CPLString &osFilename,
                                             vsi_l_offset &nSubFileOffset,
                                             vsi_l_offset &nSubFileSize )
 
 {
-    int i;
+    if( !STARTS_WITH(pszPath, "/vsisubfile/") )
+        return FALSE;
 
     osFilename = "";
     nSubFileOffset = 0;
     nSubFileSize = 0;
 
-    if( strncmp(pszPath,"/vsisubfile/",12) != 0 )
-        return FALSE;
-
-    nSubFileOffset = CPLScanUIntBig(pszPath+12, strlen(pszPath + 12));
-    for( i = 12; pszPath[i] != '\0'; i++ )
+    nSubFileOffset = CPLScanUIntBig(pszPath+12, static_cast<int>(strlen(pszPath + 12)));
+    for( int i = 12; pszPath[i] != '\0'; i++ )
     {
         if( pszPath[i] == '_' && nSubFileSize == 0 )
         {
@@ -283,7 +280,7 @@ VSISubFileFilesystemHandler::DecomposePath( const char *pszPath,
             if (pszPath[i + 1] == '-')
                 nSubFileSize = 0;
             else
-                nSubFileSize = CPLScanUIntBig(pszPath + i + 1, strlen(pszPath + i + 1));
+                nSubFileSize = CPLScanUIntBig(pszPath + i + 1, static_cast<int>(strlen(pszPath + i + 1)));
         }
         else if( pszPath[i] == ',' )
         {
@@ -306,8 +303,9 @@ VSISubFileFilesystemHandler::DecomposePath( const char *pszPath,
 /************************************************************************/
 
 VSIVirtualHandle *
-VSISubFileFilesystemHandler::Open( const char *pszFilename, 
-                                   const char *pszAccess )
+VSISubFileFilesystemHandler::Open( const char *pszFilename,
+                                   const char *pszAccess,
+                                   bool /* bSetError */ )
 
 {
     CPLString osSubFilePath;
@@ -330,7 +328,7 @@ VSISubFileFilesystemHandler::Open( const char *pszFilename,
 /*      Open the underlying file.                                       */
 /* -------------------------------------------------------------------- */
     VSILFILE *fp = VSIFOpenL( osSubFilePath, pszAccess );
-    
+
     if( fp == NULL )
         return NULL;
 
@@ -343,7 +341,11 @@ VSISubFileFilesystemHandler::Open( const char *pszFilename,
     poHandle->nSubregionOffset = nOff;
     poHandle->nSubregionSize = nSize;
 
-    VSIFSeekL( fp, nOff, SEEK_SET );
+    if( VSIFSeekL( fp, nOff, SEEK_SET ) != 0 )
+    {
+        delete poHandle;
+        poHandle = NULL;
+    }
 
     return poHandle;
 }
@@ -352,10 +354,10 @@ VSISubFileFilesystemHandler::Open( const char *pszFilename,
 /*                                Stat()                                */
 /************************************************************************/
 
-int VSISubFileFilesystemHandler::Stat( const char * pszFilename, 
+int VSISubFileFilesystemHandler::Stat( const char * pszFilename,
                                        VSIStatBufL * psStatBuf,
                                        int nFlags )
-    
+
 {
     CPLString osSubFilePath;
     vsi_l_offset nOff, nSize;
@@ -369,7 +371,7 @@ int VSISubFileFilesystemHandler::Stat( const char * pszFilename,
     }
 
     int nResult = VSIStatExL( osSubFilePath, psStatBuf, nFlags );
-    
+
     if( nResult == 0 )
     {
         if( nSize != 0 )
@@ -428,11 +430,11 @@ char **VSISubFileFilesystemHandler::ReadDir( CPL_UNUSED const char *pszPath )
 /************************************************************************/
 
 /**
- * Install /vsisubfile/ virtual file handler. 
+ * Install /vsisubfile/ virtual file handler.
  *
- * This virtual file system handler allows access to subregions of 
- * files, treating them as a file on their own to the virtual file 
- * system functions (VSIFOpenL(), etc). 
+ * This virtual file system handler allows access to subregions of
+ * files, treating them as a file on their own to the virtual file
+ * system functions (VSIFOpenL(), etc).
  *
  * A special form of the filename is used to indicate a subportion
  * of another file:
@@ -441,11 +443,11 @@ char **VSISubFileFilesystemHandler::ReadDir( CPL_UNUSED const char *pszPath )
  *
  * The size parameter is optional.  Without it the remainder of the
  * file from the start offset as treated as part of the subfile.  Otherwise
- * only <size> bytes from <offset> are treated as part of the subfile. 
- * The <filename> portion may be a relative or absolute path using normal 
- * rules.   The <offset> and <size> values are in bytes. 
+ * only <size> bytes from <offset> are treated as part of the subfile.
+ * The <filename> portion may be a relative or absolute path using normal
+ * rules.   The <offset> and <size> values are in bytes.
  *
- * eg. 
+ * eg.
  *   /vsisubfile/1000_3000,/data/abc.ntf
  *   /vsisubfile/5000,../xyz/raw.dat
  *
@@ -453,12 +455,11 @@ char **VSISubFileFilesystemHandler::ReadDir( CPL_UNUSED const char *pszPath )
  * is no meaningful support for filesystem operations for creating new
  * files, traversing directories, and deleting files within the /vsisubfile/
  * area.  Only the VSIStatL(), VSIFOpenL() and operations based on the file
- * handle returned by VSIFOpenL() operate properly. 
+ * handle returned by VSIFOpenL() operate properly.
  */
 
 void VSIInstallSubFileHandler()
 {
-    VSIFileManager::InstallHandler( "/vsisubfile/", 
+    VSIFileManager::InstallHandler( "/vsisubfile/",
                                     new VSISubFileFilesystemHandler );
 }
-                            
diff --git a/port/cpl_vsil_tar.cpp b/port/cpl_vsil_tar.cpp
index b03def9..fc0aa12 100644
--- a/port/cpl_vsil_tar.cpp
+++ b/port/cpl_vsil_tar.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsil_tar.cpp 28588 2015-03-01 20:44:43Z rouault $
+ * $Id: cpl_vsil_tar.cpp 33758 2016-03-21 09:06:22Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for tar files (.tar).
@@ -29,8 +29,14 @@
 
 #include "cpl_vsi_virtual.h"
 
-CPL_CVSID("$Id: cpl_vsil_tar.cpp 28588 2015-03-01 20:44:43Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_tar.cpp 33758 2016-03-21 09:06:22Z rouault $");
 
+#if defined(DEBUG) && !defined(HAVE_FUZZER_FRIENDLY_ARCHIVE)
+/* This is a completely custom archive format that is rather inefficient */
+/* but supports random insertions or deletions, since it doesn't record */
+/* explicit file size or rely on files starting on a particular boundary */
+#define HAVE_FUZZER_FRIENDLY_ARCHIVE 1
+#endif
 
 /************************************************************************/
 /* ==================================================================== */
@@ -38,15 +44,31 @@ CPL_CVSID("$Id: cpl_vsil_tar.cpp 28588 2015-03-01 20:44:43Z rouault $");
 /* ==================================================================== */
 /************************************************************************/
 
-class VSITarEntryFileOffset : public VSIArchiveEntryFileOffset
+class VSITarEntryFileOffset CPL_FINAL : public VSIArchiveEntryFileOffset
 {
 public:
-        GUIntBig nOffset;
+        GUIntBig m_nOffset;
+#ifdef HAVE_FUZZER_FRIENDLY_ARCHIVE
+        GUIntBig m_nFileSize;
+        CPLString m_osFileName;
+#endif
 
         VSITarEntryFileOffset(GUIntBig nOffset)
         {
-            this->nOffset = nOffset;
+            m_nOffset = nOffset;
+#ifdef HAVE_FUZZER_FRIENDLY_ARCHIVE
+            m_nFileSize = 0;
+#endif
         }
+
+#ifdef HAVE_FUZZER_FRIENDLY_ARCHIVE
+        VSITarEntryFileOffset(GUIntBig nOffset, GUIntBig nFileSize, const CPLString& osFileName)
+        {
+            m_nOffset = nOffset;
+            m_nFileSize = nFileSize;
+            m_osFileName = osFileName;
+        }
+#endif
 };
 
 /************************************************************************/
@@ -55,7 +77,7 @@ public:
 /* ==================================================================== */
 /************************************************************************/
 
-class VSITarReader : public VSIArchiveReader
+class VSITarReader CPL_FINAL : public VSIArchiveReader
 {
     private:
         VSILFILE* fp;
@@ -63,6 +85,13 @@ class VSITarReader : public VSIArchiveReader
         GUIntBig nNextFileSize;
         CPLString osNextFileName;
         GIntBig nModifiedTime;
+#ifdef HAVE_FUZZER_FRIENDLY_ARCHIVE
+        bool m_bIsFuzzerFriendly;
+        GByte m_abyBuffer[2048];
+        int m_abyBufferIdx;
+        int m_abyBufferSize;
+        GUIntBig m_nCurOffsetOld;
+#endif
 
     public:
         VSITarReader(const char* pszTarFileName);
@@ -72,7 +101,7 @@ class VSITarReader : public VSIArchiveReader
 
         virtual int GotoFirstFile();
         virtual int GotoNextFile();
-        virtual VSIArchiveEntryFileOffset* GetFileOffset() { return new VSITarEntryFileOffset(nCurOffset); }
+        virtual VSIArchiveEntryFileOffset* GetFileOffset();
         virtual GUIntBig GetFileSize() { return nNextFileSize; }
         virtual CPLString GetFileName() { return osNextFileName; }
         virtual GIntBig GetModifiedTime() { return nModifiedTime; }
@@ -84,25 +113,40 @@ class VSITarReader : public VSIArchiveReader
 /*                               VSIIsTGZ()                             */
 /************************************************************************/
 
-static int VSIIsTGZ(const char* pszFilename)
+static bool VSIIsTGZ(const char* pszFilename)
 {
-    return (!EQUALN(pszFilename, "/vsigzip/", 9) &&
+    return (!STARTS_WITH_CI(pszFilename, "/vsigzip/") &&
             ((strlen(pszFilename) > 4 &&
-            EQUALN(pszFilename + strlen(pszFilename) - 4, ".tgz", 4)) ||
+            STARTS_WITH_CI(pszFilename + strlen(pszFilename) - 4, ".tgz")) ||
             (strlen(pszFilename) > 7 &&
-            EQUALN(pszFilename + strlen(pszFilename) - 7, ".tar.gz", 7))));
+            STARTS_WITH_CI(pszFilename + strlen(pszFilename) - 7, ".tar.gz"))));
 }
 
 /************************************************************************/
 /*                           VSITarReader()                             */
 /************************************************************************/
 
-VSITarReader::VSITarReader(const char* pszTarFileName)
+VSITarReader::VSITarReader(const char* pszTarFileName) :
+    nCurOffset(0),
+    nNextFileSize(0),
+    nModifiedTime(0)
 {
     fp = VSIFOpenL(pszTarFileName, "rb");
-    nNextFileSize = 0;
-    nCurOffset = 0;
-    nModifiedTime = 0;
+#ifdef HAVE_FUZZER_FRIENDLY_ARCHIVE
+    m_bIsFuzzerFriendly = false;
+    m_abyBufferIdx = 0;
+    m_abyBufferSize = 0;
+    m_nCurOffsetOld = 0;
+    if( fp != NULL )
+    {
+        GByte abySignature[24];
+        m_bIsFuzzerFriendly =
+            (VSIFReadL(abySignature, 1, 24, fp) == 24) &&
+            (memcmp(abySignature, "FUZZER_FRIENDLY_ARCHIVE\n", 24) == 0 ||
+             memcmp(abySignature, "***NEWFILE***:", strlen("***NEWFILE***:")) == 0);
+        CPL_IGNORE_RET_VAL(VSIFSeekL(fp, 0, SEEK_SET));
+    }
+#endif
 }
 
 /************************************************************************/
@@ -112,7 +156,22 @@ VSITarReader::VSITarReader(const char* pszTarFileName)
 VSITarReader::~VSITarReader()
 {
     if (fp)
-        VSIFCloseL(fp);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
+}
+
+/************************************************************************/
+/*                          GetFileOffset()                             */
+/************************************************************************/
+
+VSIArchiveEntryFileOffset* VSITarReader::GetFileOffset()
+{
+#ifdef HAVE_FUZZER_FRIENDLY_ARCHIVE
+    if( m_bIsFuzzerFriendly )
+    {
+        return new VSITarEntryFileOffset(nCurOffset, nNextFileSize, osNextFileName);
+    }
+#endif
+    return new VSITarEntryFileOffset(nCurOffset);
 }
 
 /************************************************************************/
@@ -121,6 +180,80 @@ VSITarReader::~VSITarReader()
 
 int VSITarReader::GotoNextFile()
 {
+#ifdef HAVE_FUZZER_FRIENDLY_ARCHIVE
+    if( m_bIsFuzzerFriendly )
+    {
+        while( true )
+        {
+            if( m_abyBufferIdx >= m_abyBufferSize )
+            {
+                if( m_abyBufferSize == 0 )
+                {
+                    m_abyBufferSize = static_cast<int>(VSIFReadL(m_abyBuffer, 1, 2048, fp));
+                    if( m_abyBufferSize == 0 )
+                        return FALSE;
+                }
+                else
+                {
+                    if( m_abyBufferSize < 2048 )
+                    {
+                        if( nCurOffset > 0 && nCurOffset != m_nCurOffsetOld )
+                        {
+                            nNextFileSize = VSIFTellL(fp);
+                            nNextFileSize -= m_abyBufferSize;
+                            nNextFileSize += m_abyBufferIdx;
+                            if( nNextFileSize >= nCurOffset )
+                            {
+                                nNextFileSize -= nCurOffset;
+                                m_nCurOffsetOld = nCurOffset;
+                                return TRUE;
+                            }
+                        }
+                        return FALSE;
+                    }
+                    memcpy(m_abyBuffer, m_abyBuffer + 1024, 1024);
+                    m_abyBufferSize = static_cast<int>(VSIFReadL(m_abyBuffer + 1024, 1, 1024, fp));
+                    if( m_abyBufferSize == 0 )
+                        return FALSE;
+                    m_abyBufferIdx = 0;
+                    m_abyBufferSize += 1024;
+                }
+            }
+            if( ((m_abyBufferSize == 2048 && m_abyBufferIdx < m_abyBufferSize - ((int)strlen("***NEWFILE***:")+64)) ||
+                 (m_abyBufferSize < 2048 && m_abyBufferIdx < m_abyBufferSize - ((int)strlen("***NEWFILE***:")+2))) &&
+                memcmp( m_abyBuffer + m_abyBufferIdx, "***NEWFILE***:", strlen("***NEWFILE***:")) == 0 )
+            {
+                if( nCurOffset > 0 && nCurOffset != m_nCurOffsetOld )
+                {
+                    nNextFileSize = VSIFTellL(fp);
+                    nNextFileSize -= m_abyBufferSize;
+                    nNextFileSize += m_abyBufferIdx;
+                    if( nNextFileSize >= nCurOffset )
+                    {
+                        nNextFileSize -= nCurOffset;
+                        m_nCurOffsetOld = nCurOffset;
+                        return TRUE;
+                    }
+                }
+                m_abyBufferIdx += (int)strlen("***NEWFILE***:");
+                int nFilenameStartIdx = m_abyBufferIdx;
+                for(; m_abyBuffer[m_abyBufferIdx] != '\n' && m_abyBufferIdx < m_abyBufferSize; ++m_abyBufferIdx)
+                {
+                    /* do nothing */
+                }
+                if( m_abyBufferIdx < m_abyBufferSize )
+                {
+                    osNextFileName.assign( (const char*)(m_abyBuffer + nFilenameStartIdx), m_abyBufferIdx - nFilenameStartIdx );
+                    nCurOffset = VSIFTellL(fp);
+                    nCurOffset -= m_abyBufferSize;
+                    nCurOffset += m_abyBufferIdx + 1;
+                }
+            }
+            else
+                m_abyBufferIdx ++;
+        }
+    }
+#endif
     char abyHeader[512];
     if (VSIFReadL(abyHeader, 512, 1, fp) != 1)
         return FALSE;
@@ -139,24 +272,24 @@ int VSITarReader::GotoNextFile()
 
     osNextFileName = abyHeader;
     nNextFileSize = 0;
-    int i;
-    for(i=0;i<11;i++)
+    for(int i=0;i<11;i++)
         nNextFileSize = nNextFileSize * 8 + (abyHeader[124+i] - '0');
 
     nModifiedTime = 0;
-    for(i=0;i<11;i++)
+    for(int i=0;i<11;i++)
         nModifiedTime = nModifiedTime * 8 + (abyHeader[136+i] - '0');
 
     nCurOffset = VSIFTellL(fp);
 
-    GUIntBig nBytesToSkip = ((nNextFileSize + 511) / 512) * 512;
+    const GUIntBig nBytesToSkip = ((nNextFileSize + 511) / 512) * 512;
     if( nBytesToSkip > (~((GUIntBig)0)) - nCurOffset )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Bad .tar structure");
         return FALSE;
     }
 
-    VSIFSeekL(fp, nBytesToSkip, SEEK_CUR);
+    if( VSIFSeekL(fp, nBytesToSkip, SEEK_CUR) < 0 )
+        return FALSE;
 
     return TRUE;
 }
@@ -167,7 +300,16 @@ int VSITarReader::GotoNextFile()
 
 int VSITarReader::GotoFirstFile()
 {
-    VSIFSeekL(fp, 0, SEEK_SET);
+    if( VSIFSeekL(fp, 0, SEEK_SET) < 0 )
+        return FALSE;
+#ifdef HAVE_FUZZER_FRIENDLY_ARCHIVE
+    m_abyBufferIdx = 0;
+    m_abyBufferSize = 0;
+    nCurOffset = 0;
+    m_nCurOffsetOld = 0;
+    osNextFileName = "";
+    nNextFileSize = 0;
+#endif
     return GotoNextFile();
 }
 
@@ -178,7 +320,22 @@ int VSITarReader::GotoFirstFile()
 int VSITarReader::GotoFileOffset(VSIArchiveEntryFileOffset* pOffset)
 {
     VSITarEntryFileOffset* pTarEntryOffset = (VSITarEntryFileOffset*)pOffset;
-    VSIFSeekL(fp, pTarEntryOffset->nOffset - 512, SEEK_SET);
+#ifdef HAVE_FUZZER_FRIENDLY_ARCHIVE
+    if( m_bIsFuzzerFriendly )
+    {
+        if( VSIFSeekL(fp, pTarEntryOffset->m_nOffset + pTarEntryOffset->m_nFileSize, SEEK_SET) < 0 )
+            return FALSE;
+        m_abyBufferIdx = 0;
+        m_abyBufferSize = 0;
+        nCurOffset = pTarEntryOffset->m_nOffset;
+        m_nCurOffsetOld = pTarEntryOffset->m_nOffset;
+        osNextFileName = pTarEntryOffset->m_osFileName;
+        nNextFileSize = pTarEntryOffset->m_nFileSize;
+        return TRUE;
+    }
+#endif
+    if( VSIFSeekL(fp, pTarEntryOffset->m_nOffset - 512, SEEK_SET) < 0 )
+        return FALSE;
     return GotoNextFile();
 }
 
@@ -188,15 +345,18 @@ int VSITarReader::GotoFileOffset(VSIArchiveEntryFileOffset* pOffset)
 /* ==================================================================== */
 /************************************************************************/
 
-class VSITarFilesystemHandler : public VSIArchiveFilesystemHandler 
+class VSITarFilesystemHandler CPL_FINAL : public VSIArchiveFilesystemHandler
 {
 public:
     virtual const char* GetPrefix() { return "/vsitar"; }
     virtual std::vector<CPLString> GetExtensions();
     virtual VSIArchiveReader* CreateReader(const char* pszTarFileName);
 
-    virtual VSIVirtualHandle *Open( const char *pszFilename, 
-                                    const char *pszAccess);
+    using VSIFilesystemHandler::Open;
+
+    virtual VSIVirtualHandle *Open( const char *pszFilename,
+                                    const char *pszAccess,
+                                    bool bSetError );
 };
 
 
@@ -250,11 +410,10 @@ VSIArchiveReader* VSITarFilesystemHandler::CreateReader(const char* pszTarFileNa
 /*                                 Open()                               */
 /************************************************************************/
 
-VSIVirtualHandle* VSITarFilesystemHandler::Open( const char *pszFilename, 
-                                                 const char *pszAccess)
+VSIVirtualHandle* VSITarFilesystemHandler::Open( const char *pszFilename,
+                                                 const char *pszAccess,
+                                                 bool /* bSetError */ )
 {
-    char* tarFilename;
-    CPLString osTarInFileName;
 
     if (strchr(pszAccess, 'w') != NULL ||
         strchr(pszAccess, '+') != NULL)
@@ -264,7 +423,9 @@ VSIVirtualHandle* VSITarFilesystemHandler::Open( const char *pszFilename,
         return NULL;
     }
 
-    tarFilename = SplitFilename(pszFilename, osTarInFileName, TRUE);
+    CPLString osTarInFileName;
+    char* tarFilename
+        = SplitFilename(pszFilename, osTarInFileName, TRUE);
     if (tarFilename == NULL)
         return NULL;
 
@@ -277,12 +438,12 @@ VSIVirtualHandle* VSITarFilesystemHandler::Open( const char *pszFilename,
 
     CPLString osSubFileName("/vsisubfile/");
     VSITarEntryFileOffset* pOffset = (VSITarEntryFileOffset*) poReader->GetFileOffset();
-    osSubFileName += CPLString().Printf(CPL_FRMT_GUIB, pOffset->nOffset);
+    osSubFileName += CPLString().Printf(CPL_FRMT_GUIB, pOffset->m_nOffset);
     osSubFileName += "_";
     osSubFileName += CPLString().Printf(CPL_FRMT_GUIB, poReader->GetFileSize());
     osSubFileName += ",";
     delete pOffset;
-    
+
     if (VSIIsTGZ(tarFilename))
     {
         osSubFileName += "/vsigzip/";
@@ -320,8 +481,8 @@ VSIVirtualHandle* VSITarFilesystemHandler::Open( const char *pszFilename,
  * so the line looks like /vsitar//home/gdal/...
  * For example gdalinfo /vsitar/myarchive.tar/subdir1/file1.tif
  *
- * Syntaxic sugar : if the tar archive contains only one file located at its root,
- * just mentionning "/vsitar/path/to/the/file.tar" will work
+ * Syntactic sugar : if the tar archive contains only one file located at its
+ * root, just mentionning "/vsitar/path/to/the/file.tar" will work
  *
  * VSIStatL() will return the uncompressed size in st_size member and file
  * nature- file or directory - in st_mode member.
diff --git a/port/cpl_vsil_unix_stdio_64.cpp b/port/cpl_vsil_unix_stdio_64.cpp
index 932bc16..8d7f323 100644
--- a/port/cpl_vsil_unix_stdio_64.cpp
+++ b/port/cpl_vsil_unix_stdio_64.cpp
@@ -1,9 +1,9 @@
 /**********************************************************************
- * $Id: cpl_vsil_unix_stdio_64.cpp 29006 2015-04-25 11:03:10Z rouault $
+ * $Id: cpl_vsil_unix_stdio_64.cpp 33758 2016-03-21 09:06:22Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for Unix platforms with fseek64()
- *           and ftell64() such as IRIX. 
+ *           and ftell64() such as IRIX.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  **********************************************************************
@@ -16,16 +16,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************
  *
@@ -38,21 +38,35 @@
 
 //#define VSI_COUNT_BYTES_READ
 
+// Some unusual filesystems do not work if _FORTIFY_SOURCE in GCC or
+// clang is used within this source file, especially if techniques
+// like those in vsipreload are used.  Fortify source interacts poorly with
+// filesystems that use fread for forward seeks.  This leads to SIGSEGV within
+// fread calls.
+//
+// See this for hardening background info: https://wiki.debian.org/Hardening
+#undef _FORTIFY_SOURCE
+
 #include "cpl_port.h"
 
-#if !defined(WIN32) && !defined(WIN32CE)
+#if !defined(WIN32)
 
 #include "cpl_vsi_virtual.h"
+#include "cpl_vsi_error.h"
 #include "cpl_string.h"
 #include "cpl_multiproc.h"
 
 #include <unistd.h>
 #include <sys/stat.h>
+#ifdef HAVE_STATVFS
+#include <sys/statvfs.h>
+#endif
 #include <sys/types.h>
 #include <dirent.h>
 #include <errno.h>
+#include <new>
 
-CPL_CVSID("$Id: cpl_vsil_unix_stdio_64.cpp 29006 2015-04-25 11:03:10Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_unix_stdio_64.cpp 33758 2016-03-21 09:06:22Z rouault $");
 
 #if defined(UNIX_STDIO_64)
 
@@ -104,7 +118,7 @@ CPL_CVSID("$Id: cpl_vsil_unix_stdio_64.cpp 29006 2015-04-25 11:03:10Z rouault $"
 /* ==================================================================== */
 /************************************************************************/
 
-class VSIUnixStdioFilesystemHandler : public VSIFilesystemHandler 
+class VSIUnixStdioFilesystemHandler CPL_FINAL : public VSIFilesystemHandler
 {
 #ifdef VSI_COUNT_BYTES_READ
     vsi_l_offset  nTotalBytesRead;
@@ -117,14 +131,19 @@ public:
     virtual                  ~VSIUnixStdioFilesystemHandler();
 #endif
 
-    virtual VSIVirtualHandle *Open( const char *pszFilename, 
-                                    const char *pszAccess);
-    virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags );
+    using VSIFilesystemHandler::Open;
+
+    virtual VSIVirtualHandle *Open( const char *pszFilename,
+                                    const char *pszAccess,
+                                    bool bSetError );
+    virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf,
+                           int nFlags );
     virtual int      Unlink( const char *pszFilename );
     virtual int      Rename( const char *oldpath, const char *newpath );
     virtual int      Mkdir( const char *pszDirname, long nMode );
     virtual int      Rmdir( const char *pszDirname );
-    virtual char   **ReadDir( const char *pszDirname );
+    virtual char   **ReadDirEx( const char *pszDirname, int nMaxFiles );
+    virtual GIntBig  GetDiskFreeSpace( const char* pszDirname );
 
 #ifdef VSI_COUNT_BYTES_READ
     void             AddToTotal(vsi_l_offset nBytes);
@@ -137,23 +156,23 @@ public:
 /* ==================================================================== */
 /************************************************************************/
 
-class VSIUnixStdioHandle : public VSIVirtualHandle
+class VSIUnixStdioHandle CPL_FINAL : public VSIVirtualHandle
 {
     FILE          *fp;
-    vsi_l_offset  nOffset;
-    int           bReadOnly;
-    int           bLastOpWrite;
-    int           bLastOpRead;
-    int           bAtEOF;
+    vsi_l_offset  m_nOffset;
+    bool          bReadOnly;
+    bool          bLastOpWrite;
+    bool          bLastOpRead;
+    bool          bAtEOF;
 #ifdef VSI_COUNT_BYTES_READ
     vsi_l_offset  nTotalBytesRead;
     VSIUnixStdioFilesystemHandler *poFS;
 #endif
   public:
                       VSIUnixStdioHandle(VSIUnixStdioFilesystemHandler *poFSIn,
-                                         FILE* fpIn, int bReadOnlyIn);
+                                         FILE* fpIn, bool bReadOnlyIn);
 
-    virtual int       Seek( vsi_l_offset nOffset, int nWhence );
+    virtual int       Seek( vsi_l_offset nOffsetIn, int nWhence );
     virtual vsi_l_offset Tell();
     virtual size_t    Read( void *pBuffer, size_t nSize, size_t nMemb );
     virtual size_t    Write( const void *pBuffer, size_t nSize, size_t nMemb );
@@ -161,7 +180,8 @@ class VSIUnixStdioHandle : public VSIVirtualHandle
     virtual int       Flush();
     virtual int       Close();
     virtual int       Truncate( vsi_l_offset nNewSize );
-    virtual void     *GetNativeFileDescriptor() { return (void*) (size_t) fileno(fp); }
+    virtual void     *GetNativeFileDescriptor() {
+        return reinterpret_cast<void *>(static_cast<size_t>(fileno(fp))); }
 };
 
 
@@ -174,13 +194,19 @@ VSIUnixStdioHandle::VSIUnixStdioHandle(
 CPL_UNUSED
 #endif
                                        VSIUnixStdioFilesystemHandler *poFSIn,
-                                       FILE* fpIn, int bReadOnlyIn) :
-    fp(fpIn), nOffset(0), bReadOnly(bReadOnlyIn), bLastOpWrite(FALSE), bLastOpRead(FALSE), bAtEOF(FALSE)
+                                       FILE* fpIn, bool bReadOnlyIn) :
+    fp(fpIn),
+    m_nOffset(0),
+    bReadOnly(bReadOnlyIn),
+    bLastOpWrite(false),
+    bLastOpRead(false),
+    bAtEOF(false)
 #ifdef VSI_COUNT_BYTES_READ
-    , nTotalBytesRead(0), poFS(poFSIn)
+    ,
+    nTotalBytesRead(0),
+    poFS(poFSIn)
 #endif
-{
-}
+{}
 
 /************************************************************************/
 /*                               Close()                                */
@@ -202,58 +228,62 @@ int VSIUnixStdioHandle::Close()
 /*                                Seek()                                */
 /************************************************************************/
 
-int VSIUnixStdioHandle::Seek( vsi_l_offset nOffset, int nWhence )
+int VSIUnixStdioHandle::Seek( vsi_l_offset nOffsetIn, int nWhence )
 {
-    bAtEOF = FALSE;
+    bAtEOF = false;
 
     // seeks that do nothing are still surprisingly expensive with MSVCRT.
     // try and short circuit if possible.
-    if( nWhence == SEEK_SET && nOffset == this->nOffset )
+    if( nWhence == SEEK_SET && nOffsetIn == m_nOffset )
         return 0;
 
     // on a read-only file, we can avoid a lseek() system call to be issued
     // if the next position to seek to is within the buffered page
     if( bReadOnly && nWhence == SEEK_SET )
     {
-        GIntBig nDiff = (GIntBig)nOffset - (GIntBig)this->nOffset;
-        if( nDiff > 0 && nDiff < 4096 )
+        if( nOffsetIn > m_nOffset && nOffsetIn < 4096 + m_nOffset )
         {
+            const int nDiff = static_cast<int>(nOffsetIn - m_nOffset);
             GByte abyTemp[4096];
-            int nRead = (int)fread(abyTemp, 1, (int)nDiff, fp);
-            if( nRead == (int)nDiff )
+            const int nRead = static_cast<int>(fread(abyTemp, 1, nDiff, fp));
+            if( nRead == nDiff )
             {
-                this->nOffset = nOffset;
-                bLastOpWrite = FALSE;
-                bLastOpRead = FALSE;
+                m_nOffset = nOffsetIn;
+                bLastOpWrite = false;
+                bLastOpRead = false;
                 return 0;
             }
         }
     }
 
-    const int nResult = VSI_FSEEK64( fp, nOffset, nWhence );
-    int nError = errno;
+    const int nResult = VSI_FSEEK64( fp, nOffsetIn, nWhence );
+    const int nError = errno;
 
 #ifdef VSI_DEBUG
 
     if( nWhence == SEEK_SET )
     {
-        VSIDebug3( "VSIUnixStdioHandle::Seek(%p," CPL_FRMT_GUIB ",SEEK_SET) = %d",
-                   fp, nOffset, nResult );
+        VSIDebug3( "VSIUnixStdioHandle::Seek(%p," CPL_FRMT_GUIB
+                   ",SEEK_SET) = %d",
+                   fp, nOffsetIn, nResult );
     }
     else if( nWhence == SEEK_END )
     {
-        VSIDebug3( "VSIUnixStdioHandle::Seek(%p," CPL_FRMT_GUIB ",SEEK_END) = %d",
-                   fp, nOffset, nResult );
+        VSIDebug3( "VSIUnixStdioHandle::Seek(%p," CPL_FRMT_GUIB
+                   ",SEEK_END) = %d",
+                   fp, nOffsetIn, nResult );
     }
     else if( nWhence == SEEK_CUR )
     {
-        VSIDebug3( "VSIUnixStdioHandle::Seek(%p," CPL_FRMT_GUIB ",SEEK_CUR) = %d",
-                   fp, nOffset, nResult );
+        VSIDebug3( "VSIUnixStdioHandle::Seek(%p," CPL_FRMT_GUIB
+                   ",SEEK_CUR) = %d",
+                   fp, nOffsetIn, nResult );
     }
     else
     {
-        VSIDebug4( "VSIUnixStdioHandle::Seek(%p," CPL_FRMT_GUIB ",%d-Unknown) = %d",
-                   fp, nOffset, nWhence, nResult );
+        VSIDebug4( "VSIUnixStdioHandle::Seek(%p," CPL_FRMT_GUIB
+                   ",%d-Unknown) = %d",
+                   fp, nOffsetIn, nWhence, nResult );
     }
 
 #endif
@@ -262,20 +292,20 @@ int VSIUnixStdioHandle::Seek( vsi_l_offset nOffset, int nWhence )
     {
         if( nWhence == SEEK_SET )
         {
-            this->nOffset = nOffset;
+            m_nOffset = nOffsetIn;
         }
         else if( nWhence == SEEK_END )
         {
-            this->nOffset = VSI_FTELL64( fp );
+            m_nOffset = VSI_FTELL64( fp );
         }
         else if( nWhence == SEEK_CUR )
         {
-            this->nOffset += nOffset;
+            m_nOffset += nOffsetIn;
         }
     }
 
-    bLastOpWrite = FALSE;
-    bLastOpRead = FALSE;
+    bLastOpWrite = false;
+    bLastOpRead = false;
 
     errno = nError;
     return nResult;
@@ -288,16 +318,17 @@ int VSIUnixStdioHandle::Seek( vsi_l_offset nOffset, int nWhence )
 vsi_l_offset VSIUnixStdioHandle::Tell()
 
 {
-#ifdef notdef
-    vsi_l_offset    nOffset = VSI_FTELL64( fp );
-    int             nError = errno;
+#if 0
+    const vsi_l_offset nOffset = VSI_FTELL64( fp );
+    const int nError = errno;
 
-    VSIDebug2( "VSIUnixStdioHandle::Tell(%p) = %ld", fp, (long)nOffset );
+    VSIDebug2( "VSIUnixStdioHandle::Tell(%p) = %ld",
+               fp, static_cast<long>(nOffset) );
 
     errno = nError;
-    return nOffset;
 #endif
-    return nOffset;
+
+    return m_nOffset;
 }
 
 /************************************************************************/
@@ -327,18 +358,25 @@ size_t VSIUnixStdioHandle::Read( void * pBuffer, size_t nSize, size_t nCount )
 /*      skipped a flushing seek that we may need to do now.             */
 /* -------------------------------------------------------------------- */
     if( bLastOpWrite )
-        VSI_FSEEK64( fp, nOffset, SEEK_SET );
+    {
+        if( VSI_FSEEK64( fp, m_nOffset, SEEK_SET ) != 0 )
+        {
+            VSIDebug1("Write calling seek failed. %d", m_nOffset);
+        }
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Perform the read.                                               */
 /* -------------------------------------------------------------------- */
-    size_t  nResult = fread( pBuffer, nSize, nCount, fp );
-    int     nError = errno;
-
-    VSIDebug4( "VSIUnixStdioHandle::Read(%p,%ld,%ld) = %ld", 
-               fp, (long)nSize, (long)nCount, (long)nResult );
+    const size_t nResult = fread( pBuffer, nSize, nCount, fp );
 
+#ifdef VSI_DEBUG
+    int nError = errno;
+    VSIDebug4( "VSIUnixStdioHandle::Read(%p,%ld,%ld) = %ld",
+               fp, static_cast<long>(nSize), static_cast<long>(nCount),
+               static_cast<long>(nResult) );
     errno = nError;
+#endif
 
 /* -------------------------------------------------------------------- */
 /*      Update current offset.                                          */
@@ -348,19 +386,19 @@ size_t VSIUnixStdioHandle::Read( void * pBuffer, size_t nSize, size_t nCount )
     nTotalBytesRead += nSize * nResult;
 #endif
 
-    nOffset += nSize * nResult;
-    bLastOpWrite = FALSE;
-    bLastOpRead = TRUE;
+    m_nOffset += nSize * nResult;
+    bLastOpWrite = false;
+    bLastOpRead = true;
 
     if (nResult != nCount)
     {
         errno = 0;
         vsi_l_offset nNewOffset = VSI_FTELL64( fp );
-        if( errno == 0 ) /* ftell() can fail if we are end of file with a pipe */
-            nOffset = nNewOffset;
+        if( errno == 0 ) // ftell() can fail if we are end of file with a pipe.
+            m_nOffset = nNewOffset;
         else
             CPLDebug("VSI", "%s", VSIStrerror(errno));
-        bAtEOF = feof(fp);
+        bAtEOF = CPL_TO_BOOL(feof(fp));
     }
 
     return nResult;
@@ -370,7 +408,7 @@ size_t VSIUnixStdioHandle::Read( void * pBuffer, size_t nSize, size_t nCount )
 /*                               Write()                                */
 /************************************************************************/
 
-size_t VSIUnixStdioHandle::Write( const void * pBuffer, size_t nSize, 
+size_t VSIUnixStdioHandle::Write( const void * pBuffer, size_t nSize,
                                   size_t nCount )
 
 {
@@ -382,26 +420,35 @@ size_t VSIUnixStdioHandle::Write( const void * pBuffer, size_t nSize,
 /*      skipped a flushing seek that we may need to do now.             */
 /* -------------------------------------------------------------------- */
     if( bLastOpRead )
-        VSI_FSEEK64( fp, nOffset, SEEK_SET );
+    {
+        if( VSI_FSEEK64( fp, m_nOffset, SEEK_SET ) != 0 )
+        {
+            VSIDebug1("Write calling seek failed. %d", m_nOffset);
+        }
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Perform the write.                                              */
 /* -------------------------------------------------------------------- */
-    size_t  nResult = fwrite( pBuffer, nSize, nCount, fp );
-    int     nError = errno;
+    const size_t nResult = fwrite( pBuffer, nSize, nCount, fp );
 
-    VSIDebug4( "VSIUnixStdioHandle::Write(%p,%ld,%ld) = %ld", 
-               fp, (long)nSize, (long)nCount, (long)nResult );
+#if VSI_DEBUG
+    const int nError = errno;
+
+    VSIDebug4( "VSIUnixStdioHandle::Write(%p,%ld,%ld) = %ld",
+               fp, static_cast<long>(nSize), static_cast<long>(nCount),
+               static_cast<long>(nResult) );
 
     errno = nError;
+#endif
 
 /* -------------------------------------------------------------------- */
 /*      Update current offset.                                          */
 /* -------------------------------------------------------------------- */
-    nOffset += nSize * nResult;
-    bLastOpWrite = TRUE;
-    bLastOpRead = FALSE;
-    
+    m_nOffset += nSize * nResult;
+    bLastOpWrite = true;
+    bLastOpRead = false;
+
     return nResult;
 }
 
@@ -412,10 +459,7 @@ size_t VSIUnixStdioHandle::Write( const void * pBuffer, size_t nSize,
 int VSIUnixStdioHandle::Eof()
 
 {
-    if( bAtEOF )
-        return 1;
-    else
-        return 0;
+    return bAtEOF ? TRUE : FALSE;
 }
 
 /************************************************************************/
@@ -425,8 +469,7 @@ int VSIUnixStdioHandle::Eof()
 int VSIUnixStdioHandle::Truncate( vsi_l_offset nNewSize )
 {
     fflush(fp);
-    int nRet = VSI_FTRUNCATE64(fileno(fp), nNewSize);
-    return nRet;
+    return VSI_FTRUNCATE64( fileno(fp), nNewSize );
 }
 
 
@@ -442,10 +485,10 @@ int VSIUnixStdioHandle::Truncate( vsi_l_offset nNewSize )
 
 VSIUnixStdioFilesystemHandler::VSIUnixStdioFilesystemHandler()
 #ifdef VSI_COUNT_BYTES_READ
-     : nTotalBytesRead(0), hMutex(NULL)
+     : nTotalBytesRead(0),
+       hMutex(NULL)
 #endif
-{
-}
+{}
 
 #ifdef VSI_COUNT_BYTES_READ
 /************************************************************************/
@@ -455,7 +498,8 @@ VSIUnixStdioFilesystemHandler::VSIUnixStdioFilesystemHandler()
 VSIUnixStdioFilesystemHandler::~VSIUnixStdioFilesystemHandler()
 {
     CPLDebug( "VSI",
-              "~VSIUnixStdioFilesystemHandler() : nTotalBytesRead = " CPL_FRMT_GUIB,
+              "~VSIUnixStdioFilesystemHandler() : nTotalBytesRead = "
+              CPL_FRMT_GUIB,
               nTotalBytesRead );
 
     if( hMutex != NULL )
@@ -469,24 +513,33 @@ VSIUnixStdioFilesystemHandler::~VSIUnixStdioFilesystemHandler()
 /************************************************************************/
 
 VSIVirtualHandle *
-VSIUnixStdioFilesystemHandler::Open( const char *pszFilename, 
-                                     const char *pszAccess )
+VSIUnixStdioFilesystemHandler::Open( const char *pszFilename,
+                                     const char *pszAccess,
+                                     bool bSetError )
 
 {
     FILE    *fp = VSI_FOPEN64( pszFilename, pszAccess );
-    int     nError = errno;
-    
+    const int nError = errno;
+
     VSIDebug3( "VSIUnixStdioFilesystemHandler::Open(\"%s\",\"%s\") = %p",
                pszFilename, pszAccess, fp );
 
     if( fp == NULL )
     {
+        if(bSetError) { VSIError(VSIE_FileError, "%s", strerror(nError)); }
         errno = nError;
         return NULL;
     }
 
-    int bReadOnly = strcmp(pszAccess, "rb") == 0 || strcmp(pszAccess, "r") == 0;
-    VSIUnixStdioHandle *poHandle = new VSIUnixStdioHandle(this, fp, bReadOnly );
+    const bool bReadOnly =
+        strcmp(pszAccess, "rb") == 0 || strcmp(pszAccess, "r") == 0;
+    VSIUnixStdioHandle *poHandle =
+        new(std::nothrow) VSIUnixStdioHandle( this, fp, bReadOnly );
+    if( poHandle == NULL )
+    {
+        fclose(fp);
+        return NULL;
+    }
 
     errno = nError;
 
@@ -499,10 +552,8 @@ VSIUnixStdioFilesystemHandler::Open( const char *pszFilename,
     {
         return VSICreateCachedFile( poHandle );
     }
-    else
-    {
-        return poHandle;
-    }
+
+    return poHandle;
 }
 
 /************************************************************************/
@@ -511,7 +562,7 @@ VSIUnixStdioFilesystemHandler::Open( const char *pszFilename,
 
 int VSIUnixStdioFilesystemHandler::Stat( const char * pszFilename,
                                          VSIStatBufL * pStatBuf,
-                                         CPL_UNUSED int nFlags)
+                                         int /* nFlags */ )
 {
     return( VSI_STAT64( pszFilename, pStatBuf ) );
 }
@@ -545,7 +596,7 @@ int VSIUnixStdioFilesystemHandler::Mkdir( const char * pszPathname,
                                           long nMode )
 
 {
-    return mkdir( pszPathname, nMode );
+    return mkdir( pszPathname, static_cast<int>(nMode) );
 }
 
 /************************************************************************/
@@ -559,32 +610,36 @@ int VSIUnixStdioFilesystemHandler::Rmdir( const char * pszPathname )
 }
 
 /************************************************************************/
-/*                              ReadDir()                               */
+/*                              ReadDirEx()                             */
 /************************************************************************/
 
-char **VSIUnixStdioFilesystemHandler::ReadDir( const char *pszPath )
+char **VSIUnixStdioFilesystemHandler::ReadDirEx( const char *pszPath,
+                                                 int nMaxFiles )
 
 {
-    DIR           *hDir;
-    struct dirent *psDirEntry;
-    CPLStringList  oDir;
-
     if (strlen(pszPath) == 0)
         pszPath = ".";
 
-    if ( (hDir = opendir(pszPath)) != NULL )
+    CPLStringList  oDir;
+    DIR *hDir = opendir(pszPath);
+    if ( hDir != NULL )
     {
         // we want to avoid returning NULL for an empty list.
-        oDir.Assign( (char**) CPLCalloc(2,sizeof(char*)) );
+        oDir.Assign( static_cast<char**>( CPLCalloc(2,sizeof(char*)) ) );
 
+        struct dirent *psDirEntry;
         while( (psDirEntry = readdir(hDir)) != NULL )
+        {
             oDir.AddString( psDirEntry->d_name );
+            if( nMaxFiles > 0 && oDir.Count() > nMaxFiles )
+                break;
+        }
 
         closedir( hDir );
     }
     else
     {
-        /* Should we generate an error???  
+        /* Should we generate an error???
          * For now we'll just return NULL (at the end of the function)
          */
     }
@@ -592,6 +647,27 @@ char **VSIUnixStdioFilesystemHandler::ReadDir( const char *pszPath )
     return oDir.StealList();
 }
 
+/************************************************************************/
+/*                        GetDiskFreeSpace()                            */
+/************************************************************************/
+
+GIntBig VSIUnixStdioFilesystemHandler::GetDiskFreeSpace( const char*
+#ifdef HAVE_STATVFS
+                                                         pszDirname
+#endif
+                                                       )
+{
+    GIntBig nRet = -1;
+#ifdef HAVE_STATVFS
+    struct statvfs buf;
+    if( statvfs(pszDirname, &buf) == 0 )
+    {
+        nRet = static_cast<GIntBig>(buf.f_frsize * buf.f_bavail);
+    }
+#endif
+    return nRet;
+}
+
 #ifdef VSI_COUNT_BYTES_READ
 /************************************************************************/
 /*                            AddToTotal()                              */
diff --git a/port/cpl_vsil_win32.cpp b/port/cpl_vsil_win32.cpp
index 1b6b5a4..cdc96f3 100644
--- a/port/cpl_vsil_win32.cpp
+++ b/port/cpl_vsil_win32.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_vsil_win32.cpp 27491 2014-07-05 11:24:48Z rouault $
+ * $Id: cpl_vsil_win32.cpp 33758 2016-03-21 09:06:22Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for Win32.
@@ -15,43 +15,33 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
 #include "cpl_vsi_virtual.h"
 
-CPL_CVSID("$Id: cpl_vsil_win32.cpp 27491 2014-07-05 11:24:48Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_win32.cpp 33758 2016-03-21 09:06:22Z rouault $");
 
 #if defined(WIN32)
 
 #include <windows.h>
 #include "cpl_string.h"
 
-
-#if !defined(WIN32CE)
-#  include <sys/types.h>
-#  include <sys/stat.h>
-#  include <io.h>
-#  include <fcntl.h>
-#  include <direct.h>
-#else
-#  include <wce_io.h>
-#  include <wce_errno.h>
-#  include <wce_stdio.h>
-#  include <wce_stat.h>
-#  include "cpl_win32ce_api.h"
-#endif
-
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <io.h>
+#include <fcntl.h>
+#include <direct.h>
 
 /************************************************************************/
 /* ==================================================================== */
@@ -59,19 +49,24 @@ CPL_CVSID("$Id: cpl_vsil_win32.cpp 27491 2014-07-05 11:24:48Z rouault $");
 /* ==================================================================== */
 /************************************************************************/
 
-class VSIWin32FilesystemHandler : public VSIFilesystemHandler 
+class VSIWin32FilesystemHandler CPL_FINAL : public VSIFilesystemHandler
 {
 public:
-    virtual VSIVirtualHandle *Open( const char *pszFilename, 
-                                    const char *pszAccess);
+
+    using VSIFilesystemHandler::Open;
+
+    virtual VSIVirtualHandle *Open( const char *pszFilename,
+                                    const char *pszAccess,
+                                    bool bSetError );
     virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags );
     virtual int      Unlink( const char *pszFilename );
     virtual int      Rename( const char *oldpath, const char *newpath );
     virtual int      Mkdir( const char *pszDirname, long nMode );
     virtual int      Rmdir( const char *pszDirname );
-    virtual char   **ReadDir( const char *pszDirname );
+    virtual char   **ReadDirEx( const char *pszDirname, int nMaxFiles );
     virtual int      IsCaseSensitive( const char* pszFilename )
                       { (void) pszFilename; return FALSE; }
+    virtual GIntBig  GetDiskFreeSpace( const char* pszDirname );
 };
 
 /************************************************************************/
@@ -80,7 +75,7 @@ public:
 /* ==================================================================== */
 /************************************************************************/
 
-class VSIWin32Handle : public VSIVirtualHandle
+class VSIWin32Handle CPL_FINAL : public VSIVirtualHandle
 {
   public:
     HANDLE       hFile;
@@ -104,14 +99,15 @@ class VSIWin32Handle : public VSIVirtualHandle
 /*                                                                      */
 /* TODO: If the function is going to be public CPL function, then       */
 /* replace the switch with array of (Win32 code, errno code) tuples and */
-/* complement it with missing codes.                                    */ 
+/* complement it with missing codes.                                    */
 /************************************************************************/
 
-static int ErrnoFromGetLastError()
+static int ErrnoFromGetLastError(DWORD dwError = 0)
 {
     int err = 0;
-    DWORD dwError = GetLastError();
-    
+    if( dwError == 0 )
+        dwError = GetLastError();
+
     switch( dwError )
     {
     case NO_ERROR:
@@ -172,7 +168,7 @@ static int ErrnoFromGetLastError()
         err = ENOSPC;
         break;
     case ERROR_HANDLE_EOF:          /* Reached the end of the file. */
-        err = 0; /* There is no errno quivalent, in the errno.h */
+        err = 0; /* There is no errno equivalent in the errno.h */
         break;
     default:
         err = 0;
@@ -231,16 +227,16 @@ int VSIWin32Handle::Seek( vsi_l_offset nOffset, int nWhence )
     {
 #ifdef notdef
         LPVOID      lpMsgBuf = NULL;
-        
-        FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER 
+
+        FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER
                        | FORMAT_MESSAGE_FROM_SYSTEM
                        | FORMAT_MESSAGE_IGNORE_INSERTS,
-                       NULL, GetLastError(), 
-                       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
+                       NULL, GetLastError(),
+                       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                        (LPTSTR) &lpMsgBuf, 0, NULL );
- 
+
         printf( "[ERROR %d]\n %s\n", GetLastError(), (char *) lpMsgBuf );
-        printf( "nOffset=%u, nMoveLow=%u, dwMoveHigh=%u\n", 
+        printf( "nOffset=%u, nMoveLow=%u, dwMoveHigh=%u\n",
                 (GUInt32) nOffset, nMoveLow, dwMoveHigh );
 #endif
         errno = ErrnoFromGetLastError();
@@ -260,7 +256,7 @@ vsi_l_offset VSIWin32Handle::Tell()
     LARGE_INTEGER   li;
 
     li.HighPart = 0;
-    li.LowPart = SetFilePointer( hFile, 0, (PLONG) &(li.HighPart), 
+    li.LowPart = SetFilePointer( hFile, 0, (PLONG) &(li.HighPart),
                                  FILE_CURRENT );
 
     return (static_cast<vsi_l_offset>(li.QuadPart));
@@ -276,6 +272,10 @@ int VSIWin32Handle::Flush()
     /* Nothing needed to offer the same guarantee as POSIX fflush() */
     /* FlushFileBuffers() would be closer to fsync() */
     /* See http://trac.osgeo.org/gdal/ticket/5556 */
+
+    // Add this as a hack to make ogr_mitab_30 and _31 tests pass
+    if( CSLTestBoolean(CPLGetConfigOption("VSI_FLUSH", "FALSE")) )
+        FlushFileBuffers(hFile);
     return 0;
 }
 
@@ -286,8 +286,8 @@ int VSIWin32Handle::Flush()
 size_t VSIWin32Handle::Read( void * pBuffer, size_t nSize, size_t nCount )
 
 {
-    DWORD       dwSizeRead;
-    size_t      nResult;
+    DWORD dwSizeRead = 0;
+    size_t nResult = 0;
 
     if( !ReadFile( hFile, pBuffer, (DWORD)(nSize*nCount), &dwSizeRead, NULL ) )
     {
@@ -312,8 +312,8 @@ size_t VSIWin32Handle::Read( void * pBuffer, size_t nSize, size_t nCount )
 size_t VSIWin32Handle::Write( const void *pBuffer, size_t nSize, size_t nCount)
 
 {
-    DWORD       dwSizeWritten;
-    size_t      nResult;
+    DWORD dwSizeWritten = 0;
+    size_t nResult = 0;
 
     if( !WriteFile(hFile, (void *)pBuffer,
                    (DWORD)(nSize*nCount),&dwSizeWritten,NULL) )
@@ -363,22 +363,161 @@ int VSIWin32Handle::Truncate( vsi_l_offset nNewSize )
 /************************************************************************/
 
 /************************************************************************/
+/*                          CPLGetWineVersion()                         */
+/************************************************************************/
+
+static const char* CPLGetWineVersion()
+{
+    HMODULE hntdll = GetModuleHandle("ntdll.dll");
+    if( hntdll == NULL )
+        return NULL;
+
+    static const char * (CDECL *pwine_get_version)(void);
+    pwine_get_version = ( const char* (*)(void) ) GetProcAddress(hntdll, "wine_get_version");
+    if( pwine_get_version == NULL )
+        return NULL;
+
+    return pwine_get_version();
+}
+
+/************************************************************************/
+/*                           VSIWin32StrlenW()                          */
+/************************************************************************/
+
+static size_t VSIWin32StrlenW(const wchar_t* pwszString)
+{
+    size_t nLen = 0;
+    while( pwszString[nLen] != 0 )
+        nLen ++;
+    return nLen;
+}
+
+/************************************************************************/
+/*                        VSIWin32TryLongFilename()                     */
+/************************************************************************/
+
+static void VSIWin32TryLongFilename(wchar_t*& pwszFilename)
+{
+    size_t nLen = VSIWin32StrlenW(pwszFilename);
+    if( pwszFilename[0] != 0 &&
+        pwszFilename[1] == ':' &&
+        (pwszFilename[2] == '\\' || pwszFilename[2] == '/' ) )
+    {
+        pwszFilename = (wchar_t*) CPLRealloc( pwszFilename,
+                    (4 + nLen + 1) * sizeof(wchar_t));
+        memmove( pwszFilename + 4, pwszFilename, (nLen+1) * sizeof(wchar_t));
+    }
+    else
+    {
+        wchar_t* pwszCurDir = (wchar_t*) CPLMalloc(32768 * sizeof(wchar_t));
+        DWORD nCurDirLen = GetCurrentDirectoryW( 32768, pwszCurDir );
+        CPLAssert(nCurDirLen < 32768);
+        pwszFilename = (wchar_t*) CPLRealloc( pwszFilename,
+                    (4 + nCurDirLen + 1 + nLen + 1) * sizeof(wchar_t));
+        int nOffset = 0;
+        if( pwszFilename[0] == '.' &&
+            (pwszFilename[1] == '/' || pwszFilename[1] == '\\') )
+            nOffset = 2;
+        /* \\$\c:\a\b ..\c --> \\$\c:\a\c */
+        while( pwszFilename[nOffset + 0] == '.' && pwszFilename[nOffset + 1] == '.' &&
+              (pwszFilename[nOffset + 2] == '/' || pwszFilename[nOffset + 2] == '\\') )
+        {
+            DWORD nCurDirLenBefore = nCurDirLen;
+            while( nCurDirLen > 0 && pwszCurDir[nCurDirLen-1] != '\\' )
+                nCurDirLen --;
+            if( nCurDirLen <= 2 )
+            {
+                nCurDirLen = nCurDirLenBefore;
+                break;
+            }
+            nCurDirLen --;
+            nOffset += 3;
+        }
+        memmove( pwszFilename + 4 + nCurDirLen + 1,
+                 pwszFilename + nOffset, (nLen-nOffset+1) * sizeof(wchar_t) );
+        memmove( pwszFilename + 4, pwszCurDir, nCurDirLen * sizeof(wchar_t) );
+        pwszFilename[ 4 + nCurDirLen ] = '\\';
+        CPLFree(pwszCurDir);
+    }
+    pwszFilename[0] = '\\';
+    pwszFilename[1] = '\\';
+    pwszFilename[2] = '?';
+    pwszFilename[3] = '\\';
+
+    for(size_t i = 4; pwszFilename[i] != 0; i++)
+    {
+        if( pwszFilename[i] == '/' )
+            pwszFilename[i] = '\\';
+    }
+#if notdef
+    CPLString osFilename;
+    for(size_t i = 0; pwszFilename[i] != 0; i++)
+        osFilename += (char)pwszFilename[i];
+    CPLDebug("VSI", "Trying %s", osFilename.c_str());
+#endif
+}
+
+/************************************************************************/
+/*                         VSIWin32IsLongFilename()                     */
+/************************************************************************/
+
+static bool VSIWin32IsLongFilename( const wchar_t* pwszFilename )
+{
+    return (pwszFilename[0] == '\\' && pwszFilename[1] == '\\' &&
+            pwszFilename[2] == '?' && pwszFilename[3] == '\\');
+}
+
+/************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
 
-VSIVirtualHandle *VSIWin32FilesystemHandler::Open( const char *pszFilename, 
-                                                   const char *pszAccess )
+VSIVirtualHandle *VSIWin32FilesystemHandler::Open( const char *pszFilename,
+                                                   const char *pszAccess,
+                                                   bool /* bSetError */ )
 
 {
     DWORD dwDesiredAccess, dwCreationDisposition, dwFlagsAndAttributes;
     HANDLE hFile;
 
-    if( strchr(pszAccess, '+') != NULL ||
-        strchr(pszAccess, 'w') != 0 ||
-        strchr(pszAccess, 'a') != 0 )
-        dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
-    else
-        dwDesiredAccess = GENERIC_READ;
+    // GENERICs are used instead of FILE_GENERIC_READ
+    dwDesiredAccess = GENERIC_READ;
+    if (strchr(pszAccess, '+') != NULL || strchr(pszAccess, 'w') != NULL)
+        dwDesiredAccess |= GENERIC_WRITE;
+
+    // Append mode only makes sense on files and pipes, have to use FILE_ access
+    // these are very different from the GENERICs
+    // Append is read and write but not overwrite data (only append data)
+    if (strchr(pszAccess, 'a') != NULL )
+    {
+        dwDesiredAccess =
+            FILE_GENERIC_READ | (FILE_GENERIC_WRITE ^ FILE_WRITE_DATA);
+
+        // Wine < 1.7.4 doesn't work properly without FILE_WRITE_DATA bit
+        // (it refuses to write at all), so we'd better re-add it even if the
+        // resulting semantics isn't completely conformant.
+        // See https://bugs.winehq.org/show_bug.cgi?id=33232
+        const char* pszWineVersion = CPLGetWineVersion();
+        if( pszWineVersion != NULL )
+        {
+            int nVersion = atoi(pszWineVersion) * 10000;
+            const char* pszDot = strchr(pszWineVersion, '.');
+            if( pszDot )
+            {
+                nVersion += atoi(pszDot + 1) * 100;
+                pszDot = strchr(pszDot + 1, '.');
+                if( pszDot )
+                {
+                    nVersion += atoi(pszDot + 1);
+                }
+            }
+            if( nVersion < 1 * 10000 + 7 * 100 + 4 )
+            {
+                //CPLDebug("VSI", "Wine %s detected. Append mode needs FILE_WRITE_DATA",
+                //         pszWineVersion);
+                dwDesiredAccess |= FILE_WRITE_DATA;
+            }
+        }
+    }
 
     if( strstr(pszAccess, "w") != NULL )
         dwCreationDisposition = CREATE_ALWAYS;
@@ -387,46 +526,65 @@ VSIVirtualHandle *VSIWin32FilesystemHandler::Open( const char *pszFilename,
     else
         dwCreationDisposition = OPEN_EXISTING;
 
-    dwFlagsAndAttributes = (dwDesiredAccess == GENERIC_READ) ? 
+    dwFlagsAndAttributes = (dwDesiredAccess == GENERIC_READ) ?
         FILE_ATTRIBUTE_READONLY : FILE_ATTRIBUTE_NORMAL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      On Win32 consider treating the filename as utf-8 and            */
 /*      converting to wide characters to open.                          */
 /* -------------------------------------------------------------------- */
-#ifndef WIN32CE
+    DWORD nLastError = 0;
     if( CSLTestBoolean(
             CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
     {
-        wchar_t *pwszFilename = 
+        wchar_t *pwszFilename =
             CPLRecodeToWChar( pszFilename, CPL_ENC_UTF8, CPL_ENC_UCS2 );
 
-        hFile = CreateFileW( pwszFilename, dwDesiredAccess, 
-                            FILE_SHARE_READ | FILE_SHARE_WRITE, 
+        hFile = CreateFileW( pwszFilename, dwDesiredAccess,
+                            FILE_SHARE_READ | FILE_SHARE_WRITE,
+                            NULL, dwCreationDisposition,  dwFlagsAndAttributes,
+                            NULL );
+        if ( hFile == INVALID_HANDLE_VALUE &&
+            !VSIWin32IsLongFilename(pwszFilename) )
+        {
+            nLastError = GetLastError();
+#ifdef notdef
+            switch( nLastError )
+            {
+                    case ERROR_FILE_NOT_FOUND:      CPLDebug("VSI", "ERROR_FILE_NOT_FOUND"); break;
+                    case ERROR_PATH_NOT_FOUND:      CPLDebug("VSI", "ERROR_PATH_NOT_FOUND"); break;
+                    case ERROR_INVALID_DRIVE:       CPLDebug("VSI", "ERROR_INVALID_DRIVE"); break;
+                    case ERROR_NO_MORE_FILES:       CPLDebug("VSI", "ERROR_NO_MORE_FILES"); break;
+                    case ERROR_BAD_PATHNAME:        CPLDebug("VSI", "ERROR_BAD_PATHNAME"); break;
+                    case ERROR_BAD_NETPATH:         CPLDebug("VSI", "ERROR_BAD_NETPATH"); break;
+                    case ERROR_FILENAME_EXCED_RANGE: CPLDebug("VSI", "ERROR_FILENAME_EXCED_RANGE"); break;
+                    default:  CPLDebug("VSI", "other error %d", nLastError); break;
+            }
+#endif
+        }
+        if( nLastError == ERROR_PATH_NOT_FOUND ||
+            nLastError == ERROR_FILENAME_EXCED_RANGE )
+        {
+            VSIWin32TryLongFilename(pwszFilename);
+            nLastError = 0;
+            hFile = CreateFileW( pwszFilename, dwDesiredAccess,
+                            FILE_SHARE_READ | FILE_SHARE_WRITE,
                             NULL, dwCreationDisposition,  dwFlagsAndAttributes,
                             NULL );
+        }
         CPLFree( pwszFilename );
     }
     else
     {
-        hFile = CreateFile( pszFilename, dwDesiredAccess, 
-                            FILE_SHARE_READ | FILE_SHARE_WRITE, 
+        hFile = CreateFile( pszFilename, dwDesiredAccess,
+                            FILE_SHARE_READ | FILE_SHARE_WRITE,
                             NULL, dwCreationDisposition,  dwFlagsAndAttributes,
                             NULL );
     }
 
-/* -------------------------------------------------------------------- */
-/*      On WinCE we only support plain ascii filenames.                 */
-/* -------------------------------------------------------------------- */
-#else /* def WIN32CE */
-    hFile = CE_CreateFileA( pszFilename, dwDesiredAccess, 
-                        FILE_SHARE_READ | FILE_SHARE_WRITE, 
-                        NULL, dwCreationDisposition,  dwFlagsAndAttributes, NULL );
-#endif
-
     if( hFile == INVALID_HANDLE_VALUE )
     {
-        errno = ErrnoFromGetLastError();
+        errno = ErrnoFromGetLastError(nLastError);
         return NULL;
     }
 
@@ -434,13 +592,13 @@ VSIVirtualHandle *VSIWin32FilesystemHandler::Open( const char *pszFilename,
 /*      Create a VSI file handle.                                       */
 /* -------------------------------------------------------------------- */
     VSIWin32Handle *poHandle = new VSIWin32Handle;
-    
+
     poHandle->hFile = hFile;
     poHandle->bEOF = FALSE;
-    
+
     if (strchr(pszAccess, 'a') != 0)
         poHandle->Seek(0, SEEK_END);
-    
+
 /* -------------------------------------------------------------------- */
 /*      If VSI_CACHE is set we want to use a cached reader instead      */
 /*      of more direct io on the underlying file.                       */
@@ -460,7 +618,7 @@ VSIVirtualHandle *VSIWin32FilesystemHandler::Open( const char *pszFilename,
 /*                                Stat()                                */
 /************************************************************************/
 
-int VSIWin32FilesystemHandler::Stat( const char * pszFilename, 
+int VSIWin32FilesystemHandler::Stat( const char * pszFilename,
                                      VSIStatBufL * pStatBuf,
                                      int nFlags )
 
@@ -471,11 +629,52 @@ int VSIWin32FilesystemHandler::Stat( const char * pszFilename,
     if( CSLTestBoolean(
             CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
     {
-        int nResult;
-        wchar_t *pwszFilename = 
+        wchar_t *pwszFilename =
             CPLRecodeToWChar( pszFilename, CPL_ENC_UTF8, CPL_ENC_UCS2 );
 
-        nResult = _wstat64( pwszFilename, pStatBuf );
+        bool bTryOtherStatImpl = false;
+        int nResult = 0;
+        if( VSIWin32IsLongFilename(pwszFilename) )
+        {
+            bTryOtherStatImpl = true;
+            nResult = -1;
+        }
+        else
+        {
+            nResult = _wstat64( pwszFilename, pStatBuf );
+            if( nResult < 0 )
+            {
+                DWORD nLastError = GetLastError();
+                if( nLastError == ERROR_PATH_NOT_FOUND ||
+                    nLastError == ERROR_FILENAME_EXCED_RANGE )
+                {
+                    VSIWin32TryLongFilename(pwszFilename);
+                    bTryOtherStatImpl = true;
+                }
+            }
+        }
+
+        if( bTryOtherStatImpl )
+        {
+            // _wstat64 doesn't like \\?\ paths, so do our poor-man
+            // stat like.
+            //nResult = _wstat64( pwszFilename, pStatBuf );
+
+            VSIVirtualHandle* poHandle = Open( pszFilename, "rb");
+            if( poHandle != NULL )
+            {
+                nResult = 0;
+                memset( pStatBuf, 0, sizeof(VSIStatBufL) );
+                CPL_IGNORE_RET_VAL(poHandle->Seek(0, SEEK_END));
+                pStatBuf->st_mode = S_IFREG;
+                pStatBuf->st_size = poHandle->Tell();
+                poHandle->Close();
+                delete poHandle;
+            }
+            else
+                nResult = -1;
+        }
+
         CPLFree( pwszFilename );
 
         return nResult;
@@ -499,11 +698,10 @@ int VSIWin32FilesystemHandler::Unlink( const char * pszFilename )
     if( CSLTestBoolean(
             CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
     {
-        int nResult;
-        wchar_t *pwszFilename = 
+        wchar_t *pwszFilename =
             CPLRecodeToWChar( pszFilename, CPL_ENC_UTF8, CPL_ENC_UCS2 );
 
-        nResult = _wunlink( pwszFilename );
+        const int nResult = _wunlink( pwszFilename );
         CPLFree( pwszFilename );
         return nResult;
     }
@@ -526,13 +724,12 @@ int VSIWin32FilesystemHandler::Rename( const char *oldpath,
     if( CSLTestBoolean(
             CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
     {
-        int nResult;
-        wchar_t *pwszOldPath = 
+        wchar_t *pwszOldPath =
             CPLRecodeToWChar( oldpath, CPL_ENC_UTF8, CPL_ENC_UCS2 );
-        wchar_t *pwszNewPath = 
+        wchar_t *pwszNewPath =
             CPLRecodeToWChar( newpath, CPL_ENC_UTF8, CPL_ENC_UCS2 );
 
-        nResult = _wrename( pwszOldPath, pwszNewPath );
+        const int nResult = _wrename( pwszOldPath, pwszNewPath );
         CPLFree( pwszOldPath );
         CPLFree( pwszNewPath );
         return nResult;
@@ -557,11 +754,10 @@ int VSIWin32FilesystemHandler::Mkdir( const char * pszPathname,
     if( CSLTestBoolean(
             CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
     {
-        int nResult;
-        wchar_t *pwszFilename = 
+        wchar_t *pwszFilename =
             CPLRecodeToWChar( pszPathname, CPL_ENC_UTF8, CPL_ENC_UCS2 );
 
-        nResult = _wmkdir( pwszFilename );
+        const int nResult = _wmkdir( pwszFilename );
         CPLFree( pwszFilename );
         return nResult;
     }
@@ -583,11 +779,10 @@ int VSIWin32FilesystemHandler::Rmdir( const char * pszPathname )
     if( CSLTestBoolean(
             CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
     {
-        int nResult;
-        wchar_t *pwszFilename = 
+        wchar_t *pwszFilename =
             CPLRecodeToWChar( pszPathname, CPL_ENC_UTF8, CPL_ENC_UCS2 );
 
-        nResult = _wrmdir( pwszFilename );
+        const int nResult = _wrmdir( pwszFilename );
         CPLFree( pwszFilename );
         return nResult;
     }
@@ -602,7 +797,8 @@ int VSIWin32FilesystemHandler::Rmdir( const char * pszPathname )
 /*                              ReadDir()                               */
 /************************************************************************/
 
-char **VSIWin32FilesystemHandler::ReadDir( const char *pszPath )
+char **VSIWin32FilesystemHandler::ReadDirEx( const char *pszPath,
+                                             int nMaxFiles )
 
 {
 #if (defined(WIN32) && _MSC_VER >= 1310) || __MSVCRT_VERSION__ >= 0x0601
@@ -613,27 +809,29 @@ char **VSIWin32FilesystemHandler::ReadDir( const char *pszPath )
         intptr_t hFile;
         char    *pszFileSpec;
         CPLStringList oDir;
-        
+
         if (strlen(pszPath) == 0)
             pszPath = ".";
-        
+
         pszFileSpec = CPLStrdup(CPLSPrintf("%s\\*.*", pszPath));
-        wchar_t *pwszFileSpec = 
+        wchar_t *pwszFileSpec =
             CPLRecodeToWChar( pszFileSpec, CPL_ENC_UTF8, CPL_ENC_UCS2 );
-        
+
         if ( (hFile = _wfindfirst( pwszFileSpec, &c_file )) != -1L )
         {
             do
             {
                 oDir.AddStringDirectly(
                     CPLRecodeFromWChar(c_file.name,CPL_ENC_UCS2,CPL_ENC_UTF8));
+                if( nMaxFiles > 0 && oDir.Count() > nMaxFiles )
+                    break;
             } while( _wfindnext( hFile, &c_file ) == 0 );
-            
+
             _findclose( hFile );
         }
         else
         {
-            /* Should we generate an error???  
+            /* Should we generate an error???
              * For now we'll just return NULL (at the end of the function)
              */
         }
@@ -650,35 +848,52 @@ char **VSIWin32FilesystemHandler::ReadDir( const char *pszPath )
         intptr_t hFile;
         char    *pszFileSpec;
         CPLStringList oDir;
-        
+
         if (strlen(pszPath) == 0)
             pszPath = ".";
-        
+
         pszFileSpec = CPLStrdup(CPLSPrintf("%s\\*.*", pszPath));
-        
+
         if ( (hFile = _findfirst( pszFileSpec, &c_file )) != -1L )
         {
             do
             {
                 oDir.AddString(c_file.name);
+                if( nMaxFiles > 0 && oDir.Count() > nMaxFiles )
+                    break;
             } while( _findnext( hFile, &c_file ) == 0 );
-            
+
             _findclose( hFile );
         }
         else
         {
-            /* Should we generate an error???  
+            /* Should we generate an error???
              * For now we'll just return NULL (at the end of the function)
              */
         }
 
         CPLFree(pszFileSpec);
-        
+
         return oDir.StealList();
     }
 }
 
 /************************************************************************/
+/*                        GetDiskFreeSpace()                            */
+/************************************************************************/
+
+GIntBig VSIWin32FilesystemHandler::GetDiskFreeSpace( const char* pszDirname )
+{
+    GIntBig nRet = -1;
+    ULARGE_INTEGER nFreeBytesAvailable;
+    if( GetDiskFreeSpaceEx(pszDirname, &nFreeBytesAvailable, NULL, NULL) )
+    {
+        nRet = static_cast<GIntBig>(nFreeBytesAvailable.QuadPart);
+    }
+    return nRet;
+}
+
+/************************************************************************/
 /*                     VSIInstallLargeFileHandler()                     */
 /************************************************************************/
 
@@ -689,5 +904,3 @@ void VSIInstallLargeFileHandler()
 }
 
 #endif /* def WIN32 */
-
-
diff --git a/port/cpl_vsisimple.cpp b/port/cpl_vsisimple.cpp
index e012c29..cb6a9a3 100644
--- a/port/cpl_vsisimple.cpp
+++ b/port/cpl_vsisimple.cpp
@@ -1,7 +1,7 @@
 /******************************************************************************
- * $Id: cpl_vsisimple.cpp 28971 2015-04-21 20:40:44Z rouault $
+ * $Id: cpl_vsisimple.cpp 33724 2016-03-16 17:14:11Z goatbar $
  *
- * Project:  Common Portability Library 
+ * Project:  Common Portability Library
  * Purpose:  Simple implementation of POSIX VSI functions.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -36,10 +36,10 @@
  ****************************************************************************/
 
 #include "cpl_config.h"
-#include "cpl_port.h"
-#include "cpl_vsi.h"
 #include "cpl_error.h"
+#include "cpl_port.h"
 #include "cpl_string.h"
+#include "cpl_vsi.h"
 
 /* Uncomment to check consistent usage of VSIMalloc(), VSIRealloc(), */
 /* VSICalloc(), VSIFree(), VSIStrdup() */
@@ -61,31 +61,32 @@
 /* DEBUG_VSIMALLOC must also be defined */
 //#define DEBUG_VSIMALLOC_VERBOSE
 
-CPL_CVSID("$Id: cpl_vsisimple.cpp 28971 2015-04-21 20:40:44Z rouault $");
+/* Number of bytes of the malloc/calloc/free that triggers a debug trace. Can be 0 for all allocs */
+#define THRESHOLD_PRINT 10000
+
+/* Uncomment to print GDAL block cache use. */
+/* Only used if DEBUG_VSIMALLOC_VERBOSE is enabled */
+//#define DEBUG_BLOCK_CACHE_USE
+
+#ifdef DEBUG_BLOCK_CACHE_USE
+extern "C" GIntBig CPL_DLL CPL_STDCALL GDALGetCacheUsed64(void);
+#endif
+
+CPL_CVSID("$Id: cpl_vsisimple.cpp 33724 2016-03-16 17:14:11Z goatbar $");
 
 /* for stat() */
 
 /* Unix or Windows NT/2000/XP */
-#if !defined(WIN32) && !defined(WIN32CE)
+#if !defined(WIN32)
 #  include <unistd.h>
-#elif !defined(WIN32CE) /* not Win32 platform */
+#else
 #  include <io.h>
 #  include <fcntl.h>
 #  include <direct.h>
 #endif
 
-/* Windows CE or other platforms */
-#if defined(WIN32CE)
-#  include <wce_io.h>
-#  include <wce_stat.h>
-#  include <wce_stdio.h>
-#  include <wce_string.h>
-#  include <wce_time.h>
-# define time wceex_time
-#else
-#  include <sys/stat.h>
-#  include <time.h>
-#endif
+#include <sys/stat.h>
+#include <time.h>
 
 /************************************************************************/
 /*                              VSIFOpen()                              */
@@ -95,15 +96,14 @@ FILE *VSIFOpen( const char * pszFilename, const char * pszAccess )
 
 {
     FILE *fp = NULL;
-    int     nError;
 
-#if defined(WIN32) && !defined(WIN32CE)
+#if defined(WIN32)
     if( CSLTestBoolean(
             CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
     {
-        wchar_t *pwszFilename = 
+        wchar_t *pwszFilename =
             CPLRecodeToWChar( pszFilename, CPL_ENC_UTF8, CPL_ENC_UCS2 );
-        wchar_t *pwszAccess = 
+        wchar_t *pwszAccess =
             CPLRecodeToWChar( pszAccess, CPL_ENC_UTF8, CPL_ENC_UCS2 );
 
         fp = _wfopen( pwszFilename, pwszAccess );
@@ -115,11 +115,15 @@ FILE *VSIFOpen( const char * pszFilename, const char * pszAccess )
 #endif
     fp = fopen( (char *) pszFilename, (char *) pszAccess );
 
-    nError = errno;
+#ifdef VSI_DEBUG
+    // Capture the error from fopen to avoid being overwritten by errors
+    // from VSIDebug3.
+    const int nError = errno;
     VSIDebug3( "VSIFOpen(%s,%s) = %p", pszFilename, pszAccess, fp );
     errno = nError;
+#endif
 
-    return( fp );
+    return fp;
 }
 
 /************************************************************************/
@@ -131,7 +135,7 @@ int VSIFClose( FILE * fp )
 {
     VSIDebug1( "VSIClose(%p)", fp );
 
-    return( fclose(fp) );
+    return fclose(fp);
 }
 
 /************************************************************************/
@@ -141,10 +145,19 @@ int VSIFClose( FILE * fp )
 int VSIFSeek( FILE * fp, long nOffset, int nWhence )
 
 {
-    int     nResult = fseek( fp, nOffset, nWhence );
-    int     nError = errno;
+#ifdef DEBUG
+    /* To workaround Coverity strange warning about potential negative seek */
+    /* CID 1340084 when called from dgnwrite.cpp */
+    if( nWhence == SEEK_SET && nOffset < 0 )
+        return -1;
+#endif
+    int nResult = fseek( fp, nOffset, nWhence );
 
 #ifdef VSI_DEBUG
+    // Capture the error from fseek to avoid being overwritten by errors
+    // from VSIDebug.
+    const int nError = errno;
+
     if( nWhence == SEEK_SET )
     {
         VSIDebug3( "VSIFSeek(%p,%ld,SEEK_SET) = %d", fp, nOffset, nResult );
@@ -162,9 +175,10 @@ int VSIFSeek( FILE * fp, long nOffset, int nWhence )
         VSIDebug4( "VSIFSeek(%p,%ld,%d-Unknown) = %d",
                    fp, nOffset, nWhence, nResult );
     }
-#endif 
 
     errno = nError;
+#endif
+
     return nResult;
 }
 
@@ -175,12 +189,16 @@ int VSIFSeek( FILE * fp, long nOffset, int nWhence )
 long VSIFTell( FILE * fp )
 
 {
-    long    nOffset = ftell(fp);
-    int     nError = errno;
+    const long nOffset = ftell(fp);
 
+#ifdef VSI_DEBUG
+    // Capture the error from ftell to avoid being overwritten by errors
+    // from VSIDebug.
+    const int nError = errno;
     VSIDebug2( "VSIFTell(%p) = %ld", fp, nOffset );
-
     errno = nError;
+#endif
+
     return nOffset;
 }
 
@@ -193,6 +211,13 @@ void VSIRewind( FILE * fp )
 {
     VSIDebug1("VSIRewind(%p)", fp );
     rewind( fp );
+#ifdef VSI_DEBUG
+    // Capture the error rewind ftell to avoid being overwritten by errors
+    // from VSIDebug.
+    const int nError = errno;
+    VSIDebug2( "VSIRewind(%p) errno = %d", fp, nError );
+    errno = nError;
+#endif
 }
 
 /************************************************************************/
@@ -202,13 +227,18 @@ void VSIRewind( FILE * fp )
 size_t VSIFRead( void * pBuffer, size_t nSize, size_t nCount, FILE * fp )
 
 {
-    size_t  nResult = fread( pBuffer, nSize, nCount, fp );
-    int     nError = errno;
-
-    VSIDebug4( "VSIFRead(%p,%ld,%ld) = %ld", 
-               fp, (long)nSize, (long)nCount, (long)nResult );
+    const size_t nResult = fread( pBuffer, nSize, nCount, fp );
 
+#ifdef VSI_DEBUG
+    // Capture the error from fread to avoid being overwritten by errors
+    // from VSIDebug.
+    const int nError = errno;
+    VSIDebug4( "VSIFRead(%p,%ld,%ld) = %ld",
+               fp, static_cast<long>(nSize), static_cast<long>(nCount),
+               static_cast<long>(nResult) );
     errno = nError;
+#endif
+
     return nResult;
 }
 
@@ -219,13 +249,18 @@ size_t VSIFRead( void * pBuffer, size_t nSize, size_t nCount, FILE * fp )
 size_t VSIFWrite( const void *pBuffer, size_t nSize, size_t nCount, FILE * fp )
 
 {
-    size_t  nResult = fwrite( pBuffer, nSize, nCount, fp );
-    int     nError = errno;
-
-    VSIDebug4( "VSIFWrite(%p,%ld,%ld) = %ld", 
-               fp, (long)nSize, (long)nCount, (long)nResult );
+    const size_t nResult = fwrite( pBuffer, nSize, nCount, fp );
 
+#ifdef VSI_DEBUG
+    // Capture the error from fwrite to avoid being overwritten by errors
+    // from VSIDebug.
+    const int nError = errno;
+    VSIDebug4( "VSIFWrite(%p,%ld,%ld) = %ld",
+               fp, static_cast<long>(nSize), static_cast<long>(nCount),
+               static_cast<long>(nResult) );
     errno = nError;
+#endif
+
     return nResult;
 }
 
@@ -236,8 +271,24 @@ size_t VSIFWrite( const void *pBuffer, size_t nSize, size_t nCount, FILE * fp )
 void VSIFFlush( FILE * fp )
 
 {
+#ifdef VSI_DEBUG
     VSIDebug1( "VSIFFlush(%p)", fp );
-    fflush( fp );
+    const int result =
+#endif
+        fflush( fp );
+
+#ifdef VSI_DEBUG
+    // Capture the error rewind ftell to avoid being overwritten by errors
+    // from VSIDebug.
+    const int nError = errno;
+    VSIDebug2( "VSIRewind(%p) errno = %d", fp, nError );
+    if ( result != 0 )
+    {
+        CPLError( CE_Failure, CPLE_FileIO, "Flush failed.  errno = %d",
+                  nError);
+    }
+    errno = nError;
+#endif
 }
 
 /************************************************************************/
@@ -247,7 +298,7 @@ void VSIFFlush( FILE * fp )
 char *VSIFGets( char *pszBuffer, int nBufferSize, FILE * fp )
 
 {
-    return( fgets( pszBuffer, nBufferSize, fp ) );
+    return fgets( pszBuffer, nBufferSize, fp );
 }
 
 /************************************************************************/
@@ -257,7 +308,7 @@ char *VSIFGets( char *pszBuffer, int nBufferSize, FILE * fp )
 int VSIFGetc( FILE * fp )
 
 {
-    return( fgetc( fp ) );
+    return fgetc( fp );
 }
 
 /************************************************************************/
@@ -267,7 +318,7 @@ int VSIFGetc( FILE * fp )
 int VSIUngetc( int c, FILE * fp )
 
 {
-    return( ungetc( c, fp ) );
+    return ungetc( c, fp );
 }
 
 /************************************************************************/
@@ -282,13 +333,12 @@ int     VSIFPrintf( FILE * fp, const char * pszFormat, ... )
 
 {
     va_list     args;
-    int         nReturn;
 
     va_start( args, pszFormat );
-    nReturn = vfprintf( fp, pszFormat, args );
+    const int nReturn = vfprintf( fp, pszFormat, args );
     va_end( args );
 
-    return( nReturn );
+    return nReturn;
 }
 
 /************************************************************************/
@@ -298,7 +348,7 @@ int     VSIFPrintf( FILE * fp, const char * pszFormat, ... )
 int VSIFEof( FILE * fp )
 
 {
-    return( feof( fp ) );
+    return feof( fp );
 }
 
 /************************************************************************/
@@ -318,7 +368,7 @@ int VSIFPuts( const char * pszString, FILE * fp )
 int VSIFPutc( int nChar, FILE * fp )
 
 {
-    return( fputc( nChar, fp ) );
+    return fputc( nChar, fp );
 }
 
 
@@ -342,6 +392,8 @@ static GUIntBig nVSIFrees = 0;
 /*                         VSIShowMemStats()                            */
 /************************************************************************/
 
+void VSIShowMemStats();
+
 void VSIShowMemStats()
 {
     char* pszShowMemStats = getenv("CPL_SHOW_MEM_STATS");
@@ -424,8 +476,11 @@ void *VSICalloc( size_t nCount, size_t nSize )
     {
         CPLMutexHolderD(&hMemStatMutex);
 #ifdef DEBUG_VSIMALLOC_VERBOSE
-        fprintf(stderr, "Thread[%p] VSICalloc(%d,%d) = %p\n",
-                (void*)CPLGetPID(), (int)nCount, (int)nSize, ptr + 2 * sizeof(void*));
+        if( nMul > THRESHOLD_PRINT )
+        {
+            fprintf(stderr, "Thread[%p] VSICalloc(%d,%d) = %p\n",
+                    (void*)CPLGetPID(), (int)nCount, (int)nSize, ptr + 2 * sizeof(void*));
+        }
 #endif
 #ifdef DEBUG_VSIMALLOC_STATS
         nVSICallocs ++;
@@ -439,7 +494,7 @@ void *VSICalloc( size_t nCount, size_t nSize )
 #endif
     return ptr + 2 * sizeof(void*);
 #else
-    return( calloc( nCount, nSize ) );
+    return calloc( nCount, nSize );
 #endif
 }
 
@@ -447,10 +502,18 @@ void *VSICalloc( size_t nCount, size_t nSize )
 /*                             VSIMalloc()                              */
 /************************************************************************/
 
+#ifndef DEBUG_VSIMALLOC
+void *VSIMalloc( size_t nSize )
+
+{
+    return malloc( nSize );
+}
+
+#else  // DEBUG_VSIMALLOC
+
 void *VSIMalloc( size_t nSize )
 
 {
-#ifdef DEBUG_VSIMALLOC
     if (nMaxPeakAllocSize < 0)
     {
         char* pszMaxPeakAllocSize = getenv("CPL_MAX_PEAK_ALLOC_SIZE");
@@ -463,7 +526,7 @@ void *VSIMalloc( size_t nSize )
 #ifdef DEBUG_VSIMALLOC_STATS
     if (nMaxCumulAllocSize > 0 && (GIntBig)nCurrentTotalAllocs + (GIntBig)nSize > nMaxCumulAllocSize)
         return NULL;
-#endif
+#endif  // DEBUG_VSIMALLOC_STATS
 
 #ifdef DEBUG_VSIMALLOC_MPROTECT
     char* ptr = NULL;
@@ -471,7 +534,7 @@ void *VSIMalloc( size_t nSize )
     posix_memalign((void**)&ptr, nPageSize, (3 * sizeof(void*) + nSize + nPageSize - 1) & ~(nPageSize - 1));
 #else
     char* ptr = (char*) malloc(3 * sizeof(void*) + nSize);
-#endif
+#endif  // DEBUG_VSIMALLOC_MPROTECT
     if (ptr == NULL)
         return NULL;
     ptr[0] = 'V';
@@ -487,9 +550,28 @@ void *VSIMalloc( size_t nSize )
     {
         CPLMutexHolderD(&hMemStatMutex);
 #ifdef DEBUG_VSIMALLOC_VERBOSE
-        fprintf(stderr, "Thread[%p] VSIMalloc(%d) = %p\n",
-                (void*)CPLGetPID(), (int)nSize, ptr + 2 * sizeof(void*));
+        if( nSize > THRESHOLD_PRINT )
+        {
+            fprintf(stderr, "Thread[%p] VSIMalloc(%d) = %p"
+#ifdef DEBUG_VSIMALLOC_STATS
+                         ", current_cumul = " CPL_FRMT_GUIB
+#ifdef DEBUG_BLOCK_CACHE_USE
+                         ", block_cache_used = " CPL_FRMT_GIB
+#endif
+                         ", mal+cal-free = %d"
 #endif
+                         "\n",
+                (void*)CPLGetPID(), (int)nSize, ptr + 2 * sizeof(void*)
+#ifdef DEBUG_VSIMALLOC_STATS
+                , (GUIntBig)(nCurrentTotalAllocs + nSize),
+#ifdef DEBUG_BLOCK_CACHE_USE
+                , GDALGetCacheUsed64()
+#endif
+                ,(int)(nVSIMallocs + nVSICallocs - nVSIFrees)
+#endif
+                );
+        }
+#endif  // DEBUG_VSIMALLOC_VERBOSE
 #ifdef DEBUG_VSIMALLOC_STATS
         nVSIMallocs ++;
         if (nMaxTotalAllocs == 0)
@@ -497,17 +579,13 @@ void *VSIMalloc( size_t nSize )
         nCurrentTotalAllocs += nSize;
         if (nCurrentTotalAllocs > nMaxTotalAllocs)
             nMaxTotalAllocs = nCurrentTotalAllocs;
-#endif
+#endif  // DEBUG_VSIMALLOC_STATS
     }
-#endif
+#endif  // DEBUG_VSIMALLOC_STATS || DEBUG_VSIMALLOC_VERBOSE
     return ptr + 2 * sizeof(void*);
-#else
-    return( malloc( nSize ) );
-#endif
 }
 
-#ifdef DEBUG_VSIMALLOC
-void VSICheckMarkerBegin(char* ptr)
+static void VSICheckMarkerBegin(char* ptr)
 {
     if (memcmp(ptr, "VSIM", 4) != 0)
     {
@@ -517,7 +595,7 @@ void VSICheckMarkerBegin(char* ptr)
     }
 }
 
-void VSICheckMarkerEnd(char* ptr, size_t nEnd)
+static void VSICheckMarkerEnd(char* ptr, size_t nEnd)
 {
     if (memcmp(ptr + nEnd, "EVSI", 4) != 0)
     {
@@ -526,11 +604,11 @@ void VSICheckMarkerEnd(char* ptr, size_t nEnd)
     }
 }
 
-#endif
+#endif  // DEBUG_VSIMALLOC
 
 /************************************************************************/
 /*                             VSIRealloc()                             */
-/************************************************************************/      
+/************************************************************************/
 
 void * VSIRealloc( void * pData, size_t nNewSize )
 
@@ -538,17 +616,13 @@ void * VSIRealloc( void * pData, size_t nNewSize )
 #ifdef DEBUG_VSIMALLOC
     if (pData == NULL)
         return VSIMalloc(nNewSize);
-        
+
     char* ptr = ((char*)pData) - 2 * sizeof(void*);
     VSICheckMarkerBegin(ptr);
 
-    size_t nOldSize;
+    size_t nOldSize = 0;
     memcpy(&nOldSize, ptr + sizeof(void*), sizeof(void*));
     VSICheckMarkerEnd(ptr, 2 * sizeof(void*) + nOldSize);
-    ptr[2 * sizeof(void*) + nOldSize + 0] = 'I';
-    ptr[2 * sizeof(void*) + nOldSize + 1] = 'S';
-    ptr[2 * sizeof(void*) + nOldSize + 2] = 'V';
-    ptr[2 * sizeof(void*) + nOldSize + 3] = 'E';
 
     if (nMaxPeakAllocSize < 0)
     {
@@ -562,6 +636,11 @@ void * VSIRealloc( void * pData, size_t nNewSize )
         return NULL;
 #endif
 
+    ptr[2 * sizeof(void*) + nOldSize + 0] = 'I';
+    ptr[2 * sizeof(void*) + nOldSize + 1] = 'S';
+    ptr[2 * sizeof(void*) + nOldSize + 2] = 'V';
+    ptr[2 * sizeof(void*) + nOldSize + 3] = 'E';
+
 #ifdef DEBUG_VSIMALLOC_MPROTECT
     char* newptr = NULL;
     size_t nPageSize = getpagesize();
@@ -606,8 +685,11 @@ void * VSIRealloc( void * pData, size_t nNewSize )
     {
         CPLMutexHolderD(&hMemStatMutex);
 #ifdef DEBUG_VSIMALLOC_VERBOSE
-        fprintf(stderr, "Thread[%p] VSIRealloc(%p, %d) = %p\n",
-                (void*)CPLGetPID(), pData, (int)nNewSize, ptr + 2 * sizeof(void*));
+        if( nNewSize > THRESHOLD_PRINT )
+        {
+            fprintf(stderr, "Thread[%p] VSIRealloc(%p, %d) = %p\n",
+                    (void*)CPLGetPID(), pData, (int)nNewSize, ptr + 2 * sizeof(void*));
+        }
 #endif
 #ifdef DEBUG_VSIMALLOC_STATS
         nVSIReallocs ++;
@@ -620,7 +702,7 @@ void * VSIRealloc( void * pData, size_t nNewSize )
 #endif
     return ptr + 2 * sizeof(void*);
 #else
-    return( realloc( pData, nNewSize ) );
+    return realloc( pData, nNewSize );
 #endif
 }
 
@@ -637,7 +719,7 @@ void VSIFree( void * pData )
 
     char* ptr = ((char*)pData) - 2 * sizeof(void*);
     VSICheckMarkerBegin(ptr);
-    size_t nOldSize;
+    size_t nOldSize = 0;
     memcpy(&nOldSize, ptr + sizeof(void*), sizeof(void*));
     VSICheckMarkerEnd(ptr, 2 * sizeof(void*) + nOldSize);
     ptr[0] = 'M';
@@ -652,8 +734,11 @@ void VSIFree( void * pData )
     {
         CPLMutexHolderD(&hMemStatMutex);
 #ifdef DEBUG_VSIMALLOC_VERBOSE
-        fprintf(stderr, "Thread[%p] VSIFree(%p, (%d bytes))\n",
-                (void*)CPLGetPID(), pData, (int)nOldSize);
+        if( nOldSize > THRESHOLD_PRINT )
+        {
+            fprintf(stderr, "Thread[%p] VSIFree(%p, (%d bytes))\n",
+                    (void*)CPLGetPID(), pData, (int)nOldSize);
+        }
 #endif
 #ifdef DEBUG_VSIMALLOC_STATS
         nVSIFrees ++;
@@ -681,8 +766,8 @@ void VSIFree( void * pData )
 char *VSIStrdup( const char * pszString )
 
 {
-    int nSize = strlen(pszString) + 1;
-    char* ptr = (char*) VSIMalloc(nSize);
+    const size_t nSize = strlen(pszString) + 1;
+    char* ptr = static_cast<char*>( VSIMalloc(nSize) );
     if (ptr == NULL)
         return NULL;
     memcpy(ptr, pszString, nSize);
@@ -693,9 +778,10 @@ char *VSIStrdup( const char * pszString )
 /*                          VSICheckMul2()                              */
 /************************************************************************/
 
-static size_t VSICheckMul2( size_t mul1, size_t mul2, int *pbOverflowFlag)
+static size_t VSICheckMul2( size_t mul1, size_t mul2, int *pbOverflowFlag,
+                            const char* pszFile, int nLine )
 {
-    size_t res = mul1 * mul2;
+    const size_t res = mul1 * mul2;
     if (mul1 != 0)
     {
         if (res / mul1 == mul2)
@@ -709,8 +795,10 @@ static size_t VSICheckMul2( size_t mul1, size_t mul2, int *pbOverflowFlag)
             if (pbOverflowFlag)
                 *pbOverflowFlag = TRUE;
             CPLError(CE_Failure, CPLE_OutOfMemory,
-                     "Multiplication overflow : %lu * %lu",
-                     (unsigned long)mul1, (unsigned long)mul2);
+                     "%s: %d: Multiplication overflow : " CPL_FRMT_GUIB " * " CPL_FRMT_GUIB,
+                     pszFile ? pszFile : "(unknown file)",
+                     nLine,
+                     (GUIntBig)mul1, (GUIntBig)mul2);
         }
     }
     else
@@ -725,14 +813,15 @@ static size_t VSICheckMul2( size_t mul1, size_t mul2, int *pbOverflowFlag)
 /*                          VSICheckMul3()                              */
 /************************************************************************/
 
-static size_t VSICheckMul3( size_t mul1, size_t mul2, size_t mul3, int *pbOverflowFlag)
+static size_t VSICheckMul3( size_t mul1, size_t mul2, size_t mul3, int *pbOverflowFlag,
+                            const char* pszFile, int nLine )
 {
     if (mul1 != 0)
     {
-        size_t res = mul1 * mul2;
+        const size_t res = mul1 * mul2;
         if (res / mul1 == mul2)
         {
-            size_t res2 = res * mul3;
+            const size_t res2 = res * mul3;
             if (mul3 != 0)
             {
                 if (res2 / mul3 == res)
@@ -746,8 +835,10 @@ static size_t VSICheckMul3( size_t mul1, size_t mul2, size_t mul3, int *pbOverfl
                     if (pbOverflowFlag)
                         *pbOverflowFlag = TRUE;
                     CPLError(CE_Failure, CPLE_OutOfMemory,
-                     "Multiplication overflow : %lu * %lu * %lu",
-                     (unsigned long)mul1, (unsigned long)mul2, (unsigned long)mul3);
+                            "%s: %d: Multiplication overflow : " CPL_FRMT_GUIB " * " CPL_FRMT_GUIB " * " CPL_FRMT_GUIB,
+                            pszFile ? pszFile : "(unknown file)",
+                            nLine,
+                            (GUIntBig)mul1, (GUIntBig)mul2, (GUIntBig)mul3);
                 }
             }
             else
@@ -761,8 +852,10 @@ static size_t VSICheckMul3( size_t mul1, size_t mul2, size_t mul3, int *pbOverfl
             if (pbOverflowFlag)
                 *pbOverflowFlag = TRUE;
             CPLError(CE_Failure, CPLE_OutOfMemory,
-                     "Multiplication overflow : %lu * %lu * %lu",
-                     (unsigned long)mul1, (unsigned long)mul2, (unsigned long)mul3);
+                    "%s: %d: Multiplication overflow : " CPL_FRMT_GUIB " * " CPL_FRMT_GUIB " * " CPL_FRMT_GUIB,
+                    pszFile ? pszFile : "(unknown file)",
+                    nLine,
+                    (GUIntBig)mul1, (GUIntBig)mul2, (GUIntBig)mul3);
         }
     }
     else
@@ -784,27 +877,7 @@ static size_t VSICheckMul3( size_t mul1, size_t mul2, size_t mul3, int *pbOverfl
 */
 void CPL_DLL *VSIMalloc2( size_t nSize1, size_t nSize2 )
 {
-    int bOverflowFlag = FALSE;
-    size_t nSizeToAllocate;
-    void* pReturn;
-
-    nSizeToAllocate = VSICheckMul2( nSize1, nSize2, &bOverflowFlag );
-    if (bOverflowFlag)
-        return NULL;
-
-    if (nSizeToAllocate == 0)
-        return NULL;
-
-    pReturn = VSIMalloc(nSizeToAllocate);
-
-    if( pReturn == NULL )
-    {
-        CPLError( CE_Failure, CPLE_OutOfMemory,
-                  "VSIMalloc2(): Out of memory allocating %lu bytes.\n",
-                  (unsigned long)nSizeToAllocate );
-    }
-
-    return pReturn;
+    return VSIMalloc2Verbose( nSize1, nSize2, NULL, 0);
 }
 
 /**
@@ -816,30 +889,121 @@ void CPL_DLL *VSIMalloc2( size_t nSize1, size_t nSize2 )
 */
 void CPL_DLL *VSIMalloc3( size_t nSize1, size_t nSize2, size_t nSize3 )
 {
-    int bOverflowFlag = FALSE;
+    return VSIMalloc3Verbose( nSize1, nSize2, nSize3, NULL, 0);
+}
 
-    size_t nSizeToAllocate;
-    void* pReturn;
+/************************************************************************/
+/*                          VSIMallocVerbose()                          */
+/************************************************************************/
 
-    nSizeToAllocate = VSICheckMul3( nSize1, nSize2, nSize3, &bOverflowFlag );
-    if (bOverflowFlag)
+void *VSIMallocVerbose( size_t nSize, const char* pszFile, int nLine )
+{
+    void* pRet = VSIMalloc(nSize);
+    if( pRet == NULL && nSize != 0 )
+    {
+        CPLError(CE_Failure, CPLE_OutOfMemory,
+                 "%s, %d: cannot allocate " CPL_FRMT_GUIB " bytes",
+                 pszFile ? pszFile : "(unknown file)",
+                 nLine, (GUIntBig)nSize);
+    }
+    return pRet;
+}
+
+/************************************************************************/
+/*                          VSIMalloc2Verbose()                         */
+/************************************************************************/
+
+void *VSIMalloc2Verbose( size_t nSize1, size_t nSize2, const char* pszFile, int nLine )
+{
+    int bOverflowFlag = FALSE;
+    size_t nSizeToAllocate = VSICheckMul2( nSize1, nSize2, &bOverflowFlag, pszFile, nLine );
+    if (bOverflowFlag || nSizeToAllocate == 0)
         return NULL;
 
-    if (nSizeToAllocate == 0)
+    void* pRet = VSIMalloc(nSizeToAllocate);
+    if( pRet == NULL )
+    {
+        CPLError(CE_Failure, CPLE_OutOfMemory,
+                 "%s, %d: cannot allocate " CPL_FRMT_GUIB " bytes",
+                 pszFile ? pszFile : "(unknown file)",
+                 nLine, (GUIntBig)nSize1 * (GUIntBig)nSize2);
+    }
+    return pRet;
+}
+
+/************************************************************************/
+/*                          VSIMalloc3Verbose()                         */
+/************************************************************************/
+
+void *VSIMalloc3Verbose( size_t nSize1, size_t nSize2, size_t nSize3,
+                         const char* pszFile, int nLine )
+{
+    int bOverflowFlag = FALSE;
+    size_t nSizeToAllocate = VSICheckMul3( nSize1, nSize2, nSize3,
+                                           &bOverflowFlag, pszFile, nLine );
+    if (bOverflowFlag || nSizeToAllocate == 0)
         return NULL;
 
-    pReturn = VSIMalloc(nSizeToAllocate);
+    void* pRet = VSIMalloc(nSizeToAllocate);
+    if( pRet == NULL )
+    {
+        CPLError(CE_Failure, CPLE_OutOfMemory,
+                 "%s, %d: cannot allocate " CPL_FRMT_GUIB " bytes",
+                 pszFile ? pszFile : "(unknown file)",
+                 nLine, (GUIntBig)nSize1 * (GUIntBig)nSize2 * (GUIntBig)nSize3);
+    }
+    return pRet;
+}
+/************************************************************************/
+/*                          VSICallocVerbose()                          */
+/************************************************************************/
 
-    if( pReturn == NULL )
+void *VSICallocVerbose(  size_t nCount, size_t nSize, const char* pszFile, int nLine )
+{
+    void* pRet = VSICalloc(nCount, nSize);
+    if( pRet == NULL && nCount != 0 && nSize != 0 )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory,
-                  "VSIMalloc3(): Out of memory allocating %lu bytes.\n",
-                  (unsigned long)nSizeToAllocate );
+        CPLError(CE_Failure, CPLE_OutOfMemory,
+                 "%s, %d: cannot allocate " CPL_FRMT_GUIB " bytes",
+                 pszFile ? pszFile : "(unknown file)",
+                 nLine, (GUIntBig)nCount * (GUIntBig)nSize);
     }
+    return pRet;
+}
 
-    return pReturn;
+/************************************************************************/
+/*                          VSIReallocVerbose()                         */
+/************************************************************************/
+
+void *VSIReallocVerbose( void* pOldPtr, size_t nNewSize, const char* pszFile, int nLine )
+{
+    void* pRet = VSIRealloc(pOldPtr, nNewSize);
+    if( pRet == NULL && nNewSize != 0 )
+    {
+        CPLError(CE_Failure, CPLE_OutOfMemory,
+                 "%s, %d: cannot allocate " CPL_FRMT_GUIB " bytes",
+                 pszFile ? pszFile : "(unknown file)",
+                 nLine, (GUIntBig)(nNewSize));
+    }
+    return pRet;
 }
 
+/************************************************************************/
+/*                          VSIStrdupVerbose()                          */
+/************************************************************************/
+
+char *VSIStrdupVerbose(  const char* pszStr, const char* pszFile, int nLine )
+{
+    char* pRet = VSIStrdup(pszStr);
+    if( pRet == NULL )
+    {
+        CPLError(CE_Failure, CPLE_OutOfMemory,
+                 "%s, %d: cannot allocate " CPL_FRMT_GUIB " bytes",
+                 pszFile ? pszFile : "(unknown file)",
+                 nLine, (GUIntBig)(strlen(pszStr)+1));
+    }
+    return pRet;
+}
 
 /************************************************************************/
 /*                              VSIStat()                               */
@@ -848,23 +1012,22 @@ void CPL_DLL *VSIMalloc3( size_t nSize1, size_t nSize2, size_t nSize3 )
 int VSIStat( const char * pszFilename, VSIStatBuf * pStatBuf )
 
 {
-#if defined(WIN32) && !defined(WIN32CE)
+#if defined(WIN32)
     if( CSLTestBoolean(
             CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
     {
-        int nResult;
-        wchar_t *pwszFilename = 
+        wchar_t *pwszFilename =
             CPLRecodeToWChar( pszFilename, CPL_ENC_UTF8, CPL_ENC_UCS2 );
 
-        nResult = _wstat( pwszFilename, (struct _stat *) pStatBuf );
+        int nResult = _wstat( pwszFilename, (struct _stat *) pStatBuf );
 
         CPLFree( pwszFilename );
 
         return nResult;
     }
-    else
-#endif 
-        return( stat( pszFilename, pStatBuf ) );
+
+#endif
+    return stat( pszFilename, pStatBuf );
 }
 
 /************************************************************************/
@@ -875,13 +1038,13 @@ unsigned long VSITime( unsigned long * pnTimeToSet )
 
 {
     time_t tTime;
-        
+
     tTime = time( NULL );
 
     if( pnTimeToSet != NULL )
-        *pnTimeToSet = (unsigned long) tTime;
+        *pnTimeToSet = static_cast<unsigned long>( tTime );
 
-    return (unsigned long) tTime;
+    return static_cast<unsigned long>( tTime );
 }
 
 /************************************************************************/
@@ -893,7 +1056,7 @@ const char *VSICTime( unsigned long nTime )
 {
     time_t tTime = (time_t) nTime;
 
-    return (const char *) ctime( &tTime );
+    return reinterpret_cast<const char *>(ctime( &tTime ));
 }
 
 /************************************************************************/
@@ -906,8 +1069,7 @@ struct tm *VSIGMTime( const time_t *pnTime, struct tm *poBrokenTime )
 #if HAVE_GMTIME_R
     gmtime_r( pnTime, poBrokenTime );
 #else
-    struct tm   *poTime;
-    poTime = gmtime( pnTime );
+    struct tm *poTime = gmtime( pnTime );
     memcpy( poBrokenTime, poTime, sizeof(tm) );
 #endif
 
@@ -924,8 +1086,7 @@ struct tm *VSILocalTime( const time_t *pnTime, struct tm *poBrokenTime )
 #if HAVE_LOCALTIME_R
     localtime_r( pnTime, poBrokenTime );
 #else
-    struct tm   *poTime;
-    poTime = localtime( pnTime );
+    struct tm *poTime = localtime( pnTime );
     memcpy( poBrokenTime, poTime, sizeof(tm) );
 #endif
 
@@ -956,7 +1117,8 @@ char *VSIStrerror( int nErrno )
  */
 GIntBig CPLGetPhysicalRAM(void)
 {
-    return ((GIntBig)sysconf(_SC_PHYS_PAGES)) * sysconf(_SC_PAGESIZE);
+    return static_cast<GIntBig>(sysconf(_SC_PHYS_PAGES))
+        * sysconf(_SC_PAGESIZE);
 }
 
 #elif defined(__MACH__) && defined(__APPLE__)
@@ -966,13 +1128,11 @@ GIntBig CPLGetPhysicalRAM(void)
 
 GIntBig CPLGetPhysicalRAM(void)
 {
-    int mib[2];
     GIntBig nPhysMem = 0;
 
-    mib[0] = CTL_HW;
-    mib[1] = HW_MEMSIZE;
+    int mib[2] = { CTL_HW, HW_MEMSIZE };
     size_t nLengthRes = sizeof(nPhysMem);
-    sysctl(mib, 2, &nPhysMem, &nLengthRes, NULL, 0);
+    sysctl(mib, CPL_ARRAYSIZE(mib), &nPhysMem, &nLengthRes, NULL, 0);
 
     return nPhysMem;
 }
@@ -991,17 +1151,17 @@ GIntBig CPLGetPhysicalRAM(void)
     statex.ullTotalPhys = 0;
     statex.dwLength = sizeof (statex);
     GlobalMemoryStatusEx (&statex);
-    return (GIntBig) statex.ullTotalPhys;
+    return static_cast<GIntBig>( statex.ullTotalPhys );
 }
 
 #else
 
 GIntBig CPLGetPhysicalRAM(void)
 {
-    static int bOnce = FALSE;
+    static bool bOnce = false;
     if( !bOnce )
     {
-        bOnce = TRUE;
+        bOnce = true;
         CPLDebug("PORT", "No implementation for CPLGetPhysicalRAM()");
     }
     return 0;
diff --git a/port/cpl_win32ce_api.cpp b/port/cpl_win32ce_api.cpp
deleted file mode 100644
index c174a26..0000000
--- a/port/cpl_win32ce_api.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-/******************************************************************************
- * $Id: cpl_win32ce_api.cpp 10645 2007-01-18 02:22:39Z warmerdam $
- *
- * Name:     cpl_win32ce_api.cpp
- * Project:  CPL - Common Portability Library
- * Purpose:  ASCII wrappers around only Unicode Windows CE API.
- * Author:   Mateusz �oskot, mloskot at taxussi.com.pl
- *
- ******************************************************************************
- * Copyright (c) 2006, Mateusz �oskot
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-#include "cpl_port.h"
-#include "cpl_win32ce_api.h"
-
-#ifdef WIN32CE
-
-CPL_CVSID("$Id: cpl_win32ce_api.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
-
-
-/* Assume UNICODE and _UNICODE are defined here and TCHAR is wide-char. */
-
-#include <windows.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-HMODULE CE_LoadLibraryA(LPCSTR lpLibFileName)
-{
-    HMODULE hLib = NULL;
-    
-    size_t nLen = 0;
-    LPTSTR pszWideStr = 0;
-
-    /* Covert filename buffer to Unicode. */
-    nLen = MultiByteToWideChar (CP_ACP, 0, lpLibFileName, -1, NULL, 0) ;
-    pszWideStr = (wchar_t*)malloc(sizeof(wchar_t) * nLen);
-    MultiByteToWideChar(CP_ACP, 0, lpLibFileName, -1, pszWideStr, nLen);
-
-    hLib = LoadLibraryW(pszWideStr);
-
-    /* Free me! */
-    free(pszWideStr);
-
-    return hLib;
-}
-
-FARPROC CE_GetProcAddressA(HMODULE hModule, LPCSTR lpProcName)
-{
-    FARPROC proc = NULL;
-
-    size_t nLen = 0;
-    LPTSTR pszWideStr = 0;
-
-    /* Covert filename buffer to Unicode. */
-    nLen = MultiByteToWideChar (CP_ACP, 0, lpProcName, -1, NULL, 0) ;
-    pszWideStr = (wchar_t*)malloc(sizeof(wchar_t) * nLen);
-    MultiByteToWideChar(CP_ACP, 0, lpProcName, -1, pszWideStr, nLen);
-
-    proc = GetProcAddressW(hModule, pszWideStr);
-
-    /* Free me! */
-    free(pszWideStr);
-
-    return proc;
-}
-
-
-DWORD CE_GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize)
-{
-    DWORD dwLen = 0;
-    TCHAR szWBuf[MAX_PATH]; /* wide-char buffer */
-
-    if (lpFilename == NULL)
-    {
-        return 0; /* Error */
-    }
-
-    /* Get module filename to wide-char buffer */
-    dwLen = GetModuleFileName(hModule, szWBuf, nSize);
-   
-    /* Covert buffer from Unicode to ANSI string. */
-    WideCharToMultiByte(CP_ACP, 0, szWBuf, -1, lpFilename, dwLen, NULL, NULL);
-
-    return dwLen;
-}
-
-HANDLE CE_CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess,
-                   DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
-                   DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
-                   HANDLE hTemplateFile)
-{
-    HANDLE hFile = INVALID_HANDLE_VALUE;
-    
-    size_t nLen  = 0;
-    wchar_t * pszWideStr = NULL;
-    
-    /* Covert filename buffer to Unicode. */
-    nLen = MultiByteToWideChar (CP_ACP, 0, lpFileName, -1, NULL, 0) ;
-    pszWideStr = (wchar_t*)malloc(sizeof(wchar_t) * nLen);
-    MultiByteToWideChar(CP_ACP, 0, lpFileName, -1, pszWideStr, nLen);
-
-    hFile = CreateFileW(pszWideStr, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
-                       dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
-
-    /* Free me! */
-    free(pszWideStr);
-
-    return hFile;
-}
-
-
-#endif /* #ifdef WIN32CE */
diff --git a/port/cpl_win32ce_api.h b/port/cpl_win32ce_api.h
deleted file mode 100644
index 7e87587..0000000
--- a/port/cpl_win32ce_api.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/******************************************************************************
- * $Id: cpl_win32ce_api.h 10645 2007-01-18 02:22:39Z warmerdam $
- *
- * Name:     cpl_win32ce_api.h
- * Project:  CPL - Common Portability Library
- * Purpose:  ASCII wrappers around only Unicode Windows CE API.
- * Author:   Mateusz �oskot, mloskot at taxussi.com.pl
- *
- ******************************************************************************
- * Copyright (c) 2006, Mateusz �oskot
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-#ifndef _CPL_WINCEAPI_H_INCLUDED
-#define _CPL_WINCEAPI_H_INCLUDED    1
-
-#define WIN32CE
-#if defined(WIN32CE)
-
-#include <windows.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif  /* __cplusplus */
-
-/*
- * Windows CE API non-Unicode Wrappers
- */
-
-HMODULE CE_LoadLibraryA(
-    LPCSTR lpLibFileName
-    );
-
-FARPROC CE_GetProcAddressA(
-    HMODULE hModule,
-    LPCSTR lpProcName
-    );
-
-
-DWORD CE_GetModuleFileNameA(
-    HMODULE hModule,
-    LPSTR lpFilename,
-    DWORD nSize
-    );
-
-HANDLE CE_CreateFileA(
-    LPCSTR lpFileName,
-    DWORD dwDesiredAccess,
-    DWORD dwShareMode,
-    LPSECURITY_ATTRIBUTES lpSecurityAttributes,
-    DWORD dwCreationDisposition,
-    DWORD dwFlagsAndAttributes,
-    HANDLE hTemplateFile
-    );
-
-
-/* Replace Windows CE API calls with our own non-Unicode equivalents. */
-
-
-/* XXX - mloskot - those defines are quite confusing ! */
-/*
-#ifdef LoadLibrary
-#  undef  LoadLibrary
-#  define LoadLibrary CE_LoadLibraryA
-#endif
-
-#ifdef GetProcAddress
-#  undef  GetProcAddress
-#  define GetProcAddress CE_GetProcAddressA
-#endif
-
-#ifdef GetModuleFileName
-#  undef  GetModuleFileName
-#  define GetModuleFileName CE_GetModuleFileNameA
-#endif
-
-#ifdef CreateFile
-#  undef  CreateFile
-#  define CreateFile CE_CreateFileA
-#endif
-*/
-
-#ifdef __cplusplus
-}
-#endif  /* __cplusplus */
-
-#endif /* #ifdef WIN32CE */
-
-#endif /* #ifndef _CPL_WINCEAPI_H_INCLUDED */
diff --git a/port/cpl_wince.h b/port/cpl_wince.h
deleted file mode 100644
index eddac42..0000000
--- a/port/cpl_wince.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/******************************************************************************
- * $Id: cpl_wince.h 10645 2007-01-18 02:22:39Z warmerdam $
- *
- * Name:     cpl_win_api.h
- * Project:  CPL - Common Portability Library
- * Purpose:  Windows CE specific declarations.
- * Author:   Mateusz �oskot, mloskot at taxussi.com.pl
- *
- ******************************************************************************
- * Copyright (c) 2006, Mateusz �oskot
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-#ifndef _CPL_WINCE_H_INCLUDED
-#define _CPL_WINCE_H_INCLUDED
-
-#include "cpl_config.h"
-
-#if defined(WIN32CE)
-
-#include "cpl_conv.h"
-#include "windows.h"
-
-
-
-#endif /* #if defined(WIN32CE) */
-
-#endif /* #ifndef _CPL_WINCE_H_INCLUDED */
diff --git a/port/cpl_worker_thread_pool.cpp b/port/cpl_worker_thread_pool.cpp
new file mode 100644
index 0000000..e9ecc17
--- /dev/null
+++ b/port/cpl_worker_thread_pool.cpp
@@ -0,0 +1,468 @@
+/**********************************************************************
+ * $Id: cpl_worker_thread_pool.cpp 32171 2015-12-13 20:39:43Z goatbar $
+ *
+ * Project:  CPL - Common Portability Library
+ * Purpose:  CPL worker thread pool
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ **********************************************************************
+ * Copyright (c) 2015, Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_worker_thread_pool.h"
+#include "cpl_conv.h"
+
+/************************************************************************/
+/*                         CPLWorkerThreadPool()                        */
+/************************************************************************/
+
+/** Instantiate a new pool of worker threads.
+ *
+ * The pool is in an uninitialized state after this call. The Setup() method
+ * must be called.
+ */
+CPLWorkerThreadPool::CPLWorkerThreadPool() :
+    hCond(NULL),
+    eState(CPLWTS_OK),
+    psJobQueue(NULL),
+    nPendingJobs(0),
+    psWaitingWorkerThreadsList(NULL),
+    nWaitingWorkerThreads(0)
+{
+    hMutex = CPLCreateMutexEx(CPL_MUTEX_REGULAR);
+    CPLReleaseMutex(hMutex);
+}
+
+/************************************************************************/
+/*                          ~CPLWorkerThreadPool()                      */
+/************************************************************************/
+
+/** Destroys a pool of worker threads.
+ *
+ * Any still pending job will be completed before the destructor returns.
+ */
+CPLWorkerThreadPool::~CPLWorkerThreadPool()
+{
+    if( hCond )
+    {
+        WaitCompletion();
+
+        eState = CPLWTS_STOP;
+
+        for(size_t i=0;i<aWT.size();i++)
+        {
+            CPLAcquireMutex(aWT[i].hMutex, 1000.0);
+            CPLCondSignal(aWT[i].hCond);
+            CPLReleaseMutex(aWT[i].hMutex);
+            CPLJoinThread(aWT[i].hThread);
+            CPLDestroyCond(aWT[i].hCond);
+            CPLDestroyMutex(aWT[i].hMutex);
+        }
+
+        CPLListDestroy(psWaitingWorkerThreadsList);
+
+        CPLDestroyCond(hCond);
+    }
+    CPLDestroyMutex(hMutex);
+}
+
+/************************************************************************/
+/*                       WorkerThreadFunction()                         */
+/************************************************************************/
+
+void CPLWorkerThreadPool::WorkerThreadFunction(void* user_data)
+{
+    CPLWorkerThread* psWT = (CPLWorkerThread* ) user_data;
+    CPLWorkerThreadPool* poTP = psWT->poTP;
+
+    if( psWT->pfnInitFunc )
+        psWT->pfnInitFunc( psWT->pInitData );
+
+    while( true )
+    {
+        CPLWorkerThreadJob* psJob = poTP->GetNextJob(psWT);
+        if( psJob == NULL )
+            break;
+
+        if( psJob->pfnFunc )
+        {
+            psJob->pfnFunc(psJob->pData);
+        }
+        CPLFree(psJob);
+        //CPLDebug("JOB", "%p finished a job", psWT);
+        poTP->DeclareJobFinished();
+    }
+}
+
+/************************************************************************/
+/*                             SubmitJob()                              */
+/************************************************************************/
+
+/** Queue a new job.
+ *
+ * @param pfnFunc Function to run for the job.
+ * @param pData User data to pass to the job function.
+ * @return true in case of success.
+ */
+bool CPLWorkerThreadPool::SubmitJob(CPLThreadFunc pfnFunc, void* pData)
+{
+    CPLAssert( aWT.size() > 0 );
+
+    CPLWorkerThreadJob* psJob = (CPLWorkerThreadJob*)VSI_MALLOC_VERBOSE(sizeof(CPLWorkerThreadJob));
+    if( psJob == NULL )
+        return false;
+    psJob->pfnFunc = pfnFunc;
+    psJob->pData = pData;
+
+    CPLList* psItem = (CPLList*) VSI_MALLOC_VERBOSE(sizeof(CPLList));
+    if( psItem == NULL )
+    {
+        VSIFree(psJob);
+        return false;
+    }
+    psItem->pData = psJob;
+
+    CPLAcquireMutex(hMutex, 1000.0);
+
+    psItem->psNext = psJobQueue;
+    psJobQueue = psItem;
+    nPendingJobs ++;
+
+    if( psWaitingWorkerThreadsList )
+    {
+        CPLWorkerThread* psWorkerThread;
+
+        psWorkerThread = (CPLWorkerThread*)psWaitingWorkerThreadsList->pData;
+
+        CPLAssert( psWorkerThread->bMarkedAsWaiting );
+        psWorkerThread->bMarkedAsWaiting = FALSE;
+
+        CPLList* psNext = psWaitingWorkerThreadsList->psNext;
+        CPLList* psToFree = psWaitingWorkerThreadsList;
+        psWaitingWorkerThreadsList = psNext;
+        nWaitingWorkerThreads --;
+
+        //CPLAssert( CPLListCount(psWaitingWorkerThreadsList) == nWaitingWorkerThreads);
+
+        //CPLDebug("JOB", "Waking up %p", psWorkerThread);
+        CPLAcquireMutex(psWorkerThread->hMutex, 1000.0);
+        CPLReleaseMutex(hMutex);
+        CPLCondSignal(psWorkerThread->hCond);
+        CPLReleaseMutex(psWorkerThread->hMutex);
+
+        CPLFree(psToFree);
+    }
+    else
+        CPLReleaseMutex(hMutex);
+
+    return true;
+}
+
+/************************************************************************/
+/*                             SubmitJobs()                              */
+/************************************************************************/
+
+/** Queue several jobs
+ *
+ * @param pfnFunc Function to run for the job.
+ * @param apData User data instances to pass to the job function.
+ * @return true in case of success.
+ */
+bool CPLWorkerThreadPool::SubmitJobs(CPLThreadFunc pfnFunc, const std::vector<void*>& apData)
+{
+    CPLAssert( aWT.size() > 0 );
+
+    CPLAcquireMutex(hMutex, 1000.0);
+
+    CPLList* psJobQueueInit = psJobQueue;
+    bool bRet = true;
+
+    for(size_t i=0;i<apData.size();i++)
+    {
+        CPLWorkerThreadJob* psJob = (CPLWorkerThreadJob*)VSI_MALLOC_VERBOSE(sizeof(CPLWorkerThreadJob));
+        if( psJob == NULL )
+        {
+            bRet = false;
+            break;
+        }
+        psJob->pfnFunc = pfnFunc;
+        psJob->pData = apData[i];
+
+        CPLList* psItem = (CPLList*) VSI_MALLOC_VERBOSE(sizeof(CPLList));
+        if( psItem == NULL )
+        {
+            VSIFree(psJob);
+            bRet = false;
+            break;
+        }
+        psItem->pData = psJob;
+
+        psItem->psNext = psJobQueue;
+        psJobQueue = psItem;
+        nPendingJobs ++;
+    }
+
+    if( !bRet )
+    {
+        for( CPLList* psIter = psJobQueue; psIter != psJobQueueInit; )
+        {
+            CPLList* psNext = psIter->psNext;
+            VSIFree(psIter->pData);
+            VSIFree(psIter);
+            nPendingJobs --;
+            psIter = psNext;
+        }
+    }
+
+    CPLReleaseMutex(hMutex);
+
+    if( !bRet )
+        return false;
+
+    for(size_t i=0;i<apData.size();i++)
+    {
+        CPLAcquireMutex(hMutex, 1000.0);
+
+        if( psWaitingWorkerThreadsList && psJobQueue )
+        {
+            CPLWorkerThread* psWorkerThread;
+
+            psWorkerThread = (CPLWorkerThread*)psWaitingWorkerThreadsList->pData;
+
+            CPLAssert( psWorkerThread->bMarkedAsWaiting );
+            psWorkerThread->bMarkedAsWaiting = FALSE;
+
+            CPLList* psNext = psWaitingWorkerThreadsList->psNext;
+            CPLList* psToFree = psWaitingWorkerThreadsList;
+            psWaitingWorkerThreadsList = psNext;
+            nWaitingWorkerThreads --;
+
+            //CPLAssert( CPLListCount(psWaitingWorkerThreadsList) == nWaitingWorkerThreads);
+
+            //CPLDebug("JOB", "Waking up %p", psWorkerThread);
+            CPLAcquireMutex(psWorkerThread->hMutex, 1000.0);
+
+            //CPLAssert(psWorkerThread->psNextJob == NULL);
+            //psWorkerThread->psNextJob = (CPLWorkerThreadJob*)psJobQueue->pData;
+            //psNext = psJobQueue->psNext;
+            //CPLFree(psJobQueue);
+            //psJobQueue = psNext;
+
+            CPLReleaseMutex(hMutex);
+            CPLCondSignal(psWorkerThread->hCond);
+            CPLReleaseMutex(psWorkerThread->hMutex);
+
+            CPLFree(psToFree);
+        }
+        else
+        {
+            CPLReleaseMutex(hMutex);
+            break;
+        }
+    }
+
+    return true;
+}
+
+/************************************************************************/
+/*                            WaitCompletion()                          */
+/************************************************************************/
+
+/** Wait for completion of part or whole jobs.
+ *
+ * @param nMaxRemainingJobs Maximum number of pendings jobs that are allowed
+ *                          in the queue after this method has completed. Might be
+ *                          0 to wait for all jobs.
+ */
+void CPLWorkerThreadPool::WaitCompletion(int nMaxRemainingJobs)
+{
+    if( nMaxRemainingJobs < 0 )
+        nMaxRemainingJobs = 0;
+    while( true )
+    {
+        CPLAcquireMutex(hMutex, 1000.0);
+        int nPendingJobsLocal = nPendingJobs;
+        if( nPendingJobsLocal > nMaxRemainingJobs )
+            CPLCondWait(hCond, hMutex);
+        CPLReleaseMutex(hMutex);
+        if( nPendingJobsLocal <= nMaxRemainingJobs )
+            break;
+    }
+}
+
+/************************************************************************/
+/*                                Setup()                               */
+/************************************************************************/
+
+/** Setup the pool.
+ *
+ * @param nThreads Number of threads to launch
+ * @param pfnInitFunc Initialization function to run in each thread. May be NULL
+ * @param pasInitData Array of initialization data. Its length must be nThreads,
+ *                    or it should be NULL.
+ * @return true if initialization was successful.
+ */
+bool CPLWorkerThreadPool::Setup(int nThreads,
+                            CPLThreadFunc pfnInitFunc,
+                            void** pasInitData)
+{
+    CPLAssert( nThreads > 0 );
+
+    hCond = CPLCreateCond();
+    if( hCond == NULL )
+        return false;
+
+    bool bRet = true;
+    aWT.resize(nThreads);
+    for(int i=0;i<nThreads;i++)
+    {
+        aWT[i].pfnInitFunc = pfnInitFunc;
+        aWT[i].pInitData = pasInitData ? pasInitData[i] : NULL;
+        aWT[i].poTP = this;
+
+        aWT[i].hMutex = CPLCreateMutexEx(CPL_MUTEX_REGULAR);
+        if( aWT[i].hMutex == NULL )
+        {
+            nThreads = i;
+            aWT.resize(nThreads);
+            bRet = false;
+            break;
+        }
+        CPLReleaseMutex(aWT[i].hMutex);
+        aWT[i].hCond = CPLCreateCond();
+        if( aWT[i].hCond == NULL )
+        {
+            CPLDestroyMutex(aWT[i].hMutex);
+            nThreads = i;
+            aWT.resize(nThreads);
+            bRet = false;
+            break;
+        }
+
+        aWT[i].bMarkedAsWaiting = FALSE;
+        //aWT[i].psNextJob = NULL;
+
+        aWT[i].hThread = CPLCreateJoinableThread(WorkerThreadFunction, &(aWT[i]));
+        if( aWT[i].hThread == NULL )
+        {
+            nThreads = i;
+            aWT.resize(nThreads);
+            bRet = false;
+            break;
+        }
+    }
+
+    // Wait all threads to be started
+    while( true )
+    {
+        CPLAcquireMutex(hMutex, 1000.0);
+        int nWaitingWorkerThreadsLocal = nWaitingWorkerThreads;
+        if( nWaitingWorkerThreadsLocal < nThreads )
+            CPLCondWait(hCond, hMutex);
+        CPLReleaseMutex(hMutex);
+        if( nWaitingWorkerThreadsLocal == nThreads )
+            break;
+    }
+
+    if( eState == CPLWTS_ERROR )
+        bRet = false;
+
+    return bRet;
+}
+
+/************************************************************************/
+/*                          DeclareJobFinished()                        */
+/************************************************************************/
+
+void CPLWorkerThreadPool::DeclareJobFinished()
+{
+    CPLAcquireMutex(hMutex, 1000.0);
+    nPendingJobs --;
+    CPLCondSignal(hCond);
+    CPLReleaseMutex(hMutex);
+}
+
+/************************************************************************/
+/*                             GetNextJob()                             */
+/************************************************************************/
+
+CPLWorkerThreadJob* CPLWorkerThreadPool::GetNextJob(CPLWorkerThread* psWorkerThread)
+{
+    while(true)
+    {
+        CPLAcquireMutex(hMutex, 1000.0);
+        if( eState == CPLWTS_STOP )
+        {
+            CPLReleaseMutex(hMutex);
+            return NULL;
+        }
+        CPLList* psTopJobIter = psJobQueue;
+        if( psTopJobIter )
+        {
+            psJobQueue = psTopJobIter->psNext;
+
+            //CPLDebug("JOB", "%p got a job", psWorkerThread);
+            CPLWorkerThreadJob* psJob = (CPLWorkerThreadJob*)psTopJobIter->pData;
+            CPLReleaseMutex(hMutex);
+            CPLFree(psTopJobIter);
+            return psJob;
+        }
+
+        if( !psWorkerThread->bMarkedAsWaiting )
+        {
+            psWorkerThread->bMarkedAsWaiting = TRUE;
+            nWaitingWorkerThreads ++;
+            CPLAssert(nWaitingWorkerThreads <= (int)aWT.size());
+
+            CPLList* psItem = (CPLList*) VSI_MALLOC_VERBOSE(sizeof(CPLList));
+            if( psItem == NULL )
+            {
+                eState = CPLWTS_ERROR;
+                CPLCondSignal(hCond);
+
+                CPLReleaseMutex(hMutex);
+                return NULL;
+            }
+
+            psItem->pData = psWorkerThread;
+            psItem->psNext = psWaitingWorkerThreadsList;
+            psWaitingWorkerThreadsList = psItem;
+
+            //CPLAssert( CPLListCount(psWaitingWorkerThreadsList) == nWaitingWorkerThreads);
+        }
+
+        CPLCondSignal(hCond);
+
+        CPLAcquireMutex(psWorkerThread->hMutex, 1000.0);
+        //CPLDebug("JOB", "%p sleeping", psWorkerThread);
+        CPLReleaseMutex(hMutex);
+
+        CPLCondWait( psWorkerThread->hCond, psWorkerThread->hMutex );
+
+        //CPLWorkerThreadJob* psJob = psWorkerThread->psNextJob;
+        //psWorkerThread->psNextJob = NULL;
+
+        CPLReleaseMutex(psWorkerThread->hMutex);
+
+        //if( psJob )
+        //    return psJob;
+    }
+}
diff --git a/port/cpl_worker_thread_pool.h b/port/cpl_worker_thread_pool.h
new file mode 100644
index 0000000..d9a4331
--- /dev/null
+++ b/port/cpl_worker_thread_pool.h
@@ -0,0 +1,103 @@
+/**********************************************************************
+ * $Id: cpl_worker_thread_pool.h 33666 2016-03-07 05:21:07Z goatbar $
+ *
+ * Project:  CPL - Common Portability Library
+ * Purpose:  CPL worker thread pool
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ **********************************************************************
+ * Copyright (c) 2015, Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef CPL_WORKER_THREAD_POOL_H_INCLUDED_
+#define CPL_WORKER_THREAD_POOL_H_INCLUDED_
+
+#include "cpl_multiproc.h"
+#include "cpl_list.h"
+#include <vector>
+
+/**
+ * \file cpl_worker_thread_pool.h
+ *
+ * Class to manage a pool of worker threads.
+ * @since GDAL 2.1
+ */
+
+class CPLWorkerThreadPool;
+
+typedef struct
+{
+    CPLThreadFunc  pfnFunc;
+    void          *pData;
+} CPLWorkerThreadJob;
+
+typedef struct
+{
+    CPLThreadFunc        pfnInitFunc;
+    void                *pInitData;
+    CPLWorkerThreadPool *poTP;
+    CPLJoinableThread   *hThread;
+    int                  bMarkedAsWaiting;
+    //CPLWorkerThreadJob  *psNextJob;
+
+    CPLMutex            *hMutex;
+    CPLCond             *hCond;
+} CPLWorkerThread;
+
+typedef enum
+{
+    CPLWTS_OK,
+    CPLWTS_STOP,
+    CPLWTS_ERROR
+} CPLWorkerThreadState;
+
+class CPL_DLL CPLWorkerThreadPool
+{
+        std::vector<CPLWorkerThread> aWT;
+        CPLCond* hCond;
+        CPLMutex* hMutex;
+        volatile CPLWorkerThreadState eState;
+        CPLList* psJobQueue;
+        volatile int nPendingJobs;
+
+        CPLList* psWaitingWorkerThreadsList;
+        int nWaitingWorkerThreads;
+
+        static void WorkerThreadFunction(void* user_data);
+
+        void DeclareJobFinished();
+        CPLWorkerThreadJob* GetNextJob(CPLWorkerThread* psWorkerThread);
+
+    public:
+        CPLWorkerThreadPool();
+       ~CPLWorkerThreadPool();
+
+        bool Setup(int nThreads,
+                   CPLThreadFunc pfnInitFunc,
+                   void** pasInitData);
+        bool SubmitJob(CPLThreadFunc pfnFunc, void* pData);
+        bool SubmitJobs(CPLThreadFunc pfnFunc, const std::vector<void*>& apData);
+        void WaitCompletion(int nMaxRemainingJobs = 0);
+
+        int GetThreadCount() const { return (int)aWT.size(); }
+};
+
+#endif // CPL_WORKER_THREAD_POOL_H_INCLUDED_
diff --git a/port/cpl_xml_validate.cpp b/port/cpl_xml_validate.cpp
index 6cba8a9..8d4fa52 100644
--- a/port/cpl_xml_validate.cpp
+++ b/port/cpl_xml_validate.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_xml_validate.cpp 27755 2014-09-28 16:51:08Z goatbar $
+ * $Id: cpl_xml_validate.cpp 32883 2016-01-09 18:24:40Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement XML validation against XSD schema
@@ -29,7 +29,7 @@
 
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: cpl_xml_validate.cpp 27755 2014-09-28 16:51:08Z goatbar $");
+CPL_CVSID("$Id: cpl_xml_validate.cpp 32883 2016-01-09 18:24:40Z rouault $");
 
 #ifdef HAVE_LIBXML2
 #include <libxml/xmlversion.h>
@@ -78,7 +78,7 @@ static void CPLFixPath(char* pszPath)
             pszPath[i] = '/';
     }
 
-    while(TRUE)
+    while(true)
     {
         char* pszSlashDotDot = strstr(pszPath, "/../");
         if (pszSlashDotDot == NULL || pszSlashDotDot == pszPath)
@@ -101,7 +101,8 @@ static int bHasLibXMLBug = -1;
 /*                  CPLHasLibXMLBugWarningCallback()                    */
 /************************************************************************/
 
-static void CPLHasLibXMLBugWarningCallback (void * ctx, const char * msg, ...)
+static void CPLHasLibXMLBugWarningCallback (void * /*ctx*/,
+                                            const char* /*msg*/, ...)
 {
 }
 
@@ -109,10 +110,10 @@ static void CPLHasLibXMLBugWarningCallback (void * ctx, const char * msg, ...)
 /*                          CPLHasLibXMLBug()                           */
 /************************************************************************/
 
-static int CPLHasLibXMLBug()
+static bool CPLHasLibXMLBug()
 {
     if (bHasLibXMLBug >= 0)
-        return bHasLibXMLBug;
+        return CPL_TO_BOOL(bHasLibXMLBug);
 
     static const char szLibXMLBugTester[] =
     "<schema targetNamespace=\"http://foo\" xmlns:foo=\"http://foo\" xmlns=\"http://www.w3.org/2001/XMLSchema\">"
@@ -158,7 +159,7 @@ static int CPLHasLibXMLBug()
                  "Will try to workaround for GML schemas.");
     }
 
-    return bHasLibXMLBug;
+    return CPL_TO_BOOL(bHasLibXMLBug);
 }
 
 #endif
@@ -197,7 +198,7 @@ static CPLXMLNode* CPLExtractSubSchema(CPLXMLNode* psSubXML, CPLXMLNode* psMainS
         {
             /* Add xmlns: from subschema to main schema if missing */
             if (psNext->eType == CXT_Attribute &&
-                strncmp(psNext->pszValue, "xmlns:", 6) == 0 &&
+                STARTS_WITH(psNext->pszValue, "xmlns:") &&
                 CPLGetXMLValue(psMainSchema, psNext->pszValue, NULL) == NULL)
             {
                 CPLXMLNode* psAttr = CPLCreateXMLNode(NULL, CXT_Attribute, psNext->pszValue);
@@ -228,7 +229,7 @@ static CPLXMLNode* CPLExtractSubSchema(CPLXMLNode* psSubXML, CPLXMLNode* psMainS
 /************************************************************************/
 
 /* Return TRUE if the current node must be destroyed */
-static int CPLWorkaroundLibXMLBug(CPLXMLNode* psIter)
+static bool CPLWorkaroundLibXMLBug(CPLXMLNode* psIter)
 {
     if (psIter->eType == CXT_Element &&
         strcmp(psIter->pszValue, "element") == 0 &&
@@ -276,7 +277,7 @@ static int CPLWorkaroundLibXMLBug(CPLXMLNode* psIter)
               strcmp(CPLGetXMLValue(psIter, "name", ""), "CategoryExtentType") == 0))
     {
         /* Destroy this element */
-        return TRUE;
+        return true;
     }
 
     /* For GML 3.2.1 */
@@ -324,7 +325,7 @@ static int CPLWorkaroundLibXMLBug(CPLXMLNode* psIter)
         psIter->psChild->psNext = psComplexType;
     }
 
-    return FALSE;
+    return false;
 }
 #endif
 
@@ -336,11 +337,6 @@ static
 CPLXMLNode* CPLLoadSchemaStrInternal(CPLHashSet* hSetSchemas,
                                      const char* pszFile)
 {
-    CPLXMLNode* psXML;
-    CPLXMLNode* psSchema;
-    CPLXMLNode* psPrev;
-    CPLXMLNode* psIter;
-
     if (CPLHashSetLookup(hSetSchemas, pszFile))
         return NULL;
 
@@ -348,7 +344,7 @@ CPLXMLNode* CPLLoadSchemaStrInternal(CPLHashSet* hSetSchemas,
 
     CPLDebug("CPL", "Parsing %s", pszFile);
 
-    psXML = CPLParseXMLFile(pszFile);
+    CPLXMLNode* psXML = CPLParseXMLFile(pszFile);
     if (psXML == NULL)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -356,7 +352,7 @@ CPLXMLNode* CPLLoadSchemaStrInternal(CPLHashSet* hSetSchemas,
         return NULL;
     }
 
-    psSchema = CPLGetXMLNode(psXML, "=schema");
+    CPLXMLNode* psSchema = CPLGetXMLNode(psXML, "=schema");
     if (psSchema == NULL)
         psSchema = CPLGetXMLNode(psXML, "=xs:schema");
     if (psSchema == NULL)
@@ -369,11 +365,11 @@ CPLXMLNode* CPLLoadSchemaStrInternal(CPLHashSet* hSetSchemas,
         return NULL;
     }
 
-    psPrev = NULL;
-    psIter = psSchema->psChild;
+    CPLXMLNode* psPrev = NULL;
+    CPLXMLNode* psIter = psSchema->psChild;
     while(psIter)
     {
-        int bDestroyCurrentNode = FALSE;
+        bool bDestroyCurrentNode = false;
 
 #ifdef HAS_VALIDATION_BUG
         if (bHasLibXMLBug)
@@ -444,7 +440,7 @@ CPLXMLNode* CPLLoadSchemaStrInternal(CPLHashSet* hSetSchemas,
             {
                 /* We have already included that file, */
                 /* so just remove the <include/> node */
-                bDestroyCurrentNode = TRUE;
+                bDestroyCurrentNode = true;
             }
         }
 
@@ -460,8 +456,8 @@ CPLXMLNode* CPLLoadSchemaStrInternal(CPLHashSet* hSetSchemas,
                 if (psIter2->eType == CXT_Attribute &&
                     strcmp(psIter2->pszValue, "schemaLocation") == 0 &&
                     psIter2->psChild != NULL &&
-                    strncmp(psIter2->psChild->pszValue, "http://", 7) != 0 &&
-                    strncmp(psIter2->psChild->pszValue, "ftp://", 6) != 0 &&
+                    !STARTS_WITH(psIter2->psChild->pszValue, "http://") &&
+                    !STARTS_WITH(psIter2->psChild->pszValue, "ftp://") &&
                     /* If the top file is our warping file, don't alter the path of the import */
                     strstr(pszFile, "/vsimem/CPLValidateXML_") == NULL )
                 {
@@ -504,11 +500,7 @@ CPLXMLNode* CPLLoadSchemaStrInternal(CPLHashSet* hSetSchemas,
 static
 void CPLMoveImportAtBeginning(CPLXMLNode* psXML)
 {
-    CPLXMLNode* psIter;
-    CPLXMLNode* psPrev;
-    CPLXMLNode* psSchema;
-
-    psSchema = CPLGetXMLNode(psXML, "=schema");
+    CPLXMLNode* psSchema = CPLGetXMLNode(psXML, "=schema");
     if (psSchema == NULL)
         psSchema = CPLGetXMLNode(psXML, "=xs:schema");
     if (psSchema == NULL)
@@ -516,8 +508,8 @@ void CPLMoveImportAtBeginning(CPLXMLNode* psXML)
     if (psSchema == NULL)
         return;
 
-    psPrev = NULL;
-    psIter = psSchema->psChild;
+    CPLXMLNode* psPrev = NULL;
+    CPLXMLNode* psIter = psSchema->psChild;
     while(psIter)
     {
         if (psPrev != NULL && psIter->eType == CXT_Element &&
@@ -550,8 +542,6 @@ void CPLMoveImportAtBeginning(CPLXMLNode* psXML)
 static
 char* CPLLoadSchemaStr(const char* pszXSDFilename)
 {
-    char* pszStr = NULL;
-
 #ifdef HAS_VALIDATION_BUG
     CPLHasLibXMLBug();
 #endif
@@ -560,6 +550,8 @@ char* CPLLoadSchemaStr(const char* pszXSDFilename)
         CPLHashSetNew(CPLHashSetHashStr, CPLHashSetEqualStr, CPLFree);
     CPLXMLNode* psSchema =
         CPLLoadSchemaStrInternal(hSetSchemas, pszXSDFilename);
+
+    char* pszStr = NULL;
     if (psSchema)
     {
         CPLMoveImportAtBeginning(psSchema);
@@ -585,10 +577,9 @@ static void CPLLibXMLInputStreamCPLFree(xmlChar* pszBuffer)
 
 static CPLString CPLFindLocalXSD(const char* pszXSDFilename)
 {
-    const char *pszSchemasOpenGIS;
     CPLString osTmp;
-
-    pszSchemasOpenGIS = CPLGetConfigOption("GDAL_OPENGIS_SCHEMAS", NULL);
+    const char *pszSchemasOpenGIS
+        = CPLGetConfigOption("GDAL_OPENGIS_SCHEMAS", NULL);
     if (pszSchemasOpenGIS != NULL)
     {
         int nLen = (int)strlen(pszSchemasOpenGIS);
@@ -681,7 +672,7 @@ xmlParserInputPtr CPLExternalEntityLoader (const char * URL,
 {
     //CPLDebug("CPL", "CPLExternalEntityLoader(%s)", URL);
     CPLString osURL;
-    
+
     /* Use libxml2 catalog mechanism to resolve the URL to something else */
     xmlChar* pszResolved = xmlCatalogResolveSystem((const xmlChar*)URL);
     if (pszResolved == NULL)
@@ -695,7 +686,7 @@ xmlParserInputPtr CPLExternalEntityLoader (const char * URL,
         pszResolved = NULL;
     }
 
-    if (strncmp(URL, "http://", 7) == 0)
+    if (STARTS_WITH(URL, "http://"))
     {
         /* Make sure to use http://schemas.opengis.net/ */
         /* when gml/2 or gml/3 is detected */
@@ -736,21 +727,19 @@ xmlParserInputPtr CPLExternalEntityLoader (const char * URL,
                 return xmlNewStringInputStream(context, (const xmlChar*) szXLINK_XSD);
             }
         }
-        else if (strncmp(URL, "http://schemas.opengis.net/",
-                         strlen("http://schemas.opengis.net/")) != 0)
-        {
+        else if (!STARTS_WITH(URL, "http://schemas.opengis.net/"))        {
             CPLDebug("CPL", "Loading %s", URL);
             return pfnLibXMLOldExtranerEntityLoader(URL, ID, context);
         }
     }
-    else if (strncmp(URL, "ftp://", 6) == 0)
+    else if (STARTS_WITH(URL, "ftp://"))
     {
         return pfnLibXMLOldExtranerEntityLoader(URL, ID, context);
     }
-    else if (strncmp(URL, "file://", 7) == 0)
+    else if (STARTS_WITH(URL, "file://"))
     {
         /* Parse file:// URI so as to be able to open them with VSI*L API */
-        if (strncmp(URL, "file://localhost/", 17) == 0)
+        if (STARTS_WITH(URL, "file://localhost/"))
             URL += 16;
         else
             URL += 7;
@@ -763,21 +752,15 @@ xmlParserInputPtr CPLExternalEntityLoader (const char * URL,
     }
 
     CPLString osModURL;
-    if (strncmp(URL, "/vsizip/vsicurl/http%3A//",
-                strlen("/vsizip/vsicurl/http%3A//")) == 0)
-    {
+    if (STARTS_WITH(URL, "/vsizip/vsicurl/http%3A//"))    {
         osModURL = "/vsizip/vsicurl/http://";
         osModURL += URL + strlen("/vsizip/vsicurl/http%3A//");
     }
-    else if (strncmp(URL, "/vsicurl/http%3A//",
-                     strlen("/vsicurl/http%3A//")) == 0)
-    {
+    else if (STARTS_WITH(URL, "/vsicurl/http%3A//"))    {
         osModURL = "vsicurl/http://";
         osModURL += URL + strlen("/vsicurl/http%3A//");
     }
-    else if (strncmp(URL, "http://schemas.opengis.net/",
-                     strlen("http://schemas.opengis.net/")) == 0)
-    {
+    else if (STARTS_WITH(URL, "http://schemas.opengis.net/"))    {
         const char *pszAfterOpenGIS =
                 URL + strlen("http://schemas.opengis.net/");
 
@@ -840,10 +823,9 @@ xmlParserInputPtr CPLExternalEntityLoader (const char * URL,
 static void CPLLibXMLWarningErrorCallback (void * ctx, const char * msg, ...)
 {
     va_list varg;
-    char * pszStr;
-
     va_start(varg, msg);
-    pszStr = (char *)va_arg( varg, char *);
+
+    char *pszStr = (char *)va_arg( varg, char *);
 
     if (strstr(pszStr, "since this namespace was already imported") == NULL)
     {
@@ -880,24 +862,37 @@ char* CPLLoadContentFromFile(const char* pszFilename)
     if (fp == NULL)
         return NULL;
     vsi_l_offset nSize;
-    VSIFSeekL(fp, 0, SEEK_END);
+    if( VSIFSeekL(fp, 0, SEEK_END) != 0 )
+    {
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
+        return NULL;
+    }
     nSize = VSIFTellL(fp);
-    VSIFSeekL(fp, 0, SEEK_SET);
+    if( VSIFSeekL(fp, 0, SEEK_SET) != 0 )
+    {
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
+        return NULL;
+    }
     if ((vsi_l_offset)(int)nSize != nSize ||
         nSize > INT_MAX - 1 )
     {
-        VSIFCloseL(fp);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
         return NULL;
     }
-    char* pszBuffer = (char*)VSIMalloc(nSize + 1);
+    char* pszBuffer = (char*)VSIMalloc((size_t)nSize + 1);
     if (pszBuffer == NULL)
     {
-        VSIFCloseL(fp);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
+        return NULL;
+    }
+    if( (size_t)VSIFReadL(pszBuffer, 1, (size_t)nSize, fp) != (size_t)nSize )
+    {
+        VSIFree(pszBuffer);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
         return NULL;
     }
-    VSIFReadL(pszBuffer, 1, nSize, fp);
     pszBuffer[nSize] = '\0';
-    VSIFCloseL(fp);
+    CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
     return pszBuffer;
 }
 
@@ -931,7 +926,7 @@ CPLXMLSchemaPtr CPLLoadXMLSchema(const char* pszXSDFilename)
     xmlSetExternalEntityLoader(CPLExternalEntityLoader);
 
     xmlSchemaParserCtxtPtr pSchemaParserCtxt =
-                            xmlSchemaNewMemParserCtxt(pszStr, strlen(pszStr));
+                            xmlSchemaNewMemParserCtxt(pszStr, static_cast<int>(strlen(pszStr)));
 
     xmlSchemaSetParserErrors(pSchemaParserCtxt,
                              CPLLibXMLWarningErrorCallback,
@@ -1005,7 +1000,7 @@ int CPLValidateXML(const char* pszXMLFilename,
         }
         int nRead = (int)VSIFReadL(szHeader, 1, sizeof(szHeader)-1, fpXML);
         szHeader[nRead] = '\0';
-        VSIFCloseL(fpXML);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpXML));
     }
 
     /* Workaround following bug : "element FeatureCollection: Schemas validity error : Element '{http://www.opengis.net/wfs}FeatureCollection': No matching global declaration available for the validation root" */
@@ -1040,7 +1035,7 @@ int CPLValidateXML(const char* pszXMLFilename,
         }
         int nRead = (int)VSIFReadL(szHeader, 1, sizeof(szHeader)-1, fpXSD);
         szHeader[nRead] = '\0';
-        VSIFCloseL(fpXSD);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpXSD));
 
         if (strstr(szHeader, "gml/3.1.1") != NULL &&
             strstr(szHeader, "gml/3.1.1/base/gml.xsd") == NULL)
@@ -1053,13 +1048,13 @@ int CPLValidateXML(const char* pszXMLFilename,
             osTmpXSDFilename = CPLSPrintf("/vsimem/CPLValidateXML_%p_%p.xsd", pszXMLFilename, pszXSDFilename);
             char* pszEscapedXSDFilename = CPLEscapeString(pszXSDFilename, -1, CPLES_XML);
             VSILFILE* fpMEM = VSIFOpenL(osTmpXSDFilename, "wb");
-            VSIFPrintfL(fpMEM, "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n");
-            VSIFPrintfL(fpMEM, "   <xs:import namespace=\"%s\" schemaLocation=\"%s\"/>\n", pszWFSSchemaNamespace, pszWFSSchemaLocation);
-            VSIFPrintfL(fpMEM, "   <xs:import namespace=\"ignored\" schemaLocation=\"%s\"/>\n", pszEscapedXSDFilename);
+            CPL_IGNORE_RET_VAL(VSIFPrintfL(fpMEM, "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n"));
+            CPL_IGNORE_RET_VAL(VSIFPrintfL(fpMEM, "   <xs:import namespace=\"%s\" schemaLocation=\"%s\"/>\n", pszWFSSchemaNamespace, pszWFSSchemaLocation));
+            CPL_IGNORE_RET_VAL(VSIFPrintfL(fpMEM, "   <xs:import namespace=\"ignored\" schemaLocation=\"%s\"/>\n", pszEscapedXSDFilename));
             if (pszGMLSchemaLocation)
-                VSIFPrintfL(fpMEM, "   <xs:import namespace=\"http://www.opengis.net/gml\" schemaLocation=\"%s\"/>\n", pszGMLSchemaLocation);
-            VSIFPrintfL(fpMEM, "</xs:schema>\n");
-            VSIFCloseL(fpMEM);
+                CPL_IGNORE_RET_VAL(VSIFPrintfL(fpMEM, "   <xs:import namespace=\"http://www.opengis.net/gml\" schemaLocation=\"%s\"/>\n", pszGMLSchemaLocation));
+            CPL_IGNORE_RET_VAL(VSIFPrintfL(fpMEM, "</xs:schema>\n"));
+            CPL_IGNORE_RET_VAL(VSIFCloseL(fpMEM));
             CPLFree(pszEscapedXSDFilename);
         }
     }
@@ -1085,7 +1080,7 @@ int CPLValidateXML(const char* pszXMLFilename,
                             CPLLibXMLWarningErrorCallback,
                             (void*) pszXMLFilename);
 
-    int bValid = FALSE;
+    bool bValid = false;
     if( pszXMLFilename[0] == '<' )
     {
         xmlDocPtr pDoc = xmlParseDoc((const xmlChar *)pszXMLFilename);
@@ -1095,7 +1090,7 @@ int CPLValidateXML(const char* pszXMLFilename,
         }
         xmlFreeDoc(pDoc);
     }
-    else if (strncmp(pszXMLFilename, "/vsi", 4) != 0)
+    else if (!STARTS_WITH(pszXMLFilename, "/vsi"))
     {
         bValid =
             xmlSchemaValidateFile(pSchemaValidCtxt, pszXMLFilename, 0) == 0;
diff --git a/port/cplgetsymbol.cpp b/port/cplgetsymbol.cpp
index bb9c749..f30efac 100644
--- a/port/cplgetsymbol.cpp
+++ b/port/cplgetsymbol.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cplgetsymbol.cpp 27460 2014-06-18 12:36:06Z rouault $
+ * $Id: cplgetsymbol.cpp 33646 2016-03-05 15:54:03Z goatbar $
  *
  * Project:  Common Portability Library
  * Purpose:  Fetch a function pointer from a shared library / DLL.
@@ -30,7 +30,7 @@
 
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: cplgetsymbol.cpp 27460 2014-06-18 12:36:06Z rouault $");
+CPL_CVSID("$Id: cplgetsymbol.cpp 33646 2016-03-05 15:54:03Z goatbar $");
 
 
 /* ==================================================================== */
@@ -63,14 +63,14 @@ CPL_CVSID("$Id: cplgetsymbol.cpp 27460 2014-06-18 12:36:06Z rouault $");
  * Currently CPLGetSymbol() doesn't try to:
  * <ul>
  *  <li> prevent the reference count on the library from going up
- *    for every request, or given any opportunity to unload      
- *    the library.                                            
- *  <li> Attempt to look for the library in non-standard         
- *    locations.                                              
- *  <li> Attempt to try variations on the symbol name, like      
- *    pre-prending or post-pending an underscore.
+ *    for every request, or given any opportunity to unload
+ *    the library.
+ *  <li> Attempt to look for the library in non-standard
+ *    locations.
+ *  <li> Attempt to try variations on the symbol name, like
+ *    pre-pending or post-pending an underscore.
  * </ul>
- * 
+ *
  * Some of these issues may be worked on in the future.
  *
  * @param pszLibrary the name of the shared library or DLL containing
@@ -100,13 +100,12 @@ void *CPLGetSymbol( const char * pszLibrary, const char * pszSymbolName )
 #if (defined(__APPLE__) && defined(__MACH__))
     /* On mach-o systems, C symbols have a leading underscore and depending
      * on how dlcompat is configured it may or may not add the leading
-     * underscore.  So if dlsym() fails add an underscore and try again.
+     * underscore.  If dlsym() fails, add an underscore and try again.
      */
     if( pSymbol == NULL )
     {
-        char withUnder[strlen(pszSymbolName) + 2];
-        withUnder[0] = '_'; withUnder[1] = 0;
-        strcat(withUnder, pszSymbolName);
+        char withUnder[256];
+        snprintf(withUnder, sizeof(withUnder), "_%s", pszSymbolName);
         pSymbol = dlsym( pLibrary, withUnder );
     }
 #endif
@@ -115,9 +114,12 @@ void *CPLGetSymbol( const char * pszLibrary, const char * pszSymbolName )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", dlerror() );
+        // Do not call dlclose here.  misc.py:misc_6() demonstrates the crash.
+        // coverity[leaked_storage]
         return NULL;
     }
-    
+
+    // coverity[leaked_storage]  It is not safe to call dlclose.
     return( pSymbol );
 }
 
@@ -126,7 +128,7 @@ void *CPLGetSymbol( const char * pszLibrary, const char * pszSymbolName )
 /* ==================================================================== */
 /*                 Windows Implementation                               */
 /* ==================================================================== */
-#if defined(WIN32) && !defined(WIN32CE)
+#if defined(WIN32)
 
 #define GOT_GETSYMBOL
 
@@ -156,15 +158,15 @@ void *CPLGetSymbol( const char * pszLibrary, const char * pszSymbolName )
         /* Restore old error mode */
         SetErrorMode(uOldErrorMode);
 
-        FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER 
+        FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER
                        | FORMAT_MESSAGE_FROM_SYSTEM
                        | FORMAT_MESSAGE_IGNORE_INSERTS,
                        NULL, nLastError,
-                       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
+                       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                        (LPTSTR) &lpMsgBuf, 0, NULL );
- 
+
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Can't load requested DLL: %s\n%d: %s", 
+                  "Can't load requested DLL: %s\n%d: %s",
                   pszLibrary, nLastError, (const char *) lpMsgBuf );
         return NULL;
     }
@@ -180,52 +182,11 @@ void *CPLGetSymbol( const char * pszLibrary, const char * pszSymbolName )
                   "Can't find requested entry point: %s\n", pszSymbolName );
         return NULL;
     }
-    
-    return( pSymbol );
-}
-
-#endif /* def _WIN32 */
-
-/* ==================================================================== */
-/*                 Windows CE Implementation                               */
-/* ==================================================================== */
-#if defined(WIN32CE)
-
-#define GOT_GETSYMBOL
-
-#include "cpl_win32ce_api.h"
-
-/************************************************************************/
-/*                            CPLGetSymbol()                            */
-/************************************************************************/
-
-void *CPLGetSymbol( const char * pszLibrary, const char * pszSymbolName )
 
-{
-    void        *pLibrary;
-    void        *pSymbol;
-
-    pLibrary = CE_LoadLibraryA(pszLibrary);
-    if( pLibrary == NULL )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Can't load requested DLL: %s", pszLibrary );
-        return NULL;
-    }
-
-    pSymbol = (void *) CE_GetProcAddressA( (HINSTANCE) pLibrary, pszSymbolName );
-
-    if( pSymbol == NULL )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Can't find requested entry point: %s\n", pszSymbolName );
-        return NULL;
-    }
-    
     return( pSymbol );
 }
 
-#endif /* def WIN32CE */
+#endif /* def _WIN32 */
 
 /* ==================================================================== */
 /*      Dummy implementation.                                           */
@@ -242,7 +203,7 @@ void *CPLGetSymbol( const char * pszLibrary, const char * pszSymbolName )
 void *CPLGetSymbol(const char *pszLibrary, const char *pszEntryPoint)
 
 {
-    CPLDebug( "CPL", 
+    CPLDebug( "CPL",
               "CPLGetSymbol(%s,%s) called.  Failed as this is stub"
               " implementation.", pszLibrary, pszEntryPoint );
     return NULL;
diff --git a/port/cplkeywordparser.cpp b/port/cplkeywordparser.cpp
index 6a934c8..743c21c 100644
--- a/port/cplkeywordparser.cpp
+++ b/port/cplkeywordparser.cpp
@@ -1,17 +1,17 @@
 /******************************************************************************
- * $Id: cplkeywordparser.cpp 29123 2015-05-03 11:05:46Z bishop $
+ * $Id: cplkeywordparser.cpp 33646 2016-03-05 15:54:03Z goatbar $
  *
  * Project:  Common Portability Library
  * Purpose:  Implementation of CPLKeywordParser - a class for parsing
  *           the keyword format used for files like QuickBird .RPB files.
  *           This is a slight variation on the NASAKeywordParser used for
- *           the PDS/ISIS2/ISIS3 formats. 
+ *           the PDS/ISIS2/ISIS3 formats.
  * Author:   Frank Warmerdam <warmerdam at pobox.com
  *
  ******************************************************************************
  * Copyright (c) 2008, Frank Warmerdam <warmerdam at pobox.com>
  * Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * to deal in the Software without restriction, including without limitation
@@ -31,7 +31,7 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_string.h" 
+#include "cpl_string.h"
 #include "cplkeywordparser.h"
 
 CPL_CVSID("$Id");
@@ -46,11 +46,9 @@ CPL_CVSID("$Id");
 /*                         CPLKeywordParser()                          */
 /************************************************************************/
 
-CPLKeywordParser::CPLKeywordParser()
-
-{
-    papszKeywordList = NULL;
-}
+CPLKeywordParser::CPLKeywordParser() :
+    papszKeywordList(NULL), pszHeaderNext(NULL)
+{ }
 
 /************************************************************************/
 /*                        ~CPLKeywordParser()                          */
@@ -73,12 +71,10 @@ int CPLKeywordParser::Ingest( VSILFILE *fp )
 /* -------------------------------------------------------------------- */
 /*      Read in buffer till we find END all on it's own line.           */
 /* -------------------------------------------------------------------- */
-    for( ; TRUE; ) 
+    for( ; true; )
     {
-        const char *pszCheck;
         char szChunk[513];
-
-        int nBytesRead = VSIFReadL( szChunk, 1, 512, fp );
+        const size_t nBytesRead = VSIFReadL( szChunk, 1, 512, fp );
 
         szChunk[nBytesRead] = '\0';
         osHeaderText += szChunk;
@@ -86,12 +82,13 @@ int CPLKeywordParser::Ingest( VSILFILE *fp )
         if( nBytesRead < 512 )
             break;
 
+        const char *pszCheck;
         if( osHeaderText.size() > 520 )
             pszCheck = osHeaderText.c_str() + (osHeaderText.size() - 520);
         else
             pszCheck = szChunk;
 
-        if( strstr(pszCheck,"\r\nEND;\r\n") != NULL 
+        if( strstr(pszCheck,"\r\nEND;\r\n") != NULL
             || strstr(pszCheck,"\nEND;\n") != NULL )
             break;
     }
@@ -113,7 +110,7 @@ int CPLKeywordParser::ReadGroup( const char *pszPathPrefix )
 {
     CPLString osName, osValue;
 
-    for( ; TRUE; )
+    for( ; true; )
     {
         if( !ReadPair( osName, osValue ) )
             return FALSE;
@@ -123,14 +120,14 @@ int CPLKeywordParser::ReadGroup( const char *pszPathPrefix )
             if( !ReadGroup( (CPLString(pszPathPrefix) + osValue + ".").c_str() ) )
                 return FALSE;
         }
-        else if( EQUALN(osName,"END",3) )
+        else if( STARTS_WITH_CI(osName, "END") )
         {
             return TRUE;
         }
         else
         {
             osName = pszPathPrefix + osName;
-            papszKeywordList = CSLSetNameValue( papszKeywordList, 
+            papszKeywordList = CSLSetNameValue( papszKeywordList,
                                                 osName, osValue );
         }
     }
@@ -159,17 +156,17 @@ int CPLKeywordParser::ReadPair( CPLString &osName, CPLString &osValue )
 
     if( *pszHeaderNext != '=' )
     {
-        // ISIS3 does not have anything after the end group/object keyword. 
+        // ISIS3 does not have anything after the end group/object keyword.
         if( EQUAL(osName,"End_Group") || EQUAL(osName,"End_Object") )
             return TRUE;
         else
             return FALSE;
     }
-    
+
     pszHeaderNext++;
-    
+
     SkipWhite();
-    
+
     osValue = "";
 
     // Handle value lists like:     Name   = (Red, Red)
@@ -187,7 +184,7 @@ int CPLKeywordParser::ReadPair( CPLString &osName, CPLString &osValue )
 
             osValue += osWord;
             const char* pszIter = osWord.c_str();
-            int bInQuote = FALSE;
+            bool bInQuote = false;
             while(*pszIter != '\0')
             {
                 if (*pszIter == '"')
@@ -210,35 +207,35 @@ int CPLKeywordParser::ReadPair( CPLString &osName, CPLString &osValue )
         }
     }
 
-    else // Handle more normal "single word" values. 
+    else // Handle more normal "single word" values.
     {
         if( !ReadWord( osValue ) )
             return FALSE;
 
     }
-        
+
     SkipWhite();
 
-    // No units keyword?   
+    // No units keyword?
     if( *pszHeaderNext != '<' )
         return TRUE;
 
     // Append units keyword.  For lines that like like this:
     //  MAP_RESOLUTION               = 4.0 <PIXEL/DEGREE>
-    
+
     CPLString osWord;
-    
+
     osValue += " ";
-    
+
     while( ReadWord( osWord ) )
     {
         SkipWhite();
-        
+
         osValue += osWord;
         if( osWord[strlen(osWord)-1] == '>' )
             break;
     }
-    
+
     return TRUE;
 }
 
@@ -256,8 +253,8 @@ int CPLKeywordParser::ReadWord( CPLString &osWord )
     if( *pszHeaderNext == '\0' )
         return FALSE;
 
-    while( *pszHeaderNext != '\0' 
-           && *pszHeaderNext != '=' 
+    while( *pszHeaderNext != '\0'
+           && *pszHeaderNext != '='
            && *pszHeaderNext != ';'
            && !isspace((unsigned char)*pszHeaderNext) )
     {
@@ -294,7 +291,7 @@ int CPLKeywordParser::ReadWord( CPLString &osWord )
 
     if( *pszHeaderNext == ';' )
         pszHeaderNext++;
-    
+
     return TRUE;
 }
 
@@ -305,22 +302,22 @@ int CPLKeywordParser::ReadWord( CPLString &osWord )
 void CPLKeywordParser::SkipWhite()
 
 {
-    for( ; TRUE; )
+    for( ; true; )
     {
         // Skip white space (newline, space, tab, etc )
         if( isspace( (unsigned char)*pszHeaderNext ) )
         {
-            pszHeaderNext++; 
+            pszHeaderNext++;
             continue;
         }
-        
-        // Skip C style comments 
+
+        // Skip C style comments
         if( *pszHeaderNext == '/' && pszHeaderNext[1] == '*' )
         {
             pszHeaderNext += 2;
-            
-            while( *pszHeaderNext != '\0' 
-                   && (*pszHeaderNext != '*' 
+
+            while( *pszHeaderNext != '\0'
+                   && (*pszHeaderNext != '*'
                        || pszHeaderNext[1] != '/' ) )
             {
                 pszHeaderNext++;
@@ -330,13 +327,13 @@ void CPLKeywordParser::SkipWhite()
             continue;
         }
 
-        // Skip # style comments 
+        // Skip # style comments
         if( *pszHeaderNext == '#'  )
         {
             pszHeaderNext += 1;
 
             // consume till end of line.
-            while( *pszHeaderNext != '\0' 
+            while( *pszHeaderNext != '\0'
                    && *pszHeaderNext != 10
                    && *pszHeaderNext != 13 )
             {
@@ -345,7 +342,7 @@ void CPLKeywordParser::SkipWhite()
             continue;
         }
 
-        // not white space, return. 
+        // not white space, return.
         return;
     }
 }
@@ -358,11 +355,9 @@ const char *CPLKeywordParser::GetKeyword( const char *pszPath,
                                             const char *pszDefault )
 
 {
-    const char *pszResult;
-
-    pszResult = CSLFetchNameValue( papszKeywordList, pszPath );
+    const char *pszResult = CSLFetchNameValue( papszKeywordList, pszPath );
     if( pszResult == NULL )
         return pszDefault;
-    else
-        return pszResult;
+
+    return pszResult;
 }
diff --git a/port/cplkeywordparser.h b/port/cplkeywordparser.h
index 050807d..70f0013 100644
--- a/port/cplkeywordparser.h
+++ b/port/cplkeywordparser.h
@@ -1,16 +1,16 @@
 /******************************************************************************
- * $Id: cplkeywordparser.h 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: cplkeywordparser.h 33666 2016-03-07 05:21:07Z goatbar $
  *
  * Project:  Common Portability Library
  * Purpose:  Implementation of CPLKeywordParser - a class for parsing
  *           the keyword format used for files like QuickBird .RPB files.
  *           This is a slight variation on the NASAKeywordParser used for
- *           the PDS/ISIS2/ISIS3 formats. 
+ *           the PDS/ISIS2/ISIS3 formats.
  * Author:   Frank Warmerdam <warmerdam at pobox.com
  *
  ******************************************************************************
  * Copyright (c) 2008, Frank Warmerdam <warmerdam at pobox.com>
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * to deal in the Software without restriction, including without limitation
diff --git a/port/cplstring.cpp b/port/cplstring.cpp
index 564ead8..4097f0a 100644
--- a/port/cplstring.cpp
+++ b/port/cplstring.cpp
@@ -1,7 +1,7 @@
 /******************************************************************************
- * $Id: cplstring.cpp 28204 2014-12-24 06:00:26Z goatbar $
+ * $Id: cplstring.cpp 33646 2016-03-05 15:54:03Z goatbar $
  *
- * Project:  GDAL 
+ * Project:  GDAL
  * Purpose:  CPLString implementation.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -31,12 +31,12 @@
 #include "cpl_string.h"
 #include <string>
 
-CPL_CVSID("$Id: cplstring.cpp 28204 2014-12-24 06:00:26Z goatbar $");
+CPL_CVSID("$Id: cplstring.cpp 33646 2016-03-05 15:54:03Z goatbar $");
 
 /*
- * The CPLString class is derived from std::string, so the vast majority 
+ * The CPLString class is derived from std::string, so the vast majority
  * of the implementation comes from that.  This module is just the extensions
- * we add. 
+ * we add.
  */
 
 /************************************************************************/
@@ -82,8 +82,6 @@ CPLString &CPLString::vPrintf( const char *pszFormat, va_list args )
 /*      result.                                                         */
 /* -------------------------------------------------------------------- */
 #else
-    char szModestBuffer[500];
-    int nPR;
     va_list wrk_args;
 
 #ifdef va_copy
@@ -91,13 +89,16 @@ CPLString &CPLString::vPrintf( const char *pszFormat, va_list args )
 #else
     wrk_args = args;
 #endif
-    
-    nPR = CPLvsnprintf( szModestBuffer, sizeof(szModestBuffer), pszFormat, 
-                     wrk_args );
+
+    char szModestBuffer[500];
+    szModestBuffer[0] = '\0';
+    int nPR = CPLvsnprintf( szModestBuffer, sizeof(szModestBuffer), pszFormat,
+                             wrk_args );
     if( nPR == -1 || nPR >= (int) sizeof(szModestBuffer)-1 )
     {
         int nWorkBufferSize = 2000;
-        char *pszWorkBuffer = (char *) CPLMalloc(nWorkBufferSize);
+        char *pszWorkBuffer = reinterpret_cast<char *>(
+            CPLMalloc(nWorkBufferSize));
 
 #ifdef va_copy
         va_end( wrk_args );
@@ -106,11 +107,11 @@ CPLString &CPLString::vPrintf( const char *pszFormat, va_list args )
         wrk_args = args;
 #endif
         while( (nPR=CPLvsnprintf( pszWorkBuffer, nWorkBufferSize, pszFormat,wrk_args))
-               >= nWorkBufferSize-1 
+               >= nWorkBufferSize-1
                || nPR == -1 )
         {
             nWorkBufferSize *= 4;
-            pszWorkBuffer = (char *) CPLRealloc(pszWorkBuffer, 
+            pszWorkBuffer = (char *) CPLRealloc(pszWorkBuffer,
                                                 nWorkBufferSize );
 #ifdef va_copy
             va_end( wrk_args );
@@ -141,16 +142,16 @@ CPLString &CPLString::vPrintf( const char *pszFormat, va_list args )
 
 /**
  * Format double in C locale.
- * 
- * The passed value is formatted using the C locale (period as decimal 
- * seperator) and appended to the target CPLString. 
  *
- * @param dfValue the value to format. 
+ * The passed value is formatted using the C locale (period as decimal
+ * separator) and appended to the target CPLString.
+ *
+ * @param dfValue the value to format.
  * @param pszFormat the sprintf() style format to use or omit for default.
- * Note that this format string should only include one substitution argument 
- * and it must be for a double (%f or %g). 
+ * Note that this format string should only include one substitution argument
+ * and it must be for a double (%f or %g).
  *
- * @return a reference to the CPLString. 
+ * @return a reference to the CPLString.
  */
 
 CPLString &CPLString::FormatC( double dfValue, const char *pszFormat )
@@ -159,13 +160,14 @@ CPLString &CPLString::FormatC( double dfValue, const char *pszFormat )
     if( pszFormat == NULL )
         pszFormat = "%g";
 
-    char szWork[512]; // presumably long enough for any number?
+    // presumably long enough for any number.
+    const size_t buf_size = 512;
+    char szWork[buf_size];
 
-    CPLsprintf( szWork, pszFormat, dfValue );
-    CPLAssert( strlen(szWork) < sizeof(szWork) );
+    CPLsnprintf( szWork, buf_size, pszFormat, dfValue );
 
     *this += szWork;
-    
+
     return *this;
 }
 
@@ -179,24 +181,23 @@ CPLString &CPLString::FormatC( double dfValue, const char *pszFormat )
  * Trims white space off the let and right of the string.  White space
  * is any of a space, a tab, a newline ('\n') or a carriage control ('\r').
  *
- * @return a reference to the CPLString. 
+ * @return a reference to the CPLString.
  */
 
 CPLString &CPLString::Trim()
 
 {
-    size_t iLeft, iRight;
     static const char szWhitespace[] = " \t\r\n";
 
-    iLeft = find_first_not_of( szWhitespace );
-    iRight = find_last_not_of( szWhitespace );
+    const size_t iLeft = find_first_not_of( szWhitespace );
+    const size_t iRight = find_last_not_of( szWhitespace );
 
     if( iLeft == std::string::npos )
     {
         erase();
         return *this;
     }
-    
+
     assign( substr( iLeft, iRight - iLeft + 1 ) );
 
     return *this;
@@ -218,7 +219,7 @@ CPLString &CPLString::Recode( const char *pszSrcEncoding,
     if( strcmp(pszSrcEncoding,pszDstEncoding) == 0 )
         return *this;
 
-    char *pszRecoded = CPLRecode( c_str(), 
+    char *pszRecoded = CPLRecode( c_str(),
                                   pszSrcEncoding,
                                   pszDstEncoding );
 
@@ -235,7 +236,7 @@ CPLString &CPLString::Recode( const char *pszSrcEncoding,
 /*                               ifind()                                */
 /************************************************************************/
 
-/** 
+/**
  * Case insensitive find() alternative.
  *
  * @param str substring to find.
@@ -264,7 +265,7 @@ size_t CPLString::ifind( const char *s, size_t nPos ) const
 {
     const char *pszHaystack = c_str();
     char chFirst = (char) ::tolower( s[0] );
-    int nTargetLen = strlen(s);
+    size_t nTargetLen = strlen(s);
 
     if( nPos > size() )
         nPos = size();
@@ -297,9 +298,7 @@ size_t CPLString::ifind( const char *s, size_t nPos ) const
 CPLString &CPLString::toupper()
 
 {
-    size_t i;
-
-    for( i = 0; i < size(); i++ )
+    for( size_t i = 0; i < size(); i++ )
         (*this)[i] = (char) ::toupper( (*this)[i] );
 
     return *this;
@@ -316,9 +315,7 @@ CPLString &CPLString::toupper()
 CPLString &CPLString::tolower()
 
 {
-    size_t i;
-
-    for( i = 0; i < size(); i++ )
+    for(size_t i = 0; i < size(); i++ )
         (*this)[i] = (char) ::tolower( (*this)[i] );
 
     return *this;
@@ -422,10 +419,11 @@ CPLString CPLOPrintf( const char *pszFormat, ... )
 
 {
     va_list args;
-    CPLString osTarget;
-
     va_start( args, pszFormat );
+
+    CPLString osTarget;
     osTarget.vPrintf( pszFormat, args );
+
     va_end( args );
 
     return osTarget;
diff --git a/port/cplstringlist.cpp b/port/cplstringlist.cpp
index 5f13d75..2ab5018 100644
--- a/port/cplstringlist.cpp
+++ b/port/cplstringlist.cpp
@@ -1,772 +1,809 @@
-/******************************************************************************
- * $Id: cplstringlist.cpp 27496 2014-07-06 11:23:58Z rouault $
- *
- * Project:  GDAL 
- * Purpose:  CPLStringList implementation.
- * Author:   Frank Warmerdam, warmerdam at pobox.com
- *
- ******************************************************************************
- * Copyright (c) 2011, Frank Warmerdam <warmerdam at pobox.com>
- * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "cpl_string.h"
-#include <string>
-
-CPL_CVSID("$Id: cplstringlist.cpp 27496 2014-07-06 11:23:58Z rouault $");
-
-/************************************************************************/
-/*                           CPLStringList()                            */
-/************************************************************************/
-
-CPLStringList::CPLStringList()
-
-{
-    Initialize();
-}
-
-/************************************************************************/
-/*                           CPLStringList()                            */
-/************************************************************************/
-
-/**
- * CPLStringList constructor.
- *
- * @param papszListIn the NULL terminated list of strings to consume.
- * @param bTakeOwnership TRUE if the CPLStringList should take ownership
- * of the list of strings which implies responsibility to free them.
- */
-
-CPLStringList::CPLStringList( char **papszListIn, int bTakeOwnership )
-
-{
-    Initialize();
-    Assign( papszListIn, bTakeOwnership );
-}
-
-/************************************************************************/
-/*                           CPLStringList()                            */
-/************************************************************************/
-
-//! Copy constructor
-CPLStringList::CPLStringList( const CPLStringList &oOther )
-
-{
-    Initialize();
-    Assign( oOther.papszList, FALSE );
-
-    // We don't want to just retain a reference to the others list
-    // as we don't want to make assumptions about it's lifetime that
-    // might surprise the client developer.
-    MakeOurOwnCopy();
-    bIsSorted = oOther.bIsSorted;
-}
-
-/************************************************************************/
-/*                             operator=()                              */
-/************************************************************************/
-
-CPLStringList &CPLStringList::operator=(const CPLStringList& oOther)
-{
-    if (this != &oOther)
-    {
-        Assign( oOther.papszList, FALSE );
-
-        // We don't want to just retain a reference to the others list
-        // as we don't want to make assumptions about it's lifetime that
-        // might surprise the client developer.
-        MakeOurOwnCopy();
-        bIsSorted = oOther.bIsSorted;
-    }
-    
-    return *this;
-}
-
-/************************************************************************/
-/*                             Initialize()                             */
-/************************************************************************/
-
-void CPLStringList::Initialize()
-
-{
-    papszList = NULL;
-    nCount = 0;
-    nAllocation = 0;
-    bOwnList = FALSE;
-    bIsSorted = FALSE;
-}
-
-/************************************************************************/
-/*                           ~CPLStringList()                           */
-/************************************************************************/
-
-CPLStringList::~CPLStringList()
-
-{
-    Clear();
-}
-
-/************************************************************************/
-/*                               Clear()                                */
-/************************************************************************/
-
-/**
- * Clear the string list. 
- */
-CPLStringList &CPLStringList::Clear()
-
-{
-    if( bOwnList )
-    {
-        CSLDestroy( papszList );
-        papszList = NULL;
-
-        bOwnList = FALSE;
-        nAllocation = 0;
-        nCount = 0;
-    }
-    
-    return *this;
-}
-
-/************************************************************************/
-/*                               Assign()                               */
-/************************************************************************/
-
-/**
- * Assign a list of strings. 
- *
- * 
- * @param papszListIn the NULL terminated list of strings to consume.
- * @param bTakeOwnership TRUE if the CPLStringList should take ownership
- * of the list of strings which implies responsibility to free them.
- *
- * @return a reference to the CPLStringList on which it was invoked.
- */
-
-CPLStringList &CPLStringList::Assign( char **papszListIn, int bTakeOwnership )
-
-{
-    Clear();
-
-    papszList = papszListIn;
-    bOwnList = bTakeOwnership;
-
-    if( papszList == NULL || *papszList == NULL )
-        nCount = 0;
-    else
-        nCount = -1;      // unknown
-
-    nAllocation = 0;  
-    bIsSorted = FALSE;
-
-    return *this;
-}
-
-/************************************************************************/
-/*                               Count()                                */
-/************************************************************************/
-
-/**
- * @return count of strings in the list, zero if empty.
- */
-
-int CPLStringList::Count() const
-
-{
-    if( nCount == -1 )
-    {
-        if( papszList == NULL )
-        {
-            nCount = nAllocation = 0;
-        }
-        else
-        {
-            nCount = CSLCount( papszList );
-            nAllocation = MAX(nCount+1,nAllocation);
-        }
-    }
-    
-    return nCount;
-}
-
-/************************************************************************/
-/*                           MakeOurOwnCopy()                           */
-/*                                                                      */
-/*      If we don't own the list, a copy is made which we own.          */
-/*      Necessary if we are going to modify the list.                   */
-/************************************************************************/
-
-void CPLStringList::MakeOurOwnCopy()
-
-{
-    if( bOwnList )
-        return;
-
-    if( papszList == NULL )
-        return;
-
-    Count();
-    bOwnList = TRUE;
-    papszList = CSLDuplicate( papszList );
-    nAllocation = nCount+1;
-}
-
-/************************************************************************/
-/*                          EnsureAllocation()                          */
-/*                                                                      */
-/*      Ensure we have enough room allocated for at least the           */
-/*      requested number of strings (so nAllocation will be at least    */
-/*      one more than the target)                                       */
-/************************************************************************/
-
-void CPLStringList::EnsureAllocation( int nMaxList )
-
-{
-    if( !bOwnList )
-        MakeOurOwnCopy();
-
-    if( nAllocation <= nMaxList )
-    {
-        nAllocation = MAX(nAllocation*2 + 20,nMaxList+1);
-		if( papszList == NULL )
-		{
-			papszList = (char **) CPLCalloc(nAllocation,sizeof(char*));
-			bOwnList = TRUE;
-			nCount = 0;
-		}
-		else
-			papszList = (char **) CPLRealloc(papszList, nAllocation*sizeof(char*));
-    }
-}
-
-/************************************************************************/
-/*                         AddStringDirectly()                          */
-/************************************************************************/
-
-/**
- * Add a string to the list.
- *
- * This method is similar to AddString(), but ownership of the
- * pszNewString is transferred to the CPLStringList class.
- *
- * @param pszNewString the string to add to the list. 
- */
-
-CPLStringList &CPLStringList::AddStringDirectly( char *pszNewString )
-
-{
-    if( nCount == -1 )
-        Count();
-
-    EnsureAllocation( nCount+1 );
-
-    papszList[nCount++] = pszNewString;
-    papszList[nCount] = NULL;
-
-    bIsSorted = FALSE;
-
-    return *this;
-}
-
-/************************************************************************/
-/*                             AddString()                              */
-/************************************************************************/
-
-/**
- * Add a string to the list.
- *
- * A copy of the passed in string is made and inserted in the list.
- *
- * @param pszNewString the string to add to the list. 
- */
-
-CPLStringList &CPLStringList::AddString( const char *pszNewString )
-
-{
-    return AddStringDirectly( CPLStrdup( pszNewString ) );
-}
-
-/************************************************************************/
-/*                            AddNameValue()                            */
-/************************************************************************/
-
-/**
- * A a name=value entry to the list.
- *
- * A key=value string is prepared and appended to the list.  There is no
- * check for other values for the same key in the list.
- *
- * @param pszKey the key name to add.
- * @param pszValue the key value to add.
- */
-
-CPLStringList &CPLStringList::AddNameValue( const char  *pszKey, 
-                                            const char *pszValue )
-
-{
-    if (pszKey == NULL || pszValue==NULL)
-        return *this;
-
-    MakeOurOwnCopy();
-
-/* -------------------------------------------------------------------- */
-/*      Format the line.                                                */
-/* -------------------------------------------------------------------- */
-    char *pszLine;
-    pszLine = (char *) CPLMalloc(strlen(pszKey)+strlen(pszValue)+2);
-    sprintf( pszLine, "%s=%s", pszKey, pszValue );
-
-/* -------------------------------------------------------------------- */
-/*      If we don't need to keep the sort order things are pretty       */
-/*      straight forward.                                               */
-/* -------------------------------------------------------------------- */
-    if( !IsSorted() )
-        return AddStringDirectly( pszLine );
-
-/* -------------------------------------------------------------------- */
-/*      Find the proper insertion point.                                */
-/* -------------------------------------------------------------------- */
-    CPLAssert( IsSorted() );
-    int iKey = FindSortedInsertionPoint( pszLine );
-    InsertStringDirectly( iKey, pszLine );
-    bIsSorted = TRUE; // we have actually preserved sort order.
-
-    return *this;
-}
-
-/************************************************************************/
-/*                            SetNameValue()                            */
-/************************************************************************/
-
-/**
- * Set name=value entry in the list. 
- *
- * Similar to AddNameValue(), except if there is already a value for
- * the key in the list it is replaced instead of adding a new entry to
- * the list.  If pszValue is NULL any existing key entry is removed.
- * 
- * @param pszKey the key name to add.
- * @param pszValue the key value to add.
- */
-
-CPLStringList &CPLStringList::SetNameValue( const char *pszKey, 
-                                            const char *pszValue )
-
-{
-    int iKey = FindName( pszKey );
-
-    if( iKey == -1 )
-        return AddNameValue( pszKey, pszValue );
-
-    Count();
-    MakeOurOwnCopy();
-
-    CPLFree( papszList[iKey] );
-    if( pszValue == NULL ) // delete entry
-    {
-
-        // shift everything down by one.
-        do 
-        {
-            papszList[iKey] = papszList[iKey+1];
-        } 
-        while( papszList[iKey++] != NULL );
-
-        nCount--;
-    }
-    else
-    {
-        char *pszLine;
-        pszLine = (char *) CPLMalloc(strlen(pszKey)+strlen(pszValue)+2);
-        sprintf( pszLine, "%s=%s", pszKey, pszValue );
-
-        papszList[iKey] = pszLine;
-    }
-
-    return *this;
-}
-
-/************************************************************************/
-/*                              operator[]                              */
-/************************************************************************/
-
-/**
- * Fetch entry "i".
- *
- * Fetches the requested item in the list.  Note that the returned string
- * remains owned by the CPLStringList.  If "i" is out of range NULL is
- * returned.
- *
- * @param i the index of the list item to return.
- * @return selected entry in the list.  
- */
-char *CPLStringList::operator[]( int i )
-
-{
-    if( nCount == -1 )
-        Count();
-    
-    if( i < 0 || i >= nCount )
-        return NULL;
-    else
-        return papszList[i];
-}
-
-const char *CPLStringList::operator[]( int i ) const
-
-{
-    if( nCount == -1 )
-        Count();
-    
-    if( i < 0 || i >= nCount )
-        return NULL;
-    else
-        return papszList[i];
-}
-
-/************************************************************************/
-/*                             StealList()                              */
-/************************************************************************/
-
-/**
- * Seize ownership of underlying string array.
- *
- * This method is simmilar to List(), except that the returned list is
- * now owned by the caller and the CPLStringList is emptied.  
- *
- * @return the C style string list. 
- */
-char **CPLStringList::StealList()
-
-{
-    char **papszRetList = papszList;
-
-    bOwnList = FALSE;
-    papszList = NULL;
-    nCount = 0;
-    nAllocation = 0;
-    
-    return papszRetList;
-}
-
-
-static int CPLCompareKeyValueString(const char* pszKVa, const char* pszKVb)
-{
-    const char* pszItera = pszKVa;
-    const char* pszIterb = pszKVb;
-    while( TRUE )
-    {
-        char cha = *pszItera;
-        char chb = *pszIterb;
-        if( cha == '=' || cha == '\0' )
-        {
-            if( chb == '=' || chb == '\0' )
-                return 0;
-            else
-                return -1;
-        }
-        if( chb == '=' || chb == '\0' )
-        {
-            return 1;
-        }
-        if( cha >= 'a' && cha <= 'z' )
-            cha -= ('a' - 'A');
-        if( chb >= 'a' && chb <= 'z' )
-            chb -= ('a' - 'A');
-        if( cha < chb )
-            return -1;
-        else if( cha > chb )
-            return 1;
-        pszItera ++;
-        pszIterb ++;
-    }
-}
-
-/************************************************************************/
-/*                            llCompareStr()                            */
-/*                                                                      */
-/*      Note this is case insensitive!  This is because we normally     */
-/*      treat key value keywords as case insensitive.                   */
-/************************************************************************/
-static int llCompareStr(const void *a, const void *b)
-{
-	return CPLCompareKeyValueString((*(const char **)a),(*(const char **)b));
-}
-
-/************************************************************************/
-/*                                Sort()                                */
-/************************************************************************/
-
-/**
- * Sort the entries in the list and mark list sorted.
- *
- * Note that once put into "sorted" mode, the CPLStringList will attempt to
- * keep things in sorted order through calls to AddString(), 
- * AddStringDirectly(), AddNameValue(), SetNameValue(). Complete list
- * assignments (via Assign() and operator= will clear the sorting state.
- * When in sorted order FindName(), FetchNameValue() and FetchNameValueDef()
- * will do a binary search to find the key, substantially improve lookup
- * performance in large lists.
- */
-
-CPLStringList &CPLStringList::Sort()
-
-{
-    Count();
-    MakeOurOwnCopy();
-
-    qsort( papszList, nCount, sizeof(char*), llCompareStr );
-    bIsSorted = TRUE;
-    
-    return *this;
-}
-
-/************************************************************************/
-/*                              FindName()                              */
-/************************************************************************/
-
-/**
- * Get index of given name/value keyword.
- * 
- * Note that this search is for a line in the form name=value or name:value. 
- * Use FindString() or PartialFindString() for searches not based on name=value
- * pairs. 
- *
- * @param pszKey the name to search for.  
- *
- * @return the string list index of this name, or -1 on failure.
- */
-
-int CPLStringList::FindName( const char *pszKey ) const
-
-{
-    if( !IsSorted() )
-        return CSLFindName( papszList, pszKey );
-
-    // If we are sorted, we can do an optimized binary search. 
-    int iStart=0, iEnd=nCount-1;
-    int nKeyLen = strlen(pszKey);
-
-    while( iStart <= iEnd )
-    {
-        int iMiddle = (iEnd+iStart)/2;
-        const char *pszMiddle = papszList[iMiddle];
-
-        if (EQUALN(pszMiddle, pszKey, nKeyLen)
-            && (pszMiddle[nKeyLen] == '=' || pszMiddle[nKeyLen] == ':') )
-            return iMiddle;
-
-        if( CPLCompareKeyValueString(pszKey,pszMiddle) < 0 )
-            iEnd = iMiddle-1;
-        else
-            iStart = iMiddle+1;
-    }
-
-    return -1;
-}
-
-/************************************************************************/
-/*                            FetchBoolean()                            */
-/************************************************************************/
-/**
- *
- * Check for boolean key value.
- *
- * In a CPLStringList of "Name=Value" pairs, look to see if there is a key
- * with the given name, and if it can be interpreted as being TRUE.  If
- * the key appears without any "=Value" portion it will be considered true. 
- * If the value is NO, FALSE or 0 it will be considered FALSE otherwise
- * if the key appears in the list it will be considered TRUE.  If the key
- * doesn't appear at all, the indicated default value will be returned. 
- * 
- * @param pszKey the key value to look for (case insensitive).
- * @param bDefault the value to return if the key isn't found at all. 
- * 
- * @return TRUE or FALSE 
- */
-
-int CPLStringList::FetchBoolean( const char *pszKey, int bDefault ) const
-
-{
-    const char *pszValue = FetchNameValue( pszKey );
-
-    if( pszValue == NULL )
-        return bDefault;
-    else
-        return CSLTestBoolean( pszValue );
-}
-
-/************************************************************************/
-/*                           FetchNameValue()                           */
-/************************************************************************/
-
-/**
- * Fetch value associated with this key name.
- *
- * If this list sorted, a fast binary search is done, otherwise a linear
- * scan is done.  Name lookup is case insensitive. 
- * 
- * @param pszName the key name to search for.
- * 
- * @return the corresponding value or NULL if not found.  The returned string 
- * should not be modified and points into internal object state that may 
- * change on future calls. 
- */
-
-const char *CPLStringList::FetchNameValue( const char *pszName ) const
-
-{
-    int iKey = FindName( pszName );
-
-    if( iKey == -1 )
-        return NULL;
-
-    CPLAssert( papszList[iKey][strlen(pszName)] == '='
-               || papszList[iKey][strlen(pszName)] == ':' );
-
-    return papszList[iKey] + strlen(pszName)+1;
-}
-
-/************************************************************************/
-/*                         FetchNameValueDef()                          */
-/************************************************************************/
-
-/**
- * Fetch value associated with this key name.
- *
- * If this list sorted, a fast binary search is done, otherwise a linear
- * scan is done.  Name lookup is case insensitive. 
- * 
- * @param pszName the key name to search for.
- * @param pszDefault the default value returned if the named entry isn't found.
- * 
- * @return the corresponding value or the passed default if not found. 
- */
-
-const char *CPLStringList::FetchNameValueDef( const char *pszName,
-                                              const char *pszDefault ) const
-
-{
-    const char *pszValue = FetchNameValue( pszName );
-    if( pszValue == NULL )
-        return pszDefault;
-    else
-        return pszValue;
-}
-
-/************************************************************************/
-/*                            InsertString()                            */
-/************************************************************************/
-
-/**
- * \fn CPLStringList *CPLStringList::InsertString( int nInsertAtLineNo,
- *                                                 const char *pszNewLine );
- *
- * \brief Insert into the list at identified location.
- *
- * This method will insert a string into the list at the identified
- * location.  The insertion point must be within or at the end of the list.
- * The following entries are pushed down to make space.
- *
- * @param nInsertAtLineNo the line to insert at, zero to insert at front.
- * @param pszNewLine to the line to insert.  This string will be copied.
- */
-
-
-/************************************************************************/
-/*                        InsertStringDirectly()                        */
-/************************************************************************/
-
-/**
- * Insert into the list at identified location.
- *
- * This method will insert a string into the list at the identified
- * location.  The insertion point must be within or at the end of the list.
- * The following entries are pushed down to make space.
- *
- * @param nInsertAtLineNo the line to insert at, zero to insert at front.
- * @param pszNewLine to the line to insert, the ownership of this string
- * will be taken over the by the object.  It must have been allocated on the
- * heap.
- */
-
-CPLStringList &CPLStringList::InsertStringDirectly( int nInsertAtLineNo, 
-                                                    char *pszNewLine )
-
-{
-    if( nCount == -1 )
-        Count();
-
-    EnsureAllocation( nCount+1 );
-
-    if( nInsertAtLineNo < 0 || nInsertAtLineNo > nCount )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "CPLStringList::InsertString() requested beyond list end." );
-        return *this;
-    }
-
-    bIsSorted = FALSE;
-
-    for( int i = nCount; i > nInsertAtLineNo; i-- )
-        papszList[i] = papszList[i-1];
-
-    papszList[nInsertAtLineNo] = pszNewLine;
-    papszList[++nCount] = NULL;
-
-    return *this;
-}
-
-/************************************************************************/
-/*                      FindSortedInsertionPoint()                      */
-/*                                                                      */
-/*      Find the location at which the indicated line should be         */
-/*      inserted in order to keep things in sorted order.               */
-/************************************************************************/
-
-int CPLStringList::FindSortedInsertionPoint( const char *pszLine )
-
-{
-    CPLAssert( IsSorted() );
-    
-    int iStart=0, iEnd=nCount-1;
-
-    while( iStart <= iEnd )
-    {
-        int iMiddle = (iEnd+iStart)/2;
-        const char *pszMiddle = papszList[iMiddle];
-
-        if( CPLCompareKeyValueString(pszLine,pszMiddle) < 0 )
-            iEnd = iMiddle-1;
-        else
-            iStart = iMiddle+1;
-    }
-
-    iEnd++;
-    CPLAssert( iEnd >= 0 && iEnd <= nCount );
-    CPLAssert( iEnd == 0 
-               || CPLCompareKeyValueString(pszLine,papszList[iEnd-1]) >= 0 );
-    CPLAssert( iEnd == nCount
-               || CPLCompareKeyValueString(pszLine,papszList[iEnd]) <= 0 );
-    
-    return iEnd;
-}
+/******************************************************************************
+ * $Id: cplstringlist.cpp 33789 2016-03-26 01:31:36Z goatbar $
+ *
+ * Project:  GDAL
+ * Purpose:  CPLStringList implementation.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2011, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_string.h"
+#include <string>
+
+CPL_CVSID("$Id: cplstringlist.cpp 33789 2016-03-26 01:31:36Z goatbar $");
+
+/************************************************************************/
+/*                           CPLStringList()                            */
+/************************************************************************/
+
+CPLStringList::CPLStringList() :
+    papszList(NULL),
+    nCount(0),
+    nAllocation(0),
+    bOwnList(false),
+    bIsSorted(false)
+{}
+
+/************************************************************************/
+/*                           CPLStringList()                            */
+/************************************************************************/
+
+/**
+ * CPLStringList constructor.
+ *
+ * @param papszListIn the NULL terminated list of strings to consume.
+ * @param bTakeOwnership TRUE if the CPLStringList should take ownership
+ * of the list of strings which implies responsibility to free them.
+ */
+
+CPLStringList::CPLStringList( char **papszListIn, int bTakeOwnership )
+
+{
+    Initialize();
+    Assign( papszListIn, bTakeOwnership );
+}
+
+/************************************************************************/
+/*                           CPLStringList()                            */
+/************************************************************************/
+
+//! Copy constructor
+CPLStringList::CPLStringList( const CPLStringList &oOther )
+
+{
+    Initialize();
+    Assign( oOther.papszList, FALSE );
+
+    // We don't want to just retain a reference to the others list
+    // as we don't want to make assumptions about it's lifetime that
+    // might surprise the client developer.
+    MakeOurOwnCopy();
+    bIsSorted = oOther.bIsSorted;
+}
+
+/************************************************************************/
+/*                             operator=()                              */
+/************************************************************************/
+
+CPLStringList &CPLStringList::operator=(const CPLStringList& oOther)
+{
+    if (this != &oOther)
+    {
+        Assign( oOther.papszList, FALSE );
+
+        // We don't want to just retain a reference to the others list
+        // as we don't want to make assumptions about it's lifetime that
+        // might surprise the client developer.
+        MakeOurOwnCopy();
+        bIsSorted = oOther.bIsSorted;
+    }
+
+    return *this;
+}
+
+/************************************************************************/
+/*                             Initialize()                             */
+/************************************************************************/
+
+void CPLStringList::Initialize()
+
+{
+    papszList = NULL;
+    nCount = 0;
+    nAllocation = 0;
+    bOwnList = false;
+    bIsSorted = false;
+}
+
+/************************************************************************/
+/*                           ~CPLStringList()                           */
+/************************************************************************/
+
+CPLStringList::~CPLStringList()
+
+{
+    Clear();
+}
+
+/************************************************************************/
+/*                               Clear()                                */
+/************************************************************************/
+
+/**
+ * Clear the string list.
+ */
+CPLStringList &CPLStringList::Clear()
+
+{
+    if( bOwnList )
+    {
+        CSLDestroy( papszList );
+        papszList = NULL;
+
+        bOwnList = FALSE;
+        nAllocation = 0;
+        nCount = 0;
+    }
+
+    return *this;
+}
+
+/************************************************************************/
+/*                               Assign()                               */
+/************************************************************************/
+
+/**
+ * Assign a list of strings.
+ *
+ *
+ * @param papszListIn the NULL terminated list of strings to consume.
+ * @param bTakeOwnership TRUE if the CPLStringList should take ownership
+ * of the list of strings which implies responsibility to free them.
+ *
+ * @return a reference to the CPLStringList on which it was invoked.
+ */
+
+CPLStringList &CPLStringList::Assign( char **papszListIn, int bTakeOwnership )
+
+{
+    Clear();
+
+    papszList = papszListIn;
+    bOwnList = CPL_TO_BOOL(bTakeOwnership);
+
+    if( papszList == NULL || *papszList == NULL )
+        nCount = 0;
+    else
+        nCount = -1;      // unknown
+
+    nAllocation = 0;
+    bIsSorted = FALSE;
+
+    return *this;
+}
+
+/************************************************************************/
+/*                               Count()                                */
+/************************************************************************/
+
+/**
+ * @return count of strings in the list, zero if empty.
+ */
+
+int CPLStringList::Count() const
+
+{
+    if( nCount == -1 )
+    {
+        if( papszList == NULL )
+        {
+            nCount = nAllocation = 0;
+        }
+        else
+        {
+            nCount = CSLCount( papszList );
+            nAllocation = MAX(nCount+1,nAllocation);
+        }
+    }
+
+    return nCount;
+}
+
+/************************************************************************/
+/*                           MakeOurOwnCopy()                           */
+/*                                                                      */
+/*      If we don't own the list, a copy is made which we own.          */
+/*      Necessary if we are going to modify the list.                   */
+/************************************************************************/
+
+void CPLStringList::MakeOurOwnCopy()
+
+{
+    if( bOwnList )
+        return;
+
+    if( papszList == NULL )
+        return;
+
+    Count();
+    bOwnList = true;
+    papszList = CSLDuplicate( papszList );
+    nAllocation = nCount+1;
+}
+
+/************************************************************************/
+/*                          EnsureAllocation()                          */
+/*                                                                      */
+/*      Ensure we have enough room allocated for at least the           */
+/*      requested number of strings (so nAllocation will be at least    */
+/*      one more than the target)                                       */
+/************************************************************************/
+
+void CPLStringList::EnsureAllocation( int nMaxList )
+
+{
+    if( !bOwnList )
+        MakeOurOwnCopy();
+
+    if( nAllocation <= nMaxList )
+    {
+        nAllocation = MAX(nAllocation*2 + 20,nMaxList+1);
+        if( papszList == NULL )
+        {
+            papszList = static_cast<char **>(
+                CPLCalloc(nAllocation, sizeof(char*)) );
+            bOwnList = true;
+            nCount = 0;
+        }
+        else
+        {
+            papszList = static_cast<char **>(
+                CPLRealloc(papszList, nAllocation*sizeof(char*)) );
+        }
+    }
+}
+
+/************************************************************************/
+/*                         AddStringDirectly()                          */
+/************************************************************************/
+
+/**
+ * Add a string to the list.
+ *
+ * This method is similar to AddString(), but ownership of the
+ * pszNewString is transferred to the CPLStringList class.
+ *
+ * @param pszNewString the string to add to the list.
+ */
+
+CPLStringList &CPLStringList::AddStringDirectly( char *pszNewString )
+
+{
+    if( nCount == -1 )
+        Count();
+
+    EnsureAllocation( nCount+1 );
+
+    papszList[nCount++] = pszNewString;
+    papszList[nCount] = NULL;
+
+    bIsSorted = false;
+
+    return *this;
+}
+
+/************************************************************************/
+/*                             AddString()                              */
+/************************************************************************/
+
+/**
+ * Add a string to the list.
+ *
+ * A copy of the passed in string is made and inserted in the list.
+ *
+ * @param pszNewString the string to add to the list.
+ */
+
+CPLStringList &CPLStringList::AddString( const char *pszNewString )
+
+{
+    return AddStringDirectly( CPLStrdup( pszNewString ) );
+}
+
+/************************************************************************/
+/*                            AddNameValue()                            */
+/************************************************************************/
+
+/**
+ * Add a name=value entry to the list.
+ *
+ * A key=value string is prepared and appended to the list.  There is no
+ * check for other values for the same key in the list.
+ *
+ * @param pszKey the key name to add.
+ * @param pszValue the key value to add.
+ */
+
+CPLStringList &CPLStringList::AddNameValue( const char  *pszKey,
+                                            const char *pszValue )
+
+{
+    if (pszKey == NULL || pszValue==NULL)
+        return *this;
+
+    MakeOurOwnCopy();
+
+/* -------------------------------------------------------------------- */
+/*      Format the line.                                                */
+/* -------------------------------------------------------------------- */
+    const size_t nLen = strlen(pszKey)+strlen(pszValue)+2;
+    char *pszLine = static_cast<char *>( CPLMalloc(nLen) );
+    snprintf( pszLine, nLen, "%s=%s", pszKey, pszValue );
+
+/* -------------------------------------------------------------------- */
+/*      If we don't need to keep the sort order things are pretty       */
+/*      straight forward.                                               */
+/* -------------------------------------------------------------------- */
+    if( !IsSorted() )
+        return AddStringDirectly( pszLine );
+
+/* -------------------------------------------------------------------- */
+/*      Find the proper insertion point.                                */
+/* -------------------------------------------------------------------- */
+    CPLAssert( IsSorted() );
+    const int iKey = FindSortedInsertionPoint( pszLine );
+    InsertStringDirectly( iKey, pszLine );
+    bIsSorted = true;  // We have actually preserved sort order.
+
+    return *this;
+}
+
+/************************************************************************/
+/*                            SetNameValue()                            */
+/************************************************************************/
+
+/**
+ * Set name=value entry in the list.
+ *
+ * Similar to AddNameValue(), except if there is already a value for
+ * the key in the list it is replaced instead of adding a new entry to
+ * the list.  If pszValue is NULL any existing key entry is removed.
+ *
+ * @param pszKey the key name to add.
+ * @param pszValue the key value to add.
+ */
+
+CPLStringList &CPLStringList::SetNameValue( const char *pszKey,
+                                            const char *pszValue )
+
+{
+    int iKey = FindName( pszKey );
+
+    if( iKey == -1 )
+        return AddNameValue( pszKey, pszValue );
+
+    Count();
+    MakeOurOwnCopy();
+
+    CPLFree( papszList[iKey] );
+    if( pszValue == NULL ) // delete entry
+    {
+
+        // shift everything down by one.
+        do
+        {
+            papszList[iKey] = papszList[iKey+1];
+        }
+        while( papszList[iKey++] != NULL );
+
+        nCount--;
+    }
+    else
+    {
+        const size_t nLen = strlen(pszKey)+strlen(pszValue)+2;
+        char *pszLine = static_cast<char *>( CPLMalloc(nLen) );
+        snprintf( pszLine, nLen, "%s=%s", pszKey, pszValue );
+
+        papszList[iKey] = pszLine;
+    }
+
+    return *this;
+}
+
+/************************************************************************/
+/*                              operator[]                              */
+/************************************************************************/
+
+/**
+ * Fetch entry "i".
+ *
+ * Fetches the requested item in the list.  Note that the returned string
+ * remains owned by the CPLStringList.  If "i" is out of range NULL is
+ * returned.
+ *
+ * @param i the index of the list item to return.
+ * @return selected entry in the list.
+ */
+char *CPLStringList::operator[]( int i )
+
+{
+    if( nCount == -1 )
+        Count();
+
+    if( i < 0 || i >= nCount )
+        return NULL;
+
+    return papszList[i];
+}
+
+const char *CPLStringList::operator[]( int i ) const
+
+{
+    if( nCount == -1 )
+        Count();
+
+    if( i < 0 || i >= nCount )
+        return NULL;
+
+    return papszList[i];
+}
+
+/************************************************************************/
+/*                             StealList()                              */
+/************************************************************************/
+
+/**
+ * Seize ownership of underlying string array.
+ *
+ * This method is similar to List(), except that the returned list is
+ * now owned by the caller and the CPLStringList is emptied.
+ *
+ * @return the C style string list.
+ */
+char **CPLStringList::StealList()
+
+{
+    char **papszRetList = papszList;
+
+    bOwnList = false;
+    papszList = NULL;
+    nCount = 0;
+    nAllocation = 0;
+
+    return papszRetList;
+}
+
+
+static int CPLCompareKeyValueString(const char* pszKVa, const char* pszKVb)
+{
+    const char* pszItera = pszKVa;
+    const char* pszIterb = pszKVb;
+    while( true )
+    {
+        char cha = *pszItera;
+        char chb = *pszIterb;
+        if( cha == '=' || cha == '\0' )
+        {
+            if( chb == '=' || chb == '\0' )
+                return 0;
+            else
+                return -1;
+        }
+        if( chb == '=' || chb == '\0' )
+        {
+            return 1;
+        }
+        if( cha >= 'a' && cha <= 'z' )
+            cha -= ('a' - 'A');
+        if( chb >= 'a' && chb <= 'z' )
+            chb -= ('a' - 'A');
+        if( cha < chb )
+            return -1;
+        else if( cha > chb )
+            return 1;
+        pszItera ++;
+        pszIterb ++;
+    }
+}
+
+/************************************************************************/
+/*                            llCompareStr()                            */
+/*                                                                      */
+/*      Note this is case insensitive!  This is because we normally     */
+/*      treat key value keywords as case insensitive.                   */
+/************************************************************************/
+static int llCompareStr(const void *a, const void *b)
+{
+    return CPLCompareKeyValueString(
+        *static_cast<const char **>(const_cast<void *>(a)),
+        *static_cast<const char **>(const_cast<void *>(b)) );
+}
+
+/************************************************************************/
+/*                                Sort()                                */
+/************************************************************************/
+
+/**
+ * Sort the entries in the list and mark list sorted.
+ *
+ * Note that once put into "sorted" mode, the CPLStringList will attempt to
+ * keep things in sorted order through calls to AddString(),
+ * AddStringDirectly(), AddNameValue(), SetNameValue(). Complete list
+ * assignments (via Assign() and operator= will clear the sorting state.
+ * When in sorted order FindName(), FetchNameValue() and FetchNameValueDef()
+ * will do a binary search to find the key, substantially improve lookup
+ * performance in large lists.
+ */
+
+CPLStringList &CPLStringList::Sort()
+
+{
+    Count();
+    MakeOurOwnCopy();
+
+    if( nCount )
+        qsort( papszList, nCount, sizeof(char*), llCompareStr );
+    bIsSorted = true;
+
+    return *this;
+}
+
+/************************************************************************/
+/*                              FindName()                              */
+/************************************************************************/
+
+/**
+ * Get index of given name/value keyword.
+ *
+ * Note that this search is for a line in the form name=value or name:value.
+ * Use FindString() or PartialFindString() for searches not based on name=value
+ * pairs.
+ *
+ * @param pszKey the name to search for.
+ *
+ * @return the string list index of this name, or -1 on failure.
+ */
+
+int CPLStringList::FindName( const char *pszKey ) const
+
+{
+    if( !IsSorted() )
+        return CSLFindName( papszList, pszKey );
+
+    // If we are sorted, we can do an optimized binary search.
+    int iStart = 0;
+    int iEnd = nCount - 1;
+    size_t nKeyLen = strlen(pszKey);
+
+    while( iStart <= iEnd )
+    {
+        const int iMiddle = (iEnd + iStart) / 2;
+        const char *pszMiddle = papszList[iMiddle];
+
+        if (EQUALN(pszMiddle, pszKey, nKeyLen)
+            && (pszMiddle[nKeyLen] == '=' || pszMiddle[nKeyLen] == ':') )
+            return iMiddle;
+
+        if( CPLCompareKeyValueString(pszKey,pszMiddle) < 0 )
+            iEnd = iMiddle-1;
+        else
+            iStart = iMiddle+1;
+    }
+
+    return -1;
+}
+
+/************************************************************************/
+/*                            FetchBool()                               */
+/************************************************************************/
+/**
+ *
+ * Check for boolean key value.
+ *
+ * In a CPLStringList of "Name=Value" pairs, look to see if there is a key
+ * with the given name, and if it can be interpreted as being TRUE.  If
+ * the key appears without any "=Value" portion it will be considered true.
+ * If the value is NO, FALSE or 0 it will be considered FALSE otherwise
+ * if the key appears in the list it will be considered TRUE.  If the key
+ * doesn't appear at all, the indicated default value will be returned.
+ *
+ * @param pszKey the key value to look for (case insensitive).
+ * @param bDefault the value to return if the key isn't found at all.
+ *
+ * @return true or false
+ */
+
+bool CPLStringList::FetchBool( const char *pszKey, bool bDefault ) const
+
+{
+    const char *pszValue = FetchNameValue( pszKey );
+
+    if( pszValue == NULL )
+        return bDefault;
+
+    return CPLTestBool( pszValue );
+}
+
+/************************************************************************/
+/*                            FetchBoolean()                            */
+/************************************************************************/
+/**
+ *
+ * DEPRECATED: Check for boolean key value.
+ *
+ * In a CPLStringList of "Name=Value" pairs, look to see if there is a key
+ * with the given name, and if it can be interpreted as being TRUE.  If
+ * the key appears without any "=Value" portion it will be considered true.
+ * If the value is NO, FALSE or 0 it will be considered FALSE otherwise
+ * if the key appears in the list it will be considered TRUE.  If the key
+ * doesn't appear at all, the indicated default value will be returned.
+ *
+ * @param pszKey the key value to look for (case insensitive).
+ * @param bDefault the value to return if the key isn't found at all.
+ *
+ * @return TRUE or FALSE
+ */
+
+int CPLStringList::FetchBoolean( const char *pszKey, int bDefault ) const
+
+{
+    return FetchBool( pszKey, CPL_TO_BOOL(bDefault) ) ? TRUE : FALSE;
+}
+
+/************************************************************************/
+/*                           FetchNameValue()                           */
+/************************************************************************/
+
+/**
+ * Fetch value associated with this key name.
+ *
+ * If this list sorted, a fast binary search is done, otherwise a linear
+ * scan is done.  Name lookup is case insensitive.
+ *
+ * @param pszName the key name to search for.
+ *
+ * @return the corresponding value or NULL if not found.  The returned string
+ * should not be modified and points into internal object state that may
+ * change on future calls.
+ */
+
+const char *CPLStringList::FetchNameValue( const char *pszName ) const
+
+{
+    const int iKey = FindName( pszName );
+
+    if( iKey == -1 )
+        return NULL;
+
+    CPLAssert( papszList[iKey][strlen(pszName)] == '='
+               || papszList[iKey][strlen(pszName)] == ':' );
+
+    return papszList[iKey] + strlen(pszName)+1;
+}
+
+/************************************************************************/
+/*                         FetchNameValueDef()                          */
+/************************************************************************/
+
+/**
+ * Fetch value associated with this key name.
+ *
+ * If this list sorted, a fast binary search is done, otherwise a linear
+ * scan is done.  Name lookup is case insensitive.
+ *
+ * @param pszName the key name to search for.
+ * @param pszDefault the default value returned if the named entry isn't found.
+ *
+ * @return the corresponding value or the passed default if not found.
+ */
+
+const char *CPLStringList::FetchNameValueDef( const char *pszName,
+                                              const char *pszDefault ) const
+
+{
+    const char *pszValue = FetchNameValue( pszName );
+    if( pszValue == NULL )
+        return pszDefault;
+
+    return pszValue;
+}
+
+/************************************************************************/
+/*                            InsertString()                            */
+/************************************************************************/
+
+/**
+ * \fn CPLStringList *CPLStringList::InsertString( int nInsertAtLineNo,
+ *                                                 const char *pszNewLine );
+ *
+ * \brief Insert into the list at identified location.
+ *
+ * This method will insert a string into the list at the identified
+ * location.  The insertion point must be within or at the end of the list.
+ * The following entries are pushed down to make space.
+ *
+ * @param nInsertAtLineNo the line to insert at, zero to insert at front.
+ * @param pszNewLine to the line to insert.  This string will be copied.
+ */
+
+
+/************************************************************************/
+/*                        InsertStringDirectly()                        */
+/************************************************************************/
+
+/**
+ * Insert into the list at identified location.
+ *
+ * This method will insert a string into the list at the identified
+ * location.  The insertion point must be within or at the end of the list.
+ * The following entries are pushed down to make space.
+ *
+ * @param nInsertAtLineNo the line to insert at, zero to insert at front.
+ * @param pszNewLine to the line to insert, the ownership of this string
+ * will be taken over the by the object.  It must have been allocated on the
+ * heap.
+ */
+
+CPLStringList &CPLStringList::InsertStringDirectly( int nInsertAtLineNo,
+                                                    char *pszNewLine )
+
+{
+    if( nCount == -1 )
+        Count();
+
+    EnsureAllocation( nCount+1 );
+
+    if( nInsertAtLineNo < 0 || nInsertAtLineNo > nCount )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "CPLStringList::InsertString() requested beyond list end." );
+        return *this;
+    }
+
+    bIsSorted = false;
+
+    for( int i = nCount; i > nInsertAtLineNo; i-- )
+        papszList[i] = papszList[i-1];
+
+    papszList[nInsertAtLineNo] = pszNewLine;
+    papszList[++nCount] = NULL;
+
+    return *this;
+}
+
+/************************************************************************/
+/*                      FindSortedInsertionPoint()                      */
+/*                                                                      */
+/*      Find the location at which the indicated line should be         */
+/*      inserted in order to keep things in sorted order.               */
+/************************************************************************/
+
+int CPLStringList::FindSortedInsertionPoint( const char *pszLine )
+
+{
+    CPLAssert( IsSorted() );
+
+    int iStart=0;
+    int iEnd=nCount-1;
+
+    while( iStart <= iEnd )
+    {
+        int iMiddle = (iEnd+iStart)/2;
+        const char *pszMiddle = papszList[iMiddle];
+
+        if( CPLCompareKeyValueString(pszLine,pszMiddle) < 0 )
+            iEnd = iMiddle-1;
+        else
+            iStart = iMiddle+1;
+    }
+
+    iEnd++;
+    CPLAssert( iEnd >= 0 && iEnd <= nCount );
+    CPLAssert( iEnd == 0
+               || CPLCompareKeyValueString(pszLine,papszList[iEnd-1]) >= 0 );
+    CPLAssert( iEnd == nCount
+               || CPLCompareKeyValueString(pszLine,papszList[iEnd]) <= 0 );
+
+    return iEnd;
+}
diff --git a/port/gdal_csv.h b/port/gdal_csv.h
index e4f430c..ff782bb 100644
--- a/port/gdal_csv.h
+++ b/port/gdal_csv.h
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: gdal_csv.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: gdal_csv.h 33844 2016-04-01 08:42:13Z rouault $
  *
  * Project:  Common Portability Library
- * Purpose:  Functions for reading and scaning CSV (comma separated,
+ * Purpose:  Functions for reading and scanning CSV (comma separated,
  *           variable length text files holding tables) files.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
diff --git a/port/makefile.vc b/port/makefile.vc
index 1de6563..6fa11a3 100644
--- a/port/makefile.vc
+++ b/port/makefile.vc
@@ -49,6 +49,11 @@ OBJ	=	cpl_conv.obj \
 		cpl_google_oauth2.obj \
 		cpl_progress.obj \
 		cpl_virtualmem.obj \
+		cpl_worker_thread_pool.obj \
+		cpl_vsil_crypt.obj \
+		cpl_sha256.obj \
+		cpl_aws.obj \
+		cpl_vsi_error.obj \
 		$(ODBC_OBJ)
 
 LIB	=	cpl.lib
@@ -71,6 +76,14 @@ EXTRAFLAGS =	$(EXTRAFLAGS) -DHAVE_CURL $(CURL_CFLAGS) $(CURL_INC)
 EXTRAFLAGS =	$(EXTRAFLAGS) -DHAVE_LIBXML2 $(LIBXML2_INC)
 !ENDIF
 
+!IFDEF CRYPTOPP_INC
+EXTRAFLAGS =	$(EXTRAFLAGS) -DHAVE_CRYPTOPP $(CRYPTOPP_INC)
+!ENDIF
+
+!IFDEF USE_ONLY_CRYPTODLL_ALG
+EXTRAFLAGS =	$(EXTRAFLAGS) -DUSE_ONLY_CRYPTODLL_ALG
+!ENDIF
+
 !IFDEF ODBC_SUPPORTED
 ODBC_OBJ =	cpl_odbc.obj
 !ENDIF
@@ -85,5 +98,3 @@ clean:
 
 cpl_config.h:	cpl_config.h.vc
 	copy cpl_config.h.vc cpl_config.h
-
-
diff --git a/port/vsipreload.cpp b/port/vsipreload.cpp
index 90589ad..79e96c7 100644
--- a/port/vsipreload.cpp
+++ b/port/vsipreload.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vsipreload.cpp 28464 2015-02-12 14:40:34Z rouault $
+ * $Id: vsipreload.cpp 33724 2016-03-16 17:14:11Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Standalone shared library that can be LD_PRELOAD'ed as an overload of
@@ -37,7 +37,7 @@
 
 // Run:
 // LD_PRELOAD=./vsipreload.so ....
-// e.g: 
+// e.g:
 // LD_PRELOAD=./vsipreload.so gdalinfo /vsicurl/http://download.osgeo.org/gdal/data/ecw/spif83.ecw
 // LD_PRELOAD=./vsipreload.so gdalinfo 'HDF4_EOS:EOS_GRID:"/vsicurl/http://download.osgeo.org/gdal/data/hdf4/MOD09Q1G_EVI.A2006233.h07v03.005.2008338190308.hdf":MODIS_NACP_EVI:MODIS_EVI'
 // LD_PRELOAD=./vsipreload.so ogrinfo /vsicurl/http://svn.osgeo.org/gdal/trunk/autotest/ogr/data/testavc -ro
@@ -68,7 +68,7 @@
 #include "cpl_string.h"
 #include "cpl_hash_set.h"
 
-CPL_CVSID("$Id: vsipreload.cpp 28464 2015-02-12 14:40:34Z rouault $");
+CPL_CVSID("$Id: vsipreload.cpp 33724 2016-03-16 17:14:11Z goatbar $");
 
 static int DEBUG_VSIPRELOAD = 0;
 static int DEBUG_VSIPRELOAD_ONLY_VSIL = 1;
@@ -292,7 +292,7 @@ static int getfdFromVSILFILE(VSILFILE* fpVSIL)
 {
     CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
 
-    int fd;
+    int fd = 0;
     std::map<VSILFILE*, int>::iterator oIter = oMapVSITofd.find(fpVSIL);
     if( oIter != oMapVSITofd.end() )
         fd = oIter->second;
@@ -313,9 +313,9 @@ static int getfdFromVSILFILE(VSILFILE* fpVSIL)
 static int VSIFopenHelper(const char *path, int flags)
 {
     const char* pszMode = "rb";
-    if ((flags & 3) == O_RDONLY) 
+    if ((flags & 3) == O_RDONLY)
         pszMode = "rb";
-    else if ((flags & 3) == O_WRONLY) 
+    else if ((flags & 3) == O_WRONLY)
     {
         if( flags & O_APPEND )
             pszMode = "ab";
@@ -330,7 +330,7 @@ static int VSIFopenHelper(const char *path, int flags)
             pszMode = "rb+";
     }
     VSILFILE* fpVSIL = VSIFfopenHelper(path, pszMode );
-    int fd;
+    int fd = 0;
     if( fpVSIL != NULL )
     {
         if( flags & O_TRUNC )
@@ -349,17 +349,17 @@ static int VSIFopenHelper(const char *path, int flags)
 /*                    GET_DEBUG_VSIPRELOAD_COND()                             */
 /************************************************************************/
 
-static int GET_DEBUG_VSIPRELOAD_COND(const char* path)
+static bool GET_DEBUG_VSIPRELOAD_COND(const char* path)
 {
-    return (DEBUG_VSIPRELOAD && (!DEBUG_VSIPRELOAD_ONLY_VSIL || strncmp(path, "/vsi", 4) == 0) );
+    return (DEBUG_VSIPRELOAD && (!DEBUG_VSIPRELOAD_ONLY_VSIL || STARTS_WITH(path, "/vsi")) );
 }
 
-static int GET_DEBUG_VSIPRELOAD_COND(VSILFILE* fpVSIL)
+static bool GET_DEBUG_VSIPRELOAD_COND(VSILFILE* fpVSIL)
 {
     return (DEBUG_VSIPRELOAD && (!DEBUG_VSIPRELOAD_ONLY_VSIL || fpVSIL != NULL));
 }
 
-static int GET_DEBUG_VSIPRELOAD_COND(VSIDIR* dirP)
+static bool GET_DEBUG_VSIPRELOAD_COND(VSIDIR* dirP)
 {
     return (DEBUG_VSIPRELOAD && (!DEBUG_VSIPRELOAD_ONLY_VSIL || oSetVSIDIR.find(dirP) != oSetVSIDIR.end()));
 }
@@ -416,7 +416,7 @@ FILE *fopen(const char *path, const char *mode)
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
     if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fopen(%s, %s)\n", path, mode);
     FILE* ret;
-    if( strncmp(path, "/vsi", 4) == 0 )
+    if( STARTS_WITH(path, "/vsi") )
         ret = (FILE*) VSIFfopenHelper(path, mode);
     else
         ret = pfnfopen(path, mode);
@@ -434,7 +434,7 @@ FILE *fopen64(const char *path, const char *mode)
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
     if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fopen64(%s, %s)\n", path, mode);
     FILE* ret;
-    if( strncmp(path, "/vsi", 4) == 0 )
+    if( STARTS_WITH(path, "/vsi") )
         ret = (FILE*) VSIFfopenHelper(path, mode);
     else
         ret = pfnfopen64(path, mode);
@@ -453,7 +453,7 @@ size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
     if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fread(stream=%p,size=%d,nmemb=%d)\n",
         stream, (int)size, (int)nmemb);
-    size_t ret;
+    size_t ret = 0;
     if( fpVSIL )
         ret = VSIFReadL(ptr, size, nmemb, fpVSIL);
     else
@@ -474,7 +474,7 @@ size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
     if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fwrite(stream=%p,size=%d,nmemb=%d)\n",
         stream, (int)size, (int)nmemb);
-    size_t ret;
+    size_t ret = 0;
     if( fpVSIL != NULL )
         ret = VSIFWriteL(ptr, size, nmemb, fpVSIL);
     else
@@ -528,17 +528,16 @@ int __xstat(int ver, const char *path, struct stat *buf)
     if( DEBUG_VSIPRELOAD && (osCurDir.size() != 0 && path[0] != '/') )
         DEBUG_VSIPRELOAD_COND = 1;
     if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "__xstat(%s)\n", path);
-    if( (osCurDir.size() != 0 && path[0] != '/') || strncmp(path, "/vsi", 4) == 0 )
+    if( (osCurDir.size() != 0 && path[0] != '/') || STARTS_WITH(path, "/vsi") )
     {
         VSIStatBufL sStatBufL;
-        int ret;
         std::string newpath;
         if( (osCurDir.size() != 0 && path[0] != '/') )
         {
             newpath = CPLFormFilename(osCurDir.c_str(), path, NULL);
             path = newpath.c_str();
         }
-        ret = VSIStatL(path, &sStatBufL);
+        const int ret = VSIStatL(path, &sStatBufL);
         sStatBufL.st_ino = (int)CPLHashSetHashStr(path);
         if( ret == 0 )
         {
@@ -572,17 +571,16 @@ int __lxstat(int ver, const char *path, struct stat *buf)
     if( DEBUG_VSIPRELOAD && (osCurDir.size() != 0 && path[0] != '/') )
         DEBUG_VSIPRELOAD_COND = 1;
     if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "__lxstat(%s)\n", path);
-    if( (osCurDir.size() != 0 && path[0] != '/') || strncmp(path, "/vsi", 4) == 0 )
+    if( (osCurDir.size() != 0 && path[0] != '/') || STARTS_WITH(path, "/vsi") )
     {
         VSIStatBufL sStatBufL;
-        int ret;
         std::string newpath;
         if( (osCurDir.size() != 0 && path[0] != '/') )
         {
             newpath = CPLFormFilename(osCurDir.c_str(), path, NULL);
             path = newpath.c_str();
         }
-        ret = VSIStatL(path, &sStatBufL);
+        const int ret = VSIStatL(path, &sStatBufL);
         sStatBufL.st_ino = (int)CPLHashSetHashStr(path);
         if( ret == 0 )
         {
@@ -616,17 +614,16 @@ int __xstat64(int ver, const char *path, struct stat64 *buf)
     if( DEBUG_VSIPRELOAD && (osCurDir.size() != 0 && path[0] != '/') )
         DEBUG_VSIPRELOAD_COND = 1;
     if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "__xstat64(%s)\n", path);
-    if( (osCurDir.size() != 0 && path[0] != '/') || strncmp(path, "/vsi", 4) == 0 )
+    if( (osCurDir.size() != 0 && path[0] != '/') || STARTS_WITH(path, "/vsi") )
     {
         VSIStatBufL sStatBufL;
-        int ret;
         std::string newpath;
         if( (osCurDir.size() != 0 && path[0] != '/') )
         {
             newpath = CPLFormFilename(osCurDir.c_str(), path, NULL);
             path = newpath.c_str();
         }
-        ret = VSIStatL(path, &sStatBufL);
+        const int ret = VSIStatL(path, &sStatBufL);
         sStatBufL.st_ino = (int)CPLHashSetHashStr(path);
         if( ret == 0 )
         {
@@ -829,7 +826,7 @@ int fileno(FILE *stream)
     VSILFILE* fpVSIL = getVSILFILE(stream);
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
     if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fileno(stream=%p)\n", stream);
-    int fd;
+    int fd = 0;
     if( fpVSIL != NULL )
         fd = getfdFromVSILFILE(fpVSIL);
     else
@@ -934,7 +931,7 @@ int open(const char *path, int flags, ...)
     va_list args;
     va_start(args, flags);
     mode_t mode = va_arg(args, mode_t);
-    int fd;
+    int fd = 0;
     if( osCurDir.size() != 0 && path[0] != '/' && (flags & 3) == O_RDONLY && (flags & O_DIRECTORY) != 0 )
     {
         VSIStatBufL sStatBufL;
@@ -960,7 +957,7 @@ int open(const char *path, int flags, ...)
         else
             fd = -1;
     }
-    else if( strncmp(path, "/vsi", 4) == 0 )
+    else if( STARTS_WITH(path, "/vsi") )
         fd = VSIFopenHelper(path, flags);
     else
         fd = pfnopen(path, flags, mode);
@@ -990,7 +987,7 @@ int open64(const char *path, int flags, ...)
     va_list args;
     va_start(args, flags);
     mode_t mode = va_arg(args, mode_t);
-    int fd;
+    int fd = 0;
     if( osCurDir.size() != 0 && path[0] != '/' && (flags & 3) == O_RDONLY && (flags & O_DIRECTORY) != 0 )
     {
         VSIStatBufL sStatBufL;
@@ -1016,7 +1013,7 @@ int open64(const char *path, int flags, ...)
         else
             fd = -1;
     }
-    else if( strncmp(path, "/vsi", 4) == 0 )
+    else if( STARTS_WITH(path, "/vsi") )
         fd = VSIFopenHelper(path, flags);
     else
         fd = pfnopen64(path, flags, mode);
@@ -1080,7 +1077,7 @@ ssize_t read(int fd, void *buf, size_t count)
     VSILFILE* fpVSIL = getVSILFILE(fd);
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
     if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "read(fd=%d, count=%d)\n", fd, (int)count);
-    ssize_t ret;
+    ssize_t ret = 0;
     if( fpVSIL != NULL )
         ret = VSIFReadL(buf, 1, count, fpVSIL);
     else
@@ -1253,13 +1250,12 @@ int __fxstatat (int ver, int dirfd, const char *pathname, struct stat *buf,
         DEBUG_VSIPRELOAD_COND = 1;
     if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "__fxstatat(dirfd=%d,pathname=%s,flags=%d)\n", dirfd, pathname, flags);
 
-    if( osCurDir.size() != 0 || strncmp(pathname, "/vsi", 4) == 0 )
+    if( osCurDir.size() != 0 || STARTS_WITH(pathname, "/vsi") )
     {
         VSIStatBufL sStatBufL;
-        int ret;
         if( osCurDir.size() && dirfd == AT_FDCWD && pathname[0] != '/' )
             pathname = CPLFormFilename(osCurDir.c_str(), pathname, NULL);
-        ret = VSIStatL(pathname, &sStatBufL);
+        const int ret = VSIStatL(pathname, &sStatBufL);
         sStatBufL.st_ino = (int)CPLHashSetHashStr(pathname);
         if( ret == 0 )
         {
@@ -1329,11 +1325,11 @@ off64_t lseek64(int fd, off64_t off, int whence)
 int truncate(const char *path, off_t length)
 {
     myinit();
-    int ret;
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
     if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "truncate(%s)\n", path);
 
-    if( strncmp(path, "/vsi", 4) == 0 )
+    int ret = 0;
+    if( STARTS_WITH(path, "/vsi") )
     {
         VSILFILE* fpVSIL = VSIFOpenL(path, "wb+");
         if( fpVSIL )
@@ -1356,10 +1352,10 @@ int truncate(const char *path, off_t length)
 int ftruncate(int fd, off_t length)
 {
     myinit();
-    int ret;
     VSILFILE* fpVSIL = getVSILFILE(fd);
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
     if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "ftruncate(fd=%d)\n", fd);
+    int ret = 0;
     if( fpVSIL != NULL )
     {
         ret = VSIFTruncateL(fpVSIL, length);
@@ -1382,7 +1378,7 @@ DIR *opendir(const char *name)
     if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "opendir(%s)\n", name);
 
     DIR * ret;
-    if( osCurDir.size() != 0 || strncmp(name, "/vsi", 4) == 0 )
+    if( osCurDir.size() != 0 || STARTS_WITH(name, "/vsi") )
     {
         char** papszDir;
         if( osCurDir.size() != 0 && name[0] != '/' )
@@ -1421,12 +1417,12 @@ DIR *opendir(const char *name)
 /*                             filldir()                                */
 /************************************************************************/
 
-static int filldir(VSIDIR* mydir)
+static bool filldir(VSIDIR* mydir)
 {
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(mydir);
     char* pszName = mydir->papszDir[mydir->nIter++];
     if( pszName == NULL )
-        return FALSE;
+        return false;
     mydir->ent.d_ino = 0;
     mydir->ent.d_off = 0;
     mydir->ent.d_reclen = sizeof(mydir->ent);
@@ -1447,7 +1443,7 @@ static int filldir(VSIDIR* mydir)
     mydir->ent64.d_type = mydir->ent.d_type;
     strcpy(mydir->ent64.d_name, mydir->ent.d_name);
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -1529,7 +1525,7 @@ int dirfd(DIR *dirp)
     myinit();
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND((VSIDIR*)dirp);
     if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "dirfd(%p)\n", dirp);
-    int ret;
+    int ret = 0;
     if( oSetVSIDIR.find((VSIDIR*)dirp) != oSetVSIDIR.end() )
     {
         VSIDIR* mydir = (VSIDIR*)dirp;
@@ -1604,8 +1600,8 @@ int acl_extended_file(const char *path)
     myinit();
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
     if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "acl_extended_file(%s)\n", path);
-    int ret;
-    if( strncmp(path, "/vsi", 4) == 0 )
+    int ret = 0;
+    if( STARTS_WITH(path, "/vsi") )
         ret = -1;
     else
     {
@@ -1632,8 +1628,8 @@ int getfilecon(const char *path, /*security_context_t **/ void* con)
     myinit();
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
     if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "getfilecon(%s)\n", path);
-    int ret;
-    if( strncmp(path, "/vsi", 4) == 0 )
+    int ret = 0;
+    if( STARTS_WITH(path, "/vsi") )
     {
         errno = ENOTSUP;
         ret = -1;
@@ -1663,8 +1659,8 @@ int lgetfilecon(const char *path, /*security_context_t **/ void* con)
     myinit();
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
     if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "lgetfilecon(%s)\n", path);
-    int ret;
-    if( strncmp(path, "/vsi", 4) == 0 )
+    int ret = 0;
+    if( STARTS_WITH(path, "/vsi") )
     {
         errno = ENOTSUP;
         ret = -1;
diff --git a/port/xmlreformat.cpp b/port/xmlreformat.cpp
index 277f43d..96b8fc3 100644
--- a/port/xmlreformat.cpp
+++ b/port/xmlreformat.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: xmlreformat.cpp 24835 2012-08-23 20:11:13Z warmerdam $
+ * $Id: xmlreformat.cpp 33646 2016-03-05 15:54:03Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  XML Reformatting - mostly for testing minixml implementation.
@@ -14,16 +14,16 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************/
 
@@ -33,10 +33,8 @@
 int main( int argc, char **argv )
 
 {
-    CPLXMLNode *poTree;
     static char  szXML[20000000];
     FILE       *fp;
-    int        nLen;
 
     if( argc == 1 )
         fp = stdin;
@@ -55,9 +53,9 @@ int main( int argc, char **argv )
         }
     }
 
-    nLen = fread( szXML, 1, sizeof(szXML), fp );
+    int nLen = fread( szXML, 1, sizeof(szXML), fp );
     if( nLen >= (int) sizeof(szXML)-2 ) {
-        fprintf( stderr, 
+        fprintf( stderr,
                  "xmlreformat fixed sized buffer (%d bytes) exceeded.\n",
                  (int) sizeof(szXML) );
         exit(1);
@@ -68,7 +66,7 @@ int main( int argc, char **argv )
 
     szXML[nLen] = '\0';
 
-    poTree = CPLParseXMLString( szXML );
+    CPLXMLNode *poTree = CPLParseXMLString( szXML );
     if( poTree != NULL )
     {
         char *pszRawXML = CPLSerializeXMLTree( poTree );
diff --git a/scripts/GNUmakefile b/scripts/GNUmakefile
new file mode 100644
index 0000000..8f039e4
--- /dev/null
+++ b/scripts/GNUmakefile
@@ -0,0 +1,10 @@
+include  ../GDALmake.opt
+
+completion:
+	PATH=$(GDAL_ROOT)/swig/python/scripts:$(GDAL_ROOT)/apps:$(PATH) python completionFinder.py gdal-bash-completion.sh
+
+install:
+	if test "x`pkg-config --version 2>/dev/null`" != "x" -a "x`pkg-config --variable=compatdir bash-completion`" != "x"; then \
+		$(INSTALL_DIR) $(DESTDIR)${prefix}`pkg-config --variable=compatdir bash-completion` ; \
+		cp gdal-bash-completion.sh $(DESTDIR)${prefix}`pkg-config --variable=compatdir bash-completion`; \
+	fi
diff --git a/scripts/check_broken_links.py b/scripts/check_broken_links.py
new file mode 100755
index 0000000..a09fd6b
--- /dev/null
+++ b/scripts/check_broken_links.py
@@ -0,0 +1,87 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+###############################################################################
+# $Id$
+#
+#  Project:  GDAL
+#  Purpose:  Check validity of <a href="XXXX"> links
+#  Author:   Even Rouault <even.rouault at spatialys.com>
+#
+###############################################################################
+#  Copyright (c) 2015, Even Rouault <even.rouault at spatialys.com>
+#
+#  Permission is hereby granted, free of charge, to any person obtaining a
+#  copy of this software and associated documentation files (the "Software"),
+#  to deal in the Software without restriction, including without limitation
+#  the rights to use, copy, modify, merge, publish, distribute, sublicense,
+#  and/or sell copies of the Software, and to permit persons to whom the
+#  Software is furnished to do so, subject to the following conditions:
+#
+#  The above copyright notice and this permission notice shall be included
+#  in all copies or substantial portions of the Software.
+#
+#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+#  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+#  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+#  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+#  DEALINGS IN THE SOFTWARE.
+###############################################################################
+
+import os
+import requests
+import sys
+
+ok_set = dict()
+broken_set = {}
+
+
+def check(filename):
+    f = open(filename, 'r')
+    lines = f.readlines()
+
+    for i in range(len(lines)):
+        line = lines[i].strip('\n')
+        pos = line.find('<a href="')
+        if pos >= 0:
+            pos += len('<a href="')
+            end_pos = line.find('"', pos)
+            while end_pos < 0:
+                i += 1
+                line += lines[i].strip('\n')
+                end_pos = line.find('"', pos)
+            url = line[pos:end_pos]
+            sharp = url.find('#')
+            if sharp == 0:
+                continue
+            elif sharp > 0:
+                url = url[0:sharp]
+            if url in ok_set:
+                continue
+            if url in broken_set:
+                print('ERROR: Broken link %s in %s' % (url, filename))
+            print('Checking %s...' % url)
+            if url.startswith('http'):
+                ok = False
+                try:
+                    r = requests.get(url, verify=False)
+                    ok = r.status_code == 200
+                except:
+                    pass
+                if not ok:
+                    print('ERROR: Broken link %s in %s' % (url, filename))
+                    broken_set[url] = True
+                else:
+                    ok_set[url] = True
+            else:
+                checked_filename = os.path.join(os.path.dirname(filename), url)
+                # print(checked_filename)
+                if not os.path.exists(checked_filename):
+                    print('ERROR: Broken link %s in %s' % (url, filename))
+                    broken_set[url] = True
+                else:
+                    ok_set[url] = True
+
+for filename in sys.argv[1:]:
+    check(filename)
diff --git a/scripts/completionFinder.py b/scripts/completionFinder.py
new file mode 100644
index 0000000..3368588
--- /dev/null
+++ b/scripts/completionFinder.py
@@ -0,0 +1,287 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+###############################################################################
+# $Id$
+#
+# Project:  GDAL/OGR Utilities
+# Purpose:  Bash completion script generation
+# Author:   Guillaume Pasero <guillaume dot pasero at c dash s dot fr>
+#
+###############################################################################
+# Copyright (c) 2016, Guillaume Pasero <guillaume dot pasero at c dash s dot fr>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+###############################################################################
+
+import sys, os
+import os.path as op
+
+from subprocess import call, Popen, PIPE, STDOUT
+
+def showHelp():
+  print "Usage : completionFinder.py  output_script"
+  
+
+def processLine(line):
+  outList = []
+  lvl1 = line.split(' ')
+  lvl2 = []
+  for item in lvl1:
+    lvl2 += item.split('[')
+  lvl3 = []
+  for item in lvl2:
+    lvl3 += item.split(']')
+  lvl4 = []
+  for item in lvl3:
+    lvl4 += item.split('|')
+  
+  for item in lvl4:
+    if len(item) >= 2:
+      if item[0] == '-':
+        key = item
+        # Handle special cases -key={A/B/C}
+        if (key.count("={") == 1 and key[-1] == '}'):
+          pair = key.split("=")
+          choices = ((pair[1])[1:-1]).split('/')
+          for c in choices:
+            outList.append(pair[0]+"="+c)
+        else:
+          outList.append(key)
+  
+  return outList
+
+def processTool(toolName):
+  command = [toolName, "-"]
+
+  process = Popen(command,stdout=PIPE,stderr=STDOUT)
+  result = process.communicate()[0]
+  lines = result.split('\n')
+  index = 0
+  
+  while index < len(lines):
+    if (lines[index].find("Usage:") >= 0):
+      break
+    index += 1
+  
+  options = []
+  
+  while index < len(lines):
+    cleanLine = lines[index].strip('\t\r ')
+    if (len(cleanLine) == 0):
+      break;
+    options += processLine(cleanLine)
+    index += 1
+  
+  return options
+
+def parseGDALGeneralOptions():
+  command = ["gdalinfo", "--help-general"]
+  process = Popen(command,stdout=PIPE,stderr=STDOUT)
+  result = process.communicate()[0]
+  lines = result.split('\n')
+  index = 0
+  options = []
+  while index < len(lines):
+    cleanLine = lines[index].strip('\t\r ')
+    parts = cleanLine.split(':')
+    if (parts[0].find('--') == 0):
+      words = parts[0].split(' ')
+      options.append(words[0])
+    index += 1
+  return options
+
+def parseOGRGeneralOptions():
+  command = ["ogr2ogr", "--help-general"]
+  process = Popen(command,stdout=PIPE,stderr=STDOUT)
+  result = process.communicate()[0]
+  lines = result.split('\n')
+  index = 0
+  options = []
+  while index < len(lines):
+    cleanLine = lines[index].strip('\t\r ')
+    parts = cleanLine.split(':')
+    if (parts[0].find('--') == 0):
+      words = parts[0].split(' ')
+      options.append(words[0])
+    index += 1
+  return options
+
+# generate completion script section for :
+#   - name : the given gdal/ogr tool
+#   - optList : option list
+def getCompletionScript(name,optList):
+  output = []
+  output.append("_"+name+"()\n")
+  output.append("{\n")
+  output.append("  local cur prev\n")
+  output.append("  COMPREPLY=()\n")
+  output.append("  _get_comp_words_by_ref cur prev\n")
+  output.append("  case \"$cur\" in\n")
+  output.append("    -*)\n")
+  optLine = "      key_list=\""
+  for item in optList:
+    optLine += item + " "
+  optLine += "\"\n"
+  output.append(optLine)
+  output.append("      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )\n")
+  output.append("      return 0\n")
+  output.append("      ;;\n")
+  output.append("  esac\n")
+  
+  # adapt format parsing command : GDAL type of OGR type
+  
+  isGdal = True
+  if (name.find("ogr") == 0):
+    isGdal = False
+    
+  # gdal type
+  if isGdal:
+    formatParsingCmd = "$tool --formats | tail -n +2 | cut -f 3 -d ' '"
+    if ("-ot" in optList) or ("-of" in optList) or ("--format" in optList):
+      output.append("  tool=${COMP_WORDS[0]}\n")
+      output.append("  case \"$prev\" in\n")
+      if "-ot" in optList:
+        output.append("    -ot)\n")
+        output.append("      key_list=\"Byte Int16 UInt16 UInt32 Int32 Float32 Float64 CInt16 CInt32 CFloat32 CFloat64\"\n")
+        output.append("      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )\n")
+        output.append("      ;;\n")
+      if ("-of" in optList) and isGdal:
+        output.append("    -of)\n")
+        output.append("      key_list=\"$( "+formatParsingCmd+")\"\n")
+        output.append("      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )\n")
+        output.append("      ;;\n")
+      if ("--format" in optList) and isGdal:
+        output.append("    --format)\n")
+        output.append("      key_list=\"$( "+formatParsingCmd+")\"\n")
+        output.append("      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )\n")
+        output.append("      ;;\n")
+      output.append("  esac\n")
+  else:
+    # ogr type
+    formatParsingCmd = "$tool --formats | tail -n +2 | grep -o -E '\"[^\"]+\"' | sed 's/\ /__/'"
+    if ("-f" in optList):
+      # replace ogrtindex by ogr2ogr to check --formats 
+      output.append("  tool=${COMP_WORDS[0]/ogrtindex/ogr2ogr}\n")
+      output.append("  case \"$prev\" in\n")
+      if ("-f" in optList) and not isGdal:
+        # completion is more tricky here because of spaces
+        output.append("    -f)\n")
+        output.append("      key_list=\"$( "+formatParsingCmd+")\"\n")
+        output.append("      for iter in $key_list; do\n")
+        output.append("        if [[ $iter =~ ^$cur ]]; then\n")
+        output.append("          COMPREPLY+=( \"${iter//__/ }\" )\n")
+        output.append("        fi\n")
+        output.append("      done\n")
+        output.append("      ;;\n")
+      output.append("  esac\n")
+  
+  output.append("  return 0\n")
+  output.append("}\n")
+  output.append("complete -o default -F _"+name+" "+name+"\n")
+  
+  return output
+
+def main(argv):
+  if len(argv) < 2 :
+    showHelp()
+    return 1
+  
+  gdaltools = [ "gdal2tiles.py",\
+                "gdal2xyz.py",\
+                "gdaladdo",\
+#                "gdal_auth.py",\
+                "gdalbuildvrt",\
+                "gdal_calc.py",\
+                "gdalchksum.py",\
+                "gdalcompare.py",\
+                "gdal-config",\
+                "gdal_contour",\
+                "gdaldem",\
+                "gdal_edit.py",\
+                "gdalenhance",\
+                "gdal_fillnodata.py",\
+                "gdal_grid",\
+                "gdalident.py",\
+                "gdalimport.py",\
+                "gdalinfo",\
+                "gdallocationinfo",\
+                "gdalmanage",\
+                "gdal_merge.py",\
+                "gdalmove.py",\
+                "gdal_polygonize.py",\
+                "gdal_proximity.py",\
+                "gdal_rasterize",\
+                "gdal_retile.py",\
+                "gdalserver",\
+                "gdal_sieve.py",\
+                "gdalsrsinfo",\
+                "gdaltindex",\
+                "gdaltransform",\
+                "gdal_translate",\
+                "gdalwarp"]
+  
+  ogrtools = [ "ogr2ogr",\
+               "ogrinfo",\
+               "ogrlineref",\
+               "ogrtindex"]
+  
+  # parse general options
+  generalOptions = parseGDALGeneralOptions()
+  generalOGROptions = parseOGRGeneralOptions()
+  
+  outFile = argv[1]
+  of = open(outFile,'w')
+  of.write("# File auto-generated by completionFinder.py, do not modify manually\n")
+  of.write("""
+function_exists() {
+    declare -f -F $1 > /dev/null
+    return $?
+}
+
+# Checks that bash-completion is recent enough
+function_exists _get_comp_words_by_ref || return 0
+
+""")
+
+  for name in gdaltools:
+    # verbose print
+    print name
+    optList = processTool(name)
+    if "--help-general" in optList:
+      for item in generalOptions:
+        if not item in optList:
+          optList.append(item)
+    of.writelines(getCompletionScript(name,optList))
+  for name in ogrtools:
+    # verbose print
+    print name
+    optList = processTool(name)
+    if "--help-general" in optList:
+      for item in generalOGROptions:
+        if not item in optList:
+          optList.append(item)
+    of.writelines(getCompletionScript(name,optList))
+  
+  of.close()
+  return 0
+
+
+if __name__ == "__main__":
+  main(sys.argv)
+
diff --git a/scripts/fix_typos.sh b/scripts/fix_typos.sh
new file mode 100755
index 0000000..02ddc69
--- /dev/null
+++ b/scripts/fix_typos.sh
@@ -0,0 +1,66 @@
+#!/bin/sh
+# -*- coding: utf-8 -*-
+###############################################################################
+# $Id$
+#
+#  Project:  GDAL
+#  Purpose:  (Interactive) script to identify and fix typos
+#  Author:   Even Rouault <even.rouault at spatialys.com>
+#
+###############################################################################
+#  Copyright (c) 2016, Even Rouault <even.rouault at spatialys.com>
+#
+#  Permission is hereby granted, free of charge, to any person obtaining a
+#  copy of this software and associated documentation files (the "Software"),
+#  to deal in the Software without restriction, including without limitation
+#  the rights to use, copy, modify, merge, publish, distribute, sublicense,
+#  and/or sell copies of the Software, and to permit persons to whom the
+#  Software is furnished to do so, subject to the following conditions:
+#
+#  The above copyright notice and this permission notice shall be included
+#  in all copies or substantial portions of the Software.
+#
+#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+#  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+#  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+#  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+#  DEALINGS IN THE SOFTWARE.
+###############################################################################
+
+if ! test -d fix_typos; then
+    # Get our fork of codespell that adds --words-white-list and full filename support for -S option
+    mkdir fix_typos
+    cd fix_typos
+    git clone https://github.com/rouault/codespell
+    cd codespell
+    git checkout gdal_improvements
+    cd ..
+    # Aggregate base dictionary + QGIS one + Debian Lintian one
+    curl https://raw.githubusercontent.com/qgis/QGIS/master/scripts/spelling.dat | sed "s/:/->/" | grep -v "colour->" | grep -v "colours->" > qgis.txt
+    curl https://anonscm.debian.org/cgit/lintian/lintian.git/plain/data/spelling/corrections| grep "||" | grep -v "#" | sed "s/||/->/" > debian.txt
+    cat codespell/data/dictionary.txt qgis.txt debian.txt | awk 'NF' > gdal_dict.txt
+    echo "difered->deferred" >> gdal_dict.txt
+    echo "differed->deferred" >> gdal_dict.txt
+    cd ..
+fi
+
+EXCLUDED_FILES="*/.svn*,configure,config.status,config.sub,*/autom4te.cache/*"
+EXCLUDED_FILES="$EXCLUDED_FILES,*/hdf-eos/*,teststream.out,ogrogdilayer.cpp"
+EXCLUDED_FILES="$EXCLUDED_FILES,*/doc/br/*,*/data/*,figures.mp,*/tmp/*,*/ruby/*"
+EXCLUDED_FILES="$EXCLUDED_FILES,*/fix_typos/*,fix_typos.sh,*.eps,geopackage_aspatial.html"
+WORDS_WHITE_LIST="poSession,FIDN,TRAFIC,HTINK,repID,oCurr,INTREST,oPosition"
+WORDS_WHITE_LIST="$WORDS_WHITE_LIST,CPL_SUPRESS_CPLUSPLUS,SRP_NAM,ADRG_NAM,'SRP_NAM,AuxilaryTarget"
+# IRIS driver metadata item names: FIXME ?
+WORDS_WHITE_LIST="$WORDS_WHITE_LIST,TOP_OF_HEIGTH_INTERVAL,BOTTOM_OF_HEIGTH_INTERVAL"
+# libjpeg
+WORDS_WHITE_LIST="$WORDS_WHITE_LIST,JBUF_PASS_THRU"
+# libgif
+WORDS_WHITE_LIST="$WORDS_WHITE_LIST,IS_WRITEABLE,E_GIF_ERR_NOT_WRITEABLE"
+# libtiff
+WORDS_WHITE_LIST="$WORDS_WHITE_LIST,THRESHHOLD_BILEVEL,THRESHHOLD_HALFTONE,THRESHHOLD_ERRORDIFFUSE"
+
+python3 fix_typos/codespell/codespell.py -w -i 3 -q 2 -S $EXCLUDED_FILES \
+    -x scripts/typos_whitelist.txt --words-white-list=$WORDS_WHITE_LIST \
+    -D fix_typos/gdal_dict.txt  ..
diff --git a/scripts/gdal-bash-completion.sh b/scripts/gdal-bash-completion.sh
new file mode 100644
index 0000000..c93e661
--- /dev/null
+++ b/scripts/gdal-bash-completion.sh
@@ -0,0 +1,722 @@
+# File auto-generated by completionFinder.py, do not modify manually
+
+function_exists() {
+    declare -f -F $1 > /dev/null
+    return $?
+}
+
+# Checks that bash-completion is recent enough
+function_exists _get_comp_words_by_ref || return 0
+
+_gdal2tiles.py()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list=""
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdal2tiles.py gdal2tiles.py
+_gdal2xyz.py()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list="-skip -srcwin -band -csv "
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdal2xyz.py gdal2xyz.py
+_gdaladdo()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list="-r -ro -clean -q -oo --help-general --version --license --formats --format --optfile --config --debug --pause --locale "
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  tool=${COMP_WORDS[0]}
+  case "$prev" in
+    --format)
+      key_list="$( $tool --formats | tail -n +2 | cut -f 3 -d ' ')"
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdaladdo gdaladdo
+_gdalbuildvrt()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list="-tileindex -resolution -te -tr -tap -separate -b -sd -allow_projection_difference -q -addalpha -hidenodata -srcnodata -vrtnodata -a_srs -r -input_file_list -overwrite "
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdalbuildvrt gdalbuildvrt
+_gdal_calc.py()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list="-A --A_band -B...-Z "
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdal_calc.py gdal_calc.py
+_gdalchksum.py()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list=""
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdalchksum.py gdalchksum.py
+_gdalcompare.py()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list=""
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdalcompare.py gdalcompare.py
+_gdal-config()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list="--prefix --libs --dep-libs --cflags --datadir --version --ogr-enabled --gnm-enabled --formats "
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdal-config gdal-config
+_gdal_contour()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list="-b -a -3d -inodata -snodata -f -i -f -dsco -lco -off -fl -nln -q "
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdal_contour gdal_contour
+_gdaldem()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list=""
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdaldem gdaldem
+_gdal_edit.py()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list="--help-general -ro -a_srs -a_ullr -tr -unsetgt -a_nodata -unsetnodata -unsetstats -stats -approx_stats -gcp -unsetmd -oo -mo --version --license --formats --format --optfile --config --debug --pause --locale "
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  tool=${COMP_WORDS[0]}
+  case "$prev" in
+    --format)
+      key_list="$( $tool --formats | tail -n +2 | cut -f 3 -d ' ')"
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdal_edit.py gdal_edit.py
+_gdalenhance()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list="--help-general -of -co -ot -src_scale -dst_scale -lutbins -s_nodata -stddev -equalize -config --version --license --formats --format --optfile --config --debug --pause --locale "
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  tool=${COMP_WORDS[0]}
+  case "$prev" in
+    -ot)
+      key_list="Byte Int16 UInt16 UInt32 Int32 Float32 Float64 CInt16 CInt32 CFloat32 CFloat64"
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      ;;
+    -of)
+      key_list="$( $tool --formats | tail -n +2 | cut -f 3 -d ' ')"
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      ;;
+    --format)
+      key_list="$( $tool --formats | tail -n +2 | cut -f 3 -d ' ')"
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdalenhance gdalenhance
+_gdal_fillnodata.py()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list=""
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdal_fillnodata.py gdal_fillnodata.py
+_gdal_grid()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list="--help-general --formats -ot -of -co -zfield -z_increase -z_multiply -a_srs -spat -clipsrc -clipsrcsql -clipsrclayer -clipsrcwhere -l -where -sql -txe -tye -outsize -a -q --version --license --format --optfile --config --debug --pause --locale "
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  tool=${COMP_WORDS[0]}
+  case "$prev" in
+    -ot)
+      key_list="Byte Int16 UInt16 UInt32 Int32 Float32 Float64 CInt16 CInt32 CFloat32 CFloat64"
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      ;;
+    -of)
+      key_list="$( $tool --formats | tail -n +2 | cut -f 3 -d ' ')"
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      ;;
+    --format)
+      key_list="$( $tool --formats | tail -n +2 | cut -f 3 -d ' ')"
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdal_grid gdal_grid
+_gdalident.py()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list=""
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdalident.py gdalident.py
+_gdalimport.py()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list=""
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdalimport.py gdalimport.py
+_gdalinfo()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list="--help-general -json -mm -stats -hist -nogcp -nomd -norat -noct -nofl -checksum -proj4 -listmdd -mdd -sd -oo --version --license --formats --format --optfile --config --debug --pause --locale "
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  tool=${COMP_WORDS[0]}
+  case "$prev" in
+    --format)
+      key_list="$( $tool --formats | tail -n +2 | cut -f 3 -d ' ')"
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdalinfo gdalinfo
+_gdallocationinfo()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list="--help-general -xml -lifonly -valonly -b -overview -l_srs -geoloc -wgs84 -oo --version --license --formats --format --optfile --config --debug --pause --locale "
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  tool=${COMP_WORDS[0]}
+  case "$prev" in
+    --format)
+      key_list="$( $tool --formats | tail -n +2 | cut -f 3 -d ' ')"
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdallocationinfo gdallocationinfo
+_gdalmanage()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list="-r -u -f -f -f "
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdalmanage gdalmanage
+_gdal_merge.py()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list="-o -of -co -ps -tap -separate -q -v -pct -ul_lr -init -n -a_nodata -ot -createonly --help-general --version --license --formats --format --optfile --config --debug --pause --locale "
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  tool=${COMP_WORDS[0]}
+  case "$prev" in
+    -ot)
+      key_list="Byte Int16 UInt16 UInt32 Int32 Float32 Float64 CInt16 CInt32 CFloat32 CFloat64"
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      ;;
+    -of)
+      key_list="$( $tool --formats | tail -n +2 | cut -f 3 -d ' ')"
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      ;;
+    --format)
+      key_list="$( $tool --formats | tail -n +2 | cut -f 3 -d ' ')"
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdal_merge.py gdal_merge.py
+_gdalmove.py()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list=""
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdalmove.py gdalmove.py
+_gdal_polygonize.py()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list=""
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdal_polygonize.py gdal_polygonize.py
+_gdal_proximity.py()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list=""
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdal_proximity.py gdal_proximity.py
+_gdal_rasterize()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list="-b -i -at -burn -a -3d -add -l -where -sql -dialect -of -a_srs -co -a_nodata -init -te -tr -tap -ts -ot -q "
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  tool=${COMP_WORDS[0]}
+  case "$prev" in
+    -ot)
+      key_list="Byte Int16 UInt16 UInt32 Int32 Float32 Float64 CInt16 CInt32 CFloat32 CFloat64"
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      ;;
+    -of)
+      key_list="$( $tool --formats | tail -n +2 | cut -f 3 -d ' ')"
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdal_rasterize gdal_rasterize
+_gdal_retile.py()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list="-v -q -co -of -ps -ot -tileIndex -tileIndexField -csv -csvDelim -s_srs -pyramidOnly -levels -r -useDirForEachRow -multi -targetDir "
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  tool=${COMP_WORDS[0]}
+  case "$prev" in
+    -ot)
+      key_list="Byte Int16 UInt16 UInt32 Int32 Float32 Float64 CInt16 CInt32 CFloat32 CFloat64"
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      ;;
+    -of)
+      key_list="$( $tool --formats | tail -n +2 | cut -f 3 -d ' ')"
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdal_retile.py gdal_retile.py
+_gdalserver()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list="--help-general --help -v -tcpserver -unixserver -stdinout -pipe_in -pipe_out -nofork --version --license --formats --format --optfile --config --debug --pause --locale "
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  tool=${COMP_WORDS[0]}
+  case "$prev" in
+    --format)
+      key_list="$( $tool --formats | tail -n +2 | cut -f 3 -d ' ')"
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdalserver gdalserver
+_gdal_sieve.py()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list=""
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdal_sieve.py gdal_sieve.py
+_gdalsrsinfo()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list=""
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdalsrsinfo gdalsrsinfo
+_gdaltindex()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list="-f -tileindex -write_absolute_path -skip_different_projection -t_srs -src_srs_name -src_srs_format -lyr_name "
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdaltindex gdaltindex
+_gdaltransform()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list="--help-general -i -s_srs -t_srs -to -order -tps -rpc -geoloc -gcp -output_xy --version --license --formats --format --optfile --config --debug --pause --locale "
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  tool=${COMP_WORDS[0]}
+  case "$prev" in
+    --format)
+      key_list="$( $tool --formats | tail -n +2 | cut -f 3 -d ' ')"
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdaltransform gdaltransform
+_gdal_translate()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list="--help-general --long-usage -ot -strict -of -b -mask -expand -outsize -tr -r -unscale -scale -exponent -srcwin -epo -eco -projwin -projwin_srs -a_srs -a_ullr -a_nodata -gcp -mo -q -sds -co -stats -norat -oo --version --license --formats --format --optfile --config --debug --pause --locale "
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  tool=${COMP_WORDS[0]}
+  case "$prev" in
+    -ot)
+      key_list="Byte Int16 UInt16 UInt32 Int32 Float32 Float64 CInt16 CInt32 CFloat32 CFloat64"
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      ;;
+    -of)
+      key_list="$( $tool --formats | tail -n +2 | cut -f 3 -d ' ')"
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      ;;
+    --format)
+      key_list="$( $tool --formats | tail -n +2 | cut -f 3 -d ' ')"
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdal_translate gdal_translate
+_gdalwarp()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list="--help-general --formats -s_srs -t_srs -to -order -tps -rpc -geoloc -et -refine_gcps -te -tr -tap -ts -ovr -wo -ot -wt -srcnodata -dstnodata -dstalpha -r -wm -multi -q -cutline -cl -cwhere -csql -cblend -crop_to_cutline -of -co -overwrite -nomd -cvmd -setci -oo -doo --version --license --format --optfile --config --debug --pause --locale "
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  tool=${COMP_WORDS[0]}
+  case "$prev" in
+    -ot)
+      key_list="Byte Int16 UInt16 UInt32 Int32 Float32 Float64 CInt16 CInt32 CFloat32 CFloat64"
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      ;;
+    -of)
+      key_list="$( $tool --formats | tail -n +2 | cut -f 3 -d ' ')"
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      ;;
+    --format)
+      key_list="$( $tool --formats | tail -n +2 | cut -f 3 -d ' ')"
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _gdalwarp gdalwarp
+_ogr2ogr()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list="--help-general -skipfailures -append -update -select -where -progress -sql -dialect -preserve_fid -fid -spat -spat_srs -geomfield -a_srs -t_srs -s_srs -f -overwrite -dsco -lco -nln -nlt -dim --version --license --formats --format --optfile --config --debug --pause --locale "
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  tool=${COMP_WORDS[0]/ogrtindex/ogr2ogr}
+  case "$prev" in
+    -f)
+      key_list="$( $tool --formats | tail -n +2 | grep -o -E '"[^"]+"' | sed 's/\ /__/')"
+      for iter in $key_list; do
+        if [[ $iter =~ ^$cur ]]; then
+          COMPREPLY+=( "${iter//__/ }" )
+        fi
+      done
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _ogr2ogr ogr2ogr
+_ogrinfo()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list="--help-general -ro -q -where -spat -geomfield -fid -sql -dialect -al -so -fields=YES -fields=NO -geom=YES -geom=NO -geom=SUMMARY -formats -oo -nomd -listmdd -mdd -nocount -noextent --version --license --formats --format --optfile --config --debug --pause --locale "
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _ogrinfo ogrinfo
+_ogrlineref()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list="--help-general -progress -quiet -f -dsco -lco -create -l -ln -lf -p -pn -pm -pf -r -rn -o -on -of -s -get_pos -x -y -get_coord -m -get_subline -mb -me --version --license --formats --format --optfile --config --debug --pause --locale "
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  tool=${COMP_WORDS[0]/ogrtindex/ogr2ogr}
+  case "$prev" in
+    -f)
+      key_list="$( $tool --formats | tail -n +2 | grep -o -E '"[^"]+"' | sed 's/\ /__/')"
+      for iter in $key_list; do
+        if [[ $iter =~ ^$cur ]]; then
+          COMPREPLY+=( "${iter//__/ }" )
+        fi
+      done
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _ogrlineref ogrlineref
+_ogrtindex()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list="-lnum -lname -f -write_absolute_path -skip_different_projection -accept_different_schemas "
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  tool=${COMP_WORDS[0]/ogrtindex/ogr2ogr}
+  case "$prev" in
+    -f)
+      key_list="$( $tool --formats | tail -n +2 | grep -o -E '"[^"]+"' | sed 's/\ /__/')"
+      for iter in $key_list; do
+        if [[ $iter =~ ^$cur ]]; then
+          COMPREPLY+=( "${iter//__/ }" )
+        fi
+      done
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _ogrtindex ogrtindex
diff --git a/scripts/typos_whitelist.txt b/scripts/typos_whitelist.txt
new file mode 100644
index 0000000..be2b5c7
--- /dev/null
+++ b/scripts/typos_whitelist.txt
@@ -0,0 +1,39 @@
+    // FIXME: is it a typo here or in IRIS itself: Perspective or Prespective ?
+    "Prespective from geosync","Equidistant cylindrical","Gnomonic",
+   /* 160 */ {"Bas_St_Wol", "Untergrenze strat. Bew|lkung", "hft", UC_NONE},
+   /* 161 */ {"Bas_St_Wol", "Untergrenze strat. Bew|lkung", "hPa", UC_NONE},
+   /* 164 */ {"Top_St_Wol", "Obergrenze strat. Bew|lkung", "hft", UC_NONE},
+   /* 165 */ {"Top_St_Wol", "Obergrenze strat. Bew|lkung", "hPa", UC_NONE},
+              "Icing Regime 1.Guess(1=gen,2=conv,3=strat,4=freez)", "1",
+              "Icing Regime(1=general,2=convect,3=strat,4=freez)", "1",
+ * The generated swig_type_info structures are assigned staticly to an initial 
+ * The generated swig_type_info structures are assigned staticly to an initial
+            YUR = 0.0;
+            YUR = oES.YUR;
+        double YUR;
+    l_segment->YUR = seg_data.GetDouble(nPos+215, 22);
+    seg_data.Put(psOrbit->YUR,nPos+215,22,"%22.14f");
+/* Putting statics in headers is trouble. */
+See COMMITERS file. 
+  /* When multiple interpeters are used, a module could have already been initialized in
+    const char* pszNAM = record->GetStringSubfield("DSI", 0, "NAM", 0);
+                    const char* pszNAM = record->GetStringSubfield("FDR", iFDRFieldInstance++, "NAM", 0);
+                                                "PRT!NAM",
+    sizeOfFields[nFields] += WriteSubFieldStr(fd, osBaseFileName, 8); /* NAM */
+    sizeOfFields[nFields] += WriteSubFieldStr(fd, osNAM.c_str(), 8); /* NAM */
+                                                  "NAM!STR!PRT!SWO!SWA!NEO!NEA",
+        sizeOfFields[nFields] += WriteSubFieldStr(fd, osBaseFileName, 8); /* NAM */
+      {136, "Socialist Republic of Viet Nam"},
+		double	eps[NANGLES], ua, va, ang, epsa;
+				ang = uv2ang(ua, va);
+				i = (int) ang;
+				epsa = fabs(ang - (i+.5));
+                "     UN=Metres,SD=HHWLT,DX=2.500000,DY=2.500000\n");
+        pszUnitsPer = CPLGetXMLValue( psSrcXML, "metresPerUnit", NULL );
+    {"kilometre",    /* 15 */ 12,  13,  1000.0},
+                    oSRS.SetLinearUnits( "kilometre", 1000.0 );
+{ "kilometre", SRS_UL_KILOMETER_CONV, "km" }, // Leave as 'kilometre' instead of SRS_UL_KILOMETER due to historical usage
+            passport.stMapDescription.eUnitInPlan = SXF_COORD_MU_CENTIMETRE;
+            passport.stMapDescription.eUnitInPlan = SXF_COORD_MU_MILLIMETRE;
+    SXF_COORD_MU_CENTIMETRE,
+    SXF_COORD_MU_MILLIMETRE,
diff --git a/scripts/vce2008_wine/nmake_vce2008.local b/scripts/vce2008_wine/nmake_vce2008.local
index 7eecf19..8c248a9 100644
--- a/scripts/vce2008_wine/nmake_vce2008.local
+++ b/scripts/vce2008_wine/nmake_vce2008.local
@@ -13,7 +13,7 @@ GEOS_LIB     = c:\release-1500\lib\geos_c.lib
 # The cURL library is used for WCS, WMS, GeoJSON, SRS call importFromUrl(), WFS, GFT, CouchDB, /vsicurl/ etc.
 CURL_DIR=c:\release-1500
 CURL_INC = -I$(CURL_DIR)/include
-# Uncoment following line to use libcurl as dynamic library
+# Uncomment following line to use libcurl as dynamic library
 CURL_LIB = $(CURL_DIR)/lib/libcurl_imp.lib wsock32.lib wldap32.lib winmm.lib
 
 # Uncomment for Expat support (required for KML, GPX and GeoRSS read support).
@@ -55,7 +55,7 @@ OPENJPEG_ENABLED = YES
 OPENJPEG_CFLAGS = -Ic:\release-1500\include
 OPENJPEG_LIB = c:\release-1500\lib\openjp2.lib
 
-# Uncomment for libxml2 support (for cpl_xml_validate.cpp routines, used optionaly by the GML driver)
+# Uncomment for libxml2 support (for cpl_xml_validate.cpp routines, used optionally by the GML driver)
 LIBXML2_INC = -Ic:\release-1500\include
 LIBXML2_LIB = c:\release-1500\lib\libxml2.lib
 
diff --git a/swig/GNUmakefile b/swig/GNUmakefile
index 0c0fe23..cb5ca46 100644
--- a/swig/GNUmakefile
+++ b/swig/GNUmakefile
@@ -14,7 +14,7 @@ default: generate
 # The dist target should generate all the wrapper files for all supported
 # language bindings.  This should be called by the top level distribution
 # maker script prior to bundling up the source.  It eliminates the installer
-# from having the proper version of swig installled.
+# from having the proper version of swig installed.
 dist: generate
 
 clean:
diff --git a/swig/SWIGmake.base b/swig/SWIGmake.base
index 78300bd..e5bd8f6 100644
--- a/swig/SWIGmake.base
+++ b/swig/SWIGmake.base
@@ -3,7 +3,7 @@ SWIG = swig
 SWIGARGS = -Wall -I../include -I../include/$(BINDING) -I../include/$(BINDING)/docs
 SWIGOUTPUTDIR=
 
-WRAPPERS = gdal_wrap.cpp gdalconst_wrap.c ogr_wrap.cpp osr_wrap.cpp
+WRAPPERS = gdal_wrap.cpp gdalconst_wrap.c ogr_wrap.cpp osr_wrap.cpp gnm_wrap.cpp
 
 gdal_wrap.cpp: ../include/gdal.i ../include/MajorObject.i ../include/Driver.i ../include/Dataset.i ../include/Band.i ../include/ColorTable.i ../include/cpl.i ../include/$(BINDING)/gdal_$(BINDING).i ../include/$(BINDING)/typemaps_$(BINDING).i
 	$(SWIG) $(SWIGARGS) $(SWIGDEFINES) -I$(GDAL_ROOT) -c++ -$(BINDING) -o $(SWIGOUTPUTDIR)$@ ../include/gdal.i
@@ -16,3 +16,6 @@ ogr_wrap.cpp:  ../include/ogr.i ../include/$(BINDING)/ogr_$(BINDING).i ../includ
 
 osr_wrap.cpp:  ../include/osr.i ../include/$(BINDING)/osr_$(BINDING).i ../include/$(BINDING)/typemaps_$(BINDING).i
 	$(SWIG) $(SWIGARGS) $(SWIGDEFINES) -I$(GDAL_ROOT) -c++ -$(BINDING) -o $(SWIGOUTPUTDIR)$@ ../include/osr.i
+
+gnm_wrap.cpp:  ../include/gnm.i ../include/MajorObject.i ../include/Dataset.i ../include/$(BINDING)/typemaps_$(BINDING).i
+	$(SWIG) $(SWIGARGS) $(SWIGDEFINES) -I$(GDAL_ROOT) -c++ -$(BINDING) -o $(SWIGOUTPUTDIR)$@ ../include/gnm.i
diff --git a/swig/csharp/const/GdalConst.cs b/swig/csharp/const/GdalConst.cs
index 69ba2f3..b18d3fa 100644
--- a/swig/csharp/const/GdalConst.cs
+++ b/swig/csharp/const/GdalConst.cs
@@ -88,6 +88,7 @@ public class GdalConst {
   public static readonly int OF_ALL = GdalConstPINVOKE.OF_ALL_get();
   public static readonly int OF_RASTER = GdalConstPINVOKE.OF_RASTER_get();
   public static readonly int OF_VECTOR = GdalConstPINVOKE.OF_VECTOR_get();
+  public static readonly int OF_GNM = GdalConstPINVOKE.OF_GNM_get();
   public static readonly int OF_READONLY = GdalConstPINVOKE.OF_READONLY_get();
   public static readonly int OF_UPDATE = GdalConstPINVOKE.OF_UPDATE_get();
   public static readonly int OF_SHARED = GdalConstPINVOKE.OF_SHARED_get();
diff --git a/swig/csharp/const/GdalConstPINVOKE.cs b/swig/csharp/const/GdalConstPINVOKE.cs
index 30deb30..8b4285e 100644
--- a/swig/csharp/const/GdalConstPINVOKE.cs
+++ b/swig/csharp/const/GdalConstPINVOKE.cs
@@ -417,6 +417,9 @@ class GdalConstPINVOKE {
   [DllImport("gdalconst_wrap", EntryPoint="CSharp_OF_VECTOR_get")]
   public static extern int OF_VECTOR_get();
 
+  [DllImport("gdalconst_wrap", EntryPoint="CSharp_OF_GNM_get")]
+  public static extern int OF_GNM_get();
+
   [DllImport("gdalconst_wrap", EntryPoint="CSharp_OF_READONLY_get")]
   public static extern int OF_READONLY_get();
 
diff --git a/swig/csharp/const/gdalconst_wrap.c b/swig/csharp/const/gdalconst_wrap.c
index edc1f86..afea243 100644
--- a/swig/csharp/const/gdalconst_wrap.c
+++ b/swig/csharp/const/gdalconst_wrap.c
@@ -1026,6 +1026,16 @@ SWIGEXPORT int SWIGSTDCALL CSharp_OF_VECTOR_get() {
 }
 
 
+SWIGEXPORT int SWIGSTDCALL CSharp_OF_GNM_get() {
+  int jresult ;
+  int result;
+  
+  result = (int)(GDAL_OF_GNM);
+  jresult = result; 
+  return jresult;
+}
+
+
 SWIGEXPORT int SWIGSTDCALL CSharp_OF_READONLY_get() {
   int jresult ;
   int result;
diff --git a/swig/csharp/csharp.opt b/swig/csharp/csharp.opt
index da9518b..478be5c 100644
--- a/swig/csharp/csharp.opt
+++ b/swig/csharp/csharp.opt
@@ -1,7 +1,7 @@
 #
-# csharp.opt - C# specific user definied options
+# csharp.opt - C# specific user defined options
 #
-# $Id: csharp.opt 13439 2007-12-21 21:40:03Z tamas $
+# $Id: csharp.opt 31793 2015-11-27 18:24:25Z goatbar $
 #
 
 #Uncomment the following line if you want to compile with MONO on windows
diff --git a/swig/csharp/gdal/AsyncReader.cs b/swig/csharp/gdal/AsyncReader.cs
index a70063f..1011cf1 100644
--- a/swig/csharp/gdal/AsyncReader.cs
+++ b/swig/csharp/gdal/AsyncReader.cs
@@ -15,7 +15,7 @@ public class AsyncReader : IDisposable {
   private HandleRef swigCPtr;
   protected bool swigCMemOwn;
   protected object swigParentRef;
-  
+
   protected static object ThisOwn_true() { return null; }
   protected object ThisOwn_false() { return this; }
 
diff --git a/swig/csharp/gdal/Band.cs b/swig/csharp/gdal/Band.cs
index bc5a31e..5b7905c 100644
--- a/swig/csharp/gdal/Band.cs
+++ b/swig/csharp/gdal/Band.cs
@@ -81,7 +81,7 @@ public class Band : MajorObject {
       GC.KeepAlive(this);
       return retval;
   }
-  
+
 /*@SWIG@*/
 /*! Sixteen bit signed integer */ /*@SWIG:../include/csharp/gdal_csharp.i,52,%rasterio_functions@*/
  public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, short[] buffer, int buf_xSize, int buf_ySize, int pixelSpace, int lineSpace) {
@@ -106,7 +106,7 @@ public class Band : MajorObject {
       GC.KeepAlive(this);
       return retval;
   }
-  
+
 /*@SWIG@*/
 /*! Thirty two bit signed integer */ /*@SWIG:../include/csharp/gdal_csharp.i,52,%rasterio_functions@*/
  public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, int[] buffer, int buf_xSize, int buf_ySize, int pixelSpace, int lineSpace) {
@@ -131,7 +131,7 @@ public class Band : MajorObject {
       GC.KeepAlive(this);
       return retval;
   }
-  
+
 /*@SWIG@*/
 /*! Thirty two bit floating point */ /*@SWIG:../include/csharp/gdal_csharp.i,52,%rasterio_functions@*/
  public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, float[] buffer, int buf_xSize, int buf_ySize, int pixelSpace, int lineSpace) {
@@ -156,7 +156,7 @@ public class Band : MajorObject {
       GC.KeepAlive(this);
       return retval;
   }
-  
+
 /*@SWIG@*/
 /*! Sixty four bit floating point */ /*@SWIG:../include/csharp/gdal_csharp.i,52,%rasterio_functions@*/
  public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, double[] buffer, int buf_xSize, int buf_ySize, int pixelSpace, int lineSpace) {
@@ -181,7 +181,7 @@ public class Band : MajorObject {
       GC.KeepAlive(this);
       return retval;
   }
-  
+
 /*@SWIG@*/
   public int XSize {
     get {
@@ -260,6 +260,12 @@ public class Band : MajorObject {
     return ret;
   }
 
+  public CPLErr DeleteNoDataValue() {
+    CPLErr ret = (CPLErr)GdalPINVOKE.Band_DeleteNoDataValue(swigCPtr);
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public string GetUnitType() {
     string ret = GdalPINVOKE.Band_GetUnitType(swigCPtr);
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
@@ -282,7 +288,7 @@ public class Band : MajorObject {
                 ++count;
         }
         string[] ret = new string[count];
-        if (count > 0) {       
+        if (count > 0) {
 	        for(int cx = 0; cx < count; cx++) {
                 objPtr = System.Runtime.InteropServices.Marshal.ReadIntPtr(cPtr, cx * System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)));
                 ret[cx]= (objPtr == IntPtr.Zero) ? null : System.Runtime.InteropServices.Marshal.PtrToStringAnsi(objPtr);
@@ -481,7 +487,7 @@ public class Band : MajorObject {
                 ++count;
         }
         string[] ret = new string[count];
-        if (count > 0) {       
+        if (count > 0) {
 	        for(int cx = 0; cx < count; cx++) {
                 objPtr = System.Runtime.InteropServices.Marshal.ReadIntPtr(cPtr, cx * System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)));
                 ret[cx]= (objPtr == IntPtr.Zero) ? null : System.Runtime.InteropServices.Marshal.PtrToStringAnsi(objPtr);
diff --git a/swig/csharp/gdal/ColorEntry.cs b/swig/csharp/gdal/ColorEntry.cs
index e1ecfb9..0a800f6 100644
--- a/swig/csharp/gdal/ColorEntry.cs
+++ b/swig/csharp/gdal/ColorEntry.cs
@@ -15,7 +15,7 @@ public class ColorEntry : IDisposable {
   private HandleRef swigCPtr;
   protected bool swigCMemOwn;
   protected object swigParentRef;
-  
+
   protected static object ThisOwn_true() { return null; }
   protected object ThisOwn_false() { return this; }
 
diff --git a/swig/csharp/gdal/ColorTable.cs b/swig/csharp/gdal/ColorTable.cs
index ee7467e..ce77569 100644
--- a/swig/csharp/gdal/ColorTable.cs
+++ b/swig/csharp/gdal/ColorTable.cs
@@ -15,7 +15,7 @@ public class ColorTable : IDisposable {
   private HandleRef swigCPtr;
   protected bool swigCMemOwn;
   protected object swigParentRef;
-  
+
   protected static object ThisOwn_true() { return null; }
   protected object ThisOwn_false() { return this; }
 
diff --git a/swig/csharp/gdal/Dataset.cs b/swig/csharp/gdal/Dataset.cs
index afe8ec1..458c1f3 100644
--- a/swig/csharp/gdal/Dataset.cs
+++ b/swig/csharp/gdal/Dataset.cs
@@ -63,12 +63,12 @@ public class Dataset : MajorObject {
     }
   }
 /*! Eight bit unsigned integer */ /*@SWIG:../include/csharp/gdal_csharp.i,93,%ds_rasterio_functions@*/
- public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, byte[] buffer, int buf_xSize, int buf_ySize, 
+ public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, byte[] buffer, int buf_xSize, int buf_ySize,
      int bandCount, int[] bandMap, int pixelSpace, int lineSpace, int bandSpace) {
       CPLErr retval;
       GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
       try {
-          retval = ReadRaster(xOff, yOff, xSize, ySize, handle.AddrOfPinnedObject(), buf_xSize, buf_ySize, DataType.GDT_Byte, 
+          retval = ReadRaster(xOff, yOff, xSize, ySize, handle.AddrOfPinnedObject(), buf_xSize, buf_ySize, DataType.GDT_Byte,
                                bandCount, bandMap, pixelSpace, lineSpace, bandSpace);
       } finally {
           handle.Free();
@@ -89,15 +89,15 @@ public class Dataset : MajorObject {
       GC.KeepAlive(this);
       return retval;
   }
-  
+
 /*@SWIG@*/
 /*! Sixteen bit signed integer */ /*@SWIG:../include/csharp/gdal_csharp.i,93,%ds_rasterio_functions@*/
- public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, short[] buffer, int buf_xSize, int buf_ySize, 
+ public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, short[] buffer, int buf_xSize, int buf_ySize,
      int bandCount, int[] bandMap, int pixelSpace, int lineSpace, int bandSpace) {
       CPLErr retval;
       GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
       try {
-          retval = ReadRaster(xOff, yOff, xSize, ySize, handle.AddrOfPinnedObject(), buf_xSize, buf_ySize, DataType.GDT_Int16, 
+          retval = ReadRaster(xOff, yOff, xSize, ySize, handle.AddrOfPinnedObject(), buf_xSize, buf_ySize, DataType.GDT_Int16,
                                bandCount, bandMap, pixelSpace, lineSpace, bandSpace);
       } finally {
           handle.Free();
@@ -118,15 +118,15 @@ public class Dataset : MajorObject {
       GC.KeepAlive(this);
       return retval;
   }
-  
+
 /*@SWIG@*/
 /*! Thirty two bit signed integer */ /*@SWIG:../include/csharp/gdal_csharp.i,93,%ds_rasterio_functions@*/
- public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, int[] buffer, int buf_xSize, int buf_ySize, 
+ public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, int[] buffer, int buf_xSize, int buf_ySize,
      int bandCount, int[] bandMap, int pixelSpace, int lineSpace, int bandSpace) {
       CPLErr retval;
       GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
       try {
-          retval = ReadRaster(xOff, yOff, xSize, ySize, handle.AddrOfPinnedObject(), buf_xSize, buf_ySize, DataType.GDT_Int32, 
+          retval = ReadRaster(xOff, yOff, xSize, ySize, handle.AddrOfPinnedObject(), buf_xSize, buf_ySize, DataType.GDT_Int32,
                                bandCount, bandMap, pixelSpace, lineSpace, bandSpace);
       } finally {
           handle.Free();
@@ -147,15 +147,15 @@ public class Dataset : MajorObject {
       GC.KeepAlive(this);
       return retval;
   }
-  
+
 /*@SWIG@*/
 /*! Thirty two bit floating point */ /*@SWIG:../include/csharp/gdal_csharp.i,93,%ds_rasterio_functions@*/
- public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, float[] buffer, int buf_xSize, int buf_ySize, 
+ public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, float[] buffer, int buf_xSize, int buf_ySize,
      int bandCount, int[] bandMap, int pixelSpace, int lineSpace, int bandSpace) {
       CPLErr retval;
       GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
       try {
-          retval = ReadRaster(xOff, yOff, xSize, ySize, handle.AddrOfPinnedObject(), buf_xSize, buf_ySize, DataType.GDT_Float32, 
+          retval = ReadRaster(xOff, yOff, xSize, ySize, handle.AddrOfPinnedObject(), buf_xSize, buf_ySize, DataType.GDT_Float32,
                                bandCount, bandMap, pixelSpace, lineSpace, bandSpace);
       } finally {
           handle.Free();
@@ -176,15 +176,15 @@ public class Dataset : MajorObject {
       GC.KeepAlive(this);
       return retval;
   }
-  
+
 /*@SWIG@*/
 /*! Sixty four bit floating point */ /*@SWIG:../include/csharp/gdal_csharp.i,93,%ds_rasterio_functions@*/
- public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, double[] buffer, int buf_xSize, int buf_ySize, 
+ public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, double[] buffer, int buf_xSize, int buf_ySize,
      int bandCount, int[] bandMap, int pixelSpace, int lineSpace, int bandSpace) {
       CPLErr retval;
       GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
       try {
-          retval = ReadRaster(xOff, yOff, xSize, ySize, handle.AddrOfPinnedObject(), buf_xSize, buf_ySize, DataType.GDT_Float64, 
+          retval = ReadRaster(xOff, yOff, xSize, ySize, handle.AddrOfPinnedObject(), buf_xSize, buf_ySize, DataType.GDT_Float64,
                                bandCount, bandMap, pixelSpace, lineSpace, bandSpace);
       } finally {
           handle.Free();
@@ -205,14 +205,14 @@ public class Dataset : MajorObject {
       GC.KeepAlive(this);
       return retval;
   }
-  
+
 /*@SWIG@*/
 
 public int BuildOverviews( string resampling, int[] overviewlist, Gdal.GDALProgressFuncDelegate callback, string callback_data) {
       int retval;
       if (overviewlist.Length <= 0)
         throw new ArgumentException("overviewlist size is small (BuildOverviews)");
-        
+
       IntPtr ptr = Marshal.AllocHGlobal(overviewlist.Length * Marshal.SizeOf(overviewlist[0]));
       try {
           Marshal.Copy(overviewlist, 0, ptr, overviewlist.Length);
@@ -226,7 +226,7 @@ public int BuildOverviews( string resampling, int[] overviewlist, Gdal.GDALProgr
 public int BuildOverviews( string resampling, int[] overviewlist) {
       return BuildOverviews( resampling, overviewlist, null, null);
   }
-  
+
 public GCP[] GetGCPs() {
       /*hello*/
       IntPtr cPtr = __GetGCPs();
@@ -241,7 +241,7 @@ public GCP[] GetGCPs() {
       GC.KeepAlive(this);
       return ret;
   }
-  
+
 public CPLErr SetGCPs(GCP[] pGCPs, string pszGCPProjection) {
      CPLErr ret = 0;
      if (pGCPs != null && pGCPs.Length > 0)
@@ -249,11 +249,11 @@ public CPLErr SetGCPs(GCP[] pGCPs, string pszGCPProjection) {
          IntPtr cPtr = __AllocCArray_GDAL_GCP(pGCPs.Length);
          if (cPtr == IntPtr.Zero)
             throw new ApplicationException("Error allocating CArray with __AllocCArray_GDAL_GCP");
-            
+
          try {
              for (int i=0; i < pGCPs.Length; i++)
                 __WriteCArrayItem_GDAL_GCP(cPtr, i, pGCPs[i]);
-             
+
              ret = __SetGCPs(pGCPs.Length, cPtr, pszGCPProjection);
          }
          finally
@@ -376,7 +376,7 @@ public CPLErr SetGCPs(GCP[] pGCPs, string pszGCPProjection) {
                 ++count;
         }
         string[] ret = new string[count];
-        if (count > 0) {       
+        if (count > 0) {
 	        for(int cx = 0; cx < count; cx++) {
                 objPtr = System.Runtime.InteropServices.Marshal.ReadIntPtr(cPtr, cx * System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)));
                 ret[cx]= (objPtr == IntPtr.Zero) ? null : System.Runtime.InteropServices.Marshal.PtrToStringAnsi(objPtr);
diff --git a/swig/csharp/gdal/GCP.cs b/swig/csharp/gdal/GCP.cs
index ff5f0b4..102f1ea 100644
--- a/swig/csharp/gdal/GCP.cs
+++ b/swig/csharp/gdal/GCP.cs
@@ -15,7 +15,7 @@ public class GCP : IDisposable {
   private HandleRef swigCPtr;
   protected bool swigCMemOwn;
   protected object swigParentRef;
-  
+
   protected static object ThisOwn_true() { return null; }
   protected object ThisOwn_false() { return this; }
 
diff --git a/swig/csharp/gdal/GDALBuildVRTOptions.cs b/swig/csharp/gdal/GDALBuildVRTOptions.cs
new file mode 100644
index 0000000..04e767e
--- /dev/null
+++ b/swig/csharp/gdal/GDALBuildVRTOptions.cs
@@ -0,0 +1,77 @@
+/* ----------------------------------------------------------------------------
+ * This file was automatically generated by SWIG (http://www.swig.org).
+ * Version 2.0.12
+ *
+ * Do not make changes to this file unless you know what you are doing--modify
+ * the SWIG interface file instead.
+ * ----------------------------------------------------------------------------- */
+
+namespace OSGeo.GDAL {
+
+using System;
+using System.Runtime.InteropServices;
+
+public class GDALBuildVRTOptions : IDisposable {
+  private HandleRef swigCPtr;
+  protected bool swigCMemOwn;
+  protected object swigParentRef;
+
+  protected static object ThisOwn_true() { return null; }
+  protected object ThisOwn_false() { return this; }
+
+  public GDALBuildVRTOptions(IntPtr cPtr, bool cMemoryOwn, object parent) {
+    swigCMemOwn = cMemoryOwn;
+    swigParentRef = parent;
+    swigCPtr = new HandleRef(this, cPtr);
+  }
+
+  public static HandleRef getCPtr(GDALBuildVRTOptions obj) {
+    return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr;
+  }
+  public static HandleRef getCPtrAndDisown(GDALBuildVRTOptions obj, object parent) {
+    if (obj != null)
+    {
+      obj.swigCMemOwn = false;
+      obj.swigParentRef = parent;
+      return obj.swigCPtr;
+    }
+    else
+    {
+      return new HandleRef(null, IntPtr.Zero);
+    }
+  }
+  public static HandleRef getCPtrAndSetReference(GDALBuildVRTOptions obj, object parent) {
+    if (obj != null)
+    {
+      obj.swigParentRef = parent;
+      return obj.swigCPtr;
+    }
+    else
+    {
+      return new HandleRef(null, IntPtr.Zero);
+    }
+  }
+
+  ~GDALBuildVRTOptions() {
+    Dispose();
+  }
+
+  public virtual void Dispose() {
+  lock(this) {
+      if(swigCPtr.Handle != IntPtr.Zero && swigCMemOwn) {
+        swigCMemOwn = false;
+        GdalPINVOKE.delete_GDALBuildVRTOptions(swigCPtr);
+      }
+      swigCPtr = new HandleRef(null, IntPtr.Zero);
+      swigParentRef = null;
+      GC.SuppressFinalize(this);
+    }
+  }
+
+  public GDALBuildVRTOptions(string[] options) : this(GdalPINVOKE.new_GDALBuildVRTOptions((options != null)? new GdalPINVOKE.StringListMarshal(options)._ar : null), true, null) {
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+  }
+
+}
+
+}
diff --git a/swig/csharp/gdal/GDALDEMProcessingOptions.cs b/swig/csharp/gdal/GDALDEMProcessingOptions.cs
new file mode 100644
index 0000000..df6af03
--- /dev/null
+++ b/swig/csharp/gdal/GDALDEMProcessingOptions.cs
@@ -0,0 +1,77 @@
+/* ----------------------------------------------------------------------------
+ * This file was automatically generated by SWIG (http://www.swig.org).
+ * Version 2.0.12
+ *
+ * Do not make changes to this file unless you know what you are doing--modify
+ * the SWIG interface file instead.
+ * ----------------------------------------------------------------------------- */
+
+namespace OSGeo.GDAL {
+
+using System;
+using System.Runtime.InteropServices;
+
+public class GDALDEMProcessingOptions : IDisposable {
+  private HandleRef swigCPtr;
+  protected bool swigCMemOwn;
+  protected object swigParentRef;
+
+  protected static object ThisOwn_true() { return null; }
+  protected object ThisOwn_false() { return this; }
+
+  public GDALDEMProcessingOptions(IntPtr cPtr, bool cMemoryOwn, object parent) {
+    swigCMemOwn = cMemoryOwn;
+    swigParentRef = parent;
+    swigCPtr = new HandleRef(this, cPtr);
+  }
+
+  public static HandleRef getCPtr(GDALDEMProcessingOptions obj) {
+    return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr;
+  }
+  public static HandleRef getCPtrAndDisown(GDALDEMProcessingOptions obj, object parent) {
+    if (obj != null)
+    {
+      obj.swigCMemOwn = false;
+      obj.swigParentRef = parent;
+      return obj.swigCPtr;
+    }
+    else
+    {
+      return new HandleRef(null, IntPtr.Zero);
+    }
+  }
+  public static HandleRef getCPtrAndSetReference(GDALDEMProcessingOptions obj, object parent) {
+    if (obj != null)
+    {
+      obj.swigParentRef = parent;
+      return obj.swigCPtr;
+    }
+    else
+    {
+      return new HandleRef(null, IntPtr.Zero);
+    }
+  }
+
+  ~GDALDEMProcessingOptions() {
+    Dispose();
+  }
+
+  public virtual void Dispose() {
+  lock(this) {
+      if(swigCPtr.Handle != IntPtr.Zero && swigCMemOwn) {
+        swigCMemOwn = false;
+        GdalPINVOKE.delete_GDALDEMProcessingOptions(swigCPtr);
+      }
+      swigCPtr = new HandleRef(null, IntPtr.Zero);
+      swigParentRef = null;
+      GC.SuppressFinalize(this);
+    }
+  }
+
+  public GDALDEMProcessingOptions(string[] options) : this(GdalPINVOKE.new_GDALDEMProcessingOptions((options != null)? new GdalPINVOKE.StringListMarshal(options)._ar : null), true, null) {
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+  }
+
+}
+
+}
diff --git a/swig/csharp/gdal/GDALGridOptions.cs b/swig/csharp/gdal/GDALGridOptions.cs
new file mode 100644
index 0000000..27b59fc
--- /dev/null
+++ b/swig/csharp/gdal/GDALGridOptions.cs
@@ -0,0 +1,77 @@
+/* ----------------------------------------------------------------------------
+ * This file was automatically generated by SWIG (http://www.swig.org).
+ * Version 2.0.12
+ *
+ * Do not make changes to this file unless you know what you are doing--modify
+ * the SWIG interface file instead.
+ * ----------------------------------------------------------------------------- */
+
+namespace OSGeo.GDAL {
+
+using System;
+using System.Runtime.InteropServices;
+
+public class GDALGridOptions : IDisposable {
+  private HandleRef swigCPtr;
+  protected bool swigCMemOwn;
+  protected object swigParentRef;
+
+  protected static object ThisOwn_true() { return null; }
+  protected object ThisOwn_false() { return this; }
+
+  public GDALGridOptions(IntPtr cPtr, bool cMemoryOwn, object parent) {
+    swigCMemOwn = cMemoryOwn;
+    swigParentRef = parent;
+    swigCPtr = new HandleRef(this, cPtr);
+  }
+
+  public static HandleRef getCPtr(GDALGridOptions obj) {
+    return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr;
+  }
+  public static HandleRef getCPtrAndDisown(GDALGridOptions obj, object parent) {
+    if (obj != null)
+    {
+      obj.swigCMemOwn = false;
+      obj.swigParentRef = parent;
+      return obj.swigCPtr;
+    }
+    else
+    {
+      return new HandleRef(null, IntPtr.Zero);
+    }
+  }
+  public static HandleRef getCPtrAndSetReference(GDALGridOptions obj, object parent) {
+    if (obj != null)
+    {
+      obj.swigParentRef = parent;
+      return obj.swigCPtr;
+    }
+    else
+    {
+      return new HandleRef(null, IntPtr.Zero);
+    }
+  }
+
+  ~GDALGridOptions() {
+    Dispose();
+  }
+
+  public virtual void Dispose() {
+  lock(this) {
+      if(swigCPtr.Handle != IntPtr.Zero && swigCMemOwn) {
+        swigCMemOwn = false;
+        GdalPINVOKE.delete_GDALGridOptions(swigCPtr);
+      }
+      swigCPtr = new HandleRef(null, IntPtr.Zero);
+      swigParentRef = null;
+      GC.SuppressFinalize(this);
+    }
+  }
+
+  public GDALGridOptions(string[] options) : this(GdalPINVOKE.new_GDALGridOptions((options != null)? new GdalPINVOKE.StringListMarshal(options)._ar : null), true, null) {
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+  }
+
+}
+
+}
diff --git a/swig/csharp/gdal/GDALInfoOptions.cs b/swig/csharp/gdal/GDALInfoOptions.cs
new file mode 100644
index 0000000..e7653d0
--- /dev/null
+++ b/swig/csharp/gdal/GDALInfoOptions.cs
@@ -0,0 +1,77 @@
+/* ----------------------------------------------------------------------------
+ * This file was automatically generated by SWIG (http://www.swig.org).
+ * Version 2.0.12
+ *
+ * Do not make changes to this file unless you know what you are doing--modify
+ * the SWIG interface file instead.
+ * ----------------------------------------------------------------------------- */
+
+namespace OSGeo.GDAL {
+
+using System;
+using System.Runtime.InteropServices;
+
+public class GDALInfoOptions : IDisposable {
+  private HandleRef swigCPtr;
+  protected bool swigCMemOwn;
+  protected object swigParentRef;
+
+  protected static object ThisOwn_true() { return null; }
+  protected object ThisOwn_false() { return this; }
+
+  public GDALInfoOptions(IntPtr cPtr, bool cMemoryOwn, object parent) {
+    swigCMemOwn = cMemoryOwn;
+    swigParentRef = parent;
+    swigCPtr = new HandleRef(this, cPtr);
+  }
+
+  public static HandleRef getCPtr(GDALInfoOptions obj) {
+    return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr;
+  }
+  public static HandleRef getCPtrAndDisown(GDALInfoOptions obj, object parent) {
+    if (obj != null)
+    {
+      obj.swigCMemOwn = false;
+      obj.swigParentRef = parent;
+      return obj.swigCPtr;
+    }
+    else
+    {
+      return new HandleRef(null, IntPtr.Zero);
+    }
+  }
+  public static HandleRef getCPtrAndSetReference(GDALInfoOptions obj, object parent) {
+    if (obj != null)
+    {
+      obj.swigParentRef = parent;
+      return obj.swigCPtr;
+    }
+    else
+    {
+      return new HandleRef(null, IntPtr.Zero);
+    }
+  }
+
+  ~GDALInfoOptions() {
+    Dispose();
+  }
+
+  public virtual void Dispose() {
+  lock(this) {
+      if(swigCPtr.Handle != IntPtr.Zero && swigCMemOwn) {
+        swigCMemOwn = false;
+        GdalPINVOKE.delete_GDALInfoOptions(swigCPtr);
+      }
+      swigCPtr = new HandleRef(null, IntPtr.Zero);
+      swigParentRef = null;
+      GC.SuppressFinalize(this);
+    }
+  }
+
+  public GDALInfoOptions(string[] options) : this(GdalPINVOKE.new_GDALInfoOptions((options != null)? new GdalPINVOKE.StringListMarshal(options)._ar : null), true, null) {
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+  }
+
+}
+
+}
diff --git a/swig/csharp/gdal/GDALNearblackOptions.cs b/swig/csharp/gdal/GDALNearblackOptions.cs
new file mode 100644
index 0000000..5a5a051
--- /dev/null
+++ b/swig/csharp/gdal/GDALNearblackOptions.cs
@@ -0,0 +1,77 @@
+/* ----------------------------------------------------------------------------
+ * This file was automatically generated by SWIG (http://www.swig.org).
+ * Version 2.0.12
+ *
+ * Do not make changes to this file unless you know what you are doing--modify
+ * the SWIG interface file instead.
+ * ----------------------------------------------------------------------------- */
+
+namespace OSGeo.GDAL {
+
+using System;
+using System.Runtime.InteropServices;
+
+public class GDALNearblackOptions : IDisposable {
+  private HandleRef swigCPtr;
+  protected bool swigCMemOwn;
+  protected object swigParentRef;
+
+  protected static object ThisOwn_true() { return null; }
+  protected object ThisOwn_false() { return this; }
+
+  public GDALNearblackOptions(IntPtr cPtr, bool cMemoryOwn, object parent) {
+    swigCMemOwn = cMemoryOwn;
+    swigParentRef = parent;
+    swigCPtr = new HandleRef(this, cPtr);
+  }
+
+  public static HandleRef getCPtr(GDALNearblackOptions obj) {
+    return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr;
+  }
+  public static HandleRef getCPtrAndDisown(GDALNearblackOptions obj, object parent) {
+    if (obj != null)
+    {
+      obj.swigCMemOwn = false;
+      obj.swigParentRef = parent;
+      return obj.swigCPtr;
+    }
+    else
+    {
+      return new HandleRef(null, IntPtr.Zero);
+    }
+  }
+  public static HandleRef getCPtrAndSetReference(GDALNearblackOptions obj, object parent) {
+    if (obj != null)
+    {
+      obj.swigParentRef = parent;
+      return obj.swigCPtr;
+    }
+    else
+    {
+      return new HandleRef(null, IntPtr.Zero);
+    }
+  }
+
+  ~GDALNearblackOptions() {
+    Dispose();
+  }
+
+  public virtual void Dispose() {
+  lock(this) {
+      if(swigCPtr.Handle != IntPtr.Zero && swigCMemOwn) {
+        swigCMemOwn = false;
+        GdalPINVOKE.delete_GDALNearblackOptions(swigCPtr);
+      }
+      swigCPtr = new HandleRef(null, IntPtr.Zero);
+      swigParentRef = null;
+      GC.SuppressFinalize(this);
+    }
+  }
+
+  public GDALNearblackOptions(string[] options) : this(GdalPINVOKE.new_GDALNearblackOptions((options != null)? new GdalPINVOKE.StringListMarshal(options)._ar : null), true, null) {
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+  }
+
+}
+
+}
diff --git a/swig/csharp/gdal/GDALRasterizeOptions.cs b/swig/csharp/gdal/GDALRasterizeOptions.cs
new file mode 100644
index 0000000..a7b270f
--- /dev/null
+++ b/swig/csharp/gdal/GDALRasterizeOptions.cs
@@ -0,0 +1,77 @@
+/* ----------------------------------------------------------------------------
+ * This file was automatically generated by SWIG (http://www.swig.org).
+ * Version 2.0.12
+ *
+ * Do not make changes to this file unless you know what you are doing--modify
+ * the SWIG interface file instead.
+ * ----------------------------------------------------------------------------- */
+
+namespace OSGeo.GDAL {
+
+using System;
+using System.Runtime.InteropServices;
+
+public class GDALRasterizeOptions : IDisposable {
+  private HandleRef swigCPtr;
+  protected bool swigCMemOwn;
+  protected object swigParentRef;
+
+  protected static object ThisOwn_true() { return null; }
+  protected object ThisOwn_false() { return this; }
+
+  public GDALRasterizeOptions(IntPtr cPtr, bool cMemoryOwn, object parent) {
+    swigCMemOwn = cMemoryOwn;
+    swigParentRef = parent;
+    swigCPtr = new HandleRef(this, cPtr);
+  }
+
+  public static HandleRef getCPtr(GDALRasterizeOptions obj) {
+    return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr;
+  }
+  public static HandleRef getCPtrAndDisown(GDALRasterizeOptions obj, object parent) {
+    if (obj != null)
+    {
+      obj.swigCMemOwn = false;
+      obj.swigParentRef = parent;
+      return obj.swigCPtr;
+    }
+    else
+    {
+      return new HandleRef(null, IntPtr.Zero);
+    }
+  }
+  public static HandleRef getCPtrAndSetReference(GDALRasterizeOptions obj, object parent) {
+    if (obj != null)
+    {
+      obj.swigParentRef = parent;
+      return obj.swigCPtr;
+    }
+    else
+    {
+      return new HandleRef(null, IntPtr.Zero);
+    }
+  }
+
+  ~GDALRasterizeOptions() {
+    Dispose();
+  }
+
+  public virtual void Dispose() {
+  lock(this) {
+      if(swigCPtr.Handle != IntPtr.Zero && swigCMemOwn) {
+        swigCMemOwn = false;
+        GdalPINVOKE.delete_GDALRasterizeOptions(swigCPtr);
+      }
+      swigCPtr = new HandleRef(null, IntPtr.Zero);
+      swigParentRef = null;
+      GC.SuppressFinalize(this);
+    }
+  }
+
+  public GDALRasterizeOptions(string[] options) : this(GdalPINVOKE.new_GDALRasterizeOptions((options != null)? new GdalPINVOKE.StringListMarshal(options)._ar : null), true, null) {
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+  }
+
+}
+
+}
diff --git a/swig/csharp/gdal/GDALTranslateOptions.cs b/swig/csharp/gdal/GDALTranslateOptions.cs
new file mode 100644
index 0000000..01a6bd5
--- /dev/null
+++ b/swig/csharp/gdal/GDALTranslateOptions.cs
@@ -0,0 +1,77 @@
+/* ----------------------------------------------------------------------------
+ * This file was automatically generated by SWIG (http://www.swig.org).
+ * Version 2.0.12
+ *
+ * Do not make changes to this file unless you know what you are doing--modify
+ * the SWIG interface file instead.
+ * ----------------------------------------------------------------------------- */
+
+namespace OSGeo.GDAL {
+
+using System;
+using System.Runtime.InteropServices;
+
+public class GDALTranslateOptions : IDisposable {
+  private HandleRef swigCPtr;
+  protected bool swigCMemOwn;
+  protected object swigParentRef;
+
+  protected static object ThisOwn_true() { return null; }
+  protected object ThisOwn_false() { return this; }
+
+  public GDALTranslateOptions(IntPtr cPtr, bool cMemoryOwn, object parent) {
+    swigCMemOwn = cMemoryOwn;
+    swigParentRef = parent;
+    swigCPtr = new HandleRef(this, cPtr);
+  }
+
+  public static HandleRef getCPtr(GDALTranslateOptions obj) {
+    return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr;
+  }
+  public static HandleRef getCPtrAndDisown(GDALTranslateOptions obj, object parent) {
+    if (obj != null)
+    {
+      obj.swigCMemOwn = false;
+      obj.swigParentRef = parent;
+      return obj.swigCPtr;
+    }
+    else
+    {
+      return new HandleRef(null, IntPtr.Zero);
+    }
+  }
+  public static HandleRef getCPtrAndSetReference(GDALTranslateOptions obj, object parent) {
+    if (obj != null)
+    {
+      obj.swigParentRef = parent;
+      return obj.swigCPtr;
+    }
+    else
+    {
+      return new HandleRef(null, IntPtr.Zero);
+    }
+  }
+
+  ~GDALTranslateOptions() {
+    Dispose();
+  }
+
+  public virtual void Dispose() {
+  lock(this) {
+      if(swigCPtr.Handle != IntPtr.Zero && swigCMemOwn) {
+        swigCMemOwn = false;
+        GdalPINVOKE.delete_GDALTranslateOptions(swigCPtr);
+      }
+      swigCPtr = new HandleRef(null, IntPtr.Zero);
+      swigParentRef = null;
+      GC.SuppressFinalize(this);
+    }
+  }
+
+  public GDALTranslateOptions(string[] options) : this(GdalPINVOKE.new_GDALTranslateOptions((options != null)? new GdalPINVOKE.StringListMarshal(options)._ar : null), true, null) {
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+  }
+
+}
+
+}
diff --git a/swig/csharp/gdal/GDALVectorTranslateOptions.cs b/swig/csharp/gdal/GDALVectorTranslateOptions.cs
new file mode 100644
index 0000000..8f037a7
--- /dev/null
+++ b/swig/csharp/gdal/GDALVectorTranslateOptions.cs
@@ -0,0 +1,77 @@
+/* ----------------------------------------------------------------------------
+ * This file was automatically generated by SWIG (http://www.swig.org).
+ * Version 2.0.12
+ *
+ * Do not make changes to this file unless you know what you are doing--modify
+ * the SWIG interface file instead.
+ * ----------------------------------------------------------------------------- */
+
+namespace OSGeo.GDAL {
+
+using System;
+using System.Runtime.InteropServices;
+
+public class GDALVectorTranslateOptions : IDisposable {
+  private HandleRef swigCPtr;
+  protected bool swigCMemOwn;
+  protected object swigParentRef;
+
+  protected static object ThisOwn_true() { return null; }
+  protected object ThisOwn_false() { return this; }
+
+  public GDALVectorTranslateOptions(IntPtr cPtr, bool cMemoryOwn, object parent) {
+    swigCMemOwn = cMemoryOwn;
+    swigParentRef = parent;
+    swigCPtr = new HandleRef(this, cPtr);
+  }
+
+  public static HandleRef getCPtr(GDALVectorTranslateOptions obj) {
+    return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr;
+  }
+  public static HandleRef getCPtrAndDisown(GDALVectorTranslateOptions obj, object parent) {
+    if (obj != null)
+    {
+      obj.swigCMemOwn = false;
+      obj.swigParentRef = parent;
+      return obj.swigCPtr;
+    }
+    else
+    {
+      return new HandleRef(null, IntPtr.Zero);
+    }
+  }
+  public static HandleRef getCPtrAndSetReference(GDALVectorTranslateOptions obj, object parent) {
+    if (obj != null)
+    {
+      obj.swigParentRef = parent;
+      return obj.swigCPtr;
+    }
+    else
+    {
+      return new HandleRef(null, IntPtr.Zero);
+    }
+  }
+
+  ~GDALVectorTranslateOptions() {
+    Dispose();
+  }
+
+  public virtual void Dispose() {
+  lock(this) {
+      if(swigCPtr.Handle != IntPtr.Zero && swigCMemOwn) {
+        swigCMemOwn = false;
+        GdalPINVOKE.delete_GDALVectorTranslateOptions(swigCPtr);
+      }
+      swigCPtr = new HandleRef(null, IntPtr.Zero);
+      swigParentRef = null;
+      GC.SuppressFinalize(this);
+    }
+  }
+
+  public GDALVectorTranslateOptions(string[] options) : this(GdalPINVOKE.new_GDALVectorTranslateOptions((options != null)? new GdalPINVOKE.StringListMarshal(options)._ar : null), true, null) {
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+  }
+
+}
+
+}
diff --git a/swig/csharp/gdal/GDALWarpAppOptions.cs b/swig/csharp/gdal/GDALWarpAppOptions.cs
new file mode 100644
index 0000000..cb09644
--- /dev/null
+++ b/swig/csharp/gdal/GDALWarpAppOptions.cs
@@ -0,0 +1,77 @@
+/* ----------------------------------------------------------------------------
+ * This file was automatically generated by SWIG (http://www.swig.org).
+ * Version 2.0.12
+ *
+ * Do not make changes to this file unless you know what you are doing--modify
+ * the SWIG interface file instead.
+ * ----------------------------------------------------------------------------- */
+
+namespace OSGeo.GDAL {
+
+using System;
+using System.Runtime.InteropServices;
+
+public class GDALWarpAppOptions : IDisposable {
+  private HandleRef swigCPtr;
+  protected bool swigCMemOwn;
+  protected object swigParentRef;
+
+  protected static object ThisOwn_true() { return null; }
+  protected object ThisOwn_false() { return this; }
+
+  public GDALWarpAppOptions(IntPtr cPtr, bool cMemoryOwn, object parent) {
+    swigCMemOwn = cMemoryOwn;
+    swigParentRef = parent;
+    swigCPtr = new HandleRef(this, cPtr);
+  }
+
+  public static HandleRef getCPtr(GDALWarpAppOptions obj) {
+    return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr;
+  }
+  public static HandleRef getCPtrAndDisown(GDALWarpAppOptions obj, object parent) {
+    if (obj != null)
+    {
+      obj.swigCMemOwn = false;
+      obj.swigParentRef = parent;
+      return obj.swigCPtr;
+    }
+    else
+    {
+      return new HandleRef(null, IntPtr.Zero);
+    }
+  }
+  public static HandleRef getCPtrAndSetReference(GDALWarpAppOptions obj, object parent) {
+    if (obj != null)
+    {
+      obj.swigParentRef = parent;
+      return obj.swigCPtr;
+    }
+    else
+    {
+      return new HandleRef(null, IntPtr.Zero);
+    }
+  }
+
+  ~GDALWarpAppOptions() {
+    Dispose();
+  }
+
+  public virtual void Dispose() {
+  lock(this) {
+      if(swigCPtr.Handle != IntPtr.Zero && swigCMemOwn) {
+        swigCMemOwn = false;
+        GdalPINVOKE.delete_GDALWarpAppOptions(swigCPtr);
+      }
+      swigCPtr = new HandleRef(null, IntPtr.Zero);
+      swigParentRef = null;
+      GC.SuppressFinalize(this);
+    }
+  }
+
+  public GDALWarpAppOptions(string[] options) : this(GdalPINVOKE.new_GDALWarpAppOptions((options != null)? new GdalPINVOKE.StringListMarshal(options)._ar : null), true, null) {
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+  }
+
+}
+
+}
diff --git a/swig/csharp/gdal/Gdal.cs b/swig/csharp/gdal/Gdal.cs
index 7f0fe97..76aebab 100644
--- a/swig/csharp/gdal/Gdal.cs
+++ b/swig/csharp/gdal/Gdal.cs
@@ -15,7 +15,7 @@ public class Gdal {
 
   internal class GdalObject : IDisposable {
 	public virtual void Dispose() {
-      
+
     }
   }
   internal static GdalObject theGdalObject = new GdalObject();
@@ -35,21 +35,21 @@ public class Gdal {
   {
     if (str == null)
       return null;
-    
+
     int bytecount = System.Text.Encoding.UTF8.GetMaxByteCount(str.Length);
     byte[] bytes = new byte[bytecount + 1];
     System.Text.Encoding.UTF8.GetBytes(str, 0, str.Length, bytes, 0);
     return bytes;
   }
-  
+
   internal static string Utf8BytesToString(IntPtr pNativeData)
   {
     if (pNativeData == IntPtr.Zero)
         return null;
-        
+
     int length = Marshal.PtrToStringAnsi(pNativeData).Length;
-    byte[] strbuf = new byte[length];  
-    Marshal.Copy(pNativeData, strbuf, 0, length); 
+    byte[] strbuf = new byte[length];
+    Marshal.Copy(pNativeData, strbuf, 0, length);
     return System.Text.Encoding.UTF8.GetString(strbuf);
   }
 
@@ -68,11 +68,11 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
          IntPtr cPtr = __AllocCArray_GDAL_GCP(pGCPs.Length);
          if (cPtr == IntPtr.Zero)
             throw new ApplicationException("Error allocating CArray with __AllocCArray_GDAL_GCP");
-            
-         try {   
+
+         try {
              for (int i=0; i < pGCPs.Length; i++)
                 __WriteCArrayItem_GDAL_GCP(cPtr, i, pGCPs[i]);
-             
+
              ret = GCPsToGeoTransform(pGCPs.Length, cPtr, argout, bApproxOK);
          }
          finally
@@ -82,7 +82,7 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
      }
      return ret;
    }
-   
+
  public static void FileFromMemBuffer(string utf8_path, byte[] bytes) {
      GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
      try {
@@ -171,6 +171,18 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
     return ret;
   }
 
+  public static int VSIGetLastErrorNo() {
+    int ret = GdalPINVOKE.VSIGetLastErrorNo();
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public static string VSIGetLastErrorMsg() {
+    string ret = GdalPINVOKE.VSIGetLastErrorMsg();
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public static void PushFinderLocation(string utf8_path) {
     GdalPINVOKE.PushFinderLocation(Gdal.StringToUtf8Bytes(utf8_path));
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
@@ -192,9 +204,9 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
     return ret;
   }
 
-  public static string[] ReadDir(string utf8_path) {
+  public static string[] ReadDir(string utf8_path, int nMaxFiles) {
         /* %typemap(csout) char** CSL */
-        IntPtr cPtr = GdalPINVOKE.ReadDir(Gdal.StringToUtf8Bytes(utf8_path));
+        IntPtr cPtr = GdalPINVOKE.ReadDir(Gdal.StringToUtf8Bytes(utf8_path), nMaxFiles);
         IntPtr objPtr;
         int count = 0;
         if (cPtr != IntPtr.Zero) {
@@ -202,7 +214,7 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
                 ++count;
         }
         string[] ret = new string[count];
-        if (count > 0) {       
+        if (count > 0) {
 	        for(int cx = 0; cx < count; cx++) {
                 objPtr = System.Runtime.InteropServices.Marshal.ReadIntPtr(cPtr, cx * System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)));
                 ret[cx]= (objPtr == IntPtr.Zero) ? null : System.Runtime.InteropServices.Marshal.PtrToStringAnsi(objPtr);
@@ -225,7 +237,7 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
                 ++count;
         }
         string[] ret = new string[count];
-        if (count > 0) {       
+        if (count > 0) {
 	        for(int cx = 0; cx < count; cx++) {
                 objPtr = System.Runtime.InteropServices.Marshal.ReadIntPtr(cPtr, cx * System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)));
                 ret[cx]= (objPtr == IntPtr.Zero) ? null : System.Runtime.InteropServices.Marshal.PtrToStringAnsi(objPtr);
@@ -291,7 +303,7 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
   }
 
   public static int Rename(string pszOld, string pszNew) {
-    int ret = GdalPINVOKE.Rename(pszOld, pszNew);
+    int ret = GdalPINVOKE.Rename(Gdal.StringToUtf8Bytes(pszOld), Gdal.StringToUtf8Bytes(pszNew));
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
@@ -302,36 +314,65 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
       return ret;
 }
 
-  public static int VSIFCloseL(IntPtr arg0) {
-    int ret = GdalPINVOKE.VSIFCloseL(arg0);
+  public static IntPtr VSIFOpenExL(string utf8_path, string pszMode, int bSetError) {
+      IntPtr ret = GdalPINVOKE.VSIFOpenExL(Gdal.StringToUtf8Bytes(utf8_path), pszMode, bSetError);
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+      return ret;
+}
+
+  public static int VSIFCloseL(IntPtr fp) {
+    int ret = GdalPINVOKE.VSIFCloseL(fp);
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
 
-  public static int VSIFSeekL(IntPtr arg0, int arg1, int arg2) {
-    int ret = GdalPINVOKE.VSIFSeekL(arg0, arg1, arg2);
+  public static int VSIFSeekL(IntPtr fp, int offset, int whence) {
+    int ret = GdalPINVOKE.VSIFSeekL(fp, offset, whence);
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
 
-  public static int VSIFTellL(IntPtr arg0) {
-    int ret = GdalPINVOKE.VSIFTellL(arg0);
+  public static int VSIFTellL(IntPtr fp) {
+    int ret = GdalPINVOKE.VSIFTellL(fp);
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
 
-  public static int VSIFTruncateL(IntPtr arg0, int arg1) {
-    int ret = GdalPINVOKE.VSIFTruncateL(arg0, arg1);
+  public static int VSIFTruncateL(IntPtr fp, int length) {
+    int ret = GdalPINVOKE.VSIFTruncateL(fp, length);
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
 
-  public static int VSIFWriteL(string arg0, int arg1, int arg2, IntPtr arg3) {
-    int ret = GdalPINVOKE.VSIFWriteL(arg0, arg1, arg2, arg3);
+  public static int VSIFWriteL(string arg0, int arg1, int arg2, IntPtr fp) {
+    int ret = GdalPINVOKE.VSIFWriteL(arg0, arg1, arg2, fp);
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
 
+  public static string[] ParseCommandLine(string utf8_path) {
+        /* %typemap(csout) char** CSL */
+        IntPtr cPtr = GdalPINVOKE.ParseCommandLine(Gdal.StringToUtf8Bytes(utf8_path));
+        IntPtr objPtr;
+        int count = 0;
+        if (cPtr != IntPtr.Zero) {
+            while (Marshal.ReadIntPtr(cPtr, count*IntPtr.Size) != IntPtr.Zero)
+                ++count;
+        }
+        string[] ret = new string[count];
+        if (count > 0) {
+	        for(int cx = 0; cx < count; cx++) {
+                objPtr = System.Runtime.InteropServices.Marshal.ReadIntPtr(cPtr, cx * System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)));
+                ret[cx]= (objPtr == IntPtr.Zero) ? null : System.Runtime.InteropServices.Marshal.PtrToStringAnsi(objPtr);
+            }
+        }
+        if (cPtr != IntPtr.Zero)
+            GdalPINVOKE.StringListDestroy(cPtr);
+        
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+        return ret;
+}
+
   public static double GDAL_GCP_GCPX_get(GCP gcp) {
     double ret = GdalPINVOKE.GDAL_GCP_GCPX_get(GCP.getCPtr(gcp));
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
@@ -504,8 +545,8 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
     return ret;
   }
 
-  public static CPLErr ReprojectImage(Dataset src_ds, Dataset dst_ds, string src_wkt, string dst_wkt, ResampleAlg eResampleAlg, double WarpMemoryLimit, double maxerror, Gdal.GDALProgressFuncDelegate callback, string callback_data) {
-    CPLErr ret = (CPLErr)GdalPINVOKE.ReprojectImage(Dataset.getCPtr(src_ds), Dataset.getCPtr(dst_ds), src_wkt, dst_wkt, (int)eResampleAlg, WarpMemoryLimit, maxerror, callback, callback_data);
+  public static CPLErr ReprojectImage(Dataset src_ds, Dataset dst_ds, string src_wkt, string dst_wkt, ResampleAlg eResampleAlg, double WarpMemoryLimit, double maxerror, Gdal.GDALProgressFuncDelegate callback, string callback_data, string[] options) {
+    CPLErr ret = (CPLErr)GdalPINVOKE.ReprojectImage(Dataset.getCPtr(src_ds), Dataset.getCPtr(dst_ds), src_wkt, dst_wkt, (int)eResampleAlg, WarpMemoryLimit, maxerror, callback, callback_data, (options != null)? new GdalPINVOKE.StringListMarshal(options)._ar : null);
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
@@ -528,6 +569,12 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
     return ret;
   }
 
+  public static int FPolygonize(Band srcBand, Band maskBand, OSGeo.OGR.Layer outLayer, int iPixValField, string[] options, Gdal.GDALProgressFuncDelegate callback, string callback_data) {
+    int ret = GdalPINVOKE.FPolygonize(Band.getCPtr(srcBand), Band.getCPtr(maskBand), OSGeo.OGR.Layer.getCPtr(outLayer), iPixValField, (options != null)? new GdalPINVOKE.StringListMarshal(options)._ar : null, callback, callback_data);
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public static int FillNodata(Band targetBand, Band maskBand, double maxSearchDist, int smoothingIterations, string[] options, Gdal.GDALProgressFuncDelegate callback, string callback_data) {
     int ret = GdalPINVOKE.FillNodata(Band.getCPtr(targetBand), Band.getCPtr(maskBand), maxSearchDist, smoothingIterations, (options != null)? new GdalPINVOKE.StringListMarshal(options)._ar : null, callback, callback_data);
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
@@ -565,6 +612,13 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
     return ret;
   }
 
+  public static Dataset CreatePansharpenedVRT(string pszXML, Band panchroBand, int nInputSpectralBands, SWIGTYPE_p_p_GDALRasterBandShadow ahInputSpectralBands) {
+    IntPtr cPtr = GdalPINVOKE.CreatePansharpenedVRT(pszXML, Band.getCPtr(panchroBand), nInputSpectralBands, SWIGTYPE_p_p_GDALRasterBandShadow.getCPtr(ahInputSpectralBands));
+    Dataset ret = (cPtr == IntPtr.Zero) ? null : new Dataset(cPtr, true, ThisOwn_true());
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public static void ApplyGeoTransform(double[] padfGeoTransform, double dfPixel, double dfLine, out double pdfGeoX, out double pdfGeoY) {
     GdalPINVOKE.ApplyGeoTransform(padfGeoTransform, dfPixel, dfLine, out pdfGeoX, out pdfGeoY);
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
@@ -740,7 +794,7 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
                 ++count;
         }
         string[] ret = new string[count];
-        if (count > 0) {       
+        if (count > 0) {
 	        for(int cx = 0; cx < count; cx++) {
                 objPtr = System.Runtime.InteropServices.Marshal.ReadIntPtr(cPtr, cx * System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)));
                 ret[cx]= (objPtr == IntPtr.Zero) ? null : System.Runtime.InteropServices.Marshal.PtrToStringAnsi(objPtr);
@@ -774,6 +828,99 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
   }
 
+  public static string GDALInfo(Dataset hDataset, GDALInfoOptions infoOptions) {
+    string ret = GdalPINVOKE.GDALInfo(Dataset.getCPtr(hDataset), GDALInfoOptions.getCPtr(infoOptions));
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public static Dataset wrapper_GDALTranslate(string dest, Dataset dataset, GDALTranslateOptions translateOptions, Gdal.GDALProgressFuncDelegate callback, string callback_data) {
+    IntPtr cPtr = GdalPINVOKE.wrapper_GDALTranslate(Gdal.StringToUtf8Bytes(dest), Dataset.getCPtr(dataset), GDALTranslateOptions.getCPtr(translateOptions), callback, callback_data);
+    Dataset ret = (cPtr == IntPtr.Zero) ? null : new Dataset(cPtr, true, ThisOwn_true());
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public static int wrapper_GDALWarpDestDS(Dataset dstDS, int object_list_count, SWIGTYPE_p_p_GDALDatasetShadow poObjects, GDALWarpAppOptions warpAppOptions, Gdal.GDALProgressFuncDelegate callback, string callback_data) {
+    int ret = GdalPINVOKE.wrapper_GDALWarpDestDS(Dataset.getCPtr(dstDS), object_list_count, SWIGTYPE_p_p_GDALDatasetShadow.getCPtr(poObjects), GDALWarpAppOptions.getCPtr(warpAppOptions), callback, callback_data);
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public static Dataset wrapper_GDALWarpDestName(string dest, int object_list_count, SWIGTYPE_p_p_GDALDatasetShadow poObjects, GDALWarpAppOptions warpAppOptions, Gdal.GDALProgressFuncDelegate callback, string callback_data) {
+    IntPtr cPtr = GdalPINVOKE.wrapper_GDALWarpDestName(Gdal.StringToUtf8Bytes(dest), object_list_count, SWIGTYPE_p_p_GDALDatasetShadow.getCPtr(poObjects), GDALWarpAppOptions.getCPtr(warpAppOptions), callback, callback_data);
+    Dataset ret = (cPtr == IntPtr.Zero) ? null : new Dataset(cPtr, true, ThisOwn_true());
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public static int wrapper_GDALVectorTranslateDestDS(Dataset dstDS, Dataset srcDS, GDALVectorTranslateOptions options, Gdal.GDALProgressFuncDelegate callback, string callback_data) {
+    int ret = GdalPINVOKE.wrapper_GDALVectorTranslateDestDS(Dataset.getCPtr(dstDS), Dataset.getCPtr(srcDS), GDALVectorTranslateOptions.getCPtr(options), callback, callback_data);
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public static Dataset wrapper_GDALVectorTranslateDestName(string dest, Dataset srcDS, GDALVectorTranslateOptions options, Gdal.GDALProgressFuncDelegate callback, string callback_data) {
+    IntPtr cPtr = GdalPINVOKE.wrapper_GDALVectorTranslateDestName(Gdal.StringToUtf8Bytes(dest), Dataset.getCPtr(srcDS), GDALVectorTranslateOptions.getCPtr(options), callback, callback_data);
+    Dataset ret = (cPtr == IntPtr.Zero) ? null : new Dataset(cPtr, true, ThisOwn_true());
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public static Dataset wrapper_GDALDEMProcessing(string dest, Dataset dataset, string pszProcessing, string pszColorFilename, GDALDEMProcessingOptions options, Gdal.GDALProgressFuncDelegate callback, string callback_data) {
+    IntPtr cPtr = GdalPINVOKE.wrapper_GDALDEMProcessing(Gdal.StringToUtf8Bytes(dest), Dataset.getCPtr(dataset), pszProcessing, pszColorFilename, GDALDEMProcessingOptions.getCPtr(options), callback, callback_data);
+    Dataset ret = (cPtr == IntPtr.Zero) ? null : new Dataset(cPtr, true, ThisOwn_true());
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public static int wrapper_GDALNearblackDestDS(Dataset dstDS, Dataset srcDS, GDALNearblackOptions options, Gdal.GDALProgressFuncDelegate callback, string callback_data) {
+    int ret = GdalPINVOKE.wrapper_GDALNearblackDestDS(Dataset.getCPtr(dstDS), Dataset.getCPtr(srcDS), GDALNearblackOptions.getCPtr(options), callback, callback_data);
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public static Dataset wrapper_GDALNearblackDestName(string dest, Dataset srcDS, GDALNearblackOptions options, Gdal.GDALProgressFuncDelegate callback, string callback_data) {
+    IntPtr cPtr = GdalPINVOKE.wrapper_GDALNearblackDestName(Gdal.StringToUtf8Bytes(dest), Dataset.getCPtr(srcDS), GDALNearblackOptions.getCPtr(options), callback, callback_data);
+    Dataset ret = (cPtr == IntPtr.Zero) ? null : new Dataset(cPtr, true, ThisOwn_true());
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public static Dataset wrapper_GDALGrid(string dest, Dataset dataset, GDALGridOptions options, Gdal.GDALProgressFuncDelegate callback, string callback_data) {
+    IntPtr cPtr = GdalPINVOKE.wrapper_GDALGrid(Gdal.StringToUtf8Bytes(dest), Dataset.getCPtr(dataset), GDALGridOptions.getCPtr(options), callback, callback_data);
+    Dataset ret = (cPtr == IntPtr.Zero) ? null : new Dataset(cPtr, true, ThisOwn_true());
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public static int wrapper_GDALRasterizeDestDS(Dataset dstDS, Dataset srcDS, GDALRasterizeOptions options, Gdal.GDALProgressFuncDelegate callback, string callback_data) {
+    int ret = GdalPINVOKE.wrapper_GDALRasterizeDestDS(Dataset.getCPtr(dstDS), Dataset.getCPtr(srcDS), GDALRasterizeOptions.getCPtr(options), callback, callback_data);
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public static Dataset wrapper_GDALRasterizeDestName(string dest, Dataset srcDS, GDALRasterizeOptions options, Gdal.GDALProgressFuncDelegate callback, string callback_data) {
+    IntPtr cPtr = GdalPINVOKE.wrapper_GDALRasterizeDestName(Gdal.StringToUtf8Bytes(dest), Dataset.getCPtr(srcDS), GDALRasterizeOptions.getCPtr(options), callback, callback_data);
+    Dataset ret = (cPtr == IntPtr.Zero) ? null : new Dataset(cPtr, true, ThisOwn_true());
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public static Dataset wrapper_GDALBuildVRT_objects(string dest, int object_list_count, SWIGTYPE_p_p_GDALDatasetShadow poObjects, GDALBuildVRTOptions options, Gdal.GDALProgressFuncDelegate callback, string callback_data) {
+    IntPtr cPtr = GdalPINVOKE.wrapper_GDALBuildVRT_objects(Gdal.StringToUtf8Bytes(dest), object_list_count, SWIGTYPE_p_p_GDALDatasetShadow.getCPtr(poObjects), GDALBuildVRTOptions.getCPtr(options), callback, callback_data);
+    Dataset ret = (cPtr == IntPtr.Zero) ? null : new Dataset(cPtr, true, ThisOwn_true());
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public static Dataset wrapper_GDALBuildVRT_names(string dest, string[] source_filenames, GDALBuildVRTOptions options, Gdal.GDALProgressFuncDelegate callback, string callback_data) {
+    IntPtr cPtr = GdalPINVOKE.wrapper_GDALBuildVRT_names(Gdal.StringToUtf8Bytes(dest), (source_filenames != null)? new GdalPINVOKE.StringListMarshal(source_filenames)._ar : null, GDALBuildVRTOptions.getCPtr(options), callback, callback_data);
+    Dataset ret = (cPtr == IntPtr.Zero) ? null : new Dataset(cPtr, true, ThisOwn_true());
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
 }
 
 }
diff --git a/swig/csharp/gdal/GdalPINVOKE.cs b/swig/csharp/gdal/GdalPINVOKE.cs
index 10f2b1d..64f807a 100644
--- a/swig/csharp/gdal/GdalPINVOKE.cs
+++ b/swig/csharp/gdal/GdalPINVOKE.cs
@@ -262,6 +262,12 @@ class GdalPINVOKE {
   [DllImport("gdal_wrap", EntryPoint="CSharp_GetLastErrorMsg")]
   public static extern string GetLastErrorMsg();
 
+  [DllImport("gdal_wrap", EntryPoint="CSharp_VSIGetLastErrorNo")]
+  public static extern int VSIGetLastErrorNo();
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_VSIGetLastErrorMsg")]
+  public static extern string VSIGetLastErrorMsg();
+
   [DllImport("gdal_wrap", EntryPoint="CSharp_PushFinderLocation")]
   public static extern void PushFinderLocation(byte[] jarg1);
 
@@ -275,7 +281,7 @@ class GdalPINVOKE {
   public static extern string FindFile(string jarg1, byte[] jarg2);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_ReadDir")]
-  public static extern IntPtr ReadDir(byte[] jarg1);
+  public static extern IntPtr ReadDir(byte[] jarg1, int jarg2);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_ReadDirRecursive")]
   public static extern IntPtr ReadDirRecursive(byte[] jarg1);
@@ -308,11 +314,14 @@ class GdalPINVOKE {
   public static extern int Rmdir(byte[] jarg1);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_Rename")]
-  public static extern int Rename(string jarg1, string jarg2);
+  public static extern int Rename(byte[] jarg1, byte[] jarg2);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_VSIFOpenL")]
   public static extern IntPtr VSIFOpenL(byte[] jarg1, string jarg2);
 
+  [DllImport("gdal_wrap", EntryPoint="CSharp_VSIFOpenExL")]
+  public static extern IntPtr VSIFOpenExL(byte[] jarg1, string jarg2, int jarg3);
+
   [DllImport("gdal_wrap", EntryPoint="CSharp_VSIFCloseL")]
   public static extern int VSIFCloseL(IntPtr jarg1);
 
@@ -328,6 +337,9 @@ class GdalPINVOKE {
   [DllImport("gdal_wrap", EntryPoint="CSharp_VSIFWriteL")]
   public static extern int VSIFWriteL(string jarg1, int jarg2, int jarg3, IntPtr jarg4);
 
+  [DllImport("gdal_wrap", EntryPoint="CSharp_ParseCommandLine")]
+  public static extern IntPtr ParseCommandLine(byte[] jarg1);
+
   [DllImport("gdal_wrap", EntryPoint="CSharp_XMLNode_Type_get")]
   public static extern int XMLNode_Type_get(HandleRef jarg1);
 
@@ -742,6 +754,9 @@ class GdalPINVOKE {
   [DllImport("gdal_wrap", EntryPoint="CSharp_Band_SetNoDataValue")]
   public static extern int Band_SetNoDataValue(HandleRef jarg1, double jarg2);
 
+  [DllImport("gdal_wrap", EntryPoint="CSharp_Band_DeleteNoDataValue")]
+  public static extern int Band_DeleteNoDataValue(HandleRef jarg1);
+
   [DllImport("gdal_wrap", EntryPoint="CSharp_Band_GetUnitType")]
   public static extern string Band_GetUnitType(HandleRef jarg1);
 
@@ -953,7 +968,7 @@ class GdalPINVOKE {
   public static extern int DitherRGB2PCT(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, HandleRef jarg4, HandleRef jarg5, Gdal.GDALProgressFuncDelegate jarg6, string jarg7);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_ReprojectImage")]
-  public static extern int ReprojectImage(HandleRef jarg1, HandleRef jarg2, string jarg3, string jarg4, int jarg5, double jarg6, double jarg7, Gdal.GDALProgressFuncDelegate jarg8, string jarg9);
+  public static extern int ReprojectImage(HandleRef jarg1, HandleRef jarg2, string jarg3, string jarg4, int jarg5, double jarg6, double jarg7, Gdal.GDALProgressFuncDelegate jarg8, string jarg9, IntPtr[] jarg10);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_ComputeProximity")]
   public static extern int ComputeProximity(HandleRef jarg1, HandleRef jarg2, IntPtr[] jarg3, Gdal.GDALProgressFuncDelegate jarg4, string jarg5);
@@ -964,6 +979,9 @@ class GdalPINVOKE {
   [DllImport("gdal_wrap", EntryPoint="CSharp_Polygonize")]
   public static extern int Polygonize(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, int jarg4, IntPtr[] jarg5, Gdal.GDALProgressFuncDelegate jarg6, string jarg7);
 
+  [DllImport("gdal_wrap", EntryPoint="CSharp_FPolygonize")]
+  public static extern int FPolygonize(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, int jarg4, IntPtr[] jarg5, Gdal.GDALProgressFuncDelegate jarg6, string jarg7);
+
   [DllImport("gdal_wrap", EntryPoint="CSharp_FillNodata")]
   public static extern int FillNodata(HandleRef jarg1, HandleRef jarg2, double jarg3, int jarg4, IntPtr[] jarg5, Gdal.GDALProgressFuncDelegate jarg6, string jarg7);
 
@@ -982,6 +1000,9 @@ class GdalPINVOKE {
   [DllImport("gdal_wrap", EntryPoint="CSharp_AutoCreateWarpedVRT")]
   public static extern IntPtr AutoCreateWarpedVRT(HandleRef jarg1, string jarg2, string jarg3, int jarg4, double jarg5);
 
+  [DllImport("gdal_wrap", EntryPoint="CSharp_CreatePansharpenedVRT")]
+  public static extern IntPtr CreatePansharpenedVRT(string jarg1, HandleRef jarg2, int jarg3, HandleRef jarg4);
+
   [DllImport("gdal_wrap", EntryPoint="CSharp_new_Transformer")]
   public static extern IntPtr new_Transformer(HandleRef jarg1, HandleRef jarg2, IntPtr[] jarg3);
 
@@ -1096,6 +1117,102 @@ class GdalPINVOKE {
   [DllImport("gdal_wrap", EntryPoint="CSharp___FreeCArray_GDAL_GCP")]
   public static extern void __FreeCArray_GDAL_GCP(IntPtr jarg1);
 
+  [DllImport("gdal_wrap", EntryPoint="CSharp_new_GDALInfoOptions")]
+  public static extern IntPtr new_GDALInfoOptions(IntPtr[] jarg1);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_delete_GDALInfoOptions")]
+  public static extern void delete_GDALInfoOptions(HandleRef jarg1);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_GDALInfo")]
+  public static extern string GDALInfo(HandleRef jarg1, HandleRef jarg2);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_new_GDALTranslateOptions")]
+  public static extern IntPtr new_GDALTranslateOptions(IntPtr[] jarg1);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_delete_GDALTranslateOptions")]
+  public static extern void delete_GDALTranslateOptions(HandleRef jarg1);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_wrapper_GDALTranslate")]
+  public static extern IntPtr wrapper_GDALTranslate(byte[] jarg1, HandleRef jarg2, HandleRef jarg3, Gdal.GDALProgressFuncDelegate jarg4, string jarg5);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_new_GDALWarpAppOptions")]
+  public static extern IntPtr new_GDALWarpAppOptions(IntPtr[] jarg1);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_delete_GDALWarpAppOptions")]
+  public static extern void delete_GDALWarpAppOptions(HandleRef jarg1);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_wrapper_GDALWarpDestDS")]
+  public static extern int wrapper_GDALWarpDestDS(HandleRef jarg1, int jarg2, HandleRef jarg3, HandleRef jarg4, Gdal.GDALProgressFuncDelegate jarg5, string jarg6);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_wrapper_GDALWarpDestName")]
+  public static extern IntPtr wrapper_GDALWarpDestName(byte[] jarg1, int jarg2, HandleRef jarg3, HandleRef jarg4, Gdal.GDALProgressFuncDelegate jarg5, string jarg6);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_new_GDALVectorTranslateOptions")]
+  public static extern IntPtr new_GDALVectorTranslateOptions(IntPtr[] jarg1);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_delete_GDALVectorTranslateOptions")]
+  public static extern void delete_GDALVectorTranslateOptions(HandleRef jarg1);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_wrapper_GDALVectorTranslateDestDS")]
+  public static extern int wrapper_GDALVectorTranslateDestDS(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, Gdal.GDALProgressFuncDelegate jarg4, string jarg5);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_wrapper_GDALVectorTranslateDestName")]
+  public static extern IntPtr wrapper_GDALVectorTranslateDestName(byte[] jarg1, HandleRef jarg2, HandleRef jarg3, Gdal.GDALProgressFuncDelegate jarg4, string jarg5);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_new_GDALDEMProcessingOptions")]
+  public static extern IntPtr new_GDALDEMProcessingOptions(IntPtr[] jarg1);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_delete_GDALDEMProcessingOptions")]
+  public static extern void delete_GDALDEMProcessingOptions(HandleRef jarg1);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_wrapper_GDALDEMProcessing")]
+  public static extern IntPtr wrapper_GDALDEMProcessing(byte[] jarg1, HandleRef jarg2, string jarg3, string jarg4, HandleRef jarg5, Gdal.GDALProgressFuncDelegate jarg6, string jarg7);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_new_GDALNearblackOptions")]
+  public static extern IntPtr new_GDALNearblackOptions(IntPtr[] jarg1);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_delete_GDALNearblackOptions")]
+  public static extern void delete_GDALNearblackOptions(HandleRef jarg1);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_wrapper_GDALNearblackDestDS")]
+  public static extern int wrapper_GDALNearblackDestDS(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, Gdal.GDALProgressFuncDelegate jarg4, string jarg5);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_wrapper_GDALNearblackDestName")]
+  public static extern IntPtr wrapper_GDALNearblackDestName(byte[] jarg1, HandleRef jarg2, HandleRef jarg3, Gdal.GDALProgressFuncDelegate jarg4, string jarg5);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_new_GDALGridOptions")]
+  public static extern IntPtr new_GDALGridOptions(IntPtr[] jarg1);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_delete_GDALGridOptions")]
+  public static extern void delete_GDALGridOptions(HandleRef jarg1);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_wrapper_GDALGrid")]
+  public static extern IntPtr wrapper_GDALGrid(byte[] jarg1, HandleRef jarg2, HandleRef jarg3, Gdal.GDALProgressFuncDelegate jarg4, string jarg5);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_new_GDALRasterizeOptions")]
+  public static extern IntPtr new_GDALRasterizeOptions(IntPtr[] jarg1);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_delete_GDALRasterizeOptions")]
+  public static extern void delete_GDALRasterizeOptions(HandleRef jarg1);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_wrapper_GDALRasterizeDestDS")]
+  public static extern int wrapper_GDALRasterizeDestDS(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, Gdal.GDALProgressFuncDelegate jarg4, string jarg5);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_wrapper_GDALRasterizeDestName")]
+  public static extern IntPtr wrapper_GDALRasterizeDestName(byte[] jarg1, HandleRef jarg2, HandleRef jarg3, Gdal.GDALProgressFuncDelegate jarg4, string jarg5);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_new_GDALBuildVRTOptions")]
+  public static extern IntPtr new_GDALBuildVRTOptions(IntPtr[] jarg1);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_delete_GDALBuildVRTOptions")]
+  public static extern void delete_GDALBuildVRTOptions(HandleRef jarg1);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_wrapper_GDALBuildVRT_objects")]
+  public static extern IntPtr wrapper_GDALBuildVRT_objects(byte[] jarg1, int jarg2, HandleRef jarg3, HandleRef jarg4, Gdal.GDALProgressFuncDelegate jarg5, string jarg6);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_wrapper_GDALBuildVRT_names")]
+  public static extern IntPtr wrapper_GDALBuildVRT_names(byte[] jarg1, IntPtr[] jarg2, HandleRef jarg3, Gdal.GDALProgressFuncDelegate jarg4, string jarg5);
+
   [DllImport("gdal_wrap", EntryPoint="CSharp_Driver_SWIGUpcast")]
   public static extern IntPtr Driver_SWIGUpcast(IntPtr jarg1);
 
diff --git a/swig/csharp/gdal/MajorObject.cs b/swig/csharp/gdal/MajorObject.cs
index f9a52d2..4c62dec 100644
--- a/swig/csharp/gdal/MajorObject.cs
+++ b/swig/csharp/gdal/MajorObject.cs
@@ -15,7 +15,7 @@ public class MajorObject : IDisposable {
   private HandleRef swigCPtr;
   protected bool swigCMemOwn;
   protected object swigParentRef;
-  
+
   protected static object ThisOwn_true() { return null; }
   protected object ThisOwn_false() { return this; }
 
@@ -85,7 +85,7 @@ public class MajorObject : IDisposable {
                 ++count;
         }
         string[] ret = new string[count];
-        if (count > 0) {       
+        if (count > 0) {
 	        for(int cx = 0; cx < count; cx++) {
                 objPtr = System.Runtime.InteropServices.Marshal.ReadIntPtr(cPtr, cx * System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)));
                 ret[cx]= (objPtr == IntPtr.Zero) ? null : System.Runtime.InteropServices.Marshal.PtrToStringAnsi(objPtr);
@@ -108,7 +108,7 @@ public class MajorObject : IDisposable {
                 ++count;
         }
         string[] ret = new string[count];
-        if (count > 0) {       
+        if (count > 0) {
 	        for(int cx = 0; cx < count; cx++) {
                 objPtr = System.Runtime.InteropServices.Marshal.ReadIntPtr(cPtr, cx * System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)));
                 ret[cx]= (objPtr == IntPtr.Zero) ? null : System.Runtime.InteropServices.Marshal.PtrToStringAnsi(objPtr);
diff --git a/swig/csharp/gdal/RasterAttributeTable.cs b/swig/csharp/gdal/RasterAttributeTable.cs
index a999d9c..4ec655e 100644
--- a/swig/csharp/gdal/RasterAttributeTable.cs
+++ b/swig/csharp/gdal/RasterAttributeTable.cs
@@ -15,7 +15,7 @@ public class RasterAttributeTable : IDisposable {
   private HandleRef swigCPtr;
   protected bool swigCMemOwn;
   protected object swigParentRef;
-  
+
   protected static object ThisOwn_true() { return null; }
   protected object ThisOwn_false() { return this; }
 
diff --git a/swig/csharp/gdal/SWIGTYPE_p_p_GDALDatasetShadow.cs b/swig/csharp/gdal/SWIGTYPE_p_p_GDALDatasetShadow.cs
new file mode 100644
index 0000000..a2ed78a
--- /dev/null
+++ b/swig/csharp/gdal/SWIGTYPE_p_p_GDALDatasetShadow.cs
@@ -0,0 +1,30 @@
+/* ----------------------------------------------------------------------------
+ * This file was automatically generated by SWIG (http://www.swig.org).
+ * Version 2.0.12
+ *
+ * Do not make changes to this file unless you know what you are doing--modify
+ * the SWIG interface file instead.
+ * ----------------------------------------------------------------------------- */
+
+namespace OSGeo.GDAL {
+
+using System;
+using System.Runtime.InteropServices;
+
+public class SWIGTYPE_p_p_GDALDatasetShadow {
+  private HandleRef swigCPtr;
+
+  public SWIGTYPE_p_p_GDALDatasetShadow(IntPtr cPtr, bool futureUse, object parent) {
+    swigCPtr = new HandleRef(this, cPtr);
+  }
+
+  protected SWIGTYPE_p_p_GDALDatasetShadow() {
+    swigCPtr = new HandleRef(null, IntPtr.Zero);
+  }
+
+  public static HandleRef getCPtr(SWIGTYPE_p_p_GDALDatasetShadow obj) {
+    return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr;
+  }
+}
+
+}
diff --git a/swig/csharp/gdal/Transformer.cs b/swig/csharp/gdal/Transformer.cs
index 63a9908..0ade616 100644
--- a/swig/csharp/gdal/Transformer.cs
+++ b/swig/csharp/gdal/Transformer.cs
@@ -15,7 +15,7 @@ public class Transformer : IDisposable {
   private HandleRef swigCPtr;
   protected bool swigCMemOwn;
   protected object swigParentRef;
-  
+
   protected static object ThisOwn_true() { return null; }
   protected object ThisOwn_false() { return this; }
 
diff --git a/swig/csharp/gdal/XMLNode.cs b/swig/csharp/gdal/XMLNode.cs
index 3766757..4598fc4 100644
--- a/swig/csharp/gdal/XMLNode.cs
+++ b/swig/csharp/gdal/XMLNode.cs
@@ -15,7 +15,7 @@ public class XMLNode : IDisposable {
   private HandleRef swigCPtr;
   protected bool swigCMemOwn;
   protected object swigParentRef;
-  
+
   protected static object ThisOwn_true() { return null; }
   protected object ThisOwn_false() { return this; }
 
diff --git a/swig/csharp/gdal/gdal_wrap.cpp b/swig/csharp/gdal/gdal_wrap.cpp
index e13ed2d..49b343d 100644
--- a/swig/csharp/gdal/gdal_wrap.cpp
+++ b/swig/csharp/gdal/gdal_wrap.cpp
@@ -343,6 +343,7 @@ using namespace std;
 #include "cpl_string.h"
 #include "cpl_multiproc.h"
 #include "cpl_http.h"
+#include "cpl_vsi_error.h"
 
 #include "gdal.h"
 #include "gdal_priv.h"
@@ -365,11 +366,15 @@ typedef int RETURN_NONE;
 typedef int VSI_RETVAL;
 
 
-
-void VeryQuiteErrorHandler(CPLErr eclass, int code, const char *msg ) {
+void VeryQuietErrorHandler(CPLErr eclass, int code, const char *msg ) {
   /* If the error class is CE_Fatal, we want to have a message issued
      because the CPL support code does an abort() before any exception
      can be generated */
+#if defined(SWIGPERL)
+    AV* error_stack = get_av("Geo::GDAL::error", 0);
+    SV *error = newSVpv(msg, 0);
+    av_push(error_stack, error);
+#endif
   if (eclass == CE_Fatal ) {
     CPLDefaultErrorHandler(eclass, code, msg );
   }
@@ -377,7 +382,7 @@ void VeryQuiteErrorHandler(CPLErr eclass, int code, const char *msg ) {
 
 
 void UseExceptions() {
-  CPLSetErrorHandler( (CPLErrorHandler) VeryQuiteErrorHandler );
+  CPLSetErrorHandler( (CPLErrorHandler) VeryQuietErrorHandler );
 }
 
 void DontUseExceptions() {
@@ -441,7 +446,13 @@ typedef char retStringAndCPLFree;
 
 retStringAndCPLFree* EscapeString(int len, char *bin_string , int scheme) {
     return CPLEscapeString((const char*)bin_string, len, scheme);
-} 
+}
+
+
+char **wrapper_VSIReadDirEx( const char * utf8_path, int nMaxFiles = 0 )
+{
+    return VSIReadDirEx(utf8_path, nMaxFiles);
+}
 
 
 const char *wrapper_CPLGetConfigOption( const char * pszKey, const char * pszDefault = NULL )
@@ -474,8 +485,16 @@ VSILFILE   *wrapper_VSIFOpenL( const char *utf8_path, const char *pszMode )
     return VSIFOpenL( utf8_path, pszMode );
 }
 
+
+VSILFILE   *wrapper_VSIFOpenExL( const char *utf8_path, const char *pszMode, int bSetError )
+{
+    if (!pszMode) /* would lead to segfault */
+        pszMode = "r";
+    return VSIFOpenExL( utf8_path, pszMode, bSetError );
+}
+
 SWIGINTERN CPLXMLNode *new_CPLXMLNode__SWIG_0(char const *pszString){
-        return CPLParseXMLString( pszString );     
+        return CPLParseXMLString( pszString );
     }
 SWIGINTERN CPLXMLNode *new_CPLXMLNode__SWIG_1(CPLXMLNodeType eType,char const *pszText){
         return CPLCreateXMLNode(NULL, eType, pszText);
@@ -496,7 +515,7 @@ SWIGINTERN CPLXMLNode *CPLXMLNode_GetXMLNode(CPLXMLNode *self,char const *pszPat
         return CPLGetXMLNode( self, pszPath );
     }
 SWIGINTERN char const *CPLXMLNode_GetXMLValue(CPLXMLNode *self,char const *pszPath,char const *pszDefault){
-        return CPLGetXMLValue( self, pszPath, pszDefault );                    
+        return CPLGetXMLValue( self, pszPath, pszDefault );
     }
 SWIGINTERN void CPLXMLNode_AddXMLChild(CPLXMLNode *self,CPLXMLNode *psChild){
         CPLAddXMLChild( self, psChild );
@@ -508,7 +527,7 @@ SWIGINTERN void CPLXMLNode_AddXMLSibling(CPLXMLNode *self,CPLXMLNode *psNewSibli
         CPLAddXMLSibling( self, psNewSibling );
     }
 SWIGINTERN CPLXMLNode *CPLXMLNode_CreateXMLElementAndValue(CPLXMLNode *self,char const *pszName,char const *pszValue){
-        return CPLCreateXMLElementAndValue( self, pszName, pszValue );                                 
+        return CPLCreateXMLElementAndValue( self, pszName, pszValue );
     }
 SWIGINTERN CPLXMLNode *CPLXMLNode_CloneXMLTree(CPLXMLNode *self,CPLXMLNode *psTree){
         return CPLCloneXMLTree( psTree );
@@ -517,10 +536,10 @@ SWIGINTERN CPLXMLNode *CPLXMLNode_Clone(CPLXMLNode *self){
         return CPLCloneXMLTree( self );
     }
 SWIGINTERN int CPLXMLNode_SetXMLValue(CPLXMLNode *self,char const *pszPath,char const *pszValue){
-        return CPLSetXMLValue( self,  pszPath, pszValue );           
+        return CPLSetXMLValue( self,  pszPath, pszValue );
     }
 SWIGINTERN void CPLXMLNode_StripXMLNamespace(CPLXMLNode *self,char const *pszNamespace,int bRecurse){
-        CPLStripXMLNamespace( self, pszNamespace, bRecurse );                  
+        CPLStripXMLNamespace( self, pszNamespace, bRecurse );
     }
 SWIGINTERN char const *GDALMajorObjectShadow_GetDescription(GDALMajorObjectShadow *self){
     return GDALGetDescription( self );
@@ -551,23 +570,23 @@ SWIGINTERN CPLErr GDALMajorObjectShadow_SetMetadataItem(GDALMajorObjectShadow *s
   }
 SWIGINTERN GDALDatasetShadow *GDALDriverShadow_Create(GDALDriverShadow *self,char const *utf8_path,int xsize,int ysize,int bands=1,GDALDataType eType=GDT_Byte,char **options=0){
 
-    GDALDatasetShadow* ds = (GDALDatasetShadow*) GDALCreate(    self, 
-                                                                utf8_path, 
-                                                                xsize, 
-                                                                ysize, 
-                                                                bands, 
-                                                                eType, 
+    GDALDatasetShadow* ds = (GDALDatasetShadow*) GDALCreate(    self,
+                                                                utf8_path,
+                                                                xsize,
+                                                                ysize,
+                                                                bands,
+                                                                eType,
                                                                 options );
     return ds;
   }
 SWIGINTERN GDALDatasetShadow *GDALDriverShadow_CreateCopy(GDALDriverShadow *self,char const *utf8_path,GDALDatasetShadow *src,int strict=1,char **options=0,GDALProgressFunc callback=NULL,void *callback_data=NULL){
 
-    GDALDatasetShadow *ds = (GDALDatasetShadow*) GDALCreateCopy(    self, 
-                                                                    utf8_path, 
-                                                                    src, 
-                                                                    strict, 
-                                                                    options, 
-                                                                    callback, 
+    GDALDatasetShadow *ds = (GDALDatasetShadow*) GDALCreateCopy(    self,
+                                                                    utf8_path,
+                                                                    src,
+                                                                    strict,
+                                                                    options,
+                                                                    callback,
                                                                     callback_data );
     return ds;
   }
@@ -652,7 +671,7 @@ const char * GDAL_GCP_Info_get( GDAL_GCP *gcp ) {
   return gcp->pszInfo;
 }
 void GDAL_GCP_Info_set( GDAL_GCP *gcp, const char * pszInfo ) {
-  if ( gcp->pszInfo ) 
+  if ( gcp->pszInfo )
     CPLFree( gcp->pszInfo );
   gcp->pszInfo = CPLStrdup(pszInfo);
 }
@@ -660,13 +679,13 @@ const char * GDAL_GCP_Id_get( GDAL_GCP *gcp ) {
   return gcp->pszId;
 }
 void GDAL_GCP_Id_set( GDAL_GCP *gcp, const char * pszId ) {
-  if ( gcp->pszId ) 
+  if ( gcp->pszId )
     CPLFree( gcp->pszId );
   gcp->pszId = CPLStrdup(pszId);
 }
 
 
-/* Duplicate, but transposed names for C# because 
+/* Duplicate, but transposed names for C# because
 *  the C# module outputs backwards names
 */
 double GDAL_GCP_get_GCPX( GDAL_GCP *gcp ) {
@@ -703,7 +722,7 @@ const char * GDAL_GCP_get_Info( GDAL_GCP *gcp ) {
   return gcp->pszInfo;
 }
 void GDAL_GCP_set_Info( GDAL_GCP *gcp, const char * pszInfo ) {
-  if ( gcp->pszInfo ) 
+  if ( gcp->pszInfo )
     CPLFree( gcp->pszInfo );
   gcp->pszInfo = CPLStrdup(pszInfo);
 }
@@ -711,25 +730,19 @@ const char * GDAL_GCP_get_Id( GDAL_GCP *gcp ) {
   return gcp->pszId;
 }
 void GDAL_GCP_set_Id( GDAL_GCP *gcp, const char * pszId ) {
-  if ( gcp->pszId ) 
+  if ( gcp->pszId )
     CPLFree( gcp->pszId );
   gcp->pszId = CPLStrdup(pszId);
 }
 
 
-/* Returned size is in bytes or 0 if an error occured */
+/* Returned size is in bytes or 0 if an error occurred. */
 static
 GIntBig ComputeDatasetRasterIOSize (int buf_xsize, int buf_ysize, int nPixelSize,
                                 int nBands, int* bandMap, int nBandMapArrayLength,
                                 GIntBig nPixelSpace, GIntBig nLineSpace, GIntBig nBandSpace,
                                 int bSpacingShouldBeMultipleOfPixelSize )
 {
-#if SIZEOF_VOIDP == 8
-    const GIntBig MAX_INT = (((GIntBig)0x7fffffff) << 32) | 0xffffffff;
-#else
-    const GIntBig MAX_INT = 0x7fffffff;
-#endif
-
     if (buf_xsize <= 0 || buf_ysize <= 0)
     {
         CPLError(CE_Failure, CPLE_IllegalArg, "Illegal values for buffer size");
@@ -783,11 +796,13 @@ GIntBig ComputeDatasetRasterIOSize (int buf_xsize, int buf_ysize, int nPixelSize
     }
 
     GIntBig nRet = (GIntBig)(buf_ysize - 1) * nLineSpace + (GIntBig)(buf_xsize - 1) * nPixelSpace + (GIntBig)(nBands - 1) * nBandSpace + nPixelSize;
-    if (nRet > MAX_INT)
+#if SIZEOF_VOIDP == 4
+    if (nRet > INT_MAX)
     {
         CPLError(CE_Failure, CPLE_IllegalArg, "Integer overflow");
         return 0;
     }
+#endif
 
     return nRet;
 }
@@ -897,13 +912,13 @@ SWIGINTERN CPLErr GDALDatasetShadow_SetGeoTransform(GDALDatasetShadow *self,doub
   }
 SWIGINTERN int GDALDatasetShadow_BuildOverviews(GDALDatasetShadow *self,char const *resampling="NEAREST",int overviewlist=0,int *pOverviews=0,GDALProgressFunc callback=NULL,void *callback_data=NULL){
 
-    return GDALBuildOverviews(  self, 
-                                resampling ? resampling : "NEAREST", 
-                                overviewlist, 
-                                pOverviews, 
-                                0, 
-                                0, 
-                                callback, 
+    return GDALBuildOverviews(  self,
+                                resampling ? resampling : "NEAREST",
+                                overviewlist,
+                                pOverviews,
+                                0,
+                                0,
+                                callback,
                                 callback_data);
   }
 SWIGINTERN int GDALDatasetShadow_GetGCPCount(GDALDatasetShadow *self){
@@ -957,13 +972,13 @@ SWIGINTERN OGRErr GDALDatasetShadow_RollbackTransaction(GDALDatasetShadow *self)
     return GDALDatasetRollbackTransaction(self);
   }
 SWIGINTERN CPLErr GDALDatasetShadow_ReadRaster(GDALDatasetShadow *self,int xOff,int yOff,int xSize,int ySize,void *buffer,int buf_xSize,int buf_ySize,GDALDataType buf_type,int bandCount,int *bandMap,int pixelSpace,int lineSpace,int bandSpace){
-       return GDALDatasetRasterIO( self, GF_Read, xOff, yOff, xSize, ySize, 
-		        buffer, buf_xSize, buf_ySize, buf_type, bandCount, 
+       return GDALDatasetRasterIO( self, GF_Read, xOff, yOff, xSize, ySize,
+		        buffer, buf_xSize, buf_ySize, buf_type, bandCount,
 		        bandMap, pixelSpace, lineSpace, bandSpace);
     }
 SWIGINTERN CPLErr GDALDatasetShadow_WriteRaster(GDALDatasetShadow *self,int xOff,int yOff,int xSize,int ySize,void *buffer,int buf_xSize,int buf_ySize,GDALDataType buf_type,int bandCount,int *bandMap,int pixelSpace,int lineSpace,int bandSpace){
-       return GDALDatasetRasterIO( self, GF_Write, xOff, yOff, xSize, ySize, 
-		        buffer, buf_xSize, buf_ySize, buf_type, bandCount, 
+       return GDALDatasetRasterIO( self, GF_Write, xOff, yOff, xSize, ySize,
+		        buffer, buf_xSize, buf_ySize, buf_type, bandCount,
 		        bandMap, pixelSpace, lineSpace, bandSpace);
     }
 SWIGINTERN GDAL_GCP const *GDALDatasetShadow___GetGCPs(GDALDatasetShadow *self){
@@ -997,18 +1012,12 @@ int GDALDatasetShadow_RasterCount_get( GDALDatasetShadow *h ) {
 }
 
 
-/* Returned size is in bytes or 0 if an error occured */
+/* Returned size is in bytes or 0 if an error occurred. */
 static
 GIntBig ComputeBandRasterIOSize (int buf_xsize, int buf_ysize, int nPixelSize,
                                  GIntBig nPixelSpace, GIntBig nLineSpace,
                                  int bSpacingShouldBeMultipleOfPixelSize )
 {
-#if SIZEOF_VOIDP == 8
-    const GIntBig MAX_INT = (((GIntBig)0x7fffffff) << 32) | 0xffffffff;
-#else
-    const GIntBig MAX_INT = 0x7fffffff;
-#endif
-
     if (buf_xsize <= 0 || buf_ysize <= 0)
     {
         CPLError(CE_Failure, CPLE_IllegalArg, "Illegal values for buffer size");
@@ -1046,11 +1055,13 @@ GIntBig ComputeBandRasterIOSize (int buf_xsize, int buf_ysize, int nPixelSize,
     }
 
     GIntBig nRet = (GIntBig)(buf_ysize - 1) * nLineSpace + (GIntBig)(buf_xsize - 1) * nPixelSpace + nPixelSize;
-    if (nRet > MAX_INT)
+#if SIZEOF_VOIDP == 4
+    if (nRet > INT_MAX)
     {
         CPLError(CE_Failure, CPLE_IllegalArg, "Integer overflow");
         return 0;
     }
+#endif
 
     return nRet;
 }
@@ -1082,6 +1093,9 @@ SWIGINTERN void GDALRasterBandShadow_GetNoDataValue(GDALRasterBandShadow *self,d
 SWIGINTERN CPLErr GDALRasterBandShadow_SetNoDataValue(GDALRasterBandShadow *self,double d){
     return GDALSetRasterNoDataValue( self, d );
   }
+SWIGINTERN CPLErr GDALRasterBandShadow_DeleteNoDataValue(GDALRasterBandShadow *self){
+    return GDALDeleteRasterNoDataValue( self );
+  }
 SWIGINTERN char const *GDALRasterBandShadow_GetUnitType(GDALRasterBandShadow *self){
       return GDALGetRasterUnitType( self );
   }
@@ -1117,7 +1131,7 @@ SWIGINTERN CPLErr GDALRasterBandShadow_GetStatistics(GDALRasterBandShadow *self,
     if (max) *max = 0;
     if (mean) *mean = 0;
     if (stddev) *stddev = -1; /* This is the only way to recognize from Python if GetRasterStatistics() has updated the values */
-    return GDALGetRasterStatistics( self, approx_ok, force, 
+    return GDALGetRasterStatistics( self, approx_ok, force,
 				    min, max, mean, stddev );
   }
 SWIGINTERN CPLErr GDALRasterBandShadow_ComputeStatistics(GDALRasterBandShadow *self,bool approx_ok,double *min=NULL,double *max=NULL,double *mean=NULL,double *stddev=NULL,GDALProgressFunc callback=NULL,void *callback_data=NULL){
@@ -1141,7 +1155,7 @@ SWIGINTERN void GDALRasterBandShadow_ComputeRasterMinMax(GDALRasterBandShadow *s
     GDALComputeRasterMinMax( self, approx_ok, argout );
   }
 SWIGINTERN void GDALRasterBandShadow_ComputeBandStats(GDALRasterBandShadow *self,double argout[2],int samplestep=1){
-    GDALComputeBandStats( self, samplestep, argout+0, argout+1, 
+    GDALComputeBandStats( self, samplestep, argout+0, argout+1,
                           NULL, NULL );
   }
 SWIGINTERN CPLErr GDALRasterBandShadow_Fill(GDALRasterBandShadow *self,double real_fill,double imag_fill=0.0){
@@ -1162,7 +1176,7 @@ SWIGINTERN int GDALRasterBandShadow_SetRasterColorTable(GDALRasterBandShadow *se
 SWIGINTERN int GDALRasterBandShadow_SetColorTable(GDALRasterBandShadow *self,GDALColorTableShadow *arg){
     return GDALSetRasterColorTable( self, arg );
   }
-SWIGINTERN GDALRasterAttributeTableShadow *GDALRasterBandShadow_GetDefaultRAT(GDALRasterBandShadow *self){ 
+SWIGINTERN GDALRasterAttributeTableShadow *GDALRasterBandShadow_GetDefaultRAT(GDALRasterBandShadow *self){
       return (GDALRasterAttributeTableShadow*) GDALGetDefaultRAT(self);
   }
 SWIGINTERN int GDALRasterBandShadow_SetDefaultRAT(GDALRasterBandShadow *self,GDALRasterAttributeTableShadow *table){
@@ -1178,7 +1192,7 @@ SWIGINTERN CPLErr GDALRasterBandShadow_CreateMaskBand(GDALRasterBandShadow *self
       return GDALCreateMaskBand( self, nFlags );
   }
 SWIGINTERN CPLErr GDALRasterBandShadow_GetHistogram(GDALRasterBandShadow *self,double min=-0.5,double max=255.5,int buckets=256,int *panHistogram=NULL,int include_out_of_range=0,int approx_ok=1,GDALProgressFunc callback=NULL,void *callback_data=NULL){
-    CPLErrorReset(); 
+    CPLErrorReset();
     CPLErr err = GDALGetRasterHistogram( self, min, max, buckets, panHistogram,
                                          include_out_of_range, approx_ok,
                                          callback, callback_data );
@@ -1186,11 +1200,11 @@ SWIGINTERN CPLErr GDALRasterBandShadow_GetHistogram(GDALRasterBandShadow *self,d
   }
 SWIGINTERN CPLErr GDALRasterBandShadow_GetDefaultHistogram(GDALRasterBandShadow *self,double *min_ret=NULL,double *max_ret=NULL,int *buckets_ret=NULL,int **ppanHistogram=NULL,int force=1,GDALProgressFunc callback=NULL,void *callback_data=NULL){
     return GDALGetDefaultHistogram( self, min_ret, max_ret, buckets_ret,
-                                    ppanHistogram, force, 
+                                    ppanHistogram, force,
                                     callback, callback_data );
 }
 SWIGINTERN CPLErr GDALRasterBandShadow_SetDefaultHistogram(GDALRasterBandShadow *self,double min,double max,int buckets_in,int *panHistogram_in){
-    return GDALSetDefaultHistogram( self, min, max, 
+    return GDALSetDefaultHistogram( self, min, max,
     	   			    buckets_in, panHistogram_in );
 }
 SWIGINTERN bool GDALRasterBandShadow_HasArbitraryOverviews(GDALRasterBandShadow *self){
@@ -1203,11 +1217,11 @@ SWIGINTERN CPLErr GDALRasterBandShadow_SetCategoryNames(GDALRasterBandShadow *se
     return GDALSetRasterCategoryNames( self, papszCategoryNames );
   }
 SWIGINTERN CPLErr GDALRasterBandShadow_ReadRaster(GDALRasterBandShadow *self,int xOff,int yOff,int xSize,int ySize,void *buffer,int buf_xSize,int buf_ySize,GDALDataType buf_type,int pixelSpace,int lineSpace){
-       return GDALRasterIO( self, GF_Read, xOff, yOff, xSize, ySize, 
+       return GDALRasterIO( self, GF_Read, xOff, yOff, xSize, ySize,
 		        buffer, buf_xSize, buf_ySize, buf_type, pixelSpace, lineSpace );
     }
 SWIGINTERN CPLErr GDALRasterBandShadow_WriteRaster(GDALRasterBandShadow *self,int xOff,int yOff,int xSize,int ySize,void *buffer,int buf_xSize,int buf_ySize,GDALDataType buf_type,int pixelSpace,int lineSpace){
-       return GDALRasterIO( self, GF_Write, xOff, yOff, xSize, ySize, 
+       return GDALRasterIO( self, GF_Write, xOff, yOff, xSize, ySize,
 		        buffer, buf_xSize, buf_ySize, buf_type, pixelSpace, lineSpace );
     }
 
@@ -1249,7 +1263,7 @@ SWIGINTERN void GDALColorTableShadow_CreateColorRamp(GDALColorTableShadow *self,
         GDALCreateColorRamp(self, nStartIndex, startcolor, nEndIndex, endcolor);
     }
 SWIGINTERN GDALRasterAttributeTableShadow *new_GDALRasterAttributeTableShadow(){
-        return (GDALRasterAttributeTableShadow*) 
+        return (GDALRasterAttributeTableShadow*)
 		GDALCreateRasterAttributeTable();
     }
 SWIGINTERN void delete_GDALRasterAttributeTableShadow(GDALRasterAttributeTableShadow *self){
@@ -1258,10 +1272,10 @@ SWIGINTERN void delete_GDALRasterAttributeTableShadow(GDALRasterAttributeTableSh
 SWIGINTERN GDALRasterAttributeTableShadow *GDALRasterAttributeTableShadow_Clone(GDALRasterAttributeTableShadow *self){
         return (GDALRasterAttributeTableShadow*) GDALRATClone(self);
     }
-SWIGINTERN int GDALRasterAttributeTableShadow_GetColumnCount(GDALRasterAttributeTableShadow *self){ 
+SWIGINTERN int GDALRasterAttributeTableShadow_GetColumnCount(GDALRasterAttributeTableShadow *self){
         return GDALRATGetColumnCount( self );
     }
-SWIGINTERN char const *GDALRasterAttributeTableShadow_GetNameOfCol(GDALRasterAttributeTableShadow *self,int iCol){ 
+SWIGINTERN char const *GDALRasterAttributeTableShadow_GetNameOfCol(GDALRasterAttributeTableShadow *self,int iCol){
         return GDALRATGetNameOfCol( self, iCol );
     }
 SWIGINTERN GDALRATFieldUsage GDALRasterAttributeTableShadow_GetUsageOfCol(GDALRasterAttributeTableShadow *self,int iCol){
@@ -1273,25 +1287,25 @@ SWIGINTERN GDALRATFieldType GDALRasterAttributeTableShadow_GetTypeOfCol(GDALRast
 SWIGINTERN int GDALRasterAttributeTableShadow_GetColOfUsage(GDALRasterAttributeTableShadow *self,GDALRATFieldUsage eUsage){
         return GDALRATGetColOfUsage( self, eUsage );
     }
-SWIGINTERN int GDALRasterAttributeTableShadow_GetRowCount(GDALRasterAttributeTableShadow *self){ 
+SWIGINTERN int GDALRasterAttributeTableShadow_GetRowCount(GDALRasterAttributeTableShadow *self){
         return GDALRATGetRowCount( self );
     }
-SWIGINTERN char const *GDALRasterAttributeTableShadow_GetValueAsString(GDALRasterAttributeTableShadow *self,int iRow,int iCol){ 
+SWIGINTERN char const *GDALRasterAttributeTableShadow_GetValueAsString(GDALRasterAttributeTableShadow *self,int iRow,int iCol){
         return GDALRATGetValueAsString( self, iRow, iCol );
     }
-SWIGINTERN int GDALRasterAttributeTableShadow_GetValueAsInt(GDALRasterAttributeTableShadow *self,int iRow,int iCol){ 
+SWIGINTERN int GDALRasterAttributeTableShadow_GetValueAsInt(GDALRasterAttributeTableShadow *self,int iRow,int iCol){
         return GDALRATGetValueAsInt( self, iRow, iCol );
     }
-SWIGINTERN double GDALRasterAttributeTableShadow_GetValueAsDouble(GDALRasterAttributeTableShadow *self,int iRow,int iCol){ 
+SWIGINTERN double GDALRasterAttributeTableShadow_GetValueAsDouble(GDALRasterAttributeTableShadow *self,int iRow,int iCol){
         return GDALRATGetValueAsDouble( self, iRow, iCol );
     }
-SWIGINTERN void GDALRasterAttributeTableShadow_SetValueAsString(GDALRasterAttributeTableShadow *self,int iRow,int iCol,char const *pszValue){ 
+SWIGINTERN void GDALRasterAttributeTableShadow_SetValueAsString(GDALRasterAttributeTableShadow *self,int iRow,int iCol,char const *pszValue){
         GDALRATSetValueAsString( self, iRow, iCol, pszValue );
     }
-SWIGINTERN void GDALRasterAttributeTableShadow_SetValueAsInt(GDALRasterAttributeTableShadow *self,int iRow,int iCol,int nValue){ 
+SWIGINTERN void GDALRasterAttributeTableShadow_SetValueAsInt(GDALRasterAttributeTableShadow *self,int iRow,int iCol,int nValue){
         GDALRATSetValueAsInt( self, iRow, iCol, nValue );
     }
-SWIGINTERN void GDALRasterAttributeTableShadow_SetValueAsDouble(GDALRasterAttributeTableShadow *self,int iRow,int iCol,double dfValue){ 
+SWIGINTERN void GDALRasterAttributeTableShadow_SetValueAsDouble(GDALRasterAttributeTableShadow *self,int iRow,int iCol,double dfValue){
         GDALRATSetValueAsDouble( self, iRow, iCol, dfValue );
     }
 SWIGINTERN void GDALRasterAttributeTableShadow_SetRowCount(GDALRasterAttributeTableShadow *self,int nCount){
@@ -1318,7 +1332,7 @@ SWIGINTERN void GDALRasterAttributeTableShadow_DumpReadable(GDALRasterAttributeT
 
 #include "gdalgrid.h"
 
-#ifdef DEBUG 
+#ifdef DEBUG
 typedef struct OGRLayerHS OGRLayerShadow;
 typedef struct OGRGeometryHS OGRGeometryShadow;
 #else
@@ -1345,7 +1359,7 @@ int  ComputeMedianCutPCT ( GDALRasterBandShadow *red,
                                           colors,
                                           callback,
                                           callback_data);
-    
+
     return err;
 }
 
@@ -1367,7 +1381,7 @@ int  DitherRGB2PCT ( GDALRasterBandShadow *red,
                                   colors,
                                   callback,
                                   callback_data);
-    
+
     return err;
 }
 
@@ -1380,10 +1394,18 @@ CPLErr  ReprojectImage ( GDALDatasetShadow *src_ds,
                          double WarpMemoryLimit=0.0,
                          double maxerror = 0.0,
 			 GDALProgressFunc callback = NULL,
-                     	 void* callback_data=NULL) {
+                     	 void* callback_data=NULL,
+                         char** options = NULL ) {
 
     CPLErrorReset();
 
+    GDALWarpOptions* psOptions = NULL;
+    if( options != NULL )
+    {
+        psOptions = GDALCreateWarpOptions();
+        psOptions->papszWarpOptions = CSLDuplicate(options);
+    }
+
     CPLErr err = GDALReprojectImage( src_ds,
                                      src_wkt,
                                      dst_ds,
@@ -1393,8 +1415,11 @@ CPLErr  ReprojectImage ( GDALDatasetShadow *src_ds,
                                      maxerror,
                                      callback,
                                      callback_data,
-                                     NULL);
-    
+                                     psOptions);
+
+    if( psOptions != NULL )
+        GDALDestroyWarpOptions(psOptions);
+
     return err;
 }
 
@@ -1416,8 +1441,8 @@ int  RasterizeLayer( GDALDatasetShadow *dataset,
                  int bands, int *band_list,
                  OGRLayerShadow *layer,
                  void *pfnTransformer = NULL,
-                 void *pTransformArg = NULL, 
-		 int burn_values = 0, double *burn_values_list = NULL, 
+                 void *pTransformArg = NULL,
+		 int burn_values = 0, double *burn_values_list = NULL,
                  char **options = NULL,
                  GDALProgressFunc callback=NULL,
                  void* callback_data=NULL) {
@@ -1434,16 +1459,16 @@ int  RasterizeLayer( GDALDatasetShadow *dataset,
     }
     else if( burn_values != bands )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Did not get the expected number of burn values in RasterizeLayer()" );
         return CE_Failure;
     }
 
     eErr = GDALRasterizeLayers( dataset, bands, band_list,
-                                1, &layer, 
-                                (GDALTransformerFunc) pfnTransformer, 
+                                1, &layer,
+                                (GDALTransformerFunc) pfnTransformer,
                                 pTransformArg,
-                                burn_values_list, options, 
+                                burn_values_list, options,
                                 callback, callback_data );
 
     if( burn_values == 0 )
@@ -1455,7 +1480,7 @@ int  RasterizeLayer( GDALDatasetShadow *dataset,
 
 int  Polygonize( GDALRasterBandShadow *srcBand,
      		 GDALRasterBandShadow *maskBand,
-  	         OGRLayerShadow *outLayer, 
+  	         OGRLayerShadow *outLayer,
                  int iPixValField,
                  char **options = NULL,
                  GDALProgressFunc callback=NULL,
@@ -1468,6 +1493,21 @@ int  Polygonize( GDALRasterBandShadow *srcBand,
 }
 
 
+int  FPolygonize( GDALRasterBandShadow *srcBand,
+                 GDALRasterBandShadow *maskBand,
+                 OGRLayerShadow *outLayer,
+                 int iPixValField,
+                 char **options = NULL,
+                 GDALProgressFunc callback=NULL,
+                 void* callback_data=NULL) {
+
+    CPLErrorReset();
+
+    return GDALFPolygonize( srcBand, maskBand, outLayer, iPixValField,
+                           options, callback, callback_data );
+}
+
+
 int  FillNodata( GDALRasterBandShadow *targetBand,
      		 GDALRasterBandShadow *maskBand,
                  double maxSearchDist,
@@ -1478,8 +1518,8 @@ int  FillNodata( GDALRasterBandShadow *targetBand,
 
     CPLErrorReset();
 
-    return GDALFillNodata( targetBand, maskBand, maxSearchDist, 
-    	   		   0, smoothingIterations, options, 
+    return GDALFillNodata( targetBand, maskBand, maxSearchDist,
+    	   		   0, smoothingIterations, options,
 			   callback, callback_data );
 }
 
@@ -1494,7 +1534,7 @@ int  SieveFilter( GDALRasterBandShadow *srcBand,
 
     CPLErrorReset();
 
-    return GDALSieveFilter( srcBand, maskBand, dstBand, 
+    return GDALSieveFilter( srcBand, maskBand, dstBand,
                             threshold, connectedness,
                             options, callback, callback_data );
 }
@@ -1534,7 +1574,7 @@ int ContourGenerate( GDALRasterBandShadow *srcBand,
                      double *fixedLevels,
                      int useNoData,
                      double noDataValue,
-                     OGRLayerShadow* dstLayer, 
+                     OGRLayerShadow* dstLayer,
                      int idField,
                      int elevField,
                      GDALProgressFunc callback = NULL,
@@ -1575,12 +1615,24 @@ GDALDatasetShadow *AutoCreateWarpedVRT( GDALDatasetShadow *src_ds,
     /*throw CPLGetLastErrorMsg(); causes a SWIG_exception later*/
   }
   return ds;
-  
+
+}
+
+
+GDALDatasetShadow*  CreatePansharpenedVRT( const char* pszXML,
+                            GDALRasterBandShadow* panchroBand,
+                            int nInputSpectralBands,
+                            GDALRasterBandShadow** ahInputSpectralBands )
+{
+    CPLErrorReset();
+
+    return (GDALDatasetShadow*)GDALCreatePansharpenedVRT( pszXML, panchroBand,
+                                      nInputSpectralBands, ahInputSpectralBands );
 }
 
 SWIGINTERN GDALTransformerInfoShadow *new_GDALTransformerInfoShadow(GDALDatasetShadow *src,GDALDatasetShadow *dst,char **options){
-    GDALTransformerInfoShadow *obj = (GDALTransformerInfoShadow*) 
-       GDALCreateGenImgProjTransformer2( (GDALDatasetH)src, (GDALDatasetH)dst, 
+    GDALTransformerInfoShadow *obj = (GDALTransformerInfoShadow*)
+       GDALCreateGenImgProjTransformer2( (GDALDatasetH)src, (GDALDatasetH)dst,
                                          options );
     return obj;
   }
@@ -1590,20 +1642,20 @@ SWIGINTERN void delete_GDALTransformerInfoShadow(GDALTransformerInfoShadow *self
 SWIGINTERN int GDALTransformerInfoShadow_TransformPoint__SWIG_0(GDALTransformerInfoShadow *self,int bDstToSrc,double inout[3]){
     int nRet, nSuccess = TRUE;
 
-    nRet = GDALUseTransformer( self, bDstToSrc, 
-                               1, &inout[0], &inout[1], &inout[2], 
+    nRet = GDALUseTransformer( self, bDstToSrc,
+                               1, &inout[0], &inout[1], &inout[2],
                                &nSuccess );
 
     return nRet && nSuccess;
   }
 SWIGINTERN int GDALTransformerInfoShadow_TransformPoint__SWIG_1(GDALTransformerInfoShadow *self,double argout[3],int bDstToSrc,double x,double y,double z=0.0){
     int nRet, nSuccess = TRUE;
-    
+
     argout[0] = x;
     argout[1] = y;
     argout[2] = z;
-    nRet = GDALUseTransformer( self, bDstToSrc, 
-                               1, &argout[0], &argout[1], &argout[2], 
+    nRet = GDALUseTransformer( self, bDstToSrc,
+                               1, &argout[0], &argout[1], &argout[2],
                                &nSuccess );
 
     return nRet && nSuccess;
@@ -1619,7 +1671,7 @@ SWIGINTERN int GDALTransformerInfoShadow_TransformGeolocations(GDALTransformerIn
 
     CPLErrorReset();
 
-    return GDALTransformGeolocations( xBand, yBand, zBand, 
+    return GDALTransformGeolocations( xBand, yBand, zBand,
                                       GDALUseTransformer, self,
                             	      callback, callback_data, options );
   }
@@ -1658,6 +1710,7 @@ int GetDriverCount() {
 }
 
 
+static
 GDALDriverShadow* GetDriverByName( char const *name ) {
   return (GDALDriverShadow*) GDALGetDriverByName( name );
 }
@@ -1685,6 +1738,10 @@ GDALDatasetShadow* OpenEx( char const* utf8_path, unsigned int nOpenFlags = 0,
                            char** allowed_drivers = NULL, char** open_options = NULL,
                            char** sibling_files = NULL ) {
   CPLErrorReset();
+#ifdef SWIGPYTHON
+  if( GetUseExceptions() )
+      nOpenFlags |= GDAL_OF_VERBOSE_ERROR;
+#endif
   GDALDatasetShadow *ds = GDALOpenEx( utf8_path, nOpenFlags, allowed_drivers,
                                       open_options, sibling_files );
   if( ds != NULL && CPLGetLastErrorType() == CE_Failure )
@@ -1710,9 +1767,9 @@ GDALDatasetShadow* OpenShared( char const* utf8_path, GDALAccess eAccess = GA_Re
 }
 
 
-GDALDriverShadow *IdentifyDriver( const char *utf8_path, 
+GDALDriverShadow *IdentifyDriver( const char *utf8_path,
                                   char **papszSiblings = NULL ) {
-    return (GDALDriverShadow *) GDALIdentifyDriver( utf8_path, 
+    return (GDALDriverShadow *) GDALIdentifyDriver( utf8_path,
 	                                            papszSiblings );
 }
 
@@ -1720,8 +1777,11 @@ GDALDriverShadow *IdentifyDriver( const char *utf8_path,
   char **GeneralCmdLineProcessor( char **papszArgv, int nOptions = 0 ) {
     int nResArgCount;
 
-    nResArgCount = 
-      GDALGeneralCmdLineProcessor( CSLCount(papszArgv), &papszArgv, nOptions ); 
+    if( papszArgv == NULL )
+        return NULL;
+
+    nResArgCount =
+      GDALGeneralCmdLineProcessor( CSLCount(papszArgv), &papszArgv, nOptions );
 
     if( nResArgCount <= 0 )
         return NULL;
@@ -1751,6 +1811,377 @@ GDALDriverShadow *IdentifyDriver( const char *utf8_path,
     }
 
 
+#include "gdal_utils.h"
+
+SWIGINTERN GDALInfoOptions *new_GDALInfoOptions(char **options){
+        return GDALInfoOptionsNew(options, NULL);
+    }
+SWIGINTERN void delete_GDALInfoOptions(GDALInfoOptions *self){
+        GDALInfoOptionsFree( self );
+    }
+SWIGINTERN GDALTranslateOptions *new_GDALTranslateOptions(char **options){
+        return GDALTranslateOptionsNew(options, NULL);
+    }
+SWIGINTERN void delete_GDALTranslateOptions(GDALTranslateOptions *self){
+        GDALTranslateOptionsFree( self );
+    }
+
+GDALDatasetShadow* wrapper_GDALTranslate( const char* dest,
+                                      GDALDatasetShadow* dataset,
+                                      GDALTranslateOptions* translateOptions,
+                                      GDALProgressFunc callback=NULL,
+                                      void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( translateOptions == NULL )
+        {
+            bFreeOptions = true;
+            translateOptions = GDALTranslateOptionsNew(NULL, NULL);
+        }
+        GDALTranslateOptionsSetProgress(translateOptions, callback, callback_data);
+    }
+    GDALDatasetH hDSRet = GDALTranslate(dest, dataset, translateOptions, &usageError);
+    if( bFreeOptions )
+        GDALTranslateOptionsFree(translateOptions);
+    return hDSRet;
+}
+
+SWIGINTERN GDALWarpAppOptions *new_GDALWarpAppOptions(char **options){
+        return GDALWarpAppOptionsNew(options, NULL);
+    }
+SWIGINTERN void delete_GDALWarpAppOptions(GDALWarpAppOptions *self){
+        GDALWarpAppOptionsFree( self );
+    }
+
+int wrapper_GDALWarpDestDS( GDALDatasetShadow* dstDS,
+                            int object_list_count, GDALDatasetShadow** poObjects,
+                            GDALWarpAppOptions* warpAppOptions,
+                            GDALProgressFunc callback=NULL,
+                            void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( warpAppOptions == NULL )
+        {
+            bFreeOptions = true;
+            warpAppOptions = GDALWarpAppOptionsNew(NULL, NULL);
+        }
+        GDALWarpAppOptionsSetProgress(warpAppOptions, callback, callback_data);
+    }
+    int bRet = (GDALWarp(NULL, dstDS, object_list_count, poObjects, warpAppOptions, &usageError) != NULL);
+    if( bFreeOptions )
+        GDALWarpAppOptionsFree(warpAppOptions);
+    return bRet;
+}
+
+
+GDALDatasetShadow* wrapper_GDALWarpDestName( const char* dest,
+                                             int object_list_count, GDALDatasetShadow** poObjects,
+                                             GDALWarpAppOptions* warpAppOptions,
+                                             GDALProgressFunc callback=NULL,
+                                             void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( warpAppOptions == NULL )
+        {
+            bFreeOptions = true;
+            warpAppOptions = GDALWarpAppOptionsNew(NULL, NULL);
+        }
+        GDALWarpAppOptionsSetProgress(warpAppOptions, callback, callback_data);
+    }
+    GDALDatasetH hDSRet = GDALWarp(dest, NULL, object_list_count, poObjects, warpAppOptions, &usageError);
+    if( bFreeOptions )
+        GDALWarpAppOptionsFree(warpAppOptions);
+    return hDSRet;
+}
+
+SWIGINTERN GDALVectorTranslateOptions *new_GDALVectorTranslateOptions(char **options){
+        return GDALVectorTranslateOptionsNew(options, NULL);
+    }
+SWIGINTERN void delete_GDALVectorTranslateOptions(GDALVectorTranslateOptions *self){
+        GDALVectorTranslateOptionsFree( self );
+    }
+
+int wrapper_GDALVectorTranslateDestDS( GDALDatasetShadow* dstDS,
+                                       GDALDatasetShadow* srcDS,
+                            GDALVectorTranslateOptions* options,
+                            GDALProgressFunc callback=NULL,
+                            void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( options == NULL )
+        {
+            bFreeOptions = true;
+            options = GDALVectorTranslateOptionsNew(NULL, NULL);
+        }
+        GDALVectorTranslateOptionsSetProgress(options, callback, callback_data);
+    }
+    int bRet = (GDALVectorTranslate(NULL, dstDS, 1, &srcDS, options, &usageError) != NULL);
+    if( bFreeOptions )
+        GDALVectorTranslateOptionsFree(options);
+    return bRet;
+}
+
+
+GDALDatasetShadow* wrapper_GDALVectorTranslateDestName( const char* dest,
+                                             GDALDatasetShadow* srcDS,
+                                             GDALVectorTranslateOptions* options,
+                                             GDALProgressFunc callback=NULL,
+                                             void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( options == NULL )
+        {
+            bFreeOptions = true;
+            options = GDALVectorTranslateOptionsNew(NULL, NULL);
+        }
+        GDALVectorTranslateOptionsSetProgress(options, callback, callback_data);
+    }
+    GDALDatasetH hDSRet = GDALVectorTranslate(dest, NULL, 1, &srcDS, options, &usageError);
+    if( bFreeOptions )
+        GDALVectorTranslateOptionsFree(options);
+    return hDSRet;
+}
+
+SWIGINTERN GDALDEMProcessingOptions *new_GDALDEMProcessingOptions(char **options){
+        return GDALDEMProcessingOptionsNew(options, NULL);
+    }
+SWIGINTERN void delete_GDALDEMProcessingOptions(GDALDEMProcessingOptions *self){
+        GDALDEMProcessingOptionsFree( self );
+    }
+
+GDALDatasetShadow* wrapper_GDALDEMProcessing( const char* dest,
+                                      GDALDatasetShadow* dataset,
+                                      const char* pszProcessing,
+                                      const char* pszColorFilename,
+                                      GDALDEMProcessingOptions* options,
+                                      GDALProgressFunc callback=NULL,
+                                      void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( options == NULL )
+        {
+            bFreeOptions = true;
+            options = GDALDEMProcessingOptionsNew(NULL, NULL);
+        }
+        GDALDEMProcessingOptionsSetProgress(options, callback, callback_data);
+    }
+    GDALDatasetH hDSRet = GDALDEMProcessing(dest, dataset, pszProcessing, pszColorFilename, options, &usageError);
+    if( bFreeOptions )
+        GDALDEMProcessingOptionsFree(options);
+    return hDSRet;
+}
+
+SWIGINTERN GDALNearblackOptions *new_GDALNearblackOptions(char **options){
+        return GDALNearblackOptionsNew(options, NULL);
+    }
+SWIGINTERN void delete_GDALNearblackOptions(GDALNearblackOptions *self){
+        GDALNearblackOptionsFree( self );
+    }
+
+int wrapper_GDALNearblackDestDS( GDALDatasetShadow* dstDS,
+                            GDALDatasetShadow* srcDS,
+                            GDALNearblackOptions* options,
+                            GDALProgressFunc callback=NULL,
+                            void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( options == NULL )
+        {
+            bFreeOptions = true;
+            options = GDALNearblackOptionsNew(NULL, NULL);
+        }
+        GDALNearblackOptionsSetProgress(options, callback, callback_data);
+    }
+    int bRet = (GDALNearblack(NULL, dstDS, srcDS, options, &usageError) != NULL);
+    if( bFreeOptions )
+        GDALNearblackOptionsFree(options);
+    return bRet;
+}
+
+
+GDALDatasetShadow* wrapper_GDALNearblackDestName( const char* dest,
+                                             GDALDatasetShadow* srcDS,
+                                             GDALNearblackOptions* options,
+                                             GDALProgressFunc callback=NULL,
+                                             void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( options == NULL )
+        {
+            bFreeOptions = true;
+            options = GDALNearblackOptionsNew(NULL, NULL);
+        }
+        GDALNearblackOptionsSetProgress(options, callback, callback_data);
+    }
+    GDALDatasetH hDSRet = GDALNearblack(dest, NULL, srcDS, options, &usageError);
+    if( bFreeOptions )
+        GDALNearblackOptionsFree(options);
+    return hDSRet;
+}
+
+SWIGINTERN GDALGridOptions *new_GDALGridOptions(char **options){
+        return GDALGridOptionsNew(options, NULL);
+    }
+SWIGINTERN void delete_GDALGridOptions(GDALGridOptions *self){
+        GDALGridOptionsFree( self );
+    }
+
+GDALDatasetShadow* wrapper_GDALGrid( const char* dest,
+                                      GDALDatasetShadow* dataset,
+                                      GDALGridOptions* options,
+                                      GDALProgressFunc callback=NULL,
+                                      void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( options == NULL )
+        {
+            bFreeOptions = true;
+            options = GDALGridOptionsNew(NULL, NULL);
+        }
+        GDALGridOptionsSetProgress(options, callback, callback_data);
+    }
+    GDALDatasetH hDSRet = GDALGrid(dest, dataset, options, &usageError);
+    if( bFreeOptions )
+        GDALGridOptionsFree(options);
+    return hDSRet;
+}
+
+SWIGINTERN GDALRasterizeOptions *new_GDALRasterizeOptions(char **options){
+        return GDALRasterizeOptionsNew(options, NULL);
+    }
+SWIGINTERN void delete_GDALRasterizeOptions(GDALRasterizeOptions *self){
+        GDALRasterizeOptionsFree( self );
+    }
+
+int wrapper_GDALRasterizeDestDS( GDALDatasetShadow* dstDS,
+                            GDALDatasetShadow* srcDS,
+                            GDALRasterizeOptions* options,
+                            GDALProgressFunc callback=NULL,
+                            void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( options == NULL )
+        {
+            bFreeOptions = true;
+            options = GDALRasterizeOptionsNew(NULL, NULL);
+        }
+        GDALRasterizeOptionsSetProgress(options, callback, callback_data);
+    }
+    int bRet = (GDALRasterize(NULL, dstDS, srcDS, options, &usageError) != NULL);
+    if( bFreeOptions )
+        GDALRasterizeOptionsFree(options);
+    return bRet;
+}
+
+
+GDALDatasetShadow* wrapper_GDALRasterizeDestName( const char* dest,
+                                             GDALDatasetShadow* srcDS,
+                                             GDALRasterizeOptions* options,
+                                             GDALProgressFunc callback=NULL,
+                                             void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( options == NULL )
+        {
+            bFreeOptions = true;
+            options = GDALRasterizeOptionsNew(NULL, NULL);
+        }
+        GDALRasterizeOptionsSetProgress(options, callback, callback_data);
+    }
+    GDALDatasetH hDSRet = GDALRasterize(dest, NULL, srcDS, options, &usageError);
+    if( bFreeOptions )
+        GDALRasterizeOptionsFree(options);
+    return hDSRet;
+}
+
+SWIGINTERN GDALBuildVRTOptions *new_GDALBuildVRTOptions(char **options){
+        return GDALBuildVRTOptionsNew(options, NULL);
+    }
+SWIGINTERN void delete_GDALBuildVRTOptions(GDALBuildVRTOptions *self){
+        GDALBuildVRTOptionsFree( self );
+    }
+
+GDALDatasetShadow* wrapper_GDALBuildVRT_objects( const char* dest,
+                                             int object_list_count, GDALDatasetShadow** poObjects,
+                                             GDALBuildVRTOptions* options,
+                                             GDALProgressFunc callback=NULL,
+                                             void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( options == NULL )
+        {
+            bFreeOptions = true;
+            options = GDALBuildVRTOptionsNew(NULL, NULL);
+        }
+        GDALBuildVRTOptionsSetProgress(options, callback, callback_data);
+    }
+    GDALDatasetH hDSRet = GDALBuildVRT(dest, object_list_count, poObjects, NULL, options, &usageError);
+    if( bFreeOptions )
+        GDALBuildVRTOptionsFree(options);
+    return hDSRet;
+}
+
+
+GDALDatasetShadow* wrapper_GDALBuildVRT_names( const char* dest,
+                                         char ** source_filenames,
+                                         GDALBuildVRTOptions* options,
+                                         GDALProgressFunc callback=NULL,
+                                         void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( options == NULL )
+        {
+            bFreeOptions = true;
+            options = GDALBuildVRTOptionsNew(NULL, NULL);
+        }
+        GDALBuildVRTOptionsSetProgress(options, callback, callback_data);
+    }
+    GDALDatasetH hDSRet = GDALBuildVRT(dest, CSLCount(source_filenames), NULL, source_filenames, options, &usageError);
+    if( bFreeOptions )
+        GDALBuildVRTOptionsFree(options);
+    return hDSRet;
+}
+
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -2225,6 +2656,68 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_GetLastErrorMsg() {
 }
 
 
+SWIGEXPORT int SWIGSTDCALL CSharp_VSIGetLastErrorNo() {
+  int jresult ;
+  int result;
+  
+  {
+    CPLErrorReset();
+    result = (int)VSIGetLastErrorNo();
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT char * SWIGSTDCALL CSharp_VSIGetLastErrorMsg() {
+  char * jresult ;
+  char *result = 0 ;
+  
+  {
+    CPLErrorReset();
+    result = (char *)VSIGetLastErrorMsg();
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = SWIG_csharp_string_callback((const char *)result); 
+  return jresult;
+}
+
+
 SWIGEXPORT void SWIGSTDCALL CSharp_PushFinderLocation(char * jarg1) {
   char *arg1 = (char *) 0 ;
   
@@ -2355,12 +2848,14 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_FindFile(char * jarg1, char * jarg2) {
 }
 
 
-SWIGEXPORT void * SWIGSTDCALL CSharp_ReadDir(char * jarg1) {
+SWIGEXPORT void * SWIGSTDCALL CSharp_ReadDir(char * jarg1, int jarg2) {
   void * jresult ;
   char *arg1 = (char *) 0 ;
+  int arg2 = (int) 0 ;
   char **result = 0 ;
   
   arg1 = (char *)jarg1; 
+  arg2 = (int)jarg2; 
   {
     if (!arg1) {
       {
@@ -2370,7 +2865,7 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_ReadDir(char * jarg1) {
   }
   {
     CPLErrorReset();
-    result = (char **)VSIReadDir((char const *)arg1);
+    result = (char **)wrapper_VSIReadDirEx((char const *)arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2801,6 +3296,20 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Rename(char * jarg1, char * jarg2) {
   arg1 = (char *)jarg1; 
   arg2 = (char *)jarg2; 
   {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
     CPLErrorReset();
     result = VSIRename((char const *)arg1,(char const *)arg2);
     CPLErr eclass = CPLGetLastErrorType();
@@ -2869,6 +3378,50 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_VSIFOpenL(char * jarg1, char * jarg2) {
 }
 
 
+SWIGEXPORT void * SWIGSTDCALL CSharp_VSIFOpenExL(char * jarg1, char * jarg2, int jarg3) {
+  void * jresult ;
+  char *arg1 = (char *) 0 ;
+  char *arg2 = (char *) 0 ;
+  int arg3 ;
+  VSILFILE *result = 0 ;
+  
+  arg1 = (char *)jarg1; 
+  arg2 = (char *)jarg2; 
+  arg3 = (int)jarg3; 
+  {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (VSILFILE *)wrapper_VSIFOpenExL((char const *)arg1,(char const *)arg2,arg3);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
 SWIGEXPORT int SWIGSTDCALL CSharp_VSIFCloseL(void * jarg1) {
   int jresult ;
   VSILFILE *arg1 = (VSILFILE *) 0 ;
@@ -2876,6 +3429,13 @@ SWIGEXPORT int SWIGSTDCALL CSharp_VSIFCloseL(void * jarg1) {
   
   arg1 = (VSILFILE *)jarg1; 
   {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
     CPLErrorReset();
     result = VSIFCloseL(arg1);
     CPLErr eclass = CPLGetLastErrorType();
@@ -2913,6 +3473,13 @@ SWIGEXPORT int SWIGSTDCALL CSharp_VSIFSeekL(void * jarg1, long jarg2, int jarg3)
   arg2 = (long)jarg2; 
   arg3 = (int)jarg3; 
   {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
     CPLErrorReset();
     result = VSIFSeekL(arg1,arg2,arg3);
     CPLErr eclass = CPLGetLastErrorType();
@@ -2946,6 +3513,13 @@ SWIGEXPORT long SWIGSTDCALL CSharp_VSIFTellL(void * jarg1) {
   
   arg1 = (VSILFILE *)jarg1; 
   {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
     CPLErrorReset();
     result = (long)VSIFTellL(arg1);
     CPLErr eclass = CPLGetLastErrorType();
@@ -2981,6 +3555,13 @@ SWIGEXPORT int SWIGSTDCALL CSharp_VSIFTruncateL(void * jarg1, long jarg2) {
   arg1 = (VSILFILE *)jarg1; 
   arg2 = (long)jarg2; 
   {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
     CPLErrorReset();
     result = VSIFTruncateL(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
@@ -3020,6 +3601,13 @@ SWIGEXPORT int SWIGSTDCALL CSharp_VSIFWriteL(char * jarg1, int jarg2, int jarg3,
   arg3 = (int)jarg3; 
   arg4 = (VSILFILE *)jarg4; 
   {
+    if (!arg4) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
     CPLErrorReset();
     result = (int)VSIFWriteL((char const *)arg1,arg2,arg3,arg4);
     CPLErr eclass = CPLGetLastErrorType();
@@ -3046,6 +3634,46 @@ SWIGEXPORT int SWIGSTDCALL CSharp_VSIFWriteL(char * jarg1, int jarg2, int jarg3,
 }
 
 
+SWIGEXPORT void * SWIGSTDCALL CSharp_ParseCommandLine(char * jarg1) {
+  void * jresult ;
+  char *arg1 = (char *) 0 ;
+  char **result = 0 ;
+  
+  arg1 = (char *)jarg1; 
+  {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (char **)CSLParseCommandLine((char const *)arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
 SWIGEXPORT int SWIGSTDCALL CSharp_XMLNode_Type_get(void * jarg1) {
   int jresult ;
   CPLXMLNode *arg1 = (CPLXMLNode *) 0 ;
@@ -6156,7 +6784,7 @@ SWIGEXPORT int SWIGSTDCALL CSharp_GCPsToGeoTransform(int jarg1, void * jarg2, vo
   arg4 = (int)jarg4; 
   {
     CPLErrorReset();
-    result = GDALGCPsToGeoTransform(arg1,(GDAL_GCP const *)arg2,arg3,arg4);
+    result = (RETURN_NONE)GDALGCPsToGeoTransform(arg1,(GDAL_GCP const *)arg2,arg3,arg4);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -7800,6 +8428,39 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Band_SetNoDataValue(void * jarg1, double jarg2
 }
 
 
+SWIGEXPORT int SWIGSTDCALL CSharp_Band_DeleteNoDataValue(void * jarg1) {
+  int jresult ;
+  GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
+  CPLErr result;
+  
+  arg1 = (GDALRasterBandShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    result = (CPLErr)GDALRasterBandShadow_DeleteNoDataValue(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
 SWIGEXPORT char * SWIGSTDCALL CSharp_Band_GetUnitType(void * jarg1) {
   char * jresult ;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
@@ -10461,7 +11122,7 @@ SWIGEXPORT int SWIGSTDCALL CSharp_DitherRGB2PCT(void * jarg1, void * jarg2, void
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_ReprojectImage(void * jarg1, void * jarg2, char * jarg3, char * jarg4, int jarg5, double jarg6, double jarg7, void * jarg8, void * jarg9) {
+SWIGEXPORT int SWIGSTDCALL CSharp_ReprojectImage(void * jarg1, void * jarg2, char * jarg3, char * jarg4, int jarg5, double jarg6, double jarg7, void * jarg8, void * jarg9, void * jarg10) {
   int jresult ;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   GDALDatasetShadow *arg2 = (GDALDatasetShadow *) 0 ;
@@ -10472,6 +11133,7 @@ SWIGEXPORT int SWIGSTDCALL CSharp_ReprojectImage(void * jarg1, void * jarg2, cha
   double arg7 = (double) 0.0 ;
   GDALProgressFunc arg8 = (GDALProgressFunc) NULL ;
   void *arg9 = (void *) NULL ;
+  char **arg10 = (char **) NULL ;
   CPLErr result;
   
   arg1 = (GDALDatasetShadow *)jarg1; 
@@ -10483,6 +11145,7 @@ SWIGEXPORT int SWIGSTDCALL CSharp_ReprojectImage(void * jarg1, void * jarg2, cha
   arg7 = (double)jarg7; 
   arg8 = (GDALProgressFunc)jarg8; 
   arg9 = (void *)jarg9; 
+  arg10 = (char **)jarg10; 
   {
     if (!arg1) {
       {
@@ -10499,7 +11162,7 @@ SWIGEXPORT int SWIGSTDCALL CSharp_ReprojectImage(void * jarg1, void * jarg2, cha
   }
   {
     CPLErrorReset();
-    result = (CPLErr)ReprojectImage(arg1,arg2,(char const *)arg3,(char const *)arg4,arg5,arg6,arg7,arg8,arg9);
+    result = (CPLErr)ReprojectImage(arg1,arg2,(char const *)arg3,(char const *)arg4,arg5,arg6,arg7,arg8,arg9,arg10);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -10711,6 +11374,65 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Polygonize(void * jarg1, void * jarg2, void *
 }
 
 
+SWIGEXPORT int SWIGSTDCALL CSharp_FPolygonize(void * jarg1, void * jarg2, void * jarg3, int jarg4, void * jarg5, void * jarg6, void * jarg7) {
+  int jresult ;
+  GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
+  GDALRasterBandShadow *arg2 = (GDALRasterBandShadow *) 0 ;
+  OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
+  int arg4 ;
+  char **arg5 = (char **) NULL ;
+  GDALProgressFunc arg6 = (GDALProgressFunc) NULL ;
+  void *arg7 = (void *) NULL ;
+  int result;
+  
+  arg1 = (GDALRasterBandShadow *)jarg1; 
+  arg2 = (GDALRasterBandShadow *)jarg2; 
+  arg3 = (OGRLayerShadow *)jarg3; 
+  arg4 = (int)jarg4; 
+  arg5 = (char **)jarg5; 
+  arg6 = (GDALProgressFunc)jarg6; 
+  arg7 = (void *)jarg7; 
+  {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    if (!arg3) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (int)FPolygonize(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
 SWIGEXPORT int SWIGSTDCALL CSharp_FillNodata(void * jarg1, void * jarg2, double jarg3, int jarg4, void * jarg5, void * jarg6, void * jarg7) {
   int jresult ;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
@@ -11049,6 +11771,52 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_AutoCreateWarpedVRT(void * jarg1, char * ja
 }
 
 
+SWIGEXPORT void * SWIGSTDCALL CSharp_CreatePansharpenedVRT(char * jarg1, void * jarg2, int jarg3, void * jarg4) {
+  void * jresult ;
+  char *arg1 = (char *) 0 ;
+  GDALRasterBandShadow *arg2 = (GDALRasterBandShadow *) 0 ;
+  int arg3 ;
+  GDALRasterBandShadow **arg4 = (GDALRasterBandShadow **) 0 ;
+  GDALDatasetShadow *result = 0 ;
+  
+  arg1 = (char *)jarg1; 
+  arg2 = (GDALRasterBandShadow *)jarg2; 
+  arg3 = (int)jarg3; 
+  arg4 = (GDALRasterBandShadow **)jarg4; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (GDALDatasetShadow *)CreatePansharpenedVRT((char const *)arg1,arg2,arg3,arg4);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
 SWIGEXPORT void * SWIGSTDCALL CSharp_new_Transformer(void * jarg1, void * jarg2, void * jarg3) {
   void * jresult ;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
@@ -11386,7 +12154,7 @@ SWIGEXPORT int SWIGSTDCALL CSharp_InvGeoTransform(void * jarg1, void * jarg2) {
   }
   {
     CPLErrorReset();
-    result = GDALInvGeoTransform(arg1,arg2);
+    result = (RETURN_NONE)GDALInvGeoTransform(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -12461,6 +13229,1244 @@ SWIGEXPORT void SWIGSTDCALL CSharp___FreeCArray_GDAL_GCP(void * jarg1) {
 }
 
 
+SWIGEXPORT void * SWIGSTDCALL CSharp_new_GDALInfoOptions(void * jarg1) {
+  void * jresult ;
+  char **arg1 = (char **) 0 ;
+  GDALInfoOptions *result = 0 ;
+  
+  arg1 = (char **)jarg1; 
+  {
+    CPLErrorReset();
+    result = (GDALInfoOptions *)new_GDALInfoOptions(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_delete_GDALInfoOptions(void * jarg1) {
+  GDALInfoOptions *arg1 = (GDALInfoOptions *) 0 ;
+  
+  arg1 = (GDALInfoOptions *)jarg1; 
+  {
+    CPLErrorReset();
+    delete_GDALInfoOptions(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+}
+
+
+SWIGEXPORT char * SWIGSTDCALL CSharp_GDALInfo(void * jarg1, void * jarg2) {
+  char * jresult ;
+  GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
+  GDALInfoOptions *arg2 = (GDALInfoOptions *) 0 ;
+  retStringAndCPLFree *result = 0 ;
+  
+  arg1 = (GDALDatasetShadow *)jarg1; 
+  arg2 = (GDALInfoOptions *)jarg2; 
+  {
+    CPLErrorReset();
+    result = (retStringAndCPLFree *)GDALInfo(arg1,arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  
+  /* %typemap(out) (retStringAndCPLFree*) */
+  if(result)
+  {
+    jresult = SWIG_csharp_string_callback((const char *)result);
+    CPLFree(result);
+  }
+  else
+  {
+    jresult = NULL;
+  }
+  
+  return jresult;
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_new_GDALTranslateOptions(void * jarg1) {
+  void * jresult ;
+  char **arg1 = (char **) 0 ;
+  GDALTranslateOptions *result = 0 ;
+  
+  arg1 = (char **)jarg1; 
+  {
+    CPLErrorReset();
+    result = (GDALTranslateOptions *)new_GDALTranslateOptions(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_delete_GDALTranslateOptions(void * jarg1) {
+  GDALTranslateOptions *arg1 = (GDALTranslateOptions *) 0 ;
+  
+  arg1 = (GDALTranslateOptions *)jarg1; 
+  {
+    CPLErrorReset();
+    delete_GDALTranslateOptions(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_wrapper_GDALTranslate(char * jarg1, void * jarg2, void * jarg3, void * jarg4, void * jarg5) {
+  void * jresult ;
+  char *arg1 = (char *) 0 ;
+  GDALDatasetShadow *arg2 = (GDALDatasetShadow *) 0 ;
+  GDALTranslateOptions *arg3 = (GDALTranslateOptions *) 0 ;
+  GDALProgressFunc arg4 = (GDALProgressFunc) NULL ;
+  void *arg5 = (void *) NULL ;
+  GDALDatasetShadow *result = 0 ;
+  
+  arg1 = (char *)jarg1; 
+  arg2 = (GDALDatasetShadow *)jarg2; 
+  arg3 = (GDALTranslateOptions *)jarg3; 
+  arg4 = (GDALProgressFunc)jarg4; 
+  arg5 = (void *)jarg5; 
+  {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (GDALDatasetShadow *)wrapper_GDALTranslate((char const *)arg1,arg2,arg3,arg4,arg5);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_new_GDALWarpAppOptions(void * jarg1) {
+  void * jresult ;
+  char **arg1 = (char **) 0 ;
+  GDALWarpAppOptions *result = 0 ;
+  
+  arg1 = (char **)jarg1; 
+  {
+    CPLErrorReset();
+    result = (GDALWarpAppOptions *)new_GDALWarpAppOptions(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_delete_GDALWarpAppOptions(void * jarg1) {
+  GDALWarpAppOptions *arg1 = (GDALWarpAppOptions *) 0 ;
+  
+  arg1 = (GDALWarpAppOptions *)jarg1; 
+  {
+    CPLErrorReset();
+    delete_GDALWarpAppOptions(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_wrapper_GDALWarpDestDS(void * jarg1, int jarg2, void * jarg3, void * jarg4, void * jarg5, void * jarg6) {
+  int jresult ;
+  GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
+  int arg2 ;
+  GDALDatasetShadow **arg3 = (GDALDatasetShadow **) 0 ;
+  GDALWarpAppOptions *arg4 = (GDALWarpAppOptions *) 0 ;
+  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
+  void *arg6 = (void *) NULL ;
+  int result;
+  
+  arg1 = (GDALDatasetShadow *)jarg1; 
+  arg2 = (int)jarg2; 
+  arg3 = (GDALDatasetShadow **)jarg3; 
+  arg4 = (GDALWarpAppOptions *)jarg4; 
+  arg5 = (GDALProgressFunc)jarg5; 
+  arg6 = (void *)jarg6; 
+  {
+    CPLErrorReset();
+    result = (int)wrapper_GDALWarpDestDS(arg1,arg2,arg3,arg4,arg5,arg6);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_wrapper_GDALWarpDestName(char * jarg1, int jarg2, void * jarg3, void * jarg4, void * jarg5, void * jarg6) {
+  void * jresult ;
+  char *arg1 = (char *) 0 ;
+  int arg2 ;
+  GDALDatasetShadow **arg3 = (GDALDatasetShadow **) 0 ;
+  GDALWarpAppOptions *arg4 = (GDALWarpAppOptions *) 0 ;
+  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
+  void *arg6 = (void *) NULL ;
+  GDALDatasetShadow *result = 0 ;
+  
+  arg1 = (char *)jarg1; 
+  arg2 = (int)jarg2; 
+  arg3 = (GDALDatasetShadow **)jarg3; 
+  arg4 = (GDALWarpAppOptions *)jarg4; 
+  arg5 = (GDALProgressFunc)jarg5; 
+  arg6 = (void *)jarg6; 
+  {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (GDALDatasetShadow *)wrapper_GDALWarpDestName((char const *)arg1,arg2,arg3,arg4,arg5,arg6);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_new_GDALVectorTranslateOptions(void * jarg1) {
+  void * jresult ;
+  char **arg1 = (char **) 0 ;
+  GDALVectorTranslateOptions *result = 0 ;
+  
+  arg1 = (char **)jarg1; 
+  {
+    CPLErrorReset();
+    result = (GDALVectorTranslateOptions *)new_GDALVectorTranslateOptions(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_delete_GDALVectorTranslateOptions(void * jarg1) {
+  GDALVectorTranslateOptions *arg1 = (GDALVectorTranslateOptions *) 0 ;
+  
+  arg1 = (GDALVectorTranslateOptions *)jarg1; 
+  {
+    CPLErrorReset();
+    delete_GDALVectorTranslateOptions(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_wrapper_GDALVectorTranslateDestDS(void * jarg1, void * jarg2, void * jarg3, void * jarg4, void * jarg5) {
+  int jresult ;
+  GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
+  GDALDatasetShadow *arg2 = (GDALDatasetShadow *) 0 ;
+  GDALVectorTranslateOptions *arg3 = (GDALVectorTranslateOptions *) 0 ;
+  GDALProgressFunc arg4 = (GDALProgressFunc) NULL ;
+  void *arg5 = (void *) NULL ;
+  int result;
+  
+  arg1 = (GDALDatasetShadow *)jarg1; 
+  arg2 = (GDALDatasetShadow *)jarg2; 
+  arg3 = (GDALVectorTranslateOptions *)jarg3; 
+  arg4 = (GDALProgressFunc)jarg4; 
+  arg5 = (void *)jarg5; 
+  {
+    CPLErrorReset();
+    result = (int)wrapper_GDALVectorTranslateDestDS(arg1,arg2,arg3,arg4,arg5);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_wrapper_GDALVectorTranslateDestName(char * jarg1, void * jarg2, void * jarg3, void * jarg4, void * jarg5) {
+  void * jresult ;
+  char *arg1 = (char *) 0 ;
+  GDALDatasetShadow *arg2 = (GDALDatasetShadow *) 0 ;
+  GDALVectorTranslateOptions *arg3 = (GDALVectorTranslateOptions *) 0 ;
+  GDALProgressFunc arg4 = (GDALProgressFunc) NULL ;
+  void *arg5 = (void *) NULL ;
+  GDALDatasetShadow *result = 0 ;
+  
+  arg1 = (char *)jarg1; 
+  arg2 = (GDALDatasetShadow *)jarg2; 
+  arg3 = (GDALVectorTranslateOptions *)jarg3; 
+  arg4 = (GDALProgressFunc)jarg4; 
+  arg5 = (void *)jarg5; 
+  {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (GDALDatasetShadow *)wrapper_GDALVectorTranslateDestName((char const *)arg1,arg2,arg3,arg4,arg5);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_new_GDALDEMProcessingOptions(void * jarg1) {
+  void * jresult ;
+  char **arg1 = (char **) 0 ;
+  GDALDEMProcessingOptions *result = 0 ;
+  
+  arg1 = (char **)jarg1; 
+  {
+    CPLErrorReset();
+    result = (GDALDEMProcessingOptions *)new_GDALDEMProcessingOptions(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_delete_GDALDEMProcessingOptions(void * jarg1) {
+  GDALDEMProcessingOptions *arg1 = (GDALDEMProcessingOptions *) 0 ;
+  
+  arg1 = (GDALDEMProcessingOptions *)jarg1; 
+  {
+    CPLErrorReset();
+    delete_GDALDEMProcessingOptions(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_wrapper_GDALDEMProcessing(char * jarg1, void * jarg2, char * jarg3, char * jarg4, void * jarg5, void * jarg6, void * jarg7) {
+  void * jresult ;
+  char *arg1 = (char *) 0 ;
+  GDALDatasetShadow *arg2 = (GDALDatasetShadow *) 0 ;
+  char *arg3 = (char *) 0 ;
+  char *arg4 = (char *) 0 ;
+  GDALDEMProcessingOptions *arg5 = (GDALDEMProcessingOptions *) 0 ;
+  GDALProgressFunc arg6 = (GDALProgressFunc) NULL ;
+  void *arg7 = (void *) NULL ;
+  GDALDatasetShadow *result = 0 ;
+  
+  arg1 = (char *)jarg1; 
+  arg2 = (GDALDatasetShadow *)jarg2; 
+  arg3 = (char *)jarg3; 
+  arg4 = (char *)jarg4; 
+  arg5 = (GDALDEMProcessingOptions *)jarg5; 
+  arg6 = (GDALProgressFunc)jarg6; 
+  arg7 = (void *)jarg7; 
+  {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    if (!arg3) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (GDALDatasetShadow *)wrapper_GDALDEMProcessing((char const *)arg1,arg2,(char const *)arg3,(char const *)arg4,arg5,arg6,arg7);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_new_GDALNearblackOptions(void * jarg1) {
+  void * jresult ;
+  char **arg1 = (char **) 0 ;
+  GDALNearblackOptions *result = 0 ;
+  
+  arg1 = (char **)jarg1; 
+  {
+    CPLErrorReset();
+    result = (GDALNearblackOptions *)new_GDALNearblackOptions(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_delete_GDALNearblackOptions(void * jarg1) {
+  GDALNearblackOptions *arg1 = (GDALNearblackOptions *) 0 ;
+  
+  arg1 = (GDALNearblackOptions *)jarg1; 
+  {
+    CPLErrorReset();
+    delete_GDALNearblackOptions(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_wrapper_GDALNearblackDestDS(void * jarg1, void * jarg2, void * jarg3, void * jarg4, void * jarg5) {
+  int jresult ;
+  GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
+  GDALDatasetShadow *arg2 = (GDALDatasetShadow *) 0 ;
+  GDALNearblackOptions *arg3 = (GDALNearblackOptions *) 0 ;
+  GDALProgressFunc arg4 = (GDALProgressFunc) NULL ;
+  void *arg5 = (void *) NULL ;
+  int result;
+  
+  arg1 = (GDALDatasetShadow *)jarg1; 
+  arg2 = (GDALDatasetShadow *)jarg2; 
+  arg3 = (GDALNearblackOptions *)jarg3; 
+  arg4 = (GDALProgressFunc)jarg4; 
+  arg5 = (void *)jarg5; 
+  {
+    CPLErrorReset();
+    result = (int)wrapper_GDALNearblackDestDS(arg1,arg2,arg3,arg4,arg5);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_wrapper_GDALNearblackDestName(char * jarg1, void * jarg2, void * jarg3, void * jarg4, void * jarg5) {
+  void * jresult ;
+  char *arg1 = (char *) 0 ;
+  GDALDatasetShadow *arg2 = (GDALDatasetShadow *) 0 ;
+  GDALNearblackOptions *arg3 = (GDALNearblackOptions *) 0 ;
+  GDALProgressFunc arg4 = (GDALProgressFunc) NULL ;
+  void *arg5 = (void *) NULL ;
+  GDALDatasetShadow *result = 0 ;
+  
+  arg1 = (char *)jarg1; 
+  arg2 = (GDALDatasetShadow *)jarg2; 
+  arg3 = (GDALNearblackOptions *)jarg3; 
+  arg4 = (GDALProgressFunc)jarg4; 
+  arg5 = (void *)jarg5; 
+  {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (GDALDatasetShadow *)wrapper_GDALNearblackDestName((char const *)arg1,arg2,arg3,arg4,arg5);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_new_GDALGridOptions(void * jarg1) {
+  void * jresult ;
+  char **arg1 = (char **) 0 ;
+  GDALGridOptions *result = 0 ;
+  
+  arg1 = (char **)jarg1; 
+  {
+    CPLErrorReset();
+    result = (GDALGridOptions *)new_GDALGridOptions(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_delete_GDALGridOptions(void * jarg1) {
+  GDALGridOptions *arg1 = (GDALGridOptions *) 0 ;
+  
+  arg1 = (GDALGridOptions *)jarg1; 
+  {
+    CPLErrorReset();
+    delete_GDALGridOptions(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_wrapper_GDALGrid(char * jarg1, void * jarg2, void * jarg3, void * jarg4, void * jarg5) {
+  void * jresult ;
+  char *arg1 = (char *) 0 ;
+  GDALDatasetShadow *arg2 = (GDALDatasetShadow *) 0 ;
+  GDALGridOptions *arg3 = (GDALGridOptions *) 0 ;
+  GDALProgressFunc arg4 = (GDALProgressFunc) NULL ;
+  void *arg5 = (void *) NULL ;
+  GDALDatasetShadow *result = 0 ;
+  
+  arg1 = (char *)jarg1; 
+  arg2 = (GDALDatasetShadow *)jarg2; 
+  arg3 = (GDALGridOptions *)jarg3; 
+  arg4 = (GDALProgressFunc)jarg4; 
+  arg5 = (void *)jarg5; 
+  {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (GDALDatasetShadow *)wrapper_GDALGrid((char const *)arg1,arg2,arg3,arg4,arg5);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_new_GDALRasterizeOptions(void * jarg1) {
+  void * jresult ;
+  char **arg1 = (char **) 0 ;
+  GDALRasterizeOptions *result = 0 ;
+  
+  arg1 = (char **)jarg1; 
+  {
+    CPLErrorReset();
+    result = (GDALRasterizeOptions *)new_GDALRasterizeOptions(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_delete_GDALRasterizeOptions(void * jarg1) {
+  GDALRasterizeOptions *arg1 = (GDALRasterizeOptions *) 0 ;
+  
+  arg1 = (GDALRasterizeOptions *)jarg1; 
+  {
+    CPLErrorReset();
+    delete_GDALRasterizeOptions(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_wrapper_GDALRasterizeDestDS(void * jarg1, void * jarg2, void * jarg3, void * jarg4, void * jarg5) {
+  int jresult ;
+  GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
+  GDALDatasetShadow *arg2 = (GDALDatasetShadow *) 0 ;
+  GDALRasterizeOptions *arg3 = (GDALRasterizeOptions *) 0 ;
+  GDALProgressFunc arg4 = (GDALProgressFunc) NULL ;
+  void *arg5 = (void *) NULL ;
+  int result;
+  
+  arg1 = (GDALDatasetShadow *)jarg1; 
+  arg2 = (GDALDatasetShadow *)jarg2; 
+  arg3 = (GDALRasterizeOptions *)jarg3; 
+  arg4 = (GDALProgressFunc)jarg4; 
+  arg5 = (void *)jarg5; 
+  {
+    CPLErrorReset();
+    result = (int)wrapper_GDALRasterizeDestDS(arg1,arg2,arg3,arg4,arg5);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_wrapper_GDALRasterizeDestName(char * jarg1, void * jarg2, void * jarg3, void * jarg4, void * jarg5) {
+  void * jresult ;
+  char *arg1 = (char *) 0 ;
+  GDALDatasetShadow *arg2 = (GDALDatasetShadow *) 0 ;
+  GDALRasterizeOptions *arg3 = (GDALRasterizeOptions *) 0 ;
+  GDALProgressFunc arg4 = (GDALProgressFunc) NULL ;
+  void *arg5 = (void *) NULL ;
+  GDALDatasetShadow *result = 0 ;
+  
+  arg1 = (char *)jarg1; 
+  arg2 = (GDALDatasetShadow *)jarg2; 
+  arg3 = (GDALRasterizeOptions *)jarg3; 
+  arg4 = (GDALProgressFunc)jarg4; 
+  arg5 = (void *)jarg5; 
+  {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (GDALDatasetShadow *)wrapper_GDALRasterizeDestName((char const *)arg1,arg2,arg3,arg4,arg5);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_new_GDALBuildVRTOptions(void * jarg1) {
+  void * jresult ;
+  char **arg1 = (char **) 0 ;
+  GDALBuildVRTOptions *result = 0 ;
+  
+  arg1 = (char **)jarg1; 
+  {
+    CPLErrorReset();
+    result = (GDALBuildVRTOptions *)new_GDALBuildVRTOptions(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_delete_GDALBuildVRTOptions(void * jarg1) {
+  GDALBuildVRTOptions *arg1 = (GDALBuildVRTOptions *) 0 ;
+  
+  arg1 = (GDALBuildVRTOptions *)jarg1; 
+  {
+    CPLErrorReset();
+    delete_GDALBuildVRTOptions(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_wrapper_GDALBuildVRT_objects(char * jarg1, int jarg2, void * jarg3, void * jarg4, void * jarg5, void * jarg6) {
+  void * jresult ;
+  char *arg1 = (char *) 0 ;
+  int arg2 ;
+  GDALDatasetShadow **arg3 = (GDALDatasetShadow **) 0 ;
+  GDALBuildVRTOptions *arg4 = (GDALBuildVRTOptions *) 0 ;
+  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
+  void *arg6 = (void *) NULL ;
+  GDALDatasetShadow *result = 0 ;
+  
+  arg1 = (char *)jarg1; 
+  arg2 = (int)jarg2; 
+  arg3 = (GDALDatasetShadow **)jarg3; 
+  arg4 = (GDALBuildVRTOptions *)jarg4; 
+  arg5 = (GDALProgressFunc)jarg5; 
+  arg6 = (void *)jarg6; 
+  {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (GDALDatasetShadow *)wrapper_GDALBuildVRT_objects((char const *)arg1,arg2,arg3,arg4,arg5,arg6);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_wrapper_GDALBuildVRT_names(char * jarg1, void * jarg2, void * jarg3, void * jarg4, void * jarg5) {
+  void * jresult ;
+  char *arg1 = (char *) 0 ;
+  char **arg2 = (char **) 0 ;
+  GDALBuildVRTOptions *arg3 = (GDALBuildVRTOptions *) 0 ;
+  GDALProgressFunc arg4 = (GDALProgressFunc) NULL ;
+  void *arg5 = (void *) NULL ;
+  GDALDatasetShadow *result = 0 ;
+  
+  arg1 = (char *)jarg1; 
+  arg2 = (char **)jarg2; 
+  arg3 = (GDALBuildVRTOptions *)jarg3; 
+  arg4 = (GDALProgressFunc)jarg4; 
+  arg5 = (void *)jarg5; 
+  {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (GDALDatasetShadow *)wrapper_GDALBuildVRT_names((char const *)arg1,arg2,arg3,arg4,arg5);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
 SWIGEXPORT GDALMajorObjectShadow * SWIGSTDCALL CSharp_Driver_SWIGUpcast(GDALDriverShadow *jarg1) {
     return (GDALMajorObjectShadow *)jarg1;
 }
diff --git a/swig/csharp/ogr/CoordinateTransformation.cs b/swig/csharp/ogr/CoordinateTransformation.cs
index 85ba1ab..ad05b32 100644
--- a/swig/csharp/ogr/CoordinateTransformation.cs
+++ b/swig/csharp/ogr/CoordinateTransformation.cs
@@ -15,7 +15,7 @@ public class CoordinateTransformation : IDisposable {
   private HandleRef swigCPtr;
   protected bool swigCMemOwn;
   protected object swigParentRef;
-  
+
   protected static object ThisOwn_true() { return null; }
   protected object ThisOwn_false() { return this; }
 
diff --git a/swig/csharp/ogr/DataSource.cs b/swig/csharp/ogr/DataSource.cs
index 112e92a..4972350 100644
--- a/swig/csharp/ogr/DataSource.cs
+++ b/swig/csharp/ogr/DataSource.cs
@@ -15,7 +15,7 @@ public class DataSource : IDisposable {
   private HandleRef swigCPtr;
   protected bool swigCMemOwn;
   protected object swigParentRef;
-  
+
   protected static object ThisOwn_true() { return null; }
   protected object ThisOwn_false() { return this; }
 
diff --git a/swig/csharp/ogr/Driver.cs b/swig/csharp/ogr/Driver.cs
index 698f06c..1382001 100644
--- a/swig/csharp/ogr/Driver.cs
+++ b/swig/csharp/ogr/Driver.cs
@@ -15,7 +15,7 @@ public class Driver : IDisposable {
   private HandleRef swigCPtr;
   protected bool swigCMemOwn;
   protected object swigParentRef;
-  
+
   protected static object ThisOwn_true() { return null; }
   protected object ThisOwn_false() { return this; }
 
diff --git a/swig/csharp/ogr/Envelope.cs b/swig/csharp/ogr/Envelope.cs
index 9fe7e52..0e781c9 100644
--- a/swig/csharp/ogr/Envelope.cs
+++ b/swig/csharp/ogr/Envelope.cs
@@ -15,7 +15,7 @@ public class Envelope : IDisposable {
   private HandleRef swigCPtr;
   protected bool swigCMemOwn;
   protected object swigParentRef;
-  
+
   protected static object ThisOwn_true() { return null; }
   protected object ThisOwn_false() { return this; }
 
diff --git a/swig/csharp/ogr/Envelope3D.cs b/swig/csharp/ogr/Envelope3D.cs
index 2f2f7e8..363066e 100644
--- a/swig/csharp/ogr/Envelope3D.cs
+++ b/swig/csharp/ogr/Envelope3D.cs
@@ -15,7 +15,7 @@ public class Envelope3D : IDisposable {
   private HandleRef swigCPtr;
   protected bool swigCMemOwn;
   protected object swigParentRef;
-  
+
   protected static object ThisOwn_true() { return null; }
   protected object ThisOwn_false() { return this; }
 
diff --git a/swig/csharp/ogr/Feature.cs b/swig/csharp/ogr/Feature.cs
index c0d2c2d..8b51115 100644
--- a/swig/csharp/ogr/Feature.cs
+++ b/swig/csharp/ogr/Feature.cs
@@ -15,7 +15,7 @@ public class Feature : IDisposable {
   private HandleRef swigCPtr;
   protected bool swigCMemOwn;
   protected object swigParentRef;
-  
+
   protected static object ThisOwn_true() { return null; }
   protected object ThisOwn_false() { return this; }
 
@@ -244,7 +244,12 @@ public class Feature : IDisposable {
   }
 
   public void GetFieldAsDateTime(int id, out int pnYear, out int pnMonth, out int pnDay, out int pnHour, out int pnMinute, out float pfSecond, out int pnTZFlag) {
-    OgrPINVOKE.Feature_GetFieldAsDateTime(swigCPtr, id, out pnYear, out pnMonth, out pnDay, out pnHour, out pnMinute, out pfSecond, out pnTZFlag);
+    OgrPINVOKE.Feature_GetFieldAsDateTime__SWIG_0(swigCPtr, id, out pnYear, out pnMonth, out pnDay, out pnHour, out pnMinute, out pfSecond, out pnTZFlag);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+  }
+
+  public void GetFieldAsDateTime(string name, out int pnYear, out int pnMonth, out int pnDay, out int pnHour, out int pnMinute, out float pfSecond, out int pnTZFlag) {
+    OgrPINVOKE.Feature_GetFieldAsDateTime__SWIG_1(swigCPtr, name, out pnYear, out pnMonth, out pnDay, out pnHour, out pnMinute, out pfSecond, out pnTZFlag);
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
   }
 
@@ -252,7 +257,7 @@ public class Feature : IDisposable {
         /* %typemap(csout) int *intList */
         IntPtr cPtr = OgrPINVOKE.Feature_GetFieldAsIntegerList(swigCPtr, id, out count);
         int[] ret = new int[count];
-        if (count > 0) {       
+        if (count > 0) {
 	        System.Runtime.InteropServices.Marshal.Copy(cPtr, ret, 0, count);
         }
         
@@ -264,7 +269,7 @@ public class Feature : IDisposable {
         /* %typemap(csout) int *intList */
         IntPtr cPtr = OgrPINVOKE.Feature_GetFieldAsDoubleList(swigCPtr, id, out count);
         double[] ret = new double[count];
-        if (count > 0) {       
+        if (count > 0) {
 	        System.Runtime.InteropServices.Marshal.Copy(cPtr, ret, 0, count);
         }
         
@@ -282,7 +287,7 @@ public class Feature : IDisposable {
                 ++count;
         }
         string[] ret = new string[count];
-        if (count > 0) {       
+        if (count > 0) {
 	        for(int cx = 0; cx < count; cx++) {
                 objPtr = System.Runtime.InteropServices.Marshal.ReadIntPtr(cPtr, cx * System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)));
                 ret[cx]= (objPtr == IntPtr.Zero) ? null : System.Runtime.InteropServices.Marshal.PtrToStringAnsi(objPtr);
@@ -460,6 +465,28 @@ public class Feature : IDisposable {
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
   }
 
+  public string GetNativeData() {
+    string ret = OgrPINVOKE.Feature_GetNativeData(swigCPtr);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public string GetNativeMediaType() {
+    string ret = OgrPINVOKE.Feature_GetNativeMediaType(swigCPtr);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public void SetNativeData(string nativeData) {
+    OgrPINVOKE.Feature_SetNativeData(swigCPtr, nativeData);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+  }
+
+  public void SetNativeMediaType(string nativeMediaType) {
+    OgrPINVOKE.Feature_SetNativeMediaType(swigCPtr, nativeMediaType);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+  }
+
 }
 
 }
diff --git a/swig/csharp/ogr/FeatureDefn.cs b/swig/csharp/ogr/FeatureDefn.cs
index 82f0cd0..17efd22 100644
--- a/swig/csharp/ogr/FeatureDefn.cs
+++ b/swig/csharp/ogr/FeatureDefn.cs
@@ -15,7 +15,7 @@ public class FeatureDefn : IDisposable {
   private HandleRef swigCPtr;
   protected bool swigCMemOwn;
   protected object swigParentRef;
-  
+
   protected static object ThisOwn_true() { return null; }
   protected object ThisOwn_false() { return this; }
 
diff --git a/swig/csharp/ogr/FieldDefn.cs b/swig/csharp/ogr/FieldDefn.cs
index ab04556..63bad00 100644
--- a/swig/csharp/ogr/FieldDefn.cs
+++ b/swig/csharp/ogr/FieldDefn.cs
@@ -15,7 +15,7 @@ public class FieldDefn : IDisposable {
   private HandleRef swigCPtr;
   protected bool swigCMemOwn;
   protected object swigParentRef;
-  
+
   protected static object ThisOwn_true() { return null; }
   protected object ThisOwn_false() { return this; }
 
diff --git a/swig/csharp/ogr/GeomFieldDefn.cs b/swig/csharp/ogr/GeomFieldDefn.cs
index 866b4e7..4bda8ae 100644
--- a/swig/csharp/ogr/GeomFieldDefn.cs
+++ b/swig/csharp/ogr/GeomFieldDefn.cs
@@ -15,7 +15,7 @@ public class GeomFieldDefn : IDisposable {
   private HandleRef swigCPtr;
   protected bool swigCMemOwn;
   protected object swigParentRef;
-  
+
   protected static object ThisOwn_true() { return null; }
   protected object ThisOwn_false() { return this; }
 
diff --git a/swig/csharp/ogr/Geometry.cs b/swig/csharp/ogr/Geometry.cs
index dcf1a66..87244de 100644
--- a/swig/csharp/ogr/Geometry.cs
+++ b/swig/csharp/ogr/Geometry.cs
@@ -15,7 +15,7 @@ public class Geometry : IDisposable {
   private HandleRef swigCPtr;
   protected bool swigCMemOwn;
   protected object swigParentRef;
-  
+
   protected static object ThisOwn_true() { return null; }
   protected object ThisOwn_false() { return this; }
 
@@ -72,7 +72,7 @@ public int ExportToWkb( byte[] buffer, wkbByteOrder byte_order ) {
       int size = WkbSize();
       if (buffer.Length < size)
         throw new ArgumentException("Buffer size is small (ExportToWkb)");
-        
+
       IntPtr ptr = Marshal.AllocHGlobal(size * Marshal.SizeOf(buffer[0]));
       try {
           retval = ExportToWkb(size, ptr, byte_order);
@@ -86,11 +86,11 @@ public int ExportToWkb( byte[] buffer, wkbByteOrder byte_order ) {
   public int ExportToWkb( byte[] buffer ) {
       return ExportToWkb( buffer, wkbByteOrder.wkbXDR);
   }
-  
+
   public static Geometry CreateFromWkb(byte[] wkb){
      if (wkb.Length == 0)
         throw new ArgumentException("Buffer size is small (CreateFromWkb)");
-     Geometry retval;   
+     Geometry retval;
      IntPtr ptr = Marshal.AllocHGlobal(wkb.Length * Marshal.SizeOf(wkb[0]));
      try {
          Marshal.Copy(wkb, 0, ptr, wkb.Length);
@@ -98,17 +98,17 @@ public int ExportToWkb( byte[] buffer, wkbByteOrder byte_order ) {
       } finally {
           Marshal.FreeHGlobal(ptr);
       }
-      return retval;  
+      return retval;
   }
-  
+
   public static Geometry CreateFromWkt(string wkt){
      return new Geometry(wkbGeometryType.wkbUnknown, wkt, 0, IntPtr.Zero, null);
   }
-  
+
   public static Geometry CreateFromGML(string gml){
      return new Geometry(wkbGeometryType.wkbUnknown, null, 0, IntPtr.Zero, gml);
   }
-  
+
   public Geometry(wkbGeometryType type) : this(OgrPINVOKE.new_Geometry((int)type, null, 0, IntPtr.Zero, null), true, null) {
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
   }
@@ -157,6 +157,16 @@ public int ExportToWkb( byte[] buffer, wkbByteOrder byte_order ) {
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
   }
 
+  public void AddPointM(double x, double y, double m) {
+    OgrPINVOKE.Geometry_AddPointM(swigCPtr, x, y, m);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+  }
+
+  public void AddPointZM(double x, double y, double z, double m) {
+    OgrPINVOKE.Geometry_AddPointZM(swigCPtr, x, y, z, m);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+  }
+
   public void AddPoint_2D(double x, double y) {
     OgrPINVOKE.Geometry_AddPoint_2D(swigCPtr, x, y);
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
@@ -235,11 +245,22 @@ public int ExportToWkb( byte[] buffer, wkbByteOrder byte_order ) {
     return ret;
   }
 
+  public double GetM(int point) {
+    double ret = OgrPINVOKE.Geometry_GetM(swigCPtr, point);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public void GetPoint(int iPoint, double[] argout) {
     OgrPINVOKE.Geometry_GetPoint(swigCPtr, iPoint, argout);
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
   }
 
+  public void GetPointZM(int iPoint, double[] argout) {
+    OgrPINVOKE.Geometry_GetPointZM(swigCPtr, iPoint, argout);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+  }
+
   public void GetPoint_2D(int iPoint, double[] argout) {
     OgrPINVOKE.Geometry_GetPoint_2D(swigCPtr, iPoint, argout);
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
@@ -256,6 +277,16 @@ public int ExportToWkb( byte[] buffer, wkbByteOrder byte_order ) {
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
   }
 
+  public void SetPointM(int point, double x, double y, double m) {
+    OgrPINVOKE.Geometry_SetPointM(swigCPtr, point, x, y, m);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+  }
+
+  public void SetPointZM(int point, double x, double y, double z, double m) {
+    OgrPINVOKE.Geometry_SetPointZM(swigCPtr, point, x, y, z, m);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+  }
+
   public void SetPoint_2D(int point, double x, double y) {
     OgrPINVOKE.Geometry_SetPoint_2D(swigCPtr, point, x, y);
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
@@ -282,6 +313,13 @@ public int ExportToWkb( byte[] buffer, wkbByteOrder byte_order ) {
     return ret;
   }
 
+  public Geometry DelaunayTriangulation(double dfTolerance, int bOnlyEdges) {
+    IntPtr cPtr = OgrPINVOKE.Geometry_DelaunayTriangulation(swigCPtr, dfTolerance, bOnlyEdges);
+    Geometry ret = (cPtr == IntPtr.Zero) ? null : new Geometry(cPtr, true, ThisOwn_true());
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public Geometry Boundary() {
     IntPtr cPtr = OgrPINVOKE.Geometry_Boundary(swigCPtr);
     Geometry ret = (cPtr == IntPtr.Zero) ? null : new Geometry(cPtr, true, ThisOwn_true());
@@ -522,11 +560,39 @@ public int ExportToWkb( byte[] buffer, wkbByteOrder byte_order ) {
     return ret;
   }
 
+  public int CoordinateDimension() {
+    int ret = OgrPINVOKE.Geometry_CoordinateDimension(swigCPtr);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public int Is3D() {
+    int ret = OgrPINVOKE.Geometry_Is3D(swigCPtr);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public int IsMeasured() {
+    int ret = OgrPINVOKE.Geometry_IsMeasured(swigCPtr);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public void SetCoordinateDimension(int dimension) {
     OgrPINVOKE.Geometry_SetCoordinateDimension(swigCPtr, dimension);
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
   }
 
+  public void Set3D(int b3D) {
+    OgrPINVOKE.Geometry_Set3D(swigCPtr, b3D);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+  }
+
+  public void SetMeasured(int bMeasured) {
+    OgrPINVOKE.Geometry_SetMeasured(swigCPtr, bMeasured);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+  }
+
   public int GetDimension() {
     int ret = OgrPINVOKE.Geometry_GetDimension(swigCPtr);
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
diff --git a/swig/csharp/ogr/Layer.cs b/swig/csharp/ogr/Layer.cs
index 718ca20..bc1b8e7 100644
--- a/swig/csharp/ogr/Layer.cs
+++ b/swig/csharp/ogr/Layer.cs
@@ -15,7 +15,7 @@ public class Layer : IDisposable {
   private HandleRef swigCPtr;
   protected bool swigCMemOwn;
   protected object swigParentRef;
-  
+
   protected static object ThisOwn_true() { return null; }
   protected object ThisOwn_false() { return this; }
 
diff --git a/swig/csharp/ogr/Ogr.cs b/swig/csharp/ogr/Ogr.cs
index 0207002..4043709 100644
--- a/swig/csharp/ogr/Ogr.cs
+++ b/swig/csharp/ogr/Ogr.cs
@@ -15,7 +15,7 @@ public class Ogr {
 
   internal class OgrObject : IDisposable {
 	public virtual void Dispose() {
-      
+
     }
   }
   internal static OgrObject theOgrObject = new OgrObject();
@@ -35,21 +35,21 @@ public class Ogr {
   {
     if (str == null)
       return null;
-    
+
     int bytecount = System.Text.Encoding.UTF8.GetMaxByteCount(str.Length);
     byte[] bytes = new byte[bytecount + 1];
     System.Text.Encoding.UTF8.GetBytes(str, 0, str.Length, bytes, 0);
     return bytes;
   }
-  
+
   internal static string Utf8BytesToString(IntPtr pNativeData)
   {
     if (pNativeData == IntPtr.Zero)
         return null;
-        
+
     int length = Marshal.PtrToStringAnsi(pNativeData).Length;
-    byte[] strbuf = new byte[length];  
-    Marshal.Copy(pNativeData, strbuf, 0, length); 
+    byte[] strbuf = new byte[length];
+    Marshal.Copy(pNativeData, strbuf, 0, length);
     return System.Text.Encoding.UTF8.GetString(strbuf);
   }
 
@@ -197,6 +197,12 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
     return ret;
   }
 
+  public static wkbGeometryType GT_SetM(wkbGeometryType eType) {
+    wkbGeometryType ret = (wkbGeometryType)OgrPINVOKE.GT_SetM((int)eType);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public static wkbGeometryType GT_SetModifier(wkbGeometryType eType, int bSetZ, int bSetM) {
     wkbGeometryType ret = (wkbGeometryType)OgrPINVOKE.GT_SetModifier((int)eType, bSetZ, bSetM);
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
@@ -209,6 +215,12 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
     return ret;
   }
 
+  public static int GT_HasM(wkbGeometryType eType) {
+    int ret = OgrPINVOKE.GT_HasM((int)eType);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public static int GT_IsSubClassOf(wkbGeometryType eType, wkbGeometryType eSuperType) {
     int ret = OgrPINVOKE.GT_IsSubClassOf((int)eType, (int)eSuperType);
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
@@ -307,7 +319,7 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
                 ++count;
         }
         string[] ret = new string[count];
-        if (count > 0) {       
+        if (count > 0) {
 	        for(int cx = 0; cx < count; cx++) {
                 objPtr = System.Runtime.InteropServices.Marshal.ReadIntPtr(cPtr, cx * System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)));
                 ret[cx]= (objPtr == IntPtr.Zero) ? null : System.Runtime.InteropServices.Marshal.PtrToStringAnsi(objPtr);
@@ -338,12 +350,14 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
   public static readonly string OLCStringsAsUTF8 = OgrPINVOKE.OLCStringsAsUTF8_get();
   public static readonly string OLCCreateGeomField = OgrPINVOKE.OLCCreateGeomField_get();
   public static readonly string OLCCurveGeometries = OgrPINVOKE.OLCCurveGeometries_get();
+  public static readonly string OLCMeasuredGeometries = OgrPINVOKE.OLCMeasuredGeometries_get();
   public static readonly string ODsCCreateLayer = OgrPINVOKE.ODsCCreateLayer_get();
   public static readonly string ODsCDeleteLayer = OgrPINVOKE.ODsCDeleteLayer_get();
   public static readonly string ODsCCreateGeomFieldAfterCreateLayer = OgrPINVOKE.ODsCCreateGeomFieldAfterCreateLayer_get();
   public static readonly string ODsCCurveGeometries = OgrPINVOKE.ODsCCurveGeometries_get();
   public static readonly string ODsCTransactions = OgrPINVOKE.ODsCTransactions_get();
   public static readonly string ODsCEmulatedTransactions = OgrPINVOKE.ODsCEmulatedTransactions_get();
+  public static readonly string ODsCMeasuredGeometries = OgrPINVOKE.ODsCMeasuredGeometries_get();
   public static readonly string ODrCCreateDataSource = OgrPINVOKE.ODrCCreateDataSource_get();
   public static readonly string ODrCDeleteDataSource = OgrPINVOKE.ODrCDeleteDataSource_get();
   public static readonly string OLMD_FID64 = OgrPINVOKE.OLMD_FID64_get();
diff --git a/swig/csharp/ogr/OgrPINVOKE.cs b/swig/csharp/ogr/OgrPINVOKE.cs
index 8279fa8..6b0a41a 100644
--- a/swig/csharp/ogr/OgrPINVOKE.cs
+++ b/swig/csharp/ogr/OgrPINVOKE.cs
@@ -253,6 +253,9 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_OLCCurveGeometries_get")]
   public static extern string OLCCurveGeometries_get();
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_OLCMeasuredGeometries_get")]
+  public static extern string OLCMeasuredGeometries_get();
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_ODsCCreateLayer_get")]
   public static extern string ODsCCreateLayer_get();
 
@@ -271,6 +274,9 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_ODsCEmulatedTransactions_get")]
   public static extern string ODsCEmulatedTransactions_get();
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_ODsCMeasuredGeometries_get")]
+  public static extern string ODsCMeasuredGeometries_get();
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_ODrCCreateDataSource_get")]
   public static extern string ODrCCreateDataSource_get();
 
@@ -748,8 +754,11 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_GetFieldAsDouble__SWIG_1")]
   public static extern double Feature_GetFieldAsDouble__SWIG_1(HandleRef jarg1, string jarg2);
 
-  [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_GetFieldAsDateTime")]
-  public static extern void Feature_GetFieldAsDateTime(HandleRef jarg1, int jarg2, out int jarg3, out int jarg4, out int jarg5, out int jarg6, out int jarg7, out float jarg8, out int jarg9);
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_GetFieldAsDateTime__SWIG_0")]
+  public static extern void Feature_GetFieldAsDateTime__SWIG_0(HandleRef jarg1, int jarg2, out int jarg3, out int jarg4, out int jarg5, out int jarg6, out int jarg7, out float jarg8, out int jarg9);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_GetFieldAsDateTime__SWIG_1")]
+  public static extern void Feature_GetFieldAsDateTime__SWIG_1(HandleRef jarg1, string jarg2, out int jarg3, out int jarg4, out int jarg5, out int jarg6, out int jarg7, out float jarg8, out int jarg9);
 
   [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_GetFieldAsIntegerList")]
   public static extern IntPtr Feature_GetFieldAsIntegerList(HandleRef jarg1, int jarg2, out int jarg3);
@@ -853,6 +862,18 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_FillUnsetWithDefault")]
   public static extern void Feature_FillUnsetWithDefault(HandleRef jarg1, int jarg2, IntPtr[] jarg3);
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_GetNativeData")]
+  public static extern string Feature_GetNativeData(HandleRef jarg1);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_GetNativeMediaType")]
+  public static extern string Feature_GetNativeMediaType(HandleRef jarg1);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_SetNativeData")]
+  public static extern void Feature_SetNativeData(HandleRef jarg1, string jarg2);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_SetNativeMediaType")]
+  public static extern void Feature_SetNativeMediaType(HandleRef jarg1, string jarg2);
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_delete_FeatureDefn")]
   public static extern void delete_FeatureDefn(HandleRef jarg1);
 
@@ -1087,6 +1108,12 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_AddPoint")]
   public static extern void Geometry_AddPoint(HandleRef jarg1, double jarg2, double jarg3, double jarg4);
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_AddPointM")]
+  public static extern void Geometry_AddPointM(HandleRef jarg1, double jarg2, double jarg3, double jarg4);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_AddPointZM")]
+  public static extern void Geometry_AddPointZM(HandleRef jarg1, double jarg2, double jarg3, double jarg4, double jarg5);
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_AddPoint_2D")]
   public static extern void Geometry_AddPoint_2D(HandleRef jarg1, double jarg2, double jarg3);
 
@@ -1126,9 +1153,15 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_GetZ")]
   public static extern double Geometry_GetZ(HandleRef jarg1, int jarg2);
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_GetM")]
+  public static extern double Geometry_GetM(HandleRef jarg1, int jarg2);
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_GetPoint")]
   public static extern void Geometry_GetPoint(HandleRef jarg1, int jarg2, double[] jarg3);
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_GetPointZM")]
+  public static extern void Geometry_GetPointZM(HandleRef jarg1, int jarg2, double[] jarg3);
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_GetPoint_2D")]
   public static extern void Geometry_GetPoint_2D(HandleRef jarg1, int jarg2, double[] jarg3);
 
@@ -1138,6 +1171,12 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_SetPoint")]
   public static extern void Geometry_SetPoint(HandleRef jarg1, int jarg2, double jarg3, double jarg4, double jarg5);
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_SetPointM")]
+  public static extern void Geometry_SetPointM(HandleRef jarg1, int jarg2, double jarg3, double jarg4, double jarg5);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_SetPointZM")]
+  public static extern void Geometry_SetPointZM(HandleRef jarg1, int jarg2, double jarg3, double jarg4, double jarg5, double jarg6);
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_SetPoint_2D")]
   public static extern void Geometry_SetPoint_2D(HandleRef jarg1, int jarg2, double jarg3, double jarg4);
 
@@ -1150,6 +1189,9 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_SimplifyPreserveTopology")]
   public static extern IntPtr Geometry_SimplifyPreserveTopology(HandleRef jarg1, double jarg2);
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_DelaunayTriangulation")]
+  public static extern IntPtr Geometry_DelaunayTriangulation(HandleRef jarg1, double jarg2, int jarg3);
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_Boundary")]
   public static extern IntPtr Geometry_Boundary(HandleRef jarg1);
 
@@ -1267,9 +1309,24 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_GetCoordinateDimension")]
   public static extern int Geometry_GetCoordinateDimension(HandleRef jarg1);
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_CoordinateDimension")]
+  public static extern int Geometry_CoordinateDimension(HandleRef jarg1);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_Is3D")]
+  public static extern int Geometry_Is3D(HandleRef jarg1);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_IsMeasured")]
+  public static extern int Geometry_IsMeasured(HandleRef jarg1);
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_SetCoordinateDimension")]
   public static extern void Geometry_SetCoordinateDimension(HandleRef jarg1, int jarg2);
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_Set3D")]
+  public static extern void Geometry_Set3D(HandleRef jarg1, int jarg2);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_SetMeasured")]
+  public static extern void Geometry_SetMeasured(HandleRef jarg1, int jarg2);
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_GetDimension")]
   public static extern int Geometry_GetDimension(HandleRef jarg1);
 
@@ -1315,12 +1372,18 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_GT_SetZ")]
   public static extern int GT_SetZ(int jarg1);
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_GT_SetM")]
+  public static extern int GT_SetM(int jarg1);
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_GT_SetModifier")]
   public static extern int GT_SetModifier(int jarg1, int jarg2, int jarg3);
 
   [DllImport("ogr_wrap", EntryPoint="CSharp_GT_HasZ")]
   public static extern int GT_HasZ(int jarg1);
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_GT_HasM")]
+  public static extern int GT_HasM(int jarg1);
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_GT_IsSubClassOf")]
   public static extern int GT_IsSubClassOf(int jarg1, int jarg2);
 
diff --git a/swig/csharp/ogr/Osr.cs b/swig/csharp/ogr/Osr.cs
index c0ed9ad..0a3fc1c 100644
--- a/swig/csharp/ogr/Osr.cs
+++ b/swig/csharp/ogr/Osr.cs
@@ -15,7 +15,7 @@ public class Osr {
 
   internal class OsrObject : IDisposable {
 	public virtual void Dispose() {
-      
+
     }
   }
   internal static OsrObject theOsrObject = new OsrObject();
@@ -35,21 +35,21 @@ public class Osr {
   {
     if (str == null)
       return null;
-    
+
     int bytecount = System.Text.Encoding.UTF8.GetMaxByteCount(str.Length);
     byte[] bytes = new byte[bytecount + 1];
     System.Text.Encoding.UTF8.GetBytes(str, 0, str.Length, bytes, 0);
     return bytes;
   }
-  
+
   internal static string Utf8BytesToString(IntPtr pNativeData)
   {
     if (pNativeData == IntPtr.Zero)
         return null;
-        
+
     int length = Marshal.PtrToStringAnsi(pNativeData).Length;
-    byte[] strbuf = new byte[length];  
-    Marshal.Copy(pNativeData, strbuf, 0, length); 
+    byte[] strbuf = new byte[length];
+    Marshal.Copy(pNativeData, strbuf, 0, length);
     return System.Text.Encoding.UTF8.GetString(strbuf);
   }
 
@@ -82,7 +82,7 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
                 ++count;
         }
         string[] ret = new string[count];
-        if (count > 0) {       
+        if (count > 0) {
 	        for(int cx = 0; cx < count; cx++) {
                 objPtr = System.Runtime.InteropServices.Marshal.ReadIntPtr(cPtr, cx * System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)));
                 ret[cx]= (objPtr == IntPtr.Zero) ? null : System.Runtime.InteropServices.Marshal.PtrToStringAnsi(objPtr);
@@ -105,7 +105,7 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
                 ++count;
         }
         string[] ret = new string[count];
-        if (count > 0) {       
+        if (count > 0) {
 	        for(int cx = 0; cx < count; cx++) {
                 objPtr = System.Runtime.InteropServices.Marshal.ReadIntPtr(cPtr, cx * System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)));
                 ret[cx]= (objPtr == IntPtr.Zero) ? null : System.Runtime.InteropServices.Marshal.PtrToStringAnsi(objPtr);
@@ -130,7 +130,7 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
     return ret;
   }
 
-  public const string SRS_WKT_WGS84 = "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9108\"]],AUTHORITY[\"EPSG\",\"4326\"]]";
+  public const string SRS_WKT_WGS84 = "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]]";
   public const string SRS_PT_ALBERS_CONIC_EQUAL_AREA = "Albers_Conic_Equal_Area";
   public const string SRS_PT_AZIMUTHAL_EQUIDISTANT = "Azimuthal_Equidistant";
   public const string SRS_PT_CASSINI_SOLDNER = "Cassini_Soldner";
@@ -199,6 +199,7 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
   public const string SRS_PT_CRASTER_PARABOLIC = "Craster_Parabolic";
   public const string SRS_PT_LOXIMUTHAL = "Loximuthal";
   public const string SRS_PT_QUARTIC_AUTHALIC = "Quartic_Authalic";
+  public const string SRS_PT_SCH = "Spherical_Cross_Track_Height";
   public const string SRS_PP_CENTRAL_MERIDIAN = "central_meridian";
   public const string SRS_PP_SCALE_FACTOR = "scale_factor";
   public const string SRS_PP_STANDARD_PARALLEL_1 = "standard_parallel_1";
@@ -228,6 +229,10 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
   public const string SRS_PP_LONGITUDE_OF_1ST_POINT = "Longitude_Of_1st_Point";
   public const string SRS_PP_LATITUDE_OF_2ND_POINT = "Latitude_Of_2nd_Point";
   public const string SRS_PP_LONGITUDE_OF_2ND_POINT = "Longitude_Of_2nd_Point";
+  public const string SRS_PP_PEG_POINT_LATITUDE = "peg_point_latitude";
+  public const string SRS_PP_PEG_POINT_LONGITUDE = "peg_point_longitude";
+  public const string SRS_PP_PEG_POINT_HEADING = "peg_point_heading";
+  public const string SRS_PP_PEG_POINT_HEIGHT = "peg_point_height";
   public const string SRS_UL_METER = "Meter";
   public const string SRS_UL_FOOT = "Foot (International)";
   public const string SRS_UL_FOOT_CONV = "0.3048";
diff --git a/swig/csharp/ogr/SpatialReference.cs b/swig/csharp/ogr/SpatialReference.cs
index f2d9c2a..f015fd7 100644
--- a/swig/csharp/ogr/SpatialReference.cs
+++ b/swig/csharp/ogr/SpatialReference.cs
@@ -15,7 +15,7 @@ public class SpatialReference : IDisposable {
   private HandleRef swigCPtr;
   protected bool swigCMemOwn;
   protected object swigParentRef;
-  
+
   protected static object ThisOwn_true() { return null; }
   protected object ThisOwn_false() { return this; }
 
diff --git a/swig/csharp/ogr/StyleTable.cs b/swig/csharp/ogr/StyleTable.cs
index fccc6c6..bafbc65 100644
--- a/swig/csharp/ogr/StyleTable.cs
+++ b/swig/csharp/ogr/StyleTable.cs
@@ -15,7 +15,7 @@ public class StyleTable : IDisposable {
   private HandleRef swigCPtr;
   protected bool swigCMemOwn;
   protected object swigParentRef;
-  
+
   protected static object ThisOwn_true() { return null; }
   protected object ThisOwn_false() { return this; }
 
diff --git a/swig/csharp/ogr/ogr_wrap.cpp b/swig/csharp/ogr/ogr_wrap.cpp
index 2459d68..a7a0969 100644
--- a/swig/csharp/ogr/ogr_wrap.cpp
+++ b/swig/csharp/ogr/ogr_wrap.cpp
@@ -350,12 +350,17 @@ using namespace std;
 #include "cpl_string.h"
 #include "ogr_srs_api.h"
 
+#define FIELD_INDEX_ERROR_TMPL "Invalid field index: '%i'"
+#define FIELD_NAME_ERROR_TMPL "Invalid field name: '%s'"
+
 typedef void GDALMajorObjectShadow;
 
-#ifdef DEBUG 
+#ifdef DEBUG
 typedef struct OGRSpatialReferenceHS OSRSpatialReferenceShadow;
+#ifndef SWIGPERL
 typedef struct OGRDriverHS OGRDriverShadow;
 typedef struct OGRDataSourceHS OGRDataSourceShadow;
+#endif
 typedef struct OGRLayerHS OGRLayerShadow;
 typedef struct OGRFeatureHS OGRFeatureShadow;
 typedef struct OGRFeatureDefnHS OGRFeatureDefnShadow;
@@ -365,8 +370,10 @@ typedef struct OGRCoordinateTransformationHS OGRCoordinateTransformationShadow;
 typedef struct OGRFieldDefnHS OGRFieldDefnShadow;
 #else
 typedef void OSRSpatialReferenceShadow;
+#ifndef SWIGPERL
 typedef void OGRDriverShadow;
 typedef void OGRDataSourceShadow;
+#endif
 typedef void OGRLayerShadow;
 typedef void OGRFeatureShadow;
 typedef void OGRFeatureDefnShadow;
@@ -378,10 +385,15 @@ typedef struct OGRStyleTableHS OGRStyleTableShadow;
 typedef struct OGRGeomFieldDefnHS OGRGeomFieldDefnShadow;
 
 
-void VeryQuiteErrorHandler(CPLErr eclass, int code, const char *msg ) {
+void VeryQuietErrorHandler(CPLErr eclass, int code, const char *msg ) {
   /* If the error class is CE_Fatal, we want to have a message issued
      because the CPL support code does an abort() before any exception
      can be generated */
+#if defined(SWIGPERL)
+    AV* error_stack = get_av("Geo::GDAL::error", 0);
+    SV *error = newSVpv(msg, 0);
+    av_push(error_stack, error);
+#endif
   if (eclass == CE_Fatal ) {
     CPLDefaultErrorHandler(eclass, code, msg );
   }
@@ -389,7 +401,7 @@ void VeryQuiteErrorHandler(CPLErr eclass, int code, const char *msg ) {
 
 
 void UseExceptions() {
-  CPLSetErrorHandler( (CPLErrorHandler) VeryQuiteErrorHandler );
+  CPLSetErrorHandler( (CPLErrorHandler) VeryQuietErrorHandler );
 }
 
 void DontUseExceptions() {
@@ -741,11 +753,11 @@ SWIGINTERN OGRErr OGRFeatureShadow_SetGeomField__SWIG_1(OGRFeatureShadow *self,c
       int iField = OGR_F_GetGeomFieldIndex(self, name);
       if (iField == -1)
       {
-        CPLError(CE_Failure, 1, "No such field: '%s'", name);
-        return 6;
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+          return 6;
       }
       else
-        return OGR_F_SetGeomField(self, iField, geom);
+          return OGR_F_SetGeomField(self, iField, geom);
   }
 SWIGINTERN OGRErr OGRFeatureShadow_SetGeomFieldDirectly__SWIG_0(OGRFeatureShadow *self,int iField,OGRGeometryShadow *geom){
     return OGR_F_SetGeomFieldDirectly(self, iField, geom);
@@ -754,24 +766,24 @@ SWIGINTERN OGRErr OGRFeatureShadow_SetGeomFieldDirectly__SWIG_1(OGRFeatureShadow
       int iField = OGR_F_GetGeomFieldIndex(self, name);
       if (iField == -1)
       {
-        CPLError(CE_Failure, 1, "No such field: '%s'", name);
-        return 6;
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+          return 6;
       }
       else
-        return OGR_F_SetGeomFieldDirectly(self, iField, geom);
+          return OGR_F_SetGeomFieldDirectly(self, iField, geom);
   }
 SWIGINTERN OGRGeometryShadow *OGRFeatureShadow_GetGeomFieldRef__SWIG_0(OGRFeatureShadow *self,int iField){
     return (OGRGeometryShadow*) OGR_F_GetGeomFieldRef(self, iField);
   }
 SWIGINTERN OGRGeometryShadow *OGRFeatureShadow_GetGeomFieldRef__SWIG_1(OGRFeatureShadow *self,char const *name){
-    int i = OGR_F_GetGeomFieldIndex(self, name);
-    if (i == -1)
-    {
-      CPLError(CE_Failure, 1, "No such field: '%s'", name);
-      return NULL;
-    }
-    else
-      return (OGRGeometryShadow*) OGR_F_GetGeomFieldRef(self, i);
+      int i = OGR_F_GetGeomFieldIndex(self, name);
+      if (i == -1)
+      {
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+          return NULL;
+      }
+      else
+          return (OGRGeometryShadow*) OGR_F_GetGeomFieldRef(self, i);
   }
 SWIGINTERN OGRFeatureShadow *OGRFeatureShadow_Clone(OGRFeatureShadow *self){
     return (OGRFeatureShadow*) OGR_F_Clone(self);
@@ -788,23 +800,23 @@ SWIGINTERN OGRFieldDefnShadow *OGRFeatureShadow_GetFieldDefnRef__SWIG_0(OGRFeatu
 SWIGINTERN OGRFieldDefnShadow *OGRFeatureShadow_GetFieldDefnRef__SWIG_1(OGRFeatureShadow *self,char const *name){
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
-	  return (OGRFieldDefnShadow *) OGR_F_GetFieldDefnRef(self, i);
+          return (OGRFieldDefnShadow *) OGR_F_GetFieldDefnRef(self, i);
       return NULL;
   }
 SWIGINTERN int OGRFeatureShadow_GetGeomFieldCount(OGRFeatureShadow *self){
     return OGR_F_GetGeomFieldCount(self);
   }
 SWIGINTERN OGRGeomFieldDefnShadow *OGRFeatureShadow_GetGeomFieldDefnRef__SWIG_0(OGRFeatureShadow *self,int id){
-    return (OGRGeomFieldDefnShadow *) OGR_F_GetGeomFieldDefnRef(self, id);
+      return (OGRGeomFieldDefnShadow *) OGR_F_GetGeomFieldDefnRef(self, id);
   }
 SWIGINTERN OGRGeomFieldDefnShadow *OGRFeatureShadow_GetGeomFieldDefnRef__SWIG_1(OGRFeatureShadow *self,char const *name){
       int i = OGR_F_GetGeomFieldIndex(self, name);
       if (i == -1)
-      CPLError(CE_Failure, 1, "No such field: '%s'", name);
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
-      return (OGRGeomFieldDefnShadow *) OGR_F_GetGeomFieldDefnRef(self, i);
+          return (OGRGeomFieldDefnShadow *) OGR_F_GetGeomFieldDefnRef(self, i);
       return NULL;
   }
 SWIGINTERN char const *OGRFeatureShadow_GetFieldAsString__SWIG_0(OGRFeatureShadow *self,int id){
@@ -813,7 +825,7 @@ SWIGINTERN char const *OGRFeatureShadow_GetFieldAsString__SWIG_0(OGRFeatureShado
 SWIGINTERN char const *OGRFeatureShadow_GetFieldAsString__SWIG_1(OGRFeatureShadow *self,char const *name){
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
+	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
 	  return (const char *) OGR_F_GetFieldAsString(self, i);
       return NULL;
@@ -824,7 +836,7 @@ SWIGINTERN int OGRFeatureShadow_GetFieldAsInteger__SWIG_0(OGRFeatureShadow *self
 SWIGINTERN int OGRFeatureShadow_GetFieldAsInteger__SWIG_1(OGRFeatureShadow *self,char const *name){
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
+	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
 	  return OGR_F_GetFieldAsInteger(self, i);
       return 0;
@@ -835,9 +847,9 @@ SWIGINTERN GIntBig OGRFeatureShadow_GetFieldAsInteger64__SWIG_0(OGRFeatureShadow
 SWIGINTERN GIntBig OGRFeatureShadow_GetFieldAsInteger64__SWIG_1(OGRFeatureShadow *self,char const *name){
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-      CPLError(CE_Failure, 1, "No such field: '%s'", name);
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
-      return OGR_F_GetFieldAsInteger64(self, i);
+          return OGR_F_GetFieldAsInteger64(self, i);
       return 0;
   }
 SWIGINTERN double OGRFeatureShadow_GetFieldAsDouble__SWIG_0(OGRFeatureShadow *self,int id){
@@ -846,16 +858,25 @@ SWIGINTERN double OGRFeatureShadow_GetFieldAsDouble__SWIG_0(OGRFeatureShadow *se
 SWIGINTERN double OGRFeatureShadow_GetFieldAsDouble__SWIG_1(OGRFeatureShadow *self,char const *name){
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
-	  return OGR_F_GetFieldAsDouble(self, i);
+          return OGR_F_GetFieldAsDouble(self, i);
       return 0;
   }
-SWIGINTERN void OGRFeatureShadow_GetFieldAsDateTime(OGRFeatureShadow *self,int id,int *pnYear,int *pnMonth,int *pnDay,int *pnHour,int *pnMinute,float *pfSecond,int *pnTZFlag){
+SWIGINTERN void OGRFeatureShadow_GetFieldAsDateTime__SWIG_0(OGRFeatureShadow *self,int id,int *pnYear,int *pnMonth,int *pnDay,int *pnHour,int *pnMinute,float *pfSecond,int *pnTZFlag){
       OGR_F_GetFieldAsDateTimeEx(self, id, pnYear, pnMonth, pnDay,
 			       pnHour, pnMinute, pfSecond,
 			       pnTZFlag);
   }
+SWIGINTERN void OGRFeatureShadow_GetFieldAsDateTime__SWIG_1(OGRFeatureShadow *self,char const *name,int *pnYear,int *pnMonth,int *pnDay,int *pnHour,int *pnMinute,float *pfSecond,int *pnTZFlag){
+      int id = OGR_F_GetFieldIndex(self, name);
+      if (id == -1)
+	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      else
+	  OGR_F_GetFieldAsDateTimeEx(self, id, pnYear, pnMonth, pnDay,
+			       pnHour, pnMinute, pfSecond,
+			       pnTZFlag);
+  }
 SWIGINTERN int const *OGRFeatureShadow_GetFieldAsIntegerList(OGRFeatureShadow *self,int id,int *count){
       return OGR_F_GetFieldAsIntegerList(self, id, count);
   }
@@ -871,16 +892,22 @@ SWIGINTERN bool OGRFeatureShadow_IsFieldSet__SWIG_0(OGRFeatureShadow *self,int i
 SWIGINTERN bool OGRFeatureShadow_IsFieldSet__SWIG_1(OGRFeatureShadow *self,char const *name){
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
+	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
 	  return (OGR_F_IsFieldSet(self, i) > 0);
       return false;
   }
 SWIGINTERN int OGRFeatureShadow_GetFieldIndex(OGRFeatureShadow *self,char const *name){
-      return OGR_F_GetFieldIndex(self, name);
+      int i = OGR_F_GetFieldIndex(self, name);
+      if (i == -1)
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      return i;
   }
 SWIGINTERN int OGRFeatureShadow_GetGeomFieldIndex(OGRFeatureShadow *self,char const *name){
-      return OGR_F_GetGeomFieldIndex(self, name);
+      int i = OGR_F_GetGeomFieldIndex(self, name);
+      if (i == -1)
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      return i;
   }
 SWIGINTERN GIntBig OGRFeatureShadow_GetFID(OGRFeatureShadow *self){
     return OGR_F_GetFID(self);
@@ -897,9 +924,9 @@ SWIGINTERN void OGRFeatureShadow_UnsetField__SWIG_0(OGRFeatureShadow *self,int i
 SWIGINTERN void OGRFeatureShadow_UnsetField__SWIG_1(OGRFeatureShadow *self,char const *name){
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
-	  OGR_F_UnsetField(self, i);
+          OGR_F_UnsetField(self, i);
   }
 SWIGINTERN void OGRFeatureShadow_SetField__SWIG_0(OGRFeatureShadow *self,int id,char const *value){
     OGR_F_SetFieldString(self, id, value);
@@ -907,9 +934,9 @@ SWIGINTERN void OGRFeatureShadow_SetField__SWIG_0(OGRFeatureShadow *self,int id,
 SWIGINTERN void OGRFeatureShadow_SetField__SWIG_1(OGRFeatureShadow *self,char const *name,char const *value){
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
-	  OGR_F_SetFieldString(self, i, value);
+          OGR_F_SetFieldString(self, i, value);
   }
 SWIGINTERN void OGRFeatureShadow_SetFieldInteger64(OGRFeatureShadow *self,int id,GIntBig value){
     OGR_F_SetFieldInteger64(self, id, value);
@@ -920,7 +947,7 @@ SWIGINTERN void OGRFeatureShadow_SetField__SWIG_2(OGRFeatureShadow *self,int id,
 SWIGINTERN void OGRFeatureShadow_SetField__SWIG_3(OGRFeatureShadow *self,char const *name,int value){
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
+	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
 	  OGR_F_SetFieldInteger(self, i, value);
   }
@@ -930,22 +957,22 @@ SWIGINTERN void OGRFeatureShadow_SetField__SWIG_4(OGRFeatureShadow *self,int id,
 SWIGINTERN void OGRFeatureShadow_SetField__SWIG_5(OGRFeatureShadow *self,char const *name,double value){
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
+	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
 	  OGR_F_SetFieldDouble(self, i, value);
   }
 SWIGINTERN void OGRFeatureShadow_SetField__SWIG_6(OGRFeatureShadow *self,int id,int year,int month,int day,int hour,int minute,float second,int tzflag){
     OGR_F_SetFieldDateTimeEx(self, id, year, month, day,
-                             hour, minute, second, 
+                             hour, minute, second,
                              tzflag);
   }
 SWIGINTERN void OGRFeatureShadow_SetField__SWIG_7(OGRFeatureShadow *self,char const *name,int year,int month,int day,int hour,int minute,float second,int tzflag){
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
+	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
 	  OGR_F_SetFieldDateTimeEx(self, i, year, month, day,
-				 hour, minute, second, 
+				 hour, minute, second,
 				 tzflag);
   }
 SWIGINTERN void OGRFeatureShadow_SetFieldIntegerList(OGRFeatureShadow *self,int id,int nList,int *pList){
@@ -966,13 +993,13 @@ SWIGINTERN void OGRFeatureShadow_SetFieldBinaryFromHexString__SWIG_0(OGRFeatureS
 SWIGINTERN void OGRFeatureShadow_SetFieldBinaryFromHexString__SWIG_1(OGRFeatureShadow *self,char const *name,char const *pszValue){
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-        CPLError(CE_Failure, 1, "No such field: '%s'", name);
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
       {
-        int nBytes;
-        GByte* pabyBuf = CPLHexToBinary(pszValue, &nBytes );
-        OGR_F_SetFieldBinary(self, i, nBytes, pabyBuf);
-        CPLFree(pabyBuf);
+          int nBytes;
+          GByte* pabyBuf = CPLHexToBinary(pszValue, &nBytes );
+          OGR_F_SetFieldBinary(self, i, nBytes, pabyBuf);
+          CPLFree(pabyBuf);
       }
   }
 SWIGINTERN OGRErr OGRFeatureShadow_SetFrom(OGRFeatureShadow *self,OGRFeatureShadow *other,int forgiving=1){
@@ -1003,7 +1030,7 @@ SWIGINTERN OGRFieldType OGRFeatureShadow_GetFieldType__SWIG_0(OGRFeatureShadow *
 SWIGINTERN OGRFieldType OGRFeatureShadow_GetFieldType__SWIG_1(OGRFeatureShadow *self,char const *name){
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1) {
-          CPLError(CE_Failure, 1, "No such field: '%s'", name);
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
           return (OGRFieldType)0;
       } else
           return (OGRFieldType) OGR_Fld_GetType( OGR_F_GetFieldDefnRef( self, i ) );
@@ -1014,6 +1041,18 @@ SWIGINTERN int OGRFeatureShadow_Validate(OGRFeatureShadow *self,int flags=OGR_F_
 SWIGINTERN void OGRFeatureShadow_FillUnsetWithDefault(OGRFeatureShadow *self,int bNotNullableOnly=FALSE,char **options=NULL){
     OGR_F_FillUnsetWithDefault(self, bNotNullableOnly, options );
   }
+SWIGINTERN char const *OGRFeatureShadow_GetNativeData(OGRFeatureShadow *self){
+    return OGR_F_GetNativeData(self);
+  }
+SWIGINTERN char const *OGRFeatureShadow_GetNativeMediaType(OGRFeatureShadow *self){
+    return OGR_F_GetNativeMediaType(self);
+  }
+SWIGINTERN void OGRFeatureShadow_SetNativeData(OGRFeatureShadow *self,char const *nativeData){
+    OGR_F_SetNativeData(self, nativeData);
+  }
+SWIGINTERN void OGRFeatureShadow_SetNativeMediaType(OGRFeatureShadow *self,char const *nativeMediaType){
+    OGR_F_SetNativeMediaType(self, nativeMediaType);
+  }
 
     static int ValidateOGRGeometryType(OGRwkbGeometryType field_type)
     {
@@ -1046,6 +1085,30 @@ SWIGINTERN void OGRFeatureShadow_FillUnsetWithDefault(OGRFeatureShadow *self,int
             case wkbMultiLineString25D:
             case wkbMultiPolygon25D:
             case wkbGeometryCollection25D:
+            case wkbPointM:
+            case wkbLineStringM:
+            case wkbPolygonM:
+            case wkbMultiPointM:
+            case wkbMultiLineStringM:
+            case wkbMultiPolygonM:
+            case wkbGeometryCollectionM:
+            case wkbCircularStringM:
+            case wkbCompoundCurveM:
+            case wkbCurvePolygonM:
+            case wkbMultiCurveM:
+            case wkbMultiSurfaceM:
+            case wkbPointZM:
+            case wkbLineStringZM:
+            case wkbPolygonZM:
+            case wkbMultiPointZM:
+            case wkbMultiLineStringZM:
+            case wkbMultiPolygonZM:
+            case wkbGeometryCollectionZM:
+            case wkbCircularStringZM:
+            case wkbCompoundCurveZM:
+            case wkbCurvePolygonZM:
+            case wkbMultiCurveZM:
+            case wkbMultiSurfaceZM:
                 return TRUE;
             default:
                 CPLError(CE_Failure, CPLE_IllegalArg, "Illegal geometry type value");
@@ -1072,7 +1135,10 @@ SWIGINTERN OGRFieldDefnShadow *OGRFeatureDefnShadow_GetFieldDefn(OGRFeatureDefnS
     return (OGRFieldDefnShadow*) OGR_FD_GetFieldDefn(self, i);
   }
 SWIGINTERN int OGRFeatureDefnShadow_GetFieldIndex(OGRFeatureDefnShadow *self,char const *name){
-      return OGR_FD_GetFieldIndex(self, name);
+      int i = OGR_FD_GetFieldIndex(self, name);
+      if (i == -1)
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      return i;
   }
 SWIGINTERN void OGRFeatureDefnShadow_AddFieldDefn(OGRFeatureDefnShadow *self,OGRFieldDefnShadow *defn){
     OGR_FD_AddFieldDefn(self, defn);
@@ -1281,7 +1347,7 @@ SWIGINTERN void OGRGeomFieldDefnShadow_SetNullable(OGRGeomFieldDefnShadow *self,
     return OGR_GFld_SetNullable( self, bNullable );
   }
 
-  OGRGeometryShadow* CreateGeometryFromWkb( int len, char *bin_string, 
+  OGRGeometryShadow* CreateGeometryFromWkb( int len, char *bin_string,
                                             OSRSpatialReferenceShadow *reference=NULL ) {
     OGRGeometryH geom = NULL;
     OGRErr err = OGR_G_CreateFromWkb( (unsigned char *) bin_string,
@@ -1294,10 +1360,10 @@ SWIGINTERN void OGRGeomFieldDefnShadow_SetNullable(OGRGeomFieldDefnShadow *self,
     }
     return (OGRGeometryShadow*) geom;
   }
- 
 
 
-  OGRGeometryShadow* CreateGeometryFromWkt( char **val, 
+
+  OGRGeometryShadow* CreateGeometryFromWkt( char **val,
                                       OSRSpatialReferenceShadow *reference=NULL ) {
     OGRGeometryH geom = NULL;
     OGRErr err = OGR_G_CreateFromWkt(val,
@@ -1309,33 +1375,33 @@ SWIGINTERN void OGRGeomFieldDefnShadow_SetNullable(OGRGeomFieldDefnShadow *self,
     }
     return (OGRGeometryShadow*) geom;
   }
- 
+
 
 
   OGRGeometryShadow *CreateGeometryFromGML( const char * input_string ) {
     OGRGeometryShadow* geom = (OGRGeometryShadow*)OGR_G_CreateFromGML(input_string);
     return geom;
   }
- 
+
 
 
   OGRGeometryShadow *CreateGeometryFromJson( const char * input_string ) {
     OGRGeometryShadow* geom = (OGRGeometryShadow*)OGR_G_CreateGeometryFromJson(input_string);
     return geom;
   }
- 
 
 
-  OGRGeometryShadow* BuildPolygonFromEdges( OGRGeometryShadow*  hLineCollection,  
-                                            int bBestEffort = 0, 
-                                            int bAutoClose = 0, 
+
+  OGRGeometryShadow* BuildPolygonFromEdges( OGRGeometryShadow*  hLineCollection,
+                                            int bBestEffort = 0,
+                                            int bAutoClose = 0,
                                             double dfTolerance=0) {
-  
+
   OGRGeometryH hPolygon = NULL;
-  
+
   OGRErr eErr;
 
-  hPolygon = OGRBuildPolygonFromEdges( hLineCollection, bBestEffort, 
+  hPolygon = OGRBuildPolygonFromEdges( hLineCollection, bBestEffort,
                                        bAutoClose, dfTolerance, &eErr );
 
   if (eErr != OGRERR_NONE ) {
@@ -1347,14 +1413,14 @@ SWIGINTERN void OGRGeomFieldDefnShadow_SetNullable(OGRGeomFieldDefnShadow *self,
   }
 
 
-  OGRGeometryShadow* ApproximateArcAngles( 
+  OGRGeometryShadow* ApproximateArcAngles(
         double dfCenterX, double dfCenterY, double dfZ,
-  	double dfPrimaryRadius, double dfSecondaryAxis, double dfRotation, 
+  	double dfPrimaryRadius, double dfSecondaryAxis, double dfRotation,
         double dfStartAngle, double dfEndAngle,
         double dfMaxAngleStepSizeDegrees ) {
-  
-  return (OGRGeometryShadow* )OGR_G_ApproximateArcAngles( 
-             dfCenterX, dfCenterY, dfZ, 
+
+  return (OGRGeometryShadow* )OGR_G_ApproximateArcAngles(
+             dfCenterX, dfCenterY, dfZ,
              dfPrimaryRadius, dfSecondaryAxis, dfRotation,
              dfStartAngle, dfEndAngle, dfMaxAngleStepSizeDegrees );
   }
@@ -1444,6 +1510,12 @@ SWIGINTERN retStringAndCPLFree *OGRGeometryShadow_ExportToJson(OGRGeometryShadow
 SWIGINTERN void OGRGeometryShadow_AddPoint(OGRGeometryShadow *self,double x,double y,double z=0){
     OGR_G_AddPoint( self, x, y, z );
   }
+SWIGINTERN void OGRGeometryShadow_AddPointM(OGRGeometryShadow *self,double x,double y,double m){
+      OGR_G_AddPointM( self, x, y, m );
+  }
+SWIGINTERN void OGRGeometryShadow_AddPointZM(OGRGeometryShadow *self,double x,double y,double z,double m){
+      OGR_G_AddPointZM( self, x, y, z, m );
+  }
 SWIGINTERN void OGRGeometryShadow_AddPoint_2D(OGRGeometryShadow *self,double x,double y){
     OGR_G_AddPoint_2D( self, x, y );
   }
@@ -1483,10 +1555,17 @@ SWIGINTERN double OGRGeometryShadow_GetY(OGRGeometryShadow *self,int point=0){
 SWIGINTERN double OGRGeometryShadow_GetZ(OGRGeometryShadow *self,int point=0){
     return OGR_G_GetZ(self, point);
   }
+SWIGINTERN double OGRGeometryShadow_GetM(OGRGeometryShadow *self,int point=0){
+    return OGR_G_GetM(self, point);
+  }
 SWIGINTERN void OGRGeometryShadow_GetPoint(OGRGeometryShadow *self,int iPoint=0,double argout[3]=NULL){
 
     OGR_G_GetPoint( self, iPoint, argout+0, argout+1, argout+2 );
   }
+SWIGINTERN void OGRGeometryShadow_GetPointZM(OGRGeometryShadow *self,int iPoint=0,double argout[4]=NULL){
+
+      OGR_G_GetPointZM( self, iPoint, argout+0, argout+1, argout+2, argout+3 );
+  }
 SWIGINTERN void OGRGeometryShadow_GetPoint_2D(OGRGeometryShadow *self,int iPoint=0,double argout[2]=NULL){
 
     OGR_G_GetPoint( self, iPoint, argout+0, argout+1, NULL );
@@ -1497,6 +1576,12 @@ SWIGINTERN int OGRGeometryShadow_GetGeometryCount(OGRGeometryShadow *self){
 SWIGINTERN void OGRGeometryShadow_SetPoint(OGRGeometryShadow *self,int point,double x,double y,double z=0){
     OGR_G_SetPoint(self, point, x, y, z);
   }
+SWIGINTERN void OGRGeometryShadow_SetPointM(OGRGeometryShadow *self,int point,double x,double y,double m){
+      OGR_G_SetPointM(self, point, x, y, m);
+  }
+SWIGINTERN void OGRGeometryShadow_SetPointZM(OGRGeometryShadow *self,int point,double x,double y,double z,double m){
+      OGR_G_SetPointZM(self, point, x, y, z, m);
+  }
 SWIGINTERN void OGRGeometryShadow_SetPoint_2D(OGRGeometryShadow *self,int point,double x,double y){
     OGR_G_SetPoint_2D(self, point, x, y);
   }
@@ -1509,6 +1594,9 @@ SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_Simplify(OGRGeometryShadow *self
 SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_SimplifyPreserveTopology(OGRGeometryShadow *self,double tolerance){
     return (OGRGeometryShadow*) OGR_G_SimplifyPreserveTopology(self, tolerance);
   }
+SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_DelaunayTriangulation(OGRGeometryShadow *self,double dfTolerance=0.0,int bOnlyEdges=FALSE){
+    return (OGRGeometryShadow*) OGR_G_DelaunayTriangulation(self, dfTolerance, bOnlyEdges);
+  }
 SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_Boundary(OGRGeometryShadow *self){
     return (OGRGeometryShadow*) OGR_G_Boundary(self);
   }
@@ -1631,9 +1719,24 @@ SWIGINTERN int OGRGeometryShadow_WkbSize(OGRGeometryShadow *self){
 SWIGINTERN int OGRGeometryShadow_GetCoordinateDimension(OGRGeometryShadow *self){
     return OGR_G_GetCoordinateDimension(self);
   }
+SWIGINTERN int OGRGeometryShadow_CoordinateDimension(OGRGeometryShadow *self){
+    return OGR_G_CoordinateDimension(self);
+  }
+SWIGINTERN int OGRGeometryShadow_Is3D(OGRGeometryShadow *self){
+      return OGR_G_Is3D(self);
+  }
+SWIGINTERN int OGRGeometryShadow_IsMeasured(OGRGeometryShadow *self){
+      return OGR_G_IsMeasured(self);
+  }
 SWIGINTERN void OGRGeometryShadow_SetCoordinateDimension(OGRGeometryShadow *self,int dimension){
     OGR_G_SetCoordinateDimension(self, dimension);
   }
+SWIGINTERN void OGRGeometryShadow_Set3D(OGRGeometryShadow *self,int b3D){
+      OGR_G_Set3D(self, b3D);
+  }
+SWIGINTERN void OGRGeometryShadow_SetMeasured(OGRGeometryShadow *self,int bMeasured){
+      OGR_G_SetMeasured(self, bMeasured);
+  }
 SWIGINTERN int OGRGeometryShadow_GetDimension(OGRGeometryShadow *self){
     return OGR_G_GetDimension(self);
   }
@@ -1689,13 +1792,13 @@ OGRwkbGeometryType GT_SetModifier( OGRwkbGeometryType eType, int bSetZ, int bSet
     OGRDataSourceShadow* ds = (OGRDataSourceShadow*)OGROpen(utf8_path,update,NULL);
     if( CPLGetLastErrorType() == CE_Failure && ds != NULL )
     {
-        CPLDebug( "SWIG", 
+        CPLDebug( "SWIG",
 		  "OGROpen() succeeded, but an error is posted, so we destroy"
 		  " the datasource and fail at swig level." );
         OGRReleaseDataSource(ds);
         ds = NULL;
     }
-	
+
     return ds;
   }
 
@@ -1708,15 +1811,17 @@ OGRwkbGeometryType GT_SetModifier( OGRwkbGeometryType eType, int bSetZ, int bSet
         OGRReleaseDataSource(ds);
         ds = NULL;
     }
-	
+
     return ds;
   }
 
 
+static
 OGRDriverShadow* GetDriverByName( char const *name ) {
   return (OGRDriverShadow*) OGRGetDriverByName( name );
 }
 
+static
 OGRDriverShadow* GetDriver(int driver_number) {
   return (OGRDriverShadow*) OGRGetDriver(driver_number);
 }
@@ -1725,8 +1830,11 @@ OGRDriverShadow* GetDriver(int driver_number) {
   char **GeneralCmdLineProcessor( char **papszArgv, int nOptions = 0 ) {
     int nResArgCount;
 
-    nResArgCount = 
-      OGRGeneralCmdLineProcessor( CSLCount(papszArgv), &papszArgv, nOptions ); 
+    if( papszArgv == NULL )
+        return NULL;
+
+    nResArgCount =
+      OGRGeneralCmdLineProcessor( CSLCount(papszArgv), &papszArgv, nOptions );
 
     if( nResArgCount <= 0 )
         return NULL;
@@ -1939,6 +2047,16 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_OLCCurveGeometries_get() {
 }
 
 
+SWIGEXPORT char * SWIGSTDCALL CSharp_OLCMeasuredGeometries_get() {
+  char * jresult ;
+  char *result = 0 ;
+  
+  result = (char *)("MeasuredGeometries");
+  jresult = SWIG_csharp_string_callback((const char *)result); 
+  return jresult;
+}
+
+
 SWIGEXPORT char * SWIGSTDCALL CSharp_ODsCCreateLayer_get() {
   char * jresult ;
   char *result = 0 ;
@@ -1999,6 +2117,16 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_ODsCEmulatedTransactions_get() {
 }
 
 
+SWIGEXPORT char * SWIGSTDCALL CSharp_ODsCMeasuredGeometries_get() {
+  char * jresult ;
+  char *result = 0 ;
+  
+  result = (char *)("MeasuredGeometries");
+  jresult = SWIG_csharp_string_callback((const char *)result); 
+  return jresult;
+}
+
+
 SWIGEXPORT char * SWIGSTDCALL CSharp_ODrCCreateDataSource_get() {
   char * jresult ;
   char *result = 0 ;
@@ -6835,7 +6963,7 @@ SWIGEXPORT double SWIGSTDCALL CSharp_Feature_GetFieldAsDouble__SWIG_1(void * jar
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_Feature_GetFieldAsDateTime(void * jarg1, int jarg2, int * jarg3, int * jarg4, int * jarg5, int * jarg6, int * jarg7, float * jarg8, int * jarg9) {
+SWIGEXPORT void SWIGSTDCALL CSharp_Feature_GetFieldAsDateTime__SWIG_0(void * jarg1, int jarg2, int * jarg3, int * jarg4, int * jarg5, int * jarg6, int * jarg7, float * jarg8, int * jarg9) {
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
   int *arg3 = (int *) 0 ;
@@ -6857,7 +6985,59 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Feature_GetFieldAsDateTime(void * jarg1, int
   arg9 = (int *)jarg9; 
   {
     CPLErrorReset();
-    OGRFeatureShadow_GetFieldAsDateTime(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+    OGRFeatureShadow_GetFieldAsDateTime__SWIG_0(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Feature_GetFieldAsDateTime__SWIG_1(void * jarg1, char * jarg2, int * jarg3, int * jarg4, int * jarg5, int * jarg6, int * jarg7, float * jarg8, int * jarg9) {
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  int *arg3 = (int *) 0 ;
+  int *arg4 = (int *) 0 ;
+  int *arg5 = (int *) 0 ;
+  int *arg6 = (int *) 0 ;
+  int *arg7 = (int *) 0 ;
+  float *arg8 = (float *) 0 ;
+  int *arg9 = (int *) 0 ;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  arg3 = (int *)jarg3; 
+  arg4 = (int *)jarg4; 
+  arg5 = (int *)jarg5; 
+  arg6 = (int *)jarg6; 
+  arg7 = (int *)jarg7; 
+  arg8 = (float *)jarg8; 
+  arg9 = (int *)jarg9; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return ; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    OGRFeatureShadow_GetFieldAsDateTime__SWIG_1(arg1,(char const *)arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -8180,6 +8360,134 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Feature_FillUnsetWithDefault(void * jarg1, in
 }
 
 
+SWIGEXPORT char * SWIGSTDCALL CSharp_Feature_GetNativeData(void * jarg1) {
+  char * jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *result = 0 ;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    result = (char *)OGRFeatureShadow_GetNativeData(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = SWIG_csharp_string_callback((const char *)result); 
+  return jresult;
+}
+
+
+SWIGEXPORT char * SWIGSTDCALL CSharp_Feature_GetNativeMediaType(void * jarg1) {
+  char * jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *result = 0 ;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    result = (char *)OGRFeatureShadow_GetNativeMediaType(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = SWIG_csharp_string_callback((const char *)result); 
+  return jresult;
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetNativeData(void * jarg1, char * jarg2) {
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  {
+    CPLErrorReset();
+    OGRFeatureShadow_SetNativeData(arg1,(char const *)arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetNativeMediaType(void * jarg1, char * jarg2) {
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  {
+    CPLErrorReset();
+    OGRFeatureShadow_SetNativeMediaType(arg1,(char const *)arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+}
+
+
 SWIGEXPORT void SWIGSTDCALL CSharp_delete_FeatureDefn(void * jarg1) {
   OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   
@@ -10129,7 +10437,7 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_CreateGeometryFromWkt(void * jarg1, void *
   OGRGeometryShadow *result = 0 ;
   
   /* %typemap(in) (char **ignorechange) */
-  char * savearg = *((char **)jarg1); 
+  char * savearg = *((char **)jarg1);
   arg1 = (char **)jarg1;
   arg2 = (OSRSpatialReferenceShadow *)jarg2; 
   {
@@ -10912,17 +11220,19 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Geometry_AddPoint(void * jarg1, double jarg2,
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_Geometry_AddPoint_2D(void * jarg1, double jarg2, double jarg3) {
+SWIGEXPORT void SWIGSTDCALL CSharp_Geometry_AddPointM(void * jarg1, double jarg2, double jarg3, double jarg4) {
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   double arg2 ;
   double arg3 ;
+  double arg4 ;
   
   arg1 = (OGRGeometryShadow *)jarg1; 
   arg2 = (double)jarg2; 
   arg3 = (double)jarg3; 
+  arg4 = (double)jarg4; 
   {
     CPLErrorReset();
-    OGRGeometryShadow_AddPoint_2D(arg1,arg2,arg3);
+    OGRGeometryShadow_AddPointM(arg1,arg2,arg3,arg4);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -10945,16 +11255,86 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Geometry_AddPoint_2D(void * jarg1, double jar
 }
 
 
-SWIGEXPORT int SWIGSTDCALL CSharp_Geometry_AddGeometryDirectly(void * jarg1, void * jarg2) {
-  int jresult ;
+SWIGEXPORT void SWIGSTDCALL CSharp_Geometry_AddPointZM(void * jarg1, double jarg2, double jarg3, double jarg4, double jarg5) {
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-  OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
-  OGRErr result;
+  double arg2 ;
+  double arg3 ;
+  double arg4 ;
+  double arg5 ;
   
   arg1 = (OGRGeometryShadow *)jarg1; 
-  arg2 = (OGRGeometryShadow *)jarg2; 
-  {
-    if (!arg2) {
+  arg2 = (double)jarg2; 
+  arg3 = (double)jarg3; 
+  arg4 = (double)jarg4; 
+  arg5 = (double)jarg5; 
+  {
+    CPLErrorReset();
+    OGRGeometryShadow_AddPointZM(arg1,arg2,arg3,arg4,arg5);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Geometry_AddPoint_2D(void * jarg1, double jarg2, double jarg3) {
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  double arg2 ;
+  double arg3 ;
+  
+  arg1 = (OGRGeometryShadow *)jarg1; 
+  arg2 = (double)jarg2; 
+  arg3 = (double)jarg3; 
+  {
+    CPLErrorReset();
+    OGRGeometryShadow_AddPoint_2D(arg1,arg2,arg3);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_Geometry_AddGeometryDirectly(void * jarg1, void * jarg2) {
+  int jresult ;
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
+  OGRErr result;
+  
+  arg1 = (OGRGeometryShadow *)jarg1; 
+  arg2 = (OGRGeometryShadow *)jarg2; 
+  {
+    if (!arg2) {
       {
         SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
       };
@@ -11379,6 +11759,41 @@ SWIGEXPORT double SWIGSTDCALL CSharp_Geometry_GetZ(void * jarg1, int jarg2) {
 }
 
 
+SWIGEXPORT double SWIGSTDCALL CSharp_Geometry_GetM(void * jarg1, int jarg2) {
+  double jresult ;
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  int arg2 = (int) 0 ;
+  double result;
+  
+  arg1 = (OGRGeometryShadow *)jarg1; 
+  arg2 = (int)jarg2; 
+  {
+    CPLErrorReset();
+    result = (double)OGRGeometryShadow_GetM(arg1,arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
 SWIGEXPORT void SWIGSTDCALL CSharp_Geometry_GetPoint(void * jarg1, int jarg2, void * jarg3) {
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   int arg2 = (int) 0 ;
@@ -11415,6 +11830,42 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Geometry_GetPoint(void * jarg1, int jarg2, vo
 }
 
 
+SWIGEXPORT void SWIGSTDCALL CSharp_Geometry_GetPointZM(void * jarg1, int jarg2, void * jarg3) {
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  int arg2 = (int) 0 ;
+  double *arg3 = (double *) (double *)NULL ;
+  
+  arg1 = (OGRGeometryShadow *)jarg1; 
+  arg2 = (int)jarg2; 
+  {
+    /* %typemap(in) (double argout[ANY]) */
+    arg3 = (double *)jarg3;
+  }
+  {
+    CPLErrorReset();
+    OGRGeometryShadow_GetPointZM(arg1,arg2,arg3);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+}
+
+
 SWIGEXPORT void SWIGSTDCALL CSharp_Geometry_GetPoint_2D(void * jarg1, int jarg2, void * jarg3) {
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   int arg2 = (int) 0 ;
@@ -11521,6 +11972,82 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Geometry_SetPoint(void * jarg1, int jarg2, do
 }
 
 
+SWIGEXPORT void SWIGSTDCALL CSharp_Geometry_SetPointM(void * jarg1, int jarg2, double jarg3, double jarg4, double jarg5) {
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  int arg2 ;
+  double arg3 ;
+  double arg4 ;
+  double arg5 ;
+  
+  arg1 = (OGRGeometryShadow *)jarg1; 
+  arg2 = (int)jarg2; 
+  arg3 = (double)jarg3; 
+  arg4 = (double)jarg4; 
+  arg5 = (double)jarg5; 
+  {
+    CPLErrorReset();
+    OGRGeometryShadow_SetPointM(arg1,arg2,arg3,arg4,arg5);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Geometry_SetPointZM(void * jarg1, int jarg2, double jarg3, double jarg4, double jarg5, double jarg6) {
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  int arg2 ;
+  double arg3 ;
+  double arg4 ;
+  double arg5 ;
+  double arg6 ;
+  
+  arg1 = (OGRGeometryShadow *)jarg1; 
+  arg2 = (int)jarg2; 
+  arg3 = (double)jarg3; 
+  arg4 = (double)jarg4; 
+  arg5 = (double)jarg5; 
+  arg6 = (double)jarg6; 
+  {
+    CPLErrorReset();
+    OGRGeometryShadow_SetPointZM(arg1,arg2,arg3,arg4,arg5,arg6);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+}
+
+
 SWIGEXPORT void SWIGSTDCALL CSharp_Geometry_SetPoint_2D(void * jarg1, int jarg2, double jarg3, double jarg4) {
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   int arg2 ;
@@ -11661,6 +12188,43 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_Geometry_SimplifyPreserveTopology(void * ja
 }
 
 
+SWIGEXPORT void * SWIGSTDCALL CSharp_Geometry_DelaunayTriangulation(void * jarg1, double jarg2, int jarg3) {
+  void * jresult ;
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  double arg2 = (double) 0.0 ;
+  int arg3 = (int) FALSE ;
+  OGRGeometryShadow *result = 0 ;
+  
+  arg1 = (OGRGeometryShadow *)jarg1; 
+  arg2 = (double)jarg2; 
+  arg3 = (int)jarg3; 
+  {
+    CPLErrorReset();
+    result = (OGRGeometryShadow *)OGRGeometryShadow_DelaunayTriangulation(arg1,arg2,arg3);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
 SWIGEXPORT void * SWIGSTDCALL CSharp_Geometry_Boundary(void * jarg1) {
   void * jresult ;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
@@ -13108,6 +13672,105 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Geometry_GetCoordinateDimension(void * jarg1)
 }
 
 
+SWIGEXPORT int SWIGSTDCALL CSharp_Geometry_CoordinateDimension(void * jarg1) {
+  int jresult ;
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  int result;
+  
+  arg1 = (OGRGeometryShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    result = (int)OGRGeometryShadow_CoordinateDimension(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_Geometry_Is3D(void * jarg1) {
+  int jresult ;
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  int result;
+  
+  arg1 = (OGRGeometryShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    result = (int)OGRGeometryShadow_Is3D(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_Geometry_IsMeasured(void * jarg1) {
+  int jresult ;
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  int result;
+  
+  arg1 = (OGRGeometryShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    result = (int)OGRGeometryShadow_IsMeasured(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
 SWIGEXPORT void SWIGSTDCALL CSharp_Geometry_SetCoordinateDimension(void * jarg1, int jarg2) {
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   int arg2 ;
@@ -13139,6 +13802,68 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Geometry_SetCoordinateDimension(void * jarg1,
 }
 
 
+SWIGEXPORT void SWIGSTDCALL CSharp_Geometry_Set3D(void * jarg1, int jarg2) {
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  int arg2 ;
+  
+  arg1 = (OGRGeometryShadow *)jarg1; 
+  arg2 = (int)jarg2; 
+  {
+    CPLErrorReset();
+    OGRGeometryShadow_Set3D(arg1,arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Geometry_SetMeasured(void * jarg1, int jarg2) {
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  int arg2 ;
+  
+  arg1 = (OGRGeometryShadow *)jarg1; 
+  arg2 = (int)jarg2; 
+  {
+    CPLErrorReset();
+    OGRGeometryShadow_SetMeasured(arg1,arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+}
+
+
 SWIGEXPORT int SWIGSTDCALL CSharp_Geometry_GetDimension(void * jarg1) {
   int jresult ;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
@@ -13653,6 +14378,39 @@ SWIGEXPORT int SWIGSTDCALL CSharp_GT_SetZ(int jarg1) {
 }
 
 
+SWIGEXPORT int SWIGSTDCALL CSharp_GT_SetM(int jarg1) {
+  int jresult ;
+  OGRwkbGeometryType arg1 ;
+  OGRwkbGeometryType result;
+  
+  arg1 = (OGRwkbGeometryType)jarg1; 
+  {
+    CPLErrorReset();
+    result = (OGRwkbGeometryType)OGR_GT_SetM(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
 SWIGEXPORT int SWIGSTDCALL CSharp_GT_SetModifier(int jarg1, int jarg2, int jarg3) {
   int jresult ;
   OGRwkbGeometryType arg1 ;
@@ -13723,6 +14481,39 @@ SWIGEXPORT int SWIGSTDCALL CSharp_GT_HasZ(int jarg1) {
 }
 
 
+SWIGEXPORT int SWIGSTDCALL CSharp_GT_HasM(int jarg1) {
+  int jresult ;
+  OGRwkbGeometryType arg1 ;
+  int result;
+  
+  arg1 = (OGRwkbGeometryType)jarg1; 
+  {
+    CPLErrorReset();
+    result = (int)OGR_GT_HasM(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
 SWIGEXPORT int SWIGSTDCALL CSharp_GT_IsSubClassOf(int jarg1, int jarg2) {
   int jresult ;
   OGRwkbGeometryType arg1 ;
diff --git a/swig/csharp/ogr/osr_wrap.cpp b/swig/csharp/ogr/osr_wrap.cpp
index b9396cf..24359c3 100644
--- a/swig/csharp/ogr/osr_wrap.cpp
+++ b/swig/csharp/ogr/osr_wrap.cpp
@@ -357,10 +357,15 @@ typedef void OSRCoordinateTransformationShadow;
 #endif
 
 
-void VeryQuiteErrorHandler(CPLErr eclass, int code, const char *msg ) {
+void VeryQuietErrorHandler(CPLErr eclass, int code, const char *msg ) {
   /* If the error class is CE_Fatal, we want to have a message issued
      because the CPL support code does an abort() before any exception
      can be generated */
+#if defined(SWIGPERL)
+    AV* error_stack = get_av("Geo::GDAL::error", 0);
+    SV *error = newSVpv(msg, 0);
+    av_push(error_stack, error);
+#endif
   if (eclass == CE_Fatal ) {
     CPLDefaultErrorHandler(eclass, code, msg );
   }
@@ -368,7 +373,7 @@ void VeryQuiteErrorHandler(CPLErr eclass, int code, const char *msg ) {
 
 
 void UseExceptions() {
-  CPLSetErrorHandler( (CPLErrorHandler) VeryQuiteErrorHandler );
+  CPLSetErrorHandler( (CPLErrorHandler) VeryQuietErrorHandler );
 }
 
 void DontUseExceptions() {
@@ -385,7 +390,7 @@ OGRErr GetWellKnownGeogCSAsWKT( const char *name, char **argout ) {
   OGRSpatialReferenceH srs = OSRNewSpatialReference("");
   OGRErr rcode = OSRSetWellKnownGeogCS( srs, name );
   if( rcode == OGRERR_NONE )
-      rcode = OSRExportToWkt ( srs, argout );  
+      rcode = OSRExportToWkt ( srs, argout );
   OSRDestroySpatialReference( srs );
   return rcode;
 }
@@ -418,7 +423,7 @@ OGRErr GetUserInputAsWKT( const char *name, char **argout ) {
   OGRSpatialReferenceH srs = OSRNewSpatialReference("");
   OGRErr rcode = OSRSetFromUserInput( srs, name );
   if( rcode == OGRERR_NONE )
-      rcode = OSRExportToWkt ( srs, argout );  
+      rcode = OSRExportToWkt ( srs, argout );
   OSRDestroySpatialReference( srs );
   return rcode;
 }
@@ -476,7 +481,7 @@ SWIGINTERN char const *OSRSpatialReferenceShadow_GetAttrValue(OSRSpatialReferenc
     return OSRGetAttrValue( self, name, child );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetAttrValue(OSRSpatialReferenceShadow *self,char const *name,char const *value){
-    return OSRSetAttrValue( self, name, value ); 
+    return OSRSetAttrValue( self, name, value );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetAngularUnits(OSRSpatialReferenceShadow *self,char const *name,double to_radians){
     return OSRSetAngularUnits( self, name, to_radians );
@@ -507,7 +512,7 @@ SWIGINTERN char const *OSRSpatialReferenceShadow_GetLinearUnitsName(OSRSpatialRe
       name = OSRGetAttrValue( self, "LOCAL_CS|UNIT", 0 );
     }
 
-    if (name != 0) 
+    if (name != 0)
       return name;
 
     return "Meter";
@@ -522,8 +527,8 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetUTM(OSRSpatialReferenceShadow *se
     return OSRSetUTM( self, zone, north );
   }
 SWIGINTERN int OSRSpatialReferenceShadow_GetUTMZone(OSRSpatialReferenceShadow *self){
-    // Note: we will return south zones as negative since it is 
-    // hard to return two values as the C API does. 
+    // Note: we will return south zones as negative since it is
+    // hard to return two values as the C API does.
     int bNorth = FALSE;
     int nZone = OSRGetUTMZone( self, &bNorth );
     if( !bNorth )
@@ -540,7 +545,7 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetProjection(OSRSpatialReferenceSha
     return OSRSetProjection( self, arg );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetProjParm(OSRSpatialReferenceShadow *self,char const *name,double val){
-    return OSRSetProjParm( self, name, val ); 
+    return OSRSetProjParm( self, name, val );
   }
 SWIGINTERN double OSRSpatialReferenceShadow_GetProjParm(OSRSpatialReferenceShadow *self,char const *name,double default_val=0.0){
     // Return code ignored.
@@ -566,26 +571,26 @@ SWIGINTERN double OSRSpatialReferenceShadow_GetInvFlattening(OSRSpatialReference
     return OSRGetInvFlattening( self, 0 );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetACEA(OSRSpatialReferenceShadow *self,double stdp1,double stdp2,double clat,double clong,double fe,double fn){
-    return OSRSetACEA( self, stdp1, stdp2, clat, clong, 
+    return OSRSetACEA( self, stdp1, stdp2, clat, clong,
                        fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetAE(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetAE( self, clat, clong, 
+    return OSRSetAE( self, clat, clong,
                      fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetBonne(OSRSpatialReferenceShadow *self,double stdp,double cm,double fe,double fn){
     return OSRSetBonne( self, stdp, cm, fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetCEA(OSRSpatialReferenceShadow *self,double stdp1,double cm,double fe,double fn){
-    return OSRSetCEA( self, stdp1, cm, 
+    return OSRSetCEA( self, stdp1, cm,
                       fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetCS(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetCS( self, clat, clong, 
+    return OSRSetCS( self, clat, clong,
                      fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetEC(OSRSpatialReferenceShadow *self,double stdp1,double stdp2,double clat,double clong,double fe,double fn){
-    return OSRSetEC( self, stdp1, stdp2, clat, clong, 
+    return OSRSetEC( self, stdp1, stdp2, clat, clong,
                      fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetEckertIV(OSRSpatialReferenceShadow *self,double cm,double fe,double fn){
@@ -595,7 +600,7 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetEckertVI(OSRSpatialReferenceShado
     return OSRSetEckertVI( self, cm, fe, fn);
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetEquirectangular(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetEquirectangular( self, clat, clong, 
+    return OSRSetEquirectangular( self, clat, clong,
                                   fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetEquirectangular2(OSRSpatialReferenceShadow *self,double clat,double clong,double pseudostdparallellat,double fe,double fn){
@@ -620,7 +625,7 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGEOS(OSRSpatialReferenceShadow *s
                        fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGnomonic(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetGnomonic( self, clat, clong, 
+    return OSRSetGnomonic( self, clat, clong,
                            fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetHOM(OSRSpatialReferenceShadow *self,double clat,double clong,double azimuth,double recttoskew,double scale,double fe,double fn){
@@ -628,56 +633,56 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetHOM(OSRSpatialReferenceShadow *se
                       scale, fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetHOM2PNO(OSRSpatialReferenceShadow *self,double clat,double dfLat1,double dfLong1,double dfLat2,double dfLong2,double scale,double fe,double fn){
-    return OSRSetHOM2PNO( self, clat, dfLat1, dfLong1, dfLat2, dfLong2, 
+    return OSRSetHOM2PNO( self, clat, dfLat1, dfLong1, dfLat2, dfLong2,
                           scale, fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetKrovak(OSRSpatialReferenceShadow *self,double clat,double clong,double azimuth,double pseudostdparallellat,double scale,double fe,double fn){
-    return OSRSetKrovak( self, clat, clong, 
-                         azimuth, pseudostdparallellat, 
+    return OSRSetKrovak( self, clat, clong,
+                         azimuth, pseudostdparallellat,
                          scale, fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLAEA(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetLAEA( self, clat, clong, 
+    return OSRSetLAEA( self, clat, clong,
                        fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLCC(OSRSpatialReferenceShadow *self,double stdp1,double stdp2,double clat,double clong,double fe,double fn){
-    return OSRSetLCC( self, stdp1, stdp2, clat, clong, 
+    return OSRSetLCC( self, stdp1, stdp2, clat, clong,
                       fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLCC1SP(OSRSpatialReferenceShadow *self,double clat,double clong,double scale,double fe,double fn){
-    return OSRSetLCC1SP( self, clat, clong, scale, 
+    return OSRSetLCC1SP( self, clat, clong, scale,
                          fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLCCB(OSRSpatialReferenceShadow *self,double stdp1,double stdp2,double clat,double clong,double fe,double fn){
-    return OSRSetLCCB( self, stdp1, stdp2, clat, clong, 
+    return OSRSetLCCB( self, stdp1, stdp2, clat, clong,
                        fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetMC(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetMC( self, clat, clong,    
+    return OSRSetMC( self, clat, clong,
                      fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetMercator(OSRSpatialReferenceShadow *self,double clat,double clong,double scale,double fe,double fn){
-    return OSRSetMercator( self, clat, clong, 
+    return OSRSetMercator( self, clat, clong,
                            scale, fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetMollweide(OSRSpatialReferenceShadow *self,double cm,double fe,double fn){
-    return OSRSetMollweide( self, cm, 
+    return OSRSetMollweide( self, cm,
                             fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetNZMG(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetNZMG( self, clat, clong, 
+    return OSRSetNZMG( self, clat, clong,
                        fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetOS(OSRSpatialReferenceShadow *self,double dfOriginLat,double dfCMeridian,double scale,double fe,double fn){
-    return OSRSetOS( self, dfOriginLat, dfCMeridian, scale, 
+    return OSRSetOS( self, dfOriginLat, dfCMeridian, scale,
                      fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetOrthographic(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetOrthographic( self, clat, clong, 
+    return OSRSetOrthographic( self, clat, clong,
                                fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetPolyconic(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetPolyconic( self, clat, clong, 
+    return OSRSetPolyconic( self, clat, clong,
                             fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetPS(OSRSpatialReferenceShadow *self,double clat,double clong,double scale,double fe,double fn){
@@ -691,7 +696,7 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetSinusoidal(OSRSpatialReferenceSha
     return OSRSetSinusoidal( self, clong, fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetStereographic(OSRSpatialReferenceShadow *self,double clat,double clong,double scale,double fe,double fn){
-    return OSRSetStereographic( self, clat, clong, scale, 
+    return OSRSetStereographic( self, clat, clong, scale,
                                 fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetSOC(OSRSpatialReferenceShadow *self,double latitudeoforigin,double cm,double fe,double fn){
@@ -699,19 +704,19 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetSOC(OSRSpatialReferenceShadow *se
 	              fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetTM(OSRSpatialReferenceShadow *self,double clat,double clong,double scale,double fe,double fn){
-    return OSRSetTM( self, clat, clong, scale, 
+    return OSRSetTM( self, clat, clong, scale,
                      fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetTMVariant(OSRSpatialReferenceShadow *self,char const *pszVariantName,double clat,double clong,double scale,double fe,double fn){
-    return OSRSetTMVariant( self, pszVariantName, clat, clong,  
+    return OSRSetTMVariant( self, pszVariantName, clat, clong,
                             scale, fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetTMG(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetTMG( self, clat, clong, 
+    return OSRSetTMG( self, clat, clong,
                       fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetTMSO(OSRSpatialReferenceShadow *self,double clat,double clong,double scale,double fe,double fn){
-    return OSRSetTMSO( self, clat, clong, scale, 
+    return OSRSetTMSO( self, clat, clong, scale,
                        fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetVDG(OSRSpatialReferenceShadow *self,double clong,double fe,double fn){
@@ -5183,7 +5188,7 @@ SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_ImportFromWkt(void * jarg1, v
   
   arg1 = (OSRSpatialReferenceShadow *)jarg1; 
   /* %typemap(in) (char **ignorechange) */
-  char * savearg = *((char **)jarg2); 
+  char * savearg = *((char **)jarg2);
   arg2 = (char **)jarg2;
   {
     CPLErrorReset();
diff --git a/swig/csharp/ogr/wkbGeometryType.cs b/swig/csharp/ogr/wkbGeometryType.cs
index 3991fb9..f833bc2 100644
--- a/swig/csharp/ogr/wkbGeometryType.cs
+++ b/swig/csharp/ogr/wkbGeometryType.cs
@@ -22,6 +22,10 @@ public enum wkbGeometryType {
   wkbCurvePolygon = 10,
   wkbMultiCurve = 11,
   wkbMultiSurface = 12,
+  wkbCurve = 13,
+  wkbSurface = 14,
+  wkbPolyhedralSurface = 15,
+  wkbTIN = 16,
   wkbNone = 100,
   wkbLinearRing = 101,
   wkbCircularStringZ = 1008,
@@ -29,6 +33,42 @@ public enum wkbGeometryType {
   wkbCurvePolygonZ = 1010,
   wkbMultiCurveZ = 1011,
   wkbMultiSurfaceZ = 1012,
+  wkbCurveZ = 1013,
+  wkbSurfaceZ = 1014,
+  wkbPolyhedralSurfaceZ = 1015,
+  wkbTINZ = 1016,
+  wkbPointM = 2001,
+  wkbLineStringM = 2002,
+  wkbPolygonM = 2003,
+  wkbMultiPointM = 2004,
+  wkbMultiLineStringM = 2005,
+  wkbMultiPolygonM = 2006,
+  wkbGeometryCollectionM = 2007,
+  wkbCircularStringM = 2008,
+  wkbCompoundCurveM = 2009,
+  wkbCurvePolygonM = 2010,
+  wkbMultiCurveM = 2011,
+  wkbMultiSurfaceM = 2012,
+  wkbCurveM = 2013,
+  wkbSurfaceM = 2014,
+  wkbPolyhedralSurfaceM = 2015,
+  wkbTINM = 2016,
+  wkbPointZM = 3001,
+  wkbLineStringZM = 3002,
+  wkbPolygonZM = 3003,
+  wkbMultiPointZM = 3004,
+  wkbMultiLineStringZM = 3005,
+  wkbMultiPolygonZM = 3006,
+  wkbGeometryCollectionZM = 3007,
+  wkbCircularStringZM = 3008,
+  wkbCompoundCurveZM = 3009,
+  wkbCurvePolygonZM = 3010,
+  wkbMultiCurveZM = 3011,
+  wkbMultiSurfaceZM = 3012,
+  wkbCurveZM = 3013,
+  wkbSurfaceZM = 3014,
+  wkbPolyhedralSurfaceZM = 3015,
+  wkbTINZM = 3016,
   wkbPoint25D = -2147483647,
   wkbLineString25D = -2147483646,
   wkbPolygon25D = -2147483645,
diff --git a/swig/csharp/osr/CoordinateTransformation.cs b/swig/csharp/osr/CoordinateTransformation.cs
index 3830d67..0a862a5 100644
--- a/swig/csharp/osr/CoordinateTransformation.cs
+++ b/swig/csharp/osr/CoordinateTransformation.cs
@@ -15,7 +15,7 @@ public class CoordinateTransformation : IDisposable {
   private HandleRef swigCPtr;
   protected bool swigCMemOwn;
   protected object swigParentRef;
-  
+
   protected static object ThisOwn_true() { return null; }
   protected object ThisOwn_false() { return this; }
 
diff --git a/swig/csharp/osr/Osr.cs b/swig/csharp/osr/Osr.cs
index e498927..facfdc2 100644
--- a/swig/csharp/osr/Osr.cs
+++ b/swig/csharp/osr/Osr.cs
@@ -15,7 +15,7 @@ public class Osr {
 
   internal class OsrObject : IDisposable {
 	public virtual void Dispose() {
-      
+
     }
   }
   internal static OsrObject theOsrObject = new OsrObject();
@@ -35,21 +35,21 @@ public class Osr {
   {
     if (str == null)
       return null;
-    
+
     int bytecount = System.Text.Encoding.UTF8.GetMaxByteCount(str.Length);
     byte[] bytes = new byte[bytecount + 1];
     System.Text.Encoding.UTF8.GetBytes(str, 0, str.Length, bytes, 0);
     return bytes;
   }
-  
+
   internal static string Utf8BytesToString(IntPtr pNativeData)
   {
     if (pNativeData == IntPtr.Zero)
         return null;
-        
+
     int length = Marshal.PtrToStringAnsi(pNativeData).Length;
-    byte[] strbuf = new byte[length];  
-    Marshal.Copy(pNativeData, strbuf, 0, length); 
+    byte[] strbuf = new byte[length];
+    Marshal.Copy(pNativeData, strbuf, 0, length);
     return System.Text.Encoding.UTF8.GetString(strbuf);
   }
 
@@ -82,7 +82,7 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
                 ++count;
         }
         string[] ret = new string[count];
-        if (count > 0) {       
+        if (count > 0) {
 	        for(int cx = 0; cx < count; cx++) {
                 objPtr = System.Runtime.InteropServices.Marshal.ReadIntPtr(cPtr, cx * System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)));
                 ret[cx]= (objPtr == IntPtr.Zero) ? null : System.Runtime.InteropServices.Marshal.PtrToStringAnsi(objPtr);
@@ -105,7 +105,7 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
                 ++count;
         }
         string[] ret = new string[count];
-        if (count > 0) {       
+        if (count > 0) {
 	        for(int cx = 0; cx < count; cx++) {
                 objPtr = System.Runtime.InteropServices.Marshal.ReadIntPtr(cPtr, cx * System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)));
                 ret[cx]= (objPtr == IntPtr.Zero) ? null : System.Runtime.InteropServices.Marshal.PtrToStringAnsi(objPtr);
@@ -130,7 +130,7 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
     return ret;
   }
 
-  public const string SRS_WKT_WGS84 = "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9108\"]],AUTHORITY[\"EPSG\",\"4326\"]]";
+  public const string SRS_WKT_WGS84 = "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]]";
   public const string SRS_PT_ALBERS_CONIC_EQUAL_AREA = "Albers_Conic_Equal_Area";
   public const string SRS_PT_AZIMUTHAL_EQUIDISTANT = "Azimuthal_Equidistant";
   public const string SRS_PT_CASSINI_SOLDNER = "Cassini_Soldner";
@@ -199,6 +199,7 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
   public const string SRS_PT_CRASTER_PARABOLIC = "Craster_Parabolic";
   public const string SRS_PT_LOXIMUTHAL = "Loximuthal";
   public const string SRS_PT_QUARTIC_AUTHALIC = "Quartic_Authalic";
+  public const string SRS_PT_SCH = "Spherical_Cross_Track_Height";
   public const string SRS_PP_CENTRAL_MERIDIAN = "central_meridian";
   public const string SRS_PP_SCALE_FACTOR = "scale_factor";
   public const string SRS_PP_STANDARD_PARALLEL_1 = "standard_parallel_1";
@@ -228,6 +229,10 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
   public const string SRS_PP_LONGITUDE_OF_1ST_POINT = "Longitude_Of_1st_Point";
   public const string SRS_PP_LATITUDE_OF_2ND_POINT = "Latitude_Of_2nd_Point";
   public const string SRS_PP_LONGITUDE_OF_2ND_POINT = "Longitude_Of_2nd_Point";
+  public const string SRS_PP_PEG_POINT_LATITUDE = "peg_point_latitude";
+  public const string SRS_PP_PEG_POINT_LONGITUDE = "peg_point_longitude";
+  public const string SRS_PP_PEG_POINT_HEADING = "peg_point_heading";
+  public const string SRS_PP_PEG_POINT_HEIGHT = "peg_point_height";
   public const string SRS_UL_METER = "Meter";
   public const string SRS_UL_FOOT = "Foot (International)";
   public const string SRS_UL_FOOT_CONV = "0.3048";
diff --git a/swig/csharp/osr/SpatialReference.cs b/swig/csharp/osr/SpatialReference.cs
index d88176f..4c10a7e 100644
--- a/swig/csharp/osr/SpatialReference.cs
+++ b/swig/csharp/osr/SpatialReference.cs
@@ -15,7 +15,7 @@ public class SpatialReference : IDisposable {
   private HandleRef swigCPtr;
   protected bool swigCMemOwn;
   protected object swigParentRef;
-  
+
   protected static object ThisOwn_true() { return null; }
   protected object ThisOwn_false() { return this; }
 
diff --git a/swig/csharp/osr/osr_wrap.cpp b/swig/csharp/osr/osr_wrap.cpp
index b9396cf..24359c3 100644
--- a/swig/csharp/osr/osr_wrap.cpp
+++ b/swig/csharp/osr/osr_wrap.cpp
@@ -357,10 +357,15 @@ typedef void OSRCoordinateTransformationShadow;
 #endif
 
 
-void VeryQuiteErrorHandler(CPLErr eclass, int code, const char *msg ) {
+void VeryQuietErrorHandler(CPLErr eclass, int code, const char *msg ) {
   /* If the error class is CE_Fatal, we want to have a message issued
      because the CPL support code does an abort() before any exception
      can be generated */
+#if defined(SWIGPERL)
+    AV* error_stack = get_av("Geo::GDAL::error", 0);
+    SV *error = newSVpv(msg, 0);
+    av_push(error_stack, error);
+#endif
   if (eclass == CE_Fatal ) {
     CPLDefaultErrorHandler(eclass, code, msg );
   }
@@ -368,7 +373,7 @@ void VeryQuiteErrorHandler(CPLErr eclass, int code, const char *msg ) {
 
 
 void UseExceptions() {
-  CPLSetErrorHandler( (CPLErrorHandler) VeryQuiteErrorHandler );
+  CPLSetErrorHandler( (CPLErrorHandler) VeryQuietErrorHandler );
 }
 
 void DontUseExceptions() {
@@ -385,7 +390,7 @@ OGRErr GetWellKnownGeogCSAsWKT( const char *name, char **argout ) {
   OGRSpatialReferenceH srs = OSRNewSpatialReference("");
   OGRErr rcode = OSRSetWellKnownGeogCS( srs, name );
   if( rcode == OGRERR_NONE )
-      rcode = OSRExportToWkt ( srs, argout );  
+      rcode = OSRExportToWkt ( srs, argout );
   OSRDestroySpatialReference( srs );
   return rcode;
 }
@@ -418,7 +423,7 @@ OGRErr GetUserInputAsWKT( const char *name, char **argout ) {
   OGRSpatialReferenceH srs = OSRNewSpatialReference("");
   OGRErr rcode = OSRSetFromUserInput( srs, name );
   if( rcode == OGRERR_NONE )
-      rcode = OSRExportToWkt ( srs, argout );  
+      rcode = OSRExportToWkt ( srs, argout );
   OSRDestroySpatialReference( srs );
   return rcode;
 }
@@ -476,7 +481,7 @@ SWIGINTERN char const *OSRSpatialReferenceShadow_GetAttrValue(OSRSpatialReferenc
     return OSRGetAttrValue( self, name, child );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetAttrValue(OSRSpatialReferenceShadow *self,char const *name,char const *value){
-    return OSRSetAttrValue( self, name, value ); 
+    return OSRSetAttrValue( self, name, value );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetAngularUnits(OSRSpatialReferenceShadow *self,char const *name,double to_radians){
     return OSRSetAngularUnits( self, name, to_radians );
@@ -507,7 +512,7 @@ SWIGINTERN char const *OSRSpatialReferenceShadow_GetLinearUnitsName(OSRSpatialRe
       name = OSRGetAttrValue( self, "LOCAL_CS|UNIT", 0 );
     }
 
-    if (name != 0) 
+    if (name != 0)
       return name;
 
     return "Meter";
@@ -522,8 +527,8 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetUTM(OSRSpatialReferenceShadow *se
     return OSRSetUTM( self, zone, north );
   }
 SWIGINTERN int OSRSpatialReferenceShadow_GetUTMZone(OSRSpatialReferenceShadow *self){
-    // Note: we will return south zones as negative since it is 
-    // hard to return two values as the C API does. 
+    // Note: we will return south zones as negative since it is
+    // hard to return two values as the C API does.
     int bNorth = FALSE;
     int nZone = OSRGetUTMZone( self, &bNorth );
     if( !bNorth )
@@ -540,7 +545,7 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetProjection(OSRSpatialReferenceSha
     return OSRSetProjection( self, arg );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetProjParm(OSRSpatialReferenceShadow *self,char const *name,double val){
-    return OSRSetProjParm( self, name, val ); 
+    return OSRSetProjParm( self, name, val );
   }
 SWIGINTERN double OSRSpatialReferenceShadow_GetProjParm(OSRSpatialReferenceShadow *self,char const *name,double default_val=0.0){
     // Return code ignored.
@@ -566,26 +571,26 @@ SWIGINTERN double OSRSpatialReferenceShadow_GetInvFlattening(OSRSpatialReference
     return OSRGetInvFlattening( self, 0 );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetACEA(OSRSpatialReferenceShadow *self,double stdp1,double stdp2,double clat,double clong,double fe,double fn){
-    return OSRSetACEA( self, stdp1, stdp2, clat, clong, 
+    return OSRSetACEA( self, stdp1, stdp2, clat, clong,
                        fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetAE(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetAE( self, clat, clong, 
+    return OSRSetAE( self, clat, clong,
                      fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetBonne(OSRSpatialReferenceShadow *self,double stdp,double cm,double fe,double fn){
     return OSRSetBonne( self, stdp, cm, fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetCEA(OSRSpatialReferenceShadow *self,double stdp1,double cm,double fe,double fn){
-    return OSRSetCEA( self, stdp1, cm, 
+    return OSRSetCEA( self, stdp1, cm,
                       fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetCS(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetCS( self, clat, clong, 
+    return OSRSetCS( self, clat, clong,
                      fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetEC(OSRSpatialReferenceShadow *self,double stdp1,double stdp2,double clat,double clong,double fe,double fn){
-    return OSRSetEC( self, stdp1, stdp2, clat, clong, 
+    return OSRSetEC( self, stdp1, stdp2, clat, clong,
                      fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetEckertIV(OSRSpatialReferenceShadow *self,double cm,double fe,double fn){
@@ -595,7 +600,7 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetEckertVI(OSRSpatialReferenceShado
     return OSRSetEckertVI( self, cm, fe, fn);
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetEquirectangular(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetEquirectangular( self, clat, clong, 
+    return OSRSetEquirectangular( self, clat, clong,
                                   fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetEquirectangular2(OSRSpatialReferenceShadow *self,double clat,double clong,double pseudostdparallellat,double fe,double fn){
@@ -620,7 +625,7 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGEOS(OSRSpatialReferenceShadow *s
                        fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGnomonic(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetGnomonic( self, clat, clong, 
+    return OSRSetGnomonic( self, clat, clong,
                            fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetHOM(OSRSpatialReferenceShadow *self,double clat,double clong,double azimuth,double recttoskew,double scale,double fe,double fn){
@@ -628,56 +633,56 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetHOM(OSRSpatialReferenceShadow *se
                       scale, fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetHOM2PNO(OSRSpatialReferenceShadow *self,double clat,double dfLat1,double dfLong1,double dfLat2,double dfLong2,double scale,double fe,double fn){
-    return OSRSetHOM2PNO( self, clat, dfLat1, dfLong1, dfLat2, dfLong2, 
+    return OSRSetHOM2PNO( self, clat, dfLat1, dfLong1, dfLat2, dfLong2,
                           scale, fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetKrovak(OSRSpatialReferenceShadow *self,double clat,double clong,double azimuth,double pseudostdparallellat,double scale,double fe,double fn){
-    return OSRSetKrovak( self, clat, clong, 
-                         azimuth, pseudostdparallellat, 
+    return OSRSetKrovak( self, clat, clong,
+                         azimuth, pseudostdparallellat,
                          scale, fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLAEA(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetLAEA( self, clat, clong, 
+    return OSRSetLAEA( self, clat, clong,
                        fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLCC(OSRSpatialReferenceShadow *self,double stdp1,double stdp2,double clat,double clong,double fe,double fn){
-    return OSRSetLCC( self, stdp1, stdp2, clat, clong, 
+    return OSRSetLCC( self, stdp1, stdp2, clat, clong,
                       fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLCC1SP(OSRSpatialReferenceShadow *self,double clat,double clong,double scale,double fe,double fn){
-    return OSRSetLCC1SP( self, clat, clong, scale, 
+    return OSRSetLCC1SP( self, clat, clong, scale,
                          fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLCCB(OSRSpatialReferenceShadow *self,double stdp1,double stdp2,double clat,double clong,double fe,double fn){
-    return OSRSetLCCB( self, stdp1, stdp2, clat, clong, 
+    return OSRSetLCCB( self, stdp1, stdp2, clat, clong,
                        fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetMC(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetMC( self, clat, clong,    
+    return OSRSetMC( self, clat, clong,
                      fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetMercator(OSRSpatialReferenceShadow *self,double clat,double clong,double scale,double fe,double fn){
-    return OSRSetMercator( self, clat, clong, 
+    return OSRSetMercator( self, clat, clong,
                            scale, fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetMollweide(OSRSpatialReferenceShadow *self,double cm,double fe,double fn){
-    return OSRSetMollweide( self, cm, 
+    return OSRSetMollweide( self, cm,
                             fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetNZMG(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetNZMG( self, clat, clong, 
+    return OSRSetNZMG( self, clat, clong,
                        fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetOS(OSRSpatialReferenceShadow *self,double dfOriginLat,double dfCMeridian,double scale,double fe,double fn){
-    return OSRSetOS( self, dfOriginLat, dfCMeridian, scale, 
+    return OSRSetOS( self, dfOriginLat, dfCMeridian, scale,
                      fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetOrthographic(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetOrthographic( self, clat, clong, 
+    return OSRSetOrthographic( self, clat, clong,
                                fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetPolyconic(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetPolyconic( self, clat, clong, 
+    return OSRSetPolyconic( self, clat, clong,
                             fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetPS(OSRSpatialReferenceShadow *self,double clat,double clong,double scale,double fe,double fn){
@@ -691,7 +696,7 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetSinusoidal(OSRSpatialReferenceSha
     return OSRSetSinusoidal( self, clong, fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetStereographic(OSRSpatialReferenceShadow *self,double clat,double clong,double scale,double fe,double fn){
-    return OSRSetStereographic( self, clat, clong, scale, 
+    return OSRSetStereographic( self, clat, clong, scale,
                                 fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetSOC(OSRSpatialReferenceShadow *self,double latitudeoforigin,double cm,double fe,double fn){
@@ -699,19 +704,19 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetSOC(OSRSpatialReferenceShadow *se
 	              fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetTM(OSRSpatialReferenceShadow *self,double clat,double clong,double scale,double fe,double fn){
-    return OSRSetTM( self, clat, clong, scale, 
+    return OSRSetTM( self, clat, clong, scale,
                      fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetTMVariant(OSRSpatialReferenceShadow *self,char const *pszVariantName,double clat,double clong,double scale,double fe,double fn){
-    return OSRSetTMVariant( self, pszVariantName, clat, clong,  
+    return OSRSetTMVariant( self, pszVariantName, clat, clong,
                             scale, fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetTMG(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetTMG( self, clat, clong, 
+    return OSRSetTMG( self, clat, clong,
                       fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetTMSO(OSRSpatialReferenceShadow *self,double clat,double clong,double scale,double fe,double fn){
-    return OSRSetTMSO( self, clat, clong, scale, 
+    return OSRSetTMSO( self, clat, clong, scale,
                        fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetVDG(OSRSpatialReferenceShadow *self,double clong,double fe,double fn){
@@ -5183,7 +5188,7 @@ SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_ImportFromWkt(void * jarg1, v
   
   arg1 = (OSRSpatialReferenceShadow *)jarg1; 
   /* %typemap(in) (char **ignorechange) */
-  char * savearg = *((char **)jarg2); 
+  char * savearg = *((char **)jarg2);
   arg2 = (char **)jarg2;
   {
     CPLErrorReset();
diff --git a/swig/include/Band.i b/swig/include/Band.i
index b1efd0d..7e82cd7 100644
--- a/swig/include/Band.i
+++ b/swig/include/Band.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: Band.i 29216 2015-05-20 15:11:18Z ajolma $
+ * $Id: Band.i 32928 2016-01-11 14:21:32Z rouault $
  *
  * Name:     Band.i
  * Project:  GDAL Python Interface
@@ -34,20 +34,13 @@
  *
 *************************************************************************/
 
-
 %{
-/* Returned size is in bytes or 0 if an error occured */
+/* Returned size is in bytes or 0 if an error occurred. */
 static
 GIntBig ComputeBandRasterIOSize (int buf_xsize, int buf_ysize, int nPixelSize,
                                  GIntBig nPixelSpace, GIntBig nLineSpace,
                                  int bSpacingShouldBeMultipleOfPixelSize )
 {
-#if SIZEOF_VOIDP == 8
-    const GIntBig MAX_INT = (((GIntBig)0x7fffffff) << 32) | 0xffffffff;
-#else
-    const GIntBig MAX_INT = 0x7fffffff;
-#endif
-
     if (buf_xsize <= 0 || buf_ysize <= 0)
     {
         CPLError(CE_Failure, CPLE_IllegalArg, "Illegal values for buffer size");
@@ -85,44 +78,40 @@ GIntBig ComputeBandRasterIOSize (int buf_xsize, int buf_ysize, int nPixelSize,
     }
 
     GIntBig nRet = (GIntBig)(buf_ysize - 1) * nLineSpace + (GIntBig)(buf_xsize - 1) * nPixelSpace + nPixelSize;
-    if (nRet > MAX_INT)
+#if SIZEOF_VOIDP == 4
+    if (nRet > INT_MAX)
     {
         CPLError(CE_Failure, CPLE_IllegalArg, "Integer overflow");
         return 0;
     }
+#endif
 
     return nRet;
 }
 %}
 
-#if !defined(SWIGCSHARP) && !defined(SWIGJAVA) && !defined(SWIGPYTHON)
+#if defined(SWIGPERL)
 %{
 static
-CPLErr ReadRaster_internal( GDALRasterBandShadow *obj, 
+CPLErr ReadRaster_internal( GDALRasterBandShadow *obj,
                             int xoff, int yoff, int xsize, int ysize,
                             int buf_xsize, int buf_ysize,
                             GDALDataType buf_type,
-                            int *buf_size, char **buf,
+                            GIntBig *buf_size, char **buf,
                             GIntBig pixel_space, GIntBig line_space,
                             GDALRasterIOExtraArg* psExtraArg )
 {
   CPLErr result;
 
-  GIntBig nRequiredSize = ComputeBandRasterIOSize( buf_xsize, buf_ysize, GDALGetDataTypeSize( buf_type ) / 8,
+  *buf_size = ComputeBandRasterIOSize( buf_xsize, buf_ysize, GDALGetDataTypeSize( buf_type ) / 8,
                                        pixel_space, line_space, FALSE );
-  if (nRequiredSize > 0x7fffffff)
-  {
-     CPLError(CE_Failure, CPLE_IllegalArg, "Integer overflow");
-     nRequiredSize = 0;
-  }
-  *buf_size = (int)nRequiredSize;
-  
+
   if ( *buf_size == 0 )
   {
       *buf = 0;
       return CE_Failure;
   }
-  
+
   *buf = (char*) malloc( *buf_size );
   if ( *buf )
   {
@@ -138,7 +127,7 @@ CPLErr ReadRaster_internal( GDALRasterBandShadow *obj,
   }
   else
   {
-    CPLError(CE_Failure, CPLE_OutOfMemory, "Not enough memory to allocate %d bytes", *buf_size);
+    CPLError(CE_Failure, CPLE_OutOfMemory, "Not enough memory to allocate "CPL_FRMT_GIB" bytes", *buf_size);
     result = CE_Failure;
     *buf = 0;
     *buf_size = 0;
@@ -149,7 +138,7 @@ CPLErr ReadRaster_internal( GDALRasterBandShadow *obj,
 %}
 #endif
 
-#if !defined(SWIGCSHARP) && !defined(SWIGJAVA)
+#if defined(SWIGPYTHON) || defined(SWIGPERL)
 %{
 static
 CPLErr WriteRaster_internal( GDALRasterBandShadow *obj,
@@ -157,20 +146,21 @@ CPLErr WriteRaster_internal( GDALRasterBandShadow *obj,
                              int buf_xsize, int buf_ysize,
                              GDALDataType buf_type,
                              GIntBig buf_size, char *buffer,
-                             int pixel_space, int line_space)
+                             GIntBig pixel_space, GIntBig line_space,
+                             GDALRasterIOExtraArg* psExtraArg )
 {
     GIntBig min_buffer_size = ComputeBandRasterIOSize (buf_xsize, buf_ysize, GDALGetDataTypeSize( buf_type ) / 8,
                                                    pixel_space, line_space, FALSE );
     if ( min_buffer_size == 0 )
       return CE_Failure;
-      
+
     if ( buf_size < min_buffer_size ) {
       CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
       return CE_Failure;
     }
 
-    return GDALRasterIO( obj, GF_Write, xoff, yoff, xsize, ysize, 
-		        (void *) buffer, buf_xsize, buf_ysize, buf_type, pixel_space, line_space );
+    return GDALRasterIOEx( obj, GF_Write, xoff, yoff, xsize, ysize,
+                           (void *) buffer, buf_xsize, buf_ysize, buf_type, pixel_space, line_space, psExtraArg );
 }
 %}
 
@@ -238,7 +228,11 @@ public:
   CPLErr SetNoDataValue( double d) {
     return GDALSetRasterNoDataValue( self, d );
   }
-  
+
+  CPLErr DeleteNoDataValue() {
+    return GDALDeleteRasterNoDataValue( self );
+  }
+
   /* Interface method added for GDAL 1.7.0 */
   const char* GetUnitType() {
       return GDALGetRasterUnitType( self );
@@ -254,7 +248,7 @@ public:
     return GDALGetRasterCategoryNames( self );
   }
   %clear (char **);
-  
+
   %apply (char **options) { (char **names) };
   CPLErr SetRasterCategoryNames( char **names ) {
     return GDALSetRasterCategoryNames( self, names );
@@ -286,23 +280,23 @@ public:
   CPLErr SetScale( double val ) {
     return GDALSetRasterScale( self, val );
   }
-  
+
 %apply (double *OUTPUT){double *min, double *max, double *mean, double *stddev};
-%apply (IF_ERROR_RETURN_NONE) { (CPLErr) }; 
-  CPLErr GetStatistics( int approx_ok, int force, 
+%apply (IF_ERROR_RETURN_NONE) { (CPLErr) };
+  CPLErr GetStatistics( int approx_ok, int force,
                       double *min, double *max, double *mean, double *stddev ){
     if (min) *min = 0;
     if (max) *max = 0;
     if (mean) *mean = 0;
     if (stddev) *stddev = -1; /* This is the only way to recognize from Python if GetRasterStatistics() has updated the values */
-    return GDALGetRasterStatistics( self, approx_ok, force, 
+    return GDALGetRasterStatistics( self, approx_ok, force,
 				    min, max, mean, stddev );
   }
 %clear (CPLErr);
 
   /* Interface method added for GDAL 1.7.0 */
 %apply (double *OUTPUT){double *min, double *max, double *mean, double *stddev};
-%apply (IF_ERROR_RETURN_NONE) { (CPLErr) }; 
+%apply (IF_ERROR_RETURN_NONE) { (CPLErr) };
   CPLErr ComputeStatistics( bool approx_ok, double *min = NULL, double *max = NULL, double *mean = NULL, double *stddev = NULL,
                             GDALProgressFunc callback = NULL, void* callback_data=NULL){
     return GDALComputeRasterStatistics( self, approx_ok, min, max, mean, stddev, callback, callback_data );
@@ -341,7 +335,7 @@ public:
   }
 
   void ComputeBandStats( double argout[2], int samplestep = 1) {
-    GDALComputeBandStats( self, samplestep, argout+0, argout+1, 
+    GDALComputeBandStats( self, samplestep, argout+0, argout+1,
                           NULL, NULL );
   }
 
@@ -349,17 +343,18 @@ public:
     return GDALFillRaster( self, real_fill, imag_fill );
   }
 
-#if !defined(SWIGCSHARP) && !defined(SWIGJAVA) && !defined(SWIGPYTHON)
-%apply ( int *nLen, char **pBuf ) { (int *buf_len, char **buf ) };
+#if defined(SWIGPERL)
+%apply (GIntBig *nLen, char **pBuf) { (GIntBig *buf_len, char **buf) };
+%apply (GIntBig *optional_GIntBig) { (GIntBig*) };
 %apply ( int *optional_int ) {(int*)};
 %feature( "kwargs" ) ReadRaster;
   CPLErr ReadRaster( int xoff, int yoff, int xsize, int ysize,
-                     int *buf_len, char **buf,
+                     GIntBig *buf_len, char **buf,
                      int *buf_xsize = 0,
                      int *buf_ysize = 0,
                      int *buf_type = 0,
-                     int *buf_pixel_space = 0,
-                     int *buf_line_space = 0,
+                     GIntBig *buf_pixel_space = 0,
+                     GIntBig *buf_line_space = 0,
                      GDALRIOResampleAlg resample_alg = GRIORA_NearestNeighbour,
                      GDALProgressFunc callback = NULL,
                      void* callback_data=NULL ) {
@@ -380,12 +375,14 @@ public:
                                 nxsize, nysize, ntype, buf_len, buf, pixel_space, line_space,
                                 &sExtraArg );
   }
-%clear (int *buf_len, char **buf );
+%clear (GIntBig *buf_len, char **buf );
 %clear (int*);
-#endif /* !defined(SWIGCSHARP) && !defined(SWIGJAVA) && !defined(SWIGPYTHON) */
+%clear (GIntBig*);
+#endif
 
-#if defined(SWIGPYTHON)
+#if defined(SWIGPYTHON) || defined(SWIGPERL)
 %apply (GIntBig nLen, char *pBuf) { (GIntBig buf_len, char *buf_string) };
+%apply (GIntBig *optional_GIntBig) { (GIntBig*) };
 %apply ( int *optional_int ) {(int*)};
 %feature( "kwargs" ) WriteRaster;
   CPLErr WriteRaster( int xoff, int yoff, int xsize, int ysize,
@@ -393,42 +390,22 @@ public:
                       int *buf_xsize = 0,
                       int *buf_ysize = 0,
                       int *buf_type = 0,
-                      int *buf_pixel_space = 0,
-                      int *buf_line_space = 0) {
+                      GIntBig *buf_pixel_space = 0,
+                      GIntBig *buf_line_space = 0) {
     int nxsize = (buf_xsize==0) ? xsize : *buf_xsize;
     int nysize = (buf_ysize==0) ? ysize : *buf_ysize;
     GDALDataType ntype  = (buf_type==0) ? GDALGetRasterDataType(self)
                                         : (GDALDataType)*buf_type;
-    int pixel_space = (buf_pixel_space == 0) ? 0 : *buf_pixel_space;
-    int line_space = (buf_line_space == 0) ? 0 : *buf_line_space;
+    GIntBig pixel_space = (buf_pixel_space == 0) ? 0 : *buf_pixel_space;
+    GIntBig line_space = (buf_line_space == 0) ? 0 : *buf_line_space;
+    GDALRasterIOExtraArg* psExtraArg = NULL;
     return WriteRaster_internal( self, xoff, yoff, xsize, ysize,
-                                 nxsize, nysize, ntype, buf_len, buf_string, pixel_space, line_space );
+                                 nxsize, nysize, ntype, buf_len, buf_string, pixel_space, line_space, psExtraArg );
   }
 %clear (GIntBig buf_len, char *buf_string);
 %clear (int*);
-#elif !defined(SWIGCSHARP) && !defined(SWIGJAVA)
-%apply (int nLen, char *pBuf) { (int buf_len, char *buf_string) };
-%apply ( int *optional_int ) {(int*)};
-%feature( "kwargs" ) WriteRaster;
-  CPLErr WriteRaster( int xoff, int yoff, int xsize, int ysize,
-                      int buf_len, char *buf_string,
-                      int *buf_xsize = 0,
-                      int *buf_ysize = 0,
-                      int *buf_type = 0,
-                      int *buf_pixel_space = 0,
-                      int *buf_line_space = 0) {
-    int nxsize = (buf_xsize==0) ? xsize : *buf_xsize;
-    int nysize = (buf_ysize==0) ? ysize : *buf_ysize;
-    GDALDataType ntype  = (buf_type==0) ? GDALGetRasterDataType(self)
-                                        : (GDALDataType)*buf_type;
-    int pixel_space = (buf_pixel_space == 0) ? 0 : *buf_pixel_space;
-    int line_space = (buf_line_space == 0) ? 0 : *buf_line_space;
-    return WriteRaster_internal( self, xoff, yoff, xsize, ysize,
-                                 nxsize, nysize, ntype, buf_len, buf_string, pixel_space, line_space );
-  }
-%clear (int buf_len, char *buf_string);
-%clear (int*);
-#endif /* !defined(SWIGCSHARP) && !defined(SWIGJAVA) */
+%clear (GIntBig*);
+#endif
 
   void FlushCache() {
     GDALFlushRasterCache( self );
@@ -448,13 +425,13 @@ public:
   int SetRasterColorTable( GDALColorTableShadow *arg ) {
     return GDALSetRasterColorTable( self, arg );
   }
- 
+
   // Preferred name to match C++ API
   int SetColorTable( GDALColorTableShadow *arg ) {
     return GDALSetRasterColorTable( self, arg );
   }
- 
-  GDALRasterAttributeTableShadow *GetDefaultRAT() { 
+
+  GDALRasterAttributeTableShadow *GetDefaultRAT() {
       return (GDALRasterAttributeTableShadow*) GDALGetDefaultRAT(self);
   }
 
@@ -477,7 +454,7 @@ public:
 #if defined(SWIGPYTHON) || defined(SWIGPERL)
 #if defined(SWIGPERL)
 %apply (int len, GUIntBig *output) {(int buckets, GUIntBig *panHistogram)};
-%apply (IF_ERROR_RETURN_NONE) { (CPLErr) }; 
+%apply (IF_ERROR_RETURN_NONE) { (CPLErr) };
 #endif
 %feature( "kwargs" ) GetHistogram;
   CPLErr GetHistogram( double min=-0.5,
@@ -488,7 +465,7 @@ public:
                      int approx_ok = 1,
                      GDALProgressFunc callback = NULL,
                      void* callback_data=NULL ) {
-    CPLErrorReset(); 
+    CPLErrorReset();
     CPLErr err = GDALGetRasterHistogramEx( self, min, max, buckets, panHistogram,
                                          include_out_of_range, approx_ok,
                                          callback, callback_data );
@@ -512,7 +489,7 @@ public:
                      int approx_ok = 1,
                      GDALProgressFunc callback = NULL,
                      void* callback_data=NULL ) {
-    CPLErrorReset(); 
+    CPLErrorReset();
     CPLErr err = GDALGetRasterHistogram( self, min, max, buckets, panHistogram,
                                          include_out_of_range, approx_ok,
                                          callback, callback_data );
@@ -528,15 +505,15 @@ public:
 #if defined(SWIGPERL)
 %apply (double *OUTPUT){double *min_ret, double *max_ret}
 %apply (int *nLen, const GUIntBig **pList) {(int *buckets_ret, GUIntBig **ppanHistogram)};
-%apply (IF_ERROR_RETURN_NONE) { (CPLErr) }; 
+%apply (IF_ERROR_RETURN_NONE) { (CPLErr) };
 #endif
 %feature ("kwargs") GetDefaultHistogram;
-CPLErr GetDefaultHistogram( double *min_ret=NULL, double *max_ret=NULL, int *buckets_ret = NULL, 
-                            GUIntBig **ppanHistogram = NULL, int force = 1, 
+CPLErr GetDefaultHistogram( double *min_ret=NULL, double *max_ret=NULL, int *buckets_ret = NULL,
+                            GUIntBig **ppanHistogram = NULL, int force = 1,
                             GDALProgressFunc callback = NULL,
                             void* callback_data=NULL ) {
     return GDALGetDefaultHistogramEx( self, min_ret, max_ret, buckets_ret,
-                                    ppanHistogram, force, 
+                                    ppanHistogram, force,
                                     callback, callback_data );
 }
 #if defined(SWIGPERL)
@@ -547,12 +524,12 @@ CPLErr GetDefaultHistogram( double *min_ret=NULL, double *max_ret=NULL, int *buc
 #else
 #ifndef SWIGJAVA
 %feature ("kwargs") GetDefaultHistogram;
-CPLErr GetDefaultHistogram( double *min_ret=NULL, double *max_ret=NULL, int *buckets_ret = NULL, 
-                            int **ppanHistogram = NULL, int force = 1, 
+CPLErr GetDefaultHistogram( double *min_ret=NULL, double *max_ret=NULL, int *buckets_ret = NULL,
+                            int **ppanHistogram = NULL, int force = 1,
 			    GDALProgressFunc callback = NULL,
                             void* callback_data=NULL ) {
     return GDALGetDefaultHistogram( self, min_ret, max_ret, buckets_ret,
-                                    ppanHistogram, force, 
+                                    ppanHistogram, force,
                                     callback, callback_data );
 }
 #endif
@@ -560,9 +537,9 @@ CPLErr GetDefaultHistogram( double *min_ret=NULL, double *max_ret=NULL, int *buc
 
 #if defined(SWIGPYTHON) || defined(SWIGPERL)
 %apply (int nList, GUIntBig* pList) {(int buckets_in, GUIntBig *panHistogram_in)}
-CPLErr SetDefaultHistogram( double min, double max, 
+CPLErr SetDefaultHistogram( double min, double max,
                             int buckets_in, GUIntBig *panHistogram_in ) {
-    return GDALSetDefaultHistogramEx( self, min, max, 
+    return GDALSetDefaultHistogramEx( self, min, max,
                                     buckets_in, panHistogram_in );
 }
 %clear (int buckets_in, GUIntBig *panHistogram_in);
@@ -570,9 +547,9 @@ CPLErr SetDefaultHistogram( double min, double max,
 #if defined(SWIGJAVA)
 %apply (int nList, int* pList) {(int buckets_in, int *panHistogram_in)}
 #endif
-CPLErr SetDefaultHistogram( double min, double max, 
+CPLErr SetDefaultHistogram( double min, double max,
        			    int buckets_in, int *panHistogram_in ) {
-    return GDALSetDefaultHistogram( self, min, max, 
+    return GDALSetDefaultHistogram( self, min, max,
     	   			    buckets_in, panHistogram_in );
 }
 #if defined(SWIGJAVA)
diff --git a/swig/include/ColorTable.i b/swig/include/ColorTable.i
index 96289af..fb3200c 100644
--- a/swig/include/ColorTable.i
+++ b/swig/include/ColorTable.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ColorTable.i 16504 2009-03-07 20:01:35Z rouault $
+ * $Id: ColorTable.i 32864 2016-01-08 21:00:50Z goatbar $
  *
  * Name:     ColorTable.i
  * Project:  GDAL Python Interface
@@ -53,26 +53,26 @@ public:
     ~GDALColorTableShadow() {
         GDALDestroyColorTable(self);
     }
-  
+
     %newobject Clone();
     GDALColorTableShadow* Clone() {
         return (GDALColorTableShadow*) GDALCloneColorTable (self);
     }
-  
+
     GDALPaletteInterp GetPaletteInterpretation() {
         return GDALGetPaletteInterpretation(self);
     }
 
-#ifdef SWIGRUBY 
-%rename (get_count) GetColorEntryCount; 
-#else 
-%rename (GetCount) GetColorEntryCount; 
-#endif  
-  
+#ifdef SWIGRUBY
+%rename (get_count) GetColorEntryCount;
+#else
+%rename (GetCount) GetColorEntryCount;
+#endif
+
     int GetColorEntryCount() {
         return GDALGetColorEntryCount(self);
     }
-    
+
     GDALColorEntry* GetColorEntry (int entry) {
         return (GDALColorEntry*) GDALGetColorEntry(self, entry);
     }
@@ -86,7 +86,7 @@ public:
     void SetColorEntry( int entry, const GDALColorEntry* centry) {
         GDALSetColorEntry(self, entry, centry);
     }
-    
+
     void CreateColorRamp(   int nStartIndex, const GDALColorEntry* startcolor,
                             int nEndIndex, const GDALColorEntry* endcolor) {
         GDALCreateColorRamp(self, nStartIndex, startcolor, nEndIndex, endcolor);
diff --git a/swig/include/Dataset.i b/swig/include/Dataset.i
index d30e0cd..5d79706 100644
--- a/swig/include/Dataset.i
+++ b/swig/include/Dataset.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: Dataset.i 28601 2015-03-03 11:06:40Z rouault $
+ * $Id: Dataset.i 32935 2016-01-11 16:49:14Z rouault $
  *
  * Name:     Dataset.i
  * Project:  GDAL Python Interface
@@ -29,19 +29,13 @@
  *****************************************************************************/
 
 %{
-/* Returned size is in bytes or 0 if an error occured */
+/* Returned size is in bytes or 0 if an error occurred. */
 static
 GIntBig ComputeDatasetRasterIOSize (int buf_xsize, int buf_ysize, int nPixelSize,
                                 int nBands, int* bandMap, int nBandMapArrayLength,
                                 GIntBig nPixelSpace, GIntBig nLineSpace, GIntBig nBandSpace,
                                 int bSpacingShouldBeMultipleOfPixelSize )
 {
-#if SIZEOF_VOIDP == 8
-    const GIntBig MAX_INT = (((GIntBig)0x7fffffff) << 32) | 0xffffffff;
-#else
-    const GIntBig MAX_INT = 0x7fffffff;
-#endif
-
     if (buf_xsize <= 0 || buf_ysize <= 0)
     {
         CPLError(CE_Failure, CPLE_IllegalArg, "Illegal values for buffer size");
@@ -95,45 +89,41 @@ GIntBig ComputeDatasetRasterIOSize (int buf_xsize, int buf_ysize, int nPixelSize
     }
 
     GIntBig nRet = (GIntBig)(buf_ysize - 1) * nLineSpace + (GIntBig)(buf_xsize - 1) * nPixelSpace + (GIntBig)(nBands - 1) * nBandSpace + nPixelSize;
-    if (nRet > MAX_INT)
+#if SIZEOF_VOIDP == 4
+    if (nRet > INT_MAX)
     {
         CPLError(CE_Failure, CPLE_IllegalArg, "Integer overflow");
         return 0;
     }
+#endif
 
     return nRet;
 }
 %}
 
-#if !defined(SWIGCSHARP) && !defined(SWIGJAVA) && !defined(SWIGPYTHON)
+#if defined(SWIGPERL)
 %{
 static
-CPLErr DSReadRaster_internal( GDALDatasetShadow *obj, 
+CPLErr DSReadRaster_internal( GDALDatasetShadow *obj,
                             int xoff, int yoff, int xsize, int ysize,
                             int buf_xsize, int buf_ysize,
                             GDALDataType buf_type,
-                            int *buf_size, char **buf,
+                            GIntBig *buf_size, char **buf,
                             int band_list, int *pband_list,
                             GIntBig pixel_space, GIntBig line_space, GIntBig band_space,
                             GDALRasterIOExtraArg* psExtraArg)
 {
   CPLErr result;
 
-  GIntBig nRequiredSize = ComputeDatasetRasterIOSize (buf_xsize, buf_ysize, GDALGetDataTypeSize( buf_type ) / 8,
+  *buf_size = ComputeDatasetRasterIOSize (buf_xsize, buf_ysize, GDALGetDataTypeSize( buf_type ) / 8,
                                           band_list ? band_list : GDALGetRasterCount(obj), pband_list, band_list,
                                           pixel_space, line_space, band_space, FALSE);
-  if (nRequiredSize > 0x7fffffff)
-  {
-     CPLError(CE_Failure, CPLE_IllegalArg, "Integer overflow");
-     nRequiredSize = 0;
-  }
-  *buf_size = (int)nRequiredSize;
   if (*buf_size == 0)
   {
       *buf = 0;
       return CE_Failure;
   }
-  
+
   *buf = (char*) malloc( *buf_size );
   if (*buf)
   {
@@ -149,7 +139,7 @@ CPLErr DSReadRaster_internal( GDALDatasetShadow *obj,
   }
   else
   {
-    CPLError(CE_Failure, CPLE_OutOfMemory, "Not enough memory to allocate %d bytes", *buf_size);
+    CPLError(CE_Failure, CPLE_OutOfMemory, "Not enough memory to allocate "CPL_FRMT_GIB" bytes", *buf_size);
     result = CE_Failure;
     *buf = 0;
     *buf_size = 0;
@@ -285,7 +275,7 @@ public:
         }
         return GDALARLockBuffer(hReader,timeout);
     }
-    
+
     void UnlockBuffer()
     {
         GDALAsyncReaderH hReader = AsyncReaderWrapperGetReader(self);
@@ -297,7 +287,7 @@ public:
     }
 
     } /* extend */
-}; /* GDALAsyncReaderShadow */ 
+}; /* GDALAsyncReaderShadow */
 
 //************************************************************************/
 //
@@ -391,7 +381,7 @@ public:
 
   // The (int,int*) arguments are typemapped.  The name of the first argument
   // becomes the kwarg name for it.
-#ifndef SWIGCSHARP  
+#ifndef SWIGCSHARP
 #ifndef SWIGJAVA
 %feature("kwargs") BuildOverviews;
 #endif
@@ -411,13 +401,13 @@ public:
                       GDALProgressFunc callback = NULL,
                       void* callback_data=NULL ) {
 #endif
-    return GDALBuildOverviews(  self, 
-                                resampling ? resampling : "NEAREST", 
-                                overviewlist, 
-                                pOverviews, 
-                                0, 
-                                0, 
-                                callback, 
+    return GDALBuildOverviews(  self,
+                                resampling ? resampling : "NEAREST",
+                                overviewlist,
+                                pOverviews,
+                                0,
+                                0,
+                                callback,
                                 callback_data);
   }
 #ifndef SWIGCSHARP
@@ -436,7 +426,7 @@ public:
   const char *GetGCPProjection() {
     return GDALGetGCPProjection( self );
   }
-  
+
 #ifndef SWIGCSHARP
   void GetGCPs( int *nGCPs, GDAL_GCP const **pGCPs ) {
     *nGCPs = GDALGetGCPCount( self );
@@ -471,9 +461,10 @@ public:
   }
 %clear char **;
 
-#if defined(SWIGPYTHON)
+#if defined(SWIGPYTHON) || defined(SWIGPERL)
 %feature("kwargs") WriteRaster;
 %apply (GIntBig nLen, char *pBuf) { (GIntBig buf_len, char *buf_string) };
+%apply (GIntBig *optional_GIntBig) { (GIntBig*) };
 %apply (int *optional_int) { (int*) };
 %apply (int *optional_int) { (GDALDataType *buf_type) };
 %apply (int nList, int *pList ) { (int band_list, int *pband_list ) };
@@ -482,7 +473,7 @@ public:
                       int *buf_xsize = 0, int *buf_ysize = 0,
                       GDALDataType *buf_type = 0,
                       int band_list = 0, int *pband_list = 0,
-                      int* buf_pixel_space = 0, int* buf_line_space = 0, int* buf_band_space = 0) {
+                      GIntBig* buf_pixel_space = 0, GIntBig* buf_line_space = 0, GIntBig* buf_band_space = 0) {
     CPLErr eErr;
     int nxsize = (buf_xsize==0) ? xsize : *buf_xsize;
     int nysize = (buf_ysize==0) ? ysize : *buf_ysize;
@@ -496,9 +487,9 @@ public:
       ntype = GDALGetRasterDataType( GDALGetRasterBand( self, lastband ) );
     }
 
-    int pixel_space = (buf_pixel_space == 0) ? 0 : *buf_pixel_space;
-    int line_space = (buf_line_space == 0) ? 0 : *buf_line_space;
-    int band_space = (buf_band_space == 0) ? 0 : *buf_band_space;
+    GIntBig pixel_space = (buf_pixel_space == 0) ? 0 : *buf_pixel_space;
+    GIntBig line_space = (buf_line_space == 0) ? 0 : *buf_line_space;
+    GIntBig band_space = (buf_band_space == 0) ? 0 : *buf_band_space;
 
     GIntBig min_buffer_size =
       ComputeDatasetRasterIOSize (nxsize, nysize, GDALGetDataTypeSize( ntype ) / 8,
@@ -513,82 +504,34 @@ public:
         return CE_Failure;
     }
 
-    eErr = GDALDatasetRasterIO( self, GF_Write, xoff, yoff, xsize, ysize,
-                                (void*) buf_string, nxsize, nysize, ntype,
-                                band_list, pband_list, pixel_space, line_space, band_space );
-
-    return eErr;
-  }
-%clear (int band_list, int *pband_list );
-%clear (GDALDataType *buf_type);
-%clear (int*);
-%clear (GIntBig buf_len, char *buf_string);
-#elif !defined(SWIGCSHARP) && !defined(SWIGJAVA)
-%feature("kwargs") WriteRaster;
-%apply (int nLen, char *pBuf) { (int buf_len, char *buf_string) };
-%apply (int *optional_int) { (int*) };
-%apply (int *optional_int) { (GDALDataType *buf_type) };
-%apply (int nList, int *pList ) { (int band_list, int *pband_list ) };
-  CPLErr WriteRaster( int xoff, int yoff, int xsize, int ysize,
-                      int buf_len, char *buf_string,
-                      int *buf_xsize = 0, int *buf_ysize = 0,
-                      GDALDataType *buf_type = 0,
-                      int band_list = 0, int *pband_list = 0,
-                      int* buf_pixel_space = 0, int* buf_line_space = 0, int* buf_band_space = 0) {
-    CPLErr eErr;
-    int nxsize = (buf_xsize==0) ? xsize : *buf_xsize;
-    int nysize = (buf_ysize==0) ? ysize : *buf_ysize;
-    GDALDataType ntype;
-    if ( buf_type != 0 ) {
-      ntype = (GDALDataType) *buf_type;
-    } else {
-      int lastband = GDALGetRasterCount( self ) - 1;
-      if (lastband < 0)
-        return CE_Failure;
-      ntype = GDALGetRasterDataType( GDALGetRasterBand( self, lastband ) );
-    }
-
-    int pixel_space = (buf_pixel_space == 0) ? 0 : *buf_pixel_space;
-    int line_space = (buf_line_space == 0) ? 0 : *buf_line_space;
-    int band_space = (buf_band_space == 0) ? 0 : *buf_band_space;
+    GDALRasterIOExtraArg* psExtraArg = NULL;
 
-    GIntBig min_buffer_size =
-      ComputeDatasetRasterIOSize (nxsize, nysize, GDALGetDataTypeSize( ntype ) / 8,
-                                  band_list ? band_list : GDALGetRasterCount(self), pband_list, band_list,
-                                  pixel_space, line_space, band_space, FALSE);
-    if (min_buffer_size == 0)
-        return CE_Failure;
-
-    if ( buf_len < min_buffer_size )
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
-        return CE_Failure;
-    }
-  
-    eErr = GDALDatasetRasterIO( self, GF_Write, xoff, yoff, xsize, ysize,
-                                (void*) buf_string, nxsize, nysize, ntype,
-                                band_list, pband_list, pixel_space, line_space, band_space );
+    eErr = GDALDatasetRasterIOEx( self, GF_Write, xoff, yoff, xsize, ysize,
+                                  (void*) buf_string, nxsize, nysize, ntype,
+                                  band_list, pband_list, pixel_space, line_space, band_space, psExtraArg );
 
     return eErr;
   }
 %clear (int band_list, int *pband_list );
 %clear (GDALDataType *buf_type);
 %clear (int*);
-%clear (int buf_len, char *buf_string);
+%clear (GIntBig*);
+%clear (GIntBig buf_len, char *buf_string);
 #endif
 
-#if !defined(SWIGCSHARP) && !defined(SWIGJAVA) && !defined(SWIGPYTHON)
+#if defined(SWIGPERL)
 %feature("kwargs") ReadRaster;
 %apply (int *optional_int) { (GDALDataType *buf_type) };
 %apply (int nList, int *pList ) { (int band_list, int *pband_list ) };
-%apply ( int *nLen, char **pBuf ) { (int *buf_len, char **buf ) };
-%apply ( int *optional_int ) {(int*)};                            
+%apply (GIntBig *nLen, char **pBuf) { (GIntBig *buf_len, char **buf) };
+%apply ( int *optional_int ) {(int*)};
+%apply ( GIntBig *optional_GIntBig ) {(GIntBig*)};
 CPLErr ReadRaster(  int xoff, int yoff, int xsize, int ysize,
-	              int *buf_len, char **buf,
+	              GIntBig *buf_len, char **buf,
                       int *buf_xsize = 0, int *buf_ysize = 0,
                       GDALDataType *buf_type = 0,
                       int band_list = 0, int *pband_list = 0,
-                      int* buf_pixel_space = 0, int* buf_line_space = 0, int* buf_band_space = 0,
+                      GIntBig* buf_pixel_space = 0, GIntBig* buf_line_space = 0, GIntBig* buf_band_space = 0,
                       GDALRIOResampleAlg resample_alg = GRIORA_NearestNeighbour,
                       GDALProgressFunc callback = NULL,
                       void* callback_data=NULL )
@@ -615,20 +558,21 @@ CPLErr ReadRaster(  int xoff, int yoff, int xsize, int ysize,
     GIntBig pixel_space = (buf_pixel_space == 0) ? 0 : *buf_pixel_space;
     GIntBig line_space = (buf_line_space == 0) ? 0 : *buf_line_space;
     GIntBig band_space = (buf_band_space == 0) ? 0 : *buf_band_space;
-                            
+
     eErr = DSReadRaster_internal( self, xoff, yoff, xsize, ysize,
                                 nxsize, nysize, ntype,
-                                buf_len, buf, 
+                                buf_len, buf,
                                 band_list, pband_list,
                                 pixel_space, line_space, band_space, &sExtraArg);
 
     return eErr;
 }
-  
+
 %clear (GDALDataType *buf_type);
 %clear (int band_list, int *pband_list );
 %clear (int *buf_len, char **buf );
 %clear (int*);
+%clear (GIntBig*);
 #endif
 
 
@@ -638,13 +582,13 @@ CPLErr ReadRaster(  int xoff, int yoff, int xsize, int ysize,
 /* AddBand */
 /* AdviseRead */
 /* ReadRaster */
-  
+
 #if defined(SWIGPYTHON)
 %feature("kwargs") BeginAsyncReader;
 %newobject BeginAsyncReader;
 %apply (int nList, int *pList ) { (int band_list, int *pband_list ) };
 %apply (int nLenKeepObject, char *pBufKeepObject, void* pyObject) { (int buf_len, char *buf_string, void* pyObject) };
-%apply (int *optional_int) { (int*) };  
+%apply (int *optional_int) { (int*) };
   GDALAsyncReaderShadow* BeginAsyncReader(
        int xOff, int yOff, int xSize, int ySize,
        int buf_len, char *buf_string, void* pyObject,
@@ -660,23 +604,30 @@ CPLErr ReadRaster(  int xoff, int yoff, int xsize, int ysize,
         {
             // round up
             int nLevel = atoi(pszLevel);
-            int nRes = 2 << (nLevel - 1);
-            buf_xsize = ceil(xSize / (1.0 * nRes));
-            buf_ysize = ceil(ySize / (1.0 * nRes));
+            if( nLevel < 0 || nLevel > 30 )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "Invalid LEVEL: %d", nLevel);
+            }
+            else
+            {
+                int nRes = 1 << nLevel;
+                buf_xsize = ceil(xSize / (1.0 * nRes));
+                buf_ysize = ceil(ySize / (1.0 * nRes));
+            }
         }
     }
-    
+
     int nxsize = (buf_xsize == 0) ? xSize : buf_xsize;
     int nysize = (buf_ysize == 0) ? ySize : buf_ysize;
-    
+
     GDALDataType ntype;
     if (bufType != 0) {
         ntype = (GDALDataType) bufType;
-    } 
+    }
     else {
         ntype = GDT_Byte;
     }
-    
+
     int nBCount = (band_list) != 0 ? band_list : GDALGetRasterCount(self);
     int nMinSize = nxsize * nysize * nBCount * (GDALGetDataTypeSize(ntype) / 8);
     if (buf_string == NULL || buf_len < nMinSize)
@@ -684,14 +635,14 @@ CPLErr ReadRaster(  int xoff, int yoff, int xsize, int ysize,
         CPLError(CE_Failure, CPLE_AppDefined, "Buffer is too small");
         return NULL;
     }
-    
+
     bool myBandList = false;
     int* pBandList;
-    
+
     if (band_list != 0){
         myBandList = false;
         pBandList = pband_list;
-    }        
+    }
     else
     {
         myBandList = true;
@@ -704,6 +655,11 @@ CPLErr ReadRaster(  int xoff, int yoff, int xsize, int ysize,
     GDALAsyncReaderH hAsyncReader =
             GDALBeginAsyncReader(self, xOff, yOff, xSize, ySize, (void*) buf_string, nxsize, nysize, ntype, nBCount, pBandList, nPixelSpace, nLineSpace,
     nBandSpace, options);
+
+    if ( myBandList ) {
+       CPLFree( pBandList );
+    }
+
     if (hAsyncReader)
     {
         return (GDALAsyncReader*) CreateAsyncReaderWrapper(hAsyncReader, pyObject);
@@ -712,10 +668,6 @@ CPLErr ReadRaster(  int xoff, int yoff, int xsize, int ysize,
     {
         return NULL;
     }
-    
-    if ( myBandList ) {
-       CPLFree( pBandList );
-    }
 
   }
 
@@ -837,13 +789,13 @@ CPLErr ReadRaster(  int xoff, int yoff, int xsize, int ysize,
 
 #endif /* PYTHON */
 
-#if defined(SWIGPYTHON) || defined(SWIGJAVA)
+#if defined(SWIGPYTHON) || defined(SWIGJAVA) || defined(SWIGPERL)
 
   /* Note that datasources own their layers */
 #ifndef SWIGJAVA
   %feature( "kwargs" ) CreateLayer;
 #endif
-  OGRLayerShadow *CreateLayer(const char* name, 
+  OGRLayerShadow *CreateLayer(const char* name,
               OSRSpatialReferenceShadow* srs=NULL,
               OGRwkbGeometryType geom_type=wkbUnknown,
               char** options=0) {
@@ -908,13 +860,13 @@ CPLErr ReadRaster(  int xoff, int yoff, int xsize, int ysize,
                                                       dialect);
     return layer;
   }
-  
+
 %apply SWIGTYPE *DISOWN {OGRLayerShadow *layer};
   void ReleaseResultSet(OGRLayerShadow *layer){
     GDALDatasetReleaseResultSet(self, layer);
   }
 %clear OGRLayerShadow *layer;
-  
+
   OGRStyleTableShadow *GetStyleTable() {
     return (OGRStyleTableShadow*) GDALDatasetGetStyleTable(self);
   }
@@ -924,7 +876,7 @@ CPLErr ReadRaster(  int xoff, int yoff, int xsize, int ysize,
         GDALDatasetSetStyleTable(self, (OGRStyleTableH) table);
   }
 
-#endif /* defined(SWIGPYTHON) || defined(SWIGJAVA) */
+#endif /* defined(SWIGPYTHON) || defined(SWIGJAVA) || defined(SWIGPERL) */
 
 #ifndef SWIGJAVA
   %feature( "kwargs" ) StartTransaction;
diff --git a/swig/include/Driver.i b/swig/include/Driver.i
index f1f69bc..49cd1b6 100644
--- a/swig/include/Driver.i
+++ b/swig/include/Driver.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: Driver.i 28721 2015-03-12 15:28:20Z ajolma $
+ * $Id: Driver.i 32864 2016-01-08 21:00:50Z goatbar $
  *
  * Name:     Driver.i
  * Project:  GDAL Python Interface
@@ -57,19 +57,19 @@ public:
 #ifndef SWIGJAVA
 %feature( "kwargs" ) Create;
 #endif
-  GDALDatasetShadow *Create(    const char *utf8_path, 
-                                int xsize, 
-                                int ysize, 
+  GDALDatasetShadow *Create(    const char *utf8_path,
+                                int xsize,
+                                int ysize,
                                 int bands = 1,
-                                GDALDataType eType=GDT_Byte, 
+                                GDALDataType eType=GDT_Byte,
                                 char **options = 0 ) {
 
-    GDALDatasetShadow* ds = (GDALDatasetShadow*) GDALCreate(    self, 
-                                                                utf8_path, 
-                                                                xsize, 
-                                                                ysize, 
-                                                                bands, 
-                                                                eType, 
+    GDALDatasetShadow* ds = (GDALDatasetShadow*) GDALCreate(    self,
+                                                                utf8_path,
+                                                                xsize,
+                                                                ysize,
+                                                                bands,
+                                                                eType,
                                                                 options );
     return ds;
   }
@@ -80,19 +80,19 @@ public:
 %feature( "kwargs" ) CreateCopy;
 #endif
 #endif
-  GDALDatasetShadow *CreateCopy(    const char *utf8_path, 
-                                    GDALDatasetShadow* src, 
-                                    int strict = 1, 
-                                    char **options = 0, 
+  GDALDatasetShadow *CreateCopy(    const char *utf8_path,
+                                    GDALDatasetShadow* src,
+                                    int strict = 1,
+                                    char **options = 0,
                                     GDALProgressFunc callback = NULL,
                                     void* callback_data=NULL) {
 
-    GDALDatasetShadow *ds = (GDALDatasetShadow*) GDALCreateCopy(    self, 
-                                                                    utf8_path, 
-                                                                    src, 
-                                                                    strict, 
-                                                                    options, 
-                                                                    callback, 
+    GDALDatasetShadow *ds = (GDALDatasetShadow*) GDALCreateCopy(    self,
+                                                                    utf8_path,
+                                                                    src,
+                                                                    strict,
+                                                                    options,
+                                                                    callback,
                                                                     callback_data );
     return ds;
   }
diff --git a/swig/include/MajorObject.i b/swig/include/MajorObject.i
index a0f0be8..8517182 100644
--- a/swig/include/MajorObject.i
+++ b/swig/include/MajorObject.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: MajorObject.i 28360 2015-01-27 09:27:05Z rouault $
+ * $Id: MajorObject.i 32864 2016-01-08 21:00:50Z goatbar $
  *
  * Project:  GDAL SWIG Interfaces.
  * Purpose:  SWIG Definitions for GDALMajorObject.
@@ -28,7 +28,7 @@
  *****************************************************************************/
 
 /* For Python we don't import, but include MajorObject.i to avoid */
-/* cyclic dependency betwenn gdal.py and ogr.py. Python2 is fine with that */
+/* cyclic dependency between gdal.py and ogr.py. Python2 is fine with that */
 /* but Python3 not */
 /* We should probably define a new module for MajorObject, or merge gdal and ogr */
 /* modules */
@@ -92,7 +92,7 @@ public:
 /*
  * SetMetadata methods
  */
- 
+
 #ifdef SWIGJAVA
 %apply (char **options) { char ** papszMetadata };
   CPLErr SetMetadata( char ** papszMetadata, const char * pszDomain = "" ) {
diff --git a/swig/include/Operations.i b/swig/include/Operations.i
index b7776fa..17ce7dc 100644
--- a/swig/include/Operations.i
+++ b/swig/include/Operations.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: Operations.i 28730 2015-03-14 14:24:15Z ajolma $
+ * $Id: Operations.i 33447 2016-02-12 20:59:51Z goatbar $
  *
  * Name:     Operations.i
  * Project:  GDAL Python Interface
@@ -31,7 +31,7 @@
 %{
 #include "gdalgrid.h"
 
-#ifdef DEBUG 
+#ifdef DEBUG
 typedef struct OGRLayerHS OGRLayerShadow;
 typedef struct OGRGeometryHS OGRGeometryShadow;
 #else
@@ -48,7 +48,8 @@ typedef void OGRGeometryShadow;
 %rename (TermProgress_nocb) GDALTermProgress_nocb;
 %feature( "kwargs" ) GDALTermProgress_nocb;
 %inline %{
-int GDALTermProgress_nocb( double dfProgress, const char * pszMessage=NULL, void *pData=NULL ) {
+static int
+GDALTermProgress_nocb( double dfProgress, const char * pszMessage=NULL, void *pData=NULL ) {
   return GDALTermProgress( dfProgress, pszMessage, pData);
 }
 %}
@@ -59,7 +60,6 @@ int GDALTermProgress( double, const char *, void * );
 %nocallback;
 #endif
 
-
 /************************************************************************/
 /*                        ComputeMedianCutPCT()                         */
 /************************************************************************/
@@ -86,10 +86,10 @@ int  ComputeMedianCutPCT ( GDALRasterBandShadow *red,
                                           colors,
                                           callback,
                                           callback_data);
-    
+
     return err;
 }
-%} 
+%}
 
 /************************************************************************/
 /*                           DitherRGB2PCT()                            */
@@ -115,7 +115,7 @@ int  DitherRGB2PCT ( GDALRasterBandShadow *red,
                                   colors,
                                   callback,
                                   callback_data);
-    
+
     return err;
 }
 %}
@@ -125,6 +125,9 @@ int  DitherRGB2PCT ( GDALRasterBandShadow *red,
 /*                           ReprojectImage()                           */
 /************************************************************************/
 %apply Pointer NONNULL {GDALDatasetShadow *src_ds, GDALDatasetShadow *dst_ds};
+#ifndef SWIGJAVA
+%feature( "kwargs" ) ReprojectImage;
+#endif
 %inline %{
 CPLErr  ReprojectImage ( GDALDatasetShadow *src_ds,
                          GDALDatasetShadow *dst_ds,
@@ -134,10 +137,18 @@ CPLErr  ReprojectImage ( GDALDatasetShadow *src_ds,
                          double WarpMemoryLimit=0.0,
                          double maxerror = 0.0,
 			 GDALProgressFunc callback = NULL,
-                     	 void* callback_data=NULL) {
+                     	 void* callback_data=NULL,
+                         char** options = NULL ) {
 
     CPLErrorReset();
 
+    GDALWarpOptions* psOptions = NULL;
+    if( options != NULL )
+    {
+        psOptions = GDALCreateWarpOptions();
+        psOptions->papszWarpOptions = CSLDuplicate(options);
+    }
+
     CPLErr err = GDALReprojectImage( src_ds,
                                      src_wkt,
                                      dst_ds,
@@ -147,11 +158,14 @@ CPLErr  ReprojectImage ( GDALDatasetShadow *src_ds,
                                      maxerror,
                                      callback,
                                      callback_data,
-                                     NULL);
-    
+                                     psOptions);
+
+    if( psOptions != NULL )
+        GDALDestroyWarpOptions(psOptions);
+
     return err;
 }
-%} 
+%}
 %clear GDALDatasetShadow *src_ds, GDALDatasetShadow *dst_ds;
 
 /************************************************************************/
@@ -173,7 +187,7 @@ int  ComputeProximity( GDALRasterBandShadow *srcBand,
     return GDALComputeProximity( srcBand, proximityBand, options,
                                  callback, callback_data );
 }
-%} 
+%}
 %clear GDALRasterBandShadow *srcBand, GDALRasterBandShadow *proximityBand;
 
 /************************************************************************/
@@ -189,7 +203,7 @@ int  ComputeProximity( GDALRasterBandShadow *srcBand,
 int  RasterizeLayer( GDALDatasetShadow *dataset,
                  int bands, int *band_list,
                  OGRLayerShadow *layer,
-		 int burn_values = 0, double *burn_values_list = NULL, 
+		 int burn_values = 0, double *burn_values_list = NULL,
                  char **options = NULL,
                  GDALProgressFunc callback=NULL,
                  void* callback_data=NULL) {
@@ -206,15 +220,15 @@ int  RasterizeLayer( GDALDatasetShadow *dataset,
     }
     else if( burn_values != bands )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Did not get the expected number of burn values in RasterizeLayer()" );
         return CE_Failure;
     }
 
     eErr = GDALRasterizeLayers( dataset, bands, band_list,
-                                1, &layer, 
+                                1, &layer,
                                 NULL, NULL,
-                                burn_values_list, options, 
+                                burn_values_list, options,
                                 callback, callback_data );
 
     if( burn_values == 0 )
@@ -222,7 +236,7 @@ int  RasterizeLayer( GDALDatasetShadow *dataset,
 
     return eErr;
 }
-%} 
+%}
 #else
 %feature( "kwargs" ) RasterizeLayer;
 %apply (int nList, int *pList ) { (int bands, int *band_list ) };
@@ -232,8 +246,8 @@ int  RasterizeLayer( GDALDatasetShadow *dataset,
                  int bands, int *band_list,
                  OGRLayerShadow *layer,
                  void *pfnTransformer = NULL,
-                 void *pTransformArg = NULL, 
-		 int burn_values = 0, double *burn_values_list = NULL, 
+                 void *pTransformArg = NULL,
+		 int burn_values = 0, double *burn_values_list = NULL,
                  char **options = NULL,
                  GDALProgressFunc callback=NULL,
                  void* callback_data=NULL) {
@@ -250,16 +264,16 @@ int  RasterizeLayer( GDALDatasetShadow *dataset,
     }
     else if( burn_values != bands )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Did not get the expected number of burn values in RasterizeLayer()" );
         return CE_Failure;
     }
 
     eErr = GDALRasterizeLayers( dataset, bands, band_list,
-                                1, &layer, 
-                                (GDALTransformerFunc) pfnTransformer, 
+                                1, &layer,
+                                (GDALTransformerFunc) pfnTransformer,
                                 pTransformArg,
-                                burn_values_list, options, 
+                                burn_values_list, options,
                                 callback, callback_data );
 
     if( burn_values == 0 )
@@ -267,7 +281,7 @@ int  RasterizeLayer( GDALDatasetShadow *dataset,
 
     return eErr;
 }
-%} 
+%}
 #endif
 
 /************************************************************************/
@@ -281,7 +295,7 @@ int  RasterizeLayer( GDALDatasetShadow *dataset,
 %inline %{
 int  Polygonize( GDALRasterBandShadow *srcBand,
      		 GDALRasterBandShadow *maskBand,
-  	         OGRLayerShadow *outLayer, 
+  	         OGRLayerShadow *outLayer,
                  int iPixValField,
                  char **options = NULL,
                  GDALProgressFunc callback=NULL,
@@ -292,7 +306,27 @@ int  Polygonize( GDALRasterBandShadow *srcBand,
     return GDALPolygonize( srcBand, maskBand, outLayer, iPixValField,
                            options, callback, callback_data );
 }
-%} 
+%}
+
+#ifndef SWIGJAVA
+%feature( "kwargs" ) FPolygonize;
+#endif
+%inline %{
+int  FPolygonize( GDALRasterBandShadow *srcBand,
+                 GDALRasterBandShadow *maskBand,
+                 OGRLayerShadow *outLayer,
+                 int iPixValField,
+                 char **options = NULL,
+                 GDALProgressFunc callback=NULL,
+                 void* callback_data=NULL) {
+
+    CPLErrorReset();
+
+    return GDALFPolygonize( srcBand, maskBand, outLayer, iPixValField,
+                           options, callback, callback_data );
+}
+%}
+
 %clear GDALRasterBandShadow *srcBand, OGRLayerShadow *outLayer;
 
 /************************************************************************/
@@ -315,11 +349,11 @@ int  FillNodata( GDALRasterBandShadow *targetBand,
 
     CPLErrorReset();
 
-    return GDALFillNodata( targetBand, maskBand, maxSearchDist, 
-    	   		   0, smoothingIterations, options, 
+    return GDALFillNodata( targetBand, maskBand, maxSearchDist,
+    	   		   0, smoothingIterations, options,
 			   callback, callback_data );
 }
-%} 
+%}
 %clear GDALRasterBandShadow *targetBand;
 
 /************************************************************************/
@@ -341,11 +375,11 @@ int  SieveFilter( GDALRasterBandShadow *srcBand,
 
     CPLErrorReset();
 
-    return GDALSieveFilter( srcBand, maskBand, dstBand, 
+    return GDALSieveFilter( srcBand, maskBand, dstBand,
                             threshold, connectedness,
                             options, callback, callback_data );
 }
-%} 
+%}
 %clear GDALRasterBandShadow *srcBand, GDALRasterBandShadow *dstBand;
 
 /************************************************************************/
@@ -442,7 +476,7 @@ int wrapper_GridCreate( char* algorithmOptions,
     {
         eErr = ParseAlgorithmAndOptions( szAlgNameInvDist, &eAlgorithm, &pOptions );
     }
-    
+
     if ( eErr != CE_None )
     {
         CPLError( eErr, CPLE_AppDefined, "Failed to process algorithm name and parameters.\n" );
@@ -478,7 +512,7 @@ int ContourGenerate( GDALRasterBandShadow *srcBand,
                      double *fixedLevels,
                      int useNoData,
                      double noDataValue,
-                     OGRLayerShadow* dstLayer, 
+                     OGRLayerShadow* dstLayer,
                      int idField,
                      int elevField,
                      GDALProgressFunc callback = NULL,
@@ -529,12 +563,36 @@ GDALDatasetShadow *AutoCreateWarpedVRT( GDALDatasetShadow *src_ds,
     /*throw CPLGetLastErrorMsg(); causes a SWIG_exception later*/
   }
   return ds;
-  
+
 }
 %}
 %clear GDALDatasetShadow *src_ds;
 
 /************************************************************************/
+/*                        CreatePansharpenedVRT()                       */
+/************************************************************************/
+
+%newobject CreatePansharpenedVRT;
+#ifndef SWIGCSHARP
+%apply (int object_list_count, GDALRasterBandShadow **poObjects) {(int nInputSpectralBands, GDALRasterBandShadow **ahInputSpectralBands)};
+#endif /* SWIGCSHARP */
+%apply Pointer NONNULL { GDALRasterBandShadow* panchroBand };
+
+%inline %{
+GDALDatasetShadow*  CreatePansharpenedVRT( const char* pszXML,
+                            GDALRasterBandShadow* panchroBand,
+                            int nInputSpectralBands,
+                            GDALRasterBandShadow** ahInputSpectralBands )
+{
+    CPLErrorReset();
+
+    return (GDALDatasetShadow*)GDALCreatePansharpenedVRT( pszXML, panchroBand,
+                                      nInputSpectralBands, ahInputSpectralBands );
+}
+%}
+%clear GDALRasterBandShadow* panchroBand;
+
+/************************************************************************/
 /*                             Transformer                              */
 /************************************************************************/
 
@@ -547,8 +605,8 @@ public:
 
   GDALTransformerInfoShadow( GDALDatasetShadow *src, GDALDatasetShadow *dst,
                              char **options ) {
-    GDALTransformerInfoShadow *obj = (GDALTransformerInfoShadow*) 
-       GDALCreateGenImgProjTransformer2( (GDALDatasetH)src, (GDALDatasetH)dst, 
+    GDALTransformerInfoShadow *obj = (GDALTransformerInfoShadow*)
+       GDALCreateGenImgProjTransformer2( (GDALDatasetH)src, (GDALDatasetH)dst,
                                          options );
     return obj;
   }
@@ -568,23 +626,23 @@ public:
   int TransformPoint( int bDstToSrc, double inout[3] ) {
     int nRet, nSuccess = TRUE;
 
-    nRet = GDALUseTransformer( self, bDstToSrc, 
-                               1, &inout[0], &inout[1], &inout[2], 
+    nRet = GDALUseTransformer( self, bDstToSrc,
+                               1, &inout[0], &inout[1], &inout[2],
                                &nSuccess );
 
     return nRet && nSuccess;
   }
 %clear (double inout[3]);
 
-  int TransformPoint( double argout[3], int bDstToSrc, 
+  int TransformPoint( double argout[3], int bDstToSrc,
                       double x, double y, double z = 0.0 ) {
     int nRet, nSuccess = TRUE;
-    
+
     argout[0] = x;
     argout[1] = y;
     argout[2] = z;
-    nRet = GDALUseTransformer( self, bDstToSrc, 
-                               1, &argout[0], &argout[1], &argout[2], 
+    nRet = GDALUseTransformer( self, bDstToSrc,
+                               1, &argout[0], &argout[1], &argout[2],
                                &nSuccess );
 
     return nRet && nSuccess;
@@ -594,7 +652,7 @@ public:
   %apply (double *inout) {(double*)};
   %apply (double *inout) {(int*)};
 #endif
-  int TransformPoints( int bDstToSrc, 
+  int TransformPoints( int bDstToSrc,
                        int nCount, double *x, double *y, double *z,
                        int *panSuccess ) {
     int nRet;
@@ -619,7 +677,7 @@ public:
 #endif
 
   int  TransformGeolocations( GDALRasterBandShadow *xBand,
-                              GDALRasterBandShadow *yBand, 
+                              GDALRasterBandShadow *yBand,
 	  		      GDALRasterBandShadow *zBand,
                               GDALProgressFunc callback=NULL,
                               void* callback_data=NULL,
@@ -627,7 +685,7 @@ public:
 
     CPLErrorReset();
 
-    return GDALTransformGeolocations( xBand, yBand, zBand, 
+    return GDALTransformGeolocations( xBand, yBand, zBand,
                                       GDALUseTransformer, self,
                             	      callback, callback_data, options );
   }
diff --git a/swig/include/README.typemaps b/swig/include/README.typemaps
index cc1e7ea..d66310b 100644
--- a/swig/include/README.typemaps
+++ b/swig/include/README.typemaps
@@ -54,13 +54,17 @@ in (int *optional_int) - Required -
 in (int nGCPs, GDAL_GCP const *pGCPs) -
   Pass a fixed length array of GCP pointers into a function.
 
-in (int nList, int *pList) - Required - Pass a fixed length integer array into a function.
+in (int nList, int *pList) - Required - Pass a fixed length integer
+array into a function.
 
-in (int nLen, char *pBuf) - Required - Pass a fixed length character buffer into a function.
+in (int nLen, char *pBuf) - Required - Pass a fixed length character
+buffer into a function.
 
-in (tostring argin ) - Required - Converts any argument in the script types to a string representation.
-In python this functionality directly calls AsString (ie str()) on the object.  This functionality
-could be reduced in other languages as long as it's documented.
+in (tostring argin ) - Required - Converts any argument in the script
+types to a string representation.  In python, this functionality
+directly calls AsString (i.e. str()) on the object.  This
+functionality could be reduced in other languages as long as it's
+documented.
 
 in (const char *utf8_path) - Optional - 
   Any inputs marked this way should be treated as utf-8, and if the language supports it
@@ -74,7 +78,7 @@ converted into a native dictionary or hash structure.  Use CPLParseNameValue() t
 access the char ** type.
 
 out (CPLErr) - CPLErr is an enum defined in port/cpl_error.h.  This code is returned
-by many functions in GDAL core.  Suggested useage is to test the return code an convert
+by many functions in GDAL core.  Suggested usage is to test the return code an convert
 to an exception.
 
 out GDALColorEntry* - Return a GDALColorEntry from a function.
diff --git a/swig/include/RasterAttributeTable.i b/swig/include/RasterAttributeTable.i
index a1c5acd..2104d2b 100644
--- a/swig/include/RasterAttributeTable.i
+++ b/swig/include/RasterAttributeTable.i
@@ -39,14 +39,14 @@ typedef int GDALRATFieldUsage;
 #else
 %rename (RATFieldType) GDALRATFieldType;
 typedef enum {
-    /*! Integer field */	   	   GFT_Integer , 
+    /*! Integer field */	   	   GFT_Integer ,
     /*! Floating point (double) field */   GFT_Real,
     /*! String field */                    GFT_String
 } GDALRATFieldType;
 
 %rename (RATFieldUsage) GDALRATFieldUsage;
 typedef enum {
-    /*! General purpose field. */          GFU_Generic = 0,  
+    /*! General purpose field. */          GFU_Generic = 0,
     /*! Histogram pixel count */           GFU_PixelCount = 1,
     /*! Class name */                      GFU_Name = 2,
     /*! Class range minimum */             GFU_Min = 3,
@@ -78,24 +78,24 @@ public:
 %extend {
 
     GDALRasterAttributeTableShadow() {
-        return (GDALRasterAttributeTableShadow*) 
+        return (GDALRasterAttributeTableShadow*)
 		GDALCreateRasterAttributeTable();
     }
 
     ~GDALRasterAttributeTableShadow() {
         GDALDestroyRasterAttributeTable(self);
     }
-  
+
     %newobject Clone();
     GDALRasterAttributeTableShadow* Clone() {
         return (GDALRasterAttributeTableShadow*) GDALRATClone(self);
     }
-  
-    int GetColumnCount() { 
+
+    int GetColumnCount() {
         return GDALRATGetColumnCount( self );
     }
 
-    const char *GetNameOfCol(int iCol) { 
+    const char *GetNameOfCol(int iCol) {
         return GDALRATGetNameOfCol( self, iCol );
     }
 
@@ -110,34 +110,34 @@ public:
     int GetColOfUsage( GDALRATFieldUsage eUsage ) {
         return GDALRATGetColOfUsage( self, eUsage );
     }
-   
-    int GetRowCount() { 
+
+    int GetRowCount() {
         return GDALRATGetRowCount( self );
     }
 
-    const char *GetValueAsString( int iRow, int iCol ) { 
+    const char *GetValueAsString( int iRow, int iCol ) {
         return GDALRATGetValueAsString( self, iRow, iCol );
     }
 
-    int GetValueAsInt( int iRow, int iCol ) { 
+    int GetValueAsInt( int iRow, int iCol ) {
         return GDALRATGetValueAsInt( self, iRow, iCol );
     }
 
-    double GetValueAsDouble( int iRow, int iCol ) { 
+    double GetValueAsDouble( int iRow, int iCol ) {
         return GDALRATGetValueAsDouble( self, iRow, iCol );
     }
 
     %apply ( tostring argin ) { (const char* pszValue) };
-    void SetValueAsString( int iRow, int iCol, const char *pszValue ) { 
+    void SetValueAsString( int iRow, int iCol, const char *pszValue ) {
         GDALRATSetValueAsString( self, iRow, iCol, pszValue );
     }
     %clear (const char* pszValue );
 
-    void SetValueAsInt( int iRow, int iCol, int nValue ) { 
+    void SetValueAsInt( int iRow, int iCol, int nValue ) {
         GDALRATSetValueAsInt( self, iRow, iCol, nValue );
     }
 
-    void SetValueAsDouble( int iRow, int iCol, double dfValue ) { 
+    void SetValueAsDouble( int iRow, int iCol, double dfValue ) {
         GDALRATSetValueAsDouble( self, iRow, iCol, dfValue );
     }
 
@@ -145,7 +145,7 @@ public:
         GDALRATSetRowCount( self, nCount );
     }
 
-    int CreateColumn( const char *pszName, GDALRATFieldType eType, 
+    int CreateColumn( const char *pszName, GDALRATFieldType eType,
                       GDALRATFieldUsage eUsage ) {
         return GDALRATCreateColumn( self, pszName, eType, eUsage );
     }
diff --git a/swig/include/Transform.i b/swig/include/Transform.i
index 9cf0d14..a687217 100644
--- a/swig/include/Transform.i
+++ b/swig/include/Transform.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: Transform.i 10967 2007-03-15 20:04:37Z warmerdam $
+ * $Id: Transform.i 32864 2016-01-08 21:00:50Z goatbar $
  *
  * Project:  GDAL SWIG Interfaces.
  * Purpose:  GDAL transformer related declarations.
@@ -29,7 +29,7 @@
 
 void *GDALCreateGCPTransformer( int nGCPs, GDAL_GCP const * pGCPs,
                                      int nOrder, int bApproxOK);
- 
+
 int GDALGCPTransform    (
         void *pTransformArg,
         int     bDstToSrc,
@@ -39,5 +39,5 @@ int GDALGCPTransform    (
         double *    z,
         int *   optional_int
     );
- 
-void GDALDestroyGCPTransformer (void *pTransformArg);
\ No newline at end of file
+
+void GDALDestroyGCPTransformer (void *pTransformArg);
diff --git a/swig/include/XMLNode.i b/swig/include/XMLNode.i
index 0e2b67e..3ab41ad 100644
--- a/swig/include/XMLNode.i
+++ b/swig/include/XMLNode.i
@@ -1,9 +1,9 @@
 /******************************************************************************
- * $Id: XMLNode.i 24439 2012-05-17 21:54:16Z rouault $
+ * $Id: XMLNode.i 32864 2016-01-08 21:00:50Z goatbar $
  *
  * Project:  GDAL SWIG Interface
  * Purpose:  GDAL XML SWIG Interface declarations.
- * Author:   Tamas Szekeres (szekerest at gmeil.com)
+ * Author:   Tamas Szekeres (szekerest at gmail.com)
  *
  ******************************************************************************
  * Copyright (c) 2005, Tamas Szekeres
@@ -28,13 +28,13 @@
  *****************************************************************************/
 
 %rename (XMLNodeType) CPLXMLNodeType;
-typedef enum 
+typedef enum
 {
     CXT_Element = 0,
     CXT_Text = 1,
-    CXT_Attribute = 2,  
-    CXT_Comment = 3,    
-    CXT_Literal = 4     
+    CXT_Attribute = 2,
+    CXT_Comment = 3,
+    CXT_Literal = 4
 } CPLXMLNodeType;
 
 %rename (XMLNode) CPLXMLNode;
@@ -45,18 +45,18 @@ typedef enum
 typedef struct CPLXMLNode
 {
 %immutable;
-    CPLXMLNodeType      eType;       
-    char                *pszValue;   
+    CPLXMLNodeType      eType;
+    char                *pszValue;
     struct CPLXMLNode *psNext;
     struct CPLXMLNode *psChild;
-%mutable;  
+%mutable;
 } CPLXMLNode;
 
-%extend CPLXMLNode 
+%extend CPLXMLNode
 {
-    CPLXMLNode(const char *pszString) 
+    CPLXMLNode(const char *pszString)
     {
-        return CPLParseXMLString( pszString );     
+        return CPLParseXMLString( pszString );
     }
 
     /* Interface method added for GDAL 1.7.0 */
@@ -65,11 +65,11 @@ typedef struct CPLXMLNode
         return CPLCreateXMLNode(NULL, eType, pszText);
     }
 
-    ~CPLXMLNode() 
+    ~CPLXMLNode()
     {
         CPLDestroyXMLNode( self );
     }
-    
+
     /* Interface method added for GDAL 1.7.0 */
 #ifdef SWIGJAVA
     %newobject ParseXMLFile;
@@ -78,7 +78,7 @@ typedef struct CPLXMLNode
         return CPLParseXMLFile(pszFilename);
     }
 #endif
-    
+
 #if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGPERL)
     retStringAndCPLFree *SerializeXMLTree( )
 #else
@@ -95,25 +95,25 @@ typedef struct CPLXMLNode
         return CPLSerializeXMLTree( self );
     }
 #endif
-    
+
     CPLXMLNode *SearchXMLNode( const char *pszElement )
     {
         return CPLSearchXMLNode(self, pszElement);
     }
-    
+
     CPLXMLNode *GetXMLNode( const char *pszPath )
     {
         return CPLGetXMLNode( self, pszPath );
     }
-    
-    const char *GetXMLValue( const char *pszPath, 
+
+    const char *GetXMLValue( const char *pszPath,
                             const char *pszDefault )
     {
-        return CPLGetXMLValue( self, pszPath, pszDefault );                    
+        return CPLGetXMLValue( self, pszPath, pszDefault );
     }
-    
-    // for Java, I don't want to deal with ownerships issues
-    // so I just clone
+
+    // For Java, I don't want to deal with ownership issues,
+    // so I just clone.
 #ifdef SWIGJAVA
     %apply Pointer NONNULL {CPLXMLNode *psChild};
     void AddXMLChild( CPLXMLNode *psChild )
@@ -133,46 +133,46 @@ typedef struct CPLXMLNode
     {
         CPLAddXMLChild( self, psChild );
     }
-    
+
     int RemoveXMLChild( CPLXMLNode *psChild )
     {
         return CPLRemoveXMLChild( self, psChild );
     }
-    
+
     void AddXMLSibling( CPLXMLNode *psNewSibling )
     {
         CPLAddXMLSibling( self, psNewSibling );
     }
-    
-    CPLXMLNode *CreateXMLElementAndValue( const char *pszName, 
+
+    CPLXMLNode *CreateXMLElementAndValue( const char *pszName,
                                          const char *pszValue )
     {
-        return CPLCreateXMLElementAndValue( self, pszName, pszValue );                                 
+        return CPLCreateXMLElementAndValue( self, pszName, pszValue );
     }
-    
+
     %newobject CloneXMLTree;
     CPLXMLNode *CloneXMLTree( CPLXMLNode *psTree )
     {
         return CPLCloneXMLTree( psTree );
     }
 #endif
-    
+
     /* Interface method added for GDAL 1.7.0 */
     %newobject Clone;
     CPLXMLNode *Clone()
     {
         return CPLCloneXMLTree( self );
     }
-    
+
     int SetXMLValue( const char *pszPath,
                     const char *pszValue )
     {
-        return CPLSetXMLValue( self,  pszPath, pszValue );           
+        return CPLSetXMLValue( self,  pszPath, pszValue );
     }
-    
-    void StripXMLNamespace( const char *pszNamespace, 
+
+    void StripXMLNamespace( const char *pszNamespace,
                            int bRecurse )
     {
-        CPLStripXMLNamespace( self, pszNamespace, bRecurse );                  
+        CPLStripXMLNamespace( self, pszNamespace, bRecurse );
     }
 }
diff --git a/swig/include/cpl.i b/swig/include/cpl.i
index ce2e05c..8605130 100644
--- a/swig/include/cpl.i
+++ b/swig/include/cpl.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl.i 29223 2015-05-21 15:19:08Z ajolma $
+ * $Id: cpl.i 33758 2016-03-21 09:06:22Z rouault $
  *
  * Name:     cpl.i
  * Project:  GDAL Python Interface
@@ -150,7 +150,7 @@ void CPL_STDCALL PyCPLErrorHandler(CPLErr eErrClass, int err_no, const char* psz
 %rename (pop_finder_location) CPLPopFinderLocation;
 %rename (finder_clean) CPLFinderClean;
 %rename (find_file) CPLFindFile;
-%rename (read_dir) VSIReadDir;
+%rename (read_dir) wrapper_VSIReadDirEx;
 %rename (read_dir_recursive) VSIReadDirRecursive;
 %rename (mkdir) VSIMkdir;
 %rename (rmdir) VSIRmdir;
@@ -173,7 +173,7 @@ void CPL_STDCALL PyCPLErrorHandler(CPLErr eErrClass, int err_no, const char* psz
 %rename (PopFinderLocation) CPLPopFinderLocation;
 %rename (FinderClean) CPLFinderClean;
 %rename (FindFile) CPLFindFile;
-%rename (ReadDir) VSIReadDir;
+%rename (ReadDir) wrapper_VSIReadDirEx;
 %rename (ReadDirRecursive) VSIReadDirRecursive;
 %rename (Mkdir) VSIMkdir;
 %rename (Rmdir) VSIRmdir;
@@ -215,18 +215,18 @@ void CPLErrorReset();
 %inline %{
 retStringAndCPLFree* EscapeString(int len, unsigned char *bin_string , int scheme) {
     return CPLEscapeString((const char*)bin_string, len, scheme);
-} 
+}
 
 retStringAndCPLFree* EscapeString(const char* str, int scheme) {
     return CPLEscapeString(str, (str) ? strlen(str) : 0, scheme);
-} 
+}
 %}
 %clear (int len, unsigned char *bin_string);
 #elif defined(SWIGCSHARP)
 %inline %{
 retStringAndCPLFree* EscapeString(int len, char *bin_string , int scheme) {
     return CPLEscapeString((const char*)bin_string, len, scheme);
-} 
+}
 %}
 
 retStringAndCPLFree* EscapeString(int len, char *bin_string , int scheme=CPLES_SQL) {
@@ -237,7 +237,7 @@ retStringAndCPLFree* EscapeString(int len, char *bin_string , int scheme=CPLES_S
 %inline %{
 retStringAndCPLFree* EscapeString(int len, char *bin_string , int scheme=CPLES_SQL) {
     return CPLEscapeString(bin_string, len, scheme);
-} 
+}
 %}
 %clear (int len, char *bin_string);
 #else
@@ -245,7 +245,7 @@ retStringAndCPLFree* EscapeString(int len, char *bin_string , int scheme=CPLES_S
 %inline %{
 char* EscapeString(int len, char *bin_string , int scheme=CPLES_SQL) {
     return CPLEscapeString(bin_string, len, scheme);
-} 
+}
 %}
 %clear (int len, char *bin_string);
 #endif
@@ -255,6 +255,11 @@ char* EscapeString(int len, char *bin_string , int scheme=CPLES_SQL) {
 /* call */
 %exception CPLGetLastErrorNo
 {
+#ifdef SWIGPYTHON
+%#ifdef SED_HACKS
+    if( bUseExceptions ) bLocalUseExceptionsCode = FALSE;
+%#endif
+#endif
     result = CPLGetLastErrorNo();
 }
 #endif
@@ -265,6 +270,11 @@ int CPLGetLastErrorNo();
 /* call */
 %exception CPLGetLastErrorType
 {
+#ifdef SWIGPYTHON
+%#ifdef SED_HACKS
+    if( bUseExceptions ) bLocalUseExceptionsCode = FALSE;
+%#endif
+#endif
     result = CPLGetLastErrorType();
 }
 int CPLGetLastErrorType();
@@ -277,11 +287,19 @@ CPLErr CPLGetLastErrorType();
 /* call */
 %exception CPLGetLastErrorMsg
 {
+#ifdef SWIGPYTHON
+%#ifdef SED_HACKS
+    if( bUseExceptions ) bLocalUseExceptionsCode = FALSE;
+%#endif
+#endif
     result = (char*)CPLGetLastErrorMsg();
 }
 #endif
 const char *CPLGetLastErrorMsg();
 
+int VSIGetLastErrorNo();
+const char *VSIGetLastErrorMsg();
+
 void CPLPushFinderLocation( const char * utf8_path );
 
 void CPLPopFinderLocation();
@@ -291,7 +309,12 @@ void CPLFinderClean();
 const char * CPLFindFile( const char *pszClass, const char *utf8_path );
 
 %apply (char **CSL) {char **};
-char **VSIReadDir( const char * utf8_path );
+%inline {
+char **wrapper_VSIReadDirEx( const char * utf8_path, int nMaxFiles = 0 )
+{
+    return VSIReadDirEx(utf8_path, nMaxFiles);
+}
+}
 %clear char **;
 
 %apply (char **CSL) {char **};
@@ -374,13 +397,18 @@ int wrapper_HasThreadSupport()
 /* Added for GDAL 1.8 */
 VSI_RETVAL VSIMkdir(const char *utf8_path, int mode );
 VSI_RETVAL VSIRmdir(const char *utf8_path );
+
+%apply (const char* utf8_path) {(const char* pszOld)};
+%apply (const char* utf8_path) {(const char* pszNew)};
 VSI_RETVAL VSIRename(const char * pszOld, const char *pszNew );
+%clear (const char* pszOld);
+%clear (const char* pszNew);
 
-/* Added for GDAL 1.8 
+/* Added for GDAL 1.8
 
    We do not bother renaming the VSI*L api as this wrapping is not
-   considered "official", or available for use by application code. 
-   It is just for some testing stuff. 
+   considered "official", or available for use by application code.
+   It is just for some testing stuff.
 */
 
 #if !defined(SWIGJAVA)
@@ -453,6 +481,8 @@ int wrapper_VSIStatL( const char * utf8_path, StatBuf *psStatBufOut, int nFlags
 
 #endif
 
+%apply Pointer NONNULL {VSILFILE* fp};
+
 %rename (VSIFOpenL) wrapper_VSIFOpenL;
 %inline %{
 VSILFILE   *wrapper_VSIFOpenL( const char *utf8_path, const char *pszMode )
@@ -462,35 +492,46 @@ VSILFILE   *wrapper_VSIFOpenL( const char *utf8_path, const char *pszMode )
     return VSIFOpenL( utf8_path, pszMode );
 }
 %}
-VSI_RETVAL VSIFCloseL( VSILFILE * );
+
+%rename (VSIFOpenExL) wrapper_VSIFOpenExL;
+%inline %{
+VSILFILE   *wrapper_VSIFOpenExL( const char *utf8_path, const char *pszMode, int bSetError )
+{
+    if (!pszMode) /* would lead to segfault */
+        pszMode = "r";
+    return VSIFOpenExL( utf8_path, pszMode, bSetError );
+}
+%}
+
+VSI_RETVAL VSIFCloseL( VSILFILE* fp );
 
 #if defined(SWIGPYTHON)
-int     VSIFSeekL( VSILFILE *, GIntBig, int );
-GIntBig    VSIFTellL( VSILFILE * );
-int     VSIFTruncateL( VSILFILE *, GIntBig );
+int     VSIFSeekL( VSILFILE* fp, GIntBig offset, int whence);
+GIntBig    VSIFTellL( VSILFILE* fp );
+int     VSIFTruncateL( VSILFILE* fp, GIntBig length );
 #else
-VSI_RETVAL VSIFSeekL( VSILFILE *, long, int );
-long    VSIFTellL( VSILFILE * );
-VSI_RETVAL VSIFTruncateL( VSILFILE *, long );
+VSI_RETVAL VSIFSeekL( VSILFILE* fp, long offset, int whence);
+long    VSIFTellL( VSILFILE* fp );
+VSI_RETVAL VSIFTruncateL( VSILFILE* fp, long length );
 #endif
 
 #if defined(SWIGPYTHON)
 %rename (VSIFWriteL) wrapper_VSIFWriteL;
 %inline {
-int wrapper_VSIFWriteL( int nLen, char *pBuf, int size, int memb, VSILFILE * f)
+int wrapper_VSIFWriteL( int nLen, char *pBuf, int size, int memb, VSILFILE* fp)
 {
     if (nLen < size * memb)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Inconsistent buffer size with 'size' and 'memb' values");
         return 0;
     }
-    return VSIFWriteL(pBuf, size, memb, f);
+    return VSIFWriteL(pBuf, size, memb, fp);
 }
 }
 #elif defined(SWIGPERL)
 size_t VSIFWriteL(const void *pBuffer, size_t nSize, size_t nCount, VSILFILE *fp);
 #else
-int     VSIFWriteL( const char *, int, int, VSILFILE * );
+int     VSIFWriteL( const char *, int, int, VSILFILE *fp );
 #endif
 
 #if defined(SWIGPERL)
@@ -498,6 +539,21 @@ size_t VSIFReadL(void *pBuffer, size_t nSize, size_t nCount, VSILFILE *fp);
 #endif
 /* VSIFReadL() handled specially in python/gdal_python.i */
 
+#if defined(SWIGPERL)
+void VSIStdoutSetRedirection( VSIWriteFunction pFct, FILE* stream );
+%inline {
+void VSIStdoutUnsetRedirection()
+{
+    VSIStdoutSetRedirection( fwrite, stdout );
+}
+}
 #endif
 
-#endif
+#endif /* !defined(SWIGJAVA) */
+
+%apply (char **CSL) {char **};
+%rename (ParseCommandLine) CSLParseCommandLine;
+char **CSLParseCommandLine( const char * utf8_path );
+%clear char **;
+
+#endif /* #ifndef SWIGRUBY */
diff --git a/swig/include/cpl_exceptions.i b/swig/include/cpl_exceptions.i
index 07cff54..11abd66 100644
--- a/swig/include/cpl_exceptions.i
+++ b/swig/include/cpl_exceptions.i
@@ -1,11 +1,11 @@
 /******************************************************************************
- * $Id: cpl_exceptions.i 20628 2010-09-15 20:50:56Z ajolma $
+ * $Id: cpl_exceptions.i 32864 2016-01-08 21:00:50Z goatbar $
  *
  * Code for Optional Exception Handling through UseExceptions(),
  * DontUseExceptions()
  *
  * It uses CPLSetErrorHandler to provide a custom function
- * which notifies the bindings of errors. 
+ * which notifies the bindings of errors.
  *
  * This is not thread safe.
  *
@@ -32,10 +32,15 @@
  *****************************************************************************/
 
 %{
-void VeryQuiteErrorHandler(CPLErr eclass, int code, const char *msg ) {
+void VeryQuietErrorHandler(CPLErr eclass, int code, const char *msg ) {
   /* If the error class is CE_Fatal, we want to have a message issued
      because the CPL support code does an abort() before any exception
      can be generated */
+#if defined(SWIGPERL)
+    AV* error_stack = get_av("Geo::GDAL::error", 0);
+    SV *error = newSVpv(msg, 0);
+    av_push(error_stack, error);
+#endif
   if (eclass == CE_Fatal ) {
     CPLDefaultErrorHandler(eclass, code, msg );
   }
@@ -44,7 +49,7 @@ void VeryQuiteErrorHandler(CPLErr eclass, int code, const char *msg ) {
 
 %inline %{
 void UseExceptions() {
-  CPLSetErrorHandler( (CPLErrorHandler) VeryQuiteErrorHandler );
+  CPLSetErrorHandler( (CPLErrorHandler) VeryQuietErrorHandler );
 }
 
 void DontUseExceptions() {
@@ -60,7 +65,7 @@ void DontUseExceptions() {
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
 #if defined(SWIGPERL)
-      SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      do_confess( CPLGetLastErrorMsg(), 0 );
 #elif defined(SWIGCSHARP)
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
 #else
@@ -69,7 +74,7 @@ void DontUseExceptions() {
     }
 
 #if defined(SWIGPERL)
-    /* 
+    /*
     Make warnings regular Perl warnings. This duplicates the warning
     message if DontUseExceptions() is in effect (it is not by default).
     */
diff --git a/swig/include/cplvirtualmem.i b/swig/include/cplvirtualmem.i
index b1044c5..b8dd367 100644
--- a/swig/include/cplvirtualmem.i
+++ b/swig/include/cplvirtualmem.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cplvirtualmem.i 26832 2014-01-15 12:46:08Z rouault $
+ * $Id: cplvirtualmem.i 32864 2016-01-08 21:00:50Z goatbar $
  *
  * Name:     cplvirtualmem.i
  * Project:  GDAL Python Interface
@@ -86,5 +86,5 @@ public:
         CPLVirtualMemPin(self->vmem, start_addr, nsize, bWriteOp);
     }
 } /* extend */
-}; /* CPLVirtualMemShadow */ 
+}; /* CPLVirtualMemShadow */
 #endif
diff --git a/swig/include/csharp/gdal_csharp.i b/swig/include/csharp/gdal_csharp.i
index 90e6934..169b682 100644
--- a/swig/include/csharp/gdal_csharp.i
+++ b/swig/include/csharp/gdal_csharp.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_csharp.i 26526 2013-10-11 11:49:24Z tamas $
+ * $Id: gdal_csharp.i 33721 2016-03-15 00:56:01Z goatbar $
  *
  * Name:     gdal_csharp.i
  * Project:  GDAL CSharp Interface
@@ -27,7 +27,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
- 
+
 %include cpl_exceptions.i
 
 %rename (GetMetadata) GetMetadata_List;
@@ -72,7 +72,7 @@ DEFINE_EXTERNAL_CLASS(OGRLayerShadow, OSGeo.OGR.Layer)
       GC.KeepAlive(this);
       return retval;
   }
-  
+
 %enddef
 
 %typemap(cscode, noblock="1") GDALRasterBandShadow {
@@ -85,18 +85,18 @@ DEFINE_EXTERNAL_CLASS(OGRLayerShadow, OSGeo.OGR.Layer)
 
 /*! Sixteen bit unsigned integer */ //%rasterio_functions(DataType.GDT_UInt16,ushort)
 /*! Thirty two bit unsigned integer */ //%rasterio_functions(DataType.GDT_UInt32,uint)
-/*! Complex Int16 */ //%rasterio_functions(DataType.GDT_CInt16,int)                 
-/*! Complex Int32 */ //%rasterio_functions(DataType.GDT_CInt32,int)                 
-/*! Complex Float32 */ //%rasterio_functions(DataType.GDT_CFloat32,int)              
-/*! Complex Float64 */ //%rasterio_functions(DataType.GDT_CFloat64,int)               
+/*! Complex Int16 */ //%rasterio_functions(DataType.GDT_CInt16,int)
+/*! Complex Int32 */ //%rasterio_functions(DataType.GDT_CInt32,int)
+/*! Complex Float32 */ //%rasterio_functions(DataType.GDT_CFloat32,int)
+/*! Complex Float64 */ //%rasterio_functions(DataType.GDT_CFloat64,int)
 
 %define %ds_rasterio_functions(GDALTYPE,CSTYPE)
- public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, CSTYPE[] buffer, int buf_xSize, int buf_ySize, 
+ public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, CSTYPE[] buffer, int buf_xSize, int buf_ySize,
      int bandCount, int[] bandMap, int pixelSpace, int lineSpace, int bandSpace) {
       CPLErr retval;
       GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
       try {
-          retval = ReadRaster(xOff, yOff, xSize, ySize, handle.AddrOfPinnedObject(), buf_xSize, buf_ySize, GDALTYPE, 
+          retval = ReadRaster(xOff, yOff, xSize, ySize, handle.AddrOfPinnedObject(), buf_xSize, buf_ySize, GDALTYPE,
                                bandCount, bandMap, pixelSpace, lineSpace, bandSpace);
       } finally {
           handle.Free();
@@ -117,7 +117,7 @@ DEFINE_EXTERNAL_CLASS(OGRLayerShadow, OSGeo.OGR.Layer)
       GC.KeepAlive(this);
       return retval;
   }
-  
+
 %enddef
 
 %typemap(cscode, noblock="1") GDALDatasetShadow {
@@ -131,7 +131,7 @@ public int BuildOverviews( string resampling, int[] overviewlist, $module.GDALPr
       int retval;
       if (overviewlist.Length <= 0)
         throw new ArgumentException("overviewlist size is small (BuildOverviews)");
-        
+
       IntPtr ptr = Marshal.AllocHGlobal(overviewlist.Length * Marshal.SizeOf(overviewlist[0]));
       try {
           Marshal.Copy(overviewlist, 0, ptr, overviewlist.Length);
@@ -145,7 +145,7 @@ public int BuildOverviews( string resampling, int[] overviewlist, $module.GDALPr
 public int BuildOverviews( string resampling, int[] overviewlist) {
       return BuildOverviews( resampling, overviewlist, null, null);
   }
-  
+
 public GCP[] GetGCPs() {
       /*hello*/
       IntPtr cPtr = __GetGCPs();
@@ -160,7 +160,7 @@ public GCP[] GetGCPs() {
       GC.KeepAlive(this);
       return ret;
   }
-  
+
 public CPLErr SetGCPs(GCP[] pGCPs, string pszGCPProjection) {
      CPLErr ret = 0;
      if (pGCPs != null && pGCPs.Length > 0)
@@ -168,11 +168,11 @@ public CPLErr SetGCPs(GCP[] pGCPs, string pszGCPProjection) {
          IntPtr cPtr = __AllocCArray_GDAL_GCP(pGCPs.Length);
          if (cPtr == IntPtr.Zero)
             throw new ApplicationException("Error allocating CArray with __AllocCArray_GDAL_GCP");
-            
+
          try {
              for (int i=0; i < pGCPs.Length; i++)
                 __WriteCArrayItem_GDAL_GCP(cPtr, i, pGCPs[i]);
-             
+
              ret = __SetGCPs(pGCPs.Length, cPtr, pszGCPProjection);
          }
          finally
@@ -187,9 +187,9 @@ public CPLErr SetGCPs(GCP[] pGCPs, string pszGCPProjection) {
 
 /*! Sixteen bit unsigned integer */ //%ds_rasterio_functions(DataType.GDT_UInt16,ushort)
 /*! Thirty two bit unsigned integer */ //%ds_rasterio_functions(DataType.GDT_UInt32,uint)
-/*! Complex Int16 */ //%ds_rasterio_functions(DataType.GDT_CInt16,int)                 
-/*! Complex Int32 */ //%ds_rasterio_functions(DataType.GDT_CInt32,int)                 
-/*! Complex Float32 */ //%ds_rasterio_functions(DataType.GDT_CFloat32,int)              
+/*! Complex Int16 */ //%ds_rasterio_functions(DataType.GDT_CInt16,int)
+/*! Complex Int32 */ //%ds_rasterio_functions(DataType.GDT_CInt32,int)
+/*! Complex Float32 */ //%ds_rasterio_functions(DataType.GDT_CFloat32,int)
 /*! Complex Float64 */ //%ds_rasterio_functions(DataType.GDT_CFloat64,int)
 
 %pragma(csharp) modulecode=%{
@@ -200,11 +200,11 @@ public CPLErr SetGCPs(GCP[] pGCPs, string pszGCPProjection) {
          IntPtr cPtr = __AllocCArray_GDAL_GCP(pGCPs.Length);
          if (cPtr == IntPtr.Zero)
             throw new ApplicationException("Error allocating CArray with __AllocCArray_GDAL_GCP");
-            
-         try {   
+
+         try {
              for (int i=0; i < pGCPs.Length; i++)
                 __WriteCArrayItem_GDAL_GCP(cPtr, i, pGCPs[i]);
-             
+
              ret = GCPsToGeoTransform(pGCPs.Length, cPtr, argout, bApproxOK);
          }
          finally
@@ -214,7 +214,7 @@ public CPLErr SetGCPs(GCP[] pGCPs, string pszGCPProjection) {
      }
      return ret;
    }
-   
+
  public static void FileFromMemBuffer(string utf8_path, byte[] bytes) {
      GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
      try {
diff --git a/swig/include/csharp/gdal_csharp_extend.i b/swig/include/csharp/gdal_csharp_extend.i
index c5370f2..70ca565 100644
--- a/swig/include/csharp/gdal_csharp_extend.i
+++ b/swig/include/csharp/gdal_csharp_extend.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_csharp_extend.i 14910 2008-07-14 21:35:18Z tamas $
+ * $Id: gdal_csharp_extend.i 33721 2016-03-15 00:56:01Z goatbar $
  *
  * Name:     gdal_csharp_extend.i
  * Project:  GDAL CSharp Interface
@@ -27,57 +27,57 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
- 
- 
+
+
 /******************************************************************************
  * GDAL raster R/W support                                                    *
  *****************************************************************************/
 
-%extend GDALRasterBandShadow 
+%extend GDALRasterBandShadow
 {
 	%apply (void *buffer_ptr) {void *buffer};
 	CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, void* buffer,
-                          int buf_xSize, int buf_ySize, GDALDataType buf_type, 
+                          int buf_xSize, int buf_ySize, GDALDataType buf_type,
                           int pixelSpace, int lineSpace) {
-       return GDALRasterIO( self, GF_Read, xOff, yOff, xSize, ySize, 
+       return GDALRasterIO( self, GF_Read, xOff, yOff, xSize, ySize,
 		        buffer, buf_xSize, buf_ySize, buf_type, pixelSpace, lineSpace );
     }
     CPLErr WriteRaster(int xOff, int yOff, int xSize, int ySize, void* buffer,
-                          int buf_xSize, int buf_ySize, GDALDataType buf_type, 
+                          int buf_xSize, int buf_ySize, GDALDataType buf_type,
                           int pixelSpace, int lineSpace) {
-       return GDALRasterIO( self, GF_Write, xOff, yOff, xSize, ySize, 
+       return GDALRasterIO( self, GF_Write, xOff, yOff, xSize, ySize,
 		        buffer, buf_xSize, buf_ySize, buf_type, pixelSpace, lineSpace );
     }
     %clear void *buffer;
 }
 
-%extend GDALDatasetShadow 
+%extend GDALDatasetShadow
 {
 	%apply (void *buffer_ptr) {void *buffer};
 	%apply (int argin[ANY]) {int *bandMap};
 	CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, void* buffer,
-                          int buf_xSize, int buf_ySize, GDALDataType buf_type, 
+                          int buf_xSize, int buf_ySize, GDALDataType buf_type,
                           int bandCount, int* bandMap, int pixelSpace, int lineSpace, int bandSpace) {
-       return GDALDatasetRasterIO( self, GF_Read, xOff, yOff, xSize, ySize, 
-		        buffer, buf_xSize, buf_ySize, buf_type, bandCount, 
+       return GDALDatasetRasterIO( self, GF_Read, xOff, yOff, xSize, ySize,
+		        buffer, buf_xSize, buf_ySize, buf_type, bandCount,
 		        bandMap, pixelSpace, lineSpace, bandSpace);
     }
     CPLErr WriteRaster(int xOff, int yOff, int xSize, int ySize, void* buffer,
-                          int buf_xSize, int buf_ySize, GDALDataType buf_type, 
+                          int buf_xSize, int buf_ySize, GDALDataType buf_type,
                           int bandCount, int* bandMap, int pixelSpace, int lineSpace, int bandSpace) {
-       return GDALDatasetRasterIO( self, GF_Write, xOff, yOff, xSize, ySize, 
-		        buffer, buf_xSize, buf_ySize, buf_type, bandCount, 
+       return GDALDatasetRasterIO( self, GF_Write, xOff, yOff, xSize, ySize,
+		        buffer, buf_xSize, buf_ySize, buf_type, bandCount,
 		        bandMap, pixelSpace, lineSpace, bandSpace);
     }
     %clear void *buffer;
     %clear int* bandMap;
-    
+
     %apply (void *buffer_ptr) {const GDAL_GCP* __GetGCPs};
     const GDAL_GCP* __GetGCPs( ) {
       return GDALGetGCPs( self );
     }
     %clear const GDAL_GCP* __GetGCPs;
-    
+
     CPLErr __SetGCPs( int nGCPs, GDAL_GCP const *pGCPs, const char *pszGCPProjection ) {
         return GDALSetGCPs( self, nGCPs, pGCPs, pszGCPProjection );
     }
diff --git a/swig/include/csharp/ogr_csharp.i b/swig/include/csharp/ogr_csharp.i
index 204b081..1427bd0 100644
--- a/swig/include/csharp/ogr_csharp.i
+++ b/swig/include/csharp/ogr_csharp.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_csharp.i 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogr_csharp.i 33721 2016-03-15 00:56:01Z goatbar $
  *
  * Name:     ogr_csharp.i
  * Project:  GDAL CSharp Interface
@@ -27,7 +27,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
- 
+
 %include cpl_exceptions.i
 
 %rename (GetFieldType) GetType;
@@ -49,7 +49,7 @@ DEFINE_EXTERNAL_CLASS(GDALMajorObjectShadow, OSGeo.GDAL.MajorObject)
       int size = WkbSize();
       if (buffer.Length < size)
         throw new ArgumentException("Buffer size is small (ExportToWkb)");
-        
+
       IntPtr ptr = Marshal.AllocHGlobal(size * Marshal.SizeOf(buffer[0]));
       try {
           retval = ExportToWkb(size, ptr, byte_order);
@@ -63,11 +63,11 @@ DEFINE_EXTERNAL_CLASS(GDALMajorObjectShadow, OSGeo.GDAL.MajorObject)
   public int ExportToWkb( byte[] buffer ) {
       return ExportToWkb( buffer, wkbByteOrder.wkbXDR);
   }
-  
+
   public static $csclassname CreateFromWkb(byte[] wkb){
      if (wkb.Length == 0)
         throw new ArgumentException("Buffer size is small (CreateFromWkb)");
-     $csclassname retval;   
+     $csclassname retval;
      IntPtr ptr = Marshal.AllocHGlobal(wkb.Length * Marshal.SizeOf(wkb[0]));
      try {
          Marshal.Copy(wkb, 0, ptr, wkb.Length);
@@ -75,18 +75,18 @@ DEFINE_EXTERNAL_CLASS(GDALMajorObjectShadow, OSGeo.GDAL.MajorObject)
       } finally {
           Marshal.FreeHGlobal(ptr);
       }
-      return retval;  
+      return retval;
   }
-  
+
   public static $csclassname CreateFromWkt(string wkt){
      return new $csclassname(wkbGeometryType.wkbUnknown, wkt, 0, IntPtr.Zero, null);
   }
-  
+
   public static $csclassname CreateFromGML(string gml){
      return new $csclassname(wkbGeometryType.wkbUnknown, null, 0, IntPtr.Zero, gml);
   }
-  
+
   public Geometry(wkbGeometryType type) : this(OgrPINVOKE.new_Geometry((int)type, null, 0, IntPtr.Zero, null), true, null) {
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
   }
-}
\ No newline at end of file
+}
diff --git a/swig/include/csharp/ogr_csharp_extend.i b/swig/include/csharp/ogr_csharp_extend.i
index dd4b3c7..09f1951 100644
--- a/swig/include/csharp/ogr_csharp_extend.i
+++ b/swig/include/csharp/ogr_csharp_extend.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_csharp_extend.i 13436 2007-12-21 20:46:05Z tamas $
+ * $Id: ogr_csharp_extend.i 33721 2016-03-15 00:56:01Z goatbar $
  *
  * Name:     ogr_csharp_extend.i
  * Project:  GDAL CSharp Interface
@@ -27,13 +27,13 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
- 
- 
+
+
 /******************************************************************************
  * OGR WKB export                                                             *
  *****************************************************************************/
 
-%extend OGRGeometryShadow 
+%extend OGRGeometryShadow
 {
     %apply (void *buffer_ptr) {char *buffer};
     OGRErr ExportToWkb( int bufLen, char *buffer, OGRwkbByteOrder byte_order ) {
diff --git a/swig/include/csharp/osr_csharp.i b/swig/include/csharp/osr_csharp.i
index b6c0754..a14abff 100644
--- a/swig/include/csharp/osr_csharp.i
+++ b/swig/include/csharp/osr_csharp.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: osr_csharp.i 13679 2008-02-02 23:48:53Z tamas $
+ * $Id: osr_csharp.i 33721 2016-03-15 00:56:01Z goatbar $
  *
  * Name:     osr_csharp.i
  * Project:  GDAL CSharp Interface
@@ -27,7 +27,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
- 
+
 %include cpl_exceptions.i
 
 %include typemaps_csharp.i
diff --git a/swig/include/csharp/swig_csharp_extensions.i b/swig/include/csharp/swig_csharp_extensions.i
index 9f07a8b..3a2692d 100644
--- a/swig/include/csharp/swig_csharp_extensions.i
+++ b/swig/include/csharp/swig_csharp_extensions.i
@@ -1,15 +1,15 @@
 
 /******************************************************************************
- * $Id: swig_csharp_extensions.i 20170 2010-08-05 11:24:07Z tamas $
+ * $Id: swig_csharp_extensions.i 33721 2016-03-15 00:56:01Z goatbar $
  *
  * Name:     swig_csharp_extensions.i
- * Purpose:  Fix for the SWIG Interface problems (early GC) 
- *           and implementing SWIGTYPE *DISOWN 
+ * Purpose:  Fix for the SWIG Interface problems (early GC)
+ *           and implementing SWIGTYPE *DISOWN
  * Author:   Tamas Szekeres
  *
 */
 
-// Ensure the class is not marked BeforeFieldInit causing memory corruption with CLR4 
+// Ensure the class is not marked BeforeFieldInit causing memory corruption with CLR4
 %pragma(csharp) imclasscode=%{
   static $imclassname() {
   }
@@ -45,12 +45,12 @@
     $*csclassname ret = (cPtr == IntPtr.Zero) ? null : new $*csclassname(cPtr, $owner, ThisOwn_$owner());$excode
     return ret;
   }
-// Proxy classes (base classes, ie, not derived classes)
+// Proxy classes (base classes, i.e, not derived classes)
 %typemap(csbody) SWIGTYPE %{
   private HandleRef swigCPtr;
   protected bool swigCMemOwn;
   protected object swigParentRef;
-  
+
   protected static object ThisOwn_true() { return null; }
   protected object ThisOwn_false() { return this; }
 
@@ -182,7 +182,7 @@
 %pragma(csharp) modulecode=%{
   internal class $moduleObject : IDisposable {
 	public virtual void Dispose() {
-      
+
     }
   }
   internal static $moduleObject the$moduleObject = new $moduleObject();
@@ -194,7 +194,7 @@
 /******************************************************************************
  * Generic functions to marshal SWIGTYPE arrays                               *
  *****************************************************************************/
-  
+
 %define IMPLEMENT_ARRAY_MARSHALER(CTYPE)
 %csmethodmodifiers __WriteCArrayItem_##CTYPE "private";
 %csmethodmodifiers __ReadCArrayItem_##CTYPE "private";
diff --git a/swig/include/csharp/typemaps_csharp.i b/swig/include/csharp/typemaps_csharp.i
index bb77316..aa49cea 100644
--- a/swig/include/csharp/typemaps_csharp.i
+++ b/swig/include/csharp/typemaps_csharp.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: typemaps_csharp.i 29225 2015-05-21 16:28:00Z rouault $
+ * $Id: typemaps_csharp.i 33721 2016-03-15 00:56:01Z goatbar $
  *
  * Name:     typemaps_csharp.i
  * Project:  GDAL CSharp Interface
@@ -27,7 +27,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
- 
+
 
 %include "typemaps.i"
 
@@ -93,7 +93,7 @@ OGRErrMessages( int rc ) {
 %typemap(imtype) (CTYPE *optional_##CTYPE) "IntPtr"
 %typemap(cstype) (CTYPE *optional_##CTYPE) "ref CSTYPE"
 %typemap(csin) (CTYPE *optional_##CTYPE) "(IntPtr)$csinput"
- 
+
 %typemap(in) (CTYPE *optional_##CTYPE)
 {
   /* %typemap(in) (type *optional_##CTYPE) */
@@ -109,7 +109,7 @@ OPTIONAL_POD(int, int);
  ***************************************************/
 
 %typemap(out) (retStringAndCPLFree*)
-%{ 
+%{
     /* %typemap(out) (retStringAndCPLFree*) */
     if($1)
     {
@@ -183,7 +183,7 @@ OPTIONAL_POD(int, int);
                 ++count;
         }
         string[] ret = new string[count];
-        if (count > 0) {       
+        if (count > 0) {
 	        for(int cx = 0; cx < count; cx++) {
                 objPtr = System.Runtime.InteropServices.Marshal.ReadIntPtr(cPtr, cx * System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)));
                 ret[cx]= (objPtr == IntPtr.Zero) ? null : System.Runtime.InteropServices.Marshal.PtrToStringAnsi(objPtr);
@@ -192,7 +192,7 @@ OPTIONAL_POD(int, int);
         $excode
         return ret;
 }
- 
+
 %typemap(csout, excode=SWIGEXCODE) char** CSL {
         /* %typemap(csout) char** CSL */
         IntPtr cPtr = $imcall;
@@ -203,7 +203,7 @@ OPTIONAL_POD(int, int);
                 ++count;
         }
         string[] ret = new string[count];
-        if (count > 0) {       
+        if (count > 0) {
 	        for(int cx = 0; cx < count; cx++) {
                 objPtr = System.Runtime.InteropServices.Marshal.ReadIntPtr(cPtr, cx * System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)));
                 ret[cx]= (objPtr == IntPtr.Zero) ? null : System.Runtime.InteropServices.Marshal.PtrToStringAnsi(objPtr);
@@ -223,7 +223,7 @@ OPTIONAL_POD(int, int);
         /* %typemap(csout) int *intList */
         IntPtr cPtr = $imcall;
         int[] ret = new int[count];
-        if (count > 0) {       
+        if (count > 0) {
 	        System.Runtime.InteropServices.Marshal.Copy(cPtr, ret, 0, count);
         }
         $excode
@@ -238,7 +238,7 @@ OPTIONAL_POD(int, int);
         /* %typemap(csout) int *intList */
         IntPtr cPtr = $imcall;
         double[] ret = new double[count];
-        if (count > 0) {       
+        if (count > 0) {
 	        System.Runtime.InteropServices.Marshal.Copy(cPtr, ret, 0, count);
         }
         $excode
@@ -246,12 +246,12 @@ OPTIONAL_POD(int, int);
 }
 
 /*
- * Typemap for char **argout. 
+ * Typemap for char **argout.
  */
 %typemap(imtype) (char **argout), (char **username), (char **usrname), (char **type) "out string"
 %typemap(cstype) (char **argout), (char **username), (char **usrname), (char **type) "out string"
 %typemap(csin) (char** argout), (char **username), (char **usrname), (char **type) "out $csinput"
-  
+
 %typemap(in) (char **argout), (char **username), (char **usrname), (char **type)
 {
   /* %typemap(in) (char **argout) */
@@ -273,17 +273,17 @@ OPTIONAL_POD(int, int);
 }
 
 /*
- * Typemap for char **ignorechange. 
+ * Typemap for char **ignorechange.
  */
- 
+
 %typemap(imtype) (char **ignorechange) "ref string"
 %typemap(cstype) (char **ignorechange) "ref string"
 %typemap(csin) (char** ignorechange) "ref $csinput"
-  
+
 %typemap(in, noblock="1") (char **ignorechange)
 {
   /* %typemap(in) (char **ignorechange) */
-    $*1_type savearg = *(($1_type)$input); 
+    $*1_type savearg = *(($1_type)$input);
 	$1 = ($1_ltype)$input;
 }
 %typemap(argout, noblock="1") (char **ignorechange)
@@ -295,7 +295,7 @@ OPTIONAL_POD(int, int);
 }
 
 /*
- * Typemap for double argout[ANY]. 
+ * Typemap for double argout[ANY].
  */
 %typemap(imtype) (double argout[ANY]) "double[]"
 %typemap(cstype) (double argout[ANY]) "double[]"
@@ -326,7 +326,7 @@ OPTIONAL_POD(int, int);
 %apply double argout[ANY] {double *inout}
 
 /*
- * Typemap for double argin[ANY]. 
+ * Typemap for double argin[ANY].
  */
 
 %typemap(imtype) (double argin[ANY])  "double[]"
@@ -340,7 +340,7 @@ OPTIONAL_POD(int, int);
 }
 
 /*
- * Typemap for int argin[ANY]. 
+ * Typemap for int argin[ANY].
  */
 
 %typemap(imtype) (int argin[ANY])  "int[]"
@@ -354,7 +354,7 @@ OPTIONAL_POD(int, int);
 }
 
 /*
- * Typemap for double inout[ANY]. 
+ * Typemap for double inout[ANY].
  */
 
 %typemap(imtype) (double inout[ANY])  "double[]"
@@ -370,7 +370,7 @@ OPTIONAL_POD(int, int);
 %apply (double inout[ANY]) {double *pList};
 
 /*
- * Typemap for int inout[ANY]. 
+ * Typemap for int inout[ANY].
  */
 
 %typemap(imtype) (int inout[ANY])  "int[]"
@@ -386,7 +386,7 @@ OPTIONAL_POD(int, int);
 %apply (int inout[ANY]) {int *pList};
 
 /*
- * Helper to marshal utf8 strings. 
+ * Helper to marshal utf8 strings.
  */
 
 %pragma(csharp) modulecode=%{
@@ -394,29 +394,29 @@ OPTIONAL_POD(int, int);
   {
     if (str == null)
       return null;
-    
+
     int bytecount = System.Text.Encoding.UTF8.GetMaxByteCount(str.Length);
     byte[] bytes = new byte[bytecount + 1];
     System.Text.Encoding.UTF8.GetBytes(str, 0, str.Length, bytes, 0);
     return bytes;
   }
-  
+
   internal static string Utf8BytesToString(IntPtr pNativeData)
   {
     if (pNativeData == IntPtr.Zero)
         return null;
-        
+
     int length = Marshal.PtrToStringAnsi(pNativeData).Length;
-    byte[] strbuf = new byte[length];  
-    Marshal.Copy(pNativeData, strbuf, 0, length); 
+    byte[] strbuf = new byte[length];
+    Marshal.Copy(pNativeData, strbuf, 0, length);
     return System.Text.Encoding.UTF8.GetString(strbuf);
   }
 %}
 
 /*
- * Typemap for const char *utf8_path. 
+ * Typemap for const char *utf8_path.
  */
-%typemap(csin) (const char *utf8_path)  "$module.StringToUtf8Bytes($csinput)" 
+%typemap(csin) (const char *utf8_path)  "$module.StringToUtf8Bytes($csinput)"
 %typemap(imtype, out="IntPtr") (const char *utf8_path) "byte[]"
 %typemap(out) (const char *utf8_path) %{ $result = $1; %}
 %typemap(csout, excode=SWIGEXCODE) (const char *utf8_path) {
@@ -430,7 +430,7 @@ OPTIONAL_POD(int, int);
 %apply ( const char *utf8_path ) { const char* GetFieldAsString };
 
 /*
- * Typemap for double *defaultval. 
+ * Typemap for double *defaultval.
  */
 
 %typemap(imtype) (double *defaultval)  "ref double"
@@ -475,7 +475,7 @@ OPTIONAL_POD(int, int);
 %apply (int *hasval) {int *pnBytes};
 
 /*
- * Typemap for int **array_argout. 
+ * Typemap for int **array_argout.
  */
 
 %typemap(imtype) (int **array_argout)  "out int[]"
@@ -491,7 +491,7 @@ OPTIONAL_POD(int, int);
 %apply (int **array_argout) {int **pList};
 
 /*
- * Typemap for double **array_argout. 
+ * Typemap for double **array_argout.
  */
 
 %typemap(imtype) (double **array_argout)  "out double[]"
@@ -509,7 +509,7 @@ OPTIONAL_POD(int, int);
 /******************************************************************************
  * GDAL raster R/W support                                                    *
  *****************************************************************************/
- 
+
 %typemap(imtype, out="IntPtr") void *buffer_ptr "IntPtr"
 %typemap(cstype) void *buffer_ptr %{IntPtr%}
 %typemap(in) void *buffer_ptr %{ $1 = ($1_ltype)$input; %}
@@ -549,4 +549,4 @@ OPTIONAL_POD(int, int);
 %typemap(in) (GDALProgressFunc callback) %{ $1 = ($1_ltype)$input; %}
 %typemap(imtype) (void* callback_data) "string"
 %typemap(cstype) (void* callback_data) "string"
-%typemap(csin) (void* callback_data) "$csinput"
\ No newline at end of file
+%typemap(csin) (void* callback_data) "$csinput"
diff --git a/swig/include/gdal.i b/swig/include/gdal.i
index 4064ed1..eedb847 100644
--- a/swig/include/gdal.i
+++ b/swig/include/gdal.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal.i 29227 2015-05-21 16:58:30Z ajolma $
+ * $Id: gdal.i 33758 2016-03-21 09:06:22Z rouault $
  *
  * Name:     gdal.i
  * Project:  GDAL Python Interface
@@ -58,6 +58,7 @@ using namespace std;
 #include "cpl_string.h"
 #include "cpl_multiproc.h"
 #include "cpl_http.h"
+#include "cpl_vsi_error.h"
 
 #include "gdal.h"
 #include "gdal_priv.h"
@@ -74,9 +75,9 @@ typedef void GDALTransformerInfoShadow;
 typedef void GDALAsyncReaderShadow;
 %}
 
-#if defined(SWIGPYTHON) || defined(SWIGJAVA)
+#if defined(SWIGPYTHON) || defined(SWIGJAVA) || defined(SWIGPERL)
 %{
-#ifdef DEBUG 
+#ifdef DEBUG
 typedef struct OGRSpatialReferenceHS OSRSpatialReferenceShadow;
 typedef struct OGRLayerHS OGRLayerShadow;
 typedef struct OGRGeometryHS OGRGeometryShadow;
@@ -98,8 +99,8 @@ typedef int OGRErr;
 typedef int RETURN_NONE;
 /* return value that is used for VSI methods that return -1 on error (and set errno) */
 typedef int VSI_RETVAL;
-
 %}
+typedef int RETURN_NONE;
 
 //************************************************************************
 //
@@ -163,7 +164,7 @@ typedef enum
 
 /*! Types of color interpretations for a GDALColorTable. */
 %rename (PaletteInterp) GDALPaletteInterp;
-typedef enum 
+typedef enum
 {
   /*! Grayscale (in GDALColorEntry.c1) */                      GPI_Gray=0,
   /*! Red, Green, Blue and Alpha in (in c1, c2, c3 and c4) */  GPI_RGB=1,
@@ -196,7 +197,7 @@ typedef enum
     /*! Average */                          GRIORA_Average = 5,
     /*! Mode (selects the value which appears most often of all the sampled points) */
                                             GRIORA_Mode = 6,
-    /*! Gauss bluring */                    GRIORA_Gauss = 7
+    /*! Gauss blurring */                   GRIORA_Gauss = 7
 } GDALRIOResampleAlg;
 
 /*! Warp Resampling Algorithm */
@@ -207,7 +208,7 @@ typedef enum {
   /*! Cubic Convolution Approximation (4x4 kernel) */  GRA_Cubic=2,
   /*! Cubic B-Spline Approximation (4x4 kernel) */     GRA_CubicSpline=3,
   /*! Lanczos windowed sinc interpolation (6x6 kernel) */ GRA_Lanczos=4,
-  /*! Average (computes the average of all non-NODATA contributing pixels) */ GRA_Average=5, 
+  /*! Average (computes the average of all non-NODATA contributing pixels) */ GRA_Average=5,
   /*! Mode (selects the value which appears most often of all the sampled points) */ GRA_Mode=6
 } GDALResampleAlg;
 
@@ -236,7 +237,6 @@ typedef enum {
 %include "gdal_typemaps.i"
 #endif
 
-
 /* Default memberin typemaps required to support SWIG 1.3.39 and above */
 %typemap(memberin) char *Info %{
 /* char* Info memberin typemap */
@@ -249,7 +249,7 @@ $1;
 %}
 
 //************************************************************************
-// Apply NONNULL to all utf8_path's. 
+// Apply NONNULL to all utf8_path's.
 %apply Pointer NONNULL { const char* utf8_path };
 
 //************************************************************************
@@ -283,7 +283,6 @@ $1;
 %include "Driver.i"
 
 
-
 #if defined(SWIGPYTHON) || defined(SWIGJAVA) || defined(SWIGPERL)
 /*
  * We need to import ogr.i and osr.i for OGRLayer and OSRSpatialRefrerence
@@ -352,16 +351,20 @@ $1;
 //************************************************************************
 #if !defined(SWIGPERL) && !defined(SWIGJAVA)
 %rename (ColorEntry) GDALColorEntry;
+#ifdef SWIGPYTHON
+%nodefaultctor GDALColorEntry;
+%nodefaultdtor GDALColorEntry;
+#endif
 typedef struct
 {
     /*! gray, red, cyan or hue */
-    short      c1;      
-    /*! green, magenta, or lightness */    
-    short      c2;      
+    short      c1;
+    /*! green, magenta, or lightness */
+    short      c2;
     /*! blue, yellow, or saturation */
-    short      c3;      
+    short      c3;
     /*! alpha or blackband */
-    short      c4;      
+    short      c4;
 } GDALColorEntry;
 #endif
 
@@ -410,8 +413,6 @@ struct GDAL_GCP {
       CPLFree( self->pszId );
     CPLFree( self );
   }
-
-
 } /* extend */
 }; /* GDAL_GCP */
 
@@ -452,7 +453,7 @@ const char * GDAL_GCP_Info_get( GDAL_GCP *gcp ) {
   return gcp->pszInfo;
 }
 void GDAL_GCP_Info_set( GDAL_GCP *gcp, const char * pszInfo ) {
-  if ( gcp->pszInfo ) 
+  if ( gcp->pszInfo )
     CPLFree( gcp->pszInfo );
   gcp->pszInfo = CPLStrdup(pszInfo);
 }
@@ -460,15 +461,15 @@ const char * GDAL_GCP_Id_get( GDAL_GCP *gcp ) {
   return gcp->pszId;
 }
 void GDAL_GCP_Id_set( GDAL_GCP *gcp, const char * pszId ) {
-  if ( gcp->pszId ) 
+  if ( gcp->pszId )
     CPLFree( gcp->pszId );
   gcp->pszId = CPLStrdup(pszId);
 }
-%} //%inline 
+%} //%inline
 
 #if defined(SWIGCSHARP)
 %inline %{
-/* Duplicate, but transposed names for C# because 
+/* Duplicate, but transposed names for C# because
 *  the C# module outputs backwards names
 */
 double GDAL_GCP_get_GCPX( GDAL_GCP *gcp ) {
@@ -505,7 +506,7 @@ const char * GDAL_GCP_get_Info( GDAL_GCP *gcp ) {
   return gcp->pszInfo;
 }
 void GDAL_GCP_set_Info( GDAL_GCP *gcp, const char * pszInfo ) {
-  if ( gcp->pszInfo ) 
+  if ( gcp->pszInfo )
     CPLFree( gcp->pszInfo );
   gcp->pszInfo = CPLStrdup(pszInfo);
 }
@@ -513,11 +514,11 @@ const char * GDAL_GCP_get_Id( GDAL_GCP *gcp ) {
   return gcp->pszId;
 }
 void GDAL_GCP_set_Id( GDAL_GCP *gcp, const char * pszId ) {
-  if ( gcp->pszId ) 
+  if ( gcp->pszId )
     CPLFree( gcp->pszId );
   gcp->pszId = CPLStrdup(pszId);
 }
-%} //%inline 
+%} //%inline
 #endif //if defined(SWIGCSHARP)
 
 %clear GDAL_GCP *gcp;
@@ -526,7 +527,7 @@ void GDAL_GCP_set_Id( GDAL_GCP *gcp, const char * pszId ) {
 %rename (GCPsToGeoTransform) wrapper_GDALGCPsToGeoTransform;
 %inline
 {
-int wrapper_GDALGCPsToGeoTransform( int nGCPs, GDAL_GCP const * pGCPs, 
+int wrapper_GDALGCPsToGeoTransform( int nGCPs, GDAL_GCP const * pGCPs,
     	                             double argout[6], int bApproxOK = 1 )
 {
     return GDALGCPsToGeoTransform(nGCPs, pGCPs, argout, bApproxOK);
@@ -534,8 +535,8 @@ int wrapper_GDALGCPsToGeoTransform( int nGCPs, GDAL_GCP const * pGCPs,
 }
 #else
 %apply (IF_FALSE_RETURN_NONE) { (RETURN_NONE) };
-RETURN_NONE GDALGCPsToGeoTransform( int nGCPs, GDAL_GCP const * pGCPs, 
-    	                             double argout[6], int bApproxOK = 1 ); 
+RETURN_NONE GDALGCPsToGeoTransform( int nGCPs, GDAL_GCP const * pGCPs,
+    	                             double argout[6], int bApproxOK = 1 );
 %clear (RETURN_NONE);
 #endif
 
@@ -579,8 +580,8 @@ RETURN_NONE GDALGCPsToGeoTransform( int nGCPs, GDAL_GCP const * pGCPs,
 %apply (double argin[ANY]) {(double padfGeoTransform[6])};
 %apply (double *OUTPUT) {(double *pdfGeoX)};
 %apply (double *OUTPUT) {(double *pdfGeoY)};
-void GDALApplyGeoTransform( double padfGeoTransform[6], 
-                            double dfPixel, double dfLine, 
+void GDALApplyGeoTransform( double padfGeoTransform[6],
+                            double dfPixel, double dfLine,
                             double *pdfGeoX, double *pdfGeoY );
 %clear (double *padfGeoTransform);
 %clear (double *pdfGeoX);
@@ -617,7 +618,7 @@ void GDALAllRegister();
 
 void GDALDestroyDriverManager();
 
-#ifdef SWIGPYTHON
+#if defined(SWIGPYTHON) || defined(SWIGPERL)
 %inline {
 GIntBig wrapper_GDALGetCacheMax()
 {
@@ -740,11 +741,19 @@ int GetDriverCount() {
 
 %apply Pointer NONNULL { char const *name };
 %inline %{
+static
 GDALDriverShadow* GetDriverByName( char const *name ) {
   return (GDALDriverShadow*) GDALGetDriverByName( name );
 }
 %}
 
+#ifdef SWIGPERL
+%inline %{
+GDALDriverShadow* GetDriver( char const *name ) {
+  return (GDALDriverShadow*) GDALGetDriverByName( name );
+}
+%}
+#endif
 %inline %{
 GDALDriverShadow* GetDriver( int i ) {
   return (GDALDriverShadow*) GDALGetDriver( i );
@@ -754,6 +763,7 @@ GDALDriverShadow* GetDriver( int i ) {
 #ifdef SWIGJAVA
 %newobject Open;
 %inline %{
+static
 GDALDatasetShadow* Open( char const* utf8_path, GDALAccess eAccess) {
   CPLErrorReset();
   GDALDatasetShadow *ds = GDALOpen( utf8_path, eAccess );
@@ -804,6 +814,10 @@ GDALDatasetShadow* OpenEx( char const* utf8_path, unsigned int nOpenFlags = 0,
                            char** allowed_drivers = NULL, char** open_options = NULL,
                            char** sibling_files = NULL ) {
   CPLErrorReset();
+#ifdef SWIGPYTHON
+  if( GetUseExceptions() )
+      nOpenFlags |= GDAL_OF_VERBOSE_ERROR;
+#endif
   GDALDatasetShadow *ds = GDALOpenEx( utf8_path, nOpenFlags, allowed_drivers,
                                       open_options, sibling_files );
   if( ds != NULL && CPLGetLastErrorType() == CE_Failure )
@@ -836,9 +850,9 @@ GDALDatasetShadow* OpenShared( char const* utf8_path, GDALAccess eAccess = GA_Re
 
 %apply (char **options) {char **papszSiblings};
 %inline %{
-GDALDriverShadow *IdentifyDriver( const char *utf8_path, 
+GDALDriverShadow *IdentifyDriver( const char *utf8_path,
                                   char **papszSiblings = NULL ) {
-    return (GDALDriverShadow *) GDALIdentifyDriver( utf8_path, 
+    return (GDALDriverShadow *) GDALIdentifyDriver( utf8_path,
 	                                            papszSiblings );
 }
 %}
@@ -854,7 +868,6 @@ GDALDriverShadow *IdentifyDriver( const char *utf8_path,
 // CreateAndReprojectImage
 // GCPsToGeoTransform
 
-
 #if defined(SWIGPYTHON) || defined(SWIGJAVA)
 /* FIXME: other bindings should also use those typemaps to avoid memory leaks */
 %apply (char **options) {char ** papszArgv};
@@ -865,17 +878,18 @@ GDALDriverShadow *IdentifyDriver( const char *utf8_path,
 
 #ifdef SWIGJAVA
 %inline %{
+  static
   char **GeneralCmdLineProcessor( char **papszArgv, int nOptions = 0 ) {
     int nResArgCount;
-    
+
     /* We must add a 'dummy' element in front of the real argument list */
     /* as Java doesn't include the binary name as the first */
     /* argument, as C does... */
     char** papszArgvModBefore = CSLInsertString(CSLDuplicate(papszArgv), 0, "dummy");
     char** papszArgvModAfter = papszArgvModBefore;
 
-    nResArgCount = 
-      GDALGeneralCmdLineProcessor( CSLCount(papszArgvModBefore), &papszArgvModAfter, nOptions ); 
+    nResArgCount =
+      GDALGeneralCmdLineProcessor( CSLCount(papszArgvModBefore), &papszArgvModAfter, nOptions );
 
     CSLDestroy(papszArgvModBefore);
 
@@ -897,8 +911,11 @@ GDALDriverShadow *IdentifyDriver( const char *utf8_path,
   char **GeneralCmdLineProcessor( char **papszArgv, int nOptions = 0 ) {
     int nResArgCount;
 
-    nResArgCount = 
-      GDALGeneralCmdLineProcessor( CSLCount(papszArgv), &papszArgv, nOptions ); 
+    if( papszArgv == NULL )
+        return NULL;
+
+    nResArgCount =
+      GDALGeneralCmdLineProcessor( CSLCount(papszArgv), &papszArgv, nOptions );
 
     if( nResArgCount <= 0 )
         return NULL;
@@ -923,6 +940,607 @@ GDALDriverShadow *IdentifyDriver( const char *utf8_path,
 #ifdef SWIGPYTHON
 /* Add a __version__ attribute to match the convention */
 %pythoncode %{
-__version__ = _gdal.VersionInfo("RELEASE_NAME") 
+__version__ = _gdal.VersionInfo("RELEASE_NAME")
 %}
 #endif
+
+//************************************************************************
+//
+// GDAL Utilities
+//
+//************************************************************************
+
+%{
+#include "gdal_utils.h"
+%}
+
+%apply (const char* utf8_path) {(const char* dest)};
+
+//************************************************************************
+// gdal.Info()
+//************************************************************************
+
+#ifdef SWIGJAVA
+%rename (InfoOptions) GDALInfoOptions;
+#endif
+struct GDALInfoOptions {
+%extend {
+    GDALInfoOptions(char** options) {
+        return GDALInfoOptionsNew(options, NULL);
+    }
+
+    ~GDALInfoOptions() {
+        GDALInfoOptionsFree( self );
+    }
+}
+};
+
+#ifdef SWIGPYTHON
+%rename (InfoInternal) GDALInfo;
+#endif
+retStringAndCPLFree *GDALInfo( GDALDatasetShadow *hDataset, GDALInfoOptions *infoOptions );
+
+#ifdef SWIGJAVA
+%rename (TranslateOptions) GDALTranslateOptions;
+#endif
+struct GDALTranslateOptions {
+%extend {
+    GDALTranslateOptions(char** options) {
+        return GDALTranslateOptionsNew(options, NULL);
+    }
+
+    ~GDALTranslateOptions() {
+        GDALTranslateOptionsFree( self );
+    }
+}
+};
+
+//************************************************************************
+// gdal.Translate()
+//************************************************************************
+
+#ifdef SWIGPYTHON
+%rename (TranslateInternal) wrapper_GDALTranslate;
+#elif defined(SWIGJAVA)
+%rename (Translate) wrapper_GDALTranslate;
+#endif
+%newobject wrapper_GDALTranslate;
+
+%inline %{
+GDALDatasetShadow* wrapper_GDALTranslate( const char* dest,
+                                      GDALDatasetShadow* dataset,
+                                      GDALTranslateOptions* translateOptions,
+                                      GDALProgressFunc callback=NULL,
+                                      void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( translateOptions == NULL )
+        {
+            bFreeOptions = true;
+            translateOptions = GDALTranslateOptionsNew(NULL, NULL);
+        }
+        GDALTranslateOptionsSetProgress(translateOptions, callback, callback_data);
+    }
+    GDALDatasetH hDSRet = GDALTranslate(dest, dataset, translateOptions, &usageError);
+    if( bFreeOptions )
+        GDALTranslateOptionsFree(translateOptions);
+    return hDSRet;
+}
+%}
+
+//************************************************************************
+// gdal.Warp()
+//************************************************************************
+
+#ifdef SWIGJAVA
+%rename (WarpOptions) GDALWarpAppOptions;
+#endif
+struct GDALWarpAppOptions {
+%extend {
+    GDALWarpAppOptions(char** options) {
+        return GDALWarpAppOptionsNew(options, NULL);
+    }
+
+    ~GDALWarpAppOptions() {
+        GDALWarpAppOptionsFree( self );
+    }
+}
+};
+
+#ifdef SWIGJAVA
+%rename (Warp) wrapper_GDALWarpDestDS;
+#endif
+
+/* Note: we must use 2 distinct names due to different ownership of the result */
+
+%inline %{
+int wrapper_GDALWarpDestDS( GDALDatasetShadow* dstDS,
+                            int object_list_count, GDALDatasetShadow** poObjects,
+                            GDALWarpAppOptions* warpAppOptions,
+                            GDALProgressFunc callback=NULL,
+                            void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( warpAppOptions == NULL )
+        {
+            bFreeOptions = true;
+            warpAppOptions = GDALWarpAppOptionsNew(NULL, NULL);
+        }
+        GDALWarpAppOptionsSetProgress(warpAppOptions, callback, callback_data);
+    }
+    int bRet = (GDALWarp(NULL, dstDS, object_list_count, poObjects, warpAppOptions, &usageError) != NULL);
+    if( bFreeOptions )
+        GDALWarpAppOptionsFree(warpAppOptions);
+    return bRet;
+}
+%}
+
+#ifdef SWIGJAVA
+%rename (Warp) wrapper_GDALWarpDestName;
+#endif
+
+%newobject wrapper_GDALWarpDestName;
+
+%inline %{
+GDALDatasetShadow* wrapper_GDALWarpDestName( const char* dest,
+                                             int object_list_count, GDALDatasetShadow** poObjects,
+                                             GDALWarpAppOptions* warpAppOptions,
+                                             GDALProgressFunc callback=NULL,
+                                             void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( warpAppOptions == NULL )
+        {
+            bFreeOptions = true;
+            warpAppOptions = GDALWarpAppOptionsNew(NULL, NULL);
+        }
+        GDALWarpAppOptionsSetProgress(warpAppOptions, callback, callback_data);
+    }
+    GDALDatasetH hDSRet = GDALWarp(dest, NULL, object_list_count, poObjects, warpAppOptions, &usageError);
+    if( bFreeOptions )
+        GDALWarpAppOptionsFree(warpAppOptions);
+    return hDSRet;
+}
+%}
+
+//************************************************************************
+// gdal.VectorTranslate()
+//************************************************************************
+
+#ifdef SWIGJAVA
+%rename (VectorTranslateOptions) GDALVectorTranslateOptions;
+#endif
+struct GDALVectorTranslateOptions {
+%extend {
+    GDALVectorTranslateOptions(char** options) {
+        return GDALVectorTranslateOptionsNew(options, NULL);
+    }
+
+    ~GDALVectorTranslateOptions() {
+        GDALVectorTranslateOptionsFree( self );
+    }
+}
+};
+
+/* Note: we must use 2 distinct names due to different ownership of the result */
+
+#ifdef SWIGJAVA
+%rename (VectorTranslate) wrapper_GDALVectorTranslateDestDS;
+#endif
+
+%inline %{
+int wrapper_GDALVectorTranslateDestDS( GDALDatasetShadow* dstDS,
+                                       GDALDatasetShadow* srcDS,
+                            GDALVectorTranslateOptions* options,
+                            GDALProgressFunc callback=NULL,
+                            void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( options == NULL )
+        {
+            bFreeOptions = true;
+            options = GDALVectorTranslateOptionsNew(NULL, NULL);
+        }
+        GDALVectorTranslateOptionsSetProgress(options, callback, callback_data);
+    }
+    int bRet = (GDALVectorTranslate(NULL, dstDS, 1, &srcDS, options, &usageError) != NULL);
+    if( bFreeOptions )
+        GDALVectorTranslateOptionsFree(options);
+    return bRet;
+}
+%}
+
+#ifdef SWIGJAVA
+%rename (VectorTranslate) wrapper_GDALVectorTranslateDestName;
+#endif
+%newobject wrapper_GDALVectorTranslateDestName;
+
+%inline %{
+GDALDatasetShadow* wrapper_GDALVectorTranslateDestName( const char* dest,
+                                             GDALDatasetShadow* srcDS,
+                                             GDALVectorTranslateOptions* options,
+                                             GDALProgressFunc callback=NULL,
+                                             void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( options == NULL )
+        {
+            bFreeOptions = true;
+            options = GDALVectorTranslateOptionsNew(NULL, NULL);
+        }
+        GDALVectorTranslateOptionsSetProgress(options, callback, callback_data);
+    }
+    GDALDatasetH hDSRet = GDALVectorTranslate(dest, NULL, 1, &srcDS, options, &usageError);
+    if( bFreeOptions )
+        GDALVectorTranslateOptionsFree(options);
+    return hDSRet;
+}
+%}
+
+//************************************************************************
+// gdal.DEMProcessing()
+//************************************************************************
+
+#ifdef SWIGJAVA
+%rename (DEMProcessingOptions) GDALDEMProcessingOptions;
+#endif
+struct GDALDEMProcessingOptions {
+%extend {
+    GDALDEMProcessingOptions(char** options) {
+        return GDALDEMProcessingOptionsNew(options, NULL);
+    }
+
+    ~GDALDEMProcessingOptions() {
+        GDALDEMProcessingOptionsFree( self );
+    }
+}
+};
+
+#ifdef SWIGPYTHON
+%rename (DEMProcessingInternal) wrapper_GDALDEMProcessing;
+#elif defined(SWIGJAVA)
+%rename (DEMProcessing) wrapper_GDALDEMProcessing;
+#endif
+%newobject wrapper_GDALDEMProcessing;
+%apply Pointer NONNULL { const char* pszProcessing };
+
+%inline %{
+GDALDatasetShadow* wrapper_GDALDEMProcessing( const char* dest,
+                                      GDALDatasetShadow* dataset,
+                                      const char* pszProcessing,
+                                      const char* pszColorFilename,
+                                      GDALDEMProcessingOptions* options,
+                                      GDALProgressFunc callback=NULL,
+                                      void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( options == NULL )
+        {
+            bFreeOptions = true;
+            options = GDALDEMProcessingOptionsNew(NULL, NULL);
+        }
+        GDALDEMProcessingOptionsSetProgress(options, callback, callback_data);
+    }
+    GDALDatasetH hDSRet = GDALDEMProcessing(dest, dataset, pszProcessing, pszColorFilename, options, &usageError);
+    if( bFreeOptions )
+        GDALDEMProcessingOptionsFree(options);
+    return hDSRet;
+}
+%}
+
+//************************************************************************
+// gdal.NearBlack()
+//************************************************************************
+
+#ifdef SWIGJAVA
+%rename (NearblackOptions) GDALNearblackOptions;
+#endif
+struct GDALNearblackOptions {
+%extend {
+    GDALNearblackOptions(char** options) {
+        return GDALNearblackOptionsNew(options, NULL);
+    }
+
+    ~GDALNearblackOptions() {
+        GDALNearblackOptionsFree( self );
+    }
+}
+};
+
+/* Note: we must use 2 distinct names due to different ownership of the result */
+
+#ifdef SWIGJAVA
+%rename (Nearblack) wrapper_GDALNearblackDestDS;
+#endif
+%inline %{
+int wrapper_GDALNearblackDestDS( GDALDatasetShadow* dstDS,
+                            GDALDatasetShadow* srcDS,
+                            GDALNearblackOptions* options,
+                            GDALProgressFunc callback=NULL,
+                            void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( options == NULL )
+        {
+            bFreeOptions = true;
+            options = GDALNearblackOptionsNew(NULL, NULL);
+        }
+        GDALNearblackOptionsSetProgress(options, callback, callback_data);
+    }
+    int bRet = (GDALNearblack(NULL, dstDS, srcDS, options, &usageError) != NULL);
+    if( bFreeOptions )
+        GDALNearblackOptionsFree(options);
+    return bRet;
+}
+%}
+
+#ifdef SWIGJAVA
+%rename (Nearblack) wrapper_GDALNearblackDestName;
+#endif
+%newobject wrapper_GDALNearblackDestName;
+
+%inline %{
+GDALDatasetShadow* wrapper_GDALNearblackDestName( const char* dest,
+                                             GDALDatasetShadow* srcDS,
+                                             GDALNearblackOptions* options,
+                                             GDALProgressFunc callback=NULL,
+                                             void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( options == NULL )
+        {
+            bFreeOptions = true;
+            options = GDALNearblackOptionsNew(NULL, NULL);
+        }
+        GDALNearblackOptionsSetProgress(options, callback, callback_data);
+    }
+    GDALDatasetH hDSRet = GDALNearblack(dest, NULL, srcDS, options, &usageError);
+    if( bFreeOptions )
+        GDALNearblackOptionsFree(options);
+    return hDSRet;
+}
+%}
+
+//************************************************************************
+// gdal.Grid()
+//************************************************************************
+
+#ifdef SWIGJAVA
+%rename (GridOptions) GDALGridOptions;
+#endif
+struct GDALGridOptions {
+%extend {
+    GDALGridOptions(char** options) {
+        return GDALGridOptionsNew(options, NULL);
+    }
+
+    ~GDALGridOptions() {
+        GDALGridOptionsFree( self );
+    }
+}
+};
+
+#ifdef SWIGPYTHON
+%rename (GridInternal) wrapper_GDALGrid;
+#elif defined(SWIGJAVA)
+%rename (Grid) wrapper_GDALGrid;
+#endif
+%newobject wrapper_GDALGrid;
+
+%inline %{
+GDALDatasetShadow* wrapper_GDALGrid( const char* dest,
+                                      GDALDatasetShadow* dataset,
+                                      GDALGridOptions* options,
+                                      GDALProgressFunc callback=NULL,
+                                      void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( options == NULL )
+        {
+            bFreeOptions = true;
+            options = GDALGridOptionsNew(NULL, NULL);
+        }
+        GDALGridOptionsSetProgress(options, callback, callback_data);
+    }
+    GDALDatasetH hDSRet = GDALGrid(dest, dataset, options, &usageError);
+    if( bFreeOptions )
+        GDALGridOptionsFree(options);
+    return hDSRet;
+}
+%}
+
+//************************************************************************
+// gdal.Rasterize()
+//************************************************************************
+
+#ifdef SWIGJAVA
+%rename (RasterizeOptions) GDALRasterizeOptions;
+#endif
+struct GDALRasterizeOptions {
+%extend {
+    GDALRasterizeOptions(char** options) {
+        return GDALRasterizeOptionsNew(options, NULL);
+    }
+
+    ~GDALRasterizeOptions() {
+        GDALRasterizeOptionsFree( self );
+    }
+}
+};
+
+/* Note: we must use 2 distinct names due to different ownership of the result */
+
+#ifdef SWIGJAVA
+%rename (Rasterize) wrapper_GDALRasterizeDestDS;
+#endif
+%inline %{
+int wrapper_GDALRasterizeDestDS( GDALDatasetShadow* dstDS,
+                            GDALDatasetShadow* srcDS,
+                            GDALRasterizeOptions* options,
+                            GDALProgressFunc callback=NULL,
+                            void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( options == NULL )
+        {
+            bFreeOptions = true;
+            options = GDALRasterizeOptionsNew(NULL, NULL);
+        }
+        GDALRasterizeOptionsSetProgress(options, callback, callback_data);
+    }
+    int bRet = (GDALRasterize(NULL, dstDS, srcDS, options, &usageError) != NULL);
+    if( bFreeOptions )
+        GDALRasterizeOptionsFree(options);
+    return bRet;
+}
+%}
+
+#ifdef SWIGJAVA
+%rename (Rasterize) wrapper_GDALRasterizeDestName;
+#endif
+%newobject wrapper_GDALRasterizeDestName;
+
+%inline %{
+GDALDatasetShadow* wrapper_GDALRasterizeDestName( const char* dest,
+                                             GDALDatasetShadow* srcDS,
+                                             GDALRasterizeOptions* options,
+                                             GDALProgressFunc callback=NULL,
+                                             void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( options == NULL )
+        {
+            bFreeOptions = true;
+            options = GDALRasterizeOptionsNew(NULL, NULL);
+        }
+        GDALRasterizeOptionsSetProgress(options, callback, callback_data);
+    }
+    GDALDatasetH hDSRet = GDALRasterize(dest, NULL, srcDS, options, &usageError);
+    if( bFreeOptions )
+        GDALRasterizeOptionsFree(options);
+    return hDSRet;
+}
+%}
+
+//************************************************************************
+// gdal.BuildVRT()
+//************************************************************************
+
+#ifdef SWIGJAVA
+%rename (BuildVRTOptions) GDALBuildVRTOptions;
+#endif
+struct GDALBuildVRTOptions {
+%extend {
+    GDALBuildVRTOptions(char** options) {
+        return GDALBuildVRTOptionsNew(options, NULL);
+    }
+
+    ~GDALBuildVRTOptions() {
+        GDALBuildVRTOptionsFree( self );
+    }
+}
+};
+
+#ifdef SWIGPYTHON
+%rename (BuildVRTInternalObjects) wrapper_GDALBuildVRT_objects;
+#elif defined(SWIGJAVA)
+%rename (BuildVRT) wrapper_GDALBuildVRT_objects;
+#endif
+
+%newobject wrapper_GDALBuildVRT_objects;
+
+%inline %{
+GDALDatasetShadow* wrapper_GDALBuildVRT_objects( const char* dest,
+                                             int object_list_count, GDALDatasetShadow** poObjects,
+                                             GDALBuildVRTOptions* options,
+                                             GDALProgressFunc callback=NULL,
+                                             void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( options == NULL )
+        {
+            bFreeOptions = true;
+            options = GDALBuildVRTOptionsNew(NULL, NULL);
+        }
+        GDALBuildVRTOptionsSetProgress(options, callback, callback_data);
+    }
+    GDALDatasetH hDSRet = GDALBuildVRT(dest, object_list_count, poObjects, NULL, options, &usageError);
+    if( bFreeOptions )
+        GDALBuildVRTOptionsFree(options);
+    return hDSRet;
+}
+%}
+
+
+#ifdef SWIGPYTHON
+%rename (BuildVRTInternalNames) wrapper_GDALBuildVRT_names;
+#elif defined(SWIGJAVA)
+%rename (BuildVRT) wrapper_GDALBuildVRT_names;
+#endif
+
+%newobject wrapper_GDALBuildVRT_names;
+%apply (char **options) {char** source_filenames};
+%inline %{
+GDALDatasetShadow* wrapper_GDALBuildVRT_names( const char* dest,
+                                         char ** source_filenames,
+                                         GDALBuildVRTOptions* options,
+                                         GDALProgressFunc callback=NULL,
+                                         void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( options == NULL )
+        {
+            bFreeOptions = true;
+            options = GDALBuildVRTOptionsNew(NULL, NULL);
+        }
+        GDALBuildVRTOptionsSetProgress(options, callback, callback_data);
+    }
+    GDALDatasetH hDSRet = GDALBuildVRT(dest, CSLCount(source_filenames), NULL, source_filenames, options, &usageError);
+    if( bFreeOptions )
+        GDALBuildVRTOptionsFree(options);
+    return hDSRet;
+}
+%}
+%clear char** source_filenames;
+
+
+%clear (const char* dest);
diff --git a/swig/include/gdal_array.i b/swig/include/gdal_array.i
index 2c67f92..d076853 100644
--- a/swig/include/gdal_array.i
+++ b/swig/include/gdal_array.i
@@ -1,1285 +1,1332 @@
-/******************************************************************************
- * $Id: gdal_array.i 29330 2015-06-14 12:11:11Z rouault $
- *
- * Name:     gdal_array.i
- * Project:  GDAL Python Interface
- * Purpose:  GDAL / Numpy interface
- * Author:   Frank Warmerdam, warmerda at home.com
- *
- ******************************************************************************
- * Copyright (c) 2000, Frank Warmerdam
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *****************************************************************************/
- 
-%feature("autodoc");
-
-%module gdal_array
-
-%include constraints.i
-
-%import typemaps_python.i
-
-%import MajorObject.i
-%import Band.i
-%import Dataset.i
-%import RasterAttributeTable.i
-
-%include "cplvirtualmem.i"
-
-%init %{
-  import_array();
-  GDALRegister_NUMPY();
-%}
-
-typedef int CPLErr;
-typedef int GDALRIOResampleAlg;
-
-%include "python_strings.i"
-
-
-%{
-#include "gdal_priv.h"
-#ifdef _DEBUG
-#undef _DEBUG
-#include "Python.h"
-#define _DEBUG
-#else
-#include "Python.h"
-#endif
-#include "numpy/arrayobject.h"
-
-#ifdef DEBUG 
-typedef struct GDALRasterBandHS GDALRasterBandShadow;
-typedef struct GDALDatasetHS GDALDatasetShadow;
-typedef struct RasterAttributeTableHS GDALRasterAttributeTableShadow;
-#else
-typedef void GDALRasterBandShadow;
-typedef void GDALDatasetShadow;
-typedef void GDALRasterAttributeTableShadow;
-#endif
-
-CPL_C_START
-
-GDALRasterBandH CPL_DLL MEMCreateRasterBand( GDALDataset *, int, GByte *,
-                                             GDALDataType, int, int, int );
-CPL_C_END
-
-typedef char retStringAndCPLFree;
-
-class NUMPYDataset : public GDALDataset
-{
-    PyArrayObject *psArray;
-
-    int           bValidGeoTransform;
-    double	  adfGeoTransform[6];
-    char	  *pszProjection;
-
-    int           nGCPCount;
-    GDAL_GCP      *pasGCPList;
-    char          *pszGCPProjection;
-
-  public:
-                 NUMPYDataset();
-                 ~NUMPYDataset();
-
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr SetProjection( const char * );
-    virtual CPLErr GetGeoTransform( double * );
-    virtual CPLErr SetGeoTransform( double * );
-
-    virtual int    GetGCPCount();
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
-    virtual CPLErr SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
-                            const char *pszGCPProjection );
-
-    static GDALDataset *Open( GDALOpenInfo * );
-};
-
-
-
-/************************************************************************/
-/*                          GDALRegister_NUMPY()                        */
-/************************************************************************/
-   
-static void GDALRegister_NUMPY(void)
-
-{
-    GDALDriver	*poDriver;
-    if (! GDAL_CHECK_VERSION("NUMPY driver"))
-        return;
-    if( GDALGetDriverByName( "NUMPY" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "NUMPY" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Numeric Python Array" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        
-        poDriver->pfnOpen = NUMPYDataset::Open;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-
-    }
-}
-
-/************************************************************************/
-/*                            NUMPYDataset()                            */
-/************************************************************************/
-
-NUMPYDataset::NUMPYDataset()
-
-{
-    pszProjection = CPLStrdup("");
-    bValidGeoTransform = FALSE;
-    adfGeoTransform[0] = 0.0;
-    adfGeoTransform[1] = 1.0;
-    adfGeoTransform[2] = 0.0;
-    adfGeoTransform[3] = 0.0;
-    adfGeoTransform[4] = 0.0;
-    adfGeoTransform[5] = 1.0;
-
-    nGCPCount = 0;
-    pasGCPList = NULL;
-    pszGCPProjection = CPLStrdup("");
-}
-
-/************************************************************************/
-/*                            ~NUMPYDataset()                            */
-/************************************************************************/
-
-NUMPYDataset::~NUMPYDataset()
-
-{
-    CPLFree( pszProjection );
-
-    CPLFree( pszGCPProjection );
-    if( nGCPCount > 0 )
-    {
-        GDALDeinitGCPs( nGCPCount, pasGCPList );
-        CPLFree( pasGCPList );
-    }
-
-    FlushCache();
-    Py_DECREF( psArray );
-}
-
-/************************************************************************/
-/*                          GetProjectionRef()                          */
-/************************************************************************/
-
-const char *NUMPYDataset::GetProjectionRef()
-
-{
-    return( pszProjection );
-}
-
-/************************************************************************/
-/*                           SetProjection()                            */
-/************************************************************************/
-
-CPLErr NUMPYDataset::SetProjection( const char * pszNewProjection )
-
-{
-    CPLFree( pszProjection );
-    pszProjection = CPLStrdup( pszNewProjection );
-
-    return CE_None;
-}
-
-/************************************************************************/
-/*                          GetGeoTransform()                           */
-/************************************************************************/
-
-CPLErr NUMPYDataset::GetGeoTransform( double * padfTransform )
-
-{
-    memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
-    if( bValidGeoTransform )
-        return CE_None;
-    else
-        return CE_Failure;
-}
-
-/************************************************************************/
-/*                          SetGeoTransform()                           */
-/************************************************************************/
-
-CPLErr NUMPYDataset::SetGeoTransform( double * padfTransform )
-
-{
-    bValidGeoTransform = TRUE;
-    memcpy( adfGeoTransform, padfTransform, sizeof(double)*6 );
-    return( CE_None );
-}
-
-/************************************************************************/
-/*                            GetGCPCount()                             */
-/************************************************************************/
-
-int NUMPYDataset::GetGCPCount()
-
-{
-    return nGCPCount;
-}
-
-/************************************************************************/
-/*                          GetGCPProjection()                          */
-/************************************************************************/
-
-const char *NUMPYDataset::GetGCPProjection()
-
-{
-    return pszGCPProjection;
-}
-
-/************************************************************************/
-/*                               GetGCPs()                              */
-/************************************************************************/
-
-const GDAL_GCP *NUMPYDataset::GetGCPs()
-
-{
-    return pasGCPList;
-}
-
-/************************************************************************/
-/*                              SetGCPs()                               */
-/************************************************************************/
-
-CPLErr NUMPYDataset::SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
-                              const char *pszGCPProjection )
-
-{
-    CPLFree( this->pszGCPProjection );
-    if( this->nGCPCount > 0 )
-    {
-        GDALDeinitGCPs( this->nGCPCount, this->pasGCPList );
-        CPLFree( this->pasGCPList );
-    }
-
-    this->pszGCPProjection = CPLStrdup(pszGCPProjection);
-
-    this->nGCPCount = nGCPCount;
-
-    this->pasGCPList = GDALDuplicateGCPs( nGCPCount, pasGCPList );
-
-    return CE_None;
-}
-
-/************************************************************************/
-/*                                Open()                                */
-/************************************************************************/
-
-GDALDataset *NUMPYDataset::Open( GDALOpenInfo * poOpenInfo )
-
-{
-    PyArrayObject *psArray;
-    GDALDataType  eType;
-    int     nBands;
-
-/* -------------------------------------------------------------------- */
-/*      Is this a numpy dataset name?                                   */
-/* -------------------------------------------------------------------- */
-    if( !EQUALN(poOpenInfo->pszFilename,"NUMPY:::",8) 
-        || poOpenInfo->fpL != NULL )
-        return NULL;
-
-    psArray = NULL;
-    sscanf( poOpenInfo->pszFilename+8, "%p", &(psArray) );
-    if( psArray == NULL )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Failed to parse meaningful pointer value from NUMPY name\n"
-                  "string: %s\n", 
-                  poOpenInfo->pszFilename );
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      If we likely have corrupt definitions of the NUMPY stuff,       */
-/*      then warn now.                                                  */
-/* -------------------------------------------------------------------- */
-#ifdef NUMPY_DEFS_WRONG
-    CPLError( CE_Warning, CPLE_AppDefined, 
-              "It would appear you have built GDAL without having it use\n"
-              "the Numeric python include files.  Old definitions have\n"
-              "been used instead at build time, and it is quite possible that\n"
-              "the things will shortly fail or crash if they are wrong.\n"
-              "Consider installing Numeric, and rebuilding with HAVE_NUMPY\n"
-              "enabled in gdal\nmake.opt." );
-#endif
-
-/* -------------------------------------------------------------------- */
-/*      Is this a directly mappable Python array?  Verify rank, and     */
-/*      data type.                                                      */
-/* -------------------------------------------------------------------- */
-
-    if( psArray->nd < 2 || psArray->nd > 3 )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Illegal numpy array rank %d.\n", 
-                  psArray->nd );
-        return NULL;
-    }
-
-    switch( psArray->descr->type_num )
-    {
-      case NPY_CDOUBLE:
-        eType = GDT_CFloat64;
-        break;
-
-      case NPY_CFLOAT:
-        eType = GDT_CFloat32;
-        break;
-
-      case NPY_DOUBLE:
-        eType = GDT_Float64;
-        break;
-
-      case NPY_FLOAT:
-        eType = GDT_Float32;
-        break;
-
-      case NPY_INT:
-      case NPY_LONG:
-        eType = GDT_Int32;
-        break;
-
-      case NPY_UINT:
-      case NPY_ULONG:
-        eType = GDT_UInt32;
-        break;
-
-      case NPY_SHORT:
-        eType = GDT_Int16;
-        break;
-
-      case NPY_USHORT:
-        eType = GDT_UInt16;
-        break;
-
-      case NPY_BYTE:
-      case NPY_UBYTE:
-        eType = GDT_Byte;
-        break;
-
-      default:
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Unable to access numpy arrays of typecode `%c'.\n", 
-                  psArray->descr->type );
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Create the new NUMPYDataset object.                             */
-/* -------------------------------------------------------------------- */
-    NUMPYDataset *poDS;
-
-    poDS = new NUMPYDataset();
-
-    poDS->psArray = psArray;
-
-    poDS->eAccess = GA_ReadOnly;
-
-/* -------------------------------------------------------------------- */
-/*      Add a reference to the array.                                   */
-/* -------------------------------------------------------------------- */
-    Py_INCREF( psArray );
-
-/* -------------------------------------------------------------------- */
-/*      Workout the data layout.                                        */
-/* -------------------------------------------------------------------- */
-    int    nBandOffset;
-    int    nPixelOffset;
-    int    nLineOffset;
-
-    if( psArray->nd == 3 )
-    {
-        nBands = psArray->dimensions[0];
-        nBandOffset = psArray->strides[0];
-        poDS->nRasterXSize = psArray->dimensions[2];
-        nPixelOffset = psArray->strides[2];
-        poDS->nRasterYSize = psArray->dimensions[1];
-        nLineOffset = psArray->strides[1];
-    }
-    else
-    {
-        nBands = 1;
-        nBandOffset = 0;
-        poDS->nRasterXSize = psArray->dimensions[1];
-        nPixelOffset = psArray->strides[1];
-        poDS->nRasterYSize = psArray->dimensions[0];
-        nLineOffset = psArray->strides[0];
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Create band information objects.                                */
-/* -------------------------------------------------------------------- */
-    for( int iBand = 0; iBand < nBands; iBand++ )
-    {
-        poDS->SetBand( iBand+1, 
-                       (GDALRasterBand *) 
-                       MEMCreateRasterBand( poDS, iBand+1, 
-                                (GByte *) psArray->data + nBandOffset*iBand,
-                                          eType, nPixelOffset, nLineOffset,
-                                          FALSE ) );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Try to return a regular handle on the file.                     */
-/* -------------------------------------------------------------------- */
-    return poDS;
-}
-
-%}
-
-// So that SWIGTYPE_p_f_double_p_q_const__char_p_void__int is declared...
-/************************************************************************/
-/*                            TermProgress()                            */
-/************************************************************************/
-
-%rename (TermProgress_nocb) GDALTermProgress_nocb;
-%feature( "kwargs" ) GDALTermProgress_nocb;
-%inline %{
-int GDALTermProgress_nocb( double dfProgress, const char * pszMessage=NULL, void *pData=NULL ) {
-  return GDALTermProgress( dfProgress, pszMessage, pData);
-}
-%}
-
-%rename (TermProgress) GDALTermProgress;
-%callback("%s");
-int GDALTermProgress( double, const char *, void * );
-%nocallback;
-
-%include "callback.i"
-
-%typemap(in,numinputs=1) (PyArrayObject *psArray)
-{
-  /* %typemap(in,numinputs=1) (PyArrayObject  *psArray) */
-  if ($input != NULL && PyArray_Check($input))
-  {
-      $1 = (PyArrayObject*)($input);
-  }
-  else
-  {
-      PyErr_SetString(PyExc_TypeError, "not a numpy array");
-      SWIG_fail;
-  }
-}
-
-%inline %{
-retStringAndCPLFree* GetArrayFilename(PyArrayObject *psArray)
-{
-    char      szString[128];
-    
-    GDALRegister_NUMPY();
-    
-    /* I wish I had a safe way of checking the type */        
-    sprintf( szString, "NUMPY:::%p", psArray );
-    return CPLStrdup(szString);
-}
-%}
-
-%feature( "kwargs" ) BandRasterIONumPy;
-%inline %{
-  CPLErr BandRasterIONumPy( GDALRasterBandShadow* band, int bWrite, int xoff, int yoff, int xsize, int ysize,
-                            PyArrayObject *psArray,
-                            int buf_type,
-                            GDALRIOResampleAlg resample_alg,
-                            GDALProgressFunc callback = NULL,
-                            void* callback_data = NULL) {
-
-    GDALDataType ntype  = (GDALDataType)buf_type;
-    if( psArray->nd < 2 || psArray->nd > 3 )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Illegal numpy array rank %d.\n", 
-                  psArray->nd );
-        return CE_Failure;
-    }
-
-    int xdim = ( psArray->nd == 2) ? 1 : 2;
-    int ydim = ( psArray->nd == 2) ? 0 : 1;
-
-    int nxsize, nysize, pixel_space, line_space;
-    nxsize = psArray->dimensions[xdim];
-    nysize = psArray->dimensions[ydim];
-    pixel_space = psArray->strides[xdim];
-    line_space = psArray->strides[ydim];
-
-    GDALRasterIOExtraArg sExtraArg;
-    INIT_RASTERIO_EXTRA_ARG(sExtraArg);
-    sExtraArg.eResampleAlg = resample_alg;
-    sExtraArg.pfnProgress = callback;
-    sExtraArg.pProgressData = callback_data;
-
-    return  GDALRasterIOEx( band, (bWrite) ? GF_Write : GF_Read, xoff, yoff, xsize, ysize,
-                          psArray->data, nxsize, nysize,
-                          ntype, pixel_space, line_space, &sExtraArg );
-  }
-%}
-
-%feature( "kwargs" ) DatasetIONumPy;
-%inline %{
-  CPLErr DatasetIONumPy( GDALDatasetShadow* ds, int bWrite, int xoff, int yoff, int xsize, int ysize,
-                         PyArrayObject *psArray,
-                         int buf_type,
-                         GDALRIOResampleAlg resample_alg,
-                         GDALProgressFunc callback = NULL,
-                         void* callback_data = NULL )
-{
-    GDALDataType ntype  = (GDALDataType)buf_type;
-    if( psArray->nd != 3 )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Illegal numpy array rank %d.", 
-                  psArray->nd );
-        return CE_Failure;
-    }
-
-    int xdim = 2;
-    int ydim = 1;
-
-    int bandsize, nxsize, nysize;
-    GIntBig pixel_space, line_space, band_space;
-    nxsize = psArray->dimensions[xdim];
-    nysize = psArray->dimensions[ydim];
-    bandsize = psArray->dimensions[0];
-    if( bandsize != GDALGetRasterCount(ds) )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Illegal numpy array band dimension %d. Expected value: %d", 
-                  bandsize, GDALGetRasterCount(ds) );
-        return CE_Failure;
-    }
-    pixel_space = psArray->strides[xdim];
-    line_space = psArray->strides[ydim];
-    band_space = psArray->strides[0];
-
-    GDALRasterIOExtraArg sExtraArg;
-    INIT_RASTERIO_EXTRA_ARG(sExtraArg);
-    sExtraArg.eResampleAlg = resample_alg;
-    sExtraArg.pfnProgress = callback;
-    sExtraArg.pProgressData = callback_data;
-
-    return  GDALDatasetRasterIOEx( ds, (bWrite) ? GF_Write : GF_Read, xoff, yoff, xsize, ysize,
-                                   psArray->data, nxsize, nysize,
-                                   ntype,
-                                   bandsize, NULL,
-                                   pixel_space, line_space, band_space, &sExtraArg );
-  }
-%}
-
-%typemap(in,numinputs=0) (CPLVirtualMemShadow** pvirtualmem, int numpytypemap) (CPLVirtualMemShadow* virtualmem)
-{
-  $1 = &virtualmem;
-  $2 = 0;
-}
-
-%typemap(argout) (CPLVirtualMemShadow** pvirtualmem, int numpytypemap)
-{
-    CPLVirtualMemShadow* virtualmem = *($1);
-    void* ptr = CPLVirtualMemGetAddr( virtualmem->vmem );
-    /*size_t nsize = CPLVirtualMemGetSize( virtualmem->vmem );*/
-    GDALDataType datatype = virtualmem->eBufType;
-    int readonly = virtualmem->bReadOnly;
-    GIntBig nBufXSize = virtualmem->nBufXSize;
-    GIntBig nBufYSize = virtualmem->nBufYSize;
-    int nBandCount = virtualmem->nBandCount;
-    int bIsBandSequential = virtualmem->bIsBandSequential;
-    GDALTileOrganization eTileOrganization = virtualmem->eTileOrganization;
-    int nTileXSize = virtualmem->nTileXSize;
-    int nTileYSize = virtualmem->nTileYSize;
-    int bAuto = virtualmem->bAuto;
-    int            nPixelSpace = virtualmem->nPixelSpace; /* if bAuto == TRUE */
-    GIntBig        nLineSpace = virtualmem->nLineSpace; /* if bAuto == TRUE */
-    int numpytype;
-
-    if( datatype == GDT_CInt16 || datatype == GDT_CInt32 )
-    {
-        PyErr_SetString( PyExc_RuntimeError, "GDT_CInt16 and GDT_CInt32 not supported for now" );
-        SWIG_fail;
-    }
-
-    switch(datatype)
-    {
-        case GDT_Byte: numpytype = NPY_UBYTE; break;
-        case GDT_Int16: numpytype = NPY_INT16; break;
-        case GDT_UInt16: numpytype = NPY_UINT16; break;
-        case GDT_Int32: numpytype = NPY_INT32; break;
-        case GDT_UInt32: numpytype = NPY_UINT32; break;
-        case GDT_Float32: numpytype = NPY_FLOAT32; break;
-        case GDT_Float64: numpytype = NPY_FLOAT64; break;
-        //case GDT_CInt16: numpytype = NPY_INT16; break;
-        //case GDT_CInt32: numpytype = NPY_INT32; break;
-        case GDT_CFloat32: numpytype = NPY_CFLOAT; break;
-        case GDT_CFloat64: numpytype = NPY_CDOUBLE; break;
-        default: numpytype = NPY_UBYTE; break;
-    }
-    PyArrayObject* ar;
-    int flags = (readonly) ? 0x1 : 0x1 | 0x0400;
-    int nDataTypeSize = GDALGetDataTypeSize(datatype) / 8;
-    if( bAuto )
-    {
-        if( nBandCount == 1 )
-        {
-            npy_intp shape[2], stride[2];
-            shape[0] = nBufYSize;
-            shape[1] = nBufXSize;
-            stride[1] = nPixelSpace;
-            stride[0] = nLineSpace;
-            ar = (PyArrayObject*) PyArray_New(&PyArray_Type, 2, shape,
-                    numpytype, stride, ptr, 0, flags , NULL);
-        }
-        else
-        {
-            PyErr_SetString( PyExc_RuntimeError, "Code update needed for bAuto and nBandCount > 1 !" );
-            SWIG_fail;
-        }
-    }
-    else if( bIsBandSequential >= 0 )
-    {
-        if( nBandCount == 1 )
-        {
-            npy_intp shape[2], stride[2];
-            shape[0] = nBufYSize;
-            shape[1] = nBufXSize;
-            stride[1] = nDataTypeSize;
-            stride[0] = stride[1] * nBufXSize;
-            ar = (PyArrayObject*) PyArray_New(&PyArray_Type, 2, shape,
-                    numpytype, stride, ptr, 0, flags , NULL);
-        }
-        else
-        {
-            npy_intp shape[3], stride[3];
-            if( bIsBandSequential )
-            {
-                shape[0] = nBandCount;
-                shape[1] = nBufYSize;
-                shape[2] = nBufXSize;
-                stride[2] = nDataTypeSize;
-                stride[1] = stride[2] * nBufXSize;
-                stride[0] = stride[1] * nBufYSize;
-            }
-            else
-            {
-                shape[0] = nBufYSize;
-                shape[1] = nBufXSize;
-                shape[2] = nBandCount;
-                stride[2] = nDataTypeSize;
-                stride[1] = stride[2] * nBandCount;
-                stride[0] = stride[1] * nBufXSize;
-            }
-            ar = (PyArrayObject*) PyArray_New(&PyArray_Type, 3, shape,
-                    numpytype, stride, ptr, 0, flags , NULL);
-        }
-    }
-    else
-    {
-        int nTilesPerRow = (nBufXSize + nTileXSize - 1) / nTileXSize;
-        int nTilesPerCol = (nBufYSize + nTileYSize - 1) / nTileYSize;
-        npy_intp shape[5], stride[5];
-        if( nBandCount == 1 )
-        {
-            shape[0] = nTilesPerCol;
-            shape[1] = nTilesPerRow;
-            shape[2] = nTileYSize;
-            shape[3] = nTileXSize;
-            stride[3] = nDataTypeSize;
-            stride[2] = stride[3] * nTileXSize;
-            stride[1] = stride[2] * nTileYSize;
-            stride[0] = stride[1] * nTilesPerRow;
-            ar = (PyArrayObject*) PyArray_New(&PyArray_Type, 4, shape,
-                    numpytype, stride, ptr, 0, flags , NULL);
-        }
-        else if( eTileOrganization == GTO_TIP )
-        {
-            shape[0] = nTilesPerCol;
-            shape[1] = nTilesPerRow;
-            shape[2] = nTileYSize;
-            shape[3] = nTileXSize;
-            shape[4] = nBandCount;
-            stride[4] = nDataTypeSize;
-            stride[3] = stride[4] * nBandCount;
-            stride[2] = stride[3] * nTileXSize;
-            stride[1] = stride[2] * nTileYSize;
-            stride[0] = stride[1] * nTilesPerRow;
-            ar = (PyArrayObject*) PyArray_New(&PyArray_Type, 5, shape,
-                    numpytype, stride, ptr, 0, flags , NULL);
-        }
-        else if( eTileOrganization == GTO_BIT )
-        {
-            shape[0] = nTilesPerCol;
-            shape[1] = nTilesPerRow;
-            shape[2] = nBandCount;
-            shape[3] = nTileYSize;
-            shape[4] = nTileXSize;
-            stride[4] = nDataTypeSize;
-            stride[3] = stride[4] * nTileXSize;
-            stride[2] = stride[3] * nTileYSize;
-            stride[1] = stride[2] * nBandCount;
-            stride[0] = stride[1] * nTilesPerRow;
-            ar = (PyArrayObject*) PyArray_New(&PyArray_Type, 5, shape,
-                    numpytype, stride, ptr, 0, flags , NULL);
-        }
-        else /* GTO_BSQ */
-        {
-            shape[0] = nBandCount;
-            shape[1] = nTilesPerCol;
-            shape[2] = nTilesPerRow;
-            shape[3] = nTileYSize;
-            shape[4] = nTileXSize;
-            stride[4] = nDataTypeSize;
-            stride[3] = stride[4] * nTileXSize;
-            stride[2] = stride[3] * nTileYSize;
-            stride[1] = stride[2] * nTilesPerRow;
-            stride[0] = stride[1] * nTilesPerCol;
-            ar = (PyArrayObject*) PyArray_New(&PyArray_Type, 5, shape,
-                    numpytype, stride, ptr, 0, flags , NULL);
-        }
-    }
-
-    /* Keep a reference to the VirtualMem object */
-    ar->base = obj0;
-    Py_INCREF(obj0);
-    $result = (PyObject*) ar;
-}
-
-%apply Pointer NONNULL {CPLVirtualMemShadow* virtualmem};
-%inline %{
-    void VirtualMemGetArray(CPLVirtualMemShadow* virtualmem, CPLVirtualMemShadow** pvirtualmem, int numpytypemap)
-    {
-        *pvirtualmem = virtualmem;
-    }
-%}
-%clear CPLVirtualMemShadow* virtualmem;
-
-%feature( "kwargs" ) RATValuesIONumPyWrite;
-%inline %{
-  // need different functions for read and write
-  // since reading strings requires us to know the 
-  // length of the longest string before creating array
-  CPLErr RATValuesIONumPyWrite( GDALRasterAttributeTableShadow* poRAT, int nField, int nStart, 
-                       PyArrayObject *psArray) {
-
-    if( PyArray_NDIM(psArray) != 1 )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Illegal numpy array rank %d.\n", 
-                  PyArray_NDIM(psArray) );
-        return CE_Failure;
-    }
-
-    int nLength = PyArray_DIM(psArray, 0);
-    int nType = PyArray_TYPE(psArray);
-    CPLErr retval = CE_None;
-
-    if( nType == NPY_INT32 )
-    {
-        retval = GDALRATValuesIOAsInteger(poRAT, GF_Write, nField, nStart, nLength, 
-                        (int*)PyArray_DATA(psArray) );
-    }
-    else if( nType == NPY_DOUBLE )
-    {
-        retval = GDALRATValuesIOAsDouble(poRAT, GF_Write, nField, nStart, nLength,
-                        (double*)PyArray_DATA(psArray) );
-    }
-    else if( nType == NPY_STRING )
-    {
-        // have to convert array of strings to a char **
-        char **papszStringData = (char**)CPLCalloc(sizeof(char*), nLength);
-
-        // max size of string
-        int nMaxLen = PyArray_ITEMSIZE(psArray);
-        char *pszBuffer = (char*)CPLMalloc((nMaxLen+1) * sizeof(char));
-        // make sure there is a null char on the end
-        // as there won't be if this string is the maximum size
-        pszBuffer[nMaxLen] = '\0';
-
-        // we can't just use the memory location in the array 
-        // since long strings won't be null terminated
-        for( int i = 0; i < nLength; i++ )
-        {
-            strncpy(pszBuffer, (char*)PyArray_GETPTR1(psArray, i), nMaxLen);
-            papszStringData[i] = CPLStrdup(pszBuffer);
-        }
-        CPLFree(pszBuffer);
-
-        retval = GDALRATValuesIOAsString(poRAT, GF_Write, nField, nStart, nLength,
-                                            papszStringData);
-
-        for( int i = 0; i < nLength; i++ )
-        {
-            CPLFree(papszStringData[i]);
-        }
-        CPLFree(papszStringData);
-    }
-    else
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Illegal numpy array type %d.\n", 
-                  nType );
-        return CE_Failure;
-    }
-    return retval;
-  }
-%}
-
-%feature( "kwargs" ) RATValuesIONumPyRead;
-%inline %{
-  // need different functions for read and write
-  // since reading strings requires us to know the 
-  // length of the longest string before creating array
-  PyObject *RATValuesIONumPyRead( GDALRasterAttributeTableShadow* poRAT, int nField, int nStart, 
-                       int nLength) {
-
-    GDALRATFieldType colType = GDALRATGetTypeOfCol(poRAT, nField);
-    npy_intp dims = nLength;
-    PyObject *pOutArray = NULL;
-    if( colType == GFT_Integer )
-    {
-        pOutArray = PyArray_SimpleNew(1, &dims, NPY_INT32);
-        if( GDALRATValuesIOAsInteger(poRAT, GF_Read, nField, nStart, nLength, 
-                        (int*)PyArray_DATA(pOutArray)) != CE_None)
-        {
-            Py_DECREF(pOutArray);
-            Py_RETURN_NONE;
-        }
-    }
-    else if( colType == GFT_Real )
-    {
-        pOutArray = PyArray_SimpleNew(1, &dims, NPY_DOUBLE);
-        if( GDALRATValuesIOAsDouble(poRAT, GF_Read, nField, nStart, nLength,
-                        (double*)PyArray_DATA(pOutArray)) != CE_None)
-        {
-            Py_DECREF(pOutArray);
-            Py_RETURN_NONE;
-        }
-    }
-    else if( colType == GFT_String )
-    {
-        // must read the data first to work out max size
-        // of strings to create array
-        int n;
-        char **papszStringList = (char**)CPLCalloc(sizeof(char*), nLength);
-        if( GDALRATValuesIOAsString(poRAT, GF_Read, nField, nStart, nLength, papszStringList) != CE_None )
-        {
-            CPLFree(papszStringList);
-            Py_RETURN_NONE;
-        }
-        int nMaxLen = 0, nLen;
-        for( n = 0; n < nLength; n++ )
-        {
-            // note strlen doesn't include null char
-            // but that is what numpy expects so all good
-            nLen = strlen(papszStringList[n]);
-            if( nLen > nMaxLen )
-                nMaxLen = nLen;
-        }
-        int bZeroLength = FALSE;
-        // numpy can't deal with zero length strings
-        if( nMaxLen == 0 )
-        {
-            nMaxLen = 1;
-            bZeroLength = TRUE;
-        }
-
-        // create the dtype string
-#if PY_VERSION_HEX >= 0x03000000
-        PyObject *pDTypeString = PyUnicode_FromFormat("S%d", nMaxLen);
-#else
-        PyObject *pDTypeString = PyString_FromFormat("S%d", nMaxLen);
-#endif
-        // out type description object
-        PyArray_Descr *pDescr;
-        PyArray_DescrConverter(pDTypeString, &pDescr);
-        Py_DECREF(pDTypeString);
-
-        // create array
-        pOutArray = PyArray_SimpleNewFromDescr(1, &dims, pDescr);
-
-        // copy data in
-        if( !bZeroLength )
-        {
-            for( n = 0; n < nLength; n++ )
-            {
-                // we use strncpy so that we don't go over nMaxLen
-                // which we would if the null char is copied
-                // (which we don't want as numpy 'knows' to interpret the string as nMaxLen long)
-                strncpy((char*)PyArray_GETPTR1(pOutArray, n), papszStringList[n], nMaxLen);
-            }
-        }
-        else
-        {
-            // so there isn't rubbush in the 1 char strings
-            PyArray_FILLWBYTE(pOutArray, 0);
-        }
-
-        // free strings
-        for( n = 0; n < nLength; n++ )
-        {
-            CPLFree(papszStringList[n]);
-        }
-        CPLFree(papszStringList);
-    }
-    return pOutArray;
-  }
-%}
-
-%pythoncode %{
-import numpy
-import _gdal_array
-
-import gdalconst
-import gdal
-gdal.AllRegister()
-
-codes = {   gdalconst.GDT_Byte      :   numpy.uint8,
-            gdalconst.GDT_UInt16    :   numpy.uint16,
-            gdalconst.GDT_Int16     :   numpy.int16,
-            gdalconst.GDT_UInt32    :   numpy.uint32,
-            gdalconst.GDT_Int32     :   numpy.int32,
-            gdalconst.GDT_Float32   :   numpy.float32,
-            gdalconst.GDT_Float64   :   numpy.float64,
-            gdalconst.GDT_CInt16    :   numpy.complex64,
-            gdalconst.GDT_CInt32    :   numpy.complex64,
-            gdalconst.GDT_CFloat32  :   numpy.complex64,
-            gdalconst.GDT_CFloat64  :   numpy.complex128
-        }
-
-def OpenArray( array, prototype_ds = None ):
-
-    ds = gdal.Open( GetArrayFilename(array) )
-
-    if ds is not None and prototype_ds is not None:
-        if type(prototype_ds).__name__ == 'str':
-            prototype_ds = gdal.Open( prototype_ds )
-        if prototype_ds is not None:
-            CopyDatasetInfo( prototype_ds, ds )
-            
-    return ds
-    
-    
-def flip_code(code):
-    if isinstance(code, (numpy.dtype,type)):
-        # since several things map to complex64 we must carefully select
-        # the opposite that is an exact match (ticket 1518)
-        if code == numpy.int8:
-            return gdalconst.GDT_Byte
-        if code == numpy.complex64:
-            return gdalconst.GDT_CFloat32
-        
-        for key, value in codes.items():
-            if value == code:
-                return key
-        return None
-    else:
-        try:
-            return codes[code]
-        except KeyError:
-            return None
-
-def NumericTypeCodeToGDALTypeCode(numeric_type):
-    if not isinstance(numeric_type, (numpy.dtype,type)):
-        raise TypeError("Input must be a type")
-    return flip_code(numeric_type)
-
-def GDALTypeCodeToNumericTypeCode(gdal_code):
-    return flip_code(gdal_code)
-    
-def LoadFile( filename, xoff=0, yoff=0, xsize=None, ysize=None,
-              buf_xsize=None, buf_ysize=None, buf_type=None,
-              resample_alg = gdal.GRIORA_NearestNeighbour,
-              callback=None, callback_data=None ):
-    ds = gdal.Open( filename )
-    if ds is None:
-        raise ValueError("Can't open "+filename+"\n\n"+gdal.GetLastErrorMsg())
-
-    return DatasetReadAsArray( ds, xoff, yoff, xsize, ysize,
-                               buf_xsize=buf_xsize, buf_ysize=buf_ysize, buf_type=buf_type,
-                               resample_alg=resample_alg,
-                               callback = callback, callback_data = callback_data )
-
-def SaveArray( src_array, filename, format = "GTiff", prototype = None ):
-    driver = gdal.GetDriverByName( format )
-    if driver is None:
-        raise ValueError("Can't find driver "+format)
-
-    return driver.CreateCopy( filename, OpenArray(src_array,prototype) )
-
-
-def DatasetReadAsArray( ds, xoff=0, yoff=0, win_xsize=None, win_ysize=None, buf_obj=None,
-                        buf_xsize = None, buf_ysize = None, buf_type = None,
-                        resample_alg = gdal.GRIORA_NearestNeighbour,
-                        callback=None, callback_data=None ):
-    """Pure python implementation of reading a chunk of a GDAL file
-    into a numpy array.  Used by the gdal.Dataset.ReadAsArray method."""
-
-    if win_xsize is None:
-        win_xsize = ds.RasterXSize
-    if win_ysize is None:
-        win_ysize = ds.RasterYSize
-
-    if ds.RasterCount == 0:
-        return None
-
-    if ds.RasterCount == 1:
-        return BandReadAsArray( ds.GetRasterBand(1), xoff, yoff, win_xsize, win_ysize,
-                                buf_xsize = buf_xsize, buf_ysize = buf_ysize, buf_type = buf_type,
-                                buf_obj = buf_obj,
-                                resample_alg = resample_alg,
-                                callback = callback,
-                                callback_data = callback_data )
-
-    if buf_obj is None:
-        if buf_xsize is None:
-            buf_xsize = win_xsize
-        if buf_ysize is None:
-            buf_ysize = win_ysize
-        if buf_type is None:
-            buf_type = ds.GetRasterBand(1).DataType
-            for band_index in range(2,ds.RasterCount+1):
-                if buf_type != ds.GetRasterBand(band_index).DataType:
-                    buf_type = gdalconst.GDT_Float32
-
-        typecode = GDALTypeCodeToNumericTypeCode( buf_type )
-        if typecode == None:
-            buf_type = gdalconst.GDT_Float32
-            typecode = numpy.float32
-        if buf_type == gdalconst.GDT_Byte and ds.GetRasterBand(1).GetMetadataItem('PIXELTYPE', 'IMAGE_STRUCTURE') == 'SIGNEDBYTE':
-            typecode = numpy.int8
-        buf_obj = numpy.empty([ds.RasterCount, buf_ysize,buf_xsize], dtype = typecode)
-
-    else:
-        if len(buf_obj.shape) != 3:
-            raise ValueError('Array should have 3 dimensions')
-
-        shape_buf_xsize = buf_obj.shape[2]
-        shape_buf_ysize = buf_obj.shape[1]
-        if buf_xsize is not None and buf_xsize != shape_buf_xsize:
-            raise ValueError('Specified buf_xsize not consistent with array shape')
-        if buf_ysize is not None and buf_ysize != shape_buf_ysize:
-            raise ValueError('Specified buf_ysize not consistent with array shape')
-        if buf_obj.shape[0] != ds.RasterCount:
-            raise ValueError('Array should have space for %d bands' % ds.RasterCount)
-
-        datatype = NumericTypeCodeToGDALTypeCode( buf_obj.dtype.type )
-        if not datatype:
-            raise ValueError("array does not have corresponding GDAL data type")
-        if buf_type is not None and buf_type != datatype:
-            raise ValueError("Specified buf_type not consistent with array type")
-        buf_type = datatype
-
-    if DatasetIONumPy( ds, 0, xoff, yoff, win_xsize, win_ysize,
-                       buf_obj, buf_type, resample_alg, callback, callback_data ) != 0:
-        return None
-
-    return buf_obj
-
-def BandReadAsArray( band, xoff = 0, yoff = 0, win_xsize = None, win_ysize = None,
-                     buf_xsize=None, buf_ysize=None, buf_type=None, buf_obj=None,
-                     resample_alg = gdal.GRIORA_NearestNeighbour,
-                     callback=None, callback_data=None):
-    """Pure python implementation of reading a chunk of a GDAL file
-    into a numpy array.  Used by the gdal.Band.ReadAsArray method."""
-
-    if win_xsize is None:
-        win_xsize = band.XSize
-    if win_ysize is None:
-        win_ysize = band.YSize
-
-    if buf_obj is None:
-        if buf_xsize is None:
-            buf_xsize = win_xsize
-        if buf_ysize is None:
-            buf_ysize = win_ysize
-        if buf_type is None:
-            buf_type = band.DataType
-
-        typecode = GDALTypeCodeToNumericTypeCode( buf_type )
-        if typecode == None:
-            buf_type = gdalconst.GDT_Float32
-            typecode = numpy.float32
-        else:
-            buf_type = NumericTypeCodeToGDALTypeCode( typecode )
-
-        if buf_type == gdalconst.GDT_Byte and band.GetMetadataItem('PIXELTYPE', 'IMAGE_STRUCTURE') == 'SIGNEDBYTE':
-            typecode = numpy.int8
-        buf_obj = numpy.empty([buf_ysize,buf_xsize], dtype = typecode)
-
-    else:
-        if len(buf_obj.shape) == 2:
-            shape_buf_xsize = buf_obj.shape[1]
-            shape_buf_ysize = buf_obj.shape[0]
-        else:
-            shape_buf_xsize = buf_obj.shape[2]
-            shape_buf_ysize = buf_obj.shape[1]
-        if buf_xsize is not None and buf_xsize != shape_buf_xsize:
-            raise ValueError('Specified buf_xsize not consistent with array shape')
-        if buf_ysize is not None and buf_ysize != shape_buf_ysize:
-            raise ValueError('Specified buf_ysize not consistent with array shape')
-
-        datatype = NumericTypeCodeToGDALTypeCode( buf_obj.dtype.type )
-        if not datatype:
-            raise ValueError("array does not have corresponding GDAL data type")
-        if buf_type is not None and buf_type != datatype:
-            raise ValueError("Specified buf_type not consistent with array type")
-        buf_type = datatype
-
-    if BandRasterIONumPy( band, 0, xoff, yoff, win_xsize, win_ysize,
-                          buf_obj, buf_type, resample_alg, callback, callback_data ) != 0:
-        return None
-
-    return buf_obj
-
-def BandWriteArray( band, array, xoff=0, yoff=0,
-                    resample_alg = gdal.GRIORA_NearestNeighbour,
-                    callback=None, callback_data=None ):
-    """Pure python implementation of writing a chunk of a GDAL file
-    from a numpy array.  Used by the gdal.Band.WriteArray method."""
-
-    if array is None or len(array.shape) != 2:
-        raise ValueError("expected array of dim 2")
-
-    xsize = array.shape[1]
-    ysize = array.shape[0]
-
-    if xsize + xoff > band.XSize or ysize + yoff > band.YSize:
-        raise ValueError("array larger than output file, or offset off edge")
-
-    datatype = NumericTypeCodeToGDALTypeCode( array.dtype.type )
-
-    # if we receive some odd type, like int64, try casting to a very
-    # generic type we do support (#2285)
-    if not datatype:
-        gdal.Debug( 'gdal_array', 'force array to float64' )
-        array = array.astype( numpy.float64 )
-        datatype = NumericTypeCodeToGDALTypeCode( array.dtype.type )
-        
-    if not datatype:
-        raise ValueError("array does not have corresponding GDAL data type")
-
-    return BandRasterIONumPy( band, 1, xoff, yoff, xsize, ysize,
-                                array, datatype, resample_alg, callback, callback_data )
-
-def RATWriteArray(rat, array, field, start=0):
-    """
-    Pure Python implementation of writing a chunk of the RAT
-    from a numpy array. Type of array is coerced to one of the types
-    (int, double, string) supported. Called from RasterAttributeTable.WriteArray
-    """
-    if array is None:
-        raise ValueError("Expected array of dim 1")
-
-    # if not the array type convert it to handle lists etc
-    if not isinstance(array, numpy.ndarray):
-        array = numpy.array(array)
-
-    if array.ndim != 1:
-        raise ValueError("Expected array of dim 1")
-
-    if (start + array.size) > rat.GetRowCount():
-        raise ValueError("Array too big to fit into RAT from start position")
-
-    if numpy.issubdtype(array.dtype, numpy.integer):
-        # is some type of integer - coerce to standard int
-        # TODO: must check this is fine on all platforms
-        # confusingly numpy.int 64 bit even if native type 32 bit
-        array = array.astype(numpy.int32)
-    elif numpy.issubdtype(array.dtype, numpy.floating):
-        # is some type of floating point - coerce to double
-        array = array.astype(numpy.double)
-    elif numpy.issubdtype(array.dtype, numpy.character):
-        # cast away any kind of Unicode etc
-        array = array.astype(numpy.character)
-    else:
-        raise ValueError("Array not of a supported type (integer, double or string)")
-
-    return RATValuesIONumPyWrite(rat, field, start, array)
-
-def RATReadArray(rat, field, start=0, length=None):
-    """
-    Pure Python implementation of reading a chunk of the RAT
-    into a numpy array. Called from RasterAttributeTable.ReadAsArray
-    """
-    if length is None:
-        length = rat.GetRowCount() - start
-
-    return RATValuesIONumPyRead(rat, field, start, length)
-    
-def CopyDatasetInfo( src, dst, xoff=0, yoff=0 ):
-    """
-    Copy georeferencing information and metadata from one dataset to another.
-    src: input dataset
-    dst: output dataset - It can be a ROI - 
-    xoff, yoff:  dst's offset with respect to src in pixel/line.  
-    
-    Notes: Destination dataset must have update access.  Certain formats
-           do not support creation of geotransforms and/or gcps.
-
-    """
-
-    dst.SetMetadata( src.GetMetadata() )
-                    
-
-
-    #Check for geo transform
-    gt = src.GetGeoTransform()
-    if gt != (0,1,0,0,0,1):
-        dst.SetProjection( src.GetProjectionRef() )
-        
-        if (xoff == 0) and (yoff == 0):
-            dst.SetGeoTransform( gt  )
-        else:
-            ngt = [gt[0],gt[1],gt[2],gt[3],gt[4],gt[5]]
-            ngt[0] = gt[0] + xoff*gt[1] + yoff*gt[2];
-            ngt[3] = gt[3] + xoff*gt[4] + yoff*gt[5];
-            dst.SetGeoTransform( ( ngt[0], ngt[1], ngt[2], ngt[3], ngt[4], ngt[5] ) )
-            
-    #Check for GCPs
-    elif src.GetGCPCount() > 0:
-        
-        if (xoff == 0) and (yoff == 0):
-            dst.SetGCPs( src.GetGCPs(), src.GetGCPProjection() )
-        else:
-            gcps = src.GetGCPs()
-            #Shift gcps
-            new_gcps = []
-            for gcp in gcps:
-                ngcp = gdal.GCP()
-                ngcp.GCPX = gcp.GCPX 
-                ngcp.GCPY = gcp.GCPY
-                ngcp.GCPZ = gcp.GCPZ
-                ngcp.GCPPixel = gcp.GCPPixel - xoff
-                ngcp.GCPLine = gcp.GCPLine - yoff
-                ngcp.Info = gcp.Info
-                ngcp.Id = gcp.Id
-                new_gcps.append(ngcp)
-
-            try:
-                dst.SetGCPs( new_gcps , src.GetGCPProjection() )
-            except:
-                print ("Failed to set GCPs")
-                return
-
-    return
-%}
+/******************************************************************************
+ * $Id: gdal_array.i 33792 2016-03-26 12:54:28Z goatbar $
+ *
+ * Name:     gdal_array.i
+ * Project:  GDAL Python Interface
+ * Purpose:  GDAL / Numpy interface
+ * Author:   Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Frank Warmerdam
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+%feature("autodoc");
+
+%module gdal_array
+
+%include constraints.i
+
+%import typemaps_python.i
+
+%import MajorObject.i
+%import Band.i
+%import Dataset.i
+%import RasterAttributeTable.i
+
+%include "cplvirtualmem.i"
+
+%init %{
+  import_array();
+  GDALRegister_NUMPY();
+%}
+
+typedef int CPLErr;
+typedef int GDALRIOResampleAlg;
+
+%include "python_strings.i"
+
+%{
+#include "gdal_priv.h"
+#ifdef _DEBUG
+#undef _DEBUG
+#include "Python.h"
+#define _DEBUG
+#else
+#include "Python.h"
+#endif
+#include "numpy/arrayobject.h"
+
+#ifdef DEBUG
+typedef struct GDALRasterBandHS GDALRasterBandShadow;
+typedef struct GDALDatasetHS GDALDatasetShadow;
+typedef struct RasterAttributeTableHS GDALRasterAttributeTableShadow;
+#else
+typedef void GDALRasterBandShadow;
+typedef void GDALDatasetShadow;
+typedef void GDALRasterAttributeTableShadow;
+#endif
+
+CPL_C_START
+
+GDALRasterBandH CPL_DLL MEMCreateRasterBandEx( GDALDataset *, int, GByte *,
+                                               GDALDataType, GSpacing, GSpacing, int );
+CPL_C_END
+
+typedef char retStringAndCPLFree;
+
+class NUMPYDataset : public GDALDataset
+{
+    PyArrayObject *psArray;
+
+    int           bValidGeoTransform;
+    double	  adfGeoTransform[6];
+    char	  *pszProjection;
+
+    int           nGCPCount;
+    GDAL_GCP      *pasGCPList;
+    char          *pszGCPProjection;
+
+  public:
+                 NUMPYDataset();
+                 ~NUMPYDataset();
+
+    virtual const char *GetProjectionRef(void);
+    virtual CPLErr SetProjection( const char * );
+    virtual CPLErr GetGeoTransform( double * );
+    virtual CPLErr SetGeoTransform( double * );
+
+    virtual int    GetGCPCount();
+    virtual const char *GetGCPProjection();
+    virtual const GDAL_GCP *GetGCPs();
+    virtual CPLErr SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
+                            const char *pszGCPProjection );
+
+    static GDALDataset *Open( PyArrayObject *psArray );
+    static GDALDataset *Open( GDALOpenInfo * );
+};
+
+
+/************************************************************************/
+/*                          GDALRegister_NUMPY()                        */
+/************************************************************************/
+
+static void GDALRegister_NUMPY(void)
+
+{
+    GDALDriver	*poDriver;
+    if (! GDAL_CHECK_VERSION("NUMPY driver"))
+        return;
+    if( GDALGetDriverByName( "NUMPY" ) == NULL )
+    {
+        poDriver = new GDALDriver();
+
+        poDriver->SetDescription( "NUMPY" );
+        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                                   "Numeric Python Array" );
+        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+
+        poDriver->pfnOpen = NUMPYDataset::Open;
+
+        GetGDALDriverManager()->RegisterDriver( poDriver );
+
+    }
+}
+
+/************************************************************************/
+/*                            NUMPYDataset()                            */
+/************************************************************************/
+
+NUMPYDataset::NUMPYDataset()
+
+{
+    psArray = NULL;
+    pszProjection = CPLStrdup("");
+    bValidGeoTransform = FALSE;
+    adfGeoTransform[0] = 0.0;
+    adfGeoTransform[1] = 1.0;
+    adfGeoTransform[2] = 0.0;
+    adfGeoTransform[3] = 0.0;
+    adfGeoTransform[4] = 0.0;
+    adfGeoTransform[5] = 1.0;
+
+    nGCPCount = 0;
+    pasGCPList = NULL;
+    pszGCPProjection = CPLStrdup("");
+}
+
+/************************************************************************/
+/*                            ~NUMPYDataset()                            */
+/************************************************************************/
+
+NUMPYDataset::~NUMPYDataset()
+
+{
+    CPLFree( pszProjection );
+
+    CPLFree( pszGCPProjection );
+    if( nGCPCount > 0 )
+    {
+        GDALDeinitGCPs( nGCPCount, pasGCPList );
+        CPLFree( pasGCPList );
+    }
+
+    FlushCache();
+    Py_DECREF( psArray );
+}
+
+/************************************************************************/
+/*                          GetProjectionRef()                          */
+/************************************************************************/
+
+const char *NUMPYDataset::GetProjectionRef()
+
+{
+    return( pszProjection );
+}
+
+/************************************************************************/
+/*                           SetProjection()                            */
+/************************************************************************/
+
+CPLErr NUMPYDataset::SetProjection( const char * pszNewProjection )
+
+{
+    CPLFree( pszProjection );
+    pszProjection = CPLStrdup( pszNewProjection );
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                          GetGeoTransform()                           */
+/************************************************************************/
+
+CPLErr NUMPYDataset::GetGeoTransform( double * padfTransform )
+
+{
+    memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
+    if( bValidGeoTransform )
+        return CE_None;
+    else
+        return CE_Failure;
+}
+
+/************************************************************************/
+/*                          SetGeoTransform()                           */
+/************************************************************************/
+
+CPLErr NUMPYDataset::SetGeoTransform( double * padfTransform )
+
+{
+    bValidGeoTransform = TRUE;
+    memcpy( adfGeoTransform, padfTransform, sizeof(double)*6 );
+    return( CE_None );
+}
+
+/************************************************************************/
+/*                            GetGCPCount()                             */
+/************************************************************************/
+
+int NUMPYDataset::GetGCPCount()
+
+{
+    return nGCPCount;
+}
+
+/************************************************************************/
+/*                          GetGCPProjection()                          */
+/************************************************************************/
+
+const char *NUMPYDataset::GetGCPProjection()
+
+{
+    return pszGCPProjection;
+}
+
+/************************************************************************/
+/*                               GetGCPs()                              */
+/************************************************************************/
+
+const GDAL_GCP *NUMPYDataset::GetGCPs()
+
+{
+    return pasGCPList;
+}
+
+/************************************************************************/
+/*                              SetGCPs()                               */
+/************************************************************************/
+
+CPLErr NUMPYDataset::SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
+                              const char *pszGCPProjection )
+
+{
+    CPLFree( this->pszGCPProjection );
+    if( this->nGCPCount > 0 )
+    {
+        GDALDeinitGCPs( this->nGCPCount, this->pasGCPList );
+        CPLFree( this->pasGCPList );
+    }
+
+    this->pszGCPProjection = CPLStrdup(pszGCPProjection);
+
+    this->nGCPCount = nGCPCount;
+
+    this->pasGCPList = GDALDuplicateGCPs( nGCPCount, pasGCPList );
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *NUMPYDataset::Open( GDALOpenInfo * poOpenInfo )
+
+{
+    PyArrayObject *psArray;
+
+/* -------------------------------------------------------------------- */
+/*      Is this a numpy dataset name?                                   */
+/* -------------------------------------------------------------------- */
+    if( !EQUALN(poOpenInfo->pszFilename,"NUMPY:::",8)
+        || poOpenInfo->fpL != NULL )
+        return NULL;
+
+    psArray = NULL;
+    sscanf( poOpenInfo->pszFilename+8, "%p", &(psArray) );
+    if( psArray == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Failed to parse meaningful pointer value from NUMPY name\n"
+                  "string: %s\n",
+                  poOpenInfo->pszFilename );
+        return NULL;
+    }
+
+    if( !CSLTestBoolean(CPLGetConfigOption("GDAL_ARRAY_OPEN_BY_FILENAME", "FALSE")) )
+    {
+        if( CPLGetConfigOption("GDAL_ARRAY_OPEN_BY_FILENAME", NULL) == NULL )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                    "Opening a NumPy array through gdal.Open(gdal_array.GetArrayFilename()) "
+                    "is no longer supported by default unless the GDAL_ARRAY_OPEN_BY_FILENAME "
+                    "configuration option is set to TRUE. The recommended way is to use "
+                    "gdal_array.OpenArray() instead.");
+        }
+        return NULL;
+    }
+
+    return Open(psArray);
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset* NUMPYDataset::Open( PyArrayObject *psArray )
+{
+    GDALDataType  eType;
+    int     nBands;
+
+/* -------------------------------------------------------------------- */
+/*      If we likely have corrupt definitions of the NUMPY stuff,       */
+/*      then warn now.                                                  */
+/* -------------------------------------------------------------------- */
+#ifdef NUMPY_DEFS_WRONG
+    CPLError( CE_Warning, CPLE_AppDefined,
+              "It would appear you have built GDAL without having it use\n"
+              "the Numeric python include files.  Old definitions have\n"
+              "been used instead at build time, and it is quite possible that\n"
+              "the things will shortly fail or crash if they are wrong.\n"
+              "Consider installing Numeric, and rebuilding with HAVE_NUMPY\n"
+              "enabled in gdal\nmake.opt." );
+#endif
+
+/* -------------------------------------------------------------------- */
+/*      Is this a directly mappable Python array?  Verify rank, and     */
+/*      data type.                                                      */
+/* -------------------------------------------------------------------- */
+
+    if( psArray->nd < 2 || psArray->nd > 3 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Illegal numpy array rank %d.",
+                  psArray->nd );
+        return NULL;
+    }
+
+    switch( psArray->descr->type_num )
+    {
+      case NPY_CDOUBLE:
+        eType = GDT_CFloat64;
+        break;
+
+      case NPY_CFLOAT:
+        eType = GDT_CFloat32;
+        break;
+
+      case NPY_DOUBLE:
+        eType = GDT_Float64;
+        break;
+
+      case NPY_FLOAT:
+        eType = GDT_Float32;
+        break;
+
+      case NPY_INT:
+      case NPY_LONG:
+        eType = GDT_Int32;
+        break;
+
+      case NPY_UINT:
+      case NPY_ULONG:
+        eType = GDT_UInt32;
+        break;
+
+      case NPY_SHORT:
+        eType = GDT_Int16;
+        break;
+
+      case NPY_USHORT:
+        eType = GDT_UInt16;
+        break;
+
+      case NPY_BYTE:
+      case NPY_UBYTE:
+        eType = GDT_Byte;
+        break;
+
+      default:
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Unable to access numpy arrays of typecode `%c'.",
+                  psArray->descr->type );
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create the new NUMPYDataset object.                             */
+/* -------------------------------------------------------------------- */
+    NUMPYDataset *poDS;
+
+    poDS = new NUMPYDataset();
+    poDS->poDriver = static_cast<GDALDriver*>(GDALGetDriverByName("NUMPY"));
+
+    poDS->psArray = psArray;
+
+    poDS->eAccess = GA_ReadOnly;
+
+/* -------------------------------------------------------------------- */
+/*      Add a reference to the array.                                   */
+/* -------------------------------------------------------------------- */
+    Py_INCREF( psArray );
+
+/* -------------------------------------------------------------------- */
+/*      Workout the data layout.                                        */
+/* -------------------------------------------------------------------- */
+    npy_intp nBandOffset;
+    npy_intp nPixelOffset;
+    npy_intp nLineOffset;
+
+    if( psArray->nd == 3 )
+    {
+        nBands = psArray->dimensions[0];
+        nBandOffset = psArray->strides[0];
+        poDS->nRasterXSize = psArray->dimensions[2];
+        nPixelOffset = psArray->strides[2];
+        poDS->nRasterYSize = psArray->dimensions[1];
+        nLineOffset = psArray->strides[1];
+    }
+    else
+    {
+        nBands = 1;
+        nBandOffset = 0;
+        poDS->nRasterXSize = psArray->dimensions[1];
+        nPixelOffset = psArray->strides[1];
+        poDS->nRasterYSize = psArray->dimensions[0];
+        nLineOffset = psArray->strides[0];
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create band information objects.                                */
+/* -------------------------------------------------------------------- */
+    for( int iBand = 0; iBand < nBands; iBand++ )
+    {
+        poDS->SetBand( iBand+1,
+                       (GDALRasterBand *)
+                       MEMCreateRasterBandEx( poDS, iBand+1,
+                                (GByte *) psArray->data + nBandOffset*iBand,
+                                          eType, nPixelOffset, nLineOffset,
+                                          FALSE ) );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Try to return a regular handle on the file.                     */
+/* -------------------------------------------------------------------- */
+    return poDS;
+}
+
+%}
+
+// So that SWIGTYPE_p_f_double_p_q_const__char_p_void__int is declared...
+/************************************************************************/
+/*                            TermProgress()                            */
+/************************************************************************/
+
+%rename (TermProgress_nocb) GDALTermProgress_nocb;
+%feature( "kwargs" ) GDALTermProgress_nocb;
+%inline %{
+int GDALTermProgress_nocb( double dfProgress, const char * pszMessage=NULL, void *pData=NULL ) {
+  return GDALTermProgress( dfProgress, pszMessage, pData);
+}
+%}
+
+%rename (TermProgress) GDALTermProgress;
+%callback("%s");
+int GDALTermProgress( double, const char *, void * );
+%nocallback;
+
+%include "callback.i"
+
+%typemap(in,numinputs=1) (PyArrayObject *psArray)
+{
+  /* %typemap(in,numinputs=1) (PyArrayObject  *psArray) */
+  if ($input != NULL && PyArray_Check($input))
+  {
+      $1 = (PyArrayObject*)($input);
+  }
+  else
+  {
+      PyErr_SetString(PyExc_TypeError, "not a numpy array");
+      SWIG_fail;
+  }
+}
+
+%newobject OpenNumPyArray;
+%inline %{
+GDALDatasetShadow* OpenNumPyArray(PyArrayObject *psArray)
+{
+    return NUMPYDataset::Open( psArray );
+}
+%}
+
+/* Deprecated */
+%inline %{
+retStringAndCPLFree* GetArrayFilename(PyArrayObject *psArray)
+{
+    char      szString[128];
+
+    GDALRegister_NUMPY();
+
+    /* I wish I had a safe way of checking the type */
+    sprintf( szString, "NUMPY:::%p", psArray );
+    return CPLStrdup(szString);
+}
+%}
+
+%feature( "kwargs" ) BandRasterIONumPy;
+%inline %{
+  CPLErr BandRasterIONumPy( GDALRasterBandShadow* band, int bWrite, double xoff, double yoff, double xsize, double ysize,
+                            PyArrayObject *psArray,
+                            int buf_type,
+                            GDALRIOResampleAlg resample_alg,
+                            GDALProgressFunc callback = NULL,
+                            void* callback_data = NULL) {
+
+    GDALDataType ntype  = (GDALDataType)buf_type;
+    if( psArray->nd < 2 || psArray->nd > 3 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Illegal numpy array rank %d.\n",
+                  psArray->nd );
+        return CE_Failure;
+    }
+
+    int xdim = ( psArray->nd == 2) ? 1 : 2;
+    int ydim = ( psArray->nd == 2) ? 0 : 1;
+
+    int nxsize, nysize, pixel_space, line_space;
+    nxsize = psArray->dimensions[xdim];
+    nysize = psArray->dimensions[ydim];
+    pixel_space = psArray->strides[xdim];
+    line_space = psArray->strides[ydim];
+
+    GDALRasterIOExtraArg sExtraArg;
+    INIT_RASTERIO_EXTRA_ARG(sExtraArg);
+    sExtraArg.eResampleAlg = resample_alg;
+    sExtraArg.pfnProgress = callback;
+    sExtraArg.pProgressData = callback_data;
+    int nXOff = (int)(xoff + 0.5);
+    int nYOff = (int)(yoff + 0.5);
+    int nXSize = (int)(xsize + 0.5);
+    int nYSize = (int)(ysize + 0.5);
+    if( fabs(xoff-nXOff) > 1e-8 || fabs(yoff-nYOff) > 1e-8 ||
+        fabs(xsize-nXSize) > 1e-8 || fabs(ysize-nYSize) > 1e-8 )
+    {
+        sExtraArg.bFloatingPointWindowValidity = TRUE;
+        sExtraArg.dfXOff = xoff;
+        sExtraArg.dfYOff = yoff;
+        sExtraArg.dfXSize = xsize;
+        sExtraArg.dfYSize = ysize;
+    }
+
+    return  GDALRasterIOEx( band, (bWrite) ? GF_Write : GF_Read, nXOff, nYOff, nXSize, nYSize,
+                          psArray->data, nxsize, nysize,
+                          ntype, pixel_space, line_space, &sExtraArg );
+  }
+%}
+
+%feature( "kwargs" ) DatasetIONumPy;
+%inline %{
+  CPLErr DatasetIONumPy( GDALDatasetShadow* ds, int bWrite, int xoff, int yoff, int xsize, int ysize,
+                         PyArrayObject *psArray,
+                         int buf_type,
+                         GDALRIOResampleAlg resample_alg,
+                         GDALProgressFunc callback = NULL,
+                         void* callback_data = NULL )
+{
+    GDALDataType ntype  = (GDALDataType)buf_type;
+    if( psArray->nd != 3 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Illegal numpy array rank %d.",
+                  psArray->nd );
+        return CE_Failure;
+    }
+
+    int xdim = 2;
+    int ydim = 1;
+
+    int bandsize, nxsize, nysize;
+    GIntBig pixel_space, line_space, band_space;
+    nxsize = psArray->dimensions[xdim];
+    nysize = psArray->dimensions[ydim];
+    bandsize = psArray->dimensions[0];
+    if( bandsize != GDALGetRasterCount(ds) )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Illegal numpy array band dimension %d. Expected value: %d",
+                  bandsize, GDALGetRasterCount(ds) );
+        return CE_Failure;
+    }
+    pixel_space = psArray->strides[xdim];
+    line_space = psArray->strides[ydim];
+    band_space = psArray->strides[0];
+
+    GDALRasterIOExtraArg sExtraArg;
+    INIT_RASTERIO_EXTRA_ARG(sExtraArg);
+    sExtraArg.eResampleAlg = resample_alg;
+    sExtraArg.pfnProgress = callback;
+    sExtraArg.pProgressData = callback_data;
+
+    return  GDALDatasetRasterIOEx( ds, (bWrite) ? GF_Write : GF_Read, xoff, yoff, xsize, ysize,
+                                   psArray->data, nxsize, nysize,
+                                   ntype,
+                                   bandsize, NULL,
+                                   pixel_space, line_space, band_space, &sExtraArg );
+  }
+%}
+
+%typemap(in,numinputs=0) (CPLVirtualMemShadow** pvirtualmem, int numpytypemap) (CPLVirtualMemShadow* virtualmem)
+{
+  $1 = &virtualmem;
+  $2 = 0;
+}
+
+%typemap(argout) (CPLVirtualMemShadow** pvirtualmem, int numpytypemap)
+{
+    CPLVirtualMemShadow* virtualmem = *($1);
+    void* ptr = CPLVirtualMemGetAddr( virtualmem->vmem );
+    /*size_t nsize = CPLVirtualMemGetSize( virtualmem->vmem );*/
+    GDALDataType datatype = virtualmem->eBufType;
+    int readonly = virtualmem->bReadOnly;
+    GIntBig nBufXSize = virtualmem->nBufXSize;
+    GIntBig nBufYSize = virtualmem->nBufYSize;
+    int nBandCount = virtualmem->nBandCount;
+    int bIsBandSequential = virtualmem->bIsBandSequential;
+    GDALTileOrganization eTileOrganization = virtualmem->eTileOrganization;
+    int nTileXSize = virtualmem->nTileXSize;
+    int nTileYSize = virtualmem->nTileYSize;
+    int bAuto = virtualmem->bAuto;
+    int            nPixelSpace = virtualmem->nPixelSpace; /* if bAuto == TRUE */
+    GIntBig        nLineSpace = virtualmem->nLineSpace; /* if bAuto == TRUE */
+    int numpytype;
+
+    if( datatype == GDT_CInt16 || datatype == GDT_CInt32 )
+    {
+        PyErr_SetString( PyExc_RuntimeError, "GDT_CInt16 and GDT_CInt32 not supported for now" );
+        SWIG_fail;
+    }
+
+    switch(datatype)
+    {
+        case GDT_Byte: numpytype = NPY_UBYTE; break;
+        case GDT_Int16: numpytype = NPY_INT16; break;
+        case GDT_UInt16: numpytype = NPY_UINT16; break;
+        case GDT_Int32: numpytype = NPY_INT32; break;
+        case GDT_UInt32: numpytype = NPY_UINT32; break;
+        case GDT_Float32: numpytype = NPY_FLOAT32; break;
+        case GDT_Float64: numpytype = NPY_FLOAT64; break;
+        //case GDT_CInt16: numpytype = NPY_INT16; break;
+        //case GDT_CInt32: numpytype = NPY_INT32; break;
+        case GDT_CFloat32: numpytype = NPY_CFLOAT; break;
+        case GDT_CFloat64: numpytype = NPY_CDOUBLE; break;
+        default: numpytype = NPY_UBYTE; break;
+    }
+    PyArrayObject* ar;
+    int flags = (readonly) ? 0x1 : 0x1 | 0x0400;
+    int nDataTypeSize = GDALGetDataTypeSize(datatype) / 8;
+    if( bAuto )
+    {
+        if( nBandCount == 1 )
+        {
+            npy_intp shape[2], stride[2];
+            shape[0] = nBufYSize;
+            shape[1] = nBufXSize;
+            stride[1] = nPixelSpace;
+            stride[0] = nLineSpace;
+            ar = (PyArrayObject*) PyArray_New(&PyArray_Type, 2, shape,
+                    numpytype, stride, ptr, 0, flags , NULL);
+        }
+        else
+        {
+            PyErr_SetString( PyExc_RuntimeError, "Code update needed for bAuto and nBandCount > 1 !" );
+            SWIG_fail;
+        }
+    }
+    else if( bIsBandSequential >= 0 )
+    {
+        if( nBandCount == 1 )
+        {
+            npy_intp shape[2], stride[2];
+            shape[0] = nBufYSize;
+            shape[1] = nBufXSize;
+            stride[1] = nDataTypeSize;
+            stride[0] = stride[1] * nBufXSize;
+            ar = (PyArrayObject*) PyArray_New(&PyArray_Type, 2, shape,
+                    numpytype, stride, ptr, 0, flags , NULL);
+        }
+        else
+        {
+            npy_intp shape[3], stride[3];
+            if( bIsBandSequential )
+            {
+                shape[0] = nBandCount;
+                shape[1] = nBufYSize;
+                shape[2] = nBufXSize;
+                stride[2] = nDataTypeSize;
+                stride[1] = stride[2] * nBufXSize;
+                stride[0] = stride[1] * nBufYSize;
+            }
+            else
+            {
+                shape[0] = nBufYSize;
+                shape[1] = nBufXSize;
+                shape[2] = nBandCount;
+                stride[2] = nDataTypeSize;
+                stride[1] = stride[2] * nBandCount;
+                stride[0] = stride[1] * nBufXSize;
+            }
+            ar = (PyArrayObject*) PyArray_New(&PyArray_Type, 3, shape,
+                    numpytype, stride, ptr, 0, flags , NULL);
+        }
+    }
+    else
+    {
+        int nTilesPerRow = (nBufXSize + nTileXSize - 1) / nTileXSize;
+        int nTilesPerCol = (nBufYSize + nTileYSize - 1) / nTileYSize;
+        npy_intp shape[5], stride[5];
+        if( nBandCount == 1 )
+        {
+            shape[0] = nTilesPerCol;
+            shape[1] = nTilesPerRow;
+            shape[2] = nTileYSize;
+            shape[3] = nTileXSize;
+            stride[3] = nDataTypeSize;
+            stride[2] = stride[3] * nTileXSize;
+            stride[1] = stride[2] * nTileYSize;
+            stride[0] = stride[1] * nTilesPerRow;
+            ar = (PyArrayObject*) PyArray_New(&PyArray_Type, 4, shape,
+                    numpytype, stride, ptr, 0, flags , NULL);
+        }
+        else if( eTileOrganization == GTO_TIP )
+        {
+            shape[0] = nTilesPerCol;
+            shape[1] = nTilesPerRow;
+            shape[2] = nTileYSize;
+            shape[3] = nTileXSize;
+            shape[4] = nBandCount;
+            stride[4] = nDataTypeSize;
+            stride[3] = stride[4] * nBandCount;
+            stride[2] = stride[3] * nTileXSize;
+            stride[1] = stride[2] * nTileYSize;
+            stride[0] = stride[1] * nTilesPerRow;
+            ar = (PyArrayObject*) PyArray_New(&PyArray_Type, 5, shape,
+                    numpytype, stride, ptr, 0, flags , NULL);
+        }
+        else if( eTileOrganization == GTO_BIT )
+        {
+            shape[0] = nTilesPerCol;
+            shape[1] = nTilesPerRow;
+            shape[2] = nBandCount;
+            shape[3] = nTileYSize;
+            shape[4] = nTileXSize;
+            stride[4] = nDataTypeSize;
+            stride[3] = stride[4] * nTileXSize;
+            stride[2] = stride[3] * nTileYSize;
+            stride[1] = stride[2] * nBandCount;
+            stride[0] = stride[1] * nTilesPerRow;
+            ar = (PyArrayObject*) PyArray_New(&PyArray_Type, 5, shape,
+                    numpytype, stride, ptr, 0, flags , NULL);
+        }
+        else /* GTO_BSQ */
+        {
+            shape[0] = nBandCount;
+            shape[1] = nTilesPerCol;
+            shape[2] = nTilesPerRow;
+            shape[3] = nTileYSize;
+            shape[4] = nTileXSize;
+            stride[4] = nDataTypeSize;
+            stride[3] = stride[4] * nTileXSize;
+            stride[2] = stride[3] * nTileYSize;
+            stride[1] = stride[2] * nTilesPerRow;
+            stride[0] = stride[1] * nTilesPerCol;
+            ar = (PyArrayObject*) PyArray_New(&PyArray_Type, 5, shape,
+                    numpytype, stride, ptr, 0, flags , NULL);
+        }
+    }
+
+    /* Keep a reference to the VirtualMem object */
+    ar->base = obj0;
+    Py_INCREF(obj0);
+    Py_DECREF($result);
+    $result = (PyObject*) ar;
+}
+
+%apply Pointer NONNULL {CPLVirtualMemShadow* virtualmem};
+%inline %{
+    void VirtualMemGetArray(CPLVirtualMemShadow* virtualmem, CPLVirtualMemShadow** pvirtualmem, int numpytypemap)
+    {
+        *pvirtualmem = virtualmem;
+    }
+%}
+%clear CPLVirtualMemShadow* virtualmem;
+
+%feature( "kwargs" ) RATValuesIONumPyWrite;
+%inline %{
+  // need different functions for read and write
+  // since reading strings requires us to know the
+  // length of the longest string before creating array
+  CPLErr RATValuesIONumPyWrite( GDALRasterAttributeTableShadow* poRAT, int nField, int nStart,
+                       PyArrayObject *psArray) {
+
+    if( PyArray_NDIM(psArray) != 1 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Illegal numpy array rank %d.\n",
+                  PyArray_NDIM(psArray) );
+        return CE_Failure;
+    }
+
+    int nLength = PyArray_DIM(psArray, 0);
+    int nType = PyArray_TYPE(psArray);
+    CPLErr retval = CE_None;
+
+    if( nType == NPY_INT32 )
+    {
+        retval = GDALRATValuesIOAsInteger(poRAT, GF_Write, nField, nStart, nLength,
+                        (int*)PyArray_DATA(psArray) );
+    }
+    else if( nType == NPY_DOUBLE )
+    {
+        retval = GDALRATValuesIOAsDouble(poRAT, GF_Write, nField, nStart, nLength,
+                        (double*)PyArray_DATA(psArray) );
+    }
+    else if( nType == NPY_STRING )
+    {
+        // have to convert array of strings to a char **
+        char **papszStringData = (char**)CPLCalloc(sizeof(char*), nLength);
+
+        // max size of string
+        int nMaxLen = PyArray_ITEMSIZE(psArray);
+        char *pszBuffer = (char*)CPLMalloc((nMaxLen+1) * sizeof(char));
+        // make sure there is a null char on the end
+        // as there won't be if this string is the maximum size
+        pszBuffer[nMaxLen] = '\0';
+
+        // we can't just use the memory location in the array
+        // since long strings won't be null terminated
+        for( int i = 0; i < nLength; i++ )
+        {
+            strncpy(pszBuffer, (char*)PyArray_GETPTR1(psArray, i), nMaxLen);
+            papszStringData[i] = CPLStrdup(pszBuffer);
+        }
+        CPLFree(pszBuffer);
+
+        retval = GDALRATValuesIOAsString(poRAT, GF_Write, nField, nStart, nLength,
+                                            papszStringData);
+
+        for( int i = 0; i < nLength; i++ )
+        {
+            CPLFree(papszStringData[i]);
+        }
+        CPLFree(papszStringData);
+    }
+    else
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Illegal numpy array type %d.\n",
+                  nType );
+        return CE_Failure;
+    }
+    return retval;
+  }
+%}
+
+%feature( "kwargs" ) RATValuesIONumPyRead;
+%inline %{
+  // need different functions for read and write
+  // since reading strings requires us to know the
+  // length of the longest string before creating array
+  PyObject *RATValuesIONumPyRead( GDALRasterAttributeTableShadow* poRAT, int nField, int nStart,
+                       int nLength) {
+
+    GDALRATFieldType colType = GDALRATGetTypeOfCol(poRAT, nField);
+    npy_intp dims = nLength;
+    PyObject *pOutArray = NULL;
+    if( colType == GFT_Integer )
+    {
+        pOutArray = PyArray_SimpleNew(1, &dims, NPY_INT32);
+        if( GDALRATValuesIOAsInteger(poRAT, GF_Read, nField, nStart, nLength,
+                        (int*)PyArray_DATA(pOutArray)) != CE_None)
+        {
+            Py_DECREF(pOutArray);
+            Py_RETURN_NONE;
+        }
+    }
+    else if( colType == GFT_Real )
+    {
+        pOutArray = PyArray_SimpleNew(1, &dims, NPY_DOUBLE);
+        if( GDALRATValuesIOAsDouble(poRAT, GF_Read, nField, nStart, nLength,
+                        (double*)PyArray_DATA(pOutArray)) != CE_None)
+        {
+            Py_DECREF(pOutArray);
+            Py_RETURN_NONE;
+        }
+    }
+    else if( colType == GFT_String )
+    {
+        // must read the data first to work out max size
+        // of strings to create array
+        int n;
+        char **papszStringList = (char**)CPLCalloc(sizeof(char*), nLength);
+        if( GDALRATValuesIOAsString(poRAT, GF_Read, nField, nStart, nLength, papszStringList) != CE_None )
+        {
+            CPLFree(papszStringList);
+            Py_RETURN_NONE;
+        }
+        int nMaxLen = 0, nLen;
+        for( n = 0; n < nLength; n++ )
+        {
+            // note strlen doesn't include null char
+            // but that is what numpy expects so all good
+            nLen = strlen(papszStringList[n]);
+            if( nLen > nMaxLen )
+                nMaxLen = nLen;
+        }
+        int bZeroLength = FALSE;
+        // numpy can't deal with zero length strings
+        if( nMaxLen == 0 )
+        {
+            nMaxLen = 1;
+            bZeroLength = TRUE;
+        }
+
+        // create the dtype string
+#if PY_VERSION_HEX >= 0x03000000
+        PyObject *pDTypeString = PyUnicode_FromFormat("S%d", nMaxLen);
+#else
+        PyObject *pDTypeString = PyString_FromFormat("S%d", nMaxLen);
+#endif
+        // out type description object
+        PyArray_Descr *pDescr;
+        PyArray_DescrConverter(pDTypeString, &pDescr);
+        Py_DECREF(pDTypeString);
+
+        // create array
+        pOutArray = PyArray_SimpleNewFromDescr(1, &dims, pDescr);
+
+        // copy data in
+        if( !bZeroLength )
+        {
+            for( n = 0; n < nLength; n++ )
+            {
+                // we use strncpy so that we don't go over nMaxLen
+                // which we would if the null char is copied
+                // (which we don't want as numpy 'knows' to interpret the string as nMaxLen long)
+                strncpy((char*)PyArray_GETPTR1(pOutArray, n), papszStringList[n], nMaxLen);
+            }
+        }
+        else
+        {
+            // so there isn't rubbish in the 1 char strings
+            PyArray_FILLWBYTE(pOutArray, 0);
+        }
+
+        // free strings
+        for( n = 0; n < nLength; n++ )
+        {
+            CPLFree(papszStringList[n]);
+        }
+        CPLFree(papszStringList);
+    }
+    return pOutArray;
+  }
+%}
+
+%pythoncode %{
+import numpy
+import _gdal_array
+
+import gdalconst
+import gdal
+gdal.AllRegister()
+
+codes = {   gdalconst.GDT_Byte      :   numpy.uint8,
+            gdalconst.GDT_UInt16    :   numpy.uint16,
+            gdalconst.GDT_Int16     :   numpy.int16,
+            gdalconst.GDT_UInt32    :   numpy.uint32,
+            gdalconst.GDT_Int32     :   numpy.int32,
+            gdalconst.GDT_Float32   :   numpy.float32,
+            gdalconst.GDT_Float64   :   numpy.float64,
+            gdalconst.GDT_CInt16    :   numpy.complex64,
+            gdalconst.GDT_CInt32    :   numpy.complex64,
+            gdalconst.GDT_CFloat32  :   numpy.complex64,
+            gdalconst.GDT_CFloat64  :   numpy.complex128
+        }
+
+def OpenArray( array, prototype_ds = None ):
+
+    ds = OpenNumPyArray( array )
+
+    if ds is not None and prototype_ds is not None:
+        if type(prototype_ds).__name__ == 'str':
+            prototype_ds = gdal.Open( prototype_ds )
+        if prototype_ds is not None:
+            CopyDatasetInfo( prototype_ds, ds )
+
+    return ds
+
+
+def flip_code(code):
+    if isinstance(code, (numpy.dtype,type)):
+        # since several things map to complex64 we must carefully select
+        # the opposite that is an exact match (ticket 1518)
+        if code == numpy.int8:
+            return gdalconst.GDT_Byte
+        if code == numpy.complex64:
+            return gdalconst.GDT_CFloat32
+
+        for key, value in codes.items():
+            if value == code:
+                return key
+        return None
+    else:
+        try:
+            return codes[code]
+        except KeyError:
+            return None
+
+def NumericTypeCodeToGDALTypeCode(numeric_type):
+    if not isinstance(numeric_type, (numpy.dtype,type)):
+        raise TypeError("Input must be a type")
+    return flip_code(numeric_type)
+
+def GDALTypeCodeToNumericTypeCode(gdal_code):
+    return flip_code(gdal_code)
+
+def LoadFile( filename, xoff=0, yoff=0, xsize=None, ysize=None,
+              buf_xsize=None, buf_ysize=None, buf_type=None,
+              resample_alg = gdal.GRIORA_NearestNeighbour,
+              callback=None, callback_data=None ):
+    ds = gdal.Open( filename )
+    if ds is None:
+        raise ValueError("Can't open "+filename+"\n\n"+gdal.GetLastErrorMsg())
+
+    return DatasetReadAsArray( ds, xoff, yoff, xsize, ysize,
+                               buf_xsize=buf_xsize, buf_ysize=buf_ysize, buf_type=buf_type,
+                               resample_alg=resample_alg,
+                               callback = callback, callback_data = callback_data )
+
+def SaveArray( src_array, filename, format = "GTiff", prototype = None ):
+    driver = gdal.GetDriverByName( format )
+    if driver is None:
+        raise ValueError("Can't find driver "+format)
+
+    return driver.CreateCopy( filename, OpenArray(src_array,prototype) )
+
+
+def DatasetReadAsArray( ds, xoff=0, yoff=0, win_xsize=None, win_ysize=None, buf_obj=None,
+                        buf_xsize = None, buf_ysize = None, buf_type = None,
+                        resample_alg = gdal.GRIORA_NearestNeighbour,
+                        callback=None, callback_data=None ):
+    """Pure python implementation of reading a chunk of a GDAL file
+    into a numpy array.  Used by the gdal.Dataset.ReadAsArray method."""
+
+    if win_xsize is None:
+        win_xsize = ds.RasterXSize
+    if win_ysize is None:
+        win_ysize = ds.RasterYSize
+
+    if ds.RasterCount == 0:
+        return None
+
+    if ds.RasterCount == 1:
+        return BandReadAsArray( ds.GetRasterBand(1), xoff, yoff, win_xsize, win_ysize,
+                                buf_xsize = buf_xsize, buf_ysize = buf_ysize, buf_type = buf_type,
+                                buf_obj = buf_obj,
+                                resample_alg = resample_alg,
+                                callback = callback,
+                                callback_data = callback_data )
+
+    if buf_obj is None:
+        if buf_xsize is None:
+            buf_xsize = win_xsize
+        if buf_ysize is None:
+            buf_ysize = win_ysize
+        if buf_type is None:
+            buf_type = ds.GetRasterBand(1).DataType
+            for band_index in range(2,ds.RasterCount+1):
+                if buf_type != ds.GetRasterBand(band_index).DataType:
+                    buf_type = gdalconst.GDT_Float32
+
+        typecode = GDALTypeCodeToNumericTypeCode( buf_type )
+        if typecode == None:
+            buf_type = gdalconst.GDT_Float32
+            typecode = numpy.float32
+        if buf_type == gdalconst.GDT_Byte and ds.GetRasterBand(1).GetMetadataItem('PIXELTYPE', 'IMAGE_STRUCTURE') == 'SIGNEDBYTE':
+            typecode = numpy.int8
+        buf_obj = numpy.empty([ds.RasterCount, buf_ysize,buf_xsize], dtype = typecode)
+
+    else:
+        if len(buf_obj.shape) != 3:
+            raise ValueError('Array should have 3 dimensions')
+
+        shape_buf_xsize = buf_obj.shape[2]
+        shape_buf_ysize = buf_obj.shape[1]
+        if buf_xsize is not None and buf_xsize != shape_buf_xsize:
+            raise ValueError('Specified buf_xsize not consistent with array shape')
+        if buf_ysize is not None and buf_ysize != shape_buf_ysize:
+            raise ValueError('Specified buf_ysize not consistent with array shape')
+        if buf_obj.shape[0] != ds.RasterCount:
+            raise ValueError('Array should have space for %d bands' % ds.RasterCount)
+
+        datatype = NumericTypeCodeToGDALTypeCode( buf_obj.dtype.type )
+        if not datatype:
+            raise ValueError("array does not have corresponding GDAL data type")
+        if buf_type is not None and buf_type != datatype:
+            raise ValueError("Specified buf_type not consistent with array type")
+        buf_type = datatype
+
+    if DatasetIONumPy( ds, 0, xoff, yoff, win_xsize, win_ysize,
+                       buf_obj, buf_type, resample_alg, callback, callback_data ) != 0:
+        return None
+
+    return buf_obj
+
+def BandReadAsArray( band, xoff = 0, yoff = 0, win_xsize = None, win_ysize = None,
+                     buf_xsize=None, buf_ysize=None, buf_type=None, buf_obj=None,
+                     resample_alg = gdal.GRIORA_NearestNeighbour,
+                     callback=None, callback_data=None):
+    """Pure python implementation of reading a chunk of a GDAL file
+    into a numpy array.  Used by the gdal.Band.ReadAsArray method."""
+
+    if win_xsize is None:
+        win_xsize = band.XSize
+    if win_ysize is None:
+        win_ysize = band.YSize
+
+    if buf_obj is None:
+        if buf_xsize is None:
+            buf_xsize = win_xsize
+        if buf_ysize is None:
+            buf_ysize = win_ysize
+        if buf_type is None:
+            buf_type = band.DataType
+
+        typecode = GDALTypeCodeToNumericTypeCode( buf_type )
+        if typecode == None:
+            buf_type = gdalconst.GDT_Float32
+            typecode = numpy.float32
+        else:
+            buf_type = NumericTypeCodeToGDALTypeCode( typecode )
+
+        if buf_type == gdalconst.GDT_Byte and band.GetMetadataItem('PIXELTYPE', 'IMAGE_STRUCTURE') == 'SIGNEDBYTE':
+            typecode = numpy.int8
+        buf_obj = numpy.empty([buf_ysize,buf_xsize], dtype = typecode)
+
+    else:
+        if len(buf_obj.shape) == 2:
+            shape_buf_xsize = buf_obj.shape[1]
+            shape_buf_ysize = buf_obj.shape[0]
+        else:
+            shape_buf_xsize = buf_obj.shape[2]
+            shape_buf_ysize = buf_obj.shape[1]
+        if buf_xsize is not None and buf_xsize != shape_buf_xsize:
+            raise ValueError('Specified buf_xsize not consistent with array shape')
+        if buf_ysize is not None and buf_ysize != shape_buf_ysize:
+            raise ValueError('Specified buf_ysize not consistent with array shape')
+
+        datatype = NumericTypeCodeToGDALTypeCode( buf_obj.dtype.type )
+        if not datatype:
+            raise ValueError("array does not have corresponding GDAL data type")
+        if buf_type is not None and buf_type != datatype:
+            raise ValueError("Specified buf_type not consistent with array type")
+        buf_type = datatype
+
+    if BandRasterIONumPy( band, 0, xoff, yoff, win_xsize, win_ysize,
+                          buf_obj, buf_type, resample_alg, callback, callback_data ) != 0:
+        return None
+
+    return buf_obj
+
+def BandWriteArray( band, array, xoff=0, yoff=0,
+                    resample_alg = gdal.GRIORA_NearestNeighbour,
+                    callback=None, callback_data=None ):
+    """Pure python implementation of writing a chunk of a GDAL file
+    from a numpy array.  Used by the gdal.Band.WriteArray method."""
+
+    if array is None or len(array.shape) != 2:
+        raise ValueError("expected array of dim 2")
+
+    xsize = array.shape[1]
+    ysize = array.shape[0]
+
+    if xsize + xoff > band.XSize or ysize + yoff > band.YSize:
+        raise ValueError("array larger than output file, or offset off edge")
+
+    datatype = NumericTypeCodeToGDALTypeCode( array.dtype.type )
+
+    # if we receive some odd type, like int64, try casting to a very
+    # generic type we do support (#2285)
+    if not datatype:
+        gdal.Debug( 'gdal_array', 'force array to float64' )
+        array = array.astype( numpy.float64 )
+        datatype = NumericTypeCodeToGDALTypeCode( array.dtype.type )
+
+    if not datatype:
+        raise ValueError("array does not have corresponding GDAL data type")
+
+    return BandRasterIONumPy( band, 1, xoff, yoff, xsize, ysize,
+                                array, datatype, resample_alg, callback, callback_data )
+
+def RATWriteArray(rat, array, field, start=0):
+    """
+    Pure Python implementation of writing a chunk of the RAT
+    from a numpy array. Type of array is coerced to one of the types
+    (int, double, string) supported. Called from RasterAttributeTable.WriteArray
+    """
+    if array is None:
+        raise ValueError("Expected array of dim 1")
+
+    # if not the array type convert it to handle lists etc
+    if not isinstance(array, numpy.ndarray):
+        array = numpy.array(array)
+
+    if array.ndim != 1:
+        raise ValueError("Expected array of dim 1")
+
+    if (start + array.size) > rat.GetRowCount():
+        raise ValueError("Array too big to fit into RAT from start position")
+
+    if numpy.issubdtype(array.dtype, numpy.integer):
+        # is some type of integer - coerce to standard int
+        # TODO: must check this is fine on all platforms
+        # confusingly numpy.int 64 bit even if native type 32 bit
+        array = array.astype(numpy.int32)
+    elif numpy.issubdtype(array.dtype, numpy.floating):
+        # is some type of floating point - coerce to double
+        array = array.astype(numpy.double)
+    elif numpy.issubdtype(array.dtype, numpy.character):
+        # cast away any kind of Unicode etc
+        array = array.astype(numpy.character)
+    else:
+        raise ValueError("Array not of a supported type (integer, double or string)")
+
+    return RATValuesIONumPyWrite(rat, field, start, array)
+
+def RATReadArray(rat, field, start=0, length=None):
+    """
+    Pure Python implementation of reading a chunk of the RAT
+    into a numpy array. Called from RasterAttributeTable.ReadAsArray
+    """
+    if length is None:
+        length = rat.GetRowCount() - start
+
+    return RATValuesIONumPyRead(rat, field, start, length)
+
+def CopyDatasetInfo( src, dst, xoff=0, yoff=0 ):
+    """
+    Copy georeferencing information and metadata from one dataset to another.
+    src: input dataset
+    dst: output dataset - It can be a ROI -
+    xoff, yoff:  dst's offset with respect to src in pixel/line.
+
+    Notes: Destination dataset must have update access.  Certain formats
+           do not support creation of geotransforms and/or gcps.
+
+    """
+
+    dst.SetMetadata( src.GetMetadata() )
+
+
+
+    #Check for geo transform
+    gt = src.GetGeoTransform()
+    if gt != (0,1,0,0,0,1):
+        dst.SetProjection( src.GetProjectionRef() )
+
+        if (xoff == 0) and (yoff == 0):
+            dst.SetGeoTransform( gt  )
+        else:
+            ngt = [gt[0],gt[1],gt[2],gt[3],gt[4],gt[5]]
+            ngt[0] = gt[0] + xoff*gt[1] + yoff*gt[2];
+            ngt[3] = gt[3] + xoff*gt[4] + yoff*gt[5];
+            dst.SetGeoTransform( ( ngt[0], ngt[1], ngt[2], ngt[3], ngt[4], ngt[5] ) )
+
+    #Check for GCPs
+    elif src.GetGCPCount() > 0:
+
+        if (xoff == 0) and (yoff == 0):
+            dst.SetGCPs( src.GetGCPs(), src.GetGCPProjection() )
+        else:
+            gcps = src.GetGCPs()
+            #Shift gcps
+            new_gcps = []
+            for gcp in gcps:
+                ngcp = gdal.GCP()
+                ngcp.GCPX = gcp.GCPX
+                ngcp.GCPY = gcp.GCPY
+                ngcp.GCPZ = gcp.GCPZ
+                ngcp.GCPPixel = gcp.GCPPixel - xoff
+                ngcp.GCPLine = gcp.GCPLine - yoff
+                ngcp.Info = gcp.Info
+                ngcp.Id = gcp.Id
+                new_gcps.append(ngcp)
+
+            try:
+                dst.SetGCPs( new_gcps , src.GetGCPProjection() )
+            except:
+                print ("Failed to set GCPs")
+                return
+
+    return
+%}
diff --git a/swig/include/gdalconst.i b/swig/include/gdalconst.i
index 4747239..a5338f2 100644
--- a/swig/include/gdalconst.i
+++ b/swig/include/gdalconst.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalconst.i 29019 2015-04-25 20:34:19Z rouault $
+ * $Id: gdalconst.i 32864 2016-01-08 21:00:50Z goatbar $
  *
  * Name:     gdalconst.i
  * Project:  GDAL Python Interface
@@ -33,7 +33,7 @@
 #elif defined(SWIGCSHARP)
 %module GdalConst
 #else
-%module gdalconst 
+%module gdalconst
 #endif
 
 #if defined(SWIGJAVA)
@@ -146,6 +146,7 @@
 %constant OF_ALL     = GDAL_OF_ALL;
 %constant OF_RASTER = GDAL_OF_RASTER;
 %constant OF_VECTOR = GDAL_OF_VECTOR;
+%constant OF_GNM = GDAL_OF_GNM;
 %constant OF_READONLY = GDAL_OF_READONLY;
 %constant OF_UPDATE = GDAL_OF_UPDATE;
 %constant OF_SHARED = GDAL_OF_SHARED;
@@ -207,8 +208,8 @@
 
 // GDALRATFieldType
 %constant GFT_Integer             = GFT_Integer;
-%constant GFT_Real                = GFT_Real;   
-%constant GFT_String              = GFT_String;  
+%constant GFT_Real                = GFT_Real;
+%constant GFT_String              = GFT_String;
 
 // GDALRATFieldUsage
 %constant GFU_Generic             = GFU_Generic;
diff --git a/swig/include/gnm.i b/swig/include/gnm.i
new file mode 100644
index 0000000..f6ef5e0
--- /dev/null
+++ b/swig/include/gnm.i
@@ -0,0 +1,384 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GNM Core SWIG Interface declarations.
+ * Purpose:  GNM declarations.
+ * Authors:  Mikhail Gusev (gusevmihs at gmail dot com)
+ *           Dmitry Baryshnikov, polimax at mail.ru
+ *
+ ******************************************************************************
+ * Copyright (c) 2014, Mikhail Gusev
+ * Copyright (c) 2014-2015, NextGIS <info at nextgis.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+//#ifndef FROM_GDAL_I
+%include "exception.i"
+//#endif
+%include constraints.i
+
+#ifdef PERL_CPAN_NAMESPACE
+%module "Geo::GNM"
+#elif defined(SWIGCSHARP)
+%module Gnm
+#else
+%module gnm
+#endif
+
+#ifdef SWIGCSHARP
+%include swig_csharp_extensions.i
+#endif
+
+#ifdef SWIGPERL
+%include confess.i
+#endif
+
+#ifndef SWIGJAVA
+%feature ("compactdefaultargs");
+#endif
+
+%{
+#include "gdal.h"
+#include "gnm_api.h"
+
+typedef void GDALMajorObjectShadow;
+typedef void GNMNetworkShadow;
+typedef void GNMGenericNetworkShadow;
+%}
+
+#if defined(SWIGPYTHON) || defined(SWIGJAVA) || defined(SWIGPERL)
+%{
+#ifdef DEBUG
+typedef struct OGRLayerHS OGRLayerShadow;
+typedef struct OGRFeatureHS OGRFeatureShadow;
+typedef struct OGRSpatialReferenceHS OSRSpatialReferenceShadow;
+#else
+typedef void OGRLayerShadow;
+typedef void OGRFeatureShadow;
+typedef void OSRSpatialReferenceShadow;
+#endif
+%}
+#endif /* #if defined(SWIGPYTHON) || defined(SWIGJAVA) */
+
+
+#if defined(SWIGPYTHON)
+%include python_exceptions.i
+%include python_strings.i
+%include typemaps_python.i
+#elif defined(SWIGRUBY)
+//%include typemaps_ruby.i
+#elif defined(SWIGPHP4)
+//%include typemaps_php.i
+#elif defined(SWIGCSHARP)
+//%include gnm_csharp.i
+#elif defined(SWIGJAVA)
+//%include gnm_java.i
+#elif defined(SWIGPERL)
+//%include gnm_perl.i
+%import typemaps_perl.i
+#else
+%include gdal_typemaps.i
+#endif
+
+typedef int CPLErr;
+typedef int GNMDirection;
+
+//************************************************************************
+//
+// Define the MajorObject object
+//
+//************************************************************************
+%include "MajorObject.i"
+
+%feature("autodoc");
+
+// Redefine AlgorithmType
+%rename (GraphAlgorithm) GNMGraphAlgorithmType;
+typedef enum
+{
+    GATDijkstraShortestPath = 1,
+    GATKShortestPath = 2,
+    GATConnectedComponents = 3
+} GNMGraphAlgorithmType;
+
+#define GNMGFID GIntBig
+#define GNM_EDGE_DIR_BOTH       0   // bidirectional
+#define GNM_EDGE_DIR_SRCTOTGT   1   // from source to target
+#define GNM_EDGE_DIR_TGTTOSRC   2   // from target to source
+
+%inline %{
+  GNMNetworkShadow* CastToNetwork(GDALMajorObjectShadow* base) {
+      return (GNMNetworkShadow*)dynamic_cast<GNMNetwork*>((GDALMajorObject*)base);
+  }
+%}
+
+%inline %{
+  GNMGenericNetworkShadow* CastToGenericNetwork(GDALMajorObjectShadow* base) {
+      return (GNMGenericNetworkShadow*)dynamic_cast<GNMGenericNetwork*>((GDALMajorObject*)base);
+  }
+%}
+
+#if !defined(FROM_GDAL_I) && !defined(FROM_OGR_I)
+%inline %{
+typedef char retStringAndCPLFree;
+%}
+#endif
+
+/************************************************************************/
+/*                       GNMNetworkShadow                               */
+/************************************************************************/
+
+%rename (Network) GNMNetworkShadow;
+
+class GNMNetworkShadow : public GDALMajorObjectShadow
+{
+    GNMNetworkShadow(){}
+
+    public:
+
+    %extend
+    {
+        ~GNMNetworkShadow()
+        {
+            if ( GDALDereferenceDataset( self ) <= 0 ) {
+              GDALClose(self);
+            }
+        }
+
+        %apply SWIGTYPE *DISOWN {OGRLayerShadow *layer};
+        void ReleaseResultSet(OGRLayerShadow *layer){
+            GDALDatasetReleaseResultSet(self, layer);
+        }
+        %clear OGRLayerShadow *layer;
+
+        int GetVersion()
+        {
+            return GNMGetVersion(self);
+        }
+
+        char const *GetName()
+        {
+            return GNMGetName(self);
+        }
+
+        %newobject GetFeatureByGlobalFID;
+        OGRFeatureShadow *GetFeatureByGlobalFID (GNMGFID GFID)
+        {
+            return GNMGetFeatureByGlobalFID(self, GFID);
+        }
+
+        %newobject GetPath;
+        #ifndef SWIGJAVA
+        %feature( "kwargs" ) GetPath;
+        #endif
+        OGRLayerShadow *GetPath (GNMGFID nStartFID, GNMGFID nEndFID,
+                                 GNMGraphAlgorithmType eAlgorithm,
+                                 char **options = 0)
+        {
+            return GNMGetPath(self, nStartFID, nEndFID, eAlgorithm, options);
+        }
+
+        CPLErr DisconnectAll() {
+            return GNMDisconnectAll( self );
+        }
+
+        char const *GetProjection() {
+            return GDALGetProjectionRef( self );
+        }
+
+        char const *GetProjectionRef() {
+            return GDALGetProjectionRef( self );
+        }
+
+        %apply (char **CSL) {char **};
+        char **GetFileList() {
+            return GDALGetFileList( self );
+        }
+        %clear char **;
+
+        /* Note that datasources own their layers */
+        #ifndef SWIGJAVA
+        %feature( "kwargs" ) CreateLayer;
+        #endif
+        OGRLayerShadow *CreateLayer(const char* name,
+              OSRSpatialReferenceShadow* srs=NULL,
+              OGRwkbGeometryType geom_type=wkbUnknown,
+              char** options=0) {
+            OGRLayerShadow* layer = (OGRLayerShadow*) GDALDatasetCreateLayer( self,
+                                      name,
+                                      srs,
+                                      geom_type,
+                                      options);
+            return layer;
+        }
+
+        #ifndef SWIGJAVA
+        %feature( "kwargs" ) CopyLayer;
+        #endif
+        %apply Pointer NONNULL {OGRLayerShadow *src_layer};
+        OGRLayerShadow *CopyLayer(OGRLayerShadow *src_layer,
+            const char* new_name,
+            char** options=0) {
+            OGRLayerShadow* layer = (OGRLayerShadow*) GDALDatasetCopyLayer( self,
+                                                      src_layer,
+                                                      new_name,
+                                                      options);
+            return layer;
+        }
+
+        OGRErr DeleteLayer(int index){
+            return GDALDatasetDeleteLayer(self, index);
+        }
+
+        int GetLayerCount() {
+            return GDALDatasetGetLayerCount(self);
+        }
+
+        #ifdef SWIGJAVA
+        OGRLayerShadow *GetLayerByIndex( int index ) {
+        #else
+        OGRLayerShadow *GetLayerByIndex( int index=0) {
+        #endif
+        OGRLayerShadow* layer = (OGRLayerShadow*) GDALDatasetGetLayer(self,
+                                                                      index);
+            return layer;
+        }
+
+        OGRLayerShadow *GetLayerByName( const char* layer_name) {
+            OGRLayerShadow* layer =
+                  (OGRLayerShadow*) GDALDatasetGetLayerByName(self, layer_name);
+            return layer;
+        }
+
+        bool TestCapability(const char * cap) {
+            return (GDALDatasetTestCapability(self, cap) > 0);
+        }
+
+        #ifndef SWIGJAVA
+        %feature( "kwargs" ) StartTransaction;
+        #endif
+        OGRErr StartTransaction(int force = FALSE)
+        {
+            return GDALDatasetStartTransaction(self, force);
+        }
+
+        OGRErr CommitTransaction()
+        {
+            return GDALDatasetCommitTransaction(self);
+        }
+
+        OGRErr RollbackTransaction()
+        {
+            return GDALDatasetRollbackTransaction(self);
+        }
+
+    }
+};
+
+/************************************************************************/
+/*                   GNMGenericNetworkShadow                            */
+/************************************************************************/
+
+%rename (GenericNetwork) GNMGenericNetworkShadow;
+
+class GNMGenericNetworkShadow : public GNMNetworkShadow
+{
+    GNMGenericNetworkShadow(){}
+
+    public:
+
+    %extend
+    {
+        ~GNMGenericNetworkShadow()
+        {
+            if ( GDALDereferenceDataset( self ) <= 0 ) {
+              GDALClose(self);
+            }
+        }
+
+        CPLErr ConnectFeatures (GNMGFID nSrcFID, GNMGFID nTgtFID,
+                                GNMGFID nConFID, double dfCost,
+                                double dfInvCost,
+                                GNMDirection eDir) {
+            return GNMConnectFeatures(self, nSrcFID, nTgtFID,
+                                              nConFID, dfCost, dfInvCost, eDir);
+        }
+
+        CPLErr DisconnectFeatures (GNMGFID nSrcFID, GNMGFID nTgtFID,
+                                   GNMGFID nConFID) {
+            return GNMDisconnectFeatures(self, nSrcFID, nTgtFID,
+                                                           nConFID);
+        }
+
+        CPLErr DisconnectFeaturesWithId(GNMGFID nFID) {
+            return GNMDisconnectFeaturesWithId(self, nFID);
+        }
+
+        CPLErr ReconnectFeatures (GNMGFID nSrcFID, GNMGFID nTgtFID, GNMGFID nConFID,
+                                  double dfCost, double dfInvCost,
+                                  GNMDirection eDir) {
+            return GNMReconnectFeatures(self, nSrcFID, nTgtFID, nConFID, dfCost, dfInvCost, eDir);
+        }
+
+        %apply Pointer NONNULL {const char * pszRuleStr};
+        CPLErr CreateRule (const char *pszRuleStr) {
+            return GNMCreateRule(self, pszRuleStr);
+        }
+        %clear const char * pszRuleStr;
+
+        CPLErr DeleteAllRules() {
+            return GNMDeleteAllRules(self);
+        }
+
+        %apply Pointer NONNULL {const char * pszRuleStr};
+        CPLErr DeleteRule(const char *pszRuleStr) {
+            return GNMDeleteRule(self, pszRuleStr);
+        }
+        %clear const char * pszRuleStr;
+
+        %apply (char **CSL) {char **};
+        char** GetRules() {
+            return GNMGetRules(self);
+        }
+        %clear char **;
+
+        #ifndef SWIGJAVA
+        %feature( "kwargs" ) ConnectPointsByLines;
+        #endif
+        %apply (char **options) { char ** papszLayerList };
+        CPLErr ConnectPointsByLines (char **papszLayerList,
+                                         double dfTolerance,
+                                         double dfCost,
+                                         double dfInvCost,
+                                         GNMDirection eDir) {
+            return GNMConnectPointsByLines(self, papszLayerList, dfTolerance, dfCost, dfInvCost, eDir);
+        }
+        %clear char **papszLayerList;
+
+        CPLErr ChangeBlockState (GNMGFID nFID, bool bIsBlock) {
+            return GNMChangeBlockState(self, nFID, bIsBlock);
+        }
+
+        CPLErr ChangeAllBlockState (bool bIsBlock = false) {
+            return GNMChangeAllBlockState(self, bIsBlock);
+        }
+    }
+};
+
diff --git a/swig/include/java/callback.i b/swig/include/java/callback.i
index 160041a..eabd9d4 100644
--- a/swig/include/java/callback.i
+++ b/swig/include/java/callback.i
@@ -1,9 +1,7 @@
-
 /************************************************************************/
 /*                       Stuff for progress callback                    */
 /************************************************************************/
 
-
 %header %{
 typedef struct {
     JNIEnv *jenv;
diff --git a/swig/include/java/gdal_java.i b/swig/include/java/gdal_java.i
index f7b8fa5..b2c9c9c 100644
--- a/swig/include/java/gdal_java.i
+++ b/swig/include/java/gdal_java.i
@@ -1,20 +1,11 @@
 /******************************************************************************
- * $Id: gdal_java.i 28053 2014-12-04 09:31:07Z rouault $
+ * $Id: gdal_java.i 33123 2016-01-23 18:59:28Z rouault $
  *
  * Name:     gdal_java.i
  * Project:  GDAL SWIG Interface
  * Purpose:  Typemaps for Java bindings
  * Author:   Benjamin Collins, The MITRE Corporation
  *
- *
- * $Log$
- * Revision 1.2  2006/02/16 17:21:12  collinsb
- * Updates to Java bindings to keep the code from halting execution if the native libraries cannot be found.
- *
- * Revision 1.1  2006/02/02 20:56:07  collinsb
- * Added Java specific typemap code
- *
- *
 */
 
 %include java_exceptions.i
@@ -26,19 +17,19 @@
     try {
       System.loadLibrary("gdaljni");
       available = true;
-      
+
       if (gdal.HasThreadSupport() == 0)
       {
         System.err.println("WARNING : GDAL should be compiled with thread support for safe execution in Java.");
       }
-      
+
     } catch (UnsatisfiedLinkError e) {
       available = false;
       System.err.println("Native library load failed.");
       System.err.println(e);
     }
   }
-  
+
   public static boolean isAvailable() {
     return available;
   }
@@ -190,7 +181,7 @@ import org.gdal.gdalconst.gdalconstConstants;
       GetGCPs(gcps);
       return gcps;
   }
-  
+
   public double[] GetGeoTransform() {
       double adfGeoTransform[] = new double[6];
       GetGeoTransform(adfGeoTransform);
@@ -256,7 +247,7 @@ static CPLErr DatasetRasterIO( GDALDatasetH hDS, GDALRWFlag eRWFlag,
               "Java array type is not compatible with GDAL data type");
       return CE_Failure;
   }
-    
+
   if (band_list == 0)
   {
       if (pband_list != NULL)
@@ -344,13 +335,13 @@ CPLErr ReadRaster( int xoff, int yoff, int xsize, int ysize,
                               gdal_type, sizeof(ctype));
 }
   %enddef
-  
+
   DEFINE_DS_READ_RASTER(char, GDT_Byte)
   DEFINE_DS_READ_RASTER(short, GDT_Int16)
   DEFINE_DS_READ_RASTER(int, GDT_Int32)
   DEFINE_DS_READ_RASTER(float, GDT_Float32)
   DEFINE_DS_READ_RASTER(double, GDT_Float64)
-  
+
 
   CPLErr WriteRaster_Direct( int xoff, int yoff, int xsize, int ysize,
                             int buf_xsize, int buf_ysize,
@@ -387,7 +378,7 @@ CPLErr ReadRaster( int xoff, int yoff, int xsize, int ysize,
                               gdal_type, sizeof(ctype));
 }
  %enddef
-    
+
   DEFINE_DS_WRITE_RASTER(char, GDT_Byte)
   DEFINE_DS_WRITE_RASTER(short, GDT_Int16)
   DEFINE_DS_WRITE_RASTER(int, GDT_Int32)
@@ -422,7 +413,7 @@ static CPLErr BandRasterIO( GDALRasterBandH hBand, GDALRWFlag eRWFlag,
                 "Java array type is not compatible with GDAL data type");
         return CE_Failure;
     }
-  
+
     GIntBig nMinBufferSizeInBytes = ComputeBandRasterIOSize (
                             buf_xsize, buf_ysize, GDALGetDataTypeSize(buf_type) / 8,
                             nPixelSpace, nLineSpace, sizeof_ctype > 1 );
@@ -479,13 +470,13 @@ static CPLErr BandRasterIO( GDALRasterBandH hBand, GDALRWFlag eRWFlag,
                          gdal_type, sizeof(ctype) );
   }
   %enddef
-  
+
   DEFINE_READ_RASTER(char, GDT_Byte)
   DEFINE_READ_RASTER(short, GDT_Int16)
   DEFINE_READ_RASTER(int, GDT_Int32)
   DEFINE_READ_RASTER(float, GDT_Float32)
   DEFINE_READ_RASTER(double, GDT_Float64)
-  
+
   CPLErr WriteRaster_Direct( int xoff, int yoff, int xsize, int ysize,
                             int buf_xsize, int buf_ysize,
                             GDALDataType buf_type,
@@ -500,7 +491,7 @@ static CPLErr BandRasterIO( GDALRasterBandH hBand, GDALRWFlag eRWFlag,
                          nPixelSpace, nLineSpace,
                          GDT_Unknown, 0 );
   }
-  
+
   %define DEFINE_WRITE_RASTER(ctype, gdal_type)
   CPLErr WriteRaster( int xoff, int yoff, int xsize, int ysize,
                             int buf_xsize, int buf_ysize,
@@ -517,13 +508,13 @@ static CPLErr BandRasterIO( GDALRasterBandH hBand, GDALRWFlag eRWFlag,
                          gdal_type, sizeof(ctype) );
   }
   %enddef
-  
+
   DEFINE_WRITE_RASTER(char, GDT_Byte)
   DEFINE_WRITE_RASTER(short, GDT_Int16)
   DEFINE_WRITE_RASTER(int, GDT_Int32)
   DEFINE_WRITE_RASTER(float, GDT_Float32)
   DEFINE_WRITE_RASTER(double, GDT_Float64)
-  
+
   CPLErr ReadBlock_Direct( int nXBlockOff, int nYBlockOff, void *nioBuffer, long nioBufferSize )
   {
     if (BandBlockReadWrite_Validate((GDALRasterBandH)self, nioBuffer, nioBufferSize) != CE_None)
@@ -563,7 +554,7 @@ static CPLErr BandRasterIO( GDALRasterBandH hBand, GDALRWFlag eRWFlag,
                      bool approx_ok,
                      GDALProgressFunc callback,
                      void* callback_data) {
-    CPLErrorReset(); 
+    CPLErrorReset();
     CPLErr err = GDALGetRasterHistogram( self, min, max, buckets, panHistogram,
                                          include_out_of_range, approx_ok,
                                          callback, callback_data );
@@ -576,7 +567,7 @@ static CPLErr BandRasterIO( GDALRasterBandH hBand, GDALRWFlag eRWFlag,
                       int *panHistogram,
                       bool include_out_of_range,
                       bool approx_ok) {
-    CPLErrorReset(); 
+    CPLErrorReset();
     CPLErr err = GDALGetRasterHistogram( self, min, max, buckets, panHistogram,
                                          include_out_of_range, approx_ok,
                                          NULL, NULL);
@@ -587,7 +578,7 @@ static CPLErr BandRasterIO( GDALRasterBandH hBand, GDALRWFlag eRWFlag,
                       double max,
                       int buckets,
                       int *panHistogram) {
-    CPLErrorReset(); 
+    CPLErrorReset();
     CPLErr err = GDALGetRasterHistogram( self, min, max, buckets, panHistogram,
                                          0, 1,
                                          NULL, NULL);
@@ -596,7 +587,7 @@ static CPLErr BandRasterIO( GDALRasterBandH hBand, GDALRWFlag eRWFlag,
 
   CPLErr GetHistogram(int buckets,
                         int *panHistogram) {
-    CPLErrorReset(); 
+    CPLErrorReset();
     CPLErr err = GDALGetRasterHistogram( self, -0.5, 255.5, buckets, panHistogram,
                                          0, 1,
                                          NULL, NULL);
@@ -606,12 +597,12 @@ static CPLErr BandRasterIO( GDALRasterBandH hBand, GDALRWFlag eRWFlag,
 
 %apply (int* pnList, int** ppListOut) {(int* buckets_ret, int **ppanHistogram)};
 %apply (double *OUTPUT){double *min_ret, double *max_ret}
-  CPLErr GetDefaultHistogram( double *min_ret, double *max_ret, int* buckets_ret, 
-                              int **ppanHistogram, bool force = 1, 
+  CPLErr GetDefaultHistogram( double *min_ret, double *max_ret, int* buckets_ret,
+                              int **ppanHistogram, bool force = 1,
                               GDALProgressFunc callback = NULL,
                               void* callback_data=NULL ) {
       return GDALGetDefaultHistogram( self, min_ret, max_ret, buckets_ret,
-                                      ppanHistogram, force, 
+                                      ppanHistogram, force,
                                       callback, callback_data );
   }
 %clear (double *min_ret, double *max_ret);
@@ -657,7 +648,7 @@ import java.awt.Color;
       return Clone();
   }
 
-/* convienance method */
+  // Convenience method.
   public IndexColorModel getIndexColorModel(int bits) {
     int size = GetCount();
     byte[] reds = new byte[size];
@@ -677,7 +668,7 @@ import java.awt.Color;
       byte alpha = (byte)(entry.getAlpha()&0xff);
 
       // The byte type is -128 to 127 so a normal 255 will be -1.
-      if (alpha == -1) 
+      if (alpha == -1)
           noAlphas ++;
       else{
         if (alpha == 0){
@@ -691,7 +682,7 @@ import java.awt.Color;
         return new IndexColorModel(bits, size, reds, greens, blues);
     else if (noAlphas == (size - 1) && zeroAlphas == 1)
         return new IndexColorModel(bits, size, reds, greens, blues, lastAlphaIndex);
-    else 
+    else
         return new IndexColorModel(bits, size, reds, greens, blues, alphas);
  }
 %}
@@ -779,7 +770,7 @@ import org.gdal.gdalconst.gdalconstConstants;
    public int ReadRaster(int xoff, int yoff, int xsize, int ysize, byte[] array) {
        return ReadRaster(xoff, yoff, xsize, ysize, xsize, ysize, gdalconstConstants.GDT_Byte, array);
    }
-   
+
    public int ReadRaster(int xoff, int yoff, int xsize, int ysize, int buf_type, short[] array) {
        return ReadRaster(xoff, yoff, xsize, ysize, xsize, ysize, buf_type, array);
    }
@@ -787,31 +778,31 @@ import org.gdal.gdalconst.gdalconstConstants;
    public int ReadRaster(int xoff, int yoff, int xsize, int ysize, short[] array) {
        return ReadRaster(xoff, yoff, xsize, ysize, xsize, ysize, gdalconstConstants.GDT_Int16, array);
    }
-   
+
    public int ReadRaster(int xoff, int yoff, int xsize, int ysize, int buf_type, int[] array) {
        return ReadRaster(xoff, yoff, xsize, ysize, xsize, ysize, buf_type, array);
    }
-   
+
    public int ReadRaster(int xoff, int yoff, int xsize, int ysize, int[] array) {
        return ReadRaster(xoff, yoff, xsize, ysize, xsize, ysize, gdalconstConstants.GDT_Int32, array);
    }
-   
+
    public int ReadRaster(int xoff, int yoff, int xsize, int ysize, int buf_type, float[] array) {
        return ReadRaster(xoff, yoff, xsize, ysize, xsize, ysize, buf_type, array);
    }
-   
+
    public int ReadRaster(int xoff, int yoff, int xsize, int ysize, float[] array) {
        return ReadRaster(xoff, yoff, xsize, ysize, xsize, ysize, gdalconstConstants.GDT_Float32, array);
    }
-   
+
    public int ReadRaster(int xoff, int yoff, int xsize, int ysize, int buf_type, double[] array) {
        return ReadRaster(xoff, yoff, xsize, ysize, xsize, ysize, buf_type, array);
    }
-   
+
    public int ReadRaster(int xoff, int yoff, int xsize, int ysize, double[] array) {
        return ReadRaster(xoff, yoff, xsize, ysize, xsize, ysize, gdalconstConstants.GDT_Float64, array);
    }
-   
+
    public int WriteRaster_Direct(int xoff, int yoff, int xsize, int ysize,
                                 int buf_xsize, int buf_ysize, java.nio.ByteBuffer nioBuffer) {
        return WriteRaster_Direct(xoff, yoff, xsize, ysize, buf_xsize, buf_ysize, gdalconstConstants.GDT_Byte, nioBuffer);
@@ -834,7 +825,7 @@ import org.gdal.gdalconst.gdalconstConstants;
    public int WriteRaster(int xoff, int yoff, int xsize, int ysize, byte[] array) {
        return WriteRaster(xoff, yoff, xsize, ysize, xsize, ysize, gdalconstConstants.GDT_Byte, array);
    }
-   
+
    public int WriteRaster(int xoff, int yoff, int xsize, int ysize, int buf_type, short[] array) {
        return WriteRaster(xoff, yoff, xsize, ysize, xsize, ysize, buf_type, array);
    }
@@ -842,27 +833,27 @@ import org.gdal.gdalconst.gdalconstConstants;
    public int WriteRaster(int xoff, int yoff, int xsize, int ysize, short[] array) {
        return WriteRaster(xoff, yoff, xsize, ysize, xsize, ysize, gdalconstConstants.GDT_Int16, array);
    }
-   
+
    public int WriteRaster(int xoff, int yoff, int xsize, int ysize, int buf_type, int[] array) {
        return WriteRaster(xoff, yoff, xsize, ysize, xsize, ysize, buf_type, array);
    }
-   
+
    public int WriteRaster(int xoff, int yoff, int xsize, int ysize, int[] array) {
        return WriteRaster(xoff, yoff, xsize, ysize, xsize, ysize, gdalconstConstants.GDT_Int32, array);
    }
-   
+
    public int WriteRaster(int xoff, int yoff, int xsize, int ysize, int buf_type, float[] array) {
        return WriteRaster(xoff, yoff, xsize, ysize, xsize, ysize, buf_type, array);
    }
-   
+
    public int WriteRaster(int xoff, int yoff, int xsize, int ysize, float[] array) {
        return WriteRaster(xoff, yoff, xsize, ysize, xsize, ysize, gdalconstConstants.GDT_Float32, array);
    }
-   
+
    public int WriteRaster(int xoff, int yoff, int xsize, int ysize, int buf_type, double[] array) {
        return WriteRaster(xoff, yoff, xsize, ysize, xsize, ysize, buf_type, array);
    }
-   
+
    public int WriteRaster(int xoff, int yoff, int xsize, int ysize, double[] array) {
        return WriteRaster(xoff, yoff, xsize, ysize, xsize, ysize, gdalconstConstants.GDT_Float64, array);
    }
@@ -926,7 +917,7 @@ import org.gdal.gdalconst.gdalconstConstants;
     parentReference = reference;
   }
 
-  /* For backward compatibilty */
+  /* For backward compatibility */
   public int SetMetadata(java.util.Hashtable metadata, String domain)
   {
       if (metadata == null)
diff --git a/swig/include/java/gdalconst_java.i b/swig/include/java/gdalconst_java.i
index 6c75ba1..87cb963 100644
--- a/swig/include/java/gdalconst_java.i
+++ b/swig/include/java/gdalconst_java.i
@@ -1,20 +1,11 @@
 /******************************************************************************
- * $Id: gdalconst_java.i 21579 2011-01-24 21:57:24Z rouault $
+ * $Id: gdalconst_java.i 32864 2016-01-08 21:00:50Z goatbar $
  *
  * Name:     gdalconst_java.i
  * Project:  GDAL SWIG Interface
  * Purpose:  Typemaps for Java bindings
  * Author:   Benjamin Collins, The MITRE Corporation
  *
- *
- * $Log$
- * Revision 1.2  2006/02/16 17:21:12  collinsb
- * Updates to Java bindings to keep the code from halting execution if the native libraries cannot be found.
- *
- * Revision 1.1  2006/02/02 20:56:07  collinsb
- * Added Java specific typemap code
- *
- *
 */
 
 %pragma(java) jniclasscode=%{
@@ -30,7 +21,7 @@
       System.err.println(e);
     }
   }
-  
+
   public static boolean isAvailable() {
     return available;
   }
diff --git a/swig/include/java/java_exceptions.i b/swig/include/java/java_exceptions.i
index 223aac3..8361937 100644
--- a/swig/include/java/java_exceptions.i
+++ b/swig/include/java/java_exceptions.i
@@ -6,8 +6,8 @@
 %{
 static int bUseExceptions=1;
 
-void CPL_STDCALL 
-VeryQuietErrorHandler(CPLErr eclass, int code, const char *msg ) 
+void CPL_STDCALL
+VeryQuietErrorHandler(CPLErr eclass, int code, const char *msg )
 {
   /* If the error class is CE_Fatal, we want to have a message issued
      because the CPL support code does an abort() before any exception
diff --git a/swig/include/java/ogr_java.i b/swig/include/java/ogr_java.i
index 1ccf5a0..46ae178 100644
--- a/swig/include/java/ogr_java.i
+++ b/swig/include/java/ogr_java.i
@@ -1,20 +1,11 @@
 /******************************************************************************
- * $Id: ogr_java.i 27568 2014-08-05 13:10:20Z tamas $
+ * $Id: ogr_java.i 32864 2016-01-08 21:00:50Z goatbar $
  *
  * Name:     ogr_java.i
  * Project:  GDAL SWIG Interface
  * Purpose:  Typemaps for Java bindings
  * Author:   Benjamin Collins, The MITRE Corporation
  *
- *
- * $Log$
- * Revision 1.2  2006/02/16 17:21:12  collinsb
- * Updates to Java bindings to keep the code from halting execution if the native libraries cannot be found.
- *
- * Revision 1.1  2006/02/02 20:56:07  collinsb
- * Added Java specific typemap code
- *
- *
 */
 
 #ifndef FROM_GDAL_I
@@ -28,19 +19,19 @@
     try {
       System.loadLibrary("ogrjni");
       available = true;
-      
+
       if (org.gdal.gdal.gdal.HasThreadSupport() == 0)
       {
         System.err.println("WARNING : GDAL should be compiled with thread support for safe execution in Java.");
       }
-      
+
     } catch (UnsatisfiedLinkError e) {
       available = false;
       System.err.println("Native library load failed.");
       System.err.println(e);
     }
   }
-  
+
   public static boolean isAvailable() {
     return available;
   }
@@ -55,14 +46,14 @@
 
 /*
  *
- */ 
- 
+ */
+
 %pragma(java) jniclassimports=%{
 import org.gdal.osr.SpatialReference;
 import org.gdal.osr.CoordinateTransformation;
 import org.gdal.gdal.MajorObject;
 %}
- 
+
 %pragma(java) moduleimports=%{
 import org.gdal.osr.SpatialReference;
 import org.gdal.gdal.MajorObject;
@@ -352,8 +343,9 @@ import org.gdal.osr.CoordinateTransformation;
 
 /* ------------------------------------------------------------------- */
 /* Below an advanced technique to avoid the use of a finalize() method */
-/* in the Feature object, that prevents efficient garbarge collection. */
+/* in the Feature object, that prevents efficient garbage collection.  */
 /* This is loosely based on ideas from an article at                   */
+ // TODO: Broken URL.
 /* http://java.sun.com/developer/technicalArticles/javase/finalization */
 /* ------------------------------------------------------------------- */
 
@@ -366,7 +358,7 @@ import org.gdal.osr.CoordinateTransformation;
   static private Thread cleanupThread = null;
 
   /* We start a cleanup thread in daemon mode */
-  /* If we can't, we'll cleanup garbaged features at creation time */
+  /* If we cannot, we will cleanup garbage features at creation time */
   static
   {
     cleanupThread = new Thread() {
@@ -470,7 +462,7 @@ class%}
     if (cMemoryOwn)
         nativeObject = new type ## Native(this, cPtr);
   }
-  
+
   public static long getCPtr($javaclassname obj) {
     return (obj == null) ? 0 : obj.swigCPtr;
   }
diff --git a/swig/include/java/ogr_java_extend.i b/swig/include/java/ogr_java_extend.i
index d651338..de8dce3 100644
--- a/swig/include/java/ogr_java_extend.i
+++ b/swig/include/java/ogr_java_extend.i
@@ -3,11 +3,11 @@
  *
  * Name:     ogr_java_extend.i
  * Project:  GDAL SWIG Interface
- * Purpose:  Java specific OGR extensions 
+ * Purpose:  Java specific OGR extensions
  * Author:   Andrea Aime (andrea.aime at gmail.com)
  *
  */
- 
+
 /******************************************************************************
  * OGR WKB import and  export. Both extensions make sure byte[] is used in    *
  * java instead of char[]                                                     *
@@ -51,7 +51,7 @@
     }
 %}
 
-%extend OGRGeometryShadow 
+%extend OGRGeometryShadow
 {
   OGRGeometryShadow( OGRwkbGeometryType type, char *wkt, int nLen, unsigned char *pBuf, const char *gml ) {
     if (type != wkbUnknown ) {
diff --git a/swig/include/java/osr_java.i b/swig/include/java/osr_java.i
index 008a398..5241acc 100644
--- a/swig/include/java/osr_java.i
+++ b/swig/include/java/osr_java.i
@@ -1,20 +1,11 @@
 /******************************************************************************
- * $Id: osr_java.i 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: osr_java.i 32864 2016-01-08 21:00:50Z goatbar $
  *
  * Name:     osr_java.i
  * Project:  GDAL SWIG Interface
  * Purpose:  Typemaps for Java bindings
  * Author:   Benjamin Collins, The MITRE Corporation
  *
- *
- * $Log$
- * Revision 1.2  2006/02/16 17:21:12  collinsb
- * Updates to Java bindings to keep the code from halting execution if the native libraries cannot be found.
- *
- * Revision 1.1  2006/02/02 20:56:07  collinsb
- * Added Java specific typemap code
- *
- *
 */
 
 %include arrays_java.i
@@ -37,7 +28,7 @@
       System.err.println(e);
     }
   }
-  
+
   public static boolean isAvailable() {
     return available;
   }
@@ -58,8 +49,8 @@
 /*
  *  Needed to make the Constructor and getCptr 'public' and not 'protected'.
  *   There is likely a better way to do this (with javamethodmodifiers) but
- *   none worked for me. 
- */ 
+ *   none worked for me.
+ */
 %typemap(javabody) OSRSpatialReferenceShadow, OSRCoordinateTransformationShadow %{
   private long swigCPtr;
   protected boolean swigCMemOwn;
@@ -68,7 +59,7 @@
     swigCMemOwn = cMemoryOwn;
     swigCPtr = cPtr;
   }
-  
+
   public static long getCPtr($javaclassname obj) {
     return (obj == null) ? 0 : obj.swigCPtr;
   }
@@ -143,7 +134,7 @@
       GetTOWGS84(array);
       return array;
   }
-  
+
   public int SetTOWGS84( double p1, double p2, double p3)
   {
       return SetTOWGS84(p1, p2, p3, 0, 0, 0, 0);
@@ -169,7 +160,7 @@
       return osr.CreateCoordinateTransformation(src, dst);
   }
 %}
-    
+
 /******************************************************************************
  *
  *  Global methods
@@ -186,7 +177,7 @@ retStringAndCPLFree* GetWellKnownGeogCSAsWKT( const char *name ) {
   OGRSpatialReferenceH srs = OSRNewSpatialReference("");
   OGRErr rcode = OSRSetWellKnownGeogCS( srs, name );
   if( rcode == OGRERR_NONE )
-      rcode = OSRExportToWkt ( srs, &argout );  
+      rcode = OSRExportToWkt ( srs, &argout );
   OSRDestroySpatialReference( srs );
   return argout;
 }
@@ -201,7 +192,7 @@ retStringAndCPLFree* GetUserInputAsWKT( const char *name ) {
   OGRSpatialReferenceH srs = OSRNewSpatialReference("");
   OGRErr rcode = OSRSetFromUserInput( srs, name );
   if( rcode == OGRERR_NONE )
-      rcode = OSRExportToWkt ( srs, &argout );  
+      rcode = OSRExportToWkt ( srs, &argout );
   OSRDestroySpatialReference( srs );
   return argout;
 }
diff --git a/swig/include/java/typemaps_java.i b/swig/include/java/typemaps_java.i
index 1c3415f..dd11e96 100644
--- a/swig/include/java/typemaps_java.i
+++ b/swig/include/java/typemaps_java.i
@@ -1,20 +1,11 @@
 /******************************************************************************
- * $Id: typemaps_java.i 29225 2015-05-21 16:28:00Z rouault $
+ * $Id: typemaps_java.i 32864 2016-01-08 21:00:50Z goatbar $
  *
  * Name:     typemaps_java.i
  * Project:  GDAL SWIG Interface
  * Purpose:  Typemaps for Java bindings
  * Author:   Benjamin Collins, The MITRE Corporation
  *
- *
- * $Log$
- * Revision 1.2  2006/02/16 17:21:12  collinsb
- * Updates to Java bindings to keep the code from halting execution if the native libraries cannot be found.
- *
- * Revision 1.1  2006/02/02 20:56:07  collinsb
- * Added Java specific typemap code
- *
- *
 */
 
 %include "arrays_java.i";
@@ -32,7 +23,7 @@
     swigCMemOwn = cMemoryOwn;
     swigCPtr = cPtr;
   }
-  
+
   protected static long getCPtr($javaclassname obj) {
     return (obj == null) ? 0 : obj.swigCPtr;
   }
@@ -69,7 +60,7 @@
 
 %}
 
-%typemap(javain) SWIGTYPE *DISOWN "$javaclassname.getCPtrAndDisown($javainput)" 
+%typemap(javain) SWIGTYPE *DISOWN "$javaclassname.getCPtrAndDisown($javainput)"
 
 
 /* JAVA TYPEMAPS */
@@ -158,7 +149,7 @@
     "([F)[F");
 
   jfloatArray colorArr = jenv->NewFloatArray(4);
-  colorArr = (jfloatArray)jenv->CallObjectMethod($input, colors, colorArr); 
+  colorArr = (jfloatArray)jenv->CallObjectMethod($input, colors, colorArr);
 
   colorptr = (float *)jenv->GetFloatArrayElements(colorArr, 0);
   tmp.c1 = (short)(colorptr[0] * 255);
@@ -263,7 +254,7 @@
   for( int i = 0; i < *$1; i++ ) {
     jstring stringInfo = jenv->NewStringUTF((*$2)[i].pszInfo);
     jstring stringId = jenv->NewStringUTF((*$2)[i].pszId);
-    jobject GCPobj = jenv->NewObject(GCPClass, GCPcon, 
+    jobject GCPobj = jenv->NewObject(GCPClass, GCPcon,
                                 (*$2)[i].dfGCPX,
                                 (*$2)[i].dfGCPY,
                                 (*$2)[i].dfGCPZ,
@@ -338,7 +329,7 @@
     }
     else
     {
-        SWIG_JavaException(jenv, SWIG_ValueError, "Received a NULL pointer."); return $null; 
+        SWIG_JavaException(jenv, SWIG_ValueError, "Received a NULL pointer."); return $null;
     }
     $2 = &nBytes;
 }
@@ -561,7 +552,7 @@
  *
  *  Java typemaps for (int nList, int* pList)
  *
- ***************************************************/ 
+ ***************************************************/
 %typemap(in) (int nList, int* pList)
 {
   /* %typemap(in) (int nList, int* pList) */
@@ -607,7 +598,7 @@
  *
  *  Java typemaps for (int nList, int* pListOut)
  *
- ***************************************************/ 
+ ***************************************************/
 %typemap(in) (int nList, int* pListOut)
 {
   /* %typemap(in) (int nList, int* pListOut) */
@@ -651,7 +642,7 @@
  *
  *  Java typemaps for (int* pnList, int** ppListOut)
  *
- ***************************************************/ 
+ ***************************************************/
 %typemap(in) (int* pnList, int** ppListOut) (int nLen, int* pBuf)
 {
   /* %typemap(in) (int* pnList, int** ppListOut) */
@@ -689,7 +680,7 @@
  *
  *  Java typemaps for (int id, int *nLen, const int **pList)
  *
- ***************************************************/ 
+ ***************************************************/
 %typemap(in) (int id, int *nLen, const int **pList) (int nLen, int* pList)
 {
   /* %typemap(in) (int id, int *nLen, const int **pList) */
@@ -735,7 +726,7 @@
  *
  *  Java typemaps for (int id, int *nLen, const double **pList)
  *
- ***************************************************/ 
+ ***************************************************/
 %typemap(in) (int id, int *nLen, const double **pList) (int nLen, double* pList)
 {
   /* %typemap(in) (int id, int *nLen, const double **pList) */
@@ -780,7 +771,7 @@
  *
  *  Java typemaps for (int nList, double* pList)
  *
- ***************************************************/ 
+ ***************************************************/
 %typemap(in) (int nList, double* pList)
 {
   /* %typemap(in) (int nList, double* pList) */
@@ -825,7 +816,7 @@
  *
  *  Java typemaps for (int object_list_count, GDALRasterBandShadow **poObjects)
  *
- ***************************************************/ 
+ ***************************************************/
 %typemap(in) (int object_list_count, GDALRasterBandShadow **poObjects)
 {
   /* %typemap(in)(int object_list_count, GDALRasterBandShadow **poObjects) */
@@ -882,6 +873,66 @@
   }
 
 /***************************************************
+ *
+ *  Java typemaps for (int object_list_count, GDALDatasetShadow **poObjects)
+ *
+ ***************************************************/
+%typemap(in) (int object_list_count, GDALDatasetShadow **poObjects)
+{
+  /* %typemap(in)(int object_list_count, GDALDatasetShadow **poObjects) */
+  /* check if is List */
+  if ($input)
+  {
+    $1 = jenv->GetArrayLength($input);
+    if ($1 == 0)
+       $2 = NULL;
+    else
+    {
+        $2 = (GDALDatasetShadow**) malloc(sizeof(GDALDatasetShadow*) * $1);
+        int i;
+        for (i = 0; i<$1; i++) {
+            jobject obj = (jobject)jenv->GetObjectArrayElement($input, i);
+            if (obj == NULL)
+            {
+                free ($2 );
+                SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null object in array");
+                return $null;
+            }
+            const jclass klass = jenv->FindClass("org/gdal/gdal/Dataset");
+            const jmethodID getCPtr = jenv->GetStaticMethodID(klass, "getCPtr", "(Lorg/gdal/gdal/Dataset;)J");
+            $2[i] = (GDALDatasetShadow*) jenv->CallStaticLongMethod(klass, getCPtr, obj);
+        }
+    }
+  }
+  else
+  {
+    $1 = 0;
+    $2 = NULL;
+  }
+}
+
+%typemap(argout) (int object_list_count, GDALDatasetShadow **poObjects)
+{
+  /* %typemap(argout) (int object_list_count, GDALDatasetShadow **poObjects) */
+}
+
+%typemap(freearg) (int object_list_count, GDALDatasetShadow **poObjects)
+{
+  /* %typemap(freearg) (int object_list_count, GDALDatasetShadow **poObjects) */
+  if ($2) {
+    free((void*) $2);
+  }
+}
+
+%typemap(jni) (int object_list_count, GDALDatasetShadow **poObjects) "jobjectArray"
+%typemap(jtype) (int object_list_count, GDALDatasetShadow **poObjects) "Dataset[]"
+%typemap(jstype) (int object_list_count, GDALDatasetShadow **poObjects) "Dataset[]"
+%typemap(javain) (int object_list_count, GDALDatasetShadow **poObjects) "$javainput"
+%typemap(javaout) (int object_list_count, GDALDatasetShadow **poObjects) {
+    return $jnicall;
+  }
+
+/***************************************************
  * Typemaps converts the Hashtable to a char array *
  ***************************************************/
 
@@ -898,7 +949,7 @@
       "(Ljava/lang/Object;)Ljava/lang/Object;");
     const jmethodID keys = jenv->GetMethodID(hashtable, "keys",
       "()Ljava/util/Enumeration;");
-    const jmethodID hasMoreElements = jenv->GetMethodID(enumeration, 
+    const jmethodID hasMoreElements = jenv->GetMethodID(enumeration,
       "hasMoreElements", "()Z");
     const jmethodID nextElement = jenv->GetMethodID(enumeration,
       "nextElement", "()Ljava/lang/Object;");
@@ -988,7 +1039,7 @@
     const jclass stringClass = jenv->FindClass("java/lang/String");
     const jmethodID elements = jenv->GetMethodID(vector, "elements",
       "()Ljava/util/Enumeration;");
-    const jmethodID hasMoreElements = jenv->GetMethodID(enumeration, 
+    const jmethodID hasMoreElements = jenv->GetMethodID(enumeration,
       "hasMoreElements", "()Z");
     const jmethodID getNextElement = jenv->GetMethodID(enumeration,
       "nextElement", "()Ljava/lang/Object;");
@@ -1111,7 +1162,7 @@
 
 
 /***************************************************
- * Typemaps for char **OUTPUT 
+ * Typemaps for char **OUTPUT
  ***************************************************/
 
 %typemap(in) char **OUTPUT (char* ret)
@@ -1181,7 +1232,7 @@
   }
 
 /***************************************************
- * Typemaps for char **argout. 
+ * Typemaps for char **argout.
  ***************************************************/
 
 %typemap(in) (char **argout) ( char *argout=0 )
@@ -1331,7 +1382,7 @@
 
 
 /***************************************************
- * Typemaps for char ** 
+ * Typemaps for char **
  ***************************************************/
 
 /* This tells SWIG to treat char ** as a special case when used as a parameter
@@ -1370,7 +1421,7 @@
     jstring temp_string;
     const jclass clazz = jenv->FindClass("java/lang/String");
 
-    while ($1[len]) len++;    
+    while ($1[len]) len++;
     jresult = jenv->NewObjectArray(len, clazz, NULL);
     /* exception checking omitted */
 
@@ -1394,7 +1445,7 @@
  * Typemaps for (void * nioBuffer, long nioBufferSize)
  ***************************************************/
 
-%typemap(in, numinputs=1) (void * nioBuffer, long nioBufferSize) 
+%typemap(in, numinputs=1) (void * nioBuffer, long nioBufferSize)
 {
     /* %typemap(in, numinputs=1) (void * nioBuffer, long nioBufferSize)  */
     if ($input == 0)
@@ -1405,7 +1456,7 @@
     $1 = jenv->GetDirectBufferAddress($input);
     if ($1 == NULL)
     {
-        SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, 
+        SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException,
                                 "Unable to get address of direct buffer. Buffer must be allocated direct.");
         return $null;
     }
@@ -1432,7 +1483,7 @@
  ***************************************************/
 
 %define DEFINE_REGULAR_ARRAY_OUT(ctype, jtype, function)
-%typemap(in, numinputs=1) (ctype *regularArrayOut, long nRegularArraySizeOut) 
+%typemap(in, numinputs=1) (ctype *regularArrayOut, long nRegularArraySizeOut)
 {
     /* %typemap(in, numinputs=1) (ctype *regularArrayOut, long nRegularArraySizeOut)  */
     if ($input == 0)
@@ -1446,7 +1497,7 @@
     //$1 = (ctype*) jenv->GetPrimitiveArrayCritical($input, 0);
     if ($1 == NULL)
     {
-        SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, 
+        SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException,
                                 "Unable to allocate temporary buffer.");
         return $null;
     }
@@ -1501,7 +1552,7 @@ DEFINE_REGULAR_ARRAY_OUT(double, jdouble, SetDoubleArrayRegion);
  ***************************************************/
 
 %define DEFINE_REGULAR_ARRAY_IN(ctype, jtype, get_fct, release_fct)
-%typemap(in, numinputs=1) (ctype *regularArrayIn, long nRegularArraySizeIn) 
+%typemap(in, numinputs=1) (ctype *regularArrayIn, long nRegularArraySizeIn)
 {
     /* %typemap(in, numinputs=1) (ctype *regularArrayIn, long nRegularArraySizeIn)  */
     if ($input == 0)
@@ -1514,7 +1565,7 @@ DEFINE_REGULAR_ARRAY_OUT(double, jdouble, SetDoubleArrayRegion);
     $1 = (ctype*) jenv->get_fct($input, 0);
     if ($1 == NULL)
     {
-        SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, 
+        SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException,
                                 "Unable to get buffer.");
         return $null;
     }
@@ -1578,7 +1629,7 @@ DEFINE_REGULAR_ARRAY_IN(double, jdouble, GetDoubleArrayElements, ReleaseDoubleAr
   }
 
 /***************************************************
- * Typemaps for ( int nCount, double *x, double *y, double *z ) 
+ * Typemaps for ( int nCount, double *x, double *y, double *z )
  ***************************************************/
 
 %typemap(in) ( int nCount, double *x, double *y, double *z ) (int xyzLen)
diff --git a/swig/include/ogr.i b/swig/include/ogr.i
index edaa329..e4c9b40 100644
--- a/swig/include/ogr.i
+++ b/swig/include/ogr.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr.i 28900 2015-04-14 09:40:34Z rouault $
+ * $Id: ogr.i 33792 2016-03-26 12:54:28Z goatbar $
  *
  * Project:  OGR Core SWIG Interface declarations.
  * Purpose:  OGR declarations.
@@ -67,14 +67,14 @@ typedef int OGRFieldSubType;
 typedef int OGRJustification;
 #else
 %rename (wkbByteOrder) OGRwkbByteOrder;
-typedef enum 
+typedef enum
 {
     wkbXDR = 0,         /* MSB/Sun/Motoroloa: Most Significant Byte First   */
     wkbNDR = 1          /* LSB/Intel/Vax: Least Significant Byte First      */
 } OGRwkbByteOrder;
 
 %rename (wkbGeometryType) OGRwkbGeometryType;
-typedef enum 
+typedef enum
 {
     wkbUnknown = 0,             /* non-standard */
     wkbPoint = 1,               /* rest are standard WKB type codes */
@@ -93,6 +93,12 @@ typedef enum
                              *    ISO SQL/MM Part 3. GDAL >= 2.0 */
     wkbMultiCurve = 11,     /**< GeometryCollection of Curves, ISO SQL/MM Part 3. GDAL >= 2.0 */
     wkbMultiSurface = 12,   /**< GeometryCollection of Surfaces, ISO SQL/MM Part 3. GDAL >= 2.0 */
+    wkbCurve = 13,          /**< Curve (abstract type). ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbSurface = 14,        /**< Surface (abstract type). ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbPolyhedralSurface = 15,/**< a contiguous collection of polygons, which share common boundary segments,
+                               *   ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbTIN = 16,              /**< a PolyhedralSurface consisting only of Triangle patches
+                               *    ISO SQL/MM Part 3. GDAL >= 2.1 */
 
     wkbNone = 100,          /**< non-standard, for pure attribute records */
     wkbLinearRing = 101,    /**< non-standard, just for createGeometry() */
@@ -102,6 +108,44 @@ typedef enum
     wkbCurvePolygonZ = 1010,    /**< wkbCurvePolygon with Z component. ISO SQL/MM Part 3. GDAL >= 2.0 */
     wkbMultiCurveZ = 1011,      /**< wkbMultiCurve with Z component. ISO SQL/MM Part 3. GDAL >= 2.0 */
     wkbMultiSurfaceZ = 1012,    /**< wkbMultiSurface with Z component. ISO SQL/MM Part 3. GDAL >= 2.0 */
+    wkbCurveZ = 1013,           /**< wkbCurve with Z component. ISO SQL/MM Part 3. GDAL >= 2.0 */
+    wkbSurfaceZ = 1014,         /**< wkbSurface with Z component. ISO SQL/MM Part 3. GDAL >= 2.0 */
+    wkbPolyhedralSurfaceZ = 1015,  /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbTINZ = 1016,                /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+
+    wkbPointM = 2001,              /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbLineStringM = 2002,         /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbPolygonM = 2003,            /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbMultiPointM = 2004,         /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbMultiLineStringM = 2005,    /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbMultiPolygonM = 2006,       /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbGeometryCollectionM = 2007, /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbCircularStringM = 2008,     /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbCompoundCurveM = 2009,      /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbCurvePolygonM = 2010,       /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbMultiCurveM = 2011,         /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbMultiSurfaceM = 2012,       /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbCurveM = 2013,              /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbSurfaceM = 2014,            /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbPolyhedralSurfaceM = 2015,  /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbTINM = 2016,                /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+
+    wkbPointZM = 3001,              /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbLineStringZM = 3002,         /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbPolygonZM = 3003,            /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbMultiPointZM = 3004,         /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbMultiLineStringZM = 3005,    /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbMultiPolygonZM = 3006,       /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbGeometryCollectionZM = 3007, /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbCircularStringZM = 3008,     /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbCompoundCurveZM = 3009,      /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbCurvePolygonZM = 3010,       /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbMultiCurveZM = 3011,         /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbMultiSurfaceZM = 3012,       /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbCurveZM = 3013,              /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbSurfaceZM = 3014,            /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbPolyhedralSurfaceZM = 3015,  /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbTINZM = 3016,                /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
 
     wkbPoint25D = -2147483647,   /* 2.5D extensions as per 99-402 */
     wkbLineString25D = -2147483646,
@@ -113,7 +157,7 @@ typedef enum
 } OGRwkbGeometryType;
 
 %rename (FieldType) OGRFieldType;
-typedef enum 
+typedef enum
 {
   /** Simple 32bit integer */                   OFTInteger = 0,
   /** List of 32bit integers */                 OFTIntegerList = 1,
@@ -139,13 +183,13 @@ typedef enum
         and OFTIntegerList.*/                           OFSTBoolean = 1,
     /** Signed 16-bit integer. Only valid for OFTInteger and OFTIntegerList. */
                                                         OFSTInt16 = 2,
-    /** Single precision (32 bit) floatint point. Only valid for OFTReal and OFTRealList. */
+    /** Single precision (32 bit) floating point. Only valid for OFTReal and OFTRealList. */
                                                         OFSTFloat32 = 3
 } OGRFieldSubType;
 
 
 %rename (Justification) OGRJustification;
-typedef enum 
+typedef enum
 {
     OJUndefined = 0,
     OJLeft = 1,
@@ -165,12 +209,17 @@ using namespace std;
 #include "cpl_string.h"
 #include "ogr_srs_api.h"
 
+#define FIELD_INDEX_ERROR_TMPL "Invalid field index: '%i'"
+#define FIELD_NAME_ERROR_TMPL "Invalid field name: '%s'"
+
 typedef void GDALMajorObjectShadow;
 
-#ifdef DEBUG 
+#ifdef DEBUG
 typedef struct OGRSpatialReferenceHS OSRSpatialReferenceShadow;
+#ifndef SWIGPERL
 typedef struct OGRDriverHS OGRDriverShadow;
 typedef struct OGRDataSourceHS OGRDataSourceShadow;
+#endif
 typedef struct OGRLayerHS OGRLayerShadow;
 typedef struct OGRFeatureHS OGRFeatureShadow;
 typedef struct OGRFeatureDefnHS OGRFeatureDefnShadow;
@@ -180,8 +229,10 @@ typedef struct OGRCoordinateTransformationHS OGRCoordinateTransformationShadow;
 typedef struct OGRFieldDefnHS OGRFieldDefnShadow;
 #else
 typedef void OSRSpatialReferenceShadow;
+#ifndef SWIGPERL
 typedef void OGRDriverShadow;
 typedef void OGRDataSourceShadow;
+#endif
 typedef void OGRLayerShadow;
 typedef void OGRFeatureShadow;
 typedef void OGRFeatureDefnShadow;
@@ -224,6 +275,10 @@ typedef void retGetPoints;
 %constant wkbCurvePolygon = 10;
 %constant wkbMultiCurve = 11;
 %constant wkbMultiSurface = 12;
+%constant wkbCurve = 13;
+%constant wkbSurface = 14;
+%constant wkbPolyhedralSurface = 15;
+%constant wkbTIN = 16;
 
 %constant wkbNone = 100;
 %constant wkbLinearRing = 101;
@@ -233,6 +288,44 @@ typedef void retGetPoints;
 %constant wkbCurvePolygonZ = 1010;
 %constant wkbMultiCurveZ = 1011;
 %constant wkbMultiSurfaceZ = 1012;
+%constant wkbCurveZ = 1013;
+%constant wkbSurfaceZ = 1014;
+%constant wkbPolyhedralSurfaceZ = 1015;
+%constant wkbTINZ = 1016;
+
+%constant wkbPointM = 2001;
+%constant wkbLineStringM = 2002;
+%constant wkbPolygonM = 2003;
+%constant wkbMultiPointM = 2004;
+%constant wkbMultiLineStringM = 2005;
+%constant wkbMultiPolygonM = 2006;
+%constant wkbGeometryCollectionM = 2007;
+%constant wkbCircularStringM = 2008;
+%constant wkbCompoundCurveM = 2009;
+%constant wkbCurvePolygonM = 2010;
+%constant wkbMultiCurveM = 2011;
+%constant wkbMultiSurfaceM = 2012;
+%constant wkbCurveM = 2013;
+%constant wkbSurfaceM = 2014;
+%constant wkbPolyhedralSurfaceM = 2015;
+%constant wkbTINM = 2016;
+
+%constant wkbPointZM = 3001;
+%constant wkbLineStringZM = 3002;
+%constant wkbPolygonZM = 3003;
+%constant wkbMultiPointZM = 3004;
+%constant wkbMultiLineStringZM = 3005;
+%constant wkbMultiPolygonZM = 3006;
+%constant wkbGeometryCollectionZM = 3007;
+%constant wkbCircularStringZM = 3008;
+%constant wkbCompoundCurveZM = 3009;
+%constant wkbCurvePolygonZM = 3010;
+%constant wkbMultiCurveZM = 3011;
+%constant wkbMultiSurfaceZM = 3012;
+%constant wkbCurveZM = 3013;
+%constant wkbSurfaceZM = 3014;
+%constant wkbPolyhedralSurfaceZM = 3015;
+%constant wkbTINZM = 3016;
 
 %constant wkbPoint25D =              0x80000001;
 %constant wkbLineString25D =         0x80000002;
@@ -301,6 +394,7 @@ typedef void retGetPoints;
 %constant char *OLCIgnoreFields        = "IgnoreFields";
 %constant char *OLCCreateGeomField     = "CreateGeomField";
 %constant char *OLCCurveGeometries     = "CurveGeometries";
+%constant char *OLCMeasuredGeometries  = "MeasuredGeometries";
 
 %constant char *ODsCCreateLayer        = "CreateLayer";
 %constant char *ODsCDeleteLayer        = "DeleteLayer";
@@ -308,6 +402,7 @@ typedef void retGetPoints;
 %constant char *ODsCCurveGeometries    = "CurveGeometries";
 %constant char *ODsCTransactions       = "Transactions";
 %constant char *ODsCEmulatedTransactions = "EmulatedTransactions";
+%constant char *ODsCMeasuredGeometries = "MeasuredGeometries";
 
 %constant char *ODrCCreateDataSource   = "CreateDataSource";
 %constant char *ODrCDeleteDataSource   = "DeleteDataSource";
@@ -339,6 +434,7 @@ typedef int OGRErr;
 #define OLCStringsAsUTF8       "StringsAsUTF8"
 #define OLCCreateGeomField     "CreateGeomField"
 #define OLCCurveGeometries     "CurveGeometries"
+#define OLCMeasuredGeometries  "MeasuredGeometries";
 
 #define ODsCCreateLayer        "CreateLayer"
 #define ODsCDeleteLayer        "DeleteLayer"
@@ -346,6 +442,7 @@ typedef int OGRErr;
 #define ODsCCurveGeometries    "CurveGeometries"
 #define ODsCTransactions       "Transactions"
 #define ODsCEmulatedTransactions "EmulatedTransactions"
+#define ODsCMeasuredGeometries  "MeasuredGeometries";
 
 #define ODrCCreateDataSource   "CreateDataSource"
 #define ODrCDeleteDataSource   "DeleteDataSource"
@@ -495,6 +592,7 @@ public:
 }
 };
 
+#ifndef SWIGPERL
 /************************************************************************/
 /*                              OGRDriver                               */
 /************************************************************************/
@@ -522,28 +620,28 @@ public:
 #ifndef SWIGJAVA
 %feature( "kwargs" ) CreateDataSource;
 #endif
-  OGRDataSourceShadow *CreateDataSource( const char *utf8_path, 
+  OGRDataSourceShadow *CreateDataSource( const char *utf8_path,
                                     char **options = 0 ) {
     OGRDataSourceShadow *ds = (OGRDataSourceShadow*) OGR_Dr_CreateDataSource( self, utf8_path, options);
     return ds;
   }
-  
+
 %newobject CopyDataSource;
 #ifndef SWIGJAVA
 %feature( "kwargs" ) CopyDataSource;
 #endif
-  OGRDataSourceShadow *CopyDataSource( OGRDataSourceShadow* copy_ds, 
-                                  const char* utf8_path, 
+  OGRDataSourceShadow *CopyDataSource( OGRDataSourceShadow* copy_ds,
+                                  const char* utf8_path,
                                   char **options = 0 ) {
     OGRDataSourceShadow *ds = (OGRDataSourceShadow*) OGR_Dr_CopyDataSource(self, copy_ds, utf8_path, options);
     return ds;
   }
-  
+
 %newobject Open;
 #ifndef SWIGJAVA
 %feature( "kwargs" ) Open;
 #endif
-  OGRDataSourceShadow *Open( const char* utf8_path, 
+  OGRDataSourceShadow *Open( const char* utf8_path,
                         int update=0 ) {
     CPLErrorReset();
     OGRDataSourceShadow* ds = (OGRDataSourceShadow*) OGR_Dr_Open(self, utf8_path, update);
@@ -572,7 +670,7 @@ public:
   bool TestCapability (const char *cap) {
     return (OGR_Dr_TestCapability(self, cap) > 0);
   }
-  
+
   const char * GetName() {
     return OGR_Dr_GetName( self );
   }
@@ -619,15 +717,15 @@ public:
   int GetRefCount() {
     return OGR_DS_GetRefCount(self);
   }
-  
+
   int GetSummaryRefCount() {
     return OGR_DS_GetSummaryRefCount(self);
   }
-  
+
   int GetLayerCount() {
     return OGR_DS_GetLayerCount(self);
   }
-  
+
   OGRDriverShadow * GetDriver() {
     return (OGRDriverShadow *) OGR_DS_GetDriver( self );
   }
@@ -635,7 +733,7 @@ public:
   const char * GetName() {
     return OGR_DS_GetName(self);
   }
-  
+
   OGRErr DeleteLayer(int index){
     return OGR_DS_DeleteLayer(self, index);
   }
@@ -643,7 +741,7 @@ public:
   OGRErr SyncToDisk() {
     return OGR_DS_SyncToDisk(self);
   }
-  
+
   void FlushCache() {
     GDALFlushCache( self );
   }
@@ -652,7 +750,7 @@ public:
 #ifndef SWIGJAVA
   %feature( "kwargs" ) CreateLayer;
 #endif
-  OGRLayerShadow *CreateLayer(const char* name, 
+  OGRLayerShadow *CreateLayer(const char* name,
               OSRSpatialReferenceShadow* srs=NULL,
               OGRwkbGeometryType geom_type=wkbUnknown,
               char** options=0) {
@@ -709,13 +807,13 @@ public:
                                                       dialect);
     return layer;
   }
-  
+
 %apply SWIGTYPE *DISOWN {OGRLayerShadow *layer};
   void ReleaseResultSet(OGRLayerShadow *layer){
     OGR_DS_ReleaseResultSet(self, layer);
   }
 %clear OGRLayerShadow *layer;
-  
+
   OGRStyleTableShadow *GetStyleTable() {
     return (OGRStyleTableShadow*) OGR_DS_GetStyleTable(self);
   }
@@ -748,6 +846,7 @@ public:
 }; /* class OGRDataSourceShadow */
 
 #endif /* FROM_GDAL_I */
+#endif /* #ifndef SWIGPERL just before OGRDriver */
 
 /************************************************************************/
 /*                               OGRLayer                               */
@@ -768,11 +867,11 @@ public:
   int GetRefCount() {
     return OGR_L_GetRefCount(self);
   }
-  
+
   void SetSpatialFilter(OGRGeometryShadow* filter) {
     OGR_L_SetSpatialFilter (self, filter);
   }
-  
+
   void SetSpatialFilterRect( double minx, double miny,
                              double maxx, double maxy) {
     OGR_L_SetSpatialFilterRect(self, minx, miny, maxx, maxy);
@@ -781,7 +880,7 @@ public:
   void SetSpatialFilter(int iGeomField, OGRGeometryShadow* filter) {
     OGR_L_SetSpatialFilterEx (self, iGeomField, filter);
   }
-  
+
   void SetSpatialFilterRect( int iGeomField, double minx, double miny,
                              double maxx, double maxy) {
     OGR_L_SetSpatialFilterRectEx(self, iGeomField, minx, miny, maxx, maxy);
@@ -791,20 +890,20 @@ public:
     return (OGRGeometryShadow *) OGR_L_GetSpatialFilter(self);
   }
 
-#ifdef SWIGCSHARP 
+#ifdef SWIGCSHARP
   %apply ( const char *utf8_path ) { (char* filter_string) };
 #endif
   OGRErr SetAttributeFilter(char* filter_string) {
     return OGR_L_SetAttributeFilter((OGRLayerShadow*)self, filter_string);
   }
-#ifdef SWIGCSHARP 
+#ifdef SWIGCSHARP
   %clear (char* filter_string);
 #endif
-  
+
   void ResetReading() {
     OGR_L_ResetReading(self);
   }
-  
+
   const char * GetName() {
     return OGR_L_GetName(self);
   }
@@ -813,11 +912,11 @@ public:
   OGRwkbGeometryType GetGeomType() {
     return (OGRwkbGeometryType) OGR_L_GetGeomType(self);
   }
- 
+
   const char * GetGeometryColumn() {
     return OGR_L_GetGeometryColumn(self);
   }
-  
+
   const char * GetFIDColumn() {
     return OGR_L_GetFIDColumn(self);
   }
@@ -826,16 +925,16 @@ public:
   OGRFeatureShadow *GetFeature(GIntBig fid) {
     return (OGRFeatureShadow*) OGR_L_GetFeature(self, fid);
   }
-  
+
 %newobject GetNextFeature;
   OGRFeatureShadow *GetNextFeature() {
     return (OGRFeatureShadow*) OGR_L_GetNextFeature(self);
   }
-  
+
   OGRErr SetNextByIndex(GIntBig new_index) {
     return OGR_L_SetNextByIndex(self, new_index);
   }
-  
+
 %apply Pointer NONNULL {OGRFeatureShadow *feature};
   OGRErr SetFeature(OGRFeatureShadow *feature) {
     return OGR_L_SetFeature(self, feature);
@@ -849,22 +948,22 @@ public:
   OGRErr DeleteFeature(GIntBig fid) {
     return OGR_L_DeleteFeature(self, fid);
   }
-  
+
   OGRErr SyncToDisk() {
     return OGR_L_SyncToDisk(self);
   }
-  
+
   OGRFeatureDefnShadow *GetLayerDefn() {
     return (OGRFeatureDefnShadow*) OGR_L_GetLayerDefn(self);
   }
 
 #ifndef SWIGJAVA
-  %feature( "kwargs" ) GetFeatureCount;  
+  %feature( "kwargs" ) GetFeatureCount;
 #endif
   GIntBig GetFeatureCount(int force=1) {
     return OGR_L_GetFeatureCount(self, force);
   }
-  
+
 #if defined(SWIGCSHARP)
   %feature( "kwargs" ) GetExtent;
   OGRErr GetExtent(OGREnvelope* extent, int force=1) {
@@ -894,7 +993,7 @@ public:
   bool TestCapability(const char* cap) {
     return (OGR_L_TestCapability(self, cap) > 0);
   }
-  
+
 #ifndef SWIGJAVA
   %feature( "kwargs" ) CreateField;
 #endif
@@ -945,7 +1044,7 @@ public:
   OGRErr StartTransaction() {
     return OGR_L_StartTransaction(self);
   }
-  
+
   OGRErr CommitTransaction() {
     return OGR_L_CommitTransaction(self);
   }
@@ -957,7 +1056,7 @@ public:
   int FindFieldIndex( const char *pszFieldName, int bExactMatch ) {
     return OGR_L_FindFieldIndex(self, pszFieldName, bExactMatch );
   }
-  
+
   %newobject GetSpatialRef;
   OSRSpatialReferenceShadow *GetSpatialRef() {
     OGRSpatialReferenceH ref =  OGR_L_GetSpatialRef(self);
@@ -965,7 +1064,7 @@ public:
         OSRReference(ref);
     return (OSRSpatialReferenceShadow*) ref;
   }
-  
+
   GIntBig GetFeaturesRead() {
     return OGR_L_GetFeaturesRead(self);
   }
@@ -980,8 +1079,8 @@ public:
 #ifndef SWIGJAVA
   %feature( "kwargs" ) Intersection;
 #endif
-  OGRErr Intersection( OGRLayerShadow *method_layer, 
-                       OGRLayerShadow *result_layer, 
+  OGRErr Intersection( OGRLayerShadow *method_layer,
+                       OGRLayerShadow *result_layer,
                        char **options=NULL,
                        GDALProgressFunc callback=NULL,
                        void* callback_data=NULL ) {
@@ -991,8 +1090,8 @@ public:
 #ifndef SWIGJAVA
   %feature( "kwargs" ) Union;
 #endif
-  OGRErr Union( OGRLayerShadow *method_layer, 
-                OGRLayerShadow *result_layer, 
+  OGRErr Union( OGRLayerShadow *method_layer,
+                OGRLayerShadow *result_layer,
                 char **options=NULL,
                 GDALProgressFunc callback=NULL,
                 void* callback_data=NULL ) {
@@ -1002,8 +1101,8 @@ public:
 #ifndef SWIGJAVA
   %feature( "kwargs" ) SymDifference;
 #endif
-  OGRErr SymDifference( OGRLayerShadow *method_layer, 
-                        OGRLayerShadow *result_layer, 
+  OGRErr SymDifference( OGRLayerShadow *method_layer,
+                        OGRLayerShadow *result_layer,
                         char **options=NULL,
                         GDALProgressFunc callback=NULL,
                         void* callback_data=NULL ) {
@@ -1013,8 +1112,8 @@ public:
 #ifndef SWIGJAVA
   %feature( "kwargs" ) Identity;
 #endif
-  OGRErr Identity( OGRLayerShadow *method_layer, 
-                   OGRLayerShadow *result_layer, 
+  OGRErr Identity( OGRLayerShadow *method_layer,
+                   OGRLayerShadow *result_layer,
                    char **options=NULL,
                    GDALProgressFunc callback=NULL,
                    void* callback_data=NULL ) {
@@ -1024,8 +1123,8 @@ public:
 #ifndef SWIGJAVA
   %feature( "kwargs" ) Update;
 #endif
-  OGRErr Update( OGRLayerShadow *method_layer, 
-                 OGRLayerShadow *result_layer, 
+  OGRErr Update( OGRLayerShadow *method_layer,
+                 OGRLayerShadow *result_layer,
                  char **options=NULL,
                  GDALProgressFunc callback=NULL,
                  void* callback_data=NULL ) {
@@ -1035,8 +1134,8 @@ public:
 #ifndef SWIGJAVA
   %feature( "kwargs" ) Clip;
 #endif
-  OGRErr Clip( OGRLayerShadow *method_layer, 
-               OGRLayerShadow *result_layer, 
+  OGRErr Clip( OGRLayerShadow *method_layer,
+               OGRLayerShadow *result_layer,
                char **options=NULL,
                GDALProgressFunc callback=NULL,
                void* callback_data=NULL ) {
@@ -1046,14 +1145,14 @@ public:
 #ifndef SWIGJAVA
   %feature( "kwargs" ) Erase;
 #endif
-  OGRErr Erase( OGRLayerShadow *method_layer, 
-                OGRLayerShadow *result_layer, 
+  OGRErr Erase( OGRLayerShadow *method_layer,
+                OGRLayerShadow *result_layer,
                 char **options=NULL,
                 GDALProgressFunc callback=NULL,
                 void* callback_data=NULL ) {
     return OGR_L_Erase( self, method_layer, result_layer, options, callback, callback_data );
   }
-  
+
   OGRStyleTableShadow *GetStyleTable() {
     return (OGRStyleTableShadow*) OGR_L_GetStyleTable(self);
   }
@@ -1100,25 +1199,24 @@ public:
   OGRFeatureDefnShadow *GetDefnRef() {
     return (OGRFeatureDefnShadow*) OGR_F_GetDefnRef(self);
   }
-  
+
   OGRErr SetGeometry(OGRGeometryShadow* geom) {
     return OGR_F_SetGeometry(self, geom);
   }
 
-/* The feature takes over owernship of the geometry. */
+/* The feature takes over ownership of the geometry. */
 /* Don't change the 'geom' name as Java bindings depends on it */
 %apply SWIGTYPE *DISOWN {OGRGeometryShadow *geom};
   OGRErr SetGeometryDirectly(OGRGeometryShadow* geom) {
     return OGR_F_SetGeometryDirectly(self, geom);
   }
 %clear OGRGeometryShadow *geom;
-  
+
   /* Feature owns its geometry */
   OGRGeometryShadow *GetGeometryRef() {
     return (OGRGeometryShadow*) OGR_F_GetGeometryRef(self);
   }
 
-
   OGRErr SetGeomField(int iField, OGRGeometryShadow* geom) {
     return OGR_F_SetGeomField(self, iField, geom);
   }
@@ -1127,14 +1225,14 @@ public:
       int iField = OGR_F_GetGeomFieldIndex(self, name);
       if (iField == -1)
       {
-        CPLError(CE_Failure, 1, "No such field: '%s'", name);
-        return OGRERR_FAILURE;
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+          return OGRERR_FAILURE;
       }
       else
-        return OGR_F_SetGeomField(self, iField, geom);
+          return OGR_F_SetGeomField(self, iField, geom);
   }
 
-/* The feature takes over owernship of the geometry. */
+/* The feature takes over ownership of the geometry. */
 /* Don't change the 'geom' name as Java bindings depends on it */
 %apply SWIGTYPE *DISOWN {OGRGeometryShadow *geom};
   OGRErr SetGeomFieldDirectly(int iField, OGRGeometryShadow* geom) {
@@ -1145,14 +1243,14 @@ public:
       int iField = OGR_F_GetGeomFieldIndex(self, name);
       if (iField == -1)
       {
-        CPLError(CE_Failure, 1, "No such field: '%s'", name);
-        return OGRERR_FAILURE;
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+          return OGRERR_FAILURE;
       }
       else
-        return OGR_F_SetGeomFieldDirectly(self, iField, geom);
+          return OGR_F_SetGeomFieldDirectly(self, iField, geom);
   }
 %clear OGRGeometryShadow *geom;
-  
+
   /* Feature owns its geometry */
   OGRGeometryShadow *GetGeomFieldRef(int iField) {
     return (OGRGeometryShadow*) OGR_F_GetGeomFieldRef(self, iField);
@@ -1160,27 +1258,27 @@ public:
 
   /* Feature owns its geometry */
   OGRGeometryShadow *GetGeomFieldRef(const char* name) {
-    int i = OGR_F_GetGeomFieldIndex(self, name);
-    if (i == -1)
-    {
-      CPLError(CE_Failure, 1, "No such field: '%s'", name);
-      return NULL;
-    }
-    else
-      return (OGRGeometryShadow*) OGR_F_GetGeomFieldRef(self, i);
+      int i = OGR_F_GetGeomFieldIndex(self, name);
+      if (i == -1)
+      {
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+          return NULL;
+      }
+      else
+          return (OGRGeometryShadow*) OGR_F_GetGeomFieldRef(self, i);
   }
-  
+
   %newobject Clone;
   OGRFeatureShadow *Clone() {
     return (OGRFeatureShadow*) OGR_F_Clone(self);
   }
-  
+
 %apply Pointer NONNULL {OGRFeatureShadow *feature};
   bool Equal(OGRFeatureShadow *feature) {
     return (OGR_F_Equal(self, feature) > 0);
   }
 %clear OGRFeatureShadow *feature;
-  
+
   int GetFieldCount() {
     return OGR_F_GetFieldCount(self);
   }
@@ -1193,9 +1291,9 @@ public:
   OGRFieldDefnShadow *GetFieldDefnRef(const char* name) {
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
-	  return (OGRFieldDefnShadow *) OGR_F_GetFieldDefnRef(self, i);
+          return (OGRFieldDefnShadow *) OGR_F_GetFieldDefnRef(self, i);
       return NULL;
   }
   /* ------------------------------------------- */
@@ -1206,15 +1304,15 @@ public:
 
   /* ---- GetGeomFieldDefnRef --------------------- */
   OGRGeomFieldDefnShadow *GetGeomFieldDefnRef(int id) {
-    return (OGRGeomFieldDefnShadow *) OGR_F_GetGeomFieldDefnRef(self, id);
+      return (OGRGeomFieldDefnShadow *) OGR_F_GetGeomFieldDefnRef(self, id);
   }
 
   OGRGeomFieldDefnShadow *GetGeomFieldDefnRef(const char* name) {
       int i = OGR_F_GetGeomFieldIndex(self, name);
       if (i == -1)
-      CPLError(CE_Failure, 1, "No such field: '%s'", name);
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
-      return (OGRGeomFieldDefnShadow *) OGR_F_GetGeomFieldDefnRef(self, i);
+          return (OGRGeomFieldDefnShadow *) OGR_F_GetGeomFieldDefnRef(self, i);
       return NULL;
   }
   /* ------------------------------------------- */
@@ -1225,16 +1323,14 @@ public:
     return (const char *) OGR_F_GetFieldAsString(self, id);
   }
 
-#ifndef SWIGPERL
   const char* GetFieldAsString(const char* name) {
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
+	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
 	  return (const char *) OGR_F_GetFieldAsString(self, i);
       return NULL;
   }
-#endif
   /* ------------------------------------------- */
 
   /* ---- GetFieldAsInteger -------------------- */
@@ -1243,17 +1339,15 @@ public:
     return OGR_F_GetFieldAsInteger(self, id);
   }
 
-#ifndef SWIGPERL
   int GetFieldAsInteger(const char* name) {
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
+	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
 	  return OGR_F_GetFieldAsInteger(self, i);
       return 0;
   }
-#endif
-  /* ------------------------------------------- */  
+  /* ------------------------------------------- */
 
   /* ---- GetFieldAsInteger64 ------------------ */
 
@@ -1261,17 +1355,15 @@ public:
     return OGR_F_GetFieldAsInteger64(self, id);
   }
 
-#ifndef SWIGPERL
   GIntBig GetFieldAsInteger64(const char* name) {
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-      CPLError(CE_Failure, 1, "No such field: '%s'", name);
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
-      return OGR_F_GetFieldAsInteger64(self, i);
+          return OGR_F_GetFieldAsInteger64(self, i);
       return 0;
   }
-#endif
-  /* ------------------------------------------- */  
+  /* ------------------------------------------- */
 
   /* ---- GetFieldAsDouble --------------------- */
 
@@ -1279,17 +1371,15 @@ public:
     return OGR_F_GetFieldAsDouble(self, id);
   }
 
-#ifndef SWIGPERL
   double GetFieldAsDouble(const char* name) {
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
-	  return OGR_F_GetFieldAsDouble(self, i);
+          return OGR_F_GetFieldAsDouble(self, i);
       return 0;
   }
-#endif
-  /* ------------------------------------------- */  
+  /* ------------------------------------------- */
 
   %apply (int *OUTPUT) {(int *)};
   %apply (float *OUTPUT) {(float *)};
@@ -1300,6 +1390,17 @@ public:
 			       pnHour, pnMinute, pfSecond,
 			       pnTZFlag);
   }
+  void GetFieldAsDateTime(const char* name, int *pnYear, int *pnMonth, int *pnDay,
+			  int *pnHour, int *pnMinute, float *pfSecond,
+			  int *pnTZFlag) {
+      int id = OGR_F_GetFieldIndex(self, name);
+      if (id == -1)
+	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      else
+	  OGR_F_GetFieldAsDateTimeEx(self, id, pnYear, pnMonth, pnDay,
+			       pnHour, pnMinute, pfSecond,
+			       pnTZFlag);
+  }
   %clear (int *);
   %clear (float *);
 
@@ -1320,12 +1421,30 @@ public:
   void GetFieldAsIntegerList(int id, int *nLen, const int **pList) {
       *pList = OGR_F_GetFieldAsIntegerList(self, id, nLen);
   }
+
+  void GetFieldAsIntegerList(const char* name, int *nLen, const int **pList) {
+      int id = OGR_F_GetFieldIndex(self, name);
+      if (id == -1)
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      else
+          *pList = OGR_F_GetFieldAsIntegerList(self, id, nLen);
+  }
 #endif
 
-#if defined(SWIGPYTHON)
+#if defined(SWIGPYTHON) || defined(SWIGPERL)
   void GetFieldAsInteger64List(int id, int *nLen, const GIntBig **pList) {
       *pList = OGR_F_GetFieldAsInteger64List(self, id, nLen);
   }
+
+#if defined(SWIGPERL)
+  void GetFieldAsInteger64List(const char* name, int *nLen, const GIntBig **pList) {
+      int id = OGR_F_GetFieldIndex(self, name);
+      if (id == -1)
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      else
+          *pList = OGR_F_GetFieldAsInteger64List(self, id, nLen);
+  }
+#endif
 #endif
 
 #if defined(SWIGJAVA)
@@ -1345,6 +1464,14 @@ public:
   void GetFieldAsDoubleList(int id, int *nLen, const double **pList) {
       *pList = OGR_F_GetFieldAsDoubleList(self, id, nLen);
   }
+
+  void GetFieldAsDoubleList(const char* name, int *nLen, const double **pList) {
+      int id = OGR_F_GetFieldIndex(self, name);
+      if (id == -1)
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      else
+          *pList = OGR_F_GetFieldAsDoubleList(self, id, nLen);
+  }
 #endif
 
 #if defined(SWIGJAVA)
@@ -1363,6 +1490,14 @@ public:
   void GetFieldAsStringList(int id, char ***pList) {
       *pList = OGR_F_GetFieldAsStringList(self, id);
   }
+
+  void GetFieldAsStringList(const char* name, char ***pList) {
+      int id = OGR_F_GetFieldIndex(self, name);
+      if (id == -1)
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      else
+          *pList = OGR_F_GetFieldAsStringList(self, id);
+  }
 #endif
 
 #ifndef SWIGCSHARP
@@ -1379,7 +1514,7 @@ public:
       int id = OGR_F_GetFieldIndex(self, name);
       if (id == -1)
       {
-        CPLError(CE_Failure, 1, "No such field: '%s'", name);
+        CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
         return NULL;
       }
       else
@@ -1399,12 +1534,11 @@ public:
     return OGRERR_NONE;
   }
 
-#ifndef SWIGPERL
   OGRErr GetFieldAsBinary(const char* name, int *nLen, char **pBuf) {
       int id = OGR_F_GetFieldIndex(self, name);
       if (id == -1)
       {
-        CPLError(CE_Failure, 1, "No such field: '%s'", name);
+        CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
         return OGRERR_FAILURE;
       }
       else
@@ -1415,8 +1549,6 @@ public:
         return OGRERR_NONE;
       }
   }
-#endif /* SWIGPERL */ 
-
 #endif /* SWIGJAVA */
 
 #endif /* SWIGCSHARP */
@@ -1429,29 +1561,51 @@ public:
   bool IsFieldSet(const char* name) {
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
+	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
 	  return (OGR_F_IsFieldSet(self, i) > 0);
       return false;
   }
-  /* ------------------------------------------- */  
-      
+  /* ------------------------------------------- */
+
+#ifdef SWIGPERL
+  int GetFieldIndex(int i) {
+      if (i < 0 || i >= OGR_F_GetFieldCount(self))
+          CPLError(CE_Failure, 1, FIELD_INDEX_ERROR_TMPL, i);
+      return i;
+  }
+#endif
+
   int GetFieldIndex(const char* name) {
-      return OGR_F_GetFieldIndex(self, name);
+      int i = OGR_F_GetFieldIndex(self, name);
+      if (i == -1)
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      return i;
+  }
+
+#ifdef SWIGPERL
+  int GetGeomFieldIndex(int i) {
+      if (i < 0 || i >= OGR_F_GetGeomFieldCount(self))
+          CPLError(CE_Failure, 1, FIELD_INDEX_ERROR_TMPL, i);
+      return i;
   }
+#endif
 
   int GetGeomFieldIndex(const char* name) {
-      return OGR_F_GetGeomFieldIndex(self, name);
+      int i = OGR_F_GetGeomFieldIndex(self, name);
+      if (i == -1)
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      return i;
   }
 
   GIntBig GetFID() {
     return OGR_F_GetFID(self);
   }
-  
+
   OGRErr SetFID(GIntBig fid) {
     return OGR_F_SetFID(self, fid);
   }
-  
+
   void DumpReadable() {
     OGR_F_DumpReadable(self, NULL);
   }
@@ -1460,18 +1614,16 @@ public:
     OGR_F_UnsetField(self, id);
   }
 
-#ifndef SWIGPERL
   void UnsetField(const char* name) {
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
-	  OGR_F_UnsetField(self, i);
+          OGR_F_UnsetField(self, i);
   }
-#endif
 
   /* ---- SetField ----------------------------- */
-#ifndef SWIGCSHARP 
+#ifndef SWIGCSHARP
   %apply ( tostring argin ) { (const char* value) };
 #else
   %apply ( const char *utf8_path ) { (const char* value) };
@@ -1480,15 +1632,13 @@ public:
     OGR_F_SetFieldString(self, id, value);
   }
 
-#ifndef SWIGPERL
   void SetField(const char* name, const char* value) {
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
-	  OGR_F_SetFieldString(self, i, value);
+          OGR_F_SetFieldString(self, i, value);
   }
-#endif
   %clear (const char* value );
 
   void SetFieldInteger64(int id, GIntBig value) {
@@ -1499,74 +1649,122 @@ public:
   void SetField(int id, int value) {
     OGR_F_SetFieldInteger(self, id, value);
   }
-  
-#ifndef SWIGPERL
+
   void SetField(const char* name, int value) {
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
+	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
 	  OGR_F_SetFieldInteger(self, i, value);
   }
-#endif /* SWIGPERL */
 #endif /* SWIGPYTHON */
-  
+
   void SetField(int id, double value) {
     OGR_F_SetFieldDouble(self, id, value);
   }
-  
-#ifndef SWIGPERL
+
   void SetField(const char* name, double value) {
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
+	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
 	  OGR_F_SetFieldDouble(self, i, value);
   }
-#endif
-  
+
   void SetField( int id, int year, int month, int day,
-                             int hour, int minute, float second, 
+                             int hour, int minute, float second,
                              int tzflag ) {
     OGR_F_SetFieldDateTimeEx(self, id, year, month, day,
-                             hour, minute, second, 
+                             hour, minute, second,
                              tzflag);
   }
 
-#ifndef SWIGPERL  
   void SetField(const char* name, int year, int month, int day,
-                             int hour, int minute, float second, 
+                             int hour, int minute, float second,
                              int tzflag ) {
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
+	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
 	  OGR_F_SetFieldDateTimeEx(self, i, year, month, day,
-				 hour, minute, second, 
+				 hour, minute, second,
 				 tzflag);
   }
-#endif
 
   void SetFieldIntegerList(int id, int nList, int *pList) {
       OGR_F_SetFieldIntegerList(self, id, nList, pList);
   }
 
-#if defined(SWIGPYTHON)
+#if defined(SWIGPERL)
+  void SetFieldIntegerList(const char* name, int nList, int *pList) {
+      int id = OGR_F_GetFieldIndex(self, name);
+      if (id == -1)
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      else
+       	  OGR_F_SetFieldIntegerList(self, id, nList, pList);
+  }
+#endif
+
+#if defined(SWIGPYTHON) || defined(SWIGPERL)
   void SetFieldInteger64List(int id, int nList, GIntBig *pList) {
       OGR_F_SetFieldInteger64List(self, id, nList, pList);
   }
+
+#if defined(SWIGPERL)
+  void SetFieldInteger64List(const char* name, int nList, GIntBig *pList) {
+      int id = OGR_F_GetFieldIndex(self, name);
+      if (id == -1)
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      else
+          OGR_F_SetFieldInteger64List(self, id, nList, pList);
+  }
+#endif
 #endif
 
   void SetFieldDoubleList(int id, int nList, double *pList) {
       OGR_F_SetFieldDoubleList(self, id, nList, pList);
   }
 
+#if defined(SWIGPERL)
+  void SetFieldDoubleList(const char* name, int nList, double *pList) {
+      int id = OGR_F_GetFieldIndex(self, name);
+      if (id == -1)
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      else
+          OGR_F_SetFieldDoubleList(self, id, nList, pList);
+  }
+#endif
+
 %apply (char **options) {char **pList};
   void SetFieldStringList(int id, char **pList) {
       OGR_F_SetFieldStringList(self, id, pList);
   }
+
+#if defined(SWIGPERL)
+  void SetFieldStringList(const char* name, char **pList) {
+      int id = OGR_F_GetFieldIndex(self, name);
+      if (id == -1)
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      else
+          OGR_F_SetFieldStringList(self, id, pList);
+  }
+#endif
 %clear char**pList;
 
+#if defined(SWIGPERL)
+  void SetFieldBinary(int i, int nBytes, GByte* pabyBuf) {
+      OGR_F_SetFieldBinary(self, i, nBytes, pabyBuf);
+  }
+
+  void SetFieldBinary(const char* name, int nBytes, GByte* pabyBuf) {
+      int i = OGR_F_GetFieldIndex(self, name);
+      if (i == -1)
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      else
+          OGR_F_SetFieldBinary(self, i, nBytes, pabyBuf);
+  }
+#endif
+
   void SetFieldBinaryFromHexString(int id, const char* pszValue)
   {
      int nBytes;
@@ -1579,18 +1777,18 @@ public:
   {
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-        CPLError(CE_Failure, 1, "No such field: '%s'", name);
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
       {
-        int nBytes;
-        GByte* pabyBuf = CPLHexToBinary(pszValue, &nBytes );
-        OGR_F_SetFieldBinary(self, i, nBytes, pabyBuf);
-        CPLFree(pabyBuf);
+          int nBytes;
+          GByte* pabyBuf = CPLHexToBinary(pszValue, &nBytes );
+          OGR_F_SetFieldBinary(self, i, nBytes, pabyBuf);
+          CPLFree(pabyBuf);
       }
   }
 
-  /* ------------------------------------------- */  
-  
+  /* ------------------------------------------- */
+
 #ifndef SWIGJAVA
   %feature("kwargs") SetFrom;
 #endif
@@ -1615,12 +1813,12 @@ public:
   const char *GetStyleString() {
     return (const char*) OGR_F_GetStyleString(self);
   }
-  
+
   void SetStyleString(const char* the_string) {
     OGR_F_SetStyleString(self, the_string);
   }
 
-  /* ---- GetFieldType ------------------------- */  
+  /* ---- GetFieldType ------------------------- */
   OGRFieldType GetFieldType(int id) {
       OGRFieldDefnH fd = OGR_F_GetFieldDefnRef( self,  id );
       if (fd)
@@ -1628,17 +1826,17 @@ public:
       else
           return (OGRFieldType)0;
   }
-  
+
   OGRFieldType GetFieldType(const char* name) {
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1) {
-          CPLError(CE_Failure, 1, "No such field: '%s'", name);
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
           return (OGRFieldType)0;
       } else
           return (OGRFieldType) OGR_Fld_GetType( OGR_F_GetFieldDefnRef( self, i ) );
   }
-  /* ------------------------------------------- */  
-  
+  /* ------------------------------------------- */
+
   int Validate( int flags = OGR_F_VAL_ALL, int bEmitError = TRUE ) {
     return OGR_F_Validate(self, flags, bEmitError);
   }
@@ -1647,6 +1845,21 @@ public:
     OGR_F_FillUnsetWithDefault(self, bNotNullableOnly, options );
   }
 
+  const char* GetNativeData () {
+    return OGR_F_GetNativeData(self);
+  }
+
+  const char* GetNativeMediaType () {
+    return OGR_F_GetNativeMediaType(self);
+  }
+
+  void SetNativeData ( const char* nativeData ) {
+    OGR_F_SetNativeData(self, nativeData);
+  }
+
+  void SetNativeMediaType ( const char* nativeMediaType ) {
+    OGR_F_SetNativeMediaType(self, nativeMediaType);
+  }
 } /* %extend */
 
 
@@ -1691,6 +1904,30 @@ public:
             case wkbMultiLineString25D:
             case wkbMultiPolygon25D:
             case wkbGeometryCollection25D:
+            case wkbPointM:
+            case wkbLineStringM:
+            case wkbPolygonM:
+            case wkbMultiPointM:
+            case wkbMultiLineStringM:
+            case wkbMultiPolygonM:
+            case wkbGeometryCollectionM:
+            case wkbCircularStringM:
+            case wkbCompoundCurveM:
+            case wkbCurvePolygonM:
+            case wkbMultiCurveM:
+            case wkbMultiSurfaceM:
+            case wkbPointZM:
+            case wkbLineStringZM:
+            case wkbPolygonZM:
+            case wkbMultiPointZM:
+            case wkbMultiLineStringZM:
+            case wkbMultiPolygonZM:
+            case wkbGeometryCollectionZM:
+            case wkbCircularStringZM:
+            case wkbCompoundCurveZM:
+            case wkbCurvePolygonZM:
+            case wkbMultiCurveZM:
+            case wkbMultiSurfaceZM:
                 return TRUE;
             default:
                 CPLError(CE_Failure, CPLE_IllegalArg, "Illegal geometry type value");
@@ -1703,7 +1940,7 @@ class OGRFeatureDefnShadow {
   OGRFeatureDefnShadow();
 public:
 %extend {
-  
+
   ~OGRFeatureDefnShadow() {
     /*OGR_FD_Destroy(self);*/
     OGR_FD_Release( OGRFeatureDefnH(self) );
@@ -1717,44 +1954,73 @@ public:
     OGR_FD_Reference(h);
     return (OGRFeatureDefnShadow* )h;
   }
-  
+
   const char* GetName(){
     return OGR_FD_GetName(self);
   }
-  
+
   int GetFieldCount(){
     return OGR_FD_GetFieldCount(self);
   }
-  
+
   /* FeatureDefns own their FieldDefns */
   OGRFieldDefnShadow* GetFieldDefn(int i){
     return (OGRFieldDefnShadow*) OGR_FD_GetFieldDefn(self, i);
   }
 
+#ifdef SWIGPERL
+  int GetFieldIndex(int i) {
+      if (i < 0 || i >= OGR_FD_GetFieldCount(self))
+          CPLError(CE_Failure, 1, FIELD_INDEX_ERROR_TMPL, i);
+      return i;
+  }
+#endif
+
   int GetFieldIndex(const char* name) {
-      return OGR_FD_GetFieldIndex(self, name);
+      int i = OGR_FD_GetFieldIndex(self, name);
+      if (i == -1)
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      return i;
   }
-  
+
 %apply Pointer NONNULL {OGRFieldDefnShadow* defn};
   void AddFieldDefn(OGRFieldDefnShadow* defn) {
     OGR_FD_AddFieldDefn(self, defn);
   }
 %clear OGRFieldDefnShadow* defn;
-  
-  
+
+
   int GetGeomFieldCount(){
     return OGR_FD_GetGeomFieldCount(self);
   }
-  
+
   /* FeatureDefns own their GeomFieldDefns */
   OGRGeomFieldDefnShadow* GetGeomFieldDefn(int i){
     return (OGRGeomFieldDefnShadow*) OGR_FD_GetGeomFieldDefn(self, i);
   }
 
+#ifdef SWIGPERL
+  OGRGeomFieldDefnShadow* GetGeomFieldDefn(const char* name) {
+      int iField = OGR_FD_GetGeomFieldIndex(self, name);
+      if (iField == -1)
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      else
+          return (OGRGeomFieldDefnShadow*) OGR_FD_GetGeomFieldDefn(self, iField);
+      return NULL;
+  }
+
+  int GetGeomFieldIndex(int i) {
+      if (i < 0 || i >= OGR_FD_GetGeomFieldCount(self))
+          CPLError(CE_Failure, 1, FIELD_INDEX_ERROR_TMPL, i);
+      else
+          return i;
+  }
+#endif
+
   int GetGeomFieldIndex(const char* name) {
       return OGR_FD_GetGeomFieldIndex(self, name);
   }
-  
+
 %apply Pointer NONNULL {OGRGeomFieldDefnShadow* defn};
   void AddGeomFieldDefn(OGRGeomFieldDefnShadow* defn) {
     OGR_FD_AddGeomFieldDefn(self, defn);
@@ -1769,12 +2035,12 @@ public:
   OGRwkbGeometryType GetGeomType() {
     return (OGRwkbGeometryType) OGR_FD_GetGeomType(self);
   }
-  
+
   void SetGeomType(OGRwkbGeometryType geom_type) {
     if( ValidateOGRGeometryType(geom_type) )
         OGR_FD_SetGeomType(self, geom_type);
   }
-  
+
   int GetReferenceCount(){
     return OGR_FD_GetReferenceCount(self);
   }
@@ -1782,15 +2048,15 @@ public:
   int IsGeometryIgnored() {
     return OGR_FD_IsGeometryIgnored(self);
   }
-  
+
   void SetGeometryIgnored( int bIgnored ) {
     return OGR_FD_SetGeometryIgnored(self,bIgnored);
   }
-  
+
   int IsStyleIgnored() {
     return OGR_FD_IsStyleIgnored(self);
   }
-  
+
   void SetStyleIgnored( int bIgnored ) {
     return OGR_FD_SetStyleIgnored(self,bIgnored);
   }
@@ -1865,7 +2131,7 @@ public:
 #ifndef SWIGJAVA
   %feature("kwargs") OGRFieldDefnShadow;
 #endif
-  OGRFieldDefnShadow( const char* name_null_ok="unnamed", 
+  OGRFieldDefnShadow( const char* name_null_ok="unnamed",
                       OGRFieldType field_type=OFTString) {
     if (ValidateOGRFieldType(field_type))
         return (OGRFieldDefnShadow*) OGR_Fld_Create(name_null_ok, field_type);
@@ -1876,15 +2142,15 @@ public:
   const char * GetName() {
     return (const char *) OGR_Fld_GetNameRef(self);
   }
-  
+
   const char * GetNameRef() {
     return (const char *) OGR_Fld_GetNameRef(self);
   }
-  
+
   void SetName( const char* name) {
     OGR_Fld_SetName(self, name);
   }
-  
+
   OGRFieldType GetType() {
     return OGR_Fld_GetType(self);
   }
@@ -1906,23 +2172,23 @@ public:
   OGRJustification GetJustify() {
     return OGR_Fld_GetJustify(self);
   }
-  
+
   void SetJustify(OGRJustification justify) {
     OGR_Fld_SetJustify(self, justify);
   }
-  
+
   int GetWidth () {
     return OGR_Fld_GetWidth(self);
   }
-  
+
   void SetWidth (int width) {
     OGR_Fld_SetWidth(self, width);
   }
-  
+
   int GetPrecision() {
     return OGR_Fld_GetPrecision(self);
   }
-  
+
   void SetPrecision(int precision) {
     OGR_Fld_SetPrecision(self, precision);
   }
@@ -1988,7 +2254,7 @@ public:
 #ifndef SWIGJAVA
   %feature("kwargs") OGRGeomFieldDefnShadow;
 #endif
-  OGRGeomFieldDefnShadow( const char* name_null_ok="", 
+  OGRGeomFieldDefnShadow( const char* name_null_ok="",
                           OGRwkbGeometryType field_type = wkbUnknown) {
     if( ValidateOGRGeometryType(field_type) )
         return (OGRGeomFieldDefnShadow*) OGR_GFld_Create(name_null_ok, field_type);
@@ -1999,15 +2265,15 @@ public:
   const char * GetName() {
     return (const char *) OGR_GFld_GetNameRef(self);
   }
-  
+
   const char * GetNameRef() {
     return (const char *) OGR_GFld_GetNameRef(self);
   }
-  
+
   void SetName( const char* name) {
     OGR_GFld_SetName(self, name);
   }
-  
+
   OGRwkbGeometryType GetType() {
     return OGR_GFld_GetType(self);
   }
@@ -2063,7 +2329,7 @@ public:
 %apply (void *buffer_ptr) {char *bin_string};
 #endif
 %inline %{
-  OGRGeometryShadow* CreateGeometryFromWkb( int len, char *bin_string, 
+  OGRGeometryShadow* CreateGeometryFromWkb( int len, char *bin_string,
                                             OSRSpatialReferenceShadow *reference=NULL ) {
     OGRGeometryH geom = NULL;
     OGRErr err = OGR_G_CreateFromWkb( (unsigned char *) bin_string,
@@ -2076,7 +2342,7 @@ public:
     }
     return (OGRGeometryShadow*) geom;
   }
- 
+
 %}
 #endif
 #ifndef SWIGCSHARP
@@ -2088,7 +2354,7 @@ public:
 #ifdef SWIGJAVA
 %newobject CreateGeometryFromWkb;
 %inline {
-OGRGeometryShadow* CreateGeometryFromWkb(int nLen, unsigned char *pBuf, 
+OGRGeometryShadow* CreateGeometryFromWkb(int nLen, unsigned char *pBuf,
                                             OSRSpatialReferenceShadow *reference=NULL ) {
     OGRGeometryH geom = NULL;
     OGRErr err = OGR_G_CreateFromWkb((unsigned char*) pBuf, reference, &geom, nLen);
@@ -2107,7 +2373,7 @@ OGRGeometryShadow* CreateGeometryFromWkb(int nLen, unsigned char *pBuf,
 %apply (char **ignorechange) { (char **) };
 %newobject CreateGeometryFromWkt;
 %inline %{
-  OGRGeometryShadow* CreateGeometryFromWkt( char **val, 
+  OGRGeometryShadow* CreateGeometryFromWkt( char **val,
                                       OSRSpatialReferenceShadow *reference=NULL ) {
     OGRGeometryH geom = NULL;
     OGRErr err = OGR_G_CreateFromWkt(val,
@@ -2119,7 +2385,7 @@ OGRGeometryShadow* CreateGeometryFromWkb(int nLen, unsigned char *pBuf,
     }
     return (OGRGeometryShadow*) geom;
   }
- 
+
 %}
 %clear (char **);
 
@@ -2129,7 +2395,7 @@ OGRGeometryShadow* CreateGeometryFromWkb(int nLen, unsigned char *pBuf,
     OGRGeometryShadow* geom = (OGRGeometryShadow*)OGR_G_CreateFromGML(input_string);
     return geom;
   }
- 
+
 %}
 
 %newobject CreateGeometryFromJson;
@@ -2138,7 +2404,7 @@ OGRGeometryShadow* CreateGeometryFromWkb(int nLen, unsigned char *pBuf,
     OGRGeometryShadow* geom = (OGRGeometryShadow*)OGR_G_CreateGeometryFromJson(input_string);
     return geom;
   }
- 
+
 %}
 
 %newobject BuildPolygonFromEdges;
@@ -2146,16 +2412,16 @@ OGRGeometryShadow* CreateGeometryFromWkb(int nLen, unsigned char *pBuf,
 %feature( "kwargs" ) BuildPolygonFromEdges;
 #endif
 %inline %{
-  OGRGeometryShadow* BuildPolygonFromEdges( OGRGeometryShadow*  hLineCollection,  
-                                            int bBestEffort = 0, 
-                                            int bAutoClose = 0, 
+  OGRGeometryShadow* BuildPolygonFromEdges( OGRGeometryShadow*  hLineCollection,
+                                            int bBestEffort = 0,
+                                            int bAutoClose = 0,
                                             double dfTolerance=0) {
-  
+
   OGRGeometryH hPolygon = NULL;
-  
+
   OGRErr eErr;
 
-  hPolygon = OGRBuildPolygonFromEdges( hLineCollection, bBestEffort, 
+  hPolygon = OGRBuildPolygonFromEdges( hLineCollection, bBestEffort,
                                        bAutoClose, dfTolerance, &eErr );
 
   if (eErr != OGRERR_NONE ) {
@@ -2172,14 +2438,14 @@ OGRGeometryShadow* CreateGeometryFromWkb(int nLen, unsigned char *pBuf,
 %feature( "kwargs" ) ApproximateArcAngles;
 #endif
 %inline %{
-  OGRGeometryShadow* ApproximateArcAngles( 
+  OGRGeometryShadow* ApproximateArcAngles(
         double dfCenterX, double dfCenterY, double dfZ,
-  	double dfPrimaryRadius, double dfSecondaryAxis, double dfRotation, 
+  	double dfPrimaryRadius, double dfSecondaryAxis, double dfRotation,
         double dfStartAngle, double dfEndAngle,
         double dfMaxAngleStepSizeDegrees ) {
-  
-  return (OGRGeometryShadow* )OGR_G_ApproximateArcAngles( 
-             dfCenterX, dfCenterY, dfZ, 
+
+  return (OGRGeometryShadow* )OGR_G_ApproximateArcAngles(
+             dfCenterX, dfCenterY, dfZ,
              dfPrimaryRadius, dfSecondaryAxis, dfRotation,
              dfStartAngle, dfEndAngle, dfMaxAngleStepSizeDegrees );
   }
@@ -2260,11 +2526,11 @@ class OGRGeometryShadow {
   OGRGeometryShadow();
 public:
 %extend {
-    
+
   ~OGRGeometryShadow() {
     OGR_G_DestroyGeometry( self );
   }
-  
+
 #ifndef SWIGJAVA
 #ifdef SWIGCSHARP
 %apply (void *buffer_ptr) {char *wkb_buf};
@@ -2290,7 +2556,7 @@ public:
         CPLError(CE_Failure, 1, "Empty geometries cannot be constructed");
         return NULL;}
 
-  }  
+  }
 #ifdef SWIGCSHARP
 %clear (char *wkb_buf);
 #else
@@ -2311,14 +2577,14 @@ public:
 %apply (GByte* outBytes) {GByte*};
   GByte* ExportToWkb( int *nLen, char **pBuf, OGRwkbByteOrder byte_order=wkbXDR ) {
     *nLen = OGR_G_WkbSize( self );
-    *pBuf = (char *) malloc( *nLen * sizeof(unsigned char) );
+    *pBuf = (char *) malloc( *nLen );
     OGR_G_ExportToWkb(self, byte_order, (unsigned char*) *pBuf );
     return (GByte*)*pBuf;
   }
 
   GByte* ExportToIsoWkb( int *nLen, char **pBuf, OGRwkbByteOrder byte_order=wkbXDR ) {
     *nLen = OGR_G_WkbSize( self );
-    *pBuf = (char *) malloc( *nLen * sizeof(unsigned char) );
+    *pBuf = (char *) malloc( *nLen );
     OGR_G_ExportToIsoWkb(self, byte_order, (unsigned char*) *pBuf );
     return (GByte*)*pBuf;
   }
@@ -2327,14 +2593,14 @@ public:
   %feature("kwargs") ExportToWkb;
   OGRErr ExportToWkb( int *nLen, char **pBuf, OGRwkbByteOrder byte_order=wkbXDR ) {
     *nLen = OGR_G_WkbSize( self );
-    *pBuf = (char *) malloc( *nLen * sizeof(unsigned char) );
+    *pBuf = (char *) malloc( *nLen );
     return OGR_G_ExportToWkb(self, byte_order, (unsigned char*) *pBuf );
   }
 
   %feature("kwargs") ExportToIsoWkb;
   OGRErr ExportToIsoWkb( int *nLen, char **pBuf, OGRwkbByteOrder byte_order=wkbXDR ) {
     *nLen = OGR_G_WkbSize( self );
-    *pBuf = (char *) malloc( *nLen * sizeof(unsigned char) );
+    *pBuf = (char *) malloc( *nLen );
     return OGR_G_ExportToIsoWkb(self, byte_order, (unsigned char*) *pBuf );
   }
 #endif
@@ -2393,7 +2659,21 @@ public:
   void AddPoint(double x, double y, double z = 0) {
     OGR_G_AddPoint( self, x, y, z );
   }
-  
+
+#ifndef SWIGJAVA
+  %feature("kwargs") AddPointM;
+#endif
+  void AddPointM(double x, double y, double m) {
+      OGR_G_AddPointM( self, x, y, m );
+  }
+
+#ifndef SWIGJAVA
+  %feature("kwargs") AddPointZM;
+#endif
+  void AddPointZM(double x, double y, double z, double m) {
+      OGR_G_AddPointZM( self, x, y, z, m );
+  }
+
   void AddPoint_2D(double x, double y) {
     OGR_G_AddPoint_2D( self, x, y );
   }
@@ -2416,8 +2696,8 @@ public:
   %newobject Clone;
   OGRGeometryShadow* Clone() {
     return (OGRGeometryShadow*) OGR_G_Clone(self);
-  } 
-    
+  }
+
   OGRwkbGeometryType GetGeometryType() {
     return (OGRwkbGeometryType) OGR_G_GetGeometryType(self);
   }
@@ -2429,7 +2709,7 @@ public:
   double Length () {
     return OGR_G_Length(self);
   }
-  
+
   double Area() {
     return OGR_G_Area(self);
   }
@@ -2438,7 +2718,7 @@ public:
   double GetArea() {
     return OGR_G_Area(self);
   }
-  
+
   int GetPointCount() {
     return OGR_G_GetPointCount(self);
   }
@@ -2501,25 +2781,32 @@ public:
 #endif
 
 #ifndef SWIGJAVA
-  %feature("kwargs") GetX;  
+  %feature("kwargs") GetX;
 #endif
   double GetX(int point=0) {
     return OGR_G_GetX(self, point);
   }
 
 #ifndef SWIGJAVA
-  %feature("kwargs") GetY;  
+  %feature("kwargs") GetY;
 #endif
   double GetY(int point=0) {
     return OGR_G_GetY(self, point);
   }
 
 #ifndef SWIGJAVA
-  %feature("kwargs") GetZ;  
+  %feature("kwargs") GetZ;
 #endif
   double GetZ(int point=0) {
     return OGR_G_GetZ(self, point);
-  } 
+  }
+
+#ifndef SWIGJAVA
+  %feature("kwargs") GetM;
+#endif
+  double GetM(int point=0) {
+    return OGR_G_GetM(self, point);
+  }
 
 #ifdef SWIGJAVA
   void GetPoint(int iPoint, double argout[3]) {
@@ -2530,6 +2817,14 @@ public:
   }
 
 #ifdef SWIGJAVA
+  void GetPointZM(int iPoint, double argout[4]) {
+#else
+  void GetPointZM(int iPoint = 0, double argout[4] = NULL) {
+#endif
+      OGR_G_GetPointZM( self, iPoint, argout+0, argout+1, argout+2, argout+3 );
+  }
+
+#ifdef SWIGJAVA
   void GetPoint_2D(int iPoint, double argout[2]) {
 #else
   void GetPoint_2D(int iPoint = 0, double argout[2] = NULL) {
@@ -2542,19 +2837,33 @@ public:
   }
 
 #ifndef SWIGJAVA
-  %feature("kwargs") SetPoint;    
+  %feature("kwargs") SetPoint;
 #endif
   void SetPoint(int point, double x, double y, double z=0) {
     OGR_G_SetPoint(self, point, x, y, z);
   }
 
 #ifndef SWIGJAVA
+  %feature("kwargs") SetPointM;
+#endif
+  void SetPointM(int point, double x, double y, double m) {
+      OGR_G_SetPointM(self, point, x, y, m);
+  }
+
+#ifndef SWIGJAVA
+  %feature("kwargs") SetPointZM;
+#endif
+  void SetPointZM(int point, double x, double y, double z, double m) {
+      OGR_G_SetPointZM(self, point, x, y, z, m);
+  }
+
+#ifndef SWIGJAVA
   %feature("kwargs") SetPoint_2D;
 #endif
   void SetPoint_2D(int point, double x, double y) {
     OGR_G_SetPoint_2D(self, point, x, y);
   }
-  
+
   /* Geometries own their internal geometries */
   OGRGeometryShadow* GetGeometryRef(int geom) {
     return (OGRGeometryShadow*) OGR_G_GetGeometryRef(self, geom);
@@ -2571,24 +2880,33 @@ public:
     return (OGRGeometryShadow*) OGR_G_SimplifyPreserveTopology(self, tolerance);
   }
 
+  /* OGR >= 2.1 */
+  %newobject DelaunayTriangulation;
+#ifndef SWIGJAVA
+  %feature("kwargs") DelaunayTriangulation;
+#endif
+  OGRGeometryShadow* DelaunayTriangulation(double dfTolerance = 0.0, int bOnlyEdges = FALSE) {
+    return (OGRGeometryShadow*) OGR_G_DelaunayTriangulation(self, dfTolerance, bOnlyEdges);
+  }
+
   %newobject Boundary;
   OGRGeometryShadow* Boundary() {
     return (OGRGeometryShadow*) OGR_G_Boundary(self);
-  }  
+  }
 
   %newobject GetBoundary;
   OGRGeometryShadow* GetBoundary() {
     return (OGRGeometryShadow*) OGR_G_Boundary(self);
-  }  
+  }
 
   %newobject ConvexHull;
   OGRGeometryShadow* ConvexHull() {
     return (OGRGeometryShadow*) OGR_G_ConvexHull(self);
-  } 
+  }
 
   %newobject Buffer;
 #ifndef SWIGJAVA
-  %feature("kwargs") Buffer; 
+  %feature("kwargs") Buffer;
 #endif
   OGRGeometryShadow* Buffer( double distance, int quadsecs=30 ) {
     return (OGRGeometryShadow*) OGR_G_Buffer( self, distance, quadsecs );
@@ -2598,39 +2916,39 @@ public:
   %newobject Intersection;
   OGRGeometryShadow* Intersection( OGRGeometryShadow* other ) {
     return (OGRGeometryShadow*) OGR_G_Intersection( self, other );
-  }  
-  
+  }
+
   %newobject Union;
   OGRGeometryShadow* Union( OGRGeometryShadow* other ) {
     return (OGRGeometryShadow*) OGR_G_Union( self, other );
   }
-  
+
   %newobject UnionCascaded;
   OGRGeometryShadow* UnionCascaded() {
     return (OGRGeometryShadow*) OGR_G_UnionCascaded( self );
-  }  
-  
+  }
+
   %newobject Difference;
   OGRGeometryShadow* Difference( OGRGeometryShadow* other ) {
     return (OGRGeometryShadow*) OGR_G_Difference( self, other );
-  }  
+  }
 
   %newobject SymDifference;
   OGRGeometryShadow* SymDifference( OGRGeometryShadow* other ) {
     return (OGRGeometryShadow*) OGR_G_SymDifference( self, other );
-  } 
+  }
 
   /* old, non-standard API */
   %newobject SymmetricDifference;
   OGRGeometryShadow* SymmetricDifference( OGRGeometryShadow* other ) {
     return (OGRGeometryShadow*) OGR_G_SymDifference( self, other );
-  } 
-  
+  }
+
   double Distance( OGRGeometryShadow* other) {
     return OGR_G_Distance(self, other);
   }
 %clear OGRGeometryShadow* other;
-  
+
   void Empty () {
     OGR_G_Empty(self);
   }
@@ -2638,19 +2956,19 @@ public:
   bool IsEmpty () {
     return (OGR_G_IsEmpty(self) > 0);
   }
-  
+
   bool IsValid () {
     return (OGR_G_IsValid(self) > 0);
-  }  
-  
+  }
+
   bool IsSimple () {
     return (OGR_G_IsSimple(self) > 0);
-  }  
-  
+  }
+
   bool IsRing () {
     return (OGR_G_IsRing(self) > 0);
-  }  
-  
+  }
+
 %apply Pointer NONNULL {OGRGeometryShadow* other};
 
   bool Intersects (OGRGeometryShadow* other) {
@@ -2665,12 +2983,12 @@ public:
   bool Equals (OGRGeometryShadow* other) {
     return (OGR_G_Equals(self, other) > 0);
   }
-  
+
   /* old, non-standard API */
   bool Equal (OGRGeometryShadow* other) {
     return (OGR_G_Equals(self, other) > 0);
   }
-  
+
   bool Disjoint(OGRGeometryShadow* other) {
     return (OGR_G_Disjoint(self, other) > 0);
   }
@@ -2690,7 +3008,7 @@ public:
   bool Contains (OGRGeometryShadow* other) {
     return (OGR_G_Contains(self, other) > 0);
   }
-  
+
   bool Overlaps (OGRGeometryShadow* other) {
     return (OGR_G_Overlaps(self, other) > 0);
   }
@@ -2701,13 +3019,13 @@ public:
     return OGR_G_TransformTo(self, reference);
   }
 %clear OSRSpatialReferenceShadow* reference;
-  
+
 %apply Pointer NONNULL {OSRCoordinateTransformationShadow* trans};
   OGRErr Transform(OSRCoordinateTransformationShadow* trans) {
     return OGR_G_Transform(self, trans);
   }
 %clear OSRCoordinateTransformationShadow* trans;
-  
+
   %newobject GetSpatialReference;
   OSRSpatialReferenceShadow* GetSpatialReference() {
     OGRSpatialReferenceH ref =  OGR_G_GetSpatialReference(self);
@@ -2715,15 +3033,15 @@ public:
         OSRReference(ref);
     return (OSRSpatialReferenceShadow*) ref;
   }
-  
+
   void AssignSpatialReference(OSRSpatialReferenceShadow* reference) {
     OGR_G_AssignSpatialReference(self, reference);
   }
-  
+
   void CloseRings() {
     OGR_G_CloseRings(self);
   }
-  
+
   void FlattenTo2D() {
     OGR_G_FlattenTo2D(self);
   }
@@ -2733,7 +3051,7 @@ public:
   }
 
 
-#if defined(SWIGCSHARP)  
+#if defined(SWIGCSHARP)
   void GetEnvelope(OGREnvelope *env) {
     OGR_G_GetEnvelope(self, env);
   }
@@ -2749,7 +3067,7 @@ public:
   void GetEnvelope3D(double argout[6]) {
     OGR_G_GetEnvelope3D(self, (OGREnvelope3D*)argout);
   }
-#endif  
+#endif
 
   %newobject Centroid;
   OGRGeometryShadow* Centroid() {
@@ -2757,7 +3075,7 @@ public:
     OGR_G_Centroid( self, pt );
     return pt;
   }
-  
+
   %newobject PointOnSurface;
   OGRGeometryShadow* PointOnSurface() {
     return (OGRGeometryShadow*) OGR_G_PointOnSurface( self );
@@ -2766,15 +3084,35 @@ public:
   int WkbSize() {
     return OGR_G_WkbSize(self);
   }
-  
+
   int GetCoordinateDimension() {
     return OGR_G_GetCoordinateDimension(self);
   }
 
+  int CoordinateDimension() {
+    return OGR_G_CoordinateDimension(self);
+  }
+
+  int Is3D() {
+      return OGR_G_Is3D(self);
+  }
+
+  int IsMeasured() {
+      return OGR_G_IsMeasured(self);
+  }
+
   void SetCoordinateDimension(int dimension) {
     OGR_G_SetCoordinateDimension(self, dimension);
   }
-  
+
+  void Set3D(int b3D) {
+      OGR_G_Set3D(self, b3D);
+  }
+
+  void SetMeasured(int bMeasured) {
+      OGR_G_SetMeasured(self, bMeasured);
+  }
+
   int GetDimension() {
     return OGR_G_GetDimension(self);
   }
@@ -2786,7 +3124,7 @@ public:
 
   %newobject GetLinearGeometry;
 #ifndef SWIGJAVA
-  %feature("kwargs") GetLinearGeometry;  
+  %feature("kwargs") GetLinearGeometry;
 #endif
   OGRGeometryShadow* GetLinearGeometry(double dfMaxAngleStepSizeDegrees = 0.0,char** options = NULL) {
     return (OGRGeometryShadow* )OGR_G_GetLinearGeometry(self, dfMaxAngleStepSizeDegrees, options);
@@ -2794,7 +3132,7 @@ public:
 
   %newobject GetCurveGeometry;
 #ifndef SWIGJAVA
-  %feature("kwargs") GetCurveGeometry;  
+  %feature("kwargs") GetCurveGeometry;
 #endif
   OGRGeometryShadow* GetCurveGeometry(char** options = NULL) {
     return (OGRGeometryShadow* )OGR_G_GetCurveGeometry(self, options);
@@ -2816,6 +3154,7 @@ public:
 
 #ifndef FROM_GDAL_I
 
+#ifndef SWIGPERL
 %{
 char const *OGRDriverShadow_get_name( OGRDriverShadow *h ) {
   return OGR_Dr_GetName( h );
@@ -2833,6 +3172,7 @@ char const *OGRDataSourceShadow_name_get( OGRDataSourceShadow *h ) {
   return OGR_DS_GetName( h );
 }
 %}
+#endif
 
 int OGRGetDriverCount();
 
@@ -2859,16 +3199,31 @@ OGRwkbGeometryType OGR_GT_Flatten( OGRwkbGeometryType eType );
 %rename (GT_SetZ) OGR_GT_SetZ;
 OGRwkbGeometryType OGR_GT_SetZ( OGRwkbGeometryType eType );
 
+%rename (GT_SetM) OGR_GT_SetM;
+OGRwkbGeometryType OGR_GT_SetM( OGRwkbGeometryType eType );
+
+#ifndef SWIGPERL
 %inline  %{
 OGRwkbGeometryType GT_SetModifier( OGRwkbGeometryType eType, int bSetZ, int bSetM = FALSE)
 {
     return OGR_GT_SetModifier(eType, bSetZ, bSetM);
 }
 %}
+#else
+%inline  %{
+int GT_SetModifier( int eType, int bSetZ, int bSetM)
+{
+    return OGR_GT_SetModifier((OGRwkbGeometryType)eType, bSetZ, bSetM);
+}
+%}
+#endif
 
 %rename (GT_HasZ) OGR_GT_HasZ;
 int                OGR_GT_HasZ( OGRwkbGeometryType eType );
 
+%rename (GT_HasM) OGR_GT_HasM;
+int                OGR_GT_HasM( OGRwkbGeometryType eType );
+
 %rename (GT_IsSubClassOf) OGR_GT_IsSubClassOf;
 int                OGR_GT_IsSubClassOf( OGRwkbGeometryType eType,
                                                 OGRwkbGeometryType eSuperType );
@@ -2897,6 +3252,7 @@ void OGRSetNonLinearGeometriesEnabledFlag( int bFlag );
 %rename (GetNonLinearGeometriesEnabledFlag) OGRGetNonLinearGeometriesEnabledFlag;
 int OGRGetNonLinearGeometriesEnabledFlag(void);
 
+#ifndef SWIGPERL
 %inline %{
   OGRDataSourceShadow* GetOpenDS(int ds_number) {
     OGRDataSourceShadow* layer = (OGRDataSourceShadow*) OGRGetOpenDS(ds_number);
@@ -2916,13 +3272,13 @@ int OGRGetNonLinearGeometriesEnabledFlag(void);
     OGRDataSourceShadow* ds = (OGRDataSourceShadow*)OGROpen(utf8_path,update,NULL);
     if( CPLGetLastErrorType() == CE_Failure && ds != NULL )
     {
-        CPLDebug( "SWIG", 
+        CPLDebug( "SWIG",
 		  "OGROpen() succeeded, but an error is posted, so we destroy"
 		  " the datasource and fail at swig level." );
         OGRReleaseDataSource(ds);
         ds = NULL;
     }
-	
+
     return ds;
   }
 %}
@@ -2940,7 +3296,7 @@ int OGRGetNonLinearGeometriesEnabledFlag(void);
         OGRReleaseDataSource(ds);
         ds = NULL;
     }
-	
+
     return ds;
   }
 %}
@@ -2950,10 +3306,12 @@ int OGRGetNonLinearGeometriesEnabledFlag(void);
 #ifndef FROM_GDAL_I
 
 %inline %{
+static
 OGRDriverShadow* GetDriverByName( char const *name ) {
   return (OGRDriverShadow*) OGRGetDriverByName( name );
 }
 
+static
 OGRDriverShadow* GetDriver(int driver_number) {
   return (OGRDriverShadow*) OGRGetDriver(driver_number);
 }
@@ -2970,17 +3328,18 @@ OGRDriverShadow* GetDriver(int driver_number) {
 /* Interface method added for GDAL 1.7.0 */
 #ifdef SWIGJAVA
 %inline %{
+  static
   char **GeneralCmdLineProcessor( char **papszArgv, int nOptions = 0 ) {
     int nResArgCount;
-    
+
     /* We must add a 'dummy' element in front of the real argument list */
     /* as Java doesn't include the binary name as the first */
     /* argument, as C does... */
     char** papszArgvModBefore = CSLInsertString(CSLDuplicate(papszArgv), 0, "dummy");
     char** papszArgvModAfter = papszArgvModBefore;
 
-    nResArgCount = 
-      OGRGeneralCmdLineProcessor( CSLCount(papszArgvModBefore), &papszArgvModAfter, nOptions ); 
+    nResArgCount =
+      OGRGeneralCmdLineProcessor( CSLCount(papszArgvModBefore), &papszArgvModAfter, nOptions );
 
     CSLDestroy(papszArgvModBefore);
 
@@ -3002,8 +3361,11 @@ OGRDriverShadow* GetDriver(int driver_number) {
   char **GeneralCmdLineProcessor( char **papszArgv, int nOptions = 0 ) {
     int nResArgCount;
 
-    nResArgCount = 
-      OGRGeneralCmdLineProcessor( CSLCount(papszArgv), &papszArgv, nOptions ); 
+    if( papszArgv == NULL )
+        return NULL;
+
+    nResArgCount =
+      OGRGeneralCmdLineProcessor( CSLCount(papszArgv), &papszArgv, nOptions );
 
     if( nResArgCount <= 0 )
         return NULL;
@@ -3016,6 +3378,8 @@ OGRDriverShadow* GetDriver(int driver_number) {
 
 #endif /* FROM_GDAL_I */
 
+#endif /* #ifndef SWIGPERL */
+
 #ifdef SWIGJAVA
 class FeatureNative {
   FeatureNative();
@@ -3039,6 +3403,7 @@ class GeometryNative {
 %rename (TermProgress_nocb) GDALTermProgress_nocb;
 %feature( "kwargs" ) GDALTermProgress_nocb;
 %inline %{
+static
 int GDALTermProgress_nocb( double dfProgress, const char * pszMessage=NULL, void *pData=NULL ) {
   return GDALTermProgress( dfProgress, pszMessage, pData);
 }
@@ -3062,7 +3427,6 @@ int GDALTermProgress( double, const char *, void * );
 %include "ogr_csharp_extend.i"
 #endif
 
-
 #ifdef SWIGJAVA
 %include "ogr_java_extend.i"
 #endif
diff --git a/swig/include/ogr_error_map.i b/swig/include/ogr_error_map.i
index b635d93..fc6229b 100644
--- a/swig/include/ogr_error_map.i
+++ b/swig/include/ogr_error_map.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_error_map.i 28809 2015-03-28 17:10:07Z rouault $
+ * $Id: ogr_error_map.i 32864 2016-01-08 21:00:50Z goatbar $
  *
  * Project:  GDAL SWIG Interfaces.
  * Purpose:  OGRErr handling typemap.
@@ -28,9 +28,9 @@
  *****************************************************************************/
 
 #ifdef SWIGRUBY
-%header 
+%header
 #else
-%fragment("OGRErrMessages","header") 
+%fragment("OGRErrMessages","header")
 #endif
 %{
 
diff --git a/swig/include/osr.i b/swig/include/osr.i
index a0132f5..3fe6b22 100644
--- a/swig/include/osr.i
+++ b/swig/include/osr.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: osr.i 28972 2015-04-22 10:39:11Z rouault $
+ * $Id: osr.i 32864 2016-01-08 21:00:50Z goatbar $
  *
  * Project:  GDAL SWIG Interfaces.
  * Purpose:  OGRSpatialReference related declarations.
@@ -117,7 +117,7 @@ OGRErr GetWellKnownGeogCSAsWKT( const char *name, char **argout ) {
   OGRSpatialReferenceH srs = OSRNewSpatialReference("");
   OGRErr rcode = OSRSetWellKnownGeogCS( srs, name );
   if( rcode == OGRERR_NONE )
-      rcode = OSRExportToWkt ( srs, argout );  
+      rcode = OSRExportToWkt ( srs, argout );
   OSRDestroySpatialReference( srs );
   return rcode;
 }
@@ -131,7 +131,7 @@ OGRErr GetUserInputAsWKT( const char *name, char **argout ) {
   OGRSpatialReferenceH srs = OSRNewSpatialReference("");
   OGRErr rcode = OSRSetFromUserInput( srs, name );
   if( rcode == OGRERR_NONE )
-      rcode = OSRExportToWkt ( srs, argout );  
+      rcode = OSRExportToWkt ( srs, argout );
   OSRDestroySpatialReference( srs );
   return rcode;
 }
@@ -146,7 +146,7 @@ OGRErr GetUserInputAsWKT( const char *name, char **argout ) {
  *
  * All other languages will have a more simplistic interface which is
  * exactly the same as the C api.
- * 
+ *
  */
 
 #if !defined(SWIGPYTHON)
@@ -286,7 +286,7 @@ public:
 */
 
   OGRErr SetAttrValue( const char *name, const char *value ) {
-    return OSRSetAttrValue( self, name, value ); 
+    return OSRSetAttrValue( self, name, value );
   }
 
 /*
@@ -330,7 +330,7 @@ public:
       name = OSRGetAttrValue( self, "LOCAL_CS|UNIT", 0 );
     }
 
-    if (name != 0) 
+    if (name != 0)
       return name;
 
     return "Meter";
@@ -349,8 +349,8 @@ public:
   }
 
   int GetUTMZone() {
-    // Note: we will return south zones as negative since it is 
-    // hard to return two values as the C API does. 
+    // Note: we will return south zones as negative since it is
+    // hard to return two values as the C API does.
     int bNorth = FALSE;
     int nZone = OSRGetUTMZone( self, &bNorth );
     if( !bNorth )
@@ -371,7 +371,7 @@ public:
   }
 
   OGRErr SetProjParm( const char *name, double val ) {
-    return OSRSetProjParm( self, name, val ); 
+    return OSRSetProjParm( self, name, val );
   }
 
   double GetProjParm( const char *name, double default_val = 0.0 ) {
@@ -407,14 +407,14 @@ public:
   OGRErr SetACEA( double stdp1, double stdp2,
  		double clat, double clong,
                 double fe, double fn ) {
-    return OSRSetACEA( self, stdp1, stdp2, clat, clong, 
+    return OSRSetACEA( self, stdp1, stdp2, clat, clong,
                        fe, fn );
-  }    
+  }
 
 %feature( "kwargs" ) SetAE;
   OGRErr SetAE( double clat, double clong,
               double fe, double fn ) {
-    return OSRSetAE( self, clat, clong, 
+    return OSRSetAE( self, clat, clong,
                      fe, fn );
   }
 
@@ -426,14 +426,14 @@ public:
 %feature( "kwargs" ) SetCEA;
   OGRErr SetCEA( double stdp1, double cm,
                double fe, double fn ) {
-    return OSRSetCEA( self, stdp1, cm, 
+    return OSRSetCEA( self, stdp1, cm,
                       fe, fn );
   }
 
 %feature( "kwargs" ) SetCS;
   OGRErr SetCS( double clat, double clong,
               double fe, double fn ) {
-    return OSRSetCS( self, clat, clong, 
+    return OSRSetCS( self, clat, clong,
                      fe, fn );
   }
 
@@ -441,7 +441,7 @@ public:
   OGRErr SetEC( double stdp1, double stdp2,
               double clat, double clong,
               double fe, double fn ) {
-    return OSRSetEC( self, stdp1, stdp2, clat, clong, 
+    return OSRSetEC( self, stdp1, stdp2, clat, clong,
                      fe, fn );
   }
 
@@ -460,7 +460,7 @@ public:
 %feature( "kwargs" ) SetEquirectangular;
   OGRErr SetEquirectangular( double clat, double clong,
                            double fe, double fn ) {
-    return OSRSetEquirectangular( self, clat, clong, 
+    return OSRSetEquirectangular( self, clat, clong,
                                   fe, fn );
   }
 
@@ -483,7 +483,7 @@ public:
               double fe, double fn ) {
     return OSRSetGS( self, cm, fe, fn );
   }
-    
+
 %feature( "kwargs" ) SetGH;
   OGRErr SetGH( double cm,
               double fe, double fn ) {
@@ -493,18 +493,18 @@ public:
   OGRErr SetIGH() {
     return OSRSetIGH( self );
   }
-    
+
 %feature( "kwargs" ) SetGEOS;
   OGRErr SetGEOS( double cm, double satelliteheight,
                 double fe, double fn ) {
     return OSRSetGEOS( self, cm, satelliteheight,
                        fe, fn );
   }
-    
+
 %feature( "kwargs" ) SetGnomonic;
   OGRErr SetGnomonic( double clat, double clong,
                     double fe, double fn ) {
-    return OSRSetGnomonic( self, clat, clong, 
+    return OSRSetGnomonic( self, clat, clong,
                            fe, fn );
   }
 
@@ -523,24 +523,24 @@ public:
                    double dfLat2, double dfLong2,
                    double scale,
                    double fe, double fn ) {
-    return OSRSetHOM2PNO( self, clat, dfLat1, dfLong1, dfLat2, dfLong2, 
+    return OSRSetHOM2PNO( self, clat, dfLat1, dfLong1, dfLat2, dfLong2,
                           scale, fe, fn );
   }
 
 %feature( "kwargs" ) SetKrovak;
   OGRErr SetKrovak( double clat, double clong,
                   double azimuth, double pseudostdparallellat,
-                  double scale, 
+                  double scale,
                   double fe, double fn ) {
-    return OSRSetKrovak( self, clat, clong, 
-                         azimuth, pseudostdparallellat, 
+    return OSRSetKrovak( self, clat, clong,
+                         azimuth, pseudostdparallellat,
                          scale, fe, fn );
   }
 
 %feature( "kwargs" ) SetLAEA;
   OGRErr SetLAEA( double clat, double clong,
                 double fe, double fn ) {
-    return OSRSetLAEA( self, clat, clong, 
+    return OSRSetLAEA( self, clat, clong,
                        fe, fn );
   }
 
@@ -548,7 +548,7 @@ public:
   OGRErr SetLCC( double stdp1, double stdp2,
                double clat, double clong,
                double fe, double fn ) {
-    return OSRSetLCC( self, stdp1, stdp2, clat, clong, 
+    return OSRSetLCC( self, stdp1, stdp2, clat, clong,
                       fe, fn );
   }
 
@@ -556,7 +556,7 @@ public:
   OGRErr SetLCC1SP( double clat, double clong,
                   double scale,
                   double fe, double fn ) {
-    return OSRSetLCC1SP( self, clat, clong, scale, 
+    return OSRSetLCC1SP( self, clat, clong, scale,
                          fe, fn );
   }
 
@@ -564,36 +564,36 @@ public:
   OGRErr SetLCCB( double stdp1, double stdp2,
                 double clat, double clong,
                 double fe, double fn ) {
-    return OSRSetLCCB( self, stdp1, stdp2, clat, clong, 
+    return OSRSetLCCB( self, stdp1, stdp2, clat, clong,
                        fe, fn );
   }
-    
+
 %feature( "kwargs" ) SetMC;
   OGRErr SetMC( double clat, double clong,
               double fe, double fn ) {
-    return OSRSetMC( self, clat, clong,    
+    return OSRSetMC( self, clat, clong,
                      fe, fn );
   }
 
 %feature( "kwargs" ) SetMercator;
   OGRErr SetMercator( double clat, double clong,
-                    double scale, 
+                    double scale,
                     double fe, double fn ) {
-    return OSRSetMercator( self, clat, clong, 
+    return OSRSetMercator( self, clat, clong,
                            scale, fe, fn );
   }
 
 %feature( "kwargs" ) SetMollweide;
   OGRErr  SetMollweide( double cm,
                       double fe, double fn ) {
-    return OSRSetMollweide( self, cm, 
+    return OSRSetMollweide( self, cm,
                             fe, fn );
   }
 
 %feature( "kwargs" ) SetNZMG;
   OGRErr SetNZMG( double clat, double clong,
                 double fe, double fn ) {
-    return OSRSetNZMG( self, clat, clong, 
+    return OSRSetNZMG( self, clat, clong,
                        fe, fn );
   }
 
@@ -601,21 +601,21 @@ public:
   OGRErr SetOS( double dfOriginLat, double dfCMeridian,
               double scale,
               double fe,double fn) {
-    return OSRSetOS( self, dfOriginLat, dfCMeridian, scale, 
+    return OSRSetOS( self, dfOriginLat, dfCMeridian, scale,
                      fe, fn );
   }
-    
+
 %feature( "kwargs" ) SetOrthographic;
   OGRErr SetOrthographic( double clat, double clong,
                         double fe,double fn) {
-    return OSRSetOrthographic( self, clat, clong, 
+    return OSRSetOrthographic( self, clat, clong,
                                fe, fn );
   }
 
 %feature( "kwargs" ) SetPolyconic;
   OGRErr SetPolyconic( double clat, double clong,
                      double fe, double fn ) {
-    return OSRSetPolyconic( self, clat, clong, 
+    return OSRSetPolyconic( self, clat, clong,
                             fe, fn );
   }
 
@@ -626,39 +626,39 @@ public:
     return OSRSetPS( self, clat, clong, scale,
                      fe, fn );
   }
-    
+
 %feature( "kwargs" ) SetRobinson;
-  OGRErr SetRobinson( double clong, 
+  OGRErr SetRobinson( double clong,
                     double fe, double fn ) {
     return OSRSetRobinson( self, clong, fe, fn );
   }
-    
+
 %feature( "kwargs" ) SetSinusoidal;
-  OGRErr SetSinusoidal( double clong, 
+  OGRErr SetSinusoidal( double clong,
                       double fe, double fn ) {
     return OSRSetSinusoidal( self, clong, fe, fn );
   }
-    
+
 %feature( "kwargs" ) SetStereographic;
   OGRErr SetStereographic( double clat, double clong,
                          double scale,
                          double fe,double fn) {
-    return OSRSetStereographic( self, clat, clong, scale, 
+    return OSRSetStereographic( self, clat, clong, scale,
                                 fe, fn );
   }
-    
+
 %feature( "kwargs" ) SetSOC;
   OGRErr SetSOC( double latitudeoforigin, double cm,
                double fe, double fn ) {
     return OSRSetSOC( self, latitudeoforigin, cm,
 	              fe, fn );
   }
-    
+
 %feature( "kwargs" ) SetTM;
   OGRErr SetTM( double clat, double clong,
               double scale,
               double fe, double fn ) {
-    return OSRSetTM( self, clat, clong, scale, 
+    return OSRSetTM( self, clat, clong, scale,
                      fe, fn );
   }
 
@@ -667,14 +667,14 @@ public:
                      double clat, double clong,
                      double scale,
                      double fe, double fn ) {
-    return OSRSetTMVariant( self, pszVariantName, clat, clong,  
+    return OSRSetTMVariant( self, pszVariantName, clat, clong,
                             scale, fe, fn );
   }
 
 %feature( "kwargs" ) SetTMG;
-  OGRErr SetTMG( double clat, double clong, 
+  OGRErr SetTMG( double clat, double clong,
                double fe, double fn ) {
-    return OSRSetTMG( self, clat, clong, 
+    return OSRSetTMG( self, clat, clong,
                       fe, fn );
   }
 
@@ -682,7 +682,7 @@ public:
   OGRErr SetTMSO( double clat, double clong,
                 double scale,
                 double fe, double fn ) {
-    return OSRSetTMSO( self, clat, clong, scale, 
+    return OSRSetTMSO( self, clat, clong, scale,
                        fe, fn );
   }
 
@@ -749,10 +749,10 @@ public:
                     const char *VertDatumName = "unnamed",
                     int VertDatumType = 0) {
     return OSRSetVertCS( self, VertCSName, VertDatumName, VertDatumType );
-  }  
+  }
 
 %apply Pointer NONNULL {OSRSpatialReferenceShadow* horizcs};
-%apply Pointer NONNULL {OSRSpatialReferenceShadow* vertcs};  
+%apply Pointer NONNULL {OSRSpatialReferenceShadow* vertcs};
   OGRErr SetCompoundCS( const char *name,
                         OSRSpatialReferenceShadow *horizcs,
                         OSRSpatialReferenceShadow *vertcs ) {
@@ -851,7 +851,7 @@ public:
   OGRErr ExportToXML( char **argout, const char *dialect = "" ) {
     return OSRExportToXML( self, argout, dialect );
   }
-  
+
   OGRErr ExportToMICoordSys( char **argout ) {
     return OSRExportToMICoordSys( self, argout );
   }
@@ -890,7 +890,6 @@ public:
     return OSRMorphFromESRI(self);
   }
 
-
 } /* %extend */
 };
 
@@ -944,7 +943,7 @@ public:
     argout[2] = z;
     OCTTransform( self, 1, &argout[0], &argout[1], &argout[2] );
   }
-  
+
 #ifdef SWIGCSHARP
   %apply (double *inout) {(double*)};
 #endif
diff --git a/swig/include/perl/callback.i b/swig/include/perl/callback.i
index cab94ce..6c72054 100644
--- a/swig/include/perl/callback.i
+++ b/swig/include/perl/callback.i
@@ -1,4 +1,4 @@
-%inline %{
+%header %{
     #ifndef SWIG
     typedef struct
     {
@@ -31,4 +31,21 @@
         LEAVE;
         return ret;
     }
+    #ifndef SWIG
+    static SV *VSIStdoutSetRedirectionFct = &PL_sv_undef;
+    #endif
+    size_t callback_fwrite(const void *ptr, size_t size, size_t nmemb,
+                           FILE *stream)
+    {
+        dSP;
+        ENTER;
+        SAVETMPS;
+        PUSHMARK(SP);
+        XPUSHs(sv_2mortal(newSVpv((const char*)ptr, size*nmemb)));
+        PUTBACK;
+        call_sv(VSIStdoutSetRedirectionFct, G_DISCARD);
+        FREETMPS;
+        LEAVE;
+        return size*nmemb;
+    }
 %}
diff --git a/swig/include/perl/confess.i b/swig/include/perl/confess.i
new file mode 100644
index 0000000..62cc957
--- /dev/null
+++ b/swig/include/perl/confess.i
@@ -0,0 +1,33 @@
+%header %{
+    void do_confess(const char *error, int push_to_error_stack) {
+        SV *sv = newSVpv(error, 0);
+        if (push_to_error_stack) {
+            AV* error_stack = get_av("Geo::GDAL::error", 0);
+            av_push(error_stack, sv);
+        } else {
+            sv = sv_2mortal(sv);
+        }
+        dSP;
+        ENTER;
+        SAVETMPS;
+        PUSHMARK(SP);
+        XPUSHs( sv );
+        PUTBACK;
+        call_pv("Carp::confess", G_DISCARD);
+        /*
+        confess never returns, so these will not get executed:
+        FREETMPS;
+        LEAVE;
+        */
+    }
+    #define OUT_OF_MEMORY "Out of memory."
+    #define CALL_FAILED "Call failed. Possible reason is an index out of range, mathematical problem, or something else."
+    #define NEED_DEF "A parameter which must be defined or not empty, is not."
+    #define WRONG_CLASS "Object has a wrong class."
+    #define NEED_REF "A parameter which must be a reference, is not."
+    #define NEED_ARRAY_REF "A parameter/item which must be an array reference, is not."
+    #define NEED_BINARY_DATA "A parameter which must be binary data, is not."
+    #define NEED_CODE_REF "A parameter which must be an anonymous subroutine, is not."
+    #define WRONG_ITEM_IN_ARRAY "An item in an array parameter has wrong type."
+    #define ARRAY_TO_XML_FAILED "An array parameter cannot be converted to an XMLTree."
+%}
diff --git a/swig/include/perl/destroy.i b/swig/include/perl/destroy.i
index bd64fb6..75d9133 100644
--- a/swig/include/perl/destroy.i
+++ b/swig/include/perl/destroy.i
@@ -2,20 +2,25 @@
 %feature("shadow") ~class()
 %{
 sub DESTROY {
-    my $self;
-    if ($_[0]->isa('SCALAR')) {
-        $self = $_[0];
-    } else {
-        return unless $_[0]->isa('HASH');
-        $self = tied(%{$_[0]});
+    my $self = shift;
+    unless ($self->isa('SCALAR')) {
+        return unless $self->isa('HASH');
+        $self = tied(%{$self});
         return unless defined $self;
     }
+    my $code = $Geo::GDAL::stdout_redirection{$self};
+    delete $Geo::GDAL::stdout_redirection{$self};
     delete $ITERATORS{$self};
     if (exists $OWNER{$self}) {
         Geo::modulec::delete_class($self);
         delete $OWNER{$self};
     }
     $self->RELEASE_PARENTS();
+    if ($code) {
+        Geo::GDAL::VSIStdoutUnsetRedirection();
+        $code->close;
+    }
+
 }
 %}
 %enddef
diff --git a/swig/include/perl/gdal_perl.i b/swig/include/perl/gdal_perl.i
index 35270a8..29e65fe 100644
--- a/swig/include/perl/gdal_perl.i
+++ b/swig/include/perl/gdal_perl.i
@@ -35,7 +35,7 @@
 %}
 
 %include callback.i
-
+%include confess.i
 %include cpl_exceptions.i
 
 %rename (GetMetadata) GetMetadata_Dict;
@@ -63,7 +63,7 @@ ALTERED_DESTROY(GDALRasterAttributeTableShadow, GDALc, delete_RasterAttributeTab
 
 /* Make room for Perl interface */
 
-%rename (_GetDriver) GetDriver;
+%rename (_FindFile) FindFile;
 
 %rename (_Open) Open;
 %newobject _Open;
@@ -71,23 +71,22 @@ ALTERED_DESTROY(GDALRasterAttributeTableShadow, GDALc, delete_RasterAttributeTab
 %rename (_OpenShared) OpenShared;
 %newobject _OpenShared;
 
+%rename (_OpenEx) OpenEx;
+%newobject _OpenEx;
+
 %rename (_BuildOverviews) BuildOverviews;
 
 %rename (_ReadRaster) ReadRaster;
 %rename (_WriteRaster) WriteRaster;
 
+%rename (_CreateLayer) CreateLayer;
+%rename (_DeleteLayer) DeleteLayer;
+
 %rename (_GetMaskFlags) GetMaskFlags;
 %rename (_CreateMaskBand) CreateMaskBand;
 
-/* those that need callback_data check: */
-
-%rename (_ComputeMedianCutPCT) ComputeMedianCutPCT;
-%rename (_DitherRGB2PCT) DitherRGB2PCT;
 %rename (_ReprojectImage) ReprojectImage;
-%rename (_ComputeProximity) ComputeProximity;
-%rename (_RasterizeLayer) RasterizeLayer;
 %rename (_Polygonize) Polygonize;
-%rename (_SieveFilter) SieveFilter;
 %rename (_RegenerateOverviews) RegenerateOverviews;
 %rename (_RegenerateOverview) RegenerateOverview;
 
@@ -97,9 +96,15 @@ ALTERED_DESTROY(GDALRasterAttributeTableShadow, GDALc, delete_RasterAttributeTab
 %rename (_Create) Create;
 %newobject _Create;
 
+%rename (_CreateCopy) CreateCopy;
+%newobject _CreateCopy;
+
 %rename (_GetRasterBand) GetRasterBand;
 %rename (_AddBand) AddBand;
 
+%rename (_GetMaskBand) GetMaskBand;
+%rename (_GetOverview) GetOverview;
+
 %rename (_GetPaletteInterpretation) GetPaletteInterpretation;
 %rename (_GetHistogram) GetHistogram;
 
@@ -115,10 +120,12 @@ ALTERED_DESTROY(GDALRasterAttributeTableShadow, GDALc, delete_RasterAttributeTab
 %perlcode %{
 
 package Geo::GDAL;
+require 5.10.0; # we use //=
 use strict;
 use warnings;
 use Carp;
 use Encode;
+use Exporter 'import';
 use Geo::GDAL::Const;
 use Geo::OGR;
 use Geo::OSR;
@@ -129,9 +136,12 @@ use Geo::OSR;
 # build.
 # For GDAL 2.0 or above, GDAL X.Y.Z should then
 # VERSION = X + Y / 100.0 + Z / 10000.0
+# Note also the $VERSION in ogr_perl.i (required by pause.perl.org)
+# Note that the 1/100000 digits may be used to create more than one
+# CPAN release from one GDAL release.
 
-our $VERSION = '2.0002';
-our $GDAL_VERSION = '2.0.2';
+our $VERSION = '2.0100';
+our $GDAL_VERSION = '2.1.0';
 
 =pod
 
@@ -150,12 +160,12 @@ Geo::GDAL - Perl extension for the GDAL library for geospatial data
   my $raster_data = $dataset->GetRasterBand(1)->ReadTile;
 
   my $vector_datasource = Geo::OGR::Open('./');
- 
+
   my $vector_layer = $datasource->Layer('borders'); # e.g. a shapefile borders.shp in current directory
 
   $vector_layer->ResetReading();
-  while (my $feature = $vector_layer->GetNextFeature()) {  
-      my $geometry = $feature->GetGeometry(); 
+  while (my $feature = $vector_layer->GetNextFeature()) {
+      my $geometry = $feature->GetGeometry();
       my $value = $feature->GetField($field);
   }
 
@@ -194,18 +204,24 @@ L<https://trac.osgeo.org/gdal>
 
 =cut
 
+use Scalar::Util 'blessed';
 use vars qw/
-    @DATA_TYPES @ACCESS_TYPES @RESAMPLING_TYPES @RIO_RESAMPLING_TYPES @NODE_TYPES
+    @EXPORT_OK %EXPORT_TAGS
+    @DATA_TYPES @OPEN_FLAGS @RESAMPLING_TYPES @RIO_RESAMPLING_TYPES @NODE_TYPES
     %TYPE_STRING2INT %TYPE_INT2STRING
-    %ACCESS_STRING2INT %ACCESS_INT2STRING
+    %OF_STRING2INT
     %RESAMPLING_STRING2INT %RESAMPLING_INT2STRING
     %RIO_RESAMPLING_STRING2INT %RIO_RESAMPLING_INT2STRING
     %NODE_TYPE_STRING2INT %NODE_TYPE_INT2STRING
+    @error %stdout_redirection
     /;
+ at EXPORT_OK = qw/Driver Open BuildVRT/;
+%EXPORT_TAGS = (all => [qw(Driver Open BuildVRT)]);
+*BuildVRT = *Geo::GDAL::Dataset::BuildVRT;
 for (keys %Geo::GDAL::Const::) {
     next if /TypeCount/;
     push(@DATA_TYPES, $1), next if /^GDT_(\w+)/;
-    push(@ACCESS_TYPES, $1), next if /^GA_(\w+)/;
+    push(@OPEN_FLAGS, $1), next if /^OF_(\w+)/;
     push(@RESAMPLING_TYPES, $1), next if /^GRA_(\w+)/;
     push(@RIO_RESAMPLING_TYPES, $1), next if /^GRIORA_(\w+)/;
     push(@NODE_TYPES, $1), next if /^CXT_(\w+)/;
@@ -215,10 +231,9 @@ for my $string (@DATA_TYPES) {
     $TYPE_STRING2INT{$string} = $int;
     $TYPE_INT2STRING{$int} = $string;
 }
-for my $string (@ACCESS_TYPES) {
-    my $int = eval "\$Geo::GDAL::Const::GA_$string";
-    $ACCESS_STRING2INT{$string} = $int;
-    $ACCESS_INT2STRING{$int} = $string;
+for my $string (@OPEN_FLAGS) {
+    my $int = eval "\$Geo::GDAL::Const::OF_$string";
+    $OF_STRING2INT{$string} = $int;
 }
 for my $string (@RESAMPLING_TYPES) {
     my $int = eval "\$Geo::GDAL::Const::GRA_$string";
@@ -236,15 +251,110 @@ for my $string (@NODE_TYPES) {
     $NODE_TYPE_INT2STRING{$int} = $string;
 }
 
+sub error {
+    if (@_) {
+        my $error;
+        if (@_ == 3) {
+            my ($ecode, $offender, $ex) = @_;
+            if ($ecode == 1) {
+                my @k = sort keys %$ex;
+                $error = "Unknown value: '$offender'. " if defined $offender;
+                $error .= "Expected one of ".join(', ', @k).".";
+            } elsif ($ecode == 2) {
+                $error = "$ex not found: '$offender'.";
+            } else {
+                die("error in error: $ecode, $offender, $ex");
+            }
+        } else {
+            $error = shift;
+        }
+        push @error, $error;
+        confess($error);
+    }
+    my @stack = @error;
+    chomp(@stack);
+    @error = ();
+    return wantarray ? @stack : join("\n", @stack);
+}
+
+sub last_error {
+    my $error = $error[$#error] // '';
+    chomp($error);
+    return $error;
+}
+
+sub errstr {
+    my @stack = @error;
+    chomp(@stack);
+    @error = ();
+    return join("\n", @stack);
+}
+
+# usage: named_parameters(\@_, key value list of default parameters);
+# returns parameters in a hash with low-case-without-_ keys
+sub named_parameters {
+    my $parameters = shift;
+    my %defaults = @_;
+    my %c;
+    for my $k (keys %defaults) {
+        my $c = lc($k); $c =~ s/_//g;
+        $c{$c} = $k;
+    }
+    my %named;
+    my @p = ref($parameters->[0]) eq 'HASH' ? %{$parameters->[0]} : @$parameters;
+    if (@p) {
+        my $c = lc($p[0] // ''); $c =~ s/_//g;
+        if (@p % 2 == 0 && defined $c && exists $c{$c}) {
+            for (my $i = 0; $i < @p; $i+=2) {
+                my $c = lc($p[$i]); $c =~ s/_//g;
+                error(1, $p[$i], \%defaults) unless defined $c{$c} && exists $defaults{$c{$c}};
+                $named{$c} = $p[$i+1];
+            }
+        } else {
+            for (my $i = 0; $i < @p; $i++) {
+                my $c = lc($_[$i*2]); $c =~ s/_//g;
+                my $t = ref($defaults{$c{$c}});
+                if (!blessed($p[$i]) and (ref($p[$i]) ne $t)) {
+                    $t = $t eq '' ? 'SCALAR' : "a reference to $t";
+                    error("parameter '$p[$i]' is not $t as it should for parameter $c{$c}.");
+                }
+                $named{$c} = $p[$i]; # $p[$i] could be a sub ...
+            }
+        }
+    }
+    for my $k (keys %defaults) {
+        my $c = lc($k); $c =~ s/_//g;
+        $named{$c} //= $defaults{$k};
+    }
+    return \%named;
+}
+
+sub string2int {
+    my ($string, $string2int_hash, $int2string_hash, $default) = @_;
+    $string = $default if defined $default && !defined $string;
+    return unless defined $string;
+    return $string if $int2string_hash && exists $int2string_hash->{$string};
+    error(1, $string, $string2int_hash) unless exists $string2int_hash->{$string};
+    $string2int_hash->{$string};
+}
+
 sub RELEASE_PARENTS {
 }
 
+sub FindFile {
+    if (@_ == 1) {
+        _FindFile('', @_);
+    } else {
+        _FindFile(@_);
+    }
+}
+
 sub DataTypes {
     return @DATA_TYPES;
 }
 
-sub AccessTypes {
-    return @ACCESS_TYPES;
+sub OpenFlags {
+    return @DATA_TYPES;
 }
 
 sub ResamplingTypes {
@@ -281,16 +391,12 @@ sub Child {
 }
 
 sub GetDataTypeSize {
-    my $t = shift;
-    my $t2 = $t;
-    $t2 = $TYPE_STRING2INT{$t} if exists $TYPE_STRING2INT{$t};
-    confess "Unknown data type: '$t'." unless exists $TYPE_INT2STRING{$t2};
-    return _GetDataTypeSize($t2);
+    return _GetDataTypeSize(string2int(shift, \%TYPE_STRING2INT, \%TYPE_INT2STRING));
 }
 
 sub DataTypeValueRange {
     my $t = shift;
-    confess "Unknown data type: '$t'." unless exists $TYPE_STRING2INT{$t};
+    Geo::GDAL::error(1, $t, \%TYPE_STRING2INT) unless exists $TYPE_STRING2INT{$t};
     # these values are from gdalrasterband.cpp
     return (0,255) if $t =~ /Byte/;
     return (0,65535) if $t =~/UInt16/;
@@ -302,17 +408,13 @@ sub DataTypeValueRange {
 }
 
 sub DataTypeIsComplex {
-    my $t = shift;
-    my $t2 = $t;
-    $t2 = $TYPE_STRING2INT{$t} if exists $TYPE_STRING2INT{$t};
-    confess "Unknown data type: '$t'." unless exists $TYPE_INT2STRING{$t2};
-    return _DataTypeIsComplex($t2);
+    return _DataTypeIsComplex(string2int(shift, \%TYPE_STRING2INT));
 }
 
 sub PackCharacter {
     my $t = shift;
     $t = $TYPE_INT2STRING{$t} if exists $TYPE_INT2STRING{$t};
-    confess "Unknown data type: '$t'." unless exists $TYPE_STRING2INT{$t};
+    Geo::GDAL::error(1, $t, \%TYPE_STRING2INT) unless exists $TYPE_STRING2INT{$t};
     my $is_big_endian = unpack("h*", pack("s", 1)) =~ /01/; # from Programming Perl
     return 'C' if $t =~ /^Byte$/;
     return ($is_big_endian ? 'n': 'v') if $t =~ /^UInt16$/;
@@ -326,117 +428,100 @@ sub PackCharacter {
 sub GetDriverNames {
     my @names;
     for my $i (0..GetDriverCount()-1) {
-        my $driver = _GetDriver($i);
-        my $md = $driver->GetMetadata;
-        next unless $md->{DCAP_RASTER} and $md->{DCAP_RASTER} eq 'YES';
-        push @names, _GetDriver($i)->Name;
+        my $driver = GetDriver($i);
+        push @names, $driver->Name if $driver->TestCapability('RASTER');
     }
     return @names;
 }
+*DriverNames = *GetDriverNames;
 
 sub Drivers {
     my @drivers;
     for my $i (0..GetDriverCount()-1) {
-        my $driver = _GetDriver($i);
-        my $md = $driver->GetMetadata;
-        next unless $md->{DCAP_RASTER} and $md->{DCAP_RASTER} eq 'YES';
-        push @drivers, _GetDriver($i);
+        my $driver = GetDriver($i);
+        push @drivers, $driver if $driver->TestCapability('RASTER');
     }
     return @drivers;
 }
 
-sub GetDriver {
-    my($name) = @_;
-    $name = 0 unless defined $name;
-    my $driver;
-    $driver = _GetDriver($name) if $name =~ /^\d+$/; # is the name an index to driver list?
-    $driver = GetDriverByName("$name") unless $driver;
-    if ($driver) {
-        my $md = $driver->GetMetadata;
-        confess "Driver exists but does not have raster capabilities." 
-            unless $md->{DCAP_RASTER} and $md->{DCAP_RASTER} eq 'YES';
-        return $driver;
-    }
-    confess "Driver not found: '$name'. Maybe support for it was not built in?";
+sub Driver {
+    return 'Geo::GDAL::Driver' unless @_;
+    return GetDriver(@_);
+}
+
+sub AccessTypes {
+    return qw/ReadOnly Update/;
 }
-*Driver = *GetDriver;
 
 sub Open {
-    my @p = @_;
-    if (defined $p[1]) {
-        confess "Unknown access type: '$p[1]'." unless exists $Geo::GDAL::ACCESS_STRING2INT{$p[1]};
-        $p[1] = $Geo::GDAL::ACCESS_STRING2INT{$p[1]};
-    }
-    return _Open(@p);
+    my $p = Geo::GDAL::named_parameters(\@_, Name => '.', Access => 'ReadOnly', Type => 'Any', Options => {}, Files => []);
+    my @flags;
+    my %o = (READONLY => 1, UPDATE => 1);
+    Geo::GDAL::error(1, $p->{access}, \%o) unless $o{uc($p->{access})};
+    push @flags, uc($p->{access});
+    %o = (RASTER => 1, VECTOR => 1, ANY => 1);
+    Geo::GDAL::error(1, $p->{type}, \%o) unless $o{uc($p->{type})};
+    push @flags, uc($p->{type}) unless uc($p->{type}) eq 'ANY';
+    my $dataset = OpenEx(Name => $p->{name}, Flags => \@flags, Options => $p->{options}, Files => $p->{files});
+    unless ($dataset) {
+        my $t = "Failed to open $p->{name}.";
+        $t .= " Is it a ".lc($p->{type})." dataset?" unless uc($p->{type}) eq 'ANY';
+        error($t);
+    }
+    return $dataset;
 }
 
 sub OpenShared {
-    my @p = @_;
-    if (defined $p[1]) {
-        confess "Unknown access type: '$p[1]'." unless exists $Geo::GDAL::ACCESS_STRING2INT{$p[1]};
-        $p[1] = $Geo::GDAL::ACCESS_STRING2INT{$p[1]};
+    my @p = @_; # name, update
+    my @flags = qw/RASTER SHARED/;
+    $p[1] //= 'ReadOnly';
+    Geo::GDAL::error(1, $p[1], {ReadOnly => 1, Update => 1}) unless ($p[1] eq 'ReadOnly' or $p[1] eq 'Update');
+    push @flags, qw/READONLY/ if $p[1] eq 'ReadOnly';
+    push @flags, qw/UPDATE/ if $p[1] eq 'Update';
+    my $dataset = OpenEx($p[0], \@flags);
+    error("Failed to open $p[0]. Is it a raster dataset?") unless $dataset;
+    return $dataset;
+}
+
+sub OpenEx {
+    my $p = Geo::GDAL::named_parameters(\@_, Name => '.', Flags => [], Drivers => [], Options => {}, Files => []);
+    unless ($p) {
+        my $name = shift // '';
+        my @flags = @_;
+        $p = {name => $name, flags => \@flags, drivers => [], options => {}, files => []};
+    }
+    if ($p->{flags}) {
+        my $f = 0;
+        for my $flag (@{$p->{flags}}) {
+            Geo::GDAL::error(1, $flag, \%OF_STRING2INT) unless exists $OF_STRING2INT{$flag};
+            $f |= $Geo::GDAL::OF_STRING2INT{$flag};
+        }
+        $p->{flags} = $f;
     }
-    return _OpenShared(@p);
-}
-
-sub ComputeMedianCutPCT {
-    my @p = @_;
-    $p[6] = 1 if $p[5] and not defined $p[6];
-    _ComputeMedianCutPCT(@p);
-}
-
-sub DitherRGB2PCT {
-    my @p = @_;
-    $p[6] = 1 if $p[5] and not defined $p[6];
-    _DitherRGB2PCT(@p);
-}
-
-sub ComputeProximity {
-    my @p = @_;
-    $p[4] = 1 if $p[3] and not defined $p[4];
-    _ComputeProximity(@p);
-}
-
-sub RasterizeLayer {
-    my @p = @_;
-    $p[8] = 1 if $p[7] and not defined $p[8];
-    _RasterizeLayer(@p);
+    return _OpenEx($p->{name}, $p->{flags}, $p->{drivers}, $p->{options}, $p->{files});
 }
 
 sub Polygonize {
     my @params = @_;
-    $params[6] = 1 if $params[5] and not defined $params[6];
     $params[3] = $params[2]->GetLayerDefn->GetFieldIndex($params[3]) unless $params[3] =~ /^\d/;
     _Polygonize(@params);
 }
 
-sub SieveFilter {
-    my @p = @_;
-    $p[7] = 1 if $p[6] and not defined $p[7];
-    _SieveFilter(@p);
-}
-
 sub RegenerateOverviews {
     my @p = @_;
     $p[2] = uc($p[2]) if $p[2]; # see overview.cpp:2030
-    $p[4] = 1 if $p[3] and not defined $p[4];
     _RegenerateOverviews(@p);
 }
 
 sub RegenerateOverview {
     my @p = @_;
     $p[2] = uc($p[2]) if $p[2]; # see overview.cpp:2030
-    $p[4] = 1 if $p[3] and not defined $p[4];
     _RegenerateOverview(@p);
 }
 
 sub ReprojectImage {
     my @p = @_;
-    $p[8] = 1 if $p[7] and not defined $p[8];
-    if (defined $p[4]) {
-        confess "Unknown data type: '$p[4]'." unless exists $Geo::GDAL::RESAMPLING_STRING2INT{$p[4]};
-        $p[4] = $Geo::GDAL::RESAMPLING_STRING2INT{$p[4]};
-    }
+    $p[4] = string2int($p[4], \%RESAMPLING_STRING2INT);
     return _ReprojectImage(@p);
 }
 
@@ -447,13 +532,24 @@ sub AutoCreateWarpedVRT {
             $p[$i] = $p[$i]->ExportToWkt;
         }
     }
-    if (defined $p[3]) {
-        confess "Unknown data type: '$p[3]'." unless exists $Geo::GDAL::RESAMPLING_STRING2INT{$p[3]};
-        $p[3] = $Geo::GDAL::RESAMPLING_STRING2INT{$p[3]};
-    }
+    $p[3] = string2int($p[3], \%RESAMPLING_STRING2INT, undef, 'NearestNeighbour');
     return _AutoCreateWarpedVRT(@p);
 }
 
+sub make_processing_options {
+    my ($o) = @_;
+    if (ref $o eq 'HASH') {
+        for my $key (keys %$o) {
+            unless ($key =~ /^-/) {
+                $o->{'-'.$key} = $o->{$key};
+                delete $o->{$key};
+            }
+        }
+        $o = [%$o];
+    }
+    return $o;
+}
+
 
 
 
@@ -473,20 +569,22 @@ sub Description {
 }
 
 sub Metadata {
-    my $self = shift;
-    my $metadata;
-    $metadata = shift if ref $_[0];
-    my $domain = shift;
-    $domain = '' unless defined $domain;
+    my $self = shift,
+    my $metadata = ref $_[0] ? shift : undef;
+    my $domain = shift // '';
     SetMetadata($self, $metadata, $domain) if defined $metadata;
     GetMetadata($self, $domain) if defined wantarray;
 }
 
 
+
+
 package Geo::GDAL::Driver;
 use strict;
 use warnings;
 use Carp;
+use Scalar::Util 'blessed';
+
 use vars qw/@CAPABILITIES @DOMAINS/;
 for (keys %Geo::GDAL::Const::) {
     next if /TypeCount/;
@@ -564,36 +662,64 @@ sub CreationDataTypes {
     return split /\s+/, $h->{DMD_CREATIONDATATYPES} if $h->{DMD_CREATIONDATATYPES};
 }
 
-sub Create {
-    my $self = shift;
-    my %defaults = ( Name => 'unnamed',
-                     Width => 256,
-                     Height => 256,
-                     Bands => 1,
-                     Type => 'Byte',
-                     Options => {} );
-    my %params;
-    if (@_ == 0) {
-    } elsif (ref($_[0]) eq 'HASH') {
-        %params = %{$_[0]};
-    } elsif (exists $defaults{$_[0]} and @_ % 2 == 0) {
-        %params = @_;
-    } else {
-        ($params{Name}, $params{Width}, $params{Height}, $params{Bands}, $params{Type}, $params{Options}) = @_;
-    }
-    for my $k (keys %params) {
-        carp "Create: unrecognized named parameter '$k'." unless exists $defaults{$k};
+sub stdout_redirection_wrapper {
+    my ($self, $name, $sub, @params) = @_;
+    my $object = 0;
+    if ($name && blessed $name) {
+        $object = $name;
+        my $ref = $object->can('write');
+        Geo::GDAL::VSIStdoutSetRedirection($ref);
+        $name = '/vsistdout/';
     }
-    for my $k (keys %defaults) {
-        $params{$k} = $defaults{$k} unless defined $params{$k};
+    my $ds;
+    eval {
+        $ds = $sub->($self, $name, @params);
+    };
+    if ($object) {
+        if ($ds) {
+            $Geo::GDAL::stdout_redirection{tied(%$ds)} = $object;
+        } else {
+            Geo::GDAL::VSIStdoutUnsetRedirection();
+            $object->close;
+        }
     }
-    my $type;
-    confess "Unknown data type: '$params{Type}'." unless exists $Geo::GDAL::TYPE_STRING2INT{$params{Type}};
-    $type = $Geo::GDAL::TYPE_STRING2INT{$params{Type}};
-    return $self->_Create($params{Name}, $params{Width}, $params{Height}, $params{Bands}, $type, $params{Options});
+    confess(Geo::GDAL->last_error) if $@;
+    confess("Failed. Use Geo::OGR::Driver for vector drivers.") unless $ds;
+    return $ds;
+}
+
+sub Create {
+    my $self = shift;
+    my $p = Geo::GDAL::named_parameters(\@_, Name => 'unnamed', Width => 256, Height => 256, Bands => 1, Type => 'Byte', Options => {});
+    my $type = Geo::GDAL::string2int($p->{type}, \%Geo::GDAL::TYPE_STRING2INT);
+    return $self->stdout_redirection_wrapper(
+        $p->{name},
+        $self->can('_Create'),
+        $p->{width}, $p->{height}, $p->{bands}, $type, $p->{options}
+    );
 }
 *CreateDataset = *Create;
-*Copy = *CreateCopy;
+
+sub Copy {
+    my $self = shift;
+    my $p = Geo::GDAL::named_parameters(\@_, Name => 'unnamed', Src => undef, Strict => 1, Options => {}, Progress => undef, ProgressData => undef);
+    return $self->stdout_redirection_wrapper(
+        $p->{name},
+        $self->can('_CreateCopy'),
+        $p->{src}, $p->{strict}, $p->{options}, $p->{progress}, $p->{progressdata});
+}
+*CreateCopy = *Copy;
+
+sub Open {
+    my $self = shift;
+    my @p = @_; # name, update
+    my @flags = qw/RASTER/;
+    push @flags, qw/READONLY/ if $p[1] eq 'ReadOnly';
+    push @flags, qw/UPDATE/ if $p[1] eq 'Update';
+    my $dataset = Geo::GDAL::OpenEx($p[0], \@flags, [$self->Name()]);
+    Geo::GDAL::error("Failed to open $p[0]. Is it a raster dataset?") unless $dataset;
+    return $dataset;
+}
 
 
 
@@ -601,21 +727,34 @@ sub Create {
 package Geo::GDAL::Dataset;
 use strict;
 use warnings;
+use POSIX qw/floor ceil/;
+use Scalar::Util 'blessed';
 use Carp;
-use vars qw/%BANDS @DOMAINS/;
+use Exporter 'import';
+
+use vars qw/@EXPORT @DOMAINS @CAPABILITIES %CAPABILITIES %BANDS %LAYERS %RESULT_SET/;
+ at EXPORT = qw/BuildVRT/;
 @DOMAINS = qw/IMAGE_STRUCTURE SUBDATASETS GEOLOCATION/;
 
+sub RELEASE_PARENTS {
+    my $self = shift;
+    delete $BANDS{$self};
+}
+
+sub Dataset {
+    my $self = shift;
+    return $BANDS{tied(%$self)};
+}
+
 sub Domains {
     return @DOMAINS;
 }
-*GetDriver = *_GetDriver;
 
-sub Open {
-    return Geo::GDAL::Open(@_);
-}
+*Open = *Geo::GDAL::Open;
+*OpenShared = *Geo::GDAL::OpenShared;
 
-sub OpenShared {
-    return Geo::GDAL::OpenShared(@_);
+sub TestCapability {
+    return _TestCapability(@_);
 }
 
 sub Size {
@@ -633,21 +772,104 @@ sub Bands {
 }
 
 sub GetRasterBand {
-    my($self, $index) = @_;
-    $index = 1 unless defined $index;
+    my ($self, $index) = @_;
+    $index //= 1;
     my $band = _GetRasterBand($self, $index);
+    Geo::GDAL::error(2, $index, 'Band') unless $band;
     $BANDS{tied(%{$band})} = $self;
     return $band;
 }
 *Band = *GetRasterBand;
 
 sub AddBand {
-    my @p = @_;
-    if (defined $p[1]) {
-        confess "Unknown data type: '$p[1]'." unless exists $Geo::GDAL::TYPE_STRING2INT{$p[1]};
-        $p[1] = $Geo::GDAL::TYPE_STRING2INT{$p[1]};
+    my ($self, $type, $options) = @_;
+    $type //= 'Byte';
+    $type = Geo::GDAL::string2int($type, \%Geo::GDAL::TYPE_STRING2INT);
+    $self->_AddBand($type, $options);
+    return unless defined wantarray;
+    return $self->GetRasterBand($self->{RasterCount});
+}
+
+sub CreateMaskBand {
+    return _CreateMaskBand(@_);
+}
+
+sub ExecuteSQL {
+    my $self = shift;
+    my $layer = $self->_ExecuteSQL(@_);
+    $LAYERS{tied(%$layer)} = $self;
+    $RESULT_SET{tied(%$layer)} = 1;
+    return $layer;
+}
+
+sub ReleaseResultSet {
+    # a no-op, _ReleaseResultSet is called from Layer::DESTROY
+}
+
+sub GetLayer {
+    my($self, $name) = @_;
+    my $layer = defined $name ? GetLayerByName($self, "$name") : GetLayerByIndex($self, 0);
+    $name //= '';
+    Geo::GDAL::error(2, $name, 'Layer') unless $layer;
+    $LAYERS{tied(%$layer)} = $self;
+    return $layer;
+}
+*Layer = *GetLayer;
+
+sub GetLayerNames {
+    my $self = shift;
+    my @names;
+    for my $i (0..$self->GetLayerCount-1) {
+        my $layer = GetLayerByIndex($self, $i);
+        push @names, $layer->GetName;
     }
-    return _AddBand(@p);
+    return @names;
+}
+*Layers = *GetLayerNames;
+
+sub CreateLayer {
+    my $self = shift;
+    my $p = Geo::GDAL::named_parameters(\@_,
+                                        Name => 'unnamed',
+                                        SRS => undef,
+                                        GeometryType => 'Unknown',
+                                        Options => {},
+                                        Schema => undef,
+                                        Fields => undef,
+                                        ApproxOK => 1);
+    Geo::GDAL::error("The 'Fields' argument must be an array reference.") if $p->{fields} && ref($p->{fields}) ne 'ARRAY';
+    if (defined $p->{schema}) {
+        my $s = $p->{schema};
+        $p->{geometrytype} = $s->{GeometryType} if exists $s->{GeometryType};
+        $p->{fields} = $s->{Fields} if exists $s->{Fields};
+        $p->{name} = $s->{Name} if exists $s->{Name};
+    }
+    $p->{fields} = [] unless ref($p->{fields}) eq 'ARRAY';
+    # if fields contains spatial fields, then do not create default one
+    for my $f (@{$p->{fields}}) {
+        if ($f->{GeometryType} or exists $Geo::OGR::Geometry::TYPE_STRING2INT{$f->{Type}}) {
+            $p->{geometrytype} = 'None';
+            last;
+        }
+    }
+    my $gt = Geo::GDAL::string2int($p->{geometrytype}, \%Geo::OGR::Geometry::TYPE_STRING2INT);
+    my $layer = _CreateLayer($self, $p->{name}, $p->{srs}, $gt, $p->{options});
+    $LAYERS{tied(%$layer)} = $self;
+    for my $f (@{$p->{fields}}) {
+        $layer->CreateField($f);
+    }
+    return $layer;
+}
+
+sub DeleteLayer {
+    my ($self, $name) = @_;
+    my $index;
+    for my $i (0..$self->GetLayerCount-1) {
+        my $layer = GetLayerByIndex($self, $i);
+        $index = $i, last if $layer->GetName eq $name;
+    }
+    Geo::GDAL::error(2, $name, 'Layer') unless defined $index;
+    _DeleteLayer($self, $index);
 }
 
 sub Projection {
@@ -659,7 +881,11 @@ sub Projection {
 sub SpatialReference {
     my($self, $sr) = @_;
     SetProjection($self, $sr->As('WKT')) if defined $sr;
-    return Geo::OSR::SpatialReference->new(GetProjection($self)) if defined wantarray;
+    if (defined wantarray) {
+        my $p = GetProjection($self);
+        return unless $p;
+        return Geo::OSR::SpatialReference->new(WKT => $p);
+    }
 }
 
 sub GeoTransform {
@@ -671,7 +897,7 @@ sub GeoTransform {
             SetGeoTransform($self, \@_);
         }
     };
-    confess $@ if $@;
+    confess(Geo::GDAL->last_error) if $@;
     return unless defined wantarray;
     my $t = GetGeoTransform($self);
     if (wantarray) {
@@ -681,6 +907,30 @@ sub GeoTransform {
     }
 }
 
+sub Extent {
+    my $self = shift;
+    return $self->GeoTransform->Extent($self->Size);
+}
+
+sub Tile { # $xoff, $yoff, $xsize, $ysize, assuming strict north up
+    my ($self, $e) = @_;
+    my ($w, $h) = $self->Size;
+    #print "sz $w $h\n";
+    my $gt = $self->GeoTransform;
+    #print "gt @$gt\n";
+    confess "GeoTransform is not \"north up\"." unless $gt->NorthUp;
+    my $x = $gt->Extent($w, $h);
+    my $xoff = floor(($e->[0] - $gt->[0])/$gt->[1]);
+    $xoff = 0 if $xoff < 0;
+    my $yoff = floor(($gt->[3] - $e->[3])/(-$gt->[5]));
+    $yoff = 0 if $yoff < 0;
+    my $xsize = ceil(($e->[2] - $gt->[0])/$gt->[1]) - $xoff;
+    $xsize = $w - $xoff if $xsize > $w - $xoff;
+    my $ysize = ceil(($gt->[3] - $e->[1])/(-$gt->[5])) - $yoff;
+    $ysize = $h - $yoff if $ysize > $h - $yoff;
+    return ($xoff, $yoff, $xsize, $ysize);
+}
+
 sub GCPs {
     my $self = shift;
     if (@_ > 0) {
@@ -694,107 +944,69 @@ sub GCPs {
     return (@$GCPs, $proj);
 }
 
+sub ReadTile {
+    my ($self, $xoff, $yoff, $xsize, $ysize, $w_tile, $h_tile, $alg) = @_;
+    my @data;
+    for my $i (0..$self->Bands-1) {
+        $data[$i] = $self->Band($i+1)->ReadTile($xoff, $yoff, $xsize, $ysize, $w_tile, $h_tile, $alg);
+    }
+    return \@data;
+}
+
+sub WriteTile {
+    my ($self, $data, $xoff, $yoff) = @_;
+    $xoff //= 0;
+    $yoff //= 0;
+    for my $i (0..$self->Bands-1) {
+        $self->Band($i+1)->WriteTile($data->[$i], $xoff, $yoff);
+    }
+}
+
 sub ReadRaster {
     my $self = shift;
     my ($width, $height) = $self->Size;
     my ($type) = $self->Band->DataType;
-    my %d = (
-        XOFF => 0,
-        YOFF => 0,
-        XSIZE => $width,
-        YSIZE => $height,
-        BUFXSIZE => undef,
-        BUFYSIZE => undef,
-        BUFTYPE => $type,
-        BANDLIST => [1],
-        BUFPIXELSPACE => 0,
-        BUFLINESPACE => 0,
-        BUFBANDSPACE => 0,
-        RESAMPLEALG => 'NearestNeighbour',
-        PROGRESS => undef,
-        PROGRESSDATA => undef
+    my $p = Geo::GDAL::named_parameters(\@_,
+                                        XOff => 0,
+                                        YOff => 0,
+                                        XSize => $width,
+                                        YSize => $height,
+                                        BufXSize => undef,
+                                        BufYSize => undef,
+                                        BufType => $type,
+                                        BandList => [1],
+                                        BufPixelSpace => 0,
+                                        BufLineSpace => 0,
+                                        BufBandSpace => 0,
+                                        ResampleAlg => 'NearestNeighbour',
+                                        Progress => undef,
+                                        ProgressData => undef
         );
-    my %p;
-    my $t;
-    if (defined $_[0]) {
-        $t = uc($_[0]); 
-        $t =~ s/_//g;
-    }
-    if (@_ == 0) {
-    } elsif (ref($_[0]) eq 'HASH') {
-        %p = %{$_[0]};
-    } elsif (@_ % 2 == 0 and (defined $t and exists $d{$t})) {
-        %p = @_;
-    } else {
-        ($p{xoff},$p{yoff},$p{xsize},$p{ysize},$p{buf_xsize},$p{buf_ysize},$p{buf_type},$p{band_list},$p{buf_pixel_space},$p{buf_line_space},$p{buf_band_space},$p{resample_alg},$p{progress},$p{progress_data}) = @_;
-    }
-    for (keys %p) {
-        my $u = uc($_);
-        $u =~ s/_//g;
-        carp "Unknown named parameter '$_'." unless exists $d{$u};
-        $p{$u} = $p{$_};
-    }
-    for (keys %d) {
-        $p{$_} = $d{$_} unless defined $p{$_};
-    }
-    confess "Unknown resampling algorithm: '$p{RESAMPLEALG}'." 
-        unless exists $Geo::GDAL::RIO_RESAMPLING_STRING2INT{$p{RESAMPLEALG}};
-    $p{RESAMPLEALG} = $Geo::GDAL::RIO_RESAMPLING_STRING2INT{$p{RESAMPLEALG}};
-    unless ($Geo::GDAL::TYPE_INT2STRING{$p{BUFTYPE}}) {
-        confess "Unknown data type: '$p{BUFTYPE}'." 
-            unless exists $Geo::GDAL::TYPE_STRING2INT{$p{BUFTYPE}};
-        $p{BUFTYPE} = $Geo::GDAL::TYPE_STRING2INT{$p{BUFTYPE}};
-    }
-    $self->_ReadRaster($p{XOFF},$p{YOFF},$p{XSIZE},$p{YSIZE},$p{BUFXSIZE},$p{BUFYSIZE},$p{BUFTYPE},$p{BANDLIST},$p{BUFPIXELSPACE},$p{BUFLINESPACE},$p{BUFBANDSPACE},$p{RESAMPLEALG},$p{PROGRESS},$p{PROGRESSDATA});
+    $p->{resamplealg} = Geo::GDAL::string2int($p->{resamplealg}, \%Geo::GDAL::RIO_RESAMPLING_STRING2INT);
+    $p->{buftype} = Geo::GDAL::string2int($p->{buftype}, \%Geo::GDAL::TYPE_STRING2INT, \%Geo::GDAL::TYPE_INT2STRING);
+    $self->_ReadRaster($p->{xoff},$p->{yoff},$p->{xsize},$p->{ysize},$p->{bufxsize},$p->{bufysize},$p->{buftype},$p->{bandlist},$p->{bufpixelspace},$p->{buflinespace},$p->{bufbandspace},$p->{resamplealg},$p->{progress},$p->{progressdata});
 }
 
 sub WriteRaster {
     my $self = shift;
     my ($width, $height) = $self->Size;
     my ($type) = $self->Band->DataType;
-    my %d = (
-        XOFF => 0,
-        YOFF => 0,
-        XSIZE => $width,
-        YSIZE => $height,
-        BUF => undef,
-        BUFXSIZE => undef,
-        BUFYSIZE => undef,
-        BUFTYPE => $type,
-        BANDLIST => [1],
-        BUFPIXELSPACE => 0,
-        BUFLINESPACE => 0,
-        BUFBANDSPACE => 0
+    my $p = Geo::GDAL::named_parameters(\@_,
+                                        XOff => 0,
+                                        YOff => 0,
+                                        XSize => $width,
+                                        YSize => $height,
+                                        Buf => undef,
+                                        BufXSize => undef,
+                                        BufYSize => undef,
+                                        BufType => $type,
+                                        BandList => [1],
+                                        BufPixelSpace => 0,
+                                        BufLineSpace => 0,
+                                        BufBandSpace => 0
         );
-    my %p;
-    my $t;
-    if (defined $_[0]) {
-        $t = uc($_[0]); 
-        $t =~ s/_//g;
-    }
-    if (@_ == 0) {
-    } elsif (ref($_[0]) eq 'HASH') {
-        %p = %{$_[0]};
-    } elsif (@_ % 2 == 0 and (defined $t and exists $d{$t})) {
-        %p = @_;
-    } else {
-        ($p{xoff},$p{yoff},$p{xsize},$p{ysize},$p{buf},$p{buf_xsize},$p{buf_ysize},$p{buf_type},$p{band_list},$p{buf_pixel_space},$p{buf_line_space},$p{buf_band_space}) = @_;
-    }
-    for (keys %p) {
-        my $u = uc($_);
-        $u =~ s/_//g;
-        carp "Unknown named parameter '$_'." unless exists $d{$u};
-        $p{$u} = $p{$_};
-    }
-    for (keys %d) {
-        $p{$_} = $d{$_} unless defined $p{$_};
-    }
-    unless ($Geo::GDAL::TYPE_INT2STRING{$p{BUFTYPE}}) {
-        confess "Unknown data type: '$p{BUFTYPE}'." 
-            unless exists $Geo::GDAL::TYPE_STRING2INT{$p{BUFTYPE}};
-        $p{BUFTYPE} = $Geo::GDAL::TYPE_STRING2INT{$p{BUFTYPE}};
-    }
-    $self->_WriteRaster($p{XOFF},$p{YOFF},$p{XSIZE},$p{YSIZE},$p{BUF},$p{BUFXSIZE},$p{BUFYSIZE},$p{BUFTYPE},$p{BANDLIST},$p{BUFPIXELSPACE},$p{BUFLINESPACE},$p{BUFBANDSPACE});
+    $p->{buftype} = Geo::GDAL::string2int($p->{buftype}, \%Geo::GDAL::TYPE_STRING2INT, \%Geo::GDAL::TYPE_INT2STRING);
+    $self->_WriteRaster($p->{xoff},$p->{yoff},$p->{xsize},$p->{ysize},$p->{buf},$p->{bufxsize},$p->{bufysize},$p->{buftype},$p->{bandlist},$p->{bufpixelspace},$p->{buflinespace},$p->{bufbandspace});
 }
 
 sub BuildOverviews {
@@ -804,7 +1016,228 @@ sub BuildOverviews {
     eval {
         $self->_BuildOverviews(@p);
     };
-    confess $@ if $@;
+    confess(Geo::GDAL->last_error) if $@;
+}
+
+sub stdout_redirection_wrapper {
+    my ($self, $name, $sub, @params) = @_;
+    my $object = 0;
+    if ($name && blessed $name) {
+        $object = $name;
+        my $ref = $object->can('write');
+        Geo::GDAL::VSIStdoutSetRedirection($ref);
+        $name = '/vsistdout/';
+    }
+    my $ds;
+    eval {
+        $ds = $sub->($name, $self, @params); # self and name opposite to what is in Geo::GDAL::Driver!
+    };
+    if ($object) {
+        if ($ds) {
+            $Geo::GDAL::stdout_redirection{tied(%$ds)} = $object;
+        } else {
+            Geo::GDAL::VSIStdoutUnsetRedirection();
+            $object->close;
+        }
+    }
+    confess(Geo::GDAL->last_error) if $@;
+    return $ds;
+}
+
+sub DEMProcessing {
+    my ($self, $dest, $Processing, $ColorFilename, $options, $progress, $progress_data) = @_;
+    $options = Geo::GDAL::GDALDEMProcessingOptions->new(Geo::GDAL::make_processing_options($options));
+    return $self->stdout_redirection_wrapper(
+        $dest,
+        \&Geo::GDAL::wrapper_GDALDEMProcessing,
+        $Processing, $ColorFilename, $options, $progress, $progress_data
+    );
+}
+
+sub Nearblack {
+    my ($self, $dest, $options, $progress, $progress_data) = @_;
+    $options = Geo::GDAL::GDALNearblackOptions->new(Geo::GDAL::make_processing_options($options));
+    my $b = blessed($dest);
+    if ($b && $b eq 'Geo::GDAL::Dataset') {
+        Geo::GDAL::wrapper_GDALNearblackDestDS($dest, $self, $options, $progress, $progress_data);
+    } else {
+        return $self->stdout_redirection_wrapper(
+            $dest,
+            \&Geo::GDAL::wrapper_GDALNearblackDestName,
+            $options, $progress, $progress_data
+        );
+    }
+}
+
+sub Translate {
+    my ($self, $dest, $options, $progress, $progress_data) = @_;
+    return $self->stdout_redirection_wrapper(
+        $dest,
+        sub {
+            my ($dest, $self) = @_;
+            my $ds;
+            if ($self->_GetRasterBand(1)) {
+                $options = Geo::GDAL::GDALTranslateOptions->new(Geo::GDAL::make_processing_options($options));
+                $ds = Geo::GDAL::wrapper_GDALTranslate($dest, $self, $options, $progress, $progress_data);
+            } else {
+                $options = Geo::GDAL::GDALVectorTranslateOptions->new(Geo::GDAL::make_processing_options($options));
+                Geo::GDAL::wrapper_GDALVectorTranslateDestDS($dest, $self, $options, $progress, $progress_data);
+                $ds = Geo::GDAL::wrapper_GDALVectorTranslateDestName($dest, $self, $options, $progress, $progress_data);
+            }
+            return $ds;
+        }
+    );
+}
+
+sub Warped {
+    my $self = shift;
+    my $p = Geo::GDAL::named_parameters(\@_, SrcSRS => undef, DstSRS => undef, ResampleAlg => 'NearestNeighbour', MaxError => 0);
+    for my $srs (qw/srcsrs dstsrs/) {
+        $p->{$srs} = $p->{$srs}->ExportToWkt if $p->{$srs} && blessed $p->{$srs};
+    }
+    $p->{resamplealg} = Geo::GDAL::string2int($p->{resamplealg}, \%Geo::GDAL::RESAMPLING_STRING2INT);
+    my $warped = Geo::GDAL::_AutoCreateWarpedVRT($self, $p->{srcsrs}, $p->{dstsrs}, $p->{resamplealg}, $p->{maxerror});
+    $BANDS{tied(%{$warped})} = $self if $warped; # self must live as long as warped
+    return $warped;
+}
+
+sub Warp {
+    my ($self, $dest, $options, $progress, $progress_data) = @_;
+    $options = Geo::GDAL::GDALWarpAppOptions->new(Geo::GDAL::make_processing_options($options));
+    my $b = blessed($dest);
+    if ($b && $b eq 'Geo::GDAL::Dataset') {
+        Geo::GDAL::wrapper_GDALWarpDestDS($dest, $self, $options, $progress, $progress_data);
+    } else {
+        return $self->stdout_redirection_wrapper(
+            $dest,
+            \&Geo::GDAL::wrapper_GDALWarpDestName,
+            $options, $progress, $progress_data
+        );
+    }
+}
+
+sub Info {
+    my ($self, $o) = @_;
+    $o = Geo::GDAL::GDALInfoOptions->new(Geo::GDAL::make_processing_options($o));
+    return Geo::GDAL::GDALInfo($self, $o);
+}
+
+sub Grid {
+    my ($self, $dest, $options, $progress, $progress_data) = @_;
+    $options = Geo::GDAL::GDALGridOptions->new(Geo::GDAL::make_processing_options($options));
+    return $self->stdout_redirection_wrapper(
+        $dest,
+        \&Geo::GDAL::wrapper_GDALGrid,
+        $options, $progress, $progress_data
+    );
+}
+
+sub Rasterize {
+    my ($self, $dest, $options, $progress, $progress_data) = @_;
+    $options = Geo::GDAL::GDALRasterizeOptions->new(Geo::GDAL::make_processing_options($options));
+    my $b = blessed($dest);
+    if ($b && $b eq 'Geo::GDAL::Dataset') {
+        Geo::GDAL::wrapper_GDALRasterizeDestDS($dest, $self, $options, $progress, $progress_data);
+    } else {
+        return $self->stdout_redirection_wrapper(
+            $dest,
+            \&Geo::GDAL::wrapper_GDALRasterizeDestName,
+            $options, $progress, $progress_data
+        );
+    }
+}
+
+sub BuildVRT {
+    my ($dest, $sources, $options, $progress, $progress_data) = @_;
+    $options = Geo::GDAL::GDALBuildVRTOptions->new(Geo::GDAL::make_processing_options($options));
+    Geo::GDAL::error("Usage: Geo::GDAL::DataSet::BuildVRT(\$vrt_file_name, \\\@sources)")
+        unless ref $sources eq 'ARRAY' && defined $sources->[0];
+    unless (blessed($dest)) {
+        if (blessed($sources->[0])) {
+            return Geo::GDAL::wrapper_GDALBuildVRT_objects($dest, $sources, $options, $progress, $progress_data);
+        } else {
+            return Geo::GDAL::wrapper_GDALBuildVRT_names($dest, $sources, $options, $progress, $progress_data);
+        }
+    } else {
+        if (blessed($sources->[0])) {
+            return stdout_redirection_wrapper(
+                $sources, $dest,
+                \&Geo::GDAL::wrapper_GDALBuildVRT_objects,
+                $options, $progress, $progress_data);
+        } else {
+            return stdout_redirection_wrapper(
+                $sources, $dest,
+                \&Geo::GDAL::wrapper_GDALBuildVRT_names,
+                $options, $progress, $progress_data);
+        }
+    }
+}
+
+sub ComputeColorTable {
+    my $self = shift;
+    my $p = Geo::GDAL::named_parameters(\@_,
+                                        Red => undef,
+                                        Green => undef,
+                                        Blue => undef,
+                                        NumColors => 256,
+                                        Progress => undef,
+                                        ProgressData => undef,
+                                        Method => 'MedianCut');
+    for my $b ($self->Bands) {
+        for my $cion ($b->ColorInterpretation) {
+            if ($cion eq 'RedBand') { $p->{red} //= $b; last; }
+            if ($cion eq 'GreenBand') { $p->{green} //= $b; last; }
+            if ($cion eq 'BlueBand') { $p->{blue} //= $b; last; }
+        }
+    }
+    my $ct = Geo::GDAL::ColorTable->new;
+    Geo::GDAL::ComputeMedianCutPCT($p->{red},
+                                   $p->{green},
+                                   $p->{blue},
+                                   $p->{numcolors},
+                                   $ct, $p->{progress},
+                                   $p->{progressdata});
+    return $ct;
+}
+
+sub Dither {
+    my $self = shift;
+    my $p = Geo::GDAL::named_parameters(\@_,
+                                        Red => undef,
+                                        Green => undef,
+                                        Blue => undef,
+                                        Dest => undef,
+                                        ColorTable => undef,
+                                        Progress => undef,
+                                        ProgressData => undef);
+    for my $b ($self->Bands) {
+        for my $cion ($b->ColorInterpretation) {
+            if ($cion eq 'RedBand') { $p->{red} //= $b; last; }
+            if ($cion eq 'GreenBand') { $p->{green} //= $b; last; }
+            if ($cion eq 'BlueBand') { $p->{blue} //= $b; last; }
+        }
+    }
+    my ($w, $h) = $self->Size;
+    $p->{dest} //= Geo::GDAL::Driver('MEM')->Create(Name => 'dithered',
+                                                    Width => $w,
+                                                    Height => $h,
+                                                    Type => 'Byte')->Band;
+    $p->{colortable}
+        //= $p->{dest}->ColorTable
+            // $self->ComputeColorTable(Red => $p->{red},
+                                        Green => $p->{green},
+                                        Blue => $p->{blue},
+                                        Progress => $p->{progress},
+                                        ProgressData => $p->{progressdata});
+    Geo::GDAL::DitherRGB2PCT($p->{red},
+                             $p->{green},
+                             $p->{blue},
+                             $p->{dest},
+                             $p->{colortable},
+                             $p->{progress},
+                             $p->{progressdata});
+    $p->{dest}->ColorTable($p->{colortable});
+    return $p->{dest};
 }
 
 
@@ -816,7 +1249,8 @@ use warnings;
 use POSIX;
 use Carp;
 use Scalar::Util 'blessed';
-use vars qw/
+
+use vars qw/ %RATS
     @COLOR_INTERPRETATIONS
     %COLOR_INTERPRETATION_STRING2INT %COLOR_INTERPRETATION_INT2STRING @DOMAINS
     %MASK_FLAGS
@@ -847,12 +1281,10 @@ sub MaskFlags {
 }
 
 sub DESTROY {
-    my $self;
-    if ($_[0]->isa('SCALAR')) {
-        $self = $_[0];
-    } else {
-        return unless $_[0]->isa('HASH');
-        $self = tied(%{$_[0]});
+    my $self = shift;
+    unless ($self->isa('SCALAR')) {
+        return unless $self->isa('HASH');
+        $self = tied(%{$self});
         return unless defined $self;
     }
     delete $ITERATORS{$self};
@@ -867,6 +1299,11 @@ sub RELEASE_PARENTS {
     delete $Geo::GDAL::Dataset::BANDS{$self};
 }
 
+sub Dataset {
+    my $self = shift;
+    return $Geo::GDAL::Dataset::BANDS{tied(%{$self})};
+}
+
 sub Size {
     my $self = shift;
     return ($self->{XSize}, $self->{YSize});
@@ -898,7 +1335,7 @@ sub Unit {
     my $self = shift;
     if (@_ > 0) {
         my $unit = shift;
-        $unit = '' unless defined $unit;
+        $unit //= '';
         SetUnitType($self, $unit);
     }
     return unless defined wantarray;
@@ -916,19 +1353,23 @@ sub ScaleAndOffset {
 }
 
 sub ReadTile {
-    my($self, $xoff, $yoff, $xsize, $ysize) = @_;
-    $xoff = 0 unless defined $xoff;
-    $yoff = 0 unless defined $yoff;
-    $xsize = $self->{XSize} - $xoff unless defined $xsize;
-    $ysize = $self->{YSize} - $yoff unless defined $ysize;
-    my $buf = $self->ReadRaster($xoff, $yoff, $xsize, $ysize);
-    my $pc = Geo::GDAL::PackCharacter($self->{DataType});
-    my $w = $xsize * Geo::GDAL::GetDataTypeSize($self->{DataType})/8;
+    my($self, $xoff, $yoff, $xsize, $ysize, $w_tile, $h_tile, $alg) = @_;
+    $xoff //= 0;
+    $yoff //= 0;
+    $xsize //= $self->{XSize} - $xoff;
+    $ysize //= $self->{YSize} - $yoff;
+    $w_tile //= $xsize;
+    $h_tile //= $ysize;
+    $alg //= 'NearestNeighbour';
+    my $t = $self->{DataType};
+    $alg = Geo::GDAL::string2int($alg, \%Geo::GDAL::RIO_RESAMPLING_STRING2INT);
+    my $buf = $self->_ReadRaster($xoff, $yoff, $xsize, $ysize, $w_tile, $h_tile, $t, 0, 0, $alg);
+    my $pc = Geo::GDAL::PackCharacter($t);
+    my $w = $w_tile * Geo::GDAL::GetDataTypeSize($t)/8;
     my $offset = 0;
     my @data;
-    for (0..$ysize-1) {
-        my $sub = substr($buf, $offset, $w);
-        my @d = unpack($pc."[$xsize]", $sub);
+    for my $y (0..$h_tile-1) {
+        my @d = unpack($pc."[$w_tile]", substr($buf, $offset, $w));
         push @data, \@d;
         $offset += $w;
     }
@@ -937,12 +1378,18 @@ sub ReadTile {
 
 sub WriteTile {
     my($self, $data, $xoff, $yoff) = @_;
-    $xoff = 0 unless defined $xoff;
-    $yoff = 0 unless defined $yoff;
+    $xoff //= 0;
+    $yoff //= 0;
     my $xsize = @{$data->[0]};
-    $xsize = $self->{XSize} - $xoff if $xsize > $self->{XSize} - $xoff;
+    if ($xsize > $self->{XSize} - $xoff) {
+        warn "Buffer XSize too large ($xsize) for this raster band (width = $self->{XSize}, offset = $xoff).";
+        $xsize = $self->{XSize} - $xoff;
+    }
     my $ysize = @{$data};
-    $ysize = $self->{YSize} - $yoff if $ysize > $self->{YSize} - $yoff;
+    if ($ysize > $self->{YSize} - $yoff) {
+        $ysize = $self->{YSize} - $yoff;
+        warn "Buffer YSize too large ($ysize) for this raster band (height = $self->{YSize}, offset = $yoff).";
+    }
     my $pc = Geo::GDAL::PackCharacter($self->{DataType});
     for my $i (0..$ysize-1) {
         my $scanline = pack($pc."[$xsize]", @{$data->[$i]});
@@ -953,14 +1400,11 @@ sub WriteTile {
 sub ColorInterpretation {
     my($self, $ci) = @_;
     if (defined $ci) {
-        my $ci2 = $ci;
-        $ci2 = $COLOR_INTERPRETATION_STRING2INT{$ci} if exists $COLOR_INTERPRETATION_STRING2INT{$ci};
-        confess "Unknown color interpretation: '$ci'." unless exists $COLOR_INTERPRETATION_INT2STRING{$ci2};
-        SetRasterColorInterpretation($self, $ci2);
-        return $ci;
-    } else {
-        return $COLOR_INTERPRETATION_INT2STRING{GetRasterColorInterpretation($self)};
+        $ci = Geo::GDAL::string2int($ci, \%COLOR_INTERPRETATION_STRING2INT);
+        SetRasterColorInterpretation($self, $ci);
     }
+    return unless defined wantarray;
+    $COLOR_INTERPRETATION_INT2STRING{GetRasterColorInterpretation($self)};
 }
 
 sub ColorTable {
@@ -983,89 +1427,60 @@ sub AttributeTable {
     SetDefaultRAT($self, $_[0]) if @_ and defined $_[0];
     return unless defined wantarray;
     my $r = GetDefaultRAT($self);
-    $Geo::GDAL::RasterAttributeTable::BANDS{$r} = $self if $r;
+    $RATS{tied(%$r)} = $self if $r;
     return $r;
 }
+*RasterAttributeTable = *AttributeTable;
 
 sub GetHistogram {
     my $self = shift;
-    my %defaults = (Min => -0.5,
-                    Max => 255.5,
-                    Buckets => 256,
-                    IncludeOutOfRange => 0,
-                    ApproxOK => 0,
-                    Progress => undef,
-                    ProgressData => undef);
-    my %params = @_;
-    for (keys %params) {
-        carp "unknown parameter $_ in Geo::GDAL::Band::GetHistogram" unless exists $defaults{$_};
-    }
-    for (keys %defaults) {
-        $params{$_} = $defaults{$_} unless defined $params{$_};
-    }
-    $params{ProgressData} = 1 if $params{Progress} and not defined $params{ProgressData};
-    _GetHistogram($self, $params{Min}, $params{Max}, $params{Buckets},
-                  $params{IncludeOutOfRange}, $params{ApproxOK},
-                  $params{Progress}, $params{ProgressData});
+    my $p = Geo::GDAL::named_parameters(\@_,
+                                        Min => -0.5,
+                                        Max => 255.5,
+                                        Buckets => 256,
+                                        IncludeOutOfRange => 0,
+                                        ApproxOK => 0,
+                                        Progress => undef,
+                                        ProgressData => undef);
+    $p->{progressdata} = 1 if $p->{progress} and not defined $p->{progressdata};
+    _GetHistogram($self, $p->{min}, $p->{max}, $p->{buckets},
+                  $p->{includeoutofrange}, $p->{approxok},
+                  $p->{progress}, $p->{progressdata});
 }
 
 sub Contours {
     my $self = shift;
-    my %defaults = (DataSource => undef,
-                    LayerConstructor => {Name => 'contours'},
-                    ContourInterval => 100,
-                    ContourBase => 0,
-                    FixedLevels => [],
-                    NoDataValue => undef,
-                    IDField => -1,
-                    ElevField => -1,
-                    Progress => undef,
-                    ProgressData => undef);
-    my %params;
-    if (!defined($_[0]) or (blessed($_[0]) and $_[0]->isa('Geo::OGR::DataSource'))) {
-        ($params{DataSource}, $params{LayerConstructor},
-         $params{ContourInterval}, $params{ContourBase},
-         $params{FixedLevels}, $params{NoDataValue},
-         $params{IDField}, $params{ElevField},
-         $params{Progress}, $params{ProgressData}) = @_;
-    } else {
-        %params = @_;
-        if (exists $params{progress}) {
-            $params{Progress} = $params{progress};
-            delete $params{progress};
-        }
-        if (exists $params{progress_data}) {
-            $params{ProgressData} = $params{progress_data};
-            delete $params{progress_data};
-        }
-    }
-    for (keys %params) {
-        carp "unknown parameter $_ in Geo::GDAL::Band::Contours" unless exists $defaults{$_};
-    }
-    for (keys %defaults) {
-        $params{$_} = $defaults{$_} unless defined $params{$_};
-    }
-    $params{DataSource} = Geo::OGR::GetDriver('Memory')->CreateDataSource('ds')
-        unless defined $params{DataSource};
-    $params{LayerConstructor}->{Schema} = {} unless $params{LayerConstructor}->{Schema};
-    $params{LayerConstructor}->{Schema}{Fields} = [] unless $params{LayerConstructor}->{Schema}{Fields};
+    my $p = Geo::GDAL::named_parameters(\@_,
+                                        DataSource => undef,
+                                        LayerConstructor => {Name => 'contours'},
+                                        ContourInterval => 100,
+                                        ContourBase => 0,
+                                        FixedLevels => [],
+                                        NoDataValue => undef,
+                                        IDField => -1,
+                                        ElevField => -1,
+                                        Progress => undef,
+                                        ProgressData => undef);
+    $p->{datasource} //= Geo::OGR::GetDriver('Memory')->CreateDataSource('ds');
+    $p->{layerconstructor}->{Schema} //= {};
+    $p->{layerconstructor}->{Schema}{Fields} //= [];
     my %fields;
-    unless ($params{IDField} =~ /^[+-]?\d+$/ or $fields{$params{IDField}}) {
-        push @{$params{LayerConstructor}->{Schema}{Fields}}, {Name => $params{IDField}, Type => 'Integer'};
+    unless ($p->{idfield} =~ /^[+-]?\d+$/ or $fields{$p->{idfield}}) {
+        push @{$p->{layerconstructor}->{Schema}{Fields}}, {Name => $p->{idfield}, Type => 'Integer'};
     }
-    unless ($params{ElevField} =~ /^[+-]?\d+$/ or $fields{$params{ElevField}}) {
+    unless ($p->{elevfield} =~ /^[+-]?\d+$/ or $fields{$p->{elevfield}}) {
         my $type = $self->DataType() =~ /Float/ ? 'Real' : 'Integer';
-        push @{$params{LayerConstructor}->{Schema}{Fields}}, {Name => $params{ElevField}, Type => $type};
+        push @{$p->{layerconstructor}->{Schema}{Fields}}, {Name => $p->{elevfield}, Type => $type};
     }
-    my $layer = $params{DataSource}->CreateLayer($params{LayerConstructor});
+    my $layer = $p->{datasource}->CreateLayer($p->{layerconstructor});
     my $schema = $layer->GetLayerDefn;
-    for ('IDField', 'ElevField') {
-        $params{$_} = $schema->GetFieldIndex($params{$_}) unless $params{$_} =~ /^[+-]?\d+$/;
+    for ('idfield', 'elevfield') {
+        $p->{$_} = $schema->GetFieldIndex($p->{$_}) unless $p->{$_} =~ /^[+-]?\d+$/;
     }
-    $params{ProgressData} = 1 if $params{Progress} and not defined $params{ProgressData};
-    ContourGenerate($self, $params{ContourInterval}, $params{ContourBase}, $params{FixedLevels},
-                    $params{NoDataValue}, $layer, $params{IDField}, $params{ElevField},
-                    $params{Progress}, $params{ProgressData});
+    $p->{progressdata} = 1 if $p->{progress} and not defined $p->{progressdata};
+    ContourGenerate($self, $p->{contourinterval}, $p->{contourbase}, $p->{fixedlevels},
+                    $p->{nodatavalue}, $layer, $p->{idfield}, $p->{elevfield},
+                    $p->{progress}, $p->{progressdata});
     return $layer;
 }
 
@@ -1074,112 +1489,55 @@ sub FillNodata {
     my $mask = shift;
     $mask = $self->GetMaskBand unless $mask;
     my @p = @_;
-    $p[0] = 10 unless defined $p[0];
-    $p[1] = 0 unless defined $p[1];
-    $p[2] = undef unless defined $p[2];
-    $p[3] = undef unless defined $p[3];
-    $p[4] = undef unless defined $p[1];
+    $p[0] //= 10;
+    $p[1] //= 0;
     Geo::GDAL::FillNodata($self, $mask, @p);
 }
+*FillNoData = *FillNodata;
 *GetBandNumber = *GetBand;
 
 sub ReadRaster {
     my $self = shift;
     my ($width, $height) = $self->Size;
     my ($type) = $self->DataType;
-    my %d = (
-        XOFF => 0,
-        YOFF => 0,
-        XSIZE => $width,
-        YSIZE => $height,
-        BUFXSIZE => undef,
-        BUFYSIZE => undef,
-        BUFTYPE => $type,
-        BUFPIXELSPACE => 0,
-        BUFLINESPACE => 0,
-        RESAMPLEALG => 'NearestNeighbour',
-        PROGRESS => undef,
-        PROGRESSDATA => undef
+    my $p = Geo::GDAL::named_parameters(\@_,
+                                        XOff => 0,
+                                        YOff => 0,
+                                        XSize => $width,
+                                        YSize => $height,
+                                        BufXSize => undef,
+                                        BufYSize => undef,
+                                        BufType => $type,
+                                        BufPixelSpace => 0,
+                                        BufLineSpace => 0,
+                                        ResampleAlg => 'NearestNeighbour',
+                                        Progress => undef,
+                                        ProgressData => undef
         );
-    my %p;
-    my $t;
-    if (defined $_[0]) {
-        $t = uc($_[0]); 
-        $t =~ s/_//g;
-    }
-    if (@_ == 0) {
-    } elsif (ref($_[0]) eq 'HASH') {
-        %p = %{$_[0]};
-    } elsif (@_ % 2 == 0 and (defined $t and exists $d{$t})) {
-        %p = @_;
-    } else {
-        ($p{xoff},$p{yoff},$p{xsize},$p{ysize},$p{buf_xsize},$p{buf_ysize},$p{buf_type},$p{buf_pixel_space},$p{buf_line_space},$p{resample_alg},$p{progress},$p{progress_data}) = @_;
-    }
-    for (keys %p) {
-        my $u = uc($_);
-        $u =~ s/_//g;
-        carp "Unknown named parameter '$_'." unless exists $d{$u};
-        $p{$u} = $p{$_};
-    }
-    for (keys %d) {
-        $p{$_} = $d{$_} unless defined $p{$_};
-    }
-    confess "Unknown resampling algorithm: '$p{RESAMPLEALG}'." 
-        unless exists $Geo::GDAL::RIO_RESAMPLING_STRING2INT{$p{RESAMPLEALG}};
-    $p{RESAMPLEALG} = $Geo::GDAL::RIO_RESAMPLING_STRING2INT{$p{RESAMPLEALG}};
-    unless ($Geo::GDAL::TYPE_INT2STRING{$p{BUFTYPE}}) {
-        confess "Unknown data type: '$p{BUFTYPE}'." 
-            unless exists $Geo::GDAL::TYPE_STRING2INT{$p{BUFTYPE}};
-        $p{BUFTYPE} = $Geo::GDAL::TYPE_STRING2INT{$p{BUFTYPE}};
-    }
-    $self->_ReadRaster($p{XOFF},$p{YOFF},$p{XSIZE},$p{YSIZE},$p{BUFXSIZE},$p{BUFYSIZE},$p{BUFTYPE},$p{BUFPIXELSPACE},$p{BUFLINESPACE},$p{RESAMPLEALG},$p{PROGRESS},$p{PROGRESSDATA});
+    $p->{resamplealg} = Geo::GDAL::string2int($p->{resamplealg}, \%Geo::GDAL::RIO_RESAMPLING_STRING2INT);
+    $p->{buftype} = Geo::GDAL::string2int($p->{buftype}, \%Geo::GDAL::TYPE_STRING2INT, \%Geo::GDAL::TYPE_INT2STRING);
+    $self->_ReadRaster($p->{xoff},$p->{yoff},$p->{xsize},$p->{ysize},$p->{bufxsize},$p->{bufysize},$p->{buftype},$p->{bufpixelspace},$p->{buflinespace},$p->{resamplealg},$p->{progress},$p->{progressdata});
 }
 
 sub WriteRaster {
     my $self = shift;
     my ($width, $height) = $self->Size;
     my ($type) = $self->DataType;
-    my %d = (
-        XOFF => 0,
-        YOFF => 0,
-        XSIZE => $width,
-        YSIZE => $height,
-        BUF => undef,
-        BUFXSIZE => undef,
-        BUFYSIZE => undef,
-        BUFTYPE => $type,
-        BUFPIXELSPACE => 0,
-        BUFLINESPACE => 0
+    my $p = Geo::GDAL::named_parameters(\@_,
+                                        XOff => 0,
+                                        YOff => 0,
+                                        XSize => $width,
+                                        YSize => $height,
+                                        Buf => undef,
+                                        BufXSize => undef,
+                                        BufYSize => undef,
+                                        BufType => $type,
+                                        BufPixelSpace => 0,
+                                        BufLineSpace => 0
         );
-    my %p;
-    my $t;
-    if (defined $_[0]) {
-        $t = uc($_[0]); 
-        $t =~ s/_//g;
-    }
-    if (@_ == 0) {
-    } elsif (ref($_[0]) eq 'HASH') {
-        %p = %{$_[0]};
-    } elsif (@_ % 2 == 0 and (defined $t and exists $d{$t})) {
-        %p = @_;
-    } else {
-        ($p{xoff},$p{yoff},$p{xsize},$p{ysize},$p{buf},$p{buf_xsize},$p{buf_ysize},$p{buf_type},$p{buf_pixel_space},$p{buf_line_space}) = @_;
-    }
-    for (keys %p) {
-        my $u = uc($_);
-        $u =~ s/_//g;
-        carp "Unknown named parameter '$_'." unless exists $d{$u};
-        $p{$u} = $p{$_};
-    }
-    for (keys %d) {
-        $p{$_} = $d{$_} unless defined $p{$_};
-    }
-    unless ($Geo::GDAL::TYPE_INT2STRING{$p{BUFTYPE}}) {
-        confess "Unknown data type: '$p{BUFTYPE}'." 
-            unless exists $Geo::GDAL::TYPE_STRING2INT{$p{BUFTYPE}};
-        $p{BUFTYPE} = $Geo::GDAL::TYPE_STRING2INT{$p{BUFTYPE}};
-    }
-    $self->_WriteRaster($p{XOFF},$p{YOFF},$p{XSIZE},$p{YSIZE},$p{BUF},$p{BUFXSIZE},$p{BUFYSIZE},$p{BUFTYPE},$p{BUFPIXELSPACE},$p{BUFLINESPACE});
+    confess "Usage: \$band->WriteRaster( Buf => \$data, ... )" unless defined $p->{buf};
+    $p->{buftype} = Geo::GDAL::string2int($p->{buftype}, \%Geo::GDAL::TYPE_STRING2INT, \%Geo::GDAL::TYPE_INT2STRING);
+    $self->_WriteRaster($p->{xoff},$p->{yoff},$p->{xsize},$p->{ysize},$p->{buf},$p->{bufxsize},$p->{bufysize},$p->{buftype},$p->{bufpixelspace},$p->{buflinespace});
 }
 
 sub GetMaskFlags {
@@ -1206,11 +1564,48 @@ sub CreateMaskBand {
     $self->_CreateMaskBand($f);
 }
 
-# GetMaskBand should be redefined and the result should be put into 
-# %Geo::GDAL::Dataset::BANDS
+sub Piddle {
+    my $self = shift; # should use named parameters for read raster and band
+    # add Piddle sub to dataset too to make N x M x n piddles
+    my ($w, $h) = $self->Size;
+    my $data = $self->ReadRaster;
+    my $pdl = PDL->new;
+    my %map = (
+        Byte => 0,
+        UInt16 => 2,
+        Int16 => 1,
+        UInt32 => -1,
+        Int32 => 3,
+        Float32 => 5,
+        Float64 => 6,
+        CInt16 => -1,
+        CInt32 => -1,
+        CFloat32 => -1,
+        CFloat64 => -1
+        );
+    my $datatype = $map{$self->DataType};
+    croak "there is no direct mapping between the band datatype and PDL" if $datatype < 0;
+    $pdl->set_datatype($datatype);
+    $pdl->setdims([1,$w,$h]);
+    my $dref = $pdl->get_dataref();
+    $$dref = $data;
+    $pdl->upd_data;
+    return $pdl;
+}
 
-# GetOverview should be redefined and the result should be put into 
-# %Geo::GDAL::Dataset::BANDS
+sub GetMaskBand {
+    my $self = shift;
+    my $band = _GetMaskBand($self);
+    $Geo::GDAL::Dataset::BANDS{tied(%{$band})} = $self;
+    return $band;
+}
+
+sub GetOverview {
+    my ($self, $index) = @_;
+    my $band = _GetOverview($self, $index);
+    $Geo::GDAL::Dataset::BANDS{tied(%{$band})} = $self;
+    return $band;
+}
 
 sub RegenerateOverview {
     my $self = shift;
@@ -1218,7 +1613,7 @@ sub RegenerateOverview {
     my @p = @_;
     Geo::GDAL::RegenerateOverview($self, @p);
 }
- 
+
 sub RegenerateOverviews {
     my $self = shift;
     #arrayref overviews, scalar resampling, subref callback, scalar callback_data
@@ -1226,6 +1621,59 @@ sub RegenerateOverviews {
     Geo::GDAL::RegenerateOverviews($self, @p);
 }
 
+sub Polygonize {
+    my $self = shift;
+    my $p = Geo::GDAL::named_parameters(\@_, Mask => undef, OutLayer => undef, PixValField => 'val', Options => undef, Progress => undef, ProgressData => undef);
+    my $dt = $self->DataType;
+    my %leInt32 = (Byte => 1, Int16 => 1, Int32 => 1, UInt16 => 1);
+    my $leInt32 = $leInt32{$dt};
+    $dt = $dt =~ /Float/ ? 'Real' : 'Integer';
+    $p->{outlayer} //= Geo::OGR::Driver('Memory')->Create()->
+        CreateLayer(Name => 'polygonized',
+                    Fields => [{Name => 'val', Type => $dt},
+                               {Name => 'geom', Type => 'Polygon'}]);
+    $p->{pixvalfield} = $p->{outlayer}->GetLayerDefn->GetFieldIndex($p->{pixvalfield});
+    $p->{options}{'8CONNECTED'} = $p->{options}{Connectedness} if $p->{options}{Connectedness};
+    if ($leInt32 || $p->{options}{ForceIntPixel}) {
+        Geo::GDAL::_Polygonize($self, $p->{mask}, $p->{outlayer}, $p->{pixvalfield}, $p->{options}, $p->{progress}, $p->{progressdata});
+    } else {
+        Geo::GDAL::FPolygonize($self, $p->{mask}, $p->{outlayer}, $p->{pixvalfield}, $p->{options}, $p->{progress}, $p->{progressdata});
+    }
+    set the srs of the outlayer if it was created here
+    return $p->{outlayer};
+}
+
+sub Sieve {
+    my $self = shift;
+    my $p = Geo::GDAL::named_parameters(\@_, Mask => undef, Dest => undef, Threshold => 10, Options => undef, Progress => undef, ProgressData => undef);
+    unless ($p->{dest}) {
+        my ($w, $h) = $self->Size;
+        $p->{dest} = Geo::GDAL::Driver('MEM')->Create(Name => 'sieved', Width => $w, Height => $h, Type => $self->DataType)->Band;
+    }
+    my $c = 8;
+    if ($p->{options}{Connectedness}) {
+        $c = $p->{options}{Connectedness};
+        delete $p->{options}{Connectedness};
+    }
+    Geo::GDAL::SieveFilter($self, $p->{mask}, $p->{dest}, $p->{threshold}, $c, $p->{options}, $p->{progress}, $p->{progressdata});
+    return $p->{dest};
+}
+
+sub Distance {
+    my $self = shift;
+    my $p = Geo::GDAL::named_parameters(\@_, Distance => undef, Options => undef, Progress => undef, ProgressData => undef);
+    for my $key (keys %{$p->{options}}) {
+        $p->{options}{uc($key)} = $p->{options}{$key};
+    }
+    $p->{options}{TYPE} //= $p->{options}{DATATYPE} //= 'Float32';
+    unless ($p->{distance}) {
+        my ($w, $h) = $self->Size;
+        $p->{distance} = Geo::GDAL::Driver('MEM')->Create(Name => 'distance', Width => $w, Height => $h, Type => $p->{options}{TYPE})->Band;
+    }
+    Geo::GDAL::ComputeProximity($self, $p->{distance}, $p->{options}, $p->{progress}, $p->{progressdata});
+    return $p->{distance};
+}
+
 
 
 
@@ -1233,13 +1681,14 @@ package Geo::GDAL::ColorTable;
 use strict;
 use warnings;
 use Carp;
-use vars qw/
-    %PALETTE_INTERPRETATION_STRING2INT %PALETTE_INTERPRETATION_INT2STRING
-    /;
-for my $string (qw/Gray RGB CMYK HLS/) {
-    my $int = eval "\$Geo::GDAL::Constc::GPI_$string";
-    $PALETTE_INTERPRETATION_STRING2INT{$string} = $int;
-    $PALETTE_INTERPRETATION_INT2STRING{$int} = $string;
+
+use vars qw/%PALETTE_INTERPRETATION_STRING2INT %PALETTE_INTERPRETATION_INT2STRING/;
+for (keys %Geo::GDAL::Const::) {
+    if (/^GPI_(\w+)/) {
+        my $int = eval "\$Geo::GDAL::Const::GPI_$1";
+        $PALETTE_INTERPRETATION_STRING2INT{$1} = $int;
+        $PALETTE_INTERPRETATION_INT2STRING{$int} = $1;
+    }
 }
 %}
 
@@ -1248,7 +1697,8 @@ for my $string (qw/Gray RGB CMYK HLS/) {
 use Carp;
 sub new {
     my($pkg, $pi) = @_;
-    $pi = $PALETTE_INTERPRETATION_STRING2INT{$pi} if defined $pi and exists $PALETTE_INTERPRETATION_STRING2INT{$pi};
+    $pi //= 'RGB';
+    $pi = Geo::GDAL::string2int($pi, \%PALETTE_INTERPRETATION_STRING2INT);
     my $self = Geo::GDALc::new_ColorTable($pi);
     bless $self, $pkg if defined($self);
 }
@@ -1272,33 +1722,36 @@ sub SetColorEntry {
     eval {
         $self->_SetColorEntry($index, $color);
     };
-    confess $@ if $@;
+    confess(Geo::GDAL->last_error) if $@;
 }
 
 sub ColorEntry {
     my $self = shift;
-    my $index = shift;
-    SetColorEntry($self, $index, @_) if @_ > 0;
-    GetColorEntry($self, $index) if defined wantarray;
+    my $index = shift // 0;
+    SetColorEntry($self, $index, @_) if @_;
+    return unless defined wantarray;
+    return wantarray ? GetColorEntry($self, $index) : [GetColorEntry($self, $index)];
 }
+*Color = *ColorEntry;
 
 sub ColorTable {
     my $self = shift;
-    my @table;
     if (@_) {
         my $index = 0;
         for my $color (@_) {
-            push @table, [ColorEntry($self, $index, @$color)];
+            ColorEntry($self, $index, $color);
             $index++;
         }
-    } else {
-        for (my $index = 0; $index < GetCount($self); $index++) {
-            push @table, [ColorEntry($self, $index)];
-        }
+    }
+    return unless defined wantarray;
+    my @table;
+    for (my $index = 0; $index < GetCount($self); $index++) {
+        push @table, [ColorEntry($self, $index)];
     }
     return @table;
 }
 *ColorEntries = *ColorTable;
+*Colors = *ColorTable;
 
 
 
@@ -1307,7 +1760,8 @@ package Geo::GDAL::RasterAttributeTable;
 use strict;
 use warnings;
 use Carp;
-use vars qw/ %BANDS
+
+use vars qw/
     @FIELD_TYPES @FIELD_USAGES
     %FIELD_TYPE_STRING2INT %FIELD_TYPE_INT2STRING
     %FIELD_USAGE_STRING2INT %FIELD_USAGE_INT2STRING
@@ -1338,7 +1792,12 @@ sub FieldUsages {
 
 sub RELEASE_PARENTS {
     my $self = shift;
-    delete $BANDS{$self};
+    delete $Geo::GDAL::Band::RATS{$self};
+}
+
+sub Band {
+    my $self = shift;
+    return $Geo::GDAL::Band::RATS{tied(%$self)};
 }
 
 sub GetUsageOfCol {
@@ -1376,13 +1835,11 @@ sub Columns {
 
 sub CreateColumn {
     my($self, $name, $type, $usage) = @_;
-    confess "Unknown RAT column type: '$type'." unless exists $FIELD_TYPE_STRING2INT{$type};
-    confess "Unknown RAT column usage: '$usage'." unless exists $FIELD_USAGE_STRING2INT{$usage};
     for my $color (qw/Red Green Blue Alpha/) {
         carp "RAT column type will be 'Integer' for usage '$color'." if $usage eq $color and $type ne 'Integer';
     }
-    $type = $FIELD_TYPE_STRING2INT{$type};
-    $usage = $FIELD_USAGE_STRING2INT{$usage};
+    $type = Geo::GDAL::string2int($type, \%FIELD_TYPE_STRING2INT);
+    $usage = Geo::GDAL::string2int($usage, \%FIELD_USAGE_STRING2INT);
     _CreateColumn($self, $name, $type, $usage);
 }
 
@@ -1417,6 +1874,11 @@ package Geo::GDAL::VSIF;
 use strict;
 use warnings;
 use Carp;
+require Exporter;
+our @ISA = qw(Exporter);
+
+our @EXPORT_OK   = qw(Open Close Write Read Seek Tell Truncate MkDir ReadDir ReadDirRecursive Rename RmDir Stat Unlink);
+our %EXPORT_TAGS = (all => \@EXPORT_OK);
 
 sub Open {
     my ($path, $mode) = @_;
@@ -1431,12 +1893,7 @@ sub Write {
 
 sub Close {
     my ($self, $data) = @_;
-    eval {
-        Geo::GDAL::VSIFCloseL($self);
-    };
-    if ($@) {
-        confess "Cannot close file: $@.";
-    }
+    Geo::GDAL::VSIFCloseL($self);
 }
 
 sub Read {
@@ -1456,23 +1913,13 @@ sub Tell {
 
 sub Truncate {
     my ($self, $new_size) = @_;
-    eval {
-        Geo::GDAL::VSIFTruncateL($self, $new_size);
-    };
-    if ($@) {
-        confess "Cannot truncate file: $@.";
-    }
+    Geo::GDAL::VSIFTruncateL($self, $new_size);
 }
 
 sub MkDir {
     my ($path) = @_;
-    my $mode = 0; # unused in CPL
-    eval {
-        Geo::GDAL::Mkdir($path, $mode);
-    };
-    if ($@) {
-        confess "Cannot make directory \"$path\": $@.";
-    }
+    # mode unused in CPL
+    Geo::GDAL::Mkdir($path, 0);
 }
 *Mkdir = *MkDir;
 
@@ -1488,12 +1935,7 @@ sub ReadDirRecursive {
 
 sub Rename {
     my ($old, $new) = @_;
-    eval {
-        Geo::GDAL::Rename($old, $new);
-    };
-    if ($@) {
-        confess "Cannot rename file \"$old\": $@.";
-    }
+    Geo::GDAL::Rename($old, $new);
 }
 
 sub RmDir {
@@ -1517,29 +1959,19 @@ sub RmDir {
     };
     if ($@) {
         my $r = $recursive ? ' recursively' : '';
-        confess "Cannot remove directory \"$dirname\"$r: $@.";
+        Geo::GDAL::error("Cannot remove directory \"$dirname\"$r.");
     }
 }
 *Rmdir = *RmDir;
 
 sub Stat {
     my ($path) = @_;
-    eval {
-        Geo::GDAL::Stat($path);
-    };
-    if ($@) {
-        confess "Cannot stat file \"$path\": $@.";
-    }
+    Geo::GDAL::Stat($path);
 }
 
 sub Unlink {
     my ($filename) = @_;
-    eval {
-        Geo::GDAL::Unlink($filename);
-    };
-    if ($@) {
-        confess "Cannot unlink file \"$filename\": $@.";
-    }
+    Geo::GDAL::Unlink($filename);
 }
 
 
@@ -1549,6 +1981,7 @@ package Geo::GDAL::GeoTransform;
 use strict;
 use warnings;
 use Carp;
+use Scalar::Util 'blessed';
 
 sub new {
     my $class = shift;
@@ -1565,17 +1998,26 @@ sub new {
     return $self;
 }
 
+sub NorthUp {
+    my $self = shift;
+    return $self->[2] == 0 && $self->[4] == 0;
+}
+
 sub FromGCPs {
-    my @GCPs;
-    my $ApproxOK = 1;
-    if (ref($_[0]) eq 'ARRAY') {
-        @GCPs = @{$_[0]};
-        $ApproxOK = $_[1] if defined $_[1];
+    my $gcps;
+    my $p = shift;
+    if (ref $p eq 'ARRAY') {
+        $gcps = $p;
     } else {
-        @GCPs = @_;
-        $ApproxOK = pop @GCPs if !ref($GCPs[$#GCPs]);
+        $gcps = [];
+        while ($p && blessed $p) {
+            push @$gcps, $p;
+            $p = shift;
+        }
     }
-    my $self = Geo::GDAL::GCPsToGeoTransform(\@GCPs, $ApproxOK);
+    my $approx_ok = shift // 1;
+    Geo::GDAL::error('Usage: Geo::GDAL::GeoTransform::FromGCPs(\@gcps, $approx_ok)') unless @$gcps;
+    my $self = Geo::GDAL::GCPsToGeoTransform($gcps, $approx_ok);
     bless $self, 'Geo::GDAL::GetTransform';
     return $self;
 }
@@ -1584,7 +2026,7 @@ sub Apply {
     my ($self, $columns, $rows) = @_;
     my (@x, @y);
     for my $i (0..$#$columns) {
-        ($x[$i], $y[$i]) = 
+        ($x[$i], $y[$i]) =
             Geo::GDAL::ApplyGeoTransform($self, $columns->[$i], $rows->[$i]);
     }
     return (\@x, \@y);
@@ -1593,13 +2035,115 @@ sub Apply {
 sub Inv {
     my $self = shift;
     my @inv = Geo::GDAL::InvGeoTransform($self);
-    unless (defined wantarray) {
-        @$self = @inv;
+    return new(@inv) if defined wantarray;
+    @$self = @inv;
+}
+
+sub Extent {
+    my ($self, $w, $h) = @_;
+    my $e = Geo::GDAL::Extent->new($self->[0], $self->[3], $self->[0], $self->[3]);
+    for my $x ($self->[0] + $self->[1]*$w, $self->[0] + $self->[2]*$h, $self->[0] + $self->[1]*$w + $self->[2]*$h) {
+        $e->[0] = $x if $x < $e->[0];
+        $e->[2] = $x if $x > $e->[2];
+    }
+    for my $y ($self->[3] + $self->[4]*$w, $self->[3] + $self->[5]*$h, $self->[3] + $self->[4]*$w + $self->[5]*$h) {
+        $e->[1] = $y if $y < $e->[1];
+        $e->[3] = $y if $y > $e->[3];
+    }
+    return $e;
+}
+
+package Geo::GDAL::Extent; # array 0=xmin|left, 1=ymin|bottom, 2=xmax|right, 3=ymax|top
+
+use strict;
+use warnings;
+use Carp;
+use Scalar::Util 'blessed';
+
+sub new {
+    my $class = shift;
+    my $self;
+    if (@_ == 0) {
+        $self = [0,0,0,0];
+    } elsif (ref $_[0]) {
+        @$self = @{$_[0]};
     } else {
-        return new(@inv);
+        @$self = @_;
+    }
+    bless $self, $class;
+    return $self;
+}
+
+sub Size {
+    my $self = shift;
+    return ($self->[2] - $self->[0], $self->[3] - $self->[1]);
+}
+
+sub Overlaps {
+    my ($self, $e) = @_;
+    return $self->[0] < $e->[2] && $self->[2] > $e->[0] && $self->[1] < $e->[3] && $self->[3] > $e->[1];
+}
+
+sub Overlap {
+    my ($self, $e) = @_;
+    return undef unless $self->Overlaps($e);
+    my $ret = Geo::GDAL::Extent->new($self);
+    $ret->[0] = $e->[0] if $self->[0] < $e->[0];
+    $ret->[1] = $e->[1] if $self->[1] < $e->[1];
+    $ret->[2] = $e->[2] if $self->[2] > $e->[2];
+    $ret->[3] = $e->[3] if $self->[3] > $e->[3];
+    return $ret;
+}
+
+sub ExpandToInclude {
+    my ($self, $e) = @_;
+    $self->[0] = $e->[0] if $e->[0] < $self->[0];
+    $self->[1] = $e->[1] if $e->[1] < $self->[1];
+    $self->[2] = $e->[2] if $e->[2] > $self->[2];
+    $self->[3] = $e->[3] if $e->[3] > $self->[3];
+}
+
+package Geo::GDAL::XML;
+
+use strict;
+use warnings;
+use Carp;
+
+# XML related subs in Geo::GDAL
+
+#Geo::GDAL::Child
+#Geo::GDAL::Children
+#Geo::GDAL::NodeData
+#Geo::GDAL::NodeType
+#Geo::GDAL::NodeTypes
+#Geo::GDAL::ParseXMLString
+#Geo::GDAL::SerializeXMLTree
+
+sub new {
+    my $class = shift;
+    my $xml = shift // '';
+    my $self = Geo::GDAL::ParseXMLString($xml);
+    bless $self, $class;
+    $self->traverse(sub {my $node = shift; bless $node, $class});
+    return $self;
+}
+
+sub traverse {
+    my ($self, $sub) = @_;
+    my $type = $self->[0];
+    my $data = $self->[1];
+    $type = Geo::GDAL::NodeType($type);
+    $sub->($self, $type, $data);
+    for my $child (@{$self}[2..$#$self]) {
+        traverse($child, $sub);
     }
 }
 
+sub serialize {
+    my $self = shift;
+    return Geo::GDAL::SerializeXMLTree($self);
+}
+
 %}
 
 %{
diff --git a/swig/include/perl/ogr_perl.i b/swig/include/perl/ogr_perl.i
index 26e7cfe..1cb7587 100644
--- a/swig/include/perl/ogr_perl.i
+++ b/swig/include/perl/ogr_perl.i
@@ -36,7 +36,7 @@
 %}
 
 %include callback.i
-
+%include confess.i
 %include cpl_exceptions.i
 
 %rename (GetDriverCount) OGRGetDriverCount;
@@ -48,20 +48,11 @@
 
 %import destroy.i
 
-ALTERED_DESTROY(OGRDataSourceShadow, OGRc, delete_DataSource)
 ALTERED_DESTROY(OGRFeatureShadow, OGRc, delete_Feature)
 ALTERED_DESTROY(OGRFeatureDefnShadow, OGRc, delete_FeatureDefn)
 ALTERED_DESTROY(OGRFieldDefnShadow, OGRc, delete_FieldDefn)
 ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 
-#ifndef FROM_GDAL_I
-%extend OGRDataSourceShadow {
-
-  %rename (_ExecuteSQL) ExecuteSQL;
-
- }
-#endif
-
 %extend OGRGeometryShadow {
 
     %rename (AddPoint_3D) AddPoint;
@@ -109,17 +100,15 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 
 }
 
-/* wrapped data source methods: */
-%rename (_GetDriver) GetDriver;
-%rename (_TestCapability) TestCapability;
-
 /* wrapped layer methods: */
+%rename (_TestCapability) TestCapability;
 %rename (_ReleaseResultSet) ReleaseResultSet;
 %rename (_CreateLayer) CreateLayer;
 %rename (_DeleteLayer) DeleteLayer;
 %rename (_CreateField) CreateField;
 %rename (_DeleteField) DeleteField;
 %rename (_Validate) Validate;
+%rename (_GetFeature) GetFeature;
 
 /* wrapped feature methods: */
 %rename (_AlterFieldDefn) AlterFieldDefn;
@@ -131,180 +120,82 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 %perlcode %{
 
 package Geo::OGR;
-our $VERSION = '2.0002'; # this needs to be the same as that in gdal_perl.i
+our $VERSION = '2.0100'; # this needs to be the same as that in gdal_perl.i
 
-package Geo::OGR::Driver;
-use strict;
-use warnings;
-use Carp;
-use vars qw /@CAPABILITIES %CAPABILITIES/;
-for (keys %Geo::OGR::) {
-    push(@CAPABILITIES, $1), next if /^ODrC(\w+)/;
-}
-for my $s (@CAPABILITIES) {
-    my $cap = eval "\$Geo::OGR::ODrC$s";
-    $CAPABILITIES{$s} = $cap;
+sub Driver {
+    return 'Geo::GDAL::Driver' unless @_;
+    bless Geo::GDAL::Driver(@_), 'Geo::OGR::Driver';
 }
+*GetDriver = *Driver;
 
-sub Capabilities {
-    return @CAPABILITIES if @_ == 0;
-    my $self = shift;
-    my @cap;
-    for my $cap (@CAPABILITIES) {
-        push @cap, $cap if _TestCapability($self, $CAPABILITIES{$cap});
+sub GetDriverNames {
+    my @names;
+    for my $i (0..Geo::GDAL::GetDriverCount()-1) {
+        my $driver = Geo::GDAL::GetDriver($i);
+        push @names, $driver->Name if $driver->TestCapability('VECTOR');
     }
-    return @cap;
-}
-
-sub TestCapability {
-    my($self, $cap) = @_;
-    confess "No such capability defined for class Driver: '$cap'." unless defined $CAPABILITIES{$cap};
-    return _TestCapability($self, $CAPABILITIES{$cap});
-}
-
-*Create = *CreateDataSource;
-*Copy = *CopyDataSource;
-*OpenDataSource = *Open;
-*Delete = *DeleteDataSource;
-*Name = *GetName;
-
-
-
-
-package Geo::OGR::DataSource;
-use strict;
-use warnings;
-use Carp;
-use vars qw /@CAPABILITIES %CAPABILITIES %LAYERS %RESULT_SET/;
-for (keys %Geo::OGR::) {
-    push(@CAPABILITIES, $1), next if /^ODsC(\w+)/;
-}
-for my $s (@CAPABILITIES) {
-    my $cap = eval "\$Geo::OGR::ODsC$s";
-    $CAPABILITIES{$s} = $cap;
+    return @names;
 }
+*DriverNames = *GetDriverNames;
 
-sub Capabilities {
-    return @CAPABILITIES if @_ == 0;
-    my $self = shift;
-    my @cap;
-    for my $cap (@CAPABILITIES) {
-        push @cap, $cap if _TestCapability($self, $CAPABILITIES{$cap});
+sub Drivers {
+    my @drivers;
+    for my $i (0..GetDriverCount()-1) {
+        my $driver = Geo::GDAL::GetDriver($i);
+        push @drivers, $driver if $driver->TestCapability('VECTOR');
     }
-    return @cap;
-}
-
-sub TestCapability {
-    my($self, $cap) = @_;
-    confess "No such capability defined for class DataSource: '$cap'." unless defined $CAPABILITIES{$cap};
-    return _TestCapability($self, $CAPABILITIES{$cap});
-}
-*GetDriver = *_GetDriver;
-
-sub new {
-    my $pkg = shift;
-    return Geo::OGR::Open(@_);
+    return @drivers;
 }
 
 sub Open {
-    return Geo::OGR::Open(@_);
+    my @p = @_; # name, update
+    my @flags = qw/VECTOR/;
+    push @flags, qw/UPDATE/ if $p[1];
+    my $dataset = Geo::GDAL::OpenEx($p[0], \@flags);
+    Geo::GDAL::error("Failed to open $p[0]. Is it a vector dataset?") unless $dataset;
+    return $dataset;
 }
 
 sub OpenShared {
-    return Geo::OGR::OpenShared(@_);
+    my @p = @_; # name, update
+    my @flags = qw/VECTOR SHARED/;
+    push @flags, qw/UPDATE/ if $p[1];
+    my $dataset = Geo::GDAL::OpenEx($p[0], \@flags);
+    Geo::GDAL::error("Failed to open $p[0]. Is it a vector dataset?") unless $dataset;
+    return $dataset;
 }
 
-sub ExecuteSQL {
-    my $self = shift;
-    my $layer = $self->_ExecuteSQL(@_);
-    $LAYERS{tied(%$layer)} = $self;
-    $RESULT_SET{tied(%$layer)} = 1;
-    return $layer;
-}
+package Geo::OGR::Driver;
+our @ISA = qw/Geo::GDAL::Driver/;
 
-sub ReleaseResultSet {
-    # a no-op, _ReleaseResultSet is called from Layer::DESTROY
+sub Create {
+    my ($self, $name, $options) = @_; # name, options
+    $options //= {};
+    $self->SUPER::Create(Name => $name, Width => 0, Height => 0, Bands => 0, Type => 'Byte', Options => $options);
 }
 
-sub GetLayer {
-    my($self, $name) = @_;
-    my $layer = defined $name ? GetLayerByName($self, "$name") : GetLayerByIndex($self, 0);
-    $name = '' unless defined $name;
-    confess "No such layer: '$name'." unless $layer;
-    $LAYERS{tied(%$layer)} = $self;
-    return $layer;
+sub Copy {
+    my ($self, @p) = @_; # src, name, options
+    my $strict = 1; # the default in bindings
+    $strict = 0 if $p[2] && $p[2]->{STRICT} eq 'NO';
+    $self->SUPER::Copy($p[1], $p[0], $strict, @{$p[2..4]}); # path, src, strict, options, cb, cb_data
 }
-*Layer = *GetLayer;
 
-sub GetLayerNames {
+sub Open {
     my $self = shift;
-    my @names;
-    for my $i (0..$self->GetLayerCount-1) {
-        my $layer = GetLayerByIndex($self, $i);
-        push @names, $layer->GetName;
-    }
-    return @names;
+    my @p = @_; # name, update
+    my @flags = qw/VECTOR/;
+    push @flags, qw/UPDATE/ if $p[1];
+    my $dataset = Geo::GDAL::OpenEx($p[0], \@flags, [$self->Name()]);
+    Geo::GDAL::error("Failed to open $p[0]. Is it a vector dataset?") unless $dataset;
+    return $dataset;
 }
-*Layers = *GetLayerNames;
 
-sub CreateLayer {
-    my $self = shift;
-    my %defaults = ( Name => 'unnamed',
-                     SRS => undef,
-                     Options => {},
-                     GeometryType => 'Unknown',
-                     Schema => undef,
-                     Fields => undef,
-                     ApproxOK => 1);
-    my %params;
-    if (@_ == 0) {
-    } elsif (ref($_[0]) eq 'HASH') {
-        %params = %{$_[0]};
-    } elsif (@_ % 2 == 0 and (defined $_[0] and exists $defaults{$_[0]})) {
-        %params = @_;
-    } else {
-        ($params{Name}, $params{SRS}, $params{GeometryType}, $params{Options}, $params{Schema}) = @_;
-    }
-    for (keys %params) {
-        carp "CreateLayer: unknown named parameter '$_'." unless exists $defaults{$_};
-    }
-    if (exists $params{Schema}) {
-        my $s = $params{Schema};
-        $params{GeometryType} = $s->{GeometryType} if exists $s->{GeometryType};
-        $params{Fields} = $s->{Fields} if exists $s->{Fields};
-        $params{Name} = $s->{Name} if exists $s->{Name};
-    }
-    $defaults{GeometryType} = 'None' if $params{Fields};
-    for (keys %defaults) {
-        $params{$_} = $defaults{$_} unless defined $params{$_};
-    }
-    confess "Unknown geometry type: '$params{GeometryType}'."
-        unless exists $Geo::OGR::Geometry::TYPE_STRING2INT{$params{GeometryType}};
-    my $gt = $Geo::OGR::Geometry::TYPE_STRING2INT{$params{GeometryType}};
-    my $layer = _CreateLayer($self, $params{Name}, $params{SRS}, $gt, $params{Options});
-    $LAYERS{tied(%$layer)} = $self;
-    my $f = $params{Fields};
-    if ($f) {
-        confess "Named parameter 'Fields' must be a reference to an array." unless ref($f) eq 'ARRAY';
-        for my $field (@$f) {
-            $layer->CreateField($field);
-        }
-    }
-    return $layer;
-}
-
-sub DeleteLayer {
-    my ($self, $name) = @_;
-    my $index;
-    for my $i (0..$self->GetLayerCount-1) {
-        my $layer = GetLayerByIndex($self, $i);
-        $index = $i, last if $layer->GetName eq $name;
-    }
-    confess "No such layer: '$name'." unless defined $index;
-    _DeleteLayer($self, $index);
-}
 
+package Geo::OGR::DataSource;
 
+*Open = *Geo::OGR::Open;
+*OpenShared = *Geo::OGR::OpenShared;
 
 
 package Geo::OGR::Layer;
@@ -312,7 +203,7 @@ use strict;
 use warnings;
 use Carp;
 use Scalar::Util 'blessed';
-use vars qw /@CAPABILITIES %CAPABILITIES  %DEFNS/;
+use vars qw /@CAPABILITIES %CAPABILITIES %DEFNS %FEATURES/;
 for (keys %Geo::OGR::) {
     push(@CAPABILITIES, $1), next if /^OLC(\w+)/;
 }
@@ -322,17 +213,15 @@ for my $s (@CAPABILITIES) {
 }
 
 sub DESTROY {
-    my $self;
-    if ($_[0]->isa('SCALAR')) {
-        $self = $_[0];
-    } else {
-        return unless $_[0]->isa('HASH');
-        $self = tied(%{$_[0]});
+    my $self = shift;
+    unless ($self->isa('SCALAR')) {
+        return unless $self->isa('HASH');
+        $self = tied(%{$self});
         return unless defined $self;
     }
-    if ($Geo::OGR::DataSource::RESULT_SET{$self}) {
-        $Geo::OGR::DataSource::LAYERS{$self}->_ReleaseResultSet($self);
-        delete $Geo::OGR::DataSource::RESULT_SET{$self}
+    if ($Geo::GDAL::Dataset::RESULT_SET{$self}) {
+        $Geo::GDAL::Dataset::LAYERS{$self}->_ReleaseResultSet($self);
+        delete $Geo::GDAL::Dataset::RESULT_SET{$self}
     }
     delete $ITERATORS{$self};
     if (exists $OWNER{$self}) {
@@ -343,7 +232,12 @@ sub DESTROY {
 
 sub RELEASE_PARENTS {
     my $self = shift;
-    delete $Geo::OGR::DataSource::LAYERS{$self};
+    delete $Geo::GDAL::Dataset::LAYERS{$self};
+}
+
+sub Dataset {
+    my $self = shift;
+    return $Geo::GDAL::Dataset::LAYERS{tied(%$self)};
 }
 
 sub Capabilities {
@@ -363,14 +257,14 @@ sub TestCapability {
 
 sub GetDataSource {
     my $self = shift;
-    return $Geo::OGR::DataSource::LAYERS{$self};
+    return $Geo::GDAL::Dataset::LAYERS{tied(%$self)};
 }
 *DataSource = *GetDataSource;
 
 sub GetDefn {
     my $self = shift;
     my $defn = $self->GetLayerDefn;
-    $DEFNS{$defn} = $self;
+    $DEFNS{tied(%$defn)} = $self;
     return $defn;
 }
 
@@ -387,8 +281,8 @@ sub CreateField {
     } else {
         ($params{Defn}) = @_;
     }
-    for (keys %defaults) {
-        $params{$_} = $defaults{$_} unless defined $params{$_};
+    for my $k (keys %defaults) {
+        $params{$k} //= $defaults{$k};
     }
     if (blessed($params{Defn}) and $params{Defn}->isa('Geo::OGR::FieldDefn')) {
         $self->_CreateField($params{Defn}, $params{ApproxOK});
@@ -404,9 +298,11 @@ sub CreateField {
         if (exists $Geo::OGR::FieldDefn::TYPE_STRING2INT{$params{Type}}) {
             my $fd = Geo::OGR::FieldDefn->new(%params);
             _CreateField($self, $fd, $a);
-        } else {
+        } elsif (exists $Geo::OGR::Geometry::TYPE_STRING2INT{$params{Type}}) {
             my $fd = Geo::OGR::GeomFieldDefn->new(%params);
             CreateGeomField($self, $fd, $a);
+        } else {
+            Geo::GDAL::error("Invalid field type: $params{Type}.")
         }
     }
 }
@@ -414,37 +310,26 @@ sub CreateField {
 sub AlterFieldDefn {
     my $self = shift;
     my $field = shift;
-    my $index;
-    eval {
-        $index = $self->GetFieldIndex($field);
-    };
-    confess "Only non-spatial fields can be altered.\n$@" if $@;
+    my $index = $self->GetLayerDefn->GetFieldIndex($field);
     if (blessed($_[0]) and $_[0]->isa('Geo::OGR::FieldDefn')) {
         _AlterFieldDefn($self, $index, @_);
-    } elsif (@_ % 2 == 0) {
-        my %params = @_;
-        my $definition = Geo::OGR::FieldDefn->new(%params);
+    } else {
+        my $params = @_ % 2 == 0 ? {@_} : shift;
+        my $definition = Geo::OGR::FieldDefn->new($params);
         my $flags = 0;
-        $flags |= 1 if exists $params{Name};
-        $flags |= 2 if exists $params{Type};
-        $flags |= 4 if exists $params{Width} or exists $params{Precision};
-        $flags |= 8 if exists $params{Nullable};
-        $flags |= 16 if exists $params{Default};
+        $flags |= 1 if exists $params->{Name};
+        $flags |= 2 if exists $params->{Type};
+        $flags |= 4 if exists $params->{Width} or exists $params->{Precision};
+        $flags |= 8 if exists $params->{Nullable};
+        $flags |= 16 if exists $params->{Default};
         _AlterFieldDefn($self, $index, $definition, $flags);
-    } else {
-        croak "Usage: AlterFieldDefn(\$Name, \%NamedParameters)";
     }
 }
 
 sub DeleteField {
-    my($self, $fn) = @_;
-    my $d = $self->GetDefn;
-    my $index = $d->GetFieldIndex($fn);
-    $index = $fn if $index < 0;
-    eval {
-        _DeleteField($self, $index);
-    };
-    confess "Field not found: '$fn'. Only non-spatial fields can be deleted." if $@;
+    my($self, $field) = @_;
+    my $index = $self->GetLayerDefn->GetFieldIndex($field);
+    _DeleteField($self, $index);
 }
 
 sub GetSchema {
@@ -508,7 +393,7 @@ sub SpatialFilter {
 sub InsertFeature {
     my $self = shift;
     my $feature = shift;
-    confess "Usage: \$feature->InsertFeature(reference to a hash or array)." unless ref($feature);
+    Geo::GDAL::error("Usage: \$feature->InsertFeature(reference to a hash or array).") unless ref($feature);
     my $new = Geo::OGR::Feature->new($self->GetDefn);
     if (ref($feature) eq 'HASH') {
         $new->Row(%$feature);
@@ -518,6 +403,17 @@ sub InsertFeature {
         $new->Row($feature->Row);
     }
     $self->CreateFeature($new);
+    return unless defined wantarray;
+    $FEATURES{tied(%$new)} = $self;
+    return $new;
+}
+
+sub GetFeature {
+    my ($self, $fid) = @_;
+    $fid //= 0;
+    my $f = $self->_GetFeature($fid);
+    $FEATURES{tied(%$f)} = $self;
+    return $f;
 }
 
 sub ForFeatures {
@@ -526,6 +422,7 @@ sub ForFeatures {
     my $in_place = shift;
     $self->ResetReading;
     while (my $f = $self->GetNextFeature) {
+        $FEATURES{tied(%$f)} = $self;
         $code->($f);
         $self->SetFeature($f) if $in_place;
     };
@@ -570,13 +467,14 @@ sub GetFieldDefn {
         my $fd = $d->GetGeomFieldDefn($i);
         return $fd if $fd->Name eq $name;
     }
-    confess "No such field: '$name'.";
+    Geo::GDAL::error(2, $name, 'Field');
 }
 
 sub GeometryType {
     my $self = shift;
-    my $d = $self->GetDefn;
-    my $fd = $d->GetGeomFieldDefn(0);
+    my $field = shift;
+    $field //= 0;
+    my $fd = $self->GetDefn->GetGeomFieldDefn($field);
     return $fd->Type if $fd;
 }
 
@@ -609,6 +507,11 @@ sub RELEASE_PARENTS {
     delete $Geo::OGR::Feature::DEFNS{$self};
     delete $Geo::OGR::Layer::DEFNS{$self};
 }
+
+sub Feature {
+    my $self = shift;
+    return $Geo::OGR::Feature::DEFNS{tied(%$self)};
+}
 %}
 
 %feature("shadow") OGRFeatureDefnShadow(const char* name_null_ok=NULL)
@@ -626,15 +529,15 @@ sub new {
         %schema = @_;
     }
     my $fields = $schema{Fields};
-    confess "The Fields argument is not a reference to an array." if $fields and ref($fields) ne 'ARRAY';
-    $schema{Name} = '' unless exists $schema{Name};
+    Geo::GDAL::error("The 'Fields' argument must be an array reference.") if $fields and ref($fields) ne 'ARRAY';
+    $schema{Name} //= '';
     my $self = Geo::OGRc::new_FeatureDefn($schema{Name});
     bless $self, $pkg;
     my $gt = $schema{GeometryType};
-    if ($fields) {
-        $self->DeleteGeomFieldDefn(0); # either default behavior or argument specified
-    } else {
-        $self->GeometryType($schema{GeometryType}) if exists $schema{GeometryType};
+    if ($gt) {
+        $self->GeometryType($gt);
+    } elsif ($fields) {
+        $self->DeleteGeomFieldDefn(0);
     }
     $self->StyleIgnored($schema{StyleIgnored}) if exists $schema{StyleIgnored};
     for my $fd (@{$fields}) {
@@ -649,9 +552,10 @@ sub new {
         if (blessed($d) and $d->isa('Geo::OGR::FieldDefn')) {
             AddFieldDefn($self, $d);
         } elsif (blessed($d) and $d->isa('Geo::OGR::GeomFieldDefn')) {
+            Geo::GDAL::error("Do not mix GeometryType and geometry fields in Fields.") if $gt;
             AddGeomFieldDefn($self, $d);
         } else {
-            confess "Item in field list does not define a field.";
+            Geo::GDAL::error("Item in field list does not define a field.");
         }
     }
     return $self;
@@ -690,7 +594,7 @@ sub GetSchema {
 
 sub AddField {
     my $self = shift;
-    confess "Read-only definition." if $Geo::OGR::Feature::DEFNS{$self} or $Geo::OGR::Layer::DEFNS{$self};
+    Geo::GDAL::error("Read-only definition.") if $Geo::OGR::Feature::DEFNS{tied(%$self)} || $Geo::OGR::Layer::DEFNS{tied(%$self)};
     my %params;
     if (@_ == 0) {
     } elsif (ref($_[0]) eq 'HASH') {
@@ -698,7 +602,7 @@ sub AddField {
     } elsif (@_ % 2 == 0) {
         %params = @_;
     }
-    $params{Type} = '' unless defined $params{Type};
+    $params{Type} //= '';
     if (exists $Geo::OGR::FieldDefn::TYPE_STRING2INT{$params{Type}}) {
         my $fd = Geo::OGR::FieldDefn->new(%params);
         $self->AddFieldDefn($fd);
@@ -710,14 +614,14 @@ sub AddField {
 
 sub DeleteField {
     my ($self, $name) = @_;
-    confess "Read-only definition." if $Geo::OGR::Feature::DEFNS{$self} or $Geo::OGR::Layer::DEFNS{$self};
+    Geo::GDAL::error("Read-only definition.") if $Geo::OGR::Feature::DEFNS{tied(%$self)} || $Geo::OGR::Layer::DEFNS{tied(%$self)};
     for my $i (0..$self->GetFieldCount-1) {
-        confess "Non-geometry fields cannot be deleted." if $self->GetFieldDefn($i)->Name eq $name;
+        Geo::GDAL::error("Non-geometry fields cannot be deleted.") if $self->GetFieldDefn($i)->Name eq $name;
     }
     for my $i (0..$self->GetGeomFieldCount-1) {
         $self->DeleteGeomFieldDefn($i) if $self->GetGeomFieldDefn($i)->Name eq $name;
     }
-    confess "No such field: '$name'.";
+    Geo::GDAL::error(2, $name, 'Field');
 }
 
 sub GetFieldNames {
@@ -742,15 +646,14 @@ sub GetFieldDefn {
         my $fd = $self->GetGeomFieldDefn($i);
         return $fd if $fd->Name eq $name;
     }
-    confess "No such field: '$name'.";
+    Geo::GDAL::error(2, $name, 'Field');
 }
 
 sub GeomType {
     my ($self, $type) = @_;
-    confess "Read-only definition." if $Geo::OGR::Feature::DEFNS{$self} or $Geo::OGR::Layer::DEFNS{$self};
+    Geo::GDAL::error("Read-only definition.") if $Geo::OGR::Feature::DEFNS{tied(%$self)} || $Geo::OGR::Layer::DEFNS{tied(%$self)};
     if (defined $type) {
-        confess "Unknown geometry data type: '$type'." unless exists $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
-        $type = $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
+        $type = Geo::GDAL::string2int($type, \%Geo::OGR::Geometry::TYPE_STRING2INT);
         SetGeomType($self, $type);
     }
     return $Geo::OGR::Geometry::TYPE_INT2STRING{GetGeomType($self)} if defined wantarray;
@@ -799,23 +702,33 @@ sub new {
 %}
 
 %perlcode %{
+
+sub RELEASE_PARENTS {
+    my $self = shift;
+    delete $Geo::OGR::Layer::FEATURES{$self};
+}
+
+sub Layer {
+    my $self = shift;
+    return $Geo::OGR::Layer::FEATURES{tied(%$self)};
+}
+
 sub FETCH {
     my($self, $index) = @_;
     my $i;
-    eval {$i = $self->_GetFieldIndex($index)};
-    $self->GetField($i) unless $@;
-    $i = $self->_GetGeomFieldIndex($index);
-    $self->GetGeometry($i);
+    eval {$i = $self->GetFieldIndex($index)};
+    return $self->GetField($i) unless $@;
+    Geo::GDAL::error("It is not safe to retrieve geometries from a feature this way.");
 }
 
 sub STORE {
     my $self = shift;
     my $index = shift;
     my $i;
-    eval {$i = $self->_GetFieldIndex($index)};
+    eval {$i = $self->GetFieldIndex($index)};
     $self->SetField($i, @_) unless $@;
-    $i = $self->_GetGeomFieldIndex($index);
-    $self->SetGeometry($i, @_);
+    $i = $self->GetGeomFieldIndex($index);
+    $self->Geometry($i, @_);
 }
 
 sub FID {
@@ -844,7 +757,7 @@ sub Validate {
 
 sub GetSchema {
     my $self = shift;
-    confess "Schema of a feature cannot be set directly." if @_;
+    Geo::GDAL::error("Schema of a feature cannot be set directly.") if @_;
     return $self->GetDefnRef->Schema;
 }
 *Schema = *GetSchema;
@@ -860,14 +773,14 @@ sub Row {
         } elsif (@_ and @_ % 2 == 0) {
             %row = @_;
         } else {
-            confess 'Usage: $feature->Row(%FeatureData).';
+            Geo::GDAL::error('Usage: $feature->Row(%FeatureData).');
         }
         $self->SetFID($row{FID}) if defined $row{FID};
         #$self->Geometry($schema, $row{Geometry}) if $row{Geometry};
         for my $name (keys %row) {
             next if $name eq 'FID';
             if ($name eq 'Geometry') {
-                $self->SetGeometry(0, $row{$name});
+                $self->Geometry(0, $row{$name});
                 next;
             }
             my $f = 0;
@@ -881,13 +794,13 @@ sub Row {
             next if $f;
             for my $i (0..$ngf-1) {
                 if ($self->GetGeomFieldDefnRef($i)->Name eq $name) {
-                    $self->SetGeometry($i, $row{$name});
+                    $self->Geometry($i, $row{$name});
                     $f = 1;
                     last;
                 }
             }
             next if $f;
-            carp "Feature->Row: Unknown field: '$name'.";
+            carp "Unknown field: '$name'.";
         }
     }
     return unless defined wantarray;
@@ -897,12 +810,10 @@ sub Row {
         $row{$name} = $self->GetField($i);
     }
     for my $i (0..$ngf-1) {
-        my $name = $self->GetGeomFieldDefnRef($i)->Name;
-        $name = 'Geometry' if $name eq '';
+        my $name = $self->GetGeomFieldDefnRef($i)->Name || 'Geometry';
         $row{$name} = $self->GetGeometry($i);
     }
     $row{FID} = $self->GetFID;
-    #$row{Geometry} = $self->Geometry;
     return \%row;
 }
 
@@ -917,14 +828,14 @@ sub Tuple {
         my $values = \@_;
         if (@$values != $nf + $ngf) {
             my $n = $nf + $ngf;
-            confess "Too many or too few attribute values for a feature (need $n).";
+            Geo::GDAL::error("Too many or too few attribute values for a feature (need $n).");
         }
         my $index = 0; # index to non-geometry and geometry fields
         for my $i (0..$nf-1) {
             $self->SetField($i, $values->[$i]);
         }
         for my $i (0..$ngf-1) {
-            $self->SetGeometry($i, $values->[$nf+$i]);
+            $self->Geometry($i, $values->[$nf+$i]);
         }
     }
     return unless defined wantarray;
@@ -943,28 +854,17 @@ sub Tuple {
 sub GetDefn {
     my $self = shift;
     my $defn = $self->GetDefnRef;
-    $DEFNS{$defn} = $self;
+    $DEFNS{tied(%$defn)} = $self;
     return $defn;
 }
 
+*GetGeomFieldDefn = *GetGeomFieldDefnRef;
+
 *GetFieldNames = *Geo::OGR::Layer::GetFieldNames;
 *GetFieldDefn = *Geo::OGR::Layer::GetFieldDefn;
 
-sub _GetFieldIndex {
-    my($self, $field) = @_;
-    if ($field =~ /^\d+$/) {
-        return $field if $field >= 0 and $field < $self->GetFieldCount;
-    } else {
-        for my $i (0..$self->GetFieldCount-1) {
-            return $i if $self->GetFieldDefnRef($i)->Name eq $field;
-        }
-    }
-    confess "No such field: '$field'.";
-}
-
 sub GetField {
     my($self, $field) = @_;
-    $field = $self->_GetFieldIndex($field);
     return unless IsFieldSet($self, $field);
     my $type = GetFieldType($self, $field);
     if ($type == $Geo::OGR::OFTInteger) {
@@ -996,7 +896,7 @@ sub GetField {
         return wantarray ? @$ret : $ret;
     }
     if ($type == $Geo::OGR::OFTBinary) {
-        return GetFieldAsString($self, $field);
+        return GetFieldAsBinary($self, $field);
     }
     if ($type == $Geo::OGR::OFTDate) {
         my @ret = GetFieldAsDateTime($self, $field);
@@ -1008,64 +908,61 @@ sub GetField {
         return wantarray ? @ret[3..6] : [@ret[3..6]];
     }
     if ($type == $Geo::OGR::OFTDateTime) {
-        return GetFieldAsDateTime($self, $field);
+        my @ret = GetFieldAsDateTime($self, $field);
+        return wantarray ? @ret : [@ret];
     }
-    confess "Perl bindings do not support field type '$Geo::OGR::FieldDefn::TYPE_INT2STRING{$type}'.";
+    Geo::GDAL::error("Perl bindings do not support field type '$Geo::OGR::FieldDefn::TYPE_INT2STRING{$type}'.");
 }
 
 sub UnsetField {
     my($self, $field) = @_;
-    $field = $self->_GetFieldIndex($field);
     _UnsetField($self, $field);
 }
 
 sub SetField {
     my $self = shift;
     my $field = shift;
-    $field = $self->_GetFieldIndex($field);
-    if (@_ == 0 or !defined($_[0])) {
+    my $arg = $_[0];
+    if (@_ == 0 or !defined($arg)) {
         _UnsetField($self, $field);
         return;
     }
-    my $list = ref($_[0]) ? $_[0] : [@_];
-    my $type = GetFieldType($self, $field);
-    if ($type == $Geo::OGR::OFTInteger or
-        $type == $Geo::OGR::OFTInteger64 or
-        $type == $Geo::OGR::OFTReal or
-        $type == $Geo::OGR::OFTString or
-        $type == $Geo::OGR::OFTBinary)
-    {
-        _SetField($self, $field, $_[0]);
-    }
-    elsif ($type == $Geo::OGR::OFTIntegerList) {
-        SetFieldIntegerList($self, $field, $list);
-    }
-    elsif ($type == $Geo::OGR::OFTInteger64List) {
-        SetFieldInteger64List($self, $field, $list);
-    }
-    elsif ($type == $Geo::OGR::OFTRealList) {
-        SetFieldDoubleList($self, $field, $list);
-    }
-    elsif ($type == $Geo::OGR::OFTStringList) {
-        SetFieldStringList($self, $field, $list);
-    }
-    elsif ($type == $Geo::OGR::OFTDate) {
-        # year, month, day, hour, minute, second, timezone
-        for my $i (0..6) {
-            $list->[$i] = 0 unless defined $list->[$i];
+    $arg = [@_] if @_ > 1;
+    my $type = $self->GetFieldType($field);
+    if (ref($arg)) {
+        if ($type == $Geo::OGR::OFTIntegerList) {
+            SetFieldIntegerList($self, $field, $arg);
+        }
+        elsif ($type == $Geo::OGR::OFTInteger64List) {
+            SetFieldInteger64List($self, $field, $arg);
+        }
+        elsif ($type == $Geo::OGR::OFTRealList) {
+            SetFieldDoubleList($self, $field, $arg);
+        }
+        elsif ($type == $Geo::OGR::OFTStringList) {
+            SetFieldStringList($self, $field, $arg);
+        }
+        elsif ($type == $Geo::OGR::OFTDate) {
+            _SetField($self, $field, @$arg[0..2], 0, 0, 0, 0);
+        }
+        elsif ($type == $Geo::OGR::OFTTime) {
+            $arg->[3] //= 0;
+            _SetField($self, $field, 0, 0, 0, @$arg[0..3]);
+        }
+        elsif ($type == $Geo::OGR::OFTDateTime) {
+            $arg->[6] //= 0;
+            _SetField($self, $field, @$arg[0..6]);
+        }
+        else {
+            _SetField($self, $field, @$arg);
+        }
+    } else {
+        if ($type == $Geo::OGR::OFTBinary) {
+            #$arg = unpack('H*', $arg); # remove when SetFieldBinary is available
+            $self->SetFieldBinary($field, $arg);
+        } else {
+            _SetField($self, $field, $arg);
         }
-        _SetField($self, $field, @$list[0..6]);
-    }
-    elsif ($type == $Geo::OGR::OFTTime) {
-        $list->[3] = 0 unless defined $list->[3];
-        _SetField($self, $field, 0, 0, 0, @$list[0..3]);
-    }
-    elsif ($type == $Geo::OGR::OFTDateTime) {
-        $list->[6] = 0 unless defined $list->[6];
-        _SetField($self, $field, @$list[0..6]);
-    }
-    else {
-        confess "Perl bindings do not support field type '$Geo::OGR::FieldDefn::TYPE_INT2STRING{$type}'.";
     }
 }
 
@@ -1073,63 +970,48 @@ sub Field {
     my $self = shift;
     my $field = shift;
     $self->SetField($field, @_) if @_;
-    $self->GetField($field);
-}
-
-sub _GetGeomFieldIndex {
-    my($self, $field) = @_;
-    if (not defined $field) {
-        return 0 if $self->GetGeomFieldCount > 0;
-    } if ($field =~ /^\d+$/) {
-        return $field if $field >= 0 and $field < $self->GetGeomFieldCount;
-    } else {
-        for my $i (0..$self->GetGeomFieldCount-1) {
-            return $i if $self->GetGeomFieldDefn($i)->Name eq $field;
-        }
-        return 0 if $self->GetGeomFieldCount > 0 and $field eq 'Geometry';
-    }
-    confess "No such field: '$field'.";
+    $self->GetField($field) if defined wantarray;
 }
 
 sub Geometry {
     my $self = shift;
-    my $field = (ref($_[0]) eq '' or (@_ > 2 and @_ % 2 == 1)) ? shift : undef;
-    $field = $self->_GetGeomFieldIndex($field);
-    if (@_) {
+    my $field = ((@_ > 0 and ref($_[0]) eq '') or (@_ > 2 and @_ % 2 == 1)) ? shift : 0;
+    my $geometry;
+    if (@_ and @_ % 2 == 0) {
+        %$geometry = @_;
+    } else {
+        $geometry = shift;
+    }
+    if ($geometry) {
         my $type = $self->GetDefn->GetGeomFieldDefn($field)->Type;
-        my $geometry;
-        if (@_ == 1) {
-            $geometry = $_[0];
-        } elsif (@_ and @_ % 2 == 0) {
-            %$geometry = @_;
-        }
         if (blessed($geometry) and $geometry->isa('Geo::OGR::Geometry')) {
-            confess "The type of the inserted geometry ('".$geometry->GeometryType."') is not the field type ('$type')."
-                if $type ne 'Unknown' and $type ne $geometry->GeometryType;
+            my $gtype = $geometry->GeometryType;
+            Geo::GDAL::error("The type of the inserted geometry ('$gtype') is not the same as the type of the field ('$type').")
+                if $type ne 'Unknown' and $type ne $gtype;
             eval {
-                $self->SetGeomFieldDirectly($field, $geometry);
+                $self->SetGeomFieldDirectly($field, $geometry->Clone);
             };
-            confess "$@" if $@;
-            $GEOMETRIES{tied(%{$geometry})} = $self;
+            confess Geo::GDAL->last_error if $@;
         } elsif (ref($geometry) eq 'HASH') {
-            $geometry->{GeometryType} = $type unless exists $geometry->{GeometryType};
+            $geometry->{GeometryType} //= $type;
             eval {
                 $geometry = Geo::OGR::Geometry->new($geometry);
             };
-            confess "The type of the inserted geometry ('".$geometry->GeometryType."') is not the field type ('$type')."
-                if $type ne 'Unknown' and $type ne $geometry->GeometryType;
+            my $gtype = $geometry->GeometryType;
+            Geo::GDAL::error("The type of the inserted geometry ('$gtype') is not the same as the type of the field ('$type').")
+                if $type ne 'Unknown' and $type ne $gtype;
             eval {
                 $self->SetGeomFieldDirectly($field, $geometry);
             };
-            confess "$@" if $@;
+            confess Geo::GDAL->last_error if $@;
         } else {
-            confess "'@_' does not define a geometry.";
+            Geo::GDAL::error("Usage: \$feature->Geometry([field],[geometry])");
         }
     }
     return unless defined wantarray;
-    my $geometry = $self->GetGeomFieldRef($field);
+    $geometry = $self->GetGeomFieldRef($field);
     return unless $geometry;
-    $GEOMETRIES{tied(%{$geometry})} = $self;
+    $GEOMETRIES{tied(%$geometry)} = $self;
     return $geometry;
 }
 *GetGeometry = *Geometry;
@@ -1203,35 +1085,29 @@ sub JustifyValues {
 use Carp;
 sub new {
     my $pkg = shift;
-    my ($name, $type) = ('unnamed', 'String');
-    my %args;
+    my $params = {Name => 'unnamed', Type => 'String'};
     if (@_ == 0) {
-    } elsif (@_ == 1) {
-        $name = shift;
+    } elsif (@_ == 1 and not ref $_[0]) {
+        $params->{Name} = shift;
     } elsif (@_ == 2 and not $Geo::OGR::FieldDefn::SCHEMA_KEYS{$_[0]}) {
-        $name = shift;
-        $type = shift;
+        $params->{Name} = shift;
+        $params->{Type} = shift;
     } else {
-        my %named = @_;
-        for my $key (keys %named) {
+        my $tmp = @_ % 2 == 0 ? {@_} : shift;
+        for my $key (keys %$tmp) {
             if ($Geo::OGR::FieldDefn::SCHEMA_KEYS{$key}) {
-                $args{$key} = $named{$key};
+                $params->{$key} = $tmp->{$key};
             } else {
-                carp "Unrecognized argument: '$key'.";
+                carp "Unknown parameter: '$key'." if $key ne 'Index';
             }
         }
-        $name = $args{Name} if exists $args{Name};
-        delete $args{Name};
-        $type = $args{Type} if exists $args{Type};
-        delete $args{Type};
-    }
-    confess "Unknown field type: '$type'." unless exists $Geo::OGR::FieldDefn::TYPE_STRING2INT{$type};
-    $type = $Geo::OGR::FieldDefn::TYPE_STRING2INT{$type};
-    my $self = Geo::OGRc::new_FieldDefn($name, $type);
-    if (defined($self)) {
-        bless $self, $pkg;
-        $self->Schema(%args);
     }
+    $params->{Type} = Geo::GDAL::string2int($params->{Type}, \%Geo::OGR::FieldDefn::TYPE_STRING2INT);
+    my $self = Geo::OGRc::new_FieldDefn($params->{Name}, $params->{Type});
+    bless $self, $pkg;
+    delete $params->{Name};
+    delete $params->{Type};
+    $self->Schema($params);
     return $self;
 }
 %}
@@ -1240,10 +1116,11 @@ sub new {
 sub Schema {
     my $self = shift;
     if (@_) {
-        my %args = @_;
+        my $params = @_ % 2 == 0 ? {@_} : shift;
         for my $key (keys %SCHEMA_KEYS) {
-            eval '$self->'.$key.'($args{'.$key.'}) if exists $args{'.$key.'}';
-            croak $@ if $@;
+            next unless exists $params->{$key};
+            eval "\$self->$key(\$params->{$key})";
+            confess(Geo::GDAL->last_error()) if $@;
         }
     }
     return unless defined wantarray;
@@ -1265,7 +1142,7 @@ sub Name {
 sub Type {
     my($self, $type) = @_;
     if (defined $type) {
-        confess "Unknown field type: '$type'." unless exists $TYPE_STRING2INT{$type};
+        Geo::GDAL::error(1, $type, \%TYPE_STRING2INT) unless exists $TYPE_STRING2INT{$type};
         $type = $TYPE_STRING2INT{$type};
         SetType($self, $type);
     }
@@ -1275,7 +1152,7 @@ sub Type {
 sub SubType {
     my($self, $sub_type) = @_;
     if (defined $sub_type) {
-        confess "Unknown field sub type: '$sub_type'." unless exists $SUB_TYPE_STRING2INT{$sub_type};
+        Geo::GDAL::error(1, $sub_type, \%SUB_TYPE_STRING2INT) unless exists $SUB_TYPE_STRING2INT{$sub_type};
         $sub_type = $SUB_TYPE_STRING2INT{$sub_type};
         SetSubType($self, $sub_type);
     }
@@ -1285,7 +1162,7 @@ sub SubType {
 sub Justify {
     my($self, $justify) = @_;
     if (defined $justify) {
-        confess "Unknown justify value: '$justify'." unless exists $JUSTIFY_STRING2INT{$justify};
+        Geo::GDAL::error(1, $justify, \%JUSTIFY_STRING2INT) unless exists $JUSTIFY_STRING2INT{$justify};
         $justify = $JUSTIFY_STRING2INT{$justify} if exists $JUSTIFY_STRING2INT{$justify};
         SetJustify($self, $justify);
     }
@@ -1339,37 +1216,30 @@ use Scalar::Util 'blessed';
 use Carp;
 sub new {
     my $pkg = shift;
-    my ($name, $type) = ('geom', 'Unknown');
-    my %args;
+    my $params = {Name => 'geom', Type => 'Unknown'};
     if (@_ == 0) {
     } elsif (@_ == 1) {
-        $name = shift;
+        $params->{Name} = shift;
     } elsif (@_ == 2 and not $Geo::OGR::GeomFieldDefn::SCHEMA_KEYS{$_[0]}) {
-        $name = shift;
-        $type = shift;
+        $params->{Name} = shift;
+        $params->{Type} = shift;
     } else {
-        my %named = @_;
-        for my $key (keys %named) {
+        my $tmp = @_ % 2 == 0 ? {@_} : shift;
+        for my $key (keys %$tmp) {
             if ($Geo::OGR::GeomFieldDefn::SCHEMA_KEYS{$key}) {
-                $args{$key} = $named{$key};
+                $params->{$key} = $tmp->{$key};
             } else {
-                carp "Unrecognized argument: '$key'.";
+                carp "Unknown parameter: '$key'." if $key ne 'Index' && $key ne 'GeometryType';
             }
         }
-        $name = $args{Name} if exists $args{Name};
-        delete $args{Name};
-        $type = $args{Type} if $args{Type};
-        delete $args{Type};
-        $type = $args{GeometryType} if $args{GeometryType};
-        delete $args{GeometryType};
-    }
-    confess "Unknown geometry type: '$type'." unless exists $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
-    $type = $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
-    my $self = Geo::OGRc::new_GeomFieldDefn($name, $type);
-    if (defined($self)) {
-        bless $self, $pkg;
-        $self->Schema(%args);
+        $params->{Type} //= $tmp->{GeometryType};
     }
+    $params->{Type} = Geo::GDAL::string2int($params->{Type}, \%Geo::OGR::Geometry::TYPE_STRING2INT);
+    my $self = Geo::OGRc::new_GeomFieldDefn($params->{Name}, $params->{Type});
+    bless $self, $pkg;
+    delete $params->{Name};
+    delete $params->{Type};
+    $self->Schema($params);
     return $self;
 }
 %}
@@ -1378,10 +1248,11 @@ sub new {
 sub Schema {
     my $self = shift;
     if (@_) {
-        my %args = @_;
+        my $params = @_ % 2 == 0 ? {@_} : shift;
         for my $key (keys %SCHEMA_KEYS) {
-            eval '$self->'.$key.'($args{'.$key.'}) if exists $args{'.$key.'}';
-            croak $@ if $@;
+            next unless exists $params->{$key};
+            eval "\$self->$key(\$params->{$key})";
+            confess Geo::GDAL->last_error() if $@;
         }
     }
     return unless defined wantarray;
@@ -1403,12 +1274,12 @@ sub Name {
 sub Type {
     my($self, $type) = @_;
     if (defined $type) {
-        confess "Unknown geometry type: '$type'." unless exists $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
-        $type = $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
+        $type = Geo::GDAL::string2int($type, \%Geo::OGR::Geometry::TYPE_STRING2INT);
         SetType($self, $type);
     }
     $Geo::OGR::Geometry::TYPE_INT2STRING{GetType($self)} if defined wantarray;
 }
+*GeometryType = *Type;
 
 sub Types {
   return @Geo::OGR::Geometry::GEOMETRY_TYPES;
@@ -1458,6 +1329,11 @@ for (keys %Geo::OGR::) {
 for my $string (@GEOMETRY_TYPES) {
     my $int = eval "\$Geo::OGR::wkb$string";
     $TYPE_STRING2INT{$string} = $int;
+    if ($string =~ /25D/) {
+        my $s = $string;
+        $s =~ s/25D/Z/;
+        $TYPE_STRING2INT{$s} = $int;
+    }
     $TYPE_INT2STRING{$int} = $string;
 }
 
@@ -1473,6 +1349,11 @@ sub RELEASE_PARENTS {
     my $self = shift;
     delete $Geo::OGR::Feature::GEOMETRIES{$self};
 }
+
+sub Feature {
+    my $self = shift;
+    return $Geo::OGR::Feature::GEOMETRIES{tied(%$self)};
+}
 %}
 
 %feature("shadow") OGRGeometryShadow( OGRwkbGeometryType type = wkbUnknown, char *wkt = 0, int wkb = 0, char *wkb_buf = 0, char *gml = 0 )
@@ -1480,7 +1361,6 @@ sub RELEASE_PARENTS {
 use Carp;
 sub new {
     my $pkg = shift;
-    my ($type, $wkt, $wkb, $gml, $json, $srs, $points, $arc);
     my %param;
     if (@_ == 1 and ref($_[0]) eq 'HASH') {
         %param = %{$_[0]};
@@ -1489,18 +1369,18 @@ sub new {
     } else {
         ($param{GeometryType}) = @_;
     }
-    $type = ($param{type} or $param{Type} or $param{GeometryType});
-    $srs = ($param{srs} or $param{SRS});
-    $wkt = ($param{wkt} or $param{WKT});
-    $wkb = ($param{wkb} or $param{WKB});
-    my $hex = ($param{hexewkb} or $param{HEXEWKB}); # PostGIS HEX EWKB
+    my $type = $param{GeometryType} // $param{Type} // $param{type};
+    my $srs = $param{SRS} // $param{srs};
+    my $wkt = $param{WKT} // $param{wkt};
+    my $wkb = $param{WKB} // $param{wkb};
+    my $hex = $param{HEXEWKB} // $param{HEX_EWKB} // $param{hexewkb} // $param{hex_ewkb};
     my $srid;
     if ($hex) {
-        # get and remove SRID
+        # EWKB contains SRID
         $srid = substr($hex, 10, 8);
         substr($hex, 10, 8) = '';
     } else {
-        $hex = ($param{hexwkb} or $param{HEXWKB});
+        $hex = $param{HEXWKB} // $param{HEX_WKB} // $param{hexwkb} // $param{hex_wkb};
     }
     if ($hex) {
         $wkb = '';
@@ -1508,10 +1388,10 @@ sub new {
             $wkb .= chr(hex(substr($hex,$i,2)));
         }
     }
-    $gml = ($param{gml} or $param{GML});
-    $json = ($param{geojson} or $param{GeoJSON});
-    $points = $param{Points};
-    $arc = ($param{arc} or $param{Arc});
+    my $gml = $param{GML} // $param{gml};
+    my $json = $param{GeoJSON} // $param{geojson} // $param{JSON} // $param{json};
+    my $points = $param{Points} // $param{points};
+    my $arc = $param{Arc} // $param{arc};
     my $self;
     if (defined $wkt) {
         $self = Geo::OGRc::CreateGeometryFromWkt($wkt, $srs);
@@ -1522,14 +1402,14 @@ sub new {
     } elsif (defined $json) {
         $self = Geo::OGRc::CreateGeometryFromJson($json);
     } elsif (defined $type) {
-        confess "Unknown geometry type: '$type'." unless exists $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
-        $type = $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
+        $type = Geo::GDAL::string2int($type, \%Geo::OGR::Geometry::TYPE_STRING2INT);
         $self = Geo::OGRc::new_Geometry($type); # flattens the type
-        SetCoordinateDimension($self, 3) if Geo::OGR::GT_HasZ($type);
+        $self->Set3D(1) if Geo::OGR::GT_HasZ($type);
+        $self->SetMeasured(1) if Geo::OGR::GT_HasM($type);
     } elsif (defined $arc) {
         $self = Geo::OGRc::ApproximateArcAngles(@$arc);
     } else {
-        confess "Missing a parameter when creating a Geo::OGR::Geometry object.";
+        Geo::GDAL::error(1, undef, map {$_=>1} qw/GeometryType WKT WKB HEXEWKB HEXWKB GML GeoJSON Arc/);
     }
     bless $self, $pkg if defined $self;
     $self->Points($points) if $points;
@@ -1546,39 +1426,29 @@ sub ApproximateArcAngles {
                     Rotation => 0,
                     StartAngle => 0,
                     EndAngle => 360,
-                    MaxAngleStepSizeDegrees => 4 
+                    MaxAngleStepSizeDegrees => 4
         );
     for my $p (keys %p) {
         if (exists $default{$p}) {
-            $p{$p} = $default{$p} unless defined $p{$p};
+            $p{$p} //= $default{$p};
         } else {
-            carp "Unknown named parameter: '$p'.";
+            carp "Unknown parameter: '$p'.";
         }
     }
     for my $p (keys %default) {
-        $p{$p} = $default{$p} unless exists $p{$p};
+        $p{$p} //= $default{$p};
     }
-    confess "Usage: Center => [x,y,z]." unless ref($p{Center}) eq 'ARRAY';
+    Geo::GDAL::error("Usage: Center => [x,y,z].") unless ref($p{Center}) eq 'ARRAY';
     for my $i (0..2) {
-        $p{Center}->[$i] = 0 unless defined $p{Center}->[$i];
+        $p{Center}->[$i] //= 0;
     }
     return Geo::OGR::ApproximateArcAngles($p{Center}->[0], $p{Center}->[1], $p{Center}->[2], $p{PrimaryRadius}, $p{SecondaryAxis}, $p{Rotation}, $p{StartAngle}, $p{EndAngle}, $p{MaxAngleStepSizeDegrees});
 }
 
 sub As {
     my $self = shift;
-    my %param;
-    if (@_ == 1 and ref($_[0]) eq 'HASH') {
-        %param = %{$_[0]};
-    } elsif (@_ % 2 == 0) {
-        %param = @_;
-    } else {
-        ($param{Format}, $param{x}) = @_;
-    }
-    $param{ByteOrder} = 'XDR' unless $param{ByteOrder};
-    my $f = $param{Format};
-    my $x = $param{x};
-    $x = $param{ByteOrder} unless defined $x;
+    my $p = Geo::GDAL::named_parameters(\@_, Format => undef, ByteOrder => 'XDR', SRID => undef, Options => undef, AltitudeMode => undef);
+    my $f = $p->{format};
     if ($f =~ /text/i) {
         return $self->AsText;
     } elsif ($f =~ /wkt/i) {
@@ -1588,27 +1458,26 @@ sub As {
             return $self->AsText;
         }
     } elsif ($f =~ /binary/i) {
-        return $self->AsBinary($x);        
+        return $self->ExportToWkb($p->{byteorder});
     } elsif ($f =~ /wkb/i) {
         if ($f =~ /iso/i) {
-            return $self->ExportToIsoWkb;
-        } elsif ($f =~ /hexe/i) {
-            $param{srid} = 'XDR' unless $param{srid};
-            $x = $param{srid} unless defined $x;
-            return $self->AsHEXEWKB($x);
+            $p->{byteorder} = Geo::GDAL::string2int($p->{byteorder}, \%Geo::OGR::Geometry::BYTE_ORDER_STRING2INT);
+            return $self->ExportToIsoWkb($p->{byteorder});
+        } elsif ($f =~ /ewkb/i) {
+            return $self->AsHEXEWKB($p->{srid});
         } elsif ($f =~ /hex/i) {
             return $self->AsHEXWKB;
         } else {
-            return $self->AsBinary($x);
+            return $self->ExportToWkb($p->{byteorder});
         }
     } elsif ($f =~ /gml/i) {
-        return $self->AsGML;
+        return $self->ExportToGML($p->{options});
     } elsif ($f =~ /kml/i) {
-        return $self->AsKML;
+        return $self->ExportToKML($p->{altitudemode});
     } elsif ($f =~ /json/i) {
         return $self->AsJSON;
     } else {
-        confess "Unsupported format: $f.";
+        Geo::GDAL::error(1, $f, map {$_=>1} qw/Text WKT ISO_WKT ISO_WKB HEX_WKB HEX_EWKB Binary GML KML JSON/);
     }
 }
 
@@ -1663,19 +1532,61 @@ sub CoordinateDimension {
     GetCoordinateDimension($self) if defined wantarray;
 }
 
+sub Extent {
+    my $self = shift;
+    return Geo::GDAL::Extent->new($self->GetEnvelope);
+}
+
 sub AddPoint {
-    @_ == 4 ? AddPoint_3D(@_) : AddPoint_2D(@_);
+    my $self = shift;
+    my $t = $self->GetGeometryType;
+    my $has_z = Geo::OGR::GT_HasZ($t);
+    my $has_m = Geo::OGR::GT_HasM($t);
+    if (!$has_z && !$has_m) {
+        $self->AddPoint_2D(@_[0..1]);
+    } elsif ($has_z && !$has_m) {
+        $self->AddPoint_3D(@_[0..2]);
+    } elsif (!$has_z && $has_m) {
+        $self->AddPointM(@_[0..2]);
+    } else {
+        $self->AddPointZM(@_[0..3]);
+    }
 }
 
 sub SetPoint {
-    @_ == 5 ? SetPoint_3D(@_) : SetPoint_2D(@_);
+    my $self = shift;
+    my $t = $self->GetGeometryType;
+    my $has_z = Geo::OGR::GT_HasZ($t);
+    my $has_m = Geo::OGR::GT_HasM($t);
+    if (!$has_z && !$has_m) {
+        $self->SetPoint_2D(@_[0..2]);
+    } elsif ($has_z && !$has_m) {
+        $self->SetPoint_3D(@_[0..3]);
+    } elsif (!$has_z && $has_m) {
+        $self->SetPointM(@_[0..3]);
+    } else {
+        $self->SetPointZM(@_[0..4]);
+    }
 }
 
 sub GetPoint {
     my($self, $i) = @_;
-    $i = 0 unless defined $i;
-    my $point = ($self->GetGeometryType & 0x80000000) == 0 ? GetPoint_2D($self, $i) : GetPoint_3D($self, $i);
-    return @$point;
+    $i //= 0;
+    my $t = $self->GetGeometryType;
+    my $has_z = Geo::OGR::GT_HasZ($t);
+    my $has_m = Geo::OGR::GT_HasM($t);
+    my $point;
+    if (!$has_z && !$has_m) {
+        $point = $self->GetPoint_2D($i);
+    } elsif ($has_z && !$has_m) {
+        $point = $self->GetPoint_3D($i);
+    } elsif (!$has_z && $has_m) {
+        $point = $self->GetPointZM($i);
+        @$point = ($point->[0], $point->[1], $point->[3]);
+    } else {
+        $point = $self->GetPointZM($i);
+    }
+    return wantarray ? @$point : $point;
 }
 
 sub Point {
@@ -1683,105 +1594,101 @@ sub Point {
     my $i;
     if (@_) {
         my $t = $self->GetGeometryType;
-        if ($t == $Geo::OGR::wkbPoint) {
-            shift if @_ > 2;
-            $i = 0;
-        } elsif ($t == $Geo::OGR::wkbPoint25D) {
-            shift if @_ > 3;
-            $i = 0;
-        } else {
-            my $i = shift;
+        my $i;
+        if (Geo::OGR::GT_Flatten($t) == $Geo::OGR::wkbPoint) {
+            my $has_z = Geo::OGR::GT_HasZ($t);
+            my $has_m = Geo::OGR::GT_HasM($t);
+            if (!$has_z && !$has_m) {
+                shift if @_ > 2;
+                $i = 0;
+            } elsif ($has_z || $has_m) {
+                shift if @_ > 3;
+                $i = 0;
+            } else {
+                shift if @_ > 4;
+                $i = 0;
+            }
         }
-        SetPoint($self, $i, @_);
+        $i = shift unless defined $i;
+        $self->SetPoint($i, @_);
     }
-    return GetPoint($self, $i) if defined wantarray;
+    return unless defined wantarray;
+    my $point = $self->GetPoint;
+    return wantarray ? @$point : $point;
 }
 
 sub Points {
     my $self = shift;
     my $t = $self->GetGeometryType;
-    my $flat = not Geo::OGR::GT_HasZ($t);
-    $t = Geo::OGR::GT_Flatten($t);
-    $t = $TYPE_INT2STRING{$t};
+    my $has_z = Geo::OGR::GT_HasZ($t);
+    my $has_m = Geo::OGR::GT_HasM($t);
+    my $postfix = '';
+    $postfix .= 'Z' if Geo::OGR::GT_HasZ($t);
+    $postfix .= 'M' if Geo::OGR::GT_HasM($t);
+    $t = $TYPE_INT2STRING{Geo::OGR::GT_Flatten($t)};
     my $points = shift;
     if ($points) {
         Empty($self);
         if ($t eq 'Unknown' or $t eq 'None' or $t eq 'GeometryCollection') {
-            confess "Can't set points of a geometry of type '$t'.";
+            Geo::GDAL::error("Can't set points of a geometry of type '$t'.");
         } elsif ($t eq 'Point') {
             # support both "Point" as a list of one point and one point
             if (ref($points->[0])) {
-                $flat ?
-                    AddPoint_2D($self, @{$points->[0]}[0..1]) :
-                    AddPoint_3D($self, @{$points->[0]}[0..2]);
+                $self->AddPoint(@{$points->[0]});
             } else {
-                $flat ?
-                    AddPoint_2D($self, @$points[0..1]) :
-                    AddPoint_3D($self, @$points[0..2]);
+                $self->AddPoint(@$points);
             }
-        } elsif ($t eq 'LineString' or $t eq 'LinearRing') {
-            if ($flat) {
-                for my $p (@$points) {
-                    AddPoint_2D($self, @$p[0..1]);
-                }
-            } else{
-                for my $p (@$points) {
-                    AddPoint_3D($self, @$p[0..2]);
-                }
+        } elsif ($t eq 'LineString' or $t eq 'LinearRing' or $t eq 'CircularString') {
+            for my $p (@$points) {
+                $self->AddPoint(@$p);
             }
         } elsif ($t eq 'Polygon') {
             for my $r (@$points) {
                 my $ring = Geo::OGR::Geometry->new('LinearRing');
-                $ring->SetCoordinateDimension(3) unless $flat;
+                $ring->Set3D(1) if $has_z;
+                $ring->SetMeasured(1) if $has_m;
                 $ring->Points($r);
                 $self->AddGeometryDirectly($ring);
             }
         } elsif ($t eq 'MultiPoint') {
             for my $p (@$points) {
-                my $point = Geo::OGR::Geometry->new($flat ? 'Point' : 'Point25D');
+                my $point = Geo::OGR::Geometry->new('Point'.$postfix);
                 $point->Points($p);
                 $self->AddGeometryDirectly($point);
             }
         } elsif ($t eq 'MultiLineString') {
             for my $l (@$points) {
-                my $linestring = Geo::OGR::Geometry->new($flat ? 'LineString' : 'LineString25D');
+                my $linestring = Geo::OGR::Geometry->new('Point'.$postfix);
                 $linestring->Points($l);
                 $self->AddGeometryDirectly($linestring);
             }
         } elsif ($t eq 'MultiPolygon') {
             for my $p (@$points) {
-                my $polygon = Geo::OGR::Geometry->new($flat ? 'Polygon' : 'Polygon25D');
+                my $polygon = Geo::OGR::Geometry->new('Point'.$postfix);
                 $polygon->Points($p);
                 $self->AddGeometryDirectly($polygon);
             }
         }
     }
     return unless defined wantarray;
-    $self->_GetPoints($flat);
+    $self->_GetPoints();
 }
 
 sub _GetPoints {
-    my($self, $flat) = @_;
+    my($self) = @_;
     my @points;
     my $n = $self->GetGeometryCount;
     if ($n) {
         for my $i (0..$n-1) {
-            push @points, $self->GetGeometryRef($i)->_GetPoints($flat);
+            push @points, $self->GetGeometryRef($i)->_GetPoints();
         }
     } else {
         $n = $self->GetPointCount;
         if ($n == 1) {
-            push @points, $flat ? GetPoint_2D($self) : GetPoint_3D($self);
+            push @points, $self->GetPoint;
         } else {
-            my $i;
-            if ($flat) {
-                for my $i (0..$n-1) {
-                    push @points, scalar GetPoint_2D($self, $i);
-                }
-            } else {
-                for my $i (0..$n-1) {
-                    push @points, scalar GetPoint_3D($self, $i);
-                }
+            for my $i (0..$n-1) {
+                push @points, scalar $self->GetPoint($i);
             }
         }
     }
@@ -1790,29 +1697,24 @@ sub _GetPoints {
 
 sub ExportToWkb {
     my($self, $bo) = @_;
-    if (defined $bo) {
-        confess "Unknown byte order: '$bo'." unless exists $BYTE_ORDER_STRING2INT{$bo};
-        $bo = $BYTE_ORDER_STRING2INT{$bo};
-    }
+    $bo = Geo::GDAL::string2int($bo, \%BYTE_ORDER_STRING2INT);
     return _ExportToWkb($self, $bo);
 }
 
 sub ForceTo {
     my $self = shift;
     my $type = shift;
-    confess "Unknown geometry type: '$type'." unless exists $TYPE_STRING2INT{$type};
-    $type = $TYPE_STRING2INT{$type};
+    $type = Geo::GDAL::string2int($type, \%TYPE_STRING2INT);
     eval {
         $self = Geo::OGR::ForceTo($self, $type, @_);
     };
-    confess $@ if $@;
+    confess Geo::GDAL->last_error if $@;
     return $self;
 }
 
 sub ForceToLineString {
     my $self = shift;
-    $self = Geo::OGR::ForceToLineString($self);
-    return $self;
+    return Geo::OGR::ForceToLineString($self);
 }
 
 sub ForceToMultiPoint {
@@ -1879,13 +1781,9 @@ use warnings;
 use Carp;
 
 sub GeometryType {
-    my($type_or_name) = @_;
-    if (defined $type_or_name) {
-        return $Geo::OGR::Geometry::TYPE_STRING2INT{$type_or_name} if
-            exists $Geo::OGR::Geometry::TYPE_STRING2INT{$type_or_name};
-        return $Geo::OGR::Geometry::TYPE_INT2STRING{$type_or_name} if
-            exists $Geo::OGR::Geometry::TYPE_INT2STRING{$type_or_name};
-        confess "Unknown geometry type: '$type_or_name'.";
+    my($type) = @_;
+    if (defined $type) {
+        return Geo::GDAL::string2int($type, \%Geo::OGR::Geometry::TYPE_STRING2INT, \%Geo::OGR::Geometry::TYPE_INT2STRING);
     } else {
         return @Geo::OGR::Geometry::GEOMETRY_TYPES;
     }
@@ -1893,32 +1791,32 @@ sub GeometryType {
 
 sub GeometryTypeModify {
     my($type, $modifier) = @_;
-    confess "Unknown geometry type: '$type'." unless exists $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
+    Geo::GDAL::error(1, $type, \%Geo::OGR::Geometry::TYPE_STRING2INT) unless exists $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
     $type = $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
     return $Geo::OGR::Geometry::TYPE_INT2STRING{GT_Flatten($type)} if $modifier =~ /flat/i;
     return $Geo::OGR::Geometry::TYPE_INT2STRING{GT_SetZ($type)} if $modifier =~ /z/i;
     return $Geo::OGR::Geometry::TYPE_INT2STRING{GT_GetCollection($type)} if $modifier =~ /collection/i;
     return $Geo::OGR::Geometry::TYPE_INT2STRING{GT_GetCurve($type)} if $modifier =~ /curve/i;
     return $Geo::OGR::Geometry::TYPE_INT2STRING{GT_GetLinear($type)} if $modifier =~ /linear/i;
-    confess "Unknown geometry type modifier: '$modifier'.";
+    Geo::GDAL::error(1, $modifier, {Flatten => 1, SetZ => 1, GetCollection => 1, GetCurve => 1, GetLinear => 1});
 }
 
 sub GeometryTypeTest {
     my($type, $test, $type2) = @_;
-    confess "Unknown geometry type: '$type'." unless exists $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
+    Geo::GDAL::error(1, $type, \%Geo::OGR::Geometry::TYPE_STRING2INT) unless exists $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
     $type = $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
     if (defined $type2) {
-        confess "Unknown geometry type: '$type2'." unless exists $Geo::OGR::Geometry::TYPE_STRING2INT{$type2};
+        Geo::GDAL::error(1, $type2, \%Geo::OGR::Geometry::TYPE_STRING2INT) unless exists $Geo::OGR::Geometry::TYPE_STRING2INT{$type2};
         $type2 = $Geo::OGR::Geometry::TYPE_STRING2INT{$type2};
     } else {
-        confess "Usage: GeometryTypeTest(type1, 'is_subclass_of', type2)." if $test =~ /subclass/i;
+        Geo::GDAL::error("Usage: GeometryTypeTest(type1, 'is_subclass_of', type2).") if $test =~ /subclass/i;
     }
     return GT_HasZ($type) if $test =~ /z/i;
     return GT_IsSubClassOf($type, $type2) if $test =~ /subclass/i;
     return GT_IsCurve($type) if $test =~ /curve/i;
     return GT_IsSurface($type) if $test =~ /surface/i;
     return GT_IsNonLinear($type) if $test =~ /linear/i;
-    confess "Unknown geometry type test: '$test'.";
+    Geo::GDAL::error(1, $test, {HasZ => 1, IsSubClassOf => 1, IsCurve => 1, IsSurface => 1, IsNonLinear => 1});
 }
 
 sub RELEASE_PARENTS {
@@ -1927,30 +1825,4 @@ sub RELEASE_PARENTS {
 *ByteOrders = *Geo::OGR::Geometry::ByteOrders;
 *GeometryTypes = *Geo::OGR::Geometry::GeometryTypes;
 
-sub GetDriverNames {
-    my @names;
-    for my $i (0..GetDriverCount()-1) {
-        push @names, _GetDriver($i)->Name;
-    }
-    return @names;
-}
-
-sub Drivers {
-    my @drivers;
-    for my $i (0..GetDriverCount()-1) {
-        push @drivers, _GetDriver($i);
-    }
-    return @drivers;
-}
-
-sub GetDriver {
-    my($name) = @_;
-    $name = 0 unless defined $name;
-    my $driver;
-    $driver = _GetDriver($name) if $name =~ /^\d+$/; # is the name an index to driver list?
-    $driver = GetDriverByName("$name") unless $driver;
-    return $driver if $driver;
-    confess "Driver not found: '$name'. Maybe support for it was not built in?";
-}
-*Driver = *GetDriver;
 %}
diff --git a/swig/include/perl/osr_perl.i b/swig/include/perl/osr_perl.i
index b63b328..fde1115 100644
--- a/swig/include/perl/osr_perl.i
+++ b/swig/include/perl/osr_perl.i
@@ -1,3 +1,4 @@
+%include confess.i
 %include cpl_exceptions.i
 %import typemaps_perl.i
 
@@ -72,43 +73,43 @@ sub new {
     my $pkg = shift;
     my %param = @_;
     my $self = Geo::OSRc::new_SpatialReference();
-    if ($param{WKT}) {
+    if (exists $param{WKT}) {
         ImportFromWkt($self, $param{WKT});
-    } elsif ($param{Text}) {
+    } elsif (exists $param{Text}) {
         ImportFromWkt($self, $param{Text});
-    } elsif ($param{Proj4}) {
+    } elsif (exists $param{Proj4}) {
         ImportFromProj4($self, $param{Proj4});
-    } elsif ($param{ESRI}) {
+    } elsif (exists $param{ESRI}) {
         ImportFromESRI($self, @{$param{ESRI}});
-    } elsif ($param{EPSG}) {
+    } elsif (exists $param{EPSG}) {
         ImportFromEPSG($self, $param{EPSG});
-    } elsif ($param{EPSGA}) {
+    } elsif (exists $param{EPSGA}) {
         ImportFromEPSGA($self, $param{EPSGA});
-    } elsif ($param{PCI}) {
+    } elsif (exists $param{PCI}) {
         ImportFromPCI($self, @{$param{PCI}});
-    } elsif ($param{USGS}) {
+    } elsif (exists $param{USGS}) {
         ImportFromUSGS($self, @{$param{USGS}});
-    } elsif ($param{XML}) {
+    } elsif (exists $param{XML}) {
         ImportFromXML($self, $param{XML});
-    } elsif ($param{GML}) {
+    } elsif (exists $param{GML}) {
         ImportFromGML($self, $param{GML});
-    } elsif ($param{URL}) {
+    } elsif (exists $param{URL}) {
         ImportFromUrl($self, $param{URL});
-    } elsif ($param{ERMapper}) {
+    } elsif (exists $param{ERMapper}) {
         ImportFromERM($self, @{$param{ERMapper}});
-    } elsif ($param{ERM}) {
+    } elsif (exists $param{ERM}) {
         ImportFromERM($self, @{$param{ERM}});
-    } elsif ($param{MICoordSys}) {
+    } elsif (exists $param{MICoordSys}) {
         ImportFromMICoordSys($self, $param{MICoordSys});
-    } elsif ($param{MapInfoCS}) {
+    } elsif (exists $param{MapInfoCS}) {
         ImportFromMICoordSys($self, $param{MapInfoCS});
-    } elsif ($param{WGS}) {
+    } elsif (exists $param{WGS}) {
         eval {
             SetWellKnownGeogCS($self, 'WGS'.$param{WGS});
         };
-        confess "$@" if $@;
+        confess Geo::GDAL->last_error if $@;
     } else {
-        confess "Unrecognized/missing parameters: @_.";
+        Geo::GDAL::error("Unrecognized/missing parameters: @_.");
     }
     bless $self, $pkg if defined $self;
 }
@@ -120,28 +121,23 @@ sub Export {
     my $format;
     $format = pop if @_ == 1;
     my %params = @_;
-    $format = $params{to} unless $format;
-    $format = $params{format} unless $format;
-    $format = $params{as} unless $format;
-    if ($format eq 'WKT' or $format eq 'Text') {
-        return ExportToWkt($self);
-    } elsif ($format eq 'PrettyWKT') {
-        my $simplify = exists $params{simplify} ? $params{simplify} : 0;
-        return ExportToPrettyWkt($self, $simplify);
-    } elsif ($format eq 'Proj4') {
-        return ExportToProj4($self);
-    } elsif ($format eq 'PCI') {            
-        return ExportToPCI($self);
-    } elsif ($format eq 'USGS') {
-        return ExportToUSGS($self);
-    } elsif ($format eq 'GML' or $format eq 'XML') {
-        my $dialect = exists $params{dialect} ? $params{dialect} : '';
-        return ExportToXML($self, $dialect);
-    } elsif ($format eq 'MICoordSys' or $format eq 'MapInfoCS') {
-        return ExportToMICoordSys();
-    } else {
-        confess "Unrecognized export format.";
-    }
+    $format //= $params{to} //= $params{format} //= $params{as} //= '';
+    my $simplify = $params{simplify} // 0;
+    my $dialect = $params{dialect} // '';
+    my %converters = (
+        WKT => sub { return ExportToWkt($self) },
+        Text => sub { return ExportToWkt($self) },
+        PrettyWKT => sub { return ExportToPrettyWkt($self, $simplify) },
+        Proj4 => sub { return ExportToProj4($self) },
+        PCI => sub { return ExportToPCI($self) },
+        USGS => sub { return ExportToUSGS($self) },
+        GML => sub { return ExportToXML($self, $dialect) },
+        XML => sub { return ExportToXML($self, $dialect) },
+        MICoordSys => sub { return ExportToMICoordSys() },
+        MapInfoCS => sub { return ExportToMICoordSys() },
+        );
+    Geo::GDAL::error(1, $format, \%converters) unless $converters{$format};
+    return $converters{$format}->();
 }
 *AsText = *ExportToWkt;
 *As = *Export;
@@ -159,22 +155,22 @@ sub Set {
     } elsif (exists $params{LinearUnits} and exists $params{Value}) {
         SetLinearUnitsAndUpdateParameters($self, $params{LinearUnits}, $params{Value});
     } elsif ($params{Parameter} and exists $params{Value}) {
-        croak "Unknown projection parameter '$params{Parameter}'." unless exists $Geo::OSR::PARAMETERS{$params{Parameter}};
+        Geo::GDAL::error(1, $params{Parameter}, \%Geo::OSR::PARAMETERS) unless exists $Geo::OSR::PARAMETERS{$params{Parameter}};
         $params{Normalized} ?
             SetNormProjParm($self, $params{Parameter}, $params{Value}) :
             SetProjParm($self, $params{Parameter}, $params{Value});
-    } elsif ($params{Name}) {
+    } elsif (exists $params{Name}) {
         SetWellKnownGeogCS($self, $params{Name});
-    } elsif ($params{GuessFrom}) {
+    } elsif (exists $params{GuessFrom}) {
         SetFromUserInput($self, $params{GuessFrom});
-    } elsif ($params{LOCAL_CS}) {
+    } elsif (exists $params{LOCAL_CS}) {
         SetLocalCS($self, $params{LOCAL_CS});
-    } elsif ($params{GeocentricCS}) {
+    } elsif (exists $params{GeocentricCS}) {
         SetGeocCS($self, $params{GeocentricCS});
-    } elsif ($params{VerticalCS} and $params{Datum}) {
+    } elsif (exists $params{VerticalCS} and $params{Datum}) {
         my $type = $params{VertDatumType} || 2005;
         SetVertCS($self, $params{VerticalCS}, $params{Datum}, $type);
-    } elsif ($params{CoordinateSystem}) {
+    } elsif (exists $params{CoordinateSystem}) {
         my @parameters = ();
         @parameters = @{$params{Parameters}} if ref($params{Parameters});
         if ($params{CoordinateSystem} eq 'State Plane' and exists $params{Zone}) {
@@ -194,8 +190,8 @@ sub Set {
         } else {
             SetProjCS($self, $params{CoordinateSystem});
         }
-    } elsif ($params{Projection}) {
-        confess "Unknown projection." unless exists $Geo::OSR::PROJECTIONS{$params{Projection}};
+    } elsif (exists $params{Projection}) {
+        Geo::GDAL::error(1, $params{Projection}, \%Geo::OSR::PROJECTIONS) unless exists $Geo::OSR::PROJECTIONS{$params{Projection}};
         my @parameters = ();
         @parameters = @{$params{Parameters}} if ref($params{Parameters});
         if ($params{Projection} eq 'Albers_Conic_Equal_Area') {
@@ -276,8 +272,7 @@ sub Set {
             SetTMSO($self, @parameters);
         } elsif ($params{Projection} =~ /^Transverse_Mercator/) {
             my($variant) = $params{Projection} =~ /^Transverse_Mercator_(\w+)/;
-            $variant = $params{Variant} unless $variant;
-            $variant = $params{Name} unless $variant;
+            $variant //= $params{Variant} //= $params{Name};
             $variant ?
                 SetTMVariant($self, $variant, @parameters) :
                 SetTM($self, @parameters);
@@ -294,14 +289,14 @@ sub Set {
             SetProjection($self, $params{Projection});
         }
     } else {
-        confess "Not enough information for a spatial reference object.";
+        Geo::GDAL::error("Not enough information to create a spatial reference object.");
     }
 }
 
 sub GetUTMZone {
     my $self = shift;
     my $zone = _GetUTMZone($self);
-    if (wantarray) {            
+    if (wantarray) {
         my $north = 1;
         if ($zone < 0) {
             $zone *= -1;
diff --git a/swig/include/perl/typemaps_perl.i b/swig/include/perl/typemaps_perl.i
index bba700e..42dc3c9 100644
--- a/swig/include/perl/typemaps_perl.i
+++ b/swig/include/perl/typemaps_perl.i
@@ -10,29 +10,69 @@
  */
 %include "typemaps.i"
 
+%include "../../port/cpl_config.h"
+#if defined(WIN32) && defined(_MSC_VER)
+typedef __int64            GIntBig;
+typedef unsigned __int64   GUIntBig;
+#elif HAVE_LONG_LONG
+typedef long long          GIntBig;
+typedef unsigned long long GUIntBig;
+#else
+typedef long               GIntBig;
+typedef unsigned long      GUIntBig;
+#endif
+
 %apply (long *OUTPUT) { long *argout };
 %apply (double *OUTPUT) { double *argout };
 %apply (double *OUTPUT) { double *defaultval };
 
+%fragment("sv_to_utf8_string", "header") %{
+    char *sv_to_utf8_string(SV *sv, U8 **tmpbuf) {
+        /* if tmpbuf, only tmpbuf is freed; if not, ret is freed*/
+        char *ret;
+        if (SvOK(sv)) {
+            STRLEN len;
+            ret = SvPV(sv, len);
+            if (!SvUTF8(sv)) {
+                if (tmpbuf) {
+                    *tmpbuf = bytes_to_utf8((const U8*)ret, &len);
+                    ret = (char *)(*tmpbuf);
+                } else {
+                    ret = (char *)bytes_to_utf8((const U8*)ret, &len);
+                }
+            } else {
+                if (!tmpbuf)
+                    ret = strdup(ret);
+            }
+        } else {
+            ret = (char*)""; /* avoid "Use of uninitialized value in subroutine entry" errors */
+            if (!tmpbuf)
+                ret = strdup(ret);
+        }
+        return ret;
+    }
+    %}
+
 /*
  * double *val, int*hasval, is a special contrived typemap used for
  * the RasterBand GetNoDataValue, GetMinimum, GetMaximum, GetOffset,
  * GetScale methods. The variable hasval is tested and if it is false
  * (meaning, the value is not set in the raster band) then undef is
- * returned in scalar context.  If is is != 0, then the value is
+ * returned in scalar context.  If it is != 0, then the value is
  * coerced into a long and returned in scalar context. In list context
  * the value and hasval are returned. If hasval is zero, the value is
  * "generally the minimum supported value for the data type".
  */
 
 %typemap(in,numinputs=0) (double *val, int *hasval) ( double tmpval, int tmphasval ) {
-  /* %typemap(in,numinputs=0) (double *val, int *hasval) */
-  $1 = &tmpval;
-  $2 = &tmphasval;
-}
+    /* %typemap(in,numinputs=0) (double *val, int *hasval) */
+    $1 = &tmpval;
+    $2 = &tmphasval;
+ }
 %typemap(argout) (double *val, int *hasval) {
     /* %typemap(argout) (double *val, int *hasval) */
     if (GIMME_V == G_ARRAY) {
+        EXTEND(SP, argvi+2-items+1);
         $result = sv_newmortal();
         sv_setnv($result, *$1);
         argvi++;
@@ -48,19 +88,6 @@
     }
 }
 
-%typemap(in) GIntBig
-{
-  /* %typemap(in) GIntBig */
-  $1 = SvIV($input); //FIXME is that right ??
-}
-
-%typemap(out) GIntBig
-{
-  /* %typemap(out) GIntBig */
-  $result = sv_newmortal();
-  sv_setiv($result, (IV) $1);
-  argvi++;
-}
 %typemap(out) const char *
 {
     /* %typemap(out) const char * */
@@ -74,9 +101,10 @@
     /* %typemap(out) char **CSL */
     if (GIMME_V == G_ARRAY) {
         if ($1) {
+            int n = CSLCount($1);
+            EXTEND(SP, argvi+n-items+1);
             int i;
             for (i = 0; $1[i]; i++) {
-                if (argvi > items-1) EXTEND(SP, 1);
                 SV *sv = newSVpv($1[i], 0);
                 SvUTF8_on(sv); /* expecting GDAL to give us UTF-8 */
                 ST(argvi++) = sv_2mortal(sv);
@@ -88,10 +116,9 @@
         if ($1) {
             int i;
             for (i = 0; $1[i]; i++) {
-              SV *sv = newSVpv($1[i], 0);
-              SvUTF8_on(sv); /* expecting GDAL to give us UTF-8 */
-              if (!av_store(av, i, sv))
-                SvREFCNT_dec(sv);
+                SV *sv = newSVpv($1[i], 0);
+                SvUTF8_on(sv); /* expecting GDAL to give us UTF-8 */
+                av_push(av, sv);
             }
             CSLDestroy($1);
         }
@@ -103,35 +130,34 @@
 %typemap(out) (char **CSL_REF)
 {
     /* %typemap(out) char **CSL_REF */
-  AV *av = (AV*)sv_2mortal((SV*)newAV());
-  if ($1) {
-    int i;
-    for (i = 0; $1[i]; i++) {
-      SV *sv = newSVpv($1[i], 0);
-      SvUTF8_on(sv); /* expecting GDAL to give us UTF-8 */
-      if (!av_store(av, i, sv))
-        SvREFCNT_dec(sv);
+    AV *av = (AV*)sv_2mortal((SV*)newAV());
+    if ($1) {
+        int i;
+        for (i = 0; $1[i]; i++) {
+            SV *sv = newSVpv($1[i], 0);
+            SvUTF8_on(sv); /* expecting GDAL to give us UTF-8 */
+            av_push(av, sv);
+        }
+        CSLDestroy($1);
     }
-    CSLDestroy($1);
-  }
-  $result = newRV((SV*)av);
-  sv_2mortal($result);
-  argvi++;
+    $result = newRV((SV*)av);
+    sv_2mortal($result);
+    argvi++;
 }
 %typemap(out) (char **free)
 {
-  /* %typemap(out) char **free */
-  AV *av = (AV*)sv_2mortal((SV*)newAV());
-  if ($1) {
-    int i;
-    for (i = 0; $1[i]; i++) {
-      av_store(av, i, newSVpv($1[0], 0));
+    /* %typemap(out) char **free */
+    AV *av = (AV*)sv_2mortal((SV*)newAV());
+    if ($1) {
+        int i;
+        for (i = 0; $1[i]; i++) {
+            av_store(av, i, newSVpv($1[0], 0));
+        }
+        CPLFree($1);
     }
-    CPLFree($1);
-  }
-  $result = newRV((SV*)av);
-  sv_2mortal($result);
-  argvi++;
+    $result = newRV((SV*)av);
+    sv_2mortal($result);
+    argvi++;
 }
 
 /* typemaps for VSI_RETVAL */
@@ -139,15 +165,15 @@
 /* drop GDAL return value */
 %typemap(out) VSI_RETVAL
 {
-  /* %typemap(out) VSI_RETVAL */
+    /* %typemap(out) VSI_RETVAL */
 }
 /* croak if GDAL returns -1 */
 %typemap(ret) VSI_RETVAL
 {
- /* %typemap(ret) VSI_RETVAL */
-  if ($1 == -1 ) {
-    croak("%s", strerror(errno));
-  }
+    /* %typemap(ret) VSI_RETVAL */
+    if ($1 == -1 ) {
+        do_confess(strerror(errno), 1);
+    }
 }
 
 /* typemaps for IF_FALSE_RETURN_NONE */
@@ -155,42 +181,29 @@
 /* drop GDAL return value */
 %typemap(out) IF_FALSE_RETURN_NONE
 {
-  /* %typemap(out) IF_FALSE_RETURN_NONE */
+    /* %typemap(out) IF_FALSE_RETURN_NONE */
 }
 /* croak if GDAL return FALSE */
 %typemap(ret) IF_FALSE_RETURN_NONE
 {
- /* %typemap(ret) IF_FALSE_RETURN_NONE */
-  if ($1 == 0 ) {
-    SWIG_croak("unexpected error in '$symname'");
-  }
-}
-/* drop GDAL return value */
-%typemap(out) RETURN_NONE_TRUE_IS_ERROR
-{
-  /* %typemap(out) RETURN_NONE_TRUE_IS_ERROR */
-}
-/* croak if GDAL return TRUE */
-%typemap(ret) RETURN_NONE_TRUE_IS_ERROR
-{
- /* %typemap(ret) RETURN_NONE_TRUE_IS_ERROR */
-  if ($1 != 0 ) {
-    SWIG_croak("unexpected error in '$symname'");
-  }
+    /* %typemap(ret) IF_FALSE_RETURN_NONE */
+    if ($1 == 0 ) {
+        do_confess(CALL_FAILED, 1);
+    }
 }
 /* drop GDAL return value */
 %typemap(out) IF_ERROR_RETURN_NONE
 {
-  /* %typemap(out) IF_ERROR_RETURN_NONE */
+    /* %typemap(out) IF_ERROR_RETURN_NONE */
 }
 %typemap(out) CPLErr
 {
-  /* %typemap(out) CPLErr */
+    /* %typemap(out) CPLErr */
 }
 /* return value is really void or prepared by typemaps, avoids unnecessary sv_newmortal */
 %typemap(out) void
 {
-  /* %typemap(out) void */
+    /* %typemap(out) void */
 }
 
 /*
@@ -203,7 +216,7 @@
  *
  *    The function assumes that vector points to three consecutive doubles.
  *    This can be wrapped using:
- * 
+ *
  *    %apply (double_3 argin) { (double *vector) };
  *    FunctionOfDouble3( double *vector );
  *    %clear (double *vector);
@@ -226,248 +239,284 @@
  *    %apply (double_17 *argoug) { (double **vector) };
  *    ReturnVector17( double **vector );
  *    %clear ( double **vector );
- *   
+ *
  *    Example:  SpatialReference.ExportToPCI().
  *
  */
 
 %fragment("CreateArrayFromIntArray","header") %{
-static SV *
-CreateArrayFromIntArray( int *first, unsigned int size ) {
-  AV *av = (AV*)sv_2mortal((SV*)newAV());
-  for( unsigned int i=0; i<size; i++ ) {
-    av_store(av,i,newSViv(*first));
-    ++first;
-  }
-  return sv_2mortal(newRV((SV*)av));
-}
-%}
+    static SV *
+        CreateArrayFromIntArray( int *first, unsigned int size ) {
+        AV *av = (AV*)sv_2mortal((SV*)newAV());
+        for( unsigned int i=0; i<size; i++ ) {
+            av_store(av,i,newSViv(*first));
+            ++first;
+        }
+        return sv_2mortal(newRV((SV*)av));
+    }
+    %}
+
+%fragment("CreateArrayFromGIntBigArray","header") %{
+#define LENGTH_OF_GIntBig_AS_STRING 30
+    static SV *
+        CreateArrayFromGIntBigArray( GIntBig *first, unsigned int size ) {
+        AV *av = (AV*)sv_2mortal((SV*)newAV());
+        for( unsigned int i=0; i<size; i++ ) {
+            char s[LENGTH_OF_GIntBig_AS_STRING];
+            snprintf(s, LENGTH_OF_GIntBig_AS_STRING-1, CPL_FRMT_GIB, *first);
+            av_store(av,i,newSVpv(s, 0));
+            ++first;
+        }
+        return sv_2mortal(newRV((SV*)av));
+    }
+    %}
 
 %fragment("CreateArrayFromGUIntBigArray","header") %{
 #define LENGTH_OF_GUIntBig_AS_STRING 30
-static SV *
-CreateArrayFromGUIntBigArray( GUIntBig *first, unsigned int size ) {
-  AV *av = (AV*)sv_2mortal((SV*)newAV());
-  for( unsigned int i=0; i<size; i++ ) {
-    char s[LENGTH_OF_GUIntBig_AS_STRING];
-    snprintf(s, LENGTH_OF_GUIntBig_AS_STRING-1, CPL_FRMT_GUIB, *first);
-    av_store(av,i,newSVpv(s, 0));
-    ++first;
-  }
-  return sv_2mortal(newRV((SV*)av));
-}
-%}
+    static SV *
+        CreateArrayFromGUIntBigArray( GUIntBig *first, unsigned int size ) {
+        AV *av = (AV*)sv_2mortal((SV*)newAV());
+        for( unsigned int i=0; i<size; i++ ) {
+            char s[LENGTH_OF_GUIntBig_AS_STRING];
+            snprintf(s, LENGTH_OF_GUIntBig_AS_STRING-1, CPL_FRMT_GUIB, *first);
+            av_store(av,i,newSVpv(s, 0));
+            ++first;
+        }
+        return sv_2mortal(newRV((SV*)av));
+    }
+    %}
 
 %fragment("CreateArrayFromDoubleArray","header") %{
-static SV *
-CreateArrayFromDoubleArray( double *first, unsigned int size ) {
-  AV *av = (AV*)sv_2mortal((SV*)newAV());
-  for( unsigned int i=0; i<size; i++ ) {
-    av_store(av,i,newSVnv(*first));
-    ++first;
-  }
-  return sv_2mortal(newRV((SV*)av));
-}
-%}
+    static SV *
+        CreateArrayFromDoubleArray( double *first, unsigned int size ) {
+        AV *av = (AV*)sv_2mortal((SV*)newAV());
+        for( unsigned int i=0; i<size; i++ ) {
+            av_store(av,i,newSVnv(*first));
+            ++first;
+        }
+        return sv_2mortal(newRV((SV*)av));
+    }
+    %}
 
 %fragment("CreateArrayFromStringArray","header") %{
-static SV *
-CreateArrayFromStringArray( char **first ) {
-  AV *av = (AV*)sv_2mortal((SV*)newAV());
-  for( unsigned int i = 0; *first != NULL; i++ ) {
-    SV *sv = newSVpv(*first, strlen(*first));
-    SvUTF8_on(sv); /* expecting UTF-8 from GDAL */
-    av_store(av,i,sv);
-    ++first;
-  }
-  return sv_2mortal(newRV((SV*)av));
-}
-%}
+    static SV *
+        CreateArrayFromStringArray( char **first ) {
+        AV *av = (AV*)sv_2mortal((SV*)newAV());
+        for( unsigned int i = 0; *first != NULL; i++ ) {
+            SV *sv = newSVpv(*first, strlen(*first));
+            SvUTF8_on(sv); /* expecting UTF-8 from GDAL */
+            av_store(av,i,sv);
+            ++first;
+        }
+        return sv_2mortal(newRV((SV*)av));
+    }
+    %}
 
 /* typemaps for (int *nLen, const int **pList) */
 
 %typemap(in,numinputs=0) (int *nLen, const int **pList) (int nLen, int *pList)
 {
-  /* %typemap(in,numinputs=0) (int *nLen, const int **pList) */
-  $1 = &nLen;
-  $2 = &pList;
+    /* %typemap(in,numinputs=0) (int *nLen, const int **pList) */
+    $1 = &nLen;
+    $2 = &pList;
 }
 %typemap(argout,fragment="CreateArrayFromIntArray") (int *nLen, const int **pList)
 {
-  /* %typemap(argout) (int *nLen, const int **pList) */
-  $result = CreateArrayFromIntArray( *($2), *($1) );
-  argvi++;
+    /* %typemap(argout) (int *nLen, const int **pList) */
+    $result = CreateArrayFromIntArray( *($2), *($1) );
+    argvi++;
+}
+
+/* typemaps for (int *nLen, const GIntBig **pList) */
+
+%typemap(in,numinputs=0) (int *nLen, const GIntBig **pList) (int nLen, GIntBig *pList)
+{
+    /* %typemap(in,numinputs=0) (int *nLen, const GIntBig **pList) */
+    $1 = &nLen;
+    $2 = &pList;
+}
+%typemap(argout,fragment="CreateArrayFromGIntBigArray") (int *nLen, const GIntBig **pList)
+{
+    /* %typemap(argout) (int *nLen, const GIntBig **pList) */
+    $result = CreateArrayFromGIntBigArray( *($2), *($1) );
+    argvi++;
 }
 
 /* typemaps for (int *nLen, const GUIntBig **pList) */
 
 %typemap(in,numinputs=0) (int *nLen, const GUIntBig **pList) (int nLen, GUIntBig *pList)
 {
-  /* %typemap(in,numinputs=0) (int *nLen, const GUIntBig **pList) */
-  $1 = &nLen;
-  $2 = &pList;
+    /* %typemap(in,numinputs=0) (int *nLen, const GUIntBig **pList) */
+    $1 = &nLen;
+    $2 = &pList;
 }
 %typemap(argout,fragment="CreateArrayFromGUIntBigArray") (int *nLen, const GUIntBig **pList)
 {
-  /* %typemap(argout) (int *nLen, const GUIntBig **pList) */
-  $result = CreateArrayFromGUIntBigArray( *($2), *($1) );
-  argvi++;
+    /* %typemap(argout) (int *nLen, const GUIntBig **pList) */
+    $result = CreateArrayFromGUIntBigArray( *($2), *($1) );
+    argvi++;
 }
 
 /* typemaps for (int len, int *output) */
 
 %typemap(in,numinputs=1) (int len, int *output)
 {
-  /* %typemap(in,numinputs=1) (int len, int *output) */
-  $1 = SvIV($input);
+    /* %typemap(in,numinputs=1) (int len, int *output) */
+    $1 = SvIV($input);
 }
 %typemap(check) (int len, int *output)
 {
-  /* %typemap(check) (int len, int *output) */
-  if ($1 < 1) $1 = 1; /* stop idiocy */
-  $2 = (int *)CPLMalloc( $1 * sizeof(int) );
-    
+    /* %typemap(check) (int len, int *output) */
+    if ($1 < 1) $1 = 1; /* stop idiocy */
+    $2 = (int *)CPLMalloc( $1 * sizeof(int) );
+
 }
 %typemap(argout,fragment="CreateArrayFromIntArray") (int len, int *output)
 {
-  /* %typemap(argout) (int len, int *output) */
-  if (GIMME_V == G_ARRAY) {
-    /* return a list */
-    int i;
-    EXTEND(SP, argvi+$1-items+1);
-    for (i = 0; i < $1; i++)
-      ST(argvi++) = sv_2mortal(newSViv($2[i]));
-  } else {
-    $result = CreateArrayFromIntArray( $2, $1 );
-    argvi++;
-  }
+    /* %typemap(argout) (int len, int *output) */
+    if (GIMME_V == G_ARRAY) {
+        /* return a list */
+        int i;
+        EXTEND(SP, argvi+$1-items+1);
+        for (i = 0; i < $1; i++)
+            ST(argvi++) = sv_2mortal(newSViv($2[i]));
+    } else {
+        $result = CreateArrayFromIntArray( $2, $1 );
+        argvi++;
+    }
 }
 %typemap(freearg) (int len, int *output)
 {
-  /* %typemap(freearg) (int len, int *output) */
-  CPLFree($2);
+    /* %typemap(freearg) (int len, int *output) */
+    CPLFree($2);
 }
 
 /* typemaps for (int len, GUIntBig *output) */
 
 %typemap(in,numinputs=1) (int len, GUIntBig *output)
 {
-  /* %typemap(in,numinputs=1) (int len, GUIntBig *output) */
-  $1 = SvIV($input);
+    /* %typemap(in,numinputs=1) (int len, GUIntBig *output) */
+    $1 = SvIV($input);
 }
 %typemap(check) (int len, GUIntBig *output)
 {
-  /* %typemap(check) (int len, GUIntBig *output) */
-  if ($1 < 1) $1 = 1; /* stop idiocy */
-  $2 = (GUIntBig*)CPLMalloc( $1 * sizeof(GUIntBig) );
-    
+    /* %typemap(check) (int len, GUIntBig *output) */
+    if ($1 < 1) $1 = 1; /* stop idiocy */
+    $2 = (GUIntBig*)CPLMalloc( $1 * sizeof(GUIntBig) );
+
 }
 %typemap(argout,fragment="CreateArrayFromGUIntBigArray") (int len, GUIntBig *output)
 {
-  /* %typemap(argout) (int len, GUIntBig *output) */
-  if (GIMME_V == G_ARRAY) {
-    /* return a list */
-    int i;
-    EXTEND(SP, argvi+$1-items+1);
-    for (i = 0; i < $1; i++) {
-      char s[LENGTH_OF_GUIntBig_AS_STRING];
-      snprintf(s, LENGTH_OF_GUIntBig_AS_STRING-1, CPL_FRMT_GUIB, $2[i]);
-      ST(argvi++) = sv_2mortal(newSVpv(s, 0));
+    /* %typemap(argout) (int len, GUIntBig *output) */
+    if (GIMME_V == G_ARRAY) {
+        /* return a list */
+        int i;
+        EXTEND(SP, argvi+$1-items+1);
+        for (i = 0; i < $1; i++) {
+            char s[LENGTH_OF_GUIntBig_AS_STRING];
+            snprintf(s, LENGTH_OF_GUIntBig_AS_STRING-1, CPL_FRMT_GUIB, $2[i]);
+            ST(argvi++) = sv_2mortal(newSVpv(s, 0));
+        }
+    } else {
+        $result = CreateArrayFromGUIntBigArray( $2, $1 );
+        argvi++;
     }
-  } else {
-    $result = CreateArrayFromGUIntBigArray( $2, $1 );
-    argvi++;
-  }
 }
 %typemap(freearg) (int len, GUIntBig *output)
 {
-  /* %typemap(freearg) (int len, GUIntBig *output) */
-  CPLFree($2);
+    /* %typemap(freearg) (int len, GUIntBig *output) */
+    CPLFree($2);
 }
 
 /* typemaps for (int nLen, double *pList) */
 
 %typemap(in,numinputs=0) (int *nLen, const double **pList) (int nLen, double *pList)
 {
-  /* %typemap(in,numinputs=0) (int *nLen, const double **pList) */
-  $1 = &nLen;
-  $2 = &pList;
+    /* %typemap(in,numinputs=0) (int *nLen, const double **pList) */
+    $1 = &nLen;
+    $2 = &pList;
 }
 %typemap(argout,fragment="CreateArrayFromDoubleArray") (int *nLen, const double **pList)
 {
-  /* %typemap(argout) (int *nLen, const double **pList) */
-  $result = CreateArrayFromDoubleArray( *($2), *($1) );
-  argvi++;
+    /* %typemap(argout) (int *nLen, const double **pList) */
+    $result = CreateArrayFromDoubleArray( *($2), *($1) );
+    argvi++;
 }
 
 %typemap(in,numinputs=0) (char ***pList) (char **pList)
 {
-  /* %typemap(in,numinputs=0) (char ***pList) */
-  $1 = &pList;
+    /* %typemap(in,numinputs=0) (char ***pList) */
+    $1 = &pList;
 }
 %typemap(argout,fragment="CreateArrayFromStringArray") (char ***pList)
 {
-  /* %typemap(argout) (char ***pList) */
-  $result = CreateArrayFromStringArray( *($1) );
-  argvi++;
+    /* %typemap(argout) (char ***pList) */
+    $result = CreateArrayFromStringArray( *($1) );
+    argvi++;
 }
 
 %typemap(in,numinputs=0) ( double argout[ANY]) (double argout[$dim0])
 {
-  /* %typemap(in,numinputs=0) (double argout[ANY]) */
-  $1 = argout;
+    /* %typemap(in,numinputs=0) (double argout[ANY]) */
+    $1 = argout;
 }
 %typemap(argout,fragment="CreateArrayFromDoubleArray") ( double argout[ANY])
 {
-  /* %typemap(argout) (double argout[ANY]) */
-  if (GIMME_V == G_ARRAY) {
-    /* return a list */
-    int i;
-    EXTEND(SP, argvi+$dim0-items+1);
-    for (i = 0; i < $dim0; i++)
-      ST(argvi++) = sv_2mortal(newSVnv($1[i]));
-  } else {
-    $result = CreateArrayFromDoubleArray( $1, $dim0 );
-    argvi++;
-  }  
+    /* %typemap(argout) (double argout[ANY]) */
+    if (GIMME_V == G_ARRAY) {
+        /* return a list */
+        int i;
+        EXTEND(SP, argvi+$dim0-items+1);
+        for (i = 0; i < $dim0; i++)
+            ST(argvi++) = sv_2mortal(newSVnv($1[i]));
+    } else {
+        $result = CreateArrayFromDoubleArray( $1, $dim0 );
+        argvi++;
+    }
 }
 
 %typemap(in,numinputs=0) ( double *argout[ANY]) (double *argout)
 {
-  /* %typemap(in,numinputs=0) (double *argout[ANY]) */
-  $1 = &argout;
+    /* %typemap(in,numinputs=0) (double *argout[ANY]) */
+    $1 = &argout;
 }
 %typemap(argout,fragment="CreateArrayFromDoubleArray") ( double *argout[ANY])
 {
-  /* %typemap(argout) (double *argout[ANY]) */
-  $result = CreateArrayFromDoubleArray( *$1, $dim0 );
-  argvi++;
+    /* %typemap(argout) (double *argout[ANY]) */
+    $result = CreateArrayFromDoubleArray( *$1, $dim0 );
+    argvi++;
 }
 %typemap(freearg) (double *argout[ANY])
 {
-  /* %typemap(freearg) (double *argout[ANY]) */
-  CPLFree(*$1);
+    /* %typemap(freearg) (double *argout[ANY]) */
+    CPLFree(*$1);
 }
 %typemap(in) (double argin[ANY]) (double argin[$dim0])
 {
     /* %typemap(in) (double argin[ANY]) */
     if (!(SvROK($input) && (SvTYPE(SvRV($input))==SVt_PVAV)))
-        SWIG_croak("Expected a reference to an array.");
+        do_confess(NEED_ARRAY_REF, 1);
     $1 = argin;
     AV *av = (AV*)(SvRV($input));
     for (unsigned int i=0; i<$dim0; i++) {
-        SV **sv = av_fetch(av, i, 0);
-        $1[i] =  SvNV(*sv);
+        SV *sv = *av_fetch(av, i, 0);
+        if (!SvOK(sv))
+            do_confess(NEED_DEF, 1);
+        $1[i] =  SvNV(sv);
     }
 }
 
 /* typemaps for (int nList, int* pList) */
 
+%typemap(typecheck, precedence=SWIG_TYPECHECK_INTEGER) int nList, int* pList {
+    /* %typemap(typecheck, precedence=SWIG_TYPECHECK_INTEGER) int nList, int* pList */
+   $1 = 1;
+}
 %typemap(in,numinputs=1) (int nList, int* pList)
 {
     /* %typemap(in,numinputs=1) (int nList, int* pList) */
     if (!(SvROK($input) && (SvTYPE(SvRV($input))==SVt_PVAV)))
-        SWIG_croak("Expected a reference to an array.");
+        do_confess(NEED_ARRAY_REF, 1);
     AV *av = (AV*)(SvRV($input));
     $1 = av_len(av)+1;
     $2 = (int*)CPLMalloc($1*sizeof(int));
@@ -485,13 +534,45 @@ CreateArrayFromStringArray( char **first ) {
     CPLFree((void*) $2);
 }
 
+/* typemaps for (int nList, GIntBig* pList) */
+
+%typemap(typecheck, precedence=SWIG_TYPECHECK_INTEGER) int nList, GIntBig* pList {
+    /* %typemap(typecheck, precedence=SWIG_TYPECHECK_INTEGER) int nList, GIntBig* pList */
+   $1 = 1;
+}
+%typemap(in,numinputs=1) (int nList, GIntBig* pList)
+{
+    /* %typemap(in,numinputs=1) (int nList, GIntBig* pList) */
+    if (!(SvROK($input) && (SvTYPE(SvRV($input))==SVt_PVAV)))
+        do_confess(NEED_ARRAY_REF, 1);
+    AV *av = (AV*)(SvRV($input));
+    $1 = av_len(av)+1;
+    $2 = (GIntBig*)CPLMalloc($1*sizeof(GIntBig));
+    if ($2) {
+        for( int i = 0; i<$1; i++ ) {
+            SV **sv = av_fetch(av, i, 0);
+            $2[i] =  strtoull(SvPV_nolen(*sv), NULL, 10);
+        }
+    } else
+        SWIG_fail;
+}
+%typemap(freearg) (int nList, GIntBig* pList)
+{
+    /* %typemap(freearg) (int nList, GIntBig* pList) */
+    CPLFree((void*) $2);
+}
+
 /* typemaps for (int nList, GUIntBig* pList) */
 
+%typemap(typecheck, precedence=SWIG_TYPECHECK_INTEGER) int nList, GUIntBig* pList {
+    /* %typemap(typecheck, precedence=SWIG_TYPECHECK_INTEGER) int nList, GUIntBig* pList */
+   $1 = 1;
+}
 %typemap(in,numinputs=1) (int nList, GUIntBig* pList)
 {
     /* %typemap(in,numinputs=1) (int nList, GUIntBig* pList) */
     if (!(SvROK($input) && (SvTYPE(SvRV($input))==SVt_PVAV)))
-        SWIG_croak("Expected a reference to an array.");
+        do_confess(NEED_ARRAY_REF, 1);
     AV *av = (AV*)(SvRV($input));
     $1 = av_len(av)+1;
     $2 = (GUIntBig*)CPLMalloc($1*sizeof(GUIntBig));
@@ -515,7 +596,7 @@ CreateArrayFromStringArray( char **first ) {
 {
     /* %typemap(in,numinputs=1) (int nList, double* pList) */
     if (!(SvROK($input) && (SvTYPE(SvRV($input))==SVt_PVAV)))
-        SWIG_croak("Expected a reference to an array.");
+        do_confess(NEED_ARRAY_REF, 1);
     AV *av = (AV*)(SvRV($input));
     $1 = av_len(av)+1;
     $2 = (double*)CPLMalloc($1*sizeof(double));
@@ -533,26 +614,6 @@ CreateArrayFromStringArray( char **first ) {
     CPLFree((void*) $2);
 }
 
-%typemap(in) (char **pList)
-{
-    /* %typemap(in) (char **pList) */
-    if (!(SvROK($input) && (SvTYPE(SvRV($input))==SVt_PVAV)))
-        SWIG_croak("Expected a reference to an array.");
-    AV *av = (AV*)(SvRV($input));
-    for (int i = 0; i < av_len(av)+1; i++) {
-        SV *sv = *(av_fetch(av, i, 0));
-        sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-        char *pszItem = SvPV_nolen(sv);
-        $1 = CSLAddString( $1, pszItem );
-    }
-}
-%typemap(freearg) (char **pList)
-{
-    /* %typemap(freearg) (char **pList) */
-    if ($1)
-        CSLDestroy( $1 );
-}
-
 %typemap(in,numinputs=1) (int defined, double value)
 {
     /* %typemap(in,numinputs=1) (int defined, double value) */
@@ -569,31 +630,53 @@ CreateArrayFromStringArray( char **first ) {
  */
 %typemap(in,numinputs=0) (int *nLen, char **pBuf ) ( int nLen = 0, char *pBuf = 0 )
 {
-  /* %typemap(in,numinputs=0) (int *nLen, char **pBuf ) */
-  $1 = &nLen;
-  $2 = &pBuf;
+    /* %typemap(in,numinputs=0) (int *nLen, char **pBuf ) */
+    $1 = &nLen;
+    $2 = &pBuf;
 }
 %typemap(argout) (int *nLen, char **pBuf )
 {
-  /* %typemap(argout) (int *nLen, char **pBuf ) */
-  $result = sv_2mortal(newSVpv( *$2, *$1 ));
-  argvi++;
+    /* %typemap(argout) (int *nLen, char **pBuf ) */
+    $result = sv_2mortal(newSVpv( *$2, *$1 ));
+    argvi++;
 }
 %typemap(freearg) (int *nLen, char **pBuf )
 {
-  /* %typemap(freearg) (int *nLen, char **pBuf ) */
-  if( *$1 ) {
-    free( *$2 );
-  }
+    /* %typemap(freearg) (int *nLen, char **pBuf ) */
+    if( *$1 ) {
+        free( *$2 );
+    }
+}
+%typemap(in,numinputs=0) (GIntBig *nLen, char **pBuf ) ( GIntBig nLen = 0, char *pBuf = 0 )
+{
+    /* %typemap(in,numinputs=0) (GIntBig *nLen, char **pBuf ) */
+    $1 = &nLen;
+    $2 = &pBuf;
+}
+%typemap(argout) (GIntBig *nLen, char **pBuf )
+{
+    /* %typemap(argout) (GIntBig *nLen, char **pBuf ) */
+    $result = sv_2mortal(newSVpv( *$2, *$1 ));
+    argvi++;
+}
+%typemap(freearg) (GIntBig *nLen, char **pBuf )
+{
+    /* %typemap(freearg) (GIntBig *nLen, char **pBuf ) */
+    if( *$1 ) {
+        free( *$2 );
+    }
 }
 %typemap(in,numinputs=1) (int nLen, char *pBuf )
 {
     /* %typemap(in,numinputs=1) (int nLen, char *pBuf ) */
     if (SvOK($input)) {
-        if (!SvPOK($input))
-            SWIG_croak("Expected binary data.");
-        STRLEN len = SvCUR($input);
-        $2 = SvPV_nolen($input);
+        SV *sv = $input;
+        if (SvROK(sv) && SvTYPE(SvRV(sv)) < SVt_PVAV)
+            sv = SvRV(sv);
+        if (!SvPOK(sv))
+            do_confess(NEED_BINARY_DATA, 1);
+        STRLEN len = SvCUR(sv);
+        $2 = SvPV_nolen(sv);
         $1 = len;
     } else {
         $2 = NULL;
@@ -604,10 +687,30 @@ CreateArrayFromStringArray( char **first ) {
 {
     /* %typemap(in,numinputs=1) (int nLen, unsigned char *pBuf ) */
     if (SvOK($input)) {
-        if (!SvPOK($input))
-            SWIG_croak("Expected binary data.");
-        STRLEN len = SvCUR($input);
-        $2 = (unsigned char *)SvPV_nolen($input);
+        SV *sv = $input;
+        if (SvROK(sv) && SvTYPE(SvRV(sv)) < SVt_PVAV)
+            sv = SvRV(sv);
+        if (!SvPOK(sv))
+            do_confess(NEED_BINARY_DATA, 1);
+        STRLEN len = SvCUR(sv);
+        $2 = (unsigned char *)SvPV_nolen(sv);
+        $1 = len;
+    } else {
+        $2 = NULL;
+        $1 = 0;
+    }
+}
+%typemap(in,numinputs=1) (GIntBig nLen, char *pBuf )
+{
+    /* %typemap(in,numinputs=1) (GIntBig nLen, char *pBuf ) */
+    if (SvOK($input)) {
+        SV *sv = $input;
+        if (SvROK(sv) && SvTYPE(SvRV(sv)) < SVt_PVAV)
+            sv = SvRV(sv);
+        if (!SvPOK(sv))
+            do_confess(NEED_BINARY_DATA, 1);
+        STRLEN len = SvCUR(sv);
+        $2 = SvPV_nolen(sv);
         $1 = len;
     } else {
         $2 = NULL;
@@ -620,7 +723,7 @@ CreateArrayFromStringArray( char **first ) {
  ***************************************************/
 
 %typemap(out) (retStringAndCPLFree*)
-%{ 
+%{
     /* %typemap(out) (retStringAndCPLFree*) */
     if($1)
     {
@@ -632,21 +735,21 @@ CreateArrayFromStringArray( char **first ) {
         $result = &PL_sv_undef;
     }
     argvi++ ;
-%}
+    %}
 
 /* slightly different version(?) for GDALAsyncReader */
 %typemap(in,numinputs=0) (int *nLength, char **pBuffer ) ( int nLength = 0, char *pBuffer = 0 )
 {
-  /* %typemap(in,numinputs=0) (int *nLength, char **pBuffer ) */
-  $1 = &nLength;
-  $2 = &pBuffer;
+    /* %typemap(in,numinputs=0) (int *nLength, char **pBuffer ) */
+    $1 = &nLength;
+    $2 = &pBuffer;
 }
 %typemap(freearg) (int *nLength, char **pBuffer )
 {
-  /* %typemap(freearg) (int *nLength, char **pBuffer ) */
-  if( *$1 ) {
-    free( *$2 );
-  }
+    /* %typemap(freearg) (int *nLength, char **pBuffer ) */
+    if( *$1 ) {
+        free( *$2 );
+    }
 }
 
 
@@ -655,46 +758,48 @@ CreateArrayFromStringArray( char **first ) {
  */
 %typemap(in,numinputs=0) (int *nGCPs, GDAL_GCP const **pGCPs ) (int nGCPs=0, GDAL_GCP *pGCPs=0 )
 {
-  /* %typemap(in,numinputs=0) (int *nGCPs, GDAL_GCP const **pGCPs ) */
-  $1 = &nGCPs;
-  $2 = &pGCPs;
+    /* %typemap(in,numinputs=0) (int *nGCPs, GDAL_GCP const **pGCPs ) */
+    $1 = &nGCPs;
+    $2 = &pGCPs;
 }
 %typemap(argout) (int *nGCPs, GDAL_GCP const **pGCPs )
 {
-  /* %typemap(argout) (int *nGCPs, GDAL_GCP const **pGCPs ) */
-  AV *dict = (AV*)sv_2mortal((SV*)newAV());
-  for( int i = 0; i < *$1; i++ ) {
-    GDAL_GCP *o = new_GDAL_GCP( (*$2)[i].dfGCPX,
-                                (*$2)[i].dfGCPY,
-                                (*$2)[i].dfGCPZ,
-                                (*$2)[i].dfGCPPixel,
-                                (*$2)[i].dfGCPLine,
-                                (*$2)[i].pszInfo,
-                                (*$2)[i].pszId );
-    SV *sv = newSV(0);
-    SWIG_MakePtr( sv, (void*)o, $*2_descriptor, SWIG_SHADOW|SWIG_OWNER);
-    av_store(dict, i, sv);
-  }
-  $result = sv_2mortal(newRV((SV*)dict));
-  argvi++;
+    /* %typemap(argout) (int *nGCPs, GDAL_GCP const **pGCPs ) */
+    AV *dict = (AV*)sv_2mortal((SV*)newAV());
+    for( int i = 0; i < *$1; i++ ) {
+        GDAL_GCP *o = new_GDAL_GCP( (*$2)[i].dfGCPX,
+                                    (*$2)[i].dfGCPY,
+                                    (*$2)[i].dfGCPZ,
+                                    (*$2)[i].dfGCPPixel,
+                                    (*$2)[i].dfGCPLine,
+                                    (*$2)[i].pszInfo,
+                                    (*$2)[i].pszId );
+        SV *sv = newSV(0);
+        SWIG_MakePtr( sv, (void*)o, $*2_descriptor, SWIG_SHADOW|SWIG_OWNER);
+        av_store(dict, i, sv);
+    }
+    $result = sv_2mortal(newRV((SV*)dict));
+    argvi++;
 }
 %typemap(in,numinputs=1) (int nGCPs, GDAL_GCP const *pGCPs )
 {
     /* %typemap(in,numinputs=1) (int nGCPs, GDAL_GCP const *pGCPs ) */
     if (!(SvROK($input) && (SvTYPE(SvRV($input))==SVt_PVAV)))
-        SWIG_croak("Expected a reference to an array.");
+        do_confess(NEED_ARRAY_REF, 1);
     AV *av = (AV*)(SvRV($input));
     $1 = av_len(av)+1;
     $2 = (GDAL_GCP *)CPLMalloc($1*sizeof(GDAL_GCP));
     if ($2) {
         for (int i = 0; i < $1; i++ ) {
             SV **sv = av_fetch(av, i, 0);
-            int ret = SWIG_ConvertPtr(*sv, (void**)&($2[i]), SWIGTYPE_p_GDAL_GCP, 0);
+            GDAL_GCP *gcp;
+            int ret = SWIG_ConvertPtr(*sv, (void**)&gcp, SWIGTYPE_p_GDAL_GCP, 0);
             if (!SWIG_IsOK(ret))
-                SWIG_croak("An item in the argument array is not a GCP object.");
+                do_confess(WRONG_ITEM_IN_ARRAY, 1);
+            $2[i] = *gcp;
         }
     } else
-        SWIG_croak("Out of memory.");
+        do_confess(OUT_OF_MEMORY, 1);
 }
 %typemap(freearg) (int nGCPs, GDAL_GCP const *pGCPs )
 {
@@ -710,7 +815,7 @@ CreateArrayFromStringArray( char **first ) {
 {
     /* %typemap(out) GDALColorEntry* */
     if (!result)
-        SWIG_croak("GetColorEntry failed.");
+        do_confess(CALL_FAILED, 1);
     $result = sv_newmortal();
     sv_setiv(ST(argvi++), (IV) result->c1);
     $result = sv_newmortal();
@@ -722,14 +827,14 @@ CreateArrayFromStringArray( char **first ) {
 }
 %typemap(in,numinputs=0) GDALColorEntry*(GDALColorEntry e)
 {
-  /* %typemap(in,numinputs=0) GDALColorEntry*(GDALColorEntry e) */
-  $1 = &e;
+    /* %typemap(in,numinputs=0) GDALColorEntry*(GDALColorEntry e) */
+    $1 = &e;
 }
 %typemap(argout) GDALColorEntry*
 {
     /* %typemap(argout) GDALColorEntry* */
     if (!result)
-        SWIG_croak("GetColorEntryAsRGB failed.");
+        do_confess(CALL_FAILED, 1);
     argvi--;
     $result = sv_newmortal();
     sv_setiv(ST(argvi++), (IV) e3.c1);
@@ -742,7 +847,7 @@ CreateArrayFromStringArray( char **first ) {
 }
 %typemap(argout) const GDALColorEntry*
 {
-  /* %typemap(argout) const GDALColorEntry* */
+    /* %typemap(argout) const GDALColorEntry* */
 }
 %typemap(in,numinputs=1) const GDALColorEntry*(GDALColorEntry e)
 {
@@ -750,21 +855,30 @@ CreateArrayFromStringArray( char **first ) {
     $1 = &e3;
     int ok = SvROK($input) && SvTYPE(SvRV($input))==SVt_PVAV;
     AV *av;
-    if (ok) {
-      av = (AV*)(SvRV($input));
-      ok = av_len(av) == 3;
-    }
-    if (ok) {
-      SV **sv = av_fetch(av, 0, 0);
-      $1->c1 =  SvIV(*sv);
-      sv = av_fetch(av, 1, 0);
-      $1->c2 =  SvIV(*sv);
-      sv = av_fetch(av, 2, 0);
-      $1->c3 =  SvIV(*sv);
-      sv = av_fetch(av, 3, 0);
-      $1->c4 =  SvIV(*sv);
-    } else 
-      SWIG_croak("Color entry is an array of four values: red, green, blue, alpha.");
+    if (ok)
+        av = (AV*)(SvRV($input));
+    else
+        do_confess(NEED_ARRAY_REF, 1);
+    SV **sv = av_fetch(av, 0, 0);
+    if (sv)
+        $1->c1 = SvIV(*sv);
+    else
+        $1->c1 = 0;
+    sv = av_fetch(av, 1, 0);
+    if (sv)
+        $1->c2 = SvIV(*sv);
+    else
+        $1->c2 = 0;
+    sv = av_fetch(av, 2, 0);
+    if (sv)
+        $1->c3 = SvIV(*sv);
+    else
+        $1->c3 = 0;
+    sv = av_fetch(av, 3, 0);
+    if (sv)
+        $1->c4 = SvIV(*sv);
+    else
+        $1->c4 = 255;
 }
 
 /*
@@ -772,53 +886,58 @@ CreateArrayFromStringArray( char **first ) {
  */
 %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER) (char **dict)
 {
-  /* %typecheck(SWIG_TYPECHECK_POINTER) (char **dict) */
-  $1 = (SvROK($input) && (SvTYPE(SvRV($input))==SVt_PVHV)) ? 1 : 0;
+    /* %typecheck(SWIG_TYPECHECK_POINTER) (char **dict) */
+    $1 = (SvROK($input) && (SvTYPE(SvRV($input))==SVt_PVHV)) ? 1 : 0;
 }
 %typemap(in) char **dict
 {
-  /* %typemap(in) char **dict */
-  HV *hv = (HV*)SvRV($input);
-  SV *sv;
-  char *key;
-  I32 klen;
-  $1 = NULL;
-  hv_iterinit(hv);
-  while(sv = hv_iternextsv(hv,&key,&klen)) {
-    $1 = CSLAddNameValue( $1, key, SvPV_nolen(sv) );
-  }
+    /* %typemap(in) char **dict */
+    HV *hv = (HV*)SvRV($input);
+    SV *sv;
+    char *key;
+    I32 klen;
+    $1 = NULL;
+    hv_iterinit(hv);
+    while(sv = hv_iternextsv(hv,&key,&klen)) {
+        $1 = CSLAddNameValue( $1, key, SvPV_nolen(sv) );
+    }
 }
 %typemap(out) char **dict
 {
-  /* %typemap(out) char **dict */
-  char **stringarray = $1;
-  HV *hv = (HV*)sv_2mortal((SV*)newHV());
-  if ( stringarray != NULL ) {
-    while (*stringarray != NULL ) {
-      char const *valptr;
-      char *keyptr;
-      valptr = CPLParseNameValue( *stringarray, &keyptr );
-      if ( valptr != 0 ) {
-        hv_store(hv, keyptr, strlen(keyptr), newSVpv(valptr, strlen(valptr)), 0);
-        CPLFree( keyptr );
-      }
-      stringarray++;
+    /* %typemap(out) char **dict */
+    char **stringarray = $1;
+    HV *hv = (HV*)sv_2mortal((SV*)newHV());
+    if ( stringarray != NULL ) {
+        while (*stringarray != NULL ) {
+            char const *valptr;
+            char *keyptr;
+            valptr = CPLParseNameValue( *stringarray, &keyptr );
+            if ( valptr != 0 ) {
+                hv_store(hv, keyptr, strlen(keyptr), newSVpv(valptr, strlen(valptr)), 0);
+                CPLFree( keyptr );
+            }
+            stringarray++;
+        }
     }
-  }
-  $result = newRV((SV*)hv);
-  sv_2mortal($result);
-  argvi++;
+    $result = newRV((SV*)hv);
+    sv_2mortal($result);
+    argvi++;
 }
 %typemap(freearg) char **dict
 {
-  /* %typemap(freearg) char **dict */
-  CSLDestroy( $1 );
+    /* %typemap(freearg) char **dict */
+    CSLDestroy( $1 );
 }
 
 /*
  * Typemap char **options <-> AV
  */
-%typemap(in) char **options
+%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER) char **options
+{
+    /* %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER) char **options */
+    $1 = 1;
+}
+%typemap(in, fragment="sv_to_utf8_string") char **options
 {
     /* %typemap(in) char **options */
     if (SvOK($input)) {
@@ -827,9 +946,9 @@ CreateArrayFromStringArray( char **first ) {
                 AV *av = (AV*)(SvRV($input));
                 for (int i = 0; i < av_len(av)+1; i++) {
                     SV *sv = *(av_fetch(av, i, 0));
-                    sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                    char *pszItem = SvPV_nolen(sv);
-                    $1 = CSLAddString( $1, pszItem );
+                    char *tmp = sv_to_utf8_string(sv, NULL);
+                    $1 = CSLAddString($1, tmp);
+                    free(tmp);
                 }
             } else if (SvTYPE(SvRV($input))==SVt_PVHV) {
                 HV *hv = (HV*)SvRV($input);
@@ -838,20 +957,21 @@ CreateArrayFromStringArray( char **first ) {
                 I32 klen;
                 $1 = NULL;
                 hv_iterinit(hv);
-                while(sv = hv_iternextsv(hv,&key,&klen)) {
-                    sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                    $1 = CSLAddNameValue( $1, key, SvPV_nolen(sv) );
+                while(sv = hv_iternextsv(hv, &key, &klen)) {
+                    char *tmp = sv_to_utf8_string(sv, NULL);
+                    $1 = CSLAddNameValue($1, key, tmp);
+                    free(tmp);
                 }
             } else
-                SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
+                do_confess(NEED_REF, 1);
         } else
-            SWIG_croak("The 'options' argument is not a reference.");   
+            do_confess(NEED_REF, 1);
     }
 }
 %typemap(freearg) char **options
 {
-  /* %typemap(freearg) char **options */
-  if ($1) CSLDestroy( $1 );
+    /* %typemap(freearg) char **options */
+    if ($1) CSLDestroy( $1 );
 }
 %typemap(out) char **options
 {
@@ -876,37 +996,41 @@ CreateArrayFromStringArray( char **first ) {
  * Typemaps map mutable char ** arguments from AV.  Does not
  * return the modified argument
  */
-%typemap(in) (char **ignorechange) ( char *val )
+%typemap(in, fragment="sv_to_utf8_string") (char **ignorechange) (char *val, U8 *tmpbuf = NULL)
 {
     /* %typemap(in) (char **ignorechange) */
-    sv_utf8_upgrade($input); /* GDAL expects UTF-8 */
-    val = SvPV_nolen($input);
+    val = sv_to_utf8_string($input, &tmpbuf);
     $1 = &val;
 }
+%typemap(freearg) (char **ignorechange)
+{
+    /* %typemap(freearg) (char **ignorechange) */
+    if (tmpbuf$argnum) free(tmpbuf$argnum);
+}
 
 /*
  * Typemap for char **argout.
  */
 %typemap(in,numinputs=0) (char **argout) (char *argout=0), (char **username) (char *argout=0), (char **usrname) (char *argout=0), (char **type) (char *argout=0)
 {
-  /* %typemap(in,numinputs=0) (char **argout) */
-  $1 = &argout;
+    /* %typemap(in,numinputs=0) (char **argout) */
+    $1 = &argout;
 }
 %typemap(argout) (char **argout), (char **username), (char **usrname), (char **type)
 {
-  /* %typemap(argout) (char **argout) */
-  $result = sv_newmortal();
-  if ( $1 ) {
-    sv_setpv($result, *$1);
-    SvUTF8_on($result); /* expecting UTF-8 from GDAL */
-  }
-  argvi++;
+    /* %typemap(argout) (char **argout) */
+    $result = sv_newmortal();
+    if ( $1 ) {
+        sv_setpv($result, *$1);
+        SvUTF8_on($result); /* expecting UTF-8 from GDAL */
+    }
+    argvi++;
 }
 %typemap(freearg) (char **argout)
 {
-  /* %typemap(freearg) (char **argout) */
-  if ( *$1 )
-    CPLFree( *$1 );
+    /* %typemap(freearg) (char **argout) */
+    if ( *$1 )
+        CPLFree( *$1 );
 }
 
 /*
@@ -917,14 +1041,25 @@ CreateArrayFromStringArray( char **first ) {
  */
 %typemap(in) (int *optional_int) ( int val )
 {
-  /* %typemap(in) (int *optional_int) */
-  if ( !SvOK($input) ) {
-    $1 = 0;
-  }
-  else {
-    val = SvIV($input);
-    $1 = ($1_type)&val;
-  }
+    /* %typemap(in) (int *optional_int) */
+    if ( !SvOK($input) ) {
+        $1 = 0;
+    }
+    else {
+        val = SvIV($input);
+        $1 = ($1_type)&val;
+    }
+}
+%typemap(in) (GIntBig *optional_GIntBig) ( GIntBig val )
+{
+    /* %typemap(in) (GIntBig *optional_GIntBig) */
+    if ( !SvOK($input) ) {
+        $1 = 0;
+    }
+    else {
+        val = strtoull(SvPV_nolen($input), 0, 0);
+        $1 = ($1_type)&val;
+    }
 }
 
 /*
@@ -933,16 +1068,20 @@ CreateArrayFromStringArray( char **first ) {
  * Formats the object using str and returns the string representation
  */
 
-%typemap(in) (tostring argin)
+%typemap(in, fragment="sv_to_utf8_string") (tostring argin) (U8 *tmpbuf = NULL)
 {
-  /* %typemap(in) (tostring argin) */
-  sv_utf8_upgrade($input); /* GDAL expects UTF-8 */
-  $1 = SvPV_nolen( $input ); 
+    /* %typemap(in) (tostring argin) */
+    $1 = sv_to_utf8_string($input, &tmpbuf);
 }
 %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER) (tostring argin)
 {
-  /* %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER) (tostring argin) */
-  $1 = 1;
+    /* %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER) (tostring argin) */
+    $1 = 1;
+}
+%typemap(freearg) (tostring argin)
+{
+    /* %typemap(freearg) (tostring argin) */
+    if (tmpbuf$argnum) free(tmpbuf$argnum);
 }
 
 /*
@@ -952,7 +1091,7 @@ CreateArrayFromStringArray( char **first ) {
  */
 %typemap(out) CPLErr
 {
-  /* %typemap(out) CPLErr */
+    /* %typemap(out) CPLErr */
 }
 
 /*
@@ -967,8 +1106,8 @@ CreateArrayFromStringArray( char **first ) {
     /* %typemap(out) OGRErr */
     if ( result != 0 ) {
         const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
+        if (err and *err) do_confess(err, 0); /* this is usually better */
+        do_confess( OGRErrMessages(result), 1 );
     }
 }
 
@@ -980,61 +1119,61 @@ CreateArrayFromStringArray( char **first ) {
 /************************************************************************/
 /*                          AVToXMLTree()                               */
 /************************************************************************/
-  static CPLXMLNode *AVToXMLTree( AV *av, int *err )
-{
-    int      nChildCount = 0, iChild, nType;
-    CPLXMLNode *psThisNode;
-    char       *pszText = NULL;
-    
-    nChildCount = av_len(av) - 1; /* there are two non-childs in the array */
-    if (nChildCount < 0) {
-        /* the input XML is empty */
-        *err = 1;
-        return NULL;
-    }
-
-    nType = SvIV(*(av_fetch(av,0,0)));
-    SV *sv = *(av_fetch(av,1,0));
-    sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-    pszText = SvPV_nolen(sv);
-    psThisNode = CPLCreateXMLNode( NULL, (CPLXMLNodeType) nType, pszText );
-    
-    for( iChild = 0; iChild < nChildCount; iChild++ )
+    static CPLXMLNode *AVToXMLTree( AV *av, int *err )
     {
-        SV **s = av_fetch(av, iChild+2, 0);
-        CPLXMLNode *psChild;
-        if (!(SvROK(*s) && (SvTYPE(SvRV(*s))==SVt_PVAV))) {
-            /* expected a reference to an array */
-            *err = 2;
-            psChild = NULL;
-        } else
-            psChild = AVToXMLTree((AV*)SvRV(*s), err);
-        if (psChild)
-            CPLAddXMLChild( psThisNode, psChild );
-        else {
-            CPLDestroyXMLNode(psThisNode);
+        int      nChildCount = 0, iChild, nType;
+        CPLXMLNode *psThisNode;
+        char       *pszText = NULL;
+
+        nChildCount = av_len(av) - 1; /* There are two non-children in the array */
+        if (nChildCount < 0) {
+            /* the input XML is empty */
+            *err = 1;
             return NULL;
         }
-    }
 
-    return psThisNode;
-}
-%}
+        nType = SvIV(*(av_fetch(av,0,0)));
+        SV *sv = *(av_fetch(av,1,0));
+        char *tmp = sv_to_utf8_string(sv, NULL);
+        psThisNode = CPLCreateXMLNode(NULL, (CPLXMLNodeType)nType, tmp);
+        free(tmp);
+
+        for( iChild = 0; iChild < nChildCount; iChild++ )
+        {
+            SV **s = av_fetch(av, iChild+2, 0);
+            CPLXMLNode *psChild;
+            if (!(SvROK(*s) && (SvTYPE(SvRV(*s))==SVt_PVAV))) {
+                /* expected a reference to an array */
+                *err = 2;
+                psChild = NULL;
+            } else
+                psChild = AVToXMLTree((AV*)SvRV(*s), err);
+            if (psChild)
+                CPLAddXMLChild( psThisNode, psChild );
+            else {
+                CPLDestroyXMLNode(psThisNode);
+                return NULL;
+            }
+        }
+
+        return psThisNode;
+    }
+    %}
 
 %typemap(in,fragment="AVToXMLTree") (CPLXMLNode* xmlnode )
 {
     /* %typemap(in) (CPLXMLNode* xmlnode ) */
     if (!(SvROK($input) && (SvTYPE(SvRV($input))==SVt_PVAV)))
-        SWIG_croak("Expected a reference to an array.");
+        do_confess(NEED_ARRAY_REF, 1);
     AV *av = (AV*)(SvRV($input));
     int err;
     $1 = AVToXMLTree( av, &err );
     if ( !$1 ) {
         switch (err) {
         case 1:
-            SWIG_croak("Conversion of a Perl array to XMLTree failed: the input XML is empty.");
+            do_confess(ARRAY_TO_XML_FAILED" "NEED_DEF, 1);
         case 2:
-            SWIG_croak("Conversion of a Perl array to XMLTree failed, child should be a reference to an array.");
+            do_confess(ARRAY_TO_XML_FAILED" "NEED_ARRAY_REF, 1);
         }
     }
 }
@@ -1048,48 +1187,48 @@ CreateArrayFromStringArray( char **first ) {
 /************************************************************************/
 /*                          XMLTreeToAV()                               */
 /************************************************************************/
-static AV *XMLTreeToAV( CPLXMLNode *psTree )
-{
-    AV *av;
-    int      nChildCount = 0, iChild;
-    CPLXMLNode *psChild;
-
-    for( psChild = psTree->psChild; 
-         psChild != NULL; 
-         psChild = psChild->psNext )
-        nChildCount++;
-
-    av = (AV*)sv_2mortal((SV*)newAV());
-
-    av_store(av,0,newSViv((int) psTree->eType));
-    SV *sv = newSVpv(psTree->pszValue, strlen(psTree->pszValue));
-    SvUTF8_on(sv); /* expecting UTF-8 from GDAL */
-    av_store(av,1,sv);
-    
-    for( psChild = psTree->psChild, iChild = 2; 
-         psChild != NULL; 
-         psChild = psChild->psNext, iChild++ )
+    static AV *XMLTreeToAV( CPLXMLNode *psTree )
     {
-        SV *s = newRV((SV*)XMLTreeToAV(psChild));
-        if (!av_store(av, iChild, s))
-            SvREFCNT_dec(s);
-    }
+        AV *av;
+        int      nChildCount = 0, iChild;
+        CPLXMLNode *psChild;
 
-    return av;
-}
-%}
+        for( psChild = psTree->psChild;
+             psChild != NULL;
+             psChild = psChild->psNext )
+            nChildCount++;
+
+        av = (AV*)sv_2mortal((SV*)newAV());
+
+        av_store(av,0,newSViv((int) psTree->eType));
+        SV *sv = newSVpv(psTree->pszValue, strlen(psTree->pszValue));
+        SvUTF8_on(sv); /* expecting UTF-8 from GDAL */
+        av_store(av,1,sv);
+
+        for( psChild = psTree->psChild, iChild = 2;
+             psChild != NULL;
+             psChild = psChild->psNext, iChild++ )
+        {
+            SV *s = newRV((SV*)XMLTreeToAV(psChild));
+            if (!av_store(av, iChild, s))
+                SvREFCNT_dec(s);
+        }
+
+        return av;
+    }
+    %}
 
 %typemap(out,fragment="XMLTreeToAV") (CPLXMLNode*)
 {
-  /* %typemap(out) (CPLXMLNode*) */
-  $result = newRV((SV*)XMLTreeToAV( $1 ));
-  sv_2mortal($result);
-  argvi++;
+    /* %typemap(out) (CPLXMLNode*) */
+    $result = newRV((SV*)XMLTreeToAV( $1 ));
+    sv_2mortal($result);
+    argvi++;
 }
 %typemap(ret) (CPLXMLNode*)
 {
-  /* %typemap(ret) (CPLXMLNode*) */
-  if ( $1 ) CPLDestroyXMLNode( $1 );
+    /* %typemap(ret) (CPLXMLNode*) */
+    if ( $1 ) CPLDestroyXMLNode( $1 );
 }
 
 /* non NULL input pointer checks */
@@ -1099,22 +1238,22 @@ static AV *XMLTreeToAV( CPLXMLNode *psTree )
 {
     /* %typemap(check) (type *param) */
     if (!$1)
-        SWIG_croak("The msg must not be undefined when it is an argument to a Geo::GDAL method");
+        do_confess(NEED_DEF, 1);
 }
 %enddef
 
 %define IF_UNDEF_SET_EMPTY_STRING(type, param)
 %typemap(default) type param {
     /* %typemap(default) type param */
-  $1 = (char *)"";
-}
+    $1 = (char *)"";
+ }
 %enddef
 
 %define IF_UNDEF_NULL(type, param)
 %typemap(default) type param {
     /* %typemap(default) type param */
     $1 = NULL;
-}
+ }
 %enddef
 
 CHECK_NOT_UNDEF(char, method, method)
@@ -1140,7 +1279,7 @@ IF_UNDEF_NULL(const char *, target_key)
     /* %typemap(in) (int nCount, double *x, double *y, double *z) */
     /* $input is a ref to a list of refs to point lists */
     if (! (SvROK($input) && (SvTYPE(SvRV($input))==SVt_PVAV)))
-        SWIG_croak("Expected a reference to an array.");
+        do_confess(NEED_ARRAY_REF, 1);
     AV *av = (AV*)(SvRV($input));
     $1 = av_len(av)+1;
     $2 = (double*)CPLMalloc($1*sizeof(double));
@@ -1153,7 +1292,7 @@ IF_UNDEF_NULL(const char *, target_key)
     for (int i = 0; i < $1; i++) {
         SV **sv = av_fetch(av, i, 0); /* ref to one point list */
         if (!(SvROK(*sv) && (SvTYPE(SvRV(*sv))==SVt_PVAV)))
-            SWIG_croak("An item in the list is not a reference to an array.");
+            do_confess(WRONG_ITEM_IN_ARRAY, 1);
         AV *ac = (AV*)(SvRV(*sv));
         int n = av_len(ac)+1;
         SV **c = av_fetch(ac, 0, 0);
@@ -1212,13 +1351,13 @@ IF_UNDEF_NULL(const char *, target_key)
     if (SvOK($input)) {
         if (SvROK($input)) {
             if (SvTYPE(SvRV($input)) != SVt_PVCV) {
-               SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
+                do_confess(NEED_CODE_REF, 1);
             } else {
-               saved_env.fct = (SV *)$input;
-               $1 = &callback_d_cp_vp;
-           }
+                saved_env.fct = (SV *)$input;
+                $1 = &callback_d_cp_vp;
+            }
         } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
+            do_confess(NEED_CODE_REF, 1);
         }
     }
 }
@@ -1230,34 +1369,85 @@ IF_UNDEF_NULL(const char *, target_key)
         saved_env.data = (SV *)$input;
 }
 
+%typemap(in, numinputs=1) (VSIWriteFunction pFct, FILE* stream = NULL)
+{
+    /* %typemap(in) (VSIWriteFunction pFct) */
+    if (VSIStdoutSetRedirectionFct != &PL_sv_undef) {
+        SvREFCNT_dec(VSIStdoutSetRedirectionFct);
+    }
+    if (SvOK($input)) {
+        if (SvROK($input)) {
+            if (SvTYPE(SvRV($input)) != SVt_PVCV) {
+                do_confess(NEED_CODE_REF, 1);
+            } else {
+                VSIStdoutSetRedirectionFct = newRV_inc(SvRV((SV *)$input));
+                $1 = &callback_fwrite;
+            }
+        } else {
+            do_confess(NEED_CODE_REF, 1);
+        }
+    } else
+        VSIStdoutSetRedirectionFct = &PL_sv_undef;
+}
+
+%typemap(in) (GDALDatasetShadow *)
+{
+    /* %typemap(in) (GDALDatasetShadow *) */
+    void *argp = 0;
+    int res = SWIG_ConvertPtr($input, &argp, SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
+    if (!SWIG_IsOK(res)) {
+        do_confess(WRONG_CLASS, 1);
+    }
+    $1 = reinterpret_cast< GDALDatasetShadow * >(argp);
+    if ($1 == NULL)
+        do_confess(NEED_DEF, 1);
+}
+
+%typemap(in, numinputs=1) (int object_list_count, GDALDatasetShadow **poObjects)
+{
+    /* %typemap(in, numinputs=1) (int object_list_count, GDALDatasetShadow** poObjects) */
+    if (!(SvROK($input) && (SvTYPE(SvRV($input))==SVt_PVAV)))
+        do_confess(NEED_ARRAY_REF, 1);
+    AV *av = (AV*)(SvRV($input));
+    $1 = av_len(av)+1;
+    /* get the pointers from the array */
+    $2 = (GDALDatasetShadow **)CPLMalloc($1*sizeof(GDALDatasetShadow *));
+    if ($2) {
+        for (int i = 0; i < $1; i++) {
+            SV **sv = av_fetch(av, i, 0);
+            int ret = SWIG_ConvertPtr(*sv, &($2[i]), SWIGTYPE_p_GDALDatasetShadow, 0);
+            if (!SWIG_IsOK(ret))
+                do_confess(WRONG_ITEM_IN_ARRAY, 1);
+        }
+    } else
+        do_confess(OUT_OF_MEMORY, 1);
+}
+
+
 /*
  * Typemaps for VSIStatL
  */
 %typemap(in,numinputs=0) (VSIStatBufL *) (VSIStatBufL sStatBuf)
 {
-  /* %typemap(in,numinputs=0) (VSIStatBufL *) (VSIStatBufL sStatBuf) */
-  $1 = &sStatBuf;
+    /* %typemap(in,numinputs=0) (VSIStatBufL *) (VSIStatBufL sStatBuf) */
+    $1 = &sStatBuf;
 }
 %typemap(argout) (VSIStatBufL *)
 {
-  /* %typemap(argout) (VSIStatBufL *) */
-  SP -= 1; /* should be somewhere else, remove the filename arg */
-  EXTEND(SP, 1);
-  char mode[2];
-  mode[0] = ' ';
-  mode[1] = '\0';
-  if (S_ISREG(sStatBuf2.st_mode)) mode[0] = 'f';
-  else if (S_ISDIR(sStatBuf2.st_mode)) mode[0] = 'd';
-  else if (S_ISLNK(sStatBuf2.st_mode)) mode[0] = 'l';
-  else if (S_ISFIFO(sStatBuf2.st_mode)) mode[0] = 'p';
-  else if (S_ISSOCK(sStatBuf2.st_mode)) mode[0] = 'S';
-  else if (S_ISBLK(sStatBuf2.st_mode)) mode[0] = 'b';
-  else if (S_ISCHR(sStatBuf2.st_mode)) mode[0] = 'c';
-  PUSHs(sv_2mortal(newSVpv(mode, 0)));
-  argvi++;
-  EXTEND(SP, 1);
-  PUSHs(sv_2mortal(newSVuv(sStatBuf2.st_size)));
-  argvi++;
+    /* %typemap(argout) (VSIStatBufL *) */
+    char mode[2];
+    mode[0] = ' ';
+    mode[1] = '\0';
+    if (S_ISREG(sStatBuf2.st_mode)) mode[0] = 'f';
+    else if (S_ISDIR(sStatBuf2.st_mode)) mode[0] = 'd';
+    else if (S_ISLNK(sStatBuf2.st_mode)) mode[0] = 'l';
+    else if (S_ISFIFO(sStatBuf2.st_mode)) mode[0] = 'p';
+    else if (S_ISSOCK(sStatBuf2.st_mode)) mode[0] = 'S';
+    else if (S_ISBLK(sStatBuf2.st_mode)) mode[0] = 'b';
+    else if (S_ISCHR(sStatBuf2.st_mode)) mode[0] = 'c';
+    EXTEND(SP, argvi+2-items+1);
+    ST(argvi++) = sv_2mortal(newSVpv(mode, 0));
+    ST(argvi++) = sv_2mortal(newSVuv(sStatBuf2.st_size));
 }
 
 /*
@@ -1265,28 +1455,28 @@ IF_UNDEF_NULL(const char *, target_key)
  */
 %typemap(in,numinputs=1) (void *pBuffer, size_t nSize, size_t nCount)
 {
-  /* %typemap(in,numinputs=1) (void *pBuffer, size_t nSize, size_t nCount) */
-  size_t len = SvIV($input);
-  $1 = CPLMalloc(len);
-  if (!$1)
-      SWIG_fail;
-  $2 = 1;
-  $3 = len;
+    /* %typemap(in,numinputs=1) (void *pBuffer, size_t nSize, size_t nCount) */
+    size_t len = SvIV($input);
+    $1 = CPLMalloc(len);
+    if (!$1)
+        SWIG_fail;
+    $2 = 1;
+    $3 = len;
 }
 %typemap(argout) (void *pBuffer, size_t nSize, size_t nCount)
 {
-  /* %typemap(argout) (void *pBuffer, size_t nSize, size_t nCount) */
-  if (result) {
-    $result = sv_2mortal(newSVpvn((char*)$1, result));
-  } else {
-    $result = &PL_sv_undef;
-  }
-  CPLFree($1);
-  argvi++;
+    /* %typemap(argout) (void *pBuffer, size_t nSize, size_t nCount) */
+    if (result) {
+        $result = sv_2mortal(newSVpvn((char*)$1, result));
+    } else {
+        $result = &PL_sv_undef;
+    }
+    CPLFree($1);
+    argvi++;
 }
 %typemap(out) (size_t VSIFReadL)
 {
-  /* %typemap(out) (size_t VSIFReadL) */
+    /* %typemap(out) (size_t VSIFReadL) */
 }
 
 /*
@@ -1294,11 +1484,11 @@ IF_UNDEF_NULL(const char *, target_key)
  */
 %typemap(in,numinputs=1) (const void *pBuffer, size_t nSize, size_t nCount)
 {
-  /* %typemap(in,numinputs=1) (const void *pBuffer, size_t nSize, size_t nCount) */
-  size_t len;
-  $1 = SvPV($input, len);
-  $2 = 1;
-  $3 = len;
+    /* %typemap(in,numinputs=1) (const void *pBuffer, size_t nSize, size_t nCount) */
+    size_t len;
+    $1 = SvPV($input, len);
+    $2 = 1;
+    $3 = len;
 }
 
 /*
@@ -1312,43 +1502,58 @@ IF_UNDEF_NULL(const char *, target_key)
  * Driver__Create, Driver_CreateCopy, Driver_Delete, Open__SWIG_1,
  * OpenShared__SWIG_1, IdentifyDriver
  */
-%typemap(in,numinputs=1) (const char* utf8_path)
+%typemap(in, numinputs=1, fragment="sv_to_utf8_string") (const char* utf8_path) (U8 *tmpbuf = NULL)
+{
+    /* %typemap(in,numinputs=1) (const char* utf8_path) (U8 *tmpbuf) */
+    $1 = sv_to_utf8_string($input, &tmpbuf);
+}
+%typemap(freearg) (const char* utf8_path)
+{
+    /* %typemap(freearg) (const char* utf8_path) */
+    if (tmpbuf$argnum) free(tmpbuf$argnum);
+}
+
+%typemap(in, numinputs=1, fragment="sv_to_utf8_string") (const char* layer_name) (U8 *tmpbuf = NULL)
+{
+    /* %typemap(in,numinputs=1) (const char* layer_name) */
+    $1 = sv_to_utf8_string($input, &tmpbuf);
+}
+%typemap(freearg) (const char* layer_name)
 {
-  /* %typemap(in,numinputs=1) (const char* utf8_path) */
-  sv_utf8_upgrade($input);
-  $1 = SvPV_nolen($input);
+    /* %typemap(freearg) (const char* layer_name) */
+    if (tmpbuf$argnum) free(tmpbuf$argnum);
 }
-%typemap(in,numinputs=1) (const char* layer_name)
+
+%typemap(in, numinputs=1, fragment="sv_to_utf8_string") (const char* name) (U8 *tmpbuf = NULL)
 {
-  /* %typemap(in,numinputs=1) (const char* layer_name) */
-  sv_utf8_upgrade($input);
-  $1 = SvPV_nolen($input);
+    /* %typemap(in,numinputs=1) (const char* name) */
+    $1 = sv_to_utf8_string($input, &tmpbuf);
 }
-%typemap(in,numinputs=1) (const char* name)
+%typemap(freearg) (const char* name)
 {
-  /* %typemap(in,numinputs=1) (const char* name) */
-  sv_utf8_upgrade($input);
-  $1 = SvPV_nolen($input);
+    /* %typemap(freearg) (const char* name) */
+    if (tmpbuf$argnum) free(tmpbuf$argnum);
 }
+
 %typemap(in,numinputs=0) (int *pnBytes) (int bytes)
 {
-  /* %typemap(in,numinputs=0) (int *pnBytes) (int bytes) */
-  $1 = &bytes;
+    /* %typemap(in,numinputs=0) (int *pnBytes) (int bytes) */
+    $1 = &bytes;
 }
 %typemap(out) GByte *
 {
-  /* %typemap(out) GByte * */
-  $result = sv_newmortal();
-  sv_setpvn($result, (const char*)$1, *arg2);
-  CPLFree($1);
-  argvi++;
+    /* %typemap(out) GByte * */
+    $result = sv_newmortal();
+    sv_setpvn($result, (const char*)$1, *arg2);
+    CPLFree($1);
+    argvi++;
 }
 
 %typemap(in,numinputs=1) (int object_list_count, GDALRasterBandShadow **poObjects)
 {
     /* %typemap(in,numinputs=1) (int object_list_count, GDALRasterBandShadow **poObjects) */
     if (!(SvROK($input) && (SvTYPE(SvRV($input))==SVt_PVAV)))
-        SWIG_croak("Expected a reference to an array of Band objects.");
+        do_confess(NEED_ARRAY_REF, 1);
     AV *av = (AV*)(SvRV($input));
     $1 = av_len(av)+1;
     /* get the pointers from the array into bands */
@@ -1358,14 +1563,27 @@ IF_UNDEF_NULL(const char *, target_key)
             SV **sv = av_fetch(av, i, 0);
             int ret = SWIG_ConvertPtr(*sv, &($2[i]), SWIGTYPE_p_GDALRasterBandShadow, 0);
             if (!SWIG_IsOK(ret))
-                SWIG_croak("An item in the argument array is not a Band object.");
+                do_confess(WRONG_ITEM_IN_ARRAY, 1);
         }
     } else
-        SWIG_croak("Out of memory.");
-        
+        do_confess(OUT_OF_MEMORY, 1);
+
 }
 %typemap(freearg) (int object_list_count, GDALRasterBandShadow **poObjects)
 {
     /* %typemap(freearg) (int object_list_count, GDALRasterBandShadow **poObjects) */
     CPLFree($2);
 }
+
+%typemap(in,numinputs=1) (int nBytes, GByte* pabyBuf)
+{
+    /* %typemap(in,numinputs=1) (int nBytes, GByte* pabyBuf) */
+    $1 = SvCUR($input);
+    $2 = (GByte*)SvPV_nolen($input);
+}
+
+%typemap(typecheck, precedence=SWIG_TYPECHECK_INTEGER) int nBytes, GByte* pabyBuf
+{
+    /* %typemap(typecheck, precedence=SWIG_TYPECHECK_INTEGER) int nBytes, GByte* pabyBuf */
+   $1 = 1;
+}
diff --git a/swig/include/php/typemaps_php.i b/swig/include/php/typemaps_php.i
index bf5f480..0330335 100644
--- a/swig/include/php/typemaps_php.i
+++ b/swig/include/php/typemaps_php.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: typemaps_php.i 8582 2005-10-11 14:11:43Z kruland $
+ * $Id: typemaps_php.i 33721 2016-03-15 00:56:01Z goatbar $
  *
  * Name:     typemaps_php.i
  * Project:  GDAL PHP Interface
@@ -20,7 +20,7 @@
  * double *val, int*hasval, is a special contrived typemap used for
  * the RasterBand GetNoDataValue, GetMinimum, GetMaximum, GetOffset, GetScale methods.
  * In the python bindings, the variable hasval is tested.  If it is 0 (is, the value
- * is not set in the raster band) then Py_None is returned.  If is is != 0, then
+ * is not set in the raster band) then Py_None is returned.  If it is != 0, then
  * the value is coerced into a long and returned.
  */
 %typemap(in,numinputs=0) (double *val, int*hasval) ( double tmpval, int tmphasval ) {
@@ -52,7 +52,7 @@
 %typemap(out) IF_FALSE_RETURN_NONE
 {
  /* %typemap(out) IF_FALSE_RETURN_NONE */
- RETVAL_NULL();  
+ RETVAL_NULL();
 }
 %typemap(ret) IF_FALSE_RETURN_NONE
 {
@@ -425,7 +425,7 @@ OGRErrMessages( int rc ) {
   }
   convert_to_long_ex($input);
   val = ($*1_ltype) Z_LVAL_PP( $input );
-  $1 = &val;  
+  $1 = &val;
 }
 %typemap(typecheck,precedence=0) (int *optional_int)
 {
diff --git a/swig/include/python/callback.i b/swig/include/python/callback.i
index 45e2703..27e9065 100644
--- a/swig/include/python/callback.i
+++ b/swig/include/python/callback.i
@@ -14,7 +14,7 @@ typedef struct {
 /*                          PyProgressProxy()                           */
 /************************************************************************/
 
-int CPL_STDCALL
+static int CPL_STDCALL
 PyProgressProxy( double dfComplete, const char *pszMessage, void *pData )
 
 {
@@ -29,19 +29,25 @@ PyProgressProxy( double dfComplete, const char *pszMessage, void *pData )
         return TRUE;
 
     psInfo->nLastReported = (int) (100.0 * dfComplete);
-    
+
     if( pszMessage == NULL )
         pszMessage = "";
 
     if( psInfo->psPyCallbackData == NULL )
         psArgs = Py_BuildValue("(dsO)", dfComplete, pszMessage, Py_None );
     else
-        psArgs = Py_BuildValue("(dsO)", dfComplete, pszMessage, 
+        psArgs = Py_BuildValue("(dsO)", dfComplete, pszMessage,
 	                       psInfo->psPyCallbackData );
 
     psResult = PyEval_CallObject( psInfo->psPyCallback, psArgs);
     Py_XDECREF(psArgs);
 
+    if( PyErr_Occurred() != NULL )
+    {
+        PyErr_Clear();
+        return FALSE;
+    }
+
     if( psResult == NULL )
     {
         return TRUE;
@@ -49,19 +55,20 @@ PyProgressProxy( double dfComplete, const char *pszMessage, void *pData )
 
     if( psResult == Py_None )
     {
-	Py_XDECREF(Py_None);
         return TRUE;
     }
 
     if( !PyArg_Parse( psResult, "i", &bContinue ) )
     {
-        PyErr_SetString(PyExc_ValueError, "bad progress return value");
+        PyErr_Clear();
+        CPLError(CE_Failure, CPLE_AppDefined, "bad progress return value");
+        Py_XDECREF(psResult);
 	return FALSE;
     }
 
     Py_XDECREF(psResult);
 
-    return bContinue;    
+    return bContinue;
 }
 %}
 
diff --git a/swig/include/python/docs/README b/swig/include/python/docs/README
index e849dad..187613d 100644
--- a/swig/include/python/docs/README
+++ b/swig/include/python/docs/README
@@ -1,10 +1,10 @@
 The .i files in this directory are generated files and should not be edited
 manually.
 
-1) cd $(GDAL_ROOT)/ogr
+1) cd $(GDAL_ROOT)
 2) ( cat Doxyfile ; echo "GENERATE_XML=YES" ) | doxygen -
 
-This will generate a $(GDAL_ROOT)/ogr/xml directory with the doc in XML form
+This will generate a $(GDAL_ROOT)/xml directory with the doc in XML form
 
 3) cd $(GDAL_ROOT)/swig/python
 4) make docs
diff --git a/swig/include/python/docs/doxy2swig.py b/swig/include/python/docs/doxy2swig.py
index 519aec7..61a9c33 100755
--- a/swig/include/python/docs/doxy2swig.py
+++ b/swig/include/python/docs/doxy2swig.py
@@ -43,14 +43,13 @@ def my_open_write(dest):
         return open(dest, 'w')
 
 
-class Doxy2SWIG:    
+class Doxy2SWIG:
     """Converts Doxygen generated XML files into a file containing
     docstrings that can be used by SWIG-1.3.x that have support for
     feature("docstring").  Once the data is parsed it is stored in
     self.pieces.
+    """
 
-    """    
-    
     def __init__(self, src):
         """Initialize the instance given a source object (file or
         filename).
@@ -76,14 +75,14 @@ class Doxy2SWIG:
                         'reimplementedby', 'derivedcompoundref',
                         'basecompoundref')
         #self.generics = []
-        
+
     def generate(self):
         """Parses the file set in the initialization.  The resulting
         data is stored in `self.pieces`.
 
         """
         self.parse(self.xmldoc)
-    
+
     def parse(self, node):
         """Parse a given node.  This function in turn calls the
         `parse_<nodeType>` functions which handle the respective
@@ -109,10 +108,9 @@ class Doxy2SWIG:
 
     def parse_Element(self, node):
         """Parse an `ELEMENT_NODE`.  This calls specific
-        `do_<tagName>` handers for different elements.  If no handler
+        `do_<tagName>` handlers for different elements.  If no handler
         is available the `generic_parse` method is called.  All
         tagNames specified in `self.ignores` are simply ignored.
-        
         """
         name = node.tagName
         ignores = self.ignores
diff --git a/swig/include/python/docs/ogr_datasource_docs.i b/swig/include/python/docs/ogr_datasource_docs.i
index 6071242..bba5205 100644
--- a/swig/include/python/docs/ogr_datasource_docs.i
+++ b/swig/include/python/docs/ogr_datasource_docs.i
@@ -1,7 +1,7 @@
 %extend OGRDataSourceShadow {
 // File: ogrdatasource_8cpp.xml
 %feature("docstring")  CPL_CVSID "CPL_CVSID(\"$Id: ogrdatasource.cpp
-23403 2011-11-20 21:01:21Z ajolma $\") ";
+33105 2016-01-23 15:27:32Z rouault $\") ";
 
 %feature("docstring")  Destroy "void OGR_DS_Destroy(OGRDataSourceH
 hDS)
@@ -11,6 +11,8 @@ Closes opened datasource and releases allocated resources.
 This method is the same as the C++ method
 OGRDataSource::DestroyDataSource().
 
+Deprecated Use GDALClose() in GDAL 2.0
+
 Parameters:
 -----------
 
@@ -40,8 +42,7 @@ The papszOptions argument can be used to control driver specific
 creation options. These options are normally documented in the format
 specific documentation.
 
-This function is the same as the C++ method
-OGRDataSource::CreateLayer().
+Deprecated Use GDALDatasetCreateLayer() in GDAL 2.0
 
 Parameters:
 -----------
@@ -59,7 +60,7 @@ no constraints on the types geometry to be written.
 
 papszOptions:  a StringList of name=value options. Options are driver
 specific, and driver information can be found at the following
-url:http://www.gdal.org/ogr/ogr_formats.html
+url:http://www.gdal.org/ogr_formats.html
 
 NULL is returned on failure, or a new OGRLayer handle on success.
 Example: ";
@@ -77,7 +78,7 @@ creation options. These options are normally documented in the format
 specific documentation. The source layer may come from another
 dataset.
 
-This function is the same as the C++ method OGRDataSource::CopyLayer
+Deprecated Use GDALDatasetCopyLayer() in GDAL 2.0
 
 Parameters:
 -----------
@@ -101,8 +102,7 @@ Delete the indicated layer from the datasource.
 If this method is supported the ODsCDeleteLayer capability will test
 TRUE on the OGRDataSource.
 
-This method is the same as the C++ method
-OGRDataSource::DeleteLayer().
+Deprecated Use GDALDatasetDeleteLayer() in GDAL 2.0
 
 Parameters:
 -----------
@@ -122,8 +122,7 @@ Fetch a layer by name.
 The returned layer remains owned by the OGRDataSource and should not
 be deleted by the application.
 
-This function is the same as the C++ method
-OGRDataSource::GetLayerByName().
+Deprecated Use GDALDatasetGetLayerByName() in GDAL 2.0
 
 Parameters:
 -----------
@@ -135,10 +134,6 @@ pszLayerName:  Layer the layer name of the layer to fetch.
 an handle to the layer, or NULL if the layer is not found or an error
 occurs. ";
 
-%feature("docstring")  OGRDataSourceParseSQLType "static OGRFieldType
-OGRDataSourceParseSQLType(char *pszType, int &nWidth, int &nPrecision)
-";
-
 %feature("docstring")  ExecuteSQL "OGRLayerH
 OGR_DS_ExecuteSQL(OGRDataSourceH hDS, const char *pszStatement,
 OGRGeometryH hSpatialFilter, const char *pszDialect)
@@ -153,11 +148,12 @@ OGR_DS_ReleaseResultSet() before the data source is closed
 (destroyed).
 
 For more information on the SQL dialect supported internally by OGR
-review theOGR SQL document. Some drivers (ie. Oracle and PostGIS) pass
-the SQL directly through to the underlying RDBMS.
+review theOGR SQL document. Some drivers (i.e. Oracle and PostGIS)
+pass the SQL directly through to the underlying RDBMS.
+
+Starting with OGR 1.10, theSQLITE dialect can also be used.
 
-This function is the same as the C++ method
-OGRDataSource::ExecuteSQL();
+Deprecated Use GDALDatasetExecuteSQL() in GDAL 2.0
 
 Parameters:
 -----------
@@ -172,7 +168,8 @@ filter. Can be NULL.
 pszDialect:  allows control of the statement dialect. If set to NULL,
 the OGR SQL engine will be used, except for RDBMS drivers that will
 use their dedicated SQL engine, unless OGRSQL is explicitly passed as
-the dialect.
+the dialect. Starting with OGR 1.10, the SQLITE dialect can also be
+used.
 
 an handle to a OGRLayer containing the results of the query.
 Deallocate with OGR_DS_ReleaseResultSet(). ";
@@ -187,8 +184,7 @@ from an OGR_DS_ExecuteSQL() call on the same OGRDataSource. Failure to
 deallocate a results set before destroying the OGRDataSource may cause
 errors.
 
-This function is the same as the C++ method
-OGRDataSource::ReleaseResultSet().
+Deprecated Use GDALDatasetReleaseResultSet() in GDAL 2.0
 
 Parameters:
 -----------
@@ -209,11 +205,19 @@ whether or not the capability is available for this object.
 
 ODsCCreateLayer: True if this datasource can create new layers.
 
+ODsCDeleteLayer: True if this datasource can delete existing layers.
+
+ODsCCreateGeomFieldAfterCreateLayer: True if the layers of this
+datasource support CreateGeomField() just after layer creation.
+
+ODsCCurveGeometries: True if this datasource supports writing curve
+geometries. (GDAL 2.0). In that case, OLCCurveGeometries must also be
+declared in layers of that dataset.
+
 The #define macro forms of the capability names should be used in
-preference to the strings themselves to avoid mispelling.
+preference to the strings themselves to avoid misspelling.
 
-This function is the same as the C++ method
-OGRDataSource::TestCapability().
+Deprecated Use GDALDatasetTestCapability() in GDAL 2.0
 
 Parameters:
 -----------
@@ -229,8 +233,7 @@ OGR_DS_GetLayerCount(OGRDataSourceH hDS)
 
 Get the number of layers in this data source.
 
-This function is the same as the C++ method
-OGRDataSource::GetLayerCount().
+Deprecated Use GDALDatasetGetLayerCount() in GDAL 2.0
 
 Parameters:
 -----------
@@ -248,7 +251,7 @@ Fetch a layer by index.
 The returned layer remains owned by the OGRDataSource and should not
 be deleted by the application.
 
-This function is the same as the C++ method OGRDataSource::GetLayer().
+Deprecated Use GDALDatasetGetLayer() in GDAL 2.0
 
 Parameters:
 -----------
@@ -270,7 +273,7 @@ the same OGRSFDriver that this data source was opened with, but it
 need not be exactly the same string that was used to open the data
 source. Normally this is a filename.
 
-This function is the same as the C++ method OGRDataSource::GetName().
+Deprecated Use GDALGetDescription() in GDAL 2.0
 
 Parameters:
 -----------
@@ -281,42 +284,18 @@ pointer to an internal name string which should not be modified or
 freed by the caller. ";
 
 %feature("docstring")  SyncToDisk "OGRErr
-OGR_DS_SyncToDisk(OGRDataSourceH hDS)
-
-Flush pending changes to disk.
-
-This call is intended to force the datasource to flush any pending
-writes to disk, and leave the disk file in a consistent state. It
-would not normally have any effect on read-only datasources.
-
-Some data sources do not implement this method, and will still return
-OGRERR_NONE. An error is only returned if an error occurs while
-attempting to flush to disk.
-
-The default implementation of this method just calls the SyncToDisk()
-method on each of the layers. Conceptionally, calling SyncToDisk() on
-a datasource should include any work that might be accomplished by
-calling SyncToDisk() on layers in that data source.
-
-In any event, you should always close any opened datasource with
-OGR_DS_Destroy() that will ensure all data is correctly flushed.
-
-This method is the same as the C++ method OGRDataSource::SyncToDisk()
-
-Parameters:
------------
-
-hDS:  handle to the data source
-
-OGRERR_NONE if no error occurs (even if nothing is done) or an error
-code. ";
+OGR_DS_SyncToDisk(OGRDataSourceH hDS) ";
 
 %feature("docstring")  GetDriver "OGRSFDriverH
 OGR_DS_GetDriver(OGRDataSourceH hDS)
 
 Returns the driver that the dataset was opened with.
 
-This method is the same as the C++ method OGRDataSource::GetDriver()
+NOTE: Starting with GDAL 2.0, it is *NOT* safe to cast the returned
+handle to OGRSFDriver*. If a C++ object is needed, the handle should
+be cast to GDALDriver*.
+
+Deprecated Use GDALGetDatasetDriver() in GDAL 2.0
 
 Parameters:
 -----------
diff --git a/swig/include/python/docs/ogr_driver_docs.i b/swig/include/python/docs/ogr_driver_docs.i
index 2a9e85e..48b3ef4 100644
--- a/swig/include/python/docs/ogr_driver_docs.i
+++ b/swig/include/python/docs/ogr_driver_docs.i
@@ -1,7 +1,7 @@
 %extend OGRDriverShadow {
 // File: ogrsfdriver_8cpp.xml
 %feature("docstring")  CPL_CVSID "CPL_CVSID(\"$Id: ogrsfdriver.cpp
-23413 2011-11-22 21:53:32Z rouault $\") ";
+32177 2015-12-14 07:25:30Z goatbar $\") ";
 
 %feature("docstring")  CreateDataSource "OGRDataSourceH
 OGR_Dr_CreateDataSource(OGRSFDriverH hDriver, const char *pszName,
@@ -17,8 +17,7 @@ specific documentation.
 It is important to call OGR_DS_Destroy() when the datasource is no
 longer used to ensure that all data has been properly flushed to disk.
 
-This function is the same as the C++ method
-OGRSFDriver::CreateDataSource().
+Deprecated Use GDALCreate() in GDAL 2.0
 
 Parameters:
 -----------
@@ -29,7 +28,7 @@ pszName:  the name for the new data source. UTF-8 encoded.
 
 papszOptions:  a StringList of name=value options. Options are driver
 specific, and driver information can be found at the following
-url:http://www.gdal.org/ogr/ogr_formats.html
+url:http://www.gdal.org/ogr_formats.html
 
 NULL is returned on failure, or a new OGRDataSource handle on success.
 ";
@@ -47,8 +46,7 @@ time.
 Whether this is a supported operation on this driver case be tested
 using TestCapability() on ODrCDeleteDataSource.
 
-This method is the same as the C++ method
-OGRSFDriver::DeleteDataSource().
+Deprecated Use GDALDeleteDataset() in GDAL 2
 
 Parameters:
 -----------
@@ -63,16 +61,17 @@ not supported by this driver. ";
 %feature("docstring")  GetName "const char*
 OGR_Dr_GetName(OGRSFDriverH hDriver)
 
-Fetch name of driver (file format). This name should be relatively
-short (10-40 characters), and should reflect the underlying file
-format. For instance \"ESRI Shapefile\".
+Fetch name of driver (file format).
+
+This name should be relatively short (10-40 characters), and should
+reflect the underlying file format. For instance \"ESRI Shapefile\".
 
 This function is the same as the C++ method OGRSFDriver::GetName().
 
 Parameters:
 -----------
 
-hDriver:  handle to the the driver to get the name from.
+hDriver:  handle to the driver to get the name from.
 
 driver name. This is an internal string and should not be modified or
 freed. ";
@@ -82,7 +81,12 @@ hDriver, const char *pszName, int bUpdate)
 
 Attempt to open file with this driver.
 
-This function is the same as the C++ method OGRSFDriver::Open().
+NOTE: Starting with GDAL 2.0, it is *NOT* safe to cast the returned
+handle to OGRDataSource*. If a C++ object is needed, the handle should
+be cast to GDALDataset*. Similarly, the returned OGRSFDriverH handle
+should be cast to GDALDriver*, and NOT* OGRSFDriver*.
+
+Deprecated Use GDALOpenEx() in GDAL 2.0
 
 Parameters:
 -----------
@@ -95,7 +99,7 @@ bUpdate:  TRUE if update access is required, otherwise FALSE (the
 default).
 
 NULL on error or if the pass name is not supported by this driver,
-otherwise an handle to an OGRDataSource. This OGRDataSource should be
+otherwise an handle to a GDALDataset. This GDALDataset should be
 closed by deleting the object when it is no longer needed. ";
 
 %feature("docstring")  TestCapability "int
@@ -114,10 +118,10 @@ ODrCDeleteDataSource: True if this driver supports deleting data
 sources.
 
 The #define macro forms of the capability names should be used in
-preference to the strings themselves to avoid mispelling.
+preference to the strings themselves to avoid misspelling.
 
-This function is the same as the C++ method
-OGRSFDriver::TestCapability().
+Deprecated Use GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATE) in GDAL
+2.0
 
 Parameters:
 -----------
@@ -138,8 +142,7 @@ the source datasource.
 It is important to call OGR_DS_Destroy() when the datasource is no
 longer used to ensure that all data has been properly flushed to disk.
 
-This function is the same as the C++ method
-OGRSFDriver::CopyDataSource().
+Deprecated Use GDALCreateCopy() in GDAL 2.0
 
 Parameters:
 -----------
@@ -152,7 +155,7 @@ pszNewName:  the name for the new data source.
 
 papszOptions:  a StringList of name=value options. Options are driver
 specific, and driver information can be found at the following
-url:http://www.gdal.org/ogr/ogr_formats.html
+url:http://www.gdal.org/ogr_formats.html
 
 NULL is returned on failure, or a new OGRDataSource handle on success.
 ";
diff --git a/swig/include/python/docs/ogr_feature_docs.i b/swig/include/python/docs/ogr_feature_docs.i
index 94b4045..9ff27b6 100644
--- a/swig/include/python/docs/ogr_feature_docs.i
+++ b/swig/include/python/docs/ogr_feature_docs.i
@@ -1,7 +1,7 @@
 %extend OGRFeatureShadow {
 // File: ogrfeature_8cpp.xml
 %feature("docstring")  CPL_CVSID "CPL_CVSID(\"$Id: ogrfeature.cpp
-23414 2011-11-23 05:50:05Z warmerdam $\") ";
+33440 2016-02-12 12:02:43Z ajolma $\") ";
 
 %feature("docstring")  Create "OGRFeatureH
 OGR_F_Create(OGRFeatureDefnH hDefn)
@@ -21,8 +21,8 @@ Parameters:
 hDefn:  handle to the feature class (layer) definition to which the
 feature will adhere.
 
-an handle to the new feature object with null fields and no geometry.
-";
+an handle to the new feature object with null fields and no geometry,
+or, starting with GDAL 2.1, NULL in case out of memory situation. ";
 
 %feature("docstring")  Destroy "void OGR_F_Destroy(OGRFeatureH hFeat)
 
@@ -64,7 +64,7 @@ Set feature geometry.
 
 This function updates the features geometry, and operate exactly as
 SetGeometry(), except that this function assumes ownership of the
-passed geometry.
+passed geometry (even in case of failure of that function).
 
 This function is the same as the C++ method
 OGRFeature::SetGeometryDirectly.
@@ -109,7 +109,7 @@ Take away ownership of geometry.
 
 Fetch the geometry from this feature, and clear the reference to the
 geometry on the feature. This is a mechanism for the application to
-take over ownship of the geometry from the feature without copying.
+take over ownership of the geometry from the feature without copying.
 Sort of an inverse to OGR_FSetGeometryDirectly().
 
 After this call the OGRFeature will have a NULL geometry.
@@ -132,6 +132,78 @@ hFeat:  handle to the feature to get geometry from.
 an handle to internal feature geometry. This object should not be
 modified. ";
 
+%feature("docstring")  GetGeomFieldRef "OGRGeometryH
+OGR_F_GetGeomFieldRef(OGRFeatureH hFeat, int iField)
+
+Fetch an handle to feature geometry.
+
+This function is the same as the C++ method
+OGRFeature::GetGeomFieldRef().
+
+Parameters:
+-----------
+
+hFeat:  handle to the feature to get geometry from.
+
+iField:  geometry field to get.
+
+an handle to internal feature geometry. This object should not be
+modified.
+
+GDAL 1.11 ";
+
+%feature("docstring")  SetGeomFieldDirectly "OGRErr
+OGR_F_SetGeomFieldDirectly(OGRFeatureH hFeat, int iField, OGRGeometryH
+hGeom)
+
+Set feature geometry of a specified geometry field.
+
+This function updates the features geometry, and operate exactly as
+SetGeomField(), except that this function assumes ownership of the
+passed geometry (even in case of failure of that function).
+
+This function is the same as the C++ method
+OGRFeature::SetGeomFieldDirectly.
+
+Parameters:
+-----------
+
+hFeat:  handle to the feature on which to apply the geometry.
+
+iField:  geometry field to set.
+
+hGeom:  handle to the new geometry to apply to feature.
+
+OGRERR_NONE if successful, or OGRERR_FAILURE if the index is invalid,
+or OGR_UNSUPPORTED_GEOMETRY_TYPE if the geometry type is illegal for
+the OGRFeatureDefn (checking not yet implemented).
+
+GDAL 1.11 ";
+
+%feature("docstring")  SetGeomField "OGRErr
+OGR_F_SetGeomField(OGRFeatureH hFeat, int iField, OGRGeometryH hGeom)
+
+Set feature geometry of a specified geometry field.
+
+This function updates the features geometry, and operate exactly as
+SetGeometryDirectly(), except that this function does not assume
+ownership of the passed geometry, but instead makes a copy of it.
+
+This function is the same as the C++ OGRFeature::SetGeomField().
+
+Parameters:
+-----------
+
+hFeat:  handle to the feature on which new geometry is applied to.
+
+iField:  geometry field to set.
+
+hGeom:  handle to the new geometry to apply to feature.
+
+OGRERR_NONE if successful, or OGR_UNSUPPORTED_GEOMETRY_TYPE if the
+geometry type is illegal for the OGRFeatureDefn (checking not yet
+implemented). ";
+
 %feature("docstring")  Clone "OGRFeatureH OGR_F_Clone(OGRFeatureH
 hFeat)
 
@@ -202,6 +274,66 @@ pszName:  the name of the field to search for.
 
 the field index, or -1 if no matching field is found. ";
 
+%feature("docstring")  GetGeomFieldCount "int
+OGR_F_GetGeomFieldCount(OGRFeatureH hFeat)
+
+Fetch number of geometry fields on this feature This will always be
+the same as the geometry field count for the OGRFeatureDefn.
+
+This function is the same as the C++ method
+OGRFeature::GetGeomFieldCount().
+
+Parameters:
+-----------
+
+hFeat:  handle to the feature to get the geometry fields count from.
+
+count of geometry fields.
+
+GDAL 1.11 ";
+
+%feature("docstring")  GetGeomFieldDefnRef "OGRGeomFieldDefnH
+OGR_F_GetGeomFieldDefnRef(OGRFeatureH hFeat, int i)
+
+Fetch definition for this geometry field.
+
+This function is the same as the C++ method
+OGRFeature::GetGeomFieldDefnRef().
+
+Parameters:
+-----------
+
+hFeat:  handle to the feature on which the field is found.
+
+i:  the field to fetch, from 0 to GetGeomFieldCount()-1.
+
+an handle to the field definition (from the OGRFeatureDefn). This is
+an internal reference, and should not be deleted or modified.
+
+GDAL 1.11 ";
+
+%feature("docstring")  GetGeomFieldIndex "int
+OGR_F_GetGeomFieldIndex(OGRFeatureH hFeat, const char *pszName)
+
+Fetch the geometry field index given geometry field name.
+
+This is a cover for the OGRFeatureDefn::GetGeomFieldIndex() method.
+
+This function is the same as the C++ method
+OGRFeature::GetGeomFieldIndex().
+
+Parameters:
+-----------
+
+hFeat:  handle to the feature on which the geometry field is found.
+
+pszName:  the name of the geometry field to search for.
+
+the geometry field index, or -1 if no matching geometry field is
+found.
+
+GDAL 1.11 ";
+
 %feature("docstring")  IsFieldSet "int OGR_F_IsFieldSet(OGRFeatureH
 hFeat, int iField)
 
@@ -271,14 +403,38 @@ iField:  the field to fetch, from 0 to GetFieldCount()-1.
 
 the field value. ";
 
+%feature("docstring")  GetFieldAsInteger64 "GIntBig
+OGR_F_GetFieldAsInteger64(OGRFeatureH hFeat, int iField)
+
+Fetch field value as integer 64 bit.
+
+OFTInteger are promoted to 64 bit. OFTString features will be
+translated using CPLAtoGIntBig(). OFTReal fields will be cast to
+integer. Other field types, or errors will result in a return value of
+zero.
+
+This function is the same as the C++ method
+OGRFeature::GetFieldAsInteger64().
+
+Parameters:
+-----------
+
+hFeat:  handle to the feature that owned the field.
+
+iField:  the field to fetch, from 0 to GetFieldCount()-1.
+
+the field value.
+
+GDAL 2.0 ";
+
 %feature("docstring")  GetFieldAsDouble "double
 OGR_F_GetFieldAsDouble(OGRFeatureH hFeat, int iField)
 
 Fetch field value as a double.
 
-OFTString features will be translated using atof(). OFTInteger fields
-will be cast to double. Other field types, or errors will result in a
-return value of zero.
+OFTString features will be translated using CPLAtof(). OFTInteger
+fields will be cast to double. Other field types, or errors will
+result in a return value of zero.
 
 This function is the same as the C++ method
 OGRFeature::GetFieldAsDouble().
@@ -292,6 +448,11 @@ iField:  the field to fetch, from 0 to GetFieldCount()-1.
 
 the field value. ";
 
+%feature("docstring")  OGRFeatureFormatDateTimeBuffer "static void
+OGRFeatureFormatDateTimeBuffer(char szTempBuffer[TEMP_BUFFER_SIZE],
+int nYear, int nMonth, int nDay, int nHour, int nMinute, float
+fSecond, int nTZFlag) ";
+
 %feature("docstring")  GetFieldAsString "const char*
 OGR_F_GetFieldAsString(OGRFeatureH hFeat, int iField)
 
@@ -338,6 +499,32 @@ the field value. This list is internal, and should not be modified, or
 freed. Its lifetime may be very brief. If *pnCount is zero on return
 the returned pointer may be NULL or non-NULL. ";
 
+%feature("docstring")  GetFieldAsInteger64List "const GIntBig*
+OGR_F_GetFieldAsInteger64List(OGRFeatureH hFeat, int iField, int
+*pnCount)
+
+Fetch field value as a list of 64 bit integers.
+
+Currently this function only works for OFTInteger64List fields.
+
+This function is the same as the C++ method
+OGRFeature::GetFieldAsInteger64List().
+
+Parameters:
+-----------
+
+hFeat:  handle to the feature that owned the field.
+
+iField:  the field to fetch, from 0 to GetFieldCount()-1.
+
+pnCount:  an integer to put the list count (number of integers) into.
+
+the field value. This list is internal, and should not be modified, or
+freed. Its lifetime may be very brief. If *pnCount is zero on return
+the returned pointer may be NULL or non-NULL.
+
+GDAL 2.0 ";
+
 %feature("docstring")  GetFieldAsDoubleList "const double*
 OGR_F_GetFieldAsDoubleList(OGRFeatureH hFeat, int iField, int
 *pnCount)
@@ -390,7 +577,7 @@ OGR_F_GetFieldAsBinary(OGRFeatureH hFeat, int iField, int *pnBytes)
 
 Fetch field value as binary.
 
-Currently this method only works for OFTBinary fields.
+This method only works for OFTBinary and OFTString fields.
 
 This function is the same as the C++ method
 OGRFeature::GetFieldAsBinary().
@@ -442,17 +629,62 @@ pnSecond:  (0-59)
 pnTZFlag:  (0=unknown, 1=localtime, 100=GMT, see data model for
 details)
 
-TRUE on success or FALSE on failure. ";
+TRUE on success or FALSE on failure.
+
+See:  Use OGR_F_GetFieldAsDateTimeEx() for second with millisecond
+accuracy. ";
+
+%feature("docstring")  GetFieldAsDateTimeEx "int
+OGR_F_GetFieldAsDateTimeEx(OGRFeatureH hFeat, int iField, int *pnYear,
+int *pnMonth, int *pnDay, int *pnHour, int *pnMinute, float *pfSecond,
+int *pnTZFlag)
+
+Fetch field value as date and time.
+
+Currently this method only works for OFTDate, OFTTime and OFTDateTime
+fields.
+
+This function is the same as the C++ method
+OGRFeature::GetFieldAsDateTime().
+
+Parameters:
+-----------
+
+hFeat:  handle to the feature that owned the field.
+
+iField:  the field to fetch, from 0 to GetFieldCount()-1.
+
+pnYear:  (including century)
+
+pnMonth:  (1-12)
+
+pnDay:  (1-31)
+
+pnHour:  (0-23)
+
+pnMinute:  (0-59)
+
+pfSecond:  (0-59 with millisecond accuracy)
+
+pnTZFlag:  (0=unknown, 1=localtime, 100=GMT, see data model for
+details)
+
+TRUE on success or FALSE on failure.
+
+GDAL 2.0 ";
+
+%feature("docstring")  OGRFeatureGetIntegerValue "static int
+OGRFeatureGetIntegerValue(OGRFieldDefn *poFDefn, int nValue) ";
 
 %feature("docstring")  SetFieldInteger "void
 OGR_F_SetFieldInteger(OGRFeatureH hFeat, int iField, int nValue)
 
 Set field to integer value.
 
-OFTInteger and OFTReal fields will be set directly. OFTString fields
-will be assigned a string representation of the value, but not
-necessarily taking into account formatting constraints on this field.
-Other field types may be unaffected.
+OFTInteger, OFTInteger64 and OFTReal fields will be set directly.
+OFTString fields will be assigned a string representation of the
+value, but not necessarily taking into account formatting constraints
+on this field. Other field types may be unaffected.
 
 This function is the same as the C++ method OGRFeature::SetField().
 
@@ -465,15 +697,38 @@ iField:  the field to fetch, from 0 to GetFieldCount()-1.
 
 nValue:  the value to assign. ";
 
+%feature("docstring")  SetFieldInteger64 "void
+OGR_F_SetFieldInteger64(OGRFeatureH hFeat, int iField, GIntBig nValue)
+
+Set field to 64 bit integer value.
+
+OFTInteger, OFTInteger64 and OFTReal fields will be set directly.
+OFTString fields will be assigned a string representation of the
+value, but not necessarily taking into account formatting constraints
+on this field. Other field types may be unaffected.
+
+This function is the same as the C++ method OGRFeature::SetField().
+
+Parameters:
+-----------
+
+hFeat:  handle to the feature that owned the field.
+
+iField:  the field to fetch, from 0 to GetFieldCount()-1.
+
+nValue:  the value to assign.
+
+GDAL 2.0 ";
+
 %feature("docstring")  SetFieldDouble "void
 OGR_F_SetFieldDouble(OGRFeatureH hFeat, int iField, double dfValue)
 
 Set field to double value.
 
-OFTInteger and OFTReal fields will be set directly. OFTString fields
-will be assigned a string representation of the value, but not
-necessarily taking into account formatting constraints on this field.
-Other field types may be unaffected.
+OFTInteger, OFTInteger64 and OFTReal fields will be set directly.
+OFTString fields will be assigned a string representation of the
+value, but not necessarily taking into account formatting constraints
+on this field. Other field types may be unaffected.
 
 This function is the same as the C++ method OGRFeature::SetField().
 
@@ -493,8 +748,10 @@ OGR_F_SetFieldString(OGRFeatureH hFeat, int iField, const char
 Set field to string value.
 
 OFTInteger fields will be set based on an atoi() conversion of the
-string. OFTReal fields will be set based on an atof() conversion of
-the string. Other field types may be unaffected.
+string. OFTInteger64 fields will be set based on an CPLAtoGIntBig()
+conversion of the string. OFTReal fields will be set based on an
+CPLAtof() conversion of the string. Other field types may be
+unaffected.
 
 This function is the same as the C++ method OGRFeature::SetField().
 
@@ -513,7 +770,8 @@ int *panValues)
 
 Set field to list of integers value.
 
-This function currently on has an effect of OFTIntegerList fields.
+This function currently on has an effect of OFTIntegerList,
+OFTInteger64List and OFTRealList fields.
 
 This function is the same as the C++ method OGRFeature::SetField().
 
@@ -528,13 +786,38 @@ nCount:  the number of values in the list being assigned.
 
 panValues:  the values to assign. ";
 
+%feature("docstring")  SetFieldInteger64List "void
+OGR_F_SetFieldInteger64List(OGRFeatureH hFeat, int iField, int nCount,
+const GIntBig *panValues)
+
+Set field to list of 64 bit integers value.
+
+This function currently on has an effect of OFTIntegerList,
+OFTInteger64List and OFTRealList fields.
+
+This function is the same as the C++ method OGRFeature::SetField().
+
+Parameters:
+-----------
+
+hFeat:  handle to the feature that owned the field.
+
+iField:  the field to set, from 0 to GetFieldCount()-1.
+
+nCount:  the number of values in the list being assigned.
+
+panValues:  the values to assign.
+
+GDAL 2.0 ";
+
 %feature("docstring")  SetFieldDoubleList "void
 OGR_F_SetFieldDoubleList(OGRFeatureH hFeat, int iField, int nCount,
 double *padfValues)
 
 Set field to list of doubles value.
 
-This function currently on has an effect of OFTRealList fields.
+This function currently on has an effect of OFTIntegerList,
+OFTInteger64List, OFTRealList fields.
 
 This function is the same as the C++ method OGRFeature::SetField().
 
@@ -618,7 +901,43 @@ nMinute:  (0-59)
 nSecond:  (0-59)
 
 nTZFlag:  (0=unknown, 1=localtime, 100=GMT, see data model for
-details) ";
+details)
+
+See:  Use OGR_F_SetFieldDateTimeEx() for second with millisecond
+accuracy. ";
+
+%feature("docstring")  SetFieldDateTimeEx "void
+OGR_F_SetFieldDateTimeEx(OGRFeatureH hFeat, int iField, int nYear, int
+nMonth, int nDay, int nHour, int nMinute, float fSecond, int nTZFlag)
+
+Set field to datetime.
+
+This method currently only has an effect for OFTDate, OFTTime and
+OFTDateTime fields.
+
+Parameters:
+-----------
+
+hFeat:  handle to the feature that owned the field.
+
+iField:  the field to set, from 0 to GetFieldCount()-1.
+
+nYear:  (including century)
+
+nMonth:  (1-12)
+
+nDay:  (1-31)
+
+nHour:  (0-23)
+
+nMinute:  (0-59)
+
+fSecond:  (0-59, with millisecond accuracy)
+
+nTZFlag:  (0=unknown, 1=localtime, 100=GMT, see data model for
+details)
+
+GDAL 2.0 ";
 
 %feature("docstring")  SetFieldRaw "void
 OGR_F_SetFieldRaw(OGRFeatureH hFeat, int iField, OGRField *psValue)
@@ -660,11 +979,14 @@ hFeat:  handle to the feature to dump.
 
 fpOut:  the stream to write to, such as strout. ";
 
-%feature("docstring")  GetFID "long OGR_F_GetFID(OGRFeatureH hFeat)
+%feature("docstring")  GetFID "GIntBig OGR_F_GetFID(OGRFeatureH
+hFeat)
 
 Get feature identifier.
 
 This function is the same as the C++ method OGRFeature::GetFID().
+Note: since GDAL 2.0, this method returns a GIntBig (previously a
+long)
 
 Parameters:
 -----------
@@ -675,7 +997,7 @@ identifier.
 feature id or OGRNullFID if none has been assigned. ";
 
 %feature("docstring")  SetFID "OGRErr OGR_F_SetFID(OGRFeatureH hFeat,
-long nFID)
+GIntBig nFID)
 
 Set the feature identifier.
 
@@ -802,9 +1124,11 @@ isn't one. ";
 %feature("docstring")  SetStyleString "void
 OGR_F_SetStyleString(OGRFeatureH hFeat, const char *pszStyle)
 
-Set feature style string. This method operate exactly as
-OGR_F_SetStyleStringDirectly() except that it does not assume
-ownership of the passed string, but instead makes a copy of it.
+Set feature style string.
+
+This method operate exactly as OGR_F_SetStyleStringDirectly() except
+that it does not assume ownership of the passed string, but instead
+makes a copy of it.
 
 This function is the same as the C++ method
 OGRFeature::SetStyleString().
@@ -820,9 +1144,10 @@ pszStyle:  the style string to apply to this feature, cannot be NULL.
 %feature("docstring")  SetStyleStringDirectly "void
 OGR_F_SetStyleStringDirectly(OGRFeatureH hFeat, char *pszStyle)
 
-Set feature style string. This method operate exactly as
-OGR_F_SetStyleString() except that it assumes ownership of the passed
-string.
+Set feature style string.
+
+This method operate exactly as OGR_F_SetStyleString() except that it
+assumes ownership of the passed string.
 
 This function is the same as the C++ method
 OGRFeature::SetStyleStringDirectly().
@@ -845,4 +1170,172 @@ hStyleTable) ";
 %feature("docstring")  SetStyleTable "void
 OGR_F_SetStyleTable(OGRFeatureH hFeat, OGRStyleTableH hStyleTable) ";
 
+%feature("docstring")  FillUnsetWithDefault "void
+OGR_F_FillUnsetWithDefault(OGRFeatureH hFeat, int bNotNullableOnly,
+char **papszOptions)
+
+Fill unset fields with default values that might be defined.
+
+This function is the same as the C++ method
+OGRFeature::FillUnsetWithDefault().
+
+Parameters:
+-----------
+
+hFeat:  handle to the feature.
+
+bNotNullableOnly:  if we should fill only unset fields with a not-null
+constraint.
+
+papszOptions:  unused currently. Must be set to NULL.
+
+GDAL 2.0 ";
+
+%feature("docstring")  Validate "int OGR_F_Validate(OGRFeatureH
+hFeat, int nValidateFlags, int bEmitError)
+
+Validate that a feature meets constraints of its schema.
+
+The scope of test is specified with the nValidateFlags parameter.
+
+Regarding OGR_F_VAL_WIDTH, the test is done assuming the string width
+must be interpreted as the number of UTF-8 characters. Some drivers
+might interpret the width as the number of bytes instead. So this test
+is rather conservative (if it fails, then it will fail for all
+interpretations).
+
+This function is the same as the C++ method OGRFeature::Validate().
+
+Parameters:
+-----------
+
+hFeat:  handle to the feature to validate.
+
+nValidateFlags:  OGR_F_VAL_ALL or combination of OGR_F_VAL_NULL,
+OGR_F_VAL_GEOM_TYPE, OGR_F_VAL_WIDTH and
+OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT with '|' operator
+
+bEmitError:  TRUE if a CPLError() must be emitted when a check fails
+
+TRUE if all enabled validation tests pass.
+
+GDAL 2.0 ";
+
+%feature("docstring")  GetNativeData "const char*
+OGR_F_GetNativeData(OGRFeatureH hFeat)
+
+Returns the native data for the feature.
+
+The native data is the representation in a \"natural\" form that comes
+from the driver that created this feature, or that is aimed at an
+output driver. The native data may be in different format, which is
+indicated by OGR_F_GetNativeMediaType().
+
+Note that most drivers do not support storing the native data in the
+feature object, and if they do, generally the NATIVE_DATA open option
+must be passed at dataset opening.
+
+The \"native data\" does not imply it is something more performant or
+powerful than what can be obtained with the rest of the API, but it
+may be useful in round-tripping scenarios where some characteristics
+of the underlying format are not captured otherwise by the OGR
+abstraction.
+
+This function is the same as the C++ method
+OGRFeature::GetNativeData().
+
+Parameters:
+-----------
+
+hFeat:  handle to the feature.
+
+a string with the native data, or NULL if there is none.
+
+GDAL 2.1
+
+See:
+https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
+";
+
+%feature("docstring")  GetNativeMediaType "const char*
+OGR_F_GetNativeMediaType(OGRFeatureH hFeat)
+
+Returns the native media type for the feature.
+
+The native media type is the identifier for the format of the native
+data. It follows the IANA RFC 2045
+(seehttps://en.wikipedia.org/wiki/Media_type), e.g.
+\"application/vnd.geo+json\" for JSon.
+
+This function is the same as the C function
+OGR_F_GetNativeMediaType().
+
+Parameters:
+-----------
+
+hFeat:  handle to the feature.
+
+a string with the native media type, or NULL if there is none.
+
+GDAL 2.1
+
+See:
+https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
+";
+
+%feature("docstring")  SetNativeData "void
+OGR_F_SetNativeData(OGRFeatureH hFeat, const char *pszNativeData)
+
+Sets the native data for the feature.
+
+The native data is the representation in a \"natural\" form that comes
+from the driver that created this feature, or that is aimed at an
+output driver. The native data may be in different format, which is
+indicated by OGR_F_GetNativeMediaType().
+
+This function is the same as the C++ method
+OGRFeature::SetNativeData().
+
+Parameters:
+-----------
+
+hFeat:  handle to the feature.
+
+pszNativeData:  a string with the native data, or NULL if there is
+none.
+
+GDAL 2.1
+
+See:
+https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
+";
+
+%feature("docstring")  SetNativeMediaType "void
+OGR_F_SetNativeMediaType(OGRFeatureH hFeat, const char
+*pszNativeMediaType)
+
+Sets the native media type for the feature.
+
+The native media type is the identifier for the format of the native
+data. It follows the IANA RFC 2045
+(seehttps://en.wikipedia.org/wiki/Media_type), e.g.
+\"application/vnd.geo+json\" for JSon.
+
+This function is the same as the C++ method
+OGRFeature::SetNativeMediaType().
+
+Parameters:
+-----------
+
+hFeat:  handle to the feature.
+
+pszNativeMediaType:  a string with the native media type, or NULL if
+there is none.
+
+GDAL 2.1
+
+See:
+https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
+";
+
 }
\ No newline at end of file
diff --git a/swig/include/python/docs/ogr_featuredef_docs.i b/swig/include/python/docs/ogr_featuredef_docs.i
index 65cf886..ba84461 100644
--- a/swig/include/python/docs/ogr_featuredef_docs.i
+++ b/swig/include/python/docs/ogr_featuredef_docs.i
@@ -1,7 +1,7 @@
 %extend OGRFeatureDefnShadow {
 // File: ogrfeaturedefn_8cpp.xml
 %feature("docstring")  CPL_CVSID "CPL_CVSID(\"$Id: ogrfeaturedefn.cpp
-22900 2011-08-07 20:47:41Z rouault $\") ";
+32696 2016-01-03 10:48:58Z rouault $\") ";
 
 %feature("docstring")  Create "OGRFeatureDefnH OGR_FD_Create(const
 char *pszName)
@@ -109,7 +109,7 @@ To add a new field definition to a layer definition, do not use this
 function directly, but use OGR_L_CreateField() instead.
 
 This function should only be called while there are no OGRFeature
-objects in existance based on this OGRFeatureDefn. The OGRFieldDefn
+objects in existence based on this OGRFeatureDefn. The OGRFieldDefn
 passed in is copied, and remains the responsibility of the caller.
 
 This function is the same as the C++ method
@@ -132,7 +132,7 @@ To delete an existing field definition from a layer definition, do not
 use this function directly, but use OGR_L_DeleteField() instead.
 
 This method should only be called while there are no OGRFeature
-objects in existance based on this OGRFeatureDefn.
+objects in existence based on this OGRFeatureDefn.
 
 This method is the same as the C++ method
 OGRFeatureDefn::DeleteFieldDefn().
@@ -142,14 +142,14 @@ Parameters:
 
 hDefn:  handle to the feature definition.
 
-iField:  the index of the field defintion.
+iField:  the index of the field definition.
 
 OGRERR_NONE in case of success.
 
 OGR 1.9.0 ";
 
-%feature("docstring")  ReorderFieldDefn "OGRErr
-OGR_FD_ReorderFieldDefn(OGRFeatureDefnH hDefn, int *panMap)
+%feature("docstring")  ReorderFieldDefns "OGRErr
+OGR_FD_ReorderFieldDefns(OGRFeatureDefnH hDefn, int *panMap)
 
 Reorder the field definitions in the array of the feature definition.
 
@@ -157,7 +157,7 @@ To reorder the field definitions in a layer definition, do not use
 this function directly, but use OGR_L_ReorderFields() instead.
 
 This method should only be called while there are no OGRFeature
-objects in existance based on this OGRFeatureDefn.
+objects in existence based on this OGRFeatureDefn.
 
 This method is the same as the C++ method
 OGRFeatureDefn::ReorderFieldDefns().
@@ -174,7 +174,120 @@ reordering was panMap[i].
 
 OGRERR_NONE in case of success.
 
-OGR 1.9.0 ";
+OGR 2.1.0 ";
+
+%feature("docstring")  GetGeomFieldCount "int
+OGR_FD_GetGeomFieldCount(OGRFeatureDefnH hDefn)
+
+Fetch number of geometry fields on the passed feature definition.
+
+This function is the same as the C++
+OGRFeatureDefn::GetGeomFieldCount().
+
+Parameters:
+-----------
+
+hDefn:  handle to the feature definition to get the fields count from.
+
+count of geometry fields.
+
+GDAL 1.11 ";
+
+%feature("docstring")  GetGeomFieldDefn "OGRGeomFieldDefnH
+OGR_FD_GetGeomFieldDefn(OGRFeatureDefnH hDefn, int iGeomField)
+
+Fetch geometry field definition of the passed feature definition.
+
+This function is the same as the C++ method
+OGRFeatureDefn::GetGeomFieldDefn().
+
+Parameters:
+-----------
+
+hDefn:  handle to the feature definition to get the field definition
+from.
+
+iGeomField:  the geometry field to fetch, between 0 and
+GetGeomFieldCount()-1.
+
+an handle to an internal field definition object or NULL if invalid
+index. This object should not be modified or freed by the application.
+
+GDAL 1.11 ";
+
+%feature("docstring")  AddGeomFieldDefn "void
+OGR_FD_AddGeomFieldDefn(OGRFeatureDefnH hDefn, OGRGeomFieldDefnH
+hNewGeomField)
+
+Add a new field definition to the passed feature definition.
+
+To add a new field definition to a layer definition, do not use this
+function directly, but use OGR_L_CreateGeomField() instead.
+
+This function should only be called while there are no OGRFeature
+objects in existence based on this OGRFeatureDefn. The
+OGRGeomFieldDefn passed in is copied, and remains the responsibility
+of the caller.
+
+This function is the same as the C++ method
+OGRFeatureDefn::AddGeomFieldDefn().
+
+Parameters:
+-----------
+
+hDefn:  handle to the feature definition to add the geometry field
+definition to.
+
+hNewGeomField:  handle to the new field definition.
+
+GDAL 1.11 ";
+
+%feature("docstring")  DeleteGeomFieldDefn "OGRErr
+OGR_FD_DeleteGeomFieldDefn(OGRFeatureDefnH hDefn, int iGeomField)
+
+Delete an existing geometry field definition.
+
+To delete an existing geometry field definition from a layer
+definition, do not use this function directly, but use
+OGR_L_DeleteGeomField() instead (*not implemented yet*).
+
+This method should only be called while there are no OGRFeature
+objects in existence based on this OGRFeatureDefn.
+
+This method is the same as the C++ method
+OGRFeatureDefn::DeleteGeomFieldDefn().
+
+Parameters:
+-----------
+
+hDefn:  handle to the feature definition.
+
+iGeomField:  the index of the geometry field definition.
+
+OGRERR_NONE in case of success.
+
+GDAL 1.11 ";
+
+%feature("docstring")  GetGeomFieldIndex "int
+OGR_FD_GetGeomFieldIndex(OGRFeatureDefnH hDefn, const char
+*pszGeomFieldName)
+
+Find geometry field by name.
+
+The geometry field index of the first geometry field matching the
+passed field name (case insensitively) is returned.
+
+This function is the same as the C++ method
+OGRFeatureDefn::GetGeomFieldIndex.
+
+Parameters:
+-----------
+
+hDefn:  handle to the feature definition to get field index from.
+
+pszGeomFieldName:  the geometry field name to search for.
+
+the geometry field index, or -1 if no match found. ";
 
 %feature("docstring")  GetGeomType "OGRwkbGeometryType
 OGR_FD_GetGeomType(OGRFeatureDefnH hDefn)
@@ -184,6 +297,9 @@ Fetch the geometry base type of the passed feature definition.
 This function is the same as the C++ method
 OGRFeatureDefn::GetGeomType().
 
+Starting with GDAL 1.11, this method returns
+GetGeomFieldDefn(0)->GetType().
+
 Parameters:
 -----------
 
@@ -206,6 +322,9 @@ after any OGRFeatures have been created against this definition.
 This function is the same as the C++ method
 OGRFeatureDefn::SetGeomType().
 
+Starting with GDAL 1.11, this method calls
+GetGeomFieldDefn(0)->SetType().
+
 Parameters:
 -----------
 
@@ -260,7 +379,7 @@ OGRFeatureDefn::GetReferenceCount().
 Parameters:
 -----------
 
-hDefn:  hanlde to the feature definition on witch OGRFeature are based
+hDefn:  handle to the feature definition on witch OGRFeature are based
 on.
 
 the current reference count. ";
@@ -293,10 +412,13 @@ Determine whether the geometry can be omitted when fetching features.
 This function is the same as the C++ method
 OGRFeatureDefn::IsGeometryIgnored().
 
+Starting with GDAL 1.11, this method returns
+GetGeomFieldDefn(0)->IsIgnored().
+
 Parameters:
 -----------
 
-hDefn:  hanlde to the feature definition on witch OGRFeature are based
+hDefn:  handle to the feature definition on witch OGRFeature are based
 on.
 
 ignore state ";
@@ -309,10 +431,13 @@ Set whether the geometry can be omitted when fetching features.
 This function is the same as the C++ method
 OGRFeatureDefn::SetGeometryIgnored().
 
+Starting with GDAL 1.11, this method calls
+GetGeomFieldDefn(0)->SetIgnored().
+
 Parameters:
 -----------
 
-hDefn:  hanlde to the feature definition on witch OGRFeature are based
+hDefn:  handle to the feature definition on witch OGRFeature are based
 on.
 
 bIgnore:  ignore state ";
@@ -344,9 +469,26 @@ OGRFeatureDefn::SetStyleIgnored().
 Parameters:
 -----------
 
-hDefn:  hanlde to the feature definition on witch OGRFeature are based
+hDefn:  handle to the feature definition on witch OGRFeature are based
 on.
 
 bIgnore:  ignore state ";
 
+%feature("docstring")  IsSame "int OGR_FD_IsSame(OGRFeatureDefnH
+hFDefn, OGRFeatureDefnH hOtherFDefn)
+
+Test if the feature definition is identical to the other one.
+
+Parameters:
+-----------
+
+hFDefn:  handle to the feature definition on witch OGRFeature are
+based on.
+
+hOtherFDefn:  handle to the other feature definition to compare to.
+
+TRUE if the feature definition is identical to the other one.
+
+OGR 1.11 ";
+
 }
\ No newline at end of file
diff --git a/swig/include/python/docs/ogr_fielddef_docs.i b/swig/include/python/docs/ogr_fielddef_docs.i
index 23a4eef..7cc8122 100644
--- a/swig/include/python/docs/ogr_fielddef_docs.i
+++ b/swig/include/python/docs/ogr_fielddef_docs.i
@@ -1,13 +1,16 @@
 %extend OGRFieldDefnShadow {
 // File: ogrfielddefn_8cpp.xml
 %feature("docstring")  CPL_CVSID "CPL_CVSID(\"$Id: ogrfielddefn.cpp
-21018 2010-10-30 11:30:51Z rouault $\") ";
+31961 2015-12-03 02:01:09Z goatbar $\") ";
 
 %feature("docstring")  Create "OGRFieldDefnH OGR_Fld_Create(const
 char *pszName, OGRFieldType eType)
 
 Create a new field definition.
 
+By default, fields have no width, precision, are nullable and not
+ignored.
+
 This function is the same as the CPP method
 OGRFieldDefn::OGRFieldDefn().
 
@@ -76,8 +79,10 @@ field type. ";
 %feature("docstring")  SetType "void OGR_Fld_SetType(OGRFieldDefnH
 hDefn, OGRFieldType eType)
 
-Set the type of this field. This should never be done to an
-OGRFieldDefn that is already part of an OGRFeatureDefn.
+Set the type of this field.
+
+This should never be done to an OGRFieldDefn that is already part of
+an OGRFeatureDefn.
 
 This function is the same as the CPP method OGRFieldDefn::SetType().
 
@@ -88,6 +93,117 @@ hDefn:  handle to the field definition to set type to.
 
 eType:  the new field type. ";
 
+%feature("docstring")  GetSubType "OGRFieldSubType
+OGR_Fld_GetSubType(OGRFieldDefnH hDefn)
+
+Fetch subtype of this field.
+
+This function is the same as the CPP method
+OGRFieldDefn::GetSubType().
+
+Parameters:
+-----------
+
+hDefn:  handle to the field definition to get subtype from.
+
+field subtype.
+
+GDAL 2.0 ";
+
+%feature("docstring")  SetSubType "void
+OGR_Fld_SetSubType(OGRFieldDefnH hDefn, OGRFieldSubType eSubType)
+
+Set the subtype of this field.
+
+This should never be done to an OGRFieldDefn that is already part of
+an OGRFeatureDefn.
+
+This function is the same as the CPP method
+OGRFieldDefn::SetSubType().
+
+Parameters:
+-----------
+
+hDefn:  handle to the field definition to set type to.
+
+eSubType:  the new field subtype.
+
+GDAL 2.0 ";
+
+%feature("docstring")  SetDefault "void
+OGR_Fld_SetDefault(OGRFieldDefnH hDefn, const char *pszDefault)
+
+Set default field value.
+
+The default field value is taken into account by drivers (generally
+those with a SQL interface) that support it at field creation time.
+OGR will generally not automatically set the default field value to
+null fields by itself when calling OGRFeature::CreateFeature() /
+OGRFeature::SetFeature(), but will let the low-level layers to do the
+job. So retrieving the feature from the layer is recommended.
+
+The accepted values are NULL, a numeric value, a literal value
+enclosed between single quote characters (and inner single quote
+characters escaped by repetition of the single quote character),
+CURRENT_TIMESTAMP, CURRENT_TIME, CURRENT_DATE or a driver specific
+expression (that might be ignored by other drivers). For a datetime
+literal value, format should be 'YYYY/MM/DD HH:MM:SS[.sss]'
+(considered as UTC time).
+
+Drivers that support writing DEFAULT clauses will advertize the
+GDAL_DCAP_DEFAULT_FIELDS driver metadata item.
+
+This function is the same as the C++ method
+OGRFieldDefn::SetDefault().
+
+Parameters:
+-----------
+
+hDefn:  handle to the field definition.
+
+pszDefault:  new default field value or NULL pointer.
+
+GDAL 2.0 ";
+
+%feature("docstring")  GetDefault "const char*
+OGR_Fld_GetDefault(OGRFieldDefnH hDefn)
+
+Get default field value.
+
+This function is the same as the C++ method
+OGRFieldDefn::GetDefault().
+
+Parameters:
+-----------
+
+hDefn:  handle to the field definition.
+
+default field value or NULL.
+
+GDAL 2.0 ";
+
+%feature("docstring")  IsDefaultDriverSpecific "int
+OGR_Fld_IsDefaultDriverSpecific(OGRFieldDefnH hDefn)
+
+Returns whether the default value is driver specific.
+
+Driver specific default values are those that are *not* NULL, a
+numeric value, a literal value enclosed between single quote
+characters, CURRENT_TIMESTAMP, CURRENT_TIME, CURRENT_DATE or datetime
+literal value.
+
+This function is the same as the C++ method
+OGRFieldDefn::IsDefaultDriverSpecific().
+
+Parameters:
+-----------
+
+hDefn:  handle to the field definition
+
+TRUE if the default value is driver specific.
+
+GDAL 2.0 ";
+
 %feature("docstring")  OGR_GetFieldTypeName "const char*
 OGR_GetFieldTypeName(OGRFieldType eType)
 
@@ -103,6 +219,40 @@ eType:  the field type to get name for.
 
 the name. ";
 
+%feature("docstring")  OGR_GetFieldSubTypeName "const char*
+OGR_GetFieldSubTypeName(OGRFieldSubType eSubType)
+
+Fetch human readable name for a field subtype.
+
+This function is the same as the CPP method
+OGRFieldDefn::GetFieldSubTypeName().
+
+Parameters:
+-----------
+
+eSubType:  the field subtype to get name for.
+
+the name.
+
+GDAL 2.0 ";
+
+%feature("docstring")  OGR_AreTypeSubTypeCompatible "int
+OGR_AreTypeSubTypeCompatible(OGRFieldType eType, OGRFieldSubType
+eSubType)
+
+Return if type and subtype are compatible.
+
+Parameters:
+-----------
+
+eType:  the field type.
+
+eSubType:  the field subtype.
+
+TRUE if type and subtype are compatible
+
+GDAL 2.0 ";
+
 %feature("docstring")  GetJustify "OGRJustification
 OGR_Fld_GetJustify(OGRFieldDefnH hDefn)
 
@@ -111,6 +261,8 @@ Get the justification for this field.
 This function is the same as the CPP method
 OGRFieldDefn::GetJustify().
 
+Note: no driver is know to use the concept of field justification.
+
 Parameters:
 -----------
 
@@ -123,6 +275,8 @@ OGR_Fld_SetJustify(OGRFieldDefnH hDefn, OGRJustification eJustify)
 
 Set the justification for this field.
 
+Note: no driver is know to use the concept of field justification.
+
 This function is the same as the CPP method
 OGRFieldDefn::SetJustify().
 
@@ -164,8 +318,9 @@ nNewWidth:  the new width. ";
 %feature("docstring")  GetPrecision "int
 OGR_Fld_GetPrecision(OGRFieldDefnH hDefn)
 
-Get the formatting precision for this field. This should normally be
-zero for fields of types other than OFTReal.
+Get the formatting precision for this field.
+
+This should normally be zero for fields of types other than OFTReal.
 
 This function is the same as the CPP method
 OGRFieldDefn::GetPrecision().
@@ -239,7 +394,7 @@ OGR_Fld_SetIgnored(OGRFieldDefnH hDefn, int ignore)
 
 Set whether this field should be omitted when fetching features.
 
-This method is the same as the C function OGRFieldDefn::SetIgnored().
+This method is the same as the C++ method OGRFieldDefn::SetIgnored().
 
 Parameters:
 -----------
@@ -248,4 +403,71 @@ hDefn:  handle to the field definition
 
 ignore:  ignore state ";
 
+%feature("docstring")  IsNullable "int
+OGR_Fld_IsNullable(OGRFieldDefnH hDefn)
+
+Return whether this field can receive null values.
+
+By default, fields are nullable.
+
+Even if this method returns FALSE (i.e not-nullable field), it doesn't
+mean that OGRFeature::IsFieldSet() will necessary return TRUE, as
+fields can be temporary unset and null/not-null validation is usually
+done when OGRLayer::CreateFeature()/SetFeature() is called.
+
+This method is the same as the C++ method OGRFieldDefn::IsNullable().
+
+Parameters:
+-----------
+
+hDefn:  handle to the field definition
+
+TRUE if the field is authorized to be null.
+
+GDAL 2.0 ";
+
+%feature("docstring")  SetNullable "void
+OGR_Fld_SetNullable(OGRFieldDefnH hDefn, int bNullableIn)
+
+Set whether this field can receive null values.
+
+By default, fields are nullable, so this method is generally called
+with FALSE to set a not-null constraint.
+
+Drivers that support writing not-null constraint will advertize the
+GDAL_DCAP_NOTNULL_FIELDS driver metadata item.
+
+This method is the same as the C++ method OGRFieldDefn::SetNullable().
+
+Parameters:
+-----------
+
+hDefn:  handle to the field definition
+
+bNullableIn:  FALSE if the field must have a not-null constraint.
+
+GDAL 2.0 ";
+
+%feature("docstring")  OGRUpdateFieldType "void
+OGRUpdateFieldType(OGRFieldDefn *poFDefn, OGRFieldType eNewType,
+OGRFieldSubType eNewSubType)
+
+Update the type of a field definition by \"merging\" its existing type
+with a new type.
+
+The update is done such as broadening the type. For example a
+OFTInteger updated with OFTInteger64 will be promoted to OFTInteger64.
+
+Parameters:
+-----------
+
+poFDefn:  the field definition whose type must be updated.
+
+eNewType:  the new field type to merge into the existing type.
+
+eNewSubType:  the new field subtype to merge into the existing
+subtype.
+
+GDAL 2.1 ";
+
 }
\ No newline at end of file
diff --git a/swig/include/python/docs/ogr_geometry_docs.i b/swig/include/python/docs/ogr_geometry_docs.i
index 2cae4c0..9f190f8 100644
--- a/swig/include/python/docs/ogr_geometry_docs.i
+++ b/swig/include/python/docs/ogr_geometry_docs.i
@@ -1,7 +1,7 @@
 %extend OGRGeometryShadow {
 // File: ogrgeometry_8cpp.xml
 %feature("docstring")  CPL_CVSID "CPL_CVSID(\"$Id: ogrgeometry.cpp
-23140 2011-09-29 20:13:09Z rouault $\") ";
+33616 2016-03-02 22:14:26Z rouault $\") ";
 
 %feature("docstring")  DumpReadable "void
 OGR_G_DumpReadable(OGRGeometryH hGeom, FILE *fp, const char
@@ -50,9 +50,9 @@ hGeom, OGRGeometryH hOtherGeom)
 
 Do these features intersect?
 
-Currently this is not implemented in a rigerous fashion, and generally
-just tests whether the envelopes of the two features intersect.
-Eventually this will be made rigerous.
+Determines whether two geometries intersect. If GEOS is enabled, then
+this is done in rigorous fashion otherwise TRUE is returned if the
+envelopes (bounding boxes) of the two geometries overlap.
 
 This function is the same as the CPP method OGRGeometry::Intersects.
 
@@ -173,9 +173,6 @@ OGR_G_GetCoordinateDimension(OGRGeometryH hGeom)
 
 Get the dimension of the coordinates in this geometry.
 
-This function corresponds to the SFCOM IGeometry::GetDimension()
-method.
-
 This function is the same as the CPP method
 OGRGeometry::getCoordinateDimension().
 
@@ -185,8 +182,57 @@ Parameters:
 hGeom:  handle on the geometry to get the dimension of the coordinates
 from.
 
-in practice this will return 2 or 3. It can also return 0 in the case
-of an empty point. ";
+Deprecated use OGR_G_CoordinateDimension(), OGR_G_Is3D(), or
+OGR_G_IsMeasured().
+
+this will return 2 or 3. ";
+
+%feature("docstring")  CoordinateDimension "int
+OGR_G_CoordinateDimension(OGRGeometryH hGeom)
+
+Get the dimension of the coordinates in this geometry.
+
+This function is the same as the CPP method
+OGRGeometry::CoordinateDimension().
+
+Parameters:
+-----------
+
+hGeom:  handle on the geometry to get the dimension of the coordinates
+from.
+
+this will return 2 for XY, 3 for XYZ and XYM, and 4 for XYZM data. ";
+
+%feature("docstring")  Is3D "int OGR_G_Is3D(OGRGeometryH hGeom)
+
+See whether this geometry has Z coordinates.
+
+This function is the same as the CPP method OGRGeometry::Is3D().
+
+Parameters:
+-----------
+
+hGeom:  handle on the geometry to check whether it has Z coordinates.
+
+TRUE if the geometry has Z coordinates.
+
+GDAL 2.1 ";
+
+%feature("docstring")  IsMeasured "int OGR_G_IsMeasured(OGRGeometryH
+hGeom)
+
+See whether this geometry is measured.
+
+This function is the same as the CPP method OGRGeometry::IsMeasured().
+
+Parameters:
+-----------
+
+hGeom:  handle on the geometry to check whether it is measured.
+
+TRUE if the geometry has M coordinates.
+
+GDAL 2.1 ";
 
 %feature("docstring")  SetCoordinateDimension "void
 OGR_G_SetCoordinateDimension(OGRGeometryH hGeom, int nNewDimension)
@@ -195,8 +241,11 @@ Set the coordinate dimension.
 
 This method sets the explicit coordinate dimension. Setting the
 coordinate dimension of a geometry to 2 should zero out any existing Z
-values. Setting the dimension of a geometry collection will not
-necessarily affect the children geometries.
+values. Setting the dimension of a geometry collection, a compound
+curve, a polygon, etc. will affect the children geometries. This will
+also remove the M dimension if present before this call.
+
+Deprecated use OGR_G_Set3D() or OGR_G_SetMeasured().
 
 Parameters:
 -----------
@@ -206,6 +255,46 @@ coordinates.
 
 nNewDimension:  New coordinate dimension value, either 2 or 3. ";
 
+%feature("docstring")  Set3D "void OGR_G_Set3D(OGRGeometryH hGeom,
+int bIs3D)
+
+Add or remove the Z coordinate dimension.
+
+This method adds or removes the explicit Z coordinate dimension.
+Removing the Z coordinate dimension of a geometry will remove any
+existing Z values. Adding the Z dimension to a geometry collection, a
+compound curve, a polygon, etc. will affect the children geometries.
+
+Parameters:
+-----------
+
+hGeom:  handle on the geometry to set or unset the Z dimension.
+
+bIs3D:  Should the geometry have a Z dimension, either TRUE or FALSE.
+
+GDAL 2.1 ";
+
+%feature("docstring")  SetMeasured "void
+OGR_G_SetMeasured(OGRGeometryH hGeom, int bIsMeasured)
+
+Set the coordinate dimension.
+
+Add or remove the M coordinate dimension. This method adds or removes
+the explicit M coordinate dimension. Removing the M coordinate
+dimension of a geometry will remove any existing M values. Adding the
+M dimension to a geometry collection, a compound curve, a polygon,
+etc. will affect the children geometries.
+
+Parameters:
+-----------
+
+hGeom:  handle on the geometry to set or unset the M dimension.
+
+bIsMeasured:  Should the geometry have a M dimension, either TRUE or
+FALSE.
+
+GDAL 2.1 ";
+
 %feature("docstring")  Equals "int OGR_G_Equals(OGRGeometryH hGeom,
 OGRGeometryH hOther)
 
@@ -310,12 +399,18 @@ returned. ";
 OGR_G_ExportToWkb(OGRGeometryH hGeom, OGRwkbByteOrder eOrder, unsigned
 char *pabyDstBuffer)
 
-Convert a geometry into well known binary format.
+Convert a geometry well known binary format.
 
 This function relates to the SFCOM IWks::ExportToWKB() method.
 
+For backward compatibility purposes, it exports the Old-style 99-402
+extended dimension (Z) WKB types for types Point, LineString, Polygon,
+MultiPoint, MultiLineString, MultiPolygon and GeometryCollection. For
+other geometry types, it is equivalent to OGR_G_ExportToIsoWkb().
+
 This function is the same as the CPP method
-OGRGeometry::exportToWkb().
+OGRGeometry::exportToWkb(OGRwkbByteOrder, unsigned char *,
+OGRwkbVariant) with eWkbVariant = wkbVariantOldOgc.
 
 Parameters:
 -----------
@@ -331,6 +426,37 @@ written. This buffer must be at least OGR_G_WkbSize() byte in size.
 
 Currently OGRERR_NONE is always returned. ";
 
+%feature("docstring")  ExportToIsoWkb "OGRErr
+OGR_G_ExportToIsoWkb(OGRGeometryH hGeom, OGRwkbByteOrder eOrder,
+unsigned char *pabyDstBuffer)
+
+Convert a geometry into SFSQL 1.2 / ISO SQL/MM Part 3 well known
+binary format.
+
+This function relates to the SFCOM IWks::ExportToWKB() method. It
+exports the SFSQL 1.2 and ISO SQL/MM Part 3 extended dimension (Z&M)
+WKB types
+
+This function is the same as the CPP method
+OGRGeometry::exportToWkb(OGRwkbByteOrder, unsigned char *,
+OGRwkbVariant) with eWkbVariant = wkbVariantIso.
+
+Parameters:
+-----------
+
+hGeom:  handle on the geometry to convert to a well know binary data
+from.
+
+eOrder:  One of wkbXDR or wkbNDR indicating MSB or LSB byte order
+respectively.
+
+pabyDstBuffer:  a buffer into which the binary representation is
+written. This buffer must be at least OGR_G_WkbSize() byte in size.
+
+Currently OGRERR_NONE is always returned.
+
+GDAL 2.0 ";
+
 %feature("docstring")  ImportFromWkt "OGRErr
 OGR_G_ImportFromWkt(OGRGeometryH hGeom, char **ppszSrcText)
 
@@ -363,6 +489,11 @@ Convert a geometry into well known text format.
 
 This function relates to the SFCOM IWks::ExportToWKT() method.
 
+For backward compatibility purposes, it exports the Old-style 99-402
+extended dimension (Z) WKB types for types Point, LineString, Polygon,
+MultiPoint, MultiLineString, MultiPolygon and GeometryCollection. For
+other geometry types, it is equivalent to OGR_G_ExportToIsoWkt().
+
 This function is the same as the CPP method
 OGRGeometry::exportToWkt().
 
@@ -372,10 +503,37 @@ Parameters:
 hGeom:  handle on the geometry to convert to a text format from.
 
 ppszSrcText:  a text buffer is allocated by the program, and assigned
-to the passed pointer.
+to the passed pointer. After use, *ppszDstText should be freed with
+OGRFree().
 
 Currently OGRERR_NONE is always returned. ";
 
+%feature("docstring")  ExportToIsoWkt "OGRErr
+OGR_G_ExportToIsoWkt(OGRGeometryH hGeom, char **ppszSrcText)
+
+Convert a geometry into SFSQL 1.2 / ISO SQL/MM Part 3 well known text
+format.
+
+This function relates to the SFCOM IWks::ExportToWKT() method. It
+exports the SFSQL 1.2 and ISO SQL/MM Part 3 extended dimension (Z&M)
+WKB types
+
+This function is the same as the CPP method
+OGRGeometry::exportToWkt(,wkbVariantIso).
+
+Parameters:
+-----------
+
+hGeom:  handle on the geometry to convert to a text format from.
+
+ppszSrcText:  a text buffer is allocated by the program, and assigned
+to the passed pointer. After use, *ppszDstText should be freed with
+OGRFree().
+
+Currently OGRERR_NONE is always returned.
+
+GDAL 2.0 ";
+
 %feature("docstring")  GetGeometryType "OGRwkbGeometryType
 OGR_G_GetGeometryType(OGRGeometryH hGeom)
 
@@ -449,8 +607,10 @@ a reference to the spatial reference geometry. ";
 
 %feature("docstring")  Empty "void OGR_G_Empty(OGRGeometryH hGeom)
 
-Clear geometry information. This restores the geometry to it's initial
-state after construction, and before assignment of actual geometry.
+Clear geometry information.
+
+This restores the geometry to it's initial state after construction,
+and before assignment of actual geometry.
 
 This function relates to the SFCOM IGeometry::Empty() method.
 
@@ -540,8 +700,10 @@ OGRToOGCGeomType(OGRwkbGeometryType eGeomType) ";
 %feature("docstring")  OGRGeometryTypeToName "const char*
 OGRGeometryTypeToName(OGRwkbGeometryType eType)
 
-Fetch a human readable name corresponding to an OGRwkBGeometryType
-value. The returned value should not be modified, or freed by the
+Fetch a human readable name corresponding to an OGRwkbGeometryType
+value.
+
+The returned value should not be modified, or freed by the
 application.
 
 This function is C callable.
@@ -566,8 +728,8 @@ the most specific geometry type that can be reported for the layer.
 NOTE: wkbUnknown is the \"worst case\" indicating a mixture of
 geometry types with nothing in common but the base geometry type.
 wkbNone should be used to indicate that no geometries have been
-encountered yet, and means the first geometry encounted will establish
-the preliminary type.
+encountered yet, and means the first geometry encountered will
+establish the preliminary type.
 
 Parameters:
 -----------
@@ -578,11 +740,48 @@ eExtra:  the second input geometry type.
 
 the merged geometry type. ";
 
+%feature("docstring")  OGRMergeGeometryTypesEx "OGRwkbGeometryType
+OGRMergeGeometryTypesEx(OGRwkbGeometryType eMain, OGRwkbGeometryType
+eExtra, int bAllowPromotingToCurves)
+
+Find common geometry type.
+
+Given two geometry types, find the most specific common type. Normally
+used repeatedly with the geometries in a layer to try and establish
+the most specific geometry type that can be reported for the layer.
+
+NOTE: wkbUnknown is the \"worst case\" indicating a mixture of
+geometry types with nothing in common but the base geometry type.
+wkbNone should be used to indicate that no geometries have been
+encountered yet, and means the first geometry encountered will
+establish the preliminary type.
+
+If bAllowPromotingToCurves is set to TRUE, mixing Polygon and
+CurvePolygon will return CurvePolygon. Mixing LineString,
+CircularString, CompoundCurve will return CompoundCurve. Mixing
+MultiPolygon and MultiSurface will return MultiSurface. Mixing
+MultiCurve and MultiLineString will return MultiCurve.
+
+Parameters:
+-----------
+
+eMain:  the first input geometry type.
+
+eExtra:  the second input geometry type.
+
+bAllowPromotingToCurves:  determine if promotion to curve type must be
+done.
+
+the merged geometry type.
+
+GDAL 2.0 ";
+
 %feature("docstring")  FlattenTo2D "void
 OGR_G_FlattenTo2D(OGRGeometryH hGeom)
 
-Convert geometry to strictly 2D. In a sense this converts all Z
-coordinates to 0.0.
+Convert geometry to strictly 2D.
+
+In a sense this converts all Z coordinates to 0.0.
 
 This function is the same as the CPP method
 OGRGeometry::flattenTo2D().
@@ -610,7 +809,8 @@ hFirst, OGRGeometryH hOther)
 
 Compute distance between two geometries.
 
-Returns the shortest distance between the two geometries.
+Returns the shortest distance between the two geometries. The distance
+is expressed into the same unit as the coordinates of the geometries.
 
 This function is the same as the C++ method OGRGeometry::Distance().
 
@@ -694,7 +894,7 @@ within the buffer distance of the original geometry.
 
 Some buffer sections are properly described as curves, but are
 converted to approximate polygons. The nQuadSegs parameter can be used
-to control how many segements should be used to define a 90 degree
+to control how many segments should be used to define a 90 degree
 curve - a quadrant of a circle. A value of 30 is a reasonable default.
 Large values result in large numbers of vertices in the resulting
 buffer geometry while small numbers reduce the accuracy of the result.
@@ -711,7 +911,8 @@ Parameters:
 
 hTarget:  the geometry.
 
-dfDist:  the buffer distance to be applied.
+dfDist:  the buffer distance to be applied. Should be expressed into
+the same unit as the coordinates of the geometry.
 
 nQuadSegs:  the number of segments used to approximate a 90 degree
 (quadrant) of curvature.
@@ -1026,6 +1227,29 @@ error.
 
 OGRERR_NONE on success or OGRERR_FAILURE on error. ";
 
+%feature("docstring")  PointOnSurface "OGRGeometryH
+OGR_G_PointOnSurface(OGRGeometryH hGeom)
+
+Returns a point guaranteed to lie on the surface.
+
+This method relates to the SFCOM ISurface::get_PointOnSurface() method
+however the current implementation based on GEOS can operate on other
+geometry types than the types that are supported by SQL/MM-Part 3 :
+surfaces (polygons) and multisurfaces (multipolygons).
+
+This method is built on the GEOS library, check it for the definition
+of the geometry operation. If OGR is built without the GEOS library,
+this method will always fail, issuing a CPLE_NotSupported error.
+
+Parameters:
+-----------
+
+hGeom:  the geometry to operate on.
+
+a point guaranteed to lie on the surface or NULL if an error occurred.
+
+OGR 1.10 ";
+
 %feature("docstring")  Simplify "OGRGeometryH
 OGR_G_Simplify(OGRGeometryH hThis, double dTolerance)
 
@@ -1052,7 +1276,7 @@ OGR 1.8.0 ";
 %feature("docstring")  SimplifyPreserveTopology "OGRGeometryH
 OGR_G_SimplifyPreserveTopology(OGRGeometryH hThis, double dTolerance)
 
-Compute a simplified geometry.
+Simplify the geometry while preserving topology.
 
 This function is the same as the C++ method
 OGRGeometry::SimplifyPreserveTopology().
@@ -1073,4 +1297,320 @@ the simplified geometry or NULL if an error occurs.
 
 OGR 1.9.0 ";
 
+%feature("docstring")  DelaunayTriangulation "OGRGeometryH
+OGR_G_DelaunayTriangulation(OGRGeometryH hThis, double dfTolerance,
+int bOnlyEdges)
+
+Return a Delaunay triangulation of the vertices of the geometry.
+
+This function is the same as the C++ method
+OGRGeometry::DelaunayTriangulation().
+
+This function is built on the GEOS library, v3.4 or above. If OGR is
+built without the GEOS library, this function will always fail,
+issuing a CPLE_NotSupported error.
+
+Parameters:
+-----------
+
+hThis:  the geometry.
+
+dfTolerance:  optional snapping tolerance to use for improved
+robustness
+
+bOnlyEdges:  if TRUE, will return a MULTILINESTRING, otherwise it will
+return a GEOMETRYCOLLECTION containing triangular POLYGONs.
+
+the geometry resulting from the Delaunay triangulation or NULL if an
+error occurs.
+
+OGR 2.1 ";
+
+%feature("docstring")  Polygonize "OGRGeometryH
+OGR_G_Polygonize(OGRGeometryH hTarget)
+
+Polygonizes a set of sparse edges.
+
+A new geometry object is created and returned containing a collection
+of reassembled Polygons: NULL will be returned if the input collection
+doesn't corresponds to a MultiLinestring, or when reassembling Edges
+into Polygons is impossible due to topological inconsistencies.
+
+This function is the same as the C++ method OGRGeometry::Polygonize().
+
+This function is built on the GEOS library, check it for the
+definition of the geometry operation. If OGR is built without the GEOS
+library, this function will always fail, issuing a CPLE_NotSupported
+error.
+
+Parameters:
+-----------
+
+hTarget:  The Geometry to be polygonized.
+
+a handle to a newly allocated geometry now owned by the caller, or
+NULL on failure.
+
+OGR 1.9.0 ";
+
+%feature("docstring")  OGRHasPreparedGeometrySupport "int
+OGRHasPreparedGeometrySupport() ";
+
+%feature("docstring")  OGRCreatePreparedGeometry "OGRPreparedGeometry* OGRCreatePreparedGeometry(const OGRGeometry
+*poGeom) ";
+
+%feature("docstring")  OGRDestroyPreparedGeometry "void
+OGRDestroyPreparedGeometry(OGRPreparedGeometry *poPreparedGeom) ";
+
+%feature("docstring")  OGRPreparedGeometryIntersects "int
+OGRPreparedGeometryIntersects(const OGRPreparedGeometry
+*poPreparedGeom, const OGRGeometry *poOtherGeom) ";
+
+%feature("docstring")  OGRPreparedGeometryContains "int
+OGRPreparedGeometryContains(const OGRPreparedGeometry *poPreparedGeom,
+const OGRGeometry *poOtherGeom) ";
+
+%feature("docstring")  OGRGeometryFromEWKB "OGRGeometry*
+OGRGeometryFromEWKB(GByte *pabyWKB, int nLength, int *pnSRID, int
+bIsPostGIS1_EWKB) ";
+
+%feature("docstring")  OGRGeometryFromHexEWKB "OGRGeometry*
+OGRGeometryFromHexEWKB(const char *pszBytea, int *pnSRID, int
+bIsPostGIS1_EWKB) ";
+
+%feature("docstring")  OGRGeometryToHexEWKB "char*
+OGRGeometryToHexEWKB(OGRGeometry *poGeometry, int nSRSId, int
+nPostGISMajor, int nPostGISMinor) ";
+
+%feature("docstring")  OGR_GT_Flatten "OGRwkbGeometryType
+OGR_GT_Flatten(OGRwkbGeometryType eType)
+
+Returns the 2D geometry type corresponding to the passed geometry
+type.
+
+This function is intended to work with geometry types as old-style
+99-402 extended dimension (Z) WKB types, as well as with newer SFSQL
+1.2 and ISO SQL/MM Part 3 extended dimension (Z&M) WKB types.
+
+Parameters:
+-----------
+
+eType:  Input geometry type
+
+2D geometry type corresponding to the passed geometry type.
+
+GDAL 2.0 ";
+
+%feature("docstring")  OGR_GT_HasZ "int
+OGR_GT_HasZ(OGRwkbGeometryType eType)
+
+Return if the geometry type is a 3D geometry type.
+
+Parameters:
+-----------
+
+eType:  Input geometry type
+
+TRUE if the geometry type is a 3D geometry type.
+
+GDAL 2.0 ";
+
+%feature("docstring")  OGR_GT_HasM "int
+OGR_GT_HasM(OGRwkbGeometryType eType)
+
+Return if the geometry type is a measured type.
+
+Parameters:
+-----------
+
+eType:  Input geometry type
+
+TRUE if the geometry type is a measured type.
+
+GDAL 2.0 ";
+
+%feature("docstring")  OGR_GT_SetZ "OGRwkbGeometryType
+OGR_GT_SetZ(OGRwkbGeometryType eType)
+
+Returns the 3D geometry type corresponding to the passed geometry
+type.
+
+Parameters:
+-----------
+
+eType:  Input geometry type
+
+3D geometry type corresponding to the passed geometry type.
+
+GDAL 2.0 ";
+
+%feature("docstring")  OGR_GT_SetM "OGRwkbGeometryType
+OGR_GT_SetM(OGRwkbGeometryType eType)
+
+Returns the measured geometry type corresponding to the passed
+geometry type.
+
+Parameters:
+-----------
+
+eType:  Input geometry type
+
+measured geometry type corresponding to the passed geometry type.
+
+GDAL 2.0 ";
+
+%feature("docstring")  OGR_GT_SetModifier "OGRwkbGeometryType
+OGR_GT_SetModifier(OGRwkbGeometryType eType, int bHasZ, int bHasM)
+
+Returns a 2D or 3D geometry type depending on parameter.
+
+Parameters:
+-----------
+
+eType:  Input geometry type
+
+bHasZ:  TRUE if the output geometry type must be 3D.
+
+bHasM:  TRUE if the output geometry type must be measured.
+
+Output geometry type.
+
+GDAL 2.0 ";
+
+%feature("docstring")  OGR_GT_IsSubClassOf "int
+OGR_GT_IsSubClassOf(OGRwkbGeometryType eType, OGRwkbGeometryType
+eSuperType)
+
+Returns if a type is a subclass of another one.
+
+Parameters:
+-----------
+
+eType:  Type.
+
+eSuperType:  Super type
+
+TRUE if eType is a subclass of eSuperType.
+
+GDAL 2.0 ";
+
+%feature("docstring")  OGR_GT_GetCollection "OGRwkbGeometryType
+OGR_GT_GetCollection(OGRwkbGeometryType eType)
+
+Returns the collection type that can contain the passed geometry type.
+
+Handled conversions are : wkbNone->wkbNone, wkbPoint -> wkbMultiPoint,
+wkbLineString->wkbMultiLineString, wkbPolygon->wkbMultiPolygon,
+wkbCircularString->wkbMultiCurve, wkbCompoundCurve->wkbMultiCurve,
+wkbCurvePolygon->wkbMultiSurface. In other cases, wkbUnknown is
+returned
+
+Passed Z flag is preserved.
+
+Parameters:
+-----------
+
+eType:  Input geometry type
+
+the collection type that can contain the passed geometry type or
+wkbUnknown
+
+GDAL 2.0 ";
+
+%feature("docstring")  OGR_GT_GetCurve "OGRwkbGeometryType
+OGR_GT_GetCurve(OGRwkbGeometryType eType)
+
+Returns the curve geometry type that can contain the passed geometry
+type.
+
+Handled conversions are : wkbPolygon -> wkbCurvePolygon,
+wkbLineString->wkbCompoundCurve, wkbMultiPolygon->wkbMultiSurface and
+wkbMultiLineString->wkbMultiCurve. In other cases, the passed geometry
+is returned.
+
+Passed Z flag is preserved.
+
+Parameters:
+-----------
+
+eType:  Input geometry type
+
+the curve type that can contain the passed geometry type
+
+GDAL 2.0 ";
+
+%feature("docstring")  OGR_GT_GetLinear "OGRwkbGeometryType
+OGR_GT_GetLinear(OGRwkbGeometryType eType)
+
+Returns the non-curve geometry type that can contain the passed
+geometry type.
+
+Handled conversions are : wkbCurvePolygon -> wkbPolygon,
+wkbCircularString->wkbLineString, wkbCompoundCurve->wkbLineString,
+wkbMultiSurface->wkbMultiPolygon and
+wkbMultiCurve->wkbMultiLineString. In other cases, the passed geometry
+is returned.
+
+Passed Z flag is preserved.
+
+Parameters:
+-----------
+
+eType:  Input geometry type
+
+the non-curve type that can contain the passed geometry type
+
+GDAL 2.0 ";
+
+%feature("docstring")  OGR_GT_IsCurve "int
+OGR_GT_IsCurve(OGRwkbGeometryType eGeomType)
+
+Return if a geometry type is an instance of Curve.
+
+Such geometry type are wkbLineString, wkbCircularString,
+wkbCompoundCurve and their 3D variant.
+
+Parameters:
+-----------
+
+eGeomType:  the geometry type
+
+TRUE if the geometry type is an instance of Curve
+
+GDAL 2.0 ";
+
+%feature("docstring")  OGR_GT_IsSurface "int
+OGR_GT_IsSurface(OGRwkbGeometryType eGeomType)
+
+Return if a geometry type is an instance of Surface.
+
+Such geometry type are wkbCurvePolygon and wkbPolygon and their 3D
+variant.
+
+Parameters:
+-----------
+
+eGeomType:  the geometry type
+
+TRUE if the geometry type is an instance of Surface
+
+GDAL 2.0 ";
+
+%feature("docstring")  OGR_GT_IsNonLinear "int
+OGR_GT_IsNonLinear(OGRwkbGeometryType eGeomType)
+
+Return if a geometry type is a non-linear geometry type.
+
+Such geometry type are wkbCircularString, wkbCompoundCurve,
+wkbCurvePolygon, wkbMultiCurve, wkbMultiSurface and their 3D variant.
+
+Parameters:
+-----------
+
+eGeomType:  the geometry type
+
+TRUE if the geometry type is a non-linear geometry type.
+
+GDAL 2.0 ";
+
 }
\ No newline at end of file
diff --git a/swig/include/python/docs/ogr_layer_docs.i b/swig/include/python/docs/ogr_layer_docs.i
index 9ff1391..e4b9595 100644
--- a/swig/include/python/docs/ogr_layer_docs.i
+++ b/swig/include/python/docs/ogr_layer_docs.i
@@ -1,7 +1,7 @@
 %extend OGRLayerShadow {
 // File: ogrlayer_8cpp.xml
-%feature("docstring")  CPL_CVSID "CPL_CVSID(\"$Id: ogrlayer.cpp 22724
-2011-07-15 16:45:39Z rouault $\") ";
+%feature("docstring")  CPL_CVSID "CPL_CVSID(\"$Id: ogrlayer.cpp 33568
+2016-02-26 21:01:54Z rouault $\") ";
 
 %feature("docstring")  Reference "int OGR_L_Reference(OGRLayerH
 hLayer) ";
@@ -12,7 +12,7 @@ hLayer) ";
 %feature("docstring")  GetRefCount "int OGR_L_GetRefCount(OGRLayerH
 hLayer) ";
 
-%feature("docstring")  GetFeatureCount "int
+%feature("docstring")  GetFeatureCount "GIntBig
 OGR_L_GetFeatureCount(OGRLayerH hLayer, int bForce)
 
 Fetch the feature count in this layer.
@@ -31,6 +31,8 @@ cursor of the layer.
 
 This function is the same as the CPP OGRLayer::GetFeatureCount().
 
+Note: since GDAL 2.0, this method returns a GIntBig (previously a int)
+
 Parameters:
 -----------
 
@@ -76,6 +78,48 @@ it is expensive.
 
 OGRERR_NONE on success, OGRERR_FAILURE if extent not known. ";
 
+%feature("docstring")  GetExtentEx "OGRErr
+OGR_L_GetExtentEx(OGRLayerH hLayer, int iGeomField, OGREnvelope
+*psExtent, int bForce)
+
+Fetch the extent of this layer, on the specified geometry field.
+
+Returns the extent (MBR) of the data in the layer. If bForce is FALSE,
+and it would be expensive to establish the extent then OGRERR_FAILURE
+will be returned indicating that the extent isn't know. If bForce is
+TRUE then some implementations will actually scan the entire layer
+once to compute the MBR of all the features in the layer.
+
+Depending on the drivers, the returned extent may or may not take the
+spatial filter into account. So it is safer to call OGR_L_GetExtent()
+without setting a spatial filter.
+
+Layers without any geometry may return OGRERR_FAILURE just indicating
+that no meaningful extents could be collected.
+
+Note that some implementations of this method may alter the read
+cursor of the layer.
+
+This function is the same as the C++ method OGRLayer::GetExtent().
+
+Parameters:
+-----------
+
+hLayer:  handle to the layer from which to get extent.
+
+iGeomField:  the index of the geometry field on which to compute the
+extent.
+
+psExtent:  the structure in which the extent value will be returned.
+
+bForce:  Flag indicating whether the extent should be computed even if
+it is expensive.
+
+OGRERR_NONE on success, OGRERR_FAILURE if extent not known. ";
+
+%feature("docstring")  ContainGeomSpecialField "static int
+ContainGeomSpecialField(swq_expr_node *expr, int nLayerFieldCount) ";
+
 %feature("docstring")  SetAttributeFilter "OGRErr
 OGR_L_SetAttributeFilter(OGRLayerH hLayer, const char *pszQuery)
 
@@ -112,13 +156,15 @@ OGRERR_NONE if successfully installed, or an error code if the query
 expression is in error, or some other failure occurs. ";
 
 %feature("docstring")  GetFeature "OGRFeatureH
-OGR_L_GetFeature(OGRLayerH hLayer, long nFeatureId)
+OGR_L_GetFeature(OGRLayerH hLayer, GIntBig nFeatureId)
 
 Fetch a feature by its identifier.
 
 This function will attempt to read the identified feature. The nFID
 value cannot be OGRNullFID. Success or failure of this operation is
-unaffected by the spatial or attribute filters.
+unaffected by the spatial or attribute filters (and specialized
+implementations in drivers should make sure that they do not take into
+account spatial or attribute filters).
 
 If this function returns a non-NULL feature, it is guaranteed that its
 feature id ( OGR_F_GetFID()) will be the same as nFID.
@@ -129,8 +175,8 @@ however, the call should always work if the feature exists as a
 fallback implementation just scans all the features in the layer
 looking for the desired feature.
 
-Sequential reads are generally considered interrupted by a
-OGR_L_GetFeature() call.
+Sequential reads (with OGR_L_GetNextFeature()) are generally
+considered interrupted by a OGR_L_GetFeature() call.
 
 The returned feature should be free with OGR_F_Destroy().
 
@@ -146,7 +192,7 @@ nFeatureId:  the feature id of the feature to read.
 an handle to a feature now owned by the caller, or NULL on failure. ";
 
 %feature("docstring")  SetNextByIndex "OGRErr
-OGR_L_SetNextByIndex(OGRLayerH hLayer, long nIndex)
+OGR_L_SetNextByIndex(OGRLayerH hLayer, GIntBig nIndex)
 
 Move read cursor to the nIndex'th feature in the current resultset.
 
@@ -181,10 +227,10 @@ OGR_L_GetNextFeature(OGRLayerH hLayer)
 
 Fetch the next available feature from this layer.
 
-The returned feature becomes the responsiblity of the caller to delete
-with OGR_F_Destroy(). It is critical that all features associated with
-an OGRLayer (more specifically an OGRFeatureDefn) be deleted before
-that layer/datasource is deleted.
+The returned feature becomes the responsibility of the caller to
+delete with OGR_F_Destroy(). It is critical that all features
+associated with an OGRLayer (more specifically an OGRFeatureDefn) be
+deleted before that layer/datasource is deleted.
 
 Only features matching the current spatial filter (set with
 SetSpatialFilter()) will be returned.
@@ -193,6 +239,16 @@ This function implements sequential access to the features of a layer.
 The OGR_L_ResetReading() function can be used to start at the
 beginning again.
 
+Features returned by OGR_GetNextFeature() may or may not be affected
+by concurrent modifications depending on drivers. A guaranteed way of
+seeing modifications in effect is to call OGR_L_ResetReading() on
+layers where OGR_GetNextFeature() has been called, before reading
+again. Structural changes in layers (field addition, deletion, ...)
+when a read is in progress may or may not be possible depending on
+drivers. If a transaction is committed/aborted, the current sequential
+reading may or may not be valid after that operation and a call to
+OGR_L_ResetReading() might be needed.
+
 This function is the same as the C++ method
 OGRLayer::GetNextFeature().
 
@@ -224,7 +280,8 @@ hLayer:  handle to the layer to write the feature.
 hFeat:  the feature to write.
 
 OGRERR_NONE if the operation works, otherwise an appropriate error
-code. ";
+code (e.g OGRERR_NON_EXISTING_FEATURE if the feature does not exist).
+";
 
 %feature("docstring")  CreateFeature "OGRErr
 OGR_L_CreateFeature(OGRLayerH hLayer, OGRFeatureH hFeat)
@@ -261,15 +318,19 @@ Applications should never modify the OGRFeatureDefn used by a layer
 directly.
 
 This function should not be called while there are feature objects in
-existance that were obtained or created with the previous layer
+existence that were obtained or created with the previous layer
 definition.
 
 Not all drivers support this function. You can query a layer to check
 if it supports it with the OLCCreateField capability. Some drivers may
 only support this method while there are still no features in the
-layer. When it is supported, the existings features of the backing
+layer. When it is supported, the existing features of the backing
 file/database should be updated accordingly.
 
+Drivers may or may not support not-null constraints. If they support
+creating fields with not-null constraints, this is generally before
+creating any feature to the layer.
+
 This function is the same as the C++ method OGRLayer::CreateField().
 
 Parameters:
@@ -295,13 +356,13 @@ the deleted field. Applications should never modify the OGRFeatureDefn
 used by a layer directly.
 
 This function should not be called while there are feature objects in
-existance that were obtained or created with the previous layer
+existence that were obtained or created with the previous layer
 definition.
 
 Not all drivers support this function. You can query a layer to check
 if it supports it with the OLCDeleteField capability. Some drivers may
 only support this method while there are still no features in the
-layer. When it is supported, the existings features of the backing
+layer. When it is supported, the existing features of the backing
 file/database should be updated accordingly.
 
 This function is the same as the C++ method OGRLayer::DeleteField().
@@ -328,7 +389,7 @@ the reordering of the fields. Applications should never modify the
 OGRFeatureDefn used by a layer directly.
 
 This function should not be called while there are feature objects in
-existance that were obtained or created with the previous layer
+existence that were obtained or created with the previous layer
 definition.
 
 panMap is such that,for each field definition at position i after
@@ -341,7 +402,7 @@ initially. ReorderFields([0,2,3,1,4]) will reorder them as
 Not all drivers support this function. You can query a layer to check
 if it supports it with the OLCReorderFields capability. Some drivers
 may only support this method while there are still no features in the
-layer. When it is supported, the existings features of the backing
+layer. When it is supported, the existing features of the backing
 file/database should be updated accordingly.
 
 This function is the same as the C++ method OGRLayer::ReorderFields().
@@ -351,8 +412,9 @@ Parameters:
 
 hLayer:  handle to the layer.
 
-panMap:  an array of GetLayerDefn()->GetFieldCount() elements which is
-a permutation of [0, GetLayerDefn()->GetFieldCount()-1].
+panMap:  an array of GetLayerDefn()-> OGRFeatureDefn::GetFieldCount()
+elements which is a permutation of [0, GetLayerDefn()->
+OGRFeatureDefn::GetFieldCount()-1].
 
 OGRERR_NONE on success.
 
@@ -364,7 +426,7 @@ iNewFieldPos)
 
 Reorder an existing field on a layer.
 
-This function is a conveniency wrapper of OGR_L_ReorderFields()
+This function is a convenience wrapper of OGR_L_ReorderFields()
 dedicated to move a single field.
 
 You must use this to reorder existing fields on a real layer.
@@ -373,7 +435,7 @@ the reordering of the fields. Applications should never modify the
 OGRFeatureDefn used by a layer directly.
 
 This function should not be called while there are feature objects in
-existance that were obtained or created with the previous layer
+existence that were obtained or created with the previous layer
 definition.
 
 The field definition that was at initial position iOldFieldPos will be
@@ -387,7 +449,7 @@ initially. ReorderField(1, 3) will reorder them as
 Not all drivers support this function. You can query a layer to check
 if it supports it with the OLCReorderFields capability. Some drivers
 may only support this method while there are still no features in the
-layer. When it is supported, the existings features of the backing
+layer. When it is supported, the existing features of the backing
 file/database should be updated accordingly.
 
 This function is the same as the C++ method OGRLayer::ReorderField().
@@ -419,13 +481,13 @@ updated to reflect the altered field. Applications should never modify
 the OGRFeatureDefn used by a layer directly.
 
 This function should not be called while there are feature objects in
-existance that were obtained or created with the previous layer
+existence that were obtained or created with the previous layer
 definition.
 
 Not all drivers support this function. You can query a layer to check
 if it supports it with the OLCAlterFieldDefn capability. Some drivers
 may only support this method while there are still no features in the
-layer. When it is supported, the existings features of the backing
+layer. When it is supported, the existing features of the backing
 file/database should be updated accordingly. Some drivers might also
 not support all update flags.
 
@@ -441,15 +503,57 @@ iField:  index of the field whose definition must be altered.
 
 hNewFieldDefn:  new field definition
 
-nFlags:  combination of ALTER_NAME_FLAG, ALTER_TYPE_FLAG and
-ALTER_WIDTH_PRECISION_FLAG to indicate which of the name and/or type
-and/or width and precision fields from the new field definition must
-be taken into account.
+nFlags:  combination of ALTER_NAME_FLAG, ALTER_TYPE_FLAG,
+ALTER_WIDTH_PRECISION_FLAG, ALTER_NULLABLE_FLAG and ALTER_DEFAULT_FLAG
+to indicate which of the name and/or type and/or width and precision
+fields and/or nullability from the new field definition must be taken
+into account.
 
 OGRERR_NONE on success.
 
 OGR 1.9.0 ";
 
+%feature("docstring")  CreateGeomField "OGRErr
+OGR_L_CreateGeomField(OGRLayerH hLayer, OGRGeomFieldDefnH hField, int
+bApproxOK)
+
+Create a new geometry field on a layer.
+
+You must use this to create new geometry fields on a real layer.
+Internally the OGRFeatureDefn for the layer will be updated to reflect
+the new field. Applications should never modify the OGRFeatureDefn
+used by a layer directly.
+
+This function should not be called while there are feature objects in
+existence that were obtained or created with the previous layer
+definition.
+
+Not all drivers support this function. You can query a layer to check
+if it supports it with the OLCCreateField capability. Some drivers may
+only support this method while there are still no features in the
+layer. When it is supported, the existing features of the backing
+file/database should be updated accordingly.
+
+Drivers may or may not support not-null constraints. If they support
+creating fields with not-null constraints, this is generally before
+creating any feature to the layer.
+
+This function is the same as the C++ method OGRLayer::CreateField().
+
+Parameters:
+-----------
+
+hLayer:  handle to the layer to write the field definition.
+
+hField:  handle of the geometry field definition to write to disk.
+
+bApproxOK:  If TRUE, the field may be created in a slightly different
+form depending on the limitations of the format driver.
+
+OGRERR_NONE on success.
+
+OGR 1.11 ";
+
 %feature("docstring")  StartTransaction "OGRErr
 OGR_L_StartTransaction(OGRLayerH hLayer)
 
@@ -460,6 +564,12 @@ If starting the transaction fails, will return OGRERR_FAILURE.
 Datasources which do not support transactions will always return
 OGRERR_NONE.
 
+Note: as of GDAL 2.0, use of this API is discouraged when the dataset
+offers dataset level transaction with GDALDataset::StartTransaction().
+The reason is that most drivers can only offer transactions at dataset
+level, and not layer level. Very few drivers really support
+transactions at layer scope.
+
 This function is the same as the C++ method
 OGRLayer::StartTransaction().
 
@@ -495,9 +605,11 @@ OGR_L_RollbackTransaction(OGRLayerH hLayer)
 
 For datasources which support transactions, RollbackTransaction will
 roll back a datasource to its state before the start of the current
-transaction. If no transaction is active, or the rollback fails, will
-return OGRERR_FAILURE. Datasources which do not support transactions
-will always return OGRERR_NONE.
+transaction.
+
+If no transaction is active, or the rollback fails, will return
+OGRERR_FAILURE. Datasources which do not support transactions will
+always return OGRERR_NONE.
 
 This function is the same as the C++ method
 OGRLayer::RollbackTransaction().
@@ -527,6 +639,24 @@ hLayer:  handle to the layer to get the schema information.
 
 an handle to the feature definition. ";
 
+%feature("docstring")  FindFieldIndex "int
+OGR_L_FindFieldIndex(OGRLayerH hLayer, const char *pszFieldName, int
+bExactMatch)
+
+Find the index of field in a layer.
+
+The returned number is the index of the field in the layers, or -1 if
+the field doesn't exist.
+
+If bExactMatch is set to FALSE and the field doesn't exists in the
+given form the driver might apply some changes to make it match, like
+those it might do if the layer was created (eg. like LAUNDER in the
+OCI driver).
+
+This method is the same as the C++ method OGRLayer::FindFieldIndex().
+
+field index, or -1 if the field doesn't exist ";
+
 %feature("docstring")  GetSpatialRef "OGRSpatialReferenceH
 OGR_L_GetSpatialRef(OGRLayerH hLayer)
 
@@ -577,12 +707,12 @@ whether it should build and maintain its own spatial index for
 features in this layer.
 
 OLCFastFeatureCount / \"FastFeatureCount\": TRUE if this layer can
-return a feature count (via OGR_L_GetFeatureCount()) efficiently ...
-ie. without counting the features. In some cases this will return TRUE
+return a feature count (via OGR_L_GetFeatureCount()) efficiently, i.e.
+without counting the features. In some cases this will return TRUE
 until a spatial filter is installed after which it will return FALSE.
 
 OLCFastGetExtent / \"FastGetExtent\": TRUE if this layer can return
-its data extent (via OGR_L_GetExtent()) efficiently ... ie. without
+its data extent (via OGR_L_GetExtent()) efficiently, i.e. without
 scanning all the features. In some cases this will return TRUE until a
 spatial filter is installed after which it will return FALSE.
 
@@ -592,6 +722,10 @@ perform the SetNextByIndex() call efficiently, otherwise FALSE.
 OLCCreateField / \"CreateField\": TRUE if this layer can create new
 fields on the current layer using CreateField(), otherwise FALSE.
 
+OLCCreateGeomField / \"CreateGeomField\": (GDAL >= 1.11) TRUE if this
+layer can create new geometry fields on the current layer using
+CreateGeomField(), otherwise FALSE.
+
 OLCDeleteField / \"DeleteField\": TRUE if this layer can delete
 existing fields on the current layer using DeleteField(), otherwise
 FALSE.
@@ -615,6 +749,9 @@ OLCTransactions / \"Transactions\": TRUE if the StartTransaction(),
 CommitTransaction() and RollbackTransaction() methods work in a
 meaningful way, otherwise FALSE.
 
+OLCCurveGeometries / \"CurveGeometries\": TRUE if this layer supports
+writing curve geometries or may return such geometries. (GDAL 2.0).
+
 This function is the same as the C++ method
 OGRLayer::TestCapability().
 
@@ -626,7 +763,7 @@ hLayer:  handle to the layer to get the capability from.
 pszCap:  the name of the capability to test.
 
 TRUE if the layer has the requested capability, or FALSE otherwise.
-OGRLayers will return FALSE for any unrecognised capabilities. ";
+OGRLayers will return FALSE for any unrecognized capabilities. ";
 
 %feature("docstring")  GetSpatialFilter "OGRGeometryH
 OGR_L_GetSpatialFilter(OGRLayerH hLayer)
@@ -682,6 +819,52 @@ hGeom:  handle to the geometry to use as a filtering region. NULL may
 be passed indicating that the current spatial filter should be
 cleared, but no new one instituted. ";
 
+%feature("docstring")  SetSpatialFilterEx "void
+OGR_L_SetSpatialFilterEx(OGRLayerH hLayer, int iGeomField,
+OGRGeometryH hGeom)
+
+Set a new spatial filter.
+
+This function set the geometry to be used as a spatial filter when
+fetching features via the OGR_L_GetNextFeature() function. Only
+features that geometrically intersect the filter geometry will be
+returned.
+
+Currently this test is may be inaccurately implemented, but it is
+guaranteed that all features who's envelope (as returned by
+OGR_G_GetEnvelope()) overlaps the envelope of the spatial filter will
+be returned. This can result in more shapes being returned that should
+strictly be the case.
+
+This function makes an internal copy of the passed geometry. The
+passed geometry remains the responsibility of the caller, and may be
+safely destroyed.
+
+For the time being the passed filter geometry should be in the same
+SRS as the geometry field definition it corresponds to (as returned by
+GetLayerDefn()->OGRFeatureDefn::GetGeomFieldDefn(iGeomField)->GetSpati
+alRef()). In the future this may be generalized.
+
+Note that only the last spatial filter set is applied, even if several
+successive calls are done with different iGeomField values.
+
+This function is the same as the C++ method
+OGRLayer::SetSpatialFilter.
+
+Parameters:
+-----------
+
+hLayer:  handle to the layer on which to set the spatial filter.
+
+iGeomField:  index of the geometry field on which the spatial filter
+operates.
+
+hGeom:  handle to the geometry to use as a filtering region. NULL may
+be passed indicating that the current spatial filter should be
+cleared, but no new one instituted.
+
+GDAL 1.11 ";
+
 %feature("docstring")  SetSpatialFilterRect "void
 OGR_L_SetSpatialFilterRect(OGRLayerH hLayer, double dfMinX, double
 dfMinY, double dfMaxX, double dfMaxY)
@@ -717,6 +900,47 @@ dfMaxX:  the maximum X coordinate for the rectangular region.
 
 dfMaxY:  the maximum Y coordinate for the rectangular region. ";
 
+%feature("docstring")  SetSpatialFilterRectEx "void
+OGR_L_SetSpatialFilterRectEx(OGRLayerH hLayer, int iGeomField, double
+dfMinX, double dfMinY, double dfMaxX, double dfMaxY)
+
+Set a new rectangular spatial filter.
+
+This method set rectangle to be used as a spatial filter when fetching
+features via the OGR_L_GetNextFeature() method. Only features that
+geometrically intersect the given rectangle will be returned.
+
+The x/y values should be in the same coordinate system as as the
+geometry field definition it corresponds to (as returned by GetLayerDe
+fn()->OGRFeatureDefn::GetGeomFieldDefn(iGeomField)->GetSpatialRef()).
+Internally this method is normally implemented as creating a 5 vertex
+closed rectangular polygon and passing it to
+OGRLayer::SetSpatialFilter(). It exists as a convenience.
+
+The only way to clear a spatial filter set with this method is to call
+OGRLayer::SetSpatialFilter(NULL).
+
+This method is the same as the C++ method
+OGRLayer::SetSpatialFilterRect().
+
+Parameters:
+-----------
+
+hLayer:  handle to the layer on which to set the spatial filter.
+
+iGeomField:  index of the geometry field on which the spatial filter
+operates.
+
+dfMinX:  the minimum X coordinate for the rectangular region.
+
+dfMinY:  the minimum Y coordinate for the rectangular region.
+
+dfMaxX:  the maximum X coordinate for the rectangular region.
+
+dfMaxY:  the maximum Y coordinate for the rectangular region.
+
+GDAL 1.11 ";
+
 %feature("docstring")  ResetReading "void
 OGR_L_ResetReading(OGRLayerH hLayer)
 
@@ -732,7 +956,7 @@ Parameters:
 hLayer:  handle to the layer on which features are read. ";
 
 %feature("docstring")  SyncToDisk "OGRErr OGR_L_SyncToDisk(OGRLayerH
-hDS)
+hLayer)
 
 Flush pending changes to disk.
 
@@ -759,7 +983,7 @@ OGRERR_NONE if no error occurs (even if nothing is done) or an error
 code. ";
 
 %feature("docstring")  DeleteFeature "OGRErr
-OGR_L_DeleteFeature(OGRLayerH hDS, long nFID)
+OGR_L_DeleteFeature(OGRLayerH hLayer, GIntBig nFID)
 
 Delete feature from layer.
 
@@ -778,7 +1002,9 @@ hLayer:  handle to the layer
 
 nFID:  the feature id to be deleted from the layer
 
-OGRERR_NONE on success. ";
+OGRERR_NONE if the operation works, otherwise an appropriate error
+code (e.g OGRERR_NON_EXISTING_FEATURE if the feature does not exist).
+";
 
 %feature("docstring")  GetFeaturesRead "GIntBig
 OGR_L_GetFeaturesRead(OGRLayerH hLayer) ";
@@ -804,6 +1030,11 @@ OGR_L_GetGeometryColumn(OGRLayerH hLayer)
 This method returns the name of the underlying database column being
 used as the geometry column, or \"\" if not supported.
 
+For layers with multiple geometry fields, this method only returns the
+geometry type of the first geometry column. For other columns, use OGR
+_GFld_GetNameRef(OGR_FD_GetGeomFieldDefn(OGR_L_GetLayerDefn(hLayer),
+i)).
+
 This method is the same as the C++ method
 OGRLayer::GetGeometryColumn()
 
@@ -855,6 +1086,12 @@ OGR_FD_GetGeomType(OGR_L_GetLayerDefn(hLayer)), but for a few drivers,
 calling OGR_L_GetGeomType() directly can avoid lengthy layer
 definition initialization.
 
+For layers with multiple geometry fields, this method only returns the
+geometry type of the first geometry column. For other columns, use
+OGR_GFld_GetType(OGR_FD_GetGeomFieldDefn(OGR_L_GetLayerDefn(hLayer),
+i)). For layers without any geometry field, this method returns
+wkbNone.
+
 This function is the same as the C++ method OGRLayer::GetGeomType().
 
 Parameters:
@@ -894,4 +1131,470 @@ is passed, the ignored list is cleared.
 OGRERR_NONE if all field names have been resolved (even if the driver
 does not support this method) ";
 
+%feature("docstring")  clone_spatial_filter "static OGRErr
+clone_spatial_filter(OGRLayer *pLayer, OGRGeometry **ppGeometry) ";
+
+%feature("docstring")  create_field_map "static OGRErr
+create_field_map(OGRFeatureDefn *poDefn, int **map) ";
+
+%feature("docstring")  set_result_schema "static OGRErr
+set_result_schema(OGRLayer *pLayerResult, OGRFeatureDefn *poDefnInput,
+OGRFeatureDefn *poDefnMethod, int *mapInput, int *mapMethod, int
+combined, char **papszOptions) ";
+
+%feature("docstring")  set_filter_from "static OGRGeometry*
+set_filter_from(OGRLayer *pLayer, OGRGeometry
+*pGeometryExistingFilter, OGRFeature *pFeature) ";
+
+%feature("docstring")  promote_to_multi "static OGRGeometry*
+promote_to_multi(OGRGeometry *poGeom) ";
+
+%feature("docstring")  Intersection "OGRErr
+OGR_L_Intersection(OGRLayerH pLayerInput, OGRLayerH pLayerMethod,
+OGRLayerH pLayerResult, char **papszOptions, GDALProgressFunc
+pfnProgress, void *pProgressArg)
+
+Intersection of two layers.
+
+The result layer contains features whose geometries represent areas
+that are common between features in the input layer and in the method
+layer. The features in the result layer have attributes from both
+input and method layers. The schema of the result layer can be set by
+the user or, if it is empty, is initialized to contain all fields in
+the input and method layers.
+
+If the schema of the result is set by user and contains fields that
+have the same name as a field in input and in method layer, then the
+attribute in the result feature will get the value from the feature of
+the method layer.
+
+For best performance use the minimum amount of features in the method
+layer and copy it into a memory layer.
+
+This method relies on GEOS support. Do not use unless the GEOS support
+is compiled in.  The recognized list of options is :
+SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a feature
+could not be inserted.
+
+PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons into
+MultiPolygons, or LineStrings to MultiLineStrings.
+
+INPUT_PREFIX=string. Set a prefix for the field names that will be
+created from the fields of the input layer.
+
+METHOD_PREFIX=string. Set a prefix for the field names that will be
+created from the fields of the method layer.
+
+USE_PREPARED_GEOMETRIES=YES/NO. Set to NO to not use prepared
+geometries to pretest intersection of features of method layer with
+features of this layer.
+
+PRETEST_CONTAINMENT=YES/NO. Set to YES to pretest the containment of
+features of method layer within the features of this layer. This will
+speed up the method significantly in some cases. Requires that the
+prepared geometries are in effect.
+
+This function is the same as the C++ method OGRLayer::Intersection().
+
+Parameters:
+-----------
+
+pLayerInput:  the input layer. Should not be NULL.
+
+pLayerMethod:  the method layer. Should not be NULL.
+
+pLayerResult:  the layer where the features resulting from the
+operation are inserted. Should not be NULL. See above the note about
+the schema.
+
+papszOptions:  NULL terminated list of options (may be NULL).
+
+pfnProgress:  a GDALProgressFunc() compatible callback function for
+reporting progress or NULL.
+
+pProgressArg:  argument to be passed to pfnProgress. May be NULL.
+
+an error code if there was an error or the execution was interrupted,
+OGRERR_NONE otherwise.
+
+The first geometry field is always used.
+
+OGR 1.10 ";
+
+%feature("docstring")  Union "OGRErr OGR_L_Union(OGRLayerH
+pLayerInput, OGRLayerH pLayerMethod, OGRLayerH pLayerResult, char
+**papszOptions, GDALProgressFunc pfnProgress, void *pProgressArg)
+
+Union of two layers.
+
+The result layer contains features whose geometries represent areas
+that are in either in the input layer or in the method layer. The
+features in the result layer have attributes from both input and
+method layers. For features which represent areas that are only in the
+input or in the method layer the respective attributes have undefined
+values. The schema of the result layer can be set by the user or, if
+it is empty, is initialized to contain all fields in the input and
+method layers.
+
+If the schema of the result is set by user and contains fields that
+have the same name as a field in input and in method layer, then the
+attribute in the result feature will get the value from the feature of
+the method layer (even if it is undefined).
+
+For best performance use the minimum amount of features in the method
+layer and copy it into a memory layer.
+
+This method relies on GEOS support. Do not use unless the GEOS support
+is compiled in.  The recognized list of options is :
+SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a feature
+could not be inserted.
+
+PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons into
+MultiPolygons, or LineStrings to MultiLineStrings.
+
+INPUT_PREFIX=string. Set a prefix for the field names that will be
+created from the fields of the input layer.
+
+METHOD_PREFIX=string. Set a prefix for the field names that will be
+created from the fields of the method layer.
+
+USE_PREPARED_GEOMETRIES=YES/NO. Set to NO to not use prepared
+geometries to pretest intersection of features of method layer with
+features of this layer.
+
+This function is the same as the C++ method OGRLayer::Union().
+
+Parameters:
+-----------
+
+pLayerInput:  the input layer. Should not be NULL.
+
+pLayerMethod:  the method layer. Should not be NULL.
+
+pLayerResult:  the layer where the features resulting from the
+operation are inserted. Should not be NULL. See above the note about
+the schema.
+
+papszOptions:  NULL terminated list of options (may be NULL).
+
+pfnProgress:  a GDALProgressFunc() compatible callback function for
+reporting progress or NULL.
+
+pProgressArg:  argument to be passed to pfnProgress. May be NULL.
+
+an error code if there was an error or the execution was interrupted,
+OGRERR_NONE otherwise.
+
+The first geometry field is always used.
+
+OGR 1.10 ";
+
+%feature("docstring")  SymDifference "OGRErr
+OGR_L_SymDifference(OGRLayerH pLayerInput, OGRLayerH pLayerMethod,
+OGRLayerH pLayerResult, char **papszOptions, GDALProgressFunc
+pfnProgress, void *pProgressArg)
+
+Symmetrical difference of two layers.
+
+The result layer contains features whose geometries represent areas
+that are in either in the input layer or in the method layer but not
+in both. The features in the result layer have attributes from both
+input and method layers. For features which represent areas that are
+only in the input or in the method layer the respective attributes
+have undefined values. The schema of the result layer can be set by
+the user or, if it is empty, is initialized to contain all fields in
+the input and method layers.
+
+If the schema of the result is set by user and contains fields that
+have the same name as a field in input and in method layer, then the
+attribute in the result feature will get the value from the feature of
+the method layer (even if it is undefined).
+
+For best performance use the minimum amount of features in the method
+layer and copy it into a memory layer.
+
+This method relies on GEOS support. Do not use unless the GEOS support
+is compiled in.  The recognized list of options is :
+SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a feature
+could not be inserted.
+
+PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons into
+MultiPolygons, or LineStrings to MultiLineStrings.
+
+INPUT_PREFIX=string. Set a prefix for the field names that will be
+created from the fields of the input layer.
+
+METHOD_PREFIX=string. Set a prefix for the field names that will be
+created from the fields of the method layer.
+
+This function is the same as the C++ method OGRLayer::SymDifference().
+
+Parameters:
+-----------
+
+pLayerInput:  the input layer. Should not be NULL.
+
+pLayerMethod:  the method layer. Should not be NULL.
+
+pLayerResult:  the layer where the features resulting from the
+operation are inserted. Should not be NULL. See above the note about
+the schema.
+
+papszOptions:  NULL terminated list of options (may be NULL).
+
+pfnProgress:  a GDALProgressFunc() compatible callback function for
+reporting progress or NULL.
+
+pProgressArg:  argument to be passed to pfnProgress. May be NULL.
+
+an error code if there was an error or the execution was interrupted,
+OGRERR_NONE otherwise.
+
+The first geometry field is always used.
+
+OGR 1.10 ";
+
+%feature("docstring")  Identity "OGRErr OGR_L_Identity(OGRLayerH
+pLayerInput, OGRLayerH pLayerMethod, OGRLayerH pLayerResult, char
+**papszOptions, GDALProgressFunc pfnProgress, void *pProgressArg)
+
+Identify the features of this layer with the ones from the identity
+layer.
+
+The result layer contains features whose geometries represent areas
+that are in the input layer. The features in the result layer have
+attributes from both input and method layers. The schema of the result
+layer can be set by the user or, if it is empty, is initialized to
+contain all fields in input and method layers.
+
+If the schema of the result is set by user and contains fields that
+have the same name as a field in input and in method layer, then the
+attribute in the result feature will get the value from the feature of
+the method layer (even if it is undefined).
+
+For best performance use the minimum amount of features in the method
+layer and copy it into a memory layer.
+
+This method relies on GEOS support. Do not use unless the GEOS support
+is compiled in.  The recognized list of options is :
+SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a feature
+could not be inserted.
+
+PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons into
+MultiPolygons, or LineStrings to MultiLineStrings.
+
+INPUT_PREFIX=string. Set a prefix for the field names that will be
+created from the fields of the input layer.
+
+METHOD_PREFIX=string. Set a prefix for the field names that will be
+created from the fields of the method layer.
+
+USE_PREPARED_GEOMETRIES=YES/NO. Set to NO to not use prepared
+geometries to pretest intersection of features of method layer with
+features of this layer.
+
+This function is the same as the C++ method OGRLayer::Identity().
+
+Parameters:
+-----------
+
+pLayerInput:  the input layer. Should not be NULL.
+
+pLayerMethod:  the method layer. Should not be NULL.
+
+pLayerResult:  the layer where the features resulting from the
+operation are inserted. Should not be NULL. See above the note about
+the schema.
+
+papszOptions:  NULL terminated list of options (may be NULL).
+
+pfnProgress:  a GDALProgressFunc() compatible callback function for
+reporting progress or NULL.
+
+pProgressArg:  argument to be passed to pfnProgress. May be NULL.
+
+an error code if there was an error or the execution was interrupted,
+OGRERR_NONE otherwise.
+
+The first geometry field is always used.
+
+OGR 1.10 ";
+
+%feature("docstring")  Update "OGRErr OGR_L_Update(OGRLayerH
+pLayerInput, OGRLayerH pLayerMethod, OGRLayerH pLayerResult, char
+**papszOptions, GDALProgressFunc pfnProgress, void *pProgressArg)
+
+Update this layer with features from the update layer.
+
+The result layer contains features whose geometries represent areas
+that are either in the input layer or in the method layer. The
+features in the result layer have areas of the features of the method
+layer or those ares of the features of the input layer that are not
+covered by the method layer. The features of the result layer get
+their attributes from the input layer. The schema of the result layer
+can be set by the user or, if it is empty, is initialized to contain
+all fields in the input layer.
+
+If the schema of the result is set by user and contains fields that
+have the same name as a field in the method layer, then the attribute
+in the result feature the originates from the method layer will get
+the value from the feature of the method layer.
+
+For best performance use the minimum amount of features in the method
+layer and copy it into a memory layer.
+
+This method relies on GEOS support. Do not use unless the GEOS support
+is compiled in.  The recognized list of options is :
+SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a feature
+could not be inserted.
+
+PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons into
+MultiPolygons, or LineStrings to MultiLineStrings.
+
+INPUT_PREFIX=string. Set a prefix for the field names that will be
+created from the fields of the input layer.
+
+METHOD_PREFIX=string. Set a prefix for the field names that will be
+created from the fields of the method layer.
+
+This function is the same as the C++ method OGRLayer::Update().
+
+Parameters:
+-----------
+
+pLayerInput:  the input layer. Should not be NULL.
+
+pLayerMethod:  the method layer. Should not be NULL.
+
+pLayerResult:  the layer where the features resulting from the
+operation are inserted. Should not be NULL. See above the note about
+the schema.
+
+papszOptions:  NULL terminated list of options (may be NULL).
+
+pfnProgress:  a GDALProgressFunc() compatible callback function for
+reporting progress or NULL.
+
+pProgressArg:  argument to be passed to pfnProgress. May be NULL.
+
+an error code if there was an error or the execution was interrupted,
+OGRERR_NONE otherwise.
+
+The first geometry field is always used.
+
+OGR 1.10 ";
+
+%feature("docstring")  Clip "OGRErr OGR_L_Clip(OGRLayerH pLayerInput,
+OGRLayerH pLayerMethod, OGRLayerH pLayerResult, char **papszOptions,
+GDALProgressFunc pfnProgress, void *pProgressArg)
+
+Clip off areas that are not covered by the method layer.
+
+The result layer contains features whose geometries represent areas
+that are in the input layer and in the method layer. The features in
+the result layer have the (possibly clipped) areas of features in the
+input layer and the attributes from the same features. The schema of
+the result layer can be set by the user or, if it is empty, is
+initialized to contain all fields in the input layer.
+
+For best performance use the minimum amount of features in the method
+layer and copy it into a memory layer.
+
+This method relies on GEOS support. Do not use unless the GEOS support
+is compiled in.  The recognized list of options is :
+SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a feature
+could not be inserted.
+
+PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons into
+MultiPolygons, or LineStrings to MultiLineStrings.
+
+INPUT_PREFIX=string. Set a prefix for the field names that will be
+created from the fields of the input layer.
+
+METHOD_PREFIX=string. Set a prefix for the field names that will be
+created from the fields of the method layer.
+
+This function is the same as the C++ method OGRLayer::Clip().
+
+Parameters:
+-----------
+
+pLayerInput:  the input layer. Should not be NULL.
+
+pLayerMethod:  the method layer. Should not be NULL.
+
+pLayerResult:  the layer where the features resulting from the
+operation are inserted. Should not be NULL. See above the note about
+the schema.
+
+papszOptions:  NULL terminated list of options (may be NULL).
+
+pfnProgress:  a GDALProgressFunc() compatible callback function for
+reporting progress or NULL.
+
+pProgressArg:  argument to be passed to pfnProgress. May be NULL.
+
+an error code if there was an error or the execution was interrupted,
+OGRERR_NONE otherwise.
+
+The first geometry field is always used.
+
+OGR 1.10 ";
+
+%feature("docstring")  Erase "OGRErr OGR_L_Erase(OGRLayerH
+pLayerInput, OGRLayerH pLayerMethod, OGRLayerH pLayerResult, char
+**papszOptions, GDALProgressFunc pfnProgress, void *pProgressArg)
+
+Remove areas that are covered by the method layer.
+
+The result layer contains features whose geometries represent areas
+that are in the input layer but not in the method layer. The features
+in the result layer have attributes from the input layer. The schema
+of the result layer can be set by the user or, if it is empty, is
+initialized to contain all fields in the input layer.
+
+For best performance use the minimum amount of features in the method
+layer and copy it into a memory layer.
+
+This method relies on GEOS support. Do not use unless the GEOS support
+is compiled in.  The recognized list of options is :
+SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a feature
+could not be inserted.
+
+PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons into
+MultiPolygons, or LineStrings to MultiLineStrings.
+
+INPUT_PREFIX=string. Set a prefix for the field names that will be
+created from the fields of the input layer.
+
+METHOD_PREFIX=string. Set a prefix for the field names that will be
+created from the fields of the method layer.
+
+This function is the same as the C++ method OGRLayer::Erase().
+
+Parameters:
+-----------
+
+pLayerInput:  the input layer. Should not be NULL.
+
+pLayerMethod:  the method layer. Should not be NULL.
+
+pLayerResult:  the layer where the features resulting from the
+operation are inserted. Should not be NULL. See above the note about
+the schema.
+
+papszOptions:  NULL terminated list of options (may be NULL).
+
+pfnProgress:  a GDALProgressFunc() compatible callback function for
+reporting progress or NULL.
+
+pProgressArg:  argument to be passed to pfnProgress. May be NULL.
+
+an error code if there was an error or the execution was interrupted,
+OGRERR_NONE otherwise.
+
+The first geometry field is always used.
+
+OGR 1.10 ";
+
 }
\ No newline at end of file
diff --git a/swig/include/python/gdal_python.i b/swig/include/python/gdal_python.i
index c3cedf2..b6ad8ed 100644
--- a/swig/include/python/gdal_python.i
+++ b/swig/include/python/gdal_python.i
@@ -1,5 +1,5 @@
 /*
- * $Id: gdal_python.i 28497 2015-02-16 11:31:14Z rouault $
+ * $Id: gdal_python.i 33573 2016-02-26 21:33:04Z rouault $
  *
  * python specific code for gdal bindings.
  */
@@ -16,7 +16,7 @@
 
 %pythoncode %{
 
-  
+
   have_warned = 0
   def deprecation_warn( module ):
     global have_warned
@@ -29,8 +29,8 @@
     from warnings import warn
     warn('%s.py was placed in a namespace, it is now available as osgeo.%s' % (module,module),
          DeprecationWarning)
-         
-         
+
+
   from gdalconst import *
   import gdalconst
 
@@ -82,7 +82,6 @@
 %}
 
 
-
 %include "python_exceptions.i"
 %include "python_strings.i"
 
@@ -98,15 +97,21 @@
 %inline %{
 int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
 {
-    GIntBig buf_size = nMembSize * nMembCount;
+    GUIntBig buf_size = (GUIntBig)nMembSize * nMembCount;
+    if( nMembSize < 0 || nMembCount < 0 || buf_size > 0xFFFFFFFFU )
+   {
+        CPLError(CE_Failure, CPLE_AppDefined, "Too big request");
+        *buf = NULL;
+        return 0;
+    }
 
     if (buf_size == 0)
     {
         *buf = NULL;
         return 0;
     }
-#if PY_VERSION_HEX >= 0x03000000 
-    *buf = (void *)PyBytes_FromStringAndSize( NULL, buf_size ); 
+#if PY_VERSION_HEX >= 0x03000000
+    *buf = (void *)PyBytes_FromStringAndSize( NULL, buf_size );
     if (*buf == NULL)
     {
         *buf = Py_None;
@@ -115,16 +120,16 @@ int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
         return 0;
     }
     PyObject* o = (PyObject*) *buf;
-    char *data = PyBytes_AsString(o); 
-    GIntBig nRet = (GIntBig)VSIFReadL( data, nMembSize, nMembCount, fp );
-    if (nRet * nMembSize < buf_size)
+    char *data = PyBytes_AsString(o);
+    size_t nRet = (size_t)VSIFReadL( data, nMembSize, nMembCount, fp );
+    if (nRet * (size_t)nMembSize < buf_size)
     {
         _PyBytes_Resize(&o, nRet * nMembSize);
         *buf = o;
     }
     return nRet;
-#else 
-    *buf = (void *)PyString_FromStringAndSize( NULL, buf_size ); 
+#else
+    *buf = (void *)PyString_FromStringAndSize( NULL, buf_size );
     if (*buf == NULL)
     {
         if( !bUseExceptions ) PyErr_Clear();
@@ -132,9 +137,9 @@ int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
         return 0;
     }
     PyObject* o = (PyObject*) *buf;
-    char *data = PyString_AsString(o); 
-    GIntBig nRet = (GIntBig)VSIFReadL( data, nMembSize, nMembCount, fp );
-    if (nRet * nMembSize < buf_size)
+    char *data = PyString_AsString(o);
+    size_t nRet = (size_t)VSIFReadL( data, nMembSize, nMembCount, fp );
+    if (nRet * (size_t)nMembSize < buf_size)
     {
         _PyString_Resize(&o, nRet * nMembSize);
         *buf = o;
@@ -160,7 +165,7 @@ int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
   def serialize(self,with_Z=0):
     base = [CXT_Element,'GCP']
     base.append([CXT_Attribute,'Id',[CXT_Text,self.Id]])
-    pixval = '%0.15E' % self.GCPPixel       
+    pixval = '%0.15E' % self.GCPPixel
     lineval = '%0.15E' % self.GCPLine
     xval = '%0.15E' % self.GCPX
     yval = '%0.15E' % self.GCPY
@@ -170,7 +175,7 @@ int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
     base.append([CXT_Attribute,'X',[CXT_Text,xval]])
     base.append([CXT_Attribute,'Y',[CXT_Text,yval]])
     if with_Z:
-        base.append([CXT_Attribute,'Z',[CXT_Text,zval]])        
+        base.append([CXT_Attribute,'Z',[CXT_Text,zval]])
     return base
 %} /* pythoncode */
 }
@@ -180,7 +185,7 @@ int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
 %apply ( int *optional_int ) {(int*)};
 %apply ( GIntBig *optional_GIntBig ) {(GIntBig*)};
 %feature( "kwargs" ) ReadRaster1;
-  CPLErr ReadRaster1( int xoff, int yoff, int xsize, int ysize,
+  CPLErr ReadRaster1( double xoff, double yoff, double xsize, double ysize,
                      void **buf,
                      int *buf_xsize = 0,
                      int *buf_ysize = 0,
@@ -198,14 +203,14 @@ int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
     GIntBig line_space = (buf_line_space == 0) ? 0 : *buf_line_space;
 
     GIntBig buf_size = ComputeBandRasterIOSize( nxsize, nysize, GDALGetDataTypeSize( ntype ) / 8,
-                                            pixel_space, line_space, FALSE ); 
+                                            pixel_space, line_space, FALSE );
     if (buf_size == 0)
     {
         *buf = NULL;
         return CE_Failure;
     }
-%#if PY_VERSION_HEX >= 0x03000000 
-    *buf = (void *)PyBytes_FromStringAndSize( NULL, buf_size ); 
+%#if PY_VERSION_HEX >= 0x03000000
+    *buf = (void *)PyBytes_FromStringAndSize( NULL, buf_size );
     if (*buf == NULL)
     {
         *buf = Py_None;
@@ -213,16 +218,16 @@ int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
         CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate result buffer");
         return CE_Failure;
     }
-    char *data = PyBytes_AsString( (PyObject *)*buf ); 
-%#else 
-    *buf = (void *)PyString_FromStringAndSize( NULL, buf_size ); 
+    char *data = PyBytes_AsString( (PyObject *)*buf );
+%#else
+    *buf = (void *)PyString_FromStringAndSize( NULL, buf_size );
     if (*buf == NULL)
     {
         if( !bUseExceptions ) PyErr_Clear();
         CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate result buffer");
         return CE_Failure;
     }
-    char *data = PyString_AsString( (PyObject *)*buf ); 
+    char *data = PyString_AsString( (PyObject *)*buf );
 %#endif
 
     /* Should we clear the buffer in case there are hole in it ? */
@@ -236,10 +241,23 @@ int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
     sExtraArg.eResampleAlg = resample_alg;
     sExtraArg.pfnProgress = callback;
     sExtraArg.pProgressData = callback_data;
+    int nXOff = (int)(xoff + 0.5);
+    int nYOff = (int)(yoff + 0.5);
+    int nXSize = (int)(xsize + 0.5);
+    int nYSize = (int)(ysize + 0.5);
+    if( fabs(xoff-nXOff) > 1e-8 || fabs(yoff-nYOff) > 1e-8 ||
+        fabs(xsize-nXSize) > 1e-8 || fabs(ysize-nYSize) > 1e-8 )
+    {
+        sExtraArg.bFloatingPointWindowValidity = TRUE;
+        sExtraArg.dfXOff = xoff;
+        sExtraArg.dfYOff = yoff;
+        sExtraArg.dfXSize = xsize;
+        sExtraArg.dfYSize = ysize;
+    }
 
-    CPLErr eErr = GDALRasterIOEx( self, GF_Read, xoff, yoff, xsize, ysize, 
-                         (void *) data, nxsize, nysize, ntype, 
-                         pixel_space, line_space, &sExtraArg ); 
+    CPLErr eErr = GDALRasterIOEx( self, GF_Read, nXOff, nYOff, nXSize, nYSize,
+                         (void *) data, nxsize, nysize, ntype,
+                         pixel_space, line_space, &sExtraArg );
     if (eErr == CE_Failure)
     {
         Py_DECREF((PyObject*)*buf);
@@ -260,8 +278,8 @@ int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
     int nDataTypeSize = (GDALGetDataTypeSize(GDALGetRasterDataType(self)) / 8);
     GIntBig buf_size = (GIntBig)nBlockXSize * nBlockYSize * nDataTypeSize;
 
-%#if PY_VERSION_HEX >= 0x03000000 
-    *buf = (void *)PyBytes_FromStringAndSize( NULL, buf_size ); 
+%#if PY_VERSION_HEX >= 0x03000000
+    *buf = (void *)PyBytes_FromStringAndSize( NULL, buf_size );
     if (*buf == NULL)
     {
         *buf = Py_None;
@@ -269,18 +287,18 @@ int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
         CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate result buffer");
         return CE_Failure;
     }
-    char *data = PyBytes_AsString( (PyObject *)*buf ); 
-%#else 
-    *buf = (void *)PyString_FromStringAndSize( NULL, buf_size ); 
+    char *data = PyBytes_AsString( (PyObject *)*buf );
+%#else
+    *buf = (void *)PyString_FromStringAndSize( NULL, buf_size );
     if (*buf == NULL)
     {
         if( !bUseExceptions ) PyErr_Clear();
         CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate result buffer");
         return CE_Failure;
     }
-    char *data = PyString_AsString( (PyObject *)*buf ); 
+    char *data = PyString_AsString( (PyObject *)*buf );
 %#endif
-    CPLErr eErr = GDALReadBlock( self, xoff, yoff, (void *) data); 
+    CPLErr eErr = GDALReadBlock( self, xoff, yoff, (void *) data);
     if (eErr == CE_Failure)
     {
         Py_DECREF((PyObject*)*buf);
@@ -326,7 +344,7 @@ int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
                                           resample_alg = resample_alg,
                                           callback = callback,
                                           callback_data = callback_data)
-    
+
   def WriteArray(self, array, xoff=0, yoff=0,
                  resample_alg = GRIORA_NearestNeighbour,
                  callback = None,
@@ -403,7 +421,7 @@ int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
 
   def __get_array_interface__(self):
       shape = [1, self.XSize, self.YSize]
-      
+
 %}
 }
 
@@ -453,24 +471,24 @@ CPLErr ReadRaster1(  int xoff, int yoff, int xsize, int ysize,
         return CE_Failure;
     }
 
-%#if PY_VERSION_HEX >= 0x03000000 
-    *buf = (void *)PyBytes_FromStringAndSize( NULL, buf_size ); 
+%#if PY_VERSION_HEX >= 0x03000000
+    *buf = (void *)PyBytes_FromStringAndSize( NULL, buf_size );
     if (*buf == NULL)
     {
         if( !bUseExceptions ) PyErr_Clear();
         CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate result buffer");
         return CE_Failure;
     }
-    char *data = PyBytes_AsString( (PyObject *)*buf ); 
-%#else 
-    *buf = (void *)PyString_FromStringAndSize( NULL, buf_size ); 
+    char *data = PyBytes_AsString( (PyObject *)*buf );
+%#else
+    *buf = (void *)PyString_FromStringAndSize( NULL, buf_size );
     if (*buf == NULL)
     {
         if( !bUseExceptions ) PyErr_Clear();
         CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate result buffer");
         return CE_Failure;
     }
-    char *data = PyString_AsString( (PyObject *)*buf ); 
+    char *data = PyString_AsString( (PyObject *)*buf );
 %#endif
 
     /* Should we clear the buffer in case there are hole in it ? */
@@ -640,7 +658,7 @@ CPLErr ReadRaster1(  int xoff, int yoff, int xsize, int ysize,
 
     def GetSubDatasets(self):
         sd_list = []
-        
+
         sd = self.GetMetadata('SUBDATASETS')
         if sd is None:
             return sd_list
@@ -726,3 +744,1030 @@ CPLErr ReadRaster1(  int xoff, int yoff, int xsize, int ysize,
 }
 
 %include "callback.i"
+
+
+%pythoncode %{
+
+def _is_str_or_unicode(o):
+    return isinstance(o, str) or str(type(o)) == "<type 'unicode'>"
+
+def InfoOptions(options = [], format = 'text', deserialize = True,
+         computeMinMax = False, reportHistograms = False, reportProj4 = False,
+         stats = False, approxStats = False, computeChecksum = False,
+         showGCPs = True, showMetadata = True, showRAT = True, showColorTable = True,
+         listMDD = False, showFileList = True, allMetadata = False,
+         extraMDDomains = None):
+    """ Create a InfoOptions() object that can be passed to gdal.Info()
+        options can be be an array of strings, a string or let empty and filled from other keywords."""
+    import copy
+
+    if _is_str_or_unicode(options):
+        new_options = ParseCommandLine(options)
+        format = 'text'
+        if '-json' in new_options:
+            format = 'json'
+    else:
+        new_options = copy.copy(options)
+        if format == 'json':
+            new_options += ['-json']
+        if computeMinMax:
+            new_options += ['-mm']
+        if reportHistograms:
+            new_options += ['-hist']
+        if reportProj4:
+            new_options += ['-proj4']
+        if stats:
+            new_options += ['-stats']
+        if approxStats:
+            new_options += ['-approx_stats']
+        if computeChecksum:
+            new_options += ['-checksum']
+        if not showGCPs:
+            new_options += ['-nogcp']
+        if not showMetadata:
+            new_options += ['-nomd']
+        if not showRAT:
+            new_options += ['-norat']
+        if not showColorTable:
+            new_options += ['-noct']
+        if listMDD:
+            new_options += ['-listmdd']
+        if not showFileList:
+            new_options += ['-nofl']
+        if allMetadata:
+            new_options += ['-mdd', 'all']
+        if extraMDDomains is not None:
+            for mdd in extraMDDomains:
+                new_options += ['-mdd', mdd]
+
+    return (GDALInfoOptions(new_options), format, deserialize)
+
+def Info(ds, **kwargs):
+    """ Return information on a dataset.
+        Arguments are :
+          ds --- a Dataset object or a filename
+        Keyword arguments are :
+          options --- return of gdal.InfoOptions(), string or array of strings
+          other keywords arguments of gdal.InfoOptions()
+        If options is provided as a gdal.InfoOptions() object, other keywords are ignored. """
+    if not 'options' in kwargs or type(kwargs['options']) == type([]) or _is_str_or_unicode(kwargs['options']):
+        (opts, format, deserialize) = InfoOptions(**kwargs)
+    else:
+        (opts, format, deserialize) = kwargs['options']
+    if _is_str_or_unicode(ds):
+        ds = Open(ds)
+    ret = InfoInternal(ds, opts)
+    if format == 'json' and deserialize:
+        import json
+        ret = json.loads(ret)
+    return ret
+
+
+def TranslateOptions(options = [], format = 'GTiff',
+              outputType = GDT_Unknown, bandList = None, maskBand = None,
+              width = 0, height = 0, widthPct = 0.0, heightPct = 0.0,
+              xRes = 0.0, yRes = 0.0,
+              creationOptions = None, srcWin = None, projWin = None, projWinSRS = None, strict = False,
+              unscale = False, scaleParams = None, exponents = None,
+              outputBounds = None, metadataOptions = None,
+              outputSRS = None, GCPs = None,
+              noData = None, rgbExpand = None,
+              stats = False, rat = True, resampleAlg = None,
+              callback = None, callback_data = None):
+    """ Create a TranslateOptions() object that can be passed to gdal.Translate()
+        Keyword arguments are :
+          options --- can be be an array of strings, a string or let empty and filled from other keywords.
+          format --- output format ("GTiff", etc...)
+          outputType --- output type (gdal.GDT_Byte, etc...)
+          bandList --- array of band numbers (index start at 1)
+          maskBand --- mask band to generate or not ("none", "auto", "mask", 1, ...)
+          width --- width of the output raster in pixel
+          height --- height of the output raster in pixel
+          widthPct --- width of the output raster in percentage (100 = original width)
+          heightPct --- height of the output raster in percentage (100 = original height)
+          xRes --- output horizontal resolution
+          yRes --- output vertical resolution
+          creationOptions --- list of creation options
+          srcWin --- subwindow in pixels to extract: [left_x, top_y, width, height]
+          projWin --- subwindow in projected coordinates to extract: [ulx, uly, lrx, lry]
+          projWinSRS --- SRS in which projWin is expressed
+          strict --- strict mode
+          unscale --- unscale values with scale and offset metadata
+          scaleParams --- list of scale parameters, each of the form [src_min,src_max] or [src_min,src_max,dst_min,dst_max]
+          exponents --- list of exponentiation parameters
+          outputBounds --- assigned output bounds: [ulx, uly, lrx, lry]
+          metadataOptions --- list of metadata options
+          outputSRS --- assigned output SRS
+          GCPs --- list of GCPs
+          noData --- nodata value (or "none" to unset it)
+          rgbExpand --- Color palette expansion mode: "gray", "rgb", "rgba"
+          stats --- whether to calculate statistics
+          rat --- whether to write source RAT
+          resampleAlg --- resampling mode
+          callback --- callback method
+          callback_data --- user data for callback
+    """
+    import copy
+
+    if _is_str_or_unicode(options):
+        new_options = ParseCommandLine(options)
+    else:
+        new_options = copy.copy(options)
+        new_options += ['-of', format]
+        if outputType != GDT_Unknown:
+            new_options += ['-ot', GetDataTypeName(outputType) ]
+        if maskBand != None:
+            new_options += ['-mask', str(maskBand) ]
+        if bandList != None:
+            for b in bandList:
+                new_options += ['-b', str(b) ]
+        if width != 0 or height != 0:
+            new_options += ['-outsize', str(width), str(height)]
+        elif widthPct != 0 and heightPct != 0:
+            new_options += ['-outsize', str(widthPct) + '%%', str(heightPct) + '%%']
+        if creationOptions is not None:
+            for opt in creationOptions:
+                new_options += ['-co', opt ]
+        if srcWin is not None:
+            new_options += ['-srcwin', str(srcWin[0]), str(srcWin[1]), str(srcWin[2]), str(srcWin[3])]
+        if strict:
+            new_options += ['-strict']
+        if unscale:
+            new_options += ['-unscale']
+        if scaleParams:
+            for scaleParam in scaleParams:
+                new_options += ['-scale']
+                for v in scaleParam:
+                    new_options += [ str(v) ]
+        if exponents:
+            for exponent in exponents:
+                new_options += ['-exponent', str(exponent)]
+        if outputBounds is not None:
+            new_options += ['-a_ullr', str(outputBounds[0]), str(outputBounds[1]), str(outputBounds[2]), str(outputBounds[3])]
+        if metadataOptions is not None:
+            for opt in metadataOptions:
+                new_options += ['-mo', opt ]
+        if outputSRS is not None:
+            new_options += ['-a_srs', str(outputSRS) ]
+        if GCPs is not None:
+            for gcp in GCPs:
+                new_options += ['-gcp', str(gcp.GCPPixel), str(gcp.GCPLine), str(gcp.GCPX), str(gcp.GCPY), str(gcp.GCPZ) ]
+        if projWin is not None:
+            new_options += ['-projwin', str(projWin[0]), str(projWin[1]), str(projWin[2]), str(projWin[3])]
+        if projWinSRS is not None:
+            new_options += ['-projwin_srs', str(projWinSRS) ]
+        if noData is not None:
+            new_options += ['-a_nodata', str(noData) ]
+        if rgbExpand is not None:
+            new_options += ['-expand', str(rgbExpand) ]
+        if stats:
+            new_options += ['-stats']
+        if not rat:
+            new_options += ['-norat']
+        if resampleAlg is not None:
+            if resampleAlg == GRA_NearestNeighbour:
+                new_options += ['-r', 'near']
+            elif resampleAlg == GRA_Bilinear:
+                new_options += ['-r', 'bilinear']
+            elif resampleAlg == GRA_Cubic:
+                new_options += ['-r', 'cubic']
+            elif resampleAlg == GRA_CubicSpline:
+                new_options += ['-r', 'cubicspline']
+            elif resampleAlg == GRA_Lanczos:
+                new_options += ['-r', 'lanczos']
+            elif resampleAlg == GRA_Average:
+                new_options += ['-r', 'average']
+            elif resampleAlg == GRA_Mode:
+                new_options += ['-r', 'mode']
+            else:
+                new_options += ['-r', str(resampleAlg) ]
+        if xRes != 0 and yRes != 0:
+            new_options += ['-tr', str(xRes), str(yRes) ]
+
+    return (GDALTranslateOptions(new_options), callback, callback_data)
+
+def Translate(destName, srcDS, **kwargs):
+    """ Convert a dataset.
+        Arguments are :
+          destName --- Output dataset name
+          srcDS --- a Dataset object or a filename
+        Keyword arguments are :
+          options --- return of gdal.InfoOptions(), string or array of strings
+          other keywords arguments of gdal.TranslateOptions()
+        If options is provided as a gdal.TranslateOptions() object, other keywords are ignored. """
+
+    if not 'options' in kwargs or type(kwargs['options']) == type([]) or _is_str_or_unicode(kwargs['options']):
+        (opts, callback, callback_data) = TranslateOptions(**kwargs)
+    else:
+        (opts, callback, callback_data) = kwargs['options']
+    if _is_str_or_unicode(srcDS):
+        srcDS = Open(srcDS)
+
+    return TranslateInternal(destName, srcDS, opts, callback, callback_data)
+
+def WarpOptions(options = [], format = 'GTiff',
+         outputBounds = None,
+         outputBoundsSRS = None,
+         xRes = None, yRes = None, targetAlignedPixels = False,
+         width = 0, height = 0,
+         srcSRS = None, dstSRS = None,
+         srcAlpha = False, dstAlpha = False,
+         warpOptions = None, errorThreshold = None,
+         warpMemoryLimit = None, creationOptions = None, outputType = GDT_Unknown,
+         workingType = GDT_Unknown, resampleAlg = None,
+         srcNodata = None, dstNodata = None, multithread = False,
+         tps = False, rpc = False, geoloc = False, polynomialOrder = None,
+         transformerOptions = None, cutlineDSName = None,
+         cutlineLayer = None, cutlineWhere = None, cutlineSQL = None, cutlineBlend = None, cropToCutline = False,
+         copyMetadata = True, metadataConflictValue = None,
+         setColorInterpretation = False,
+         callback = None, callback_data = None):
+    """ Create a WarpOptions() object that can be passed to gdal.Warp()
+        Keyword arguments are :
+          options --- can be be an array of strings, a string or let empty and filled from other keywords.
+          format --- output format ("GTiff", etc...)
+          outputBounds --- output bounds as (minX, minY, maxX, maxY) in target SRS
+          outputBoundsSRS --- SRS in which output bounds are expressed, in the case they are not expressed in dstSRS
+          xRes, yRes --- output resolution in target SRS
+          targetAlignedPixels --- whether to force output bounds to be multiple of output resolution
+          width --- width of the output raster in pixel
+          height --- height of the output raster in pixel
+          srcSRS --- source SRS
+          dstSRS --- output SRS
+          srcAlpha --- whether to force the last band of the input dataset to be considered as an alpha band
+          dstAlpha --- whether to force the creation of an output alpha band
+          outputType --- output type (gdal.GDT_Byte, etc...)
+          workingType --- working type (gdal.GDT_Byte, etc...)
+          warpOptions --- list of warping options
+          errorThreshold --- error threshold for approximation transformer (in pixels)
+          warpMemoryLimit --- size of working buffer in bytes
+          resampleAlg --- resampling mode
+          creationOptions --- list of creation options
+          srcNodata --- source nodata value(s)
+          dstNodata --- output nodata value(s)
+          multithread --- whether to multithread computation and I/O operations
+          tps --- whether to use Thin Plate Spline GCP transformer
+          rpc --- whether to use RPC transformer
+          geoloc --- whether to use GeoLocation array transformer
+          polynomialOrder --- order of polynomial GCP interpolation
+          transformerOptions --- list of transformer options
+          cutlineDSName --- cutline dataset name
+          cutlineLayer --- cutline layer name
+          cutlineWhere --- cutline WHERE clause
+          cutlineSQL --- cutline SQL statement
+          cutlineBlend --- cutline blend distance in pixels
+          cropToCutline --- whether to use cutline extent for output bounds
+          copyMetadata --- whether to copy source metadata
+          metadataConflictValue --- metadata data conflict value
+          setColorInterpretation --- whether to force color interpretation of input bands to output bands
+          callback --- callback method
+          callback_data --- user data for callback
+    """
+    import copy
+
+    if _is_str_or_unicode(options):
+        new_options = ParseCommandLine(options)
+    else:
+        new_options = copy.copy(options)
+        new_options += ['-of', format]
+        if outputType != GDT_Unknown:
+            new_options += ['-ot', GetDataTypeName(outputType) ]
+        if workingType != GDT_Unknown:
+            new_options += ['-wt', GetDataTypeName(workingType) ]
+        if outputBounds is not None:
+            new_options += ['-te', str(outputBounds[0]), str(outputBounds[1]), str(outputBounds[2]), str(outputBounds[3]) ]
+        if outputBoundsSRS is not None:
+            new_options += ['-te_srs', str(outputBoundsSRS) ]
+        if xRes is not None and yRes is not None:
+            new_options += ['-tr', str(xRes), str(yRes) ]
+        if width != 0 or height != 0:
+            new_options += ['-ts', str(width), str(height)]
+        if srcSRS is not None:
+            new_options += ['-s_srs', str(srcSRS) ]
+        if dstSRS is not None:
+            new_options += ['-t_srs', str(dstSRS) ]
+        if targetAlignedPixels:
+            new_options += ['-tap']
+        if srcAlpha:
+            new_options += ['-srcalpha']
+        if dstAlpha:
+            new_options += ['-dstalpha']
+        if warpOptions is not None:
+            for opt in warpOptions:
+                new_options += ['-wo', str(opt)]
+        if errorThreshold is not None:
+            new_options += ['-et', str(errorThreshold)]
+        if resampleAlg is not None:
+            if resampleAlg == GRIORA_NearestNeighbour:
+                new_options += ['-r', 'near']
+            elif resampleAlg == GRIORA_Bilinear:
+                new_options += ['-rb']
+            elif resampleAlg == GRIORA_Cubic:
+                new_options += ['-rc']
+            elif resampleAlg == GRIORA_CubicSpline:
+                new_options += ['-rcs']
+            elif resampleAlg == GRIORA_Lanczos:
+                new_options += ['-r', 'lanczos']
+            elif resampleAlg == GRIORA_Average:
+                new_options += ['-r', 'average']
+            elif resampleAlg == GRIORA_Mode:
+                new_options += ['-r', 'mode']
+            elif resampleAlg == GRIORA_Gauss:
+                new_options += ['-r', 'gauss']
+            else:
+                new_options += ['-r', str(resampleAlg) ]
+        if warpMemoryLimit is not None:
+            new_options += ['-wm', str(warpMemoryLimit) ]
+        if creationOptions is not None:
+            for opt in creationOptions:
+                new_options += ['-co', opt ]
+        if srcNodata is not None:
+            new_options += ['-srcnodata', str(srcNodata) ]
+        if dstNodata is not None:
+            new_options += ['-dstnodata', str(dstNodata) ]
+        if multithread:
+            new_options += ['-multi']
+        if tps:
+            new_options += ['-tps']
+        if rpc:
+            new_options += ['-rpc']
+        if geoloc:
+            new_options += ['-geoloc']
+        if polynomialOrder is not None:
+            new_options += ['-order', str(polynomialOrder)]
+        if transformerOptions is not None:
+            for opt in transformerOptions:
+                new_options += ['-to', opt ]
+        if cutlineDSName is not None:
+            new_options += ['-cutline', str(cutlineDSName) ]
+        if cutlineLayer is not None:
+            new_options += ['-cl', str(cutlineLayer) ]
+        if cutlineWhere is not None:
+            new_options += ['-cwhere', str(cutlineWhere) ]
+        if cutlineSQL is not None:
+            new_options += ['-csql', str(cutlineSQL) ]
+        if cutlineBlend is not None:
+            new_options += ['-cblend', str(cutlineBlend) ]
+        if cropToCutline:
+            new_options += ['-crop_to_cutline']
+        if not copyMetadata:
+            new_options += ['-nomd']
+        if metadataConflictValue:
+            new_options += ['-cvmd', str(metadataConflictValue) ]
+        if setColorInterpretation:
+            new_options += ['-setci']
+
+    return (GDALWarpAppOptions(new_options), callback, callback_data)
+
+def Warp(destNameOrDestDS, srcDSOrSrcDSTab, **kwargs):
+    """ Warp one or several datasets.
+        Arguments are :
+          destNameOrDestDS --- Output dataset name or object
+          srcDSOrSrcDSTab --- an array of Dataset objects or filenames, or a Dataset object or a filename
+        Keyword arguments are :
+          options --- return of gdal.InfoOptions(), string or array of strings
+          other keywords arguments of gdal.WarpOptions()
+        If options is provided as a gdal.WarpOptions() object, other keywords are ignored. """
+
+    if not 'options' in kwargs or type(kwargs['options']) == type([]) or _is_str_or_unicode(kwargs['options']):
+        (opts, callback, callback_data) = WarpOptions(**kwargs)
+    else:
+        (opts, callback, callback_data) = kwargs['options']
+    if _is_str_or_unicode(srcDSOrSrcDSTab):
+        srcDSTab = [Open(srcDSOrSrcDSTab)]
+    elif type(srcDSOrSrcDSTab) == type([]):
+        srcDSTab = []
+        for elt in srcDSOrSrcDSTab:
+            if _is_str_or_unicode(elt):
+                srcDSTab.append(Open(elt))
+            else:
+                srcDSTab.append(elt)
+    else:
+        srcDSTab = [ srcDSOrSrcDSTab ]
+
+    if _is_str_or_unicode(destNameOrDestDS):
+        return wrapper_GDALWarpDestName(destNameOrDestDS, srcDSTab, opts, callback, callback_data)
+    else:
+        return wrapper_GDALWarpDestDS(destNameOrDestDS, srcDSTab, opts, callback, callback_data)
+
+
+def VectorTranslateOptions(options = [], format = 'ESRI Shapefile',
+         accessMode = None,
+         srcSRS = None, dstSRS = None, reproject = True,
+         SQLStatement = None, SQLDialect = None, where = None, selectFields = None, spatFilter = None,
+         datasetCreationOptions = None,
+         layerCreationOptions = None,
+         layers = None,
+         layerName = None,
+         geometryType = None,
+         dim = None,
+         segmentizeMaxDist= None,
+         zField = None,
+         skipFailures = False,
+         callback = None, callback_data = None):
+    """ Create a VectorTranslateOptions() object that can be passed to gdal.VectorTranslate()
+        Keyword arguments are :
+          options --- can be be an array of strings, a string or let empty and filled from other keywords.
+          format --- output format ("ESRI Shapefile", etc...)
+          accessMode --- None for creation, 'update', 'append', 'overwrite'
+          srcSRS --- source SRS
+          dstSRS --- output SRS (with reprojection if reproject = True)
+          reproject --- whether to do reprojection
+          SQLStatement --- SQL statement to apply to the source dataset
+          SQLDialect --- SQL dialect ('OGRSQL', 'SQLITE', ...)
+          where --- WHERE clause to apply to source layer(s)
+          selectFields --- list of fields to select
+          spatFilter --- spatial filter as (minX, minY, maxX, maxY) bounding box
+          datasetCreationOptions --- list of dataset creation options
+          layerCreationOptions --- list of layer creation options
+          layers --- list of layers to convert
+          layerName --- output layer name
+          geometryType --- output layer geometry type ('POINT', ....)
+          dim --- output dimension ('XY', 'XYZ', 'XYM', 'XYZM', 'layer_dim')
+          segmentizeMaxDist --- maximum distance between consecutive nodes of a line geometry
+          zField --- name of field to use to set the Z component of geometries
+          skipFailures --- whether to skip failures
+          callback --- callback method
+          callback_data --- user data for callback
+    """
+    import copy
+
+    if _is_str_or_unicode(options):
+        new_options = ParseCommandLine(options)
+    else:
+        new_options = copy.copy(options)
+        new_options += ['-f', format]
+        if srcSRS is not None:
+            new_options += ['-s_srs', str(srcSRS) ]
+        if dstSRS is not None:
+            if reproject:
+                new_options += ['-t_srs', str(dstSRS) ]
+            else:
+                new_options += ['-a_srs', str(dstSRS) ]
+        if SQLStatement is not None:
+            new_options += ['-sql', str(SQLStatement) ]
+        if SQLDialect is not None:
+            new_options += ['-dialect', str(SQLDialect) ]
+        if where is not None:
+            new_options += ['-where', str(where) ]
+        if accessMode is not None:
+            if accessMode == 'update':
+                new_options += ['-update']
+            elif accessMode == 'append':
+                new_options += ['-append']
+            elif accessMode == 'overwrite':
+                new_options += ['-overwrite']
+            else:
+                raise Exception('unhandled accessMode')
+        if selectFields is not None:
+            val = ''
+            for item in selectFields:
+                if len(val)>0:
+                    val += ','
+                val += item
+            new_options += ['-select', val]
+        if datasetCreationOptions is not None:
+            for opt in datasetCreationOptions:
+                new_options += ['-dsco', opt ]
+        if layerCreationOptions is not None:
+            for opt in layerCreationOptions:
+                new_options += ['-lco', opt ]
+        if layers is not None:
+            for lyr in layers:
+                new_options += [ lyr ]
+        if segmentizeMaxDist is not None:
+            new_options += ['-segmentize', str(segmentizeMaxDist) ]
+        if spatFilter is not None:
+            new_options += ['-spat', str(spatFilter[0]), str(spatFilter[1]), str(spatFilter[2]), str(spatFilter[3]) ]
+        if layerName is not None:
+            new_options += ['-nln', layerName]
+        if geometryType is not None:
+            new_options += ['-nlt', geometryType]
+        if dim is not None:
+            new_options += ['-dim', dim]
+        if zField is not None:
+            new_options += ['-zfield', zField]
+        if skipFailures:
+            new_options += ['-skip']
+
+    if callback is not None:
+        new_options += [ '-progress' ]
+
+    return (GDALVectorTranslateOptions(new_options), callback, callback_data)
+
+def VectorTranslate(destNameOrDestDS, srcDS, **kwargs):
+    """ Convert one vector dataset
+        Arguments are :
+          destNameOrDestDS --- Output dataset name or object
+          srcDS --- a Dataset object or a filename
+        Keyword arguments are :
+          options --- return of gdal.InfoOptions(), string or array of strings
+          other keywords arguments of gdal.VectorTranslateOptions()
+        If options is provided as a gdal.VectorTranslateOptions() object, other keywords are ignored. """
+
+    if not 'options' in kwargs or type(kwargs['options']) == type([]) or _is_str_or_unicode(kwargs['options']):
+        (opts, callback, callback_data) = VectorTranslateOptions(**kwargs)
+    else:
+        (opts, callback, callback_data) = kwargs['options']
+    if _is_str_or_unicode(srcDS):
+        srcDS = OpenEx(srcDS)
+
+    if _is_str_or_unicode(destNameOrDestDS):
+        return wrapper_GDALVectorTranslateDestName(destNameOrDestDS, srcDS, opts, callback, callback_data)
+    else:
+        return wrapper_GDALVectorTranslateDestDS(destNameOrDestDS, srcDS, opts, callback, callback_data)
+
+def DEMProcessingOptions(options = [], colorFilename = None, format = 'GTiff',
+              creationOptions = None, computeEdges = False, alg = 'Horn', band = 1,
+              zFactor = None, scale = None, azimuth = None, altitude = None, combined = False,
+              slopeFormat = None, trigonometric = False, zeroForFlat = False,
+              callback = None, callback_data = None):
+    """ Create a DEMProcessingOptions() object that can be passed to gdal.DEMProcessing()
+        Keyword arguments are :
+          options --- can be be an array of strings, a string or let empty and filled from other keywords.
+          colorFilename --- (mandatory for "color-relief") name of file that contains palette definition for the "color-relief" processing.
+          format --- output format ("GTiff", etc...)
+          creationOptions --- list of creation options
+          computeEdges --- whether to compute values at raster edges.
+          alg --- 'ZevenbergenThorne' or 'Horn'
+          band --- source band number to use
+          zFactor --- (hillshade only) vertical exaggeration used to pre-multiply the elevations.
+          scale --- ratio of vertical units to horizontal.
+          azimuth --- (hillshade only) azimuth of the light, in degrees. 0 if it comes from the top of the raster, 90 from the east, ... The default value, 315, should rarely be changed as it is the value generally used to generate shaded maps.
+          altitude ---(hillshade only) altitude of the light, in degrees. 90 if the light comes from above the DEM, 0 if it is raking light.
+          combined --- (hillshade only) whether to compute combined shading, a combination of slope and oblique shading.
+          slopeformat --- (slope only) "degree" or "percent".
+          trigonometric --- (aspect only) whether to return trigonometric angle instead of azimuth. Thus 0deg means East, 90deg North, 180deg West, 270deg South.
+          zeroForFlat --- (aspect only) whether to return 0 for flat areas with slope=0, instead of -9999.
+          callback --- callback method
+          callback_data --- user data for callback
+    """
+    import copy
+
+    if _is_str_or_unicode(options):
+        new_options = ParseCommandLine(options)
+    else:
+        new_options = copy.copy(options)
+        new_options += ['-of', format]
+        if creationOptions is not None:
+            for opt in creationOptions:
+                new_options += ['-co', opt ]
+        if computeEdges:
+            new_options += ['-compute_edges' ]
+        if alg ==  'ZevenbergenThorne':
+            new_options += ['-alg', 'ZevenbergenThorne']
+        new_options += ['-b', str(band) ]
+        if zFactor is not None:
+            new_options += ['-z', str(zFactor) ]
+        if scale is not None:
+            new_options += ['-s', str(scale) ]
+        if azimuth is not None:
+            new_options += ['-az', str(azimuth) ]
+        if altitude is not None:
+            new_options += ['-alt', str(altitude) ]
+        if combined:
+            new_options += ['-combined' ]
+        if slopeFormat == 'percent':
+            new_options += ['-p' ]
+        if trigonometric:
+            new_options += ['-trigonometric' ]
+        if zeroForFlat:
+            new_options += ['zero_for_flat' ]
+
+    return (GDALDEMProcessingOptions(new_options), colorFilename, callback, callback_data)
+
+def DEMProcessing(destName, srcDS, processing, **kwargs):
+    """ Apply a DEM processing.
+        Arguments are :
+          destName --- Output dataset name
+          srcDS --- a Dataset object or a filename
+          processing --- one of "hillshade", "slope", "aspect", "color-relief", "TRI", "TPI", "Roughness"
+        Keyword arguments are :
+          options --- return of gdal.InfoOptions(), string or array of strings
+          other keywords arguments of gdal.DEMProcessingOptions()
+        If options is provided as a gdal.DEMProcessingOptions() object, other keywords are ignored. """
+
+    if not 'options' in kwargs or type(kwargs['options']) == type([]) or _is_str_or_unicode(kwargs['options']):
+        (opts, colorFilename, callback, callback_data) = DEMProcessingOptions(**kwargs)
+    else:
+        (opts, colorFilename, callback, callback_data) = kwargs['options']
+    if _is_str_or_unicode(srcDS):
+        srcDS = Open(srcDS)
+
+    return DEMProcessingInternal(destName, srcDS, processing, colorFilename, opts, callback, callback_data)
+
+
+def NearblackOptions(options = [], format = 'GTiff',
+         creationOptions = None, white = False, colors = None,
+         maxNonBlack = None, nearDist = None, setAlpha = False, setMask = False,
+         callback = None, callback_data = None):
+    """ Create a NearblackOptions() object that can be passed to gdal.Nearblack()
+        Keyword arguments are :
+          options --- can be be an array of strings, a string or let empty and filled from other keywords.
+          format --- output format ("GTiff", etc...)
+          creationOptions --- list of creation options
+          white --- whether to search for nearly white (255) pixels instead of nearly black pixels.
+          colors --- list of colors  to search for, e.g. ((0,0,0),(255,255,255)). The pixels that are considered as the collar are set to 0
+          maxNonBlack --- number of non-black (or other searched colors specified with white / colors) pixels that can be encountered before the giving up search inwards. Defaults to 2.
+          nearDist --- select how far from black, white or custom colors the pixel values can be and still considered near black, white or custom color.  Defaults to 15.
+          setAlpha --- adds an alpha band if the output file.
+          setMask --- adds a mask band to the output file.
+          callback --- callback method
+          callback_data --- user data for callback
+    """
+    import copy
+
+    if _is_str_or_unicode(options):
+        new_options = ParseCommandLine(options)
+    else:
+        new_options = copy.copy(options)
+        new_options += ['-of', format]
+        if creationOptions is not None:
+            for opt in creationOptions:
+                new_options += ['-co', opt ]
+        if white:
+            new_options += ['-white']
+        if colors is not None:
+            for color in colors:
+                color_str = ''
+                for cpt in color:
+                    if color_str != '':
+                        color_str += ','
+                    color_str += str(cpt)
+                new_options += ['-color',color_str]
+        if maxNonBlack is not None:
+            new_options += ['-nb', str(maxNonBlack) ]
+        if nearDist is not None:
+            new_options += ['-near', str(nearDist) ]
+        if setAlpha:
+            new_options += ['-setalpha']
+        if setMask:
+            new_options += ['-setmask']
+
+    return (GDALNearblackOptions(new_options), callback, callback_data)
+
+def Nearblack(destNameOrDestDS, srcDS, **kwargs):
+    """ Convert nearly black/white borders to exact value.
+        Arguments are :
+          destNameOrDestDS --- Output dataset name or object
+          srcDS --- a Dataset object or a filename
+        Keyword arguments are :
+          options --- return of gdal.InfoOptions(), string or array of strings
+          other keywords arguments of gdal.NearblackOptions()
+        If options is provided as a gdal.NearblackOptions() object, other keywords are ignored. """
+
+    if not 'options' in kwargs or type(kwargs['options']) == type([]) or _is_str_or_unicode(kwargs['options']):
+        (opts, callback, callback_data) = NearblackOptions(**kwargs)
+    else:
+        (opts, callback, callback_data) = kwargs['options']
+    if _is_str_or_unicode(srcDS):
+        srcDS = OpenEx(srcDS)
+
+    if _is_str_or_unicode(destNameOrDestDS):
+        return wrapper_GDALNearblackDestName(destNameOrDestDS, srcDS, opts, callback, callback_data)
+    else:
+        return wrapper_GDALNearblackDestDS(destNameOrDestDS, srcDS, opts, callback, callback_data)
+
+
+def GridOptions(options = [], format = 'GTiff',
+              outputType = GDT_Unknown,
+              width = 0, height = 0,
+              creationOptions = None,
+              outputBounds = None,
+              outputSRS = None,
+              noData = None,
+              algorithm = None,
+              layers = None,
+              SQLStatement = None,
+              where = None,
+              spatFilter = None,
+              zfield = None,
+              z_increase = None,
+              z_multiply = None,
+              callback = None, callback_data = None):
+    """ Create a GridOptions() object that can be passed to gdal.Grid()
+        Keyword arguments are :
+          options --- can be be an array of strings, a string or let empty and filled from other keywords.
+          format --- output format ("GTiff", etc...)
+          outputType --- output type (gdal.GDT_Byte, etc...)
+          width --- width of the output raster in pixel
+          height --- height of the output raster in pixel
+          creationOptions --- list of creation options
+          outputBounds --- assigned output bounds: [ulx, uly, lrx, lry]
+          outputSRS --- assigned output SRS
+          noData --- nodata value
+          algorithm --- e.g "invdist:power=2.0:smoothing=0.0:radius1=0.0:radius2=0.0:angle=0.0:max_points=0:min_points=0:nodata=0.0"
+          layers --- list of layers to convert
+          SQLStatement --- SQL statement to apply to the source dataset
+          where --- WHERE clause to apply to source layer(s)
+          spatFilter --- spatial filter as (minX, minY, maxX, maxY) bounding box
+          zfield --- Identifies an attribute field on the features to be used to get a Z value from. This value overrides Z value read from feature geometry record.
+          z_increase --- Addition to the attribute field on the features to be used to get a Z value from. The addition should be the same unit as Z value. The result value will be Z value + Z increase value. The default value is 0.
+          z_multiply - Multiplication ratio for Z field. This can be used for shift from e.g. foot to meters or from  elevation to deep. The result value will be (Z value + Z increase value) * Z multiply value.  The default value is 1.
+          callback --- callback method
+          callback_data --- user data for callback
+    """
+    import copy
+
+    if _is_str_or_unicode(options):
+        new_options = ParseCommandLine(options)
+    else:
+        new_options = copy.copy(options)
+        new_options += ['-of', format]
+        if outputType != GDT_Unknown:
+            new_options += ['-ot', GetDataTypeName(outputType) ]
+        if width != 0 or height != 0:
+            new_options += ['-outsize', str(width), str(height)]
+        if creationOptions is not None:
+            for opt in creationOptions:
+                new_options += ['-co', opt ]
+        if outputBounds is not None:
+            new_options += ['-txe', str(outputBounds[0]), str(outputBounds[2]), '-tye', str(outputBounds[1]), str(outputBounds[3])]
+        if outputSRS is not None:
+            new_options += ['-a_srs', str(outputSRS) ]
+        if algorithm is not None:
+            new_options += ['-a', algorithm ]
+        if layers is not None:
+            if type(layers) == type(()) or type(layers) == type([]):
+                for layer in layers:
+                    new_options += ['-l', layer]
+            else:
+                new_options += ['-l', layers]
+        if SQLStatement is not None:
+            new_options += ['-sql', str(SQLStatement) ]
+        if where is not None:
+            new_options += ['-where', str(where) ]
+        if zfield is not None:
+            new_options += ['-zfield', zfield ]
+        if z_increase is not None:
+            new_options += ['-z_increase', str(z_increase) ]
+        if z_multiply is not None:
+            new_options += ['-z_multiply', str(z_multiply) ]
+        if spatFilter is not None:
+            new_options += ['-spat', str(spatFilter[0]), str(spatFilter[1]), str(spatFilter[2]), str(spatFilter[3]) ]
+
+    return (GDALGridOptions(new_options), callback, callback_data)
+
+def Grid(destName, srcDS, **kwargs):
+    """ Create raster from the scattered data.
+        Arguments are :
+          destName --- Output dataset name
+          srcDS --- a Dataset object or a filename
+        Keyword arguments are :
+          options --- return of gdal.InfoOptions(), string or array of strings
+          other keywords arguments of gdal.GridOptions()
+        If options is provided as a gdal.GridOptions() object, other keywords are ignored. """
+
+    if not 'options' in kwargs or type(kwargs['options']) == type([]) or _is_str_or_unicode(kwargs['options']):
+        (opts, callback, callback_data) = GridOptions(**kwargs)
+    else:
+        (opts, callback, callback_data) = kwargs['options']
+    if _is_str_or_unicode(srcDS):
+        srcDS = OpenEx(srcDS, OF_VECTOR)
+
+    return GridInternal(destName, srcDS, opts, callback, callback_data)
+
+def RasterizeOptions(options = [], format = None,
+         creationOptions = None, noData = None, initValues = None,
+         outputBounds = None, outputSRS = None,
+         width = None, height = None,
+         xRes = None, yRes = None, targetAlignedPixels = False,
+         bands = None, inverse = False, allTouched = False,
+         burnValues = None, attribute = None, useZ = False, layers = None,
+         SQLStatement = None, SQLDialect = None, where = None,
+         callback = None, callback_data = None):
+    """ Create a RasterizeOptions() object that can be passed to gdal.Rasterize()
+        Keyword arguments are :
+          options --- can be be an array of strings, a string or let empty and filled from other keywords.
+          format --- output format ("GTiff", etc...)
+          creationOptions --- list of creation options
+          outputBounds --- assigned output bounds: [minx, miny, maxx, maxy]
+          outputSRS --- assigned output SRS
+          width --- width of the output raster in pixel
+          height --- height of the output raster in pixel
+          xRes, yRes --- output resolution in target SRS
+          targetAlignedPixels --- whether to force output bounds to be multiple of output resolution
+          noData --- nodata value
+          initValues --- Value or list of values to pre-initialize the output image bands with.  However, it is not marked as the nodata value in the output file.  If only one value is given, the same value is used in all the bands.
+          bands --- list of output bands to burn values into
+          inverse --- whether to invert rasterization, i.e. burn the fixed burn value, or the burn value associated  with the first feature into all parts of the image not inside the provided a polygon.
+          allTouched -- whether to enable the ALL_TOUCHED rasterization option so that all pixels touched by lines or polygons will be updated, not just those on the line render path, or whose center point is within the polygon.
+          burnValues -- list of fixed values to burn into each band for all objects. Excusive with attribute.
+          attribute --- identifies an attribute field on the features to be used for a burn-in value. The value will be burned into all output bands. Excusive with burnValues.
+          useZ --- whether to indicate that a burn value should be extracted from the "Z" values of the feature. These values are added to the burn value given by burnValues or attribute if provided. As of now, only points and lines are drawn in 3D.
+          layers --- list of layers from the datasource that will be used for input features.
+          SQLStatement --- SQL statement to apply to the source dataset
+          SQLDialect --- SQL dialect ('OGRSQL', 'SQLITE', ...)
+          where --- WHERE clause to apply to source layer(s)
+          callback --- callback method
+          callback_data --- user data for callback
+    """
+    import copy
+
+    if _is_str_or_unicode(options):
+        new_options = ParseCommandLine(options)
+    else:
+        new_options = copy.copy(options)
+        if format is not None:
+            new_options += ['-of', format]
+        if creationOptions is not None:
+            for opt in creationOptions:
+                new_options += ['-co', opt ]
+        if bands is not None:
+            for b in bands:
+                new_options += ['-b', str(b) ]
+        if noData is not None:
+            new_options += ['-a_nodata', str(noData) ]
+        if initValues is not None:
+            if type(initValues) == type(()) or type(initValues) == type([]):
+                for val in initValues:
+                    new_options += ['-init', str(val) ]
+            else:
+                new_options += ['-init', str(initValues) ]
+        if outputBounds is not None:
+            new_options += ['-te', str(outputBounds[0]), str(outputBounds[1]), str(outputBounds[2]), str(outputBounds[3])]
+        if outputSRS is not None:
+            new_options += ['-a_srs', str(outputSRS) ]
+        if width is not None and height is not None:
+            new_options += ['-ts', str(width), str(height)]
+        if xRes is not None and yRes is not None:
+            new_options += ['-tr', str(xRes), str(yRes)]
+        if targetAlignedPixels:
+            new_options += ['-tap']
+        if inverse:
+            new_options += ['-i']
+        if allTouched:
+            new_options += ['-at']
+        if burnValues is not None:
+            if attribute is not None:
+                raise Exception('burnValues and attribute option are exclusive.')
+            if type(burnValues) == type(()) or type(burnValues) == type([]):
+                for val in burnValues:
+                    new_options += ['-burn', str(val) ]
+            else:
+                new_options += ['-burn', str(burnValues) ]
+        if attribute is not None:
+            new_options += ['-a', attribute]
+        if useZ:
+            new_options += ['-3d']
+        if layers is not None:
+            if type(layers) == type(()) or type(layers) == type([]):
+                for layer in layers:
+                    new_options += ['-l', layer]
+            else:
+                new_options += ['-l', layers]
+        if SQLStatement is not None:
+            new_options += ['-sql', str(SQLStatement) ]
+        if SQLDialect is not None:
+            new_options += ['-dialect', str(SQLDialect) ]
+        if where is not None:
+            new_options += ['-where', str(where) ]
+
+    return (GDALRasterizeOptions(new_options), callback, callback_data)
+
+def Rasterize(destNameOrDestDS, srcDS, **kwargs):
+    """ Burns vector geometries into a raster
+        Arguments are :
+          destNameOrDestDS --- Output dataset name or object
+          srcDS --- a Dataset object or a filename
+        Keyword arguments are :
+          options --- return of gdal.InfoOptions(), string or array of strings
+          other keywords arguments of gdal.RasterizeOptions()
+        If options is provided as a gdal.RasterizeOptions() object, other keywords are ignored. """
+
+    if not 'options' in kwargs or type(kwargs['options']) == type([]) or _is_str_or_unicode(kwargs['options']):
+        (opts, callback, callback_data) = RasterizeOptions(**kwargs)
+    else:
+        (opts, callback, callback_data) = kwargs['options']
+    if _is_str_or_unicode(srcDS):
+        srcDS = OpenEx(srcDS)
+
+    if _is_str_or_unicode(destNameOrDestDS):
+        return wrapper_GDALRasterizeDestName(destNameOrDestDS, srcDS, opts, callback, callback_data)
+    else:
+        return wrapper_GDALRasterizeDestDS(destNameOrDestDS, srcDS, opts, callback, callback_data)
+
+
+def BuildVRTOptions(options = [],
+                    resolution = None,
+                    outputBounds = None,
+                    xRes = None, yRes = None,
+                    targetAlignedPixels = None,
+                    separate = None,
+                    bandList = None,
+                    addAlpha = None,
+                    resampleAlg = None,
+                    outputSRS = None,
+                    allowProjectionDifference = None,
+                    srcNodata = None,
+                    VRTNodata = None,
+                    hideNodata = None,
+                    callback = None, callback_data = None):
+    """ Create a BuildVRTOptions() object that can be passed to gdal.BuildVRT()
+        Keyword arguments are :
+          options --- can be be an array of strings, a string or let empty and filled from other keywords..
+          resolution --- 'highest', 'lowest', 'average', 'user'.
+          outputBounds --- output bounds as (minX, minY, maxX, maxY) in target SRS.
+          xRes, yRes --- output resolution in target SRS.
+          targetAlignedPixels --- whether to force output bounds to be multiple of output resolution.
+          separate --- whether each source file goes into a separate stacked band in the VRT band.
+          bandList --- array of band numbers (index start at 1).
+          addAlpha --- whether to add an alpha mask band to the VRT when the source raster have none.
+          resampleAlg --- resampling mode.
+          outputSRS --- assigned output SRS.
+          allowProjectionDifference --- whether to accept input datasets have not the same projection. Note: they will *not* be reprojected.
+          srcNodata --- source nodata value(s).
+          VRTNodata --- nodata values at the VRT band level.
+          hideNodata --- whether to make the VRT band not report the NoData value.
+          callback --- callback method.
+          callback_data --- user data for callback.
+    """
+    import copy
+
+    if _is_str_or_unicode(options):
+        new_options = ParseCommandLine(options)
+    else:
+        new_options = copy.copy(options)
+        if resolution is not None:
+            new_options += ['-resolution', str(resolution) ]
+        if outputBounds is not None:
+            new_options += ['-te', str(outputBounds[0]), str(outputBounds[1]), str(outputBounds[2]), str(outputBounds[3])]
+        if xRes is not None and yRes is not None:
+            new_options += ['-tr', str(xRes), str(yRes)]
+        if targetAlignedPixels:
+            new_options += ['-tap']
+        if separate:
+            new_options += ['-separate']
+        if bandList != None:
+            for b in bandList:
+                new_options += ['-b', str(b) ]
+        if addAlpha:
+            new_options += ['-addalpha']
+        if resampleAlg is not None:
+            if resampleAlg == GRIORA_NearestNeighbour:
+                new_options += ['-r', 'near']
+            elif resampleAlg == GRIORA_Bilinear:
+                new_options += ['-rb']
+            elif resampleAlg == GRIORA_Cubic:
+                new_options += ['-rc']
+            elif resampleAlg == GRIORA_CubicSpline:
+                new_options += ['-rcs']
+            elif resampleAlg == GRIORA_Lanczos:
+                new_options += ['-r', 'lanczos']
+            elif resampleAlg == GRIORA_Average:
+                new_options += ['-r', 'average']
+            elif resampleAlg == GRIORA_Mode:
+                new_options += ['-r', 'mode']
+            elif resampleAlg == GRIORA_Gauss:
+                new_options += ['-r', 'gauss']
+            else:
+                new_options += ['-r', str(resampleAlg) ]
+        if outputSRS is not None:
+            new_options += ['-a_srs', str(outputSRS) ]
+        if allowProjectionDifference:
+            new_options += ['-allow_projection_difference']
+        if srcNodata is not None:
+            new_options += ['-srcnodata', str(srcNodata) ]
+        if VRTNodata is not None:
+            new_options += ['-vrtnodata', str(VRTNodata) ]
+        if hideNodata:
+            new_options += ['-hidenodata']
+
+    return (GDALBuildVRTOptions(new_options), callback, callback_data)
+
+def BuildVRT(destName, srcDSOrSrcDSTab, **kwargs):
+    """ Build a VRT from a list of datasets.
+        Arguments are :
+          destName --- Output dataset name
+          srcDSOrSrcDSTab --- an array of Dataset objects or filenames, or a Dataset object or a filename
+        Keyword arguments are :
+          options --- return of gdal.InfoOptions(), string or array of strings
+          other keywords arguments of gdal.BuildVRTOptions()
+        If options is provided as a gdal.BuildVRTOptions() object, other keywords are ignored. """
+
+    if not 'options' in kwargs or type(kwargs['options']) == type([]) or _is_str_or_unicode(kwargs['options']):
+        (opts, callback, callback_data) = BuildVRTOptions(**kwargs)
+    else:
+        (opts, callback, callback_data) = kwargs['options']
+
+    srcDSTab = []
+    srcDSNamesTab = []
+    if _is_str_or_unicode(srcDSOrSrcDSTab):
+        srcDSNamesTab = [ srcDSOrSrcDSTab ]
+    elif type(srcDSOrSrcDSTab) == type([]):
+        for elt in srcDSOrSrcDSTab:
+            if _is_str_or_unicode(elt):
+                srcDSNamesTab.append(elt)
+            else:
+                srcDSTab.append(elt)
+        if len(srcDSTab) != 0 and len(srcDSNamesTab) != 0:
+            raise Exception('Mix of names and dataset objects not supported')
+    else:
+        srcDSTab = [ srcDSOrSrcDSTab ]
+
+    if len(srcDSTab) > 0:
+        return BuildVRTInternalObjects(destName, srcDSTab, opts, callback, callback_data)
+    else:
+        return BuildVRTInternalNames(destName, srcDSNamesTab, opts, callback, callback_data)
+
+%}
diff --git a/swig/include/python/ogr_python.i b/swig/include/python/ogr_python.i
index d430806..e0580d2 100644
--- a/swig/include/python/ogr_python.i
+++ b/swig/include/python/ogr_python.i
@@ -1,10 +1,9 @@
 /*
- * $Id: ogr_python.i 29550 2015-07-21 13:24:49Z rouault $
+ * $Id: ogr_python.i 33763 2016-03-21 16:31:17Z rouault $
  *
  * python specific code for ogr bindings.
  */
 
-
 %feature("autodoc");
 
 #ifndef FROM_GDAL_I
@@ -13,14 +12,14 @@
   if ( OGRGetDriverCount() == 0 ) {
     OGRRegisterAll();
   }
-  
+
 %}
 #endif
 
 /*%{
-    
-#if PY_MINOR_VERSION >= 4 
-#include "datetime.h" 
+
+#if PY_MINOR_VERSION >= 4
+#include "datetime.h"
 #define USE_PYTHONDATETIME 1
 #endif
 %}
@@ -48,19 +47,19 @@
 %extend OGRDataSourceShadow {
   %pythoncode {
     def Destroy(self):
-      "Once called, self has effectively been destroyed.  Do not access. For backwards compatiblity only"
+      "Once called, self has effectively been destroyed.  Do not access. For backwards compatibility only"
       _ogr.delete_DataSource( self )
       self.thisown = 0
 
     def Release(self):
-      "Once called, self has effectively been destroyed.  Do not access. For backwards compatiblity only"
+      "Once called, self has effectively been destroyed.  Do not access. For backwards compatibility only"
       _ogr.delete_DataSource( self )
       self.thisown = 0
 
     def Reference(self):
       "For backwards compatibility only."
       return self.Reference()
-  
+
     def Dereference(self):
       "For backwards compatibility only."
       self.Dereference()
@@ -123,7 +122,7 @@
     def Reference(self):
       "For backwards compatibility only."
       pass
-  
+
     def Dereference(self):
       "For backwards compatibility only."
       pass
@@ -202,7 +201,7 @@
     OGR_F_SetFieldString(self, id, value);
   }
   %clear (const char* value );
-  
+
   %pythoncode %{
     def Reference(self):
       pass
@@ -211,7 +210,7 @@
       pass
 
     def Destroy(self):
-      "Once called, self has effectively been destroyed.  Do not access. For backwards compatiblity only"
+      "Once called, self has effectively been destroyed.  Do not access. For backwards compatibility only"
       _ogr.delete_Feature( self )
       self.thisown = 0
 
@@ -222,7 +221,7 @@
     def __copy__(self):
         return self.Clone()
 
-    # This makes it possible to fetch fields in the form "feature.area". 
+    # This makes it possible to fetch fields in the form "feature.area".
     # This has some risk of name collisions.
     def __getattr__(self, key):
         """Returns the values of fields by the given name"""
@@ -239,7 +238,7 @@
         else:
             return self.GetField(idx)
 
-    # This makes it possible to set fields in the form "feature.area". 
+    # This makes it possible to set fields in the form "feature.area".
     # This has some risk of name collisions.
     def __setattr__(self, key, value):
         """Set the values of fields by the given name"""
@@ -256,7 +255,7 @@
                 else:
                     self.__dict__[key] = value
 
-    # This makes it possible to fetch fields in the form "feature['area']". 
+    # This makes it possible to fetch fields in the form "feature['area']".
     def __getitem__(self, key):
         """Returns the values of fields by the given name / field_index"""
         if isinstance(key, str):
@@ -271,7 +270,7 @@
         else:
             return self.GetField(fld_index)
 
-    # This makes it possible to set fields in the form "feature['area'] = 123". 
+    # This makes it possible to set fields in the form "feature['area'] = 123".
     def __setitem__(self, key, value):
         """Returns the value of a field by field name / index"""
         if isinstance(key, str):
@@ -327,9 +326,9 @@
         SetField(self, char name, int value)
         SetField(self, int id, double value)
         SetField(self, char name, double value)
-        SetField(self, int id, int year, int month, int day, int hour, int minute, 
+        SetField(self, int id, int year, int month, int day, int hour, int minute,
             int second, int tzflag)
-        SetField(self, char name, int year, int month, int day, int hour, 
+        SetField(self, char name, int year, int month, int day, int hour,
             int minute, int second, int tzflag)
         """
 
@@ -386,7 +385,7 @@
             fieldname = self.GetFieldDefnRef(i).GetName()
             names.append(fieldname)
         return names
-    
+
     def items(self):
         keys = self.keys()
         output = {}
@@ -398,7 +397,7 @@
 
     def ExportToJson(self, as_object = False, options = None):
         """Exports a GeoJSON object which represents the Feature. The
-           as_object parameter determines whether the returned value 
+           as_object parameter determines whether the returned value
            should be a Python object instead of a string. Defaults to False.
            The options parameter is passed to Geometry.ExportToJson()"""
 
@@ -422,15 +421,22 @@
         output = {'type':'Feature',
                    'geometry': geom_json_object,
                    'properties': {}
-                  } 
-        
+                  }
+
         fid = self.GetFID()
         if fid != NullFID:
             output['id'] = fid
-            
+
         for key in self.keys():
-            output['properties'][key] = self.GetField(key)
-        
+            fld_defn = self.GetFieldDefnRef(self.GetFieldIndex(key))
+            if fld_defn.GetType() == _ogr.OFTInteger and fld_defn.GetSubType() == _ogr.OFSTBoolean:
+                if self.GetField(key):
+                    output['properties'][key] = True
+                else:
+                    output['properties'][key] = False
+            else:
+                output['properties'][key] = self.GetField(key)
+
         if not as_object:
             output = simplejson.dumps(output)
 
@@ -444,25 +450,25 @@
 %extend OGRGeometryShadow {
 %pythoncode %{
   def Destroy(self):
-    self.__swig_destroy__(self) 
+    self.__swig_destroy__(self)
     self.__del__()
     self.thisown = 0
 
   def __str__(self):
     return self.ExportToWkt()
-    
+
 
   def __reduce__(self):
     return (self.__class__, (), self.ExportToWkb())
- 	
+
   def __setstate__(self, state):
       result = CreateGeometryFromWkb(state)
       self.this = result.this
-        
+
   def __iter__(self):
       self.iter_subgeom = 0
       return self
-      
+
   def next(self):
       if self.iter_subgeom < self.GetGeometryCount():
           subgeom = self.GetGeometryRef(self.iter_subgeom)
@@ -495,7 +501,7 @@
 %extend OGRFeatureDefnShadow {
 %pythoncode {
   def Destroy(self):
-    "Once called, self has effectively been destroyed.  Do not access. For backwards compatiblity only"
+    "Once called, self has effectively been destroyed.  Do not access. For backwards compatibility only"
     _ogr.delete_FeatureDefn( self )
     self.thisown = 0
 
@@ -505,7 +511,7 @@
 %extend OGRFieldDefnShadow {
 %pythoncode %{
   def Destroy(self):
-    "Once called, self has effectively been destroyed.  Do not access. For backwards compatiblity only"
+    "Once called, self has effectively been destroyed.  Do not access. For backwards compatibility only"
     _ogr.delete_FieldDefn( self )
     self.thisown = 0
 %}
@@ -527,10 +533,10 @@
 }
 #endif
 
-
+#ifdef no_longer_defined_since_it_breaks_py2exe_pyinstaller_ticket_6364
 %pythoncode %{
 
-# Backup original dictionnary before doing anything else
+# Backup original dictionary before doing anything else
 _initial_dict = globals().copy()
 
 @property
@@ -586,7 +592,7 @@ class _MyHelper(object):
             import sys
 
             # Restore original module before calling help() otherwise
-            # we don't get methods or classes mentionned
+            # we don't get methods or classes mentioned
             sys.modules[self.module.__name__] = self.module._original_module
 
             ret = self.original_help(self.module._original_module, **kwds)
@@ -605,3 +611,4 @@ del _MyHelper
 del _Module
 
 %}
+#endif
diff --git a/swig/include/python/osr_python.i b/swig/include/python/osr_python.i
index 4f14524..5fb8555 100644
--- a/swig/include/python/osr_python.i
+++ b/swig/include/python/osr_python.i
@@ -1,10 +1,9 @@
 /*
- * $Id: osr_python.i 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: osr_python.i 32939 2016-01-11 18:01:28Z rouault $
  *
  * python specific code for ogr bindings.
  */
 
-
 %feature("autodoc");
 
 #ifndef FROM_GDAL_I
@@ -19,7 +18,7 @@ py_OPTGetProjectionMethods(PyObject *self, PyObject *args) {
     PyObject *py_MList;
     char     **papszMethods;
     int      iMethod;
-    
+
     self = self;
     args = args;
 
@@ -33,10 +32,13 @@ py_OPTGetProjectionMethods(PyObject *self, PyObject *args) {
 	PyObject *py_PList;
 	int       iParam;
 
-	papszParameters = OPTGetParameterList( papszMethods[iMethod], 
+	papszParameters = OPTGetParameterList( papszMethods[iMethod],
 					       &pszUserMethodName );
         if( papszParameters == NULL )
+        {
+            CSLDestroy( papszMethods );
             return NULL;
+        }
 
 	py_PList = PyList_New(CSLCount(papszParameters));
 	for( iParam = 0; papszParameters[iParam] != NULL; iParam++ )
@@ -45,25 +47,25 @@ py_OPTGetProjectionMethods(PyObject *self, PyObject *args) {
 	    char    *pszUserParamName;
             double  dfDefault;
 
-	    OPTGetParameterInfo( papszMethods[iMethod], 
-				 papszParameters[iParam], 
-				 &pszUserParamName, 
+	    OPTGetParameterInfo( papszMethods[iMethod],
+				 papszParameters[iParam],
+				 &pszUserParamName,
 				 &pszType, &dfDefault );
-	    PyList_SetItem(py_PList, iParam, 
-			   Py_BuildValue("(sssd)", 
-					 papszParameters[iParam], 
-					 pszUserParamName, 
+	    PyList_SetItem(py_PList, iParam,
+			   Py_BuildValue("(sssd)",
+					 papszParameters[iParam],
+					 pszUserParamName,
                                          pszType, dfDefault ));
 	}
-	
+
 	CSLDestroy( papszParameters );
 
-	PyList_SetItem(py_MList, iMethod, 
-		       Py_BuildValue("(ssO)", 
-		                     papszMethods[iMethod], 
-				     pszUserMethodName, 
+	PyList_SetItem(py_MList, iMethod,
+		       Py_BuildValue("(ssO)",
+		                     papszMethods[iMethod],
+				     pszUserMethodName,
 		                     py_PList));
-        
+
         Py_XDECREF( py_PList );
     }
 
diff --git a/swig/include/python/python_exceptions.i b/swig/include/python/python_exceptions.i
index ed2964f..b6be2bd 100644
--- a/swig/include/python/python_exceptions.i
+++ b/swig/include/python/python_exceptions.i
@@ -4,16 +4,16 @@
  * it was moved into this file.
  */
 %{
-int bUseExceptions=0;
-CPLErrorHandler pfnPreviousHandler = CPLDefaultErrorHandler;
+static int bUseExceptions=0;
+static CPLErrorHandler pfnPreviousHandler = CPLDefaultErrorHandler;
 
-void CPL_STDCALL 
-PythonBindingErrorHandler(CPLErr eclass, int code, const char *msg ) 
+static void CPL_STDCALL
+PythonBindingErrorHandler(CPLErr eclass, int code, const char *msg )
 {
-  /* 
+  /*
   ** Generally we want to suppress error reporting if we have exceptions
-  ** enabled as the error message will be in the exception thrown in 
-  ** Python.  
+  ** enabled as the error message will be in the exception thrown in
+  ** Python.
   */
 
   /* If the error class is CE_Fatal, we want to have a message issued
@@ -35,20 +35,26 @@ PythonBindingErrorHandler(CPLErr eclass, int code, const char *msg )
 
 %inline %{
 
+static
 int GetUseExceptions() {
+  CPLErrorReset();
   return bUseExceptions;
 }
 
+static
 void UseExceptions() {
+  CPLErrorReset();
   if( !bUseExceptions )
   {
     bUseExceptions = 1;
-    pfnPreviousHandler = 
+    pfnPreviousHandler =
         CPLSetErrorHandler( (CPLErrorHandler) PythonBindingErrorHandler );
   }
 }
 
+static
 void DontUseExceptions() {
+  CPLErrorReset();
   if( bUseExceptions )
   {
     bUseExceptions = 0;
@@ -57,6 +63,25 @@ void DontUseExceptions() {
 }
 %}
 
+%{
+/* Completely unrelated: just to avoid Coverity warnings */
+
+static int bReturnSame = 1;
+
+void NeverCallMePlease() {
+    bReturnSame = 0;
+}
+
+/* Some SWIG code generates dead code, which Coverity warns about */
+template<class T> static T ReturnSame(T x)
+{
+    if( bReturnSame )
+        return x;
+    return 0;
+}
+
+%}
+
 %include exception.i
 
 %exception {
@@ -65,11 +90,12 @@ void DontUseExceptions() {
         CPLErrorReset();
     }
     $action
+%#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+%#endif
 }
-
diff --git a/swig/include/python/python_strings.i b/swig/include/python/python_strings.i
index 61e70ac..b1593ae 100644
--- a/swig/include/python/python_strings.i
+++ b/swig/include/python/python_strings.i
@@ -1,96 +1,96 @@
-/******************************************************************************
- * $Id: python_strings.i 20716 2010-09-30 22:27:35Z rouault $
- *
- * Name:     python_strings.i
- * Project:  GDAL Python Interface
- * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
- *
- ******************************************************************************
- * Copyright (c) 2009, Even Rouault
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *****************************************************************************/
- 
-%{
-
-/* Return a PyObject* from a NULL terminated C String */
-static PyObject* GDALPythonObjectFromCStr(const char *pszStr)
-{
-  const unsigned char* pszIter = (const unsigned char*) pszStr;
-  while(*pszIter != 0)
-  {
-    if (*pszIter > 127)
-    {
-        PyObject* pyObj = PyUnicode_DecodeUTF8(pszStr, strlen(pszStr), "ignore");
-        if (pyObj != NULL)
-            return pyObj;
-#if PY_VERSION_HEX >= 0x03000000
-        return PyBytes_FromString(pszStr);
-#else
-        return PyString_FromString(pszStr);
-#endif
-    }
-    pszIter ++;
-  }
-#if PY_VERSION_HEX >= 0x03000000
-  return PyUnicode_FromString(pszStr); 
-#else
-  return PyString_FromString(pszStr);
-#endif
-}
-
-/* Return a NULL terminated c String from a PyObject */
-/* Result must be freed with GDALPythonFreeCStr */
-static char* GDALPythonObjectToCStr(PyObject* pyObject, int* pbToFree)
-{
-  *pbToFree = 0;
-  if (PyUnicode_Check(pyObject))
-  {
-      char *pszStr;
-      char *pszNewStr;
-      Py_ssize_t nLen;
-      PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObject);
-#if PY_VERSION_HEX >= 0x03000000
-      PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
-#else
-      PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
-#endif
-      pszNewStr = (char *) malloc(nLen+1);
-      memcpy(pszNewStr, pszStr, nLen+1);
-      Py_XDECREF(pyUTF8Str);
-      *pbToFree = 1;
-      return pszNewStr;
-  }
-  else 
-  {
-#if PY_VERSION_HEX >= 0x03000000
-      return PyBytes_AsString(pyObject);
-#else
-      return PyString_AsString(pyObject);
-#endif
-  }
-}
-
-static void GDALPythonFreeCStr(void* ptr, int bToFree)
-{
-   if (bToFree)
-       free(ptr);
-}
-
-%}
+/******************************************************************************
+ * $Id: python_strings.i 33792 2016-03-26 12:54:28Z goatbar $
+ *
+ * Name:     python_strings.i
+ * Project:  GDAL Python Interface
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2009, Even Rouault
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+%{
+
+/* Return a PyObject* from a NULL terminated C String */
+static PyObject* GDALPythonObjectFromCStr(const char *pszStr)
+{
+  const unsigned char* pszIter = (const unsigned char*) pszStr;
+  while(*pszIter != 0)
+  {
+    if (*pszIter > 127)
+    {
+        PyObject* pyObj = PyUnicode_DecodeUTF8(pszStr, strlen(pszStr), "ignore");
+        if (pyObj != NULL)
+            return pyObj;
+#if PY_VERSION_HEX >= 0x03000000
+        return PyBytes_FromString(pszStr);
+#else
+        return PyString_FromString(pszStr);
+#endif
+    }
+    pszIter ++;
+  }
+#if PY_VERSION_HEX >= 0x03000000
+  return PyUnicode_FromString(pszStr);
+#else
+  return PyString_FromString(pszStr);
+#endif
+}
+
+/* Return a NULL terminated c String from a PyObject */
+/* Result must be freed with GDALPythonFreeCStr */
+static char* GDALPythonObjectToCStr(PyObject* pyObject, int* pbToFree)
+{
+  *pbToFree = 0;
+  if (PyUnicode_Check(pyObject))
+  {
+      char *pszStr;
+      char *pszNewStr;
+      Py_ssize_t nLen;
+      PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObject);
+#if PY_VERSION_HEX >= 0x03000000
+      PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+      PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+      pszNewStr = (char *) malloc(nLen+1);
+      memcpy(pszNewStr, pszStr, nLen+1);
+      Py_XDECREF(pyUTF8Str);
+      *pbToFree = 1;
+      return pszNewStr;
+  }
+  else
+  {
+#if PY_VERSION_HEX >= 0x03000000
+      return PyBytes_AsString(pyObject);
+#else
+      return PyString_AsString(pyObject);
+#endif
+  }
+}
+
+static void GDALPythonFreeCStr(void* ptr, int bToFree)
+{
+   if (bToFree)
+       free(ptr);
+}
+
+%}
diff --git a/swig/include/python/typemaps_python.i b/swig/include/python/typemaps_python.i
index 2d9366b..bf1b934 100644
--- a/swig/include/python/typemaps_python.i
+++ b/swig/include/python/typemaps_python.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: typemaps_python.i 29225 2015-05-21 16:28:00Z rouault $
+ * $Id: typemaps_python.i 32994 2016-01-15 10:53:46Z rouault $
  *
  * Name:     typemaps_python.i
  * Project:  GDAL Python Interface
@@ -51,7 +51,7 @@
  * double *val, int*hasval, is a special contrived typemap used for
  * the RasterBand GetNoDataValue, GetMinimum, GetMaximum, GetOffset, GetScale methods.
  * In the python bindings, the variable hasval is tested.  If it is 0 (is, the value
- * is not set in the raster band) then Py_None is returned.  If is is != 0, then
+ * is not set in the raster band) then Py_None is returned.  If it is != 0, then
  * the value is coerced into a long and returned.
  */
 %typemap(in,numinputs=0) (double *val, int*hasval) ( double tmpval, int tmphasval ) {
@@ -81,7 +81,7 @@
   $2 = &isvalid;
 }
 
-%typemap(argout) (double argout[6], int* isvalid) 
+%typemap(argout) (double argout[6], int* isvalid)
 {
    /* %typemap(argout) (double argout[6], int* isvalid)  */
   PyObject *r;
@@ -169,11 +169,7 @@
 %typemap(ret) OGRErr
 {
   /* %typemap(ret) OGRErr */
-  if (resultobj == Py_None ) {
-    Py_DECREF(resultobj);
-    resultobj = 0;
-  }
-  if (resultobj == 0) {
+  if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
     resultobj = PyInt_FromLong( $1 );
   }
 }
@@ -194,6 +190,7 @@ CreateTupleFromDoubleArray( double *first, unsigned int size ) {
 %typemap(in,numinputs=0) ( double argout[ANY]) (double argout[$dim0])
 {
   /* %typemap(in,numinputs=0) (double argout[ANY]) */
+  memset(argout, 0, sizeof(argout));
   $1 = argout;
 }
 %typemap(argout,fragment="t_output_helper,CreateTupleFromDoubleArray") ( double argout[ANY])
@@ -206,6 +203,7 @@ CreateTupleFromDoubleArray( double *first, unsigned int size ) {
 %typemap(in,numinputs=0) ( double *argout[ANY]) (double *argout)
 {
   /* %typemap(in,numinputs=0) (double *argout[ANY]) */
+  argout = NULL;
   $1 = &argout;
 }
 %typemap(argout,fragment="t_output_helper,CreateTupleFromDoubleArray") ( double *argout[ANY])
@@ -227,7 +225,7 @@ CreateTupleFromDoubleArray( double *first, unsigned int size ) {
     PyErr_SetString(PyExc_TypeError, "not a sequence");
     SWIG_fail;
   }
-  int seq_size = PySequence_Size($input);
+  Py_ssize_t seq_size = PySequence_Size($input);
   if ( seq_size != $dim0 ) {
     PyErr_SetString(PyExc_TypeError, "sequence must have length ##size");
     SWIG_fail;
@@ -256,7 +254,12 @@ CreateTupleFromDoubleArray( double *first, unsigned int size ) {
     PyErr_SetString(PyExc_TypeError, "not a sequence");
     SWIG_fail;
   }
-  $1 = PySequence_Size($input);
+  Py_ssize_t size = PySequence_Size($input);
+  if( size != (int)size ) {
+    PyErr_SetString(PyExc_TypeError, "too big sequence");
+    SWIG_fail;
+  }
+  $1 = (int)size;
   $2 = (int*) malloc($1*sizeof(int));
   for( int i = 0; i<$1; i++ ) {
     PyObject *o = PySequence_GetItem($input,i);
@@ -288,7 +291,12 @@ CreateTupleFromDoubleArray( double *first, unsigned int size ) {
     PyErr_SetString(PyExc_TypeError, "not a sequence");
     SWIG_fail;
   }
-  $1 = PySequence_Size($input);
+  Py_ssize_t size = PySequence_Size($input);
+  if( size != (int)size ) {
+    PyErr_SetString(PyExc_TypeError, "too big sequence");
+    SWIG_fail;
+  }
+  $1 = (int)size;
   $2 = (GIntBig*) malloc($1*sizeof(GIntBig));
   for( int i = 0; i<$1; i++ ) {
     PyObject *o = PySequence_GetItem($input,i);
@@ -322,7 +330,12 @@ CreateTupleFromDoubleArray( double *first, unsigned int size ) {
     PyErr_SetString(PyExc_TypeError, "not a sequence");
     SWIG_fail;
   }
-  $1 = PySequence_Size($input);
+  Py_ssize_t size = PySequence_Size($input);
+  if( size != (int)size ) {
+    PyErr_SetString(PyExc_TypeError, "too big sequence");
+    SWIG_fail;
+  }
+  $1 = (int)size;
   $2 = (GUIntBig*) malloc($1*sizeof(GUIntBig));
   for( int i = 0; i<$1; i++ ) {
     PyObject *o = PySequence_GetItem($input,i);
@@ -356,7 +369,12 @@ CreateTupleFromDoubleArray( double *first, unsigned int size ) {
     PyErr_SetString(PyExc_TypeError, "not a sequence");
     SWIG_fail;
   }
-  $1 = PySequence_Size($input);
+  Py_ssize_t size = PySequence_Size($input);
+  if( size != (int)size ) {
+    PyErr_SetString(PyExc_TypeError, "too big sequence");
+    SWIG_fail;
+  }
+  $1 = (int)size;
   $2 = (double*) malloc($1*sizeof(double));
   for( int i = 0; i<$1; i++ ) {
     PyObject *o = PySequence_GetItem($input,i);
@@ -701,8 +719,8 @@ CreateTupleFromDoubleArray( int *first, unsigned int size ) {
                                 (*$2)[i].dfGCPLine,
                                 (*$2)[i].pszInfo,
                                 (*$2)[i].pszId );
-	
-    PyTuple_SetItem(dict, i, 
+
+    PyTuple_SetItem(dict, i,
        SWIG_NewPointerObj((void*)o,SWIGTYPE_p_GDAL_GCP,1) );
   }
   Py_DECREF($result);
@@ -716,13 +734,18 @@ CreateTupleFromDoubleArray( int *first, unsigned int size ) {
     PyErr_SetString(PyExc_TypeError, "not a sequence");
     SWIG_fail;
   }
-  $1 = PySequence_Size($input);
+  Py_ssize_t size = PySequence_Size($input);
+  if( size != (int)size ) {
+    PyErr_SetString(PyExc_TypeError, "too big sequence");
+    SWIG_fail;
+  }
+  $1 = (int)size;
   tmpGCPList = (GDAL_GCP*) malloc($1*sizeof(GDAL_GCP));
   $2 = tmpGCPList;
   for( int i = 0; i<$1; i++ ) {
     PyObject *o = PySequence_GetItem($input,i);
     GDAL_GCP *item = 0;
-    SWIG_ConvertPtr( o, (void**)&item, SWIGTYPE_p_GDAL_GCP, SWIG_POINTER_EXCEPTION | 0 );
+    CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( o, (void**)&item, SWIGTYPE_p_GDAL_GCP, SWIG_POINTER_EXCEPTION | 0 ));
     if ( ! item ) {
       Py_DECREF(o);
       SWIG_fail;
@@ -760,7 +783,7 @@ CreateTupleFromDoubleArray( int *first, unsigned int size ) {
     PyErr_SetString(PyExc_TypeError, "not a sequence");
     SWIG_fail;
   }
-   int size = PySequence_Size($input);
+   Py_ssize_t size = PySequence_Size($input);
    if ( size > 4 ) {
      PyErr_SetString(PyExc_TypeError, "ColorEntry sequence too long");
      SWIG_fail;
@@ -823,8 +846,12 @@ CreateTupleFromDoubleArray( int *first, unsigned int size ) {
   /* %typemap(in) char **dict */
   $1 = NULL;
   if ( PySequence_Check( $input ) ) {
-    int size = PySequence_Size($input);
-    for (int i = 0; i < size; i++) {
+    Py_ssize_t size = PySequence_Size($input);
+    if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+    }
+    for (int i = 0; i < (int)size; i++) {
       PyObject* pyObj = PySequence_GetItem($input,i);
       int bFreeStr;
       char* pszStr = GDALPythonObjectToCStr(pyObj, &bFreeStr);
@@ -840,16 +867,16 @@ CreateTupleFromDoubleArray( int *first, unsigned int size ) {
   }
   else if ( PyMapping_Check( $input ) ) {
     /* We need to use the dictionary form. */
-    int size = PyMapping_Length( $input );
-    if ( size > 0 ) {
+    Py_ssize_t size = PyMapping_Length( $input );
+    if ( size > 0 && size == (int)size) {
       PyObject *item_list = PyMapping_Items( $input );
-      for( int i=0; i<size; i++ ) {
+      for( int i=0; i<(int)size; i++ ) {
         PyObject *it = PySequence_GetItem( item_list, i );
 
         PyObject *k, *v;
         if ( ! PyArg_ParseTuple( it, "OO", &k, &v ) ) {
           Py_DECREF(it);
-          PyErr_SetString(PyExc_TypeError,"dictionnaire must contain tuples of strings");
+          PyErr_SetString(PyExc_TypeError,"Dictionary must contain tuples of strings");
           SWIG_fail;
         }
 
@@ -861,7 +888,7 @@ CreateTupleFromDoubleArray( int *first, unsigned int size ) {
             GDALPythonFreeCStr(pszK, bFreeK);
             GDALPythonFreeCStr(pszV, bFreeV);
             Py_DECREF(it);
-            PyErr_SetString(PyExc_TypeError,"dictionnaire must contain tuples of strings");
+            PyErr_SetString(PyExc_TypeError,"Dictionary must contain tuples of strings");
             SWIG_fail;
         }
          $1 = CSLAddNameValue( $1, pszK, pszV );
@@ -900,8 +927,12 @@ CreateTupleFromDoubleArray( int *first, unsigned int size ) {
     SWIG_fail;
   }
 
-  int size = PySequence_Size($input);
-  for (int i = 0; i < size; i++) {
+  Py_ssize_t size = PySequence_Size($input);
+  if( size != (int)size ) {
+    PyErr_SetString(PyExc_TypeError, "too big sequence");
+    SWIG_fail;
+  }
+  for (int i = 0; i < (int)size; i++) {
     PyObject* pyObj = PySequence_GetItem($input,i);
     if (PyUnicode_Check(pyObj))
     {
@@ -1010,7 +1041,7 @@ CreateTupleFromDoubleArray( int *first, unsigned int size ) {
 {
   /* %typemap(argout) (char **argout) */
   PyObject *o;
-  if ( $1 != NULL && *$1 != NULL) {
+  if ( ReturnSame($1) != NULL && *$1 != NULL ) {
     o = GDALPythonObjectFromCStr( *$1 );
   }
   else {
@@ -1072,8 +1103,8 @@ OPTIONAL_POD(GIntBig,L);
     PyErr_SetString( PyExc_RuntimeError, "Unable to format argument as string");
     SWIG_fail;
   }
- 
-  $1 = GDALPythonObjectToCStr(str, &bToFree); 
+
+  $1 = GDALPythonObjectToCStr(str, &bToFree);
 }
 %typemap(freearg)(tostring argin)
 {
@@ -1086,26 +1117,6 @@ OPTIONAL_POD(GIntBig,L);
 }
 
 /*
- * Typemap for CPLErr.
- * This typemap will use the wrapper C-variable
- * int UseExceptions to determine proper behavour for
- * CPLErr return codes.
- * If UseExceptions ==0, then return the rc.
- * If UseExceptions ==1, then if rc >= CE_Failure, raise an exception.
- */
-%typemap(ret) CPLErr
-{
-  /* %typemap(ret) CPLErr */
-  if ( bUseExceptions == 0 ) {
-    /* We're not using exceptions.  And no error has occurred */
-    if ( $result == 0 ) {
-      /* No other return values set so return ErrorCode */
-      $result = PyInt_FromLong($1);
-    }
-  }
-}
-
-/*
  * Typemaps for minixml:  CPLXMLNode* input, CPLXMLNode *ret
  */
 
@@ -1116,7 +1127,7 @@ OPTIONAL_POD(GIntBig,L);
 static CPLXMLNode *PyListToXMLTree( PyObject *pyList )
 
 {
-    int      nChildCount = 0, iChild, nType;
+    int      nChildCount = 0, iChild, nType = 0;
     CPLXMLNode *psThisNode;
     CPLXMLNode *psChild;
     char       *pszText = NULL;
@@ -1128,8 +1139,8 @@ static CPLXMLNode *PyListToXMLTree( PyObject *pyList )
         return NULL;
     }
 
-    PyArg_Parse( PyList_GET_ITEM(pyList,0), "i", &nType );
-    PyArg_Parse( PyList_GET_ITEM(pyList,1), "s", &pszText );
+    CPL_IGNORE_RET_VAL(PyArg_Parse( PyList_GET_ITEM(pyList,0), "i", &nType ));
+    CPL_IGNORE_RET_VAL(PyArg_Parse( PyList_GET_ITEM(pyList,1), "s", &pszText ));
 
     /* Detect "pseudo" root */
     if (nType == CXT_Element && pszText != NULL && strlen(pszText) == 0 && nChildCount == 2)
@@ -1142,8 +1153,8 @@ static CPLXMLNode *PyListToXMLTree( PyObject *pyList )
         }
         int nTypeFirst = 0;
         char* pszTextFirst = NULL;
-        PyArg_Parse( PyList_GET_ITEM(pyFirst,0), "i", &nTypeFirst );
-        PyArg_Parse( PyList_GET_ITEM(pyFirst,1), "s", &pszTextFirst );
+        CPL_IGNORE_RET_VAL(PyArg_Parse( PyList_GET_ITEM(pyFirst,0), "i", &nTypeFirst ));
+        CPL_IGNORE_RET_VAL(PyArg_Parse( PyList_GET_ITEM(pyFirst,1), "s", &pszTextFirst ));
         if (nTypeFirst == CXT_Element && pszTextFirst != NULL && pszTextFirst[0] == '?')
         {
             psThisNode = PyListToXMLTree( PyList_GET_ITEM(pyList,2) );
@@ -1173,7 +1184,7 @@ static CPLXMLNode *PyListToXMLTree( PyObject *pyList )
 %typemap(freearg) (CPLXMLNode *xmlnode)
 {
   /* %typemap(freearg) (CPLXMLNode *xmlnode) */
-  if ( $1 ) CPLDestroyXMLNode( $1 );
+  CPLDestroyXMLNode( $1 );
 }
 
 %fragment("XMLTreeToPyList","header") %{
@@ -1189,8 +1200,8 @@ static PyObject *XMLTreeToPyList( CPLXMLNode *psTree )
     if( psTree == NULL )
         return Py_None;
 
-    for( psChild = psTree->psChild; 
-         psChild != NULL; 
+    for( psChild = psTree->psChild;
+         psChild != NULL;
          psChild = psChild->psNext )
         nChildCount++;
 
@@ -1199,14 +1210,14 @@ static PyObject *XMLTreeToPyList( CPLXMLNode *psTree )
     PyList_SetItem( pyList, 0, Py_BuildValue( "i", (int) psTree->eType ) );
     PyList_SetItem( pyList, 1, Py_BuildValue( "s", psTree->pszValue ) );
 
-    for( psChild = psTree->psChild, iChild = 2; 
-         psChild != NULL; 
+    for( psChild = psTree->psChild, iChild = 2;
+         psChild != NULL;
          psChild = psChild->psNext, iChild++ )
     {
         PyList_SetItem( pyList, iChild, XMLTreeToPyList( psChild ) );
     }
 
-    return pyList; 
+    return pyList;
 }
 %}
 
@@ -1276,7 +1287,7 @@ static PyObject *XMLTreeToPyList( CPLXMLNode *psTree )
 
 /*  This typemap takes the $input'ed  PyObject* and hangs it on the     */
 /*  struct's callback data .                                            */
-%typemap(in) (void* callback_data=NULL) 
+%typemap(in) (void* callback_data=NULL)
 {
     /* %typemap(in) ( void* callback_data=NULL)  */
         psProgressInfo->psPyCallbackData = $input ;
@@ -1289,45 +1300,45 @@ static PyObject *XMLTreeToPyList( CPLXMLNode *psTree )
 /*  otherwise, setup the psProgressInfo's callback to be our PyObject*  */
 /*  and set our callback function to be PyProgressProxy, which is       */
 /*  defined in gdal_python.i                                            */
-%typemap(in) ( GDALProgressFunc callback = NULL) 
+%typemap(in) ( GDALProgressFunc callback = NULL)
 {
     /* %typemap(in) (GDALProgressFunc callback = NULL) */
     /* callback_func typemap */
     if ($input && $input != Py_None ) {
         void* cbfunction = NULL;
-        SWIG_ConvertPtr( $input, 
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( $input,
                          (void**)&cbfunction,
                          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-                         SWIG_POINTER_EXCEPTION | 0 );
+                         SWIG_POINTER_EXCEPTION | 0 ));
 
         if ( cbfunction == GDALTermProgress ) {
             $1 = GDALTermProgress;
         } else {
             if (!PyCallable_Check($input)) {
-                PyErr_SetString( PyExc_RuntimeError, 
+                PyErr_SetString( PyExc_RuntimeError,
                                  "Object given is not a Python function" );
                 SWIG_fail;
             }
             psProgressInfo->psPyCallback = $input;
             $1 = PyProgressProxy;
         }
-        
+
     }
 
 }
 
 /*  clean up our global (to the wrapper function) psProgressInfo        */
 /*  struct now that we're done with it.                                 */
-%typemap(freearg) (void* callback_data=NULL) 
+%typemap(freearg) (void* callback_data=NULL)
 {
     /* %typemap(freearg) ( void* callback_data=NULL)  */
-  
+
         CPLFree(psProgressInfo);
 
 }
 
 
-%typemap(in) ( CPLErrorHandler pfnErrorHandler = NULL, void* user_data = NULL ) 
+%typemap(in) ( CPLErrorHandler pfnErrorHandler = NULL, void* user_data = NULL )
 {
     /* %typemap(in) (CPLErrorHandler pfnErrorHandler = NULL, void* user_data = NULL) */
     int alloc = 0;
@@ -1352,7 +1363,7 @@ static PyObject *XMLTreeToPyList( CPLXMLNode *psTree )
     }
     else if (!PyCallable_Check($input))
     {
-        PyErr_SetString( PyExc_RuntimeError, 
+        PyErr_SetString( PyExc_RuntimeError,
                          "Object given is not a String or a Python function" );
         SWIG_fail;
     }
@@ -1365,7 +1376,7 @@ static PyObject *XMLTreeToPyList( CPLXMLNode *psTree )
 }
 
 
-%typemap(arginit) ( GUInt32 ) 
+%typemap(arginit) ( GUInt32 )
 {
     /* %typemap(out) ( GUInt32 )  */
 
@@ -1373,7 +1384,7 @@ static PyObject *XMLTreeToPyList( CPLXMLNode *psTree )
 
 }
 
-%typemap(out) ( GUInt32 ) 
+%typemap(out) ( GUInt32 )
 {
     /* %typemap(out) ( GUInt32 )  */
 
@@ -1381,7 +1392,7 @@ static PyObject *XMLTreeToPyList( CPLXMLNode *psTree )
 
 }
 
-%typemap(in) ( GUInt32 ) 
+%typemap(in) ( GUInt32 )
 {
     /* %typemap(in) ( GUInt32 )  */
 
@@ -1400,9 +1411,14 @@ static PyObject *XMLTreeToPyList( CPLXMLNode *psTree )
     PyErr_SetString(PyExc_TypeError, "not a sequence");
     SWIG_fail;
   }
-  $1 = PySequence_Size($input);
+  Py_ssize_t size = PySequence_Size($input);
+  if( size != (int)size ) {
+    PyErr_SetString(PyExc_TypeError, "too big sequence");
+    SWIG_fail;
+  }
+  $1 = (int)size;
   $2 = (type**) CPLMalloc($1*sizeof(type*));
-  
+
   for( int i = 0; i<$1; i++ ) {
 
       PyObject *o = PySequence_GetItem($input,i);
@@ -1431,13 +1447,14 @@ static PyObject *XMLTreeToPyList( CPLXMLNode *psTree )
 %enddef
 
 OBJECT_LIST_INPUT(GDALRasterBandShadow);
+OBJECT_LIST_INPUT(GDALDatasetShadow);
 
 /* ***************************************************************************
  *                       GetHistogram()
  * Python is somewhat special in that we don't want the caller
  * to pass in the histogram array to populate.  Instead we allocate
- * it internally, call the C level, and then turn the result into 
- * a list object. 
+ * it internally, call the C level, and then turn the result into
+ * a list object.
  */
 
 %typemap(arginit) (int buckets, GUIntBig* panHistogram)
@@ -1450,7 +1467,7 @@ OBJECT_LIST_INPUT(GDALRasterBandShadow);
 {
   /* %typemap(in) int buckets, GUIntBig* panHistogram -> list */
   int requested_buckets = 0;
-  SWIG_AsVal_int($input, &requested_buckets);
+  CPL_IGNORE_RET_VAL(SWIG_AsVal_int($input, &requested_buckets));
   if( requested_buckets != $1 )
   {
     $1 = requested_buckets;
@@ -1480,6 +1497,7 @@ OBJECT_LIST_INPUT(GDALRasterBandShadow);
 {
   /* %typemap(out) int buckets, GUIntBig* panHistogram -> list */
   GUIntBig *integerarray = $2;
+  Py_DECREF( $result );
   if ( integerarray == NULL ) {
     $result = Py_None;
     Py_INCREF( $result );
@@ -1505,9 +1523,9 @@ OBJECT_LIST_INPUT(GDALRasterBandShadow);
 
 %typemap(arginit, noblock=1) (double *min_ret, double *max_ret, int *buckets_ret, GUIntBig **ppanHistogram)
 {
-   double min_val, max_val;
-   int buckets_val;
-   GUIntBig *panHistogram;
+   double min_val = 0.0, max_val = 0.0;
+   int buckets_val = 0;
+   GUIntBig *panHistogram = NULL;
 
    $1 = &min_val;
    $2 = &max_val;
@@ -1521,7 +1539,7 @@ OBJECT_LIST_INPUT(GDALRasterBandShadow);
   PyObject *psList = NULL;
 
   Py_XDECREF($result);
-  
+
   if (panHistogram)
   {
       psList = PyList_New(buckets_val);
@@ -1639,7 +1657,12 @@ DecomposeSequenceOfCoordinates( PyObject *seq, int nCount, double *x, double *y,
     SWIG_fail;
   }
 
-  $1 = PySequence_Size($input);
+  Py_ssize_t size = PySequence_Size($input);
+  if( size != (int)size ) {
+    PyErr_SetString(PyExc_TypeError, "too big sequence");
+    SWIG_fail;
+  }
+  $1 = (int)size;
   $2 = (double*) VSIMalloc($1*sizeof(double));
   $3 = (double*) VSIMalloc($1*sizeof(double));
   $4 = (double*) VSIMalloc($1*sizeof(double));
@@ -1690,7 +1713,12 @@ DecomposeSequenceOfCoordinates( PyObject *seq, int nCount, double *x, double *y,
     SWIG_fail;
   }
 
-  $1 = PySequence_Size($input);
+  Py_ssize_t size = PySequence_Size($input);
+  if( size != (int)size ) {
+    PyErr_SetString(PyExc_TypeError, "too big sequence");
+    SWIG_fail;
+  }
+  $1 = (int)size;
   $2 = (double*) VSIMalloc($1*sizeof(double));
   $3 = (double*) VSIMalloc($1*sizeof(double));
   $4 = (double*) VSIMalloc($1*sizeof(double));
@@ -1825,7 +1853,7 @@ DecomposeSequenceOfCoordinates( PyObject *seq, int nCount, double *x, double *y,
 }
 %typemap(argout) (void** pptr, size_t* pnsize, GDALDataType* pdatatype, int* preadonly)
 {
-%#if PY_VERSION_HEX >= 0x02070000 
+%#if PY_VERSION_HEX >= 0x02070000
   /* %typemap(argout) (void** pptr, size_t* pnsize, GDALDataType* pdatatype, int* preadonly)*/
   Py_buffer *buf=(Py_buffer*)malloc(sizeof(Py_buffer));
   if (PyBuffer_FillInfo(buf,  obj0,  *($1), *($2), *($4), PyBUF_ND)) {
@@ -1833,47 +1861,47 @@ DecomposeSequenceOfCoordinates( PyObject *seq, int nCount, double *x, double *y,
   }
   if( *($3) == GDT_Byte )
   {
-    buf->format = "B";
+    buf->format = (char*) "B";
     buf->itemsize = 1;
   }
   else if( *($3) == GDT_Int16 )
   {
-    buf->format = "h";
+    buf->format = (char*) "h";
     buf->itemsize = 2;
   }
   else if( *($3) == GDT_UInt16 )
   {
-    buf->format = "H";
+    buf->format = (char*) "H";
     buf->itemsize = 2;
   }
   else if( *($3) == GDT_Int32 )
   {
-    buf->format = "i";
+    buf->format = (char*) "i";
     buf->itemsize = 4;
   }
   else if( *($3) == GDT_UInt32 )
   {
-    buf->format = "I";
+    buf->format = (char*) "I";
     buf->itemsize = 4;
   }
   else if( *($3) == GDT_Float32 )
   {
-    buf->format = "f";
+    buf->format = (char*) "f";
     buf->itemsize = 4;
   }
   else if( *($3) == GDT_Float64 )
   {
-    buf->format = "F";
+    buf->format = (char*) "F";
     buf->itemsize = 8;
   }
   else
   {
-    buf->format = "B";
+    buf->format = (char*) "B";
     buf->itemsize = 1;
   }
+  Py_DECREF($result);
   $result = PyMemoryView_FromBuffer(buf);
 %#else
   PyErr_SetString( PyExc_RuntimeError, "needs Python 2.7 or later" );
-  SWIG_fail;
 %#endif
 }
diff --git a/swig/include/ruby/gdal_ruby.i b/swig/include/ruby/gdal_ruby.i
index f4fd5bf..9964189 100644
--- a/swig/include/ruby/gdal_ruby.i
+++ b/swig/include/ruby/gdal_ruby.i
@@ -1,5 +1,5 @@
 /*
- * $Id: gdal_ruby.i 28039 2014-11-30 18:24:59Z rouault $
+ * $Id: gdal_ruby.i 33721 2016-03-15 00:56:01Z goatbar $
  *
  * ruby specific code for gdal bindings.
  */
@@ -64,8 +64,8 @@ static VALUE XMLTreeToRubyArray( CPLXMLNode *psTree )
     int      nChildCount = 0, iChild;
     CPLXMLNode *psChild;
 
-    for( psChild = psTree->psChild; 
-         psChild != NULL; 
+    for( psChild = psTree->psChild;
+         psChild != NULL;
          psChild = psChild->psNext )
         nChildCount++;
 
@@ -74,14 +74,14 @@ static VALUE XMLTreeToRubyArray( CPLXMLNode *psTree )
 	 rb_ary_store(rubyArray, 0, INT2NUM((int) psTree->eType));
 	 rb_ary_store(rubyArray, 1, rb_str_new2(psTree->pszValue));
 
-    for( psChild = psTree->psChild, iChild = 2; 
-         psChild != NULL; 
+    for( psChild = psTree->psChild, iChild = 2;
+         psChild != NULL;
          psChild = psChild->psNext, iChild++ )
     {
         rb_ary_store(rubyArray, iChild, XMLTreeToRubyArray(psChild));
     }
 
-    return rubyArray; 
+    return rubyArray;
 }
 %}
 
@@ -96,7 +96,7 @@ static VALUE XMLTreeToRubyArray( CPLXMLNode *psTree )
     def serialize(self,with_Z=0):
         base = [CXT_Element,'GCP']
         base.append([CXT_Attribute,'Id',[CXT_Text,self.Id]])
-        pixval = '%0.15E' % self.GCPPixel       
+        pixval = '%0.15E' % self.GCPPixel
         lineval = '%0.15E' % self.GCPLine
         xval = '%0.15E' % self.GCPX
         yval = '%0.15E' % self.GCPY
@@ -106,9 +106,9 @@ static VALUE XMLTreeToRubyArray( CPLXMLNode *psTree )
         base.append([CXT_Attribute,'X',[CXT_Text,xval]])
         base.append([CXT_Attribute,'Y',[CXT_Text,yval]])
         if with_Z:
-            base.append([CXT_Attribute,'Z',[CXT_Text,zval]])        
+            base.append([CXT_Attribute,'Z',[CXT_Text,zval]])
         return base
-} 
+}
 }
 
 %extend GDALRasterBandShadow {
@@ -120,7 +120,7 @@ static VALUE XMLTreeToRubyArray( CPLXMLNode *psTree )
       return gdalnumeric.BandReadAsArray( self, xoff, yoff,
                                           win_xsize, win_ysize,
                                           buf_xsize, buf_ysize, buf_obj )
-    
+
   def WriteArray(self, array, xoff=0, yoff=0):
       import gdalnumeric
 
diff --git a/swig/include/ruby/ogr_ruby.i b/swig/include/ruby/ogr_ruby.i
index 3a69c23..293bf66 100644
--- a/swig/include/ruby/ogr_ruby.i
+++ b/swig/include/ruby/ogr_ruby.i
@@ -1,5 +1,5 @@
 /*
- * $Id: ogr_ruby.i 28039 2014-11-30 18:24:59Z rouault $
+ * $Id: ogr_ruby.i 33721 2016-03-15 00:56:01Z goatbar $
  *
  * ruby specific code for ogr bindings.
  */
@@ -109,7 +109,7 @@
  		{
 			/* Convert the pointer to a Ruby object.  Note we set the flag
 		   to one manually to show this is a new object */
-			VALUE object = SWIG_NewPointerObj((void *) feature, $descriptor(OGRFeatureShadow *), SWIG_POINTER_OWN);			
+			VALUE object = SWIG_NewPointerObj((void *) feature, $descriptor(OGRFeatureShadow *), SWIG_POINTER_OWN);
 
 			/* Now invoke the block specified for this method. */
 			rb_yield(object);
@@ -134,9 +134,9 @@
 			default:
 				SWIG_exception(SWIG_TypeError, "Value must be a string or integer.");
 		}
-		
+
 		int count = OGR_F_GetFieldCount(self);
-		
+
 		if (index < 0 || index > count) {
 			SWIG_exception(SWIG_IndexError, "Illegal field requested.");
 		}
@@ -146,7 +146,7 @@
 	  	result = Qnil;
 	  	return result;
 	  }
-	  
+
 	  // get field type
     OGRFieldType field_type = (OGRFieldType) OGR_Fld_GetType(OGR_F_GetFieldDefnRef( self, index));
 
@@ -160,9 +160,9 @@
 			case OFTIntegerList: {
 				int len = 0;
 				const int* list = OGR_F_GetFieldAsIntegerList(self, index, &len);
-				
+
 				result = rb_ary_new2(len);
-				
+
 		    for ( int i = 0; i < len; ++i, ++list ) {
 					VALUE item = INT2NUM(*list);
 		      rb_ary_store(result, item, i);
@@ -179,9 +179,9 @@
 			case OFTRealList: {
 				int len = 0;
 				const double* list = OGR_F_GetFieldAsDoubleList(self, index, &len);
-				
+
 				result = rb_ary_new2(len);
-				
+
 		    for ( int i = 0; i < len; ++i, ++list ) {
 					VALUE item = rb_float_new(*list);
 		      rb_ary_store(result, item, i);
@@ -198,9 +198,9 @@
 			case OFTStringList:
 /*				int len3 = 0;
 				const char** string_list = OGR_F_GetFieldAsStringList(self, index, &len);
-				
+
 				result = rb_ary_new2(len3);
-				
+
 		    for ( int i = 0; i < len; ++i, ++string_list ) {
 					VALUE item = rb_str_new2(*string_list);
 		      rb_ary_store(result, item, i);
@@ -210,9 +210,9 @@
 			default:
 				SWIG_exception(SWIG_TypeError, "Unsupported field type.");
 		}
-	
-		return result;		
-	}        
+
+		return result;
+	}
 }
 
 
diff --git a/swig/include/ruby/osr_ruby.i b/swig/include/ruby/osr_ruby.i
index 694624f..2f3b256 100644
--- a/swig/include/ruby/osr_ruby.i
+++ b/swig/include/ruby/osr_ruby.i
@@ -6,7 +6,7 @@ py_OPTGetProjectionMethods(PyObject *self, PyObject *args) {
     PyObject *py_MList;
     char     **papszMethods;
     int      iMethod;
-    
+
     self = self;
     args = args;
 
@@ -20,7 +20,7 @@ py_OPTGetProjectionMethods(PyObject *self, PyObject *args) {
 	PyObject *py_PList;
 	int       iParam;
 
-	papszParameters = OPTGetParameterList( papszMethods[iMethod], 
+	papszParameters = OPTGetParameterList( papszMethods[iMethod],
 					       &pszUserMethodName );
         if( papszParameters == NULL )
             return NULL;
@@ -32,23 +32,23 @@ py_OPTGetProjectionMethods(PyObject *self, PyObject *args) {
 	    char    *pszUserParamName;
             double  dfDefault;
 
-	    OPTGetParameterInfo( papszMethods[iMethod], 
-				 papszParameters[iParam], 
-				 &pszUserParamName, 
+	    OPTGetParameterInfo( papszMethods[iMethod],
+				 papszParameters[iParam],
+				 &pszUserParamName,
 				 &pszType, &dfDefault );
-	    PyList_SetItem(py_PList, iParam, 
-			   Py_BuildValue("(sssd)", 
-					 papszParameters[iParam], 
-					 pszUserParamName, 
+	    PyList_SetItem(py_PList, iParam,
+			   Py_BuildValue("(sssd)",
+					 papszParameters[iParam],
+					 pszUserParamName,
                                          pszType, dfDefault ));
 	}
-	
+
 	CSLDestroy( papszParameters );
 
-	PyList_SetItem(py_MList, iMethod, 
-		       Py_BuildValue("(ssO)", 
-		                     papszMethods[iMethod], 
-				     pszUserMethodName, 
+	PyList_SetItem(py_MList, iMethod,
+		       Py_BuildValue("(ssO)",
+		                     papszMethods[iMethod],
+				     pszUserMethodName,
 		                     py_PList));
     }
 
diff --git a/swig/include/ruby/typemaps_ruby.i b/swig/include/ruby/typemaps_ruby.i
index ec1ec33..d18dd69 100644
--- a/swig/include/ruby/typemaps_ruby.i
+++ b/swig/include/ruby/typemaps_ruby.i
@@ -1,6 +1,6 @@
 
 /******************************************************************************
- * $Id: typemaps_ruby.i 28039 2014-11-30 18:24:59Z rouault $
+ * $Id: typemaps_ruby.i 33721 2016-03-15 00:56:01Z goatbar $
  *
  * Name:     typemaps_ruby.i
  * Project:  GDAL Ruby Interface
@@ -47,7 +47,8 @@
  * Added note saying that SWIG 1.3.26 or higher is required because the bindings need the SWIGTYPE *DISOWN  typemap.
  *
  * Revision 1.3  2005/08/21 23:52:08  cfis
- * The Layer each method was not correctly setting the owernship flag for returned objects.  This has now been fixed and commented.
+ * The Layer each method was not correctly setting the ownership flag
+ * for returned objects.  This has now been fixed and commented.
  *
  * Revision 1.2  2005/08/20 20:50:13  cfis
  * Added GetLayer method that maps to either GetLayerByName or GetLayerByIndex.  Also commented out Open and OpenShared as DataSouce class static methods.
@@ -59,7 +60,7 @@
 
 /* !NOTE! - The Ruby bindings require SWIG-1.3.26 or above.  Earlier versions
    do not work because they did not include support for the WWIGTYPE *DISOWN
-	typemap which is crucial for supporting the AddGeometryDirectly and 
+	typemap which is crucial for supporting the AddGeometryDirectly and
 	SetGeometryDirectly methods.
 
 	These typemaps  were ported from typemaps_python.i.  For more information
@@ -76,7 +77,7 @@
  * double *val, int *hasval, is a special contrived typemap used for
  * the RasterBand GetNoDataValue, GetMinimum, GetMaximum, GetOffset, GetScale methods.
  * In the Ruby bindings, the variable hasval is tested.  If it is 0 (is, the value
- * is not set in the raster band) then Py_None is returned.  If is is != 0, then
+ * is not set in the raster band) then Py_None is returned.  If it is != 0, then
  * the value is coerced into a long and returned.
  */
 %typemap(in,numinputs=0) (double *val, int *hasval) (double tmpval, int tmphasval) {
@@ -88,14 +89,14 @@
 %typemap(argout) (double *val, int *hasval) {
   /* %typemap(argout) (double *val, int *hasval) */
 	VALUE argOut;
-	
+
   if ( !*$2 ) {
     argOut = Qnil;
   }
   else {
     argOut = rb_float_new(*$1);
   }
-  
+
   $result = SWIG_AppendOutput($result, argOut);
 }
 
@@ -148,7 +149,7 @@
 
   /* Get the length */
   int seq_size = RARRAY_LEN($input);
-  
+
   if ( seq_size != $dim0 ) {
     rb_raise(rb_eRangeError, "sequence must have length %i.", seq_size);
   }
@@ -156,11 +157,11 @@
   for( int i = 0; i<$dim0; i++ ) {
     /* Get the Ruby Object */
     VALUE item = rb_ary_entry($input,i);
-    
+
     /* Convert to double and store in array*/
     temp[i] = NUM2DBL(item);
   }
-  
+
   /* Set argument $1 equal to the temp array */
 	$1 = temp;
 }
@@ -182,9 +183,9 @@
     VALUE value = rb_float_new(($1)[i]);
     rb_ary_push(outArr, value);
   }
-  
+
   /* Add the output to the result */
-  $result = SWIG_AppendOutput($result, outArr);	
+  $result = SWIG_AppendOutput($result, outArr);
 }
 
 %typemap(in,numinputs=0) (double *argout[ANY]) (double *argout)
@@ -205,9 +206,9 @@
     VALUE value = rb_float_new((*$1)[i]);
     rb_ary_push(outArr, value);
   }
-  
+
   /* Add the output to the result */
-  $result = SWIG_AppendOutput($result, outArr);	
+  $result = SWIG_AppendOutput($result, outArr);
 }
 
 %typemap(freearg) (double *argout[ANY])
@@ -226,14 +227,14 @@
 
   /* Get the length */
   $1 = RARRAY_LEN($input);
-  
+
   /* Allocate space for the C array. */
   $2 = (int*) malloc($1*sizeof(int));
-  
+
   for( int i = 0; i<$1; i++ ) {
     /* Get the Ruby Object */
     VALUE item = rb_ary_entry($input,i);
-    /* Conver to an integer */
+    /* Convert to an integer */
     $2[i] = NUM2INT(item);
   }
 }
@@ -302,8 +303,8 @@
                                 (*$2)[i].dfGCPLine,
                                 (*$2)[i].pszInfo,
                                 (*$2)[i].pszId );
-	
-	 rb_ary_store($result, i, 
+
+	 rb_ary_store($result, i,
 					  SWIG_NewPointerObj((void*)o, SWIGTYPE_p_GDAL_GCP,1));
   }*/
 }
@@ -382,24 +383,24 @@
   /* %typemap(in) char **dict */
 
   $1 = NULL;
-  
+
   /* is the provided object an array or a hash? */
   if ( TYPE($input) == T_ARRAY) {
     /* get the size of the array */
     int size = RARRAY_LEN($input);
-    
+
     for (int i = 0; i < size; i++) {
       /* get the ruby object */
       VALUE value = rb_ary_entry($input, i);
-      
-      /* Convert the value to a string via ruby duck typing 
+
+      /* Convert the value to a string via ruby duck typing
        * (i.e., the object might not actually be a string)
        */
       char *pszItem = StringValuePtr(value);
       $1 = CSLAddString( $1, pszItem );
     }
   }
-  
+
   else if ( TYPE($input) == T_HASH) {
     /* This is a hash - get the size by calling via the ruby method */
     int size = NUM2INT(rb_funcall($input, rb_intern("size"), 0, NULL));
@@ -412,13 +413,13 @@
       	/* Get the key and value as ruby objects */
         VALUE key = rb_ary_entry(keys_arr, i);
         VALUE value = rb_hash_aref($input, key);
-		
-        /* Convert the key and value to strings via ruby duck typing 
+
+        /* Convert the key and value to strings via ruby duck typing
          * (i.e., the objects might not actually be strings)
          */
        char *nm = StringValuePtr(key);
        char *val = StringValuePtr(value);
-		
+
        /* Add the value */
        $1 = CSLAddNameValue( $1, nm, val );
       }
@@ -554,7 +555,7 @@
   else {
     outArg = Qnil;
   }
-  
+
   $result = SWIG_AppendOutput($result, outArg);
 }
 
@@ -669,7 +670,7 @@
 %apply char* {tostring argin}
 %apply int* {int* optional_int};
 
-%typemap(in) GDALDataType, CPLErr, GDALPaletteInterp, GDALAccess, 
+%typemap(in) GDALDataType, CPLErr, GDALPaletteInterp, GDALAccess,
 	GDALResampleAlg, GDALColorInterp, OGRwkbGeometryType, OGRFieldType,
 	OGRJustification, OGRwkbByteOrder
 {
@@ -684,7 +685,7 @@
 		If the parent goes out of scope it will free the child, invalidating
 		the scripting language object that represents the child.  To prevent
 		that create a reference from the child to the parent, thereby telling
-		the garabage collector not to GC the parent.*/
+		the garbage collector not to GC the parent. */
 
 	$result = SWIG_NewPointerObj((void *) $1, $1_descriptor,$owner);
 	rb_iv_set($result, "swig_parent_reference", self);
@@ -702,17 +703,17 @@
 /* -----------  GByte --------------- */
 /* Tread byte arrays as char arrays */
 
-%typemap(in,numinputs=1,fragment="SWIG_AsCharPtrAndSize") (int nBytes, const GByte *pabyData) 
+%typemap(in,numinputs=1,fragment="SWIG_AsCharPtrAndSize") (int nBytes, const GByte *pabyData)
   (int res, GByte *buf = 0, size_t size = 0, int alloc = 0)  {
 
 	/*%typemap(in,numinputs=1,fragment="SWIG_AsCharPtrAndSize") (int nBytes, const GByte *pabyData) */
-  
+
   res = SWIG_AsCharPtrAndSize($input, (char**)&buf, &size, &alloc);
   if (!SWIG_IsOK(res)) {
     %argument_fail(res, "(GByte*, int)", $symname, $argnum);
   }
-  $1 = ($1_ltype) size - 1;				       
-  $2 = ($2_ltype) buf;					       
+  $1 = ($1_ltype) size - 1;
+  $2 = ($2_ltype) buf;
 }
 
 %typemap(freearg) (int nBytes, const GByte *pabyData) {
@@ -723,7 +724,7 @@
 
 %typemap(in,numinputs=1,fragment="SWIG_AsCharPtrAndSize") (const char *pszHex, int *pnBytes)
   (int res, char *buf = 0, int size = 0, int alloc = 0)  {
-	
+
 	/*% typemap(in,numinputs=1,fragment="SWIG_AsCharPtrAndSize") (const char *pszHex, int *pnBytes) */
   $2 = &size;
   res = SWIG_AsCharPtr($input, &buf, &alloc);
@@ -731,9 +732,9 @@
     %argument_fail(res,"$type",$symname, $argnum);
   }
   $1 = buf;
-}    
+}
+
 
-  
 %typemap(argout) (const char *pszHex, int *pnBytes) {
 	/* %typemap(argout) (const char *pszHex, int *pnBytes) */
   $result = SWIG_FromCharPtrAndSize((char*)result, (size_t)*$2);
@@ -742,6 +743,6 @@
 
 %typemap(out) GByte*  {
 	/* %typemap(out) GByte* */
-	
+
 	/* Stops insertion of default type map. */
-}
\ No newline at end of file
+}
diff --git a/swig/java/GNUmakefile b/swig/java/GNUmakefile
index 28a7573..c1ccb5d 100644
--- a/swig/java/GNUmakefile
+++ b/swig/java/GNUmakefile
@@ -31,10 +31,10 @@ makedir:
 	mkdir -p org/gdal/gdalconst
 	mkdir -p org/gdal/ogr
 	mkdir -p org/gdal/osr
+	mkdir -p org/gdal/gnm
 
-
-JAVA_MODULES = libgdaljni.$(SO_EXT) libogrjni.$(SO_EXT) libgdalconstjni.$(SO_EXT) libosrjni.$(SO_EXT)
-JAVA_OBJECTS = gdalconst_wrap.$(OBJ_EXT) gdal_wrap.$(OBJ_EXT) osr_wrap.$(OBJ_EXT) ogr_wrap.$(OBJ_EXT)
+JAVA_MODULES = libgdaljni.$(SO_EXT) libogrjni.$(SO_EXT) libgdalconstjni.$(SO_EXT) libosrjni.$(SO_EXT) libgnmjni.$(SO_EXT)
+JAVA_OBJECTS = gdalconst_wrap.$(OBJ_EXT) gdal_wrap.$(OBJ_EXT) osr_wrap.$(OBJ_EXT) ogr_wrap.$(OBJ_EXT) gnm_wrap.$(OBJ_EXT)
 
 clean:
 	-rm -f ${JAVA_MODULES}
@@ -87,6 +87,9 @@ test:
 	${JAVA_RUN} gdalinfo -checksum tmp_test/byte.tif
 	${JAVA_RUN} ogr2ogr tmp_test/out.shp test_data/poly.shp -progress -overwrite
 	${JAVA_RUN} ogrinfo -ro -al tmp_test/out.shp
+	${JAVA_RUN} ogr2ogr_new tmp_test/out2.shp test_data/poly.shp -progress -overwrite
+	${JAVA_RUN} ogr2ogr_new tmp_test/out2.shp test_data/poly.shp -append
+	${JAVA_RUN} ogrinfo -ro -al tmp_test/out2.shp
 	${JAVA_RUN} OSRTransform
 	${JAVA_RUN} gdalmajorobject
 	${JAVA_RUN} GDALTestIO
diff --git a/swig/java/add_javadoc.c b/swig/java/add_javadoc.c
index d091871..ebf33a3 100644
--- a/swig/java/add_javadoc.c
+++ b/swig/java/add_javadoc.c
@@ -29,7 +29,7 @@
 *******************************************************************************/
 
 /* NOTE : this is really a quick and very dirty hack to put the javadoc contained */
-/* in a special formated file, javadoc.java, into the SWIG generated java files */
+/* in a special formatted file, javadoc.java, into the SWIG generated java files */
 /* This program leaks memory and would crash easily on unexpected inputs */
 
 #include <stdio.h>
@@ -322,7 +322,7 @@ begin:
     for(j=0;j<nInstances;j++)
     {
         if (!instances[j].bUsed)
-            fprintf(stderr, "WARNING: did not find occurence of %s\n", instances[j].methodName);
+            fprintf(stderr, "WARNING: did not find occurrence of %s\n", instances[j].methodName);
     }
     
     return 0;
diff --git a/swig/java/apps/GDALContour.java b/swig/java/apps/GDALContour.java
index 77c3687..66f80d5 100644
--- a/swig/java/apps/GDALContour.java
+++ b/swig/java/apps/GDALContour.java
@@ -294,12 +294,12 @@ public class GDALContour {
          */
 
         FeatureDefn feature = layer.GetLayerDefn();
-        
+
         gdal.ContourGenerate(band, contourInterval, offset, fixedLevelsDouble,
                 (ignoreNodata ? 1 : 0), sourceNodata, layer, feature.GetFieldIndex("ID"),
                 (attributName != null ? feature.GetFieldIndex(attributName) : -1),
                 progressCallback);
-        
+
         dataSource.delete();
         dataset.delete();
     }
diff --git a/swig/java/apps/GDALOverviews.java b/swig/java/apps/GDALOverviews.java
index 51c9db0..ebcf983 100644
--- a/swig/java/apps/GDALOverviews.java
+++ b/swig/java/apps/GDALOverviews.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: GDALOverviews.java 20974 2010-10-26 18:03:08Z rouault $
+ * $Id: GDALOverviews.java 32865 2016-01-08 21:22:17Z goatbar $
  *
  * Name:     GDALOverviews.java
  * Project:  GDAL Java Interface
@@ -53,7 +53,7 @@ import org.gdal.gdal.TermProgressCallback;
 /// </summary> 
 
 class GDALOverviews {
-	
+
 	public static void usage() 
 
 	{ 
@@ -61,7 +61,7 @@ class GDALOverviews {
 		System.out.println("example: gdaloverviews sample.tif \"NEAREST\" 2 4");
 		System.exit(-1);
 	}
- 
+
     public static void main(String[] args) 
     {
         /* -------------------------------------------------------------------- */
@@ -71,14 +71,14 @@ class GDALOverviews {
 
         args = gdal.GeneralCmdLineProcessor(args);
         if (args.length <= 2) usage();
-        
+
         try 
         {
             /* -------------------------------------------------------------------- */
             /*      Open dataset.                                                   */
             /* -------------------------------------------------------------------- */
             Dataset ds = gdal.Open( args[0], gdalconst.GA_Update );
-		
+
             if (ds == null) 
             {
                 System.out.println("Can't open " + args[0]);
@@ -89,22 +89,22 @@ class GDALOverviews {
             System.out.println("  Projection: " + ds.GetProjectionRef());
             System.out.println("  RasterCount: " + ds.getRasterCount());
             System.out.println("  RasterSize (" + ds.getRasterXSize() + "," + ds.getRasterYSize() + ")");
-            
+
             int[] levels = new int[args.length -2];
 
             System.out.println(levels.length);
-           
+
             for (int i = 2; i < args.length; i++)
             {
                 levels[i-2] = Integer.parseInt(args[i]);
             }
-			
+
             if (ds.BuildOverviews(args[1], levels, new TermProgressCallback()) != gdalconst.CE_None)
             {
                 System.out.println("The BuildOverviews operation doesn't work");
                 System.exit(-1);
             }
- 
+
             /* -------------------------------------------------------------------- */
             /*      Displaying the raster parameters                                */
             /* -------------------------------------------------------------------- */
@@ -138,4 +138,4 @@ class GDALOverviews {
         }
     }
 
-}
\ No newline at end of file
+}
diff --git a/swig/java/apps/GDALProximity.java b/swig/java/apps/GDALProximity.java
index 4f82d66..aff3ac9 100644
--- a/swig/java/apps/GDALProximity.java
+++ b/swig/java/apps/GDALProximity.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: GDALProximity.java 18104 2009-11-26 00:43:16Z ilucena $
+ * $Id: GDALProximity.java 32865 2016-01-08 21:22:17Z goatbar $
  *
  * Project: GDAL
  * Purpose: Compute each pixel's proximity to a set of target pixels.
@@ -112,7 +112,7 @@ public class GDALProximity {
         int TargetValues[] = new int[0];
         float DistMult = 1.0F;
         String Options = "";
-       
+
         for (int i = 0; i < args.length; i++) {
             if (args[i].equals("-of")) {
                 i++;
@@ -193,7 +193,7 @@ public class GDALProximity {
         WorkProximityDriver = gdal.IdentifyDriver(OutputFilename);
 
         if (WorkProximityDriver != null) {
-            
+
             WorkProximityDataset = gdal.Open(OutputFilename, gdalconstConstants.GA_Update);
 
             if (WorkProximityDataset == null) {
@@ -206,7 +206,7 @@ public class GDALProximity {
             /*
              * Create a new output dataset
              */
-          
+
             WorkProximityDriver = gdal.GetDriverByName(OutputFormat);
 
             WorkProximityDataset = WorkProximityDriver.Create(OutputFilename, 
@@ -231,7 +231,7 @@ public class GDALProximity {
 
         if( GeoUnits ) {
             double geoTransform[] = SourceDataset.GetGeoTransform();
-            
+
             if( Math.abs(geoTransform[1]) != Math.abs(geoTransform[5])) {
                 System.err.println("Pixels not square, distances will be inaccurate.");
             }
@@ -452,7 +452,7 @@ public class GDALProximity {
              */
 
             boolean isATarger = false;
-            
+
             if( TargetValues.length == 0) {
                 isATarger = scanlineArray[iPixel] != 0.0F;
             } else {
@@ -463,7 +463,7 @@ public class GDALProximity {
                     }
                 }
             }
-            
+
             if (isATarger) {
                 proximityArray[iPixel] = 0.0F;
                 nearXArray[iPixel] = (short) iPixel;
diff --git a/swig/java/apps/ReadXML.java b/swig/java/apps/ReadXML.java
index 7e23f75..2e5fc24 100644
--- a/swig/java/apps/ReadXML.java
+++ b/swig/java/apps/ReadXML.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ReadXML.java 16344 2009-02-15 00:20:49Z rouault $
+ * $Id: ReadXML.java 32865 2016-01-08 21:22:17Z goatbar $
  *
  * Name:     ReadXML.java
  * Project:  GDAL Java Interface
@@ -49,10 +49,10 @@ import org.gdal.gdal.XMLNodeType;
 /// </summary> 
 
 public class ReadXML {
-    
+
     public static void usage() 
 
-    { 
+    {
             System.out.println("usage example: readxml {xml string}");
             System.exit(-1);
     }
diff --git a/swig/java/apps/WKT2WKB.java b/swig/java/apps/WKT2WKB.java
index ed428e8..1f1c1c3 100644
--- a/swig/java/apps/WKT2WKB.java
+++ b/swig/java/apps/WKT2WKB.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: WKT2WKB.java 16344 2009-02-15 00:20:49Z rouault $
+ * $Id: WKT2WKB.java 32865 2016-01-08 21:22:17Z goatbar $
  *
  * Name:     WKT2WKB.java
  * Project:  GDAL Java Interface
@@ -48,9 +48,9 @@ import org.gdal.ogr.Geometry;
 /// </summary> 
 
 public class WKT2WKB {
-        
+
         public static void usage() 
-        { 
+        {
                 System.out.println("usage example: wkt2wkb \"POINT(47.0 19.2)\"");
                 System.exit(-1);
         }
diff --git a/swig/java/apps/gdalinfo.java b/swig/java/apps/gdalinfo.java
index 4dda025..8f2ed5b 100644
--- a/swig/java/apps/gdalinfo.java
+++ b/swig/java/apps/gdalinfo.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalinfo.java 28051 2014-12-03 18:59:00Z goatbar $
+ * $Id: gdalinfo.java 32865 2016-01-08 21:22:17Z goatbar $
  *
  * Name:     gdalinfo.java
  * Project:  GDAL SWIG Interface
@@ -74,7 +74,8 @@ public class gdalinfo {
 			double[] adfGeoTransform = new double[6];
 			Driver hDriver;
 			Vector papszMetadata;
-			boolean bComputeMinMax = false /* , bSample = false */;
+                        boolean bComputeMinMax = false;
+                        /* boolean bSample = false; */
 			boolean bShowGCPs = true, bShowMetadata = true;
 			boolean bStats = false, bApproxStats = true;
                         boolean bShowColorTable = true, bComputeChecksum = false;
@@ -252,7 +253,7 @@ public class gdalinfo {
 					System.out.println("  " + (String) keys.nextElement());
 				}
 			}
-                        
+
                         Enumeration eExtraMDDDomains = papszExtraMDDomains.elements();
                         while(eExtraMDDDomains.hasMoreElements())
                         {
@@ -289,7 +290,7 @@ public class gdalinfo {
 					System.out.println("  " + (String) keys.nextElement());
 				}
 			}
-                    
+
                     /* -------------------------------------------------------------------- */
                     /*      Report geolocation.                                             */
                     /* -------------------------------------------------------------------- */
@@ -301,7 +302,7 @@ public class gdalinfo {
                                     System.out.println("  " + (String) keys.nextElement());
                             }
                         }
-                    
+
                     /* -------------------------------------------------------------------- */
                     /*      Report RPCs                                                     */
                     /* -------------------------------------------------------------------- */
@@ -373,14 +374,14 @@ public class gdalinfo {
                                         System.out.print( "Min=" + pass1[0] + " ");
                                     if( pass2[0] != null )
                                         System.out.print( "Max=" + pass2[0] + " ");
-                                
+
                                     if( bComputeMinMax )
                                     {
                                         hBand.ComputeRasterMinMax(adfCMinMax, 0);
                                         System.out.print( "  Computed Min/Max=" + adfCMinMax[0]
 							+ "," + adfCMinMax[1]);
                                     }
-                        
+
                                     System.out.print( "\n" );
 				}
 
@@ -446,10 +447,10 @@ public class gdalinfo {
                                                 iOverview++ )
                                             {
                                                 Band	hOverview;
-                            
+
                                                 if( iOverview != 0 )
                                                     System.out.print( ", " );
-                            
+
                                                 hOverview = hBand.GetOverview(iOverview);
                                                 System.out.print( hOverview.Checksum());
                                             }
@@ -467,7 +468,7 @@ public class gdalinfo {
                                 if( (nMaskFlags & (gdalconstConstants.GMF_NODATA|gdalconstConstants.GMF_ALL_VALID)) == 0 )
                                 {
                                     Band hMaskBand = hBand.GetMaskBand() ;
-                        
+
                                     System.out.print( "  Mask Flags: " );
                                     if( (nMaskFlags & gdalconstConstants.GMF_PER_DATASET) != 0 )
                                         System.out.print( "PER_DATASET " );
@@ -478,22 +479,22 @@ public class gdalinfo {
                                     if( (nMaskFlags & gdalconstConstants.GMF_ALL_VALID) != 0 )
                                         System.out.print( "ALL_VALID " );
                                     System.out.print( "\n" );
-                        
+
                                     if( hMaskBand != null &&
                                         hMaskBand.GetOverviewCount() > 0 )
                                     {
                                         int		iOverview;
-                        
+
                                         System.out.print( "  Overviews of mask band: " );
                                         for( iOverview = 0; 
                                             iOverview < hMaskBand.GetOverviewCount();
                                             iOverview++ )
                                         {
                                             Band	hOverview;
-                        
+
                                             if( iOverview != 0 )
                                                 System.out.print( ", " );
-                        
+
                                             hOverview = hMaskBand.GetOverview( iOverview );
                                             System.out.print( 
                                                     hOverview.getXSize() + "x" +
@@ -502,7 +503,7 @@ public class gdalinfo {
                                         System.out.print( "\n" );
                                     }
                                 }
-                                
+
 				if( hBand.GetUnitType() != null && hBand.GetUnitType().length() > 0)
 				{
 				     System.out.println( "  Unit Type: " + hBand.GetUnitType() );
diff --git a/swig/java/apps/multireadtest.java b/swig/java/apps/multireadtest.java
index 08e3c4c..248c7c7 100644
--- a/swig/java/apps/multireadtest.java
+++ b/swig/java/apps/multireadtest.java
@@ -34,12 +34,12 @@ import org.gdal.gdal.Dataset;
 public class multireadtest implements Runnable
 {
     private String _filename;
-    
+
     public multireadtest(String filename)
     {
         _filename = filename;
     }
-    
+
     public void run()
     {
         for(int i=0;i<100;i++)
@@ -49,11 +49,11 @@ public class multireadtest implements Runnable
             //ds.delete();
         }
     }
-    
+
     public static void main(String[] args) throws InterruptedException
     {
         String filename = args[0];
-        
+
         gdal.AllRegister();
 
         Thread t[] = new Thread[4];
diff --git a/swig/java/apps/ogr2ogr.java b/swig/java/apps/ogr2ogr.java
index 206c2ce..3197a1c 100644
--- a/swig/java/apps/ogr2ogr.java
+++ b/swig/java/apps/ogr2ogr.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr2ogr.java 25229 2012-11-16 19:06:58Z rouault $
+ * $Id: ogr2ogr.java 32865 2016-01-08 21:22:17Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Java port of a simple client for translating between formats.
@@ -142,18 +142,18 @@ public class ogr2ogr
     /* -------------------------------------------------------------------- */
         if( ogr.GetDriverCount() == 0 )
             ogr.RegisterAll();
-    
+
     /* -------------------------------------------------------------------- */
     /*      Processing command line arguments.                              */
     /* -------------------------------------------------------------------- */
         args = ogr.GeneralCmdLineProcessor( args );
-        
+
         if( args.length < 2 )
         {
             Usage();
             System.exit( -1 );
         }
-    
+
         for( int iArg = 0; iArg < args.length; iArg++ )
         {
             if( args[iArg].equalsIgnoreCase("-f") && iArg < args.length-1 )
@@ -276,7 +276,7 @@ public class ogr2ogr
                 oRing.AddPoint(xmax, ymax);
                 oRing.AddPoint(xmax, ymin);
                 oRing.AddPoint(xmin, ymin);
-                
+
                 poSpatialFilter = new Geometry(ogrConstants.wkbPolygon);
                 poSpatialFilter.AddGeometry(oRing);
             }
@@ -358,7 +358,7 @@ public class ogr2ogr
                     oRing.AddPoint(xmax, ymax);
                     oRing.AddPoint(xmax, ymin);
                     oRing.AddPoint(xmin, ymin);
-                    
+
                     poClipSrc = new Geometry(ogrConstants.wkbPolygon);
                     poClipSrc.AddGeometry(oRing);
                 }
@@ -412,7 +412,7 @@ public class ogr2ogr
                     oRing.AddPoint(xmax, ymax);
                     oRing.AddPoint(xmax, ymin);
                     oRing.AddPoint(xmin, ymin);
-                    
+
                     poClipDst = new Geometry(ogrConstants.wkbPolygon);
                     poClipDst.AddGeometry(oRing);
                 }
@@ -472,7 +472,7 @@ public class ogr2ogr
             else
                 papszLayers.addElement (args[iArg] );
         }
-    
+
         if( pszDataSource == null )
             Usage();
 
@@ -502,7 +502,7 @@ public class ogr2ogr
                 Usage();
             }
         }
-        
+
         if( pszClipDstDS != null)
         {
             poClipDst = LoadGeometry(pszClipDstDS, pszClipDstSQL, pszClipDstLayer, pszClipDstWhere);
@@ -516,9 +516,9 @@ public class ogr2ogr
     /*      Open data source.                                               */
     /* -------------------------------------------------------------------- */
         DataSource poDS;
-            
+
         poDS = ogr.Open( pszDataSource, false );
-    
+
     /* -------------------------------------------------------------------- */
     /*      Report failure                                                  */
     /* -------------------------------------------------------------------- */
@@ -526,21 +526,21 @@ public class ogr2ogr
         {
             System.err.println("FAILURE:\n" + 
                     "Unable to open datasource ` " + pszDataSource + "' with the following drivers.");
-    
+
             for( int iDriver = 0; iDriver < ogr.GetDriverCount(); iDriver++ )
             {
                 System.err.println("  . " + ogr.GetDriver(iDriver).GetName() );
             }
-    
+
             System.exit( 1 );
         }
-    
+
     /* -------------------------------------------------------------------- */
     /*      Try opening the output datasource as an existing, writable      */
     /* -------------------------------------------------------------------- */
         DataSource       poODS = null;
         Driver poDriver = null;
-        
+
         if( bUpdate )
         {
             poODS = ogr.Open( pszDestDataSource, true );
@@ -568,7 +568,7 @@ public class ogr2ogr
                     System.exit( 1 );
                 }
             }
-    
+
             else if( papszDSCO.size() > 0 )
             {
                 System.err.println("WARNING: Datasource creation options ignored since an existing datasource\n" +
@@ -578,27 +578,27 @@ public class ogr2ogr
             if (poODS != null)
                 poDriver = poODS.GetDriver();
         }
-    
+
     /* -------------------------------------------------------------------- */
     /*      Find the output driver.                                         */
     /* -------------------------------------------------------------------- */
         if( !bUpdate )
         {
             int                  iDriver;
-    
+
             poDriver = ogr.GetDriverByName(pszFormat);
             if( poDriver == null )
             {
                 System.err.println("Unable to find driver `" + pszFormat +"'." );
                 System.err.println( "The following drivers are available:" );
-            
+
                 for( iDriver = 0; iDriver < ogr.GetDriverCount(); iDriver++ )
                 {
                     System.err.println("  . " + ogr.GetDriver(iDriver).GetName() );
                 }
                 System.exit( 1 );
             }
-    
+
             if( poDriver.TestCapability( ogr.ODrCCreateDataSource ) == false )
             {
                 System.err.println( pszFormat + " driver does not support data source creation.");
@@ -643,7 +643,7 @@ public class ogr2ogr
                 System.exit( 1 );
             }
         }
-    
+
     /* -------------------------------------------------------------------- */
     /*      Parse the output SRS definition if possible.                    */
     /* -------------------------------------------------------------------- */
@@ -656,7 +656,7 @@ public class ogr2ogr
                 System.exit( 1 );
             }
         }
-    
+
     /* -------------------------------------------------------------------- */
     /*      Parse the source SRS definition if possible.                    */
     /* -------------------------------------------------------------------- */
@@ -669,22 +669,22 @@ public class ogr2ogr
                 System.exit( 1 );
             }
         }
-    
+
     /* -------------------------------------------------------------------- */
     /*      Special case for -sql clause.  No source layers required.       */
     /* -------------------------------------------------------------------- */
         if( pszSQLStatement != null )
         {
             Layer poResultSet;
-    
+
             if( pszWHERE != null )
                 System.err.println( "-where clause ignored in combination with -sql." );
             if( papszLayers.size() > 0 )
                 System.err.println( "layer names ignored in combination with -sql." );
-            
+
             poResultSet = poDS.ExecuteSQL( pszSQLStatement, poSpatialFilter, 
                                             null );
-    
+
             if( poResultSet != null )
             {
                 long nCountLayerFeatures = 0;
@@ -730,7 +730,7 @@ public class ogr2ogr
                     System.err.println(
                             "Terminating translation prematurely after failed\n" +
                             "translation from sql statement." );
-    
+
                     System.exit( 1 );
                 }
                 poDS.ReleaseResultSet( poResultSet );
@@ -882,18 +882,18 @@ public class ogr2ogr
     /* -------------------------------------------------------------------- */
     /*      Close down.                                                     */
     /* -------------------------------------------------------------------- */
-        /* We must explicetely destroy the output dataset in order the file */
+        /* We must explicitly destroy the output dataset in order the file */
         /* to be properly closed ! */
         poODS.delete();
         poDS.delete();
     }
-    
+
     /************************************************************************/
     /*                               Usage()                                */
     /************************************************************************/
-    
+
     static void Usage()
-    
+
     {
         System.out.print( "Usage: ogr2ogr [--help-general] [-skipfailures] [-append] [-update] [-gt n]\n" +
                 "               [-select field_list] [-where restricted_where] \n" +
@@ -908,15 +908,15 @@ public class ogr2ogr
                 "               [-lco NAME=VALUE] [-nln name] [-nlt type] [layer [layer ...]]\n" +
                 "\n" +
                 " -f format_name: output file format name, possible values are:\n");
-        
+
         for( int iDriver = 0; iDriver < ogr.GetDriverCount(); iDriver++ )
         {
             Driver poDriver = ogr.GetDriver(iDriver);
-    
+
             if( poDriver.TestCapability( ogr.ODrCCreateDataSource ) )
                 System.out.print( "     -f \"" + poDriver.GetName() + "\"\n" );
         }
-    
+
         System.out.print( " -append: Append to existing layer instead of creating new if it exists\n" +
                 " -overwrite: delete the output layer and recreate it empty\n" +
                 " -update: Open existing output datasource in update mode\n" +
@@ -942,15 +942,15 @@ public class ogr2ogr
                 "      fields of type string in the new layer. Valid types are : \n" +
                 "      Integer, Real, String, Date, Time, DateTime, Binary, IntegerList, RealList,\n" +
                 "      StringList. Special value All can be used to convert all fields to strings.\n");
-    
+
         System.out.print(" -a_srs srs_def: Assign an output SRS\n" +
             " -t_srs srs_def: Reproject/transform to this SRS on output\n" +
             " -s_srs srs_def: Override source SRS\n" +
             "\n" + 
             " Srs_def can be a full WKT definition (hard to escape properly),\n" +
-            " or a well known definition (ie. EPSG:4326) or a file with a WKT\n" +
+            " or a well known definition (i.e. EPSG:4326) or a file with a WKT\n" +
             " definition.\n" );
-    
+
         System.exit( 1 );
     }
 
@@ -968,7 +968,6 @@ public class ogr2ogr
         return -1;
     }
 
-    
     static boolean IsNumber(String pszStr)
     {
         try
@@ -981,7 +980,7 @@ public class ogr2ogr
             return false;
         }
     }
-    
+
     static Geometry LoadGeometry( String pszDS,
                                   String pszSQL,
                                   String pszLyr,
@@ -991,45 +990,45 @@ public class ogr2ogr
         Layer            poLyr;
         Feature          poFeat;
         Geometry         poGeom = null;
-            
+
         poDS = ogr.Open( pszDS, false );
         if (poDS == null)
             return null;
-    
+
         if (pszSQL != null)
             poLyr = poDS.ExecuteSQL( pszSQL, null, null ); 
         else if (pszLyr != null)
             poLyr = poDS.GetLayerByName(pszLyr);
         else
             poLyr = poDS.GetLayer(0);
-            
+
         if (poLyr == null)
         {
             System.err.print("Failed to identify source layer from datasource.\n");
             poDS.delete();
             return null;
         }
-        
+
         if (pszWhere != null)
             poLyr.SetAttributeFilter(pszWhere);
-            
+
         while ((poFeat = poLyr.GetNextFeature()) != null)
         {
             Geometry poSrcGeom = poFeat.GetGeometryRef();
             if (poSrcGeom != null)
             {
                 int eType = wkbFlatten(poSrcGeom.GetGeometryType());
-                
+
                 if (poGeom == null)
                     poGeom = new Geometry( ogr.wkbMultiPolygon );
-    
+
                 if( eType == ogr.wkbPolygon )
                     poGeom.AddGeometry( poSrcGeom );
                 else if( eType == ogr.wkbMultiPolygon )
                 {
                     int iGeom;
                     int nGeomCount = poSrcGeom.GetGeometryCount();
-    
+
                     for( iGeom = 0; iGeom < nGeomCount; iGeom++ )
                     {
                         poGeom.AddGeometry(poSrcGeom.GetGeometryRef(iGeom) );
@@ -1102,7 +1101,7 @@ public class ogr2ogr
     /************************************************************************/
     /*                           TranslateLayer()                           */
     /************************************************************************/
-    
+
     static boolean TranslateLayer( DataSource poSrcDS, 
                             Layer poSrcLayer,
                             DataSource poDstDS,
@@ -1123,7 +1122,7 @@ public class ogr2ogr
                             String pszZField,
                             String pszWHERE,
                             ProgressCallback pfnProgress)
-    
+
     {
         Layer    poDstLayer;
         FeatureDefn poSrcFDefn;
@@ -1131,73 +1130,73 @@ public class ogr2ogr
         boolean         bForceToPolygon = false;
         boolean         bForceToMultiPolygon = false;
         boolean         bForceToMultiLineString = false;
-    
+
         if( pszNewLayerName == null )
             pszNewLayerName = poSrcLayer.GetLayerDefn().GetName();
-    
+
         if( wkbFlatten(eGType) == ogr.wkbPolygon )
             bForceToPolygon = true;
         else if( wkbFlatten(eGType) == ogr.wkbMultiPolygon )
             bForceToMultiPolygon = true;
         else if( wkbFlatten(eGType) == ogr.wkbMultiLineString )
             bForceToMultiLineString = true;
-    
+
     /* -------------------------------------------------------------------- */
     /*      Setup coordinate transformation if we need it.                  */
     /* -------------------------------------------------------------------- */
         CoordinateTransformation poCT = null;
-    
+
         if( bTransform )
         {
             if( poSourceSRS == null )
                 poSourceSRS = poSrcLayer.GetSpatialRef();
-    
+
             if( poSourceSRS == null )
             {
                 System.err.println("Can't transform coordinates, source layer has no\n" +
                         "coordinate system.  Use -s_srs to set one." );
                 System.exit( 1 );
             }
-    
+
             /*CPLAssert( null != poSourceSRS );
             CPLAssert( null != poOutputSRS );*/
-    
+
             /* New in GDAL 1.10. Before was "new CoordinateTransformation(srs,dst)". */
             poCT = CoordinateTransformation.CreateCoordinateTransformation( poSourceSRS, poOutputSRS );
             if( poCT == null )
             {
                 String pszWKT = null;
-    
+
                 System.err.println("Failed to create coordinate transformation between the\n" +
                     "following coordinate systems.  This may be because they\n" +
                     "are not transformable, or because projection services\n" +
                     "(PROJ.4 DLL/.so) could not be loaded." );
-                
+
                 pszWKT = poSourceSRS.ExportToPrettyWkt( 0 );
                 System.err.println( "Source:\n" + pszWKT );
-                
+
                 pszWKT = poOutputSRS.ExportToPrettyWkt( 0 );
                 System.err.println( "Target:\n" + pszWKT );
                 System.exit( 1 );
             }
         }
-        
+
     /* -------------------------------------------------------------------- */
     /*      Get other info.                                                 */
     /* -------------------------------------------------------------------- */
         poSrcFDefn = poSrcLayer.GetLayerDefn();
-        
+
         if( poOutputSRS == null )
             poOutputSRS = poSrcLayer.GetSpatialRef();
-    
+
     /* -------------------------------------------------------------------- */
     /*      Find the layer.                                                 */
     /* -------------------------------------------------------------------- */
 
-        /* GetLayerByName() can instanciate layers that would have been */
+        /* GetLayerByName() can instantiate layers that would have been */
         /* 'hidden' otherwise, for example, non-spatial tables in a */
-        /* Postgis-enabled database, so this apparently useless command is */
-        /* not useless... (#4012) */
+        /* PostGIS-enabled database, so this apparently useless command is */
+        /* not useless. (#4012) */
         gdal.PushErrorHandler("CPLQuietErrorHandler");
         poDstLayer = poDstDS.GetLayerByName(pszNewLayerName);
         gdal.PopErrorHandler();
@@ -1238,7 +1237,7 @@ public class ogr2ogr
             }
             poDstLayer = null;
         }
-    
+
     /* -------------------------------------------------------------------- */
     /*      If the layer does not exist, then create it.                    */
     /* -------------------------------------------------------------------- */
@@ -1272,25 +1271,25 @@ public class ogr2ogr
                 if ( pszZField != null )
                     eGType |= ogr.wkb25DBit;
             }
-    
+
             if( poDstDS.TestCapability( ogr.ODsCCreateLayer ) == false)
             {
                 System.err.println(
                 "Layer " + pszNewLayerName + "not found, and CreateLayer not supported by driver.");
                 return false;
             }
-    
+
             gdal.ErrorReset();
-    
+
             poDstLayer = poDstDS.CreateLayer( pszNewLayerName, poOutputSRS,
                                               eGType, papszLCO );
-    
+
             if( poDstLayer == null )
                 return false;
-    
+
             bAppend = false;
         }
-    
+
     /* -------------------------------------------------------------------- */
     /*      Otherwise we will append to it, if append was requested.        */
     /* -------------------------------------------------------------------- */
@@ -1308,7 +1307,7 @@ public class ogr2ogr
                         "         being appended to." );
             }
         }
-    
+
     /* -------------------------------------------------------------------- */
     /*      Add fields.  Default to copy all field.                         */
     /*      If only a subset of all fields requested, then output only      */
@@ -1486,7 +1485,7 @@ public class ogr2ogr
                     panMap[iField] = iDstField;
             }
         }
-    
+
     /* -------------------------------------------------------------------- */
     /*      Transfer features.                                              */
     /* -------------------------------------------------------------------- */
@@ -1501,14 +1500,14 @@ public class ogr2ogr
         }
 
         poSrcLayer.ResetReading();
-    
+
         if( nGroupTransactions > 0)
             poDstLayer.StartTransaction();
-    
+
         while( true )
         {
             Feature      poDstFeature = null;
-    
+
             if( nFIDToFetch != OGRNullFID )
             {
                 // Only fetch feature on first pass.
@@ -1519,7 +1518,7 @@ public class ogr2ogr
             }
             else
                 poFeature = poSrcLayer.GetNextFeature();
-            
+
             if( poFeature == null )
                 break;
 
@@ -1548,7 +1547,7 @@ public class ogr2ogr
 
             for(int iPart = 0; iPart < nIters; iPart++)
             {
-    
+
                 if( ++nFeaturesInTransaction == nGroupTransactions )
                 {
                     poDstLayer.CommitTransaction();
@@ -1710,10 +1709,10 @@ public class ogr2ogr
                 pfnProgress.run(nCount * 1.0 / nCountLayerFeatures, "");
 
         }
-    
+
         if( nGroupTransactions > 0 )
             poDstLayer.CommitTransaction();
-    
+
         return true;
     }
 }
diff --git a/swig/java/apps/ogr2ogr_new.java b/swig/java/apps/ogr2ogr_new.java
new file mode 100644
index 0000000..3051813
--- /dev/null
+++ b/swig/java/apps/ogr2ogr_new.java
@@ -0,0 +1,84 @@
+/******************************************************************************
+ * $Id: ogr2ogr_new.java 30884 2015-10-07 14:01:07Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Simple client for translating between formats.
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2015, Even Rouault
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+import org.gdal.gdal.gdal;
+import org.gdal.gdal.Dataset;
+import org.gdal.gdal.VectorTranslateOptions;
+import org.gdal.gdalconst.*;
+import java.util.Vector;
+
+public class ogr2ogr_new
+{
+    public static void main(String[] args)
+    {
+        gdal.AllRegister();
+
+        String src = null, dest = null;
+        Vector newArgs = new Vector();
+        boolean tryUpdate = false;
+        for(int i=0;i<args.length;i++)
+        {
+            if( args[i].charAt(0) == '-')
+            {
+                if( args[i].equals("-update") ||
+                    args[i].equals("-append") ||
+                    args[i].equals("-overwrite") )
+                {
+                    tryUpdate = true;
+                }
+                newArgs.add(args[i]);
+            }
+            else if( dest == null )
+                dest = args[i];
+            else if( src == null )
+                src = args[i];
+            else
+                newArgs.add(args[i]);
+        }
+
+        Dataset srcDS = gdal.OpenEx(src, gdalconst.OF_VECTOR | gdalconst.OF_VERBOSE_ERROR);
+        Dataset outDS = null;
+        if( tryUpdate )
+        {
+            outDS = gdal.OpenEx(dest, gdalconst.OF_VECTOR | gdalconst.OF_UPDATE);
+        }
+        if( outDS != null )
+        {
+            int ret = gdal.VectorTranslate(outDS, srcDS, new VectorTranslateOptions(newArgs));
+            if( ret != 1 )
+                System.exit(1);
+        }
+        else
+        {
+            outDS = gdal.VectorTranslate(dest, srcDS, new VectorTranslateOptions(newArgs));
+            if( outDS == null )
+                System.exit(1);
+        }
+    }
+}
diff --git a/swig/java/apps/ogrinfo.java b/swig/java/apps/ogrinfo.java
index f683f3d..e4427a3 100644
--- a/swig/java/apps/ogrinfo.java
+++ b/swig/java/apps/ogrinfo.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrinfo.java 23704 2012-01-06 10:27:08Z rouault $
+ * $Id: ogrinfo.java 32865 2016-01-08 21:22:17Z goatbar $
  *
  * Name:     ogrinfo.java
  * Project:  GDAL SWIG Interface
@@ -45,10 +45,10 @@ public class ogrinfo
     static boolean     bReadOnly = false;
     static boolean     bVerbose = true;
     static boolean     bSummaryOnly = false;
-    
+
     static final int OGRNullFID = -1;
     static int     nFetchFID = OGRNullFID;
-    
+
     public static void main(String[] args)
     {
         String pszWHERE = null;
@@ -91,7 +91,7 @@ public class ogrinfo
                 oRing.AddPoint(xmax, ymax);
                 oRing.AddPoint(xmax, ymin);
                 oRing.AddPoint(xmin, ymin);
-                
+
                 poSpatialFilter = new Geometry(ogrConstants.wkbPolygon);
                 poSpatialFilter.AddGeometry(oRing);
             }
@@ -157,7 +157,7 @@ public class ogrinfo
 /* -------------------------------------------------------------------- */
 /*      Open data source.                                               */
 /* -------------------------------------------------------------------- */
-        
+
         DataSource poDS = ogr.Open(pszDataSource, !bReadOnly);
         if (poDS == null && !bReadOnly)
         {
@@ -167,7 +167,7 @@ public class ogrinfo
                 System.out.println( "Had to open data source read-only.");
             }
         }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Report failure                                                  */
 /* -------------------------------------------------------------------- */
@@ -175,15 +175,15 @@ public class ogrinfo
         {
             System.out.print( "FAILURE:\n" +
                 "Unable to open datasource `" + pszDataSource + "' with the following drivers.\n");
-            
+
             for( int iDriver = 0; iDriver < ogr.GetDriverCount(); iDriver++ )
             {
                 System.out.println( "  -> " + ogr.GetDriver(iDriver).GetName() );
             }
-            
+
             return;
         }
-        
+
         Driver poDriver = poDS.GetDriver();
 
 /* -------------------------------------------------------------------- */
@@ -199,12 +199,12 @@ public class ogrinfo
         if( pszSQLStatement != null )
         {
             nRepeatCount = 0;  // skip layer reporting.
-    
+
             if( papszLayers.size() > 0 )
                 System.out.println( "layer names ignored in combination with -sql." );
-            
+
             Layer poResultSet = poDS.ExecuteSQL( pszSQLStatement, poSpatialFilter, pszDialect );
-    
+
             if( poResultSet != null )
             {
                 if( pszWHERE != null )
@@ -215,7 +215,7 @@ public class ogrinfo
                         return;
                     }
                 }
-    
+
                 ReportOnLayer( poResultSet, null, null );
                 poDS.ReleaseResultSet( poResultSet );
             }
@@ -225,7 +225,7 @@ public class ogrinfo
 /*      Process each data source layer.                                 */
 /* -------------------------------------------------------------------- */
         //CPLDebug( "OGR", "GetLayerCount() = %d\n", poDS->GetLayerCount() );
-    
+
         for( int iRepeat = 0; iRepeat < nRepeatCount; iRepeat++ )
         {
             if (papszLayers.size() == 0)
@@ -322,7 +322,7 @@ public class ogrinfo
                 return;
             }
         }
-    
+
         if( poSpatialFilter != null )
             poLayer.SetSpatialFilter( poSpatialFilter );
 
@@ -330,41 +330,41 @@ public class ogrinfo
 /*      Report various overall information.                             */
 /* -------------------------------------------------------------------- */
         System.out.println();
-        
+
         System.out.println( "Layer name: "+  poDefn.GetName() );
-    
+
         if( bVerbose )
         {
             System.out.println( "Geometry: " +
                     ogr.GeometryTypeToName( poDefn.GetGeomType() ) );
-            
+
             System.out.println( "Feature Count: " + poLayer.GetFeatureCount() );
-            
+
             double oExt[] = poLayer.GetExtent(true);
             if (oExt != null)
                 System.out.println("Extent: (" + oExt[0] + ", " + oExt[2] + ") - (" + oExt[1] + ", " + oExt[3] + ")");
-    
+
             String pszWKT;
-            
+
             if( poLayer.GetSpatialRef() == null )
                 pszWKT = "(unknown)";
             else
             {
                 pszWKT = poLayer.GetSpatialRef().ExportToPrettyWkt();
-            }            
-    
+            }
+
             System.out.println( "Layer SRS WKT:\n" + pszWKT );
-        
+
             if( poLayer.GetFIDColumn().length() > 0 )
                 System.out.println( "FID Column = " + poLayer.GetFIDColumn() );
-        
+
             if( poLayer.GetGeometryColumn().length() > 0 )
                 System.out.println( "Geometry Column = " +  poLayer.GetGeometryColumn() );
-    
+
             for( int iAttr = 0; iAttr < poDefn.GetFieldCount(); iAttr++ )
             {
                 FieldDefn  poField = poDefn.GetFieldDefn( iAttr );
-                
+
                 System.out.println( poField.GetNameRef() + ": " + poField.GetFieldTypeName( poField.GetFieldType() ) + " (" + poField.GetWidth() + "." + poField.GetPrecision() + ")");
             }
         }
@@ -372,7 +372,7 @@ public class ogrinfo
 /*      Read, and dump features.                                        */
 /* -------------------------------------------------------------------- */
         Feature  poFeature;
-    
+
         if( nFetchFID == OGRNullFID && !bSummaryOnly )
         {
             while( (poFeature = poLayer.GetNextFeature()) != null )
diff --git a/swig/java/gnm/makefile.vc b/swig/java/gnm/makefile.vc
new file mode 100644
index 0000000..20ceabc
--- /dev/null
+++ b/swig/java/gnm/makefile.vc
@@ -0,0 +1,16 @@
+OBJ	=	gnm_wrap.obj
+
+GDAL_ROOT	=	..\..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+default:	$(OBJ)
+	xcopy /D  /Y *.obj ..
+
+clean:
+	-del *.obj
+	-del *.cs
+	-del *.cpp
+
+.cpp.obj:	
+	$(CC) $(CFLAGS) $(JAVA_INCLUDE) /c $*.cpp
diff --git a/swig/java/java.opt b/swig/java/java.opt
index 848ae2e..6aba3e6 100644
--- a/swig/java/java.opt
+++ b/swig/java/java.opt
@@ -2,6 +2,7 @@
 # Java Stuff
 #JAVA_HOME = "C:\Program Files\Java\jdk1.6.0_16"
 #JAVA_HOME = /usr/lib/jvm/java-6-openjdk/
+#JAVA_HOME = /usr/lib/jvm/java-7-openjdk-amd64/
 JAVADOC=$(JAVA_HOME)/bin/javadoc
 JAVAC=$(JAVA_HOME)/bin/javac
 JAVA=$(JAVA_HOME)/bin/java
diff --git a/swig/java/javadoc.java b/swig/java/javadoc.java
index 18e3c7e..d2224f7 100644
--- a/swig/java/javadoc.java
+++ b/swig/java/javadoc.java
@@ -1,5 +1,5 @@
 /* ***************************************************************************
-* $Id: javadoc.java 28785 2015-03-26 20:46:45Z goatbar $
+* $Id: javadoc.java 33129 2016-01-23 21:10:49Z rouault $
 *
 * Project:  GDAL/OGR Java bindings
 * Purpose:  Documentation for the Java bindings
@@ -123,7 +123,7 @@ public class gdal:public static java.util.Vector GeneralCmdLineProcessor(java.ut
  * are emitted (use Error(gdalconst.CE_Warning,...) to ensure messages are displayed).
  * If CPL_DEBUG is set, but is an empty string or the word "ON" then all
  * debug messages are shown.  Otherwise only messages whose category appears
- * somewhere within the CPL_DEBUG value are displayed (as determinted by
+ * somewhere within the CPL_DEBUG value are displayed (as determined by
  * strstr()).
  * <p>
  * Categories are usually an identifier for the subsystem producing the
@@ -139,7 +139,7 @@ public class gdal:public static void Debug(String msg_class, String message)
  * Push a new error handler.
  *
  * This pushes a new error handler on the thread-local error handler
- * stack.  This handler will be used untill removed with gdal.PopErrorHandler().
+ * stack.  This handler will be used until removed with gdal.PopErrorHandler().
  *
  * @param callbackName handler function name : "CPLQuietErrorHandler", "CPLDefaultErrorHandler", "CPLLoggingErrorHandler"
  */
@@ -149,7 +149,7 @@ public class gdal:public static int PushErrorHandler(String callbackName)
  * Push the quiet error handler.
  *
  * This pushes a new error handler on the thread-local error handler
- * stack.  This handler will be used untill removed with gdal.PopErrorHandler().
+ * stack.  This handler will be used until removed with gdal.PopErrorHandler().
  *
  * @since Java bindings 1.7.0
  */
@@ -190,7 +190,7 @@ public class gdal:public static int SetErrorHandler()
  * The msg_class argument can have the value gdalconst.CE_Warning indicating that the
  * message is an informational warning, gdalconst.CE_Failure indicating that the
  * action failed, but that normal recover mechanisms will be used or
- * CE_Fatal meaning that a fatal error has occured, and that Error()
+ * CE_Fatal meaning that a fatal error has occurred, and that Error()
  * should not return.  
  * <p>
  * The default behaviour of Error() is to report errors to stderr,
@@ -278,7 +278,7 @@ public class gdal:public static int Unlink(String fileName)
  * This function will "escape" a variety of special characters
  * to make the string suitable to embed within a string constant
  * or to write within a text stream but in a form that can be
- * reconstitued to it's original form.  The escaping will even preserve
+ * reconstituted to it's original form.  The escaping will even preserve
  * zero bytes allowing preservation of raw binary data.
  * <ul>
  * <li>gdalconst.CPLES_BackslashQuotable(0): This scheme turns a binary string into 
@@ -287,7 +287,7 @@ public class gdal:public static int Unlink(String fileName)
  * the usual C style. 
  *
  * <li>gdalconst.CPLES_XML(1): This scheme converts the '<', '<' and '&' characters into
- * their XML/HTML equivelent (>, < and &) making a string safe
+ * their XML/HTML equivalent (>, < and &) making a string safe
  * to embed as CDATA within an XML element.  The '\\0' is not escaped and 
  * should not be included in the input.
  *
@@ -1148,13 +1148,13 @@ public class gdal:public static Dataset AutoCreateWarpedVRT(Dataset src_ds)
  * <p>
  * Available request values:
  * <ul>
- * <li> "VERSION_NUM": Returns GDAL_VERSION_NUM formatted as a string.  ie. "1170"
+ * <li> "VERSION_NUM": Returns GDAL_VERSION_NUM formatted as a string.  i.e. "1170"
  *      Note: starting with GDAL 1.10, this string will be longer than 4 characters.
  * <li> "RELEASE_DATE": Returns GDAL_RELEASE_DATE formatted as a string.  
- * ie. "20020416".
- * <li> "RELEASE_NAME": Returns the GDAL_RELEASE_NAME. ie. "1.1.7"
+ * i.e. "20020416".
+ * <li> "RELEASE_NAME": Returns the GDAL_RELEASE_NAME. i.e. "1.1.7"
  * <li> "--version": Returns one line version message suitable for use in 
- * response to --version requests.  ie. "GDAL 1.1.7, released 2002/04/16"
+ * response to --version requests.  i.e. "GDAL 1.1.7, released 2002/04/16"
  * <li> "LICENCE": Returns the content of the LICENSE.TXT file from the GDAL_DATA directory.
  * </ul>
  *
@@ -1167,7 +1167,7 @@ public class gdal:public static String VersionInfo(String request)
 /**
  * Get runtime version information.
  *
- * @return a string containing GDAL_VERSION_NUM formatted as a string.  ie. "1170"
+ * @return a string containing GDAL_VERSION_NUM formatted as a string.  i.e. "1170"
  *
  * @since Java bindings 1.7.0
  */
@@ -1234,7 +1234,7 @@ public class gdal:public static int GetCacheUsed()
 /**
  * Get data type size in bits.
  * <p>
- * Returns the size of a a GDT_* type <b>in bits</b>, not bytes!
+ * Returns the size of a GDT_* type <b>in bits</b>, not bytes!
  *
  * @param eDataType type, such as gdalconst.GDT_Byte. 
  * @return the number of bits or zero if it is not recognised.
@@ -1420,7 +1420,7 @@ public class gdal:public static Dataset OpenShared(String name)
  * exotic drivers this may not refer to a physical file, but instead contain
  * information for the driver on how to access a dataset.
  *
- * @param fileList a veector of strings.
+ * @param fileList a vector of strings.
  * These strings are filenames that are auxiliary to the main filename. The passed
  * value may be null.
  *
@@ -1674,7 +1674,7 @@ public class ColorTable:public int GetCount()
 /**
  * Fetch palette interpretation.
  * <p>
- * The returned value is used to interprete the values in the GDALColorEntry.
+ * The returned value is used to interpret the values in the GDALColorEntry.
  *
  * @return palette interpretation enumeration value, usually gdalconst.GPI_RGB. 
  */
@@ -2042,10 +2042,10 @@ public class Dataset:public java.util.Vector GetGCPs()
  * <p>
  * This method assigns the passed set of GCPs to this dataset, as well as
  * setting their coordinate system.  Internally copies are made of the
- * coordinate system and list of points, so the caller remains resposible for
+ * coordinate system and list of points, so the caller remains responsible for
  * deallocating these arguments if appropriate. 
  * <p>
- * Most formats do not support setting of GCPs, even foramts that can 
+ * Most formats do not support setting of GCPs, even formats that can 
  * handle GCPs.  These formats will return CE_Failure. 
  *
  * @param gcpArray array of GCP objects being assigned
@@ -2080,14 +2080,14 @@ public class Dataset:public int GetRasterXSize()
 /**
  * Fetch raster height in pixels.
  *
- * @return the heigt in pixels of raster bands in this Dataset.
+ * @return the height in pixels of raster bands in this Dataset.
  */
 public class Dataset:public int getRasterYSize()
 
 /**
  * Fetch raster height in pixels.
  *
- * @return the heigt in pixels of raster bands in this Dataset.
+ * @return the height in pixels of raster bands in this Dataset.
  *
  * @since Java bindings 1.7.0
  */
@@ -2993,7 +2993,7 @@ public class Band:public int getDataType()
  * Fetch default raster histogram. 
  * <p>
  * The default method in GDALRasterBand will compute a default histogram. This
- * method is overriden by derived classes (such as GDALPamRasterBand, VRTDataset, HFADataset...)
+ * method is overridden by derived classes (such as GDALPamRasterBand, VRTDataset, HFADataset...)
  * that may be able to fetch efficiently an already stored histogram.
  * <p>
  * For example,
@@ -3352,7 +3352,7 @@ public class Band:public int GetRasterDataType()
  * subset of image tiles may be used in computing the statistics.  
  * <p>
  * If force is false results will only be returned if it can be done 
- * quickly (ie. without scanning the data).  If force is false and 
+ * quickly (i.e. without scanning the data).  If force is false and 
  * results cannot be returned efficiently, the method will return CE_Warning
  * but no warning will have been issued.   This is a non-standard use of
  * the CE_Warning return value to indicate "nothing done". 
@@ -4892,7 +4892,7 @@ public class org.gdal.gdal.Driver:public Dataset Create(String name, int xsize,
  *
  * @param name the name for the new dataset. 
  * @param src_ds the dataset being duplicated. 
- * @param strict 1 if the copy must be strictly equivelent, or more
+ * @param strict 1 if the copy must be strictly equivalent, or more
  * normally 0 indicating that the copy may adapt as needed for the 
  * output format. 
  * @param options additional format dependent options controlling 
@@ -5101,7 +5101,7 @@ public class ProgressCallback:public int run(double dfComplete, String message)
   * Every 2.5% of progress another number or period is emitted.  Note that
   * GDALTermProgress() uses internal static data to keep track of the last
   * percentage reported and will get confused if two terminal based progress
-  * reportings are active at the same time eithin in a single thread or across multiple threads.
+  * reportings are active at the same time either in in a single thread or across multiple threads.
   * <p>
   * Example :
   * <pre>
@@ -5569,7 +5569,7 @@ public interface gdalconstConstants:public final static int CPLES_BackslashQuota
  * CPLES_XML(1).
  * <p>
  * This scheme converts the '<', '<' and '&' characters into
- * their XML/HTML equivelent (>, < and &) making a string safe
+ * their XML/HTML equivalent (>, < and &) making a string safe
  * to embed as CDATA within an XML element.  The '\\0' is not escaped and 
  * should not be included in the input.
  */
@@ -6056,7 +6056,7 @@ public class org.gdal.ogr.Driver:public int DeleteDataSource(String name)
  </ul>
  <p>
  The constant forms of the capability names should be used in preference
- to the strings themselves to avoid mispelling.
+ to the strings themselves to avoid misspelling.
 
  @param cap the capability to test.
 
@@ -6261,7 +6261,7 @@ public class DataSource:public int DeleteLayer(int index)
  ReleaseResultsSet() before the data source is closed  (destroyed).
  <p>
  For more information on the SQL dialect supported internally by OGR
- review the <a href="ogr_sql.html">OGR SQL</a> document.  Some drivers (ie.
+ review the <a href="ogr_sql.html">OGR SQL</a> document.  Some drivers (i.e.
  Oracle and PostGIS) pass the SQL directly through to the underlying RDBMS.
 
  @param statement the SQL statement to execute. 
@@ -6346,7 +6346,7 @@ public class DataSource:public int SyncToDisk()
  </ul>
  <p>
  The constant forms of the capability names should be used in preference
- to the strings themselves to avoid mispelling.
+ to the strings themselves to avoid misspelling.
 
  @param cap the capability to test.
 
@@ -6500,12 +6500,12 @@ on a real layer. Internally the FeatureDefn for the layer will be updated
 to reflect the new field.  Applications should never modify the FeatureDefn
 used by a layer directly.
 <p>
-This method should not be called while there are feature objects in existance that
+This method should not be called while there are feature objects in existence that
 were obtained or created with the previous layer definition.
 <p>
 Not all drivers support this method. You can query a layer to check if it supports it
 with the OLCCreateField capability. Some drivers may only support this method while
-there are still no features in the layer. When it is supported, the existings features of the
+there are still no features in the layer. When it is supported, the existing features of the
 backing file/database should be updated accordingly.
 
 @param field_def field definition to write to disk. 
@@ -6534,12 +6534,12 @@ on a real layer. Internally the FeatureDefn for the layer will be updated
 to reflect the deleted field.  Applications should never modify the FeatureDefn
 used by a layer directly.
 <p>
-This method should not be called while there are feature objects in existance that
+This method should not be called while there are feature objects in existence that
 were obtained or created with the previous layer definition.
 <p>
 Not all drivers support this method. You can query a layer to check if it supports it
 with the OLCDeleteField capability. Some drivers may only support this method while
-there are still no features in the layer. When it is supported, the existings features of the
+there are still no features in the layer. When it is supported, the existing features of the
 backing file/database should be updated accordingly.
 
 @param iField index of the field to delete.
@@ -6558,7 +6558,7 @@ on a real layer. Internally the FeatureDefn for the layer will be updated
 to reflect the reordering of the fields.  Applications should never modify the FeatureDefn
 used by a layer directly.
 <p>
-This method should not be called while there are feature objects in existance that
+This method should not be called while there are feature objects in existence that
 were obtained or created with the previous layer definition.
 <p>
 panMap is such that,for each field definition at position i after reordering,
@@ -6569,7 +6569,7 @@ ReorderFields(new Integer[]{0,2,3,1,4}) will reorder them as "0","2","3","1","4"
 <p>
 Not all drivers support this method. You can query a layer to check if it supports it
 with the OLCReorderFields capability. Some drivers may only support this method while
-there are still no features in the layer. When it is supported, the existings features of the
+there are still no features in the layer. When it is supported, the existing features of the
 backing file/database should be updated accordingly.
 
 @param panMap an array of GetLayerDefn().GetFieldCount() elements which
@@ -6584,7 +6584,7 @@ public class Layer:public int ReorderFields( int[] panMap )
 /**
 Reorder an existing field on a layer.
 <p>
-This method is a conveniency wrapper of ReorderFields() dedicated to move a single field.
+This method is a convenience wrapper of ReorderFields() dedicated to move a single field.
 It is a non-virtual method, so drivers should implement ReorderFields() instead.
 <p>
 You must use this to reorder existing fields
@@ -6592,7 +6592,7 @@ on a real layer. Internally the FeatureDefn for the layer will be updated
 to reflect the reordering of the fields.  Applications should never modify the FeatureDefn
 used by a layer directly.
 <p>
-This method should not be called while there are feature objects in existance that
+This method should not be called while there are feature objects in existence that
 were obtained or created with the previous layer definition.
 <p>
 The field definition that was at initial position iOldFieldPos will be moved at
@@ -6603,7 +6603,7 @@ ReorderField(1, 3) will reorder them as "0","2","3","1","4".
 <p>
 Not all drivers support this method. You can query a layer to check if it supports it
 with the OLCReorderFields capability. Some drivers may only support this method while
-there are still no features in the layer. When it is supported, the existings features of the
+there are still no features in the layer. When it is supported, the existing features of the
 backing file/database should be updated accordingly.
 
 @param iOldFieldPos previous position of the field to move. Must be in the range [0,GetFieldCount()-1].
@@ -6623,12 +6623,12 @@ Internally the FeatureDefn for the layer will be updated
 to reflect the altered field.  Applications should never modify the FeatureDefn
 used by a layer directly.
 <p>
-This method should not be called while there are feature objects in existance that
+This method should not be called while there are feature objects in existence that
 were obtained or created with the previous layer definition.
 <p>
 Not all drivers support this method. You can query a layer to check if it supports it
 with the OLCAlterFieldDefn capability. Some drivers may only support this method while
-there are still no features in the layer. When it is supported, the existings features of the
+there are still no features in the layer. When it is supported, the existing features of the
 backing file/database should be updated accordingly. Some drivers might also not support
 all update flags.
 
@@ -6649,7 +6649,7 @@ public class Layer:public int AlterFieldDefn( int iField, FieldDefn newFieldDefn
  <p>
  Returns the extent (MBR) of the data in the layer.  If force is 0,
  and it would be expensive to establish the extent then a RuntimeException
- will be throwned indicating that the extent isn't know.  If force is 
+ will be thrown indicating that the extent is not known.  If force is 
  1 then some implementations will actually scan the entire layer once
  to compute the MBR of all the features in the layer.
  <p>
@@ -7104,12 +7104,12 @@ should build and maintain it's own spatial index for features in this layer.<p>
 
  <li> <b>OLCFastFeatureCount</b> / "FastFeatureCount": 
 true if this layer can return a feature
-count (via GetFeatureCount()) efficiently ... ie. without counting
+count (via GetFeatureCount()) efficiently, i.e. without counting
 the features.  In some cases this will return true until a spatial filter is
 installed after which it will return false.<p>
 
  <li> <b>OLCFastGetExtent</b> / "FastGetExtent": 
-true if this layer can return its data extent (via GetExtent()) efficiently ... ie. without scanning all the features.  In some cases this will return true until a spatial filter is installed after which it will return false.<p>
+true if this layer can return its data extent (via GetExtent()) efficiently, i.e. without scanning all the features.  In some cases this will return true until a spatial filter is installed after which it will return false.<p>
 
  <li> <b>OLCFastSetNextByIndex</b> / "FastSetNextByIndex": 
 true if this layer can perform the SetNextByIndex() call efficiently, otherwise
@@ -7149,7 +7149,7 @@ is uncertain, though it might still be UTF-8.<p>
  @param cap the name of the capability to test.
 
  @return true if the layer has the requested capability, or false otherwise.
-Layers will return false for any unrecognised capabilities.<p>
+Layers will return false for any unrecognized capabilities.<p>
 
 */
 public class Layer:public boolean TestCapability(String cap)
@@ -8179,7 +8179,7 @@ public class Geometry:public Geometry(int eGeometryType)
 /** 
  * Create a new geometry.
  * <p>
- * The geometry can be instanciated by 4 different and exclusive way :
+ * The geometry can be instantiated by 4 different and exclusive way:
  * <ul>
  * <li> By specifying the geometry type (ogr.wkbPoint, etc..)</li>
  * <li> By specifying the well known text representation (wkt)</li>
@@ -8413,7 +8413,7 @@ public class Geometry:public Geometry ConvexHull()
  *
  * @param gml The GML fragment for the geometry.
  *
- * @return a geometry on succes, or null on error.
+ * @return a geometry on success, or null on error.
  *
  * @since Java bindings 1.7.0
  */
@@ -8424,7 +8424,7 @@ public class Geometry:public static Geometry CreateFromGML(String gml)
  *
  * @param json GeoJSON content
  *
- * @return a geometry on succes, or null on error.
+ * @return a geometry on success, or null on error.
  *
  * @since Java bindings 1.7.0
  */
@@ -8436,7 +8436,7 @@ public class Geometry:public static Geometry CreateFromJson(String json)
  *
  * @param wkb input BLOB data.
  *
- * @return a geometry on succes, or null on error.
+ * @return a geometry on success, or null on error.
  *
  * @since Java bindings 1.7.0
  */
@@ -8449,7 +8449,7 @@ public class Geometry:public static Geometry CreateFromWkb(byte[] wkb)
  * @param wkt string containing well known text
  *                representation of the geometry to be created.
  *
- * @return a geometry on succes, or null on error.
+ * @return a geometry on success, or null on error.
  *
  * @since Java bindings 1.7.0
  */
@@ -8466,7 +8466,7 @@ public class Geometry:public static Geometry CreateFromWkt(String wkt)
  *
  * @param other the geometry to compare to this geometry.
  *
- * @return true if they are crossing, otherwise false.  
+ * @return true if they are crossing, otherwise false.
  */
 public class Geometry:public boolean Crosses(Geometry other)
 
@@ -8792,7 +8792,7 @@ public class Geometry:public String GetGeometryName()
  * <p>
  * This function returns an handle to a geometry within the container.
  * The returned geometry remains owned by the container, and should not be
- * modified.  The handle is only valid untill the next change to the
+ * modified.  The handle is only valid until the next change to the
  * geometry container.  Use Clone() to make a copy.
  * <p>
  * This function relates to the SFCOM 
@@ -8970,7 +8970,7 @@ public class Geometry:public boolean Intersect(Geometry other)
  * Do these features intersect?
  * <p>
  * Determines whether two geometries intersect.  If GEOS is enabled, then
- * this is done in rigerous fashion otherwise true is returned if the
+ * this is done in rigorous fashion otherwise true is returned if the
  * envelopes (bounding boxes) of the two features overlap.
  * <p>
  * The geom argument may be safely null, but in this case the method
@@ -9380,7 +9380,7 @@ public class FeatureDefn:public FeatureDefn(String name)
  * function directly, but use Layer.<a href="Layer.html#CreateField(org.gdal.ogr.FieldDefn)">CreateField()</a> instead.
  * <p>
  * This method should only be called while there are no Feature
- * objects in existance based on this FeatureDefn.  The FieldDefn
+ * objects in existence based on this FeatureDefn.  The FieldDefn
  * passed in is copied, and remains the responsibility of the caller.
  *
  * @param defn the definition of the new field.
@@ -9661,7 +9661,7 @@ public class ogr
 /**
  * Use exceptions instead of error return codes.
  * <p>
- * This is the default behavious : methods that in C/C++ return an OGRErr return code
+ * This is the default behaviour : methods that in C/C++ return an OGRErr return code
  * would throw a RuntimeException() in case the code it is different
  * from ogr.OGRERR_NONE. By calling this method, you can get
  * back to that original state if DontUseExceptions() was called in-between.
@@ -10144,7 +10144,7 @@ public class ogr:public static Geometry ForceToMultiLineString(Geometry geom)
 /* Class SpatialReference */
 
 /**
- * This class respresents a OpenGIS Spatial Reference System, and contains
+ * This class represents an OpenGIS Spatial Reference System, and contains
  * methods for converting between this object organization and well known
  * text (WKT) format.  This object is reference counted as one instance of
  * the object is normally shared between many Geometry objects.
@@ -10164,7 +10164,7 @@ public class SpatialReference
  * Constructor.
  * <p>
  * This constructor takes an optional string argument which if passed
- * should be a WKT representation of an SRS.  Passing this is equivelent
+ * should be a WKT representation of an SRS.  Passing this is equivalent
  * to not passing it, and then calling importFromWkt() with the WKT string.
  * <p>
  * Note that newly created objects are given a reference count of one. 
@@ -10199,7 +10199,7 @@ public class SpatialReference:public String __str__()
  * where an aspect of the coordinate system can be easily and safely 
  * corresponded with an EPSG identifier.  In practice, this method will 
  * evolve over time.  In theory it can add authority nodes for any object
- * (ie. spheroid, datum, GEOGCS, units, and PROJCS) that could have an 
+ * (i.e. spheroid, datum, GEOGCS, units, and PROJCS) that could have an 
  * authority node.  Mostly this is useful to inserting appropriate 
  * PROJCS codes for common formulations (like UTM n WGS84). 
  * <p>
@@ -10278,7 +10278,7 @@ public class SpatialReference:public int ExportToMICoordSys(String[] argout)
 public class SpatialReference:public int ExportToPCI(String[] proj, String[] units, double[] parms)
 
 /**
- * Convert this SRS into a a nicely formatted WKT string for display to a person.
+ * Convert this SRS into a nicely formatted WKT string for display to a person.
  * <p>
  * Same as below with simplify == 0 and the string is returned as a return value
  *
@@ -10289,7 +10289,7 @@ public class SpatialReference:public int ExportToPCI(String[] proj, String[] uni
 public class SpatialReference:public String ExportToPrettyWkt()
 
 /**
- * Convert this SRS into a a nicely formatted WKT string for display to a person.
+ * Convert this SRS into a nicely formatted WKT string for display to a person.
  * <p>
  * Same as below but the string is returned as a return value
  *
@@ -10300,7 +10300,7 @@ public class SpatialReference:public String ExportToPrettyWkt()
 public class SpatialReference:public String ExportToPrettyWkt(int simplify)
 
 /**
- * Convert this SRS into a a nicely formatted WKT string for display to a person.
+ * Convert this SRS into a nicely formatted WKT string for display to a person.
  * <p>
  * Same as below with simplify == 0.
  *
@@ -10311,7 +10311,7 @@ public class SpatialReference:public String ExportToPrettyWkt(int simplify)
 public class SpatialReference:public int ExportToPrettyWkt(String[] argout)
 
 /**
- * Convert this SRS into a a nicely formatted WKT string for display to a person.
+ * Convert this SRS into a nicely formatted WKT string for display to a person.
  *
  * @param argout an already allocated array of 1 string to receive the output
  * @param simplify 1 if the AXIS, AUTHORITY and EXTENSION nodes should be stripped off
@@ -10438,7 +10438,7 @@ public class SpatialReference:public int ExportToXML(String[] argout, String dia
  * WKT is valid. 
  * <p>
  * This method should be expected to evolve over time to as problems are
- * discovered.  The following are amoung the fixup actions this method will
+ * discovered.  The following are among the fixup actions this method will
  * take:
  * <ul>
  * <li>Fixup the ordering of nodes to match the BNF WKT ordering, using
@@ -10513,7 +10513,7 @@ public class SpatialReference:public String GetAttrValue(String name, int child)
  * code values should be integral.
  *
  * @param target_key the partial or complete path to the node to 
- * get an authority from.  ie. "PROJCS", "GEOGCS", "GEOGCS|UNIT" or null to 
+ * get an authority from.  i.e. "PROJCS", "GEOGCS", "GEOGCS|UNIT" or null to 
  * search for an authority node on the root element.
  *
  * @return value code from authority node, or null on failure.
@@ -10529,7 +10529,7 @@ public class SpatialReference:public String GetAuthorityCode(String target_key)
  * The most common authority is "EPSG".
  *
  * @param target_key the partial or complete path to the node to 
- * get an authority from.  ie. "PROJCS", "GEOGCS", "GEOGCS|UNIT" or null to 
+ * get an authority from.  i.e. "PROJCS", "GEOGCS", "GEOGCS|UNIT" or null to 
  * search for an authority node on the root element.
  *
  * @return value code from authority node, or null on failure.
@@ -10667,13 +10667,13 @@ public class SpatialReference:public int ImportFromEPSG(int nCode)
  * as the newer pseudo-OGC WKT .prj files.  Note that new style .prj files
  * are in OGC WKT format, but require some manipulation to correct datum
  * names, and units on some projection parameters.  This is addressed within
- * importFromESRI() by an automatical call to morphFromESRI(). 
+ * importFromESRI() by an automatic call to morphFromESRI(). 
  * <p>
  * Currently only GEOGRAPHIC, UTM, STATEPLANE, GREATBRITIAN_GRID, ALBERS, 
  * EQUIDISTANT_CONIC, and TRANSVERSE (mercator) projections are supported
  * from old style files. 
  * <p>
- * At this time there is no equivelent exportToESRI() method.  Writing old
+ * At this time there is no equivalent exportToESRI() method.  Writing old
  * style .prj files is not supported by OGRSpatialReference. However the
  * morphToESRI() and exportToWkt() methods can be used to generate output
  * suitable to write to new style (Arc 8) .prj files. 
@@ -10764,16 +10764,16 @@ public class SpatialReference:public int ImportFromPCI(String proj, String units
  * <p>
  * The OGRSpatialReference is initialized from the passed PROJ.4 style
  * coordinate system string.  In addition to many +proj formulations which
- * have OGC equivelents, it is also possible to import "+init=epsg:n" style
+ * have OGC equivalents, it is also possible to import "+init=epsg:n" style
  * definitions.  These are passed to importFromEPSG().  Other init strings
  * (such as the state plane zones) are not currently supported.   
  * <p><pre>
  * Example:
  *   pszProj4 = "+proj=utm +zone=11 +datum=WGS84" 
  * </pre><p>
- * Some parameters, such as grids, recognised by PROJ.4 may not be well
+ * Some parameters, such as grids, recognized by PROJ.4 may not be well
  * understood and translated into the OGRSpatialReference model. It is possible
- * to add the +wktext parameter which is a special keyword that OGR recognises
+ * to add the +wktext parameter which is a special keyword that OGR recognizes
  * as meaning "embed the entire PROJ.4 string in the WKT and use it literally
  * when converting back to PROJ.4 format".
  * <p><pre>
@@ -11223,7 +11223,7 @@ public class SpatialReference:public int SetAngularUnits(String name, double to_
  * Set attribute value in spatial reference.
  * <p>
  * Missing intermediate nodes in the path will be created if not already
- * in existance.  If the attribute has no children one will be created and
+ * in existence.  If the attribute has no children one will be created and
  * assigned the value otherwise the zeroth child will be assigned the value.
  *
  * @param name full path to attribute to be set.  For instance
@@ -11241,7 +11241,7 @@ public class SpatialReference:public int SetAttrValue(String name, String value)
  * Set the authority for a node.
  *
  * @param target_key the partial or complete path to the node to 
- * set an authority on.  ie. "PROJCS", "GEOGCS" or "GEOGCS|UNIT".
+ * set an authority on.  i.e. "PROJCS", "GEOGCS" or "GEOGCS|UNIT".
  *
  * @param authority authority name, such as "EPSG".
  *
@@ -11303,7 +11303,7 @@ public class SpatialReference:public int SetGeocCS()
  * <p>
  * This method is will ensure a GEOCCS node is created as the root,
  * and set the provided name on it.  If used on a GEOGCS coordinate system,
- * the DATUM and PRIMEM nodes from the GEOGCS will be tarnsferred over to
+ * the DATUM and PRIMEM nodes from the GEOGCS will be transferred over to
  * the GEOGCS.
  *
  * @param name the user visible name to assign. Not used as a key. May be null
@@ -11382,7 +11382,7 @@ public class SpatialReference:public int SetGeogCS(String pszGeogName, String ps
  * This can be computed from the semi minor axis as 
  * 1/f = 1.0 / (1.0 - semiminor/semimajor).
  *
- * @param pszPMName the name of the prime merdidian (not to serve as a key)
+ * @param pszPMName the name of the prime meridian (not to serve as a key)
  * If this is null a default value of "Greenwich" will be used. 
  * 
  * @param dfPMOffset the longitude of greenwich relative to this prime
@@ -11557,7 +11557,7 @@ public class SpatialReference:public int SetStatePlane(int zone, int is_nad83, S
  * and return OGRERR_FAILURE.
  *
  * @param zone State plane zone number, in the USGS numbering scheme (as
- * dinstinct from the Arc/Info and Erdas numbering scheme. 
+ * distinct from the Arc/Info and Erdas numbering scheme. 
  *
  * @param is_nad83 1 if the NAD83 zone definition should be used or 0
  * if the NAD27 zone definition should be used.  
@@ -11578,7 +11578,7 @@ public class SpatialReference:public int SetStatePlane(int zone, int is_nad83, S
  * This method creates a UNIT subnode with the specified values as a
  * child of the target node.
  *
- * @param target the keyword to set the linear units for.  ie. "PROJCS" or "VERT_CS"
+ * @param target the keyword to set the linear units for.  i.e. "PROJCS" or "VERT_CS"
  *
  * @param name the units name to be used.  Some preferred units
  * names can be found in ogr_srs_api.h such as SRS_UL_METER, SRS_UL_FOOT
@@ -11874,7 +11874,7 @@ public class osr
 /**
  * Use exceptions instead of error return codes.
  * <p>
- * This is the default behavious : methods that in C/C++ return an OGRErr return code
+ * This is the default behaviour : methods that in C/C++ return an OGRErr return code
  * would throw a RuntimeException() in case the code it is different
  * from ogr.OGRERR_NONE. By calling this method, you can get
  * back to that original state if DontUseExceptions() was called in-between.
diff --git a/swig/java/makefile.vc b/swig/java/makefile.vc
index de76c23..b9d43ed 100644
--- a/swig/java/makefile.vc
+++ b/swig/java/makefile.vc
@@ -10,9 +10,9 @@ GDALLIB	=    $(GDAL_ROOT)\gdal.lib
 
 JAVA_RUN = $(JAVA) -Djava.library.path=. -cp gdal.jar;build\apps
 
-OBJ	=	gdal_wrap.obj gdalconst_wrap.obj ogr_wrap.obj osr_wrap.obj
+OBJ	=	gdal_wrap.obj gdalconst_wrap.obj ogr_wrap.obj osr_wrap.obj gnm_wrap.obj
 
-all:  ogr_dir gdal_dir const_dir osr_dir
+all:  ogr_dir gdal_dir const_dir osr_dir gnm_dir
 	set JAVA_HOME="$(JAVA_HOME)"
 	$(ANT_HOME)\bin\ant
 
@@ -24,6 +24,13 @@ ogr_dir:
 	link ogr_wrap.obj $(GDALLIB) /out:ogrjni.dll /DLL
 	if exist ogrjni.dll.manifest mt -manifest ogrjni.dll.manifest -outputresource:ogrjni.dll;2
 
+gnm_dir:
+	cd gnm
+	$(MAKE) /f makefile.vc
+	cd ..
+	link gnm_wrap.obj $(GDALLIB) /out:gnmjni.dll /DLL
+	if exist gnmjni.dll.manifest mt -manifest gnmjni.dll.manifest -outputresource:gnmjni.dll;2
+
 gdal_dir:
 	cd gdal
 	$(MAKE) /f makefile.vc
@@ -69,6 +76,9 @@ clean:
 	cd ogr
 	$(MAKE) /f makefile.vc clean
 	cd ..
+	cd gnm
+	$(MAKE) /f makefile.vc clean
+	cd ..
 	cd const
 	$(MAKE) /f makefile.vc clean
 	cd ..
diff --git a/swig/makefile.vc b/swig/makefile.vc
index 9d565f7..868f5f8 100644
--- a/swig/makefile.vc
+++ b/swig/makefile.vc
@@ -12,6 +12,8 @@ gdalvars:
 
 python: gdalvars 
         cd python
+        -del setup_vars.ini
+        echo 'GNM_ENABLED=$(GNM_ENABLED)' > setup_vars.ini
         $(SWIG) -python -modern -new_repr -o extensions/gdalconst_wrap.c -outdir osgeo ..\include\gdalconst.i
         $(SWIG) -c++ -python -modern -new_repr -I../include/python -I../include/python/docs -o extensions/gdal_wrap.cpp -outdir osgeo ..\include\gdal.i
         $(SWIG) -c++ -python -modern -new_repr -I../include/python -I../include/python/docs -o extensions/osr_wrap.cpp -outdir osgeo ..\include\osr.i
@@ -50,6 +52,12 @@ java: gdalvars
         cd const
         $(SWIG) -java -c++ -package org.gdal.gdalconst -outdir ../org/gdal/gdalconst -I../../include/java -o gdalconst_wrap.cpp ../../../include/gdalconst.i
         cd ..
+		cd org\gdal
+        if not exist gnm mkdir gnm
+        cd ../../
+		cd gnm
+        $(SWIG) -java -c++ -package org.gdal.gnm -outdir ../org/gdal/gnm -I../../include/java -o gnm_wrap.cpp ../../../include/gnm.i
+        cd ..
         $(MAKE) /f makefile.vc
 
 #ruby: gdalvars
diff --git a/swig/perl/Changes b/swig/perl/Changes
new file mode 100644
index 0000000..e67ce2e
--- /dev/null
+++ b/swig/perl/Changes
@@ -0,0 +1,73 @@
+2.1 <release date here>
+  [Enhancements/changes in the API]
+  * The output from a GDAL driver can be redirected to a write method
+    of a class.
+  * The methods of Geo::GDAL::VSIF (the GDAL file system wrapper) can
+    be imported.
+  * New methods in Dataset: ComputeColorTable, Dither, DEMProcessing,
+    Grid, Info, Nearblack, Rasterize, Translate, Warp, Warped.
+  * New methods in Band: Distance Polygonize and Sieve
+  * New methods in Dataset: ReadTile and WriteTile, these return
+    arrays with three dimensions
+  * ReadTile and WriteTile methods (Band, Dataset) now accept tile
+    size and resampling algorithm
+  * The GDAL XML API has been put into a new class Geo::GDAL::XML. The
+    old API is still there (like for many other enhancements), it is
+    just removed from the documentation to clean up the API of the
+    class Geo::GDAL.
+  * Geo::OGR::Driver and Geo::OGR::DataSource are now pure Perl
+    interfaces to GDAL classes, which do the actual work. This should
+    have been done in 2.0, which merged vector and raster driver and
+    dataset classes. Geo::OGR::Driver is needed for opening, creating,
+    and copying vector datasets but Geo::OGR::DataSource is just a
+    legacy class.
+  * New pure Perl class Geo::GDAL::Extent, which is an array [xmin,
+    ymin, xmax, ymax] to ease some tasks
+  * A new API for GDAL error messages. All errors that are emitted in
+    GDAL during the execution of a call are stored in a stack (array)
+    in Geo::GDAL. The error stack (possibly a multiline string) can be
+    retrieved using the subroutine Geo::GDAL::errstr, which also
+    clears the stack.
+  * The named parameter calling system has been integrated into one
+    subroutine in the bindings, which unifies its behavior. The named
+    parameters capability has been added to some methods.
+  * All errors which are not emitted by Perl or by Swig are now
+    confessed (the stack trace is included), even those that happen
+    within the typemaps (C code between Perl and Swig interface).
+  * The bindings now require at least Perl 5.10, at least for the null
+    coalescing operator.
+  * File::Share can now be used to obtain a file containing the path
+    to GDAL support files.
+  * Add support for 64bit integers if the OS supports them.
+
+  [Bug fixes]
+  * Fix memory leak: CSLAdd* functions copy the parameter string.
+  * Fix the use of EXTEND. Returning large arrays caused core dumps.
+  * Perl bindings have GintBig, so the 64bit versions should be used.
+  * Review of parent - child relationships and their management
+  * Fix a bug in Layer DESTROY.
+  * Fix Geotransform::FromGCPs and typemap for GCP array input. Add
+    tests for these.
+  * Fix sending utf8 from Perl to GDAL. Should also remove some
+    "uninitialized value" warnings.
+  * Fix a bug in Dataset->SpatialReference.
+  * Fix tests which fail if Perl uses longdouble.
+  * The shadow feature was not working for Feature class. Bugfix for
+    Geo::OGR::Feature->new().
+  * Fix #6050: string formatting in croak.
+  * Fix #6039 use standard C comments in swig bindings.
+
+  [Other things]
+  * Many Documentation enhancements and fixes.
+  * Many new tests.
+  * Enhancements to Makefile.PL for independent builds & automatic tests.
+  * Add basic POD to GDAL.pm to make this module look nice in metacpan.
+  * Edit Makefile.PL due to rt.cpan.org requests 91636 and 107023.
+  * Perl Makefile.PL: add support for all hardening buildflags (patch
+    by Bas Couwenberg, #5998).
+
+2.0 Jun 14, 2015
+
+1.11 Apr 16, 2014
+
+1.10 Apr 24, 2013
diff --git a/swig/perl/Changes-in-the-API-in-2.0 b/swig/perl/Changes-in-the-API-in-2.0
index 6513b40..dd3c6a1 100644
--- a/swig/perl/Changes-in-the-API-in-2.0
+++ b/swig/perl/Changes-in-the-API-in-2.0
@@ -11,7 +11,7 @@ constructors:
 
     Geo::GDAL does not use the "create" constructors any more.  All
     constructors are called "new" and use the new syntax.  This
-    applieds to classes Geo::GDAL::ColorTable, Geo::OGR::Feature,
+    applies to classes Geo::GDAL::ColorTable, Geo::OGR::Feature,
     Geo::OGR::FeatureDefn, Geo::OGR::FieldDefn,
     Geo::OGR::GeomFieldDefn, Geo::OGR::Geometry, and
     Geo::OSR::SpatialReference.
diff --git a/swig/perl/Doxyfile b/swig/perl/Doxyfile
index c56fef1..d24c7d5 100644
--- a/swig/perl/Doxyfile
+++ b/swig/perl/Doxyfile
@@ -38,7 +38,7 @@ PROJECT_NAME           = Geo::GDAL
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = 2.0
+PROJECT_NUMBER         = 2.1
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
@@ -287,7 +287,7 @@ EXTENSION_MAPPING      =
 # documentation. See http://daringfireball.net/projects/markdown/ for details.
 # The output of markdown processing is further processed by doxygen, so you can
 # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
-# case of backward compatibilities issues.
+# case of backward compatibility issues.
 # The default value is: YES.
 
 MARKDOWN_SUPPORT       = YES
@@ -1398,7 +1398,7 @@ EXT_LINKS_IN_WINDOW    = NO
 
 FORMULA_FONTSIZE       = 10
 
-# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
 # generated for formulas are transparent PNGs. Transparent PNGs are not
 # supported properly for IE 6.0, but are supported on all modern browsers.
 #
@@ -1958,7 +1958,7 @@ PREDEFINED             =
 EXPAND_AS_DEFINED      =
 
 # If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
-# remove all refrences to function-like macros that are alone on a line, have an
+# remove all references to function-like macros that are alone on a line, have an
 # all uppercase name, and do not end with a semicolon. Such function macros are
 # typically used for boiler-plate code, and will confuse the parser if not
 # removed.
diff --git a/swig/perl/GNUmakefile b/swig/perl/GNUmakefile
index fb668c0..c02f1e0 100644
--- a/swig/perl/GNUmakefile
+++ b/swig/perl/GNUmakefile
@@ -16,12 +16,14 @@ generate: ${WRAPPERS}
 	if [ -f Const.pm ]; then mv Const.pm lib/Geo/GDAL; fi
 	if [ -f OGR.pm ]; then mv OGR.pm lib/Geo; fi
 	if [ -f OSR.pm ]; then mv OSR.pm lib/Geo; fi
+	if [ -f GNM.pm ]; then mv GNM.pm lib/Geo; fi
 
 build: gdal_wrap.cc Makefile_Geo__GDAL
 	$(MAKE) -f Makefile_Geo__GDAL
 	$(MAKE) -f Makefile_Geo__GDAL__Const
-	$(MAKE) -f Makefile_Geo__OGR
 	$(MAKE) -f Makefile_Geo__OSR
+	if [ -f Makefile_Geo__OGR ]; then $(MAKE) -f Makefile_Geo__OGR; fi
+	if [ -f Makefile_Geo__GNM ]; then $(MAKE) -f Makefile_Geo__GNM; fi
 
 gdal_wrap.cc: generate
 
@@ -34,8 +36,9 @@ test: build
 install: build
 	$(MAKE) -f Makefile_Geo__GDAL install
 	$(MAKE) -f Makefile_Geo__GDAL__Const install
-	$(MAKE) -f Makefile_Geo__OGR install
 	$(MAKE) -f Makefile_Geo__OSR install
+	if [ -f Makefile_Geo__OGR ]; then $(MAKE) -f Makefile_Geo__OGR install; fi
+	if [ -f Makefile_Geo__GNM ]; then $(MAKE) -f Makefile_Geo__GNM install; fi
 
 dist: Makefile_Geo__GDAL
 	$(MAKE) -f Makefile_Geo__GDAL dist
@@ -45,15 +48,17 @@ clean:
 	-rm -f gdalconst.bs gdalconst_wrap.o
 	-rm -f ogr.bs ogr_wrap.o
 	-rm -f osr.bs osr_wrap.o
+	-rm -f gnm.bs gnm_wrap.o
 	-rm -rf blib
 	-rm -f pm_to_blib
-	-rm -f Makefile_Geo__GDAL Makefile_Geo__GDAL__Const Makefile_Geo__OGR Makefile_Geo__OSR
+	-rm -f Makefile_Geo__GDAL Makefile_Geo__GDAL__Const Makefile_Geo__OGR Makefile_Geo__OSR Makefile_Geo__GNM
 
 veryclean: clean
 	-rm -f ${WRAPPERS} 
-	-rm -f gdal.pm gdalconst.pm osr.pm ogr.pm
+	-rm -f *.pm
 	-rm -f META.* MYMETA.*
 	-rm -f *.tar.gz
+	-rm -f *.bs
 
 doc: .FORCE
 
diff --git a/swig/perl/MANIFEST b/swig/perl/MANIFEST
index b2507f1..621dc4d 100644
--- a/swig/perl/MANIFEST
+++ b/swig/perl/MANIFEST
@@ -1,4 +1,5 @@
 MANIFEST
+Changes
 Doxyfile
 README
 Makefile
@@ -7,10 +8,12 @@ lib/Geo/GDAL/Const.pm
 lib/Geo/GDAL.pm
 lib/Geo/OGR.pm
 lib/Geo/OSR.pm
+lib/Geo/GNM.pm
 lib/Geo/GDAL/Const.dox
 lib/Geo/GDAL.dox
 lib/Geo/OGR.dox
 lib/Geo/OSR.dox
+lib/Geo/GNM.dox
 t/00.t
 t/01.t
 t/02.t
@@ -18,6 +21,9 @@ t/03.t
 t/gdal.t
 t/ogr.t
 t/osr.t
+t/open.t
+t/utf8.t
+t/gcp.t
 Makefile.PL
 gdalconst_wrap.c
 gdal_wrap.cpp
diff --git a/swig/perl/Makefile.PL b/swig/perl/Makefile.PL
index ac6bdd4..09f250f 100644
--- a/swig/perl/Makefile.PL
+++ b/swig/perl/Makefile.PL
@@ -4,7 +4,6 @@ use File::Basename;
 use ExtUtils::MakeMaker;
 use Config;
 use Cwd;
-#use File::ShareDir::Install;
 
 # pick up our parameters from @ARGV
 my %ARGV;
@@ -59,6 +58,8 @@ if ($ARGV{'--gdal-source-tree'}) {
     $source_tree = $ARGV{'--gdal-source-tree'};
     die "Path '$source_tree' does not exist." unless -e $source_tree && -d $source_tree;
 }
+elsif ($ARGV{'--gdal-source-tree'} eq '0') {
+}
 elsif (-r '../../GDALmake.opt.in') {
     $source_tree = '../..';
     print "Building in source tree.\n" if $source_tree;
@@ -132,7 +133,7 @@ from the version these bindings were developed for (I have
 $my_gdal_version and $config has $gdal_version). 
 You can either
 
-- get GDAL development files from $uri or from whereever you get
+- get GDAL development files from $uri or from wherever you get
   development files for your system,
 
 - specify another gdal-config,
@@ -179,9 +180,6 @@ if ($ARGV{'--debug'}) {
     print "INC = $INC\n";
 }
 
-#install_share 'share';
-#store_datadir_for_tests($source_tree, $config);
-
 for my $module (sort keys %object) {
     my $add = $module;
     $add =~ s/:/_/g;
@@ -228,9 +226,8 @@ for my $module (sort keys %object) {
                        'ExtUtils::MakeMaker' => 0,
                        'Config' => 0,
                        'Cwd' => 0,
-#                       'File::Fetch' => 0,
-#                       'Capture::Tiny' => 0,
-#                       'File::ShareDir::Install' => 0 
+                       'File::Fetch' => 0,
+                       'Capture::Tiny' => 0,
                    },
                    BUILD_REQUIRES => {
                        'strict' => 0,
@@ -238,20 +235,22 @@ for my $module (sort keys %object) {
                        'File::Basename' => 0,
                        'ExtUtils::MakeMaker' => 0,
                        'Config' => 0,
-                       'Cwd' => 0,
-#                       'File::Fetch' => 0,
-#                       'Capture::Tiny' => 0,
-#                       'File::ShareDir::Install' => 0 
+                       'File::Fetch' => 0,
+                       'Capture::Tiny' => 0,
+                       'Cwd' => 0 
                    },
                    PREREQ_PM => {
                        Carp => 0,
                        Encode => 0,
                        'Scalar::Util' => 0,
-                       POSIX => 0 },
+                       POSIX => 0 
+                   },
                    TEST_REQUIRES => {
                        'Scalar::Util' => 0,
-#                       'File::Share' => 0,
-                       'Test::More' => 0 },
+                       'Test::More' => 0,
+                       'Encode' => 0,
+                       POSIX => 0
+                   }
         );
 }
 
@@ -460,24 +459,3 @@ sub parse_libtool_library_file_for_l {
     }
     return $l;
 }
-
-sub store_datadir_for_tests {
-    my ($source_tree, $config) = @_;
-    open(my $fh, ">", "share/gdal-datadir") or die "cannot open > share/gdal-datadir: $!";
-    if ($source_tree) {
-        $source_tree = Cwd::abs_path($source_tree);
-        print $fh "$source_tree/data\n";
-    }
-    elsif (-x $config) {
-        my $datadir;
-        chomp($datadir = `$config --datadir`);
-        print $fh "$datadir\n";
-    }
-    else {
-        print STDERR "I could not set GDAL data directory. Expect problems with tests.\n";
-    }
-    close $fh;
-}
-
-#package MY;
-#use File::ShareDir::Install qw(postamble);
diff --git a/swig/perl/gdal_wrap.cpp b/swig/perl/gdal_wrap.cpp
deleted file mode 100644
index 228620d..0000000
--- a/swig/perl/gdal_wrap.cpp
+++ /dev/null
@@ -1,23512 +0,0 @@
-/* ----------------------------------------------------------------------------
- * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 2.0.12
- *
- * This file is not intended to be easily readable and contains a number of
- * coding conventions designed to improve portability and efficiency. Do not make
- * changes to this file unless you know what you are doing--modify the SWIG
- * interface file instead.
- * ----------------------------------------------------------------------------- */
-
-#define SWIGPERL
-#define SWIG_CASTRANK_MODE
-
-
-#ifdef __cplusplus
-/* SwigValueWrapper is described in swig.swg */
-template<typename T> class SwigValueWrapper {
-  struct SwigMovePointer {
-    T *ptr;
-    SwigMovePointer(T *p) : ptr(p) { }
-    ~SwigMovePointer() { delete ptr; }
-    SwigMovePointer& operator=(SwigMovePointer& rhs) { T* oldptr = ptr; ptr = 0; delete oldptr; ptr = rhs.ptr; rhs.ptr = 0; return *this; }
-  } pointer;
-  SwigValueWrapper& operator=(const SwigValueWrapper<T>& rhs);
-  SwigValueWrapper(const SwigValueWrapper<T>& rhs);
-public:
-  SwigValueWrapper() : pointer(0) { }
-  SwigValueWrapper& operator=(const T& t) { SwigMovePointer tmp(new T(t)); pointer = tmp; return *this; }
-  operator T&() const { return *pointer.ptr; }
-  T *operator&() { return pointer.ptr; }
-};
-
-template <typename T> T SwigValueInit() {
-  return T();
-}
-#endif
-
-/* -----------------------------------------------------------------------------
- *  This section contains generic SWIG labels for method/variable
- *  declarations/attributes, and other compiler dependent labels.
- * ----------------------------------------------------------------------------- */
-
-/* template workaround for compilers that cannot correctly implement the C++ standard */
-#ifndef SWIGTEMPLATEDISAMBIGUATOR
-# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560)
-#  define SWIGTEMPLATEDISAMBIGUATOR template
-# elif defined(__HP_aCC)
-/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */
-/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */
-#  define SWIGTEMPLATEDISAMBIGUATOR template
-# else
-#  define SWIGTEMPLATEDISAMBIGUATOR
-# endif
-#endif
-
-/* inline attribute */
-#ifndef SWIGINLINE
-# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__))
-#   define SWIGINLINE inline
-# else
-#   define SWIGINLINE
-# endif
-#endif
-
-/* attribute recognised by some compilers to avoid 'unused' warnings */
-#ifndef SWIGUNUSED
-# if defined(__GNUC__)
-#   if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
-#     define SWIGUNUSED __attribute__ ((__unused__))
-#   else
-#     define SWIGUNUSED
-#   endif
-# elif defined(__ICC)
-#   define SWIGUNUSED __attribute__ ((__unused__))
-# else
-#   define SWIGUNUSED
-# endif
-#endif
-
-#ifndef SWIG_MSC_UNSUPPRESS_4505
-# if defined(_MSC_VER)
-#   pragma warning(disable : 4505) /* unreferenced local function has been removed */
-# endif
-#endif
-
-#ifndef SWIGUNUSEDPARM
-# ifdef __cplusplus
-#   define SWIGUNUSEDPARM(p)
-# else
-#   define SWIGUNUSEDPARM(p) p SWIGUNUSED
-# endif
-#endif
-
-/* internal SWIG method */
-#ifndef SWIGINTERN
-# define SWIGINTERN static SWIGUNUSED
-#endif
-
-/* internal inline SWIG method */
-#ifndef SWIGINTERNINLINE
-# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE
-#endif
-
-/* exporting methods */
-#if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
-#  ifndef GCC_HASCLASSVISIBILITY
-#    define GCC_HASCLASSVISIBILITY
-#  endif
-#endif
-
-#ifndef SWIGEXPORT
-# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
-#   if defined(STATIC_LINKED)
-#     define SWIGEXPORT
-#   else
-#     define SWIGEXPORT __declspec(dllexport)
-#   endif
-# else
-#   if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY)
-#     define SWIGEXPORT __attribute__ ((visibility("default")))
-#   else
-#     define SWIGEXPORT
-#   endif
-# endif
-#endif
-
-/* calling conventions for Windows */
-#ifndef SWIGSTDCALL
-# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
-#   define SWIGSTDCALL __stdcall
-# else
-#   define SWIGSTDCALL
-# endif
-#endif
-
-/* Deal with Microsoft's attempt at deprecating C standard runtime functions */
-#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
-# define _CRT_SECURE_NO_DEPRECATE
-#endif
-
-/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */
-#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE)
-# define _SCL_SECURE_NO_DEPRECATE
-#endif
-
-
-/* -----------------------------------------------------------------------------
- * swigrun.swg
- *
- * This file contains generic C API SWIG runtime support for pointer
- * type checking.
- * ----------------------------------------------------------------------------- */
-
-/* This should only be incremented when either the layout of swig_type_info changes,
-   or for whatever reason, the runtime changes incompatibly */
-#define SWIG_RUNTIME_VERSION "4"
-
-/* define SWIG_TYPE_TABLE_NAME as "SWIG_TYPE_TABLE" */
-#ifdef SWIG_TYPE_TABLE
-# define SWIG_QUOTE_STRING(x) #x
-# define SWIG_EXPAND_AND_QUOTE_STRING(x) SWIG_QUOTE_STRING(x)
-# define SWIG_TYPE_TABLE_NAME SWIG_EXPAND_AND_QUOTE_STRING(SWIG_TYPE_TABLE)
-#else
-# define SWIG_TYPE_TABLE_NAME
-#endif
-
-/*
-  You can use the SWIGRUNTIME and SWIGRUNTIMEINLINE macros for
-  creating a static or dynamic library from the SWIG runtime code.
-  In 99.9% of the cases, SWIG just needs to declare them as 'static'.
-
-  But only do this if strictly necessary, ie, if you have problems
-  with your compiler or suchlike.
-*/
-
-#ifndef SWIGRUNTIME
-# define SWIGRUNTIME SWIGINTERN
-#endif
-
-#ifndef SWIGRUNTIMEINLINE
-# define SWIGRUNTIMEINLINE SWIGRUNTIME SWIGINLINE
-#endif
-
-/*  Generic buffer size */
-#ifndef SWIG_BUFFER_SIZE
-# define SWIG_BUFFER_SIZE 1024
-#endif
-
-/* Flags for pointer conversions */
-#define SWIG_POINTER_DISOWN        0x1
-#define SWIG_CAST_NEW_MEMORY       0x2
-
-/* Flags for new pointer objects */
-#define SWIG_POINTER_OWN           0x1
-
-
-/*
-   Flags/methods for returning states.
-
-   The SWIG conversion methods, as ConvertPtr, return an integer
-   that tells if the conversion was successful or not. And if not,
-   an error code can be returned (see swigerrors.swg for the codes).
-
-   Use the following macros/flags to set or process the returning
-   states.
-
-   In old versions of SWIG, code such as the following was usually written:
-
-     if (SWIG_ConvertPtr(obj,vptr,ty.flags) != -1) {
-       // success code
-     } else {
-       //fail code
-     }
-
-   Now you can be more explicit:
-
-    int res = SWIG_ConvertPtr(obj,vptr,ty.flags);
-    if (SWIG_IsOK(res)) {
-      // success code
-    } else {
-      // fail code
-    }
-
-   which is the same really, but now you can also do
-
-    Type *ptr;
-    int res = SWIG_ConvertPtr(obj,(void **)(&ptr),ty.flags);
-    if (SWIG_IsOK(res)) {
-      // success code
-      if (SWIG_IsNewObj(res) {
-        ...
-	delete *ptr;
-      } else {
-        ...
-      }
-    } else {
-      // fail code
-    }
-
-   I.e., now SWIG_ConvertPtr can return new objects and you can
-   identify the case and take care of the deallocation. Of course that
-   also requires SWIG_ConvertPtr to return new result values, such as
-
-      int SWIG_ConvertPtr(obj, ptr,...) {
-        if (<obj is ok>) {
-          if (<need new object>) {
-            *ptr = <ptr to new allocated object>;
-            return SWIG_NEWOBJ;
-          } else {
-            *ptr = <ptr to old object>;
-            return SWIG_OLDOBJ;
-          }
-        } else {
-          return SWIG_BADOBJ;
-        }
-      }
-
-   Of course, returning the plain '0(success)/-1(fail)' still works, but you can be
-   more explicit by returning SWIG_BADOBJ, SWIG_ERROR or any of the
-   SWIG errors code.
-
-   Finally, if the SWIG_CASTRANK_MODE is enabled, the result code
-   allows to return the 'cast rank', for example, if you have this
-
-       int food(double)
-       int fooi(int);
-
-   and you call
-
-      food(1)   // cast rank '1'  (1 -> 1.0)
-      fooi(1)   // cast rank '0'
-
-   just use the SWIG_AddCast()/SWIG_CheckState()
-*/
-
-#define SWIG_OK                    (0)
-#define SWIG_ERROR                 (-1)
-#define SWIG_IsOK(r)               (r >= 0)
-#define SWIG_ArgError(r)           ((r != SWIG_ERROR) ? r : SWIG_TypeError)
-
-/* The CastRankLimit says how many bits are used for the cast rank */
-#define SWIG_CASTRANKLIMIT         (1 << 8)
-/* The NewMask denotes the object was created (using new/malloc) */
-#define SWIG_NEWOBJMASK            (SWIG_CASTRANKLIMIT  << 1)
-/* The TmpMask is for in/out typemaps that use temporal objects */
-#define SWIG_TMPOBJMASK            (SWIG_NEWOBJMASK << 1)
-/* Simple returning values */
-#define SWIG_BADOBJ                (SWIG_ERROR)
-#define SWIG_OLDOBJ                (SWIG_OK)
-#define SWIG_NEWOBJ                (SWIG_OK | SWIG_NEWOBJMASK)
-#define SWIG_TMPOBJ                (SWIG_OK | SWIG_TMPOBJMASK)
-/* Check, add and del mask methods */
-#define SWIG_AddNewMask(r)         (SWIG_IsOK(r) ? (r | SWIG_NEWOBJMASK) : r)
-#define SWIG_DelNewMask(r)         (SWIG_IsOK(r) ? (r & ~SWIG_NEWOBJMASK) : r)
-#define SWIG_IsNewObj(r)           (SWIG_IsOK(r) && (r & SWIG_NEWOBJMASK))
-#define SWIG_AddTmpMask(r)         (SWIG_IsOK(r) ? (r | SWIG_TMPOBJMASK) : r)
-#define SWIG_DelTmpMask(r)         (SWIG_IsOK(r) ? (r & ~SWIG_TMPOBJMASK) : r)
-#define SWIG_IsTmpObj(r)           (SWIG_IsOK(r) && (r & SWIG_TMPOBJMASK))
-
-/* Cast-Rank Mode */
-#if defined(SWIG_CASTRANK_MODE)
-#  ifndef SWIG_TypeRank
-#    define SWIG_TypeRank             unsigned long
-#  endif
-#  ifndef SWIG_MAXCASTRANK            /* Default cast allowed */
-#    define SWIG_MAXCASTRANK          (2)
-#  endif
-#  define SWIG_CASTRANKMASK          ((SWIG_CASTRANKLIMIT) -1)
-#  define SWIG_CastRank(r)           (r & SWIG_CASTRANKMASK)
-SWIGINTERNINLINE int SWIG_AddCast(int r) {
-  return SWIG_IsOK(r) ? ((SWIG_CastRank(r) < SWIG_MAXCASTRANK) ? (r + 1) : SWIG_ERROR) : r;
-}
-SWIGINTERNINLINE int SWIG_CheckState(int r) {
-  return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0;
-}
-#else /* no cast-rank mode */
-#  define SWIG_AddCast(r) (r)
-#  define SWIG_CheckState(r) (SWIG_IsOK(r) ? 1 : 0)
-#endif
-
-
-#include <string.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef void *(*swig_converter_func)(void *, int *);
-typedef struct swig_type_info *(*swig_dycast_func)(void **);
-
-/* Structure to store information on one type */
-typedef struct swig_type_info {
-  const char             *name;			/* mangled name of this type */
-  const char             *str;			/* human readable name of this type */
-  swig_dycast_func        dcast;		/* dynamic cast function down a hierarchy */
-  struct swig_cast_info  *cast;			/* linked list of types that can cast into this type */
-  void                   *clientdata;		/* language specific type data */
-  int                    owndata;		/* flag if the structure owns the clientdata */
-} swig_type_info;
-
-/* Structure to store a type and conversion function used for casting */
-typedef struct swig_cast_info {
-  swig_type_info         *type;			/* pointer to type that is equivalent to this type */
-  swig_converter_func     converter;		/* function to cast the void pointers */
-  struct swig_cast_info  *next;			/* pointer to next cast in linked list */
-  struct swig_cast_info  *prev;			/* pointer to the previous cast */
-} swig_cast_info;
-
-/* Structure used to store module information
- * Each module generates one structure like this, and the runtime collects
- * all of these structures and stores them in a circularly linked list.*/
-typedef struct swig_module_info {
-  swig_type_info         **types;		/* Array of pointers to swig_type_info structures that are in this module */
-  size_t                 size;		        /* Number of types in this module */
-  struct swig_module_info *next;		/* Pointer to next element in circularly linked list */
-  swig_type_info         **type_initial;	/* Array of initially generated type structures */
-  swig_cast_info         **cast_initial;	/* Array of initially generated casting structures */
-  void                    *clientdata;		/* Language specific module data */
-} swig_module_info;
-
-/*
-  Compare two type names skipping the space characters, therefore
-  "char*" == "char *" and "Class<int>" == "Class<int >", etc.
-
-  Return 0 when the two name types are equivalent, as in
-  strncmp, but skipping ' '.
-*/
-SWIGRUNTIME int
-SWIG_TypeNameComp(const char *f1, const char *l1,
-		  const char *f2, const char *l2) {
-  for (;(f1 != l1) && (f2 != l2); ++f1, ++f2) {
-    while ((*f1 == ' ') && (f1 != l1)) ++f1;
-    while ((*f2 == ' ') && (f2 != l2)) ++f2;
-    if (*f1 != *f2) return (*f1 > *f2) ? 1 : -1;
-  }
-  return (int)((l1 - f1) - (l2 - f2));
-}
-
-/*
-  Check type equivalence in a name list like <name1>|<name2>|...
-  Return 0 if equal, -1 if nb < tb, 1 if nb > tb
-*/
-SWIGRUNTIME int
-SWIG_TypeCmp(const char *nb, const char *tb) {
-  int equiv = 1;
-  const char* te = tb + strlen(tb);
-  const char* ne = nb;
-  while (equiv != 0 && *ne) {
-    for (nb = ne; *ne; ++ne) {
-      if (*ne == '|') break;
-    }
-    equiv = SWIG_TypeNameComp(nb, ne, tb, te);
-    if (*ne) ++ne;
-  }
-  return equiv;
-}
-
-/*
-  Check type equivalence in a name list like <name1>|<name2>|...
-  Return 0 if not equal, 1 if equal
-*/
-SWIGRUNTIME int
-SWIG_TypeEquiv(const char *nb, const char *tb) {
-  return SWIG_TypeCmp(nb, tb) == 0 ? 1 : 0;
-}
-
-/*
-  Check the typename
-*/
-SWIGRUNTIME swig_cast_info *
-SWIG_TypeCheck(const char *c, swig_type_info *ty) {
-  if (ty) {
-    swig_cast_info *iter = ty->cast;
-    while (iter) {
-      if (strcmp(iter->type->name, c) == 0) {
-        if (iter == ty->cast)
-          return iter;
-        /* Move iter to the top of the linked list */
-        iter->prev->next = iter->next;
-        if (iter->next)
-          iter->next->prev = iter->prev;
-        iter->next = ty->cast;
-        iter->prev = 0;
-        if (ty->cast) ty->cast->prev = iter;
-        ty->cast = iter;
-        return iter;
-      }
-      iter = iter->next;
-    }
-  }
-  return 0;
-}
-
-/*
-  Identical to SWIG_TypeCheck, except strcmp is replaced with a pointer comparison
-*/
-SWIGRUNTIME swig_cast_info *
-SWIG_TypeCheckStruct(swig_type_info *from, swig_type_info *ty) {
-  if (ty) {
-    swig_cast_info *iter = ty->cast;
-    while (iter) {
-      if (iter->type == from) {
-        if (iter == ty->cast)
-          return iter;
-        /* Move iter to the top of the linked list */
-        iter->prev->next = iter->next;
-        if (iter->next)
-          iter->next->prev = iter->prev;
-        iter->next = ty->cast;
-        iter->prev = 0;
-        if (ty->cast) ty->cast->prev = iter;
-        ty->cast = iter;
-        return iter;
-      }
-      iter = iter->next;
-    }
-  }
-  return 0;
-}
-
-/*
-  Cast a pointer up an inheritance hierarchy
-*/
-SWIGRUNTIMEINLINE void *
-SWIG_TypeCast(swig_cast_info *ty, void *ptr, int *newmemory) {
-  return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr, newmemory);
-}
-
-/*
-   Dynamic pointer casting. Down an inheritance hierarchy
-*/
-SWIGRUNTIME swig_type_info *
-SWIG_TypeDynamicCast(swig_type_info *ty, void **ptr) {
-  swig_type_info *lastty = ty;
-  if (!ty || !ty->dcast) return ty;
-  while (ty && (ty->dcast)) {
-    ty = (*ty->dcast)(ptr);
-    if (ty) lastty = ty;
-  }
-  return lastty;
-}
-
-/*
-  Return the name associated with this type
-*/
-SWIGRUNTIMEINLINE const char *
-SWIG_TypeName(const swig_type_info *ty) {
-  return ty->name;
-}
-
-/*
-  Return the pretty name associated with this type,
-  that is an unmangled type name in a form presentable to the user.
-*/
-SWIGRUNTIME const char *
-SWIG_TypePrettyName(const swig_type_info *type) {
-  /* The "str" field contains the equivalent pretty names of the
-     type, separated by vertical-bar characters.  We choose
-     to print the last name, as it is often (?) the most
-     specific. */
-  if (!type) return NULL;
-  if (type->str != NULL) {
-    const char *last_name = type->str;
-    const char *s;
-    for (s = type->str; *s; s++)
-      if (*s == '|') last_name = s+1;
-    return last_name;
-  }
-  else
-    return type->name;
-}
-
-/*
-   Set the clientdata field for a type
-*/
-SWIGRUNTIME void
-SWIG_TypeClientData(swig_type_info *ti, void *clientdata) {
-  swig_cast_info *cast = ti->cast;
-  /* if (ti->clientdata == clientdata) return; */
-  ti->clientdata = clientdata;
-
-  while (cast) {
-    if (!cast->converter) {
-      swig_type_info *tc = cast->type;
-      if (!tc->clientdata) {
-	SWIG_TypeClientData(tc, clientdata);
-      }
-    }
-    cast = cast->next;
-  }
-}
-SWIGRUNTIME void
-SWIG_TypeNewClientData(swig_type_info *ti, void *clientdata) {
-  SWIG_TypeClientData(ti, clientdata);
-  ti->owndata = 1;
-}
-
-/*
-  Search for a swig_type_info structure only by mangled name
-  Search is a O(log #types)
-
-  We start searching at module start, and finish searching when start == end.
-  Note: if start == end at the beginning of the function, we go all the way around
-  the circular list.
-*/
-SWIGRUNTIME swig_type_info *
-SWIG_MangledTypeQueryModule(swig_module_info *start,
-                            swig_module_info *end,
-		            const char *name) {
-  swig_module_info *iter = start;
-  do {
-    if (iter->size) {
-      register size_t l = 0;
-      register size_t r = iter->size - 1;
-      do {
-	/* since l+r >= 0, we can (>> 1) instead (/ 2) */
-	register size_t i = (l + r) >> 1;
-	const char *iname = iter->types[i]->name;
-	if (iname) {
-	  register int compare = strcmp(name, iname);
-	  if (compare == 0) {
-	    return iter->types[i];
-	  } else if (compare < 0) {
-	    if (i) {
-	      r = i - 1;
-	    } else {
-	      break;
-	    }
-	  } else if (compare > 0) {
-	    l = i + 1;
-	  }
-	} else {
-	  break; /* should never happen */
-	}
-      } while (l <= r);
-    }
-    iter = iter->next;
-  } while (iter != end);
-  return 0;
-}
-
-/*
-  Search for a swig_type_info structure for either a mangled name or a human readable name.
-  It first searches the mangled names of the types, which is a O(log #types)
-  If a type is not found it then searches the human readable names, which is O(#types).
-
-  We start searching at module start, and finish searching when start == end.
-  Note: if start == end at the beginning of the function, we go all the way around
-  the circular list.
-*/
-SWIGRUNTIME swig_type_info *
-SWIG_TypeQueryModule(swig_module_info *start,
-                     swig_module_info *end,
-		     const char *name) {
-  /* STEP 1: Search the name field using binary search */
-  swig_type_info *ret = SWIG_MangledTypeQueryModule(start, end, name);
-  if (ret) {
-    return ret;
-  } else {
-    /* STEP 2: If the type hasn't been found, do a complete search
-       of the str field (the human readable name) */
-    swig_module_info *iter = start;
-    do {
-      register size_t i = 0;
-      for (; i < iter->size; ++i) {
-	if (iter->types[i]->str && (SWIG_TypeEquiv(iter->types[i]->str, name)))
-	  return iter->types[i];
-      }
-      iter = iter->next;
-    } while (iter != end);
-  }
-
-  /* neither found a match */
-  return 0;
-}
-
-/*
-   Pack binary data into a string
-*/
-SWIGRUNTIME char *
-SWIG_PackData(char *c, void *ptr, size_t sz) {
-  static const char hex[17] = "0123456789abcdef";
-  register const unsigned char *u = (unsigned char *) ptr;
-  register const unsigned char *eu =  u + sz;
-  for (; u != eu; ++u) {
-    register unsigned char uu = *u;
-    *(c++) = hex[(uu & 0xf0) >> 4];
-    *(c++) = hex[uu & 0xf];
-  }
-  return c;
-}
-
-/*
-   Unpack binary data from a string
-*/
-SWIGRUNTIME const char *
-SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
-  register unsigned char *u = (unsigned char *) ptr;
-  register const unsigned char *eu = u + sz;
-  for (; u != eu; ++u) {
-    register char d = *(c++);
-    register unsigned char uu;
-    if ((d >= '0') && (d <= '9'))
-      uu = ((d - '0') << 4);
-    else if ((d >= 'a') && (d <= 'f'))
-      uu = ((d - ('a'-10)) << 4);
-    else
-      return (char *) 0;
-    d = *(c++);
-    if ((d >= '0') && (d <= '9'))
-      uu |= (d - '0');
-    else if ((d >= 'a') && (d <= 'f'))
-      uu |= (d - ('a'-10));
-    else
-      return (char *) 0;
-    *u = uu;
-  }
-  return c;
-}
-
-/*
-   Pack 'void *' into a string buffer.
-*/
-SWIGRUNTIME char *
-SWIG_PackVoidPtr(char *buff, void *ptr, const char *name, size_t bsz) {
-  char *r = buff;
-  if ((2*sizeof(void *) + 2) > bsz) return 0;
-  *(r++) = '_';
-  r = SWIG_PackData(r,&ptr,sizeof(void *));
-  if (strlen(name) + 1 > (bsz - (r - buff))) return 0;
-  strcpy(r,name);
-  return buff;
-}
-
-SWIGRUNTIME const char *
-SWIG_UnpackVoidPtr(const char *c, void **ptr, const char *name) {
-  if (*c != '_') {
-    if (strcmp(c,"NULL") == 0) {
-      *ptr = (void *) 0;
-      return name;
-    } else {
-      return 0;
-    }
-  }
-  return SWIG_UnpackData(++c,ptr,sizeof(void *));
-}
-
-SWIGRUNTIME char *
-SWIG_PackDataName(char *buff, void *ptr, size_t sz, const char *name, size_t bsz) {
-  char *r = buff;
-  size_t lname = (name ? strlen(name) : 0);
-  if ((2*sz + 2 + lname) > bsz) return 0;
-  *(r++) = '_';
-  r = SWIG_PackData(r,ptr,sz);
-  if (lname) {
-    strncpy(r,name,lname+1);
-  } else {
-    *r = 0;
-  }
-  return buff;
-}
-
-SWIGRUNTIME const char *
-SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) {
-  if (*c != '_') {
-    if (strcmp(c,"NULL") == 0) {
-      memset(ptr,0,sz);
-      return name;
-    } else {
-      return 0;
-    }
-  }
-  return SWIG_UnpackData(++c,ptr,sz);
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-/*  Errors in SWIG */
-#define  SWIG_UnknownError    	   -1
-#define  SWIG_IOError        	   -2
-#define  SWIG_RuntimeError   	   -3
-#define  SWIG_IndexError     	   -4
-#define  SWIG_TypeError      	   -5
-#define  SWIG_DivisionByZero 	   -6
-#define  SWIG_OverflowError  	   -7
-#define  SWIG_SyntaxError    	   -8
-#define  SWIG_ValueError     	   -9
-#define  SWIG_SystemError    	   -10
-#define  SWIG_AttributeError 	   -11
-#define  SWIG_MemoryError    	   -12
-#define  SWIG_NullReferenceError   -13
-
-
-
-#ifdef __cplusplus
-/* Needed on some windows machines---since MS plays funny games with the header files under C++ */
-#include <math.h>
-#include <stdlib.h>
-extern "C" {
-#endif
-#include "EXTERN.h"
-#include "perl.h"
-#include "XSUB.h"
-
-/* Add in functionality missing in older versions of Perl. Much of this is based on Devel-PPPort on cpan. */
-
-/* Add PERL_REVISION, PERL_VERSION, PERL_SUBVERSION if missing */
-#ifndef PERL_REVISION
-#  if !defined(__PATCHLEVEL_H_INCLUDED__) && !(defined(PATCHLEVEL) && defined(SUBVERSION))
-#    define PERL_PATCHLEVEL_H_IMPLICIT
-#    include <patchlevel.h>
-#  endif
-#  if !(defined(PERL_VERSION) || (defined(SUBVERSION) && defined(PATCHLEVEL)))
-#    include <could_not_find_Perl_patchlevel.h>
-#  endif
-#  ifndef PERL_REVISION
-#    define PERL_REVISION       (5)
-#    define PERL_VERSION        PATCHLEVEL
-#    define PERL_SUBVERSION     SUBVERSION
-#  endif
-#endif
-
-#if defined(WIN32) && defined(PERL_OBJECT) && !defined(PerlIO_exportFILE)
-#define PerlIO_exportFILE(fh,fl) (FILE*)(fh)
-#endif
-
-#ifndef SvIOK_UV
-# define SvIOK_UV(sv)       (SvIOK(sv) && (SvUVX(sv) == SvIVX(sv)))
-#endif
-
-#ifndef SvUOK
-# define SvUOK(sv)           SvIOK_UV(sv)
-#endif
-
-#if ((PERL_VERSION < 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION <= 5)))
-#  define PL_sv_undef               sv_undef
-#  define PL_na	                    na
-#  define PL_errgv                  errgv
-#  define PL_sv_no                  sv_no
-#  define PL_sv_yes                 sv_yes
-#  define PL_markstack_ptr          markstack_ptr
-#endif
-
-#ifndef IVSIZE
-#  ifdef LONGSIZE
-#    define IVSIZE LONGSIZE
-#  else
-#    define IVSIZE 4 /* A bold guess, but the best we can make. */
-#  endif
-#endif
-
-#ifndef INT2PTR
-#  if (IVSIZE == PTRSIZE) && (UVSIZE == PTRSIZE)
-#    define PTRV                  UV
-#    define INT2PTR(any,d)        (any)(d)
-#  else
-#    if PTRSIZE == LONGSIZE
-#      define PTRV                unsigned long
-#    else
-#      define PTRV                unsigned
-#    endif
-#    define INT2PTR(any,d)        (any)(PTRV)(d)
-#  endif
-
-#  define NUM2PTR(any,d)  (any)(PTRV)(d)
-#  define PTR2IV(p)       INT2PTR(IV,p)
-#  define PTR2UV(p)       INT2PTR(UV,p)
-#  define PTR2NV(p)       NUM2PTR(NV,p)
-
-#  if PTRSIZE == LONGSIZE
-#    define PTR2ul(p)     (unsigned long)(p)
-#  else
-#    define PTR2ul(p)     INT2PTR(unsigned long,p)
-#  endif
-#endif /* !INT2PTR */
-
-#ifndef SvPV_nolen
-# define SvPV_nolen(x) SvPV(x,PL_na)
-#endif
-
-#ifndef get_sv
-#  define get_sv perl_get_sv
-#endif
-
-#ifndef ERRSV
-#  define ERRSV get_sv("@",FALSE)
-#endif
-
-#ifndef pTHX_
-#define pTHX_
-#endif   
-
-#include <string.h>
-#ifdef __cplusplus
-}
-#endif
-
-/* -----------------------------------------------------------------------------
- * error manipulation
- * ----------------------------------------------------------------------------- */
-
-SWIGINTERN const char*
-SWIG_Perl_ErrorType(int code) {
-  switch(code) {
-  case SWIG_MemoryError:
-    return "MemoryError";
-  case SWIG_IOError:
-    return "IOError";
-  case SWIG_RuntimeError:
-    return "RuntimeError";
-  case SWIG_IndexError:
-    return "IndexError";
-  case SWIG_TypeError:
-    return "TypeError";
-  case SWIG_DivisionByZero:
-    return "ZeroDivisionError";
-  case SWIG_OverflowError:
-    return "OverflowError";
-  case SWIG_SyntaxError:
-    return "SyntaxError";
-  case SWIG_ValueError:
-    return "ValueError";
-  case SWIG_SystemError:
-    return "SystemError";
-  case SWIG_AttributeError:
-    return "AttributeError";
-  default:
-    return "RuntimeError";
-  }
-}
-
-
-/* -----------------------------------------------------------------------------
- * perlrun.swg
- *
- * This file contains the runtime support for Perl modules
- * and includes code for managing global variables and pointer
- * type checking.
- * ----------------------------------------------------------------------------- */
-
-#ifdef PERL_OBJECT
-#define SWIG_PERL_OBJECT_DECL CPerlObj *SWIGUNUSEDPARM(pPerl),
-#define SWIG_PERL_OBJECT_CALL pPerl,
-#else
-#define SWIG_PERL_OBJECT_DECL
-#define SWIG_PERL_OBJECT_CALL
-#endif
-
-/* Common SWIG API */
-
-/* for raw pointers */
-#define SWIG_ConvertPtr(obj, pp, type, flags)           SWIG_Perl_ConvertPtr(SWIG_PERL_OBJECT_CALL obj, pp, type, flags)
-#define SWIG_ConvertPtrAndOwn(obj, pp, type, flags,own) SWIG_Perl_ConvertPtrAndOwn(SWIG_PERL_OBJECT_CALL obj, pp, type, flags, own)
-#define SWIG_NewPointerObj(p, type, flags)              SWIG_Perl_NewPointerObj(SWIG_PERL_OBJECT_CALL p, type, flags)
-
-/* for raw packed data */
-#define SWIG_ConvertPacked(obj, p, s, type)             SWIG_Perl_ConvertPacked(SWIG_PERL_OBJECT_CALL obj, p, s, type)
-#define SWIG_NewPackedObj(p, s, type)	                SWIG_Perl_NewPackedObj(SWIG_PERL_OBJECT_CALL p, s, type)
-
-/* for class or struct pointers */
-#define SWIG_ConvertInstance(obj, pptr, type, flags)    SWIG_ConvertPtr(obj, pptr, type, flags)
-#define SWIG_NewInstanceObj(ptr, type, flags)           SWIG_NewPointerObj(ptr, type, flags)
-
-/* for C or C++ function pointers */
-#define SWIG_ConvertFunctionPtr(obj, pptr, type)        SWIG_ConvertPtr(obj, pptr, type, 0)
-#define SWIG_NewFunctionPtrObj(ptr, type)               SWIG_NewPointerObj(ptr, type, 0)
-
-/* for C++ member pointers, ie, member methods */
-#define SWIG_ConvertMember(obj, ptr, sz, ty)            SWIG_ConvertPacked(obj, ptr, sz, ty)
-#define SWIG_NewMemberObj(ptr, sz, type)                SWIG_NewPackedObj(ptr, sz, type)
-
-
-/* Runtime API */
-
-#define SWIG_GetModule(clientdata)                      SWIG_Perl_GetModule(clientdata)
-#define SWIG_SetModule(clientdata, pointer)             SWIG_Perl_SetModule(pointer)
-
-
-/* Error manipulation */
-
-#define SWIG_ErrorType(code)                            SWIG_Perl_ErrorType(code)               
-#define SWIG_Error(code, msg)            		sv_setpvf(get_sv("@", GV_ADD), "%s %s", SWIG_ErrorType(code), msg)
-#define SWIG_fail                        		goto fail						    
-
-/* Perl-specific SWIG API */
-
-#define SWIG_MakePtr(sv, ptr, type, flags)              SWIG_Perl_MakePtr(SWIG_PERL_OBJECT_CALL sv, ptr, type, flags)
-#define SWIG_MakePackedObj(sv, p, s, type)	        SWIG_Perl_MakePackedObj(SWIG_PERL_OBJECT_CALL sv, p, s, type)
-#define SWIG_SetError(str)                              SWIG_Error(SWIG_RuntimeError, str)
-
-
-#define SWIG_PERL_DECL_ARGS_1(arg1)                     (SWIG_PERL_OBJECT_DECL arg1)
-#define SWIG_PERL_CALL_ARGS_1(arg1)                     (SWIG_PERL_OBJECT_CALL arg1)
-#define SWIG_PERL_DECL_ARGS_2(arg1, arg2)               (SWIG_PERL_OBJECT_DECL arg1, arg2)
-#define SWIG_PERL_CALL_ARGS_2(arg1, arg2)               (SWIG_PERL_OBJECT_CALL arg1, arg2)
-
-/* -----------------------------------------------------------------------------
- * pointers/data manipulation
- * ----------------------------------------------------------------------------- */
-
-/* For backward compatibility only */
-#define SWIG_POINTER_EXCEPTION  0
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define SWIG_OWNER   SWIG_POINTER_OWN
-#define SWIG_SHADOW  SWIG_OWNER << 1
-
-#define SWIG_MAYBE_PERL_OBJECT SWIG_PERL_OBJECT_DECL
-
-/* SWIG Perl macros */
-
-/* Macro to declare an XS function */
-#ifndef XSPROTO
-#   define XSPROTO(name) void name(pTHX_ CV* cv)
-#endif
-
-/* Macro to call an XS function */
-#ifdef PERL_OBJECT 
-#  define SWIG_CALLXS(_name) _name(cv,pPerl) 
-#else 
-#  ifndef MULTIPLICITY 
-#    define SWIG_CALLXS(_name) _name(cv) 
-#  else 
-#    define SWIG_CALLXS(_name) _name(PERL_GET_THX, cv) 
-#  endif 
-#endif 
-
-#ifdef PERL_OBJECT
-#define MAGIC_PPERL  CPerlObj *pPerl = (CPerlObj *) this;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-typedef int (CPerlObj::*SwigMagicFunc)(SV *, MAGIC *);
-#ifdef __cplusplus
-}
-#endif
-
-#define SWIG_MAGIC(a,b) (SV *a, MAGIC *b)
-#define SWIGCLASS_STATIC
-
-#else /* PERL_OBJECT */
-
-#define MAGIC_PPERL
-#define SWIGCLASS_STATIC static SWIGUNUSED
-
-#ifndef MULTIPLICITY
-#define SWIG_MAGIC(a,b) (SV *a, MAGIC *b)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-typedef int (*SwigMagicFunc)(SV *, MAGIC *);
-#ifdef __cplusplus
-}
-#endif
-
-#else /* MULTIPLICITY */
-
-#define SWIG_MAGIC(a,b) (struct interpreter *interp, SV *a, MAGIC *b)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-typedef int (*SwigMagicFunc)(struct interpreter *, SV *, MAGIC *);
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* MULTIPLICITY */
-#endif /* PERL_OBJECT */
-
-#  ifdef PERL_OBJECT
-#    define SWIG_croak_null() SWIG_Perl_croak_null(pPerl)
-static void SWIG_Perl_croak_null(CPerlObj *pPerl)
-#  else
-static void SWIG_croak_null()
-#  endif
-{
-  SV *err = get_sv("@", GV_ADD);
-#  if (PERL_VERSION < 6)
-  croak("%_", err);
-#  else
-  if (sv_isobject(err))
-    croak(0);
-  else
-    croak("%s", SvPV_nolen(err));
-#  endif
-}
-
-
-/* 
-   Define how strict is the cast between strings and integers/doubles
-   when overloading between these types occurs.
-   
-   The default is making it as strict as possible by using SWIG_AddCast
-   when needed.
-   
-   You can use -DSWIG_PERL_NO_STRICT_STR2NUM at compilation time to
-   disable the SWIG_AddCast, making the casting between string and
-   numbers less strict.
-
-   In the end, we try to solve the overloading between strings and
-   numerical types in the more natural way, but if you can avoid it,
-   well, avoid it using %rename, for example.
-*/
-#ifndef SWIG_PERL_NO_STRICT_STR2NUM
-# ifndef SWIG_PERL_STRICT_STR2NUM
-#  define SWIG_PERL_STRICT_STR2NUM
-# endif
-#endif
-#ifdef SWIG_PERL_STRICT_STR2NUM
-/* string takes precedence */
-#define SWIG_Str2NumCast(x) SWIG_AddCast(x)  
-#else
-/* number takes precedence */
-#define SWIG_Str2NumCast(x) x
-#endif
-
-
-
-#include <stdlib.h>
-
-SWIGRUNTIME const char *
-SWIG_Perl_TypeProxyName(const swig_type_info *type) {
-  if (!type) return NULL;
-  if (type->clientdata != NULL) {
-    return (const char*) type->clientdata;
-  } 
-  else {
-    return type->name;
-  }
-}
-
-/* Identical to SWIG_TypeCheck, except for strcmp comparison */
-SWIGRUNTIME swig_cast_info *
-SWIG_TypeProxyCheck(const char *c, swig_type_info *ty) {
-  if (ty) {
-    swig_cast_info *iter = ty->cast;
-    while (iter) {
-      if (strcmp(SWIG_Perl_TypeProxyName(iter->type), c) == 0) {
-        if (iter == ty->cast)
-          return iter;
-        /* Move iter to the top of the linked list */
-        iter->prev->next = iter->next;
-        if (iter->next)
-          iter->next->prev = iter->prev;
-        iter->next = ty->cast;
-        iter->prev = 0;
-        if (ty->cast) ty->cast->prev = iter;
-        ty->cast = iter;
-        return iter;
-      }
-      iter = iter->next;
-    }
-  }
-  return 0;
-}
-
-/* Function for getting a pointer value */
-
-SWIGRUNTIME int
-SWIG_Perl_ConvertPtrAndOwn(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *_t, int flags, int *own) {
-  swig_cast_info *tc;
-  void *voidptr = (void *)0;
-  SV *tsv = 0;
-
-  if (own)
-    *own = 0;
-
-  /* If magical, apply more magic */
-  if (SvGMAGICAL(sv))
-    mg_get(sv);
-
-  /* Check to see if this is an object */
-  if (sv_isobject(sv)) {
-    IV tmp = 0;
-    tsv = (SV*) SvRV(sv);
-    if ((SvTYPE(tsv) == SVt_PVHV)) {
-      MAGIC *mg;
-      if (SvMAGICAL(tsv)) {
-        mg = mg_find(tsv,'P');
-        if (mg) {
-          sv = mg->mg_obj;
-          if (sv_isobject(sv)) {
-	    tsv = (SV*)SvRV(sv);
-            tmp = SvIV(tsv);
-          }
-        }
-      } else {
-        return SWIG_ERROR;
-      }
-    } else {
-      tmp = SvIV(tsv);
-    }
-    voidptr = INT2PTR(void *,tmp);
-  } else if (! SvOK(sv)) {            /* Check for undef */
-    *(ptr) = (void *) 0;
-    return SWIG_OK;
-  } else if (SvTYPE(sv) == SVt_RV) {  /* Check for NULL pointer */
-    if (!SvROK(sv)) {
-      /* In Perl 5.12 and later, SVt_RV == SVt_IV, so sv could be a valid integer value.  */
-      if (SvIOK(sv)) {
-        return SWIG_ERROR;
-      } else {
-        /* NULL pointer (reference to undef). */
-        *(ptr) = (void *) 0;
-        return SWIG_OK;
-      }
-    } else {
-      return SWIG_ERROR;
-    }
-  } else {                            /* Don't know what it is */
-    return SWIG_ERROR;
-  }
-  if (_t) {
-    /* Now see if the types match */
-    char *_c = HvNAME(SvSTASH(SvRV(sv)));
-    tc = SWIG_TypeProxyCheck(_c,_t);
-    if (!tc) {
-      return SWIG_ERROR;
-    }
-    {
-      int newmemory = 0;
-      *ptr = SWIG_TypeCast(tc,voidptr,&newmemory);
-      if (newmemory == SWIG_CAST_NEW_MEMORY) {
-        assert(own); /* badly formed typemap which will lead to a memory leak - it must set and use own to delete *ptr */
-        if (own)
-          *own = *own | SWIG_CAST_NEW_MEMORY;
-      }
-    }
-  } else {
-    *ptr = voidptr;
-  }
-
-  /* 
-   *  DISOWN implementation: we need a perl guru to check this one.
-   */
-  if (tsv && (flags & SWIG_POINTER_DISOWN)) {
-    /* 
-     *  almost copy paste code from below SWIG_POINTER_OWN setting
-     */
-    SV *obj = sv;
-    HV *stash = SvSTASH(SvRV(obj));
-    GV *gv = *(GV**)hv_fetch(stash, "OWNER", 5, TRUE);
-    if (isGV(gv)) {
-      HV *hv = GvHVn(gv);
-      /*
-       * To set ownership (see below), a newSViv(1) entry is added. 
-       * Hence, to remove ownership, we delete the entry.
-       */
-      if (hv_exists_ent(hv, obj, 0)) {
-	hv_delete_ent(hv, obj, 0, 0);
-      }
-    }
-  }
-  return SWIG_OK;
-}
-
-SWIGRUNTIME int
-SWIG_Perl_ConvertPtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *_t, int flags) {
-  return SWIG_Perl_ConvertPtrAndOwn(sv, ptr, _t, flags, 0);
-}
-
-SWIGRUNTIME void
-SWIG_Perl_MakePtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void *ptr, swig_type_info *t, int flags) {
-  if (ptr && (flags & (SWIG_SHADOW | SWIG_POINTER_OWN))) {
-    SV *self;
-    SV *obj=newSV(0);
-    HV *hash=newHV();
-    HV *stash;
-    sv_setref_pv(obj, SWIG_Perl_TypeProxyName(t), ptr);
-    stash=SvSTASH(SvRV(obj));
-    if (flags & SWIG_POINTER_OWN) {
-      HV *hv;
-      GV *gv = *(GV**)hv_fetch(stash, "OWNER", 5, TRUE);
-      if (!isGV(gv))
-        gv_init(gv, stash, "OWNER", 5, FALSE);
-      hv=GvHVn(gv);
-      hv_store_ent(hv, obj, newSViv(1), 0);
-    }
-    sv_magic((SV *)hash, (SV *)obj, 'P', Nullch, 0);
-    SvREFCNT_dec(obj);
-    self=newRV_noinc((SV *)hash);
-    sv_setsv(sv, self);
-    SvREFCNT_dec((SV *)self);
-    sv_bless(sv, stash);
-  }
-  else {
-    sv_setref_pv(sv, SWIG_Perl_TypeProxyName(t), ptr);
-  }
-}
-
-SWIGRUNTIMEINLINE SV *
-SWIG_Perl_NewPointerObj(SWIG_MAYBE_PERL_OBJECT void *ptr, swig_type_info *t, int flags) {
-  SV *result = sv_newmortal();
-  SWIG_MakePtr(result, ptr, t, flags);
-  return result;
-}
-
-SWIGRUNTIME void
-SWIG_Perl_MakePackedObj(SWIG_MAYBE_PERL_OBJECT SV *sv, void *ptr, int sz, swig_type_info *type) {
-  char result[1024];
-  char *r = result;
-  if ((2*sz + 1 + strlen(SWIG_Perl_TypeProxyName(type))) > 1000) return;
-  *(r++) = '_';
-  r = SWIG_PackData(r,ptr,sz);
-  strcpy(r,SWIG_Perl_TypeProxyName(type));
-  sv_setpv(sv, result);
-}
-
-SWIGRUNTIME SV *
-SWIG_Perl_NewPackedObj(SWIG_MAYBE_PERL_OBJECT void *ptr, int sz, swig_type_info *type) {
-  SV *result = sv_newmortal();
-  SWIG_Perl_MakePackedObj(result, ptr, sz, type);
-  return result;
-}
-
-/* Convert a packed value value */
-SWIGRUNTIME int
-SWIG_Perl_ConvertPacked(SWIG_MAYBE_PERL_OBJECT SV *obj, void *ptr, int sz, swig_type_info *ty) {
-  swig_cast_info *tc;
-  const char  *c = 0;
-
-  if ((!obj) || (!SvOK(obj))) return SWIG_ERROR;
-  c = SvPV_nolen(obj);
-  /* Pointer values must start with leading underscore */
-  if (*c != '_') return SWIG_ERROR;
-  c++;
-  c = SWIG_UnpackData(c,ptr,sz);
-  if (ty) {
-    tc = SWIG_TypeCheck(c,ty);
-    if (!tc) return SWIG_ERROR;
-  }
-  return SWIG_OK;
-}
-
-
-/* Macros for low-level exception handling */
-#define SWIG_croak(x)    { SWIG_Error(SWIG_RuntimeError, x); SWIG_fail; }
-
-
-typedef XSPROTO(SwigPerlWrapper);
-typedef SwigPerlWrapper *SwigPerlWrapperPtr;
-
-/* Structure for command table */
-typedef struct {
-  const char         *name;
-  SwigPerlWrapperPtr  wrapper;
-} swig_command_info;
-
-/* Information for constant table */
-
-#define SWIG_INT     1
-#define SWIG_FLOAT   2
-#define SWIG_STRING  3
-#define SWIG_POINTER 4
-#define SWIG_BINARY  5
-
-/* Constant information structure */
-typedef struct swig_constant_info {
-    int              type;
-    const char      *name;
-    long             lvalue;
-    double           dvalue;
-    void            *pvalue;
-    swig_type_info **ptype;
-} swig_constant_info;
-
-
-/* Structure for variable table */
-typedef struct {
-  const char   *name;
-  SwigMagicFunc   set;
-  SwigMagicFunc   get;
-  swig_type_info  **type;
-} swig_variable_info;
-
-/* Magic variable code */
-#ifndef PERL_OBJECT
-# ifdef __cplusplus
-#  define swig_create_magic(s,a,b,c) _swig_create_magic(s,const_cast<char*>(a),b,c)
-# else
-#  define swig_create_magic(s,a,b,c) _swig_create_magic(s,(char*)(a),b,c)
-# endif
-# ifndef MULTIPLICITY
-SWIGRUNTIME void _swig_create_magic(SV *sv, char *name, int (*set)(SV *, MAGIC *), int (*get)(SV *,MAGIC *)) 
-# else
-SWIGRUNTIME void _swig_create_magic(SV *sv, char *name, int (*set)(struct interpreter*, SV *, MAGIC *), int (*get)(struct interpreter*, SV *,MAGIC *)) 
-# endif
-#else
-#  define swig_create_magic(s,a,b,c) _swig_create_magic(pPerl,s,a,b,c)
-SWIGRUNTIME void _swig_create_magic(CPerlObj *pPerl, SV *sv, const char *name, int (CPerlObj::*set)(SV *, MAGIC *), int (CPerlObj::*get)(SV *, MAGIC *)) 
-#endif
-{
-  MAGIC *mg;
-  sv_magic(sv,sv,'U',name,strlen(name));
-  mg = mg_find(sv,'U');
-  mg->mg_virtual = (MGVTBL *) malloc(sizeof(MGVTBL));
-  mg->mg_virtual->svt_get = (SwigMagicFunc) get;
-  mg->mg_virtual->svt_set = (SwigMagicFunc) set;
-  mg->mg_virtual->svt_len = 0;
-  mg->mg_virtual->svt_clear = 0;
-  mg->mg_virtual->svt_free = 0;
-}
-
-
-SWIGRUNTIME swig_module_info *
-SWIG_Perl_GetModule(void *SWIGUNUSEDPARM(clientdata)) {
-  static void *type_pointer = (void *)0;
-  SV *pointer;
-
-  /* first check if pointer already created */
-  if (!type_pointer) {
-    pointer = get_sv("swig_runtime_data::type_pointer" SWIG_RUNTIME_VERSION SWIG_TYPE_TABLE_NAME, FALSE | GV_ADDMULTI);
-    if (pointer && SvOK(pointer)) {
-      type_pointer = INT2PTR(swig_type_info **, SvIV(pointer));
-    }
-  }
-
-  return (swig_module_info *) type_pointer;
-}
-
-SWIGRUNTIME void
-SWIG_Perl_SetModule(swig_module_info *module) {
-  SV *pointer;
-
-  /* create a new pointer */
-  pointer = get_sv("swig_runtime_data::type_pointer" SWIG_RUNTIME_VERSION SWIG_TYPE_TABLE_NAME, TRUE | GV_ADDMULTI);
-  sv_setiv(pointer, PTR2IV(module));
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-/* Workaround perl5 global namespace pollution. Note that undefining library
- * functions like fopen will not solve the problem on all platforms as fopen
- * might be a macro on Windows but not necessarily on other operating systems. */
-#ifdef do_open
-  #undef do_open
-#endif
-#ifdef do_close
-  #undef do_close
-#endif
-#ifdef do_exec
-  #undef do_exec
-#endif
-#ifdef scalar
-  #undef scalar
-#endif
-#ifdef list
-  #undef list
-#endif
-#ifdef apply
-  #undef apply
-#endif
-#ifdef convert
-  #undef convert
-#endif
-#ifdef Error
-  #undef Error
-#endif
-#ifdef form
-  #undef form
-#endif
-#ifdef vform
-  #undef vform
-#endif
-#ifdef LABEL
-  #undef LABEL
-#endif
-#ifdef METHOD
-  #undef METHOD
-#endif
-#ifdef Move
-  #undef Move
-#endif
-#ifdef yylex
-  #undef yylex
-#endif
-#ifdef yyparse
-  #undef yyparse
-#endif
-#ifdef yyerror
-  #undef yyerror
-#endif
-#ifdef invert
-  #undef invert
-#endif
-#ifdef ref
-  #undef ref
-#endif
-#ifdef read
-  #undef read
-#endif
-#ifdef write
-  #undef write
-#endif
-#ifdef eof
-  #undef eof
-#endif
-#ifdef close
-  #undef close
-#endif
-#ifdef rewind
-  #undef rewind
-#endif
-#ifdef free
-  #undef free
-#endif
-#ifdef malloc
-  #undef malloc
-#endif
-#ifdef calloc
-  #undef calloc
-#endif
-#ifdef Stat
-  #undef Stat
-#endif
-#ifdef check
-  #undef check
-#endif
-#ifdef seekdir
-  #undef seekdir
-#endif
-#ifdef open
-  #undef open
-#endif
-#ifdef readdir
-  #undef readdir
-#endif
-#ifdef bind
-  #undef bind
-#endif
-#ifdef access
-  #undef access
-#endif
-#ifdef stat
-  #undef stat
-#endif
-
-#ifdef bool
-  /* Leave if macro is from C99 stdbool.h */
-  #ifndef __bool_true_false_are_defined
-    #undef bool
-  #endif
-#endif
-
-
-
-
-#define SWIG_exception_fail(code, msg) do { SWIG_Error(code, msg); SWIG_fail; } while(0) 
-
-#define SWIG_contract_assert(expr, msg) if (!(expr)) { SWIG_Error(SWIG_RuntimeError, msg); SWIG_fail; } else 
-
-
-
-  #define SWIG_exception(code, msg) do { SWIG_Error(code, msg); SWIG_fail;; } while(0) 
-
-
-/* -------- TYPES TABLE (BEGIN) -------- */
-
-#define SWIGTYPE_p_CPLErrorHandler swig_types[0]
-#define SWIGTYPE_p_CPLXMLNode swig_types[1]
-#define SWIGTYPE_p_GByte swig_types[2]
-#define SWIGTYPE_p_GDALAsyncReaderShadow swig_types[3]
-#define SWIGTYPE_p_GDALColorEntry swig_types[4]
-#define SWIGTYPE_p_GDALColorTableShadow swig_types[5]
-#define SWIGTYPE_p_GDALDatasetShadow swig_types[6]
-#define SWIGTYPE_p_GDALDriverShadow swig_types[7]
-#define SWIGTYPE_p_GDALMajorObjectShadow swig_types[8]
-#define SWIGTYPE_p_GDALProgressFunc swig_types[9]
-#define SWIGTYPE_p_GDALRasterAttributeTableShadow swig_types[10]
-#define SWIGTYPE_p_GDALRasterBandShadow swig_types[11]
-#define SWIGTYPE_p_GDALTransformerInfoShadow swig_types[12]
-#define SWIGTYPE_p_GDAL_GCP swig_types[13]
-#define SWIGTYPE_p_GUIntBig swig_types[14]
-#define SWIGTYPE_p_OGRLayerShadow swig_types[15]
-#define SWIGTYPE_p_VSIStatBufL swig_types[16]
-#define SWIGTYPE_p_char swig_types[17]
-#define SWIGTYPE_p_double swig_types[18]
-#define SWIGTYPE_p_f_double_p_q_const__char_p_void__int swig_types[19]
-#define SWIGTYPE_p_int swig_types[20]
-#define SWIGTYPE_p_p_GDALRasterBandShadow swig_types[21]
-#define SWIGTYPE_p_p_GDAL_GCP swig_types[22]
-#define SWIGTYPE_p_p_GUIntBig swig_types[23]
-#define SWIGTYPE_p_p_char swig_types[24]
-#define SWIGTYPE_p_void swig_types[25]
-static swig_type_info *swig_types[27];
-static swig_module_info swig_module = {swig_types, 26, 0, 0, 0, 0};
-#define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)
-#define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)
-
-/* -------- TYPES TABLE (END) -------- */
-
-#define SWIG_init    boot_Geo__GDAL
-
-#define SWIG_name   "Geo::GDALc::boot_Geo__GDAL"
-#define SWIG_prefix "Geo::GDALc::"
-
-#define SWIGVERSION 0x020012 
-#define SWIG_VERSION SWIGVERSION
-
-
-#define SWIG_as_voidptr(a) const_cast< void * >(static_cast< const void * >(a)) 
-#define SWIG_as_voidptrptr(a) ((void)SWIG_as_voidptr(*a),reinterpret_cast< void** >(a)) 
-
-
-#include <stdexcept>
-
-
-#ifdef __cplusplus
-extern "C"
-#endif
-#ifndef PERL_OBJECT
-#ifndef MULTIPLICITY
-SWIGEXPORT void SWIG_init (CV* cv);
-#else
-SWIGEXPORT void SWIG_init (pTHXo_ CV* cv);
-#endif
-#else
-SWIGEXPORT void SWIG_init (CV *cv, CPerlObj *);
-#endif
-
-
-#include <iostream>
-using namespace std;
-
-#include "cpl_port.h"
-#include "cpl_string.h"
-#include "cpl_multiproc.h"
-#include "cpl_http.h"
-
-#include "gdal.h"
-#include "gdal_priv.h"
-#include "gdal_alg.h"
-#include "gdalwarper.h"
-
-typedef void GDALMajorObjectShadow;
-typedef void GDALDriverShadow;
-typedef void GDALDatasetShadow;
-typedef void GDALRasterBandShadow;
-typedef void GDALColorTableShadow;
-typedef void GDALRasterAttributeTableShadow;
-typedef void GDALTransformerInfoShadow;
-typedef void GDALAsyncReaderShadow;
-
-
-/* use this to not return the int returned by GDAL */
-typedef int RETURN_NONE;
-/* return value that is used for VSI methods that return -1 on error (and set errno) */
-typedef int VSI_RETVAL;
-
-
-
-    #ifndef SWIG
-    typedef struct
-    {
-        SV *fct;
-        SV *data;
-    } SavedEnv;
-    #endif
-    int callback_d_cp_vp(double d, const char *cp, void *vp)
-    {
-        int count, ret;
-        SavedEnv *env_ptr = (SavedEnv *)vp;
-        dSP;
-        ENTER;
-        SAVETMPS;
-        PUSHMARK(SP);
-        XPUSHs(sv_2mortal(newSVnv(d)));
-        XPUSHs(sv_2mortal(newSVpv(cp, 0)));
-        if (env_ptr->data)
-            XPUSHs(env_ptr->data);
-        PUTBACK;
-        count = call_sv(env_ptr->fct, G_SCALAR);
-        SPAGAIN;
-        if (count != 1) {
-            fprintf(stderr, "The callback must return only one value.\n");
-            return 0; /* interrupt */
-        }
-        ret = POPi;
-        PUTBACK;
-        FREETMPS;
-        LEAVE;
-        return ret;
-    }
-
-
-SWIGINTERN int
-SWIG_AsVal_double SWIG_PERL_DECL_ARGS_2(SV *obj, double *val)
-{
-  if (SvNIOK(obj)) {
-    if (val) *val = SvNV(obj);
-    return SWIG_OK;
-  } else if (SvIOK(obj)) {
-    if (val) *val = (double) SvIV(obj);
-    return SWIG_AddCast(SWIG_OK);
-  } else {
-    const char *nptr = SvPV_nolen(obj);
-    if (nptr) {
-      char *endptr;
-      double v;
-      errno = 0;
-      v = strtod(nptr, &endptr);
-      if (errno == ERANGE) {
-	errno = 0;
-	return SWIG_OverflowError;
-      } else {
-	if (*endptr == '\0') {
-	  if (val) *val = v;
-	  return SWIG_Str2NumCast(SWIG_OK);
-	}
-      }
-    }
-  }
-  return SWIG_TypeError;
-}
-
-
-SWIGINTERN swig_type_info*
-SWIG_pchar_descriptor(void)
-{
-  static int init = 0;
-  static swig_type_info* info = 0;
-  if (!init) {
-    info = SWIG_TypeQuery("_p_char");
-    init = 1;
-  }
-  return info;
-}
-
-
-SWIGINTERN int
-SWIG_AsCharPtrAndSize(SV *obj, char** cptr, size_t* psize, int *alloc)
-{
-  if (SvMAGICAL(obj)) {
-     SV *tmp = sv_newmortal();
-     SvSetSV(tmp, obj);
-     obj = tmp;
-  }
-  if (SvPOK(obj)) {
-    STRLEN len = 0;
-    char *cstr = SvPV(obj, len); 
-    size_t size = len + 1;
-    if (cptr)  {
-      if (alloc) {
-	if (*alloc == SWIG_NEWOBJ) {
-	  *cptr = reinterpret_cast< char* >(memcpy((new char[size]), cstr, sizeof(char)*(size)));
-	} else {
-	  *cptr = cstr;
-	  *alloc = SWIG_OLDOBJ;
-	}
-      }
-    }
-    if (psize) *psize = size;
-    return SWIG_OK;
-  } else {
-    swig_type_info* pchar_descriptor = SWIG_pchar_descriptor();
-    if (pchar_descriptor) {
-      char* vptr = 0; 
-      if (SWIG_ConvertPtr(obj, (void**)&vptr, pchar_descriptor, 0) == SWIG_OK) {
-	if (cptr) *cptr = vptr;
-	if (psize) *psize = vptr ? (strlen(vptr) + 1) : 0;
-	if (alloc) *alloc = SWIG_OLDOBJ;
-	return SWIG_OK;
-      }
-    }
-  }
-  return SWIG_TypeError;
-}
-
-
-
-
-
-SWIGINTERNINLINE SV *
-SWIG_From_long  SWIG_PERL_DECL_ARGS_1(long value)
-{
-  SV *sv;
-  if (value >= IV_MIN && value <= IV_MAX)
-    sv = newSViv(value);
-  else
-    sv = newSVpvf("%ld", value);
-  return sv_2mortal(sv);
-}
-
-
-SWIGINTERNINLINE SV *
-SWIG_From_int  SWIG_PERL_DECL_ARGS_1(int value)
-{    
-  return SWIG_From_long  SWIG_PERL_CALL_ARGS_1(value);
-}
-
-
-void VeryQuiteErrorHandler(CPLErr eclass, int code, const char *msg ) {
-  /* If the error class is CE_Fatal, we want to have a message issued
-     because the CPL support code does an abort() before any exception
-     can be generated */
-  if (eclass == CE_Fatal ) {
-    CPLDefaultErrorHandler(eclass, code, msg );
-  }
-}
-
-
-void UseExceptions() {
-  CPLSetErrorHandler( (CPLErrorHandler) VeryQuiteErrorHandler );
-}
-
-void DontUseExceptions() {
-  CPLSetErrorHandler( CPLDefaultErrorHandler );
-}
-
-
-typedef void OGRLayerShadow;
-
-
-typedef char retStringAndCPLFree;
-
-
-  void Debug( const char *msg_class, const char *message ) {
-    CPLDebug( msg_class, "%s", message );
-  }
-
-  CPLErr SetErrorHandler( char const * pszCallbackName = NULL )
-  {
-    CPLErrorHandler pfnHandler = NULL;
-    if( pszCallbackName == NULL || EQUAL(pszCallbackName,"CPLQuietErrorHandler") )
-      pfnHandler = CPLQuietErrorHandler;
-    else if( EQUAL(pszCallbackName,"CPLDefaultErrorHandler") )
-      pfnHandler = CPLDefaultErrorHandler;
-    else if( EQUAL(pszCallbackName,"CPLLoggingErrorHandler") )
-      pfnHandler = CPLLoggingErrorHandler;
-
-    if ( pfnHandler == NULL )
-      return CE_Fatal;
-
-    CPLSetErrorHandler( pfnHandler );
-
-    return CE_None;
-  }
-
-
-  CPLErr PushErrorHandler( char const * pszCallbackName = NULL ) {
-    CPLErrorHandler pfnHandler = NULL;
-    if( pszCallbackName == NULL || EQUAL(pszCallbackName,"CPLQuietErrorHandler") )
-      pfnHandler = CPLQuietErrorHandler;
-    else if( EQUAL(pszCallbackName,"CPLDefaultErrorHandler") )
-      pfnHandler = CPLDefaultErrorHandler;
-    else if( EQUAL(pszCallbackName,"CPLLoggingErrorHandler") )
-      pfnHandler = CPLLoggingErrorHandler;
-
-    if ( pfnHandler == NULL )
-      return CE_Fatal;
-
-    CPLPushErrorHandler( pfnHandler );
-
-    return CE_None;
-  }
-
-
-  void Error( CPLErr msg_class = CE_Failure, int err_code = 0, const char* msg = "error" ) {
-    CPLError( msg_class, err_code, "%s", msg );
-  }
-
-
-#include <limits.h>
-#if !defined(SWIG_NO_LLONG_MAX)
-# if !defined(LLONG_MAX) && defined(__GNUC__) && defined (__LONG_LONG_MAX__)
-#   define LLONG_MAX __LONG_LONG_MAX__
-#   define LLONG_MIN (-LLONG_MAX - 1LL)
-#   define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL)
-# endif
-#endif
-
-
-#include <float.h>
-
-
-#include <math.h>
-
-
-SWIGINTERNINLINE int
-SWIG_CanCastAsInteger(double *d, double min, double max) {
-  double x = *d;
-  if ((min <= x && x <= max)) {
-   double fx = floor(x);
-   double cx = ceil(x);
-   double rd =  ((x - fx) < 0.5) ? fx : cx; /* simple rint */
-   if ((errno == EDOM) || (errno == ERANGE)) {
-     errno = 0;
-   } else {
-     double summ, reps, diff;
-     if (rd < x) {
-       diff = x - rd;
-     } else if (rd > x) {
-       diff = rd - x;
-     } else {
-       return 1;
-     }
-     summ = rd + x;
-     reps = diff/summ;
-     if (reps < 8*DBL_EPSILON) {
-       *d = rd;
-       return 1;
-     }
-   }
-  }
-  return 0;
-}
-
-
-SWIGINTERN int
-SWIG_AsVal_long SWIG_PERL_DECL_ARGS_2(SV *obj, long* val)
-{
-  if (SvUOK(obj)) {
-    UV v = SvUV(obj);
-    if (v <= LONG_MAX) {
-      if (val) *val = v;
-      return SWIG_OK;
-    }
-    return SWIG_OverflowError;
-  } else if (SvIOK(obj)) {
-    IV v = SvIV(obj);
-    if (v >= LONG_MIN && v <= LONG_MAX) {
-      if(val) *val = v;
-      return SWIG_OK;
-    }
-    return SWIG_OverflowError;
-  } else {
-    int dispatch = 0;
-    const char *nptr = SvPV_nolen(obj);
-    if (nptr) {
-      char *endptr;
-      long v;
-      errno = 0;
-      v = strtol(nptr, &endptr,0);
-      if (errno == ERANGE) {
-	errno = 0;
-	return SWIG_OverflowError;
-      } else {
-	if (*endptr == '\0') {
-	  if (val) *val = v;
-	  return SWIG_Str2NumCast(SWIG_OK);
-	}
-      }
-    }
-    if (!dispatch) {
-      double d;
-      int res = SWIG_AddCast(SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(obj,&d));
-      if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LONG_MIN, LONG_MAX)) {
-	if (val) *val = (long)(d);
-	return res;
-      }
-    }
-  }
-  return SWIG_TypeError;
-}
-
-
-SWIGINTERN int
-SWIG_AsVal_int SWIG_PERL_DECL_ARGS_2(SV * obj, int *val)
-{
-  long v;
-  int res = SWIG_AsVal_long SWIG_PERL_CALL_ARGS_2(obj, &v);
-  if (SWIG_IsOK(res)) {
-    if ((v < INT_MIN || v > INT_MAX)) {
-      return SWIG_OverflowError;
-    } else {
-      if (val) *val = static_cast< int >(v);
-    }
-  }  
-  return res;
-}
-
-
-retStringAndCPLFree* EscapeString(int len, char *bin_string , int scheme=CPLES_SQL) {
-    return CPLEscapeString(bin_string, len, scheme);
-} 
-
-
-const char *wrapper_CPLGetConfigOption( const char * pszKey, const char * pszDefault = NULL )
-{
-    return CPLGetConfigOption( pszKey, pszDefault );
-}
-
-
-void wrapper_VSIFileFromMemBuffer( const char* utf8_path, int nBytes, const GByte *pabyData)
-{
-    GByte* pabyDataDup = (GByte*)VSIMalloc(nBytes);
-    if (pabyDataDup == NULL)
-            return;
-    memcpy(pabyDataDup, pabyData, nBytes);
-    VSIFCloseL(VSIFileFromMemBuffer(utf8_path, (GByte*) pabyDataDup, nBytes, TRUE));
-}
-
-
-
-int wrapper_HasThreadSupport()
-{
-    return strcmp(CPLGetThreadingModel(), "stub") != 0;
-}
-
-
-VSILFILE   *wrapper_VSIFOpenL( const char *utf8_path, const char *pszMode )
-{
-    if (!pszMode) /* would lead to segfault */
-        pszMode = "r";
-    return VSIFOpenL( utf8_path, pszMode );
-}
-
-
-SWIGINTERN int
-SWIG_AsVal_unsigned_SS_long SWIG_PERL_DECL_ARGS_2(SV *obj, unsigned long *val) 
-{
-  if (SvUOK(obj)) {
-    UV v = SvUV(obj);
-    if (v <= ULONG_MAX) {
-      if (val) *val = v;
-      return SWIG_OK;
-    }
-    return SWIG_OverflowError;
-  } else if (SvIOK(obj)) {
-    IV v = SvIV(obj);
-    if (v >= 0 && v <= ULONG_MAX) {
-      if (val) *val = v;
-      return SWIG_OK;
-    }
-    return SWIG_OverflowError;
-  } else {
-    int dispatch = 0;
-    const char *nptr = SvPV_nolen(obj);
-    if (nptr) {
-      char *endptr;
-      unsigned long v;
-      errno = 0;
-      v = strtoul(nptr, &endptr,0);
-      if (errno == ERANGE) {
-	errno = 0;
-	return SWIG_OverflowError;
-      } else {
-	if (*endptr == '\0') {
-	  if (val) *val = v;
-	  return SWIG_Str2NumCast(SWIG_OK);
-	}
-      }
-    }
-    if (!dispatch) {
-      double d;
-      int res = SWIG_AddCast(SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(obj,&d));
-      if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, ULONG_MAX)) {
-	if (val) *val = (unsigned long)(d);
-	return res;
-      }
-    }
-  }
-  return SWIG_TypeError;
-}
-
-
-SWIGINTERNINLINE int
-SWIG_AsVal_size_t SWIG_PERL_DECL_ARGS_2(SV * obj, size_t *val)
-{
-  unsigned long v;
-  int res = SWIG_AsVal_unsigned_SS_long SWIG_PERL_CALL_ARGS_2(obj, val ? &v : 0);
-  if (SWIG_IsOK(res) && val) *val = static_cast< size_t >(v);
-  return res;
-}
-
-
-SWIGINTERNINLINE SV *
-SWIG_From_unsigned_SS_long  SWIG_PERL_DECL_ARGS_1(unsigned long value)
-{
-  SV *sv;
-  if (value <= UV_MAX)
-    sv = newSVuv(value);
-  else
-    sv = newSVpvf("%lu", value);
-  return sv_2mortal(sv);
-}
-
-
-SWIGINTERNINLINE SV *
-SWIG_From_size_t  SWIG_PERL_DECL_ARGS_1(size_t value)
-{    
-  return SWIG_From_unsigned_SS_long  SWIG_PERL_CALL_ARGS_1(static_cast< unsigned long >(value));
-}
-
-SWIGINTERN char const *GDALMajorObjectShadow_GetDescription(GDALMajorObjectShadow *self){
-    return GDALGetDescription( self );
-  }
-SWIGINTERN void GDALMajorObjectShadow_SetDescription(GDALMajorObjectShadow *self,char const *pszNewDesc){
-    GDALSetDescription( self, pszNewDesc );
-  }
-SWIGINTERN char **GDALMajorObjectShadow_GetMetadataDomainList(GDALMajorObjectShadow *self){
-    return GDALGetMetadataDomainList( self );
-  }
-SWIGINTERN char **GDALMajorObjectShadow_GetMetadata_Dict(GDALMajorObjectShadow *self,char const *pszDomain=""){
-    return GDALGetMetadata( self, pszDomain );
-  }
-SWIGINTERN CPLErr GDALMajorObjectShadow_SetMetadata__SWIG_0(GDALMajorObjectShadow *self,char **papszMetadata,char const *pszDomain=""){
-    return GDALSetMetadata( self, papszMetadata, pszDomain );
-  }
-SWIGINTERN CPLErr GDALMajorObjectShadow_SetMetadata__SWIG_1(GDALMajorObjectShadow *self,char *pszMetadataString,char const *pszDomain=""){
-    char *tmpList[2];
-    tmpList[0] = pszMetadataString;
-    tmpList[1] = 0;
-    return GDALSetMetadata( self, tmpList, pszDomain );
-  }
-SWIGINTERN char const *GDALMajorObjectShadow_GetMetadataItem(GDALMajorObjectShadow *self,char const *pszName,char const *pszDomain=""){
-    return GDALGetMetadataItem( self, pszName, pszDomain);
-  }
-SWIGINTERN CPLErr GDALMajorObjectShadow_SetMetadataItem(GDALMajorObjectShadow *self,char const *pszName,char const *pszValue,char const *pszDomain=""){
-    return GDALSetMetadataItem( self, pszName, pszValue, pszDomain);
-  }
-SWIGINTERN GDALDatasetShadow *GDALDriverShadow_Create(GDALDriverShadow *self,char const *utf8_path,int xsize,int ysize,int bands=1,GDALDataType eType=GDT_Byte,char **options=0){
-
-    GDALDatasetShadow* ds = (GDALDatasetShadow*) GDALCreate(    self, 
-                                                                utf8_path, 
-                                                                xsize, 
-                                                                ysize, 
-                                                                bands, 
-                                                                eType, 
-                                                                options );
-    return ds;
-  }
-SWIGINTERN GDALDatasetShadow *GDALDriverShadow_CreateCopy(GDALDriverShadow *self,char const *utf8_path,GDALDatasetShadow *src,int strict=1,char **options=0,GDALProgressFunc callback=NULL,void *callback_data=NULL){
-
-    GDALDatasetShadow *ds = (GDALDatasetShadow*) GDALCreateCopy(    self, 
-                                                                    utf8_path, 
-                                                                    src, 
-                                                                    strict, 
-                                                                    options, 
-                                                                    callback, 
-                                                                    callback_data );
-    return ds;
-  }
-SWIGINTERN CPLErr GDALDriverShadow_Delete(GDALDriverShadow *self,char const *utf8_path){
-    return GDALDeleteDataset( self, utf8_path );
-  }
-SWIGINTERN CPLErr GDALDriverShadow_Rename(GDALDriverShadow *self,char const *newName,char const *oldName){
-    return GDALRenameDataset( self, newName, oldName );
-  }
-SWIGINTERN CPLErr GDALDriverShadow_CopyFiles(GDALDriverShadow *self,char const *newName,char const *oldName){
-    return GDALCopyDatasetFiles( self, newName, oldName );
-  }
-SWIGINTERN int GDALDriverShadow_Register(GDALDriverShadow *self){
-    return GDALRegisterDriver( self );
-  }
-SWIGINTERN void GDALDriverShadow_Deregister(GDALDriverShadow *self){
-    GDALDeregisterDriver( self );
-  }
-
-char const *GDALDriverShadow_ShortName_get( GDALDriverShadow *h ) {
-  return GDALGetDriverShortName( h );
-}
-char const *GDALDriverShadow_LongName_get( GDALDriverShadow *h ) {
-  return GDALGetDriverLongName( h );
-}
-char const *GDALDriverShadow_HelpTopic_get( GDALDriverShadow *h ) {
-  return GDALGetDriverHelpTopic( h );
-}
-
-
-SWIGINTERNINLINE SV *
-SWIG_From_double  SWIG_PERL_DECL_ARGS_1(double value)
-{
-  return sv_2mortal(newSVnv(value));
-}
-
-
-SWIGINTERNINLINE SV *
-SWIG_FromCharPtrAndSize(const char* carray, size_t size)
-{
-  SV *obj = sv_newmortal();
-  if (carray) {
-    sv_setpvn(obj, carray, size);
-  } else {
-    sv_setsv(obj, &PL_sv_undef);
-  }
-  return obj;
-}
-
-
-SWIGINTERNINLINE SV * 
-SWIG_FromCharPtr(const char *cptr)
-{ 
-  return SWIG_FromCharPtrAndSize(cptr, (cptr ? strlen(cptr) : 0));
-}
-
-SWIGINTERN GDAL_GCP *new_GDAL_GCP(double x=0.0,double y=0.0,double z=0.0,double pixel=0.0,double line=0.0,char const *info="",char const *id=""){
-
-    GDAL_GCP *self = (GDAL_GCP*) CPLMalloc( sizeof( GDAL_GCP ) );
-    self->dfGCPX = x;
-    self->dfGCPY = y;
-    self->dfGCPZ = z;
-    self->dfGCPPixel = pixel;
-    self->dfGCPLine = line;
-    self->pszInfo =  CPLStrdup( (info == 0) ? "" : info );
-    self->pszId = CPLStrdup( (id==0)? "" : id );
-    return self;
-  }
-SWIGINTERN void delete_GDAL_GCP(GDAL_GCP *self){
-    if ( self->pszInfo )
-      CPLFree( self->pszInfo );
-    if ( self->pszId )
-      CPLFree( self->pszId );
-    CPLFree( self );
-  }
-
-
-double GDAL_GCP_GCPX_get( GDAL_GCP *gcp ) {
-  return gcp->dfGCPX;
-}
-void GDAL_GCP_GCPX_set( GDAL_GCP *gcp, double dfGCPX ) {
-  gcp->dfGCPX = dfGCPX;
-}
-double GDAL_GCP_GCPY_get( GDAL_GCP *gcp ) {
-  return gcp->dfGCPY;
-}
-void GDAL_GCP_GCPY_set( GDAL_GCP *gcp, double dfGCPY ) {
-  gcp->dfGCPY = dfGCPY;
-}
-double GDAL_GCP_GCPZ_get( GDAL_GCP *gcp ) {
-  return gcp->dfGCPZ;
-}
-void GDAL_GCP_GCPZ_set( GDAL_GCP *gcp, double dfGCPZ ) {
-  gcp->dfGCPZ = dfGCPZ;
-}
-double GDAL_GCP_GCPPixel_get( GDAL_GCP *gcp ) {
-  return gcp->dfGCPPixel;
-}
-void GDAL_GCP_GCPPixel_set( GDAL_GCP *gcp, double dfGCPPixel ) {
-  gcp->dfGCPPixel = dfGCPPixel;
-}
-double GDAL_GCP_GCPLine_get( GDAL_GCP *gcp ) {
-  return gcp->dfGCPLine;
-}
-void GDAL_GCP_GCPLine_set( GDAL_GCP *gcp, double dfGCPLine ) {
-  gcp->dfGCPLine = dfGCPLine;
-}
-const char * GDAL_GCP_Info_get( GDAL_GCP *gcp ) {
-  return gcp->pszInfo;
-}
-void GDAL_GCP_Info_set( GDAL_GCP *gcp, const char * pszInfo ) {
-  if ( gcp->pszInfo ) 
-    CPLFree( gcp->pszInfo );
-  gcp->pszInfo = CPLStrdup(pszInfo);
-}
-const char * GDAL_GCP_Id_get( GDAL_GCP *gcp ) {
-  return gcp->pszId;
-}
-void GDAL_GCP_Id_set( GDAL_GCP *gcp, const char * pszId ) {
-  if ( gcp->pszId ) 
-    CPLFree( gcp->pszId );
-  gcp->pszId = CPLStrdup(pszId);
-}
-
-
-static SV *
-CreateArrayFromDoubleArray( double *first, unsigned int size ) {
-  AV *av = (AV*)sv_2mortal((SV*)newAV());
-  for( unsigned int i=0; i<size; i++ ) {
-    av_store(av,i,newSVnv(*first));
-    ++first;
-  }
-  return sv_2mortal(newRV((SV*)av));
-}
-
-
-/* Returned size is in bytes or 0 if an error occured */
-static
-GIntBig ComputeDatasetRasterIOSize (int buf_xsize, int buf_ysize, int nPixelSize,
-                                int nBands, int* bandMap, int nBandMapArrayLength,
-                                GIntBig nPixelSpace, GIntBig nLineSpace, GIntBig nBandSpace,
-                                int bSpacingShouldBeMultipleOfPixelSize )
-{
-#if SIZEOF_VOIDP == 8
-    const GIntBig MAX_INT = (((GIntBig)0x7fffffff) << 32) | 0xffffffff;
-#else
-    const GIntBig MAX_INT = 0x7fffffff;
-#endif
-
-    if (buf_xsize <= 0 || buf_ysize <= 0)
-    {
-        CPLError(CE_Failure, CPLE_IllegalArg, "Illegal values for buffer size");
-        return 0;
-    }
-
-    if (nPixelSpace < 0 || nLineSpace < 0 || nBandSpace < 0)
-    {
-        CPLError(CE_Failure, CPLE_IllegalArg, "Illegal values for space arguments");
-        return 0;
-    }
-
-    if (nPixelSize == 0)
-    {
-        CPLError(CE_Failure, CPLE_IllegalArg, "Illegal value for data type");
-        return 0;
-    }
-
-    if( nPixelSpace == 0 )
-        nPixelSpace = nPixelSize;
-    else if ( bSpacingShouldBeMultipleOfPixelSize && (nPixelSpace % nPixelSize) != 0 )
-    {
-        CPLError(CE_Failure, CPLE_IllegalArg, "nPixelSpace should be a multiple of nPixelSize");
-        return 0;
-    }
-
-    if( nLineSpace == 0 )
-    {
-        nLineSpace = nPixelSpace * buf_xsize;
-    }
-    else if ( bSpacingShouldBeMultipleOfPixelSize && (nLineSpace % nPixelSize) != 0 )
-    {
-        CPLError(CE_Failure, CPLE_IllegalArg, "nLineSpace should be a multiple of nPixelSize");
-        return 0;
-    }
-
-    if( nBandSpace == 0 )
-    {
-        nBandSpace = nLineSpace * buf_ysize;
-    }
-    else if ( bSpacingShouldBeMultipleOfPixelSize && (nBandSpace % nPixelSize) != 0 )
-    {
-        CPLError(CE_Failure, CPLE_IllegalArg, "nLineSpace should be a multiple of nPixelSize");
-        return 0;
-    }
-
-    if (nBands <= 0 || (bandMap != NULL && nBands > nBandMapArrayLength))
-    {
-        CPLError(CE_Failure, CPLE_IllegalArg, "Invalid band count");
-        return 0;
-    }
-
-    GIntBig nRet = (GIntBig)(buf_ysize - 1) * nLineSpace + (GIntBig)(buf_xsize - 1) * nPixelSpace + (GIntBig)(nBands - 1) * nBandSpace + nPixelSize;
-    if (nRet > MAX_INT)
-    {
-        CPLError(CE_Failure, CPLE_IllegalArg, "Integer overflow");
-        return 0;
-    }
-
-    return nRet;
-}
-
-
-static
-CPLErr DSReadRaster_internal( GDALDatasetShadow *obj, 
-                            int xoff, int yoff, int xsize, int ysize,
-                            int buf_xsize, int buf_ysize,
-                            GDALDataType buf_type,
-                            int *buf_size, char **buf,
-                            int band_list, int *pband_list,
-                            GIntBig pixel_space, GIntBig line_space, GIntBig band_space,
-                            GDALRasterIOExtraArg* psExtraArg)
-{
-  CPLErr result;
-
-  GIntBig nRequiredSize = ComputeDatasetRasterIOSize (buf_xsize, buf_ysize, GDALGetDataTypeSize( buf_type ) / 8,
-                                          band_list ? band_list : GDALGetRasterCount(obj), pband_list, band_list,
-                                          pixel_space, line_space, band_space, FALSE);
-  if (nRequiredSize > 0x7fffffff)
-  {
-     CPLError(CE_Failure, CPLE_IllegalArg, "Integer overflow");
-     nRequiredSize = 0;
-  }
-  *buf_size = (int)nRequiredSize;
-  if (*buf_size == 0)
-  {
-      *buf = 0;
-      return CE_Failure;
-  }
-  
-  *buf = (char*) malloc( *buf_size );
-  if (*buf)
-  {
-    result = GDALDatasetRasterIOEx(obj, GF_Read, xoff, yoff, xsize, ysize,
-                                    (void*) *buf, buf_xsize, buf_ysize, buf_type,
-                                    band_list, pband_list, pixel_space, line_space, band_space,
-                                    psExtraArg );
-    if ( result != CE_None ) {
-        free( *buf );
-        *buf = 0;
-        *buf_size = 0;
-    }
-  }
-  else
-  {
-    CPLError(CE_Failure, CPLE_OutOfMemory, "Not enough memory to allocate %d bytes", *buf_size);
-    result = CE_Failure;
-    *buf = 0;
-    *buf_size = 0;
-  }
-  return result;
-}
-
-
-typedef struct
-{
-    GDALAsyncReaderH  hAsyncReader;
-    void             *pyObject;
-} GDALAsyncReaderWrapper;
-
-typedef void* GDALAsyncReaderWrapperH;
-
-static GDALAsyncReaderH AsyncReaderWrapperGetReader(GDALAsyncReaderWrapperH hWrapper)
-{
-    GDALAsyncReaderWrapper* psWrapper = (GDALAsyncReaderWrapper*)hWrapper;
-    if (psWrapper->hAsyncReader == NULL)
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "AsyncReader object is defunct");
-    }
-    return psWrapper->hAsyncReader;
-}
-
-#if defined(SWIGPYTHON)
-static void* AsyncReaderWrapperGetPyObject(GDALAsyncReaderWrapperH hWrapper)
-{
-    GDALAsyncReaderWrapper* psWrapper = (GDALAsyncReaderWrapper*)hWrapper;
-    return psWrapper->pyObject;
-}
-#endif
-
-static void DeleteAsyncReaderWrapper(GDALAsyncReaderWrapperH hWrapper)
-{
-    GDALAsyncReaderWrapper* psWrapper = (GDALAsyncReaderWrapper*)hWrapper;
-    if (psWrapper->hAsyncReader != NULL)
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Native AsyncReader object will leak. EndAsyncReader() should have been called before");
-    }
-    CPLFree(psWrapper);
-}
-
-
-SWIGINTERN void delete_GDALAsyncReaderShadow(GDALAsyncReaderShadow *self){
-        DeleteAsyncReaderWrapper(self);
-    }
-SWIGINTERN GDALAsyncStatusType GDALAsyncReaderShadow_GetNextUpdatedRegion(GDALAsyncReaderShadow *self,double timeout,int *xoff,int *yoff,int *buf_xsize,int *buf_ysize){
-        GDALAsyncReaderH hReader = AsyncReaderWrapperGetReader(self);
-        if (hReader == NULL)
-        {
-            *xoff = 0;
-            *yoff = 0;
-            *buf_xsize = 0;
-            *buf_ysize = 0;
-            return GARIO_ERROR;
-        }
-        return GDALARGetNextUpdatedRegion(hReader, timeout, xoff, yoff, buf_xsize, buf_ysize );
-    }
-SWIGINTERN int GDALAsyncReaderShadow_LockBuffer(GDALAsyncReaderShadow *self,double timeout){
-        GDALAsyncReaderH hReader = AsyncReaderWrapperGetReader(self);
-        if (hReader == NULL)
-        {
-            return 0;
-        }
-        return GDALARLockBuffer(hReader,timeout);
-    }
-SWIGINTERN void GDALAsyncReaderShadow_UnlockBuffer(GDALAsyncReaderShadow *self){
-        GDALAsyncReaderH hReader = AsyncReaderWrapperGetReader(self);
-        if (hReader == NULL)
-        {
-            return;
-        }
-        GDALARUnlockBuffer(hReader);
-    }
-SWIGINTERN void delete_GDALDatasetShadow(GDALDatasetShadow *self){
-    if ( GDALDereferenceDataset( self ) <= 0 ) {
-      GDALClose(self);
-    }
-  }
-SWIGINTERN GDALDriverShadow *GDALDatasetShadow_GetDriver(GDALDatasetShadow *self){
-    return (GDALDriverShadow*) GDALGetDatasetDriver( self );
-  }
-SWIGINTERN GDALRasterBandShadow *GDALDatasetShadow_GetRasterBand(GDALDatasetShadow *self,int nBand){
-    return (GDALRasterBandShadow*) GDALGetRasterBand( self, nBand );
-  }
-SWIGINTERN char const *GDALDatasetShadow_GetProjection(GDALDatasetShadow *self){
-    return GDALGetProjectionRef( self );
-  }
-SWIGINTERN char const *GDALDatasetShadow_GetProjectionRef(GDALDatasetShadow *self){
-    return GDALGetProjectionRef( self );
-  }
-SWIGINTERN CPLErr GDALDatasetShadow_SetProjection(GDALDatasetShadow *self,char const *prj){
-    return GDALSetProjection( self, prj );
-  }
-SWIGINTERN void GDALDatasetShadow_GetGeoTransform(GDALDatasetShadow *self,double argout[6]){
-    if ( GDALGetGeoTransform( self, argout ) != CE_None ) {
-      argout[0] = 0.0;
-      argout[1] = 1.0;
-      argout[2] = 0.0;
-      argout[3] = 0.0;
-      argout[4] = 0.0;
-      argout[5] = 1.0;
-    }
-  }
-SWIGINTERN CPLErr GDALDatasetShadow_SetGeoTransform(GDALDatasetShadow *self,double argin[6]){
-    return GDALSetGeoTransform( self, argin );
-  }
-SWIGINTERN int GDALDatasetShadow_BuildOverviews(GDALDatasetShadow *self,char const *resampling="NEAREST",int overviewlist=0,int *pOverviews=0,GDALProgressFunc callback=NULL,void *callback_data=NULL){
-
-    return GDALBuildOverviews(  self, 
-                                resampling ? resampling : "NEAREST", 
-                                overviewlist, 
-                                pOverviews, 
-                                0, 
-                                0, 
-                                callback, 
-                                callback_data);
-  }
-SWIGINTERN int GDALDatasetShadow_GetGCPCount(GDALDatasetShadow *self){
-    return GDALGetGCPCount( self );
-  }
-SWIGINTERN char const *GDALDatasetShadow_GetGCPProjection(GDALDatasetShadow *self){
-    return GDALGetGCPProjection( self );
-  }
-SWIGINTERN void GDALDatasetShadow_GetGCPs(GDALDatasetShadow *self,int *nGCPs,GDAL_GCP const **pGCPs){
-    *nGCPs = GDALGetGCPCount( self );
-    *pGCPs = GDALGetGCPs( self );
-  }
-SWIGINTERN CPLErr GDALDatasetShadow_SetGCPs(GDALDatasetShadow *self,int nGCPs,GDAL_GCP const *pGCPs,char const *pszGCPProjection){
-    return GDALSetGCPs( self, nGCPs, pGCPs, pszGCPProjection );
-  }
-SWIGINTERN void GDALDatasetShadow_FlushCache(GDALDatasetShadow *self){
-    GDALFlushCache( self );
-  }
-SWIGINTERN CPLErr GDALDatasetShadow_AddBand(GDALDatasetShadow *self,GDALDataType datatype=GDT_Byte,char **options=0){
-    return GDALAddBand( self, datatype, options );
-  }
-SWIGINTERN CPLErr GDALDatasetShadow_CreateMaskBand(GDALDatasetShadow *self,int nFlags){
-      return GDALCreateDatasetMaskBand( self, nFlags );
-  }
-SWIGINTERN char **GDALDatasetShadow_GetFileList(GDALDatasetShadow *self){
-    return GDALGetFileList( self );
-  }
-SWIGINTERN CPLErr GDALDatasetShadow_WriteRaster(GDALDatasetShadow *self,int xoff,int yoff,int xsize,int ysize,int buf_len,char *buf_string,int *buf_xsize=0,int *buf_ysize=0,GDALDataType *buf_type=0,int band_list=0,int *pband_list=0,int *buf_pixel_space=0,int *buf_line_space=0,int *buf_band_space=0){
-    CPLErr eErr;
-    int nxsize = (buf_xsize==0) ? xsize : *buf_xsize;
-    int nysize = (buf_ysize==0) ? ysize : *buf_ysize;
-    GDALDataType ntype;
-    if ( buf_type != 0 ) {
-      ntype = (GDALDataType) *buf_type;
-    } else {
-      int lastband = GDALGetRasterCount( self ) - 1;
-      if (lastband < 0)
-        return CE_Failure;
-      ntype = GDALGetRasterDataType( GDALGetRasterBand( self, lastband ) );
-    }
-
-    int pixel_space = (buf_pixel_space == 0) ? 0 : *buf_pixel_space;
-    int line_space = (buf_line_space == 0) ? 0 : *buf_line_space;
-    int band_space = (buf_band_space == 0) ? 0 : *buf_band_space;
-
-    GIntBig min_buffer_size =
-      ComputeDatasetRasterIOSize (nxsize, nysize, GDALGetDataTypeSize( ntype ) / 8,
-                                  band_list ? band_list : GDALGetRasterCount(self), pband_list, band_list,
-                                  pixel_space, line_space, band_space, FALSE);
-    if (min_buffer_size == 0)
-        return CE_Failure;
-
-    if ( buf_len < min_buffer_size )
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
-        return CE_Failure;
-    }
-  
-    eErr = GDALDatasetRasterIO( self, GF_Write, xoff, yoff, xsize, ysize,
-                                (void*) buf_string, nxsize, nysize, ntype,
-                                band_list, pband_list, pixel_space, line_space, band_space );
-
-    return eErr;
-  }
-SWIGINTERN CPLErr GDALDatasetShadow_ReadRaster(GDALDatasetShadow *self,int xoff,int yoff,int xsize,int ysize,int *buf_len,char **buf,int *buf_xsize=0,int *buf_ysize=0,GDALDataType *buf_type=0,int band_list=0,int *pband_list=0,int *buf_pixel_space=0,int *buf_line_space=0,int *buf_band_space=0,GDALRIOResampleAlg resample_alg=GRIORA_NearestNeighbour,GDALProgressFunc callback=NULL,void *callback_data=NULL){
-    CPLErr eErr;
-    int nxsize = (buf_xsize==0) ? xsize : *buf_xsize;
-    int nysize = (buf_ysize==0) ? ysize : *buf_ysize;
-    GDALDataType ntype;
-    if ( buf_type != 0 ) {
-      ntype = (GDALDataType) *buf_type;
-    } else {
-      int lastband = GDALGetRasterCount( self ) - 1;
-      if (lastband < 0)
-        return CE_Failure;
-      ntype = GDALGetRasterDataType( GDALGetRasterBand( self, lastband ) );
-    }
-
-    GDALRasterIOExtraArg sExtraArg;
-    INIT_RASTERIO_EXTRA_ARG(sExtraArg);
-    sExtraArg.eResampleAlg = resample_alg;
-    sExtraArg.pfnProgress = callback;
-    sExtraArg.pProgressData = callback_data;
-
-    GIntBig pixel_space = (buf_pixel_space == 0) ? 0 : *buf_pixel_space;
-    GIntBig line_space = (buf_line_space == 0) ? 0 : *buf_line_space;
-    GIntBig band_space = (buf_band_space == 0) ? 0 : *buf_band_space;
-                            
-    eErr = DSReadRaster_internal( self, xoff, yoff, xsize, ysize,
-                                nxsize, nysize, ntype,
-                                buf_len, buf, 
-                                band_list, pband_list,
-                                pixel_space, line_space, band_space, &sExtraArg);
-
-    return eErr;
-}
-SWIGINTERN OGRErr GDALDatasetShadow_StartTransaction(GDALDatasetShadow *self,int force=FALSE){
-    return GDALDatasetStartTransaction(self, force);
-  }
-
-
-#include "ogr_core.h"
-static char const *
-OGRErrMessages( int rc ) {
-  switch( rc ) {
-  case OGRERR_NONE:
-    return "OGR Error: None";
-  case OGRERR_NOT_ENOUGH_DATA:
-    return "OGR Error: Not enough data to deserialize";
-  case OGRERR_NOT_ENOUGH_MEMORY:
-    return "OGR Error: Not enough memory";
-  case OGRERR_UNSUPPORTED_GEOMETRY_TYPE:
-    return "OGR Error: Unsupported geometry type";
-  case OGRERR_UNSUPPORTED_OPERATION:
-    return "OGR Error: Unsupported operation";
-  case OGRERR_CORRUPT_DATA:
-    return "OGR Error: Corrupt data";
-  case OGRERR_FAILURE:
-    return "OGR Error: General Error";
-  case OGRERR_UNSUPPORTED_SRS:
-    return "OGR Error: Unsupported SRS";
-  case OGRERR_INVALID_HANDLE:
-    return "OGR Error: Invalid handle";
-  case OGRERR_NON_EXISTING_FEATURE:
-    return "OGR Error: Non existing feature";
-  default:
-    return "OGR Error: Unknown";
-  }
-}
-
-SWIGINTERN OGRErr GDALDatasetShadow_CommitTransaction(GDALDatasetShadow *self){
-    return GDALDatasetCommitTransaction(self);
-  }
-SWIGINTERN OGRErr GDALDatasetShadow_RollbackTransaction(GDALDatasetShadow *self){
-    return GDALDatasetRollbackTransaction(self);
-  }
-
-int GDALDatasetShadow_RasterXSize_get( GDALDatasetShadow *h ) {
-  return GDALGetRasterXSize( h );
-}
-int GDALDatasetShadow_RasterYSize_get( GDALDatasetShadow *h ) {
-  return GDALGetRasterYSize( h );
-}
-int GDALDatasetShadow_RasterCount_get( GDALDatasetShadow *h ) {
-  return GDALGetRasterCount( h );
-}
-
-
-/* Returned size is in bytes or 0 if an error occured */
-static
-GIntBig ComputeBandRasterIOSize (int buf_xsize, int buf_ysize, int nPixelSize,
-                                 GIntBig nPixelSpace, GIntBig nLineSpace,
-                                 int bSpacingShouldBeMultipleOfPixelSize )
-{
-#if SIZEOF_VOIDP == 8
-    const GIntBig MAX_INT = (((GIntBig)0x7fffffff) << 32) | 0xffffffff;
-#else
-    const GIntBig MAX_INT = 0x7fffffff;
-#endif
-
-    if (buf_xsize <= 0 || buf_ysize <= 0)
-    {
-        CPLError(CE_Failure, CPLE_IllegalArg, "Illegal values for buffer size");
-        return 0;
-    }
-
-    if (nPixelSpace < 0 || nLineSpace < 0)
-    {
-        CPLError(CE_Failure, CPLE_IllegalArg, "Illegal values for space arguments");
-        return 0;
-    }
-
-    if (nPixelSize == 0)
-    {
-        CPLError(CE_Failure, CPLE_IllegalArg, "Illegal value for data type");
-        return 0;
-    }
-
-    if( nPixelSpace == 0 )
-        nPixelSpace = nPixelSize;
-    else if ( bSpacingShouldBeMultipleOfPixelSize && (nPixelSpace % nPixelSize) != 0 )
-    {
-        CPLError(CE_Failure, CPLE_IllegalArg, "nPixelSpace should be a multiple of nPixelSize");
-        return 0;
-    }
-
-    if( nLineSpace == 0 )
-    {
-        nLineSpace = nPixelSpace * buf_xsize;
-    }
-    else if ( bSpacingShouldBeMultipleOfPixelSize && (nLineSpace % nPixelSize) != 0 )
-    {
-        CPLError(CE_Failure, CPLE_IllegalArg, "nLineSpace should be a multiple of nPixelSize");
-        return 0;
-    }
-
-    GIntBig nRet = (GIntBig)(buf_ysize - 1) * nLineSpace + (GIntBig)(buf_xsize - 1) * nPixelSpace + nPixelSize;
-    if (nRet > MAX_INT)
-    {
-        CPLError(CE_Failure, CPLE_IllegalArg, "Integer overflow");
-        return 0;
-    }
-
-    return nRet;
-}
-
-
-static
-CPLErr ReadRaster_internal( GDALRasterBandShadow *obj, 
-                            int xoff, int yoff, int xsize, int ysize,
-                            int buf_xsize, int buf_ysize,
-                            GDALDataType buf_type,
-                            int *buf_size, char **buf,
-                            GIntBig pixel_space, GIntBig line_space,
-                            GDALRasterIOExtraArg* psExtraArg )
-{
-  CPLErr result;
-
-  GIntBig nRequiredSize = ComputeBandRasterIOSize( buf_xsize, buf_ysize, GDALGetDataTypeSize( buf_type ) / 8,
-                                       pixel_space, line_space, FALSE );
-  if (nRequiredSize > 0x7fffffff)
-  {
-     CPLError(CE_Failure, CPLE_IllegalArg, "Integer overflow");
-     nRequiredSize = 0;
-  }
-  *buf_size = (int)nRequiredSize;
-  
-  if ( *buf_size == 0 )
-  {
-      *buf = 0;
-      return CE_Failure;
-  }
-  
-  *buf = (char*) malloc( *buf_size );
-  if ( *buf )
-  {
-    result =  GDALRasterIOEx( obj, GF_Read, xoff, yoff, xsize, ysize,
-                                    (void *) *buf, buf_xsize, buf_ysize,
-                                    buf_type, pixel_space, line_space, psExtraArg );
-    if ( result != CE_None )
-    {
-        free( *buf );
-        *buf = 0;
-        *buf_size = 0;
-    }
-  }
-  else
-  {
-    CPLError(CE_Failure, CPLE_OutOfMemory, "Not enough memory to allocate %d bytes", *buf_size);
-    result = CE_Failure;
-    *buf = 0;
-    *buf_size = 0;
-  }
-
-  return result;
-}
-
-
-static
-CPLErr WriteRaster_internal( GDALRasterBandShadow *obj,
-                             int xoff, int yoff, int xsize, int ysize,
-                             int buf_xsize, int buf_ysize,
-                             GDALDataType buf_type,
-                             GIntBig buf_size, char *buffer,
-                             int pixel_space, int line_space)
-{
-    GIntBig min_buffer_size = ComputeBandRasterIOSize (buf_xsize, buf_ysize, GDALGetDataTypeSize( buf_type ) / 8,
-                                                   pixel_space, line_space, FALSE );
-    if ( min_buffer_size == 0 )
-      return CE_Failure;
-      
-    if ( buf_size < min_buffer_size ) {
-      CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
-      return CE_Failure;
-    }
-
-    return GDALRasterIO( obj, GF_Write, xoff, yoff, xsize, ysize, 
-		        (void *) buffer, buf_xsize, buf_ysize, buf_type, pixel_space, line_space );
-}
-
-SWIGINTERN GDALDatasetShadow *GDALRasterBandShadow_GetDataset(GDALRasterBandShadow *self){
-    return (GDALDatasetShadow*) GDALGetBandDataset(self);
-  }
-SWIGINTERN int GDALRasterBandShadow_GetBand(GDALRasterBandShadow *self){
-    return GDALGetBandNumber(self);
-  }
-SWIGINTERN void GDALRasterBandShadow_GetBlockSize(GDALRasterBandShadow *self,int *pnBlockXSize,int *pnBlockYSize){
-      GDALGetBlockSize(self, pnBlockXSize, pnBlockYSize);
-  }
-SWIGINTERN GDALColorInterp GDALRasterBandShadow_GetColorInterpretation(GDALRasterBandShadow *self){
-    return GDALGetRasterColorInterpretation( self );
-  }
-SWIGINTERN GDALColorInterp GDALRasterBandShadow_GetRasterColorInterpretation(GDALRasterBandShadow *self){
-    return GDALGetRasterColorInterpretation( self );
-  }
-SWIGINTERN CPLErr GDALRasterBandShadow_SetColorInterpretation(GDALRasterBandShadow *self,GDALColorInterp val){
-    return GDALSetRasterColorInterpretation( self, val );
-  }
-SWIGINTERN CPLErr GDALRasterBandShadow_SetRasterColorInterpretation(GDALRasterBandShadow *self,GDALColorInterp val){
-    return GDALSetRasterColorInterpretation( self, val );
-  }
-SWIGINTERN void GDALRasterBandShadow_GetNoDataValue(GDALRasterBandShadow *self,double *val,int *hasval){
-    *val = GDALGetRasterNoDataValue( self, hasval );
-  }
-SWIGINTERN CPLErr GDALRasterBandShadow_SetNoDataValue(GDALRasterBandShadow *self,double d){
-    return GDALSetRasterNoDataValue( self, d );
-  }
-SWIGINTERN char const *GDALRasterBandShadow_GetUnitType(GDALRasterBandShadow *self){
-      return GDALGetRasterUnitType( self );
-  }
-SWIGINTERN CPLErr GDALRasterBandShadow_SetUnitType(GDALRasterBandShadow *self,char const *val){
-    return GDALSetRasterUnitType( self, val );
-  }
-SWIGINTERN char **GDALRasterBandShadow_GetRasterCategoryNames(GDALRasterBandShadow *self){
-    return GDALGetRasterCategoryNames( self );
-  }
-SWIGINTERN CPLErr GDALRasterBandShadow_SetRasterCategoryNames(GDALRasterBandShadow *self,char **names){
-    return GDALSetRasterCategoryNames( self, names );
-  }
-SWIGINTERN void GDALRasterBandShadow_GetMinimum(GDALRasterBandShadow *self,double *val,int *hasval){
-    *val = GDALGetRasterMinimum( self, hasval );
-  }
-SWIGINTERN void GDALRasterBandShadow_GetMaximum(GDALRasterBandShadow *self,double *val,int *hasval){
-    *val = GDALGetRasterMaximum( self, hasval );
-  }
-SWIGINTERN void GDALRasterBandShadow_GetOffset(GDALRasterBandShadow *self,double *val,int *hasval){
-    *val = GDALGetRasterOffset( self, hasval );
-  }
-SWIGINTERN void GDALRasterBandShadow_GetScale(GDALRasterBandShadow *self,double *val,int *hasval){
-    *val = GDALGetRasterScale( self, hasval );
-  }
-SWIGINTERN CPLErr GDALRasterBandShadow_SetOffset(GDALRasterBandShadow *self,double val){
-    return GDALSetRasterOffset( self, val );
-  }
-SWIGINTERN CPLErr GDALRasterBandShadow_SetScale(GDALRasterBandShadow *self,double val){
-    return GDALSetRasterScale( self, val );
-  }
-SWIGINTERN CPLErr GDALRasterBandShadow_GetStatistics(GDALRasterBandShadow *self,int approx_ok,int force,double *min,double *max,double *mean,double *stddev){
-    if (min) *min = 0;
-    if (max) *max = 0;
-    if (mean) *mean = 0;
-    if (stddev) *stddev = -1; /* This is the only way to recognize from Python if GetRasterStatistics() has updated the values */
-    return GDALGetRasterStatistics( self, approx_ok, force, 
-				    min, max, mean, stddev );
-  }
-
-SWIGINTERN int
-SWIG_AsVal_bool SWIG_PERL_DECL_ARGS_2(SV *obj, bool* val)
-{
-  if (obj == &PL_sv_yes) {
-    if (val) *val = true;
-    return SWIG_OK;
-  } else if (obj == &PL_sv_no) { 
-    if (val) *val = false;
-    return SWIG_OK;
-  } else {
-    if (val) *val = SvTRUE(obj) ? true : false;
-    return SWIG_AddCast(SWIG_OK);    
-  }
-}
-
-SWIGINTERN CPLErr GDALRasterBandShadow_ComputeStatistics(GDALRasterBandShadow *self,bool approx_ok,double *min=NULL,double *max=NULL,double *mean=NULL,double *stddev=NULL,GDALProgressFunc callback=NULL,void *callback_data=NULL){
-    return GDALComputeRasterStatistics( self, approx_ok, min, max, mean, stddev, callback, callback_data );
-  }
-SWIGINTERN CPLErr GDALRasterBandShadow_SetStatistics(GDALRasterBandShadow *self,double min,double max,double mean,double stddev){
-    return GDALSetRasterStatistics( self, min, max, mean, stddev );
-  }
-SWIGINTERN int GDALRasterBandShadow_GetOverviewCount(GDALRasterBandShadow *self){
-    return GDALGetOverviewCount( self );
-  }
-SWIGINTERN GDALRasterBandShadow *GDALRasterBandShadow_GetOverview(GDALRasterBandShadow *self,int i){
-    return (GDALRasterBandShadow*) GDALGetOverview( self, i );
-  }
-SWIGINTERN int GDALRasterBandShadow_Checksum(GDALRasterBandShadow *self,int xoff=0,int yoff=0,int *xsize=0,int *ysize=0){
-    int nxsize = (xsize!=0) ? *xsize : GDALGetRasterBandXSize( self );
-    int nysize = (ysize!=0) ? *ysize : GDALGetRasterBandYSize( self );
-    return GDALChecksumImage( self, xoff, yoff, nxsize, nysize );
-  }
-SWIGINTERN void GDALRasterBandShadow_ComputeRasterMinMax(GDALRasterBandShadow *self,double argout[2],int approx_ok=0){
-    GDALComputeRasterMinMax( self, approx_ok, argout );
-  }
-SWIGINTERN void GDALRasterBandShadow_ComputeBandStats(GDALRasterBandShadow *self,double argout[2],int samplestep=1){
-    GDALComputeBandStats( self, samplestep, argout+0, argout+1, 
-                          NULL, NULL );
-  }
-SWIGINTERN CPLErr GDALRasterBandShadow_Fill(GDALRasterBandShadow *self,double real_fill,double imag_fill=0.0){
-    return GDALFillRaster( self, real_fill, imag_fill );
-  }
-SWIGINTERN CPLErr GDALRasterBandShadow_ReadRaster(GDALRasterBandShadow *self,int xoff,int yoff,int xsize,int ysize,int *buf_len,char **buf,int *buf_xsize=0,int *buf_ysize=0,int *buf_type=0,int *buf_pixel_space=0,int *buf_line_space=0,GDALRIOResampleAlg resample_alg=GRIORA_NearestNeighbour,GDALProgressFunc callback=NULL,void *callback_data=NULL){
-    int nxsize = (buf_xsize==0) ? xsize : *buf_xsize;
-    int nysize = (buf_ysize==0) ? ysize : *buf_ysize;
-    GDALDataType ntype  = (buf_type==0) ? GDALGetRasterDataType(self)
-                                        : (GDALDataType)*buf_type;
-    GIntBig pixel_space = (buf_pixel_space == 0) ? 0 : *buf_pixel_space;
-    GIntBig line_space = (buf_line_space == 0) ? 0 : *buf_line_space;
-
-    GDALRasterIOExtraArg sExtraArg;
-    INIT_RASTERIO_EXTRA_ARG(sExtraArg);
-    sExtraArg.eResampleAlg = resample_alg;
-    sExtraArg.pfnProgress = callback;
-    sExtraArg.pProgressData = callback_data;
-
-    return ReadRaster_internal( self, xoff, yoff, xsize, ysize,
-                                nxsize, nysize, ntype, buf_len, buf, pixel_space, line_space,
-                                &sExtraArg );
-  }
-SWIGINTERN CPLErr GDALRasterBandShadow_WriteRaster(GDALRasterBandShadow *self,int xoff,int yoff,int xsize,int ysize,int buf_len,char *buf_string,int *buf_xsize=0,int *buf_ysize=0,int *buf_type=0,int *buf_pixel_space=0,int *buf_line_space=0){
-    int nxsize = (buf_xsize==0) ? xsize : *buf_xsize;
-    int nysize = (buf_ysize==0) ? ysize : *buf_ysize;
-    GDALDataType ntype  = (buf_type==0) ? GDALGetRasterDataType(self)
-                                        : (GDALDataType)*buf_type;
-    int pixel_space = (buf_pixel_space == 0) ? 0 : *buf_pixel_space;
-    int line_space = (buf_line_space == 0) ? 0 : *buf_line_space;
-    return WriteRaster_internal( self, xoff, yoff, xsize, ysize,
-                                 nxsize, nysize, ntype, buf_len, buf_string, pixel_space, line_space );
-  }
-SWIGINTERN void GDALRasterBandShadow_FlushCache(GDALRasterBandShadow *self){
-    GDALFlushRasterCache( self );
-  }
-SWIGINTERN GDALColorTableShadow *GDALRasterBandShadow_GetRasterColorTable(GDALRasterBandShadow *self){
-    return (GDALColorTableShadow*) GDALGetRasterColorTable( self );
-  }
-SWIGINTERN GDALColorTableShadow *GDALRasterBandShadow_GetColorTable(GDALRasterBandShadow *self){
-    return (GDALColorTableShadow*) GDALGetRasterColorTable( self );
-  }
-SWIGINTERN int GDALRasterBandShadow_SetRasterColorTable(GDALRasterBandShadow *self,GDALColorTableShadow *arg){
-    return GDALSetRasterColorTable( self, arg );
-  }
-SWIGINTERN int GDALRasterBandShadow_SetColorTable(GDALRasterBandShadow *self,GDALColorTableShadow *arg){
-    return GDALSetRasterColorTable( self, arg );
-  }
-SWIGINTERN GDALRasterAttributeTableShadow *GDALRasterBandShadow_GetDefaultRAT(GDALRasterBandShadow *self){ 
-      return (GDALRasterAttributeTableShadow*) GDALGetDefaultRAT(self);
-  }
-SWIGINTERN int GDALRasterBandShadow_SetDefaultRAT(GDALRasterBandShadow *self,GDALRasterAttributeTableShadow *table){
-      return GDALSetDefaultRAT(self, table);
-  }
-SWIGINTERN GDALRasterBandShadow *GDALRasterBandShadow_GetMaskBand(GDALRasterBandShadow *self){
-      return (GDALRasterBandShadow *) GDALGetMaskBand( self );
-  }
-SWIGINTERN int GDALRasterBandShadow_GetMaskFlags(GDALRasterBandShadow *self){
-      return GDALGetMaskFlags( self );
-  }
-SWIGINTERN CPLErr GDALRasterBandShadow_CreateMaskBand(GDALRasterBandShadow *self,int nFlags){
-      return GDALCreateMaskBand( self, nFlags );
-  }
-
-#define LENGTH_OF_GUIntBig_AS_STRING 30
-static SV *
-CreateArrayFromGUIntBigArray( GUIntBig *first, unsigned int size ) {
-  AV *av = (AV*)sv_2mortal((SV*)newAV());
-  for( unsigned int i=0; i<size; i++ ) {
-    char s[LENGTH_OF_GUIntBig_AS_STRING];
-    snprintf(s, LENGTH_OF_GUIntBig_AS_STRING-1, CPL_FRMT_GUIB, *first);
-    av_store(av,i,newSVpv(s, 0));
-    ++first;
-  }
-  return sv_2mortal(newRV((SV*)av));
-}
-
-SWIGINTERN CPLErr GDALRasterBandShadow_GetHistogram(GDALRasterBandShadow *self,double min=-0.5,double max=255.5,int buckets=256,GUIntBig *panHistogram=NULL,int include_out_of_range=0,int approx_ok=1,GDALProgressFunc callback=NULL,void *callback_data=NULL){
-    CPLErrorReset(); 
-    CPLErr err = GDALGetRasterHistogramEx( self, min, max, buckets, panHistogram,
-                                         include_out_of_range, approx_ok,
-                                         callback, callback_data );
-    return err;
-  }
-SWIGINTERN CPLErr GDALRasterBandShadow_GetDefaultHistogram(GDALRasterBandShadow *self,double *min_ret=NULL,double *max_ret=NULL,int *buckets_ret=NULL,GUIntBig **ppanHistogram=NULL,int force=1,GDALProgressFunc callback=NULL,void *callback_data=NULL){
-    return GDALGetDefaultHistogramEx( self, min_ret, max_ret, buckets_ret,
-                                    ppanHistogram, force, 
-                                    callback, callback_data );
-}
-SWIGINTERN CPLErr GDALRasterBandShadow_SetDefaultHistogram(GDALRasterBandShadow *self,double min,double max,int buckets_in,GUIntBig *panHistogram_in){
-    return GDALSetDefaultHistogramEx( self, min, max, 
-                                    buckets_in, panHistogram_in );
-}
-SWIGINTERN bool GDALRasterBandShadow_HasArbitraryOverviews(GDALRasterBandShadow *self){
-      return (GDALHasArbitraryOverviews( self ) != 0) ? true : false;
-  }
-
-SWIGINTERNINLINE SV *
-SWIG_From_bool  SWIG_PERL_DECL_ARGS_1(bool value)
-{
-  return boolSV(value);
-}
-
-SWIGINTERN char **GDALRasterBandShadow_GetCategoryNames(GDALRasterBandShadow *self){
-    return GDALGetRasterCategoryNames( self );
-  }
-SWIGINTERN CPLErr GDALRasterBandShadow_SetCategoryNames(GDALRasterBandShadow *self,char **papszCategoryNames){
-    return GDALSetRasterCategoryNames( self, papszCategoryNames );
-  }
-SWIGINTERN CPLErr GDALRasterBandShadow_ContourGenerate(GDALRasterBandShadow *self,double dfContourInterval,double dfContourBase,int nFixedLevelCount,double *padfFixedLevels,int bUseNoData,double dfNoDataValue,OGRLayerShadow *hLayer,int iIDField,int iElevField,GDALProgressFunc progress=NULL,void *progress_data=NULL){
-        return GDALContourGenerate( self, dfContourInterval, dfContourBase,
-                                    nFixedLevelCount, padfFixedLevels,
-                                    bUseNoData, dfNoDataValue,
-                                    hLayer, iIDField, iElevField,
-                                    progress,
-                                    progress_data );
-    }
-
-GDALDataType GDALRasterBandShadow_DataType_get( GDALRasterBandShadow *h ) {
-  return GDALGetRasterDataType( h );
-}
-int GDALRasterBandShadow_XSize_get( GDALRasterBandShadow *h ) {
-  return GDALGetRasterBandXSize( h );
-}
-int GDALRasterBandShadow_YSize_get( GDALRasterBandShadow *h ) {
-  return GDALGetRasterBandYSize( h );
-}
-
-SWIGINTERN GDALColorTableShadow *new_GDALColorTableShadow(GDALPaletteInterp palette=GPI_RGB){
-        return (GDALColorTableShadow*) GDALCreateColorTable(palette);
-    }
-SWIGINTERN void delete_GDALColorTableShadow(GDALColorTableShadow *self){
-        GDALDestroyColorTable(self);
-    }
-SWIGINTERN GDALColorTableShadow *GDALColorTableShadow_Clone(GDALColorTableShadow *self){
-        return (GDALColorTableShadow*) GDALCloneColorTable (self);
-    }
-SWIGINTERN GDALPaletteInterp GDALColorTableShadow_GetPaletteInterpretation(GDALColorTableShadow *self){
-        return GDALGetPaletteInterpretation(self);
-    }
-SWIGINTERN int GDALColorTableShadow_GetColorEntryCount(GDALColorTableShadow *self){
-        return GDALGetColorEntryCount(self);
-    }
-SWIGINTERN GDALColorEntry *GDALColorTableShadow_GetColorEntry(GDALColorTableShadow *self,int entry){
-        return (GDALColorEntry*) GDALGetColorEntry(self, entry);
-    }
-SWIGINTERN int GDALColorTableShadow_GetColorEntryAsRGB(GDALColorTableShadow *self,int entry,GDALColorEntry *centry){
-        return GDALGetColorEntryAsRGB(self, entry, centry);
-    }
-SWIGINTERN void GDALColorTableShadow_SetColorEntry(GDALColorTableShadow *self,int entry,GDALColorEntry const *centry){
-        GDALSetColorEntry(self, entry, centry);
-    }
-SWIGINTERN void GDALColorTableShadow_CreateColorRamp(GDALColorTableShadow *self,int nStartIndex,GDALColorEntry const *startcolor,int nEndIndex,GDALColorEntry const *endcolor){
-        GDALCreateColorRamp(self, nStartIndex, startcolor, nEndIndex, endcolor);
-    }
-SWIGINTERN GDALRasterAttributeTableShadow *new_GDALRasterAttributeTableShadow(){
-        return (GDALRasterAttributeTableShadow*) 
-		GDALCreateRasterAttributeTable();
-    }
-SWIGINTERN void delete_GDALRasterAttributeTableShadow(GDALRasterAttributeTableShadow *self){
-        GDALDestroyRasterAttributeTable(self);
-    }
-SWIGINTERN GDALRasterAttributeTableShadow *GDALRasterAttributeTableShadow_Clone(GDALRasterAttributeTableShadow *self){
-        return (GDALRasterAttributeTableShadow*) GDALRATClone(self);
-    }
-SWIGINTERN int GDALRasterAttributeTableShadow_GetColumnCount(GDALRasterAttributeTableShadow *self){ 
-        return GDALRATGetColumnCount( self );
-    }
-SWIGINTERN char const *GDALRasterAttributeTableShadow_GetNameOfCol(GDALRasterAttributeTableShadow *self,int iCol){ 
-        return GDALRATGetNameOfCol( self, iCol );
-    }
-SWIGINTERN GDALRATFieldUsage GDALRasterAttributeTableShadow_GetUsageOfCol(GDALRasterAttributeTableShadow *self,int iCol){
-        return GDALRATGetUsageOfCol( self, iCol );
-    }
-SWIGINTERN GDALRATFieldType GDALRasterAttributeTableShadow_GetTypeOfCol(GDALRasterAttributeTableShadow *self,int iCol){
-        return GDALRATGetTypeOfCol( self, iCol );
-    }
-SWIGINTERN int GDALRasterAttributeTableShadow_GetColOfUsage(GDALRasterAttributeTableShadow *self,GDALRATFieldUsage eUsage){
-        return GDALRATGetColOfUsage( self, eUsage );
-    }
-SWIGINTERN int GDALRasterAttributeTableShadow_GetRowCount(GDALRasterAttributeTableShadow *self){ 
-        return GDALRATGetRowCount( self );
-    }
-SWIGINTERN char const *GDALRasterAttributeTableShadow_GetValueAsString(GDALRasterAttributeTableShadow *self,int iRow,int iCol){ 
-        return GDALRATGetValueAsString( self, iRow, iCol );
-    }
-SWIGINTERN int GDALRasterAttributeTableShadow_GetValueAsInt(GDALRasterAttributeTableShadow *self,int iRow,int iCol){ 
-        return GDALRATGetValueAsInt( self, iRow, iCol );
-    }
-SWIGINTERN double GDALRasterAttributeTableShadow_GetValueAsDouble(GDALRasterAttributeTableShadow *self,int iRow,int iCol){ 
-        return GDALRATGetValueAsDouble( self, iRow, iCol );
-    }
-SWIGINTERN void GDALRasterAttributeTableShadow_SetValueAsString(GDALRasterAttributeTableShadow *self,int iRow,int iCol,char const *pszValue){ 
-        GDALRATSetValueAsString( self, iRow, iCol, pszValue );
-    }
-SWIGINTERN void GDALRasterAttributeTableShadow_SetValueAsInt(GDALRasterAttributeTableShadow *self,int iRow,int iCol,int nValue){ 
-        GDALRATSetValueAsInt( self, iRow, iCol, nValue );
-    }
-SWIGINTERN void GDALRasterAttributeTableShadow_SetValueAsDouble(GDALRasterAttributeTableShadow *self,int iRow,int iCol,double dfValue){ 
-        GDALRATSetValueAsDouble( self, iRow, iCol, dfValue );
-    }
-SWIGINTERN void GDALRasterAttributeTableShadow_SetRowCount(GDALRasterAttributeTableShadow *self,int nCount){
-        GDALRATSetRowCount( self, nCount );
-    }
-SWIGINTERN int GDALRasterAttributeTableShadow_CreateColumn(GDALRasterAttributeTableShadow *self,char const *pszName,GDALRATFieldType eType,GDALRATFieldUsage eUsage){
-        return GDALRATCreateColumn( self, pszName, eType, eUsage );
-    }
-SWIGINTERN bool GDALRasterAttributeTableShadow_GetLinearBinning(GDALRasterAttributeTableShadow *self,double *pdfRow0Min,double *pdfBinSize){
-        return (GDALRATGetLinearBinning(self, pdfRow0Min, pdfBinSize) != 0) ? true : false;
-    }
-SWIGINTERN int GDALRasterAttributeTableShadow_SetLinearBinning(GDALRasterAttributeTableShadow *self,double dfRow0Min,double dfBinSize){
-        return GDALRATSetLinearBinning(self, dfRow0Min, dfBinSize);
-    }
-SWIGINTERN int GDALRasterAttributeTableShadow_GetRowOfValue(GDALRasterAttributeTableShadow *self,double dfValue){
-        return GDALRATGetRowOfValue( self, dfValue );
-    }
-SWIGINTERN int GDALRasterAttributeTableShadow_ChangesAreWrittenToFile(GDALRasterAttributeTableShadow *self){
-        return GDALRATChangesAreWrittenToFile( self );
-    }
-SWIGINTERN void GDALRasterAttributeTableShadow_DumpReadable(GDALRasterAttributeTableShadow *self){
-        GDALRATDumpReadable( self, NULL );
-    }
-
-#include "gdalgrid.h"
-
-#ifdef DEBUG 
-typedef struct OGRLayerHS OGRLayerShadow;
-typedef struct OGRGeometryHS OGRGeometryShadow;
-#else
-typedef void OGRLayerShadow;
-typedef void OGRGeometryShadow;
-#endif
-
-
-int GDALTermProgress_nocb( double dfProgress, const char * pszMessage=NULL, void *pData=NULL ) {
-  return GDALTermProgress( dfProgress, pszMessage, pData);
-}
-
-
-int  ComputeMedianCutPCT ( GDALRasterBandShadow *red,
-                              GDALRasterBandShadow *green,
-                              GDALRasterBandShadow *blue,
-                              int num_colors,
-                              GDALColorTableShadow* colors,
-                              GDALProgressFunc callback = NULL,
-                              void* callback_data=NULL) {
-
-    CPLErrorReset();
-
-    int err = GDALComputeMedianCutPCT( red,
-                                          green,
-                                          blue,
-                                          NULL,
-                                          num_colors,
-                                          colors,
-                                          callback,
-                                          callback_data);
-    
-    return err;
-}
-
-
-int  DitherRGB2PCT ( GDALRasterBandShadow *red,
-                     GDALRasterBandShadow *green,
-                     GDALRasterBandShadow *blue,
-                     GDALRasterBandShadow *target,
-                     GDALColorTableShadow *colors,
-                     GDALProgressFunc callback = NULL,
-                     void* callback_data=NULL) {
-
-    CPLErrorReset();
-    int err;
-    err = GDALDitherRGB2PCT(  red,
-                                  green,
-                                  blue,
-                                  target,
-                                  colors,
-                                  callback,
-                                  callback_data);
-    
-    return err;
-}
-
-
-CPLErr  ReprojectImage ( GDALDatasetShadow *src_ds,
-                         GDALDatasetShadow *dst_ds,
-                         const char *src_wkt=NULL,
-                         const char *dst_wkt=NULL,
-                         GDALResampleAlg eResampleAlg=GRA_NearestNeighbour,
-                         double WarpMemoryLimit=0.0,
-                         double maxerror = 0.0,
-			 GDALProgressFunc callback = NULL,
-                     	 void* callback_data=NULL) {
-
-    CPLErrorReset();
-
-    CPLErr err = GDALReprojectImage( src_ds,
-                                     src_wkt,
-                                     dst_ds,
-                                     dst_wkt,
-                                     eResampleAlg,
-                                     WarpMemoryLimit,
-                                     maxerror,
-                                     callback,
-                                     callback_data,
-                                     NULL);
-    
-    return err;
-}
-
-
-int  ComputeProximity( GDALRasterBandShadow *srcBand,
-                       GDALRasterBandShadow *proximityBand,
-                       char **options = NULL,
-                       GDALProgressFunc callback=NULL,
-                       void* callback_data=NULL) {
-
-    CPLErrorReset();
-
-    return GDALComputeProximity( srcBand, proximityBand, options,
-                                 callback, callback_data );
-}
-
-
-int  RasterizeLayer( GDALDatasetShadow *dataset,
-                 int bands, int *band_list,
-                 OGRLayerShadow *layer,
-                 void *pfnTransformer = NULL,
-                 void *pTransformArg = NULL, 
-		 int burn_values = 0, double *burn_values_list = NULL, 
-                 char **options = NULL,
-                 GDALProgressFunc callback=NULL,
-                 void* callback_data=NULL) {
-
-    CPLErr eErr;
-
-    CPLErrorReset();
-
-    if( burn_values == 0 )
-    {
-        burn_values_list = (double *) CPLMalloc(sizeof(double)*bands);
-        for( int i = 0; i < bands; i++ )
-            burn_values_list[i] = 255.0;
-    }
-    else if( burn_values != bands )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Did not get the expected number of burn values in RasterizeLayer()" );
-        return CE_Failure;
-    }
-
-    eErr = GDALRasterizeLayers( dataset, bands, band_list,
-                                1, &layer, 
-                                (GDALTransformerFunc) pfnTransformer, 
-                                pTransformArg,
-                                burn_values_list, options, 
-                                callback, callback_data );
-
-    if( burn_values == 0 )
-        CPLFree( burn_values_list );
-
-    return eErr;
-}
-
-
-int  Polygonize( GDALRasterBandShadow *srcBand,
-     		 GDALRasterBandShadow *maskBand,
-  	         OGRLayerShadow *outLayer, 
-                 int iPixValField,
-                 char **options = NULL,
-                 GDALProgressFunc callback=NULL,
-                 void* callback_data=NULL) {
-
-    CPLErrorReset();
-
-    return GDALPolygonize( srcBand, maskBand, outLayer, iPixValField,
-                           options, callback, callback_data );
-}
-
-
-int  FillNodata( GDALRasterBandShadow *targetBand,
-     		 GDALRasterBandShadow *maskBand,
-                 double maxSearchDist,
-                 int smoothingIterations,
-                 char **options = NULL,
-                 GDALProgressFunc callback=NULL,
-                 void* callback_data=NULL) {
-
-    CPLErrorReset();
-
-    return GDALFillNodata( targetBand, maskBand, maxSearchDist, 
-    	   		   0, smoothingIterations, options, 
-			   callback, callback_data );
-}
-
-
-int  SieveFilter( GDALRasterBandShadow *srcBand,
-     		  GDALRasterBandShadow *maskBand,
-  	          GDALRasterBandShadow *dstBand,
-                  int threshold, int connectedness=4,
-                  char **options = NULL,
-                  GDALProgressFunc callback=NULL,
-                  void* callback_data=NULL) {
-
-    CPLErrorReset();
-
-    return GDALSieveFilter( srcBand, maskBand, dstBand, 
-                            threshold, connectedness,
-                            options, callback, callback_data );
-}
-
-
-int  RegenerateOverviews( GDALRasterBandShadow *srcBand,
-     			  int overviewBandCount,
-                          GDALRasterBandShadow **overviewBands,
-                          const char *resampling = "average",
-                          GDALProgressFunc callback=NULL,
-                          void* callback_data=NULL) {
-
-    CPLErrorReset();
-
-    return GDALRegenerateOverviews( srcBand, overviewBandCount, overviewBands,
-    	   			    resampling ? resampling : "average", callback, callback_data );
-}
-
-
-int  RegenerateOverview( GDALRasterBandShadow *srcBand,
-                          GDALRasterBandShadow *overviewBand,
-                          const char *resampling = "average",
-                          GDALProgressFunc callback=NULL,
-                          void* callback_data=NULL) {
-
-    CPLErrorReset();
-
-    return GDALRegenerateOverviews( srcBand, 1, &overviewBand,
-    	   			    resampling ? resampling : "average", callback, callback_data );
-}
-
-
-int ContourGenerate( GDALRasterBandShadow *srcBand,
-                     double contourInterval,
-                     double contourBase,
-                     int fixedLevelCount,
-                     double *fixedLevels,
-                     int useNoData,
-                     double noDataValue,
-                     OGRLayerShadow* dstLayer, 
-                     int idField,
-                     int elevField,
-                     GDALProgressFunc callback = NULL,
-                     void* callback_data = NULL)
-{
-    CPLErr eErr;
-
-    CPLErrorReset();
-
-    eErr =  GDALContourGenerate( srcBand,
-                                 contourInterval,
-                                 contourBase,
-                                 fixedLevelCount,
-                                 fixedLevels,
-                                 useNoData,
-                                 noDataValue,
-                                 dstLayer,
-                                 idField,
-                                 elevField,
-                                 callback,
-                                 callback_data);
-
-    return eErr;
-}
-
-
-GDALDatasetShadow *AutoCreateWarpedVRT( GDALDatasetShadow *src_ds,
-                                        const char *src_wkt = 0,
-                                        const char *dst_wkt = 0,
-                                        GDALResampleAlg eResampleAlg = GRA_NearestNeighbour,
-                                        double maxerror = 0.0 ) {
-  GDALDatasetShadow *ds = GDALAutoCreateWarpedVRT( src_ds, src_wkt,
-                                                   dst_wkt,
-                                                   eResampleAlg,
-                                                   maxerror,
-                                                   0 );
-  if (ds == 0) {
-    /*throw CPLGetLastErrorMsg(); causes a SWIG_exception later*/
-  }
-  return ds;
-  
-}
-
-SWIGINTERN GDALTransformerInfoShadow *new_GDALTransformerInfoShadow(GDALDatasetShadow *src,GDALDatasetShadow *dst,char **options){
-    GDALTransformerInfoShadow *obj = (GDALTransformerInfoShadow*) 
-       GDALCreateGenImgProjTransformer2( (GDALDatasetH)src, (GDALDatasetH)dst, 
-                                         options );
-    return obj;
-  }
-SWIGINTERN void delete_GDALTransformerInfoShadow(GDALTransformerInfoShadow *self){
-    GDALDestroyTransformer( self );
-  }
-SWIGINTERN int GDALTransformerInfoShadow_TransformPoint__SWIG_0(GDALTransformerInfoShadow *self,int bDstToSrc,double inout[3]){
-    int nRet, nSuccess = TRUE;
-
-    nRet = GDALUseTransformer( self, bDstToSrc, 
-                               1, &inout[0], &inout[1], &inout[2], 
-                               &nSuccess );
-
-    return nRet && nSuccess;
-  }
-SWIGINTERN int GDALTransformerInfoShadow_TransformPoint__SWIG_1(GDALTransformerInfoShadow *self,double argout[3],int bDstToSrc,double x,double y,double z=0.0){
-    int nRet, nSuccess = TRUE;
-    
-    argout[0] = x;
-    argout[1] = y;
-    argout[2] = z;
-    nRet = GDALUseTransformer( self, bDstToSrc, 
-                               1, &argout[0], &argout[1], &argout[2], 
-                               &nSuccess );
-
-    return nRet && nSuccess;
-  }
-SWIGINTERN int GDALTransformerInfoShadow_TransformPoints(GDALTransformerInfoShadow *self,int bDstToSrc,int nCount,double *x,double *y,double *z,int *panSuccess){
-    int nRet;
-
-    nRet = GDALUseTransformer( self, bDstToSrc, nCount, x, y, z, panSuccess );
-
-    return nRet;
-  }
-SWIGINTERN int GDALTransformerInfoShadow_TransformGeolocations(GDALTransformerInfoShadow *self,GDALRasterBandShadow *xBand,GDALRasterBandShadow *yBand,GDALRasterBandShadow *zBand,GDALProgressFunc callback=NULL,void *callback_data=NULL,char **options=NULL){
-
-    CPLErrorReset();
-
-    return GDALTransformGeolocations( xBand, yBand, zBand, 
-                                      GDALUseTransformer, self,
-                            	      callback, callback_data, options );
-  }
-
-int wrapper_GDALGetCacheMax()
-{
-    return GDALGetCacheMax();
-}
-
-
-int wrapper_GDALGetCacheUsed()
-{
-    return GDALGetCacheUsed();
-}
-
-
-void wrapper_GDALSetCacheMax(int nBytes)
-{
-    return GDALSetCacheMax(nBytes);
-}
-
-
-/************************************************************************/
-/*                          XMLTreeToAV()                               */
-/************************************************************************/
-static AV *XMLTreeToAV( CPLXMLNode *psTree )
-{
-    AV *av;
-    int      nChildCount = 0, iChild;
-    CPLXMLNode *psChild;
-
-    for( psChild = psTree->psChild; 
-         psChild != NULL; 
-         psChild = psChild->psNext )
-        nChildCount++;
-
-    av = (AV*)sv_2mortal((SV*)newAV());
-
-    av_store(av,0,newSViv((int) psTree->eType));
-    SV *sv = newSVpv(psTree->pszValue, strlen(psTree->pszValue));
-    SvUTF8_on(sv); /* expecting UTF-8 from GDAL */
-    av_store(av,1,sv);
-    
-    for( psChild = psTree->psChild, iChild = 2; 
-         psChild != NULL; 
-         psChild = psChild->psNext, iChild++ )
-    {
-        SV *s = newRV((SV*)XMLTreeToAV(psChild));
-        if (!av_store(av, iChild, s))
-            SvREFCNT_dec(s);
-    }
-
-    return av;
-}
-
-
-/************************************************************************/
-/*                          AVToXMLTree()                               */
-/************************************************************************/
-  static CPLXMLNode *AVToXMLTree( AV *av, int *err )
-{
-    int      nChildCount = 0, iChild, nType;
-    CPLXMLNode *psThisNode;
-    char       *pszText = NULL;
-    
-    nChildCount = av_len(av) - 1; /* there are two non-childs in the array */
-    if (nChildCount < 0) {
-        /* the input XML is empty */
-        *err = 1;
-        return NULL;
-    }
-
-    nType = SvIV(*(av_fetch(av,0,0)));
-    SV *sv = *(av_fetch(av,1,0));
-    sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-    pszText = SvPV_nolen(sv);
-    psThisNode = CPLCreateXMLNode( NULL, (CPLXMLNodeType) nType, pszText );
-    
-    for( iChild = 0; iChild < nChildCount; iChild++ )
-    {
-        SV **s = av_fetch(av, iChild+2, 0);
-        CPLXMLNode *psChild;
-        if (!(SvROK(*s) && (SvTYPE(SvRV(*s))==SVt_PVAV))) {
-            /* expected a reference to an array */
-            *err = 2;
-            psChild = NULL;
-        } else
-            psChild = AVToXMLTree((AV*)SvRV(*s), err);
-        if (psChild)
-            CPLAddXMLChild( psThisNode, psChild );
-        else {
-            CPLDestroyXMLNode(psThisNode);
-            return NULL;
-        }
-    }
-
-    return psThisNode;
-}
-
-
-retStringAndCPLFree *GetJPEG2000StructureAsString( const char* pszFilename, char** options = NULL )
-{
-    CPLXMLNode* psNode = GDALGetJPEG2000Structure(pszFilename, options);
-    if( psNode == NULL )
-        return NULL;
-    char* pszXML = CPLSerializeXMLTree(psNode);
-    CPLDestroyXMLNode(psNode);
-    return pszXML;
-}
-
-
-int GetDriverCount() {
-  return GDALGetDriverCount();
-}
-
-
-GDALDriverShadow* GetDriverByName( char const *name ) {
-  return (GDALDriverShadow*) GDALGetDriverByName( name );
-}
-
-
-GDALDriverShadow* GetDriver( int i ) {
-  return (GDALDriverShadow*) GDALGetDriver( i );
-}
-
-
-GDALDatasetShadow* Open( char const* utf8_path, GDALAccess eAccess = GA_ReadOnly ) {
-  CPLErrorReset();
-  GDALDatasetShadow *ds = GDALOpen( utf8_path, eAccess );
-  if( ds != NULL && CPLGetLastErrorType() == CE_Failure )
-  {
-      if ( GDALDereferenceDataset( ds ) <= 0 )
-          GDALClose(ds);
-      ds = NULL;
-  }
-  return (GDALDatasetShadow*) ds;
-}
-
-
-GDALDatasetShadow* OpenEx( char const* utf8_path, unsigned int nOpenFlags = 0,
-                           char** allowed_drivers = NULL, char** open_options = NULL,
-                           char** sibling_files = NULL ) {
-  CPLErrorReset();
-  GDALDatasetShadow *ds = GDALOpenEx( utf8_path, nOpenFlags, allowed_drivers,
-                                      open_options, sibling_files );
-  if( ds != NULL && CPLGetLastErrorType() == CE_Failure )
-  {
-      if ( GDALDereferenceDataset( ds ) <= 0 )
-          GDALClose(ds);
-      ds = NULL;
-  }
-  return (GDALDatasetShadow*) ds;
-}
-
-
-SWIGINTERN int
-SWIG_AsVal_unsigned_SS_int SWIG_PERL_DECL_ARGS_2(SV * obj, unsigned int *val)
-{
-  unsigned long v;
-  int res = SWIG_AsVal_unsigned_SS_long SWIG_PERL_CALL_ARGS_2(obj, &v);
-  if (SWIG_IsOK(res)) {
-    if ((v > UINT_MAX)) {
-      return SWIG_OverflowError;
-    } else {
-      if (val) *val = static_cast< unsigned int >(v);
-    }
-  }  
-  return res;
-}
-
-
-GDALDatasetShadow* OpenShared( char const* utf8_path, GDALAccess eAccess = GA_ReadOnly ) {
-  CPLErrorReset();
-  GDALDatasetShadow *ds = GDALOpenShared( utf8_path, eAccess );
-  if( ds != NULL && CPLGetLastErrorType() == CE_Failure )
-  {
-      if ( GDALDereferenceDataset( ds ) <= 0 )
-          GDALClose(ds);
-      ds = NULL;
-  }
-  return (GDALDatasetShadow*) ds;
-}
-
-
-GDALDriverShadow *IdentifyDriver( const char *utf8_path, 
-                                  char **papszSiblings = NULL ) {
-    return (GDALDriverShadow *) GDALIdentifyDriver( utf8_path, 
-	                                            papszSiblings );
-}
-
-
-  char **GeneralCmdLineProcessor( char **papszArgv, int nOptions = 0 ) {
-    int nResArgCount;
-
-    nResArgCount = 
-      GDALGeneralCmdLineProcessor( CSLCount(papszArgv), &papszArgv, nOptions ); 
-
-    if( nResArgCount <= 0 )
-        return NULL;
-    else
-        return papszArgv;
-  }
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef PERL_OBJECT
-#define MAGIC_CLASS _wrap_Geo__GDAL_var::
-class _wrap_Geo__GDAL_var : public CPerlObj {
-public:
-#else
-#define MAGIC_CLASS
-#endif
-SWIGCLASS_STATIC int swig_magic_readonly(pTHX_ SV *SWIGUNUSEDPARM(sv), MAGIC *SWIGUNUSEDPARM(mg)) {
-    MAGIC_PPERL
-    croak("Value is read-only.");
-    return 0;
-}
-
-
-#ifdef PERL_OBJECT
-};
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-XS(_wrap_callback_d_cp_vp) {
-  {
-    double arg1 ;
-    char *arg2 = (char *) 0 ;
-    void *arg3 = (void *) 0 ;
-    double val1 ;
-    int ecode1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int res3 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: callback_d_cp_vp(d,cp,vp);");
-    }
-    ecode1 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "callback_d_cp_vp" "', argument " "1"" of type '" "double""'");
-    } 
-    arg1 = static_cast< double >(val1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "callback_d_cp_vp" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    res3 = SWIG_ConvertPtr(ST(2),SWIG_as_voidptrptr(&arg3), 0, 0);
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "callback_d_cp_vp" "', argument " "3"" of type '" "void *""'"); 
-    }
-    result = (int)callback_d_cp_vp(arg1,(char const *)arg2,arg3);
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_UseExceptions) {
-  {
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 0)) {
-      SWIG_croak("Usage: UseExceptions();");
-    }
-    UseExceptions();
-    ST(argvi) = sv_newmortal();
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_DontUseExceptions) {
-  {
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 0)) {
-      SWIG_croak("Usage: DontUseExceptions();");
-    }
-    DontUseExceptions();
-    ST(argvi) = sv_newmortal();
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Debug) {
-  {
-    char *arg1 = (char *) 0 ;
-    char *arg2 = (char *) 0 ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Debug(msg_class,message);");
-    }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Debug" "', argument " "1"" of type '" "char const *""'");
-    }
-    arg1 = reinterpret_cast< char * >(buf1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Debug" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    {
-      CPLErrorReset();
-      Debug((char const *)arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SetErrorHandler) {
-  {
-    char *arg1 = (char *) NULL ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 1)) {
-      SWIG_croak("Usage: SetErrorHandler(pszCallbackName);");
-    }
-    if (items > 0) {
-      res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-      if (!SWIG_IsOK(res1)) {
-        SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SetErrorHandler" "', argument " "1"" of type '" "char const *""'");
-      }
-      arg1 = reinterpret_cast< char * >(buf1);
-    }
-    {
-      CPLErrorReset();
-      result = (CPLErr)SetErrorHandler((char const *)arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) CPLErr */
-    }
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    XSRETURN(argvi);
-  fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_PushErrorHandler__SWIG_0) {
-  {
-    char *arg1 = (char *) NULL ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 1)) {
-      SWIG_croak("Usage: PushErrorHandler(pszCallbackName);");
-    }
-    if (items > 0) {
-      res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-      if (!SWIG_IsOK(res1)) {
-        SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "PushErrorHandler" "', argument " "1"" of type '" "char const *""'");
-      }
-      arg1 = reinterpret_cast< char * >(buf1);
-    }
-    {
-      CPLErrorReset();
-      result = (CPLErr)PushErrorHandler((char const *)arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) CPLErr */
-    }
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    XSRETURN(argvi);
-  fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Error) {
-  {
-    CPLErr arg1 = (CPLErr) CE_Failure ;
-    int arg2 = (int) 0 ;
-    char *arg3 = (char *) "error" ;
-    int val1 ;
-    int ecode1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int res3 ;
-    char *buf3 = 0 ;
-    int alloc3 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 3)) {
-      SWIG_croak("Usage: Error(msg_class,err_code,msg);");
-    }
-    if (items > 0) {
-      ecode1 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-      if (!SWIG_IsOK(ecode1)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "Error" "', argument " "1"" of type '" "CPLErr""'");
-      } 
-      arg1 = static_cast< CPLErr >(val1);
-    }
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Error" "', argument " "2"" of type '" "int""'");
-      } 
-      arg2 = static_cast< int >(val2);
-    }
-    if (items > 2) {
-      res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
-      if (!SWIG_IsOK(res3)) {
-        SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Error" "', argument " "3"" of type '" "char const *""'");
-      }
-      arg3 = reinterpret_cast< char * >(buf3);
-    }
-    {
-      CPLErrorReset();
-      Error(arg1,arg2,(char const *)arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    XSRETURN(argvi);
-  fail:
-    
-    
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GOA2GetAuthorizationURL) {
-  {
-    char *arg1 = (char *) 0 ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
-    int argvi = 0;
-    retStringAndCPLFree *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GOA2GetAuthorizationURL(pszScope);");
-    }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GOA2GetAuthorizationURL" "', argument " "1"" of type '" "char const *""'");
-    }
-    arg1 = reinterpret_cast< char * >(buf1);
-    {
-      CPLErrorReset();
-      result = (retStringAndCPLFree *)GOA2GetAuthorizationURL((char const *)arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    
-    /* %typemap(out) (retStringAndCPLFree*) */
-    if(result)
-    {
-      ST(argvi) = SWIG_FromCharPtr((const char *)result);
-      CPLFree(result);
-    }
-    else
-    {
-      ST(argvi) = &PL_sv_undef;
-    }
-    argvi++ ;
-    
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    XSRETURN(argvi);
-  fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GOA2GetRefreshToken) {
-  {
-    char *arg1 = (char *) 0 ;
-    char *arg2 = (char *) 0 ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    retStringAndCPLFree *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: GOA2GetRefreshToken(pszAuthToken,pszScope);");
-    }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GOA2GetRefreshToken" "', argument " "1"" of type '" "char const *""'");
-    }
-    arg1 = reinterpret_cast< char * >(buf1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "GOA2GetRefreshToken" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    {
-      CPLErrorReset();
-      result = (retStringAndCPLFree *)GOA2GetRefreshToken((char const *)arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    
-    /* %typemap(out) (retStringAndCPLFree*) */
-    if(result)
-    {
-      ST(argvi) = SWIG_FromCharPtr((const char *)result);
-      CPLFree(result);
-    }
-    else
-    {
-      ST(argvi) = &PL_sv_undef;
-    }
-    argvi++ ;
-    
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GOA2GetAccessToken) {
-  {
-    char *arg1 = (char *) 0 ;
-    char *arg2 = (char *) 0 ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    retStringAndCPLFree *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: GOA2GetAccessToken(pszRefreshToken,pszScope);");
-    }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GOA2GetAccessToken" "', argument " "1"" of type '" "char const *""'");
-    }
-    arg1 = reinterpret_cast< char * >(buf1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "GOA2GetAccessToken" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    {
-      CPLErrorReset();
-      result = (retStringAndCPLFree *)GOA2GetAccessToken((char const *)arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    
-    /* %typemap(out) (retStringAndCPLFree*) */
-    if(result)
-    {
-      ST(argvi) = SWIG_FromCharPtr((const char *)result);
-      CPLFree(result);
-    }
-    else
-    {
-      ST(argvi) = &PL_sv_undef;
-    }
-    argvi++ ;
-    
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_PushErrorHandler__SWIG_1) {
-  {
-    CPLErrorHandler arg1 ;
-    void *argp1 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: PushErrorHandler(CPLErrorHandler);");
-    }
-    {
-      res1 = SWIG_ConvertPtr(ST(0), &argp1, SWIGTYPE_p_CPLErrorHandler,  0 );
-      if (!SWIG_IsOK(res1)) {
-        SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "PushErrorHandler" "', argument " "1"" of type '" "CPLErrorHandler""'"); 
-      }  
-      if (!argp1) {
-        SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "PushErrorHandler" "', argument " "1"" of type '" "CPLErrorHandler""'");
-      } else {
-        arg1 = *(reinterpret_cast< CPLErrorHandler * >(argp1));
-      }
-    }
-    {
-      CPLErrorReset();
-      CPLPushErrorHandler(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_PushErrorHandler) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if ((items >= 0) && (items <= 1)) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      if (items > 0) {
-        {
-          int res = SWIG_AsCharPtrAndSize(ST(0), 0, NULL, 0);
-          _v = SWIG_CheckState(res);
-        }
-        if (!_v) goto check_1;
-        _ranki += _v*_pi;
-        _rankm += _pi;
-        _pi *= SWIG_MAXCASTRANK;
-      }
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 1) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_CPLErrorHandler, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_PushErrorHandler__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_PushErrorHandler__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'PushErrorHandler'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_PopErrorHandler) {
-  {
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 0)) {
-      SWIG_croak("Usage: PopErrorHandler();");
-    }
-    {
-      CPLErrorReset();
-      CPLPopErrorHandler();
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_ErrorReset) {
-  {
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 0)) {
-      SWIG_croak("Usage: ErrorReset();");
-    }
-    {
-      CPLErrorReset();
-      CPLErrorReset();
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_EscapeString) {
-  {
-    int arg1 ;
-    char *arg2 = (char *) 0 ;
-    int arg3 = (int) CPLES_SQL ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    retStringAndCPLFree *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: EscapeString(len,bin_string,scheme);");
-    }
-    {
-      /* %typemap(in,numinputs=1) (int nLen, char *pBuf ) */
-      if (SvOK(ST(0))) {
-        if (!SvPOK(ST(0)))
-        SWIG_croak("Expected binary data.");
-        STRLEN len = SvCUR(ST(0));
-        arg2 = SvPV_nolen(ST(0));
-        arg1 = len;
-      } else {
-        arg2 = NULL;
-        arg1 = 0;
-      }
-    }
-    if (items > 1) {
-      ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val3);
-      if (!SWIG_IsOK(ecode3)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "EscapeString" "', argument " "3"" of type '" "int""'");
-      } 
-      arg3 = static_cast< int >(val3);
-    }
-    {
-      CPLErrorReset();
-      result = (retStringAndCPLFree *)EscapeString(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    
-    /* %typemap(out) (retStringAndCPLFree*) */
-    if(result)
-    {
-      ST(argvi) = SWIG_FromCharPtr((const char *)result);
-      CPLFree(result);
-    }
-    else
-    {
-      ST(argvi) = &PL_sv_undef;
-    }
-    argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GetLastErrorNo) {
-  {
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 0)) {
-      SWIG_croak("Usage: GetLastErrorNo();");
-    }
-    {
-      CPLErrorReset();
-      result = (int)CPLGetLastErrorNo();
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GetLastErrorType) {
-  {
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 0)) {
-      SWIG_croak("Usage: GetLastErrorType();");
-    }
-    {
-      CPLErrorReset();
-      result = (CPLErr)CPLGetLastErrorType();
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) CPLErr */
-    }
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GetLastErrorMsg) {
-  {
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 0)) {
-      SWIG_croak("Usage: GetLastErrorMsg();");
-    }
-    {
-      CPLErrorReset();
-      result = (char *)CPLGetLastErrorMsg();
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_PushFinderLocation) {
-  {
-    char *arg1 = (char *) 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    {
-      /* %typemap(default) const char * utf8_path */
-      arg1 = (char *)"";
-    }
-    if ((items < 0) || (items > 1)) {
-      SWIG_croak("Usage: PushFinderLocation(utf8_path);");
-    }
-    if (items > 0) {
-      {
-        /* %typemap(in,numinputs=1) (const char* utf8_path) */
-        sv_utf8_upgrade(ST(0));
-        arg1 = SvPV_nolen(ST(0));
-      }
-    }
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      CPLPushFinderLocation((char const *)arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_PopFinderLocation) {
-  {
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 0)) {
-      SWIG_croak("Usage: PopFinderLocation();");
-    }
-    {
-      CPLErrorReset();
-      CPLPopFinderLocation();
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FinderClean) {
-  {
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 0)) {
-      SWIG_croak("Usage: FinderClean();");
-    }
-    {
-      CPLErrorReset();
-      CPLFinderClean();
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FindFile) {
-  {
-    char *arg1 = (char *) 0 ;
-    char *arg2 = (char *) 0 ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    {
-      /* %typemap(default) const char * utf8_path */
-      arg2 = (char *)"";
-    }
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: FindFile(pszClass,utf8_path);");
-    }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FindFile" "', argument " "1"" of type '" "char const *""'");
-    }
-    arg1 = reinterpret_cast< char * >(buf1);
-    if (items > 1) {
-      {
-        /* %typemap(in,numinputs=1) (const char* utf8_path) */
-        sv_utf8_upgrade(ST(1));
-        arg2 = SvPV_nolen(ST(1));
-      }
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (char *)CPLFindFile((char const *)arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    XSRETURN(argvi);
-  fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_ReadDir) {
-  {
-    char *arg1 = (char *) 0 ;
-    int argvi = 0;
-    char **result = 0 ;
-    dXSARGS;
-    
-    {
-      /* %typemap(default) const char * utf8_path */
-      arg1 = (char *)"";
-    }
-    if ((items < 0) || (items > 1)) {
-      SWIG_croak("Usage: ReadDir(utf8_path);");
-    }
-    if (items > 0) {
-      {
-        /* %typemap(in,numinputs=1) (const char* utf8_path) */
-        sv_utf8_upgrade(ST(0));
-        arg1 = SvPV_nolen(ST(0));
-      }
-    }
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (char **)VSIReadDir((char const *)arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) char **CSL */
-      if (GIMME_V == G_ARRAY) {
-        if (result) {
-          int i;
-          for (i = 0; result[i]; i++) {
-            if (argvi > items-1) EXTEND(SP, 1);
-            SV *sv = newSVpv(result[i], 0);
-            SvUTF8_on(sv); /* expecting GDAL to give us UTF-8 */
-            ST(argvi++) = sv_2mortal(sv);
-          }
-          CSLDestroy(result);
-        }
-      } else {
-        AV *av = (AV*)sv_2mortal((SV*)newAV());
-        if (result) {
-          int i;
-          for (i = 0; result[i]; i++) {
-            SV *sv = newSVpv(result[i], 0);
-            SvUTF8_on(sv); /* expecting GDAL to give us UTF-8 */
-            if (!av_store(av, i, sv))
-            SvREFCNT_dec(sv);
-          }
-          CSLDestroy(result);
-        }
-        ST(argvi) = newRV((SV*)av);
-        sv_2mortal(ST(argvi));
-        argvi++;
-      }
-    }
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_ReadDirRecursive) {
-  {
-    char *arg1 = (char *) 0 ;
-    int argvi = 0;
-    char **result = 0 ;
-    dXSARGS;
-    
-    {
-      /* %typemap(default) const char * utf8_path */
-      arg1 = (char *)"";
-    }
-    if ((items < 0) || (items > 1)) {
-      SWIG_croak("Usage: ReadDirRecursive(utf8_path);");
-    }
-    if (items > 0) {
-      {
-        /* %typemap(in,numinputs=1) (const char* utf8_path) */
-        sv_utf8_upgrade(ST(0));
-        arg1 = SvPV_nolen(ST(0));
-      }
-    }
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (char **)VSIReadDirRecursive((char const *)arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) char **CSL */
-      if (GIMME_V == G_ARRAY) {
-        if (result) {
-          int i;
-          for (i = 0; result[i]; i++) {
-            if (argvi > items-1) EXTEND(SP, 1);
-            SV *sv = newSVpv(result[i], 0);
-            SvUTF8_on(sv); /* expecting GDAL to give us UTF-8 */
-            ST(argvi++) = sv_2mortal(sv);
-          }
-          CSLDestroy(result);
-        }
-      } else {
-        AV *av = (AV*)sv_2mortal((SV*)newAV());
-        if (result) {
-          int i;
-          for (i = 0; result[i]; i++) {
-            SV *sv = newSVpv(result[i], 0);
-            SvUTF8_on(sv); /* expecting GDAL to give us UTF-8 */
-            if (!av_store(av, i, sv))
-            SvREFCNT_dec(sv);
-          }
-          CSLDestroy(result);
-        }
-        ST(argvi) = newRV((SV*)av);
-        sv_2mortal(ST(argvi));
-        argvi++;
-      }
-    }
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SetConfigOption) {
-  {
-    char *arg1 = (char *) 0 ;
-    char *arg2 = (char *) 0 ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: SetConfigOption(pszKey,pszValue);");
-    }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SetConfigOption" "', argument " "1"" of type '" "char const *""'");
-    }
-    arg1 = reinterpret_cast< char * >(buf1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SetConfigOption" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      CPLSetConfigOption((char const *)arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GetConfigOption) {
-  {
-    char *arg1 = (char *) 0 ;
-    char *arg2 = (char *) NULL ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: GetConfigOption(pszKey,pszDefault);");
-    }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GetConfigOption" "', argument " "1"" of type '" "char const *""'");
-    }
-    arg1 = reinterpret_cast< char * >(buf1);
-    if (items > 1) {
-      res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-      if (!SWIG_IsOK(res2)) {
-        SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "GetConfigOption" "', argument " "2"" of type '" "char const *""'");
-      }
-      arg2 = reinterpret_cast< char * >(buf2);
-    }
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (char *)wrapper_CPLGetConfigOption((char const *)arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_CPLBinaryToHex) {
-  {
-    int arg1 ;
-    GByte *arg2 = (GByte *) 0 ;
-    int argvi = 0;
-    retStringAndCPLFree *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: CPLBinaryToHex(nBytes,pabyData);");
-    }
-    {
-      /* %typemap(in,numinputs=1) (int nLen, unsigned char *pBuf ) */
-      if (SvOK(ST(0))) {
-        if (!SvPOK(ST(0)))
-        SWIG_croak("Expected binary data.");
-        STRLEN len = SvCUR(ST(0));
-        arg2 = (unsigned char *)SvPV_nolen(ST(0));
-        arg1 = len;
-      } else {
-        arg2 = NULL;
-        arg1 = 0;
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (retStringAndCPLFree *)CPLBinaryToHex(arg1,(GByte const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    
-    /* %typemap(out) (retStringAndCPLFree*) */
-    if(result)
-    {
-      ST(argvi) = SWIG_FromCharPtr((const char *)result);
-      CPLFree(result);
-    }
-    else
-    {
-      ST(argvi) = &PL_sv_undef;
-    }
-    argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_CPLHexToBinary) {
-  {
-    char *arg1 = (char *) 0 ;
-    int *arg2 = (int *) 0 ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
-    int bytes2 ;
-    int argvi = 0;
-    GByte *result = 0 ;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (int *pnBytes) (int bytes2) */
-      arg2 = &bytes2;
-    }
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: CPLHexToBinary(pszHex);");
-    }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CPLHexToBinary" "', argument " "1"" of type '" "char const *""'");
-    }
-    arg1 = reinterpret_cast< char * >(buf1);
-    {
-      CPLErrorReset();
-      result = (GByte *)CPLHexToBinary((char const *)arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) GByte * */
-      ST(argvi) = sv_newmortal();
-      sv_setpvn(ST(argvi), (const char*)result, *arg2);
-      CPLFree(result);
-      argvi++;
-    }
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    
-    XSRETURN(argvi);
-  fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FileFromMemBuffer) {
-  {
-    char *arg1 = (char *) 0 ;
-    int arg2 ;
-    GByte *arg3 = (GByte *) 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    {
-      /* %typemap(default) const char * utf8_path */
-      arg1 = (char *)"";
-    }
-    if ((items < 0) || (items > 3)) {
-      SWIG_croak("Usage: FileFromMemBuffer(utf8_path,nBytes,pabyData);");
-    }
-    if (items > 0) {
-      {
-        /* %typemap(in,numinputs=1) (const char* utf8_path) */
-        sv_utf8_upgrade(ST(0));
-        arg1 = SvPV_nolen(ST(0));
-      }
-    }
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FileFromMemBuffer" "', argument " "2"" of type '" "int""'");
-      } 
-      arg2 = static_cast< int >(val2);
-    }
-    if (items > 2) {
-      res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_GByte, 0 |  0 );
-      if (!SWIG_IsOK(res3)) {
-        SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "FileFromMemBuffer" "', argument " "3"" of type '" "GByte const *""'"); 
-      }
-      arg3 = reinterpret_cast< GByte * >(argp3);
-    }
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      wrapper_VSIFileFromMemBuffer((char const *)arg1,arg2,(GByte const *)arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Unlink) {
-  {
-    char *arg1 = (char *) 0 ;
-    int argvi = 0;
-    VSI_RETVAL result;
-    dXSARGS;
-    
-    {
-      /* %typemap(default) const char * utf8_path */
-      arg1 = (char *)"";
-    }
-    if ((items < 0) || (items > 1)) {
-      SWIG_croak("Usage: Unlink(utf8_path);");
-    }
-    if (items > 0) {
-      {
-        /* %typemap(in,numinputs=1) (const char* utf8_path) */
-        sv_utf8_upgrade(ST(0));
-        arg1 = SvPV_nolen(ST(0));
-      }
-    }
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = VSIUnlink((char const *)arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) VSI_RETVAL */
-    }
-    {
-      /* %typemap(ret) VSI_RETVAL */
-      if (result == -1 ) {
-        croak("%s", strerror(errno));
-      }
-    }
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_HasThreadSupport) {
-  {
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 0)) {
-      SWIG_croak("Usage: HasThreadSupport();");
-    }
-    {
-      CPLErrorReset();
-      result = (int)wrapper_HasThreadSupport();
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Mkdir) {
-  {
-    char *arg1 = (char *) 0 ;
-    int arg2 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    VSI_RETVAL result;
-    dXSARGS;
-    
-    {
-      /* %typemap(default) const char * utf8_path */
-      arg1 = (char *)"";
-    }
-    if ((items < 0) || (items > 2)) {
-      SWIG_croak("Usage: Mkdir(utf8_path,mode);");
-    }
-    if (items > 0) {
-      {
-        /* %typemap(in,numinputs=1) (const char* utf8_path) */
-        sv_utf8_upgrade(ST(0));
-        arg1 = SvPV_nolen(ST(0));
-      }
-    }
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Mkdir" "', argument " "2"" of type '" "int""'");
-      } 
-      arg2 = static_cast< int >(val2);
-    }
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = VSIMkdir((char const *)arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) VSI_RETVAL */
-    }
-    
-    {
-      /* %typemap(ret) VSI_RETVAL */
-      if (result == -1 ) {
-        croak("%s", strerror(errno));
-      }
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Rmdir) {
-  {
-    char *arg1 = (char *) 0 ;
-    int argvi = 0;
-    VSI_RETVAL result;
-    dXSARGS;
-    
-    {
-      /* %typemap(default) const char * utf8_path */
-      arg1 = (char *)"";
-    }
-    if ((items < 0) || (items > 1)) {
-      SWIG_croak("Usage: Rmdir(utf8_path);");
-    }
-    if (items > 0) {
-      {
-        /* %typemap(in,numinputs=1) (const char* utf8_path) */
-        sv_utf8_upgrade(ST(0));
-        arg1 = SvPV_nolen(ST(0));
-      }
-    }
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = VSIRmdir((char const *)arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) VSI_RETVAL */
-    }
-    {
-      /* %typemap(ret) VSI_RETVAL */
-      if (result == -1 ) {
-        croak("%s", strerror(errno));
-      }
-    }
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Rename) {
-  {
-    char *arg1 = (char *) 0 ;
-    char *arg2 = (char *) 0 ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    VSI_RETVAL result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Rename(pszOld,pszNew);");
-    }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Rename" "', argument " "1"" of type '" "char const *""'");
-    }
-    arg1 = reinterpret_cast< char * >(buf1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Rename" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    {
-      CPLErrorReset();
-      result = VSIRename((char const *)arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) VSI_RETVAL */
-    }
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    {
-      /* %typemap(ret) VSI_RETVAL */
-      if (result == -1 ) {
-        croak("%s", strerror(errno));
-      }
-    }
-    XSRETURN(argvi);
-  fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Stat) {
-  {
-    char *arg1 = (char *) 0 ;
-    VSIStatBufL *arg2 = (VSIStatBufL *) 0 ;
-    VSIStatBufL sStatBuf2 ;
-    int argvi = 0;
-    VSI_RETVAL result;
-    dXSARGS;
-    
-    {
-      /* %typemap(default) const char * utf8_path */
-      arg1 = (char *)"";
-    }
-    {
-      /* %typemap(in,numinputs=0) (VSIStatBufL *) (VSIStatBufL sStatBuf2) */
-      arg2 = &sStatBuf2;
-    }
-    if ((items < 0) || (items > 1)) {
-      SWIG_croak("Usage: Stat(utf8_path);");
-    }
-    if (items > 0) {
-      {
-        /* %typemap(in,numinputs=1) (const char* utf8_path) */
-        sv_utf8_upgrade(ST(0));
-        arg1 = SvPV_nolen(ST(0));
-      }
-    }
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = VSIStatL((char const *)arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) VSI_RETVAL */
-    }
-    {
-      /* %typemap(argout) (VSIStatBufL *) */
-      SP -= 1; /* should be somewhere else, remove the filename arg */
-      EXTEND(SP, 1);
-      char mode[2];
-      mode[0] = ' ';
-      mode[1] = '\0';
-      if (S_ISREG(sStatBuf2.st_mode)) mode[0] = 'f';
-      else if (S_ISDIR(sStatBuf2.st_mode)) mode[0] = 'd';
-      else if (S_ISLNK(sStatBuf2.st_mode)) mode[0] = 'l';
-      else if (S_ISFIFO(sStatBuf2.st_mode)) mode[0] = 'p';
-      else if (S_ISSOCK(sStatBuf2.st_mode)) mode[0] = 'S';
-      else if (S_ISBLK(sStatBuf2.st_mode)) mode[0] = 'b';
-      else if (S_ISCHR(sStatBuf2.st_mode)) mode[0] = 'c';
-      PUSHs(sv_2mortal(newSVpv(mode, 0)));
-      argvi++;
-      EXTEND(SP, 1);
-      PUSHs(sv_2mortal(newSVuv(sStatBuf2.st_size)));
-      argvi++;
-    }
-    
-    {
-      /* %typemap(ret) VSI_RETVAL */
-      if (result == -1 ) {
-        croak("%s", strerror(errno));
-      }
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_VSIFOpenL) {
-  {
-    char *arg1 = (char *) 0 ;
-    char *arg2 = (char *) 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    VSILFILE *result = 0 ;
-    dXSARGS;
-    
-    {
-      /* %typemap(default) const char * utf8_path */
-      arg1 = (char *)"";
-    }
-    if ((items < 0) || (items > 2)) {
-      SWIG_croak("Usage: VSIFOpenL(utf8_path,pszMode);");
-    }
-    if (items > 0) {
-      {
-        /* %typemap(in,numinputs=1) (const char* utf8_path) */
-        sv_utf8_upgrade(ST(0));
-        arg1 = SvPV_nolen(ST(0));
-      }
-    }
-    if (items > 1) {
-      res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-      if (!SWIG_IsOK(res2)) {
-        SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "VSIFOpenL" "', argument " "2"" of type '" "char const *""'");
-      }
-      arg2 = reinterpret_cast< char * >(buf2);
-    }
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (VSILFILE *)wrapper_VSIFOpenL((char const *)arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_void, 0 | 0); argvi++ ;
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_VSIFCloseL) {
-  {
-    VSILFILE *arg1 = (VSILFILE *) 0 ;
-    int res1 ;
-    int argvi = 0;
-    VSI_RETVAL result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: VSIFCloseL(VSILFILE *);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0),SWIG_as_voidptrptr(&arg1), 0, 0);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "VSIFCloseL" "', argument " "1"" of type '" "VSILFILE *""'"); 
-    }
-    {
-      CPLErrorReset();
-      result = VSIFCloseL(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) VSI_RETVAL */
-    }
-    
-    {
-      /* %typemap(ret) VSI_RETVAL */
-      if (result == -1 ) {
-        croak("%s", strerror(errno));
-      }
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_VSIFSeekL) {
-  {
-    VSILFILE *arg1 = (VSILFILE *) 0 ;
-    long arg2 ;
-    int arg3 ;
-    int res1 ;
-    long val2 ;
-    int ecode2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    VSI_RETVAL result;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: VSIFSeekL(VSILFILE *,long,int);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0),SWIG_as_voidptrptr(&arg1), 0, 0);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "VSIFSeekL" "', argument " "1"" of type '" "VSILFILE *""'"); 
-    }
-    ecode2 = SWIG_AsVal_long SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "VSIFSeekL" "', argument " "2"" of type '" "long""'");
-    } 
-    arg2 = static_cast< long >(val2);
-    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "VSIFSeekL" "', argument " "3"" of type '" "int""'");
-    } 
-    arg3 = static_cast< int >(val3);
-    {
-      CPLErrorReset();
-      result = VSIFSeekL(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) VSI_RETVAL */
-    }
-    
-    
-    
-    {
-      /* %typemap(ret) VSI_RETVAL */
-      if (result == -1 ) {
-        croak("%s", strerror(errno));
-      }
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_VSIFTellL) {
-  {
-    VSILFILE *arg1 = (VSILFILE *) 0 ;
-    int res1 ;
-    int argvi = 0;
-    long result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: VSIFTellL(VSILFILE *);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0),SWIG_as_voidptrptr(&arg1), 0, 0);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "VSIFTellL" "', argument " "1"" of type '" "VSILFILE *""'"); 
-    }
-    {
-      CPLErrorReset();
-      result = (long)VSIFTellL(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_long  SWIG_PERL_CALL_ARGS_1(static_cast< long >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_VSIFTruncateL) {
-  {
-    VSILFILE *arg1 = (VSILFILE *) 0 ;
-    long arg2 ;
-    int res1 ;
-    long val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    VSI_RETVAL result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: VSIFTruncateL(VSILFILE *,long);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0),SWIG_as_voidptrptr(&arg1), 0, 0);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "VSIFTruncateL" "', argument " "1"" of type '" "VSILFILE *""'"); 
-    }
-    ecode2 = SWIG_AsVal_long SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "VSIFTruncateL" "', argument " "2"" of type '" "long""'");
-    } 
-    arg2 = static_cast< long >(val2);
-    {
-      CPLErrorReset();
-      result = VSIFTruncateL(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) VSI_RETVAL */
-    }
-    
-    
-    {
-      /* %typemap(ret) VSI_RETVAL */
-      if (result == -1 ) {
-        croak("%s", strerror(errno));
-      }
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_VSIFWriteL) {
-  {
-    void *arg1 = (void *) 0 ;
-    size_t arg2 ;
-    size_t arg3 ;
-    VSILFILE *arg4 = (VSILFILE *) 0 ;
-    int res4 ;
-    int argvi = 0;
-    size_t result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: VSIFWriteL(pBuffer,nSize,nCount,fp);");
-    }
-    {
-      /* %typemap(in,numinputs=1) (const void *pBuffer, size_t nSize, size_t nCount) */
-      size_t len;
-      arg1 = SvPV(ST(0), len);
-      arg2 = 1;
-      arg3 = len;
-    }
-    res4 = SWIG_ConvertPtr(ST(1),SWIG_as_voidptrptr(&arg4), 0, 0);
-    if (!SWIG_IsOK(res4)) {
-      SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "VSIFWriteL" "', argument " "4"" of type '" "VSILFILE *""'"); 
-    }
-    {
-      CPLErrorReset();
-      result = VSIFWriteL((void const *)arg1,arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_size_t  SWIG_PERL_CALL_ARGS_1(static_cast< size_t >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_VSIFReadL) {
-  {
-    void *arg1 = (void *) 0 ;
-    size_t arg2 ;
-    size_t arg3 ;
-    VSILFILE *arg4 = (VSILFILE *) 0 ;
-    int res4 ;
-    int argvi = 0;
-    SV * _saved[1] ;
-    size_t result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: VSIFReadL(pBuffer,nSize,nCount,fp);");
-    }
-    {
-      /* %typemap(in,numinputs=1) (void *pBuffer, size_t nSize, size_t nCount) */
-      size_t len = SvIV(ST(0));
-      arg1 = CPLMalloc(len);
-      if (!arg1)
-      SWIG_fail;
-      arg2 = 1;
-      arg3 = len;
-    }
-    res4 = SWIG_ConvertPtr(ST(1),SWIG_as_voidptrptr(&arg4), 0, 0);
-    if (!SWIG_IsOK(res4)) {
-      SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "VSIFReadL" "', argument " "4"" of type '" "VSILFILE *""'"); 
-    }
-    _saved[0] = ST(0);
-    {
-      CPLErrorReset();
-      result = VSIFReadL(arg1,arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) (size_t VSIFReadL) */
-    }
-    {
-      /* %typemap(argout) (void *pBuffer, size_t nSize, size_t nCount) */
-      if (result) {
-        ST(argvi) = sv_2mortal(newSVpvn((char*)arg1, result));
-      } else {
-        ST(argvi) = &PL_sv_undef;
-      }
-      CPLFree(arg1);
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_MajorObject_GetDescription) {
-  {
-    GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: MajorObject_GetDescription(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_GetDescription" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char *)GDALMajorObjectShadow_GetDescription(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_MajorObject_SetDescription) {
-  {
-    GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: MajorObject_SetDescription(self,pszNewDesc);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_SetDescription" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "MajorObject_SetDescription" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      GDALMajorObjectShadow_SetDescription(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_MajorObject_GetMetadataDomainList) {
-  {
-    GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char **result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: MajorObject_GetMetadataDomainList(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_GetMetadataDomainList" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char **)GDALMajorObjectShadow_GetMetadataDomainList(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) char **CSL */
-      if (GIMME_V == G_ARRAY) {
-        if (result) {
-          int i;
-          for (i = 0; result[i]; i++) {
-            if (argvi > items-1) EXTEND(SP, 1);
-            SV *sv = newSVpv(result[i], 0);
-            SvUTF8_on(sv); /* expecting GDAL to give us UTF-8 */
-            ST(argvi++) = sv_2mortal(sv);
-          }
-          CSLDestroy(result);
-        }
-      } else {
-        AV *av = (AV*)sv_2mortal((SV*)newAV());
-        if (result) {
-          int i;
-          for (i = 0; result[i]; i++) {
-            SV *sv = newSVpv(result[i], 0);
-            SvUTF8_on(sv); /* expecting GDAL to give us UTF-8 */
-            if (!av_store(av, i, sv))
-            SvREFCNT_dec(sv);
-          }
-          CSLDestroy(result);
-        }
-        ST(argvi) = newRV((SV*)av);
-        sv_2mortal(ST(argvi));
-        argvi++;
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_MajorObject_GetMetadata) {
-  {
-    GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
-    char *arg2 = (char *) "" ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    char **result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: MajorObject_GetMetadata(self,pszDomain);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_GetMetadata" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
-    if (items > 1) {
-      res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-      if (!SWIG_IsOK(res2)) {
-        SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "MajorObject_GetMetadata" "', argument " "2"" of type '" "char const *""'");
-      }
-      arg2 = reinterpret_cast< char * >(buf2);
-    }
-    {
-      CPLErrorReset();
-      result = (char **)GDALMajorObjectShadow_GetMetadata_Dict(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) char **dict */
-      char **stringarray = result;
-      HV *hv = (HV*)sv_2mortal((SV*)newHV());
-      if ( stringarray != NULL ) {
-        while (*stringarray != NULL ) {
-          char const *valptr;
-          char *keyptr;
-          valptr = CPLParseNameValue( *stringarray, &keyptr );
-          if ( valptr != 0 ) {
-            hv_store(hv, keyptr, strlen(keyptr), newSVpv(valptr, strlen(valptr)), 0);
-            CPLFree( keyptr );
-          }
-          stringarray++;
-        }
-      }
-      ST(argvi) = newRV((SV*)hv);
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_MajorObject_SetMetadata__SWIG_0) {
-  {
-    GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
-    char **arg2 = (char **) 0 ;
-    char *arg3 = (char *) "" ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res3 ;
-    char *buf3 = 0 ;
-    int alloc3 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 3)) {
-      SWIG_croak("Usage: MajorObject_SetMetadata(self,papszMetadata,pszDomain);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_SetMetadata" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
-    {
-      /* %typemap(in) char **dict */
-      HV *hv = (HV*)SvRV(ST(1));
-      SV *sv;
-      char *key;
-      I32 klen;
-      arg2 = NULL;
-      hv_iterinit(hv);
-      while(sv = hv_iternextsv(hv,&key,&klen)) {
-        arg2 = CSLAddNameValue( arg2, key, SvPV_nolen(sv) );
-      }
-    }
-    if (items > 2) {
-      res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
-      if (!SWIG_IsOK(res3)) {
-        SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "MajorObject_SetMetadata" "', argument " "3"" of type '" "char const *""'");
-      }
-      arg3 = reinterpret_cast< char * >(buf3);
-    }
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALMajorObjectShadow_SetMetadata__SWIG_0(arg1,arg2,(char const *)arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) CPLErr */
-    }
-    
-    {
-      /* %typemap(freearg) char **dict */
-      CSLDestroy( arg2 );
-    }
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) char **dict */
-      CSLDestroy( arg2 );
-    }
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_MajorObject_SetMetadata__SWIG_1) {
-  {
-    GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    char *arg3 = (char *) "" ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int res3 ;
-    char *buf3 = 0 ;
-    int alloc3 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 3)) {
-      SWIG_croak("Usage: MajorObject_SetMetadata(self,pszMetadataString,pszDomain);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_SetMetadata" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "MajorObject_SetMetadata" "', argument " "2"" of type '" "char *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    if (items > 2) {
-      res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
-      if (!SWIG_IsOK(res3)) {
-        SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "MajorObject_SetMetadata" "', argument " "3"" of type '" "char const *""'");
-      }
-      arg3 = reinterpret_cast< char * >(buf3);
-    }
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALMajorObjectShadow_SetMetadata__SWIG_1(arg1,arg2,(char const *)arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) CPLErr */
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_MajorObject_SetMetadata) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if ((items >= 2) && (items <= 3)) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_GDALMajorObjectShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          /* %typecheck(SWIG_TYPECHECK_POINTER) (char **dict) */
-          _v = (SvROK(ST(1)) && (SvTYPE(SvRV(ST(1)))==SVt_PVHV)) ? 1 : 0;
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (items > 2) {
-        {
-          int res = SWIG_AsCharPtrAndSize(ST(2), 0, NULL, 0);
-          _v = SWIG_CheckState(res);
-        }
-        if (!_v) goto check_1;
-        _ranki += _v*_pi;
-        _rankm += _pi;
-        _pi *= SWIG_MAXCASTRANK;
-      }
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if ((items >= 2) && (items <= 3)) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_GDALMajorObjectShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (items > 2) {
-        {
-          int res = SWIG_AsCharPtrAndSize(ST(2), 0, NULL, 0);
-          _v = SWIG_CheckState(res);
-        }
-        if (!_v) goto check_2;
-        _ranki += _v*_pi;
-        _rankm += _pi;
-        _pi *= SWIG_MAXCASTRANK;
-      }
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_MajorObject_SetMetadata__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_MajorObject_SetMetadata__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'MajorObject_SetMetadata'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_MajorObject_GetMetadataItem) {
-  {
-    GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    char *arg3 = (char *) "" ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int res3 ;
-    char *buf3 = 0 ;
-    int alloc3 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 3)) {
-      SWIG_croak("Usage: MajorObject_GetMetadataItem(self,pszName,pszDomain);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_GetMetadataItem" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "MajorObject_GetMetadataItem" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    if (items > 2) {
-      res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
-      if (!SWIG_IsOK(res3)) {
-        SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "MajorObject_GetMetadataItem" "', argument " "3"" of type '" "char const *""'");
-      }
-      arg3 = reinterpret_cast< char * >(buf3);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (char *)GDALMajorObjectShadow_GetMetadataItem(arg1,(char const *)arg2,(char const *)arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_MajorObject_SetMetadataItem) {
-  {
-    GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    char *arg3 = (char *) 0 ;
-    char *arg4 = (char *) "" ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int res3 ;
-    char *buf3 = 0 ;
-    int alloc3 = 0 ;
-    int res4 ;
-    char *buf4 = 0 ;
-    int alloc4 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 4)) {
-      SWIG_croak("Usage: MajorObject_SetMetadataItem(self,pszName,pszValue,pszDomain);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_SetMetadataItem" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "MajorObject_SetMetadataItem" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "MajorObject_SetMetadataItem" "', argument " "3"" of type '" "char const *""'");
-    }
-    arg3 = reinterpret_cast< char * >(buf3);
-    if (items > 3) {
-      res4 = SWIG_AsCharPtrAndSize(ST(3), &buf4, NULL, &alloc4);
-      if (!SWIG_IsOK(res4)) {
-        SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "MajorObject_SetMetadataItem" "', argument " "4"" of type '" "char const *""'");
-      }
-      arg4 = reinterpret_cast< char * >(buf4);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALMajorObjectShadow_SetMetadataItem(arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) CPLErr */
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Driver_ShortName_get) {
-  {
-    GDALDriverShadow *arg1 = (GDALDriverShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Driver_ShortName_get(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDriverShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_ShortName_get" "', argument " "1"" of type '" "GDALDriverShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDriverShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char *)GDALDriverShadow_ShortName_get(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Driver_LongName_get) {
-  {
-    GDALDriverShadow *arg1 = (GDALDriverShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Driver_LongName_get(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDriverShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_LongName_get" "', argument " "1"" of type '" "GDALDriverShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDriverShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char *)GDALDriverShadow_LongName_get(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Driver_HelpTopic_get) {
-  {
-    GDALDriverShadow *arg1 = (GDALDriverShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Driver_HelpTopic_get(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDriverShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_HelpTopic_get" "', argument " "1"" of type '" "GDALDriverShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDriverShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char *)GDALDriverShadow_HelpTopic_get(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Driver__Create) {
-  {
-    GDALDriverShadow *arg1 = (GDALDriverShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    int arg3 ;
-    int arg4 ;
-    int arg5 = (int) 1 ;
-    GDALDataType arg6 = (GDALDataType) GDT_Byte ;
-    char **arg7 = (char **) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int val4 ;
-    int ecode4 = 0 ;
-    int val5 ;
-    int ecode5 = 0 ;
-    int val6 ;
-    int ecode6 = 0 ;
-    int argvi = 0;
-    GDALDatasetShadow *result = 0 ;
-    dXSARGS;
-    
-    {
-      /* %typemap(default) const char * utf8_path */
-      arg2 = (char *)"";
-    }
-    if ((items < 1) || (items > 7)) {
-      SWIG_croak("Usage: Driver__Create(self,utf8_path,xsize,ysize,bands,eType,options);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDriverShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver__Create" "', argument " "1"" of type '" "GDALDriverShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDriverShadow * >(argp1);
-    if (items > 1) {
-      {
-        /* %typemap(in,numinputs=1) (const char* utf8_path) */
-        sv_utf8_upgrade(ST(1));
-        arg2 = SvPV_nolen(ST(1));
-      }
-    }
-    if (items > 2) {
-      ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-      if (!SWIG_IsOK(ecode3)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Driver__Create" "', argument " "3"" of type '" "int""'");
-      } 
-      arg3 = static_cast< int >(val3);
-    }
-    if (items > 3) {
-      ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-      if (!SWIG_IsOK(ecode4)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Driver__Create" "', argument " "4"" of type '" "int""'");
-      } 
-      arg4 = static_cast< int >(val4);
-    }
-    if (items > 4) {
-      ecode5 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-      if (!SWIG_IsOK(ecode5)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Driver__Create" "', argument " "5"" of type '" "int""'");
-      } 
-      arg5 = static_cast< int >(val5);
-    }
-    if (items > 5) {
-      ecode6 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(5), &val6);
-      if (!SWIG_IsOK(ecode6)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "Driver__Create" "', argument " "6"" of type '" "GDALDataType""'");
-      } 
-      arg6 = static_cast< GDALDataType >(val6);
-    }
-    if (items > 6) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(6))) {
-          if (SvROK(ST(6))) {
-            if (SvTYPE(SvRV(ST(6)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(6)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg7 = CSLAddString( arg7, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(6)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(6));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg7 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg7 = CSLAddNameValue( arg7, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (GDALDatasetShadow *)GDALDriverShadow_Create(arg1,(char const *)arg2,arg3,arg4,arg5,arg6,arg7);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    
-    
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg7) CSLDestroy( arg7 );
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg7) CSLDestroy( arg7 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Driver_CreateCopy) {
-  {
-    GDALDriverShadow *arg1 = (GDALDriverShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    GDALDatasetShadow *arg3 = (GDALDatasetShadow *) 0 ;
-    int arg4 = (int) 1 ;
-    char **arg5 = (char **) 0 ;
-    GDALProgressFunc arg6 = (GDALProgressFunc) NULL ;
-    void *arg7 = (void *) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
-    int val4 ;
-    int ecode4 = 0 ;
-    int argvi = 0;
-    GDALDatasetShadow *result = 0 ;
-    dXSARGS;
-    
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg7 = (void *)(&saved_env);
-    {
-      /* %typemap(default) const char * utf8_path */
-      arg2 = (char *)"";
-    }
-    if ((items < 1) || (items > 7)) {
-      SWIG_croak("Usage: Driver_CreateCopy(self,utf8_path,src,strict,options,callback,callback_data);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDriverShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_CreateCopy" "', argument " "1"" of type '" "GDALDriverShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDriverShadow * >(argp1);
-    if (items > 1) {
-      {
-        /* %typemap(in,numinputs=1) (const char* utf8_path) */
-        sv_utf8_upgrade(ST(1));
-        arg2 = SvPV_nolen(ST(1));
-      }
-    }
-    if (items > 2) {
-      res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-      if (!SWIG_IsOK(res3)) {
-        SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Driver_CreateCopy" "', argument " "3"" of type '" "GDALDatasetShadow *""'"); 
-      }
-      arg3 = reinterpret_cast< GDALDatasetShadow * >(argp3);
-    }
-    if (items > 3) {
-      ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-      if (!SWIG_IsOK(ecode4)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Driver_CreateCopy" "', argument " "4"" of type '" "int""'");
-      } 
-      arg4 = static_cast< int >(val4);
-    }
-    if (items > 4) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(4))) {
-          if (SvROK(ST(4))) {
-            if (SvTYPE(SvRV(ST(4)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(4)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg5 = CSLAddString( arg5, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(4)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(4));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg5 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg5 = CSLAddNameValue( arg5, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    if (items > 5) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(5))) {
-          if (SvROK(ST(5))) {
-            if (SvTYPE(SvRV(ST(5))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(5);
-              arg6 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 6) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(6)))
-        saved_env.data = (SV *)ST(6);
-      }
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      if (!arg3) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (GDALDatasetShadow *)GDALDriverShadow_CreateCopy(arg1,(char const *)arg2,arg3,arg4,arg5,arg6,arg7);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg5) CSLDestroy( arg5 );
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg5) CSLDestroy( arg5 );
-    }
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Driver_Delete) {
-  {
-    GDALDriverShadow *arg1 = (GDALDriverShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    {
-      /* %typemap(default) const char * utf8_path */
-      arg2 = (char *)"";
-    }
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: Driver_Delete(self,utf8_path);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDriverShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_Delete" "', argument " "1"" of type '" "GDALDriverShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDriverShadow * >(argp1);
-    if (items > 1) {
-      {
-        /* %typemap(in,numinputs=1) (const char* utf8_path) */
-        sv_utf8_upgrade(ST(1));
-        arg2 = SvPV_nolen(ST(1));
-      }
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALDriverShadow_Delete(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) CPLErr */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Driver_Rename) {
-  {
-    GDALDriverShadow *arg1 = (GDALDriverShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    char *arg3 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int res3 ;
-    char *buf3 = 0 ;
-    int alloc3 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Driver_Rename(self,newName,oldName);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDriverShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_Rename" "', argument " "1"" of type '" "GDALDriverShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDriverShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Driver_Rename" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Driver_Rename" "', argument " "3"" of type '" "char const *""'");
-    }
-    arg3 = reinterpret_cast< char * >(buf3);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      if (!arg3) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALDriverShadow_Rename(arg1,(char const *)arg2,(char const *)arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) CPLErr */
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Driver_CopyFiles) {
-  {
-    GDALDriverShadow *arg1 = (GDALDriverShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    char *arg3 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int res3 ;
-    char *buf3 = 0 ;
-    int alloc3 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Driver_CopyFiles(self,newName,oldName);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDriverShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_CopyFiles" "', argument " "1"" of type '" "GDALDriverShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDriverShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Driver_CopyFiles" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Driver_CopyFiles" "', argument " "3"" of type '" "char const *""'");
-    }
-    arg3 = reinterpret_cast< char * >(buf3);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      if (!arg3) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALDriverShadow_CopyFiles(arg1,(char const *)arg2,(char const *)arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) CPLErr */
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Driver_Register) {
-  {
-    GDALDriverShadow *arg1 = (GDALDriverShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Driver_Register(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDriverShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_Register" "', argument " "1"" of type '" "GDALDriverShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDriverShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)GDALDriverShadow_Register(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Driver_Deregister) {
-  {
-    GDALDriverShadow *arg1 = (GDALDriverShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Driver_Deregister(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDriverShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_Deregister" "', argument " "1"" of type '" "GDALDriverShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDriverShadow * >(argp1);
-    {
-      CPLErrorReset();
-      GDALDriverShadow_Deregister(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GCP_X_set) {
-  {
-    GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
-    double arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: GCP_X_set(self,GCPX);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDAL_GCP, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GCP_X_set" "', argument " "1"" of type '" "GDAL_GCP *""'"); 
-    }
-    arg1 = reinterpret_cast< GDAL_GCP * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "GCP_X_set" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    {
-      CPLErrorReset();
-      GDAL_GCP_GCPX_set(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GCP_X_get) {
-  {
-    GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    double result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GCP_X_get(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDAL_GCP, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GCP_X_get" "', argument " "1"" of type '" "GDAL_GCP *""'"); 
-    }
-    arg1 = reinterpret_cast< GDAL_GCP * >(argp1);
-    {
-      CPLErrorReset();
-      result = (double)GDAL_GCP_GCPX_get(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GCP_Y_set) {
-  {
-    GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
-    double arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: GCP_Y_set(self,GCPY);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDAL_GCP, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GCP_Y_set" "', argument " "1"" of type '" "GDAL_GCP *""'"); 
-    }
-    arg1 = reinterpret_cast< GDAL_GCP * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "GCP_Y_set" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    {
-      CPLErrorReset();
-      GDAL_GCP_GCPY_set(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GCP_Y_get) {
-  {
-    GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    double result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GCP_Y_get(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDAL_GCP, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GCP_Y_get" "', argument " "1"" of type '" "GDAL_GCP *""'"); 
-    }
-    arg1 = reinterpret_cast< GDAL_GCP * >(argp1);
-    {
-      CPLErrorReset();
-      result = (double)GDAL_GCP_GCPY_get(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GCP_Z_set) {
-  {
-    GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
-    double arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: GCP_Z_set(self,GCPZ);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDAL_GCP, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GCP_Z_set" "', argument " "1"" of type '" "GDAL_GCP *""'"); 
-    }
-    arg1 = reinterpret_cast< GDAL_GCP * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "GCP_Z_set" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    {
-      CPLErrorReset();
-      GDAL_GCP_GCPZ_set(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GCP_Z_get) {
-  {
-    GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    double result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GCP_Z_get(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDAL_GCP, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GCP_Z_get" "', argument " "1"" of type '" "GDAL_GCP *""'"); 
-    }
-    arg1 = reinterpret_cast< GDAL_GCP * >(argp1);
-    {
-      CPLErrorReset();
-      result = (double)GDAL_GCP_GCPZ_get(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GCP_Column_set) {
-  {
-    GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
-    double arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: GCP_Column_set(self,GCPPixel);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDAL_GCP, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GCP_Column_set" "', argument " "1"" of type '" "GDAL_GCP *""'"); 
-    }
-    arg1 = reinterpret_cast< GDAL_GCP * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "GCP_Column_set" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    {
-      CPLErrorReset();
-      GDAL_GCP_GCPPixel_set(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GCP_Column_get) {
-  {
-    GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    double result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GCP_Column_get(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDAL_GCP, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GCP_Column_get" "', argument " "1"" of type '" "GDAL_GCP *""'"); 
-    }
-    arg1 = reinterpret_cast< GDAL_GCP * >(argp1);
-    {
-      CPLErrorReset();
-      result = (double)GDAL_GCP_GCPPixel_get(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GCP_Row_set) {
-  {
-    GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
-    double arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: GCP_Row_set(self,GCPLine);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDAL_GCP, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GCP_Row_set" "', argument " "1"" of type '" "GDAL_GCP *""'"); 
-    }
-    arg1 = reinterpret_cast< GDAL_GCP * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "GCP_Row_set" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    {
-      CPLErrorReset();
-      GDAL_GCP_GCPLine_set(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GCP_Row_get) {
-  {
-    GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    double result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GCP_Row_get(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDAL_GCP, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GCP_Row_get" "', argument " "1"" of type '" "GDAL_GCP *""'"); 
-    }
-    arg1 = reinterpret_cast< GDAL_GCP * >(argp1);
-    {
-      CPLErrorReset();
-      result = (double)GDAL_GCP_GCPLine_get(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GCP_Info_set) {
-  {
-    GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: GCP_Info_set(self,Info);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDAL_GCP, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GCP_Info_set" "', argument " "1"" of type '" "GDAL_GCP *""'"); 
-    }
-    arg1 = reinterpret_cast< GDAL_GCP * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "GCP_Info_set" "', argument " "2"" of type '" "char *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    {
-      CPLErrorReset();
-      GDAL_GCP_Info_set(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GCP_Info_get) {
-  {
-    GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GCP_Info_get(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDAL_GCP, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GCP_Info_get" "', argument " "1"" of type '" "GDAL_GCP *""'"); 
-    }
-    arg1 = reinterpret_cast< GDAL_GCP * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char *)GDAL_GCP_Info_get(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_FromCharPtr((const char *)result); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GCP_Id_set) {
-  {
-    GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: GCP_Id_set(self,Id);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDAL_GCP, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GCP_Id_set" "', argument " "1"" of type '" "GDAL_GCP *""'"); 
-    }
-    arg1 = reinterpret_cast< GDAL_GCP * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "GCP_Id_set" "', argument " "2"" of type '" "char *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    {
-      CPLErrorReset();
-      GDAL_GCP_Id_set(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GCP_Id_get) {
-  {
-    GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GCP_Id_get(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDAL_GCP, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GCP_Id_get" "', argument " "1"" of type '" "GDAL_GCP *""'"); 
-    }
-    arg1 = reinterpret_cast< GDAL_GCP * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char *)GDAL_GCP_Id_get(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_FromCharPtr((const char *)result); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_new_GCP) {
-  {
-    double arg1 = (double) 0.0 ;
-    double arg2 = (double) 0.0 ;
-    double arg3 = (double) 0.0 ;
-    double arg4 = (double) 0.0 ;
-    double arg5 = (double) 0.0 ;
-    char *arg6 = (char *) "" ;
-    char *arg7 = (char *) "" ;
-    double val1 ;
-    int ecode1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    int res6 ;
-    char *buf6 = 0 ;
-    int alloc6 = 0 ;
-    int res7 ;
-    char *buf7 = 0 ;
-    int alloc7 = 0 ;
-    int argvi = 0;
-    GDAL_GCP *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 7)) {
-      SWIG_croak("Usage: new_GCP(x,y,z,pixel,line,info,id);");
-    }
-    if (items > 0) {
-      ecode1 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-      if (!SWIG_IsOK(ecode1)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "new_GCP" "', argument " "1"" of type '" "double""'");
-      } 
-      arg1 = static_cast< double >(val1);
-    }
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "new_GCP" "', argument " "2"" of type '" "double""'");
-      } 
-      arg2 = static_cast< double >(val2);
-    }
-    if (items > 2) {
-      ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-      if (!SWIG_IsOK(ecode3)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "new_GCP" "', argument " "3"" of type '" "double""'");
-      } 
-      arg3 = static_cast< double >(val3);
-    }
-    if (items > 3) {
-      ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-      if (!SWIG_IsOK(ecode4)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "new_GCP" "', argument " "4"" of type '" "double""'");
-      } 
-      arg4 = static_cast< double >(val4);
-    }
-    if (items > 4) {
-      ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-      if (!SWIG_IsOK(ecode5)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "new_GCP" "', argument " "5"" of type '" "double""'");
-      } 
-      arg5 = static_cast< double >(val5);
-    }
-    if (items > 5) {
-      res6 = SWIG_AsCharPtrAndSize(ST(5), &buf6, NULL, &alloc6);
-      if (!SWIG_IsOK(res6)) {
-        SWIG_exception_fail(SWIG_ArgError(res6), "in method '" "new_GCP" "', argument " "6"" of type '" "char const *""'");
-      }
-      arg6 = reinterpret_cast< char * >(buf6);
-    }
-    if (items > 6) {
-      res7 = SWIG_AsCharPtrAndSize(ST(6), &buf7, NULL, &alloc7);
-      if (!SWIG_IsOK(res7)) {
-        SWIG_exception_fail(SWIG_ArgError(res7), "in method '" "new_GCP" "', argument " "7"" of type '" "char const *""'");
-      }
-      arg7 = reinterpret_cast< char * >(buf7);
-    }
-    {
-      CPLErrorReset();
-      result = (GDAL_GCP *)new_GDAL_GCP(arg1,arg2,arg3,arg4,arg5,(char const *)arg6,(char const *)arg7);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDAL_GCP, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    
-    
-    
-    
-    if (alloc6 == SWIG_NEWOBJ) delete[] buf6;
-    if (alloc7 == SWIG_NEWOBJ) delete[] buf7;
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    if (alloc6 == SWIG_NEWOBJ) delete[] buf6;
-    if (alloc7 == SWIG_NEWOBJ) delete[] buf7;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_delete_GCP) {
-  {
-    GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: delete_GCP(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDAL_GCP, SWIG_POINTER_DISOWN |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_GCP" "', argument " "1"" of type '" "GDAL_GCP *""'"); 
-    }
-    arg1 = reinterpret_cast< GDAL_GCP * >(argp1);
-    {
-      CPLErrorReset();
-      delete_GDAL_GCP(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GDAL_GCP_GCPX_get) {
-  {
-    GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    double result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GDAL_GCP_GCPX_get(gcp);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDAL_GCP, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GDAL_GCP_GCPX_get" "', argument " "1"" of type '" "GDAL_GCP *""'"); 
-    }
-    arg1 = reinterpret_cast< GDAL_GCP * >(argp1);
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (double)GDAL_GCP_GCPX_get(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GDAL_GCP_GCPX_set) {
-  {
-    GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
-    double arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: GDAL_GCP_GCPX_set(gcp,dfGCPX);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDAL_GCP, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GDAL_GCP_GCPX_set" "', argument " "1"" of type '" "GDAL_GCP *""'"); 
-    }
-    arg1 = reinterpret_cast< GDAL_GCP * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "GDAL_GCP_GCPX_set" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      GDAL_GCP_GCPX_set(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GDAL_GCP_GCPY_get) {
-  {
-    GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    double result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GDAL_GCP_GCPY_get(gcp);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDAL_GCP, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GDAL_GCP_GCPY_get" "', argument " "1"" of type '" "GDAL_GCP *""'"); 
-    }
-    arg1 = reinterpret_cast< GDAL_GCP * >(argp1);
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (double)GDAL_GCP_GCPY_get(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GDAL_GCP_GCPY_set) {
-  {
-    GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
-    double arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: GDAL_GCP_GCPY_set(gcp,dfGCPY);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDAL_GCP, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GDAL_GCP_GCPY_set" "', argument " "1"" of type '" "GDAL_GCP *""'"); 
-    }
-    arg1 = reinterpret_cast< GDAL_GCP * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "GDAL_GCP_GCPY_set" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      GDAL_GCP_GCPY_set(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GDAL_GCP_GCPZ_get) {
-  {
-    GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    double result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GDAL_GCP_GCPZ_get(gcp);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDAL_GCP, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GDAL_GCP_GCPZ_get" "', argument " "1"" of type '" "GDAL_GCP *""'"); 
-    }
-    arg1 = reinterpret_cast< GDAL_GCP * >(argp1);
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (double)GDAL_GCP_GCPZ_get(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GDAL_GCP_GCPZ_set) {
-  {
-    GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
-    double arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: GDAL_GCP_GCPZ_set(gcp,dfGCPZ);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDAL_GCP, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GDAL_GCP_GCPZ_set" "', argument " "1"" of type '" "GDAL_GCP *""'"); 
-    }
-    arg1 = reinterpret_cast< GDAL_GCP * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "GDAL_GCP_GCPZ_set" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      GDAL_GCP_GCPZ_set(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GDAL_GCP_GCPPixel_get) {
-  {
-    GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    double result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GDAL_GCP_GCPPixel_get(gcp);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDAL_GCP, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GDAL_GCP_GCPPixel_get" "', argument " "1"" of type '" "GDAL_GCP *""'"); 
-    }
-    arg1 = reinterpret_cast< GDAL_GCP * >(argp1);
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (double)GDAL_GCP_GCPPixel_get(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GDAL_GCP_GCPPixel_set) {
-  {
-    GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
-    double arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: GDAL_GCP_GCPPixel_set(gcp,dfGCPPixel);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDAL_GCP, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GDAL_GCP_GCPPixel_set" "', argument " "1"" of type '" "GDAL_GCP *""'"); 
-    }
-    arg1 = reinterpret_cast< GDAL_GCP * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "GDAL_GCP_GCPPixel_set" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      GDAL_GCP_GCPPixel_set(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GDAL_GCP_GCPLine_get) {
-  {
-    GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    double result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GDAL_GCP_GCPLine_get(gcp);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDAL_GCP, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GDAL_GCP_GCPLine_get" "', argument " "1"" of type '" "GDAL_GCP *""'"); 
-    }
-    arg1 = reinterpret_cast< GDAL_GCP * >(argp1);
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (double)GDAL_GCP_GCPLine_get(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GDAL_GCP_GCPLine_set) {
-  {
-    GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
-    double arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: GDAL_GCP_GCPLine_set(gcp,dfGCPLine);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDAL_GCP, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GDAL_GCP_GCPLine_set" "', argument " "1"" of type '" "GDAL_GCP *""'"); 
-    }
-    arg1 = reinterpret_cast< GDAL_GCP * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "GDAL_GCP_GCPLine_set" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      GDAL_GCP_GCPLine_set(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GDAL_GCP_Info_get) {
-  {
-    GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GDAL_GCP_Info_get(gcp);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDAL_GCP, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GDAL_GCP_Info_get" "', argument " "1"" of type '" "GDAL_GCP *""'"); 
-    }
-    arg1 = reinterpret_cast< GDAL_GCP * >(argp1);
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (char *)GDAL_GCP_Info_get(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GDAL_GCP_Info_set) {
-  {
-    GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: GDAL_GCP_Info_set(gcp,pszInfo);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDAL_GCP, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GDAL_GCP_Info_set" "', argument " "1"" of type '" "GDAL_GCP *""'"); 
-    }
-    arg1 = reinterpret_cast< GDAL_GCP * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "GDAL_GCP_Info_set" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      GDAL_GCP_Info_set(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GDAL_GCP_Id_get) {
-  {
-    GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GDAL_GCP_Id_get(gcp);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDAL_GCP, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GDAL_GCP_Id_get" "', argument " "1"" of type '" "GDAL_GCP *""'"); 
-    }
-    arg1 = reinterpret_cast< GDAL_GCP * >(argp1);
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (char *)GDAL_GCP_Id_get(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GDAL_GCP_Id_set) {
-  {
-    GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: GDAL_GCP_Id_set(gcp,pszId);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDAL_GCP, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GDAL_GCP_Id_set" "', argument " "1"" of type '" "GDAL_GCP *""'"); 
-    }
-    arg1 = reinterpret_cast< GDAL_GCP * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "GDAL_GCP_Id_set" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      GDAL_GCP_Id_set(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GCPsToGeoTransform) {
-  {
-    int arg1 ;
-    GDAL_GCP *arg2 = (GDAL_GCP *) 0 ;
-    double *arg3 ;
-    int arg4 = (int) 1 ;
-    double argout3[6] ;
-    int val4 ;
-    int ecode4 = 0 ;
-    int argvi = 0;
-    RETURN_NONE result;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (double argout3[ANY]) */
-      arg3 = argout3;
-    }
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: GCPsToGeoTransform(nGCPs,pGCPs,bApproxOK);");
-    }
-    {
-      /* %typemap(in,numinputs=1) (int nGCPs, GDAL_GCP const *pGCPs ) */
-      if (!(SvROK(ST(0)) && (SvTYPE(SvRV(ST(0)))==SVt_PVAV)))
-      SWIG_croak("Expected a reference to an array.");
-      AV *av = (AV*)(SvRV(ST(0)));
-      arg1 = av_len(av)+1;
-      arg2 = (GDAL_GCP *)CPLMalloc(arg1*sizeof(GDAL_GCP));
-      if (arg2) {
-        for (int i = 0; i < arg1; i++ ) {
-          SV **sv = av_fetch(av, i, 0);
-          int ret = SWIG_ConvertPtr(*sv, (void**)&(arg2[i]), SWIGTYPE_p_GDAL_GCP, 0);
-          if (!SWIG_IsOK(ret))
-          SWIG_croak("An item in the argument array is not a GCP object.");
-        }
-      } else
-      SWIG_croak("Out of memory.");
-    }
-    if (items > 1) {
-      ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val4);
-      if (!SWIG_IsOK(ecode4)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "GCPsToGeoTransform" "', argument " "4"" of type '" "int""'");
-      } 
-      arg4 = static_cast< int >(val4);
-    }
-    {
-      CPLErrorReset();
-      result = GDALGCPsToGeoTransform(arg1,(GDAL_GCP const *)arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) IF_FALSE_RETURN_NONE */
-    }
-    {
-      /* %typemap(argout) (double argout[ANY]) */
-      if (GIMME_V == G_ARRAY) {
-        /* return a list */
-        int i;
-        EXTEND(SP, argvi+6-items+1);
-        for (i = 0; i < 6; i++)
-        ST(argvi++) = sv_2mortal(newSVnv(arg3[i]));
-      } else {
-        ST(argvi) = CreateArrayFromDoubleArray( arg3, 6 );
-        argvi++;
-      }  
-    }
-    {
-      /* %typemap(freearg) (int nGCPs, GDAL_GCP const *pGCPs ) */
-      CPLFree(arg2);
-    }
-    
-    
-    {
-      /* %typemap(ret) IF_FALSE_RETURN_NONE */
-      if (result == 0 ) {
-        SWIG_croak("unexpected error in 'GCPsToGeoTransform'");
-      }
-    }
-    XSRETURN(argvi);
-  fail:
-    {
-      /* %typemap(freearg) (int nGCPs, GDAL_GCP const *pGCPs ) */
-      CPLFree(arg2);
-    }
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_delete_AsyncReader) {
-  {
-    GDALAsyncReaderShadow *arg1 = (GDALAsyncReaderShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: delete_AsyncReader(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALAsyncReaderShadow, SWIG_POINTER_DISOWN |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_AsyncReader" "', argument " "1"" of type '" "GDALAsyncReaderShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALAsyncReaderShadow * >(argp1);
-    {
-      CPLErrorReset();
-      delete_GDALAsyncReaderShadow(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_AsyncReader_GetNextUpdatedRegion) {
-  {
-    GDALAsyncReaderShadow *arg1 = (GDALAsyncReaderShadow *) 0 ;
-    double arg2 ;
-    int *arg3 = (int *) 0 ;
-    int *arg4 = (int *) 0 ;
-    int *arg5 = (int *) 0 ;
-    int *arg6 = (int *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    int temp3 ;
-    int res3 = SWIG_TMPOBJ ;
-    int temp4 ;
-    int res4 = SWIG_TMPOBJ ;
-    int temp5 ;
-    int res5 = SWIG_TMPOBJ ;
-    int temp6 ;
-    int res6 = SWIG_TMPOBJ ;
-    int argvi = 0;
-    GDALAsyncStatusType result;
-    dXSARGS;
-    
-    arg3 = &temp3;
-    arg4 = &temp4;
-    arg5 = &temp5;
-    arg6 = &temp6;
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: AsyncReader_GetNextUpdatedRegion(self,timeout);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALAsyncReaderShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "AsyncReader_GetNextUpdatedRegion" "', argument " "1"" of type '" "GDALAsyncReaderShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALAsyncReaderShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "AsyncReader_GetNextUpdatedRegion" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    {
-      CPLErrorReset();
-      result = (GDALAsyncStatusType)GDALAsyncReaderShadow_GetNextUpdatedRegion(arg1,arg2,arg3,arg4,arg5,arg6);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    if (SWIG_IsTmpObj(res3)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg3)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_int, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res4)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg4)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res5)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg5)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res5) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg5), SWIGTYPE_p_int, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res6)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg6)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res6) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg6), SWIGTYPE_p_int, new_flags); argvi++  ;
-    }
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_AsyncReader_LockBuffer) {
-  {
-    GDALAsyncReaderShadow *arg1 = (GDALAsyncReaderShadow *) 0 ;
-    double arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: AsyncReader_LockBuffer(self,timeout);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALAsyncReaderShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "AsyncReader_LockBuffer" "', argument " "1"" of type '" "GDALAsyncReaderShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALAsyncReaderShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "AsyncReader_LockBuffer" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    {
-      CPLErrorReset();
-      result = (int)GDALAsyncReaderShadow_LockBuffer(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_AsyncReader_UnlockBuffer) {
-  {
-    GDALAsyncReaderShadow *arg1 = (GDALAsyncReaderShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: AsyncReader_UnlockBuffer(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALAsyncReaderShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "AsyncReader_UnlockBuffer" "', argument " "1"" of type '" "GDALAsyncReaderShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALAsyncReaderShadow * >(argp1);
-    {
-      CPLErrorReset();
-      GDALAsyncReaderShadow_UnlockBuffer(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Dataset_RasterXSize_get) {
-  {
-    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Dataset_RasterXSize_get(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset_RasterXSize_get" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)GDALDatasetShadow_RasterXSize_get(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Dataset_RasterYSize_get) {
-  {
-    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Dataset_RasterYSize_get(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset_RasterYSize_get" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)GDALDatasetShadow_RasterYSize_get(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Dataset_RasterCount_get) {
-  {
-    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Dataset_RasterCount_get(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset_RasterCount_get" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)GDALDatasetShadow_RasterCount_get(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_delete_Dataset) {
-  {
-    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: delete_Dataset(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDatasetShadow, SWIG_POINTER_DISOWN |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_Dataset" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-    {
-      CPLErrorReset();
-      delete_GDALDatasetShadow(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Dataset__GetDriver) {
-  {
-    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    GDALDriverShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Dataset__GetDriver(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset__GetDriver" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (GDALDriverShadow *)GDALDatasetShadow_GetDriver(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDriverShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Dataset__GetRasterBand) {
-  {
-    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    GDALRasterBandShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Dataset__GetRasterBand(self,nBand);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset__GetRasterBand" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Dataset__GetRasterBand" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (GDALRasterBandShadow *)GDALDatasetShadow_GetRasterBand(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALRasterBandShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Dataset_GetProjection) {
-  {
-    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Dataset_GetProjection(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset_GetProjection" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char *)GDALDatasetShadow_GetProjection(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Dataset_GetProjectionRef) {
-  {
-    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Dataset_GetProjectionRef(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset_GetProjectionRef" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char *)GDALDatasetShadow_GetProjectionRef(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Dataset_SetProjection) {
-  {
-    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Dataset_SetProjection(self,prj);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset_SetProjection" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Dataset_SetProjection" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALDatasetShadow_SetProjection(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) CPLErr */
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Dataset_GetGeoTransform) {
-  {
-    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-    double *arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double argout2[6] ;
-    int argvi = 0;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (double argout2[ANY]) */
-      arg2 = argout2;
-    }
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Dataset_GetGeoTransform(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset_GetGeoTransform" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-    {
-      CPLErrorReset();
-      GDALDatasetShadow_GetGeoTransform(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    {
-      /* %typemap(argout) (double argout[ANY]) */
-      if (GIMME_V == G_ARRAY) {
-        /* return a list */
-        int i;
-        EXTEND(SP, argvi+6-items+1);
-        for (i = 0; i < 6; i++)
-        ST(argvi++) = sv_2mortal(newSVnv(arg2[i]));
-      } else {
-        ST(argvi) = CreateArrayFromDoubleArray( arg2, 6 );
-        argvi++;
-      }  
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Dataset_SetGeoTransform) {
-  {
-    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-    double *arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double argin2[6] ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Dataset_SetGeoTransform(self,argin);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset_SetGeoTransform" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-    {
-      /* %typemap(in) (double argin2[ANY]) */
-      if (!(SvROK(ST(1)) && (SvTYPE(SvRV(ST(1)))==SVt_PVAV)))
-      SWIG_croak("Expected a reference to an array.");
-      arg2 = argin2;
-      AV *av = (AV*)(SvRV(ST(1)));
-      for (unsigned int i=0; i<6; i++) {
-        SV **sv = av_fetch(av, i, 0);
-        arg2[i] =  SvNV(*sv);
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALDatasetShadow_SetGeoTransform(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) CPLErr */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Dataset__BuildOverviews) {
-  {
-    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-    char *arg2 = (char *) "NEAREST" ;
-    int arg3 = (int) 0 ;
-    int *arg4 = (int *) 0 ;
-    GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
-    void *arg6 = (void *) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg6 = (void *)(&saved_env);
-    if ((items < 1) || (items > 5)) {
-      SWIG_croak("Usage: Dataset__BuildOverviews(self,resampling,overviewlist,pOverviews,callback,callback_data);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset__BuildOverviews" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-    if (items > 1) {
-      res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-      if (!SWIG_IsOK(res2)) {
-        SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Dataset__BuildOverviews" "', argument " "2"" of type '" "char const *""'");
-      }
-      arg2 = reinterpret_cast< char * >(buf2);
-    }
-    if (items > 2) {
-      {
-        /* %typemap(in,numinputs=1) (int nList, int* pList) */
-        if (!(SvROK(ST(2)) && (SvTYPE(SvRV(ST(2)))==SVt_PVAV)))
-        SWIG_croak("Expected a reference to an array.");
-        AV *av = (AV*)(SvRV(ST(2)));
-        arg3 = av_len(av)+1;
-        arg4 = (int*)CPLMalloc(arg3*sizeof(int));
-        if (arg4) {
-          for( int i = 0; i<arg3; i++ ) {
-            SV **sv = av_fetch(av, i, 0);
-            arg4[i] =  SvIV(*sv);
-          }
-        } else
-        SWIG_fail;
-      }
-    }
-    if (items > 3) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(3))) {
-          if (SvROK(ST(3))) {
-            if (SvTYPE(SvRV(ST(3))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(3);
-              arg5 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 4) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(4)))
-        saved_env.data = (SV *)ST(4);
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (int)GDALDatasetShadow_BuildOverviews(arg1,(char const *)arg2,arg3,arg4,arg5,arg6);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    {
-      /* %typemap(freearg) (int nList, int* pList) */
-      CPLFree((void*) arg4);
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    {
-      /* %typemap(freearg) (int nList, int* pList) */
-      CPLFree((void*) arg4);
-    }
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Dataset_GetGCPCount) {
-  {
-    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Dataset_GetGCPCount(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset_GetGCPCount" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)GDALDatasetShadow_GetGCPCount(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Dataset_GetGCPProjection) {
-  {
-    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Dataset_GetGCPProjection(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset_GetGCPProjection" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char *)GDALDatasetShadow_GetGCPProjection(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Dataset_GetGCPs) {
-  {
-    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-    int *arg2 = (int *) 0 ;
-    GDAL_GCP **arg3 = (GDAL_GCP **) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int nGCPs2 = 0 ;
-    GDAL_GCP *pGCPs2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (int *nGCPs2, GDAL_GCP const **pGCPs2 ) */
-      arg2 = &nGCPs2;
-      arg3 = &pGCPs2;
-    }
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Dataset_GetGCPs(self,pGCPs);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset_GetGCPs" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-    {
-      CPLErrorReset();
-      GDALDatasetShadow_GetGCPs(arg1,arg2,(GDAL_GCP const **)arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    {
-      /* %typemap(argout) (int *nGCPs, GDAL_GCP const **pGCPs ) */
-      AV *dict = (AV*)sv_2mortal((SV*)newAV());
-      for( int i = 0; i < *arg2; i++ ) {
-        GDAL_GCP *o = new_GDAL_GCP( (*arg3)[i].dfGCPX,
-          (*arg3)[i].dfGCPY,
-          (*arg3)[i].dfGCPZ,
-          (*arg3)[i].dfGCPPixel,
-          (*arg3)[i].dfGCPLine,
-          (*arg3)[i].pszInfo,
-          (*arg3)[i].pszId );
-        SV *sv = newSV(0);
-        SWIG_MakePtr( sv, (void*)o, SWIGTYPE_p_GDAL_GCP, SWIG_SHADOW|SWIG_OWNER);
-        av_store(dict, i, sv);
-      }
-      ST(argvi) = sv_2mortal(newRV((SV*)dict));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Dataset_SetGCPs) {
-  {
-    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-    int arg2 ;
-    GDAL_GCP *arg3 = (GDAL_GCP *) 0 ;
-    char *arg4 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res4 ;
-    char *buf4 = 0 ;
-    int alloc4 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Dataset_SetGCPs(self,nGCPs,pGCPs,pszGCPProjection);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset_SetGCPs" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (int nGCPs, GDAL_GCP const *pGCPs ) */
-      if (!(SvROK(ST(1)) && (SvTYPE(SvRV(ST(1)))==SVt_PVAV)))
-      SWIG_croak("Expected a reference to an array.");
-      AV *av = (AV*)(SvRV(ST(1)));
-      arg2 = av_len(av)+1;
-      arg3 = (GDAL_GCP *)CPLMalloc(arg2*sizeof(GDAL_GCP));
-      if (arg3) {
-        for (int i = 0; i < arg2; i++ ) {
-          SV **sv = av_fetch(av, i, 0);
-          int ret = SWIG_ConvertPtr(*sv, (void**)&(arg3[i]), SWIGTYPE_p_GDAL_GCP, 0);
-          if (!SWIG_IsOK(ret))
-          SWIG_croak("An item in the argument array is not a GCP object.");
-        }
-      } else
-      SWIG_croak("Out of memory.");
-    }
-    res4 = SWIG_AsCharPtrAndSize(ST(2), &buf4, NULL, &alloc4);
-    if (!SWIG_IsOK(res4)) {
-      SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "Dataset_SetGCPs" "', argument " "4"" of type '" "char const *""'");
-    }
-    arg4 = reinterpret_cast< char * >(buf4);
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALDatasetShadow_SetGCPs(arg1,arg2,(GDAL_GCP const *)arg3,(char const *)arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) CPLErr */
-    }
-    
-    {
-      /* %typemap(freearg) (int nGCPs, GDAL_GCP const *pGCPs ) */
-      CPLFree(arg3);
-    }
-    if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) (int nGCPs, GDAL_GCP const *pGCPs ) */
-      CPLFree(arg3);
-    }
-    if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Dataset_FlushCache) {
-  {
-    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Dataset_FlushCache(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset_FlushCache" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-    {
-      CPLErrorReset();
-      GDALDatasetShadow_FlushCache(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Dataset__AddBand) {
-  {
-    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-    GDALDataType arg2 = (GDALDataType) GDT_Byte ;
-    char **arg3 = (char **) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 3)) {
-      SWIG_croak("Usage: Dataset__AddBand(self,datatype,options);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset__AddBand" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Dataset__AddBand" "', argument " "2"" of type '" "GDALDataType""'");
-      } 
-      arg2 = static_cast< GDALDataType >(val2);
-    }
-    if (items > 2) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(2))) {
-          if (SvROK(ST(2))) {
-            if (SvTYPE(SvRV(ST(2)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(2)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg3 = CSLAddString( arg3, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(2)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(2));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg3 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg3 = CSLAddNameValue( arg3, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALDatasetShadow_AddBand(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) CPLErr */
-    }
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg3) CSLDestroy( arg3 );
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg3) CSLDestroy( arg3 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Dataset__CreateMaskBand) {
-  {
-    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Dataset__CreateMaskBand(self,nFlags);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset__CreateMaskBand" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Dataset__CreateMaskBand" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALDatasetShadow_CreateMaskBand(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) CPLErr */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Dataset_GetFileList) {
-  {
-    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char **result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Dataset_GetFileList(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset_GetFileList" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char **)GDALDatasetShadow_GetFileList(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) char **CSL */
-      if (GIMME_V == G_ARRAY) {
-        if (result) {
-          int i;
-          for (i = 0; result[i]; i++) {
-            if (argvi > items-1) EXTEND(SP, 1);
-            SV *sv = newSVpv(result[i], 0);
-            SvUTF8_on(sv); /* expecting GDAL to give us UTF-8 */
-            ST(argvi++) = sv_2mortal(sv);
-          }
-          CSLDestroy(result);
-        }
-      } else {
-        AV *av = (AV*)sv_2mortal((SV*)newAV());
-        if (result) {
-          int i;
-          for (i = 0; result[i]; i++) {
-            SV *sv = newSVpv(result[i], 0);
-            SvUTF8_on(sv); /* expecting GDAL to give us UTF-8 */
-            if (!av_store(av, i, sv))
-            SvREFCNT_dec(sv);
-          }
-          CSLDestroy(result);
-        }
-        ST(argvi) = newRV((SV*)av);
-        sv_2mortal(ST(argvi));
-        argvi++;
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Dataset__WriteRaster) {
-  {
-    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-    int arg2 ;
-    int arg3 ;
-    int arg4 ;
-    int arg5 ;
-    int arg6 ;
-    char *arg7 = (char *) 0 ;
-    int *arg8 = (int *) 0 ;
-    int *arg9 = (int *) 0 ;
-    GDALDataType *arg10 = (GDALDataType *) 0 ;
-    int arg11 = (int) 0 ;
-    int *arg12 = (int *) 0 ;
-    int *arg13 = (int *) 0 ;
-    int *arg14 = (int *) 0 ;
-    int *arg15 = (int *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int val4 ;
-    int ecode4 = 0 ;
-    int val5 ;
-    int ecode5 = 0 ;
-    int val8 ;
-    int val9 ;
-    int val10 ;
-    int val13 ;
-    int val14 ;
-    int val15 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 6) || (items > 13)) {
-      SWIG_croak("Usage: Dataset__WriteRaster(self,xoff,yoff,xsize,ysize,buf_len,buf_string,buf_xsize,buf_ysize,buf_type,band_list,pband_list,buf_pixel_space,buf_line_space,buf_band_space);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset__WriteRaster" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Dataset__WriteRaster" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Dataset__WriteRaster" "', argument " "3"" of type '" "int""'");
-    } 
-    arg3 = static_cast< int >(val3);
-    ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Dataset__WriteRaster" "', argument " "4"" of type '" "int""'");
-    } 
-    arg4 = static_cast< int >(val4);
-    ecode5 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Dataset__WriteRaster" "', argument " "5"" of type '" "int""'");
-    } 
-    arg5 = static_cast< int >(val5);
-    {
-      /* %typemap(in,numinputs=1) (int nLen, char *pBuf ) */
-      if (SvOK(ST(5))) {
-        if (!SvPOK(ST(5)))
-        SWIG_croak("Expected binary data.");
-        STRLEN len = SvCUR(ST(5));
-        arg7 = SvPV_nolen(ST(5));
-        arg6 = len;
-      } else {
-        arg7 = NULL;
-        arg6 = 0;
-      }
-    }
-    if (items > 6) {
-      {
-        /* %typemap(in) (int *optional_int) */
-        if ( !SvOK(ST(6)) ) {
-          arg8 = 0;
-        }
-        else {
-          val8 = SvIV(ST(6));
-          arg8 = (int *)&val8;
-        }
-      }
-    }
-    if (items > 7) {
-      {
-        /* %typemap(in) (int *optional_int) */
-        if ( !SvOK(ST(7)) ) {
-          arg9 = 0;
-        }
-        else {
-          val9 = SvIV(ST(7));
-          arg9 = (int *)&val9;
-        }
-      }
-    }
-    if (items > 8) {
-      {
-        /* %typemap(in) (int *optional_int) */
-        if ( !SvOK(ST(8)) ) {
-          arg10 = 0;
-        }
-        else {
-          val10 = SvIV(ST(8));
-          arg10 = (GDALDataType *)&val10;
-        }
-      }
-    }
-    if (items > 9) {
-      {
-        /* %typemap(in,numinputs=1) (int nList, int* pList) */
-        if (!(SvROK(ST(9)) && (SvTYPE(SvRV(ST(9)))==SVt_PVAV)))
-        SWIG_croak("Expected a reference to an array.");
-        AV *av = (AV*)(SvRV(ST(9)));
-        arg11 = av_len(av)+1;
-        arg12 = (int*)CPLMalloc(arg11*sizeof(int));
-        if (arg12) {
-          for( int i = 0; i<arg11; i++ ) {
-            SV **sv = av_fetch(av, i, 0);
-            arg12[i] =  SvIV(*sv);
-          }
-        } else
-        SWIG_fail;
-      }
-    }
-    if (items > 10) {
-      {
-        /* %typemap(in) (int *optional_int) */
-        if ( !SvOK(ST(10)) ) {
-          arg13 = 0;
-        }
-        else {
-          val13 = SvIV(ST(10));
-          arg13 = (int *)&val13;
-        }
-      }
-    }
-    if (items > 11) {
-      {
-        /* %typemap(in) (int *optional_int) */
-        if ( !SvOK(ST(11)) ) {
-          arg14 = 0;
-        }
-        else {
-          val14 = SvIV(ST(11));
-          arg14 = (int *)&val14;
-        }
-      }
-    }
-    if (items > 12) {
-      {
-        /* %typemap(in) (int *optional_int) */
-        if ( !SvOK(ST(12)) ) {
-          arg15 = 0;
-        }
-        else {
-          val15 = SvIV(ST(12));
-          arg15 = (int *)&val15;
-        }
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALDatasetShadow_WriteRaster(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12,arg13,arg14,arg15);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) CPLErr */
-    }
-    
-    
-    
-    
-    
-    
-    
-    
-    {
-      /* %typemap(freearg) (int nList, int* pList) */
-      CPLFree((void*) arg12);
-    }
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    
-    
-    
-    {
-      /* %typemap(freearg) (int nList, int* pList) */
-      CPLFree((void*) arg12);
-    }
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Dataset__ReadRaster) {
-  {
-    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-    int arg2 ;
-    int arg3 ;
-    int arg4 ;
-    int arg5 ;
-    int *arg6 = (int *) 0 ;
-    char **arg7 = (char **) 0 ;
-    int *arg8 = (int *) 0 ;
-    int *arg9 = (int *) 0 ;
-    GDALDataType *arg10 = (GDALDataType *) 0 ;
-    int arg11 = (int) 0 ;
-    int *arg12 = (int *) 0 ;
-    int *arg13 = (int *) 0 ;
-    int *arg14 = (int *) 0 ;
-    int *arg15 = (int *) 0 ;
-    GDALRIOResampleAlg arg16 = (GDALRIOResampleAlg) GRIORA_NearestNeighbour ;
-    GDALProgressFunc arg17 = (GDALProgressFunc) NULL ;
-    void *arg18 = (void *) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int val4 ;
-    int ecode4 = 0 ;
-    int val5 ;
-    int ecode5 = 0 ;
-    int nLen6 = 0 ;
-    char *pBuf6 = 0 ;
-    int val8 ;
-    int val9 ;
-    int val10 ;
-    int val13 ;
-    int val14 ;
-    int val15 ;
-    int val16 ;
-    int ecode16 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg18 = (void *)(&saved_env);
-    {
-      /* %typemap(in,numinputs=0) (int *nLen6, char **pBuf6 ) */
-      arg6 = &nLen6;
-      arg7 = &pBuf6;
-    }
-    if ((items < 5) || (items > 15)) {
-      SWIG_croak("Usage: Dataset__ReadRaster(self,xoff,yoff,xsize,ysize,buf,buf_xsize,buf_ysize,buf_type,band_list,pband_list,buf_pixel_space,buf_line_space,buf_band_space,resample_alg,callback,callback_data);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset__ReadRaster" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Dataset__ReadRaster" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Dataset__ReadRaster" "', argument " "3"" of type '" "int""'");
-    } 
-    arg3 = static_cast< int >(val3);
-    ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Dataset__ReadRaster" "', argument " "4"" of type '" "int""'");
-    } 
-    arg4 = static_cast< int >(val4);
-    ecode5 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Dataset__ReadRaster" "', argument " "5"" of type '" "int""'");
-    } 
-    arg5 = static_cast< int >(val5);
-    if (items > 5) {
-      {
-        /* %typemap(in) (int *optional_int) */
-        if ( !SvOK(ST(5)) ) {
-          arg8 = 0;
-        }
-        else {
-          val8 = SvIV(ST(5));
-          arg8 = (int *)&val8;
-        }
-      }
-    }
-    if (items > 6) {
-      {
-        /* %typemap(in) (int *optional_int) */
-        if ( !SvOK(ST(6)) ) {
-          arg9 = 0;
-        }
-        else {
-          val9 = SvIV(ST(6));
-          arg9 = (int *)&val9;
-        }
-      }
-    }
-    if (items > 7) {
-      {
-        /* %typemap(in) (int *optional_int) */
-        if ( !SvOK(ST(7)) ) {
-          arg10 = 0;
-        }
-        else {
-          val10 = SvIV(ST(7));
-          arg10 = (GDALDataType *)&val10;
-        }
-      }
-    }
-    if (items > 8) {
-      {
-        /* %typemap(in,numinputs=1) (int nList, int* pList) */
-        if (!(SvROK(ST(8)) && (SvTYPE(SvRV(ST(8)))==SVt_PVAV)))
-        SWIG_croak("Expected a reference to an array.");
-        AV *av = (AV*)(SvRV(ST(8)));
-        arg11 = av_len(av)+1;
-        arg12 = (int*)CPLMalloc(arg11*sizeof(int));
-        if (arg12) {
-          for( int i = 0; i<arg11; i++ ) {
-            SV **sv = av_fetch(av, i, 0);
-            arg12[i] =  SvIV(*sv);
-          }
-        } else
-        SWIG_fail;
-      }
-    }
-    if (items > 9) {
-      {
-        /* %typemap(in) (int *optional_int) */
-        if ( !SvOK(ST(9)) ) {
-          arg13 = 0;
-        }
-        else {
-          val13 = SvIV(ST(9));
-          arg13 = (int *)&val13;
-        }
-      }
-    }
-    if (items > 10) {
-      {
-        /* %typemap(in) (int *optional_int) */
-        if ( !SvOK(ST(10)) ) {
-          arg14 = 0;
-        }
-        else {
-          val14 = SvIV(ST(10));
-          arg14 = (int *)&val14;
-        }
-      }
-    }
-    if (items > 11) {
-      {
-        /* %typemap(in) (int *optional_int) */
-        if ( !SvOK(ST(11)) ) {
-          arg15 = 0;
-        }
-        else {
-          val15 = SvIV(ST(11));
-          arg15 = (int *)&val15;
-        }
-      }
-    }
-    if (items > 12) {
-      ecode16 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(12), &val16);
-      if (!SWIG_IsOK(ecode16)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode16), "in method '" "Dataset__ReadRaster" "', argument " "16"" of type '" "GDALRIOResampleAlg""'");
-      } 
-      arg16 = static_cast< GDALRIOResampleAlg >(val16);
-    }
-    if (items > 13) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(13))) {
-          if (SvROK(ST(13))) {
-            if (SvTYPE(SvRV(ST(13))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(13);
-              arg17 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 14) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(14)))
-        saved_env.data = (SV *)ST(14);
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALDatasetShadow_ReadRaster(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12,arg13,arg14,arg15,arg16,arg17,arg18);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) CPLErr */
-    }
-    {
-      /* %typemap(argout) (int *nLen, char **pBuf ) */
-      ST(argvi) = sv_2mortal(newSVpv( *arg7, *arg6 ));
-      argvi++;
-    }
-    
-    
-    
-    
-    
-    {
-      /* %typemap(freearg) (int *nLen, char **pBuf ) */
-      if( *arg6 ) {
-        free( *arg7 );
-      }
-    }
-    
-    
-    
-    {
-      /* %typemap(freearg) (int nList, int* pList) */
-      CPLFree((void*) arg12);
-    }
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    {
-      /* %typemap(freearg) (int *nLen, char **pBuf ) */
-      if( *arg6 ) {
-        free( *arg7 );
-      }
-    }
-    
-    
-    
-    {
-      /* %typemap(freearg) (int nList, int* pList) */
-      CPLFree((void*) arg12);
-    }
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Dataset_StartTransaction) {
-  {
-    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-    int arg2 = (int) FALSE ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: Dataset_StartTransaction(self,force);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset_StartTransaction" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Dataset_StartTransaction" "', argument " "2"" of type '" "int""'");
-      } 
-      arg2 = static_cast< int >(val2);
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)GDALDatasetShadow_StartTransaction(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Dataset_CommitTransaction) {
-  {
-    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Dataset_CommitTransaction(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset_CommitTransaction" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRErr)GDALDatasetShadow_CommitTransaction(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Dataset_RollbackTransaction) {
-  {
-    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Dataset_RollbackTransaction(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset_RollbackTransaction" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRErr)GDALDatasetShadow_RollbackTransaction(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_XSize_get) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Band_XSize_get(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_XSize_get" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)GDALRasterBandShadow_XSize_get(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_YSize_get) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Band_YSize_get(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_YSize_get" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)GDALRasterBandShadow_YSize_get(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_DataType_get) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    GDALDataType result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Band_DataType_get(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_DataType_get" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (GDALDataType)GDALRasterBandShadow_DataType_get(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_GetDataset) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    GDALDatasetShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Band_GetDataset(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_GetDataset" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (GDALDatasetShadow *)GDALRasterBandShadow_GetDataset(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_GetBand) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Band_GetBand(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_GetBand" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)GDALRasterBandShadow_GetBand(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_GetBlockSize) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    int *arg2 = (int *) 0 ;
-    int *arg3 = (int *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int temp2 ;
-    int res2 = SWIG_TMPOBJ ;
-    int temp3 ;
-    int res3 = SWIG_TMPOBJ ;
-    int argvi = 0;
-    dXSARGS;
-    
-    arg2 = &temp2;
-    arg3 = &temp3;
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Band_GetBlockSize(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_GetBlockSize" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    {
-      CPLErrorReset();
-      GDALRasterBandShadow_GetBlockSize(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    if (SWIG_IsTmpObj(res2)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg2)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res2) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg2), SWIGTYPE_p_int, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res3)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg3)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_int, new_flags); argvi++  ;
-    }
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_GetColorInterpretation) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    GDALColorInterp result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Band_GetColorInterpretation(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_GetColorInterpretation" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (GDALColorInterp)GDALRasterBandShadow_GetColorInterpretation(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_GetRasterColorInterpretation) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    GDALColorInterp result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Band_GetRasterColorInterpretation(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_GetRasterColorInterpretation" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (GDALColorInterp)GDALRasterBandShadow_GetRasterColorInterpretation(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_SetColorInterpretation) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    GDALColorInterp arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Band_SetColorInterpretation(self,val);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_SetColorInterpretation" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Band_SetColorInterpretation" "', argument " "2"" of type '" "GDALColorInterp""'");
-    } 
-    arg2 = static_cast< GDALColorInterp >(val2);
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALRasterBandShadow_SetColorInterpretation(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) CPLErr */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_SetRasterColorInterpretation) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    GDALColorInterp arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Band_SetRasterColorInterpretation(self,val);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_SetRasterColorInterpretation" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Band_SetRasterColorInterpretation" "', argument " "2"" of type '" "GDALColorInterp""'");
-    } 
-    arg2 = static_cast< GDALColorInterp >(val2);
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALRasterBandShadow_SetRasterColorInterpretation(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) CPLErr */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_GetNoDataValue) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    double *arg2 = (double *) 0 ;
-    int *arg3 = (int *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double tmpval2 ;
-    int tmphasval2 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (double *val, int *hasval) */
-      arg2 = &tmpval2;
-      arg3 = &tmphasval2;
-    }
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Band_GetNoDataValue(self,hasval);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_GetNoDataValue" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    {
-      CPLErrorReset();
-      GDALRasterBandShadow_GetNoDataValue(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    {
-      /* %typemap(argout) (double *val, int *hasval) */
-      if (GIMME_V == G_ARRAY) {
-        ST(argvi) = sv_newmortal();
-        sv_setnv(ST(argvi), *arg2);
-        argvi++;
-        ST(argvi) = sv_newmortal();
-        sv_setiv(ST(argvi), *arg3);
-        argvi++;
-      } else {
-        if ( *arg3 ) {
-          ST(argvi) = sv_newmortal();
-          sv_setnv(ST(argvi), *arg2);
-          argvi++;
-        }
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_SetNoDataValue) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    double arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Band_SetNoDataValue(self,d);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_SetNoDataValue" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Band_SetNoDataValue" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALRasterBandShadow_SetNoDataValue(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) CPLErr */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_GetUnitType) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Band_GetUnitType(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_GetUnitType" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char *)GDALRasterBandShadow_GetUnitType(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_SetUnitType) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Band_SetUnitType(self,val);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_SetUnitType" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Band_SetUnitType" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALRasterBandShadow_SetUnitType(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) CPLErr */
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_GetRasterCategoryNames) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char **result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Band_GetRasterCategoryNames(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_GetRasterCategoryNames" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char **)GDALRasterBandShadow_GetRasterCategoryNames(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) char **options -> ( string ) */
-      AV* av = (AV*)sv_2mortal((SV*)newAV());
-      char **stringarray = result;
-      if ( stringarray != NULL ) {
-        int n = CSLCount( stringarray );
-        for ( int i = 0; i < n; i++ ) {
-          SV *sv = newSVpv(stringarray[i], 0);
-          SvUTF8_on(sv); /* expecting UTF-8 from GDAL */
-          if (!av_store(av, i, sv))
-          SvREFCNT_dec(sv);
-        }
-      }
-      ST(argvi) = newRV((SV*)av);
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_SetRasterCategoryNames) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    char **arg2 = (char **) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Band_SetRasterCategoryNames(self,names);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_SetRasterCategoryNames" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    {
-      /* %typemap(in) char **options */
-      if (SvOK(ST(1))) {
-        if (SvROK(ST(1))) {
-          if (SvTYPE(SvRV(ST(1)))==SVt_PVAV) {
-            AV *av = (AV*)(SvRV(ST(1)));
-            for (int i = 0; i < av_len(av)+1; i++) {
-              SV *sv = *(av_fetch(av, i, 0));
-              sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-              char *pszItem = SvPV_nolen(sv);
-              arg2 = CSLAddString( arg2, pszItem );
-            }
-          } else if (SvTYPE(SvRV(ST(1)))==SVt_PVHV) {
-            HV *hv = (HV*)SvRV(ST(1));
-            SV *sv;
-            char *key;
-            I32 klen;
-            arg2 = NULL;
-            hv_iterinit(hv);
-            while(sv = hv_iternextsv(hv,&key,&klen)) {
-              sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-              arg2 = CSLAddNameValue( arg2, key, SvPV_nolen(sv) );
-            }
-          } else
-          SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-        } else
-        SWIG_croak("The 'options' argument is not a reference.");   
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALRasterBandShadow_SetRasterCategoryNames(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) CPLErr */
-    }
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg2) CSLDestroy( arg2 );
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg2) CSLDestroy( arg2 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_GetMinimum) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    double *arg2 = (double *) 0 ;
-    int *arg3 = (int *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double tmpval2 ;
-    int tmphasval2 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (double *val, int *hasval) */
-      arg2 = &tmpval2;
-      arg3 = &tmphasval2;
-    }
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Band_GetMinimum(self,hasval);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_GetMinimum" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    {
-      CPLErrorReset();
-      GDALRasterBandShadow_GetMinimum(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    {
-      /* %typemap(argout) (double *val, int *hasval) */
-      if (GIMME_V == G_ARRAY) {
-        ST(argvi) = sv_newmortal();
-        sv_setnv(ST(argvi), *arg2);
-        argvi++;
-        ST(argvi) = sv_newmortal();
-        sv_setiv(ST(argvi), *arg3);
-        argvi++;
-      } else {
-        if ( *arg3 ) {
-          ST(argvi) = sv_newmortal();
-          sv_setnv(ST(argvi), *arg2);
-          argvi++;
-        }
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_GetMaximum) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    double *arg2 = (double *) 0 ;
-    int *arg3 = (int *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double tmpval2 ;
-    int tmphasval2 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (double *val, int *hasval) */
-      arg2 = &tmpval2;
-      arg3 = &tmphasval2;
-    }
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Band_GetMaximum(self,hasval);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_GetMaximum" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    {
-      CPLErrorReset();
-      GDALRasterBandShadow_GetMaximum(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    {
-      /* %typemap(argout) (double *val, int *hasval) */
-      if (GIMME_V == G_ARRAY) {
-        ST(argvi) = sv_newmortal();
-        sv_setnv(ST(argvi), *arg2);
-        argvi++;
-        ST(argvi) = sv_newmortal();
-        sv_setiv(ST(argvi), *arg3);
-        argvi++;
-      } else {
-        if ( *arg3 ) {
-          ST(argvi) = sv_newmortal();
-          sv_setnv(ST(argvi), *arg2);
-          argvi++;
-        }
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_GetOffset) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    double *arg2 = (double *) 0 ;
-    int *arg3 = (int *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double tmpval2 ;
-    int tmphasval2 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (double *val, int *hasval) */
-      arg2 = &tmpval2;
-      arg3 = &tmphasval2;
-    }
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Band_GetOffset(self,hasval);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_GetOffset" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    {
-      CPLErrorReset();
-      GDALRasterBandShadow_GetOffset(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    {
-      /* %typemap(argout) (double *val, int *hasval) */
-      if (GIMME_V == G_ARRAY) {
-        ST(argvi) = sv_newmortal();
-        sv_setnv(ST(argvi), *arg2);
-        argvi++;
-        ST(argvi) = sv_newmortal();
-        sv_setiv(ST(argvi), *arg3);
-        argvi++;
-      } else {
-        if ( *arg3 ) {
-          ST(argvi) = sv_newmortal();
-          sv_setnv(ST(argvi), *arg2);
-          argvi++;
-        }
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_GetScale) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    double *arg2 = (double *) 0 ;
-    int *arg3 = (int *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double tmpval2 ;
-    int tmphasval2 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (double *val, int *hasval) */
-      arg2 = &tmpval2;
-      arg3 = &tmphasval2;
-    }
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Band_GetScale(self,hasval);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_GetScale" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    {
-      CPLErrorReset();
-      GDALRasterBandShadow_GetScale(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    {
-      /* %typemap(argout) (double *val, int *hasval) */
-      if (GIMME_V == G_ARRAY) {
-        ST(argvi) = sv_newmortal();
-        sv_setnv(ST(argvi), *arg2);
-        argvi++;
-        ST(argvi) = sv_newmortal();
-        sv_setiv(ST(argvi), *arg3);
-        argvi++;
-      } else {
-        if ( *arg3 ) {
-          ST(argvi) = sv_newmortal();
-          sv_setnv(ST(argvi), *arg2);
-          argvi++;
-        }
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_SetOffset) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    double arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Band_SetOffset(self,val);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_SetOffset" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Band_SetOffset" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALRasterBandShadow_SetOffset(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) CPLErr */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_SetScale) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    double arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Band_SetScale(self,val);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_SetScale" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Band_SetScale" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALRasterBandShadow_SetScale(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) CPLErr */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_GetStatistics) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    int arg2 ;
-    int arg3 ;
-    double *arg4 = (double *) 0 ;
-    double *arg5 = (double *) 0 ;
-    double *arg6 = (double *) 0 ;
-    double *arg7 = (double *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    double temp4 ;
-    int res4 = SWIG_TMPOBJ ;
-    double temp5 ;
-    int res5 = SWIG_TMPOBJ ;
-    double temp6 ;
-    int res6 = SWIG_TMPOBJ ;
-    double temp7 ;
-    int res7 = SWIG_TMPOBJ ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    arg4 = &temp4;
-    arg5 = &temp5;
-    arg6 = &temp6;
-    arg7 = &temp7;
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Band_GetStatistics(self,approx_ok,force);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_GetStatistics" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Band_GetStatistics" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Band_GetStatistics" "', argument " "3"" of type '" "int""'");
-    } 
-    arg3 = static_cast< int >(val3);
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALRasterBandShadow_GetStatistics(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) IF_ERROR_RETURN_NONE */
-    }
-    if (SWIG_IsTmpObj(res4)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1((*arg4)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_double, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res5)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1((*arg5)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res5) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg5), SWIGTYPE_p_double, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res6)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1((*arg6)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res6) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg6), SWIGTYPE_p_double, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res7)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1((*arg7)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res7) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg7), SWIGTYPE_p_double, new_flags); argvi++  ;
-    }
-    
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_ComputeStatistics) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    bool arg2 ;
-    double *arg3 = (double *) NULL ;
-    double *arg4 = (double *) NULL ;
-    double *arg5 = (double *) NULL ;
-    double *arg6 = (double *) NULL ;
-    GDALProgressFunc arg7 = (GDALProgressFunc) NULL ;
-    void *arg8 = (void *) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    bool val2 ;
-    int ecode2 = 0 ;
-    double temp3 ;
-    int res3 = SWIG_TMPOBJ ;
-    double temp4 ;
-    int res4 = SWIG_TMPOBJ ;
-    double temp5 ;
-    int res5 = SWIG_TMPOBJ ;
-    double temp6 ;
-    int res6 = SWIG_TMPOBJ ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg8 = (void *)(&saved_env);
-    arg3 = &temp3;
-    arg4 = &temp4;
-    arg5 = &temp5;
-    arg6 = &temp6;
-    if ((items < 2) || (items > 4)) {
-      SWIG_croak("Usage: Band_ComputeStatistics(self,approx_ok,callback,callback_data);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_ComputeStatistics" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    ecode2 = SWIG_AsVal_bool SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Band_ComputeStatistics" "', argument " "2"" of type '" "bool""'");
-    } 
-    arg2 = static_cast< bool >(val2);
-    if (items > 2) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(2))) {
-          if (SvROK(ST(2))) {
-            if (SvTYPE(SvRV(ST(2))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(2);
-              arg7 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 3) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(3)))
-        saved_env.data = (SV *)ST(3);
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALRasterBandShadow_ComputeStatistics(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) IF_ERROR_RETURN_NONE */
-    }
-    if (SWIG_IsTmpObj(res3)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1((*arg3)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_double, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res4)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1((*arg4)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_double, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res5)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1((*arg5)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res5) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg5), SWIGTYPE_p_double, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res6)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1((*arg6)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res6) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg6), SWIGTYPE_p_double, new_flags); argvi++  ;
-    }
-    
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_SetStatistics) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 5) || (items > 5)) {
-      SWIG_croak("Usage: Band_SetStatistics(self,min,max,mean,stddev);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_SetStatistics" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Band_SetStatistics" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Band_SetStatistics" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Band_SetStatistics" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Band_SetStatistics" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALRasterBandShadow_SetStatistics(arg1,arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_GetOverviewCount) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Band_GetOverviewCount(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_GetOverviewCount" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)GDALRasterBandShadow_GetOverviewCount(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_GetOverview) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    GDALRasterBandShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Band_GetOverview(self,i);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_GetOverview" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Band_GetOverview" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (GDALRasterBandShadow *)GDALRasterBandShadow_GetOverview(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALRasterBandShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_Checksum) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    int arg2 = (int) 0 ;
-    int arg3 = (int) 0 ;
-    int *arg4 = (int *) 0 ;
-    int *arg5 = (int *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int val4 ;
-    int val5 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 5)) {
-      SWIG_croak("Usage: Band_Checksum(self,xoff,yoff,xsize,ysize);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_Checksum" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Band_Checksum" "', argument " "2"" of type '" "int""'");
-      } 
-      arg2 = static_cast< int >(val2);
-    }
-    if (items > 2) {
-      ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-      if (!SWIG_IsOK(ecode3)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Band_Checksum" "', argument " "3"" of type '" "int""'");
-      } 
-      arg3 = static_cast< int >(val3);
-    }
-    if (items > 3) {
-      {
-        /* %typemap(in) (int *optional_int) */
-        if ( !SvOK(ST(3)) ) {
-          arg4 = 0;
-        }
-        else {
-          val4 = SvIV(ST(3));
-          arg4 = (int *)&val4;
-        }
-      }
-    }
-    if (items > 4) {
-      {
-        /* %typemap(in) (int *optional_int) */
-        if ( !SvOK(ST(4)) ) {
-          arg5 = 0;
-        }
-        else {
-          val5 = SvIV(ST(4));
-          arg5 = (int *)&val5;
-        }
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (int)GDALRasterBandShadow_Checksum(arg1,arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_ComputeRasterMinMax) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    double *arg2 ;
-    int arg3 = (int) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double argout2[2] ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (double argout2[ANY]) */
-      arg2 = argout2;
-    }
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: Band_ComputeRasterMinMax(self,approx_ok);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_ComputeRasterMinMax" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    if (items > 1) {
-      ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val3);
-      if (!SWIG_IsOK(ecode3)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Band_ComputeRasterMinMax" "', argument " "3"" of type '" "int""'");
-      } 
-      arg3 = static_cast< int >(val3);
-    }
-    {
-      CPLErrorReset();
-      GDALRasterBandShadow_ComputeRasterMinMax(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    {
-      /* %typemap(argout) (double argout[ANY]) */
-      if (GIMME_V == G_ARRAY) {
-        /* return a list */
-        int i;
-        EXTEND(SP, argvi+2-items+1);
-        for (i = 0; i < 2; i++)
-        ST(argvi++) = sv_2mortal(newSVnv(arg2[i]));
-      } else {
-        ST(argvi) = CreateArrayFromDoubleArray( arg2, 2 );
-        argvi++;
-      }  
-    }
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_ComputeBandStats) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    double *arg2 ;
-    int arg3 = (int) 1 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double argout2[2] ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (double argout2[ANY]) */
-      arg2 = argout2;
-    }
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: Band_ComputeBandStats(self,samplestep);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_ComputeBandStats" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    if (items > 1) {
-      ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val3);
-      if (!SWIG_IsOK(ecode3)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Band_ComputeBandStats" "', argument " "3"" of type '" "int""'");
-      } 
-      arg3 = static_cast< int >(val3);
-    }
-    {
-      CPLErrorReset();
-      GDALRasterBandShadow_ComputeBandStats(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    {
-      /* %typemap(argout) (double argout[ANY]) */
-      if (GIMME_V == G_ARRAY) {
-        /* return a list */
-        int i;
-        EXTEND(SP, argvi+2-items+1);
-        for (i = 0; i < 2; i++)
-        ST(argvi++) = sv_2mortal(newSVnv(arg2[i]));
-      } else {
-        ST(argvi) = CreateArrayFromDoubleArray( arg2, 2 );
-        argvi++;
-      }  
-    }
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_Fill) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    double arg2 ;
-    double arg3 = (double) 0.0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 3)) {
-      SWIG_croak("Usage: Band_Fill(self,real_fill,imag_fill);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_Fill" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Band_Fill" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    if (items > 2) {
-      ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-      if (!SWIG_IsOK(ecode3)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Band_Fill" "', argument " "3"" of type '" "double""'");
-      } 
-      arg3 = static_cast< double >(val3);
-    }
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALRasterBandShadow_Fill(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band__ReadRaster) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    int arg2 ;
-    int arg3 ;
-    int arg4 ;
-    int arg5 ;
-    int *arg6 = (int *) 0 ;
-    char **arg7 = (char **) 0 ;
-    int *arg8 = (int *) 0 ;
-    int *arg9 = (int *) 0 ;
-    int *arg10 = (int *) 0 ;
-    int *arg11 = (int *) 0 ;
-    int *arg12 = (int *) 0 ;
-    GDALRIOResampleAlg arg13 = (GDALRIOResampleAlg) GRIORA_NearestNeighbour ;
-    GDALProgressFunc arg14 = (GDALProgressFunc) NULL ;
-    void *arg15 = (void *) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int val4 ;
-    int ecode4 = 0 ;
-    int val5 ;
-    int ecode5 = 0 ;
-    int nLen6 = 0 ;
-    char *pBuf6 = 0 ;
-    int val8 ;
-    int val9 ;
-    int val10 ;
-    int val11 ;
-    int val12 ;
-    int val13 ;
-    int ecode13 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg15 = (void *)(&saved_env);
-    {
-      /* %typemap(in,numinputs=0) (int *nLen6, char **pBuf6 ) */
-      arg6 = &nLen6;
-      arg7 = &pBuf6;
-    }
-    if ((items < 5) || (items > 13)) {
-      SWIG_croak("Usage: Band__ReadRaster(self,xoff,yoff,xsize,ysize,buf,buf_xsize,buf_ysize,buf_type,buf_pixel_space,buf_line_space,resample_alg,callback,callback_data);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band__ReadRaster" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Band__ReadRaster" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Band__ReadRaster" "', argument " "3"" of type '" "int""'");
-    } 
-    arg3 = static_cast< int >(val3);
-    ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Band__ReadRaster" "', argument " "4"" of type '" "int""'");
-    } 
-    arg4 = static_cast< int >(val4);
-    ecode5 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Band__ReadRaster" "', argument " "5"" of type '" "int""'");
-    } 
-    arg5 = static_cast< int >(val5);
-    if (items > 5) {
-      {
-        /* %typemap(in) (int *optional_int) */
-        if ( !SvOK(ST(5)) ) {
-          arg8 = 0;
-        }
-        else {
-          val8 = SvIV(ST(5));
-          arg8 = (int *)&val8;
-        }
-      }
-    }
-    if (items > 6) {
-      {
-        /* %typemap(in) (int *optional_int) */
-        if ( !SvOK(ST(6)) ) {
-          arg9 = 0;
-        }
-        else {
-          val9 = SvIV(ST(6));
-          arg9 = (int *)&val9;
-        }
-      }
-    }
-    if (items > 7) {
-      {
-        /* %typemap(in) (int *optional_int) */
-        if ( !SvOK(ST(7)) ) {
-          arg10 = 0;
-        }
-        else {
-          val10 = SvIV(ST(7));
-          arg10 = (int *)&val10;
-        }
-      }
-    }
-    if (items > 8) {
-      {
-        /* %typemap(in) (int *optional_int) */
-        if ( !SvOK(ST(8)) ) {
-          arg11 = 0;
-        }
-        else {
-          val11 = SvIV(ST(8));
-          arg11 = (int *)&val11;
-        }
-      }
-    }
-    if (items > 9) {
-      {
-        /* %typemap(in) (int *optional_int) */
-        if ( !SvOK(ST(9)) ) {
-          arg12 = 0;
-        }
-        else {
-          val12 = SvIV(ST(9));
-          arg12 = (int *)&val12;
-        }
-      }
-    }
-    if (items > 10) {
-      ecode13 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(10), &val13);
-      if (!SWIG_IsOK(ecode13)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode13), "in method '" "Band__ReadRaster" "', argument " "13"" of type '" "GDALRIOResampleAlg""'");
-      } 
-      arg13 = static_cast< GDALRIOResampleAlg >(val13);
-    }
-    if (items > 11) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(11))) {
-          if (SvROK(ST(11))) {
-            if (SvTYPE(SvRV(ST(11))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(11);
-              arg14 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 12) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(12)))
-        saved_env.data = (SV *)ST(12);
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALRasterBandShadow_ReadRaster(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12,arg13,arg14,arg15);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    {
-      /* %typemap(argout) (int *nLen, char **pBuf ) */
-      ST(argvi) = sv_2mortal(newSVpv( *arg7, *arg6 ));
-      argvi++;
-    }
-    
-    
-    
-    
-    
-    {
-      /* %typemap(freearg) (int *nLen, char **pBuf ) */
-      if( *arg6 ) {
-        free( *arg7 );
-      }
-    }
-    
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    {
-      /* %typemap(freearg) (int *nLen, char **pBuf ) */
-      if( *arg6 ) {
-        free( *arg7 );
-      }
-    }
-    
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band__WriteRaster) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    int arg2 ;
-    int arg3 ;
-    int arg4 ;
-    int arg5 ;
-    int arg6 ;
-    char *arg7 = (char *) 0 ;
-    int *arg8 = (int *) 0 ;
-    int *arg9 = (int *) 0 ;
-    int *arg10 = (int *) 0 ;
-    int *arg11 = (int *) 0 ;
-    int *arg12 = (int *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int val4 ;
-    int ecode4 = 0 ;
-    int val5 ;
-    int ecode5 = 0 ;
-    int val8 ;
-    int val9 ;
-    int val10 ;
-    int val11 ;
-    int val12 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 6) || (items > 11)) {
-      SWIG_croak("Usage: Band__WriteRaster(self,xoff,yoff,xsize,ysize,buf_len,buf_string,buf_xsize,buf_ysize,buf_type,buf_pixel_space,buf_line_space);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band__WriteRaster" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Band__WriteRaster" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Band__WriteRaster" "', argument " "3"" of type '" "int""'");
-    } 
-    arg3 = static_cast< int >(val3);
-    ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Band__WriteRaster" "', argument " "4"" of type '" "int""'");
-    } 
-    arg4 = static_cast< int >(val4);
-    ecode5 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Band__WriteRaster" "', argument " "5"" of type '" "int""'");
-    } 
-    arg5 = static_cast< int >(val5);
-    {
-      /* %typemap(in,numinputs=1) (int nLen, char *pBuf ) */
-      if (SvOK(ST(5))) {
-        if (!SvPOK(ST(5)))
-        SWIG_croak("Expected binary data.");
-        STRLEN len = SvCUR(ST(5));
-        arg7 = SvPV_nolen(ST(5));
-        arg6 = len;
-      } else {
-        arg7 = NULL;
-        arg6 = 0;
-      }
-    }
-    if (items > 6) {
-      {
-        /* %typemap(in) (int *optional_int) */
-        if ( !SvOK(ST(6)) ) {
-          arg8 = 0;
-        }
-        else {
-          val8 = SvIV(ST(6));
-          arg8 = (int *)&val8;
-        }
-      }
-    }
-    if (items > 7) {
-      {
-        /* %typemap(in) (int *optional_int) */
-        if ( !SvOK(ST(7)) ) {
-          arg9 = 0;
-        }
-        else {
-          val9 = SvIV(ST(7));
-          arg9 = (int *)&val9;
-        }
-      }
-    }
-    if (items > 8) {
-      {
-        /* %typemap(in) (int *optional_int) */
-        if ( !SvOK(ST(8)) ) {
-          arg10 = 0;
-        }
-        else {
-          val10 = SvIV(ST(8));
-          arg10 = (int *)&val10;
-        }
-      }
-    }
-    if (items > 9) {
-      {
-        /* %typemap(in) (int *optional_int) */
-        if ( !SvOK(ST(9)) ) {
-          arg11 = 0;
-        }
-        else {
-          val11 = SvIV(ST(9));
-          arg11 = (int *)&val11;
-        }
-      }
-    }
-    if (items > 10) {
-      {
-        /* %typemap(in) (int *optional_int) */
-        if ( !SvOK(ST(10)) ) {
-          arg12 = 0;
-        }
-        else {
-          val12 = SvIV(ST(10));
-          arg12 = (int *)&val12;
-        }
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALRasterBandShadow_WriteRaster(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_FlushCache) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Band_FlushCache(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_FlushCache" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    {
-      CPLErrorReset();
-      GDALRasterBandShadow_FlushCache(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_GetRasterColorTable) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    GDALColorTableShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Band_GetRasterColorTable(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_GetRasterColorTable" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (GDALColorTableShadow *)GDALRasterBandShadow_GetRasterColorTable(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALColorTableShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_GetColorTable) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    GDALColorTableShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Band_GetColorTable(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_GetColorTable" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (GDALColorTableShadow *)GDALRasterBandShadow_GetColorTable(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALColorTableShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_SetRasterColorTable) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    GDALColorTableShadow *arg2 = (GDALColorTableShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Band_SetRasterColorTable(self,arg);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_SetRasterColorTable" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_GDALColorTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Band_SetRasterColorTable" "', argument " "2"" of type '" "GDALColorTableShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< GDALColorTableShadow * >(argp2);
-    {
-      CPLErrorReset();
-      result = (int)GDALRasterBandShadow_SetRasterColorTable(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_SetColorTable) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    GDALColorTableShadow *arg2 = (GDALColorTableShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Band_SetColorTable(self,arg);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_SetColorTable" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_GDALColorTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Band_SetColorTable" "', argument " "2"" of type '" "GDALColorTableShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< GDALColorTableShadow * >(argp2);
-    {
-      CPLErrorReset();
-      result = (int)GDALRasterBandShadow_SetColorTable(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_GetDefaultRAT) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    GDALRasterAttributeTableShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Band_GetDefaultRAT(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_GetDefaultRAT" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (GDALRasterAttributeTableShadow *)GDALRasterBandShadow_GetDefaultRAT(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALRasterAttributeTableShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_SetDefaultRAT) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    GDALRasterAttributeTableShadow *arg2 = (GDALRasterAttributeTableShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Band_SetDefaultRAT(self,table);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_SetDefaultRAT" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_GDALRasterAttributeTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Band_SetDefaultRAT" "', argument " "2"" of type '" "GDALRasterAttributeTableShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< GDALRasterAttributeTableShadow * >(argp2);
-    {
-      CPLErrorReset();
-      result = (int)GDALRasterBandShadow_SetDefaultRAT(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_GetMaskBand) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    GDALRasterBandShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Band_GetMaskBand(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_GetMaskBand" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (GDALRasterBandShadow *)GDALRasterBandShadow_GetMaskBand(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALRasterBandShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band__GetMaskFlags) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Band__GetMaskFlags(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band__GetMaskFlags" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)GDALRasterBandShadow_GetMaskFlags(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band__CreateMaskBand) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Band__CreateMaskBand(self,nFlags);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band__CreateMaskBand" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Band__CreateMaskBand" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALRasterBandShadow_CreateMaskBand(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band__GetHistogram) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    double arg2 = (double) -0.5 ;
-    double arg3 = (double) 255.5 ;
-    int arg4 = (int) 256 ;
-    GUIntBig *arg5 = (GUIntBig *) NULL ;
-    int arg6 = (int) 0 ;
-    int arg7 = (int) 1 ;
-    GDALProgressFunc arg8 = (GDALProgressFunc) NULL ;
-    void *arg9 = (void *) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    int val6 ;
-    int ecode6 = 0 ;
-    int val7 ;
-    int ecode7 = 0 ;
-    int argvi = 0;
-    SV * _saved[1] ;
-    CPLErr result;
-    dXSARGS;
-    
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg9 = (void *)(&saved_env);
-    if ((items < 1) || (items > 8)) {
-      SWIG_croak("Usage: Band__GetHistogram(self,min,max,buckets,panHistogram,include_out_of_range,approx_ok,callback,callback_data);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band__GetHistogram" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Band__GetHistogram" "', argument " "2"" of type '" "double""'");
-      } 
-      arg2 = static_cast< double >(val2);
-    }
-    if (items > 2) {
-      ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-      if (!SWIG_IsOK(ecode3)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Band__GetHistogram" "', argument " "3"" of type '" "double""'");
-      } 
-      arg3 = static_cast< double >(val3);
-    }
-    if (items > 3) {
-      {
-        /* %typemap(in,numinputs=1) (int len, GUIntBig *output) */
-        arg4 = SvIV(ST(3));
-      }
-    }
-    if (items > 4) {
-      ecode6 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(4), &val6);
-      if (!SWIG_IsOK(ecode6)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "Band__GetHistogram" "', argument " "6"" of type '" "int""'");
-      } 
-      arg6 = static_cast< int >(val6);
-    }
-    if (items > 5) {
-      ecode7 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(5), &val7);
-      if (!SWIG_IsOK(ecode7)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "Band__GetHistogram" "', argument " "7"" of type '" "int""'");
-      } 
-      arg7 = static_cast< int >(val7);
-    }
-    if (items > 6) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(6))) {
-          if (SvROK(ST(6))) {
-            if (SvTYPE(SvRV(ST(6))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(6);
-              arg8 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 7) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(7)))
-        saved_env.data = (SV *)ST(7);
-      }
-    }
-    {
-      /* %typemap(check) (int len, GUIntBig *output) */
-      if (arg4 < 1) arg4 = 1; /* stop idiocy */
-      arg5 = (GUIntBig*)CPLMalloc( arg4 * sizeof(GUIntBig) );
-      
-    }
-    _saved[0] = ST(3);
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALRasterBandShadow_GetHistogram(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) IF_ERROR_RETURN_NONE */
-    }
-    {
-      /* %typemap(argout) (int len, GUIntBig *output) */
-      if (GIMME_V == G_ARRAY) {
-        /* return a list */
-        int i;
-        EXTEND(SP, argvi+arg4-items+1);
-        for (i = 0; i < arg4; i++) {
-          char s[LENGTH_OF_GUIntBig_AS_STRING];
-          snprintf(s, LENGTH_OF_GUIntBig_AS_STRING-1, CPL_FRMT_GUIB, arg5[i]);
-          ST(argvi++) = sv_2mortal(newSVpv(s, 0));
-        }
-      } else {
-        ST(argvi) = CreateArrayFromGUIntBigArray( arg5, arg4 );
-        argvi++;
-      }
-    }
-    
-    
-    
-    {
-      /* %typemap(freearg) (int len, GUIntBig *output) */
-      CPLFree(arg5);
-    }
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    {
-      /* %typemap(freearg) (int len, GUIntBig *output) */
-      CPLFree(arg5);
-    }
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_GetDefaultHistogram) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    double *arg2 = (double *) NULL ;
-    double *arg3 = (double *) NULL ;
-    int *arg4 = (int *) NULL ;
-    GUIntBig **arg5 = (GUIntBig **) NULL ;
-    int arg6 = (int) 1 ;
-    GDALProgressFunc arg7 = (GDALProgressFunc) NULL ;
-    void *arg8 = (void *) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double temp2 ;
-    int res2 = SWIG_TMPOBJ ;
-    double temp3 ;
-    int res3 = SWIG_TMPOBJ ;
-    int nLen4 ;
-    GUIntBig *pList4 ;
-    int val6 ;
-    int ecode6 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg8 = (void *)(&saved_env);
-    arg2 = &temp2;
-    arg3 = &temp3;
-    {
-      /* %typemap(in,numinputs=0) (int *nLen4, const GUIntBig **pList4) */
-      arg4 = &nLen4;
-      arg5 = &pList4;
-    }
-    if ((items < 1) || (items > 4)) {
-      SWIG_croak("Usage: Band_GetDefaultHistogram(self,ppanHistogram,force,callback,callback_data);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_GetDefaultHistogram" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    if (items > 1) {
-      ecode6 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val6);
-      if (!SWIG_IsOK(ecode6)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "Band_GetDefaultHistogram" "', argument " "6"" of type '" "int""'");
-      } 
-      arg6 = static_cast< int >(val6);
-    }
-    if (items > 2) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(2))) {
-          if (SvROK(ST(2))) {
-            if (SvTYPE(SvRV(ST(2))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(2);
-              arg7 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 3) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(3)))
-        saved_env.data = (SV *)ST(3);
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALRasterBandShadow_GetDefaultHistogram(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) IF_ERROR_RETURN_NONE */
-    }
-    if (SWIG_IsTmpObj(res2)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1((*arg2)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res2) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg2), SWIGTYPE_p_double, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res3)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1((*arg3)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_double, new_flags); argvi++  ;
-    }
-    {
-      /* %typemap(argout) (int *nLen, const GUIntBig **pList) */
-      ST(argvi) = CreateArrayFromGUIntBigArray( *(arg5), *(arg4) );
-      argvi++;
-    }
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_SetDefaultHistogram) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    int arg4 ;
-    GUIntBig *arg5 = (GUIntBig *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 4) || (items > 4)) {
-      SWIG_croak("Usage: Band_SetDefaultHistogram(self,min,max,buckets_in,panHistogram_in);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_SetDefaultHistogram" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Band_SetDefaultHistogram" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Band_SetDefaultHistogram" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    {
-      /* %typemap(in,numinputs=1) (int nList, GUIntBig* pList) */
-      if (!(SvROK(ST(3)) && (SvTYPE(SvRV(ST(3)))==SVt_PVAV)))
-      SWIG_croak("Expected a reference to an array.");
-      AV *av = (AV*)(SvRV(ST(3)));
-      arg4 = av_len(av)+1;
-      arg5 = (GUIntBig*)CPLMalloc(arg4*sizeof(GUIntBig));
-      if (arg5) {
-        for( int i = 0; i<arg4; i++ ) {
-          SV **sv = av_fetch(av, i, 0);
-          arg5[i] =  strtoull(SvPV_nolen(*sv), NULL, 10);
-        }
-      } else
-      SWIG_fail;
-    }
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALRasterBandShadow_SetDefaultHistogram(arg1,arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    
-    {
-      /* %typemap(freearg) (int nList, GUIntBig* pList) */
-      CPLFree((void*) arg5);
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    {
-      /* %typemap(freearg) (int nList, GUIntBig* pList) */
-      CPLFree((void*) arg5);
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_HasArbitraryOverviews) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    bool result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Band_HasArbitraryOverviews(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_HasArbitraryOverviews" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (bool)GDALRasterBandShadow_HasArbitraryOverviews(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_GetCategoryNames) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char **result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Band_GetCategoryNames(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_GetCategoryNames" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char **)GDALRasterBandShadow_GetCategoryNames(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) char **options -> ( string ) */
-      AV* av = (AV*)sv_2mortal((SV*)newAV());
-      char **stringarray = result;
-      if ( stringarray != NULL ) {
-        int n = CSLCount( stringarray );
-        for ( int i = 0; i < n; i++ ) {
-          SV *sv = newSVpv(stringarray[i], 0);
-          SvUTF8_on(sv); /* expecting UTF-8 from GDAL */
-          if (!av_store(av, i, sv))
-          SvREFCNT_dec(sv);
-        }
-      }
-      ST(argvi) = newRV((SV*)av);
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_SetCategoryNames) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    char **arg2 = (char **) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Band_SetCategoryNames(self,papszCategoryNames);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_SetCategoryNames" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    {
-      /* %typemap(in) char **options */
-      if (SvOK(ST(1))) {
-        if (SvROK(ST(1))) {
-          if (SvTYPE(SvRV(ST(1)))==SVt_PVAV) {
-            AV *av = (AV*)(SvRV(ST(1)));
-            for (int i = 0; i < av_len(av)+1; i++) {
-              SV *sv = *(av_fetch(av, i, 0));
-              sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-              char *pszItem = SvPV_nolen(sv);
-              arg2 = CSLAddString( arg2, pszItem );
-            }
-          } else if (SvTYPE(SvRV(ST(1)))==SVt_PVHV) {
-            HV *hv = (HV*)SvRV(ST(1));
-            SV *sv;
-            char *key;
-            I32 klen;
-            arg2 = NULL;
-            hv_iterinit(hv);
-            while(sv = hv_iternextsv(hv,&key,&klen)) {
-              sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-              arg2 = CSLAddNameValue( arg2, key, SvPV_nolen(sv) );
-            }
-          } else
-          SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-        } else
-        SWIG_croak("The 'options' argument is not a reference.");   
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALRasterBandShadow_SetCategoryNames(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg2) CSLDestroy( arg2 );
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg2) CSLDestroy( arg2 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Band_ContourGenerate) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    int arg4 ;
-    double *arg5 = (double *) 0 ;
-    int arg6 ;
-    double arg7 ;
-    OGRLayerShadow *arg8 = (OGRLayerShadow *) 0 ;
-    int arg9 ;
-    int arg10 ;
-    GDALProgressFunc arg11 = (GDALProgressFunc) NULL ;
-    void *arg12 = (void *) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    void *argp8 = 0 ;
-    int res8 = 0 ;
-    int val9 ;
-    int ecode9 = 0 ;
-    int val10 ;
-    int ecode10 = 0 ;
-    void *argp11 ;
-    int res11 = 0 ;
-    int res12 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 8) || (items > 10)) {
-      SWIG_croak("Usage: Band_ContourGenerate(self,dfContourInterval,dfContourBase,nFixedLevelCount,padfFixedLevels,bUseNoData,dfNoDataValue,hLayer,iIDField,iElevField,progress,progress_data);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_ContourGenerate" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Band_ContourGenerate" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Band_ContourGenerate" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    {
-      /* %typemap(in,numinputs=1) (int nList, double* pList) */
-      if (!(SvROK(ST(3)) && (SvTYPE(SvRV(ST(3)))==SVt_PVAV)))
-      SWIG_croak("Expected a reference to an array.");
-      AV *av = (AV*)(SvRV(ST(3)));
-      arg4 = av_len(av)+1;
-      arg5 = (double*)CPLMalloc(arg4*sizeof(double));
-      if (arg5) {
-        for( int i = 0; i<arg4; i++ ) {
-          SV **sv = av_fetch(av, i, 0);
-          arg5[i] =  SvNV(*sv);
-        }
-      } else
-      SWIG_fail;
-    }
-    {
-      /* %typemap(in,numinputs=1) (int defined, double value) */
-      arg6 = SvOK(ST(4));
-      arg7 = SvNV(ST(4));
-    }
-    res8 = SWIG_ConvertPtr(ST(5), &argp8,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res8)) {
-      SWIG_exception_fail(SWIG_ArgError(res8), "in method '" "Band_ContourGenerate" "', argument " "8"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg8 = reinterpret_cast< OGRLayerShadow * >(argp8);
-    ecode9 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(6), &val9);
-    if (!SWIG_IsOK(ecode9)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode9), "in method '" "Band_ContourGenerate" "', argument " "9"" of type '" "int""'");
-    } 
-    arg9 = static_cast< int >(val9);
-    ecode10 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(7), &val10);
-    if (!SWIG_IsOK(ecode10)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode10), "in method '" "Band_ContourGenerate" "', argument " "10"" of type '" "int""'");
-    } 
-    arg10 = static_cast< int >(val10);
-    if (items > 8) {
-      {
-        res11 = SWIG_ConvertPtr(ST(8), &argp11, SWIGTYPE_p_GDALProgressFunc,  0 );
-        if (!SWIG_IsOK(res11)) {
-          SWIG_exception_fail(SWIG_ArgError(res11), "in method '" "Band_ContourGenerate" "', argument " "11"" of type '" "GDALProgressFunc""'"); 
-        }  
-        if (!argp11) {
-          SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "Band_ContourGenerate" "', argument " "11"" of type '" "GDALProgressFunc""'");
-        } else {
-          arg11 = *(reinterpret_cast< GDALProgressFunc * >(argp11));
-        }
-      }
-    }
-    if (items > 9) {
-      res12 = SWIG_ConvertPtr(ST(9),SWIG_as_voidptrptr(&arg12), 0, 0);
-      if (!SWIG_IsOK(res12)) {
-        SWIG_exception_fail(SWIG_ArgError(res12), "in method '" "Band_ContourGenerate" "', argument " "12"" of type '" "void *""'"); 
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (CPLErr)GDALRasterBandShadow_ContourGenerate(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    
-    {
-      /* %typemap(freearg) (int nList, double* pList) */
-      CPLFree((void*) arg5);
-    }
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    {
-      /* %typemap(freearg) (int nList, double* pList) */
-      CPLFree((void*) arg5);
-    }
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_new_ColorTable) {
-  {
-    GDALPaletteInterp arg1 = (GDALPaletteInterp) GPI_RGB ;
-    int val1 ;
-    int ecode1 = 0 ;
-    int argvi = 0;
-    GDALColorTableShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 1)) {
-      SWIG_croak("Usage: new_ColorTable(palette);");
-    }
-    if (items > 0) {
-      ecode1 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-      if (!SWIG_IsOK(ecode1)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "new_ColorTable" "', argument " "1"" of type '" "GDALPaletteInterp""'");
-      } 
-      arg1 = static_cast< GDALPaletteInterp >(val1);
-    }
-    {
-      CPLErrorReset();
-      result = (GDALColorTableShadow *)new_GDALColorTableShadow(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALColorTableShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_delete_ColorTable) {
-  {
-    GDALColorTableShadow *arg1 = (GDALColorTableShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: delete_ColorTable(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALColorTableShadow, SWIG_POINTER_DISOWN |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_ColorTable" "', argument " "1"" of type '" "GDALColorTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALColorTableShadow * >(argp1);
-    {
-      CPLErrorReset();
-      delete_GDALColorTableShadow(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_ColorTable_Clone) {
-  {
-    GDALColorTableShadow *arg1 = (GDALColorTableShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    GDALColorTableShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: ColorTable_Clone(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALColorTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ColorTable_Clone" "', argument " "1"" of type '" "GDALColorTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALColorTableShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (GDALColorTableShadow *)GDALColorTableShadow_Clone(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALColorTableShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_ColorTable__GetPaletteInterpretation) {
-  {
-    GDALColorTableShadow *arg1 = (GDALColorTableShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    GDALPaletteInterp result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: ColorTable__GetPaletteInterpretation(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALColorTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ColorTable__GetPaletteInterpretation" "', argument " "1"" of type '" "GDALColorTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALColorTableShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (GDALPaletteInterp)GDALColorTableShadow_GetPaletteInterpretation(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_ColorTable_GetCount) {
-  {
-    GDALColorTableShadow *arg1 = (GDALColorTableShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: ColorTable_GetCount(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALColorTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ColorTable_GetCount" "', argument " "1"" of type '" "GDALColorTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALColorTableShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)GDALColorTableShadow_GetColorEntryCount(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_ColorTable_GetColorEntry) {
-  {
-    GDALColorTableShadow *arg1 = (GDALColorTableShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    GDALColorEntry *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: ColorTable_GetColorEntry(self,entry);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALColorTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ColorTable_GetColorEntry" "', argument " "1"" of type '" "GDALColorTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALColorTableShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "ColorTable_GetColorEntry" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (GDALColorEntry *)GDALColorTableShadow_GetColorEntry(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) GDALColorEntry* */
-      if (!result)
-      SWIG_croak("GetColorEntry failed.");
-      ST(argvi) = sv_newmortal();
-      sv_setiv(ST(argvi++), (IV) result->c1);
-      ST(argvi) = sv_newmortal();
-      sv_setiv(ST(argvi++), (IV) result->c2);
-      ST(argvi) = sv_newmortal();
-      sv_setiv(ST(argvi++), (IV) result->c3);
-      ST(argvi) = sv_newmortal();
-      sv_setiv(ST(argvi++), (IV) result->c4);
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_ColorTable_GetColorEntryAsRGB) {
-  {
-    GDALColorTableShadow *arg1 = (GDALColorTableShadow *) 0 ;
-    int arg2 ;
-    GDALColorEntry *arg3 = (GDALColorEntry *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    GDALColorEntry e3 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) GDALColorEntry*(GDALColorEntry e3) */
-      arg3 = &e3;
-    }
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: ColorTable_GetColorEntryAsRGB(self,entry);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALColorTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ColorTable_GetColorEntryAsRGB" "', argument " "1"" of type '" "GDALColorTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALColorTableShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "ColorTable_GetColorEntryAsRGB" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (int)GDALColorTableShadow_GetColorEntryAsRGB(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    {
-      /* %typemap(argout) GDALColorEntry* */
-      if (!result)
-      SWIG_croak("GetColorEntryAsRGB failed.");
-      argvi--;
-      ST(argvi) = sv_newmortal();
-      sv_setiv(ST(argvi++), (IV) e3.c1);
-      ST(argvi) = sv_newmortal();
-      sv_setiv(ST(argvi++), (IV) e3.c2);
-      ST(argvi) = sv_newmortal();
-      sv_setiv(ST(argvi++), (IV) e3.c3);
-      ST(argvi) = sv_newmortal();
-      sv_setiv(ST(argvi++), (IV) e3.c4);
-    }
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_ColorTable__SetColorEntry) {
-  {
-    GDALColorTableShadow *arg1 = (GDALColorTableShadow *) 0 ;
-    int arg2 ;
-    GDALColorEntry *arg3 = (GDALColorEntry *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    GDALColorEntry e3 ;
-    int argvi = 0;
-    SV * _saved[1] ;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: ColorTable__SetColorEntry(self,entry,centry);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALColorTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ColorTable__SetColorEntry" "', argument " "1"" of type '" "GDALColorTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALColorTableShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "ColorTable__SetColorEntry" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      /* %typemap(in,numinputs=1) const GDALColorEntry*(GDALColorEntry e3) */
-      arg3 = &e3;
-      int ok = SvROK(ST(2)) && SvTYPE(SvRV(ST(2)))==SVt_PVAV;
-      AV *av;
-      if (ok) {
-        av = (AV*)(SvRV(ST(2)));
-        ok = av_len(av) == 3;
-      }
-      if (ok) {
-        SV **sv = av_fetch(av, 0, 0);
-        arg3->c1 =  SvIV(*sv);
-        sv = av_fetch(av, 1, 0);
-        arg3->c2 =  SvIV(*sv);
-        sv = av_fetch(av, 2, 0);
-        arg3->c3 =  SvIV(*sv);
-        sv = av_fetch(av, 3, 0);
-        arg3->c4 =  SvIV(*sv);
-      } else 
-      SWIG_croak("Color entry is an array of four values: red, green, blue, alpha.");
-    }
-    _saved[0] = ST(2);
-    {
-      CPLErrorReset();
-      GDALColorTableShadow_SetColorEntry(arg1,arg2,(GDALColorEntry const *)arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    {
-      /* %typemap(argout) const GDALColorEntry* */
-    }
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_ColorTable_CreateColorRamp) {
-  {
-    GDALColorTableShadow *arg1 = (GDALColorTableShadow *) 0 ;
-    int arg2 ;
-    GDALColorEntry *arg3 = (GDALColorEntry *) 0 ;
-    int arg4 ;
-    GDALColorEntry *arg5 = (GDALColorEntry *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    GDALColorEntry e3 ;
-    int val4 ;
-    int ecode4 = 0 ;
-    GDALColorEntry e5 ;
-    int argvi = 0;
-    SV * _saved[2] ;
-    dXSARGS;
-    
-    if ((items < 5) || (items > 5)) {
-      SWIG_croak("Usage: ColorTable_CreateColorRamp(self,nStartIndex,startcolor,nEndIndex,endcolor);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALColorTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ColorTable_CreateColorRamp" "', argument " "1"" of type '" "GDALColorTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALColorTableShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "ColorTable_CreateColorRamp" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      /* %typemap(in,numinputs=1) const GDALColorEntry*(GDALColorEntry e3) */
-      arg3 = &e3;
-      int ok = SvROK(ST(2)) && SvTYPE(SvRV(ST(2)))==SVt_PVAV;
-      AV *av;
-      if (ok) {
-        av = (AV*)(SvRV(ST(2)));
-        ok = av_len(av) == 3;
-      }
-      if (ok) {
-        SV **sv = av_fetch(av, 0, 0);
-        arg3->c1 =  SvIV(*sv);
-        sv = av_fetch(av, 1, 0);
-        arg3->c2 =  SvIV(*sv);
-        sv = av_fetch(av, 2, 0);
-        arg3->c3 =  SvIV(*sv);
-        sv = av_fetch(av, 3, 0);
-        arg3->c4 =  SvIV(*sv);
-      } else 
-      SWIG_croak("Color entry is an array of four values: red, green, blue, alpha.");
-    }
-    ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "ColorTable_CreateColorRamp" "', argument " "4"" of type '" "int""'");
-    } 
-    arg4 = static_cast< int >(val4);
-    {
-      /* %typemap(in,numinputs=1) const GDALColorEntry*(GDALColorEntry e5) */
-      arg5 = &e3;
-      int ok = SvROK(ST(4)) && SvTYPE(SvRV(ST(4)))==SVt_PVAV;
-      AV *av;
-      if (ok) {
-        av = (AV*)(SvRV(ST(4)));
-        ok = av_len(av) == 3;
-      }
-      if (ok) {
-        SV **sv = av_fetch(av, 0, 0);
-        arg5->c1 =  SvIV(*sv);
-        sv = av_fetch(av, 1, 0);
-        arg5->c2 =  SvIV(*sv);
-        sv = av_fetch(av, 2, 0);
-        arg5->c3 =  SvIV(*sv);
-        sv = av_fetch(av, 3, 0);
-        arg5->c4 =  SvIV(*sv);
-      } else 
-      SWIG_croak("Color entry is an array of four values: red, green, blue, alpha.");
-    }
-    _saved[0] = ST(2);
-    _saved[1] = ST(4);
-    {
-      CPLErrorReset();
-      GDALColorTableShadow_CreateColorRamp(arg1,arg2,(GDALColorEntry const *)arg3,arg4,(GDALColorEntry const *)arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    {
-      /* %typemap(argout) const GDALColorEntry* */
-    }
-    {
-      /* %typemap(argout) const GDALColorEntry* */
-    }
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_new_RasterAttributeTable) {
-  {
-    int argvi = 0;
-    GDALRasterAttributeTableShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 0)) {
-      SWIG_croak("Usage: new_RasterAttributeTable();");
-    }
-    {
-      CPLErrorReset();
-      result = (GDALRasterAttributeTableShadow *)new_GDALRasterAttributeTableShadow();
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALRasterAttributeTableShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_delete_RasterAttributeTable) {
-  {
-    GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: delete_RasterAttributeTable(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterAttributeTableShadow, SWIG_POINTER_DISOWN |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_RasterAttributeTable" "', argument " "1"" of type '" "GDALRasterAttributeTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterAttributeTableShadow * >(argp1);
-    {
-      CPLErrorReset();
-      delete_GDALRasterAttributeTableShadow(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_RasterAttributeTable_Clone) {
-  {
-    GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    GDALRasterAttributeTableShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: RasterAttributeTable_Clone(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterAttributeTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RasterAttributeTable_Clone" "', argument " "1"" of type '" "GDALRasterAttributeTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterAttributeTableShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (GDALRasterAttributeTableShadow *)GDALRasterAttributeTableShadow_Clone(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALRasterAttributeTableShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_RasterAttributeTable_GetColumnCount) {
-  {
-    GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: RasterAttributeTable_GetColumnCount(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterAttributeTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RasterAttributeTable_GetColumnCount" "', argument " "1"" of type '" "GDALRasterAttributeTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterAttributeTableShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)GDALRasterAttributeTableShadow_GetColumnCount(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_RasterAttributeTable_GetNameOfCol) {
-  {
-    GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: RasterAttributeTable_GetNameOfCol(self,iCol);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterAttributeTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RasterAttributeTable_GetNameOfCol" "', argument " "1"" of type '" "GDALRasterAttributeTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterAttributeTableShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "RasterAttributeTable_GetNameOfCol" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (char *)GDALRasterAttributeTableShadow_GetNameOfCol(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_RasterAttributeTable__GetUsageOfCol) {
-  {
-    GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    GDALRATFieldUsage result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: RasterAttributeTable__GetUsageOfCol(self,iCol);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterAttributeTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RasterAttributeTable__GetUsageOfCol" "', argument " "1"" of type '" "GDALRasterAttributeTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterAttributeTableShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "RasterAttributeTable__GetUsageOfCol" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (GDALRATFieldUsage)GDALRasterAttributeTableShadow_GetUsageOfCol(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_RasterAttributeTable__GetTypeOfCol) {
-  {
-    GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    GDALRATFieldType result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: RasterAttributeTable__GetTypeOfCol(self,iCol);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterAttributeTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RasterAttributeTable__GetTypeOfCol" "', argument " "1"" of type '" "GDALRasterAttributeTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterAttributeTableShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "RasterAttributeTable__GetTypeOfCol" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (GDALRATFieldType)GDALRasterAttributeTableShadow_GetTypeOfCol(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_RasterAttributeTable__GetColOfUsage) {
-  {
-    GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
-    GDALRATFieldUsage arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: RasterAttributeTable__GetColOfUsage(self,eUsage);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterAttributeTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RasterAttributeTable__GetColOfUsage" "', argument " "1"" of type '" "GDALRasterAttributeTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterAttributeTableShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "RasterAttributeTable__GetColOfUsage" "', argument " "2"" of type '" "GDALRATFieldUsage""'");
-    } 
-    arg2 = static_cast< GDALRATFieldUsage >(val2);
-    {
-      CPLErrorReset();
-      result = (int)GDALRasterAttributeTableShadow_GetColOfUsage(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_RasterAttributeTable_GetRowCount) {
-  {
-    GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: RasterAttributeTable_GetRowCount(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterAttributeTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RasterAttributeTable_GetRowCount" "', argument " "1"" of type '" "GDALRasterAttributeTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterAttributeTableShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)GDALRasterAttributeTableShadow_GetRowCount(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_RasterAttributeTable_GetValueAsString) {
-  {
-    GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
-    int arg2 ;
-    int arg3 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: RasterAttributeTable_GetValueAsString(self,iRow,iCol);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterAttributeTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RasterAttributeTable_GetValueAsString" "', argument " "1"" of type '" "GDALRasterAttributeTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterAttributeTableShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "RasterAttributeTable_GetValueAsString" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "RasterAttributeTable_GetValueAsString" "', argument " "3"" of type '" "int""'");
-    } 
-    arg3 = static_cast< int >(val3);
-    {
-      CPLErrorReset();
-      result = (char *)GDALRasterAttributeTableShadow_GetValueAsString(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_RasterAttributeTable_GetValueAsInt) {
-  {
-    GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
-    int arg2 ;
-    int arg3 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: RasterAttributeTable_GetValueAsInt(self,iRow,iCol);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterAttributeTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RasterAttributeTable_GetValueAsInt" "', argument " "1"" of type '" "GDALRasterAttributeTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterAttributeTableShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "RasterAttributeTable_GetValueAsInt" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "RasterAttributeTable_GetValueAsInt" "', argument " "3"" of type '" "int""'");
-    } 
-    arg3 = static_cast< int >(val3);
-    {
-      CPLErrorReset();
-      result = (int)GDALRasterAttributeTableShadow_GetValueAsInt(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_RasterAttributeTable_GetValueAsDouble) {
-  {
-    GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
-    int arg2 ;
-    int arg3 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    double result;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: RasterAttributeTable_GetValueAsDouble(self,iRow,iCol);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterAttributeTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RasterAttributeTable_GetValueAsDouble" "', argument " "1"" of type '" "GDALRasterAttributeTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterAttributeTableShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "RasterAttributeTable_GetValueAsDouble" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "RasterAttributeTable_GetValueAsDouble" "', argument " "3"" of type '" "int""'");
-    } 
-    arg3 = static_cast< int >(val3);
-    {
-      CPLErrorReset();
-      result = (double)GDALRasterAttributeTableShadow_GetValueAsDouble(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_RasterAttributeTable_SetValueAsString) {
-  {
-    GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
-    int arg2 ;
-    int arg3 ;
-    char *arg4 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 4) || (items > 4)) {
-      SWIG_croak("Usage: RasterAttributeTable_SetValueAsString(self,iRow,iCol,pszValue);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterAttributeTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RasterAttributeTable_SetValueAsString" "', argument " "1"" of type '" "GDALRasterAttributeTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterAttributeTableShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "RasterAttributeTable_SetValueAsString" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "RasterAttributeTable_SetValueAsString" "', argument " "3"" of type '" "int""'");
-    } 
-    arg3 = static_cast< int >(val3);
-    {
-      /* %typemap(in) (tostring argin) */
-      sv_utf8_upgrade(ST(3)); /* GDAL expects UTF-8 */
-      arg4 = SvPV_nolen( ST(3) ); 
-    }
-    {
-      CPLErrorReset();
-      GDALRasterAttributeTableShadow_SetValueAsString(arg1,arg2,arg3,(char const *)arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_RasterAttributeTable_SetValueAsInt) {
-  {
-    GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
-    int arg2 ;
-    int arg3 ;
-    int arg4 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int val4 ;
-    int ecode4 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 4) || (items > 4)) {
-      SWIG_croak("Usage: RasterAttributeTable_SetValueAsInt(self,iRow,iCol,nValue);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterAttributeTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RasterAttributeTable_SetValueAsInt" "', argument " "1"" of type '" "GDALRasterAttributeTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterAttributeTableShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "RasterAttributeTable_SetValueAsInt" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "RasterAttributeTable_SetValueAsInt" "', argument " "3"" of type '" "int""'");
-    } 
-    arg3 = static_cast< int >(val3);
-    ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "RasterAttributeTable_SetValueAsInt" "', argument " "4"" of type '" "int""'");
-    } 
-    arg4 = static_cast< int >(val4);
-    {
-      CPLErrorReset();
-      GDALRasterAttributeTableShadow_SetValueAsInt(arg1,arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_RasterAttributeTable_SetValueAsDouble) {
-  {
-    GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
-    int arg2 ;
-    int arg3 ;
-    double arg4 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 4) || (items > 4)) {
-      SWIG_croak("Usage: RasterAttributeTable_SetValueAsDouble(self,iRow,iCol,dfValue);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterAttributeTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RasterAttributeTable_SetValueAsDouble" "', argument " "1"" of type '" "GDALRasterAttributeTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterAttributeTableShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "RasterAttributeTable_SetValueAsDouble" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "RasterAttributeTable_SetValueAsDouble" "', argument " "3"" of type '" "int""'");
-    } 
-    arg3 = static_cast< int >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "RasterAttributeTable_SetValueAsDouble" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    {
-      CPLErrorReset();
-      GDALRasterAttributeTableShadow_SetValueAsDouble(arg1,arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_RasterAttributeTable_SetRowCount) {
-  {
-    GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: RasterAttributeTable_SetRowCount(self,nCount);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterAttributeTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RasterAttributeTable_SetRowCount" "', argument " "1"" of type '" "GDALRasterAttributeTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterAttributeTableShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "RasterAttributeTable_SetRowCount" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      GDALRasterAttributeTableShadow_SetRowCount(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_RasterAttributeTable__CreateColumn) {
-  {
-    GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    GDALRATFieldType arg3 ;
-    GDALRATFieldUsage arg4 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int val4 ;
-    int ecode4 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 4) || (items > 4)) {
-      SWIG_croak("Usage: RasterAttributeTable__CreateColumn(self,pszName,eType,eUsage);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterAttributeTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RasterAttributeTable__CreateColumn" "', argument " "1"" of type '" "GDALRasterAttributeTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterAttributeTableShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "RasterAttributeTable__CreateColumn" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "RasterAttributeTable__CreateColumn" "', argument " "3"" of type '" "GDALRATFieldType""'");
-    } 
-    arg3 = static_cast< GDALRATFieldType >(val3);
-    ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "RasterAttributeTable__CreateColumn" "', argument " "4"" of type '" "GDALRATFieldUsage""'");
-    } 
-    arg4 = static_cast< GDALRATFieldUsage >(val4);
-    {
-      CPLErrorReset();
-      result = (int)GDALRasterAttributeTableShadow_CreateColumn(arg1,(char const *)arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_RasterAttributeTable_GetLinearBinning) {
-  {
-    GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
-    double *arg2 = (double *) 0 ;
-    double *arg3 = (double *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double temp2 ;
-    int res2 = SWIG_TMPOBJ ;
-    double temp3 ;
-    int res3 = SWIG_TMPOBJ ;
-    int argvi = 0;
-    bool result;
-    dXSARGS;
-    
-    arg2 = &temp2;
-    arg3 = &temp3;
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: RasterAttributeTable_GetLinearBinning(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterAttributeTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RasterAttributeTable_GetLinearBinning" "', argument " "1"" of type '" "GDALRasterAttributeTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterAttributeTableShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (bool)GDALRasterAttributeTableShadow_GetLinearBinning(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
-    if (SWIG_IsTmpObj(res2)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1((*arg2)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res2) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg2), SWIGTYPE_p_double, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res3)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1((*arg3)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_double, new_flags); argvi++  ;
-    }
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_RasterAttributeTable_SetLinearBinning) {
-  {
-    GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: RasterAttributeTable_SetLinearBinning(self,dfRow0Min,dfBinSize);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterAttributeTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RasterAttributeTable_SetLinearBinning" "', argument " "1"" of type '" "GDALRasterAttributeTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterAttributeTableShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "RasterAttributeTable_SetLinearBinning" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "RasterAttributeTable_SetLinearBinning" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    {
-      CPLErrorReset();
-      result = (int)GDALRasterAttributeTableShadow_SetLinearBinning(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_RasterAttributeTable_GetRowOfValue) {
-  {
-    GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
-    double arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: RasterAttributeTable_GetRowOfValue(self,dfValue);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterAttributeTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RasterAttributeTable_GetRowOfValue" "', argument " "1"" of type '" "GDALRasterAttributeTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterAttributeTableShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "RasterAttributeTable_GetRowOfValue" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    {
-      CPLErrorReset();
-      result = (int)GDALRasterAttributeTableShadow_GetRowOfValue(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_RasterAttributeTable_ChangesAreWrittenToFile) {
-  {
-    GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: RasterAttributeTable_ChangesAreWrittenToFile(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterAttributeTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RasterAttributeTable_ChangesAreWrittenToFile" "', argument " "1"" of type '" "GDALRasterAttributeTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterAttributeTableShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)GDALRasterAttributeTableShadow_ChangesAreWrittenToFile(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_RasterAttributeTable_DumpReadable) {
-  {
-    GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: RasterAttributeTable_DumpReadable(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterAttributeTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RasterAttributeTable_DumpReadable" "', argument " "1"" of type '" "GDALRasterAttributeTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterAttributeTableShadow * >(argp1);
-    {
-      CPLErrorReset();
-      GDALRasterAttributeTableShadow_DumpReadable(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_TermProgress_nocb) {
-  {
-    double arg1 ;
-    char *arg2 = (char *) NULL ;
-    void *arg3 = (void *) NULL ;
-    double val1 ;
-    int ecode1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int res3 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 3)) {
-      SWIG_croak("Usage: TermProgress_nocb(dfProgress,pszMessage,pData);");
-    }
-    ecode1 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "TermProgress_nocb" "', argument " "1"" of type '" "double""'");
-    } 
-    arg1 = static_cast< double >(val1);
-    if (items > 1) {
-      res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-      if (!SWIG_IsOK(res2)) {
-        SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "TermProgress_nocb" "', argument " "2"" of type '" "char const *""'");
-      }
-      arg2 = reinterpret_cast< char * >(buf2);
-    }
-    if (items > 2) {
-      res3 = SWIG_ConvertPtr(ST(2),SWIG_as_voidptrptr(&arg3), 0, 0);
-      if (!SWIG_IsOK(res3)) {
-        SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "TermProgress_nocb" "', argument " "3"" of type '" "void *""'"); 
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (int)GDALTermProgress_nocb(arg1,(char const *)arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap__ComputeMedianCutPCT) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    GDALRasterBandShadow *arg2 = (GDALRasterBandShadow *) 0 ;
-    GDALRasterBandShadow *arg3 = (GDALRasterBandShadow *) 0 ;
-    int arg4 ;
-    GDALColorTableShadow *arg5 = (GDALColorTableShadow *) 0 ;
-    GDALProgressFunc arg6 = (GDALProgressFunc) NULL ;
-    void *arg7 = (void *) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
-    int val4 ;
-    int ecode4 = 0 ;
-    void *argp5 = 0 ;
-    int res5 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg7 = (void *)(&saved_env);
-    if ((items < 5) || (items > 7)) {
-      SWIG_croak("Usage: _ComputeMedianCutPCT(red,green,blue,num_colors,colors,callback,callback_data);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "_ComputeMedianCutPCT" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "_ComputeMedianCutPCT" "', argument " "2"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< GDALRasterBandShadow * >(argp2);
-    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "_ComputeMedianCutPCT" "', argument " "3"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg3 = reinterpret_cast< GDALRasterBandShadow * >(argp3);
-    ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "_ComputeMedianCutPCT" "', argument " "4"" of type '" "int""'");
-    } 
-    arg4 = static_cast< int >(val4);
-    res5 = SWIG_ConvertPtr(ST(4), &argp5,SWIGTYPE_p_GDALColorTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res5)) {
-      SWIG_exception_fail(SWIG_ArgError(res5), "in method '" "_ComputeMedianCutPCT" "', argument " "5"" of type '" "GDALColorTableShadow *""'"); 
-    }
-    arg5 = reinterpret_cast< GDALColorTableShadow * >(argp5);
-    if (items > 5) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(5))) {
-          if (SvROK(ST(5))) {
-            if (SvTYPE(SvRV(ST(5))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(5);
-              arg6 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 6) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(6)))
-        saved_env.data = (SV *)ST(6);
-      }
-    }
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      if (!arg3) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      if (!arg5) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (int)ComputeMedianCutPCT(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap__DitherRGB2PCT) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    GDALRasterBandShadow *arg2 = (GDALRasterBandShadow *) 0 ;
-    GDALRasterBandShadow *arg3 = (GDALRasterBandShadow *) 0 ;
-    GDALRasterBandShadow *arg4 = (GDALRasterBandShadow *) 0 ;
-    GDALColorTableShadow *arg5 = (GDALColorTableShadow *) 0 ;
-    GDALProgressFunc arg6 = (GDALProgressFunc) NULL ;
-    void *arg7 = (void *) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
-    void *argp4 = 0 ;
-    int res4 = 0 ;
-    void *argp5 = 0 ;
-    int res5 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg7 = (void *)(&saved_env);
-    if ((items < 5) || (items > 7)) {
-      SWIG_croak("Usage: _DitherRGB2PCT(red,green,blue,target,colors,callback,callback_data);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "_DitherRGB2PCT" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "_DitherRGB2PCT" "', argument " "2"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< GDALRasterBandShadow * >(argp2);
-    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "_DitherRGB2PCT" "', argument " "3"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg3 = reinterpret_cast< GDALRasterBandShadow * >(argp3);
-    res4 = SWIG_ConvertPtr(ST(3), &argp4,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res4)) {
-      SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "_DitherRGB2PCT" "', argument " "4"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg4 = reinterpret_cast< GDALRasterBandShadow * >(argp4);
-    res5 = SWIG_ConvertPtr(ST(4), &argp5,SWIGTYPE_p_GDALColorTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res5)) {
-      SWIG_exception_fail(SWIG_ArgError(res5), "in method '" "_DitherRGB2PCT" "', argument " "5"" of type '" "GDALColorTableShadow *""'"); 
-    }
-    arg5 = reinterpret_cast< GDALColorTableShadow * >(argp5);
-    if (items > 5) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(5))) {
-          if (SvROK(ST(5))) {
-            if (SvTYPE(SvRV(ST(5))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(5);
-              arg6 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 6) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(6)))
-        saved_env.data = (SV *)ST(6);
-      }
-    }
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      if (!arg3) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      if (!arg4) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      if (!arg5) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (int)DitherRGB2PCT(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap__ReprojectImage) {
-  {
-    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-    GDALDatasetShadow *arg2 = (GDALDatasetShadow *) 0 ;
-    char *arg3 = (char *) NULL ;
-    char *arg4 = (char *) NULL ;
-    GDALResampleAlg arg5 = (GDALResampleAlg) GRA_NearestNeighbour ;
-    double arg6 = (double) 0.0 ;
-    double arg7 = (double) 0.0 ;
-    GDALProgressFunc arg8 = (GDALProgressFunc) NULL ;
-    void *arg9 = (void *) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int res3 ;
-    char *buf3 = 0 ;
-    int alloc3 = 0 ;
-    int res4 ;
-    char *buf4 = 0 ;
-    int alloc4 = 0 ;
-    int val5 ;
-    int ecode5 = 0 ;
-    double val6 ;
-    int ecode6 = 0 ;
-    double val7 ;
-    int ecode7 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg9 = (void *)(&saved_env);
-    if ((items < 2) || (items > 9)) {
-      SWIG_croak("Usage: _ReprojectImage(src_ds,dst_ds,src_wkt,dst_wkt,eResampleAlg,WarpMemoryLimit,maxerror,callback,callback_data);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "_ReprojectImage" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "_ReprojectImage" "', argument " "2"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< GDALDatasetShadow * >(argp2);
-    if (items > 2) {
-      res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
-      if (!SWIG_IsOK(res3)) {
-        SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "_ReprojectImage" "', argument " "3"" of type '" "char const *""'");
-      }
-      arg3 = reinterpret_cast< char * >(buf3);
-    }
-    if (items > 3) {
-      res4 = SWIG_AsCharPtrAndSize(ST(3), &buf4, NULL, &alloc4);
-      if (!SWIG_IsOK(res4)) {
-        SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "_ReprojectImage" "', argument " "4"" of type '" "char const *""'");
-      }
-      arg4 = reinterpret_cast< char * >(buf4);
-    }
-    if (items > 4) {
-      ecode5 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-      if (!SWIG_IsOK(ecode5)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "_ReprojectImage" "', argument " "5"" of type '" "GDALResampleAlg""'");
-      } 
-      arg5 = static_cast< GDALResampleAlg >(val5);
-    }
-    if (items > 5) {
-      ecode6 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(5), &val6);
-      if (!SWIG_IsOK(ecode6)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "_ReprojectImage" "', argument " "6"" of type '" "double""'");
-      } 
-      arg6 = static_cast< double >(val6);
-    }
-    if (items > 6) {
-      ecode7 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(6), &val7);
-      if (!SWIG_IsOK(ecode7)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "_ReprojectImage" "', argument " "7"" of type '" "double""'");
-      } 
-      arg7 = static_cast< double >(val7);
-    }
-    if (items > 7) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(7))) {
-          if (SvROK(ST(7))) {
-            if (SvTYPE(SvRV(ST(7))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(7);
-              arg8 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 8) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(8)))
-        saved_env.data = (SV *)ST(8);
-      }
-    }
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (CPLErr)ReprojectImage(arg1,arg2,(char const *)arg3,(char const *)arg4,arg5,arg6,arg7,arg8,arg9);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap__ComputeProximity) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    GDALRasterBandShadow *arg2 = (GDALRasterBandShadow *) 0 ;
-    char **arg3 = (char **) NULL ;
-    GDALProgressFunc arg4 = (GDALProgressFunc) NULL ;
-    void *arg5 = (void *) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg5 = (void *)(&saved_env);
-    if ((items < 2) || (items > 5)) {
-      SWIG_croak("Usage: _ComputeProximity(srcBand,proximityBand,options,callback,callback_data);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "_ComputeProximity" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "_ComputeProximity" "', argument " "2"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< GDALRasterBandShadow * >(argp2);
-    if (items > 2) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(2))) {
-          if (SvROK(ST(2))) {
-            if (SvTYPE(SvRV(ST(2)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(2)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg3 = CSLAddString( arg3, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(2)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(2));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg3 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg3 = CSLAddNameValue( arg3, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    if (items > 3) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(3))) {
-          if (SvROK(ST(3))) {
-            if (SvTYPE(SvRV(ST(3))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(3);
-              arg4 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 4) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(4)))
-        saved_env.data = (SV *)ST(4);
-      }
-    }
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (int)ComputeProximity(arg1,arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg3) CSLDestroy( arg3 );
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg3) CSLDestroy( arg3 );
-    }
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap__RasterizeLayer) {
-  {
-    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-    int arg2 ;
-    int *arg3 = (int *) 0 ;
-    OGRLayerShadow *arg4 = (OGRLayerShadow *) 0 ;
-    void *arg5 = (void *) NULL ;
-    void *arg6 = (void *) NULL ;
-    int arg7 = (int) 0 ;
-    double *arg8 = (double *) NULL ;
-    char **arg9 = (char **) NULL ;
-    GDALProgressFunc arg10 = (GDALProgressFunc) NULL ;
-    void *arg11 = (void *) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp4 = 0 ;
-    int res4 = 0 ;
-    int res5 ;
-    int res6 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg11 = (void *)(&saved_env);
-    if ((items < 3) || (items > 9)) {
-      SWIG_croak("Usage: _RasterizeLayer(dataset,bands,band_list,layer,pfnTransformer,pTransformArg,burn_values,burn_values_list,options,callback,callback_data);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "_RasterizeLayer" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (int nList, int* pList) */
-      if (!(SvROK(ST(1)) && (SvTYPE(SvRV(ST(1)))==SVt_PVAV)))
-      SWIG_croak("Expected a reference to an array.");
-      AV *av = (AV*)(SvRV(ST(1)));
-      arg2 = av_len(av)+1;
-      arg3 = (int*)CPLMalloc(arg2*sizeof(int));
-      if (arg3) {
-        for( int i = 0; i<arg2; i++ ) {
-          SV **sv = av_fetch(av, i, 0);
-          arg3[i] =  SvIV(*sv);
-        }
-      } else
-      SWIG_fail;
-    }
-    res4 = SWIG_ConvertPtr(ST(2), &argp4,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res4)) {
-      SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "_RasterizeLayer" "', argument " "4"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg4 = reinterpret_cast< OGRLayerShadow * >(argp4);
-    if (items > 3) {
-      res5 = SWIG_ConvertPtr(ST(3),SWIG_as_voidptrptr(&arg5), 0, 0);
-      if (!SWIG_IsOK(res5)) {
-        SWIG_exception_fail(SWIG_ArgError(res5), "in method '" "_RasterizeLayer" "', argument " "5"" of type '" "void *""'"); 
-      }
-    }
-    if (items > 4) {
-      res6 = SWIG_ConvertPtr(ST(4),SWIG_as_voidptrptr(&arg6), 0, 0);
-      if (!SWIG_IsOK(res6)) {
-        SWIG_exception_fail(SWIG_ArgError(res6), "in method '" "_RasterizeLayer" "', argument " "6"" of type '" "void *""'"); 
-      }
-    }
-    if (items > 5) {
-      {
-        /* %typemap(in,numinputs=1) (int nList, double* pList) */
-        if (!(SvROK(ST(5)) && (SvTYPE(SvRV(ST(5)))==SVt_PVAV)))
-        SWIG_croak("Expected a reference to an array.");
-        AV *av = (AV*)(SvRV(ST(5)));
-        arg7 = av_len(av)+1;
-        arg8 = (double*)CPLMalloc(arg7*sizeof(double));
-        if (arg8) {
-          for( int i = 0; i<arg7; i++ ) {
-            SV **sv = av_fetch(av, i, 0);
-            arg8[i] =  SvNV(*sv);
-          }
-        } else
-        SWIG_fail;
-      }
-    }
-    if (items > 6) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(6))) {
-          if (SvROK(ST(6))) {
-            if (SvTYPE(SvRV(ST(6)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(6)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg9 = CSLAddString( arg9, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(6)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(6));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg9 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg9 = CSLAddNameValue( arg9, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    if (items > 7) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(7))) {
-          if (SvROK(ST(7))) {
-            if (SvTYPE(SvRV(ST(7))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(7);
-              arg10 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 8) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(8)))
-        saved_env.data = (SV *)ST(8);
-      }
-    }
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      if (!arg4) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (int)RasterizeLayer(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    {
-      /* %typemap(freearg) (int nList, int* pList) */
-      CPLFree((void*) arg3);
-    }
-    
-    
-    
-    {
-      /* %typemap(freearg) (int nList, double* pList) */
-      CPLFree((void*) arg8);
-    }
-    {
-      /* %typemap(freearg) char **options */
-      if (arg9) CSLDestroy( arg9 );
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) (int nList, int* pList) */
-      CPLFree((void*) arg3);
-    }
-    
-    
-    
-    {
-      /* %typemap(freearg) (int nList, double* pList) */
-      CPLFree((void*) arg8);
-    }
-    {
-      /* %typemap(freearg) char **options */
-      if (arg9) CSLDestroy( arg9 );
-    }
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap__Polygonize) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    GDALRasterBandShadow *arg2 = (GDALRasterBandShadow *) 0 ;
-    OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
-    int arg4 ;
-    char **arg5 = (char **) NULL ;
-    GDALProgressFunc arg6 = (GDALProgressFunc) NULL ;
-    void *arg7 = (void *) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
-    int val4 ;
-    int ecode4 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg7 = (void *)(&saved_env);
-    if ((items < 4) || (items > 7)) {
-      SWIG_croak("Usage: _Polygonize(srcBand,maskBand,outLayer,iPixValField,options,callback,callback_data);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "_Polygonize" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "_Polygonize" "', argument " "2"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< GDALRasterBandShadow * >(argp2);
-    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "_Polygonize" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
-    ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "_Polygonize" "', argument " "4"" of type '" "int""'");
-    } 
-    arg4 = static_cast< int >(val4);
-    if (items > 4) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(4))) {
-          if (SvROK(ST(4))) {
-            if (SvTYPE(SvRV(ST(4)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(4)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg5 = CSLAddString( arg5, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(4)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(4));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg5 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg5 = CSLAddNameValue( arg5, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    if (items > 5) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(5))) {
-          if (SvROK(ST(5))) {
-            if (SvTYPE(SvRV(ST(5))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(5);
-              arg6 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 6) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(6)))
-        saved_env.data = (SV *)ST(6);
-      }
-    }
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      if (!arg3) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (int)Polygonize(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg5) CSLDestroy( arg5 );
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg5) CSLDestroy( arg5 );
-    }
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FillNodata) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    GDALRasterBandShadow *arg2 = (GDALRasterBandShadow *) 0 ;
-    double arg3 ;
-    int arg4 ;
-    char **arg5 = (char **) NULL ;
-    GDALProgressFunc arg6 = (GDALProgressFunc) NULL ;
-    void *arg7 = (void *) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    int val4 ;
-    int ecode4 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg7 = (void *)(&saved_env);
-    if ((items < 4) || (items > 7)) {
-      SWIG_croak("Usage: FillNodata(targetBand,maskBand,maxSearchDist,smoothingIterations,options,callback,callback_data);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FillNodata" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "FillNodata" "', argument " "2"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< GDALRasterBandShadow * >(argp2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "FillNodata" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "FillNodata" "', argument " "4"" of type '" "int""'");
-    } 
-    arg4 = static_cast< int >(val4);
-    if (items > 4) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(4))) {
-          if (SvROK(ST(4))) {
-            if (SvTYPE(SvRV(ST(4)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(4)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg5 = CSLAddString( arg5, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(4)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(4));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg5 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg5 = CSLAddNameValue( arg5, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    if (items > 5) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(5))) {
-          if (SvROK(ST(5))) {
-            if (SvTYPE(SvRV(ST(5))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(5);
-              arg6 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 6) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(6)))
-        saved_env.data = (SV *)ST(6);
-      }
-    }
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (int)FillNodata(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg5) CSLDestroy( arg5 );
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg5) CSLDestroy( arg5 );
-    }
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap__SieveFilter) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    GDALRasterBandShadow *arg2 = (GDALRasterBandShadow *) 0 ;
-    GDALRasterBandShadow *arg3 = (GDALRasterBandShadow *) 0 ;
-    int arg4 ;
-    int arg5 = (int) 4 ;
-    char **arg6 = (char **) NULL ;
-    GDALProgressFunc arg7 = (GDALProgressFunc) NULL ;
-    void *arg8 = (void *) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
-    int val4 ;
-    int ecode4 = 0 ;
-    int val5 ;
-    int ecode5 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg8 = (void *)(&saved_env);
-    if ((items < 4) || (items > 8)) {
-      SWIG_croak("Usage: _SieveFilter(srcBand,maskBand,dstBand,threshold,connectedness,options,callback,callback_data);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "_SieveFilter" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "_SieveFilter" "', argument " "2"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< GDALRasterBandShadow * >(argp2);
-    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "_SieveFilter" "', argument " "3"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg3 = reinterpret_cast< GDALRasterBandShadow * >(argp3);
-    ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "_SieveFilter" "', argument " "4"" of type '" "int""'");
-    } 
-    arg4 = static_cast< int >(val4);
-    if (items > 4) {
-      ecode5 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-      if (!SWIG_IsOK(ecode5)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "_SieveFilter" "', argument " "5"" of type '" "int""'");
-      } 
-      arg5 = static_cast< int >(val5);
-    }
-    if (items > 5) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(5))) {
-          if (SvROK(ST(5))) {
-            if (SvTYPE(SvRV(ST(5)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(5)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg6 = CSLAddString( arg6, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(5)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(5));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg6 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg6 = CSLAddNameValue( arg6, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    if (items > 6) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(6))) {
-          if (SvROK(ST(6))) {
-            if (SvTYPE(SvRV(ST(6))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(6);
-              arg7 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 7) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(7)))
-        saved_env.data = (SV *)ST(7);
-      }
-    }
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      if (!arg3) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (int)SieveFilter(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg6) CSLDestroy( arg6 );
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg6) CSLDestroy( arg6 );
-    }
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap__RegenerateOverviews) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    int arg2 ;
-    GDALRasterBandShadow **arg3 = (GDALRasterBandShadow **) 0 ;
-    char *arg4 = (char *) "average" ;
-    GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
-    void *arg6 = (void *) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res4 ;
-    char *buf4 = 0 ;
-    int alloc4 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg6 = (void *)(&saved_env);
-    if ((items < 2) || (items > 5)) {
-      SWIG_croak("Usage: _RegenerateOverviews(srcBand,overviewBandCount,overviewBands,resampling,callback,callback_data);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "_RegenerateOverviews" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (int object_list_count, GDALRasterBandShadow **poObjects) */
-      if (!(SvROK(ST(1)) && (SvTYPE(SvRV(ST(1)))==SVt_PVAV)))
-      SWIG_croak("Expected a reference to an array of Band objects.");
-      AV *av = (AV*)(SvRV(ST(1)));
-      arg2 = av_len(av)+1;
-      /* get the pointers from the array into bands */
-      arg3 = (GDALRasterBandShadow **)CPLMalloc(arg2*sizeof(GDALRasterBandShadow *));
-      if (arg3) {
-        for (int i = 0; i < arg2; i++) {
-          SV **sv = av_fetch(av, i, 0);
-          int ret = SWIG_ConvertPtr(*sv, &(arg3[i]), SWIGTYPE_p_GDALRasterBandShadow, 0);
-          if (!SWIG_IsOK(ret))
-          SWIG_croak("An item in the argument array is not a Band object.");
-        }
-      } else
-      SWIG_croak("Out of memory.");
-      
-    }
-    if (items > 2) {
-      res4 = SWIG_AsCharPtrAndSize(ST(2), &buf4, NULL, &alloc4);
-      if (!SWIG_IsOK(res4)) {
-        SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "_RegenerateOverviews" "', argument " "4"" of type '" "char const *""'");
-      }
-      arg4 = reinterpret_cast< char * >(buf4);
-    }
-    if (items > 3) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(3))) {
-          if (SvROK(ST(3))) {
-            if (SvTYPE(SvRV(ST(3))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(3);
-              arg5 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 4) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(4)))
-        saved_env.data = (SV *)ST(4);
-      }
-    }
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (int)RegenerateOverviews(arg1,arg2,arg3,(char const *)arg4,arg5,arg6);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    {
-      /* %typemap(freearg) (int object_list_count, GDALRasterBandShadow **poObjects) */
-      CPLFree(arg3);
-    }
-    if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) (int object_list_count, GDALRasterBandShadow **poObjects) */
-      CPLFree(arg3);
-    }
-    if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap__RegenerateOverview) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    GDALRasterBandShadow *arg2 = (GDALRasterBandShadow *) 0 ;
-    char *arg3 = (char *) "average" ;
-    GDALProgressFunc arg4 = (GDALProgressFunc) NULL ;
-    void *arg5 = (void *) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int res3 ;
-    char *buf3 = 0 ;
-    int alloc3 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg5 = (void *)(&saved_env);
-    if ((items < 2) || (items > 5)) {
-      SWIG_croak("Usage: _RegenerateOverview(srcBand,overviewBand,resampling,callback,callback_data);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "_RegenerateOverview" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "_RegenerateOverview" "', argument " "2"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< GDALRasterBandShadow * >(argp2);
-    if (items > 2) {
-      res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
-      if (!SWIG_IsOK(res3)) {
-        SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "_RegenerateOverview" "', argument " "3"" of type '" "char const *""'");
-      }
-      arg3 = reinterpret_cast< char * >(buf3);
-    }
-    if (items > 3) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(3))) {
-          if (SvROK(ST(3))) {
-            if (SvTYPE(SvRV(ST(3))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(3);
-              arg4 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 4) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(4)))
-        saved_env.data = (SV *)ST(4);
-      }
-    }
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (int)RegenerateOverview(arg1,arg2,(char const *)arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_ContourGenerate) {
-  {
-    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    int arg4 ;
-    double *arg5 = (double *) 0 ;
-    int arg6 ;
-    double arg7 ;
-    OGRLayerShadow *arg8 = (OGRLayerShadow *) 0 ;
-    int arg9 ;
-    int arg10 ;
-    GDALProgressFunc arg11 = (GDALProgressFunc) NULL ;
-    void *arg12 = (void *) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    int val6 ;
-    int ecode6 = 0 ;
-    double val7 ;
-    int ecode7 = 0 ;
-    void *argp8 = 0 ;
-    int res8 = 0 ;
-    int val9 ;
-    int ecode9 = 0 ;
-    int val10 ;
-    int ecode10 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg12 = (void *)(&saved_env);
-    if ((items < 9) || (items > 11)) {
-      SWIG_croak("Usage: ContourGenerate(srcBand,contourInterval,contourBase,fixedLevelCount,fixedLevels,useNoData,noDataValue,dstLayer,idField,elevField,callback,callback_data);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ContourGenerate" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "ContourGenerate" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "ContourGenerate" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    {
-      /* %typemap(in,numinputs=1) (int nList, double* pList) */
-      if (!(SvROK(ST(3)) && (SvTYPE(SvRV(ST(3)))==SVt_PVAV)))
-      SWIG_croak("Expected a reference to an array.");
-      AV *av = (AV*)(SvRV(ST(3)));
-      arg4 = av_len(av)+1;
-      arg5 = (double*)CPLMalloc(arg4*sizeof(double));
-      if (arg5) {
-        for( int i = 0; i<arg4; i++ ) {
-          SV **sv = av_fetch(av, i, 0);
-          arg5[i] =  SvNV(*sv);
-        }
-      } else
-      SWIG_fail;
-    }
-    ecode6 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(4), &val6);
-    if (!SWIG_IsOK(ecode6)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "ContourGenerate" "', argument " "6"" of type '" "int""'");
-    } 
-    arg6 = static_cast< int >(val6);
-    ecode7 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(5), &val7);
-    if (!SWIG_IsOK(ecode7)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "ContourGenerate" "', argument " "7"" of type '" "double""'");
-    } 
-    arg7 = static_cast< double >(val7);
-    res8 = SWIG_ConvertPtr(ST(6), &argp8,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res8)) {
-      SWIG_exception_fail(SWIG_ArgError(res8), "in method '" "ContourGenerate" "', argument " "8"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg8 = reinterpret_cast< OGRLayerShadow * >(argp8);
-    ecode9 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(7), &val9);
-    if (!SWIG_IsOK(ecode9)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode9), "in method '" "ContourGenerate" "', argument " "9"" of type '" "int""'");
-    } 
-    arg9 = static_cast< int >(val9);
-    ecode10 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(8), &val10);
-    if (!SWIG_IsOK(ecode10)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode10), "in method '" "ContourGenerate" "', argument " "10"" of type '" "int""'");
-    } 
-    arg10 = static_cast< int >(val10);
-    if (items > 9) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(9))) {
-          if (SvROK(ST(9))) {
-            if (SvTYPE(SvRV(ST(9))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(9);
-              arg11 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 10) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(10)))
-        saved_env.data = (SV *)ST(10);
-      }
-    }
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      if (!arg8) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (int)ContourGenerate(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    
-    {
-      /* %typemap(freearg) (int nList, double* pList) */
-      CPLFree((void*) arg5);
-    }
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    {
-      /* %typemap(freearg) (int nList, double* pList) */
-      CPLFree((void*) arg5);
-    }
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap__AutoCreateWarpedVRT) {
-  {
-    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    char *arg3 = (char *) 0 ;
-    GDALResampleAlg arg4 = (GDALResampleAlg) GRA_NearestNeighbour ;
-    double arg5 = (double) 0.0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int res3 ;
-    char *buf3 = 0 ;
-    int alloc3 = 0 ;
-    int val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    int argvi = 0;
-    GDALDatasetShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 5)) {
-      SWIG_croak("Usage: _AutoCreateWarpedVRT(src_ds,src_wkt,dst_wkt,eResampleAlg,maxerror);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "_AutoCreateWarpedVRT" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-    if (items > 1) {
-      res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-      if (!SWIG_IsOK(res2)) {
-        SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "_AutoCreateWarpedVRT" "', argument " "2"" of type '" "char const *""'");
-      }
-      arg2 = reinterpret_cast< char * >(buf2);
-    }
-    if (items > 2) {
-      res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
-      if (!SWIG_IsOK(res3)) {
-        SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "_AutoCreateWarpedVRT" "', argument " "3"" of type '" "char const *""'");
-      }
-      arg3 = reinterpret_cast< char * >(buf3);
-    }
-    if (items > 3) {
-      ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-      if (!SWIG_IsOK(ecode4)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "_AutoCreateWarpedVRT" "', argument " "4"" of type '" "GDALResampleAlg""'");
-      } 
-      arg4 = static_cast< GDALResampleAlg >(val4);
-    }
-    if (items > 4) {
-      ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-      if (!SWIG_IsOK(ecode5)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "_AutoCreateWarpedVRT" "', argument " "5"" of type '" "double""'");
-      } 
-      arg5 = static_cast< double >(val5);
-    }
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (GDALDatasetShadow *)AutoCreateWarpedVRT(arg1,(char const *)arg2,(char const *)arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_new_Transformer) {
-  {
-    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-    GDALDatasetShadow *arg2 = (GDALDatasetShadow *) 0 ;
-    char **arg3 = (char **) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    GDALTransformerInfoShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: new_Transformer(src,dst,options);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_Transformer" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "new_Transformer" "', argument " "2"" of type '" "GDALDatasetShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< GDALDatasetShadow * >(argp2);
-    {
-      /* %typemap(in) char **options */
-      if (SvOK(ST(2))) {
-        if (SvROK(ST(2))) {
-          if (SvTYPE(SvRV(ST(2)))==SVt_PVAV) {
-            AV *av = (AV*)(SvRV(ST(2)));
-            for (int i = 0; i < av_len(av)+1; i++) {
-              SV *sv = *(av_fetch(av, i, 0));
-              sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-              char *pszItem = SvPV_nolen(sv);
-              arg3 = CSLAddString( arg3, pszItem );
-            }
-          } else if (SvTYPE(SvRV(ST(2)))==SVt_PVHV) {
-            HV *hv = (HV*)SvRV(ST(2));
-            SV *sv;
-            char *key;
-            I32 klen;
-            arg3 = NULL;
-            hv_iterinit(hv);
-            while(sv = hv_iternextsv(hv,&key,&klen)) {
-              sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-              arg3 = CSLAddNameValue( arg3, key, SvPV_nolen(sv) );
-            }
-          } else
-          SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-        } else
-        SWIG_croak("The 'options' argument is not a reference.");   
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (GDALTransformerInfoShadow *)new_GDALTransformerInfoShadow(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALTransformerInfoShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg3) CSLDestroy( arg3 );
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg3) CSLDestroy( arg3 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_delete_Transformer) {
-  {
-    GDALTransformerInfoShadow *arg1 = (GDALTransformerInfoShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: delete_Transformer(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALTransformerInfoShadow, SWIG_POINTER_DISOWN |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_Transformer" "', argument " "1"" of type '" "GDALTransformerInfoShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALTransformerInfoShadow * >(argp1);
-    {
-      CPLErrorReset();
-      delete_GDALTransformerInfoShadow(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Transformer_TransformPoint__SWIG_0) {
-  {
-    GDALTransformerInfoShadow *arg1 = (GDALTransformerInfoShadow *) 0 ;
-    int arg2 ;
-    double *arg3 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    double argin3[3] ;
-    int argvi = 0;
-    SV * _saved[1] ;
-    int result;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Transformer_TransformPoint(self,bDstToSrc,inout);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALTransformerInfoShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Transformer_TransformPoint" "', argument " "1"" of type '" "GDALTransformerInfoShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALTransformerInfoShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Transformer_TransformPoint" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      /* %typemap(in) (double argin3[ANY]) */
-      if (!(SvROK(ST(2)) && (SvTYPE(SvRV(ST(2)))==SVt_PVAV)))
-      SWIG_croak("Expected a reference to an array.");
-      arg3 = argin3;
-      AV *av = (AV*)(SvRV(ST(2)));
-      for (unsigned int i=0; i<3; i++) {
-        SV **sv = av_fetch(av, i, 0);
-        arg3[i] =  SvNV(*sv);
-      }
-    }
-    _saved[0] = ST(2);
-    {
-      CPLErrorReset();
-      result = (int)GDALTransformerInfoShadow_TransformPoint__SWIG_0(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    {
-      /* %typemap(argout) (double argout[ANY]) */
-      if (GIMME_V == G_ARRAY) {
-        /* return a list */
-        int i;
-        EXTEND(SP, argvi+3-items+1);
-        for (i = 0; i < 3; i++)
-        ST(argvi++) = sv_2mortal(newSVnv(arg3[i]));
-      } else {
-        ST(argvi) = CreateArrayFromDoubleArray( arg3, 3 );
-        argvi++;
-      }  
-    }
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Transformer_TransformPoint__SWIG_1) {
-  {
-    GDALTransformerInfoShadow *arg1 = (GDALTransformerInfoShadow *) 0 ;
-    double *arg2 ;
-    int arg3 ;
-    double arg4 ;
-    double arg5 ;
-    double arg6 = (double) 0.0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double argout2[3] ;
-    int val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    double val6 ;
-    int ecode6 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (double argout2[ANY]) */
-      arg2 = argout2;
-    }
-    if ((items < 4) || (items > 5)) {
-      SWIG_croak("Usage: Transformer_TransformPoint(self,bDstToSrc,x,y,z);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALTransformerInfoShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Transformer_TransformPoint" "', argument " "1"" of type '" "GDALTransformerInfoShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALTransformerInfoShadow * >(argp1);
-    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Transformer_TransformPoint" "', argument " "3"" of type '" "int""'");
-    } 
-    arg3 = static_cast< int >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Transformer_TransformPoint" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Transformer_TransformPoint" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    if (items > 4) {
-      ecode6 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val6);
-      if (!SWIG_IsOK(ecode6)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "Transformer_TransformPoint" "', argument " "6"" of type '" "double""'");
-      } 
-      arg6 = static_cast< double >(val6);
-    }
-    {
-      CPLErrorReset();
-      result = (int)GDALTransformerInfoShadow_TransformPoint__SWIG_1(arg1,arg2,arg3,arg4,arg5,arg6);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    {
-      /* %typemap(argout) (double argout[ANY]) */
-      if (GIMME_V == G_ARRAY) {
-        /* return a list */
-        int i;
-        EXTEND(SP, argvi+3-items+1);
-        for (i = 0; i < 3; i++)
-        ST(argvi++) = sv_2mortal(newSVnv(arg2[i]));
-      } else {
-        ST(argvi) = CreateArrayFromDoubleArray( arg2, 3 );
-        argvi++;
-      }  
-    }
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Transformer_TransformPoint) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 3) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_GDALTransformerInfoShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(2), &vptr, SWIGTYPE_p_double, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if ((items >= 4) && (items <= 5)) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_GDALTransformerInfoShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (items > 4) {
-        {
-          {
-            int res = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), NULL);
-            _v = SWIG_CheckState(res);
-          }
-        }
-        if (!_v) goto check_2;
-        _ranki += _v*_pi;
-        _rankm += _pi;
-        _pi *= SWIG_MAXCASTRANK;
-      }
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Transformer_TransformPoint__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Transformer_TransformPoint__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'Transformer_TransformPoint'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_Transformer__TransformPoints) {
-  {
-    GDALTransformerInfoShadow *arg1 = (GDALTransformerInfoShadow *) 0 ;
-    int arg2 ;
-    int arg3 ;
-    double *arg4 = (double *) 0 ;
-    double *arg5 = (double *) 0 ;
-    double *arg6 = (double *) 0 ;
-    int *arg7 = (int *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    void *argp7 = 0 ;
-    int res7 = 0 ;
-    int argvi = 0;
-    SV * _saved[1] ;
-    int result;
-    dXSARGS;
-    
-    if ((items < 4) || (items > 4)) {
-      SWIG_croak("Usage: Transformer__TransformPoints(self,bDstToSrc,nCount,x,y,z,panSuccess);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALTransformerInfoShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Transformer__TransformPoints" "', argument " "1"" of type '" "GDALTransformerInfoShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALTransformerInfoShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Transformer__TransformPoints" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      /* %typemap(in) (int nCount, double *x, double *y, double *z) */
-      /* ST(2) is a ref to a list of refs to point lists */
-      if (! (SvROK(ST(2)) && (SvTYPE(SvRV(ST(2)))==SVt_PVAV)))
-      SWIG_croak("Expected a reference to an array.");
-      AV *av = (AV*)(SvRV(ST(2)));
-      arg3 = av_len(av)+1;
-      arg4 = (double*)CPLMalloc(arg3*sizeof(double));
-      if (arg4)
-      arg5 = (double*)CPLMalloc(arg3*sizeof(double));
-      if (arg4 && arg5)
-      arg6 = (double*)CPLMalloc(arg3*sizeof(double));
-      if (!arg4 or !arg5 or !arg6)
-      SWIG_fail;
-      for (int i = 0; i < arg3; i++) {
-        SV **sv = av_fetch(av, i, 0); /* ref to one point list */
-        if (!(SvROK(*sv) && (SvTYPE(SvRV(*sv))==SVt_PVAV)))
-        SWIG_croak("An item in the list is not a reference to an array.");
-        AV *ac = (AV*)(SvRV(*sv));
-        int n = av_len(ac)+1;
-        SV **c = av_fetch(ac, 0, 0);
-        arg4[i] = SvNV(*c);
-        c = av_fetch(ac, 1, 0);
-        arg5[i] = SvNV(*c);
-        if (n < 3) {
-          arg6[i] = 0;
-        } else {
-          c = av_fetch(ac, 2, 0);
-          arg6[i] = SvNV(*c);
-        }
-      }
-    }
-    res7 = SWIG_ConvertPtr(ST(3), &argp7,SWIGTYPE_p_int, 0 |  0 );
-    if (!SWIG_IsOK(res7)) {
-      SWIG_exception_fail(SWIG_ArgError(res7), "in method '" "Transformer__TransformPoints" "', argument " "7"" of type '" "int *""'"); 
-    }
-    arg7 = reinterpret_cast< int * >(argp7);
-    _saved[0] = ST(2);
-    {
-      CPLErrorReset();
-      result = (int)GDALTransformerInfoShadow_TransformPoints(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    {
-      /* %typemap(argout) (int nCount, double *x, double *y, double *z) */
-      AV *av = (AV*)(SvRV(_saved[0]));
-      for (int i = 0; i < arg3; i++) {
-        SV **sv = av_fetch(av, i, 0);
-        AV *ac = (AV*)(SvRV(*sv));
-        int n = av_len(ac)+1;
-        SV *c = newSVnv(arg4[i]);
-        if (!av_store(ac, 0, c))
-        SvREFCNT_dec(c);
-        c = newSVnv(arg5[i]);
-        if (!av_store(ac, 1, c))
-        SvREFCNT_dec(c);
-        c = newSVnv(arg6[i]);
-        if (!av_store(ac, 2, c))
-        SvREFCNT_dec(c);
-      }
-    }
-    
-    
-    {
-      /* %typemap(freearg) (int nCount, double *x, double *y, double *z) */
-      CPLFree(arg4);
-      CPLFree(arg5);
-      CPLFree(arg6);
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    {
-      /* %typemap(freearg) (int nCount, double *x, double *y, double *z) */
-      CPLFree(arg4);
-      CPLFree(arg5);
-      CPLFree(arg6);
-    }
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Transformer_TransformGeolocations) {
-  {
-    GDALTransformerInfoShadow *arg1 = (GDALTransformerInfoShadow *) 0 ;
-    GDALRasterBandShadow *arg2 = (GDALRasterBandShadow *) 0 ;
-    GDALRasterBandShadow *arg3 = (GDALRasterBandShadow *) 0 ;
-    GDALRasterBandShadow *arg4 = (GDALRasterBandShadow *) 0 ;
-    GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
-    void *arg6 = (void *) NULL ;
-    char **arg7 = (char **) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
-    void *argp4 = 0 ;
-    int res4 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg6 = (void *)(&saved_env);
-    if ((items < 4) || (items > 7)) {
-      SWIG_croak("Usage: Transformer_TransformGeolocations(self,xBand,yBand,zBand,callback,callback_data,options);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALTransformerInfoShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Transformer_TransformGeolocations" "', argument " "1"" of type '" "GDALTransformerInfoShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALTransformerInfoShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Transformer_TransformGeolocations" "', argument " "2"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< GDALRasterBandShadow * >(argp2);
-    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Transformer_TransformGeolocations" "', argument " "3"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg3 = reinterpret_cast< GDALRasterBandShadow * >(argp3);
-    res4 = SWIG_ConvertPtr(ST(3), &argp4,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res4)) {
-      SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "Transformer_TransformGeolocations" "', argument " "4"" of type '" "GDALRasterBandShadow *""'"); 
-    }
-    arg4 = reinterpret_cast< GDALRasterBandShadow * >(argp4);
-    if (items > 4) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(4))) {
-          if (SvROK(ST(4))) {
-            if (SvTYPE(SvRV(ST(4))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(4);
-              arg5 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 5) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(5)))
-        saved_env.data = (SV *)ST(5);
-      }
-    }
-    if (items > 6) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(6))) {
-          if (SvROK(ST(6))) {
-            if (SvTYPE(SvRV(ST(6)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(6)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg7 = CSLAddString( arg7, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(6)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(6));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg7 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg7 = CSLAddNameValue( arg7, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      if (!arg3) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      if (!arg4) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (int)GDALTransformerInfoShadow_TransformGeolocations(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg7) CSLDestroy( arg7 );
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg7) CSLDestroy( arg7 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_ApplyGeoTransform) {
-  {
-    double *arg1 ;
-    double arg2 ;
-    double arg3 ;
-    double *arg4 = (double *) 0 ;
-    double *arg5 = (double *) 0 ;
-    double argin1[6] ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double temp4 ;
-    int res4 = SWIG_TMPOBJ ;
-    double temp5 ;
-    int res5 = SWIG_TMPOBJ ;
-    int argvi = 0;
-    dXSARGS;
-    
-    arg4 = &temp4;
-    arg5 = &temp5;
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: ApplyGeoTransform(padfGeoTransform,dfPixel,dfLine);");
-    }
-    {
-      /* %typemap(in) (double argin1[ANY]) */
-      if (!(SvROK(ST(0)) && (SvTYPE(SvRV(ST(0)))==SVt_PVAV)))
-      SWIG_croak("Expected a reference to an array.");
-      arg1 = argin1;
-      AV *av = (AV*)(SvRV(ST(0)));
-      for (unsigned int i=0; i<6; i++) {
-        SV **sv = av_fetch(av, i, 0);
-        arg1[i] =  SvNV(*sv);
-      }
-    }
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "ApplyGeoTransform" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "ApplyGeoTransform" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    {
-      CPLErrorReset();
-      GDALApplyGeoTransform(arg1,arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    if (SWIG_IsTmpObj(res4)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1((*arg4)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_double, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res5)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1((*arg5)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res5) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg5), SWIGTYPE_p_double, new_flags); argvi++  ;
-    }
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_InvGeoTransform) {
-  {
-    double *arg1 ;
-    double *arg2 ;
-    double argin1[6] ;
-    double argout2[6] ;
-    int argvi = 0;
-    RETURN_NONE result;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (double argout2[ANY]) */
-      arg2 = argout2;
-    }
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: InvGeoTransform(gt_in);");
-    }
-    {
-      /* %typemap(in) (double argin1[ANY]) */
-      if (!(SvROK(ST(0)) && (SvTYPE(SvRV(ST(0)))==SVt_PVAV)))
-      SWIG_croak("Expected a reference to an array.");
-      arg1 = argin1;
-      AV *av = (AV*)(SvRV(ST(0)));
-      for (unsigned int i=0; i<6; i++) {
-        SV **sv = av_fetch(av, i, 0);
-        arg1[i] =  SvNV(*sv);
-      }
-    }
-    {
-      CPLErrorReset();
-      result = GDALInvGeoTransform(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) IF_FALSE_RETURN_NONE */
-    }
-    {
-      /* %typemap(argout) (double argout[ANY]) */
-      if (GIMME_V == G_ARRAY) {
-        /* return a list */
-        int i;
-        EXTEND(SP, argvi+6-items+1);
-        for (i = 0; i < 6; i++)
-        ST(argvi++) = sv_2mortal(newSVnv(arg2[i]));
-      } else {
-        ST(argvi) = CreateArrayFromDoubleArray( arg2, 6 );
-        argvi++;
-      }  
-    }
-    
-    
-    {
-      /* %typemap(ret) IF_FALSE_RETURN_NONE */
-      if (result == 0 ) {
-        SWIG_croak("unexpected error in 'InvGeoTransform'");
-      }
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_VersionInfo) {
-  {
-    char *arg1 = (char *) "VERSION_NUM" ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 1)) {
-      SWIG_croak("Usage: VersionInfo(request);");
-    }
-    if (items > 0) {
-      res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-      if (!SWIG_IsOK(res1)) {
-        SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "VersionInfo" "', argument " "1"" of type '" "char const *""'");
-      }
-      arg1 = reinterpret_cast< char * >(buf1);
-    }
-    {
-      /* %typemap(check) (const char *request) */
-      if (!arg1)
-      SWIG_croak("The request must not be undefined when it is an argument to a Geo::GDAL method");
-    }
-    {
-      CPLErrorReset();
-      result = (char *)GDALVersionInfo((char const *)arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    XSRETURN(argvi);
-  fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_AllRegister) {
-  {
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 0)) {
-      SWIG_croak("Usage: AllRegister();");
-    }
-    {
-      CPLErrorReset();
-      GDALAllRegister();
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GDALDestroyDriverManager) {
-  {
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 0)) {
-      SWIG_croak("Usage: GDALDestroyDriverManager();");
-    }
-    {
-      CPLErrorReset();
-      GDALDestroyDriverManager();
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GetCacheMax) {
-  {
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 0)) {
-      SWIG_croak("Usage: GetCacheMax();");
-    }
-    {
-      CPLErrorReset();
-      result = (int)wrapper_GDALGetCacheMax();
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GetCacheUsed) {
-  {
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 0)) {
-      SWIG_croak("Usage: GetCacheUsed();");
-    }
-    {
-      CPLErrorReset();
-      result = (int)wrapper_GDALGetCacheUsed();
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SetCacheMax) {
-  {
-    int arg1 ;
-    int val1 ;
-    int ecode1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SetCacheMax(nBytes);");
-    }
-    ecode1 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "SetCacheMax" "', argument " "1"" of type '" "int""'");
-    } 
-    arg1 = static_cast< int >(val1);
-    {
-      CPLErrorReset();
-      wrapper_GDALSetCacheMax(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap__GetDataTypeSize) {
-  {
-    GDALDataType arg1 ;
-    int val1 ;
-    int ecode1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: _GetDataTypeSize(eDataType);");
-    }
-    ecode1 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "_GetDataTypeSize" "', argument " "1"" of type '" "GDALDataType""'");
-    } 
-    arg1 = static_cast< GDALDataType >(val1);
-    {
-      CPLErrorReset();
-      result = (int)GDALGetDataTypeSize(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap__DataTypeIsComplex) {
-  {
-    GDALDataType arg1 ;
-    int val1 ;
-    int ecode1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: _DataTypeIsComplex(eDataType);");
-    }
-    ecode1 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "_DataTypeIsComplex" "', argument " "1"" of type '" "GDALDataType""'");
-    } 
-    arg1 = static_cast< GDALDataType >(val1);
-    {
-      CPLErrorReset();
-      result = (int)GDALDataTypeIsComplex(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GetDataTypeName) {
-  {
-    GDALDataType arg1 ;
-    int val1 ;
-    int ecode1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GetDataTypeName(eDataType);");
-    }
-    ecode1 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "GetDataTypeName" "', argument " "1"" of type '" "GDALDataType""'");
-    } 
-    arg1 = static_cast< GDALDataType >(val1);
-    {
-      CPLErrorReset();
-      result = (char *)GDALGetDataTypeName(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GetDataTypeByName) {
-  {
-    char *arg1 = (char *) 0 ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
-    int argvi = 0;
-    GDALDataType result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GetDataTypeByName(pszDataTypeName);");
-    }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GetDataTypeByName" "', argument " "1"" of type '" "char const *""'");
-    }
-    arg1 = reinterpret_cast< char * >(buf1);
-    {
-      CPLErrorReset();
-      result = (GDALDataType)GDALGetDataTypeByName((char const *)arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    XSRETURN(argvi);
-  fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GetColorInterpretationName) {
-  {
-    GDALColorInterp arg1 ;
-    int val1 ;
-    int ecode1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GetColorInterpretationName(eColorInterp);");
-    }
-    ecode1 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "GetColorInterpretationName" "', argument " "1"" of type '" "GDALColorInterp""'");
-    } 
-    arg1 = static_cast< GDALColorInterp >(val1);
-    {
-      CPLErrorReset();
-      result = (char *)GDALGetColorInterpretationName(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GetPaletteInterpretationName) {
-  {
-    GDALPaletteInterp arg1 ;
-    int val1 ;
-    int ecode1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GetPaletteInterpretationName(ePaletteInterp);");
-    }
-    ecode1 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "GetPaletteInterpretationName" "', argument " "1"" of type '" "GDALPaletteInterp""'");
-    } 
-    arg1 = static_cast< GDALPaletteInterp >(val1);
-    {
-      CPLErrorReset();
-      result = (char *)GDALGetPaletteInterpretationName(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_DecToDMS) {
-  {
-    double arg1 ;
-    char *arg2 = (char *) 0 ;
-    int arg3 = (int) 2 ;
-    double val1 ;
-    int ecode1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 3)) {
-      SWIG_croak("Usage: DecToDMS(double,char const *,int);");
-    }
-    ecode1 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "DecToDMS" "', argument " "1"" of type '" "double""'");
-    } 
-    arg1 = static_cast< double >(val1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "DecToDMS" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    if (items > 2) {
-      ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-      if (!SWIG_IsOK(ecode3)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "DecToDMS" "', argument " "3"" of type '" "int""'");
-      } 
-      arg3 = static_cast< int >(val3);
-    }
-    {
-      CPLErrorReset();
-      result = (char *)GDALDecToDMS(arg1,(char const *)arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_PackedDMSToDec) {
-  {
-    double arg1 ;
-    double val1 ;
-    int ecode1 = 0 ;
-    int argvi = 0;
-    double result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: PackedDMSToDec(dfPacked);");
-    }
-    ecode1 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "PackedDMSToDec" "', argument " "1"" of type '" "double""'");
-    } 
-    arg1 = static_cast< double >(val1);
-    {
-      CPLErrorReset();
-      result = (double)GDALPackedDMSToDec(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_DecToPackedDMS) {
-  {
-    double arg1 ;
-    double val1 ;
-    int ecode1 = 0 ;
-    int argvi = 0;
-    double result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: DecToPackedDMS(dfDec);");
-    }
-    ecode1 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "DecToPackedDMS" "', argument " "1"" of type '" "double""'");
-    } 
-    arg1 = static_cast< double >(val1);
-    {
-      CPLErrorReset();
-      result = (double)GDALDecToPackedDMS(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_ParseXMLString) {
-  {
-    char *arg1 = (char *) 0 ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
-    int argvi = 0;
-    CPLXMLNode *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: ParseXMLString(pszXMLString);");
-    }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ParseXMLString" "', argument " "1"" of type '" "char *""'");
-    }
-    arg1 = reinterpret_cast< char * >(buf1);
-    {
-      CPLErrorReset();
-      result = (CPLXMLNode *)CPLParseXMLString(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) (CPLXMLNode*) */
-      ST(argvi) = newRV((SV*)XMLTreeToAV( result ));
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    {
-      /* %typemap(ret) (CPLXMLNode*) */
-      if ( result ) CPLDestroyXMLNode( result );
-    }
-    XSRETURN(argvi);
-  fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SerializeXMLTree) {
-  {
-    CPLXMLNode *arg1 = (CPLXMLNode *) 0 ;
-    int argvi = 0;
-    retStringAndCPLFree *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SerializeXMLTree(xmlnode);");
-    }
-    {
-      /* %typemap(in) (CPLXMLNode* xmlnode ) */
-      if (!(SvROK(ST(0)) && (SvTYPE(SvRV(ST(0)))==SVt_PVAV)))
-      SWIG_croak("Expected a reference to an array.");
-      AV *av = (AV*)(SvRV(ST(0)));
-      int err;
-      arg1 = AVToXMLTree( av, &err );
-      if ( !arg1 ) {
-        switch (err) {
-        case 1:
-          SWIG_croak("Conversion of a Perl array to XMLTree failed: the input XML is empty.");
-        case 2:
-          SWIG_croak("Conversion of a Perl array to XMLTree failed, child should be a reference to an array.");
-        }
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (retStringAndCPLFree *)CPLSerializeXMLTree(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    
-    /* %typemap(out) (retStringAndCPLFree*) */
-    if(result)
-    {
-      ST(argvi) = SWIG_FromCharPtr((const char *)result);
-      CPLFree(result);
-    }
-    else
-    {
-      ST(argvi) = &PL_sv_undef;
-    }
-    argvi++ ;
-    
-    {
-      /* %typemap(freearg) (CPLXMLNode *xmlnode) */
-      if ( arg1 ) CPLDestroyXMLNode( arg1 );
-    }
-    XSRETURN(argvi);
-  fail:
-    {
-      /* %typemap(freearg) (CPLXMLNode *xmlnode) */
-      if ( arg1 ) CPLDestroyXMLNode( arg1 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GetJPEG2000StructureAsString) {
-  {
-    char *arg1 = (char *) 0 ;
-    char **arg2 = (char **) NULL ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
-    int argvi = 0;
-    retStringAndCPLFree *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: GetJPEG2000StructureAsString(pszFilename,options);");
-    }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GetJPEG2000StructureAsString" "', argument " "1"" of type '" "char const *""'");
-    }
-    arg1 = reinterpret_cast< char * >(buf1);
-    if (items > 1) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(1))) {
-          if (SvROK(ST(1))) {
-            if (SvTYPE(SvRV(ST(1)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(1)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg2 = CSLAddString( arg2, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(1)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(1));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg2 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg2 = CSLAddNameValue( arg2, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (retStringAndCPLFree *)GetJPEG2000StructureAsString((char const *)arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    
-    /* %typemap(out) (retStringAndCPLFree*) */
-    if(result)
-    {
-      ST(argvi) = SWIG_FromCharPtr((const char *)result);
-      CPLFree(result);
-    }
-    else
-    {
-      ST(argvi) = &PL_sv_undef;
-    }
-    argvi++ ;
-    
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    {
-      /* %typemap(freearg) char **options */
-      if (arg2) CSLDestroy( arg2 );
-    }
-    XSRETURN(argvi);
-  fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    {
-      /* %typemap(freearg) char **options */
-      if (arg2) CSLDestroy( arg2 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GetDriverCount) {
-  {
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 0)) {
-      SWIG_croak("Usage: GetDriverCount();");
-    }
-    {
-      CPLErrorReset();
-      result = (int)GetDriverCount();
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GetDriverByName) {
-  {
-    char *arg1 = (char *) 0 ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
-    int argvi = 0;
-    GDALDriverShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GetDriverByName(name);");
-    }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GetDriverByName" "', argument " "1"" of type '" "char const *""'");
-    }
-    arg1 = reinterpret_cast< char * >(buf1);
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (GDALDriverShadow *)GetDriverByName((char const *)arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDriverShadow, 0 | SWIG_SHADOW); argvi++ ;
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    XSRETURN(argvi);
-  fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap__GetDriver) {
-  {
-    int arg1 ;
-    int val1 ;
-    int ecode1 = 0 ;
-    int argvi = 0;
-    GDALDriverShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: _GetDriver(i);");
-    }
-    ecode1 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "_GetDriver" "', argument " "1"" of type '" "int""'");
-    } 
-    arg1 = static_cast< int >(val1);
-    {
-      CPLErrorReset();
-      result = (GDALDriverShadow *)GetDriver(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDriverShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap__Open__SWIG_1) {
-  {
-    char *arg1 = (char *) 0 ;
-    GDALAccess arg2 = (GDALAccess) GA_ReadOnly ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    GDALDatasetShadow *result = 0 ;
-    dXSARGS;
-    
-    {
-      /* %typemap(default) const char * utf8_path */
-      arg1 = (char *)"";
-    }
-    if ((items < 0) || (items > 2)) {
-      SWIG_croak("Usage: _Open(utf8_path,eAccess);");
-    }
-    if (items > 0) {
-      {
-        /* %typemap(in,numinputs=1) (const char* utf8_path) */
-        sv_utf8_upgrade(ST(0));
-        arg1 = SvPV_nolen(ST(0));
-      }
-    }
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "_Open" "', argument " "2"" of type '" "GDALAccess""'");
-      } 
-      arg2 = static_cast< GDALAccess >(val2);
-    }
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (GDALDatasetShadow *)Open((char const *)arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap__Open) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if ((items >= 0) && (items <= 2)) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      if (items > 0) {
-        {
-          int res = SWIG_AsCharPtrAndSize(ST(0), 0, NULL, 0);
-          _v = SWIG_CheckState(res);
-        }
-        if (!_v) goto check_1;
-        _ranki += _v*_pi;
-        _rankm += _pi;
-        _pi *= SWIG_MAXCASTRANK;
-        if (items > 1) {
-          {
-            {
-              int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-              _v = SWIG_CheckState(res);
-            }
-          }
-          if (!_v) goto check_1;
-          _ranki += _v*_pi;
-          _rankm += _pi;
-          _pi *= SWIG_MAXCASTRANK;
-        }
-      }
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap__Open__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded '_Open'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_OpenEx) {
-  {
-    char *arg1 = (char *) 0 ;
-    unsigned int arg2 = (unsigned int) 0 ;
-    char **arg3 = (char **) NULL ;
-    char **arg4 = (char **) NULL ;
-    char **arg5 = (char **) NULL ;
-    unsigned int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    GDALDatasetShadow *result = 0 ;
-    dXSARGS;
-    
-    {
-      /* %typemap(default) const char * utf8_path */
-      arg1 = (char *)"";
-    }
-    if ((items < 0) || (items > 5)) {
-      SWIG_croak("Usage: OpenEx(utf8_path,nOpenFlags,allowed_drivers,open_options,sibling_files);");
-    }
-    if (items > 0) {
-      {
-        /* %typemap(in,numinputs=1) (const char* utf8_path) */
-        sv_utf8_upgrade(ST(0));
-        arg1 = SvPV_nolen(ST(0));
-      }
-    }
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_unsigned_SS_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "OpenEx" "', argument " "2"" of type '" "unsigned int""'");
-      } 
-      arg2 = static_cast< unsigned int >(val2);
-    }
-    if (items > 2) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(2))) {
-          if (SvROK(ST(2))) {
-            if (SvTYPE(SvRV(ST(2)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(2)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg3 = CSLAddString( arg3, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(2)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(2));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg3 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg3 = CSLAddNameValue( arg3, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    if (items > 3) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(3))) {
-          if (SvROK(ST(3))) {
-            if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(3)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg4 = CSLAddString( arg4, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(3));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg4 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg4 = CSLAddNameValue( arg4, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    if (items > 4) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(4))) {
-          if (SvROK(ST(4))) {
-            if (SvTYPE(SvRV(ST(4)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(4)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg5 = CSLAddString( arg5, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(4)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(4));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg5 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg5 = CSLAddNameValue( arg5, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (GDALDatasetShadow *)OpenEx((char const *)arg1,arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg3) CSLDestroy( arg3 );
-    }
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
-    {
-      /* %typemap(freearg) char **options */
-      if (arg5) CSLDestroy( arg5 );
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg3) CSLDestroy( arg3 );
-    }
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
-    {
-      /* %typemap(freearg) char **options */
-      if (arg5) CSLDestroy( arg5 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap__OpenShared__SWIG_1) {
-  {
-    char *arg1 = (char *) 0 ;
-    GDALAccess arg2 = (GDALAccess) GA_ReadOnly ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    GDALDatasetShadow *result = 0 ;
-    dXSARGS;
-    
-    {
-      /* %typemap(default) const char * utf8_path */
-      arg1 = (char *)"";
-    }
-    if ((items < 0) || (items > 2)) {
-      SWIG_croak("Usage: _OpenShared(utf8_path,eAccess);");
-    }
-    if (items > 0) {
-      {
-        /* %typemap(in,numinputs=1) (const char* utf8_path) */
-        sv_utf8_upgrade(ST(0));
-        arg1 = SvPV_nolen(ST(0));
-      }
-    }
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "_OpenShared" "', argument " "2"" of type '" "GDALAccess""'");
-      } 
-      arg2 = static_cast< GDALAccess >(val2);
-    }
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (GDALDatasetShadow *)OpenShared((char const *)arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap__OpenShared) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if ((items >= 0) && (items <= 2)) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      if (items > 0) {
-        {
-          int res = SWIG_AsCharPtrAndSize(ST(0), 0, NULL, 0);
-          _v = SWIG_CheckState(res);
-        }
-        if (!_v) goto check_1;
-        _ranki += _v*_pi;
-        _rankm += _pi;
-        _pi *= SWIG_MAXCASTRANK;
-        if (items > 1) {
-          {
-            {
-              int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-              _v = SWIG_CheckState(res);
-            }
-          }
-          if (!_v) goto check_1;
-          _ranki += _v*_pi;
-          _rankm += _pi;
-          _pi *= SWIG_MAXCASTRANK;
-        }
-      }
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap__OpenShared__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded '_OpenShared'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_IdentifyDriver) {
-  {
-    char *arg1 = (char *) 0 ;
-    char **arg2 = (char **) NULL ;
-    int argvi = 0;
-    GDALDriverShadow *result = 0 ;
-    dXSARGS;
-    
-    {
-      /* %typemap(default) const char * utf8_path */
-      arg1 = (char *)"";
-    }
-    if ((items < 0) || (items > 2)) {
-      SWIG_croak("Usage: IdentifyDriver(utf8_path,papszSiblings);");
-    }
-    if (items > 0) {
-      {
-        /* %typemap(in,numinputs=1) (const char* utf8_path) */
-        sv_utf8_upgrade(ST(0));
-        arg1 = SvPV_nolen(ST(0));
-      }
-    }
-    if (items > 1) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(1))) {
-          if (SvROK(ST(1))) {
-            if (SvTYPE(SvRV(ST(1)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(1)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg2 = CSLAddString( arg2, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(1)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(1));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg2 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg2 = CSLAddNameValue( arg2, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (GDALDriverShadow *)IdentifyDriver((char const *)arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDriverShadow, 0 | SWIG_SHADOW); argvi++ ;
-    {
-      /* %typemap(freearg) char **options */
-      if (arg2) CSLDestroy( arg2 );
-    }
-    XSRETURN(argvi);
-  fail:
-    {
-      /* %typemap(freearg) char **options */
-      if (arg2) CSLDestroy( arg2 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GeneralCmdLineProcessor) {
-  {
-    char **arg1 = (char **) 0 ;
-    int arg2 = (int) 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    char **result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: GeneralCmdLineProcessor(papszArgv,nOptions);");
-    }
-    {
-      /* %typemap(in) char **options */
-      if (SvOK(ST(0))) {
-        if (SvROK(ST(0))) {
-          if (SvTYPE(SvRV(ST(0)))==SVt_PVAV) {
-            AV *av = (AV*)(SvRV(ST(0)));
-            for (int i = 0; i < av_len(av)+1; i++) {
-              SV *sv = *(av_fetch(av, i, 0));
-              sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-              char *pszItem = SvPV_nolen(sv);
-              arg1 = CSLAddString( arg1, pszItem );
-            }
-          } else if (SvTYPE(SvRV(ST(0)))==SVt_PVHV) {
-            HV *hv = (HV*)SvRV(ST(0));
-            SV *sv;
-            char *key;
-            I32 klen;
-            arg1 = NULL;
-            hv_iterinit(hv);
-            while(sv = hv_iternextsv(hv,&key,&klen)) {
-              sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-              arg1 = CSLAddNameValue( arg1, key, SvPV_nolen(sv) );
-            }
-          } else
-          SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-        } else
-        SWIG_croak("The 'options' argument is not a reference.");   
-      }
-    }
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "GeneralCmdLineProcessor" "', argument " "2"" of type '" "int""'");
-      } 
-      arg2 = static_cast< int >(val2);
-    }
-    {
-      CPLErrorReset();
-      result = (char **)GeneralCmdLineProcessor(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) char **options -> ( string ) */
-      AV* av = (AV*)sv_2mortal((SV*)newAV());
-      char **stringarray = result;
-      if ( stringarray != NULL ) {
-        int n = CSLCount( stringarray );
-        for ( int i = 0; i < n; i++ ) {
-          SV *sv = newSVpv(stringarray[i], 0);
-          SvUTF8_on(sv); /* expecting UTF-8 from GDAL */
-          if (!av_store(av, i, sv))
-          SvREFCNT_dec(sv);
-        }
-      }
-      ST(argvi) = newRV((SV*)av);
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    {
-      /* %typemap(freearg) char **options */
-      if (arg1) CSLDestroy( arg1 );
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    {
-      /* %typemap(freearg) char **options */
-      if (arg1) CSLDestroy( arg1 );
-    }
-    
-    SWIG_croak_null();
-  }
-}
-
-
-
-/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */
-
-static void *_p_GDALDriverShadowTo_p_GDALMajorObjectShadow(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((GDALMajorObjectShadow *)  ((GDALDriverShadow *) x));
-}
-static void *_p_OGRLayerShadowTo_p_GDALMajorObjectShadow(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((GDALMajorObjectShadow *)  ((OGRLayerShadow *) x));
-}
-static void *_p_GDALDatasetShadowTo_p_GDALMajorObjectShadow(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((GDALMajorObjectShadow *)  ((GDALDatasetShadow *) x));
-}
-static void *_p_GDALRasterBandShadowTo_p_GDALMajorObjectShadow(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((GDALMajorObjectShadow *)  ((GDALRasterBandShadow *) x));
-}
-static swig_type_info _swigt__p_CPLErrorHandler = {"_p_CPLErrorHandler", "CPLErrorHandler *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_CPLXMLNode = {"_p_CPLXMLNode", "CPLXMLNode *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_GByte = {"_p_GByte", "GByte *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_GDALAsyncReaderShadow = {"_p_GDALAsyncReaderShadow", "GDALAsyncReaderShadow *", 0, 0, (void*)"Geo::GDAL::AsyncReader", 0};
-static swig_type_info _swigt__p_GDALColorEntry = {"_p_GDALColorEntry", "GDALColorEntry *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_GDALColorTableShadow = {"_p_GDALColorTableShadow", "GDALColorTableShadow *", 0, 0, (void*)"Geo::GDAL::ColorTable", 0};
-static swig_type_info _swigt__p_GDALDatasetShadow = {"_p_GDALDatasetShadow", "GDALDatasetShadow *", 0, 0, (void*)"Geo::GDAL::Dataset", 0};
-static swig_type_info _swigt__p_GDALDriverShadow = {"_p_GDALDriverShadow", "GDALDriverShadow *", 0, 0, (void*)"Geo::GDAL::Driver", 0};
-static swig_type_info _swigt__p_GDALMajorObjectShadow = {"_p_GDALMajorObjectShadow", "GDALMajorObjectShadow *", 0, 0, (void*)"Geo::GDAL::MajorObject", 0};
-static swig_type_info _swigt__p_GDALProgressFunc = {"_p_GDALProgressFunc", "GDALProgressFunc *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_GDALRasterAttributeTableShadow = {"_p_GDALRasterAttributeTableShadow", "GDALRasterAttributeTableShadow *", 0, 0, (void*)"Geo::GDAL::RasterAttributeTable", 0};
-static swig_type_info _swigt__p_GDALRasterBandShadow = {"_p_GDALRasterBandShadow", "GDALRasterBandShadow *", 0, 0, (void*)"Geo::GDAL::Band", 0};
-static swig_type_info _swigt__p_GDALTransformerInfoShadow = {"_p_GDALTransformerInfoShadow", "GDALTransformerInfoShadow *", 0, 0, (void*)"Geo::GDAL::Transformer", 0};
-static swig_type_info _swigt__p_GDAL_GCP = {"_p_GDAL_GCP", "GDAL_GCP *", 0, 0, (void*)"Geo::GDAL::GCP", 0};
-static swig_type_info _swigt__p_GUIntBig = {"_p_GUIntBig", "GUIntBig *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_OGRLayerShadow = {"_p_OGRLayerShadow", "OGRLayerShadow *", 0, 0, (void*)"Geo::OGR::Layer", 0};
-static swig_type_info _swigt__p_VSIStatBufL = {"_p_VSIStatBufL", "VSIStatBufL *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_char = {"_p_char", "char *|retStringAndCPLFree *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_double = {"_p_double", "double *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_f_double_p_q_const__char_p_void__int = {"_p_f_double_p_q_const__char_p_void__int", "int (*)(double,char const *,void *)", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_int = {"_p_int", "OGRFieldSubType *|GDALRATFieldType *|OGRFieldType *|int *|GDALAccess *|OGRwkbByteOrder *|CPLErr *|GDALRWFlag *|OGRJustification *|GDALRATFieldUsage *|GDALTileOrganization *|GDALPaletteInterp *|GDALColorInterp *|GDALResampleAlg *|GDALRIOResampleAlg *|OGRErr *|OGRwkbGeometryType *|GDALDataType *|GDALAsyncStatusType *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_p_GDALRasterBandShadow = {"_p_p_GDALRasterBandShadow", "GDALRasterBandShadow **", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_p_GDAL_GCP = {"_p_p_GDAL_GCP", "GDAL_GCP **", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_p_GUIntBig = {"_p_p_GUIntBig", "GUIntBig **", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_p_char = {"_p_p_char", "char **", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_void = {"_p_void", "VSILFILE *|void *", 0, 0, (void*)0, 0};
-
-static swig_type_info *swig_type_initial[] = {
-  &_swigt__p_CPLErrorHandler,
-  &_swigt__p_CPLXMLNode,
-  &_swigt__p_GByte,
-  &_swigt__p_GDALAsyncReaderShadow,
-  &_swigt__p_GDALColorEntry,
-  &_swigt__p_GDALColorTableShadow,
-  &_swigt__p_GDALDatasetShadow,
-  &_swigt__p_GDALDriverShadow,
-  &_swigt__p_GDALMajorObjectShadow,
-  &_swigt__p_GDALProgressFunc,
-  &_swigt__p_GDALRasterAttributeTableShadow,
-  &_swigt__p_GDALRasterBandShadow,
-  &_swigt__p_GDALTransformerInfoShadow,
-  &_swigt__p_GDAL_GCP,
-  &_swigt__p_GUIntBig,
-  &_swigt__p_OGRLayerShadow,
-  &_swigt__p_VSIStatBufL,
-  &_swigt__p_char,
-  &_swigt__p_double,
-  &_swigt__p_f_double_p_q_const__char_p_void__int,
-  &_swigt__p_int,
-  &_swigt__p_p_GDALRasterBandShadow,
-  &_swigt__p_p_GDAL_GCP,
-  &_swigt__p_p_GUIntBig,
-  &_swigt__p_p_char,
-  &_swigt__p_void,
-};
-
-static swig_cast_info _swigc__p_CPLErrorHandler[] = {  {&_swigt__p_CPLErrorHandler, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_CPLXMLNode[] = {  {&_swigt__p_CPLXMLNode, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_GByte[] = {  {&_swigt__p_GByte, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_GDALAsyncReaderShadow[] = {  {&_swigt__p_GDALAsyncReaderShadow, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_GDALColorEntry[] = {  {&_swigt__p_GDALColorEntry, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_GDALColorTableShadow[] = {  {&_swigt__p_GDALColorTableShadow, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_GDALDatasetShadow[] = {  {&_swigt__p_GDALDatasetShadow, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_GDALDriverShadow[] = {  {&_swigt__p_GDALDriverShadow, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_GDALMajorObjectShadow[] = {  {&_swigt__p_GDALMajorObjectShadow, 0, 0, 0},  {&_swigt__p_GDALDriverShadow, _p_GDALDriverShadowTo_p_GDALMajorObjectShadow, 0, 0},  {&_swigt__p_OGRLayerShadow, _p_OGRLayerShadowTo_p_GDALMajorObjectShadow, 0, 0},  {&_swigt__p_GDALDatasetShadow, _p_GDALDatasetShadowTo_p_GDALMajorObjectShadow, 0, 0},  {&_swigt__p_GDALRasterBandShadow, _p_GDALRasterBandShadowTo_p_GDALMajorObjectShadow, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_GDALProgressFunc[] = {  {&_swigt__p_GDALProgressFunc, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_GDALRasterAttributeTableShadow[] = {  {&_swigt__p_GDALRasterAttributeTableShadow, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_GDALRasterBandShadow[] = {  {&_swigt__p_GDALRasterBandShadow, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_GDALTransformerInfoShadow[] = {  {&_swigt__p_GDALTransformerInfoShadow, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_GDAL_GCP[] = {  {&_swigt__p_GDAL_GCP, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_GUIntBig[] = {  {&_swigt__p_GUIntBig, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_OGRLayerShadow[] = {  {&_swigt__p_OGRLayerShadow, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_VSIStatBufL[] = {  {&_swigt__p_VSIStatBufL, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_char[] = {  {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_double[] = {  {&_swigt__p_double, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_f_double_p_q_const__char_p_void__int[] = {  {&_swigt__p_f_double_p_q_const__char_p_void__int, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_int[] = {  {&_swigt__p_int, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_p_GDALRasterBandShadow[] = {  {&_swigt__p_p_GDALRasterBandShadow, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_p_GDAL_GCP[] = {  {&_swigt__p_p_GDAL_GCP, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_p_GUIntBig[] = {  {&_swigt__p_p_GUIntBig, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_p_char[] = {  {&_swigt__p_p_char, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_void[] = {  {&_swigt__p_void, 0, 0, 0},{0, 0, 0, 0}};
-
-static swig_cast_info *swig_cast_initial[] = {
-  _swigc__p_CPLErrorHandler,
-  _swigc__p_CPLXMLNode,
-  _swigc__p_GByte,
-  _swigc__p_GDALAsyncReaderShadow,
-  _swigc__p_GDALColorEntry,
-  _swigc__p_GDALColorTableShadow,
-  _swigc__p_GDALDatasetShadow,
-  _swigc__p_GDALDriverShadow,
-  _swigc__p_GDALMajorObjectShadow,
-  _swigc__p_GDALProgressFunc,
-  _swigc__p_GDALRasterAttributeTableShadow,
-  _swigc__p_GDALRasterBandShadow,
-  _swigc__p_GDALTransformerInfoShadow,
-  _swigc__p_GDAL_GCP,
-  _swigc__p_GUIntBig,
-  _swigc__p_OGRLayerShadow,
-  _swigc__p_VSIStatBufL,
-  _swigc__p_char,
-  _swigc__p_double,
-  _swigc__p_f_double_p_q_const__char_p_void__int,
-  _swigc__p_int,
-  _swigc__p_p_GDALRasterBandShadow,
-  _swigc__p_p_GDAL_GCP,
-  _swigc__p_p_GUIntBig,
-  _swigc__p_p_char,
-  _swigc__p_void,
-};
-
-
-/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */
-
-static swig_constant_info swig_constants[] = {
-{0,0,0,0,0,0}
-};
-#ifdef __cplusplus
-}
-#endif
-static swig_variable_info swig_variables[] = {
-{0,0,0,0}
-};
-static swig_command_info swig_commands[] = {
-{"Geo::GDALc::callback_d_cp_vp", _wrap_callback_d_cp_vp},
-{"Geo::GDALc::UseExceptions", _wrap_UseExceptions},
-{"Geo::GDALc::DontUseExceptions", _wrap_DontUseExceptions},
-{"Geo::GDALc::Debug", _wrap_Debug},
-{"Geo::GDALc::SetErrorHandler", _wrap_SetErrorHandler},
-{"Geo::GDALc::Error", _wrap_Error},
-{"Geo::GDALc::GOA2GetAuthorizationURL", _wrap_GOA2GetAuthorizationURL},
-{"Geo::GDALc::GOA2GetRefreshToken", _wrap_GOA2GetRefreshToken},
-{"Geo::GDALc::GOA2GetAccessToken", _wrap_GOA2GetAccessToken},
-{"Geo::GDALc::PushErrorHandler", _wrap_PushErrorHandler},
-{"Geo::GDALc::PopErrorHandler", _wrap_PopErrorHandler},
-{"Geo::GDALc::ErrorReset", _wrap_ErrorReset},
-{"Geo::GDALc::EscapeString", _wrap_EscapeString},
-{"Geo::GDALc::GetLastErrorNo", _wrap_GetLastErrorNo},
-{"Geo::GDALc::GetLastErrorType", _wrap_GetLastErrorType},
-{"Geo::GDALc::GetLastErrorMsg", _wrap_GetLastErrorMsg},
-{"Geo::GDALc::PushFinderLocation", _wrap_PushFinderLocation},
-{"Geo::GDALc::PopFinderLocation", _wrap_PopFinderLocation},
-{"Geo::GDALc::FinderClean", _wrap_FinderClean},
-{"Geo::GDALc::FindFile", _wrap_FindFile},
-{"Geo::GDALc::ReadDir", _wrap_ReadDir},
-{"Geo::GDALc::ReadDirRecursive", _wrap_ReadDirRecursive},
-{"Geo::GDALc::SetConfigOption", _wrap_SetConfigOption},
-{"Geo::GDALc::GetConfigOption", _wrap_GetConfigOption},
-{"Geo::GDALc::CPLBinaryToHex", _wrap_CPLBinaryToHex},
-{"Geo::GDALc::CPLHexToBinary", _wrap_CPLHexToBinary},
-{"Geo::GDALc::FileFromMemBuffer", _wrap_FileFromMemBuffer},
-{"Geo::GDALc::Unlink", _wrap_Unlink},
-{"Geo::GDALc::HasThreadSupport", _wrap_HasThreadSupport},
-{"Geo::GDALc::Mkdir", _wrap_Mkdir},
-{"Geo::GDALc::Rmdir", _wrap_Rmdir},
-{"Geo::GDALc::Rename", _wrap_Rename},
-{"Geo::GDALc::Stat", _wrap_Stat},
-{"Geo::GDALc::VSIFOpenL", _wrap_VSIFOpenL},
-{"Geo::GDALc::VSIFCloseL", _wrap_VSIFCloseL},
-{"Geo::GDALc::VSIFSeekL", _wrap_VSIFSeekL},
-{"Geo::GDALc::VSIFTellL", _wrap_VSIFTellL},
-{"Geo::GDALc::VSIFTruncateL", _wrap_VSIFTruncateL},
-{"Geo::GDALc::VSIFWriteL", _wrap_VSIFWriteL},
-{"Geo::GDALc::VSIFReadL", _wrap_VSIFReadL},
-{"Geo::GDALc::MajorObject_GetDescription", _wrap_MajorObject_GetDescription},
-{"Geo::GDALc::MajorObject_SetDescription", _wrap_MajorObject_SetDescription},
-{"Geo::GDALc::MajorObject_GetMetadataDomainList", _wrap_MajorObject_GetMetadataDomainList},
-{"Geo::GDALc::MajorObject_GetMetadata", _wrap_MajorObject_GetMetadata},
-{"Geo::GDALc::MajorObject_SetMetadata", _wrap_MajorObject_SetMetadata},
-{"Geo::GDALc::MajorObject_GetMetadataItem", _wrap_MajorObject_GetMetadataItem},
-{"Geo::GDALc::MajorObject_SetMetadataItem", _wrap_MajorObject_SetMetadataItem},
-{"Geo::GDALc::Driver_ShortName_get", _wrap_Driver_ShortName_get},
-{"Geo::GDALc::Driver_LongName_get", _wrap_Driver_LongName_get},
-{"Geo::GDALc::Driver_HelpTopic_get", _wrap_Driver_HelpTopic_get},
-{"Geo::GDALc::Driver__Create", _wrap_Driver__Create},
-{"Geo::GDALc::Driver_CreateCopy", _wrap_Driver_CreateCopy},
-{"Geo::GDALc::Driver_Delete", _wrap_Driver_Delete},
-{"Geo::GDALc::Driver_Rename", _wrap_Driver_Rename},
-{"Geo::GDALc::Driver_CopyFiles", _wrap_Driver_CopyFiles},
-{"Geo::GDALc::Driver_Register", _wrap_Driver_Register},
-{"Geo::GDALc::Driver_Deregister", _wrap_Driver_Deregister},
-{"Geo::GDALc::GCP_X_set", _wrap_GCP_X_set},
-{"Geo::GDALc::GCP_X_get", _wrap_GCP_X_get},
-{"Geo::GDALc::GCP_Y_set", _wrap_GCP_Y_set},
-{"Geo::GDALc::GCP_Y_get", _wrap_GCP_Y_get},
-{"Geo::GDALc::GCP_Z_set", _wrap_GCP_Z_set},
-{"Geo::GDALc::GCP_Z_get", _wrap_GCP_Z_get},
-{"Geo::GDALc::GCP_Column_set", _wrap_GCP_Column_set},
-{"Geo::GDALc::GCP_Column_get", _wrap_GCP_Column_get},
-{"Geo::GDALc::GCP_Row_set", _wrap_GCP_Row_set},
-{"Geo::GDALc::GCP_Row_get", _wrap_GCP_Row_get},
-{"Geo::GDALc::GCP_Info_set", _wrap_GCP_Info_set},
-{"Geo::GDALc::GCP_Info_get", _wrap_GCP_Info_get},
-{"Geo::GDALc::GCP_Id_set", _wrap_GCP_Id_set},
-{"Geo::GDALc::GCP_Id_get", _wrap_GCP_Id_get},
-{"Geo::GDALc::new_GCP", _wrap_new_GCP},
-{"Geo::GDALc::delete_GCP", _wrap_delete_GCP},
-{"Geo::GDALc::GDAL_GCP_GCPX_get", _wrap_GDAL_GCP_GCPX_get},
-{"Geo::GDALc::GDAL_GCP_GCPX_set", _wrap_GDAL_GCP_GCPX_set},
-{"Geo::GDALc::GDAL_GCP_GCPY_get", _wrap_GDAL_GCP_GCPY_get},
-{"Geo::GDALc::GDAL_GCP_GCPY_set", _wrap_GDAL_GCP_GCPY_set},
-{"Geo::GDALc::GDAL_GCP_GCPZ_get", _wrap_GDAL_GCP_GCPZ_get},
-{"Geo::GDALc::GDAL_GCP_GCPZ_set", _wrap_GDAL_GCP_GCPZ_set},
-{"Geo::GDALc::GDAL_GCP_GCPPixel_get", _wrap_GDAL_GCP_GCPPixel_get},
-{"Geo::GDALc::GDAL_GCP_GCPPixel_set", _wrap_GDAL_GCP_GCPPixel_set},
-{"Geo::GDALc::GDAL_GCP_GCPLine_get", _wrap_GDAL_GCP_GCPLine_get},
-{"Geo::GDALc::GDAL_GCP_GCPLine_set", _wrap_GDAL_GCP_GCPLine_set},
-{"Geo::GDALc::GDAL_GCP_Info_get", _wrap_GDAL_GCP_Info_get},
-{"Geo::GDALc::GDAL_GCP_Info_set", _wrap_GDAL_GCP_Info_set},
-{"Geo::GDALc::GDAL_GCP_Id_get", _wrap_GDAL_GCP_Id_get},
-{"Geo::GDALc::GDAL_GCP_Id_set", _wrap_GDAL_GCP_Id_set},
-{"Geo::GDALc::GCPsToGeoTransform", _wrap_GCPsToGeoTransform},
-{"Geo::GDALc::delete_AsyncReader", _wrap_delete_AsyncReader},
-{"Geo::GDALc::AsyncReader_GetNextUpdatedRegion", _wrap_AsyncReader_GetNextUpdatedRegion},
-{"Geo::GDALc::AsyncReader_LockBuffer", _wrap_AsyncReader_LockBuffer},
-{"Geo::GDALc::AsyncReader_UnlockBuffer", _wrap_AsyncReader_UnlockBuffer},
-{"Geo::GDALc::Dataset_RasterXSize_get", _wrap_Dataset_RasterXSize_get},
-{"Geo::GDALc::Dataset_RasterYSize_get", _wrap_Dataset_RasterYSize_get},
-{"Geo::GDALc::Dataset_RasterCount_get", _wrap_Dataset_RasterCount_get},
-{"Geo::GDALc::delete_Dataset", _wrap_delete_Dataset},
-{"Geo::GDALc::Dataset__GetDriver", _wrap_Dataset__GetDriver},
-{"Geo::GDALc::Dataset__GetRasterBand", _wrap_Dataset__GetRasterBand},
-{"Geo::GDALc::Dataset_GetProjection", _wrap_Dataset_GetProjection},
-{"Geo::GDALc::Dataset_GetProjectionRef", _wrap_Dataset_GetProjectionRef},
-{"Geo::GDALc::Dataset_SetProjection", _wrap_Dataset_SetProjection},
-{"Geo::GDALc::Dataset_GetGeoTransform", _wrap_Dataset_GetGeoTransform},
-{"Geo::GDALc::Dataset_SetGeoTransform", _wrap_Dataset_SetGeoTransform},
-{"Geo::GDALc::Dataset__BuildOverviews", _wrap_Dataset__BuildOverviews},
-{"Geo::GDALc::Dataset_GetGCPCount", _wrap_Dataset_GetGCPCount},
-{"Geo::GDALc::Dataset_GetGCPProjection", _wrap_Dataset_GetGCPProjection},
-{"Geo::GDALc::Dataset_GetGCPs", _wrap_Dataset_GetGCPs},
-{"Geo::GDALc::Dataset_SetGCPs", _wrap_Dataset_SetGCPs},
-{"Geo::GDALc::Dataset_FlushCache", _wrap_Dataset_FlushCache},
-{"Geo::GDALc::Dataset__AddBand", _wrap_Dataset__AddBand},
-{"Geo::GDALc::Dataset__CreateMaskBand", _wrap_Dataset__CreateMaskBand},
-{"Geo::GDALc::Dataset_GetFileList", _wrap_Dataset_GetFileList},
-{"Geo::GDALc::Dataset__WriteRaster", _wrap_Dataset__WriteRaster},
-{"Geo::GDALc::Dataset__ReadRaster", _wrap_Dataset__ReadRaster},
-{"Geo::GDALc::Dataset_StartTransaction", _wrap_Dataset_StartTransaction},
-{"Geo::GDALc::Dataset_CommitTransaction", _wrap_Dataset_CommitTransaction},
-{"Geo::GDALc::Dataset_RollbackTransaction", _wrap_Dataset_RollbackTransaction},
-{"Geo::GDALc::Band_XSize_get", _wrap_Band_XSize_get},
-{"Geo::GDALc::Band_YSize_get", _wrap_Band_YSize_get},
-{"Geo::GDALc::Band_DataType_get", _wrap_Band_DataType_get},
-{"Geo::GDALc::Band_GetDataset", _wrap_Band_GetDataset},
-{"Geo::GDALc::Band_GetBand", _wrap_Band_GetBand},
-{"Geo::GDALc::Band_GetBlockSize", _wrap_Band_GetBlockSize},
-{"Geo::GDALc::Band_GetColorInterpretation", _wrap_Band_GetColorInterpretation},
-{"Geo::GDALc::Band_GetRasterColorInterpretation", _wrap_Band_GetRasterColorInterpretation},
-{"Geo::GDALc::Band_SetColorInterpretation", _wrap_Band_SetColorInterpretation},
-{"Geo::GDALc::Band_SetRasterColorInterpretation", _wrap_Band_SetRasterColorInterpretation},
-{"Geo::GDALc::Band_GetNoDataValue", _wrap_Band_GetNoDataValue},
-{"Geo::GDALc::Band_SetNoDataValue", _wrap_Band_SetNoDataValue},
-{"Geo::GDALc::Band_GetUnitType", _wrap_Band_GetUnitType},
-{"Geo::GDALc::Band_SetUnitType", _wrap_Band_SetUnitType},
-{"Geo::GDALc::Band_GetRasterCategoryNames", _wrap_Band_GetRasterCategoryNames},
-{"Geo::GDALc::Band_SetRasterCategoryNames", _wrap_Band_SetRasterCategoryNames},
-{"Geo::GDALc::Band_GetMinimum", _wrap_Band_GetMinimum},
-{"Geo::GDALc::Band_GetMaximum", _wrap_Band_GetMaximum},
-{"Geo::GDALc::Band_GetOffset", _wrap_Band_GetOffset},
-{"Geo::GDALc::Band_GetScale", _wrap_Band_GetScale},
-{"Geo::GDALc::Band_SetOffset", _wrap_Band_SetOffset},
-{"Geo::GDALc::Band_SetScale", _wrap_Band_SetScale},
-{"Geo::GDALc::Band_GetStatistics", _wrap_Band_GetStatistics},
-{"Geo::GDALc::Band_ComputeStatistics", _wrap_Band_ComputeStatistics},
-{"Geo::GDALc::Band_SetStatistics", _wrap_Band_SetStatistics},
-{"Geo::GDALc::Band_GetOverviewCount", _wrap_Band_GetOverviewCount},
-{"Geo::GDALc::Band_GetOverview", _wrap_Band_GetOverview},
-{"Geo::GDALc::Band_Checksum", _wrap_Band_Checksum},
-{"Geo::GDALc::Band_ComputeRasterMinMax", _wrap_Band_ComputeRasterMinMax},
-{"Geo::GDALc::Band_ComputeBandStats", _wrap_Band_ComputeBandStats},
-{"Geo::GDALc::Band_Fill", _wrap_Band_Fill},
-{"Geo::GDALc::Band__ReadRaster", _wrap_Band__ReadRaster},
-{"Geo::GDALc::Band__WriteRaster", _wrap_Band__WriteRaster},
-{"Geo::GDALc::Band_FlushCache", _wrap_Band_FlushCache},
-{"Geo::GDALc::Band_GetRasterColorTable", _wrap_Band_GetRasterColorTable},
-{"Geo::GDALc::Band_GetColorTable", _wrap_Band_GetColorTable},
-{"Geo::GDALc::Band_SetRasterColorTable", _wrap_Band_SetRasterColorTable},
-{"Geo::GDALc::Band_SetColorTable", _wrap_Band_SetColorTable},
-{"Geo::GDALc::Band_GetDefaultRAT", _wrap_Band_GetDefaultRAT},
-{"Geo::GDALc::Band_SetDefaultRAT", _wrap_Band_SetDefaultRAT},
-{"Geo::GDALc::Band_GetMaskBand", _wrap_Band_GetMaskBand},
-{"Geo::GDALc::Band__GetMaskFlags", _wrap_Band__GetMaskFlags},
-{"Geo::GDALc::Band__CreateMaskBand", _wrap_Band__CreateMaskBand},
-{"Geo::GDALc::Band__GetHistogram", _wrap_Band__GetHistogram},
-{"Geo::GDALc::Band_GetDefaultHistogram", _wrap_Band_GetDefaultHistogram},
-{"Geo::GDALc::Band_SetDefaultHistogram", _wrap_Band_SetDefaultHistogram},
-{"Geo::GDALc::Band_HasArbitraryOverviews", _wrap_Band_HasArbitraryOverviews},
-{"Geo::GDALc::Band_GetCategoryNames", _wrap_Band_GetCategoryNames},
-{"Geo::GDALc::Band_SetCategoryNames", _wrap_Band_SetCategoryNames},
-{"Geo::GDALc::Band_ContourGenerate", _wrap_Band_ContourGenerate},
-{"Geo::GDALc::new_ColorTable", _wrap_new_ColorTable},
-{"Geo::GDALc::delete_ColorTable", _wrap_delete_ColorTable},
-{"Geo::GDALc::ColorTable_Clone", _wrap_ColorTable_Clone},
-{"Geo::GDALc::ColorTable__GetPaletteInterpretation", _wrap_ColorTable__GetPaletteInterpretation},
-{"Geo::GDALc::ColorTable_GetCount", _wrap_ColorTable_GetCount},
-{"Geo::GDALc::ColorTable_GetColorEntry", _wrap_ColorTable_GetColorEntry},
-{"Geo::GDALc::ColorTable_GetColorEntryAsRGB", _wrap_ColorTable_GetColorEntryAsRGB},
-{"Geo::GDALc::ColorTable__SetColorEntry", _wrap_ColorTable__SetColorEntry},
-{"Geo::GDALc::ColorTable_CreateColorRamp", _wrap_ColorTable_CreateColorRamp},
-{"Geo::GDALc::new_RasterAttributeTable", _wrap_new_RasterAttributeTable},
-{"Geo::GDALc::delete_RasterAttributeTable", _wrap_delete_RasterAttributeTable},
-{"Geo::GDALc::RasterAttributeTable_Clone", _wrap_RasterAttributeTable_Clone},
-{"Geo::GDALc::RasterAttributeTable_GetColumnCount", _wrap_RasterAttributeTable_GetColumnCount},
-{"Geo::GDALc::RasterAttributeTable_GetNameOfCol", _wrap_RasterAttributeTable_GetNameOfCol},
-{"Geo::GDALc::RasterAttributeTable__GetUsageOfCol", _wrap_RasterAttributeTable__GetUsageOfCol},
-{"Geo::GDALc::RasterAttributeTable__GetTypeOfCol", _wrap_RasterAttributeTable__GetTypeOfCol},
-{"Geo::GDALc::RasterAttributeTable__GetColOfUsage", _wrap_RasterAttributeTable__GetColOfUsage},
-{"Geo::GDALc::RasterAttributeTable_GetRowCount", _wrap_RasterAttributeTable_GetRowCount},
-{"Geo::GDALc::RasterAttributeTable_GetValueAsString", _wrap_RasterAttributeTable_GetValueAsString},
-{"Geo::GDALc::RasterAttributeTable_GetValueAsInt", _wrap_RasterAttributeTable_GetValueAsInt},
-{"Geo::GDALc::RasterAttributeTable_GetValueAsDouble", _wrap_RasterAttributeTable_GetValueAsDouble},
-{"Geo::GDALc::RasterAttributeTable_SetValueAsString", _wrap_RasterAttributeTable_SetValueAsString},
-{"Geo::GDALc::RasterAttributeTable_SetValueAsInt", _wrap_RasterAttributeTable_SetValueAsInt},
-{"Geo::GDALc::RasterAttributeTable_SetValueAsDouble", _wrap_RasterAttributeTable_SetValueAsDouble},
-{"Geo::GDALc::RasterAttributeTable_SetRowCount", _wrap_RasterAttributeTable_SetRowCount},
-{"Geo::GDALc::RasterAttributeTable__CreateColumn", _wrap_RasterAttributeTable__CreateColumn},
-{"Geo::GDALc::RasterAttributeTable_GetLinearBinning", _wrap_RasterAttributeTable_GetLinearBinning},
-{"Geo::GDALc::RasterAttributeTable_SetLinearBinning", _wrap_RasterAttributeTable_SetLinearBinning},
-{"Geo::GDALc::RasterAttributeTable_GetRowOfValue", _wrap_RasterAttributeTable_GetRowOfValue},
-{"Geo::GDALc::RasterAttributeTable_ChangesAreWrittenToFile", _wrap_RasterAttributeTable_ChangesAreWrittenToFile},
-{"Geo::GDALc::RasterAttributeTable_DumpReadable", _wrap_RasterAttributeTable_DumpReadable},
-{"Geo::GDALc::TermProgress_nocb", _wrap_TermProgress_nocb},
-{"Geo::GDALc::_ComputeMedianCutPCT", _wrap__ComputeMedianCutPCT},
-{"Geo::GDALc::_DitherRGB2PCT", _wrap__DitherRGB2PCT},
-{"Geo::GDALc::_ReprojectImage", _wrap__ReprojectImage},
-{"Geo::GDALc::_ComputeProximity", _wrap__ComputeProximity},
-{"Geo::GDALc::_RasterizeLayer", _wrap__RasterizeLayer},
-{"Geo::GDALc::_Polygonize", _wrap__Polygonize},
-{"Geo::GDALc::FillNodata", _wrap_FillNodata},
-{"Geo::GDALc::_SieveFilter", _wrap__SieveFilter},
-{"Geo::GDALc::_RegenerateOverviews", _wrap__RegenerateOverviews},
-{"Geo::GDALc::_RegenerateOverview", _wrap__RegenerateOverview},
-{"Geo::GDALc::ContourGenerate", _wrap_ContourGenerate},
-{"Geo::GDALc::_AutoCreateWarpedVRT", _wrap__AutoCreateWarpedVRT},
-{"Geo::GDALc::new_Transformer", _wrap_new_Transformer},
-{"Geo::GDALc::delete_Transformer", _wrap_delete_Transformer},
-{"Geo::GDALc::Transformer_TransformPoint", _wrap_Transformer_TransformPoint},
-{"Geo::GDALc::Transformer__TransformPoints", _wrap_Transformer__TransformPoints},
-{"Geo::GDALc::Transformer_TransformGeolocations", _wrap_Transformer_TransformGeolocations},
-{"Geo::GDALc::ApplyGeoTransform", _wrap_ApplyGeoTransform},
-{"Geo::GDALc::InvGeoTransform", _wrap_InvGeoTransform},
-{"Geo::GDALc::VersionInfo", _wrap_VersionInfo},
-{"Geo::GDALc::AllRegister", _wrap_AllRegister},
-{"Geo::GDALc::GDALDestroyDriverManager", _wrap_GDALDestroyDriverManager},
-{"Geo::GDALc::GetCacheMax", _wrap_GetCacheMax},
-{"Geo::GDALc::GetCacheUsed", _wrap_GetCacheUsed},
-{"Geo::GDALc::SetCacheMax", _wrap_SetCacheMax},
-{"Geo::GDALc::_GetDataTypeSize", _wrap__GetDataTypeSize},
-{"Geo::GDALc::_DataTypeIsComplex", _wrap__DataTypeIsComplex},
-{"Geo::GDALc::GetDataTypeName", _wrap_GetDataTypeName},
-{"Geo::GDALc::GetDataTypeByName", _wrap_GetDataTypeByName},
-{"Geo::GDALc::GetColorInterpretationName", _wrap_GetColorInterpretationName},
-{"Geo::GDALc::GetPaletteInterpretationName", _wrap_GetPaletteInterpretationName},
-{"Geo::GDALc::DecToDMS", _wrap_DecToDMS},
-{"Geo::GDALc::PackedDMSToDec", _wrap_PackedDMSToDec},
-{"Geo::GDALc::DecToPackedDMS", _wrap_DecToPackedDMS},
-{"Geo::GDALc::ParseXMLString", _wrap_ParseXMLString},
-{"Geo::GDALc::SerializeXMLTree", _wrap_SerializeXMLTree},
-{"Geo::GDALc::GetJPEG2000StructureAsString", _wrap_GetJPEG2000StructureAsString},
-{"Geo::GDALc::GetDriverCount", _wrap_GetDriverCount},
-{"Geo::GDALc::GetDriverByName", _wrap_GetDriverByName},
-{"Geo::GDALc::_GetDriver", _wrap__GetDriver},
-{"Geo::GDALc::_Open", _wrap__Open},
-{"Geo::GDALc::OpenEx", _wrap_OpenEx},
-{"Geo::GDALc::_OpenShared", _wrap__OpenShared},
-{"Geo::GDALc::IdentifyDriver", _wrap_IdentifyDriver},
-{"Geo::GDALc::GeneralCmdLineProcessor", _wrap_GeneralCmdLineProcessor},
-{0,0}
-};
-/* -----------------------------------------------------------------------------
- * Type initialization:
- * This problem is tough by the requirement that no dynamic
- * memory is used. Also, since swig_type_info structures store pointers to
- * swig_cast_info structures and swig_cast_info structures store pointers back
- * to swig_type_info structures, we need some lookup code at initialization.
- * The idea is that swig generates all the structures that are needed.
- * The runtime then collects these partially filled structures.
- * The SWIG_InitializeModule function takes these initial arrays out of
- * swig_module, and does all the lookup, filling in the swig_module.types
- * array with the correct data and linking the correct swig_cast_info
- * structures together.
- *
- * The generated swig_type_info structures are assigned staticly to an initial
- * array. We just loop through that array, and handle each type individually.
- * First we lookup if this type has been already loaded, and if so, use the
- * loaded structure instead of the generated one. Then we have to fill in the
- * cast linked list. The cast data is initially stored in something like a
- * two-dimensional array. Each row corresponds to a type (there are the same
- * number of rows as there are in the swig_type_initial array). Each entry in
- * a column is one of the swig_cast_info structures for that type.
- * The cast_initial array is actually an array of arrays, because each row has
- * a variable number of columns. So to actually build the cast linked list,
- * we find the array of casts associated with the type, and loop through it
- * adding the casts to the list. The one last trick we need to do is making
- * sure the type pointer in the swig_cast_info struct is correct.
- *
- * First off, we lookup the cast->type name to see if it is already loaded.
- * There are three cases to handle:
- *  1) If the cast->type has already been loaded AND the type we are adding
- *     casting info to has not been loaded (it is in this module), THEN we
- *     replace the cast->type pointer with the type pointer that has already
- *     been loaded.
- *  2) If BOTH types (the one we are adding casting info to, and the
- *     cast->type) are loaded, THEN the cast info has already been loaded by
- *     the previous module so we just ignore it.
- *  3) Finally, if cast->type has not already been loaded, then we add that
- *     swig_cast_info to the linked list (because the cast->type) pointer will
- *     be correct.
- * ----------------------------------------------------------------------------- */
-
-#ifdef __cplusplus
-extern "C" {
-#if 0
-} /* c-mode */
-#endif
-#endif
-
-#if 0
-#define SWIGRUNTIME_DEBUG
-#endif
-
-
-SWIGRUNTIME void
-SWIG_InitializeModule(void *clientdata) {
-  size_t i;
-  swig_module_info *module_head, *iter;
-  int found, init;
-  
-  /* check to see if the circular list has been setup, if not, set it up */
-  if (swig_module.next==0) {
-    /* Initialize the swig_module */
-    swig_module.type_initial = swig_type_initial;
-    swig_module.cast_initial = swig_cast_initial;
-    swig_module.next = &swig_module;
-    init = 1;
-  } else {
-    init = 0;
-  }
-  
-  /* Try and load any already created modules */
-  module_head = SWIG_GetModule(clientdata);
-  if (!module_head) {
-    /* This is the first module loaded for this interpreter */
-    /* so set the swig module into the interpreter */
-    SWIG_SetModule(clientdata, &swig_module);
-    module_head = &swig_module;
-  } else {
-    /* the interpreter has loaded a SWIG module, but has it loaded this one? */
-    found=0;
-    iter=module_head;
-    do {
-      if (iter==&swig_module) {
-        found=1;
-        break;
-      }
-      iter=iter->next;
-    } while (iter!= module_head);
-    
-    /* if the is found in the list, then all is done and we may leave */
-    if (found) return;
-    /* otherwise we must add out module into the list */
-    swig_module.next = module_head->next;
-    module_head->next = &swig_module;
-  }
-  
-  /* When multiple interpreters are used, a module could have already been initialized in
-       a different interpreter, but not yet have a pointer in this interpreter.
-       In this case, we do not want to continue adding types... everything should be
-       set up already */
-  if (init == 0) return;
-  
-  /* Now work on filling in swig_module.types */
-#ifdef SWIGRUNTIME_DEBUG
-  printf("SWIG_InitializeModule: size %d\n", swig_module.size);
-#endif
-  for (i = 0; i < swig_module.size; ++i) {
-    swig_type_info *type = 0;
-    swig_type_info *ret;
-    swig_cast_info *cast;
-    
-#ifdef SWIGRUNTIME_DEBUG
-    printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name);
-#endif
-    
-    /* if there is another module already loaded */
-    if (swig_module.next != &swig_module) {
-      type = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, swig_module.type_initial[i]->name);
-    }
-    if (type) {
-      /* Overwrite clientdata field */
-#ifdef SWIGRUNTIME_DEBUG
-      printf("SWIG_InitializeModule: found type %s\n", type->name);
-#endif
-      if (swig_module.type_initial[i]->clientdata) {
-        type->clientdata = swig_module.type_initial[i]->clientdata;
-#ifdef SWIGRUNTIME_DEBUG
-        printf("SWIG_InitializeModule: found and overwrite type %s \n", type->name);
-#endif
-      }
-    } else {
-      type = swig_module.type_initial[i];
-    }
-    
-    /* Insert casting types */
-    cast = swig_module.cast_initial[i];
-    while (cast->type) {
-      /* Don't need to add information already in the list */
-      ret = 0;
-#ifdef SWIGRUNTIME_DEBUG
-      printf("SWIG_InitializeModule: look cast %s\n", cast->type->name);
-#endif
-      if (swig_module.next != &swig_module) {
-        ret = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, cast->type->name);
-#ifdef SWIGRUNTIME_DEBUG
-        if (ret) printf("SWIG_InitializeModule: found cast %s\n", ret->name);
-#endif
-      }
-      if (ret) {
-        if (type == swig_module.type_initial[i]) {
-#ifdef SWIGRUNTIME_DEBUG
-          printf("SWIG_InitializeModule: skip old type %s\n", ret->name);
-#endif
-          cast->type = ret;
-          ret = 0;
-        } else {
-          /* Check for casting already in the list */
-          swig_cast_info *ocast = SWIG_TypeCheck(ret->name, type);
-#ifdef SWIGRUNTIME_DEBUG
-          if (ocast) printf("SWIG_InitializeModule: skip old cast %s\n", ret->name);
-#endif
-          if (!ocast) ret = 0;
-        }
-      }
-      
-      if (!ret) {
-#ifdef SWIGRUNTIME_DEBUG
-        printf("SWIG_InitializeModule: adding cast %s\n", cast->type->name);
-#endif
-        if (type->cast) {
-          type->cast->prev = cast;
-          cast->next = type->cast;
-        }
-        type->cast = cast;
-      }
-      cast++;
-    }
-    /* Set entry in modules->types array equal to the type */
-    swig_module.types[i] = type;
-  }
-  swig_module.types[i] = 0;
-  
-#ifdef SWIGRUNTIME_DEBUG
-  printf("**** SWIG_InitializeModule: Cast List ******\n");
-  for (i = 0; i < swig_module.size; ++i) {
-    int j = 0;
-    swig_cast_info *cast = swig_module.cast_initial[i];
-    printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name);
-    while (cast->type) {
-      printf("SWIG_InitializeModule: cast type %s\n", cast->type->name);
-      cast++;
-      ++j;
-    }
-    printf("---- Total casts: %d\n",j);
-  }
-  printf("**** SWIG_InitializeModule: Cast List ******\n");
-#endif
-}
-
-/* This function will propagate the clientdata field of type to
-* any new swig_type_info structures that have been added into the list
-* of equivalent types.  It is like calling
-* SWIG_TypeClientData(type, clientdata) a second time.
-*/
-SWIGRUNTIME void
-SWIG_PropagateClientData(void) {
-  size_t i;
-  swig_cast_info *equiv;
-  static int init_run = 0;
-  
-  if (init_run) return;
-  init_run = 1;
-  
-  for (i = 0; i < swig_module.size; i++) {
-    if (swig_module.types[i]->clientdata) {
-      equiv = swig_module.types[i]->cast;
-      while (equiv) {
-        if (!equiv->converter) {
-          if (equiv->type && !equiv->type->clientdata)
-          SWIG_TypeClientData(equiv->type, swig_module.types[i]->clientdata);
-        }
-        equiv = equiv->next;
-      }
-    }
-  }
-}
-
-#ifdef __cplusplus
-#if 0
-{
-  /* c-mode */
-#endif
-}
-#endif
-
-
-
-#ifdef __cplusplus
-extern "C"
-#endif
-
-XS(SWIG_init) {
-  dXSARGS;
-  int i;
-  
-  SWIG_InitializeModule(0);
-  
-  /* Install commands */
-  for (i = 0; swig_commands[i].name; i++) {
-    /* Casts only needed for Perl < 5.10. */
-#ifdef __cplusplus
-    newXS(const_cast<char*>(swig_commands[i].name), swig_commands[i].wrapper, const_cast<char*>(__FILE__));
-#else
-    newXS((char*)swig_commands[i].name, swig_commands[i].wrapper, (char*)__FILE__);
-#endif
-  }
-  
-  /* Install variables */
-  for (i = 0; swig_variables[i].name; i++) {
-    SV *sv;
-    sv = get_sv(swig_variables[i].name, TRUE | 0x2 | GV_ADDMULTI);
-    if (swig_variables[i].type) {
-      SWIG_MakePtr(sv,(void *)1, *swig_variables[i].type,0);
-    } else {
-      sv_setiv(sv,(IV) 0);
-    }
-    swig_create_magic(sv, swig_variables[i].name, swig_variables[i].set, swig_variables[i].get); 
-  }
-  
-  /* Install constant */
-  for (i = 0; swig_constants[i].type; i++) {
-    SV *sv;
-    sv = get_sv(swig_constants[i].name, TRUE | 0x2 | GV_ADDMULTI);
-    switch(swig_constants[i].type) {
-    case SWIG_INT:
-      sv_setiv(sv, (IV) swig_constants[i].lvalue);
-      break;
-    case SWIG_FLOAT:
-      sv_setnv(sv, (double) swig_constants[i].dvalue);
-      break;
-    case SWIG_STRING:
-      sv_setpv(sv, (const char *) swig_constants[i].pvalue);
-      break;
-    case SWIG_POINTER:
-      SWIG_MakePtr(sv, swig_constants[i].pvalue, *(swig_constants[i].ptype),0);
-      break;
-    case SWIG_BINARY:
-      SWIG_MakePackedObj(sv, swig_constants[i].pvalue, swig_constants[i].lvalue, *(swig_constants[i].ptype));
-      break;
-    default:
-      break;
-    }
-    SvREADONLY_on(sv);
-  }
-  
-  
-  /* gdal_perl.i %init code */
-  UseExceptions();
-  if ( GDALGetDriverCount() == 0 ) {
-    GDALAllRegister();
-  }
-  
-  SWIG_TypeClientData(SWIGTYPE_p_GDALMajorObjectShadow, (void*) "Geo::GDAL::MajorObject");
-  SWIG_TypeClientData(SWIGTYPE_p_GDALDriverShadow, (void*) "Geo::GDAL::Driver");
-  SWIG_TypeClientData(SWIGTYPE_p_GDAL_GCP, (void*) "Geo::GDAL::GCP");
-  SWIG_TypeClientData(SWIGTYPE_p_GDALAsyncReaderShadow, (void*) "Geo::GDAL::AsyncReader");
-  SWIG_TypeClientData(SWIGTYPE_p_GDALDatasetShadow, (void*) "Geo::GDAL::Dataset");
-  SWIG_TypeClientData(SWIGTYPE_p_GDALRasterBandShadow, (void*) "Geo::GDAL::Band");
-  SWIG_TypeClientData(SWIGTYPE_p_GDALColorTableShadow, (void*) "Geo::GDAL::ColorTable");
-  SWIG_TypeClientData(SWIGTYPE_p_GDALRasterAttributeTableShadow, (void*) "Geo::GDAL::RasterAttributeTable");
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "TermProgress", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_NewFunctionPtrObj((void *)(int (*)(double,char const *,void *))(GDALTermProgress), SWIGTYPE_p_f_double_p_q_const__char_p_void__int));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  SWIG_TypeClientData(SWIGTYPE_p_GDALTransformerInfoShadow, (void*) "Geo::GDAL::Transformer");
-  ST(0) = &PL_sv_yes;
-  XSRETURN(1);
-}
-
diff --git a/swig/perl/gdalconst_wrap.c b/swig/perl/gdalconst_wrap.c
deleted file mode 100644
index 9d7e4e8..0000000
--- a/swig/perl/gdalconst_wrap.c
+++ /dev/null
@@ -1,2603 +0,0 @@
-/* ----------------------------------------------------------------------------
- * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 2.0.12
- *
- * This file is not intended to be easily readable and contains a number of
- * coding conventions designed to improve portability and efficiency. Do not make
- * changes to this file unless you know what you are doing--modify the SWIG
- * interface file instead.
- * ----------------------------------------------------------------------------- */
-
-#define SWIGPERL
-#define SWIG_CASTRANK_MODE
-
-/* -----------------------------------------------------------------------------
- *  This section contains generic SWIG labels for method/variable
- *  declarations/attributes, and other compiler dependent labels.
- * ----------------------------------------------------------------------------- */
-
-/* template workaround for compilers that cannot correctly implement the C++ standard */
-#ifndef SWIGTEMPLATEDISAMBIGUATOR
-# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560)
-#  define SWIGTEMPLATEDISAMBIGUATOR template
-# elif defined(__HP_aCC)
-/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */
-/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */
-#  define SWIGTEMPLATEDISAMBIGUATOR template
-# else
-#  define SWIGTEMPLATEDISAMBIGUATOR
-# endif
-#endif
-
-/* inline attribute */
-#ifndef SWIGINLINE
-# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__))
-#   define SWIGINLINE inline
-# else
-#   define SWIGINLINE
-# endif
-#endif
-
-/* attribute recognised by some compilers to avoid 'unused' warnings */
-#ifndef SWIGUNUSED
-# if defined(__GNUC__)
-#   if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
-#     define SWIGUNUSED __attribute__ ((__unused__))
-#   else
-#     define SWIGUNUSED
-#   endif
-# elif defined(__ICC)
-#   define SWIGUNUSED __attribute__ ((__unused__))
-# else
-#   define SWIGUNUSED
-# endif
-#endif
-
-#ifndef SWIG_MSC_UNSUPPRESS_4505
-# if defined(_MSC_VER)
-#   pragma warning(disable : 4505) /* unreferenced local function has been removed */
-# endif
-#endif
-
-#ifndef SWIGUNUSEDPARM
-# ifdef __cplusplus
-#   define SWIGUNUSEDPARM(p)
-# else
-#   define SWIGUNUSEDPARM(p) p SWIGUNUSED
-# endif
-#endif
-
-/* internal SWIG method */
-#ifndef SWIGINTERN
-# define SWIGINTERN static SWIGUNUSED
-#endif
-
-/* internal inline SWIG method */
-#ifndef SWIGINTERNINLINE
-# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE
-#endif
-
-/* exporting methods */
-#if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
-#  ifndef GCC_HASCLASSVISIBILITY
-#    define GCC_HASCLASSVISIBILITY
-#  endif
-#endif
-
-#ifndef SWIGEXPORT
-# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
-#   if defined(STATIC_LINKED)
-#     define SWIGEXPORT
-#   else
-#     define SWIGEXPORT __declspec(dllexport)
-#   endif
-# else
-#   if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY)
-#     define SWIGEXPORT __attribute__ ((visibility("default")))
-#   else
-#     define SWIGEXPORT
-#   endif
-# endif
-#endif
-
-/* calling conventions for Windows */
-#ifndef SWIGSTDCALL
-# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
-#   define SWIGSTDCALL __stdcall
-# else
-#   define SWIGSTDCALL
-# endif
-#endif
-
-/* Deal with Microsoft's attempt at deprecating C standard runtime functions */
-#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
-# define _CRT_SECURE_NO_DEPRECATE
-#endif
-
-/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */
-#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE)
-# define _SCL_SECURE_NO_DEPRECATE
-#endif
-
-
-/* -----------------------------------------------------------------------------
- * swigrun.swg
- *
- * This file contains generic C API SWIG runtime support for pointer
- * type checking.
- * ----------------------------------------------------------------------------- */
-
-/* This should only be incremented when either the layout of swig_type_info changes,
-   or for whatever reason, the runtime changes incompatibly */
-#define SWIG_RUNTIME_VERSION "4"
-
-/* define SWIG_TYPE_TABLE_NAME as "SWIG_TYPE_TABLE" */
-#ifdef SWIG_TYPE_TABLE
-# define SWIG_QUOTE_STRING(x) #x
-# define SWIG_EXPAND_AND_QUOTE_STRING(x) SWIG_QUOTE_STRING(x)
-# define SWIG_TYPE_TABLE_NAME SWIG_EXPAND_AND_QUOTE_STRING(SWIG_TYPE_TABLE)
-#else
-# define SWIG_TYPE_TABLE_NAME
-#endif
-
-/*
-  You can use the SWIGRUNTIME and SWIGRUNTIMEINLINE macros for
-  creating a static or dynamic library from the SWIG runtime code.
-  In 99.9% of the cases, SWIG just needs to declare them as 'static'.
-
-  But only do this if strictly necessary, ie, if you have problems
-  with your compiler or suchlike.
-*/
-
-#ifndef SWIGRUNTIME
-# define SWIGRUNTIME SWIGINTERN
-#endif
-
-#ifndef SWIGRUNTIMEINLINE
-# define SWIGRUNTIMEINLINE SWIGRUNTIME SWIGINLINE
-#endif
-
-/*  Generic buffer size */
-#ifndef SWIG_BUFFER_SIZE
-# define SWIG_BUFFER_SIZE 1024
-#endif
-
-/* Flags for pointer conversions */
-#define SWIG_POINTER_DISOWN        0x1
-#define SWIG_CAST_NEW_MEMORY       0x2
-
-/* Flags for new pointer objects */
-#define SWIG_POINTER_OWN           0x1
-
-
-/*
-   Flags/methods for returning states.
-
-   The SWIG conversion methods, as ConvertPtr, return an integer
-   that tells if the conversion was successful or not. And if not,
-   an error code can be returned (see swigerrors.swg for the codes).
-
-   Use the following macros/flags to set or process the returning
-   states.
-
-   In old versions of SWIG, code such as the following was usually written:
-
-     if (SWIG_ConvertPtr(obj,vptr,ty.flags) != -1) {
-       // success code
-     } else {
-       //fail code
-     }
-
-   Now you can be more explicit:
-
-    int res = SWIG_ConvertPtr(obj,vptr,ty.flags);
-    if (SWIG_IsOK(res)) {
-      // success code
-    } else {
-      // fail code
-    }
-
-   which is the same really, but now you can also do
-
-    Type *ptr;
-    int res = SWIG_ConvertPtr(obj,(void **)(&ptr),ty.flags);
-    if (SWIG_IsOK(res)) {
-      // success code
-      if (SWIG_IsNewObj(res) {
-        ...
-	delete *ptr;
-      } else {
-        ...
-      }
-    } else {
-      // fail code
-    }
-
-   I.e., now SWIG_ConvertPtr can return new objects and you can
-   identify the case and take care of the deallocation. Of course that
-   also requires SWIG_ConvertPtr to return new result values, such as
-
-      int SWIG_ConvertPtr(obj, ptr,...) {
-        if (<obj is ok>) {
-          if (<need new object>) {
-            *ptr = <ptr to new allocated object>;
-            return SWIG_NEWOBJ;
-          } else {
-            *ptr = <ptr to old object>;
-            return SWIG_OLDOBJ;
-          }
-        } else {
-          return SWIG_BADOBJ;
-        }
-      }
-
-   Of course, returning the plain '0(success)/-1(fail)' still works, but you can be
-   more explicit by returning SWIG_BADOBJ, SWIG_ERROR or any of the
-   SWIG errors code.
-
-   Finally, if the SWIG_CASTRANK_MODE is enabled, the result code
-   allows to return the 'cast rank', for example, if you have this
-
-       int food(double)
-       int fooi(int);
-
-   and you call
-
-      food(1)   // cast rank '1'  (1 -> 1.0)
-      fooi(1)   // cast rank '0'
-
-   just use the SWIG_AddCast()/SWIG_CheckState()
-*/
-
-#define SWIG_OK                    (0)
-#define SWIG_ERROR                 (-1)
-#define SWIG_IsOK(r)               (r >= 0)
-#define SWIG_ArgError(r)           ((r != SWIG_ERROR) ? r : SWIG_TypeError)
-
-/* The CastRankLimit says how many bits are used for the cast rank */
-#define SWIG_CASTRANKLIMIT         (1 << 8)
-/* The NewMask denotes the object was created (using new/malloc) */
-#define SWIG_NEWOBJMASK            (SWIG_CASTRANKLIMIT  << 1)
-/* The TmpMask is for in/out typemaps that use temporal objects */
-#define SWIG_TMPOBJMASK            (SWIG_NEWOBJMASK << 1)
-/* Simple returning values */
-#define SWIG_BADOBJ                (SWIG_ERROR)
-#define SWIG_OLDOBJ                (SWIG_OK)
-#define SWIG_NEWOBJ                (SWIG_OK | SWIG_NEWOBJMASK)
-#define SWIG_TMPOBJ                (SWIG_OK | SWIG_TMPOBJMASK)
-/* Check, add and del mask methods */
-#define SWIG_AddNewMask(r)         (SWIG_IsOK(r) ? (r | SWIG_NEWOBJMASK) : r)
-#define SWIG_DelNewMask(r)         (SWIG_IsOK(r) ? (r & ~SWIG_NEWOBJMASK) : r)
-#define SWIG_IsNewObj(r)           (SWIG_IsOK(r) && (r & SWIG_NEWOBJMASK))
-#define SWIG_AddTmpMask(r)         (SWIG_IsOK(r) ? (r | SWIG_TMPOBJMASK) : r)
-#define SWIG_DelTmpMask(r)         (SWIG_IsOK(r) ? (r & ~SWIG_TMPOBJMASK) : r)
-#define SWIG_IsTmpObj(r)           (SWIG_IsOK(r) && (r & SWIG_TMPOBJMASK))
-
-/* Cast-Rank Mode */
-#if defined(SWIG_CASTRANK_MODE)
-#  ifndef SWIG_TypeRank
-#    define SWIG_TypeRank             unsigned long
-#  endif
-#  ifndef SWIG_MAXCASTRANK            /* Default cast allowed */
-#    define SWIG_MAXCASTRANK          (2)
-#  endif
-#  define SWIG_CASTRANKMASK          ((SWIG_CASTRANKLIMIT) -1)
-#  define SWIG_CastRank(r)           (r & SWIG_CASTRANKMASK)
-SWIGINTERNINLINE int SWIG_AddCast(int r) {
-  return SWIG_IsOK(r) ? ((SWIG_CastRank(r) < SWIG_MAXCASTRANK) ? (r + 1) : SWIG_ERROR) : r;
-}
-SWIGINTERNINLINE int SWIG_CheckState(int r) {
-  return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0;
-}
-#else /* no cast-rank mode */
-#  define SWIG_AddCast(r) (r)
-#  define SWIG_CheckState(r) (SWIG_IsOK(r) ? 1 : 0)
-#endif
-
-
-#include <string.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef void *(*swig_converter_func)(void *, int *);
-typedef struct swig_type_info *(*swig_dycast_func)(void **);
-
-/* Structure to store information on one type */
-typedef struct swig_type_info {
-  const char             *name;			/* mangled name of this type */
-  const char             *str;			/* human readable name of this type */
-  swig_dycast_func        dcast;		/* dynamic cast function down a hierarchy */
-  struct swig_cast_info  *cast;			/* linked list of types that can cast into this type */
-  void                   *clientdata;		/* language specific type data */
-  int                    owndata;		/* flag if the structure owns the clientdata */
-} swig_type_info;
-
-/* Structure to store a type and conversion function used for casting */
-typedef struct swig_cast_info {
-  swig_type_info         *type;			/* pointer to type that is equivalent to this type */
-  swig_converter_func     converter;		/* function to cast the void pointers */
-  struct swig_cast_info  *next;			/* pointer to next cast in linked list */
-  struct swig_cast_info  *prev;			/* pointer to the previous cast */
-} swig_cast_info;
-
-/* Structure used to store module information
- * Each module generates one structure like this, and the runtime collects
- * all of these structures and stores them in a circularly linked list.*/
-typedef struct swig_module_info {
-  swig_type_info         **types;		/* Array of pointers to swig_type_info structures that are in this module */
-  size_t                 size;		        /* Number of types in this module */
-  struct swig_module_info *next;		/* Pointer to next element in circularly linked list */
-  swig_type_info         **type_initial;	/* Array of initially generated type structures */
-  swig_cast_info         **cast_initial;	/* Array of initially generated casting structures */
-  void                    *clientdata;		/* Language specific module data */
-} swig_module_info;
-
-/*
-  Compare two type names skipping the space characters, therefore
-  "char*" == "char *" and "Class<int>" == "Class<int >", etc.
-
-  Return 0 when the two name types are equivalent, as in
-  strncmp, but skipping ' '.
-*/
-SWIGRUNTIME int
-SWIG_TypeNameComp(const char *f1, const char *l1,
-		  const char *f2, const char *l2) {
-  for (;(f1 != l1) && (f2 != l2); ++f1, ++f2) {
-    while ((*f1 == ' ') && (f1 != l1)) ++f1;
-    while ((*f2 == ' ') && (f2 != l2)) ++f2;
-    if (*f1 != *f2) return (*f1 > *f2) ? 1 : -1;
-  }
-  return (int)((l1 - f1) - (l2 - f2));
-}
-
-/*
-  Check type equivalence in a name list like <name1>|<name2>|...
-  Return 0 if equal, -1 if nb < tb, 1 if nb > tb
-*/
-SWIGRUNTIME int
-SWIG_TypeCmp(const char *nb, const char *tb) {
-  int equiv = 1;
-  const char* te = tb + strlen(tb);
-  const char* ne = nb;
-  while (equiv != 0 && *ne) {
-    for (nb = ne; *ne; ++ne) {
-      if (*ne == '|') break;
-    }
-    equiv = SWIG_TypeNameComp(nb, ne, tb, te);
-    if (*ne) ++ne;
-  }
-  return equiv;
-}
-
-/*
-  Check type equivalence in a name list like <name1>|<name2>|...
-  Return 0 if not equal, 1 if equal
-*/
-SWIGRUNTIME int
-SWIG_TypeEquiv(const char *nb, const char *tb) {
-  return SWIG_TypeCmp(nb, tb) == 0 ? 1 : 0;
-}
-
-/*
-  Check the typename
-*/
-SWIGRUNTIME swig_cast_info *
-SWIG_TypeCheck(const char *c, swig_type_info *ty) {
-  if (ty) {
-    swig_cast_info *iter = ty->cast;
-    while (iter) {
-      if (strcmp(iter->type->name, c) == 0) {
-        if (iter == ty->cast)
-          return iter;
-        /* Move iter to the top of the linked list */
-        iter->prev->next = iter->next;
-        if (iter->next)
-          iter->next->prev = iter->prev;
-        iter->next = ty->cast;
-        iter->prev = 0;
-        if (ty->cast) ty->cast->prev = iter;
-        ty->cast = iter;
-        return iter;
-      }
-      iter = iter->next;
-    }
-  }
-  return 0;
-}
-
-/*
-  Identical to SWIG_TypeCheck, except strcmp is replaced with a pointer comparison
-*/
-SWIGRUNTIME swig_cast_info *
-SWIG_TypeCheckStruct(swig_type_info *from, swig_type_info *ty) {
-  if (ty) {
-    swig_cast_info *iter = ty->cast;
-    while (iter) {
-      if (iter->type == from) {
-        if (iter == ty->cast)
-          return iter;
-        /* Move iter to the top of the linked list */
-        iter->prev->next = iter->next;
-        if (iter->next)
-          iter->next->prev = iter->prev;
-        iter->next = ty->cast;
-        iter->prev = 0;
-        if (ty->cast) ty->cast->prev = iter;
-        ty->cast = iter;
-        return iter;
-      }
-      iter = iter->next;
-    }
-  }
-  return 0;
-}
-
-/*
-  Cast a pointer up an inheritance hierarchy
-*/
-SWIGRUNTIMEINLINE void *
-SWIG_TypeCast(swig_cast_info *ty, void *ptr, int *newmemory) {
-  return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr, newmemory);
-}
-
-/*
-   Dynamic pointer casting. Down an inheritance hierarchy
-*/
-SWIGRUNTIME swig_type_info *
-SWIG_TypeDynamicCast(swig_type_info *ty, void **ptr) {
-  swig_type_info *lastty = ty;
-  if (!ty || !ty->dcast) return ty;
-  while (ty && (ty->dcast)) {
-    ty = (*ty->dcast)(ptr);
-    if (ty) lastty = ty;
-  }
-  return lastty;
-}
-
-/*
-  Return the name associated with this type
-*/
-SWIGRUNTIMEINLINE const char *
-SWIG_TypeName(const swig_type_info *ty) {
-  return ty->name;
-}
-
-/*
-  Return the pretty name associated with this type,
-  that is an unmangled type name in a form presentable to the user.
-*/
-SWIGRUNTIME const char *
-SWIG_TypePrettyName(const swig_type_info *type) {
-  /* The "str" field contains the equivalent pretty names of the
-     type, separated by vertical-bar characters.  We choose
-     to print the last name, as it is often (?) the most
-     specific. */
-  if (!type) return NULL;
-  if (type->str != NULL) {
-    const char *last_name = type->str;
-    const char *s;
-    for (s = type->str; *s; s++)
-      if (*s == '|') last_name = s+1;
-    return last_name;
-  }
-  else
-    return type->name;
-}
-
-/*
-   Set the clientdata field for a type
-*/
-SWIGRUNTIME void
-SWIG_TypeClientData(swig_type_info *ti, void *clientdata) {
-  swig_cast_info *cast = ti->cast;
-  /* if (ti->clientdata == clientdata) return; */
-  ti->clientdata = clientdata;
-
-  while (cast) {
-    if (!cast->converter) {
-      swig_type_info *tc = cast->type;
-      if (!tc->clientdata) {
-	SWIG_TypeClientData(tc, clientdata);
-      }
-    }
-    cast = cast->next;
-  }
-}
-SWIGRUNTIME void
-SWIG_TypeNewClientData(swig_type_info *ti, void *clientdata) {
-  SWIG_TypeClientData(ti, clientdata);
-  ti->owndata = 1;
-}
-
-/*
-  Search for a swig_type_info structure only by mangled name
-  Search is a O(log #types)
-
-  We start searching at module start, and finish searching when start == end.
-  Note: if start == end at the beginning of the function, we go all the way around
-  the circular list.
-*/
-SWIGRUNTIME swig_type_info *
-SWIG_MangledTypeQueryModule(swig_module_info *start,
-                            swig_module_info *end,
-		            const char *name) {
-  swig_module_info *iter = start;
-  do {
-    if (iter->size) {
-      register size_t l = 0;
-      register size_t r = iter->size - 1;
-      do {
-	/* since l+r >= 0, we can (>> 1) instead (/ 2) */
-	register size_t i = (l + r) >> 1;
-	const char *iname = iter->types[i]->name;
-	if (iname) {
-	  register int compare = strcmp(name, iname);
-	  if (compare == 0) {
-	    return iter->types[i];
-	  } else if (compare < 0) {
-	    if (i) {
-	      r = i - 1;
-	    } else {
-	      break;
-	    }
-	  } else if (compare > 0) {
-	    l = i + 1;
-	  }
-	} else {
-	  break; /* should never happen */
-	}
-      } while (l <= r);
-    }
-    iter = iter->next;
-  } while (iter != end);
-  return 0;
-}
-
-/*
-  Search for a swig_type_info structure for either a mangled name or a human readable name.
-  It first searches the mangled names of the types, which is a O(log #types)
-  If a type is not found it then searches the human readable names, which is O(#types).
-
-  We start searching at module start, and finish searching when start == end.
-  Note: if start == end at the beginning of the function, we go all the way around
-  the circular list.
-*/
-SWIGRUNTIME swig_type_info *
-SWIG_TypeQueryModule(swig_module_info *start,
-                     swig_module_info *end,
-		     const char *name) {
-  /* STEP 1: Search the name field using binary search */
-  swig_type_info *ret = SWIG_MangledTypeQueryModule(start, end, name);
-  if (ret) {
-    return ret;
-  } else {
-    /* STEP 2: If the type hasn't been found, do a complete search
-       of the str field (the human readable name) */
-    swig_module_info *iter = start;
-    do {
-      register size_t i = 0;
-      for (; i < iter->size; ++i) {
-	if (iter->types[i]->str && (SWIG_TypeEquiv(iter->types[i]->str, name)))
-	  return iter->types[i];
-      }
-      iter = iter->next;
-    } while (iter != end);
-  }
-
-  /* neither found a match */
-  return 0;
-}
-
-/*
-   Pack binary data into a string
-*/
-SWIGRUNTIME char *
-SWIG_PackData(char *c, void *ptr, size_t sz) {
-  static const char hex[17] = "0123456789abcdef";
-  register const unsigned char *u = (unsigned char *) ptr;
-  register const unsigned char *eu =  u + sz;
-  for (; u != eu; ++u) {
-    register unsigned char uu = *u;
-    *(c++) = hex[(uu & 0xf0) >> 4];
-    *(c++) = hex[uu & 0xf];
-  }
-  return c;
-}
-
-/*
-   Unpack binary data from a string
-*/
-SWIGRUNTIME const char *
-SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
-  register unsigned char *u = (unsigned char *) ptr;
-  register const unsigned char *eu = u + sz;
-  for (; u != eu; ++u) {
-    register char d = *(c++);
-    register unsigned char uu;
-    if ((d >= '0') && (d <= '9'))
-      uu = ((d - '0') << 4);
-    else if ((d >= 'a') && (d <= 'f'))
-      uu = ((d - ('a'-10)) << 4);
-    else
-      return (char *) 0;
-    d = *(c++);
-    if ((d >= '0') && (d <= '9'))
-      uu |= (d - '0');
-    else if ((d >= 'a') && (d <= 'f'))
-      uu |= (d - ('a'-10));
-    else
-      return (char *) 0;
-    *u = uu;
-  }
-  return c;
-}
-
-/*
-   Pack 'void *' into a string buffer.
-*/
-SWIGRUNTIME char *
-SWIG_PackVoidPtr(char *buff, void *ptr, const char *name, size_t bsz) {
-  char *r = buff;
-  if ((2*sizeof(void *) + 2) > bsz) return 0;
-  *(r++) = '_';
-  r = SWIG_PackData(r,&ptr,sizeof(void *));
-  if (strlen(name) + 1 > (bsz - (r - buff))) return 0;
-  strcpy(r,name);
-  return buff;
-}
-
-SWIGRUNTIME const char *
-SWIG_UnpackVoidPtr(const char *c, void **ptr, const char *name) {
-  if (*c != '_') {
-    if (strcmp(c,"NULL") == 0) {
-      *ptr = (void *) 0;
-      return name;
-    } else {
-      return 0;
-    }
-  }
-  return SWIG_UnpackData(++c,ptr,sizeof(void *));
-}
-
-SWIGRUNTIME char *
-SWIG_PackDataName(char *buff, void *ptr, size_t sz, const char *name, size_t bsz) {
-  char *r = buff;
-  size_t lname = (name ? strlen(name) : 0);
-  if ((2*sz + 2 + lname) > bsz) return 0;
-  *(r++) = '_';
-  r = SWIG_PackData(r,ptr,sz);
-  if (lname) {
-    strncpy(r,name,lname+1);
-  } else {
-    *r = 0;
-  }
-  return buff;
-}
-
-SWIGRUNTIME const char *
-SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) {
-  if (*c != '_') {
-    if (strcmp(c,"NULL") == 0) {
-      memset(ptr,0,sz);
-      return name;
-    } else {
-      return 0;
-    }
-  }
-  return SWIG_UnpackData(++c,ptr,sz);
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-/*  Errors in SWIG */
-#define  SWIG_UnknownError    	   -1
-#define  SWIG_IOError        	   -2
-#define  SWIG_RuntimeError   	   -3
-#define  SWIG_IndexError     	   -4
-#define  SWIG_TypeError      	   -5
-#define  SWIG_DivisionByZero 	   -6
-#define  SWIG_OverflowError  	   -7
-#define  SWIG_SyntaxError    	   -8
-#define  SWIG_ValueError     	   -9
-#define  SWIG_SystemError    	   -10
-#define  SWIG_AttributeError 	   -11
-#define  SWIG_MemoryError    	   -12
-#define  SWIG_NullReferenceError   -13
-
-
-
-#ifdef __cplusplus
-/* Needed on some windows machines---since MS plays funny games with the header files under C++ */
-#include <math.h>
-#include <stdlib.h>
-extern "C" {
-#endif
-#include "EXTERN.h"
-#include "perl.h"
-#include "XSUB.h"
-
-/* Add in functionality missing in older versions of Perl. Much of this is based on Devel-PPPort on cpan. */
-
-/* Add PERL_REVISION, PERL_VERSION, PERL_SUBVERSION if missing */
-#ifndef PERL_REVISION
-#  if !defined(__PATCHLEVEL_H_INCLUDED__) && !(defined(PATCHLEVEL) && defined(SUBVERSION))
-#    define PERL_PATCHLEVEL_H_IMPLICIT
-#    include <patchlevel.h>
-#  endif
-#  if !(defined(PERL_VERSION) || (defined(SUBVERSION) && defined(PATCHLEVEL)))
-#    include <could_not_find_Perl_patchlevel.h>
-#  endif
-#  ifndef PERL_REVISION
-#    define PERL_REVISION       (5)
-#    define PERL_VERSION        PATCHLEVEL
-#    define PERL_SUBVERSION     SUBVERSION
-#  endif
-#endif
-
-#if defined(WIN32) && defined(PERL_OBJECT) && !defined(PerlIO_exportFILE)
-#define PerlIO_exportFILE(fh,fl) (FILE*)(fh)
-#endif
-
-#ifndef SvIOK_UV
-# define SvIOK_UV(sv)       (SvIOK(sv) && (SvUVX(sv) == SvIVX(sv)))
-#endif
-
-#ifndef SvUOK
-# define SvUOK(sv)           SvIOK_UV(sv)
-#endif
-
-#if ((PERL_VERSION < 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION <= 5)))
-#  define PL_sv_undef               sv_undef
-#  define PL_na	                    na
-#  define PL_errgv                  errgv
-#  define PL_sv_no                  sv_no
-#  define PL_sv_yes                 sv_yes
-#  define PL_markstack_ptr          markstack_ptr
-#endif
-
-#ifndef IVSIZE
-#  ifdef LONGSIZE
-#    define IVSIZE LONGSIZE
-#  else
-#    define IVSIZE 4 /* A bold guess, but the best we can make. */
-#  endif
-#endif
-
-#ifndef INT2PTR
-#  if (IVSIZE == PTRSIZE) && (UVSIZE == PTRSIZE)
-#    define PTRV                  UV
-#    define INT2PTR(any,d)        (any)(d)
-#  else
-#    if PTRSIZE == LONGSIZE
-#      define PTRV                unsigned long
-#    else
-#      define PTRV                unsigned
-#    endif
-#    define INT2PTR(any,d)        (any)(PTRV)(d)
-#  endif
-
-#  define NUM2PTR(any,d)  (any)(PTRV)(d)
-#  define PTR2IV(p)       INT2PTR(IV,p)
-#  define PTR2UV(p)       INT2PTR(UV,p)
-#  define PTR2NV(p)       NUM2PTR(NV,p)
-
-#  if PTRSIZE == LONGSIZE
-#    define PTR2ul(p)     (unsigned long)(p)
-#  else
-#    define PTR2ul(p)     INT2PTR(unsigned long,p)
-#  endif
-#endif /* !INT2PTR */
-
-#ifndef SvPV_nolen
-# define SvPV_nolen(x) SvPV(x,PL_na)
-#endif
-
-#ifndef get_sv
-#  define get_sv perl_get_sv
-#endif
-
-#ifndef ERRSV
-#  define ERRSV get_sv("@",FALSE)
-#endif
-
-#ifndef pTHX_
-#define pTHX_
-#endif   
-
-#include <string.h>
-#ifdef __cplusplus
-}
-#endif
-
-/* -----------------------------------------------------------------------------
- * error manipulation
- * ----------------------------------------------------------------------------- */
-
-SWIGINTERN const char*
-SWIG_Perl_ErrorType(int code) {
-  switch(code) {
-  case SWIG_MemoryError:
-    return "MemoryError";
-  case SWIG_IOError:
-    return "IOError";
-  case SWIG_RuntimeError:
-    return "RuntimeError";
-  case SWIG_IndexError:
-    return "IndexError";
-  case SWIG_TypeError:
-    return "TypeError";
-  case SWIG_DivisionByZero:
-    return "ZeroDivisionError";
-  case SWIG_OverflowError:
-    return "OverflowError";
-  case SWIG_SyntaxError:
-    return "SyntaxError";
-  case SWIG_ValueError:
-    return "ValueError";
-  case SWIG_SystemError:
-    return "SystemError";
-  case SWIG_AttributeError:
-    return "AttributeError";
-  default:
-    return "RuntimeError";
-  }
-}
-
-
-/* -----------------------------------------------------------------------------
- * perlrun.swg
- *
- * This file contains the runtime support for Perl modules
- * and includes code for managing global variables and pointer
- * type checking.
- * ----------------------------------------------------------------------------- */
-
-#ifdef PERL_OBJECT
-#define SWIG_PERL_OBJECT_DECL CPerlObj *SWIGUNUSEDPARM(pPerl),
-#define SWIG_PERL_OBJECT_CALL pPerl,
-#else
-#define SWIG_PERL_OBJECT_DECL
-#define SWIG_PERL_OBJECT_CALL
-#endif
-
-/* Common SWIG API */
-
-/* for raw pointers */
-#define SWIG_ConvertPtr(obj, pp, type, flags)           SWIG_Perl_ConvertPtr(SWIG_PERL_OBJECT_CALL obj, pp, type, flags)
-#define SWIG_ConvertPtrAndOwn(obj, pp, type, flags,own) SWIG_Perl_ConvertPtrAndOwn(SWIG_PERL_OBJECT_CALL obj, pp, type, flags, own)
-#define SWIG_NewPointerObj(p, type, flags)              SWIG_Perl_NewPointerObj(SWIG_PERL_OBJECT_CALL p, type, flags)
-
-/* for raw packed data */
-#define SWIG_ConvertPacked(obj, p, s, type)             SWIG_Perl_ConvertPacked(SWIG_PERL_OBJECT_CALL obj, p, s, type)
-#define SWIG_NewPackedObj(p, s, type)	                SWIG_Perl_NewPackedObj(SWIG_PERL_OBJECT_CALL p, s, type)
-
-/* for class or struct pointers */
-#define SWIG_ConvertInstance(obj, pptr, type, flags)    SWIG_ConvertPtr(obj, pptr, type, flags)
-#define SWIG_NewInstanceObj(ptr, type, flags)           SWIG_NewPointerObj(ptr, type, flags)
-
-/* for C or C++ function pointers */
-#define SWIG_ConvertFunctionPtr(obj, pptr, type)        SWIG_ConvertPtr(obj, pptr, type, 0)
-#define SWIG_NewFunctionPtrObj(ptr, type)               SWIG_NewPointerObj(ptr, type, 0)
-
-/* for C++ member pointers, ie, member methods */
-#define SWIG_ConvertMember(obj, ptr, sz, ty)            SWIG_ConvertPacked(obj, ptr, sz, ty)
-#define SWIG_NewMemberObj(ptr, sz, type)                SWIG_NewPackedObj(ptr, sz, type)
-
-
-/* Runtime API */
-
-#define SWIG_GetModule(clientdata)                      SWIG_Perl_GetModule(clientdata)
-#define SWIG_SetModule(clientdata, pointer)             SWIG_Perl_SetModule(pointer)
-
-
-/* Error manipulation */
-
-#define SWIG_ErrorType(code)                            SWIG_Perl_ErrorType(code)               
-#define SWIG_Error(code, msg)            		sv_setpvf(get_sv("@", GV_ADD), "%s %s", SWIG_ErrorType(code), msg)
-#define SWIG_fail                        		goto fail						    
-
-/* Perl-specific SWIG API */
-
-#define SWIG_MakePtr(sv, ptr, type, flags)              SWIG_Perl_MakePtr(SWIG_PERL_OBJECT_CALL sv, ptr, type, flags)
-#define SWIG_MakePackedObj(sv, p, s, type)	        SWIG_Perl_MakePackedObj(SWIG_PERL_OBJECT_CALL sv, p, s, type)
-#define SWIG_SetError(str)                              SWIG_Error(SWIG_RuntimeError, str)
-
-
-#define SWIG_PERL_DECL_ARGS_1(arg1)                     (SWIG_PERL_OBJECT_DECL arg1)
-#define SWIG_PERL_CALL_ARGS_1(arg1)                     (SWIG_PERL_OBJECT_CALL arg1)
-#define SWIG_PERL_DECL_ARGS_2(arg1, arg2)               (SWIG_PERL_OBJECT_DECL arg1, arg2)
-#define SWIG_PERL_CALL_ARGS_2(arg1, arg2)               (SWIG_PERL_OBJECT_CALL arg1, arg2)
-
-/* -----------------------------------------------------------------------------
- * pointers/data manipulation
- * ----------------------------------------------------------------------------- */
-
-/* For backward compatibility only */
-#define SWIG_POINTER_EXCEPTION  0
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define SWIG_OWNER   SWIG_POINTER_OWN
-#define SWIG_SHADOW  SWIG_OWNER << 1
-
-#define SWIG_MAYBE_PERL_OBJECT SWIG_PERL_OBJECT_DECL
-
-/* SWIG Perl macros */
-
-/* Macro to declare an XS function */
-#ifndef XSPROTO
-#   define XSPROTO(name) void name(pTHX_ CV* cv)
-#endif
-
-/* Macro to call an XS function */
-#ifdef PERL_OBJECT 
-#  define SWIG_CALLXS(_name) _name(cv,pPerl) 
-#else 
-#  ifndef MULTIPLICITY 
-#    define SWIG_CALLXS(_name) _name(cv) 
-#  else 
-#    define SWIG_CALLXS(_name) _name(PERL_GET_THX, cv) 
-#  endif 
-#endif 
-
-#ifdef PERL_OBJECT
-#define MAGIC_PPERL  CPerlObj *pPerl = (CPerlObj *) this;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-typedef int (CPerlObj::*SwigMagicFunc)(SV *, MAGIC *);
-#ifdef __cplusplus
-}
-#endif
-
-#define SWIG_MAGIC(a,b) (SV *a, MAGIC *b)
-#define SWIGCLASS_STATIC
-
-#else /* PERL_OBJECT */
-
-#define MAGIC_PPERL
-#define SWIGCLASS_STATIC static SWIGUNUSED
-
-#ifndef MULTIPLICITY
-#define SWIG_MAGIC(a,b) (SV *a, MAGIC *b)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-typedef int (*SwigMagicFunc)(SV *, MAGIC *);
-#ifdef __cplusplus
-}
-#endif
-
-#else /* MULTIPLICITY */
-
-#define SWIG_MAGIC(a,b) (struct interpreter *interp, SV *a, MAGIC *b)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-typedef int (*SwigMagicFunc)(struct interpreter *, SV *, MAGIC *);
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* MULTIPLICITY */
-#endif /* PERL_OBJECT */
-
-#  ifdef PERL_OBJECT
-#    define SWIG_croak_null() SWIG_Perl_croak_null(pPerl)
-static void SWIG_Perl_croak_null(CPerlObj *pPerl)
-#  else
-static void SWIG_croak_null()
-#  endif
-{
-  SV *err = get_sv("@", GV_ADD);
-#  if (PERL_VERSION < 6)
-  croak("%_", err);
-#  else
-  if (sv_isobject(err))
-    croak(0);
-  else
-    croak("%s", SvPV_nolen(err));
-#  endif
-}
-
-
-/* 
-   Define how strict is the cast between strings and integers/doubles
-   when overloading between these types occurs.
-   
-   The default is making it as strict as possible by using SWIG_AddCast
-   when needed.
-   
-   You can use -DSWIG_PERL_NO_STRICT_STR2NUM at compilation time to
-   disable the SWIG_AddCast, making the casting between string and
-   numbers less strict.
-
-   In the end, we try to solve the overloading between strings and
-   numerical types in the more natural way, but if you can avoid it,
-   well, avoid it using %rename, for example.
-*/
-#ifndef SWIG_PERL_NO_STRICT_STR2NUM
-# ifndef SWIG_PERL_STRICT_STR2NUM
-#  define SWIG_PERL_STRICT_STR2NUM
-# endif
-#endif
-#ifdef SWIG_PERL_STRICT_STR2NUM
-/* string takes precedence */
-#define SWIG_Str2NumCast(x) SWIG_AddCast(x)  
-#else
-/* number takes precedence */
-#define SWIG_Str2NumCast(x) x
-#endif
-
-
-
-#include <stdlib.h>
-
-SWIGRUNTIME const char *
-SWIG_Perl_TypeProxyName(const swig_type_info *type) {
-  if (!type) return NULL;
-  if (type->clientdata != NULL) {
-    return (const char*) type->clientdata;
-  } 
-  else {
-    return type->name;
-  }
-}
-
-/* Identical to SWIG_TypeCheck, except for strcmp comparison */
-SWIGRUNTIME swig_cast_info *
-SWIG_TypeProxyCheck(const char *c, swig_type_info *ty) {
-  if (ty) {
-    swig_cast_info *iter = ty->cast;
-    while (iter) {
-      if (strcmp(SWIG_Perl_TypeProxyName(iter->type), c) == 0) {
-        if (iter == ty->cast)
-          return iter;
-        /* Move iter to the top of the linked list */
-        iter->prev->next = iter->next;
-        if (iter->next)
-          iter->next->prev = iter->prev;
-        iter->next = ty->cast;
-        iter->prev = 0;
-        if (ty->cast) ty->cast->prev = iter;
-        ty->cast = iter;
-        return iter;
-      }
-      iter = iter->next;
-    }
-  }
-  return 0;
-}
-
-/* Function for getting a pointer value */
-
-SWIGRUNTIME int
-SWIG_Perl_ConvertPtrAndOwn(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *_t, int flags, int *own) {
-  swig_cast_info *tc;
-  void *voidptr = (void *)0;
-  SV *tsv = 0;
-
-  if (own)
-    *own = 0;
-
-  /* If magical, apply more magic */
-  if (SvGMAGICAL(sv))
-    mg_get(sv);
-
-  /* Check to see if this is an object */
-  if (sv_isobject(sv)) {
-    IV tmp = 0;
-    tsv = (SV*) SvRV(sv);
-    if ((SvTYPE(tsv) == SVt_PVHV)) {
-      MAGIC *mg;
-      if (SvMAGICAL(tsv)) {
-        mg = mg_find(tsv,'P');
-        if (mg) {
-          sv = mg->mg_obj;
-          if (sv_isobject(sv)) {
-	    tsv = (SV*)SvRV(sv);
-            tmp = SvIV(tsv);
-          }
-        }
-      } else {
-        return SWIG_ERROR;
-      }
-    } else {
-      tmp = SvIV(tsv);
-    }
-    voidptr = INT2PTR(void *,tmp);
-  } else if (! SvOK(sv)) {            /* Check for undef */
-    *(ptr) = (void *) 0;
-    return SWIG_OK;
-  } else if (SvTYPE(sv) == SVt_RV) {  /* Check for NULL pointer */
-    if (!SvROK(sv)) {
-      /* In Perl 5.12 and later, SVt_RV == SVt_IV, so sv could be a valid integer value.  */
-      if (SvIOK(sv)) {
-        return SWIG_ERROR;
-      } else {
-        /* NULL pointer (reference to undef). */
-        *(ptr) = (void *) 0;
-        return SWIG_OK;
-      }
-    } else {
-      return SWIG_ERROR;
-    }
-  } else {                            /* Don't know what it is */
-    return SWIG_ERROR;
-  }
-  if (_t) {
-    /* Now see if the types match */
-    char *_c = HvNAME(SvSTASH(SvRV(sv)));
-    tc = SWIG_TypeProxyCheck(_c,_t);
-    if (!tc) {
-      return SWIG_ERROR;
-    }
-    {
-      int newmemory = 0;
-      *ptr = SWIG_TypeCast(tc,voidptr,&newmemory);
-      if (newmemory == SWIG_CAST_NEW_MEMORY) {
-        assert(own); /* badly formed typemap which will lead to a memory leak - it must set and use own to delete *ptr */
-        if (own)
-          *own = *own | SWIG_CAST_NEW_MEMORY;
-      }
-    }
-  } else {
-    *ptr = voidptr;
-  }
-
-  /* 
-   *  DISOWN implementation: we need a perl guru to check this one.
-   */
-  if (tsv && (flags & SWIG_POINTER_DISOWN)) {
-    /* 
-     *  almost copy paste code from below SWIG_POINTER_OWN setting
-     */
-    SV *obj = sv;
-    HV *stash = SvSTASH(SvRV(obj));
-    GV *gv = *(GV**)hv_fetch(stash, "OWNER", 5, TRUE);
-    if (isGV(gv)) {
-      HV *hv = GvHVn(gv);
-      /*
-       * To set ownership (see below), a newSViv(1) entry is added. 
-       * Hence, to remove ownership, we delete the entry.
-       */
-      if (hv_exists_ent(hv, obj, 0)) {
-	hv_delete_ent(hv, obj, 0, 0);
-      }
-    }
-  }
-  return SWIG_OK;
-}
-
-SWIGRUNTIME int
-SWIG_Perl_ConvertPtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *_t, int flags) {
-  return SWIG_Perl_ConvertPtrAndOwn(sv, ptr, _t, flags, 0);
-}
-
-SWIGRUNTIME void
-SWIG_Perl_MakePtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void *ptr, swig_type_info *t, int flags) {
-  if (ptr && (flags & (SWIG_SHADOW | SWIG_POINTER_OWN))) {
-    SV *self;
-    SV *obj=newSV(0);
-    HV *hash=newHV();
-    HV *stash;
-    sv_setref_pv(obj, SWIG_Perl_TypeProxyName(t), ptr);
-    stash=SvSTASH(SvRV(obj));
-    if (flags & SWIG_POINTER_OWN) {
-      HV *hv;
-      GV *gv = *(GV**)hv_fetch(stash, "OWNER", 5, TRUE);
-      if (!isGV(gv))
-        gv_init(gv, stash, "OWNER", 5, FALSE);
-      hv=GvHVn(gv);
-      hv_store_ent(hv, obj, newSViv(1), 0);
-    }
-    sv_magic((SV *)hash, (SV *)obj, 'P', Nullch, 0);
-    SvREFCNT_dec(obj);
-    self=newRV_noinc((SV *)hash);
-    sv_setsv(sv, self);
-    SvREFCNT_dec((SV *)self);
-    sv_bless(sv, stash);
-  }
-  else {
-    sv_setref_pv(sv, SWIG_Perl_TypeProxyName(t), ptr);
-  }
-}
-
-SWIGRUNTIMEINLINE SV *
-SWIG_Perl_NewPointerObj(SWIG_MAYBE_PERL_OBJECT void *ptr, swig_type_info *t, int flags) {
-  SV *result = sv_newmortal();
-  SWIG_MakePtr(result, ptr, t, flags);
-  return result;
-}
-
-SWIGRUNTIME void
-SWIG_Perl_MakePackedObj(SWIG_MAYBE_PERL_OBJECT SV *sv, void *ptr, int sz, swig_type_info *type) {
-  char result[1024];
-  char *r = result;
-  if ((2*sz + 1 + strlen(SWIG_Perl_TypeProxyName(type))) > 1000) return;
-  *(r++) = '_';
-  r = SWIG_PackData(r,ptr,sz);
-  strcpy(r,SWIG_Perl_TypeProxyName(type));
-  sv_setpv(sv, result);
-}
-
-SWIGRUNTIME SV *
-SWIG_Perl_NewPackedObj(SWIG_MAYBE_PERL_OBJECT void *ptr, int sz, swig_type_info *type) {
-  SV *result = sv_newmortal();
-  SWIG_Perl_MakePackedObj(result, ptr, sz, type);
-  return result;
-}
-
-/* Convert a packed value value */
-SWIGRUNTIME int
-SWIG_Perl_ConvertPacked(SWIG_MAYBE_PERL_OBJECT SV *obj, void *ptr, int sz, swig_type_info *ty) {
-  swig_cast_info *tc;
-  const char  *c = 0;
-
-  if ((!obj) || (!SvOK(obj))) return SWIG_ERROR;
-  c = SvPV_nolen(obj);
-  /* Pointer values must start with leading underscore */
-  if (*c != '_') return SWIG_ERROR;
-  c++;
-  c = SWIG_UnpackData(c,ptr,sz);
-  if (ty) {
-    tc = SWIG_TypeCheck(c,ty);
-    if (!tc) return SWIG_ERROR;
-  }
-  return SWIG_OK;
-}
-
-
-/* Macros for low-level exception handling */
-#define SWIG_croak(x)    { SWIG_Error(SWIG_RuntimeError, x); SWIG_fail; }
-
-
-typedef XSPROTO(SwigPerlWrapper);
-typedef SwigPerlWrapper *SwigPerlWrapperPtr;
-
-/* Structure for command table */
-typedef struct {
-  const char         *name;
-  SwigPerlWrapperPtr  wrapper;
-} swig_command_info;
-
-/* Information for constant table */
-
-#define SWIG_INT     1
-#define SWIG_FLOAT   2
-#define SWIG_STRING  3
-#define SWIG_POINTER 4
-#define SWIG_BINARY  5
-
-/* Constant information structure */
-typedef struct swig_constant_info {
-    int              type;
-    const char      *name;
-    long             lvalue;
-    double           dvalue;
-    void            *pvalue;
-    swig_type_info **ptype;
-} swig_constant_info;
-
-
-/* Structure for variable table */
-typedef struct {
-  const char   *name;
-  SwigMagicFunc   set;
-  SwigMagicFunc   get;
-  swig_type_info  **type;
-} swig_variable_info;
-
-/* Magic variable code */
-#ifndef PERL_OBJECT
-# ifdef __cplusplus
-#  define swig_create_magic(s,a,b,c) _swig_create_magic(s,const_cast<char*>(a),b,c)
-# else
-#  define swig_create_magic(s,a,b,c) _swig_create_magic(s,(char*)(a),b,c)
-# endif
-# ifndef MULTIPLICITY
-SWIGRUNTIME void _swig_create_magic(SV *sv, char *name, int (*set)(SV *, MAGIC *), int (*get)(SV *,MAGIC *)) 
-# else
-SWIGRUNTIME void _swig_create_magic(SV *sv, char *name, int (*set)(struct interpreter*, SV *, MAGIC *), int (*get)(struct interpreter*, SV *,MAGIC *)) 
-# endif
-#else
-#  define swig_create_magic(s,a,b,c) _swig_create_magic(pPerl,s,a,b,c)
-SWIGRUNTIME void _swig_create_magic(CPerlObj *pPerl, SV *sv, const char *name, int (CPerlObj::*set)(SV *, MAGIC *), int (CPerlObj::*get)(SV *, MAGIC *)) 
-#endif
-{
-  MAGIC *mg;
-  sv_magic(sv,sv,'U',name,strlen(name));
-  mg = mg_find(sv,'U');
-  mg->mg_virtual = (MGVTBL *) malloc(sizeof(MGVTBL));
-  mg->mg_virtual->svt_get = (SwigMagicFunc) get;
-  mg->mg_virtual->svt_set = (SwigMagicFunc) set;
-  mg->mg_virtual->svt_len = 0;
-  mg->mg_virtual->svt_clear = 0;
-  mg->mg_virtual->svt_free = 0;
-}
-
-
-SWIGRUNTIME swig_module_info *
-SWIG_Perl_GetModule(void *SWIGUNUSEDPARM(clientdata)) {
-  static void *type_pointer = (void *)0;
-  SV *pointer;
-
-  /* first check if pointer already created */
-  if (!type_pointer) {
-    pointer = get_sv("swig_runtime_data::type_pointer" SWIG_RUNTIME_VERSION SWIG_TYPE_TABLE_NAME, FALSE | GV_ADDMULTI);
-    if (pointer && SvOK(pointer)) {
-      type_pointer = INT2PTR(swig_type_info **, SvIV(pointer));
-    }
-  }
-
-  return (swig_module_info *) type_pointer;
-}
-
-SWIGRUNTIME void
-SWIG_Perl_SetModule(swig_module_info *module) {
-  SV *pointer;
-
-  /* create a new pointer */
-  pointer = get_sv("swig_runtime_data::type_pointer" SWIG_RUNTIME_VERSION SWIG_TYPE_TABLE_NAME, TRUE | GV_ADDMULTI);
-  sv_setiv(pointer, PTR2IV(module));
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-/* Workaround perl5 global namespace pollution. Note that undefining library
- * functions like fopen will not solve the problem on all platforms as fopen
- * might be a macro on Windows but not necessarily on other operating systems. */
-#ifdef do_open
-  #undef do_open
-#endif
-#ifdef do_close
-  #undef do_close
-#endif
-#ifdef do_exec
-  #undef do_exec
-#endif
-#ifdef scalar
-  #undef scalar
-#endif
-#ifdef list
-  #undef list
-#endif
-#ifdef apply
-  #undef apply
-#endif
-#ifdef convert
-  #undef convert
-#endif
-#ifdef Error
-  #undef Error
-#endif
-#ifdef form
-  #undef form
-#endif
-#ifdef vform
-  #undef vform
-#endif
-#ifdef LABEL
-  #undef LABEL
-#endif
-#ifdef METHOD
-  #undef METHOD
-#endif
-#ifdef Move
-  #undef Move
-#endif
-#ifdef yylex
-  #undef yylex
-#endif
-#ifdef yyparse
-  #undef yyparse
-#endif
-#ifdef yyerror
-  #undef yyerror
-#endif
-#ifdef invert
-  #undef invert
-#endif
-#ifdef ref
-  #undef ref
-#endif
-#ifdef read
-  #undef read
-#endif
-#ifdef write
-  #undef write
-#endif
-#ifdef eof
-  #undef eof
-#endif
-#ifdef close
-  #undef close
-#endif
-#ifdef rewind
-  #undef rewind
-#endif
-#ifdef free
-  #undef free
-#endif
-#ifdef malloc
-  #undef malloc
-#endif
-#ifdef calloc
-  #undef calloc
-#endif
-#ifdef Stat
-  #undef Stat
-#endif
-#ifdef check
-  #undef check
-#endif
-#ifdef seekdir
-  #undef seekdir
-#endif
-#ifdef open
-  #undef open
-#endif
-#ifdef readdir
-  #undef readdir
-#endif
-#ifdef bind
-  #undef bind
-#endif
-#ifdef access
-  #undef access
-#endif
-#ifdef stat
-  #undef stat
-#endif
-
-#ifdef bool
-  /* Leave if macro is from C99 stdbool.h */
-  #ifndef __bool_true_false_are_defined
-    #undef bool
-  #endif
-#endif
-
-
-
-
-#define SWIG_exception_fail(code, msg) do { SWIG_Error(code, msg); SWIG_fail; } while(0) 
-
-#define SWIG_contract_assert(expr, msg) if (!(expr)) { SWIG_Error(SWIG_RuntimeError, msg); SWIG_fail; } else 
-
-
-
-/* -------- TYPES TABLE (BEGIN) -------- */
-
-#define SWIGTYPE_p_char swig_types[0]
-static swig_type_info *swig_types[2];
-static swig_module_info swig_module = {swig_types, 1, 0, 0, 0, 0};
-#define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)
-#define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)
-
-/* -------- TYPES TABLE (END) -------- */
-
-#define SWIG_init    boot_Geo__GDAL__Const
-
-#define SWIG_name   "Geo::GDAL::Constc::boot_Geo__GDAL__Const"
-#define SWIG_prefix "Geo::GDAL::Constc::"
-
-#define SWIGVERSION 0x020012 
-#define SWIG_VERSION SWIGVERSION
-
-
-#define SWIG_as_voidptr(a) (void *)((const void *)(a)) 
-#define SWIG_as_voidptrptr(a) ((void)SWIG_as_voidptr(*a),(void**)(a)) 
-
-
-#ifdef __cplusplus
-extern "C"
-#endif
-#ifndef PERL_OBJECT
-#ifndef MULTIPLICITY
-SWIGEXPORT void SWIG_init (CV* cv);
-#else
-SWIGEXPORT void SWIG_init (pTHXo_ CV* cv);
-#endif
-#else
-SWIGEXPORT void SWIG_init (CV *cv, CPerlObj *);
-#endif
-
-
-#include "gdal.h"
-#include "gdalwarper.h"
-#include "cpl_string.h"
-#include "cpl_minixml.h"
-
-
-SWIGINTERNINLINE SV *
-SWIG_From_long  SWIG_PERL_DECL_ARGS_1(long value)
-{
-  SV *sv;
-  if (value >= IV_MIN && value <= IV_MAX)
-    sv = newSViv(value);
-  else
-    sv = newSVpvf("%ld", value);
-  return sv_2mortal(sv);
-}
-
-
-SWIGINTERNINLINE SV *
-SWIG_From_int  SWIG_PERL_DECL_ARGS_1(int value)
-{    
-  return SWIG_From_long  SWIG_PERL_CALL_ARGS_1(value);
-}
-
-
-SWIGINTERNINLINE SV *
-SWIG_FromCharPtrAndSize(const char* carray, size_t size)
-{
-  SV *obj = sv_newmortal();
-  if (carray) {
-    sv_setpvn(obj, carray, size);
-  } else {
-    sv_setsv(obj, &PL_sv_undef);
-  }
-  return obj;
-}
-
-
-SWIGINTERNINLINE SV * 
-SWIG_FromCharPtr(const char *cptr)
-{ 
-  return SWIG_FromCharPtrAndSize(cptr, (cptr ? strlen(cptr) : 0));
-}
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef PERL_OBJECT
-#define MAGIC_CLASS _wrap_Geo__GDAL__Const_var::
-class _wrap_Geo__GDAL__Const_var : public CPerlObj {
-public:
-#else
-#define MAGIC_CLASS
-#endif
-SWIGCLASS_STATIC int swig_magic_readonly(pTHX_ SV *SWIGUNUSEDPARM(sv), MAGIC *SWIGUNUSEDPARM(mg)) {
-    MAGIC_PPERL
-    croak("Value is read-only.");
-    return 0;
-}
-
-
-#ifdef PERL_OBJECT
-};
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */
-
-static swig_type_info _swigt__p_char = {"_p_char", "char *", 0, 0, (void*)0, 0};
-
-static swig_type_info *swig_type_initial[] = {
-  &_swigt__p_char,
-};
-
-static swig_cast_info _swigc__p_char[] = {  {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}};
-
-static swig_cast_info *swig_cast_initial[] = {
-  _swigc__p_char,
-};
-
-
-/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */
-
-static swig_constant_info swig_constants[] = {
-{0,0,0,0,0,0}
-};
-#ifdef __cplusplus
-}
-#endif
-static swig_variable_info swig_variables[] = {
-{0,0,0,0}
-};
-static swig_command_info swig_commands[] = {
-{0,0}
-};
-/* -----------------------------------------------------------------------------
- * Type initialization:
- * This problem is tough by the requirement that no dynamic
- * memory is used. Also, since swig_type_info structures store pointers to
- * swig_cast_info structures and swig_cast_info structures store pointers back
- * to swig_type_info structures, we need some lookup code at initialization.
- * The idea is that swig generates all the structures that are needed.
- * The runtime then collects these partially filled structures.
- * The SWIG_InitializeModule function takes these initial arrays out of
- * swig_module, and does all the lookup, filling in the swig_module.types
- * array with the correct data and linking the correct swig_cast_info
- * structures together.
- *
- * The generated swig_type_info structures are assigned staticly to an initial
- * array. We just loop through that array, and handle each type individually.
- * First we lookup if this type has been already loaded, and if so, use the
- * loaded structure instead of the generated one. Then we have to fill in the
- * cast linked list. The cast data is initially stored in something like a
- * two-dimensional array. Each row corresponds to a type (there are the same
- * number of rows as there are in the swig_type_initial array). Each entry in
- * a column is one of the swig_cast_info structures for that type.
- * The cast_initial array is actually an array of arrays, because each row has
- * a variable number of columns. So to actually build the cast linked list,
- * we find the array of casts associated with the type, and loop through it
- * adding the casts to the list. The one last trick we need to do is making
- * sure the type pointer in the swig_cast_info struct is correct.
- *
- * First off, we lookup the cast->type name to see if it is already loaded.
- * There are three cases to handle:
- *  1) If the cast->type has already been loaded AND the type we are adding
- *     casting info to has not been loaded (it is in this module), THEN we
- *     replace the cast->type pointer with the type pointer that has already
- *     been loaded.
- *  2) If BOTH types (the one we are adding casting info to, and the
- *     cast->type) are loaded, THEN the cast info has already been loaded by
- *     the previous module so we just ignore it.
- *  3) Finally, if cast->type has not already been loaded, then we add that
- *     swig_cast_info to the linked list (because the cast->type) pointer will
- *     be correct.
- * ----------------------------------------------------------------------------- */
-
-#ifdef __cplusplus
-extern "C" {
-#if 0
-} /* c-mode */
-#endif
-#endif
-
-#if 0
-#define SWIGRUNTIME_DEBUG
-#endif
-
-
-SWIGRUNTIME void
-SWIG_InitializeModule(void *clientdata) {
-  size_t i;
-  swig_module_info *module_head, *iter;
-  int found, init;
-  
-  /* check to see if the circular list has been setup, if not, set it up */
-  if (swig_module.next==0) {
-    /* Initialize the swig_module */
-    swig_module.type_initial = swig_type_initial;
-    swig_module.cast_initial = swig_cast_initial;
-    swig_module.next = &swig_module;
-    init = 1;
-  } else {
-    init = 0;
-  }
-  
-  /* Try and load any already created modules */
-  module_head = SWIG_GetModule(clientdata);
-  if (!module_head) {
-    /* This is the first module loaded for this interpreter */
-    /* so set the swig module into the interpreter */
-    SWIG_SetModule(clientdata, &swig_module);
-    module_head = &swig_module;
-  } else {
-    /* the interpreter has loaded a SWIG module, but has it loaded this one? */
-    found=0;
-    iter=module_head;
-    do {
-      if (iter==&swig_module) {
-        found=1;
-        break;
-      }
-      iter=iter->next;
-    } while (iter!= module_head);
-    
-    /* if the is found in the list, then all is done and we may leave */
-    if (found) return;
-    /* otherwise we must add out module into the list */
-    swig_module.next = module_head->next;
-    module_head->next = &swig_module;
-  }
-  
-  /* When multiple interpreters are used, a module could have already been initialized in
-       a different interpreter, but not yet have a pointer in this interpreter.
-       In this case, we do not want to continue adding types... everything should be
-       set up already */
-  if (init == 0) return;
-  
-  /* Now work on filling in swig_module.types */
-#ifdef SWIGRUNTIME_DEBUG
-  printf("SWIG_InitializeModule: size %d\n", swig_module.size);
-#endif
-  for (i = 0; i < swig_module.size; ++i) {
-    swig_type_info *type = 0;
-    swig_type_info *ret;
-    swig_cast_info *cast;
-    
-#ifdef SWIGRUNTIME_DEBUG
-    printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name);
-#endif
-    
-    /* if there is another module already loaded */
-    if (swig_module.next != &swig_module) {
-      type = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, swig_module.type_initial[i]->name);
-    }
-    if (type) {
-      /* Overwrite clientdata field */
-#ifdef SWIGRUNTIME_DEBUG
-      printf("SWIG_InitializeModule: found type %s\n", type->name);
-#endif
-      if (swig_module.type_initial[i]->clientdata) {
-        type->clientdata = swig_module.type_initial[i]->clientdata;
-#ifdef SWIGRUNTIME_DEBUG
-        printf("SWIG_InitializeModule: found and overwrite type %s \n", type->name);
-#endif
-      }
-    } else {
-      type = swig_module.type_initial[i];
-    }
-    
-    /* Insert casting types */
-    cast = swig_module.cast_initial[i];
-    while (cast->type) {
-      /* Don't need to add information already in the list */
-      ret = 0;
-#ifdef SWIGRUNTIME_DEBUG
-      printf("SWIG_InitializeModule: look cast %s\n", cast->type->name);
-#endif
-      if (swig_module.next != &swig_module) {
-        ret = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, cast->type->name);
-#ifdef SWIGRUNTIME_DEBUG
-        if (ret) printf("SWIG_InitializeModule: found cast %s\n", ret->name);
-#endif
-      }
-      if (ret) {
-        if (type == swig_module.type_initial[i]) {
-#ifdef SWIGRUNTIME_DEBUG
-          printf("SWIG_InitializeModule: skip old type %s\n", ret->name);
-#endif
-          cast->type = ret;
-          ret = 0;
-        } else {
-          /* Check for casting already in the list */
-          swig_cast_info *ocast = SWIG_TypeCheck(ret->name, type);
-#ifdef SWIGRUNTIME_DEBUG
-          if (ocast) printf("SWIG_InitializeModule: skip old cast %s\n", ret->name);
-#endif
-          if (!ocast) ret = 0;
-        }
-      }
-      
-      if (!ret) {
-#ifdef SWIGRUNTIME_DEBUG
-        printf("SWIG_InitializeModule: adding cast %s\n", cast->type->name);
-#endif
-        if (type->cast) {
-          type->cast->prev = cast;
-          cast->next = type->cast;
-        }
-        type->cast = cast;
-      }
-      cast++;
-    }
-    /* Set entry in modules->types array equal to the type */
-    swig_module.types[i] = type;
-  }
-  swig_module.types[i] = 0;
-  
-#ifdef SWIGRUNTIME_DEBUG
-  printf("**** SWIG_InitializeModule: Cast List ******\n");
-  for (i = 0; i < swig_module.size; ++i) {
-    int j = 0;
-    swig_cast_info *cast = swig_module.cast_initial[i];
-    printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name);
-    while (cast->type) {
-      printf("SWIG_InitializeModule: cast type %s\n", cast->type->name);
-      cast++;
-      ++j;
-    }
-    printf("---- Total casts: %d\n",j);
-  }
-  printf("**** SWIG_InitializeModule: Cast List ******\n");
-#endif
-}
-
-/* This function will propagate the clientdata field of type to
-* any new swig_type_info structures that have been added into the list
-* of equivalent types.  It is like calling
-* SWIG_TypeClientData(type, clientdata) a second time.
-*/
-SWIGRUNTIME void
-SWIG_PropagateClientData(void) {
-  size_t i;
-  swig_cast_info *equiv;
-  static int init_run = 0;
-  
-  if (init_run) return;
-  init_run = 1;
-  
-  for (i = 0; i < swig_module.size; i++) {
-    if (swig_module.types[i]->clientdata) {
-      equiv = swig_module.types[i]->cast;
-      while (equiv) {
-        if (!equiv->converter) {
-          if (equiv->type && !equiv->type->clientdata)
-          SWIG_TypeClientData(equiv->type, swig_module.types[i]->clientdata);
-        }
-        equiv = equiv->next;
-      }
-    }
-  }
-}
-
-#ifdef __cplusplus
-#if 0
-{
-  /* c-mode */
-#endif
-}
-#endif
-
-
-
-#ifdef __cplusplus
-extern "C"
-#endif
-
-XS(SWIG_init) {
-  dXSARGS;
-  int i;
-  
-  SWIG_InitializeModule(0);
-  
-  /* Install commands */
-  for (i = 0; swig_commands[i].name; i++) {
-    /* Casts only needed for Perl < 5.10. */
-#ifdef __cplusplus
-    newXS(const_cast<char*>(swig_commands[i].name), swig_commands[i].wrapper, const_cast<char*>(__FILE__));
-#else
-    newXS((char*)swig_commands[i].name, swig_commands[i].wrapper, (char*)__FILE__);
-#endif
-  }
-  
-  /* Install variables */
-  for (i = 0; swig_variables[i].name; i++) {
-    SV *sv;
-    sv = get_sv(swig_variables[i].name, TRUE | 0x2 | GV_ADDMULTI);
-    if (swig_variables[i].type) {
-      SWIG_MakePtr(sv,(void *)1, *swig_variables[i].type,0);
-    } else {
-      sv_setiv(sv,(IV) 0);
-    }
-    swig_create_magic(sv, swig_variables[i].name, swig_variables[i].set, swig_variables[i].get); 
-  }
-  
-  /* Install constant */
-  for (i = 0; swig_constants[i].type; i++) {
-    SV *sv;
-    sv = get_sv(swig_constants[i].name, TRUE | 0x2 | GV_ADDMULTI);
-    switch(swig_constants[i].type) {
-    case SWIG_INT:
-      sv_setiv(sv, (IV) swig_constants[i].lvalue);
-      break;
-    case SWIG_FLOAT:
-      sv_setnv(sv, (double) swig_constants[i].dvalue);
-      break;
-    case SWIG_STRING:
-      sv_setpv(sv, (const char *) swig_constants[i].pvalue);
-      break;
-    case SWIG_POINTER:
-      SWIG_MakePtr(sv, swig_constants[i].pvalue, *(swig_constants[i].ptype),0);
-      break;
-    case SWIG_BINARY:
-      SWIG_MakePackedObj(sv, swig_constants[i].pvalue, swig_constants[i].lvalue, *(swig_constants[i].ptype));
-      break;
-    default:
-      break;
-    }
-    SvREADONLY_on(sv);
-  }
-  
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GDT_Unknown", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDT_Unknown)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GDT_Byte", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDT_Byte)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GDT_UInt16", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDT_UInt16)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GDT_Int16", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDT_Int16)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GDT_UInt32", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDT_UInt32)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GDT_Int32", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDT_Int32)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GDT_Float32", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDT_Float32)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GDT_Float64", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDT_Float64)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GDT_CInt16", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDT_CInt16)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GDT_CInt32", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDT_CInt32)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GDT_CFloat32", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDT_CFloat32)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GDT_CFloat64", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDT_CFloat64)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GDT_TypeCount", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDT_TypeCount)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GA_ReadOnly", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GA_ReadOnly)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GA_Update", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GA_Update)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GF_Read", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GF_Read)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GF_Write", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GF_Write)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GRIORA_NearestNeighbour", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GRIORA_NearestNeighbour)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GRIORA_Bilinear", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GRIORA_Bilinear)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GRIORA_Cubic", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GRIORA_Cubic)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GRIORA_CubicSpline", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GRIORA_CubicSpline)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GRIORA_Lanczos", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GRIORA_Lanczos)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GRIORA_Average", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GRIORA_Average)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GRIORA_Mode", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GRIORA_Mode)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GRIORA_Gauss", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GRIORA_Gauss)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GCI_Undefined", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_Undefined)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GCI_GrayIndex", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_GrayIndex)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GCI_PaletteIndex", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_PaletteIndex)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GCI_RedBand", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_RedBand)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GCI_GreenBand", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_GreenBand)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GCI_BlueBand", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_BlueBand)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GCI_AlphaBand", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_AlphaBand)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GCI_HueBand", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_HueBand)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GCI_SaturationBand", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_SaturationBand)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GCI_LightnessBand", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_LightnessBand)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GCI_CyanBand", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_CyanBand)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GCI_MagentaBand", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_MagentaBand)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GCI_YellowBand", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_YellowBand)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GCI_BlackBand", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_BlackBand)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GCI_YCbCr_YBand", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_YCbCr_YBand)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GCI_YCbCr_CrBand", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_YCbCr_CrBand)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GCI_YCbCr_CbBand", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_YCbCr_CbBand)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GRA_NearestNeighbour", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GRA_NearestNeighbour)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GRA_Bilinear", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GRA_Bilinear)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GRA_Cubic", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GRA_Cubic)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GRA_CubicSpline", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GRA_CubicSpline)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GRA_Lanczos", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GRA_Lanczos)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GRA_Average", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GRA_Average)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GRA_Mode", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GRA_Mode)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GPI_Gray", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GPI_Gray)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GPI_RGB", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GPI_RGB)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GPI_CMYK", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GPI_CMYK)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GPI_HLS", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GPI_HLS)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "CXT_Element", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CXT_Element)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "CXT_Text", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CXT_Text)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "CXT_Attribute", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CXT_Attribute)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "CXT_Comment", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CXT_Comment)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "CXT_Literal", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CXT_Literal)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "CE_None", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CE_None)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "CE_Debug", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CE_Debug)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "CE_Warning", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CE_Warning)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "CE_Failure", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CE_Failure)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "CE_Fatal", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CE_Fatal)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "CPLE_None", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CPLE_None)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "CPLE_AppDefined", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CPLE_AppDefined)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "CPLE_OutOfMemory", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CPLE_OutOfMemory)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "CPLE_FileIO", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CPLE_FileIO)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "CPLE_OpenFailed", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CPLE_OpenFailed)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "CPLE_IllegalArg", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CPLE_IllegalArg)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "CPLE_NotSupported", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CPLE_NotSupported)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "CPLE_AssertionFailed", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CPLE_AssertionFailed)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "CPLE_NoWriteAccess", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CPLE_NoWriteAccess)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "CPLE_UserInterrupt", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CPLE_UserInterrupt)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OF_ALL", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDAL_OF_ALL)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OF_RASTER", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDAL_OF_RASTER)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OF_VECTOR", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDAL_OF_VECTOR)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OF_READONLY", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDAL_OF_READONLY)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OF_UPDATE", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDAL_OF_UPDATE)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OF_SHARED", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDAL_OF_SHARED)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OF_VERBOSE_ERROR", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDAL_OF_VERBOSE_ERROR)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "DMD_LONGNAME", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr(GDAL_DMD_LONGNAME));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "DMD_HELPTOPIC", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr(GDAL_DMD_HELPTOPIC));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "DMD_MIMETYPE", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr(GDAL_DMD_MIMETYPE));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "DMD_EXTENSION", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr(GDAL_DMD_EXTENSION));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "DMD_EXTENSIONS", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr(GDAL_DMD_EXTENSIONS));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "DMD_CONNECTION_PREFIX", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr(GDAL_DMD_CONNECTION_PREFIX));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "DMD_CREATIONOPTIONLIST", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr(GDAL_DMD_CREATIONOPTIONLIST));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "DMD_CREATIONDATATYPES", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr(GDAL_DMD_CREATIONDATATYPES));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "DMD_CREATIONFIELDDATATYPES", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr(GDAL_DMD_CREATIONFIELDDATATYPES));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "DMD_SUBDATASETS", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr(GDAL_DMD_SUBDATASETS));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "DCAP_OPEN", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr(GDAL_DCAP_OPEN));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "DCAP_CREATE", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr(GDAL_DCAP_CREATE));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "DCAP_CREATECOPY", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr(GDAL_DCAP_CREATECOPY));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "DCAP_VIRTUALIO", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr(GDAL_DCAP_VIRTUALIO));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "DCAP_RASTER", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr(GDAL_DCAP_RASTER));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "DCAP_VECTOR", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr(GDAL_DCAP_VECTOR));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "DCAP_NOTNULL_FIELDS", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr(GDAL_DCAP_NOTNULL_FIELDS));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "DCAP_DEFAULT_FIELDS", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr(GDAL_DCAP_DEFAULT_FIELDS));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "DCAP_NOTNULL_GEOMFIELDS", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr(GDAL_DCAP_NOTNULL_GEOMFIELDS));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "CPLES_BackslashQuotable", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CPLES_BackslashQuotable)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "CPLES_XML", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CPLES_XML)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "CPLES_URL", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CPLES_URL)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "CPLES_SQL", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CPLES_SQL)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "CPLES_CSV", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CPLES_CSV)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GFT_Integer", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFT_Integer)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GFT_Real", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFT_Real)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GFT_String", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFT_String)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GFU_Generic", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_Generic)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GFU_PixelCount", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_PixelCount)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GFU_Name", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_Name)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GFU_Min", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_Min)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GFU_Max", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_Max)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GFU_MinMax", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_MinMax)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GFU_Red", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_Red)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GFU_Green", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_Green)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GFU_Blue", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_Blue)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GFU_Alpha", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_Alpha)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GFU_RedMin", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_RedMin)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GFU_GreenMin", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_GreenMin)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GFU_BlueMin", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_BlueMin)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GFU_AlphaMin", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_AlphaMin)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GFU_RedMax", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_RedMax)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GFU_GreenMax", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_GreenMax)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GFU_BlueMax", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_BlueMax)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GFU_AlphaMax", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_AlphaMax)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GFU_MaxCount", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_MaxCount)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GMF_ALL_VALID", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(0x01)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GMF_PER_DATASET", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(0x02)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GMF_ALPHA", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(0x04)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GMF_NODATA", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(0x08)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GARIO_PENDING", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GARIO_PENDING)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GARIO_UPDATE", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GARIO_UPDATE)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GARIO_ERROR", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GARIO_ERROR)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GARIO_COMPLETE", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GARIO_COMPLETE)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GTO_TIP", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GTO_TIP)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GTO_BIT", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GTO_BIT)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "GTO_BSQ", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GTO_BSQ)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  ST(0) = &PL_sv_yes;
-  XSRETURN(1);
-}
-
diff --git a/swig/perl/index.dox b/swig/perl/index.dox
index 0244374..c565ca2 100644
--- a/swig/perl/index.dox
+++ b/swig/perl/index.dox
@@ -2,7 +2,7 @@
 
 \section index_version Version
 
-These pages document the version 2.0 of the GDAL Perl API,
+These pages document the development version of the GDAL Perl API,
 which is extended from the released versions APIs. Old versions: 
 <a href="../1.4/index.html">1.4</a>
 <a href="../1.5/index.html">1.5</a>
@@ -12,6 +12,7 @@ which is extended from the released versions APIs. Old versions:
 <a href="../1.9/index.html">1.9</a>
 <a href="../1.10/index.html">1.10</a>
 <a href="../1.11/index.html">1.11</a>
+<a href="../2.0/index.html">2.0</a>
 
 \section index_intro Introduction
 
@@ -27,6 +28,22 @@ emphasizes the recommended Perl API. Some methods and aliases to
 method names are left out since they may skip some built-in usability
 or other additions.
 
+\subsection usage Usage
+
+\code
+use Geo::GDAL;
+\endcode
+
+Makes all classes available in your Perl program. Some subroutines
+(Driver, Open, BuildVRT) can be imported into the main namespace with
+':all'.
+
+\code
+use Geo::GDAL qw/:all/;
+\endcode
+
+\subsection arguments Arguments
+
 Some arguments are optional and have a default value. This is
 illustrated like this:
 
@@ -72,38 +89,49 @@ $return = $object->method(); # method called in scalar context
 Many of the methods may throw an error, which can be caught by putting
 the call into eval{}; and then examining the contents of $\@.
 
-\section class_methods_vs_object_methods Class methods and attributes vs object methods and attributes 
+\section class_methods_vs_object_methods Modules, package subroutines, class methods, and object methods
+
+Geo::GDAL is the module, which you `use` in your Perl program. A
+module is a file with `.pm` extension. When you `use` the Geo::GDAL
+module, it `use`s other modules. Geo::GDAL modules define several
+packages, also known as namespaces, which are usually but not always
+classes.  Subroutines within packages may either be simply
+subroutines, class methods, or object methods.
 
-Some methods are class methods and some methods are object
-methods. Object methods are always invoked for objects, i.e.
+Objects of a class are often created using the class method `new`
+
+\code
+$object = SomeClass->new();
+\endcode
+
+Object methods in packages are always invoked for objects
 
 \code
 $object->method();
 \endcode
 
-while class methods are invoked either as methods
+while class methods are invoked for classes
 
 \code
 Geo::GDAL::Class->method();
 \endcode
 
-or as subroutines
+and package subroutines are invoked as subroutines in namespaces
 
 \code
 Geo::GDAL::Class::subroutine();
 \endcode
 
-The disctinction between class methods and subroutines is subtle but
-often important. The method invocation passes the class name as the
-first argument while the subroutine invocation does not. Especially
-constructor (new) must be called as a class method.
+The distinction between class methods and package subroutines is
+subtle but often important. The method invocation passes the class
+name as the first argument while the subroutine invocation does
+not. Especially constructor (new) must be called as a class method.
 
 Similar to methods, also attributes are either class attributes or
-object attributes. Class attributes are global variables that are
-associated with a class and object attributes are variables owned by
-each individual object. Class attributes are used for example for
-enumerated values. In some cases object attributes can be accessed
-as hash values
+object attributes. Class attributes are package variables and object
+attributes are variables owned by each individual object. Class
+attributes are used for example for enumerated values. In some cases
+object attributes can be accessed as hash values
 
 \code
 $value = $object->{attribute};
@@ -123,24 +151,50 @@ read-only, and this constraint is enforced using class attributes.
 
 \section index_exceptions Exceptions
 
-Geo::GDAL uses the Perl exception mechanism. This means that
-exceptions that GDAL classifies as failures or fatal errors trigger a
-Perl exception, and an exception that is classified as a warning
-triggers a Perl warning.
+Geo::GDAL uses the Perl exception mechanism. It means that exceptions
+which GDAL classifies as failures trigger a Perl exception, and an
+exception that is classified as a warning triggers a Perl warning.
+Fatal errors trigger a message to standard error and an abort.
+
+All errors are confessed (except those generated by Swig, which are
+croaked) in the Perl bindings, i.e., the Perl stack is included in the
+Perl error message $\@. However, several error messages may be
+generated by GDAL as a result of one call and only the last error
+message is included in $\@. The whole stack of GDAL error messages is
+stored in a package variable \@Geo::GDAL::error. Thus, $\@ and
+\@Geo::GDAL::error give a different insight into the error.  It is
+usually not a good idea to look directly into \@Geo::GDAL::error,
+instead call Geo::GDAL::errstr, which returns the error stack chomped
+and joined into one string.
+
+Note that it is a good idea to call Geo::GDAL::errstr(); before eval
+{}; to clear the error stack.
 
 Perl exceptions can be caught by eval() and Perl warnings can be
 caught by signal \_\_WARN\_\_. Examples:
 
 \code
 eval {
-    $point = Geo::OGR::Geometry->new(WKT=>"POINTXX(1 1)");
+    my $point = Geo::OGR::Geometry->new(WKT=>"POINTXX(1 1)");
 };
-print STDERR "Error: $@";
+say STDERR Geo::GDAL->errstr if $@;
 \endcode
 
-Prints:
+Produces:
 \code
-Error: RuntimeError OGR Error: Unsupported geometry type
+OGR Error: Unsupported geometry type
+\endcode
+
+while
+
+\code
+$point = Geo::OGR::Geometry->new(WKT=>"POINTXX(1 1)");
+\endcode
+
+Produces:
+\code
+OGR Error: Unsupported geometry type at <long path>/OGR.pm line 652.
+	Geo::OGR::Geometry::new("Geo::OGR::Geometry", "WKT", "POINTXX(1 1)") called at foo.pl line 18
 \endcode
 
 and
@@ -156,11 +210,51 @@ Geo::GDAL::GetDriver('GTiff')->Create( Name => 'my.tiff',
                                        Options => { my_unknown_option => 'b' } );
 \endcode
 
-Prints: 
+Produces: 
 \code
 Warning: Driver GTiff does not support my_unknown_option creation option at site/lib/Geo/GDAL.pm line 771.
 \endcode
 
+\subsection cpl_debug Environment variable CPL_DEBUG
+
+Setting $ENV{CPL_DEBUG} to 'ON' makes GDAL verbose about many
+non-fatal things. It may be useful in trying to figure out what is
+going on internally. GDAL uses its normal error mechanism to report
+the debug messages. This means that the messages will end up in
+\@Geo::GDAL::error and can be accessed with Geo::GDAL::errstr. That
+can be changed by calling Geo::GDAL::DontUseExceptions, after which
+all error and debug messages are sent to standard error (STDERR). For
+example
+
+\code
+$ENV{CPL_DEBUG} = 'ON';
+Geo::GDAL::DontUseExceptions;
+my $mp = Geo::OGR::Geometry->new(GeometryType => 'MultiPoint', Points => [[1,1]]);
+$mp->AddGeometry(Geo::OGR::Geometry->new(GeometryType => 'Point'));
+say $mp->As(Format => 'ISO WKT');
+\endcode
+
+Prints
+
+OGR: OGRMultiPoint::exportToWkt() - skipping POINT EMPTY.
+
+to STDERR, and 
+
+MULTIPOINT ((1 1))
+
+to STDOUT.
+
+\section index_named_params Named parameters
+
+Quite many methods and subroutines in Geo::GDAL accept named
+parameters. In all cases the named parameters are handled with the
+same filter, which accepts either a list of parameters (the order is
+the order in which the named parameters are described in this
+documentation), single hash reference, or a list of key value pairs.
+The keys are given in the documentation but the filter ignores case
+and underscores. Thus, although the name of the parameter is
+ProgressData, the method will happily recognize also progress_data.
+
 \section index_progress Progress callback
 
 Some methods accept a callback function for reporting the
@@ -177,6 +271,76 @@ sub progress {
 }
 \endcode
 
+\section index_stdout_redirection Redirecting stdout to a writer object
+
+The Perl bindings takes advantage of the virtual file system of GDAL
+and offers a way to redirect the output from a format driver to a Perl
+object. The object needs to implement \c write and \c close
+methods. \c write is called for each output from the driver with the
+output byte string as an argument. \c close is called when the dataset
+being used in the creation is destroyed. Note that the destruction of
+the dataset may depend on destruction of all objects that depend on
+it. For a simple example see page \ref streaming.
+
+Due to the limitation of the redirection mechanism only one redirection
+may be active at any time.
+
+Note that the return value of the \c write method does not have any
+effect. Internally the return value is set to the length of the byte
+string.
+
+\section index_refcount Reference counting
+
+In GDAL many objects may depend on other objects to exist, for example
+a geometry, which is an attribute of a feature depends on the feature
+to exist when the geometry is accessed. If a feature is destroyed,
+then using a geometry object, which points for its data into the
+feature, will lead to memory error.
+
+GDAL maintains its own reference counting but this is largely lost in
+the bindings.
+
+The Perl bindings attempt to maintain these dependencies by keeping
+the parent objects alive under the hood, independent of their existence 
+in the user space. Thus it is perfectly legal to do something like
+
+\code
+my $layer = Geo::OGR::Driver('Memory')->
+    Create()->
+        CreateLayer(Name => 'layer', 
+                    Fields => [{Name => 'test', Type => 'Integer'}, 
+                               {Name => 'geom', Type => 'Point'}]);
+\endcode
+
+or
+
+\code
+my $geometry;
+{
+    my $feature = $layer->InsertFeature({test => 13, geom => {WKT => 'POINT (10 20)'}});
+    $geometry = $feature->Geometry('geom');
+}
+say $geometry->AsText;
+\endcode
+
+There is at least one caveat. Swig sets the bindings up in such a way
+that the objects are tied hashes. For example a feature can used as a
+hash.
+
+\code
+my $feature = $lauer->InsertFeature({test => 13, geom => {WKT => 'POINT (10 20)'}});
+my $test = $feature->{test};
+\endcode
+
+Due to the mechanism of tied hashes in Perl it is not possible to
+maintain the parent referencing when using this syntax. Thus do not
+use this for subobjects. (In fact it will create an error.)
+
+\code
+my $feature = $lauer->InsertFeature({test => 13, geom => {WKT => 'POINT (10 20)'}});
+my $geom = $feature->{geom}; # will lead to memory error!
+\endcode
+
 \section index_footer Note
 
 This documentation is generated from files within the GDAL
diff --git a/swig/perl/lib/Geo/GDAL.dox b/swig/perl/lib/Geo/GDAL.dox
index e8afbc3..c0b0fa5 100644
--- a/swig/perl/lib/Geo/GDAL.dox
+++ b/swig/perl/lib/Geo/GDAL.dox
@@ -1,10 +1,10 @@
 ## @class Geo::GDAL
 # @brief GDAL utility functions and a root class for raster classes.
 #
-# Geo::GDAL wraps many GDAL utility functions and acts as a root class
-# for all GDAL raster classes. A "raster" is a dataset, whose core is
-# a rectagular grid or grids of pixels, called a "band" in GDAL. Each
-# pixel contains a numeric value of a specific data type
+# Geo::GDAL wraps many GDAL utility functions and is as a root class
+# for all GDAL raster classes. A "raster" is an object, whose core is
+# a rectagular grid of cells, called a "band" in GDAL. Each cell
+# contains a numeric value of a specific data type.
 
 ## @ignore FileFromMemBuffer
 ## @ignore GDALDestroyDriverManager
@@ -21,7 +21,13 @@
 ## @ignore GetLastErrorNo
 ## @ignore GetLastErrorType
 
+## @ignore last_error
+## @ignore error
+## @ignore named_parameters
+## @ignore string2int
+
 ## @ignore GeneralCmdLineProcessor
+## @ignore ParseCommandLine
 
 ## @ignore GetDataTypeName
 ## @ignore GetDataTypeByName
@@ -39,40 +45,120 @@
 ## @ignore ReadDir
 ## @ignore ReadDirRecursive
 ## @ignore Rename
-## @ignore RmDir
 ## @ignore Rmdir
 ## @ignore Stat
 ## @ignore Unlink
+## @ignore VSIStdoutSetRedirection
+## @ignore VSIStdoutUnsetRedirection
+## @ignore Debug
 
 ## @ignore FillNodata
 ## @ignore ContourGenerate
 ## @ignore RegenerateOverviews
 ## @ignore RegenerateOverview
 
-## @cmethod $VersionInfo($request = 'VERSION_NUM')
+## @ignore ApplyGeoTransform
+## @ignore InvGeoTransform
+## @ignore GCPsToGeoTransform
+
+## @ignore make_processing_options
+
+## @ignore_class Geo::GDAL::GDALDEMProcessingOptions
+## @ignore wrapper_GDALDEMProcessing
+
+## @ignore_class Geo::GDAL::GDALGridOptions
+## @ignore wrapper_GDALGrid
+
+## @ignore_class Geo::GDAL::GDALNearblackOptions
+## @ignore wrapper_GDALNearblackDestDS
+## @ignore wrapper_GDALNearblackDestName
+
+## @ignore_class Geo::GDAL::GDALRasterizeOptions
+## @ignore wrapper_GDALRasterizeDestDS
+## @ignore wrapper_GDALRasterizeDestName
+
+## @ignore_class Geo::GDAL::GDALTranslateOptions
+## @ignore wrapper_GDALTranslate
+
+## @ignore_class Geo::GDAL::GDALVectorTranslateOptions
+## @ignore wrapper_GDALVectorTranslateDestDS
+## @ignore wrapper_GDALVectorTranslateDestName
+
+## @ignore_class Geo::GDAL::GDALWarpAppOptions
+## @ignore wrapper_GDALWarpDestDS
+## @ignore wrapper_GDALWarpDestName
+
+## @ignore_class Geo::GDAL::GDALInfoOptions
+## @ignore GDALInfo
+
+## @ignore_class Geo::GDAL::GDALBuildVRTOptions
+## @ignore wrapper_GDALBuildVRT_objects
+## @ignore wrapper_GDALBuildVRT_names
+
+## @ignore ComputeMedianCutPCT
+## @ignore DitherRGB2PCT
+## @ignore ReprojectImage
+## @ignore AutoCreateWarpedVRT
+## @ignore ComputeProximity
+## @ignore RasterizeLayer
+## @ignore Polygonize
+## @ignore FPolygonize
+## @ignore SieveFilter
+
+##### XML is in its own class
+
+## @ignore NodeTypes
+## @ignore NodeType
+## @ignore ParseXMLString
+## @ignore NodeData
+## @ignore Children
+## @ignore Child
+## @ignore SerializeXMLTree
+
+
+## @sub UseExceptions 
+# Use the Perl exception mechanism for GDAL messages (failures are
+# confessed and warnings are warned) and collect the messages
+# into \@Geo::GDAL::error. This is the default.
+
+## @sub DontUseExceptions
+# Do not use the Perl exception mechanism for GDAL messages. Instead
+# the messages are printed to standard error.
+
+## @sub $errstr
+# Clear the error stack and return all generated GDAL error messages in one (possibly multiline) string.
+# @return the chomped error stack joined with newlines.
+
+## @sub $VersionInfo($request = 'VERSION_NUM')
 # @param request A string specifying the request. Currently either
 # "VERSION_NUM", "RELEASE_DATE", "RELEASE_NAME", or
 # "--version". Default is "VERSION_NUM".
 # @return Requested information.
 
-## @cmethod PushFinderLocation($path)
+## @sub PushFinderLocation($path)
 # Add a path to the set of paths from where GDAL support files are
-# sought.
-
-## @cmethod PopFinderLocation()
+# sought. Note that GDAL puts initially into the finder the current
+# directory and value of GDAL_DATA environment variable (if it
+# exists), installation directory (prepended with '/share/gdal' or
+# '/Resources/gdal'), or '/usr/local/share/gdal'. It is usually only
+# needed to add paths to the finder if using an alternate set of data
+# files or a non-installed GDAL is used (as in testing).
+
+## @sub PopFinderLocation()
 # Remove the latest addition from the set of support file search
-# paths.
+# paths. Note that calling this subroutine may remove paths GDAL put
+# into the finder.
 
-## @cmethod FinderClean()
+## @sub FinderClean()
 # Clear the set of support file search paths.
 
-## @cmethod $FindFile($class, $basename)
+## @sub $FindFile($basename)
 # Search for GDAL support files.
 #
 # An example:
 # \code
 # use Geo::GDAL;
-# $a = Geo::GDAL::FindFile('gdal', 'pcs.csv');
+# $a = Geo::GDAL::FindFile('pcs.csv');
 # print STDERR "$a\n";
 # \endcode
 # Prints (for example):
@@ -80,74 +166,63 @@
 # c:\msys\1.0\local\share\gdal\pcs.csv
 # \endcode
 #
-# @param class The class of files to search for. For example 'gdal'.
-# @param basename The basename of the file to search for. For example
-#  'pcs.csv'.
+# @param basename The name of the file to search for. For example
+# 'pcs.csv'.
 # @return the path to the searched file or undef.
 
-## @cmethod SetConfigOption($key, $value)
-# @param key A GDAL config option. Possible values include
-# 'GDAL_FORCE_CACHING', 'USE_RRD', GDAL_DATA', 'GDAL_SKIP',
-# 'GDAL_DRIVER_PATH', 'GDAL_IGNORE_AXIS_ORIENTATION',
-# 'GMLJP2OVERRIDE', 'GDAL_DISABLE_READDIR_ON_OPEN',
-# 'GDAL_PAM_ENABLED', 'GDAL_PAM_MODE', 'GDAL_PAM_PROXY_DIR',
-# 'GDAL_MAX_DATASET_POOL_SIZE', 'GDAL_FORCE_CACHING', 'GDAL_CACHEMAX',
-# 'GDAL_SWATH_SIZE', 'PROJSO', 'CENTER_LONG',
-# 'OGR_DEBUG_ORGANIZE_POLYGONS', 'OGR_ORGANIZE_POLYGONS',
-# and 'GDAL_JP2K_ALT_OFFSETVECTOR_ORDER'.
-# Consult the GDAL main documentation for the semantics of config options.
+## @sub SetConfigOption($key, $value)
+# @param key A GDAL config option.  Consult <a
+# href="https://trac.osgeo.org/gdal/wiki/ConfigOptions">the GDAL
+# documentation</a> for available options and their use.
 # @param value A value for the option, typically 'YES', 'NO',
-# undef, a path, or a filename.
+# undef, path, numeric value, or a filename.
 
-## @cmethod $GetConfigOption($key, $default)
-# @param key A GDAL config option.
-# @param default A default value for the option.
-# @return the value of the GDAL config option or the value of the
-# default parameter.
+## @sub $GetConfigOption($key)
+# @param key A GDAL config option.  Consult <a
+# href="https://trac.osgeo.org/gdal/wiki/ConfigOptions">the GDAL
+# documentation</a> for available options and their use.
+# @return the value of the GDAL config option.
 
-## @ignore ApplyGeoTransform
-## @ignore InvGeoTransform
-## @ignore GCPsToGeoTransform
-
-## @cmethod $GetCacheMax()
+## @sub $GetCacheMax()
 # @return maximum amount of memory (as bytes) for caching within GDAL.
 
-## @cmethod SetCacheMax($Bytes)
+## @sub SetCacheMax($Bytes)
 # @param Bytes New maximum amount of memory for caching within GDAL.
-#
 
-## @cmethod $GetCacheUsed()
+## @sub $GetCacheUsed()
 # @return the amount of memory currently used for caching within GDAL.
 
-## @cmethod @DataTypes()
-# @return a list of GDAL pixel data types. These are currently:
+## @sub @DataTypes()
+# @return a list of GDAL raster cell data types. These are currently:
 # +list Geo::GDAL::Const GDT_ TypeCount
 
-## @cmethod $GetDataTypeSize($DataType)
-# @param DataType A GDAL pixel data type (one of those listed by Geo::GDAL::DataTypes).
+## @sub $GetDataTypeSize($DataType)
+# @param DataType A GDAL raster cell data type (one of those listed by Geo::GDAL::DataTypes).
 # @return the size as the number of bits.
 
-## @cmethod @DataTypeValueRange($DataType)
+## @sub @DataTypeValueRange($DataType)
 # @param DataType Data type (one of those listed by Geo::GDAL::DataTypes).
 # @note Some returned values are inaccurate.
 #
 # @return the minimum, maximum range of the data type.
 
-## @cmethod $DataTypeIsComplex($DataType)
-# @param DataType A GDAL pixel data type (one of those listed by Geo::GDAL::DataTypes).
+## @sub $DataTypeIsComplex($DataType)
+# @param DataType A GDAL raster cell data type (one of those listed by Geo::GDAL::DataTypes).
 # @return true if the data type is a complex number.
 
-## @cmethod @AccessTypes()
+## @sub @OpenFlags()
 # @return a list of GDAL data set open modes. These are currently:
-# +list Geo::GDAL::Const GA_
+# +list Geo::GDAL::Const OF_
 
-## @cmethod @ResamplingTypes()
-# @return a list of GDAL resampling methods.
+## @sub @ResamplingTypes()
+# @return a list of GDAL resampling methods. These are currently:
+# +list Geo::GDAL::Const GRA_
 
-## @cmethod @RIOResamplingTypes()
-# @return a list of GDAL raster IO resampling methods.
+## @sub @RIOResamplingTypes()
+# @return a list of GDAL raster IO resampling methods. These are currently:
+# +list Geo::GDAL::Const GRIORA_
 
-## @cmethod $DecToDMS($angle, $axis, $precision=2)
+## @sub $DecToDMS($angle, $axis, $precision=2)
 # Convert decimal degrees to degrees, minutes, and seconds string
 # @param angle A number
 # @param axis A string specifying latitude or longitude ('Long').
@@ -155,244 +230,110 @@
 # @return a string nndnn'nn.nn'"L where n is a number and L is either
 # N or E
 
-## @cmethod $PackedDMSToDec($packed)
+## @sub $PackedDMSToDec($packed)
 # @param packed DMS as a number DDDMMMSSS.SS
 # @return decimal degrees
 
-## @cmethod $DecToPackedDMS($dec)
+## @sub $DecToPackedDMS($dec)
 # @param dec Decimal degrees
 # @return packed DMS, i.e., a number DDDMMMSSS.SS
 
-## @cmethod @NodeTypes()
-# @return a list of GDAL XML parser node types. These are currently:
-# +list Geo::GDAL::Const CXT_
-
-## @cmethod $NodeType($type)
-# Convert between integer and string expressions of CPLXMLNodeTypes
-# @param type (as integer)
-# @return type (as string)
-
-## @cmethod \@ParseXMLString($XML)
-# Parses a given XML into an array of arrays and returns a reference
-# to that. An array in the structure is: (CPLXMLNodeType, value,
-# child, child, ...). CPLXMLNodeType is an integer.
-# @param XML
-# @return an XMLTree.
-#
-# Example:
-# \code
-open FILE, "data.xml" or die "Couldn't open file: $!"; 
-my $xml = join("", <FILE>); 
-close FILE;
-my $tree = Geo::GDAL::ParseXMLString($xml);
-traverse($tree);
-print Geo::GDAL::SerializeXMLTree($tree),"\n";
- 
-sub traverse {
-.    my $node = shift;
-.    my $type = shift @$node;
-.    my $data = shift @$node;
-.    $type = Geo::GDAL::NodeType($type); 
-.    print "$type, $data\n";
-.    for my $child (@$node) {
-.        traverse($child);
-.    }
-}
-# \endcode
-
-## @cmethod @NodeData($node)
-# @param node
-# @return ($NodeType, $value)
-
-## @cmethod @Children($node)
-# @param node
-# @return
-
-## @cmethod @Child($node, $i)
-# @param node
-# @param i 0 .. number of children - 1
-# @return
-
-## @cmethod $SerializeXMLTree(arrayref XMLTree)
-# @param XMLTree
-# @return XML
-
-## @ignore Drivers
 ## @ignore GetDriverCount
-
-## @cmethod @GetDriverNames()
-# @return a list of the named of all (available and registered) GDAL
-# raster drivers.
-
-## @ignore Driver
+## @ignore GetDriver
 ## @ignore GetDriverByName
-
-## @cmethod Geo::GDAL::Driver GetDriver($name)
-# Create a driver object for the internal GDAL driver.
-# @param name the (short) name of the driver.
-# @return a Geo::GDAL::Driver object, which represents the internal driver.
-
-## @cmethod Geo::GDAL::Driver IdentifyDriver($path, $siblings)
+## @ignore GetDriverNames
+
+## @sub @Drivers()
+# @note Use Geo::OGR::Drivers for vector drivers.
+# @return a list of all available GDAL raster drivers.
+
+## @sub @DriverNames()
+# Available raster format drivers.
+# @note Use Geo::OGR::DriverNames for vector drivers.
+# @return a list of the short names of all available GDAL raster drivers.
+
+## @sub Geo::GDAL::Driver Driver($Name)
+# Access a format driver.
+# @param Name The short name of the driver. One of
+# Geo::GDAL::DriverNames or Geo::OGR::DriverNames.
+# @note This subroutine is imported into the main namespace if Geo::GDAL
+# is used with qw/:all/.
+# @return a Geo::GDAL::Driver object.
+
+## @sub Geo::GDAL::Driver IdentifyDriver($path, $siblings)
 # @param path a dataset path.
-# @param siblings [optional] A list of names of files in the directory
-# specified by the path.
-# @return a Geo::GDAL::Driver object, which represents an internal driver.
-
-## @cmethod ComputeMedianCutPCT(Geo::GDAL::Band red, Geo::GDAL::Band green, Geo::GDAL::Band blue, $num_colors, $colors, subref progress, $progress_data)
-# Compute an "optimal" color table for a three band image.
-# @param red a Geo::GDAL::Band object
-# @param green a Geo::GDAL::Band object
-# @param blue a Geo::GDAL::Band object
-# @param num_colors the desired number of colors 
-# @param colors an empty Geo::GDAL::ColorTable object
-# @param progress [optional] a reference to a subroutine, which will
-# be called with parameters (number progress, string msg, progress_data)
-# @param progress_data [optional]
-#
-# <a href="http://www.gdal.org/gdal__alg_8h.html">Documentation for GDAL algorithms</a>
-
-## @cmethod DitherRGB2PCT($red, $green, $blue, $target, $colors, subref progress, $progress_data)
-# Dither a three band image into one band using a color table.
-# @param red a Geo::GDAL::Band object
-# @param green a Geo::GDAL::Band object
-# @param blue a Geo::GDAL::Band object
-# @param target a Geo::GDAL::Band object
-# @param colors a Geo::GDAL::ColorTable object
-# @param progress [optional] a reference to a subroutine, which will
-# be called with parameters (number progress, string msg, progress_data)
-# @param progress_data [optional]
-#
-# <a href="http://www.gdal.org/gdal__alg_8h.html">Documentation for GDAL algorithms</a>
-
-## @cmethod ReprojectImage($src_ds, $dst_ds, $src_wkt=undef, $dst_wkt=undef, $ResampleAlg='NearestNeighbour', $WarpMemoryLimit=0, $maxerror=0.0, subref progress, $progress_data)
-# @param src_ds Source dataset.
-# @param dst_ds Destination dataset.
-# @param src_wkt Source projection as a WKT.
-# @param dst_wkt Destination projection as a WKT.
-# @param ResampleAlg One of NearestNeighbour Bilinear Cubic or CubicSpline.
-# @param WarpMemoryLimit The amount of memory allowed for caching. Default is 0, i.e., no limit.
-# @param maxerror Maximum error measured in input pixels that is
-# allowed in approximating the transformation. Default is 0.0, i.e.,
-# exact calculations.
-# @param progress [optional] a reference to a subroutine, which will
-# be called with parameters (number progress, string msg, progress_data).
-# Reprojection is terminated if the progress function returns 0.
-# @param progress_data [optional]
-#
-# <a href="http://www.gdal.org/gdalwarper_8h.html">Documentation for GDAL warper</a>
-
-## @cmethod Geo::GDAL::Dataset AutoCreateWarpedVRT(Geo::GDAL::Dataset src, Geo::OSR::SpatialReference src_srs=undef, Geo::OSR::SpatialReference dst_srs=undef, $ResampleAlg='NearestNeighbour', $maxerror=0.0)
-# @param src
-# @param src_srs source projection.
-# @param dst_srs destination projection.
-# @param ResampleAlg one of Geo::GDAL::ResamplingTypes().
-# @param maxerror
-# @return a new Geo::GDAL::Dataset object
-#
-# <a href="http://www.gdal.org/gdalwarper_8h.html">Documentation for GDAL warper</a>
-
-## @cmethod ComputeProximity(Geo::GDAL::Band src, Geo::GDAL::Band proximity, hashref options, subref progress, $progress_data)
-# @param src The raster from which the proximities are computed from.
-# @param proximity The raster to which the proximities are computed to.
-# @param options Options. Supported key, value pairs are 
-# - VALUES => n[,n]* A list of target pixel values to measure the
-# distance from.  If this option is not provided proximity will be
-# computed from non-zero pixel values.  Currently pixel values are
-# internally processed as integers.
-# - DISTUNITS => PIXEL|GEO Indicates whether distances will be
-# computed in pixel units or in georeferenced units.  The default is
-# pixel units.  This also determines the interpretation of MAXDIST.
-# - MAXDIST => n The maximum distance to search.  Proximity distances
-# greater than this value will not be computed.  Instead output pixels
-# will be set to a nodata value.
-# - NODATA => n The NODATA value to use on the output band for pixels
-# that are beyond MAXDIST.  If not provided, the hProximityBand will
-# be queried for a nodata value.  If one is not found, 65535 will be
-# used.
-# - FIXED_BUF_VAL => n If this option is set, all pixels within the
-# MAXDIST threadhold are set to this fixed value instead of to a
-# proximity distance.
-# @param progress [optional] a reference to a subroutine, which will
-# be called with parameters (number progress, string msg, progress_data)
-# @param progress_data [optional]
-#
-# <a href="http://www.gdal.org/gdal__alg_8h.html">Documentation for GDAL algorithms</a>
+# @param siblings [optional] A list of names of files that belong to the data format.
+# @return a Geo::GDAL::Driver.
 
-## @cmethod RasterizeLayer(Geo::GDAL::Dataset ds, arrayref bands, Geo::OGR::Layer layer, $transformer, $arg, arrayref burn_values, hashref options, subref progress, $progress_data)
-# @param ds
-# @param bands A reference to a list of bands to be updated.
-# @param layer
-# @param transformer Not supported, must be undef.
-# @param arg Transformer argument, must be undef.
-# @param burn_values Values to be used for burning the geometries. One for each layer.
-# @param options Not used.
-# @param progress [optional] a reference to a subroutine, which will
-# be called with parameters (number progress, string msg, progress_data)
-# @param progress_data [optional]
-#
-# <a href="http://www.gdal.org/gdal__alg_8h.html">Documentation for GDAL algorithms</a>
-
-## @cmethod Polygonize(Geo::GDAL::Band src, Geo::GDAL::Band mask, Geo::OGR::Layer out, $PixValField, hashref options, subref progress, $progress_data)
-# @param src
-# @param mask All pixels in the mask band with a value other than zero
-# will be considered suitable for collection as polygons. Must be
-# undef if not used.
-# @param out
-# @param PixValField The index (or name) of the field in output layer
-# into which the pixel value of the polygon should be written.
-# @param options Not used.
-# @param progress [optional] a reference to a subroutine, which will
-# be called with parameters (number progress, string msg, progress_data)
-# @param progress_data [optional]
-#
-# <a href="http://www.gdal.org/gdal__alg_8h.html">Documentation for GDAL algorithms</a>
-
-## @cmethod SieveFilter(Geo::GDAL::Band src, Geo::GDAL::Band mask, Geo::GDAL::Band dst, $threshold, $connectedness, hashref options, subref progress, $progress_data)
-# Removes small raster polygons.
-# @param src
-# @param mask
-# @param dst
-# @param threshold An integer.
-# @param connectedness 4 or 8
-# @param options Not used.
-# @param progress [optional] a reference to a subroutine, which will
-# be called with parameters (number progress, string msg, progress_data)
-# @param progress_data [optional]
-#
-# <a href="http://www.gdal.org/gdal__alg_8h.html">Documentation for GDAL algorithms</a>
-
-## @cmethod \@GeneralCmdLineProcessor(arrayref argv, $options = 0)
-# @param argv
-# @param options integer
-# @return arrayref
-
-## @cmethod $PackCharacter($DataType)
+## @sub $PackCharacter($DataType)
 # Get the character that is needed for Perl's pack and unpack when
 # they are used with Geo::GDAL::Band::ReadRaster and
 # Geo::GDAL::Band::WriteRaster. Note that Geo::GDAL::Band::ReadTile
 # and Geo::GDAL::Band::WriteTile have simpler interfaces that do not
 # require pack and unpack.
-# @param DataType A GDAL pixel data type (typically from $band->{DataType}).
+# @param DataType A GDAL raster cell data type, typically from $band->DataType.
 # @return a character which can be used in Perl's pack and unpack.
 
-## @cmethod Geo::GDAL::Dataset Open($name, $access = 'ReadOnly')
+## @ignore AccessTypes
+
+## @sub Geo::GDAL::Dataset Open(%params)
+# Open a dataset.
+# An example, which opens an existing raster dataset for editing:
+# \code
+# use Geo::GDAL qw/:all/;
+# $ds = Open(Name => 'existing.tiff', Access => 'Update');
+# \endcode
+# @param params Named parameters:
+# - \a Name Dataset string (typically a filename). Default is '.'.
+# - \a Access Access type, either 'ReadOnly' or 'Update'. Default is 'ReadOnly'.
+# - \a Type Dataset type, either 'Raster', 'Vector', or 'Any'. Default is 'Any'.
+# - \a Options A hash of GDAL open options passed to candidate drivers. Default is {}.
+# - \a Files A list of names of files that are auxiliary to the main file. Default is [].
+#
+# @note This subroutine is imported into the main namespace if Geo::GDAL
+# is use'd with qw/:all/.
+#
+# @note Some datasets / dataset strings do not explicitly imply the
+# dataset type (for example a PostGIS database). If the type is not
+# specified in such a case the returned dataset may be of either type.
+#
+# @return a new Geo::GDAL::Dataset object if success.
+
+## @sub Geo::GDAL::Dataset OpenShared($name, $access = 'ReadOnly')
+# Open a raster dataset in shared mode.
+# @param name Raster dataset string (typically a filename).
+# @param access Access type, either 'ReadOnly' (the default) or 'Update'.
+# @return a new Geo::GDAL::Dataset object or undef.
+
+## @sub Geo::GDAL::Dataset OpenEx(%params)
+# The generic dataset open method, used internally by all Open and OpenShared methods.
+# @param params Named parameters:
+# - \a Name The name of the data set or source to open. (Default is '.')
+# - \a Flags A list of access mode flags. Available flags are listed by Geo::GDAL::OpenFlags(). (Default is [])
+# - \a Drivers A list of short names of drivers that may be used. Empty list means all. (Default is [])
+# - \a Options A hash of GDAL open options passed to candidate drivers. (Default is {})
+# - \a Files A list of names of files that are auxiliary to the main file. (Default is [])
+#
 # An example
 # \code
-# use Geo::GDAL;
-# $ds = Geo::GDAL::Open('existing.tiff', 'Update');
+# $ds = Geo::GDAL::OpenEx(Name => 'existing.tiff', Flags => [qw/RASTER UPDATE/]);
 # \endcode
-# @param name
-# @param access Access type (one of those listed by Geo::GDAL::AccessTypes).
 # @return a new Geo::GDAL::Dataset object.
 
-## @cmethod Geo::GDAL::Dataset OpenShared($name, $access = 'ReadOnly')
-# @param name
-# @param access Access type (one of those listed by Geo::GDAL::AccessTypes).
-# @return a new Geo::GDAL::Dataset object.
 
-## @cmethod Geo::GDAL::Dataset OpenEx($name, $open_flags = 0, array reference allowed_drivers = undef, array reference open_options = undef, array reference sibling_files = undef);
-# @return a new Geo::GDAL::Dataset object.
 
+## @class Geo::GDAL::XML
+# @brief A simple XML parser
+
+## @method new($string)
+# @param string String containing XML.
+# @return A new Geo::GDAL::XML object, which is a reference to an anonymous array.
+
+## @method traverse(coderef subroutine)
+# @param subroutine Code reference, which will be called for each node in the XML with parameters: node, node_type, node_value. Node type is either Attribute, Comment, Element, Literal, or Text.
+
+## @method serialize()
+# @return The XML serialized into a string.
 
 
 
@@ -405,12 +346,11 @@ sub traverse {
 
 
 
-
 ## @class Geo::GDAL::MajorObject
 # @brief An object, which holds meta data.
 # @isa (Geo::GDAL)
 
-## @cmethod Domains
+## @sub Domains
 # @return the class specific DOMAINS list
 
 ## @method $Description($description)
@@ -447,9 +387,12 @@ sub traverse {
 
 
 ## @class Geo::GDAL::Driver
-# @brief A raster format driver.
+# @brief A driver for a specific dataset format.
 # @isa (Geo::GDAL::MajorObject Geo::GDAL)
 
+## @method Open
+# The same as Geo::GDAL::Open except that only this driver is allowed.
+
 ## @ignore Register
 ## @ignore Deregister
 
@@ -467,7 +410,7 @@ sub traverse {
 # @param NewName String.
 # @param OldName String.
 
-## @method Copy($NewName, $OldName)
+## @method CopyFiles($NewName, $OldName)
 # Copy the files of a dataset.
 # @param NewName String.
 # @param OldName String.
@@ -476,7 +419,7 @@ sub traverse {
 # @return The short name of the driver.
 
 ## @method @Capabilities()
-# @return A list of capabilities. When executed as a class method
+# @return A list of capabilities. When executed as a package subroutine
 # returns a list of all potential capabilities a driver may have. When
 # executed as an object method returns a list of all capabilities the
 # driver has.
@@ -507,36 +450,38 @@ sub traverse {
 # name, type and description or Value. Value is a listref.
 
 ## @method @CreationDataTypes()
-# @return a list of data types that can be used for new datasets.
+# @return a list of data types that can be used for new datasets of this format. A subset of Geo::GDAL::DataTypes
 
 ## @ignore CreateDataset
 
 ## @method Geo::GDAL::Dataset Create(%params)
-# Create a GDAL dataset using this driver.
+# Create a raster dataset using this driver.
 # @note a.k.a. CreateDataset
 #
-# @note As a list the parameters are: Name, Width, Height, NumberOfBands, PixelDataType, Options
-#
-# Create a new Geo::GDAL::Dataset
-# @param params named parameters:
-# - \a Name the name of the dataset (default is 'unnamed').
-# - \a Width the width of the dataset (default is 256).
-# - \a Height the height of the dataset (default is 256).
-# - \a Bands number of bands in the dataset (default is 1).
-# - \a Type the data type of the pixels the dataset (default is 'Byte'). One of Geo::OGR::Driver::CreationDataTypes.
-# - \a Options creation options as a reference to a hash (default is {}).
+# @param params Named parameters:
+# - \a Name The name for the dataset (default is 'unnamed') or an object, which implements write and close.
+# - \a Width The width for the raster dataset (default is 256).
+# - \a Height The height for the raster dataset (default is 256).
+# - \a Bands The number of bands to create into the raster dataset (default is 1).
+# - \a Type The data type for the raster cells (default is 'Byte'). One of Geo::GDAL::Driver::CreationDataTypes.
+# - \a Options Driver creation options as a reference to a hash (default is {}).
 #
-# @return a new Geo::GDAL::Dataset object.
+# @return A new Geo::GDAL::Dataset object.
 
 ## @ignore CreateCopy
 
-## @method Geo::GDAL::Dataset Copy($name, $src, $strict = 1, hashref options = undef)
-# Create a new Geo::GDAL::Dataset as a copy of an existing dataset.
+## @method Geo::GDAL::Dataset Copy(%params)
+# Create a new raster Geo::GDAL::Dataset as a copy of an existing dataset.
 # @note a.k.a. CreateCopy 
-# @param name
-# @param src A Geo::GDAL::Dataset object.
-# @param strict
-# @param options An anonymous hash of driver specific parameters.
+#
+# @param params Named parameters:
+# - \a Name name for the new raster dataset.
+# - \a Src the source Geo::GDAL::Dataset object.
+# - \a Strict 1 (default) if the copy must be strictly equivalent, or 0 if the copy may adapt.
+# - \a Options an anonymous hash of driver specific options.
+# - \a Progress [optional] a reference to a subroutine, which will
+# be called with parameters (number progress, string msg, progress_data).
+# - \a ProgressData [optional]
 # @return a new Geo::GDAL::Dataset object.
 
 ## @method Delete($name)
@@ -546,15 +491,15 @@ sub traverse {
 
 
 ## @class Geo::GDAL::GCP
-# @brief A ground control point for georeferencing images.
+# @brief A ground control point for georeferencing rasters.
 # @isa (Geo::GDAL)
 
 ## @cmethod $new($x = 0.0, $y = 0.0, $z = 0.0, $column = 0.0, $row = 0.0, $info = "", $id = "")
 # @param x projection coordinate
 # @param y projection coordinate
 # @param z projection coordinate
-# @param column pixel x coordinate
-# @param row pixel y coordinate
+# @param column cell x coordinate
+# @param row cell y coordinate
 # @param info informational message
 # @param id unique identifier (string)
 # @return a new Geo::GDAL::GCP object
@@ -569,14 +514,10 @@ sub traverse {
 # projection coordinate (access as $gcp->{Z})
 
 ## @attr Column
-# pixel x coordinate (access as $gcp->{Column})
-# @note Pixel is deprecated.
-#
+# cell x coordinate (access as $gcp->{Column})
 
 ## @attr Row
-# pixel y coordinate (access as $gcp->{Row})
-# @note Line is deprecated.
-#
+# cell y coordinate (access as $gcp->{Row})
 
 ## @attr Info
 # informational message (access as $gcp->{Info})
@@ -588,10 +529,17 @@ sub traverse {
 
 
 ## @class Geo::GDAL::Dataset
-# @brief A set of associated raster bands.
+# @brief A set of associated raster bands or vector layer source.
 # @isa (Geo::GDAL::MajorObject Geo::GDAL)
 
+## @sub Geo::GDAL::Dataset Open
+# The same as Geo::GDAL::Open
+
+## @sub Geo::GDAL::Dataset OpenShared
+# The same as Geo::GDAL::OpenShared
+
 ## @ignore FlushCache
+## @ignore stdout_redirection_wrapper
 
 ## @attr RasterXSize
 # scalar (access as $dataset->{RasterXSize})
@@ -602,21 +550,6 @@ sub traverse {
 ## @attr RasterCount
 # scalar (access as $dataset->{RasterCount})
 
-## @cmethod Geo::GDAL::Dataset Open($name, $access='ReadOnly')
-# An example:
-# \code
-# use Geo::GDAL;
-# $ds = Geo::GDAL::Dataset::Open('/data/dem.tiff', 'Update');
-# \endcode
-# @param name
-# @param access Access type (one of those listed by Geo::GDAL::AccessTypes).
-# @return a new Geo::GDAL::Dataset object.
-
-## @cmethod Geo::GDAL::Dataset OpenShared($name, $access='ReadOnly')
-# @param name
-# @param access Access type (one of those listed by Geo::GDAL::AccessTypes).
-# @return a new Geo::GDAL::Dataset object.
-
 ## @method @GetFileList()
 # @return list of files GDAL believes to be part of this dataset.
 
@@ -624,7 +557,7 @@ sub traverse {
 # @return (width, height)
 
 ## @method Geo::GDAL::Driver GetDriver()
-# @return a new Geo::GDAL::Driver object
+# @return a Geo::GDAL::Driver object that was used to open or create this dataset.
 
 ## @ignore GetRasterBand
 
@@ -637,6 +570,80 @@ sub traverse {
 ## @method @Bands()
 # @return a list of new Geo::GDAL::Band objects
 
+## @ignore GetLayerByIndex
+## @ignore GetLayerByName
+## @ignore Layer
+
+## @method Geo::OGR::Layer GetLayer($name)
+# @param name the name of the requested layer. If not given, then
+# returns the first layer in the data source.
+# @return a new Geo::OGR::Layer object that represents the layer
+# in the data source.
+
+## @ignore GetLayerCount
+## @ignore Layers
+
+## @method @GetLayerNames()
+# @note Delivers the functionality of undocumented method GetLayerCount.
+# @return a list of the names of the layers this data source provides.
+
+## @method Geo::OGR::Layer CreateLayer(%params)
+# @brief Create a new vector layer into this dataset.
+#
+# @param %params Named parameters:
+# - \a Name (scalar) name for the new layer.
+# - \a Fields (array reference) a list of (scalar and geometry) field definitions as in 
+# Geo::OGR::Layer::CreateField.
+# - \a ApproxOK (boolean value, default is true) a flag, which is forwarded to Geo::OGR::Layer::CreateField.
+# - \a Options (hash reference) driver specific hash of layer creation options.
+# - \a Schema (hash reference, deprecated, use \a Fields and \a Name) may contain keys Name, Fields, GeomFields, GeometryType.
+# - \a SRS (scalar, deprecated) the spatial reference for the default geometry field.
+# - \a GeometryType (scalar) the type of the default geometry field
+# (if only one geometry field). Default is 'Unknown'.
+#
+# @note If Fields or Schema|Fields is not given, a default geometry
+# field (Name => '', GeometryType => 'Unknown') is created. If it is
+# given and it contains spatial fields, GeometryType is ignored. The
+# type can be also set with the named parameter.
+#
+# Example:
+# \code
+# my $roads = Geo::OGR::Driver('Memory')->Create('road')->
+# .   CreateLayer(
+# .       Fields => [ { Name => 'class', 
+# .                     Type => 'Integer' },
+# .                   { Name => 'geom', 
+# .                     Type => 'LineString25D' } ] );
+# \endcode
+#
+# @note Many formats allow only one spatial field, which currently
+# requires the use of GeometryType.
+#
+# @return a new Geo::OGR::Layer object.
+
+## @method Geo::OGR::Layer CopyLayer($layer, $name, hashref options = undef)
+# @param layer A Geo::OGR::Layer object to be copied.
+# @param name A name for the new layer.
+# @param options A ref to a hash of format specific options.
+# @return a new Geo::OGR::Layer object.
+
+## @method DeleteLayer($name)
+# Deletes a layer from the data source. Note that if there is a layer
+# object for the deleted layer, it becomes unusable.
+# @param name name of the layer to delete.
+
+## @method Geo::OGR::Layer ExecuteSQL($statement, $geom = undef, $dialect = "")
+# @param statement A SQL statement.
+# @param geom A Geo::OGR::Geometry object.
+# @param dialect
+# @return a new Geo::OGR::Layer object. The data source object will
+# exist as long as the layer object exists.
+
+## @method ReleaseResultSet($layer)
+# @param layer A layer the has been created with ExecuteSQL.
+# @note There is no need to call this method. The result set layer is
+# released in the destructor of the layer that was created with SQL.
+
 ## @ignore GetProjectionRef
 ## @ignore GetProjection
 ## @ignore SetProjection
@@ -654,7 +661,7 @@ sub traverse {
 ## @ignore SetGeoTransform
 
 ## @method Geo::GDAL::GeoTransform GeoTransform(Geo::GDAL::GeoTransform $geo_transform)
-# Transformation from pixel coordinates (column,row) to projection
+# Transformation from cell coordinates (column,row) to projection
 # coordinates (x,y)
 # \code
 # x = geo_transform[0] + column*geo_transform[1] + row*geo_transform[2]
@@ -663,7 +670,7 @@ sub traverse {
 # @param geo_transform [optional]
 # @return the geo transform in a non-void context.
 
-## @method BuildOverviews($resampling, arrayref overviews, subref progress, $progress_data)
+## @method BuildOverviews($resampling, arrayref overviews, coderef progress, $progress_data)
 # @param resampling the resampling method, one of Geo::GDAL::RIOResamplingTypes.
 # @param overviews The list of overview decimation factors to
 # build. For example [2,4,8].
@@ -688,43 +695,43 @@ sub traverse {
 # Write cached data to disk. There is usually no need to call this
 # method.
 
-## @method AddBand($datatype = 'Byte', hashref options = 0)
+## @method AddBand($datatype = 'Byte', hashref options = {})
 # Add a new band to the dataset. The driver must support the action.
-# @param datatype GDAL pixel data type (one of those listed by Geo::GDAL::DataTypes).
-# @param options reference to a hash of format specific key=>value options.
+# @param datatype GDAL raster cell data type (one of those listed by Geo::GDAL::DataTypes).
+# @param options reference to a hash of format specific options.
+# @return The added band.
 
 ## @method WriteRaster(%params)
 # Write data into the dataset. 
 #
-# @param params named parameters. These are
-# - \a XOff x offset (pixel coordinates) (default is 0)
-# - \a YOff y offset (pixel coordinates) (default is 0)
+# @param params Named parameters:
+# - \a XOff x offset (cell coordinates) (default is 0)
+# - \a YOff y offset (cell coordinates) (default is 0)
 # - \a XSize width of the area to write (default is the width of the dataset)
 # - \a YSize height of the area to write (default is the height of the dataset)
-# - \a Buf a buffer containing the data. Create the buffer with \a pack function of Perl. See Geo::GDAL::Band::PackCharacter.
+# - \a Buf a buffer (or a reference to a buffer) containing the data. Create the buffer with \a pack function of Perl. See Geo::GDAL::Band::PackCharacter.
 # - \a BufXSize (default is undef, i.e., the same as XSize)
 # - \a BufYSize (default is undef, i.e., the same as YSize)
 # - \a BufType data type of the buffer (default is the data type of the first band)
-# - \a BandList a reference to an array of band indeces (default is [1])
+# - \a BandList a reference to an array of band indices (default is [1])
 # - \a BufPixelSpace (default is 0)
 # - \a BufLineSpace (default is 0)
 # - \a BufBandSpace (default is 0)
 #
-# If the parameters are given as a list the order is as above.
 # <a href="http://www.gdal.org/classGDALDataset.html">Entry in GDAL docs (method RasterIO)</a>
 
 ## @method $ReadRaster(%params)
 # Read data from the dataset.
 #
-# @param params named parameters. These are
-# - \a XOff x offset (pixel coordinates) (default is 0)
-# - \a YOff y offset (pixel coordinates) (default is 0)
+# @param params Named parameters:
+# - \a XOff x offset (cell coordinates) (default is 0)
+# - \a YOff y offset (cell coordinates) (default is 0)
 # - \a XSize width of the area to read (default is the width of the dataset)
 # - \a YSize height of the area to read (default is the height of the dataset)
 # - \a BufXSize (default is undef, i.e., the same as XSize)
 # - \a BufYSize (default is undef, i.e., the same as YSize)
 # - \a BufType data type of the buffer (default is the data type of the first band)
-# - \a BandList a reference to an array of band indeces (default is [1])
+# - \a BandList a reference to an array of band indices (default is [1])
 # - \a BufPixelSpace (default is 0)
 # - \a BufLineSpace (default is 0)
 # - \a BufBandSpace (default is 0)
@@ -732,13 +739,170 @@ sub traverse {
 # - \a Progress reference to a progress function (default is undef)
 # - \a ProgressData (default is undef)
 #
-# If the parameters are given as a list the order is as above.
 # <a href="http://www.gdal.org/classGDALDataset.html">Entry in GDAL docs (method RasterIO)</a>
 # @return a buffer, open the buffer with \a unpack function of Perl. See Geo::GDAL::Band::PackCharacter.
 
 ## @method CreateMaskBand()
 # Add a mask band to the dataset.
 
+## @method Geo::GDAL::Dataset DEMProcessing($Dest, $Processing, $ColorFilename, $Options, coderef progress, $progress_data)
+# Apply a DEM processing to this dataset.
+# @param Dest Destination raster dataset definition string (typically filename) or an object, which implements write and close.
+# @param Processing Processing to apply, one of "hillshade", "slope", "aspect", "color-relief", "TRI", "TPI", or "Roughness".
+# @param ColorFilename The color palette for color-relief.
+# @param Options A reference to a hash or list of options. For a hash
+# the keys are without the prefix '-'. For example give { of => 'PNG'
+# } to set the output format. For a list the options are given as for
+# the command line utility. See <a
+# href="http://www.gdal.org/gdaldem.html">gdaldem</a> for all options.
+# @param progress [optional] A reference to a subroutine, which will
+# be called with parameters (number progress, string msg, progress_data).
+# @param progress_data [optional]
+#
+
+## @method Geo::GDAL::Dataset Nearblack($Dest, $Options, coderef progress, $progress_data)
+# Convert nearly black/white pixels to black/white.
+# @param Dest Destination raster dataset definition string (typically
+# filename), destination dataset to which to add an alpha or mask
+# band, or an object, which implements write and close.
+# @param Options A reference to a hash or list of options. For a hash
+# the keys are without the prefix '-'. For example give { of => 'PNG'
+# } to set the output format. For a list the options are given as for
+# the command line utility. See <a
+# href="http://www.gdal.org/nearblack.html">nearblack</a> for all
+# options.
+# @return Dataset if destination dataset definition string was given,
+# otherwise a boolean for success/fail but the method croaks if there
+# was an error.
+
+## @method Geo::GDAL::Dataset Translate($Dest, $Options, coderef progress, $progress_data)
+# Convert this dataset into another format.
+# @param Dest Destination dataset definition string (typically
+# filename) or an object, which implements write and close.
+# @param Options A reference to a hash or list of options. For a hash
+# the keys are without the prefix '-'. For example give { of => 'PNG'
+# } to set the output format. For a list the options are given as for
+# the command line utility. See <a
+# href="http://www.gdal.org/gdal_translate.html">gdal_translate</a>
+# and <a href="http://www.gdal.org/ogr2ogr.html">ogr2ogr</a> for all
+# options.
+# @return New dataset object if destination dataset definition
+# string was given, otherwise a boolean for success/fail but the
+# method croaks if there was an error.
+
+## @method Geo::GDAL::Dataset Warped(%params)
+# Create a virtual warped dataset from this dataset.
+#
+# @param params Named parameters:
+# - \a SrcSRS Override the spatial reference system of this dataset if there is one (default is undef).
+# - \a DstSRS The target spatial reference system of the result (default is undef).
+# - \a ResampleAlg The resampling algorithm (default is 'NearestNeighbour').
+# - \a MaxError Maximum error measured in input cellsize that is allowed in approximating the transformation (default is 0 for exact calculations).
+#
+# # <a href="http://www.gdal.org/gdalwarper_8h.html">Documentation for GDAL warper.</a>
+#
+# @return a new Geo::GDAL::Dataset object
+
+## @method Geo::GDAL::Dataset Warp($Dest, $Options, coderef progress, $progress_data)
+# Reproject this dataset.
+# @param Dest Destination raster dataset definition string (typically
+# filename) or an object, which implements write and close.
+# @param Options A reference to a hash or list of options. For a hash
+# the keys are without the prefix '-'. For example give { of => 'PNG'
+# } to set the output format. For a list the options are given as for
+# the command line utility. See <a
+# href="http://www.gdal.org/gdalwarp.html">gdalwarp</a> for
+# all options.
+
+## @method Geo::GDAL::Dataset Grid($Dest, $Options)
+# Creates a regular raster grid from this data source.
+# This is equivalent to the gdal_grid utility.
+# @param Dest Destination raster dataset definition string (typically filename) or an object, which implements write and close.
+# @param Options A reference to a hash or list of options. For a
+# hash the keys are without the prefix '-'. For example give { of =>
+# 'PNG' } to set the output format. You must specify at least layer
+# name (key = l) or SQL to create a layer (key = sql). For a list the
+# options are given as for the command line utility. See 
+# <a href="http://www.gdal.org/gdal_grid.html">gdal_grid</a> for a
+# complete list of options.
+#
+
+## @method Geo::GDAL::Dataset Rasterize($Dest, $Options, coderef progress, $progress_data)
+# Render data from this data source into a raster.
+# @param Dest Destination raster dataset definition string (typically
+# filename), destination dataset, or an object, which implements write and close.
+# @param Options A reference to a hash or list of options. For a hash the keys
+# are without the prefix '-' and the values must be strings. For
+# example give { of => 'PNG' } to set the output format. You must
+# specify at least layer name (key = l) or SQL to create a layer (key
+# = sql). To create a new raster, you need to specify either target
+# resolution (tr => xres,yres) or target file size (ts =>
+# width,height). For a list the options are given as for the command
+# line utility.See <a href="http://www.gdal.org/gdal_rasterize.html">gdal_rasterize</a> for a
+# complete list of options.
+# @return Dataset if destination dataset definition string was given,
+# otherwise a boolean for success/fail but the method croaks if there
+# was an error.
+#
+
+## @method Geo::GDAL::Dataset BuildVRT($Dest, arrayref Sources, $Options, coderef progress, $progress_data)
+# Build a virtual dataset from a set of datasets.
+# @param Dest Destination raster dataset definition string (typically
+# filename), or an object, which implements write and close.
+# @param Sources A list of filenames of input datasets or a list of
+# dataset objects.
+# @param Options A reference to a hash or list of options. For a hash
+# the keys are without the prefix '-' and the values must be
+# strings. For example give { r => 'cubic' } to select a resampling
+# algorithm. For a list the options are given as for the command line
+# utility. See <a
+# href="http://www.gdal.org/gdalbuildvrt.html">gdalbuildvrt</a> for a
+# complete list of options.
+# @return Dataset object
+#
+# @note This subroutine is imported into the main namespace if Geo::GDAL
+# is use'd with qw/:all/.
+
+## @method $Info($Options)
+# Information about this dataset.
+# @param Options A reference to a hash or list of options. For a hash
+# the keys are without the prefix '-'. For example give { JSON => 1 }
+# to set the output format to JSON. For a list the options are given
+# as for the command line utility. See <a
+# href="http://www.gdal.org/gdalinfo.html">gdalinfo</a> for all
+# options.
+
+## @method Geo::GDAL::ColorTable ComputeColorTable(%params)
+# Compute a color table from an RGB image
+# @param params Named parameters:
+# - \a Red The red band, the default is to use the red band of this dataset.
+# - \a Green The green band, the default is to use the green band of this dataset.
+# - \a Blue The blue band, the default is to use the blue band of this dataset.
+# - \a NumColors The number of colors in the computed color table. Default is 256.
+# - \a Progress reference to a progress function (default is undef)
+# - \a ProgressData (default is undef)
+# - \a Method The computation method. The default and currently only option is the median cut algorithm.
+#
+# @return a new color table object.
+
+## @method Geo::GDAL::Band Dither(%params)
+# Compute one band with color table image from an RGB image
+# @params params Named parameters:
+# - \a Red The red band, the default is to use the red band of this dataset.
+# - \a Green The green band, the default is to use the green band of this dataset.
+# - \a Blue The blue band, the default is to use the blue band of this dataset.
+# - \a Dest The destination band. If this is not defined, a new in-memory band (and a dataset) will be created.
+# - \a ColorTable The color table for the result. If this is not defined, and the destination band does not contain one, it will be computed with the ComputeColorTable method.
+# - \a Progress Reference to a progress function (default is undef). Note that if ColorTable is computed using ComputeColorTable method, the progress will run twice from 0 to 1.
+# - \a ProgressData (default is undef)
+#
+# @return the destination band.
+#
+# Usage example. This code converts an RGB JPEG image into a one band PNG image with a color table.
+\code
+my $d = Geo::GDAL::Open('pic.jpg');
+Geo::GDAL::Driver('PNG')->Copy(Name => 'test.png', Src => $d->Dither->Dataset);
+\endcode
 
 
 
@@ -746,11 +910,10 @@ sub traverse {
 # @brief A raster band.
 # @isa ( Geo::GDAL::MajorObject Geo::GDAL )
 
-## @ignore COLOR_INTERPRETATIONS 
-
-## @cmethods ColorInterpretations
+## @sub ColorInterpretations
 # @return a list of types of color interpretation for raster
-# bands.
+# bands. These are currently:
+# +list Geo::GDAL::Const GCI_
 
 ## @attr XSize
 # Object attribute.
@@ -760,23 +923,27 @@ sub traverse {
 # Object attribute.
 # scalar (access as $band->{YSize})
 
+## @ignore GetDataset
+
+## @method Geo::GDAL::Dataset Dataset()
+# @return The dataset which this band belongs to.
+
 ## @ignore GetBand
 
 ## @method $GetBandNumber()
-# @note a.k.a. GetBand
-# @return the number of this band.
+# @return The index of this band in the parent dataset list of bands.
 
 ## @method $DataType()
-# @return the data type of this band (as string, one of Geo::GDAL::DataTypes).
+# @return The data type of this band. One of Geo::GDAL::DataTypes.
 
 ## @method $PackCharacter()
-# @return the character to use in Perl pack and unpack for the DataType of this band.
+# @return The character to use in Perl pack and unpack for the data of this band.
 
 ## @method @Size()
-# @return the size of the band as a list (width, height).
+# @return The size of the band as a list (width, height).
 
 ## @method @GetBlockSize()
-# @return the size of a preferred i/o raster blocks as a list (width,
+# @return The size of a preferred i/o raster blocks as a list (width,
 # height).
 
 ## @ignore GetRasterColorInterpretation
@@ -790,21 +957,24 @@ sub traverse {
 # SetColorInterpretation (set only and requires an integer)
 # @param color_interpretation [optional] new color interpretation, one
 # of Geo::GDAL::Band::ColorInterpretations.
-# @return color interpretation, one of Geo::GDAL::Band::ColorInterpretations.
+# @return The color interpretation of this band. One of Geo::GDAL::Band::ColorInterpretations.
 
 ## @ignore GetNoDataValue
 ## @ignore SetNoDataValue
 
+## @method $DeleteNoDataValue()
+
 ## @method $NoDataValue($NoDataValue)
-# @note a.k.a. GetNoDataValue (get only), SetNoDataValue (set only)
+# Remove no data value from this band.
+
 # @param NoDataValue [optional]
 # Get or set the "no data" value.
-# @note $band->NoDataValue(undef) sets the "no data" value to the Posix
-# floating point maximum.
-# @return the "no data" value in scalar context. In list context
-# returns the no data value or an out of range value and a boolean
-# value, which indicates which is the case (true is first, false is
-# second).
+# @note $band->NoDataValue(undef) sets the "no data" value to the
+# Posix floating point maximum. Use Geo::GDAL::Band::DeleteNoDataValue
+# to remove no data value from this band.
+# @return The "no data" value or undef in scalar context. An undef
+# value indicates that there is no no data value associated with this
+# band.
 
 ## @ignore GetUnitType
 ## @ignore SetUnitType
@@ -821,7 +991,7 @@ sub traverse {
 ## @ignore SetOffset
 
 ## @method ScaleAndOffset($scale, $offset)
-# Scale and offset are used to transform raw pixel values into the
+# Scale and offset are used to transform raw cell values into the
 # units returned by GetUnits(). The conversion function is:
 # \code
 # Units value = (raw value * scale) + offset
@@ -942,37 +1112,36 @@ sub traverse {
 # .    return $_[0] < $_[1] ? $_[0] : $_[1];
 # }
 # \endcode
-# @param xoff
-# @param yoff
-# @param xsize
-# @param ysize
+# @param xoff Number of cell to skip before starting to read from a row. Pixels are read from left to right.
+# @param yoff Number of cells to skip before starting to read from a column. Pixels are read from top to bottom.
+# @param xsize Number of cells to read from each row.
+# @param ysize Number of cells to read from each column.
 # @return a two-dimensional Perl array, organizes as data->[y][x], y =
-# 0..height-1, x = 0..width-1.
+# 0..height-1, x = 0..width-1. I.e., y is row and x is column.
 
 ## @method WriteRaster(%params)
 # Write data into the band.
 #
-# @param params named parameters. These are
-# - \a XOff x offset (pixel coordinates) (default is 0)
-# - \a YOff y offset (pixel coordinates) (default is 0)
+# @param params Named parameters:
+# - \a XOff x offset (cell coordinates) (default is 0)
+# - \a YOff y offset (cell coordinates) (default is 0)
 # - \a XSize width of the area to write (default is the width of the band)
 # - \a YSize height of the area to write (default is the height of the band)
-# - \a Buf a buffer containing the data. Create the buffer with \a pack function of Perl. See Geo::GDAL::Band::PackCharacter.
+# - \a Buf a buffer (or a reference to a buffer) containing the data. Create the buffer with \a pack function of Perl. See Geo::GDAL::Band::PackCharacter.
 # - \a BufXSize (default is undef, i.e., the same as XSize)
 # - \a BufYSize (default is undef, i.e., the same as YSize)
 # - \a BufType data type of the buffer (default is the data type of the band)
 # - \a BufPixelSpace (default is 0)
 # - \a BufLineSpace (default is 0)
 #
-# If the parameters are given as a list the order is as above.
 # <a href="http://www.gdal.org/classGDALDataset.html">Entry in GDAL docs (method RasterIO)</a>
 
 ## @method $ReadRaster(%params)
 # Read data from the band.
 #
-# @param params named parameters. These are
-# - \a XOff x offset (pixel coordinates) (default is 0)
-# - \a YOff y offset (pixel coordinates) (default is 0)
+# @param params Named parameters:
+# - \a XOff x offset (cell coordinates) (default is 0)
+# - \a YOff y offset (cell coordinates) (default is 0)
 # - \a XSize width of the area to read (default is the width of the band)
 # - \a YSize height of the area to read (default is the height of the band)
 # - \a BufXSize (default is undef, i.e., the same as XSize)
@@ -984,7 +1153,6 @@ sub traverse {
 # - \a Progress reference to a progress function (default is undef)
 # - \a ProgressData (default is undef)
 #
-# If the parameters are given as a list the order is as above.
 # <a href="http://www.gdal.org/classGDALDataset.html">Entry in GDAL docs (method RasterIO)</a>
 # @return a buffer, open the buffer with \a unpack function of Perl. See Geo::GDAL::Band::PackCharacter.
 
@@ -1001,45 +1169,46 @@ sub traverse {
 # - \a ApproxOK if histogram can be computed from overviews, default is false
 # - \a Progress an optional progress function, the default is undef
 # - \a ProgressData data for the progress function, the default is undef
+# @note Histogram counts are treated as strings in the bindings to be
+# able to use large integers (if GUIntBig is larger than Perl IV). In
+# practice this is only important if you have a 32 bit machine and
+# very large bucket counts. In those cases it may also be necessary to
+# use Math::BigInt.
 # @return a list which contains the count of values in each bucket
 
-## @method @GetDefaultHistogram($force = 1, subref progress = undef, $progress_data = undef)
+## @method @GetDefaultHistogram($force = 1, coderef progress = undef, $progress_data = undef)
 # @param force true to force the computation
 # @param progress [optional] a reference to a subroutine, which will
 # be called with parameters (number progress, string msg, progress_data)
 # @param progress_data [optional]
+# @note See Note in Geo::GDAL::Band::GetHistogram.
 # @return a list: ($min, $max, arrayref histogram).
 
 ## @method @SetDefaultHistogram($min, $max, $histogram)
 # @param min
 # @param max
+# @note See Note in Geo::GDAL::Band::GetHistogram.
 # @param histogram reference to an array containing the histogram
-#
 
 ## @method FlushCache()
 # Write cached data to disk. There is usually no need to call this
 # method.
 
-## @method Geo::GDAL::ColorTable ColorTable($ColorTable)
-# Get or set the color table of this band.
-# @param ColorTable [optional] a Geo::GDAL::ColorTable object
-# @return a new Geo::GDAL::ColorTable object in a non-void context.
-
 ## @ignore GetRasterColorTable
 ## @ignore SetRasterColorTable
+## @ignore GetColorTable
+## @ignore SetColorTable
 
-## @method Geo::GDAL::ColorTable GetColorTable()
-# @note a.k.a. GetRasterColorTable, see also ColorTable
-# @return a color table object.
-
-## @method SetColorTable($ColorTable)
-# @note a.k.a. SetRasterColorTable, see also ColorTable
-# @param ColorTable A color table object.
-#
+## @method Geo::GDAL::ColorTable ColorTable($ColorTable)
+# Get or set the color table of this band.
+# @param ColorTable [optional] a Geo::GDAL::ColorTable object
+# @return A new Geo::GDAL::ColorTable object which represents the
+# internal color table associated with this band. Returns undef this
+# band does not have an associated color table.
 
-## @cmethod @MaskFlags
+## @sub @MaskFlags
 # @return the list of mask flags. These are
-# - \a AllValid: There are no invalid pixels, all mask values will be 255.
+# - \a AllValid: There are no invalid cell, all mask values will be 255.
 # When used this will normally be the only flag set.
 # - \a PerDataset: The mask band is shared between all bands on the dataset.
 # - \a Alpha: The mask band is actually an alpha band and may have values
@@ -1057,8 +1226,8 @@ sub traverse {
 # band.
 
 ## @method @GetMaskFlags()
-# @return th mask flags of the mask band associated with this
-# band. The flags are Geo::GDAL::Band::MaskFlags.
+# @return the mask flags of the mask band associated with this
+# band. The flags are one or more of Geo::GDAL::Band::MaskFlags.
 
 ## @ignore GetRasterCategoryNames
 ## @ignore SetRasterCategoryNames
@@ -1077,9 +1246,22 @@ sub traverse {
 # @return a new Geo::GDAL::RasterAttributeTable object, whose data is
 # contained within the band.
 
+## @method Geo::OGR::Layer Polygonize(%params)
+# Polygonize this raster band.
+#
+# @param params Named parameters:
+# - \a Mask A raster band, which is used as a mask to select polygonized areas. Default is undef.
+# - \a OutLayer A vector layer into which the polygons are written. If not given, an in-memory layer 'polygonized' is created and returned.
+# - \a PixValField The name of the field in the output layer into which the cell value of the polygon area is stored. Default is 'val'.
+# - \a Options Hash or list of options. Connectedness can be set to 4 to use 4-connectedness, otherwise 8-connectedness is used. ForceIntPixel can be set to 1 to force using a 32 bit int buffer for cell values in the process. If this is not set and the data type of this raster does not fit into a 32 bit int buffer, a 32 bit float buffer is used.
+# - \a Progress Progress function.
+# - \a ProgressData Additional parameter for the progress function.
+#
+# @return Output vector layer.
+
 ## @ignore ContourGenerate
 
-## @method Geo::OGR::Layer Contours($DataSource, hashref LayerConstructor, $ContourInterval, $ContourBase, arrayref FixedLevels, $NoDataValue, $IDField, $ElevField, subref Progress, $ProgressData)
+## @method Geo::OGR::Layer Contours($DataSource, hashref LayerConstructor, $ContourInterval, $ContourBase, arrayref FixedLevels, $NoDataValue, $IDField, $ElevField, coderef Progress, $ProgressData)
 # Generate contours for this raster band. This method can also be used with named parameters.
 # @note This method is a wrapper for ContourGenerate.
 #
@@ -1104,13 +1286,14 @@ sub traverse {
 # @param progress_data [optional]
 # @return
 
-## @method FillNodata($mask, $max_search_dist, $smoothing_iterations, $options, subref progress, $progress_data)
-# Interpolate values for pixels in this raster. The pixels to fill
+## @ignore FillNodata
+
+## @method FillNoData($mask, $max_search_dist, $smoothing_iterations, $options, coderef progress, $progress_data)
+# Interpolate values for cells in this raster. The cells to fill
 # should be marked in the mask band with zero.
-# @note This is a wrapper for Geo::GDAL::FillNodata.
 #
-# @param mask [optional] a mask band indicating pixels to be interpolated (zero valued) (default is to get it with Geo::GDAL::Band::GetMaskBand).
-# @param max_search_dist [optional] the maximum number of pixels to
+# @param mask [optional] a mask band indicating cells to be interpolated (zero valued) (default is to get it with Geo::GDAL::Band::GetMaskBand).
+# @param max_search_dist [optional] the maximum number of cells to
 # search in all directions to find values to interpolate from (default is 10).
 # @param smoothing_iterations [optional] the number of 3x3 smoothing filter passes to run (0 or more) (default is 0).
 # @param options [optional] A reference to a hash. No options have been defined so far for this algorithm (default is {}).
@@ -1120,7 +1303,7 @@ sub traverse {
 #
 # <a href="http://www.gdal.org/gdal__alg_8h.html">Documentation for GDAL algorithms</a>
 
-## @method RegenerateOverviews(arrayref overviews, $resampling, subref progress, $progress_data)
+## @method RegenerateOverviews(arrayref overviews, $resampling, coderef progress, $progress_data)
 # @todo This is not yet available
 #
 # @param overviews a list of Geo::GDAL::Band objects for the overviews.
@@ -1129,74 +1312,98 @@ sub traverse {
 # be called with parameters (number progress, string msg, progress_data)
 # @param progress_data [optional]
 
-## @method RegenerateOverview(Geo::GDAL::Band overview, $resampling, subref progress, $progress_data)
+## @method RegenerateOverview(Geo::GDAL::Band overview, $resampling, coderef progress, $progress_data)
 # @param overview a Geo::GDAL::Band object for the overview.
 # @param resampling [optional] the resampling method (one of Geo::GDAL::RIOResamplingTypes) (default is Average).
 # @param progress [optional] a reference to a subroutine, which will
 # be called with parameters (number progress, string msg, progress_data)
 # @param progress_data [optional]
 
+## @method Geo::GDAL::Band Sieve(%params)
+# Remove small areas by merging them into the largest neighbour area.
+# @param params Named parameters:
+# - \a Mask A raster band, which is used as a mask to select sieved areas. Default is undef.
+# - \a Dest A raster band into which the result is written. If not given, an new in-memory raster band is created and returned.
+# - \a Threshold The smallest area size (in number of cells) which are not sieved away.
+# - \a Options Hash or list of options. {Connectedness => 4} can be specified to use 4-connectedness, otherwise 8-connectedness is used.
+# - \a Progress Progress function.
+# - \a ProgressData Additional parameter for the progress function.
+#
+# @return The filtered raster band.
+
+## @method Geo::GDAL::Band Distance(%params)
+# Compute distances to specific cells of this raster.
+# @param params Named parameters:
+# - \a Distance A raster band, into which the distances are computed. If not given, a not given, a new in-memory raster band is created and returned. The data type of the raster can be given in the options.
+# - \a Options Hash of options. Options are:
+#   - \a Values A list of cell values in this band to measure the distance from. If this option is not provided, the distance will be computed to non-zero pixel values. Currently pixel values are internally processed as integers.
+#   - \a DistUnits=PIXEL|GEO Indicates whether distances will be computed in cells or in georeferenced units. The default is pixel units. This also determines the interpretation of MaxDist.
+#   - \a MaxDist=n The maximum distance to search. Distances greater than this value will not be computed. Instead output cells will be set to a nodata value.
+#   - \a NoData=n The nodata value to use on the distance band for cells that are beyond MaxDist. If not provided, the distance band will be queried for a nodata value. If one is not found, 65535 will be used (255 if the type is Byte).
+#   - \a Use_Input_NoData=YES|NO If this option is set, the nodata value of this band will be respected. Leaving nodata cells in the input as nodata pixels in the distance raster.
+#   - \a Fixed_Buf_Val=n If this option is set, all cells within the MaxDist threshold are set to this value instead of the distance value.
+#   - \a DataType The data type for the result if it is not given.
+# - \a Progress Progress function.
+# - \a ProgressData Additional parameter for the progress function.
+#
+# @note This GDAL function behind this API is called GDALComputeProximity.
+#
+# @return The distance raster.
 
 
 
 ## @class Geo::GDAL::ColorTable
-# @brief A color table in a raster band.
+# @brief A color table from a raster band or a color table, which can be used for a band.
 # @isa ( Geo::GDAL::MajorObject Geo::GDAL )
 
 ## @cmethod Geo::GDAL::ColorTable new($GDALPaletteInterp = 'RGB')
-#
-# Usage:
-# \code
-# $ct = Geo::GDAL::ColorTable->new(...arguments...);
-# \endcode
+# Create a new empty color table.
 # @return a new Geo::GDAL::ColorTable object
 
 ## @method Geo::GDAL::ColorTable Clone()
+# Clone an existing color table.
 # @return a new Geo::GDAL::ColorTable object
 
 ## @method $GetPaletteInterpretation()
-# @return paletter interpretation (string)
+# @return palette interpretation (string)
 
 ## @method $GetCount()
-# @return scalar (count of color entries as int)
-
-## @method @ColorTable(@colortable)
-# Get or set the table of color entries.
-# @param colortable [optional]
-# @return a table of color entries (a list of lists) in a non void context
-
-## @method @ColorEntries(@color_entries)
-# Get or set the table of color entries.
-# @deprecated use Geo::GDAL::ColorTable::ColorTable
-#
-# @param color_entries [optional]
-# @return a table of color entries (a list of lists) in a non void context
-
-## @method @ColorEntry($i, @color)
-# Get or set a color entry.
-# @param i
-# @param color [optional]
-# @return a color entry
-
-## @method @GetColorEntry($i)
-# @param i
-# @return array ColorEntry = ($c1, $c2, $c3, $c4)
-
-## @method @GetColorEntryAsRGB($i)
-# @param i
-# @return array ColorEntry = ($r, $g, $b, $alpha)
-
-## @method SetColorEntry($index, @ColorEntry)
-# @param index
-# @param ColorEntry a list or a reference to an array
-#
+# @return The number of colors in this color table.
+
+## @ignore ColorEntries
+## @ignore ColorTable
+
+## @method @Colors(@colors)
+# Get or set the colors in this color table.
+# @note The color table will expand to the size of the input list but
+# it will not shrink.
+# @param colors [optional] A list of all colors (a list of lists) for this color table.
+# @return A list of colors (a list of lists).
+
+## @ignore GetColorEntry
+## @ignore GetColorEntryAsRGB
+## @ignore SetColorEntry
+## @ignore ColorEntry
+
+## @method @Color($index, @color)
+# Get or set a color in this color table.
+# @param index The index of the color in the table. Note that the
+# color table may expand if the index is larger than the current max
+# index of this table and a color is given. An attempt to retrieve a
+# color out of the current size of the table causes an error.
+# @param color [optional] The color, either a list or a reference to a
+# list. If the list is too short or has undef values, the undef values
+# are taken as 0 except for alpha, which is taken as 255.
+# @note A color is an array of four integers having a value between 0
+# and 255: (gray, red, cyan or hue; green, magenta, or lightness;
+# blue, yellow, or saturation; alpha or blackband)
+# @return A color, in list context a list and in scalar context a reference to an anonymous array.
 
 ## @method CreateColorRamp($start_index, arrayref start_color, $end_index, arrayref end_color)
 # @param start_index
 # @param start_color
 # @param end_index
 # @param end_color
-#
 
 
 
@@ -1208,10 +1415,10 @@ sub traverse {
 ## @cmethod Geo::GDAL::RasterAttributeTable new()
 # @return a new Geo::GDAL::RasterAttributeTable object
 
-## @cmethod @FieldTypes()
+## @sub @FieldTypes()
 # @return
 
-## @cmethod @FieldUsages()
+## @sub @FieldUsages()
 # @return
 
 ## @method Geo::GDAL::RasterAttributeTable Clone()
@@ -1254,7 +1461,7 @@ sub traverse {
 # @return
 
 ## @method $GetRowOfValue($value)
-# @param value a pixel value
+# @param value a cell value
 # @return row index or -1
 
 ## @method $Value($row, $column, $value)
@@ -1300,8 +1507,8 @@ sub traverse {
 ## @ignore SetLinearBinning
 
 ## @method LinearBinning($Row0MinIn, $BinSizeIn)
-# @param Row0MinIn [optional] the lower bound (pixel value) of the first category.
-# @param BinSizeIn [optional] the width of each category (in pixel value units).
+# @param Row0MinIn [optional] the lower bound (cell value) of the first category.
+# @param BinSizeIn [optional] the width of each category (in cell value units).
 # @return ($Row0MinIn, $BinSizeIn) or an empty list if LinearBinning is not set.
 
 
@@ -1320,7 +1527,7 @@ sub traverse {
 # @brief A GDAL virtual file system.
 # @isa = ( Geo::GDAL )
 
-## @cmethod Geo::GDAL::VSIF Open($filename, $mode)
+## @sub Geo::GDAL::VSIF Open($filename, $mode)
 # @param filename Name of the file to open. For example "/vsimem/x".
 # @param mode Access mode. 'r', 'r+', 'w', etc.
 # @return A file handle on success.
@@ -1341,38 +1548,39 @@ sub traverse {
 
 ## @method Truncate($new_size)
 
-## @cmethod @ReadDir($dir)
+## @sub @ReadDir($dir)
 # @return Contents of a directory in an anonymous array or as a list.
 
-## @cmethod $ReadDirRecursive($dir)
+## @sub $ReadDirRecursive($dir)
+# @note Give the directory in the form '/vsimem', i.e., without trailing '/'.
 # @return Contents of a directory tree in an anonymous array.
 
-## @cmethod @Stat($filename)
+## @sub @Stat($filename)
 # @return ($filemode, $filesize). filemode is f for a plain file, d
 # for a directory, l for a symbolic link, p for a named pipe (FIFO), S
 # for a socket, b for a block special file, and c for a character
 # special file.
 
-## @cmethod Unlink($filename)
+## @sub Unlink($filename)
 # @param filename The file to delete.
 # @return 0 on success and -1 on an error.
 
 ## @ignore Mkdir
 
-## @cmethod Mkdir($path, $mode)
+## @sub MkDir($path)
 # Make a directory.
+# @param path The directory to make.
 # @note The name of this method is VSIMkdir in GDAL.
-#
 
-## @cmethod Rmdir($path)
+## @ignore Rmdir
+
+## @sub RmDir($path)
 # Remove a directory.
 # @note The name of this method is VSIRmdir in GDAL.
-#
 
-## @cmethod Rename($old, $new)
+## @sub Rename($old, $new)
 # Rename a file.
 # @note The name of this method is VSIRename in GDAL.
-#
 
 
 
@@ -1386,10 +1594,10 @@ sub traverse {
 # y = d + column * e + row * f
 # \endcode
 # where<br/>
-# (column,row) is the location in pixel coordinates<br/>
+# (column,row) is the location in cell coordinates<br/>
 # (x,y) is the location in projection coordinates<br/>
 # or vice versa.
-# A Geo::GDAL::GeoTransform object is a reference to an anonymous array.
+# A Geo::GDAL::GeoTransform object is a reference to an anonymous array [a,b,c,d,e,f].
 # @isa = ( Geo::GDAL )
 
 ## @cmethod new(@coeffs)
diff --git a/swig/perl/lib/Geo/GDAL.pm b/swig/perl/lib/Geo/GDAL.pm
deleted file mode 100644
index 0d2753c..0000000
--- a/swig/perl/lib/Geo/GDAL.pm
+++ /dev/null
@@ -1,2071 +0,0 @@
-# This file was automatically generated by SWIG (http://www.swig.org).
-# Version 2.0.12
-#
-# Do not make changes to this file unless you know what you are doing--modify
-# the SWIG interface file instead.
-
-package Geo::GDAL;
-use base qw(Exporter);
-use base qw(DynaLoader);
-require Geo::OGR;
-require Geo::OSR;
-package Geo::GDALc;
-bootstrap Geo::GDAL;
-package Geo::GDAL;
- at EXPORT = qw();
-
-# ---------- BASE METHODS -------------
-
-package Geo::GDAL;
-
-sub TIEHASH {
-    my ($classname,$obj) = @_;
-    return bless $obj, $classname;
-}
-
-sub CLEAR { }
-
-sub FIRSTKEY { }
-
-sub NEXTKEY { }
-
-sub FETCH {
-    my ($self,$field) = @_;
-    my $member_func = "swig_${field}_get";
-    $self->$member_func();
-}
-
-sub STORE {
-    my ($self,$field,$newval) = @_;
-    my $member_func = "swig_${field}_set";
-    $self->$member_func($newval);
-}
-
-sub this {
-    my $ptr = shift;
-    return tied(%$ptr);
-}
-
-
-# ------- FUNCTION WRAPPERS --------
-
-package Geo::GDAL;
-
-*callback_d_cp_vp = *Geo::GDALc::callback_d_cp_vp;
-*UseExceptions = *Geo::GDALc::UseExceptions;
-*DontUseExceptions = *Geo::GDALc::DontUseExceptions;
-*Debug = *Geo::GDALc::Debug;
-*SetErrorHandler = *Geo::GDALc::SetErrorHandler;
-*Error = *Geo::GDALc::Error;
-*GOA2GetAuthorizationURL = *Geo::GDALc::GOA2GetAuthorizationURL;
-*GOA2GetRefreshToken = *Geo::GDALc::GOA2GetRefreshToken;
-*GOA2GetAccessToken = *Geo::GDALc::GOA2GetAccessToken;
-*PushErrorHandler = *Geo::GDALc::PushErrorHandler;
-*PopErrorHandler = *Geo::GDALc::PopErrorHandler;
-*ErrorReset = *Geo::GDALc::ErrorReset;
-*EscapeString = *Geo::GDALc::EscapeString;
-*GetLastErrorNo = *Geo::GDALc::GetLastErrorNo;
-*GetLastErrorType = *Geo::GDALc::GetLastErrorType;
-*GetLastErrorMsg = *Geo::GDALc::GetLastErrorMsg;
-*PushFinderLocation = *Geo::GDALc::PushFinderLocation;
-*PopFinderLocation = *Geo::GDALc::PopFinderLocation;
-*FinderClean = *Geo::GDALc::FinderClean;
-*FindFile = *Geo::GDALc::FindFile;
-*ReadDir = *Geo::GDALc::ReadDir;
-*ReadDirRecursive = *Geo::GDALc::ReadDirRecursive;
-*SetConfigOption = *Geo::GDALc::SetConfigOption;
-*GetConfigOption = *Geo::GDALc::GetConfigOption;
-*CPLBinaryToHex = *Geo::GDALc::CPLBinaryToHex;
-*CPLHexToBinary = *Geo::GDALc::CPLHexToBinary;
-*FileFromMemBuffer = *Geo::GDALc::FileFromMemBuffer;
-*Unlink = *Geo::GDALc::Unlink;
-*HasThreadSupport = *Geo::GDALc::HasThreadSupport;
-*Mkdir = *Geo::GDALc::Mkdir;
-*Rmdir = *Geo::GDALc::Rmdir;
-*Rename = *Geo::GDALc::Rename;
-*Stat = *Geo::GDALc::Stat;
-*VSIFOpenL = *Geo::GDALc::VSIFOpenL;
-*VSIFCloseL = *Geo::GDALc::VSIFCloseL;
-*VSIFSeekL = *Geo::GDALc::VSIFSeekL;
-*VSIFTellL = *Geo::GDALc::VSIFTellL;
-*VSIFTruncateL = *Geo::GDALc::VSIFTruncateL;
-*VSIFWriteL = *Geo::GDALc::VSIFWriteL;
-*VSIFReadL = *Geo::GDALc::VSIFReadL;
-*GDAL_GCP_GCPX_get = *Geo::GDALc::GDAL_GCP_GCPX_get;
-*GDAL_GCP_GCPX_set = *Geo::GDALc::GDAL_GCP_GCPX_set;
-*GDAL_GCP_GCPY_get = *Geo::GDALc::GDAL_GCP_GCPY_get;
-*GDAL_GCP_GCPY_set = *Geo::GDALc::GDAL_GCP_GCPY_set;
-*GDAL_GCP_GCPZ_get = *Geo::GDALc::GDAL_GCP_GCPZ_get;
-*GDAL_GCP_GCPZ_set = *Geo::GDALc::GDAL_GCP_GCPZ_set;
-*GDAL_GCP_GCPPixel_get = *Geo::GDALc::GDAL_GCP_GCPPixel_get;
-*GDAL_GCP_GCPPixel_set = *Geo::GDALc::GDAL_GCP_GCPPixel_set;
-*GDAL_GCP_GCPLine_get = *Geo::GDALc::GDAL_GCP_GCPLine_get;
-*GDAL_GCP_GCPLine_set = *Geo::GDALc::GDAL_GCP_GCPLine_set;
-*GDAL_GCP_Info_get = *Geo::GDALc::GDAL_GCP_Info_get;
-*GDAL_GCP_Info_set = *Geo::GDALc::GDAL_GCP_Info_set;
-*GDAL_GCP_Id_get = *Geo::GDALc::GDAL_GCP_Id_get;
-*GDAL_GCP_Id_set = *Geo::GDALc::GDAL_GCP_Id_set;
-*GCPsToGeoTransform = *Geo::GDALc::GCPsToGeoTransform;
-*TermProgress_nocb = *Geo::GDALc::TermProgress_nocb;
-*_ComputeMedianCutPCT = *Geo::GDALc::_ComputeMedianCutPCT;
-*_DitherRGB2PCT = *Geo::GDALc::_DitherRGB2PCT;
-*_ReprojectImage = *Geo::GDALc::_ReprojectImage;
-*_ComputeProximity = *Geo::GDALc::_ComputeProximity;
-*_RasterizeLayer = *Geo::GDALc::_RasterizeLayer;
-*_Polygonize = *Geo::GDALc::_Polygonize;
-*FillNodata = *Geo::GDALc::FillNodata;
-*_SieveFilter = *Geo::GDALc::_SieveFilter;
-*_RegenerateOverviews = *Geo::GDALc::_RegenerateOverviews;
-*_RegenerateOverview = *Geo::GDALc::_RegenerateOverview;
-*ContourGenerate = *Geo::GDALc::ContourGenerate;
-*_AutoCreateWarpedVRT = *Geo::GDALc::_AutoCreateWarpedVRT;
-*ApplyGeoTransform = *Geo::GDALc::ApplyGeoTransform;
-*InvGeoTransform = *Geo::GDALc::InvGeoTransform;
-*VersionInfo = *Geo::GDALc::VersionInfo;
-*AllRegister = *Geo::GDALc::AllRegister;
-*GDALDestroyDriverManager = *Geo::GDALc::GDALDestroyDriverManager;
-*GetCacheMax = *Geo::GDALc::GetCacheMax;
-*GetCacheUsed = *Geo::GDALc::GetCacheUsed;
-*SetCacheMax = *Geo::GDALc::SetCacheMax;
-*_GetDataTypeSize = *Geo::GDALc::_GetDataTypeSize;
-*_DataTypeIsComplex = *Geo::GDALc::_DataTypeIsComplex;
-*GetDataTypeName = *Geo::GDALc::GetDataTypeName;
-*GetDataTypeByName = *Geo::GDALc::GetDataTypeByName;
-*GetColorInterpretationName = *Geo::GDALc::GetColorInterpretationName;
-*GetPaletteInterpretationName = *Geo::GDALc::GetPaletteInterpretationName;
-*DecToDMS = *Geo::GDALc::DecToDMS;
-*PackedDMSToDec = *Geo::GDALc::PackedDMSToDec;
-*DecToPackedDMS = *Geo::GDALc::DecToPackedDMS;
-*ParseXMLString = *Geo::GDALc::ParseXMLString;
-*SerializeXMLTree = *Geo::GDALc::SerializeXMLTree;
-*GetJPEG2000StructureAsString = *Geo::GDALc::GetJPEG2000StructureAsString;
-*GetDriverCount = *Geo::GDALc::GetDriverCount;
-*GetDriverByName = *Geo::GDALc::GetDriverByName;
-*_GetDriver = *Geo::GDALc::_GetDriver;
-*_Open = *Geo::GDALc::_Open;
-*OpenEx = *Geo::GDALc::OpenEx;
-*_OpenShared = *Geo::GDALc::_OpenShared;
-*IdentifyDriver = *Geo::GDALc::IdentifyDriver;
-*GeneralCmdLineProcessor = *Geo::GDALc::GeneralCmdLineProcessor;
-
-############# Class : Geo::GDAL::MajorObject ##############
-
-package Geo::GDAL::MajorObject;
-use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
- at ISA = qw( Geo::GDAL );
-%OWNER = ();
-*GetDescription = *Geo::GDALc::MajorObject_GetDescription;
-*SetDescription = *Geo::GDALc::MajorObject_SetDescription;
-*GetMetadataDomainList = *Geo::GDALc::MajorObject_GetMetadataDomainList;
-*GetMetadata = *Geo::GDALc::MajorObject_GetMetadata;
-*SetMetadata = *Geo::GDALc::MajorObject_SetMetadata;
-*GetMetadataItem = *Geo::GDALc::MajorObject_GetMetadataItem;
-*SetMetadataItem = *Geo::GDALc::MajorObject_SetMetadataItem;
-sub DISOWN {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    delete $OWNER{$ptr};
-}
-
-sub ACQUIRE {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    $OWNER{$ptr} = 1;
-}
-
-
-############# Class : Geo::GDAL::Driver ##############
-
-package Geo::GDAL::Driver;
-use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
- at ISA = qw( Geo::GDAL::MajorObject Geo::GDAL );
-%OWNER = ();
-%ITERATORS = ();
-*swig_ShortName_get = *Geo::GDALc::Driver_ShortName_get;
-*swig_ShortName_set = *Geo::GDALc::Driver_ShortName_set;
-*swig_LongName_get = *Geo::GDALc::Driver_LongName_get;
-*swig_LongName_set = *Geo::GDALc::Driver_LongName_set;
-*swig_HelpTopic_get = *Geo::GDALc::Driver_HelpTopic_get;
-*swig_HelpTopic_set = *Geo::GDALc::Driver_HelpTopic_set;
-*_Create = *Geo::GDALc::Driver__Create;
-*CreateCopy = *Geo::GDALc::Driver_CreateCopy;
-*Delete = *Geo::GDALc::Driver_Delete;
-*Rename = *Geo::GDALc::Driver_Rename;
-*CopyFiles = *Geo::GDALc::Driver_CopyFiles;
-*Register = *Geo::GDALc::Driver_Register;
-*Deregister = *Geo::GDALc::Driver_Deregister;
-sub DISOWN {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    delete $OWNER{$ptr};
-}
-
-sub ACQUIRE {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    $OWNER{$ptr} = 1;
-}
-
-
-############# Class : Geo::GDAL::GCP ##############
-
-package Geo::GDAL::GCP;
-use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
- at ISA = qw( Geo::GDAL );
-%OWNER = ();
-%ITERATORS = ();
-*swig_X_get = *Geo::GDALc::GCP_X_get;
-*swig_X_set = *Geo::GDALc::GCP_X_set;
-*swig_Y_get = *Geo::GDALc::GCP_Y_get;
-*swig_Y_set = *Geo::GDALc::GCP_Y_set;
-*swig_Z_get = *Geo::GDALc::GCP_Z_get;
-*swig_Z_set = *Geo::GDALc::GCP_Z_set;
-*swig_Column_get = *Geo::GDALc::GCP_Column_get;
-*swig_Column_set = *Geo::GDALc::GCP_Column_set;
-*swig_Row_get = *Geo::GDALc::GCP_Row_get;
-*swig_Row_set = *Geo::GDALc::GCP_Row_set;
-*swig_Info_get = *Geo::GDALc::GCP_Info_get;
-*swig_Info_set = *Geo::GDALc::GCP_Info_set;
-*swig_Id_get = *Geo::GDALc::GCP_Id_get;
-*swig_Id_set = *Geo::GDALc::GCP_Id_set;
-sub new {
-    my $pkg = shift;
-    my $self = Geo::GDALc::new_GCP(@_);
-    bless $self, $pkg if defined($self);
-}
-
-sub DESTROY {
-    my $self;
-    if ($_[0]->isa('SCALAR')) {
-        $self = $_[0];
-    } else {
-        return unless $_[0]->isa('HASH');
-        $self = tied(%{$_[0]});
-        return unless defined $self;
-    }
-    delete $ITERATORS{$self};
-    if (exists $OWNER{$self}) {
-        Geo::GDALc::delete_GCP($self);
-        delete $OWNER{$self};
-    }
-    $self->RELEASE_PARENTS();
-}
-
-sub DISOWN {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    delete $OWNER{$ptr};
-}
-
-sub ACQUIRE {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    $OWNER{$ptr} = 1;
-}
-
-
-############# Class : Geo::GDAL::AsyncReader ##############
-
-package Geo::GDAL::AsyncReader;
-use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
- at ISA = qw( Geo::GDAL );
-%OWNER = ();
-%ITERATORS = ();
-sub DESTROY {
-    return unless $_[0]->isa('HASH');
-    my $self = tied(%{$_[0]});
-    return unless defined $self;
-    delete $ITERATORS{$self};
-    if (exists $OWNER{$self}) {
-        Geo::GDALc::delete_AsyncReader($self);
-        delete $OWNER{$self};
-    }
-}
-
-*GetNextUpdatedRegion = *Geo::GDALc::AsyncReader_GetNextUpdatedRegion;
-*LockBuffer = *Geo::GDALc::AsyncReader_LockBuffer;
-*UnlockBuffer = *Geo::GDALc::AsyncReader_UnlockBuffer;
-sub DISOWN {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    delete $OWNER{$ptr};
-}
-
-sub ACQUIRE {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    $OWNER{$ptr} = 1;
-}
-
-
-############# Class : Geo::GDAL::Dataset ##############
-
-package Geo::GDAL::Dataset;
-use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
- at ISA = qw( Geo::GDAL::MajorObject Geo::GDAL );
-%OWNER = ();
-%ITERATORS = ();
-*swig_RasterXSize_get = *Geo::GDALc::Dataset_RasterXSize_get;
-*swig_RasterXSize_set = *Geo::GDALc::Dataset_RasterXSize_set;
-*swig_RasterYSize_get = *Geo::GDALc::Dataset_RasterYSize_get;
-*swig_RasterYSize_set = *Geo::GDALc::Dataset_RasterYSize_set;
-*swig_RasterCount_get = *Geo::GDALc::Dataset_RasterCount_get;
-*swig_RasterCount_set = *Geo::GDALc::Dataset_RasterCount_set;
-sub DESTROY {
-    my $self;
-    if ($_[0]->isa('SCALAR')) {
-        $self = $_[0];
-    } else {
-        return unless $_[0]->isa('HASH');
-        $self = tied(%{$_[0]});
-        return unless defined $self;
-    }
-    delete $ITERATORS{$self};
-    if (exists $OWNER{$self}) {
-        Geo::GDALc::delete_Dataset($self);
-        delete $OWNER{$self};
-    }
-    $self->RELEASE_PARENTS();
-}
-
-*_GetDriver = *Geo::GDALc::Dataset__GetDriver;
-*_GetRasterBand = *Geo::GDALc::Dataset__GetRasterBand;
-*GetProjection = *Geo::GDALc::Dataset_GetProjection;
-*GetProjectionRef = *Geo::GDALc::Dataset_GetProjectionRef;
-*SetProjection = *Geo::GDALc::Dataset_SetProjection;
-*GetGeoTransform = *Geo::GDALc::Dataset_GetGeoTransform;
-*SetGeoTransform = *Geo::GDALc::Dataset_SetGeoTransform;
-*_BuildOverviews = *Geo::GDALc::Dataset__BuildOverviews;
-*GetGCPCount = *Geo::GDALc::Dataset_GetGCPCount;
-*GetGCPProjection = *Geo::GDALc::Dataset_GetGCPProjection;
-*GetGCPs = *Geo::GDALc::Dataset_GetGCPs;
-*SetGCPs = *Geo::GDALc::Dataset_SetGCPs;
-*FlushCache = *Geo::GDALc::Dataset_FlushCache;
-*_AddBand = *Geo::GDALc::Dataset__AddBand;
-*_CreateMaskBand = *Geo::GDALc::Dataset__CreateMaskBand;
-*GetFileList = *Geo::GDALc::Dataset_GetFileList;
-*_WriteRaster = *Geo::GDALc::Dataset__WriteRaster;
-*_ReadRaster = *Geo::GDALc::Dataset__ReadRaster;
-*StartTransaction = *Geo::GDALc::Dataset_StartTransaction;
-*CommitTransaction = *Geo::GDALc::Dataset_CommitTransaction;
-*RollbackTransaction = *Geo::GDALc::Dataset_RollbackTransaction;
-sub DISOWN {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    delete $OWNER{$ptr};
-}
-
-sub ACQUIRE {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    $OWNER{$ptr} = 1;
-}
-
-
-############# Class : Geo::GDAL::Band ##############
-
-package Geo::GDAL::Band;
-use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
- at ISA = qw( Geo::GDAL::MajorObject Geo::GDAL );
-%OWNER = ();
-%ITERATORS = ();
-*swig_XSize_get = *Geo::GDALc::Band_XSize_get;
-*swig_XSize_set = *Geo::GDALc::Band_XSize_set;
-*swig_YSize_get = *Geo::GDALc::Band_YSize_get;
-*swig_YSize_set = *Geo::GDALc::Band_YSize_set;
-*swig_DataType_get = *Geo::GDALc::Band_DataType_get;
-*swig_DataType_set = *Geo::GDALc::Band_DataType_set;
-*GetDataset = *Geo::GDALc::Band_GetDataset;
-*GetBand = *Geo::GDALc::Band_GetBand;
-*GetBlockSize = *Geo::GDALc::Band_GetBlockSize;
-*GetColorInterpretation = *Geo::GDALc::Band_GetColorInterpretation;
-*GetRasterColorInterpretation = *Geo::GDALc::Band_GetRasterColorInterpretation;
-*SetColorInterpretation = *Geo::GDALc::Band_SetColorInterpretation;
-*SetRasterColorInterpretation = *Geo::GDALc::Band_SetRasterColorInterpretation;
-*GetNoDataValue = *Geo::GDALc::Band_GetNoDataValue;
-*SetNoDataValue = *Geo::GDALc::Band_SetNoDataValue;
-*GetUnitType = *Geo::GDALc::Band_GetUnitType;
-*SetUnitType = *Geo::GDALc::Band_SetUnitType;
-*GetRasterCategoryNames = *Geo::GDALc::Band_GetRasterCategoryNames;
-*SetRasterCategoryNames = *Geo::GDALc::Band_SetRasterCategoryNames;
-*GetMinimum = *Geo::GDALc::Band_GetMinimum;
-*GetMaximum = *Geo::GDALc::Band_GetMaximum;
-*GetOffset = *Geo::GDALc::Band_GetOffset;
-*GetScale = *Geo::GDALc::Band_GetScale;
-*SetOffset = *Geo::GDALc::Band_SetOffset;
-*SetScale = *Geo::GDALc::Band_SetScale;
-*GetStatistics = *Geo::GDALc::Band_GetStatistics;
-*ComputeStatistics = *Geo::GDALc::Band_ComputeStatistics;
-*SetStatistics = *Geo::GDALc::Band_SetStatistics;
-*GetOverviewCount = *Geo::GDALc::Band_GetOverviewCount;
-*GetOverview = *Geo::GDALc::Band_GetOverview;
-*Checksum = *Geo::GDALc::Band_Checksum;
-*ComputeRasterMinMax = *Geo::GDALc::Band_ComputeRasterMinMax;
-*ComputeBandStats = *Geo::GDALc::Band_ComputeBandStats;
-*Fill = *Geo::GDALc::Band_Fill;
-*_ReadRaster = *Geo::GDALc::Band__ReadRaster;
-*_WriteRaster = *Geo::GDALc::Band__WriteRaster;
-*FlushCache = *Geo::GDALc::Band_FlushCache;
-*GetRasterColorTable = *Geo::GDALc::Band_GetRasterColorTable;
-*GetColorTable = *Geo::GDALc::Band_GetColorTable;
-*SetRasterColorTable = *Geo::GDALc::Band_SetRasterColorTable;
-*SetColorTable = *Geo::GDALc::Band_SetColorTable;
-*GetDefaultRAT = *Geo::GDALc::Band_GetDefaultRAT;
-*SetDefaultRAT = *Geo::GDALc::Band_SetDefaultRAT;
-*GetMaskBand = *Geo::GDALc::Band_GetMaskBand;
-*_GetMaskFlags = *Geo::GDALc::Band__GetMaskFlags;
-*_CreateMaskBand = *Geo::GDALc::Band__CreateMaskBand;
-*_GetHistogram = *Geo::GDALc::Band__GetHistogram;
-*GetDefaultHistogram = *Geo::GDALc::Band_GetDefaultHistogram;
-*SetDefaultHistogram = *Geo::GDALc::Band_SetDefaultHistogram;
-*HasArbitraryOverviews = *Geo::GDALc::Band_HasArbitraryOverviews;
-*GetCategoryNames = *Geo::GDALc::Band_GetCategoryNames;
-*SetCategoryNames = *Geo::GDALc::Band_SetCategoryNames;
-*ContourGenerate = *Geo::GDALc::Band_ContourGenerate;
-sub DISOWN {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    delete $OWNER{$ptr};
-}
-
-sub ACQUIRE {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    $OWNER{$ptr} = 1;
-}
-
-
-############# Class : Geo::GDAL::ColorTable ##############
-
-package Geo::GDAL::ColorTable;
-use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
- at ISA = qw( Geo::GDAL );
-%OWNER = ();
-use Carp;
-sub new {
-    my($pkg, $pi) = @_;
-    $pi = $PALETTE_INTERPRETATION_STRING2INT{$pi} if defined $pi and exists $PALETTE_INTERPRETATION_STRING2INT{$pi};
-    my $self = Geo::GDALc::new_ColorTable($pi);
-    bless $self, $pkg if defined($self);
-}
-
-sub DESTROY {
-    my $self;
-    if ($_[0]->isa('SCALAR')) {
-        $self = $_[0];
-    } else {
-        return unless $_[0]->isa('HASH');
-        $self = tied(%{$_[0]});
-        return unless defined $self;
-    }
-    delete $ITERATORS{$self};
-    if (exists $OWNER{$self}) {
-        Geo::GDALc::delete_ColorTable($self);
-        delete $OWNER{$self};
-    }
-    $self->RELEASE_PARENTS();
-}
-
-*Clone = *Geo::GDALc::ColorTable_Clone;
-*_GetPaletteInterpretation = *Geo::GDALc::ColorTable__GetPaletteInterpretation;
-*GetCount = *Geo::GDALc::ColorTable_GetCount;
-*GetColorEntry = *Geo::GDALc::ColorTable_GetColorEntry;
-*GetColorEntryAsRGB = *Geo::GDALc::ColorTable_GetColorEntryAsRGB;
-*_SetColorEntry = *Geo::GDALc::ColorTable__SetColorEntry;
-*CreateColorRamp = *Geo::GDALc::ColorTable_CreateColorRamp;
-sub DISOWN {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    delete $OWNER{$ptr};
-}
-
-sub ACQUIRE {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    $OWNER{$ptr} = 1;
-}
-
-
-############# Class : Geo::GDAL::RasterAttributeTable ##############
-
-package Geo::GDAL::RasterAttributeTable;
-use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
- at ISA = qw( Geo::GDAL );
-%OWNER = ();
-sub new {
-    my $pkg = shift;
-    my $self = Geo::GDALc::new_RasterAttributeTable(@_);
-    bless $self, $pkg if defined($self);
-}
-
-sub DESTROY {
-    my $self;
-    if ($_[0]->isa('SCALAR')) {
-        $self = $_[0];
-    } else {
-        return unless $_[0]->isa('HASH');
-        $self = tied(%{$_[0]});
-        return unless defined $self;
-    }
-    delete $ITERATORS{$self};
-    if (exists $OWNER{$self}) {
-        Geo::GDALc::delete_RasterAttributeTable($self);
-        delete $OWNER{$self};
-    }
-    $self->RELEASE_PARENTS();
-}
-
-*Clone = *Geo::GDALc::RasterAttributeTable_Clone;
-*GetColumnCount = *Geo::GDALc::RasterAttributeTable_GetColumnCount;
-*GetNameOfCol = *Geo::GDALc::RasterAttributeTable_GetNameOfCol;
-*_GetUsageOfCol = *Geo::GDALc::RasterAttributeTable__GetUsageOfCol;
-*_GetTypeOfCol = *Geo::GDALc::RasterAttributeTable__GetTypeOfCol;
-*_GetColOfUsage = *Geo::GDALc::RasterAttributeTable__GetColOfUsage;
-*GetRowCount = *Geo::GDALc::RasterAttributeTable_GetRowCount;
-*GetValueAsString = *Geo::GDALc::RasterAttributeTable_GetValueAsString;
-*GetValueAsInt = *Geo::GDALc::RasterAttributeTable_GetValueAsInt;
-*GetValueAsDouble = *Geo::GDALc::RasterAttributeTable_GetValueAsDouble;
-*SetValueAsString = *Geo::GDALc::RasterAttributeTable_SetValueAsString;
-*SetValueAsInt = *Geo::GDALc::RasterAttributeTable_SetValueAsInt;
-*SetValueAsDouble = *Geo::GDALc::RasterAttributeTable_SetValueAsDouble;
-*SetRowCount = *Geo::GDALc::RasterAttributeTable_SetRowCount;
-*_CreateColumn = *Geo::GDALc::RasterAttributeTable__CreateColumn;
-*GetLinearBinning = *Geo::GDALc::RasterAttributeTable_GetLinearBinning;
-*SetLinearBinning = *Geo::GDALc::RasterAttributeTable_SetLinearBinning;
-*GetRowOfValue = *Geo::GDALc::RasterAttributeTable_GetRowOfValue;
-*ChangesAreWrittenToFile = *Geo::GDALc::RasterAttributeTable_ChangesAreWrittenToFile;
-*DumpReadable = *Geo::GDALc::RasterAttributeTable_DumpReadable;
-sub DISOWN {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    delete $OWNER{$ptr};
-}
-
-sub ACQUIRE {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    $OWNER{$ptr} = 1;
-}
-
-
-############# Class : Geo::GDAL::Transformer ##############
-
-package Geo::GDAL::Transformer;
-use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
- at ISA = qw( Geo::GDAL );
-%OWNER = ();
-%ITERATORS = ();
-sub new {
-    my $pkg = shift;
-    my $self = Geo::GDALc::new_Transformer(@_);
-    bless $self, $pkg if defined($self);
-}
-
-sub DESTROY {
-    return unless $_[0]->isa('HASH');
-    my $self = tied(%{$_[0]});
-    return unless defined $self;
-    delete $ITERATORS{$self};
-    if (exists $OWNER{$self}) {
-        Geo::GDALc::delete_Transformer($self);
-        delete $OWNER{$self};
-    }
-}
-
-*TransformPoint = *Geo::GDALc::Transformer_TransformPoint;
-*_TransformPoints = *Geo::GDALc::Transformer__TransformPoints;
-*TransformGeolocations = *Geo::GDALc::Transformer_TransformGeolocations;
-sub DISOWN {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    delete $OWNER{$ptr};
-}
-
-sub ACQUIRE {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    $OWNER{$ptr} = 1;
-}
-
-
-# ------- VARIABLE STUBS --------
-
-package Geo::GDAL;
-
-*TermProgress = *Geo::GDALc::TermProgress;
-
-
-package Geo::GDAL;
-use strict;
-use warnings;
-use Carp;
-use Encode;
-use Geo::GDAL::Const;
-use Geo::OGR;
-use Geo::OSR;
-# $VERSION is the Perl module (CPAN) version number, which must be
-# an increasing floating point number.  $GDAL_VERSION is the
-# version number of the GDAL that this module is a part of. It is
-# used in build time to check the version of GDAL against which we
-# build.
-# For GDAL 2.0 or above, GDAL X.Y.Z should then
-# VERSION = X + Y / 100.0 + Z / 10000.0
-
-our $VERSION = '2.0002';
-our $GDAL_VERSION = '2.0.2';
-
-=pod
-
-=head1 NAME
-
-Geo::GDAL - Perl extension for the GDAL library for geospatial data
-
-=head1 SYNOPSIS
-
-  use Geo::GDAL;
-
-  my $raster_file = shift @ARGV;
-
-  my $raster_dataset = Geo::GDAL::Open($file);
-
-  my $raster_data = $dataset->GetRasterBand(1)->ReadTile;
-
-  my $vector_datasource = Geo::OGR::Open('./');
- 
-  my $vector_layer = $datasource->Layer('borders'); # e.g. a shapefile borders.shp in current directory
-
-  $vector_layer->ResetReading();
-  while (my $feature = $vector_layer->GetNextFeature()) {  
-      my $geometry = $feature->GetGeometry(); 
-      my $value = $feature->GetField($field);
-  }
-
-=head1 DESCRIPTION
-
-This Perl module lets you to manage (read, analyse, write) geospatial
-data stored in several formats.
-
-=head2 EXPORT
-
-None by default.
-
-=head1 SEE ALSO
-
-The GDAL home page is L<http://gdal.org/>
-
-The documentation of this module is written in Doxygen format. See
-L<http://ajolma.net/Geo-GDAL/snapshot/>
-
-=head1 AUTHOR
-
-Ari Jolma
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright (C) 2005- by Ari Jolma and GDAL bindings developers.
-
-This library is free software; you can redistribute it and/or modify
-it under the terms of MIT License
-
-L<https://opensource.org/licenses/MIT>
-
-=head1 REPOSITORY
-
-L<https://trac.osgeo.org/gdal>
-
-=cut
-
-use vars qw/
-    @DATA_TYPES @ACCESS_TYPES @RESAMPLING_TYPES @RIO_RESAMPLING_TYPES @NODE_TYPES
-    %TYPE_STRING2INT %TYPE_INT2STRING
-    %ACCESS_STRING2INT %ACCESS_INT2STRING
-    %RESAMPLING_STRING2INT %RESAMPLING_INT2STRING
-    %RIO_RESAMPLING_STRING2INT %RIO_RESAMPLING_INT2STRING
-    %NODE_TYPE_STRING2INT %NODE_TYPE_INT2STRING
-    /;
-for (keys %Geo::GDAL::Const::) {
-    next if /TypeCount/;
-    push(@DATA_TYPES, $1), next if /^GDT_(\w+)/;
-    push(@ACCESS_TYPES, $1), next if /^GA_(\w+)/;
-    push(@RESAMPLING_TYPES, $1), next if /^GRA_(\w+)/;
-    push(@RIO_RESAMPLING_TYPES, $1), next if /^GRIORA_(\w+)/;
-    push(@NODE_TYPES, $1), next if /^CXT_(\w+)/;
-}
-for my $string (@DATA_TYPES) {
-    my $int = eval "\$Geo::GDAL::Const::GDT_$string";
-    $TYPE_STRING2INT{$string} = $int;
-    $TYPE_INT2STRING{$int} = $string;
-}
-for my $string (@ACCESS_TYPES) {
-    my $int = eval "\$Geo::GDAL::Const::GA_$string";
-    $ACCESS_STRING2INT{$string} = $int;
-    $ACCESS_INT2STRING{$int} = $string;
-}
-for my $string (@RESAMPLING_TYPES) {
-    my $int = eval "\$Geo::GDAL::Const::GRA_$string";
-    $RESAMPLING_STRING2INT{$string} = $int;
-    $RESAMPLING_INT2STRING{$int} = $string;
-}
-for my $string (@RIO_RESAMPLING_TYPES) {
-    my $int = eval "\$Geo::GDAL::Const::GRIORA_$string";
-    $RIO_RESAMPLING_STRING2INT{$string} = $int;
-    $RIO_RESAMPLING_INT2STRING{$int} = $string;
-}
-for my $string (@NODE_TYPES) {
-    my $int = eval "\$Geo::GDAL::Const::CXT_$string";
-    $NODE_TYPE_STRING2INT{$string} = $int;
-    $NODE_TYPE_INT2STRING{$int} = $string;
-}
-
-sub RELEASE_PARENTS {
-}
-
-sub DataTypes {
-    return @DATA_TYPES;
-}
-
-sub AccessTypes {
-    return @ACCESS_TYPES;
-}
-
-sub ResamplingTypes {
-    return @RESAMPLING_TYPES;
-}
-
-sub RIOResamplingTypes {
-    return @RIO_RESAMPLING_TYPES;
-}
-
-sub NodeTypes {
-    return @NODE_TYPES;
-}
-
-sub NodeType {
-    my $type = shift;
-    return $NODE_TYPE_INT2STRING{$type} if $type =~ /^\d/;
-    return $NODE_TYPE_STRING2INT{$type};
-}
-
-sub NodeData {
-    my $node = shift;
-    return (Geo::GDAL::NodeType($node->[0]), $node->[1]);
-}
-
-sub Children {
-    my $node = shift;
-    return @$node[2..$#$node];
-}
-
-sub Child {
-    my($node, $child) = @_;
-    return $node->[2+$child];
-}
-
-sub GetDataTypeSize {
-    my $t = shift;
-    my $t2 = $t;
-    $t2 = $TYPE_STRING2INT{$t} if exists $TYPE_STRING2INT{$t};
-    confess "Unknown data type: '$t'." unless exists $TYPE_INT2STRING{$t2};
-    return _GetDataTypeSize($t2);
-}
-
-sub DataTypeValueRange {
-    my $t = shift;
-    confess "Unknown data type: '$t'." unless exists $TYPE_STRING2INT{$t};
-    # these values are from gdalrasterband.cpp
-    return (0,255) if $t =~ /Byte/;
-    return (0,65535) if $t =~/UInt16/;
-    return (-32768,32767) if $t =~/Int16/;
-    return (0,4294967295) if $t =~/UInt32/;
-    return (-2147483648,2147483647) if $t =~/Int32/;
-    return (-4294967295.0,4294967295.0) if $t =~/Float32/;
-    return (-4294967295.0,4294967295.0) if $t =~/Float64/;
-}
-
-sub DataTypeIsComplex {
-    my $t = shift;
-    my $t2 = $t;
-    $t2 = $TYPE_STRING2INT{$t} if exists $TYPE_STRING2INT{$t};
-    confess "Unknown data type: '$t'." unless exists $TYPE_INT2STRING{$t2};
-    return _DataTypeIsComplex($t2);
-}
-
-sub PackCharacter {
-    my $t = shift;
-    $t = $TYPE_INT2STRING{$t} if exists $TYPE_INT2STRING{$t};
-    confess "Unknown data type: '$t'." unless exists $TYPE_STRING2INT{$t};
-    my $is_big_endian = unpack("h*", pack("s", 1)) =~ /01/; # from Programming Perl
-    return 'C' if $t =~ /^Byte$/;
-    return ($is_big_endian ? 'n': 'v') if $t =~ /^UInt16$/;
-    return 's' if $t =~ /^Int16$/;
-    return ($is_big_endian ? 'N' : 'V') if $t =~ /^UInt32$/;
-    return 'l' if $t =~ /^Int32$/;
-    return 'f' if $t =~ /^Float32$/;
-    return 'd' if $t =~ /^Float64$/;
-}
-
-sub GetDriverNames {
-    my @names;
-    for my $i (0..GetDriverCount()-1) {
-        my $driver = _GetDriver($i);
-        my $md = $driver->GetMetadata;
-        next unless $md->{DCAP_RASTER} and $md->{DCAP_RASTER} eq 'YES';
-        push @names, _GetDriver($i)->Name;
-    }
-    return @names;
-}
-
-sub Drivers {
-    my @drivers;
-    for my $i (0..GetDriverCount()-1) {
-        my $driver = _GetDriver($i);
-        my $md = $driver->GetMetadata;
-        next unless $md->{DCAP_RASTER} and $md->{DCAP_RASTER} eq 'YES';
-        push @drivers, _GetDriver($i);
-    }
-    return @drivers;
-}
-
-sub GetDriver {
-    my($name) = @_;
-    $name = 0 unless defined $name;
-    my $driver;
-    $driver = _GetDriver($name) if $name =~ /^\d+$/; # is the name an index to driver list?
-    $driver = GetDriverByName("$name") unless $driver;
-    if ($driver) {
-        my $md = $driver->GetMetadata;
-        confess "Driver exists but does not have raster capabilities." 
-            unless $md->{DCAP_RASTER} and $md->{DCAP_RASTER} eq 'YES';
-        return $driver;
-    }
-    confess "Driver not found: '$name'. Maybe support for it was not built in?";
-}
-*Driver = *GetDriver;
-
-sub Open {
-    my @p = @_;
-    if (defined $p[1]) {
-        confess "Unknown access type: '$p[1]'." unless exists $Geo::GDAL::ACCESS_STRING2INT{$p[1]};
-        $p[1] = $Geo::GDAL::ACCESS_STRING2INT{$p[1]};
-    }
-    return _Open(@p);
-}
-
-sub OpenShared {
-    my @p = @_;
-    if (defined $p[1]) {
-        confess "Unknown access type: '$p[1]'." unless exists $Geo::GDAL::ACCESS_STRING2INT{$p[1]};
-        $p[1] = $Geo::GDAL::ACCESS_STRING2INT{$p[1]};
-    }
-    return _OpenShared(@p);
-}
-
-sub ComputeMedianCutPCT {
-    my @p = @_;
-    $p[6] = 1 if $p[5] and not defined $p[6];
-    _ComputeMedianCutPCT(@p);
-}
-
-sub DitherRGB2PCT {
-    my @p = @_;
-    $p[6] = 1 if $p[5] and not defined $p[6];
-    _DitherRGB2PCT(@p);
-}
-
-sub ComputeProximity {
-    my @p = @_;
-    $p[4] = 1 if $p[3] and not defined $p[4];
-    _ComputeProximity(@p);
-}
-
-sub RasterizeLayer {
-    my @p = @_;
-    $p[8] = 1 if $p[7] and not defined $p[8];
-    _RasterizeLayer(@p);
-}
-
-sub Polygonize {
-    my @params = @_;
-    $params[6] = 1 if $params[5] and not defined $params[6];
-    $params[3] = $params[2]->GetLayerDefn->GetFieldIndex($params[3]) unless $params[3] =~ /^\d/;
-    _Polygonize(@params);
-}
-
-sub SieveFilter {
-    my @p = @_;
-    $p[7] = 1 if $p[6] and not defined $p[7];
-    _SieveFilter(@p);
-}
-
-sub RegenerateOverviews {
-    my @p = @_;
-    $p[2] = uc($p[2]) if $p[2]; # see overview.cpp:2030
-    $p[4] = 1 if $p[3] and not defined $p[4];
-    _RegenerateOverviews(@p);
-}
-
-sub RegenerateOverview {
-    my @p = @_;
-    $p[2] = uc($p[2]) if $p[2]; # see overview.cpp:2030
-    $p[4] = 1 if $p[3] and not defined $p[4];
-    _RegenerateOverview(@p);
-}
-
-sub ReprojectImage {
-    my @p = @_;
-    $p[8] = 1 if $p[7] and not defined $p[8];
-    if (defined $p[4]) {
-        confess "Unknown data type: '$p[4]'." unless exists $Geo::GDAL::RESAMPLING_STRING2INT{$p[4]};
-        $p[4] = $Geo::GDAL::RESAMPLING_STRING2INT{$p[4]};
-    }
-    return _ReprojectImage(@p);
-}
-
-sub AutoCreateWarpedVRT {
-    my @p = @_;
-    for my $i (1..2) {
-        if (defined $p[$i] and ref($p[$i])) {
-            $p[$i] = $p[$i]->ExportToWkt;
-        }
-    }
-    if (defined $p[3]) {
-        confess "Unknown data type: '$p[3]'." unless exists $Geo::GDAL::RESAMPLING_STRING2INT{$p[3]};
-        $p[3] = $Geo::GDAL::RESAMPLING_STRING2INT{$p[3]};
-    }
-    return _AutoCreateWarpedVRT(@p);
-}
-
-
-
-
-package Geo::GDAL::MajorObject;
-use strict;
-use warnings;
-use vars qw/@DOMAINS/;
-
-sub Domains {
-    return @DOMAINS;
-}
-
-sub Description {
-    my($self, $desc) = @_;
-    SetDescription($self, $desc) if defined $desc;
-    GetDescription($self) if defined wantarray;
-}
-
-sub Metadata {
-    my $self = shift;
-    my $metadata;
-    $metadata = shift if ref $_[0];
-    my $domain = shift;
-    $domain = '' unless defined $domain;
-    SetMetadata($self, $metadata, $domain) if defined $metadata;
-    GetMetadata($self, $domain) if defined wantarray;
-}
-
-
-package Geo::GDAL::Driver;
-use strict;
-use warnings;
-use Carp;
-use vars qw/@CAPABILITIES @DOMAINS/;
-for (keys %Geo::GDAL::Const::) {
-    next if /TypeCount/;
-    push(@CAPABILITIES, $1), next if /^DCAP_(\w+)/;
-}
-
-sub Domains {
-    return @DOMAINS;
-}
-
-sub Name {
-    my $self = shift;
-    return $self->{ShortName};
-}
-
-sub Capabilities {
-    my $self = shift;
-    return @CAPABILITIES unless $self;
-    my $h = $self->GetMetadata;
-    my @cap;
-    for my $cap (@CAPABILITIES) {
-        my $test = $h->{'DCAP_'.uc($cap)};
-        push @cap, $cap if defined($test) and $test eq 'YES';
-    }
-    return @cap;
-}
-
-sub TestCapability {
-    my($self, $cap) = @_;
-    my $h = $self->GetMetadata->{'DCAP_'.uc($cap)};
-    return (defined($h) and $h eq 'YES') ? 1 : undef;
-}
-
-sub Extension {
-    my $self = shift;
-    my $h = $self->GetMetadata;
-    return $h->{DMD_EXTENSION};
-}
-
-sub MIMEType {
-    my $self = shift;
-    my $h = $self->GetMetadata;
-    return $h->{DMD_MIMETYPE};
-}
-
-sub CreationOptionList {
-    my $self = shift;
-    my @options;
-    my $h = $self->GetMetadata->{DMD_CREATIONOPTIONLIST};
-    if ($h) {
-        $h = Geo::GDAL::ParseXMLString($h);
-        my($type, $value) = Geo::GDAL::NodeData($h);
-        if ($value eq 'CreationOptionList') {
-            for my $o (Geo::GDAL::Children($h)) {
-                my %option;
-                for my $a (Geo::GDAL::Children($o)) {
-                    my(undef, $key) = Geo::GDAL::NodeData($a);
-                    my(undef, $value) = Geo::GDAL::NodeData(Geo::GDAL::Child($a, 0));
-                    if ($key eq 'Value') {
-                        push @{$option{$key}}, $value;
-                    } else {
-                        $option{$key} = $value;
-                    }
-                }
-                push @options, \%option;
-            }
-        }
-    }
-    return @options;
-}
-
-sub CreationDataTypes {
-    my $self = shift;
-    my $h = $self->GetMetadata;
-    return split /\s+/, $h->{DMD_CREATIONDATATYPES} if $h->{DMD_CREATIONDATATYPES};
-}
-
-sub Create {
-    my $self = shift;
-    my %defaults = ( Name => 'unnamed',
-                     Width => 256,
-                     Height => 256,
-                     Bands => 1,
-                     Type => 'Byte',
-                     Options => {} );
-    my %params;
-    if (@_ == 0) {
-    } elsif (ref($_[0]) eq 'HASH') {
-        %params = %{$_[0]};
-    } elsif (exists $defaults{$_[0]} and @_ % 2 == 0) {
-        %params = @_;
-    } else {
-        ($params{Name}, $params{Width}, $params{Height}, $params{Bands}, $params{Type}, $params{Options}) = @_;
-    }
-    for my $k (keys %params) {
-        carp "Create: unrecognized named parameter '$k'." unless exists $defaults{$k};
-    }
-    for my $k (keys %defaults) {
-        $params{$k} = $defaults{$k} unless defined $params{$k};
-    }
-    my $type;
-    confess "Unknown data type: '$params{Type}'." unless exists $Geo::GDAL::TYPE_STRING2INT{$params{Type}};
-    $type = $Geo::GDAL::TYPE_STRING2INT{$params{Type}};
-    return $self->_Create($params{Name}, $params{Width}, $params{Height}, $params{Bands}, $type, $params{Options});
-}
-*CreateDataset = *Create;
-*Copy = *CreateCopy;
-
-
-
-
-package Geo::GDAL::Dataset;
-use strict;
-use warnings;
-use Carp;
-use vars qw/%BANDS @DOMAINS/;
- at DOMAINS = qw/IMAGE_STRUCTURE SUBDATASETS GEOLOCATION/;
-
-sub Domains {
-    return @DOMAINS;
-}
-*GetDriver = *_GetDriver;
-
-sub Open {
-    return Geo::GDAL::Open(@_);
-}
-
-sub OpenShared {
-    return Geo::GDAL::OpenShared(@_);
-}
-
-sub Size {
-    my $self = shift;
-    return ($self->{RasterXSize}, $self->{RasterYSize});
-}
-
-sub Bands {
-    my $self = shift;
-    my @bands;
-    for my $i (1..$self->{RasterCount}) {
-        push @bands, GetRasterBand($self, $i);
-    }
-    return @bands;
-}
-
-sub GetRasterBand {
-    my($self, $index) = @_;
-    $index = 1 unless defined $index;
-    my $band = _GetRasterBand($self, $index);
-    $BANDS{tied(%{$band})} = $self;
-    return $band;
-}
-*Band = *GetRasterBand;
-
-sub AddBand {
-    my @p = @_;
-    if (defined $p[1]) {
-        confess "Unknown data type: '$p[1]'." unless exists $Geo::GDAL::TYPE_STRING2INT{$p[1]};
-        $p[1] = $Geo::GDAL::TYPE_STRING2INT{$p[1]};
-    }
-    return _AddBand(@p);
-}
-
-sub Projection {
-    my($self, $proj) = @_;
-    SetProjection($self, $proj) if defined $proj;
-    GetProjection($self) if defined wantarray;
-}
-
-sub SpatialReference {
-    my($self, $sr) = @_;
-    SetProjection($self, $sr->As('WKT')) if defined $sr;
-    return Geo::OSR::SpatialReference->new(GetProjection($self)) if defined wantarray;
-}
-
-sub GeoTransform {
-    my $self = shift;
-    eval {
-        if (@_ == 1) {
-            SetGeoTransform($self, $_[0]);
-        } elsif (@_ > 1) {
-            SetGeoTransform($self, \@_);
-        }
-    };
-    confess $@ if $@;
-    return unless defined wantarray;
-    my $t = GetGeoTransform($self);
-    if (wantarray) {
-        return @$t;
-    } else {
-        return Geo::GDAL::GeoTransform->new($t);
-    }
-}
-
-sub GCPs {
-    my $self = shift;
-    if (@_ > 0) {
-        my $proj = pop @_;
-        $proj = $proj->Export('WKT') if $proj and ref($proj);
-        SetGCPs($self, \@_, $proj);
-    }
-    return unless defined wantarray;
-    my $proj = Geo::OSR::SpatialReference->new(GetGCPProjection($self));
-    my $GCPs = GetGCPs($self);
-    return (@$GCPs, $proj);
-}
-
-sub ReadRaster {
-    my $self = shift;
-    my ($width, $height) = $self->Size;
-    my ($type) = $self->Band->DataType;
-    my %d = (
-        XOFF => 0,
-        YOFF => 0,
-        XSIZE => $width,
-        YSIZE => $height,
-        BUFXSIZE => undef,
-        BUFYSIZE => undef,
-        BUFTYPE => $type,
-        BANDLIST => [1],
-        BUFPIXELSPACE => 0,
-        BUFLINESPACE => 0,
-        BUFBANDSPACE => 0,
-        RESAMPLEALG => 'NearestNeighbour',
-        PROGRESS => undef,
-        PROGRESSDATA => undef
-        );
-    my %p;
-    my $t;
-    if (defined $_[0]) {
-        $t = uc($_[0]); 
-        $t =~ s/_//g;
-    }
-    if (@_ == 0) {
-    } elsif (ref($_[0]) eq 'HASH') {
-        %p = %{$_[0]};
-    } elsif (@_ % 2 == 0 and (defined $t and exists $d{$t})) {
-        %p = @_;
-    } else {
-        ($p{xoff},$p{yoff},$p{xsize},$p{ysize},$p{buf_xsize},$p{buf_ysize},$p{buf_type},$p{band_list},$p{buf_pixel_space},$p{buf_line_space},$p{buf_band_space},$p{resample_alg},$p{progress},$p{progress_data}) = @_;
-    }
-    for (keys %p) {
-        my $u = uc($_);
-        $u =~ s/_//g;
-        carp "Unknown named parameter '$_'." unless exists $d{$u};
-        $p{$u} = $p{$_};
-    }
-    for (keys %d) {
-        $p{$_} = $d{$_} unless defined $p{$_};
-    }
-    confess "Unknown resampling algorithm: '$p{RESAMPLEALG}'." 
-        unless exists $Geo::GDAL::RIO_RESAMPLING_STRING2INT{$p{RESAMPLEALG}};
-    $p{RESAMPLEALG} = $Geo::GDAL::RIO_RESAMPLING_STRING2INT{$p{RESAMPLEALG}};
-    unless ($Geo::GDAL::TYPE_INT2STRING{$p{BUFTYPE}}) {
-        confess "Unknown data type: '$p{BUFTYPE}'." 
-            unless exists $Geo::GDAL::TYPE_STRING2INT{$p{BUFTYPE}};
-        $p{BUFTYPE} = $Geo::GDAL::TYPE_STRING2INT{$p{BUFTYPE}};
-    }
-    $self->_ReadRaster($p{XOFF},$p{YOFF},$p{XSIZE},$p{YSIZE},$p{BUFXSIZE},$p{BUFYSIZE},$p{BUFTYPE},$p{BANDLIST},$p{BUFPIXELSPACE},$p{BUFLINESPACE},$p{BUFBANDSPACE},$p{RESAMPLEALG},$p{PROGRESS},$p{PROGRESSDATA});
-}
-
-sub WriteRaster {
-    my $self = shift;
-    my ($width, $height) = $self->Size;
-    my ($type) = $self->Band->DataType;
-    my %d = (
-        XOFF => 0,
-        YOFF => 0,
-        XSIZE => $width,
-        YSIZE => $height,
-        BUF => undef,
-        BUFXSIZE => undef,
-        BUFYSIZE => undef,
-        BUFTYPE => $type,
-        BANDLIST => [1],
-        BUFPIXELSPACE => 0,
-        BUFLINESPACE => 0,
-        BUFBANDSPACE => 0
-        );
-    my %p;
-    my $t;
-    if (defined $_[0]) {
-        $t = uc($_[0]); 
-        $t =~ s/_//g;
-    }
-    if (@_ == 0) {
-    } elsif (ref($_[0]) eq 'HASH') {
-        %p = %{$_[0]};
-    } elsif (@_ % 2 == 0 and (defined $t and exists $d{$t})) {
-        %p = @_;
-    } else {
-        ($p{xoff},$p{yoff},$p{xsize},$p{ysize},$p{buf},$p{buf_xsize},$p{buf_ysize},$p{buf_type},$p{band_list},$p{buf_pixel_space},$p{buf_line_space},$p{buf_band_space}) = @_;
-    }
-    for (keys %p) {
-        my $u = uc($_);
-        $u =~ s/_//g;
-        carp "Unknown named parameter '$_'." unless exists $d{$u};
-        $p{$u} = $p{$_};
-    }
-    for (keys %d) {
-        $p{$_} = $d{$_} unless defined $p{$_};
-    }
-    unless ($Geo::GDAL::TYPE_INT2STRING{$p{BUFTYPE}}) {
-        confess "Unknown data type: '$p{BUFTYPE}'." 
-            unless exists $Geo::GDAL::TYPE_STRING2INT{$p{BUFTYPE}};
-        $p{BUFTYPE} = $Geo::GDAL::TYPE_STRING2INT{$p{BUFTYPE}};
-    }
-    $self->_WriteRaster($p{XOFF},$p{YOFF},$p{XSIZE},$p{YSIZE},$p{BUF},$p{BUFXSIZE},$p{BUFYSIZE},$p{BUFTYPE},$p{BANDLIST},$p{BUFPIXELSPACE},$p{BUFLINESPACE},$p{BUFBANDSPACE});
-}
-
-sub BuildOverviews {
-    my $self = shift;
-    my @p = @_;
-    $p[0] = uc($p[0]) if $p[0];
-    eval {
-        $self->_BuildOverviews(@p);
-    };
-    confess $@ if $@;
-}
-
-
-
-
-package Geo::GDAL::Band;
-use strict;
-use warnings;
-use POSIX;
-use Carp;
-use Scalar::Util 'blessed';
-use vars qw/
-    @COLOR_INTERPRETATIONS
-    %COLOR_INTERPRETATION_STRING2INT %COLOR_INTERPRETATION_INT2STRING @DOMAINS
-    %MASK_FLAGS
-    /;
-for (keys %Geo::GDAL::Const::) {
-    next if /TypeCount/;
-    push(@COLOR_INTERPRETATIONS, $1), next if /^GCI_(\w+)/;
-}
-for my $string (@COLOR_INTERPRETATIONS) {
-    my $int = eval "\$Geo::GDAL::Constc::GCI_$string";
-    $COLOR_INTERPRETATION_STRING2INT{$string} = $int;
-    $COLOR_INTERPRETATION_INT2STRING{$int} = $string;
-}
- at DOMAINS = qw/IMAGE_STRUCTURE RESAMPLING/;
-%MASK_FLAGS = (AllValid => 1, PerDataset => 2, Alpha => 4, NoData => 8);
-
-sub Domains {
-    return @DOMAINS;
-}
-
-sub ColorInterpretations {
-    return @COLOR_INTERPRETATIONS;
-}
-
-sub MaskFlags {
-    my @f = sort {$MASK_FLAGS{$a} <=> $MASK_FLAGS{$b}} keys %MASK_FLAGS;
-    return @f;
-}
-
-sub DESTROY {
-    my $self;
-    if ($_[0]->isa('SCALAR')) {
-        $self = $_[0];
-    } else {
-        return unless $_[0]->isa('HASH');
-        $self = tied(%{$_[0]});
-        return unless defined $self;
-    }
-    delete $ITERATORS{$self};
-    if (exists $OWNER{$self}) {
-        delete $OWNER{$self};
-    }
-    $self->RELEASE_PARENTS();
-}
-
-sub RELEASE_PARENTS {
-    my $self = shift;
-    delete $Geo::GDAL::Dataset::BANDS{$self};
-}
-
-sub Size {
-    my $self = shift;
-    return ($self->{XSize}, $self->{YSize});
-}
-
-sub DataType {
-    my $self = shift;
-    return $Geo::GDAL::TYPE_INT2STRING{$self->{DataType}};
-}
-
-sub PackCharacter {
-    my $self = shift;
-    return Geo::GDAL::PackCharacter($self->DataType);
-}
-
-sub NoDataValue {
-    my $self = shift;
-    if (@_ > 0) {
-        if (defined $_[0]) {
-            SetNoDataValue($self, $_[0]);
-        } else {
-            SetNoDataValue($self, POSIX::FLT_MAX); # hopefully an "out of range" value
-        }
-    }
-    GetNoDataValue($self);
-}
-
-sub Unit {
-    my $self = shift;
-    if (@_ > 0) {
-        my $unit = shift;
-        $unit = '' unless defined $unit;
-        SetUnitType($self, $unit);
-    }
-    return unless defined wantarray;
-    GetUnitType($self);
-}
-
-sub ScaleAndOffset {
-    my $self = shift;
-    SetScale($self, $_[0]) if @_ > 0 and defined $_[0];
-    SetOffset($self, $_[1]) if @_ > 1 and defined $_[1];
-    return unless defined wantarray;
-    my $scale = GetScale($self);
-    my $offset = GetOffset($self);
-    return ($scale, $offset);
-}
-
-sub ReadTile {
-    my($self, $xoff, $yoff, $xsize, $ysize) = @_;
-    $xoff = 0 unless defined $xoff;
-    $yoff = 0 unless defined $yoff;
-    $xsize = $self->{XSize} - $xoff unless defined $xsize;
-    $ysize = $self->{YSize} - $yoff unless defined $ysize;
-    my $buf = $self->ReadRaster($xoff, $yoff, $xsize, $ysize);
-    my $pc = Geo::GDAL::PackCharacter($self->{DataType});
-    my $w = $xsize * Geo::GDAL::GetDataTypeSize($self->{DataType})/8;
-    my $offset = 0;
-    my @data;
-    for (0..$ysize-1) {
-        my $sub = substr($buf, $offset, $w);
-        my @d = unpack($pc."[$xsize]", $sub);
-        push @data, \@d;
-        $offset += $w;
-    }
-    return \@data;
-}
-
-sub WriteTile {
-    my($self, $data, $xoff, $yoff) = @_;
-    $xoff = 0 unless defined $xoff;
-    $yoff = 0 unless defined $yoff;
-    my $xsize = @{$data->[0]};
-    $xsize = $self->{XSize} - $xoff if $xsize > $self->{XSize} - $xoff;
-    my $ysize = @{$data};
-    $ysize = $self->{YSize} - $yoff if $ysize > $self->{YSize} - $yoff;
-    my $pc = Geo::GDAL::PackCharacter($self->{DataType});
-    for my $i (0..$ysize-1) {
-        my $scanline = pack($pc."[$xsize]", @{$data->[$i]});
-        $self->WriteRaster( $xoff, $yoff+$i, $xsize, 1, $scanline );
-    }
-}
-
-sub ColorInterpretation {
-    my($self, $ci) = @_;
-    if (defined $ci) {
-        my $ci2 = $ci;
-        $ci2 = $COLOR_INTERPRETATION_STRING2INT{$ci} if exists $COLOR_INTERPRETATION_STRING2INT{$ci};
-        confess "Unknown color interpretation: '$ci'." unless exists $COLOR_INTERPRETATION_INT2STRING{$ci2};
-        SetRasterColorInterpretation($self, $ci2);
-        return $ci;
-    } else {
-        return $COLOR_INTERPRETATION_INT2STRING{GetRasterColorInterpretation($self)};
-    }
-}
-
-sub ColorTable {
-    my $self = shift;
-    SetRasterColorTable($self, $_[0]) if @_ and defined $_[0];
-    return unless defined wantarray;
-    GetRasterColorTable($self);
-}
-
-sub CategoryNames {
-    my $self = shift;
-    SetRasterCategoryNames($self, \@_) if @_;
-    return unless defined wantarray;
-    my $n = GetRasterCategoryNames($self);
-    return @$n;
-}
-
-sub AttributeTable {
-    my $self = shift;
-    SetDefaultRAT($self, $_[0]) if @_ and defined $_[0];
-    return unless defined wantarray;
-    my $r = GetDefaultRAT($self);
-    $Geo::GDAL::RasterAttributeTable::BANDS{$r} = $self if $r;
-    return $r;
-}
-
-sub GetHistogram {
-    my $self = shift;
-    my %defaults = (Min => -0.5,
-                    Max => 255.5,
-                    Buckets => 256,
-                    IncludeOutOfRange => 0,
-                    ApproxOK => 0,
-                    Progress => undef,
-                    ProgressData => undef);
-    my %params = @_;
-    for (keys %params) {
-        carp "unknown parameter $_ in Geo::GDAL::Band::GetHistogram" unless exists $defaults{$_};
-    }
-    for (keys %defaults) {
-        $params{$_} = $defaults{$_} unless defined $params{$_};
-    }
-    $params{ProgressData} = 1 if $params{Progress} and not defined $params{ProgressData};
-    _GetHistogram($self, $params{Min}, $params{Max}, $params{Buckets},
-                  $params{IncludeOutOfRange}, $params{ApproxOK},
-                  $params{Progress}, $params{ProgressData});
-}
-
-sub Contours {
-    my $self = shift;
-    my %defaults = (DataSource => undef,
-                    LayerConstructor => {Name => 'contours'},
-                    ContourInterval => 100,
-                    ContourBase => 0,
-                    FixedLevels => [],
-                    NoDataValue => undef,
-                    IDField => -1,
-                    ElevField => -1,
-                    Progress => undef,
-                    ProgressData => undef);
-    my %params;
-    if (!defined($_[0]) or (blessed($_[0]) and $_[0]->isa('Geo::OGR::DataSource'))) {
-        ($params{DataSource}, $params{LayerConstructor},
-         $params{ContourInterval}, $params{ContourBase},
-         $params{FixedLevels}, $params{NoDataValue},
-         $params{IDField}, $params{ElevField},
-         $params{Progress}, $params{ProgressData}) = @_;
-    } else {
-        %params = @_;
-        if (exists $params{progress}) {
-            $params{Progress} = $params{progress};
-            delete $params{progress};
-        }
-        if (exists $params{progress_data}) {
-            $params{ProgressData} = $params{progress_data};
-            delete $params{progress_data};
-        }
-    }
-    for (keys %params) {
-        carp "unknown parameter $_ in Geo::GDAL::Band::Contours" unless exists $defaults{$_};
-    }
-    for (keys %defaults) {
-        $params{$_} = $defaults{$_} unless defined $params{$_};
-    }
-    $params{DataSource} = Geo::OGR::GetDriver('Memory')->CreateDataSource('ds')
-        unless defined $params{DataSource};
-    $params{LayerConstructor}->{Schema} = {} unless $params{LayerConstructor}->{Schema};
-    $params{LayerConstructor}->{Schema}{Fields} = [] unless $params{LayerConstructor}->{Schema}{Fields};
-    my %fields;
-    unless ($params{IDField} =~ /^[+-]?\d+$/ or $fields{$params{IDField}}) {
-        push @{$params{LayerConstructor}->{Schema}{Fields}}, {Name => $params{IDField}, Type => 'Integer'};
-    }
-    unless ($params{ElevField} =~ /^[+-]?\d+$/ or $fields{$params{ElevField}}) {
-        my $type = $self->DataType() =~ /Float/ ? 'Real' : 'Integer';
-        push @{$params{LayerConstructor}->{Schema}{Fields}}, {Name => $params{ElevField}, Type => $type};
-    }
-    my $layer = $params{DataSource}->CreateLayer($params{LayerConstructor});
-    my $schema = $layer->GetLayerDefn;
-    for ('IDField', 'ElevField') {
-        $params{$_} = $schema->GetFieldIndex($params{$_}) unless $params{$_} =~ /^[+-]?\d+$/;
-    }
-    $params{ProgressData} = 1 if $params{Progress} and not defined $params{ProgressData};
-    ContourGenerate($self, $params{ContourInterval}, $params{ContourBase}, $params{FixedLevels},
-                    $params{NoDataValue}, $layer, $params{IDField}, $params{ElevField},
-                    $params{Progress}, $params{ProgressData});
-    return $layer;
-}
-
-sub FillNodata {
-    my $self = shift;
-    my $mask = shift;
-    $mask = $self->GetMaskBand unless $mask;
-    my @p = @_;
-    $p[0] = 10 unless defined $p[0];
-    $p[1] = 0 unless defined $p[1];
-    $p[2] = undef unless defined $p[2];
-    $p[3] = undef unless defined $p[3];
-    $p[4] = undef unless defined $p[1];
-    Geo::GDAL::FillNodata($self, $mask, @p);
-}
-*GetBandNumber = *GetBand;
-
-sub ReadRaster {
-    my $self = shift;
-    my ($width, $height) = $self->Size;
-    my ($type) = $self->DataType;
-    my %d = (
-        XOFF => 0,
-        YOFF => 0,
-        XSIZE => $width,
-        YSIZE => $height,
-        BUFXSIZE => undef,
-        BUFYSIZE => undef,
-        BUFTYPE => $type,
-        BUFPIXELSPACE => 0,
-        BUFLINESPACE => 0,
-        RESAMPLEALG => 'NearestNeighbour',
-        PROGRESS => undef,
-        PROGRESSDATA => undef
-        );
-    my %p;
-    my $t;
-    if (defined $_[0]) {
-        $t = uc($_[0]); 
-        $t =~ s/_//g;
-    }
-    if (@_ == 0) {
-    } elsif (ref($_[0]) eq 'HASH') {
-        %p = %{$_[0]};
-    } elsif (@_ % 2 == 0 and (defined $t and exists $d{$t})) {
-        %p = @_;
-    } else {
-        ($p{xoff},$p{yoff},$p{xsize},$p{ysize},$p{buf_xsize},$p{buf_ysize},$p{buf_type},$p{buf_pixel_space},$p{buf_line_space},$p{resample_alg},$p{progress},$p{progress_data}) = @_;
-    }
-    for (keys %p) {
-        my $u = uc($_);
-        $u =~ s/_//g;
-        carp "Unknown named parameter '$_'." unless exists $d{$u};
-        $p{$u} = $p{$_};
-    }
-    for (keys %d) {
-        $p{$_} = $d{$_} unless defined $p{$_};
-    }
-    confess "Unknown resampling algorithm: '$p{RESAMPLEALG}'." 
-        unless exists $Geo::GDAL::RIO_RESAMPLING_STRING2INT{$p{RESAMPLEALG}};
-    $p{RESAMPLEALG} = $Geo::GDAL::RIO_RESAMPLING_STRING2INT{$p{RESAMPLEALG}};
-    unless ($Geo::GDAL::TYPE_INT2STRING{$p{BUFTYPE}}) {
-        confess "Unknown data type: '$p{BUFTYPE}'." 
-            unless exists $Geo::GDAL::TYPE_STRING2INT{$p{BUFTYPE}};
-        $p{BUFTYPE} = $Geo::GDAL::TYPE_STRING2INT{$p{BUFTYPE}};
-    }
-    $self->_ReadRaster($p{XOFF},$p{YOFF},$p{XSIZE},$p{YSIZE},$p{BUFXSIZE},$p{BUFYSIZE},$p{BUFTYPE},$p{BUFPIXELSPACE},$p{BUFLINESPACE},$p{RESAMPLEALG},$p{PROGRESS},$p{PROGRESSDATA});
-}
-
-sub WriteRaster {
-    my $self = shift;
-    my ($width, $height) = $self->Size;
-    my ($type) = $self->DataType;
-    my %d = (
-        XOFF => 0,
-        YOFF => 0,
-        XSIZE => $width,
-        YSIZE => $height,
-        BUF => undef,
-        BUFXSIZE => undef,
-        BUFYSIZE => undef,
-        BUFTYPE => $type,
-        BUFPIXELSPACE => 0,
-        BUFLINESPACE => 0
-        );
-    my %p;
-    my $t;
-    if (defined $_[0]) {
-        $t = uc($_[0]); 
-        $t =~ s/_//g;
-    }
-    if (@_ == 0) {
-    } elsif (ref($_[0]) eq 'HASH') {
-        %p = %{$_[0]};
-    } elsif (@_ % 2 == 0 and (defined $t and exists $d{$t})) {
-        %p = @_;
-    } else {
-        ($p{xoff},$p{yoff},$p{xsize},$p{ysize},$p{buf},$p{buf_xsize},$p{buf_ysize},$p{buf_type},$p{buf_pixel_space},$p{buf_line_space}) = @_;
-    }
-    for (keys %p) {
-        my $u = uc($_);
-        $u =~ s/_//g;
-        carp "Unknown named parameter '$_'." unless exists $d{$u};
-        $p{$u} = $p{$_};
-    }
-    for (keys %d) {
-        $p{$_} = $d{$_} unless defined $p{$_};
-    }
-    unless ($Geo::GDAL::TYPE_INT2STRING{$p{BUFTYPE}}) {
-        confess "Unknown data type: '$p{BUFTYPE}'." 
-            unless exists $Geo::GDAL::TYPE_STRING2INT{$p{BUFTYPE}};
-        $p{BUFTYPE} = $Geo::GDAL::TYPE_STRING2INT{$p{BUFTYPE}};
-    }
-    $self->_WriteRaster($p{XOFF},$p{YOFF},$p{XSIZE},$p{YSIZE},$p{BUF},$p{BUFXSIZE},$p{BUFYSIZE},$p{BUFTYPE},$p{BUFPIXELSPACE},$p{BUFLINESPACE});
-}
-
-sub GetMaskFlags {
-    my $self = shift;
-    my $f = $self->_GetMaskFlags;
-    my @f;
-    for my $flag (keys %MASK_FLAGS) {
-        push @f, $flag if $f & $MASK_FLAGS{$flag};
-    }
-    return wantarray ? @f : $f;
-}
-
-sub CreateMaskBand {
-    my $self = shift;
-    my $f = 0;
-    if (@_ and $_[0] =~ /^\d$/) {
-        $f = shift;
-    } else {
-        for my $flag (@_) {
-            carp "Unknown mask flag: '$flag'." unless $MASK_FLAGS{$flag};
-            $f |= $MASK_FLAGS{$flag};
-        }
-    }
-    $self->_CreateMaskBand($f);
-}
-
-# GetMaskBand should be redefined and the result should be put into 
-# %Geo::GDAL::Dataset::BANDS
-
-# GetOverview should be redefined and the result should be put into 
-# %Geo::GDAL::Dataset::BANDS
-
-sub RegenerateOverview {
-    my $self = shift;
-    #Geo::GDAL::Band overview, scalar resampling, subref callback, scalar callback_data
-    my @p = @_;
-    Geo::GDAL::RegenerateOverview($self, @p);
-}
- 
-sub RegenerateOverviews {
-    my $self = shift;
-    #arrayref overviews, scalar resampling, subref callback, scalar callback_data
-    my @p = @_;
-    Geo::GDAL::RegenerateOverviews($self, @p);
-}
-
-
-
-
-package Geo::GDAL::ColorTable;
-use strict;
-use warnings;
-use Carp;
-use vars qw/
-    %PALETTE_INTERPRETATION_STRING2INT %PALETTE_INTERPRETATION_INT2STRING
-    /;
-for my $string (qw/Gray RGB CMYK HLS/) {
-    my $int = eval "\$Geo::GDAL::Constc::GPI_$string";
-    $PALETTE_INTERPRETATION_STRING2INT{$string} = $int;
-    $PALETTE_INTERPRETATION_INT2STRING{$int} = $string;
-}
-
-sub GetPaletteInterpretation {
-    my $self = shift;
-    return $PALETTE_INTERPRETATION_INT2STRING{GetPaletteInterpretation($self)};
-}
-
-sub SetColorEntry {
-    my $self = shift;
-    my $index = shift;
-    my $color;
-    if (ref($_[0]) eq 'ARRAY') {
-        $color = shift;
-    } else {
-        $color = [@_];
-    }
-    eval {
-        $self->_SetColorEntry($index, $color);
-    };
-    confess $@ if $@;
-}
-
-sub ColorEntry {
-    my $self = shift;
-    my $index = shift;
-    SetColorEntry($self, $index, @_) if @_ > 0;
-    GetColorEntry($self, $index) if defined wantarray;
-}
-
-sub ColorTable {
-    my $self = shift;
-    my @table;
-    if (@_) {
-        my $index = 0;
-        for my $color (@_) {
-            push @table, [ColorEntry($self, $index, @$color)];
-            $index++;
-        }
-    } else {
-        for (my $index = 0; $index < GetCount($self); $index++) {
-            push @table, [ColorEntry($self, $index)];
-        }
-    }
-    return @table;
-}
-*ColorEntries = *ColorTable;
-
-
-
-
-package Geo::GDAL::RasterAttributeTable;
-use strict;
-use warnings;
-use Carp;
-use vars qw/ %BANDS
-    @FIELD_TYPES @FIELD_USAGES
-    %FIELD_TYPE_STRING2INT %FIELD_TYPE_INT2STRING
-    %FIELD_USAGE_STRING2INT %FIELD_USAGE_INT2STRING
-    /;
-for (keys %Geo::GDAL::Const::) {
-    next if /TypeCount/;
-    push(@FIELD_TYPES, $1), next if /^GFT_(\w+)/;
-    push(@FIELD_USAGES, $1), next if /^GFU_(\w+)/;
-}
-for my $string (@FIELD_TYPES) {
-    my $int = eval "\$Geo::GDAL::Constc::GFT_$string";
-    $FIELD_TYPE_STRING2INT{$string} = $int;
-    $FIELD_TYPE_INT2STRING{$int} = $string;
-}
-for my $string (@FIELD_USAGES) {
-    my $int = eval "\$Geo::GDAL::Constc::GFU_$string";
-    $FIELD_USAGE_STRING2INT{$string} = $int;
-    $FIELD_USAGE_INT2STRING{$int} = $string;
-}
-
-sub FieldTypes {
-    return @FIELD_TYPES;
-}
-
-sub FieldUsages {
-    return @FIELD_USAGES;
-}
-
-sub RELEASE_PARENTS {
-    my $self = shift;
-    delete $BANDS{$self};
-}
-
-sub GetUsageOfCol {
-    my($self, $col) = @_;
-    $FIELD_USAGE_INT2STRING{_GetUsageOfCol($self, $col)};
-}
-
-sub GetColOfUsage {
-    my($self, $usage) = @_;
-    _GetColOfUsage($self, $FIELD_USAGE_STRING2INT{$usage});
-}
-
-sub GetTypeOfCol {
-    my($self, $col) = @_;
-    $FIELD_TYPE_INT2STRING{_GetTypeOfCol($self, $col)};
-}
-
-sub Columns {
-    my $self = shift;
-    my %columns;
-    if (@_) { # create columns
-        %columns = @_;
-        for my $name (keys %columns) {
-            $self->CreateColumn($name, $columns{$name}{Type}, $columns{$name}{Usage});
-        }
-    }
-    %columns = ();
-    for my $c (0..$self->GetColumnCount-1) {
-        my $name = $self->GetNameOfCol($c);
-        $columns{$name}{Type} = $self->GetTypeOfCol($c);
-        $columns{$name}{Usage} = $self->GetUsageOfCol($c);
-    }
-    return %columns;
-}
-
-sub CreateColumn {
-    my($self, $name, $type, $usage) = @_;
-    confess "Unknown RAT column type: '$type'." unless exists $FIELD_TYPE_STRING2INT{$type};
-    confess "Unknown RAT column usage: '$usage'." unless exists $FIELD_USAGE_STRING2INT{$usage};
-    for my $color (qw/Red Green Blue Alpha/) {
-        carp "RAT column type will be 'Integer' for usage '$color'." if $usage eq $color and $type ne 'Integer';
-    }
-    $type = $FIELD_TYPE_STRING2INT{$type};
-    $usage = $FIELD_USAGE_STRING2INT{$usage};
-    _CreateColumn($self, $name, $type, $usage);
-}
-
-sub Value {
-    my($self, $row, $column) = @_;
-    SetValueAsString($self, $row, $column, $_[3]) if defined $_[3];
-    return unless defined wantarray;
-    GetValueAsString($self, $row, $column);
-}
-
-sub LinearBinning {
-    my $self = shift;
-    SetLinearBinning($self, @_) if @_ > 0;
-    return unless defined wantarray;
-    my @a = GetLinearBinning($self);
-    return $a[0] ? ($a[1], $a[2]) : ();
-}
-
-
-
-
-package Geo::GDAL::GCP;
-
-*swig_Pixel_get = *Geo::GDALc::GCP_Column_get;
-*swig_Pixel_set = *Geo::GDALc::GCP_Column_set;
-*swig_Line_get = *Geo::GDALc::GCP_Row_get;
-*swig_Line_set = *Geo::GDALc::GCP_Row_set;
-
-
-
-package Geo::GDAL::VSIF;
-use strict;
-use warnings;
-use Carp;
-
-sub Open {
-    my ($path, $mode) = @_;
-    my $self = Geo::GDAL::VSIFOpenL($path, $mode);
-    bless $self, 'Geo::GDAL::VSIF';
-}
-
-sub Write {
-    my ($self, $data) = @_;
-    Geo::GDAL::VSIFWriteL($data, $self);
-}
-
-sub Close {
-    my ($self, $data) = @_;
-    eval {
-        Geo::GDAL::VSIFCloseL($self);
-    };
-    if ($@) {
-        confess "Cannot close file: $@.";
-    }
-}
-
-sub Read {
-    my ($self, $count) = @_;
-    Geo::GDAL::VSIFReadL($count, $self);
-}
-
-sub Seek {
-    my ($self, $offset, $whence) = @_;
-    Geo::GDAL::VSIFSeekL($self, $offset, $whence);
-}
-
-sub Tell {
-    my ($self) = @_;
-    Geo::GDAL::VSIFTellL($self);
-}
-
-sub Truncate {
-    my ($self, $new_size) = @_;
-    eval {
-        Geo::GDAL::VSIFTruncateL($self, $new_size);
-    };
-    if ($@) {
-        confess "Cannot truncate file: $@.";
-    }
-}
-
-sub MkDir {
-    my ($path) = @_;
-    my $mode = 0; # unused in CPL
-    eval {
-        Geo::GDAL::Mkdir($path, $mode);
-    };
-    if ($@) {
-        confess "Cannot make directory \"$path\": $@.";
-    }
-}
-*Mkdir = *MkDir;
-
-sub ReadDir {
-    my ($path) = @_;
-    Geo::GDAL::ReadDir($path);
-}
-
-sub ReadDirRecursive {
-    my ($path) = @_;
-    Geo::GDAL::ReadDirRecursive($path);
-}
-
-sub Rename {
-    my ($old, $new) = @_;
-    eval {
-        Geo::GDAL::Rename($old, $new);
-    };
-    if ($@) {
-        confess "Cannot rename file \"$old\": $@.";
-    }
-}
-
-sub RmDir {
-    my ($dirname, $recursive) = @_;
-    eval {
-        if (!$recursive) {
-            Geo::GDAL::Rmdir($dirname);
-        } else {
-            for my $f (ReadDir($dirname)) {
-                next if $f eq '..' or $f eq '.';
-                my @s = Stat($dirname.'/'.$f);
-                if ($s[0] eq 'f') {
-                    Unlink($dirname.'/'.$f);
-                } elsif ($s[0] eq 'd') {
-                    Rmdir($dirname.'/'.$f, 1);
-                    Rmdir($dirname.'/'.$f);
-                }
-            }
-            RmDir($dirname);
-        }
-    };
-    if ($@) {
-        my $r = $recursive ? ' recursively' : '';
-        confess "Cannot remove directory \"$dirname\"$r: $@.";
-    }
-}
-*Rmdir = *RmDir;
-
-sub Stat {
-    my ($path) = @_;
-    eval {
-        Geo::GDAL::Stat($path);
-    };
-    if ($@) {
-        confess "Cannot stat file \"$path\": $@.";
-    }
-}
-
-sub Unlink {
-    my ($filename) = @_;
-    eval {
-        Geo::GDAL::Unlink($filename);
-    };
-    if ($@) {
-        confess "Cannot unlink file \"$filename\": $@.";
-    }
-}
-
-
-
-
-package Geo::GDAL::GeoTransform;
-use strict;
-use warnings;
-use Carp;
-
-sub new {
-    my $class = shift;
-    my $self;
-    if (@_ == 0) {
-        $self = [0,1,0,0,0,1];
-    } elsif (@_ == 1) {
-        $self = $_[0];
-    } else {
-        my @a = @_;
-        $self = \@a;
-    }
-    bless $self, $class;
-    return $self;
-}
-
-sub FromGCPs {
-    my @GCPs;
-    my $ApproxOK = 1;
-    if (ref($_[0]) eq 'ARRAY') {
-        @GCPs = @{$_[0]};
-        $ApproxOK = $_[1] if defined $_[1];
-    } else {
-        @GCPs = @_;
-        $ApproxOK = pop @GCPs if !ref($GCPs[$#GCPs]);
-    }
-    my $self = Geo::GDAL::GCPsToGeoTransform(\@GCPs, $ApproxOK);
-    bless $self, 'Geo::GDAL::GetTransform';
-    return $self;
-}
-
-sub Apply {
-    my ($self, $columns, $rows) = @_;
-    my (@x, @y);
-    for my $i (0..$#$columns) {
-        ($x[$i], $y[$i]) = 
-            Geo::GDAL::ApplyGeoTransform($self, $columns->[$i], $rows->[$i]);
-    }
-    return (\@x, \@y);
-}
-
-sub Inv {
-    my $self = shift;
-    my @inv = Geo::GDAL::InvGeoTransform($self);
-    unless (defined wantarray) {
-        @$self = @inv;
-    } else {
-        return new(@inv);
-    }
-}
-
-1;
diff --git a/swig/perl/lib/Geo/GDAL/Const.pm b/swig/perl/lib/Geo/GDAL/Const.pm
deleted file mode 100644
index ac7c710..0000000
--- a/swig/perl/lib/Geo/GDAL/Const.pm
+++ /dev/null
@@ -1,194 +0,0 @@
-# This file was automatically generated by SWIG (http://www.swig.org).
-# Version 2.0.12
-#
-# Do not make changes to this file unless you know what you are doing--modify
-# the SWIG interface file instead.
-
-package Geo::GDAL::Const;
-use base qw(Exporter);
-use base qw(DynaLoader);
-package Geo::GDAL::Constc;
-bootstrap Geo::GDAL::Const;
-package Geo::GDAL::Const;
- at EXPORT = qw();
-
-# ---------- BASE METHODS -------------
-
-package Geo::GDAL::Const;
-
-sub TIEHASH {
-    my ($classname,$obj) = @_;
-    return bless $obj, $classname;
-}
-
-sub CLEAR { }
-
-sub FIRSTKEY { }
-
-sub NEXTKEY { }
-
-sub FETCH {
-    my ($self,$field) = @_;
-    my $member_func = "swig_${field}_get";
-    $self->$member_func();
-}
-
-sub STORE {
-    my ($self,$field,$newval) = @_;
-    my $member_func = "swig_${field}_set";
-    $self->$member_func($newval);
-}
-
-sub this {
-    my $ptr = shift;
-    return tied(%$ptr);
-}
-
-
-# ------- FUNCTION WRAPPERS --------
-
-package Geo::GDAL::Const;
-
-
-# ------- VARIABLE STUBS --------
-
-package Geo::GDAL::Const;
-
-*GDT_Unknown = *Geo::GDAL::Constc::GDT_Unknown;
-*GDT_Byte = *Geo::GDAL::Constc::GDT_Byte;
-*GDT_UInt16 = *Geo::GDAL::Constc::GDT_UInt16;
-*GDT_Int16 = *Geo::GDAL::Constc::GDT_Int16;
-*GDT_UInt32 = *Geo::GDAL::Constc::GDT_UInt32;
-*GDT_Int32 = *Geo::GDAL::Constc::GDT_Int32;
-*GDT_Float32 = *Geo::GDAL::Constc::GDT_Float32;
-*GDT_Float64 = *Geo::GDAL::Constc::GDT_Float64;
-*GDT_CInt16 = *Geo::GDAL::Constc::GDT_CInt16;
-*GDT_CInt32 = *Geo::GDAL::Constc::GDT_CInt32;
-*GDT_CFloat32 = *Geo::GDAL::Constc::GDT_CFloat32;
-*GDT_CFloat64 = *Geo::GDAL::Constc::GDT_CFloat64;
-*GDT_TypeCount = *Geo::GDAL::Constc::GDT_TypeCount;
-*GA_ReadOnly = *Geo::GDAL::Constc::GA_ReadOnly;
-*GA_Update = *Geo::GDAL::Constc::GA_Update;
-*GF_Read = *Geo::GDAL::Constc::GF_Read;
-*GF_Write = *Geo::GDAL::Constc::GF_Write;
-*GRIORA_NearestNeighbour = *Geo::GDAL::Constc::GRIORA_NearestNeighbour;
-*GRIORA_Bilinear = *Geo::GDAL::Constc::GRIORA_Bilinear;
-*GRIORA_Cubic = *Geo::GDAL::Constc::GRIORA_Cubic;
-*GRIORA_CubicSpline = *Geo::GDAL::Constc::GRIORA_CubicSpline;
-*GRIORA_Lanczos = *Geo::GDAL::Constc::GRIORA_Lanczos;
-*GRIORA_Average = *Geo::GDAL::Constc::GRIORA_Average;
-*GRIORA_Mode = *Geo::GDAL::Constc::GRIORA_Mode;
-*GRIORA_Gauss = *Geo::GDAL::Constc::GRIORA_Gauss;
-*GCI_Undefined = *Geo::GDAL::Constc::GCI_Undefined;
-*GCI_GrayIndex = *Geo::GDAL::Constc::GCI_GrayIndex;
-*GCI_PaletteIndex = *Geo::GDAL::Constc::GCI_PaletteIndex;
-*GCI_RedBand = *Geo::GDAL::Constc::GCI_RedBand;
-*GCI_GreenBand = *Geo::GDAL::Constc::GCI_GreenBand;
-*GCI_BlueBand = *Geo::GDAL::Constc::GCI_BlueBand;
-*GCI_AlphaBand = *Geo::GDAL::Constc::GCI_AlphaBand;
-*GCI_HueBand = *Geo::GDAL::Constc::GCI_HueBand;
-*GCI_SaturationBand = *Geo::GDAL::Constc::GCI_SaturationBand;
-*GCI_LightnessBand = *Geo::GDAL::Constc::GCI_LightnessBand;
-*GCI_CyanBand = *Geo::GDAL::Constc::GCI_CyanBand;
-*GCI_MagentaBand = *Geo::GDAL::Constc::GCI_MagentaBand;
-*GCI_YellowBand = *Geo::GDAL::Constc::GCI_YellowBand;
-*GCI_BlackBand = *Geo::GDAL::Constc::GCI_BlackBand;
-*GCI_YCbCr_YBand = *Geo::GDAL::Constc::GCI_YCbCr_YBand;
-*GCI_YCbCr_CrBand = *Geo::GDAL::Constc::GCI_YCbCr_CrBand;
-*GCI_YCbCr_CbBand = *Geo::GDAL::Constc::GCI_YCbCr_CbBand;
-*GRA_NearestNeighbour = *Geo::GDAL::Constc::GRA_NearestNeighbour;
-*GRA_Bilinear = *Geo::GDAL::Constc::GRA_Bilinear;
-*GRA_Cubic = *Geo::GDAL::Constc::GRA_Cubic;
-*GRA_CubicSpline = *Geo::GDAL::Constc::GRA_CubicSpline;
-*GRA_Lanczos = *Geo::GDAL::Constc::GRA_Lanczos;
-*GRA_Average = *Geo::GDAL::Constc::GRA_Average;
-*GRA_Mode = *Geo::GDAL::Constc::GRA_Mode;
-*GPI_Gray = *Geo::GDAL::Constc::GPI_Gray;
-*GPI_RGB = *Geo::GDAL::Constc::GPI_RGB;
-*GPI_CMYK = *Geo::GDAL::Constc::GPI_CMYK;
-*GPI_HLS = *Geo::GDAL::Constc::GPI_HLS;
-*CXT_Element = *Geo::GDAL::Constc::CXT_Element;
-*CXT_Text = *Geo::GDAL::Constc::CXT_Text;
-*CXT_Attribute = *Geo::GDAL::Constc::CXT_Attribute;
-*CXT_Comment = *Geo::GDAL::Constc::CXT_Comment;
-*CXT_Literal = *Geo::GDAL::Constc::CXT_Literal;
-*CE_None = *Geo::GDAL::Constc::CE_None;
-*CE_Debug = *Geo::GDAL::Constc::CE_Debug;
-*CE_Warning = *Geo::GDAL::Constc::CE_Warning;
-*CE_Failure = *Geo::GDAL::Constc::CE_Failure;
-*CE_Fatal = *Geo::GDAL::Constc::CE_Fatal;
-*CPLE_None = *Geo::GDAL::Constc::CPLE_None;
-*CPLE_AppDefined = *Geo::GDAL::Constc::CPLE_AppDefined;
-*CPLE_OutOfMemory = *Geo::GDAL::Constc::CPLE_OutOfMemory;
-*CPLE_FileIO = *Geo::GDAL::Constc::CPLE_FileIO;
-*CPLE_OpenFailed = *Geo::GDAL::Constc::CPLE_OpenFailed;
-*CPLE_IllegalArg = *Geo::GDAL::Constc::CPLE_IllegalArg;
-*CPLE_NotSupported = *Geo::GDAL::Constc::CPLE_NotSupported;
-*CPLE_AssertionFailed = *Geo::GDAL::Constc::CPLE_AssertionFailed;
-*CPLE_NoWriteAccess = *Geo::GDAL::Constc::CPLE_NoWriteAccess;
-*CPLE_UserInterrupt = *Geo::GDAL::Constc::CPLE_UserInterrupt;
-*OF_ALL = *Geo::GDAL::Constc::OF_ALL;
-*OF_RASTER = *Geo::GDAL::Constc::OF_RASTER;
-*OF_VECTOR = *Geo::GDAL::Constc::OF_VECTOR;
-*OF_READONLY = *Geo::GDAL::Constc::OF_READONLY;
-*OF_UPDATE = *Geo::GDAL::Constc::OF_UPDATE;
-*OF_SHARED = *Geo::GDAL::Constc::OF_SHARED;
-*OF_VERBOSE_ERROR = *Geo::GDAL::Constc::OF_VERBOSE_ERROR;
-*DMD_LONGNAME = *Geo::GDAL::Constc::DMD_LONGNAME;
-*DMD_HELPTOPIC = *Geo::GDAL::Constc::DMD_HELPTOPIC;
-*DMD_MIMETYPE = *Geo::GDAL::Constc::DMD_MIMETYPE;
-*DMD_EXTENSION = *Geo::GDAL::Constc::DMD_EXTENSION;
-*DMD_EXTENSIONS = *Geo::GDAL::Constc::DMD_EXTENSIONS;
-*DMD_CONNECTION_PREFIX = *Geo::GDAL::Constc::DMD_CONNECTION_PREFIX;
-*DMD_CREATIONOPTIONLIST = *Geo::GDAL::Constc::DMD_CREATIONOPTIONLIST;
-*DMD_CREATIONDATATYPES = *Geo::GDAL::Constc::DMD_CREATIONDATATYPES;
-*DMD_CREATIONFIELDDATATYPES = *Geo::GDAL::Constc::DMD_CREATIONFIELDDATATYPES;
-*DMD_SUBDATASETS = *Geo::GDAL::Constc::DMD_SUBDATASETS;
-*DCAP_OPEN = *Geo::GDAL::Constc::DCAP_OPEN;
-*DCAP_CREATE = *Geo::GDAL::Constc::DCAP_CREATE;
-*DCAP_CREATECOPY = *Geo::GDAL::Constc::DCAP_CREATECOPY;
-*DCAP_VIRTUALIO = *Geo::GDAL::Constc::DCAP_VIRTUALIO;
-*DCAP_RASTER = *Geo::GDAL::Constc::DCAP_RASTER;
-*DCAP_VECTOR = *Geo::GDAL::Constc::DCAP_VECTOR;
-*DCAP_NOTNULL_FIELDS = *Geo::GDAL::Constc::DCAP_NOTNULL_FIELDS;
-*DCAP_DEFAULT_FIELDS = *Geo::GDAL::Constc::DCAP_DEFAULT_FIELDS;
-*DCAP_NOTNULL_GEOMFIELDS = *Geo::GDAL::Constc::DCAP_NOTNULL_GEOMFIELDS;
-*CPLES_BackslashQuotable = *Geo::GDAL::Constc::CPLES_BackslashQuotable;
-*CPLES_XML = *Geo::GDAL::Constc::CPLES_XML;
-*CPLES_URL = *Geo::GDAL::Constc::CPLES_URL;
-*CPLES_SQL = *Geo::GDAL::Constc::CPLES_SQL;
-*CPLES_CSV = *Geo::GDAL::Constc::CPLES_CSV;
-*GFT_Integer = *Geo::GDAL::Constc::GFT_Integer;
-*GFT_Real = *Geo::GDAL::Constc::GFT_Real;
-*GFT_String = *Geo::GDAL::Constc::GFT_String;
-*GFU_Generic = *Geo::GDAL::Constc::GFU_Generic;
-*GFU_PixelCount = *Geo::GDAL::Constc::GFU_PixelCount;
-*GFU_Name = *Geo::GDAL::Constc::GFU_Name;
-*GFU_Min = *Geo::GDAL::Constc::GFU_Min;
-*GFU_Max = *Geo::GDAL::Constc::GFU_Max;
-*GFU_MinMax = *Geo::GDAL::Constc::GFU_MinMax;
-*GFU_Red = *Geo::GDAL::Constc::GFU_Red;
-*GFU_Green = *Geo::GDAL::Constc::GFU_Green;
-*GFU_Blue = *Geo::GDAL::Constc::GFU_Blue;
-*GFU_Alpha = *Geo::GDAL::Constc::GFU_Alpha;
-*GFU_RedMin = *Geo::GDAL::Constc::GFU_RedMin;
-*GFU_GreenMin = *Geo::GDAL::Constc::GFU_GreenMin;
-*GFU_BlueMin = *Geo::GDAL::Constc::GFU_BlueMin;
-*GFU_AlphaMin = *Geo::GDAL::Constc::GFU_AlphaMin;
-*GFU_RedMax = *Geo::GDAL::Constc::GFU_RedMax;
-*GFU_GreenMax = *Geo::GDAL::Constc::GFU_GreenMax;
-*GFU_BlueMax = *Geo::GDAL::Constc::GFU_BlueMax;
-*GFU_AlphaMax = *Geo::GDAL::Constc::GFU_AlphaMax;
-*GFU_MaxCount = *Geo::GDAL::Constc::GFU_MaxCount;
-*GMF_ALL_VALID = *Geo::GDAL::Constc::GMF_ALL_VALID;
-*GMF_PER_DATASET = *Geo::GDAL::Constc::GMF_PER_DATASET;
-*GMF_ALPHA = *Geo::GDAL::Constc::GMF_ALPHA;
-*GMF_NODATA = *Geo::GDAL::Constc::GMF_NODATA;
-*GARIO_PENDING = *Geo::GDAL::Constc::GARIO_PENDING;
-*GARIO_UPDATE = *Geo::GDAL::Constc::GARIO_UPDATE;
-*GARIO_ERROR = *Geo::GDAL::Constc::GARIO_ERROR;
-*GARIO_COMPLETE = *Geo::GDAL::Constc::GARIO_COMPLETE;
-*GTO_TIP = *Geo::GDAL::Constc::GTO_TIP;
-*GTO_BIT = *Geo::GDAL::Constc::GTO_BIT;
-*GTO_BSQ = *Geo::GDAL::Constc::GTO_BSQ;
-1;
diff --git a/swig/perl/lib/Geo/GNM.dox b/swig/perl/lib/Geo/GNM.dox
new file mode 100644
index 0000000..de019ef
--- /dev/null
+++ b/swig/perl/lib/Geo/GNM.dox
@@ -0,0 +1,14 @@
+## @class Geo::GNM
+# @brief Base class for geographical networks in GDAL.
+
+
+## @class Geo::GNM::MajorObject
+# @isa (Geo::GNM)
+
+
+## @class Geo::GNM::Network
+# @isa (Geo::GNM::MajorObject Geo::GNM)
+
+
+## @class Geo::GNM::GenericNetwork
+# @isa ( Geo::GNM::Network Geo::GNM )
\ No newline at end of file
diff --git a/swig/perl/lib/Geo/OGR.dox b/swig/perl/lib/Geo/OGR.dox
index b7a4123..2166c26 100644
--- a/swig/perl/lib/Geo/OGR.dox
+++ b/swig/perl/lib/Geo/OGR.dox
@@ -11,6 +11,8 @@
 
 ## @ignore ApproximateArcAngles
 
+## @ignore OLMD_FID64
+
 ## @ignore ForceTo
 ## @ignore ForceToLineString
 ## @ignore ForceToMultiLineString
@@ -18,18 +20,17 @@
 ## @ignore ForceToMultiPolygon
 ## @ignore ForceToPolygon
 
-## @ignore GeneralCmdLineProcessor
 ## @ignore GeometryTypeToName
 ## @ignore GetFieldTypeName
 
 ## @ignore GeometryType
 ## @ignore GetFieldSubTypeName
 
-## @cmethod @GeometryTypes()
+## @sub @GeometryTypes()
 # @return a list of all geometry types, currently:
 # +list Geo::OGR wkb 25DBit,25Bit,NDR,XDR
 
-## @cmethod list ByteOrders
+## @sub list ByteOrders
 # @return a list of byte order types, XDR and NDR. XDR denotes
 # big-endian and NDR denotes little-endian.
 
@@ -49,232 +50,78 @@
 ## @ignore CreateGeometryFromGML
 ## @ignore CreateGeometryFromJson
 
-## @ignore Drivers
-## @ignore GetDriverCount
-## @ignore GetDriverByName
-## @ignore Driver
+## @method SetGenerate_DB2_V72_BYTE_ORDER($Generate_DB2_V72_BYTE_ORDER)
+# Needed only on IBM DB2.
+
+## @ignore NullFID
 
-## @method @GetDriverNames()
-# @return a list of the names of available Geo::OGR::Drivers.
+## @ignore GetDriver
+## @ignore GetDriverCount
+## @ignore GetDriverNames
 
-## @method Geo::OGR::Driver GetDriver($name)
-# @param name a driver name. One of Geo::OGR::GetDriverNames.
-# @return a Geo::OGR::Driver object that represents the internal driver.
+## @sub @Drivers()
+# @note Use Geo::GDAL::Drivers for raster drivers.
+# @return a list of all available GDAL vector drivers.
 
-## @method $GetOpenDSCount()
-# @return the number of all open data sources.
+## @sub @DriverNames()
+# A.k.a GetDriverNames
+# @note Use Geo::GDAL::DriverNames for raster drivers.
+# @return a list of the short names of all available GDAL vector drivers.
 
-## @method SetGenerate_DB2_V72_BYTE_ORDER($Generate_DB2_V72_BYTE_ORDER)
-# Needed only on IBM DB2.
+## @sub Geo::GDAL::Driver Driver($name)
+# A.k.a GetDriver.
+# @param name the short name of the driver.
+# @note No check is made that the driver is actually a vector driver.
+# @return a Geo::GDAL::Driver object.
 
-## @method Geo::OGR::DataSource GetOpenDS($number)
-# @param number The number of the requested data source.
-# @return a new Geo::OGR::DataSource object.
 
-## @method Geo::OGR::DataSource Open($name, $update = 0)
+## @method Geo::GDAL::Dataset Open($name, $update = 0)
+# Open a vector data source.
 # @param name The data source string (directory, filename, etc.).
-# @param update Whether to open the data source in update mode.
-# @return a new Geo::OGR::DataSource object.
+# @param update Whether to open the data source in update mode (default is not).
+# @return a new Geo::GDAL::Dataset object.
 
-## @method Geo::OGR::DataSource OpenShared($name, $update = 0)
+## @method Geo::GDAL::Dataset OpenShared($name, $update = 0)
+# Open a vector data source in shared mode.
 # @param name The data source string (directory, filename, etc.).
 # @param update Whether to open the data source in update mode.
-# @return a new Geo::OGR::DataSource object.
-
-## @ignore NullFID
-
+# @return a new Geo::GDAL::Dataset object.
 
 
 
 ## @class Geo::OGR::Driver
-# @brief A vector format driver.
-#
-# A driver may, depending on its capabilities, create, open, copy, and
-# delete data sources.
-# @isa (Geo::OGR)
-
-## @ignore Register
-## @ignore Deregister
-
-## @method @Capabilities()
-# Both a class and an object method.
-# @return a list of capabilities. The object method returns a list of
-# the capabilities the driver has. The class method returns a list of
-# all potential capabilities a driver may have. These are currently:
-# +list Geo::OGR ODrC
-#
-# Examples:
-# \code
-# @all_capabilities = Geo::OGR::Driver::Capabilities;
-# @capabilities_of_a_driver = Geo::OGR::Driver('KML')->Capabilities;
-# \endcode
-
-## @method $TestCapability($cap)
-# @param cap A capability string.
-# @return boolean value.
+# @brief A vector format driver. This is a legacy class which
+# should not be used in new code. Use Geo::GDAL::Driver.
 
-## @ignore CreateDataSource
+## @method Open
+# The same as Geo::OGR::Open except that only this driver is allowed.
 
-## @method Geo::OGR::DataSource Create($name, hashref options = undef )
-# Create an OGR data source object.
-# @note a.k.a. CreateDataSource
+## @method Geo::GDAL::Dataset Create($name, hashref options = undef )
+# Create a new vector data source using this driver.
 # @param name The data source name.
-# @param options Driver specific options.
-#
-# Usage:
-# \code
-# $ds = Geo::OGR::Driver('driver name')->Create('data source name', {});
-# \endcode
-# @return a new Geo::OGR::DataSource object.
-
-## @ignore CopyDataSource
-
-## @method Geo::OGR::DataSource Copy(Geo::OGR::DataSource source, $name, arrayref options = undef)
-# Copy an OGR data source object.
-# @note a.k.a. CopyDataSource
-# @param source the Geo::OGR::DataSource object to be copied.
-# @param name the name for the new data source.
-# @param options driver specific options.
-# @return a new Geo::OGR::DataSource object.
-
-## @ignore OpenDataSource
-
-## @method Geo::OGR::DataSource Open($name, $update = 0)
-# Open an OGR data source object. Alternative name: OpenDataSource.
-# @note a.k.a. GetDataSource
-# @param name the name of data source.
-# @param update whether to open the data source in update mode.
-# @return a new Geo::OGR::DataSource object
-
-## @ignore DeleteDataSource
-
-## @method Delete($name)
-# Delete an OGR data source.
-# @note a.k.a. DeleteDataSource
-# @param name The name of data source.
-
-## @ignore GetName
-
-## @method $Name()
-# @note a.k.a. GetName
-# @return the name of the driver.
+# @param options Driver specific dataset creation options. 
 
+## @method Geo::GDAL::Dataset Copy(Geo::GDAL::Dataset source, $name, arrayref options = undef)
+# Copy a vector data source into a new data source with this driver.
+# @param source The Geo::GDAL::Dataset object to be copied.
+# @param name The name for the new data source.
+# @param options Driver specific options. In addition to options
+# specified in GDAL documentation the option STRICT can be set to 'NO'
+# for a more relaxed copy. Otherwise the STRICT is 'YES'.
+# @note The order of the first two parameters is different from that in Geo::GDAL::Driver::Copy.
+# @return a new Geo::GDAL::Dataset object.
 
 
 
 ## @class Geo::OGR::DataSource
-# @brief A source and/or storage of vector data layers.
-#
-# A data source object may, depending on its capabilities, create,
-# open (as such or using GDAL SQL), copy, and delete layers.
-# @isa (Geo::OGR)
+# @brief A vector dataset. This is a legacy class which should not be
+# used in new code. Use Geo::GDAL::Dataset.
 
-## @ignore SyncToDisk
+## @sub Geo::GDAL::Dataset Open
+# The same as Geo::OGR::Open
 
-## @method @Capabilities()
-# Both a class and an object method.
-# @return a list of capabilities. The object method returns a list of
-# all capabilities the data source has. The class method returns a
-# list of all potential capabilities a data source may have. These are
-# currently:
-# +list Geo::OGR ODsC
-
-## @method $TestCapability($cap)
-# @param cap A capability string.
-# @return a boolean value indicating whether the data source has the
-# specified capability.
-
-## @cmethod Geo::OGR::DataSource Open($name, $update = 0)
-# An example:
-# \code
-# use Geo::GDAL;
-# $ds = Geo::OGR::DataSource::Open('/data/roads.shp');
-# \endcode
-# @param name The data source name (directory, filename, etc.).
-# @param update Whether to open the data source in update mode.
-# @return a new Geo::OGR::DataSource object.
-
-## @cmethod Geo::OGR::DataSource OpenShared($name, $update = 0)
-# @param name The data source name (directory, filename, etc.).
-# @param update Whether to open the data source in update mode.
-# @return a new Geo::OGR::DataSource object.
-
-## @ignore GetLayerByIndex
-## @ignore GetLayerByName
-## @ignore Layer
-
-## @method Geo::OGR::Layer GetLayer($name)
-# @param name the name of the requested layer. If not given, then
-# returns the first layer in the data source.
-# @return a new Geo::OGR::Layer object that represents the layer
-# in the data source.
-
-## @ignore GetLayerCount
-## @ignore Layers
-
-## @method @GetLayerNames()
-# @note Delivers the functionality of undocumented method GetLayerCount.
-# @return a list of the names of the layers this data source provides.
-
-## @method Geo::OGR::Driver GetDriver()
-# @return a Geo::OGR::Driver object for this data source.
-
-## @method $GetName()
-# @return the name of this data source.
-
-## @method Geo::OGR::Layer CreateLayer(%params)
-# @brief Create a new layer into this data source.
-#
-# @param %params A list of named parameters:
-# - \a Name (scalar) name for the new layer.
-# - \a Fields (array reference) a list of field definitions as in 
-# Geo::OGR::Layer::CreateField.
-# - \a ApproxOK (boolean value, default is true) a flag, which is forwarded to Geo::OGR::Layer::CreateField.
-# - \a Options (hash reference) driver specific hash of layer creation options.
-# - \a Schema (hash reference, deprecated) may contain keys Name, Fields, GeomFields, GeometryType.
-# - \a SRS (scalar, deprecated) the spatial reference for the default geometry field.
-# - \a GeometryType (scalar) the type of the default geometry field (if only one geometry field).
-#
-# @note If Fields or Schema|Fields is not given, a default geometry
-# field (Name => '', GeometryType => 'Unknown') is created. The type
-# can be also set with the named parameter.
-#
-# Example:
-# \code
-# my $roads = Geo::OGR::Driver('Memory')->Create('road')->
-# .   CreateLayer(
-# .       Fields => [ { Name => 'class', 
-# .                     Type => 'Integer' },
-# .                   { Name => 'geom', 
-# .                     Type => 'LineString25D' } ] );
-# \endcode
-# @return a new Geo::OGR::Layer object.
-
-## @method Geo::OGR::Layer CopyLayer($layer, $name, hashref options = undef)
-# @param layer A Geo::OGR::Layer object to be copied.
-# @param name A name for the new layer.
-# @param options A ref to a hash of format specific options.
-# @return a new Geo::OGR::Layer object.
-
-## @method DeleteLayer($name)
-# Deletes a layer from the data source. Note that if there is a layer
-# object for the deleted layer, it becomes unusable.
-# @param name name of the layer to delete.
-
-## @method Geo::OGR::Layer ExecuteSQL($statement, $geom = undef, $dialect = "")
-# @param statement A SQL statement.
-# @param geom A Geo::OGR::Geometry object.
-# @param dialect
-# @return a new Geo::OGR::Layer object. The data source object will
-# exist as long as the layer object exists.
-
-## @method ReleaseResultSet($layer)
-# @param layer A layer the has been created with ExecuteSQL.
-# @note There is no need to call this method. The result set layer is
-# released in the destructor of the layer that was created with SQL.
-
-## @ignore GetRefCount
-## @ignore GetSummaryRefCount
+## @sub Geo::GDAL::Dataset OpenShared
+# The same as Geo::OGR::OpenShared
 
 
 
@@ -294,21 +141,25 @@
 # compared to each other with methods Clip, Erase, Identity,
 # Intersection, SymDifference, Union, and Update.
 # @isa (Geo::OGR)
+#
+# A layer may have metadata OLMD_FID64 => 'YES' if it holds features
+# with 64 bit FIDs. The metadata of a layer can be obtained with
+# GetMetadata method.
 
 ## @method @Capabilities()
-# Both a class and an object method.
+# Both a package subroutine and an object method.
 # @return a list of capabilities. The object method returns a list of
-# the capabilities the layer has. The class method returns a list of
+# the capabilities the layer has. The package subroutine returns a list of
 # all potential capabilities a layer may have. These are currently:
 # +list Geo::OGR OLC
 #
 # Examples:
 # \code
-# @cap = Geo::OGR::Layer::Capabilities(); # the class method
+# @cap = Geo::OGR::Layer::Capabilities(); # the package subroutine
 # @cap = $layer->Capabilities(); # the object method
 # \endcode
 
-## @method Clip(Geo::OGR::Layer method, Geo::OGR::Layer result, hashref options, subref callback, $callback_data)
+## @method Clip(Geo::OGR::Layer method, Geo::OGR::Layer result, hashref options, coderef callback, $callback_data)
 # Clip off areas that are not covered by the method layer. The schema
 # of the result layer can be set before calling this method, or is
 # initialized to to contain all fields from
@@ -320,7 +171,7 @@
 # be called with parameters (number progress, string msg, callback_data)
 # @param callback_data [optional]
 
-## @method Intersection(Geo::OGR::Layer method, Geo::OGR::Layer result, hashref options, subref callback, $callback_data)
+## @method Intersection(Geo::OGR::Layer method, Geo::OGR::Layer result, hashref options, coderef callback, $callback_data)
 # The result layer contains features whose geometries represent areas
 # that are common between features in the input layer and in the
 # method layer. The schema of the result layer can be set before
@@ -333,7 +184,7 @@
 # be called with parameters (number progress, string msg, callback_data)
 # @param callback_data [optional]
 
-## @method Union(Geo::OGR::Layer method, Geo::OGR::Layer result, hashref options, subref callback, $callback_data)
+## @method Union(Geo::OGR::Layer method, Geo::OGR::Layer result, hashref options, coderef callback, $callback_data)
 # The result layer contains features whose geometries represent areas
 # that are in either in the input layer or in the method layer. The
 # schema of the result layer can be set before calling this method, or
@@ -345,7 +196,7 @@
 # be called with parameters (number progress, string msg, callback_data)
 # @param callback_data [optional]
 
-## @method SymDifference(Geo::OGR::Layer method, Geo::OGR::Layer result, hashref options, subref callback, $callback_data)
+## @method SymDifference(Geo::OGR::Layer method, Geo::OGR::Layer result, hashref options, coderef callback, $callback_data)
 # The result layer contains features whose geometries represent areas
 # that are in either in the input layer or in the method layer but not
 # in both. The features in the result layer have attributes from both
@@ -361,7 +212,7 @@
 # be called with parameters (number progress, string msg, callback_data)
 # @param callback_data [optional]
 
-## @method Identity(Geo::OGR::Layer method, Geo::OGR::Layer result, hashref options, subref callback, $callback_data)
+## @method Identity(Geo::OGR::Layer method, Geo::OGR::Layer result, hashref options, coderef callback, $callback_data)
 # The result layer contains features whose geometries represent areas
 # that are in the input layer. The features in the result layer have
 # attributes from both input and method layers. The schema of the
@@ -374,7 +225,7 @@
 # be called with parameters (number progress, string msg, callback_data)
 # @param callback_data [optional]
 
-## @method Update(Geo::OGR::Layer method, Geo::OGR::Layer result, hashref options, subref callback, $callback_data)
+## @method Update(Geo::OGR::Layer method, Geo::OGR::Layer result, hashref options, coderef callback, $callback_data)
 # The result layer contains features whose geometries represent areas
 # that are either in the input layer or in the method layer. The
 # features in the result layer have areas of the features of the
@@ -390,7 +241,7 @@
 # be called with parameters (number progress, string msg, callback_data)
 # @param callback_data [optional]
 
-## @method Erase(Geo::OGR::Layer method, Geo::OGR::Layer result, hashref options, subref callback, $callback_data)
+## @method Erase(Geo::OGR::Layer method, Geo::OGR::Layer result, hashref options, coderef callback, $callback_data)
 # The result layer contains features whose geometries represent areas
 # that are in the input layer but not in the method layer. The
 # features in the result layer have attributes from the input
@@ -581,6 +432,7 @@
 # @param feature a Geo::OGR::Feature object or reference to feature
 # data in a hash (as in Geo::OGR::Feature::Row) or in an array (as in
 # Geo::OGR::Feature::Tuple)
+# @return the new feature.
 
 ## @method DeleteFeature($fid)
 # @param fid feature id
@@ -601,12 +453,10 @@
 # @param force compute the extent even if it is expensive
 # @note In scalar context returns a reference to an anonymous array
 # containing the extent.
-# @note The order of values is different from those returned by
-# Geo::OGR::Geometry::GetEnvelope.
-# @return the extent ($minx, $miny, $maxx, $maxy)
+# @return the extent ($minx, $maxx, $miny, $maxy)
 
 # @param force
-# @return the extent = ($minx, $miny, $maxx, $maxy) as a listref
+# @return the extent = ($minx, $maxx, $miny, $maxy) as a listref
 
 ## @method StartTransaction()
 
@@ -625,16 +475,15 @@
 ## @ignore GetGeometryColumn
 ## @ignore GetGeomType
 
+## @method $GeometryType($field)
+# @param field the name or index of the spatial field.
+# @return the geometry type of the spatial field.
+
 ## @method @GetFieldNames()
 # @return a list of the names of the fields in this layer. The
 # non-geometry field names are first in the list and then the geometry
 # fields.
 
-## @method $GetFieldDef($name)
-# @param name name of the field.
-# @return the definition object of the given field. Either
-# Geo::OGR::FieldDefn or Geo::OGR::GeomFieldDefn.
-
 ## @method SetIgnoredFields(@fields)
 # @param fields a list of field names
 
@@ -653,8 +502,20 @@
 # @isa (Geo::OGR)
 
 ## @cmethod Geo::OGR::Feature new(%schema)
-# @param schema as in Schema
-# @return a new Geo::OGR::Feature object
+# @brief Create a new feature.
+# @param A Geo::OGR::FeatureDefn object or named parameters to create one:
+# - \a Name
+# - \a Fields a list of Geo::OGR::FieldDefn or Geo::OGR::GeomFieldDefn
+# objects or anonymous hashes from which such can be created.
+# - \a GeometryType the geometry type if the feature has only one spatial field.
+# - \a StyleIgnored whether the style can be omitted when fetching features. (default is false)
+#
+# @note Do not mix GeometryType and geometry fields in Fields list.
+#
+# @return a new Geo::OGR::Feature object.
+
+## @method Geo::OGR::Layer Layer()
+# @return the layer to which this feature belongs to or undef.
 
 ## @method $DumpReadable()
 # Write the contents of this feature to stdout.
@@ -668,8 +529,12 @@
 ## @ignore Schema
 
 ## @method \%GetSchema()
-# @brief Get the schema of this feature. 
-# @return the schema of this layer, as in Geo::OGR::FeatureDefn::Schema.
+# @brief Get the schema of this feature.
+#
+# @return the schema as a hash whose keywords are Name, StyleIgnored
+# and Fields. Fields is an anonymous array of first non-spatial and
+# then spatial field schemas as in Geo::OGR::FieldDefn::Schema() and
+# Geo::OGR::GeomFieldDefn::Schema().
 
 ## @method \%Row(%row)
 # @note This method discards the data the destination feature (or
@@ -678,10 +543,10 @@
 #
 # Get and/or set the data of the feature. The key of the (key,value)
 # pairs of the row is the field name. Special field names FID and
-# Geometry are used for feature id and geometry respectively. The
-# geometry is set and get using the Geo::OGR::Feature::Geometry
-# method. Field values are set using the Geo::OGR::Feature::SetField
-# method.
+# Geometry are used for feature id and (single) geometry
+# respectively. The geometry/ies is/are set and get using the
+# Geo::OGR::Feature::Geometry method. Field values are set using the
+# Geo::OGR::Feature::Field method.
 # @param row [optional] feature data in a hash.
 # @return a reference to feature data in a hash. Spatial fields are
 # returned as Geo::OGR::Geometry objects.
@@ -696,9 +561,9 @@
 #
 # Get and/set the data of the feature. The expected data in the tuple
 # is ([feature_id,] non-spatial fields, spatial fields). The fields in
-# the order they are in the schema. Field values are set using the
-# Geo::OGR::Feature::Field method. Geometries are set and get using
-# the Geo::OGR::Feature::Geometry method.
+# the tuple are in the order they are in the schema. Field values are
+# set using the Geo::OGR::Feature::Field method. Geometries are set
+# and get using the Geo::OGR::Feature::Geometry method.
 # @param tuple [optional] feature data in an array
 # @return feature data in an array
 
@@ -736,39 +601,43 @@
 ## @ignore GetFieldAsString
 ## @ignore GetFieldAsInteger
 ## @ignore GetFieldAsDouble
+## @ignore GetFieldAsBinary
 ## @ignore GetFieldAsDateTime
+## @ignore GetFieldAsInteger64
 ## @ignore GetFieldAsDoubleList
 ## @ignore GetFieldAsIntegerList
+## @ignore GetFieldAsInteger64List
 ## @ignore GetFieldAsStringList
 
-## @method @GetField($name)
-# @note A number of GetFieldAs* methods exist but they are not
-# documented. Syntax $feature->{field} can be used to access the
-# field (v1.9.0)
-# @param name the name of the field
-# @return the value of the field, which may be a scalar or a list,
-# depending on the field type.
-
+## @ignore SetFieldBinary
+## @ignore SetFieldBinaryFromHexString
+## @ignore SetFieldInteger64
 ## @ignore SetFieldDoubleList
 ## @ignore SetFieldIntegerList
+## @ignore SetFieldInteger64List
 ## @ignore SetFieldStringList
 
+## @ignore IsFieldSet
+## @ignore UnsetField
+
 ## @method SetField($name, @Value)
-# @note Syntax $feature->{field} can be used to access the
-# field (v1.9.0)
-# @param name the name of the field.
-# @param Value a string, integer, double, a list (year, month,
-# day), a list (hour, minute, second, tzflag), a list (year, month,
-# day, hour, minute, second, tzflag), or a list of integers, doubles,
-# or strings.
-# @note If value is not given or is undefined this method unsets the field.
-
-## @method Field($name, @Value)
-# @brief Get or set the field.
-# @param name the name of the field.
-# @param Value a scalar or list depending on the field type.
-# @return the value of the field, which may be a scalar or a list,
-# depending on the field type.
+# See Field().
+
+## @method @GetField($name)
+# See Field().
+
+## @method Field($name, $value, ...)
+# @brief Get, set, or unset the field value.
+# @param name the name (or the index) of the field.
+# @param value a scalar, a list of scalars or a reference to a
+# list. If undef, the field is unset. If a scalar or a list of
+# scalars, the field is set from them.
+# @note Non-scalar fields (for example Date) can be set either from a
+# scalar, which is then assumed to be a string and parsed, or from a
+# list of values (for example year, month, day for Date).
+# @return in non-void context the value of the field, which may be a
+# scalar or a list, depending on the field type. For unset fields the
+# undef value is returned.
 
 ## @ignore SetGeometry
 ## @ignore SetGeometryDirectly
@@ -778,25 +647,26 @@
 ## @ignore SetGeomField
 ## @ignore SetGeomFieldDirectly
 
-## @method $Geometry($name, $geometry)
+## @method Geometry($name, $geometry)
 # @brief Get or set the value of a geometry field.
 # @note This method delivers the functionality of undocumented methods
 # SetGeometry($geometry), SetGeometryDirectly, SetGeomField,
 # SetGeomFieldDirectly, GetGeometry, GetGeometryRef.
 #
 # Set or get the geometry in the feature. When setting, does a check
-# against the schema (GeometryType) of the feature. The ownership of
-# the geometry is given (if the parameter is an object) or kept to the
-# feature and thus the geometry will keep the feature alive as long as
-# the geometry is alive.
+# against the schema (GeometryType) of the feature. If the parameter
+# is a geometry object, it is cloned.
 # @param name [optional] the name of the spatial field,
 # whose geometry is to be set. If not given, sets or gets the geometry
-# of the first spatial field.
-# @param geometry [optional] a Geo::OGR::Geometry object or a hash
-# array from which such can be created (using
-# Geo::OGR::Geometry::new)
-# @return in a non-void context the geometry in the feature
-# as a Geo::OGR::Geometry object.
+# of the first (or the single) spatial field.
+# @param geometry [optional] a Geo::OGR::Geometry object or a
+# reference to a hash from which such can be created (using
+# Geo::OGR::Geometry::new).
+# @return in a non-void context the indicated geometry in the feature
+# as a Geo::OGR::Geometry object. The returned object contains a
+# reference to the actual geometry data in the feature (the geometry
+# is not cloned) and to the feature object, thus keeping the feature
+# object from being destroyed while the geometry object exists.
 
 ## @ignore SetFromWithMap
 
@@ -813,9 +683,7 @@
 # @return boolean
 
 ## @method UnsetField($field)
-# @note Field value can be unset by calling SetField without
-# parameters or with an undefined argument.
-# @param field the name (or index) of the field
+# See Field().
 
 ## @method $FID($id)
 # @brief Get or set the id of this feature.
@@ -842,10 +710,12 @@
 
 
 ## @class Geo::OGR::FeatureDefn
-# @brief A definition of the attributes of a feature class or a layer.
+# @brief The schema of a feature or a layer.
 #
-# A definition object is a collection of field definition objects. A
-# read-only definition object is obtained from a layer or a feature.
+# A FeatureDefn object is a collection of field definition objects. A
+# read-only FeatureDefn object can be obtained from a layer
+# (Geo::OGR::Layer::GetDefn()) or a feature
+# (Geo::OGR::Feature::GetDefn()).
 # @isa (Geo::OGR)
 
 ## @cmethod Geo::OGR::FeatureDefn new(%schema)
@@ -855,7 +725,7 @@
 # GeometryType is 'Unknown' or the value of the named parameter
 # GeometryType.
 # @param schema [optional] The schema for the new feature definition,
-# as in Geo::OGR::FeatureDefn::Schema.
+# as in Geo::OGR::FeatureDefn::Schema().
 # @return a Geo::OGR::FeatureDefn object
 #
 # Example usage:
@@ -871,11 +741,10 @@
 ## @method \%GetSchema()
 # @brief Get the schema of this feature or layer definition. 
 #
-# The schema is a hash whose keywords are Name, StyleIgnored and
-# Fields. Fields is an anonymous array of first non-spatial and then
-# spatial field schemas as in Geo::OGR::FieldDefn::Schema and
-# Geo::OGR::GeomFieldDefn::Schema.
-# @return the schema of this feature or layer definition.
+# @return the schema as a hash whose keywords are Name, StyleIgnored
+# and Fields. Fields is an anonymous array of first non-spatial and
+# then spatial field schemas as in Geo::OGR::FieldDefn::Schema() and
+# Geo::OGR::GeomFieldDefn::Schema().
 
 ## @ignore Name
 
@@ -904,7 +773,7 @@
 ## @ignore AddGeomFieldDefn
 
 ## @method AddField(%params)
-# @param params named parameters to create a new Geo::OGR::FieldDefn
+# @param params Named parameters to create a new Geo::OGR::FieldDefn
 # or Geo::OGR::GeomFieldDefn object.
 
 ## @ignore DeleteGeomFieldDefn
@@ -967,31 +836,24 @@
 # @brief A definition of a non-spatial attribute.
 # @isa (Geo::OGR)
 
-## @cmethod list Types
+## @sub list Types
 # Field types supported by GDAL. Current list is
 # +list Geo::OGR OFT
+# (However, WideString is not supported.)
 
-## @cmethod list JustifyValues
+## @sub list JustifyValues
 # Justify values supported by GDAL. Current list is
 # +list Geo::OGR OJ
 
 ## @cmethod Geo::OGR::FieldDefn new(%params)
 # @brief Create a new field definition.
 #
-# This method supports both an argument list and named arguments.
-#
-# @param name Field name (please do not try to name the field as Name or Type etc.).
-# @param type One of supported field types
-# (see Geo::OGR::FieldDefn::Types). Optional. Default is String.
-#
-# or
-#
-# @param params one or more of:
+# @param Named parameters:
 # - \a Name Field name (default is 'unnamed').
 # - \a Type Field type, one of Geo::OGR::FieldDefn::Types (default is 'String').
 # - \a SubType Field sub type, one of Geo::OGR::FieldDefn::SubTypes.
 # - \a Justify Justify value, one of Geo::OGR::FieldDefn::JustifyValues
-# - \a Width
+# - \a Width 
 # - \a Precision
 # - \a Nullable (default is true)
 # - \a Default 
@@ -1019,6 +881,7 @@
 ## @ignore SetType
 
 ## @method $Type($type)
+# Get and/or set the type of the field.
 # @note a.k.a. GetFieldTypeName, GetTypeName, GetType, SetType
 # @param type [optional] One of field types (Geo::OGR::FieldDefn::Types).
 # @return one of field types in non-void context.
@@ -1113,7 +976,7 @@
 ## @method Type
 # @return the type of this geometry field. One of Geo::OGR::GeomFieldDefn::Types
 
-## @cmethod Types
+## @sub Types
 # @return a list of all geometry types, currently:
 # +list Geo::OGR wkb 25DBit,25Bit,NDR,XDR
 
@@ -1168,15 +1031,14 @@
 # @note Most spatial analysis methods require <a
 # href="http://geos.osgeo.org/doxygen/">GEOS</a> to work rigorously.
 
-## @cmethod @GeometryTypes()
+## @sub @GeometryTypes()
 # Same as Geo::OGR::GeometryTypes
 
-## @cmethod list ByteOrders
+## @sub list ByteOrders
 # Same as Geo::OGR::ByteOrders
 
 ## @cmethod Geo::OGR::Geometry new(%params)
-# @param %params A named parameter, one of: WKT, WKB, HEXWKB,
-# HEXEWKB, GML, GeoJSON, arc, or GeometryType and optionally Points.
+# @param %params A named parameter, one of:
 # - \a GeometryType one the supported geometry types, see Geo::OGR::GeometryTypes.
 # - \a WKT a well known text string, which defines a geometry.
 # - \a WKB a well known binary string, which defines a geometry.
@@ -1191,26 +1053,20 @@
 #      Geo::OGR::Geometry::Points; Note: requires also GeometryType
 #      parameter
 #
-# @note uses CreateGeometryFrom* functions from Geo::OGR
-#
 # @return a new Geo::OGR::Geometry object.
-# Usage:
-# \code
-# $g = Geo::OGR::Geometry->new(...arguments...);
-# \endcode
 
-## @cmethod Geo::OGR::Geometry ApproximateArcAngles(%params)
+## @sub Geo::OGR::Geometry ApproximateArcAngles(%params)
 # Create a line string, which approximates an arc. 
 # @note All angles are in degrees.
 #
-# @param %params named parameters, these are:
+# @param %params Named parameters:
 # - \a Center center point (default is [0, 0, 0])
-# - \a PrimaryRadius default is 1,
-# - \a SecondaryAxis default is 1,
-# - \a Rotation default is 0,
-# - \a StartAngle default is 0,
-# - \a EndAngle default is 360,
-# - \a MaxAngleStepSizeDegrees default is 4 
+# - \a PrimaryRadius default is 1.
+# - \a SecondaryAxis default is 1.
+# - \a Rotation default is 0.
+# - \a StartAngle default is 0.
+# - \a EndAngle default is 360.
+# - \a MaxAngleStepSizeDegrees default is 4. 
 # @return a new Geo::OGR::Geometry object.
 
 ## @method FlattenTo2D()
@@ -1245,13 +1101,24 @@
 
 ## @method $As(%params)
 # Export the geometry into a known format.
-
-# @param params named parameters, either: Text (a.k.a WKT), WKB
-# (a.k.a. Binary) (ByteOrder can also be defined, default is 'XDR'),
-# ISO WKT and WKB, HEXWKB, HEXEWKB (srid can also be given), GML,
-# GeoJSON, Binary.
-
-# @note Uses As\<format\>/ExportTo\<format\> methods.
+#
+# @param params Named parameters:
+# - \a Format One of 
+#     - \a WKT Well Known Text.
+#     - <em>ISO WKT</em>
+#     - \a Text Same as WKT.
+#     - \a WKB Well Known Binary.
+#     - <em>ISO WKB</em>
+#     - \a Binary Same as WKB.
+#     - \a HEXWKB
+#     - \a HEXEWKB
+#     - \a GML
+#     - \a GeoJSON
+# - \a ByteOrder Byte order for binary formats. Default is 'XDR'.
+# - \a SRID Spatial reference id for HEXEWKB.
+# - \a Options GML generation options.
+# - \a AltitudeMode For KML.
+#
 # @return the geometry in a given format.
 
 ## @method AddPoint($x, $y, $z)
@@ -1567,8 +1434,6 @@
 ## @method @GetEnvelope()
 # @note In scalar context returns a reference to an anonymous array
 # containing the envelope.
-# @note The order of values is different from those returned by
-# Geo::OGR::Layer::GetExtent.
 # @return the envelope ($minx, $maxx, $miny, $maxy)
 
 ## @method @GetEnvelope3D()
diff --git a/swig/perl/lib/Geo/OGR.pm b/swig/perl/lib/Geo/OGR.pm
deleted file mode 100644
index 8dc87b1..0000000
--- a/swig/perl/lib/Geo/OGR.pm
+++ /dev/null
@@ -1,2530 +0,0 @@
-# This file was automatically generated by SWIG (http://www.swig.org).
-# Version 2.0.12
-#
-# Do not make changes to this file unless you know what you are doing--modify
-# the SWIG interface file instead.
-
-package Geo::OGR;
-use base qw(Exporter);
-use base qw(DynaLoader);
-require Geo::OSR;
-require Geo::GDAL;
-package Geo::OGRc;
-bootstrap Geo::OGR;
-package Geo::OGR;
- at EXPORT = qw();
-
-# ---------- BASE METHODS -------------
-
-package Geo::OGR;
-
-sub TIEHASH {
-    my ($classname,$obj) = @_;
-    return bless $obj, $classname;
-}
-
-sub CLEAR { }
-
-sub FIRSTKEY { }
-
-sub NEXTKEY { }
-
-sub FETCH {
-    my ($self,$field) = @_;
-    my $member_func = "swig_${field}_get";
-    $self->$member_func();
-}
-
-sub STORE {
-    my ($self,$field,$newval) = @_;
-    my $member_func = "swig_${field}_set";
-    $self->$member_func($newval);
-}
-
-sub this {
-    my $ptr = shift;
-    return tied(%$ptr);
-}
-
-
-# ------- FUNCTION WRAPPERS --------
-
-package Geo::OGR;
-
-*callback_d_cp_vp = *Geo::OGRc::callback_d_cp_vp;
-*UseExceptions = *Geo::OGRc::UseExceptions;
-*DontUseExceptions = *Geo::OGRc::DontUseExceptions;
-*CreateGeometryFromWkb = *Geo::OGRc::CreateGeometryFromWkb;
-*CreateGeometryFromWkt = *Geo::OGRc::CreateGeometryFromWkt;
-*CreateGeometryFromGML = *Geo::OGRc::CreateGeometryFromGML;
-*CreateGeometryFromJson = *Geo::OGRc::CreateGeometryFromJson;
-*BuildPolygonFromEdges = *Geo::OGRc::BuildPolygonFromEdges;
-*ApproximateArcAngles = *Geo::OGRc::ApproximateArcAngles;
-*ForceToPolygon = *Geo::OGRc::ForceToPolygon;
-*ForceToLineString = *Geo::OGRc::ForceToLineString;
-*ForceToMultiPolygon = *Geo::OGRc::ForceToMultiPolygon;
-*ForceToMultiPoint = *Geo::OGRc::ForceToMultiPoint;
-*ForceToMultiLineString = *Geo::OGRc::ForceToMultiLineString;
-*ForceTo = *Geo::OGRc::ForceTo;
-*GetDriverCount = *Geo::OGRc::GetDriverCount;
-*GetOpenDSCount = *Geo::OGRc::GetOpenDSCount;
-*SetGenerate_DB2_V72_BYTE_ORDER = *Geo::OGRc::SetGenerate_DB2_V72_BYTE_ORDER;
-*RegisterAll = *Geo::OGRc::RegisterAll;
-*GeometryTypeToName = *Geo::OGRc::GeometryTypeToName;
-*GetFieldTypeName = *Geo::OGRc::GetFieldTypeName;
-*GetFieldSubTypeName = *Geo::OGRc::GetFieldSubTypeName;
-*GT_Flatten = *Geo::OGRc::GT_Flatten;
-*GT_SetZ = *Geo::OGRc::GT_SetZ;
-*GT_SetModifier = *Geo::OGRc::GT_SetModifier;
-*GT_HasZ = *Geo::OGRc::GT_HasZ;
-*GT_IsSubClassOf = *Geo::OGRc::GT_IsSubClassOf;
-*GT_IsCurve = *Geo::OGRc::GT_IsCurve;
-*GT_IsSurface = *Geo::OGRc::GT_IsSurface;
-*GT_IsNonLinear = *Geo::OGRc::GT_IsNonLinear;
-*GT_GetCollection = *Geo::OGRc::GT_GetCollection;
-*GT_GetCurve = *Geo::OGRc::GT_GetCurve;
-*GT_GetLinear = *Geo::OGRc::GT_GetLinear;
-*SetNonLinearGeometriesEnabledFlag = *Geo::OGRc::SetNonLinearGeometriesEnabledFlag;
-*GetNonLinearGeometriesEnabledFlag = *Geo::OGRc::GetNonLinearGeometriesEnabledFlag;
-*GetOpenDS = *Geo::OGRc::GetOpenDS;
-*Open = *Geo::OGRc::Open;
-*OpenShared = *Geo::OGRc::OpenShared;
-*GetDriverByName = *Geo::OGRc::GetDriverByName;
-*_GetDriver = *Geo::OGRc::_GetDriver;
-*GeneralCmdLineProcessor = *Geo::OGRc::GeneralCmdLineProcessor;
-*TermProgress_nocb = *Geo::OGRc::TermProgress_nocb;
-
-############# Class : Geo::OGR::StyleTable ##############
-
-package Geo::OGR::StyleTable;
-use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
- at ISA = qw( Geo::OGR );
-%OWNER = ();
-%ITERATORS = ();
-sub new {
-    my $pkg = shift;
-    my $self = Geo::OGRc::new_StyleTable(@_);
-    bless $self, $pkg if defined($self);
-}
-
-sub DESTROY {
-    return unless $_[0]->isa('HASH');
-    my $self = tied(%{$_[0]});
-    return unless defined $self;
-    delete $ITERATORS{$self};
-    if (exists $OWNER{$self}) {
-        Geo::OGRc::delete_StyleTable($self);
-        delete $OWNER{$self};
-    }
-}
-
-*AddStyle = *Geo::OGRc::StyleTable_AddStyle;
-*LoadStyleTable = *Geo::OGRc::StyleTable_LoadStyleTable;
-*SaveStyleTable = *Geo::OGRc::StyleTable_SaveStyleTable;
-*Find = *Geo::OGRc::StyleTable_Find;
-*ResetStyleStringReading = *Geo::OGRc::StyleTable_ResetStyleStringReading;
-*GetNextStyle = *Geo::OGRc::StyleTable_GetNextStyle;
-*GetLastStyleName = *Geo::OGRc::StyleTable_GetLastStyleName;
-sub DISOWN {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    delete $OWNER{$ptr};
-}
-
-sub ACQUIRE {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    $OWNER{$ptr} = 1;
-}
-
-
-############# Class : Geo::OGR::Driver ##############
-
-package Geo::OGR::Driver;
-use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
- at ISA = qw( Geo::GDAL::MajorObject Geo::OGR );
-%OWNER = ();
-%ITERATORS = ();
-*swig_name_get = *Geo::OGRc::Driver_name_get;
-*swig_name_set = *Geo::OGRc::Driver_name_set;
-*CreateDataSource = *Geo::OGRc::Driver_CreateDataSource;
-*CopyDataSource = *Geo::OGRc::Driver_CopyDataSource;
-*Open = *Geo::OGRc::Driver_Open;
-*DeleteDataSource = *Geo::OGRc::Driver_DeleteDataSource;
-*_TestCapability = *Geo::OGRc::Driver__TestCapability;
-*GetName = *Geo::OGRc::Driver_GetName;
-*Register = *Geo::OGRc::Driver_Register;
-*Deregister = *Geo::OGRc::Driver_Deregister;
-sub DISOWN {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    delete $OWNER{$ptr};
-}
-
-sub ACQUIRE {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    $OWNER{$ptr} = 1;
-}
-
-
-############# Class : Geo::OGR::DataSource ##############
-
-package Geo::OGR::DataSource;
-use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
- at ISA = qw( Geo::GDAL::MajorObject Geo::OGR );
-%OWNER = ();
-%ITERATORS = ();
-*swig_name_get = *Geo::OGRc::DataSource_name_get;
-*swig_name_set = *Geo::OGRc::DataSource_name_set;
-sub DESTROY {
-    my $self;
-    if ($_[0]->isa('SCALAR')) {
-        $self = $_[0];
-    } else {
-        return unless $_[0]->isa('HASH');
-        $self = tied(%{$_[0]});
-        return unless defined $self;
-    }
-    delete $ITERATORS{$self};
-    if (exists $OWNER{$self}) {
-        Geo::OGRc::delete_DataSource($self);
-        delete $OWNER{$self};
-    }
-    $self->RELEASE_PARENTS();
-}
-
-*GetRefCount = *Geo::OGRc::DataSource_GetRefCount;
-*GetSummaryRefCount = *Geo::OGRc::DataSource_GetSummaryRefCount;
-*GetLayerCount = *Geo::OGRc::DataSource_GetLayerCount;
-*_GetDriver = *Geo::OGRc::DataSource__GetDriver;
-*GetName = *Geo::OGRc::DataSource_GetName;
-*_DeleteLayer = *Geo::OGRc::DataSource__DeleteLayer;
-*SyncToDisk = *Geo::OGRc::DataSource_SyncToDisk;
-*FlushCache = *Geo::OGRc::DataSource_FlushCache;
-*_CreateLayer = *Geo::OGRc::DataSource__CreateLayer;
-*CopyLayer = *Geo::OGRc::DataSource_CopyLayer;
-*GetLayerByIndex = *Geo::OGRc::DataSource_GetLayerByIndex;
-*GetLayerByName = *Geo::OGRc::DataSource_GetLayerByName;
-*_TestCapability = *Geo::OGRc::DataSource__TestCapability;
-*_ExecuteSQL = *Geo::OGRc::DataSource__ExecuteSQL;
-*_ReleaseResultSet = *Geo::OGRc::DataSource__ReleaseResultSet;
-*GetStyleTable = *Geo::OGRc::DataSource_GetStyleTable;
-*SetStyleTable = *Geo::OGRc::DataSource_SetStyleTable;
-*StartTransaction = *Geo::OGRc::DataSource_StartTransaction;
-*CommitTransaction = *Geo::OGRc::DataSource_CommitTransaction;
-*RollbackTransaction = *Geo::OGRc::DataSource_RollbackTransaction;
-sub DISOWN {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    delete $OWNER{$ptr};
-}
-
-sub ACQUIRE {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    $OWNER{$ptr} = 1;
-}
-
-
-############# Class : Geo::OGR::Layer ##############
-
-package Geo::OGR::Layer;
-use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
- at ISA = qw( Geo::GDAL::MajorObject Geo::OGR );
-%OWNER = ();
-*GetRefCount = *Geo::OGRc::Layer_GetRefCount;
-*SetSpatialFilter = *Geo::OGRc::Layer_SetSpatialFilter;
-*SetSpatialFilterRect = *Geo::OGRc::Layer_SetSpatialFilterRect;
-*GetSpatialFilter = *Geo::OGRc::Layer_GetSpatialFilter;
-*SetAttributeFilter = *Geo::OGRc::Layer_SetAttributeFilter;
-*ResetReading = *Geo::OGRc::Layer_ResetReading;
-*GetName = *Geo::OGRc::Layer_GetName;
-*GetGeomType = *Geo::OGRc::Layer_GetGeomType;
-*GetGeometryColumn = *Geo::OGRc::Layer_GetGeometryColumn;
-*GetFIDColumn = *Geo::OGRc::Layer_GetFIDColumn;
-*GetFeature = *Geo::OGRc::Layer_GetFeature;
-*GetNextFeature = *Geo::OGRc::Layer_GetNextFeature;
-*SetNextByIndex = *Geo::OGRc::Layer_SetNextByIndex;
-*SetFeature = *Geo::OGRc::Layer_SetFeature;
-*CreateFeature = *Geo::OGRc::Layer_CreateFeature;
-*DeleteFeature = *Geo::OGRc::Layer_DeleteFeature;
-*SyncToDisk = *Geo::OGRc::Layer_SyncToDisk;
-*GetLayerDefn = *Geo::OGRc::Layer_GetLayerDefn;
-*GetFeatureCount = *Geo::OGRc::Layer_GetFeatureCount;
-*GetExtent = *Geo::OGRc::Layer_GetExtent;
-*_TestCapability = *Geo::OGRc::Layer__TestCapability;
-*_CreateField = *Geo::OGRc::Layer__CreateField;
-*_DeleteField = *Geo::OGRc::Layer__DeleteField;
-*ReorderField = *Geo::OGRc::Layer_ReorderField;
-*ReorderFields = *Geo::OGRc::Layer_ReorderFields;
-*_AlterFieldDefn = *Geo::OGRc::Layer__AlterFieldDefn;
-*CreateGeomField = *Geo::OGRc::Layer_CreateGeomField;
-*StartTransaction = *Geo::OGRc::Layer_StartTransaction;
-*CommitTransaction = *Geo::OGRc::Layer_CommitTransaction;
-*RollbackTransaction = *Geo::OGRc::Layer_RollbackTransaction;
-*FindFieldIndex = *Geo::OGRc::Layer_FindFieldIndex;
-*GetSpatialRef = *Geo::OGRc::Layer_GetSpatialRef;
-*GetFeaturesRead = *Geo::OGRc::Layer_GetFeaturesRead;
-*SetIgnoredFields = *Geo::OGRc::Layer_SetIgnoredFields;
-*Intersection = *Geo::OGRc::Layer_Intersection;
-*Union = *Geo::OGRc::Layer_Union;
-*SymDifference = *Geo::OGRc::Layer_SymDifference;
-*Identity = *Geo::OGRc::Layer_Identity;
-*Update = *Geo::OGRc::Layer_Update;
-*Clip = *Geo::OGRc::Layer_Clip;
-*Erase = *Geo::OGRc::Layer_Erase;
-*GetStyleTable = *Geo::OGRc::Layer_GetStyleTable;
-*SetStyleTable = *Geo::OGRc::Layer_SetStyleTable;
-sub DISOWN {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    delete $OWNER{$ptr};
-}
-
-sub ACQUIRE {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    $OWNER{$ptr} = 1;
-}
-
-
-############# Class : Geo::OGR::Feature ##############
-
-package Geo::OGR::Feature;
-use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
- at ISA = qw( Geo::OGR );
-%OWNER = ();
-sub DESTROY {
-    my $self;
-    if ($_[0]->isa('SCALAR')) {
-        $self = $_[0];
-    } else {
-        return unless $_[0]->isa('HASH');
-        $self = tied(%{$_[0]});
-        return unless defined $self;
-    }
-    delete $ITERATORS{$self};
-    if (exists $OWNER{$self}) {
-        Geo::OGRc::delete_Feature($self);
-        delete $OWNER{$self};
-    }
-    $self->RELEASE_PARENTS();
-}
-
-use Carp;
-sub new {
-    my $pkg = shift;
-    my $arg = blessed($_[0]);
-    my $defn;
-    if ($arg && $arg eq 'Geo::OGR::FeatureDefn') {
-        $defn = $_[0];
-    } else {
-        $defn = Geo::OGR::FeatureDefn->new(@_);
-    }
-    my $self = Geo::OGRc::new_Feature($defn);
-    bless $self, $pkg if defined($self);
-}
-
-*GetDefnRef = *Geo::OGRc::Feature_GetDefnRef;
-*_SetGeometry = *Geo::OGRc::Feature__SetGeometry;
-*SetGeometryDirectly = *Geo::OGRc::Feature_SetGeometryDirectly;
-*GetGeometryRef = *Geo::OGRc::Feature_GetGeometryRef;
-*SetGeomField = *Geo::OGRc::Feature_SetGeomField;
-*SetGeomFieldDirectly = *Geo::OGRc::Feature_SetGeomFieldDirectly;
-*GetGeomFieldRef = *Geo::OGRc::Feature_GetGeomFieldRef;
-*Clone = *Geo::OGRc::Feature_Clone;
-*Equal = *Geo::OGRc::Feature_Equal;
-*GetFieldCount = *Geo::OGRc::Feature_GetFieldCount;
-*GetFieldDefnRef = *Geo::OGRc::Feature_GetFieldDefnRef;
-*GetGeomFieldCount = *Geo::OGRc::Feature_GetGeomFieldCount;
-*GetGeomFieldDefnRef = *Geo::OGRc::Feature_GetGeomFieldDefnRef;
-*GetFieldAsString = *Geo::OGRc::Feature_GetFieldAsString;
-*GetFieldAsInteger = *Geo::OGRc::Feature_GetFieldAsInteger;
-*GetFieldAsInteger64 = *Geo::OGRc::Feature_GetFieldAsInteger64;
-*GetFieldAsDouble = *Geo::OGRc::Feature_GetFieldAsDouble;
-*GetFieldAsDateTime = *Geo::OGRc::Feature_GetFieldAsDateTime;
-*GetFieldAsIntegerList = *Geo::OGRc::Feature_GetFieldAsIntegerList;
-*GetFieldAsDoubleList = *Geo::OGRc::Feature_GetFieldAsDoubleList;
-*GetFieldAsStringList = *Geo::OGRc::Feature_GetFieldAsStringList;
-*GetFieldAsBinary = *Geo::OGRc::Feature_GetFieldAsBinary;
-*IsFieldSet = *Geo::OGRc::Feature_IsFieldSet;
-*GetFieldIndex = *Geo::OGRc::Feature_GetFieldIndex;
-*GetGeomFieldIndex = *Geo::OGRc::Feature_GetGeomFieldIndex;
-*GetFID = *Geo::OGRc::Feature_GetFID;
-*SetFID = *Geo::OGRc::Feature_SetFID;
-*DumpReadable = *Geo::OGRc::Feature_DumpReadable;
-*_UnsetField = *Geo::OGRc::Feature__UnsetField;
-*SetFieldInteger64 = *Geo::OGRc::Feature_SetFieldInteger64;
-*_SetField = *Geo::OGRc::Feature__SetField;
-*SetFieldIntegerList = *Geo::OGRc::Feature_SetFieldIntegerList;
-*SetFieldDoubleList = *Geo::OGRc::Feature_SetFieldDoubleList;
-*SetFieldStringList = *Geo::OGRc::Feature_SetFieldStringList;
-*SetFieldBinaryFromHexString = *Geo::OGRc::Feature_SetFieldBinaryFromHexString;
-*_SetFrom = *Geo::OGRc::Feature__SetFrom;
-*SetFromWithMap = *Geo::OGRc::Feature_SetFromWithMap;
-*GetStyleString = *Geo::OGRc::Feature_GetStyleString;
-*SetStyleString = *Geo::OGRc::Feature_SetStyleString;
-*GetFieldType = *Geo::OGRc::Feature_GetFieldType;
-*_Validate = *Geo::OGRc::Feature__Validate;
-*FillUnsetWithDefault = *Geo::OGRc::Feature_FillUnsetWithDefault;
-sub DISOWN {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    delete $OWNER{$ptr};
-}
-
-sub ACQUIRE {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    $OWNER{$ptr} = 1;
-}
-
-
-############# Class : Geo::OGR::FeatureDefn ##############
-
-package Geo::OGR::FeatureDefn;
-use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
- at ISA = qw( Geo::OGR );
-%OWNER = ();
-sub DESTROY {
-    my $self;
-    if ($_[0]->isa('SCALAR')) {
-        $self = $_[0];
-    } else {
-        return unless $_[0]->isa('HASH');
-        $self = tied(%{$_[0]});
-        return unless defined $self;
-    }
-    delete $ITERATORS{$self};
-    if (exists $OWNER{$self}) {
-        Geo::OGRc::delete_FeatureDefn($self);
-        delete $OWNER{$self};
-    }
-    $self->RELEASE_PARENTS();
-}
-
-use strict;
-use warnings;
-use Carp;
-use Scalar::Util 'blessed';
-sub new {
-    my $pkg = shift;
-    my %schema;
-    if (@_ == 1 and ref($_[0]) eq 'HASH') {
-        %schema = %{$_[0]};
-    } elsif (@_ and @_ % 2 == 0) {
-        %schema = @_;
-    }
-    my $fields = $schema{Fields};
-    confess "The Fields argument is not a reference to an array." if $fields and ref($fields) ne 'ARRAY';
-    $schema{Name} = '' unless exists $schema{Name};
-    my $self = Geo::OGRc::new_FeatureDefn($schema{Name});
-    bless $self, $pkg;
-    my $gt = $schema{GeometryType};
-    if ($fields) {
-        $self->DeleteGeomFieldDefn(0); # either default behavior or argument specified
-    } else {
-        $self->GeometryType($schema{GeometryType}) if exists $schema{GeometryType};
-    }
-    $self->StyleIgnored($schema{StyleIgnored}) if exists $schema{StyleIgnored};
-    for my $fd (@{$fields}) {
-        my $d = $fd;
-        if (ref($fd) eq 'HASH') {
-            if ($fd->{GeometryType} or exists $Geo::OGR::Geometry::TYPE_STRING2INT{$fd->{Type}}) {
-                $d = Geo::OGR::GeomFieldDefn->new(%$fd);
-            } else {
-                $d = Geo::OGR::FieldDefn->new(%$fd);
-            }
-        }
-        if (blessed($d) and $d->isa('Geo::OGR::FieldDefn')) {
-            AddFieldDefn($self, $d);
-        } elsif (blessed($d) and $d->isa('Geo::OGR::GeomFieldDefn')) {
-            AddGeomFieldDefn($self, $d);
-        } else {
-            confess "Item in field list does not define a field.";
-        }
-    }
-    return $self;
-}
-
-*GetName = *Geo::OGRc::FeatureDefn_GetName;
-*GetFieldCount = *Geo::OGRc::FeatureDefn_GetFieldCount;
-*GetFieldDefn = *Geo::OGRc::FeatureDefn_GetFieldDefn;
-*GetFieldIndex = *Geo::OGRc::FeatureDefn_GetFieldIndex;
-*AddFieldDefn = *Geo::OGRc::FeatureDefn_AddFieldDefn;
-*GetGeomFieldCount = *Geo::OGRc::FeatureDefn_GetGeomFieldCount;
-*GetGeomFieldDefn = *Geo::OGRc::FeatureDefn_GetGeomFieldDefn;
-*GetGeomFieldIndex = *Geo::OGRc::FeatureDefn_GetGeomFieldIndex;
-*AddGeomFieldDefn = *Geo::OGRc::FeatureDefn_AddGeomFieldDefn;
-*DeleteGeomFieldDefn = *Geo::OGRc::FeatureDefn_DeleteGeomFieldDefn;
-*GetGeomType = *Geo::OGRc::FeatureDefn_GetGeomType;
-*SetGeomType = *Geo::OGRc::FeatureDefn_SetGeomType;
-*GetReferenceCount = *Geo::OGRc::FeatureDefn_GetReferenceCount;
-*IsGeometryIgnored = *Geo::OGRc::FeatureDefn_IsGeometryIgnored;
-*SetGeometryIgnored = *Geo::OGRc::FeatureDefn_SetGeometryIgnored;
-*IsStyleIgnored = *Geo::OGRc::FeatureDefn_IsStyleIgnored;
-*SetStyleIgnored = *Geo::OGRc::FeatureDefn_SetStyleIgnored;
-*IsSame = *Geo::OGRc::FeatureDefn_IsSame;
-sub DISOWN {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    delete $OWNER{$ptr};
-}
-
-sub ACQUIRE {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    $OWNER{$ptr} = 1;
-}
-
-
-############# Class : Geo::OGR::FieldDefn ##############
-
-package Geo::OGR::FieldDefn;
-use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
- at ISA = qw( Geo::OGR );
-%OWNER = ();
-sub DESTROY {
-    my $self;
-    if ($_[0]->isa('SCALAR')) {
-        $self = $_[0];
-    } else {
-        return unless $_[0]->isa('HASH');
-        $self = tied(%{$_[0]});
-        return unless defined $self;
-    }
-    delete $ITERATORS{$self};
-    if (exists $OWNER{$self}) {
-        Geo::OGRc::delete_FieldDefn($self);
-        delete $OWNER{$self};
-    }
-    $self->RELEASE_PARENTS();
-}
-
-use Carp;
-sub new {
-    my $pkg = shift;
-    my ($name, $type) = ('unnamed', 'String');
-    my %args;
-    if (@_ == 0) {
-    } elsif (@_ == 1) {
-        $name = shift;
-    } elsif (@_ == 2 and not $Geo::OGR::FieldDefn::SCHEMA_KEYS{$_[0]}) {
-        $name = shift;
-        $type = shift;
-    } else {
-        my %named = @_;
-        for my $key (keys %named) {
-            if ($Geo::OGR::FieldDefn::SCHEMA_KEYS{$key}) {
-                $args{$key} = $named{$key};
-            } else {
-                carp "Unrecognized argument: '$key'.";
-            }
-        }
-        $name = $args{Name} if exists $args{Name};
-        delete $args{Name};
-        $type = $args{Type} if exists $args{Type};
-        delete $args{Type};
-    }
-    confess "Unknown field type: '$type'." unless exists $Geo::OGR::FieldDefn::TYPE_STRING2INT{$type};
-    $type = $Geo::OGR::FieldDefn::TYPE_STRING2INT{$type};
-    my $self = Geo::OGRc::new_FieldDefn($name, $type);
-    if (defined($self)) {
-        bless $self, $pkg;
-        $self->Schema(%args);
-    }
-    return $self;
-}
-
-*GetName = *Geo::OGRc::FieldDefn_GetName;
-*GetNameRef = *Geo::OGRc::FieldDefn_GetNameRef;
-*SetName = *Geo::OGRc::FieldDefn_SetName;
-*GetType = *Geo::OGRc::FieldDefn_GetType;
-*SetType = *Geo::OGRc::FieldDefn_SetType;
-*GetSubType = *Geo::OGRc::FieldDefn_GetSubType;
-*SetSubType = *Geo::OGRc::FieldDefn_SetSubType;
-*GetJustify = *Geo::OGRc::FieldDefn_GetJustify;
-*SetJustify = *Geo::OGRc::FieldDefn_SetJustify;
-*GetWidth = *Geo::OGRc::FieldDefn_GetWidth;
-*SetWidth = *Geo::OGRc::FieldDefn_SetWidth;
-*GetPrecision = *Geo::OGRc::FieldDefn_GetPrecision;
-*SetPrecision = *Geo::OGRc::FieldDefn_SetPrecision;
-*GetTypeName = *Geo::OGRc::FieldDefn_GetTypeName;
-*GetFieldTypeName = *Geo::OGRc::FieldDefn_GetFieldTypeName;
-*IsIgnored = *Geo::OGRc::FieldDefn_IsIgnored;
-*SetIgnored = *Geo::OGRc::FieldDefn_SetIgnored;
-*IsNullable = *Geo::OGRc::FieldDefn_IsNullable;
-*SetNullable = *Geo::OGRc::FieldDefn_SetNullable;
-*GetDefault = *Geo::OGRc::FieldDefn_GetDefault;
-*SetDefault = *Geo::OGRc::FieldDefn_SetDefault;
-*IsDefaultDriverSpecific = *Geo::OGRc::FieldDefn_IsDefaultDriverSpecific;
-sub DISOWN {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    delete $OWNER{$ptr};
-}
-
-sub ACQUIRE {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    $OWNER{$ptr} = 1;
-}
-
-
-############# Class : Geo::OGR::GeomFieldDefn ##############
-
-package Geo::OGR::GeomFieldDefn;
-use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
- at ISA = qw( Geo::OGR );
-%OWNER = ();
-%ITERATORS = ();
-sub DESTROY {
-    return unless $_[0]->isa('HASH');
-    my $self = tied(%{$_[0]});
-    return unless defined $self;
-    delete $ITERATORS{$self};
-    if (exists $OWNER{$self}) {
-        Geo::OGRc::delete_GeomFieldDefn($self);
-        delete $OWNER{$self};
-    }
-}
-
-use Carp;
-sub new {
-    my $pkg = shift;
-    my ($name, $type) = ('geom', 'Unknown');
-    my %args;
-    if (@_ == 0) {
-    } elsif (@_ == 1) {
-        $name = shift;
-    } elsif (@_ == 2 and not $Geo::OGR::GeomFieldDefn::SCHEMA_KEYS{$_[0]}) {
-        $name = shift;
-        $type = shift;
-    } else {
-        my %named = @_;
-        for my $key (keys %named) {
-            if ($Geo::OGR::GeomFieldDefn::SCHEMA_KEYS{$key}) {
-                $args{$key} = $named{$key};
-            } else {
-                carp "Unrecognized argument: '$key'.";
-            }
-        }
-        $name = $args{Name} if exists $args{Name};
-        delete $args{Name};
-        $type = $args{Type} if $args{Type};
-        delete $args{Type};
-        $type = $args{GeometryType} if $args{GeometryType};
-        delete $args{GeometryType};
-    }
-    confess "Unknown geometry type: '$type'." unless exists $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
-    $type = $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
-    my $self = Geo::OGRc::new_GeomFieldDefn($name, $type);
-    if (defined($self)) {
-        bless $self, $pkg;
-        $self->Schema(%args);
-    }
-    return $self;
-}
-
-*GetName = *Geo::OGRc::GeomFieldDefn_GetName;
-*GetNameRef = *Geo::OGRc::GeomFieldDefn_GetNameRef;
-*SetName = *Geo::OGRc::GeomFieldDefn_SetName;
-*GetType = *Geo::OGRc::GeomFieldDefn_GetType;
-*SetType = *Geo::OGRc::GeomFieldDefn_SetType;
-*GetSpatialRef = *Geo::OGRc::GeomFieldDefn_GetSpatialRef;
-*SetSpatialRef = *Geo::OGRc::GeomFieldDefn_SetSpatialRef;
-*IsIgnored = *Geo::OGRc::GeomFieldDefn_IsIgnored;
-*SetIgnored = *Geo::OGRc::GeomFieldDefn_SetIgnored;
-*IsNullable = *Geo::OGRc::GeomFieldDefn_IsNullable;
-*SetNullable = *Geo::OGRc::GeomFieldDefn_SetNullable;
-sub DISOWN {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    delete $OWNER{$ptr};
-}
-
-sub ACQUIRE {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    $OWNER{$ptr} = 1;
-}
-
-
-############# Class : Geo::OGR::Geometry ##############
-
-package Geo::OGR::Geometry;
-use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
- at ISA = qw( Geo::OGR );
-%OWNER = ();
-sub DESTROY {
-    my $self;
-    if ($_[0]->isa('SCALAR')) {
-        $self = $_[0];
-    } else {
-        return unless $_[0]->isa('HASH');
-        $self = tied(%{$_[0]});
-        return unless defined $self;
-    }
-    delete $ITERATORS{$self};
-    if (exists $OWNER{$self}) {
-        Geo::OGRc::delete_Geometry($self);
-        delete $OWNER{$self};
-    }
-    $self->RELEASE_PARENTS();
-}
-
-use Carp;
-sub new {
-    my $pkg = shift;
-    my ($type, $wkt, $wkb, $gml, $json, $srs, $points, $arc);
-    my %param;
-    if (@_ == 1 and ref($_[0]) eq 'HASH') {
-        %param = %{$_[0]};
-    } elsif (@_ % 2 == 0) {
-        %param = @_;
-    } else {
-        ($param{GeometryType}) = @_;
-    }
-    $type = ($param{type} or $param{Type} or $param{GeometryType});
-    $srs = ($param{srs} or $param{SRS});
-    $wkt = ($param{wkt} or $param{WKT});
-    $wkb = ($param{wkb} or $param{WKB});
-    my $hex = ($param{hexewkb} or $param{HEXEWKB}); # PostGIS HEX EWKB
-    my $srid;
-    if ($hex) {
-        # get and remove SRID
-        $srid = substr($hex, 10, 8);
-        substr($hex, 10, 8) = '';
-    } else {
-        $hex = ($param{hexwkb} or $param{HEXWKB});
-    }
-    if ($hex) {
-        $wkb = '';
-        for (my $i = 0; $i < length($hex); $i+=2) {
-            $wkb .= chr(hex(substr($hex,$i,2)));
-        }
-    }
-    $gml = ($param{gml} or $param{GML});
-    $json = ($param{geojson} or $param{GeoJSON});
-    $points = $param{Points};
-    $arc = ($param{arc} or $param{Arc});
-    my $self;
-    if (defined $wkt) {
-        $self = Geo::OGRc::CreateGeometryFromWkt($wkt, $srs);
-    } elsif (defined $wkb) {
-        $self = Geo::OGRc::CreateGeometryFromWkb($wkb, $srs);
-    } elsif (defined $gml) {
-        $self = Geo::OGRc::CreateGeometryFromGML($gml);
-    } elsif (defined $json) {
-        $self = Geo::OGRc::CreateGeometryFromJson($json);
-    } elsif (defined $type) {
-        confess "Unknown geometry type: '$type'." unless exists $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
-        $type = $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
-        $self = Geo::OGRc::new_Geometry($type); # flattens the type
-        SetCoordinateDimension($self, 3) if Geo::OGR::GT_HasZ($type);
-    } elsif (defined $arc) {
-        $self = Geo::OGRc::ApproximateArcAngles(@$arc);
-    } else {
-        confess "Missing a parameter when creating a Geo::OGR::Geometry object.";
-    }
-    bless $self, $pkg if defined $self;
-    $self->Points($points) if $points;
-    return $self;
-}
-
-*ExportToWkt = *Geo::OGRc::Geometry_ExportToWkt;
-*ExportToIsoWkt = *Geo::OGRc::Geometry_ExportToIsoWkt;
-*_ExportToWkb = *Geo::OGRc::Geometry__ExportToWkb;
-*ExportToIsoWkb = *Geo::OGRc::Geometry_ExportToIsoWkb;
-*ExportToGML = *Geo::OGRc::Geometry_ExportToGML;
-*ExportToKML = *Geo::OGRc::Geometry_ExportToKML;
-*ExportToJson = *Geo::OGRc::Geometry_ExportToJson;
-*AddPoint_3D = *Geo::OGRc::Geometry_AddPoint_3D;
-*AddPoint_2D = *Geo::OGRc::Geometry_AddPoint_2D;
-*AddGeometryDirectly = *Geo::OGRc::Geometry_AddGeometryDirectly;
-*AddGeometry = *Geo::OGRc::Geometry_AddGeometry;
-*Clone = *Geo::OGRc::Geometry_Clone;
-*GetGeometryType = *Geo::OGRc::Geometry_GetGeometryType;
-*GetGeometryName = *Geo::OGRc::Geometry_GetGeometryName;
-*Length = *Geo::OGRc::Geometry_Length;
-*Area = *Geo::OGRc::Geometry_Area;
-*GetArea = *Geo::OGRc::Geometry_GetArea;
-*GetPointCount = *Geo::OGRc::Geometry_GetPointCount;
-*GetX = *Geo::OGRc::Geometry_GetX;
-*GetY = *Geo::OGRc::Geometry_GetY;
-*GetZ = *Geo::OGRc::Geometry_GetZ;
-*GetPoint_3D = *Geo::OGRc::Geometry_GetPoint_3D;
-*GetPoint_2D = *Geo::OGRc::Geometry_GetPoint_2D;
-*GetGeometryCount = *Geo::OGRc::Geometry_GetGeometryCount;
-*SetPoint_3D = *Geo::OGRc::Geometry_SetPoint_3D;
-*SetPoint_2D = *Geo::OGRc::Geometry_SetPoint_2D;
-*GetGeometryRef = *Geo::OGRc::Geometry_GetGeometryRef;
-*Simplify = *Geo::OGRc::Geometry_Simplify;
-*SimplifyPreserveTopology = *Geo::OGRc::Geometry_SimplifyPreserveTopology;
-*Boundary = *Geo::OGRc::Geometry_Boundary;
-*GetBoundary = *Geo::OGRc::Geometry_GetBoundary;
-*ConvexHull = *Geo::OGRc::Geometry_ConvexHull;
-*Buffer = *Geo::OGRc::Geometry_Buffer;
-*Intersection = *Geo::OGRc::Geometry_Intersection;
-*Union = *Geo::OGRc::Geometry_Union;
-*UnionCascaded = *Geo::OGRc::Geometry_UnionCascaded;
-*Difference = *Geo::OGRc::Geometry_Difference;
-*SymDifference = *Geo::OGRc::Geometry_SymDifference;
-*SymmetricDifference = *Geo::OGRc::Geometry_SymmetricDifference;
-*Distance = *Geo::OGRc::Geometry_Distance;
-*Empty = *Geo::OGRc::Geometry_Empty;
-*IsEmpty = *Geo::OGRc::Geometry_IsEmpty;
-*IsValid = *Geo::OGRc::Geometry_IsValid;
-*IsSimple = *Geo::OGRc::Geometry_IsSimple;
-*IsRing = *Geo::OGRc::Geometry_IsRing;
-*Intersects = *Geo::OGRc::Geometry_Intersects;
-*Intersect = *Geo::OGRc::Geometry_Intersect;
-*Equals = *Geo::OGRc::Geometry_Equals;
-*Equal = *Geo::OGRc::Geometry_Equal;
-*Disjoint = *Geo::OGRc::Geometry_Disjoint;
-*Touches = *Geo::OGRc::Geometry_Touches;
-*Crosses = *Geo::OGRc::Geometry_Crosses;
-*Within = *Geo::OGRc::Geometry_Within;
-*Contains = *Geo::OGRc::Geometry_Contains;
-*Overlaps = *Geo::OGRc::Geometry_Overlaps;
-*TransformTo = *Geo::OGRc::Geometry_TransformTo;
-*Transform = *Geo::OGRc::Geometry_Transform;
-*GetSpatialReference = *Geo::OGRc::Geometry_GetSpatialReference;
-*AssignSpatialReference = *Geo::OGRc::Geometry_AssignSpatialReference;
-*CloseRings = *Geo::OGRc::Geometry_CloseRings;
-*FlattenTo2D = *Geo::OGRc::Geometry_FlattenTo2D;
-*Segmentize = *Geo::OGRc::Geometry_Segmentize;
-*GetEnvelope = *Geo::OGRc::Geometry_GetEnvelope;
-*GetEnvelope3D = *Geo::OGRc::Geometry_GetEnvelope3D;
-*Centroid = *Geo::OGRc::Geometry_Centroid;
-*PointOnSurface = *Geo::OGRc::Geometry_PointOnSurface;
-*WkbSize = *Geo::OGRc::Geometry_WkbSize;
-*GetCoordinateDimension = *Geo::OGRc::Geometry_GetCoordinateDimension;
-*SetCoordinateDimension = *Geo::OGRc::Geometry_SetCoordinateDimension;
-*GetDimension = *Geo::OGRc::Geometry_GetDimension;
-*HasCurveGeometry = *Geo::OGRc::Geometry_HasCurveGeometry;
-*GetLinearGeometry = *Geo::OGRc::Geometry_GetLinearGeometry;
-*GetCurveGeometry = *Geo::OGRc::Geometry_GetCurveGeometry;
-*Value = *Geo::OGRc::Geometry_Value;
-*Move = *Geo::OGRc::Geometry_Move;
-sub DISOWN {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    delete $OWNER{$ptr};
-}
-
-sub ACQUIRE {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    $OWNER{$ptr} = 1;
-}
-
-
-# ------- VARIABLE STUBS --------
-
-package Geo::OGR;
-
-*wkb25DBit = *Geo::OGRc::wkb25DBit;
-*wkb25Bit = *Geo::OGRc::wkb25Bit;
-*wkbUnknown = *Geo::OGRc::wkbUnknown;
-*wkbPoint = *Geo::OGRc::wkbPoint;
-*wkbLineString = *Geo::OGRc::wkbLineString;
-*wkbPolygon = *Geo::OGRc::wkbPolygon;
-*wkbMultiPoint = *Geo::OGRc::wkbMultiPoint;
-*wkbMultiLineString = *Geo::OGRc::wkbMultiLineString;
-*wkbMultiPolygon = *Geo::OGRc::wkbMultiPolygon;
-*wkbGeometryCollection = *Geo::OGRc::wkbGeometryCollection;
-*wkbCircularString = *Geo::OGRc::wkbCircularString;
-*wkbCompoundCurve = *Geo::OGRc::wkbCompoundCurve;
-*wkbCurvePolygon = *Geo::OGRc::wkbCurvePolygon;
-*wkbMultiCurve = *Geo::OGRc::wkbMultiCurve;
-*wkbMultiSurface = *Geo::OGRc::wkbMultiSurface;
-*wkbNone = *Geo::OGRc::wkbNone;
-*wkbLinearRing = *Geo::OGRc::wkbLinearRing;
-*wkbCircularStringZ = *Geo::OGRc::wkbCircularStringZ;
-*wkbCompoundCurveZ = *Geo::OGRc::wkbCompoundCurveZ;
-*wkbCurvePolygonZ = *Geo::OGRc::wkbCurvePolygonZ;
-*wkbMultiCurveZ = *Geo::OGRc::wkbMultiCurveZ;
-*wkbMultiSurfaceZ = *Geo::OGRc::wkbMultiSurfaceZ;
-*wkbPoint25D = *Geo::OGRc::wkbPoint25D;
-*wkbLineString25D = *Geo::OGRc::wkbLineString25D;
-*wkbPolygon25D = *Geo::OGRc::wkbPolygon25D;
-*wkbMultiPoint25D = *Geo::OGRc::wkbMultiPoint25D;
-*wkbMultiLineString25D = *Geo::OGRc::wkbMultiLineString25D;
-*wkbMultiPolygon25D = *Geo::OGRc::wkbMultiPolygon25D;
-*wkbGeometryCollection25D = *Geo::OGRc::wkbGeometryCollection25D;
-*OFTInteger = *Geo::OGRc::OFTInteger;
-*OFTIntegerList = *Geo::OGRc::OFTIntegerList;
-*OFTReal = *Geo::OGRc::OFTReal;
-*OFTRealList = *Geo::OGRc::OFTRealList;
-*OFTString = *Geo::OGRc::OFTString;
-*OFTStringList = *Geo::OGRc::OFTStringList;
-*OFTWideString = *Geo::OGRc::OFTWideString;
-*OFTWideStringList = *Geo::OGRc::OFTWideStringList;
-*OFTBinary = *Geo::OGRc::OFTBinary;
-*OFTDate = *Geo::OGRc::OFTDate;
-*OFTTime = *Geo::OGRc::OFTTime;
-*OFTDateTime = *Geo::OGRc::OFTDateTime;
-*OFTInteger64 = *Geo::OGRc::OFTInteger64;
-*OFTInteger64List = *Geo::OGRc::OFTInteger64List;
-*OFSTNone = *Geo::OGRc::OFSTNone;
-*OFSTBoolean = *Geo::OGRc::OFSTBoolean;
-*OFSTInt16 = *Geo::OGRc::OFSTInt16;
-*OFSTFloat32 = *Geo::OGRc::OFSTFloat32;
-*OJUndefined = *Geo::OGRc::OJUndefined;
-*OJLeft = *Geo::OGRc::OJLeft;
-*OJRight = *Geo::OGRc::OJRight;
-*wkbXDR = *Geo::OGRc::wkbXDR;
-*wkbNDR = *Geo::OGRc::wkbNDR;
-*NullFID = *Geo::OGRc::NullFID;
-*ALTER_NAME_FLAG = *Geo::OGRc::ALTER_NAME_FLAG;
-*ALTER_TYPE_FLAG = *Geo::OGRc::ALTER_TYPE_FLAG;
-*ALTER_WIDTH_PRECISION_FLAG = *Geo::OGRc::ALTER_WIDTH_PRECISION_FLAG;
-*ALTER_NULLABLE_FLAG = *Geo::OGRc::ALTER_NULLABLE_FLAG;
-*ALTER_DEFAULT_FLAG = *Geo::OGRc::ALTER_DEFAULT_FLAG;
-*ALTER_ALL_FLAG = *Geo::OGRc::ALTER_ALL_FLAG;
-*F_VAL_NULL = *Geo::OGRc::F_VAL_NULL;
-*F_VAL_GEOM_TYPE = *Geo::OGRc::F_VAL_GEOM_TYPE;
-*F_VAL_WIDTH = *Geo::OGRc::F_VAL_WIDTH;
-*F_VAL_ALLOW_NULL_WHEN_DEFAULT = *Geo::OGRc::F_VAL_ALLOW_NULL_WHEN_DEFAULT;
-*F_VAL_ALL = *Geo::OGRc::F_VAL_ALL;
-*OLCRandomRead = *Geo::OGRc::OLCRandomRead;
-*OLCSequentialWrite = *Geo::OGRc::OLCSequentialWrite;
-*OLCRandomWrite = *Geo::OGRc::OLCRandomWrite;
-*OLCFastSpatialFilter = *Geo::OGRc::OLCFastSpatialFilter;
-*OLCFastFeatureCount = *Geo::OGRc::OLCFastFeatureCount;
-*OLCFastGetExtent = *Geo::OGRc::OLCFastGetExtent;
-*OLCCreateField = *Geo::OGRc::OLCCreateField;
-*OLCDeleteField = *Geo::OGRc::OLCDeleteField;
-*OLCReorderFields = *Geo::OGRc::OLCReorderFields;
-*OLCAlterFieldDefn = *Geo::OGRc::OLCAlterFieldDefn;
-*OLCTransactions = *Geo::OGRc::OLCTransactions;
-*OLCDeleteFeature = *Geo::OGRc::OLCDeleteFeature;
-*OLCFastSetNextByIndex = *Geo::OGRc::OLCFastSetNextByIndex;
-*OLCStringsAsUTF8 = *Geo::OGRc::OLCStringsAsUTF8;
-*OLCIgnoreFields = *Geo::OGRc::OLCIgnoreFields;
-*OLCCreateGeomField = *Geo::OGRc::OLCCreateGeomField;
-*OLCCurveGeometries = *Geo::OGRc::OLCCurveGeometries;
-*ODsCCreateLayer = *Geo::OGRc::ODsCCreateLayer;
-*ODsCDeleteLayer = *Geo::OGRc::ODsCDeleteLayer;
-*ODsCCreateGeomFieldAfterCreateLayer = *Geo::OGRc::ODsCCreateGeomFieldAfterCreateLayer;
-*ODsCCurveGeometries = *Geo::OGRc::ODsCCurveGeometries;
-*ODsCTransactions = *Geo::OGRc::ODsCTransactions;
-*ODsCEmulatedTransactions = *Geo::OGRc::ODsCEmulatedTransactions;
-*ODrCCreateDataSource = *Geo::OGRc::ODrCCreateDataSource;
-*ODrCDeleteDataSource = *Geo::OGRc::ODrCDeleteDataSource;
-*OLMD_FID64 = *Geo::OGRc::OLMD_FID64;
-*TermProgress = *Geo::OGRc::TermProgress;
-
-
-package Geo::OGR;
-our $VERSION = '2.0002'; # this needs to be the same as that in gdal_perl.i
-
-package Geo::OGR::Driver;
-use strict;
-use warnings;
-use Carp;
-use vars qw /@CAPABILITIES %CAPABILITIES/;
-for (keys %Geo::OGR::) {
-    push(@CAPABILITIES, $1), next if /^ODrC(\w+)/;
-}
-for my $s (@CAPABILITIES) {
-    my $cap = eval "\$Geo::OGR::ODrC$s";
-    $CAPABILITIES{$s} = $cap;
-}
-
-sub Capabilities {
-    return @CAPABILITIES if @_ == 0;
-    my $self = shift;
-    my @cap;
-    for my $cap (@CAPABILITIES) {
-        push @cap, $cap if _TestCapability($self, $CAPABILITIES{$cap});
-    }
-    return @cap;
-}
-
-sub TestCapability {
-    my($self, $cap) = @_;
-    confess "No such capability defined for class Driver: '$cap'." unless defined $CAPABILITIES{$cap};
-    return _TestCapability($self, $CAPABILITIES{$cap});
-}
-
-*Create = *CreateDataSource;
-*Copy = *CopyDataSource;
-*OpenDataSource = *Open;
-*Delete = *DeleteDataSource;
-*Name = *GetName;
-
-
-
-
-package Geo::OGR::DataSource;
-use strict;
-use warnings;
-use Carp;
-use vars qw /@CAPABILITIES %CAPABILITIES %LAYERS %RESULT_SET/;
-for (keys %Geo::OGR::) {
-    push(@CAPABILITIES, $1), next if /^ODsC(\w+)/;
-}
-for my $s (@CAPABILITIES) {
-    my $cap = eval "\$Geo::OGR::ODsC$s";
-    $CAPABILITIES{$s} = $cap;
-}
-
-sub Capabilities {
-    return @CAPABILITIES if @_ == 0;
-    my $self = shift;
-    my @cap;
-    for my $cap (@CAPABILITIES) {
-        push @cap, $cap if _TestCapability($self, $CAPABILITIES{$cap});
-    }
-    return @cap;
-}
-
-sub TestCapability {
-    my($self, $cap) = @_;
-    confess "No such capability defined for class DataSource: '$cap'." unless defined $CAPABILITIES{$cap};
-    return _TestCapability($self, $CAPABILITIES{$cap});
-}
-*GetDriver = *_GetDriver;
-
-sub new {
-    my $pkg = shift;
-    return Geo::OGR::Open(@_);
-}
-
-sub Open {
-    return Geo::OGR::Open(@_);
-}
-
-sub OpenShared {
-    return Geo::OGR::OpenShared(@_);
-}
-
-sub ExecuteSQL {
-    my $self = shift;
-    my $layer = $self->_ExecuteSQL(@_);
-    $LAYERS{tied(%$layer)} = $self;
-    $RESULT_SET{tied(%$layer)} = 1;
-    return $layer;
-}
-
-sub ReleaseResultSet {
-    # a no-op, _ReleaseResultSet is called from Layer::DESTROY
-}
-
-sub GetLayer {
-    my($self, $name) = @_;
-    my $layer = defined $name ? GetLayerByName($self, "$name") : GetLayerByIndex($self, 0);
-    $name = '' unless defined $name;
-    confess "No such layer: '$name'." unless $layer;
-    $LAYERS{tied(%$layer)} = $self;
-    return $layer;
-}
-*Layer = *GetLayer;
-
-sub GetLayerNames {
-    my $self = shift;
-    my @names;
-    for my $i (0..$self->GetLayerCount-1) {
-        my $layer = GetLayerByIndex($self, $i);
-        push @names, $layer->GetName;
-    }
-    return @names;
-}
-*Layers = *GetLayerNames;
-
-sub CreateLayer {
-    my $self = shift;
-    my %defaults = ( Name => 'unnamed',
-                     SRS => undef,
-                     Options => {},
-                     GeometryType => 'Unknown',
-                     Schema => undef,
-                     Fields => undef,
-                     ApproxOK => 1);
-    my %params;
-    if (@_ == 0) {
-    } elsif (ref($_[0]) eq 'HASH') {
-        %params = %{$_[0]};
-    } elsif (@_ % 2 == 0 and (defined $_[0] and exists $defaults{$_[0]})) {
-        %params = @_;
-    } else {
-        ($params{Name}, $params{SRS}, $params{GeometryType}, $params{Options}, $params{Schema}) = @_;
-    }
-    for (keys %params) {
-        carp "CreateLayer: unknown named parameter '$_'." unless exists $defaults{$_};
-    }
-    if (exists $params{Schema}) {
-        my $s = $params{Schema};
-        $params{GeometryType} = $s->{GeometryType} if exists $s->{GeometryType};
-        $params{Fields} = $s->{Fields} if exists $s->{Fields};
-        $params{Name} = $s->{Name} if exists $s->{Name};
-    }
-    $defaults{GeometryType} = 'None' if $params{Fields};
-    for (keys %defaults) {
-        $params{$_} = $defaults{$_} unless defined $params{$_};
-    }
-    confess "Unknown geometry type: '$params{GeometryType}'."
-        unless exists $Geo::OGR::Geometry::TYPE_STRING2INT{$params{GeometryType}};
-    my $gt = $Geo::OGR::Geometry::TYPE_STRING2INT{$params{GeometryType}};
-    my $layer = _CreateLayer($self, $params{Name}, $params{SRS}, $gt, $params{Options});
-    $LAYERS{tied(%$layer)} = $self;
-    my $f = $params{Fields};
-    if ($f) {
-        confess "Named parameter 'Fields' must be a reference to an array." unless ref($f) eq 'ARRAY';
-        for my $field (@$f) {
-            $layer->CreateField($field);
-        }
-    }
-    return $layer;
-}
-
-sub DeleteLayer {
-    my ($self, $name) = @_;
-    my $index;
-    for my $i (0..$self->GetLayerCount-1) {
-        my $layer = GetLayerByIndex($self, $i);
-        $index = $i, last if $layer->GetName eq $name;
-    }
-    confess "No such layer: '$name'." unless defined $index;
-    _DeleteLayer($self, $index);
-}
-
-
-
-
-package Geo::OGR::Layer;
-use strict;
-use warnings;
-use Carp;
-use Scalar::Util 'blessed';
-use vars qw /@CAPABILITIES %CAPABILITIES  %DEFNS/;
-for (keys %Geo::OGR::) {
-    push(@CAPABILITIES, $1), next if /^OLC(\w+)/;
-}
-for my $s (@CAPABILITIES) {
-    my $cap = eval "\$Geo::OGR::OLC$s";
-    $CAPABILITIES{$s} = $cap;
-}
-
-sub DESTROY {
-    my $self;
-    if ($_[0]->isa('SCALAR')) {
-        $self = $_[0];
-    } else {
-        return unless $_[0]->isa('HASH');
-        $self = tied(%{$_[0]});
-        return unless defined $self;
-    }
-    if ($Geo::OGR::DataSource::RESULT_SET{$self}) {
-        $Geo::OGR::DataSource::LAYERS{$self}->_ReleaseResultSet($self);
-        delete $Geo::OGR::DataSource::RESULT_SET{$self}
-    }
-    delete $ITERATORS{$self};
-    if (exists $OWNER{$self}) {
-        delete $OWNER{$self};
-    }
-    $self->RELEASE_PARENTS();
-}
-
-sub RELEASE_PARENTS {
-    my $self = shift;
-    delete $Geo::OGR::DataSource::LAYERS{$self};
-}
-
-sub Capabilities {
-    return @CAPABILITIES if @_ == 0;
-    my $self = shift;
-    my @cap;
-    for my $cap (@CAPABILITIES) {
-        push @cap, $cap if _TestCapability($self, $CAPABILITIES{$cap});
-    }
-    return @cap;
-}
-
-sub TestCapability {
-    my($self, $cap) = @_;
-    return _TestCapability($self, $CAPABILITIES{$cap});
-}
-
-sub GetDataSource {
-    my $self = shift;
-    return $Geo::OGR::DataSource::LAYERS{$self};
-}
-*DataSource = *GetDataSource;
-
-sub GetDefn {
-    my $self = shift;
-    my $defn = $self->GetLayerDefn;
-    $DEFNS{$defn} = $self;
-    return $defn;
-}
-
-sub CreateField {
-    my $self = shift;
-    my %defaults = ( ApproxOK => 1,
-                     Type => '' );
-    my %params;
-    if (@_ == 0) {
-    } elsif (ref($_[0]) eq 'HASH') {
-        %params = %{$_[0]};
-    } elsif (@_ % 2 == 0) {
-        %params = @_;
-    } else {
-        ($params{Defn}) = @_;
-    }
-    for (keys %defaults) {
-        $params{$_} = $defaults{$_} unless defined $params{$_};
-    }
-    if (blessed($params{Defn}) and $params{Defn}->isa('Geo::OGR::FieldDefn')) {
-        $self->_CreateField($params{Defn}, $params{ApproxOK});
-    } elsif (blessed($_[0]) and $params{Defn}->isa('Geo::OGR::GeomFieldDefn')) {
-        $self->CreateGeomField($params{Defn}, $params{ApproxOK});
-    } else {
-        my $a = $params{ApproxOK};
-        delete $params{ApproxOK};
-        if (exists $params{GeometryType}) {
-            $params{Type} = $params{GeometryType};
-            delete $params{GeometryType};
-        }
-        if (exists $Geo::OGR::FieldDefn::TYPE_STRING2INT{$params{Type}}) {
-            my $fd = Geo::OGR::FieldDefn->new(%params);
-            _CreateField($self, $fd, $a);
-        } else {
-            my $fd = Geo::OGR::GeomFieldDefn->new(%params);
-            CreateGeomField($self, $fd, $a);
-        }
-    }
-}
-
-sub AlterFieldDefn {
-    my $self = shift;
-    my $field = shift;
-    my $index;
-    eval {
-        $index = $self->GetFieldIndex($field);
-    };
-    confess "Only non-spatial fields can be altered.\n$@" if $@;
-    if (blessed($_[0]) and $_[0]->isa('Geo::OGR::FieldDefn')) {
-        _AlterFieldDefn($self, $index, @_);
-    } elsif (@_ % 2 == 0) {
-        my %params = @_;
-        my $definition = Geo::OGR::FieldDefn->new(%params);
-        my $flags = 0;
-        $flags |= 1 if exists $params{Name};
-        $flags |= 2 if exists $params{Type};
-        $flags |= 4 if exists $params{Width} or exists $params{Precision};
-        $flags |= 8 if exists $params{Nullable};
-        $flags |= 16 if exists $params{Default};
-        _AlterFieldDefn($self, $index, $definition, $flags);
-    } else {
-        croak "Usage: AlterFieldDefn(\$Name, \%NamedParameters)";
-    }
-}
-
-sub DeleteField {
-    my($self, $fn) = @_;
-    my $d = $self->GetDefn;
-    my $index = $d->GetFieldIndex($fn);
-    $index = $fn if $index < 0;
-    eval {
-        _DeleteField($self, $index);
-    };
-    confess "Field not found: '$fn'. Only non-spatial fields can be deleted." if $@;
-}
-
-sub GetSchema {
-    my $self = shift;
-    carp "Schema of a layer should not be set directly." if @_;
-    if (@_ and @_ % 2 == 0) {
-        my %schema = @_;
-        if ($schema{Fields}) {
-            for my $field (@{$schema{Fields}}) {
-                $self->CreateField($field);
-            }
-        }
-    }
-    return $self->GetDefn->Schema;
-}
-*Schema = *GetSchema;
-
-sub Row {
-    my $self = shift;
-    my $update = @_ > 0;
-    my %row = @_;
-    my $feature = defined $row{FID} ? $self->GetFeature($row{FID}) : $self->GetNextFeature;
-    return unless $feature;
-    my $ret;
-    if (defined wantarray) {
-        $ret = $feature->Row(@_);
-    } else {
-        $feature->Row(@_);
-    }
-    $self->SetFeature($feature) if $update;
-    return unless defined wantarray;
-    return $ret;
-}
-
-sub Tuple {
-    my $self = shift;
-    my $FID = shift;
-    my $feature = defined $FID ? $self->GetFeature($FID) : $self->GetNextFeature;
-    return unless $feature;
-    my $set = @_ > 0;
-    unshift @_, $feature->GetFID if $set;
-    my @ret;
-    if (defined wantarray) {
-        @ret = $feature->Tuple(@_);
-    } else {
-        $feature->Tuple(@_);
-    }
-    $self->SetFeature($feature) if $set;
-    return unless defined wantarray;
-    return @ret;
-}
-
-sub SpatialFilter {
-    my $self = shift;
-    $self->SetSpatialFilter($_[0]) if @_ == 1;
-    $self->SetSpatialFilterRect(@_) if @_ == 4;
-    return unless defined wantarray;
-    $self->GetSpatialFilter;
-}
-
-sub InsertFeature {
-    my $self = shift;
-    my $feature = shift;
-    confess "Usage: \$feature->InsertFeature(reference to a hash or array)." unless ref($feature);
-    my $new = Geo::OGR::Feature->new($self->GetDefn);
-    if (ref($feature) eq 'HASH') {
-        $new->Row(%$feature);
-    } elsif (ref($feature) eq 'ARRAY') {
-        $new->Tuple(@$feature);
-    } elsif (blessed($feature) and $feature->isa('Geo::OGR::Feature')) {
-        $new->Row($feature->Row);
-    }
-    $self->CreateFeature($new);
-}
-
-sub ForFeatures {
-    my $self = shift;
-    my $code = shift;
-    my $in_place = shift;
-    $self->ResetReading;
-    while (my $f = $self->GetNextFeature) {
-        $code->($f);
-        $self->SetFeature($f) if $in_place;
-    };
-}
-
-sub ForGeometries {
-    my $self = shift;
-    my $code = shift;
-    my $in_place = shift;
-    $self->ResetReading;
-    while (my $f = $self->GetNextFeature) {
-        my $g = $f->Geometry();
-        $code->($g);
-        if ($in_place) {
-            $f->Geometry($g);
-            $self->SetFeature($f);
-        }
-    }
-}
-
-sub GetFieldNames {
-    my $self = shift;
-    my $d = $self->GetDefn;
-    my @ret;
-    for (my $i = 0; $i < $d->GetFieldCount; $i++) {
-        push @ret, $d->GetFieldDefn($i)->Name();
-    }
-    for (my $i = 0; $i < $d->GetGeomFieldCount; $i++) {
-        push @ret, $d->GetGeomFieldDefn($i)->Name();
-    }
-    return @ret;
-}
-
-sub GetFieldDefn {
-    my ($self, $name) = @_;
-    my $d = $self->GetDefn;
-    for (my $i = 0; $i < $d->GetFieldCount; $i++) {
-        my $fd = $d->GetFieldDefn($i);
-        return $fd if $fd->Name eq $name;
-    }
-    for (my $i = 0; $i < $d->GetGeomFieldCount; $i++) {
-        my $fd = $d->GetGeomFieldDefn($i);
-        return $fd if $fd->Name eq $name;
-    }
-    confess "No such field: '$name'.";
-}
-
-sub GeometryType {
-    my $self = shift;
-    my $d = $self->GetDefn;
-    my $fd = $d->GetGeomFieldDefn(0);
-    return $fd->Type if $fd;
-}
-
-sub SpatialReference {
-    my($self, $field, $sr) = @_;
-    my $d = $self->GetDefn;
-    my $i;
-    if (not defined $field or (blessed($field) and $field->isa('Geo::OSR::SpatialReference'))) {
-        $i = 0;
-    } else {
-        $i = $d->GetGeomFieldIndex($field);
-    }
-    my $d2 = $d->GetGeomFieldDefn($i);
-    $d2->SpatialReference($sr) if defined $sr;
-    return $d2->SpatialReference() if defined wantarray;
-}
-
-
-
-
-package Geo::OGR::FeatureDefn;
-use strict;
-use warnings;
-use Encode;
-use Carp;
-use Scalar::Util 'blessed';
-
-sub RELEASE_PARENTS {
-    my $self = shift;
-    delete $Geo::OGR::Feature::DEFNS{$self};
-    delete $Geo::OGR::Layer::DEFNS{$self};
-}
-
-*Name = *GetName;
-
-sub GetSchema {
-    my $self = shift;
-    carp "Schema of a feature definition should not be set directly." if @_;
-    if (@_ and @_ % 2 == 0) {
-        my %schema = @_;
-        if ($schema{Fields}) {
-            for my $field (@{$schema{Fields}}) {
-                $self->AddField($field);
-            }
-        }
-    }
-    my %schema;
-    $schema{Name} = $self->Name();
-    $schema{StyleIgnored} = $self->StyleIgnored();
-    $schema{Fields} = [];
-    for my $i (0..$self->GetFieldCount-1) {
-        my $s = $self->GetFieldDefn($i)->Schema;
-        push @{$schema{Fields}}, $s;
-    }
-    for my $i (0..$self->GetGeomFieldCount-1) {
-        my $s = $self->GetGeomFieldDefn($i)->Schema;
-        push @{$schema{Fields}}, $s;
-    }
-    return wantarray ? %schema : \%schema;
-}
-*Schema = *GetSchema;
-
-sub AddField {
-    my $self = shift;
-    confess "Read-only definition." if $Geo::OGR::Feature::DEFNS{$self} or $Geo::OGR::Layer::DEFNS{$self};
-    my %params;
-    if (@_ == 0) {
-    } elsif (ref($_[0]) eq 'HASH') {
-        %params = %{$_[0]};
-    } elsif (@_ % 2 == 0) {
-        %params = @_;
-    }
-    $params{Type} = '' unless defined $params{Type};
-    if (exists $Geo::OGR::FieldDefn::TYPE_STRING2INT{$params{Type}}) {
-        my $fd = Geo::OGR::FieldDefn->new(%params);
-        $self->AddFieldDefn($fd);
-    } else {
-        my $fd = Geo::OGR::GeomFieldDefn->new(%params);
-        $self->AddGeomFieldDefn($fd);
-    }
-}
-
-sub DeleteField {
-    my ($self, $name) = @_;
-    confess "Read-only definition." if $Geo::OGR::Feature::DEFNS{$self} or $Geo::OGR::Layer::DEFNS{$self};
-    for my $i (0..$self->GetFieldCount-1) {
-        confess "Non-geometry fields cannot be deleted." if $self->GetFieldDefn($i)->Name eq $name;
-    }
-    for my $i (0..$self->GetGeomFieldCount-1) {
-        $self->DeleteGeomFieldDefn($i) if $self->GetGeomFieldDefn($i)->Name eq $name;
-    }
-    confess "No such field: '$name'.";
-}
-
-sub GetFieldNames {
-    my $self = shift;
-    my @names = ();
-    for my $i (0..$self->GetFieldCount-1) {
-        push @names, $self->GetFieldDefn($i)->Name;
-    }
-    for my $i (0..$self->GetGeomFieldCount-1) {
-        push @names, $self->GetGeomFieldDefn($i)->Name;
-    }
-    return @names;
-}
-
-sub GetFieldDefn {
-    my ($self, $name) = @_;
-    for my $i (0..$self->GetFieldCount-1) {
-        my $fd = $self->GetFieldDefn($i);
-        return $fd if $fd->Name eq $name;
-    }
-    for my $i (0..$self->GetGeomFieldCount-1) {
-        my $fd = $self->GetGeomFieldDefn($i);
-        return $fd if $fd->Name eq $name;
-    }
-    confess "No such field: '$name'.";
-}
-
-sub GeomType {
-    my ($self, $type) = @_;
-    confess "Read-only definition." if $Geo::OGR::Feature::DEFNS{$self} or $Geo::OGR::Layer::DEFNS{$self};
-    if (defined $type) {
-        confess "Unknown geometry data type: '$type'." unless exists $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
-        $type = $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
-        SetGeomType($self, $type);
-    }
-    return $Geo::OGR::Geometry::TYPE_INT2STRING{GetGeomType($self)} if defined wantarray;
-}
-*GeometryType = *GeomType;
-
-sub GeometryIgnored {
-    my $self = shift;
-    SetGeometryIgnored($self, $_[0]) if @_;
-    IsGeometryIgnored($self) if defined wantarray;
-}
-
-sub StyleIgnored {
-    my $self = shift;
-    SetStyleIgnored($self, $_[0]) if @_;
-    IsStyleIgnored($self) if defined wantarray;
-}
-
-
-
-
-package Geo::OGR::Feature;
-use strict;
-use warnings;
-use vars qw /%GEOMETRIES %DEFNS/;
-use Carp;
-use Encode;
-use Scalar::Util 'blessed';
-
-sub FETCH {
-    my($self, $index) = @_;
-    my $i;
-    eval {$i = $self->_GetFieldIndex($index)};
-    $self->GetField($i) unless $@;
-    $i = $self->_GetGeomFieldIndex($index);
-    $self->GetGeometry($i);
-}
-
-sub STORE {
-    my $self = shift;
-    my $index = shift;
-    my $i;
-    eval {$i = $self->_GetFieldIndex($index)};
-    $self->SetField($i, @_) unless $@;
-    $i = $self->_GetGeomFieldIndex($index);
-    $self->SetGeometry($i, @_);
-}
-
-sub FID {
-    my $self = shift;
-    $self->SetFID($_[0]) if @_;
-    return unless defined wantarray;
-    $self->GetFID;
-}
-
-sub StyleString {
-    my $self = shift;
-    $self->SetStyleString($_[0]) if @_;
-    return unless defined wantarray;
-    $self->GetStyleString;
-}
-
-sub Validate {
-    my $self = shift;
-    my $flags = 0;
-    for my $flag (@_) {
-        my $f = eval '$Geo::OGR::'.uc($flag);
-        $flags |= $f;
-    }
-    _Validate($self, $flags);
-}
-
-sub GetSchema {
-    my $self = shift;
-    confess "Schema of a feature cannot be set directly." if @_;
-    return $self->GetDefnRef->Schema;
-}
-*Schema = *GetSchema;
-
-sub Row {
-    my $self = shift;
-    my $nf = $self->GetFieldCount;
-    my $ngf = $self->GetGeomFieldCount;
-    if (@_) { # update
-        my %row;
-        if (@_ == 1 and ref($_[0]) eq 'HASH') {
-            %row = %{$_[0]};
-        } elsif (@_ and @_ % 2 == 0) {
-            %row = @_;
-        } else {
-            confess 'Usage: $feature->Row(%FeatureData).';
-        }
-        $self->SetFID($row{FID}) if defined $row{FID};
-        #$self->Geometry($schema, $row{Geometry}) if $row{Geometry};
-        for my $name (keys %row) {
-            next if $name eq 'FID';
-            if ($name eq 'Geometry') {
-                $self->SetGeometry(0, $row{$name});
-                next;
-            }
-            my $f = 0;
-            for my $i (0..$nf-1) {
-                if ($self->GetFieldDefnRef($i)->Name eq $name) {
-                    $self->SetField($i, $row{$name});
-                    $f = 1;
-                    last;
-                }
-            }
-            next if $f;
-            for my $i (0..$ngf-1) {
-                if ($self->GetGeomFieldDefnRef($i)->Name eq $name) {
-                    $self->SetGeometry($i, $row{$name});
-                    $f = 1;
-                    last;
-                }
-            }
-            next if $f;
-            carp "Feature->Row: Unknown field: '$name'.";
-        }
-    }
-    return unless defined wantarray;
-    my %row = ();
-    for my $i (0..$nf-1) {
-        my $name = $self->GetFieldDefnRef($i)->Name;
-        $row{$name} = $self->GetField($i);
-    }
-    for my $i (0..$ngf-1) {
-        my $name = $self->GetGeomFieldDefnRef($i)->Name;
-        $name = 'Geometry' if $name eq '';
-        $row{$name} = $self->GetGeometry($i);
-    }
-    $row{FID} = $self->GetFID;
-    #$row{Geometry} = $self->Geometry;
-    return \%row;
-}
-
-sub Tuple {
-    my $self = shift;
-    my $nf = $self->GetFieldCount;
-    my $ngf = $self->GetGeomFieldCount;
-    if (@_) {
-        my $FID;
-        $FID = shift if @_ == $nf + $ngf + 1;
-        $self->SetFID($FID) if defined $FID;
-        my $values = \@_;
-        if (@$values != $nf + $ngf) {
-            my $n = $nf + $ngf;
-            confess "Too many or too few attribute values for a feature (need $n).";
-        }
-        my $index = 0; # index to non-geometry and geometry fields
-        for my $i (0..$nf-1) {
-            $self->SetField($i, $values->[$i]);
-        }
-        for my $i (0..$ngf-1) {
-            $self->SetGeometry($i, $values->[$nf+$i]);
-        }
-    }
-    return unless defined wantarray;
-    my @ret = ($self->GetFID);
-    for my $i (0..$nf-1) {
-        my $v = $self->GetField($i);
-        push @ret, $v;
-    }
-    for my $i (0..$ngf-1) {
-        my $v = $self->GetGeometry($i);
-        push @ret, $v;
-    }
-    return @ret;
-}
-
-sub GetDefn {
-    my $self = shift;
-    my $defn = $self->GetDefnRef;
-    $DEFNS{$defn} = $self;
-    return $defn;
-}
-
-*GetFieldNames = *Geo::OGR::Layer::GetFieldNames;
-*GetFieldDefn = *Geo::OGR::Layer::GetFieldDefn;
-
-sub _GetFieldIndex {
-    my($self, $field) = @_;
-    if ($field =~ /^\d+$/) {
-        return $field if $field >= 0 and $field < $self->GetFieldCount;
-    } else {
-        for my $i (0..$self->GetFieldCount-1) {
-            return $i if $self->GetFieldDefnRef($i)->Name eq $field;
-        }
-    }
-    confess "No such field: '$field'.";
-}
-
-sub GetField {
-    my($self, $field) = @_;
-    $field = $self->_GetFieldIndex($field);
-    return unless IsFieldSet($self, $field);
-    my $type = GetFieldType($self, $field);
-    if ($type == $Geo::OGR::OFTInteger) {
-        return GetFieldAsInteger($self, $field);
-    }
-    if ($type == $Geo::OGR::OFTInteger64) {
-        return GetFieldAsInteger64($self, $field);
-    }
-    if ($type == $Geo::OGR::OFTReal) {
-        return GetFieldAsDouble($self, $field);
-    }
-    if ($type == $Geo::OGR::OFTString) {
-        return GetFieldAsString($self, $field);
-    }
-    if ($type == $Geo::OGR::OFTIntegerList) {
-        my $ret = GetFieldAsIntegerList($self, $field);
-        return wantarray ? @$ret : $ret;
-    }
-    if ($type == $Geo::OGR::OFTInteger64List) {
-        my $ret = GetFieldAsInteger64List($self, $field);
-        return wantarray ? @$ret : $ret;
-    }
-    if ($type == $Geo::OGR::OFTRealList) {
-        my $ret = GetFieldAsDoubleList($self, $field);
-        return wantarray ? @$ret : $ret;
-    }
-    if ($type == $Geo::OGR::OFTStringList) {
-        my $ret = GetFieldAsStringList($self, $field);
-        return wantarray ? @$ret : $ret;
-    }
-    if ($type == $Geo::OGR::OFTBinary) {
-        return GetFieldAsString($self, $field);
-    }
-    if ($type == $Geo::OGR::OFTDate) {
-        my @ret = GetFieldAsDateTime($self, $field);
-        # year, month, day, hour, minute, second, timezone
-        return wantarray ? @ret[0..2] : [@ret[0..2]];
-    }
-    if ($type == $Geo::OGR::OFTTime) {
-        my @ret = GetFieldAsDateTime($self, $field);
-        return wantarray ? @ret[3..6] : [@ret[3..6]];
-    }
-    if ($type == $Geo::OGR::OFTDateTime) {
-        return GetFieldAsDateTime($self, $field);
-    }
-    confess "Perl bindings do not support field type '$Geo::OGR::FieldDefn::TYPE_INT2STRING{$type}'.";
-}
-
-sub UnsetField {
-    my($self, $field) = @_;
-    $field = $self->_GetFieldIndex($field);
-    _UnsetField($self, $field);
-}
-
-sub SetField {
-    my $self = shift;
-    my $field = shift;
-    $field = $self->_GetFieldIndex($field);
-    if (@_ == 0 or !defined($_[0])) {
-        _UnsetField($self, $field);
-        return;
-    }
-    my $list = ref($_[0]) ? $_[0] : [@_];
-    my $type = GetFieldType($self, $field);
-    if ($type == $Geo::OGR::OFTInteger or
-        $type == $Geo::OGR::OFTInteger64 or
-        $type == $Geo::OGR::OFTReal or
-        $type == $Geo::OGR::OFTString or
-        $type == $Geo::OGR::OFTBinary)
-    {
-        _SetField($self, $field, $_[0]);
-    }
-    elsif ($type == $Geo::OGR::OFTIntegerList) {
-        SetFieldIntegerList($self, $field, $list);
-    }
-    elsif ($type == $Geo::OGR::OFTInteger64List) {
-        SetFieldInteger64List($self, $field, $list);
-    }
-    elsif ($type == $Geo::OGR::OFTRealList) {
-        SetFieldDoubleList($self, $field, $list);
-    }
-    elsif ($type == $Geo::OGR::OFTStringList) {
-        SetFieldStringList($self, $field, $list);
-    }
-    elsif ($type == $Geo::OGR::OFTDate) {
-        # year, month, day, hour, minute, second, timezone
-        for my $i (0..6) {
-            $list->[$i] = 0 unless defined $list->[$i];
-        }
-        _SetField($self, $field, @$list[0..6]);
-    }
-    elsif ($type == $Geo::OGR::OFTTime) {
-        $list->[3] = 0 unless defined $list->[3];
-        _SetField($self, $field, 0, 0, 0, @$list[0..3]);
-    }
-    elsif ($type == $Geo::OGR::OFTDateTime) {
-        $list->[6] = 0 unless defined $list->[6];
-        _SetField($self, $field, @$list[0..6]);
-    }
-    else {
-        confess "Perl bindings do not support field type '$Geo::OGR::FieldDefn::TYPE_INT2STRING{$type}'.";
-    }
-}
-
-sub Field {
-    my $self = shift;
-    my $field = shift;
-    $self->SetField($field, @_) if @_;
-    $self->GetField($field);
-}
-
-sub _GetGeomFieldIndex {
-    my($self, $field) = @_;
-    if (not defined $field) {
-        return 0 if $self->GetGeomFieldCount > 0;
-    } if ($field =~ /^\d+$/) {
-        return $field if $field >= 0 and $field < $self->GetGeomFieldCount;
-    } else {
-        for my $i (0..$self->GetGeomFieldCount-1) {
-            return $i if $self->GetGeomFieldDefn($i)->Name eq $field;
-        }
-        return 0 if $self->GetGeomFieldCount > 0 and $field eq 'Geometry';
-    }
-    confess "No such field: '$field'.";
-}
-
-sub Geometry {
-    my $self = shift;
-    my $field = (ref($_[0]) eq '' or (@_ > 2 and @_ % 2 == 1)) ? shift : undef;
-    $field = $self->_GetGeomFieldIndex($field);
-    if (@_) {
-        my $type = $self->GetDefn->GetGeomFieldDefn($field)->Type;
-        my $geometry;
-        if (@_ == 1) {
-            $geometry = $_[0];
-        } elsif (@_ and @_ % 2 == 0) {
-            %$geometry = @_;
-        }
-        if (blessed($geometry) and $geometry->isa('Geo::OGR::Geometry')) {
-            confess "The type of the inserted geometry ('".$geometry->GeometryType."') is not the field type ('$type')."
-                if $type ne 'Unknown' and $type ne $geometry->GeometryType;
-            eval {
-                $self->SetGeomFieldDirectly($field, $geometry);
-            };
-            confess "$@" if $@;
-            $GEOMETRIES{tied(%{$geometry})} = $self;
-        } elsif (ref($geometry) eq 'HASH') {
-            $geometry->{GeometryType} = $type unless exists $geometry->{GeometryType};
-            eval {
-                $geometry = Geo::OGR::Geometry->new($geometry);
-            };
-            confess "The type of the inserted geometry ('".$geometry->GeometryType."') is not the field type ('$type')."
-                if $type ne 'Unknown' and $type ne $geometry->GeometryType;
-            eval {
-                $self->SetGeomFieldDirectly($field, $geometry);
-            };
-            confess "$@" if $@;
-        } else {
-            confess "'@_' does not define a geometry.";
-        }
-    }
-    return unless defined wantarray;
-    my $geometry = $self->GetGeomFieldRef($field);
-    return unless $geometry;
-    $GEOMETRIES{tied(%{$geometry})} = $self;
-    return $geometry;
-}
-*GetGeometry = *Geometry;
-*SetGeometry = *Geometry;
-
-sub SetFrom {
-    my($self, $other) = @_;
-    _SetFrom($self, $other), return if @_ <= 2;
-    my $forgiving = $_[2];
-    _SetFrom($self, $other, $forgiving), return if @_ <= 3;
-    my $map = $_[3];
-    my @list;
-    for my $i (1..GetFieldCount($self)) {
-        push @list, ($map->{$i} || -1);
-    }
-    SetFromWithMap($self, $other, 1, \@list);
-}
-
-
-
-
-package Geo::OGR::FieldDefn;
-use strict;
-use warnings;
-use vars qw /
-    %SCHEMA_KEYS
-    @TYPES @SUB_TYPES @JUSTIFY_VALUES
-    %TYPE_STRING2INT %TYPE_INT2STRING
-    %SUB_TYPE_STRING2INT %SUB_TYPE_INT2STRING
-    %JUSTIFY_STRING2INT %JUSTIFY_INT2STRING
-    /;
-use Carp;
-use Encode;
-%SCHEMA_KEYS = map {$_ => 1} qw/Name Type SubType Justify Width Precision Nullable Default Ignored/;
-for (keys %Geo::OGR::) {
-    push(@TYPES, $1), next if /^OFT(\w+)/;
-    push(@SUB_TYPES, $1), next if /^OFST(\w+)/;
-    push(@JUSTIFY_VALUES, $1), next if /^OJ(\w+)/;
-}
-for my $string (@TYPES) {
-    my $int = eval "\$Geo::OGR::OFT$string";
-    $TYPE_STRING2INT{$string} = $int;
-    $TYPE_INT2STRING{$int} = $string;
-}
-for my $string (@SUB_TYPES) {
-    my $int = eval "\$Geo::OGR::OFST$string";
-    $SUB_TYPE_STRING2INT{$string} = $int;
-    $SUB_TYPE_INT2STRING{$int} = $string;
-}
-for my $string (@JUSTIFY_VALUES) {
-    my $int = eval "\$Geo::OGR::OJ$string";
-    $JUSTIFY_STRING2INT{$string} = $int;
-    $JUSTIFY_INT2STRING{$int} = $string;
-}
-
-sub Types {
-    return @TYPES;
-}
-
-sub SubTypes {
-    return @SUB_TYPES;
-}
-
-sub JustifyValues {
-    return @JUSTIFY_VALUES;
-}
-
-sub Schema {
-    my $self = shift;
-    if (@_) {
-        my %args = @_;
-        for my $key (keys %SCHEMA_KEYS) {
-            eval '$self->'.$key.'($args{'.$key.'}) if exists $args{'.$key.'}';
-            croak $@ if $@;
-        }
-    }
-    return unless defined wantarray;
-    my %schema = ();
-    for my $key (keys %SCHEMA_KEYS) {
-        $schema{$key} = eval '$self->'.$key;
-    }
-    return wantarray ? %schema : \%schema;
-}
-*GetSchema = *Schema;
-*SetSchema = *Schema;
-
-sub Name {
-    my $self = shift;
-    SetName($self, $_[0]) if @_;
-    GetName($self) if defined wantarray;
-}
-
-sub Type {
-    my($self, $type) = @_;
-    if (defined $type) {
-        confess "Unknown field type: '$type'." unless exists $TYPE_STRING2INT{$type};
-        $type = $TYPE_STRING2INT{$type};
-        SetType($self, $type);
-    }
-    return $TYPE_INT2STRING{GetType($self)} if defined wantarray;
-}
-
-sub SubType {
-    my($self, $sub_type) = @_;
-    if (defined $sub_type) {
-        confess "Unknown field sub type: '$sub_type'." unless exists $SUB_TYPE_STRING2INT{$sub_type};
-        $sub_type = $SUB_TYPE_STRING2INT{$sub_type};
-        SetSubType($self, $sub_type);
-    }
-    return $SUB_TYPE_INT2STRING{GetSubType($self)} if defined wantarray;
-}
-
-sub Justify {
-    my($self, $justify) = @_;
-    if (defined $justify) {
-        confess "Unknown justify value: '$justify'." unless exists $JUSTIFY_STRING2INT{$justify};
-        $justify = $JUSTIFY_STRING2INT{$justify} if exists $JUSTIFY_STRING2INT{$justify};
-        SetJustify($self, $justify);
-    }
-    return $JUSTIFY_INT2STRING{GetJustify($self)} if defined wantarray;
-}
-
-sub Width {
-    my $self = shift;
-    SetWidth($self, $_[0]) if @_;
-    GetWidth($self) if defined wantarray;
-}
-
-sub Precision {
-    my $self = shift;
-    SetPrecision($self, $_[0]) if @_;
-    GetPrecision($self) if defined wantarray;
-}
-
-sub Nullable {
-    my $self = shift;
-    SetNullable($self, $_[0]) if @_;
-    IsNullable($self) if defined wantarray;
-}
-
-sub Default {
-    my $self = shift;
-    SetDefault($self, $_[0]) if @_;
-    GetDefault($self) if defined wantarray;
-}
-
-sub Ignored {
-    my $self = shift;
-    SetIgnored($self, $_[0]) if @_;
-    IsIgnored($self) if defined wantarray;
-}
-
-
-
-
-package Geo::OGR::GeomFieldDefn;
-use strict;
-use warnings;
-use vars qw / %SCHEMA_KEYS /;
-use Carp;
-use Scalar::Util 'blessed';
-%SCHEMA_KEYS = map {$_ => 1} qw/Name Type SpatialReference Nullable Ignored/;
-
-sub Schema {
-    my $self = shift;
-    if (@_) {
-        my %args = @_;
-        for my $key (keys %SCHEMA_KEYS) {
-            eval '$self->'.$key.'($args{'.$key.'}) if exists $args{'.$key.'}';
-            croak $@ if $@;
-        }
-    }
-    return unless defined wantarray;
-    my %schema = ();
-    for my $key (keys %SCHEMA_KEYS) {
-        $schema{$key} = eval '$self->'.$key;
-    }
-    return wantarray ? %schema : \%schema;
-}
-*GetSchema = *Schema;
-*SetSchema = *Schema;
-
-sub Name {
-    my $self = shift;
-    SetName($self, $_[0]) if @_;
-    GetName($self) if defined wantarray;
-}
-
-sub Type {
-    my($self, $type) = @_;
-    if (defined $type) {
-        confess "Unknown geometry type: '$type'." unless exists $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
-        $type = $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
-        SetType($self, $type);
-    }
-    $Geo::OGR::Geometry::TYPE_INT2STRING{GetType($self)} if defined wantarray;
-}
-
-sub Types {
-  return @Geo::OGR::Geometry::GEOMETRY_TYPES;
-}
-
-sub SpatialReference {
-    my $self = shift;
-    SetSpatialRef($self, $_[0]) if @_;
-    GetSpatialRef($self) if defined wantarray;
-}
-
-sub Nullable {
-    my $self = shift;
-    SetNullable($self, $_[0]) if @_;
-    IsNullable($self) if defined wantarray;
-}
-
-sub Ignored {
-    my $self = shift;
-    SetIgnored($self, $_[0]) if @_;
-    IsIgnored($self) if defined wantarray;
-}
-
-
-
-
-package Geo::OGR::Geometry;
-use strict;
-use warnings;
-use Carp;
-use vars qw /
-    @BYTE_ORDER_TYPES @GEOMETRY_TYPES
-    %BYTE_ORDER_STRING2INT %BYTE_ORDER_INT2STRING
-    %TYPE_STRING2INT %TYPE_INT2STRING
-    /;
- at BYTE_ORDER_TYPES = qw/XDR NDR/;
-for my $string (@BYTE_ORDER_TYPES) {
-    my $int = eval "\$Geo::OGR::wkb$string";
-    $BYTE_ORDER_STRING2INT{$string} = $int;
-    $BYTE_ORDER_INT2STRING{$int} = $string;
-}
-for (keys %Geo::OGR::) {
-    next if /^wkb25/;
-    next if /^wkb.DR/;
-    push(@GEOMETRY_TYPES, $1), next if /^wkb(\w+)/;
-}
-for my $string (@GEOMETRY_TYPES) {
-    my $int = eval "\$Geo::OGR::wkb$string";
-    $TYPE_STRING2INT{$string} = $int;
-    $TYPE_INT2STRING{$int} = $string;
-}
-
-sub ByteOrders {
-    return @BYTE_ORDER_TYPES;
-}
-
-sub GeometryTypes {
-    return @GEOMETRY_TYPES;
-}
-
-sub RELEASE_PARENTS {
-    my $self = shift;
-    delete $Geo::OGR::Feature::GEOMETRIES{$self};
-}
-
-sub ApproximateArcAngles {
-    my %p = @_;
-    my %default = ( Center => [0,0,0],
-                    PrimaryRadius => 1,
-                    SecondaryAxis => 1,
-                    Rotation => 0,
-                    StartAngle => 0,
-                    EndAngle => 360,
-                    MaxAngleStepSizeDegrees => 4 
-        );
-    for my $p (keys %p) {
-        if (exists $default{$p}) {
-            $p{$p} = $default{$p} unless defined $p{$p};
-        } else {
-            carp "Unknown named parameter: '$p'.";
-        }
-    }
-    for my $p (keys %default) {
-        $p{$p} = $default{$p} unless exists $p{$p};
-    }
-    confess "Usage: Center => [x,y,z]." unless ref($p{Center}) eq 'ARRAY';
-    for my $i (0..2) {
-        $p{Center}->[$i] = 0 unless defined $p{Center}->[$i];
-    }
-    return Geo::OGR::ApproximateArcAngles($p{Center}->[0], $p{Center}->[1], $p{Center}->[2], $p{PrimaryRadius}, $p{SecondaryAxis}, $p{Rotation}, $p{StartAngle}, $p{EndAngle}, $p{MaxAngleStepSizeDegrees});
-}
-
-sub As {
-    my $self = shift;
-    my %param;
-    if (@_ == 1 and ref($_[0]) eq 'HASH') {
-        %param = %{$_[0]};
-    } elsif (@_ % 2 == 0) {
-        %param = @_;
-    } else {
-        ($param{Format}, $param{x}) = @_;
-    }
-    $param{ByteOrder} = 'XDR' unless $param{ByteOrder};
-    my $f = $param{Format};
-    my $x = $param{x};
-    $x = $param{ByteOrder} unless defined $x;
-    if ($f =~ /text/i) {
-        return $self->AsText;
-    } elsif ($f =~ /wkt/i) {
-        if ($f =~ /iso/i) {
-            return $self->ExportToIsoWkt;
-        } else {
-            return $self->AsText;
-        }
-    } elsif ($f =~ /binary/i) {
-        return $self->AsBinary($x);        
-    } elsif ($f =~ /wkb/i) {
-        if ($f =~ /iso/i) {
-            return $self->ExportToIsoWkb;
-        } elsif ($f =~ /hexe/i) {
-            $param{srid} = 'XDR' unless $param{srid};
-            $x = $param{srid} unless defined $x;
-            return $self->AsHEXEWKB($x);
-        } elsif ($f =~ /hex/i) {
-            return $self->AsHEXWKB;
-        } else {
-            return $self->AsBinary($x);
-        }
-    } elsif ($f =~ /gml/i) {
-        return $self->AsGML;
-    } elsif ($f =~ /kml/i) {
-        return $self->AsKML;
-    } elsif ($f =~ /json/i) {
-        return $self->AsJSON;
-    } else {
-        confess "Unsupported format: $f.";
-    }
-}
-
-sub AsHEXWKB {
-    my ($self) = @_;
-    my $wkb = _ExportToWkb($self, 1);
-    my $hex = '';
-    for (my $i = 0; $i < length($wkb); $i++) {
-        my $x = sprintf("%x", ord(substr($wkb,$i,1)));
-        $x = '0' . $x if length($x) == 1;
-        $hex .= uc($x);
-    }
-    return $hex;
-}
-
-sub AsHEXEWKB {
-    my ($self, $srid) = @_;
-    my $hex = AsHEXWKB($self);
-    if ($srid) {
-        my $s = sprintf("%x", $srid);
-        $srid = '';
-        do {
-            if (length($s) > 2) {
-                $srid .= substr($s,-2,2);
-                substr($s,-2,2) = '';
-            } elsif (length($s) > 1) {
-                $srid .= $s;
-                $s = '';
-            } else {
-                $srid .= '0'.$s;
-                $s = '';
-            }
-        } until $s eq '';
-    } else {
-        $srid = '00000000';
-    }
-    while (length($srid) < 8) {
-        $srid .= '00';
-    }
-    substr($hex, 10, 0) = uc($srid);
-    return $hex;
-}
-
-sub GeometryType {
-    my $self = shift;
-    return $TYPE_INT2STRING{$self->GetGeometryType};
-}
-
-sub CoordinateDimension {
-    my $self = shift;
-    SetCoordinateDimension($self, $_[0]) if @_;
-    GetCoordinateDimension($self) if defined wantarray;
-}
-
-sub AddPoint {
-    @_ == 4 ? AddPoint_3D(@_) : AddPoint_2D(@_);
-}
-
-sub SetPoint {
-    @_ == 5 ? SetPoint_3D(@_) : SetPoint_2D(@_);
-}
-
-sub GetPoint {
-    my($self, $i) = @_;
-    $i = 0 unless defined $i;
-    my $point = ($self->GetGeometryType & 0x80000000) == 0 ? GetPoint_2D($self, $i) : GetPoint_3D($self, $i);
-    return @$point;
-}
-
-sub Point {
-    my $self = shift;
-    my $i;
-    if (@_) {
-        my $t = $self->GetGeometryType;
-        if ($t == $Geo::OGR::wkbPoint) {
-            shift if @_ > 2;
-            $i = 0;
-        } elsif ($t == $Geo::OGR::wkbPoint25D) {
-            shift if @_ > 3;
-            $i = 0;
-        } else {
-            my $i = shift;
-        }
-        SetPoint($self, $i, @_);
-    }
-    return GetPoint($self, $i) if defined wantarray;
-}
-
-sub Points {
-    my $self = shift;
-    my $t = $self->GetGeometryType;
-    my $flat = not Geo::OGR::GT_HasZ($t);
-    $t = Geo::OGR::GT_Flatten($t);
-    $t = $TYPE_INT2STRING{$t};
-    my $points = shift;
-    if ($points) {
-        Empty($self);
-        if ($t eq 'Unknown' or $t eq 'None' or $t eq 'GeometryCollection') {
-            confess "Can't set points of a geometry of type '$t'.";
-        } elsif ($t eq 'Point') {
-            # support both "Point" as a list of one point and one point
-            if (ref($points->[0])) {
-                $flat ?
-                    AddPoint_2D($self, @{$points->[0]}[0..1]) :
-                    AddPoint_3D($self, @{$points->[0]}[0..2]);
-            } else {
-                $flat ?
-                    AddPoint_2D($self, @$points[0..1]) :
-                    AddPoint_3D($self, @$points[0..2]);
-            }
-        } elsif ($t eq 'LineString' or $t eq 'LinearRing') {
-            if ($flat) {
-                for my $p (@$points) {
-                    AddPoint_2D($self, @$p[0..1]);
-                }
-            } else{
-                for my $p (@$points) {
-                    AddPoint_3D($self, @$p[0..2]);
-                }
-            }
-        } elsif ($t eq 'Polygon') {
-            for my $r (@$points) {
-                my $ring = Geo::OGR::Geometry->new('LinearRing');
-                $ring->SetCoordinateDimension(3) unless $flat;
-                $ring->Points($r);
-                $self->AddGeometryDirectly($ring);
-            }
-        } elsif ($t eq 'MultiPoint') {
-            for my $p (@$points) {
-                my $point = Geo::OGR::Geometry->new($flat ? 'Point' : 'Point25D');
-                $point->Points($p);
-                $self->AddGeometryDirectly($point);
-            }
-        } elsif ($t eq 'MultiLineString') {
-            for my $l (@$points) {
-                my $linestring = Geo::OGR::Geometry->new($flat ? 'LineString' : 'LineString25D');
-                $linestring->Points($l);
-                $self->AddGeometryDirectly($linestring);
-            }
-        } elsif ($t eq 'MultiPolygon') {
-            for my $p (@$points) {
-                my $polygon = Geo::OGR::Geometry->new($flat ? 'Polygon' : 'Polygon25D');
-                $polygon->Points($p);
-                $self->AddGeometryDirectly($polygon);
-            }
-        }
-    }
-    return unless defined wantarray;
-    $self->_GetPoints($flat);
-}
-
-sub _GetPoints {
-    my($self, $flat) = @_;
-    my @points;
-    my $n = $self->GetGeometryCount;
-    if ($n) {
-        for my $i (0..$n-1) {
-            push @points, $self->GetGeometryRef($i)->_GetPoints($flat);
-        }
-    } else {
-        $n = $self->GetPointCount;
-        if ($n == 1) {
-            push @points, $flat ? GetPoint_2D($self) : GetPoint_3D($self);
-        } else {
-            my $i;
-            if ($flat) {
-                for my $i (0..$n-1) {
-                    push @points, scalar GetPoint_2D($self, $i);
-                }
-            } else {
-                for my $i (0..$n-1) {
-                    push @points, scalar GetPoint_3D($self, $i);
-                }
-            }
-        }
-    }
-    return \@points;
-}
-
-sub ExportToWkb {
-    my($self, $bo) = @_;
-    if (defined $bo) {
-        confess "Unknown byte order: '$bo'." unless exists $BYTE_ORDER_STRING2INT{$bo};
-        $bo = $BYTE_ORDER_STRING2INT{$bo};
-    }
-    return _ExportToWkb($self, $bo);
-}
-
-sub ForceTo {
-    my $self = shift;
-    my $type = shift;
-    confess "Unknown geometry type: '$type'." unless exists $TYPE_STRING2INT{$type};
-    $type = $TYPE_STRING2INT{$type};
-    eval {
-        $self = Geo::OGR::ForceTo($self, $type, @_);
-    };
-    confess $@ if $@;
-    return $self;
-}
-
-sub ForceToLineString {
-    my $self = shift;
-    $self = Geo::OGR::ForceToLineString($self);
-    return $self;
-}
-
-sub ForceToMultiPoint {
-    my $self = shift;
-    $self = Geo::OGR::ForceToMultiPoint($self);
-    for my $g (@_) {
-        $self->AddGeometry($g);
-    }
-    return $self;
-}
-
-sub ForceToMultiLineString {
-    my $self = shift;
-    $self = Geo::OGR::ForceToMultiLineString($self);
-    for my $g (@_) {
-        $self->AddGeometry($g);
-    }
-    return $self;
-}
-
-sub ForceToMultiPolygon {
-    my $self = shift;
-    $self = Geo::OGR::ForceToMultiPolygon($self);
-    for my $g (@_) {
-        $self->AddGeometry($g);
-    }
-    return $self;
-}
-
-sub ForceToCollection {
-    my $self = Geo::OGR::Geometry->new(GeometryType => 'GeometryCollection');
-    for my $g (@_) {
-        $self->AddGeometry($g);
-    }
-    return $self;
-}
-*Collect = *ForceToCollection;
-
-sub Dissolve {
-    my $self = shift;
-    my @c;
-    my $n = $self->GetGeometryCount;
-    if ($n > 0) {
-        for my $i (0..$n-1) {
-            push @c, $self->GetGeometryRef($i)->Clone;
-        }
-    } else {
-        push @c, $self;
-    }
-    return @c;
-}
-*AsText = *ExportToWkt;
-*AsBinary = *ExportToWkb;
-*AsGML = *ExportToGML;
-*AsKML = *ExportToKML;
-*AsJSON = *ExportToJson;
-*BuildPolygonFromEdges = *Geo::OGR::BuildPolygonFromEdges;
-*ForceToPolygon = *Geo::OGR::ForceToPolygon;
-
-
-package Geo::OGR;
-use strict;
-use warnings;
-use Carp;
-
-sub GeometryType {
-    my($type_or_name) = @_;
-    if (defined $type_or_name) {
-        return $Geo::OGR::Geometry::TYPE_STRING2INT{$type_or_name} if
-            exists $Geo::OGR::Geometry::TYPE_STRING2INT{$type_or_name};
-        return $Geo::OGR::Geometry::TYPE_INT2STRING{$type_or_name} if
-            exists $Geo::OGR::Geometry::TYPE_INT2STRING{$type_or_name};
-        confess "Unknown geometry type: '$type_or_name'.";
-    } else {
-        return @Geo::OGR::Geometry::GEOMETRY_TYPES;
-    }
-}
-
-sub GeometryTypeModify {
-    my($type, $modifier) = @_;
-    confess "Unknown geometry type: '$type'." unless exists $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
-    $type = $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
-    return $Geo::OGR::Geometry::TYPE_INT2STRING{GT_Flatten($type)} if $modifier =~ /flat/i;
-    return $Geo::OGR::Geometry::TYPE_INT2STRING{GT_SetZ($type)} if $modifier =~ /z/i;
-    return $Geo::OGR::Geometry::TYPE_INT2STRING{GT_GetCollection($type)} if $modifier =~ /collection/i;
-    return $Geo::OGR::Geometry::TYPE_INT2STRING{GT_GetCurve($type)} if $modifier =~ /curve/i;
-    return $Geo::OGR::Geometry::TYPE_INT2STRING{GT_GetLinear($type)} if $modifier =~ /linear/i;
-    confess "Unknown geometry type modifier: '$modifier'.";
-}
-
-sub GeometryTypeTest {
-    my($type, $test, $type2) = @_;
-    confess "Unknown geometry type: '$type'." unless exists $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
-    $type = $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
-    if (defined $type2) {
-        confess "Unknown geometry type: '$type2'." unless exists $Geo::OGR::Geometry::TYPE_STRING2INT{$type2};
-        $type2 = $Geo::OGR::Geometry::TYPE_STRING2INT{$type2};
-    } else {
-        confess "Usage: GeometryTypeTest(type1, 'is_subclass_of', type2)." if $test =~ /subclass/i;
-    }
-    return GT_HasZ($type) if $test =~ /z/i;
-    return GT_IsSubClassOf($type, $type2) if $test =~ /subclass/i;
-    return GT_IsCurve($type) if $test =~ /curve/i;
-    return GT_IsSurface($type) if $test =~ /surface/i;
-    return GT_IsNonLinear($type) if $test =~ /linear/i;
-    confess "Unknown geometry type test: '$test'.";
-}
-
-sub RELEASE_PARENTS {
-}
-
-*ByteOrders = *Geo::OGR::Geometry::ByteOrders;
-*GeometryTypes = *Geo::OGR::Geometry::GeometryTypes;
-
-sub GetDriverNames {
-    my @names;
-    for my $i (0..GetDriverCount()-1) {
-        push @names, _GetDriver($i)->Name;
-    }
-    return @names;
-}
-
-sub Drivers {
-    my @drivers;
-    for my $i (0..GetDriverCount()-1) {
-        push @drivers, _GetDriver($i);
-    }
-    return @drivers;
-}
-
-sub GetDriver {
-    my($name) = @_;
-    $name = 0 unless defined $name;
-    my $driver;
-    $driver = _GetDriver($name) if $name =~ /^\d+$/; # is the name an index to driver list?
-    $driver = GetDriverByName("$name") unless $driver;
-    return $driver if $driver;
-    confess "Driver not found: '$name'. Maybe support for it was not built in?";
-}
-*Driver = *GetDriver;
-1;
diff --git a/swig/perl/lib/Geo/OSR.dox b/swig/perl/lib/Geo/OSR.dox
index 8f9b871..ade5306 100644
--- a/swig/perl/lib/Geo/OSR.dox
+++ b/swig/perl/lib/Geo/OSR.dox
@@ -1,49 +1,49 @@
 ## @class Geo::OSR
 # @brief Base class for projection related classes.
 
-## @cmethod @Projections()
+## @sub @Projections()
 # @return list of known projections.
 
-## @cmethod @Parameters()
+## @sub @Parameters()
 # @return list of known projection parameters.
 
-## @cmethod @LinearUnits()
+## @sub @LinearUnits()
 # @return list of known linear units.
 
-## @cmethod @AngularUnits()
+## @sub @AngularUnits()
 # @return list of known angular units.
 
-## @cmethod @Datums()
+## @sub @Datums()
 # @return list of known datums.
 
-## @cmethod $GetWellKnownGeogCSAsWKT($name)
+## @sub $GetWellKnownGeogCSAsWKT($name)
 # @brief Get well known geographic coordinate system as WKT
 # @param name a well known name
-# @return a WKT string
+# @return a WKT string.
 
-## @cmethod $GetUserInputAsWKT($name)
+## @sub $GetUserInputAsWKT($name)
 # @param name the user input
-# @return a WKT string
+# @return a WKT string.
 
-## @cmethod \@GetProjectionMethods()
+## @sub \@GetProjectionMethods()
 # @deprecated Use Geo::OSR::Projections.
 #
-# @return reference to an array of possible projection methods
+# @return reference to an array of possible projection methods.
 
-## @cmethod @GetProjectionMethodParameterList($projection)
+## @sub @GetProjectionMethodParameterList($projection)
 # @param projection one of Geo::OSR::Projections
-# @return (arrayref parameters, $projection_name)
+# @return a list (arrayref parameters, $projection_name).
 
-## @cmethod @GetProjectionMethodParamInfo($projection, $parameter)
+## @sub @GetProjectionMethodParamInfo($projection, $parameter)
 # @param projection one of Geo::OSR::Projections
 # @param parameter one of Geo::OSR::Parameters
-# @return ($user_friendly_name, $type, $default_value)
+# @return a list ($user_friendly_name, $type, $default_value).
 
 
 ## @class Geo::OSR::SpatialReference
 # @brief A spatial reference system.
 #
-# <a href="http://www.gdal.org/ogr/classOGRSpatialReference.html">Documentation
+# <a href="http://www.gdal.org/classOGRSpatialReference.html">Documentation
 # of the underlying C++ class at www.gdal.org</a>
 
 ## @ignore ImportFromEPSGA
@@ -76,7 +76,7 @@
 # - ERMapper: listref: [Projection, Datum, Units]
 # - MapInfoCS: MapInfo style co-ordinate system definition
 #
-# For more information, consult the import methods in <a href="http://www.gdal.org/ogr/classOGRSpatialReference.html">OGR documentation</a>.
+# For more information, consult the import methods in <a href="http://www.gdal.org/classOGRSpatialReference.html">OGR documentation</a>.
 #
 # @note ImportFrom* methods also exist but are not documented here.
 #
diff --git a/swig/perl/lib/Geo/OSR.pm b/swig/perl/lib/Geo/OSR.pm
deleted file mode 100644
index 058215f..0000000
--- a/swig/perl/lib/Geo/OSR.pm
+++ /dev/null
@@ -1,725 +0,0 @@
-# This file was automatically generated by SWIG (http://www.swig.org).
-# Version 2.0.12
-#
-# Do not make changes to this file unless you know what you are doing--modify
-# the SWIG interface file instead.
-
-package Geo::OSR;
-use base qw(Exporter);
-use base qw(DynaLoader);
-package Geo::OSRc;
-bootstrap Geo::OSR;
-package Geo::OSR;
- at EXPORT = qw();
-
-# ---------- BASE METHODS -------------
-
-package Geo::OSR;
-
-sub TIEHASH {
-    my ($classname,$obj) = @_;
-    return bless $obj, $classname;
-}
-
-sub CLEAR { }
-
-sub FIRSTKEY { }
-
-sub NEXTKEY { }
-
-sub FETCH {
-    my ($self,$field) = @_;
-    my $member_func = "swig_${field}_get";
-    $self->$member_func();
-}
-
-sub STORE {
-    my ($self,$field,$newval) = @_;
-    my $member_func = "swig_${field}_set";
-    $self->$member_func($newval);
-}
-
-sub this {
-    my $ptr = shift;
-    return tied(%$ptr);
-}
-
-
-# ------- FUNCTION WRAPPERS --------
-
-package Geo::OSR;
-
-*UseExceptions = *Geo::OSRc::UseExceptions;
-*DontUseExceptions = *Geo::OSRc::DontUseExceptions;
-*GetWellKnownGeogCSAsWKT = *Geo::OSRc::GetWellKnownGeogCSAsWKT;
-*GetUserInputAsWKT = *Geo::OSRc::GetUserInputAsWKT;
-*GetProjectionMethods = *Geo::OSRc::GetProjectionMethods;
-*GetProjectionMethodParameterList = *Geo::OSRc::GetProjectionMethodParameterList;
-*GetProjectionMethodParamInfo = *Geo::OSRc::GetProjectionMethodParamInfo;
-*CreateCoordinateTransformation = *Geo::OSRc::CreateCoordinateTransformation;
-
-############# Class : Geo::OSR::SpatialReference ##############
-
-package Geo::OSR::SpatialReference;
-use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
- at ISA = qw( Geo::OSR );
-%OWNER = ();
-%ITERATORS = ();
-use Carp;
-sub new {
-    my $pkg = shift;
-    my %param = @_;
-    my $self = Geo::OSRc::new_SpatialReference();
-    if ($param{WKT}) {
-        ImportFromWkt($self, $param{WKT});
-    } elsif ($param{Text}) {
-        ImportFromWkt($self, $param{Text});
-    } elsif ($param{Proj4}) {
-        ImportFromProj4($self, $param{Proj4});
-    } elsif ($param{ESRI}) {
-        ImportFromESRI($self, @{$param{ESRI}});
-    } elsif ($param{EPSG}) {
-        ImportFromEPSG($self, $param{EPSG});
-    } elsif ($param{EPSGA}) {
-        ImportFromEPSGA($self, $param{EPSGA});
-    } elsif ($param{PCI}) {
-        ImportFromPCI($self, @{$param{PCI}});
-    } elsif ($param{USGS}) {
-        ImportFromUSGS($self, @{$param{USGS}});
-    } elsif ($param{XML}) {
-        ImportFromXML($self, $param{XML});
-    } elsif ($param{GML}) {
-        ImportFromGML($self, $param{GML});
-    } elsif ($param{URL}) {
-        ImportFromUrl($self, $param{URL});
-    } elsif ($param{ERMapper}) {
-        ImportFromERM($self, @{$param{ERMapper}});
-    } elsif ($param{ERM}) {
-        ImportFromERM($self, @{$param{ERM}});
-    } elsif ($param{MICoordSys}) {
-        ImportFromMICoordSys($self, $param{MICoordSys});
-    } elsif ($param{MapInfoCS}) {
-        ImportFromMICoordSys($self, $param{MapInfoCS});
-    } elsif ($param{WGS}) {
-        eval {
-            SetWellKnownGeogCS($self, 'WGS'.$param{WGS});
-        };
-        confess "$@" if $@;
-    } else {
-        confess "Unrecognized/missing parameters: @_.";
-    }
-    bless $self, $pkg if defined $self;
-}
-
-sub DESTROY {
-    return unless $_[0]->isa('HASH');
-    my $self = tied(%{$_[0]});
-    return unless defined $self;
-    delete $ITERATORS{$self};
-    if (exists $OWNER{$self}) {
-        Geo::OSRc::delete_SpatialReference($self);
-        delete $OWNER{$self};
-    }
-}
-
-*IsSame = *Geo::OSRc::SpatialReference_IsSame;
-*IsSameGeogCS = *Geo::OSRc::SpatialReference_IsSameGeogCS;
-*IsSameVertCS = *Geo::OSRc::SpatialReference_IsSameVertCS;
-*IsGeographic = *Geo::OSRc::SpatialReference_IsGeographic;
-*IsProjected = *Geo::OSRc::SpatialReference_IsProjected;
-*IsCompound = *Geo::OSRc::SpatialReference_IsCompound;
-*IsGeocentric = *Geo::OSRc::SpatialReference_IsGeocentric;
-*IsLocal = *Geo::OSRc::SpatialReference_IsLocal;
-*IsVertical = *Geo::OSRc::SpatialReference_IsVertical;
-*EPSGTreatsAsLatLong = *Geo::OSRc::SpatialReference_EPSGTreatsAsLatLong;
-*EPSGTreatsAsNorthingEasting = *Geo::OSRc::SpatialReference_EPSGTreatsAsNorthingEasting;
-*SetAuthority = *Geo::OSRc::SpatialReference_SetAuthority;
-*GetAttrValue = *Geo::OSRc::SpatialReference_GetAttrValue;
-*SetAttrValue = *Geo::OSRc::SpatialReference_SetAttrValue;
-*SetAngularUnits = *Geo::OSRc::SpatialReference_SetAngularUnits;
-*GetAngularUnits = *Geo::OSRc::SpatialReference_GetAngularUnits;
-*SetTargetLinearUnits = *Geo::OSRc::SpatialReference_SetTargetLinearUnits;
-*SetLinearUnits = *Geo::OSRc::SpatialReference_SetLinearUnits;
-*SetLinearUnitsAndUpdateParameters = *Geo::OSRc::SpatialReference_SetLinearUnitsAndUpdateParameters;
-*GetLinearUnits = *Geo::OSRc::SpatialReference_GetLinearUnits;
-*GetLinearUnitsName = *Geo::OSRc::SpatialReference_GetLinearUnitsName;
-*GetAuthorityCode = *Geo::OSRc::SpatialReference_GetAuthorityCode;
-*GetAuthorityName = *Geo::OSRc::SpatialReference_GetAuthorityName;
-*SetUTM = *Geo::OSRc::SpatialReference_SetUTM;
-*_GetUTMZone = *Geo::OSRc::SpatialReference__GetUTMZone;
-*SetStatePlane = *Geo::OSRc::SpatialReference_SetStatePlane;
-*AutoIdentifyEPSG = *Geo::OSRc::SpatialReference_AutoIdentifyEPSG;
-*SetProjection = *Geo::OSRc::SpatialReference_SetProjection;
-*SetProjParm = *Geo::OSRc::SpatialReference_SetProjParm;
-*GetProjParm = *Geo::OSRc::SpatialReference_GetProjParm;
-*SetNormProjParm = *Geo::OSRc::SpatialReference_SetNormProjParm;
-*GetNormProjParm = *Geo::OSRc::SpatialReference_GetNormProjParm;
-*GetSemiMajor = *Geo::OSRc::SpatialReference_GetSemiMajor;
-*GetSemiMinor = *Geo::OSRc::SpatialReference_GetSemiMinor;
-*GetInvFlattening = *Geo::OSRc::SpatialReference_GetInvFlattening;
-*SetACEA = *Geo::OSRc::SpatialReference_SetACEA;
-*SetAE = *Geo::OSRc::SpatialReference_SetAE;
-*SetBonne = *Geo::OSRc::SpatialReference_SetBonne;
-*SetCEA = *Geo::OSRc::SpatialReference_SetCEA;
-*SetCS = *Geo::OSRc::SpatialReference_SetCS;
-*SetEC = *Geo::OSRc::SpatialReference_SetEC;
-*SetEckertIV = *Geo::OSRc::SpatialReference_SetEckertIV;
-*SetEckertVI = *Geo::OSRc::SpatialReference_SetEckertVI;
-*SetEquirectangular = *Geo::OSRc::SpatialReference_SetEquirectangular;
-*SetEquirectangular2 = *Geo::OSRc::SpatialReference_SetEquirectangular2;
-*SetGaussSchreiberTMercator = *Geo::OSRc::SpatialReference_SetGaussSchreiberTMercator;
-*SetGS = *Geo::OSRc::SpatialReference_SetGS;
-*SetGH = *Geo::OSRc::SpatialReference_SetGH;
-*SetIGH = *Geo::OSRc::SpatialReference_SetIGH;
-*SetGEOS = *Geo::OSRc::SpatialReference_SetGEOS;
-*SetGnomonic = *Geo::OSRc::SpatialReference_SetGnomonic;
-*SetHOM = *Geo::OSRc::SpatialReference_SetHOM;
-*SetHOM2PNO = *Geo::OSRc::SpatialReference_SetHOM2PNO;
-*SetKrovak = *Geo::OSRc::SpatialReference_SetKrovak;
-*SetLAEA = *Geo::OSRc::SpatialReference_SetLAEA;
-*SetLCC = *Geo::OSRc::SpatialReference_SetLCC;
-*SetLCC1SP = *Geo::OSRc::SpatialReference_SetLCC1SP;
-*SetLCCB = *Geo::OSRc::SpatialReference_SetLCCB;
-*SetMC = *Geo::OSRc::SpatialReference_SetMC;
-*SetMercator = *Geo::OSRc::SpatialReference_SetMercator;
-*SetMollweide = *Geo::OSRc::SpatialReference_SetMollweide;
-*SetNZMG = *Geo::OSRc::SpatialReference_SetNZMG;
-*SetOS = *Geo::OSRc::SpatialReference_SetOS;
-*SetOrthographic = *Geo::OSRc::SpatialReference_SetOrthographic;
-*SetPolyconic = *Geo::OSRc::SpatialReference_SetPolyconic;
-*SetPS = *Geo::OSRc::SpatialReference_SetPS;
-*SetRobinson = *Geo::OSRc::SpatialReference_SetRobinson;
-*SetSinusoidal = *Geo::OSRc::SpatialReference_SetSinusoidal;
-*SetStereographic = *Geo::OSRc::SpatialReference_SetStereographic;
-*SetSOC = *Geo::OSRc::SpatialReference_SetSOC;
-*SetTM = *Geo::OSRc::SpatialReference_SetTM;
-*SetTMVariant = *Geo::OSRc::SpatialReference_SetTMVariant;
-*SetTMG = *Geo::OSRc::SpatialReference_SetTMG;
-*SetTMSO = *Geo::OSRc::SpatialReference_SetTMSO;
-*SetVDG = *Geo::OSRc::SpatialReference_SetVDG;
-*SetWellKnownGeogCS = *Geo::OSRc::SpatialReference_SetWellKnownGeogCS;
-*SetFromUserInput = *Geo::OSRc::SpatialReference_SetFromUserInput;
-*CopyGeogCSFrom = *Geo::OSRc::SpatialReference_CopyGeogCSFrom;
-*SetTOWGS84 = *Geo::OSRc::SpatialReference_SetTOWGS84;
-*GetTOWGS84 = *Geo::OSRc::SpatialReference_GetTOWGS84;
-*SetLocalCS = *Geo::OSRc::SpatialReference_SetLocalCS;
-*SetGeogCS = *Geo::OSRc::SpatialReference_SetGeogCS;
-*SetProjCS = *Geo::OSRc::SpatialReference_SetProjCS;
-*SetGeocCS = *Geo::OSRc::SpatialReference_SetGeocCS;
-*SetVertCS = *Geo::OSRc::SpatialReference_SetVertCS;
-*SetCompoundCS = *Geo::OSRc::SpatialReference_SetCompoundCS;
-*ImportFromWkt = *Geo::OSRc::SpatialReference_ImportFromWkt;
-*ImportFromProj4 = *Geo::OSRc::SpatialReference_ImportFromProj4;
-*ImportFromUrl = *Geo::OSRc::SpatialReference_ImportFromUrl;
-*ImportFromESRI = *Geo::OSRc::SpatialReference_ImportFromESRI;
-*ImportFromEPSG = *Geo::OSRc::SpatialReference_ImportFromEPSG;
-*ImportFromEPSGA = *Geo::OSRc::SpatialReference_ImportFromEPSGA;
-*ImportFromPCI = *Geo::OSRc::SpatialReference_ImportFromPCI;
-*ImportFromUSGS = *Geo::OSRc::SpatialReference_ImportFromUSGS;
-*ImportFromXML = *Geo::OSRc::SpatialReference_ImportFromXML;
-*ImportFromERM = *Geo::OSRc::SpatialReference_ImportFromERM;
-*ImportFromMICoordSys = *Geo::OSRc::SpatialReference_ImportFromMICoordSys;
-*ImportFromOzi = *Geo::OSRc::SpatialReference_ImportFromOzi;
-*ExportToWkt = *Geo::OSRc::SpatialReference_ExportToWkt;
-*ExportToPrettyWkt = *Geo::OSRc::SpatialReference_ExportToPrettyWkt;
-*ExportToProj4 = *Geo::OSRc::SpatialReference_ExportToProj4;
-*ExportToPCI = *Geo::OSRc::SpatialReference_ExportToPCI;
-*ExportToUSGS = *Geo::OSRc::SpatialReference_ExportToUSGS;
-*ExportToXML = *Geo::OSRc::SpatialReference_ExportToXML;
-*ExportToMICoordSys = *Geo::OSRc::SpatialReference_ExportToMICoordSys;
-*CloneGeogCS = *Geo::OSRc::SpatialReference_CloneGeogCS;
-*Clone = *Geo::OSRc::SpatialReference_Clone;
-*Validate = *Geo::OSRc::SpatialReference_Validate;
-*StripCTParms = *Geo::OSRc::SpatialReference_StripCTParms;
-*FixupOrdering = *Geo::OSRc::SpatialReference_FixupOrdering;
-*Fixup = *Geo::OSRc::SpatialReference_Fixup;
-*MorphToESRI = *Geo::OSRc::SpatialReference_MorphToESRI;
-*MorphFromESRI = *Geo::OSRc::SpatialReference_MorphFromESRI;
-sub DISOWN {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    delete $OWNER{$ptr};
-}
-
-sub ACQUIRE {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    $OWNER{$ptr} = 1;
-}
-
-
-############# Class : Geo::OSR::CoordinateTransformation ##############
-
-package Geo::OSR::CoordinateTransformation;
-use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
- at ISA = qw( Geo::OSR );
-%OWNER = ();
-%ITERATORS = ();
-sub new {
-    my $pkg = shift;
-    my $self = Geo::OSRc::new_CoordinateTransformation(@_);
-    bless $self, $pkg if defined($self);
-}
-
-sub DESTROY {
-    return unless $_[0]->isa('HASH');
-    my $self = tied(%{$_[0]});
-    return unless defined $self;
-    delete $ITERATORS{$self};
-    if (exists $OWNER{$self}) {
-        Geo::OSRc::delete_CoordinateTransformation($self);
-        delete $OWNER{$self};
-    }
-}
-
-*TransformPoint = *Geo::OSRc::CoordinateTransformation_TransformPoint;
-*_TransformPoints = *Geo::OSRc::CoordinateTransformation__TransformPoints;
-sub DISOWN {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    delete $OWNER{$ptr};
-}
-
-sub ACQUIRE {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    $OWNER{$ptr} = 1;
-}
-
-
-# ------- VARIABLE STUBS --------
-
-package Geo::OSR;
-
-*SRS_WKT_WGS84 = *Geo::OSRc::SRS_WKT_WGS84;
-*SRS_PT_ALBERS_CONIC_EQUAL_AREA = *Geo::OSRc::SRS_PT_ALBERS_CONIC_EQUAL_AREA;
-*SRS_PT_AZIMUTHAL_EQUIDISTANT = *Geo::OSRc::SRS_PT_AZIMUTHAL_EQUIDISTANT;
-*SRS_PT_CASSINI_SOLDNER = *Geo::OSRc::SRS_PT_CASSINI_SOLDNER;
-*SRS_PT_CYLINDRICAL_EQUAL_AREA = *Geo::OSRc::SRS_PT_CYLINDRICAL_EQUAL_AREA;
-*SRS_PT_BONNE = *Geo::OSRc::SRS_PT_BONNE;
-*SRS_PT_ECKERT_I = *Geo::OSRc::SRS_PT_ECKERT_I;
-*SRS_PT_ECKERT_II = *Geo::OSRc::SRS_PT_ECKERT_II;
-*SRS_PT_ECKERT_III = *Geo::OSRc::SRS_PT_ECKERT_III;
-*SRS_PT_ECKERT_IV = *Geo::OSRc::SRS_PT_ECKERT_IV;
-*SRS_PT_ECKERT_V = *Geo::OSRc::SRS_PT_ECKERT_V;
-*SRS_PT_ECKERT_VI = *Geo::OSRc::SRS_PT_ECKERT_VI;
-*SRS_PT_EQUIDISTANT_CONIC = *Geo::OSRc::SRS_PT_EQUIDISTANT_CONIC;
-*SRS_PT_EQUIRECTANGULAR = *Geo::OSRc::SRS_PT_EQUIRECTANGULAR;
-*SRS_PT_GALL_STEREOGRAPHIC = *Geo::OSRc::SRS_PT_GALL_STEREOGRAPHIC;
-*SRS_PT_GAUSSSCHREIBERTMERCATOR = *Geo::OSRc::SRS_PT_GAUSSSCHREIBERTMERCATOR;
-*SRS_PT_GEOSTATIONARY_SATELLITE = *Geo::OSRc::SRS_PT_GEOSTATIONARY_SATELLITE;
-*SRS_PT_GOODE_HOMOLOSINE = *Geo::OSRc::SRS_PT_GOODE_HOMOLOSINE;
-*SRS_PT_IGH = *Geo::OSRc::SRS_PT_IGH;
-*SRS_PT_GNOMONIC = *Geo::OSRc::SRS_PT_GNOMONIC;
-*SRS_PT_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER = *Geo::OSRc::SRS_PT_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER;
-*SRS_PT_HOTINE_OBLIQUE_MERCATOR = *Geo::OSRc::SRS_PT_HOTINE_OBLIQUE_MERCATOR;
-*SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN = *Geo::OSRc::SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN;
-*SRS_PT_LABORDE_OBLIQUE_MERCATOR = *Geo::OSRc::SRS_PT_LABORDE_OBLIQUE_MERCATOR;
-*SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP = *Geo::OSRc::SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP;
-*SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP = *Geo::OSRc::SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP;
-*SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM = *Geo::OSRc::SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM;
-*SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA = *Geo::OSRc::SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA;
-*SRS_PT_MERCATOR_1SP = *Geo::OSRc::SRS_PT_MERCATOR_1SP;
-*SRS_PT_MERCATOR_2SP = *Geo::OSRc::SRS_PT_MERCATOR_2SP;
-*SRS_PT_MERCATOR_AUXILIARY_SPHERE = *Geo::OSRc::SRS_PT_MERCATOR_AUXILIARY_SPHERE;
-*SRS_PT_MILLER_CYLINDRICAL = *Geo::OSRc::SRS_PT_MILLER_CYLINDRICAL;
-*SRS_PT_MOLLWEIDE = *Geo::OSRc::SRS_PT_MOLLWEIDE;
-*SRS_PT_NEW_ZEALAND_MAP_GRID = *Geo::OSRc::SRS_PT_NEW_ZEALAND_MAP_GRID;
-*SRS_PT_OBLIQUE_STEREOGRAPHIC = *Geo::OSRc::SRS_PT_OBLIQUE_STEREOGRAPHIC;
-*SRS_PT_ORTHOGRAPHIC = *Geo::OSRc::SRS_PT_ORTHOGRAPHIC;
-*SRS_PT_POLAR_STEREOGRAPHIC = *Geo::OSRc::SRS_PT_POLAR_STEREOGRAPHIC;
-*SRS_PT_POLYCONIC = *Geo::OSRc::SRS_PT_POLYCONIC;
-*SRS_PT_ROBINSON = *Geo::OSRc::SRS_PT_ROBINSON;
-*SRS_PT_SINUSOIDAL = *Geo::OSRc::SRS_PT_SINUSOIDAL;
-*SRS_PT_STEREOGRAPHIC = *Geo::OSRc::SRS_PT_STEREOGRAPHIC;
-*SRS_PT_SWISS_OBLIQUE_CYLINDRICAL = *Geo::OSRc::SRS_PT_SWISS_OBLIQUE_CYLINDRICAL;
-*SRS_PT_TRANSVERSE_MERCATOR = *Geo::OSRc::SRS_PT_TRANSVERSE_MERCATOR;
-*SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED = *Geo::OSRc::SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED;
-*SRS_PT_TRANSVERSE_MERCATOR_MI_21 = *Geo::OSRc::SRS_PT_TRANSVERSE_MERCATOR_MI_21;
-*SRS_PT_TRANSVERSE_MERCATOR_MI_22 = *Geo::OSRc::SRS_PT_TRANSVERSE_MERCATOR_MI_22;
-*SRS_PT_TRANSVERSE_MERCATOR_MI_23 = *Geo::OSRc::SRS_PT_TRANSVERSE_MERCATOR_MI_23;
-*SRS_PT_TRANSVERSE_MERCATOR_MI_24 = *Geo::OSRc::SRS_PT_TRANSVERSE_MERCATOR_MI_24;
-*SRS_PT_TRANSVERSE_MERCATOR_MI_25 = *Geo::OSRc::SRS_PT_TRANSVERSE_MERCATOR_MI_25;
-*SRS_PT_TUNISIA_MINING_GRID = *Geo::OSRc::SRS_PT_TUNISIA_MINING_GRID;
-*SRS_PT_TWO_POINT_EQUIDISTANT = *Geo::OSRc::SRS_PT_TWO_POINT_EQUIDISTANT;
-*SRS_PT_VANDERGRINTEN = *Geo::OSRc::SRS_PT_VANDERGRINTEN;
-*SRS_PT_KROVAK = *Geo::OSRc::SRS_PT_KROVAK;
-*SRS_PT_IMW_POLYCONIC = *Geo::OSRc::SRS_PT_IMW_POLYCONIC;
-*SRS_PT_WAGNER_I = *Geo::OSRc::SRS_PT_WAGNER_I;
-*SRS_PT_WAGNER_II = *Geo::OSRc::SRS_PT_WAGNER_II;
-*SRS_PT_WAGNER_III = *Geo::OSRc::SRS_PT_WAGNER_III;
-*SRS_PT_WAGNER_IV = *Geo::OSRc::SRS_PT_WAGNER_IV;
-*SRS_PT_WAGNER_V = *Geo::OSRc::SRS_PT_WAGNER_V;
-*SRS_PT_WAGNER_VI = *Geo::OSRc::SRS_PT_WAGNER_VI;
-*SRS_PT_WAGNER_VII = *Geo::OSRc::SRS_PT_WAGNER_VII;
-*SRS_PT_QSC = *Geo::OSRc::SRS_PT_QSC;
-*SRS_PT_AITOFF = *Geo::OSRc::SRS_PT_AITOFF;
-*SRS_PT_WINKEL_I = *Geo::OSRc::SRS_PT_WINKEL_I;
-*SRS_PT_WINKEL_II = *Geo::OSRc::SRS_PT_WINKEL_II;
-*SRS_PT_WINKEL_TRIPEL = *Geo::OSRc::SRS_PT_WINKEL_TRIPEL;
-*SRS_PT_CRASTER_PARABOLIC = *Geo::OSRc::SRS_PT_CRASTER_PARABOLIC;
-*SRS_PT_LOXIMUTHAL = *Geo::OSRc::SRS_PT_LOXIMUTHAL;
-*SRS_PT_QUARTIC_AUTHALIC = *Geo::OSRc::SRS_PT_QUARTIC_AUTHALIC;
-*SRS_PP_CENTRAL_MERIDIAN = *Geo::OSRc::SRS_PP_CENTRAL_MERIDIAN;
-*SRS_PP_SCALE_FACTOR = *Geo::OSRc::SRS_PP_SCALE_FACTOR;
-*SRS_PP_STANDARD_PARALLEL_1 = *Geo::OSRc::SRS_PP_STANDARD_PARALLEL_1;
-*SRS_PP_STANDARD_PARALLEL_2 = *Geo::OSRc::SRS_PP_STANDARD_PARALLEL_2;
-*SRS_PP_PSEUDO_STD_PARALLEL_1 = *Geo::OSRc::SRS_PP_PSEUDO_STD_PARALLEL_1;
-*SRS_PP_LONGITUDE_OF_CENTER = *Geo::OSRc::SRS_PP_LONGITUDE_OF_CENTER;
-*SRS_PP_LATITUDE_OF_CENTER = *Geo::OSRc::SRS_PP_LATITUDE_OF_CENTER;
-*SRS_PP_LONGITUDE_OF_ORIGIN = *Geo::OSRc::SRS_PP_LONGITUDE_OF_ORIGIN;
-*SRS_PP_LATITUDE_OF_ORIGIN = *Geo::OSRc::SRS_PP_LATITUDE_OF_ORIGIN;
-*SRS_PP_FALSE_EASTING = *Geo::OSRc::SRS_PP_FALSE_EASTING;
-*SRS_PP_FALSE_NORTHING = *Geo::OSRc::SRS_PP_FALSE_NORTHING;
-*SRS_PP_AZIMUTH = *Geo::OSRc::SRS_PP_AZIMUTH;
-*SRS_PP_LONGITUDE_OF_POINT_1 = *Geo::OSRc::SRS_PP_LONGITUDE_OF_POINT_1;
-*SRS_PP_LATITUDE_OF_POINT_1 = *Geo::OSRc::SRS_PP_LATITUDE_OF_POINT_1;
-*SRS_PP_LONGITUDE_OF_POINT_2 = *Geo::OSRc::SRS_PP_LONGITUDE_OF_POINT_2;
-*SRS_PP_LATITUDE_OF_POINT_2 = *Geo::OSRc::SRS_PP_LATITUDE_OF_POINT_2;
-*SRS_PP_LONGITUDE_OF_POINT_3 = *Geo::OSRc::SRS_PP_LONGITUDE_OF_POINT_3;
-*SRS_PP_LATITUDE_OF_POINT_3 = *Geo::OSRc::SRS_PP_LATITUDE_OF_POINT_3;
-*SRS_PP_RECTIFIED_GRID_ANGLE = *Geo::OSRc::SRS_PP_RECTIFIED_GRID_ANGLE;
-*SRS_PP_LANDSAT_NUMBER = *Geo::OSRc::SRS_PP_LANDSAT_NUMBER;
-*SRS_PP_PATH_NUMBER = *Geo::OSRc::SRS_PP_PATH_NUMBER;
-*SRS_PP_PERSPECTIVE_POINT_HEIGHT = *Geo::OSRc::SRS_PP_PERSPECTIVE_POINT_HEIGHT;
-*SRS_PP_SATELLITE_HEIGHT = *Geo::OSRc::SRS_PP_SATELLITE_HEIGHT;
-*SRS_PP_FIPSZONE = *Geo::OSRc::SRS_PP_FIPSZONE;
-*SRS_PP_ZONE = *Geo::OSRc::SRS_PP_ZONE;
-*SRS_PP_LATITUDE_OF_1ST_POINT = *Geo::OSRc::SRS_PP_LATITUDE_OF_1ST_POINT;
-*SRS_PP_LONGITUDE_OF_1ST_POINT = *Geo::OSRc::SRS_PP_LONGITUDE_OF_1ST_POINT;
-*SRS_PP_LATITUDE_OF_2ND_POINT = *Geo::OSRc::SRS_PP_LATITUDE_OF_2ND_POINT;
-*SRS_PP_LONGITUDE_OF_2ND_POINT = *Geo::OSRc::SRS_PP_LONGITUDE_OF_2ND_POINT;
-*SRS_UL_METER = *Geo::OSRc::SRS_UL_METER;
-*SRS_UL_FOOT = *Geo::OSRc::SRS_UL_FOOT;
-*SRS_UL_FOOT_CONV = *Geo::OSRc::SRS_UL_FOOT_CONV;
-*SRS_UL_US_FOOT = *Geo::OSRc::SRS_UL_US_FOOT;
-*SRS_UL_US_FOOT_CONV = *Geo::OSRc::SRS_UL_US_FOOT_CONV;
-*SRS_UL_NAUTICAL_MILE = *Geo::OSRc::SRS_UL_NAUTICAL_MILE;
-*SRS_UL_NAUTICAL_MILE_CONV = *Geo::OSRc::SRS_UL_NAUTICAL_MILE_CONV;
-*SRS_UL_LINK = *Geo::OSRc::SRS_UL_LINK;
-*SRS_UL_LINK_CONV = *Geo::OSRc::SRS_UL_LINK_CONV;
-*SRS_UL_CHAIN = *Geo::OSRc::SRS_UL_CHAIN;
-*SRS_UL_CHAIN_CONV = *Geo::OSRc::SRS_UL_CHAIN_CONV;
-*SRS_UL_ROD = *Geo::OSRc::SRS_UL_ROD;
-*SRS_UL_ROD_CONV = *Geo::OSRc::SRS_UL_ROD_CONV;
-*SRS_UL_LINK_Clarke = *Geo::OSRc::SRS_UL_LINK_Clarke;
-*SRS_UL_LINK_Clarke_CONV = *Geo::OSRc::SRS_UL_LINK_Clarke_CONV;
-*SRS_UL_KILOMETER = *Geo::OSRc::SRS_UL_KILOMETER;
-*SRS_UL_KILOMETER_CONV = *Geo::OSRc::SRS_UL_KILOMETER_CONV;
-*SRS_UL_DECIMETER = *Geo::OSRc::SRS_UL_DECIMETER;
-*SRS_UL_DECIMETER_CONV = *Geo::OSRc::SRS_UL_DECIMETER_CONV;
-*SRS_UL_CENTIMETER = *Geo::OSRc::SRS_UL_CENTIMETER;
-*SRS_UL_CENTIMETER_CONV = *Geo::OSRc::SRS_UL_CENTIMETER_CONV;
-*SRS_UL_MILLIMETER = *Geo::OSRc::SRS_UL_MILLIMETER;
-*SRS_UL_MILLIMETER_CONV = *Geo::OSRc::SRS_UL_MILLIMETER_CONV;
-*SRS_UL_INTL_NAUT_MILE = *Geo::OSRc::SRS_UL_INTL_NAUT_MILE;
-*SRS_UL_INTL_NAUT_MILE_CONV = *Geo::OSRc::SRS_UL_INTL_NAUT_MILE_CONV;
-*SRS_UL_INTL_INCH = *Geo::OSRc::SRS_UL_INTL_INCH;
-*SRS_UL_INTL_INCH_CONV = *Geo::OSRc::SRS_UL_INTL_INCH_CONV;
-*SRS_UL_INTL_FOOT = *Geo::OSRc::SRS_UL_INTL_FOOT;
-*SRS_UL_INTL_FOOT_CONV = *Geo::OSRc::SRS_UL_INTL_FOOT_CONV;
-*SRS_UL_INTL_YARD = *Geo::OSRc::SRS_UL_INTL_YARD;
-*SRS_UL_INTL_YARD_CONV = *Geo::OSRc::SRS_UL_INTL_YARD_CONV;
-*SRS_UL_INTL_STAT_MILE = *Geo::OSRc::SRS_UL_INTL_STAT_MILE;
-*SRS_UL_INTL_STAT_MILE_CONV = *Geo::OSRc::SRS_UL_INTL_STAT_MILE_CONV;
-*SRS_UL_INTL_FATHOM = *Geo::OSRc::SRS_UL_INTL_FATHOM;
-*SRS_UL_INTL_FATHOM_CONV = *Geo::OSRc::SRS_UL_INTL_FATHOM_CONV;
-*SRS_UL_INTL_CHAIN = *Geo::OSRc::SRS_UL_INTL_CHAIN;
-*SRS_UL_INTL_CHAIN_CONV = *Geo::OSRc::SRS_UL_INTL_CHAIN_CONV;
-*SRS_UL_INTL_LINK = *Geo::OSRc::SRS_UL_INTL_LINK;
-*SRS_UL_INTL_LINK_CONV = *Geo::OSRc::SRS_UL_INTL_LINK_CONV;
-*SRS_UL_US_INCH = *Geo::OSRc::SRS_UL_US_INCH;
-*SRS_UL_US_INCH_CONV = *Geo::OSRc::SRS_UL_US_INCH_CONV;
-*SRS_UL_US_YARD = *Geo::OSRc::SRS_UL_US_YARD;
-*SRS_UL_US_YARD_CONV = *Geo::OSRc::SRS_UL_US_YARD_CONV;
-*SRS_UL_US_CHAIN = *Geo::OSRc::SRS_UL_US_CHAIN;
-*SRS_UL_US_CHAIN_CONV = *Geo::OSRc::SRS_UL_US_CHAIN_CONV;
-*SRS_UL_US_STAT_MILE = *Geo::OSRc::SRS_UL_US_STAT_MILE;
-*SRS_UL_US_STAT_MILE_CONV = *Geo::OSRc::SRS_UL_US_STAT_MILE_CONV;
-*SRS_UL_INDIAN_YARD = *Geo::OSRc::SRS_UL_INDIAN_YARD;
-*SRS_UL_INDIAN_YARD_CONV = *Geo::OSRc::SRS_UL_INDIAN_YARD_CONV;
-*SRS_UL_INDIAN_FOOT = *Geo::OSRc::SRS_UL_INDIAN_FOOT;
-*SRS_UL_INDIAN_FOOT_CONV = *Geo::OSRc::SRS_UL_INDIAN_FOOT_CONV;
-*SRS_UL_INDIAN_CHAIN = *Geo::OSRc::SRS_UL_INDIAN_CHAIN;
-*SRS_UL_INDIAN_CHAIN_CONV = *Geo::OSRc::SRS_UL_INDIAN_CHAIN_CONV;
-*SRS_UA_DEGREE = *Geo::OSRc::SRS_UA_DEGREE;
-*SRS_UA_DEGREE_CONV = *Geo::OSRc::SRS_UA_DEGREE_CONV;
-*SRS_UA_RADIAN = *Geo::OSRc::SRS_UA_RADIAN;
-*SRS_PM_GREENWICH = *Geo::OSRc::SRS_PM_GREENWICH;
-*SRS_DN_NAD27 = *Geo::OSRc::SRS_DN_NAD27;
-*SRS_DN_NAD83 = *Geo::OSRc::SRS_DN_NAD83;
-*SRS_DN_WGS72 = *Geo::OSRc::SRS_DN_WGS72;
-*SRS_DN_WGS84 = *Geo::OSRc::SRS_DN_WGS84;
-*SRS_WGS84_SEMIMAJOR = *Geo::OSRc::SRS_WGS84_SEMIMAJOR;
-*SRS_WGS84_INVFLATTENING = *Geo::OSRc::SRS_WGS84_INVFLATTENING;
-
-
-package Geo::OSR;
-use strict;
-use warnings;
-
-use vars qw /%PROJECTIONS %PARAMETERS %LINEAR_UNITS %ANGULAR_UNITS %DATUMS/;
-
-for (keys %Geo::OSR::) {
-    if (/^SRS_PT_(\w+)/) {
-        my $p = eval '$Geo::OSR::'.$_;
-        $PROJECTIONS{$p} = 1;
-    }
-    elsif (/^SRS_PP_(\w+)/) {
-        my $p = eval '$Geo::OSR::'.$_;
-        $PARAMETERS{$p} = 1;
-    }
-    elsif (/^SRS_UL_(\w+)/) {
-        my $p = eval '$Geo::OSR::'.$_;
-        $LINEAR_UNITS{$p} = 1;
-    }
-    elsif (/^SRS_UA_(\w+)/) {
-        my $p = eval '$Geo::OSR::'.$_;
-        $ANGULAR_UNITS{$p} = 1;
-    }
-    elsif (/^SRS_DN_(\w+)/) {
-        my $p = eval '$Geo::OSR::'.$_;
-        $DATUMS{$p} = 1;
-    }
-}
-
-sub Projections {
-    return keys %PROJECTIONS;
-}
-
-sub Parameters {
-    return keys %PARAMETERS;
-}
-
-sub LinearUnits {
-    return keys %LINEAR_UNITS;
-}
-
-sub AngularUnits {
-    return keys %ANGULAR_UNITS;
-}
-
-sub Datums {
-    return keys %DATUMS;
-}
-
-sub RELEASE_PARENTS {
-}
-
-
-package Geo::OSR::SpatialReference;
-use strict;
-use warnings;
-use Carp;
-
-sub Export {
-    my $self = shift;
-    my $format;
-    $format = pop if @_ == 1;
-    my %params = @_;
-    $format = $params{to} unless $format;
-    $format = $params{format} unless $format;
-    $format = $params{as} unless $format;
-    if ($format eq 'WKT' or $format eq 'Text') {
-        return ExportToWkt($self);
-    } elsif ($format eq 'PrettyWKT') {
-        my $simplify = exists $params{simplify} ? $params{simplify} : 0;
-        return ExportToPrettyWkt($self, $simplify);
-    } elsif ($format eq 'Proj4') {
-        return ExportToProj4($self);
-    } elsif ($format eq 'PCI') {            
-        return ExportToPCI($self);
-    } elsif ($format eq 'USGS') {
-        return ExportToUSGS($self);
-    } elsif ($format eq 'GML' or $format eq 'XML') {
-        my $dialect = exists $params{dialect} ? $params{dialect} : '';
-        return ExportToXML($self, $dialect);
-    } elsif ($format eq 'MICoordSys' or $format eq 'MapInfoCS') {
-        return ExportToMICoordSys();
-    } else {
-        confess "Unrecognized export format.";
-    }
-}
-*AsText = *ExportToWkt;
-*As = *Export;
-
-sub Set {
-    my($self, %params) = @_;
-    if (exists $params{Authority} and exists $params{TargetKey} and exists $params{Node} and exists $params{Code}) {
-        SetAuthority($self, $params{TargetKey}, $params{Authority}, $params{Code});
-    } elsif (exists $params{Node} and exists $params{Value}) {
-        SetAttrValue($self, $params{Node}, $params{Value});
-    } elsif (exists $params{AngularUnits} and exists $params{Value}) {
-        SetAngularUnits($self, $params{AngularUnits}, $params{Value});
-    } elsif (exists $params{LinearUnits} and exists $params{Node} and exists $params{Value}) {
-        SetTargetLinearUnits($self, $params{Node}, $params{LinearUnits}, $params{Value});
-    } elsif (exists $params{LinearUnits} and exists $params{Value}) {
-        SetLinearUnitsAndUpdateParameters($self, $params{LinearUnits}, $params{Value});
-    } elsif ($params{Parameter} and exists $params{Value}) {
-        croak "Unknown projection parameter '$params{Parameter}'." unless exists $Geo::OSR::PARAMETERS{$params{Parameter}};
-        $params{Normalized} ?
-            SetNormProjParm($self, $params{Parameter}, $params{Value}) :
-            SetProjParm($self, $params{Parameter}, $params{Value});
-    } elsif ($params{Name}) {
-        SetWellKnownGeogCS($self, $params{Name});
-    } elsif ($params{GuessFrom}) {
-        SetFromUserInput($self, $params{GuessFrom});
-    } elsif ($params{LOCAL_CS}) {
-        SetLocalCS($self, $params{LOCAL_CS});
-    } elsif ($params{GeocentricCS}) {
-        SetGeocCS($self, $params{GeocentricCS});
-    } elsif ($params{VerticalCS} and $params{Datum}) {
-        my $type = $params{VertDatumType} || 2005;
-        SetVertCS($self, $params{VerticalCS}, $params{Datum}, $type);
-    } elsif ($params{CoordinateSystem}) {
-        my @parameters = ();
-        @parameters = @{$params{Parameters}} if ref($params{Parameters});
-        if ($params{CoordinateSystem} eq 'State Plane' and exists $params{Zone}) {
-            my $NAD83 = exists $params{NAD83} ? $params{NAD83} : 1;
-            my $name = exists $params{UnitName} ? $params{UnitName} : undef;
-            my $c = exists $params{UnitConversionFactor} ? $params{UnitConversionFactor} : 0.0;
-            SetStatePlane($self, $params{Zone}, $NAD83, $name, $c);
-        } elsif ($params{CoordinateSystem} eq 'UTM' and exists $params{Zone} and exists $params{North}) {
-            my $north = exists $params{North} ? $params{North} : 1;
-            SetUTM($self, $params{Zone}, $north);
-        } elsif ($params{CoordinateSystem} eq 'WGS') {
-            SetTOWGS84($self, @parameters);
-        } elsif ($params{CoordinateSystem} and $params{Datum} and $params{Spheroid}) {
-            SetGeogCS($self, $params{CoordinateSystem}, $params{Datum}, $params{Spheroid}, @parameters);
-        } elsif ($params{CoordinateSystem} and $params{HorizontalCS} and $params{VerticalCS}) {
-            SetCompoundCS($self, $params{CoordinateSystem}, $params{HorizontalCS}, $params{VerticalCS});
-        } else {
-            SetProjCS($self, $params{CoordinateSystem});
-        }
-    } elsif ($params{Projection}) {
-        confess "Unknown projection." unless exists $Geo::OSR::PROJECTIONS{$params{Projection}};
-        my @parameters = ();
-        @parameters = @{$params{Parameters}} if ref($params{Parameters});
-        if ($params{Projection} eq 'Albers_Conic_Equal_Area') {
-            SetACEA($self, @parameters);
-        } elsif ($params{Projection} eq 'Azimuthal_Equidistant') {
-            SetAE($self, @parameters);
-        } elsif ($params{Projection} eq 'Bonne') {
-            SetBonne($self, @parameters);
-        } elsif ($params{Projection} eq 'Cylindrical_Equal_Area') {
-            SetCEA($self, @parameters);
-        } elsif ($params{Projection} eq 'Cassini_Soldner') {
-            SetCS($self, @parameters);
-        } elsif ($params{Projection} eq 'Equidistant_Conic') {
-            SetEC($self, @parameters);
-            # Eckert_I, Eckert_II, Eckert_III, Eckert_V ?
-        } elsif ($params{Projection} eq 'Eckert_IV') {
-            SetEckertIV($self, @parameters);
-        } elsif ($params{Projection} eq 'Eckert_VI') {
-            SetEckertVI($self, @parameters);
-        } elsif ($params{Projection} eq 'Equirectangular') {
-            @parameters == 4 ?
-                SetEquirectangular($self, @parameters) :
-                SetEquirectangular2($self, @parameters);
-        } elsif ($params{Projection} eq 'Gauss_Schreiber_Transverse_Mercator') {
-            SetGaussSchreiberTMercator($self, @parameters);
-        } elsif ($params{Projection} eq 'Gall_Stereographic') {
-            SetGS($self, @parameters);
-        } elsif ($params{Projection} eq 'Goode_Homolosine') {
-            SetGH($self, @parameters);
-        } elsif ($params{Projection} eq 'Interrupted_Goode_Homolosine') {
-            SetIGH($self);
-        } elsif ($params{Projection} eq 'Geostationary_Satellite') {
-            SetGEOS($self, @parameters);
-        } elsif ($params{Projection} eq 'Gnomonic') {
-            SetGnomonic($self, @parameters);
-        } elsif ($params{Projection} eq 'Hotine_Oblique_Mercator') {
-            # Hotine_Oblique_Mercator_Azimuth_Center ?
-            SetHOM($self, @parameters);
-        } elsif ($params{Projection} eq 'Hotine_Oblique_Mercator_Two_Point_Natural_Origin') {
-            SetHOM2PNO($self, @parameters);
-        } elsif ($params{Projection} eq 'Krovak') {
-            SetKrovak($self, @parameters);
-        } elsif ($params{Projection} eq 'Lambert_Azimuthal_Equal_Area') {
-            SetLAEA($self, @parameters);
-        } elsif ($params{Projection} eq 'Lambert_Conformal_Conic_2SP') {
-            SetLCC($self, @parameters);
-        } elsif ($params{Projection} eq 'Lambert_Conformal_Conic_1SP') {
-            SetLCC1SP($self, @parameters);
-        } elsif ($params{Projection} eq 'Lambert_Conformal_Conic_2SP_Belgium') {
-            SetLCCB($self, @parameters);
-        } elsif ($params{Projection} eq 'miller_cylindrical') {
-            SetMC($self, @parameters);
-        } elsif ($params{Projection} =~ /^Mercator/) {
-            # Mercator_1SP, Mercator_2SP, Mercator_Auxiliary_Sphere ?
-            # variant is in Variant (or Name)
-            SetMercator($self, @parameters);
-        } elsif ($params{Projection} eq 'Mollweide') {
-            SetMollweide($self, @parameters);
-        } elsif ($params{Projection} eq 'New_Zealand_Map_Grid') {
-            SetNZMG($self, @parameters);
-        } elsif ($params{Projection} eq 'Oblique_Stereographic') {
-            SetOS($self, @parameters);
-        } elsif ($params{Projection} eq 'Orthographic') {
-            SetOrthographic($self, @parameters);
-        } elsif ($params{Projection} eq 'Polyconic') {
-            SetPolyconic($self, @parameters);
-        } elsif ($params{Projection} eq 'Polar_Stereographic') {
-            SetPS($self, @parameters);
-        } elsif ($params{Projection} eq 'Robinson') {
-            SetRobinson($self, @parameters);
-        } elsif ($params{Projection} eq 'Sinusoidal') {
-            SetSinusoidal($self, @parameters);
-        } elsif ($params{Projection} eq 'Stereographic') {
-            SetStereographic($self, @parameters);
-        } elsif ($params{Projection} eq 'Swiss_Oblique_Cylindrical') {
-            SetSOC($self, @parameters);
-        } elsif ($params{Projection} eq 'Transverse_Mercator_South_Orientated') {
-            SetTMSO($self, @parameters);
-        } elsif ($params{Projection} =~ /^Transverse_Mercator/) {
-            my($variant) = $params{Projection} =~ /^Transverse_Mercator_(\w+)/;
-            $variant = $params{Variant} unless $variant;
-            $variant = $params{Name} unless $variant;
-            $variant ?
-                SetTMVariant($self, $variant, @parameters) :
-                SetTM($self, @parameters);
-        } elsif ($params{Projection} eq 'Tunisia_Mining_Grid') {
-            SetTMG($self, @parameters);
-        } elsif ($params{Projection} eq 'VanDerGrinten') {
-            SetVDG($self, @parameters);
-        } else {
-            # Aitoff, Craster_Parabolic, International_Map_of_the_World_Polyconic, Laborde_Oblique_Mercator
-            # Loximuthal, Miller_Cylindrical, Quadrilateralized_Spherical_Cube, Quartic_Authalic, Two_Point_Equidistant
-            # Wagner_I, Wagner_II, Wagner_III, Wagner_IV, Wagner_V, Wagner_VI, Wagner_VII
-            # Winkel_I, Winkel_II, Winkel_Tripel
-            # ?
-            SetProjection($self, $params{Projection});
-        }
-    } else {
-        confess "Not enough information for a spatial reference object.";
-    }
-}
-
-sub GetUTMZone {
-    my $self = shift;
-    my $zone = _GetUTMZone($self);
-    if (wantarray) {            
-        my $north = 1;
-        if ($zone < 0) {
-            $zone *= -1;
-            $north = 0;
-        }
-        return ($zone, $north);
-    } else {
-        return $zone;
-    }
-}
-
-
-package Geo::OSR::CoordinateTransformation;
-use strict;
-use warnings;
-
-sub TransformPoints {
-    my($self, $points) = @_;
-    _TransformPoints($self, $points), return unless ref($points->[0]->[0]);
-    for my $p (@$points) {
-        TransformPoints($self, $p);
-    }
-}
-1;
diff --git a/swig/perl/ogr_wrap.cpp b/swig/perl/ogr_wrap.cpp
deleted file mode 100644
index 6439b65..0000000
--- a/swig/perl/ogr_wrap.cpp
+++ /dev/null
@@ -1,26600 +0,0 @@
-/* ----------------------------------------------------------------------------
- * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 2.0.12
- *
- * This file is not intended to be easily readable and contains a number of
- * coding conventions designed to improve portability and efficiency. Do not make
- * changes to this file unless you know what you are doing--modify the SWIG
- * interface file instead.
- * ----------------------------------------------------------------------------- */
-
-#define SWIGPERL
-#define SWIG_CASTRANK_MODE
-
-
-#ifdef __cplusplus
-/* SwigValueWrapper is described in swig.swg */
-template<typename T> class SwigValueWrapper {
-  struct SwigMovePointer {
-    T *ptr;
-    SwigMovePointer(T *p) : ptr(p) { }
-    ~SwigMovePointer() { delete ptr; }
-    SwigMovePointer& operator=(SwigMovePointer& rhs) { T* oldptr = ptr; ptr = 0; delete oldptr; ptr = rhs.ptr; rhs.ptr = 0; return *this; }
-  } pointer;
-  SwigValueWrapper& operator=(const SwigValueWrapper<T>& rhs);
-  SwigValueWrapper(const SwigValueWrapper<T>& rhs);
-public:
-  SwigValueWrapper() : pointer(0) { }
-  SwigValueWrapper& operator=(const T& t) { SwigMovePointer tmp(new T(t)); pointer = tmp; return *this; }
-  operator T&() const { return *pointer.ptr; }
-  T *operator&() { return pointer.ptr; }
-};
-
-template <typename T> T SwigValueInit() {
-  return T();
-}
-#endif
-
-/* -----------------------------------------------------------------------------
- *  This section contains generic SWIG labels for method/variable
- *  declarations/attributes, and other compiler dependent labels.
- * ----------------------------------------------------------------------------- */
-
-/* template workaround for compilers that cannot correctly implement the C++ standard */
-#ifndef SWIGTEMPLATEDISAMBIGUATOR
-# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560)
-#  define SWIGTEMPLATEDISAMBIGUATOR template
-# elif defined(__HP_aCC)
-/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */
-/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */
-#  define SWIGTEMPLATEDISAMBIGUATOR template
-# else
-#  define SWIGTEMPLATEDISAMBIGUATOR
-# endif
-#endif
-
-/* inline attribute */
-#ifndef SWIGINLINE
-# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__))
-#   define SWIGINLINE inline
-# else
-#   define SWIGINLINE
-# endif
-#endif
-
-/* attribute recognised by some compilers to avoid 'unused' warnings */
-#ifndef SWIGUNUSED
-# if defined(__GNUC__)
-#   if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
-#     define SWIGUNUSED __attribute__ ((__unused__))
-#   else
-#     define SWIGUNUSED
-#   endif
-# elif defined(__ICC)
-#   define SWIGUNUSED __attribute__ ((__unused__))
-# else
-#   define SWIGUNUSED
-# endif
-#endif
-
-#ifndef SWIG_MSC_UNSUPPRESS_4505
-# if defined(_MSC_VER)
-#   pragma warning(disable : 4505) /* unreferenced local function has been removed */
-# endif
-#endif
-
-#ifndef SWIGUNUSEDPARM
-# ifdef __cplusplus
-#   define SWIGUNUSEDPARM(p)
-# else
-#   define SWIGUNUSEDPARM(p) p SWIGUNUSED
-# endif
-#endif
-
-/* internal SWIG method */
-#ifndef SWIGINTERN
-# define SWIGINTERN static SWIGUNUSED
-#endif
-
-/* internal inline SWIG method */
-#ifndef SWIGINTERNINLINE
-# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE
-#endif
-
-/* exporting methods */
-#if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
-#  ifndef GCC_HASCLASSVISIBILITY
-#    define GCC_HASCLASSVISIBILITY
-#  endif
-#endif
-
-#ifndef SWIGEXPORT
-# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
-#   if defined(STATIC_LINKED)
-#     define SWIGEXPORT
-#   else
-#     define SWIGEXPORT __declspec(dllexport)
-#   endif
-# else
-#   if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY)
-#     define SWIGEXPORT __attribute__ ((visibility("default")))
-#   else
-#     define SWIGEXPORT
-#   endif
-# endif
-#endif
-
-/* calling conventions for Windows */
-#ifndef SWIGSTDCALL
-# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
-#   define SWIGSTDCALL __stdcall
-# else
-#   define SWIGSTDCALL
-# endif
-#endif
-
-/* Deal with Microsoft's attempt at deprecating C standard runtime functions */
-#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
-# define _CRT_SECURE_NO_DEPRECATE
-#endif
-
-/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */
-#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE)
-# define _SCL_SECURE_NO_DEPRECATE
-#endif
-
-
-/* -----------------------------------------------------------------------------
- * swigrun.swg
- *
- * This file contains generic C API SWIG runtime support for pointer
- * type checking.
- * ----------------------------------------------------------------------------- */
-
-/* This should only be incremented when either the layout of swig_type_info changes,
-   or for whatever reason, the runtime changes incompatibly */
-#define SWIG_RUNTIME_VERSION "4"
-
-/* define SWIG_TYPE_TABLE_NAME as "SWIG_TYPE_TABLE" */
-#ifdef SWIG_TYPE_TABLE
-# define SWIG_QUOTE_STRING(x) #x
-# define SWIG_EXPAND_AND_QUOTE_STRING(x) SWIG_QUOTE_STRING(x)
-# define SWIG_TYPE_TABLE_NAME SWIG_EXPAND_AND_QUOTE_STRING(SWIG_TYPE_TABLE)
-#else
-# define SWIG_TYPE_TABLE_NAME
-#endif
-
-/*
-  You can use the SWIGRUNTIME and SWIGRUNTIMEINLINE macros for
-  creating a static or dynamic library from the SWIG runtime code.
-  In 99.9% of the cases, SWIG just needs to declare them as 'static'.
-
-  But only do this if strictly necessary, ie, if you have problems
-  with your compiler or suchlike.
-*/
-
-#ifndef SWIGRUNTIME
-# define SWIGRUNTIME SWIGINTERN
-#endif
-
-#ifndef SWIGRUNTIMEINLINE
-# define SWIGRUNTIMEINLINE SWIGRUNTIME SWIGINLINE
-#endif
-
-/*  Generic buffer size */
-#ifndef SWIG_BUFFER_SIZE
-# define SWIG_BUFFER_SIZE 1024
-#endif
-
-/* Flags for pointer conversions */
-#define SWIG_POINTER_DISOWN        0x1
-#define SWIG_CAST_NEW_MEMORY       0x2
-
-/* Flags for new pointer objects */
-#define SWIG_POINTER_OWN           0x1
-
-
-/*
-   Flags/methods for returning states.
-
-   The SWIG conversion methods, as ConvertPtr, return an integer
-   that tells if the conversion was successful or not. And if not,
-   an error code can be returned (see swigerrors.swg for the codes).
-
-   Use the following macros/flags to set or process the returning
-   states.
-
-   In old versions of SWIG, code such as the following was usually written:
-
-     if (SWIG_ConvertPtr(obj,vptr,ty.flags) != -1) {
-       // success code
-     } else {
-       //fail code
-     }
-
-   Now you can be more explicit:
-
-    int res = SWIG_ConvertPtr(obj,vptr,ty.flags);
-    if (SWIG_IsOK(res)) {
-      // success code
-    } else {
-      // fail code
-    }
-
-   which is the same really, but now you can also do
-
-    Type *ptr;
-    int res = SWIG_ConvertPtr(obj,(void **)(&ptr),ty.flags);
-    if (SWIG_IsOK(res)) {
-      // success code
-      if (SWIG_IsNewObj(res) {
-        ...
-	delete *ptr;
-      } else {
-        ...
-      }
-    } else {
-      // fail code
-    }
-
-   I.e., now SWIG_ConvertPtr can return new objects and you can
-   identify the case and take care of the deallocation. Of course that
-   also requires SWIG_ConvertPtr to return new result values, such as
-
-      int SWIG_ConvertPtr(obj, ptr,...) {
-        if (<obj is ok>) {
-          if (<need new object>) {
-            *ptr = <ptr to new allocated object>;
-            return SWIG_NEWOBJ;
-          } else {
-            *ptr = <ptr to old object>;
-            return SWIG_OLDOBJ;
-          }
-        } else {
-          return SWIG_BADOBJ;
-        }
-      }
-
-   Of course, returning the plain '0(success)/-1(fail)' still works, but you can be
-   more explicit by returning SWIG_BADOBJ, SWIG_ERROR or any of the
-   SWIG errors code.
-
-   Finally, if the SWIG_CASTRANK_MODE is enabled, the result code
-   allows to return the 'cast rank', for example, if you have this
-
-       int food(double)
-       int fooi(int);
-
-   and you call
-
-      food(1)   // cast rank '1'  (1 -> 1.0)
-      fooi(1)   // cast rank '0'
-
-   just use the SWIG_AddCast()/SWIG_CheckState()
-*/
-
-#define SWIG_OK                    (0)
-#define SWIG_ERROR                 (-1)
-#define SWIG_IsOK(r)               (r >= 0)
-#define SWIG_ArgError(r)           ((r != SWIG_ERROR) ? r : SWIG_TypeError)
-
-/* The CastRankLimit says how many bits are used for the cast rank */
-#define SWIG_CASTRANKLIMIT         (1 << 8)
-/* The NewMask denotes the object was created (using new/malloc) */
-#define SWIG_NEWOBJMASK            (SWIG_CASTRANKLIMIT  << 1)
-/* The TmpMask is for in/out typemaps that use temporal objects */
-#define SWIG_TMPOBJMASK            (SWIG_NEWOBJMASK << 1)
-/* Simple returning values */
-#define SWIG_BADOBJ                (SWIG_ERROR)
-#define SWIG_OLDOBJ                (SWIG_OK)
-#define SWIG_NEWOBJ                (SWIG_OK | SWIG_NEWOBJMASK)
-#define SWIG_TMPOBJ                (SWIG_OK | SWIG_TMPOBJMASK)
-/* Check, add and del mask methods */
-#define SWIG_AddNewMask(r)         (SWIG_IsOK(r) ? (r | SWIG_NEWOBJMASK) : r)
-#define SWIG_DelNewMask(r)         (SWIG_IsOK(r) ? (r & ~SWIG_NEWOBJMASK) : r)
-#define SWIG_IsNewObj(r)           (SWIG_IsOK(r) && (r & SWIG_NEWOBJMASK))
-#define SWIG_AddTmpMask(r)         (SWIG_IsOK(r) ? (r | SWIG_TMPOBJMASK) : r)
-#define SWIG_DelTmpMask(r)         (SWIG_IsOK(r) ? (r & ~SWIG_TMPOBJMASK) : r)
-#define SWIG_IsTmpObj(r)           (SWIG_IsOK(r) && (r & SWIG_TMPOBJMASK))
-
-/* Cast-Rank Mode */
-#if defined(SWIG_CASTRANK_MODE)
-#  ifndef SWIG_TypeRank
-#    define SWIG_TypeRank             unsigned long
-#  endif
-#  ifndef SWIG_MAXCASTRANK            /* Default cast allowed */
-#    define SWIG_MAXCASTRANK          (2)
-#  endif
-#  define SWIG_CASTRANKMASK          ((SWIG_CASTRANKLIMIT) -1)
-#  define SWIG_CastRank(r)           (r & SWIG_CASTRANKMASK)
-SWIGINTERNINLINE int SWIG_AddCast(int r) {
-  return SWIG_IsOK(r) ? ((SWIG_CastRank(r) < SWIG_MAXCASTRANK) ? (r + 1) : SWIG_ERROR) : r;
-}
-SWIGINTERNINLINE int SWIG_CheckState(int r) {
-  return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0;
-}
-#else /* no cast-rank mode */
-#  define SWIG_AddCast(r) (r)
-#  define SWIG_CheckState(r) (SWIG_IsOK(r) ? 1 : 0)
-#endif
-
-
-#include <string.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef void *(*swig_converter_func)(void *, int *);
-typedef struct swig_type_info *(*swig_dycast_func)(void **);
-
-/* Structure to store information on one type */
-typedef struct swig_type_info {
-  const char             *name;			/* mangled name of this type */
-  const char             *str;			/* human readable name of this type */
-  swig_dycast_func        dcast;		/* dynamic cast function down a hierarchy */
-  struct swig_cast_info  *cast;			/* linked list of types that can cast into this type */
-  void                   *clientdata;		/* language specific type data */
-  int                    owndata;		/* flag if the structure owns the clientdata */
-} swig_type_info;
-
-/* Structure to store a type and conversion function used for casting */
-typedef struct swig_cast_info {
-  swig_type_info         *type;			/* pointer to type that is equivalent to this type */
-  swig_converter_func     converter;		/* function to cast the void pointers */
-  struct swig_cast_info  *next;			/* pointer to next cast in linked list */
-  struct swig_cast_info  *prev;			/* pointer to the previous cast */
-} swig_cast_info;
-
-/* Structure used to store module information
- * Each module generates one structure like this, and the runtime collects
- * all of these structures and stores them in a circularly linked list.*/
-typedef struct swig_module_info {
-  swig_type_info         **types;		/* Array of pointers to swig_type_info structures that are in this module */
-  size_t                 size;		        /* Number of types in this module */
-  struct swig_module_info *next;		/* Pointer to next element in circularly linked list */
-  swig_type_info         **type_initial;	/* Array of initially generated type structures */
-  swig_cast_info         **cast_initial;	/* Array of initially generated casting structures */
-  void                    *clientdata;		/* Language specific module data */
-} swig_module_info;
-
-/*
-  Compare two type names skipping the space characters, therefore
-  "char*" == "char *" and "Class<int>" == "Class<int >", etc.
-
-  Return 0 when the two name types are equivalent, as in
-  strncmp, but skipping ' '.
-*/
-SWIGRUNTIME int
-SWIG_TypeNameComp(const char *f1, const char *l1,
-		  const char *f2, const char *l2) {
-  for (;(f1 != l1) && (f2 != l2); ++f1, ++f2) {
-    while ((*f1 == ' ') && (f1 != l1)) ++f1;
-    while ((*f2 == ' ') && (f2 != l2)) ++f2;
-    if (*f1 != *f2) return (*f1 > *f2) ? 1 : -1;
-  }
-  return (int)((l1 - f1) - (l2 - f2));
-}
-
-/*
-  Check type equivalence in a name list like <name1>|<name2>|...
-  Return 0 if equal, -1 if nb < tb, 1 if nb > tb
-*/
-SWIGRUNTIME int
-SWIG_TypeCmp(const char *nb, const char *tb) {
-  int equiv = 1;
-  const char* te = tb + strlen(tb);
-  const char* ne = nb;
-  while (equiv != 0 && *ne) {
-    for (nb = ne; *ne; ++ne) {
-      if (*ne == '|') break;
-    }
-    equiv = SWIG_TypeNameComp(nb, ne, tb, te);
-    if (*ne) ++ne;
-  }
-  return equiv;
-}
-
-/*
-  Check type equivalence in a name list like <name1>|<name2>|...
-  Return 0 if not equal, 1 if equal
-*/
-SWIGRUNTIME int
-SWIG_TypeEquiv(const char *nb, const char *tb) {
-  return SWIG_TypeCmp(nb, tb) == 0 ? 1 : 0;
-}
-
-/*
-  Check the typename
-*/
-SWIGRUNTIME swig_cast_info *
-SWIG_TypeCheck(const char *c, swig_type_info *ty) {
-  if (ty) {
-    swig_cast_info *iter = ty->cast;
-    while (iter) {
-      if (strcmp(iter->type->name, c) == 0) {
-        if (iter == ty->cast)
-          return iter;
-        /* Move iter to the top of the linked list */
-        iter->prev->next = iter->next;
-        if (iter->next)
-          iter->next->prev = iter->prev;
-        iter->next = ty->cast;
-        iter->prev = 0;
-        if (ty->cast) ty->cast->prev = iter;
-        ty->cast = iter;
-        return iter;
-      }
-      iter = iter->next;
-    }
-  }
-  return 0;
-}
-
-/*
-  Identical to SWIG_TypeCheck, except strcmp is replaced with a pointer comparison
-*/
-SWIGRUNTIME swig_cast_info *
-SWIG_TypeCheckStruct(swig_type_info *from, swig_type_info *ty) {
-  if (ty) {
-    swig_cast_info *iter = ty->cast;
-    while (iter) {
-      if (iter->type == from) {
-        if (iter == ty->cast)
-          return iter;
-        /* Move iter to the top of the linked list */
-        iter->prev->next = iter->next;
-        if (iter->next)
-          iter->next->prev = iter->prev;
-        iter->next = ty->cast;
-        iter->prev = 0;
-        if (ty->cast) ty->cast->prev = iter;
-        ty->cast = iter;
-        return iter;
-      }
-      iter = iter->next;
-    }
-  }
-  return 0;
-}
-
-/*
-  Cast a pointer up an inheritance hierarchy
-*/
-SWIGRUNTIMEINLINE void *
-SWIG_TypeCast(swig_cast_info *ty, void *ptr, int *newmemory) {
-  return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr, newmemory);
-}
-
-/*
-   Dynamic pointer casting. Down an inheritance hierarchy
-*/
-SWIGRUNTIME swig_type_info *
-SWIG_TypeDynamicCast(swig_type_info *ty, void **ptr) {
-  swig_type_info *lastty = ty;
-  if (!ty || !ty->dcast) return ty;
-  while (ty && (ty->dcast)) {
-    ty = (*ty->dcast)(ptr);
-    if (ty) lastty = ty;
-  }
-  return lastty;
-}
-
-/*
-  Return the name associated with this type
-*/
-SWIGRUNTIMEINLINE const char *
-SWIG_TypeName(const swig_type_info *ty) {
-  return ty->name;
-}
-
-/*
-  Return the pretty name associated with this type,
-  that is an unmangled type name in a form presentable to the user.
-*/
-SWIGRUNTIME const char *
-SWIG_TypePrettyName(const swig_type_info *type) {
-  /* The "str" field contains the equivalent pretty names of the
-     type, separated by vertical-bar characters.  We choose
-     to print the last name, as it is often (?) the most
-     specific. */
-  if (!type) return NULL;
-  if (type->str != NULL) {
-    const char *last_name = type->str;
-    const char *s;
-    for (s = type->str; *s; s++)
-      if (*s == '|') last_name = s+1;
-    return last_name;
-  }
-  else
-    return type->name;
-}
-
-/*
-   Set the clientdata field for a type
-*/
-SWIGRUNTIME void
-SWIG_TypeClientData(swig_type_info *ti, void *clientdata) {
-  swig_cast_info *cast = ti->cast;
-  /* if (ti->clientdata == clientdata) return; */
-  ti->clientdata = clientdata;
-
-  while (cast) {
-    if (!cast->converter) {
-      swig_type_info *tc = cast->type;
-      if (!tc->clientdata) {
-	SWIG_TypeClientData(tc, clientdata);
-      }
-    }
-    cast = cast->next;
-  }
-}
-SWIGRUNTIME void
-SWIG_TypeNewClientData(swig_type_info *ti, void *clientdata) {
-  SWIG_TypeClientData(ti, clientdata);
-  ti->owndata = 1;
-}
-
-/*
-  Search for a swig_type_info structure only by mangled name
-  Search is a O(log #types)
-
-  We start searching at module start, and finish searching when start == end.
-  Note: if start == end at the beginning of the function, we go all the way around
-  the circular list.
-*/
-SWIGRUNTIME swig_type_info *
-SWIG_MangledTypeQueryModule(swig_module_info *start,
-                            swig_module_info *end,
-		            const char *name) {
-  swig_module_info *iter = start;
-  do {
-    if (iter->size) {
-      register size_t l = 0;
-      register size_t r = iter->size - 1;
-      do {
-	/* since l+r >= 0, we can (>> 1) instead (/ 2) */
-	register size_t i = (l + r) >> 1;
-	const char *iname = iter->types[i]->name;
-	if (iname) {
-	  register int compare = strcmp(name, iname);
-	  if (compare == 0) {
-	    return iter->types[i];
-	  } else if (compare < 0) {
-	    if (i) {
-	      r = i - 1;
-	    } else {
-	      break;
-	    }
-	  } else if (compare > 0) {
-	    l = i + 1;
-	  }
-	} else {
-	  break; /* should never happen */
-	}
-      } while (l <= r);
-    }
-    iter = iter->next;
-  } while (iter != end);
-  return 0;
-}
-
-/*
-  Search for a swig_type_info structure for either a mangled name or a human readable name.
-  It first searches the mangled names of the types, which is a O(log #types)
-  If a type is not found it then searches the human readable names, which is O(#types).
-
-  We start searching at module start, and finish searching when start == end.
-  Note: if start == end at the beginning of the function, we go all the way around
-  the circular list.
-*/
-SWIGRUNTIME swig_type_info *
-SWIG_TypeQueryModule(swig_module_info *start,
-                     swig_module_info *end,
-		     const char *name) {
-  /* STEP 1: Search the name field using binary search */
-  swig_type_info *ret = SWIG_MangledTypeQueryModule(start, end, name);
-  if (ret) {
-    return ret;
-  } else {
-    /* STEP 2: If the type hasn't been found, do a complete search
-       of the str field (the human readable name) */
-    swig_module_info *iter = start;
-    do {
-      register size_t i = 0;
-      for (; i < iter->size; ++i) {
-	if (iter->types[i]->str && (SWIG_TypeEquiv(iter->types[i]->str, name)))
-	  return iter->types[i];
-      }
-      iter = iter->next;
-    } while (iter != end);
-  }
-
-  /* neither found a match */
-  return 0;
-}
-
-/*
-   Pack binary data into a string
-*/
-SWIGRUNTIME char *
-SWIG_PackData(char *c, void *ptr, size_t sz) {
-  static const char hex[17] = "0123456789abcdef";
-  register const unsigned char *u = (unsigned char *) ptr;
-  register const unsigned char *eu =  u + sz;
-  for (; u != eu; ++u) {
-    register unsigned char uu = *u;
-    *(c++) = hex[(uu & 0xf0) >> 4];
-    *(c++) = hex[uu & 0xf];
-  }
-  return c;
-}
-
-/*
-   Unpack binary data from a string
-*/
-SWIGRUNTIME const char *
-SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
-  register unsigned char *u = (unsigned char *) ptr;
-  register const unsigned char *eu = u + sz;
-  for (; u != eu; ++u) {
-    register char d = *(c++);
-    register unsigned char uu;
-    if ((d >= '0') && (d <= '9'))
-      uu = ((d - '0') << 4);
-    else if ((d >= 'a') && (d <= 'f'))
-      uu = ((d - ('a'-10)) << 4);
-    else
-      return (char *) 0;
-    d = *(c++);
-    if ((d >= '0') && (d <= '9'))
-      uu |= (d - '0');
-    else if ((d >= 'a') && (d <= 'f'))
-      uu |= (d - ('a'-10));
-    else
-      return (char *) 0;
-    *u = uu;
-  }
-  return c;
-}
-
-/*
-   Pack 'void *' into a string buffer.
-*/
-SWIGRUNTIME char *
-SWIG_PackVoidPtr(char *buff, void *ptr, const char *name, size_t bsz) {
-  char *r = buff;
-  if ((2*sizeof(void *) + 2) > bsz) return 0;
-  *(r++) = '_';
-  r = SWIG_PackData(r,&ptr,sizeof(void *));
-  if (strlen(name) + 1 > (bsz - (r - buff))) return 0;
-  strcpy(r,name);
-  return buff;
-}
-
-SWIGRUNTIME const char *
-SWIG_UnpackVoidPtr(const char *c, void **ptr, const char *name) {
-  if (*c != '_') {
-    if (strcmp(c,"NULL") == 0) {
-      *ptr = (void *) 0;
-      return name;
-    } else {
-      return 0;
-    }
-  }
-  return SWIG_UnpackData(++c,ptr,sizeof(void *));
-}
-
-SWIGRUNTIME char *
-SWIG_PackDataName(char *buff, void *ptr, size_t sz, const char *name, size_t bsz) {
-  char *r = buff;
-  size_t lname = (name ? strlen(name) : 0);
-  if ((2*sz + 2 + lname) > bsz) return 0;
-  *(r++) = '_';
-  r = SWIG_PackData(r,ptr,sz);
-  if (lname) {
-    strncpy(r,name,lname+1);
-  } else {
-    *r = 0;
-  }
-  return buff;
-}
-
-SWIGRUNTIME const char *
-SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) {
-  if (*c != '_') {
-    if (strcmp(c,"NULL") == 0) {
-      memset(ptr,0,sz);
-      return name;
-    } else {
-      return 0;
-    }
-  }
-  return SWIG_UnpackData(++c,ptr,sz);
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-/*  Errors in SWIG */
-#define  SWIG_UnknownError    	   -1
-#define  SWIG_IOError        	   -2
-#define  SWIG_RuntimeError   	   -3
-#define  SWIG_IndexError     	   -4
-#define  SWIG_TypeError      	   -5
-#define  SWIG_DivisionByZero 	   -6
-#define  SWIG_OverflowError  	   -7
-#define  SWIG_SyntaxError    	   -8
-#define  SWIG_ValueError     	   -9
-#define  SWIG_SystemError    	   -10
-#define  SWIG_AttributeError 	   -11
-#define  SWIG_MemoryError    	   -12
-#define  SWIG_NullReferenceError   -13
-
-
-
-#ifdef __cplusplus
-/* Needed on some windows machines---since MS plays funny games with the header files under C++ */
-#include <math.h>
-#include <stdlib.h>
-extern "C" {
-#endif
-#include "EXTERN.h"
-#include "perl.h"
-#include "XSUB.h"
-
-/* Add in functionality missing in older versions of Perl. Much of this is based on Devel-PPPort on cpan. */
-
-/* Add PERL_REVISION, PERL_VERSION, PERL_SUBVERSION if missing */
-#ifndef PERL_REVISION
-#  if !defined(__PATCHLEVEL_H_INCLUDED__) && !(defined(PATCHLEVEL) && defined(SUBVERSION))
-#    define PERL_PATCHLEVEL_H_IMPLICIT
-#    include <patchlevel.h>
-#  endif
-#  if !(defined(PERL_VERSION) || (defined(SUBVERSION) && defined(PATCHLEVEL)))
-#    include <could_not_find_Perl_patchlevel.h>
-#  endif
-#  ifndef PERL_REVISION
-#    define PERL_REVISION       (5)
-#    define PERL_VERSION        PATCHLEVEL
-#    define PERL_SUBVERSION     SUBVERSION
-#  endif
-#endif
-
-#if defined(WIN32) && defined(PERL_OBJECT) && !defined(PerlIO_exportFILE)
-#define PerlIO_exportFILE(fh,fl) (FILE*)(fh)
-#endif
-
-#ifndef SvIOK_UV
-# define SvIOK_UV(sv)       (SvIOK(sv) && (SvUVX(sv) == SvIVX(sv)))
-#endif
-
-#ifndef SvUOK
-# define SvUOK(sv)           SvIOK_UV(sv)
-#endif
-
-#if ((PERL_VERSION < 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION <= 5)))
-#  define PL_sv_undef               sv_undef
-#  define PL_na	                    na
-#  define PL_errgv                  errgv
-#  define PL_sv_no                  sv_no
-#  define PL_sv_yes                 sv_yes
-#  define PL_markstack_ptr          markstack_ptr
-#endif
-
-#ifndef IVSIZE
-#  ifdef LONGSIZE
-#    define IVSIZE LONGSIZE
-#  else
-#    define IVSIZE 4 /* A bold guess, but the best we can make. */
-#  endif
-#endif
-
-#ifndef INT2PTR
-#  if (IVSIZE == PTRSIZE) && (UVSIZE == PTRSIZE)
-#    define PTRV                  UV
-#    define INT2PTR(any,d)        (any)(d)
-#  else
-#    if PTRSIZE == LONGSIZE
-#      define PTRV                unsigned long
-#    else
-#      define PTRV                unsigned
-#    endif
-#    define INT2PTR(any,d)        (any)(PTRV)(d)
-#  endif
-
-#  define NUM2PTR(any,d)  (any)(PTRV)(d)
-#  define PTR2IV(p)       INT2PTR(IV,p)
-#  define PTR2UV(p)       INT2PTR(UV,p)
-#  define PTR2NV(p)       NUM2PTR(NV,p)
-
-#  if PTRSIZE == LONGSIZE
-#    define PTR2ul(p)     (unsigned long)(p)
-#  else
-#    define PTR2ul(p)     INT2PTR(unsigned long,p)
-#  endif
-#endif /* !INT2PTR */
-
-#ifndef SvPV_nolen
-# define SvPV_nolen(x) SvPV(x,PL_na)
-#endif
-
-#ifndef get_sv
-#  define get_sv perl_get_sv
-#endif
-
-#ifndef ERRSV
-#  define ERRSV get_sv("@",FALSE)
-#endif
-
-#ifndef pTHX_
-#define pTHX_
-#endif   
-
-#include <string.h>
-#ifdef __cplusplus
-}
-#endif
-
-/* -----------------------------------------------------------------------------
- * error manipulation
- * ----------------------------------------------------------------------------- */
-
-SWIGINTERN const char*
-SWIG_Perl_ErrorType(int code) {
-  switch(code) {
-  case SWIG_MemoryError:
-    return "MemoryError";
-  case SWIG_IOError:
-    return "IOError";
-  case SWIG_RuntimeError:
-    return "RuntimeError";
-  case SWIG_IndexError:
-    return "IndexError";
-  case SWIG_TypeError:
-    return "TypeError";
-  case SWIG_DivisionByZero:
-    return "ZeroDivisionError";
-  case SWIG_OverflowError:
-    return "OverflowError";
-  case SWIG_SyntaxError:
-    return "SyntaxError";
-  case SWIG_ValueError:
-    return "ValueError";
-  case SWIG_SystemError:
-    return "SystemError";
-  case SWIG_AttributeError:
-    return "AttributeError";
-  default:
-    return "RuntimeError";
-  }
-}
-
-
-/* -----------------------------------------------------------------------------
- * perlrun.swg
- *
- * This file contains the runtime support for Perl modules
- * and includes code for managing global variables and pointer
- * type checking.
- * ----------------------------------------------------------------------------- */
-
-#ifdef PERL_OBJECT
-#define SWIG_PERL_OBJECT_DECL CPerlObj *SWIGUNUSEDPARM(pPerl),
-#define SWIG_PERL_OBJECT_CALL pPerl,
-#else
-#define SWIG_PERL_OBJECT_DECL
-#define SWIG_PERL_OBJECT_CALL
-#endif
-
-/* Common SWIG API */
-
-/* for raw pointers */
-#define SWIG_ConvertPtr(obj, pp, type, flags)           SWIG_Perl_ConvertPtr(SWIG_PERL_OBJECT_CALL obj, pp, type, flags)
-#define SWIG_ConvertPtrAndOwn(obj, pp, type, flags,own) SWIG_Perl_ConvertPtrAndOwn(SWIG_PERL_OBJECT_CALL obj, pp, type, flags, own)
-#define SWIG_NewPointerObj(p, type, flags)              SWIG_Perl_NewPointerObj(SWIG_PERL_OBJECT_CALL p, type, flags)
-
-/* for raw packed data */
-#define SWIG_ConvertPacked(obj, p, s, type)             SWIG_Perl_ConvertPacked(SWIG_PERL_OBJECT_CALL obj, p, s, type)
-#define SWIG_NewPackedObj(p, s, type)	                SWIG_Perl_NewPackedObj(SWIG_PERL_OBJECT_CALL p, s, type)
-
-/* for class or struct pointers */
-#define SWIG_ConvertInstance(obj, pptr, type, flags)    SWIG_ConvertPtr(obj, pptr, type, flags)
-#define SWIG_NewInstanceObj(ptr, type, flags)           SWIG_NewPointerObj(ptr, type, flags)
-
-/* for C or C++ function pointers */
-#define SWIG_ConvertFunctionPtr(obj, pptr, type)        SWIG_ConvertPtr(obj, pptr, type, 0)
-#define SWIG_NewFunctionPtrObj(ptr, type)               SWIG_NewPointerObj(ptr, type, 0)
-
-/* for C++ member pointers, ie, member methods */
-#define SWIG_ConvertMember(obj, ptr, sz, ty)            SWIG_ConvertPacked(obj, ptr, sz, ty)
-#define SWIG_NewMemberObj(ptr, sz, type)                SWIG_NewPackedObj(ptr, sz, type)
-
-
-/* Runtime API */
-
-#define SWIG_GetModule(clientdata)                      SWIG_Perl_GetModule(clientdata)
-#define SWIG_SetModule(clientdata, pointer)             SWIG_Perl_SetModule(pointer)
-
-
-/* Error manipulation */
-
-#define SWIG_ErrorType(code)                            SWIG_Perl_ErrorType(code)               
-#define SWIG_Error(code, msg)            		sv_setpvf(get_sv("@", GV_ADD), "%s %s", SWIG_ErrorType(code), msg)
-#define SWIG_fail                        		goto fail						    
-
-/* Perl-specific SWIG API */
-
-#define SWIG_MakePtr(sv, ptr, type, flags)              SWIG_Perl_MakePtr(SWIG_PERL_OBJECT_CALL sv, ptr, type, flags)
-#define SWIG_MakePackedObj(sv, p, s, type)	        SWIG_Perl_MakePackedObj(SWIG_PERL_OBJECT_CALL sv, p, s, type)
-#define SWIG_SetError(str)                              SWIG_Error(SWIG_RuntimeError, str)
-
-
-#define SWIG_PERL_DECL_ARGS_1(arg1)                     (SWIG_PERL_OBJECT_DECL arg1)
-#define SWIG_PERL_CALL_ARGS_1(arg1)                     (SWIG_PERL_OBJECT_CALL arg1)
-#define SWIG_PERL_DECL_ARGS_2(arg1, arg2)               (SWIG_PERL_OBJECT_DECL arg1, arg2)
-#define SWIG_PERL_CALL_ARGS_2(arg1, arg2)               (SWIG_PERL_OBJECT_CALL arg1, arg2)
-
-/* -----------------------------------------------------------------------------
- * pointers/data manipulation
- * ----------------------------------------------------------------------------- */
-
-/* For backward compatibility only */
-#define SWIG_POINTER_EXCEPTION  0
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define SWIG_OWNER   SWIG_POINTER_OWN
-#define SWIG_SHADOW  SWIG_OWNER << 1
-
-#define SWIG_MAYBE_PERL_OBJECT SWIG_PERL_OBJECT_DECL
-
-/* SWIG Perl macros */
-
-/* Macro to declare an XS function */
-#ifndef XSPROTO
-#   define XSPROTO(name) void name(pTHX_ CV* cv)
-#endif
-
-/* Macro to call an XS function */
-#ifdef PERL_OBJECT 
-#  define SWIG_CALLXS(_name) _name(cv,pPerl) 
-#else 
-#  ifndef MULTIPLICITY 
-#    define SWIG_CALLXS(_name) _name(cv) 
-#  else 
-#    define SWIG_CALLXS(_name) _name(PERL_GET_THX, cv) 
-#  endif 
-#endif 
-
-#ifdef PERL_OBJECT
-#define MAGIC_PPERL  CPerlObj *pPerl = (CPerlObj *) this;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-typedef int (CPerlObj::*SwigMagicFunc)(SV *, MAGIC *);
-#ifdef __cplusplus
-}
-#endif
-
-#define SWIG_MAGIC(a,b) (SV *a, MAGIC *b)
-#define SWIGCLASS_STATIC
-
-#else /* PERL_OBJECT */
-
-#define MAGIC_PPERL
-#define SWIGCLASS_STATIC static SWIGUNUSED
-
-#ifndef MULTIPLICITY
-#define SWIG_MAGIC(a,b) (SV *a, MAGIC *b)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-typedef int (*SwigMagicFunc)(SV *, MAGIC *);
-#ifdef __cplusplus
-}
-#endif
-
-#else /* MULTIPLICITY */
-
-#define SWIG_MAGIC(a,b) (struct interpreter *interp, SV *a, MAGIC *b)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-typedef int (*SwigMagicFunc)(struct interpreter *, SV *, MAGIC *);
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* MULTIPLICITY */
-#endif /* PERL_OBJECT */
-
-#  ifdef PERL_OBJECT
-#    define SWIG_croak_null() SWIG_Perl_croak_null(pPerl)
-static void SWIG_Perl_croak_null(CPerlObj *pPerl)
-#  else
-static void SWIG_croak_null()
-#  endif
-{
-  SV *err = get_sv("@", GV_ADD);
-#  if (PERL_VERSION < 6)
-  croak("%_", err);
-#  else
-  if (sv_isobject(err))
-    croak(0);
-  else
-    croak("%s", SvPV_nolen(err));
-#  endif
-}
-
-
-/* 
-   Define how strict is the cast between strings and integers/doubles
-   when overloading between these types occurs.
-   
-   The default is making it as strict as possible by using SWIG_AddCast
-   when needed.
-   
-   You can use -DSWIG_PERL_NO_STRICT_STR2NUM at compilation time to
-   disable the SWIG_AddCast, making the casting between string and
-   numbers less strict.
-
-   In the end, we try to solve the overloading between strings and
-   numerical types in the more natural way, but if you can avoid it,
-   well, avoid it using %rename, for example.
-*/
-#ifndef SWIG_PERL_NO_STRICT_STR2NUM
-# ifndef SWIG_PERL_STRICT_STR2NUM
-#  define SWIG_PERL_STRICT_STR2NUM
-# endif
-#endif
-#ifdef SWIG_PERL_STRICT_STR2NUM
-/* string takes precedence */
-#define SWIG_Str2NumCast(x) SWIG_AddCast(x)  
-#else
-/* number takes precedence */
-#define SWIG_Str2NumCast(x) x
-#endif
-
-
-
-#include <stdlib.h>
-
-SWIGRUNTIME const char *
-SWIG_Perl_TypeProxyName(const swig_type_info *type) {
-  if (!type) return NULL;
-  if (type->clientdata != NULL) {
-    return (const char*) type->clientdata;
-  } 
-  else {
-    return type->name;
-  }
-}
-
-/* Identical to SWIG_TypeCheck, except for strcmp comparison */
-SWIGRUNTIME swig_cast_info *
-SWIG_TypeProxyCheck(const char *c, swig_type_info *ty) {
-  if (ty) {
-    swig_cast_info *iter = ty->cast;
-    while (iter) {
-      if (strcmp(SWIG_Perl_TypeProxyName(iter->type), c) == 0) {
-        if (iter == ty->cast)
-          return iter;
-        /* Move iter to the top of the linked list */
-        iter->prev->next = iter->next;
-        if (iter->next)
-          iter->next->prev = iter->prev;
-        iter->next = ty->cast;
-        iter->prev = 0;
-        if (ty->cast) ty->cast->prev = iter;
-        ty->cast = iter;
-        return iter;
-      }
-      iter = iter->next;
-    }
-  }
-  return 0;
-}
-
-/* Function for getting a pointer value */
-
-SWIGRUNTIME int
-SWIG_Perl_ConvertPtrAndOwn(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *_t, int flags, int *own) {
-  swig_cast_info *tc;
-  void *voidptr = (void *)0;
-  SV *tsv = 0;
-
-  if (own)
-    *own = 0;
-
-  /* If magical, apply more magic */
-  if (SvGMAGICAL(sv))
-    mg_get(sv);
-
-  /* Check to see if this is an object */
-  if (sv_isobject(sv)) {
-    IV tmp = 0;
-    tsv = (SV*) SvRV(sv);
-    if ((SvTYPE(tsv) == SVt_PVHV)) {
-      MAGIC *mg;
-      if (SvMAGICAL(tsv)) {
-        mg = mg_find(tsv,'P');
-        if (mg) {
-          sv = mg->mg_obj;
-          if (sv_isobject(sv)) {
-	    tsv = (SV*)SvRV(sv);
-            tmp = SvIV(tsv);
-          }
-        }
-      } else {
-        return SWIG_ERROR;
-      }
-    } else {
-      tmp = SvIV(tsv);
-    }
-    voidptr = INT2PTR(void *,tmp);
-  } else if (! SvOK(sv)) {            /* Check for undef */
-    *(ptr) = (void *) 0;
-    return SWIG_OK;
-  } else if (SvTYPE(sv) == SVt_RV) {  /* Check for NULL pointer */
-    if (!SvROK(sv)) {
-      /* In Perl 5.12 and later, SVt_RV == SVt_IV, so sv could be a valid integer value.  */
-      if (SvIOK(sv)) {
-        return SWIG_ERROR;
-      } else {
-        /* NULL pointer (reference to undef). */
-        *(ptr) = (void *) 0;
-        return SWIG_OK;
-      }
-    } else {
-      return SWIG_ERROR;
-    }
-  } else {                            /* Don't know what it is */
-    return SWIG_ERROR;
-  }
-  if (_t) {
-    /* Now see if the types match */
-    char *_c = HvNAME(SvSTASH(SvRV(sv)));
-    tc = SWIG_TypeProxyCheck(_c,_t);
-    if (!tc) {
-      return SWIG_ERROR;
-    }
-    {
-      int newmemory = 0;
-      *ptr = SWIG_TypeCast(tc,voidptr,&newmemory);
-      if (newmemory == SWIG_CAST_NEW_MEMORY) {
-        assert(own); /* badly formed typemap which will lead to a memory leak - it must set and use own to delete *ptr */
-        if (own)
-          *own = *own | SWIG_CAST_NEW_MEMORY;
-      }
-    }
-  } else {
-    *ptr = voidptr;
-  }
-
-  /* 
-   *  DISOWN implementation: we need a perl guru to check this one.
-   */
-  if (tsv && (flags & SWIG_POINTER_DISOWN)) {
-    /* 
-     *  almost copy paste code from below SWIG_POINTER_OWN setting
-     */
-    SV *obj = sv;
-    HV *stash = SvSTASH(SvRV(obj));
-    GV *gv = *(GV**)hv_fetch(stash, "OWNER", 5, TRUE);
-    if (isGV(gv)) {
-      HV *hv = GvHVn(gv);
-      /*
-       * To set ownership (see below), a newSViv(1) entry is added. 
-       * Hence, to remove ownership, we delete the entry.
-       */
-      if (hv_exists_ent(hv, obj, 0)) {
-	hv_delete_ent(hv, obj, 0, 0);
-      }
-    }
-  }
-  return SWIG_OK;
-}
-
-SWIGRUNTIME int
-SWIG_Perl_ConvertPtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *_t, int flags) {
-  return SWIG_Perl_ConvertPtrAndOwn(sv, ptr, _t, flags, 0);
-}
-
-SWIGRUNTIME void
-SWIG_Perl_MakePtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void *ptr, swig_type_info *t, int flags) {
-  if (ptr && (flags & (SWIG_SHADOW | SWIG_POINTER_OWN))) {
-    SV *self;
-    SV *obj=newSV(0);
-    HV *hash=newHV();
-    HV *stash;
-    sv_setref_pv(obj, SWIG_Perl_TypeProxyName(t), ptr);
-    stash=SvSTASH(SvRV(obj));
-    if (flags & SWIG_POINTER_OWN) {
-      HV *hv;
-      GV *gv = *(GV**)hv_fetch(stash, "OWNER", 5, TRUE);
-      if (!isGV(gv))
-        gv_init(gv, stash, "OWNER", 5, FALSE);
-      hv=GvHVn(gv);
-      hv_store_ent(hv, obj, newSViv(1), 0);
-    }
-    sv_magic((SV *)hash, (SV *)obj, 'P', Nullch, 0);
-    SvREFCNT_dec(obj);
-    self=newRV_noinc((SV *)hash);
-    sv_setsv(sv, self);
-    SvREFCNT_dec((SV *)self);
-    sv_bless(sv, stash);
-  }
-  else {
-    sv_setref_pv(sv, SWIG_Perl_TypeProxyName(t), ptr);
-  }
-}
-
-SWIGRUNTIMEINLINE SV *
-SWIG_Perl_NewPointerObj(SWIG_MAYBE_PERL_OBJECT void *ptr, swig_type_info *t, int flags) {
-  SV *result = sv_newmortal();
-  SWIG_MakePtr(result, ptr, t, flags);
-  return result;
-}
-
-SWIGRUNTIME void
-SWIG_Perl_MakePackedObj(SWIG_MAYBE_PERL_OBJECT SV *sv, void *ptr, int sz, swig_type_info *type) {
-  char result[1024];
-  char *r = result;
-  if ((2*sz + 1 + strlen(SWIG_Perl_TypeProxyName(type))) > 1000) return;
-  *(r++) = '_';
-  r = SWIG_PackData(r,ptr,sz);
-  strcpy(r,SWIG_Perl_TypeProxyName(type));
-  sv_setpv(sv, result);
-}
-
-SWIGRUNTIME SV *
-SWIG_Perl_NewPackedObj(SWIG_MAYBE_PERL_OBJECT void *ptr, int sz, swig_type_info *type) {
-  SV *result = sv_newmortal();
-  SWIG_Perl_MakePackedObj(result, ptr, sz, type);
-  return result;
-}
-
-/* Convert a packed value value */
-SWIGRUNTIME int
-SWIG_Perl_ConvertPacked(SWIG_MAYBE_PERL_OBJECT SV *obj, void *ptr, int sz, swig_type_info *ty) {
-  swig_cast_info *tc;
-  const char  *c = 0;
-
-  if ((!obj) || (!SvOK(obj))) return SWIG_ERROR;
-  c = SvPV_nolen(obj);
-  /* Pointer values must start with leading underscore */
-  if (*c != '_') return SWIG_ERROR;
-  c++;
-  c = SWIG_UnpackData(c,ptr,sz);
-  if (ty) {
-    tc = SWIG_TypeCheck(c,ty);
-    if (!tc) return SWIG_ERROR;
-  }
-  return SWIG_OK;
-}
-
-
-/* Macros for low-level exception handling */
-#define SWIG_croak(x)    { SWIG_Error(SWIG_RuntimeError, x); SWIG_fail; }
-
-
-typedef XSPROTO(SwigPerlWrapper);
-typedef SwigPerlWrapper *SwigPerlWrapperPtr;
-
-/* Structure for command table */
-typedef struct {
-  const char         *name;
-  SwigPerlWrapperPtr  wrapper;
-} swig_command_info;
-
-/* Information for constant table */
-
-#define SWIG_INT     1
-#define SWIG_FLOAT   2
-#define SWIG_STRING  3
-#define SWIG_POINTER 4
-#define SWIG_BINARY  5
-
-/* Constant information structure */
-typedef struct swig_constant_info {
-    int              type;
-    const char      *name;
-    long             lvalue;
-    double           dvalue;
-    void            *pvalue;
-    swig_type_info **ptype;
-} swig_constant_info;
-
-
-/* Structure for variable table */
-typedef struct {
-  const char   *name;
-  SwigMagicFunc   set;
-  SwigMagicFunc   get;
-  swig_type_info  **type;
-} swig_variable_info;
-
-/* Magic variable code */
-#ifndef PERL_OBJECT
-# ifdef __cplusplus
-#  define swig_create_magic(s,a,b,c) _swig_create_magic(s,const_cast<char*>(a),b,c)
-# else
-#  define swig_create_magic(s,a,b,c) _swig_create_magic(s,(char*)(a),b,c)
-# endif
-# ifndef MULTIPLICITY
-SWIGRUNTIME void _swig_create_magic(SV *sv, char *name, int (*set)(SV *, MAGIC *), int (*get)(SV *,MAGIC *)) 
-# else
-SWIGRUNTIME void _swig_create_magic(SV *sv, char *name, int (*set)(struct interpreter*, SV *, MAGIC *), int (*get)(struct interpreter*, SV *,MAGIC *)) 
-# endif
-#else
-#  define swig_create_magic(s,a,b,c) _swig_create_magic(pPerl,s,a,b,c)
-SWIGRUNTIME void _swig_create_magic(CPerlObj *pPerl, SV *sv, const char *name, int (CPerlObj::*set)(SV *, MAGIC *), int (CPerlObj::*get)(SV *, MAGIC *)) 
-#endif
-{
-  MAGIC *mg;
-  sv_magic(sv,sv,'U',name,strlen(name));
-  mg = mg_find(sv,'U');
-  mg->mg_virtual = (MGVTBL *) malloc(sizeof(MGVTBL));
-  mg->mg_virtual->svt_get = (SwigMagicFunc) get;
-  mg->mg_virtual->svt_set = (SwigMagicFunc) set;
-  mg->mg_virtual->svt_len = 0;
-  mg->mg_virtual->svt_clear = 0;
-  mg->mg_virtual->svt_free = 0;
-}
-
-
-SWIGRUNTIME swig_module_info *
-SWIG_Perl_GetModule(void *SWIGUNUSEDPARM(clientdata)) {
-  static void *type_pointer = (void *)0;
-  SV *pointer;
-
-  /* first check if pointer already created */
-  if (!type_pointer) {
-    pointer = get_sv("swig_runtime_data::type_pointer" SWIG_RUNTIME_VERSION SWIG_TYPE_TABLE_NAME, FALSE | GV_ADDMULTI);
-    if (pointer && SvOK(pointer)) {
-      type_pointer = INT2PTR(swig_type_info **, SvIV(pointer));
-    }
-  }
-
-  return (swig_module_info *) type_pointer;
-}
-
-SWIGRUNTIME void
-SWIG_Perl_SetModule(swig_module_info *module) {
-  SV *pointer;
-
-  /* create a new pointer */
-  pointer = get_sv("swig_runtime_data::type_pointer" SWIG_RUNTIME_VERSION SWIG_TYPE_TABLE_NAME, TRUE | GV_ADDMULTI);
-  sv_setiv(pointer, PTR2IV(module));
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-/* Workaround perl5 global namespace pollution. Note that undefining library
- * functions like fopen will not solve the problem on all platforms as fopen
- * might be a macro on Windows but not necessarily on other operating systems. */
-#ifdef do_open
-  #undef do_open
-#endif
-#ifdef do_close
-  #undef do_close
-#endif
-#ifdef do_exec
-  #undef do_exec
-#endif
-#ifdef scalar
-  #undef scalar
-#endif
-#ifdef list
-  #undef list
-#endif
-#ifdef apply
-  #undef apply
-#endif
-#ifdef convert
-  #undef convert
-#endif
-#ifdef Error
-  #undef Error
-#endif
-#ifdef form
-  #undef form
-#endif
-#ifdef vform
-  #undef vform
-#endif
-#ifdef LABEL
-  #undef LABEL
-#endif
-#ifdef METHOD
-  #undef METHOD
-#endif
-#ifdef Move
-  #undef Move
-#endif
-#ifdef yylex
-  #undef yylex
-#endif
-#ifdef yyparse
-  #undef yyparse
-#endif
-#ifdef yyerror
-  #undef yyerror
-#endif
-#ifdef invert
-  #undef invert
-#endif
-#ifdef ref
-  #undef ref
-#endif
-#ifdef read
-  #undef read
-#endif
-#ifdef write
-  #undef write
-#endif
-#ifdef eof
-  #undef eof
-#endif
-#ifdef close
-  #undef close
-#endif
-#ifdef rewind
-  #undef rewind
-#endif
-#ifdef free
-  #undef free
-#endif
-#ifdef malloc
-  #undef malloc
-#endif
-#ifdef calloc
-  #undef calloc
-#endif
-#ifdef Stat
-  #undef Stat
-#endif
-#ifdef check
-  #undef check
-#endif
-#ifdef seekdir
-  #undef seekdir
-#endif
-#ifdef open
-  #undef open
-#endif
-#ifdef readdir
-  #undef readdir
-#endif
-#ifdef bind
-  #undef bind
-#endif
-#ifdef access
-  #undef access
-#endif
-#ifdef stat
-  #undef stat
-#endif
-
-#ifdef bool
-  /* Leave if macro is from C99 stdbool.h */
-  #ifndef __bool_true_false_are_defined
-    #undef bool
-  #endif
-#endif
-
-
-
-
-#define SWIG_exception_fail(code, msg) do { SWIG_Error(code, msg); SWIG_fail; } while(0) 
-
-#define SWIG_contract_assert(expr, msg) if (!(expr)) { SWIG_Error(SWIG_RuntimeError, msg); SWIG_fail; } else 
-
-
-
-  #define SWIG_exception(code, msg) do { SWIG_Error(code, msg); SWIG_fail;; } while(0) 
-
-
-/* -------- TYPES TABLE (BEGIN) -------- */
-
-#define SWIGTYPE_p_GDALMajorObjectShadow swig_types[0]
-#define SWIGTYPE_p_GDALProgressFunc swig_types[1]
-#define SWIGTYPE_p_GIntBig swig_types[2]
-#define SWIGTYPE_p_OGRDataSourceShadow swig_types[3]
-#define SWIGTYPE_p_OGRDriverShadow swig_types[4]
-#define SWIGTYPE_p_OGRFeatureDefnShadow swig_types[5]
-#define SWIGTYPE_p_OGRFeatureShadow swig_types[6]
-#define SWIGTYPE_p_OGRFieldDefnShadow swig_types[7]
-#define SWIGTYPE_p_OGRGeomFieldDefnShadow swig_types[8]
-#define SWIGTYPE_p_OGRGeometryShadow swig_types[9]
-#define SWIGTYPE_p_OGRLayerShadow swig_types[10]
-#define SWIGTYPE_p_OGRStyleTableShadow swig_types[11]
-#define SWIGTYPE_p_OSRCoordinateTransformationShadow swig_types[12]
-#define SWIGTYPE_p_OSRSpatialReferenceShadow swig_types[13]
-#define SWIGTYPE_p_char swig_types[14]
-#define SWIGTYPE_p_double swig_types[15]
-#define SWIGTYPE_p_f_double_p_q_const__char_p_void__int swig_types[16]
-#define SWIGTYPE_p_float swig_types[17]
-#define SWIGTYPE_p_int swig_types[18]
-#define SWIGTYPE_p_p_char swig_types[19]
-#define SWIGTYPE_p_p_double swig_types[20]
-#define SWIGTYPE_p_p_int swig_types[21]
-#define SWIGTYPE_p_p_p_char swig_types[22]
-static swig_type_info *swig_types[24];
-static swig_module_info swig_module = {swig_types, 23, 0, 0, 0, 0};
-#define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)
-#define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)
-
-/* -------- TYPES TABLE (END) -------- */
-
-#define SWIG_init    boot_Geo__OGR
-
-#define SWIG_name   "Geo::OGRc::boot_Geo__OGR"
-#define SWIG_prefix "Geo::OGRc::"
-
-#define SWIGVERSION 0x020012 
-#define SWIG_VERSION SWIGVERSION
-
-
-#define SWIG_as_voidptr(a) const_cast< void * >(static_cast< const void * >(a)) 
-#define SWIG_as_voidptrptr(a) ((void)SWIG_as_voidptr(*a),reinterpret_cast< void** >(a)) 
-
-
-#include <stdexcept>
-
-
-#ifdef __cplusplus
-extern "C"
-#endif
-#ifndef PERL_OBJECT
-#ifndef MULTIPLICITY
-SWIGEXPORT void SWIG_init (CV* cv);
-#else
-SWIGEXPORT void SWIG_init (pTHXo_ CV* cv);
-#endif
-#else
-SWIGEXPORT void SWIG_init (CV *cv, CPerlObj *);
-#endif
-
-
-typedef char retStringAndCPLFree;
-
-
-#include <iostream>
-using namespace std;
-
-#include "gdal.h"
-#include "ogr_api.h"
-#include "ogr_p.h"
-#include "ogr_core.h"
-#include "cpl_port.h"
-#include "cpl_string.h"
-#include "ogr_srs_api.h"
-
-typedef void GDALMajorObjectShadow;
-
-#ifdef DEBUG 
-typedef struct OGRSpatialReferenceHS OSRSpatialReferenceShadow;
-typedef struct OGRDriverHS OGRDriverShadow;
-typedef struct OGRDataSourceHS OGRDataSourceShadow;
-typedef struct OGRLayerHS OGRLayerShadow;
-typedef struct OGRFeatureHS OGRFeatureShadow;
-typedef struct OGRFeatureDefnHS OGRFeatureDefnShadow;
-typedef struct OGRGeometryHS OGRGeometryShadow;
-typedef struct OGRCoordinateTransformationHS OSRCoordinateTransformationShadow;
-typedef struct OGRCoordinateTransformationHS OGRCoordinateTransformationShadow;
-typedef struct OGRFieldDefnHS OGRFieldDefnShadow;
-#else
-typedef void OSRSpatialReferenceShadow;
-typedef void OGRDriverShadow;
-typedef void OGRDataSourceShadow;
-typedef void OGRLayerShadow;
-typedef void OGRFeatureShadow;
-typedef void OGRFeatureDefnShadow;
-typedef void OGRGeometryShadow;
-typedef void OSRCoordinateTransformationShadow;
-typedef void OGRFieldDefnShadow;
-#endif
-typedef struct OGRStyleTableHS OGRStyleTableShadow;
-typedef struct OGRGeomFieldDefnHS OGRGeomFieldDefnShadow;
-
-
-SWIGINTERNINLINE SV *
-SWIG_From_long  SWIG_PERL_DECL_ARGS_1(long value)
-{
-  SV *sv;
-  if (value >= IV_MIN && value <= IV_MAX)
-    sv = newSViv(value);
-  else
-    sv = newSVpvf("%ld", value);
-  return sv_2mortal(sv);
-}
-
-
-SWIGINTERNINLINE SV *
-SWIG_From_int  SWIG_PERL_DECL_ARGS_1(int value)
-{    
-  return SWIG_From_long  SWIG_PERL_CALL_ARGS_1(value);
-}
-
-
-SWIGINTERNINLINE SV *
-SWIG_FromCharPtrAndSize(const char* carray, size_t size)
-{
-  SV *obj = sv_newmortal();
-  if (carray) {
-    sv_setpvn(obj, carray, size);
-  } else {
-    sv_setsv(obj, &PL_sv_undef);
-  }
-  return obj;
-}
-
-
-SWIGINTERNINLINE SV * 
-SWIG_FromCharPtr(const char *cptr)
-{ 
-  return SWIG_FromCharPtrAndSize(cptr, (cptr ? strlen(cptr) : 0));
-}
-
-
-    #ifndef SWIG
-    typedef struct
-    {
-        SV *fct;
-        SV *data;
-    } SavedEnv;
-    #endif
-    int callback_d_cp_vp(double d, const char *cp, void *vp)
-    {
-        int count, ret;
-        SavedEnv *env_ptr = (SavedEnv *)vp;
-        dSP;
-        ENTER;
-        SAVETMPS;
-        PUSHMARK(SP);
-        XPUSHs(sv_2mortal(newSVnv(d)));
-        XPUSHs(sv_2mortal(newSVpv(cp, 0)));
-        if (env_ptr->data)
-            XPUSHs(env_ptr->data);
-        PUTBACK;
-        count = call_sv(env_ptr->fct, G_SCALAR);
-        SPAGAIN;
-        if (count != 1) {
-            fprintf(stderr, "The callback must return only one value.\n");
-            return 0; /* interrupt */
-        }
-        ret = POPi;
-        PUTBACK;
-        FREETMPS;
-        LEAVE;
-        return ret;
-    }
-
-
-SWIGINTERN int
-SWIG_AsVal_double SWIG_PERL_DECL_ARGS_2(SV *obj, double *val)
-{
-  if (SvNIOK(obj)) {
-    if (val) *val = SvNV(obj);
-    return SWIG_OK;
-  } else if (SvIOK(obj)) {
-    if (val) *val = (double) SvIV(obj);
-    return SWIG_AddCast(SWIG_OK);
-  } else {
-    const char *nptr = SvPV_nolen(obj);
-    if (nptr) {
-      char *endptr;
-      double v;
-      errno = 0;
-      v = strtod(nptr, &endptr);
-      if (errno == ERANGE) {
-	errno = 0;
-	return SWIG_OverflowError;
-      } else {
-	if (*endptr == '\0') {
-	  if (val) *val = v;
-	  return SWIG_Str2NumCast(SWIG_OK);
-	}
-      }
-    }
-  }
-  return SWIG_TypeError;
-}
-
-
-SWIGINTERN swig_type_info*
-SWIG_pchar_descriptor(void)
-{
-  static int init = 0;
-  static swig_type_info* info = 0;
-  if (!init) {
-    info = SWIG_TypeQuery("_p_char");
-    init = 1;
-  }
-  return info;
-}
-
-
-SWIGINTERN int
-SWIG_AsCharPtrAndSize(SV *obj, char** cptr, size_t* psize, int *alloc)
-{
-  if (SvMAGICAL(obj)) {
-     SV *tmp = sv_newmortal();
-     SvSetSV(tmp, obj);
-     obj = tmp;
-  }
-  if (SvPOK(obj)) {
-    STRLEN len = 0;
-    char *cstr = SvPV(obj, len); 
-    size_t size = len + 1;
-    if (cptr)  {
-      if (alloc) {
-	if (*alloc == SWIG_NEWOBJ) {
-	  *cptr = reinterpret_cast< char* >(memcpy((new char[size]), cstr, sizeof(char)*(size)));
-	} else {
-	  *cptr = cstr;
-	  *alloc = SWIG_OLDOBJ;
-	}
-      }
-    }
-    if (psize) *psize = size;
-    return SWIG_OK;
-  } else {
-    swig_type_info* pchar_descriptor = SWIG_pchar_descriptor();
-    if (pchar_descriptor) {
-      char* vptr = 0; 
-      if (SWIG_ConvertPtr(obj, (void**)&vptr, pchar_descriptor, 0) == SWIG_OK) {
-	if (cptr) *cptr = vptr;
-	if (psize) *psize = vptr ? (strlen(vptr) + 1) : 0;
-	if (alloc) *alloc = SWIG_OLDOBJ;
-	return SWIG_OK;
-      }
-    }
-  }
-  return SWIG_TypeError;
-}
-
-
-
-
-
-void VeryQuiteErrorHandler(CPLErr eclass, int code, const char *msg ) {
-  /* If the error class is CE_Fatal, we want to have a message issued
-     because the CPL support code does an abort() before any exception
-     can be generated */
-  if (eclass == CE_Fatal ) {
-    CPLDefaultErrorHandler(eclass, code, msg );
-  }
-}
-
-
-void UseExceptions() {
-  CPLSetErrorHandler( (CPLErrorHandler) VeryQuiteErrorHandler );
-}
-
-void DontUseExceptions() {
-  CPLSetErrorHandler( CPLDefaultErrorHandler );
-}
-
-SWIGINTERN OGRStyleTableShadow *new_OGRStyleTableShadow(){
-        return (OGRStyleTableShadow*) OGR_STBL_Create();
-   }
-SWIGINTERN void delete_OGRStyleTableShadow(OGRStyleTableShadow *self){
-        OGR_STBL_Destroy( (OGRStyleTableH) self );
-   }
-SWIGINTERN int OGRStyleTableShadow_AddStyle(OGRStyleTableShadow *self,char const *pszName,char const *pszStyleString){
-        return OGR_STBL_AddStyle( (OGRStyleTableH) self, pszName, pszStyleString);
-   }
-SWIGINTERN int OGRStyleTableShadow_LoadStyleTable(OGRStyleTableShadow *self,char const *utf8_path){
-        return OGR_STBL_LoadStyleTable( (OGRStyleTableH) self, utf8_path );
-   }
-SWIGINTERN int OGRStyleTableShadow_SaveStyleTable(OGRStyleTableShadow *self,char const *utf8_path){
-        return OGR_STBL_SaveStyleTable( (OGRStyleTableH) self, utf8_path );
-   }
-SWIGINTERN char const *OGRStyleTableShadow_Find(OGRStyleTableShadow *self,char const *pszName){
-        return OGR_STBL_Find( (OGRStyleTableH) self, pszName );
-   }
-SWIGINTERN void OGRStyleTableShadow_ResetStyleStringReading(OGRStyleTableShadow *self){
-        OGR_STBL_ResetStyleStringReading( (OGRStyleTableH) self );
-   }
-SWIGINTERN char const *OGRStyleTableShadow_GetNextStyle(OGRStyleTableShadow *self){
-        return OGR_STBL_GetNextStyle( (OGRStyleTableH) self );
-   }
-SWIGINTERN char const *OGRStyleTableShadow_GetLastStyleName(OGRStyleTableShadow *self){
-        return OGR_STBL_GetLastStyleName( (OGRStyleTableH) self );
-   }
-SWIGINTERN OGRDataSourceShadow *OGRDriverShadow_CreateDataSource(OGRDriverShadow *self,char const *utf8_path,char **options=0){
-    OGRDataSourceShadow *ds = (OGRDataSourceShadow*) OGR_Dr_CreateDataSource( self, utf8_path, options);
-    return ds;
-  }
-SWIGINTERN OGRDataSourceShadow *OGRDriverShadow_CopyDataSource(OGRDriverShadow *self,OGRDataSourceShadow *copy_ds,char const *utf8_path,char **options=0){
-    OGRDataSourceShadow *ds = (OGRDataSourceShadow*) OGR_Dr_CopyDataSource(self, copy_ds, utf8_path, options);
-    return ds;
-  }
-
-#include <limits.h>
-#if !defined(SWIG_NO_LLONG_MAX)
-# if !defined(LLONG_MAX) && defined(__GNUC__) && defined (__LONG_LONG_MAX__)
-#   define LLONG_MAX __LONG_LONG_MAX__
-#   define LLONG_MIN (-LLONG_MAX - 1LL)
-#   define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL)
-# endif
-#endif
-
-
-#include <float.h>
-
-
-#include <math.h>
-
-
-SWIGINTERNINLINE int
-SWIG_CanCastAsInteger(double *d, double min, double max) {
-  double x = *d;
-  if ((min <= x && x <= max)) {
-   double fx = floor(x);
-   double cx = ceil(x);
-   double rd =  ((x - fx) < 0.5) ? fx : cx; /* simple rint */
-   if ((errno == EDOM) || (errno == ERANGE)) {
-     errno = 0;
-   } else {
-     double summ, reps, diff;
-     if (rd < x) {
-       diff = x - rd;
-     } else if (rd > x) {
-       diff = rd - x;
-     } else {
-       return 1;
-     }
-     summ = rd + x;
-     reps = diff/summ;
-     if (reps < 8*DBL_EPSILON) {
-       *d = rd;
-       return 1;
-     }
-   }
-  }
-  return 0;
-}
-
-
-SWIGINTERN int
-SWIG_AsVal_long SWIG_PERL_DECL_ARGS_2(SV *obj, long* val)
-{
-  if (SvUOK(obj)) {
-    UV v = SvUV(obj);
-    if (v <= LONG_MAX) {
-      if (val) *val = v;
-      return SWIG_OK;
-    }
-    return SWIG_OverflowError;
-  } else if (SvIOK(obj)) {
-    IV v = SvIV(obj);
-    if (v >= LONG_MIN && v <= LONG_MAX) {
-      if(val) *val = v;
-      return SWIG_OK;
-    }
-    return SWIG_OverflowError;
-  } else {
-    int dispatch = 0;
-    const char *nptr = SvPV_nolen(obj);
-    if (nptr) {
-      char *endptr;
-      long v;
-      errno = 0;
-      v = strtol(nptr, &endptr,0);
-      if (errno == ERANGE) {
-	errno = 0;
-	return SWIG_OverflowError;
-      } else {
-	if (*endptr == '\0') {
-	  if (val) *val = v;
-	  return SWIG_Str2NumCast(SWIG_OK);
-	}
-      }
-    }
-    if (!dispatch) {
-      double d;
-      int res = SWIG_AddCast(SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(obj,&d));
-      if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LONG_MIN, LONG_MAX)) {
-	if (val) *val = (long)(d);
-	return res;
-      }
-    }
-  }
-  return SWIG_TypeError;
-}
-
-
-SWIGINTERN int
-SWIG_AsVal_int SWIG_PERL_DECL_ARGS_2(SV * obj, int *val)
-{
-  long v;
-  int res = SWIG_AsVal_long SWIG_PERL_CALL_ARGS_2(obj, &v);
-  if (SWIG_IsOK(res)) {
-    if ((v < INT_MIN || v > INT_MAX)) {
-      return SWIG_OverflowError;
-    } else {
-      if (val) *val = static_cast< int >(v);
-    }
-  }  
-  return res;
-}
-
-SWIGINTERN OGRDataSourceShadow *OGRDriverShadow_Open(OGRDriverShadow *self,char const *utf8_path,int update=0){
-    CPLErrorReset();
-    OGRDataSourceShadow* ds = (OGRDataSourceShadow*) OGR_Dr_Open(self, utf8_path, update);
-    if( CPLGetLastErrorType() == CE_Failure && ds != NULL )
-    {
-        CPLDebug(
-            "SWIG",
-            "OGR_Dr_Open() succeeded, but an error is posted, so we destroy"
-            " the datasource and fail at swig level.\nError:%s",
-            CPLGetLastErrorMsg() );
-        OGRReleaseDataSource(ds);
-        ds = NULL;
-    }
-    return ds;
-  }
-SWIGINTERN int OGRDriverShadow_DeleteDataSource(OGRDriverShadow *self,char const *utf8_path){
-
-    return OGR_Dr_DeleteDataSource( self, utf8_path );
-  }
-SWIGINTERN bool OGRDriverShadow_TestCapability(OGRDriverShadow *self,char const *cap){
-    return (OGR_Dr_TestCapability(self, cap) > 0);
-  }
-
-SWIGINTERNINLINE SV *
-SWIG_From_bool  SWIG_PERL_DECL_ARGS_1(bool value)
-{
-  return boolSV(value);
-}
-
-SWIGINTERN char const *OGRDriverShadow_GetName(OGRDriverShadow *self){
-    return OGR_Dr_GetName( self );
-  }
-SWIGINTERN void OGRDriverShadow_Register(OGRDriverShadow *self){
-    OGRRegisterDriver( self );
-  }
-SWIGINTERN void OGRDriverShadow_Deregister(OGRDriverShadow *self){
-    OGRDeregisterDriver( self );
-  }
-SWIGINTERN void delete_OGRDataSourceShadow(OGRDataSourceShadow *self){
-    OGRReleaseDataSource(self);
-  }
-SWIGINTERN int OGRDataSourceShadow_GetRefCount(OGRDataSourceShadow *self){
-    return OGR_DS_GetRefCount(self);
-  }
-SWIGINTERN int OGRDataSourceShadow_GetSummaryRefCount(OGRDataSourceShadow *self){
-    return OGR_DS_GetSummaryRefCount(self);
-  }
-SWIGINTERN int OGRDataSourceShadow_GetLayerCount(OGRDataSourceShadow *self){
-    return OGR_DS_GetLayerCount(self);
-  }
-SWIGINTERN OGRDriverShadow *OGRDataSourceShadow_GetDriver(OGRDataSourceShadow *self){
-    return (OGRDriverShadow *) OGR_DS_GetDriver( self );
-  }
-SWIGINTERN char const *OGRDataSourceShadow_GetName(OGRDataSourceShadow *self){
-    return OGR_DS_GetName(self);
-  }
-SWIGINTERN OGRErr OGRDataSourceShadow_DeleteLayer(OGRDataSourceShadow *self,int index){
-    return OGR_DS_DeleteLayer(self, index);
-  }
-
-
-#include "ogr_core.h"
-static char const *
-OGRErrMessages( int rc ) {
-  switch( rc ) {
-  case OGRERR_NONE:
-    return "OGR Error: None";
-  case OGRERR_NOT_ENOUGH_DATA:
-    return "OGR Error: Not enough data to deserialize";
-  case OGRERR_NOT_ENOUGH_MEMORY:
-    return "OGR Error: Not enough memory";
-  case OGRERR_UNSUPPORTED_GEOMETRY_TYPE:
-    return "OGR Error: Unsupported geometry type";
-  case OGRERR_UNSUPPORTED_OPERATION:
-    return "OGR Error: Unsupported operation";
-  case OGRERR_CORRUPT_DATA:
-    return "OGR Error: Corrupt data";
-  case OGRERR_FAILURE:
-    return "OGR Error: General Error";
-  case OGRERR_UNSUPPORTED_SRS:
-    return "OGR Error: Unsupported SRS";
-  case OGRERR_INVALID_HANDLE:
-    return "OGR Error: Invalid handle";
-  case OGRERR_NON_EXISTING_FEATURE:
-    return "OGR Error: Non existing feature";
-  default:
-    return "OGR Error: Unknown";
-  }
-}
-
-SWIGINTERN OGRErr OGRDataSourceShadow_SyncToDisk(OGRDataSourceShadow *self){
-    return OGR_DS_SyncToDisk(self);
-  }
-SWIGINTERN void OGRDataSourceShadow_FlushCache(OGRDataSourceShadow *self){
-    GDALFlushCache( self );
-  }
-SWIGINTERN OGRLayerShadow *OGRDataSourceShadow_CreateLayer(OGRDataSourceShadow *self,char const *name,OSRSpatialReferenceShadow *srs=NULL,OGRwkbGeometryType geom_type=wkbUnknown,char **options=0){
-    OGRLayerShadow* layer = (OGRLayerShadow*) OGR_DS_CreateLayer( self,
-								  name,
-								  srs,
-								  geom_type,
-								  options);
-    return layer;
-  }
-SWIGINTERN OGRLayerShadow *OGRDataSourceShadow_CopyLayer(OGRDataSourceShadow *self,OGRLayerShadow *src_layer,char const *new_name,char **options=0){
-    OGRLayerShadow* layer = (OGRLayerShadow*) OGR_DS_CopyLayer( self,
-                                                      src_layer,
-                                                      new_name,
-                                                      options);
-    return layer;
-  }
-SWIGINTERN OGRLayerShadow *OGRDataSourceShadow_GetLayerByIndex(OGRDataSourceShadow *self,int index=0){
-
-    OGRLayerShadow* layer = (OGRLayerShadow*) OGR_DS_GetLayer(self, index);
-    return layer;
-  }
-SWIGINTERN OGRLayerShadow *OGRDataSourceShadow_GetLayerByName(OGRDataSourceShadow *self,char const *layer_name){
-    OGRLayerShadow* layer = (OGRLayerShadow*) OGR_DS_GetLayerByName(self, layer_name);
-    return layer;
-  }
-SWIGINTERN bool OGRDataSourceShadow_TestCapability(OGRDataSourceShadow *self,char const *cap){
-    return (OGR_DS_TestCapability(self, cap) > 0);
-  }
-SWIGINTERN OGRLayerShadow *OGRDataSourceShadow_ExecuteSQL(OGRDataSourceShadow *self,char const *statement,OGRGeometryShadow *spatialFilter=NULL,char const *dialect=""){
-    OGRLayerShadow* layer = (OGRLayerShadow*) OGR_DS_ExecuteSQL((OGRDataSourceShadow*)self,
-                                                      statement,
-                                                      spatialFilter,
-                                                      dialect);
-    return layer;
-  }
-SWIGINTERN void OGRDataSourceShadow_ReleaseResultSet(OGRDataSourceShadow *self,OGRLayerShadow *layer){
-    OGR_DS_ReleaseResultSet(self, layer);
-  }
-SWIGINTERN OGRStyleTableShadow *OGRDataSourceShadow_GetStyleTable(OGRDataSourceShadow *self){
-    return (OGRStyleTableShadow*) OGR_DS_GetStyleTable(self);
-  }
-SWIGINTERN void OGRDataSourceShadow_SetStyleTable(OGRDataSourceShadow *self,OGRStyleTableShadow *table){
-    if( table != NULL )
-        OGR_DS_SetStyleTable(self, (OGRStyleTableH) table);
-  }
-SWIGINTERN OGRErr OGRDataSourceShadow_StartTransaction(OGRDataSourceShadow *self,int force=FALSE){
-    return GDALDatasetStartTransaction(self, force);
-  }
-SWIGINTERN OGRErr OGRDataSourceShadow_CommitTransaction(OGRDataSourceShadow *self){
-    return GDALDatasetCommitTransaction(self);
-  }
-SWIGINTERN OGRErr OGRDataSourceShadow_RollbackTransaction(OGRDataSourceShadow *self){
-    return GDALDatasetRollbackTransaction(self);
-  }
-SWIGINTERN int OGRLayerShadow_GetRefCount(OGRLayerShadow *self){
-    return OGR_L_GetRefCount(self);
-  }
-SWIGINTERN void OGRLayerShadow_SetSpatialFilter__SWIG_0(OGRLayerShadow *self,OGRGeometryShadow *filter){
-    OGR_L_SetSpatialFilter (self, filter);
-  }
-SWIGINTERN void OGRLayerShadow_SetSpatialFilterRect__SWIG_0(OGRLayerShadow *self,double minx,double miny,double maxx,double maxy){
-    OGR_L_SetSpatialFilterRect(self, minx, miny, maxx, maxy);
-  }
-SWIGINTERN void OGRLayerShadow_SetSpatialFilter__SWIG_1(OGRLayerShadow *self,int iGeomField,OGRGeometryShadow *filter){
-    OGR_L_SetSpatialFilterEx (self, iGeomField, filter);
-  }
-SWIGINTERN void OGRLayerShadow_SetSpatialFilterRect__SWIG_1(OGRLayerShadow *self,int iGeomField,double minx,double miny,double maxx,double maxy){
-    OGR_L_SetSpatialFilterRectEx(self, iGeomField, minx, miny, maxx, maxy);
-  }
-SWIGINTERN OGRGeometryShadow *OGRLayerShadow_GetSpatialFilter(OGRLayerShadow *self){
-    return (OGRGeometryShadow *) OGR_L_GetSpatialFilter(self);
-  }
-SWIGINTERN OGRErr OGRLayerShadow_SetAttributeFilter(OGRLayerShadow *self,char *filter_string){
-    return OGR_L_SetAttributeFilter((OGRLayerShadow*)self, filter_string);
-  }
-SWIGINTERN void OGRLayerShadow_ResetReading(OGRLayerShadow *self){
-    OGR_L_ResetReading(self);
-  }
-SWIGINTERN char const *OGRLayerShadow_GetName(OGRLayerShadow *self){
-    return OGR_L_GetName(self);
-  }
-SWIGINTERN OGRwkbGeometryType OGRLayerShadow_GetGeomType(OGRLayerShadow *self){
-    return (OGRwkbGeometryType) OGR_L_GetGeomType(self);
-  }
-SWIGINTERN char const *OGRLayerShadow_GetGeometryColumn(OGRLayerShadow *self){
-    return OGR_L_GetGeometryColumn(self);
-  }
-SWIGINTERN char const *OGRLayerShadow_GetFIDColumn(OGRLayerShadow *self){
-    return OGR_L_GetFIDColumn(self);
-  }
-SWIGINTERN OGRFeatureShadow *OGRLayerShadow_GetFeature(OGRLayerShadow *self,GIntBig fid){
-    return (OGRFeatureShadow*) OGR_L_GetFeature(self, fid);
-  }
-SWIGINTERN OGRFeatureShadow *OGRLayerShadow_GetNextFeature(OGRLayerShadow *self){
-    return (OGRFeatureShadow*) OGR_L_GetNextFeature(self);
-  }
-SWIGINTERN OGRErr OGRLayerShadow_SetNextByIndex(OGRLayerShadow *self,GIntBig new_index){
-    return OGR_L_SetNextByIndex(self, new_index);
-  }
-SWIGINTERN OGRErr OGRLayerShadow_SetFeature(OGRLayerShadow *self,OGRFeatureShadow *feature){
-    return OGR_L_SetFeature(self, feature);
-  }
-SWIGINTERN OGRErr OGRLayerShadow_CreateFeature(OGRLayerShadow *self,OGRFeatureShadow *feature){
-    return OGR_L_CreateFeature(self, feature);
-  }
-SWIGINTERN OGRErr OGRLayerShadow_DeleteFeature(OGRLayerShadow *self,GIntBig fid){
-    return OGR_L_DeleteFeature(self, fid);
-  }
-SWIGINTERN OGRErr OGRLayerShadow_SyncToDisk(OGRLayerShadow *self){
-    return OGR_L_SyncToDisk(self);
-  }
-SWIGINTERN OGRFeatureDefnShadow *OGRLayerShadow_GetLayerDefn(OGRLayerShadow *self){
-    return (OGRFeatureDefnShadow*) OGR_L_GetLayerDefn(self);
-  }
-SWIGINTERN GIntBig OGRLayerShadow_GetFeatureCount(OGRLayerShadow *self,int force=1){
-    return OGR_L_GetFeatureCount(self, force);
-  }
-
-static SV *
-CreateArrayFromDoubleArray( double *first, unsigned int size ) {
-  AV *av = (AV*)sv_2mortal((SV*)newAV());
-  for( unsigned int i=0; i<size; i++ ) {
-    av_store(av,i,newSVnv(*first));
-    ++first;
-  }
-  return sv_2mortal(newRV((SV*)av));
-}
-
-SWIGINTERN OGRErr OGRLayerShadow_GetExtent(OGRLayerShadow *self,double argout[4],int force=1){
-
-
-
-    return OGR_L_GetExtent(self, (OGREnvelope*)argout, force);
-  }
-SWIGINTERN bool OGRLayerShadow_TestCapability(OGRLayerShadow *self,char const *cap){
-    return (OGR_L_TestCapability(self, cap) > 0);
-  }
-SWIGINTERN OGRErr OGRLayerShadow_CreateField(OGRLayerShadow *self,OGRFieldDefnShadow *field_def,int approx_ok=1){
-    return OGR_L_CreateField(self, field_def, approx_ok);
-  }
-SWIGINTERN OGRErr OGRLayerShadow_DeleteField(OGRLayerShadow *self,int iField){
-    return OGR_L_DeleteField(self, iField);
-  }
-SWIGINTERN OGRErr OGRLayerShadow_ReorderField(OGRLayerShadow *self,int iOldFieldPos,int iNewFieldPos){
-    return OGR_L_ReorderField(self, iOldFieldPos, iNewFieldPos);
-  }
-SWIGINTERN OGRErr OGRLayerShadow_ReorderFields(OGRLayerShadow *self,int nList,int *pList){
-    if (nList != OGR_FD_GetFieldCount(OGR_L_GetLayerDefn(self)))
-    {
-      CPLError(CE_Failure, CPLE_IllegalArg,
-               "List should have %d elements",
-               OGR_FD_GetFieldCount(OGR_L_GetLayerDefn(self)));
-      return OGRERR_FAILURE;
-    }
-    return OGR_L_ReorderFields(self, pList);
-  }
-SWIGINTERN OGRErr OGRLayerShadow_AlterFieldDefn(OGRLayerShadow *self,int iField,OGRFieldDefnShadow *field_def,int nFlags){
-    return OGR_L_AlterFieldDefn(self, iField, field_def, nFlags);
-  }
-SWIGINTERN OGRErr OGRLayerShadow_CreateGeomField(OGRLayerShadow *self,OGRGeomFieldDefnShadow *field_def,int approx_ok=1){
-    return OGR_L_CreateGeomField(self, field_def, approx_ok);
-  }
-SWIGINTERN OGRErr OGRLayerShadow_StartTransaction(OGRLayerShadow *self){
-    return OGR_L_StartTransaction(self);
-  }
-SWIGINTERN OGRErr OGRLayerShadow_CommitTransaction(OGRLayerShadow *self){
-    return OGR_L_CommitTransaction(self);
-  }
-SWIGINTERN OGRErr OGRLayerShadow_RollbackTransaction(OGRLayerShadow *self){
-    return OGR_L_RollbackTransaction(self);
-  }
-SWIGINTERN int OGRLayerShadow_FindFieldIndex(OGRLayerShadow *self,char const *pszFieldName,int bExactMatch){
-    return OGR_L_FindFieldIndex(self, pszFieldName, bExactMatch );
-  }
-SWIGINTERN OSRSpatialReferenceShadow *OGRLayerShadow_GetSpatialRef(OGRLayerShadow *self){
-    OGRSpatialReferenceH ref =  OGR_L_GetSpatialRef(self);
-    if( ref )
-        OSRReference(ref);
-    return (OSRSpatialReferenceShadow*) ref;
-  }
-SWIGINTERN GIntBig OGRLayerShadow_GetFeaturesRead(OGRLayerShadow *self){
-    return OGR_L_GetFeaturesRead(self);
-  }
-SWIGINTERN OGRErr OGRLayerShadow_SetIgnoredFields(OGRLayerShadow *self,char const **options){
-    return OGR_L_SetIgnoredFields( self, options );
-  }
-SWIGINTERN OGRErr OGRLayerShadow_Intersection(OGRLayerShadow *self,OGRLayerShadow *method_layer,OGRLayerShadow *result_layer,char **options=NULL,GDALProgressFunc callback=NULL,void *callback_data=NULL){
-    return OGR_L_Intersection( self, method_layer, result_layer, options, callback, callback_data );
-  }
-SWIGINTERN OGRErr OGRLayerShadow_Union(OGRLayerShadow *self,OGRLayerShadow *method_layer,OGRLayerShadow *result_layer,char **options=NULL,GDALProgressFunc callback=NULL,void *callback_data=NULL){
-    return OGR_L_Union( self, method_layer, result_layer, options, callback, callback_data );
-  }
-SWIGINTERN OGRErr OGRLayerShadow_SymDifference(OGRLayerShadow *self,OGRLayerShadow *method_layer,OGRLayerShadow *result_layer,char **options=NULL,GDALProgressFunc callback=NULL,void *callback_data=NULL){
-    return OGR_L_SymDifference( self, method_layer, result_layer, options, callback, callback_data );
-  }
-SWIGINTERN OGRErr OGRLayerShadow_Identity(OGRLayerShadow *self,OGRLayerShadow *method_layer,OGRLayerShadow *result_layer,char **options=NULL,GDALProgressFunc callback=NULL,void *callback_data=NULL){
-    return OGR_L_Identity( self, method_layer, result_layer, options, callback, callback_data );
-  }
-SWIGINTERN OGRErr OGRLayerShadow_Update(OGRLayerShadow *self,OGRLayerShadow *method_layer,OGRLayerShadow *result_layer,char **options=NULL,GDALProgressFunc callback=NULL,void *callback_data=NULL){
-    return OGR_L_Update( self, method_layer, result_layer, options, callback, callback_data );
-  }
-SWIGINTERN OGRErr OGRLayerShadow_Clip(OGRLayerShadow *self,OGRLayerShadow *method_layer,OGRLayerShadow *result_layer,char **options=NULL,GDALProgressFunc callback=NULL,void *callback_data=NULL){
-    return OGR_L_Clip( self, method_layer, result_layer, options, callback, callback_data );
-  }
-SWIGINTERN OGRErr OGRLayerShadow_Erase(OGRLayerShadow *self,OGRLayerShadow *method_layer,OGRLayerShadow *result_layer,char **options=NULL,GDALProgressFunc callback=NULL,void *callback_data=NULL){
-    return OGR_L_Erase( self, method_layer, result_layer, options, callback, callback_data );
-  }
-SWIGINTERN OGRStyleTableShadow *OGRLayerShadow_GetStyleTable(OGRLayerShadow *self){
-    return (OGRStyleTableShadow*) OGR_L_GetStyleTable(self);
-  }
-SWIGINTERN void OGRLayerShadow_SetStyleTable(OGRLayerShadow *self,OGRStyleTableShadow *table){
-    if( table != NULL )
-        OGR_L_SetStyleTable(self, (OGRStyleTableH) table);
-  }
-SWIGINTERN void delete_OGRFeatureShadow(OGRFeatureShadow *self){
-    OGR_F_Destroy(self);
-  }
-SWIGINTERN OGRFeatureShadow *new_OGRFeatureShadow(OGRFeatureDefnShadow *feature_def){
-      return (OGRFeatureShadow*) OGR_F_Create( feature_def );
-  }
-SWIGINTERN OGRFeatureDefnShadow *OGRFeatureShadow_GetDefnRef(OGRFeatureShadow *self){
-    return (OGRFeatureDefnShadow*) OGR_F_GetDefnRef(self);
-  }
-SWIGINTERN OGRErr OGRFeatureShadow_SetGeometry(OGRFeatureShadow *self,OGRGeometryShadow *geom){
-    return OGR_F_SetGeometry(self, geom);
-  }
-SWIGINTERN OGRErr OGRFeatureShadow_SetGeometryDirectly(OGRFeatureShadow *self,OGRGeometryShadow *geom){
-    return OGR_F_SetGeometryDirectly(self, geom);
-  }
-SWIGINTERN OGRGeometryShadow *OGRFeatureShadow_GetGeometryRef(OGRFeatureShadow *self){
-    return (OGRGeometryShadow*) OGR_F_GetGeometryRef(self);
-  }
-SWIGINTERN OGRErr OGRFeatureShadow_SetGeomField__SWIG_0(OGRFeatureShadow *self,int iField,OGRGeometryShadow *geom){
-    return OGR_F_SetGeomField(self, iField, geom);
-  }
-SWIGINTERN OGRErr OGRFeatureShadow_SetGeomField__SWIG_1(OGRFeatureShadow *self,char const *name,OGRGeometryShadow *geom){
-      int iField = OGR_F_GetGeomFieldIndex(self, name);
-      if (iField == -1)
-      {
-        CPLError(CE_Failure, 1, "No such field: '%s'", name);
-        return OGRERR_FAILURE;
-      }
-      else
-        return OGR_F_SetGeomField(self, iField, geom);
-  }
-SWIGINTERN OGRErr OGRFeatureShadow_SetGeomFieldDirectly__SWIG_0(OGRFeatureShadow *self,int iField,OGRGeometryShadow *geom){
-    return OGR_F_SetGeomFieldDirectly(self, iField, geom);
-  }
-SWIGINTERN OGRErr OGRFeatureShadow_SetGeomFieldDirectly__SWIG_1(OGRFeatureShadow *self,char const *name,OGRGeometryShadow *geom){
-      int iField = OGR_F_GetGeomFieldIndex(self, name);
-      if (iField == -1)
-      {
-        CPLError(CE_Failure, 1, "No such field: '%s'", name);
-        return OGRERR_FAILURE;
-      }
-      else
-        return OGR_F_SetGeomFieldDirectly(self, iField, geom);
-  }
-SWIGINTERN OGRGeometryShadow *OGRFeatureShadow_GetGeomFieldRef__SWIG_0(OGRFeatureShadow *self,int iField){
-    return (OGRGeometryShadow*) OGR_F_GetGeomFieldRef(self, iField);
-  }
-SWIGINTERN OGRGeometryShadow *OGRFeatureShadow_GetGeomFieldRef__SWIG_1(OGRFeatureShadow *self,char const *name){
-    int i = OGR_F_GetGeomFieldIndex(self, name);
-    if (i == -1)
-    {
-      CPLError(CE_Failure, 1, "No such field: '%s'", name);
-      return NULL;
-    }
-    else
-      return (OGRGeometryShadow*) OGR_F_GetGeomFieldRef(self, i);
-  }
-SWIGINTERN OGRFeatureShadow *OGRFeatureShadow_Clone(OGRFeatureShadow *self){
-    return (OGRFeatureShadow*) OGR_F_Clone(self);
-  }
-SWIGINTERN bool OGRFeatureShadow_Equal(OGRFeatureShadow *self,OGRFeatureShadow *feature){
-    return (OGR_F_Equal(self, feature) > 0);
-  }
-SWIGINTERN int OGRFeatureShadow_GetFieldCount(OGRFeatureShadow *self){
-    return OGR_F_GetFieldCount(self);
-  }
-SWIGINTERN OGRFieldDefnShadow *OGRFeatureShadow_GetFieldDefnRef__SWIG_0(OGRFeatureShadow *self,int id){
-    return (OGRFieldDefnShadow *) OGR_F_GetFieldDefnRef(self, id);
-  }
-SWIGINTERN OGRFieldDefnShadow *OGRFeatureShadow_GetFieldDefnRef__SWIG_1(OGRFeatureShadow *self,char const *name){
-      int i = OGR_F_GetFieldIndex(self, name);
-      if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
-      else
-	  return (OGRFieldDefnShadow *) OGR_F_GetFieldDefnRef(self, i);
-      return NULL;
-  }
-SWIGINTERN int OGRFeatureShadow_GetGeomFieldCount(OGRFeatureShadow *self){
-    return OGR_F_GetGeomFieldCount(self);
-  }
-SWIGINTERN OGRGeomFieldDefnShadow *OGRFeatureShadow_GetGeomFieldDefnRef__SWIG_0(OGRFeatureShadow *self,int id){
-    return (OGRGeomFieldDefnShadow *) OGR_F_GetGeomFieldDefnRef(self, id);
-  }
-SWIGINTERN OGRGeomFieldDefnShadow *OGRFeatureShadow_GetGeomFieldDefnRef__SWIG_1(OGRFeatureShadow *self,char const *name){
-      int i = OGR_F_GetGeomFieldIndex(self, name);
-      if (i == -1)
-      CPLError(CE_Failure, 1, "No such field: '%s'", name);
-      else
-      return (OGRGeomFieldDefnShadow *) OGR_F_GetGeomFieldDefnRef(self, i);
-      return NULL;
-  }
-SWIGINTERN char const *OGRFeatureShadow_GetFieldAsString(OGRFeatureShadow *self,int id){
-    return (const char *) OGR_F_GetFieldAsString(self, id);
-  }
-SWIGINTERN int OGRFeatureShadow_GetFieldAsInteger(OGRFeatureShadow *self,int id){
-    return OGR_F_GetFieldAsInteger(self, id);
-  }
-SWIGINTERN GIntBig OGRFeatureShadow_GetFieldAsInteger64(OGRFeatureShadow *self,int id){
-    return OGR_F_GetFieldAsInteger64(self, id);
-  }
-SWIGINTERN double OGRFeatureShadow_GetFieldAsDouble(OGRFeatureShadow *self,int id){
-    return OGR_F_GetFieldAsDouble(self, id);
-  }
-
-SWIGINTERNINLINE SV *
-SWIG_From_double  SWIG_PERL_DECL_ARGS_1(double value)
-{
-  return sv_2mortal(newSVnv(value));
-}
-
-
-SWIGINTERNINLINE SV *
-SWIG_From_float  SWIG_PERL_DECL_ARGS_1(float value)
-{    
-  return SWIG_From_double  SWIG_PERL_CALL_ARGS_1(value);
-}
-
-SWIGINTERN void OGRFeatureShadow_GetFieldAsDateTime(OGRFeatureShadow *self,int id,int *pnYear,int *pnMonth,int *pnDay,int *pnHour,int *pnMinute,float *pfSecond,int *pnTZFlag){
-      OGR_F_GetFieldAsDateTimeEx(self, id, pnYear, pnMonth, pnDay,
-			       pnHour, pnMinute, pfSecond,
-			       pnTZFlag);
-  }
-
-static SV *
-CreateArrayFromIntArray( int *first, unsigned int size ) {
-  AV *av = (AV*)sv_2mortal((SV*)newAV());
-  for( unsigned int i=0; i<size; i++ ) {
-    av_store(av,i,newSViv(*first));
-    ++first;
-  }
-  return sv_2mortal(newRV((SV*)av));
-}
-
-SWIGINTERN void OGRFeatureShadow_GetFieldAsIntegerList(OGRFeatureShadow *self,int id,int *nLen,int const **pList){
-      *pList = OGR_F_GetFieldAsIntegerList(self, id, nLen);
-  }
-SWIGINTERN void OGRFeatureShadow_GetFieldAsDoubleList(OGRFeatureShadow *self,int id,int *nLen,double const **pList){
-      *pList = OGR_F_GetFieldAsDoubleList(self, id, nLen);
-  }
-
-static SV *
-CreateArrayFromStringArray( char **first ) {
-  AV *av = (AV*)sv_2mortal((SV*)newAV());
-  for( unsigned int i = 0; *first != NULL; i++ ) {
-    SV *sv = newSVpv(*first, strlen(*first));
-    SvUTF8_on(sv); /* expecting UTF-8 from GDAL */
-    av_store(av,i,sv);
-    ++first;
-  }
-  return sv_2mortal(newRV((SV*)av));
-}
-
-SWIGINTERN void OGRFeatureShadow_GetFieldAsStringList(OGRFeatureShadow *self,int id,char ***pList){
-      *pList = OGR_F_GetFieldAsStringList(self, id);
-  }
-SWIGINTERN OGRErr OGRFeatureShadow_GetFieldAsBinary(OGRFeatureShadow *self,int id,int *nLen,char **pBuf){
-    GByte* pabyBlob = OGR_F_GetFieldAsBinary(self, id, nLen);
-    *pBuf = (char*)malloc(*nLen);
-    memcpy(*pBuf, pabyBlob, *nLen);
-    return OGRERR_NONE;
-  }
-SWIGINTERN bool OGRFeatureShadow_IsFieldSet__SWIG_0(OGRFeatureShadow *self,int id){
-    return (OGR_F_IsFieldSet(self, id) > 0);
-  }
-SWIGINTERN bool OGRFeatureShadow_IsFieldSet__SWIG_1(OGRFeatureShadow *self,char const *name){
-      int i = OGR_F_GetFieldIndex(self, name);
-      if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
-      else
-	  return (OGR_F_IsFieldSet(self, i) > 0);
-      return false;
-  }
-SWIGINTERN int OGRFeatureShadow_GetFieldIndex(OGRFeatureShadow *self,char const *name){
-      return OGR_F_GetFieldIndex(self, name);
-  }
-SWIGINTERN int OGRFeatureShadow_GetGeomFieldIndex(OGRFeatureShadow *self,char const *name){
-      return OGR_F_GetGeomFieldIndex(self, name);
-  }
-SWIGINTERN GIntBig OGRFeatureShadow_GetFID(OGRFeatureShadow *self){
-    return OGR_F_GetFID(self);
-  }
-SWIGINTERN OGRErr OGRFeatureShadow_SetFID(OGRFeatureShadow *self,GIntBig fid){
-    return OGR_F_SetFID(self, fid);
-  }
-SWIGINTERN void OGRFeatureShadow_DumpReadable(OGRFeatureShadow *self){
-    OGR_F_DumpReadable(self, NULL);
-  }
-SWIGINTERN void OGRFeatureShadow_UnsetField(OGRFeatureShadow *self,int id){
-    OGR_F_UnsetField(self, id);
-  }
-SWIGINTERN void OGRFeatureShadow_SetField__SWIG_0(OGRFeatureShadow *self,int id,char const *value){
-    OGR_F_SetFieldString(self, id, value);
-  }
-SWIGINTERN void OGRFeatureShadow_SetFieldInteger64(OGRFeatureShadow *self,int id,GIntBig value){
-    OGR_F_SetFieldInteger64(self, id, value);
-  }
-SWIGINTERN void OGRFeatureShadow_SetField__SWIG_1(OGRFeatureShadow *self,int id,int value){
-    OGR_F_SetFieldInteger(self, id, value);
-  }
-SWIGINTERN void OGRFeatureShadow_SetField__SWIG_2(OGRFeatureShadow *self,int id,double value){
-    OGR_F_SetFieldDouble(self, id, value);
-  }
-
-/* Getting isfinite working pre C99 across multiple platforms is non-trivial. Users can provide SWIG_isfinite on older platforms. */
-#ifndef SWIG_isfinite
-# if defined(isfinite)
-#  define SWIG_isfinite(X) (isfinite(X))
-# elif defined(_MSC_VER)
-#  define SWIG_isfinite(X) (_finite(X))
-# elif defined(__sun) && defined(__SVR4)
-#  include <ieeefp.h>
-#  define SWIG_isfinite(X) (finite(X))
-# endif
-#endif
-
-
-/* Accept infinite as a valid float value unless we are unable to check if a value is finite */
-#ifdef SWIG_isfinite
-# define SWIG_Float_Overflow_Check(X) ((X < -FLT_MAX || X > FLT_MAX) && SWIG_isfinite(X))
-#else
-# define SWIG_Float_Overflow_Check(X) ((X < -FLT_MAX || X > FLT_MAX))
-#endif
-
-
-SWIGINTERN int
-SWIG_AsVal_float SWIG_PERL_DECL_ARGS_2(SV * obj, float *val)
-{
-  double v;
-  int res = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(obj, &v);
-  if (SWIG_IsOK(res)) {
-    if (SWIG_Float_Overflow_Check(v)) {
-      return SWIG_OverflowError;
-    } else {
-      if (val) *val = static_cast< float >(v);
-    }
-  }  
-  return res;
-}
-
-SWIGINTERN void OGRFeatureShadow_SetField__SWIG_3(OGRFeatureShadow *self,int id,int year,int month,int day,int hour,int minute,float second,int tzflag){
-    OGR_F_SetFieldDateTimeEx(self, id, year, month, day,
-                             hour, minute, second, 
-                             tzflag);
-  }
-SWIGINTERN void OGRFeatureShadow_SetFieldIntegerList(OGRFeatureShadow *self,int id,int nList,int *pList){
-      OGR_F_SetFieldIntegerList(self, id, nList, pList);
-  }
-SWIGINTERN void OGRFeatureShadow_SetFieldDoubleList(OGRFeatureShadow *self,int id,int nList,double *pList){
-      OGR_F_SetFieldDoubleList(self, id, nList, pList);
-  }
-SWIGINTERN void OGRFeatureShadow_SetFieldStringList(OGRFeatureShadow *self,int id,char **pList){
-      OGR_F_SetFieldStringList(self, id, pList);
-  }
-SWIGINTERN void OGRFeatureShadow_SetFieldBinaryFromHexString__SWIG_0(OGRFeatureShadow *self,int id,char const *pszValue){
-     int nBytes;
-     GByte* pabyBuf = CPLHexToBinary(pszValue, &nBytes );
-     OGR_F_SetFieldBinary(self, id, nBytes, pabyBuf);
-     CPLFree(pabyBuf);
-  }
-SWIGINTERN void OGRFeatureShadow_SetFieldBinaryFromHexString__SWIG_1(OGRFeatureShadow *self,char const *name,char const *pszValue){
-      int i = OGR_F_GetFieldIndex(self, name);
-      if (i == -1)
-        CPLError(CE_Failure, 1, "No such field: '%s'", name);
-      else
-      {
-        int nBytes;
-        GByte* pabyBuf = CPLHexToBinary(pszValue, &nBytes );
-        OGR_F_SetFieldBinary(self, i, nBytes, pabyBuf);
-        CPLFree(pabyBuf);
-      }
-  }
-SWIGINTERN OGRErr OGRFeatureShadow_SetFrom(OGRFeatureShadow *self,OGRFeatureShadow *other,int forgiving=1){
-    return OGR_F_SetFrom(self, other, forgiving);
-  }
-SWIGINTERN OGRErr OGRFeatureShadow_SetFromWithMap(OGRFeatureShadow *self,OGRFeatureShadow *other,int forgiving,int nList,int *pList){
-    if (nList != OGR_F_GetFieldCount(other))
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "The size of map doesn't match with the field count of the source feature");
-        return OGRERR_FAILURE;
-    }
-    return OGR_F_SetFromWithMap(self, other, forgiving, pList);
-  }
-SWIGINTERN char const *OGRFeatureShadow_GetStyleString(OGRFeatureShadow *self){
-    return (const char*) OGR_F_GetStyleString(self);
-  }
-SWIGINTERN void OGRFeatureShadow_SetStyleString(OGRFeatureShadow *self,char const *the_string){
-    OGR_F_SetStyleString(self, the_string);
-  }
-SWIGINTERN OGRFieldType OGRFeatureShadow_GetFieldType__SWIG_0(OGRFeatureShadow *self,int id){
-      OGRFieldDefnH fd = OGR_F_GetFieldDefnRef( self,  id );
-      if (fd)
-          return (OGRFieldType) OGR_Fld_GetType( fd );
-      else
-          return (OGRFieldType)0;
-  }
-SWIGINTERN OGRFieldType OGRFeatureShadow_GetFieldType__SWIG_1(OGRFeatureShadow *self,char const *name){
-      int i = OGR_F_GetFieldIndex(self, name);
-      if (i == -1) {
-          CPLError(CE_Failure, 1, "No such field: '%s'", name);
-          return (OGRFieldType)0;
-      } else
-          return (OGRFieldType) OGR_Fld_GetType( OGR_F_GetFieldDefnRef( self, i ) );
-  }
-SWIGINTERN int OGRFeatureShadow_Validate(OGRFeatureShadow *self,int flags=OGR_F_VAL_ALL,int bEmitError=TRUE){
-    return OGR_F_Validate(self, flags, bEmitError);
-  }
-SWIGINTERN void OGRFeatureShadow_FillUnsetWithDefault(OGRFeatureShadow *self,int bNotNullableOnly=FALSE,char **options=NULL){
-    OGR_F_FillUnsetWithDefault(self, bNotNullableOnly, options );
-  }
-
-    static int ValidateOGRGeometryType(OGRwkbGeometryType field_type)
-    {
-        switch(field_type)
-        {
-            case wkbUnknown:
-            case wkbPoint:
-            case wkbLineString:
-            case wkbPolygon:
-            case wkbMultiPoint:
-            case wkbMultiLineString:
-            case wkbMultiPolygon:
-            case wkbGeometryCollection:
-            case wkbCircularString:
-            case wkbCompoundCurve:
-            case wkbCurvePolygon:
-            case wkbMultiCurve:
-            case wkbMultiSurface:
-            case wkbNone:
-            /*case wkbLinearRing:*/
-            case wkbCircularStringZ:
-            case wkbCompoundCurveZ:
-            case wkbCurvePolygonZ:
-            case wkbMultiCurveZ:
-            case wkbMultiSurfaceZ:
-            case wkbPoint25D:
-            case wkbLineString25D:
-            case wkbPolygon25D:
-            case wkbMultiPoint25D:
-            case wkbMultiLineString25D:
-            case wkbMultiPolygon25D:
-            case wkbGeometryCollection25D:
-                return TRUE;
-            default:
-                CPLError(CE_Failure, CPLE_IllegalArg, "Illegal geometry type value");
-                return FALSE;
-        }
-    }
-
-SWIGINTERN void delete_OGRFeatureDefnShadow(OGRFeatureDefnShadow *self){
-    /*OGR_FD_Destroy(self);*/
-    OGR_FD_Release( OGRFeatureDefnH(self) );
-  }
-SWIGINTERN OGRFeatureDefnShadow *new_OGRFeatureDefnShadow(char const *name_null_ok=NULL){
-    OGRFeatureDefnH h = OGR_FD_Create(name_null_ok);
-    OGR_FD_Reference(h);
-    return (OGRFeatureDefnShadow* )h;
-  }
-SWIGINTERN char const *OGRFeatureDefnShadow_GetName(OGRFeatureDefnShadow *self){
-    return OGR_FD_GetName(self);
-  }
-SWIGINTERN int OGRFeatureDefnShadow_GetFieldCount(OGRFeatureDefnShadow *self){
-    return OGR_FD_GetFieldCount(self);
-  }
-SWIGINTERN OGRFieldDefnShadow *OGRFeatureDefnShadow_GetFieldDefn(OGRFeatureDefnShadow *self,int i){
-    return (OGRFieldDefnShadow*) OGR_FD_GetFieldDefn(self, i);
-  }
-SWIGINTERN int OGRFeatureDefnShadow_GetFieldIndex(OGRFeatureDefnShadow *self,char const *name){
-      return OGR_FD_GetFieldIndex(self, name);
-  }
-SWIGINTERN void OGRFeatureDefnShadow_AddFieldDefn(OGRFeatureDefnShadow *self,OGRFieldDefnShadow *defn){
-    OGR_FD_AddFieldDefn(self, defn);
-  }
-SWIGINTERN int OGRFeatureDefnShadow_GetGeomFieldCount(OGRFeatureDefnShadow *self){
-    return OGR_FD_GetGeomFieldCount(self);
-  }
-SWIGINTERN OGRGeomFieldDefnShadow *OGRFeatureDefnShadow_GetGeomFieldDefn(OGRFeatureDefnShadow *self,int i){
-    return (OGRGeomFieldDefnShadow*) OGR_FD_GetGeomFieldDefn(self, i);
-  }
-SWIGINTERN int OGRFeatureDefnShadow_GetGeomFieldIndex(OGRFeatureDefnShadow *self,char const *name){
-      return OGR_FD_GetGeomFieldIndex(self, name);
-  }
-SWIGINTERN void OGRFeatureDefnShadow_AddGeomFieldDefn(OGRFeatureDefnShadow *self,OGRGeomFieldDefnShadow *defn){
-    OGR_FD_AddGeomFieldDefn(self, defn);
-  }
-SWIGINTERN OGRErr OGRFeatureDefnShadow_DeleteGeomFieldDefn(OGRFeatureDefnShadow *self,int idx){
-    return OGR_FD_DeleteGeomFieldDefn(self, idx);
-  }
-SWIGINTERN OGRwkbGeometryType OGRFeatureDefnShadow_GetGeomType(OGRFeatureDefnShadow *self){
-    return (OGRwkbGeometryType) OGR_FD_GetGeomType(self);
-  }
-SWIGINTERN void OGRFeatureDefnShadow_SetGeomType(OGRFeatureDefnShadow *self,OGRwkbGeometryType geom_type){
-    if( ValidateOGRGeometryType(geom_type) )
-        OGR_FD_SetGeomType(self, geom_type);
-  }
-SWIGINTERN int OGRFeatureDefnShadow_GetReferenceCount(OGRFeatureDefnShadow *self){
-    return OGR_FD_GetReferenceCount(self);
-  }
-SWIGINTERN int OGRFeatureDefnShadow_IsGeometryIgnored(OGRFeatureDefnShadow *self){
-    return OGR_FD_IsGeometryIgnored(self);
-  }
-SWIGINTERN void OGRFeatureDefnShadow_SetGeometryIgnored(OGRFeatureDefnShadow *self,int bIgnored){
-    return OGR_FD_SetGeometryIgnored(self,bIgnored);
-  }
-SWIGINTERN int OGRFeatureDefnShadow_IsStyleIgnored(OGRFeatureDefnShadow *self){
-    return OGR_FD_IsStyleIgnored(self);
-  }
-SWIGINTERN void OGRFeatureDefnShadow_SetStyleIgnored(OGRFeatureDefnShadow *self,int bIgnored){
-    return OGR_FD_SetStyleIgnored(self,bIgnored);
-  }
-SWIGINTERN int OGRFeatureDefnShadow_IsSame(OGRFeatureDefnShadow *self,OGRFeatureDefnShadow *other_defn){
-    return OGR_FD_IsSame(self, other_defn);
-  }
-
-    static int ValidateOGRFieldType(OGRFieldType field_type)
-    {
-        switch(field_type)
-        {
-            case OFTInteger:
-            case OFTIntegerList:
-            case OFTReal:
-            case OFTRealList:
-            case OFTString:
-            case OFTStringList:
-            case OFTBinary:
-            case OFTDate:
-            case OFTTime:
-            case OFTDateTime:
-            case OFTInteger64:
-            case OFTInteger64List:
-                return TRUE;
-            default:
-                CPLError(CE_Failure, CPLE_IllegalArg, "Illegal field type value");
-                return FALSE;
-        }
-    }
-
-
-    static int ValidateOGRFieldSubType(OGRFieldSubType field_subtype)
-    {
-        switch(field_subtype)
-        {
-            case OFSTNone:
-            case OFSTBoolean:
-            case OFSTInt16:
-            case OFSTFloat32:
-                return TRUE;
-            default:
-                CPLError(CE_Failure, CPLE_IllegalArg, "Illegal field subtype value");
-                return FALSE;
-        }
-    }
-
-SWIGINTERN void delete_OGRFieldDefnShadow(OGRFieldDefnShadow *self){
-    OGR_Fld_Destroy(self);
-  }
-SWIGINTERN OGRFieldDefnShadow *new_OGRFieldDefnShadow(char const *name_null_ok="unnamed",OGRFieldType field_type=OFTString){
-    if (ValidateOGRFieldType(field_type))
-        return (OGRFieldDefnShadow*) OGR_Fld_Create(name_null_ok, field_type);
-    else
-        return NULL;
-  }
-SWIGINTERN char const *OGRFieldDefnShadow_GetName(OGRFieldDefnShadow *self){
-    return (const char *) OGR_Fld_GetNameRef(self);
-  }
-SWIGINTERN char const *OGRFieldDefnShadow_GetNameRef(OGRFieldDefnShadow *self){
-    return (const char *) OGR_Fld_GetNameRef(self);
-  }
-SWIGINTERN void OGRFieldDefnShadow_SetName(OGRFieldDefnShadow *self,char const *name){
-    OGR_Fld_SetName(self, name);
-  }
-SWIGINTERN OGRFieldType OGRFieldDefnShadow_GetType(OGRFieldDefnShadow *self){
-    return OGR_Fld_GetType(self);
-  }
-SWIGINTERN void OGRFieldDefnShadow_SetType(OGRFieldDefnShadow *self,OGRFieldType type){
-    if (ValidateOGRFieldType(type))
-        OGR_Fld_SetType(self, type);
-  }
-SWIGINTERN OGRFieldSubType OGRFieldDefnShadow_GetSubType(OGRFieldDefnShadow *self){
-    return OGR_Fld_GetSubType(self);
-  }
-SWIGINTERN void OGRFieldDefnShadow_SetSubType(OGRFieldDefnShadow *self,OGRFieldSubType type){
-    if (ValidateOGRFieldSubType(type))
-        OGR_Fld_SetSubType(self, type);
-  }
-SWIGINTERN OGRJustification OGRFieldDefnShadow_GetJustify(OGRFieldDefnShadow *self){
-    return OGR_Fld_GetJustify(self);
-  }
-SWIGINTERN void OGRFieldDefnShadow_SetJustify(OGRFieldDefnShadow *self,OGRJustification justify){
-    OGR_Fld_SetJustify(self, justify);
-  }
-SWIGINTERN int OGRFieldDefnShadow_GetWidth(OGRFieldDefnShadow *self){
-    return OGR_Fld_GetWidth(self);
-  }
-SWIGINTERN void OGRFieldDefnShadow_SetWidth(OGRFieldDefnShadow *self,int width){
-    OGR_Fld_SetWidth(self, width);
-  }
-SWIGINTERN int OGRFieldDefnShadow_GetPrecision(OGRFieldDefnShadow *self){
-    return OGR_Fld_GetPrecision(self);
-  }
-SWIGINTERN void OGRFieldDefnShadow_SetPrecision(OGRFieldDefnShadow *self,int precision){
-    OGR_Fld_SetPrecision(self, precision);
-  }
-SWIGINTERN char const *OGRFieldDefnShadow_GetTypeName(OGRFieldDefnShadow *self){
-      return OGR_GetFieldTypeName(OGR_Fld_GetType(self));
-  }
-SWIGINTERN char const *OGRFieldDefnShadow_GetFieldTypeName(OGRFieldDefnShadow *self,OGRFieldType type){
-    return OGR_GetFieldTypeName(type);
-  }
-SWIGINTERN int OGRFieldDefnShadow_IsIgnored(OGRFieldDefnShadow *self){
-    return OGR_Fld_IsIgnored( self );
-  }
-SWIGINTERN void OGRFieldDefnShadow_SetIgnored(OGRFieldDefnShadow *self,int bIgnored){
-    OGR_Fld_SetIgnored( self, bIgnored );
-  }
-SWIGINTERN int OGRFieldDefnShadow_IsNullable(OGRFieldDefnShadow *self){
-    return OGR_Fld_IsNullable( self );
-  }
-SWIGINTERN void OGRFieldDefnShadow_SetNullable(OGRFieldDefnShadow *self,int bNullable){
-    OGR_Fld_SetNullable( self, bNullable );
-  }
-SWIGINTERN char const *OGRFieldDefnShadow_GetDefault(OGRFieldDefnShadow *self){
-    return OGR_Fld_GetDefault( self );
-  }
-SWIGINTERN void OGRFieldDefnShadow_SetDefault(OGRFieldDefnShadow *self,char const *pszValue){
-    OGR_Fld_SetDefault( self, pszValue );
-  }
-SWIGINTERN int OGRFieldDefnShadow_IsDefaultDriverSpecific(OGRFieldDefnShadow *self){
-    return OGR_Fld_IsDefaultDriverSpecific( self );
-  }
-SWIGINTERN void delete_OGRGeomFieldDefnShadow(OGRGeomFieldDefnShadow *self){
-    OGR_GFld_Destroy(self);
-  }
-SWIGINTERN OGRGeomFieldDefnShadow *new_OGRGeomFieldDefnShadow(char const *name_null_ok="",OGRwkbGeometryType field_type=wkbUnknown){
-    if( ValidateOGRGeometryType(field_type) )
-        return (OGRGeomFieldDefnShadow*) OGR_GFld_Create(name_null_ok, field_type);
-    else
-        return NULL;
-  }
-SWIGINTERN char const *OGRGeomFieldDefnShadow_GetName(OGRGeomFieldDefnShadow *self){
-    return (const char *) OGR_GFld_GetNameRef(self);
-  }
-SWIGINTERN char const *OGRGeomFieldDefnShadow_GetNameRef(OGRGeomFieldDefnShadow *self){
-    return (const char *) OGR_GFld_GetNameRef(self);
-  }
-SWIGINTERN void OGRGeomFieldDefnShadow_SetName(OGRGeomFieldDefnShadow *self,char const *name){
-    OGR_GFld_SetName(self, name);
-  }
-SWIGINTERN OGRwkbGeometryType OGRGeomFieldDefnShadow_GetType(OGRGeomFieldDefnShadow *self){
-    return OGR_GFld_GetType(self);
-  }
-SWIGINTERN void OGRGeomFieldDefnShadow_SetType(OGRGeomFieldDefnShadow *self,OGRwkbGeometryType type){
-    if( ValidateOGRGeometryType(type) )
-        OGR_GFld_SetType(self, type);
-  }
-SWIGINTERN OSRSpatialReferenceShadow *OGRGeomFieldDefnShadow_GetSpatialRef(OGRGeomFieldDefnShadow *self){
-    OGRSpatialReferenceH ref =  OGR_GFld_GetSpatialRef(self);
-    if( ref )
-        OSRReference(ref);
-    return (OSRSpatialReferenceShadow*) ref;
-  }
-SWIGINTERN void OGRGeomFieldDefnShadow_SetSpatialRef(OGRGeomFieldDefnShadow *self,OSRSpatialReferenceShadow *srs){
-     OGR_GFld_SetSpatialRef( self, (OGRSpatialReferenceH)srs );
-  }
-SWIGINTERN int OGRGeomFieldDefnShadow_IsIgnored(OGRGeomFieldDefnShadow *self){
-    return OGR_GFld_IsIgnored( self );
-  }
-SWIGINTERN void OGRGeomFieldDefnShadow_SetIgnored(OGRGeomFieldDefnShadow *self,int bIgnored){
-    OGR_GFld_SetIgnored( self, bIgnored );
-  }
-SWIGINTERN int OGRGeomFieldDefnShadow_IsNullable(OGRGeomFieldDefnShadow *self){
-    return OGR_GFld_IsNullable( self );
-  }
-SWIGINTERN void OGRGeomFieldDefnShadow_SetNullable(OGRGeomFieldDefnShadow *self,int bNullable){
-    return OGR_GFld_SetNullable( self, bNullable );
-  }
-
-  OGRGeometryShadow* CreateGeometryFromWkb( int len, char *bin_string, 
-                                            OSRSpatialReferenceShadow *reference=NULL ) {
-    OGRGeometryH geom = NULL;
-    OGRErr err = OGR_G_CreateFromWkb( (unsigned char *) bin_string,
-                                      reference,
-                                      &geom,
-                                      len );
-    if (err != 0 ) {
-       CPLError(CE_Failure, err, "%s", OGRErrMessages(err));
-       return NULL;
-    }
-    return (OGRGeometryShadow*) geom;
-  }
- 
-
-
-  OGRGeometryShadow* CreateGeometryFromWkt( char **val, 
-                                      OSRSpatialReferenceShadow *reference=NULL ) {
-    OGRGeometryH geom = NULL;
-    OGRErr err = OGR_G_CreateFromWkt(val,
-                                      reference,
-                                      &geom);
-    if (err != 0 ) {
-       CPLError(CE_Failure, err, "%s", OGRErrMessages(err));
-       return NULL;
-    }
-    return (OGRGeometryShadow*) geom;
-  }
- 
-
-
-  OGRGeometryShadow *CreateGeometryFromGML( const char * input_string ) {
-    OGRGeometryShadow* geom = (OGRGeometryShadow*)OGR_G_CreateFromGML(input_string);
-    return geom;
-  }
- 
-
-
-  OGRGeometryShadow *CreateGeometryFromJson( const char * input_string ) {
-    OGRGeometryShadow* geom = (OGRGeometryShadow*)OGR_G_CreateGeometryFromJson(input_string);
-    return geom;
-  }
- 
-
-
-  OGRGeometryShadow* BuildPolygonFromEdges( OGRGeometryShadow*  hLineCollection,  
-                                            int bBestEffort = 0, 
-                                            int bAutoClose = 0, 
-                                            double dfTolerance=0) {
-  
-  OGRGeometryH hPolygon = NULL;
-  
-  OGRErr eErr;
-
-  hPolygon = OGRBuildPolygonFromEdges( hLineCollection, bBestEffort, 
-                                       bAutoClose, dfTolerance, &eErr );
-
-  if (eErr != OGRERR_NONE ) {
-    CPLError(CE_Failure, eErr, "%s", OGRErrMessages(eErr));
-    return NULL;
-  }
-
-  return (OGRGeometryShadow* )hPolygon;
-  }
-
-
-  OGRGeometryShadow* ApproximateArcAngles( 
-        double dfCenterX, double dfCenterY, double dfZ,
-  	double dfPrimaryRadius, double dfSecondaryAxis, double dfRotation, 
-        double dfStartAngle, double dfEndAngle,
-        double dfMaxAngleStepSizeDegrees ) {
-  
-  return (OGRGeometryShadow* )OGR_G_ApproximateArcAngles( 
-             dfCenterX, dfCenterY, dfZ, 
-             dfPrimaryRadius, dfSecondaryAxis, dfRotation,
-             dfStartAngle, dfEndAngle, dfMaxAngleStepSizeDegrees );
-  }
-
-
-OGRGeometryShadow* ForceToPolygon( OGRGeometryShadow *geom_in ) {
- if (geom_in == NULL)
-     return NULL;
- return (OGRGeometryShadow* )OGR_G_ForceToPolygon( OGR_G_Clone(geom_in) );
-}
-
-
-OGRGeometryShadow* ForceToLineString( OGRGeometryShadow *geom_in ) {
- if (geom_in == NULL)
-     return NULL;
- return (OGRGeometryShadow* )OGR_G_ForceToLineString( OGR_G_Clone(geom_in) );
-}
-
-
-OGRGeometryShadow* ForceToMultiPolygon( OGRGeometryShadow *geom_in ) {
- if (geom_in == NULL)
-     return NULL;
- return (OGRGeometryShadow* )OGR_G_ForceToMultiPolygon( OGR_G_Clone(geom_in) );
-}
-
-
-OGRGeometryShadow* ForceToMultiPoint( OGRGeometryShadow *geom_in ) {
- if (geom_in == NULL)
-     return NULL;
- return (OGRGeometryShadow* )OGR_G_ForceToMultiPoint( OGR_G_Clone(geom_in) );
-}
-
-
-OGRGeometryShadow* ForceToMultiLineString( OGRGeometryShadow *geom_in ) {
- if (geom_in == NULL)
-     return NULL;
- return (OGRGeometryShadow* )OGR_G_ForceToMultiLineString( OGR_G_Clone(geom_in) );
-}
-
-
-OGRGeometryShadow* ForceTo( OGRGeometryShadow *geom_in, OGRwkbGeometryType eTargetType, char** options = NULL ) {
- if (geom_in == NULL)
-     return NULL;
- return (OGRGeometryShadow* )OGR_G_ForceTo( OGR_G_Clone(geom_in), eTargetType, options );
-}
-
-SWIGINTERN void delete_OGRGeometryShadow(OGRGeometryShadow *self){
-    OGR_G_DestroyGeometry( self );
-  }
-SWIGINTERN OGRGeometryShadow *new_OGRGeometryShadow(OGRwkbGeometryType type=wkbUnknown,char *wkt=0,int wkb=0,char *wkb_buf=0,char *gml=0){
-    if (type != wkbUnknown ) {
-      return (OGRGeometryShadow*) OGR_G_CreateGeometry( type );
-    }
-    else if ( wkt != 0 ) {
-      return CreateGeometryFromWkt( &wkt );
-    }
-    else if ( wkb != 0 ) {
-      return CreateGeometryFromWkb( wkb, wkb_buf );
-    }
-    else if ( gml != 0 ) {
-      return CreateGeometryFromGML( gml );
-    }
-    // throw?
-    else {
-        CPLError(CE_Failure, 1, "Empty geometries cannot be constructed");
-        return NULL;}
-
-  }
-SWIGINTERN OGRErr OGRGeometryShadow_ExportToWkt(OGRGeometryShadow *self,char **argout){
-    return OGR_G_ExportToWkt(self, argout);
-  }
-SWIGINTERN OGRErr OGRGeometryShadow_ExportToIsoWkt(OGRGeometryShadow *self,char **argout){
-    return OGR_G_ExportToIsoWkt(self, argout);
-  }
-SWIGINTERN OGRErr OGRGeometryShadow_ExportToWkb(OGRGeometryShadow *self,int *nLen,char **pBuf,OGRwkbByteOrder byte_order=wkbXDR){
-    *nLen = OGR_G_WkbSize( self );
-    *pBuf = (char *) malloc( *nLen * sizeof(unsigned char) );
-    return OGR_G_ExportToWkb(self, byte_order, (unsigned char*) *pBuf );
-  }
-SWIGINTERN OGRErr OGRGeometryShadow_ExportToIsoWkb(OGRGeometryShadow *self,int *nLen,char **pBuf,OGRwkbByteOrder byte_order=wkbXDR){
-    *nLen = OGR_G_WkbSize( self );
-    *pBuf = (char *) malloc( *nLen * sizeof(unsigned char) );
-    return OGR_G_ExportToIsoWkb(self, byte_order, (unsigned char*) *pBuf );
-  }
-SWIGINTERN retStringAndCPLFree *OGRGeometryShadow_ExportToGML(OGRGeometryShadow *self,char **options=0){
-    return (retStringAndCPLFree*) OGR_G_ExportToGMLEx(self, options);
-  }
-SWIGINTERN retStringAndCPLFree *OGRGeometryShadow_ExportToKML(OGRGeometryShadow *self,char const *altitude_mode=NULL){
-    return (retStringAndCPLFree *) OGR_G_ExportToKML(self, altitude_mode);
-  }
-SWIGINTERN retStringAndCPLFree *OGRGeometryShadow_ExportToJson(OGRGeometryShadow *self,char **options=0){
-    return (retStringAndCPLFree *) OGR_G_ExportToJsonEx(self, options);
-  }
-SWIGINTERN void OGRGeometryShadow_AddPoint(OGRGeometryShadow *self,double x,double y,double z=0){
-    OGR_G_AddPoint( self, x, y, z );
-  }
-SWIGINTERN void OGRGeometryShadow_AddPoint_2D(OGRGeometryShadow *self,double x,double y){
-    OGR_G_AddPoint_2D( self, x, y );
-  }
-SWIGINTERN OGRErr OGRGeometryShadow_AddGeometryDirectly(OGRGeometryShadow *self,OGRGeometryShadow *other_disown){
-    return OGR_G_AddGeometryDirectly( self, other_disown );
-  }
-SWIGINTERN OGRErr OGRGeometryShadow_AddGeometry(OGRGeometryShadow *self,OGRGeometryShadow *other){
-    return OGR_G_AddGeometry( self, other );
-  }
-SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_Clone(OGRGeometryShadow *self){
-    return (OGRGeometryShadow*) OGR_G_Clone(self);
-  }
-SWIGINTERN OGRwkbGeometryType OGRGeometryShadow_GetGeometryType(OGRGeometryShadow *self){
-    return (OGRwkbGeometryType) OGR_G_GetGeometryType(self);
-  }
-SWIGINTERN char const *OGRGeometryShadow_GetGeometryName(OGRGeometryShadow *self){
-    return (const char *) OGR_G_GetGeometryName(self);
-  }
-SWIGINTERN double OGRGeometryShadow_Length(OGRGeometryShadow *self){
-    return OGR_G_Length(self);
-  }
-SWIGINTERN double OGRGeometryShadow_Area(OGRGeometryShadow *self){
-    return OGR_G_Area(self);
-  }
-SWIGINTERN double OGRGeometryShadow_GetArea(OGRGeometryShadow *self){
-    return OGR_G_Area(self);
-  }
-SWIGINTERN int OGRGeometryShadow_GetPointCount(OGRGeometryShadow *self){
-    return OGR_G_GetPointCount(self);
-  }
-SWIGINTERN double OGRGeometryShadow_GetX(OGRGeometryShadow *self,int point=0){
-    return OGR_G_GetX(self, point);
-  }
-SWIGINTERN double OGRGeometryShadow_GetY(OGRGeometryShadow *self,int point=0){
-    return OGR_G_GetY(self, point);
-  }
-SWIGINTERN double OGRGeometryShadow_GetZ(OGRGeometryShadow *self,int point=0){
-    return OGR_G_GetZ(self, point);
-  }
-SWIGINTERN void OGRGeometryShadow_GetPoint(OGRGeometryShadow *self,int iPoint=0,double argout[3]=NULL){
-
-    OGR_G_GetPoint( self, iPoint, argout+0, argout+1, argout+2 );
-  }
-SWIGINTERN void OGRGeometryShadow_GetPoint_2D(OGRGeometryShadow *self,int iPoint=0,double argout[2]=NULL){
-
-    OGR_G_GetPoint( self, iPoint, argout+0, argout+1, NULL );
-  }
-SWIGINTERN int OGRGeometryShadow_GetGeometryCount(OGRGeometryShadow *self){
-    return OGR_G_GetGeometryCount(self);
-  }
-SWIGINTERN void OGRGeometryShadow_SetPoint(OGRGeometryShadow *self,int point,double x,double y,double z=0){
-    OGR_G_SetPoint(self, point, x, y, z);
-  }
-SWIGINTERN void OGRGeometryShadow_SetPoint_2D(OGRGeometryShadow *self,int point,double x,double y){
-    OGR_G_SetPoint_2D(self, point, x, y);
-  }
-SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_GetGeometryRef(OGRGeometryShadow *self,int geom){
-    return (OGRGeometryShadow*) OGR_G_GetGeometryRef(self, geom);
-  }
-SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_Simplify(OGRGeometryShadow *self,double tolerance){
-    return (OGRGeometryShadow*) OGR_G_Simplify(self, tolerance);
-  }
-SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_SimplifyPreserveTopology(OGRGeometryShadow *self,double tolerance){
-    return (OGRGeometryShadow*) OGR_G_SimplifyPreserveTopology(self, tolerance);
-  }
-SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_Boundary(OGRGeometryShadow *self){
-    return (OGRGeometryShadow*) OGR_G_Boundary(self);
-  }
-SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_GetBoundary(OGRGeometryShadow *self){
-    return (OGRGeometryShadow*) OGR_G_Boundary(self);
-  }
-SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_ConvexHull(OGRGeometryShadow *self){
-    return (OGRGeometryShadow*) OGR_G_ConvexHull(self);
-  }
-SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_Buffer(OGRGeometryShadow *self,double distance,int quadsecs=30){
-    return (OGRGeometryShadow*) OGR_G_Buffer( self, distance, quadsecs );
-  }
-SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_Intersection(OGRGeometryShadow *self,OGRGeometryShadow *other){
-    return (OGRGeometryShadow*) OGR_G_Intersection( self, other );
-  }
-SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_Union(OGRGeometryShadow *self,OGRGeometryShadow *other){
-    return (OGRGeometryShadow*) OGR_G_Union( self, other );
-  }
-SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_UnionCascaded(OGRGeometryShadow *self){
-    return (OGRGeometryShadow*) OGR_G_UnionCascaded( self );
-  }
-SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_Difference(OGRGeometryShadow *self,OGRGeometryShadow *other){
-    return (OGRGeometryShadow*) OGR_G_Difference( self, other );
-  }
-SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_SymDifference(OGRGeometryShadow *self,OGRGeometryShadow *other){
-    return (OGRGeometryShadow*) OGR_G_SymDifference( self, other );
-  }
-SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_SymmetricDifference(OGRGeometryShadow *self,OGRGeometryShadow *other){
-    return (OGRGeometryShadow*) OGR_G_SymDifference( self, other );
-  }
-SWIGINTERN double OGRGeometryShadow_Distance(OGRGeometryShadow *self,OGRGeometryShadow *other){
-    return OGR_G_Distance(self, other);
-  }
-SWIGINTERN void OGRGeometryShadow_Empty(OGRGeometryShadow *self){
-    OGR_G_Empty(self);
-  }
-SWIGINTERN bool OGRGeometryShadow_IsEmpty(OGRGeometryShadow *self){
-    return (OGR_G_IsEmpty(self) > 0);
-  }
-SWIGINTERN bool OGRGeometryShadow_IsValid(OGRGeometryShadow *self){
-    return (OGR_G_IsValid(self) > 0);
-  }
-SWIGINTERN bool OGRGeometryShadow_IsSimple(OGRGeometryShadow *self){
-    return (OGR_G_IsSimple(self) > 0);
-  }
-SWIGINTERN bool OGRGeometryShadow_IsRing(OGRGeometryShadow *self){
-    return (OGR_G_IsRing(self) > 0);
-  }
-SWIGINTERN bool OGRGeometryShadow_Intersects(OGRGeometryShadow *self,OGRGeometryShadow *other){
-    return (OGR_G_Intersects(self, other) > 0);
-  }
-SWIGINTERN bool OGRGeometryShadow_Intersect(OGRGeometryShadow *self,OGRGeometryShadow *other){
-    return (OGR_G_Intersects(self, other) > 0);
-  }
-SWIGINTERN bool OGRGeometryShadow_Equals(OGRGeometryShadow *self,OGRGeometryShadow *other){
-    return (OGR_G_Equals(self, other) > 0);
-  }
-SWIGINTERN bool OGRGeometryShadow_Equal(OGRGeometryShadow *self,OGRGeometryShadow *other){
-    return (OGR_G_Equals(self, other) > 0);
-  }
-SWIGINTERN bool OGRGeometryShadow_Disjoint(OGRGeometryShadow *self,OGRGeometryShadow *other){
-    return (OGR_G_Disjoint(self, other) > 0);
-  }
-SWIGINTERN bool OGRGeometryShadow_Touches(OGRGeometryShadow *self,OGRGeometryShadow *other){
-    return (OGR_G_Touches(self, other) > 0);
-  }
-SWIGINTERN bool OGRGeometryShadow_Crosses(OGRGeometryShadow *self,OGRGeometryShadow *other){
-    return (OGR_G_Crosses(self, other) > 0);
-  }
-SWIGINTERN bool OGRGeometryShadow_Within(OGRGeometryShadow *self,OGRGeometryShadow *other){
-    return (OGR_G_Within(self, other) > 0);
-  }
-SWIGINTERN bool OGRGeometryShadow_Contains(OGRGeometryShadow *self,OGRGeometryShadow *other){
-    return (OGR_G_Contains(self, other) > 0);
-  }
-SWIGINTERN bool OGRGeometryShadow_Overlaps(OGRGeometryShadow *self,OGRGeometryShadow *other){
-    return (OGR_G_Overlaps(self, other) > 0);
-  }
-SWIGINTERN OGRErr OGRGeometryShadow_TransformTo(OGRGeometryShadow *self,OSRSpatialReferenceShadow *reference){
-    return OGR_G_TransformTo(self, reference);
-  }
-SWIGINTERN OGRErr OGRGeometryShadow_Transform(OGRGeometryShadow *self,OSRCoordinateTransformationShadow *trans){
-    return OGR_G_Transform(self, trans);
-  }
-SWIGINTERN OSRSpatialReferenceShadow *OGRGeometryShadow_GetSpatialReference(OGRGeometryShadow *self){
-    OGRSpatialReferenceH ref =  OGR_G_GetSpatialReference(self);
-    if( ref )
-        OSRReference(ref);
-    return (OSRSpatialReferenceShadow*) ref;
-  }
-SWIGINTERN void OGRGeometryShadow_AssignSpatialReference(OGRGeometryShadow *self,OSRSpatialReferenceShadow *reference){
-    OGR_G_AssignSpatialReference(self, reference);
-  }
-SWIGINTERN void OGRGeometryShadow_CloseRings(OGRGeometryShadow *self){
-    OGR_G_CloseRings(self);
-  }
-SWIGINTERN void OGRGeometryShadow_FlattenTo2D(OGRGeometryShadow *self){
-    OGR_G_FlattenTo2D(self);
-  }
-SWIGINTERN void OGRGeometryShadow_Segmentize(OGRGeometryShadow *self,double dfMaxLength){
-    OGR_G_Segmentize(self, dfMaxLength);
-  }
-SWIGINTERN void OGRGeometryShadow_GetEnvelope(OGRGeometryShadow *self,double argout[4]){
-    OGR_G_GetEnvelope(self, (OGREnvelope*)argout);
-  }
-SWIGINTERN void OGRGeometryShadow_GetEnvelope3D(OGRGeometryShadow *self,double argout[6]){
-    OGR_G_GetEnvelope3D(self, (OGREnvelope3D*)argout);
-  }
-SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_Centroid(OGRGeometryShadow *self){
-    OGRGeometryShadow *pt = (OGRGeometryShadow*) OGR_G_CreateGeometry( wkbPoint );
-    OGR_G_Centroid( self, pt );
-    return pt;
-  }
-SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_PointOnSurface(OGRGeometryShadow *self){
-    return (OGRGeometryShadow*) OGR_G_PointOnSurface( self );
-  }
-SWIGINTERN int OGRGeometryShadow_WkbSize(OGRGeometryShadow *self){
-    return OGR_G_WkbSize(self);
-  }
-SWIGINTERN int OGRGeometryShadow_GetCoordinateDimension(OGRGeometryShadow *self){
-    return OGR_G_GetCoordinateDimension(self);
-  }
-SWIGINTERN void OGRGeometryShadow_SetCoordinateDimension(OGRGeometryShadow *self,int dimension){
-    OGR_G_SetCoordinateDimension(self, dimension);
-  }
-SWIGINTERN int OGRGeometryShadow_GetDimension(OGRGeometryShadow *self){
-    return OGR_G_GetDimension(self);
-  }
-SWIGINTERN int OGRGeometryShadow_HasCurveGeometry(OGRGeometryShadow *self,int bLookForCircular=FALSE){
-        return OGR_G_HasCurveGeometry(self, bLookForCircular);
-  }
-SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_GetLinearGeometry(OGRGeometryShadow *self,double dfMaxAngleStepSizeDegrees=0.0,char **options=NULL){
-    return (OGRGeometryShadow* )OGR_G_GetLinearGeometry(self, dfMaxAngleStepSizeDegrees, options);
-  }
-SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_GetCurveGeometry(OGRGeometryShadow *self,char **options=NULL){
-    return (OGRGeometryShadow* )OGR_G_GetCurveGeometry(self, options);
-  }
-SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_Value(OGRGeometryShadow *self,double dfDistance){
-    return OGR_G_Value(self, dfDistance);
-  }
-SWIGINTERN void OGRGeometryShadow_Move(OGRGeometryShadow *self,double dx,double dy,double dz=0){
-        int n = OGR_G_GetGeometryCount(self);
-        if (n > 0) {
-            int i;
-            for (i = 0; i < n; i++) {
-                OGRGeometryShadow *g = (OGRGeometryShadow*)OGR_G_GetGeometryRef(self, i);
-                OGRGeometryShadow_Move(g, dx, dy, dz);
-            }
-        } else {
-            int i;
-            int d = OGR_G_GetCoordinateDimension(self);
-            for (i = 0; i < OGR_G_GetPointCount(self); i++) {
-                if (d == 0) {
-                } else {
-                    double x = OGR_G_GetX(self, i);
-                    double y = OGR_G_GetY(self, i);
-                    if (d == 2) {
-                        OGR_G_SetPoint_2D(self, i, x+dx, y+dy);
-                    } else {
-                        double z = OGR_G_GetZ(self, i);
-                        OGR_G_SetPoint(self, i, x+dx, y+dy, z+dz);
-                    }
-                }
-            }
-        }
-    }
-
-char const *OGRDriverShadow_get_name( OGRDriverShadow *h ) {
-  return OGR_Dr_GetName( h );
-}
-
-char const *OGRDataSourceShadow_get_name( OGRDataSourceShadow *h ) {
-  return OGR_DS_GetName( h );
-}
-
-char const *OGRDriverShadow_name_get( OGRDriverShadow *h ) {
-  return OGR_Dr_GetName( h );
-}
-
-char const *OGRDataSourceShadow_name_get( OGRDataSourceShadow *h ) {
-  return OGR_DS_GetName( h );
-}
-
-
-OGRwkbGeometryType GT_SetModifier( OGRwkbGeometryType eType, int bSetZ, int bSetM = FALSE)
-{
-    return OGR_GT_SetModifier(eType, bSetZ, bSetM);
-}
-
-
-  OGRDataSourceShadow* GetOpenDS(int ds_number) {
-    OGRDataSourceShadow* layer = (OGRDataSourceShadow*) OGRGetOpenDS(ds_number);
-    return layer;
-  }
-
-
-  OGRDataSourceShadow* Open( const char *utf8_path, int update =0 ) {
-    CPLErrorReset();
-    OGRDataSourceShadow* ds = (OGRDataSourceShadow*)OGROpen(utf8_path,update,NULL);
-    if( CPLGetLastErrorType() == CE_Failure && ds != NULL )
-    {
-        CPLDebug( "SWIG", 
-		  "OGROpen() succeeded, but an error is posted, so we destroy"
-		  " the datasource and fail at swig level." );
-        OGRReleaseDataSource(ds);
-        ds = NULL;
-    }
-	
-    return ds;
-  }
-
-
-  OGRDataSourceShadow* OpenShared( const char *utf8_path, int update =0 ) {
-    CPLErrorReset();
-    OGRDataSourceShadow* ds = (OGRDataSourceShadow*)OGROpenShared(utf8_path,update,NULL);
-    if( CPLGetLastErrorType() == CE_Failure && ds != NULL )
-    {
-        OGRReleaseDataSource(ds);
-        ds = NULL;
-    }
-	
-    return ds;
-  }
-
-
-OGRDriverShadow* GetDriverByName( char const *name ) {
-  return (OGRDriverShadow*) OGRGetDriverByName( name );
-}
-
-OGRDriverShadow* GetDriver(int driver_number) {
-  return (OGRDriverShadow*) OGRGetDriver(driver_number);
-}
-
-
-  char **GeneralCmdLineProcessor( char **papszArgv, int nOptions = 0 ) {
-    int nResArgCount;
-
-    nResArgCount = 
-      OGRGeneralCmdLineProcessor( CSLCount(papszArgv), &papszArgv, nOptions ); 
-
-    if( nResArgCount <= 0 )
-        return NULL;
-    else
-        return papszArgv;
-  }
-
-
-int GDALTermProgress_nocb( double dfProgress, const char * pszMessage=NULL, void *pData=NULL ) {
-  return GDALTermProgress( dfProgress, pszMessage, pData);
-}
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef PERL_OBJECT
-#define MAGIC_CLASS _wrap_Geo__OGR_var::
-class _wrap_Geo__OGR_var : public CPerlObj {
-public:
-#else
-#define MAGIC_CLASS
-#endif
-SWIGCLASS_STATIC int swig_magic_readonly(pTHX_ SV *SWIGUNUSEDPARM(sv), MAGIC *SWIGUNUSEDPARM(mg)) {
-    MAGIC_PPERL
-    croak("Value is read-only.");
-    return 0;
-}
-
-
-#ifdef PERL_OBJECT
-};
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-XS(_wrap_callback_d_cp_vp) {
-  {
-    double arg1 ;
-    char *arg2 = (char *) 0 ;
-    void *arg3 = (void *) 0 ;
-    double val1 ;
-    int ecode1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int res3 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: callback_d_cp_vp(d,cp,vp);");
-    }
-    ecode1 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "callback_d_cp_vp" "', argument " "1"" of type '" "double""'");
-    } 
-    arg1 = static_cast< double >(val1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "callback_d_cp_vp" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    res3 = SWIG_ConvertPtr(ST(2),SWIG_as_voidptrptr(&arg3), 0, 0);
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "callback_d_cp_vp" "', argument " "3"" of type '" "void *""'"); 
-    }
-    result = (int)callback_d_cp_vp(arg1,(char const *)arg2,arg3);
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_UseExceptions) {
-  {
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 0)) {
-      SWIG_croak("Usage: UseExceptions();");
-    }
-    UseExceptions();
-    ST(argvi) = sv_newmortal();
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_DontUseExceptions) {
-  {
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 0)) {
-      SWIG_croak("Usage: DontUseExceptions();");
-    }
-    DontUseExceptions();
-    ST(argvi) = sv_newmortal();
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_new_StyleTable) {
-  {
-    int argvi = 0;
-    OGRStyleTableShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 0)) {
-      SWIG_croak("Usage: new_StyleTable();");
-    }
-    {
-      CPLErrorReset();
-      result = (OGRStyleTableShadow *)new_OGRStyleTableShadow();
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRStyleTableShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_delete_StyleTable) {
-  {
-    OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: delete_StyleTable(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRStyleTableShadow, SWIG_POINTER_DISOWN |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_StyleTable" "', argument " "1"" of type '" "OGRStyleTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRStyleTableShadow * >(argp1);
-    {
-      CPLErrorReset();
-      delete_OGRStyleTableShadow(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_StyleTable_AddStyle) {
-  {
-    OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    char *arg3 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int res3 ;
-    char *buf3 = 0 ;
-    int alloc3 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: StyleTable_AddStyle(self,pszName,pszStyleString);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "StyleTable_AddStyle" "', argument " "1"" of type '" "OGRStyleTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRStyleTableShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "StyleTable_AddStyle" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "StyleTable_AddStyle" "', argument " "3"" of type '" "char const *""'");
-    }
-    arg3 = reinterpret_cast< char * >(buf3);
-    {
-      CPLErrorReset();
-      result = (int)OGRStyleTableShadow_AddStyle(arg1,(char const *)arg2,(char const *)arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_StyleTable_LoadStyleTable) {
-  {
-    OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    {
-      /* %typemap(default) const char * utf8_path */
-      arg2 = (char *)"";
-    }
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: StyleTable_LoadStyleTable(self,utf8_path);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "StyleTable_LoadStyleTable" "', argument " "1"" of type '" "OGRStyleTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRStyleTableShadow * >(argp1);
-    if (items > 1) {
-      {
-        /* %typemap(in,numinputs=1) (const char* utf8_path) */
-        sv_utf8_upgrade(ST(1));
-        arg2 = SvPV_nolen(ST(1));
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (int)OGRStyleTableShadow_LoadStyleTable(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_StyleTable_SaveStyleTable) {
-  {
-    OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    {
-      /* %typemap(default) const char * utf8_path */
-      arg2 = (char *)"";
-    }
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: StyleTable_SaveStyleTable(self,utf8_path);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "StyleTable_SaveStyleTable" "', argument " "1"" of type '" "OGRStyleTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRStyleTableShadow * >(argp1);
-    if (items > 1) {
-      {
-        /* %typemap(in,numinputs=1) (const char* utf8_path) */
-        sv_utf8_upgrade(ST(1));
-        arg2 = SvPV_nolen(ST(1));
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (int)OGRStyleTableShadow_SaveStyleTable(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_StyleTable_Find) {
-  {
-    OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: StyleTable_Find(self,pszName);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "StyleTable_Find" "', argument " "1"" of type '" "OGRStyleTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRStyleTableShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "StyleTable_Find" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    {
-      CPLErrorReset();
-      result = (char *)OGRStyleTableShadow_Find(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_StyleTable_ResetStyleStringReading) {
-  {
-    OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: StyleTable_ResetStyleStringReading(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "StyleTable_ResetStyleStringReading" "', argument " "1"" of type '" "OGRStyleTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRStyleTableShadow * >(argp1);
-    {
-      CPLErrorReset();
-      OGRStyleTableShadow_ResetStyleStringReading(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_StyleTable_GetNextStyle) {
-  {
-    OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: StyleTable_GetNextStyle(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "StyleTable_GetNextStyle" "', argument " "1"" of type '" "OGRStyleTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRStyleTableShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char *)OGRStyleTableShadow_GetNextStyle(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_StyleTable_GetLastStyleName) {
-  {
-    OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: StyleTable_GetLastStyleName(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "StyleTable_GetLastStyleName" "', argument " "1"" of type '" "OGRStyleTableShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRStyleTableShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char *)OGRStyleTableShadow_GetLastStyleName(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Driver_name_get) {
-  {
-    OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Driver_name_get(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_name_get" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char *)OGRDriverShadow_name_get(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Driver_CreateDataSource) {
-  {
-    OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    char **arg3 = (char **) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRDataSourceShadow *result = 0 ;
-    dXSARGS;
-    
-    {
-      /* %typemap(default) const char * utf8_path */
-      arg2 = (char *)"";
-    }
-    if ((items < 1) || (items > 3)) {
-      SWIG_croak("Usage: Driver_CreateDataSource(self,utf8_path,options);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_CreateDataSource" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
-    if (items > 1) {
-      {
-        /* %typemap(in,numinputs=1) (const char* utf8_path) */
-        sv_utf8_upgrade(ST(1));
-        arg2 = SvPV_nolen(ST(1));
-      }
-    }
-    if (items > 2) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(2))) {
-          if (SvROK(ST(2))) {
-            if (SvTYPE(SvRV(ST(2)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(2)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg3 = CSLAddString( arg3, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(2)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(2));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg3 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg3 = CSLAddNameValue( arg3, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRDataSourceShadow *)OGRDriverShadow_CreateDataSource(arg1,(char const *)arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDataSourceShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg3) CSLDestroy( arg3 );
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg3) CSLDestroy( arg3 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Driver_CopyDataSource) {
-  {
-    OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
-    OGRDataSourceShadow *arg2 = (OGRDataSourceShadow *) 0 ;
-    char *arg3 = (char *) 0 ;
-    char **arg4 = (char **) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    OGRDataSourceShadow *result = 0 ;
-    dXSARGS;
-    
-    {
-      /* %typemap(default) const char * utf8_path */
-      arg3 = (char *)"";
-    }
-    if ((items < 2) || (items > 4)) {
-      SWIG_croak("Usage: Driver_CopyDataSource(self,copy_ds,utf8_path,options);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_CopyDataSource" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Driver_CopyDataSource" "', argument " "2"" of type '" "OGRDataSourceShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRDataSourceShadow * >(argp2);
-    if (items > 2) {
-      {
-        /* %typemap(in,numinputs=1) (const char* utf8_path) */
-        sv_utf8_upgrade(ST(2));
-        arg3 = SvPV_nolen(ST(2));
-      }
-    }
-    if (items > 3) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(3))) {
-          if (SvROK(ST(3))) {
-            if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(3)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg4 = CSLAddString( arg4, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(3));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg4 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg4 = CSLAddNameValue( arg4, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRDataSourceShadow *)OGRDriverShadow_CopyDataSource(arg1,arg2,(char const *)arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDataSourceShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Driver_Open) {
-  {
-    OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    int arg3 = (int) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    OGRDataSourceShadow *result = 0 ;
-    dXSARGS;
-    
-    {
-      /* %typemap(default) const char * utf8_path */
-      arg2 = (char *)"";
-    }
-    if ((items < 1) || (items > 3)) {
-      SWIG_croak("Usage: Driver_Open(self,utf8_path,update);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_Open" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
-    if (items > 1) {
-      {
-        /* %typemap(in,numinputs=1) (const char* utf8_path) */
-        sv_utf8_upgrade(ST(1));
-        arg2 = SvPV_nolen(ST(1));
-      }
-    }
-    if (items > 2) {
-      ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-      if (!SWIG_IsOK(ecode3)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Driver_Open" "', argument " "3"" of type '" "int""'");
-      } 
-      arg3 = static_cast< int >(val3);
-    }
-    {
-      CPLErrorReset();
-      result = (OGRDataSourceShadow *)OGRDriverShadow_Open(arg1,(char const *)arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDataSourceShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Driver_DeleteDataSource) {
-  {
-    OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    {
-      /* %typemap(default) const char * utf8_path */
-      arg2 = (char *)"";
-    }
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: Driver_DeleteDataSource(self,utf8_path);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_DeleteDataSource" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
-    if (items > 1) {
-      {
-        /* %typemap(in,numinputs=1) (const char* utf8_path) */
-        sv_utf8_upgrade(ST(1));
-        arg2 = SvPV_nolen(ST(1));
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (int)OGRDriverShadow_DeleteDataSource(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Driver__TestCapability) {
-  {
-    OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    bool result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Driver__TestCapability(self,cap);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver__TestCapability" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Driver__TestCapability" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (bool)OGRDriverShadow_TestCapability(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Driver_GetName) {
-  {
-    OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Driver_GetName(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_GetName" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char *)OGRDriverShadow_GetName(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Driver_Register) {
-  {
-    OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Driver_Register(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_Register" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
-    {
-      CPLErrorReset();
-      OGRDriverShadow_Register(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Driver_Deregister) {
-  {
-    OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Driver_Deregister(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_Deregister" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
-    {
-      CPLErrorReset();
-      OGRDriverShadow_Deregister(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_DataSource_name_get) {
-  {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: DataSource_name_get(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_name_get" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char *)OGRDataSourceShadow_name_get(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_delete_DataSource) {
-  {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: delete_DataSource(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, SWIG_POINTER_DISOWN |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_DataSource" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      delete_OGRDataSourceShadow(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_DataSource_GetRefCount) {
-  {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: DataSource_GetRefCount(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetRefCount" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OGRDataSourceShadow_GetRefCount(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_DataSource_GetSummaryRefCount) {
-  {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: DataSource_GetSummaryRefCount(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetSummaryRefCount" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OGRDataSourceShadow_GetSummaryRefCount(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_DataSource_GetLayerCount) {
-  {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: DataSource_GetLayerCount(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetLayerCount" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OGRDataSourceShadow_GetLayerCount(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_DataSource__GetDriver) {
-  {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRDriverShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: DataSource__GetDriver(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource__GetDriver" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRDriverShadow *)OGRDataSourceShadow_GetDriver(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDriverShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_DataSource_GetName) {
-  {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: DataSource_GetName(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetName" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char *)OGRDataSourceShadow_GetName(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_DataSource__DeleteLayer) {
-  {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: DataSource__DeleteLayer(self,index);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource__DeleteLayer" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "DataSource__DeleteLayer" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRDataSourceShadow_DeleteLayer(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_DataSource_SyncToDisk) {
-  {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: DataSource_SyncToDisk(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_SyncToDisk" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRDataSourceShadow_SyncToDisk(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_DataSource_FlushCache) {
-  {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: DataSource_FlushCache(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_FlushCache" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      OGRDataSourceShadow_FlushCache(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_DataSource__CreateLayer) {
-  {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    OSRSpatialReferenceShadow *arg3 = (OSRSpatialReferenceShadow *) NULL ;
-    OGRwkbGeometryType arg4 = (OGRwkbGeometryType) wkbUnknown ;
-    char **arg5 = (char **) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
-    int val4 ;
-    int ecode4 = 0 ;
-    int argvi = 0;
-    OGRLayerShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 5)) {
-      SWIG_croak("Usage: DataSource__CreateLayer(self,name,srs,geom_type,options);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource__CreateLayer" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    if (items > 2) {
-      res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-      if (!SWIG_IsOK(res3)) {
-        SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "DataSource__CreateLayer" "', argument " "3"" of type '" "OSRSpatialReferenceShadow *""'"); 
-      }
-      arg3 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp3);
-    }
-    if (items > 3) {
-      ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-      if (!SWIG_IsOK(ecode4)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "DataSource__CreateLayer" "', argument " "4"" of type '" "OGRwkbGeometryType""'");
-      } 
-      arg4 = static_cast< OGRwkbGeometryType >(val4);
-    }
-    if (items > 4) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(4))) {
-          if (SvROK(ST(4))) {
-            if (SvTYPE(SvRV(ST(4)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(4)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg5 = CSLAddString( arg5, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(4)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(4));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg5 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg5 = CSLAddNameValue( arg5, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRLayerShadow *)OGRDataSourceShadow_CreateLayer(arg1,(char const *)arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg5) CSLDestroy( arg5 );
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg5) CSLDestroy( arg5 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_DataSource_CopyLayer) {
-  {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-    OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-    char *arg3 = (char *) 0 ;
-    char **arg4 = (char **) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int res3 ;
-    char *buf3 = 0 ;
-    int alloc3 = 0 ;
-    int argvi = 0;
-    OGRLayerShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 4)) {
-      SWIG_croak("Usage: DataSource_CopyLayer(self,src_layer,new_name,options);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_CopyLayer" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "DataSource_CopyLayer" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
-    res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "DataSource_CopyLayer" "', argument " "3"" of type '" "char const *""'");
-    }
-    arg3 = reinterpret_cast< char * >(buf3);
-    if (items > 3) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(3))) {
-          if (SvROK(ST(3))) {
-            if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(3)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg4 = CSLAddString( arg4, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(3));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg4 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg4 = CSLAddNameValue( arg4, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRLayerShadow *)OGRDataSourceShadow_CopyLayer(arg1,arg2,(char const *)arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_DataSource_GetLayerByIndex) {
-  {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-    int arg2 = (int) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    OGRLayerShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: DataSource_GetLayerByIndex(self,index);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetLayerByIndex" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "DataSource_GetLayerByIndex" "', argument " "2"" of type '" "int""'");
-      } 
-      arg2 = static_cast< int >(val2);
-    }
-    {
-      CPLErrorReset();
-      result = (OGRLayerShadow *)OGRDataSourceShadow_GetLayerByIndex(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_DataSource_GetLayerByName) {
-  {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRLayerShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: DataSource_GetLayerByName(self,layer_name);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetLayerByName" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* layer_name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    {
-      CPLErrorReset();
-      result = (OGRLayerShadow *)OGRDataSourceShadow_GetLayerByName(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_DataSource__TestCapability) {
-  {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    bool result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: DataSource__TestCapability(self,cap);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource__TestCapability" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "DataSource__TestCapability" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (bool)OGRDataSourceShadow_TestCapability(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_DataSource__ExecuteSQL) {
-  {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    OGRGeometryShadow *arg3 = (OGRGeometryShadow *) NULL ;
-    char *arg4 = (char *) "" ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
-    int res4 ;
-    char *buf4 = 0 ;
-    int alloc4 = 0 ;
-    int argvi = 0;
-    OGRLayerShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 4)) {
-      SWIG_croak("Usage: DataSource__ExecuteSQL(self,statement,spatialFilter,dialect);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource__ExecuteSQL" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "DataSource__ExecuteSQL" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    if (items > 2) {
-      res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-      if (!SWIG_IsOK(res3)) {
-        SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "DataSource__ExecuteSQL" "', argument " "3"" of type '" "OGRGeometryShadow *""'"); 
-      }
-      arg3 = reinterpret_cast< OGRGeometryShadow * >(argp3);
-    }
-    if (items > 3) {
-      res4 = SWIG_AsCharPtrAndSize(ST(3), &buf4, NULL, &alloc4);
-      if (!SWIG_IsOK(res4)) {
-        SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "DataSource__ExecuteSQL" "', argument " "4"" of type '" "char const *""'");
-      }
-      arg4 = reinterpret_cast< char * >(buf4);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRLayerShadow *)OGRDataSourceShadow_ExecuteSQL(arg1,(char const *)arg2,arg3,(char const *)arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    
-    if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    
-    if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_DataSource__ReleaseResultSet) {
-  {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-    OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: DataSource__ReleaseResultSet(self,layer);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource__ReleaseResultSet" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), SWIG_as_voidptrptr(&arg2), SWIGTYPE_p_OGRLayerShadow, SWIG_POINTER_DISOWN |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "DataSource__ReleaseResultSet" "', argument " "2"" of type '" "OGRLayerShadow *""'");
-    }
-    {
-      CPLErrorReset();
-      OGRDataSourceShadow_ReleaseResultSet(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_DataSource_GetStyleTable) {
-  {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRStyleTableShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: DataSource_GetStyleTable(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_GetStyleTable" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRStyleTableShadow *)OGRDataSourceShadow_GetStyleTable(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRStyleTableShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_DataSource_SetStyleTable) {
-  {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-    OGRStyleTableShadow *arg2 = (OGRStyleTableShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: DataSource_SetStyleTable(self,table);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_SetStyleTable" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "DataSource_SetStyleTable" "', argument " "2"" of type '" "OGRStyleTableShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRStyleTableShadow * >(argp2);
-    {
-      CPLErrorReset();
-      OGRDataSourceShadow_SetStyleTable(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_DataSource_StartTransaction) {
-  {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-    int arg2 = (int) FALSE ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: DataSource_StartTransaction(self,force);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_StartTransaction" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "DataSource_StartTransaction" "', argument " "2"" of type '" "int""'");
-      } 
-      arg2 = static_cast< int >(val2);
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRDataSourceShadow_StartTransaction(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_DataSource_CommitTransaction) {
-  {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: DataSource_CommitTransaction(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_CommitTransaction" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRDataSourceShadow_CommitTransaction(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_DataSource_RollbackTransaction) {
-  {
-    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: DataSource_RollbackTransaction(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource_RollbackTransaction" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRDataSourceShadow_RollbackTransaction(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_GetRefCount) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_GetRefCount(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetRefCount" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OGRLayerShadow_GetRefCount(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_SetSpatialFilter__SWIG_0) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Layer_SetSpatialFilter(self,filter);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetSpatialFilter" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_SetSpatialFilter" "', argument " "2"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRGeometryShadow * >(argp2);
-    {
-      CPLErrorReset();
-      OGRLayerShadow_SetSpatialFilter__SWIG_0(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_SetSpatialFilterRect__SWIG_0) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 5) || (items > 5)) {
-      SWIG_croak("Usage: Layer_SetSpatialFilterRect(self,minx,miny,maxx,maxy);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetSpatialFilterRect" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_SetSpatialFilterRect" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Layer_SetSpatialFilterRect" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Layer_SetSpatialFilterRect" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Layer_SetSpatialFilterRect" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    {
-      CPLErrorReset();
-      OGRLayerShadow_SetSpatialFilterRect__SWIG_0(arg1,arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_SetSpatialFilter__SWIG_1) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    int arg2 ;
-    OGRGeometryShadow *arg3 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Layer_SetSpatialFilter(self,iGeomField,filter);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetSpatialFilter" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_SetSpatialFilter" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_SetSpatialFilter" "', argument " "3"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg3 = reinterpret_cast< OGRGeometryShadow * >(argp3);
-    {
-      CPLErrorReset();
-      OGRLayerShadow_SetSpatialFilter__SWIG_1(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_SetSpatialFilter) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRLayerShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(1), &vptr, SWIGTYPE_p_OGRGeometryShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 3) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRLayerShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(2), &vptr, SWIGTYPE_p_OGRGeometryShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Layer_SetSpatialFilter__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Layer_SetSpatialFilter__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'Layer_SetSpatialFilter'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_Layer_SetSpatialFilterRect__SWIG_1) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    int arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    double arg6 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    double val6 ;
-    int ecode6 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 6) || (items > 6)) {
-      SWIG_croak("Usage: Layer_SetSpatialFilterRect(self,iGeomField,minx,miny,maxx,maxy);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetSpatialFilterRect" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_SetSpatialFilterRect" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Layer_SetSpatialFilterRect" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Layer_SetSpatialFilterRect" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Layer_SetSpatialFilterRect" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    ecode6 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(5), &val6);
-    if (!SWIG_IsOK(ecode6)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "Layer_SetSpatialFilterRect" "', argument " "6"" of type '" "double""'");
-    } 
-    arg6 = static_cast< double >(val6);
-    {
-      CPLErrorReset();
-      OGRLayerShadow_SetSpatialFilterRect__SWIG_1(arg1,arg2,arg3,arg4,arg5,arg6);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_SetSpatialFilterRect) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 5) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRLayerShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 6) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRLayerShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(5), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Layer_SetSpatialFilterRect__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Layer_SetSpatialFilterRect__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'Layer_SetSpatialFilterRect'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_Layer_GetSpatialFilter) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_GetSpatialFilter(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetSpatialFilter" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)OGRLayerShadow_GetSpatialFilter(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_SetAttributeFilter) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Layer_SetAttributeFilter(self,filter_string);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetAttributeFilter" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_SetAttributeFilter" "', argument " "2"" of type '" "char *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_SetAttributeFilter(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_ResetReading) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_ResetReading(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_ResetReading" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    {
-      CPLErrorReset();
-      OGRLayerShadow_ResetReading(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_GetName) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_GetName(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetName" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char *)OGRLayerShadow_GetName(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_GetGeomType) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRwkbGeometryType result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_GetGeomType(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetGeomType" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRwkbGeometryType)OGRLayerShadow_GetGeomType(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_GetGeometryColumn) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_GetGeometryColumn(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetGeometryColumn" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char *)OGRLayerShadow_GetGeometryColumn(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_GetFIDColumn) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_GetFIDColumn(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetFIDColumn" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char *)OGRLayerShadow_GetFIDColumn(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_GetFeature) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    GIntBig arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRFeatureShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Layer_GetFeature(self,fid);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetFeature" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    {
-      /* %typemap(in) GIntBig */
-      arg2 = SvIV(ST(1)); //FIXME is that right ??
-    }
-    {
-      CPLErrorReset();
-      result = (OGRFeatureShadow *)OGRLayerShadow_GetFeature(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_GetNextFeature) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRFeatureShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_GetNextFeature(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetNextFeature" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRFeatureShadow *)OGRLayerShadow_GetNextFeature(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_SetNextByIndex) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    GIntBig arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Layer_SetNextByIndex(self,new_index);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetNextByIndex" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    {
-      /* %typemap(in) GIntBig */
-      arg2 = SvIV(ST(1)); //FIXME is that right ??
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_SetNextByIndex(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_SetFeature) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Layer_SetFeature(self,feature);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetFeature" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_SetFeature" "', argument " "2"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRFeatureShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_SetFeature(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_CreateFeature) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Layer_CreateFeature(self,feature);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_CreateFeature" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_CreateFeature" "', argument " "2"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRFeatureShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_CreateFeature(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_DeleteFeature) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    GIntBig arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Layer_DeleteFeature(self,fid);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_DeleteFeature" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    {
-      /* %typemap(in) GIntBig */
-      arg2 = SvIV(ST(1)); //FIXME is that right ??
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_DeleteFeature(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_SyncToDisk) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_SyncToDisk(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SyncToDisk" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_SyncToDisk(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_GetLayerDefn) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRFeatureDefnShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_GetLayerDefn(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetLayerDefn" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRFeatureDefnShadow *)OGRLayerShadow_GetLayerDefn(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureDefnShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_GetFeatureCount) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    int arg2 = (int) 1 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    GIntBig result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: Layer_GetFeatureCount(self,force);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetFeatureCount" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_GetFeatureCount" "', argument " "2"" of type '" "int""'");
-      } 
-      arg2 = static_cast< int >(val2);
-    }
-    {
-      CPLErrorReset();
-      result = OGRLayerShadow_GetFeatureCount(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) GIntBig */
-      ST(argvi) = sv_newmortal();
-      sv_setiv(ST(argvi), (IV) result);
-      argvi++;
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_GetExtent) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    double *arg2 ;
-    int arg3 = (int) 1 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double argout2[4] ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (double argout2[ANY]) */
-      arg2 = argout2;
-    }
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: Layer_GetExtent(self,force);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetExtent" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    if (items > 1) {
-      ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val3);
-      if (!SWIG_IsOK(ecode3)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Layer_GetExtent" "', argument " "3"" of type '" "int""'");
-      } 
-      arg3 = static_cast< int >(val3);
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_GetExtent(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    {
-      /* %typemap(argout) (double argout[ANY]) */
-      if (GIMME_V == G_ARRAY) {
-        /* return a list */
-        int i;
-        EXTEND(SP, argvi+4-items+1);
-        for (i = 0; i < 4; i++)
-        ST(argvi++) = sv_2mortal(newSVnv(arg2[i]));
-      } else {
-        ST(argvi) = CreateArrayFromDoubleArray( arg2, 4 );
-        argvi++;
-      }  
-    }
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer__TestCapability) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    bool result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Layer__TestCapability(self,cap);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer__TestCapability" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer__TestCapability" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (bool)OGRLayerShadow_TestCapability(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer__CreateField) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    OGRFieldDefnShadow *arg2 = (OGRFieldDefnShadow *) 0 ;
-    int arg3 = (int) 1 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 3)) {
-      SWIG_croak("Usage: Layer__CreateField(self,field_def,approx_ok);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer__CreateField" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer__CreateField" "', argument " "2"" of type '" "OGRFieldDefnShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRFieldDefnShadow * >(argp2);
-    if (items > 2) {
-      ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-      if (!SWIG_IsOK(ecode3)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Layer__CreateField" "', argument " "3"" of type '" "int""'");
-      } 
-      arg3 = static_cast< int >(val3);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_CreateField(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer__DeleteField) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Layer__DeleteField(self,iField);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer__DeleteField" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer__DeleteField" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_DeleteField(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_ReorderField) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    int arg2 ;
-    int arg3 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Layer_ReorderField(self,iOldFieldPos,iNewFieldPos);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_ReorderField" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer_ReorderField" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Layer_ReorderField" "', argument " "3"" of type '" "int""'");
-    } 
-    arg3 = static_cast< int >(val3);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_ReorderField(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_ReorderFields) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    int arg2 ;
-    int *arg3 = (int *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Layer_ReorderFields(self,nList,pList);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_ReorderFields" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (int nList, int* pList) */
-      if (!(SvROK(ST(1)) && (SvTYPE(SvRV(ST(1)))==SVt_PVAV)))
-      SWIG_croak("Expected a reference to an array.");
-      AV *av = (AV*)(SvRV(ST(1)));
-      arg2 = av_len(av)+1;
-      arg3 = (int*)CPLMalloc(arg2*sizeof(int));
-      if (arg3) {
-        for( int i = 0; i<arg2; i++ ) {
-          SV **sv = av_fetch(av, i, 0);
-          arg3[i] =  SvIV(*sv);
-        }
-      } else
-      SWIG_fail;
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_ReorderFields(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    {
-      /* %typemap(freearg) (int nList, int* pList) */
-      CPLFree((void*) arg3);
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) (int nList, int* pList) */
-      CPLFree((void*) arg3);
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer__AlterFieldDefn) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    int arg2 ;
-    OGRFieldDefnShadow *arg3 = (OGRFieldDefnShadow *) 0 ;
-    int arg4 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
-    int val4 ;
-    int ecode4 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 4) || (items > 4)) {
-      SWIG_croak("Usage: Layer__AlterFieldDefn(self,iField,field_def,nFlags);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer__AlterFieldDefn" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Layer__AlterFieldDefn" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer__AlterFieldDefn" "', argument " "3"" of type '" "OGRFieldDefnShadow *""'"); 
-    }
-    arg3 = reinterpret_cast< OGRFieldDefnShadow * >(argp3);
-    ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Layer__AlterFieldDefn" "', argument " "4"" of type '" "int""'");
-    } 
-    arg4 = static_cast< int >(val4);
-    {
-      if (!arg3) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_AlterFieldDefn(arg1,arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_CreateGeomField) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    OGRGeomFieldDefnShadow *arg2 = (OGRGeomFieldDefnShadow *) 0 ;
-    int arg3 = (int) 1 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 3)) {
-      SWIG_croak("Usage: Layer_CreateGeomField(self,field_def,approx_ok);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_CreateGeomField" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_CreateGeomField" "', argument " "2"" of type '" "OGRGeomFieldDefnShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp2);
-    if (items > 2) {
-      ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-      if (!SWIG_IsOK(ecode3)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Layer_CreateGeomField" "', argument " "3"" of type '" "int""'");
-      } 
-      arg3 = static_cast< int >(val3);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_CreateGeomField(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_StartTransaction) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_StartTransaction(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_StartTransaction" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_StartTransaction(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_CommitTransaction) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_CommitTransaction(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_CommitTransaction" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_CommitTransaction(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_RollbackTransaction) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_RollbackTransaction(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_RollbackTransaction" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_RollbackTransaction(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_FindFieldIndex) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    int arg3 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Layer_FindFieldIndex(self,pszFieldName,bExactMatch);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_FindFieldIndex" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_FindFieldIndex" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Layer_FindFieldIndex" "', argument " "3"" of type '" "int""'");
-    } 
-    arg3 = static_cast< int >(val3);
-    {
-      CPLErrorReset();
-      result = (int)OGRLayerShadow_FindFieldIndex(arg1,(char const *)arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_GetSpatialRef) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OSRSpatialReferenceShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_GetSpatialRef(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetSpatialRef" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OSRSpatialReferenceShadow *)OGRLayerShadow_GetSpatialRef(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OSRSpatialReferenceShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_GetFeaturesRead) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    GIntBig result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_GetFeaturesRead(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetFeaturesRead" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = OGRLayerShadow_GetFeaturesRead(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) GIntBig */
-      ST(argvi) = sv_newmortal();
-      sv_setiv(ST(argvi), (IV) result);
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_SetIgnoredFields) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    char **arg2 = (char **) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Layer_SetIgnoredFields(self,options);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetIgnoredFields" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    {
-      /* %typemap(in) char **options */
-      if (SvOK(ST(1))) {
-        if (SvROK(ST(1))) {
-          if (SvTYPE(SvRV(ST(1)))==SVt_PVAV) {
-            AV *av = (AV*)(SvRV(ST(1)));
-            for (int i = 0; i < av_len(av)+1; i++) {
-              SV *sv = *(av_fetch(av, i, 0));
-              sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-              char *pszItem = SvPV_nolen(sv);
-              arg2 = CSLAddString( arg2, pszItem );
-            }
-          } else if (SvTYPE(SvRV(ST(1)))==SVt_PVHV) {
-            HV *hv = (HV*)SvRV(ST(1));
-            SV *sv;
-            char *key;
-            I32 klen;
-            arg2 = NULL;
-            hv_iterinit(hv);
-            while(sv = hv_iternextsv(hv,&key,&klen)) {
-              sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-              arg2 = CSLAddNameValue( arg2, key, SvPV_nolen(sv) );
-            }
-          } else
-          SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-        } else
-        SWIG_croak("The 'options' argument is not a reference.");   
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_SetIgnoredFields(arg1,(char const **)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg2) CSLDestroy( arg2 );
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg2) CSLDestroy( arg2 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_Intersection) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-    OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
-    char **arg4 = (char **) NULL ;
-    GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
-    void *arg6 = (void *) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg6 = (void *)(&saved_env);
-    if ((items < 3) || (items > 6)) {
-      SWIG_croak("Usage: Layer_Intersection(self,method_layer,result_layer,options,callback,callback_data);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_Intersection" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_Intersection" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
-    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_Intersection" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
-    if (items > 3) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(3))) {
-          if (SvROK(ST(3))) {
-            if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(3)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg4 = CSLAddString( arg4, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(3));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg4 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg4 = CSLAddNameValue( arg4, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    if (items > 4) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(4))) {
-          if (SvROK(ST(4))) {
-            if (SvTYPE(SvRV(ST(4))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(4);
-              arg5 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 5) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(5)))
-        saved_env.data = (SV *)ST(5);
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_Intersection(arg1,arg2,arg3,arg4,arg5,arg6);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_Union) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-    OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
-    char **arg4 = (char **) NULL ;
-    GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
-    void *arg6 = (void *) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg6 = (void *)(&saved_env);
-    if ((items < 3) || (items > 6)) {
-      SWIG_croak("Usage: Layer_Union(self,method_layer,result_layer,options,callback,callback_data);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_Union" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_Union" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
-    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_Union" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
-    if (items > 3) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(3))) {
-          if (SvROK(ST(3))) {
-            if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(3)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg4 = CSLAddString( arg4, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(3));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg4 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg4 = CSLAddNameValue( arg4, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    if (items > 4) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(4))) {
-          if (SvROK(ST(4))) {
-            if (SvTYPE(SvRV(ST(4))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(4);
-              arg5 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 5) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(5)))
-        saved_env.data = (SV *)ST(5);
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_Union(arg1,arg2,arg3,arg4,arg5,arg6);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_SymDifference) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-    OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
-    char **arg4 = (char **) NULL ;
-    GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
-    void *arg6 = (void *) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg6 = (void *)(&saved_env);
-    if ((items < 3) || (items > 6)) {
-      SWIG_croak("Usage: Layer_SymDifference(self,method_layer,result_layer,options,callback,callback_data);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SymDifference" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_SymDifference" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
-    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_SymDifference" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
-    if (items > 3) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(3))) {
-          if (SvROK(ST(3))) {
-            if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(3)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg4 = CSLAddString( arg4, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(3));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg4 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg4 = CSLAddNameValue( arg4, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    if (items > 4) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(4))) {
-          if (SvROK(ST(4))) {
-            if (SvTYPE(SvRV(ST(4))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(4);
-              arg5 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 5) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(5)))
-        saved_env.data = (SV *)ST(5);
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_SymDifference(arg1,arg2,arg3,arg4,arg5,arg6);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_Identity) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-    OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
-    char **arg4 = (char **) NULL ;
-    GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
-    void *arg6 = (void *) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg6 = (void *)(&saved_env);
-    if ((items < 3) || (items > 6)) {
-      SWIG_croak("Usage: Layer_Identity(self,method_layer,result_layer,options,callback,callback_data);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_Identity" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_Identity" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
-    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_Identity" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
-    if (items > 3) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(3))) {
-          if (SvROK(ST(3))) {
-            if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(3)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg4 = CSLAddString( arg4, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(3));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg4 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg4 = CSLAddNameValue( arg4, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    if (items > 4) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(4))) {
-          if (SvROK(ST(4))) {
-            if (SvTYPE(SvRV(ST(4))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(4);
-              arg5 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 5) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(5)))
-        saved_env.data = (SV *)ST(5);
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_Identity(arg1,arg2,arg3,arg4,arg5,arg6);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_Update) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-    OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
-    char **arg4 = (char **) NULL ;
-    GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
-    void *arg6 = (void *) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg6 = (void *)(&saved_env);
-    if ((items < 3) || (items > 6)) {
-      SWIG_croak("Usage: Layer_Update(self,method_layer,result_layer,options,callback,callback_data);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_Update" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_Update" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
-    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_Update" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
-    if (items > 3) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(3))) {
-          if (SvROK(ST(3))) {
-            if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(3)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg4 = CSLAddString( arg4, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(3));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg4 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg4 = CSLAddNameValue( arg4, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    if (items > 4) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(4))) {
-          if (SvROK(ST(4))) {
-            if (SvTYPE(SvRV(ST(4))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(4);
-              arg5 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 5) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(5)))
-        saved_env.data = (SV *)ST(5);
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_Update(arg1,arg2,arg3,arg4,arg5,arg6);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_Clip) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-    OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
-    char **arg4 = (char **) NULL ;
-    GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
-    void *arg6 = (void *) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg6 = (void *)(&saved_env);
-    if ((items < 3) || (items > 6)) {
-      SWIG_croak("Usage: Layer_Clip(self,method_layer,result_layer,options,callback,callback_data);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_Clip" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_Clip" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
-    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_Clip" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
-    if (items > 3) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(3))) {
-          if (SvROK(ST(3))) {
-            if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(3)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg4 = CSLAddString( arg4, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(3));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg4 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg4 = CSLAddNameValue( arg4, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    if (items > 4) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(4))) {
-          if (SvROK(ST(4))) {
-            if (SvTYPE(SvRV(ST(4))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(4);
-              arg5 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 5) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(5)))
-        saved_env.data = (SV *)ST(5);
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_Clip(arg1,arg2,arg3,arg4,arg5,arg6);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_Erase) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
-    OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
-    char **arg4 = (char **) NULL ;
-    GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
-    void *arg6 = (void *) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg6 = (void *)(&saved_env);
-    if ((items < 3) || (items > 6)) {
-      SWIG_croak("Usage: Layer_Erase(self,method_layer,result_layer,options,callback,callback_data);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_Erase" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_Erase" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
-    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Layer_Erase" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
-    if (items > 3) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(3))) {
-          if (SvROK(ST(3))) {
-            if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(3)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg4 = CSLAddString( arg4, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(3));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg4 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg4 = CSLAddNameValue( arg4, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    if (items > 4) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(4))) {
-          if (SvROK(ST(4))) {
-            if (SvTYPE(SvRV(ST(4))) != SVt_PVCV) {
-              SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-            } else {
-              saved_env.fct = (SV *)ST(4);
-              arg5 = &callback_d_cp_vp;
-            }
-          } else {
-            SWIG_croak("the callback argument of a Geo::GDAL method must be a reference to a subroutine");
-          }
-        }
-      }
-    }
-    if (items > 5) {
-      {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(5)))
-        saved_env.data = (SV *)ST(5);
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRLayerShadow_Erase(arg1,arg2,arg3,arg4,arg5,arg6);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg4) CSLDestroy( arg4 );
-    }
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_GetStyleTable) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRStyleTableShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer_GetStyleTable(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_GetStyleTable" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRStyleTableShadow *)OGRLayerShadow_GetStyleTable(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRStyleTableShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Layer_SetStyleTable) {
-  {
-    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
-    OGRStyleTableShadow *arg2 = (OGRStyleTableShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Layer_SetStyleTable(self,table);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Layer_SetStyleTable" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Layer_SetStyleTable" "', argument " "2"" of type '" "OGRStyleTableShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRStyleTableShadow * >(argp2);
-    {
-      CPLErrorReset();
-      OGRLayerShadow_SetStyleTable(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_delete_Feature) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: delete_Feature(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, SWIG_POINTER_DISOWN |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_Feature" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      CPLErrorReset();
-      delete_OGRFeatureShadow(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_new_Feature) {
-  {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRFeatureShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: new_Feature(feature_def);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_Feature" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRFeatureShadow *)new_OGRFeatureShadow(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetDefnRef) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRFeatureDefnShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Feature_GetDefnRef(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetDefnRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRFeatureDefnShadow *)OGRFeatureShadow_GetDefnRef(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureDefnShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature__SetGeometry) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature__SetGeometry(self,geom);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__SetGeometry" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature__SetGeometry" "', argument " "2"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRGeometryShadow * >(argp2);
-    {
-      /* %typemap(check) (OGRGeometryShadow *geom) */
-      if (!arg2)
-      SWIG_croak("The geometry must not be undefined when it is an argument to a Geo::GDAL method");
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRFeatureShadow_SetGeometry(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_SetGeometryDirectly) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_SetGeometryDirectly(self,geom);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetGeometryDirectly" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), SWIG_as_voidptrptr(&arg2), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_DISOWN |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetGeometryDirectly" "', argument " "2"" of type '" "OGRGeometryShadow *""'");
-    }
-    {
-      /* %typemap(check) (OGRGeometryShadow *geom) */
-      if (!arg2)
-      SWIG_croak("The geometry must not be undefined when it is an argument to a Geo::GDAL method");
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRFeatureShadow_SetGeometryDirectly(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetGeometryRef) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Feature_GetGeometryRef(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetGeometryRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)OGRFeatureShadow_GetGeometryRef(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_SetGeomField__SWIG_0) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    OGRGeometryShadow *arg3 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature_SetGeomField(self,iField,geom);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetGeomField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetGeomField" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Feature_SetGeomField" "', argument " "3"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg3 = reinterpret_cast< OGRGeometryShadow * >(argp3);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRFeatureShadow_SetGeomField__SWIG_0(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_SetGeomField__SWIG_1) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    OGRGeometryShadow *arg3 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature_SetGeomField(self,name,geom);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetGeomField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Feature_SetGeomField" "', argument " "3"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg3 = reinterpret_cast< OGRGeometryShadow * >(argp3);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRFeatureShadow_SetGeomField__SWIG_1(arg1,(char const *)arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_SetGeomField) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 3) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(2), &vptr, SWIGTYPE_p_OGRGeometryShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 3) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(2), &vptr, SWIGTYPE_p_OGRGeometryShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_SetGeomField__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_SetGeomField__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'Feature_SetGeomField'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_Feature_SetGeomFieldDirectly__SWIG_0) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    OGRGeometryShadow *arg3 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int res3 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature_SetGeomFieldDirectly(self,iField,geom);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetGeomFieldDirectly" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetGeomFieldDirectly" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    res3 = SWIG_ConvertPtr(ST(2), SWIG_as_voidptrptr(&arg3), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_DISOWN |  0 );
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Feature_SetGeomFieldDirectly" "', argument " "3"" of type '" "OGRGeometryShadow *""'");
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRFeatureShadow_SetGeomFieldDirectly__SWIG_0(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_SetGeomFieldDirectly__SWIG_1) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    OGRGeometryShadow *arg3 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res3 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature_SetGeomFieldDirectly(self,name,geom);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetGeomFieldDirectly" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    res3 = SWIG_ConvertPtr(ST(2), SWIG_as_voidptrptr(&arg3), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_DISOWN |  0 );
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Feature_SetGeomFieldDirectly" "', argument " "3"" of type '" "OGRGeometryShadow *""'");
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRFeatureShadow_SetGeomFieldDirectly__SWIG_1(arg1,(char const *)arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_SetGeomFieldDirectly) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 3) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(2), &vptr, SWIGTYPE_p_OGRGeometryShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 3) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(2), &vptr, SWIGTYPE_p_OGRGeometryShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_SetGeomFieldDirectly__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_SetGeomFieldDirectly__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'Feature_SetGeomFieldDirectly'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_Feature_GetGeomFieldRef__SWIG_0) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetGeomFieldRef(self,iField);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetGeomFieldRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetGeomFieldRef" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)OGRFeatureShadow_GetGeomFieldRef__SWIG_0(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetGeomFieldRef__SWIG_1) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetGeomFieldRef(self,name);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetGeomFieldRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)OGRFeatureShadow_GetGeomFieldRef__SWIG_1(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetGeomFieldRef) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetGeomFieldRef__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetGeomFieldRef__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'Feature_GetGeomFieldRef'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_Feature_Clone) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRFeatureShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Feature_Clone(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_Clone" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRFeatureShadow *)OGRFeatureShadow_Clone(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_Equal) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    bool result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_Equal(self,feature);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_Equal" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_Equal" "', argument " "2"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRFeatureShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (bool)OGRFeatureShadow_Equal(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetFieldCount) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Feature_GetFieldCount(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldCount" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OGRFeatureShadow_GetFieldCount(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetFieldDefnRef__SWIG_0) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    OGRFieldDefnShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldDefnRef(self,id);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldDefnRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldDefnRef" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (OGRFieldDefnShadow *)OGRFeatureShadow_GetFieldDefnRef__SWIG_0(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFieldDefnShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetFieldDefnRef__SWIG_1) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRFieldDefnShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldDefnRef(self,name);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldDefnRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRFieldDefnShadow *)OGRFeatureShadow_GetFieldDefnRef__SWIG_1(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFieldDefnShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetFieldDefnRef) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldDefnRef__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldDefnRef__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'Feature_GetFieldDefnRef'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_Feature_GetGeomFieldCount) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Feature_GetGeomFieldCount(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetGeomFieldCount" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OGRFeatureShadow_GetGeomFieldCount(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetGeomFieldDefnRef__SWIG_0) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    OGRGeomFieldDefnShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetGeomFieldDefnRef(self,id);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetGeomFieldDefnRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetGeomFieldDefnRef" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (OGRGeomFieldDefnShadow *)OGRFeatureShadow_GetGeomFieldDefnRef__SWIG_0(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetGeomFieldDefnRef__SWIG_1) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRGeomFieldDefnShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetGeomFieldDefnRef(self,name);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetGeomFieldDefnRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRGeomFieldDefnShadow *)OGRFeatureShadow_GetGeomFieldDefnRef__SWIG_1(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetGeomFieldDefnRef) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetGeomFieldDefnRef__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetGeomFieldDefnRef__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'Feature_GetGeomFieldDefnRef'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_Feature_GetFieldAsString) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsString(self,id);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsString" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsString" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (char *)OGRFeatureShadow_GetFieldAsString(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetFieldAsInteger) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsInteger(self,id);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsInteger" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsInteger" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (int)OGRFeatureShadow_GetFieldAsInteger(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetFieldAsInteger64) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    GIntBig result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsInteger64(self,id);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsInteger64" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsInteger64" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = OGRFeatureShadow_GetFieldAsInteger64(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) GIntBig */
-      ST(argvi) = sv_newmortal();
-      sv_setiv(ST(argvi), (IV) result);
-      argvi++;
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetFieldAsDouble) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    double result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsDouble(self,id);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsDouble" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsDouble" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (double)OGRFeatureShadow_GetFieldAsDouble(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetFieldAsDateTime) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    int *arg3 = (int *) 0 ;
-    int *arg4 = (int *) 0 ;
-    int *arg5 = (int *) 0 ;
-    int *arg6 = (int *) 0 ;
-    int *arg7 = (int *) 0 ;
-    float *arg8 = (float *) 0 ;
-    int *arg9 = (int *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int temp3 ;
-    int res3 = SWIG_TMPOBJ ;
-    int temp4 ;
-    int res4 = SWIG_TMPOBJ ;
-    int temp5 ;
-    int res5 = SWIG_TMPOBJ ;
-    int temp6 ;
-    int res6 = SWIG_TMPOBJ ;
-    int temp7 ;
-    int res7 = SWIG_TMPOBJ ;
-    float temp8 ;
-    int res8 = SWIG_TMPOBJ ;
-    int temp9 ;
-    int res9 = SWIG_TMPOBJ ;
-    int argvi = 0;
-    dXSARGS;
-    
-    arg3 = &temp3;
-    arg4 = &temp4;
-    arg5 = &temp5;
-    arg6 = &temp6;
-    arg7 = &temp7;
-    arg8 = &temp8;
-    arg9 = &temp9;
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsDateTime(self,id);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsDateTime" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsDateTime" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_GetFieldAsDateTime(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    if (SWIG_IsTmpObj(res3)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg3)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_int, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res4)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg4)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res5)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg5)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res5) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg5), SWIGTYPE_p_int, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res6)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg6)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res6) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg6), SWIGTYPE_p_int, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res7)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg7)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res7) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg7), SWIGTYPE_p_int, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res8)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_float  SWIG_PERL_CALL_ARGS_1((*arg8)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res8) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg8), SWIGTYPE_p_float, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res9)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg9)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res9) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg9), SWIGTYPE_p_int, new_flags); argvi++  ;
-    }
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetFieldAsIntegerList) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    int *arg3 = (int *) 0 ;
-    int **arg4 = (int **) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int nLen3 ;
-    int *pList3 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (int *nLen3, const int **pList3) */
-      arg3 = &nLen3;
-      arg4 = &pList3;
-    }
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsIntegerList(self,id,pList);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsIntegerList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsIntegerList" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_GetFieldAsIntegerList(arg1,arg2,arg3,(int const **)arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    {
-      /* %typemap(argout) (int *nLen, const int **pList) */
-      ST(argvi) = CreateArrayFromIntArray( *(arg4), *(arg3) );
-      argvi++;
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetFieldAsDoubleList) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    int *arg3 = (int *) 0 ;
-    double **arg4 = (double **) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int nLen3 ;
-    double *pList3 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (int *nLen3, const double **pList3) */
-      arg3 = &nLen3;
-      arg4 = &pList3;
-    }
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsDoubleList(self,id,pList);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsDoubleList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsDoubleList" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_GetFieldAsDoubleList(arg1,arg2,arg3,(double const **)arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    {
-      /* %typemap(argout) (int *nLen, const double **pList) */
-      ST(argvi) = CreateArrayFromDoubleArray( *(arg4), *(arg3) );
-      argvi++;
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetFieldAsStringList) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    char ***arg3 = (char ***) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    char **pList3 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (char ***pList3) */
-      arg3 = &pList3;
-    }
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsStringList(self,id);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsStringList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsStringList" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_GetFieldAsStringList(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    {
-      /* %typemap(argout) (char ***pList) */
-      ST(argvi) = CreateArrayFromStringArray( *(arg3) );
-      argvi++;
-    }
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetFieldAsBinary) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    int *arg3 = (int *) 0 ;
-    char **arg4 = (char **) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int nLen3 = 0 ;
-    char *pBuf3 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (int *nLen3, char **pBuf3 ) */
-      arg3 = &nLen3;
-      arg4 = &pBuf3;
-    }
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsBinary(self,id,pBuf);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsBinary" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsBinary" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRFeatureShadow_GetFieldAsBinary(arg1,arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    {
-      /* %typemap(argout) (int *nLen, char **pBuf ) */
-      ST(argvi) = sv_2mortal(newSVpv( *arg4, *arg3 ));
-      argvi++;
-    }
-    
-    
-    {
-      /* %typemap(freearg) (int *nLen, char **pBuf ) */
-      if( *arg3 ) {
-        free( *arg4 );
-      }
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    
-    {
-      /* %typemap(freearg) (int *nLen, char **pBuf ) */
-      if( *arg3 ) {
-        free( *arg4 );
-      }
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_IsFieldSet__SWIG_0) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    bool result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_IsFieldSet(self,id);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_IsFieldSet" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_IsFieldSet" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (bool)OGRFeatureShadow_IsFieldSet__SWIG_0(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_IsFieldSet__SWIG_1) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    bool result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_IsFieldSet(self,name);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_IsFieldSet" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (bool)OGRFeatureShadow_IsFieldSet__SWIG_1(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_IsFieldSet) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_IsFieldSet__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_IsFieldSet__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'Feature_IsFieldSet'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_Feature_GetFieldIndex) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldIndex(self,name);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldIndex" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (int)OGRFeatureShadow_GetFieldIndex(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetGeomFieldIndex) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetGeomFieldIndex(self,name);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetGeomFieldIndex" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (int)OGRFeatureShadow_GetGeomFieldIndex(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetFID) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    GIntBig result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Feature_GetFID(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFID" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = OGRFeatureShadow_GetFID(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) GIntBig */
-      ST(argvi) = sv_newmortal();
-      sv_setiv(ST(argvi), (IV) result);
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_SetFID) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    GIntBig arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_SetFID(self,fid);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFID" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in) GIntBig */
-      arg2 = SvIV(ST(1)); //FIXME is that right ??
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRFeatureShadow_SetFID(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_DumpReadable) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Feature_DumpReadable(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_DumpReadable" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_DumpReadable(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature__UnsetField) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature__UnsetField(self,id);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__UnsetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature__UnsetField" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_UnsetField(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature__SetField__SWIG_0) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    char *arg3 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature__SetField(self,id,value);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature__SetField" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      /* %typemap(in) (tostring argin) */
-      sv_utf8_upgrade(ST(2)); /* GDAL expects UTF-8 */
-      arg3 = SvPV_nolen( ST(2) ); 
-    }
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_SetField__SWIG_0(arg1,arg2,(char const *)arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_SetFieldInteger64) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    GIntBig arg3 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature_SetFieldInteger64(self,id,value);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldInteger64" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldInteger64" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      /* %typemap(in) GIntBig */
-      arg3 = SvIV(ST(2)); //FIXME is that right ??
-    }
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_SetFieldInteger64(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature__SetField__SWIG_1) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    int arg3 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature__SetField(self,id,value);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature__SetField" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature__SetField" "', argument " "3"" of type '" "int""'");
-    } 
-    arg3 = static_cast< int >(val3);
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_SetField__SWIG_1(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature__SetField__SWIG_2) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    double arg3 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature__SetField(self,id,value);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature__SetField" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature__SetField" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_SetField__SWIG_2(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature__SetField__SWIG_3) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    int arg3 ;
-    int arg4 ;
-    int arg5 ;
-    int arg6 ;
-    int arg7 ;
-    float arg8 ;
-    int arg9 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int val4 ;
-    int ecode4 = 0 ;
-    int val5 ;
-    int ecode5 = 0 ;
-    int val6 ;
-    int ecode6 = 0 ;
-    int val7 ;
-    int ecode7 = 0 ;
-    float val8 ;
-    int ecode8 = 0 ;
-    int val9 ;
-    int ecode9 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 9) || (items > 9)) {
-      SWIG_croak("Usage: Feature__SetField(self,id,year,month,day,hour,minute,second,tzflag);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature__SetField" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature__SetField" "', argument " "3"" of type '" "int""'");
-    } 
-    arg3 = static_cast< int >(val3);
-    ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Feature__SetField" "', argument " "4"" of type '" "int""'");
-    } 
-    arg4 = static_cast< int >(val4);
-    ecode5 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Feature__SetField" "', argument " "5"" of type '" "int""'");
-    } 
-    arg5 = static_cast< int >(val5);
-    ecode6 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(5), &val6);
-    if (!SWIG_IsOK(ecode6)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "Feature__SetField" "', argument " "6"" of type '" "int""'");
-    } 
-    arg6 = static_cast< int >(val6);
-    ecode7 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(6), &val7);
-    if (!SWIG_IsOK(ecode7)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "Feature__SetField" "', argument " "7"" of type '" "int""'");
-    } 
-    arg7 = static_cast< int >(val7);
-    ecode8 = SWIG_AsVal_float SWIG_PERL_CALL_ARGS_2(ST(7), &val8);
-    if (!SWIG_IsOK(ecode8)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "Feature__SetField" "', argument " "8"" of type '" "float""'");
-    } 
-    arg8 = static_cast< float >(val8);
-    ecode9 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(8), &val9);
-    if (!SWIG_IsOK(ecode9)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode9), "in method '" "Feature__SetField" "', argument " "9"" of type '" "int""'");
-    } 
-    arg9 = static_cast< int >(val9);
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_SetField__SWIG_3(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature__SetField) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 3) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          /* %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER) (tostring argin) */
-          _v = 1;
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 3) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-    if (items == 3) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_3;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_3;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_3;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 3;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_3:
-    
-    if (items == 9) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_4;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_4;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_4;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_4;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(4), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_4;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(5), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_4;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(6), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_4;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_float SWIG_PERL_CALL_ARGS_2(ST(7), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_4;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(8), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_4;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 4;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_4:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature__SetField__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature__SetField__SWIG_1); return;
-    case 3:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature__SetField__SWIG_2); return;
-    case 4:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature__SetField__SWIG_3); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'Feature__SetField'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_Feature_SetFieldIntegerList) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    int arg3 ;
-    int *arg4 = (int *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature_SetFieldIntegerList(self,id,nList,pList);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldIntegerList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldIntegerList" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      /* %typemap(in,numinputs=1) (int nList, int* pList) */
-      if (!(SvROK(ST(2)) && (SvTYPE(SvRV(ST(2)))==SVt_PVAV)))
-      SWIG_croak("Expected a reference to an array.");
-      AV *av = (AV*)(SvRV(ST(2)));
-      arg3 = av_len(av)+1;
-      arg4 = (int*)CPLMalloc(arg3*sizeof(int));
-      if (arg4) {
-        for( int i = 0; i<arg3; i++ ) {
-          SV **sv = av_fetch(av, i, 0);
-          arg4[i] =  SvIV(*sv);
-        }
-      } else
-      SWIG_fail;
-    }
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_SetFieldIntegerList(arg1,arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    {
-      /* %typemap(freearg) (int nList, int* pList) */
-      CPLFree((void*) arg4);
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    
-    {
-      /* %typemap(freearg) (int nList, int* pList) */
-      CPLFree((void*) arg4);
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_SetFieldDoubleList) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    int arg3 ;
-    double *arg4 = (double *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature_SetFieldDoubleList(self,id,nList,pList);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldDoubleList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldDoubleList" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      /* %typemap(in,numinputs=1) (int nList, double* pList) */
-      if (!(SvROK(ST(2)) && (SvTYPE(SvRV(ST(2)))==SVt_PVAV)))
-      SWIG_croak("Expected a reference to an array.");
-      AV *av = (AV*)(SvRV(ST(2)));
-      arg3 = av_len(av)+1;
-      arg4 = (double*)CPLMalloc(arg3*sizeof(double));
-      if (arg4) {
-        for( int i = 0; i<arg3; i++ ) {
-          SV **sv = av_fetch(av, i, 0);
-          arg4[i] =  SvNV(*sv);
-        }
-      } else
-      SWIG_fail;
-    }
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_SetFieldDoubleList(arg1,arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    {
-      /* %typemap(freearg) (int nList, double* pList) */
-      CPLFree((void*) arg4);
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    
-    {
-      /* %typemap(freearg) (int nList, double* pList) */
-      CPLFree((void*) arg4);
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_SetFieldStringList) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    char **arg3 = (char **) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature_SetFieldStringList(self,id,pList);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldStringList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldStringList" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      /* %typemap(in) char **options */
-      if (SvOK(ST(2))) {
-        if (SvROK(ST(2))) {
-          if (SvTYPE(SvRV(ST(2)))==SVt_PVAV) {
-            AV *av = (AV*)(SvRV(ST(2)));
-            for (int i = 0; i < av_len(av)+1; i++) {
-              SV *sv = *(av_fetch(av, i, 0));
-              sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-              char *pszItem = SvPV_nolen(sv);
-              arg3 = CSLAddString( arg3, pszItem );
-            }
-          } else if (SvTYPE(SvRV(ST(2)))==SVt_PVHV) {
-            HV *hv = (HV*)SvRV(ST(2));
-            SV *sv;
-            char *key;
-            I32 klen;
-            arg3 = NULL;
-            hv_iterinit(hv);
-            while(sv = hv_iternextsv(hv,&key,&klen)) {
-              sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-              arg3 = CSLAddNameValue( arg3, key, SvPV_nolen(sv) );
-            }
-          } else
-          SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-        } else
-        SWIG_croak("The 'options' argument is not a reference.");   
-      }
-    }
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_SetFieldStringList(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg3) CSLDestroy( arg3 );
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg3) CSLDestroy( arg3 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_SetFieldBinaryFromHexString__SWIG_0) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    char *arg3 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int res3 ;
-    char *buf3 = 0 ;
-    int alloc3 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature_SetFieldBinaryFromHexString(self,id,pszValue);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldBinaryFromHexString" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldBinaryFromHexString" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Feature_SetFieldBinaryFromHexString" "', argument " "3"" of type '" "char const *""'");
-    }
-    arg3 = reinterpret_cast< char * >(buf3);
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_SetFieldBinaryFromHexString__SWIG_0(arg1,arg2,(char const *)arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    XSRETURN(argvi);
-  fail:
-    
-    
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_SetFieldBinaryFromHexString__SWIG_1) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    char *arg3 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res3 ;
-    char *buf3 = 0 ;
-    int alloc3 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature_SetFieldBinaryFromHexString(self,name,pszValue);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldBinaryFromHexString" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Feature_SetFieldBinaryFromHexString" "', argument " "3"" of type '" "char const *""'");
-    }
-    arg3 = reinterpret_cast< char * >(buf3);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_SetFieldBinaryFromHexString__SWIG_1(arg1,(char const *)arg2,(char const *)arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_SetFieldBinaryFromHexString) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 3) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(2), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 3) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(2), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_SetFieldBinaryFromHexString__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_SetFieldBinaryFromHexString__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'Feature_SetFieldBinaryFromHexString'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_Feature__SetFrom) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
-    int arg3 = (int) 1 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 3)) {
-      SWIG_croak("Usage: Feature__SetFrom(self,other,forgiving);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__SetFrom" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature__SetFrom" "', argument " "2"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRFeatureShadow * >(argp2);
-    if (items > 2) {
-      ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-      if (!SWIG_IsOK(ecode3)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature__SetFrom" "', argument " "3"" of type '" "int""'");
-      } 
-      arg3 = static_cast< int >(val3);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRFeatureShadow_SetFrom(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_SetFromWithMap) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
-    int arg3 ;
-    int arg4 ;
-    int *arg5 = (int *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 4) || (items > 4)) {
-      SWIG_croak("Usage: Feature_SetFromWithMap(self,other,forgiving,nList,pList);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFromWithMap" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetFromWithMap" "', argument " "2"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRFeatureShadow * >(argp2);
-    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature_SetFromWithMap" "', argument " "3"" of type '" "int""'");
-    } 
-    arg3 = static_cast< int >(val3);
-    {
-      /* %typemap(in,numinputs=1) (int nList, int* pList) */
-      if (!(SvROK(ST(3)) && (SvTYPE(SvRV(ST(3)))==SVt_PVAV)))
-      SWIG_croak("Expected a reference to an array.");
-      AV *av = (AV*)(SvRV(ST(3)));
-      arg4 = av_len(av)+1;
-      arg5 = (int*)CPLMalloc(arg4*sizeof(int));
-      if (arg5) {
-        for( int i = 0; i<arg4; i++ ) {
-          SV **sv = av_fetch(av, i, 0);
-          arg5[i] =  SvIV(*sv);
-        }
-      } else
-      SWIG_fail;
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRFeatureShadow_SetFromWithMap(arg1,arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    {
-      /* %typemap(freearg) (int nList, int* pList) */
-      CPLFree((void*) arg5);
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    {
-      /* %typemap(freearg) (int nList, int* pList) */
-      CPLFree((void*) arg5);
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetStyleString) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Feature_GetStyleString(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetStyleString" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char *)OGRFeatureShadow_GetStyleString(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_SetStyleString) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_SetStyleString(self,the_string);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetStyleString" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetStyleString" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_SetStyleString(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetFieldType__SWIG_0) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    OGRFieldType result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldType(self,id);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldType" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldType" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (OGRFieldType)OGRFeatureShadow_GetFieldType__SWIG_0(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetFieldType__SWIG_1) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRFieldType result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldType(self,name);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldType" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRFieldType)OGRFeatureShadow_GetFieldType__SWIG_1(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetFieldType) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldType__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldType__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'Feature_GetFieldType'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_Feature__Validate) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 = (int) OGR_F_VAL_ALL ;
-    int arg3 = (int) TRUE ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 3)) {
-      SWIG_croak("Usage: Feature__Validate(self,flags,bEmitError);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__Validate" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature__Validate" "', argument " "2"" of type '" "int""'");
-      } 
-      arg2 = static_cast< int >(val2);
-    }
-    if (items > 2) {
-      ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-      if (!SWIG_IsOK(ecode3)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature__Validate" "', argument " "3"" of type '" "int""'");
-      } 
-      arg3 = static_cast< int >(val3);
-    }
-    {
-      CPLErrorReset();
-      result = (int)OGRFeatureShadow_Validate(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_FillUnsetWithDefault) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 = (int) FALSE ;
-    char **arg3 = (char **) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 3)) {
-      SWIG_croak("Usage: Feature_FillUnsetWithDefault(self,bNotNullableOnly,options);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_FillUnsetWithDefault" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_FillUnsetWithDefault" "', argument " "2"" of type '" "int""'");
-      } 
-      arg2 = static_cast< int >(val2);
-    }
-    if (items > 2) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(2))) {
-          if (SvROK(ST(2))) {
-            if (SvTYPE(SvRV(ST(2)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(2)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg3 = CSLAddString( arg3, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(2)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(2));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg3 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg3 = CSLAddNameValue( arg3, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_FillUnsetWithDefault(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg3) CSLDestroy( arg3 );
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg3) CSLDestroy( arg3 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_delete_FeatureDefn) {
-  {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: delete_FeatureDefn(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, SWIG_POINTER_DISOWN |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_FeatureDefn" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-    {
-      CPLErrorReset();
-      delete_OGRFeatureDefnShadow(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_new_FeatureDefn) {
-  {
-    char *arg1 = (char *) NULL ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
-    int argvi = 0;
-    OGRFeatureDefnShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 1)) {
-      SWIG_croak("Usage: new_FeatureDefn(name_null_ok);");
-    }
-    if (items > 0) {
-      res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-      if (!SWIG_IsOK(res1)) {
-        SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_FeatureDefn" "', argument " "1"" of type '" "char const *""'");
-      }
-      arg1 = reinterpret_cast< char * >(buf1);
-    }
-    {
-      CPLErrorReset();
-      result = (OGRFeatureDefnShadow *)new_OGRFeatureDefnShadow((char const *)arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureDefnShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    XSRETURN(argvi);
-  fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FeatureDefn_GetName) {
-  {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FeatureDefn_GetName(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetName" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char *)OGRFeatureDefnShadow_GetName(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FeatureDefn_GetFieldCount) {
-  {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FeatureDefn_GetFieldCount(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetFieldCount" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OGRFeatureDefnShadow_GetFieldCount(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FeatureDefn_GetFieldDefn) {
-  {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    OGRFieldDefnShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FeatureDefn_GetFieldDefn(self,i);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetFieldDefn" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn_GetFieldDefn" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (OGRFieldDefnShadow *)OGRFeatureDefnShadow_GetFieldDefn(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFieldDefnShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FeatureDefn_GetFieldIndex) {
-  {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FeatureDefn_GetFieldIndex(self,name);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetFieldIndex" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (int)OGRFeatureDefnShadow_GetFieldIndex(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FeatureDefn_AddFieldDefn) {
-  {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-    OGRFieldDefnShadow *arg2 = (OGRFieldDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FeatureDefn_AddFieldDefn(self,defn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_AddFieldDefn" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "FeatureDefn_AddFieldDefn" "', argument " "2"" of type '" "OGRFieldDefnShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRFieldDefnShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      OGRFeatureDefnShadow_AddFieldDefn(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FeatureDefn_GetGeomFieldCount) {
-  {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FeatureDefn_GetGeomFieldCount(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetGeomFieldCount" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OGRFeatureDefnShadow_GetGeomFieldCount(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FeatureDefn_GetGeomFieldDefn) {
-  {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    OGRGeomFieldDefnShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FeatureDefn_GetGeomFieldDefn(self,i);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetGeomFieldDefn" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn_GetGeomFieldDefn" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (OGRGeomFieldDefnShadow *)OGRFeatureDefnShadow_GetGeomFieldDefn(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FeatureDefn_GetGeomFieldIndex) {
-  {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FeatureDefn_GetGeomFieldIndex(self,name);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetGeomFieldIndex" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (int)OGRFeatureDefnShadow_GetGeomFieldIndex(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FeatureDefn_AddGeomFieldDefn) {
-  {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-    OGRGeomFieldDefnShadow *arg2 = (OGRGeomFieldDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FeatureDefn_AddGeomFieldDefn(self,defn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_AddGeomFieldDefn" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "FeatureDefn_AddGeomFieldDefn" "', argument " "2"" of type '" "OGRGeomFieldDefnShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      OGRFeatureDefnShadow_AddGeomFieldDefn(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FeatureDefn_DeleteGeomFieldDefn) {
-  {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FeatureDefn_DeleteGeomFieldDefn(self,idx);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_DeleteGeomFieldDefn" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn_DeleteGeomFieldDefn" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRFeatureDefnShadow_DeleteGeomFieldDefn(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FeatureDefn_GetGeomType) {
-  {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRwkbGeometryType result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FeatureDefn_GetGeomType(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetGeomType" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRwkbGeometryType)OGRFeatureDefnShadow_GetGeomType(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FeatureDefn_SetGeomType) {
-  {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-    OGRwkbGeometryType arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FeatureDefn_SetGeomType(self,geom_type);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_SetGeomType" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn_SetGeomType" "', argument " "2"" of type '" "OGRwkbGeometryType""'");
-    } 
-    arg2 = static_cast< OGRwkbGeometryType >(val2);
-    {
-      CPLErrorReset();
-      OGRFeatureDefnShadow_SetGeomType(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FeatureDefn_GetReferenceCount) {
-  {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FeatureDefn_GetReferenceCount(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetReferenceCount" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OGRFeatureDefnShadow_GetReferenceCount(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FeatureDefn_IsGeometryIgnored) {
-  {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FeatureDefn_IsGeometryIgnored(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_IsGeometryIgnored" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OGRFeatureDefnShadow_IsGeometryIgnored(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FeatureDefn_SetGeometryIgnored) {
-  {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FeatureDefn_SetGeometryIgnored(self,bIgnored);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_SetGeometryIgnored" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn_SetGeometryIgnored" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      OGRFeatureDefnShadow_SetGeometryIgnored(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FeatureDefn_IsStyleIgnored) {
-  {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FeatureDefn_IsStyleIgnored(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_IsStyleIgnored" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OGRFeatureDefnShadow_IsStyleIgnored(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FeatureDefn_SetStyleIgnored) {
-  {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FeatureDefn_SetStyleIgnored(self,bIgnored);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_SetStyleIgnored" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn_SetStyleIgnored" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      OGRFeatureDefnShadow_SetStyleIgnored(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FeatureDefn_IsSame) {
-  {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-    OGRFeatureDefnShadow *arg2 = (OGRFeatureDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FeatureDefn_IsSame(self,other_defn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_IsSame" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "FeatureDefn_IsSame" "', argument " "2"" of type '" "OGRFeatureDefnShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRFeatureDefnShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (int)OGRFeatureDefnShadow_IsSame(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_delete_FieldDefn) {
-  {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: delete_FieldDefn(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, SWIG_POINTER_DISOWN |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_FieldDefn" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-    {
-      CPLErrorReset();
-      delete_OGRFieldDefnShadow(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_new_FieldDefn) {
-  {
-    char *arg1 = (char *) "unnamed" ;
-    OGRFieldType arg2 = (OGRFieldType) OFTString ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    OGRFieldDefnShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 2)) {
-      SWIG_croak("Usage: new_FieldDefn(name_null_ok,field_type);");
-    }
-    if (items > 0) {
-      res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-      if (!SWIG_IsOK(res1)) {
-        SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_FieldDefn" "', argument " "1"" of type '" "char const *""'");
-      }
-      arg1 = reinterpret_cast< char * >(buf1);
-    }
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "new_FieldDefn" "', argument " "2"" of type '" "OGRFieldType""'");
-      } 
-      arg2 = static_cast< OGRFieldType >(val2);
-    }
-    {
-      CPLErrorReset();
-      result = (OGRFieldDefnShadow *)new_OGRFieldDefnShadow((char const *)arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFieldDefnShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    
-    XSRETURN(argvi);
-  fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FieldDefn_GetName) {
-  {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FieldDefn_GetName(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetName" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char *)OGRFieldDefnShadow_GetName(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FieldDefn_GetNameRef) {
-  {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FieldDefn_GetNameRef(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetNameRef" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char *)OGRFieldDefnShadow_GetNameRef(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FieldDefn_SetName) {
-  {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FieldDefn_SetName(self,name);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetName" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      OGRFieldDefnShadow_SetName(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FieldDefn_GetType) {
-  {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRFieldType result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FieldDefn_GetType(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetType" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRFieldType)OGRFieldDefnShadow_GetType(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FieldDefn_SetType) {
-  {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-    OGRFieldType arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FieldDefn_SetType(self,type);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetType" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_SetType" "', argument " "2"" of type '" "OGRFieldType""'");
-    } 
-    arg2 = static_cast< OGRFieldType >(val2);
-    {
-      CPLErrorReset();
-      OGRFieldDefnShadow_SetType(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FieldDefn_GetSubType) {
-  {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRFieldSubType result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FieldDefn_GetSubType(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetSubType" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRFieldSubType)OGRFieldDefnShadow_GetSubType(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FieldDefn_SetSubType) {
-  {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-    OGRFieldSubType arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FieldDefn_SetSubType(self,type);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetSubType" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_SetSubType" "', argument " "2"" of type '" "OGRFieldSubType""'");
-    } 
-    arg2 = static_cast< OGRFieldSubType >(val2);
-    {
-      CPLErrorReset();
-      OGRFieldDefnShadow_SetSubType(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FieldDefn_GetJustify) {
-  {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRJustification result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FieldDefn_GetJustify(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetJustify" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRJustification)OGRFieldDefnShadow_GetJustify(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FieldDefn_SetJustify) {
-  {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-    OGRJustification arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FieldDefn_SetJustify(self,justify);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetJustify" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_SetJustify" "', argument " "2"" of type '" "OGRJustification""'");
-    } 
-    arg2 = static_cast< OGRJustification >(val2);
-    {
-      CPLErrorReset();
-      OGRFieldDefnShadow_SetJustify(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FieldDefn_GetWidth) {
-  {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FieldDefn_GetWidth(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetWidth" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OGRFieldDefnShadow_GetWidth(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FieldDefn_SetWidth) {
-  {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FieldDefn_SetWidth(self,width);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetWidth" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_SetWidth" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      OGRFieldDefnShadow_SetWidth(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FieldDefn_GetPrecision) {
-  {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FieldDefn_GetPrecision(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetPrecision" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OGRFieldDefnShadow_GetPrecision(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FieldDefn_SetPrecision) {
-  {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FieldDefn_SetPrecision(self,precision);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetPrecision" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_SetPrecision" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      OGRFieldDefnShadow_SetPrecision(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FieldDefn_GetTypeName) {
-  {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FieldDefn_GetTypeName(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetTypeName" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char *)OGRFieldDefnShadow_GetTypeName(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FieldDefn_GetFieldTypeName) {
-  {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-    OGRFieldType arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FieldDefn_GetFieldTypeName(self,type);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetFieldTypeName" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_GetFieldTypeName" "', argument " "2"" of type '" "OGRFieldType""'");
-    } 
-    arg2 = static_cast< OGRFieldType >(val2);
-    {
-      CPLErrorReset();
-      result = (char *)OGRFieldDefnShadow_GetFieldTypeName(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FieldDefn_IsIgnored) {
-  {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FieldDefn_IsIgnored(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_IsIgnored" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OGRFieldDefnShadow_IsIgnored(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FieldDefn_SetIgnored) {
-  {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FieldDefn_SetIgnored(self,bIgnored);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetIgnored" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_SetIgnored" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      OGRFieldDefnShadow_SetIgnored(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FieldDefn_IsNullable) {
-  {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FieldDefn_IsNullable(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_IsNullable" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OGRFieldDefnShadow_IsNullable(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FieldDefn_SetNullable) {
-  {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FieldDefn_SetNullable(self,bNullable);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetNullable" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FieldDefn_SetNullable" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      OGRFieldDefnShadow_SetNullable(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FieldDefn_GetDefault) {
-  {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FieldDefn_GetDefault(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_GetDefault" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char *)OGRFieldDefnShadow_GetDefault(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FieldDefn_SetDefault) {
-  {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FieldDefn_SetDefault(self,pszValue);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetDefault" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "FieldDefn_SetDefault" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    {
-      CPLErrorReset();
-      OGRFieldDefnShadow_SetDefault(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FieldDefn_IsDefaultDriverSpecific) {
-  {
-    OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FieldDefn_IsDefaultDriverSpecific(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_IsDefaultDriverSpecific" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OGRFieldDefnShadow_IsDefaultDriverSpecific(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_delete_GeomFieldDefn) {
-  {
-    OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: delete_GeomFieldDefn(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, SWIG_POINTER_DISOWN |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_GeomFieldDefn" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
-    {
-      CPLErrorReset();
-      delete_OGRGeomFieldDefnShadow(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_new_GeomFieldDefn) {
-  {
-    char *arg1 = (char *) "" ;
-    OGRwkbGeometryType arg2 = (OGRwkbGeometryType) wkbUnknown ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    OGRGeomFieldDefnShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 2)) {
-      SWIG_croak("Usage: new_GeomFieldDefn(name_null_ok,field_type);");
-    }
-    if (items > 0) {
-      res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-      if (!SWIG_IsOK(res1)) {
-        SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_GeomFieldDefn" "', argument " "1"" of type '" "char const *""'");
-      }
-      arg1 = reinterpret_cast< char * >(buf1);
-    }
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "new_GeomFieldDefn" "', argument " "2"" of type '" "OGRwkbGeometryType""'");
-      } 
-      arg2 = static_cast< OGRwkbGeometryType >(val2);
-    }
-    {
-      CPLErrorReset();
-      result = (OGRGeomFieldDefnShadow *)new_OGRGeomFieldDefnShadow((char const *)arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeomFieldDefnShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    
-    XSRETURN(argvi);
-  fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GeomFieldDefn_GetName) {
-  {
-    OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GeomFieldDefn_GetName(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GeomFieldDefn_GetName" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char *)OGRGeomFieldDefnShadow_GetName(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GeomFieldDefn_GetNameRef) {
-  {
-    OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GeomFieldDefn_GetNameRef(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GeomFieldDefn_GetNameRef" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char *)OGRGeomFieldDefnShadow_GetNameRef(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GeomFieldDefn_SetName) {
-  {
-    OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: GeomFieldDefn_SetName(self,name);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GeomFieldDefn_SetName" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      OGRGeomFieldDefnShadow_SetName(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GeomFieldDefn_GetType) {
-  {
-    OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRwkbGeometryType result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GeomFieldDefn_GetType(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GeomFieldDefn_GetType" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRwkbGeometryType)OGRGeomFieldDefnShadow_GetType(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GeomFieldDefn_SetType) {
-  {
-    OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
-    OGRwkbGeometryType arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: GeomFieldDefn_SetType(self,type);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GeomFieldDefn_SetType" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "GeomFieldDefn_SetType" "', argument " "2"" of type '" "OGRwkbGeometryType""'");
-    } 
-    arg2 = static_cast< OGRwkbGeometryType >(val2);
-    {
-      CPLErrorReset();
-      OGRGeomFieldDefnShadow_SetType(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GeomFieldDefn_GetSpatialRef) {
-  {
-    OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OSRSpatialReferenceShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GeomFieldDefn_GetSpatialRef(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GeomFieldDefn_GetSpatialRef" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OSRSpatialReferenceShadow *)OGRGeomFieldDefnShadow_GetSpatialRef(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OSRSpatialReferenceShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GeomFieldDefn_SetSpatialRef) {
-  {
-    OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
-    OSRSpatialReferenceShadow *arg2 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: GeomFieldDefn_SetSpatialRef(self,srs);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GeomFieldDefn_SetSpatialRef" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "GeomFieldDefn_SetSpatialRef" "', argument " "2"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp2);
-    {
-      CPLErrorReset();
-      OGRGeomFieldDefnShadow_SetSpatialRef(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GeomFieldDefn_IsIgnored) {
-  {
-    OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GeomFieldDefn_IsIgnored(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GeomFieldDefn_IsIgnored" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OGRGeomFieldDefnShadow_IsIgnored(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GeomFieldDefn_SetIgnored) {
-  {
-    OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: GeomFieldDefn_SetIgnored(self,bIgnored);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GeomFieldDefn_SetIgnored" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "GeomFieldDefn_SetIgnored" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      OGRGeomFieldDefnShadow_SetIgnored(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GeomFieldDefn_IsNullable) {
-  {
-    OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GeomFieldDefn_IsNullable(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GeomFieldDefn_IsNullable" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OGRGeomFieldDefnShadow_IsNullable(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GeomFieldDefn_SetNullable) {
-  {
-    OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: GeomFieldDefn_SetNullable(self,bNullable);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GeomFieldDefn_SetNullable" "', argument " "1"" of type '" "OGRGeomFieldDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeomFieldDefnShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "GeomFieldDefn_SetNullable" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      OGRGeomFieldDefnShadow_SetNullable(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_CreateGeometryFromWkb) {
-  {
-    int arg1 ;
-    char *arg2 = (char *) 0 ;
-    OSRSpatialReferenceShadow *arg3 = (OSRSpatialReferenceShadow *) NULL ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: CreateGeometryFromWkb(len,bin_string,reference);");
-    }
-    {
-      /* %typemap(in,numinputs=1) (int nLen, char *pBuf ) */
-      if (SvOK(ST(0))) {
-        if (!SvPOK(ST(0)))
-        SWIG_croak("Expected binary data.");
-        STRLEN len = SvCUR(ST(0));
-        arg2 = SvPV_nolen(ST(0));
-        arg1 = len;
-      } else {
-        arg2 = NULL;
-        arg1 = 0;
-      }
-    }
-    if (items > 1) {
-      res3 = SWIG_ConvertPtr(ST(1), &argp3,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-      if (!SWIG_IsOK(res3)) {
-        SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "CreateGeometryFromWkb" "', argument " "3"" of type '" "OSRSpatialReferenceShadow *""'"); 
-      }
-      arg3 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp3);
-    }
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)CreateGeometryFromWkb(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_CreateGeometryFromWkt) {
-  {
-    char **arg1 = (char **) 0 ;
-    OSRSpatialReferenceShadow *arg2 = (OSRSpatialReferenceShadow *) NULL ;
-    char *val1 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: CreateGeometryFromWkt(val,reference);");
-    }
-    {
-      /* %typemap(in) (char **ignorechange) */
-      sv_utf8_upgrade(ST(0)); /* GDAL expects UTF-8 */
-      val1 = SvPV_nolen(ST(0));
-      arg1 = &val1;
-    }
-    if (items > 1) {
-      res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-      if (!SWIG_IsOK(res2)) {
-        SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "CreateGeometryFromWkt" "', argument " "2"" of type '" "OSRSpatialReferenceShadow *""'"); 
-      }
-      arg2 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp2);
-    }
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)CreateGeometryFromWkt(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_CreateGeometryFromGML) {
-  {
-    char *arg1 = (char *) 0 ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: CreateGeometryFromGML(input_string);");
-    }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CreateGeometryFromGML" "', argument " "1"" of type '" "char const *""'");
-    }
-    arg1 = reinterpret_cast< char * >(buf1);
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)CreateGeometryFromGML((char const *)arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    XSRETURN(argvi);
-  fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_CreateGeometryFromJson) {
-  {
-    char *arg1 = (char *) 0 ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: CreateGeometryFromJson(input_string);");
-    }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CreateGeometryFromJson" "', argument " "1"" of type '" "char const *""'");
-    }
-    arg1 = reinterpret_cast< char * >(buf1);
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)CreateGeometryFromJson((char const *)arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    XSRETURN(argvi);
-  fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_BuildPolygonFromEdges) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    int arg2 = (int) 0 ;
-    int arg3 = (int) 0 ;
-    double arg4 = (double) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 4)) {
-      SWIG_croak("Usage: BuildPolygonFromEdges(hLineCollection,bBestEffort,bAutoClose,dfTolerance);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "BuildPolygonFromEdges" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "BuildPolygonFromEdges" "', argument " "2"" of type '" "int""'");
-      } 
-      arg2 = static_cast< int >(val2);
-    }
-    if (items > 2) {
-      ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-      if (!SWIG_IsOK(ecode3)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "BuildPolygonFromEdges" "', argument " "3"" of type '" "int""'");
-      } 
-      arg3 = static_cast< int >(val3);
-    }
-    if (items > 3) {
-      ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-      if (!SWIG_IsOK(ecode4)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "BuildPolygonFromEdges" "', argument " "4"" of type '" "double""'");
-      } 
-      arg4 = static_cast< double >(val4);
-    }
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)BuildPolygonFromEdges(arg1,arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_ApproximateArcAngles) {
-  {
-    double arg1 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    double arg6 ;
-    double arg7 ;
-    double arg8 ;
-    double arg9 ;
-    double val1 ;
-    int ecode1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    double val6 ;
-    int ecode6 = 0 ;
-    double val7 ;
-    int ecode7 = 0 ;
-    double val8 ;
-    int ecode8 = 0 ;
-    double val9 ;
-    int ecode9 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 9) || (items > 9)) {
-      SWIG_croak("Usage: ApproximateArcAngles(dfCenterX,dfCenterY,dfZ,dfPrimaryRadius,dfSecondaryAxis,dfRotation,dfStartAngle,dfEndAngle,dfMaxAngleStepSizeDegrees);");
-    }
-    ecode1 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "ApproximateArcAngles" "', argument " "1"" of type '" "double""'");
-    } 
-    arg1 = static_cast< double >(val1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "ApproximateArcAngles" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "ApproximateArcAngles" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "ApproximateArcAngles" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "ApproximateArcAngles" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    ecode6 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(5), &val6);
-    if (!SWIG_IsOK(ecode6)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "ApproximateArcAngles" "', argument " "6"" of type '" "double""'");
-    } 
-    arg6 = static_cast< double >(val6);
-    ecode7 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(6), &val7);
-    if (!SWIG_IsOK(ecode7)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "ApproximateArcAngles" "', argument " "7"" of type '" "double""'");
-    } 
-    arg7 = static_cast< double >(val7);
-    ecode8 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(7), &val8);
-    if (!SWIG_IsOK(ecode8)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "ApproximateArcAngles" "', argument " "8"" of type '" "double""'");
-    } 
-    arg8 = static_cast< double >(val8);
-    ecode9 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(8), &val9);
-    if (!SWIG_IsOK(ecode9)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode9), "in method '" "ApproximateArcAngles" "', argument " "9"" of type '" "double""'");
-    } 
-    arg9 = static_cast< double >(val9);
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)ApproximateArcAngles(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_ForceToPolygon) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: ForceToPolygon(geom_in);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ForceToPolygon" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)ForceToPolygon(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_ForceToLineString) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: ForceToLineString(geom_in);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ForceToLineString" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)ForceToLineString(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_ForceToMultiPolygon) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: ForceToMultiPolygon(geom_in);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ForceToMultiPolygon" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)ForceToMultiPolygon(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_ForceToMultiPoint) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: ForceToMultiPoint(geom_in);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ForceToMultiPoint" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)ForceToMultiPoint(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_ForceToMultiLineString) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: ForceToMultiLineString(geom_in);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ForceToMultiLineString" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)ForceToMultiLineString(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_ForceTo) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    OGRwkbGeometryType arg2 ;
-    char **arg3 = (char **) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 3)) {
-      SWIG_croak("Usage: ForceTo(geom_in,eTargetType,options);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ForceTo" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "ForceTo" "', argument " "2"" of type '" "OGRwkbGeometryType""'");
-    } 
-    arg2 = static_cast< OGRwkbGeometryType >(val2);
-    if (items > 2) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(2))) {
-          if (SvROK(ST(2))) {
-            if (SvTYPE(SvRV(ST(2)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(2)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg3 = CSLAddString( arg3, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(2)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(2));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg3 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg3 = CSLAddNameValue( arg3, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)ForceTo(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg3) CSLDestroy( arg3 );
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg3) CSLDestroy( arg3 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_delete_Geometry) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: delete_Geometry(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_DISOWN |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_Geometry" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      delete_OGRGeometryShadow(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_new_Geometry) {
-  {
-    OGRwkbGeometryType arg1 = (OGRwkbGeometryType) wkbUnknown ;
-    char *arg2 = (char *) 0 ;
-    int arg3 = (int) 0 ;
-    char *arg4 = (char *) 0 ;
-    char *arg5 = (char *) 0 ;
-    int val1 ;
-    int ecode1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int res5 ;
-    char *buf5 = 0 ;
-    int alloc5 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 4)) {
-      SWIG_croak("Usage: new_Geometry(type,wkt,wkb,wkb_buf,gml);");
-    }
-    if (items > 0) {
-      ecode1 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-      if (!SWIG_IsOK(ecode1)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "new_Geometry" "', argument " "1"" of type '" "OGRwkbGeometryType""'");
-      } 
-      arg1 = static_cast< OGRwkbGeometryType >(val1);
-    }
-    if (items > 1) {
-      res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-      if (!SWIG_IsOK(res2)) {
-        SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "new_Geometry" "', argument " "2"" of type '" "char *""'");
-      }
-      arg2 = reinterpret_cast< char * >(buf2);
-    }
-    if (items > 2) {
-      {
-        /* %typemap(in,numinputs=1) (int nLen, char *pBuf ) */
-        if (SvOK(ST(2))) {
-          if (!SvPOK(ST(2)))
-          SWIG_croak("Expected binary data.");
-          STRLEN len = SvCUR(ST(2));
-          arg4 = SvPV_nolen(ST(2));
-          arg3 = len;
-        } else {
-          arg4 = NULL;
-          arg3 = 0;
-        }
-      }
-    }
-    if (items > 3) {
-      res5 = SWIG_AsCharPtrAndSize(ST(3), &buf5, NULL, &alloc5);
-      if (!SWIG_IsOK(res5)) {
-        SWIG_exception_fail(SWIG_ArgError(res5), "in method '" "new_Geometry" "', argument " "5"" of type '" "char *""'");
-      }
-      arg5 = reinterpret_cast< char * >(buf5);
-    }
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)new_OGRGeometryShadow(arg1,arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc5 == SWIG_NEWOBJ) delete[] buf5;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc5 == SWIG_NEWOBJ) delete[] buf5;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_ExportToWkt) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    char **arg2 = (char **) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    char *argout2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (char **argout2) */
-      arg2 = &argout2;
-    }
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Geometry_ExportToWkt(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_ExportToWkt" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRGeometryShadow_ExportToWkt(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    {
-      /* %typemap(argout) (char **argout) */
-      ST(argvi) = sv_newmortal();
-      if ( arg2 ) {
-        sv_setpv(ST(argvi), *arg2);
-        SvUTF8_on(ST(argvi)); /* expecting UTF-8 from GDAL */
-      }
-      argvi++;
-    }
-    
-    {
-      /* %typemap(freearg) (char **argout) */
-      if ( *arg2 )
-      CPLFree( *arg2 );
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) (char **argout) */
-      if ( *arg2 )
-      CPLFree( *arg2 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_ExportToIsoWkt) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    char **arg2 = (char **) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    char *argout2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (char **argout2) */
-      arg2 = &argout2;
-    }
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Geometry_ExportToIsoWkt(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_ExportToIsoWkt" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRGeometryShadow_ExportToIsoWkt(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    {
-      /* %typemap(argout) (char **argout) */
-      ST(argvi) = sv_newmortal();
-      if ( arg2 ) {
-        sv_setpv(ST(argvi), *arg2);
-        SvUTF8_on(ST(argvi)); /* expecting UTF-8 from GDAL */
-      }
-      argvi++;
-    }
-    
-    {
-      /* %typemap(freearg) (char **argout) */
-      if ( *arg2 )
-      CPLFree( *arg2 );
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) (char **argout) */
-      if ( *arg2 )
-      CPLFree( *arg2 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry__ExportToWkb) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    int *arg2 = (int *) 0 ;
-    char **arg3 = (char **) 0 ;
-    OGRwkbByteOrder arg4 = (OGRwkbByteOrder) wkbXDR ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int nLen2 = 0 ;
-    char *pBuf2 = 0 ;
-    int val4 ;
-    int ecode4 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (int *nLen2, char **pBuf2 ) */
-      arg2 = &nLen2;
-      arg3 = &pBuf2;
-    }
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: Geometry__ExportToWkb(self,pBuf,byte_order);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry__ExportToWkb" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    if (items > 1) {
-      ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val4);
-      if (!SWIG_IsOK(ecode4)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Geometry__ExportToWkb" "', argument " "4"" of type '" "OGRwkbByteOrder""'");
-      } 
-      arg4 = static_cast< OGRwkbByteOrder >(val4);
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRGeometryShadow_ExportToWkb(arg1,arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    {
-      /* %typemap(argout) (int *nLen, char **pBuf ) */
-      ST(argvi) = sv_2mortal(newSVpv( *arg3, *arg2 ));
-      argvi++;
-    }
-    
-    {
-      /* %typemap(freearg) (int *nLen, char **pBuf ) */
-      if( *arg2 ) {
-        free( *arg3 );
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) (int *nLen, char **pBuf ) */
-      if( *arg2 ) {
-        free( *arg3 );
-      }
-    }
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_ExportToIsoWkb) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    int *arg2 = (int *) 0 ;
-    char **arg3 = (char **) 0 ;
-    OGRwkbByteOrder arg4 = (OGRwkbByteOrder) wkbXDR ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int nLen2 = 0 ;
-    char *pBuf2 = 0 ;
-    int val4 ;
-    int ecode4 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (int *nLen2, char **pBuf2 ) */
-      arg2 = &nLen2;
-      arg3 = &pBuf2;
-    }
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_ExportToIsoWkb(self,pBuf,byte_order);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_ExportToIsoWkb" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    if (items > 1) {
-      ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val4);
-      if (!SWIG_IsOK(ecode4)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Geometry_ExportToIsoWkb" "', argument " "4"" of type '" "OGRwkbByteOrder""'");
-      } 
-      arg4 = static_cast< OGRwkbByteOrder >(val4);
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRGeometryShadow_ExportToIsoWkb(arg1,arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    {
-      /* %typemap(argout) (int *nLen, char **pBuf ) */
-      ST(argvi) = sv_2mortal(newSVpv( *arg3, *arg2 ));
-      argvi++;
-    }
-    
-    {
-      /* %typemap(freearg) (int *nLen, char **pBuf ) */
-      if( *arg2 ) {
-        free( *arg3 );
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) (int *nLen, char **pBuf ) */
-      if( *arg2 ) {
-        free( *arg3 );
-      }
-    }
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_ExportToGML) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    char **arg2 = (char **) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    retStringAndCPLFree *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_ExportToGML(self,options);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_ExportToGML" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    if (items > 1) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(1))) {
-          if (SvROK(ST(1))) {
-            if (SvTYPE(SvRV(ST(1)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(1)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg2 = CSLAddString( arg2, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(1)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(1));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg2 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg2 = CSLAddNameValue( arg2, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (retStringAndCPLFree *)OGRGeometryShadow_ExportToGML(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    
-    /* %typemap(out) (retStringAndCPLFree*) */
-    if(result)
-    {
-      ST(argvi) = SWIG_FromCharPtr((const char *)result);
-      CPLFree(result);
-    }
-    else
-    {
-      ST(argvi) = &PL_sv_undef;
-    }
-    argvi++ ;
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg2) CSLDestroy( arg2 );
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg2) CSLDestroy( arg2 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_ExportToKML) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    char *arg2 = (char *) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    retStringAndCPLFree *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_ExportToKML(self,altitude_mode);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_ExportToKML" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    if (items > 1) {
-      res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-      if (!SWIG_IsOK(res2)) {
-        SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Geometry_ExportToKML" "', argument " "2"" of type '" "char const *""'");
-      }
-      arg2 = reinterpret_cast< char * >(buf2);
-    }
-    {
-      CPLErrorReset();
-      result = (retStringAndCPLFree *)OGRGeometryShadow_ExportToKML(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    
-    /* %typemap(out) (retStringAndCPLFree*) */
-    if(result)
-    {
-      ST(argvi) = SWIG_FromCharPtr((const char *)result);
-      CPLFree(result);
-    }
-    else
-    {
-      ST(argvi) = &PL_sv_undef;
-    }
-    argvi++ ;
-    
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_ExportToJson) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    char **arg2 = (char **) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    retStringAndCPLFree *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_ExportToJson(self,options);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_ExportToJson" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    if (items > 1) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(1))) {
-          if (SvROK(ST(1))) {
-            if (SvTYPE(SvRV(ST(1)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(1)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg2 = CSLAddString( arg2, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(1)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(1));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg2 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg2 = CSLAddNameValue( arg2, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (retStringAndCPLFree *)OGRGeometryShadow_ExportToJson(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    
-    /* %typemap(out) (retStringAndCPLFree*) */
-    if(result)
-    {
-      ST(argvi) = SWIG_FromCharPtr((const char *)result);
-      CPLFree(result);
-    }
-    else
-    {
-      ST(argvi) = &PL_sv_undef;
-    }
-    argvi++ ;
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg2) CSLDestroy( arg2 );
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg2) CSLDestroy( arg2 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_AddPoint_3D) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 = (double) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 4)) {
-      SWIG_croak("Usage: Geometry_AddPoint_3D(self,x,y,z);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_AddPoint_3D" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_AddPoint_3D" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Geometry_AddPoint_3D" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    if (items > 3) {
-      ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-      if (!SWIG_IsOK(ecode4)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Geometry_AddPoint_3D" "', argument " "4"" of type '" "double""'");
-      } 
-      arg4 = static_cast< double >(val4);
-    }
-    {
-      CPLErrorReset();
-      OGRGeometryShadow_AddPoint(arg1,arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_AddPoint_2D) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Geometry_AddPoint_2D(self,x,y);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_AddPoint_2D" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_AddPoint_2D" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Geometry_AddPoint_2D" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    {
-      CPLErrorReset();
-      OGRGeometryShadow_AddPoint_2D(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_AddGeometryDirectly) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_AddGeometryDirectly(self,other_disown);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_AddGeometryDirectly" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), SWIG_as_voidptrptr(&arg2), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_DISOWN |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Geometry_AddGeometryDirectly" "', argument " "2"" of type '" "OGRGeometryShadow *""'");
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRGeometryShadow_AddGeometryDirectly(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_AddGeometry) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_AddGeometry(self,other);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_AddGeometry" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Geometry_AddGeometry" "', argument " "2"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRGeometryShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRGeometryShadow_AddGeometry(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_Clone) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Geometry_Clone(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_Clone" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)OGRGeometryShadow_Clone(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_GetGeometryType) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRwkbGeometryType result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Geometry_GetGeometryType(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_GetGeometryType" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRwkbGeometryType)OGRGeometryShadow_GetGeometryType(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_GetGeometryName) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Geometry_GetGeometryName(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_GetGeometryName" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char *)OGRGeometryShadow_GetGeometryName(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_Length) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    double result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Geometry_Length(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_Length" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (double)OGRGeometryShadow_Length(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_Area) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    double result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Geometry_Area(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_Area" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (double)OGRGeometryShadow_Area(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_GetArea) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    double result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Geometry_GetArea(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_GetArea" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (double)OGRGeometryShadow_GetArea(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_GetPointCount) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Geometry_GetPointCount(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_GetPointCount" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OGRGeometryShadow_GetPointCount(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_GetX) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    int arg2 = (int) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    double result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_GetX(self,point);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_GetX" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_GetX" "', argument " "2"" of type '" "int""'");
-      } 
-      arg2 = static_cast< int >(val2);
-    }
-    {
-      CPLErrorReset();
-      result = (double)OGRGeometryShadow_GetX(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_GetY) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    int arg2 = (int) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    double result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_GetY(self,point);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_GetY" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_GetY" "', argument " "2"" of type '" "int""'");
-      } 
-      arg2 = static_cast< int >(val2);
-    }
-    {
-      CPLErrorReset();
-      result = (double)OGRGeometryShadow_GetY(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_GetZ) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    int arg2 = (int) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    double result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_GetZ(self,point);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_GetZ" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_GetZ" "', argument " "2"" of type '" "int""'");
-      } 
-      arg2 = static_cast< int >(val2);
-    }
-    {
-      CPLErrorReset();
-      result = (double)OGRGeometryShadow_GetZ(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_GetPoint_3D) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    int arg2 = (int) 0 ;
-    double *arg3 = (double *) (double *)NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    double argout3[3] ;
-    int argvi = 0;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (double argout3[ANY]) */
-      arg3 = argout3;
-    }
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_GetPoint_3D(self,iPoint);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_GetPoint_3D" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_GetPoint_3D" "', argument " "2"" of type '" "int""'");
-      } 
-      arg2 = static_cast< int >(val2);
-    }
-    {
-      CPLErrorReset();
-      OGRGeometryShadow_GetPoint(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    {
-      /* %typemap(argout) (double argout[ANY]) */
-      if (GIMME_V == G_ARRAY) {
-        /* return a list */
-        int i;
-        EXTEND(SP, argvi+3-items+1);
-        for (i = 0; i < 3; i++)
-        ST(argvi++) = sv_2mortal(newSVnv(arg3[i]));
-      } else {
-        ST(argvi) = CreateArrayFromDoubleArray( arg3, 3 );
-        argvi++;
-      }  
-    }
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_GetPoint_2D) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    int arg2 = (int) 0 ;
-    double *arg3 = (double *) (double *)NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    double argout3[2] ;
-    int argvi = 0;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (double argout3[ANY]) */
-      arg3 = argout3;
-    }
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_GetPoint_2D(self,iPoint);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_GetPoint_2D" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_GetPoint_2D" "', argument " "2"" of type '" "int""'");
-      } 
-      arg2 = static_cast< int >(val2);
-    }
-    {
-      CPLErrorReset();
-      OGRGeometryShadow_GetPoint_2D(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    {
-      /* %typemap(argout) (double argout[ANY]) */
-      if (GIMME_V == G_ARRAY) {
-        /* return a list */
-        int i;
-        EXTEND(SP, argvi+2-items+1);
-        for (i = 0; i < 2; i++)
-        ST(argvi++) = sv_2mortal(newSVnv(arg3[i]));
-      } else {
-        ST(argvi) = CreateArrayFromDoubleArray( arg3, 2 );
-        argvi++;
-      }  
-    }
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_GetGeometryCount) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Geometry_GetGeometryCount(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_GetGeometryCount" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OGRGeometryShadow_GetGeometryCount(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_SetPoint_3D) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    int arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 = (double) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 4) || (items > 5)) {
-      SWIG_croak("Usage: Geometry_SetPoint_3D(self,point,x,y,z);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_SetPoint_3D" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_SetPoint_3D" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Geometry_SetPoint_3D" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Geometry_SetPoint_3D" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    if (items > 4) {
-      ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-      if (!SWIG_IsOK(ecode5)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Geometry_SetPoint_3D" "', argument " "5"" of type '" "double""'");
-      } 
-      arg5 = static_cast< double >(val5);
-    }
-    {
-      CPLErrorReset();
-      OGRGeometryShadow_SetPoint(arg1,arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_SetPoint_2D) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    int arg2 ;
-    double arg3 ;
-    double arg4 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 4) || (items > 4)) {
-      SWIG_croak("Usage: Geometry_SetPoint_2D(self,point,x,y);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_SetPoint_2D" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_SetPoint_2D" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Geometry_SetPoint_2D" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Geometry_SetPoint_2D" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    {
-      CPLErrorReset();
-      OGRGeometryShadow_SetPoint_2D(arg1,arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_GetGeometryRef) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_GetGeometryRef(self,geom);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_GetGeometryRef" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_GetGeometryRef" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)OGRGeometryShadow_GetGeometryRef(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_Simplify) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    double arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_Simplify(self,tolerance);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_Simplify" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_Simplify" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)OGRGeometryShadow_Simplify(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_SimplifyPreserveTopology) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    double arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_SimplifyPreserveTopology(self,tolerance);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_SimplifyPreserveTopology" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_SimplifyPreserveTopology" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)OGRGeometryShadow_SimplifyPreserveTopology(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_Boundary) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Geometry_Boundary(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_Boundary" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)OGRGeometryShadow_Boundary(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_GetBoundary) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Geometry_GetBoundary(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_GetBoundary" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)OGRGeometryShadow_GetBoundary(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_ConvexHull) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Geometry_ConvexHull(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_ConvexHull" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)OGRGeometryShadow_ConvexHull(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_Buffer) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    double arg2 ;
-    int arg3 = (int) 30 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 3)) {
-      SWIG_croak("Usage: Geometry_Buffer(self,distance,quadsecs);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_Buffer" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_Buffer" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    if (items > 2) {
-      ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-      if (!SWIG_IsOK(ecode3)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Geometry_Buffer" "', argument " "3"" of type '" "int""'");
-      } 
-      arg3 = static_cast< int >(val3);
-    }
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)OGRGeometryShadow_Buffer(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_Intersection) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_Intersection(self,other);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_Intersection" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Geometry_Intersection" "', argument " "2"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRGeometryShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)OGRGeometryShadow_Intersection(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_Union) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_Union(self,other);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_Union" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Geometry_Union" "', argument " "2"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRGeometryShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)OGRGeometryShadow_Union(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_UnionCascaded) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Geometry_UnionCascaded(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_UnionCascaded" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)OGRGeometryShadow_UnionCascaded(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_Difference) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_Difference(self,other);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_Difference" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Geometry_Difference" "', argument " "2"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRGeometryShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)OGRGeometryShadow_Difference(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_SymDifference) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_SymDifference(self,other);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_SymDifference" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Geometry_SymDifference" "', argument " "2"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRGeometryShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)OGRGeometryShadow_SymDifference(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_SymmetricDifference) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_SymmetricDifference(self,other);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_SymmetricDifference" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Geometry_SymmetricDifference" "', argument " "2"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRGeometryShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)OGRGeometryShadow_SymmetricDifference(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_Distance) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    double result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_Distance(self,other);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_Distance" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Geometry_Distance" "', argument " "2"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRGeometryShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (double)OGRGeometryShadow_Distance(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_Empty) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Geometry_Empty(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_Empty" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      OGRGeometryShadow_Empty(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_IsEmpty) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    bool result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Geometry_IsEmpty(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_IsEmpty" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (bool)OGRGeometryShadow_IsEmpty(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_IsValid) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    bool result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Geometry_IsValid(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_IsValid" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (bool)OGRGeometryShadow_IsValid(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_IsSimple) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    bool result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Geometry_IsSimple(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_IsSimple" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (bool)OGRGeometryShadow_IsSimple(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_IsRing) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    bool result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Geometry_IsRing(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_IsRing" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (bool)OGRGeometryShadow_IsRing(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_Intersects) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    bool result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_Intersects(self,other);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_Intersects" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Geometry_Intersects" "', argument " "2"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRGeometryShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (bool)OGRGeometryShadow_Intersects(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_Intersect) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    bool result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_Intersect(self,other);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_Intersect" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Geometry_Intersect" "', argument " "2"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRGeometryShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (bool)OGRGeometryShadow_Intersect(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_Equals) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    bool result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_Equals(self,other);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_Equals" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Geometry_Equals" "', argument " "2"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRGeometryShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (bool)OGRGeometryShadow_Equals(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_Equal) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    bool result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_Equal(self,other);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_Equal" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Geometry_Equal" "', argument " "2"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRGeometryShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (bool)OGRGeometryShadow_Equal(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_Disjoint) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    bool result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_Disjoint(self,other);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_Disjoint" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Geometry_Disjoint" "', argument " "2"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRGeometryShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (bool)OGRGeometryShadow_Disjoint(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_Touches) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    bool result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_Touches(self,other);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_Touches" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Geometry_Touches" "', argument " "2"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRGeometryShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (bool)OGRGeometryShadow_Touches(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_Crosses) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    bool result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_Crosses(self,other);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_Crosses" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Geometry_Crosses" "', argument " "2"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRGeometryShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (bool)OGRGeometryShadow_Crosses(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_Within) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    bool result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_Within(self,other);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_Within" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Geometry_Within" "', argument " "2"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRGeometryShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (bool)OGRGeometryShadow_Within(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_Contains) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    bool result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_Contains(self,other);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_Contains" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Geometry_Contains" "', argument " "2"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRGeometryShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (bool)OGRGeometryShadow_Contains(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_Overlaps) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    bool result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_Overlaps(self,other);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_Overlaps" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Geometry_Overlaps" "', argument " "2"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OGRGeometryShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (bool)OGRGeometryShadow_Overlaps(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_TransformTo) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    OSRSpatialReferenceShadow *arg2 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_TransformTo(self,reference);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_TransformTo" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Geometry_TransformTo" "', argument " "2"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRGeometryShadow_TransformTo(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_Transform) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    OSRCoordinateTransformationShadow *arg2 = (OSRCoordinateTransformationShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_Transform(self,trans);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_Transform" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OSRCoordinateTransformationShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Geometry_Transform" "', argument " "2"" of type '" "OSRCoordinateTransformationShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OSRCoordinateTransformationShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRGeometryShadow_Transform(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_GetSpatialReference) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OSRSpatialReferenceShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Geometry_GetSpatialReference(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_GetSpatialReference" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OSRSpatialReferenceShadow *)OGRGeometryShadow_GetSpatialReference(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OSRSpatialReferenceShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_AssignSpatialReference) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    OSRSpatialReferenceShadow *arg2 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_AssignSpatialReference(self,reference);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_AssignSpatialReference" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Geometry_AssignSpatialReference" "', argument " "2"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp2);
-    {
-      CPLErrorReset();
-      OGRGeometryShadow_AssignSpatialReference(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_CloseRings) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Geometry_CloseRings(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_CloseRings" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      OGRGeometryShadow_CloseRings(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_FlattenTo2D) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Geometry_FlattenTo2D(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_FlattenTo2D" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      OGRGeometryShadow_FlattenTo2D(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_Segmentize) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    double arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_Segmentize(self,dfMaxLength);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_Segmentize" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_Segmentize" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    {
-      CPLErrorReset();
-      OGRGeometryShadow_Segmentize(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_GetEnvelope) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    double *arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double argout2[4] ;
-    int argvi = 0;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (double argout2[ANY]) */
-      arg2 = argout2;
-    }
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Geometry_GetEnvelope(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_GetEnvelope" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      OGRGeometryShadow_GetEnvelope(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    {
-      /* %typemap(argout) (double argout[ANY]) */
-      if (GIMME_V == G_ARRAY) {
-        /* return a list */
-        int i;
-        EXTEND(SP, argvi+4-items+1);
-        for (i = 0; i < 4; i++)
-        ST(argvi++) = sv_2mortal(newSVnv(arg2[i]));
-      } else {
-        ST(argvi) = CreateArrayFromDoubleArray( arg2, 4 );
-        argvi++;
-      }  
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_GetEnvelope3D) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    double *arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double argout2[6] ;
-    int argvi = 0;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (double argout2[ANY]) */
-      arg2 = argout2;
-    }
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Geometry_GetEnvelope3D(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_GetEnvelope3D" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      OGRGeometryShadow_GetEnvelope3D(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    {
-      /* %typemap(argout) (double argout[ANY]) */
-      if (GIMME_V == G_ARRAY) {
-        /* return a list */
-        int i;
-        EXTEND(SP, argvi+6-items+1);
-        for (i = 0; i < 6; i++)
-        ST(argvi++) = sv_2mortal(newSVnv(arg2[i]));
-      } else {
-        ST(argvi) = CreateArrayFromDoubleArray( arg2, 6 );
-        argvi++;
-      }  
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_Centroid) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Geometry_Centroid(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_Centroid" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)OGRGeometryShadow_Centroid(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_PointOnSurface) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Geometry_PointOnSurface(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_PointOnSurface" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)OGRGeometryShadow_PointOnSurface(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_WkbSize) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Geometry_WkbSize(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_WkbSize" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OGRGeometryShadow_WkbSize(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_GetCoordinateDimension) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Geometry_GetCoordinateDimension(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_GetCoordinateDimension" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OGRGeometryShadow_GetCoordinateDimension(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_SetCoordinateDimension) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_SetCoordinateDimension(self,dimension);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_SetCoordinateDimension" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_SetCoordinateDimension" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      OGRGeometryShadow_SetCoordinateDimension(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_GetDimension) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Geometry_GetDimension(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_GetDimension" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OGRGeometryShadow_GetDimension(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_HasCurveGeometry) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    int arg2 = (int) FALSE ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_HasCurveGeometry(self,bLookForCircular);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_HasCurveGeometry" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_HasCurveGeometry" "', argument " "2"" of type '" "int""'");
-      } 
-      arg2 = static_cast< int >(val2);
-    }
-    {
-      CPLErrorReset();
-      result = (int)OGRGeometryShadow_HasCurveGeometry(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_GetLinearGeometry) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    double arg2 = (double) 0.0 ;
-    char **arg3 = (char **) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 3)) {
-      SWIG_croak("Usage: Geometry_GetLinearGeometry(self,dfMaxAngleStepSizeDegrees,options);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_GetLinearGeometry" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_GetLinearGeometry" "', argument " "2"" of type '" "double""'");
-      } 
-      arg2 = static_cast< double >(val2);
-    }
-    if (items > 2) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(2))) {
-          if (SvROK(ST(2))) {
-            if (SvTYPE(SvRV(ST(2)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(2)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg3 = CSLAddString( arg3, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(2)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(2));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg3 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg3 = CSLAddNameValue( arg3, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)OGRGeometryShadow_GetLinearGeometry(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg3) CSLDestroy( arg3 );
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg3) CSLDestroy( arg3 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_GetCurveGeometry) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    char **arg2 = (char **) NULL ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_GetCurveGeometry(self,options);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_GetCurveGeometry" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    if (items > 1) {
-      {
-        /* %typemap(in) char **options */
-        if (SvOK(ST(1))) {
-          if (SvROK(ST(1))) {
-            if (SvTYPE(SvRV(ST(1)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(1)));
-              for (int i = 0; i < av_len(av)+1; i++) {
-                SV *sv = *(av_fetch(av, i, 0));
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                char *pszItem = SvPV_nolen(sv);
-                arg2 = CSLAddString( arg2, pszItem );
-              }
-            } else if (SvTYPE(SvRV(ST(1)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(1));
-              SV *sv;
-              char *key;
-              I32 klen;
-              arg2 = NULL;
-              hv_iterinit(hv);
-              while(sv = hv_iternextsv(hv,&key,&klen)) {
-                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-                arg2 = CSLAddNameValue( arg2, key, SvPV_nolen(sv) );
-              }
-            } else
-            SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-          } else
-          SWIG_croak("The 'options' argument is not a reference.");   
-        }
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)OGRGeometryShadow_GetCurveGeometry(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg2) CSLDestroy( arg2 );
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg2) CSLDestroy( arg2 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_Value) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    double arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    OGRGeometryShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Geometry_Value(self,dfDistance);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_Value" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_Value" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    {
-      CPLErrorReset();
-      result = (OGRGeometryShadow *)OGRGeometryShadow_Value(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Geometry_Move) {
-  {
-    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 = (double) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 4)) {
-      SWIG_croak("Usage: Geometry_Move(self,dx,dy,dz);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_Move" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_Move" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Geometry_Move" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    if (items > 3) {
-      ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-      if (!SWIG_IsOK(ecode4)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Geometry_Move" "', argument " "4"" of type '" "double""'");
-      } 
-      arg4 = static_cast< double >(val4);
-    }
-    {
-      CPLErrorReset();
-      OGRGeometryShadow_Move(arg1,arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GetDriverCount) {
-  {
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 0)) {
-      SWIG_croak("Usage: GetDriverCount();");
-    }
-    {
-      CPLErrorReset();
-      result = (int)OGRGetDriverCount();
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GetOpenDSCount) {
-  {
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 0)) {
-      SWIG_croak("Usage: GetOpenDSCount();");
-    }
-    {
-      CPLErrorReset();
-      result = (int)OGRGetOpenDSCount();
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SetGenerate_DB2_V72_BYTE_ORDER) {
-  {
-    int arg1 ;
-    int val1 ;
-    int ecode1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SetGenerate_DB2_V72_BYTE_ORDER(bGenerate_DB2_V72_BYTE_ORDER);");
-    }
-    ecode1 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "SetGenerate_DB2_V72_BYTE_ORDER" "', argument " "1"" of type '" "int""'");
-    } 
-    arg1 = static_cast< int >(val1);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRSetGenerate_DB2_V72_BYTE_ORDER(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_RegisterAll) {
-  {
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 0)) {
-      SWIG_croak("Usage: RegisterAll();");
-    }
-    {
-      CPLErrorReset();
-      OGRRegisterAll();
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GeometryTypeToName) {
-  {
-    OGRwkbGeometryType arg1 ;
-    int val1 ;
-    int ecode1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GeometryTypeToName(eType);");
-    }
-    ecode1 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "GeometryTypeToName" "', argument " "1"" of type '" "OGRwkbGeometryType""'");
-    } 
-    arg1 = static_cast< OGRwkbGeometryType >(val1);
-    {
-      CPLErrorReset();
-      result = (char *)OGRGeometryTypeToName(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GetFieldTypeName) {
-  {
-    OGRFieldType arg1 ;
-    int val1 ;
-    int ecode1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GetFieldTypeName(type);");
-    }
-    ecode1 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "GetFieldTypeName" "', argument " "1"" of type '" "OGRFieldType""'");
-    } 
-    arg1 = static_cast< OGRFieldType >(val1);
-    {
-      CPLErrorReset();
-      result = (char *)OGR_GetFieldTypeName(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GetFieldSubTypeName) {
-  {
-    OGRFieldSubType arg1 ;
-    int val1 ;
-    int ecode1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GetFieldSubTypeName(type);");
-    }
-    ecode1 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "GetFieldSubTypeName" "', argument " "1"" of type '" "OGRFieldSubType""'");
-    } 
-    arg1 = static_cast< OGRFieldSubType >(val1);
-    {
-      CPLErrorReset();
-      result = (char *)OGR_GetFieldSubTypeName(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GT_Flatten) {
-  {
-    OGRwkbGeometryType arg1 ;
-    int val1 ;
-    int ecode1 = 0 ;
-    int argvi = 0;
-    OGRwkbGeometryType result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GT_Flatten(eType);");
-    }
-    ecode1 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "GT_Flatten" "', argument " "1"" of type '" "OGRwkbGeometryType""'");
-    } 
-    arg1 = static_cast< OGRwkbGeometryType >(val1);
-    {
-      CPLErrorReset();
-      result = (OGRwkbGeometryType)OGR_GT_Flatten(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GT_SetZ) {
-  {
-    OGRwkbGeometryType arg1 ;
-    int val1 ;
-    int ecode1 = 0 ;
-    int argvi = 0;
-    OGRwkbGeometryType result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GT_SetZ(eType);");
-    }
-    ecode1 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "GT_SetZ" "', argument " "1"" of type '" "OGRwkbGeometryType""'");
-    } 
-    arg1 = static_cast< OGRwkbGeometryType >(val1);
-    {
-      CPLErrorReset();
-      result = (OGRwkbGeometryType)OGR_GT_SetZ(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GT_SetModifier) {
-  {
-    OGRwkbGeometryType arg1 ;
-    int arg2 ;
-    int arg3 = (int) FALSE ;
-    int val1 ;
-    int ecode1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    OGRwkbGeometryType result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 3)) {
-      SWIG_croak("Usage: GT_SetModifier(eType,bSetZ,bSetM);");
-    }
-    ecode1 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "GT_SetModifier" "', argument " "1"" of type '" "OGRwkbGeometryType""'");
-    } 
-    arg1 = static_cast< OGRwkbGeometryType >(val1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "GT_SetModifier" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    if (items > 2) {
-      ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-      if (!SWIG_IsOK(ecode3)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "GT_SetModifier" "', argument " "3"" of type '" "int""'");
-      } 
-      arg3 = static_cast< int >(val3);
-    }
-    {
-      CPLErrorReset();
-      result = (OGRwkbGeometryType)GT_SetModifier(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GT_HasZ) {
-  {
-    OGRwkbGeometryType arg1 ;
-    int val1 ;
-    int ecode1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GT_HasZ(eType);");
-    }
-    ecode1 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "GT_HasZ" "', argument " "1"" of type '" "OGRwkbGeometryType""'");
-    } 
-    arg1 = static_cast< OGRwkbGeometryType >(val1);
-    {
-      CPLErrorReset();
-      result = (int)OGR_GT_HasZ(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GT_IsSubClassOf) {
-  {
-    OGRwkbGeometryType arg1 ;
-    OGRwkbGeometryType arg2 ;
-    int val1 ;
-    int ecode1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: GT_IsSubClassOf(eType,eSuperType);");
-    }
-    ecode1 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "GT_IsSubClassOf" "', argument " "1"" of type '" "OGRwkbGeometryType""'");
-    } 
-    arg1 = static_cast< OGRwkbGeometryType >(val1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "GT_IsSubClassOf" "', argument " "2"" of type '" "OGRwkbGeometryType""'");
-    } 
-    arg2 = static_cast< OGRwkbGeometryType >(val2);
-    {
-      CPLErrorReset();
-      result = (int)OGR_GT_IsSubClassOf(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GT_IsCurve) {
-  {
-    OGRwkbGeometryType arg1 ;
-    int val1 ;
-    int ecode1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GT_IsCurve(OGRwkbGeometryType);");
-    }
-    ecode1 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "GT_IsCurve" "', argument " "1"" of type '" "OGRwkbGeometryType""'");
-    } 
-    arg1 = static_cast< OGRwkbGeometryType >(val1);
-    {
-      CPLErrorReset();
-      result = (int)OGR_GT_IsCurve(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GT_IsSurface) {
-  {
-    OGRwkbGeometryType arg1 ;
-    int val1 ;
-    int ecode1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GT_IsSurface(OGRwkbGeometryType);");
-    }
-    ecode1 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "GT_IsSurface" "', argument " "1"" of type '" "OGRwkbGeometryType""'");
-    } 
-    arg1 = static_cast< OGRwkbGeometryType >(val1);
-    {
-      CPLErrorReset();
-      result = (int)OGR_GT_IsSurface(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GT_IsNonLinear) {
-  {
-    OGRwkbGeometryType arg1 ;
-    int val1 ;
-    int ecode1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GT_IsNonLinear(OGRwkbGeometryType);");
-    }
-    ecode1 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "GT_IsNonLinear" "', argument " "1"" of type '" "OGRwkbGeometryType""'");
-    } 
-    arg1 = static_cast< OGRwkbGeometryType >(val1);
-    {
-      CPLErrorReset();
-      result = (int)OGR_GT_IsNonLinear(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GT_GetCollection) {
-  {
-    OGRwkbGeometryType arg1 ;
-    int val1 ;
-    int ecode1 = 0 ;
-    int argvi = 0;
-    OGRwkbGeometryType result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GT_GetCollection(eType);");
-    }
-    ecode1 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "GT_GetCollection" "', argument " "1"" of type '" "OGRwkbGeometryType""'");
-    } 
-    arg1 = static_cast< OGRwkbGeometryType >(val1);
-    {
-      CPLErrorReset();
-      result = (OGRwkbGeometryType)OGR_GT_GetCollection(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GT_GetCurve) {
-  {
-    OGRwkbGeometryType arg1 ;
-    int val1 ;
-    int ecode1 = 0 ;
-    int argvi = 0;
-    OGRwkbGeometryType result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GT_GetCurve(eType);");
-    }
-    ecode1 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "GT_GetCurve" "', argument " "1"" of type '" "OGRwkbGeometryType""'");
-    } 
-    arg1 = static_cast< OGRwkbGeometryType >(val1);
-    {
-      CPLErrorReset();
-      result = (OGRwkbGeometryType)OGR_GT_GetCurve(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GT_GetLinear) {
-  {
-    OGRwkbGeometryType arg1 ;
-    int val1 ;
-    int ecode1 = 0 ;
-    int argvi = 0;
-    OGRwkbGeometryType result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GT_GetLinear(eType);");
-    }
-    ecode1 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "GT_GetLinear" "', argument " "1"" of type '" "OGRwkbGeometryType""'");
-    } 
-    arg1 = static_cast< OGRwkbGeometryType >(val1);
-    {
-      CPLErrorReset();
-      result = (OGRwkbGeometryType)OGR_GT_GetLinear(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SetNonLinearGeometriesEnabledFlag) {
-  {
-    int arg1 ;
-    int val1 ;
-    int ecode1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SetNonLinearGeometriesEnabledFlag(bFlag);");
-    }
-    ecode1 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "SetNonLinearGeometriesEnabledFlag" "', argument " "1"" of type '" "int""'");
-    } 
-    arg1 = static_cast< int >(val1);
-    {
-      CPLErrorReset();
-      OGRSetNonLinearGeometriesEnabledFlag(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GetNonLinearGeometriesEnabledFlag) {
-  {
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 0)) {
-      SWIG_croak("Usage: GetNonLinearGeometriesEnabledFlag();");
-    }
-    {
-      CPLErrorReset();
-      result = (int)OGRGetNonLinearGeometriesEnabledFlag();
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GetOpenDS) {
-  {
-    int arg1 ;
-    int val1 ;
-    int ecode1 = 0 ;
-    int argvi = 0;
-    OGRDataSourceShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GetOpenDS(ds_number);");
-    }
-    ecode1 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "GetOpenDS" "', argument " "1"" of type '" "int""'");
-    } 
-    arg1 = static_cast< int >(val1);
-    {
-      CPLErrorReset();
-      result = (OGRDataSourceShadow *)GetOpenDS(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDataSourceShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Open) {
-  {
-    char *arg1 = (char *) 0 ;
-    int arg2 = (int) 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    OGRDataSourceShadow *result = 0 ;
-    dXSARGS;
-    
-    {
-      /* %typemap(default) const char * utf8_path */
-      arg1 = (char *)"";
-    }
-    if ((items < 0) || (items > 2)) {
-      SWIG_croak("Usage: Open(utf8_path,update);");
-    }
-    if (items > 0) {
-      {
-        /* %typemap(in,numinputs=1) (const char* utf8_path) */
-        sv_utf8_upgrade(ST(0));
-        arg1 = SvPV_nolen(ST(0));
-      }
-    }
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Open" "', argument " "2"" of type '" "int""'");
-      } 
-      arg2 = static_cast< int >(val2);
-    }
-    {
-      CPLErrorReset();
-      result = (OGRDataSourceShadow *)Open((char const *)arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDataSourceShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_OpenShared) {
-  {
-    char *arg1 = (char *) 0 ;
-    int arg2 = (int) 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    OGRDataSourceShadow *result = 0 ;
-    dXSARGS;
-    
-    {
-      /* %typemap(default) const char * utf8_path */
-      arg1 = (char *)"";
-    }
-    if ((items < 0) || (items > 2)) {
-      SWIG_croak("Usage: OpenShared(utf8_path,update);");
-    }
-    if (items > 0) {
-      {
-        /* %typemap(in,numinputs=1) (const char* utf8_path) */
-        sv_utf8_upgrade(ST(0));
-        arg1 = SvPV_nolen(ST(0));
-      }
-    }
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "OpenShared" "', argument " "2"" of type '" "int""'");
-      } 
-      arg2 = static_cast< int >(val2);
-    }
-    {
-      CPLErrorReset();
-      result = (OGRDataSourceShadow *)OpenShared((char const *)arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDataSourceShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GetDriverByName) {
-  {
-    char *arg1 = (char *) 0 ;
-    int argvi = 0;
-    OGRDriverShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GetDriverByName(name);");
-    }
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(0));
-      arg1 = SvPV_nolen(ST(0));
-    }
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRDriverShadow *)GetDriverByName((char const *)arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDriverShadow, 0 | SWIG_SHADOW); argvi++ ;
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap__GetDriver) {
-  {
-    int arg1 ;
-    int val1 ;
-    int ecode1 = 0 ;
-    int argvi = 0;
-    OGRDriverShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: _GetDriver(driver_number);");
-    }
-    ecode1 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "_GetDriver" "', argument " "1"" of type '" "int""'");
-    } 
-    arg1 = static_cast< int >(val1);
-    {
-      CPLErrorReset();
-      result = (OGRDriverShadow *)GetDriver(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDriverShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GeneralCmdLineProcessor) {
-  {
-    char **arg1 = (char **) 0 ;
-    int arg2 = (int) 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    char **result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: GeneralCmdLineProcessor(papszArgv,nOptions);");
-    }
-    {
-      /* %typemap(in) char **options */
-      if (SvOK(ST(0))) {
-        if (SvROK(ST(0))) {
-          if (SvTYPE(SvRV(ST(0)))==SVt_PVAV) {
-            AV *av = (AV*)(SvRV(ST(0)));
-            for (int i = 0; i < av_len(av)+1; i++) {
-              SV *sv = *(av_fetch(av, i, 0));
-              sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-              char *pszItem = SvPV_nolen(sv);
-              arg1 = CSLAddString( arg1, pszItem );
-            }
-          } else if (SvTYPE(SvRV(ST(0)))==SVt_PVHV) {
-            HV *hv = (HV*)SvRV(ST(0));
-            SV *sv;
-            char *key;
-            I32 klen;
-            arg1 = NULL;
-            hv_iterinit(hv);
-            while(sv = hv_iternextsv(hv,&key,&klen)) {
-              sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-              arg1 = CSLAddNameValue( arg1, key, SvPV_nolen(sv) );
-            }
-          } else
-          SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-        } else
-        SWIG_croak("The 'options' argument is not a reference.");   
-      }
-    }
-    if (items > 1) {
-      ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-      if (!SWIG_IsOK(ecode2)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "GeneralCmdLineProcessor" "', argument " "2"" of type '" "int""'");
-      } 
-      arg2 = static_cast< int >(val2);
-    }
-    {
-      CPLErrorReset();
-      result = (char **)GeneralCmdLineProcessor(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) char **options -> ( string ) */
-      AV* av = (AV*)sv_2mortal((SV*)newAV());
-      char **stringarray = result;
-      if ( stringarray != NULL ) {
-        int n = CSLCount( stringarray );
-        for ( int i = 0; i < n; i++ ) {
-          SV *sv = newSVpv(stringarray[i], 0);
-          SvUTF8_on(sv); /* expecting UTF-8 from GDAL */
-          if (!av_store(av, i, sv))
-          SvREFCNT_dec(sv);
-        }
-      }
-      ST(argvi) = newRV((SV*)av);
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    {
-      /* %typemap(freearg) char **options */
-      if (arg1) CSLDestroy( arg1 );
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    {
-      /* %typemap(freearg) char **options */
-      if (arg1) CSLDestroy( arg1 );
-    }
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_TermProgress_nocb) {
-  {
-    double arg1 ;
-    char *arg2 = (char *) NULL ;
-    void *arg3 = (void *) NULL ;
-    double val1 ;
-    int ecode1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int res3 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 3)) {
-      SWIG_croak("Usage: TermProgress_nocb(dfProgress,pszMessage,pData);");
-    }
-    ecode1 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-    if (!SWIG_IsOK(ecode1)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "TermProgress_nocb" "', argument " "1"" of type '" "double""'");
-    } 
-    arg1 = static_cast< double >(val1);
-    if (items > 1) {
-      res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-      if (!SWIG_IsOK(res2)) {
-        SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "TermProgress_nocb" "', argument " "2"" of type '" "char const *""'");
-      }
-      arg2 = reinterpret_cast< char * >(buf2);
-    }
-    if (items > 2) {
-      res3 = SWIG_ConvertPtr(ST(2),SWIG_as_voidptrptr(&arg3), 0, 0);
-      if (!SWIG_IsOK(res3)) {
-        SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "TermProgress_nocb" "', argument " "3"" of type '" "void *""'"); 
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (int)GDALTermProgress_nocb(arg1,(char const *)arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    
-    SWIG_croak_null();
-  }
-}
-
-
-
-/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */
-
-static void *_p_OGRDriverShadowTo_p_GDALMajorObjectShadow(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((GDALMajorObjectShadow *)  ((OGRDriverShadow *) x));
-}
-static void *_p_OGRLayerShadowTo_p_GDALMajorObjectShadow(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((GDALMajorObjectShadow *)  ((OGRLayerShadow *) x));
-}
-static void *_p_OGRDataSourceShadowTo_p_GDALMajorObjectShadow(void *x, int *SWIGUNUSEDPARM(newmemory)) {
-    return (void *)((GDALMajorObjectShadow *)  ((OGRDataSourceShadow *) x));
-}
-static swig_type_info _swigt__p_GDALMajorObjectShadow = {"_p_GDALMajorObjectShadow", "GDALMajorObjectShadow *", 0, 0, (void*)"Geo::GDAL::MajorObject", 0};
-static swig_type_info _swigt__p_GDALProgressFunc = {"_p_GDALProgressFunc", "GDALProgressFunc *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_GIntBig = {"_p_GIntBig", "GIntBig *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_OGRDataSourceShadow = {"_p_OGRDataSourceShadow", "OGRDataSourceShadow *", 0, 0, (void*)"Geo::OGR::DataSource", 0};
-static swig_type_info _swigt__p_OGRDriverShadow = {"_p_OGRDriverShadow", "OGRDriverShadow *", 0, 0, (void*)"Geo::OGR::Driver", 0};
-static swig_type_info _swigt__p_OGRFeatureDefnShadow = {"_p_OGRFeatureDefnShadow", "OGRFeatureDefnShadow *", 0, 0, (void*)"Geo::OGR::FeatureDefn", 0};
-static swig_type_info _swigt__p_OGRFeatureShadow = {"_p_OGRFeatureShadow", "OGRFeatureShadow *", 0, 0, (void*)"Geo::OGR::Feature", 0};
-static swig_type_info _swigt__p_OGRFieldDefnShadow = {"_p_OGRFieldDefnShadow", "OGRFieldDefnShadow *", 0, 0, (void*)"Geo::OGR::FieldDefn", 0};
-static swig_type_info _swigt__p_OGRGeomFieldDefnShadow = {"_p_OGRGeomFieldDefnShadow", "OGRGeomFieldDefnShadow *", 0, 0, (void*)"Geo::OGR::GeomFieldDefn", 0};
-static swig_type_info _swigt__p_OGRGeometryShadow = {"_p_OGRGeometryShadow", "OGRGeometryShadow *", 0, 0, (void*)"Geo::OGR::Geometry", 0};
-static swig_type_info _swigt__p_OGRLayerShadow = {"_p_OGRLayerShadow", "OGRLayerShadow *", 0, 0, (void*)"Geo::OGR::Layer", 0};
-static swig_type_info _swigt__p_OGRStyleTableShadow = {"_p_OGRStyleTableShadow", "OGRStyleTableShadow *", 0, 0, (void*)"Geo::OGR::StyleTable", 0};
-static swig_type_info _swigt__p_OSRCoordinateTransformationShadow = {"_p_OSRCoordinateTransformationShadow", "OSRCoordinateTransformationShadow *", 0, 0, (void*)"Geo::OSR::CoordinateTransformation", 0};
-static swig_type_info _swigt__p_OSRSpatialReferenceShadow = {"_p_OSRSpatialReferenceShadow", "OSRSpatialReferenceShadow *", 0, 0, (void*)"Geo::OSR::SpatialReference", 0};
-static swig_type_info _swigt__p_char = {"_p_char", "char *|retStringAndCPLFree *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_double = {"_p_double", "double *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_f_double_p_q_const__char_p_void__int = {"_p_f_double_p_q_const__char_p_void__int", "int (*)(double,char const *,void *)", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_float = {"_p_float", "float *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_int = {"_p_int", "OGRFieldSubType *|OGRFieldType *|int *|OGRwkbGeometryType *|OGRJustification *|OGRwkbByteOrder *|OGRErr *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_p_char = {"_p_p_char", "char **", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_p_double = {"_p_p_double", "double **", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_p_int = {"_p_p_int", "int **", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_p_p_char = {"_p_p_p_char", "char ***", 0, 0, (void*)0, 0};
-
-static swig_type_info *swig_type_initial[] = {
-  &_swigt__p_GDALMajorObjectShadow,
-  &_swigt__p_GDALProgressFunc,
-  &_swigt__p_GIntBig,
-  &_swigt__p_OGRDataSourceShadow,
-  &_swigt__p_OGRDriverShadow,
-  &_swigt__p_OGRFeatureDefnShadow,
-  &_swigt__p_OGRFeatureShadow,
-  &_swigt__p_OGRFieldDefnShadow,
-  &_swigt__p_OGRGeomFieldDefnShadow,
-  &_swigt__p_OGRGeometryShadow,
-  &_swigt__p_OGRLayerShadow,
-  &_swigt__p_OGRStyleTableShadow,
-  &_swigt__p_OSRCoordinateTransformationShadow,
-  &_swigt__p_OSRSpatialReferenceShadow,
-  &_swigt__p_char,
-  &_swigt__p_double,
-  &_swigt__p_f_double_p_q_const__char_p_void__int,
-  &_swigt__p_float,
-  &_swigt__p_int,
-  &_swigt__p_p_char,
-  &_swigt__p_p_double,
-  &_swigt__p_p_int,
-  &_swigt__p_p_p_char,
-};
-
-static swig_cast_info _swigc__p_GDALMajorObjectShadow[] = {  {&_swigt__p_GDALMajorObjectShadow, 0, 0, 0},  {&_swigt__p_OGRDriverShadow, _p_OGRDriverShadowTo_p_GDALMajorObjectShadow, 0, 0},  {&_swigt__p_OGRLayerShadow, _p_OGRLayerShadowTo_p_GDALMajorObjectShadow, 0, 0},  {&_swigt__p_OGRDataSourceShadow, _p_OGRDataSourceShadowTo_p_GDALMajorObjectShadow, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_GDALProgressFunc[] = {  {&_swigt__p_GDALProgressFunc, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_GIntBig[] = {  {&_swigt__p_GIntBig, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_OGRDataSourceShadow[] = {  {&_swigt__p_OGRDataSourceShadow, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_OGRDriverShadow[] = {  {&_swigt__p_OGRDriverShadow, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_OGRFeatureDefnShadow[] = {  {&_swigt__p_OGRFeatureDefnShadow, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_OGRFeatureShadow[] = {  {&_swigt__p_OGRFeatureShadow, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_OGRFieldDefnShadow[] = {  {&_swigt__p_OGRFieldDefnShadow, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_OGRGeomFieldDefnShadow[] = {  {&_swigt__p_OGRGeomFieldDefnShadow, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_OGRGeometryShadow[] = {  {&_swigt__p_OGRGeometryShadow, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_OGRLayerShadow[] = {  {&_swigt__p_OGRLayerShadow, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_OGRStyleTableShadow[] = {  {&_swigt__p_OGRStyleTableShadow, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_OSRCoordinateTransformationShadow[] = {  {&_swigt__p_OSRCoordinateTransformationShadow, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_OSRSpatialReferenceShadow[] = {  {&_swigt__p_OSRSpatialReferenceShadow, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_char[] = {  {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_double[] = {  {&_swigt__p_double, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_f_double_p_q_const__char_p_void__int[] = {  {&_swigt__p_f_double_p_q_const__char_p_void__int, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_float[] = {  {&_swigt__p_float, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_int[] = {  {&_swigt__p_int, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_p_char[] = {  {&_swigt__p_p_char, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_p_double[] = {  {&_swigt__p_p_double, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_p_int[] = {  {&_swigt__p_p_int, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_p_p_char[] = {  {&_swigt__p_p_p_char, 0, 0, 0},{0, 0, 0, 0}};
-
-static swig_cast_info *swig_cast_initial[] = {
-  _swigc__p_GDALMajorObjectShadow,
-  _swigc__p_GDALProgressFunc,
-  _swigc__p_GIntBig,
-  _swigc__p_OGRDataSourceShadow,
-  _swigc__p_OGRDriverShadow,
-  _swigc__p_OGRFeatureDefnShadow,
-  _swigc__p_OGRFeatureShadow,
-  _swigc__p_OGRFieldDefnShadow,
-  _swigc__p_OGRGeomFieldDefnShadow,
-  _swigc__p_OGRGeometryShadow,
-  _swigc__p_OGRLayerShadow,
-  _swigc__p_OGRStyleTableShadow,
-  _swigc__p_OSRCoordinateTransformationShadow,
-  _swigc__p_OSRSpatialReferenceShadow,
-  _swigc__p_char,
-  _swigc__p_double,
-  _swigc__p_f_double_p_q_const__char_p_void__int,
-  _swigc__p_float,
-  _swigc__p_int,
-  _swigc__p_p_char,
-  _swigc__p_p_double,
-  _swigc__p_p_int,
-  _swigc__p_p_p_char,
-};
-
-
-/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */
-
-static swig_constant_info swig_constants[] = {
-{0,0,0,0,0,0}
-};
-#ifdef __cplusplus
-}
-#endif
-static swig_variable_info swig_variables[] = {
-{0,0,0,0}
-};
-static swig_command_info swig_commands[] = {
-{"Geo::OGRc::callback_d_cp_vp", _wrap_callback_d_cp_vp},
-{"Geo::OGRc::UseExceptions", _wrap_UseExceptions},
-{"Geo::OGRc::DontUseExceptions", _wrap_DontUseExceptions},
-{"Geo::OGRc::new_StyleTable", _wrap_new_StyleTable},
-{"Geo::OGRc::delete_StyleTable", _wrap_delete_StyleTable},
-{"Geo::OGRc::StyleTable_AddStyle", _wrap_StyleTable_AddStyle},
-{"Geo::OGRc::StyleTable_LoadStyleTable", _wrap_StyleTable_LoadStyleTable},
-{"Geo::OGRc::StyleTable_SaveStyleTable", _wrap_StyleTable_SaveStyleTable},
-{"Geo::OGRc::StyleTable_Find", _wrap_StyleTable_Find},
-{"Geo::OGRc::StyleTable_ResetStyleStringReading", _wrap_StyleTable_ResetStyleStringReading},
-{"Geo::OGRc::StyleTable_GetNextStyle", _wrap_StyleTable_GetNextStyle},
-{"Geo::OGRc::StyleTable_GetLastStyleName", _wrap_StyleTable_GetLastStyleName},
-{"Geo::OGRc::Driver_name_get", _wrap_Driver_name_get},
-{"Geo::OGRc::Driver_CreateDataSource", _wrap_Driver_CreateDataSource},
-{"Geo::OGRc::Driver_CopyDataSource", _wrap_Driver_CopyDataSource},
-{"Geo::OGRc::Driver_Open", _wrap_Driver_Open},
-{"Geo::OGRc::Driver_DeleteDataSource", _wrap_Driver_DeleteDataSource},
-{"Geo::OGRc::Driver__TestCapability", _wrap_Driver__TestCapability},
-{"Geo::OGRc::Driver_GetName", _wrap_Driver_GetName},
-{"Geo::OGRc::Driver_Register", _wrap_Driver_Register},
-{"Geo::OGRc::Driver_Deregister", _wrap_Driver_Deregister},
-{"Geo::OGRc::DataSource_name_get", _wrap_DataSource_name_get},
-{"Geo::OGRc::delete_DataSource", _wrap_delete_DataSource},
-{"Geo::OGRc::DataSource_GetRefCount", _wrap_DataSource_GetRefCount},
-{"Geo::OGRc::DataSource_GetSummaryRefCount", _wrap_DataSource_GetSummaryRefCount},
-{"Geo::OGRc::DataSource_GetLayerCount", _wrap_DataSource_GetLayerCount},
-{"Geo::OGRc::DataSource__GetDriver", _wrap_DataSource__GetDriver},
-{"Geo::OGRc::DataSource_GetName", _wrap_DataSource_GetName},
-{"Geo::OGRc::DataSource__DeleteLayer", _wrap_DataSource__DeleteLayer},
-{"Geo::OGRc::DataSource_SyncToDisk", _wrap_DataSource_SyncToDisk},
-{"Geo::OGRc::DataSource_FlushCache", _wrap_DataSource_FlushCache},
-{"Geo::OGRc::DataSource__CreateLayer", _wrap_DataSource__CreateLayer},
-{"Geo::OGRc::DataSource_CopyLayer", _wrap_DataSource_CopyLayer},
-{"Geo::OGRc::DataSource_GetLayerByIndex", _wrap_DataSource_GetLayerByIndex},
-{"Geo::OGRc::DataSource_GetLayerByName", _wrap_DataSource_GetLayerByName},
-{"Geo::OGRc::DataSource__TestCapability", _wrap_DataSource__TestCapability},
-{"Geo::OGRc::DataSource__ExecuteSQL", _wrap_DataSource__ExecuteSQL},
-{"Geo::OGRc::DataSource__ReleaseResultSet", _wrap_DataSource__ReleaseResultSet},
-{"Geo::OGRc::DataSource_GetStyleTable", _wrap_DataSource_GetStyleTable},
-{"Geo::OGRc::DataSource_SetStyleTable", _wrap_DataSource_SetStyleTable},
-{"Geo::OGRc::DataSource_StartTransaction", _wrap_DataSource_StartTransaction},
-{"Geo::OGRc::DataSource_CommitTransaction", _wrap_DataSource_CommitTransaction},
-{"Geo::OGRc::DataSource_RollbackTransaction", _wrap_DataSource_RollbackTransaction},
-{"Geo::OGRc::Layer_GetRefCount", _wrap_Layer_GetRefCount},
-{"Geo::OGRc::Layer_SetSpatialFilter", _wrap_Layer_SetSpatialFilter},
-{"Geo::OGRc::Layer_SetSpatialFilterRect", _wrap_Layer_SetSpatialFilterRect},
-{"Geo::OGRc::Layer_GetSpatialFilter", _wrap_Layer_GetSpatialFilter},
-{"Geo::OGRc::Layer_SetAttributeFilter", _wrap_Layer_SetAttributeFilter},
-{"Geo::OGRc::Layer_ResetReading", _wrap_Layer_ResetReading},
-{"Geo::OGRc::Layer_GetName", _wrap_Layer_GetName},
-{"Geo::OGRc::Layer_GetGeomType", _wrap_Layer_GetGeomType},
-{"Geo::OGRc::Layer_GetGeometryColumn", _wrap_Layer_GetGeometryColumn},
-{"Geo::OGRc::Layer_GetFIDColumn", _wrap_Layer_GetFIDColumn},
-{"Geo::OGRc::Layer_GetFeature", _wrap_Layer_GetFeature},
-{"Geo::OGRc::Layer_GetNextFeature", _wrap_Layer_GetNextFeature},
-{"Geo::OGRc::Layer_SetNextByIndex", _wrap_Layer_SetNextByIndex},
-{"Geo::OGRc::Layer_SetFeature", _wrap_Layer_SetFeature},
-{"Geo::OGRc::Layer_CreateFeature", _wrap_Layer_CreateFeature},
-{"Geo::OGRc::Layer_DeleteFeature", _wrap_Layer_DeleteFeature},
-{"Geo::OGRc::Layer_SyncToDisk", _wrap_Layer_SyncToDisk},
-{"Geo::OGRc::Layer_GetLayerDefn", _wrap_Layer_GetLayerDefn},
-{"Geo::OGRc::Layer_GetFeatureCount", _wrap_Layer_GetFeatureCount},
-{"Geo::OGRc::Layer_GetExtent", _wrap_Layer_GetExtent},
-{"Geo::OGRc::Layer__TestCapability", _wrap_Layer__TestCapability},
-{"Geo::OGRc::Layer__CreateField", _wrap_Layer__CreateField},
-{"Geo::OGRc::Layer__DeleteField", _wrap_Layer__DeleteField},
-{"Geo::OGRc::Layer_ReorderField", _wrap_Layer_ReorderField},
-{"Geo::OGRc::Layer_ReorderFields", _wrap_Layer_ReorderFields},
-{"Geo::OGRc::Layer__AlterFieldDefn", _wrap_Layer__AlterFieldDefn},
-{"Geo::OGRc::Layer_CreateGeomField", _wrap_Layer_CreateGeomField},
-{"Geo::OGRc::Layer_StartTransaction", _wrap_Layer_StartTransaction},
-{"Geo::OGRc::Layer_CommitTransaction", _wrap_Layer_CommitTransaction},
-{"Geo::OGRc::Layer_RollbackTransaction", _wrap_Layer_RollbackTransaction},
-{"Geo::OGRc::Layer_FindFieldIndex", _wrap_Layer_FindFieldIndex},
-{"Geo::OGRc::Layer_GetSpatialRef", _wrap_Layer_GetSpatialRef},
-{"Geo::OGRc::Layer_GetFeaturesRead", _wrap_Layer_GetFeaturesRead},
-{"Geo::OGRc::Layer_SetIgnoredFields", _wrap_Layer_SetIgnoredFields},
-{"Geo::OGRc::Layer_Intersection", _wrap_Layer_Intersection},
-{"Geo::OGRc::Layer_Union", _wrap_Layer_Union},
-{"Geo::OGRc::Layer_SymDifference", _wrap_Layer_SymDifference},
-{"Geo::OGRc::Layer_Identity", _wrap_Layer_Identity},
-{"Geo::OGRc::Layer_Update", _wrap_Layer_Update},
-{"Geo::OGRc::Layer_Clip", _wrap_Layer_Clip},
-{"Geo::OGRc::Layer_Erase", _wrap_Layer_Erase},
-{"Geo::OGRc::Layer_GetStyleTable", _wrap_Layer_GetStyleTable},
-{"Geo::OGRc::Layer_SetStyleTable", _wrap_Layer_SetStyleTable},
-{"Geo::OGRc::delete_Feature", _wrap_delete_Feature},
-{"Geo::OGRc::new_Feature", _wrap_new_Feature},
-{"Geo::OGRc::Feature_GetDefnRef", _wrap_Feature_GetDefnRef},
-{"Geo::OGRc::Feature__SetGeometry", _wrap_Feature__SetGeometry},
-{"Geo::OGRc::Feature_SetGeometryDirectly", _wrap_Feature_SetGeometryDirectly},
-{"Geo::OGRc::Feature_GetGeometryRef", _wrap_Feature_GetGeometryRef},
-{"Geo::OGRc::Feature_SetGeomField", _wrap_Feature_SetGeomField},
-{"Geo::OGRc::Feature_SetGeomFieldDirectly", _wrap_Feature_SetGeomFieldDirectly},
-{"Geo::OGRc::Feature_GetGeomFieldRef", _wrap_Feature_GetGeomFieldRef},
-{"Geo::OGRc::Feature_Clone", _wrap_Feature_Clone},
-{"Geo::OGRc::Feature_Equal", _wrap_Feature_Equal},
-{"Geo::OGRc::Feature_GetFieldCount", _wrap_Feature_GetFieldCount},
-{"Geo::OGRc::Feature_GetFieldDefnRef", _wrap_Feature_GetFieldDefnRef},
-{"Geo::OGRc::Feature_GetGeomFieldCount", _wrap_Feature_GetGeomFieldCount},
-{"Geo::OGRc::Feature_GetGeomFieldDefnRef", _wrap_Feature_GetGeomFieldDefnRef},
-{"Geo::OGRc::Feature_GetFieldAsString", _wrap_Feature_GetFieldAsString},
-{"Geo::OGRc::Feature_GetFieldAsInteger", _wrap_Feature_GetFieldAsInteger},
-{"Geo::OGRc::Feature_GetFieldAsInteger64", _wrap_Feature_GetFieldAsInteger64},
-{"Geo::OGRc::Feature_GetFieldAsDouble", _wrap_Feature_GetFieldAsDouble},
-{"Geo::OGRc::Feature_GetFieldAsDateTime", _wrap_Feature_GetFieldAsDateTime},
-{"Geo::OGRc::Feature_GetFieldAsIntegerList", _wrap_Feature_GetFieldAsIntegerList},
-{"Geo::OGRc::Feature_GetFieldAsDoubleList", _wrap_Feature_GetFieldAsDoubleList},
-{"Geo::OGRc::Feature_GetFieldAsStringList", _wrap_Feature_GetFieldAsStringList},
-{"Geo::OGRc::Feature_GetFieldAsBinary", _wrap_Feature_GetFieldAsBinary},
-{"Geo::OGRc::Feature_IsFieldSet", _wrap_Feature_IsFieldSet},
-{"Geo::OGRc::Feature_GetFieldIndex", _wrap_Feature_GetFieldIndex},
-{"Geo::OGRc::Feature_GetGeomFieldIndex", _wrap_Feature_GetGeomFieldIndex},
-{"Geo::OGRc::Feature_GetFID", _wrap_Feature_GetFID},
-{"Geo::OGRc::Feature_SetFID", _wrap_Feature_SetFID},
-{"Geo::OGRc::Feature_DumpReadable", _wrap_Feature_DumpReadable},
-{"Geo::OGRc::Feature__UnsetField", _wrap_Feature__UnsetField},
-{"Geo::OGRc::Feature_SetFieldInteger64", _wrap_Feature_SetFieldInteger64},
-{"Geo::OGRc::Feature__SetField", _wrap_Feature__SetField},
-{"Geo::OGRc::Feature_SetFieldIntegerList", _wrap_Feature_SetFieldIntegerList},
-{"Geo::OGRc::Feature_SetFieldDoubleList", _wrap_Feature_SetFieldDoubleList},
-{"Geo::OGRc::Feature_SetFieldStringList", _wrap_Feature_SetFieldStringList},
-{"Geo::OGRc::Feature_SetFieldBinaryFromHexString", _wrap_Feature_SetFieldBinaryFromHexString},
-{"Geo::OGRc::Feature__SetFrom", _wrap_Feature__SetFrom},
-{"Geo::OGRc::Feature_SetFromWithMap", _wrap_Feature_SetFromWithMap},
-{"Geo::OGRc::Feature_GetStyleString", _wrap_Feature_GetStyleString},
-{"Geo::OGRc::Feature_SetStyleString", _wrap_Feature_SetStyleString},
-{"Geo::OGRc::Feature_GetFieldType", _wrap_Feature_GetFieldType},
-{"Geo::OGRc::Feature__Validate", _wrap_Feature__Validate},
-{"Geo::OGRc::Feature_FillUnsetWithDefault", _wrap_Feature_FillUnsetWithDefault},
-{"Geo::OGRc::delete_FeatureDefn", _wrap_delete_FeatureDefn},
-{"Geo::OGRc::new_FeatureDefn", _wrap_new_FeatureDefn},
-{"Geo::OGRc::FeatureDefn_GetName", _wrap_FeatureDefn_GetName},
-{"Geo::OGRc::FeatureDefn_GetFieldCount", _wrap_FeatureDefn_GetFieldCount},
-{"Geo::OGRc::FeatureDefn_GetFieldDefn", _wrap_FeatureDefn_GetFieldDefn},
-{"Geo::OGRc::FeatureDefn_GetFieldIndex", _wrap_FeatureDefn_GetFieldIndex},
-{"Geo::OGRc::FeatureDefn_AddFieldDefn", _wrap_FeatureDefn_AddFieldDefn},
-{"Geo::OGRc::FeatureDefn_GetGeomFieldCount", _wrap_FeatureDefn_GetGeomFieldCount},
-{"Geo::OGRc::FeatureDefn_GetGeomFieldDefn", _wrap_FeatureDefn_GetGeomFieldDefn},
-{"Geo::OGRc::FeatureDefn_GetGeomFieldIndex", _wrap_FeatureDefn_GetGeomFieldIndex},
-{"Geo::OGRc::FeatureDefn_AddGeomFieldDefn", _wrap_FeatureDefn_AddGeomFieldDefn},
-{"Geo::OGRc::FeatureDefn_DeleteGeomFieldDefn", _wrap_FeatureDefn_DeleteGeomFieldDefn},
-{"Geo::OGRc::FeatureDefn_GetGeomType", _wrap_FeatureDefn_GetGeomType},
-{"Geo::OGRc::FeatureDefn_SetGeomType", _wrap_FeatureDefn_SetGeomType},
-{"Geo::OGRc::FeatureDefn_GetReferenceCount", _wrap_FeatureDefn_GetReferenceCount},
-{"Geo::OGRc::FeatureDefn_IsGeometryIgnored", _wrap_FeatureDefn_IsGeometryIgnored},
-{"Geo::OGRc::FeatureDefn_SetGeometryIgnored", _wrap_FeatureDefn_SetGeometryIgnored},
-{"Geo::OGRc::FeatureDefn_IsStyleIgnored", _wrap_FeatureDefn_IsStyleIgnored},
-{"Geo::OGRc::FeatureDefn_SetStyleIgnored", _wrap_FeatureDefn_SetStyleIgnored},
-{"Geo::OGRc::FeatureDefn_IsSame", _wrap_FeatureDefn_IsSame},
-{"Geo::OGRc::delete_FieldDefn", _wrap_delete_FieldDefn},
-{"Geo::OGRc::new_FieldDefn", _wrap_new_FieldDefn},
-{"Geo::OGRc::FieldDefn_GetName", _wrap_FieldDefn_GetName},
-{"Geo::OGRc::FieldDefn_GetNameRef", _wrap_FieldDefn_GetNameRef},
-{"Geo::OGRc::FieldDefn_SetName", _wrap_FieldDefn_SetName},
-{"Geo::OGRc::FieldDefn_GetType", _wrap_FieldDefn_GetType},
-{"Geo::OGRc::FieldDefn_SetType", _wrap_FieldDefn_SetType},
-{"Geo::OGRc::FieldDefn_GetSubType", _wrap_FieldDefn_GetSubType},
-{"Geo::OGRc::FieldDefn_SetSubType", _wrap_FieldDefn_SetSubType},
-{"Geo::OGRc::FieldDefn_GetJustify", _wrap_FieldDefn_GetJustify},
-{"Geo::OGRc::FieldDefn_SetJustify", _wrap_FieldDefn_SetJustify},
-{"Geo::OGRc::FieldDefn_GetWidth", _wrap_FieldDefn_GetWidth},
-{"Geo::OGRc::FieldDefn_SetWidth", _wrap_FieldDefn_SetWidth},
-{"Geo::OGRc::FieldDefn_GetPrecision", _wrap_FieldDefn_GetPrecision},
-{"Geo::OGRc::FieldDefn_SetPrecision", _wrap_FieldDefn_SetPrecision},
-{"Geo::OGRc::FieldDefn_GetTypeName", _wrap_FieldDefn_GetTypeName},
-{"Geo::OGRc::FieldDefn_GetFieldTypeName", _wrap_FieldDefn_GetFieldTypeName},
-{"Geo::OGRc::FieldDefn_IsIgnored", _wrap_FieldDefn_IsIgnored},
-{"Geo::OGRc::FieldDefn_SetIgnored", _wrap_FieldDefn_SetIgnored},
-{"Geo::OGRc::FieldDefn_IsNullable", _wrap_FieldDefn_IsNullable},
-{"Geo::OGRc::FieldDefn_SetNullable", _wrap_FieldDefn_SetNullable},
-{"Geo::OGRc::FieldDefn_GetDefault", _wrap_FieldDefn_GetDefault},
-{"Geo::OGRc::FieldDefn_SetDefault", _wrap_FieldDefn_SetDefault},
-{"Geo::OGRc::FieldDefn_IsDefaultDriverSpecific", _wrap_FieldDefn_IsDefaultDriverSpecific},
-{"Geo::OGRc::delete_GeomFieldDefn", _wrap_delete_GeomFieldDefn},
-{"Geo::OGRc::new_GeomFieldDefn", _wrap_new_GeomFieldDefn},
-{"Geo::OGRc::GeomFieldDefn_GetName", _wrap_GeomFieldDefn_GetName},
-{"Geo::OGRc::GeomFieldDefn_GetNameRef", _wrap_GeomFieldDefn_GetNameRef},
-{"Geo::OGRc::GeomFieldDefn_SetName", _wrap_GeomFieldDefn_SetName},
-{"Geo::OGRc::GeomFieldDefn_GetType", _wrap_GeomFieldDefn_GetType},
-{"Geo::OGRc::GeomFieldDefn_SetType", _wrap_GeomFieldDefn_SetType},
-{"Geo::OGRc::GeomFieldDefn_GetSpatialRef", _wrap_GeomFieldDefn_GetSpatialRef},
-{"Geo::OGRc::GeomFieldDefn_SetSpatialRef", _wrap_GeomFieldDefn_SetSpatialRef},
-{"Geo::OGRc::GeomFieldDefn_IsIgnored", _wrap_GeomFieldDefn_IsIgnored},
-{"Geo::OGRc::GeomFieldDefn_SetIgnored", _wrap_GeomFieldDefn_SetIgnored},
-{"Geo::OGRc::GeomFieldDefn_IsNullable", _wrap_GeomFieldDefn_IsNullable},
-{"Geo::OGRc::GeomFieldDefn_SetNullable", _wrap_GeomFieldDefn_SetNullable},
-{"Geo::OGRc::CreateGeometryFromWkb", _wrap_CreateGeometryFromWkb},
-{"Geo::OGRc::CreateGeometryFromWkt", _wrap_CreateGeometryFromWkt},
-{"Geo::OGRc::CreateGeometryFromGML", _wrap_CreateGeometryFromGML},
-{"Geo::OGRc::CreateGeometryFromJson", _wrap_CreateGeometryFromJson},
-{"Geo::OGRc::BuildPolygonFromEdges", _wrap_BuildPolygonFromEdges},
-{"Geo::OGRc::ApproximateArcAngles", _wrap_ApproximateArcAngles},
-{"Geo::OGRc::ForceToPolygon", _wrap_ForceToPolygon},
-{"Geo::OGRc::ForceToLineString", _wrap_ForceToLineString},
-{"Geo::OGRc::ForceToMultiPolygon", _wrap_ForceToMultiPolygon},
-{"Geo::OGRc::ForceToMultiPoint", _wrap_ForceToMultiPoint},
-{"Geo::OGRc::ForceToMultiLineString", _wrap_ForceToMultiLineString},
-{"Geo::OGRc::ForceTo", _wrap_ForceTo},
-{"Geo::OGRc::delete_Geometry", _wrap_delete_Geometry},
-{"Geo::OGRc::new_Geometry", _wrap_new_Geometry},
-{"Geo::OGRc::Geometry_ExportToWkt", _wrap_Geometry_ExportToWkt},
-{"Geo::OGRc::Geometry_ExportToIsoWkt", _wrap_Geometry_ExportToIsoWkt},
-{"Geo::OGRc::Geometry__ExportToWkb", _wrap_Geometry__ExportToWkb},
-{"Geo::OGRc::Geometry_ExportToIsoWkb", _wrap_Geometry_ExportToIsoWkb},
-{"Geo::OGRc::Geometry_ExportToGML", _wrap_Geometry_ExportToGML},
-{"Geo::OGRc::Geometry_ExportToKML", _wrap_Geometry_ExportToKML},
-{"Geo::OGRc::Geometry_ExportToJson", _wrap_Geometry_ExportToJson},
-{"Geo::OGRc::Geometry_AddPoint_3D", _wrap_Geometry_AddPoint_3D},
-{"Geo::OGRc::Geometry_AddPoint_2D", _wrap_Geometry_AddPoint_2D},
-{"Geo::OGRc::Geometry_AddGeometryDirectly", _wrap_Geometry_AddGeometryDirectly},
-{"Geo::OGRc::Geometry_AddGeometry", _wrap_Geometry_AddGeometry},
-{"Geo::OGRc::Geometry_Clone", _wrap_Geometry_Clone},
-{"Geo::OGRc::Geometry_GetGeometryType", _wrap_Geometry_GetGeometryType},
-{"Geo::OGRc::Geometry_GetGeometryName", _wrap_Geometry_GetGeometryName},
-{"Geo::OGRc::Geometry_Length", _wrap_Geometry_Length},
-{"Geo::OGRc::Geometry_Area", _wrap_Geometry_Area},
-{"Geo::OGRc::Geometry_GetArea", _wrap_Geometry_GetArea},
-{"Geo::OGRc::Geometry_GetPointCount", _wrap_Geometry_GetPointCount},
-{"Geo::OGRc::Geometry_GetX", _wrap_Geometry_GetX},
-{"Geo::OGRc::Geometry_GetY", _wrap_Geometry_GetY},
-{"Geo::OGRc::Geometry_GetZ", _wrap_Geometry_GetZ},
-{"Geo::OGRc::Geometry_GetPoint_3D", _wrap_Geometry_GetPoint_3D},
-{"Geo::OGRc::Geometry_GetPoint_2D", _wrap_Geometry_GetPoint_2D},
-{"Geo::OGRc::Geometry_GetGeometryCount", _wrap_Geometry_GetGeometryCount},
-{"Geo::OGRc::Geometry_SetPoint_3D", _wrap_Geometry_SetPoint_3D},
-{"Geo::OGRc::Geometry_SetPoint_2D", _wrap_Geometry_SetPoint_2D},
-{"Geo::OGRc::Geometry_GetGeometryRef", _wrap_Geometry_GetGeometryRef},
-{"Geo::OGRc::Geometry_Simplify", _wrap_Geometry_Simplify},
-{"Geo::OGRc::Geometry_SimplifyPreserveTopology", _wrap_Geometry_SimplifyPreserveTopology},
-{"Geo::OGRc::Geometry_Boundary", _wrap_Geometry_Boundary},
-{"Geo::OGRc::Geometry_GetBoundary", _wrap_Geometry_GetBoundary},
-{"Geo::OGRc::Geometry_ConvexHull", _wrap_Geometry_ConvexHull},
-{"Geo::OGRc::Geometry_Buffer", _wrap_Geometry_Buffer},
-{"Geo::OGRc::Geometry_Intersection", _wrap_Geometry_Intersection},
-{"Geo::OGRc::Geometry_Union", _wrap_Geometry_Union},
-{"Geo::OGRc::Geometry_UnionCascaded", _wrap_Geometry_UnionCascaded},
-{"Geo::OGRc::Geometry_Difference", _wrap_Geometry_Difference},
-{"Geo::OGRc::Geometry_SymDifference", _wrap_Geometry_SymDifference},
-{"Geo::OGRc::Geometry_SymmetricDifference", _wrap_Geometry_SymmetricDifference},
-{"Geo::OGRc::Geometry_Distance", _wrap_Geometry_Distance},
-{"Geo::OGRc::Geometry_Empty", _wrap_Geometry_Empty},
-{"Geo::OGRc::Geometry_IsEmpty", _wrap_Geometry_IsEmpty},
-{"Geo::OGRc::Geometry_IsValid", _wrap_Geometry_IsValid},
-{"Geo::OGRc::Geometry_IsSimple", _wrap_Geometry_IsSimple},
-{"Geo::OGRc::Geometry_IsRing", _wrap_Geometry_IsRing},
-{"Geo::OGRc::Geometry_Intersects", _wrap_Geometry_Intersects},
-{"Geo::OGRc::Geometry_Intersect", _wrap_Geometry_Intersect},
-{"Geo::OGRc::Geometry_Equals", _wrap_Geometry_Equals},
-{"Geo::OGRc::Geometry_Equal", _wrap_Geometry_Equal},
-{"Geo::OGRc::Geometry_Disjoint", _wrap_Geometry_Disjoint},
-{"Geo::OGRc::Geometry_Touches", _wrap_Geometry_Touches},
-{"Geo::OGRc::Geometry_Crosses", _wrap_Geometry_Crosses},
-{"Geo::OGRc::Geometry_Within", _wrap_Geometry_Within},
-{"Geo::OGRc::Geometry_Contains", _wrap_Geometry_Contains},
-{"Geo::OGRc::Geometry_Overlaps", _wrap_Geometry_Overlaps},
-{"Geo::OGRc::Geometry_TransformTo", _wrap_Geometry_TransformTo},
-{"Geo::OGRc::Geometry_Transform", _wrap_Geometry_Transform},
-{"Geo::OGRc::Geometry_GetSpatialReference", _wrap_Geometry_GetSpatialReference},
-{"Geo::OGRc::Geometry_AssignSpatialReference", _wrap_Geometry_AssignSpatialReference},
-{"Geo::OGRc::Geometry_CloseRings", _wrap_Geometry_CloseRings},
-{"Geo::OGRc::Geometry_FlattenTo2D", _wrap_Geometry_FlattenTo2D},
-{"Geo::OGRc::Geometry_Segmentize", _wrap_Geometry_Segmentize},
-{"Geo::OGRc::Geometry_GetEnvelope", _wrap_Geometry_GetEnvelope},
-{"Geo::OGRc::Geometry_GetEnvelope3D", _wrap_Geometry_GetEnvelope3D},
-{"Geo::OGRc::Geometry_Centroid", _wrap_Geometry_Centroid},
-{"Geo::OGRc::Geometry_PointOnSurface", _wrap_Geometry_PointOnSurface},
-{"Geo::OGRc::Geometry_WkbSize", _wrap_Geometry_WkbSize},
-{"Geo::OGRc::Geometry_GetCoordinateDimension", _wrap_Geometry_GetCoordinateDimension},
-{"Geo::OGRc::Geometry_SetCoordinateDimension", _wrap_Geometry_SetCoordinateDimension},
-{"Geo::OGRc::Geometry_GetDimension", _wrap_Geometry_GetDimension},
-{"Geo::OGRc::Geometry_HasCurveGeometry", _wrap_Geometry_HasCurveGeometry},
-{"Geo::OGRc::Geometry_GetLinearGeometry", _wrap_Geometry_GetLinearGeometry},
-{"Geo::OGRc::Geometry_GetCurveGeometry", _wrap_Geometry_GetCurveGeometry},
-{"Geo::OGRc::Geometry_Value", _wrap_Geometry_Value},
-{"Geo::OGRc::Geometry_Move", _wrap_Geometry_Move},
-{"Geo::OGRc::GetDriverCount", _wrap_GetDriverCount},
-{"Geo::OGRc::GetOpenDSCount", _wrap_GetOpenDSCount},
-{"Geo::OGRc::SetGenerate_DB2_V72_BYTE_ORDER", _wrap_SetGenerate_DB2_V72_BYTE_ORDER},
-{"Geo::OGRc::RegisterAll", _wrap_RegisterAll},
-{"Geo::OGRc::GeometryTypeToName", _wrap_GeometryTypeToName},
-{"Geo::OGRc::GetFieldTypeName", _wrap_GetFieldTypeName},
-{"Geo::OGRc::GetFieldSubTypeName", _wrap_GetFieldSubTypeName},
-{"Geo::OGRc::GT_Flatten", _wrap_GT_Flatten},
-{"Geo::OGRc::GT_SetZ", _wrap_GT_SetZ},
-{"Geo::OGRc::GT_SetModifier", _wrap_GT_SetModifier},
-{"Geo::OGRc::GT_HasZ", _wrap_GT_HasZ},
-{"Geo::OGRc::GT_IsSubClassOf", _wrap_GT_IsSubClassOf},
-{"Geo::OGRc::GT_IsCurve", _wrap_GT_IsCurve},
-{"Geo::OGRc::GT_IsSurface", _wrap_GT_IsSurface},
-{"Geo::OGRc::GT_IsNonLinear", _wrap_GT_IsNonLinear},
-{"Geo::OGRc::GT_GetCollection", _wrap_GT_GetCollection},
-{"Geo::OGRc::GT_GetCurve", _wrap_GT_GetCurve},
-{"Geo::OGRc::GT_GetLinear", _wrap_GT_GetLinear},
-{"Geo::OGRc::SetNonLinearGeometriesEnabledFlag", _wrap_SetNonLinearGeometriesEnabledFlag},
-{"Geo::OGRc::GetNonLinearGeometriesEnabledFlag", _wrap_GetNonLinearGeometriesEnabledFlag},
-{"Geo::OGRc::GetOpenDS", _wrap_GetOpenDS},
-{"Geo::OGRc::Open", _wrap_Open},
-{"Geo::OGRc::OpenShared", _wrap_OpenShared},
-{"Geo::OGRc::GetDriverByName", _wrap_GetDriverByName},
-{"Geo::OGRc::_GetDriver", _wrap__GetDriver},
-{"Geo::OGRc::GeneralCmdLineProcessor", _wrap_GeneralCmdLineProcessor},
-{"Geo::OGRc::TermProgress_nocb", _wrap_TermProgress_nocb},
-{0,0}
-};
-/* -----------------------------------------------------------------------------
- * Type initialization:
- * This problem is tough by the requirement that no dynamic
- * memory is used. Also, since swig_type_info structures store pointers to
- * swig_cast_info structures and swig_cast_info structures store pointers back
- * to swig_type_info structures, we need some lookup code at initialization.
- * The idea is that swig generates all the structures that are needed.
- * The runtime then collects these partially filled structures.
- * The SWIG_InitializeModule function takes these initial arrays out of
- * swig_module, and does all the lookup, filling in the swig_module.types
- * array with the correct data and linking the correct swig_cast_info
- * structures together.
- *
- * The generated swig_type_info structures are assigned staticly to an initial
- * array. We just loop through that array, and handle each type individually.
- * First we lookup if this type has been already loaded, and if so, use the
- * loaded structure instead of the generated one. Then we have to fill in the
- * cast linked list. The cast data is initially stored in something like a
- * two-dimensional array. Each row corresponds to a type (there are the same
- * number of rows as there are in the swig_type_initial array). Each entry in
- * a column is one of the swig_cast_info structures for that type.
- * The cast_initial array is actually an array of arrays, because each row has
- * a variable number of columns. So to actually build the cast linked list,
- * we find the array of casts associated with the type, and loop through it
- * adding the casts to the list. The one last trick we need to do is making
- * sure the type pointer in the swig_cast_info struct is correct.
- *
- * First off, we lookup the cast->type name to see if it is already loaded.
- * There are three cases to handle:
- *  1) If the cast->type has already been loaded AND the type we are adding
- *     casting info to has not been loaded (it is in this module), THEN we
- *     replace the cast->type pointer with the type pointer that has already
- *     been loaded.
- *  2) If BOTH types (the one we are adding casting info to, and the
- *     cast->type) are loaded, THEN the cast info has already been loaded by
- *     the previous module so we just ignore it.
- *  3) Finally, if cast->type has not already been loaded, then we add that
- *     swig_cast_info to the linked list (because the cast->type) pointer will
- *     be correct.
- * ----------------------------------------------------------------------------- */
-
-#ifdef __cplusplus
-extern "C" {
-#if 0
-} /* c-mode */
-#endif
-#endif
-
-#if 0
-#define SWIGRUNTIME_DEBUG
-#endif
-
-
-SWIGRUNTIME void
-SWIG_InitializeModule(void *clientdata) {
-  size_t i;
-  swig_module_info *module_head, *iter;
-  int found, init;
-  
-  /* check to see if the circular list has been setup, if not, set it up */
-  if (swig_module.next==0) {
-    /* Initialize the swig_module */
-    swig_module.type_initial = swig_type_initial;
-    swig_module.cast_initial = swig_cast_initial;
-    swig_module.next = &swig_module;
-    init = 1;
-  } else {
-    init = 0;
-  }
-  
-  /* Try and load any already created modules */
-  module_head = SWIG_GetModule(clientdata);
-  if (!module_head) {
-    /* This is the first module loaded for this interpreter */
-    /* so set the swig module into the interpreter */
-    SWIG_SetModule(clientdata, &swig_module);
-    module_head = &swig_module;
-  } else {
-    /* the interpreter has loaded a SWIG module, but has it loaded this one? */
-    found=0;
-    iter=module_head;
-    do {
-      if (iter==&swig_module) {
-        found=1;
-        break;
-      }
-      iter=iter->next;
-    } while (iter!= module_head);
-    
-    /* if the is found in the list, then all is done and we may leave */
-    if (found) return;
-    /* otherwise we must add out module into the list */
-    swig_module.next = module_head->next;
-    module_head->next = &swig_module;
-  }
-  
-  /* When multiple interpreters are used, a module could have already been initialized in
-       a different interpreter, but not yet have a pointer in this interpreter.
-       In this case, we do not want to continue adding types... everything should be
-       set up already */
-  if (init == 0) return;
-  
-  /* Now work on filling in swig_module.types */
-#ifdef SWIGRUNTIME_DEBUG
-  printf("SWIG_InitializeModule: size %d\n", swig_module.size);
-#endif
-  for (i = 0; i < swig_module.size; ++i) {
-    swig_type_info *type = 0;
-    swig_type_info *ret;
-    swig_cast_info *cast;
-    
-#ifdef SWIGRUNTIME_DEBUG
-    printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name);
-#endif
-    
-    /* if there is another module already loaded */
-    if (swig_module.next != &swig_module) {
-      type = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, swig_module.type_initial[i]->name);
-    }
-    if (type) {
-      /* Overwrite clientdata field */
-#ifdef SWIGRUNTIME_DEBUG
-      printf("SWIG_InitializeModule: found type %s\n", type->name);
-#endif
-      if (swig_module.type_initial[i]->clientdata) {
-        type->clientdata = swig_module.type_initial[i]->clientdata;
-#ifdef SWIGRUNTIME_DEBUG
-        printf("SWIG_InitializeModule: found and overwrite type %s \n", type->name);
-#endif
-      }
-    } else {
-      type = swig_module.type_initial[i];
-    }
-    
-    /* Insert casting types */
-    cast = swig_module.cast_initial[i];
-    while (cast->type) {
-      /* Don't need to add information already in the list */
-      ret = 0;
-#ifdef SWIGRUNTIME_DEBUG
-      printf("SWIG_InitializeModule: look cast %s\n", cast->type->name);
-#endif
-      if (swig_module.next != &swig_module) {
-        ret = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, cast->type->name);
-#ifdef SWIGRUNTIME_DEBUG
-        if (ret) printf("SWIG_InitializeModule: found cast %s\n", ret->name);
-#endif
-      }
-      if (ret) {
-        if (type == swig_module.type_initial[i]) {
-#ifdef SWIGRUNTIME_DEBUG
-          printf("SWIG_InitializeModule: skip old type %s\n", ret->name);
-#endif
-          cast->type = ret;
-          ret = 0;
-        } else {
-          /* Check for casting already in the list */
-          swig_cast_info *ocast = SWIG_TypeCheck(ret->name, type);
-#ifdef SWIGRUNTIME_DEBUG
-          if (ocast) printf("SWIG_InitializeModule: skip old cast %s\n", ret->name);
-#endif
-          if (!ocast) ret = 0;
-        }
-      }
-      
-      if (!ret) {
-#ifdef SWIGRUNTIME_DEBUG
-        printf("SWIG_InitializeModule: adding cast %s\n", cast->type->name);
-#endif
-        if (type->cast) {
-          type->cast->prev = cast;
-          cast->next = type->cast;
-        }
-        type->cast = cast;
-      }
-      cast++;
-    }
-    /* Set entry in modules->types array equal to the type */
-    swig_module.types[i] = type;
-  }
-  swig_module.types[i] = 0;
-  
-#ifdef SWIGRUNTIME_DEBUG
-  printf("**** SWIG_InitializeModule: Cast List ******\n");
-  for (i = 0; i < swig_module.size; ++i) {
-    int j = 0;
-    swig_cast_info *cast = swig_module.cast_initial[i];
-    printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name);
-    while (cast->type) {
-      printf("SWIG_InitializeModule: cast type %s\n", cast->type->name);
-      cast++;
-      ++j;
-    }
-    printf("---- Total casts: %d\n",j);
-  }
-  printf("**** SWIG_InitializeModule: Cast List ******\n");
-#endif
-}
-
-/* This function will propagate the clientdata field of type to
-* any new swig_type_info structures that have been added into the list
-* of equivalent types.  It is like calling
-* SWIG_TypeClientData(type, clientdata) a second time.
-*/
-SWIGRUNTIME void
-SWIG_PropagateClientData(void) {
-  size_t i;
-  swig_cast_info *equiv;
-  static int init_run = 0;
-  
-  if (init_run) return;
-  init_run = 1;
-  
-  for (i = 0; i < swig_module.size; i++) {
-    if (swig_module.types[i]->clientdata) {
-      equiv = swig_module.types[i]->cast;
-      while (equiv) {
-        if (!equiv->converter) {
-          if (equiv->type && !equiv->type->clientdata)
-          SWIG_TypeClientData(equiv->type, swig_module.types[i]->clientdata);
-        }
-        equiv = equiv->next;
-      }
-    }
-  }
-}
-
-#ifdef __cplusplus
-#if 0
-{
-  /* c-mode */
-#endif
-}
-#endif
-
-
-
-#ifdef __cplusplus
-extern "C"
-#endif
-
-XS(SWIG_init) {
-  dXSARGS;
-  int i;
-  
-  SWIG_InitializeModule(0);
-  
-  /* Install commands */
-  for (i = 0; swig_commands[i].name; i++) {
-    /* Casts only needed for Perl < 5.10. */
-#ifdef __cplusplus
-    newXS(const_cast<char*>(swig_commands[i].name), swig_commands[i].wrapper, const_cast<char*>(__FILE__));
-#else
-    newXS((char*)swig_commands[i].name, swig_commands[i].wrapper, (char*)__FILE__);
-#endif
-  }
-  
-  /* Install variables */
-  for (i = 0; swig_variables[i].name; i++) {
-    SV *sv;
-    sv = get_sv(swig_variables[i].name, TRUE | 0x2 | GV_ADDMULTI);
-    if (swig_variables[i].type) {
-      SWIG_MakePtr(sv,(void *)1, *swig_variables[i].type,0);
-    } else {
-      sv_setiv(sv,(IV) 0);
-    }
-    swig_create_magic(sv, swig_variables[i].name, swig_variables[i].set, swig_variables[i].get); 
-  }
-  
-  /* Install constant */
-  for (i = 0; swig_constants[i].type; i++) {
-    SV *sv;
-    sv = get_sv(swig_constants[i].name, TRUE | 0x2 | GV_ADDMULTI);
-    switch(swig_constants[i].type) {
-    case SWIG_INT:
-      sv_setiv(sv, (IV) swig_constants[i].lvalue);
-      break;
-    case SWIG_FLOAT:
-      sv_setnv(sv, (double) swig_constants[i].dvalue);
-      break;
-    case SWIG_STRING:
-      sv_setpv(sv, (const char *) swig_constants[i].pvalue);
-      break;
-    case SWIG_POINTER:
-      SWIG_MakePtr(sv, swig_constants[i].pvalue, *(swig_constants[i].ptype),0);
-      break;
-    case SWIG_BINARY:
-      SWIG_MakePackedObj(sv, swig_constants[i].pvalue, swig_constants[i].lvalue, *(swig_constants[i].ptype));
-      break;
-    default:
-      break;
-    }
-    SvREADONLY_on(sv);
-  }
-  
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkb25DBit", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(0x80000000)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkb25Bit", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(0x80000000)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkbUnknown", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(0)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkbPoint", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(1)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkbLineString", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(2)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkbPolygon", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(3)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkbMultiPoint", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(4)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkbMultiLineString", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(5)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkbMultiPolygon", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(6)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkbGeometryCollection", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(7)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkbCircularString", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(8)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkbCompoundCurve", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(9)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkbCurvePolygon", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(10)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkbMultiCurve", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(11)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkbMultiSurface", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(12)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkbNone", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(100)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkbLinearRing", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(101)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkbCircularStringZ", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(1008)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkbCompoundCurveZ", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(1009)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkbCurvePolygonZ", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(1010)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkbMultiCurveZ", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(1011)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkbMultiSurfaceZ", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(1012)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkbPoint25D", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(0x80000001)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkbLineString25D", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(0x80000002)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkbPolygon25D", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(0x80000003)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkbMultiPoint25D", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(0x80000004)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkbMultiLineString25D", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(0x80000005)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkbMultiPolygon25D", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(0x80000006)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkbGeometryCollection25D", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(0x80000007)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OFTInteger", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(0)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OFTIntegerList", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(1)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OFTReal", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(2)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OFTRealList", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(3)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OFTString", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(4)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OFTStringList", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(5)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OFTWideString", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(6)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OFTWideStringList", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(7)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OFTBinary", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(8)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OFTDate", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(9)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OFTTime", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(10)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OFTDateTime", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(11)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OFTInteger64", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(12)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OFTInteger64List", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(13)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OFSTNone", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(0)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OFSTBoolean", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(1)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OFSTInt16", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(2)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OFSTFloat32", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(3)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OJUndefined", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(0)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OJLeft", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(1)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OJRight", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(2)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkbXDR", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(0)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "wkbNDR", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(1)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "NullFID", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(-1)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "ALTER_NAME_FLAG", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(1)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "ALTER_TYPE_FLAG", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(2)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "ALTER_WIDTH_PRECISION_FLAG", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(4)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "ALTER_NULLABLE_FLAG", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(8)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "ALTER_DEFAULT_FLAG", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(16)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "ALTER_ALL_FLAG", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(1+2+4+8+16)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "F_VAL_NULL", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(0x00000001)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "F_VAL_GEOM_TYPE", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(0x00000002)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "F_VAL_WIDTH", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(0x00000004)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "F_VAL_ALLOW_NULL_WHEN_DEFAULT", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(0x00000008)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "F_VAL_ALL", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(0xFFFFFFFF)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OLCRandomRead", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("RandomRead"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OLCSequentialWrite", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("SequentialWrite"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OLCRandomWrite", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("RandomWrite"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OLCFastSpatialFilter", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("FastSpatialFilter"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OLCFastFeatureCount", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("FastFeatureCount"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OLCFastGetExtent", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("FastGetExtent"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OLCCreateField", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("CreateField"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OLCDeleteField", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("DeleteField"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OLCReorderFields", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("ReorderFields"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OLCAlterFieldDefn", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("AlterFieldDefn"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OLCTransactions", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Transactions"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OLCDeleteFeature", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("DeleteFeature"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OLCFastSetNextByIndex", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("FastSetNextByIndex"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OLCStringsAsUTF8", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("StringsAsUTF8"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OLCIgnoreFields", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("IgnoreFields"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OLCCreateGeomField", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("CreateGeomField"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OLCCurveGeometries", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("CurveGeometries"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "ODsCCreateLayer", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("CreateLayer"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "ODsCDeleteLayer", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("DeleteLayer"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "ODsCCreateGeomFieldAfterCreateLayer", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("CreateGeomFieldAfterCreateLayer"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "ODsCCurveGeometries", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("CurveGeometries"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "ODsCTransactions", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Transactions"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "ODsCEmulatedTransactions", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("EmulatedTransactions"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "ODrCCreateDataSource", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("CreateDataSource"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "ODrCDeleteDataSource", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("DeleteDataSource"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "OLMD_FID64", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("OLMD_FID64"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  
-  
-  /*UseExceptions(); is set by GDAL module */
-  if ( OGRGetDriverCount() == 0 ) {
-    OGRRegisterAll();
-  }
-  
-  
-  SWIG_TypeClientData(SWIGTYPE_p_OGRStyleTableShadow, (void*) "Geo::OGR::StyleTable");
-  SWIG_TypeClientData(SWIGTYPE_p_OGRDriverShadow, (void*) "Geo::OGR::Driver");
-  SWIG_TypeClientData(SWIGTYPE_p_OGRDataSourceShadow, (void*) "Geo::OGR::DataSource");
-  SWIG_TypeClientData(SWIGTYPE_p_OGRLayerShadow, (void*) "Geo::OGR::Layer");
-  SWIG_TypeClientData(SWIGTYPE_p_OGRFeatureShadow, (void*) "Geo::OGR::Feature");
-  SWIG_TypeClientData(SWIGTYPE_p_OGRFeatureDefnShadow, (void*) "Geo::OGR::FeatureDefn");
-  SWIG_TypeClientData(SWIGTYPE_p_OGRFieldDefnShadow, (void*) "Geo::OGR::FieldDefn");
-  SWIG_TypeClientData(SWIGTYPE_p_OGRGeomFieldDefnShadow, (void*) "Geo::OGR::GeomFieldDefn");
-  SWIG_TypeClientData(SWIGTYPE_p_OGRGeometryShadow, (void*) "Geo::OGR::Geometry");
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "TermProgress", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_NewFunctionPtrObj((void *)(int (*)(double,char const *,void *))(GDALTermProgress), SWIGTYPE_p_f_double_p_q_const__char_p_void__int));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  ST(0) = &PL_sv_yes;
-  XSRETURN(1);
-}
-
diff --git a/swig/perl/osr_wrap.cpp b/swig/perl/osr_wrap.cpp
deleted file mode 100644
index cd05df1..0000000
--- a/swig/perl/osr_wrap.cpp
+++ /dev/null
@@ -1,14358 +0,0 @@
-/* ----------------------------------------------------------------------------
- * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 2.0.12
- *
- * This file is not intended to be easily readable and contains a number of
- * coding conventions designed to improve portability and efficiency. Do not make
- * changes to this file unless you know what you are doing--modify the SWIG
- * interface file instead.
- * ----------------------------------------------------------------------------- */
-
-#define SWIGPERL
-#define SWIG_CASTRANK_MODE
-
-
-#ifdef __cplusplus
-/* SwigValueWrapper is described in swig.swg */
-template<typename T> class SwigValueWrapper {
-  struct SwigMovePointer {
-    T *ptr;
-    SwigMovePointer(T *p) : ptr(p) { }
-    ~SwigMovePointer() { delete ptr; }
-    SwigMovePointer& operator=(SwigMovePointer& rhs) { T* oldptr = ptr; ptr = 0; delete oldptr; ptr = rhs.ptr; rhs.ptr = 0; return *this; }
-  } pointer;
-  SwigValueWrapper& operator=(const SwigValueWrapper<T>& rhs);
-  SwigValueWrapper(const SwigValueWrapper<T>& rhs);
-public:
-  SwigValueWrapper() : pointer(0) { }
-  SwigValueWrapper& operator=(const T& t) { SwigMovePointer tmp(new T(t)); pointer = tmp; return *this; }
-  operator T&() const { return *pointer.ptr; }
-  T *operator&() { return pointer.ptr; }
-};
-
-template <typename T> T SwigValueInit() {
-  return T();
-}
-#endif
-
-/* -----------------------------------------------------------------------------
- *  This section contains generic SWIG labels for method/variable
- *  declarations/attributes, and other compiler dependent labels.
- * ----------------------------------------------------------------------------- */
-
-/* template workaround for compilers that cannot correctly implement the C++ standard */
-#ifndef SWIGTEMPLATEDISAMBIGUATOR
-# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560)
-#  define SWIGTEMPLATEDISAMBIGUATOR template
-# elif defined(__HP_aCC)
-/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */
-/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */
-#  define SWIGTEMPLATEDISAMBIGUATOR template
-# else
-#  define SWIGTEMPLATEDISAMBIGUATOR
-# endif
-#endif
-
-/* inline attribute */
-#ifndef SWIGINLINE
-# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__))
-#   define SWIGINLINE inline
-# else
-#   define SWIGINLINE
-# endif
-#endif
-
-/* attribute recognised by some compilers to avoid 'unused' warnings */
-#ifndef SWIGUNUSED
-# if defined(__GNUC__)
-#   if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
-#     define SWIGUNUSED __attribute__ ((__unused__))
-#   else
-#     define SWIGUNUSED
-#   endif
-# elif defined(__ICC)
-#   define SWIGUNUSED __attribute__ ((__unused__))
-# else
-#   define SWIGUNUSED
-# endif
-#endif
-
-#ifndef SWIG_MSC_UNSUPPRESS_4505
-# if defined(_MSC_VER)
-#   pragma warning(disable : 4505) /* unreferenced local function has been removed */
-# endif
-#endif
-
-#ifndef SWIGUNUSEDPARM
-# ifdef __cplusplus
-#   define SWIGUNUSEDPARM(p)
-# else
-#   define SWIGUNUSEDPARM(p) p SWIGUNUSED
-# endif
-#endif
-
-/* internal SWIG method */
-#ifndef SWIGINTERN
-# define SWIGINTERN static SWIGUNUSED
-#endif
-
-/* internal inline SWIG method */
-#ifndef SWIGINTERNINLINE
-# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE
-#endif
-
-/* exporting methods */
-#if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
-#  ifndef GCC_HASCLASSVISIBILITY
-#    define GCC_HASCLASSVISIBILITY
-#  endif
-#endif
-
-#ifndef SWIGEXPORT
-# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
-#   if defined(STATIC_LINKED)
-#     define SWIGEXPORT
-#   else
-#     define SWIGEXPORT __declspec(dllexport)
-#   endif
-# else
-#   if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY)
-#     define SWIGEXPORT __attribute__ ((visibility("default")))
-#   else
-#     define SWIGEXPORT
-#   endif
-# endif
-#endif
-
-/* calling conventions for Windows */
-#ifndef SWIGSTDCALL
-# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
-#   define SWIGSTDCALL __stdcall
-# else
-#   define SWIGSTDCALL
-# endif
-#endif
-
-/* Deal with Microsoft's attempt at deprecating C standard runtime functions */
-#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
-# define _CRT_SECURE_NO_DEPRECATE
-#endif
-
-/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */
-#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE)
-# define _SCL_SECURE_NO_DEPRECATE
-#endif
-
-
-/* -----------------------------------------------------------------------------
- * swigrun.swg
- *
- * This file contains generic C API SWIG runtime support for pointer
- * type checking.
- * ----------------------------------------------------------------------------- */
-
-/* This should only be incremented when either the layout of swig_type_info changes,
-   or for whatever reason, the runtime changes incompatibly */
-#define SWIG_RUNTIME_VERSION "4"
-
-/* define SWIG_TYPE_TABLE_NAME as "SWIG_TYPE_TABLE" */
-#ifdef SWIG_TYPE_TABLE
-# define SWIG_QUOTE_STRING(x) #x
-# define SWIG_EXPAND_AND_QUOTE_STRING(x) SWIG_QUOTE_STRING(x)
-# define SWIG_TYPE_TABLE_NAME SWIG_EXPAND_AND_QUOTE_STRING(SWIG_TYPE_TABLE)
-#else
-# define SWIG_TYPE_TABLE_NAME
-#endif
-
-/*
-  You can use the SWIGRUNTIME and SWIGRUNTIMEINLINE macros for
-  creating a static or dynamic library from the SWIG runtime code.
-  In 99.9% of the cases, SWIG just needs to declare them as 'static'.
-
-  But only do this if strictly necessary, ie, if you have problems
-  with your compiler or suchlike.
-*/
-
-#ifndef SWIGRUNTIME
-# define SWIGRUNTIME SWIGINTERN
-#endif
-
-#ifndef SWIGRUNTIMEINLINE
-# define SWIGRUNTIMEINLINE SWIGRUNTIME SWIGINLINE
-#endif
-
-/*  Generic buffer size */
-#ifndef SWIG_BUFFER_SIZE
-# define SWIG_BUFFER_SIZE 1024
-#endif
-
-/* Flags for pointer conversions */
-#define SWIG_POINTER_DISOWN        0x1
-#define SWIG_CAST_NEW_MEMORY       0x2
-
-/* Flags for new pointer objects */
-#define SWIG_POINTER_OWN           0x1
-
-
-/*
-   Flags/methods for returning states.
-
-   The SWIG conversion methods, as ConvertPtr, return an integer
-   that tells if the conversion was successful or not. And if not,
-   an error code can be returned (see swigerrors.swg for the codes).
-
-   Use the following macros/flags to set or process the returning
-   states.
-
-   In old versions of SWIG, code such as the following was usually written:
-
-     if (SWIG_ConvertPtr(obj,vptr,ty.flags) != -1) {
-       // success code
-     } else {
-       //fail code
-     }
-
-   Now you can be more explicit:
-
-    int res = SWIG_ConvertPtr(obj,vptr,ty.flags);
-    if (SWIG_IsOK(res)) {
-      // success code
-    } else {
-      // fail code
-    }
-
-   which is the same really, but now you can also do
-
-    Type *ptr;
-    int res = SWIG_ConvertPtr(obj,(void **)(&ptr),ty.flags);
-    if (SWIG_IsOK(res)) {
-      // success code
-      if (SWIG_IsNewObj(res) {
-        ...
-	delete *ptr;
-      } else {
-        ...
-      }
-    } else {
-      // fail code
-    }
-
-   I.e., now SWIG_ConvertPtr can return new objects and you can
-   identify the case and take care of the deallocation. Of course that
-   also requires SWIG_ConvertPtr to return new result values, such as
-
-      int SWIG_ConvertPtr(obj, ptr,...) {
-        if (<obj is ok>) {
-          if (<need new object>) {
-            *ptr = <ptr to new allocated object>;
-            return SWIG_NEWOBJ;
-          } else {
-            *ptr = <ptr to old object>;
-            return SWIG_OLDOBJ;
-          }
-        } else {
-          return SWIG_BADOBJ;
-        }
-      }
-
-   Of course, returning the plain '0(success)/-1(fail)' still works, but you can be
-   more explicit by returning SWIG_BADOBJ, SWIG_ERROR or any of the
-   SWIG errors code.
-
-   Finally, if the SWIG_CASTRANK_MODE is enabled, the result code
-   allows to return the 'cast rank', for example, if you have this
-
-       int food(double)
-       int fooi(int);
-
-   and you call
-
-      food(1)   // cast rank '1'  (1 -> 1.0)
-      fooi(1)   // cast rank '0'
-
-   just use the SWIG_AddCast()/SWIG_CheckState()
-*/
-
-#define SWIG_OK                    (0)
-#define SWIG_ERROR                 (-1)
-#define SWIG_IsOK(r)               (r >= 0)
-#define SWIG_ArgError(r)           ((r != SWIG_ERROR) ? r : SWIG_TypeError)
-
-/* The CastRankLimit says how many bits are used for the cast rank */
-#define SWIG_CASTRANKLIMIT         (1 << 8)
-/* The NewMask denotes the object was created (using new/malloc) */
-#define SWIG_NEWOBJMASK            (SWIG_CASTRANKLIMIT  << 1)
-/* The TmpMask is for in/out typemaps that use temporal objects */
-#define SWIG_TMPOBJMASK            (SWIG_NEWOBJMASK << 1)
-/* Simple returning values */
-#define SWIG_BADOBJ                (SWIG_ERROR)
-#define SWIG_OLDOBJ                (SWIG_OK)
-#define SWIG_NEWOBJ                (SWIG_OK | SWIG_NEWOBJMASK)
-#define SWIG_TMPOBJ                (SWIG_OK | SWIG_TMPOBJMASK)
-/* Check, add and del mask methods */
-#define SWIG_AddNewMask(r)         (SWIG_IsOK(r) ? (r | SWIG_NEWOBJMASK) : r)
-#define SWIG_DelNewMask(r)         (SWIG_IsOK(r) ? (r & ~SWIG_NEWOBJMASK) : r)
-#define SWIG_IsNewObj(r)           (SWIG_IsOK(r) && (r & SWIG_NEWOBJMASK))
-#define SWIG_AddTmpMask(r)         (SWIG_IsOK(r) ? (r | SWIG_TMPOBJMASK) : r)
-#define SWIG_DelTmpMask(r)         (SWIG_IsOK(r) ? (r & ~SWIG_TMPOBJMASK) : r)
-#define SWIG_IsTmpObj(r)           (SWIG_IsOK(r) && (r & SWIG_TMPOBJMASK))
-
-/* Cast-Rank Mode */
-#if defined(SWIG_CASTRANK_MODE)
-#  ifndef SWIG_TypeRank
-#    define SWIG_TypeRank             unsigned long
-#  endif
-#  ifndef SWIG_MAXCASTRANK            /* Default cast allowed */
-#    define SWIG_MAXCASTRANK          (2)
-#  endif
-#  define SWIG_CASTRANKMASK          ((SWIG_CASTRANKLIMIT) -1)
-#  define SWIG_CastRank(r)           (r & SWIG_CASTRANKMASK)
-SWIGINTERNINLINE int SWIG_AddCast(int r) {
-  return SWIG_IsOK(r) ? ((SWIG_CastRank(r) < SWIG_MAXCASTRANK) ? (r + 1) : SWIG_ERROR) : r;
-}
-SWIGINTERNINLINE int SWIG_CheckState(int r) {
-  return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0;
-}
-#else /* no cast-rank mode */
-#  define SWIG_AddCast(r) (r)
-#  define SWIG_CheckState(r) (SWIG_IsOK(r) ? 1 : 0)
-#endif
-
-
-#include <string.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef void *(*swig_converter_func)(void *, int *);
-typedef struct swig_type_info *(*swig_dycast_func)(void **);
-
-/* Structure to store information on one type */
-typedef struct swig_type_info {
-  const char             *name;			/* mangled name of this type */
-  const char             *str;			/* human readable name of this type */
-  swig_dycast_func        dcast;		/* dynamic cast function down a hierarchy */
-  struct swig_cast_info  *cast;			/* linked list of types that can cast into this type */
-  void                   *clientdata;		/* language specific type data */
-  int                    owndata;		/* flag if the structure owns the clientdata */
-} swig_type_info;
-
-/* Structure to store a type and conversion function used for casting */
-typedef struct swig_cast_info {
-  swig_type_info         *type;			/* pointer to type that is equivalent to this type */
-  swig_converter_func     converter;		/* function to cast the void pointers */
-  struct swig_cast_info  *next;			/* pointer to next cast in linked list */
-  struct swig_cast_info  *prev;			/* pointer to the previous cast */
-} swig_cast_info;
-
-/* Structure used to store module information
- * Each module generates one structure like this, and the runtime collects
- * all of these structures and stores them in a circularly linked list.*/
-typedef struct swig_module_info {
-  swig_type_info         **types;		/* Array of pointers to swig_type_info structures that are in this module */
-  size_t                 size;		        /* Number of types in this module */
-  struct swig_module_info *next;		/* Pointer to next element in circularly linked list */
-  swig_type_info         **type_initial;	/* Array of initially generated type structures */
-  swig_cast_info         **cast_initial;	/* Array of initially generated casting structures */
-  void                    *clientdata;		/* Language specific module data */
-} swig_module_info;
-
-/*
-  Compare two type names skipping the space characters, therefore
-  "char*" == "char *" and "Class<int>" == "Class<int >", etc.
-
-  Return 0 when the two name types are equivalent, as in
-  strncmp, but skipping ' '.
-*/
-SWIGRUNTIME int
-SWIG_TypeNameComp(const char *f1, const char *l1,
-		  const char *f2, const char *l2) {
-  for (;(f1 != l1) && (f2 != l2); ++f1, ++f2) {
-    while ((*f1 == ' ') && (f1 != l1)) ++f1;
-    while ((*f2 == ' ') && (f2 != l2)) ++f2;
-    if (*f1 != *f2) return (*f1 > *f2) ? 1 : -1;
-  }
-  return (int)((l1 - f1) - (l2 - f2));
-}
-
-/*
-  Check type equivalence in a name list like <name1>|<name2>|...
-  Return 0 if equal, -1 if nb < tb, 1 if nb > tb
-*/
-SWIGRUNTIME int
-SWIG_TypeCmp(const char *nb, const char *tb) {
-  int equiv = 1;
-  const char* te = tb + strlen(tb);
-  const char* ne = nb;
-  while (equiv != 0 && *ne) {
-    for (nb = ne; *ne; ++ne) {
-      if (*ne == '|') break;
-    }
-    equiv = SWIG_TypeNameComp(nb, ne, tb, te);
-    if (*ne) ++ne;
-  }
-  return equiv;
-}
-
-/*
-  Check type equivalence in a name list like <name1>|<name2>|...
-  Return 0 if not equal, 1 if equal
-*/
-SWIGRUNTIME int
-SWIG_TypeEquiv(const char *nb, const char *tb) {
-  return SWIG_TypeCmp(nb, tb) == 0 ? 1 : 0;
-}
-
-/*
-  Check the typename
-*/
-SWIGRUNTIME swig_cast_info *
-SWIG_TypeCheck(const char *c, swig_type_info *ty) {
-  if (ty) {
-    swig_cast_info *iter = ty->cast;
-    while (iter) {
-      if (strcmp(iter->type->name, c) == 0) {
-        if (iter == ty->cast)
-          return iter;
-        /* Move iter to the top of the linked list */
-        iter->prev->next = iter->next;
-        if (iter->next)
-          iter->next->prev = iter->prev;
-        iter->next = ty->cast;
-        iter->prev = 0;
-        if (ty->cast) ty->cast->prev = iter;
-        ty->cast = iter;
-        return iter;
-      }
-      iter = iter->next;
-    }
-  }
-  return 0;
-}
-
-/*
-  Identical to SWIG_TypeCheck, except strcmp is replaced with a pointer comparison
-*/
-SWIGRUNTIME swig_cast_info *
-SWIG_TypeCheckStruct(swig_type_info *from, swig_type_info *ty) {
-  if (ty) {
-    swig_cast_info *iter = ty->cast;
-    while (iter) {
-      if (iter->type == from) {
-        if (iter == ty->cast)
-          return iter;
-        /* Move iter to the top of the linked list */
-        iter->prev->next = iter->next;
-        if (iter->next)
-          iter->next->prev = iter->prev;
-        iter->next = ty->cast;
-        iter->prev = 0;
-        if (ty->cast) ty->cast->prev = iter;
-        ty->cast = iter;
-        return iter;
-      }
-      iter = iter->next;
-    }
-  }
-  return 0;
-}
-
-/*
-  Cast a pointer up an inheritance hierarchy
-*/
-SWIGRUNTIMEINLINE void *
-SWIG_TypeCast(swig_cast_info *ty, void *ptr, int *newmemory) {
-  return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr, newmemory);
-}
-
-/*
-   Dynamic pointer casting. Down an inheritance hierarchy
-*/
-SWIGRUNTIME swig_type_info *
-SWIG_TypeDynamicCast(swig_type_info *ty, void **ptr) {
-  swig_type_info *lastty = ty;
-  if (!ty || !ty->dcast) return ty;
-  while (ty && (ty->dcast)) {
-    ty = (*ty->dcast)(ptr);
-    if (ty) lastty = ty;
-  }
-  return lastty;
-}
-
-/*
-  Return the name associated with this type
-*/
-SWIGRUNTIMEINLINE const char *
-SWIG_TypeName(const swig_type_info *ty) {
-  return ty->name;
-}
-
-/*
-  Return the pretty name associated with this type,
-  that is an unmangled type name in a form presentable to the user.
-*/
-SWIGRUNTIME const char *
-SWIG_TypePrettyName(const swig_type_info *type) {
-  /* The "str" field contains the equivalent pretty names of the
-     type, separated by vertical-bar characters.  We choose
-     to print the last name, as it is often (?) the most
-     specific. */
-  if (!type) return NULL;
-  if (type->str != NULL) {
-    const char *last_name = type->str;
-    const char *s;
-    for (s = type->str; *s; s++)
-      if (*s == '|') last_name = s+1;
-    return last_name;
-  }
-  else
-    return type->name;
-}
-
-/*
-   Set the clientdata field for a type
-*/
-SWIGRUNTIME void
-SWIG_TypeClientData(swig_type_info *ti, void *clientdata) {
-  swig_cast_info *cast = ti->cast;
-  /* if (ti->clientdata == clientdata) return; */
-  ti->clientdata = clientdata;
-
-  while (cast) {
-    if (!cast->converter) {
-      swig_type_info *tc = cast->type;
-      if (!tc->clientdata) {
-	SWIG_TypeClientData(tc, clientdata);
-      }
-    }
-    cast = cast->next;
-  }
-}
-SWIGRUNTIME void
-SWIG_TypeNewClientData(swig_type_info *ti, void *clientdata) {
-  SWIG_TypeClientData(ti, clientdata);
-  ti->owndata = 1;
-}
-
-/*
-  Search for a swig_type_info structure only by mangled name
-  Search is a O(log #types)
-
-  We start searching at module start, and finish searching when start == end.
-  Note: if start == end at the beginning of the function, we go all the way around
-  the circular list.
-*/
-SWIGRUNTIME swig_type_info *
-SWIG_MangledTypeQueryModule(swig_module_info *start,
-                            swig_module_info *end,
-		            const char *name) {
-  swig_module_info *iter = start;
-  do {
-    if (iter->size) {
-      register size_t l = 0;
-      register size_t r = iter->size - 1;
-      do {
-	/* since l+r >= 0, we can (>> 1) instead (/ 2) */
-	register size_t i = (l + r) >> 1;
-	const char *iname = iter->types[i]->name;
-	if (iname) {
-	  register int compare = strcmp(name, iname);
-	  if (compare == 0) {
-	    return iter->types[i];
-	  } else if (compare < 0) {
-	    if (i) {
-	      r = i - 1;
-	    } else {
-	      break;
-	    }
-	  } else if (compare > 0) {
-	    l = i + 1;
-	  }
-	} else {
-	  break; /* should never happen */
-	}
-      } while (l <= r);
-    }
-    iter = iter->next;
-  } while (iter != end);
-  return 0;
-}
-
-/*
-  Search for a swig_type_info structure for either a mangled name or a human readable name.
-  It first searches the mangled names of the types, which is a O(log #types)
-  If a type is not found it then searches the human readable names, which is O(#types).
-
-  We start searching at module start, and finish searching when start == end.
-  Note: if start == end at the beginning of the function, we go all the way around
-  the circular list.
-*/
-SWIGRUNTIME swig_type_info *
-SWIG_TypeQueryModule(swig_module_info *start,
-                     swig_module_info *end,
-		     const char *name) {
-  /* STEP 1: Search the name field using binary search */
-  swig_type_info *ret = SWIG_MangledTypeQueryModule(start, end, name);
-  if (ret) {
-    return ret;
-  } else {
-    /* STEP 2: If the type hasn't been found, do a complete search
-       of the str field (the human readable name) */
-    swig_module_info *iter = start;
-    do {
-      register size_t i = 0;
-      for (; i < iter->size; ++i) {
-	if (iter->types[i]->str && (SWIG_TypeEquiv(iter->types[i]->str, name)))
-	  return iter->types[i];
-      }
-      iter = iter->next;
-    } while (iter != end);
-  }
-
-  /* neither found a match */
-  return 0;
-}
-
-/*
-   Pack binary data into a string
-*/
-SWIGRUNTIME char *
-SWIG_PackData(char *c, void *ptr, size_t sz) {
-  static const char hex[17] = "0123456789abcdef";
-  register const unsigned char *u = (unsigned char *) ptr;
-  register const unsigned char *eu =  u + sz;
-  for (; u != eu; ++u) {
-    register unsigned char uu = *u;
-    *(c++) = hex[(uu & 0xf0) >> 4];
-    *(c++) = hex[uu & 0xf];
-  }
-  return c;
-}
-
-/*
-   Unpack binary data from a string
-*/
-SWIGRUNTIME const char *
-SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
-  register unsigned char *u = (unsigned char *) ptr;
-  register const unsigned char *eu = u + sz;
-  for (; u != eu; ++u) {
-    register char d = *(c++);
-    register unsigned char uu;
-    if ((d >= '0') && (d <= '9'))
-      uu = ((d - '0') << 4);
-    else if ((d >= 'a') && (d <= 'f'))
-      uu = ((d - ('a'-10)) << 4);
-    else
-      return (char *) 0;
-    d = *(c++);
-    if ((d >= '0') && (d <= '9'))
-      uu |= (d - '0');
-    else if ((d >= 'a') && (d <= 'f'))
-      uu |= (d - ('a'-10));
-    else
-      return (char *) 0;
-    *u = uu;
-  }
-  return c;
-}
-
-/*
-   Pack 'void *' into a string buffer.
-*/
-SWIGRUNTIME char *
-SWIG_PackVoidPtr(char *buff, void *ptr, const char *name, size_t bsz) {
-  char *r = buff;
-  if ((2*sizeof(void *) + 2) > bsz) return 0;
-  *(r++) = '_';
-  r = SWIG_PackData(r,&ptr,sizeof(void *));
-  if (strlen(name) + 1 > (bsz - (r - buff))) return 0;
-  strcpy(r,name);
-  return buff;
-}
-
-SWIGRUNTIME const char *
-SWIG_UnpackVoidPtr(const char *c, void **ptr, const char *name) {
-  if (*c != '_') {
-    if (strcmp(c,"NULL") == 0) {
-      *ptr = (void *) 0;
-      return name;
-    } else {
-      return 0;
-    }
-  }
-  return SWIG_UnpackData(++c,ptr,sizeof(void *));
-}
-
-SWIGRUNTIME char *
-SWIG_PackDataName(char *buff, void *ptr, size_t sz, const char *name, size_t bsz) {
-  char *r = buff;
-  size_t lname = (name ? strlen(name) : 0);
-  if ((2*sz + 2 + lname) > bsz) return 0;
-  *(r++) = '_';
-  r = SWIG_PackData(r,ptr,sz);
-  if (lname) {
-    strncpy(r,name,lname+1);
-  } else {
-    *r = 0;
-  }
-  return buff;
-}
-
-SWIGRUNTIME const char *
-SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) {
-  if (*c != '_') {
-    if (strcmp(c,"NULL") == 0) {
-      memset(ptr,0,sz);
-      return name;
-    } else {
-      return 0;
-    }
-  }
-  return SWIG_UnpackData(++c,ptr,sz);
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-/*  Errors in SWIG */
-#define  SWIG_UnknownError    	   -1
-#define  SWIG_IOError        	   -2
-#define  SWIG_RuntimeError   	   -3
-#define  SWIG_IndexError     	   -4
-#define  SWIG_TypeError      	   -5
-#define  SWIG_DivisionByZero 	   -6
-#define  SWIG_OverflowError  	   -7
-#define  SWIG_SyntaxError    	   -8
-#define  SWIG_ValueError     	   -9
-#define  SWIG_SystemError    	   -10
-#define  SWIG_AttributeError 	   -11
-#define  SWIG_MemoryError    	   -12
-#define  SWIG_NullReferenceError   -13
-
-
-
-#ifdef __cplusplus
-/* Needed on some windows machines---since MS plays funny games with the header files under C++ */
-#include <math.h>
-#include <stdlib.h>
-extern "C" {
-#endif
-#include "EXTERN.h"
-#include "perl.h"
-#include "XSUB.h"
-
-/* Add in functionality missing in older versions of Perl. Much of this is based on Devel-PPPort on cpan. */
-
-/* Add PERL_REVISION, PERL_VERSION, PERL_SUBVERSION if missing */
-#ifndef PERL_REVISION
-#  if !defined(__PATCHLEVEL_H_INCLUDED__) && !(defined(PATCHLEVEL) && defined(SUBVERSION))
-#    define PERL_PATCHLEVEL_H_IMPLICIT
-#    include <patchlevel.h>
-#  endif
-#  if !(defined(PERL_VERSION) || (defined(SUBVERSION) && defined(PATCHLEVEL)))
-#    include <could_not_find_Perl_patchlevel.h>
-#  endif
-#  ifndef PERL_REVISION
-#    define PERL_REVISION       (5)
-#    define PERL_VERSION        PATCHLEVEL
-#    define PERL_SUBVERSION     SUBVERSION
-#  endif
-#endif
-
-#if defined(WIN32) && defined(PERL_OBJECT) && !defined(PerlIO_exportFILE)
-#define PerlIO_exportFILE(fh,fl) (FILE*)(fh)
-#endif
-
-#ifndef SvIOK_UV
-# define SvIOK_UV(sv)       (SvIOK(sv) && (SvUVX(sv) == SvIVX(sv)))
-#endif
-
-#ifndef SvUOK
-# define SvUOK(sv)           SvIOK_UV(sv)
-#endif
-
-#if ((PERL_VERSION < 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION <= 5)))
-#  define PL_sv_undef               sv_undef
-#  define PL_na	                    na
-#  define PL_errgv                  errgv
-#  define PL_sv_no                  sv_no
-#  define PL_sv_yes                 sv_yes
-#  define PL_markstack_ptr          markstack_ptr
-#endif
-
-#ifndef IVSIZE
-#  ifdef LONGSIZE
-#    define IVSIZE LONGSIZE
-#  else
-#    define IVSIZE 4 /* A bold guess, but the best we can make. */
-#  endif
-#endif
-
-#ifndef INT2PTR
-#  if (IVSIZE == PTRSIZE) && (UVSIZE == PTRSIZE)
-#    define PTRV                  UV
-#    define INT2PTR(any,d)        (any)(d)
-#  else
-#    if PTRSIZE == LONGSIZE
-#      define PTRV                unsigned long
-#    else
-#      define PTRV                unsigned
-#    endif
-#    define INT2PTR(any,d)        (any)(PTRV)(d)
-#  endif
-
-#  define NUM2PTR(any,d)  (any)(PTRV)(d)
-#  define PTR2IV(p)       INT2PTR(IV,p)
-#  define PTR2UV(p)       INT2PTR(UV,p)
-#  define PTR2NV(p)       NUM2PTR(NV,p)
-
-#  if PTRSIZE == LONGSIZE
-#    define PTR2ul(p)     (unsigned long)(p)
-#  else
-#    define PTR2ul(p)     INT2PTR(unsigned long,p)
-#  endif
-#endif /* !INT2PTR */
-
-#ifndef SvPV_nolen
-# define SvPV_nolen(x) SvPV(x,PL_na)
-#endif
-
-#ifndef get_sv
-#  define get_sv perl_get_sv
-#endif
-
-#ifndef ERRSV
-#  define ERRSV get_sv("@",FALSE)
-#endif
-
-#ifndef pTHX_
-#define pTHX_
-#endif   
-
-#include <string.h>
-#ifdef __cplusplus
-}
-#endif
-
-/* -----------------------------------------------------------------------------
- * error manipulation
- * ----------------------------------------------------------------------------- */
-
-SWIGINTERN const char*
-SWIG_Perl_ErrorType(int code) {
-  switch(code) {
-  case SWIG_MemoryError:
-    return "MemoryError";
-  case SWIG_IOError:
-    return "IOError";
-  case SWIG_RuntimeError:
-    return "RuntimeError";
-  case SWIG_IndexError:
-    return "IndexError";
-  case SWIG_TypeError:
-    return "TypeError";
-  case SWIG_DivisionByZero:
-    return "ZeroDivisionError";
-  case SWIG_OverflowError:
-    return "OverflowError";
-  case SWIG_SyntaxError:
-    return "SyntaxError";
-  case SWIG_ValueError:
-    return "ValueError";
-  case SWIG_SystemError:
-    return "SystemError";
-  case SWIG_AttributeError:
-    return "AttributeError";
-  default:
-    return "RuntimeError";
-  }
-}
-
-
-/* -----------------------------------------------------------------------------
- * perlrun.swg
- *
- * This file contains the runtime support for Perl modules
- * and includes code for managing global variables and pointer
- * type checking.
- * ----------------------------------------------------------------------------- */
-
-#ifdef PERL_OBJECT
-#define SWIG_PERL_OBJECT_DECL CPerlObj *SWIGUNUSEDPARM(pPerl),
-#define SWIG_PERL_OBJECT_CALL pPerl,
-#else
-#define SWIG_PERL_OBJECT_DECL
-#define SWIG_PERL_OBJECT_CALL
-#endif
-
-/* Common SWIG API */
-
-/* for raw pointers */
-#define SWIG_ConvertPtr(obj, pp, type, flags)           SWIG_Perl_ConvertPtr(SWIG_PERL_OBJECT_CALL obj, pp, type, flags)
-#define SWIG_ConvertPtrAndOwn(obj, pp, type, flags,own) SWIG_Perl_ConvertPtrAndOwn(SWIG_PERL_OBJECT_CALL obj, pp, type, flags, own)
-#define SWIG_NewPointerObj(p, type, flags)              SWIG_Perl_NewPointerObj(SWIG_PERL_OBJECT_CALL p, type, flags)
-
-/* for raw packed data */
-#define SWIG_ConvertPacked(obj, p, s, type)             SWIG_Perl_ConvertPacked(SWIG_PERL_OBJECT_CALL obj, p, s, type)
-#define SWIG_NewPackedObj(p, s, type)	                SWIG_Perl_NewPackedObj(SWIG_PERL_OBJECT_CALL p, s, type)
-
-/* for class or struct pointers */
-#define SWIG_ConvertInstance(obj, pptr, type, flags)    SWIG_ConvertPtr(obj, pptr, type, flags)
-#define SWIG_NewInstanceObj(ptr, type, flags)           SWIG_NewPointerObj(ptr, type, flags)
-
-/* for C or C++ function pointers */
-#define SWIG_ConvertFunctionPtr(obj, pptr, type)        SWIG_ConvertPtr(obj, pptr, type, 0)
-#define SWIG_NewFunctionPtrObj(ptr, type)               SWIG_NewPointerObj(ptr, type, 0)
-
-/* for C++ member pointers, ie, member methods */
-#define SWIG_ConvertMember(obj, ptr, sz, ty)            SWIG_ConvertPacked(obj, ptr, sz, ty)
-#define SWIG_NewMemberObj(ptr, sz, type)                SWIG_NewPackedObj(ptr, sz, type)
-
-
-/* Runtime API */
-
-#define SWIG_GetModule(clientdata)                      SWIG_Perl_GetModule(clientdata)
-#define SWIG_SetModule(clientdata, pointer)             SWIG_Perl_SetModule(pointer)
-
-
-/* Error manipulation */
-
-#define SWIG_ErrorType(code)                            SWIG_Perl_ErrorType(code)               
-#define SWIG_Error(code, msg)            		sv_setpvf(get_sv("@", GV_ADD), "%s %s", SWIG_ErrorType(code), msg)
-#define SWIG_fail                        		goto fail						    
-
-/* Perl-specific SWIG API */
-
-#define SWIG_MakePtr(sv, ptr, type, flags)              SWIG_Perl_MakePtr(SWIG_PERL_OBJECT_CALL sv, ptr, type, flags)
-#define SWIG_MakePackedObj(sv, p, s, type)	        SWIG_Perl_MakePackedObj(SWIG_PERL_OBJECT_CALL sv, p, s, type)
-#define SWIG_SetError(str)                              SWIG_Error(SWIG_RuntimeError, str)
-
-
-#define SWIG_PERL_DECL_ARGS_1(arg1)                     (SWIG_PERL_OBJECT_DECL arg1)
-#define SWIG_PERL_CALL_ARGS_1(arg1)                     (SWIG_PERL_OBJECT_CALL arg1)
-#define SWIG_PERL_DECL_ARGS_2(arg1, arg2)               (SWIG_PERL_OBJECT_DECL arg1, arg2)
-#define SWIG_PERL_CALL_ARGS_2(arg1, arg2)               (SWIG_PERL_OBJECT_CALL arg1, arg2)
-
-/* -----------------------------------------------------------------------------
- * pointers/data manipulation
- * ----------------------------------------------------------------------------- */
-
-/* For backward compatibility only */
-#define SWIG_POINTER_EXCEPTION  0
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define SWIG_OWNER   SWIG_POINTER_OWN
-#define SWIG_SHADOW  SWIG_OWNER << 1
-
-#define SWIG_MAYBE_PERL_OBJECT SWIG_PERL_OBJECT_DECL
-
-/* SWIG Perl macros */
-
-/* Macro to declare an XS function */
-#ifndef XSPROTO
-#   define XSPROTO(name) void name(pTHX_ CV* cv)
-#endif
-
-/* Macro to call an XS function */
-#ifdef PERL_OBJECT 
-#  define SWIG_CALLXS(_name) _name(cv,pPerl) 
-#else 
-#  ifndef MULTIPLICITY 
-#    define SWIG_CALLXS(_name) _name(cv) 
-#  else 
-#    define SWIG_CALLXS(_name) _name(PERL_GET_THX, cv) 
-#  endif 
-#endif 
-
-#ifdef PERL_OBJECT
-#define MAGIC_PPERL  CPerlObj *pPerl = (CPerlObj *) this;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-typedef int (CPerlObj::*SwigMagicFunc)(SV *, MAGIC *);
-#ifdef __cplusplus
-}
-#endif
-
-#define SWIG_MAGIC(a,b) (SV *a, MAGIC *b)
-#define SWIGCLASS_STATIC
-
-#else /* PERL_OBJECT */
-
-#define MAGIC_PPERL
-#define SWIGCLASS_STATIC static SWIGUNUSED
-
-#ifndef MULTIPLICITY
-#define SWIG_MAGIC(a,b) (SV *a, MAGIC *b)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-typedef int (*SwigMagicFunc)(SV *, MAGIC *);
-#ifdef __cplusplus
-}
-#endif
-
-#else /* MULTIPLICITY */
-
-#define SWIG_MAGIC(a,b) (struct interpreter *interp, SV *a, MAGIC *b)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-typedef int (*SwigMagicFunc)(struct interpreter *, SV *, MAGIC *);
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* MULTIPLICITY */
-#endif /* PERL_OBJECT */
-
-#  ifdef PERL_OBJECT
-#    define SWIG_croak_null() SWIG_Perl_croak_null(pPerl)
-static void SWIG_Perl_croak_null(CPerlObj *pPerl)
-#  else
-static void SWIG_croak_null()
-#  endif
-{
-  SV *err = get_sv("@", GV_ADD);
-#  if (PERL_VERSION < 6)
-  croak("%_", err);
-#  else
-  if (sv_isobject(err))
-    croak(0);
-  else
-    croak("%s", SvPV_nolen(err));
-#  endif
-}
-
-
-/* 
-   Define how strict is the cast between strings and integers/doubles
-   when overloading between these types occurs.
-   
-   The default is making it as strict as possible by using SWIG_AddCast
-   when needed.
-   
-   You can use -DSWIG_PERL_NO_STRICT_STR2NUM at compilation time to
-   disable the SWIG_AddCast, making the casting between string and
-   numbers less strict.
-
-   In the end, we try to solve the overloading between strings and
-   numerical types in the more natural way, but if you can avoid it,
-   well, avoid it using %rename, for example.
-*/
-#ifndef SWIG_PERL_NO_STRICT_STR2NUM
-# ifndef SWIG_PERL_STRICT_STR2NUM
-#  define SWIG_PERL_STRICT_STR2NUM
-# endif
-#endif
-#ifdef SWIG_PERL_STRICT_STR2NUM
-/* string takes precedence */
-#define SWIG_Str2NumCast(x) SWIG_AddCast(x)  
-#else
-/* number takes precedence */
-#define SWIG_Str2NumCast(x) x
-#endif
-
-
-
-#include <stdlib.h>
-
-SWIGRUNTIME const char *
-SWIG_Perl_TypeProxyName(const swig_type_info *type) {
-  if (!type) return NULL;
-  if (type->clientdata != NULL) {
-    return (const char*) type->clientdata;
-  } 
-  else {
-    return type->name;
-  }
-}
-
-/* Identical to SWIG_TypeCheck, except for strcmp comparison */
-SWIGRUNTIME swig_cast_info *
-SWIG_TypeProxyCheck(const char *c, swig_type_info *ty) {
-  if (ty) {
-    swig_cast_info *iter = ty->cast;
-    while (iter) {
-      if (strcmp(SWIG_Perl_TypeProxyName(iter->type), c) == 0) {
-        if (iter == ty->cast)
-          return iter;
-        /* Move iter to the top of the linked list */
-        iter->prev->next = iter->next;
-        if (iter->next)
-          iter->next->prev = iter->prev;
-        iter->next = ty->cast;
-        iter->prev = 0;
-        if (ty->cast) ty->cast->prev = iter;
-        ty->cast = iter;
-        return iter;
-      }
-      iter = iter->next;
-    }
-  }
-  return 0;
-}
-
-/* Function for getting a pointer value */
-
-SWIGRUNTIME int
-SWIG_Perl_ConvertPtrAndOwn(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *_t, int flags, int *own) {
-  swig_cast_info *tc;
-  void *voidptr = (void *)0;
-  SV *tsv = 0;
-
-  if (own)
-    *own = 0;
-
-  /* If magical, apply more magic */
-  if (SvGMAGICAL(sv))
-    mg_get(sv);
-
-  /* Check to see if this is an object */
-  if (sv_isobject(sv)) {
-    IV tmp = 0;
-    tsv = (SV*) SvRV(sv);
-    if ((SvTYPE(tsv) == SVt_PVHV)) {
-      MAGIC *mg;
-      if (SvMAGICAL(tsv)) {
-        mg = mg_find(tsv,'P');
-        if (mg) {
-          sv = mg->mg_obj;
-          if (sv_isobject(sv)) {
-	    tsv = (SV*)SvRV(sv);
-            tmp = SvIV(tsv);
-          }
-        }
-      } else {
-        return SWIG_ERROR;
-      }
-    } else {
-      tmp = SvIV(tsv);
-    }
-    voidptr = INT2PTR(void *,tmp);
-  } else if (! SvOK(sv)) {            /* Check for undef */
-    *(ptr) = (void *) 0;
-    return SWIG_OK;
-  } else if (SvTYPE(sv) == SVt_RV) {  /* Check for NULL pointer */
-    if (!SvROK(sv)) {
-      /* In Perl 5.12 and later, SVt_RV == SVt_IV, so sv could be a valid integer value.  */
-      if (SvIOK(sv)) {
-        return SWIG_ERROR;
-      } else {
-        /* NULL pointer (reference to undef). */
-        *(ptr) = (void *) 0;
-        return SWIG_OK;
-      }
-    } else {
-      return SWIG_ERROR;
-    }
-  } else {                            /* Don't know what it is */
-    return SWIG_ERROR;
-  }
-  if (_t) {
-    /* Now see if the types match */
-    char *_c = HvNAME(SvSTASH(SvRV(sv)));
-    tc = SWIG_TypeProxyCheck(_c,_t);
-    if (!tc) {
-      return SWIG_ERROR;
-    }
-    {
-      int newmemory = 0;
-      *ptr = SWIG_TypeCast(tc,voidptr,&newmemory);
-      if (newmemory == SWIG_CAST_NEW_MEMORY) {
-        assert(own); /* badly formed typemap which will lead to a memory leak - it must set and use own to delete *ptr */
-        if (own)
-          *own = *own | SWIG_CAST_NEW_MEMORY;
-      }
-    }
-  } else {
-    *ptr = voidptr;
-  }
-
-  /* 
-   *  DISOWN implementation: we need a perl guru to check this one.
-   */
-  if (tsv && (flags & SWIG_POINTER_DISOWN)) {
-    /* 
-     *  almost copy paste code from below SWIG_POINTER_OWN setting
-     */
-    SV *obj = sv;
-    HV *stash = SvSTASH(SvRV(obj));
-    GV *gv = *(GV**)hv_fetch(stash, "OWNER", 5, TRUE);
-    if (isGV(gv)) {
-      HV *hv = GvHVn(gv);
-      /*
-       * To set ownership (see below), a newSViv(1) entry is added. 
-       * Hence, to remove ownership, we delete the entry.
-       */
-      if (hv_exists_ent(hv, obj, 0)) {
-	hv_delete_ent(hv, obj, 0, 0);
-      }
-    }
-  }
-  return SWIG_OK;
-}
-
-SWIGRUNTIME int
-SWIG_Perl_ConvertPtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *_t, int flags) {
-  return SWIG_Perl_ConvertPtrAndOwn(sv, ptr, _t, flags, 0);
-}
-
-SWIGRUNTIME void
-SWIG_Perl_MakePtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void *ptr, swig_type_info *t, int flags) {
-  if (ptr && (flags & (SWIG_SHADOW | SWIG_POINTER_OWN))) {
-    SV *self;
-    SV *obj=newSV(0);
-    HV *hash=newHV();
-    HV *stash;
-    sv_setref_pv(obj, SWIG_Perl_TypeProxyName(t), ptr);
-    stash=SvSTASH(SvRV(obj));
-    if (flags & SWIG_POINTER_OWN) {
-      HV *hv;
-      GV *gv = *(GV**)hv_fetch(stash, "OWNER", 5, TRUE);
-      if (!isGV(gv))
-        gv_init(gv, stash, "OWNER", 5, FALSE);
-      hv=GvHVn(gv);
-      hv_store_ent(hv, obj, newSViv(1), 0);
-    }
-    sv_magic((SV *)hash, (SV *)obj, 'P', Nullch, 0);
-    SvREFCNT_dec(obj);
-    self=newRV_noinc((SV *)hash);
-    sv_setsv(sv, self);
-    SvREFCNT_dec((SV *)self);
-    sv_bless(sv, stash);
-  }
-  else {
-    sv_setref_pv(sv, SWIG_Perl_TypeProxyName(t), ptr);
-  }
-}
-
-SWIGRUNTIMEINLINE SV *
-SWIG_Perl_NewPointerObj(SWIG_MAYBE_PERL_OBJECT void *ptr, swig_type_info *t, int flags) {
-  SV *result = sv_newmortal();
-  SWIG_MakePtr(result, ptr, t, flags);
-  return result;
-}
-
-SWIGRUNTIME void
-SWIG_Perl_MakePackedObj(SWIG_MAYBE_PERL_OBJECT SV *sv, void *ptr, int sz, swig_type_info *type) {
-  char result[1024];
-  char *r = result;
-  if ((2*sz + 1 + strlen(SWIG_Perl_TypeProxyName(type))) > 1000) return;
-  *(r++) = '_';
-  r = SWIG_PackData(r,ptr,sz);
-  strcpy(r,SWIG_Perl_TypeProxyName(type));
-  sv_setpv(sv, result);
-}
-
-SWIGRUNTIME SV *
-SWIG_Perl_NewPackedObj(SWIG_MAYBE_PERL_OBJECT void *ptr, int sz, swig_type_info *type) {
-  SV *result = sv_newmortal();
-  SWIG_Perl_MakePackedObj(result, ptr, sz, type);
-  return result;
-}
-
-/* Convert a packed value value */
-SWIGRUNTIME int
-SWIG_Perl_ConvertPacked(SWIG_MAYBE_PERL_OBJECT SV *obj, void *ptr, int sz, swig_type_info *ty) {
-  swig_cast_info *tc;
-  const char  *c = 0;
-
-  if ((!obj) || (!SvOK(obj))) return SWIG_ERROR;
-  c = SvPV_nolen(obj);
-  /* Pointer values must start with leading underscore */
-  if (*c != '_') return SWIG_ERROR;
-  c++;
-  c = SWIG_UnpackData(c,ptr,sz);
-  if (ty) {
-    tc = SWIG_TypeCheck(c,ty);
-    if (!tc) return SWIG_ERROR;
-  }
-  return SWIG_OK;
-}
-
-
-/* Macros for low-level exception handling */
-#define SWIG_croak(x)    { SWIG_Error(SWIG_RuntimeError, x); SWIG_fail; }
-
-
-typedef XSPROTO(SwigPerlWrapper);
-typedef SwigPerlWrapper *SwigPerlWrapperPtr;
-
-/* Structure for command table */
-typedef struct {
-  const char         *name;
-  SwigPerlWrapperPtr  wrapper;
-} swig_command_info;
-
-/* Information for constant table */
-
-#define SWIG_INT     1
-#define SWIG_FLOAT   2
-#define SWIG_STRING  3
-#define SWIG_POINTER 4
-#define SWIG_BINARY  5
-
-/* Constant information structure */
-typedef struct swig_constant_info {
-    int              type;
-    const char      *name;
-    long             lvalue;
-    double           dvalue;
-    void            *pvalue;
-    swig_type_info **ptype;
-} swig_constant_info;
-
-
-/* Structure for variable table */
-typedef struct {
-  const char   *name;
-  SwigMagicFunc   set;
-  SwigMagicFunc   get;
-  swig_type_info  **type;
-} swig_variable_info;
-
-/* Magic variable code */
-#ifndef PERL_OBJECT
-# ifdef __cplusplus
-#  define swig_create_magic(s,a,b,c) _swig_create_magic(s,const_cast<char*>(a),b,c)
-# else
-#  define swig_create_magic(s,a,b,c) _swig_create_magic(s,(char*)(a),b,c)
-# endif
-# ifndef MULTIPLICITY
-SWIGRUNTIME void _swig_create_magic(SV *sv, char *name, int (*set)(SV *, MAGIC *), int (*get)(SV *,MAGIC *)) 
-# else
-SWIGRUNTIME void _swig_create_magic(SV *sv, char *name, int (*set)(struct interpreter*, SV *, MAGIC *), int (*get)(struct interpreter*, SV *,MAGIC *)) 
-# endif
-#else
-#  define swig_create_magic(s,a,b,c) _swig_create_magic(pPerl,s,a,b,c)
-SWIGRUNTIME void _swig_create_magic(CPerlObj *pPerl, SV *sv, const char *name, int (CPerlObj::*set)(SV *, MAGIC *), int (CPerlObj::*get)(SV *, MAGIC *)) 
-#endif
-{
-  MAGIC *mg;
-  sv_magic(sv,sv,'U',name,strlen(name));
-  mg = mg_find(sv,'U');
-  mg->mg_virtual = (MGVTBL *) malloc(sizeof(MGVTBL));
-  mg->mg_virtual->svt_get = (SwigMagicFunc) get;
-  mg->mg_virtual->svt_set = (SwigMagicFunc) set;
-  mg->mg_virtual->svt_len = 0;
-  mg->mg_virtual->svt_clear = 0;
-  mg->mg_virtual->svt_free = 0;
-}
-
-
-SWIGRUNTIME swig_module_info *
-SWIG_Perl_GetModule(void *SWIGUNUSEDPARM(clientdata)) {
-  static void *type_pointer = (void *)0;
-  SV *pointer;
-
-  /* first check if pointer already created */
-  if (!type_pointer) {
-    pointer = get_sv("swig_runtime_data::type_pointer" SWIG_RUNTIME_VERSION SWIG_TYPE_TABLE_NAME, FALSE | GV_ADDMULTI);
-    if (pointer && SvOK(pointer)) {
-      type_pointer = INT2PTR(swig_type_info **, SvIV(pointer));
-    }
-  }
-
-  return (swig_module_info *) type_pointer;
-}
-
-SWIGRUNTIME void
-SWIG_Perl_SetModule(swig_module_info *module) {
-  SV *pointer;
-
-  /* create a new pointer */
-  pointer = get_sv("swig_runtime_data::type_pointer" SWIG_RUNTIME_VERSION SWIG_TYPE_TABLE_NAME, TRUE | GV_ADDMULTI);
-  sv_setiv(pointer, PTR2IV(module));
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-/* Workaround perl5 global namespace pollution. Note that undefining library
- * functions like fopen will not solve the problem on all platforms as fopen
- * might be a macro on Windows but not necessarily on other operating systems. */
-#ifdef do_open
-  #undef do_open
-#endif
-#ifdef do_close
-  #undef do_close
-#endif
-#ifdef do_exec
-  #undef do_exec
-#endif
-#ifdef scalar
-  #undef scalar
-#endif
-#ifdef list
-  #undef list
-#endif
-#ifdef apply
-  #undef apply
-#endif
-#ifdef convert
-  #undef convert
-#endif
-#ifdef Error
-  #undef Error
-#endif
-#ifdef form
-  #undef form
-#endif
-#ifdef vform
-  #undef vform
-#endif
-#ifdef LABEL
-  #undef LABEL
-#endif
-#ifdef METHOD
-  #undef METHOD
-#endif
-#ifdef Move
-  #undef Move
-#endif
-#ifdef yylex
-  #undef yylex
-#endif
-#ifdef yyparse
-  #undef yyparse
-#endif
-#ifdef yyerror
-  #undef yyerror
-#endif
-#ifdef invert
-  #undef invert
-#endif
-#ifdef ref
-  #undef ref
-#endif
-#ifdef read
-  #undef read
-#endif
-#ifdef write
-  #undef write
-#endif
-#ifdef eof
-  #undef eof
-#endif
-#ifdef close
-  #undef close
-#endif
-#ifdef rewind
-  #undef rewind
-#endif
-#ifdef free
-  #undef free
-#endif
-#ifdef malloc
-  #undef malloc
-#endif
-#ifdef calloc
-  #undef calloc
-#endif
-#ifdef Stat
-  #undef Stat
-#endif
-#ifdef check
-  #undef check
-#endif
-#ifdef seekdir
-  #undef seekdir
-#endif
-#ifdef open
-  #undef open
-#endif
-#ifdef readdir
-  #undef readdir
-#endif
-#ifdef bind
-  #undef bind
-#endif
-#ifdef access
-  #undef access
-#endif
-#ifdef stat
-  #undef stat
-#endif
-
-#ifdef bool
-  /* Leave if macro is from C99 stdbool.h */
-  #ifndef __bool_true_false_are_defined
-    #undef bool
-  #endif
-#endif
-
-
-
-
-#define SWIG_exception_fail(code, msg) do { SWIG_Error(code, msg); SWIG_fail; } while(0) 
-
-#define SWIG_contract_assert(expr, msg) if (!(expr)) { SWIG_Error(SWIG_RuntimeError, msg); SWIG_fail; } else 
-
-
-
-  #define SWIG_exception(code, msg) do { SWIG_Error(code, msg); SWIG_fail;; } while(0) 
-
-
-/* -------- TYPES TABLE (BEGIN) -------- */
-
-#define SWIGTYPE_p_OSRCoordinateTransformationShadow swig_types[0]
-#define SWIGTYPE_p_OSRSpatialReferenceShadow swig_types[1]
-#define SWIGTYPE_p_char swig_types[2]
-#define SWIGTYPE_p_double swig_types[3]
-#define SWIGTYPE_p_int swig_types[4]
-#define SWIGTYPE_p_long swig_types[5]
-#define SWIGTYPE_p_p_char swig_types[6]
-#define SWIGTYPE_p_p_double swig_types[7]
-static swig_type_info *swig_types[9];
-static swig_module_info swig_module = {swig_types, 8, 0, 0, 0, 0};
-#define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)
-#define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)
-
-/* -------- TYPES TABLE (END) -------- */
-
-#define SWIG_init    boot_Geo__OSR
-
-#define SWIG_name   "Geo::OSRc::boot_Geo__OSR"
-#define SWIG_prefix "Geo::OSRc::"
-
-#define SWIGVERSION 0x020012 
-#define SWIG_VERSION SWIGVERSION
-
-
-#define SWIG_as_voidptr(a) const_cast< void * >(static_cast< const void * >(a)) 
-#define SWIG_as_voidptrptr(a) ((void)SWIG_as_voidptr(*a),reinterpret_cast< void** >(a)) 
-
-
-#include <stdexcept>
-
-
-#ifdef __cplusplus
-extern "C"
-#endif
-#ifndef PERL_OBJECT
-#ifndef MULTIPLICITY
-SWIGEXPORT void SWIG_init (CV* cv);
-#else
-SWIGEXPORT void SWIG_init (pTHXo_ CV* cv);
-#endif
-#else
-SWIGEXPORT void SWIG_init (CV *cv, CPerlObj *);
-#endif
-
-
-SWIGINTERNINLINE SV *
-SWIG_FromCharPtrAndSize(const char* carray, size_t size)
-{
-  SV *obj = sv_newmortal();
-  if (carray) {
-    sv_setpvn(obj, carray, size);
-  } else {
-    sv_setsv(obj, &PL_sv_undef);
-  }
-  return obj;
-}
-
-
-SWIGINTERNINLINE SV * 
-SWIG_FromCharPtr(const char *cptr)
-{ 
-  return SWIG_FromCharPtrAndSize(cptr, (cptr ? strlen(cptr) : 0));
-}
-
-
-SWIGINTERNINLINE SV *
-SWIG_From_double  SWIG_PERL_DECL_ARGS_1(double value)
-{
-  return sv_2mortal(newSVnv(value));
-}
-
-
-typedef char retStringAndCPLFree;
-
-
-#include <iostream>
-using namespace std;
-
-#include "cpl_string.h"
-#include "cpl_conv.h"
-
-#include "ogr_srs_api.h"
-
-#ifdef DEBUG
-typedef struct OGRSpatialReferenceHS OSRSpatialReferenceShadow;
-typedef struct OGRCoordinateTransformationHS OSRCoordinateTransformationShadow;
-typedef struct OGRCoordinateTransformationHS OGRCoordinateTransformationShadow;
-#else
-typedef void OSRSpatialReferenceShadow;
-typedef void OSRCoordinateTransformationShadow;
-#endif
-
-
-void VeryQuiteErrorHandler(CPLErr eclass, int code, const char *msg ) {
-  /* If the error class is CE_Fatal, we want to have a message issued
-     because the CPL support code does an abort() before any exception
-     can be generated */
-  if (eclass == CE_Fatal ) {
-    CPLDefaultErrorHandler(eclass, code, msg );
-  }
-}
-
-
-void UseExceptions() {
-  CPLSetErrorHandler( (CPLErrorHandler) VeryQuiteErrorHandler );
-}
-
-void DontUseExceptions() {
-  CPLSetErrorHandler( CPLDefaultErrorHandler );
-}
-
-
-OGRErr GetWellKnownGeogCSAsWKT( const char *name, char **argout ) {
-  OGRSpatialReferenceH srs = OSRNewSpatialReference("");
-  OGRErr rcode = OSRSetWellKnownGeogCS( srs, name );
-  if( rcode == OGRERR_NONE )
-      rcode = OSRExportToWkt ( srs, argout );  
-  OSRDestroySpatialReference( srs );
-  return rcode;
-}
-
-
-SWIGINTERN swig_type_info*
-SWIG_pchar_descriptor(void)
-{
-  static int init = 0;
-  static swig_type_info* info = 0;
-  if (!init) {
-    info = SWIG_TypeQuery("_p_char");
-    init = 1;
-  }
-  return info;
-}
-
-
-SWIGINTERN int
-SWIG_AsCharPtrAndSize(SV *obj, char** cptr, size_t* psize, int *alloc)
-{
-  if (SvMAGICAL(obj)) {
-     SV *tmp = sv_newmortal();
-     SvSetSV(tmp, obj);
-     obj = tmp;
-  }
-  if (SvPOK(obj)) {
-    STRLEN len = 0;
-    char *cstr = SvPV(obj, len); 
-    size_t size = len + 1;
-    if (cptr)  {
-      if (alloc) {
-	if (*alloc == SWIG_NEWOBJ) {
-	  *cptr = reinterpret_cast< char* >(memcpy((new char[size]), cstr, sizeof(char)*(size)));
-	} else {
-	  *cptr = cstr;
-	  *alloc = SWIG_OLDOBJ;
-	}
-      }
-    }
-    if (psize) *psize = size;
-    return SWIG_OK;
-  } else {
-    swig_type_info* pchar_descriptor = SWIG_pchar_descriptor();
-    if (pchar_descriptor) {
-      char* vptr = 0; 
-      if (SWIG_ConvertPtr(obj, (void**)&vptr, pchar_descriptor, 0) == SWIG_OK) {
-	if (cptr) *cptr = vptr;
-	if (psize) *psize = vptr ? (strlen(vptr) + 1) : 0;
-	if (alloc) *alloc = SWIG_OLDOBJ;
-	return SWIG_OK;
-      }
-    }
-  }
-  return SWIG_TypeError;
-}
-
-
-
-
-
-
-#include "ogr_core.h"
-static char const *
-OGRErrMessages( int rc ) {
-  switch( rc ) {
-  case OGRERR_NONE:
-    return "OGR Error: None";
-  case OGRERR_NOT_ENOUGH_DATA:
-    return "OGR Error: Not enough data to deserialize";
-  case OGRERR_NOT_ENOUGH_MEMORY:
-    return "OGR Error: Not enough memory";
-  case OGRERR_UNSUPPORTED_GEOMETRY_TYPE:
-    return "OGR Error: Unsupported geometry type";
-  case OGRERR_UNSUPPORTED_OPERATION:
-    return "OGR Error: Unsupported operation";
-  case OGRERR_CORRUPT_DATA:
-    return "OGR Error: Corrupt data";
-  case OGRERR_FAILURE:
-    return "OGR Error: General Error";
-  case OGRERR_UNSUPPORTED_SRS:
-    return "OGR Error: Unsupported SRS";
-  case OGRERR_INVALID_HANDLE:
-    return "OGR Error: Invalid handle";
-  case OGRERR_NON_EXISTING_FEATURE:
-    return "OGR Error: Non existing feature";
-  default:
-    return "OGR Error: Unknown";
-  }
-}
-
-
-OGRErr GetUserInputAsWKT( const char *name, char **argout ) {
-  OGRSpatialReferenceH srs = OSRNewSpatialReference("");
-  OGRErr rcode = OSRSetFromUserInput( srs, name );
-  if( rcode == OGRERR_NONE )
-      rcode = OSRExportToWkt ( srs, argout );  
-  OSRDestroySpatialReference( srs );
-  return rcode;
-}
-
-SWIGINTERN OSRSpatialReferenceShadow *new_OSRSpatialReferenceShadow(char const *wkt=""){
-    return (OSRSpatialReferenceShadow*) OSRNewSpatialReference(wkt);
-  }
-SWIGINTERN void delete_OSRSpatialReferenceShadow(OSRSpatialReferenceShadow *self){
-    if (OSRDereference( self ) == 0 ) {
-      OSRDestroySpatialReference( self );
-    }
-  }
-SWIGINTERN int OSRSpatialReferenceShadow_IsSame(OSRSpatialReferenceShadow *self,OSRSpatialReferenceShadow *rhs){
-    return OSRIsSame( self, rhs );
-  }
-
-SWIGINTERNINLINE SV *
-SWIG_From_long  SWIG_PERL_DECL_ARGS_1(long value)
-{
-  SV *sv;
-  if (value >= IV_MIN && value <= IV_MAX)
-    sv = newSViv(value);
-  else
-    sv = newSVpvf("%ld", value);
-  return sv_2mortal(sv);
-}
-
-
-SWIGINTERNINLINE SV *
-SWIG_From_int  SWIG_PERL_DECL_ARGS_1(int value)
-{    
-  return SWIG_From_long  SWIG_PERL_CALL_ARGS_1(value);
-}
-
-SWIGINTERN int OSRSpatialReferenceShadow_IsSameGeogCS(OSRSpatialReferenceShadow *self,OSRSpatialReferenceShadow *rhs){
-    return OSRIsSameGeogCS( self, rhs );
-  }
-SWIGINTERN int OSRSpatialReferenceShadow_IsSameVertCS(OSRSpatialReferenceShadow *self,OSRSpatialReferenceShadow *rhs){
-    return OSRIsSameVertCS( self, rhs );
-  }
-SWIGINTERN int OSRSpatialReferenceShadow_IsGeographic(OSRSpatialReferenceShadow *self){
-    return OSRIsGeographic(self);
-  }
-SWIGINTERN int OSRSpatialReferenceShadow_IsProjected(OSRSpatialReferenceShadow *self){
-    return OSRIsProjected(self);
-  }
-SWIGINTERN int OSRSpatialReferenceShadow_IsCompound(OSRSpatialReferenceShadow *self){
-    return OSRIsCompound(self);
-  }
-SWIGINTERN int OSRSpatialReferenceShadow_IsGeocentric(OSRSpatialReferenceShadow *self){
-    return OSRIsGeocentric(self);
-  }
-SWIGINTERN int OSRSpatialReferenceShadow_IsLocal(OSRSpatialReferenceShadow *self){
-    return OSRIsLocal(self);
-  }
-SWIGINTERN int OSRSpatialReferenceShadow_IsVertical(OSRSpatialReferenceShadow *self){
-    return OSRIsVertical(self);
-  }
-SWIGINTERN int OSRSpatialReferenceShadow_EPSGTreatsAsLatLong(OSRSpatialReferenceShadow *self){
-    return OSREPSGTreatsAsLatLong(self);
-  }
-SWIGINTERN int OSRSpatialReferenceShadow_EPSGTreatsAsNorthingEasting(OSRSpatialReferenceShadow *self){
-    return OSREPSGTreatsAsNorthingEasting(self);
-  }
-
-#include <limits.h>
-#if !defined(SWIG_NO_LLONG_MAX)
-# if !defined(LLONG_MAX) && defined(__GNUC__) && defined (__LONG_LONG_MAX__)
-#   define LLONG_MAX __LONG_LONG_MAX__
-#   define LLONG_MIN (-LLONG_MAX - 1LL)
-#   define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL)
-# endif
-#endif
-
-
-SWIGINTERN int
-SWIG_AsVal_double SWIG_PERL_DECL_ARGS_2(SV *obj, double *val)
-{
-  if (SvNIOK(obj)) {
-    if (val) *val = SvNV(obj);
-    return SWIG_OK;
-  } else if (SvIOK(obj)) {
-    if (val) *val = (double) SvIV(obj);
-    return SWIG_AddCast(SWIG_OK);
-  } else {
-    const char *nptr = SvPV_nolen(obj);
-    if (nptr) {
-      char *endptr;
-      double v;
-      errno = 0;
-      v = strtod(nptr, &endptr);
-      if (errno == ERANGE) {
-	errno = 0;
-	return SWIG_OverflowError;
-      } else {
-	if (*endptr == '\0') {
-	  if (val) *val = v;
-	  return SWIG_Str2NumCast(SWIG_OK);
-	}
-      }
-    }
-  }
-  return SWIG_TypeError;
-}
-
-
-#include <float.h>
-
-
-#include <math.h>
-
-
-SWIGINTERNINLINE int
-SWIG_CanCastAsInteger(double *d, double min, double max) {
-  double x = *d;
-  if ((min <= x && x <= max)) {
-   double fx = floor(x);
-   double cx = ceil(x);
-   double rd =  ((x - fx) < 0.5) ? fx : cx; /* simple rint */
-   if ((errno == EDOM) || (errno == ERANGE)) {
-     errno = 0;
-   } else {
-     double summ, reps, diff;
-     if (rd < x) {
-       diff = x - rd;
-     } else if (rd > x) {
-       diff = rd - x;
-     } else {
-       return 1;
-     }
-     summ = rd + x;
-     reps = diff/summ;
-     if (reps < 8*DBL_EPSILON) {
-       *d = rd;
-       return 1;
-     }
-   }
-  }
-  return 0;
-}
-
-
-SWIGINTERN int
-SWIG_AsVal_long SWIG_PERL_DECL_ARGS_2(SV *obj, long* val)
-{
-  if (SvUOK(obj)) {
-    UV v = SvUV(obj);
-    if (v <= LONG_MAX) {
-      if (val) *val = v;
-      return SWIG_OK;
-    }
-    return SWIG_OverflowError;
-  } else if (SvIOK(obj)) {
-    IV v = SvIV(obj);
-    if (v >= LONG_MIN && v <= LONG_MAX) {
-      if(val) *val = v;
-      return SWIG_OK;
-    }
-    return SWIG_OverflowError;
-  } else {
-    int dispatch = 0;
-    const char *nptr = SvPV_nolen(obj);
-    if (nptr) {
-      char *endptr;
-      long v;
-      errno = 0;
-      v = strtol(nptr, &endptr,0);
-      if (errno == ERANGE) {
-	errno = 0;
-	return SWIG_OverflowError;
-      } else {
-	if (*endptr == '\0') {
-	  if (val) *val = v;
-	  return SWIG_Str2NumCast(SWIG_OK);
-	}
-      }
-    }
-    if (!dispatch) {
-      double d;
-      int res = SWIG_AddCast(SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(obj,&d));
-      if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LONG_MIN, LONG_MAX)) {
-	if (val) *val = (long)(d);
-	return res;
-      }
-    }
-  }
-  return SWIG_TypeError;
-}
-
-
-SWIGINTERN int
-SWIG_AsVal_int SWIG_PERL_DECL_ARGS_2(SV * obj, int *val)
-{
-  long v;
-  int res = SWIG_AsVal_long SWIG_PERL_CALL_ARGS_2(obj, &v);
-  if (SWIG_IsOK(res)) {
-    if ((v < INT_MIN || v > INT_MAX)) {
-      return SWIG_OverflowError;
-    } else {
-      if (val) *val = static_cast< int >(v);
-    }
-  }  
-  return res;
-}
-
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetAuthority(OSRSpatialReferenceShadow *self,char const *pszTargetKey,char const *pszAuthority,int nCode){
-    return OSRSetAuthority( self, pszTargetKey, pszAuthority, nCode );
-  }
-SWIGINTERN char const *OSRSpatialReferenceShadow_GetAttrValue(OSRSpatialReferenceShadow *self,char const *name,int child=0){
-    return OSRGetAttrValue( self, name, child );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetAttrValue(OSRSpatialReferenceShadow *self,char const *name,char const *value){
-    return OSRSetAttrValue( self, name, value ); 
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetAngularUnits(OSRSpatialReferenceShadow *self,char const *name,double to_radians){
-    return OSRSetAngularUnits( self, name, to_radians );
-  }
-SWIGINTERN double OSRSpatialReferenceShadow_GetAngularUnits(OSRSpatialReferenceShadow *self){
-    // Return code ignored.
-    return OSRGetAngularUnits( self, 0 );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetTargetLinearUnits(OSRSpatialReferenceShadow *self,char const *target,char const *name,double to_meters){
-    return OSRSetTargetLinearUnits( self, target, name, to_meters );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLinearUnits(OSRSpatialReferenceShadow *self,char const *name,double to_meters){
-    return OSRSetLinearUnits( self, name, to_meters );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLinearUnitsAndUpdateParameters(OSRSpatialReferenceShadow *self,char const *name,double to_meters){
-    return OSRSetLinearUnitsAndUpdateParameters( self, name, to_meters );
-  }
-SWIGINTERN double OSRSpatialReferenceShadow_GetLinearUnits(OSRSpatialReferenceShadow *self){
-    // Return code ignored.
-    return OSRGetLinearUnits( self, 0 );
-  }
-SWIGINTERN char const *OSRSpatialReferenceShadow_GetLinearUnitsName(OSRSpatialReferenceShadow *self){
-    const char *name = 0;
-    if ( OSRIsProjected( self ) ) {
-      name = OSRGetAttrValue( self, "PROJCS|UNIT", 0 );
-    }
-    else if ( OSRIsLocal( self ) ) {
-      name = OSRGetAttrValue( self, "LOCAL_CS|UNIT", 0 );
-    }
-
-    if (name != 0) 
-      return name;
-
-    return "Meter";
-  }
-SWIGINTERN char const *OSRSpatialReferenceShadow_GetAuthorityCode(OSRSpatialReferenceShadow *self,char const *target_key){
-    return OSRGetAuthorityCode( self, target_key );
-  }
-SWIGINTERN char const *OSRSpatialReferenceShadow_GetAuthorityName(OSRSpatialReferenceShadow *self,char const *target_key){
-    return OSRGetAuthorityName( self, target_key );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetUTM(OSRSpatialReferenceShadow *self,int zone,int north=1){
-    return OSRSetUTM( self, zone, north );
-  }
-SWIGINTERN int OSRSpatialReferenceShadow_GetUTMZone(OSRSpatialReferenceShadow *self){
-    // Note: we will return south zones as negative since it is 
-    // hard to return two values as the C API does. 
-    int bNorth = FALSE;
-    int nZone = OSRGetUTMZone( self, &bNorth );
-    if( !bNorth )
-        nZone = -1 * ABS(nZone);
-    return nZone;
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetStatePlane(OSRSpatialReferenceShadow *self,int zone,int is_nad83=1,char const *unitsname="",double units=0.0){
-    return OSRSetStatePlaneWithUnits( self, zone, is_nad83, unitsname, units );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_AutoIdentifyEPSG(OSRSpatialReferenceShadow *self){
-    return OSRAutoIdentifyEPSG( self );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetProjection(OSRSpatialReferenceShadow *self,char const *arg){
-    return OSRSetProjection( self, arg );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetProjParm(OSRSpatialReferenceShadow *self,char const *name,double val){
-    return OSRSetProjParm( self, name, val ); 
-  }
-SWIGINTERN double OSRSpatialReferenceShadow_GetProjParm(OSRSpatialReferenceShadow *self,char const *name,double default_val=0.0){
-    // Return code ignored.
-    return OSRGetProjParm( self, name, default_val, 0 );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetNormProjParm(OSRSpatialReferenceShadow *self,char const *name,double val){
-    return OSRSetNormProjParm( self, name, val );
-  }
-SWIGINTERN double OSRSpatialReferenceShadow_GetNormProjParm(OSRSpatialReferenceShadow *self,char const *name,double default_val=0.0){
-    // Return code ignored.
-    return OSRGetNormProjParm( self, name, default_val, 0 );
-  }
-SWIGINTERN double OSRSpatialReferenceShadow_GetSemiMajor(OSRSpatialReferenceShadow *self){
-    // Return code ignored.
-    return OSRGetSemiMajor( self, 0 );
-  }
-SWIGINTERN double OSRSpatialReferenceShadow_GetSemiMinor(OSRSpatialReferenceShadow *self){
-    // Return code ignored.
-    return OSRGetSemiMinor( self, 0 );
-  }
-SWIGINTERN double OSRSpatialReferenceShadow_GetInvFlattening(OSRSpatialReferenceShadow *self){
-    // Return code ignored.
-    return OSRGetInvFlattening( self, 0 );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetACEA(OSRSpatialReferenceShadow *self,double stdp1,double stdp2,double clat,double clong,double fe,double fn){
-    return OSRSetACEA( self, stdp1, stdp2, clat, clong, 
-                       fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetAE(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetAE( self, clat, clong, 
-                     fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetBonne(OSRSpatialReferenceShadow *self,double stdp,double cm,double fe,double fn){
-    return OSRSetBonne( self, stdp, cm, fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetCEA(OSRSpatialReferenceShadow *self,double stdp1,double cm,double fe,double fn){
-    return OSRSetCEA( self, stdp1, cm, 
-                      fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetCS(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetCS( self, clat, clong, 
-                     fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetEC(OSRSpatialReferenceShadow *self,double stdp1,double stdp2,double clat,double clong,double fe,double fn){
-    return OSRSetEC( self, stdp1, stdp2, clat, clong, 
-                     fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetEckertIV(OSRSpatialReferenceShadow *self,double cm,double fe,double fn){
-    return OSRSetEckertIV( self, cm, fe, fn);
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetEckertVI(OSRSpatialReferenceShadow *self,double cm,double fe,double fn){
-    return OSRSetEckertVI( self, cm, fe, fn);
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetEquirectangular(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetEquirectangular( self, clat, clong, 
-                                  fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetEquirectangular2(OSRSpatialReferenceShadow *self,double clat,double clong,double pseudostdparallellat,double fe,double fn){
-    return OSRSetEquirectangular2( self, clat, clong,
-                                   pseudostdparallellat,
-                                   fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGaussSchreiberTMercator(OSRSpatialReferenceShadow *self,double clat,double clong,double sc,double fe,double fn){
-    return OSRSetGaussSchreiberTMercator( self, clat, clong, sc, fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGS(OSRSpatialReferenceShadow *self,double cm,double fe,double fn){
-    return OSRSetGS( self, cm, fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGH(OSRSpatialReferenceShadow *self,double cm,double fe,double fn){
-    return OSRSetGH( self, cm, fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetIGH(OSRSpatialReferenceShadow *self){
-    return OSRSetIGH( self );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGEOS(OSRSpatialReferenceShadow *self,double cm,double satelliteheight,double fe,double fn){
-    return OSRSetGEOS( self, cm, satelliteheight,
-                       fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGnomonic(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetGnomonic( self, clat, clong, 
-                           fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetHOM(OSRSpatialReferenceShadow *self,double clat,double clong,double azimuth,double recttoskew,double scale,double fe,double fn){
-    return OSRSetHOM( self, clat, clong, azimuth, recttoskew,
-                      scale, fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetHOM2PNO(OSRSpatialReferenceShadow *self,double clat,double dfLat1,double dfLong1,double dfLat2,double dfLong2,double scale,double fe,double fn){
-    return OSRSetHOM2PNO( self, clat, dfLat1, dfLong1, dfLat2, dfLong2, 
-                          scale, fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetKrovak(OSRSpatialReferenceShadow *self,double clat,double clong,double azimuth,double pseudostdparallellat,double scale,double fe,double fn){
-    return OSRSetKrovak( self, clat, clong, 
-                         azimuth, pseudostdparallellat, 
-                         scale, fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLAEA(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetLAEA( self, clat, clong, 
-                       fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLCC(OSRSpatialReferenceShadow *self,double stdp1,double stdp2,double clat,double clong,double fe,double fn){
-    return OSRSetLCC( self, stdp1, stdp2, clat, clong, 
-                      fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLCC1SP(OSRSpatialReferenceShadow *self,double clat,double clong,double scale,double fe,double fn){
-    return OSRSetLCC1SP( self, clat, clong, scale, 
-                         fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLCCB(OSRSpatialReferenceShadow *self,double stdp1,double stdp2,double clat,double clong,double fe,double fn){
-    return OSRSetLCCB( self, stdp1, stdp2, clat, clong, 
-                       fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetMC(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetMC( self, clat, clong,    
-                     fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetMercator(OSRSpatialReferenceShadow *self,double clat,double clong,double scale,double fe,double fn){
-    return OSRSetMercator( self, clat, clong, 
-                           scale, fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetMollweide(OSRSpatialReferenceShadow *self,double cm,double fe,double fn){
-    return OSRSetMollweide( self, cm, 
-                            fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetNZMG(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetNZMG( self, clat, clong, 
-                       fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetOS(OSRSpatialReferenceShadow *self,double dfOriginLat,double dfCMeridian,double scale,double fe,double fn){
-    return OSRSetOS( self, dfOriginLat, dfCMeridian, scale, 
-                     fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetOrthographic(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetOrthographic( self, clat, clong, 
-                               fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetPolyconic(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetPolyconic( self, clat, clong, 
-                            fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetPS(OSRSpatialReferenceShadow *self,double clat,double clong,double scale,double fe,double fn){
-    return OSRSetPS( self, clat, clong, scale,
-                     fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetRobinson(OSRSpatialReferenceShadow *self,double clong,double fe,double fn){
-    return OSRSetRobinson( self, clong, fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetSinusoidal(OSRSpatialReferenceShadow *self,double clong,double fe,double fn){
-    return OSRSetSinusoidal( self, clong, fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetStereographic(OSRSpatialReferenceShadow *self,double clat,double clong,double scale,double fe,double fn){
-    return OSRSetStereographic( self, clat, clong, scale, 
-                                fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetSOC(OSRSpatialReferenceShadow *self,double latitudeoforigin,double cm,double fe,double fn){
-    return OSRSetSOC( self, latitudeoforigin, cm,
-	              fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetTM(OSRSpatialReferenceShadow *self,double clat,double clong,double scale,double fe,double fn){
-    return OSRSetTM( self, clat, clong, scale, 
-                     fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetTMVariant(OSRSpatialReferenceShadow *self,char const *pszVariantName,double clat,double clong,double scale,double fe,double fn){
-    return OSRSetTMVariant( self, pszVariantName, clat, clong,  
-                            scale, fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetTMG(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetTMG( self, clat, clong, 
-                      fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetTMSO(OSRSpatialReferenceShadow *self,double clat,double clong,double scale,double fe,double fn){
-    return OSRSetTMSO( self, clat, clong, scale, 
-                       fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetVDG(OSRSpatialReferenceShadow *self,double clong,double fe,double fn){
-    return OSRSetVDG( self, clong, fe, fn );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetWellKnownGeogCS(OSRSpatialReferenceShadow *self,char const *name){
-    return OSRSetWellKnownGeogCS( self, name );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetFromUserInput(OSRSpatialReferenceShadow *self,char const *name){
-    return OSRSetFromUserInput( self, name );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_CopyGeogCSFrom(OSRSpatialReferenceShadow *self,OSRSpatialReferenceShadow *rhs){
-    return OSRCopyGeogCSFrom( self, rhs );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetTOWGS84(OSRSpatialReferenceShadow *self,double p1,double p2,double p3,double p4=0.0,double p5=0.0,double p6=0.0,double p7=0.0){
-
-    return OSRSetTOWGS84( self, p1, p2, p3, p4, p5, p6, p7 );
-  }
-
-static SV *
-CreateArrayFromDoubleArray( double *first, unsigned int size ) {
-  AV *av = (AV*)sv_2mortal((SV*)newAV());
-  for( unsigned int i=0; i<size; i++ ) {
-    av_store(av,i,newSVnv(*first));
-    ++first;
-  }
-  return sv_2mortal(newRV((SV*)av));
-}
-
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_GetTOWGS84(OSRSpatialReferenceShadow *self,double argout[7]){
-    return OSRGetTOWGS84( self, argout, 7 );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLocalCS(OSRSpatialReferenceShadow *self,char const *pszName){
-    return OSRSetLocalCS( self, pszName );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGeogCS(OSRSpatialReferenceShadow *self,char const *pszGeogName,char const *pszDatumName,char const *pszEllipsoidName,double dfSemiMajor,double dfInvFlattening,char const *pszPMName="Greenwich",double dfPMOffset=0.0,char const *pszUnits="degree",double dfConvertToRadians=0.0174532925199433){
-    return OSRSetGeogCS( self, pszGeogName, pszDatumName, pszEllipsoidName,
-                         dfSemiMajor, dfInvFlattening,
-                         pszPMName, dfPMOffset, pszUnits, dfConvertToRadians );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetProjCS(OSRSpatialReferenceShadow *self,char const *name="unnamed"){
-    return OSRSetProjCS( self, name );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGeocCS(OSRSpatialReferenceShadow *self,char const *name="unnamed"){
-    return OSRSetGeocCS( self, name );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetVertCS(OSRSpatialReferenceShadow *self,char const *VertCSName="unnamed",char const *VertDatumName="unnamed",int VertDatumType=0){
-    return OSRSetVertCS( self, VertCSName, VertDatumName, VertDatumType );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetCompoundCS(OSRSpatialReferenceShadow *self,char const *name,OSRSpatialReferenceShadow *horizcs,OSRSpatialReferenceShadow *vertcs){
-    return OSRSetCompoundCS( self, name, horizcs, vertcs );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_ImportFromWkt(OSRSpatialReferenceShadow *self,char **ppszInput){
-    return OSRImportFromWkt( self, ppszInput );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_ImportFromProj4(OSRSpatialReferenceShadow *self,char *ppszInput){
-    return OSRImportFromProj4( self, ppszInput );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_ImportFromUrl(OSRSpatialReferenceShadow *self,char *url){
-    return OSRImportFromUrl( self, url );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_ImportFromESRI(OSRSpatialReferenceShadow *self,char **ppszInput){
-    return OSRImportFromESRI( self, ppszInput );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_ImportFromEPSG(OSRSpatialReferenceShadow *self,int arg){
-    return OSRImportFromEPSG(self, arg);
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_ImportFromEPSGA(OSRSpatialReferenceShadow *self,int arg){
-    return OSRImportFromEPSGA(self, arg);
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_ImportFromPCI(OSRSpatialReferenceShadow *self,char const *proj,char const *units="METRE",double argin[17]=0){
-    return OSRImportFromPCI( self, proj, units, argin );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_ImportFromUSGS(OSRSpatialReferenceShadow *self,long proj_code,long zone=0,double argin[15]=0,long datum_code=0){
-    return OSRImportFromUSGS( self, proj_code, zone, argin, datum_code );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_ImportFromXML(OSRSpatialReferenceShadow *self,char const *xmlString){
-    return OSRImportFromXML( self, xmlString );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_ImportFromERM(OSRSpatialReferenceShadow *self,char const *proj,char const *datum,char const *units){
-    return OSRImportFromERM( self, proj, datum, units );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_ImportFromMICoordSys(OSRSpatialReferenceShadow *self,char const *pszCoordSys){
-    return OSRImportFromMICoordSys( self, pszCoordSys );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_ImportFromOzi(OSRSpatialReferenceShadow *self,char const *const *papszLines){
-    return OSRImportFromOzi( self, papszLines );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_ExportToWkt(OSRSpatialReferenceShadow *self,char **argout){
-    return OSRExportToWkt( self, argout );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_ExportToPrettyWkt(OSRSpatialReferenceShadow *self,char **argout,int simplify=0){
-    return OSRExportToPrettyWkt( self, argout, simplify );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_ExportToProj4(OSRSpatialReferenceShadow *self,char **argout){
-    return OSRExportToProj4( self, argout );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_ExportToPCI(OSRSpatialReferenceShadow *self,char **proj,char **units,double *parms[17]){
-    return OSRExportToPCI( self, proj, units, parms );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_ExportToUSGS(OSRSpatialReferenceShadow *self,long *code,long *zone,double *parms[15],long *datum){
-    return OSRExportToUSGS( self, code, zone, parms, datum );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_ExportToXML(OSRSpatialReferenceShadow *self,char **argout,char const *dialect=""){
-    return OSRExportToXML( self, argout, dialect );
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_ExportToMICoordSys(OSRSpatialReferenceShadow *self,char **argout){
-    return OSRExportToMICoordSys( self, argout );
-  }
-SWIGINTERN OSRSpatialReferenceShadow *OSRSpatialReferenceShadow_CloneGeogCS(OSRSpatialReferenceShadow *self){
-    return (OSRSpatialReferenceShadow*) OSRCloneGeogCS(self);
-  }
-SWIGINTERN OSRSpatialReferenceShadow *OSRSpatialReferenceShadow_Clone(OSRSpatialReferenceShadow *self){
-    return (OSRSpatialReferenceShadow*) OSRClone(self);
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_Validate(OSRSpatialReferenceShadow *self){
-    return OSRValidate(self);
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_StripCTParms(OSRSpatialReferenceShadow *self){
-    return OSRStripCTParms(self);
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_FixupOrdering(OSRSpatialReferenceShadow *self){
-    return OSRFixupOrdering(self);
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_Fixup(OSRSpatialReferenceShadow *self){
-    return OSRFixup(self);
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_MorphToESRI(OSRSpatialReferenceShadow *self){
-    return OSRMorphToESRI(self);
-  }
-SWIGINTERN OGRErr OSRSpatialReferenceShadow_MorphFromESRI(OSRSpatialReferenceShadow *self){
-    return OSRMorphFromESRI(self);
-  }
-SWIGINTERN OSRCoordinateTransformationShadow *new_OSRCoordinateTransformationShadow(OSRSpatialReferenceShadow *src,OSRSpatialReferenceShadow *dst){
-    OSRCoordinateTransformationShadow *obj = (OSRCoordinateTransformationShadow*) OCTNewCoordinateTransformation( src, dst );
-    return obj;
-  }
-SWIGINTERN void delete_OSRCoordinateTransformationShadow(OSRCoordinateTransformationShadow *self){
-    OCTDestroyCoordinateTransformation( self );
-  }
-SWIGINTERN void OSRCoordinateTransformationShadow_TransformPoint__SWIG_0(OSRCoordinateTransformationShadow *self,double inout[3]){
-    if (self == NULL)
-        return;
-    OCTTransform( self, 1, &inout[0], &inout[1], &inout[2] );
-  }
-SWIGINTERN void OSRCoordinateTransformationShadow_TransformPoint__SWIG_1(OSRCoordinateTransformationShadow *self,double argout[3],double x,double y,double z=0.0){
-    if (self == NULL)
-        return;
-    argout[0] = x;
-    argout[1] = y;
-    argout[2] = z;
-    OCTTransform( self, 1, &argout[0], &argout[1], &argout[2] );
-  }
-SWIGINTERN void OSRCoordinateTransformationShadow_TransformPoints(OSRCoordinateTransformationShadow *self,int nCount,double *x,double *y,double *z){
-    if (self == NULL)
-        return;
-    OCTTransform( self, nCount, x, y, z );
-  }
-
-  OSRCoordinateTransformationShadow *CreateCoordinateTransformation( OSRSpatialReferenceShadow *src, OSRSpatialReferenceShadow *dst ) {
-    OSRCoordinateTransformationShadow *obj = (OSRCoordinateTransformationShadow*) OCTNewCoordinateTransformation( src, dst );
-    return obj;
-}
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef PERL_OBJECT
-#define MAGIC_CLASS _wrap_Geo__OSR_var::
-class _wrap_Geo__OSR_var : public CPerlObj {
-public:
-#else
-#define MAGIC_CLASS
-#endif
-SWIGCLASS_STATIC int swig_magic_readonly(pTHX_ SV *SWIGUNUSEDPARM(sv), MAGIC *SWIGUNUSEDPARM(mg)) {
-    MAGIC_PPERL
-    croak("Value is read-only.");
-    return 0;
-}
-
-
-#ifdef PERL_OBJECT
-};
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-XS(_wrap_UseExceptions) {
-  {
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 0)) {
-      SWIG_croak("Usage: UseExceptions();");
-    }
-    UseExceptions();
-    ST(argvi) = sv_newmortal();
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_DontUseExceptions) {
-  {
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 0)) {
-      SWIG_croak("Usage: DontUseExceptions();");
-    }
-    DontUseExceptions();
-    ST(argvi) = sv_newmortal();
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GetWellKnownGeogCSAsWKT) {
-  {
-    char *arg1 = (char *) 0 ;
-    char **arg2 = (char **) 0 ;
-    char *argout2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (char **argout2) */
-      arg2 = &argout2;
-    }
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GetWellKnownGeogCSAsWKT(name);");
-    }
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(0));
-      arg1 = SvPV_nolen(ST(0));
-    }
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)GetWellKnownGeogCSAsWKT((char const *)arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    {
-      /* %typemap(argout) (char **argout) */
-      ST(argvi) = sv_newmortal();
-      if ( arg2 ) {
-        sv_setpv(ST(argvi), *arg2);
-        SvUTF8_on(ST(argvi)); /* expecting UTF-8 from GDAL */
-      }
-      argvi++;
-    }
-    {
-      /* %typemap(freearg) (char **argout) */
-      if ( *arg2 )
-      CPLFree( *arg2 );
-    }
-    XSRETURN(argvi);
-  fail:
-    {
-      /* %typemap(freearg) (char **argout) */
-      if ( *arg2 )
-      CPLFree( *arg2 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GetUserInputAsWKT) {
-  {
-    char *arg1 = (char *) 0 ;
-    char **arg2 = (char **) 0 ;
-    char *argout2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (char **argout2) */
-      arg2 = &argout2;
-    }
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GetUserInputAsWKT(name);");
-    }
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(0));
-      arg1 = SvPV_nolen(ST(0));
-    }
-    {
-      if (!arg1) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)GetUserInputAsWKT((char const *)arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    {
-      /* %typemap(argout) (char **argout) */
-      ST(argvi) = sv_newmortal();
-      if ( arg2 ) {
-        sv_setpv(ST(argvi), *arg2);
-        SvUTF8_on(ST(argvi)); /* expecting UTF-8 from GDAL */
-      }
-      argvi++;
-    }
-    {
-      /* %typemap(freearg) (char **argout) */
-      if ( *arg2 )
-      CPLFree( *arg2 );
-    }
-    XSRETURN(argvi);
-  fail:
-    {
-      /* %typemap(freearg) (char **argout) */
-      if ( *arg2 )
-      CPLFree( *arg2 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GetProjectionMethods) {
-  {
-    int argvi = 0;
-    char **result = 0 ;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 0)) {
-      SWIG_croak("Usage: GetProjectionMethods();");
-    }
-    {
-      CPLErrorReset();
-      result = (char **)OPTGetProjectionMethods();
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) char **CSL */
-      if (GIMME_V == G_ARRAY) {
-        if (result) {
-          int i;
-          for (i = 0; result[i]; i++) {
-            if (argvi > items-1) EXTEND(SP, 1);
-            SV *sv = newSVpv(result[i], 0);
-            SvUTF8_on(sv); /* expecting GDAL to give us UTF-8 */
-            ST(argvi++) = sv_2mortal(sv);
-          }
-          CSLDestroy(result);
-        }
-      } else {
-        AV *av = (AV*)sv_2mortal((SV*)newAV());
-        if (result) {
-          int i;
-          for (i = 0; result[i]; i++) {
-            SV *sv = newSVpv(result[i], 0);
-            SvUTF8_on(sv); /* expecting GDAL to give us UTF-8 */
-            if (!av_store(av, i, sv))
-            SvREFCNT_dec(sv);
-          }
-          CSLDestroy(result);
-        }
-        ST(argvi) = newRV((SV*)av);
-        sv_2mortal(ST(argvi));
-        argvi++;
-      }
-    }
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GetProjectionMethodParameterList) {
-  {
-    char *arg1 = (char *) 0 ;
-    char **arg2 = (char **) 0 ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
-    char *argout2 = 0 ;
-    int argvi = 0;
-    char **result = 0 ;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (char **argout2) */
-      arg2 = &argout2;
-    }
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: GetProjectionMethodParameterList(method);");
-    }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GetProjectionMethodParameterList" "', argument " "1"" of type '" "char *""'");
-    }
-    arg1 = reinterpret_cast< char * >(buf1);
-    {
-      /* %typemap(check) (char *method) */
-      if (!arg1)
-      SWIG_croak("The method must not be undefined when it is an argument to a Geo::GDAL method");
-    }
-    {
-      CPLErrorReset();
-      result = (char **)OPTGetParameterList(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) char **CSL_REF */
-      AV *av = (AV*)sv_2mortal((SV*)newAV());
-      if (result) {
-        int i;
-        for (i = 0; result[i]; i++) {
-          SV *sv = newSVpv(result[i], 0);
-          SvUTF8_on(sv); /* expecting GDAL to give us UTF-8 */
-          if (!av_store(av, i, sv))
-          SvREFCNT_dec(sv);
-        }
-        CSLDestroy(result);
-      }
-      ST(argvi) = newRV((SV*)av);
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    {
-      /* %typemap(argout) (char **argout) */
-      ST(argvi) = sv_newmortal();
-      if ( arg2 ) {
-        sv_setpv(ST(argvi), *arg2);
-        SvUTF8_on(ST(argvi)); /* expecting UTF-8 from GDAL */
-      }
-      argvi++;
-    }
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    
-    XSRETURN(argvi);
-  fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_GetProjectionMethodParamInfo) {
-  {
-    char *arg1 = (char *) 0 ;
-    char *arg2 = (char *) 0 ;
-    char **arg3 = (char **) 0 ;
-    char **arg4 = (char **) 0 ;
-    double *arg5 = (double *) 0 ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    char *argout3 = 0 ;
-    char *argout4 = 0 ;
-    double temp5 ;
-    int res5 = SWIG_TMPOBJ ;
-    int argvi = 0;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (char **argout3) */
-      arg3 = &argout3;
-    }
-    {
-      /* %typemap(in,numinputs=0) (char **argout4) */
-      arg4 = &argout4;
-    }
-    arg5 = &temp5;
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: GetProjectionMethodParamInfo(method,param);");
-    }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GetProjectionMethodParamInfo" "', argument " "1"" of type '" "char *""'");
-    }
-    arg1 = reinterpret_cast< char * >(buf1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "GetProjectionMethodParamInfo" "', argument " "2"" of type '" "char *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    {
-      /* %typemap(check) (char *method) */
-      if (!arg1)
-      SWIG_croak("The method must not be undefined when it is an argument to a Geo::GDAL method");
-    }
-    {
-      CPLErrorReset();
-      OPTGetParameterInfo(arg1,arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    {
-      /* %typemap(argout) (char **argout) */
-      ST(argvi) = sv_newmortal();
-      if ( arg3 ) {
-        sv_setpv(ST(argvi), *arg3);
-        SvUTF8_on(ST(argvi)); /* expecting UTF-8 from GDAL */
-      }
-      argvi++;
-    }
-    {
-      /* %typemap(argout) (char **argout) */
-      ST(argvi) = sv_newmortal();
-      if ( arg4 ) {
-        sv_setpv(ST(argvi), *arg4);
-        SvUTF8_on(ST(argvi)); /* expecting UTF-8 from GDAL */
-      }
-      argvi++;
-    }
-    if (SWIG_IsTmpObj(res5)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1((*arg5)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res5) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg5), SWIGTYPE_p_double, new_flags); argvi++  ;
-    }
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_new_SpatialReference) {
-  {
-    char *arg1 = (char *) "" ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
-    int argvi = 0;
-    OSRSpatialReferenceShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 1)) {
-      SWIG_croak("Usage: new_SpatialReference(wkt);");
-    }
-    if (items > 0) {
-      res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-      if (!SWIG_IsOK(res1)) {
-        SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_SpatialReference" "', argument " "1"" of type '" "char const *""'");
-      }
-      arg1 = reinterpret_cast< char * >(buf1);
-    }
-    {
-      CPLErrorReset();
-      result = (OSRSpatialReferenceShadow *)new_OSRSpatialReferenceShadow((char const *)arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OSRSpatialReferenceShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    XSRETURN(argvi);
-  fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_delete_SpatialReference) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: delete_SpatialReference(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, SWIG_POINTER_DISOWN |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_SpatialReference" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      delete_OSRSpatialReferenceShadow(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_IsSame) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    OSRSpatialReferenceShadow *arg2 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: SpatialReference_IsSame(self,rhs);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_IsSame" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_IsSame" "', argument " "2"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (int)OSRSpatialReferenceShadow_IsSame(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_IsSameGeogCS) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    OSRSpatialReferenceShadow *arg2 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: SpatialReference_IsSameGeogCS(self,rhs);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_IsSameGeogCS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_IsSameGeogCS" "', argument " "2"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (int)OSRSpatialReferenceShadow_IsSameGeogCS(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_IsSameVertCS) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    OSRSpatialReferenceShadow *arg2 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: SpatialReference_IsSameVertCS(self,rhs);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_IsSameVertCS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_IsSameVertCS" "', argument " "2"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (int)OSRSpatialReferenceShadow_IsSameVertCS(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_IsGeographic) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_IsGeographic(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_IsGeographic" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OSRSpatialReferenceShadow_IsGeographic(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_IsProjected) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_IsProjected(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_IsProjected" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OSRSpatialReferenceShadow_IsProjected(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_IsCompound) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_IsCompound(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_IsCompound" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OSRSpatialReferenceShadow_IsCompound(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_IsGeocentric) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_IsGeocentric(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_IsGeocentric" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OSRSpatialReferenceShadow_IsGeocentric(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_IsLocal) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_IsLocal(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_IsLocal" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OSRSpatialReferenceShadow_IsLocal(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_IsVertical) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_IsVertical(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_IsVertical" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OSRSpatialReferenceShadow_IsVertical(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_EPSGTreatsAsLatLong) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_EPSGTreatsAsLatLong(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_EPSGTreatsAsLatLong" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OSRSpatialReferenceShadow_EPSGTreatsAsLatLong(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_EPSGTreatsAsNorthingEasting) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_EPSGTreatsAsNorthingEasting(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_EPSGTreatsAsNorthingEasting" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OSRSpatialReferenceShadow_EPSGTreatsAsNorthingEasting(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetAuthority) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    char *arg3 = (char *) 0 ;
-    int arg4 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int res3 ;
-    char *buf3 = 0 ;
-    int alloc3 = 0 ;
-    int val4 ;
-    int ecode4 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 4) || (items > 4)) {
-      SWIG_croak("Usage: SpatialReference_SetAuthority(self,pszTargetKey,pszAuthority,nCode);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetAuthority" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_SetAuthority" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "SpatialReference_SetAuthority" "', argument " "3"" of type '" "char const *""'");
-    }
-    arg3 = reinterpret_cast< char * >(buf3);
-    ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetAuthority" "', argument " "4"" of type '" "int""'");
-    } 
-    arg4 = static_cast< int >(val4);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetAuthority(arg1,(char const *)arg2,(char const *)arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_GetAttrValue) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    int arg3 = (int) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 3)) {
-      SWIG_croak("Usage: SpatialReference_GetAttrValue(self,name,child);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_GetAttrValue" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    if (items > 2) {
-      ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-      if (!SWIG_IsOK(ecode3)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_GetAttrValue" "', argument " "3"" of type '" "int""'");
-      } 
-      arg3 = static_cast< int >(val3);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (char *)OSRSpatialReferenceShadow_GetAttrValue(arg1,(char const *)arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetAttrValue) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    char *arg3 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res3 ;
-    char *buf3 = 0 ;
-    int alloc3 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: SpatialReference_SetAttrValue(self,name,value);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetAttrValue" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "SpatialReference_SetAttrValue" "', argument " "3"" of type '" "char const *""'");
-    }
-    arg3 = reinterpret_cast< char * >(buf3);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetAttrValue(arg1,(char const *)arg2,(char const *)arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetAngularUnits) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    double arg3 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: SpatialReference_SetAngularUnits(self,name,to_radians);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetAngularUnits" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetAngularUnits" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetAngularUnits(arg1,(char const *)arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_GetAngularUnits) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    double result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_GetAngularUnits(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_GetAngularUnits" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (double)OSRSpatialReferenceShadow_GetAngularUnits(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetTargetLinearUnits) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    char *arg3 = (char *) 0 ;
-    double arg4 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 4) || (items > 4)) {
-      SWIG_croak("Usage: SpatialReference_SetTargetLinearUnits(self,target,name,to_meters);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetTargetLinearUnits" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_SetTargetLinearUnits" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(2));
-      arg3 = SvPV_nolen(ST(2));
-    }
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetTargetLinearUnits" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    {
-      if (!arg3) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetTargetLinearUnits(arg1,(char const *)arg2,(char const *)arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetLinearUnits) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    double arg3 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: SpatialReference_SetLinearUnits(self,name,to_meters);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetLinearUnits" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetLinearUnits" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetLinearUnits(arg1,(char const *)arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetLinearUnitsAndUpdateParameters) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    double arg3 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: SpatialReference_SetLinearUnitsAndUpdateParameters(self,name,to_meters);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetLinearUnitsAndUpdateParameters" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetLinearUnitsAndUpdateParameters" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetLinearUnitsAndUpdateParameters(arg1,(char const *)arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_GetLinearUnits) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    double result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_GetLinearUnits(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_GetLinearUnits" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (double)OSRSpatialReferenceShadow_GetLinearUnits(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_GetLinearUnitsName) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_GetLinearUnitsName(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_GetLinearUnitsName" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (char *)OSRSpatialReferenceShadow_GetLinearUnitsName(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_GetAuthorityCode) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    {
-      /* %typemap(default) const char * target_key */
-      arg2 = NULL;
-    }
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: SpatialReference_GetAuthorityCode(self,target_key);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_GetAuthorityCode" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    if (items > 1) {
-      res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-      if (!SWIG_IsOK(res2)) {
-        SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_GetAuthorityCode" "', argument " "2"" of type '" "char const *""'");
-      }
-      arg2 = reinterpret_cast< char * >(buf2);
-    }
-    {
-      CPLErrorReset();
-      result = (char *)OSRSpatialReferenceShadow_GetAuthorityCode(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_GetAuthorityName) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    {
-      /* %typemap(default) const char * target_key */
-      arg2 = NULL;
-    }
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: SpatialReference_GetAuthorityName(self,target_key);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_GetAuthorityName" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    if (items > 1) {
-      res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-      if (!SWIG_IsOK(res2)) {
-        SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_GetAuthorityName" "', argument " "2"" of type '" "char const *""'");
-      }
-      arg2 = reinterpret_cast< char * >(buf2);
-    }
-    {
-      CPLErrorReset();
-      result = (char *)OSRSpatialReferenceShadow_GetAuthorityName(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetUTM) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    int arg2 ;
-    int arg3 = (int) 1 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 3)) {
-      SWIG_croak("Usage: SpatialReference_SetUTM(self,zone,north);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetUTM" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetUTM" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    if (items > 2) {
-      ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-      if (!SWIG_IsOK(ecode3)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetUTM" "', argument " "3"" of type '" "int""'");
-      } 
-      arg3 = static_cast< int >(val3);
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetUTM(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference__GetUTMZone) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference__GetUTMZone(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference__GetUTMZone" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OSRSpatialReferenceShadow_GetUTMZone(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetStatePlane) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    int arg2 ;
-    int arg3 = (int) 1 ;
-    char *arg4 = (char *) "" ;
-    double arg5 = (double) 0.0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int res4 ;
-    char *buf4 = 0 ;
-    int alloc4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 5)) {
-      SWIG_croak("Usage: SpatialReference_SetStatePlane(self,zone,is_nad83,unitsname,units);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetStatePlane" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetStatePlane" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    if (items > 2) {
-      ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-      if (!SWIG_IsOK(ecode3)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetStatePlane" "', argument " "3"" of type '" "int""'");
-      } 
-      arg3 = static_cast< int >(val3);
-    }
-    if (items > 3) {
-      res4 = SWIG_AsCharPtrAndSize(ST(3), &buf4, NULL, &alloc4);
-      if (!SWIG_IsOK(res4)) {
-        SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "SpatialReference_SetStatePlane" "', argument " "4"" of type '" "char const *""'");
-      }
-      arg4 = reinterpret_cast< char * >(buf4);
-    }
-    if (items > 4) {
-      ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-      if (!SWIG_IsOK(ecode5)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetStatePlane" "', argument " "5"" of type '" "double""'");
-      } 
-      arg5 = static_cast< double >(val5);
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetStatePlane(arg1,arg2,arg3,(char const *)arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_AutoIdentifyEPSG) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_AutoIdentifyEPSG(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_AutoIdentifyEPSG" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_AutoIdentifyEPSG(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetProjection) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: SpatialReference_SetProjection(self,arg);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetProjection" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_SetProjection" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetProjection(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetProjParm) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    double arg3 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: SpatialReference_SetProjParm(self,name,val);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetProjParm" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetProjParm" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetProjParm(arg1,(char const *)arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_GetProjParm) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    double arg3 = (double) 0.0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    double result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 3)) {
-      SWIG_croak("Usage: SpatialReference_GetProjParm(self,name,default_val);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_GetProjParm" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    if (items > 2) {
-      ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-      if (!SWIG_IsOK(ecode3)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_GetProjParm" "', argument " "3"" of type '" "double""'");
-      } 
-      arg3 = static_cast< double >(val3);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (double)OSRSpatialReferenceShadow_GetProjParm(arg1,(char const *)arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetNormProjParm) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    double arg3 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: SpatialReference_SetNormProjParm(self,name,val);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetNormProjParm" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetNormProjParm" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetNormProjParm(arg1,(char const *)arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_GetNormProjParm) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    double arg3 = (double) 0.0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    double result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 3)) {
-      SWIG_croak("Usage: SpatialReference_GetNormProjParm(self,name,default_val);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_GetNormProjParm" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    if (items > 2) {
-      ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-      if (!SWIG_IsOK(ecode3)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_GetNormProjParm" "', argument " "3"" of type '" "double""'");
-      } 
-      arg3 = static_cast< double >(val3);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (double)OSRSpatialReferenceShadow_GetNormProjParm(arg1,(char const *)arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_GetSemiMajor) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    double result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_GetSemiMajor(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_GetSemiMajor" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (double)OSRSpatialReferenceShadow_GetSemiMajor(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_GetSemiMinor) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    double result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_GetSemiMinor(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_GetSemiMinor" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (double)OSRSpatialReferenceShadow_GetSemiMinor(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_GetInvFlattening) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    double result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_GetInvFlattening(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_GetInvFlattening" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (double)OSRSpatialReferenceShadow_GetInvFlattening(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetACEA) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    double arg6 ;
-    double arg7 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    double val6 ;
-    int ecode6 = 0 ;
-    double val7 ;
-    int ecode7 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 7) || (items > 7)) {
-      SWIG_croak("Usage: SpatialReference_SetACEA(self,stdp1,stdp2,clat,clong,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetACEA" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetACEA" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetACEA" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetACEA" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetACEA" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    ecode6 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(5), &val6);
-    if (!SWIG_IsOK(ecode6)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "SpatialReference_SetACEA" "', argument " "6"" of type '" "double""'");
-    } 
-    arg6 = static_cast< double >(val6);
-    ecode7 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(6), &val7);
-    if (!SWIG_IsOK(ecode7)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "SpatialReference_SetACEA" "', argument " "7"" of type '" "double""'");
-    } 
-    arg7 = static_cast< double >(val7);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetACEA(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetAE) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 5) || (items > 5)) {
-      SWIG_croak("Usage: SpatialReference_SetAE(self,clat,clong,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetAE" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetAE" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetAE" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetAE" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetAE" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetAE(arg1,arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetBonne) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 5) || (items > 5)) {
-      SWIG_croak("Usage: SpatialReference_SetBonne(self,stdp,cm,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetBonne" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetBonne" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetBonne" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetBonne" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetBonne" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetBonne(arg1,arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetCEA) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 5) || (items > 5)) {
-      SWIG_croak("Usage: SpatialReference_SetCEA(self,stdp1,cm,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetCEA" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetCEA" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetCEA" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetCEA" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetCEA" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetCEA(arg1,arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetCS) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 5) || (items > 5)) {
-      SWIG_croak("Usage: SpatialReference_SetCS(self,clat,clong,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetCS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetCS" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetCS" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetCS" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetCS" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetCS(arg1,arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetEC) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    double arg6 ;
-    double arg7 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    double val6 ;
-    int ecode6 = 0 ;
-    double val7 ;
-    int ecode7 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 7) || (items > 7)) {
-      SWIG_croak("Usage: SpatialReference_SetEC(self,stdp1,stdp2,clat,clong,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetEC" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetEC" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetEC" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetEC" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetEC" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    ecode6 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(5), &val6);
-    if (!SWIG_IsOK(ecode6)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "SpatialReference_SetEC" "', argument " "6"" of type '" "double""'");
-    } 
-    arg6 = static_cast< double >(val6);
-    ecode7 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(6), &val7);
-    if (!SWIG_IsOK(ecode7)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "SpatialReference_SetEC" "', argument " "7"" of type '" "double""'");
-    } 
-    arg7 = static_cast< double >(val7);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetEC(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetEckertIV) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 4) || (items > 4)) {
-      SWIG_croak("Usage: SpatialReference_SetEckertIV(self,cm,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetEckertIV" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetEckertIV" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetEckertIV" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetEckertIV" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetEckertIV(arg1,arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetEckertVI) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 4) || (items > 4)) {
-      SWIG_croak("Usage: SpatialReference_SetEckertVI(self,cm,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetEckertVI" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetEckertVI" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetEckertVI" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetEckertVI" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetEckertVI(arg1,arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetEquirectangular) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 5) || (items > 5)) {
-      SWIG_croak("Usage: SpatialReference_SetEquirectangular(self,clat,clong,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetEquirectangular" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetEquirectangular" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetEquirectangular" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetEquirectangular" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetEquirectangular" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetEquirectangular(arg1,arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetEquirectangular2) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    double arg6 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    double val6 ;
-    int ecode6 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 6) || (items > 6)) {
-      SWIG_croak("Usage: SpatialReference_SetEquirectangular2(self,clat,clong,pseudostdparallellat,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetEquirectangular2" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetEquirectangular2" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetEquirectangular2" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetEquirectangular2" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetEquirectangular2" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    ecode6 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(5), &val6);
-    if (!SWIG_IsOK(ecode6)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "SpatialReference_SetEquirectangular2" "', argument " "6"" of type '" "double""'");
-    } 
-    arg6 = static_cast< double >(val6);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetEquirectangular2(arg1,arg2,arg3,arg4,arg5,arg6);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetGaussSchreiberTMercator) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    double arg6 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    double val6 ;
-    int ecode6 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 6) || (items > 6)) {
-      SWIG_croak("Usage: SpatialReference_SetGaussSchreiberTMercator(self,clat,clong,sc,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetGaussSchreiberTMercator" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetGaussSchreiberTMercator" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetGaussSchreiberTMercator" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetGaussSchreiberTMercator" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetGaussSchreiberTMercator" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    ecode6 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(5), &val6);
-    if (!SWIG_IsOK(ecode6)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "SpatialReference_SetGaussSchreiberTMercator" "', argument " "6"" of type '" "double""'");
-    } 
-    arg6 = static_cast< double >(val6);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetGaussSchreiberTMercator(arg1,arg2,arg3,arg4,arg5,arg6);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetGS) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 4) || (items > 4)) {
-      SWIG_croak("Usage: SpatialReference_SetGS(self,cm,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetGS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetGS" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetGS" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetGS" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetGS(arg1,arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetGH) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 4) || (items > 4)) {
-      SWIG_croak("Usage: SpatialReference_SetGH(self,cm,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetGH" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetGH" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetGH" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetGH" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetGH(arg1,arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetIGH) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_SetIGH(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetIGH" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetIGH(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetGEOS) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 5) || (items > 5)) {
-      SWIG_croak("Usage: SpatialReference_SetGEOS(self,cm,satelliteheight,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetGEOS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetGEOS" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetGEOS" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetGEOS" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetGEOS" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetGEOS(arg1,arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetGnomonic) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 5) || (items > 5)) {
-      SWIG_croak("Usage: SpatialReference_SetGnomonic(self,clat,clong,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetGnomonic" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetGnomonic" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetGnomonic" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetGnomonic" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetGnomonic" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetGnomonic(arg1,arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetHOM) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    double arg6 ;
-    double arg7 ;
-    double arg8 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    double val6 ;
-    int ecode6 = 0 ;
-    double val7 ;
-    int ecode7 = 0 ;
-    double val8 ;
-    int ecode8 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 8) || (items > 8)) {
-      SWIG_croak("Usage: SpatialReference_SetHOM(self,clat,clong,azimuth,recttoskew,scale,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetHOM" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetHOM" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetHOM" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetHOM" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetHOM" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    ecode6 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(5), &val6);
-    if (!SWIG_IsOK(ecode6)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "SpatialReference_SetHOM" "', argument " "6"" of type '" "double""'");
-    } 
-    arg6 = static_cast< double >(val6);
-    ecode7 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(6), &val7);
-    if (!SWIG_IsOK(ecode7)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "SpatialReference_SetHOM" "', argument " "7"" of type '" "double""'");
-    } 
-    arg7 = static_cast< double >(val7);
-    ecode8 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(7), &val8);
-    if (!SWIG_IsOK(ecode8)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "SpatialReference_SetHOM" "', argument " "8"" of type '" "double""'");
-    } 
-    arg8 = static_cast< double >(val8);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetHOM(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetHOM2PNO) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    double arg6 ;
-    double arg7 ;
-    double arg8 ;
-    double arg9 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    double val6 ;
-    int ecode6 = 0 ;
-    double val7 ;
-    int ecode7 = 0 ;
-    double val8 ;
-    int ecode8 = 0 ;
-    double val9 ;
-    int ecode9 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 9) || (items > 9)) {
-      SWIG_croak("Usage: SpatialReference_SetHOM2PNO(self,clat,dfLat1,dfLong1,dfLat2,dfLong2,scale,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetHOM2PNO" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetHOM2PNO" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetHOM2PNO" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetHOM2PNO" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetHOM2PNO" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    ecode6 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(5), &val6);
-    if (!SWIG_IsOK(ecode6)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "SpatialReference_SetHOM2PNO" "', argument " "6"" of type '" "double""'");
-    } 
-    arg6 = static_cast< double >(val6);
-    ecode7 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(6), &val7);
-    if (!SWIG_IsOK(ecode7)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "SpatialReference_SetHOM2PNO" "', argument " "7"" of type '" "double""'");
-    } 
-    arg7 = static_cast< double >(val7);
-    ecode8 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(7), &val8);
-    if (!SWIG_IsOK(ecode8)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "SpatialReference_SetHOM2PNO" "', argument " "8"" of type '" "double""'");
-    } 
-    arg8 = static_cast< double >(val8);
-    ecode9 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(8), &val9);
-    if (!SWIG_IsOK(ecode9)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode9), "in method '" "SpatialReference_SetHOM2PNO" "', argument " "9"" of type '" "double""'");
-    } 
-    arg9 = static_cast< double >(val9);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetHOM2PNO(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetKrovak) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    double arg6 ;
-    double arg7 ;
-    double arg8 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    double val6 ;
-    int ecode6 = 0 ;
-    double val7 ;
-    int ecode7 = 0 ;
-    double val8 ;
-    int ecode8 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 8) || (items > 8)) {
-      SWIG_croak("Usage: SpatialReference_SetKrovak(self,clat,clong,azimuth,pseudostdparallellat,scale,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetKrovak" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetKrovak" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetKrovak" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetKrovak" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetKrovak" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    ecode6 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(5), &val6);
-    if (!SWIG_IsOK(ecode6)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "SpatialReference_SetKrovak" "', argument " "6"" of type '" "double""'");
-    } 
-    arg6 = static_cast< double >(val6);
-    ecode7 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(6), &val7);
-    if (!SWIG_IsOK(ecode7)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "SpatialReference_SetKrovak" "', argument " "7"" of type '" "double""'");
-    } 
-    arg7 = static_cast< double >(val7);
-    ecode8 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(7), &val8);
-    if (!SWIG_IsOK(ecode8)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "SpatialReference_SetKrovak" "', argument " "8"" of type '" "double""'");
-    } 
-    arg8 = static_cast< double >(val8);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetKrovak(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetLAEA) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 5) || (items > 5)) {
-      SWIG_croak("Usage: SpatialReference_SetLAEA(self,clat,clong,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetLAEA" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetLAEA" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetLAEA" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetLAEA" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetLAEA" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetLAEA(arg1,arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetLCC) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    double arg6 ;
-    double arg7 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    double val6 ;
-    int ecode6 = 0 ;
-    double val7 ;
-    int ecode7 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 7) || (items > 7)) {
-      SWIG_croak("Usage: SpatialReference_SetLCC(self,stdp1,stdp2,clat,clong,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetLCC" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetLCC" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetLCC" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetLCC" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetLCC" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    ecode6 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(5), &val6);
-    if (!SWIG_IsOK(ecode6)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "SpatialReference_SetLCC" "', argument " "6"" of type '" "double""'");
-    } 
-    arg6 = static_cast< double >(val6);
-    ecode7 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(6), &val7);
-    if (!SWIG_IsOK(ecode7)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "SpatialReference_SetLCC" "', argument " "7"" of type '" "double""'");
-    } 
-    arg7 = static_cast< double >(val7);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetLCC(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetLCC1SP) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    double arg6 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    double val6 ;
-    int ecode6 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 6) || (items > 6)) {
-      SWIG_croak("Usage: SpatialReference_SetLCC1SP(self,clat,clong,scale,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetLCC1SP" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetLCC1SP" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetLCC1SP" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetLCC1SP" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetLCC1SP" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    ecode6 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(5), &val6);
-    if (!SWIG_IsOK(ecode6)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "SpatialReference_SetLCC1SP" "', argument " "6"" of type '" "double""'");
-    } 
-    arg6 = static_cast< double >(val6);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetLCC1SP(arg1,arg2,arg3,arg4,arg5,arg6);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetLCCB) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    double arg6 ;
-    double arg7 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    double val6 ;
-    int ecode6 = 0 ;
-    double val7 ;
-    int ecode7 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 7) || (items > 7)) {
-      SWIG_croak("Usage: SpatialReference_SetLCCB(self,stdp1,stdp2,clat,clong,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetLCCB" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetLCCB" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetLCCB" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetLCCB" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetLCCB" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    ecode6 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(5), &val6);
-    if (!SWIG_IsOK(ecode6)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "SpatialReference_SetLCCB" "', argument " "6"" of type '" "double""'");
-    } 
-    arg6 = static_cast< double >(val6);
-    ecode7 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(6), &val7);
-    if (!SWIG_IsOK(ecode7)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "SpatialReference_SetLCCB" "', argument " "7"" of type '" "double""'");
-    } 
-    arg7 = static_cast< double >(val7);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetLCCB(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetMC) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 5) || (items > 5)) {
-      SWIG_croak("Usage: SpatialReference_SetMC(self,clat,clong,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetMC" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetMC" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetMC" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetMC" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetMC" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetMC(arg1,arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetMercator) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    double arg6 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    double val6 ;
-    int ecode6 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 6) || (items > 6)) {
-      SWIG_croak("Usage: SpatialReference_SetMercator(self,clat,clong,scale,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetMercator" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetMercator" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetMercator" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetMercator" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetMercator" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    ecode6 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(5), &val6);
-    if (!SWIG_IsOK(ecode6)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "SpatialReference_SetMercator" "', argument " "6"" of type '" "double""'");
-    } 
-    arg6 = static_cast< double >(val6);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetMercator(arg1,arg2,arg3,arg4,arg5,arg6);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetMollweide) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 4) || (items > 4)) {
-      SWIG_croak("Usage: SpatialReference_SetMollweide(self,cm,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetMollweide" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetMollweide" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetMollweide" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetMollweide" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetMollweide(arg1,arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetNZMG) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 5) || (items > 5)) {
-      SWIG_croak("Usage: SpatialReference_SetNZMG(self,clat,clong,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetNZMG" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetNZMG" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetNZMG" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetNZMG" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetNZMG" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetNZMG(arg1,arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetOS) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    double arg6 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    double val6 ;
-    int ecode6 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 6) || (items > 6)) {
-      SWIG_croak("Usage: SpatialReference_SetOS(self,dfOriginLat,dfCMeridian,scale,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetOS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetOS" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetOS" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetOS" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetOS" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    ecode6 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(5), &val6);
-    if (!SWIG_IsOK(ecode6)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "SpatialReference_SetOS" "', argument " "6"" of type '" "double""'");
-    } 
-    arg6 = static_cast< double >(val6);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetOS(arg1,arg2,arg3,arg4,arg5,arg6);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetOrthographic) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 5) || (items > 5)) {
-      SWIG_croak("Usage: SpatialReference_SetOrthographic(self,clat,clong,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetOrthographic" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetOrthographic" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetOrthographic" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetOrthographic" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetOrthographic" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetOrthographic(arg1,arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetPolyconic) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 5) || (items > 5)) {
-      SWIG_croak("Usage: SpatialReference_SetPolyconic(self,clat,clong,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetPolyconic" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetPolyconic" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetPolyconic" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetPolyconic" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetPolyconic" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetPolyconic(arg1,arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetPS) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    double arg6 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    double val6 ;
-    int ecode6 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 6) || (items > 6)) {
-      SWIG_croak("Usage: SpatialReference_SetPS(self,clat,clong,scale,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetPS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetPS" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetPS" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetPS" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetPS" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    ecode6 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(5), &val6);
-    if (!SWIG_IsOK(ecode6)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "SpatialReference_SetPS" "', argument " "6"" of type '" "double""'");
-    } 
-    arg6 = static_cast< double >(val6);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetPS(arg1,arg2,arg3,arg4,arg5,arg6);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetRobinson) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 4) || (items > 4)) {
-      SWIG_croak("Usage: SpatialReference_SetRobinson(self,clong,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetRobinson" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetRobinson" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetRobinson" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetRobinson" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetRobinson(arg1,arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetSinusoidal) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 4) || (items > 4)) {
-      SWIG_croak("Usage: SpatialReference_SetSinusoidal(self,clong,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetSinusoidal" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetSinusoidal" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetSinusoidal" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetSinusoidal" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetSinusoidal(arg1,arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetStereographic) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    double arg6 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    double val6 ;
-    int ecode6 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 6) || (items > 6)) {
-      SWIG_croak("Usage: SpatialReference_SetStereographic(self,clat,clong,scale,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetStereographic" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetStereographic" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetStereographic" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetStereographic" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetStereographic" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    ecode6 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(5), &val6);
-    if (!SWIG_IsOK(ecode6)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "SpatialReference_SetStereographic" "', argument " "6"" of type '" "double""'");
-    } 
-    arg6 = static_cast< double >(val6);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetStereographic(arg1,arg2,arg3,arg4,arg5,arg6);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetSOC) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 5) || (items > 5)) {
-      SWIG_croak("Usage: SpatialReference_SetSOC(self,latitudeoforigin,cm,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetSOC" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetSOC" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetSOC" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetSOC" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetSOC" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetSOC(arg1,arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetTM) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    double arg6 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    double val6 ;
-    int ecode6 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 6) || (items > 6)) {
-      SWIG_croak("Usage: SpatialReference_SetTM(self,clat,clong,scale,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetTM" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetTM" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetTM" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetTM" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetTM" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    ecode6 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(5), &val6);
-    if (!SWIG_IsOK(ecode6)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "SpatialReference_SetTM" "', argument " "6"" of type '" "double""'");
-    } 
-    arg6 = static_cast< double >(val6);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetTM(arg1,arg2,arg3,arg4,arg5,arg6);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetTMVariant) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    double arg6 ;
-    double arg7 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    double val6 ;
-    int ecode6 = 0 ;
-    double val7 ;
-    int ecode7 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 7) || (items > 7)) {
-      SWIG_croak("Usage: SpatialReference_SetTMVariant(self,pszVariantName,clat,clong,scale,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetTMVariant" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_SetTMVariant" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetTMVariant" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetTMVariant" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetTMVariant" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    ecode6 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(5), &val6);
-    if (!SWIG_IsOK(ecode6)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "SpatialReference_SetTMVariant" "', argument " "6"" of type '" "double""'");
-    } 
-    arg6 = static_cast< double >(val6);
-    ecode7 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(6), &val7);
-    if (!SWIG_IsOK(ecode7)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "SpatialReference_SetTMVariant" "', argument " "7"" of type '" "double""'");
-    } 
-    arg7 = static_cast< double >(val7);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetTMVariant(arg1,(char const *)arg2,arg3,arg4,arg5,arg6,arg7);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetTMG) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 5) || (items > 5)) {
-      SWIG_croak("Usage: SpatialReference_SetTMG(self,clat,clong,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetTMG" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetTMG" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetTMG" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetTMG" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetTMG" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetTMG(arg1,arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetTMSO) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 ;
-    double arg6 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    double val6 ;
-    int ecode6 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 6) || (items > 6)) {
-      SWIG_croak("Usage: SpatialReference_SetTMSO(self,clat,clong,scale,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetTMSO" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetTMSO" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetTMSO" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetTMSO" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetTMSO" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    ecode6 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(5), &val6);
-    if (!SWIG_IsOK(ecode6)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "SpatialReference_SetTMSO" "', argument " "6"" of type '" "double""'");
-    } 
-    arg6 = static_cast< double >(val6);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetTMSO(arg1,arg2,arg3,arg4,arg5,arg6);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetVDG) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 4) || (items > 4)) {
-      SWIG_croak("Usage: SpatialReference_SetVDG(self,clong,fe,fn);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetVDG" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetVDG" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetVDG" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetVDG" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetVDG(arg1,arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetWellKnownGeogCS) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: SpatialReference_SetWellKnownGeogCS(self,name);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetWellKnownGeogCS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetWellKnownGeogCS(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetFromUserInput) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: SpatialReference_SetFromUserInput(self,name);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetFromUserInput" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetFromUserInput(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_CopyGeogCSFrom) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    OSRSpatialReferenceShadow *arg2 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: SpatialReference_CopyGeogCSFrom(self,rhs);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_CopyGeogCSFrom" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_CopyGeogCSFrom" "', argument " "2"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_CopyGeogCSFrom(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetTOWGS84) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 = (double) 0.0 ;
-    double arg6 = (double) 0.0 ;
-    double arg7 = (double) 0.0 ;
-    double arg8 = (double) 0.0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    double val6 ;
-    int ecode6 = 0 ;
-    double val7 ;
-    int ecode7 = 0 ;
-    double val8 ;
-    int ecode8 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 4) || (items > 8)) {
-      SWIG_croak("Usage: SpatialReference_SetTOWGS84(self,p1,p2,p3,p4,p5,p6,p7);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetTOWGS84" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_SetTOWGS84" "', argument " "2"" of type '" "double""'");
-    } 
-    arg2 = static_cast< double >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetTOWGS84" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetTOWGS84" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    if (items > 4) {
-      ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-      if (!SWIG_IsOK(ecode5)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetTOWGS84" "', argument " "5"" of type '" "double""'");
-      } 
-      arg5 = static_cast< double >(val5);
-    }
-    if (items > 5) {
-      ecode6 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(5), &val6);
-      if (!SWIG_IsOK(ecode6)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "SpatialReference_SetTOWGS84" "', argument " "6"" of type '" "double""'");
-      } 
-      arg6 = static_cast< double >(val6);
-    }
-    if (items > 6) {
-      ecode7 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(6), &val7);
-      if (!SWIG_IsOK(ecode7)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "SpatialReference_SetTOWGS84" "', argument " "7"" of type '" "double""'");
-      } 
-      arg7 = static_cast< double >(val7);
-    }
-    if (items > 7) {
-      ecode8 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(7), &val8);
-      if (!SWIG_IsOK(ecode8)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "SpatialReference_SetTOWGS84" "', argument " "8"" of type '" "double""'");
-      } 
-      arg8 = static_cast< double >(val8);
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetTOWGS84(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_GetTOWGS84) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double *arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double argout2[7] ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (double argout2[ANY]) */
-      arg2 = argout2;
-    }
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_GetTOWGS84(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_GetTOWGS84" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_GetTOWGS84(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    {
-      /* %typemap(argout) (double argout[ANY]) */
-      if (GIMME_V == G_ARRAY) {
-        /* return a list */
-        int i;
-        EXTEND(SP, argvi+7-items+1);
-        for (i = 0; i < 7; i++)
-        ST(argvi++) = sv_2mortal(newSVnv(arg2[i]));
-      } else {
-        ST(argvi) = CreateArrayFromDoubleArray( arg2, 7 );
-        argvi++;
-      }  
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetLocalCS) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: SpatialReference_SetLocalCS(self,pszName);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetLocalCS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_SetLocalCS" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetLocalCS(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetGeogCS) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    char *arg3 = (char *) 0 ;
-    char *arg4 = (char *) 0 ;
-    double arg5 ;
-    double arg6 ;
-    char *arg7 = (char *) "Greenwich" ;
-    double arg8 = (double) 0.0 ;
-    char *arg9 = (char *) "degree" ;
-    double arg10 = (double) 0.0174532925199433 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int res3 ;
-    char *buf3 = 0 ;
-    int alloc3 = 0 ;
-    int res4 ;
-    char *buf4 = 0 ;
-    int alloc4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    double val6 ;
-    int ecode6 = 0 ;
-    int res7 ;
-    char *buf7 = 0 ;
-    int alloc7 = 0 ;
-    double val8 ;
-    int ecode8 = 0 ;
-    int res9 ;
-    char *buf9 = 0 ;
-    int alloc9 = 0 ;
-    double val10 ;
-    int ecode10 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 6) || (items > 10)) {
-      SWIG_croak("Usage: SpatialReference_SetGeogCS(self,pszGeogName,pszDatumName,pszEllipsoidName,dfSemiMajor,dfInvFlattening,pszPMName,dfPMOffset,pszUnits,dfConvertToRadians);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetGeogCS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_SetGeogCS" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "SpatialReference_SetGeogCS" "', argument " "3"" of type '" "char const *""'");
-    }
-    arg3 = reinterpret_cast< char * >(buf3);
-    res4 = SWIG_AsCharPtrAndSize(ST(3), &buf4, NULL, &alloc4);
-    if (!SWIG_IsOK(res4)) {
-      SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "SpatialReference_SetGeogCS" "', argument " "4"" of type '" "char const *""'");
-    }
-    arg4 = reinterpret_cast< char * >(buf4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetGeogCS" "', argument " "5"" of type '" "double""'");
-    } 
-    arg5 = static_cast< double >(val5);
-    ecode6 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(5), &val6);
-    if (!SWIG_IsOK(ecode6)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "SpatialReference_SetGeogCS" "', argument " "6"" of type '" "double""'");
-    } 
-    arg6 = static_cast< double >(val6);
-    if (items > 6) {
-      res7 = SWIG_AsCharPtrAndSize(ST(6), &buf7, NULL, &alloc7);
-      if (!SWIG_IsOK(res7)) {
-        SWIG_exception_fail(SWIG_ArgError(res7), "in method '" "SpatialReference_SetGeogCS" "', argument " "7"" of type '" "char const *""'");
-      }
-      arg7 = reinterpret_cast< char * >(buf7);
-    }
-    if (items > 7) {
-      ecode8 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(7), &val8);
-      if (!SWIG_IsOK(ecode8)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "SpatialReference_SetGeogCS" "', argument " "8"" of type '" "double""'");
-      } 
-      arg8 = static_cast< double >(val8);
-    }
-    if (items > 8) {
-      res9 = SWIG_AsCharPtrAndSize(ST(8), &buf9, NULL, &alloc9);
-      if (!SWIG_IsOK(res9)) {
-        SWIG_exception_fail(SWIG_ArgError(res9), "in method '" "SpatialReference_SetGeogCS" "', argument " "9"" of type '" "char const *""'");
-      }
-      arg9 = reinterpret_cast< char * >(buf9);
-    }
-    if (items > 9) {
-      ecode10 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(9), &val10);
-      if (!SWIG_IsOK(ecode10)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode10), "in method '" "SpatialReference_SetGeogCS" "', argument " "10"" of type '" "double""'");
-      } 
-      arg10 = static_cast< double >(val10);
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetGeogCS(arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4,arg5,arg6,(char const *)arg7,arg8,(char const *)arg9,arg10);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
-    
-    
-    if (alloc7 == SWIG_NEWOBJ) delete[] buf7;
-    
-    if (alloc9 == SWIG_NEWOBJ) delete[] buf9;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
-    
-    
-    if (alloc7 == SWIG_NEWOBJ) delete[] buf7;
-    
-    if (alloc9 == SWIG_NEWOBJ) delete[] buf9;
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetProjCS) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) "unnamed" ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: SpatialReference_SetProjCS(self,name);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetProjCS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    if (items > 1) {
-      {
-        /* %typemap(in,numinputs=1) (const char* name) */
-        sv_utf8_upgrade(ST(1));
-        arg2 = SvPV_nolen(ST(1));
-      }
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetProjCS(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetGeocCS) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) "unnamed" ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: SpatialReference_SetGeocCS(self,name);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetGeocCS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    if (items > 1) {
-      {
-        /* %typemap(in,numinputs=1) (const char* name) */
-        sv_utf8_upgrade(ST(1));
-        arg2 = SvPV_nolen(ST(1));
-      }
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetGeocCS(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetVertCS) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) "unnamed" ;
-    char *arg3 = (char *) "unnamed" ;
-    int arg4 = (int) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int res3 ;
-    char *buf3 = 0 ;
-    int alloc3 = 0 ;
-    int val4 ;
-    int ecode4 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 4)) {
-      SWIG_croak("Usage: SpatialReference_SetVertCS(self,VertCSName,VertDatumName,VertDatumType);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetVertCS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    if (items > 1) {
-      res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-      if (!SWIG_IsOK(res2)) {
-        SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_SetVertCS" "', argument " "2"" of type '" "char const *""'");
-      }
-      arg2 = reinterpret_cast< char * >(buf2);
-    }
-    if (items > 2) {
-      res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
-      if (!SWIG_IsOK(res3)) {
-        SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "SpatialReference_SetVertCS" "', argument " "3"" of type '" "char const *""'");
-      }
-      arg3 = reinterpret_cast< char * >(buf3);
-    }
-    if (items > 3) {
-      ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-      if (!SWIG_IsOK(ecode4)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetVertCS" "', argument " "4"" of type '" "int""'");
-      } 
-      arg4 = static_cast< int >(val4);
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetVertCS(arg1,(char const *)arg2,(char const *)arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_SetCompoundCS) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    OSRSpatialReferenceShadow *arg3 = (OSRSpatialReferenceShadow *) 0 ;
-    OSRSpatialReferenceShadow *arg4 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp3 = 0 ;
-    int res3 = 0 ;
-    void *argp4 = 0 ;
-    int res4 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 4) || (items > 4)) {
-      SWIG_croak("Usage: SpatialReference_SetCompoundCS(self,name,horizcs,vertcs);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetCompoundCS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      sv_utf8_upgrade(ST(1));
-      arg2 = SvPV_nolen(ST(1));
-    }
-    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "SpatialReference_SetCompoundCS" "', argument " "3"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg3 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp3);
-    res4 = SWIG_ConvertPtr(ST(3), &argp4,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res4)) {
-      SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "SpatialReference_SetCompoundCS" "', argument " "4"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg4 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp4);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      if (!arg3) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      if (!arg4) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetCompoundCS(arg1,(char const *)arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_ImportFromWkt) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char **arg2 = (char **) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    char *val2 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: SpatialReference_ImportFromWkt(self,ppszInput);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_ImportFromWkt" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      /* %typemap(in) (char **ignorechange) */
-      sv_utf8_upgrade(ST(1)); /* GDAL expects UTF-8 */
-      val2 = SvPV_nolen(ST(1));
-      arg2 = &val2;
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_ImportFromWkt(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_ImportFromProj4) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: SpatialReference_ImportFromProj4(self,ppszInput);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_ImportFromProj4" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_ImportFromProj4" "', argument " "2"" of type '" "char *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_ImportFromProj4(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_ImportFromUrl) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: SpatialReference_ImportFromUrl(self,url);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_ImportFromUrl" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_ImportFromUrl" "', argument " "2"" of type '" "char *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_ImportFromUrl(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_ImportFromESRI) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char **arg2 = (char **) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: SpatialReference_ImportFromESRI(self,ppszInput);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_ImportFromESRI" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      /* %typemap(in) char **options */
-      if (SvOK(ST(1))) {
-        if (SvROK(ST(1))) {
-          if (SvTYPE(SvRV(ST(1)))==SVt_PVAV) {
-            AV *av = (AV*)(SvRV(ST(1)));
-            for (int i = 0; i < av_len(av)+1; i++) {
-              SV *sv = *(av_fetch(av, i, 0));
-              sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-              char *pszItem = SvPV_nolen(sv);
-              arg2 = CSLAddString( arg2, pszItem );
-            }
-          } else if (SvTYPE(SvRV(ST(1)))==SVt_PVHV) {
-            HV *hv = (HV*)SvRV(ST(1));
-            SV *sv;
-            char *key;
-            I32 klen;
-            arg2 = NULL;
-            hv_iterinit(hv);
-            while(sv = hv_iternextsv(hv,&key,&klen)) {
-              sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-              arg2 = CSLAddNameValue( arg2, key, SvPV_nolen(sv) );
-            }
-          } else
-          SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-        } else
-        SWIG_croak("The 'options' argument is not a reference.");   
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_ImportFromESRI(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg2) CSLDestroy( arg2 );
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg2) CSLDestroy( arg2 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_ImportFromEPSG) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: SpatialReference_ImportFromEPSG(self,arg);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_ImportFromEPSG" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_ImportFromEPSG" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_ImportFromEPSG(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_ImportFromEPSGA) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: SpatialReference_ImportFromEPSGA(self,arg);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_ImportFromEPSGA" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_ImportFromEPSGA" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_ImportFromEPSGA(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_ImportFromPCI) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    char *arg3 = (char *) "METRE" ;
-    double *arg4 = (double *) (double *)0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int res3 ;
-    char *buf3 = 0 ;
-    int alloc3 = 0 ;
-    double argin4[17] ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 4)) {
-      SWIG_croak("Usage: SpatialReference_ImportFromPCI(self,proj,units,argin);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_ImportFromPCI" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_ImportFromPCI" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    if (items > 2) {
-      res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
-      if (!SWIG_IsOK(res3)) {
-        SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "SpatialReference_ImportFromPCI" "', argument " "3"" of type '" "char const *""'");
-      }
-      arg3 = reinterpret_cast< char * >(buf3);
-    }
-    if (items > 3) {
-      {
-        /* %typemap(in) (double argin4[ANY]) */
-        if (!(SvROK(ST(3)) && (SvTYPE(SvRV(ST(3)))==SVt_PVAV)))
-        SWIG_croak("Expected a reference to an array.");
-        arg4 = argin4;
-        AV *av = (AV*)(SvRV(ST(3)));
-        for (unsigned int i=0; i<17; i++) {
-          SV **sv = av_fetch(av, i, 0);
-          arg4[i] =  SvNV(*sv);
-        }
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_ImportFromPCI(arg1,(char const *)arg2,(char const *)arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_ImportFromUSGS) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    long arg2 ;
-    long arg3 = (long) 0 ;
-    double *arg4 = (double *) (double *)0 ;
-    long arg5 = (long) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    long val2 ;
-    int ecode2 = 0 ;
-    long val3 ;
-    int ecode3 = 0 ;
-    double argin4[15] ;
-    long val5 ;
-    int ecode5 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 5)) {
-      SWIG_croak("Usage: SpatialReference_ImportFromUSGS(self,proj_code,zone,argin,datum_code);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_ImportFromUSGS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    ecode2 = SWIG_AsVal_long SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SpatialReference_ImportFromUSGS" "', argument " "2"" of type '" "long""'");
-    } 
-    arg2 = static_cast< long >(val2);
-    if (items > 2) {
-      ecode3 = SWIG_AsVal_long SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-      if (!SWIG_IsOK(ecode3)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_ImportFromUSGS" "', argument " "3"" of type '" "long""'");
-      } 
-      arg3 = static_cast< long >(val3);
-    }
-    if (items > 3) {
-      {
-        /* %typemap(in) (double argin4[ANY]) */
-        if (!(SvROK(ST(3)) && (SvTYPE(SvRV(ST(3)))==SVt_PVAV)))
-        SWIG_croak("Expected a reference to an array.");
-        arg4 = argin4;
-        AV *av = (AV*)(SvRV(ST(3)));
-        for (unsigned int i=0; i<15; i++) {
-          SV **sv = av_fetch(av, i, 0);
-          arg4[i] =  SvNV(*sv);
-        }
-      }
-    }
-    if (items > 4) {
-      ecode5 = SWIG_AsVal_long SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-      if (!SWIG_IsOK(ecode5)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_ImportFromUSGS" "', argument " "5"" of type '" "long""'");
-      } 
-      arg5 = static_cast< long >(val5);
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_ImportFromUSGS(arg1,arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_ImportFromXML) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: SpatialReference_ImportFromXML(self,xmlString);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_ImportFromXML" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_ImportFromXML" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_ImportFromXML(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_ImportFromERM) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    char *arg3 = (char *) 0 ;
-    char *arg4 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int res3 ;
-    char *buf3 = 0 ;
-    int alloc3 = 0 ;
-    int res4 ;
-    char *buf4 = 0 ;
-    int alloc4 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 4) || (items > 4)) {
-      SWIG_croak("Usage: SpatialReference_ImportFromERM(self,proj,datum,units);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_ImportFromERM" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_ImportFromERM" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "SpatialReference_ImportFromERM" "', argument " "3"" of type '" "char const *""'");
-    }
-    arg3 = reinterpret_cast< char * >(buf3);
-    res4 = SWIG_AsCharPtrAndSize(ST(3), &buf4, NULL, &alloc4);
-    if (!SWIG_IsOK(res4)) {
-      SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "SpatialReference_ImportFromERM" "', argument " "4"" of type '" "char const *""'");
-    }
-    arg4 = reinterpret_cast< char * >(buf4);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      if (!arg3) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_ImportFromERM(arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_ImportFromMICoordSys) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: SpatialReference_ImportFromMICoordSys(self,pszCoordSys);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_ImportFromMICoordSys" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_ImportFromMICoordSys" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_ImportFromMICoordSys(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_ImportFromOzi) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char **arg2 = (char **) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: SpatialReference_ImportFromOzi(self,papszLines);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_ImportFromOzi" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      /* %typemap(in) char **options */
-      if (SvOK(ST(1))) {
-        if (SvROK(ST(1))) {
-          if (SvTYPE(SvRV(ST(1)))==SVt_PVAV) {
-            AV *av = (AV*)(SvRV(ST(1)));
-            for (int i = 0; i < av_len(av)+1; i++) {
-              SV *sv = *(av_fetch(av, i, 0));
-              sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-              char *pszItem = SvPV_nolen(sv);
-              arg2 = CSLAddString( arg2, pszItem );
-            }
-          } else if (SvTYPE(SvRV(ST(1)))==SVt_PVHV) {
-            HV *hv = (HV*)SvRV(ST(1));
-            SV *sv;
-            char *key;
-            I32 klen;
-            arg2 = NULL;
-            hv_iterinit(hv);
-            while(sv = hv_iternextsv(hv,&key,&klen)) {
-              sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
-              arg2 = CSLAddNameValue( arg2, key, SvPV_nolen(sv) );
-            }
-          } else
-          SWIG_croak("The 'options' argument is not a reference to an array or a hash.");
-        } else
-        SWIG_croak("The 'options' argument is not a reference.");   
-      }
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_ImportFromOzi(arg1,(char const *const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg2) CSLDestroy( arg2 );
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) char **options */
-      if (arg2) CSLDestroy( arg2 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_ExportToWkt) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char **arg2 = (char **) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    char *argout2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (char **argout2) */
-      arg2 = &argout2;
-    }
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_ExportToWkt(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_ExportToWkt" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_ExportToWkt(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    {
-      /* %typemap(argout) (char **argout) */
-      ST(argvi) = sv_newmortal();
-      if ( arg2 ) {
-        sv_setpv(ST(argvi), *arg2);
-        SvUTF8_on(ST(argvi)); /* expecting UTF-8 from GDAL */
-      }
-      argvi++;
-    }
-    
-    {
-      /* %typemap(freearg) (char **argout) */
-      if ( *arg2 )
-      CPLFree( *arg2 );
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) (char **argout) */
-      if ( *arg2 )
-      CPLFree( *arg2 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_ExportToPrettyWkt) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char **arg2 = (char **) 0 ;
-    int arg3 = (int) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    char *argout2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (char **argout2) */
-      arg2 = &argout2;
-    }
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: SpatialReference_ExportToPrettyWkt(self,simplify);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_ExportToPrettyWkt" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    if (items > 1) {
-      ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val3);
-      if (!SWIG_IsOK(ecode3)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_ExportToPrettyWkt" "', argument " "3"" of type '" "int""'");
-      } 
-      arg3 = static_cast< int >(val3);
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_ExportToPrettyWkt(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    {
-      /* %typemap(argout) (char **argout) */
-      ST(argvi) = sv_newmortal();
-      if ( arg2 ) {
-        sv_setpv(ST(argvi), *arg2);
-        SvUTF8_on(ST(argvi)); /* expecting UTF-8 from GDAL */
-      }
-      argvi++;
-    }
-    
-    {
-      /* %typemap(freearg) (char **argout) */
-      if ( *arg2 )
-      CPLFree( *arg2 );
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) (char **argout) */
-      if ( *arg2 )
-      CPLFree( *arg2 );
-    }
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_ExportToProj4) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char **arg2 = (char **) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    char *argout2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (char **argout2) */
-      arg2 = &argout2;
-    }
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_ExportToProj4(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_ExportToProj4" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_ExportToProj4(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    {
-      /* %typemap(argout) (char **argout) */
-      ST(argvi) = sv_newmortal();
-      if ( arg2 ) {
-        sv_setpv(ST(argvi), *arg2);
-        SvUTF8_on(ST(argvi)); /* expecting UTF-8 from GDAL */
-      }
-      argvi++;
-    }
-    
-    {
-      /* %typemap(freearg) (char **argout) */
-      if ( *arg2 )
-      CPLFree( *arg2 );
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) (char **argout) */
-      if ( *arg2 )
-      CPLFree( *arg2 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_ExportToPCI) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char **arg2 = (char **) 0 ;
-    char **arg3 = (char **) 0 ;
-    double **arg4 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    char *argout2 = 0 ;
-    char *argout3 = 0 ;
-    double *argout4 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (char **argout2) */
-      arg2 = &argout2;
-    }
-    {
-      /* %typemap(in,numinputs=0) (char **argout3) */
-      arg3 = &argout3;
-    }
-    {
-      /* %typemap(in,numinputs=0) (double *argout4[ANY]) */
-      arg4 = &argout4;
-    }
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_ExportToPCI(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_ExportToPCI" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_ExportToPCI(arg1,arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    {
-      /* %typemap(argout) (char **argout) */
-      ST(argvi) = sv_newmortal();
-      if ( arg2 ) {
-        sv_setpv(ST(argvi), *arg2);
-        SvUTF8_on(ST(argvi)); /* expecting UTF-8 from GDAL */
-      }
-      argvi++;
-    }
-    {
-      /* %typemap(argout) (char **argout) */
-      ST(argvi) = sv_newmortal();
-      if ( arg3 ) {
-        sv_setpv(ST(argvi), *arg3);
-        SvUTF8_on(ST(argvi)); /* expecting UTF-8 from GDAL */
-      }
-      argvi++;
-    }
-    {
-      /* %typemap(argout) (double *argout[ANY]) */
-      ST(argvi) = CreateArrayFromDoubleArray( *arg4, 17 );
-      argvi++;
-    }
-    
-    {
-      /* %typemap(freearg) (char **argout) */
-      if ( *arg2 )
-      CPLFree( *arg2 );
-    }
-    {
-      /* %typemap(freearg) (char **argout) */
-      if ( *arg3 )
-      CPLFree( *arg3 );
-    }
-    {
-      /* %typemap(freearg) (double *argout[ANY]) */
-      CPLFree(*arg4);
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) (char **argout) */
-      if ( *arg2 )
-      CPLFree( *arg2 );
-    }
-    {
-      /* %typemap(freearg) (char **argout) */
-      if ( *arg3 )
-      CPLFree( *arg3 );
-    }
-    {
-      /* %typemap(freearg) (double *argout[ANY]) */
-      CPLFree(*arg4);
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_ExportToUSGS) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    long *arg2 = (long *) 0 ;
-    long *arg3 = (long *) 0 ;
-    double **arg4 ;
-    long *arg5 = (long *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    long temp2 ;
-    int res2 = SWIG_TMPOBJ ;
-    long temp3 ;
-    int res3 = SWIG_TMPOBJ ;
-    double *argout4 ;
-    long temp5 ;
-    int res5 = SWIG_TMPOBJ ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    arg2 = &temp2;
-    arg3 = &temp3;
-    {
-      /* %typemap(in,numinputs=0) (double *argout4[ANY]) */
-      arg4 = &argout4;
-    }
-    arg5 = &temp5;
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_ExportToUSGS(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_ExportToUSGS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_ExportToUSGS(arg1,arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    if (SWIG_IsTmpObj(res2)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_long  SWIG_PERL_CALL_ARGS_1((*arg2)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res2) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg2), SWIGTYPE_p_long, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res3)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_long  SWIG_PERL_CALL_ARGS_1((*arg3)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_long, new_flags); argvi++  ;
-    }
-    {
-      /* %typemap(argout) (double *argout[ANY]) */
-      ST(argvi) = CreateArrayFromDoubleArray( *arg4, 15 );
-      argvi++;
-    }
-    if (SWIG_IsTmpObj(res5)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_long  SWIG_PERL_CALL_ARGS_1((*arg5)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res5) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg5), SWIGTYPE_p_long, new_flags); argvi++  ;
-    }
-    
-    
-    
-    {
-      /* %typemap(freearg) (double *argout[ANY]) */
-      CPLFree(*arg4);
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    {
-      /* %typemap(freearg) (double *argout[ANY]) */
-      CPLFree(*arg4);
-    }
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_ExportToXML) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char **arg2 = (char **) 0 ;
-    char *arg3 = (char *) "" ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    char *argout2 = 0 ;
-    int res3 ;
-    char *buf3 = 0 ;
-    int alloc3 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (char **argout2) */
-      arg2 = &argout2;
-    }
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: SpatialReference_ExportToXML(self,dialect);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_ExportToXML" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    if (items > 1) {
-      res3 = SWIG_AsCharPtrAndSize(ST(1), &buf3, NULL, &alloc3);
-      if (!SWIG_IsOK(res3)) {
-        SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "SpatialReference_ExportToXML" "', argument " "3"" of type '" "char const *""'");
-      }
-      arg3 = reinterpret_cast< char * >(buf3);
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_ExportToXML(arg1,arg2,(char const *)arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    {
-      /* %typemap(argout) (char **argout) */
-      ST(argvi) = sv_newmortal();
-      if ( arg2 ) {
-        sv_setpv(ST(argvi), *arg2);
-        SvUTF8_on(ST(argvi)); /* expecting UTF-8 from GDAL */
-      }
-      argvi++;
-    }
-    
-    {
-      /* %typemap(freearg) (char **argout) */
-      if ( *arg2 )
-      CPLFree( *arg2 );
-    }
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) (char **argout) */
-      if ( *arg2 )
-      CPLFree( *arg2 );
-    }
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_ExportToMICoordSys) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char **arg2 = (char **) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    char *argout2 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (char **argout2) */
-      arg2 = &argout2;
-    }
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_ExportToMICoordSys(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_ExportToMICoordSys" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_ExportToMICoordSys(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    {
-      /* %typemap(argout) (char **argout) */
-      ST(argvi) = sv_newmortal();
-      if ( arg2 ) {
-        sv_setpv(ST(argvi), *arg2);
-        SvUTF8_on(ST(argvi)); /* expecting UTF-8 from GDAL */
-      }
-      argvi++;
-    }
-    
-    {
-      /* %typemap(freearg) (char **argout) */
-      if ( *arg2 )
-      CPLFree( *arg2 );
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) (char **argout) */
-      if ( *arg2 )
-      CPLFree( *arg2 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_CloneGeogCS) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OSRSpatialReferenceShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_CloneGeogCS(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_CloneGeogCS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OSRSpatialReferenceShadow *)OSRSpatialReferenceShadow_CloneGeogCS(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OSRSpatialReferenceShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_Clone) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OSRSpatialReferenceShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_Clone(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_Clone" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OSRSpatialReferenceShadow *)OSRSpatialReferenceShadow_Clone(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OSRSpatialReferenceShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_Validate) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_Validate(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_Validate" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_Validate(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_StripCTParms) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_StripCTParms(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_StripCTParms" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_StripCTParms(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_FixupOrdering) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_FixupOrdering(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_FixupOrdering" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_FixupOrdering(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_Fixup) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_Fixup(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_Fixup" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_Fixup(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_MorphToESRI) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_MorphToESRI(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_MorphToESRI" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_MorphToESRI(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SpatialReference_MorphFromESRI) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_MorphFromESRI(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_MorphFromESRI" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_MorphFromESRI(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) SWIG_croak(err); /* this is usually better */
-        SWIG_croak( OGRErrMessages(result) );
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_new_CoordinateTransformation) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    OSRSpatialReferenceShadow *arg2 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    OSRCoordinateTransformationShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: new_CoordinateTransformation(src,dst);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_CoordinateTransformation" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "new_CoordinateTransformation" "', argument " "2"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp2);
-    {
-      CPLErrorReset();
-      result = (OSRCoordinateTransformationShadow *)new_OSRCoordinateTransformationShadow(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OSRCoordinateTransformationShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_delete_CoordinateTransformation) {
-  {
-    OSRCoordinateTransformationShadow *arg1 = (OSRCoordinateTransformationShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: delete_CoordinateTransformation(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRCoordinateTransformationShadow, SWIG_POINTER_DISOWN |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_CoordinateTransformation" "', argument " "1"" of type '" "OSRCoordinateTransformationShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRCoordinateTransformationShadow * >(argp1);
-    {
-      /* %typemap(check) (OSRCoordinateTransformationShadow *) */
-      if (!arg1)
-      SWIG_croak("The coordinate transformation must not be undefined when it is an argument to a Geo::GDAL method");
-    }
-    {
-      CPLErrorReset();
-      delete_OSRCoordinateTransformationShadow(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_CoordinateTransformation_TransformPoint__SWIG_0) {
-  {
-    OSRCoordinateTransformationShadow *arg1 = (OSRCoordinateTransformationShadow *) 0 ;
-    double *arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double argin2[3] ;
-    int argvi = 0;
-    SV * _saved[1] ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: CoordinateTransformation_TransformPoint(self,inout);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRCoordinateTransformationShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CoordinateTransformation_TransformPoint" "', argument " "1"" of type '" "OSRCoordinateTransformationShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRCoordinateTransformationShadow * >(argp1);
-    {
-      /* %typemap(in) (double argin2[ANY]) */
-      if (!(SvROK(ST(1)) && (SvTYPE(SvRV(ST(1)))==SVt_PVAV)))
-      SWIG_croak("Expected a reference to an array.");
-      arg2 = argin2;
-      AV *av = (AV*)(SvRV(ST(1)));
-      for (unsigned int i=0; i<3; i++) {
-        SV **sv = av_fetch(av, i, 0);
-        arg2[i] =  SvNV(*sv);
-      }
-    }
-    {
-      /* %typemap(check) (OSRCoordinateTransformationShadow *) */
-      if (!arg1)
-      SWIG_croak("The coordinate transformation must not be undefined when it is an argument to a Geo::GDAL method");
-    }
-    _saved[0] = ST(1);
-    {
-      CPLErrorReset();
-      OSRCoordinateTransformationShadow_TransformPoint__SWIG_0(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    {
-      /* %typemap(argout) (double argout[ANY]) */
-      if (GIMME_V == G_ARRAY) {
-        /* return a list */
-        int i;
-        EXTEND(SP, argvi+3-items+1);
-        for (i = 0; i < 3; i++)
-        ST(argvi++) = sv_2mortal(newSVnv(arg2[i]));
-      } else {
-        ST(argvi) = CreateArrayFromDoubleArray( arg2, 3 );
-        argvi++;
-      }  
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_CoordinateTransformation_TransformPoint__SWIG_1) {
-  {
-    OSRCoordinateTransformationShadow *arg1 = (OSRCoordinateTransformationShadow *) 0 ;
-    double *arg2 ;
-    double arg3 ;
-    double arg4 ;
-    double arg5 = (double) 0.0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    double argout2[3] ;
-    double val3 ;
-    int ecode3 = 0 ;
-    double val4 ;
-    int ecode4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (double argout2[ANY]) */
-      arg2 = argout2;
-    }
-    if ((items < 3) || (items > 4)) {
-      SWIG_croak("Usage: CoordinateTransformation_TransformPoint(self,x,y,z);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRCoordinateTransformationShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CoordinateTransformation_TransformPoint" "', argument " "1"" of type '" "OSRCoordinateTransformationShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRCoordinateTransformationShadow * >(argp1);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "CoordinateTransformation_TransformPoint" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "CoordinateTransformation_TransformPoint" "', argument " "4"" of type '" "double""'");
-    } 
-    arg4 = static_cast< double >(val4);
-    if (items > 3) {
-      ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val5);
-      if (!SWIG_IsOK(ecode5)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "CoordinateTransformation_TransformPoint" "', argument " "5"" of type '" "double""'");
-      } 
-      arg5 = static_cast< double >(val5);
-    }
-    {
-      /* %typemap(check) (OSRCoordinateTransformationShadow *) */
-      if (!arg1)
-      SWIG_croak("The coordinate transformation must not be undefined when it is an argument to a Geo::GDAL method");
-    }
-    {
-      CPLErrorReset();
-      OSRCoordinateTransformationShadow_TransformPoint__SWIG_1(arg1,arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    {
-      /* %typemap(argout) (double argout[ANY]) */
-      if (GIMME_V == G_ARRAY) {
-        /* return a list */
-        int i;
-        EXTEND(SP, argvi+3-items+1);
-        for (i = 0; i < 3; i++)
-        ST(argvi++) = sv_2mortal(newSVnv(arg2[i]));
-      } else {
-        ST(argvi) = CreateArrayFromDoubleArray( arg2, 3 );
-        argvi++;
-      }  
-    }
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_CoordinateTransformation_TransformPoint) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OSRCoordinateTransformationShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(1), &vptr, SWIGTYPE_p_double, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if ((items >= 3) && (items <= 4)) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OSRCoordinateTransformationShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (items > 3) {
-        {
-          {
-            int res = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), NULL);
-            _v = SWIG_CheckState(res);
-          }
-        }
-        if (!_v) goto check_2;
-        _ranki += _v*_pi;
-        _rankm += _pi;
-        _pi *= SWIG_MAXCASTRANK;
-      }
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_CoordinateTransformation_TransformPoint__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_CoordinateTransformation_TransformPoint__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'CoordinateTransformation_TransformPoint'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_CoordinateTransformation__TransformPoints) {
-  {
-    OSRCoordinateTransformationShadow *arg1 = (OSRCoordinateTransformationShadow *) 0 ;
-    int arg2 ;
-    double *arg3 = (double *) 0 ;
-    double *arg4 = (double *) 0 ;
-    double *arg5 = (double *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    SV * _saved[1] ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: CoordinateTransformation__TransformPoints(self,nCount,x,y,z);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRCoordinateTransformationShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CoordinateTransformation__TransformPoints" "', argument " "1"" of type '" "OSRCoordinateTransformationShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRCoordinateTransformationShadow * >(argp1);
-    {
-      /* %typemap(in) (int nCount, double *x, double *y, double *z) */
-      /* ST(1) is a ref to a list of refs to point lists */
-      if (! (SvROK(ST(1)) && (SvTYPE(SvRV(ST(1)))==SVt_PVAV)))
-      SWIG_croak("Expected a reference to an array.");
-      AV *av = (AV*)(SvRV(ST(1)));
-      arg2 = av_len(av)+1;
-      arg3 = (double*)CPLMalloc(arg2*sizeof(double));
-      if (arg3)
-      arg4 = (double*)CPLMalloc(arg2*sizeof(double));
-      if (arg3 && arg4)
-      arg5 = (double*)CPLMalloc(arg2*sizeof(double));
-      if (!arg3 or !arg4 or !arg5)
-      SWIG_fail;
-      for (int i = 0; i < arg2; i++) {
-        SV **sv = av_fetch(av, i, 0); /* ref to one point list */
-        if (!(SvROK(*sv) && (SvTYPE(SvRV(*sv))==SVt_PVAV)))
-        SWIG_croak("An item in the list is not a reference to an array.");
-        AV *ac = (AV*)(SvRV(*sv));
-        int n = av_len(ac)+1;
-        SV **c = av_fetch(ac, 0, 0);
-        arg3[i] = SvNV(*c);
-        c = av_fetch(ac, 1, 0);
-        arg4[i] = SvNV(*c);
-        if (n < 3) {
-          arg5[i] = 0;
-        } else {
-          c = av_fetch(ac, 2, 0);
-          arg5[i] = SvNV(*c);
-        }
-      }
-    }
-    {
-      /* %typemap(check) (OSRCoordinateTransformationShadow *) */
-      if (!arg1)
-      SWIG_croak("The coordinate transformation must not be undefined when it is an argument to a Geo::GDAL method");
-    }
-    _saved[0] = ST(1);
-    {
-      CPLErrorReset();
-      OSRCoordinateTransformationShadow_TransformPoints(arg1,arg2,arg3,arg4,arg5);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    {
-      /* %typemap(argout) (int nCount, double *x, double *y, double *z) */
-      AV *av = (AV*)(SvRV(_saved[0]));
-      for (int i = 0; i < arg2; i++) {
-        SV **sv = av_fetch(av, i, 0);
-        AV *ac = (AV*)(SvRV(*sv));
-        int n = av_len(ac)+1;
-        SV *c = newSVnv(arg3[i]);
-        if (!av_store(ac, 0, c))
-        SvREFCNT_dec(c);
-        c = newSVnv(arg4[i]);
-        if (!av_store(ac, 1, c))
-        SvREFCNT_dec(c);
-        c = newSVnv(arg5[i]);
-        if (!av_store(ac, 2, c))
-        SvREFCNT_dec(c);
-      }
-    }
-    
-    {
-      /* %typemap(freearg) (int nCount, double *x, double *y, double *z) */
-      CPLFree(arg3);
-      CPLFree(arg4);
-      CPLFree(arg5);
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) (int nCount, double *x, double *y, double *z) */
-      CPLFree(arg3);
-      CPLFree(arg4);
-      CPLFree(arg5);
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_CreateCoordinateTransformation) {
-  {
-    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    OSRSpatialReferenceShadow *arg2 = (OSRSpatialReferenceShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    void *argp2 = 0 ;
-    int res2 = 0 ;
-    int argvi = 0;
-    OSRCoordinateTransformationShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: CreateCoordinateTransformation(src,dst);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CreateCoordinateTransformation" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "CreateCoordinateTransformation" "', argument " "2"" of type '" "OSRSpatialReferenceShadow *""'"); 
-    }
-    arg2 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp2);
-    {
-      CPLErrorReset();
-      result = (OSRCoordinateTransformationShadow *)CreateCoordinateTransformation(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /* 
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OSRCoordinateTransformationShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-
-/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */
-
-static swig_type_info _swigt__p_OSRCoordinateTransformationShadow = {"_p_OSRCoordinateTransformationShadow", "OSRCoordinateTransformationShadow *", 0, 0, (void*)"Geo::OSR::CoordinateTransformation", 0};
-static swig_type_info _swigt__p_OSRSpatialReferenceShadow = {"_p_OSRSpatialReferenceShadow", "OSRSpatialReferenceShadow *", 0, 0, (void*)"Geo::OSR::SpatialReference", 0};
-static swig_type_info _swigt__p_char = {"_p_char", "char *|retStringAndCPLFree *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_double = {"_p_double", "double *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_int = {"_p_int", "int *|OGRErr *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_long = {"_p_long", "long *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_p_char = {"_p_p_char", "char **", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_p_double = {"_p_p_double", "double **", 0, 0, (void*)0, 0};
-
-static swig_type_info *swig_type_initial[] = {
-  &_swigt__p_OSRCoordinateTransformationShadow,
-  &_swigt__p_OSRSpatialReferenceShadow,
-  &_swigt__p_char,
-  &_swigt__p_double,
-  &_swigt__p_int,
-  &_swigt__p_long,
-  &_swigt__p_p_char,
-  &_swigt__p_p_double,
-};
-
-static swig_cast_info _swigc__p_OSRCoordinateTransformationShadow[] = {  {&_swigt__p_OSRCoordinateTransformationShadow, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_OSRSpatialReferenceShadow[] = {  {&_swigt__p_OSRSpatialReferenceShadow, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_char[] = {  {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_double[] = {  {&_swigt__p_double, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_int[] = {  {&_swigt__p_int, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_long[] = {  {&_swigt__p_long, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_p_char[] = {  {&_swigt__p_p_char, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_p_double[] = {  {&_swigt__p_p_double, 0, 0, 0},{0, 0, 0, 0}};
-
-static swig_cast_info *swig_cast_initial[] = {
-  _swigc__p_OSRCoordinateTransformationShadow,
-  _swigc__p_OSRSpatialReferenceShadow,
-  _swigc__p_char,
-  _swigc__p_double,
-  _swigc__p_int,
-  _swigc__p_long,
-  _swigc__p_p_char,
-  _swigc__p_p_double,
-};
-
-
-/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */
-
-static swig_constant_info swig_constants[] = {
-{0,0,0,0,0,0}
-};
-#ifdef __cplusplus
-}
-#endif
-static swig_variable_info swig_variables[] = {
-{0,0,0,0}
-};
-static swig_command_info swig_commands[] = {
-{"Geo::OSRc::UseExceptions", _wrap_UseExceptions},
-{"Geo::OSRc::DontUseExceptions", _wrap_DontUseExceptions},
-{"Geo::OSRc::GetWellKnownGeogCSAsWKT", _wrap_GetWellKnownGeogCSAsWKT},
-{"Geo::OSRc::GetUserInputAsWKT", _wrap_GetUserInputAsWKT},
-{"Geo::OSRc::GetProjectionMethods", _wrap_GetProjectionMethods},
-{"Geo::OSRc::GetProjectionMethodParameterList", _wrap_GetProjectionMethodParameterList},
-{"Geo::OSRc::GetProjectionMethodParamInfo", _wrap_GetProjectionMethodParamInfo},
-{"Geo::OSRc::new_SpatialReference", _wrap_new_SpatialReference},
-{"Geo::OSRc::delete_SpatialReference", _wrap_delete_SpatialReference},
-{"Geo::OSRc::SpatialReference_IsSame", _wrap_SpatialReference_IsSame},
-{"Geo::OSRc::SpatialReference_IsSameGeogCS", _wrap_SpatialReference_IsSameGeogCS},
-{"Geo::OSRc::SpatialReference_IsSameVertCS", _wrap_SpatialReference_IsSameVertCS},
-{"Geo::OSRc::SpatialReference_IsGeographic", _wrap_SpatialReference_IsGeographic},
-{"Geo::OSRc::SpatialReference_IsProjected", _wrap_SpatialReference_IsProjected},
-{"Geo::OSRc::SpatialReference_IsCompound", _wrap_SpatialReference_IsCompound},
-{"Geo::OSRc::SpatialReference_IsGeocentric", _wrap_SpatialReference_IsGeocentric},
-{"Geo::OSRc::SpatialReference_IsLocal", _wrap_SpatialReference_IsLocal},
-{"Geo::OSRc::SpatialReference_IsVertical", _wrap_SpatialReference_IsVertical},
-{"Geo::OSRc::SpatialReference_EPSGTreatsAsLatLong", _wrap_SpatialReference_EPSGTreatsAsLatLong},
-{"Geo::OSRc::SpatialReference_EPSGTreatsAsNorthingEasting", _wrap_SpatialReference_EPSGTreatsAsNorthingEasting},
-{"Geo::OSRc::SpatialReference_SetAuthority", _wrap_SpatialReference_SetAuthority},
-{"Geo::OSRc::SpatialReference_GetAttrValue", _wrap_SpatialReference_GetAttrValue},
-{"Geo::OSRc::SpatialReference_SetAttrValue", _wrap_SpatialReference_SetAttrValue},
-{"Geo::OSRc::SpatialReference_SetAngularUnits", _wrap_SpatialReference_SetAngularUnits},
-{"Geo::OSRc::SpatialReference_GetAngularUnits", _wrap_SpatialReference_GetAngularUnits},
-{"Geo::OSRc::SpatialReference_SetTargetLinearUnits", _wrap_SpatialReference_SetTargetLinearUnits},
-{"Geo::OSRc::SpatialReference_SetLinearUnits", _wrap_SpatialReference_SetLinearUnits},
-{"Geo::OSRc::SpatialReference_SetLinearUnitsAndUpdateParameters", _wrap_SpatialReference_SetLinearUnitsAndUpdateParameters},
-{"Geo::OSRc::SpatialReference_GetLinearUnits", _wrap_SpatialReference_GetLinearUnits},
-{"Geo::OSRc::SpatialReference_GetLinearUnitsName", _wrap_SpatialReference_GetLinearUnitsName},
-{"Geo::OSRc::SpatialReference_GetAuthorityCode", _wrap_SpatialReference_GetAuthorityCode},
-{"Geo::OSRc::SpatialReference_GetAuthorityName", _wrap_SpatialReference_GetAuthorityName},
-{"Geo::OSRc::SpatialReference_SetUTM", _wrap_SpatialReference_SetUTM},
-{"Geo::OSRc::SpatialReference__GetUTMZone", _wrap_SpatialReference__GetUTMZone},
-{"Geo::OSRc::SpatialReference_SetStatePlane", _wrap_SpatialReference_SetStatePlane},
-{"Geo::OSRc::SpatialReference_AutoIdentifyEPSG", _wrap_SpatialReference_AutoIdentifyEPSG},
-{"Geo::OSRc::SpatialReference_SetProjection", _wrap_SpatialReference_SetProjection},
-{"Geo::OSRc::SpatialReference_SetProjParm", _wrap_SpatialReference_SetProjParm},
-{"Geo::OSRc::SpatialReference_GetProjParm", _wrap_SpatialReference_GetProjParm},
-{"Geo::OSRc::SpatialReference_SetNormProjParm", _wrap_SpatialReference_SetNormProjParm},
-{"Geo::OSRc::SpatialReference_GetNormProjParm", _wrap_SpatialReference_GetNormProjParm},
-{"Geo::OSRc::SpatialReference_GetSemiMajor", _wrap_SpatialReference_GetSemiMajor},
-{"Geo::OSRc::SpatialReference_GetSemiMinor", _wrap_SpatialReference_GetSemiMinor},
-{"Geo::OSRc::SpatialReference_GetInvFlattening", _wrap_SpatialReference_GetInvFlattening},
-{"Geo::OSRc::SpatialReference_SetACEA", _wrap_SpatialReference_SetACEA},
-{"Geo::OSRc::SpatialReference_SetAE", _wrap_SpatialReference_SetAE},
-{"Geo::OSRc::SpatialReference_SetBonne", _wrap_SpatialReference_SetBonne},
-{"Geo::OSRc::SpatialReference_SetCEA", _wrap_SpatialReference_SetCEA},
-{"Geo::OSRc::SpatialReference_SetCS", _wrap_SpatialReference_SetCS},
-{"Geo::OSRc::SpatialReference_SetEC", _wrap_SpatialReference_SetEC},
-{"Geo::OSRc::SpatialReference_SetEckertIV", _wrap_SpatialReference_SetEckertIV},
-{"Geo::OSRc::SpatialReference_SetEckertVI", _wrap_SpatialReference_SetEckertVI},
-{"Geo::OSRc::SpatialReference_SetEquirectangular", _wrap_SpatialReference_SetEquirectangular},
-{"Geo::OSRc::SpatialReference_SetEquirectangular2", _wrap_SpatialReference_SetEquirectangular2},
-{"Geo::OSRc::SpatialReference_SetGaussSchreiberTMercator", _wrap_SpatialReference_SetGaussSchreiberTMercator},
-{"Geo::OSRc::SpatialReference_SetGS", _wrap_SpatialReference_SetGS},
-{"Geo::OSRc::SpatialReference_SetGH", _wrap_SpatialReference_SetGH},
-{"Geo::OSRc::SpatialReference_SetIGH", _wrap_SpatialReference_SetIGH},
-{"Geo::OSRc::SpatialReference_SetGEOS", _wrap_SpatialReference_SetGEOS},
-{"Geo::OSRc::SpatialReference_SetGnomonic", _wrap_SpatialReference_SetGnomonic},
-{"Geo::OSRc::SpatialReference_SetHOM", _wrap_SpatialReference_SetHOM},
-{"Geo::OSRc::SpatialReference_SetHOM2PNO", _wrap_SpatialReference_SetHOM2PNO},
-{"Geo::OSRc::SpatialReference_SetKrovak", _wrap_SpatialReference_SetKrovak},
-{"Geo::OSRc::SpatialReference_SetLAEA", _wrap_SpatialReference_SetLAEA},
-{"Geo::OSRc::SpatialReference_SetLCC", _wrap_SpatialReference_SetLCC},
-{"Geo::OSRc::SpatialReference_SetLCC1SP", _wrap_SpatialReference_SetLCC1SP},
-{"Geo::OSRc::SpatialReference_SetLCCB", _wrap_SpatialReference_SetLCCB},
-{"Geo::OSRc::SpatialReference_SetMC", _wrap_SpatialReference_SetMC},
-{"Geo::OSRc::SpatialReference_SetMercator", _wrap_SpatialReference_SetMercator},
-{"Geo::OSRc::SpatialReference_SetMollweide", _wrap_SpatialReference_SetMollweide},
-{"Geo::OSRc::SpatialReference_SetNZMG", _wrap_SpatialReference_SetNZMG},
-{"Geo::OSRc::SpatialReference_SetOS", _wrap_SpatialReference_SetOS},
-{"Geo::OSRc::SpatialReference_SetOrthographic", _wrap_SpatialReference_SetOrthographic},
-{"Geo::OSRc::SpatialReference_SetPolyconic", _wrap_SpatialReference_SetPolyconic},
-{"Geo::OSRc::SpatialReference_SetPS", _wrap_SpatialReference_SetPS},
-{"Geo::OSRc::SpatialReference_SetRobinson", _wrap_SpatialReference_SetRobinson},
-{"Geo::OSRc::SpatialReference_SetSinusoidal", _wrap_SpatialReference_SetSinusoidal},
-{"Geo::OSRc::SpatialReference_SetStereographic", _wrap_SpatialReference_SetStereographic},
-{"Geo::OSRc::SpatialReference_SetSOC", _wrap_SpatialReference_SetSOC},
-{"Geo::OSRc::SpatialReference_SetTM", _wrap_SpatialReference_SetTM},
-{"Geo::OSRc::SpatialReference_SetTMVariant", _wrap_SpatialReference_SetTMVariant},
-{"Geo::OSRc::SpatialReference_SetTMG", _wrap_SpatialReference_SetTMG},
-{"Geo::OSRc::SpatialReference_SetTMSO", _wrap_SpatialReference_SetTMSO},
-{"Geo::OSRc::SpatialReference_SetVDG", _wrap_SpatialReference_SetVDG},
-{"Geo::OSRc::SpatialReference_SetWellKnownGeogCS", _wrap_SpatialReference_SetWellKnownGeogCS},
-{"Geo::OSRc::SpatialReference_SetFromUserInput", _wrap_SpatialReference_SetFromUserInput},
-{"Geo::OSRc::SpatialReference_CopyGeogCSFrom", _wrap_SpatialReference_CopyGeogCSFrom},
-{"Geo::OSRc::SpatialReference_SetTOWGS84", _wrap_SpatialReference_SetTOWGS84},
-{"Geo::OSRc::SpatialReference_GetTOWGS84", _wrap_SpatialReference_GetTOWGS84},
-{"Geo::OSRc::SpatialReference_SetLocalCS", _wrap_SpatialReference_SetLocalCS},
-{"Geo::OSRc::SpatialReference_SetGeogCS", _wrap_SpatialReference_SetGeogCS},
-{"Geo::OSRc::SpatialReference_SetProjCS", _wrap_SpatialReference_SetProjCS},
-{"Geo::OSRc::SpatialReference_SetGeocCS", _wrap_SpatialReference_SetGeocCS},
-{"Geo::OSRc::SpatialReference_SetVertCS", _wrap_SpatialReference_SetVertCS},
-{"Geo::OSRc::SpatialReference_SetCompoundCS", _wrap_SpatialReference_SetCompoundCS},
-{"Geo::OSRc::SpatialReference_ImportFromWkt", _wrap_SpatialReference_ImportFromWkt},
-{"Geo::OSRc::SpatialReference_ImportFromProj4", _wrap_SpatialReference_ImportFromProj4},
-{"Geo::OSRc::SpatialReference_ImportFromUrl", _wrap_SpatialReference_ImportFromUrl},
-{"Geo::OSRc::SpatialReference_ImportFromESRI", _wrap_SpatialReference_ImportFromESRI},
-{"Geo::OSRc::SpatialReference_ImportFromEPSG", _wrap_SpatialReference_ImportFromEPSG},
-{"Geo::OSRc::SpatialReference_ImportFromEPSGA", _wrap_SpatialReference_ImportFromEPSGA},
-{"Geo::OSRc::SpatialReference_ImportFromPCI", _wrap_SpatialReference_ImportFromPCI},
-{"Geo::OSRc::SpatialReference_ImportFromUSGS", _wrap_SpatialReference_ImportFromUSGS},
-{"Geo::OSRc::SpatialReference_ImportFromXML", _wrap_SpatialReference_ImportFromXML},
-{"Geo::OSRc::SpatialReference_ImportFromERM", _wrap_SpatialReference_ImportFromERM},
-{"Geo::OSRc::SpatialReference_ImportFromMICoordSys", _wrap_SpatialReference_ImportFromMICoordSys},
-{"Geo::OSRc::SpatialReference_ImportFromOzi", _wrap_SpatialReference_ImportFromOzi},
-{"Geo::OSRc::SpatialReference_ExportToWkt", _wrap_SpatialReference_ExportToWkt},
-{"Geo::OSRc::SpatialReference_ExportToPrettyWkt", _wrap_SpatialReference_ExportToPrettyWkt},
-{"Geo::OSRc::SpatialReference_ExportToProj4", _wrap_SpatialReference_ExportToProj4},
-{"Geo::OSRc::SpatialReference_ExportToPCI", _wrap_SpatialReference_ExportToPCI},
-{"Geo::OSRc::SpatialReference_ExportToUSGS", _wrap_SpatialReference_ExportToUSGS},
-{"Geo::OSRc::SpatialReference_ExportToXML", _wrap_SpatialReference_ExportToXML},
-{"Geo::OSRc::SpatialReference_ExportToMICoordSys", _wrap_SpatialReference_ExportToMICoordSys},
-{"Geo::OSRc::SpatialReference_CloneGeogCS", _wrap_SpatialReference_CloneGeogCS},
-{"Geo::OSRc::SpatialReference_Clone", _wrap_SpatialReference_Clone},
-{"Geo::OSRc::SpatialReference_Validate", _wrap_SpatialReference_Validate},
-{"Geo::OSRc::SpatialReference_StripCTParms", _wrap_SpatialReference_StripCTParms},
-{"Geo::OSRc::SpatialReference_FixupOrdering", _wrap_SpatialReference_FixupOrdering},
-{"Geo::OSRc::SpatialReference_Fixup", _wrap_SpatialReference_Fixup},
-{"Geo::OSRc::SpatialReference_MorphToESRI", _wrap_SpatialReference_MorphToESRI},
-{"Geo::OSRc::SpatialReference_MorphFromESRI", _wrap_SpatialReference_MorphFromESRI},
-{"Geo::OSRc::new_CoordinateTransformation", _wrap_new_CoordinateTransformation},
-{"Geo::OSRc::delete_CoordinateTransformation", _wrap_delete_CoordinateTransformation},
-{"Geo::OSRc::CoordinateTransformation_TransformPoint", _wrap_CoordinateTransformation_TransformPoint},
-{"Geo::OSRc::CoordinateTransformation__TransformPoints", _wrap_CoordinateTransformation__TransformPoints},
-{"Geo::OSRc::CreateCoordinateTransformation", _wrap_CreateCoordinateTransformation},
-{0,0}
-};
-/* -----------------------------------------------------------------------------
- * Type initialization:
- * This problem is tough by the requirement that no dynamic
- * memory is used. Also, since swig_type_info structures store pointers to
- * swig_cast_info structures and swig_cast_info structures store pointers back
- * to swig_type_info structures, we need some lookup code at initialization.
- * The idea is that swig generates all the structures that are needed.
- * The runtime then collects these partially filled structures.
- * The SWIG_InitializeModule function takes these initial arrays out of
- * swig_module, and does all the lookup, filling in the swig_module.types
- * array with the correct data and linking the correct swig_cast_info
- * structures together.
- *
- * The generated swig_type_info structures are assigned staticly to an initial
- * array. We just loop through that array, and handle each type individually.
- * First we lookup if this type has been already loaded, and if so, use the
- * loaded structure instead of the generated one. Then we have to fill in the
- * cast linked list. The cast data is initially stored in something like a
- * two-dimensional array. Each row corresponds to a type (there are the same
- * number of rows as there are in the swig_type_initial array). Each entry in
- * a column is one of the swig_cast_info structures for that type.
- * The cast_initial array is actually an array of arrays, because each row has
- * a variable number of columns. So to actually build the cast linked list,
- * we find the array of casts associated with the type, and loop through it
- * adding the casts to the list. The one last trick we need to do is making
- * sure the type pointer in the swig_cast_info struct is correct.
- *
- * First off, we lookup the cast->type name to see if it is already loaded.
- * There are three cases to handle:
- *  1) If the cast->type has already been loaded AND the type we are adding
- *     casting info to has not been loaded (it is in this module), THEN we
- *     replace the cast->type pointer with the type pointer that has already
- *     been loaded.
- *  2) If BOTH types (the one we are adding casting info to, and the
- *     cast->type) are loaded, THEN the cast info has already been loaded by
- *     the previous module so we just ignore it.
- *  3) Finally, if cast->type has not already been loaded, then we add that
- *     swig_cast_info to the linked list (because the cast->type) pointer will
- *     be correct.
- * ----------------------------------------------------------------------------- */
-
-#ifdef __cplusplus
-extern "C" {
-#if 0
-} /* c-mode */
-#endif
-#endif
-
-#if 0
-#define SWIGRUNTIME_DEBUG
-#endif
-
-
-SWIGRUNTIME void
-SWIG_InitializeModule(void *clientdata) {
-  size_t i;
-  swig_module_info *module_head, *iter;
-  int found, init;
-  
-  /* check to see if the circular list has been setup, if not, set it up */
-  if (swig_module.next==0) {
-    /* Initialize the swig_module */
-    swig_module.type_initial = swig_type_initial;
-    swig_module.cast_initial = swig_cast_initial;
-    swig_module.next = &swig_module;
-    init = 1;
-  } else {
-    init = 0;
-  }
-  
-  /* Try and load any already created modules */
-  module_head = SWIG_GetModule(clientdata);
-  if (!module_head) {
-    /* This is the first module loaded for this interpreter */
-    /* so set the swig module into the interpreter */
-    SWIG_SetModule(clientdata, &swig_module);
-    module_head = &swig_module;
-  } else {
-    /* the interpreter has loaded a SWIG module, but has it loaded this one? */
-    found=0;
-    iter=module_head;
-    do {
-      if (iter==&swig_module) {
-        found=1;
-        break;
-      }
-      iter=iter->next;
-    } while (iter!= module_head);
-    
-    /* if the is found in the list, then all is done and we may leave */
-    if (found) return;
-    /* otherwise we must add out module into the list */
-    swig_module.next = module_head->next;
-    module_head->next = &swig_module;
-  }
-  
-  /* When multiple interpreters are used, a module could have already been initialized in
-       a different interpreter, but not yet have a pointer in this interpreter.
-       In this case, we do not want to continue adding types... everything should be
-       set up already */
-  if (init == 0) return;
-  
-  /* Now work on filling in swig_module.types */
-#ifdef SWIGRUNTIME_DEBUG
-  printf("SWIG_InitializeModule: size %d\n", swig_module.size);
-#endif
-  for (i = 0; i < swig_module.size; ++i) {
-    swig_type_info *type = 0;
-    swig_type_info *ret;
-    swig_cast_info *cast;
-    
-#ifdef SWIGRUNTIME_DEBUG
-    printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name);
-#endif
-    
-    /* if there is another module already loaded */
-    if (swig_module.next != &swig_module) {
-      type = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, swig_module.type_initial[i]->name);
-    }
-    if (type) {
-      /* Overwrite clientdata field */
-#ifdef SWIGRUNTIME_DEBUG
-      printf("SWIG_InitializeModule: found type %s\n", type->name);
-#endif
-      if (swig_module.type_initial[i]->clientdata) {
-        type->clientdata = swig_module.type_initial[i]->clientdata;
-#ifdef SWIGRUNTIME_DEBUG
-        printf("SWIG_InitializeModule: found and overwrite type %s \n", type->name);
-#endif
-      }
-    } else {
-      type = swig_module.type_initial[i];
-    }
-    
-    /* Insert casting types */
-    cast = swig_module.cast_initial[i];
-    while (cast->type) {
-      /* Don't need to add information already in the list */
-      ret = 0;
-#ifdef SWIGRUNTIME_DEBUG
-      printf("SWIG_InitializeModule: look cast %s\n", cast->type->name);
-#endif
-      if (swig_module.next != &swig_module) {
-        ret = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, cast->type->name);
-#ifdef SWIGRUNTIME_DEBUG
-        if (ret) printf("SWIG_InitializeModule: found cast %s\n", ret->name);
-#endif
-      }
-      if (ret) {
-        if (type == swig_module.type_initial[i]) {
-#ifdef SWIGRUNTIME_DEBUG
-          printf("SWIG_InitializeModule: skip old type %s\n", ret->name);
-#endif
-          cast->type = ret;
-          ret = 0;
-        } else {
-          /* Check for casting already in the list */
-          swig_cast_info *ocast = SWIG_TypeCheck(ret->name, type);
-#ifdef SWIGRUNTIME_DEBUG
-          if (ocast) printf("SWIG_InitializeModule: skip old cast %s\n", ret->name);
-#endif
-          if (!ocast) ret = 0;
-        }
-      }
-      
-      if (!ret) {
-#ifdef SWIGRUNTIME_DEBUG
-        printf("SWIG_InitializeModule: adding cast %s\n", cast->type->name);
-#endif
-        if (type->cast) {
-          type->cast->prev = cast;
-          cast->next = type->cast;
-        }
-        type->cast = cast;
-      }
-      cast++;
-    }
-    /* Set entry in modules->types array equal to the type */
-    swig_module.types[i] = type;
-  }
-  swig_module.types[i] = 0;
-  
-#ifdef SWIGRUNTIME_DEBUG
-  printf("**** SWIG_InitializeModule: Cast List ******\n");
-  for (i = 0; i < swig_module.size; ++i) {
-    int j = 0;
-    swig_cast_info *cast = swig_module.cast_initial[i];
-    printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name);
-    while (cast->type) {
-      printf("SWIG_InitializeModule: cast type %s\n", cast->type->name);
-      cast++;
-      ++j;
-    }
-    printf("---- Total casts: %d\n",j);
-  }
-  printf("**** SWIG_InitializeModule: Cast List ******\n");
-#endif
-}
-
-/* This function will propagate the clientdata field of type to
-* any new swig_type_info structures that have been added into the list
-* of equivalent types.  It is like calling
-* SWIG_TypeClientData(type, clientdata) a second time.
-*/
-SWIGRUNTIME void
-SWIG_PropagateClientData(void) {
-  size_t i;
-  swig_cast_info *equiv;
-  static int init_run = 0;
-  
-  if (init_run) return;
-  init_run = 1;
-  
-  for (i = 0; i < swig_module.size; i++) {
-    if (swig_module.types[i]->clientdata) {
-      equiv = swig_module.types[i]->cast;
-      while (equiv) {
-        if (!equiv->converter) {
-          if (equiv->type && !equiv->type->clientdata)
-          SWIG_TypeClientData(equiv->type, swig_module.types[i]->clientdata);
-        }
-        equiv = equiv->next;
-      }
-    }
-  }
-}
-
-#ifdef __cplusplus
-#if 0
-{
-  /* c-mode */
-#endif
-}
-#endif
-
-
-
-#ifdef __cplusplus
-extern "C"
-#endif
-
-XS(SWIG_init) {
-  dXSARGS;
-  int i;
-  
-  SWIG_InitializeModule(0);
-  
-  /* Install commands */
-  for (i = 0; swig_commands[i].name; i++) {
-    /* Casts only needed for Perl < 5.10. */
-#ifdef __cplusplus
-    newXS(const_cast<char*>(swig_commands[i].name), swig_commands[i].wrapper, const_cast<char*>(__FILE__));
-#else
-    newXS((char*)swig_commands[i].name, swig_commands[i].wrapper, (char*)__FILE__);
-#endif
-  }
-  
-  /* Install variables */
-  for (i = 0; swig_variables[i].name; i++) {
-    SV *sv;
-    sv = get_sv(swig_variables[i].name, TRUE | 0x2 | GV_ADDMULTI);
-    if (swig_variables[i].type) {
-      SWIG_MakePtr(sv,(void *)1, *swig_variables[i].type,0);
-    } else {
-      sv_setiv(sv,(IV) 0);
-    }
-    swig_create_magic(sv, swig_variables[i].name, swig_variables[i].set, swig_variables[i].get); 
-  }
-  
-  /* Install constant */
-  for (i = 0; swig_constants[i].type; i++) {
-    SV *sv;
-    sv = get_sv(swig_constants[i].name, TRUE | 0x2 | GV_ADDMULTI);
-    switch(swig_constants[i].type) {
-    case SWIG_INT:
-      sv_setiv(sv, (IV) swig_constants[i].lvalue);
-      break;
-    case SWIG_FLOAT:
-      sv_setnv(sv, (double) swig_constants[i].dvalue);
-      break;
-    case SWIG_STRING:
-      sv_setpv(sv, (const char *) swig_constants[i].pvalue);
-      break;
-    case SWIG_POINTER:
-      SWIG_MakePtr(sv, swig_constants[i].pvalue, *(swig_constants[i].ptype),0);
-      break;
-    case SWIG_BINARY:
-      SWIG_MakePackedObj(sv, swig_constants[i].pvalue, swig_constants[i].lvalue, *(swig_constants[i].ptype));
-      break;
-    default:
-      break;
-    }
-    SvREADONLY_on(sv);
-  }
-  
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_WKT_WGS84", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9108\"]],AUTHORITY[\"EPSG\",\"4326\"]]"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_ALBERS_CONIC_EQUAL_AREA", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Albers_Conic_Equal_Area"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_AZIMUTHAL_EQUIDISTANT", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Azimuthal_Equidistant"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_CASSINI_SOLDNER", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Cassini_Soldner"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_CYLINDRICAL_EQUAL_AREA", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Cylindrical_Equal_Area"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_BONNE", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Bonne"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_ECKERT_I", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Eckert_I"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_ECKERT_II", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Eckert_II"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_ECKERT_III", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Eckert_III"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_ECKERT_IV", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Eckert_IV"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_ECKERT_V", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Eckert_V"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_ECKERT_VI", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Eckert_VI"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_EQUIDISTANT_CONIC", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Equidistant_Conic"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_EQUIRECTANGULAR", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Equirectangular"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_GALL_STEREOGRAPHIC", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Gall_Stereographic"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_GAUSSSCHREIBERTMERCATOR", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Gauss_Schreiber_Transverse_Mercator"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_GEOSTATIONARY_SATELLITE", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Geostationary_Satellite"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_GOODE_HOMOLOSINE", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Goode_Homolosine"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_IGH", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Interrupted_Goode_Homolosine"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_GNOMONIC", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Gnomonic"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Hotine_Oblique_Mercator_Azimuth_Center"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_HOTINE_OBLIQUE_MERCATOR", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Hotine_Oblique_Mercator"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Hotine_Oblique_Mercator_Two_Point_Natural_Origin"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_LABORDE_OBLIQUE_MERCATOR", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Laborde_Oblique_Mercator"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Lambert_Conformal_Conic_1SP"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Lambert_Conformal_Conic_2SP"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Lambert_Conformal_Conic_2SP_Belgium"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Lambert_Azimuthal_Equal_Area"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_MERCATOR_1SP", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Mercator_1SP"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_MERCATOR_2SP", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Mercator_2SP"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_MERCATOR_AUXILIARY_SPHERE", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Mercator_Auxiliary_Sphere"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_MILLER_CYLINDRICAL", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Miller_Cylindrical"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_MOLLWEIDE", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Mollweide"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_NEW_ZEALAND_MAP_GRID", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("New_Zealand_Map_Grid"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_OBLIQUE_STEREOGRAPHIC", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Oblique_Stereographic"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_ORTHOGRAPHIC", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Orthographic"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_POLAR_STEREOGRAPHIC", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Polar_Stereographic"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_POLYCONIC", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Polyconic"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_ROBINSON", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Robinson"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_SINUSOIDAL", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Sinusoidal"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_STEREOGRAPHIC", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Stereographic"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_SWISS_OBLIQUE_CYLINDRICAL", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Swiss_Oblique_Cylindrical"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_TRANSVERSE_MERCATOR", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Transverse_Mercator"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Transverse_Mercator_South_Orientated"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_TRANSVERSE_MERCATOR_MI_21", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Transverse_Mercator_MapInfo_21"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_TRANSVERSE_MERCATOR_MI_22", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Transverse_Mercator_MapInfo_22"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_TRANSVERSE_MERCATOR_MI_23", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Transverse_Mercator_MapInfo_23"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_TRANSVERSE_MERCATOR_MI_24", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Transverse_Mercator_MapInfo_24"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_TRANSVERSE_MERCATOR_MI_25", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Transverse_Mercator_MapInfo_25"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_TUNISIA_MINING_GRID", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Tunisia_Mining_Grid"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_TWO_POINT_EQUIDISTANT", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Two_Point_Equidistant"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_VANDERGRINTEN", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("VanDerGrinten"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_KROVAK", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Krovak"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_IMW_POLYCONIC", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("International_Map_of_the_World_Polyconic"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_WAGNER_I", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Wagner_I"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_WAGNER_II", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Wagner_II"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_WAGNER_III", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Wagner_III"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_WAGNER_IV", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Wagner_IV"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_WAGNER_V", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Wagner_V"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_WAGNER_VI", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Wagner_VI"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_WAGNER_VII", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Wagner_VII"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_QSC", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Quadrilateralized_Spherical_Cube"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_AITOFF", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Aitoff"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_WINKEL_I", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Winkel_I"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_WINKEL_II", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Winkel_II"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_WINKEL_TRIPEL", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Winkel_Tripel"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_CRASTER_PARABOLIC", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Craster_Parabolic"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_LOXIMUTHAL", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Loximuthal"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_QUARTIC_AUTHALIC", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Quartic_Authalic"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_CENTRAL_MERIDIAN", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("central_meridian"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_SCALE_FACTOR", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("scale_factor"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_STANDARD_PARALLEL_1", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("standard_parallel_1"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_STANDARD_PARALLEL_2", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("standard_parallel_2"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_PSEUDO_STD_PARALLEL_1", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("pseudo_standard_parallel_1"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_LONGITUDE_OF_CENTER", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("longitude_of_center"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_LATITUDE_OF_CENTER", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("latitude_of_center"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_LONGITUDE_OF_ORIGIN", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("longitude_of_origin"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_LATITUDE_OF_ORIGIN", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("latitude_of_origin"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_FALSE_EASTING", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("false_easting"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_FALSE_NORTHING", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("false_northing"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_AZIMUTH", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("azimuth"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_LONGITUDE_OF_POINT_1", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("longitude_of_point_1"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_LATITUDE_OF_POINT_1", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("latitude_of_point_1"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_LONGITUDE_OF_POINT_2", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("longitude_of_point_2"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_LATITUDE_OF_POINT_2", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("latitude_of_point_2"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_LONGITUDE_OF_POINT_3", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("longitude_of_point_3"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_LATITUDE_OF_POINT_3", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("latitude_of_point_3"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_RECTIFIED_GRID_ANGLE", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("rectified_grid_angle"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_LANDSAT_NUMBER", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("landsat_number"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_PATH_NUMBER", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("path_number"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_PERSPECTIVE_POINT_HEIGHT", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("perspective_point_height"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_SATELLITE_HEIGHT", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("satellite_height"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_FIPSZONE", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("fipszone"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_ZONE", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("zone"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_LATITUDE_OF_1ST_POINT", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Latitude_Of_1st_Point"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_LONGITUDE_OF_1ST_POINT", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Longitude_Of_1st_Point"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_LATITUDE_OF_2ND_POINT", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Latitude_Of_2nd_Point"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_LONGITUDE_OF_2ND_POINT", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Longitude_Of_2nd_Point"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_METER", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Meter"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_FOOT", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Foot (International)"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_FOOT_CONV", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("0.3048"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_US_FOOT", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Foot_US"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_US_FOOT_CONV", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("0.3048006096012192"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_NAUTICAL_MILE", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Nautical Mile"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_NAUTICAL_MILE_CONV", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("1852.0"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_LINK", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Link"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_LINK_CONV", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("0.20116684023368047"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_CHAIN", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Chain"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_CHAIN_CONV", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("20.116684023368047"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_ROD", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Rod"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_ROD_CONV", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("5.02921005842012"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_LINK_Clarke", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Link_Clarke"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_LINK_Clarke_CONV", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("0.2011661949"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_KILOMETER", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Kilometer"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_KILOMETER_CONV", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("1000."));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_DECIMETER", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Decimeter"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_DECIMETER_CONV", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("0.1"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_CENTIMETER", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Centimeter"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_CENTIMETER_CONV", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("0.01"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_MILLIMETER", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Millimeter"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_MILLIMETER_CONV", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("0.001"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_NAUT_MILE", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Nautical_Mile_International"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_NAUT_MILE_CONV", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("1852.0"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_INCH", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Inch_International"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_INCH_CONV", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("0.0254"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_FOOT", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Foot_International"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_FOOT_CONV", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("0.3048"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_YARD", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Yard_International"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_YARD_CONV", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("0.9144"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_STAT_MILE", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Statute_Mile_International"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_STAT_MILE_CONV", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("1609.344"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_FATHOM", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Fathom_International"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_FATHOM_CONV", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("1.8288"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_CHAIN", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Chain_International"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_CHAIN_CONV", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("20.1168"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_LINK", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Link_International"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INTL_LINK_CONV", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("0.201168"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_US_INCH", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Inch_US_Surveyor"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_US_INCH_CONV", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("0.025400050800101603"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_US_YARD", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Yard_US_Surveyor"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_US_YARD_CONV", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("0.914401828803658"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_US_CHAIN", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Chain_US_Surveyor"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_US_CHAIN_CONV", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("20.11684023368047"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_US_STAT_MILE", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Statute_Mile_US_Surveyor"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_US_STAT_MILE_CONV", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("1609.347218694437"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INDIAN_YARD", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Yard_Indian"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INDIAN_YARD_CONV", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("0.91439523"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INDIAN_FOOT", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Foot_Indian"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INDIAN_FOOT_CONV", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("0.30479841"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INDIAN_CHAIN", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Chain_Indian"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_INDIAN_CHAIN_CONV", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("20.11669506"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UA_DEGREE", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("degree"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UA_DEGREE_CONV", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("0.0174532925199433"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_UA_RADIAN", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("radian"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_PM_GREENWICH", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("Greenwich"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_DN_NAD27", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("North_American_Datum_1927"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_DN_NAD83", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("North_American_Datum_1983"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_DN_WGS72", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("WGS_1972"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_DN_WGS84", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_FromCharPtr("WGS_1984"));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_WGS84_SEMIMAJOR", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(6378137.0)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
-    SV *sv = get_sv((char*) SWIG_prefix "SRS_WGS84_INVFLATTENING", TRUE | 0x2 | GV_ADDMULTI);
-    sv_setsv(sv, SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(298.257223563)));
-    SvREADONLY_on(sv);
-  } while(0) /*@SWIG@*/;
-  SWIG_TypeClientData(SWIGTYPE_p_OSRSpatialReferenceShadow, (void*) "Geo::OSR::SpatialReference");
-  SWIG_TypeClientData(SWIGTYPE_p_OSRCoordinateTransformationShadow, (void*) "Geo::OSR::CoordinateTransformation");
-  ST(0) = &PL_sv_yes;
-  XSRETURN(1);
-}
-
diff --git a/swig/perl/parse-for-doxygen.pl b/swig/perl/parse-for-doxygen.pl
index dc57517..6192fbd 100644
--- a/swig/perl/parse-for-doxygen.pl
+++ b/swig/perl/parse-for-doxygen.pl
@@ -1,4 +1,8 @@
-my @pm = qw(lib/Geo/GDAL.pm lib/Geo/OGR.pm lib/Geo/OSR.pm lib/Geo/GDAL/Const.pm);
+use strict;
+use warnings;
+use Modern::Perl;
+
+my @pm = qw(lib/Geo/GDAL.pm lib/Geo/OGR.pm lib/Geo/OSR.pm lib/Geo/GDAL/Const.pm lib/Geo/GNM.pm);
 
 my %internal_methods = map {$_=>1} qw/TIEHASH CLEAR FIRSTKEY NEXTKEY FETCH STORE 
                                       DESTROY DISOWN ACQUIRE RELEASE_PARENTS
@@ -21,6 +25,7 @@ for my $pm (@pm) {
         next if $_ eq '';
         next if $_ =~ /^#####/; # skip swig comments
         my($w) = /^(\S+)\s/;
+        $w //= '';
         if ($w eq 'package') {
             $package = $_;
             $package =~ s/^(\S+)\s+//;
@@ -33,6 +38,7 @@ for my $pm (@pm) {
             $sub = $_;
             $sub =~ s/^(\S+)\s+//;
             $sub =~ s/\W.*//;
+            next if $sub eq ''; # skip anonymous subs
             $package{$package}{subs}{$sub} = 1;
             $attr = '';
             next;
@@ -56,7 +62,7 @@ for my $pm (@pm) {
         if (/use base/) {
             #print "$_\n";
         }
-        if (/\@ISA/ and /=/) {
+        if ($package and /\@ISA/ and /=/) {
             my $isa = $_;
             $isa =~ s/\@ISA//;
             $isa =~ s/=//;
@@ -64,7 +70,7 @@ for my $pm (@pm) {
             $isa =~ s/\(//;
             $isa =~ s/\)//;
             $isa =~ s/;//;
-            @isa = split /\s+/, $isa;
+            my @isa = split /\s+/, $isa;
             for my $isa (@isa) {
                 next if $isa eq '';
                 push @{$package{$package}{isas}}, $isa;
@@ -84,19 +90,17 @@ for my $pm (@pm) {
     close $fh;
 }
 
-my @dox = qw(lib/Geo/GDAL.dox lib/Geo/OGR.dox lib/Geo/OSR.dox);
+my @dox = qw(lib/Geo/GDAL.dox lib/Geo/OGR.dox lib/Geo/OSR.dox lib/Geo/GNM.dox);
 
-my $package;
-my $sub;
-my $attr;
 for my $dox (@dox) {
     open(my $fh, "<", $dox) or die "cannot open < $dox: $!";
     while (<$fh>) {
         chomp;
         next if $_ eq '';
-        s/^[\s#]+//;
-        #next if $_ eq '';
-        ($w) = /^(\S+)\s/;
+        s/^[#]+//;
+        s/^ //;
+        my ($w) = /^(\S+)\s/;
+        $w //= '';
         if ($w eq '@class') {
             $package = $_;
             $package =~ s/^(\S+)\s+//;
@@ -110,16 +114,24 @@ for my $dox (@dox) {
         if ($w eq '@ignore') {
             $sub = $_;
             $sub =~ s/^(\S+)\s+//;
+            $sub =~ s/\s+$//;
             #delete $package{$package}{subs}{$sub};
             $package{$package}{dox}{$sub}{d} = $sub;
             $package{$package}{dox}{$sub}{at} = $w;
             $package{$package}{dox}{$sub}{ignore} = 1;
             next;
         }
-        if ($w eq '@cmethod' or $w eq '@method') {
+        if ($w eq '@ignore_class') {
+            my $class = $_;
+            $class =~ s/^(\S+)\s+//;
+            $package{$class}{ignore} = 1;
+            next;
+        }
+        if ($w eq '@cmethod' or $w eq '@method' or $w eq '@sub') {
             $sub = $_;
             $sub =~ s/^(\S+)\s+//;
-            $d = $sub;
+            $sub =~ s/\s+$//;
+            my $d = $sub;
             if (/(\w+)\(/) {
                 $sub = $1;
             } elsif (/(\w+)$/) {
@@ -137,7 +149,7 @@ for my $dox (@dox) {
             $attr =~ s/^(\S+)\s+//;
             $attr =~ s/\s*list\s+/@/;
             $attr = '$'.$attr unless $attr =~ /^@/;;
-            $d = $attr;
+            my $d = $attr;
             $attr =~ s/@//;
             #print "attr: '$d'\n";
             $package{$package}{attrs}{$attr} = 1;
@@ -168,6 +180,13 @@ for my $dox (@dox) {
 for my $package (sort keys %package) {
     next if $package eq '';
     next if $package eq 'Geo::GDAL::Const';
+    next if $package{$package}{ignore};
+    for my $sub (sort keys %{$package{$package}{dox}}) {
+        next if $sub =~ /^\$/;
+        if ($package{$package}{dox}{$sub} and not $package{$package}{subs}{$sub}) {
+            print STDERR "Warning: non-existing $package::$sub documented.\n";
+        }
+    }
     print "#** \@class $package\n";
     for my $l (@{$package{$package}{package_dox}}) {
         print "# $l\n";
@@ -175,7 +194,7 @@ for my $package (sort keys %package) {
     print "#*\n";
     print "package $package;\n\n";
 
-    print "use base qw(",join(' ', @{$package{$package}{isas}}),")\n\n";
+    print "use base qw(",join(' ', @{$package{$package}{isas}}),")\n\n" if $package{$package}{isas};
 
     for my $attr (sort keys %{$package{$package}{attrs}}) {
         next if $package{$package}{dox}{$attr}{ignore};
@@ -196,7 +215,7 @@ for my $package (sort keys %package) {
         next if $package{$package}{dox}{$sub}{ignore};
         next if $sub =~ /^_/; # no use showing these
         next if $sub =~ /swig_/; # skip attribute setters and getters
-        next if $sub =~ /GDAL_GCP_/; # skip GDAL::GCP class methods from class GDAL
+        next if $sub =~ /GDAL_GCP_/; # skip GDAL::GCP package subroutines from class GDAL
 
         next if $sub =~ /GT_/; # done in methods geometry type test and modify
 
@@ -219,7 +238,8 @@ for my $package (sort keys %package) {
         next if $sub =~ /^SRS_UA_/;
         next if $sub =~ /^SRS_DN_/;
         
-        next if $internal_methods{$sub}; # skip internal methods
+        my $at = $package{$package}{dox}{$sub}{at} // '';
+        next if $internal_methods{$sub} && !$at; # skip non-documented internal methods
 
         my $d = $package{$package}{dox}{$sub}{d};
         my $nxt = 0;
@@ -234,33 +254,37 @@ for my $package (sort keys %package) {
         $d =~ s/^\\\@/array reference /;
         $d =~ s/^\%/hash /;
         $d =~ s/^\\\%/hash reference /;
-        $dp = $d;
+        my $dp = $d;
         $dp .= '()' unless $dp =~ /\(/;
         print "#** \@method $dp\n";
-        if ($private_methods{$d} or $package{$package}{dox}{$sub}{at} eq '@ignore') {
+        if ($private_methods{$d} or $at eq '@ignore') {
             print "# Undocumented method, do not call unless you know what you're doing.\n";
             print "# \@todo Test and document this method.\n";
         }
-        if ($package{$package}{dox}{$sub}{at} eq '@cmethod') {
+        if ($at eq '@cmethod') {
             print "# Class method.\n";
         }
+        elsif ($at eq '@sub') {
+            print "# Package subroutine.\n";
+        }
+        elsif ($at eq '@method') {
+            print "# Object method.\n";
+        }
         for my $c (@{$package{$package}{dox}{$sub}{c}}) {
             if ($c =~ /^\+list/) {
                 $c =~ s/\+list //;
                 my($pkg, $prefix, $exclude) = split / /, $c;
-                #print STDERR "$pkg, $prefix, $exclude\n";
-                my %exclude = map {$_=>1} split /,/, $exclude;
-                print "# ";
+                my %exclude;
+                %exclude = map {$_=>1} split /,/, $exclude if $exclude;
                 my @list;
                 for my $l (sort keys %{$package{$pkg}{subs}}) {
                     next unless $l =~ /^$prefix/;
                     $l =~ s/^$prefix//;
                     next if $exclude{$l};
-                    #print STDERR "  $l\n";
                     push @list, $l;
                 }
                 my $last = pop @list;
-                print join(', ', @list),", and $last.\n";
+                print "# ",join(', ', @list),", and $last.\n";
             } else {
                 print "# $c\n";
             }
@@ -269,7 +293,7 @@ for my $package (sort keys %package) {
         print "sub $sub {\n";
         my $code = $package{$package}{code}{$sub};
         fix_indentation($code);
-        pop @$code if $code->[$#$code] =~ /^\s*}\s*$/; # remove duplicate ending } of the sub
+        pop @$code if $code->[$#$code] && $code->[$#$code] =~ /^\s*}\s*$/; # remove duplicate ending } of the sub
         for my $l (@$code) {
             print "$l\n";
         }
@@ -279,6 +303,7 @@ for my $package (sort keys %package) {
 
 sub fix_indentation {
     my $code = shift;
+    return unless $code && @$code;
     my($space) = $code->[0] =~ /^(\s*)/;
     my $l = length($space);
     if ($l < 4) {
diff --git a/swig/perl/rr.dox b/swig/perl/rr.dox
index 6481a59..f52f85b 100644
--- a/swig/perl/rr.dox
+++ b/swig/perl/rr.dox
@@ -10,7 +10,7 @@ use Geo::GDAL;
 
 $file = shift @ARGV;
 
-$dataset = Geo::GDAL::Open($file);
+$dataset = Geo::GDAL::OpenEx($file);
 die "can't open $file as a raster dataset" unless $dataset;
 
 ($minx, $dx, undef, $maxy, undef, $dy) = $dataset->GeoTransform();
diff --git a/swig/perl/rv.dox b/swig/perl/rv.dox
index c2d9f7c..c8f6442 100644
--- a/swig/perl/rv.dox
+++ b/swig/perl/rv.dox
@@ -18,7 +18,7 @@ $dsname = "./";          # name of the datasource (in this case a directory)
 $lname = "borders";      # name of the layer
 $field = "country";      # name of the field whose value we need
 
-$datasource = Geo::OGR::Open($dsname);
+$datasource = Geo::GDAL::OpenEx($dsname);
 $layer = $datasource->Layer($lname);
 
 $layer->ResetReading();
diff --git a/swig/perl/streaming.dox b/swig/perl/streaming.dox
new file mode 100644
index 0000000..4adb2b9
--- /dev/null
+++ b/swig/perl/streaming.dox
@@ -0,0 +1,36 @@
+/*! \page streaming Streaming a dataset
+
+The code here does not have any warranty. It is recommended that
+before using any of this code, you look into it and try to understand
+what it does, what input it needs, etc. Do not blindly execute
+anything!
+
+This example will stream a vector dataset as GML through an object,
+which implements <a
+href="http://search.cpan.org/~miyagawa/PSGI-1.102/PSGI.pod#Delayed_Response_and_Streaming_Body">write
+and close methods</a>.
+
+\code
+
+my $layer = Geo::OGR::DataSource::Open(<data source name here>)->GetLayer(<layer name here>);
+
+{
+    package Writer;
+    sub write {
+        # note that the object itself is not available!
+        my ($w) = @_;
+        print $w;
+    }
+    sub close {
+        # note that the object itself is not available!
+        print "done\n";
+    }
+}
+
+my $writer = bless {}, 'Writer';
+
+Geo::OGR::Driver('GML')->Create($writer)->CopyLayer($layer, <layer name here>);
+
+\endcode
+
+*/
diff --git a/swig/perl/t/00-measures-00.t b/swig/perl/t/00-measures-00.t
new file mode 100644
index 0000000..57d2b9c
--- /dev/null
+++ b/swig/perl/t/00-measures-00.t
@@ -0,0 +1,44 @@
+use strict;
+use warnings;
+use bytes;
+use v5.10;
+use Test::More qw(no_plan);
+BEGIN { use_ok('Geo::GDAL') };
+
+# test geometry types
+
+my @t = @Geo::OGR::Geometry::GEOMETRY_TYPES;
+my %t2i = %Geo::OGR::Geometry::TYPE_STRING2INT;
+my %i2t = %Geo::OGR::Geometry::TYPE_INT2STRING;
+
+for my $geom (@t) {
+    next if $geom eq 'Unknown';
+    next if $geom eq 'None';
+
+    my $i = $t2i{$geom};
+
+    my $j = Geo::OGR::GT_Flatten($i);
+    ok(!Geo::OGR::GT_HasZ($j), "$geom, no Z after GT_Flatten");
+    ok(!Geo::OGR::GT_HasM($j), "$geom, no M after GT_Flatten");
+
+    $j = Geo::OGR::GT_SetZ($i);
+    ok(Geo::OGR::GT_HasZ($j), "$geom, has Z after GT_SetZ");
+    ok(bool(Geo::OGR::GT_HasM($i)) eq bool(Geo::OGR::GT_HasM($j)), "$geom, no change to M after GT_SetZ");
+
+    $j = Geo::OGR::GT_SetM($i);
+    ok(bool(Geo::OGR::GT_HasZ($i)) eq bool(Geo::OGR::GT_HasZ($j)), "$geom, no change to Z after GT_SetM");
+    ok(Geo::OGR::GT_HasM($j), "$geom, has M after GT_SetM");
+
+    for my $z (0,1) {
+        for my $m (0,1) {
+            $j = Geo::OGR::GT_SetModifier($i,$z,$m);
+            ok(bool($z) eq bool(Geo::OGR::GT_HasZ($j)), "$geom, set Z to $z after SetModifier");
+            ok(bool($m) eq bool(Geo::OGR::GT_HasM($j)), "$geom, set M to $m after SetModifier");
+        }
+    }
+}
+
+sub bool {
+    my $val = shift;
+    return $val ? 'true' : 'false';
+}
diff --git a/swig/perl/t/00-measures-01.t b/swig/perl/t/00-measures-01.t
new file mode 100644
index 0000000..7a9bfe8
--- /dev/null
+++ b/swig/perl/t/00-measures-01.t
@@ -0,0 +1,495 @@
+use strict;
+use warnings;
+use bytes;
+use v5.10;
+use Test::More qw(no_plan);
+BEGIN { use_ok('Geo::GDAL') };
+
+# input => ISO, old
+my @wkt = (
+    'POINT EMPTY' => ['POINT EMPTY', 'POINT EMPTY'],
+    'POINT Z EMPTY' => ['POINT Z EMPTY', 'POINT EMPTY'],
+    'POINT M EMPTY' => ['POINT M EMPTY', 'POINT EMPTY'],
+    'POINT ZM EMPTY' => ['POINT ZM EMPTY', 'POINT EMPTY'],
+    'POINT (EMPTY)' => ['POINT EMPTY', 'POINT EMPTY'],
+    'POINT EMPTY (1 2)' => ['error', 'error'],
+    'POINT (1)' => ['error', 'error'],
+    'POINT (1 2)' => ['POINT (1 2)', 'POINT (1 2)'],
+    'POINT (1 2 3)' => ['POINT Z (1 2 3)', 'POINT (1 2 3)'],
+    'POINT (1 2 3 4)' => ['POINT ZM (1 2 3 4)', 'POINT (1 2 3)'],
+    'POINT (1 2 3 4 5)' => ['error', 'error'],
+    'POINT Z (1 2 3)' => ['POINT Z (1 2 3)', 'POINT (1 2 3)'],
+    'POINT Z (1 2)' => ['POINT Z (1 2 0)', 'POINT (1 2 0)'],
+    'POINT Z (1 2 3 4)' => ['POINT Z (1 2 3)', 'POINT (1 2 3)'], # backwards compatibility
+    'POINT M (1 2 3)' => ['POINT M (1 2 3)', 'POINT (1 2)'],
+    'POINT M (1 2)' => ['POINT M (1 2 0)', 'POINT (1 2)'],
+    'POINT M (1 2 3 4)' => ['error', 'error'],
+    'POINT ZM (1 2 3 4)' => ['POINT ZM (1 2 3 4)', 'POINT (1 2 3)'],
+    'POINT ZM (1 2 3)' => ['POINT ZM (1 2 3 0)', 'POINT (1 2 3)'],
+    'POINT ZM (1 2 3 4 5)' => ['error', 'error'],
+
+    'LINESTRING EMPTY' => ['LINESTRING EMPTY', 'LINESTRING EMPTY'],
+    'LINESTRING Z EMPTY' => ['LINESTRING Z EMPTY', 'LINESTRING EMPTY'],
+    'LINESTRING M EMPTY' => ['LINESTRING M EMPTY', 'LINESTRING EMPTY'],
+    'LINESTRING ZM EMPTY' => ['LINESTRING ZM EMPTY', 'LINESTRING EMPTY'],
+    'LINESTRING (EMPTY)' => ['LINESTRING EMPTY', 'LINESTRING EMPTY'],
+    'LINESTRING EMPTY (1 2, 3 4)' => ['error', 'error'],
+    'LINESTRING (1, 3)' => ['error', 'error'],
+    'LINESTRING (1 2, 3 4)' => ['LINESTRING (1 2,3 4)', 'LINESTRING (1 2,3 4)'],
+    'LINESTRING (1 2, 3 4 5)' => ['LINESTRING Z (1 2 0,3 4 5)', 'LINESTRING (1 2 0,3 4 5)'],
+    'LINESTRING (1 2 3, 3 4 5)' => ['LINESTRING Z (1 2 3,3 4 5)', 'LINESTRING (1 2 3,3 4 5)'],
+    'LINESTRING (1 2 3 4, 5 6 7 8)' => ['LINESTRING ZM (1 2 3 4,5 6 7 8)', 'LINESTRING (1 2 3,5 6 7)'],
+    'LINESTRING (1 2 3 4 5, 6 7 8 9)' => ['error', 'error'],
+    'LINESTRING Z (1 2 3, 6 7 8)' => ['LINESTRING Z (1 2 3,6 7 8)', 'LINESTRING (1 2 3,6 7 8)'],
+    'LINESTRING Z (1 2, 6 7)' => ['LINESTRING Z (1 2 0,6 7 0)', 'LINESTRING (1 2 0,6 7 0)'],
+    'LINESTRING Z (1 2 3 4, 6 7 8 9)' => ['LINESTRING Z (1 2 3,6 7 8)', 'LINESTRING (1 2 3,6 7 8)'], # backwards compatibility
+    'LINESTRING M (1 2 3, 6 7 8)' => ['LINESTRING M (1 2 3,6 7 8)', 'LINESTRING (1 2,6 7)'],
+    'LINESTRING M (1 2, 6 7)' => ['LINESTRING M (1 2 0,6 7 0)', 'LINESTRING (1 2,6 7)'],
+    'LINESTRING M (1 2 3 4, 6 7 8 9)' => ['LINESTRING ZM (1 2 3 4,6 7 8 9)', 'LINESTRING (1 2 3,6 7 8)'],
+    'LINESTRING ZM (1 2 3 4, 6 7 8 9)' => ['LINESTRING ZM (1 2 3 4,6 7 8 9)', 'LINESTRING (1 2 3,6 7 8)'],
+    'LINESTRING ZM (1 2 3, 6 7 8)' => ['LINESTRING ZM (1 2 3 0,6 7 8 0)', 'LINESTRING (1 2 3,6 7 8)'],
+    'LINESTRING ZM (1 2 3 4 5, 6 7 8 9 10)' => ['error', 'error'],
+
+    'POLYGON (EMPTY)' => ['POLYGON EMPTY', 'POLYGON EMPTY'],
+    'POLYGON Z (EMPTY)' => ['POLYGON Z EMPTY', 'POLYGON EMPTY'],
+    'POLYGON M (EMPTY)' => ['POLYGON M EMPTY', 'POLYGON EMPTY'],
+    'POLYGON ZM (EMPTY)' => ['POLYGON ZM EMPTY', 'POLYGON EMPTY'],
+
+    'MULTIPOINT EMPTY' => ['MULTIPOINT EMPTY', 'MULTIPOINT EMPTY'],
+    'MULTILINESTRING EMPTY' => ['MULTILINESTRING EMPTY', 'MULTILINESTRING EMPTY'],
+    'MULTIPOLYGON EMPTY' => ['MULTIPOLYGON EMPTY', 'MULTIPOLYGON EMPTY'],
+    'GEOMETRYCOLLECTION EMPTY' => ['GEOMETRYCOLLECTION EMPTY', 'GEOMETRYCOLLECTION EMPTY'],
+    'CIRCULARSTRING EMPTY' => ['CIRCULARSTRING EMPTY', 'CIRCULARSTRING EMPTY'],
+    'COMPOUNDCURVE EMPTY' => ['COMPOUNDCURVE EMPTY', 'COMPOUNDCURVE EMPTY'],
+    'CURVEPOLYGON EMPTY' => ['CURVEPOLYGON EMPTY', 'CURVEPOLYGON EMPTY'],
+    'MULTICURVE EMPTY' => ['MULTICURVE EMPTY', 'MULTICURVE EMPTY'],
+    'MULTISURFACE EMPTY' => ['MULTISURFACE EMPTY', 'MULTISURFACE EMPTY'],
+
+    'MULTIPOINT Z EMPTY' => ['MULTIPOINT Z EMPTY', 'MULTIPOINT EMPTY'],
+    'MULTILINESTRING Z EMPTY' => ['MULTILINESTRING Z EMPTY', 'MULTILINESTRING EMPTY'],
+    'MULTIPOLYGON Z EMPTY' => ['MULTIPOLYGON Z EMPTY', 'MULTIPOLYGON EMPTY'],
+    'GEOMETRYCOLLECTION Z EMPTY' => ['GEOMETRYCOLLECTION Z EMPTY', 'GEOMETRYCOLLECTION EMPTY'],
+    'CIRCULARSTRING Z EMPTY' => ['CIRCULARSTRING Z EMPTY', 'CIRCULARSTRING Z EMPTY'],
+    'COMPOUNDCURVE Z EMPTY' => ['COMPOUNDCURVE Z EMPTY', 'COMPOUNDCURVE Z EMPTY'],
+    'CURVEPOLYGON Z EMPTY' => ['CURVEPOLYGON Z EMPTY', 'CURVEPOLYGON Z EMPTY'],
+    'MULTICURVE Z EMPTY' => ['MULTICURVE Z EMPTY', 'MULTICURVE Z EMPTY'],
+    'MULTISURFACE Z EMPTY' => ['MULTISURFACE Z EMPTY', 'MULTISURFACE Z EMPTY'],
+
+    'MULTIPOINT M EMPTY' => ['MULTIPOINT M EMPTY', 'MULTIPOINT EMPTY'],
+    'MULTILINESTRING M EMPTY' => ['MULTILINESTRING M EMPTY', 'MULTILINESTRING EMPTY'],
+    'MULTIPOLYGON M EMPTY' => ['MULTIPOLYGON M EMPTY', 'MULTIPOLYGON EMPTY'],
+    'GEOMETRYCOLLECTION M EMPTY' => ['GEOMETRYCOLLECTION M EMPTY', 'GEOMETRYCOLLECTION EMPTY'],
+    'CIRCULARSTRING M EMPTY' => ['CIRCULARSTRING M EMPTY', 'CIRCULARSTRING M EMPTY'],
+    'COMPOUNDCURVE M EMPTY' => ['COMPOUNDCURVE M EMPTY', 'COMPOUNDCURVE M EMPTY'],
+    'CURVEPOLYGON M EMPTY' => ['CURVEPOLYGON M EMPTY', 'CURVEPOLYGON M EMPTY'],
+    'MULTICURVE M EMPTY' => ['MULTICURVE M EMPTY', 'MULTICURVE M EMPTY'],
+    'MULTISURFACE M EMPTY' => ['MULTISURFACE M EMPTY', 'MULTISURFACE M EMPTY'],
+
+    'MULTIPOINT ZM EMPTY' => ['MULTIPOINT ZM EMPTY', 'MULTIPOINT EMPTY'],
+    'MULTILINESTRING ZM EMPTY' => ['MULTILINESTRING ZM EMPTY', 'MULTILINESTRING EMPTY'],
+    'MULTIPOLYGON ZM EMPTY' => ['MULTIPOLYGON ZM EMPTY', 'MULTIPOLYGON EMPTY'],
+    'GEOMETRYCOLLECTION ZM EMPTY' => ['GEOMETRYCOLLECTION ZM EMPTY', 'GEOMETRYCOLLECTION EMPTY'],
+    'CIRCULARSTRING ZM EMPTY' => ['CIRCULARSTRING ZM EMPTY', 'CIRCULARSTRING ZM EMPTY'],
+    'COMPOUNDCURVE ZM EMPTY' => ['COMPOUNDCURVE ZM EMPTY', 'COMPOUNDCURVE ZM EMPTY'],
+    'CURVEPOLYGON ZM EMPTY' => ['CURVEPOLYGON ZM EMPTY', 'CURVEPOLYGON ZM EMPTY'],
+    'MULTICURVE ZM EMPTY' => ['MULTICURVE ZM EMPTY', 'MULTICURVE ZM EMPTY'],
+    'MULTISURFACE ZM EMPTY' => ['MULTISURFACE ZM EMPTY', 'MULTISURFACE ZM EMPTY'],
+
+    'POLYGON ((1 2, 3 4, 5 6),(1 2, 2 2, 0 0))' => 
+    ['POLYGON ((1 2,3 4,5 6),(1 2,2 2,0 0))', 'POLYGON ((1 2,3 4,5 6),(1 2,2 2,0 0))'],
+
+    'POLYGON Z ((1 2, 3 4, 5 6 7),(1 2, 2 2, 0 0))' => 
+    ['POLYGON Z ((1 2 0,3 4 0,5 6 7),(1 2 0,2 2 0,0 0 0))', 'POLYGON ((1 2 0,3 4 0,5 6 7),(1 2 0,2 2 0,0 0 0))'],
+
+    'POLYGON M ((1 2, 3 4, 5 6),(1 2, 2 2, 0 0))' => 
+    ['POLYGON M ((1 2 0,3 4 0,5 6 0),(1 2 0,2 2 0,0 0 0))', 'POLYGON ((1 2,3 4,5 6),(1 2,2 2,0 0))'],
+
+    'POLYGON ZM ((1 2, 3 4, 5 6),(1 2, 2 2, 0 0))' => 
+    ['POLYGON ZM ((1 2 0 0,3 4 0 0,5 6 0 0),(1 2 0 0,2 2 0 0,0 0 0 0))', 'POLYGON ((1 2 0,3 4 0,5 6 0),(1 2 0,2 2 0,0 0 0))'],
+
+    'MULTIPOLYGON (((1 2 -4,1 3 -3,2 3 -3,2 2 -3,1 2 -6)),((-1 -2,-1 -3,-2 -3,-2 -2,-1 -2,50 60 7)))' => 
+    ['MULTIPOLYGON Z (((1 2 -4,1 3 -3,2 3 -3,2 2 -3,1 2 -6)),((-1 -2 0,-1 -3 0,-2 -3 0,-2 -2 0,-1 -2 0,50 60 7)))', 
+     'MULTIPOLYGON (((1 2 -4,1 3 -3,2 3 -3,2 2 -3,1 2 -6)),((-1 -2 0,-1 -3 0,-2 -3 0,-2 -2 0,-1 -2 0,50 60 7)))'],
+
+    'MULTIPOINT ((1 2 3 4),(5 6 7))' =>
+    [ 'MULTIPOINT ZM ((1 2 3 4),(5 6 7 0))',
+      'MULTIPOINT (1 2 3,5 6 7)' ],
+
+    'MULTILINESTRING ((1 2 3 4,5 6 7),(5 6 7,1 2 3 4))' =>
+    [ 'MULTILINESTRING ZM ((1 2 3 4,5 6 7 0),(5 6 7 0,1 2 3 4))',
+      'MULTILINESTRING ((1 2 3,5 6 7),(5 6 7,1 2 3))' ],
+
+    "POINT (1 2)" => 
+    [ 'POINT (1 2)', 'POINT (1 2)'],
+
+    "MULTIPOINT (1 2,3 4)" => 
+    [ 'MULTIPOINT ((1 2),(3 4))', 'MULTIPOINT (1 2,3 4)'],
+
+    "LINESTRING (1 2,3 4)" => 
+    [ 'LINESTRING (1 2,3 4)', 'LINESTRING (1 2,3 4)'],
+
+    "MULTILINESTRING ((1 2,3 4))" => 
+    [ 'MULTILINESTRING ((1 2,3 4))', 'MULTILINESTRING ((1 2,3 4))'],
+
+    "MULTILINESTRING ((1 2,3 4),(5 6,7 8))" => 
+    [ 'MULTILINESTRING ((1 2,3 4),(5 6,7 8))', 'MULTILINESTRING ((1 2,3 4),(5 6,7 8))'],
+
+    "POLYGON ((0 0,0 1,1 1,1 0,0 0))" => 
+    [ 'POLYGON ((0 0,0 1,1 1,1 0,0 0))', 'POLYGON ((0 0,0 1,1 1,1 0,0 0))'],
+
+    "MULTIPOLYGON (((0 0,0 1,1 1,1 0,0 0)))" => 
+    [ 'MULTIPOLYGON (((0 0,0 1,1 1,1 0,0 0)))', 'MULTIPOLYGON (((0 0,0 1,1 1,1 0,0 0)))'],
+
+    "MULTIPOLYGON (((0 0,0 1,1 1,1 0,0 0),(0.25 0.25,0.75 0.25,0.75 0.75,0.25 0.75,0.25 0.25)),((2 0,2 1,3 1,3 0,2 0)))" => 
+    [ 'MULTIPOLYGON (((0 0,0 1,1 1,1 0,0 0),(0.25 0.25,0.75 0.25,0.75 0.75,0.25 0.75,0.25 0.25)),((2 0,2 1,3 1,3 0,2 0)))', 
+      'MULTIPOLYGON (((0 0,0 1,1 1,1 0,0 0),(0.25 0.25,0.75 0.25,0.75 0.75,0.25 0.75,0.25 0.25)),((2 0,2 1,3 1,3 0,2 0)))'],
+
+    "MULTIPOINT (1 2 -10,3 4 -20)" => 
+    [ 'MULTIPOINT Z ((1 2 -10),(3 4 -20))', 'MULTIPOINT (1 2 -10,3 4 -20)'],
+
+    "LINESTRING (1 2 -10,3 4 -20)" => 
+    [ 'LINESTRING Z (1 2 -10,3 4 -20)', 'LINESTRING (1 2 -10,3 4 -20)'],
+
+    "MULTILINESTRING ((1 2 -10,3 4 -20))" => 
+    [ 'MULTILINESTRING Z ((1 2 -10,3 4 -20))', 'MULTILINESTRING ((1 2 -10,3 4 -20))'],
+
+    "MULTILINESTRING ((1 2 -10,3 4 -20))" => 
+    [ 'MULTILINESTRING Z ((1 2 -10,3 4 -20))', 'MULTILINESTRING ((1 2 -10,3 4 -20))'],
+
+    "POLYGON ((0 0 -10,0 1 -10,1 1 -10,1 0 -10,0 0 -10))" => 
+    [ 'POLYGON Z ((0 0 -10,0 1 -10,1 1 -10,1 0 -10,0 0 -10))', 'POLYGON ((0 0 -10,0 1 -10,1 1 -10,1 0 -10,0 0 -10))'],
+
+    "MULTIPOLYGON (((0 0 -10,0 1 -10,1 1 -10,1 0 -10,0 0 -10)))" => 
+    [ 'MULTIPOLYGON Z (((0 0 -10,0 1 -10,1 1 -10,1 0 -10,0 0 -10)))', 'MULTIPOLYGON (((0 0 -10,0 1 -10,1 1 -10,1 0 -10,0 0 -10)))'],
+
+    "MULTIPOLYGON (((0 0 -10,0 1 -10,1 1 -10,1 0 -10,0 0 -10)))" => 
+    [ 'MULTIPOLYGON Z (((0 0 -10,0 1 -10,1 1 -10,1 0 -10,0 0 -10)))', 'MULTIPOLYGON (((0 0 -10,0 1 -10,1 1 -10,1 0 -10,0 0 -10)))'],
+
+    "MULTIPOLYGON (((0 0 0,0 1 0,1 0 0,0 0 0)),((0 1 0,1 0 0,1 1 0,0 1 0)),((10 0 0,10 1 0,11 0 0,10 0 0)),((10 0 0,11 0 0,10 -1 0,10 0 0)),((5 0 0,5 1 0,6 0 0,5 0 0)),((15 0 0,15 1 0,16 0 0,15 0 0)),((100 0 0,100 1 0,101 1 0,101 0 0,100 0 0),(100.25 0.25 0,100.75 0.25 0,100.75 0.75 0,100.75 0.25 0,100.25 0.25 0)))" => 
+    [ 'MULTIPOLYGON Z (((0 0 0,0 1 0,1 0 0,0 0 0)),((0 1 0,1 0 0,1 1 0,0 1 0)),((10 0 0,10 1 0,11 0 0,10 0 0)),((10 0 0,11 0 0,10 -1 0,10 0 0)),((5 0 0,5 1 0,6 0 0,5 0 0)),((15 0 0,15 1 0,16 0 0,15 0 0)),((100 0 0,100 1 0,101 1 0,101 0 0,100 0 0),(100.25 0.25 0,100.75 0.25 0,100.75 0.75 0,100.75 0.25 0,100.25 0.25 0)))', 
+      'MULTIPOLYGON (((0 0 0,0 1 0,1 0 0,0 0 0)),((0 1 0,1 0 0,1 1 0,0 1 0)),((10 0 0,10 1 0,11 0 0,10 0 0)),((10 0 0,11 0 0,10 -1 0,10 0 0)),((5 0 0,5 1 0,6 0 0,5 0 0)),((15 0 0,15 1 0,16 0 0,15 0 0)),((100 0 0,100 1 0,101 1 0,101 0 0,100 0 0),(100.25 0.25 0,100.75 0.25 0,100.75 0.75 0,100.75 0.25 0,100.25 0.25 0)))'],
+
+    'CIRCULARSTRING (0 1,2 3,4 5)' => 
+    [ 'CIRCULARSTRING (0 1,2 3,4 5)', 'CIRCULARSTRING (0 1,2 3,4 5)'],
+
+    'CIRCULARSTRING Z (0 1 2,4 5 6,7 8 9)' => 
+    [ 'CIRCULARSTRING Z (0 1 2,4 5 6,7 8 9)', 'CIRCULARSTRING Z (0 1 2,4 5 6,7 8 9)'],
+
+    'COMPOUNDCURVE ((0 1,2 3,4 5))' => 
+    [ 'COMPOUNDCURVE ((0 1,2 3,4 5))', 'COMPOUNDCURVE ((0 1,2 3,4 5))'],
+
+    'COMPOUNDCURVE Z ((0 1 2,4 5 6,7 8 9))' => 
+    [ 'COMPOUNDCURVE Z ((0 1 2,4 5 6,7 8 9))', 'COMPOUNDCURVE Z ((0 1 2,4 5 6,7 8 9))'],
+
+    'COMPOUNDCURVE ((0 1,2 3,4 5),CIRCULARSTRING (4 5,6 7,8 9))' => 
+    [ 'COMPOUNDCURVE ((0 1,2 3,4 5),CIRCULARSTRING (4 5,6 7,8 9))', 'COMPOUNDCURVE ((0 1,2 3,4 5),CIRCULARSTRING (4 5,6 7,8 9))'],
+
+    'COMPOUNDCURVE Z ((0 1 2,4 5 6,7 8 9),CIRCULARSTRING Z (7 8 9,10 11 12,13 14 15))' => 
+    [ 'COMPOUNDCURVE Z ((0 1 2,4 5 6,7 8 9),CIRCULARSTRING Z (7 8 9,10 11 12,13 14 15))', 'COMPOUNDCURVE Z ((0 1 2,4 5 6,7 8 9),CIRCULARSTRING Z (7 8 9,10 11 12,13 14 15))'],
+
+    'CURVEPOLYGON ((0 0,0 1,1 1,1 0,0 0))' => 
+    [ 'CURVEPOLYGON ((0 0,0 1,1 1,1 0,0 0))', 'CURVEPOLYGON ((0 0,0 1,1 1,1 0,0 0))'],
+
+    'CURVEPOLYGON Z ((0 0 2,0 1 3,1 1 4,1 0 5,0 0 2))' => 
+    [ 'CURVEPOLYGON Z ((0 0 2,0 1 3,1 1 4,1 0 5,0 0 2))', 'CURVEPOLYGON Z ((0 0 2,0 1 3,1 1 4,1 0 5,0 0 2))'],
+
+    'CURVEPOLYGON (COMPOUNDCURVE (CIRCULARSTRING (0 0,1 0,0 0)))' => 
+    [ 'CURVEPOLYGON (COMPOUNDCURVE (CIRCULARSTRING (0 0,1 0,0 0)))', 'CURVEPOLYGON (COMPOUNDCURVE (CIRCULARSTRING (0 0,1 0,0 0)))'],
+
+    'CURVEPOLYGON Z (COMPOUNDCURVE Z (CIRCULARSTRING Z (0 0 2,1 0 3,0 0 2)))' => 
+    [ 'CURVEPOLYGON Z (COMPOUNDCURVE Z (CIRCULARSTRING Z (0 0 2,1 0 3,0 0 2)))', 
+      'CURVEPOLYGON Z (COMPOUNDCURVE Z (CIRCULARSTRING Z (0 0 2,1 0 3,0 0 2)))'],
+
+    'MULTICURVE (CIRCULARSTRING (0 0,1 0,0 0),(0 0,1 1))' => 
+    [ 'MULTICURVE (CIRCULARSTRING (0 0,1 0,0 0),(0 0,1 1))', 'MULTICURVE (CIRCULARSTRING (0 0,1 0,0 0),(0 0,1 1))'],
+
+    'MULTICURVE Z (CIRCULARSTRING Z (0 0 1,1 0 1,0 0 1),(0 0 1,1 1 1))' => 
+    [ 'MULTICURVE Z (CIRCULARSTRING Z (0 0 1,1 0 1,0 0 1),(0 0 1,1 1 1))', 
+      'MULTICURVE Z (CIRCULARSTRING Z (0 0 1,1 0 1,0 0 1),(0 0 1,1 1 1))'],
+
+    'MULTICURVE (CIRCULARSTRING (0 0,1 0,0 0),(0 0,1 1),COMPOUNDCURVE ((0 0,1 1),CIRCULARSTRING (1 1,2 2,3 3)))' => 
+    [ 'MULTICURVE (CIRCULARSTRING (0 0,1 0,0 0),(0 0,1 1),COMPOUNDCURVE ((0 0,1 1),CIRCULARSTRING (1 1,2 2,3 3)))', 
+      'MULTICURVE (CIRCULARSTRING (0 0,1 0,0 0),(0 0,1 1),COMPOUNDCURVE ((0 0,1 1),CIRCULARSTRING (1 1,2 2,3 3)))'],
+
+    'MULTISURFACE (((0 0,0 10,10 10,10 0,0 0)),CURVEPOLYGON (CIRCULARSTRING (0 0,1 0,0 0)))' => 
+    [ 'MULTISURFACE (((0 0,0 10,10 10,10 0,0 0)),CURVEPOLYGON (CIRCULARSTRING (0 0,1 0,0 0)))', 
+      'MULTISURFACE (((0 0,0 10,10 10,10 0,0 0)),CURVEPOLYGON (CIRCULARSTRING (0 0,1 0,0 0)))'],
+
+    'MULTISURFACE Z (((0 0 1,0 10 1,10 10 1,10 0 1,0 0 1)),CURVEPOLYGON Z (CIRCULARSTRING Z (0 0 1,1 0 1,0 0 1)))' => 
+    [ 'MULTISURFACE Z (((0 0 1,0 10 1,10 10 1,10 0 1,0 0 1)),CURVEPOLYGON Z (CIRCULARSTRING Z (0 0 1,1 0 1,0 0 1)))', 
+      'MULTISURFACE Z (((0 0 1,0 10 1,10 10 1,10 0 1,0 0 1)),CURVEPOLYGON Z (CIRCULARSTRING Z (0 0 1,1 0 1,0 0 1)))'],
+
+    'GEOMETRYCOLLECTION (CIRCULARSTRING (0 1,2 3,4 5),COMPOUNDCURVE ((0 1,2 3,4 5)),CURVEPOLYGON ((0 0,0 1,1 1,1 0,0 0)),MULTICURVE ((0 0,1 1)),MULTISURFACE (((0 0,0 10,10 10,10 0,0 0))))' => 
+    [ 'GEOMETRYCOLLECTION (CIRCULARSTRING (0 1,2 3,4 5),COMPOUNDCURVE ((0 1,2 3,4 5)),CURVEPOLYGON ((0 0,0 1,1 1,1 0,0 0)),MULTICURVE ((0 0,1 1)),MULTISURFACE (((0 0,0 10,10 10,10 0,0 0))))', 
+      'GEOMETRYCOLLECTION (CIRCULARSTRING (0 1,2 3,4 5),COMPOUNDCURVE ((0 1,2 3,4 5)),CURVEPOLYGON ((0 0,0 1,1 1,1 0,0 0)),MULTICURVE ((0 0,1 1)),MULTISURFACE (((0 0,0 10,10 10,10 0,0 0))))'],
+
+    'GEOMETRYCOLLECTION (POINT (1 2 3))' => 
+    [ 'GEOMETRYCOLLECTION Z (POINT Z (1 2 3))', 'GEOMETRYCOLLECTION (POINT (1 2 3))' ],
+
+    'GEOMETRYCOLLECTION (POINT Z (1 2 3))' => 
+    [ 'GEOMETRYCOLLECTION Z (POINT Z (1 2 3))', 'GEOMETRYCOLLECTION (POINT (1 2 3))' ],
+
+    'GEOMETRYCOLLECTION (POINT M (1 2 3))' => 
+    [ 'GEOMETRYCOLLECTION M (POINT M (1 2 3))', 'GEOMETRYCOLLECTION (POINT (1 2))' ],
+
+    'GEOMETRYCOLLECTION (POINT ZM (1 2 3))' => 
+    [ 'GEOMETRYCOLLECTION ZM (POINT ZM (1 2 3 0))', 'GEOMETRYCOLLECTION (POINT (1 2 3))' ],
+
+    'GEOMETRYCOLLECTION Z (POINT (1 2 3))' => 
+    [ 'GEOMETRYCOLLECTION Z (POINT Z (1 2 3))', 'GEOMETRYCOLLECTION (POINT (1 2 3))' ],
+
+    'GEOMETRYCOLLECTION Z (POINT Z (1 2 3))' => 
+    [ 'GEOMETRYCOLLECTION Z (POINT Z (1 2 3))', 'GEOMETRYCOLLECTION (POINT (1 2 3))' ],
+
+    'GEOMETRYCOLLECTION Z (POINT M (1 2 3))' => 
+    [ 'GEOMETRYCOLLECTION ZM (POINT ZM (1 2 0 3))', 'GEOMETRYCOLLECTION (POINT (1 2 0))' ],
+    
+    'GEOMETRYCOLLECTION Z (POINT ZM (1 2 3))' => 
+    [ 'GEOMETRYCOLLECTION ZM (POINT ZM (1 2 3 0))', 'GEOMETRYCOLLECTION (POINT (1 2 3))' ],
+    
+    'GEOMETRYCOLLECTION M (POINT (1 2 3))' => ['error', 'error'],
+    
+    'GEOMETRYCOLLECTION M (POINT Z (1 2 3))' => ['error', 'error'],
+
+    'GEOMETRYCOLLECTION M (POINT M (1 2 3))' => 
+    [ 'GEOMETRYCOLLECTION M (POINT M (1 2 3))', 'GEOMETRYCOLLECTION (POINT (1 2))' ],
+    
+    'GEOMETRYCOLLECTION M (POINT ZM (1 2 3))' => 
+    [ 'GEOMETRYCOLLECTION ZM (POINT ZM (1 2 3 0))', 'GEOMETRYCOLLECTION (POINT (1 2 3))' ],
+    
+    'GEOMETRYCOLLECTION ZM (POINT (1 2 3))' => 
+    [ 'GEOMETRYCOLLECTION ZM (POINT ZM (1 2 3 0))', 'GEOMETRYCOLLECTION (POINT (1 2 3))' ],
+    
+    'GEOMETRYCOLLECTION ZM (POINT Z (1 2 3))' => 
+    [ 'GEOMETRYCOLLECTION ZM (POINT ZM (1 2 3 0))', 'GEOMETRYCOLLECTION (POINT (1 2 3))' ],
+
+    'GEOMETRYCOLLECTION ZM (POINT M (1 2 3))' => 
+    [ 'GEOMETRYCOLLECTION ZM (POINT ZM (1 2 0 3))', 'GEOMETRYCOLLECTION (POINT (1 2 0))' ],
+
+    'GEOMETRYCOLLECTION ZM (POINT ZM (1 2 3))' => 
+    [ 'GEOMETRYCOLLECTION ZM (POINT ZM (1 2 3 0))', 'GEOMETRYCOLLECTION (POINT (1 2 3))' ],
+
+    'MULTICURVE (LINESTRING (1 2 3))' => 
+    [ 'MULTICURVE Z ((1 2 3))', 'MULTICURVE Z ((1 2 3))' ],
+
+    'MULTICURVE (LINESTRING Z (1 2 3))' => 
+    [ 'MULTICURVE Z ((1 2 3))', 'MULTICURVE Z ((1 2 3))' ],
+
+    'MULTICURVE (LINESTRING M (1 2 3))' => 
+    [ 'MULTICURVE M ((1 2 3))', 'MULTICURVE M ((1 2 3))' ],
+
+    'MULTICURVE (LINESTRING ZM (1 2 3))' => 
+    [ 'MULTICURVE ZM ((1 2 3 0))', 'MULTICURVE ZM ((1 2 3 0))' ],
+
+    'MULTICURVE Z (LINESTRING (1 2 3))' => 
+    [ 'MULTICURVE Z ((1 2 3))', 'MULTICURVE Z ((1 2 3))' ],
+
+    'MULTICURVE Z (LINESTRING Z (1 2 3))' => 
+    [ 'MULTICURVE Z ((1 2 3))', 'MULTICURVE Z ((1 2 3))' ],
+
+    'MULTICURVE Z (LINESTRING M (1 2 3))' => 
+    [ 'MULTICURVE ZM ((1 2 0 3))', 'MULTICURVE ZM ((1 2 0 3))' ],
+
+    'MULTICURVE Z (LINESTRING ZM (1 2 3))' => 
+    [ 'MULTICURVE ZM ((1 2 3 0))', 'MULTICURVE ZM ((1 2 3 0))' ],
+    
+    'MULTICURVE M (LINESTRING (1 2 3))' => ['error', 'error'],
+    
+    'MULTICURVE M (LINESTRING Z (1 2 3))' => ['error', 'error'],
+    
+    'MULTICURVE M (LINESTRING M (1 2 3))' => 
+    [ 'MULTICURVE M ((1 2 3))', 'MULTICURVE M ((1 2 3))' ],
+    
+    'MULTICURVE M (LINESTRING ZM (1 2 3))' => 
+    [ 'MULTICURVE ZM ((1 2 3 0))', 'MULTICURVE ZM ((1 2 3 0))' ],
+    
+    'MULTICURVE ZM (LINESTRING (1 2 3))' => 
+    [ 'MULTICURVE ZM ((1 2 3 0))', 'MULTICURVE ZM ((1 2 3 0))' ],
+    
+    'MULTICURVE ZM (LINESTRING Z (1 2 3))' => 
+    [ 'MULTICURVE ZM ((1 2 3 0))', 'MULTICURVE ZM ((1 2 3 0))' ],
+    
+    'MULTICURVE ZM (LINESTRING M (1 2 3))' => 
+    [ 'MULTICURVE ZM ((1 2 0 3))', 'MULTICURVE ZM ((1 2 0 3))' ],
+    
+    'MULTICURVE ZM (LINESTRING ZM (1 2 3))' => 
+    [ 'MULTICURVE ZM ((1 2 3 0))', 'MULTICURVE ZM ((1 2 3 0))' ],
+
+    'MULTICURVE (CIRCULARSTRING (1 2 3,1 2 3,1 2 3))' => 
+    [ 'MULTICURVE Z (CIRCULARSTRING Z (1 2 3,1 2 3,1 2 3))', 'MULTICURVE Z (CIRCULARSTRING Z (1 2 3,1 2 3,1 2 3))' ],
+    
+    'MULTICURVE (CIRCULARSTRING Z (1 2 3,1 2 3,1 2 3))' => 
+    [ 'MULTICURVE Z (CIRCULARSTRING Z (1 2 3,1 2 3,1 2 3))', 'MULTICURVE Z (CIRCULARSTRING Z (1 2 3,1 2 3,1 2 3))' ],
+    
+    'MULTICURVE (CIRCULARSTRING M (1 2 3,1 2 3,1 2 3))' => 
+    [ 'MULTICURVE M (CIRCULARSTRING M (1 2 3,1 2 3,1 2 3))', 'MULTICURVE M (CIRCULARSTRING M (1 2 3,1 2 3,1 2 3))' ],
+    
+    'MULTICURVE (CIRCULARSTRING ZM (1 2 3,1 2 3,1 2 3))' => 
+    [ 'MULTICURVE ZM (CIRCULARSTRING ZM (1 2 3 0,1 2 3 0,1 2 3 0))', 'MULTICURVE ZM (CIRCULARSTRING ZM (1 2 3 0,1 2 3 0,1 2 3 0))' ],
+    
+    'MULTICURVE Z (CIRCULARSTRING (1 2 3,1 2 3,1 2 3))' => 
+    [ 'MULTICURVE Z (CIRCULARSTRING Z (1 2 3,1 2 3,1 2 3))', 'MULTICURVE Z (CIRCULARSTRING Z (1 2 3,1 2 3,1 2 3))' ],
+    
+    'MULTICURVE Z (CIRCULARSTRING Z (1 2 3,1 2 3,1 2 3))' => 
+    [ 'MULTICURVE Z (CIRCULARSTRING Z (1 2 3,1 2 3,1 2 3))', 'MULTICURVE Z (CIRCULARSTRING Z (1 2 3,1 2 3,1 2 3))' ],
+    
+    'MULTICURVE Z (CIRCULARSTRING M (1 2 3,1 2 3,1 2 3))' => 
+    [ 'MULTICURVE ZM (CIRCULARSTRING ZM (1 2 0 3,1 2 0 3,1 2 0 3))', 'MULTICURVE ZM (CIRCULARSTRING ZM (1 2 0 3,1 2 0 3,1 2 0 3))' ],
+    
+    'MULTICURVE Z (CIRCULARSTRING ZM (1 2 3,1 2 3,1 2 3))' => 
+    [ 'MULTICURVE ZM (CIRCULARSTRING ZM (1 2 3 0,1 2 3 0,1 2 3 0))', 'MULTICURVE ZM (CIRCULARSTRING ZM (1 2 3 0,1 2 3 0,1 2 3 0))' ],
+    
+    'MULTICURVE M (CIRCULARSTRING (1 2 3,1 2 3,1 2 3))' => ['error', 'error'],
+    
+    'MULTICURVE M (CIRCULARSTRING Z (1 2 3,1 2 3,1 2 3))' => ['error', 'error'],
+    
+    'MULTICURVE M (CIRCULARSTRING M (1 2 3,1 2 3,1 2 3))' => 
+    [ 'MULTICURVE M (CIRCULARSTRING M (1 2 3,1 2 3,1 2 3))', 'MULTICURVE M (CIRCULARSTRING M (1 2 3,1 2 3,1 2 3))' ],
+
+    'MULTICURVE M (CIRCULARSTRING ZM (1 2 3,1 2 3,1 2 3))' => 
+    [ 'MULTICURVE ZM (CIRCULARSTRING ZM (1 2 3 0,1 2 3 0,1 2 3 0))', 'MULTICURVE ZM (CIRCULARSTRING ZM (1 2 3 0,1 2 3 0,1 2 3 0))' ],
+
+    'MULTICURVE ZM (CIRCULARSTRING (1 2 3,1 2 3,1 2 3))' => 
+    [ 'MULTICURVE ZM (CIRCULARSTRING ZM (1 2 3 0,1 2 3 0,1 2 3 0))', 'MULTICURVE ZM (CIRCULARSTRING ZM (1 2 3 0,1 2 3 0,1 2 3 0))' ],
+
+    'MULTICURVE ZM (CIRCULARSTRING Z (1 2 3,1 2 3,1 2 3))' => 
+    [ 'MULTICURVE ZM (CIRCULARSTRING ZM (1 2 3 0,1 2 3 0,1 2 3 0))', 'MULTICURVE ZM (CIRCULARSTRING ZM (1 2 3 0,1 2 3 0,1 2 3 0))' ],
+
+'MULTICURVE ZM (CIRCULARSTRING M (1 2 3,1 2 3,1 2 3))' => 
+    [ 'MULTICURVE ZM (CIRCULARSTRING ZM (1 2 0 3,1 2 0 3,1 2 0 3))', 'MULTICURVE ZM (CIRCULARSTRING ZM (1 2 0 3,1 2 0 3,1 2 0 3))' ],
+
+'MULTICURVE ZM (CIRCULARSTRING ZM (1 2 3,1 2 3,1 2 3))' => 
+    [ 'MULTICURVE ZM (CIRCULARSTRING ZM (1 2 3 0,1 2 3 0,1 2 3 0))', 'MULTICURVE ZM (CIRCULARSTRING ZM (1 2 3 0,1 2 3 0,1 2 3 0))' ],
+
+    'POINT (1 2)' => 
+    [ 'POINT (1 2)', 'POINT (1 2)' ],
+'POINT (1 2 3)' => 
+    [ 'POINT Z (1 2 3)', 'POINT (1 2 3)' ],
+'POINT (1 2 3 4)' => 
+    [ 'POINT ZM (1 2 3 4)', 'POINT (1 2 3)' ],
+'POINT Z (1 2)' => 
+    [ 'POINT Z (1 2 0)', 'POINT (1 2 0)' ],
+'POINT Z (1 2 3)' => 
+    [ 'POINT Z (1 2 3)', 'POINT (1 2 3)' ],
+'POINT Z (1 2 3 4)' => 
+    [ 'POINT Z (1 2 3)', 'POINT (1 2 3)' ],
+'POINT M (1 2)' => 
+    [ 'POINT M (1 2 0)', 'POINT (1 2)' ],
+'POINT M (1 2 3)' => 
+    [ 'POINT M (1 2 3)', 'POINT (1 2)' ],
+'POINT M (1 2 3 4)' => 
+    [ 'POINT ZM (1 2 3 4)', 'POINT (1 2 3)' ],
+'POINT ZM (1 2)' => 
+    [ 'POINT ZM (1 2 0 0)', 'POINT (1 2 0)' ],
+'POINT ZM (1 2 3)' => 
+    [ 'POINT ZM (1 2 3 0)', 'POINT (1 2 3)' ],
+'POINT ZM (1 2 3 4)' => 
+    [ 'POINT ZM (1 2 3 4)', 'POINT (1 2 3)' ],
+'LINESTRING (1 2,1 2)' => 
+    [ 'LINESTRING (1 2,1 2)', 'LINESTRING (1 2,1 2)' ],
+'LINESTRING (1 2 3,1 2 3)' => 
+    [ 'LINESTRING Z (1 2 3,1 2 3)', 'LINESTRING (1 2 3,1 2 3)' ],
+'LINESTRING (1 2 3 4,1 2 3 4)' => 
+    [ 'LINESTRING ZM (1 2 3 4,1 2 3 4)', 'LINESTRING (1 2 3,1 2 3)' ],
+'LINESTRING Z (1 2,1 2)' => 
+    [ 'LINESTRING Z (1 2 0,1 2 0)', 'LINESTRING (1 2 0,1 2 0)' ],
+'LINESTRING Z (1 2 3,1 2 3)' => 
+    [ 'LINESTRING Z (1 2 3,1 2 3)', 'LINESTRING (1 2 3,1 2 3)' ],
+'LINESTRING Z (1 2 3 4,1 2 3 4)' => 
+    [ 'LINESTRING Z (1 2 3,1 2 3)', 'LINESTRING (1 2 3,1 2 3)' ],
+'LINESTRING M (1 2,1 2)' => 
+    [ 'LINESTRING M (1 2 0,1 2 0)', 'LINESTRING (1 2,1 2)' ],
+'LINESTRING M (1 2 3,1 2 3)' => 
+    [ 'LINESTRING M (1 2 3,1 2 3)', 'LINESTRING (1 2,1 2)' ],
+'LINESTRING M (1 2 3 4,1 2 3 4)' => 
+    [ 'LINESTRING ZM (1 2 3 4,1 2 3 4)', 'LINESTRING (1 2 3,1 2 3)' ],
+'LINESTRING ZM (1 2,1 2)' => 
+    [ 'LINESTRING ZM (1 2 0 0,1 2 0 0)', 'LINESTRING (1 2 0,1 2 0)' ],
+'LINESTRING ZM (1 2 3,1 2 3)' => 
+    [ 'LINESTRING ZM (1 2 3 0,1 2 3 0)', 'LINESTRING (1 2 3,1 2 3)' ],
+'LINESTRING ZM (1 2 3 4,1 2 3 4)' => 
+    [ 'LINESTRING ZM (1 2 3 4,1 2 3 4)', 'LINESTRING (1 2 3,1 2 3)' ],
+
+
+    );
+
+my %wkt = @wkt;
+
+for (my $i = 0; $i < @wkt; $i+=2) {
+    my $key = $wkt[$i];
+    #say "$key"; next;
+    #say "$key, $wkt{$key}"; next;
+    #say "WKT not ok $key $wkt{$key}";
+    my ($type) = $key =~ /^(\w+)/;
+    if ($type =~ /^(\w)(\w+)/) {
+        $type = $1 . lc($2);
+    }
+    $type =~ s/string/String/;
+    my $wkt = $key;
+
+    my $format = 'ISO';
+    for my $out (@{$wkt{$key}}) {
+        my $e = '';
+        if ($format eq 'ISO') {
+            if ($out =~ /ZM/) {
+                $e = ' ZM';
+            } elsif ($out =~ /Z/) {
+                $e = ' Z';
+            } elsif ($out =~ / M /) {
+                $e = ' M'
+            }
+        }
+        my $p;
+        eval {
+            $p = Geo::OGR::Geometry->new(WKT => $wkt);
+        };
+        my $result;
+        my $exp;
+        if ($@) {
+            $result = 'error';
+            $exp = $out;
+        } else {
+            $result = $p->As(Format => $format.' WKT');
+            $exp = $out;
+        }
+        ok($exp eq $result, "$key, $format WKT: expected: $exp, got: $result");
+
+        if ($p) {
+            my $p = Geo::OGR::Geometry->new(WKT => $key);
+            my $exp = '';
+            my $exp2 = '';
+            my $x = $wkt{$key}->[0];
+            if ($x =~ /ZM/) {
+                $exp2 = $exp = 'ZM';
+            } elsif ($x =~ /Z/) {
+                $exp = 'Z';
+                $exp2 = '25D';
+            } elsif ($x =~ / M /) {
+                $exp2 = $exp = 'M'
+            }
+            $exp2 = $type.$exp2;
+            $exp = $type.$exp;
+            my $result = $p->GeometryType;
+            ok(lc($exp) eq lc($result) || lc($exp2) eq lc($result), "$key, $format Type: expected: $exp, got: $result");
+            
+            my $wkb = $p->As(Format => $format.' WKB', ByteOrder => 'NDR');
+            my $len = bytes::length($wkb);
+            my $t = bytes::substr($wkb,1,4);
+            $t = unpack("l",$t);
+            my $q = Geo::OGR::Geometry->new(WKB => $wkb);
+            $exp = $p->As(Format => $format.' WKT');
+            $result = $q->As(Format => $format.' WKT');
+
+            if ($format eq '' and ($key =~ /^POINT (\w*) (|\()EMPTY(|\))/ or $key =~ /^POINT (|\()EMPTY(|\))/)) {
+                if ($1 =~ /Z/) {
+                    $exp = 'POINT (0 0 0)';
+                } else {
+                    $exp = 'POINT (0 0)';
+                }
+            }
+
+            ok($exp eq $result, "$key, WKB: expected: $exp, got: $result ($len,$t)");
+        }
+        $format = '';
+    }
+}
diff --git a/swig/perl/t/00-measures-02.t b/swig/perl/t/00-measures-02.t
new file mode 100644
index 0000000..ea69df6
--- /dev/null
+++ b/swig/perl/t/00-measures-02.t
@@ -0,0 +1,59 @@
+use strict;
+use warnings;
+use bytes;
+use v5.10;
+use Test::More qw(no_plan);
+BEGIN { use_ok('Geo::GDAL') };
+
+# test measured geometries with memory driver
+
+my @data = (
+    PointM => 'POINT M (1 2 3)',
+    );
+my @x = (
+    LineStringM => 'LINESTRING M (1 2 3)',
+    PolygonM => 'POLYGON M ((1 2 3))',
+    MultiPointM => 'MULTIPOINT M ((1 2 3))',
+    MultiLineStringM => 'MULTILINESTRING M ((1 2 3))',
+    MultiPolygonM => 'MULTIPOLYGON M (((1 2 3)))',
+    GeometryCollectionM => 'GEOMETRYCOLLECTION M (POINT M (1 2 3))',
+    CircularStringM => 'CIRCULARSTRING M (1 2 3,1 2 3,1 2 3)',
+    CompoundCurveM => 'COMPOUNDCURVE M ((0 1 2,2 3 4))',
+    CurvePolygonM => 'CURVEPOLYGON M ((0 0 1,0 1 1,1 1 1,1 0 1,0 0 1))',
+    MultiCurveM => 'MULTICURVE M (CIRCULARSTRING M (0 0 2,1 0 2,0 0 2),(0 0 2,1 1 2))',
+    MultiSurfaceM => 'MULTISURFACE M (((1 2 3)))',
+    PointZM => 'POINT ZM (1 2 3 4)',
+    LineStringZM => 'LINESTRING ZM (1 2 3 4)',
+    PolygonZM => 'POLYGON ZM ((1 2 3 4))',
+    MultiPointZM => 'MULTIPOINT ZM ((1 2 3 4))',
+    MultiLineStringZM => 'MULTILINESTRING ZM ((1 2 3 4))',
+    MultiPolygonZM => 'MULTIPOLYGON ZM (((1 2 3 4)))',
+    GeometryCollectionZM => 'GEOMETRYCOLLECTION ZM (POINT ZM (1 2 3 4))',
+    CircularStringZM => 'CIRCULARSTRING ZM (1 2 3 4,1 2 3 4,1 2 3 4)',
+    CompoundCurveZM => 'COMPOUNDCURVE ZM ((0 1 2 3,2 3 4 5))',
+    CurvePolygonZM => 'CURVEPOLYGON ZM ((0 0 1 2,0 1 1 2,1 1 1 2,1 0 1 2,0 0 1 2))',
+    MultiCurveZM => 'MULTICURVE ZM (CIRCULARSTRING ZM (0 0 2 3,1 0 2 3,0 0 2 3),(0 0 2 3,1 1 2 3))',
+    MultiSurfaceZM => 'MULTISURFACE ZM (((1 2 3 4)))',
+);
+
+for (my $i = 0; $i < @data; $i+=2) {
+    my $type = $data[$i];
+    #next unless $type eq 'CompoundCurveM';
+    my $l = Geo::OGR::Driver('Memory')->Create('test')->CreateLayer(GeometryType => $type);
+    eval {
+        my $g = Geo::OGR::Geometry->new(WKT => $data[$i+1]);
+        $l->InsertFeature({Geometry => {WKT => $data[$i+1]}});
+    };
+    if ($@) {
+        say "not ok: $type => $data[$i+1] ($@)";
+        next;
+    }
+    $l->ResetReading;
+    while (my $f = $l->GetNextFeature()) {
+        my $g = $f->GetGeometryRef;
+        my $t = $g->GeometryType;
+        ok($t eq $type, "$type, type: $t");
+        my $wkt = $g->As(Format => 'ISO WKT');
+        ok($wkt eq $data[$i+1], "$type, expected: $data[$i+1] got: $wkt");
+    }
+}
diff --git a/swig/perl/t/00-measures-03.t b/swig/perl/t/00-measures-03.t
new file mode 100644
index 0000000..560dbda
--- /dev/null
+++ b/swig/perl/t/00-measures-03.t
@@ -0,0 +1,261 @@
+use strict;
+use warnings;
+use bytes;
+use v5.10;
+use Test::More qw(no_plan);
+BEGIN { use_ok('Geo::GDAL') };
+
+# test measured geometries in shape driver
+
+my @data = (
+    Point => 'POINT (1 2)',
+    LineString => 'LINESTRING (1 2)',
+    Polygon => 'POLYGON ((1 2))',
+    MultiPoint => 'MULTIPOINT ((1 2))',
+
+    PointZ => 'POINT Z (1 2 3)',
+    LineStringZ => 'LINESTRING Z (1 2 3)',
+    PolygonZ => 'POLYGON Z ((1 2 3))',
+    MultiPointZ => 'MULTIPOINT Z ((1 2 3))',
+
+    PointM => 'POINT M (1 2 3)',
+    LineStringM => 'LINESTRING M (1 2 3)',
+    PolygonM => 'POLYGON M ((1 2 3))',
+    MultiPointM => 'MULTIPOINT M ((1 2 3))',
+
+    MultiLineStringM => 'MULTILINESTRING M ((1 2 3))',
+    MultiPolygonM => 'MULTIPOLYGON M (((1 2 3)))',
+#    CircularStringM => 'CIRCULARSTRING M (1 2 3,1 2 3,1 2 3)',
+#    CompoundCurveM => 'COMPOUNDCURVE M ((0 1 2,2 3 4))',
+#    CurvePolygonM => 'CURVEPOLYGON M ((0 0 1,0 1 1,1 1 1,1 0 1,0 0 1))',
+#    MultiCurveM => 'MULTICURVE M (CIRCULARSTRING M (0 0 2,1 0 2,0 0 2),(0 0 2,1 1 2))',
+#    MultiSurfaceM => 'MULTISURFACE M (((1 2 3)))',
+
+    PointZM => 'POINT ZM (1 2 3 4)',
+    LineStringZM => 'LINESTRING ZM (1 2 3 4)',
+    PolygonZM => 'POLYGON ZM ((1 2 3 4))',
+    MultiPointZM => 'MULTIPOINT ZM ((1 2 3 4))',
+
+    MultiLineStringZM => 'MULTILINESTRING ZM ((1 2 3 4))',
+    MultiPolygonZM => 'MULTIPOLYGON ZM (((1 2 3 4)))',
+#    CircularStringZM => 'CIRCULARSTRING ZM (1 2 3 4,1 2 3 4,1 2 3 4)',
+#    CompoundCurveZM => 'COMPOUNDCURVE ZM ((0 1 2 3,2 3 4 5))',
+#    CurvePolygonZM => 'CURVEPOLYGON ZM ((0 0 1 2,0 1 1 2,1 1 1 2,1 0 1 2,0 0 1 2))',
+#    MultiCurveZM => 'MULTICURVE ZM (CIRCULARSTRING ZM (0 0 2 3,1 0 2 3,0 0 2 3),(0 0 2 3,1 1 2 3))',
+#    MultiSurfaceZM => 'MULTISURFACE ZM (((1 2 3 4)))',
+);
+
+my $driver = 'ESRI Shapefile';
+my $dir = '/vsimem/';
+
+if (1) {
+for (my $i = 0; $i < @data; $i+=2) {
+    my $type = $data[$i];
+    my $l = Geo::OGR::Driver($driver)->Create($dir.$type.'.shp')->CreateLayer(GeometryType => $type);
+    eval {
+        $l->InsertFeature({Geometry => {WKT => $data[$i+1]}});
+    };
+    if ($@) {
+        my @e = split /\n/, $@;
+        $e[0] =~ s/\. at .*/./;
+        ok(0, "$driver, insert feature: $type => $data[$i+1] ($e[0])");
+        next;
+    }
+    
+    # close and open
+    undef $l;
+    $l = Geo::OGR::Open($dir)->GetLayer($type);
+    my $t = $l->GeometryType;
+    $t =~ s/25D/Z/;
+    my $exp = $type;
+    $exp =~ s/^Multi// if $exp =~ /MultiLine|MultiPoly/;
+    ok($t eq $exp, "$driver layer geom type: expected: $exp, got: $t");
+
+    $l->ResetReading;
+    while (my $f = $l->GetNextFeature()) {
+        my $g = $f->GetGeometryRef;
+        my $t = $g->GeometryType;
+        $t =~ s/25D/Z/;
+        my $exp = $type;
+        $exp =~ s/^Multi// if $exp =~ /MultiLine|MultiPoly/;
+        ok($t eq $exp, "$driver retrieve feature: expected: $exp, got: $t");
+        my $wkt = $g->As(Format => 'ISO WKT');
+        $exp = $data[$i+1];
+        if ($exp =~ /MULTILINE|MULTIPOLY/) {
+            $exp =~ s/^MULTI//;
+            $exp =~ s/\(\(/\(/;
+            $exp =~ s/\)\)/\)/;
+        }
+        ok($wkt eq $exp, "$driver retrieve feature: $type, expected: $exp got: $wkt");
+    }
+}
+}
+
+# test opening with requested type
+
+ at data = (
+    Point => 'POINT (1 2)',
+    LineString => 'LINESTRING (1 2)',
+    Polygon => 'POLYGON ((1 2))',
+    MultiPoint => 'MULTIPOINT ((1 2))',
+
+    PointZ => 'POINT Z (1 2 3)',
+    LineStringZ => 'LINESTRING Z (1 2 3)',
+    PolygonZ => 'POLYGON Z ((1 2 3))',
+    MultiPointZ => 'MULTIPOINT Z ((1 2 3))',
+
+    PointM => 'POINT M (1 2 3)',
+    LineStringM => 'LINESTRING M (1 2 3)',
+    PolygonM => 'POLYGON M ((1 2 3))',
+    MultiPointM => 'MULTIPOINT M ((1 2 3))',
+
+    PointZM => 'POINT ZM (1 2 3 4)',
+    LineStringZM => 'LINESTRING ZM (1 2 3 4)',
+    PolygonZM => 'POLYGON ZM ((1 2 3 4))',
+    MultiPointZM => 'MULTIPOINT ZM ((1 2 3 4))',
+);
+my %data = @data;
+
+my @shpt = (POINT => 'Point', ARC => 'LineString', POLYGON => 'Polygon', MULTIPOINT => 'MultiPoint');
+my %shpt = @shpt;
+
+my %type2shpt;
+for (my $j = 0; $j < @shpt; $j+=2) {
+    $type2shpt{$shpt[$j+1]} = $shpt[$j];
+}
+
+if (1) {
+for (my $i = 0; $i < @data; $i+=2) {
+    my $type = $data[$i];
+    my $basetype = $type;
+    $basetype =~ s/(M|Z|ZM)$//;
+    my $shpt = $type2shpt{$basetype};
+    for my $dim ('','Z','M','ZM') {
+        my $l = Geo::OGR::Driver($driver)->Create($dir.$type.'.shp')->CreateLayer(
+            GeometryType => 'Unknown', 
+            Options => { SHPT => $shpt.$dim });
+        #my $wkt = $data{$basetype.$dim};
+        #my $f0 = Geo::OGR::Feature->new(GeometryType => $basetype.$dim);
+        #$f0->Geometry({WKT => $wkt});
+        my $wkt = $data[$i+1];
+        my $f0 = Geo::OGR::Feature->new(GeometryType => $type);
+        $f0->Geometry({WKT => $wkt});
+        eval {
+            $l->CreateFeature($f0);
+        };
+        if ($@) {
+            my @e = split /\n/, $@;
+            $e[0] =~ s/\. at .*/./;
+            ok(0, "$driver with option SHPT=$shpt$dim, insert feature: $type => $wkt ($e[0])");
+            next;
+        } else {
+            ok(1, "$driver with option SHPT=$shpt$dim, insert feature: $type => $wkt");
+        }
+        
+        # close and open
+        undef $l;
+        my $adjust = 'NO';
+        if ($dim eq 'Z') { # M is added implicitly
+            $adjust = 'ALL_SHAPES'; # but we strip it away with this
+        }
+        $l = Geo::GDAL::OpenEx(name => $dir, options => {ADJUST_GEOM_TYPE=>$adjust})->GetLayer($type);
+        my $t = $l->GeometryType;
+        $t =~ s/25D/Z/;
+        my $exp = $shpt{$shpt}.$dim;
+        ok($t eq $exp, "$driver with option SHPT=$shpt$dim layer geom type ($type): expected: $exp, got: $t");
+        
+        $l->ResetReading;
+        while (my $f = $l->GetNextFeature()) {
+            my $g = $f->GetGeometryRef;
+            my $t = $g->GeometryType;
+            $t =~ s/25D/Z/;
+            my $exp = $basetype.$dim;
+            ok($t eq $exp, "$driver with option SHPT=$shpt$dim retrieve feature: expected: $exp, got: $t");
+            my $wkt = $g->As(Format => 'ISO WKT');
+            $exp = $data{$basetype.$dim};
+            if (!($type =~ /M$/) and $dim eq 'M') {
+                $exp =~ s/3/-0/;
+            } elsif (($type =~ /ZM$/) and $dim eq 'Z') {
+            } elsif (!($type =~ /Z$/) and $dim eq 'Z') {
+                $exp =~ s/3/0/;
+            } elsif (($type =~ /ZM$/) and $dim eq 'M') {
+                $exp =~ s/4 //;
+                $exp =~ s/3/4/;
+            } elsif (($type =~ /Z$/) and $dim eq 'ZM') {
+                $exp =~ s/4/-0/;
+            } elsif (($type =~ /ZM$/) and $dim eq 'ZM') {
+            } elsif (($type =~ /ZM$/) and $dim eq 'ZM') {
+                $exp =~ s/3 //;
+            } elsif (($type =~ /M$/) and $dim eq 'ZM') {
+                $exp =~ s/3/0/;
+                $exp =~ s/4/3/;
+            } elsif (!($type =~ /ZM$/) and $dim eq 'ZM') {
+                $exp =~ s/3/0/;
+                $exp =~ s/4/-0/;
+            }
+            $wkt =~ s/-[\d\.e\+]+/-0/; # "no data" M to "-0"
+            ok($wkt eq $exp, "$driver with option SHPT=$shpt$dim retrieve feature: expected: $exp got: $wkt");
+        }
+    }
+}
+}
+
+# test using no data M values 
+
+ at data = (
+    PointM => 'POINT M (1 2 -2E38)',
+    LineStringM => 'LINESTRING M (1 2 -2E38)',
+    PolygonM => 'POLYGON M ((1 2 -2E38))',
+    MultiPointM => 'MULTIPOINT M ((1 2 -2E38))',
+
+    PointZM => 'POINT ZM (1 2 3 -2E38)',
+    LineStringZM => 'LINESTRING ZM (1 2 3 -2E38)',
+    PolygonZM => 'POLYGON ZM ((1 2 3 -2E38))',
+    MultiPointZM => 'MULTIPOINT ZM ((1 2 3 -2E38))',
+);
+
+my $test = "$driver with no data M";
+
+if (0) {
+for (my $i = 0; $i < @data; $i+=2) {
+    my $type = $data[$i];
+    my $basetype = $type;
+    $basetype =~ s/(M|Z|ZM)$//;
+    my $fallback_type = $basetype;
+    $fallback_type .= $type =~ /ZM$/ ? 'Z' : '';
+    my $l = Geo::OGR::Driver($driver)->Create($dir.$type.'.shp')->CreateLayer(GeometryType => $type);
+    eval {
+        $l->InsertFeature({Geometry => { WKT => $data[$i+1] }});
+    };
+    if ($@) {
+        my @e = split /\n/, $@;
+        $e[0] =~ s/\. at .*/./;
+        ok(0, "$test, insert feature: $type => $data[$i+1] ($e[0])");
+        next;
+    } else {
+        ok(1, "$test, insert feature: $type => $data[$i+1]");
+    }
+    
+    # close and open
+    undef $l;
+    $l = Geo::OGR::Open($dir)->GetLayer($type);
+    my $t = $l->GeometryType;
+    $t =~ s/25D/Z/;
+    my $exp = $fallback_type;
+    ok($t eq $exp, "$test layer geom type: expected: $exp, got: $t");
+    
+    $l->ResetReading;
+    while (my $f = $l->GetNextFeature()) {
+        my $g = $f->GetGeometryRef;
+        my $t = $g->GeometryType;
+        $t =~ s/25D/Z/;
+        my $exp = $fallback_type;
+        ok($t eq $exp, "$test retrieve feature: expected: $exp, got: $t");
+        my $wkt = $g->As(Format => 'ISO WKT');
+        $exp = $data[$i+1];
+        $exp =~ s/ -2E38//;
+        $exp =~ s/M //;
+        ok($wkt eq $exp, "$test retrieve feature: $type, expected: $exp got: $wkt");
+    }
+}
+}
diff --git a/swig/perl/t/00-measures-04.t b/swig/perl/t/00-measures-04.t
new file mode 100644
index 0000000..de54d8d
--- /dev/null
+++ b/swig/perl/t/00-measures-04.t
@@ -0,0 +1,83 @@
+use strict;
+use warnings;
+use bytes;
+use v5.10;
+use Test::More qw(no_plan);
+BEGIN { use_ok('Geo::GDAL') };
+
+# test measured geometries in pg driver
+
+#Geo::GDAL::SetConfigOption('CPL_DEBUG', 'ON');
+#Geo::GDAL::DontUseExceptions();
+
+my @data = (
+    Point => 'POINT (1 2)',
+    PointZ => 'POINT Z (1 2 3)',
+    PointM => 'POINT M (1 2 3)',
+    PointZM => 'POINT ZM (1 2 3 4)',
+
+    LineStringM => 'LINESTRING M (1 2 3)',
+    LineStringZM => 'LINESTRING ZM (1 2 3 4,5 6 7 8)',
+
+    PolygonM => 'POLYGON M ((1 2 3))',
+    MultiPointM => 'MULTIPOINT M ((1 2 3))',
+    MultiLineStringM => 'MULTILINESTRING M ((1 2 3))',
+    MultiPolygonM => 'MULTIPOLYGON M (((1 2 3)))',
+    CircularStringM => 'CIRCULARSTRING M (1 2 3,1 2 3,1 2 3)',
+    CompoundCurveM => 'COMPOUNDCURVE M ((0 1 2,2 3 4))',
+    CurvePolygonM => 'CURVEPOLYGON M ((0 0 1,0 1 1,1 1 1,1 0 1,0 0 1))',
+    MultiCurveM => 'MULTICURVE M (CIRCULARSTRING M (0 0 2,1 0 2,0 0 2),(0 0 2,1 1 2))',
+    MultiSurfaceM => 'MULTISURFACE M (((1 2 3)))',
+
+    PolygonZM => 'POLYGON ZM ((1 2 3 4,5 6 7 8,9 6 7 8,1 2 3 0))',
+    MultiPointZM => 'MULTIPOINT ZM ((1 2 3 4))',
+    MultiLineStringZM => 'MULTILINESTRING ZM ((1 2 3 4,5 6 7 8))',
+    MultiPolygonZM => 'MULTIPOLYGON ZM (((1 2 3 4,5 6 7 8,9 6 7 8,1 2 3 0)))',
+    CircularStringZM => 'CIRCULARSTRING ZM (1 2 3 4,1 2 3 4,1 2 3 4)',
+    CompoundCurveZM => 'COMPOUNDCURVE ZM ((0 1 2 3,2 3 4 5))',
+    CurvePolygonZM => 'CURVEPOLYGON ZM ((0 0 1 2,0 1 1 2,1 1 1 2,1 0 1 2,0 0 1 2))',
+    MultiCurveZM => 'MULTICURVE ZM (CIRCULARSTRING ZM (0 0 2 3,1 0 2 3,0 0 2 3),(0 0 2 3,1 1 2 3))',
+    MultiSurfaceZM => 'MULTISURFACE ZM (((1 2 3 4,5 6 7 8,9 6 7 8,1 2 3 0)))',
+);
+
+my $driver = 'PostgreSQL';
+
+for (my $i = 0; $i < @data; $i+=2) {
+    my $type = $data[$i];
+    eval {
+        Geo::OGR::Open('PG:dbname=autotest', 1)->DeleteLayer(lc($type));
+    };
+    my $l = Geo::OGR::Open('PG:dbname=autotest', 1)->CreateLayer(Name => $type, GeometryType => $type);
+    my $t = $l->GeometryType;
+    $t = 'PointZ' if $t eq 'Point25D';
+    ok($t eq $type, "$driver layer geom type: expected: $type, got: $t");
+    eval {
+        $l->InsertFeature({Geometry => {WKT => $data[$i+1]} });
+    };
+    if ($@) {
+        my @e = split /\n/, $@;
+        $e[0] =~ s/\. at .*/./;
+        ok(0, "$driver, insert feature: $type => $data[$i+1] ($e[0])");
+        undef $l;
+        Geo::OGR::Open('PG:dbname=autotest', 1)->DeleteLayer(lc($type));
+        next;
+    }
+
+    # close and open
+    $l = Geo::OGR::Open('PG:dbname=autotest')->Layer($type);
+    $t = $l->GeometryType;
+    $t = 'PointZ' if $t eq 'Point25D';
+    ok($t eq $type, "$driver layer geom type: expected: $type, got: $t");
+
+    $l->ResetReading;
+    while (my $f = $l->GetNextFeature()) {
+        my $g = $f->GetGeometryRef;
+        my $t = $g->GeometryType;
+        $t = 'PointZ' if $t eq 'Point25D';
+        ok($t eq $type, "$driver retrieve feature: expected: $type, got: $t");
+        my $wkt = $g->As(Format => 'ISO WKT');
+        ok($wkt eq $data[$i+1], "$driver retrieve feature: $type, expected: $data[$i+1] got: $wkt");
+    }
+
+    Geo::OGR::Open('PG:dbname=autotest', 1)->DeleteLayer(lc($type));
+}
diff --git a/swig/perl/t/00.t b/swig/perl/t/00.t
index 9d3cfea..022c12e 100644
--- a/swig/perl/t/00.t
+++ b/swig/perl/t/00.t
@@ -3,106 +3,192 @@ use warnings;
 use Scalar::Util 'blessed';
 use Test::More qw(no_plan);
 BEGIN { use_ok('Geo::GDAL') };
-Geo::GDAL::PushFinderLocation('../../data');
 
-# Documented subs in Geo::GDAL 
+# list of subs to test (documented subroutines) obtained with
+# perl parse-for-doxygen.pl | grep '^sub \|package'
+# the subs should be listed on test programs with 'ok', 'below', or 'above' added
+
+my @list;
+
+# package Geo::GDAL
+#
+# sub AccessTypes ok
+
+eval {
+    @list = Geo::GDAL::AccessTypes();
+};
+ok((@list > 0 and $@ eq ''), "AccessTypes, got $@");
+
+# sub AutoCreateWarpedVRT
+
+# sub CPLBinaryToHex ok
+# sub CPLHexToBinary ok
 
 my $binary = Geo::GDAL::CPLHexToBinary('ab10');
 my $hex = Geo::GDAL::CPLBinaryToHex($binary);
 ok($hex eq 'AB10', "CPLHexToBinary and CPLBinaryToHex, got $hex");
 
+# sub Child
+# sub Children
+# sub ComputeMedianCutPCT
+# sub ComputeProximity
+
+# sub DataTypeIsComplex ok
+# sub DataTypeValueRange ok
+# sub DataTypes ok
+
+eval {
+    @list = Geo::GDAL::DataTypes();
+};
+ok((@list > 0 and $@ eq ''), "DataTypes, got $@");
+
+for my $type (Geo::GDAL::DataTypes()) {
+    my $nr = $Geo::GDAL::TYPE_STRING2INT{$type};
+    my $c = Geo::GDAL::GetDataTypeName($nr);
+    ok($type eq $c, "Data type $type");
+    eval {
+        my $scalar = Geo::GDAL::DataTypeIsComplex($type);
+        @list = Geo::GDAL::DataTypeValueRange($type);
+        $scalar = Geo::GDAL::GetDataTypeSize($type);
+        $scalar = Geo::GDAL::PackCharacter($type);
+    };
+    ok(($@ eq '' and ($type eq 'Unknown' or @list == 2)), 
+       "$type: DataTypeIsComplex, DataTypeValueRange, GetDataTypeSize, PackCharacter, got $@ and ".scalar(@list));
+}
+
+# sub Debug
+
+# sub DecToDMS ok
+# sub DecToPackedDMS ok
+
 my $dms = Geo::GDAL::DecToDMS(62, 'Long');
 ok($dms eq " 62d 0' 0.00\"E", "DecToDMS, got '$dms'"),
 $dms = Geo::GDAL::DecToPackedDMS(62.15);
 my $dec = Geo::GDAL::PackedDMSToDec($dms);
+$dec = sprintf("%.2f", $dec);
 ok($dec == 62.15, "DecToPackedDMS and PackedDMSToDec, got $dec");
 
+# sub DitherRGB2PCT
+
+# sub EscapeString ok
+
 my $s = Geo::GDAL::EscapeString("abc");
 ok($s eq 'abc', "EscapeString, got $s");
 
-Geo::GDAL::SetConfigOption('foo', 'bar');
-$s = Geo::GDAL::GetConfigOption('foo');
-ok($s eq 'bar', "SetConfigOption and GetConfigOption, got $s");
+# sub FindFile ok
 
-Geo::GDAL::SetCacheMax(1000000);
-$s = Geo::GDAL::GetCacheMax();
-ok($s == 1000000, "SetCacheMax and GetCacheMax, got $s");
-$s = Geo::GDAL::GetCacheUsed();
-ok($s == 0, "GetCacheUsed, got $s");
+SKIP: {
+    $s = Geo::GDAL::FindFile('', 'gcs.csv');
+
+    skip "GDAL support files not found. Please set GDAL_DATA.", 1 unless $s;
+
+    ok($s, "FindFile, got $s");
+}
+
+# sub FinderClean ok
 
 eval {
     Geo::GDAL::PushFinderLocation('abc');
     Geo::GDAL::PopFinderLocation();
     Geo::GDAL::FinderClean();
-    Geo::GDAL::PushFinderLocation('../../data');
 };
 ok($@ eq '', "FinderClean, PushFinderLocation and PopFinderLocation, got $@");
 
-$s = Geo::GDAL::FindFile('', 'gcs.csv');
-print STDERR "Can't find GDAL support files. Expect an error below. Please set GDAL_DATA.\n" unless $s;
+# sub GOA2GetAccessToken
+# sub GOA2GetAuthorizationURL
+# sub GOA2GetRefreshToken
 
-my @list;
+# sub GetCacheMax ok
+# sub GetCacheUsed ok
 
-eval {
-    @list = Geo::GDAL::AccessTypes();
-};
-ok((@list > 0 and $@ eq ''), "AccessTypes, got $@");
+Geo::GDAL::SetCacheMax(1000000);
+$s = Geo::GDAL::GetCacheMax();
+ok($s == 1000000, "SetCacheMax and GetCacheMax, got $s");
+$s = Geo::GDAL::GetCacheUsed();
+ok($s == 0, "GetCacheUsed, got $s");
 
-eval {
-    @list = Geo::GDAL::DataTypes();
-};
-ok((@list > 0 and $@ eq ''), "DataTypes, got $@");
+# sub GetConfigOption ok
+
+Geo::GDAL::SetConfigOption('foo', 'bar');
+$s = Geo::GDAL::GetConfigOption('foo');
+ok($s eq 'bar', "SetConfigOption and GetConfigOption, got $s");
+
+# sub GetDataTypeSize above
+# sub GetDriver ok
+
+for my $name (Geo::GDAL::GetDriverNames()) {
+    my $driver;
+    eval {
+        $driver = Geo::GDAL::GetDriver($name);
+    };
+    ok($driver, "$name: GetDriver");
+}
+
+# sub GetDriverNames ok
 
 eval {
     @list = Geo::GDAL::GetDriverNames();
 };
 ok((@list > 0 and $@ eq ''), "GetDriverNames, got $@");
 
+# sub GetJPEG2000StructureAsString
+# sub IdentifyDriver below (Driver->Create)
+# sub NodeData
+# sub NodeType ok
+# sub NodeTypes ok
+
 eval {
     @list = Geo::GDAL::NodeTypes();
 };
 ok((@list > 0 and $@ eq ''), "NodeTypes, got $@");
 
+# sub Open
+# sub OpenEx
+# sub OpenShared
+# sub PackCharacter
+# sub PackedDMSToDec above
+# sub ParseXMLString ok
+
+my $xml = '<PAMDataset><Metadata><MDI key="PyramidResamplingType">NEAREST</MDI></Metadata></PAMDataset>';
+
+my $a = Geo::GDAL::ParseXMLString($xml);
+my @elements;
+traverse($a);
+ok((@elements == 6 and $elements[5][0] eq 'Text' and $elements[5][1] eq 'NEAREST'), "XML parsing and traversing");
+
+# sub Polygonize
+# sub PopFinderLocation ok
+# sub PushFinderLocation ok
+# sub RIOResamplingTypes ok
+
 eval {
     @list = Geo::GDAL::RIOResamplingTypes();
 };
 ok((@list > 0 and $@ eq ''), "RIOResamplingTypes, got $@");
 
+# sub RasterizeLayer
+# sub ReprojectImage
+# sub ResamplingTypes ok
+
 eval {
     @list = Geo::GDAL::ResamplingTypes();
 };
 ok((@list > 0 and $@ eq ''), "ResamplingTypes, got $@");
 
-for my $type (Geo::GDAL::DataTypes()) {
-    my $nr = $Geo::GDAL::TYPE_STRING2INT{$type};
-    my $c = Geo::GDAL::GetDataTypeName($nr);
-    ok($type eq $c, "Data type $type");
-    eval {
-        my $scalar = Geo::GDAL::DataTypeIsComplex($type);
-        @list = Geo::GDAL::DataTypeValueRange($type);
-        $scalar = Geo::GDAL::GetDataTypeSize($type);
-        $scalar = Geo::GDAL::PackCharacter($type);
-    };
-    ok(($@ eq '' and ($type eq 'Unknown' or @list == 2)), 
-       "$type: DataTypeIsComplex, DataTypeValueRange, GetDataTypeSize, PackCharacter, got $@ and ".scalar(@list));
-}
-
-for my $name (Geo::GDAL::GetDriverNames()) {
-    my $driver;
-    eval {
-        $driver = Geo::GDAL::GetDriver($name);
-    };
-    ok($driver, "$name: GetDriver");
-}
+# sub SerializeXMLTree ok
 
+my $xml2 = Geo::GDAL::SerializeXMLTree($a);
+$xml2 =~ s/\s//g;
+$xml2 =~ s/key/ key/g;
+ok($xml2 eq $xml, "SerializeXMLTree, got $xml2");
 
-my $xml = '<PAMDataset><Metadata><MDI key="PyramidResamplingType">NEAREST</MDI></Metadata></PAMDataset>';
+# sub SetCacheMax
+# sub SetConfigOption above
+# sub SieveFilter
+# sub VersionInfo ok
 
-my $a = Geo::GDAL::ParseXMLString($xml);
-my @elements;
-traverse($a);
-ok((@elements == 6 and $elements[5][0] eq 'Text' and $elements[5][1] eq 'NEAREST'), 
-   "XML parsing and traversing");
+my $VersionInfo = Geo::GDAL::VersionInfo('VERSION_NUM');
+ok($VersionInfo, "VersionInfo, got $VersionInfo");
 
 sub traverse {
     my $node = shift;
@@ -115,90 +201,70 @@ sub traverse {
     }
 }
 
-my $xml2 = Geo::GDAL::SerializeXMLTree($a);
-$xml2 =~ s/\s//g;
-$xml2 =~ s/key/ key/g;
-ok($xml2 eq $xml, "SerializeXMLTree, got $xml2");
+# package Geo::GDAL::AsyncReader
+#
+# sub GetNextUpdatedRegion
+# sub LockBuffer
+# sub UnlockBuffer
 
-my $VersionInfo = Geo::GDAL::VersionInfo('VERSION_NUM');
-ok($VersionInfo, "VersionInfo, got $VersionInfo");
+
+# package Geo::GDAL::GeoTransform
+#
+# sub Apply
+# sub FromGCPs
+# sub Inv
+# sub new ok
 
 my $dataset = Geo::GDAL::Driver('MEM')->Create();
 my $transform = Geo::GDAL::GeoTransform->new;
 $dataset->GeoTransform($transform);
 $transform = $dataset->GeoTransform();
 
-$dataset = Geo::GDAL::Driver('GTiff')->Create(Name => '/vsimem/test.gtiff');
- at list = $dataset->GetFileList();
-undef $dataset;
+# package Geo::GDAL::VSIF
+# sub Close ok
+# sub MkDir ok
+# sub Open ok
+my $vsif = Geo::GDAL::VSIF::Open('/vsimem/test', 'w');
+ok(blessed $vsif, "VSIF Open");
+my $c = $vsif->Write('12345');
+ok($c == 5, "VSIF Write $c");
+$vsif->Close();
+# sub Read ok
+$vsif = Geo::GDAL::VSIF::Open('/vsimem/test', 'r');
+my $r = $vsif->Read($c);
+$vsif->Close();
+ok($r == 12345, "VSIF Read $r");
+# sub ReadDir ok
 
 @list = Geo::GDAL::VSIF::ReadDir('/vsimem/');
-print "@list\n";
-my $driver = Geo::GDAL::IdentifyDriver('/vsimem/test.gtiff');
-print $driver->Name,"\n";
-
-
-$dataset = Geo::GDAL::Open('/vsimem/test.gtiff', 'ReadOnly');
-print "$dataset\n";
-undef $dataset;
-
-$dataset = Geo::GDAL::OpenShared('/vsimem/test.gtiff', 'ReadOnly');
-print "$dataset\n";
-$dataset = Geo::GDAL::OpenEx('/vsimem/test.gtiff');
-print "$dataset\n";
-
-
-__END__
-
-# Classes
-
-AsyncReader
-Band
-ColorTable
-Dataset
-Driver
-GCP
-GeoTransform
-MajorObject
-RasterAttributeTable
-Transformer
-VSIF
-
-__END__
- 
-public method 	Debug ()
- 
-public method 	GOA2GetAccessToken ()
-public method 	GOA2GetAuthorizationURL ()
-public method 	GOA2GetRefreshToken ()
-
-public method 	GetJPEG2000StructureAsString ()
-
-Algorithms:
-
-my $src_srs = Geo::OSR::SpatialReference->new(EPSG => 2392);
-my $dst_srs = Geo::OSR::SpatialReference->new(EPSG => 2393);
-my $ResampleAlg = 'NearestNeighbour';
-my $maxerror = 0.0;
-my $dataset = Geo::GDAL::AutoCreateWarpedVRT($src, $src_srs, $dst_srs, $ResampleAlg, $maxerror);
-
-public method 	DitherRGB2PCT (scalar red, scalar green, scalar blue, scalar target, scalar colors, subref callback, scalar callback_data)
- 
-public method 	ComputeMedianCutPCT (Geo::GDAL::Band red, Geo::GDAL::Band green, Geo::GDAL::Band blue, scalar num_colors, scalar colors, subref callback, scalar callback_data)
- 
-public method 	ComputeProximity (Geo::GDAL::Band src, Geo::GDAL::Band proximity, hashref options, subref callback, scalar callback_data)
-
-public method 	Polygonize (Geo::GDAL::Band src, Geo::GDAL::Band mask, Geo::OGR::Layer out, scalar PixValField, hashref options, subref callback, scalar callback_data)
- 
-public method 	RasterizeLayer (Geo::GDAL::Dataset ds, arrayref bands, Geo::OGR::Layer layer, scalar transformer, scalar arg, arrayref burn_values, hashref options, subref callback, scalar callback_data)
- 
-public method 	RegenerateOverview (Geo::GDAL::Band src, Geo::GDAL::Band overview, scalar resampling, subref callback, scalar callback_data)
- 
-public method 	RegenerateOverviews (Geo::GDAL::Band src, arrayref overviews, scalar resampling, subref callback, scalar callback_data)
- 
-public method 	ReprojectImage (scalar src_ds, scalar dst_ds, scalar src_wkt=undef, scalar dst_wkt=undef, scalar ResampleAlg='NearestNeighbour', scalar WarpMemoryLimit=0, scalar maxerror=0.0, subref callback, scalar callback_data)
- 
-public method 	SieveFilter (Geo::GDAL::Band src, Geo::GDAL::Band mask, Geo::GDAL::Band dst, scalar threshold, scalar connectedness, hashref options, subref callback, scalar callback_data)
- 
-
- 
+ok($list[0] eq 'test', "ReadDir: @list");
+
+eval {
+    Geo::GDAL::VSIF::MkDir('/vsimem/test');
+};
+ok($@ ne '', "error is ok: $@");
+Geo::GDAL::VSIF::MkDir('/vsimem/test-dir');
+$vsif = Geo::GDAL::VSIF::Open('/vsimem/test-dir/x', 'w');
+$vsif->Write('12345');
+$vsif->Close();
+
+# sub ReadDirRecursive ok
+ at list = Geo::GDAL::VSIF::ReadDirRecursive('/vsimem');
+ok(@list == 3, "ReadDirRecursive: @list");
+
+# sub Rename ok
+Geo::GDAL::VSIF::Rename('/vsimem/test-dir/x', '/vsimem/test-dir/y');
+ at list = Geo::GDAL::VSIF::ReadDirRecursive('/vsimem');
+ok($list[2] eq 'test-dir/y', "Rename: @list");
+
+# sub RmDir
+Geo::GDAL::VSIF::RmDir('/vsimem/test-dir', 1);
+ at list = Geo::GDAL::VSIF::ReadDirRecursive('/vsimem');
+ok(@list == 1, "RmDir: @list");
+
+# sub Seek
+# sub Stat
+# sub Tell
+# sub Truncate
+# sub Unlink
+# sub Write ok
diff --git a/swig/perl/t/01.t b/swig/perl/t/01.t
index 2312f9d..6d118e2 100644
--- a/swig/perl/t/01.t
+++ b/swig/perl/t/01.t
@@ -3,38 +3,40 @@ use warnings;
 use Test::More qw(no_plan);
 BEGIN { use_ok('Geo::GDAL') };
 
-# Create and open dataset
+# package Geo::GDAL::Driver
+#
+# sub Capabilities ok
+
+my %cap = map {$_=>1} Geo::GDAL::Driver::Capabilities;
+my @cap = Geo::GDAL::Driver('GTiff')->Capabilities;
+for my $cap (@cap) {
+    ok($cap{$cap}, "Capability $cap");
+    my $t = Geo::GDAL::Driver('GTiff')->TestCapability($cap);
+    ok($t, "Test capability $cap");
+}
+
+# sub Copy
+# sub CopyFiles
+# sub Create ok
 
 my $dataset = Geo::GDAL::Driver('GTiff')->Create(Name => '/vsimem/test.gtiff', Width => 123, Height => 45);
 ok($dataset, "Create a geotiff into vsimem");
 my @list = $dataset->GetFileList();
 ok($list[0] eq '/vsimem/test.gtiff', "GetFileList");
-undef $dataset;
-
- at list = Geo::GDAL::VSIF::ReadDir('/vsimem/');
-ok($list[0] eq 'test.gtiff', "ReadDir");
 
 my $driver = Geo::GDAL::IdentifyDriver('/vsimem/test.gtiff');
 ok($driver->Name eq Geo::GDAL::Driver('GTiff')->Name, "IdentifyDriver");
 
-$dataset = Geo::GDAL::Open('/vsimem/test.gtiff', 'ReadOnly');
-ok($dataset, "Open");
+# sub CreationDataTypes
+# sub CreationOptionList
+# sub Delete
+# sub Domains
+# sub Extension
+# sub MIMEType
+# sub Name
+# sub Rename
+# sub TestCapability above
 
-$dataset = Geo::GDAL::OpenShared('/vsimem/test.gtiff', 'ReadOnly');
-ok($dataset, "OpenShared");
-
-$dataset = Geo::GDAL::OpenEx('/vsimem/test.gtiff');
-ok($dataset, "OpenEx");
-
-# Geo::GDAL::Driver 
-
-my %cap = map {$_=>1} Geo::GDAL::Driver::Capabilities;
-my @cap = Geo::GDAL::Driver('GTiff')->Capabilities;
-for my $cap (@cap) {
-    ok($cap{$cap}, "Capability $cap");
-    my $t = Geo::GDAL::Driver('GTiff')->TestCapability($cap);
-    ok($t, "Test capability $cap");
-}
 
 my $dataset2 = Geo::GDAL::Driver('MEM')->Copy('', $dataset);
 my @size1 = $dataset->Size;
diff --git a/swig/perl/t/02.t b/swig/perl/t/02.t
index d07a825..d39916d 100644
--- a/swig/perl/t/02.t
+++ b/swig/perl/t/02.t
@@ -1,22 +1,77 @@
 use strict;
 use warnings;
+use Carp;
 use Test::More qw(no_plan);
 BEGIN { use_ok('Geo::GDAL') };
 
-# Geo::GDAL::Dataset
+# package Geo::GDAL::Dataset
+#
+# sub AddBand
+# sub Band
+# sub Bands
+# sub BuildOverviews
+# sub CommitTransaction
+# sub Domains
+# sub GCPs
+# sub GeoTransform
+# sub GetDriver
+# sub GetFileList
+# sub GetGCPProjection
+# sub Open
+# sub OpenShared
+
+my $dataset = Geo::GDAL::Driver('GTiff')->Create(Name => '/vsimem/test.gtiff', Width => 123, Height => 45);
+undef $dataset; # need to do this since Open is called before the assignment
+
+$dataset = Geo::GDAL::Open('/vsimem/test.gtiff', 'ReadOnly');
+ok($dataset, "Open");
+
+$dataset = Geo::GDAL::OpenShared('/vsimem/test.gtiff', 'ReadOnly');
+ok($dataset, "OpenShared");
+
+$dataset = Geo::GDAL::OpenEx('/vsimem/test.gtiff');
+ok($dataset, "OpenEx");
+
+
+# sub ReadRaster
+# sub RollbackTransaction
+# sub Size
+# sub SpatialReference
+# sub StartTransaction
+# sub WriteRaster
+
+$dataset = Geo::GDAL::Driver('GTiff')->Create(Name => '/vsimem/test.gtiff', Width => 123);
+my @list = $dataset->GetFileList();
+undef $dataset;
+
+ at list = Geo::GDAL::VSIF::ReadDir('/vsimem/');
+print "@list\n";
+my $driver = Geo::GDAL::IdentifyDriver('/vsimem/test.gtiff');
+print $driver->Name,"\n";
+
+
+$dataset = Geo::GDAL::Open('/vsimem/test.gtiff', 'ReadOnly');
+print "$dataset\n";
+undef $dataset;
+
+$dataset = Geo::GDAL::OpenShared('/vsimem/test.gtiff', 'ReadOnly');
+print "$dataset\n";
+$dataset = Geo::GDAL::OpenEx('/vsimem/test.gtiff');
+print "$dataset\n";
+
 
 my %dt = map {$_=>1} Geo::GDAL::Dataset::Domains();
 for my $dt (Geo::GDAL::Driver('MEM')->Create->Domains()) {
     ok($dt{$dt}, "Dataset domain: $dt");
 }
 
-my $dataset = Geo::GDAL::Driver('MEM')->Create(Width => 8, Height => 10);
+$dataset = Geo::GDAL::Driver('MEM')->Create(Width => 8, Height => 10);
 my $band = $dataset->Band;
 my $band2 = $dataset->Band(1);
 my @bands = $dataset->Bands;
 ok(@bands == 1, "Bands");
 
-my @list = Geo::GDAL::DataTypes();
+ at list = Geo::GDAL::DataTypes();
 #print "@list\n";
 $dataset->AddBand('Int32', {a => 1});
 @bands = $dataset->Bands;
@@ -48,6 +103,14 @@ $dataset->WriteRaster(XOff => 0, yoff => 0, buf => $buf, BandList => [1]);
 my $data = $dataset->Band(1)->ReadTile;
 ok(($data->[0][0] == 1 and $data->[9][7] == 2), "WriteRaster ReadTile");
 
+$data[80] = 1;
+$data[159] = 2;
+$buf = pack("$pc*", @data[80..159]);
+$dataset->WriteRaster(XOff => 0, yoff => 0, buf => \$buf, BandList => [1]);
+$data = $dataset->Band(1)->ReadTile;
+ok(($data->[0][0] == 1 and $data->[9][7] == 2), "WriteRaster ReadTile 2");
+
+
 $data->[5][5] = 3;
 $dataset->Band(1)->WriteTile($data);
 $data = $dataset->Band(1)->ReadTile;
@@ -55,18 +118,3 @@ ok($data->[5][5] == 3, "WriteTile");
 #for my $row (@$data) {
 #    print "@$row\n";
 #}
-
-__END__
-
-tests to do
-
-CreateMaskBand
-
-GCPs
-GetGCPProjection
-
-SpatialReference
-
-StartTransaction
-CommitTransaction
-RollbackTransaction
diff --git a/swig/perl/t/03.t b/swig/perl/t/03.t
index 7acb27d..61fde37 100644
--- a/swig/perl/t/03.t
+++ b/swig/perl/t/03.t
@@ -4,14 +4,67 @@ use Scalar::Util 'blessed';
 use Test::More qw(no_plan);
 BEGIN { use_ok('Geo::GDAL') };
 
-# Geo::GDAL::Band
+# package Geo::GDAL::Band
+# sub AttributeTable
+# sub CategoryNames
+# sub Checksum
+# sub ColorInterpretation
+# sub ColorInterpretations
+# sub ColorTable
+# sub ComputeBandStats
+# sub ComputeRasterMinMax
+# sub ComputeStatistics
+# sub Contours
+# sub CreateMaskBand
+# sub DataType
+# sub Domains
+# sub Fill
+# sub FillNodata
+# sub FlushCache
+# sub GetBandNumber
+# sub GetBlockSize
+# sub GetColorTable
+# sub GetDataset
+# sub GetDefaultHistogram
+# sub GetHistogram
+# sub GetMaskBand
+# sub GetMaskFlags
+# sub GetMaximum
+# sub GetMinimum
+# sub GetOverview
+# sub GetOverviewCount
+# sub GetStatistics
+# sub HasArbitraryOverviews
+# sub MaskFlags
+# sub NoDataValue
+# sub PackCharacter
+# sub ReadRaster
+# sub ReadTile
+# sub RegenerateOverview
+# sub RegenerateOverviews
+# sub ScaleAndOffset
+# sub SetColorTable
+# sub SetDefaultHistogram
+# sub SetStatistics
+# sub Size
+# sub Unit
+# sub WriteRaster
+# sub WriteTile
+
 
 my $dataset = Geo::GDAL::Driver('GTiff')->Create(Name => '/vsimem/test.gtiff', Width => 4, Height => 6);
 my $band = $dataset->Band;
-
-$band->CategoryNames('a','b');
-my @list = $band->CategoryNames;
-ok(($list[0] eq 'a' and $list[1] eq 'b'), "CategoryNames");
+my @list;
+
+SKIP: {
+    eval {
+        $band->SetCategoryNames('a','b');
+    };
+    skip "Setting category names in geotiffs not supported." unless $@ eq '';
+    $band->CategoryNames('a','b',1);
+    @list = $band->CategoryNames;
+    ok(($list[0] eq 'a' and $list[1] eq 'b'), "CategoryNames");
+}
 
 @list = $band->GetBlockSize;
 ok(($list[0] == 4 and $list[1] == 6), "GetBlockSize");
@@ -229,6 +282,14 @@ eval {
 };
 ok(!$@, "SetDefaultHistogram");
 
+my @h = ('12345678987654321','9223372036854775806');
+$band->SetDefaultHistogram(0, 100, \@h);
+my @hist = $band->GetDefaultHistogram(0);
+ok($hist[0] == 0, "DefaultHistogram");
+ok($hist[1] == 100, "DefaultHistogram");
+ok($hist[2][0] eq $h[0], "DefaultHistogram");
+ok($hist[2][1] eq $h[1], "DefaultHistogram");
+
 my $buf = $band->ReadRaster();
 my $pc = $band->PackCharacter;
 my @data = unpack("$pc*", $buf);
diff --git a/swig/perl/t/alg.t b/swig/perl/t/alg.t
new file mode 100644
index 0000000..156d759
--- /dev/null
+++ b/swig/perl/t/alg.t
@@ -0,0 +1,82 @@
+use strict;
+use warnings;
+use v5.10;
+use Scalar::Util 'blessed';
+use Test::More tests => 7;
+BEGIN { use_ok('Geo::GDAL') };
+
+{
+    my $b = Geo::GDAL::Driver('MEM')->Create(Width => 40, Height => 40)->Band;
+    my $d = $b->ReadTile;
+    for my $y (20..29) {
+        for my $x (10..19) {
+            $d->[$y][$x] = 1;
+        }
+    }
+    $b->WriteTile($d);
+    my $l = $b->Polygonize;
+    my $c = $l->GetFeatureCount;
+    ok($c == 2, "polygonize made 2 features");
+    $l->ForFeatures(
+        sub {
+            my $f = shift;
+            my $g = $f->Geometry;
+            ok($g->AsText eq 
+               'POLYGON ((0 0,0 -40,40 -40,40 0,0 0),(10 -20,20 -20,20 -30,10 -30,10 -20))', 
+               'big geometry with hole') if $f->{val} == 0;
+            ok($g->AsText eq 
+               'POLYGON ((10 -20,10 -30,20 -30,20 -20,10 -20))', 
+               'small geometry') if $f->{val} == 1;
+        });
+}
+
+{
+    my $b = Geo::GDAL::Driver('MEM')->Create(Width => 20, Height => 20)->Band;
+    my $d = $b->ReadTile;
+    for my $y (0..19) {
+        for my $x (0..19) {
+            $d->[$y][$x] = 5;
+        }
+    }
+    $d->[15][4] = 1;
+    $d->[10][13] = 1;
+    $d->[11][13] = 1;
+    $d->[2][4] = 1;
+    $d->[3][4] = 1;
+    $d->[3][5] = 1;
+    $b->WriteTile($d);
+    my $r = $b->Sieve(Threshold => 2, Options => {Connectedness => 4});
+    $d = $r->ReadTile;
+    ok($d->[15][4] == 5, "Sieved area with size 1 away.");
+}
+
+{
+    my $d = Geo::GDAL::Driver('MEM')->Create(Width => 20, Height => 20, Bands => 3);
+    $d->Band(1)->ColorInterpretation('RedBand');
+    $d->Band(2)->ColorInterpretation('GreenBand');
+    $d->Band(3)->ColorInterpretation('BlueBand');
+    for my $b ($d->Bands) {
+        my $d = $b->ReadTile;
+        for my $y (0..19) {
+            for my $x (0..19) {
+                $d->[$y][$x] = int(rand(256));
+            }
+        }
+        $b->WriteTile($d);
+    }
+    my $b = $d->Dither;
+    my $ct = $b->ColorTable;
+    my @n = $ct->ColorEntries;
+    #say STDERR "@n";
+    ok(@n == 256, "Dither using computed ct");
+}
+
+{
+    my $b = Geo::GDAL::Driver('MEM')->Create(Width => 20, Height => 20, Type => 'Byte')->Band;
+    my $d = $b->ReadTile;
+    $d->[9][9] = 1;
+    $b->WriteTile($d);
+    my $b2 = $b->Distance(Options => {Type => 'Byte'});
+    $d = $b2->ReadTile;
+    ok($d->[0][0] == 13, "Distance raster");
+}
diff --git a/swig/perl/t/callback.t b/swig/perl/t/callback.t
new file mode 100644
index 0000000..8e45064
--- /dev/null
+++ b/swig/perl/t/callback.t
@@ -0,0 +1,42 @@
+use strict;
+use warnings;
+use Scalar::Util 'blessed';
+use Test::More tests => 2;
+BEGIN { use_ok('Geo::GDAL') };
+
+{
+    package Output;
+    use strict;
+    use warnings;
+    our @output;
+    sub new {
+        return bless {}, 'Output';
+    }
+    sub write {
+        my $line = shift;
+        push @output, $line;
+    }
+    sub close {
+        push @output, "end";
+    }
+}
+
+{   # create a small layer and copy it to vsistdout with redirection
+    my $l = Geo::OGR::Driver('Memory')->Create()->CreateLayer(GeometryType => 'None');
+    $l->CreateField(Name => 'value', Type => 'Integer');
+    $l->CreateField(Name => 'geom', GeometryType => 'Point');
+    $l->InsertFeature([12,{wkt=>'POINT(1 1)'}]);
+
+    my $output = Output->new;
+    my $l2 = Geo::OGR::Driver('GeoJSON')->Create($output)->CopyLayer($l, '');
+
+    $output = join '', @Output::output;
+    $output =~ s/\n//g;
+
+    ok($output eq 
+       '{"type": "FeatureCollection",'.
+       '"features": '.
+       '[{ "type": "Feature", "id": 0, "properties": '.
+       '{ "value": 12 }, "geometry": { "type": "Point", '.
+       '"coordinates": [ 1.0, 1.0 ] } }]}end', "Redirect stdout to write/close methods.");
+}
diff --git a/swig/perl/t/error.t b/swig/perl/t/error.t
new file mode 100644
index 0000000..39ad6d1
--- /dev/null
+++ b/swig/perl/t/error.t
@@ -0,0 +1,30 @@
+use strict;
+use warnings;
+use v5.10;
+use Scalar::Util 'blessed';
+use Test::More tests => 6;
+BEGIN { use_ok('Geo::GDAL') };
+
+my $e;
+
+eval {
+    my $ds = Geo::GDAL::Driver('GTiff')->Create(Name => '/vsimem/tmp', Bands => 0);
+};
+ok(($@ =~ /called at t\/error.t/), "Error in GDAL is confessed (by a call in cpl_exceptions.i).");
+
+eval {
+    Geo::GDAL::VSIF::MkDir('/cannot/make/this');
+};
+ok(($@ =~ /called at t\/error.t/), "Error in bindings is confessed (by a call in typemaps_perl.i).");
+
+Geo::GDAL->errstr;
+$e = Geo::GDAL->errstr;
+ok($e eq '', 'Calling Geo::GDAL::errstr clears the error stack.');
+
+eval {
+    Geo::GDAL::GetDataTypeSize('bar');
+};
+ok(($@ =~ /called at t\/error.t/), "Error in Perl layer is confessed (by a call to Geo::GDAL::error in {gdal,ogr,osr}_perl.i).");
+
+$e = Geo::GDAL->errstr;
+ok($@ =~ /$e/, 'Pure errors can be obtained from Geo::GDAL::errstr');
diff --git a/swig/perl/t/feature.t b/swig/perl/t/feature.t
new file mode 100644
index 0000000..e55d08d
--- /dev/null
+++ b/swig/perl/t/feature.t
@@ -0,0 +1,173 @@
+use utf8;
+use strict;
+use warnings;
+use bytes;
+use v5.10;
+use Test::More qw(no_plan);
+BEGIN { use_ok('Geo::GDAL') };
+
+# test features and their fields
+
+my @fields = (
+    {Name => 'Binary', Type => 'Binary'},
+    {Name => 'Time', Type => 'Time'},
+    {Name => 'Date', Type => 'Date'}, 
+    {Name => 'DateTime', Type => 'DateTime'}, 
+    {Name => 'Integer', Type => 'Integer'}, 
+    {Name => 'Integer64', Type => 'Integer64'}, 
+    {Name => 'IntegerList', Type => 'IntegerList'}, 
+    {Name => 'Integer64List', Type => 'Integer64List'},
+    {Name => 'Real', Type => 'Real'}, 
+    {Name => 'RealList', Type => 'RealList'},
+    {Name => 'String', Type => 'String'},
+    {Name => 'StringList', Type => 'StringList'},
+    #{Name => 'WideString', Type => 'WideString'},
+    #{Name => 'WideStringList', Type => 'WideStringList'}
+   );
+
+my $f = Geo::OGR::Feature->new(
+    GeometryType => 'Point', 
+    Fields => \@fields
+    );
+
+{
+    my $l = $f->Layer();
+    ok(!(defined $l), "Layer of an orphan feature is undefined.");
+}
+
+{
+    my @n = $f->GetFieldNames();
+    ok(@n == @fields + 1, "Get field names (count).");
+}
+
+{
+    my $i = $f->GetFieldIndex('Binary');
+    ok($i == 0, "Get field index");
+}
+
+{
+    my $v = $f->Field('Integer');
+    ok(!(defined $v), "Unset field returns undef.");
+    $f->Field(Integer => 1);
+    $v = $f->Field('Integer');
+    ok($v == 1, "Set field returns its value.");
+    $f->Field(Integer => undef);
+    $v = $f->Field('Integer');
+    ok(!(defined $v), "Setting field to undef unsets it.");
+}
+
+{
+    my $b = 'åäöAJ';
+    my $c = $f->Field(String => $b);
+    ok($b eq $c, "Set and get string field.");
+}
+
+{
+    my $b = ['åäöAJ','åäöAJx'];
+    my $c = $f->Field(StringList => $b);
+    ok($b->[0] eq $c->[0] && $b->[1] eq $c->[1], "Set and get string list field.");
+}
+
+{
+    my $b = 123.456;
+    my $c = $f->Field(Real => $b);
+    ok("$b" eq "$c", "Set and get real field.");
+}
+
+{
+    my $b = [123.456,2123.4567];
+    my $c = $f->Field(RealList => $b);
+    ok("@$b" eq "@$c", "Set and get real list field.");
+}
+
+{
+    my $b = 123;
+    my $c = $f->Field(Integer => $b);
+    ok("$b" eq "$c", "Set and get integer field.");
+}
+
+{
+    my $b = [123,12];
+    my $c = $f->Field(IntegerList => $b);
+    ok("@$b" eq "@$c", "Set and get integer list field.");
+}
+
+{
+    my $b = 9223372036854775806;
+    my $c = $f->Field(Integer64 => $b);
+    ok($b eq $c, "Set and get integer64 field.");
+}
+
+{
+    my $b = [9223372036854775806,12];
+    my $c = $f->Field(Integer64List => $b);
+    ok("@$b" eq "@$c", "Set and get integer64 list field.");
+}
+
+{
+    my $b_hex = '4100204d414e204120504c414e20412043414e414c2050414e414d41';
+    my $b = pack('H*', $b_hex);
+    $f->Field(Binary => $b);
+    my $c = $f->Field('Binary');
+    my $c_hex = unpack('H*', $c);
+    ok($c_hex eq $b_hex, "Set and get a binary field.");
+    $c = $f->Field(0);
+    $c_hex = unpack('H*', $c);
+    ok($c_hex eq $b_hex, "Set and get a binary field.");
+}
+
+{
+    my $b = [2008,3,23];
+    my $c = $f->Field(Date => $b);
+    ok("@$b" eq "@$c", "Set and get date field.");
+}
+
+{
+    my $b = [2008,3,23,2,3,4,1];
+    my $c = $f->Field(DateTime => $b);
+    ok("@$b" eq "@$c", "Set and get datetime field.");
+}
+
+{
+    my $b = [2,3,4,1];
+    my $c = $f->Field(Time => $b);
+    ok("@$b" eq "@$c", "Set and get time field.");
+}
+
+{
+    my $p = [1,2];
+    my $b = Geo::OGR::Geometry->new(GeometryType => 'Point', points => $p);
+    my $c = $f->Geometry($b);
+    ok($b->As(Format => 'ISO WKT') eq $c->As(Format => 'ISO WKT'), "Set and get the geometry field.");
+    $c = $f->Geometry(0 => $b);
+    ok($b->As(Format => 'ISO WKT') eq $c->As(Format => 'ISO WKT'), "Set and get the geometry field.");
+}
+
+eval {
+    $f = Geo::OGR::Feature->new(
+        GeometryType => 'Point', 
+        Fields => [
+            {Name => 'Integer', Type => 'Integer'},
+            {Name => 'Point', Type => 'Point'},
+            {Name => 'LineString', Type => 'LineString'},
+        ]);
+};
+ok($@, "Mixing error.");
+
+ at fields = ({Name => 'Integer', Type => 'Integer'},
+           {Name => 'Point', Type => 'Point'},
+           {Name => 'LineString', Type => 'LineString'});
+
+$f = Geo::OGR::Feature->new(Fields => \@fields);
+
+{
+    my @n = $f->GetFieldNames();
+    ok(@n == @fields, "Get field names (count).");
+}
+
+{
+    my $p = [1,2];
+    my $b = Geo::OGR::Geometry->new(GeometryType => 'Point', points => $p);
+    my $c = $f->Geometry(Point => $b);
+    ok($b->As(Format => 'ISO WKT') eq $c->As(Format => 'ISO WKT'), "Set and get the point field.");
+}
diff --git a/swig/perl/t/gcp.t b/swig/perl/t/gcp.t
new file mode 100644
index 0000000..29f16d0
--- /dev/null
+++ b/swig/perl/t/gcp.t
@@ -0,0 +1,38 @@
+use strict;
+use warnings;
+use v5.10;
+use Scalar::Util 'blessed';
+use Test::More tests => 5;
+BEGIN { use_ok('Geo::GDAL') };
+
+# test GCPs
+
+my $ds = Geo::GDAL::Driver('GTiff')->Create(Name=>'/vsimem/tmp.tiff', Bands=>1, Width=>312);
+my ($w, $h) = $ds->Size;
+ok($w == 312, "set width ok");
+
+my $t = Geo::GDAL::GeoTransform->new(1.23,1,0, 1,0,1);
+$t = $ds->GeoTransform($t);
+ok(sprintf("%.2f", $t->[0]) eq '1.23', "geotransform ok");
+
+my $xmin = $t->[0];
+my $ymin = $t->[3] + $t->[5]*$h;
+my $xmax = $t->[0] + $t->[1]*$w;
+my $ymax = $t->[3];
+#say "extent $xmin $ymin $xmax $ymax";
+
+my @gcp;
+$gcp[1] = Geo::GDAL::GCP->new($xmin, $ymax, 0, 0, 0);
+$gcp[0] = Geo::GDAL::GCP->new($xmax, $ymax, 0, $w, 0);
+$gcp[3] = Geo::GDAL::GCP->new($xmin, $ymin, 0, 0, $h);
+$gcp[2] = Geo::GDAL::GCP->new($xmax, $ymin, 0, $w, $h);
+my $gt = Geo::GDAL::GeoTransform::FromGCPs(\@gcp, 0);
+
+#say "transform: @$gt";
+ok(sprintf("%.2f", $t->[0]) eq '1.23', "geotransform from gcps ok");
+
+$gt = Geo::GDAL::GeoTransform::FromGCPs(@gcp, 0);
+
+#say "transform: @$gt";
+ok(sprintf("%.2f", $t->[0]) eq '1.23', "geotransform from gcp array ok");
+
diff --git a/swig/perl/t/gdal.t b/swig/perl/t/gdal.t
index 98c2645..a8b6ed9 100644
--- a/swig/perl/t/gdal.t
+++ b/swig/perl/t/gdal.t
@@ -2,7 +2,6 @@ use strict;
 use warnings;
 use Test::More qw(no_plan);
 BEGIN { use_ok('Geo::GDAL') };
-Geo::GDAL::PushFinderLocation('../../data');
 
 use vars qw/%available_driver %test_driver $loaded $verbose @types @fails @tested_drivers/;
 
@@ -29,33 +28,6 @@ $verbose = $ENV{VERBOSE};
 
 system "rm -rf tmp_ds_*" unless $^O eq 'MSWin32';
 
-%test_driver = ('GTiff' => 1,
-		'MEM' => 1,
-		'EHdr' => 1,
-		);
-
- at types = (qw/Byte UInt16 Int16 UInt32 Int32 Float32 Float64 CInt16 CInt32 CFloat32 CFloat64/);
-
-my %no_colortable = map {$_=>1} ('NITF','ELAS','BMP','ILWIS','BT','RMF','RST');
-
-my %no_nodatavalue = map {$_=>1} ('NITF','HFA','ELAS','BMP','ILWIS','BT','IDA','RMF');
-
-my %no_geotransform = map {$_=>1} ('NITF','PAux','PNM','MFF','ENVI','BMP','EHdr');
-
-my %no_setgcp = map {$_=>1} ('HFA','ELAS','MEM','BMP','PCIDSK','ILWIS','PNM','ENVI',
-			     'NITF','EHdr','MFF','MFF2','BT','IDA','RMF','RST');
-
-my %no_open = map {$_=>1} ('VRT','MEM','ILWIS','MFF2');
-
-if (0) {
-    {
-	my $ds = Geo::GDAL::Dataset::Open('/data/Corine/lceugr100_00/lceugr100_00_pct.tif');
-	$b = $ds->GetRasterBand(1);
-    }
-    $b->GetDefaultRAT();
-    exit;
-}
-
 {
     # test memory files
     my $fp = Geo::GDAL::VSIFOpenL('/vsimem/x', 'w');
@@ -71,7 +43,7 @@ if (0) {
 
 {
     my $driver = Geo::GDAL::GetDriver('MEM');
-    my $dataset = $driver->Create('tmp', 10, 10, 3 , 'Int32', []);
+    my $dataset = $driver->Create('tmp', 10, 10, 3 , 'Int32', {});
     ok($dataset->isa('Geo::GDAL::Dataset'), 'Geo::GDAL::Dataset');
     ok($dataset->{RasterXSize} == 10, "Geo::GDAL::Dataset::RasterXSize $dataset->{RasterXSize}");
     ok($dataset->{RasterCount} == 3, "Geo::GDAL::Dataset::RasterCount $dataset->{RasterCount}");
@@ -115,7 +87,7 @@ if (0) {
     eval {
 	@histogram = $b->GetHistogram();
     };
-    ok($#histogram == 255, "Histogram: @histogram");
+    ok($#histogram == 255, "Histogram");
     eval {
 	$b->SetDefaultHistogram(1,10,[0..255]);
     };
@@ -127,8 +99,8 @@ if (0) {
     eval {
 	@histogram = $b->GetHistogram(Min=>0, Max=>100, Buckets=>20);
     };
-    ok($#histogram == 19, "Histogram with parameters: @histogram");
-
+    ok($#histogram == 19, "Histogram with parameters");
+ 
     Geo::GDAL::RegenerateOverview($r, $b, 'GAUSS');
     
     my $band = $r;
@@ -174,7 +146,7 @@ if (0) {
     my @usages;
     for my $u (@u) {
 	for my $t (@t) {
-	    $r->CreateColumn("$t $u", $t, $u);
+	    $r->CreateColumn("$t $u", $t, $u); # do not warn about RAT column types
             push @types, $t;
             push @usages, $u;
 	}
@@ -243,224 +215,127 @@ system "rm -rf tmp_ds_*" unless $^O eq 'MSWin32';
 
 sub gdal_tests {
 
-    for my $driver (Geo::GDAL::Drivers) {
-
-	my $name = $driver->{ShortName};
-	
-	unless (defined $name) {
-	    $name = 'unnamed';
-	    my $i = 1;
-	    while ($available_driver{$name}) {
-		$name = 'unnamed '.$i;
-		$i++;
-	    }
-	}
-
-	$available_driver{$name} = 1;
-	mytest('skipped: not tested',undef,$name,'test'),next unless $test_driver{$name};
+    my $name = 'MEM';
 
-        next if $name eq 'MFF2'; # does not work probably because of changes in hkvdataset.cpp
-	
-	my $metadata = $driver->GetMetadata();
-	
-	unless ($metadata->{DCAP_CREATE} and $metadata->{DCAP_CREATE} eq 'YES') {
-	    mytest('skipped: no capability',undef,$name,'dataset create');
-	    next;
-	}
+    my $driver = Geo::GDAL::Driver($name);
 	
-	my @create = split /\s+/,$metadata->{DMD_CREATIONDATATYPES};
-	
-	@create = (qw/Byte Float32 UInt16 Int16 CInt16 CInt32 CFloat32/)
-	    if $driver->{ShortName} eq 'MFF2';
-	
-	unless (@create) {
-	    mytest('skipped: no creation datatypes',undef,$name,'dataset create');
-	    next;
-	}
-	
-	if ($driver->{ShortName} eq 'PAux') {
-	    mytest('skipped: does not work?',undef,$name,'dataset create');
-	    next;
-	}
-
-        next unless $driver->{ShortName} eq 'MEM';
-
-	push @tested_drivers,$name;
-	
-	my $ext = $metadata->{DMD_EXTENSION} ? '.'.$metadata->{DMD_EXTENSION} : '';
-	$ext = '' if $driver->{ShortName} eq 'ILWIS';
-	
-	for my $type (@create) {
-	    
-	    if (($driver->{ShortName} eq 'MFF2') and ($type eq 'CInt32')) {
-		mytest('skipped: does not work?',undef,$name,$type,'dataset create');
-		next;
-	    }
-
-	    my $filename = "tmp_ds_".$driver->{ShortName}."_$type$ext";
-	    my $width = 100;
-	    my $height = 50;
-	    my $bands = 1;
-	    my $options = undef;
-
-	    my $dataset;
-
-	    eval {
-		$dataset = $driver->Create($filename, $width, $height, $bands , $type, []);
-	    };
-
-	    mytest($dataset,'no error message',$name,$type,'dataset create');
-	    next unless $dataset;
-
-	    mytest($dataset->{RasterXSize} == $width,'RasterXSize',$name,$type,'RasterXSize');
-	    mytest($dataset->{RasterYSize} == $height,'RasterYSize',$name,$type,'RasterYSize');
-	    
-	    my $band = $dataset->GetRasterBand(1);
-	    
-	    if ($no_geotransform{$driver->{ShortName}}) 
-	    {
-		mytest('skipped',undef,$name,$type,'Get/SetGeoTransform');
-
-	    } else
-	    {
-		my $transform = $dataset->GetGeoTransform();
-		$transform->[5] = 12;
-		$dataset->SetGeoTransform($transform);
-		my $transform2 = $dataset->GetGeoTransform();
-		mytest($transform->[5] == $transform2->[5],
-		       "$transform->[5] != $transform2->[5]",$name,$type,'Get/SetGeoTransform');
-	    }
-
-	    if ($no_nodatavalue{$driver->{ShortName}}) 
-	    {
-		mytest('skipped',undef,$name,$type,'Get/SetNoDataValue');
-		
-	    } else
-	    {
-		if ($name ne 'GTiff') {
-		    $band->ColorInterpretation('GreenBand');
-		    my $value = $band->ColorInterpretation;
-		    mytest($value eq 'GreenBand',"$value ne GreenBand",$name,$type,'ColorInterpretation');
-		}
-
-		$band->SetNoDataValue(5);
-		my $value = $band->GetNoDataValue;
-		mytest($value == 5,"$value != 5",$name,$type,'Get/SetNoDataValue');
-	    }
-	    
-	    if ($no_colortable{$driver->{ShortName}} 
-		or ($driver->{ShortName} eq 'GTiff' and ($type ne 'Byte' or $type ne 'UInt16'))
-		)
-	    {
-		mytest('skipped',undef,$name,$type,'Colortable');
-		
-	    } else 
-	    {
-		my $colortable = Geo::GDAL::ColorTable->new('Gray');
-		my @rgba = (255,0,0,255);
-		$colortable->SetColorEntry(0, \@rgba);
-		$band->ColorTable($colortable);
-		$colortable = $band->ColorTable;
-		my @rgba2 = $colortable->GetColorEntry(0);
-		
-		mytest($rgba[0] == $rgba2[0] and
-		       $rgba[1] == $rgba2[1] and
-		       $rgba[2] == $rgba2[2] and
-		       $rgba[3] == $rgba2[3],"colors do not match",$name,$type,'Colortable');
-	    }
-	    
-	    my $pc;
-	    eval {
-		$pc = Geo::GDAL::PackCharacter($band->{DataType});
-	    };
-	    
-	    if ($driver->{ShortName} eq 'VRT') 
-	    {
-		mytest('skipped',"",$name,$type,'WriteRaster');
-		
-	    } elsif (!$pc) 
-	    {
-		mytest('skipped',"no packtype defined yet",$name,$type,'WriteRaster');
-		
-	    } else 
-	    {
-		$pc = "${pc}[$width]";
-		my $scanline = pack($pc,(1..$width));
-		
-		for my $yoff (0..$height-1) {
-		    $band->WriteRaster( 0, $yoff, $width, 1, $scanline );
-		}
-	    }
-
-	    
-	    if ($no_setgcp{$driver->{ShortName}})
-	    {
-		mytest('skipped',undef,$name,$type,'Set/GetGCPs');
-		
-	    } else 
-	    {
-		my @gcps = ();
-		push @gcps,new Geo::GDAL::GCP(1.1,2.2);
-		push @gcps,new Geo::GDAL::GCP(2.1,3.2);
-		my $po = "ho ho ho";
-		$dataset->SetGCPs(\@gcps,$po);
-		my $c = $dataset->GetGCPCount();
-		my $p = $dataset->GetGCPProjection();
-		my $gcps = $dataset->GetGCPs();
-		my $y1 = $gcps->[0]->{Y};
-		my $y2 = $gcps->[1]->{Y};
-		my $y1o = $gcps[0]->{Y};
-		my $y2o = $gcps[1]->{Y};
-		mytest(($c == 2 and $p eq $po and $y1 == $y1o and $y2 == $y2o),
-		       "$c != 2 or $p ne $po or $y1 != $y1o or $y2 != $y2o",$name,$type,'Set/GetGCPs');
-	    }
-
-	    undef $band;
-	    undef $dataset;
-	    
-	    if ($no_open{$driver->{ShortName}} or 
-		($driver->{ShortName} eq 'MFF2' and 
-		 ($type eq 'Int32' or $type eq 'Float64' or $type eq 'CFloat64')))
-	    {
-		mytest('skipped',undef,$name,$type,'open');
-		
-	    } else 
-	    {    
-		$ext = $metadata->{DMD_EXTENSION} ? '.'.$metadata->{DMD_EXTENSION} : '';
-		$filename = "tmp_ds_".$driver->{ShortName}."_$type$ext";
-		
-		eval {
-		    $dataset = Geo::GDAL::Open($filename);
-		};
-		mytest($dataset,'no message',$name,$type,"open $filename");
-		
-		if ($dataset) {
-		    mytest($dataset->{RasterXSize} == $width,'RasterXSize',$name,$type,'RasterXSize');
-		    mytest($dataset->{RasterYSize} == $height,'RasterYSize',$name,$type,'RasterYSize');
-		    
-		    my $band = $dataset->GetRasterBand(1);
-
-		    {
-			my @a = ('abc','def');
-			my @b = $band->CategoryNames(@a);
-			ok(is_deeply(\@a, \@b,"$name,$type,CategoryNames"));
-		    }
-		    
-		    if ($pc) {
-			
-			my $scanline = $band->ReadRaster( 0, 0, $width, 1);
-			my @data = unpack($pc, $scanline);
-			mytest($data[49] == 50,'',$name,$type,'ReadRaster');
-			
-		    }
-		    
-		}
-		undef $dataset;
-	    }    
-	}
+    my @create = (qw/Byte Float32 UInt16 Int16 CInt16 CInt32 CFloat32/);
+
+    push @tested_drivers, $name;
+
+    for my $type (@create) {
+
+        my $filename = "tmp_ds_".$driver->{ShortName}."_$type";
+        my $width = 100;
+        my $height = 50;
+        my $bands = 1;
+        my $options = undef;
+        
+        my $dataset;
+        
+        eval {
+            $dataset = $driver->Create($filename, $width, $height, $bands, $type, {});
+        };
+        
+        mytest($dataset, @$, $name, $type, "$name $type dataset create");
+        next unless $dataset;
+        
+        mytest($dataset->{RasterXSize} == $width,'RasterXSize',$name,$type,'RasterXSize');
+        mytest($dataset->{RasterYSize} == $height,'RasterYSize',$name,$type,'RasterYSize');
+        
+        my $band = $dataset->GetRasterBand(1);
+        
+        my $transform = $dataset->GetGeoTransform();
+        $transform->[5] = 12;
+        $dataset->SetGeoTransform($transform);
+        my $transform2 = $dataset->GetGeoTransform();
+        mytest($transform->[5] == $transform2->[5],
+               "$transform->[5] != $transform2->[5]",$name,$type,'Get/SetGeoTransform');
+        
+        $band->ColorInterpretation('GreenBand');
+        my $value = $band->ColorInterpretation;
+        mytest($value eq 'GreenBand',"$value ne GreenBand",$name,$type,'ColorInterpretation');
+            
+        $band->SetNoDataValue(5);
+        my $value = $band->GetNoDataValue;
+        mytest($value == 5,"$value != 5",$name,$type,'Get/SetNoDataValue');
+        
+        my $colortable = Geo::GDAL::ColorTable->new('Gray');
+        my @rgba = (255,0,0,255);
+        $colortable->SetColorEntry(0, \@rgba);
+        $band->ColorTable($colortable);
+        $colortable = $band->ColorTable;
+        my @rgba2 = $colortable->GetColorEntry(0);
+        
+        mytest($rgba[0] == $rgba2[0] and
+               $rgba[1] == $rgba2[1] and
+               $rgba[2] == $rgba2[2] and
+               $rgba[3] == $rgba2[3],"colors do not match",$name,$type,'Colortable');
+        
+        my $pc;
+        eval {
+            $pc = Geo::GDAL::PackCharacter($band->{DataType});
+        };
+        
+        if ($pc) {
+            $pc = "${pc}[$width]";
+            my $scanline = pack($pc,(1..$width));
+        
+            for my $yoff (0..$height-1) {
+                $band->WriteRaster( 0, $yoff, $width, 1, $scanline );
+            }
+        }
+        
+        my @gcps = ();
+        push @gcps,new Geo::GDAL::GCP(1.1,2.2);
+        push @gcps,new Geo::GDAL::GCP(2.1,3.2);
+        my $po = "ho ho ho";
+        $dataset->SetGCPs(\@gcps,$po);
+        my $c = $dataset->GetGCPCount();
+        my $p = $dataset->GetGCPProjection();
+        my $gcps = $dataset->GetGCPs();
+        my $y1 = $gcps->[0]->{Y};
+        my $y2 = $gcps->[1]->{Y};
+        my $y1o = $gcps[0]->{Y};
+        my $y2o = $gcps[1]->{Y};
+        mytest(($c == 2 and $p eq $po and $y1 == $y1o and $y2 == $y2o),
+               "$c != 2 or $p ne $po or $y1 != $y1o or $y2 != $y2o",$name,$type,'Set/GetGCPs');
+        
+        undef $band;
+        undef $dataset;
+        
+        unless ($name eq 'MEM') {
+            eval {
+                $dataset = Geo::GDAL::Open($filename);
+            };
+            mytest($dataset,'no message',$name,$type,"open $filename");
+        }
+        
+        if ($dataset) {
+            mytest($dataset->{RasterXSize} == $width,'RasterXSize',$name,$type,'RasterXSize');
+            mytest($dataset->{RasterYSize} == $height,'RasterYSize',$name,$type,'RasterYSize');
+            
+            my $band = $dataset->GetRasterBand(1);
+            
+            {
+                my @a = ('abc','def');
+                my @b = $band->CategoryNames(@a);
+                ok(is_deeply(\@a, \@b,"$name,$type,CategoryNames"));
+            }
+            
+            if ($pc) {
+                
+                my $scanline = $band->ReadRaster( 0, 0, $width, 1);
+                my @data = unpack($pc, $scanline);
+                mytest($data[49] == 50,'',$name,$type,'ReadRaster');
+                
+            }
+            
+        }
+        undef $dataset;
     }
 }
-
+    
 sub cmp_ar {
     my($n,$a1,$a2) = @_;
     return 0 unless $n == @$a1;
diff --git a/swig/perl/t/layer.t b/swig/perl/t/layer.t
new file mode 100644
index 0000000..e0af087
--- /dev/null
+++ b/swig/perl/t/layer.t
@@ -0,0 +1,59 @@
+use strict;
+use warnings;
+use bytes;
+use v5.10;
+use Test::More qw(no_plan);
+BEGIN { use_ok('Geo::GDAL') };
+
+# test layer construction and schema manipulation
+
+my $ds = Geo::OGR::Driver('Memory')->Create('test');
+
+my $l = $ds->CreateLayer(
+        Fields => [ { Name => 'Integer', 
+                      Type => 'Integer' },
+                    { Name => 'Point', 
+                      Type => 'Point' } ] );
+my $s = $l->Schema;
+my $f = $s->{Fields};
+
+ok(@$f == 2, "Two fields");
+ok($f->[0]->{Type} eq 'Integer', "First Integer");
+ok($f->[1]->{Type} eq 'Point', "Second Point");
+
+$l = $ds->CreateLayer(
+    GeometryType => 'Point',
+    Fields => [ { Name => 'Integer', 
+                  Type => 'Integer' } ] );
+$s = $l->Schema;
+$f = $s->{Fields};
+
+ok(@$f == 2, "Two fields");
+ok($f->[0]->{Type} eq 'Integer', "First Integer");
+ok($f->[1]->{Type} eq 'Point', "Second Point");
+ok($f->[1]->{Name} eq '', "Second with no name");
+
+$l->AlterFieldDefn(Integer => (Type => 'String', Name => 'String'));
+$s = $l->Schema;
+$f = $s->{Fields};
+ok($f->[0]->{Type} eq 'String', "Alter field type");
+ok($f->[0]->{Name} eq 'String', "Alter field name");
+
+$l->CreateField(Type => 'Real', Name => 'Real');
+$l->CreateField(Type => 'LineString', Name => 'LineString');
+$s = $l->Schema;
+$f = $s->{Fields};
+ok(@$f == 4, "Add two fields.");
+ok($f->[1]->{Type} eq 'Real', "New Real");
+ok($f->[3]->{Type} eq 'LineString', "New LineString");
+
+$l->DeleteField('String');
+$s = $l->Schema;
+$f = $s->{Fields};
+ok(@$f == 3, "Delete one field.");
+
+ok($l->GeometryType(0) eq 'Point', "Get GeometryType");
+ok($l->GeometryType('LineString') eq 'LineString', "Get GeometryType");
+
+# ReorderField
+# ReorderFields
diff --git a/swig/perl/t/nodata.t b/swig/perl/t/nodata.t
new file mode 100644
index 0000000..bbb5486
--- /dev/null
+++ b/swig/perl/t/nodata.t
@@ -0,0 +1,33 @@
+use strict;
+use warnings;
+use utf8;
+use v5.10;
+use Scalar::Util 'blessed';
+use Encode qw(encode decode);
+use Test::More tests => 5;
+BEGIN { use_ok('Geo::GDAL') };
+
+my $b = Geo::GDAL::Driver('MEM')->Create()->Band;
+
+{
+    my $nodata = $b->NoDataValue;
+    ok((not defined $nodata), "NoDataValue returns undef if there is no nodata value");
+}
+
+{
+    my @nodata = $b->NoDataValue;
+    ok((not $nodata[1]), "NoDataValue returns (x, untrue) if there is no nodata value");
+}
+
+$b->NoDataValue(13);
+
+{
+    my $nodata = $b->NoDataValue;
+    ok($nodata == 13, "NoDataValue returns the nodata value if there is nodata value");
+}
+
+{
+    my @nodata = $b->NoDataValue;
+    ok(($nodata[0] == 13 and $nodata[1]), "NoDataValue returns (nodata, true) if there is nodata value");
+}
+
diff --git a/swig/perl/t/ogr.t b/swig/perl/t/ogr.t
index 5e368a8..0b40b52 100644
--- a/swig/perl/t/ogr.t
+++ b/swig/perl/t/ogr.t
@@ -2,10 +2,12 @@ use strict;
 use warnings;
 use Test::More qw(no_plan);
 BEGIN { use_ok('Geo::GDAL') };
-Geo::GDAL::PushFinderLocation('../../data');
 
 use vars qw/%test_driver $loaded $verbose @types %pack_types @fails @tested_drivers/;
 
+# this is a mixture or mostly ad hoc tests
+# a good set of tests focusing on the Perl bindings is really needed
+
 {
     my $l = Geo::OGR::Driver('Memory')->Create()->CreateLayer();
     $l->CreateField(Name => 'value', Type => 'Integer');
@@ -40,11 +42,6 @@ use vars qw/%test_driver $loaded $verbose @types %pack_types @fails @tested_driv
     ok($n == 3, 'The extra field is scrapped because layer does not have a field for it');
 }
 
-%test_driver = ('ESRI Shapefile' => 1,
-		'MapInfo File' => 1,
-		'Memory' => 1,
-		);
-
 {
     # test conversion methods
     my $g = Geo::OGR::Geometry->new(WKT=>'POINT (1 1)');
@@ -113,62 +110,9 @@ use vars qw/%test_driver $loaded $verbose @types %pack_types @fails @tested_driv
 }
 
 {
-    # test list valued fields
-    my $d = Geo::OGR::FeatureDefn->new(
-        Fields=>[
-            { Name => 'ilist',
-              Type => 'IntegerList',
-            },
-            { Name => 'rlist',
-              Type => 'RealList',
-            },
-            { Name => 'slist',
-              Type => 'StringList',
-            },
-            { Name => 'date',
-              Type => 'Date',
-            },
-            { Name => 'time',
-              Type => 'Time',
-            },
-            { Name => 'datetime',
-              Type => 'DateTime',
-            },
-        ]
-        );
-    my $f = Geo::OGR::Feature->new($d);
-    #use Data::Dumper;
-    #print Dumper {$f->Schema};
-    ok($f->Schema->{Fields}->[5]->{Name} eq 'datetime', "Name in field in schema");
-    $f->Row( ilist => [1,2,3],
-	     rlist => [1.1,2.2,3.3],
-	     slist => ['a','b','c'],
-	     date => [2008,3,23],
-	     time => [12,55,15],
-	     datetime => [2008,3,23,12,55,20],
-	     );
-    my @test;
-    @test = $f->GetField('ilist');
-    ok(is_deeply(\@test, [1,2,3]), 'integer list');
-    @test = $f->GetField('rlist');
-    for (@test) {
-        $_ = sprintf("%.1f", $_);
-    }
-    ok(is_deeply(\@test, [1.1,2.2,3.3]), 'double list');
-    @test = $f->GetField('slist');
-    ok(is_deeply(\@test, ['a','b','c']), 'string list');
-    @test = $f->GetField('date');
-    ok(is_deeply(\@test, [2008,3,23]), 'date');
-    @test = $f->GetField('time');
-    ok(is_deeply(\@test, [12,55,15,0]), 'time');
-    @test = $f->Field('datetime');
-    ok(is_deeply(\@test, [2008,3,23,12,55,20,0]), 'datetime');
-}
-
-{
     my $g2;
     {
-	my $d = Geo::OGR::FeatureDefn->new(Fields=>[Geo::OGR::FieldDefn->new(Name=>'Foo')]);
+	my $d = Geo::OGR::FeatureDefn->new(Fields=>[Geo::OGR::FieldDefn->new(Name => 'Foo', Index => 1)]);
         $d->AddField(Type => 'Point');
 	my $f = Geo::OGR::Feature->new($d);
 	my $g = Geo::OGR::Geometry->new('Point');
@@ -192,10 +136,10 @@ use vars qw/%test_driver $loaded $verbose @types %pack_types @fails @tested_driv
 {
     my $driver = Geo::OGR::Driver('Memory');
     my %cap = map {$_=>1} $driver->Capabilities;
-    ok($cap{CreateDataSource}, "driver capabilities");
-    my $datasource = $driver->CreateDataSource('test');
-    %cap = map {$_=>1} $datasource->Capabilities;
-    ok($cap{CreateLayer} and $cap{DeleteLayer}, "data source capabilities");
+    ok($cap{CREATE}, "driver capabilities");
+    my $datasource = $driver->Create('test');
+    #%cap = map {$_=>1} $datasource->Capabilities;
+    #ok($cap{CreateLayer} and $cap{DeleteLayer}, "data source capabilities");
     
     my $layer = $datasource->CreateLayer('a', undef, 'Point');
     my %cap = map { $_ => 1 } $layer->Capabilities;
@@ -255,7 +199,7 @@ my @tmp = @types;
 for (@tmp) {
     my $a = Geo::OGR::GeometryType($_);
     my $b = Geo::OGR::GeometryType($a);
-    ok($_ eq $b, "geometry type back and forth");
+    #ok($_ eq $b, "geometry type back and forth");
     next if /25/;
     next if /Ring/;
     next if /None/;
diff --git a/swig/perl/t/open.t b/swig/perl/t/open.t
new file mode 100644
index 0000000..f29a599
--- /dev/null
+++ b/swig/perl/t/open.t
@@ -0,0 +1,74 @@
+use strict;
+use warnings;
+use Scalar::Util 'blessed';
+use Test::More qw(no_plan);
+BEGIN { use_ok('Geo::GDAL') };
+
+# Drivers, DriverNames, Driver
+#
+# Geo::GDAL
+# Geo::OGR
+
+for my $method (qw/Drivers DriverNames Driver/) {
+    ok(Geo::GDAL->can($method), "$method exists");
+    ok(Geo::OGR->can($method), "$method exists");
+}
+
+for my $driver (Geo::GDAL::Drivers()) {
+    ok($driver->TestCapability('RASTER'), $driver->Name." is a raster driver");
+}
+
+for my $driver (Geo::OGR::Drivers()) {
+    ok($driver->TestCapability('VECTOR'), $driver->Name." is a vector driver");
+}
+
+# Open, OpenShared, OpenEx 
+#
+# Geo::GDAL: Open, OpenShared, OpenEx
+# Geo::OGR: Open, OpenShared
+# Geo::GDAL::Driver: Open
+# Geo::OGR::Driver: Open
+# Geo::GDAL::Dataset: Open, OpenShared
+# Geo::OGR::DataSource: Open, OpenShared
+
+for my $method (qw/Open OpenShared OpenEx/) {
+    ok(Geo::GDAL->can($method), "$method exists");
+ }
+
+for my $method (qw/Open OpenShared/) {
+    ok(Geo::OGR->can($method), "$method exists");
+    ok(Geo::GDAL::Dataset->can($method), "$method exists");
+    ok(Geo::OGR::DataSource->can($method), "$method exists");
+}
+
+for my $method (qw/Open/) {
+    ok(Geo::GDAL::Driver->can($method), "$method exists");
+    ok(Geo::OGR::Driver->can($method), "$method exists");
+}
+
+# Create, Copy
+#
+# Geo::GDAL::Driver
+# Geo::OGR::Driver
+
+for my $method (qw/Create Copy/) {
+    ok(Geo::GDAL::Driver->can($method), "$method exists");
+    ok(Geo::OGR::Driver->can($method), "$method exists");
+}
+
+{
+    my $ds = Geo::GDAL::Driver('MEM')->Create();
+    ok($ds, "MEM Create works.");
+}
+
+{
+    my $ds = Geo::OGR::Driver('Memory')->Create();
+    ok($ds, "Memory Create works.");
+}
+
+{
+    my $ds = Geo::GDAL::Driver('MEM')->Create();
+    my $progress;
+    Geo::GDAL::Driver('MEM')->Copy( Name => '', src => $ds, progress => sub {$progress = "Me progress!";1});
+    ok($progress eq "Me progress!", "MEM Copy works.");
+}
diff --git a/swig/perl/t/osr.t b/swig/perl/t/osr.t
index 858a662..0cf9602 100644
--- a/swig/perl/t/osr.t
+++ b/swig/perl/t/osr.t
@@ -2,18 +2,29 @@ use strict;
 use warnings;
 use Test::More qw(no_plan);
 BEGIN { use_ok('Geo::GDAL') };
-Geo::GDAL::PushFinderLocation('../../data');
 
-my $srs1 = Geo::OSR::SpatialReference->new(EPSG=>2936);
-my $srs2 = Geo::OSR::SpatialReference->new(Text=>$srs1->AsText);
+Geo::GDAL::PushFinderLocation('../../data'); # built in src tree
+Geo::GDAL::PushFinderLocation('./gdal/data'); # built with downloaded srcs
 
-ok($srs1->ExportToProj4 eq $srs2->ExportToProj4, "new EPSG, Text, Proj4");
+my $find = Geo::GDAL::FindFile('pcs.csv');
 
-my $src = Geo::OSR::SpatialReference->new(EPSG => 2392);
-my $dst = Geo::OSR::SpatialReference->new(EPSG => 2393);
-ok(($src and $dst), "new Geo::OSR::SpatialReference");
+SKIP: {
+    skip "GDAL data files are not available", 2 if !$find;
+    my $srs1 = Geo::OSR::SpatialReference->new(EPSG=>2936);
+    my $srs2 = Geo::OSR::SpatialReference->new(Text=>$srs1->AsText);
+    ok($srs1->ExportToProj4 eq $srs2->ExportToProj4, "new EPSG, Text, Proj4");
+
+    my $src = Geo::OSR::SpatialReference->new(EPSG => 2392);
+    my $dst = Geo::OSR::SpatialReference->new(EPSG => 2393);
+    ok(($src and $dst), "new Geo::OSR::SpatialReference");
+}
 
 SKIP: {
+    skip "GDAL data files are not available", 3 if !$find;
+
+    my $src = Geo::OSR::SpatialReference->new(EPSG => 2392);
+    my $dst = Geo::OSR::SpatialReference->new(EPSG => 2393);
+
     skip "PROJSO not set", 1 if (!$ENV{PROJSO} and $^O eq 'MSWin32');
     my ($t1, $t2);
     eval {
@@ -47,4 +58,3 @@ SKIP: {
     ok(int($p2) == int($polygon[0][0][0]), "from EPSG 2392 to 2393 and back in polygon"); 
     
 }
-
diff --git a/swig/perl/t/parenting.t b/swig/perl/t/parenting.t
new file mode 100644
index 0000000..96955a7
--- /dev/null
+++ b/swig/perl/t/parenting.t
@@ -0,0 +1,131 @@
+use strict;
+use warnings;
+use Scalar::Util 'blessed';
+use Test::More tests => 12;
+BEGIN { use_ok('Geo::GDAL') };
+
+# test parenting, i.e., that dependent objects keep their parents alive
+# child -> parent
+# ---------------
+# Dataset -> Dataset (virtual dataset) BANDS
+# Band -> Dataset BANDS
+# Layer -> Dataset LAYERS
+# RAT -> Band RATS
+# Defn -> Feature DEFNS
+# Defn -> Layer DEFNS
+# Feature -> Layer FEATURES
+# Geometry -> Feature GEOMETRIES
+#
+# parent class has a CHILDREN hash, which contains
+# keys tied(%$child) and $parent values
+#
+# child class has a method RELEASE_PARENTS, which deletes
+# a value from a hash in its parent class
+# the $self in RELEASE_PARENTS is already the scalar $self
+#
+# every time a parent object returns or gives in some other
+# way a child object to user, it records the child into the hash
+
+# Band, Layer, Dataset -> Dataset
+
+{
+    my $ds = Geo::GDAL::Driver('MEM')->Create();
+    my $ds_str = "$ds";
+    my $b = $ds->Band;
+    undef $ds; # does not really delete the underlying dataset
+    my $ds2 = $b->Dataset;
+    my $ds2_str = "$ds2";
+    ok($ds2_str eq $ds_str, "band keeps its parent dataset alive");
+}
+
+{
+    my $ds = Geo::OGR::Driver('Memory')->Create();
+    my $ds_str = "$ds";
+    my $l = $ds->CreateLayer(Name => 'layer');
+    undef $ds; # does not really delete the underlying dataset
+    my $ds2 = $l->Dataset;
+    my $ds2_str = "$ds2";
+    ok($ds2_str eq $ds_str, "layer keeps its parent dataset alive");
+}
+
+{
+    my $ds = Geo::GDAL::Driver('MEM')->Create();
+    my $gt = $ds->GeoTransform(0,2,0,0,0,-1);
+    my $ds_str = "$ds";
+    my $d = $ds->Warped();
+    undef $ds; # does not really delete the underlying dataset
+    my $ds2 = $d->Dataset;
+    my $ds2_str = "$ds2";
+    ok($ds2_str eq $ds_str, "a virtual dataset keeps its parent dataset alive");
+}
+
+# RasterAttributeTable -> Band
+
+{
+    my $ds = Geo::GDAL::Driver('GTiff')->Create(Name => '/vsimem/tmp');
+    my $ds_str = "$ds";
+    my $rat = $ds->Band->RasterAttributeTable(Geo::GDAL::RasterAttributeTable->new);
+    undef $ds; # does not really delete the underlying dataset and band
+    my $ds2 = $rat->Band->Dataset;
+    my $ds2_str = "$ds2";
+    ok($ds2_str eq $ds_str, "a raster attribute table keeps its parent band alive");
+}
+
+# FeatureDefn -> Feature, Layer
+
+{
+    my $ds = Geo::OGR::Driver('Memory')->Create();
+    my $ds_str = "$ds";
+    my $fd = $ds->CreateLayer(Name => 'layer', Fields => [{Name => 'test', Type => 'Integer'}])
+        ->InsertFeature({test => 13})
+        ->GetDefn;
+    undef $ds; # does not really delete the underlying dataset
+    my $ds2 = $fd->Feature->Layer->Dataset;
+    my $ds2_str = "$ds2";
+    ok($ds2_str eq $ds_str, "FeatureDefn keeps its parent dataset alive");
+}
+
+{
+    my $ds = Geo::OGR::Driver('Memory')->Create();
+    my $ds_str = "$ds";
+    my $l = $ds->CreateLayer(Name => 'layer', Fields => [{Name => 'test', Type => 'Integer'}]);
+    $l->InsertFeature({test => 13});
+    my $f;
+    $l->ForFeatures(sub {$f = shift});
+    ok($f->{test} == 13, "Got back the right feature with GetNextFeature.");
+    undef $ds; # does not really delete the underlying dataset
+    my $ds2 = $f->Layer->Dataset;
+    my $ds2_str = "$ds2";
+    ok($ds2_str eq $ds_str, "Feature keeps its parent dataset alive (1/2)");
+}
+
+{
+    my $ds = Geo::OGR::Driver('Memory')->Create();
+    my $ds_str = "$ds";
+    my $l = $ds->CreateLayer(Name => 'layer', Fields => [{Name => 'test', Type => 'Integer'}]);
+    $l->InsertFeature({test => 13});
+    my $f = $l->GetFeature(0);
+    ok($f->{test} == 13, "Got back the right feature with GetFeature.");
+    undef $ds; # does not really delete the underlying dataset
+    my $ds2 = $f->Layer->Dataset;
+    my $ds2_str = "$ds2";
+    ok($ds2_str eq $ds_str, "Feature keeps its parent dataset alive (2/2)");
+}
+
+# Geometry -> Feature
+
+{
+    my $ds = Geo::OGR::Driver('Memory')->Create();
+    my $ds_str = "$ds";
+    my $l = $ds->CreateLayer(Name => 'layer', 
+                             Fields => [{Name => 'test', Type => 'Integer'}, 
+                                        {Name => 'geom', Type => 'Point'}]);
+    $l->InsertFeature({test => 13, geom => {WKT => 'POINT (10 20)'}});
+    my $g = $l->GetFeature(0)->Geometry('geom');
+    ok($g->AsText eq 'POINT (10 20)', "Got back the right geometry.");
+    undef $ds; # does not really delete the underlying dataset
+    undef $l;
+    my $ds2 = $g->Feature->Layer->Dataset;
+    my $ds2_str = "$ds2";
+    ok($ds2_str eq $ds_str, "Geometry keeps its parent dataset alive");
+}
diff --git a/swig/perl/t/utf8.t b/swig/perl/t/utf8.t
new file mode 100644
index 0000000..49bf9c0
--- /dev/null
+++ b/swig/perl/t/utf8.t
@@ -0,0 +1,68 @@
+use strict;
+use warnings;
+use utf8;
+use Scalar::Util 'blessed';
+use Encode qw(encode decode);
+use Test::More tests => 13;
+BEGIN { use_ok('Geo::GDAL') };
+
+# test utf8 conversion in bindings
+
+binmode STDERR, ":utf8"; # when debugging, we like to see the truth
+
+my $fn = "Äri"; # filename with a non-ascii character
+
+system "touch ./$fn"; # touch it
+
+my $e = -e $fn;
+ok($e, "touch a file"); # and it is there
+
+# now use GDAL tools
+
+my %files = map {$_=>1} Geo::GDAL::VSIF::ReadDir('./');
+
+ok($files{$fn}, "it is there");
+
+Geo::GDAL::VSIF::Unlink($fn);
+$e = -e $fn;
+ok(!$e, "deleted");
+
+# that works because the variable has utf8 flag set
+ok(utf8::is_utf8($fn), "Perl knows it is utf8");
+
+system "touch ./$fn"; # touch it again
+
+$fn = "\xC4ri"; # same filename in Perl's internal format
+ok(!utf8::is_utf8($fn), "Perl does not have utf8");
+
+$e = -e $fn;
+ok(!$e, "not there?");
+
+$fn = encode("utf8", $fn); # convert from internal format to utf8
+Encode::_utf8_on($fn); # yes, you have utf8 now
+$e = -e $fn;
+ok($e, "yes it is");
+
+$fn = "\xC4ri"; # internal format, no utf8 flag
+Geo::GDAL::VSIF::Unlink($fn); # encoding is done in the bindings
+$e = -e $fn;
+ok(!$e, "encoding is done in the bindings");
+
+system "touch ./Äri"; # touch it again
+%files = map {$_=>$_} Geo::GDAL::VSIF::ReadDir('./');
+$fn = $files{'Äri'};
+ok(utf8::is_utf8($fn), "utf8 flag is set in the bindings");
+
+system "echo Äri >Äri"; 
+$fn = `cat Äri`;
+chomp($fn);
+ok(!utf8::is_utf8($fn), "Perl does not know it has utf8");
+eval {
+    Geo::GDAL::VSIF::Unlink($fn);
+};
+ok($@, "decoding utf8 ot utf8 is not a good idea");
+
+Encode::_utf8_on($fn); # yes, you have utf8 now
+Geo::GDAL::VSIF::Unlink($fn);
+$e = -e $fn;
+ok(!$e, "show is over");
diff --git a/swig/perl/t/util.t b/swig/perl/t/util.t
new file mode 100644
index 0000000..f450013
--- /dev/null
+++ b/swig/perl/t/util.t
@@ -0,0 +1,76 @@
+use strict;
+use warnings;
+use Scalar::Util 'blessed';
+use Test::More qw(no_plan);
+BEGIN { use_ok('Geo::GDAL') };
+
+# test utilities
+
+# named_parameters
+# call with a list
+
+{
+    my $ret = Geo::GDAL::named_parameters([2], a => 1, b => undef, c => 'abc');
+    ok($ret->{a} == 2, "named_parameters, list, new value");
+    ok($ret->{c} eq 'abc', "named_parameters, list, default value");
+}
+
+# call with a hash ref
+
+{
+    my $ret = Geo::GDAL::named_parameters([{a => 2}], a => 1, b => undef, c => 'abc');
+    ok($ret->{a} == 2, "named_parameters, hash ref, new value $ret->{a}");
+    ok($ret->{c} eq 'abc', "named_parameters, list, default value");
+}
+
+# call with a hash
+
+{
+    my $ret = Geo::GDAL::named_parameters([a => 2], a => 1, b => undef, c => 'abc');
+    ok($ret->{a} == 2, "named_parameters, hash, new value");
+    ok($ret->{c} eq 'abc', "named_parameters, list, default value");
+}
+
+
+# string2int
+my %int2string = (1 => 'a', 2 => 'b', 3 => 'c');
+my %string2int = (a => 1, b => 2, c => 3);
+
+# undef is returned
+{
+    my $a = undef;
+    my $b = Geo::GDAL::string2int($a, \%string2int, \%int2string);
+    ok(!defined $b, "string2int undef is returned");
+}
+
+# default is returned
+{
+    my $a = undef;
+    my $b = Geo::GDAL::string2int($a, \%string2int, \%int2string, 'b');
+    ok($b == 2, "string2int default is returned");
+}
+
+# return given if known int
+{
+    my $a = 2;
+    my $b = Geo::GDAL::string2int($a, \%string2int, \%int2string);
+    ok($b == 2, "string2int return given if known int");
+}
+
+# return string converted to int if known
+{
+    my $a = 'c';
+    my $b = Geo::GDAL::string2int($a, \%string2int, \%int2string);
+    ok($b == 3, "string2int return string converted to int if known");
+}
+
+# error if string is not known
+{
+    my $a = 'x';
+    my $b;
+    eval {
+        $b = Geo::GDAL::string2int($a, \%string2int, \%int2string);
+    };
+    ok($@, "string2int error if string is not known");
+}
+
diff --git a/swig/php/gdal_wrap.cpp b/swig/php/gdal_wrap.cpp
index fcd9997..24b9939 100644
--- a/swig/php/gdal_wrap.cpp
+++ b/swig/php/gdal_wrap.cpp
@@ -167,8 +167,8 @@ template <typename T> T SwigValueInit() {
   You can use the SWIGRUNTIME and SWIGRUNTIMEINLINE macros for
   creating a static or dynamic library from the SWIG runtime code.
   In 99.9% of the cases, SWIG just needs to declare them as 'static'.
-  
-  But only do this if strictly necessary, ie, if you have problems
+
+  But only do this if strictly necessary, i.e. if you have problems
   with your compiler or suchlike.
 */
 
@@ -848,7 +848,7 @@ SWIG_ZTS_SetPointerZval(zval *z, void *ptr, swig_type_info *type, int newobject
       /*
        * Wrap the resource in an object, the resource will be accessible
        * via the "_cPtr" member. This is currently only used by
-       * directorin typemaps.
+       * directory typemaps.
        */
       value->newobject = 0;
       zval *resource;
@@ -1438,7 +1438,7 @@ t_output_helper( zval **target, zval *o) {
 }
 
 
-/* Returned size is in bytes or 0 if an error occured */
+/* Returned size is in bytes or 0 if an error occurred */
 static
 GIntBig ComputeDatasetRasterIOSize (int buf_xsize, int buf_ysize, int nPixelSize,
                                 int nBands, int* bandMap, int nBandMapArrayLength,
@@ -1784,7 +1784,7 @@ int GDALDatasetShadow_RasterCount_get( GDALDatasetShadow *h ) {
 }
 
 
-/* Returned size is in bytes or 0 if an error occured */
+/* Returned size is in bytes or 0 if an error occurred */
 static
 GIntBig ComputeBandRasterIOSize (int buf_xsize, int buf_ysize, int nPixelSize,
                              int nPixelSpace, int nLineSpace,
@@ -2212,7 +2212,7 @@ int  ComputeMedianCutPCT ( GDALRasterBandShadow *red,
                                           colors,
                                           callback,
                                           callback_data);
-    
+
     return err;
 }
 
@@ -2234,7 +2234,7 @@ int  DitherRGB2PCT ( GDALRasterBandShadow *red,
                                   colors,
                                   callback,
                                   callback_data);
-    
+
     return err;
 }
 
@@ -2261,7 +2261,7 @@ CPLErr  ReprojectImage ( GDALDatasetShadow *src_ds,
                                      callback,
                                      callback_data,
                                      NULL);
-    
+
     return err;
 }
 
@@ -13527,10 +13527,10 @@ SWIG_InitializeModule(void *clientdata) {
     module_head->next = &swig_module;
   }
 
-  /* When multiple interpeters are used, a module could have already been initialized in
-     a different interpreter, but not yet have a pointer in this interpreter.
-     In this case, we do not want to continue adding types... everything should be
-     set up already */
+  /* When multiple interpreters are used, a module could have already
+     been initialized in a different interpreter, but not yet have a
+     pointer in this interpreter.  In this case, we do not want to
+     continue adding types... everything should be set up already */
   if (init == 0) return;
 
   /* Now work on filling in swig_module.types */
@@ -13541,7 +13541,7 @@ SWIG_InitializeModule(void *clientdata) {
     swig_type_info *type = 0;
     swig_type_info *ret;
     swig_cast_info *cast;
-  
+
 #ifdef SWIGRUNTIME_DEBUG
     printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name);
 #endif
diff --git a/swig/php/gdalconst_wrap.c b/swig/php/gdalconst_wrap.c
index f106bfd..dfa61bd 100644
--- a/swig/php/gdalconst_wrap.c
+++ b/swig/php/gdalconst_wrap.c
@@ -145,7 +145,7 @@
   In 99.9% of the cases, SWIG just needs to declare them as 'static'.
   
   But only do this if strictly necessary, ie, if you have problems
-  with your compiler or suchlike.
+  with your compiler or such.
 */
 
 #ifndef SWIGRUNTIME
@@ -824,7 +824,7 @@ SWIG_ZTS_SetPointerZval(zval *z, void *ptr, swig_type_info *type, int newobject
       /*
        * Wrap the resource in an object, the resource will be accessible
        * via the "_cPtr" member. This is currently only used by
-       * directorin typemaps.
+       * directory typemaps.
        */
       value->newobject = 0;
       zval *resource;
@@ -1232,10 +1232,10 @@ SWIG_InitializeModule(void *clientdata) {
     module_head->next = &swig_module;
   }
 
-  /* When multiple interpeters are used, a module could have already been initialized in
-     a different interpreter, but not yet have a pointer in this interpreter.
-     In this case, we do not want to continue adding types... everything should be
-     set up already */
+  /* When multiple interpreters are used, a module could have already
+     been initialized in a different interpreter, but not yet have a
+     pointer in this interpreter.  In this case, we do not want to
+     continue adding types... everything should be set up already */
   if (init == 0) return;
 
   /* Now work on filling in swig_module.types */
diff --git a/swig/php/gnm.php b/swig/php/gnm.php
new file mode 100644
index 0000000..d399d7d
--- /dev/null
+++ b/swig/php/gnm.php
@@ -0,0 +1,293 @@
+<?php
+
+/* ----------------------------------------------------------------------------
+ * This file was automatically generated by SWIG (http://www.swig.org).
+ * Version 2.0.12
+ *
+ * This file is not intended to be easily readable and contains a number of
+ * coding conventions designed to improve portability and efficiency. Do not make
+ * changes to this file unless you know what you are doing--modify the SWIG
+ * interface file instead.
+ * ----------------------------------------------------------------------------- */
+
+// Try to load our extension if it's not already loaded.
+if (!extension_loaded('gnm')) {
+  if (strtolower(substr(PHP_OS, 0, 3)) === 'win') {
+    if (!dl('php_gnm.dll')) return;
+  } else {
+    // PHP_SHLIB_SUFFIX gives 'dylib' on MacOS X but modules are 'so'.
+    if (PHP_SHLIB_SUFFIX === 'dylib') {
+      if (!dl('gnm.so')) return;
+    } else {
+      if (!dl('gnm.'.PHP_SHLIB_SUFFIX)) return;
+    }
+  }
+}
+
+
+
+abstract class gnm {
+	const GATDijkstraShortestPath = 1;
+
+	const GATKShortestPath = 2;
+
+	const GATConnectedComponents = 3;
+
+	const GNM_EDGE_DIR_BOTH = GNM_EDGE_DIR_BOTH;
+
+	const GNM_EDGE_DIR_SRCTOTGT = GNM_EDGE_DIR_SRCTOTGT;
+
+	const GNM_EDGE_DIR_TGTTOSRC = GNM_EDGE_DIR_TGTTOSRC;
+
+	static function CastToNetwork($base) {
+		$r=CastToNetwork($base);
+		if (is_resource($r)) {
+			$c=substr(get_resource_type($r), (strpos(get_resource_type($r), '__') ? strpos(get_resource_type($r), '__') + 2 : 3));
+			if (class_exists($c)) return new $c($r);
+			return new Network($r);
+		}
+		return $r;
+	}
+
+	static function CastToGenericNetwork($base) {
+		$r=CastToGenericNetwork($base);
+		if (is_resource($r)) {
+			$c=substr(get_resource_type($r), (strpos(get_resource_type($r), '__') ? strpos(get_resource_type($r), '__') + 2 : 3));
+			if (class_exists($c)) return new $c($r);
+			return new GenericNetwork($r);
+		}
+		return $r;
+	}
+}
+
+/* PHP Proxy Classes */
+class MajorObject {
+	public $_cPtr=null;
+	protected $_pData=array();
+
+	function __set($var,$value) {
+		if ($var === 'thisown') return swig_gnm_alter_newobject($this->_cPtr,$value);
+		$this->_pData[$var] = $value;
+	}
+
+	function __isset($var) {
+		if ($var === 'thisown') return true;
+		return array_key_exists($var, $this->_pData);
+	}
+
+	function __get($var) {
+		if ($var === 'thisown') return swig_gnm_get_newobject($this->_cPtr);
+		return $this->_pData[$var];
+	}
+	function __construct($h) {
+		$this->_cPtr=$h;
+	}
+
+	function GetDescription() {
+		return MajorObject_GetDescription($this->_cPtr);
+	}
+
+	function SetDescription($pszNewDesc) {
+		MajorObject_SetDescription($this->_cPtr,$pszNewDesc);
+	}
+
+	function GetMetadataDomainList() {
+		return MajorObject_GetMetadataDomainList($this->_cPtr);
+	}
+
+	function GetMetadata_Dict($pszDomain="") {
+		return MajorObject_GetMetadata_Dict($this->_cPtr,$pszDomain);
+	}
+
+	function GetMetadata_List($pszDomain="") {
+		return MajorObject_GetMetadata_List($this->_cPtr,$pszDomain);
+	}
+
+	function SetMetadata($papszMetadata_or_pszMetadataString,$pszDomain="") {
+		$r=MajorObject_SetMetadata($this->_cPtr,$papszMetadata_or_pszMetadataString,$pszDomain);
+		return $r;
+	}
+
+	function GetMetadataItem($pszName,$pszDomain="") {
+		return MajorObject_GetMetadataItem($this->_cPtr,$pszName,$pszDomain);
+	}
+
+	function SetMetadataItem($pszName,$pszValue,$pszDomain="") {
+		return MajorObject_SetMetadataItem($this->_cPtr,$pszName,$pszValue,$pszDomain);
+	}
+}
+
+class Network extends MajorObject {
+	public $_cPtr=null;
+
+	function __set($var,$value) {
+		if ($var === 'thisown') return swig_gnm_alter_newobject($this->_cPtr,$value);
+		MajorObject::__set($var,$value);
+	}
+
+	function __isset($var) {
+		if ($var === 'thisown') return true;
+		return MajorObject::__isset($var);
+	}
+
+	function __get($var) {
+		if ($var === 'thisown') return swig_gnm_get_newobject($this->_cPtr);
+		return MajorObject::__get($var);
+	}
+	function __construct($h) {
+		$this->_cPtr=$h;
+	}
+
+	function ReleaseResultSet($layer) {
+		Network_ReleaseResultSet($this->_cPtr,$layer);
+	}
+
+	function GetVersion() {
+		return Network_GetVersion($this->_cPtr);
+	}
+
+	function GetName() {
+		return Network_GetName($this->_cPtr);
+	}
+
+	function GetFeatureByGlobalFID($GFID) {
+		return Network_GetFeatureByGlobalFID($this->_cPtr,$GFID);
+	}
+
+	function GetPath($nStartFID,$nEndFID,$eAlgorithm,$options=null) {
+		return Network_GetPath($this->_cPtr,$nStartFID,$nEndFID,$eAlgorithm,$options);
+	}
+
+	function DisconnectAll() {
+		return Network_DisconnectAll($this->_cPtr);
+	}
+
+	function GetProjection() {
+		return Network_GetProjection($this->_cPtr);
+	}
+
+	function GetProjectionRef() {
+		return Network_GetProjectionRef($this->_cPtr);
+	}
+
+	function GetFileList() {
+		return Network_GetFileList($this->_cPtr);
+	}
+
+	function CreateLayer($name,$srs=null,$geom_type=null,$options=null) {
+		switch (func_num_args()) {
+		case 1: case 2: $r=Network_CreateLayer($this->_cPtr,$name,$srs); break;
+		default: $r=Network_CreateLayer($this->_cPtr,$name,$srs,$geom_type,$options);
+		}
+		return $r;
+	}
+
+	function CopyLayer($src_layer,$new_name,$options=null) {
+		return Network_CopyLayer($this->_cPtr,$src_layer,$new_name,$options);
+	}
+
+	function DeleteLayer($index) {
+		return Network_DeleteLayer($this->_cPtr,$index);
+	}
+
+	function GetLayerCount() {
+		return Network_GetLayerCount($this->_cPtr);
+	}
+
+	function GetLayerByIndex($index=0) {
+		return Network_GetLayerByIndex($this->_cPtr,$index);
+	}
+
+	function GetLayerByName($layer_name) {
+		return Network_GetLayerByName($this->_cPtr,$layer_name);
+	}
+
+	function TestCapability($cap) {
+		return Network_TestCapability($this->_cPtr,$cap);
+	}
+
+	function StartTransaction($force=null) {
+		switch (func_num_args()) {
+		case 0: $r=Network_StartTransaction($this->_cPtr); break;
+		default: $r=Network_StartTransaction($this->_cPtr,$force);
+		}
+		return $r;
+	}
+
+	function CommitTransaction() {
+		return Network_CommitTransaction($this->_cPtr);
+	}
+
+	function RollbackTransaction() {
+		return Network_RollbackTransaction($this->_cPtr);
+	}
+}
+
+class GenericNetwork extends Network {
+	public $_cPtr=null;
+
+	function __set($var,$value) {
+		if ($var === 'thisown') return swig_gnm_alter_newobject($this->_cPtr,$value);
+		Network::__set($var,$value);
+	}
+
+	function __isset($var) {
+		if ($var === 'thisown') return true;
+		return Network::__isset($var);
+	}
+
+	function __get($var) {
+		if ($var === 'thisown') return swig_gnm_get_newobject($this->_cPtr);
+		return Network::__get($var);
+	}
+	function __construct($h) {
+		$this->_cPtr=$h;
+	}
+
+	function ConnectFeatures($nSrcFID,$nTgtFID,$nConFID,$dfCost,$dfInvCost,$eDir) {
+		return GenericNetwork_ConnectFeatures($this->_cPtr,$nSrcFID,$nTgtFID,$nConFID,$dfCost,$dfInvCost,$eDir);
+	}
+
+	function DisconnectFeatures($nSrcFID,$nTgtFID,$nConFID) {
+		return GenericNetwork_DisconnectFeatures($this->_cPtr,$nSrcFID,$nTgtFID,$nConFID);
+	}
+
+	function DisconnectFeaturesWithId($nFID) {
+		return GenericNetwork_DisconnectFeaturesWithId($this->_cPtr,$nFID);
+	}
+
+	function ReconnectFeatures($nSrcFID,$nTgtFID,$nConFID,$dfCost,$dfInvCost,$eDir) {
+		return GenericNetwork_ReconnectFeatures($this->_cPtr,$nSrcFID,$nTgtFID,$nConFID,$dfCost,$dfInvCost,$eDir);
+	}
+
+	function CreateRule($pszRuleStr) {
+		return GenericNetwork_CreateRule($this->_cPtr,$pszRuleStr);
+	}
+
+	function DeleteAllRules() {
+		return GenericNetwork_DeleteAllRules($this->_cPtr);
+	}
+
+	function DeleteRule($pszRuleStr) {
+		return GenericNetwork_DeleteRule($this->_cPtr,$pszRuleStr);
+	}
+
+	function GetRules() {
+		return GenericNetwork_GetRules($this->_cPtr);
+	}
+
+	function ConnectPointsByLines($papszLayerList,$dfTolerance,$dfCost,$dfInvCost,$eDir) {
+		return GenericNetwork_ConnectPointsByLines($this->_cPtr,$papszLayerList,$dfTolerance,$dfCost,$dfInvCost,$eDir);
+	}
+
+	function ChangeBlockState($nFID,$bIsBlock) {
+		return GenericNetwork_ChangeBlockState($this->_cPtr,$nFID,$bIsBlock);
+	}
+
+	function ChangeAllBlockState($bIsBlock=false) {
+		return GenericNetwork_ChangeAllBlockState($this->_cPtr,$bIsBlock);
+	}
+}
+
+
+?>
diff --git a/swig/php/gnm_wrap.cpp b/swig/php/gnm_wrap.cpp
new file mode 100644
index 0000000..8474f46
--- /dev/null
+++ b/swig/php/gnm_wrap.cpp
@@ -0,0 +1,3705 @@
+/* ----------------------------------------------------------------------------
+ * This file was automatically generated by SWIG (http://www.swig.org).
+ * Version 2.0.12
+ *
+ * This file is not intended to be easily readable and contains a number of
+ * coding conventions designed to improve portability and efficiency. Do not make
+ * changes to this file unless you know what you are doing--modify the SWIG
+ * interface file instead.
+ * ----------------------------------------------------------------------------- */
+
+#define SWIGPHP
+
+#define SWIG_PREFIX ""
+#define SWIG_PREFIX_LEN 0
+
+#ifdef __cplusplus
+/* SwigValueWrapper is described in swig.swg */
+template<typename T> class SwigValueWrapper {
+  struct SwigMovePointer {
+    T *ptr;
+    SwigMovePointer(T *p) : ptr(p) { }
+    ~SwigMovePointer() { delete ptr; }
+    SwigMovePointer& operator=(SwigMovePointer& rhs) { T* oldptr = ptr; ptr = 0; delete oldptr; ptr = rhs.ptr; rhs.ptr = 0; return *this; }
+  } pointer;
+  SwigValueWrapper& operator=(const SwigValueWrapper<T>& rhs);
+  SwigValueWrapper(const SwigValueWrapper<T>& rhs);
+public:
+  SwigValueWrapper() : pointer(0) { }
+  SwigValueWrapper& operator=(const T& t) { SwigMovePointer tmp(new T(t)); pointer = tmp; return *this; }
+  operator T&() const { return *pointer.ptr; }
+  T *operator&() { return pointer.ptr; }
+};
+
+template <typename T> T SwigValueInit() {
+  return T();
+}
+#endif
+
+/* -----------------------------------------------------------------------------
+ *  This section contains generic SWIG labels for method/variable
+ *  declarations/attributes, and other compiler dependent labels.
+ * ----------------------------------------------------------------------------- */
+
+/* template workaround for compilers that cannot correctly implement the C++ standard */
+#ifndef SWIGTEMPLATEDISAMBIGUATOR
+# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560)
+#  define SWIGTEMPLATEDISAMBIGUATOR template
+# elif defined(__HP_aCC)
+/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */
+/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */
+#  define SWIGTEMPLATEDISAMBIGUATOR template
+# else
+#  define SWIGTEMPLATEDISAMBIGUATOR
+# endif
+#endif
+
+/* inline attribute */
+#ifndef SWIGINLINE
+# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__))
+#   define SWIGINLINE inline
+# else
+#   define SWIGINLINE
+# endif
+#endif
+
+/* attribute recognised by some compilers to avoid 'unused' warnings */
+#ifndef SWIGUNUSED
+# if defined(__GNUC__)
+#   if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
+#     define SWIGUNUSED __attribute__ ((__unused__))
+#   else
+#     define SWIGUNUSED
+#   endif
+# elif defined(__ICC)
+#   define SWIGUNUSED __attribute__ ((__unused__))
+# else
+#   define SWIGUNUSED
+# endif
+#endif
+
+#ifndef SWIG_MSC_UNSUPPRESS_4505
+# if defined(_MSC_VER)
+#   pragma warning(disable : 4505) /* unreferenced local function has been removed */
+# endif
+#endif
+
+#ifndef SWIGUNUSEDPARM
+# ifdef __cplusplus
+#   define SWIGUNUSEDPARM(p)
+# else
+#   define SWIGUNUSEDPARM(p) p SWIGUNUSED
+# endif
+#endif
+
+/* internal SWIG method */
+#ifndef SWIGINTERN
+# define SWIGINTERN static SWIGUNUSED
+#endif
+
+/* internal inline SWIG method */
+#ifndef SWIGINTERNINLINE
+# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE
+#endif
+
+/* exporting methods */
+#if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+#  ifndef GCC_HASCLASSVISIBILITY
+#    define GCC_HASCLASSVISIBILITY
+#  endif
+#endif
+
+#ifndef SWIGEXPORT
+# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+#   if defined(STATIC_LINKED)
+#     define SWIGEXPORT
+#   else
+#     define SWIGEXPORT __declspec(dllexport)
+#   endif
+# else
+#   if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY)
+#     define SWIGEXPORT __attribute__ ((visibility("default")))
+#   else
+#     define SWIGEXPORT
+#   endif
+# endif
+#endif
+
+/* calling conventions for Windows */
+#ifndef SWIGSTDCALL
+# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+#   define SWIGSTDCALL __stdcall
+# else
+#   define SWIGSTDCALL
+# endif
+#endif
+
+/* Deal with Microsoft's attempt at deprecating C standard runtime functions */
+#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
+# define _CRT_SECURE_NO_DEPRECATE
+#endif
+
+/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */
+#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE)
+# define _SCL_SECURE_NO_DEPRECATE
+#endif
+
+
+/* -----------------------------------------------------------------------------
+ * swigrun.swg
+ *
+ * This file contains generic C API SWIG runtime support for pointer
+ * type checking.
+ * ----------------------------------------------------------------------------- */
+
+/* This should only be incremented when either the layout of swig_type_info changes,
+   or for whatever reason, the runtime changes incompatibly */
+#define SWIG_RUNTIME_VERSION "4"
+
+/* define SWIG_TYPE_TABLE_NAME as "SWIG_TYPE_TABLE" */
+#ifdef SWIG_TYPE_TABLE
+# define SWIG_QUOTE_STRING(x) #x
+# define SWIG_EXPAND_AND_QUOTE_STRING(x) SWIG_QUOTE_STRING(x)
+# define SWIG_TYPE_TABLE_NAME SWIG_EXPAND_AND_QUOTE_STRING(SWIG_TYPE_TABLE)
+#else
+# define SWIG_TYPE_TABLE_NAME
+#endif
+
+/*
+  You can use the SWIGRUNTIME and SWIGRUNTIMEINLINE macros for
+  creating a static or dynamic library from the SWIG runtime code.
+  In 99.9% of the cases, SWIG just needs to declare them as 'static'.
+
+  But only do this if strictly necessary, i.e. if you have problems
+  with your compiler or such.
+*/
+
+#ifndef SWIGRUNTIME
+# define SWIGRUNTIME SWIGINTERN
+#endif
+
+#ifndef SWIGRUNTIMEINLINE
+# define SWIGRUNTIMEINLINE SWIGRUNTIME SWIGINLINE
+#endif
+
+/*  Generic buffer size */
+#ifndef SWIG_BUFFER_SIZE
+# define SWIG_BUFFER_SIZE 1024
+#endif
+
+/* Flags for pointer conversions */
+#define SWIG_POINTER_DISOWN        0x1
+#define SWIG_CAST_NEW_MEMORY       0x2
+
+/* Flags for new pointer objects */
+#define SWIG_POINTER_OWN           0x1
+
+
+/*
+   Flags/methods for returning states.
+
+   The SWIG conversion methods, as ConvertPtr, return an integer
+   that tells if the conversion was successful or not. And if not,
+   an error code can be returned (see swigerrors.swg for the codes).
+
+   Use the following macros/flags to set or process the returning
+   states.
+
+   In old versions of SWIG, code such as the following was usually written:
+
+     if (SWIG_ConvertPtr(obj,vptr,ty.flags) != -1) {
+       // success code
+     } else {
+       //fail code
+     }
+
+   Now you can be more explicit:
+
+    int res = SWIG_ConvertPtr(obj,vptr,ty.flags);
+    if (SWIG_IsOK(res)) {
+      // success code
+    } else {
+      // fail code
+    }
+
+   which is the same really, but now you can also do
+
+    Type *ptr;
+    int res = SWIG_ConvertPtr(obj,(void **)(&ptr),ty.flags);
+    if (SWIG_IsOK(res)) {
+      // success code
+      if (SWIG_IsNewObj(res) {
+        ...
+	delete *ptr;
+      } else {
+        ...
+      }
+    } else {
+      // fail code
+    }
+
+   I.e., now SWIG_ConvertPtr can return new objects and you can
+   identify the case and take care of the deallocation. Of course that
+   also requires SWIG_ConvertPtr to return new result values, such as
+
+      int SWIG_ConvertPtr(obj, ptr,...) {
+        if (<obj is ok>) {
+          if (<need new object>) {
+            *ptr = <ptr to new allocated object>;
+            return SWIG_NEWOBJ;
+          } else {
+            *ptr = <ptr to old object>;
+            return SWIG_OLDOBJ;
+          }
+        } else {
+          return SWIG_BADOBJ;
+        }
+      }
+
+   Of course, returning the plain '0(success)/-1(fail)' still works, but you can be
+   more explicit by returning SWIG_BADOBJ, SWIG_ERROR or any of the
+   SWIG errors code.
+
+   Finally, if the SWIG_CASTRANK_MODE is enabled, the result code
+   allows to return the 'cast rank', for example, if you have this
+
+       int food(double)
+       int fooi(int);
+
+   and you call
+
+      food(1)   // cast rank '1'  (1 -> 1.0)
+      fooi(1)   // cast rank '0'
+
+   just use the SWIG_AddCast()/SWIG_CheckState()
+*/
+
+#define SWIG_OK                    (0)
+#define SWIG_ERROR                 (-1)
+#define SWIG_IsOK(r)               (r >= 0)
+#define SWIG_ArgError(r)           ((r != SWIG_ERROR) ? r : SWIG_TypeError)
+
+/* The CastRankLimit says how many bits are used for the cast rank */
+#define SWIG_CASTRANKLIMIT         (1 << 8)
+/* The NewMask denotes the object was created (using new/malloc) */
+#define SWIG_NEWOBJMASK            (SWIG_CASTRANKLIMIT  << 1)
+/* The TmpMask is for in/out typemaps that use temporal objects */
+#define SWIG_TMPOBJMASK            (SWIG_NEWOBJMASK << 1)
+/* Simple returning values */
+#define SWIG_BADOBJ                (SWIG_ERROR)
+#define SWIG_OLDOBJ                (SWIG_OK)
+#define SWIG_NEWOBJ                (SWIG_OK | SWIG_NEWOBJMASK)
+#define SWIG_TMPOBJ                (SWIG_OK | SWIG_TMPOBJMASK)
+/* Check, add and del mask methods */
+#define SWIG_AddNewMask(r)         (SWIG_IsOK(r) ? (r | SWIG_NEWOBJMASK) : r)
+#define SWIG_DelNewMask(r)         (SWIG_IsOK(r) ? (r & ~SWIG_NEWOBJMASK) : r)
+#define SWIG_IsNewObj(r)           (SWIG_IsOK(r) && (r & SWIG_NEWOBJMASK))
+#define SWIG_AddTmpMask(r)         (SWIG_IsOK(r) ? (r | SWIG_TMPOBJMASK) : r)
+#define SWIG_DelTmpMask(r)         (SWIG_IsOK(r) ? (r & ~SWIG_TMPOBJMASK) : r)
+#define SWIG_IsTmpObj(r)           (SWIG_IsOK(r) && (r & SWIG_TMPOBJMASK))
+
+/* Cast-Rank Mode */
+#if defined(SWIG_CASTRANK_MODE)
+#  ifndef SWIG_TypeRank
+#    define SWIG_TypeRank             unsigned long
+#  endif
+#  ifndef SWIG_MAXCASTRANK            /* Default cast allowed */
+#    define SWIG_MAXCASTRANK          (2)
+#  endif
+#  define SWIG_CASTRANKMASK          ((SWIG_CASTRANKLIMIT) -1)
+#  define SWIG_CastRank(r)           (r & SWIG_CASTRANKMASK)
+SWIGINTERNINLINE int SWIG_AddCast(int r) {
+  return SWIG_IsOK(r) ? ((SWIG_CastRank(r) < SWIG_MAXCASTRANK) ? (r + 1) : SWIG_ERROR) : r;
+}
+SWIGINTERNINLINE int SWIG_CheckState(int r) {
+  return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0;
+}
+#else /* no cast-rank mode */
+#  define SWIG_AddCast(r) (r)
+#  define SWIG_CheckState(r) (SWIG_IsOK(r) ? 1 : 0)
+#endif
+
+
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void *(*swig_converter_func)(void *, int *);
+typedef struct swig_type_info *(*swig_dycast_func)(void **);
+
+/* Structure to store information on one type */
+typedef struct swig_type_info {
+  const char             *name;			/* mangled name of this type */
+  const char             *str;			/* human readable name of this type */
+  swig_dycast_func        dcast;		/* dynamic cast function down a hierarchy */
+  struct swig_cast_info  *cast;			/* linked list of types that can cast into this type */
+  void                   *clientdata;		/* language specific type data */
+  int                    owndata;		/* flag if the structure owns the clientdata */
+} swig_type_info;
+
+/* Structure to store a type and conversion function used for casting */
+typedef struct swig_cast_info {
+  swig_type_info         *type;			/* pointer to type that is equivalent to this type */
+  swig_converter_func     converter;		/* function to cast the void pointers */
+  struct swig_cast_info  *next;			/* pointer to next cast in linked list */
+  struct swig_cast_info  *prev;			/* pointer to the previous cast */
+} swig_cast_info;
+
+/* Structure used to store module information
+ * Each module generates one structure like this, and the runtime collects
+ * all of these structures and stores them in a circularly linked list.*/
+typedef struct swig_module_info {
+  swig_type_info         **types;		/* Array of pointers to swig_type_info structures that are in this module */
+  size_t                 size;		        /* Number of types in this module */
+  struct swig_module_info *next;		/* Pointer to next element in circularly linked list */
+  swig_type_info         **type_initial;	/* Array of initially generated type structures */
+  swig_cast_info         **cast_initial;	/* Array of initially generated casting structures */
+  void                    *clientdata;		/* Language specific module data */
+} swig_module_info;
+
+/*
+  Compare two type names skipping the space characters, therefore
+  "char*" == "char *" and "Class<int>" == "Class<int >", etc.
+
+  Return 0 when the two name types are equivalent, as in
+  strncmp, but skipping ' '.
+*/
+SWIGRUNTIME int
+SWIG_TypeNameComp(const char *f1, const char *l1,
+		  const char *f2, const char *l2) {
+  for (;(f1 != l1) && (f2 != l2); ++f1, ++f2) {
+    while ((*f1 == ' ') && (f1 != l1)) ++f1;
+    while ((*f2 == ' ') && (f2 != l2)) ++f2;
+    if (*f1 != *f2) return (*f1 > *f2) ? 1 : -1;
+  }
+  return (int)((l1 - f1) - (l2 - f2));
+}
+
+/*
+  Check type equivalence in a name list like <name1>|<name2>|...
+  Return 0 if equal, -1 if nb < tb, 1 if nb > tb
+*/
+SWIGRUNTIME int
+SWIG_TypeCmp(const char *nb, const char *tb) {
+  int equiv = 1;
+  const char* te = tb + strlen(tb);
+  const char* ne = nb;
+  while (equiv != 0 && *ne) {
+    for (nb = ne; *ne; ++ne) {
+      if (*ne == '|') break;
+    }
+    equiv = SWIG_TypeNameComp(nb, ne, tb, te);
+    if (*ne) ++ne;
+  }
+  return equiv;
+}
+
+/*
+  Check type equivalence in a name list like <name1>|<name2>|...
+  Return 0 if not equal, 1 if equal
+*/
+SWIGRUNTIME int
+SWIG_TypeEquiv(const char *nb, const char *tb) {
+  return SWIG_TypeCmp(nb, tb) == 0 ? 1 : 0;
+}
+
+/*
+  Check the typename
+*/
+SWIGRUNTIME swig_cast_info *
+SWIG_TypeCheck(const char *c, swig_type_info *ty) {
+  if (ty) {
+    swig_cast_info *iter = ty->cast;
+    while (iter) {
+      if (strcmp(iter->type->name, c) == 0) {
+        if (iter == ty->cast)
+          return iter;
+        /* Move iter to the top of the linked list */
+        iter->prev->next = iter->next;
+        if (iter->next)
+          iter->next->prev = iter->prev;
+        iter->next = ty->cast;
+        iter->prev = 0;
+        if (ty->cast) ty->cast->prev = iter;
+        ty->cast = iter;
+        return iter;
+      }
+      iter = iter->next;
+    }
+  }
+  return 0;
+}
+
+/*
+  Identical to SWIG_TypeCheck, except strcmp is replaced with a pointer comparison
+*/
+SWIGRUNTIME swig_cast_info *
+SWIG_TypeCheckStruct(swig_type_info *from, swig_type_info *ty) {
+  if (ty) {
+    swig_cast_info *iter = ty->cast;
+    while (iter) {
+      if (iter->type == from) {
+        if (iter == ty->cast)
+          return iter;
+        /* Move iter to the top of the linked list */
+        iter->prev->next = iter->next;
+        if (iter->next)
+          iter->next->prev = iter->prev;
+        iter->next = ty->cast;
+        iter->prev = 0;
+        if (ty->cast) ty->cast->prev = iter;
+        ty->cast = iter;
+        return iter;
+      }
+      iter = iter->next;
+    }
+  }
+  return 0;
+}
+
+/*
+  Cast a pointer up an inheritance hierarchy
+*/
+SWIGRUNTIMEINLINE void *
+SWIG_TypeCast(swig_cast_info *ty, void *ptr, int *newmemory) {
+  return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr, newmemory);
+}
+
+/*
+   Dynamic pointer casting. Down an inheritance hierarchy
+*/
+SWIGRUNTIME swig_type_info *
+SWIG_TypeDynamicCast(swig_type_info *ty, void **ptr) {
+  swig_type_info *lastty = ty;
+  if (!ty || !ty->dcast) return ty;
+  while (ty && (ty->dcast)) {
+    ty = (*ty->dcast)(ptr);
+    if (ty) lastty = ty;
+  }
+  return lastty;
+}
+
+/*
+  Return the name associated with this type
+*/
+SWIGRUNTIMEINLINE const char *
+SWIG_TypeName(const swig_type_info *ty) {
+  return ty->name;
+}
+
+/*
+  Return the pretty name associated with this type,
+  that is an unmangled type name in a form presentable to the user.
+*/
+SWIGRUNTIME const char *
+SWIG_TypePrettyName(const swig_type_info *type) {
+  /* The "str" field contains the equivalent pretty names of the
+     type, separated by vertical-bar characters.  We choose
+     to print the last name, as it is often (?) the most
+     specific. */
+  if (!type) return NULL;
+  if (type->str != NULL) {
+    const char *last_name = type->str;
+    const char *s;
+    for (s = type->str; *s; s++)
+      if (*s == '|') last_name = s+1;
+    return last_name;
+  }
+  else
+    return type->name;
+}
+
+/*
+   Set the clientdata field for a type
+*/
+SWIGRUNTIME void
+SWIG_TypeClientData(swig_type_info *ti, void *clientdata) {
+  swig_cast_info *cast = ti->cast;
+  /* if (ti->clientdata == clientdata) return; */
+  ti->clientdata = clientdata;
+
+  while (cast) {
+    if (!cast->converter) {
+      swig_type_info *tc = cast->type;
+      if (!tc->clientdata) {
+	SWIG_TypeClientData(tc, clientdata);
+      }
+    }
+    cast = cast->next;
+  }
+}
+SWIGRUNTIME void
+SWIG_TypeNewClientData(swig_type_info *ti, void *clientdata) {
+  SWIG_TypeClientData(ti, clientdata);
+  ti->owndata = 1;
+}
+
+/*
+  Search for a swig_type_info structure only by mangled name
+  Search is a O(log #types)
+
+  We start searching at module start, and finish searching when start == end.
+  Note: if start == end at the beginning of the function, we go all the way around
+  the circular list.
+*/
+SWIGRUNTIME swig_type_info *
+SWIG_MangledTypeQueryModule(swig_module_info *start,
+                            swig_module_info *end,
+		            const char *name) {
+  swig_module_info *iter = start;
+  do {
+    if (iter->size) {
+      register size_t l = 0;
+      register size_t r = iter->size - 1;
+      do {
+	/* since l+r >= 0, we can (>> 1) instead (/ 2) */
+	register size_t i = (l + r) >> 1;
+	const char *iname = iter->types[i]->name;
+	if (iname) {
+	  register int compare = strcmp(name, iname);
+	  if (compare == 0) {
+	    return iter->types[i];
+	  } else if (compare < 0) {
+	    if (i) {
+	      r = i - 1;
+	    } else {
+	      break;
+	    }
+	  } else if (compare > 0) {
+	    l = i + 1;
+	  }
+	} else {
+	  break; /* should never happen */
+	}
+      } while (l <= r);
+    }
+    iter = iter->next;
+  } while (iter != end);
+  return 0;
+}
+
+/*
+  Search for a swig_type_info structure for either a mangled name or a human readable name.
+  It first searches the mangled names of the types, which is a O(log #types)
+  If a type is not found it then searches the human readable names, which is O(#types).
+
+  We start searching at module start, and finish searching when start == end.
+  Note: if start == end at the beginning of the function, we go all the way around
+  the circular list.
+*/
+SWIGRUNTIME swig_type_info *
+SWIG_TypeQueryModule(swig_module_info *start,
+                     swig_module_info *end,
+		     const char *name) {
+  /* STEP 1: Search the name field using binary search */
+  swig_type_info *ret = SWIG_MangledTypeQueryModule(start, end, name);
+  if (ret) {
+    return ret;
+  } else {
+    /* STEP 2: If the type hasn't been found, do a complete search
+       of the str field (the human readable name) */
+    swig_module_info *iter = start;
+    do {
+      register size_t i = 0;
+      for (; i < iter->size; ++i) {
+	if (iter->types[i]->str && (SWIG_TypeEquiv(iter->types[i]->str, name)))
+	  return iter->types[i];
+      }
+      iter = iter->next;
+    } while (iter != end);
+  }
+
+  /* neither found a match */
+  return 0;
+}
+
+/*
+   Pack binary data into a string
+*/
+SWIGRUNTIME char *
+SWIG_PackData(char *c, void *ptr, size_t sz) {
+  static const char hex[17] = "0123456789abcdef";
+  register const unsigned char *u = (unsigned char *) ptr;
+  register const unsigned char *eu =  u + sz;
+  for (; u != eu; ++u) {
+    register unsigned char uu = *u;
+    *(c++) = hex[(uu & 0xf0) >> 4];
+    *(c++) = hex[uu & 0xf];
+  }
+  return c;
+}
+
+/*
+   Unpack binary data from a string
+*/
+SWIGRUNTIME const char *
+SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
+  register unsigned char *u = (unsigned char *) ptr;
+  register const unsigned char *eu = u + sz;
+  for (; u != eu; ++u) {
+    register char d = *(c++);
+    register unsigned char uu;
+    if ((d >= '0') && (d <= '9'))
+      uu = ((d - '0') << 4);
+    else if ((d >= 'a') && (d <= 'f'))
+      uu = ((d - ('a'-10)) << 4);
+    else
+      return (char *) 0;
+    d = *(c++);
+    if ((d >= '0') && (d <= '9'))
+      uu |= (d - '0');
+    else if ((d >= 'a') && (d <= 'f'))
+      uu |= (d - ('a'-10));
+    else
+      return (char *) 0;
+    *u = uu;
+  }
+  return c;
+}
+
+/*
+   Pack 'void *' into a string buffer.
+*/
+SWIGRUNTIME char *
+SWIG_PackVoidPtr(char *buff, void *ptr, const char *name, size_t bsz) {
+  char *r = buff;
+  if ((2*sizeof(void *) + 2) > bsz) return 0;
+  *(r++) = '_';
+  r = SWIG_PackData(r,&ptr,sizeof(void *));
+  if (strlen(name) + 1 > (bsz - (r - buff))) return 0;
+  strcpy(r,name);
+  return buff;
+}
+
+SWIGRUNTIME const char *
+SWIG_UnpackVoidPtr(const char *c, void **ptr, const char *name) {
+  if (*c != '_') {
+    if (strcmp(c,"NULL") == 0) {
+      *ptr = (void *) 0;
+      return name;
+    } else {
+      return 0;
+    }
+  }
+  return SWIG_UnpackData(++c,ptr,sizeof(void *));
+}
+
+SWIGRUNTIME char *
+SWIG_PackDataName(char *buff, void *ptr, size_t sz, const char *name, size_t bsz) {
+  char *r = buff;
+  size_t lname = (name ? strlen(name) : 0);
+  if ((2*sz + 2 + lname) > bsz) return 0;
+  *(r++) = '_';
+  r = SWIG_PackData(r,ptr,sz);
+  if (lname) {
+    strncpy(r,name,lname+1);
+  } else {
+    *r = 0;
+  }
+  return buff;
+}
+
+SWIGRUNTIME const char *
+SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) {
+  if (*c != '_') {
+    if (strcmp(c,"NULL") == 0) {
+      memset(ptr,0,sz);
+      return name;
+    } else {
+      return 0;
+    }
+  }
+  return SWIG_UnpackData(++c,ptr,sz);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+/* -----------------------------------------------------------------------------
+ * phprun.swg
+ *
+ * PHP runtime library
+ * ----------------------------------------------------------------------------- */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "zend.h"
+#include "zend_API.h"
+#include "zend_exceptions.h"
+#include "php.h"
+#include "ext/standard/php_string.h"
+#include <stdlib.h> /* for abort(), used in generated code. */
+
+#ifdef ZEND_RAW_FENTRY
+/* ZEND_RAW_FENTRY was added somewhere between 5.2.0 and 5.2.3 */
+# define SWIG_ZEND_NAMED_FE(ZN, N, A) ZEND_RAW_FENTRY((char*)#ZN, N, A, 0)
+#else
+/* This causes warnings from GCC >= 4.2 (assigning a string literal to char*).
+ * But this seems to be unavoidable without directly assuming knowledge of
+ * the structure, which changed between PHP4 and PHP5. */
+# define SWIG_ZEND_NAMED_FE(ZN, N, A) ZEND_NAMED_FE(ZN, N, A)
+#endif
+
+#ifndef Z_SET_ISREF_P
+/* For PHP < 5.3 */
+# define Z_SET_ISREF_P(z) (z)->is_ref = 1
+#endif
+#ifndef Z_SET_REFCOUNT_P
+/* For PHP < 5.3 */
+# define Z_SET_REFCOUNT_P(z, rc) (z)->refcount = (rc)
+#endif
+
+#define SWIG_LONG_CONSTANT(N, V) zend_register_long_constant((char*)#N, sizeof(#N), V, CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC)
+#define SWIG_DOUBLE_CONSTANT(N, V) zend_register_double_constant((char*)#N, sizeof(#N), V, CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC)
+#define SWIG_STRING_CONSTANT(N, V) zend_register_stringl_constant((char*)#N, sizeof(#N), (char*)(V), strlen(V), CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC)
+#define SWIG_CHAR_CONSTANT(N, V) do {\
+    static char swig_char = (V);\
+    zend_register_stringl_constant((char*)#N, sizeof(#N), &swig_char, 1, CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC);\
+} while (0)
+
+/* These TSRMLS_ stuff should already be defined now, but with older php under
+   redhat are not... */
+#ifndef TSRMLS_D
+#define TSRMLS_D
+#endif
+#ifndef TSRMLS_DC
+#define TSRMLS_DC
+#endif
+#ifndef TSRMLS_C
+#define TSRMLS_C
+#endif
+#ifndef TSRMLS_CC
+#define TSRMLS_CC
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/* But in fact SWIG_ConvertPtr is the native interface for getting typed
+   pointer values out of zvals.  We need the TSRMLS_ macros for when we
+   make PHP type calls later as we handle php resources */
+#define SWIG_ConvertPtr(obj,pp,type,flags) SWIG_ZTS_ConvertPtr(obj,pp,type,flags TSRMLS_CC)
+
+
+#define SWIG_fail goto fail
+
+static const char *default_error_msg = "Unknown error occurred";
+static int default_error_code = E_ERROR;
+
+#define SWIG_PHP_Arg_Error_Msg(argnum,extramsg) "Error in argument " #argnum " "#extramsg
+
+#define SWIG_PHP_Error(code,msg) do { SWIG_ErrorCode() = code; SWIG_ErrorMsg() = msg; SWIG_fail; } while (0)
+
+#define SWIG_contract_assert(expr,msg) \
+  if (!(expr) ) { zend_printf("Contract Assert Failed %s\n",msg ); } else
+
+/* Standard SWIG API */
+#define SWIG_GetModule(clientdata) SWIG_Php_GetModule(clientdata)
+#define SWIG_SetModule(clientdata, pointer) SWIG_Php_SetModule(pointer)
+
+/* used to wrap returned objects in so we know whether they are newobject
+   and need freeing, or not */
+typedef struct {
+  void * ptr;
+  int newobject;
+} swig_object_wrapper;
+
+/* empty zend destructor for types without one */
+static ZEND_RSRC_DTOR_FUNC(SWIG_landfill) { (void)rsrc; }
+
+#define SWIG_SetPointerZval(a,b,c,d) SWIG_ZTS_SetPointerZval(a,b,c,d TSRMLS_CC)
+#define SWIG_as_voidptr(a) const_cast< void * >(static_cast< const void * >(a))
+
+static void
+SWIG_ZTS_SetPointerZval(zval *z, void *ptr, swig_type_info *type, int newobject TSRMLS_DC) {
+  /*
+   * First test for Null pointers.  Return those as PHP native NULL
+   */
+  if (!ptr ) {
+    ZVAL_NULL(z);
+    return;
+  }
+  if (type->clientdata) {
+    swig_object_wrapper *value;
+    if (! (*(int *)(type->clientdata)))
+      zend_error(E_ERROR, "Type: %s failed to register with zend",type->name);
+    value=(swig_object_wrapper *)emalloc(sizeof(swig_object_wrapper));
+    value->ptr=ptr;
+    value->newobject=(newobject & 1);
+    if ((newobject & 2) == 0) {
+      /* Just register the pointer as a resource. */
+      ZEND_REGISTER_RESOURCE(z, value, *(int *)(type->clientdata));
+    } else {
+      /*
+       * Wrap the resource in an object, the resource will be accessible
+       * via the "_cPtr" member. This is currently only used by
+       * directory typemaps.
+       */
+      zval *resource;
+      zend_class_entry **ce = NULL;
+      const char *type_name = type->name+3; /* +3 so: _p_Foo -> Foo */
+      size_t type_name_len;
+      int result;
+      const char * p;
+
+      /* Namespace__Foo -> Foo */
+      /* FIXME: ugly and goes wrong for classes with __ in their names. */
+      while ((p = strstr(type_name, "__")) != NULL) {
+        type_name = p + 2;
+      }
+      type_name_len = strlen(type_name);
+
+      MAKE_STD_ZVAL(resource);
+      ZEND_REGISTER_RESOURCE(resource, value, *(int *)(type->clientdata));
+      if (SWIG_PREFIX_LEN > 0) {
+        char * classname = (char*)emalloc(SWIG_PREFIX_LEN + type_name_len + 1);
+        strcpy(classname, SWIG_PREFIX);
+        strcpy(classname + SWIG_PREFIX_LEN, type_name);
+        result = zend_lookup_class(classname, SWIG_PREFIX_LEN + type_name_len, &ce TSRMLS_CC);
+        efree(classname);
+      } else {
+        result = zend_lookup_class((char *)type_name, type_name_len, &ce TSRMLS_CC);
+      }
+      if (result != SUCCESS) {
+        /* class does not exist */
+        object_init(z);
+      } else {
+        object_init_ex(z, *ce);
+      }
+      Z_SET_REFCOUNT_P(z, 1);
+      Z_SET_ISREF_P(z);
+      zend_hash_update(HASH_OF(z), (char*)"_cPtr", sizeof("_cPtr"), (void*)&resource, sizeof(zval), NULL);
+    }
+    return;
+  }
+  zend_error(E_ERROR, "Type: %s not registered with zend",type->name);
+}
+
+/* This pointer conversion routine takes the native pointer p (along with
+   its type name) and converts it by calling appropriate casting functions
+   according to ty.  The resultant pointer is returned, or NULL is returned
+   if the pointer can't be cast.
+
+   Sadly PHP has no API to find a type name from a type id, only from an
+   instance of a resource of the type id, so we have to pass type_name as well.
+
+   The two functions which might call this are:
+   SWIG_ZTS_ConvertResourcePtr which gets the type name from the resource
+   and the registered zend destructors for which we have one per type each
+   with the type name hard wired in. */
+static void *
+SWIG_ZTS_ConvertResourceData(void * p, const char *type_name, swig_type_info *ty TSRMLS_DC) {
+  swig_cast_info *tc;
+  void *result = 0;
+
+  if (!ty) {
+    /* They don't care about the target type, so just pass on the pointer! */
+    return p;
+  }
+
+  if (! type_name) {  
+    /* can't convert p to ptr type ty if we don't know what type p is */
+    return NULL;
+  }
+
+  /* convert and cast p from type_name to ptr as ty. */
+  tc = SWIG_TypeCheck(type_name, ty);
+  if (tc) {
+    int newmemory = 0;
+    result = SWIG_TypeCast(tc, p, &newmemory);
+    assert(!newmemory); /* newmemory handling not yet implemented */
+  }
+  return result;
+}
+
+/* This function returns a pointer of type ty by extracting the pointer
+   and type info from the resource in z.  z must be a resource.
+   If it fails, NULL is returned.
+   It uses SWIG_ZTS_ConvertResourceData to do the real work. */
+static void *
+SWIG_ZTS_ConvertResourcePtr(zval *z, swig_type_info *ty, int flags TSRMLS_DC) {
+  swig_object_wrapper *value;
+  void *p;
+  int type;
+  const char *type_name;
+
+  value = (swig_object_wrapper *) zend_list_find(z->value.lval, &type);
+  if (type==-1) return NULL;
+  if (flags & SWIG_POINTER_DISOWN) {
+    value->newobject = 0;
+  }
+  p = value->ptr;
+
+  type_name=zend_rsrc_list_get_rsrc_type(z->value.lval TSRMLS_CC);
+
+  return SWIG_ZTS_ConvertResourceData(p, type_name, ty TSRMLS_CC);
+}
+
+/* We allow passing of a RESOURCE pointing to the object or an OBJECT whose
+   _cPtr is a resource pointing to the object */
+static int
+SWIG_ZTS_ConvertPtr(zval *z, void **ptr, swig_type_info *ty, int flags TSRMLS_DC) {
+  if (z == NULL) {
+    *ptr = 0;
+    return 0;
+  }
+
+  switch (z->type) {
+    case IS_OBJECT: {
+      zval ** _cPtr;
+      if (zend_hash_find(HASH_OF(z),(char*)"_cPtr",sizeof("_cPtr"),(void**)&_cPtr)==SUCCESS) {
+	if ((*_cPtr)->type==IS_RESOURCE) {
+	  *ptr = SWIG_ZTS_ConvertResourcePtr(*_cPtr, ty, flags TSRMLS_CC);
+	  return (*ptr == NULL ? -1 : 0);
+	}
+      }
+      break;
+    }
+    case IS_RESOURCE:
+      *ptr = SWIG_ZTS_ConvertResourcePtr(z, ty, flags TSRMLS_CC);
+      return (*ptr == NULL ? -1 : 0);
+    case IS_NULL:
+      *ptr = 0;
+      return 0;
+  }
+
+  return -1;
+}
+
+static char const_name[] = "swig_runtime_data_type_pointer";
+static swig_module_info *SWIG_Php_GetModule(void *SWIGUNUSEDPARM(clientdata)) {
+  zval *pointer;
+  swig_module_info *ret = 0;
+  TSRMLS_FETCH();
+
+  MAKE_STD_ZVAL(pointer);
+
+  if (zend_get_constant(const_name, sizeof(const_name) - 1, pointer TSRMLS_CC)) {
+    if (pointer->type == IS_LONG) {
+      ret = (swig_module_info *) pointer->value.lval;
+    }
+  } 
+  FREE_ZVAL(pointer);
+  return ret; 
+}
+
+static void SWIG_Php_SetModule(swig_module_info *pointer) {
+  TSRMLS_FETCH();
+  REGISTER_MAIN_LONG_CONSTANT(const_name, (long) pointer, 0);
+}
+
+/*  Errors in SWIG */
+#define  SWIG_UnknownError    	   -1
+#define  SWIG_IOError        	   -2
+#define  SWIG_RuntimeError   	   -3
+#define  SWIG_IndexError     	   -4
+#define  SWIG_TypeError      	   -5
+#define  SWIG_DivisionByZero 	   -6
+#define  SWIG_OverflowError  	   -7
+#define  SWIG_SyntaxError    	   -8
+#define  SWIG_ValueError     	   -9
+#define  SWIG_SystemError    	   -10
+#define  SWIG_AttributeError 	   -11
+#define  SWIG_MemoryError    	   -12
+#define  SWIG_NullReferenceError   -13
+
+
+
+
+/* -------- TYPES TABLE (BEGIN) -------- */
+
+#define SWIGTYPE_int swig_types[0]
+#define SWIGTYPE_p_GDALMajorObjectShadow swig_types[1]
+#define SWIGTYPE_p_GIntBig swig_types[2]
+#define SWIGTYPE_p_GNMGenericNetworkShadow swig_types[3]
+#define SWIGTYPE_p_GNMGraphAlgorithmType swig_types[4]
+#define SWIGTYPE_p_GNMNetworkShadow swig_types[5]
+#define SWIGTYPE_p_OGRFeatureShadow swig_types[6]
+#define SWIGTYPE_p_OGRLayerShadow swig_types[7]
+#define SWIGTYPE_p_OGRwkbGeometryType swig_types[8]
+#define SWIGTYPE_p_OSRSpatialReferenceShadow swig_types[9]
+#define SWIGTYPE_p_char swig_types[10]
+#define SWIGTYPE_p_int swig_types[11]
+#define SWIGTYPE_p_p_OGRLayerShadow swig_types[12]
+#define SWIGTYPE_p_p_char swig_types[13]
+static swig_type_info *swig_types[15];
+static swig_module_info swig_module = {swig_types, 14, 0, 0, 0, 0};
+#define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)
+#define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)
+
+/* -------- TYPES TABLE (END) -------- */
+
+/* header section */
+ZEND_BEGIN_MODULE_GLOBALS(gnm)
+const char *error_msg;
+int error_code;
+ZEND_END_MODULE_GLOBALS(gnm)
+ZEND_DECLARE_MODULE_GLOBALS(gnm)
+#ifdef ZTS
+#define SWIG_ErrorMsg() TSRMG(gnm_globals_id, zend_gnm_globals *, error_msg )
+#define SWIG_ErrorCode() TSRMG(gnm_globals_id, zend_gnm_globals *, error_code )
+#else
+#define SWIG_ErrorMsg() (gnm_globals.error_msg)
+#define SWIG_ErrorCode() (gnm_globals.error_code)
+#endif
+
+#ifdef __GNUC__
+static void SWIG_FAIL() __attribute__ ((__noreturn__));
+#endif
+
+static void SWIG_FAIL() {
+    TSRMLS_FETCH();
+    zend_error(SWIG_ErrorCode(), "%s", SWIG_ErrorMsg());
+    abort();
+}
+
+static void gnm_init_globals(zend_gnm_globals *globals ) {
+  globals->error_msg = default_error_msg;
+  globals->error_code = default_error_code;
+}
+static void gnm_destroy_globals(zend_gnm_globals * globals) { (void)globals; }
+
+static void SWIG_ResetError() {
+  TSRMLS_FETCH();
+  SWIG_ErrorMsg() = default_error_msg;
+  SWIG_ErrorCode() = default_error_code;
+}
+
+ZEND_NAMED_FUNCTION(_wrap_swig_gnm_alter_newobject) {
+  zval **args[2];
+  swig_object_wrapper *value;
+  int type;
+  int thisown;
+
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 2 || zend_get_parameters_array_ex(2, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+
+  value = (swig_object_wrapper *) zend_list_find((*args[0])->value.lval, &type);
+  value->newobject = zval_is_true(*args[1]);
+
+  return;
+}
+ZEND_NAMED_FUNCTION(_wrap_swig_gnm_get_newobject) {
+  zval **args[1];
+  swig_object_wrapper *value;
+  int type;
+
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+
+  value = (swig_object_wrapper *) zend_list_find((*args[0])->value.lval, &type);
+  RETVAL_LONG(value->newobject);
+
+  return;
+}
+#define SWIG_name  "gnm"
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "php.h"
+#include "php_ini.h"
+#include "ext/standard/info.h"
+#include "php_gnm.h"
+#ifdef __cplusplus
+}
+#endif
+
+
+#include "zend_exceptions.h"
+#define SWIG_exception(code, msg) { zend_throw_exception(NULL, (char*)msg, code TSRMLS_CC); }
+
+
+#include <stdexcept>
+
+
+#include "gdal.h"
+#include "gnm_api.h"
+
+typedef void GDALMajorObjectShadow;
+typedef void GNMNetworkShadow;
+typedef void GNMGenericNetworkShadow;
+
+SWIGINTERN char const *GDALMajorObjectShadow_GetDescription(GDALMajorObjectShadow *self){
+    return GDALGetDescription( self );
+  }
+SWIGINTERN void GDALMajorObjectShadow_SetDescription(GDALMajorObjectShadow *self,char const *pszNewDesc){
+    GDALSetDescription( self, pszNewDesc );
+  }
+SWIGINTERN char **GDALMajorObjectShadow_GetMetadataDomainList(GDALMajorObjectShadow *self){
+    return GDALGetMetadataDomainList( self );
+  }
+SWIGINTERN char **GDALMajorObjectShadow_GetMetadata_Dict(GDALMajorObjectShadow *self,char const *pszDomain=""){
+    return GDALGetMetadata( self, pszDomain );
+  }
+SWIGINTERN char **GDALMajorObjectShadow_GetMetadata_List(GDALMajorObjectShadow *self,char const *pszDomain=""){
+    return GDALGetMetadata( self, pszDomain );
+  }
+SWIGINTERN CPLErr GDALMajorObjectShadow_SetMetadata__SWIG_0(GDALMajorObjectShadow *self,char **papszMetadata,char const *pszDomain=""){
+    return GDALSetMetadata( self, papszMetadata, pszDomain );
+  }
+SWIGINTERN CPLErr GDALMajorObjectShadow_SetMetadata__SWIG_1(GDALMajorObjectShadow *self,char *pszMetadataString,char const *pszDomain=""){
+    char *tmpList[2];
+    tmpList[0] = pszMetadataString;
+    tmpList[1] = 0;
+    return GDALSetMetadata( self, tmpList, pszDomain );
+  }
+SWIGINTERN char const *GDALMajorObjectShadow_GetMetadataItem(GDALMajorObjectShadow *self,char const *pszName,char const *pszDomain=""){
+    return GDALGetMetadataItem( self, pszName, pszDomain);
+  }
+SWIGINTERN CPLErr GDALMajorObjectShadow_SetMetadataItem(GDALMajorObjectShadow *self,char const *pszName,char const *pszValue,char const *pszDomain=""){
+    return GDALSetMetadataItem( self, pszName, pszValue, pszDomain);
+  }
+
+  GNMNetworkShadow* CastToNetwork(GDALMajorObjectShadow* base) {
+      return (GNMNetworkShadow*)dynamic_cast<GNMNetwork*>((GDALMajorObject*)base);
+  }
+
+
+  GNMGenericNetworkShadow* CastToGenericNetwork(GDALMajorObjectShadow* base) {
+      return (GNMGenericNetworkShadow*)dynamic_cast<GNMGenericNetwork*>((GDALMajorObject*)base);
+  }
+
+
+typedef char retStringAndCPLFree;
+
+SWIGINTERN void delete_GNMNetworkShadow(GNMNetworkShadow *self){
+            if ( GDALDereferenceDataset( self ) <= 0 ) {
+              GDALClose(self);
+            }
+        }
+SWIGINTERN void GNMNetworkShadow_ReleaseResultSet(GNMNetworkShadow *self,OGRLayerShadow *layer){
+            GDALDatasetReleaseResultSet(self, layer);
+        }
+SWIGINTERN int GNMNetworkShadow_GetVersion(GNMNetworkShadow *self){
+            return GNMGetVersion(self);
+        }
+SWIGINTERN char const *GNMNetworkShadow_GetName(GNMNetworkShadow *self){
+            return GNMGetName(self);
+        }
+SWIGINTERN OGRFeatureShadow *GNMNetworkShadow_GetFeatureByGlobalFID(GNMNetworkShadow *self,GIntBig GFID){
+            return GNMGetFeatureByGlobalFID(self, GFID);
+        }
+SWIGINTERN OGRLayerShadow *GNMNetworkShadow_GetPath(GNMNetworkShadow *self,GIntBig nStartFID,GIntBig nEndFID,GNMGraphAlgorithmType eAlgorithm,char **options=0){
+            return GNMGetPath(self, nStartFID, nEndFID, eAlgorithm, options);
+        }
+SWIGINTERN CPLErr GNMNetworkShadow_DisconnectAll(GNMNetworkShadow *self){
+            return GNMDisconnectAll( self );
+        }
+SWIGINTERN char const *GNMNetworkShadow_GetProjection(GNMNetworkShadow *self){
+            return GDALGetProjectionRef( self );
+        }
+SWIGINTERN char const *GNMNetworkShadow_GetProjectionRef(GNMNetworkShadow *self){
+            return GDALGetProjectionRef( self );
+        }
+SWIGINTERN char **GNMNetworkShadow_GetFileList(GNMNetworkShadow *self){
+            return GDALGetFileList( self );
+        }
+SWIGINTERN OGRLayerShadow *GNMNetworkShadow_CreateLayer(GNMNetworkShadow *self,char const *name,OSRSpatialReferenceShadow *srs=NULL,OGRwkbGeometryType geom_type=wkbUnknown,char **options=0){
+            OGRLayerShadow* layer = (OGRLayerShadow*) GDALDatasetCreateLayer( self,
+                                      name,
+                                      srs,
+                                      geom_type,
+                                      options);
+            return layer;
+        }
+SWIGINTERN OGRLayerShadow *GNMNetworkShadow_CopyLayer(GNMNetworkShadow *self,OGRLayerShadow *src_layer,char const *new_name,char **options=0){
+            OGRLayerShadow* layer = (OGRLayerShadow*) GDALDatasetCopyLayer( self,
+                                                      src_layer,
+                                                      new_name,
+                                                      options);
+            return layer;
+        }
+SWIGINTERN OGRErr GNMNetworkShadow_DeleteLayer(GNMNetworkShadow *self,int index){
+            return GDALDatasetDeleteLayer(self, index);
+        }
+
+static char *
+OGRErrMessages( int rc ) {
+  switch( rc ) {
+  case 0:
+    return "OGR Error 0: None";
+  case 1:
+    return "OGR Error 1: Not enough data";
+  case 2:
+    return "OGR Error 2: Unsupported geometry type";
+  case 3:
+    return "OGR Error 3: Unsupported operation";
+  case 4:
+    return "OGR Error 4: Corrupt data";
+  case 5:
+    return "OGR Error 5: General Error";
+  case 6:
+    return "OGR Error 6: Unsupported SRS";
+  default:
+    return "OGR Error: Unknown";
+  }
+}
+
+SWIGINTERN int GNMNetworkShadow_GetLayerCount(GNMNetworkShadow *self){
+            return GDALDatasetGetLayerCount(self);
+        }
+SWIGINTERN OGRLayerShadow *GNMNetworkShadow_GetLayerByIndex(GNMNetworkShadow *self,int index=0){
+        
+        OGRLayerShadow* layer = (OGRLayerShadow*) GDALDatasetGetLayer(self, 
+                                                                      index);
+            return layer;
+        }
+SWIGINTERN OGRLayerShadow *GNMNetworkShadow_GetLayerByName(GNMNetworkShadow *self,char const *layer_name){
+            OGRLayerShadow* layer = 
+                  (OGRLayerShadow*) GDALDatasetGetLayerByName(self, layer_name);
+            return layer;
+        }
+SWIGINTERN bool GNMNetworkShadow_TestCapability(GNMNetworkShadow *self,char const *cap){
+            return (GDALDatasetTestCapability(self, cap) > 0);
+        }
+SWIGINTERN OGRErr GNMNetworkShadow_StartTransaction(GNMNetworkShadow *self,int force=FALSE){
+            return GDALDatasetStartTransaction(self, force);
+        }
+SWIGINTERN OGRErr GNMNetworkShadow_CommitTransaction(GNMNetworkShadow *self){
+            return GDALDatasetCommitTransaction(self);
+        }
+SWIGINTERN OGRErr GNMNetworkShadow_RollbackTransaction(GNMNetworkShadow *self){
+            return GDALDatasetRollbackTransaction(self);
+        }
+SWIGINTERN void delete_GNMGenericNetworkShadow(GNMGenericNetworkShadow *self){
+            if ( GDALDereferenceDataset( self ) <= 0 ) {
+              GDALClose(self);
+            }
+        }
+SWIGINTERN CPLErr GNMGenericNetworkShadow_ConnectFeatures(GNMGenericNetworkShadow *self,GIntBig nSrcFID,GIntBig nTgtFID,GIntBig nConFID,double dfCost,double dfInvCost,GNMDirection eDir){
+            return GNMConnectFeatures(self, nSrcFID, nTgtFID,
+                                              nConFID, dfCost, dfInvCost, eDir);                        
+        }
+SWIGINTERN CPLErr GNMGenericNetworkShadow_DisconnectFeatures(GNMGenericNetworkShadow *self,GIntBig nSrcFID,GIntBig nTgtFID,GIntBig nConFID){
+            return GNMDisconnectFeatures(self, nSrcFID, nTgtFID,
+                                                           nConFID);                           
+        }
+SWIGINTERN CPLErr GNMGenericNetworkShadow_DisconnectFeaturesWithId(GNMGenericNetworkShadow *self,GIntBig nFID){
+            return GNMDisconnectFeaturesWithId(self, nFID);
+        }
+SWIGINTERN CPLErr GNMGenericNetworkShadow_ReconnectFeatures(GNMGenericNetworkShadow *self,GIntBig nSrcFID,GIntBig nTgtFID,GIntBig nConFID,double dfCost,double dfInvCost,GNMDirection eDir){
+            return GNMReconnectFeatures(self, nSrcFID, nTgtFID, nConFID, dfCost, dfInvCost, eDir);
+        }
+SWIGINTERN CPLErr GNMGenericNetworkShadow_CreateRule(GNMGenericNetworkShadow *self,char const *pszRuleStr){
+            return GNMCreateRule(self, pszRuleStr);
+        }
+SWIGINTERN CPLErr GNMGenericNetworkShadow_DeleteAllRules(GNMGenericNetworkShadow *self){
+            return GNMDeleteAllRules(self);
+        }
+SWIGINTERN CPLErr GNMGenericNetworkShadow_DeleteRule(GNMGenericNetworkShadow *self,char const *pszRuleStr){
+            return GNMDeleteRule(self, pszRuleStr);
+        }
+SWIGINTERN char **GNMGenericNetworkShadow_GetRules(GNMGenericNetworkShadow *self){
+            return GNMGetRules(self);
+        }
+SWIGINTERN CPLErr GNMGenericNetworkShadow_ConnectPointsByLines(GNMGenericNetworkShadow *self,char **papszLayerList,double dfTolerance,double dfCost,double dfInvCost,GNMDirection eDir){
+            return GNMConnectPointsByLines(self, papszLayerList, dfTolerance, dfCost, dfInvCost, eDir);
+        }
+SWIGINTERN CPLErr GNMGenericNetworkShadow_ChangeBlockState(GNMGenericNetworkShadow *self,GIntBig nFID,bool bIsBlock){
+            return GNMChangeBlockState(self, nFID, bIsBlock);
+        }
+SWIGINTERN CPLErr GNMGenericNetworkShadow_ChangeAllBlockState(GNMGenericNetworkShadow *self,bool bIsBlock=false){            
+            return GNMChangeAllBlockState(self, bIsBlock);
+        }
+
+/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */
+
+static void *_p_GNMGenericNetworkShadowTo_p_GNMNetworkShadow(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((GNMNetworkShadow *)  ((GNMGenericNetworkShadow *) x));
+}
+static void *_p_GNMNetworkShadowTo_p_GDALMajorObjectShadow(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((GDALMajorObjectShadow *)  ((GNMNetworkShadow *) x));
+}
+static void *_p_GNMGenericNetworkShadowTo_p_GDALMajorObjectShadow(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((GDALMajorObjectShadow *) (GNMNetworkShadow *) ((GNMGenericNetworkShadow *) x));
+}
+static swig_type_info _swigt__int = {"_int", "int", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_GDALMajorObjectShadow = {"_p_GDALMajorObjectShadow", "GDALMajorObjectShadow *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_GIntBig = {"_p_GIntBig", "GIntBig *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_GNMGenericNetworkShadow = {"_p_GNMGenericNetworkShadow", "GNMGenericNetworkShadow *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_GNMGraphAlgorithmType = {"_p_GNMGraphAlgorithmType", "enum GNMGraphAlgorithmType *|GNMGraphAlgorithmType *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_GNMNetworkShadow = {"_p_GNMNetworkShadow", "GNMNetworkShadow *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_OGRFeatureShadow = {"_p_OGRFeatureShadow", "OGRFeatureShadow *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_OGRLayerShadow = {"_p_OGRLayerShadow", "OGRLayerShadow *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_OGRwkbGeometryType = {"_p_OGRwkbGeometryType", "OGRwkbGeometryType *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_OSRSpatialReferenceShadow = {"_p_OSRSpatialReferenceShadow", "OSRSpatialReferenceShadow *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_char = {"_p_char", "char *|retStringAndCPLFree *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_int = {"_p_int", "CPLErr *|int *|GNMDirection *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_p_OGRLayerShadow = {"_p_p_OGRLayerShadow", "OGRLayerShadow **", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_p_char = {"_p_p_char", "char **", 0, 0, (void*)0, 0};
+
+static swig_type_info *swig_type_initial[] = {
+  &_swigt__int,
+  &_swigt__p_GDALMajorObjectShadow,
+  &_swigt__p_GIntBig,
+  &_swigt__p_GNMGenericNetworkShadow,
+  &_swigt__p_GNMGraphAlgorithmType,
+  &_swigt__p_GNMNetworkShadow,
+  &_swigt__p_OGRFeatureShadow,
+  &_swigt__p_OGRLayerShadow,
+  &_swigt__p_OGRwkbGeometryType,
+  &_swigt__p_OSRSpatialReferenceShadow,
+  &_swigt__p_char,
+  &_swigt__p_int,
+  &_swigt__p_p_OGRLayerShadow,
+  &_swigt__p_p_char,
+};
+
+static swig_cast_info _swigc__int[] = {  {&_swigt__int, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_GDALMajorObjectShadow[] = {  {&_swigt__p_GDALMajorObjectShadow, 0, 0, 0},  {&_swigt__p_GNMNetworkShadow, _p_GNMNetworkShadowTo_p_GDALMajorObjectShadow, 0, 0},  {&_swigt__p_GNMGenericNetworkShadow, _p_GNMGenericNetworkShadowTo_p_GDALMajorObjectShadow, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_GIntBig[] = {  {&_swigt__p_GIntBig, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_GNMGenericNetworkShadow[] = {  {&_swigt__p_GNMGenericNetworkShadow, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_GNMGraphAlgorithmType[] = {  {&_swigt__p_GNMGraphAlgorithmType, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_GNMNetworkShadow[] = {  {&_swigt__p_GNMNetworkShadow, 0, 0, 0},  {&_swigt__p_GNMGenericNetworkShadow, _p_GNMGenericNetworkShadowTo_p_GNMNetworkShadow, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_OGRFeatureShadow[] = {  {&_swigt__p_OGRFeatureShadow, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_OGRLayerShadow[] = {  {&_swigt__p_OGRLayerShadow, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_OGRwkbGeometryType[] = {  {&_swigt__p_OGRwkbGeometryType, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_OSRSpatialReferenceShadow[] = {  {&_swigt__p_OSRSpatialReferenceShadow, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_char[] = {  {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_int[] = {  {&_swigt__p_int, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_p_OGRLayerShadow[] = {  {&_swigt__p_p_OGRLayerShadow, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_p_char[] = {  {&_swigt__p_p_char, 0, 0, 0},{0, 0, 0, 0}};
+
+static swig_cast_info *swig_cast_initial[] = {
+  _swigc__int,
+  _swigc__p_GDALMajorObjectShadow,
+  _swigc__p_GIntBig,
+  _swigc__p_GNMGenericNetworkShadow,
+  _swigc__p_GNMGraphAlgorithmType,
+  _swigc__p_GNMNetworkShadow,
+  _swigc__p_OGRFeatureShadow,
+  _swigc__p_OGRLayerShadow,
+  _swigc__p_OGRwkbGeometryType,
+  _swigc__p_OSRSpatialReferenceShadow,
+  _swigc__p_char,
+  _swigc__p_int,
+  _swigc__p_p_OGRLayerShadow,
+  _swigc__p_p_char,
+};
+
+
+/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */
+
+/* end header section */
+/* vdecl subsection */
+static int le_swig__p_GIntBig=0; /* handle for _p_GIntBig */
+static int le_swig__p_GNMGraphAlgorithmType=0; /* handle for _p_GNMGraphAlgorithmType */
+static int le_swig__p_OGRwkbGeometryType=0; /* handle for _p_OGRwkbGeometryType */
+static int le_swig__p_char=0; /* handle for _p_char */
+static int le_swig__p_p_char=0; /* handle for _p_p_char */
+static int le_swig__p_OSRSpatialReferenceShadow=0; /* handle for _p_OSRSpatialReferenceShadow */
+static int le_swig__p_OGRFeatureShadow=0; /* handle for _p_OGRFeatureShadow */
+static int le_swig__p_GNMGenericNetworkShadow=0; /* handle for GenericNetwork */
+static int le_swig__p_GNMNetworkShadow=0; /* handle for Network */
+static int le_swig__int=0; /* handle for _int */
+static int le_swig__p_int=0; /* handle for _p_int */
+static int le_swig__p_p_OGRLayerShadow=0; /* handle for _p_p_OGRLayerShadow */
+static int le_swig__p_OGRLayerShadow=0; /* handle for _p_OGRLayerShadow */
+static int le_swig__p_GDALMajorObjectShadow=0; /* handle for MajorObject */
+/* end vdecl subsection */
+/* wrapper section */
+ZEND_NAMED_FUNCTION(_wrap_MajorObject_GetDescription) {
+  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
+  zval **args[1];
+  char *result = 0 ;
+  
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GDALMajorObjectShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of MajorObject_GetDescription. Expected SWIGTYPE_p_GDALMajorObjectShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  result = (char *)GDALMajorObjectShadow_GetDescription(arg1);
+  {
+    if(!result) {
+      ZVAL_NULL(return_value);
+    } else {
+      ZVAL_STRING(return_value, (char *)result, 1);
+    }
+  }
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_MajorObject_SetDescription) {
+  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  zval **args[2];
+  
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 2 || zend_get_parameters_array_ex(2, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GDALMajorObjectShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of MajorObject_SetDescription. Expected SWIGTYPE_p_GDALMajorObjectShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  
+  /*@SWIG:/usr/share/swig2.0/php/utils.i,62,CONVERT_STRING_IN@*/
+  if ((*args[1])->type==IS_NULL) {
+    arg2 = (char *) 0;
+  } else {
+    convert_to_string_ex(args[1]);
+    arg2 = (char *) Z_STRVAL_PP(args[1]);
+  }
+  /*@SWIG@*/;
+  
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  GDALMajorObjectShadow_SetDescription(arg1,(char const *)arg2);
+  
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_MajorObject_GetMetadataDomainList) {
+  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
+  zval **args[1];
+  char **result = 0 ;
+  
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GDALMajorObjectShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of MajorObject_GetMetadataDomainList. Expected SWIGTYPE_p_GDALMajorObjectShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  result = (char **)GDALMajorObjectShadow_GetMetadataDomainList(arg1);
+  
+  SWIG_SetPointerZval(return_value, (void *)result, SWIGTYPE_p_p_char, 0);
+  
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_MajorObject_GetMetadata_Dict) {
+  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
+  char *arg2 = (char *) "" ;
+  zval **args[2];
+  int arg_count;
+  char **result = 0 ;
+  
+  SWIG_ResetError();
+  arg_count = ZEND_NUM_ARGS();
+  if(arg_count<1 || arg_count>2 ||
+    zend_get_parameters_array_ex(arg_count,args)!=SUCCESS)
+  WRONG_PARAM_COUNT;
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GDALMajorObjectShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of MajorObject_GetMetadata_Dict. Expected SWIGTYPE_p_GDALMajorObjectShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  if(arg_count > 1) {
+    /*@SWIG:/usr/share/swig2.0/php/utils.i,62,CONVERT_STRING_IN@*/
+    if ((*args[1])->type==IS_NULL) {
+      arg2 = (char *) 0;
+    } else {
+      convert_to_string_ex(args[1]);
+      arg2 = (char *) Z_STRVAL_PP(args[1]);
+    }
+    /*@SWIG@*/;
+    
+  }
+  result = (char **)GDALMajorObjectShadow_GetMetadata_Dict(arg1,(char const *)arg2);
+  {
+    /* %typemap(out) char **dict */
+    char **stringarray = result;
+    array_init(return_value);
+    if ( stringarray != NULL ) {
+      while (*stringarray != NULL ) {
+        char const *valptr;
+        char *keyptr;
+        valptr = CPLParseNameValue( *stringarray, &keyptr );
+        if ( valptr != 0 ) {
+          add_assoc_string(return_value,keyptr,(char*)valptr,1);
+          CPLFree( keyptr );
+        }
+        stringarray++;
+      }
+    }
+  }
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_MajorObject_GetMetadata_List) {
+  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
+  char *arg2 = (char *) "" ;
+  zval **args[2];
+  int arg_count;
+  char **result = 0 ;
+  
+  SWIG_ResetError();
+  arg_count = ZEND_NUM_ARGS();
+  if(arg_count<1 || arg_count>2 ||
+    zend_get_parameters_array_ex(arg_count,args)!=SUCCESS)
+  WRONG_PARAM_COUNT;
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GDALMajorObjectShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of MajorObject_GetMetadata_List. Expected SWIGTYPE_p_GDALMajorObjectShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  if(arg_count > 1) {
+    /*@SWIG:/usr/share/swig2.0/php/utils.i,62,CONVERT_STRING_IN@*/
+    if ((*args[1])->type==IS_NULL) {
+      arg2 = (char *) 0;
+    } else {
+      convert_to_string_ex(args[1]);
+      arg2 = (char *) Z_STRVAL_PP(args[1]);
+    }
+    /*@SWIG@*/;
+    
+  }
+  result = (char **)GDALMajorObjectShadow_GetMetadata_List(arg1,(char const *)arg2);
+  {
+    /* %typemap(out) char ** -> ( string ) */
+    char **stringarray = result;
+    if ( stringarray == NULL ) {
+      RETVAL_NULL();
+    }
+    else {
+      int len = CSLCount( stringarray );
+      array_init(return_value);
+      for ( int i = 0; i < len; ++i, ++stringarray ) {
+        add_next_index_string( return_value, *stringarray, 1 );
+      }
+    }
+  }
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_MajorObject_SetMetadata__SWIG_0) {
+  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
+  char **arg2 = (char **) 0 ;
+  char *arg3 = (char *) "" ;
+  zval **args[3];
+  int arg_count;
+  CPLErr result;
+  
+  SWIG_ResetError();
+  arg_count = ZEND_NUM_ARGS();
+  if(arg_count<2 || arg_count>3 ||
+    zend_get_parameters_array_ex(arg_count,args)!=SUCCESS)
+  WRONG_PARAM_COUNT;
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GDALMajorObjectShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of MajorObject_SetMetadata. Expected SWIGTYPE_p_GDALMajorObjectShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  {
+    /* %typemap(in) char **dict */
+    zend_error(E_ERROR,"Typemap (in) char **dict not properly defined");
+    /*  if ( PySequence_Check( args[1] ) ) {
+        int size = PySequence_Size(args[1]);
+        for (int i = 0; i < size; i++) {
+          char *pszItem = NULL;
+          if ( ! PyArg_Parse( PySequence_GetItem(args[1],i), "s", &pszItem ) ) {
+            PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+            SWIG_fail;
+          }
+          arg2 = CSLAddString( arg2, pszItem );
+        }
+      }
+    */
+  }
+  if(arg_count > 2) {
+    /*@SWIG:/usr/share/swig2.0/php/utils.i,62,CONVERT_STRING_IN@*/
+    if ((*args[2])->type==IS_NULL) {
+      arg3 = (char *) 0;
+    } else {
+      convert_to_string_ex(args[2]);
+      arg3 = (char *) Z_STRVAL_PP(args[2]);
+    }
+    /*@SWIG@*/;
+    
+  }
+  result = (CPLErr)GDALMajorObjectShadow_SetMetadata__SWIG_0(arg1,arg2,(char const *)arg3);
+  {
+    ZVAL_LONG(return_value,result);
+  }
+  {
+    /* %typemap(freearg) char **dict */
+    CSLDestroy( arg2 );
+  }
+  return;
+fail:
+  {
+    /* %typemap(freearg) char **dict */
+    CSLDestroy( arg2 );
+  }
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_MajorObject_SetMetadata__SWIG_1) {
+  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  char *arg3 = (char *) "" ;
+  zval **args[3];
+  int arg_count;
+  CPLErr result;
+  
+  SWIG_ResetError();
+  arg_count = ZEND_NUM_ARGS();
+  if(arg_count<2 || arg_count>3 ||
+    zend_get_parameters_array_ex(arg_count,args)!=SUCCESS)
+  WRONG_PARAM_COUNT;
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GDALMajorObjectShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of MajorObject_SetMetadata. Expected SWIGTYPE_p_GDALMajorObjectShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  
+  /*@SWIG:/usr/share/swig2.0/php/utils.i,62,CONVERT_STRING_IN@*/
+  if ((*args[1])->type==IS_NULL) {
+    arg2 = (char *) 0;
+  } else {
+    convert_to_string_ex(args[1]);
+    arg2 = (char *) Z_STRVAL_PP(args[1]);
+  }
+  /*@SWIG@*/;
+  
+  if(arg_count > 2) {
+    /*@SWIG:/usr/share/swig2.0/php/utils.i,62,CONVERT_STRING_IN@*/
+    if ((*args[2])->type==IS_NULL) {
+      arg3 = (char *) 0;
+    } else {
+      convert_to_string_ex(args[2]);
+      arg3 = (char *) Z_STRVAL_PP(args[2]);
+    }
+    /*@SWIG@*/;
+    
+  }
+  result = (CPLErr)GDALMajorObjectShadow_SetMetadata__SWIG_1(arg1,arg2,(char const *)arg3);
+  {
+    ZVAL_LONG(return_value,result);
+  }
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_MajorObject_SetMetadata) {
+  int argc;
+  zval **argv[3];
+  
+  argc = ZEND_NUM_ARGS();
+  zend_get_parameters_array_ex(argc,argv);
+  if ((argc >= 2) && (argc <= 3)) {
+    int _v;
+    {
+      void *tmp;
+      _v = (SWIG_ConvertPtr(*argv[0], (void**)&tmp, SWIGTYPE_p_GDALMajorObjectShadow, 0) >= 0);
+    }
+    if (_v) {
+      {
+        /* %typecheck(SWIG_TYPECHECK_POINTER) (char **dict) */
+        _v = 0; //(PyMapping_Check(argv[1]) || PySequence_Check(argv[1]) ) ? 1 : 0;
+      }
+      if (_v) {
+        if (argc <= 2) {
+          _wrap_MajorObject_SetMetadata__SWIG_0(INTERNAL_FUNCTION_PARAM_PASSTHRU); return;
+        }
+        _v = (Z_TYPE_PP(argv[2]) == IS_STRING); 
+        if (_v) {
+          _wrap_MajorObject_SetMetadata__SWIG_0(INTERNAL_FUNCTION_PARAM_PASSTHRU); return;
+        }
+      }
+    }
+  }
+  if ((argc >= 2) && (argc <= 3)) {
+    int _v;
+    {
+      void *tmp;
+      _v = (SWIG_ConvertPtr(*argv[0], (void**)&tmp, SWIGTYPE_p_GDALMajorObjectShadow, 0) >= 0);
+    }
+    if (_v) {
+      _v = (Z_TYPE_PP(argv[1]) == IS_STRING); 
+      if (_v) {
+        if (argc <= 2) {
+          _wrap_MajorObject_SetMetadata__SWIG_1(INTERNAL_FUNCTION_PARAM_PASSTHRU); return;
+        }
+        _v = (Z_TYPE_PP(argv[2]) == IS_STRING); 
+        if (_v) {
+          _wrap_MajorObject_SetMetadata__SWIG_1(INTERNAL_FUNCTION_PARAM_PASSTHRU); return;
+        }
+      }
+    }
+  }
+  
+  SWIG_ErrorCode() = E_ERROR;
+  SWIG_ErrorMsg() = "No matching function for overloaded 'MajorObject_SetMetadata'";
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_MajorObject_GetMetadataItem) {
+  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  char *arg3 = (char *) "" ;
+  zval **args[3];
+  int arg_count;
+  char *result = 0 ;
+  
+  SWIG_ResetError();
+  arg_count = ZEND_NUM_ARGS();
+  if(arg_count<2 || arg_count>3 ||
+    zend_get_parameters_array_ex(arg_count,args)!=SUCCESS)
+  WRONG_PARAM_COUNT;
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GDALMajorObjectShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of MajorObject_GetMetadataItem. Expected SWIGTYPE_p_GDALMajorObjectShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  
+  /*@SWIG:/usr/share/swig2.0/php/utils.i,62,CONVERT_STRING_IN@*/
+  if ((*args[1])->type==IS_NULL) {
+    arg2 = (char *) 0;
+  } else {
+    convert_to_string_ex(args[1]);
+    arg2 = (char *) Z_STRVAL_PP(args[1]);
+  }
+  /*@SWIG@*/;
+  
+  if(arg_count > 2) {
+    /*@SWIG:/usr/share/swig2.0/php/utils.i,62,CONVERT_STRING_IN@*/
+    if ((*args[2])->type==IS_NULL) {
+      arg3 = (char *) 0;
+    } else {
+      convert_to_string_ex(args[2]);
+      arg3 = (char *) Z_STRVAL_PP(args[2]);
+    }
+    /*@SWIG@*/;
+    
+  }
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  result = (char *)GDALMajorObjectShadow_GetMetadataItem(arg1,(char const *)arg2,(char const *)arg3);
+  {
+    if(!result) {
+      ZVAL_NULL(return_value);
+    } else {
+      ZVAL_STRING(return_value, (char *)result, 1);
+    }
+  }
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_MajorObject_SetMetadataItem) {
+  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  char *arg3 = (char *) 0 ;
+  char *arg4 = (char *) "" ;
+  zval **args[4];
+  int arg_count;
+  CPLErr result;
+  
+  SWIG_ResetError();
+  arg_count = ZEND_NUM_ARGS();
+  if(arg_count<3 || arg_count>4 ||
+    zend_get_parameters_array_ex(arg_count,args)!=SUCCESS)
+  WRONG_PARAM_COUNT;
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GDALMajorObjectShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of MajorObject_SetMetadataItem. Expected SWIGTYPE_p_GDALMajorObjectShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  
+  /*@SWIG:/usr/share/swig2.0/php/utils.i,62,CONVERT_STRING_IN@*/
+  if ((*args[1])->type==IS_NULL) {
+    arg2 = (char *) 0;
+  } else {
+    convert_to_string_ex(args[1]);
+    arg2 = (char *) Z_STRVAL_PP(args[1]);
+  }
+  /*@SWIG@*/;
+  
+  
+  /*@SWIG:/usr/share/swig2.0/php/utils.i,62,CONVERT_STRING_IN@*/
+  if ((*args[2])->type==IS_NULL) {
+    arg3 = (char *) 0;
+  } else {
+    convert_to_string_ex(args[2]);
+    arg3 = (char *) Z_STRVAL_PP(args[2]);
+  }
+  /*@SWIG@*/;
+  
+  if(arg_count > 3) {
+    /*@SWIG:/usr/share/swig2.0/php/utils.i,62,CONVERT_STRING_IN@*/
+    if ((*args[3])->type==IS_NULL) {
+      arg4 = (char *) 0;
+    } else {
+      convert_to_string_ex(args[3]);
+      arg4 = (char *) Z_STRVAL_PP(args[3]);
+    }
+    /*@SWIG@*/;
+    
+  }
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  result = (CPLErr)GDALMajorObjectShadow_SetMetadataItem(arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4);
+  {
+    ZVAL_LONG(return_value,result);
+  }
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_CastToNetwork) {
+  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
+  zval **args[1];
+  GNMNetworkShadow *result = 0 ;
+  
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GDALMajorObjectShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of CastToNetwork. Expected SWIGTYPE_p_GDALMajorObjectShadow");
+    }
+  }
+  result = (GNMNetworkShadow *)CastToNetwork(arg1);
+  
+  SWIG_SetPointerZval(return_value, (void *)result, SWIGTYPE_p_GNMNetworkShadow, 0);
+  
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_CastToGenericNetwork) {
+  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
+  zval **args[1];
+  GNMGenericNetworkShadow *result = 0 ;
+  
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GDALMajorObjectShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of CastToGenericNetwork. Expected SWIGTYPE_p_GDALMajorObjectShadow");
+    }
+  }
+  result = (GNMGenericNetworkShadow *)CastToGenericNetwork(arg1);
+  
+  SWIG_SetPointerZval(return_value, (void *)result, SWIGTYPE_p_GNMGenericNetworkShadow, 0);
+  
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+/* This function is designed to be called by the zend list destructors */
+/* to typecast and do the actual destruction */
+static void __wrap_delete_Network(zend_rsrc_list_entry *rsrc, const char *type_name TSRMLS_DC) {
+  swig_object_wrapper *value=(swig_object_wrapper *) rsrc->ptr ;
+  void *ptr=value->ptr ;
+  int newobject=value->newobject ;
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  
+  efree(value);
+  if (! newobject) return; /* can't delete it! */
+  arg1 = (GNMNetworkShadow *)SWIG_ZTS_ConvertResourceData(ptr,type_name,SWIGTYPE_p_GNMNetworkShadow TSRMLS_CC);
+  if (! arg1) zend_error(E_ERROR, "GNMNetworkShadow resource already free'd");
+  delete_GNMNetworkShadow(arg1);
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_Network_ReleaseResultSet) {
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+  zval **args[2];
+  
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 2 || zend_get_parameters_array_ex(2, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GNMNetworkShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of Network_ReleaseResultSet. Expected SWIGTYPE_p_GNMNetworkShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  {
+    if(SWIG_ConvertPtr(*args[1], (void **) &arg2, SWIGTYPE_p_OGRLayerShadow, SWIG_POINTER_DISOWN ) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 2 of Network_ReleaseResultSet. Expected SWIGTYPE_p_p_OGRLayerShadow");
+    }
+  }
+  GNMNetworkShadow_ReleaseResultSet(arg1,arg2);
+  
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_Network_GetVersion) {
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  zval **args[1];
+  int result;
+  
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GNMNetworkShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of Network_GetVersion. Expected SWIGTYPE_p_GNMNetworkShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  result = (int)GNMNetworkShadow_GetVersion(arg1);
+  {
+    ZVAL_LONG(return_value,result);
+  }
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_Network_GetName) {
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  zval **args[1];
+  char *result = 0 ;
+  
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GNMNetworkShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of Network_GetName. Expected SWIGTYPE_p_GNMNetworkShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  result = (char *)GNMNetworkShadow_GetName(arg1);
+  {
+    if(!result) {
+      ZVAL_NULL(return_value);
+    } else {
+      ZVAL_STRING(return_value, (char *)result, 1);
+    }
+  }
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_Network_GetFeatureByGlobalFID) {
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  GIntBig arg2 ;
+  GIntBig *tmp2 ;
+  zval **args[2];
+  OGRFeatureShadow *result = 0 ;
+  
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 2 || zend_get_parameters_array_ex(2, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GNMNetworkShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of Network_GetFeatureByGlobalFID. Expected SWIGTYPE_p_GNMNetworkShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  {
+    if(SWIG_ConvertPtr(*args[1], (void **) &tmp2, SWIGTYPE_p_GIntBig, 0) < 0 || tmp2 == NULL) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 2 of Network_GetFeatureByGlobalFID. Expected SWIGTYPE_p_GIntBig");
+    }
+    arg2 = *tmp2;
+  }
+  result = (OGRFeatureShadow *)GNMNetworkShadow_GetFeatureByGlobalFID(arg1,arg2);
+  
+  SWIG_SetPointerZval(return_value, (void *)result, SWIGTYPE_p_OGRFeatureShadow, 1);
+  
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_Network_GetPath) {
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  GIntBig arg2 ;
+  GIntBig arg3 ;
+  GNMGraphAlgorithmType arg4 ;
+  char **arg5 = (char **) 0 ;
+  GIntBig *tmp2 ;
+  GIntBig *tmp3 ;
+  zval **args[5];
+  int arg_count;
+  OGRLayerShadow *result = 0 ;
+  
+  SWIG_ResetError();
+  arg_count = ZEND_NUM_ARGS();
+  if(arg_count<4 || arg_count>5 ||
+    zend_get_parameters_array_ex(arg_count,args)!=SUCCESS)
+  WRONG_PARAM_COUNT;
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GNMNetworkShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of Network_GetPath. Expected SWIGTYPE_p_GNMNetworkShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  {
+    if(SWIG_ConvertPtr(*args[1], (void **) &tmp2, SWIGTYPE_p_GIntBig, 0) < 0 || tmp2 == NULL) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 2 of Network_GetPath. Expected SWIGTYPE_p_GIntBig");
+    }
+    arg2 = *tmp2;
+  }
+  {
+    if(SWIG_ConvertPtr(*args[2], (void **) &tmp3, SWIGTYPE_p_GIntBig, 0) < 0 || tmp3 == NULL) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 3 of Network_GetPath. Expected SWIGTYPE_p_GIntBig");
+    }
+    arg3 = *tmp3;
+  }
+  
+  /*@SWIG:/usr/share/swig2.0/php/utils.i,7,CONVERT_INT_IN@*/
+  convert_to_long_ex(args[3]);
+  arg4 = (GNMGraphAlgorithmType) Z_LVAL_PP(args[3]);
+  /*@SWIG@*/;
+  
+  if(arg_count > 4) {
+    {
+      /* %typemap(in) char **options */
+      zend_error(E_ERROR,"Typemap (in) char **options not properly defined");
+      //  int size = PySequence_Size(args[4]);
+      //  for (int i = 0; i < size; i++) {
+      //    char *pszItem = NULL;
+      //    if ( ! PyArg_Parse( PySequence_GetItem(args[4],i), "s", &pszItem ) ) {
+      //      PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+      //      SWIG_fail;
+      //    }
+      //    arg5 = CSLAddString( arg5, pszItem );
+      //  }
+    }
+  }
+  result = (OGRLayerShadow *)GNMNetworkShadow_GetPath(arg1,arg2,arg3,arg4,arg5);
+  
+  SWIG_SetPointerZval(return_value, (void *)result, SWIGTYPE_p_OGRLayerShadow, 1);
+  
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg5 );
+  }
+  return;
+fail:
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg5 );
+  }
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_Network_DisconnectAll) {
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  zval **args[1];
+  CPLErr result;
+  
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GNMNetworkShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of Network_DisconnectAll. Expected SWIGTYPE_p_GNMNetworkShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  result = (CPLErr)GNMNetworkShadow_DisconnectAll(arg1);
+  {
+    ZVAL_LONG(return_value,result);
+  }
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_Network_GetProjection) {
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  zval **args[1];
+  char *result = 0 ;
+  
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GNMNetworkShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of Network_GetProjection. Expected SWIGTYPE_p_GNMNetworkShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  result = (char *)GNMNetworkShadow_GetProjection(arg1);
+  {
+    if(!result) {
+      ZVAL_NULL(return_value);
+    } else {
+      ZVAL_STRING(return_value, (char *)result, 1);
+    }
+  }
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_Network_GetProjectionRef) {
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  zval **args[1];
+  char *result = 0 ;
+  
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GNMNetworkShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of Network_GetProjectionRef. Expected SWIGTYPE_p_GNMNetworkShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  result = (char *)GNMNetworkShadow_GetProjectionRef(arg1);
+  {
+    if(!result) {
+      ZVAL_NULL(return_value);
+    } else {
+      ZVAL_STRING(return_value, (char *)result, 1);
+    }
+  }
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_Network_GetFileList) {
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  zval **args[1];
+  char **result = 0 ;
+  
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GNMNetworkShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of Network_GetFileList. Expected SWIGTYPE_p_GNMNetworkShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  result = (char **)GNMNetworkShadow_GetFileList(arg1);
+  
+  SWIG_SetPointerZval(return_value, (void *)result, SWIGTYPE_p_p_char, 0);
+  
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_Network_CreateLayer) {
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  OSRSpatialReferenceShadow *arg3 = (OSRSpatialReferenceShadow *) NULL ;
+  OGRwkbGeometryType arg4 = (OGRwkbGeometryType) wkbUnknown ;
+  char **arg5 = (char **) 0 ;
+  OGRwkbGeometryType *tmp4 ;
+  zval **args[5];
+  int arg_count;
+  OGRLayerShadow *result = 0 ;
+  
+  SWIG_ResetError();
+  arg_count = ZEND_NUM_ARGS();
+  if(arg_count<2 || arg_count>5 ||
+    zend_get_parameters_array_ex(arg_count,args)!=SUCCESS)
+  WRONG_PARAM_COUNT;
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GNMNetworkShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of Network_CreateLayer. Expected SWIGTYPE_p_GNMNetworkShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  
+  /*@SWIG:/usr/share/swig2.0/php/utils.i,62,CONVERT_STRING_IN@*/
+  if ((*args[1])->type==IS_NULL) {
+    arg2 = (char *) 0;
+  } else {
+    convert_to_string_ex(args[1]);
+    arg2 = (char *) Z_STRVAL_PP(args[1]);
+  }
+  /*@SWIG@*/;
+  
+  if(arg_count > 2) {
+    {
+      if(SWIG_ConvertPtr(*args[2], (void **) &arg3, SWIGTYPE_p_OSRSpatialReferenceShadow, 0) < 0) {
+        SWIG_PHP_Error(E_ERROR, "Type error in argument 3 of Network_CreateLayer. Expected SWIGTYPE_p_OSRSpatialReferenceShadow");
+      }
+    }
+  }
+  if(arg_count > 3) {
+    {
+      if(SWIG_ConvertPtr(*args[3], (void **) &tmp4, SWIGTYPE_p_OGRwkbGeometryType, 0) < 0 || tmp4 == NULL) {
+        SWIG_PHP_Error(E_ERROR, "Type error in argument 4 of Network_CreateLayer. Expected SWIGTYPE_p_OGRwkbGeometryType");
+      }
+      arg4 = *tmp4;
+    }
+  }
+  if(arg_count > 4) {
+    {
+      /* %typemap(in) char **options */
+      zend_error(E_ERROR,"Typemap (in) char **options not properly defined");
+      //  int size = PySequence_Size(args[4]);
+      //  for (int i = 0; i < size; i++) {
+      //    char *pszItem = NULL;
+      //    if ( ! PyArg_Parse( PySequence_GetItem(args[4],i), "s", &pszItem ) ) {
+      //      PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+      //      SWIG_fail;
+      //    }
+      //    arg5 = CSLAddString( arg5, pszItem );
+      //  }
+    }
+  }
+  result = (OGRLayerShadow *)GNMNetworkShadow_CreateLayer(arg1,(char const *)arg2,arg3,arg4,arg5);
+  
+  SWIG_SetPointerZval(return_value, (void *)result, SWIGTYPE_p_OGRLayerShadow, 0);
+  
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg5 );
+  }
+  return;
+fail:
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg5 );
+  }
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_Network_CopyLayer) {
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+  char *arg3 = (char *) 0 ;
+  char **arg4 = (char **) 0 ;
+  zval **args[4];
+  int arg_count;
+  OGRLayerShadow *result = 0 ;
+  
+  SWIG_ResetError();
+  arg_count = ZEND_NUM_ARGS();
+  if(arg_count<3 || arg_count>4 ||
+    zend_get_parameters_array_ex(arg_count,args)!=SUCCESS)
+  WRONG_PARAM_COUNT;
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GNMNetworkShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of Network_CopyLayer. Expected SWIGTYPE_p_GNMNetworkShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  {
+    if(SWIG_ConvertPtr(*args[1], (void **) &arg2, SWIGTYPE_p_OGRLayerShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 2 of Network_CopyLayer. Expected SWIGTYPE_p_OGRLayerShadow");
+    }
+  }
+  
+  /*@SWIG:/usr/share/swig2.0/php/utils.i,62,CONVERT_STRING_IN@*/
+  if ((*args[2])->type==IS_NULL) {
+    arg3 = (char *) 0;
+  } else {
+    convert_to_string_ex(args[2]);
+    arg3 = (char *) Z_STRVAL_PP(args[2]);
+  }
+  /*@SWIG@*/;
+  
+  if(arg_count > 3) {
+    {
+      /* %typemap(in) char **options */
+      zend_error(E_ERROR,"Typemap (in) char **options not properly defined");
+      //  int size = PySequence_Size(args[3]);
+      //  for (int i = 0; i < size; i++) {
+      //    char *pszItem = NULL;
+      //    if ( ! PyArg_Parse( PySequence_GetItem(args[3],i), "s", &pszItem ) ) {
+      //      PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+      //      SWIG_fail;
+      //    }
+      //    arg4 = CSLAddString( arg4, pszItem );
+      //  }
+    }
+  }
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  result = (OGRLayerShadow *)GNMNetworkShadow_CopyLayer(arg1,arg2,(char const *)arg3,arg4);
+  
+  SWIG_SetPointerZval(return_value, (void *)result, SWIGTYPE_p_OGRLayerShadow, 0);
+  
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg4 );
+  }
+  return;
+fail:
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg4 );
+  }
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_Network_DeleteLayer) {
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  int arg2 ;
+  zval **args[2];
+  OGRErr result;
+  
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 2 || zend_get_parameters_array_ex(2, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GNMNetworkShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of Network_DeleteLayer. Expected SWIGTYPE_p_GNMNetworkShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  
+  /*@SWIG:/usr/share/swig2.0/php/utils.i,7,CONVERT_INT_IN@*/
+  convert_to_long_ex(args[1]);
+  arg2 = (int) Z_LVAL_PP(args[1]);
+  /*@SWIG@*/;
+  
+  result = GNMNetworkShadow_DeleteLayer(arg1,arg2);
+  {
+    /* %typemap(out) OGRErr */
+    if (result != 0 ) {
+      SWIG_PHP_Error(E_ERROR,OGRErrMessages(result));
+    }
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    RETVAL_LONG(0);
+  }
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_Network_GetLayerCount) {
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  zval **args[1];
+  int result;
+  
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GNMNetworkShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of Network_GetLayerCount. Expected SWIGTYPE_p_GNMNetworkShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  result = (int)GNMNetworkShadow_GetLayerCount(arg1);
+  {
+    ZVAL_LONG(return_value,result);
+  }
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_Network_GetLayerByIndex) {
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  int arg2 = (int) 0 ;
+  zval **args[2];
+  int arg_count;
+  OGRLayerShadow *result = 0 ;
+  
+  SWIG_ResetError();
+  arg_count = ZEND_NUM_ARGS();
+  if(arg_count<1 || arg_count>2 ||
+    zend_get_parameters_array_ex(arg_count,args)!=SUCCESS)
+  WRONG_PARAM_COUNT;
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GNMNetworkShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of Network_GetLayerByIndex. Expected SWIGTYPE_p_GNMNetworkShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  if(arg_count > 1) {
+    /*@SWIG:/usr/share/swig2.0/php/utils.i,7,CONVERT_INT_IN@*/
+    convert_to_long_ex(args[1]);
+    arg2 = (int) Z_LVAL_PP(args[1]);
+    /*@SWIG@*/;
+    
+  }
+  result = (OGRLayerShadow *)GNMNetworkShadow_GetLayerByIndex(arg1,arg2);
+  
+  SWIG_SetPointerZval(return_value, (void *)result, SWIGTYPE_p_OGRLayerShadow, 0);
+  
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_Network_GetLayerByName) {
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  zval **args[2];
+  OGRLayerShadow *result = 0 ;
+  
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 2 || zend_get_parameters_array_ex(2, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GNMNetworkShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of Network_GetLayerByName. Expected SWIGTYPE_p_GNMNetworkShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  
+  /*@SWIG:/usr/share/swig2.0/php/utils.i,62,CONVERT_STRING_IN@*/
+  if ((*args[1])->type==IS_NULL) {
+    arg2 = (char *) 0;
+  } else {
+    convert_to_string_ex(args[1]);
+    arg2 = (char *) Z_STRVAL_PP(args[1]);
+  }
+  /*@SWIG@*/;
+  
+  result = (OGRLayerShadow *)GNMNetworkShadow_GetLayerByName(arg1,(char const *)arg2);
+  
+  SWIG_SetPointerZval(return_value, (void *)result, SWIGTYPE_p_OGRLayerShadow, 0);
+  
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_Network_TestCapability) {
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  zval **args[2];
+  bool result;
+  
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 2 || zend_get_parameters_array_ex(2, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GNMNetworkShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of Network_TestCapability. Expected SWIGTYPE_p_GNMNetworkShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  
+  /*@SWIG:/usr/share/swig2.0/php/utils.i,62,CONVERT_STRING_IN@*/
+  if ((*args[1])->type==IS_NULL) {
+    arg2 = (char *) 0;
+  } else {
+    convert_to_string_ex(args[1]);
+    arg2 = (char *) Z_STRVAL_PP(args[1]);
+  }
+  /*@SWIG@*/;
+  
+  result = (bool)GNMNetworkShadow_TestCapability(arg1,(char const *)arg2);
+  {
+    ZVAL_BOOL(return_value,(result)?1:0);
+  }
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_Network_StartTransaction) {
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  int arg2 = (int) FALSE ;
+  zval **args[2];
+  int arg_count;
+  OGRErr result;
+  
+  SWIG_ResetError();
+  arg_count = ZEND_NUM_ARGS();
+  if(arg_count<1 || arg_count>2 ||
+    zend_get_parameters_array_ex(arg_count,args)!=SUCCESS)
+  WRONG_PARAM_COUNT;
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GNMNetworkShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of Network_StartTransaction. Expected SWIGTYPE_p_GNMNetworkShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  if(arg_count > 1) {
+    /*@SWIG:/usr/share/swig2.0/php/utils.i,7,CONVERT_INT_IN@*/
+    convert_to_long_ex(args[1]);
+    arg2 = (int) Z_LVAL_PP(args[1]);
+    /*@SWIG@*/;
+    
+  }
+  result = GNMNetworkShadow_StartTransaction(arg1,arg2);
+  {
+    /* %typemap(out) OGRErr */
+    if (result != 0 ) {
+      SWIG_PHP_Error(E_ERROR,OGRErrMessages(result));
+    }
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    RETVAL_LONG(0);
+  }
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_Network_CommitTransaction) {
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  zval **args[1];
+  OGRErr result;
+  
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GNMNetworkShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of Network_CommitTransaction. Expected SWIGTYPE_p_GNMNetworkShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  result = GNMNetworkShadow_CommitTransaction(arg1);
+  {
+    /* %typemap(out) OGRErr */
+    if (result != 0 ) {
+      SWIG_PHP_Error(E_ERROR,OGRErrMessages(result));
+    }
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    RETVAL_LONG(0);
+  }
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_Network_RollbackTransaction) {
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  zval **args[1];
+  OGRErr result;
+  
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GNMNetworkShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of Network_RollbackTransaction. Expected SWIGTYPE_p_GNMNetworkShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  result = GNMNetworkShadow_RollbackTransaction(arg1);
+  {
+    /* %typemap(out) OGRErr */
+    if (result != 0 ) {
+      SWIG_PHP_Error(E_ERROR,OGRErrMessages(result));
+    }
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    RETVAL_LONG(0);
+  }
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+/* This function is designed to be called by the zend list destructors */
+/* to typecast and do the actual destruction */
+static void __wrap_delete_GenericNetwork(zend_rsrc_list_entry *rsrc, const char *type_name TSRMLS_DC) {
+  swig_object_wrapper *value=(swig_object_wrapper *) rsrc->ptr ;
+  void *ptr=value->ptr ;
+  int newobject=value->newobject ;
+  GNMGenericNetworkShadow *arg1 = (GNMGenericNetworkShadow *) 0 ;
+  
+  efree(value);
+  if (! newobject) return; /* can't delete it! */
+  arg1 = (GNMGenericNetworkShadow *)SWIG_ZTS_ConvertResourceData(ptr,type_name,SWIGTYPE_p_GNMGenericNetworkShadow TSRMLS_CC);
+  if (! arg1) zend_error(E_ERROR, "GNMGenericNetworkShadow resource already free'd");
+  delete_GNMGenericNetworkShadow(arg1);
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_GenericNetwork_ConnectFeatures) {
+  GNMGenericNetworkShadow *arg1 = (GNMGenericNetworkShadow *) 0 ;
+  GIntBig arg2 ;
+  GIntBig arg3 ;
+  GIntBig arg4 ;
+  double arg5 ;
+  double arg6 ;
+  GNMDirection arg7 ;
+  GIntBig *tmp2 ;
+  GIntBig *tmp3 ;
+  GIntBig *tmp4 ;
+  zval **args[7];
+  CPLErr result;
+  
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 7 || zend_get_parameters_array_ex(7, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GNMGenericNetworkShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of GenericNetwork_ConnectFeatures. Expected SWIGTYPE_p_GNMGenericNetworkShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  {
+    if(SWIG_ConvertPtr(*args[1], (void **) &tmp2, SWIGTYPE_p_GIntBig, 0) < 0 || tmp2 == NULL) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 2 of GenericNetwork_ConnectFeatures. Expected SWIGTYPE_p_GIntBig");
+    }
+    arg2 = *tmp2;
+  }
+  {
+    if(SWIG_ConvertPtr(*args[2], (void **) &tmp3, SWIGTYPE_p_GIntBig, 0) < 0 || tmp3 == NULL) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 3 of GenericNetwork_ConnectFeatures. Expected SWIGTYPE_p_GIntBig");
+    }
+    arg3 = *tmp3;
+  }
+  {
+    if(SWIG_ConvertPtr(*args[3], (void **) &tmp4, SWIGTYPE_p_GIntBig, 0) < 0 || tmp4 == NULL) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 4 of GenericNetwork_ConnectFeatures. Expected SWIGTYPE_p_GIntBig");
+    }
+    arg4 = *tmp4;
+  }
+  
+  /*@SWIG:/usr/share/swig2.0/php/utils.i,52,CONVERT_FLOAT_IN@*/
+  convert_to_double_ex(args[4]);
+  arg5 = (double) Z_DVAL_PP(args[4]);
+  /*@SWIG@*/;
+  
+  
+  /*@SWIG:/usr/share/swig2.0/php/utils.i,52,CONVERT_FLOAT_IN@*/
+  convert_to_double_ex(args[5]);
+  arg6 = (double) Z_DVAL_PP(args[5]);
+  /*@SWIG@*/;
+  
+  
+  /*@SWIG:/usr/share/swig2.0/php/utils.i,7,CONVERT_INT_IN@*/
+  convert_to_long_ex(args[6]);
+  arg7 = (GNMDirection) Z_LVAL_PP(args[6]);
+  /*@SWIG@*/;
+  
+  result = (CPLErr)GNMGenericNetworkShadow_ConnectFeatures(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+  {
+    ZVAL_LONG(return_value,result);
+  }
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_GenericNetwork_DisconnectFeatures) {
+  GNMGenericNetworkShadow *arg1 = (GNMGenericNetworkShadow *) 0 ;
+  GIntBig arg2 ;
+  GIntBig arg3 ;
+  GIntBig arg4 ;
+  GIntBig *tmp2 ;
+  GIntBig *tmp3 ;
+  GIntBig *tmp4 ;
+  zval **args[4];
+  CPLErr result;
+  
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 4 || zend_get_parameters_array_ex(4, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GNMGenericNetworkShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of GenericNetwork_DisconnectFeatures. Expected SWIGTYPE_p_GNMGenericNetworkShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  {
+    if(SWIG_ConvertPtr(*args[1], (void **) &tmp2, SWIGTYPE_p_GIntBig, 0) < 0 || tmp2 == NULL) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 2 of GenericNetwork_DisconnectFeatures. Expected SWIGTYPE_p_GIntBig");
+    }
+    arg2 = *tmp2;
+  }
+  {
+    if(SWIG_ConvertPtr(*args[2], (void **) &tmp3, SWIGTYPE_p_GIntBig, 0) < 0 || tmp3 == NULL) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 3 of GenericNetwork_DisconnectFeatures. Expected SWIGTYPE_p_GIntBig");
+    }
+    arg3 = *tmp3;
+  }
+  {
+    if(SWIG_ConvertPtr(*args[3], (void **) &tmp4, SWIGTYPE_p_GIntBig, 0) < 0 || tmp4 == NULL) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 4 of GenericNetwork_DisconnectFeatures. Expected SWIGTYPE_p_GIntBig");
+    }
+    arg4 = *tmp4;
+  }
+  result = (CPLErr)GNMGenericNetworkShadow_DisconnectFeatures(arg1,arg2,arg3,arg4);
+  {
+    ZVAL_LONG(return_value,result);
+  }
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_GenericNetwork_DisconnectFeaturesWithId) {
+  GNMGenericNetworkShadow *arg1 = (GNMGenericNetworkShadow *) 0 ;
+  GIntBig arg2 ;
+  GIntBig *tmp2 ;
+  zval **args[2];
+  CPLErr result;
+  
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 2 || zend_get_parameters_array_ex(2, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GNMGenericNetworkShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of GenericNetwork_DisconnectFeaturesWithId. Expected SWIGTYPE_p_GNMGenericNetworkShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  {
+    if(SWIG_ConvertPtr(*args[1], (void **) &tmp2, SWIGTYPE_p_GIntBig, 0) < 0 || tmp2 == NULL) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 2 of GenericNetwork_DisconnectFeaturesWithId. Expected SWIGTYPE_p_GIntBig");
+    }
+    arg2 = *tmp2;
+  }
+  result = (CPLErr)GNMGenericNetworkShadow_DisconnectFeaturesWithId(arg1,arg2);
+  {
+    ZVAL_LONG(return_value,result);
+  }
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_GenericNetwork_ReconnectFeatures) {
+  GNMGenericNetworkShadow *arg1 = (GNMGenericNetworkShadow *) 0 ;
+  GIntBig arg2 ;
+  GIntBig arg3 ;
+  GIntBig arg4 ;
+  double arg5 ;
+  double arg6 ;
+  GNMDirection arg7 ;
+  GIntBig *tmp2 ;
+  GIntBig *tmp3 ;
+  GIntBig *tmp4 ;
+  zval **args[7];
+  CPLErr result;
+  
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 7 || zend_get_parameters_array_ex(7, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GNMGenericNetworkShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of GenericNetwork_ReconnectFeatures. Expected SWIGTYPE_p_GNMGenericNetworkShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  {
+    if(SWIG_ConvertPtr(*args[1], (void **) &tmp2, SWIGTYPE_p_GIntBig, 0) < 0 || tmp2 == NULL) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 2 of GenericNetwork_ReconnectFeatures. Expected SWIGTYPE_p_GIntBig");
+    }
+    arg2 = *tmp2;
+  }
+  {
+    if(SWIG_ConvertPtr(*args[2], (void **) &tmp3, SWIGTYPE_p_GIntBig, 0) < 0 || tmp3 == NULL) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 3 of GenericNetwork_ReconnectFeatures. Expected SWIGTYPE_p_GIntBig");
+    }
+    arg3 = *tmp3;
+  }
+  {
+    if(SWIG_ConvertPtr(*args[3], (void **) &tmp4, SWIGTYPE_p_GIntBig, 0) < 0 || tmp4 == NULL) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 4 of GenericNetwork_ReconnectFeatures. Expected SWIGTYPE_p_GIntBig");
+    }
+    arg4 = *tmp4;
+  }
+  
+  /*@SWIG:/usr/share/swig2.0/php/utils.i,52,CONVERT_FLOAT_IN@*/
+  convert_to_double_ex(args[4]);
+  arg5 = (double) Z_DVAL_PP(args[4]);
+  /*@SWIG@*/;
+  
+  
+  /*@SWIG:/usr/share/swig2.0/php/utils.i,52,CONVERT_FLOAT_IN@*/
+  convert_to_double_ex(args[5]);
+  arg6 = (double) Z_DVAL_PP(args[5]);
+  /*@SWIG@*/;
+  
+  
+  /*@SWIG:/usr/share/swig2.0/php/utils.i,7,CONVERT_INT_IN@*/
+  convert_to_long_ex(args[6]);
+  arg7 = (GNMDirection) Z_LVAL_PP(args[6]);
+  /*@SWIG@*/;
+  
+  result = (CPLErr)GNMGenericNetworkShadow_ReconnectFeatures(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+  {
+    ZVAL_LONG(return_value,result);
+  }
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_GenericNetwork_CreateRule) {
+  GNMGenericNetworkShadow *arg1 = (GNMGenericNetworkShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  zval **args[2];
+  CPLErr result;
+  
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 2 || zend_get_parameters_array_ex(2, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GNMGenericNetworkShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of GenericNetwork_CreateRule. Expected SWIGTYPE_p_GNMGenericNetworkShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  
+  /*@SWIG:/usr/share/swig2.0/php/utils.i,62,CONVERT_STRING_IN@*/
+  if ((*args[1])->type==IS_NULL) {
+    arg2 = (char *) 0;
+  } else {
+    convert_to_string_ex(args[1]);
+    arg2 = (char *) Z_STRVAL_PP(args[1]);
+  }
+  /*@SWIG@*/;
+  
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  result = (CPLErr)GNMGenericNetworkShadow_CreateRule(arg1,(char const *)arg2);
+  {
+    ZVAL_LONG(return_value,result);
+  }
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_GenericNetwork_DeleteAllRules) {
+  GNMGenericNetworkShadow *arg1 = (GNMGenericNetworkShadow *) 0 ;
+  zval **args[1];
+  CPLErr result;
+  
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GNMGenericNetworkShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of GenericNetwork_DeleteAllRules. Expected SWIGTYPE_p_GNMGenericNetworkShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  result = (CPLErr)GNMGenericNetworkShadow_DeleteAllRules(arg1);
+  {
+    ZVAL_LONG(return_value,result);
+  }
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_GenericNetwork_DeleteRule) {
+  GNMGenericNetworkShadow *arg1 = (GNMGenericNetworkShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  zval **args[2];
+  CPLErr result;
+  
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 2 || zend_get_parameters_array_ex(2, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GNMGenericNetworkShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of GenericNetwork_DeleteRule. Expected SWIGTYPE_p_GNMGenericNetworkShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  
+  /*@SWIG:/usr/share/swig2.0/php/utils.i,62,CONVERT_STRING_IN@*/
+  if ((*args[1])->type==IS_NULL) {
+    arg2 = (char *) 0;
+  } else {
+    convert_to_string_ex(args[1]);
+    arg2 = (char *) Z_STRVAL_PP(args[1]);
+  }
+  /*@SWIG@*/;
+  
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  result = (CPLErr)GNMGenericNetworkShadow_DeleteRule(arg1,(char const *)arg2);
+  {
+    ZVAL_LONG(return_value,result);
+  }
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_GenericNetwork_GetRules) {
+  GNMGenericNetworkShadow *arg1 = (GNMGenericNetworkShadow *) 0 ;
+  zval **args[1];
+  char **result = 0 ;
+  
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GNMGenericNetworkShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of GenericNetwork_GetRules. Expected SWIGTYPE_p_GNMGenericNetworkShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  result = (char **)GNMGenericNetworkShadow_GetRules(arg1);
+  
+  SWIG_SetPointerZval(return_value, (void *)result, SWIGTYPE_p_p_char, 0);
+  
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_GenericNetwork_ConnectPointsByLines) {
+  GNMGenericNetworkShadow *arg1 = (GNMGenericNetworkShadow *) 0 ;
+  char **arg2 = (char **) 0 ;
+  double arg3 ;
+  double arg4 ;
+  double arg5 ;
+  GNMDirection arg6 ;
+  zval **args[6];
+  CPLErr result;
+  
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 6 || zend_get_parameters_array_ex(6, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GNMGenericNetworkShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of GenericNetwork_ConnectPointsByLines. Expected SWIGTYPE_p_GNMGenericNetworkShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  {
+    /* %typemap(in) char **options */
+    zend_error(E_ERROR,"Typemap (in) char **options not properly defined");
+    //  int size = PySequence_Size(args[1]);
+    //  for (int i = 0; i < size; i++) {
+    //    char *pszItem = NULL;
+    //    if ( ! PyArg_Parse( PySequence_GetItem(args[1],i), "s", &pszItem ) ) {
+    //      PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+    //      SWIG_fail;
+    //    }
+    //    arg2 = CSLAddString( arg2, pszItem );
+    //  }
+  }
+  
+  /*@SWIG:/usr/share/swig2.0/php/utils.i,52,CONVERT_FLOAT_IN@*/
+  convert_to_double_ex(args[2]);
+  arg3 = (double) Z_DVAL_PP(args[2]);
+  /*@SWIG@*/;
+  
+  
+  /*@SWIG:/usr/share/swig2.0/php/utils.i,52,CONVERT_FLOAT_IN@*/
+  convert_to_double_ex(args[3]);
+  arg4 = (double) Z_DVAL_PP(args[3]);
+  /*@SWIG@*/;
+  
+  
+  /*@SWIG:/usr/share/swig2.0/php/utils.i,52,CONVERT_FLOAT_IN@*/
+  convert_to_double_ex(args[4]);
+  arg5 = (double) Z_DVAL_PP(args[4]);
+  /*@SWIG@*/;
+  
+  
+  /*@SWIG:/usr/share/swig2.0/php/utils.i,7,CONVERT_INT_IN@*/
+  convert_to_long_ex(args[5]);
+  arg6 = (GNMDirection) Z_LVAL_PP(args[5]);
+  /*@SWIG@*/;
+  
+  result = (CPLErr)GNMGenericNetworkShadow_ConnectPointsByLines(arg1,arg2,arg3,arg4,arg5,arg6);
+  {
+    ZVAL_LONG(return_value,result);
+  }
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg2 );
+  }
+  return;
+fail:
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg2 );
+  }
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_GenericNetwork_ChangeBlockState) {
+  GNMGenericNetworkShadow *arg1 = (GNMGenericNetworkShadow *) 0 ;
+  GIntBig arg2 ;
+  bool arg3 ;
+  GIntBig *tmp2 ;
+  zval **args[3];
+  CPLErr result;
+  
+  SWIG_ResetError();
+  if(ZEND_NUM_ARGS() != 3 || zend_get_parameters_array_ex(3, args) != SUCCESS) {
+    WRONG_PARAM_COUNT;
+  }
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GNMGenericNetworkShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of GenericNetwork_ChangeBlockState. Expected SWIGTYPE_p_GNMGenericNetworkShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  {
+    if(SWIG_ConvertPtr(*args[1], (void **) &tmp2, SWIGTYPE_p_GIntBig, 0) < 0 || tmp2 == NULL) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 2 of GenericNetwork_ChangeBlockState. Expected SWIGTYPE_p_GIntBig");
+    }
+    arg2 = *tmp2;
+  }
+  
+  /*@SWIG:/usr/share/swig2.0/php/utils.i,2,CONVERT_BOOL_IN@*/
+  convert_to_boolean_ex(args[2]);
+  arg3 = (bool) Z_LVAL_PP(args[2]);
+  /*@SWIG@*/;
+  
+  result = (CPLErr)GNMGenericNetworkShadow_ChangeBlockState(arg1,arg2,arg3);
+  {
+    ZVAL_LONG(return_value,result);
+  }
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_GenericNetwork_ChangeAllBlockState) {
+  GNMGenericNetworkShadow *arg1 = (GNMGenericNetworkShadow *) 0 ;
+  bool arg2 = (bool) false ;
+  zval **args[2];
+  int arg_count;
+  CPLErr result;
+  
+  SWIG_ResetError();
+  arg_count = ZEND_NUM_ARGS();
+  if(arg_count<1 || arg_count>2 ||
+    zend_get_parameters_array_ex(arg_count,args)!=SUCCESS)
+  WRONG_PARAM_COUNT;
+  
+  {
+    if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_GNMGenericNetworkShadow, 0) < 0) {
+      SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of GenericNetwork_ChangeAllBlockState. Expected SWIGTYPE_p_GNMGenericNetworkShadow");
+    }
+  }
+  if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+  if(arg_count > 1) {
+    /*@SWIG:/usr/share/swig2.0/php/utils.i,2,CONVERT_BOOL_IN@*/
+    convert_to_boolean_ex(args[1]);
+    arg2 = (bool) Z_LVAL_PP(args[1]);
+    /*@SWIG@*/;
+    
+  }
+  result = (CPLErr)GNMGenericNetworkShadow_ChangeAllBlockState(arg1,arg2);
+  {
+    ZVAL_LONG(return_value,result);
+  }
+  return;
+fail:
+  SWIG_FAIL();
+}
+
+
+static ZEND_RSRC_DTOR_FUNC(_wrap_destroy_p_GIntBig) {
+  /* No destructor for simple type _p_GIntBig */
+  efree(rsrc->ptr);
+}
+static ZEND_RSRC_DTOR_FUNC(_wrap_destroy_p_GNMGraphAlgorithmType) {
+  /* No destructor for simple type _p_GNMGraphAlgorithmType */
+  efree(rsrc->ptr);
+}
+static ZEND_RSRC_DTOR_FUNC(_wrap_destroy_p_OGRwkbGeometryType) {
+  /* No destructor for simple type _p_OGRwkbGeometryType */
+  efree(rsrc->ptr);
+}
+static ZEND_RSRC_DTOR_FUNC(_wrap_destroy_p_char) {
+  /* No destructor for simple type _p_char */
+  efree(rsrc->ptr);
+}
+static ZEND_RSRC_DTOR_FUNC(_wrap_destroy_p_p_char) {
+  /* No destructor for simple type _p_p_char */
+  efree(rsrc->ptr);
+}
+static ZEND_RSRC_DTOR_FUNC(_wrap_destroy_p_OSRSpatialReferenceShadow) {
+  /* No destructor for simple type _p_OSRSpatialReferenceShadow */
+  efree(rsrc->ptr);
+}
+static ZEND_RSRC_DTOR_FUNC(_wrap_destroy_p_OGRFeatureShadow) {
+  /* No destructor for simple type _p_OGRFeatureShadow */
+  efree(rsrc->ptr);
+}
+static ZEND_RSRC_DTOR_FUNC(_wrap_destroy_p_GNMGenericNetworkShadow) {
+  __wrap_delete_GenericNetwork(rsrc, SWIGTYPE_p_GNMGenericNetworkShadow->name TSRMLS_CC);
+}
+static ZEND_RSRC_DTOR_FUNC(_wrap_destroy_p_GNMNetworkShadow) {
+  __wrap_delete_Network(rsrc, SWIGTYPE_p_GNMNetworkShadow->name TSRMLS_CC);
+}
+static ZEND_RSRC_DTOR_FUNC(_wrap_destroy_int) {
+  /* No destructor for simple type _int */
+  efree(rsrc->ptr);
+}
+static ZEND_RSRC_DTOR_FUNC(_wrap_destroy_p_int) {
+  /* No destructor for simple type _p_int */
+  efree(rsrc->ptr);
+}
+static ZEND_RSRC_DTOR_FUNC(_wrap_destroy_p_p_OGRLayerShadow) {
+  /* No destructor for simple type _p_p_OGRLayerShadow */
+  efree(rsrc->ptr);
+}
+static ZEND_RSRC_DTOR_FUNC(_wrap_destroy_p_OGRLayerShadow) {
+  /* No destructor for simple type _p_OGRLayerShadow */
+  efree(rsrc->ptr);
+}
+static ZEND_RSRC_DTOR_FUNC(_wrap_destroy_p_GDALMajorObjectShadow) {
+  /* No destructor for class MajorObject */
+  efree(rsrc->ptr);
+}
+/* end wrapper section */
+/* class entry subsection */
+
+
+/* entry subsection */
+/* Every non-class user visible function must have an entry here */
+static zend_function_entry gnm_functions[] = {
+ SWIG_ZEND_NAMED_FE(majorobject_getdescription,_wrap_MajorObject_GetDescription,NULL)
+ SWIG_ZEND_NAMED_FE(majorobject_setdescription,_wrap_MajorObject_SetDescription,NULL)
+ SWIG_ZEND_NAMED_FE(majorobject_getmetadatadomainlist,_wrap_MajorObject_GetMetadataDomainList,NULL)
+ SWIG_ZEND_NAMED_FE(majorobject_getmetadata_dict,_wrap_MajorObject_GetMetadata_Dict,NULL)
+ SWIG_ZEND_NAMED_FE(majorobject_getmetadata_list,_wrap_MajorObject_GetMetadata_List,NULL)
+ SWIG_ZEND_NAMED_FE(majorobject_setmetadata,_wrap_MajorObject_SetMetadata,NULL)
+ SWIG_ZEND_NAMED_FE(majorobject_getmetadataitem,_wrap_MajorObject_GetMetadataItem,NULL)
+ SWIG_ZEND_NAMED_FE(majorobject_setmetadataitem,_wrap_MajorObject_SetMetadataItem,NULL)
+ SWIG_ZEND_NAMED_FE(casttonetwork,_wrap_CastToNetwork,NULL)
+ SWIG_ZEND_NAMED_FE(casttogenericnetwork,_wrap_CastToGenericNetwork,NULL)
+ SWIG_ZEND_NAMED_FE(network_releaseresultset,_wrap_Network_ReleaseResultSet,NULL)
+ SWIG_ZEND_NAMED_FE(network_getversion,_wrap_Network_GetVersion,NULL)
+ SWIG_ZEND_NAMED_FE(network_getname,_wrap_Network_GetName,NULL)
+ SWIG_ZEND_NAMED_FE(network_getfeaturebyglobalfid,_wrap_Network_GetFeatureByGlobalFID,NULL)
+ SWIG_ZEND_NAMED_FE(network_getpath,_wrap_Network_GetPath,NULL)
+ SWIG_ZEND_NAMED_FE(network_disconnectall,_wrap_Network_DisconnectAll,NULL)
+ SWIG_ZEND_NAMED_FE(network_getprojection,_wrap_Network_GetProjection,NULL)
+ SWIG_ZEND_NAMED_FE(network_getprojectionref,_wrap_Network_GetProjectionRef,NULL)
+ SWIG_ZEND_NAMED_FE(network_getfilelist,_wrap_Network_GetFileList,NULL)
+ SWIG_ZEND_NAMED_FE(network_createlayer,_wrap_Network_CreateLayer,NULL)
+ SWIG_ZEND_NAMED_FE(network_copylayer,_wrap_Network_CopyLayer,NULL)
+ SWIG_ZEND_NAMED_FE(network_deletelayer,_wrap_Network_DeleteLayer,NULL)
+ SWIG_ZEND_NAMED_FE(network_getlayercount,_wrap_Network_GetLayerCount,NULL)
+ SWIG_ZEND_NAMED_FE(network_getlayerbyindex,_wrap_Network_GetLayerByIndex,NULL)
+ SWIG_ZEND_NAMED_FE(network_getlayerbyname,_wrap_Network_GetLayerByName,NULL)
+ SWIG_ZEND_NAMED_FE(network_testcapability,_wrap_Network_TestCapability,NULL)
+ SWIG_ZEND_NAMED_FE(network_starttransaction,_wrap_Network_StartTransaction,NULL)
+ SWIG_ZEND_NAMED_FE(network_committransaction,_wrap_Network_CommitTransaction,NULL)
+ SWIG_ZEND_NAMED_FE(network_rollbacktransaction,_wrap_Network_RollbackTransaction,NULL)
+ SWIG_ZEND_NAMED_FE(genericnetwork_connectfeatures,_wrap_GenericNetwork_ConnectFeatures,NULL)
+ SWIG_ZEND_NAMED_FE(genericnetwork_disconnectfeatures,_wrap_GenericNetwork_DisconnectFeatures,NULL)
+ SWIG_ZEND_NAMED_FE(genericnetwork_disconnectfeatureswithid,_wrap_GenericNetwork_DisconnectFeaturesWithId,NULL)
+ SWIG_ZEND_NAMED_FE(genericnetwork_reconnectfeatures,_wrap_GenericNetwork_ReconnectFeatures,NULL)
+ SWIG_ZEND_NAMED_FE(genericnetwork_createrule,_wrap_GenericNetwork_CreateRule,NULL)
+ SWIG_ZEND_NAMED_FE(genericnetwork_deleteallrules,_wrap_GenericNetwork_DeleteAllRules,NULL)
+ SWIG_ZEND_NAMED_FE(genericnetwork_deleterule,_wrap_GenericNetwork_DeleteRule,NULL)
+ SWIG_ZEND_NAMED_FE(genericnetwork_getrules,_wrap_GenericNetwork_GetRules,NULL)
+ SWIG_ZEND_NAMED_FE(genericnetwork_connectpointsbylines,_wrap_GenericNetwork_ConnectPointsByLines,NULL)
+ SWIG_ZEND_NAMED_FE(genericnetwork_changeblockstate,_wrap_GenericNetwork_ChangeBlockState,NULL)
+ SWIG_ZEND_NAMED_FE(genericnetwork_changeallblockstate,_wrap_GenericNetwork_ChangeAllBlockState,NULL)
+ SWIG_ZEND_NAMED_FE(swig_gnm_alter_newobject,_wrap_swig_gnm_alter_newobject,NULL)
+ SWIG_ZEND_NAMED_FE(swig_gnm_get_newobject,_wrap_swig_gnm_get_newobject,NULL)
+{NULL, NULL, NULL}
+};
+
+/* init section */
+#if ZEND_MODULE_API_NO <= 20090626
+#undef ZEND_MODULE_BUILD_ID
+#define ZEND_MODULE_BUILD_ID (char*)"API" ZEND_TOSTR(ZEND_MODULE_API_NO) ZEND_BUILD_TS ZEND_BUILD_DEBUG ZEND_BUILD_SYSTEM ZEND_BUILD_EXTRA
+#endif
+zend_module_entry gnm_module_entry = {
+    STANDARD_MODULE_HEADER,
+    (char*)"gnm",
+    gnm_functions,
+    PHP_MINIT(gnm),
+    PHP_MSHUTDOWN(gnm),
+    PHP_RINIT(gnm),
+    PHP_RSHUTDOWN(gnm),
+    PHP_MINFO(gnm),
+    NO_VERSION_YET,
+    STANDARD_MODULE_PROPERTIES
+};
+zend_module_entry* SWIG_module_entry = &gnm_module_entry;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+SWIGEXPORT zend_module_entry *get_module(void) { return &gnm_module_entry; }
+#ifdef __cplusplus
+}
+#endif
+
+#define SWIG_php_minit PHP_MINIT_FUNCTION(gnm)
+/* -----------------------------------------------------------------------------
+ * Type initialization:
+ * This problem is tough by the requirement that no dynamic
+ * memory is used. Also, since swig_type_info structures store pointers to
+ * swig_cast_info structures and swig_cast_info structures store pointers back
+ * to swig_type_info structures, we need some lookup code at initialization.
+ * The idea is that swig generates all the structures that are needed.
+ * The runtime then collects these partially filled structures.
+ * The SWIG_InitializeModule function takes these initial arrays out of
+ * swig_module, and does all the lookup, filling in the swig_module.types
+ * array with the correct data and linking the correct swig_cast_info
+ * structures together.
+ *
+ * The generated swig_type_info structures are assigned staticly to an initial
+ * array. We just loop through that array, and handle each type individually.
+ * First we lookup if this type has been already loaded, and if so, use the
+ * loaded structure instead of the generated one. Then we have to fill in the
+ * cast linked list. The cast data is initially stored in something like a
+ * two-dimensional array. Each row corresponds to a type (there are the same
+ * number of rows as there are in the swig_type_initial array). Each entry in
+ * a column is one of the swig_cast_info structures for that type.
+ * The cast_initial array is actually an array of arrays, because each row has
+ * a variable number of columns. So to actually build the cast linked list,
+ * we find the array of casts associated with the type, and loop through it
+ * adding the casts to the list. The one last trick we need to do is making
+ * sure the type pointer in the swig_cast_info struct is correct.
+ *
+ * First off, we lookup the cast->type name to see if it is already loaded.
+ * There are three cases to handle:
+ *  1) If the cast->type has already been loaded AND the type we are adding
+ *     casting info to has not been loaded (it is in this module), THEN we
+ *     replace the cast->type pointer with the type pointer that has already
+ *     been loaded.
+ *  2) If BOTH types (the one we are adding casting info to, and the
+ *     cast->type) are loaded, THEN the cast info has already been loaded by
+ *     the previous module so we just ignore it.
+ *  3) Finally, if cast->type has not already been loaded, then we add that
+ *     swig_cast_info to the linked list (because the cast->type) pointer will
+ *     be correct.
+ * ----------------------------------------------------------------------------- */
+
+#ifdef __cplusplus
+extern "C" {
+#if 0
+} /* c-mode */
+#endif
+#endif
+
+#if 0
+#define SWIGRUNTIME_DEBUG
+#endif
+
+
+SWIGRUNTIME void
+SWIG_InitializeModule(void *clientdata) {
+  size_t i;
+  swig_module_info *module_head, *iter;
+  int found, init;
+
+  /* check to see if the circular list has been setup, if not, set it up */
+  if (swig_module.next==0) {
+    /* Initialize the swig_module */
+    swig_module.type_initial = swig_type_initial;
+    swig_module.cast_initial = swig_cast_initial;
+    swig_module.next = &swig_module;
+    init = 1;
+  } else {
+    init = 0;
+  }
+
+  /* Try and load any already created modules */
+  module_head = SWIG_GetModule(clientdata);
+  if (!module_head) {
+    /* This is the first module loaded for this interpreter */
+    /* so set the swig module into the interpreter */
+    SWIG_SetModule(clientdata, &swig_module);
+    module_head = &swig_module;
+  } else {
+    /* the interpreter has loaded a SWIG module, but has it loaded this one? */
+    found=0;
+    iter=module_head;
+    do {
+      if (iter==&swig_module) {
+        found=1;
+        break;
+      }
+      iter=iter->next;
+    } while (iter!= module_head);
+
+    /* if the is found in the list, then all is done and we may leave */
+    if (found) return;
+    /* otherwise we must add out module into the list */
+    swig_module.next = module_head->next;
+    module_head->next = &swig_module;
+  }
+
+  /* When multiple interpreters are used, a module could have already been initialized in
+     a different interpreter, but not yet have a pointer in this interpreter.
+     In this case, we do not want to continue adding types... everything should be
+     set up already */
+  if (init == 0) return;
+
+  /* Now work on filling in swig_module.types */
+#ifdef SWIGRUNTIME_DEBUG
+  printf("SWIG_InitializeModule: size %d\n", swig_module.size);
+#endif
+  for (i = 0; i < swig_module.size; ++i) {
+    swig_type_info *type = 0;
+    swig_type_info *ret;
+    swig_cast_info *cast;
+
+#ifdef SWIGRUNTIME_DEBUG
+    printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name);
+#endif
+
+    /* if there is another module already loaded */
+    if (swig_module.next != &swig_module) {
+      type = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, swig_module.type_initial[i]->name);
+    }
+    if (type) {
+      /* Overwrite clientdata field */
+#ifdef SWIGRUNTIME_DEBUG
+      printf("SWIG_InitializeModule: found type %s\n", type->name);
+#endif
+      if (swig_module.type_initial[i]->clientdata) {
+	type->clientdata = swig_module.type_initial[i]->clientdata;
+#ifdef SWIGRUNTIME_DEBUG
+      printf("SWIG_InitializeModule: found and overwrite type %s \n", type->name);
+#endif
+      }
+    } else {
+      type = swig_module.type_initial[i];
+    }
+
+    /* Insert casting types */
+    cast = swig_module.cast_initial[i];
+    while (cast->type) {
+
+      /* Don't need to add information already in the list */
+      ret = 0;
+#ifdef SWIGRUNTIME_DEBUG
+      printf("SWIG_InitializeModule: look cast %s\n", cast->type->name);
+#endif
+      if (swig_module.next != &swig_module) {
+        ret = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, cast->type->name);
+#ifdef SWIGRUNTIME_DEBUG
+	if (ret) printf("SWIG_InitializeModule: found cast %s\n", ret->name);
+#endif
+      }
+      if (ret) {
+	if (type == swig_module.type_initial[i]) {
+#ifdef SWIGRUNTIME_DEBUG
+	  printf("SWIG_InitializeModule: skip old type %s\n", ret->name);
+#endif
+	  cast->type = ret;
+	  ret = 0;
+	} else {
+	  /* Check for casting already in the list */
+	  swig_cast_info *ocast = SWIG_TypeCheck(ret->name, type);
+#ifdef SWIGRUNTIME_DEBUG
+	  if (ocast) printf("SWIG_InitializeModule: skip old cast %s\n", ret->name);
+#endif
+	  if (!ocast) ret = 0;
+	}
+      }
+
+      if (!ret) {
+#ifdef SWIGRUNTIME_DEBUG
+	printf("SWIG_InitializeModule: adding cast %s\n", cast->type->name);
+#endif
+        if (type->cast) {
+          type->cast->prev = cast;
+          cast->next = type->cast;
+        }
+        type->cast = cast;
+      }
+      cast++;
+    }
+    /* Set entry in modules->types array equal to the type */
+    swig_module.types[i] = type;
+  }
+  swig_module.types[i] = 0;
+
+#ifdef SWIGRUNTIME_DEBUG
+  printf("**** SWIG_InitializeModule: Cast List ******\n");
+  for (i = 0; i < swig_module.size; ++i) {
+    int j = 0;
+    swig_cast_info *cast = swig_module.cast_initial[i];
+    printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name);
+    while (cast->type) {
+      printf("SWIG_InitializeModule: cast type %s\n", cast->type->name);
+      cast++;
+      ++j;
+    }
+  printf("---- Total casts: %d\n",j);
+  }
+  printf("**** SWIG_InitializeModule: Cast List ******\n");
+#endif
+}
+
+/* This function will propagate the clientdata field of type to
+* any new swig_type_info structures that have been added into the list
+* of equivalent types.  It is like calling
+* SWIG_TypeClientData(type, clientdata) a second time.
+*/
+SWIGRUNTIME void
+SWIG_PropagateClientData(void) {
+  size_t i;
+  swig_cast_info *equiv;
+  static int init_run = 0;
+
+  if (init_run) return;
+  init_run = 1;
+
+  for (i = 0; i < swig_module.size; i++) {
+    if (swig_module.types[i]->clientdata) {
+      equiv = swig_module.types[i]->cast;
+      while (equiv) {
+        if (!equiv->converter) {
+          if (equiv->type && !equiv->type->clientdata)
+            SWIG_TypeClientData(equiv->type, swig_module.types[i]->clientdata);
+        }
+        equiv = equiv->next;
+      }
+    }
+  }
+}
+
+#ifdef __cplusplus
+#if 0
+{ /* c-mode */
+#endif
+}
+#endif
+
+
+  SWIG_php_minit {
+    SWIG_InitializeModule(0);
+
+/* oinit subsection */
+ZEND_INIT_MODULE_GLOBALS(gnm, gnm_init_globals, gnm_destroy_globals);
+
+/* Register resource destructors for pointer types */
+le_swig__p_GIntBig=zend_register_list_destructors_ex(_wrap_destroy_p_GIntBig,NULL,(char *)(SWIGTYPE_p_GIntBig->name),module_number);
+SWIG_TypeClientData(SWIGTYPE_p_GIntBig,&le_swig__p_GIntBig);
+le_swig__p_GNMGraphAlgorithmType=zend_register_list_destructors_ex(_wrap_destroy_p_GNMGraphAlgorithmType,NULL,(char *)(SWIGTYPE_p_GNMGraphAlgorithmType->name),module_number);
+SWIG_TypeClientData(SWIGTYPE_p_GNMGraphAlgorithmType,&le_swig__p_GNMGraphAlgorithmType);
+le_swig__p_OGRwkbGeometryType=zend_register_list_destructors_ex(_wrap_destroy_p_OGRwkbGeometryType,NULL,(char *)(SWIGTYPE_p_OGRwkbGeometryType->name),module_number);
+SWIG_TypeClientData(SWIGTYPE_p_OGRwkbGeometryType,&le_swig__p_OGRwkbGeometryType);
+le_swig__p_char=zend_register_list_destructors_ex(_wrap_destroy_p_char,NULL,(char *)(SWIGTYPE_p_char->name),module_number);
+SWIG_TypeClientData(SWIGTYPE_p_char,&le_swig__p_char);
+le_swig__p_p_char=zend_register_list_destructors_ex(_wrap_destroy_p_p_char,NULL,(char *)(SWIGTYPE_p_p_char->name),module_number);
+SWIG_TypeClientData(SWIGTYPE_p_p_char,&le_swig__p_p_char);
+le_swig__p_OSRSpatialReferenceShadow=zend_register_list_destructors_ex(_wrap_destroy_p_OSRSpatialReferenceShadow,NULL,(char *)(SWIGTYPE_p_OSRSpatialReferenceShadow->name),module_number);
+SWIG_TypeClientData(SWIGTYPE_p_OSRSpatialReferenceShadow,&le_swig__p_OSRSpatialReferenceShadow);
+le_swig__p_OGRFeatureShadow=zend_register_list_destructors_ex(_wrap_destroy_p_OGRFeatureShadow,NULL,(char *)(SWIGTYPE_p_OGRFeatureShadow->name),module_number);
+SWIG_TypeClientData(SWIGTYPE_p_OGRFeatureShadow,&le_swig__p_OGRFeatureShadow);
+le_swig__p_GNMGenericNetworkShadow=zend_register_list_destructors_ex(_wrap_destroy_p_GNMGenericNetworkShadow,NULL,(char *)(SWIGTYPE_p_GNMGenericNetworkShadow->name),module_number);
+SWIG_TypeClientData(SWIGTYPE_p_GNMGenericNetworkShadow,&le_swig__p_GNMGenericNetworkShadow);
+le_swig__p_GNMNetworkShadow=zend_register_list_destructors_ex(_wrap_destroy_p_GNMNetworkShadow,NULL,(char *)(SWIGTYPE_p_GNMNetworkShadow->name),module_number);
+SWIG_TypeClientData(SWIGTYPE_p_GNMNetworkShadow,&le_swig__p_GNMNetworkShadow);
+le_swig__int=zend_register_list_destructors_ex(_wrap_destroy_int,NULL,(char *)(SWIGTYPE_int->name),module_number);
+SWIG_TypeClientData(SWIGTYPE_int,&le_swig__int);
+le_swig__p_int=zend_register_list_destructors_ex(_wrap_destroy_p_int,NULL,(char *)(SWIGTYPE_p_int->name),module_number);
+SWIG_TypeClientData(SWIGTYPE_p_int,&le_swig__p_int);
+le_swig__p_p_OGRLayerShadow=zend_register_list_destructors_ex(_wrap_destroy_p_p_OGRLayerShadow,NULL,(char *)(SWIGTYPE_p_p_OGRLayerShadow->name),module_number);
+SWIG_TypeClientData(SWIGTYPE_p_p_OGRLayerShadow,&le_swig__p_p_OGRLayerShadow);
+le_swig__p_OGRLayerShadow=zend_register_list_destructors_ex(_wrap_destroy_p_OGRLayerShadow,NULL,(char *)(SWIGTYPE_p_OGRLayerShadow->name),module_number);
+SWIG_TypeClientData(SWIGTYPE_p_OGRLayerShadow,&le_swig__p_OGRLayerShadow);
+le_swig__p_GDALMajorObjectShadow=zend_register_list_destructors_ex(_wrap_destroy_p_GDALMajorObjectShadow,NULL,(char *)(SWIGTYPE_p_GDALMajorObjectShadow->name),module_number);
+SWIG_TypeClientData(SWIGTYPE_p_GDALMajorObjectShadow,&le_swig__p_GDALMajorObjectShadow);
+CG(active_class_entry) = NULL;
+/* end oinit subsection */
+
+/* cinit subsection */
+SWIG_LONG_CONSTANT(GATDijkstraShortestPath, GATDijkstraShortestPath);
+SWIG_LONG_CONSTANT(GATKShortestPath, GATKShortestPath);
+SWIG_LONG_CONSTANT(GATConnectedComponents, GATConnectedComponents);
+SWIG_LONG_CONSTANT(GNM_EDGE_DIR_BOTH, 0);
+SWIG_LONG_CONSTANT(GNM_EDGE_DIR_SRCTOTGT, 1);
+SWIG_LONG_CONSTANT(GNM_EDGE_DIR_TGTTOSRC, 2);
+/* end cinit subsection */
+
+    return SUCCESS;
+}
+
+PHP_RINIT_FUNCTION(gnm)
+{
+/* rinit section */
+
+/* vinit subsection */
+/* end vinit subsection */
+
+    return SUCCESS;
+}
+
+PHP_MSHUTDOWN_FUNCTION(gnm)
+{
+/* shutdown section */
+#ifdef ZTS
+    ts_free_id(gnm_globals_id);
+#endif
+    return SUCCESS;
+}
+
+PHP_RSHUTDOWN_FUNCTION(gnm)
+{
+/* rshutdown section */
+
+    return SUCCESS;
+}
+
+PHP_MINFO_FUNCTION(gnm)
+{
+}
+/* end init section */
diff --git a/swig/php/ogr_wrap.cpp b/swig/php/ogr_wrap.cpp
index e979f5d..b99a242 100644
--- a/swig/php/ogr_wrap.cpp
+++ b/swig/php/ogr_wrap.cpp
@@ -167,9 +167,9 @@ template <typename T> T SwigValueInit() {
   You can use the SWIGRUNTIME and SWIGRUNTIMEINLINE macros for
   creating a static or dynamic library from the SWIG runtime code.
   In 99.9% of the cases, SWIG just needs to declare them as 'static'.
-  
-  But only do this if strictly necessary, ie, if you have problems
-  with your compiler or suchlike.
+
+  But only do this if strictly necessary, i.e. if you have problems
+  with your compiler or such.
 */
 
 #ifndef SWIGRUNTIME
@@ -848,7 +848,7 @@ SWIG_ZTS_SetPointerZval(zval *z, void *ptr, swig_type_info *type, int newobject
       /*
        * Wrap the resource in an object, the resource will be accessible
        * via the "_cPtr" member. This is currently only used by
-       * directorin typemaps.
+       * directory typemaps.
        */
       value->newobject = 0;
       zval *resource;
@@ -10852,10 +10852,10 @@ SWIG_InitializeModule(void *clientdata) {
     module_head->next = &swig_module;
   }
 
-  /* When multiple interpeters are used, a module could have already been initialized in
-     a different interpreter, but not yet have a pointer in this interpreter.
-     In this case, we do not want to continue adding types... everything should be
-     set up already */
+  /* When multiple interpreters are used, a module could have already
+     been initialized in a different interpreter, but not yet have a
+     pointer in this interpreter.  In this case, we do not want to
+     continue adding types... everything should be set up already */
   if (init == 0) return;
 
   /* Now work on filling in swig_module.types */
@@ -10866,7 +10866,7 @@ SWIG_InitializeModule(void *clientdata) {
     swig_type_info *type = 0;
     swig_type_info *ret;
     swig_cast_info *cast;
-  
+
 #ifdef SWIGRUNTIME_DEBUG
     printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name);
 #endif
diff --git a/swig/php/osr_wrap.cpp b/swig/php/osr_wrap.cpp
index b0d2173..c514f46 100644
--- a/swig/php/osr_wrap.cpp
+++ b/swig/php/osr_wrap.cpp
@@ -167,9 +167,9 @@ template <typename T> T SwigValueInit() {
   You can use the SWIGRUNTIME and SWIGRUNTIMEINLINE macros for
   creating a static or dynamic library from the SWIG runtime code.
   In 99.9% of the cases, SWIG just needs to declare them as 'static'.
-  
-  But only do this if strictly necessary, ie, if you have problems
-  with your compiler or suchlike.
+
+  But only do this if strictly necessary, i.e. if you have problems
+  with your compiler or such.
 */
 
 #ifndef SWIGRUNTIME
@@ -848,7 +848,7 @@ SWIG_ZTS_SetPointerZval(zval *z, void *ptr, swig_type_info *type, int newobject
       /*
        * Wrap the resource in an object, the resource will be accessible
        * via the "_cPtr" member. This is currently only used by
-       * directorin typemaps.
+       * directory typemaps.
        */
       value->newobject = 0;
       zval *resource;
@@ -8083,10 +8083,10 @@ SWIG_InitializeModule(void *clientdata) {
     module_head->next = &swig_module;
   }
 
-  /* When multiple interpeters are used, a module could have already been initialized in
-     a different interpreter, but not yet have a pointer in this interpreter.
-     In this case, we do not want to continue adding types... everything should be
-     set up already */
+  /* When multiple interpreters are used, a module could have already
+     been initialized in a different interpreter, but not yet have a
+     pointer in this interpreter.  In this case, we do not want to
+     continue adding types... everything should be set up already */
   if (init == 0) return;
 
   /* Now work on filling in swig_module.types */
@@ -8097,7 +8097,7 @@ SWIG_InitializeModule(void *clientdata) {
     swig_type_info *type = 0;
     swig_type_info *ret;
     swig_cast_info *cast;
-  
+
 #ifdef SWIGRUNTIME_DEBUG
     printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name);
 #endif
diff --git a/swig/php/php_gnm.h b/swig/php/php_gnm.h
new file mode 100644
index 0000000..89365cd
--- /dev/null
+++ b/swig/php/php_gnm.h
@@ -0,0 +1,73 @@
+/* ----------------------------------------------------------------------------
+ * This file was automatically generated by SWIG (http://www.swig.org).
+ * Version 2.0.12
+ *
+ * This file is not intended to be easily readable and contains a number of
+ * coding conventions designed to improve portability and efficiency. Do not make
+ * changes to this file unless you know what you are doing--modify the SWIG
+ * interface file instead.
+ * ----------------------------------------------------------------------------- */
+
+#ifndef PHP_GNM_H
+#define PHP_GNM_H
+
+extern zend_module_entry gnm_module_entry;
+#define phpext_gnm_ptr &gnm_module_entry
+
+#ifdef PHP_WIN32
+# define PHP_GNM_API __declspec(dllexport)
+#else
+# define PHP_GNM_API
+#endif
+
+#ifdef ZTS
+#include "TSRM.h"
+#endif
+
+PHP_MINIT_FUNCTION(gnm);
+PHP_MSHUTDOWN_FUNCTION(gnm);
+PHP_RINIT_FUNCTION(gnm);
+PHP_RSHUTDOWN_FUNCTION(gnm);
+PHP_MINFO_FUNCTION(gnm);
+
+ZEND_NAMED_FUNCTION(_wrap_MajorObject_GetDescription);
+ZEND_NAMED_FUNCTION(_wrap_MajorObject_SetDescription);
+ZEND_NAMED_FUNCTION(_wrap_MajorObject_GetMetadataDomainList);
+ZEND_NAMED_FUNCTION(_wrap_MajorObject_GetMetadata_Dict);
+ZEND_NAMED_FUNCTION(_wrap_MajorObject_GetMetadata_List);
+ZEND_NAMED_FUNCTION(_wrap_MajorObject_SetMetadata);
+ZEND_NAMED_FUNCTION(_wrap_MajorObject_GetMetadataItem);
+ZEND_NAMED_FUNCTION(_wrap_MajorObject_SetMetadataItem);
+ZEND_NAMED_FUNCTION(_wrap_CastToNetwork);
+ZEND_NAMED_FUNCTION(_wrap_CastToGenericNetwork);
+ZEND_NAMED_FUNCTION(_wrap_Network_ReleaseResultSet);
+ZEND_NAMED_FUNCTION(_wrap_Network_GetVersion);
+ZEND_NAMED_FUNCTION(_wrap_Network_GetName);
+ZEND_NAMED_FUNCTION(_wrap_Network_GetFeatureByGlobalFID);
+ZEND_NAMED_FUNCTION(_wrap_Network_GetPath);
+ZEND_NAMED_FUNCTION(_wrap_Network_DisconnectAll);
+ZEND_NAMED_FUNCTION(_wrap_Network_GetProjection);
+ZEND_NAMED_FUNCTION(_wrap_Network_GetProjectionRef);
+ZEND_NAMED_FUNCTION(_wrap_Network_GetFileList);
+ZEND_NAMED_FUNCTION(_wrap_Network_CreateLayer);
+ZEND_NAMED_FUNCTION(_wrap_Network_CopyLayer);
+ZEND_NAMED_FUNCTION(_wrap_Network_DeleteLayer);
+ZEND_NAMED_FUNCTION(_wrap_Network_GetLayerCount);
+ZEND_NAMED_FUNCTION(_wrap_Network_GetLayerByIndex);
+ZEND_NAMED_FUNCTION(_wrap_Network_GetLayerByName);
+ZEND_NAMED_FUNCTION(_wrap_Network_TestCapability);
+ZEND_NAMED_FUNCTION(_wrap_Network_StartTransaction);
+ZEND_NAMED_FUNCTION(_wrap_Network_CommitTransaction);
+ZEND_NAMED_FUNCTION(_wrap_Network_RollbackTransaction);
+ZEND_NAMED_FUNCTION(_wrap_GenericNetwork_ConnectFeatures);
+ZEND_NAMED_FUNCTION(_wrap_GenericNetwork_DisconnectFeatures);
+ZEND_NAMED_FUNCTION(_wrap_GenericNetwork_DisconnectFeaturesWithId);
+ZEND_NAMED_FUNCTION(_wrap_GenericNetwork_ReconnectFeatures);
+ZEND_NAMED_FUNCTION(_wrap_GenericNetwork_CreateRule);
+ZEND_NAMED_FUNCTION(_wrap_GenericNetwork_DeleteAllRules);
+ZEND_NAMED_FUNCTION(_wrap_GenericNetwork_DeleteRule);
+ZEND_NAMED_FUNCTION(_wrap_GenericNetwork_GetRules);
+ZEND_NAMED_FUNCTION(_wrap_GenericNetwork_ConnectPointsByLines);
+ZEND_NAMED_FUNCTION(_wrap_GenericNetwork_ChangeBlockState);
+ZEND_NAMED_FUNCTION(_wrap_GenericNetwork_ChangeAllBlockState);
+#endif /* PHP_GNM_H */
diff --git a/swig/python/GNUmakefile b/swig/python/GNUmakefile
index b4d5e90..57b31a7 100644
--- a/swig/python/GNUmakefile
+++ b/swig/python/GNUmakefile
@@ -18,7 +18,7 @@ SCRIPTS			= `ls ./scripts`
 PY_COMMANDS     =       epsg_tr.py gdalchksum.py gdal2xyz.py gcps2wld.py \
                         gdalimport.py gdal_merge.py pct2rgb.py rgb2pct.py \
                         gcps2vec.py
-PY_MODULES      =       ${PACKAGE_DIR}/gdal.py ${PACKAGE_DIR}/ogr.py ${PACKAGE_DIR}/osr.py ${PACKAGE_DIR}/gdalconst.py ${PACKAGE_DIR}/gdal_array.py
+PY_MODULES      =       ${PACKAGE_DIR}/gdal.py ${PACKAGE_DIR}/ogr.py ${PACKAGE_DIR}/osr.py ${PACKAGE_DIR}/gdalconst.py ${PACKAGE_DIR}/gdal_array.py ${PACKAGE_DIR}/gnm.py
 
 clean:
 	-rm -f ${PACKAGE_DIR}/*.pyc
@@ -38,6 +38,7 @@ veryclean: clean
 	-rm -f ${SWIGOUTPUTDIR}/ogr_wrap.cpp
 	-rm -f ${SWIGOUTPUTDIR}/osr_wrap.cpp
 	-rm -f ${SWIGOUTPUTDIR}/gdal_array_wrap.cpp
+	-rm -f ${SWIGOUTPUTDIR}/gnm_wrap.cpp
 
 gdal_wrap.cpp: ../include/python/gdal_python.i
 
@@ -52,44 +53,94 @@ gdal_array_wrap.cpp:  ../include/gdal_array.i ../include/python/typemaps_python.
 # The python3.2.patch is from https://sourceforge.net/tracker/?func=detail&aid=3057804&group_id=1645&atid=101645
 # and is no longer necessary with swig 2.0.4
 generate: ${WRAPPERS} gdal_array_wrap.cpp
-	for i in gdal_wrap.cpp gdalconst_wrap.c ogr_wrap.cpp osr_wrap.cpp gdal_array_wrap.cpp; do sed "s/PyErr_Format(PyExc_RuntimeError, mesg)/PyErr_SetString(PyExc_RuntimeError, mesg)/" ${SWIGOUTPUTDIR}/$$i | sed "s/int len;/Py_ssize_t len;/" > ${SWIGOUTPUTDIR}/$$i.tmp; mv -f ${SWIGOUTPUTDIR}/$$i.tmp ${SWIGOUTPUTDIR}/$$i; done
+	for i in gdal_wrap.cpp gdalconst_wrap.c ogr_wrap.cpp osr_wrap.cpp gdal_array_wrap.cpp gnm_wrap.cpp; do if test -f ${SWIGOUTPUTDIR}/$$i; then sed "s/PyErr_Format(PyExc_RuntimeError, mesg)/PyErr_SetString(PyExc_RuntimeError, mesg)/" ${SWIGOUTPUTDIR}/$$i | sed "s/int len;/Py_ssize_t len;/" > ${SWIGOUTPUTDIR}/$$i.tmp; mv -f ${SWIGOUTPUTDIR}/$$i.tmp ${SWIGOUTPUTDIR}/$$i; fi; done
+	# Following is to prevent Coverity Scan to warn about Dereference before null check (REVERSE_INULL)
+	for i in gdal_wrap.cpp gdalconst_wrap.c ogr_wrap.cpp osr_wrap.cpp gdal_array_wrap.cpp gnm_wrap.cpp; do if test -f ${SWIGOUTPUTDIR}/$$i; then sed "s/if (!PyTuple_Check(args)) SWIG_fail;/if (args == NULL || !PyTuple_Check(args)) SWIG_fail;/" ${SWIGOUTPUTDIR}/$$i | sed "s/argc = args ? (int)PyObject_Length(args) : 0/argc = (int)PyObject_Length(args)/" > ${SWIGOUTPUTDIR}/$$i.tmp; mv -f ${SWIGOUTPUTDIR}/$$i.tmp ${SWIGOUTPUTDIR}/$$i; fi; done
+	for i in gdal_wrap.cpp gdalconst_wrap.c ogr_wrap.cpp osr_wrap.cpp gdal_array_wrap.cpp gnm_wrap.cpp; do if test -f ${SWIGOUTPUTDIR}/$$i; then sed "s/if (SWIG_IsTmpObj(res\([1-9]\)))/if (ReturnSame(SWIG_IsTmpObj(res\1)))/" ${SWIGOUTPUTDIR}/$$i  > ${SWIGOUTPUTDIR}/$$i.tmp; mv -f ${SWIGOUTPUTDIR}/$$i.tmp ${SWIGOUTPUTDIR}/$$i; fi; done
+	for i in gdal_wrap.cpp gdalconst_wrap.c ogr_wrap.cpp osr_wrap.cpp gdal_array_wrap.cpp gnm_wrap.cpp; do if test -f ${SWIGOUTPUTDIR}/$$i; then sed "s/if( alloc\([1-9]\) == SWIG_NEWOBJ )/if (ReturnSame(alloc\1) == SWIG_NEWOBJ )/" ${SWIGOUTPUTDIR}/$$i  > ${SWIGOUTPUTDIR}/$$i.tmp; mv -f ${SWIGOUTPUTDIR}/$$i.tmp ${SWIGOUTPUTDIR}/$$i; fi; done
+	for i in gdal_wrap.cpp gdalconst_wrap.c ogr_wrap.cpp osr_wrap.cpp gdal_array_wrap.cpp gnm_wrap.cpp; do if test -f ${SWIGOUTPUTDIR}/$$i; then sed 's/strncpy(buff, "swig_ptr: ", 10)/memcpy(buff, "swig_ptr: ", 10)/' ${SWIGOUTPUTDIR}/$$i  > ${SWIGOUTPUTDIR}/$$i.tmp; mv -f ${SWIGOUTPUTDIR}/$$i.tmp ${SWIGOUTPUTDIR}/$$i; fi; done
+	# Only GNU sed accepts inserting newlines with \n. This is just to please Coverity, so no need to find a workaround
+	sed --version | grep GNU >/dev/null && (for i in gdal_wrap.cpp gdalconst_wrap.c ogr_wrap.cpp osr_wrap.cpp gnm_wrap.cpp; do if test -f ${SWIGOUTPUTDIR}/$$i; then sed "s/PyObject \*resultobj = 0;/PyObject \*resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;/" ${SWIGOUTPUTDIR}/$$i  | sed "s/#define SWIGPYTHON/#define SWIGPYTHON\n#define SED_HACKS/" | sed "s/return resultobj;/if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Fail [...]
+	# Unused assigned variable
+	for i in gdal_wrap.cpp gdalconst_wrap.c ogr_wrap.cpp osr_wrap.cpp gdal_array_wrap.cpp gnm_wrap.cpp; do if test -f ${SWIGOUTPUTDIR}/$$i; then sed 's/module_head = \&swig_module;/\/\*module_head = \&swig_module;\*\//' ${SWIGOUTPUTDIR}/$$i  > ${SWIGOUTPUTDIR}/$$i.tmp; mv -f ${SWIGOUTPUTDIR}/$$i.tmp ${SWIGOUTPUTDIR}/$$i; fi; done
+	for i in gdal_wrap.cpp; do sed 's/result = (CPLErr)\(.*\);/CPL_IGNORE_RET_VAL(result = (CPLErr)\1);/' ${SWIGOUTPUTDIR}/$$i  > ${SWIGOUTPUTDIR}/$$i.tmp; mv -f ${SWIGOUTPUTDIR}/$$i.tmp ${SWIGOUTPUTDIR}/$$i; done
 	-grep "1\.3\.40" extensions/gdal_wrap.cpp >/dev/null && patch -p0 < python3.2.patch
 	-grep "1\.3\.40" extensions/gdal_wrap.cpp >/dev/null && cat python3.2.patch | sed "s/gdal_wrap/ogr_wrap/" | patch -p0
 	-grep "1\.3\.40" extensions/gdal_wrap.cpp >/dev/null && cat python3.2.patch | sed "s/gdal_wrap/osr_wrap/" | patch -p0
 	-grep "1\.3\.40" extensions/gdal_wrap.cpp >/dev/null && cat python3.2.patch | sed "s/gdal_wrap\.cpp/gdalconst_wrap\.c/" | patch -p0
 	-grep "1\.3\.40" extensions/gdal_wrap.cpp >/dev/null && cat python3.2.patch | sed "s/gdal_wrap/gdal_array_wrap/" | patch -p0
-    
-build:
+
+build: extensions/gdal_wrap.cpp
+	rm -f setup_vars.ini
+	echo 'GNM_ENABLED=$(GNM_ENABLED)' >> setup_vars.ini
 	$(PYTHON) setup.py build
 
 egg:
 	$(PYTHON) setup.py bdist_egg 
-	
-install:
+
+site_package_dir=$(shell $(PYTHON) -c "from __future__ import print_function;from distutils.sysconfig import get_python_lib;print(get_python_lib(prefix=\"$(prefix)\"))")
 
 ifeq ($(PY_HAVE_SETUPTOOLS),1)
-	$(PYTHON) setup.py install 
+    setup_opts=--single-version-externally-managed --record=record.txt
+endif
+
+ifdef DESTDIR
+    setup_opts+=--root=$(DESTDIR)
+endif
+
+ifdef prefix
+    ifeq ($(shell uname),Darwin)
+        STD_UNIX_LAYOUT=$(shell $(PYTHON) -c "from __future__ import print_function;import sys;print(\"FALSE\" if \"framework\" in sys.prefix.lower() else \"TRUE\")")
+        ifeq ($(STD_UNIX_LAYOUT),"TRUE")
+            setup_opts+=--prefix=$(prefix)
+        else
+            ifdef PYTHON_INSTALL_LIB
+                setup_opts+=--install-lib=$(PYTHON_INSTALL_LIB)
+            endif
+        endif
+    else
+        setup_opts+=--prefix=$(prefix)
+    endif
+endif
+
+ifdef INSTALL_LAYOUT
+    setup_opts+=--install-layout=$(INSTALL_LAYOUT)
 else
-	$(PYTHON) setup.py install --prefix=$(DESTDIR)$(prefix)
+    ifneq ($(shell echo $(site_package_dir) | grep dist-packages),)
+        setup_opts+=--install-layout=deb
+    endif
 endif
 
+install:
+	@if [ ! -d $(site_package_dir) ]; then \
+		mkdir -p $(DESTDIR)$(site_package_dir); \
+		echo "----------------------------------------------------------------------";\
+		echo ""; \
+		echo "The GDAL python package has been installed in $(site_package_dir)"; \
+		echo "Please ensure to add $(site_package_dir) to your PYTHONPATH"; \
+		echo ""; \
+		echo "----------------------------------------------------------------------";\
+	fi
+	env PYTHONPATH=$(site_package_dir)$${PYTHONPATH:+:$$PYTHONPATH} \
+		$(PYTHON) setup.py install ${setup_opts}
 	for f in $(SCRIPTS) ; do $(INSTALL) ./scripts/$$f $(DESTDIR)$(INST_BIN) ; done
 
+# see swig/include/python/docs/README to refresh the  ../include/python/docs/ files
 docs:
-	$(PYTHON) ../include/python/docs/doxy2swig.py ../../ogr/xml/ogrlayer_8cpp.xml ../include/python/docs/ogr_layer_docs.i OGRLayerShadow OGR_L_
+	$(PYTHON) ../include/python/docs/doxy2swig.py ../../xml/ogrlayer_8cpp.xml ../include/python/docs/ogr_layer_docs.i OGRLayerShadow OGR_L_
 
-	$(PYTHON) ../include/python/docs/doxy2swig.py ../../ogr/xml/ogrgeometry_8cpp.xml ../include/python/docs/ogr_geometry_docs.i OGRGeometryShadow OGR_G_
+	$(PYTHON) ../include/python/docs/doxy2swig.py ../../xml/ogrgeometry_8cpp.xml ../include/python/docs/ogr_geometry_docs.i OGRGeometryShadow OGR_G_
 
-	$(PYTHON) ../include/python/docs/doxy2swig.py ../../ogr/xml/ogrdatasource_8cpp.xml ../include/python/docs/ogr_datasource_docs.i OGRDataSourceShadow OGR_DS_
+	$(PYTHON) ../include/python/docs/doxy2swig.py ../../xml/ogrdatasource_8cpp.xml ../include/python/docs/ogr_datasource_docs.i OGRDataSourceShadow OGR_DS_
 
 
-	$(PYTHON) ../include/python/docs/doxy2swig.py ../../ogr/xml/ogrsfdriver_8cpp.xml ../include/python/docs/ogr_driver_docs.i OGRDriverShadow OGR_Dr_
+	$(PYTHON) ../include/python/docs/doxy2swig.py ../../xml/ogrsfdriver_8cpp.xml ../include/python/docs/ogr_driver_docs.i OGRDriverShadow OGR_Dr_
 
-	$(PYTHON) ../include/python/docs/doxy2swig.py ../../ogr/xml/ogrfeature_8cpp.xml ../include/python/docs/ogr_feature_docs.i OGRFeatureShadow OGR_F_
+	$(PYTHON) ../include/python/docs/doxy2swig.py ../../xml/ogrfeature_8cpp.xml ../include/python/docs/ogr_feature_docs.i OGRFeatureShadow OGR_F_
 
-	$(PYTHON) ../include/python/docs/doxy2swig.py ../../ogr/xml/ogrfeaturedefn_8cpp.xml ../include/python/docs/ogr_featuredef_docs.i OGRFeatureDefnShadow OGR_FD_
+	$(PYTHON) ../include/python/docs/doxy2swig.py ../../xml/ogrfeaturedefn_8cpp.xml ../include/python/docs/ogr_featuredef_docs.i OGRFeatureDefnShadow OGR_FD_
 
-	$(PYTHON) ../include/python/docs/doxy2swig.py ../../ogr/xml/ogrfielddefn_8cpp.xml ../include/python/docs/ogr_fielddef_docs.i OGRFieldDefnShadow OGR_Fld_
+	$(PYTHON) ../include/python/docs/doxy2swig.py ../../xml/ogrfielddefn_8cpp.xml ../include/python/docs/ogr_fielddef_docs.i OGRFieldDefnShadow OGR_Fld_
 
 epydoc: generate
 	epydoc --config epydoc.conf
diff --git a/swig/python/README.txt b/swig/python/README.txt
index ef91d99..17ebafb 100644
--- a/swig/python/README.txt
+++ b/swig/python/README.txt
@@ -16,7 +16,7 @@ reference documentation, but the `GDAL API Tutorial`_ includes Python examples.
 Dependencies
 ------------
  
- * libgdal (2.0.0 or greater) and header files (gdal-devel)
+ * libgdal (1.11.0 or greater) and header files (gdal-devel)
  * numpy (1.0.0 or greater) and header files (numpy-devel) (not explicitly 
    required, but many examples and utilities will not work without it)
 
@@ -152,7 +152,7 @@ There are five major modules that are included with the GDAL_ Python bindings.::
 Additionally, there are five compatibility modules that are included but 
 provide notices to state that they are deprecated and will be going away.  
 If you are using GDAL 1.7 bindings, you should update your imports to utilize 
-the usage above, but the following will work until at least GDAL 2.0. ::
+the usage above, but the following will work until at least GDAL 2.1. ::
 
   >>> import gdal
   >>> import ogr
@@ -209,7 +209,7 @@ data, this approach is expected to be prohibitively memory intensive.
 
 .. _GDAL API Tutorial: http://www.gdal.org/gdal_tutorial.html
 .. _GDAL Windows Binaries: http://gisinternals.com/sdk/
-.. _Microsoft KnowledgeBase doc: http://support.microsoft.com/kb/310519
+.. _Microsoft Knowledge Base doc: http://support.microsoft.com/kb/310519
 .. _Python Cheeseshop: http://pypi.python.org/pypi/GDAL/
 .. _val_repl.py: http://trac.osgeo.org/gdal/browser/trunk/gdal/swig/python/samples/val_repl.py
 .. _GDAL: http://www.gdal.org
diff --git a/swig/python/extensions/gdal_array_wrap.cpp b/swig/python/extensions/gdal_array_wrap.cpp
index a0d3b30..25eaa8a 100644
--- a/swig/python/extensions/gdal_array_wrap.cpp
+++ b/swig/python/extensions/gdal_array_wrap.cpp
@@ -1,11 +1,11 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.40
- * 
- * This file is not intended to be easily readable and contains a number of 
+ * Version 2.0.12
+ *
+ * This file is not intended to be easily readable and contains a number of
  * coding conventions designed to improve portability and efficiency. Do not make
- * changes to this file unless you know what you are doing--modify the SWIG 
- * interface file instead. 
+ * changes to this file unless you know what you are doing--modify the SWIG
+ * interface file instead.
  * ----------------------------------------------------------------------------- */
 
 #define SWIGPYTHON
@@ -66,28 +66,28 @@ template <typename T> T SwigValueInit() {
 #ifndef SWIGUNUSED
 # if defined(__GNUC__)
 #   if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
-#     define SWIGUNUSED __attribute__ ((__unused__)) 
+#     define SWIGUNUSED __attribute__ ((__unused__))
 #   else
 #     define SWIGUNUSED
 #   endif
 # elif defined(__ICC)
-#   define SWIGUNUSED __attribute__ ((__unused__)) 
+#   define SWIGUNUSED __attribute__ ((__unused__))
 # else
-#   define SWIGUNUSED 
+#   define SWIGUNUSED
 # endif
 #endif
 
 #ifndef SWIG_MSC_UNSUPPRESS_4505
 # if defined(_MSC_VER)
 #   pragma warning(disable : 4505) /* unreferenced local function has been removed */
-# endif 
+# endif
 #endif
 
 #ifndef SWIGUNUSEDPARM
 # ifdef __cplusplus
 #   define SWIGUNUSEDPARM(p)
 # else
-#   define SWIGUNUSEDPARM(p) p SWIGUNUSED 
+#   define SWIGUNUSEDPARM(p) p SWIGUNUSED
 # endif
 #endif
 
@@ -130,7 +130,7 @@ template <typename T> T SwigValueInit() {
 #   define SWIGSTDCALL __stdcall
 # else
 #   define SWIGSTDCALL
-# endif 
+# endif
 #endif
 
 /* Deal with Microsoft's attempt at deprecating C standard runtime functions */
@@ -145,8 +145,14 @@ template <typename T> T SwigValueInit() {
 
 
 
-/* Python.h has to appear first */
-#include <Python.h>
+#if defined(_DEBUG) && defined(SWIG_PYTHON_INTERPRETER_NO_DEBUG)
+/* Use debug wrappers with the Python release dll */
+# undef _DEBUG
+# include <Python.h>
+# define _DEBUG
+#else
+# include <Python.h>
+#endif
 
 /* -----------------------------------------------------------------------------
  * swigrun.swg
@@ -172,7 +178,7 @@ template <typename T> T SwigValueInit() {
   You can use the SWIGRUNTIME and SWIGRUNTIMEINLINE macros for
   creating a static or dynamic library from the SWIG runtime code.
   In 99.9% of the cases, SWIG just needs to declare them as 'static'.
-  
+
   But only do this if strictly necessary, ie, if you have problems
   with your compiler or suchlike.
 */
@@ -198,16 +204,16 @@ template <typename T> T SwigValueInit() {
 #define SWIG_POINTER_OWN           0x1
 
 
-/* 
+/*
    Flags/methods for returning states.
-   
-   The SWIG conversion methods, as ConvertPtr, return and integer 
+
+   The SWIG conversion methods, as ConvertPtr, return an integer
    that tells if the conversion was successful or not. And if not,
    an error code can be returned (see swigerrors.swg for the codes).
-   
+
    Use the following macros/flags to set or process the returning
    states.
-   
+
    In old versions of SWIG, code such as the following was usually written:
 
      if (SWIG_ConvertPtr(obj,vptr,ty.flags) != -1) {
@@ -240,23 +246,23 @@ template <typename T> T SwigValueInit() {
     } else {
       // fail code
     }
-    
+
    I.e., now SWIG_ConvertPtr can return new objects and you can
    identify the case and take care of the deallocation. Of course that
    also requires SWIG_ConvertPtr to return new result values, such as
 
-      int SWIG_ConvertPtr(obj, ptr,...) {         
-        if (<obj is ok>) {			       
-          if (<need new object>) {		       
-            *ptr = <ptr to new allocated object>; 
-            return SWIG_NEWOBJ;		       
-          } else {				       
-            *ptr = <ptr to old object>;	       
-            return SWIG_OLDOBJ;		       
-          } 				       
-        } else {				       
-          return SWIG_BADOBJ;		       
-        }					       
+      int SWIG_ConvertPtr(obj, ptr,...) {
+        if (<obj is ok>) {
+          if (<need new object>) {
+            *ptr = <ptr to new allocated object>;
+            return SWIG_NEWOBJ;
+          } else {
+            *ptr = <ptr to old object>;
+            return SWIG_OLDOBJ;
+          }
+        } else {
+          return SWIG_BADOBJ;
+        }
       }
 
    Of course, returning the plain '0(success)/-1(fail)' still works, but you can be
@@ -270,17 +276,17 @@ template <typename T> T SwigValueInit() {
        int fooi(int);
 
    and you call
- 
+
       food(1)   // cast rank '1'  (1 -> 1.0)
       fooi(1)   // cast rank '0'
 
    just use the SWIG_AddCast()/SWIG_CheckState()
 */
 
-#define SWIG_OK                    (0) 
+#define SWIG_OK                    (0)
 #define SWIG_ERROR                 (-1)
 #define SWIG_IsOK(r)               (r >= 0)
-#define SWIG_ArgError(r)           ((r != SWIG_ERROR) ? r : SWIG_TypeError)  
+#define SWIG_ArgError(r)           ((r != SWIG_ERROR) ? r : SWIG_TypeError)
 
 /* The CastRankLimit says how many bits are used for the cast rank */
 #define SWIG_CASTRANKLIMIT         (1 << 8)
@@ -311,14 +317,14 @@ template <typename T> T SwigValueInit() {
 #  endif
 #  define SWIG_CASTRANKMASK          ((SWIG_CASTRANKLIMIT) -1)
 #  define SWIG_CastRank(r)           (r & SWIG_CASTRANKMASK)
-SWIGINTERNINLINE int SWIG_AddCast(int r) { 
+SWIGINTERNINLINE int SWIG_AddCast(int r) {
   return SWIG_IsOK(r) ? ((SWIG_CastRank(r) < SWIG_MAXCASTRANK) ? (r + 1) : SWIG_ERROR) : r;
 }
-SWIGINTERNINLINE int SWIG_CheckState(int r) { 
-  return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0; 
+SWIGINTERNINLINE int SWIG_CheckState(int r) {
+  return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0;
 }
 #else /* no cast-rank mode */
-#  define SWIG_AddCast
+#  define SWIG_AddCast(r) (r)
 #  define SWIG_CheckState(r) (SWIG_IsOK(r) ? 1 : 0)
 #endif
 
@@ -362,7 +368,7 @@ typedef struct swig_module_info {
   void                    *clientdata;		/* Language specific module data */
 } swig_module_info;
 
-/* 
+/*
   Compare two type names skipping the space characters, therefore
   "char*" == "char *" and "Class<int>" == "Class<int >", etc.
 
@@ -382,18 +388,18 @@ SWIG_TypeNameComp(const char *f1, const char *l1,
 
 /*
   Check type equivalence in a name list like <name1>|<name2>|...
-  Return 0 if not equal, 1 if equal
+  Return 0 if equal, -1 if nb < tb, 1 if nb > tb
 */
 SWIGRUNTIME int
-SWIG_TypeEquiv(const char *nb, const char *tb) {
-  int equiv = 0;
+SWIG_TypeCmp(const char *nb, const char *tb) {
+  int equiv = 1;
   const char* te = tb + strlen(tb);
   const char* ne = nb;
-  while (!equiv && *ne) {
+  while (equiv != 0 && *ne) {
     for (nb = ne; *ne; ++ne) {
       if (*ne == '|') break;
     }
-    equiv = (SWIG_TypeNameComp(nb, ne, tb, te) == 0) ? 1 : 0;
+    equiv = SWIG_TypeNameComp(nb, ne, tb, te);
     if (*ne) ++ne;
   }
   return equiv;
@@ -401,24 +407,13 @@ SWIG_TypeEquiv(const char *nb, const char *tb) {
 
 /*
   Check type equivalence in a name list like <name1>|<name2>|...
-  Return 0 if equal, -1 if nb < tb, 1 if nb > tb
+  Return 0 if not equal, 1 if equal
 */
 SWIGRUNTIME int
-SWIG_TypeCompare(const char *nb, const char *tb) {
-  int equiv = 0;
-  const char* te = tb + strlen(tb);
-  const char* ne = nb;
-  while (!equiv && *ne) {
-    for (nb = ne; *ne; ++ne) {
-      if (*ne == '|') break;
-    }
-    equiv = (SWIG_TypeNameComp(nb, ne, tb, te) == 0) ? 1 : 0;
-    if (*ne) ++ne;
-  }
-  return equiv;
+SWIG_TypeEquiv(const char *nb, const char *tb) {
+  return SWIG_TypeCmp(nb, tb) == 0 ? 1 : 0;
 }
 
-
 /*
   Check the typename
 */
@@ -446,7 +441,7 @@ SWIG_TypeCheck(const char *c, swig_type_info *ty) {
   return 0;
 }
 
-/* 
+/*
   Identical to SWIG_TypeCheck, except strcmp is replaced with a pointer comparison
 */
 SWIGRUNTIME swig_cast_info *
@@ -481,7 +476,7 @@ SWIG_TypeCast(swig_cast_info *ty, void *ptr, int *newmemory) {
   return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr, newmemory);
 }
 
-/* 
+/*
    Dynamic pointer casting. Down an inheritance hierarchy
 */
 SWIGRUNTIME swig_type_info *
@@ -525,7 +520,7 @@ SWIG_TypePrettyName(const swig_type_info *type) {
     return type->name;
 }
 
-/* 
+/*
    Set the clientdata field for a type
 */
 SWIGRUNTIME void
@@ -533,14 +528,14 @@ SWIG_TypeClientData(swig_type_info *ti, void *clientdata) {
   swig_cast_info *cast = ti->cast;
   /* if (ti->clientdata == clientdata) return; */
   ti->clientdata = clientdata;
-  
+
   while (cast) {
     if (!cast->converter) {
       swig_type_info *tc = cast->type;
       if (!tc->clientdata) {
 	SWIG_TypeClientData(tc, clientdata);
       }
-    }    
+    }
     cast = cast->next;
   }
 }
@@ -549,18 +544,18 @@ SWIG_TypeNewClientData(swig_type_info *ti, void *clientdata) {
   SWIG_TypeClientData(ti, clientdata);
   ti->owndata = 1;
 }
-  
+
 /*
   Search for a swig_type_info structure only by mangled name
   Search is a O(log #types)
-  
-  We start searching at module start, and finish searching when start == end.  
+
+  We start searching at module start, and finish searching when start == end.
   Note: if start == end at the beginning of the function, we go all the way around
   the circular list.
 */
 SWIGRUNTIME swig_type_info *
-SWIG_MangledTypeQueryModule(swig_module_info *start, 
-                            swig_module_info *end, 
+SWIG_MangledTypeQueryModule(swig_module_info *start,
+                            swig_module_info *end,
 		            const char *name) {
   swig_module_info *iter = start;
   do {
@@ -569,11 +564,11 @@ SWIG_MangledTypeQueryModule(swig_module_info *start,
       register size_t r = iter->size - 1;
       do {
 	/* since l+r >= 0, we can (>> 1) instead (/ 2) */
-	register size_t i = (l + r) >> 1; 
+	register size_t i = (l + r) >> 1;
 	const char *iname = iter->types[i]->name;
 	if (iname) {
 	  register int compare = strcmp(name, iname);
-	  if (compare == 0) {	    
+	  if (compare == 0) {
 	    return iter->types[i];
 	  } else if (compare < 0) {
 	    if (i) {
@@ -598,14 +593,14 @@ SWIG_MangledTypeQueryModule(swig_module_info *start,
   Search for a swig_type_info structure for either a mangled name or a human readable name.
   It first searches the mangled names of the types, which is a O(log #types)
   If a type is not found it then searches the human readable names, which is O(#types).
-  
-  We start searching at module start, and finish searching when start == end.  
+
+  We start searching at module start, and finish searching when start == end.
   Note: if start == end at the beginning of the function, we go all the way around
   the circular list.
 */
 SWIGRUNTIME swig_type_info *
-SWIG_TypeQueryModule(swig_module_info *start, 
-                     swig_module_info *end, 
+SWIG_TypeQueryModule(swig_module_info *start,
+                     swig_module_info *end,
 		     const char *name) {
   /* STEP 1: Search the name field using binary search */
   swig_type_info *ret = SWIG_MangledTypeQueryModule(start, end, name);
@@ -624,12 +619,12 @@ SWIG_TypeQueryModule(swig_module_info *start,
       iter = iter->next;
     } while (iter != end);
   }
-  
+
   /* neither found a match */
   return 0;
 }
 
-/* 
+/*
    Pack binary data into a string
 */
 SWIGRUNTIME char *
@@ -645,7 +640,7 @@ SWIG_PackData(char *c, void *ptr, size_t sz) {
   return c;
 }
 
-/* 
+/*
    Unpack binary data from a string
 */
 SWIGRUNTIME const char *
@@ -659,21 +654,21 @@ SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
       uu = ((d - '0') << 4);
     else if ((d >= 'a') && (d <= 'f'))
       uu = ((d - ('a'-10)) << 4);
-    else 
+    else
       return (char *) 0;
     d = *(c++);
     if ((d >= '0') && (d <= '9'))
       uu |= (d - '0');
     else if ((d >= 'a') && (d <= 'f'))
       uu |= (d - ('a'-10));
-    else 
+    else
       return (char *) 0;
     *u = uu;
   }
   return c;
 }
 
-/* 
+/*
    Pack 'void *' into a string buffer.
 */
 SWIGRUNTIME char *
@@ -733,18 +728,18 @@ SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) {
 #endif
 
 /*  Errors in SWIG */
-#define  SWIG_UnknownError    	   -1 
-#define  SWIG_IOError        	   -2 
-#define  SWIG_RuntimeError   	   -3 
-#define  SWIG_IndexError     	   -4 
-#define  SWIG_TypeError      	   -5 
-#define  SWIG_DivisionByZero 	   -6 
-#define  SWIG_OverflowError  	   -7 
-#define  SWIG_SyntaxError    	   -8 
-#define  SWIG_ValueError     	   -9 
+#define  SWIG_UnknownError    	   -1
+#define  SWIG_IOError        	   -2
+#define  SWIG_RuntimeError   	   -3
+#define  SWIG_IndexError     	   -4
+#define  SWIG_TypeError      	   -5
+#define  SWIG_DivisionByZero 	   -6
+#define  SWIG_OverflowError  	   -7
+#define  SWIG_SyntaxError    	   -8
+#define  SWIG_ValueError     	   -9
 #define  SWIG_SystemError    	   -10
 #define  SWIG_AttributeError 	   -11
-#define  SWIG_MemoryError    	   -12 
+#define  SWIG_MemoryError    	   -12
 #define  SWIG_NullReferenceError   -13
 
 
@@ -756,7 +751,16 @@ SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) {
 #define PyInt_Check(x) PyLong_Check(x)
 #define PyInt_AsLong(x) PyLong_AsLong(x)
 #define PyInt_FromLong(x) PyLong_FromLong(x)
+#define PyInt_FromSize_t(x) PyLong_FromSize_t(x)
+#define PyString_Check(name) PyBytes_Check(name)
+#define PyString_FromString(x) PyUnicode_FromString(x)
 #define PyString_Format(fmt, args)  PyUnicode_Format(fmt, args)
+#define PyString_AsString(str) PyBytes_AsString(str)
+#define PyString_Size(str) PyBytes_Size(str)	
+#define PyString_InternFromString(key) PyUnicode_InternFromString(key)
+#define Py_TPFLAGS_HAVE_CLASS Py_TPFLAGS_BASETYPE
+#define PyString_AS_STRING(x) PyUnicode_AS_STRING(x)
+#define _PyLong_FromSsize_t(x) PyLong_FromSsize_t(x)
 
 #endif
 
@@ -896,6 +900,67 @@ PyObject *PyBool_FromLong(long ok)
 typedef int Py_ssize_t;
 # define PY_SSIZE_T_MAX INT_MAX
 # define PY_SSIZE_T_MIN INT_MIN
+typedef inquiry lenfunc;
+typedef intargfunc ssizeargfunc;
+typedef intintargfunc ssizessizeargfunc;
+typedef intobjargproc ssizeobjargproc;
+typedef intintobjargproc ssizessizeobjargproc;
+typedef getreadbufferproc readbufferproc;
+typedef getwritebufferproc writebufferproc;
+typedef getsegcountproc segcountproc;
+typedef getcharbufferproc charbufferproc;
+static long PyNumber_AsSsize_t (PyObject *x, void *SWIGUNUSEDPARM(exc))
+{
+  long result = 0;
+  PyObject *i = PyNumber_Int(x);
+  if (i) {
+    result = PyInt_AsLong(i);
+    Py_DECREF(i);
+  }
+  return result;
+}
+#endif
+
+#if PY_VERSION_HEX < 0x02050000
+#define PyInt_FromSize_t(x) PyInt_FromLong((long)x)
+#endif
+
+#if PY_VERSION_HEX < 0x02040000
+#define Py_VISIT(op)				\
+  do { 						\
+    if (op) {					\
+      int vret = visit((op), arg);		\
+      if (vret)					\
+        return vret;				\
+    }						\
+  } while (0)
+#endif
+
+#if PY_VERSION_HEX < 0x02030000
+typedef struct {
+  PyTypeObject type;
+  PyNumberMethods as_number;
+  PyMappingMethods as_mapping;
+  PySequenceMethods as_sequence;
+  PyBufferProcs as_buffer;
+  PyObject *name, *slots;
+} PyHeapTypeObject;
+#endif
+
+#if PY_VERSION_HEX < 0x02030000
+typedef destructor freefunc;
+#endif
+
+#if ((PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 6) || \
+     (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION > 0) || \
+     (PY_MAJOR_VERSION > 3))
+# define SWIGPY_USE_CAPSULE
+# define SWIGPY_CAPSULE_NAME ((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer_capsule" SWIG_TYPE_TABLE_NAME)
+#endif
+
+#if PY_VERSION_HEX < 0x03020000
+#define PyDescr_TYPE(x) (((PyDescrObject *)(x))->d_type)
+#define PyDescr_NAME(x) (((PyDescrObject *)(x))->d_name)
 #endif
 
 /* -----------------------------------------------------------------------------
@@ -1042,9 +1107,6 @@ SWIG_Python_AddErrorMsg(const char* mesg)
 
 #ifdef __cplusplus
 extern "C" {
-#if 0
-} /* cc-mode */
-#endif
 #endif
 
 /* -----------------------------------------------------------------------------
@@ -1070,27 +1132,24 @@ typedef struct swig_const_info {
  * Wrapper of PyInstanceMethod_New() used in Python 3
  * It is exported to the generated module, used for -fastproxy
  * ----------------------------------------------------------------------------- */
-SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func)
-{
 #if PY_VERSION_HEX >= 0x03000000
+SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *func)
+{
   return PyInstanceMethod_New(func);
+}
 #else
+SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *SWIGUNUSEDPARM(func))
+{
   return NULL;
-#endif
 }
+#endif
 
 #ifdef __cplusplus
-#if 0
-{ /* cc-mode */
-#endif
 }
 #endif
 
 
 /* -----------------------------------------------------------------------------
- * See the LICENSE file for information on copyright, usage and redistribution
- * of SWIG, and the README file for authors - http://www.swig.org/release.html.
- *
  * pyrun.swg
  *
  * This file contains the runtime support for Python modules
@@ -1105,7 +1164,15 @@ SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func)
 #define SWIG_Python_ConvertPtr(obj, pptr, type, flags)  SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, 0)
 #define SWIG_ConvertPtr(obj, pptr, type, flags)         SWIG_Python_ConvertPtr(obj, pptr, type, flags)
 #define SWIG_ConvertPtrAndOwn(obj,pptr,type,flags,own)  SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, own)
-#define SWIG_NewPointerObj(ptr, type, flags)            SWIG_Python_NewPointerObj(ptr, type, flags)
+
+#ifdef SWIGPYTHON_BUILTIN
+#define SWIG_NewPointerObj(ptr, type, flags)            SWIG_Python_NewPointerObj(self, ptr, type, flags)
+#else
+#define SWIG_NewPointerObj(ptr, type, flags)            SWIG_Python_NewPointerObj(NULL, ptr, type, flags)
+#endif
+
+#define SWIG_InternalNewPointerObj(ptr, type, flags)	SWIG_Python_NewPointerObj(NULL, ptr, type, flags)
+
 #define SWIG_CheckImplicit(ty)                          SWIG_Python_CheckImplicit(ty) 
 #define SWIG_AcquirePtr(ptr, src)                       SWIG_Python_AcquirePtr(ptr, src)
 #define swig_owntype                                    int
@@ -1120,7 +1187,7 @@ SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func)
 
 /* for C or C++ function pointers */
 #define SWIG_ConvertFunctionPtr(obj, pptr, type)        SWIG_Python_ConvertFunctionPtr(obj, pptr, type)
-#define SWIG_NewFunctionPtrObj(ptr, type)               SWIG_Python_NewPointerObj(ptr, type, 0)
+#define SWIG_NewFunctionPtrObj(ptr, type)               SWIG_Python_NewPointerObj(NULL, ptr, type, 0)
 
 /* for C++ member pointers, ie, member methods */
 #define SWIG_ConvertMember(obj, ptr, sz, ty)            SWIG_Python_ConvertPacked(obj, ptr, sz, ty)
@@ -1129,11 +1196,7 @@ SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func)
 
 /* Runtime API */
 
-#if PY_VERSION_HEX >= 0x03020000
-#define SWIG_PYTHON_USE_CAPSULE
-#endif
-
-#define SWIG_GetModule(clientdata)                      SWIG_Python_GetModule()
+#define SWIG_GetModule(clientdata)                      SWIG_Python_GetModule(clientdata)
 #define SWIG_SetModule(clientdata, pointer)             SWIG_Python_SetModule(pointer)
 #define SWIG_NewClientData(obj)                         SwigPyClientData_New(obj)
 
@@ -1159,7 +1222,7 @@ SWIG_Python_SetErrorObj(PyObject *errtype, PyObject *obj) {
 SWIGINTERN void 
 SWIG_Python_SetErrorMsg(PyObject *errtype, const char *msg) {
   SWIG_PYTHON_THREAD_BEGIN_BLOCK;
-  PyErr_SetString(errtype, (char *) msg);
+  PyErr_SetString(errtype, msg);
   SWIG_PYTHON_THREAD_END_BLOCK;
 }
 
@@ -1167,12 +1230,41 @@ SWIG_Python_SetErrorMsg(PyObject *errtype, const char *msg) {
 
 /* Set a constant value */
 
+#if defined(SWIGPYTHON_BUILTIN)
+
+SWIGINTERN void
+SwigPyBuiltin_AddPublicSymbol(PyObject *seq, const char *key) {
+  PyObject *s = PyString_InternFromString(key);
+  PyList_Append(seq, s);
+  Py_DECREF(s);
+}
+
+SWIGINTERN void
+SWIG_Python_SetConstant(PyObject *d, PyObject *public_interface, const char *name, PyObject *obj) {   
+#if PY_VERSION_HEX < 0x02030000
+  PyDict_SetItemString(d, (char *)name, obj);
+#else
+  PyDict_SetItemString(d, name, obj);
+#endif
+  Py_DECREF(obj);
+  if (public_interface)
+    SwigPyBuiltin_AddPublicSymbol(public_interface, name);
+}
+
+#else
+
 SWIGINTERN void
 SWIG_Python_SetConstant(PyObject *d, const char *name, PyObject *obj) {   
-  PyDict_SetItemString(d, (char*) name, obj);
+#if PY_VERSION_HEX < 0x02030000
+  PyDict_SetItemString(d, (char *)name, obj);
+#else
+  PyDict_SetItemString(d, name, obj);
+#endif
   Py_DECREF(obj);                            
 }
 
+#endif
+
 /* Append a value to the result obj */
 
 SWIGINTERN PyObject*
@@ -1233,6 +1325,14 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi
     }
   }  
   if (!PyTuple_Check(args)) {
+    if (min <= 1 && max >= 1) {
+      register int i;
+      objs[0] = args;
+      for (i = 1; i < max; ++i) {
+	objs[i] = 0;
+      }
+      return 2;
+    }
     PyErr_SetString(PyExc_SystemError, "UnpackTuple() argument list is not a tuple");
     return 0;
   } else {
@@ -1285,11 +1385,11 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi
 
 #define SWIG_POINTER_IMPLICIT_CONV  (SWIG_POINTER_DISOWN   << 1)
 
+#define SWIG_BUILTIN_TP_INIT	    (SWIG_POINTER_OWN << 2)
+#define SWIG_BUILTIN_INIT	    (SWIG_BUILTIN_TP_INIT | SWIG_POINTER_OWN)
+
 #ifdef __cplusplus
 extern "C" {
-#if 0
-} /* cc-mode */
-#endif
 #endif
 
 /*  How to access Py_None */
@@ -1340,6 +1440,7 @@ typedef struct {
   PyObject *destroy;
   int delargs;
   int implicitconv;
+  PyTypeObject *pytype;
 } SwigPyClientData;
 
 SWIGRUNTIMEINLINE int 
@@ -1406,13 +1507,13 @@ SwigPyClientData_New(PyObject* obj)
       data->delargs = 0;
     }
     data->implicitconv = 0;
+    data->pytype = 0;
     return data;
   }
 }
 
 SWIGRUNTIME void 
-SwigPyClientData_Del(SwigPyClientData* data)
-{
+SwigPyClientData_Del(SwigPyClientData *data) {
   Py_XDECREF(data->newraw);
   Py_XDECREF(data->newargs);
   Py_XDECREF(data->destroy);
@@ -1426,6 +1527,9 @@ typedef struct {
   swig_type_info *ty;
   int own;
   PyObject *next;
+#ifdef SWIGPYTHON_BUILTIN
+  PyObject *dict;
+#endif
 } SwigPyObject;
 
 SWIGRUNTIME PyObject *
@@ -1476,54 +1580,26 @@ SwigPyObject_repr(SwigPyObject *v, PyObject *args)
 #endif
 {
   const char *name = SWIG_TypePrettyName(v->ty);
-  PyObject *repr = SWIG_Python_str_FromFormat("<Swig Object of type '%s' at %p>", name, v);
+  PyObject *repr = SWIG_Python_str_FromFormat("<Swig Object of type '%s' at %p>", (name ? name : "unknown"), (void *)v);
   if (v->next) {
-#ifdef METH_NOARGS
+# ifdef METH_NOARGS
     PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next);
-#else
+# else
     PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next, args);
-#endif
-#if PY_VERSION_HEX >= 0x03000000
+# endif
+# if PY_VERSION_HEX >= 0x03000000
     PyObject *joined = PyUnicode_Concat(repr, nrep);
     Py_DecRef(repr);
     Py_DecRef(nrep);
     repr = joined;
-#else
+# else
     PyString_ConcatAndDel(&repr,nrep);
-#endif
+# endif
   }
   return repr;  
 }
 
 SWIGRUNTIME int
-SwigPyObject_print(SwigPyObject *v, FILE *fp, int SWIGUNUSEDPARM(flags))
-{
-  char *str;
-#ifdef METH_NOARGS
-  PyObject *repr = SwigPyObject_repr(v);
-#else
-  PyObject *repr = SwigPyObject_repr(v, NULL);
-#endif
-  if (repr) {
-    str = SWIG_Python_str_AsChar(repr); 
-    fputs(str, fp);
-    SWIG_Python_str_DelForPy3(str);
-    Py_DECREF(repr);
-    return 0; 
-  } else {
-    return 1; 
-  }
-}
-
-SWIGRUNTIME PyObject *
-SwigPyObject_str(SwigPyObject *v)
-{
-  char result[SWIG_BUFFER_SIZE];
-  return SWIG_PackVoidPtr(result, v->ptr, v->ty->name, sizeof(result)) ?
-    SWIG_Python_str_FromChar(result) : 0;
-}
-
-SWIGRUNTIME int
 SwigPyObject_compare(SwigPyObject *v, SwigPyObject *w)
 {
   void *i = v->ptr;
@@ -1540,27 +1616,43 @@ SwigPyObject_richcompare(SwigPyObject *v, SwigPyObject *w, int op)
     Py_INCREF(Py_NotImplemented);
     return Py_NotImplemented;
   }
-  if( (SwigPyObject_compare(v, w)==0) == (op == Py_EQ) )
-    res = Py_True;
-  else
-    res = Py_False;
-  Py_INCREF(res);
+  res = PyBool_FromLong( (SwigPyObject_compare(v, w)==0) == (op == Py_EQ) ? 1 : 0);
   return res;  
 }
 
 
-SWIGRUNTIME PyTypeObject* _PySwigObject_type(void);
+SWIGRUNTIME PyTypeObject* SwigPyObject_TypeOnce(void);
 
+#ifdef SWIGPYTHON_BUILTIN
+static swig_type_info *SwigPyObject_stype = 0;
 SWIGRUNTIME PyTypeObject*
 SwigPyObject_type(void) {
-  static PyTypeObject *SWIG_STATIC_POINTER(type) = _PySwigObject_type();
+    SwigPyClientData *cd;
+    assert(SwigPyObject_stype);
+    cd = (SwigPyClientData*) SwigPyObject_stype->clientdata;
+    assert(cd);
+    assert(cd->pytype);
+    return cd->pytype;
+}
+#else
+SWIGRUNTIME PyTypeObject*
+SwigPyObject_type(void) {
+  static PyTypeObject *SWIG_STATIC_POINTER(type) = SwigPyObject_TypeOnce();
   return type;
 }
+#endif
 
 SWIGRUNTIMEINLINE int
 SwigPyObject_Check(PyObject *op) {
+#ifdef SWIGPYTHON_BUILTIN
+  PyTypeObject *target_tp = SwigPyObject_type();
+  if (PyType_IsSubtype(op->ob_type, target_tp))
+    return 1;
+  return (strcmp(op->ob_type->tp_name, "SwigPyObject") == 0);
+#else
   return (Py_TYPE(op) == SwigPyObject_type())
     || (strcmp(Py_TYPE(op)->tp_name,"SwigPyObject") == 0);
+#endif
 }
 
 SWIGRUNTIME PyObject *
@@ -1664,8 +1756,10 @@ SwigPyObject_own(PyObject *v, PyObject *args)
   PyObject *val = 0;
 #if (PY_VERSION_HEX < 0x02020000)
   if (!PyArg_ParseTuple(args,(char *)"|O:own",&val))
-#else
+#elif (PY_VERSION_HEX < 0x02050000)
   if (!PyArg_UnpackTuple(args, (char *)"own", 0, 1, &val)) 
+#else
+  if (!PyArg_UnpackTuple(args, "own", 0, 1, &val)) 
 #endif
     {
       return NULL;
@@ -1697,7 +1791,7 @@ SwigPyObject_own(PyObject *v, PyObject *args)
 static PyMethodDef
 swigobject_methods[] = {
   {(char *)"disown",  (PyCFunction)SwigPyObject_disown,  METH_NOARGS,  (char *)"releases ownership of the pointer"},
-  {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_NOARGS,  (char *)"aquires ownership of the pointer"},
+  {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_NOARGS,  (char *)"acquires ownership of the pointer"},
   {(char *)"own",     (PyCFunction)SwigPyObject_own,     METH_VARARGS, (char *)"returns/sets ownership of the pointer"},
   {(char *)"append",  (PyCFunction)SwigPyObject_append,  METH_O,       (char *)"appends another 'this' object"},
   {(char *)"next",    (PyCFunction)SwigPyObject_next,    METH_NOARGS,  (char *)"returns the next 'this' object"},
@@ -1726,9 +1820,9 @@ SwigPyObject_getattr(SwigPyObject *sobj,char *name)
 #endif
 
 SWIGRUNTIME PyTypeObject*
-_PySwigObject_type(void) {
+SwigPyObject_TypeOnce(void) {
   static char swigobject_doc[] = "Swig object carries a C/C++ instance pointer";
-  
+
   static PyNumberMethods SwigPyObject_as_number = {
     (binaryfunc)0, /*nb_add*/
     (binaryfunc)0, /*nb_subtract*/
@@ -1775,85 +1869,89 @@ _PySwigObject_type(void) {
 #endif
   };
 
-  static PyTypeObject swigpyobject_type;  
+  static PyTypeObject swigpyobject_type;
   static int type_init = 0;
   if (!type_init) {
-    const PyTypeObject tmp
-      = {
-	/* PyObject header changed in Python 3 */
+    const PyTypeObject tmp = {
+      /* PyObject header changed in Python 3 */
 #if PY_VERSION_HEX >= 0x03000000
-	PyVarObject_HEAD_INIT(&PyType_Type, 0)
-#else    
-	PyObject_HEAD_INIT(NULL)
-	0,				    /* ob_size */
-#endif
-	(char *)"SwigPyObject",		    /* tp_name */
-	sizeof(SwigPyObject),		    /* tp_basicsize */
-	0,			            /* tp_itemsize */
-	(destructor)SwigPyObject_dealloc,   /* tp_dealloc */
-	(printfunc)SwigPyObject_print,	    /* tp_print */
+      PyVarObject_HEAD_INIT(NULL, 0)
+#else
+      PyObject_HEAD_INIT(NULL)
+      0,                                    /* ob_size */
+#endif
+      (char *)"SwigPyObject",               /* tp_name */
+      sizeof(SwigPyObject),                 /* tp_basicsize */
+      0,                                    /* tp_itemsize */
+      (destructor)SwigPyObject_dealloc,     /* tp_dealloc */
+      0,				    /* tp_print */
 #if PY_VERSION_HEX < 0x02020000
-	(getattrfunc)SwigPyObject_getattr,  /* tp_getattr */ 
+      (getattrfunc)SwigPyObject_getattr,    /* tp_getattr */
 #else
-	(getattrfunc)0,			    /* tp_getattr */ 
+      (getattrfunc)0,                       /* tp_getattr */
 #endif
-	(setattrfunc)0,			    /* tp_setattr */ 
+      (setattrfunc)0,                       /* tp_setattr */
 #if PY_VERSION_HEX >= 0x03000000
     0, /* tp_reserved in 3.0.1, tp_compare in 3.0.0 but not used */
 #else
-	(cmpfunc)SwigPyObject_compare,	    /* tp_compare */
-#endif
-	(reprfunc)SwigPyObject_repr,	    /* tp_repr */    
-	&SwigPyObject_as_number,	    /* tp_as_number */
-	0,				    /* tp_as_sequence */
-	0,				    /* tp_as_mapping */
-	(hashfunc)0,			    /* tp_hash */
-	(ternaryfunc)0,			    /* tp_call */
-	(reprfunc)SwigPyObject_str,	    /* tp_str */
-	PyObject_GenericGetAttr,            /* tp_getattro */
-	0,				    /* tp_setattro */
-	0,		                    /* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT,	            /* tp_flags */
-	swigobject_doc, 	            /* tp_doc */        
-	0,                                  /* tp_traverse */
-	0,                                  /* tp_clear */
-	(richcmpfunc)SwigPyObject_richcompare,           /* tp_richcompare */
-	0,                                  /* tp_weaklistoffset */
+      (cmpfunc)SwigPyObject_compare,        /* tp_compare */
+#endif
+      (reprfunc)SwigPyObject_repr,          /* tp_repr */
+      &SwigPyObject_as_number,              /* tp_as_number */
+      0,                                    /* tp_as_sequence */
+      0,                                    /* tp_as_mapping */
+      (hashfunc)0,                          /* tp_hash */
+      (ternaryfunc)0,                       /* tp_call */
+      0,				    /* tp_str */
+      PyObject_GenericGetAttr,              /* tp_getattro */
+      0,                                    /* tp_setattro */
+      0,                                    /* tp_as_buffer */
+      Py_TPFLAGS_DEFAULT,                   /* tp_flags */
+      swigobject_doc,                       /* tp_doc */
+      0,                                    /* tp_traverse */
+      0,                                    /* tp_clear */
+      (richcmpfunc)SwigPyObject_richcompare,/* tp_richcompare */
+      0,                                    /* tp_weaklistoffset */
 #if PY_VERSION_HEX >= 0x02020000
-	0,                                  /* tp_iter */
-	0,                                  /* tp_iternext */
-	swigobject_methods,		    /* tp_methods */ 
-	0,			            /* tp_members */
-	0,				    /* tp_getset */	    	
-	0,			            /* tp_base */	        
-	0,				    /* tp_dict */	    	
-	0,				    /* tp_descr_get */  	
-	0,				    /* tp_descr_set */  	
-	0,				    /* tp_dictoffset */ 	
-	0,				    /* tp_init */	    	
-	0,				    /* tp_alloc */	    	
-	0,			            /* tp_new */	    	
-	0,	                            /* tp_free */	   
-	0,                                  /* tp_is_gc */  
-	0,				    /* tp_bases */   
-	0,				    /* tp_mro */
-	0,				    /* tp_cache */   
-	0,				    /* tp_subclasses */
-	0,				    /* tp_weaklist */
+      0,                                    /* tp_iter */
+      0,                                    /* tp_iternext */
+      swigobject_methods,                   /* tp_methods */
+      0,                                    /* tp_members */
+      0,                                    /* tp_getset */
+      0,                                    /* tp_base */
+      0,                                    /* tp_dict */
+      0,                                    /* tp_descr_get */
+      0,                                    /* tp_descr_set */
+      0,                                    /* tp_dictoffset */
+      0,                                    /* tp_init */
+      0,                                    /* tp_alloc */
+      0,                                    /* tp_new */
+      0,                                    /* tp_free */
+      0,                                    /* tp_is_gc */
+      0,                                    /* tp_bases */
+      0,                                    /* tp_mro */
+      0,                                    /* tp_cache */
+      0,                                    /* tp_subclasses */
+      0,                                    /* tp_weaklist */
 #endif
 #if PY_VERSION_HEX >= 0x02030000
-	0,                                  /* tp_del */
+      0,                                    /* tp_del */
+#endif
+#if PY_VERSION_HEX >= 0x02060000
+      0,                                    /* tp_version */
 #endif
 #ifdef COUNT_ALLOCS
-	0,0,0,0                             /* tp_alloc -> tp_next */
+      0,0,0,0                               /* tp_alloc -> tp_next */
 #endif
-      };
+    };
     swigpyobject_type = tmp;
-    /* for Python 3 we already assigned ob_type in PyVarObject_HEAD_INIT() */
-#if PY_VERSION_HEX < 0x03000000
+    type_init = 1;
+#if PY_VERSION_HEX < 0x02020000
     swigpyobject_type.ob_type = &PyType_Type;
+#else
+    if (PyType_Ready(&swigpyobject_type) < 0)
+      return NULL;
 #endif
-    type_init = 1;
   }
   return &swigpyobject_type;
 }
@@ -1927,17 +2025,17 @@ SwigPyPacked_compare(SwigPyPacked *v, SwigPyPacked *w)
   return s ? s : strncmp((char *)v->pack, (char *)w->pack, 2*v->size);
 }
 
-SWIGRUNTIME PyTypeObject* _PySwigPacked_type(void);
+SWIGRUNTIME PyTypeObject* SwigPyPacked_TypeOnce(void);
 
 SWIGRUNTIME PyTypeObject*
 SwigPyPacked_type(void) {
-  static PyTypeObject *SWIG_STATIC_POINTER(type) = _PySwigPacked_type();
+  static PyTypeObject *SWIG_STATIC_POINTER(type) = SwigPyPacked_TypeOnce();
   return type;
 }
 
 SWIGRUNTIMEINLINE int
 SwigPyPacked_Check(PyObject *op) {
-  return ((op)->ob_type == _PySwigPacked_type()) 
+  return ((op)->ob_type == SwigPyPacked_TypeOnce()) 
     || (strcmp((op)->ob_type->tp_name,"SwigPyPacked") == 0);
 }
 
@@ -1952,83 +2050,87 @@ SwigPyPacked_dealloc(PyObject *v)
 }
 
 SWIGRUNTIME PyTypeObject*
-_PySwigPacked_type(void) {
+SwigPyPacked_TypeOnce(void) {
   static char swigpacked_doc[] = "Swig object carries a C/C++ instance pointer";
   static PyTypeObject swigpypacked_type;
-  static int type_init = 0;  
+  static int type_init = 0;
   if (!type_init) {
-    const PyTypeObject tmp
-      = {
-    /* PyObject header changed in Python 3 */
+    const PyTypeObject tmp = {
+      /* PyObject header changed in Python 3 */
 #if PY_VERSION_HEX>=0x03000000
-    PyVarObject_HEAD_INIT(&PyType_Type, 0)
+      PyVarObject_HEAD_INIT(NULL, 0)
 #else
-	PyObject_HEAD_INIT(NULL)
-    0,				    /* ob_size */	
-#endif
-	(char *)"SwigPyPacked",		    /* tp_name */	
-	sizeof(SwigPyPacked),		    /* tp_basicsize */	
-	0,				    /* tp_itemsize */	
-	(destructor)SwigPyPacked_dealloc,   /* tp_dealloc */	
-	(printfunc)SwigPyPacked_print,	    /* tp_print */   	
-	(getattrfunc)0,			    /* tp_getattr */ 	
-	(setattrfunc)0,			    /* tp_setattr */ 	
+      PyObject_HEAD_INIT(NULL)
+      0,                                    /* ob_size */
+#endif
+      (char *)"SwigPyPacked",               /* tp_name */
+      sizeof(SwigPyPacked),                 /* tp_basicsize */
+      0,                                    /* tp_itemsize */
+      (destructor)SwigPyPacked_dealloc,     /* tp_dealloc */
+      (printfunc)SwigPyPacked_print,        /* tp_print */
+      (getattrfunc)0,                       /* tp_getattr */
+      (setattrfunc)0,                       /* tp_setattr */
 #if PY_VERSION_HEX>=0x03000000
-    0, /* tp_reserved in 3.0.1 */
+      0, /* tp_reserved in 3.0.1 */
 #else
-    (cmpfunc)SwigPyPacked_compare,	    /* tp_compare */
-#endif
-	(reprfunc)SwigPyPacked_repr,	    /* tp_repr */
-	0,	                            /* tp_as_number */
-	0,				    /* tp_as_sequence */
-	0,				    /* tp_as_mapping */
-	(hashfunc)0,			    /* tp_hash */
-	(ternaryfunc)0,			    /* tp_call */
-	(reprfunc)SwigPyPacked_str,	    /* tp_str */
-	PyObject_GenericGetAttr,            /* tp_getattro */
-	0,				    /* tp_setattro */
-	0,		                    /* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT,	            /* tp_flags */
-	swigpacked_doc, 	            /* tp_doc */
-	0,                                  /* tp_traverse */
-	0,                                  /* tp_clear */
-	0,                                  /* tp_richcompare */
-	0,                                  /* tp_weaklistoffset */
+      (cmpfunc)SwigPyPacked_compare,        /* tp_compare */
+#endif
+      (reprfunc)SwigPyPacked_repr,          /* tp_repr */
+      0,                                    /* tp_as_number */
+      0,                                    /* tp_as_sequence */
+      0,                                    /* tp_as_mapping */
+      (hashfunc)0,                          /* tp_hash */
+      (ternaryfunc)0,                       /* tp_call */
+      (reprfunc)SwigPyPacked_str,           /* tp_str */
+      PyObject_GenericGetAttr,              /* tp_getattro */
+      0,                                    /* tp_setattro */
+      0,                                    /* tp_as_buffer */
+      Py_TPFLAGS_DEFAULT,                   /* tp_flags */
+      swigpacked_doc,                       /* tp_doc */
+      0,                                    /* tp_traverse */
+      0,                                    /* tp_clear */
+      0,                                    /* tp_richcompare */
+      0,                                    /* tp_weaklistoffset */
 #if PY_VERSION_HEX >= 0x02020000
-	0,                                  /* tp_iter */
-	0,                                  /* tp_iternext */
-	0,		                    /* tp_methods */ 
-	0,			            /* tp_members */
-	0,				    /* tp_getset */	    	
-	0,			            /* tp_base */	        
-	0,				    /* tp_dict */	    	
-	0,				    /* tp_descr_get */  	
-	0,				    /* tp_descr_set */  	
-	0,				    /* tp_dictoffset */ 	
-	0,				    /* tp_init */	    	
-	0,				    /* tp_alloc */	    	
-	0,			            /* tp_new */	    	
-	0, 	                            /* tp_free */	   
-        0,                                  /* tp_is_gc */  
-	0,				    /* tp_bases */   
-	0,				    /* tp_mro */
-	0,				    /* tp_cache */   
- 	0,				    /* tp_subclasses */
-	0,				    /* tp_weaklist */
+      0,                                    /* tp_iter */
+      0,                                    /* tp_iternext */
+      0,                                    /* tp_methods */
+      0,                                    /* tp_members */
+      0,                                    /* tp_getset */
+      0,                                    /* tp_base */
+      0,                                    /* tp_dict */
+      0,                                    /* tp_descr_get */
+      0,                                    /* tp_descr_set */
+      0,                                    /* tp_dictoffset */
+      0,                                    /* tp_init */
+      0,                                    /* tp_alloc */
+      0,                                    /* tp_new */
+      0,                                    /* tp_free */
+      0,                                    /* tp_is_gc */
+      0,                                    /* tp_bases */
+      0,                                    /* tp_mro */
+      0,                                    /* tp_cache */
+      0,                                    /* tp_subclasses */
+      0,                                    /* tp_weaklist */
 #endif
 #if PY_VERSION_HEX >= 0x02030000
-	0,                                  /* tp_del */
+      0,                                    /* tp_del */
+#endif
+#if PY_VERSION_HEX >= 0x02060000
+      0,                                    /* tp_version */
 #endif
 #ifdef COUNT_ALLOCS
-	0,0,0,0                             /* tp_alloc -> tp_next */
+      0,0,0,0                               /* tp_alloc -> tp_next */
 #endif
-      };
+    };
     swigpypacked_type = tmp;
-    /* for Python 3 the ob_type already assigned in PyVarObject_HEAD_INIT() */
-#if PY_VERSION_HEX < 0x03000000
+    type_init = 1;
+#if PY_VERSION_HEX < 0x02020000
     swigpypacked_type.ob_type = &PyType_Type;
+#else
+    if (PyType_Ready(&swigpypacked_type) < 0)
+      return NULL;
 #endif
-    type_init = 1;
   }
   return &swigpypacked_type;
 }
@@ -2075,10 +2177,13 @@ _SWIG_This(void)
     return SWIG_Python_str_FromChar("this");
 }
 
+static PyObject *swig_this = NULL;
+
 SWIGRUNTIME PyObject *
 SWIG_This(void)
 {
-  static PyObject *SWIG_STATIC_POINTER(swig_this) = _SWIG_This();
+  if (swig_this == NULL)
+    swig_this = _SWIG_This();
   return swig_this;
 }
 
@@ -2092,50 +2197,65 @@ SWIG_This(void)
 SWIGRUNTIME SwigPyObject *
 SWIG_Python_GetSwigThis(PyObject *pyobj) 
 {
-  if (SwigPyObject_Check(pyobj)) {
+  PyObject *obj;
+
+  if (SwigPyObject_Check(pyobj))
     return (SwigPyObject *) pyobj;
-  } else {
-    PyObject *obj = 0;
+
+#ifdef SWIGPYTHON_BUILTIN
+  (void)obj;
+# ifdef PyWeakref_CheckProxy
+  if (PyWeakref_CheckProxy(pyobj)) {
+    pyobj = PyWeakref_GET_OBJECT(pyobj);
+    if (pyobj && SwigPyObject_Check(pyobj))
+      return (SwigPyObject*) pyobj;
+  }
+# endif
+  return NULL;
+#else
+
+  obj = 0;
+
 #if (!defined(SWIG_PYTHON_SLOW_GETSET_THIS) && (PY_VERSION_HEX >= 0x02030000))
-    if (PyInstance_Check(pyobj)) {
-      obj = _PyInstance_Lookup(pyobj, SWIG_This());      
+  if (PyInstance_Check(pyobj)) {
+    obj = _PyInstance_Lookup(pyobj, SWIG_This());      
+  } else {
+    PyObject **dictptr = _PyObject_GetDictPtr(pyobj);
+    if (dictptr != NULL) {
+      PyObject *dict = *dictptr;
+      obj = dict ? PyDict_GetItem(dict, SWIG_This()) : 0;
     } else {
-      PyObject **dictptr = _PyObject_GetDictPtr(pyobj);
-      if (dictptr != NULL) {
-	PyObject *dict = *dictptr;
-	obj = dict ? PyDict_GetItem(dict, SWIG_This()) : 0;
-      } else {
 #ifdef PyWeakref_CheckProxy
-	if (PyWeakref_CheckProxy(pyobj)) {
-	  PyObject *wobj = PyWeakref_GET_OBJECT(pyobj);
-	  return wobj ? SWIG_Python_GetSwigThis(wobj) : 0;
-	}
+      if (PyWeakref_CheckProxy(pyobj)) {
+	PyObject *wobj = PyWeakref_GET_OBJECT(pyobj);
+	return wobj ? SWIG_Python_GetSwigThis(wobj) : 0;
+      }
 #endif
-	obj = PyObject_GetAttr(pyobj,SWIG_This());
-	if (obj) {
-	  Py_DECREF(obj);
-	} else {
-	  if (PyErr_Occurred()) PyErr_Clear();
-	  return 0;
-	}
+      obj = PyObject_GetAttr(pyobj,SWIG_This());
+      if (obj) {
+	Py_DECREF(obj);
+      } else {
+	if (PyErr_Occurred()) PyErr_Clear();
+	return 0;
       }
     }
+  }
 #else
-    obj = PyObject_GetAttr(pyobj,SWIG_This());
-    if (obj) {
-      Py_DECREF(obj);
-    } else {
-      if (PyErr_Occurred()) PyErr_Clear();
-      return 0;
-    }
+  obj = PyObject_GetAttr(pyobj,SWIG_This());
+  if (obj) {
+    Py_DECREF(obj);
+  } else {
+    if (PyErr_Occurred()) PyErr_Clear();
+    return 0;
+  }
 #endif
-    if (obj && !SwigPyObject_Check(obj)) {
-      /* a PyObject is called 'this', try to get the 'real this'
-	 SwigPyObject from it */ 
-      return SWIG_Python_GetSwigThis(obj);
-    }
-    return (SwigPyObject *)obj;
+  if (obj && !SwigPyObject_Check(obj)) {
+    /* a PyObject is called 'this', try to get the 'real this'
+       SwigPyObject from it */ 
+    return SWIG_Python_GetSwigThis(obj);
   }
+  return (SwigPyObject *)obj;
+#endif
 }
 
 /* Acquire a pointer value */
@@ -2157,91 +2277,105 @@ SWIG_Python_AcquirePtr(PyObject *obj, int own) {
 
 SWIGRUNTIME int
 SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int flags, int *own) {
-  if (!obj) return SWIG_ERROR;
-  if (obj == Py_None) {
-    if (ptr) *ptr = 0;
+  int res;
+  SwigPyObject *sobj;
+  int implicit_conv = (flags & SWIG_POINTER_IMPLICIT_CONV) != 0;
+
+  if (!obj)
+    return SWIG_ERROR;
+  if (obj == Py_None && !implicit_conv) {
+    if (ptr)
+      *ptr = 0;
     return SWIG_OK;
-  } else {
-    SwigPyObject *sobj = SWIG_Python_GetSwigThis(obj);
+  }
+
+  res = SWIG_ERROR;
+
+  sobj = SWIG_Python_GetSwigThis(obj);
+  if (own)
+    *own = 0;
+  while (sobj) {
+    void *vptr = sobj->ptr;
+    if (ty) {
+      swig_type_info *to = sobj->ty;
+      if (to == ty) {
+        /* no type cast needed */
+        if (ptr) *ptr = vptr;
+        break;
+      } else {
+        swig_cast_info *tc = SWIG_TypeCheck(to->name,ty);
+        if (!tc) {
+          sobj = (SwigPyObject *)sobj->next;
+        } else {
+          if (ptr) {
+            int newmemory = 0;
+            *ptr = SWIG_TypeCast(tc,vptr,&newmemory);
+            if (newmemory == SWIG_CAST_NEW_MEMORY) {
+              assert(own); /* badly formed typemap which will lead to a memory leak - it must set and use own to delete *ptr */
+              if (own)
+                *own = *own | SWIG_CAST_NEW_MEMORY;
+            }
+          }
+          break;
+        }
+      }
+    } else {
+      if (ptr) *ptr = vptr;
+      break;
+    }
+  }
+  if (sobj) {
     if (own)
-      *own = 0;
-    while (sobj) {
-      void *vptr = sobj->ptr;
-      if (ty) {
-	swig_type_info *to = sobj->ty;
-	if (to == ty) {
-	  /* no type cast needed */
-	  if (ptr) *ptr = vptr;
-	  break;
-	} else {
-	  swig_cast_info *tc = SWIG_TypeCheck(to->name,ty);
-	  if (!tc) {
-	    sobj = (SwigPyObject *)sobj->next;
-	  } else {
-	    if (ptr) {
-              int newmemory = 0;
-              *ptr = SWIG_TypeCast(tc,vptr,&newmemory);
-              if (newmemory == SWIG_CAST_NEW_MEMORY) {
-                assert(own);
-                if (own)
-                  *own = *own | SWIG_CAST_NEW_MEMORY;
+      *own = *own | sobj->own;
+    if (flags & SWIG_POINTER_DISOWN) {
+      sobj->own = 0;
+    }
+    res = SWIG_OK;
+  } else {
+    if (implicit_conv) {
+      SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0;
+      if (data && !data->implicitconv) {
+        PyObject *klass = data->klass;
+        if (klass) {
+          PyObject *impconv;
+          data->implicitconv = 1; /* avoid recursion and call 'explicit' constructors*/
+          impconv = SWIG_Python_CallFunctor(klass, obj);
+          data->implicitconv = 0;
+          if (PyErr_Occurred()) {
+            PyErr_Clear();
+            impconv = 0;
+          }
+          if (impconv) {
+            SwigPyObject *iobj = SWIG_Python_GetSwigThis(impconv);
+            if (iobj) {
+              void *vptr;
+              res = SWIG_Python_ConvertPtrAndOwn((PyObject*)iobj, &vptr, ty, 0, 0);
+              if (SWIG_IsOK(res)) {
+                if (ptr) {
+                  *ptr = vptr;
+                  /* transfer the ownership to 'ptr' */
+                  iobj->own = 0;
+                  res = SWIG_AddCast(res);
+                  res = SWIG_AddNewMask(res);
+                } else {
+                  res = SWIG_AddCast(res);		    
+                }
               }
             }
-	    break;
-	  }
-	}
-      } else {
-	if (ptr) *ptr = vptr;
-	break;
+            Py_DECREF(impconv);
+          }
+        }
       }
     }
-    if (sobj) {
-      if (own)
-        *own = *own | sobj->own;
-      if (flags & SWIG_POINTER_DISOWN) {
-	sobj->own = 0;
-      }
-      return SWIG_OK;
-    } else {
-      int res = SWIG_ERROR;
-      if (flags & SWIG_POINTER_IMPLICIT_CONV) {
-	SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0;
-	if (data && !data->implicitconv) {
-	  PyObject *klass = data->klass;
-	  if (klass) {
-	    PyObject *impconv;
-	    data->implicitconv = 1; /* avoid recursion and call 'explicit' constructors*/
-	    impconv = SWIG_Python_CallFunctor(klass, obj);
-	    data->implicitconv = 0;
-	    if (PyErr_Occurred()) {
-	      PyErr_Clear();
-	      impconv = 0;
-	    }
-	    if (impconv) {
-	      SwigPyObject *iobj = SWIG_Python_GetSwigThis(impconv);
-	      if (iobj) {
-		void *vptr;
-		res = SWIG_Python_ConvertPtrAndOwn((PyObject*)iobj, &vptr, ty, 0, 0);
-		if (SWIG_IsOK(res)) {
-		  if (ptr) {
-		    *ptr = vptr;
-		    /* transfer the ownership to 'ptr' */
-		    iobj->own = 0;
-		    res = SWIG_AddCast(res);
-		    res = SWIG_AddNewMask(res);
-		  } else {
-		    res = SWIG_AddCast(res);		    
-		  }
-		}
-	      }
-	      Py_DECREF(impconv);
-	    }
-	  }
-	}
-      }
-      return res;
+    if (!SWIG_IsOK(res) && obj == Py_None) {
+      if (ptr)
+        *ptr = 0;
+      if (PyErr_Occurred())
+        PyErr_Clear();
+      res = SWIG_OK;
     }
   }
+  return res;
 }
 
 /* Convert a function ptr value */
@@ -2328,23 +2462,29 @@ SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this)
   } else {
 #if PY_VERSION_HEX >= 0x03000000
     inst = PyBaseObject_Type.tp_new((PyTypeObject*) data->newargs, Py_None, Py_None);
-    PyObject_SetAttr(inst, SWIG_This(), swig_this);
-    Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
+    if (inst) {
+      PyObject_SetAttr(inst, SWIG_This(), swig_this);
+      Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
+    }
 #else
     PyObject *dict = PyDict_New();
-    PyDict_SetItem(dict, SWIG_This(), swig_this);
-    inst = PyInstance_NewRaw(data->newargs, dict);
-    Py_DECREF(dict);
+    if (dict) {
+      PyDict_SetItem(dict, SWIG_This(), swig_this);
+      inst = PyInstance_NewRaw(data->newargs, dict);
+      Py_DECREF(dict);
+    }
 #endif
   }
   return inst;
 #else
 #if (PY_VERSION_HEX >= 0x02010000)
-  PyObject *inst;
+  PyObject *inst = 0;
   PyObject *dict = PyDict_New();
-  PyDict_SetItem(dict, SWIG_This(), swig_this);
-  inst = PyInstance_NewRaw(data->newargs, dict);
-  Py_DECREF(dict);
+  if (dict) {
+    PyDict_SetItem(dict, SWIG_This(), swig_this);
+    inst = PyInstance_NewRaw(data->newargs, dict);
+    Py_DECREF(dict);
+  }
   return (PyObject *) inst;
 #else
   PyInstanceObject *inst = PyObject_NEW(PyInstanceObject, &PyInstance_Type);
@@ -2395,7 +2535,7 @@ SWIG_Python_SetSwigThis(PyObject *inst, PyObject *swig_this)
 SWIGINTERN PyObject *
 SWIG_Python_InitShadowInstance(PyObject *args) {
   PyObject *obj[2];
-  if (!SWIG_Python_UnpackTuple(args,(char*)"swiginit", 2, 2, obj)) {
+  if (!SWIG_Python_UnpackTuple(args, "swiginit", 2, 2, obj)) {
     return NULL;
   } else {
     SwigPyObject *sthis = SWIG_Python_GetSwigThis(obj[0]);
@@ -2411,22 +2551,52 @@ SWIG_Python_InitShadowInstance(PyObject *args) {
 /* Create a new pointer object */
 
 SWIGRUNTIME PyObject *
-SWIG_Python_NewPointerObj(void *ptr, swig_type_info *type, int flags) {
-  if (!ptr) {
+SWIG_Python_NewPointerObj(PyObject *self, void *ptr, swig_type_info *type, int flags) {
+  SwigPyClientData *clientdata;
+  PyObject * robj;
+  int own;
+
+  if (!ptr)
     return SWIG_Py_Void();
-  } else {
-    int own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0;
-    PyObject *robj = SwigPyObject_New(ptr, type, own);
-    SwigPyClientData *clientdata = type ? (SwigPyClientData *)(type->clientdata) : 0;
-    if (clientdata && !(flags & SWIG_POINTER_NOSHADOW)) {
-      PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj);
-      if (inst) {
-	Py_DECREF(robj);
-	robj = inst;
+
+  clientdata = type ? (SwigPyClientData *)(type->clientdata) : 0;
+  own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0;
+  if (clientdata && clientdata->pytype) {
+    SwigPyObject *newobj;
+    if (flags & SWIG_BUILTIN_TP_INIT) {
+      newobj = (SwigPyObject*) self;
+      if (newobj->ptr) {
+        PyObject *next_self = clientdata->pytype->tp_alloc(clientdata->pytype, 0);
+        while (newobj->next)
+	  newobj = (SwigPyObject *) newobj->next;
+        newobj->next = next_self;
+        newobj = (SwigPyObject *)next_self;
       }
+    } else {
+      newobj = PyObject_New(SwigPyObject, clientdata->pytype);
     }
-    return robj;
+    if (newobj) {
+      newobj->ptr = ptr;
+      newobj->ty = type;
+      newobj->own = own;
+      newobj->next = 0;
+#ifdef SWIGPYTHON_BUILTIN
+      newobj->dict = 0;
+#endif
+      return (PyObject*) newobj;
+    }
+    return SWIG_Py_Void();
+  }
+
+  assert(!(flags & SWIG_BUILTIN_TP_INIT));
+
+  robj = SwigPyObject_New(ptr, type, own);
+  if (robj && clientdata && !(flags & SWIG_POINTER_NOSHADOW)) {
+    PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj);
+    Py_DECREF(robj);
+    robj = inst;
   }
+  return robj;
 }
 
 /* Create a new packed object */
@@ -2445,19 +2615,19 @@ void *SWIG_ReturnGlobalTypeList(void *);
 #endif
 
 SWIGRUNTIME swig_module_info *
-SWIG_Python_GetModule(void) {
+SWIG_Python_GetModule(void *SWIGUNUSEDPARM(clientdata)) {
   static void *type_pointer = (void *)0;
   /* first check if module already created */
   if (!type_pointer) {
 #ifdef SWIG_LINK_RUNTIME
     type_pointer = SWIG_ReturnGlobalTypeList((void *)0);
 #else
-#ifdef SWIG_PYTHON_USE_CAPSULE
-    type_pointer = PyCapsule_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer" SWIG_TYPE_TABLE_NAME, 0);
-#else
+# ifdef SWIGPY_USE_CAPSULE
+    type_pointer = PyCapsule_Import(SWIGPY_CAPSULE_NAME, 0);
+# else
     type_pointer = PyCObject_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
 				    (char*)"type_pointer" SWIG_TYPE_TABLE_NAME);
-#endif
+# endif
     if (PyErr_Occurred()) {
       PyErr_Clear();
       type_pointer = (void *)0;
@@ -2500,26 +2670,19 @@ PyModule_AddObject(PyObject *m, char *name, PyObject *o)
 #endif
 
 SWIGRUNTIME void
-#ifdef SWIG_PYTHON_USE_CAPSULE
-SWIG_Python_DestroyModule(PyObject *capsule)
-{
-  swig_module_info *swig_module;
-  swig_type_info **types;
-  size_t i;
-  swig_module = (swig_module_info *)PyCapsule_GetPointer(capsule, (char*)"swig_runtime_data" SWIG_RUNTIME_VERSION);
-  if (swig_module == NULL)
-  {
-    PyErr_Clear();
-    return;
-  }
-  types = swig_module->types;
+#ifdef SWIGPY_USE_CAPSULE
+SWIG_Python_DestroyModule(PyObject *obj)
 #else
 SWIG_Python_DestroyModule(void *vptr)
+#endif
 {
+#ifdef SWIGPY_USE_CAPSULE
+  swig_module_info *swig_module = (swig_module_info *) PyCapsule_GetPointer(obj, SWIGPY_CAPSULE_NAME);
+#else
   swig_module_info *swig_module = (swig_module_info *) vptr;
+#endif
   swig_type_info **types = swig_module->types;
   size_t i;
-#endif
   for (i =0; i < swig_module->size; ++i) {
     swig_type_info *ty = types[i];
     if (ty->owndata) {
@@ -2528,31 +2691,33 @@ SWIG_Python_DestroyModule(void *vptr)
     }
   }
   Py_DECREF(SWIG_This());
+  swig_this = NULL;
 }
 
 SWIGRUNTIME void
 SWIG_Python_SetModule(swig_module_info *swig_module) {
-  static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} };/* Sentinel */
-
 #if PY_VERSION_HEX >= 0x03000000
  /* Add a dummy module object into sys.modules */
   PyObject *module = PyImport_AddModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION);
 #else
-  PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
-				   swig_empty_runtime_method_table);
+  static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} }; /* Sentinel */
+  PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION, swig_empty_runtime_method_table);
 #endif
-#ifdef SWIG_PYTHON_USE_CAPSULE
-  PyObject *pointer = PyCapsule_New((void *) swig_module,
-                                    (char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer" SWIG_TYPE_TABLE_NAME,
-                                    SWIG_Python_DestroyModule);
+#ifdef SWIGPY_USE_CAPSULE
+  PyObject *pointer = PyCapsule_New((void *) swig_module, SWIGPY_CAPSULE_NAME, SWIG_Python_DestroyModule);
+  if (pointer && module) {
+    PyModule_AddObject(module, (char*)"type_pointer_capsule" SWIG_TYPE_TABLE_NAME, pointer);
+  } else {
+    Py_XDECREF(pointer);
+  }
 #else
   PyObject *pointer = PyCObject_FromVoidPtr((void *) swig_module, SWIG_Python_DestroyModule);
-#endif
   if (pointer && module) {
     PyModule_AddObject(module, (char*)"type_pointer" SWIG_TYPE_TABLE_NAME, pointer);
   } else {
     Py_XDECREF(pointer);
   }
+#endif
 }
 
 /* The python cached type query */
@@ -2570,17 +2735,17 @@ SWIG_Python_TypeQuery(const char *type)
   PyObject *obj = PyDict_GetItem(cache, key);
   swig_type_info *descriptor;
   if (obj) {
-#ifdef SWIG_PYTHON_USE_CAPSULE
-    descriptor = (swig_type_info *) PyCapsule_GetPointer(obj, (char*)"swig_type_info");
+#ifdef SWIGPY_USE_CAPSULE
+    descriptor = (swig_type_info *) PyCapsule_GetPointer(obj, NULL);
 #else
     descriptor = (swig_type_info *) PyCObject_AsVoidPtr(obj);
 #endif
   } else {
-    swig_module_info *swig_module = SWIG_Python_GetModule();
+    swig_module_info *swig_module = SWIG_GetModule(0);
     descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type);
     if (descriptor) {
-#ifdef SWIG_PYTHON_USE_CAPSULE
-      obj = PyCapsule_New(descriptor, (char*)"swig_type_info", NULL);
+#ifdef SWIGPY_USE_CAPSULE
+      obj = PyCapsule_New((void*) descriptor, NULL, NULL);
 #else
       obj = PyCObject_FromVoidPtr(descriptor, NULL);
 #endif
@@ -2644,7 +2809,7 @@ SwigPyObject_GetDesc(PyObject *self)
 {
   SwigPyObject *v = (SwigPyObject *)self;
   swig_type_info *ty = v ? v->ty : 0;
-  return ty ? ty->str : (char*)"";
+  return ty ? ty->str : "";
 }
 
 SWIGRUNTIME void
@@ -2687,7 +2852,7 @@ SWIG_Python_TypeError(const char *type, PyObject *obj)
 
 /* Convert a pointer value, signal an exception on a type mismatch */
 SWIGRUNTIME void *
-SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int argnum, int flags) {
+SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int SWIGUNUSEDPARM(argnum), int flags) {
   void *result;
   if (SWIG_Python_ConvertPtr(obj, &result, ty, flags) == -1) {
     PyErr_Clear();
@@ -2701,11 +2866,61 @@ SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int argnum, int flags)
   return result;
 }
 
+#ifdef SWIGPYTHON_BUILTIN
+SWIGRUNTIME int
+SWIG_Python_NonDynamicSetAttr(PyObject *obj, PyObject *name, PyObject *value) {
+  PyTypeObject *tp = obj->ob_type;
+  PyObject *descr;
+  PyObject *encoded_name;
+  descrsetfunc f;
+  int res = -1;
+
+# ifdef Py_USING_UNICODE
+  if (PyString_Check(name)) {
+    name = PyUnicode_Decode(PyString_AsString(name), PyString_Size(name), NULL, NULL);
+    if (!name)
+      return -1;
+  } else if (!PyUnicode_Check(name))
+# else
+  if (!PyString_Check(name))
+# endif
+  {
+    PyErr_Format(PyExc_TypeError, "attribute name must be string, not '%.200s'", name->ob_type->tp_name);
+    return -1;
+  } else {
+    Py_INCREF(name);
+  }
+
+  if (!tp->tp_dict) {
+    if (PyType_Ready(tp) < 0)
+      goto done;
+  }
 
-#ifdef __cplusplus
-#if 0
-{ /* cc-mode */
+  descr = _PyType_Lookup(tp, name);
+  f = NULL;
+  if (descr != NULL)
+    f = descr->ob_type->tp_descr_set;
+  if (!f) {
+    if (PyString_Check(name)) {
+      encoded_name = name;
+      Py_INCREF(name);
+    } else {
+      encoded_name = PyUnicode_AsUTF8String(name);
+    }
+    PyErr_Format(PyExc_AttributeError, "'%.100s' object has no attribute '%.200s'", tp->tp_name, PyString_AsString(encoded_name));
+    Py_DECREF(encoded_name);
+  } else {
+    res = f(descr, obj, value);
+  }
+  
+  done:
+  Py_DECREF(name);
+  return res;
+}
 #endif
+
+
+#ifdef __cplusplus
 }
 #endif
 
@@ -2760,7 +2975,7 @@ static swig_module_info swig_module = {swig_types, 13, 0, 0, 0, 0};
 #endif
 #define SWIG_name    "_gdal_array"
 
-#define SWIGVERSION 0x010340 
+#define SWIGVERSION 0x020012 
 #define SWIG_VERSION SWIGVERSION
 
 
@@ -2947,6 +3162,7 @@ SWIG_CanCastAsInteger(double *d, double min, double max) {
 SWIGINTERN int
 SWIG_AsVal_unsigned_SS_long (PyObject *obj, unsigned long *val) 
 {
+#if PY_VERSION_HEX < 0x03000000
   if (PyInt_Check(obj)) {
     long v = PyInt_AsLong(obj);
     if (v >= 0) {
@@ -2955,13 +3171,27 @@ SWIG_AsVal_unsigned_SS_long (PyObject *obj, unsigned long *val)
     } else {
       return SWIG_OverflowError;
     }
-  } else if (PyLong_Check(obj)) {
+  } else
+#endif
+  if (PyLong_Check(obj)) {
     unsigned long v = PyLong_AsUnsignedLong(obj);
     if (!PyErr_Occurred()) {
       if (val) *val = v;
       return SWIG_OK;
     } else {
       PyErr_Clear();
+#if PY_VERSION_HEX >= 0x03000000
+      {
+        long v = PyLong_AsLong(obj);
+        if (!PyErr_Occurred()) {
+          if (v < 0) {
+            return SWIG_OverflowError;
+          }
+        } else {
+          PyErr_Clear();
+        }
+      }
+#endif
     }
   }
 #ifdef SWIG_PYTHON_CAST_MODE
@@ -3090,7 +3320,7 @@ static PyObject* GDALPythonObjectFromCStr(const char *pszStr)
     pszIter ++;
   }
 #if PY_VERSION_HEX >= 0x03000000
-  return PyUnicode_FromString(pszStr); 
+  return PyUnicode_FromString(pszStr);
 #else
   return PyString_FromString(pszStr);
 #endif
@@ -3118,7 +3348,7 @@ static char* GDALPythonObjectToCStr(PyObject* pyObject, int* pbToFree)
       *pbToFree = 1;
       return pszNewStr;
   }
-  else 
+  else
   {
 #if PY_VERSION_HEX >= 0x03000000
       return PyBytes_AsString(pyObject);
@@ -3146,7 +3376,7 @@ static void GDALPythonFreeCStr(void* ptr, int bToFree)
 #endif
 #include "numpy/arrayobject.h"
 
-#ifdef DEBUG 
+#ifdef DEBUG
 typedef struct GDALRasterBandHS GDALRasterBandShadow;
 typedef struct GDALDatasetHS GDALDatasetShadow;
 typedef struct RasterAttributeTableHS GDALRasterAttributeTableShadow;
@@ -3158,8 +3388,8 @@ typedef void GDALRasterAttributeTableShadow;
 
 CPL_C_START
 
-GDALRasterBandH CPL_DLL MEMCreateRasterBand( GDALDataset *, int, GByte *,
-                                             GDALDataType, int, int, int );
+GDALRasterBandH CPL_DLL MEMCreateRasterBandEx( GDALDataset *, int, GByte *,
+                                               GDALDataType, GSpacing, GSpacing, int );
 CPL_C_END
 
 typedef char retStringAndCPLFree;
@@ -3191,15 +3421,15 @@ class NUMPYDataset : public GDALDataset
     virtual CPLErr SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
                             const char *pszGCPProjection );
 
+    static GDALDataset *Open( PyArrayObject *psArray );
     static GDALDataset *Open( GDALOpenInfo * );
 };
 
 
-
 /************************************************************************/
 /*                          GDALRegister_NUMPY()                        */
 /************************************************************************/
-   
+
 static void GDALRegister_NUMPY(void)
 
 {
@@ -3209,12 +3439,12 @@ static void GDALRegister_NUMPY(void)
     if( GDALGetDriverByName( "NUMPY" ) == NULL )
     {
         poDriver = new GDALDriver();
-        
+
         poDriver->SetDescription( "NUMPY" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
+        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
                                    "Numeric Python Array" );
         poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        
+
         poDriver->pfnOpen = NUMPYDataset::Open;
 
         GetGDALDriverManager()->RegisterDriver( poDriver );
@@ -3229,6 +3459,7 @@ static void GDALRegister_NUMPY(void)
 NUMPYDataset::NUMPYDataset()
 
 {
+    psArray = NULL;
     pszProjection = CPLStrdup("");
     bValidGeoTransform = FALSE;
     adfGeoTransform[0] = 0.0;
@@ -3374,8 +3605,6 @@ GDALDataset *NUMPYDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
     PyArrayObject *psArray;
-    GDALDataType  eType;
-    int     nBands;
 
 /* -------------------------------------------------------------------- */
 /*      Is this a numpy dataset name?                                   */
@@ -3395,12 +3624,37 @@ GDALDataset *NUMPYDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
+    if( !CSLTestBoolean(CPLGetConfigOption("GDAL_ARRAY_OPEN_BY_FILENAME", "FALSE")) )
+    {
+        if( CPLGetConfigOption("GDAL_ARRAY_OPEN_BY_FILENAME", NULL) == NULL )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                    "Opening a NumPy array through gdal.Open(gdal_array.GetArrayFilename()) "
+                    "is no longer supported by default unless the GDAL_ARRAY_OPEN_BY_FILENAME "
+                    "configuration option is set to TRUE. The recommended way is to use "
+                    "gdal_array.OpenArray() instead.");
+        }
+        return NULL;
+    }
+
+    return Open(psArray);
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset* NUMPYDataset::Open( PyArrayObject *psArray )
+{
+    GDALDataType  eType;
+    int     nBands;
+
 /* -------------------------------------------------------------------- */
 /*      If we likely have corrupt definitions of the NUMPY stuff,       */
 /*      then warn now.                                                  */
 /* -------------------------------------------------------------------- */
 #ifdef NUMPY_DEFS_WRONG
-    CPLError( CE_Warning, CPLE_AppDefined, 
+    CPLError( CE_Warning, CPLE_AppDefined,
               "It would appear you have built GDAL without having it use\n"
               "the Numeric python include files.  Old definitions have\n"
               "been used instead at build time, and it is quite possible that\n"
@@ -3416,8 +3670,8 @@ GDALDataset *NUMPYDataset::Open( GDALOpenInfo * poOpenInfo )
 
     if( psArray->nd < 2 || psArray->nd > 3 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Illegal numpy array rank %d.\n", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Illegal numpy array rank %d.",
                   psArray->nd );
         return NULL;
     }
@@ -3464,8 +3718,8 @@ GDALDataset *NUMPYDataset::Open( GDALOpenInfo * poOpenInfo )
         break;
 
       default:
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Unable to access numpy arrays of typecode `%c'.\n", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Unable to access numpy arrays of typecode `%c'.",
                   psArray->descr->type );
         return NULL;
     }
@@ -3476,6 +3730,7 @@ GDALDataset *NUMPYDataset::Open( GDALOpenInfo * poOpenInfo )
     NUMPYDataset *poDS;
 
     poDS = new NUMPYDataset();
+    poDS->poDriver = static_cast<GDALDriver*>(GDALGetDriverByName("NUMPY"));
 
     poDS->psArray = psArray;
 
@@ -3489,9 +3744,9 @@ GDALDataset *NUMPYDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Workout the data layout.                                        */
 /* -------------------------------------------------------------------- */
-    int    nBandOffset;
-    int    nPixelOffset;
-    int    nLineOffset;
+    npy_intp nBandOffset;
+    npy_intp nPixelOffset;
+    npy_intp nLineOffset;
 
     if( psArray->nd == 3 )
     {
@@ -3517,9 +3772,9 @@ GDALDataset *NUMPYDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     for( int iBand = 0; iBand < nBands; iBand++ )
     {
-        poDS->SetBand( iBand+1, 
-                       (GDALRasterBand *) 
-                       MEMCreateRasterBand( poDS, iBand+1, 
+        poDS->SetBand( iBand+1,
+                       (GDALRasterBand *)
+                       MEMCreateRasterBandEx( poDS, iBand+1,
                                 (GByte *) psArray->data + nBandOffset*iBand,
                                           eType, nPixelOffset, nLineOffset,
                                           FALSE ) );
@@ -3630,13 +3885,10 @@ SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc)
 
 
 
-  #define SWIG_From_long   PyInt_FromLong 
-
-
-SWIGINTERNINLINE PyObject *
-SWIG_From_int  (int value)
-{    
-  return SWIG_From_long  (value);
+SWIGINTERNINLINE PyObject*
+  SWIG_From_int  (int value)
+{
+  return PyInt_FromLong((long) value);
 }
 
 
@@ -3651,7 +3903,7 @@ typedef struct {
 /*                          PyProgressProxy()                           */
 /************************************************************************/
 
-int CPL_STDCALL
+static int CPL_STDCALL
 PyProgressProxy( double dfComplete, const char *pszMessage, void *pData )
 
 {
@@ -3666,19 +3918,25 @@ PyProgressProxy( double dfComplete, const char *pszMessage, void *pData )
         return TRUE;
 
     psInfo->nLastReported = (int) (100.0 * dfComplete);
-    
+
     if( pszMessage == NULL )
         pszMessage = "";
 
     if( psInfo->psPyCallbackData == NULL )
         psArgs = Py_BuildValue("(dsO)", dfComplete, pszMessage, Py_None );
     else
-        psArgs = Py_BuildValue("(dsO)", dfComplete, pszMessage, 
+        psArgs = Py_BuildValue("(dsO)", dfComplete, pszMessage,
 	                       psInfo->psPyCallbackData );
 
     psResult = PyEval_CallObject( psInfo->psPyCallback, psArgs);
     Py_XDECREF(psArgs);
 
+    if( PyErr_Occurred() != NULL )
+    {
+        PyErr_Clear();
+        return FALSE;
+    }
+
     if( psResult == NULL )
     {
         return TRUE;
@@ -3686,19 +3944,26 @@ PyProgressProxy( double dfComplete, const char *pszMessage, void *pData )
 
     if( psResult == Py_None )
     {
-	Py_XDECREF(Py_None);
         return TRUE;
     }
 
     if( !PyArg_Parse( psResult, "i", &bContinue ) )
     {
-        PyErr_SetString(PyExc_ValueError, "bad progress return value");
+        PyErr_Clear();
+        CPLError(CE_Failure, CPLE_AppDefined, "bad progress return value");
+        Py_XDECREF(psResult);
 	return FALSE;
     }
 
     Py_XDECREF(psResult);
 
-    return bContinue;    
+    return bContinue;
+}
+
+
+GDALDatasetShadow* OpenNumPyArray(PyArrayObject *psArray)
+{
+    return NUMPYDataset::Open( psArray );
 }
 
 
@@ -3714,7 +3979,7 @@ retStringAndCPLFree* GetArrayFilename(PyArrayObject *psArray)
 }
 
 
-  CPLErr BandRasterIONumPy( GDALRasterBandShadow* band, int bWrite, int xoff, int yoff, int xsize, int ysize,
+  CPLErr BandRasterIONumPy( GDALRasterBandShadow* band, int bWrite, double xoff, double yoff, double xsize, double ysize,
                             PyArrayObject *psArray,
                             int buf_type,
                             GDALRIOResampleAlg resample_alg,
@@ -3724,8 +3989,8 @@ retStringAndCPLFree* GetArrayFilename(PyArrayObject *psArray)
     GDALDataType ntype  = (GDALDataType)buf_type;
     if( psArray->nd < 2 || psArray->nd > 3 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Illegal numpy array rank %d.\n", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Illegal numpy array rank %d.\n",
                   psArray->nd );
         return CE_Failure;
     }
@@ -3744,8 +4009,21 @@ retStringAndCPLFree* GetArrayFilename(PyArrayObject *psArray)
     sExtraArg.eResampleAlg = resample_alg;
     sExtraArg.pfnProgress = callback;
     sExtraArg.pProgressData = callback_data;
+    int nXOff = (int)(xoff + 0.5);
+    int nYOff = (int)(yoff + 0.5);
+    int nXSize = (int)(xsize + 0.5);
+    int nYSize = (int)(ysize + 0.5);
+    if( fabs(xoff-nXOff) > 1e-8 || fabs(yoff-nYOff) > 1e-8 ||
+        fabs(xsize-nXSize) > 1e-8 || fabs(ysize-nYSize) > 1e-8 )
+    {
+        sExtraArg.bFloatingPointWindowValidity = TRUE;
+        sExtraArg.dfXOff = xoff;
+        sExtraArg.dfYOff = yoff;
+        sExtraArg.dfXSize = xsize;
+        sExtraArg.dfYSize = ysize;
+    }
 
-    return  GDALRasterIOEx( band, (bWrite) ? GF_Write : GF_Read, xoff, yoff, xsize, ysize,
+    return  GDALRasterIOEx( band, (bWrite) ? GF_Write : GF_Read, nXOff, nYOff, nXSize, nYSize,
                           psArray->data, nxsize, nysize,
                           ntype, pixel_space, line_space, &sExtraArg );
   }
@@ -3761,8 +4039,8 @@ retStringAndCPLFree* GetArrayFilename(PyArrayObject *psArray)
     GDALDataType ntype  = (GDALDataType)buf_type;
     if( psArray->nd != 3 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Illegal numpy array rank %d.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Illegal numpy array rank %d.",
                   psArray->nd );
         return CE_Failure;
     }
@@ -3777,8 +4055,8 @@ retStringAndCPLFree* GetArrayFilename(PyArrayObject *psArray)
     bandsize = psArray->dimensions[0];
     if( bandsize != GDALGetRasterCount(ds) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Illegal numpy array band dimension %d. Expected value: %d", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Illegal numpy array band dimension %d. Expected value: %d",
                   bandsize, GDALGetRasterCount(ds) );
         return CE_Failure;
     }
@@ -3807,15 +4085,15 @@ retStringAndCPLFree* GetArrayFilename(PyArrayObject *psArray)
 
 
   // need different functions for read and write
-  // since reading strings requires us to know the 
+  // since reading strings requires us to know the
   // length of the longest string before creating array
-  CPLErr RATValuesIONumPyWrite( GDALRasterAttributeTableShadow* poRAT, int nField, int nStart, 
+  CPLErr RATValuesIONumPyWrite( GDALRasterAttributeTableShadow* poRAT, int nField, int nStart,
                        PyArrayObject *psArray) {
 
     if( PyArray_NDIM(psArray) != 1 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Illegal numpy array rank %d.\n", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Illegal numpy array rank %d.\n",
                   PyArray_NDIM(psArray) );
         return CE_Failure;
     }
@@ -3826,7 +4104,7 @@ retStringAndCPLFree* GetArrayFilename(PyArrayObject *psArray)
 
     if( nType == NPY_INT32 )
     {
-        retval = GDALRATValuesIOAsInteger(poRAT, GF_Write, nField, nStart, nLength, 
+        retval = GDALRATValuesIOAsInteger(poRAT, GF_Write, nField, nStart, nLength,
                         (int*)PyArray_DATA(psArray) );
     }
     else if( nType == NPY_DOUBLE )
@@ -3846,7 +4124,7 @@ retStringAndCPLFree* GetArrayFilename(PyArrayObject *psArray)
         // as there won't be if this string is the maximum size
         pszBuffer[nMaxLen] = '\0';
 
-        // we can't just use the memory location in the array 
+        // we can't just use the memory location in the array
         // since long strings won't be null terminated
         for( int i = 0; i < nLength; i++ )
         {
@@ -3866,8 +4144,8 @@ retStringAndCPLFree* GetArrayFilename(PyArrayObject *psArray)
     }
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Illegal numpy array type %d.\n", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Illegal numpy array type %d.\n",
                   nType );
         return CE_Failure;
     }
@@ -3876,9 +4154,9 @@ retStringAndCPLFree* GetArrayFilename(PyArrayObject *psArray)
 
 
   // need different functions for read and write
-  // since reading strings requires us to know the 
+  // since reading strings requires us to know the
   // length of the longest string before creating array
-  PyObject *RATValuesIONumPyRead( GDALRasterAttributeTableShadow* poRAT, int nField, int nStart, 
+  PyObject *RATValuesIONumPyRead( GDALRasterAttributeTableShadow* poRAT, int nField, int nStart,
                        int nLength) {
 
     GDALRATFieldType colType = GDALRATGetTypeOfCol(poRAT, nField);
@@ -3887,7 +4165,7 @@ retStringAndCPLFree* GetArrayFilename(PyArrayObject *psArray)
     if( colType == GFT_Integer )
     {
         pOutArray = PyArray_SimpleNew(1, &dims, NPY_INT32);
-        if( GDALRATValuesIOAsInteger(poRAT, GF_Read, nField, nStart, nLength, 
+        if( GDALRATValuesIOAsInteger(poRAT, GF_Read, nField, nStart, nLength,
                         (int*)PyArray_DATA(pOutArray)) != CE_None)
         {
             Py_DECREF(pOutArray);
@@ -3959,7 +4237,7 @@ retStringAndCPLFree* GetArrayFilename(PyArrayObject *psArray)
         }
         else
         {
-            // so there isn't rubbush in the 1 char strings
+            // so there isn't rubbish in the 1 char strings
             PyArray_FILLWBYTE(pOutArray, 0);
         }
 
@@ -4028,7 +4306,7 @@ SWIGINTERN PyObject *_wrap_VirtualMem_GetAddr(PyObject *SWIGUNUSEDPARM(self), Py
   CPLVirtualMemShadow_GetAddr(arg1,arg2,arg3,arg4,arg5);
   resultobj = SWIG_Py_Void();
   {
-#if PY_VERSION_HEX >= 0x02070000 
+#if PY_VERSION_HEX >= 0x02070000
     /* %typemap(argout) (void** pptr, size_t* pnsize, GDALDataType* pdatatype, int* preadonly)*/
     Py_buffer *buf=(Py_buffer*)malloc(sizeof(Py_buffer));
     if (PyBuffer_FillInfo(buf,  obj0,  *(arg2), *(arg3), *(arg5), PyBUF_ND)) {
@@ -4036,48 +4314,48 @@ SWIGINTERN PyObject *_wrap_VirtualMem_GetAddr(PyObject *SWIGUNUSEDPARM(self), Py
     }
     if( *(arg4) == GDT_Byte )
     {
-      buf->format = "B";
+      buf->format = (char*) "B";
       buf->itemsize = 1;
     }
     else if( *(arg4) == GDT_Int16 )
     {
-      buf->format = "h";
+      buf->format = (char*) "h";
       buf->itemsize = 2;
     }
     else if( *(arg4) == GDT_UInt16 )
     {
-      buf->format = "H";
+      buf->format = (char*) "H";
       buf->itemsize = 2;
     }
     else if( *(arg4) == GDT_Int32 )
     {
-      buf->format = "i";
+      buf->format = (char*) "i";
       buf->itemsize = 4;
     }
     else if( *(arg4) == GDT_UInt32 )
     {
-      buf->format = "I";
+      buf->format = (char*) "I";
       buf->itemsize = 4;
     }
     else if( *(arg4) == GDT_Float32 )
     {
-      buf->format = "f";
+      buf->format = (char*) "f";
       buf->itemsize = 4;
     }
     else if( *(arg4) == GDT_Float64 )
     {
-      buf->format = "F";
+      buf->format = (char*) "F";
       buf->itemsize = 8;
     }
     else
     {
-      buf->format = "B";
+      buf->format = (char*) "B";
       buf->itemsize = 1;
     }
+    Py_DECREF(resultobj);
     resultobj = PyMemoryView_FromBuffer(buf);
 #else
     PyErr_SetString( PyExc_RuntimeError, "needs Python 2.7 or later" );
-    SWIG_fail;
 #endif
   }
   return resultobj;
@@ -4229,9 +4507,9 @@ SWIGINTERN PyObject *_wrap_VirtualMem_Pin(PyObject *self, PyObject *args) {
   PyObject *argv[5];
   int ii;
   
-  if (!PyTuple_Check(args)) SWIG_fail;
+  if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
   argc = (int)PyObject_Length(args);
-  for (ii = 0; (ii < argc) && (ii < 4); ii++) {
+  for (ii = 0; (ii < 4) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
   if (argc == 1) {
@@ -4308,13 +4586,13 @@ SWIGINTERN PyObject *_wrap_VirtualMem_Pin(PyObject *self, PyObject *args) {
   }
   
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'VirtualMem_Pin'.\n"
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'VirtualMem_Pin'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    Pin(CPLVirtualMemShadow *,size_t,size_t,int)\n"
-    "    Pin(CPLVirtualMemShadow *,size_t,size_t)\n"
-    "    Pin(CPLVirtualMemShadow *,size_t)\n"
-    "    Pin(CPLVirtualMemShadow *)\n");
-  return NULL;
+    "    CPLVirtualMemShadow::Pin(size_t,size_t,int)\n"
+    "    CPLVirtualMemShadow::Pin(size_t,size_t)\n"
+    "    CPLVirtualMemShadow::Pin(size_t)\n"
+    "    CPLVirtualMemShadow::Pin()\n");
+  return 0;
 }
 
 
@@ -4373,6 +4651,33 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_OpenNumPyArray(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  PyArrayObject *arg1 = (PyArrayObject *) 0 ;
+  PyObject * obj0 = 0 ;
+  GDALDatasetShadow *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:OpenNumPyArray",&obj0)) SWIG_fail;
+  {
+    /* %typemap(in,numinputs=1) (PyArrayObject  *psArray) */
+    if (obj0 != NULL && PyArray_Check(obj0))
+    {
+      arg1 = (PyArrayObject*)(obj0);
+    }
+    else
+    {
+      PyErr_SetString(PyExc_TypeError, "not a numpy array");
+      SWIG_fail;
+    }
+  }
+  result = (GDALDatasetShadow *)OpenNumPyArray(arg1);
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_GetArrayFilename(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   PyArrayObject *arg1 = (PyArrayObject *) 0 ;
@@ -4411,10 +4716,10 @@ SWIGINTERN PyObject *_wrap_BandRasterIONumPy(PyObject *SWIGUNUSEDPARM(self), PyO
   PyObject *resultobj = 0;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   int arg2 ;
-  int arg3 ;
-  int arg4 ;
-  int arg5 ;
-  int arg6 ;
+  double arg3 ;
+  double arg4 ;
+  double arg5 ;
+  double arg6 ;
   PyArrayObject *arg7 = (PyArrayObject *) 0 ;
   int arg8 ;
   GDALRIOResampleAlg arg9 ;
@@ -4424,13 +4729,13 @@ SWIGINTERN PyObject *_wrap_BandRasterIONumPy(PyObject *SWIGUNUSEDPARM(self), PyO
   int res1 = 0 ;
   int val2 ;
   int ecode2 = 0 ;
-  int val3 ;
+  double val3 ;
   int ecode3 = 0 ;
-  int val4 ;
+  double val4 ;
   int ecode4 = 0 ;
-  int val5 ;
+  double val5 ;
   int ecode5 = 0 ;
-  int val6 ;
+  double val6 ;
   int ecode6 = 0 ;
   int val8 ;
   int ecode8 = 0 ;
@@ -4470,26 +4775,26 @@ SWIGINTERN PyObject *_wrap_BandRasterIONumPy(PyObject *SWIGUNUSEDPARM(self), PyO
     SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "BandRasterIONumPy" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
-  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  ecode3 = SWIG_AsVal_double(obj2, &val3);
   if (!SWIG_IsOK(ecode3)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "BandRasterIONumPy" "', argument " "3"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "BandRasterIONumPy" "', argument " "3"" of type '" "double""'");
   } 
-  arg3 = static_cast< int >(val3);
-  ecode4 = SWIG_AsVal_int(obj3, &val4);
+  arg3 = static_cast< double >(val3);
+  ecode4 = SWIG_AsVal_double(obj3, &val4);
   if (!SWIG_IsOK(ecode4)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "BandRasterIONumPy" "', argument " "4"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "BandRasterIONumPy" "', argument " "4"" of type '" "double""'");
   } 
-  arg4 = static_cast< int >(val4);
-  ecode5 = SWIG_AsVal_int(obj4, &val5);
+  arg4 = static_cast< double >(val4);
+  ecode5 = SWIG_AsVal_double(obj4, &val5);
   if (!SWIG_IsOK(ecode5)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "BandRasterIONumPy" "', argument " "5"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "BandRasterIONumPy" "', argument " "5"" of type '" "double""'");
   } 
-  arg5 = static_cast< int >(val5);
-  ecode6 = SWIG_AsVal_int(obj5, &val6);
+  arg5 = static_cast< double >(val5);
+  ecode6 = SWIG_AsVal_double(obj5, &val6);
   if (!SWIG_IsOK(ecode6)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "BandRasterIONumPy" "', argument " "6"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "BandRasterIONumPy" "', argument " "6"" of type '" "double""'");
   } 
-  arg6 = static_cast< int >(val6);
+  arg6 = static_cast< double >(val6);
   {
     /* %typemap(in,numinputs=1) (PyArrayObject  *psArray) */
     if (obj6 != NULL && PyArray_Check(obj6))
@@ -4518,16 +4823,16 @@ SWIGINTERN PyObject *_wrap_BandRasterIONumPy(PyObject *SWIGUNUSEDPARM(self), PyO
       /* callback_func typemap */
       if (obj9 && obj9 != Py_None ) {
         void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj9, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj9,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
         
         if ( cbfunction == GDALTermProgress ) {
           arg10 = GDALTermProgress;
         } else {
           if (!PyCallable_Check(obj9)) {
-            PyErr_SetString( PyExc_RuntimeError, 
+            PyErr_SetString( PyExc_RuntimeError,
               "Object given is not a Python function" );
             SWIG_fail;
           }
@@ -4676,16 +4981,16 @@ SWIGINTERN PyObject *_wrap_DatasetIONumPy(PyObject *SWIGUNUSEDPARM(self), PyObje
       /* callback_func typemap */
       if (obj9 && obj9 != Py_None ) {
         void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj9, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj9,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
         
         if ( cbfunction == GDALTermProgress ) {
           arg10 = GDALTermProgress;
         } else {
           if (!PyCallable_Check(obj9)) {
-            PyErr_SetString( PyExc_RuntimeError, 
+            PyErr_SetString( PyExc_RuntimeError,
               "Object given is not a Python function" );
             SWIG_fail;
           }
@@ -4915,6 +5220,7 @@ SWIGINTERN PyObject *_wrap_VirtualMemGetArray(PyObject *SWIGUNUSEDPARM(self), Py
     /* Keep a reference to the VirtualMem object */
     ar->base = obj0;
     Py_INCREF(obj0);
+    Py_DECREF(resultobj);
     resultobj = (PyObject*) ar;
   }
   return resultobj;
@@ -5037,35 +5343,28 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"delete_VirtualMem", _wrap_delete_VirtualMem, METH_VARARGS, (char *)"delete_VirtualMem(VirtualMem self)"},
 	 { (char *)"VirtualMem_GetAddr", _wrap_VirtualMem_GetAddr, METH_VARARGS, (char *)"VirtualMem_GetAddr(VirtualMem self)"},
 	 { (char *)"VirtualMem_Pin", _wrap_VirtualMem_Pin, METH_VARARGS, (char *)"\n"
-		"Pin(size_t start_offset = 0, size_t nsize = 0, int bWriteOp = 0)\n"
-		"Pin(size_t start_offset = 0, size_t nsize = 0)\n"
-		"Pin(size_t start_offset = 0)\n"
+		"Pin(size_t start_offset=0, size_t nsize=0, int bWriteOp=0)\n"
+		"Pin(size_t start_offset=0, size_t nsize=0)\n"
+		"Pin(size_t start_offset=0)\n"
 		"VirtualMem_Pin(VirtualMem self)\n"
 		""},
 	 { (char *)"VirtualMem_swigregister", VirtualMem_swigregister, METH_VARARGS, NULL},
-	 { (char *)"TermProgress_nocb", (PyCFunction) _wrap_TermProgress_nocb, METH_VARARGS | METH_KEYWORDS, (char *)"TermProgress_nocb(double dfProgress, char pszMessage = None, void pData = None) -> int"},
-	 { (char *)"GetArrayFilename", _wrap_GetArrayFilename, METH_VARARGS, (char *)"GetArrayFilename(PyArrayObject psArray) -> retStringAndCPLFree"},
+	 { (char *)"TermProgress_nocb", (PyCFunction) _wrap_TermProgress_nocb, METH_VARARGS | METH_KEYWORDS, (char *)"TermProgress_nocb(double dfProgress, char const * pszMessage=None, void * pData=None) -> int"},
+	 { (char *)"OpenNumPyArray", _wrap_OpenNumPyArray, METH_VARARGS, (char *)"OpenNumPyArray(PyArrayObject * psArray) -> Dataset"},
+	 { (char *)"GetArrayFilename", _wrap_GetArrayFilename, METH_VARARGS, (char *)"GetArrayFilename(PyArrayObject * psArray) -> retStringAndCPLFree *"},
 	 { (char *)"BandRasterIONumPy", (PyCFunction) _wrap_BandRasterIONumPy, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"BandRasterIONumPy(Band band, int bWrite, int xoff, int yoff, int xsize, \n"
-		"    int ysize, PyArrayObject psArray, int buf_type, \n"
-		"    GDALRIOResampleAlg resample_alg, GDALProgressFunc callback = None, \n"
-		"    void callback_data = None) -> CPLErr\n"
+		"BandRasterIONumPy(Band band, int bWrite, double xoff, double yoff, double xsize, double ysize, PyArrayObject * psArray, \n"
+		"    int buf_type, GDALRIOResampleAlg resample_alg, GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None) -> CPLErr\n"
 		""},
 	 { (char *)"DatasetIONumPy", (PyCFunction) _wrap_DatasetIONumPy, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"DatasetIONumPy(Dataset ds, int bWrite, int xoff, int yoff, int xsize, \n"
-		"    int ysize, PyArrayObject psArray, int buf_type, \n"
-		"    GDALRIOResampleAlg resample_alg, GDALProgressFunc callback = None, \n"
-		"    void callback_data = None) -> CPLErr\n"
+		"DatasetIONumPy(Dataset ds, int bWrite, int xoff, int yoff, int xsize, int ysize, PyArrayObject * psArray, \n"
+		"    int buf_type, GDALRIOResampleAlg resample_alg, GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None) -> CPLErr\n"
 		""},
 	 { (char *)"VirtualMemGetArray", _wrap_VirtualMemGetArray, METH_VARARGS, (char *)"VirtualMemGetArray(VirtualMem virtualmem)"},
-	 { (char *)"RATValuesIONumPyWrite", (PyCFunction) _wrap_RATValuesIONumPyWrite, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"RATValuesIONumPyWrite(RasterAttributeTable poRAT, int nField, int nStart, \n"
-		"    PyArrayObject psArray) -> CPLErr\n"
-		""},
-	 { (char *)"RATValuesIONumPyRead", (PyCFunction) _wrap_RATValuesIONumPyRead, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"RATValuesIONumPyRead(RasterAttributeTable poRAT, int nField, int nStart, \n"
-		"    int nLength) -> PyObject\n"
-		""},
+	 { (char *)"RATValuesIONumPyWrite", (PyCFunction) _wrap_RATValuesIONumPyWrite, METH_VARARGS | METH_KEYWORDS, (char *)"RATValuesIONumPyWrite(RasterAttributeTable poRAT, int nField, int nStart, PyArrayObject * psArray) -> CPLErr"},
+	 { (char *)"RATValuesIONumPyRead", (PyCFunction) _wrap_RATValuesIONumPyRead, METH_VARARGS | METH_KEYWORDS, (char *)"RATValuesIONumPyRead(RasterAttributeTable poRAT, int nField, int nStart, int nLength) -> PyObject *"},
 	 { NULL, NULL, 0, NULL }
 };
 
@@ -5144,18 +5443,18 @@ static swig_const_info swig_const_table[] = {
 #endif
 /* -----------------------------------------------------------------------------
  * Type initialization:
- * This problem is tough by the requirement that no dynamic 
- * memory is used. Also, since swig_type_info structures store pointers to 
+ * This problem is tough by the requirement that no dynamic
+ * memory is used. Also, since swig_type_info structures store pointers to
  * swig_cast_info structures and swig_cast_info structures store pointers back
- * to swig_type_info structures, we need some lookup code at initialization. 
- * The idea is that swig generates all the structures that are needed. 
- * The runtime then collects these partially filled structures. 
- * The SWIG_InitializeModule function takes these initial arrays out of 
+ * to swig_type_info structures, we need some lookup code at initialization.
+ * The idea is that swig generates all the structures that are needed.
+ * The runtime then collects these partially filled structures.
+ * The SWIG_InitializeModule function takes these initial arrays out of
  * swig_module, and does all the lookup, filling in the swig_module.types
  * array with the correct data and linking the correct swig_cast_info
  * structures together.
  *
- * The generated swig_type_info structures are assigned staticly to an initial 
+ * The generated swig_type_info structures are assigned staticly to an initial
  * array. We just loop through that array, and handle each type individually.
  * First we lookup if this type has been already loaded, and if so, use the
  * loaded structure instead of the generated one. Then we have to fill in the
@@ -5165,17 +5464,17 @@ static swig_const_info swig_const_table[] = {
  * a column is one of the swig_cast_info structures for that type.
  * The cast_initial array is actually an array of arrays, because each row has
  * a variable number of columns. So to actually build the cast linked list,
- * we find the array of casts associated with the type, and loop through it 
+ * we find the array of casts associated with the type, and loop through it
  * adding the casts to the list. The one last trick we need to do is making
  * sure the type pointer in the swig_cast_info struct is correct.
  *
- * First off, we lookup the cast->type name to see if it is already loaded. 
+ * First off, we lookup the cast->type name to see if it is already loaded.
  * There are three cases to handle:
  *  1) If the cast->type has already been loaded AND the type we are adding
  *     casting info to has not been loaded (it is in this module), THEN we
  *     replace the cast->type pointer with the type pointer that has already
  *     been loaded.
- *  2) If BOTH types (the one we are adding casting info to, and the 
+ *  2) If BOTH types (the one we are adding casting info to, and the
  *     cast->type) are loaded, THEN the cast info has already been loaded by
  *     the previous module so we just ignore it.
  *  3) Finally, if cast->type has not already been loaded, then we add that
@@ -5201,8 +5500,6 @@ SWIG_InitializeModule(void *clientdata) {
   swig_module_info *module_head, *iter;
   int found, init;
   
-  clientdata = clientdata;
-  
   /* check to see if the circular list has been setup, if not, set it up */
   if (swig_module.next==0) {
     /* Initialize the swig_module */
@@ -5220,7 +5517,7 @@ SWIG_InitializeModule(void *clientdata) {
     /* This is the first module loaded for this interpreter */
     /* so set the swig module into the interpreter */
     SWIG_SetModule(clientdata, &swig_module);
-    module_head = &swig_module;
+    /*module_head = &swig_module;*/
   } else {
     /* the interpreter has loaded a SWIG module, but has it loaded this one? */
     found=0;
@@ -5240,7 +5537,7 @@ SWIG_InitializeModule(void *clientdata) {
     module_head->next = &swig_module;
   }
   
-  /* When multiple interpeters are used, a module could have already been initialized in
+  /* When multiple interpreters are used, a module could have already been initialized in
        a different interpreter, but not yet have a pointer in this interpreter.
        In this case, we do not want to continue adding types... everything should be
        set up already */
@@ -5513,24 +5810,23 @@ extern "C" {
   swig_varlink_type(void) {
     static char varlink__doc__[] = "Swig var link object";
     static PyTypeObject varlink_type;
-    static int type_init = 0;  
+    static int type_init = 0;
     if (!type_init) {
-      const PyTypeObject tmp
-      = {
+      const PyTypeObject tmp = {
         /* PyObject header changed in Python 3 */
 #if PY_VERSION_HEX >= 0x03000000
-        PyVarObject_HEAD_INIT(&PyType_Type, 0)
+        PyVarObject_HEAD_INIT(NULL, 0)
 #else
         PyObject_HEAD_INIT(NULL)
-        0,                                  /* Number of items in variable part (ob_size) */
-#endif
-        (char *)"swigvarlink",              /* Type name (tp_name) */
-        sizeof(swig_varlinkobject),         /* Basic size (tp_basicsize) */
-        0,                                  /* Itemsize (tp_itemsize) */
-        (destructor) swig_varlink_dealloc,  /* Deallocator (tp_dealloc) */ 
-        (printfunc) swig_varlink_print,     /* Print (tp_print) */
-        (getattrfunc) swig_varlink_getattr, /* get attr (tp_getattr) */
-        (setattrfunc) swig_varlink_setattr, /* Set attr (tp_setattr) */
+        0,                                  /* ob_size */
+#endif
+        (char *)"swigvarlink",              /* tp_name */
+        sizeof(swig_varlinkobject),         /* tp_basicsize */
+        0,                                  /* tp_itemsize */
+        (destructor) swig_varlink_dealloc,  /* tp_dealloc */
+        (printfunc) swig_varlink_print,     /* tp_print */
+        (getattrfunc) swig_varlink_getattr, /* tp_getattr */
+        (setattrfunc) swig_varlink_setattr, /* tp_setattr */
         0,                                  /* tp_compare */
         (reprfunc) swig_varlink_repr,       /* tp_repr */
         0,                                  /* tp_as_number */
@@ -5554,16 +5850,21 @@ extern "C" {
 #if PY_VERSION_HEX >= 0x02030000
         0,                                  /* tp_del */
 #endif
+#if PY_VERSION_HEX >= 0x02060000
+        0,                                  /* tp_version */
+#endif
 #ifdef COUNT_ALLOCS
         0,0,0,0                             /* tp_alloc -> tp_next */
 #endif
       };
       varlink_type = tmp;
-      /* for Python 3 we already assigned ob_type in PyVarObject_HEAD_INIT() */
-#if PY_VERSION_HEX < 0x03000000
+      type_init = 1;
+#if PY_VERSION_HEX < 0x02020000
       varlink_type.ob_type = &PyType_Type;
+#else
+      if (PyType_Ready(&varlink_type) < 0)
+      return NULL;
 #endif
-      type_init = 1;
     }
     return &varlink_type;
   }
@@ -5614,7 +5915,7 @@ extern "C" {
     for (i = 0; constants[i].type; ++i) {
       switch(constants[i].type) {
       case SWIG_PY_POINTER:
-        obj = SWIG_NewPointerObj(constants[i].pvalue, *(constants[i]).ptype,0);
+        obj = SWIG_InternalNewPointerObj(constants[i].pvalue, *(constants[i]).ptype,0);
         break;
       case SWIG_PY_BINARY:
         obj = SWIG_NewPackedObj(constants[i].pvalue, constants[i].lvalue, *(constants[i].ptype));
@@ -5654,18 +5955,18 @@ extern "C" {
           }
         }
         if (ci) {
-          size_t shift = (ci->ptype) - types;
-          swig_type_info *ty = types_initial[shift];
-          size_t ldoc = (c - methods[i].ml_doc);
-          size_t lptr = strlen(ty->name)+2*sizeof(void*)+2;
-          char *ndoc = (char*)malloc(ldoc + lptr + 10);
-          if (ndoc) {
-            char *buff = ndoc;
-            void *ptr = (ci->type == SWIG_PY_POINTER) ? ci->pvalue : 0;
-            if (ptr) {
+          void *ptr = (ci->type == SWIG_PY_POINTER) ? ci->pvalue : 0;
+          if (ptr) {
+            size_t shift = (ci->ptype) - types;
+            swig_type_info *ty = types_initial[shift];
+            size_t ldoc = (c - methods[i].ml_doc);
+            size_t lptr = strlen(ty->name)+2*sizeof(void*)+2;
+            char *ndoc = (char*)malloc(ldoc + lptr + 10);
+            if (ndoc) {
+              char *buff = ndoc;
               strncpy(buff, methods[i].ml_doc, ldoc);
               buff += ldoc;
-              strncpy(buff, "swig_ptr: ", 10);
+              memcpy(buff, "swig_ptr: ", 10);
               buff += 10;
               SWIG_PackVoidPtr(buff, ptr, ty->name, lptr);
               methods[i].ml_doc = ndoc;
@@ -5695,10 +5996,19 @@ PyObject*
 void
 #endif
 SWIG_init(void) {
-  PyObject *m, *d;  
+  PyObject *m, *d, *md;
 #if PY_VERSION_HEX >= 0x03000000
   static struct PyModuleDef SWIG_module = {
+# if PY_VERSION_HEX >= 0x03020000
     PyModuleDef_HEAD_INIT,
+# else
+    {
+      PyObject_HEAD_INIT(NULL)
+      NULL, /* m_init */
+      0,    /* m_index */
+      NULL, /* m_copy */
+    },
+# endif
     (char *) SWIG_name,
     NULL,
     -1,
@@ -5710,6 +6020,49 @@ SWIG_init(void) {
   };
 #endif
   
+#if defined(SWIGPYTHON_BUILTIN)
+  static SwigPyClientData SwigPyObject_clientdata = {
+    0, 0, 0, 0, 0, 0, 0
+  };
+  static PyGetSetDef this_getset_def = {
+    (char *)"this", &SwigPyBuiltin_ThisClosure, NULL, NULL, NULL
+  };
+  static SwigPyGetSet thisown_getset_closure = {
+    (PyCFunction) SwigPyObject_own,
+    (PyCFunction) SwigPyObject_own
+  };
+  static PyGetSetDef thisown_getset_def = {
+    (char *)"thisown", SwigPyBuiltin_GetterClosure, SwigPyBuiltin_SetterClosure, NULL, &thisown_getset_closure
+  };
+  PyObject *metatype_args;
+  PyTypeObject *builtin_pytype;
+  int builtin_base_count;
+  swig_type_info *builtin_basetype;
+  PyObject *tuple;
+  PyGetSetDescrObject *static_getset;
+  PyTypeObject *metatype;
+  SwigPyClientData *cd;
+  PyObject *public_interface, *public_symbol;
+  PyObject *this_descr;
+  PyObject *thisown_descr;
+  int i;
+  
+  (void)builtin_pytype;
+  (void)builtin_base_count;
+  (void)builtin_basetype;
+  (void)tuple;
+  (void)static_getset;
+  
+  /* metatype is used to implement static member variables. */
+  metatype_args = Py_BuildValue("(s(O){})", "SwigPyObjectType", &PyType_Type);
+  assert(metatype_args);
+  metatype = (PyTypeObject *) PyType_Type.tp_call((PyObject *) &PyType_Type, metatype_args, NULL);
+  assert(metatype);
+  Py_DECREF(metatype_args);
+  metatype->tp_setattro = (setattrofunc) &SwigPyObjectType_setattro;
+  assert(PyType_Ready(metatype) >= 0);
+#endif
+  
   /* Fix SwigMethods to carry the callback ptrs when needed */
   SWIG_Python_FixMethods(SwigMethods, swig_const_table, swig_types, swig_type_initial);
   
@@ -5718,11 +6071,48 @@ SWIG_init(void) {
 #else
   m = Py_InitModule((char *) SWIG_name, SwigMethods);
 #endif
-  d = PyModule_GetDict(m);
+  md = d = PyModule_GetDict(m);
+  (void)md;
   
   SWIG_InitializeModule(0);
-  SWIG_InstallConstants(d,swig_const_table);
   
+#ifdef SWIGPYTHON_BUILTIN
+  SwigPyObject_stype = SWIG_MangledTypeQuery("_p_SwigPyObject");
+  assert(SwigPyObject_stype);
+  cd = (SwigPyClientData*) SwigPyObject_stype->clientdata;
+  if (!cd) {
+    SwigPyObject_stype->clientdata = &SwigPyObject_clientdata;
+    SwigPyObject_clientdata.pytype = SwigPyObject_TypeOnce();
+  } else if (SwigPyObject_TypeOnce()->tp_basicsize != cd->pytype->tp_basicsize) {
+    PyErr_SetString(PyExc_RuntimeError, "Import error: attempted to load two incompatible swig-generated modules.");
+# if PY_VERSION_HEX >= 0x03000000
+    return NULL;
+# else
+    return;
+# endif
+  }
+  
+  /* All objects have a 'this' attribute */
+  this_descr = PyDescr_NewGetSet(SwigPyObject_type(), &this_getset_def);
+  (void)this_descr;
+  
+  /* All objects have a 'thisown' attribute */
+  thisown_descr = PyDescr_NewGetSet(SwigPyObject_type(), &thisown_getset_def);
+  (void)thisown_descr;
+  
+  public_interface = PyList_New(0);
+  public_symbol = 0;
+  (void)public_symbol;
+  
+  PyDict_SetItemString(md, "__all__", public_interface);
+  Py_DECREF(public_interface);
+  for (i = 0; SwigMethods[i].ml_name != NULL; ++i)
+  SwigPyBuiltin_AddPublicSymbol(public_interface, SwigMethods[i].ml_name);
+  for (i = 0; swig_const_table[i].name != 0; ++i)
+  SwigPyBuiltin_AddPublicSymbol(public_interface, swig_const_table[i].name);
+#endif
+  
+  SWIG_InstallConstants(d,swig_const_table);
   
   
   import_array();
diff --git a/swig/python/extensions/gdal_wrap.cpp b/swig/python/extensions/gdal_wrap.cpp
index c1aa90b..0493dd3 100644
--- a/swig/python/extensions/gdal_wrap.cpp
+++ b/swig/python/extensions/gdal_wrap.cpp
@@ -1,14 +1,15 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.40
- * 
- * This file is not intended to be easily readable and contains a number of 
+ * Version 2.0.12
+ *
+ * This file is not intended to be easily readable and contains a number of
  * coding conventions designed to improve portability and efficiency. Do not make
- * changes to this file unless you know what you are doing--modify the SWIG 
- * interface file instead. 
+ * changes to this file unless you know what you are doing--modify the SWIG
+ * interface file instead.
  * ----------------------------------------------------------------------------- */
 
 #define SWIGPYTHON
+#define SED_HACKS
 #define SWIG_PYTHON_DIRECTOR_NO_VTABLE
 
 
@@ -66,28 +67,28 @@ template <typename T> T SwigValueInit() {
 #ifndef SWIGUNUSED
 # if defined(__GNUC__)
 #   if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
-#     define SWIGUNUSED __attribute__ ((__unused__)) 
+#     define SWIGUNUSED __attribute__ ((__unused__))
 #   else
 #     define SWIGUNUSED
 #   endif
 # elif defined(__ICC)
-#   define SWIGUNUSED __attribute__ ((__unused__)) 
+#   define SWIGUNUSED __attribute__ ((__unused__))
 # else
-#   define SWIGUNUSED 
+#   define SWIGUNUSED
 # endif
 #endif
 
 #ifndef SWIG_MSC_UNSUPPRESS_4505
 # if defined(_MSC_VER)
 #   pragma warning(disable : 4505) /* unreferenced local function has been removed */
-# endif 
+# endif
 #endif
 
 #ifndef SWIGUNUSEDPARM
 # ifdef __cplusplus
 #   define SWIGUNUSEDPARM(p)
 # else
-#   define SWIGUNUSEDPARM(p) p SWIGUNUSED 
+#   define SWIGUNUSEDPARM(p) p SWIGUNUSED
 # endif
 #endif
 
@@ -130,7 +131,7 @@ template <typename T> T SwigValueInit() {
 #   define SWIGSTDCALL __stdcall
 # else
 #   define SWIGSTDCALL
-# endif 
+# endif
 #endif
 
 /* Deal with Microsoft's attempt at deprecating C standard runtime functions */
@@ -145,8 +146,14 @@ template <typename T> T SwigValueInit() {
 
 
 
-/* Python.h has to appear first */
-#include <Python.h>
+#if defined(_DEBUG) && defined(SWIG_PYTHON_INTERPRETER_NO_DEBUG)
+/* Use debug wrappers with the Python release dll */
+# undef _DEBUG
+# include <Python.h>
+# define _DEBUG
+#else
+# include <Python.h>
+#endif
 
 /* -----------------------------------------------------------------------------
  * swigrun.swg
@@ -172,7 +179,7 @@ template <typename T> T SwigValueInit() {
   You can use the SWIGRUNTIME and SWIGRUNTIMEINLINE macros for
   creating a static or dynamic library from the SWIG runtime code.
   In 99.9% of the cases, SWIG just needs to declare them as 'static'.
-  
+
   But only do this if strictly necessary, ie, if you have problems
   with your compiler or suchlike.
 */
@@ -198,16 +205,16 @@ template <typename T> T SwigValueInit() {
 #define SWIG_POINTER_OWN           0x1
 
 
-/* 
+/*
    Flags/methods for returning states.
-   
-   The SWIG conversion methods, as ConvertPtr, return and integer 
+
+   The SWIG conversion methods, as ConvertPtr, return an integer
    that tells if the conversion was successful or not. And if not,
    an error code can be returned (see swigerrors.swg for the codes).
-   
+
    Use the following macros/flags to set or process the returning
    states.
-   
+
    In old versions of SWIG, code such as the following was usually written:
 
      if (SWIG_ConvertPtr(obj,vptr,ty.flags) != -1) {
@@ -240,23 +247,23 @@ template <typename T> T SwigValueInit() {
     } else {
       // fail code
     }
-    
+
    I.e., now SWIG_ConvertPtr can return new objects and you can
    identify the case and take care of the deallocation. Of course that
    also requires SWIG_ConvertPtr to return new result values, such as
 
-      int SWIG_ConvertPtr(obj, ptr,...) {         
-        if (<obj is ok>) {			       
-          if (<need new object>) {		       
-            *ptr = <ptr to new allocated object>; 
-            return SWIG_NEWOBJ;		       
-          } else {				       
-            *ptr = <ptr to old object>;	       
-            return SWIG_OLDOBJ;		       
-          } 				       
-        } else {				       
-          return SWIG_BADOBJ;		       
-        }					       
+      int SWIG_ConvertPtr(obj, ptr,...) {
+        if (<obj is ok>) {
+          if (<need new object>) {
+            *ptr = <ptr to new allocated object>;
+            return SWIG_NEWOBJ;
+          } else {
+            *ptr = <ptr to old object>;
+            return SWIG_OLDOBJ;
+          }
+        } else {
+          return SWIG_BADOBJ;
+        }
       }
 
    Of course, returning the plain '0(success)/-1(fail)' still works, but you can be
@@ -270,17 +277,17 @@ template <typename T> T SwigValueInit() {
        int fooi(int);
 
    and you call
- 
+
       food(1)   // cast rank '1'  (1 -> 1.0)
       fooi(1)   // cast rank '0'
 
    just use the SWIG_AddCast()/SWIG_CheckState()
 */
 
-#define SWIG_OK                    (0) 
+#define SWIG_OK                    (0)
 #define SWIG_ERROR                 (-1)
 #define SWIG_IsOK(r)               (r >= 0)
-#define SWIG_ArgError(r)           ((r != SWIG_ERROR) ? r : SWIG_TypeError)  
+#define SWIG_ArgError(r)           ((r != SWIG_ERROR) ? r : SWIG_TypeError)
 
 /* The CastRankLimit says how many bits are used for the cast rank */
 #define SWIG_CASTRANKLIMIT         (1 << 8)
@@ -311,14 +318,14 @@ template <typename T> T SwigValueInit() {
 #  endif
 #  define SWIG_CASTRANKMASK          ((SWIG_CASTRANKLIMIT) -1)
 #  define SWIG_CastRank(r)           (r & SWIG_CASTRANKMASK)
-SWIGINTERNINLINE int SWIG_AddCast(int r) { 
+SWIGINTERNINLINE int SWIG_AddCast(int r) {
   return SWIG_IsOK(r) ? ((SWIG_CastRank(r) < SWIG_MAXCASTRANK) ? (r + 1) : SWIG_ERROR) : r;
 }
-SWIGINTERNINLINE int SWIG_CheckState(int r) { 
-  return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0; 
+SWIGINTERNINLINE int SWIG_CheckState(int r) {
+  return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0;
 }
 #else /* no cast-rank mode */
-#  define SWIG_AddCast
+#  define SWIG_AddCast(r) (r)
 #  define SWIG_CheckState(r) (SWIG_IsOK(r) ? 1 : 0)
 #endif
 
@@ -362,7 +369,7 @@ typedef struct swig_module_info {
   void                    *clientdata;		/* Language specific module data */
 } swig_module_info;
 
-/* 
+/*
   Compare two type names skipping the space characters, therefore
   "char*" == "char *" and "Class<int>" == "Class<int >", etc.
 
@@ -382,18 +389,18 @@ SWIG_TypeNameComp(const char *f1, const char *l1,
 
 /*
   Check type equivalence in a name list like <name1>|<name2>|...
-  Return 0 if not equal, 1 if equal
+  Return 0 if equal, -1 if nb < tb, 1 if nb > tb
 */
 SWIGRUNTIME int
-SWIG_TypeEquiv(const char *nb, const char *tb) {
-  int equiv = 0;
+SWIG_TypeCmp(const char *nb, const char *tb) {
+  int equiv = 1;
   const char* te = tb + strlen(tb);
   const char* ne = nb;
-  while (!equiv && *ne) {
+  while (equiv != 0 && *ne) {
     for (nb = ne; *ne; ++ne) {
       if (*ne == '|') break;
     }
-    equiv = (SWIG_TypeNameComp(nb, ne, tb, te) == 0) ? 1 : 0;
+    equiv = SWIG_TypeNameComp(nb, ne, tb, te);
     if (*ne) ++ne;
   }
   return equiv;
@@ -401,24 +408,13 @@ SWIG_TypeEquiv(const char *nb, const char *tb) {
 
 /*
   Check type equivalence in a name list like <name1>|<name2>|...
-  Return 0 if equal, -1 if nb < tb, 1 if nb > tb
+  Return 0 if not equal, 1 if equal
 */
 SWIGRUNTIME int
-SWIG_TypeCompare(const char *nb, const char *tb) {
-  int equiv = 0;
-  const char* te = tb + strlen(tb);
-  const char* ne = nb;
-  while (!equiv && *ne) {
-    for (nb = ne; *ne; ++ne) {
-      if (*ne == '|') break;
-    }
-    equiv = (SWIG_TypeNameComp(nb, ne, tb, te) == 0) ? 1 : 0;
-    if (*ne) ++ne;
-  }
-  return equiv;
+SWIG_TypeEquiv(const char *nb, const char *tb) {
+  return SWIG_TypeCmp(nb, tb) == 0 ? 1 : 0;
 }
 
-
 /*
   Check the typename
 */
@@ -446,7 +442,7 @@ SWIG_TypeCheck(const char *c, swig_type_info *ty) {
   return 0;
 }
 
-/* 
+/*
   Identical to SWIG_TypeCheck, except strcmp is replaced with a pointer comparison
 */
 SWIGRUNTIME swig_cast_info *
@@ -481,7 +477,7 @@ SWIG_TypeCast(swig_cast_info *ty, void *ptr, int *newmemory) {
   return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr, newmemory);
 }
 
-/* 
+/*
    Dynamic pointer casting. Down an inheritance hierarchy
 */
 SWIGRUNTIME swig_type_info *
@@ -525,7 +521,7 @@ SWIG_TypePrettyName(const swig_type_info *type) {
     return type->name;
 }
 
-/* 
+/*
    Set the clientdata field for a type
 */
 SWIGRUNTIME void
@@ -533,14 +529,14 @@ SWIG_TypeClientData(swig_type_info *ti, void *clientdata) {
   swig_cast_info *cast = ti->cast;
   /* if (ti->clientdata == clientdata) return; */
   ti->clientdata = clientdata;
-  
+
   while (cast) {
     if (!cast->converter) {
       swig_type_info *tc = cast->type;
       if (!tc->clientdata) {
 	SWIG_TypeClientData(tc, clientdata);
       }
-    }    
+    }
     cast = cast->next;
   }
 }
@@ -549,18 +545,18 @@ SWIG_TypeNewClientData(swig_type_info *ti, void *clientdata) {
   SWIG_TypeClientData(ti, clientdata);
   ti->owndata = 1;
 }
-  
+
 /*
   Search for a swig_type_info structure only by mangled name
   Search is a O(log #types)
-  
-  We start searching at module start, and finish searching when start == end.  
+
+  We start searching at module start, and finish searching when start == end.
   Note: if start == end at the beginning of the function, we go all the way around
   the circular list.
 */
 SWIGRUNTIME swig_type_info *
-SWIG_MangledTypeQueryModule(swig_module_info *start, 
-                            swig_module_info *end, 
+SWIG_MangledTypeQueryModule(swig_module_info *start,
+                            swig_module_info *end,
 		            const char *name) {
   swig_module_info *iter = start;
   do {
@@ -569,11 +565,11 @@ SWIG_MangledTypeQueryModule(swig_module_info *start,
       register size_t r = iter->size - 1;
       do {
 	/* since l+r >= 0, we can (>> 1) instead (/ 2) */
-	register size_t i = (l + r) >> 1; 
+	register size_t i = (l + r) >> 1;
 	const char *iname = iter->types[i]->name;
 	if (iname) {
 	  register int compare = strcmp(name, iname);
-	  if (compare == 0) {	    
+	  if (compare == 0) {
 	    return iter->types[i];
 	  } else if (compare < 0) {
 	    if (i) {
@@ -598,14 +594,14 @@ SWIG_MangledTypeQueryModule(swig_module_info *start,
   Search for a swig_type_info structure for either a mangled name or a human readable name.
   It first searches the mangled names of the types, which is a O(log #types)
   If a type is not found it then searches the human readable names, which is O(#types).
-  
-  We start searching at module start, and finish searching when start == end.  
+
+  We start searching at module start, and finish searching when start == end.
   Note: if start == end at the beginning of the function, we go all the way around
   the circular list.
 */
 SWIGRUNTIME swig_type_info *
-SWIG_TypeQueryModule(swig_module_info *start, 
-                     swig_module_info *end, 
+SWIG_TypeQueryModule(swig_module_info *start,
+                     swig_module_info *end,
 		     const char *name) {
   /* STEP 1: Search the name field using binary search */
   swig_type_info *ret = SWIG_MangledTypeQueryModule(start, end, name);
@@ -624,12 +620,12 @@ SWIG_TypeQueryModule(swig_module_info *start,
       iter = iter->next;
     } while (iter != end);
   }
-  
+
   /* neither found a match */
   return 0;
 }
 
-/* 
+/*
    Pack binary data into a string
 */
 SWIGRUNTIME char *
@@ -645,7 +641,7 @@ SWIG_PackData(char *c, void *ptr, size_t sz) {
   return c;
 }
 
-/* 
+/*
    Unpack binary data from a string
 */
 SWIGRUNTIME const char *
@@ -659,21 +655,21 @@ SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
       uu = ((d - '0') << 4);
     else if ((d >= 'a') && (d <= 'f'))
       uu = ((d - ('a'-10)) << 4);
-    else 
+    else
       return (char *) 0;
     d = *(c++);
     if ((d >= '0') && (d <= '9'))
       uu |= (d - '0');
     else if ((d >= 'a') && (d <= 'f'))
       uu |= (d - ('a'-10));
-    else 
+    else
       return (char *) 0;
     *u = uu;
   }
   return c;
 }
 
-/* 
+/*
    Pack 'void *' into a string buffer.
 */
 SWIGRUNTIME char *
@@ -733,18 +729,18 @@ SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) {
 #endif
 
 /*  Errors in SWIG */
-#define  SWIG_UnknownError    	   -1 
-#define  SWIG_IOError        	   -2 
-#define  SWIG_RuntimeError   	   -3 
-#define  SWIG_IndexError     	   -4 
-#define  SWIG_TypeError      	   -5 
-#define  SWIG_DivisionByZero 	   -6 
-#define  SWIG_OverflowError  	   -7 
-#define  SWIG_SyntaxError    	   -8 
-#define  SWIG_ValueError     	   -9 
+#define  SWIG_UnknownError    	   -1
+#define  SWIG_IOError        	   -2
+#define  SWIG_RuntimeError   	   -3
+#define  SWIG_IndexError     	   -4
+#define  SWIG_TypeError      	   -5
+#define  SWIG_DivisionByZero 	   -6
+#define  SWIG_OverflowError  	   -7
+#define  SWIG_SyntaxError    	   -8
+#define  SWIG_ValueError     	   -9
 #define  SWIG_SystemError    	   -10
 #define  SWIG_AttributeError 	   -11
-#define  SWIG_MemoryError    	   -12 
+#define  SWIG_MemoryError    	   -12
 #define  SWIG_NullReferenceError   -13
 
 
@@ -756,7 +752,16 @@ SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) {
 #define PyInt_Check(x) PyLong_Check(x)
 #define PyInt_AsLong(x) PyLong_AsLong(x)
 #define PyInt_FromLong(x) PyLong_FromLong(x)
+#define PyInt_FromSize_t(x) PyLong_FromSize_t(x)
+#define PyString_Check(name) PyBytes_Check(name)
+#define PyString_FromString(x) PyUnicode_FromString(x)
 #define PyString_Format(fmt, args)  PyUnicode_Format(fmt, args)
+#define PyString_AsString(str) PyBytes_AsString(str)
+#define PyString_Size(str) PyBytes_Size(str)	
+#define PyString_InternFromString(key) PyUnicode_InternFromString(key)
+#define Py_TPFLAGS_HAVE_CLASS Py_TPFLAGS_BASETYPE
+#define PyString_AS_STRING(x) PyUnicode_AS_STRING(x)
+#define _PyLong_FromSsize_t(x) PyLong_FromSsize_t(x)
 
 #endif
 
@@ -896,6 +901,67 @@ PyObject *PyBool_FromLong(long ok)
 typedef int Py_ssize_t;
 # define PY_SSIZE_T_MAX INT_MAX
 # define PY_SSIZE_T_MIN INT_MIN
+typedef inquiry lenfunc;
+typedef intargfunc ssizeargfunc;
+typedef intintargfunc ssizessizeargfunc;
+typedef intobjargproc ssizeobjargproc;
+typedef intintobjargproc ssizessizeobjargproc;
+typedef getreadbufferproc readbufferproc;
+typedef getwritebufferproc writebufferproc;
+typedef getsegcountproc segcountproc;
+typedef getcharbufferproc charbufferproc;
+static long PyNumber_AsSsize_t (PyObject *x, void *SWIGUNUSEDPARM(exc))
+{
+  long result = 0;
+  PyObject *i = PyNumber_Int(x);
+  if (i) {
+    result = PyInt_AsLong(i);
+    Py_DECREF(i);
+  }
+  return result;
+}
+#endif
+
+#if PY_VERSION_HEX < 0x02050000
+#define PyInt_FromSize_t(x) PyInt_FromLong((long)x)
+#endif
+
+#if PY_VERSION_HEX < 0x02040000
+#define Py_VISIT(op)				\
+  do { 						\
+    if (op) {					\
+      int vret = visit((op), arg);		\
+      if (vret)					\
+        return vret;				\
+    }						\
+  } while (0)
+#endif
+
+#if PY_VERSION_HEX < 0x02030000
+typedef struct {
+  PyTypeObject type;
+  PyNumberMethods as_number;
+  PyMappingMethods as_mapping;
+  PySequenceMethods as_sequence;
+  PyBufferProcs as_buffer;
+  PyObject *name, *slots;
+} PyHeapTypeObject;
+#endif
+
+#if PY_VERSION_HEX < 0x02030000
+typedef destructor freefunc;
+#endif
+
+#if ((PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 6) || \
+     (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION > 0) || \
+     (PY_MAJOR_VERSION > 3))
+# define SWIGPY_USE_CAPSULE
+# define SWIGPY_CAPSULE_NAME ((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer_capsule" SWIG_TYPE_TABLE_NAME)
+#endif
+
+#if PY_VERSION_HEX < 0x03020000
+#define PyDescr_TYPE(x) (((PyDescrObject *)(x))->d_type)
+#define PyDescr_NAME(x) (((PyDescrObject *)(x))->d_name)
 #endif
 
 /* -----------------------------------------------------------------------------
@@ -1042,9 +1108,6 @@ SWIG_Python_AddErrorMsg(const char* mesg)
 
 #ifdef __cplusplus
 extern "C" {
-#if 0
-} /* cc-mode */
-#endif
 #endif
 
 /* -----------------------------------------------------------------------------
@@ -1070,27 +1133,24 @@ typedef struct swig_const_info {
  * Wrapper of PyInstanceMethod_New() used in Python 3
  * It is exported to the generated module, used for -fastproxy
  * ----------------------------------------------------------------------------- */
-SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func)
-{
 #if PY_VERSION_HEX >= 0x03000000
+SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *func)
+{
   return PyInstanceMethod_New(func);
+}
 #else
+SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *SWIGUNUSEDPARM(func))
+{
   return NULL;
-#endif
 }
+#endif
 
 #ifdef __cplusplus
-#if 0
-{ /* cc-mode */
-#endif
 }
 #endif
 
 
 /* -----------------------------------------------------------------------------
- * See the LICENSE file for information on copyright, usage and redistribution
- * of SWIG, and the README file for authors - http://www.swig.org/release.html.
- *
  * pyrun.swg
  *
  * This file contains the runtime support for Python modules
@@ -1105,7 +1165,15 @@ SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func)
 #define SWIG_Python_ConvertPtr(obj, pptr, type, flags)  SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, 0)
 #define SWIG_ConvertPtr(obj, pptr, type, flags)         SWIG_Python_ConvertPtr(obj, pptr, type, flags)
 #define SWIG_ConvertPtrAndOwn(obj,pptr,type,flags,own)  SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, own)
-#define SWIG_NewPointerObj(ptr, type, flags)            SWIG_Python_NewPointerObj(ptr, type, flags)
+
+#ifdef SWIGPYTHON_BUILTIN
+#define SWIG_NewPointerObj(ptr, type, flags)            SWIG_Python_NewPointerObj(self, ptr, type, flags)
+#else
+#define SWIG_NewPointerObj(ptr, type, flags)            SWIG_Python_NewPointerObj(NULL, ptr, type, flags)
+#endif
+
+#define SWIG_InternalNewPointerObj(ptr, type, flags)	SWIG_Python_NewPointerObj(NULL, ptr, type, flags)
+
 #define SWIG_CheckImplicit(ty)                          SWIG_Python_CheckImplicit(ty) 
 #define SWIG_AcquirePtr(ptr, src)                       SWIG_Python_AcquirePtr(ptr, src)
 #define swig_owntype                                    int
@@ -1120,7 +1188,7 @@ SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func)
 
 /* for C or C++ function pointers */
 #define SWIG_ConvertFunctionPtr(obj, pptr, type)        SWIG_Python_ConvertFunctionPtr(obj, pptr, type)
-#define SWIG_NewFunctionPtrObj(ptr, type)               SWIG_Python_NewPointerObj(ptr, type, 0)
+#define SWIG_NewFunctionPtrObj(ptr, type)               SWIG_Python_NewPointerObj(NULL, ptr, type, 0)
 
 /* for C++ member pointers, ie, member methods */
 #define SWIG_ConvertMember(obj, ptr, sz, ty)            SWIG_Python_ConvertPacked(obj, ptr, sz, ty)
@@ -1129,11 +1197,7 @@ SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func)
 
 /* Runtime API */
 
-#if PY_VERSION_HEX >= 0x03020000
-#define SWIG_PYTHON_USE_CAPSULE
-#endif
-
-#define SWIG_GetModule(clientdata)                      SWIG_Python_GetModule()
+#define SWIG_GetModule(clientdata)                      SWIG_Python_GetModule(clientdata)
 #define SWIG_SetModule(clientdata, pointer)             SWIG_Python_SetModule(pointer)
 #define SWIG_NewClientData(obj)                         SwigPyClientData_New(obj)
 
@@ -1159,7 +1223,7 @@ SWIG_Python_SetErrorObj(PyObject *errtype, PyObject *obj) {
 SWIGINTERN void 
 SWIG_Python_SetErrorMsg(PyObject *errtype, const char *msg) {
   SWIG_PYTHON_THREAD_BEGIN_BLOCK;
-  PyErr_SetString(errtype, (char *) msg);
+  PyErr_SetString(errtype, msg);
   SWIG_PYTHON_THREAD_END_BLOCK;
 }
 
@@ -1167,12 +1231,41 @@ SWIG_Python_SetErrorMsg(PyObject *errtype, const char *msg) {
 
 /* Set a constant value */
 
+#if defined(SWIGPYTHON_BUILTIN)
+
+SWIGINTERN void
+SwigPyBuiltin_AddPublicSymbol(PyObject *seq, const char *key) {
+  PyObject *s = PyString_InternFromString(key);
+  PyList_Append(seq, s);
+  Py_DECREF(s);
+}
+
+SWIGINTERN void
+SWIG_Python_SetConstant(PyObject *d, PyObject *public_interface, const char *name, PyObject *obj) {   
+#if PY_VERSION_HEX < 0x02030000
+  PyDict_SetItemString(d, (char *)name, obj);
+#else
+  PyDict_SetItemString(d, name, obj);
+#endif
+  Py_DECREF(obj);
+  if (public_interface)
+    SwigPyBuiltin_AddPublicSymbol(public_interface, name);
+}
+
+#else
+
 SWIGINTERN void
 SWIG_Python_SetConstant(PyObject *d, const char *name, PyObject *obj) {   
-  PyDict_SetItemString(d, (char*) name, obj);
+#if PY_VERSION_HEX < 0x02030000
+  PyDict_SetItemString(d, (char *)name, obj);
+#else
+  PyDict_SetItemString(d, name, obj);
+#endif
   Py_DECREF(obj);                            
 }
 
+#endif
+
 /* Append a value to the result obj */
 
 SWIGINTERN PyObject*
@@ -1233,6 +1326,14 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi
     }
   }  
   if (!PyTuple_Check(args)) {
+    if (min <= 1 && max >= 1) {
+      register int i;
+      objs[0] = args;
+      for (i = 1; i < max; ++i) {
+	objs[i] = 0;
+      }
+      return 2;
+    }
     PyErr_SetString(PyExc_SystemError, "UnpackTuple() argument list is not a tuple");
     return 0;
   } else {
@@ -1285,11 +1386,11 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi
 
 #define SWIG_POINTER_IMPLICIT_CONV  (SWIG_POINTER_DISOWN   << 1)
 
+#define SWIG_BUILTIN_TP_INIT	    (SWIG_POINTER_OWN << 2)
+#define SWIG_BUILTIN_INIT	    (SWIG_BUILTIN_TP_INIT | SWIG_POINTER_OWN)
+
 #ifdef __cplusplus
 extern "C" {
-#if 0
-} /* cc-mode */
-#endif
 #endif
 
 /*  How to access Py_None */
@@ -1340,6 +1441,7 @@ typedef struct {
   PyObject *destroy;
   int delargs;
   int implicitconv;
+  PyTypeObject *pytype;
 } SwigPyClientData;
 
 SWIGRUNTIMEINLINE int 
@@ -1406,13 +1508,13 @@ SwigPyClientData_New(PyObject* obj)
       data->delargs = 0;
     }
     data->implicitconv = 0;
+    data->pytype = 0;
     return data;
   }
 }
 
 SWIGRUNTIME void 
-SwigPyClientData_Del(SwigPyClientData* data)
-{
+SwigPyClientData_Del(SwigPyClientData *data) {
   Py_XDECREF(data->newraw);
   Py_XDECREF(data->newargs);
   Py_XDECREF(data->destroy);
@@ -1426,6 +1528,9 @@ typedef struct {
   swig_type_info *ty;
   int own;
   PyObject *next;
+#ifdef SWIGPYTHON_BUILTIN
+  PyObject *dict;
+#endif
 } SwigPyObject;
 
 SWIGRUNTIME PyObject *
@@ -1476,54 +1581,26 @@ SwigPyObject_repr(SwigPyObject *v, PyObject *args)
 #endif
 {
   const char *name = SWIG_TypePrettyName(v->ty);
-  PyObject *repr = SWIG_Python_str_FromFormat("<Swig Object of type '%s' at %p>", name, v);
+  PyObject *repr = SWIG_Python_str_FromFormat("<Swig Object of type '%s' at %p>", (name ? name : "unknown"), (void *)v);
   if (v->next) {
-#ifdef METH_NOARGS
+# ifdef METH_NOARGS
     PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next);
-#else
+# else
     PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next, args);
-#endif
-#if PY_VERSION_HEX >= 0x03000000
+# endif
+# if PY_VERSION_HEX >= 0x03000000
     PyObject *joined = PyUnicode_Concat(repr, nrep);
     Py_DecRef(repr);
     Py_DecRef(nrep);
     repr = joined;
-#else
+# else
     PyString_ConcatAndDel(&repr,nrep);
-#endif
+# endif
   }
   return repr;  
 }
 
 SWIGRUNTIME int
-SwigPyObject_print(SwigPyObject *v, FILE *fp, int SWIGUNUSEDPARM(flags))
-{
-  char *str;
-#ifdef METH_NOARGS
-  PyObject *repr = SwigPyObject_repr(v);
-#else
-  PyObject *repr = SwigPyObject_repr(v, NULL);
-#endif
-  if (repr) {
-    str = SWIG_Python_str_AsChar(repr); 
-    fputs(str, fp);
-    SWIG_Python_str_DelForPy3(str);
-    Py_DECREF(repr);
-    return 0; 
-  } else {
-    return 1; 
-  }
-}
-
-SWIGRUNTIME PyObject *
-SwigPyObject_str(SwigPyObject *v)
-{
-  char result[SWIG_BUFFER_SIZE];
-  return SWIG_PackVoidPtr(result, v->ptr, v->ty->name, sizeof(result)) ?
-    SWIG_Python_str_FromChar(result) : 0;
-}
-
-SWIGRUNTIME int
 SwigPyObject_compare(SwigPyObject *v, SwigPyObject *w)
 {
   void *i = v->ptr;
@@ -1540,27 +1617,43 @@ SwigPyObject_richcompare(SwigPyObject *v, SwigPyObject *w, int op)
     Py_INCREF(Py_NotImplemented);
     return Py_NotImplemented;
   }
-  if( (SwigPyObject_compare(v, w)==0) == (op == Py_EQ) )
-    res = Py_True;
-  else
-    res = Py_False;
-  Py_INCREF(res);
+  res = PyBool_FromLong( (SwigPyObject_compare(v, w)==0) == (op == Py_EQ) ? 1 : 0);
   return res;  
 }
 
 
-SWIGRUNTIME PyTypeObject* _PySwigObject_type(void);
+SWIGRUNTIME PyTypeObject* SwigPyObject_TypeOnce(void);
 
+#ifdef SWIGPYTHON_BUILTIN
+static swig_type_info *SwigPyObject_stype = 0;
+SWIGRUNTIME PyTypeObject*
+SwigPyObject_type(void) {
+    SwigPyClientData *cd;
+    assert(SwigPyObject_stype);
+    cd = (SwigPyClientData*) SwigPyObject_stype->clientdata;
+    assert(cd);
+    assert(cd->pytype);
+    return cd->pytype;
+}
+#else
 SWIGRUNTIME PyTypeObject*
 SwigPyObject_type(void) {
-  static PyTypeObject *SWIG_STATIC_POINTER(type) = _PySwigObject_type();
+  static PyTypeObject *SWIG_STATIC_POINTER(type) = SwigPyObject_TypeOnce();
   return type;
 }
+#endif
 
 SWIGRUNTIMEINLINE int
 SwigPyObject_Check(PyObject *op) {
+#ifdef SWIGPYTHON_BUILTIN
+  PyTypeObject *target_tp = SwigPyObject_type();
+  if (PyType_IsSubtype(op->ob_type, target_tp))
+    return 1;
+  return (strcmp(op->ob_type->tp_name, "SwigPyObject") == 0);
+#else
   return (Py_TYPE(op) == SwigPyObject_type())
     || (strcmp(Py_TYPE(op)->tp_name,"SwigPyObject") == 0);
+#endif
 }
 
 SWIGRUNTIME PyObject *
@@ -1664,8 +1757,10 @@ SwigPyObject_own(PyObject *v, PyObject *args)
   PyObject *val = 0;
 #if (PY_VERSION_HEX < 0x02020000)
   if (!PyArg_ParseTuple(args,(char *)"|O:own",&val))
-#else
+#elif (PY_VERSION_HEX < 0x02050000)
   if (!PyArg_UnpackTuple(args, (char *)"own", 0, 1, &val)) 
+#else
+  if (!PyArg_UnpackTuple(args, "own", 0, 1, &val)) 
 #endif
     {
       return NULL;
@@ -1697,7 +1792,7 @@ SwigPyObject_own(PyObject *v, PyObject *args)
 static PyMethodDef
 swigobject_methods[] = {
   {(char *)"disown",  (PyCFunction)SwigPyObject_disown,  METH_NOARGS,  (char *)"releases ownership of the pointer"},
-  {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_NOARGS,  (char *)"aquires ownership of the pointer"},
+  {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_NOARGS,  (char *)"acquires ownership of the pointer"},
   {(char *)"own",     (PyCFunction)SwigPyObject_own,     METH_VARARGS, (char *)"returns/sets ownership of the pointer"},
   {(char *)"append",  (PyCFunction)SwigPyObject_append,  METH_O,       (char *)"appends another 'this' object"},
   {(char *)"next",    (PyCFunction)SwigPyObject_next,    METH_NOARGS,  (char *)"returns the next 'this' object"},
@@ -1726,9 +1821,9 @@ SwigPyObject_getattr(SwigPyObject *sobj,char *name)
 #endif
 
 SWIGRUNTIME PyTypeObject*
-_PySwigObject_type(void) {
+SwigPyObject_TypeOnce(void) {
   static char swigobject_doc[] = "Swig object carries a C/C++ instance pointer";
-  
+
   static PyNumberMethods SwigPyObject_as_number = {
     (binaryfunc)0, /*nb_add*/
     (binaryfunc)0, /*nb_subtract*/
@@ -1775,85 +1870,89 @@ _PySwigObject_type(void) {
 #endif
   };
 
-  static PyTypeObject swigpyobject_type;  
+  static PyTypeObject swigpyobject_type;
   static int type_init = 0;
   if (!type_init) {
-    const PyTypeObject tmp
-      = {
-	/* PyObject header changed in Python 3 */
+    const PyTypeObject tmp = {
+      /* PyObject header changed in Python 3 */
 #if PY_VERSION_HEX >= 0x03000000
-	PyVarObject_HEAD_INIT(&PyType_Type, 0)
-#else    
-	PyObject_HEAD_INIT(NULL)
-	0,				    /* ob_size */
-#endif
-	(char *)"SwigPyObject",		    /* tp_name */
-	sizeof(SwigPyObject),		    /* tp_basicsize */
-	0,			            /* tp_itemsize */
-	(destructor)SwigPyObject_dealloc,   /* tp_dealloc */
-	(printfunc)SwigPyObject_print,	    /* tp_print */
+      PyVarObject_HEAD_INIT(NULL, 0)
+#else
+      PyObject_HEAD_INIT(NULL)
+      0,                                    /* ob_size */
+#endif
+      (char *)"SwigPyObject",               /* tp_name */
+      sizeof(SwigPyObject),                 /* tp_basicsize */
+      0,                                    /* tp_itemsize */
+      (destructor)SwigPyObject_dealloc,     /* tp_dealloc */
+      0,				    /* tp_print */
 #if PY_VERSION_HEX < 0x02020000
-	(getattrfunc)SwigPyObject_getattr,  /* tp_getattr */ 
+      (getattrfunc)SwigPyObject_getattr,    /* tp_getattr */
 #else
-	(getattrfunc)0,			    /* tp_getattr */ 
+      (getattrfunc)0,                       /* tp_getattr */
 #endif
-	(setattrfunc)0,			    /* tp_setattr */ 
+      (setattrfunc)0,                       /* tp_setattr */
 #if PY_VERSION_HEX >= 0x03000000
     0, /* tp_reserved in 3.0.1, tp_compare in 3.0.0 but not used */
 #else
-	(cmpfunc)SwigPyObject_compare,	    /* tp_compare */
-#endif
-	(reprfunc)SwigPyObject_repr,	    /* tp_repr */    
-	&SwigPyObject_as_number,	    /* tp_as_number */
-	0,				    /* tp_as_sequence */
-	0,				    /* tp_as_mapping */
-	(hashfunc)0,			    /* tp_hash */
-	(ternaryfunc)0,			    /* tp_call */
-	(reprfunc)SwigPyObject_str,	    /* tp_str */
-	PyObject_GenericGetAttr,            /* tp_getattro */
-	0,				    /* tp_setattro */
-	0,		                    /* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT,	            /* tp_flags */
-	swigobject_doc, 	            /* tp_doc */        
-	0,                                  /* tp_traverse */
-	0,                                  /* tp_clear */
-	(richcmpfunc)SwigPyObject_richcompare,           /* tp_richcompare */
-	0,                                  /* tp_weaklistoffset */
+      (cmpfunc)SwigPyObject_compare,        /* tp_compare */
+#endif
+      (reprfunc)SwigPyObject_repr,          /* tp_repr */
+      &SwigPyObject_as_number,              /* tp_as_number */
+      0,                                    /* tp_as_sequence */
+      0,                                    /* tp_as_mapping */
+      (hashfunc)0,                          /* tp_hash */
+      (ternaryfunc)0,                       /* tp_call */
+      0,				    /* tp_str */
+      PyObject_GenericGetAttr,              /* tp_getattro */
+      0,                                    /* tp_setattro */
+      0,                                    /* tp_as_buffer */
+      Py_TPFLAGS_DEFAULT,                   /* tp_flags */
+      swigobject_doc,                       /* tp_doc */
+      0,                                    /* tp_traverse */
+      0,                                    /* tp_clear */
+      (richcmpfunc)SwigPyObject_richcompare,/* tp_richcompare */
+      0,                                    /* tp_weaklistoffset */
 #if PY_VERSION_HEX >= 0x02020000
-	0,                                  /* tp_iter */
-	0,                                  /* tp_iternext */
-	swigobject_methods,		    /* tp_methods */ 
-	0,			            /* tp_members */
-	0,				    /* tp_getset */	    	
-	0,			            /* tp_base */	        
-	0,				    /* tp_dict */	    	
-	0,				    /* tp_descr_get */  	
-	0,				    /* tp_descr_set */  	
-	0,				    /* tp_dictoffset */ 	
-	0,				    /* tp_init */	    	
-	0,				    /* tp_alloc */	    	
-	0,			            /* tp_new */	    	
-	0,	                            /* tp_free */	   
-	0,                                  /* tp_is_gc */  
-	0,				    /* tp_bases */   
-	0,				    /* tp_mro */
-	0,				    /* tp_cache */   
-	0,				    /* tp_subclasses */
-	0,				    /* tp_weaklist */
+      0,                                    /* tp_iter */
+      0,                                    /* tp_iternext */
+      swigobject_methods,                   /* tp_methods */
+      0,                                    /* tp_members */
+      0,                                    /* tp_getset */
+      0,                                    /* tp_base */
+      0,                                    /* tp_dict */
+      0,                                    /* tp_descr_get */
+      0,                                    /* tp_descr_set */
+      0,                                    /* tp_dictoffset */
+      0,                                    /* tp_init */
+      0,                                    /* tp_alloc */
+      0,                                    /* tp_new */
+      0,                                    /* tp_free */
+      0,                                    /* tp_is_gc */
+      0,                                    /* tp_bases */
+      0,                                    /* tp_mro */
+      0,                                    /* tp_cache */
+      0,                                    /* tp_subclasses */
+      0,                                    /* tp_weaklist */
 #endif
 #if PY_VERSION_HEX >= 0x02030000
-	0,                                  /* tp_del */
+      0,                                    /* tp_del */
+#endif
+#if PY_VERSION_HEX >= 0x02060000
+      0,                                    /* tp_version */
 #endif
 #ifdef COUNT_ALLOCS
-	0,0,0,0                             /* tp_alloc -> tp_next */
+      0,0,0,0                               /* tp_alloc -> tp_next */
 #endif
-      };
+    };
     swigpyobject_type = tmp;
-    /* for Python 3 we already assigned ob_type in PyVarObject_HEAD_INIT() */
-#if PY_VERSION_HEX < 0x03000000
+    type_init = 1;
+#if PY_VERSION_HEX < 0x02020000
     swigpyobject_type.ob_type = &PyType_Type;
+#else
+    if (PyType_Ready(&swigpyobject_type) < 0)
+      return NULL;
 #endif
-    type_init = 1;
   }
   return &swigpyobject_type;
 }
@@ -1927,17 +2026,17 @@ SwigPyPacked_compare(SwigPyPacked *v, SwigPyPacked *w)
   return s ? s : strncmp((char *)v->pack, (char *)w->pack, 2*v->size);
 }
 
-SWIGRUNTIME PyTypeObject* _PySwigPacked_type(void);
+SWIGRUNTIME PyTypeObject* SwigPyPacked_TypeOnce(void);
 
 SWIGRUNTIME PyTypeObject*
 SwigPyPacked_type(void) {
-  static PyTypeObject *SWIG_STATIC_POINTER(type) = _PySwigPacked_type();
+  static PyTypeObject *SWIG_STATIC_POINTER(type) = SwigPyPacked_TypeOnce();
   return type;
 }
 
 SWIGRUNTIMEINLINE int
 SwigPyPacked_Check(PyObject *op) {
-  return ((op)->ob_type == _PySwigPacked_type()) 
+  return ((op)->ob_type == SwigPyPacked_TypeOnce()) 
     || (strcmp((op)->ob_type->tp_name,"SwigPyPacked") == 0);
 }
 
@@ -1952,83 +2051,87 @@ SwigPyPacked_dealloc(PyObject *v)
 }
 
 SWIGRUNTIME PyTypeObject*
-_PySwigPacked_type(void) {
+SwigPyPacked_TypeOnce(void) {
   static char swigpacked_doc[] = "Swig object carries a C/C++ instance pointer";
   static PyTypeObject swigpypacked_type;
-  static int type_init = 0;  
+  static int type_init = 0;
   if (!type_init) {
-    const PyTypeObject tmp
-      = {
-    /* PyObject header changed in Python 3 */
+    const PyTypeObject tmp = {
+      /* PyObject header changed in Python 3 */
 #if PY_VERSION_HEX>=0x03000000
-    PyVarObject_HEAD_INIT(&PyType_Type, 0)
+      PyVarObject_HEAD_INIT(NULL, 0)
 #else
-	PyObject_HEAD_INIT(NULL)
-    0,				    /* ob_size */	
-#endif
-	(char *)"SwigPyPacked",		    /* tp_name */	
-	sizeof(SwigPyPacked),		    /* tp_basicsize */	
-	0,				    /* tp_itemsize */	
-	(destructor)SwigPyPacked_dealloc,   /* tp_dealloc */	
-	(printfunc)SwigPyPacked_print,	    /* tp_print */   	
-	(getattrfunc)0,			    /* tp_getattr */ 	
-	(setattrfunc)0,			    /* tp_setattr */ 	
+      PyObject_HEAD_INIT(NULL)
+      0,                                    /* ob_size */
+#endif
+      (char *)"SwigPyPacked",               /* tp_name */
+      sizeof(SwigPyPacked),                 /* tp_basicsize */
+      0,                                    /* tp_itemsize */
+      (destructor)SwigPyPacked_dealloc,     /* tp_dealloc */
+      (printfunc)SwigPyPacked_print,        /* tp_print */
+      (getattrfunc)0,                       /* tp_getattr */
+      (setattrfunc)0,                       /* tp_setattr */
 #if PY_VERSION_HEX>=0x03000000
-    0, /* tp_reserved in 3.0.1 */
+      0, /* tp_reserved in 3.0.1 */
 #else
-    (cmpfunc)SwigPyPacked_compare,	    /* tp_compare */
-#endif
-	(reprfunc)SwigPyPacked_repr,	    /* tp_repr */
-	0,	                            /* tp_as_number */
-	0,				    /* tp_as_sequence */
-	0,				    /* tp_as_mapping */
-	(hashfunc)0,			    /* tp_hash */
-	(ternaryfunc)0,			    /* tp_call */
-	(reprfunc)SwigPyPacked_str,	    /* tp_str */
-	PyObject_GenericGetAttr,            /* tp_getattro */
-	0,				    /* tp_setattro */
-	0,		                    /* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT,	            /* tp_flags */
-	swigpacked_doc, 	            /* tp_doc */
-	0,                                  /* tp_traverse */
-	0,                                  /* tp_clear */
-	0,                                  /* tp_richcompare */
-	0,                                  /* tp_weaklistoffset */
+      (cmpfunc)SwigPyPacked_compare,        /* tp_compare */
+#endif
+      (reprfunc)SwigPyPacked_repr,          /* tp_repr */
+      0,                                    /* tp_as_number */
+      0,                                    /* tp_as_sequence */
+      0,                                    /* tp_as_mapping */
+      (hashfunc)0,                          /* tp_hash */
+      (ternaryfunc)0,                       /* tp_call */
+      (reprfunc)SwigPyPacked_str,           /* tp_str */
+      PyObject_GenericGetAttr,              /* tp_getattro */
+      0,                                    /* tp_setattro */
+      0,                                    /* tp_as_buffer */
+      Py_TPFLAGS_DEFAULT,                   /* tp_flags */
+      swigpacked_doc,                       /* tp_doc */
+      0,                                    /* tp_traverse */
+      0,                                    /* tp_clear */
+      0,                                    /* tp_richcompare */
+      0,                                    /* tp_weaklistoffset */
 #if PY_VERSION_HEX >= 0x02020000
-	0,                                  /* tp_iter */
-	0,                                  /* tp_iternext */
-	0,		                    /* tp_methods */ 
-	0,			            /* tp_members */
-	0,				    /* tp_getset */	    	
-	0,			            /* tp_base */	        
-	0,				    /* tp_dict */	    	
-	0,				    /* tp_descr_get */  	
-	0,				    /* tp_descr_set */  	
-	0,				    /* tp_dictoffset */ 	
-	0,				    /* tp_init */	    	
-	0,				    /* tp_alloc */	    	
-	0,			            /* tp_new */	    	
-	0, 	                            /* tp_free */	   
-        0,                                  /* tp_is_gc */  
-	0,				    /* tp_bases */   
-	0,				    /* tp_mro */
-	0,				    /* tp_cache */   
- 	0,				    /* tp_subclasses */
-	0,				    /* tp_weaklist */
+      0,                                    /* tp_iter */
+      0,                                    /* tp_iternext */
+      0,                                    /* tp_methods */
+      0,                                    /* tp_members */
+      0,                                    /* tp_getset */
+      0,                                    /* tp_base */
+      0,                                    /* tp_dict */
+      0,                                    /* tp_descr_get */
+      0,                                    /* tp_descr_set */
+      0,                                    /* tp_dictoffset */
+      0,                                    /* tp_init */
+      0,                                    /* tp_alloc */
+      0,                                    /* tp_new */
+      0,                                    /* tp_free */
+      0,                                    /* tp_is_gc */
+      0,                                    /* tp_bases */
+      0,                                    /* tp_mro */
+      0,                                    /* tp_cache */
+      0,                                    /* tp_subclasses */
+      0,                                    /* tp_weaklist */
 #endif
 #if PY_VERSION_HEX >= 0x02030000
-	0,                                  /* tp_del */
+      0,                                    /* tp_del */
+#endif
+#if PY_VERSION_HEX >= 0x02060000
+      0,                                    /* tp_version */
 #endif
 #ifdef COUNT_ALLOCS
-	0,0,0,0                             /* tp_alloc -> tp_next */
+      0,0,0,0                               /* tp_alloc -> tp_next */
 #endif
-      };
+    };
     swigpypacked_type = tmp;
-    /* for Python 3 the ob_type already assigned in PyVarObject_HEAD_INIT() */
-#if PY_VERSION_HEX < 0x03000000
+    type_init = 1;
+#if PY_VERSION_HEX < 0x02020000
     swigpypacked_type.ob_type = &PyType_Type;
+#else
+    if (PyType_Ready(&swigpypacked_type) < 0)
+      return NULL;
 #endif
-    type_init = 1;
   }
   return &swigpypacked_type;
 }
@@ -2075,10 +2178,13 @@ _SWIG_This(void)
     return SWIG_Python_str_FromChar("this");
 }
 
+static PyObject *swig_this = NULL;
+
 SWIGRUNTIME PyObject *
 SWIG_This(void)
 {
-  static PyObject *SWIG_STATIC_POINTER(swig_this) = _SWIG_This();
+  if (swig_this == NULL)
+    swig_this = _SWIG_This();
   return swig_this;
 }
 
@@ -2092,50 +2198,65 @@ SWIG_This(void)
 SWIGRUNTIME SwigPyObject *
 SWIG_Python_GetSwigThis(PyObject *pyobj) 
 {
-  if (SwigPyObject_Check(pyobj)) {
+  PyObject *obj;
+
+  if (SwigPyObject_Check(pyobj))
     return (SwigPyObject *) pyobj;
-  } else {
-    PyObject *obj = 0;
+
+#ifdef SWIGPYTHON_BUILTIN
+  (void)obj;
+# ifdef PyWeakref_CheckProxy
+  if (PyWeakref_CheckProxy(pyobj)) {
+    pyobj = PyWeakref_GET_OBJECT(pyobj);
+    if (pyobj && SwigPyObject_Check(pyobj))
+      return (SwigPyObject*) pyobj;
+  }
+# endif
+  return NULL;
+#else
+
+  obj = 0;
+
 #if (!defined(SWIG_PYTHON_SLOW_GETSET_THIS) && (PY_VERSION_HEX >= 0x02030000))
-    if (PyInstance_Check(pyobj)) {
-      obj = _PyInstance_Lookup(pyobj, SWIG_This());      
+  if (PyInstance_Check(pyobj)) {
+    obj = _PyInstance_Lookup(pyobj, SWIG_This());      
+  } else {
+    PyObject **dictptr = _PyObject_GetDictPtr(pyobj);
+    if (dictptr != NULL) {
+      PyObject *dict = *dictptr;
+      obj = dict ? PyDict_GetItem(dict, SWIG_This()) : 0;
     } else {
-      PyObject **dictptr = _PyObject_GetDictPtr(pyobj);
-      if (dictptr != NULL) {
-	PyObject *dict = *dictptr;
-	obj = dict ? PyDict_GetItem(dict, SWIG_This()) : 0;
-      } else {
 #ifdef PyWeakref_CheckProxy
-	if (PyWeakref_CheckProxy(pyobj)) {
-	  PyObject *wobj = PyWeakref_GET_OBJECT(pyobj);
-	  return wobj ? SWIG_Python_GetSwigThis(wobj) : 0;
-	}
+      if (PyWeakref_CheckProxy(pyobj)) {
+	PyObject *wobj = PyWeakref_GET_OBJECT(pyobj);
+	return wobj ? SWIG_Python_GetSwigThis(wobj) : 0;
+      }
 #endif
-	obj = PyObject_GetAttr(pyobj,SWIG_This());
-	if (obj) {
-	  Py_DECREF(obj);
-	} else {
-	  if (PyErr_Occurred()) PyErr_Clear();
-	  return 0;
-	}
+      obj = PyObject_GetAttr(pyobj,SWIG_This());
+      if (obj) {
+	Py_DECREF(obj);
+      } else {
+	if (PyErr_Occurred()) PyErr_Clear();
+	return 0;
       }
     }
+  }
 #else
-    obj = PyObject_GetAttr(pyobj,SWIG_This());
-    if (obj) {
-      Py_DECREF(obj);
-    } else {
-      if (PyErr_Occurred()) PyErr_Clear();
-      return 0;
-    }
+  obj = PyObject_GetAttr(pyobj,SWIG_This());
+  if (obj) {
+    Py_DECREF(obj);
+  } else {
+    if (PyErr_Occurred()) PyErr_Clear();
+    return 0;
+  }
 #endif
-    if (obj && !SwigPyObject_Check(obj)) {
-      /* a PyObject is called 'this', try to get the 'real this'
-	 SwigPyObject from it */ 
-      return SWIG_Python_GetSwigThis(obj);
-    }
-    return (SwigPyObject *)obj;
+  if (obj && !SwigPyObject_Check(obj)) {
+    /* a PyObject is called 'this', try to get the 'real this'
+       SwigPyObject from it */ 
+    return SWIG_Python_GetSwigThis(obj);
   }
+  return (SwigPyObject *)obj;
+#endif
 }
 
 /* Acquire a pointer value */
@@ -2157,91 +2278,105 @@ SWIG_Python_AcquirePtr(PyObject *obj, int own) {
 
 SWIGRUNTIME int
 SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int flags, int *own) {
-  if (!obj) return SWIG_ERROR;
-  if (obj == Py_None) {
-    if (ptr) *ptr = 0;
+  int res;
+  SwigPyObject *sobj;
+  int implicit_conv = (flags & SWIG_POINTER_IMPLICIT_CONV) != 0;
+
+  if (!obj)
+    return SWIG_ERROR;
+  if (obj == Py_None && !implicit_conv) {
+    if (ptr)
+      *ptr = 0;
     return SWIG_OK;
-  } else {
-    SwigPyObject *sobj = SWIG_Python_GetSwigThis(obj);
+  }
+
+  res = SWIG_ERROR;
+
+  sobj = SWIG_Python_GetSwigThis(obj);
+  if (own)
+    *own = 0;
+  while (sobj) {
+    void *vptr = sobj->ptr;
+    if (ty) {
+      swig_type_info *to = sobj->ty;
+      if (to == ty) {
+        /* no type cast needed */
+        if (ptr) *ptr = vptr;
+        break;
+      } else {
+        swig_cast_info *tc = SWIG_TypeCheck(to->name,ty);
+        if (!tc) {
+          sobj = (SwigPyObject *)sobj->next;
+        } else {
+          if (ptr) {
+            int newmemory = 0;
+            *ptr = SWIG_TypeCast(tc,vptr,&newmemory);
+            if (newmemory == SWIG_CAST_NEW_MEMORY) {
+              assert(own); /* badly formed typemap which will lead to a memory leak - it must set and use own to delete *ptr */
+              if (own)
+                *own = *own | SWIG_CAST_NEW_MEMORY;
+            }
+          }
+          break;
+        }
+      }
+    } else {
+      if (ptr) *ptr = vptr;
+      break;
+    }
+  }
+  if (sobj) {
     if (own)
-      *own = 0;
-    while (sobj) {
-      void *vptr = sobj->ptr;
-      if (ty) {
-	swig_type_info *to = sobj->ty;
-	if (to == ty) {
-	  /* no type cast needed */
-	  if (ptr) *ptr = vptr;
-	  break;
-	} else {
-	  swig_cast_info *tc = SWIG_TypeCheck(to->name,ty);
-	  if (!tc) {
-	    sobj = (SwigPyObject *)sobj->next;
-	  } else {
-	    if (ptr) {
-              int newmemory = 0;
-              *ptr = SWIG_TypeCast(tc,vptr,&newmemory);
-              if (newmemory == SWIG_CAST_NEW_MEMORY) {
-                assert(own);
-                if (own)
-                  *own = *own | SWIG_CAST_NEW_MEMORY;
+      *own = *own | sobj->own;
+    if (flags & SWIG_POINTER_DISOWN) {
+      sobj->own = 0;
+    }
+    res = SWIG_OK;
+  } else {
+    if (implicit_conv) {
+      SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0;
+      if (data && !data->implicitconv) {
+        PyObject *klass = data->klass;
+        if (klass) {
+          PyObject *impconv;
+          data->implicitconv = 1; /* avoid recursion and call 'explicit' constructors*/
+          impconv = SWIG_Python_CallFunctor(klass, obj);
+          data->implicitconv = 0;
+          if (PyErr_Occurred()) {
+            PyErr_Clear();
+            impconv = 0;
+          }
+          if (impconv) {
+            SwigPyObject *iobj = SWIG_Python_GetSwigThis(impconv);
+            if (iobj) {
+              void *vptr;
+              res = SWIG_Python_ConvertPtrAndOwn((PyObject*)iobj, &vptr, ty, 0, 0);
+              if (SWIG_IsOK(res)) {
+                if (ptr) {
+                  *ptr = vptr;
+                  /* transfer the ownership to 'ptr' */
+                  iobj->own = 0;
+                  res = SWIG_AddCast(res);
+                  res = SWIG_AddNewMask(res);
+                } else {
+                  res = SWIG_AddCast(res);		    
+                }
               }
             }
-	    break;
-	  }
-	}
-      } else {
-	if (ptr) *ptr = vptr;
-	break;
+            Py_DECREF(impconv);
+          }
+        }
       }
     }
-    if (sobj) {
-      if (own)
-        *own = *own | sobj->own;
-      if (flags & SWIG_POINTER_DISOWN) {
-	sobj->own = 0;
-      }
-      return SWIG_OK;
-    } else {
-      int res = SWIG_ERROR;
-      if (flags & SWIG_POINTER_IMPLICIT_CONV) {
-	SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0;
-	if (data && !data->implicitconv) {
-	  PyObject *klass = data->klass;
-	  if (klass) {
-	    PyObject *impconv;
-	    data->implicitconv = 1; /* avoid recursion and call 'explicit' constructors*/
-	    impconv = SWIG_Python_CallFunctor(klass, obj);
-	    data->implicitconv = 0;
-	    if (PyErr_Occurred()) {
-	      PyErr_Clear();
-	      impconv = 0;
-	    }
-	    if (impconv) {
-	      SwigPyObject *iobj = SWIG_Python_GetSwigThis(impconv);
-	      if (iobj) {
-		void *vptr;
-		res = SWIG_Python_ConvertPtrAndOwn((PyObject*)iobj, &vptr, ty, 0, 0);
-		if (SWIG_IsOK(res)) {
-		  if (ptr) {
-		    *ptr = vptr;
-		    /* transfer the ownership to 'ptr' */
-		    iobj->own = 0;
-		    res = SWIG_AddCast(res);
-		    res = SWIG_AddNewMask(res);
-		  } else {
-		    res = SWIG_AddCast(res);		    
-		  }
-		}
-	      }
-	      Py_DECREF(impconv);
-	    }
-	  }
-	}
-      }
-      return res;
+    if (!SWIG_IsOK(res) && obj == Py_None) {
+      if (ptr)
+        *ptr = 0;
+      if (PyErr_Occurred())
+        PyErr_Clear();
+      res = SWIG_OK;
     }
   }
+  return res;
 }
 
 /* Convert a function ptr value */
@@ -2328,23 +2463,29 @@ SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this)
   } else {
 #if PY_VERSION_HEX >= 0x03000000
     inst = PyBaseObject_Type.tp_new((PyTypeObject*) data->newargs, Py_None, Py_None);
-    PyObject_SetAttr(inst, SWIG_This(), swig_this);
-    Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
+    if (inst) {
+      PyObject_SetAttr(inst, SWIG_This(), swig_this);
+      Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
+    }
 #else
     PyObject *dict = PyDict_New();
-    PyDict_SetItem(dict, SWIG_This(), swig_this);
-    inst = PyInstance_NewRaw(data->newargs, dict);
-    Py_DECREF(dict);
+    if (dict) {
+      PyDict_SetItem(dict, SWIG_This(), swig_this);
+      inst = PyInstance_NewRaw(data->newargs, dict);
+      Py_DECREF(dict);
+    }
 #endif
   }
   return inst;
 #else
 #if (PY_VERSION_HEX >= 0x02010000)
-  PyObject *inst;
+  PyObject *inst = 0;
   PyObject *dict = PyDict_New();
-  PyDict_SetItem(dict, SWIG_This(), swig_this);
-  inst = PyInstance_NewRaw(data->newargs, dict);
-  Py_DECREF(dict);
+  if (dict) {
+    PyDict_SetItem(dict, SWIG_This(), swig_this);
+    inst = PyInstance_NewRaw(data->newargs, dict);
+    Py_DECREF(dict);
+  }
   return (PyObject *) inst;
 #else
   PyInstanceObject *inst = PyObject_NEW(PyInstanceObject, &PyInstance_Type);
@@ -2395,7 +2536,7 @@ SWIG_Python_SetSwigThis(PyObject *inst, PyObject *swig_this)
 SWIGINTERN PyObject *
 SWIG_Python_InitShadowInstance(PyObject *args) {
   PyObject *obj[2];
-  if (!SWIG_Python_UnpackTuple(args,(char*)"swiginit", 2, 2, obj)) {
+  if (!SWIG_Python_UnpackTuple(args, "swiginit", 2, 2, obj)) {
     return NULL;
   } else {
     SwigPyObject *sthis = SWIG_Python_GetSwigThis(obj[0]);
@@ -2411,22 +2552,52 @@ SWIG_Python_InitShadowInstance(PyObject *args) {
 /* Create a new pointer object */
 
 SWIGRUNTIME PyObject *
-SWIG_Python_NewPointerObj(void *ptr, swig_type_info *type, int flags) {
-  if (!ptr) {
+SWIG_Python_NewPointerObj(PyObject *self, void *ptr, swig_type_info *type, int flags) {
+  SwigPyClientData *clientdata;
+  PyObject * robj;
+  int own;
+
+  if (!ptr)
     return SWIG_Py_Void();
-  } else {
-    int own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0;
-    PyObject *robj = SwigPyObject_New(ptr, type, own);
-    SwigPyClientData *clientdata = type ? (SwigPyClientData *)(type->clientdata) : 0;
-    if (clientdata && !(flags & SWIG_POINTER_NOSHADOW)) {
-      PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj);
-      if (inst) {
-	Py_DECREF(robj);
-	robj = inst;
+
+  clientdata = type ? (SwigPyClientData *)(type->clientdata) : 0;
+  own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0;
+  if (clientdata && clientdata->pytype) {
+    SwigPyObject *newobj;
+    if (flags & SWIG_BUILTIN_TP_INIT) {
+      newobj = (SwigPyObject*) self;
+      if (newobj->ptr) {
+        PyObject *next_self = clientdata->pytype->tp_alloc(clientdata->pytype, 0);
+        while (newobj->next)
+	  newobj = (SwigPyObject *) newobj->next;
+        newobj->next = next_self;
+        newobj = (SwigPyObject *)next_self;
       }
+    } else {
+      newobj = PyObject_New(SwigPyObject, clientdata->pytype);
+    }
+    if (newobj) {
+      newobj->ptr = ptr;
+      newobj->ty = type;
+      newobj->own = own;
+      newobj->next = 0;
+#ifdef SWIGPYTHON_BUILTIN
+      newobj->dict = 0;
+#endif
+      return (PyObject*) newobj;
     }
-    return robj;
+    return SWIG_Py_Void();
+  }
+
+  assert(!(flags & SWIG_BUILTIN_TP_INIT));
+
+  robj = SwigPyObject_New(ptr, type, own);
+  if (robj && clientdata && !(flags & SWIG_POINTER_NOSHADOW)) {
+    PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj);
+    Py_DECREF(robj);
+    robj = inst;
   }
+  return robj;
 }
 
 /* Create a new packed object */
@@ -2445,19 +2616,19 @@ void *SWIG_ReturnGlobalTypeList(void *);
 #endif
 
 SWIGRUNTIME swig_module_info *
-SWIG_Python_GetModule(void) {
+SWIG_Python_GetModule(void *SWIGUNUSEDPARM(clientdata)) {
   static void *type_pointer = (void *)0;
   /* first check if module already created */
   if (!type_pointer) {
 #ifdef SWIG_LINK_RUNTIME
     type_pointer = SWIG_ReturnGlobalTypeList((void *)0);
 #else
-#ifdef SWIG_PYTHON_USE_CAPSULE
-    type_pointer = PyCapsule_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer" SWIG_TYPE_TABLE_NAME, 0);
-#else
+# ifdef SWIGPY_USE_CAPSULE
+    type_pointer = PyCapsule_Import(SWIGPY_CAPSULE_NAME, 0);
+# else
     type_pointer = PyCObject_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
 				    (char*)"type_pointer" SWIG_TYPE_TABLE_NAME);
-#endif
+# endif
     if (PyErr_Occurred()) {
       PyErr_Clear();
       type_pointer = (void *)0;
@@ -2500,26 +2671,19 @@ PyModule_AddObject(PyObject *m, char *name, PyObject *o)
 #endif
 
 SWIGRUNTIME void
-#ifdef SWIG_PYTHON_USE_CAPSULE
-SWIG_Python_DestroyModule(PyObject *capsule)
-{
-  swig_module_info *swig_module;
-  swig_type_info **types;
-  size_t i;
-  swig_module = (swig_module_info *)PyCapsule_GetPointer(capsule, (char*)"swig_runtime_data" SWIG_RUNTIME_VERSION);
-  if (swig_module == NULL)
-  {
-    PyErr_Clear();
-    return;
-  }
-  types = swig_module->types;
+#ifdef SWIGPY_USE_CAPSULE
+SWIG_Python_DestroyModule(PyObject *obj)
 #else
 SWIG_Python_DestroyModule(void *vptr)
+#endif
 {
+#ifdef SWIGPY_USE_CAPSULE
+  swig_module_info *swig_module = (swig_module_info *) PyCapsule_GetPointer(obj, SWIGPY_CAPSULE_NAME);
+#else
   swig_module_info *swig_module = (swig_module_info *) vptr;
+#endif
   swig_type_info **types = swig_module->types;
   size_t i;
-#endif
   for (i =0; i < swig_module->size; ++i) {
     swig_type_info *ty = types[i];
     if (ty->owndata) {
@@ -2528,31 +2692,33 @@ SWIG_Python_DestroyModule(void *vptr)
     }
   }
   Py_DECREF(SWIG_This());
+  swig_this = NULL;
 }
 
 SWIGRUNTIME void
 SWIG_Python_SetModule(swig_module_info *swig_module) {
-  static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} };/* Sentinel */
-
 #if PY_VERSION_HEX >= 0x03000000
  /* Add a dummy module object into sys.modules */
   PyObject *module = PyImport_AddModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION);
 #else
-  PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
-				   swig_empty_runtime_method_table);
+  static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} }; /* Sentinel */
+  PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION, swig_empty_runtime_method_table);
 #endif
-#ifdef SWIG_PYTHON_USE_CAPSULE
-  PyObject *pointer = PyCapsule_New((void *) swig_module,
-                                    (char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer" SWIG_TYPE_TABLE_NAME,
-                                    SWIG_Python_DestroyModule);
+#ifdef SWIGPY_USE_CAPSULE
+  PyObject *pointer = PyCapsule_New((void *) swig_module, SWIGPY_CAPSULE_NAME, SWIG_Python_DestroyModule);
+  if (pointer && module) {
+    PyModule_AddObject(module, (char*)"type_pointer_capsule" SWIG_TYPE_TABLE_NAME, pointer);
+  } else {
+    Py_XDECREF(pointer);
+  }
 #else
   PyObject *pointer = PyCObject_FromVoidPtr((void *) swig_module, SWIG_Python_DestroyModule);
-#endif
   if (pointer && module) {
     PyModule_AddObject(module, (char*)"type_pointer" SWIG_TYPE_TABLE_NAME, pointer);
   } else {
     Py_XDECREF(pointer);
   }
+#endif
 }
 
 /* The python cached type query */
@@ -2570,17 +2736,17 @@ SWIG_Python_TypeQuery(const char *type)
   PyObject *obj = PyDict_GetItem(cache, key);
   swig_type_info *descriptor;
   if (obj) {
-#ifdef SWIG_PYTHON_USE_CAPSULE
-    descriptor = (swig_type_info *) PyCapsule_GetPointer(obj, (char*)"swig_type_info");
+#ifdef SWIGPY_USE_CAPSULE
+    descriptor = (swig_type_info *) PyCapsule_GetPointer(obj, NULL);
 #else
     descriptor = (swig_type_info *) PyCObject_AsVoidPtr(obj);
 #endif
   } else {
-    swig_module_info *swig_module = SWIG_Python_GetModule();
+    swig_module_info *swig_module = SWIG_GetModule(0);
     descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type);
     if (descriptor) {
-#ifdef SWIG_PYTHON_USE_CAPSULE
-      obj = PyCapsule_New(descriptor, (char*)"swig_type_info", NULL);
+#ifdef SWIGPY_USE_CAPSULE
+      obj = PyCapsule_New((void*) descriptor, NULL, NULL);
 #else
       obj = PyCObject_FromVoidPtr(descriptor, NULL);
 #endif
@@ -2644,7 +2810,7 @@ SwigPyObject_GetDesc(PyObject *self)
 {
   SwigPyObject *v = (SwigPyObject *)self;
   swig_type_info *ty = v ? v->ty : 0;
-  return ty ? ty->str : (char*)"";
+  return ty ? ty->str : "";
 }
 
 SWIGRUNTIME void
@@ -2687,7 +2853,7 @@ SWIG_Python_TypeError(const char *type, PyObject *obj)
 
 /* Convert a pointer value, signal an exception on a type mismatch */
 SWIGRUNTIME void *
-SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int argnum, int flags) {
+SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int SWIGUNUSEDPARM(argnum), int flags) {
   void *result;
   if (SWIG_Python_ConvertPtr(obj, &result, ty, flags) == -1) {
     PyErr_Clear();
@@ -2701,11 +2867,61 @@ SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int argnum, int flags)
   return result;
 }
 
+#ifdef SWIGPYTHON_BUILTIN
+SWIGRUNTIME int
+SWIG_Python_NonDynamicSetAttr(PyObject *obj, PyObject *name, PyObject *value) {
+  PyTypeObject *tp = obj->ob_type;
+  PyObject *descr;
+  PyObject *encoded_name;
+  descrsetfunc f;
+  int res = -1;
+
+# ifdef Py_USING_UNICODE
+  if (PyString_Check(name)) {
+    name = PyUnicode_Decode(PyString_AsString(name), PyString_Size(name), NULL, NULL);
+    if (!name)
+      return -1;
+  } else if (!PyUnicode_Check(name))
+# else
+  if (!PyString_Check(name))
+# endif
+  {
+    PyErr_Format(PyExc_TypeError, "attribute name must be string, not '%.200s'", name->ob_type->tp_name);
+    return -1;
+  } else {
+    Py_INCREF(name);
+  }
+
+  if (!tp->tp_dict) {
+    if (PyType_Ready(tp) < 0)
+      goto done;
+  }
+
+  descr = _PyType_Lookup(tp, name);
+  f = NULL;
+  if (descr != NULL)
+    f = descr->ob_type->tp_descr_set;
+  if (!f) {
+    if (PyString_Check(name)) {
+      encoded_name = name;
+      Py_INCREF(name);
+    } else {
+      encoded_name = PyUnicode_AsUTF8String(name);
+    }
+    PyErr_Format(PyExc_AttributeError, "'%.100s' object has no attribute '%.200s'", tp->tp_name, PyString_AsString(encoded_name));
+    Py_DECREF(encoded_name);
+  } else {
+    res = f(descr, obj, value);
+  }
+  
+  done:
+  Py_DECREF(name);
+  return res;
+}
+#endif
+
 
 #ifdef __cplusplus
-#if 0
-{ /* cc-mode */
-#endif
 }
 #endif
 
@@ -2727,36 +2943,46 @@ SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int argnum, int flags)
 #define SWIGTYPE_p_CPLXMLNode swig_types[2]
 #define SWIGTYPE_p_GByte swig_types[3]
 #define SWIGTYPE_p_GDALAsyncReaderShadow swig_types[4]
-#define SWIGTYPE_p_GDALColorEntry swig_types[5]
-#define SWIGTYPE_p_GDALColorTableShadow swig_types[6]
-#define SWIGTYPE_p_GDALDatasetShadow swig_types[7]
-#define SWIGTYPE_p_GDALDriverShadow swig_types[8]
-#define SWIGTYPE_p_GDALMajorObjectShadow swig_types[9]
-#define SWIGTYPE_p_GDALProgressFunc swig_types[10]
-#define SWIGTYPE_p_GDALRasterAttributeTableShadow swig_types[11]
-#define SWIGTYPE_p_GDALRasterBandShadow swig_types[12]
-#define SWIGTYPE_p_GDALTransformerInfoShadow swig_types[13]
-#define SWIGTYPE_p_GDAL_GCP swig_types[14]
-#define SWIGTYPE_p_GIntBig swig_types[15]
-#define SWIGTYPE_p_GUIntBig swig_types[16]
-#define SWIGTYPE_p_OGRGeometryShadow swig_types[17]
-#define SWIGTYPE_p_OGRLayerShadow swig_types[18]
-#define SWIGTYPE_p_OGRStyleTableShadow swig_types[19]
-#define SWIGTYPE_p_OSRSpatialReferenceShadow swig_types[20]
-#define SWIGTYPE_p_StatBuf swig_types[21]
-#define SWIGTYPE_p_char swig_types[22]
-#define SWIGTYPE_p_double swig_types[23]
-#define SWIGTYPE_p_f_double_p_q_const__char_p_void__int swig_types[24]
-#define SWIGTYPE_p_int swig_types[25]
-#define SWIGTYPE_p_p_GDALRasterBandShadow swig_types[26]
-#define SWIGTYPE_p_p_GDAL_GCP swig_types[27]
-#define SWIGTYPE_p_p_GUIntBig swig_types[28]
-#define SWIGTYPE_p_p_char swig_types[29]
-#define SWIGTYPE_p_p_void swig_types[30]
-#define SWIGTYPE_p_size_t swig_types[31]
-#define SWIGTYPE_p_void swig_types[32]
-static swig_type_info *swig_types[34];
-static swig_module_info swig_module = {swig_types, 33, 0, 0, 0, 0};
+#define SWIGTYPE_p_GDALBuildVRTOptions swig_types[5]
+#define SWIGTYPE_p_GDALColorEntry swig_types[6]
+#define SWIGTYPE_p_GDALColorTableShadow swig_types[7]
+#define SWIGTYPE_p_GDALDEMProcessingOptions swig_types[8]
+#define SWIGTYPE_p_GDALDatasetShadow swig_types[9]
+#define SWIGTYPE_p_GDALDriverShadow swig_types[10]
+#define SWIGTYPE_p_GDALGridOptions swig_types[11]
+#define SWIGTYPE_p_GDALInfoOptions swig_types[12]
+#define SWIGTYPE_p_GDALMajorObjectShadow swig_types[13]
+#define SWIGTYPE_p_GDALNearblackOptions swig_types[14]
+#define SWIGTYPE_p_GDALProgressFunc swig_types[15]
+#define SWIGTYPE_p_GDALRasterAttributeTableShadow swig_types[16]
+#define SWIGTYPE_p_GDALRasterBandShadow swig_types[17]
+#define SWIGTYPE_p_GDALRasterizeOptions swig_types[18]
+#define SWIGTYPE_p_GDALTransformerInfoShadow swig_types[19]
+#define SWIGTYPE_p_GDALTranslateOptions swig_types[20]
+#define SWIGTYPE_p_GDALVectorTranslateOptions swig_types[21]
+#define SWIGTYPE_p_GDALWarpAppOptions swig_types[22]
+#define SWIGTYPE_p_GDAL_GCP swig_types[23]
+#define SWIGTYPE_p_GIntBig swig_types[24]
+#define SWIGTYPE_p_GUIntBig swig_types[25]
+#define SWIGTYPE_p_OGRGeometryShadow swig_types[26]
+#define SWIGTYPE_p_OGRLayerShadow swig_types[27]
+#define SWIGTYPE_p_OGRStyleTableShadow swig_types[28]
+#define SWIGTYPE_p_OSRSpatialReferenceShadow swig_types[29]
+#define SWIGTYPE_p_StatBuf swig_types[30]
+#define SWIGTYPE_p_char swig_types[31]
+#define SWIGTYPE_p_double swig_types[32]
+#define SWIGTYPE_p_f_double_p_q_const__char_p_void__int swig_types[33]
+#define SWIGTYPE_p_int swig_types[34]
+#define SWIGTYPE_p_p_GDALDatasetShadow swig_types[35]
+#define SWIGTYPE_p_p_GDALRasterBandShadow swig_types[36]
+#define SWIGTYPE_p_p_GDAL_GCP swig_types[37]
+#define SWIGTYPE_p_p_GUIntBig swig_types[38]
+#define SWIGTYPE_p_p_char swig_types[39]
+#define SWIGTYPE_p_p_void swig_types[40]
+#define SWIGTYPE_p_size_t swig_types[41]
+#define SWIGTYPE_p_void swig_types[42]
+static swig_type_info *swig_types[44];
+static swig_module_info swig_module = {swig_types, 43, 0, 0, 0, 0};
 #define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)
 #define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)
 
@@ -2780,7 +3006,7 @@ static swig_module_info swig_module = {swig_types, 33, 0, 0, 0, 0};
 #endif
 #define SWIG_name    "_gdal"
 
-#define SWIGVERSION 0x010340 
+#define SWIGVERSION 0x020012 
 #define SWIG_VERSION SWIGVERSION
 
 
@@ -2860,6 +3086,7 @@ using namespace std;
 #include "cpl_string.h"
 #include "cpl_multiproc.h"
 #include "cpl_http.h"
+#include "cpl_vsi_error.h"
 
 #include "gdal.h"
 #include "gdal_priv.h"
@@ -2876,7 +3103,7 @@ typedef void GDALTransformerInfoShadow;
 typedef void GDALAsyncReaderShadow;
 
 
-#ifdef DEBUG 
+#ifdef DEBUG
 typedef struct OGRSpatialReferenceHS OSRSpatialReferenceShadow;
 typedef struct OGRLayerHS OGRLayerShadow;
 typedef struct OGRGeometryHS OGRGeometryShadow;
@@ -2894,17 +3121,16 @@ typedef int RETURN_NONE;
 typedef int VSI_RETVAL;
 
 
+static int bUseExceptions=0;
+static CPLErrorHandler pfnPreviousHandler = CPLDefaultErrorHandler;
 
-int bUseExceptions=0;
-CPLErrorHandler pfnPreviousHandler = CPLDefaultErrorHandler;
-
-void CPL_STDCALL 
-PythonBindingErrorHandler(CPLErr eclass, int code, const char *msg ) 
+static void CPL_STDCALL
+PythonBindingErrorHandler(CPLErr eclass, int code, const char *msg )
 {
-  /* 
+  /*
   ** Generally we want to suppress error reporting if we have exceptions
-  ** enabled as the error message will be in the exception thrown in 
-  ** Python.  
+  ** enabled as the error message will be in the exception thrown in
+  ** Python.
   */
 
   /* If the error class is CE_Fatal, we want to have a message issued
@@ -2925,20 +3151,26 @@ PythonBindingErrorHandler(CPLErr eclass, int code, const char *msg )
 
 
 
+static
 int GetUseExceptions() {
+  CPLErrorReset();
   return bUseExceptions;
 }
 
+static
 void UseExceptions() {
+  CPLErrorReset();
   if( !bUseExceptions )
   {
     bUseExceptions = 1;
-    pfnPreviousHandler = 
+    pfnPreviousHandler =
         CPLSetErrorHandler( (CPLErrorHandler) PythonBindingErrorHandler );
   }
 }
 
+static
 void DontUseExceptions() {
+  CPLErrorReset();
   if( bUseExceptions )
   {
     bUseExceptions = 0;
@@ -2947,17 +3179,32 @@ void DontUseExceptions() {
 }
 
 
-  #define SWIG_From_long   PyInt_FromLong 
+SWIGINTERNINLINE PyObject*
+  SWIG_From_int  (int value)
+{
+  return PyInt_FromLong((long) value);
+}
+
+
+/* Completely unrelated: just to avoid Coverity warnings */
 
+static int bReturnSame = 1;
 
-SWIGINTERNINLINE PyObject *
-SWIG_From_int  (int value)
-{    
-  return SWIG_From_long  (value);
+void NeverCallMePlease() {
+    bReturnSame = 0;
+}
+
+/* Some SWIG code generates dead code, which Coverity warns about */
+template<class T> static T ReturnSame(T x)
+{
+    if( bReturnSame )
+        return x;
+    return 0;
 }
 
 
 
+
 /* Return a PyObject* from a NULL terminated C String */
 static PyObject* GDALPythonObjectFromCStr(const char *pszStr)
 {
@@ -2978,7 +3225,7 @@ static PyObject* GDALPythonObjectFromCStr(const char *pszStr)
     pszIter ++;
   }
 #if PY_VERSION_HEX >= 0x03000000
-  return PyUnicode_FromString(pszStr); 
+  return PyUnicode_FromString(pszStr);
 #else
   return PyString_FromString(pszStr);
 #endif
@@ -3006,7 +3253,7 @@ static char* GDALPythonObjectToCStr(PyObject* pyObject, int* pbToFree)
       *pbToFree = 1;
       return pszNewStr;
   }
-  else 
+  else
   {
 #if PY_VERSION_HEX >= 0x03000000
       return PyBytes_AsString(pyObject);
@@ -3026,15 +3273,21 @@ static void GDALPythonFreeCStr(void* ptr, int bToFree)
 
 int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
 {
-    GIntBig buf_size = nMembSize * nMembCount;
+    GUIntBig buf_size = (GUIntBig)nMembSize * nMembCount;
+    if( nMembSize < 0 || nMembCount < 0 || buf_size > 0xFFFFFFFFU )
+   {
+        CPLError(CE_Failure, CPLE_AppDefined, "Too big request");
+        *buf = NULL;
+        return 0;
+    }
 
     if (buf_size == 0)
     {
         *buf = NULL;
         return 0;
     }
-#if PY_VERSION_HEX >= 0x03000000 
-    *buf = (void *)PyBytes_FromStringAndSize( NULL, buf_size ); 
+#if PY_VERSION_HEX >= 0x03000000
+    *buf = (void *)PyBytes_FromStringAndSize( NULL, buf_size );
     if (*buf == NULL)
     {
         *buf = Py_None;
@@ -3043,16 +3296,16 @@ int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
         return 0;
     }
     PyObject* o = (PyObject*) *buf;
-    char *data = PyBytes_AsString(o); 
-    GIntBig nRet = (GIntBig)VSIFReadL( data, nMembSize, nMembCount, fp );
-    if (nRet * nMembSize < buf_size)
+    char *data = PyBytes_AsString(o);
+    size_t nRet = (size_t)VSIFReadL( data, nMembSize, nMembCount, fp );
+    if (nRet * (size_t)nMembSize < buf_size)
     {
         _PyBytes_Resize(&o, nRet * nMembSize);
         *buf = o;
     }
     return nRet;
-#else 
-    *buf = (void *)PyString_FromStringAndSize( NULL, buf_size ); 
+#else
+    *buf = (void *)PyString_FromStringAndSize( NULL, buf_size );
     if (*buf == NULL)
     {
         if( !bUseExceptions ) PyErr_Clear();
@@ -3060,9 +3313,9 @@ int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
         return 0;
     }
     PyObject* o = (PyObject*) *buf;
-    char *data = PyString_AsString(o); 
-    GIntBig nRet = (GIntBig)VSIFReadL( data, nMembSize, nMembCount, fp );
-    if (nRet * nMembSize < buf_size)
+    char *data = PyString_AsString(o);
+    size_t nRet = (size_t)VSIFReadL( data, nMembSize, nMembCount, fp );
+    if (nRet * (size_t)nMembSize < buf_size)
     {
         _PyString_Resize(&o, nRet * nMembSize);
         *buf = o;
@@ -3228,7 +3481,7 @@ typedef struct {
 /*                          PyProgressProxy()                           */
 /************************************************************************/
 
-int CPL_STDCALL
+static int CPL_STDCALL
 PyProgressProxy( double dfComplete, const char *pszMessage, void *pData )
 
 {
@@ -3243,19 +3496,25 @@ PyProgressProxy( double dfComplete, const char *pszMessage, void *pData )
         return TRUE;
 
     psInfo->nLastReported = (int) (100.0 * dfComplete);
-    
+
     if( pszMessage == NULL )
         pszMessage = "";
 
     if( psInfo->psPyCallbackData == NULL )
         psArgs = Py_BuildValue("(dsO)", dfComplete, pszMessage, Py_None );
     else
-        psArgs = Py_BuildValue("(dsO)", dfComplete, pszMessage, 
+        psArgs = Py_BuildValue("(dsO)", dfComplete, pszMessage,
 	                       psInfo->psPyCallbackData );
 
     psResult = PyEval_CallObject( psInfo->psPyCallback, psArgs);
     Py_XDECREF(psArgs);
 
+    if( PyErr_Occurred() != NULL )
+    {
+        PyErr_Clear();
+        return FALSE;
+    }
+
     if( psResult == NULL )
     {
         return TRUE;
@@ -3263,19 +3522,20 @@ PyProgressProxy( double dfComplete, const char *pszMessage, void *pData )
 
     if( psResult == Py_None )
     {
-	Py_XDECREF(Py_None);
         return TRUE;
     }
 
     if( !PyArg_Parse( psResult, "i", &bContinue ) )
     {
-        PyErr_SetString(PyExc_ValueError, "bad progress return value");
+        PyErr_Clear();
+        CPLError(CE_Failure, CPLE_AppDefined, "bad progress return value");
+        Py_XDECREF(psResult);
 	return FALSE;
     }
 
     Py_XDECREF(psResult);
 
-    return bContinue;    
+    return bContinue;
 }
 
 
@@ -3434,7 +3694,7 @@ void CPL_STDCALL PyCPLErrorHandler(CPLErr eErrClass, int err_no, const char* psz
 
 retStringAndCPLFree* EscapeString(int len, char *bin_string , int scheme=CPLES_SQL) {
     return CPLEscapeString(bin_string, len, scheme);
-} 
+}
 
 
 SWIGINTERNINLINE PyObject *
@@ -3444,7 +3704,7 @@ SWIG_FromCharPtrAndSize(const char* carray, size_t size)
     if (size > INT_MAX) {
       swig_type_info* pchar_descriptor = SWIG_pchar_descriptor();
       return pchar_descriptor ? 
-	SWIG_NewPointerObj(const_cast< char * >(carray), pchar_descriptor, 0) : SWIG_Py_Void();
+	SWIG_InternalNewPointerObj(const_cast< char * >(carray), pchar_descriptor, 0) : SWIG_Py_Void();
     } else {
 #if PY_VERSION_HEX >= 0x03000000
       return PyUnicode_FromStringAndSize(carray, static_cast< int >(size));
@@ -3465,6 +3725,12 @@ SWIG_FromCharPtr(const char *cptr)
 }
 
 
+char **wrapper_VSIReadDirEx( const char * utf8_path, int nMaxFiles = 0 )
+{
+    return VSIReadDirEx(utf8_path, nMaxFiles);
+}
+
+
 const char *wrapper_CPLGetConfigOption( const char * pszKey, const char * pszDefault = NULL )
 {
     return CPLGetConfigOption( pszKey, pszDefault );
@@ -3530,14 +3796,22 @@ VSILFILE   *wrapper_VSIFOpenL( const char *utf8_path, const char *pszMode )
 }
 
 
-int wrapper_VSIFWriteL( int nLen, char *pBuf, int size, int memb, VSILFILE * f)
+VSILFILE   *wrapper_VSIFOpenExL( const char *utf8_path, const char *pszMode, int bSetError )
+{
+    if (!pszMode) /* would lead to segfault */
+        pszMode = "r";
+    return VSIFOpenExL( utf8_path, pszMode, bSetError );
+}
+
+
+int wrapper_VSIFWriteL( int nLen, char *pBuf, int size, int memb, VSILFILE* fp)
 {
     if (nLen < size * memb)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Inconsistent buffer size with 'size' and 'memb' values");
         return 0;
     }
-    return VSIFWriteL(pBuf, size, memb, f);
+    return VSIFWriteL(pBuf, size, memb, fp);
 }
 
 SWIGINTERN char const *GDALMajorObjectShadow_GetDescription(GDALMajorObjectShadow *self){
@@ -3572,23 +3846,23 @@ SWIGINTERN CPLErr GDALMajorObjectShadow_SetMetadataItem(GDALMajorObjectShadow *s
   }
 SWIGINTERN GDALDatasetShadow *GDALDriverShadow_Create(GDALDriverShadow *self,char const *utf8_path,int xsize,int ysize,int bands=1,GDALDataType eType=GDT_Byte,char **options=0){
 
-    GDALDatasetShadow* ds = (GDALDatasetShadow*) GDALCreate(    self, 
-                                                                utf8_path, 
-                                                                xsize, 
-                                                                ysize, 
-                                                                bands, 
-                                                                eType, 
+    GDALDatasetShadow* ds = (GDALDatasetShadow*) GDALCreate(    self,
+                                                                utf8_path,
+                                                                xsize,
+                                                                ysize,
+                                                                bands,
+                                                                eType,
                                                                 options );
     return ds;
   }
 SWIGINTERN GDALDatasetShadow *GDALDriverShadow_CreateCopy(GDALDriverShadow *self,char const *utf8_path,GDALDatasetShadow *src,int strict=1,char **options=0,GDALProgressFunc callback=NULL,void *callback_data=NULL){
 
-    GDALDatasetShadow *ds = (GDALDatasetShadow*) GDALCreateCopy(    self, 
-                                                                    utf8_path, 
-                                                                    src, 
-                                                                    strict, 
-                                                                    options, 
-                                                                    callback, 
+    GDALDatasetShadow *ds = (GDALDatasetShadow*) GDALCreateCopy(    self,
+                                                                    utf8_path,
+                                                                    src,
+                                                                    strict,
+                                                                    options,
+                                                                    callback,
                                                                     callback_data );
     return ds;
   }
@@ -3635,6 +3909,9 @@ SWIG_AsVal_short (PyObject * obj, short *val)
 }
 
 
+  #define SWIG_From_long   PyLong_FromLong 
+
+
 SWIGINTERNINLINE PyObject *
 SWIG_From_short  (short value)
 {    
@@ -3699,7 +3976,7 @@ const char * GDAL_GCP_Info_get( GDAL_GCP *gcp ) {
   return gcp->pszInfo;
 }
 void GDAL_GCP_Info_set( GDAL_GCP *gcp, const char * pszInfo ) {
-  if ( gcp->pszInfo ) 
+  if ( gcp->pszInfo )
     CPLFree( gcp->pszInfo );
   gcp->pszInfo = CPLStrdup(pszInfo);
 }
@@ -3707,7 +3984,7 @@ const char * GDAL_GCP_Id_get( GDAL_GCP *gcp ) {
   return gcp->pszId;
 }
 void GDAL_GCP_Id_set( GDAL_GCP *gcp, const char * pszId ) {
-  if ( gcp->pszId ) 
+  if ( gcp->pszId )
     CPLFree( gcp->pszId );
   gcp->pszId = CPLStrdup(pszId);
 }
@@ -3762,6 +4039,7 @@ SWIGINTERN void CPLVirtualMemShadow_GetAddr(CPLVirtualMemShadow *self,void **ppt
 SWIGINTERN int
 SWIG_AsVal_unsigned_SS_long (PyObject *obj, unsigned long *val) 
 {
+#if PY_VERSION_HEX < 0x03000000
   if (PyInt_Check(obj)) {
     long v = PyInt_AsLong(obj);
     if (v >= 0) {
@@ -3770,13 +4048,27 @@ SWIG_AsVal_unsigned_SS_long (PyObject *obj, unsigned long *val)
     } else {
       return SWIG_OverflowError;
     }
-  } else if (PyLong_Check(obj)) {
+  } else
+#endif
+  if (PyLong_Check(obj)) {
     unsigned long v = PyLong_AsUnsignedLong(obj);
     if (!PyErr_Occurred()) {
       if (val) *val = v;
       return SWIG_OK;
     } else {
       PyErr_Clear();
+#if PY_VERSION_HEX >= 0x03000000
+      {
+        long v = PyLong_AsLong(obj);
+        if (!PyErr_Occurred()) {
+          if (v < 0) {
+            return SWIG_OverflowError;
+          }
+        } else {
+          PyErr_Clear();
+        }
+      }
+#endif
     }
   }
 #ifdef SWIG_PYTHON_CAST_MODE
@@ -3819,19 +4111,13 @@ SWIGINTERN void CPLVirtualMemShadow_Pin(CPLVirtualMemShadow *self,size_t start_o
         CPLVirtualMemPin(self->vmem, start_addr, nsize, bWriteOp);
     }
 
-/* Returned size is in bytes or 0 if an error occured */
+/* Returned size is in bytes or 0 if an error occurred. */
 static
 GIntBig ComputeDatasetRasterIOSize (int buf_xsize, int buf_ysize, int nPixelSize,
                                 int nBands, int* bandMap, int nBandMapArrayLength,
                                 GIntBig nPixelSpace, GIntBig nLineSpace, GIntBig nBandSpace,
                                 int bSpacingShouldBeMultipleOfPixelSize )
 {
-#if SIZEOF_VOIDP == 8
-    const GIntBig MAX_INT = (((GIntBig)0x7fffffff) << 32) | 0xffffffff;
-#else
-    const GIntBig MAX_INT = 0x7fffffff;
-#endif
-
     if (buf_xsize <= 0 || buf_ysize <= 0)
     {
         CPLError(CE_Failure, CPLE_IllegalArg, "Illegal values for buffer size");
@@ -3885,11 +4171,13 @@ GIntBig ComputeDatasetRasterIOSize (int buf_xsize, int buf_ysize, int nPixelSize
     }
 
     GIntBig nRet = (GIntBig)(buf_ysize - 1) * nLineSpace + (GIntBig)(buf_xsize - 1) * nPixelSpace + (GIntBig)(nBands - 1) * nBandSpace + nPixelSize;
-    if (nRet > MAX_INT)
+#if SIZEOF_VOIDP == 4
+    if (nRet > INT_MAX)
     {
         CPLError(CE_Failure, CPLE_IllegalArg, "Integer overflow");
         return 0;
     }
+#endif
 
     return nRet;
 }
@@ -4040,13 +4328,13 @@ SWIGINTERN CPLErr GDALDatasetShadow_SetGeoTransform(GDALDatasetShadow *self,doub
   }
 SWIGINTERN int GDALDatasetShadow_BuildOverviews(GDALDatasetShadow *self,char const *resampling="NEAREST",int overviewlist=0,int *pOverviews=0,GDALProgressFunc callback=NULL,void *callback_data=NULL){
 
-    return GDALBuildOverviews(  self, 
-                                resampling ? resampling : "NEAREST", 
-                                overviewlist, 
-                                pOverviews, 
-                                0, 
-                                0, 
-                                callback, 
+    return GDALBuildOverviews(  self,
+                                resampling ? resampling : "NEAREST",
+                                overviewlist,
+                                pOverviews,
+                                0,
+                                0,
+                                callback,
                                 callback_data);
   }
 SWIGINTERN int GDALDatasetShadow_GetGCPCount(GDALDatasetShadow *self){
@@ -4074,7 +4362,7 @@ SWIGINTERN CPLErr GDALDatasetShadow_CreateMaskBand(GDALDatasetShadow *self,int n
 SWIGINTERN char **GDALDatasetShadow_GetFileList(GDALDatasetShadow *self){
     return GDALGetFileList( self );
   }
-SWIGINTERN CPLErr GDALDatasetShadow_WriteRaster(GDALDatasetShadow *self,int xoff,int yoff,int xsize,int ysize,GIntBig buf_len,char *buf_string,int *buf_xsize=0,int *buf_ysize=0,GDALDataType *buf_type=0,int band_list=0,int *pband_list=0,int *buf_pixel_space=0,int *buf_line_space=0,int *buf_band_space=0){
+SWIGINTERN CPLErr GDALDatasetShadow_WriteRaster(GDALDatasetShadow *self,int xoff,int yoff,int xsize,int ysize,GIntBig buf_len,char *buf_string,int *buf_xsize=0,int *buf_ysize=0,GDALDataType *buf_type=0,int band_list=0,int *pband_list=0,GIntBig *buf_pixel_space=0,GIntBig *buf_line_space=0,GIntBig *buf_band_space=0){
     CPLErr eErr;
     int nxsize = (buf_xsize==0) ? xsize : *buf_xsize;
     int nysize = (buf_ysize==0) ? ysize : *buf_ysize;
@@ -4088,9 +4376,9 @@ SWIGINTERN CPLErr GDALDatasetShadow_WriteRaster(GDALDatasetShadow *self,int xoff
       ntype = GDALGetRasterDataType( GDALGetRasterBand( self, lastband ) );
     }
 
-    int pixel_space = (buf_pixel_space == 0) ? 0 : *buf_pixel_space;
-    int line_space = (buf_line_space == 0) ? 0 : *buf_line_space;
-    int band_space = (buf_band_space == 0) ? 0 : *buf_band_space;
+    GIntBig pixel_space = (buf_pixel_space == 0) ? 0 : *buf_pixel_space;
+    GIntBig line_space = (buf_line_space == 0) ? 0 : *buf_line_space;
+    GIntBig band_space = (buf_band_space == 0) ? 0 : *buf_band_space;
 
     GIntBig min_buffer_size =
       ComputeDatasetRasterIOSize (nxsize, nysize, GDALGetDataTypeSize( ntype ) / 8,
@@ -4105,9 +4393,11 @@ SWIGINTERN CPLErr GDALDatasetShadow_WriteRaster(GDALDatasetShadow *self,int xoff
         return CE_Failure;
     }
 
-    eErr = GDALDatasetRasterIO( self, GF_Write, xoff, yoff, xsize, ysize,
-                                (void*) buf_string, nxsize, nysize, ntype,
-                                band_list, pband_list, pixel_space, line_space, band_space );
+    GDALRasterIOExtraArg* psExtraArg = NULL;
+
+    eErr = GDALDatasetRasterIOEx( self, GF_Write, xoff, yoff, xsize, ysize,
+                                  (void*) buf_string, nxsize, nysize, ntype,
+                                  band_list, pband_list, pixel_space, line_space, band_space, psExtraArg );
 
     return eErr;
   }
@@ -4121,23 +4411,30 @@ SWIGINTERN GDALAsyncReaderShadow *GDALDatasetShadow_BeginAsyncReader(GDALDataset
         {
             // round up
             int nLevel = atoi(pszLevel);
-            int nRes = 2 << (nLevel - 1);
-            buf_xsize = ceil(xSize / (1.0 * nRes));
-            buf_ysize = ceil(ySize / (1.0 * nRes));
+            if( nLevel < 0 || nLevel > 30 )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "Invalid LEVEL: %d", nLevel);
+            }
+            else
+            {
+                int nRes = 1 << nLevel;
+                buf_xsize = ceil(xSize / (1.0 * nRes));
+                buf_ysize = ceil(ySize / (1.0 * nRes));
+            }
         }
     }
-    
+
     int nxsize = (buf_xsize == 0) ? xSize : buf_xsize;
     int nysize = (buf_ysize == 0) ? ySize : buf_ysize;
-    
+
     GDALDataType ntype;
     if (bufType != 0) {
         ntype = (GDALDataType) bufType;
-    } 
+    }
     else {
         ntype = GDT_Byte;
     }
-    
+
     int nBCount = (band_list) != 0 ? band_list : GDALGetRasterCount(self);
     int nMinSize = nxsize * nysize * nBCount * (GDALGetDataTypeSize(ntype) / 8);
     if (buf_string == NULL || buf_len < nMinSize)
@@ -4145,14 +4442,14 @@ SWIGINTERN GDALAsyncReaderShadow *GDALDatasetShadow_BeginAsyncReader(GDALDataset
         CPLError(CE_Failure, CPLE_AppDefined, "Buffer is too small");
         return NULL;
     }
-    
+
     bool myBandList = false;
     int* pBandList;
-    
+
     if (band_list != 0){
         myBandList = false;
         pBandList = pband_list;
-    }        
+    }
     else
     {
         myBandList = true;
@@ -4165,6 +4462,11 @@ SWIGINTERN GDALAsyncReaderShadow *GDALDatasetShadow_BeginAsyncReader(GDALDataset
     GDALAsyncReaderH hAsyncReader =
             GDALBeginAsyncReader(self, xOff, yOff, xSize, ySize, (void*) buf_string, nxsize, nysize, ntype, nBCount, pBandList, nPixelSpace, nLineSpace,
     nBandSpace, options);
+
+    if ( myBandList ) {
+       CPLFree( pBandList );
+    }
+
     if (hAsyncReader)
     {
         return (GDALAsyncReader*) CreateAsyncReaderWrapper(hAsyncReader, pyObject);
@@ -4173,10 +4475,6 @@ SWIGINTERN GDALAsyncReaderShadow *GDALDatasetShadow_BeginAsyncReader(GDALDataset
     {
         return NULL;
     }
-    
-    if ( myBandList ) {
-       CPLFree( pBandList );
-    }
 
   }
 SWIGINTERN void GDALDatasetShadow_EndAsyncReader(GDALDatasetShadow *self,GDALAsyncReaderShadow *ario){
@@ -4388,24 +4686,24 @@ SWIGINTERN CPLErr GDALDatasetShadow_ReadRaster1(GDALDatasetShadow *self,int xoff
         return CE_Failure;
     }
 
-#if PY_VERSION_HEX >= 0x03000000 
-    *buf = (void *)PyBytes_FromStringAndSize( NULL, buf_size ); 
+#if PY_VERSION_HEX >= 0x03000000
+    *buf = (void *)PyBytes_FromStringAndSize( NULL, buf_size );
     if (*buf == NULL)
     {
         if( !bUseExceptions ) PyErr_Clear();
         CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate result buffer");
         return CE_Failure;
     }
-    char *data = PyBytes_AsString( (PyObject *)*buf ); 
-#else 
-    *buf = (void *)PyString_FromStringAndSize( NULL, buf_size ); 
+    char *data = PyBytes_AsString( (PyObject *)*buf );
+#else
+    *buf = (void *)PyString_FromStringAndSize( NULL, buf_size );
     if (*buf == NULL)
     {
         if( !bUseExceptions ) PyErr_Clear();
         CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate result buffer");
         return CE_Failure;
     }
-    char *data = PyString_AsString( (PyObject *)*buf ); 
+    char *data = PyString_AsString( (PyObject *)*buf );
 #endif
 
     /* Should we clear the buffer in case there are hole in it ? */
@@ -4450,18 +4748,12 @@ int GDALDatasetShadow_RasterCount_get( GDALDatasetShadow *h ) {
 }
 
 
-/* Returned size is in bytes or 0 if an error occured */
+/* Returned size is in bytes or 0 if an error occurred. */
 static
 GIntBig ComputeBandRasterIOSize (int buf_xsize, int buf_ysize, int nPixelSize,
                                  GIntBig nPixelSpace, GIntBig nLineSpace,
                                  int bSpacingShouldBeMultipleOfPixelSize )
 {
-#if SIZEOF_VOIDP == 8
-    const GIntBig MAX_INT = (((GIntBig)0x7fffffff) << 32) | 0xffffffff;
-#else
-    const GIntBig MAX_INT = 0x7fffffff;
-#endif
-
     if (buf_xsize <= 0 || buf_ysize <= 0)
     {
         CPLError(CE_Failure, CPLE_IllegalArg, "Illegal values for buffer size");
@@ -4499,11 +4791,13 @@ GIntBig ComputeBandRasterIOSize (int buf_xsize, int buf_ysize, int nPixelSize,
     }
 
     GIntBig nRet = (GIntBig)(buf_ysize - 1) * nLineSpace + (GIntBig)(buf_xsize - 1) * nPixelSpace + nPixelSize;
-    if (nRet > MAX_INT)
+#if SIZEOF_VOIDP == 4
+    if (nRet > INT_MAX)
     {
         CPLError(CE_Failure, CPLE_IllegalArg, "Integer overflow");
         return 0;
     }
+#endif
 
     return nRet;
 }
@@ -4515,20 +4809,21 @@ CPLErr WriteRaster_internal( GDALRasterBandShadow *obj,
                              int buf_xsize, int buf_ysize,
                              GDALDataType buf_type,
                              GIntBig buf_size, char *buffer,
-                             int pixel_space, int line_space)
+                             GIntBig pixel_space, GIntBig line_space,
+                             GDALRasterIOExtraArg* psExtraArg )
 {
     GIntBig min_buffer_size = ComputeBandRasterIOSize (buf_xsize, buf_ysize, GDALGetDataTypeSize( buf_type ) / 8,
                                                    pixel_space, line_space, FALSE );
     if ( min_buffer_size == 0 )
       return CE_Failure;
-      
+
     if ( buf_size < min_buffer_size ) {
       CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
       return CE_Failure;
     }
 
-    return GDALRasterIO( obj, GF_Write, xoff, yoff, xsize, ysize, 
-		        (void *) buffer, buf_xsize, buf_ysize, buf_type, pixel_space, line_space );
+    return GDALRasterIOEx( obj, GF_Write, xoff, yoff, xsize, ysize,
+                           (void *) buffer, buf_xsize, buf_ysize, buf_type, pixel_space, line_space, psExtraArg );
 }
 
 SWIGINTERN GDALDatasetShadow *GDALRasterBandShadow_GetDataset(GDALRasterBandShadow *self){
@@ -4558,6 +4853,9 @@ SWIGINTERN void GDALRasterBandShadow_GetNoDataValue(GDALRasterBandShadow *self,d
 SWIGINTERN CPLErr GDALRasterBandShadow_SetNoDataValue(GDALRasterBandShadow *self,double d){
     return GDALSetRasterNoDataValue( self, d );
   }
+SWIGINTERN CPLErr GDALRasterBandShadow_DeleteNoDataValue(GDALRasterBandShadow *self){
+    return GDALDeleteRasterNoDataValue( self );
+  }
 SWIGINTERN char const *GDALRasterBandShadow_GetUnitType(GDALRasterBandShadow *self){
       return GDALGetRasterUnitType( self );
   }
@@ -4593,7 +4891,7 @@ SWIGINTERN CPLErr GDALRasterBandShadow_GetStatistics(GDALRasterBandShadow *self,
     if (max) *max = 0;
     if (mean) *mean = 0;
     if (stddev) *stddev = -1; /* This is the only way to recognize from Python if GetRasterStatistics() has updated the values */
-    return GDALGetRasterStatistics( self, approx_ok, force, 
+    return GDALGetRasterStatistics( self, approx_ok, force,
 				    min, max, mean, stddev );
   }
 
@@ -4628,21 +4926,22 @@ SWIGINTERN void GDALRasterBandShadow_ComputeRasterMinMax(GDALRasterBandShadow *s
     GDALComputeRasterMinMax( self, approx_ok, argout );
   }
 SWIGINTERN void GDALRasterBandShadow_ComputeBandStats(GDALRasterBandShadow *self,double argout[2],int samplestep=1){
-    GDALComputeBandStats( self, samplestep, argout+0, argout+1, 
+    GDALComputeBandStats( self, samplestep, argout+0, argout+1,
                           NULL, NULL );
   }
 SWIGINTERN CPLErr GDALRasterBandShadow_Fill(GDALRasterBandShadow *self,double real_fill,double imag_fill=0.0){
     return GDALFillRaster( self, real_fill, imag_fill );
   }
-SWIGINTERN CPLErr GDALRasterBandShadow_WriteRaster(GDALRasterBandShadow *self,int xoff,int yoff,int xsize,int ysize,GIntBig buf_len,char *buf_string,int *buf_xsize=0,int *buf_ysize=0,int *buf_type=0,int *buf_pixel_space=0,int *buf_line_space=0){
+SWIGINTERN CPLErr GDALRasterBandShadow_WriteRaster(GDALRasterBandShadow *self,int xoff,int yoff,int xsize,int ysize,GIntBig buf_len,char *buf_string,int *buf_xsize=0,int *buf_ysize=0,int *buf_type=0,GIntBig *buf_pixel_space=0,GIntBig *buf_line_space=0){
     int nxsize = (buf_xsize==0) ? xsize : *buf_xsize;
     int nysize = (buf_ysize==0) ? ysize : *buf_ysize;
     GDALDataType ntype  = (buf_type==0) ? GDALGetRasterDataType(self)
                                         : (GDALDataType)*buf_type;
-    int pixel_space = (buf_pixel_space == 0) ? 0 : *buf_pixel_space;
-    int line_space = (buf_line_space == 0) ? 0 : *buf_line_space;
+    GIntBig pixel_space = (buf_pixel_space == 0) ? 0 : *buf_pixel_space;
+    GIntBig line_space = (buf_line_space == 0) ? 0 : *buf_line_space;
+    GDALRasterIOExtraArg* psExtraArg = NULL;
     return WriteRaster_internal( self, xoff, yoff, xsize, ysize,
-                                 nxsize, nysize, ntype, buf_len, buf_string, pixel_space, line_space );
+                                 nxsize, nysize, ntype, buf_len, buf_string, pixel_space, line_space, psExtraArg );
   }
 SWIGINTERN void GDALRasterBandShadow_FlushCache(GDALRasterBandShadow *self){
     GDALFlushRasterCache( self );
@@ -4659,7 +4958,7 @@ SWIGINTERN int GDALRasterBandShadow_SetRasterColorTable(GDALRasterBandShadow *se
 SWIGINTERN int GDALRasterBandShadow_SetColorTable(GDALRasterBandShadow *self,GDALColorTableShadow *arg){
     return GDALSetRasterColorTable( self, arg );
   }
-SWIGINTERN GDALRasterAttributeTableShadow *GDALRasterBandShadow_GetDefaultRAT(GDALRasterBandShadow *self){ 
+SWIGINTERN GDALRasterAttributeTableShadow *GDALRasterBandShadow_GetDefaultRAT(GDALRasterBandShadow *self){
       return (GDALRasterAttributeTableShadow*) GDALGetDefaultRAT(self);
   }
 SWIGINTERN int GDALRasterBandShadow_SetDefaultRAT(GDALRasterBandShadow *self,GDALRasterAttributeTableShadow *table){
@@ -4675,7 +4974,7 @@ SWIGINTERN CPLErr GDALRasterBandShadow_CreateMaskBand(GDALRasterBandShadow *self
       return GDALCreateMaskBand( self, nFlags );
   }
 SWIGINTERN CPLErr GDALRasterBandShadow_GetHistogram(GDALRasterBandShadow *self,double min=-0.5,double max=255.5,int buckets=256,GUIntBig *panHistogram=NULL,int include_out_of_range=0,int approx_ok=1,GDALProgressFunc callback=NULL,void *callback_data=NULL){
-    CPLErrorReset(); 
+    CPLErrorReset();
     CPLErr err = GDALGetRasterHistogramEx( self, min, max, buckets, panHistogram,
                                          include_out_of_range, approx_ok,
                                          callback, callback_data );
@@ -4683,11 +4982,11 @@ SWIGINTERN CPLErr GDALRasterBandShadow_GetHistogram(GDALRasterBandShadow *self,d
   }
 SWIGINTERN CPLErr GDALRasterBandShadow_GetDefaultHistogram(GDALRasterBandShadow *self,double *min_ret=NULL,double *max_ret=NULL,int *buckets_ret=NULL,GUIntBig **ppanHistogram=NULL,int force=1,GDALProgressFunc callback=NULL,void *callback_data=NULL){
     return GDALGetDefaultHistogramEx( self, min_ret, max_ret, buckets_ret,
-                                    ppanHistogram, force, 
+                                    ppanHistogram, force,
                                     callback, callback_data );
 }
 SWIGINTERN CPLErr GDALRasterBandShadow_SetDefaultHistogram(GDALRasterBandShadow *self,double min,double max,int buckets_in,GUIntBig *panHistogram_in){
-    return GDALSetDefaultHistogramEx( self, min, max, 
+    return GDALSetDefaultHistogramEx( self, min, max,
                                     buckets_in, panHistogram_in );
 }
 SWIGINTERN bool GDALRasterBandShadow_HasArbitraryOverviews(GDALRasterBandShadow *self){
@@ -4771,7 +5070,7 @@ SWIGINTERN CPLVirtualMemShadow *GDALRasterBandShadow_GetTiledVirtualMem(GDALRast
         vmemshadow->nBandCount = 1;
         return vmemshadow;
     }
-SWIGINTERN CPLErr GDALRasterBandShadow_ReadRaster1(GDALRasterBandShadow *self,int xoff,int yoff,int xsize,int ysize,void **buf,int *buf_xsize=0,int *buf_ysize=0,int *buf_type=0,GIntBig *buf_pixel_space=0,GIntBig *buf_line_space=0,GDALRIOResampleAlg resample_alg=GRIORA_NearestNeighbour,GDALProgressFunc callback=NULL,void *callback_data=NULL){
+SWIGINTERN CPLErr GDALRasterBandShadow_ReadRaster1(GDALRasterBandShadow *self,double xoff,double yoff,double xsize,double ysize,void **buf,int *buf_xsize=0,int *buf_ysize=0,int *buf_type=0,GIntBig *buf_pixel_space=0,GIntBig *buf_line_space=0,GDALRIOResampleAlg resample_alg=GRIORA_NearestNeighbour,GDALProgressFunc callback=NULL,void *callback_data=NULL){
     int nxsize = (buf_xsize==0) ? xsize : *buf_xsize;
     int nysize = (buf_ysize==0) ? ysize : *buf_ysize;
     GDALDataType ntype  = (buf_type==0) ? GDALGetRasterDataType(self)
@@ -4780,14 +5079,14 @@ SWIGINTERN CPLErr GDALRasterBandShadow_ReadRaster1(GDALRasterBandShadow *self,in
     GIntBig line_space = (buf_line_space == 0) ? 0 : *buf_line_space;
 
     GIntBig buf_size = ComputeBandRasterIOSize( nxsize, nysize, GDALGetDataTypeSize( ntype ) / 8,
-                                            pixel_space, line_space, FALSE ); 
+                                            pixel_space, line_space, FALSE );
     if (buf_size == 0)
     {
         *buf = NULL;
         return CE_Failure;
     }
-#if PY_VERSION_HEX >= 0x03000000 
-    *buf = (void *)PyBytes_FromStringAndSize( NULL, buf_size ); 
+#if PY_VERSION_HEX >= 0x03000000
+    *buf = (void *)PyBytes_FromStringAndSize( NULL, buf_size );
     if (*buf == NULL)
     {
         *buf = Py_None;
@@ -4795,16 +5094,16 @@ SWIGINTERN CPLErr GDALRasterBandShadow_ReadRaster1(GDALRasterBandShadow *self,in
         CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate result buffer");
         return CE_Failure;
     }
-    char *data = PyBytes_AsString( (PyObject *)*buf ); 
-#else 
-    *buf = (void *)PyString_FromStringAndSize( NULL, buf_size ); 
+    char *data = PyBytes_AsString( (PyObject *)*buf );
+#else
+    *buf = (void *)PyString_FromStringAndSize( NULL, buf_size );
     if (*buf == NULL)
     {
         if( !bUseExceptions ) PyErr_Clear();
         CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate result buffer");
         return CE_Failure;
     }
-    char *data = PyString_AsString( (PyObject *)*buf ); 
+    char *data = PyString_AsString( (PyObject *)*buf );
 #endif
 
     /* Should we clear the buffer in case there are hole in it ? */
@@ -4818,10 +5117,23 @@ SWIGINTERN CPLErr GDALRasterBandShadow_ReadRaster1(GDALRasterBandShadow *self,in
     sExtraArg.eResampleAlg = resample_alg;
     sExtraArg.pfnProgress = callback;
     sExtraArg.pProgressData = callback_data;
+    int nXOff = (int)(xoff + 0.5);
+    int nYOff = (int)(yoff + 0.5);
+    int nXSize = (int)(xsize + 0.5);
+    int nYSize = (int)(ysize + 0.5);
+    if( fabs(xoff-nXOff) > 1e-8 || fabs(yoff-nYOff) > 1e-8 ||
+        fabs(xsize-nXSize) > 1e-8 || fabs(ysize-nYSize) > 1e-8 )
+    {
+        sExtraArg.bFloatingPointWindowValidity = TRUE;
+        sExtraArg.dfXOff = xoff;
+        sExtraArg.dfYOff = yoff;
+        sExtraArg.dfXSize = xsize;
+        sExtraArg.dfYSize = ysize;
+    }
 
-    CPLErr eErr = GDALRasterIOEx( self, GF_Read, xoff, yoff, xsize, ysize, 
-                         (void *) data, nxsize, nysize, ntype, 
-                         pixel_space, line_space, &sExtraArg ); 
+    CPLErr eErr = GDALRasterIOEx( self, GF_Read, nXOff, nYOff, nXSize, nYSize,
+                         (void *) data, nxsize, nysize, ntype,
+                         pixel_space, line_space, &sExtraArg );
     if (eErr == CE_Failure)
     {
         Py_DECREF((PyObject*)*buf);
@@ -4836,8 +5148,8 @@ SWIGINTERN CPLErr GDALRasterBandShadow_ReadBlock(GDALRasterBandShadow *self,int
     int nDataTypeSize = (GDALGetDataTypeSize(GDALGetRasterDataType(self)) / 8);
     GIntBig buf_size = (GIntBig)nBlockXSize * nBlockYSize * nDataTypeSize;
 
-#if PY_VERSION_HEX >= 0x03000000 
-    *buf = (void *)PyBytes_FromStringAndSize( NULL, buf_size ); 
+#if PY_VERSION_HEX >= 0x03000000
+    *buf = (void *)PyBytes_FromStringAndSize( NULL, buf_size );
     if (*buf == NULL)
     {
         *buf = Py_None;
@@ -4845,18 +5157,18 @@ SWIGINTERN CPLErr GDALRasterBandShadow_ReadBlock(GDALRasterBandShadow *self,int
         CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate result buffer");
         return CE_Failure;
     }
-    char *data = PyBytes_AsString( (PyObject *)*buf ); 
-#else 
-    *buf = (void *)PyString_FromStringAndSize( NULL, buf_size ); 
+    char *data = PyBytes_AsString( (PyObject *)*buf );
+#else
+    *buf = (void *)PyString_FromStringAndSize( NULL, buf_size );
     if (*buf == NULL)
     {
         if( !bUseExceptions ) PyErr_Clear();
         CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate result buffer");
         return CE_Failure;
     }
-    char *data = PyString_AsString( (PyObject *)*buf ); 
+    char *data = PyString_AsString( (PyObject *)*buf );
 #endif
-    CPLErr eErr = GDALReadBlock( self, xoff, yoff, (void *) data); 
+    CPLErr eErr = GDALReadBlock( self, xoff, yoff, (void *) data);
     if (eErr == CE_Failure)
     {
         Py_DECREF((PyObject*)*buf);
@@ -4903,7 +5215,7 @@ SWIGINTERN void GDALColorTableShadow_CreateColorRamp(GDALColorTableShadow *self,
         GDALCreateColorRamp(self, nStartIndex, startcolor, nEndIndex, endcolor);
     }
 SWIGINTERN GDALRasterAttributeTableShadow *new_GDALRasterAttributeTableShadow(){
-        return (GDALRasterAttributeTableShadow*) 
+        return (GDALRasterAttributeTableShadow*)
 		GDALCreateRasterAttributeTable();
     }
 SWIGINTERN void delete_GDALRasterAttributeTableShadow(GDALRasterAttributeTableShadow *self){
@@ -4912,10 +5224,10 @@ SWIGINTERN void delete_GDALRasterAttributeTableShadow(GDALRasterAttributeTableSh
 SWIGINTERN GDALRasterAttributeTableShadow *GDALRasterAttributeTableShadow_Clone(GDALRasterAttributeTableShadow *self){
         return (GDALRasterAttributeTableShadow*) GDALRATClone(self);
     }
-SWIGINTERN int GDALRasterAttributeTableShadow_GetColumnCount(GDALRasterAttributeTableShadow *self){ 
+SWIGINTERN int GDALRasterAttributeTableShadow_GetColumnCount(GDALRasterAttributeTableShadow *self){
         return GDALRATGetColumnCount( self );
     }
-SWIGINTERN char const *GDALRasterAttributeTableShadow_GetNameOfCol(GDALRasterAttributeTableShadow *self,int iCol){ 
+SWIGINTERN char const *GDALRasterAttributeTableShadow_GetNameOfCol(GDALRasterAttributeTableShadow *self,int iCol){
         return GDALRATGetNameOfCol( self, iCol );
     }
 SWIGINTERN GDALRATFieldUsage GDALRasterAttributeTableShadow_GetUsageOfCol(GDALRasterAttributeTableShadow *self,int iCol){
@@ -4927,25 +5239,25 @@ SWIGINTERN GDALRATFieldType GDALRasterAttributeTableShadow_GetTypeOfCol(GDALRast
 SWIGINTERN int GDALRasterAttributeTableShadow_GetColOfUsage(GDALRasterAttributeTableShadow *self,GDALRATFieldUsage eUsage){
         return GDALRATGetColOfUsage( self, eUsage );
     }
-SWIGINTERN int GDALRasterAttributeTableShadow_GetRowCount(GDALRasterAttributeTableShadow *self){ 
+SWIGINTERN int GDALRasterAttributeTableShadow_GetRowCount(GDALRasterAttributeTableShadow *self){
         return GDALRATGetRowCount( self );
     }
-SWIGINTERN char const *GDALRasterAttributeTableShadow_GetValueAsString(GDALRasterAttributeTableShadow *self,int iRow,int iCol){ 
+SWIGINTERN char const *GDALRasterAttributeTableShadow_GetValueAsString(GDALRasterAttributeTableShadow *self,int iRow,int iCol){
         return GDALRATGetValueAsString( self, iRow, iCol );
     }
-SWIGINTERN int GDALRasterAttributeTableShadow_GetValueAsInt(GDALRasterAttributeTableShadow *self,int iRow,int iCol){ 
+SWIGINTERN int GDALRasterAttributeTableShadow_GetValueAsInt(GDALRasterAttributeTableShadow *self,int iRow,int iCol){
         return GDALRATGetValueAsInt( self, iRow, iCol );
     }
-SWIGINTERN double GDALRasterAttributeTableShadow_GetValueAsDouble(GDALRasterAttributeTableShadow *self,int iRow,int iCol){ 
+SWIGINTERN double GDALRasterAttributeTableShadow_GetValueAsDouble(GDALRasterAttributeTableShadow *self,int iRow,int iCol){
         return GDALRATGetValueAsDouble( self, iRow, iCol );
     }
-SWIGINTERN void GDALRasterAttributeTableShadow_SetValueAsString(GDALRasterAttributeTableShadow *self,int iRow,int iCol,char const *pszValue){ 
+SWIGINTERN void GDALRasterAttributeTableShadow_SetValueAsString(GDALRasterAttributeTableShadow *self,int iRow,int iCol,char const *pszValue){
         GDALRATSetValueAsString( self, iRow, iCol, pszValue );
     }
-SWIGINTERN void GDALRasterAttributeTableShadow_SetValueAsInt(GDALRasterAttributeTableShadow *self,int iRow,int iCol,int nValue){ 
+SWIGINTERN void GDALRasterAttributeTableShadow_SetValueAsInt(GDALRasterAttributeTableShadow *self,int iRow,int iCol,int nValue){
         GDALRATSetValueAsInt( self, iRow, iCol, nValue );
     }
-SWIGINTERN void GDALRasterAttributeTableShadow_SetValueAsDouble(GDALRasterAttributeTableShadow *self,int iRow,int iCol,double dfValue){ 
+SWIGINTERN void GDALRasterAttributeTableShadow_SetValueAsDouble(GDALRasterAttributeTableShadow *self,int iRow,int iCol,double dfValue){
         GDALRATSetValueAsDouble( self, iRow, iCol, dfValue );
     }
 SWIGINTERN void GDALRasterAttributeTableShadow_SetRowCount(GDALRasterAttributeTableShadow *self,int nCount){
@@ -4972,7 +5284,7 @@ SWIGINTERN void GDALRasterAttributeTableShadow_DumpReadable(GDALRasterAttributeT
 
 #include "gdalgrid.h"
 
-#ifdef DEBUG 
+#ifdef DEBUG
 typedef struct OGRLayerHS OGRLayerShadow;
 typedef struct OGRGeometryHS OGRGeometryShadow;
 #else
@@ -4981,7 +5293,8 @@ typedef void OGRGeometryShadow;
 #endif
 
 
-int GDALTermProgress_nocb( double dfProgress, const char * pszMessage=NULL, void *pData=NULL ) {
+static int
+GDALTermProgress_nocb( double dfProgress, const char * pszMessage=NULL, void *pData=NULL ) {
   return GDALTermProgress( dfProgress, pszMessage, pData);
 }
 
@@ -5004,7 +5317,7 @@ int  ComputeMedianCutPCT ( GDALRasterBandShadow *red,
                                           colors,
                                           callback,
                                           callback_data);
-    
+
     return err;
 }
 
@@ -5026,7 +5339,7 @@ int  DitherRGB2PCT ( GDALRasterBandShadow *red,
                                   colors,
                                   callback,
                                   callback_data);
-    
+
     return err;
 }
 
@@ -5039,10 +5352,18 @@ CPLErr  ReprojectImage ( GDALDatasetShadow *src_ds,
                          double WarpMemoryLimit=0.0,
                          double maxerror = 0.0,
 			 GDALProgressFunc callback = NULL,
-                     	 void* callback_data=NULL) {
+                     	 void* callback_data=NULL,
+                         char** options = NULL ) {
 
     CPLErrorReset();
 
+    GDALWarpOptions* psOptions = NULL;
+    if( options != NULL )
+    {
+        psOptions = GDALCreateWarpOptions();
+        psOptions->papszWarpOptions = CSLDuplicate(options);
+    }
+
     CPLErr err = GDALReprojectImage( src_ds,
                                      src_wkt,
                                      dst_ds,
@@ -5052,8 +5373,11 @@ CPLErr  ReprojectImage ( GDALDatasetShadow *src_ds,
                                      maxerror,
                                      callback,
                                      callback_data,
-                                     NULL);
-    
+                                     psOptions);
+
+    if( psOptions != NULL )
+        GDALDestroyWarpOptions(psOptions);
+
     return err;
 }
 
@@ -5075,8 +5399,8 @@ int  RasterizeLayer( GDALDatasetShadow *dataset,
                  int bands, int *band_list,
                  OGRLayerShadow *layer,
                  void *pfnTransformer = NULL,
-                 void *pTransformArg = NULL, 
-		 int burn_values = 0, double *burn_values_list = NULL, 
+                 void *pTransformArg = NULL,
+		 int burn_values = 0, double *burn_values_list = NULL,
                  char **options = NULL,
                  GDALProgressFunc callback=NULL,
                  void* callback_data=NULL) {
@@ -5093,16 +5417,16 @@ int  RasterizeLayer( GDALDatasetShadow *dataset,
     }
     else if( burn_values != bands )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Did not get the expected number of burn values in RasterizeLayer()" );
         return CE_Failure;
     }
 
     eErr = GDALRasterizeLayers( dataset, bands, band_list,
-                                1, &layer, 
-                                (GDALTransformerFunc) pfnTransformer, 
+                                1, &layer,
+                                (GDALTransformerFunc) pfnTransformer,
                                 pTransformArg,
-                                burn_values_list, options, 
+                                burn_values_list, options,
                                 callback, callback_data );
 
     if( burn_values == 0 )
@@ -5114,7 +5438,7 @@ int  RasterizeLayer( GDALDatasetShadow *dataset,
 
 int  Polygonize( GDALRasterBandShadow *srcBand,
      		 GDALRasterBandShadow *maskBand,
-  	         OGRLayerShadow *outLayer, 
+  	         OGRLayerShadow *outLayer,
                  int iPixValField,
                  char **options = NULL,
                  GDALProgressFunc callback=NULL,
@@ -5127,6 +5451,21 @@ int  Polygonize( GDALRasterBandShadow *srcBand,
 }
 
 
+int  FPolygonize( GDALRasterBandShadow *srcBand,
+                 GDALRasterBandShadow *maskBand,
+                 OGRLayerShadow *outLayer,
+                 int iPixValField,
+                 char **options = NULL,
+                 GDALProgressFunc callback=NULL,
+                 void* callback_data=NULL) {
+
+    CPLErrorReset();
+
+    return GDALFPolygonize( srcBand, maskBand, outLayer, iPixValField,
+                           options, callback, callback_data );
+}
+
+
 int  FillNodata( GDALRasterBandShadow *targetBand,
      		 GDALRasterBandShadow *maskBand,
                  double maxSearchDist,
@@ -5137,8 +5476,8 @@ int  FillNodata( GDALRasterBandShadow *targetBand,
 
     CPLErrorReset();
 
-    return GDALFillNodata( targetBand, maskBand, maxSearchDist, 
-    	   		   0, smoothingIterations, options, 
+    return GDALFillNodata( targetBand, maskBand, maxSearchDist,
+    	   		   0, smoothingIterations, options,
 			   callback, callback_data );
 }
 
@@ -5153,7 +5492,7 @@ int  SieveFilter( GDALRasterBandShadow *srcBand,
 
     CPLErrorReset();
 
-    return GDALSieveFilter( srcBand, maskBand, dstBand, 
+    return GDALSieveFilter( srcBand, maskBand, dstBand,
                             threshold, connectedness,
                             options, callback, callback_data );
 }
@@ -5193,7 +5532,7 @@ int ContourGenerate( GDALRasterBandShadow *srcBand,
                      double *fixedLevels,
                      int useNoData,
                      double noDataValue,
-                     OGRLayerShadow* dstLayer, 
+                     OGRLayerShadow* dstLayer,
                      int idField,
                      int elevField,
                      GDALProgressFunc callback = NULL,
@@ -5234,12 +5573,24 @@ GDALDatasetShadow *AutoCreateWarpedVRT( GDALDatasetShadow *src_ds,
     /*throw CPLGetLastErrorMsg(); causes a SWIG_exception later*/
   }
   return ds;
-  
+
+}
+
+
+GDALDatasetShadow*  CreatePansharpenedVRT( const char* pszXML,
+                            GDALRasterBandShadow* panchroBand,
+                            int nInputSpectralBands,
+                            GDALRasterBandShadow** ahInputSpectralBands )
+{
+    CPLErrorReset();
+
+    return (GDALDatasetShadow*)GDALCreatePansharpenedVRT( pszXML, panchroBand,
+                                      nInputSpectralBands, ahInputSpectralBands );
 }
 
 SWIGINTERN GDALTransformerInfoShadow *new_GDALTransformerInfoShadow(GDALDatasetShadow *src,GDALDatasetShadow *dst,char **options){
-    GDALTransformerInfoShadow *obj = (GDALTransformerInfoShadow*) 
-       GDALCreateGenImgProjTransformer2( (GDALDatasetH)src, (GDALDatasetH)dst, 
+    GDALTransformerInfoShadow *obj = (GDALTransformerInfoShadow*)
+       GDALCreateGenImgProjTransformer2( (GDALDatasetH)src, (GDALDatasetH)dst,
                                          options );
     return obj;
   }
@@ -5249,20 +5600,20 @@ SWIGINTERN void delete_GDALTransformerInfoShadow(GDALTransformerInfoShadow *self
 SWIGINTERN int GDALTransformerInfoShadow_TransformPoint__SWIG_0(GDALTransformerInfoShadow *self,int bDstToSrc,double inout[3]){
     int nRet, nSuccess = TRUE;
 
-    nRet = GDALUseTransformer( self, bDstToSrc, 
-                               1, &inout[0], &inout[1], &inout[2], 
+    nRet = GDALUseTransformer( self, bDstToSrc,
+                               1, &inout[0], &inout[1], &inout[2],
                                &nSuccess );
 
     return nRet && nSuccess;
   }
 SWIGINTERN int GDALTransformerInfoShadow_TransformPoint__SWIG_1(GDALTransformerInfoShadow *self,double argout[3],int bDstToSrc,double x,double y,double z=0.0){
     int nRet, nSuccess = TRUE;
-    
+
     argout[0] = x;
     argout[1] = y;
     argout[2] = z;
-    nRet = GDALUseTransformer( self, bDstToSrc, 
-                               1, &argout[0], &argout[1], &argout[2], 
+    nRet = GDALUseTransformer( self, bDstToSrc,
+                               1, &argout[0], &argout[1], &argout[2],
                                &nSuccess );
 
     return nRet && nSuccess;
@@ -5353,7 +5704,7 @@ SWIGINTERN int GDALTransformerInfoShadow_TransformGeolocations(GDALTransformerIn
 
     CPLErrorReset();
 
-    return GDALTransformGeolocations( xBand, yBand, zBand, 
+    return GDALTransformGeolocations( xBand, yBand, zBand,
                                       GDALUseTransformer, self,
                             	      callback, callback_data, options );
   }
@@ -5388,8 +5739,8 @@ static PyObject *XMLTreeToPyList( CPLXMLNode *psTree )
     if( psTree == NULL )
         return Py_None;
 
-    for( psChild = psTree->psChild; 
-         psChild != NULL; 
+    for( psChild = psTree->psChild;
+         psChild != NULL;
          psChild = psChild->psNext )
         nChildCount++;
 
@@ -5398,14 +5749,14 @@ static PyObject *XMLTreeToPyList( CPLXMLNode *psTree )
     PyList_SetItem( pyList, 0, Py_BuildValue( "i", (int) psTree->eType ) );
     PyList_SetItem( pyList, 1, Py_BuildValue( "s", psTree->pszValue ) );
 
-    for( psChild = psTree->psChild, iChild = 2; 
-         psChild != NULL; 
+    for( psChild = psTree->psChild, iChild = 2;
+         psChild != NULL;
          psChild = psChild->psNext, iChild++ )
     {
         PyList_SetItem( pyList, iChild, XMLTreeToPyList( psChild ) );
     }
 
-    return pyList; 
+    return pyList;
 }
 
 
@@ -5415,7 +5766,7 @@ static PyObject *XMLTreeToPyList( CPLXMLNode *psTree )
 static CPLXMLNode *PyListToXMLTree( PyObject *pyList )
 
 {
-    int      nChildCount = 0, iChild, nType;
+    int      nChildCount = 0, iChild, nType = 0;
     CPLXMLNode *psThisNode;
     CPLXMLNode *psChild;
     char       *pszText = NULL;
@@ -5427,8 +5778,8 @@ static CPLXMLNode *PyListToXMLTree( PyObject *pyList )
         return NULL;
     }
 
-    PyArg_Parse( PyList_GET_ITEM(pyList,0), "i", &nType );
-    PyArg_Parse( PyList_GET_ITEM(pyList,1), "s", &pszText );
+    CPL_IGNORE_RET_VAL(PyArg_Parse( PyList_GET_ITEM(pyList,0), "i", &nType ));
+    CPL_IGNORE_RET_VAL(PyArg_Parse( PyList_GET_ITEM(pyList,1), "s", &pszText ));
 
     /* Detect "pseudo" root */
     if (nType == CXT_Element && pszText != NULL && strlen(pszText) == 0 && nChildCount == 2)
@@ -5441,8 +5792,8 @@ static CPLXMLNode *PyListToXMLTree( PyObject *pyList )
         }
         int nTypeFirst = 0;
         char* pszTextFirst = NULL;
-        PyArg_Parse( PyList_GET_ITEM(pyFirst,0), "i", &nTypeFirst );
-        PyArg_Parse( PyList_GET_ITEM(pyFirst,1), "s", &pszTextFirst );
+        CPL_IGNORE_RET_VAL(PyArg_Parse( PyList_GET_ITEM(pyFirst,0), "i", &nTypeFirst ));
+        CPL_IGNORE_RET_VAL(PyArg_Parse( PyList_GET_ITEM(pyFirst,1), "s", &pszTextFirst ));
         if (nTypeFirst == CXT_Element && pszTextFirst != NULL && pszTextFirst[0] == '?')
         {
             psThisNode = PyListToXMLTree( PyList_GET_ITEM(pyList,2) );
@@ -5479,6 +5830,7 @@ int GetDriverCount() {
 }
 
 
+static
 GDALDriverShadow* GetDriverByName( char const *name ) {
   return (GDALDriverShadow*) GDALGetDriverByName( name );
 }
@@ -5506,6 +5858,10 @@ GDALDatasetShadow* OpenEx( char const* utf8_path, unsigned int nOpenFlags = 0,
                            char** allowed_drivers = NULL, char** open_options = NULL,
                            char** sibling_files = NULL ) {
   CPLErrorReset();
+#ifdef SWIGPYTHON
+  if( GetUseExceptions() )
+      nOpenFlags |= GDAL_OF_VERBOSE_ERROR;
+#endif
   GDALDatasetShadow *ds = GDALOpenEx( utf8_path, nOpenFlags, allowed_drivers,
                                       open_options, sibling_files );
   if( ds != NULL && CPLGetLastErrorType() == CE_Failure )
@@ -5547,9 +5903,9 @@ GDALDatasetShadow* OpenShared( char const* utf8_path, GDALAccess eAccess = GA_Re
 }
 
 
-GDALDriverShadow *IdentifyDriver( const char *utf8_path, 
+GDALDriverShadow *IdentifyDriver( const char *utf8_path,
                                   char **papszSiblings = NULL ) {
-    return (GDALDriverShadow *) GDALIdentifyDriver( utf8_path, 
+    return (GDALDriverShadow *) GDALIdentifyDriver( utf8_path,
 	                                            papszSiblings );
 }
 
@@ -5557,8 +5913,11 @@ GDALDriverShadow *IdentifyDriver( const char *utf8_path,
   char **GeneralCmdLineProcessor( char **papszArgv, int nOptions = 0 ) {
     int nResArgCount;
 
-    nResArgCount = 
-      GDALGeneralCmdLineProcessor( CSLCount(papszArgv), &papszArgv, nOptions ); 
+    if( papszArgv == NULL )
+        return NULL;
+
+    nResArgCount =
+      GDALGeneralCmdLineProcessor( CSLCount(papszArgv), &papszArgv, nOptions );
 
     if( nResArgCount <= 0 )
         return NULL;
@@ -5566,50 +5925,424 @@ GDALDriverShadow *IdentifyDriver( const char *utf8_path,
         return papszArgv;
   }
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-SWIGINTERN PyObject *_wrap_GetUseExceptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  int result;
-  
-  if (!PyArg_ParseTuple(args,(char *)":GetUseExceptions")) SWIG_fail;
-  result = (int)GetUseExceptions();
-  resultobj = SWIG_From_int(static_cast< int >(result));
-  return resultobj;
-fail:
-  return NULL;
-}
 
+#include "gdal_utils.h"
 
-SWIGINTERN PyObject *_wrap_UseExceptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  
-  if (!PyArg_ParseTuple(args,(char *)":UseExceptions")) SWIG_fail;
-  UseExceptions();
-  resultobj = SWIG_Py_Void();
-  return resultobj;
-fail:
-  return NULL;
+SWIGINTERN GDALInfoOptions *new_GDALInfoOptions(char **options){
+        return GDALInfoOptionsNew(options, NULL);
+    }
+SWIGINTERN void delete_GDALInfoOptions(GDALInfoOptions *self){
+        GDALInfoOptionsFree( self );
+    }
+SWIGINTERN GDALTranslateOptions *new_GDALTranslateOptions(char **options){
+        return GDALTranslateOptionsNew(options, NULL);
+    }
+SWIGINTERN void delete_GDALTranslateOptions(GDALTranslateOptions *self){
+        GDALTranslateOptionsFree( self );
+    }
+
+GDALDatasetShadow* wrapper_GDALTranslate( const char* dest,
+                                      GDALDatasetShadow* dataset,
+                                      GDALTranslateOptions* translateOptions,
+                                      GDALProgressFunc callback=NULL,
+                                      void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( translateOptions == NULL )
+        {
+            bFreeOptions = true;
+            translateOptions = GDALTranslateOptionsNew(NULL, NULL);
+        }
+        GDALTranslateOptionsSetProgress(translateOptions, callback, callback_data);
+    }
+    GDALDatasetH hDSRet = GDALTranslate(dest, dataset, translateOptions, &usageError);
+    if( bFreeOptions )
+        GDALTranslateOptionsFree(translateOptions);
+    return hDSRet;
 }
 
+SWIGINTERN GDALWarpAppOptions *new_GDALWarpAppOptions(char **options){
+        return GDALWarpAppOptionsNew(options, NULL);
+    }
+SWIGINTERN void delete_GDALWarpAppOptions(GDALWarpAppOptions *self){
+        GDALWarpAppOptionsFree( self );
+    }
 
-SWIGINTERN PyObject *_wrap_DontUseExceptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  
-  if (!PyArg_ParseTuple(args,(char *)":DontUseExceptions")) SWIG_fail;
-  DontUseExceptions();
-  resultobj = SWIG_Py_Void();
-  return resultobj;
-fail:
-  return NULL;
+int wrapper_GDALWarpDestDS( GDALDatasetShadow* dstDS,
+                            int object_list_count, GDALDatasetShadow** poObjects,
+                            GDALWarpAppOptions* warpAppOptions,
+                            GDALProgressFunc callback=NULL,
+                            void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( warpAppOptions == NULL )
+        {
+            bFreeOptions = true;
+            warpAppOptions = GDALWarpAppOptionsNew(NULL, NULL);
+        }
+        GDALWarpAppOptionsSetProgress(warpAppOptions, callback, callback_data);
+    }
+    int bRet = (GDALWarp(NULL, dstDS, object_list_count, poObjects, warpAppOptions, &usageError) != NULL);
+    if( bFreeOptions )
+        GDALWarpAppOptionsFree(warpAppOptions);
+    return bRet;
 }
 
 
-SWIGINTERN PyObject *_wrap_VSIFReadL(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  void **arg1 = (void **) 0 ;
-  int arg2 ;
+GDALDatasetShadow* wrapper_GDALWarpDestName( const char* dest,
+                                             int object_list_count, GDALDatasetShadow** poObjects,
+                                             GDALWarpAppOptions* warpAppOptions,
+                                             GDALProgressFunc callback=NULL,
+                                             void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( warpAppOptions == NULL )
+        {
+            bFreeOptions = true;
+            warpAppOptions = GDALWarpAppOptionsNew(NULL, NULL);
+        }
+        GDALWarpAppOptionsSetProgress(warpAppOptions, callback, callback_data);
+    }
+    GDALDatasetH hDSRet = GDALWarp(dest, NULL, object_list_count, poObjects, warpAppOptions, &usageError);
+    if( bFreeOptions )
+        GDALWarpAppOptionsFree(warpAppOptions);
+    return hDSRet;
+}
+
+SWIGINTERN GDALVectorTranslateOptions *new_GDALVectorTranslateOptions(char **options){
+        return GDALVectorTranslateOptionsNew(options, NULL);
+    }
+SWIGINTERN void delete_GDALVectorTranslateOptions(GDALVectorTranslateOptions *self){
+        GDALVectorTranslateOptionsFree( self );
+    }
+
+int wrapper_GDALVectorTranslateDestDS( GDALDatasetShadow* dstDS,
+                                       GDALDatasetShadow* srcDS,
+                            GDALVectorTranslateOptions* options,
+                            GDALProgressFunc callback=NULL,
+                            void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( options == NULL )
+        {
+            bFreeOptions = true;
+            options = GDALVectorTranslateOptionsNew(NULL, NULL);
+        }
+        GDALVectorTranslateOptionsSetProgress(options, callback, callback_data);
+    }
+    int bRet = (GDALVectorTranslate(NULL, dstDS, 1, &srcDS, options, &usageError) != NULL);
+    if( bFreeOptions )
+        GDALVectorTranslateOptionsFree(options);
+    return bRet;
+}
+
+
+GDALDatasetShadow* wrapper_GDALVectorTranslateDestName( const char* dest,
+                                             GDALDatasetShadow* srcDS,
+                                             GDALVectorTranslateOptions* options,
+                                             GDALProgressFunc callback=NULL,
+                                             void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( options == NULL )
+        {
+            bFreeOptions = true;
+            options = GDALVectorTranslateOptionsNew(NULL, NULL);
+        }
+        GDALVectorTranslateOptionsSetProgress(options, callback, callback_data);
+    }
+    GDALDatasetH hDSRet = GDALVectorTranslate(dest, NULL, 1, &srcDS, options, &usageError);
+    if( bFreeOptions )
+        GDALVectorTranslateOptionsFree(options);
+    return hDSRet;
+}
+
+SWIGINTERN GDALDEMProcessingOptions *new_GDALDEMProcessingOptions(char **options){
+        return GDALDEMProcessingOptionsNew(options, NULL);
+    }
+SWIGINTERN void delete_GDALDEMProcessingOptions(GDALDEMProcessingOptions *self){
+        GDALDEMProcessingOptionsFree( self );
+    }
+
+GDALDatasetShadow* wrapper_GDALDEMProcessing( const char* dest,
+                                      GDALDatasetShadow* dataset,
+                                      const char* pszProcessing,
+                                      const char* pszColorFilename,
+                                      GDALDEMProcessingOptions* options,
+                                      GDALProgressFunc callback=NULL,
+                                      void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( options == NULL )
+        {
+            bFreeOptions = true;
+            options = GDALDEMProcessingOptionsNew(NULL, NULL);
+        }
+        GDALDEMProcessingOptionsSetProgress(options, callback, callback_data);
+    }
+    GDALDatasetH hDSRet = GDALDEMProcessing(dest, dataset, pszProcessing, pszColorFilename, options, &usageError);
+    if( bFreeOptions )
+        GDALDEMProcessingOptionsFree(options);
+    return hDSRet;
+}
+
+SWIGINTERN GDALNearblackOptions *new_GDALNearblackOptions(char **options){
+        return GDALNearblackOptionsNew(options, NULL);
+    }
+SWIGINTERN void delete_GDALNearblackOptions(GDALNearblackOptions *self){
+        GDALNearblackOptionsFree( self );
+    }
+
+int wrapper_GDALNearblackDestDS( GDALDatasetShadow* dstDS,
+                            GDALDatasetShadow* srcDS,
+                            GDALNearblackOptions* options,
+                            GDALProgressFunc callback=NULL,
+                            void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( options == NULL )
+        {
+            bFreeOptions = true;
+            options = GDALNearblackOptionsNew(NULL, NULL);
+        }
+        GDALNearblackOptionsSetProgress(options, callback, callback_data);
+    }
+    int bRet = (GDALNearblack(NULL, dstDS, srcDS, options, &usageError) != NULL);
+    if( bFreeOptions )
+        GDALNearblackOptionsFree(options);
+    return bRet;
+}
+
+
+GDALDatasetShadow* wrapper_GDALNearblackDestName( const char* dest,
+                                             GDALDatasetShadow* srcDS,
+                                             GDALNearblackOptions* options,
+                                             GDALProgressFunc callback=NULL,
+                                             void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( options == NULL )
+        {
+            bFreeOptions = true;
+            options = GDALNearblackOptionsNew(NULL, NULL);
+        }
+        GDALNearblackOptionsSetProgress(options, callback, callback_data);
+    }
+    GDALDatasetH hDSRet = GDALNearblack(dest, NULL, srcDS, options, &usageError);
+    if( bFreeOptions )
+        GDALNearblackOptionsFree(options);
+    return hDSRet;
+}
+
+SWIGINTERN GDALGridOptions *new_GDALGridOptions(char **options){
+        return GDALGridOptionsNew(options, NULL);
+    }
+SWIGINTERN void delete_GDALGridOptions(GDALGridOptions *self){
+        GDALGridOptionsFree( self );
+    }
+
+GDALDatasetShadow* wrapper_GDALGrid( const char* dest,
+                                      GDALDatasetShadow* dataset,
+                                      GDALGridOptions* options,
+                                      GDALProgressFunc callback=NULL,
+                                      void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( options == NULL )
+        {
+            bFreeOptions = true;
+            options = GDALGridOptionsNew(NULL, NULL);
+        }
+        GDALGridOptionsSetProgress(options, callback, callback_data);
+    }
+    GDALDatasetH hDSRet = GDALGrid(dest, dataset, options, &usageError);
+    if( bFreeOptions )
+        GDALGridOptionsFree(options);
+    return hDSRet;
+}
+
+SWIGINTERN GDALRasterizeOptions *new_GDALRasterizeOptions(char **options){
+        return GDALRasterizeOptionsNew(options, NULL);
+    }
+SWIGINTERN void delete_GDALRasterizeOptions(GDALRasterizeOptions *self){
+        GDALRasterizeOptionsFree( self );
+    }
+
+int wrapper_GDALRasterizeDestDS( GDALDatasetShadow* dstDS,
+                            GDALDatasetShadow* srcDS,
+                            GDALRasterizeOptions* options,
+                            GDALProgressFunc callback=NULL,
+                            void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( options == NULL )
+        {
+            bFreeOptions = true;
+            options = GDALRasterizeOptionsNew(NULL, NULL);
+        }
+        GDALRasterizeOptionsSetProgress(options, callback, callback_data);
+    }
+    int bRet = (GDALRasterize(NULL, dstDS, srcDS, options, &usageError) != NULL);
+    if( bFreeOptions )
+        GDALRasterizeOptionsFree(options);
+    return bRet;
+}
+
+
+GDALDatasetShadow* wrapper_GDALRasterizeDestName( const char* dest,
+                                             GDALDatasetShadow* srcDS,
+                                             GDALRasterizeOptions* options,
+                                             GDALProgressFunc callback=NULL,
+                                             void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( options == NULL )
+        {
+            bFreeOptions = true;
+            options = GDALRasterizeOptionsNew(NULL, NULL);
+        }
+        GDALRasterizeOptionsSetProgress(options, callback, callback_data);
+    }
+    GDALDatasetH hDSRet = GDALRasterize(dest, NULL, srcDS, options, &usageError);
+    if( bFreeOptions )
+        GDALRasterizeOptionsFree(options);
+    return hDSRet;
+}
+
+SWIGINTERN GDALBuildVRTOptions *new_GDALBuildVRTOptions(char **options){
+        return GDALBuildVRTOptionsNew(options, NULL);
+    }
+SWIGINTERN void delete_GDALBuildVRTOptions(GDALBuildVRTOptions *self){
+        GDALBuildVRTOptionsFree( self );
+    }
+
+GDALDatasetShadow* wrapper_GDALBuildVRT_objects( const char* dest,
+                                             int object_list_count, GDALDatasetShadow** poObjects,
+                                             GDALBuildVRTOptions* options,
+                                             GDALProgressFunc callback=NULL,
+                                             void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( options == NULL )
+        {
+            bFreeOptions = true;
+            options = GDALBuildVRTOptionsNew(NULL, NULL);
+        }
+        GDALBuildVRTOptionsSetProgress(options, callback, callback_data);
+    }
+    GDALDatasetH hDSRet = GDALBuildVRT(dest, object_list_count, poObjects, NULL, options, &usageError);
+    if( bFreeOptions )
+        GDALBuildVRTOptionsFree(options);
+    return hDSRet;
+}
+
+
+GDALDatasetShadow* wrapper_GDALBuildVRT_names( const char* dest,
+                                         char ** source_filenames,
+                                         GDALBuildVRTOptions* options,
+                                         GDALProgressFunc callback=NULL,
+                                         void* callback_data=NULL)
+{
+    int usageError; /* ignored */
+    bool bFreeOptions = false;
+    if( callback )
+    {
+        if( options == NULL )
+        {
+            bFreeOptions = true;
+            options = GDALBuildVRTOptionsNew(NULL, NULL);
+        }
+        GDALBuildVRTOptionsSetProgress(options, callback, callback_data);
+    }
+    GDALDatasetH hDSRet = GDALBuildVRT(dest, CSLCount(source_filenames), NULL, source_filenames, options, &usageError);
+    if( bFreeOptions )
+        GDALBuildVRTOptionsFree(options);
+    return hDSRet;
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+SWIGINTERN PyObject *_wrap_GetUseExceptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)":GetUseExceptions")) SWIG_fail;
+  result = (int)GetUseExceptions();
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_UseExceptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  
+  if (!PyArg_ParseTuple(args,(char *)":UseExceptions")) SWIG_fail;
+  UseExceptions();
+  resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_DontUseExceptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  
+  if (!PyArg_ParseTuple(args,(char *)":DontUseExceptions")) SWIG_fail;
+  DontUseExceptions();
+  resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_VSIFReadL(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  void **arg1 = (void **) 0 ;
+  int arg2 ;
   int arg3 ;
   VSILFILE *arg4 = (VSILFILE *) 0 ;
   void *pyObject1 = NULL ;
@@ -5647,12 +6380,14 @@ SWIGINTERN PyObject *_wrap_VSIFReadL(PyObject *SWIGUNUSEDPARM(self), PyObject *a
       CPLErrorReset();
     }
     result = (int)wrapper_VSIFReadL(arg1,arg2,arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
@@ -5668,6 +6403,7 @@ SWIGINTERN PyObject *_wrap_VSIFReadL(PyObject *SWIGUNUSEDPARM(self), PyObject *a
       Py_INCREF(resultobj);
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -5675,7 +6411,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Debug(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   char *arg2 = (char *) 0 ;
   int res1 ;
@@ -5703,16 +6439,19 @@ SWIGINTERN PyObject *_wrap_Debug(PyObject *SWIGUNUSEDPARM(self), PyObject *args)
       CPLErrorReset();
     }
     Debug((char const *)arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
@@ -5722,7 +6461,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SetErrorHandler(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) NULL ;
   int res1 ;
   char *buf1 = 0 ;
@@ -5742,26 +6481,19 @@ SWIGINTERN PyObject *_wrap_SetErrorHandler(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)SetErrorHandler((char const *)arg1);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)SetErrorHandler((char const *)arg1));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-  {
-    /* %typemap(ret) CPLErr */
-    if ( bUseExceptions == 0 ) {
-      /* We're not using exceptions.  And no error has occurred */
-      if ( resultobj == 0 ) {
-        /* No other return values set so return ErrorCode */
-        resultobj = PyInt_FromLong(result);
-      }
-    }
-  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
@@ -5770,7 +6502,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_PushErrorHandler(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   CPLErrorHandler arg1 = (CPLErrorHandler) NULL ;
   void *arg2 = (void *) NULL ;
   PyObject * obj0 = 0 ;
@@ -5802,7 +6534,7 @@ SWIGINTERN PyObject *_wrap_PushErrorHandler(PyObject *SWIGUNUSEDPARM(self), PyOb
       }
       else if (!PyCallable_Check(obj0))
       {
-        PyErr_SetString( PyExc_RuntimeError, 
+        PyErr_SetString( PyExc_RuntimeError,
           "Object given is not a String or a Python function" );
         SWIG_fail;
       }
@@ -5818,25 +6550,18 @@ SWIGINTERN PyObject *_wrap_PushErrorHandler(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)PushErrorHandler(arg1,arg2);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)PushErrorHandler(arg1,arg2));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
-  {
-    /* %typemap(ret) CPLErr */
-    if ( bUseExceptions == 0 ) {
-      /* We're not using exceptions.  And no error has occurred */
-      if ( resultobj == 0 ) {
-        /* No other return values set so return ErrorCode */
-        resultobj = PyInt_FromLong(result);
-      }
-    }
-  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -5844,7 +6569,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_PopErrorHandler(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   
   if (!PyArg_ParseTuple(args,(char *)":PopErrorHandler")) SWIG_fail;
   {
@@ -5852,14 +6577,17 @@ SWIGINTERN PyObject *_wrap_PopErrorHandler(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     PopErrorHandler();
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -5867,7 +6595,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Error(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   CPLErr arg1 = (CPLErr) CE_Failure ;
   int arg2 = (int) 0 ;
   char *arg3 = (char *) "error" ;
@@ -5909,15 +6637,18 @@ SWIGINTERN PyObject *_wrap_Error(PyObject *SWIGUNUSEDPARM(self), PyObject *args)
       CPLErrorReset();
     }
     Error(arg1,arg2,(char const *)arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
@@ -5926,7 +6657,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GOA2GetAuthorizationURL(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   int res1 ;
   char *buf1 = 0 ;
@@ -5945,12 +6676,14 @@ SWIGINTERN PyObject *_wrap_GOA2GetAuthorizationURL(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     result = (retStringAndCPLFree *)GOA2GetAuthorizationURL((char const *)arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) (retStringAndCPLFree*) */
@@ -5961,6 +6694,7 @@ SWIGINTERN PyObject *_wrap_GOA2GetAuthorizationURL(PyObject *SWIGUNUSEDPARM(self
     }
   }
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
@@ -5969,7 +6703,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GOA2GetRefreshToken(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   char *arg2 = (char *) 0 ;
   int res1 ;
@@ -5998,12 +6732,14 @@ SWIGINTERN PyObject *_wrap_GOA2GetRefreshToken(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     result = (retStringAndCPLFree *)GOA2GetRefreshToken((char const *)arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) (retStringAndCPLFree*) */
@@ -6015,6 +6751,7 @@ SWIGINTERN PyObject *_wrap_GOA2GetRefreshToken(PyObject *SWIGUNUSEDPARM(self), P
   }
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
@@ -6024,7 +6761,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GOA2GetAccessToken(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   char *arg2 = (char *) 0 ;
   int res1 ;
@@ -6053,12 +6790,14 @@ SWIGINTERN PyObject *_wrap_GOA2GetAccessToken(PyObject *SWIGUNUSEDPARM(self), Py
       CPLErrorReset();
     }
     result = (retStringAndCPLFree *)GOA2GetAccessToken((char const *)arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) (retStringAndCPLFree*) */
@@ -6070,6 +6809,7 @@ SWIGINTERN PyObject *_wrap_GOA2GetAccessToken(PyObject *SWIGUNUSEDPARM(self), Py
   }
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
@@ -6079,7 +6819,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_ErrorReset(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   
   if (!PyArg_ParseTuple(args,(char *)":ErrorReset")) SWIG_fail;
   {
@@ -6087,14 +6827,17 @@ SWIGINTERN PyObject *_wrap_ErrorReset(PyObject *SWIGUNUSEDPARM(self), PyObject *
       CPLErrorReset();
     }
     CPLErrorReset();
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6102,7 +6845,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_EscapeString(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   int arg1 ;
   char *arg2 = (char *) 0 ;
   int arg3 = (int) CPLES_SQL ;
@@ -6168,12 +6911,14 @@ SWIGINTERN PyObject *_wrap_EscapeString(PyObject *SWIGUNUSEDPARM(self), PyObject
       CPLErrorReset();
     }
     result = (retStringAndCPLFree *)EscapeString(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) (retStringAndCPLFree*) */
@@ -6185,15 +6930,16 @@ SWIGINTERN PyObject *_wrap_EscapeString(PyObject *SWIGUNUSEDPARM(self), PyObject
   }
   {
     /* %typemap(freearg) (int *nLen, char *pBuf ) */
-    if( alloc1 == SWIG_NEWOBJ ) {
+    if (ReturnSame(alloc1) == SWIG_NEWOBJ ) {
       delete[] arg2;
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
     /* %typemap(freearg) (int *nLen, char *pBuf ) */
-    if( alloc1 == SWIG_NEWOBJ ) {
+    if (ReturnSame(alloc1) == SWIG_NEWOBJ ) {
       delete[] arg2;
     }
   }
@@ -6202,14 +6948,19 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GetLastErrorNo(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   int result;
   
   if (!PyArg_ParseTuple(args,(char *)":GetLastErrorNo")) SWIG_fail;
   {
+#ifdef SED_HACKS
+    if( bUseExceptions ) bLocalUseExceptionsCode = FALSE;
+#endif
+    
     result = CPLGetLastErrorNo();
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6217,14 +6968,19 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GetLastErrorType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   int result;
   
   if (!PyArg_ParseTuple(args,(char *)":GetLastErrorType")) SWIG_fail;
   {
+#ifdef SED_HACKS
+    if( bUseExceptions ) bLocalUseExceptionsCode = FALSE;
+#endif
+    
     result = CPLGetLastErrorType();
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6232,14 +6988,73 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GetLastErrorMsg(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *result = 0 ;
   
   if (!PyArg_ParseTuple(args,(char *)":GetLastErrorMsg")) SWIG_fail;
   {
+#ifdef SED_HACKS
+    if( bUseExceptions ) bLocalUseExceptionsCode = FALSE;
+#endif
+    
     result = (char*)CPLGetLastErrorMsg();
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_VSIGetLastErrorNo(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)":VSIGetLastErrorNo")) SWIG_fail;
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)VSIGetLastErrorNo();
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_VSIGetLastErrorMsg(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  char *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)":VSIGetLastErrorMsg")) SWIG_fail;
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (char *)VSIGetLastErrorMsg();
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6247,7 +7062,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_PushFinderLocation(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   int bToFree1 = 0 ;
   PyObject * obj0 = 0 ;
@@ -6272,18 +7087,21 @@ SWIGINTERN PyObject *_wrap_PushFinderLocation(PyObject *SWIGUNUSEDPARM(self), Py
       CPLErrorReset();
     }
     CPLPushFinderLocation((char const *)arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
     /* %typemap(freearg) (const char *utf8_path) */
     GDALPythonFreeCStr(arg1, bToFree1);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -6295,7 +7113,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_PopFinderLocation(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   
   if (!PyArg_ParseTuple(args,(char *)":PopFinderLocation")) SWIG_fail;
   {
@@ -6303,14 +7121,17 @@ SWIGINTERN PyObject *_wrap_PopFinderLocation(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     CPLPopFinderLocation();
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6318,7 +7139,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FinderClean(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   
   if (!PyArg_ParseTuple(args,(char *)":FinderClean")) SWIG_fail;
   {
@@ -6326,14 +7147,17 @@ SWIGINTERN PyObject *_wrap_FinderClean(PyObject *SWIGUNUSEDPARM(self), PyObject
       CPLErrorReset();
     }
     CPLFinderClean();
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6341,7 +7165,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FindFile(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   char *arg2 = (char *) 0 ;
   int res1 ;
@@ -6377,12 +7201,14 @@ SWIGINTERN PyObject *_wrap_FindFile(PyObject *SWIGUNUSEDPARM(self), PyObject *ar
       CPLErrorReset();
     }
     result = (char *)CPLFindFile((char const *)arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
@@ -6390,6 +7216,7 @@ SWIGINTERN PyObject *_wrap_FindFile(PyObject *SWIGUNUSEDPARM(self), PyObject *ar
     /* %typemap(freearg) (const char *utf8_path) */
     GDALPythonFreeCStr(arg2, bToFree2);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
@@ -6402,13 +7229,17 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_ReadDir(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
+  int arg2 = (int) 0 ;
   int bToFree1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
   PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
   char **result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:ReadDir",&obj0)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O|O:ReadDir",&obj0,&obj1)) SWIG_fail;
   {
     /* %typemap(in) (const char *utf8_path) */
     arg1 = GDALPythonObjectToCStr( obj0, &bToFree1 );
@@ -6418,6 +7249,13 @@ SWIGINTERN PyObject *_wrap_ReadDir(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
       SWIG_fail;
     }
   }
+  if (obj1) {
+    ecode2 = SWIG_AsVal_int(obj1, &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "ReadDir" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+  }
   {
     if (!arg1) {
       SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
@@ -6427,13 +7265,15 @@ SWIGINTERN PyObject *_wrap_ReadDir(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char **)VSIReadDir((char const *)arg1);
+    result = (char **)wrapper_VSIReadDirEx((char const *)arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) char **CSL -> ( string ) */
@@ -6456,6 +7296,7 @@ SWIGINTERN PyObject *_wrap_ReadDir(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
     /* %typemap(freearg) (const char *utf8_path) */
     GDALPythonFreeCStr(arg1, bToFree1);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -6467,7 +7308,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_ReadDirRecursive(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   int bToFree1 = 0 ;
   PyObject * obj0 = 0 ;
@@ -6493,12 +7334,14 @@ SWIGINTERN PyObject *_wrap_ReadDirRecursive(PyObject *SWIGUNUSEDPARM(self), PyOb
       CPLErrorReset();
     }
     result = (char **)VSIReadDirRecursive((char const *)arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) char **CSL -> ( string ) */
@@ -6521,6 +7364,7 @@ SWIGINTERN PyObject *_wrap_ReadDirRecursive(PyObject *SWIGUNUSEDPARM(self), PyOb
     /* %typemap(freearg) (const char *utf8_path) */
     GDALPythonFreeCStr(arg1, bToFree1);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -6532,7 +7376,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SetConfigOption(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   char *arg2 = (char *) 0 ;
   int res1 ;
@@ -6565,16 +7409,19 @@ SWIGINTERN PyObject *_wrap_SetConfigOption(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     CPLSetConfigOption((char const *)arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
@@ -6584,7 +7431,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GetConfigOption(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   char *arg2 = (char *) NULL ;
   int res1 ;
@@ -6620,16 +7467,19 @@ SWIGINTERN PyObject *_wrap_GetConfigOption(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     result = (char *)wrapper_CPLGetConfigOption((char const *)arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
@@ -6639,7 +7489,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_CPLBinaryToHex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   int arg1 ;
   GByte *arg2 = (GByte *) 0 ;
   int alloc1 = 0 ;
@@ -6691,12 +7541,14 @@ SWIGINTERN PyObject *_wrap_CPLBinaryToHex(PyObject *SWIGUNUSEDPARM(self), PyObje
       CPLErrorReset();
     }
     result = (retStringAndCPLFree *)CPLBinaryToHex(arg1,(GByte const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) (retStringAndCPLFree*) */
@@ -6708,15 +7560,16 @@ SWIGINTERN PyObject *_wrap_CPLBinaryToHex(PyObject *SWIGUNUSEDPARM(self), PyObje
   }
   {
     /* %typemap(freearg) (int *nLen, char *pBuf ) */
-    if( alloc1 == SWIG_NEWOBJ ) {
+    if (ReturnSame(alloc1) == SWIG_NEWOBJ ) {
       delete[] arg2;
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
     /* %typemap(freearg) (int *nLen, char *pBuf ) */
-    if( alloc1 == SWIG_NEWOBJ ) {
+    if (ReturnSame(alloc1) == SWIG_NEWOBJ ) {
       delete[] arg2;
     }
   }
@@ -6725,7 +7578,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_CPLHexToBinary(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   int *arg2 = (int *) 0 ;
   int res1 ;
@@ -6753,15 +7606,18 @@ SWIGINTERN PyObject *_wrap_CPLHexToBinary(PyObject *SWIGUNUSEDPARM(self), PyObje
       CPLErrorReset();
     }
     result = (GByte *)CPLHexToBinary((char const *)arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GByte, 0 |  0 );
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
@@ -6770,7 +7626,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FileFromMemBuffer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   int arg2 ;
   GByte *arg3 = (GByte *) 0 ;
@@ -6838,12 +7694,14 @@ SWIGINTERN PyObject *_wrap_FileFromMemBuffer(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     wrapper_VSIFileFromMemBuffer((char const *)arg1,arg2,(GByte const *)arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
@@ -6852,10 +7710,11 @@ SWIGINTERN PyObject *_wrap_FileFromMemBuffer(PyObject *SWIGUNUSEDPARM(self), PyO
   }
   {
     /* %typemap(freearg) (int *nLen, char *pBuf ) */
-    if( alloc2 == SWIG_NEWOBJ ) {
+    if (ReturnSame(alloc2) == SWIG_NEWOBJ ) {
       delete[] arg3;
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -6864,7 +7723,7 @@ fail:
   }
   {
     /* %typemap(freearg) (int *nLen, char *pBuf ) */
-    if( alloc2 == SWIG_NEWOBJ ) {
+    if (ReturnSame(alloc2) == SWIG_NEWOBJ ) {
       delete[] arg3;
     }
   }
@@ -6873,7 +7732,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Unlink(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   int bToFree1 = 0 ;
   PyObject * obj0 = 0 ;
@@ -6899,18 +7758,21 @@ SWIGINTERN PyObject *_wrap_Unlink(PyObject *SWIGUNUSEDPARM(self), PyObject *args
       CPLErrorReset();
     }
     result = VSIUnlink((char const *)arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
     /* %typemap(freearg) (const char *utf8_path) */
     GDALPythonFreeCStr(arg1, bToFree1);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -6922,7 +7784,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_HasThreadSupport(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   int result;
   
   if (!PyArg_ParseTuple(args,(char *)":HasThreadSupport")) SWIG_fail;
@@ -6931,14 +7793,17 @@ SWIGINTERN PyObject *_wrap_HasThreadSupport(PyObject *SWIGUNUSEDPARM(self), PyOb
       CPLErrorReset();
     }
     result = (int)wrapper_HasThreadSupport();
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6946,7 +7811,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Mkdir(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   int arg2 ;
   int bToFree1 = 0 ;
@@ -6981,18 +7846,21 @@ SWIGINTERN PyObject *_wrap_Mkdir(PyObject *SWIGUNUSEDPARM(self), PyObject *args)
       CPLErrorReset();
     }
     result = VSIMkdir((char const *)arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
     /* %typemap(freearg) (const char *utf8_path) */
     GDALPythonFreeCStr(arg1, bToFree1);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -7004,7 +7872,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Rmdir(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   int bToFree1 = 0 ;
   PyObject * obj0 = 0 ;
@@ -7030,18 +7898,21 @@ SWIGINTERN PyObject *_wrap_Rmdir(PyObject *SWIGUNUSEDPARM(self), PyObject *args)
       CPLErrorReset();
     }
     result = VSIRmdir((char const *)arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
     /* %typemap(freearg) (const char *utf8_path) */
     GDALPythonFreeCStr(arg1, bToFree1);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -7053,55 +7924,84 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Rename(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   char *arg2 = (char *) 0 ;
-  int res1 ;
-  char *buf1 = 0 ;
-  int alloc1 = 0 ;
-  int res2 ;
-  char *buf2 = 0 ;
-  int alloc2 = 0 ;
+  int bToFree1 = 0 ;
+  int bToFree2 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   VSI_RETVAL result;
   
   if (!PyArg_ParseTuple(args,(char *)"OO:Rename",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, NULL, &alloc1);
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Rename" "', argument " "1"" of type '" "char const *""'");
-  }
-  arg1 = reinterpret_cast< char * >(buf1);
-  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Rename" "', argument " "2"" of type '" "char const *""'");
-  }
-  arg2 = reinterpret_cast< char * >(buf2);
   {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
+    /* %typemap(in) (const char *utf8_path) */
+    arg1 = GDALPythonObjectToCStr( obj0, &bToFree1 );
+    if (arg1 == NULL)
+    {
+      PyErr_SetString( PyExc_RuntimeError, "not a string" );
+      SWIG_fail;
     }
-    result = VSIRename((char const *)arg1,(char const *)arg2);
+  }
+  {
+    /* %typemap(in) (const char *utf8_path) */
+    arg2 = GDALPythonObjectToCStr( obj1, &bToFree2 );
+    if (arg2 == NULL)
+    {
+      PyErr_SetString( PyExc_RuntimeError, "not a string" );
+      SWIG_fail;
+    }
+  }
+  {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = VSIRename((char const *)arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
-  if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
+  }
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg2, bToFree2);
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
-  if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
+  }
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg2, bToFree2);
+  }
   return NULL;
 }
 
 
 SWIGINTERN PyObject *_wrap_StatBuf_mode_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   StatBuf *arg1 = (StatBuf *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -7116,6 +8016,7 @@ SWIGINTERN PyObject *_wrap_StatBuf_mode_get(PyObject *SWIGUNUSEDPARM(self), PyOb
   arg1 = reinterpret_cast< StatBuf * >(argp1);
   result = (int) ((arg1)->mode);
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7123,7 +8024,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_StatBuf_size_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   StatBuf *arg1 = (StatBuf *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -7146,6 +8047,7 @@ SWIGINTERN PyObject *_wrap_StatBuf_size_get(PyObject *SWIGUNUSEDPARM(self), PyOb
     resultobj = PyInt_FromString(szTmp, NULL, 10);
 #endif
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7153,7 +8055,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_StatBuf_mtime_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   StatBuf *arg1 = (StatBuf *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -7176,6 +8078,7 @@ SWIGINTERN PyObject *_wrap_StatBuf_mtime_get(PyObject *SWIGUNUSEDPARM(self), PyO
     resultobj = PyInt_FromString(szTmp, NULL, 10);
 #endif
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7183,7 +8086,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_new_StatBuf(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   StatBuf *arg1 = (StatBuf *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -7201,14 +8104,17 @@ SWIGINTERN PyObject *_wrap_new_StatBuf(PyObject *SWIGUNUSEDPARM(self), PyObject
       CPLErrorReset();
     }
     result = (StatBuf *)new_StatBuf(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_StatBuf, SWIG_POINTER_NEW |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7216,7 +8122,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_delete_StatBuf(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   StatBuf *arg1 = (StatBuf *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -7233,14 +8139,17 @@ SWIGINTERN PyObject *_wrap_delete_StatBuf(PyObject *SWIGUNUSEDPARM(self), PyObje
       CPLErrorReset();
     }
     delete_StatBuf(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7248,7 +8157,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_StatBuf_IsDirectory(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   StatBuf *arg1 = (StatBuf *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -7266,14 +8175,17 @@ SWIGINTERN PyObject *_wrap_StatBuf_IsDirectory(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     result = (int)StatBuf_IsDirectory(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7288,7 +8200,7 @@ SWIGINTERN PyObject *StatBuf_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObje
 }
 
 SWIGINTERN PyObject *_wrap_VSIStatL(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   StatBuf *arg2 = (StatBuf *) 0 ;
   int arg3 = (int) 0 ;
@@ -7331,12 +8243,14 @@ SWIGINTERN PyObject *_wrap_VSIStatL(PyObject *SWIGUNUSEDPARM(self), PyObject *ar
       CPLErrorReset();
     }
     result = (int)wrapper_VSIStatL((char const *)arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
@@ -7351,6 +8265,7 @@ SWIGINTERN PyObject *_wrap_VSIStatL(PyObject *SWIGUNUSEDPARM(self), PyObject *ar
     /* %typemap(freearg) (const char *utf8_path) */
     GDALPythonFreeCStr(arg1, bToFree1);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -7362,7 +8277,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_VSIFOpenL(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   char *arg2 = (char *) 0 ;
   int bToFree1 = 0 ;
@@ -7398,12 +8313,87 @@ SWIGINTERN PyObject *_wrap_VSIFOpenL(PyObject *SWIGUNUSEDPARM(self), PyObject *a
       CPLErrorReset();
     }
     result = (VSILFILE *)wrapper_VSIFOpenL((char const *)arg1,(char const *)arg2);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_void, 0 |  0 );
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
+  }
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
+  }
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_VSIFOpenExL(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  char *arg1 = (char *) 0 ;
+  char *arg2 = (char *) 0 ;
+  int arg3 ;
+  int bToFree1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  VSILFILE *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOO:VSIFOpenExL",&obj0,&obj1,&obj2)) SWIG_fail;
+  {
+    /* %typemap(in) (const char *utf8_path) */
+    arg1 = GDALPythonObjectToCStr( obj0, &bToFree1 );
+    if (arg1 == NULL)
+    {
+      PyErr_SetString( PyExc_RuntimeError, "not a string" );
+      SWIG_fail;
+    }
+  }
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "VSIFOpenExL" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "VSIFOpenExL" "', argument " "3"" of type '" "int""'");
+  } 
+  arg3 = static_cast< int >(val3);
+  {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (VSILFILE *)wrapper_VSIFOpenExL((char const *)arg1,(char const *)arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_void, 0 |  0 );
   {
@@ -7411,6 +8401,7 @@ SWIGINTERN PyObject *_wrap_VSIFOpenL(PyObject *SWIGUNUSEDPARM(self), PyObject *a
     GDALPythonFreeCStr(arg1, bToFree1);
   }
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -7423,7 +8414,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_VSIFCloseL(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   VSILFILE *arg1 = (VSILFILE *) 0 ;
   int res1 ;
   PyObject * obj0 = 0 ;
@@ -7435,18 +8426,26 @@ SWIGINTERN PyObject *_wrap_VSIFCloseL(PyObject *SWIGUNUSEDPARM(self), PyObject *
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "VSIFCloseL" "', argument " "1"" of type '" "VSILFILE *""'"); 
   }
   {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
     result = VSIFCloseL(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7454,7 +8453,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_VSIFSeekL(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   VSILFILE *arg1 = (VSILFILE *) 0 ;
   GIntBig arg2 ;
   int arg3 ;
@@ -7485,18 +8484,26 @@ SWIGINTERN PyObject *_wrap_VSIFSeekL(PyObject *SWIGUNUSEDPARM(self), PyObject *a
   } 
   arg3 = static_cast< int >(val3);
   {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
     result = (int)VSIFSeekL(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7504,7 +8511,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_VSIFTellL(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   VSILFILE *arg1 = (VSILFILE *) 0 ;
   int res1 ;
   PyObject * obj0 = 0 ;
@@ -7516,16 +8523,23 @@ SWIGINTERN PyObject *_wrap_VSIFTellL(PyObject *SWIGUNUSEDPARM(self), PyObject *a
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "VSIFTellL" "', argument " "1"" of type '" "VSILFILE *""'"); 
   }
   {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
     result = VSIFTellL(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     char szTmp[32];
@@ -7536,6 +8550,7 @@ SWIGINTERN PyObject *_wrap_VSIFTellL(PyObject *SWIGUNUSEDPARM(self), PyObject *a
     resultobj = PyInt_FromString(szTmp, NULL, 10);
 #endif
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7543,7 +8558,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_VSIFTruncateL(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   VSILFILE *arg1 = (VSILFILE *) 0 ;
   GIntBig arg2 ;
   int res1 ;
@@ -7565,18 +8580,26 @@ SWIGINTERN PyObject *_wrap_VSIFTruncateL(PyObject *SWIGUNUSEDPARM(self), PyObjec
     arg2 = (GIntBig)val;
   }
   {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
     result = (int)VSIFTruncateL(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7584,7 +8607,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_VSIFWriteL(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   int arg1 ;
   char *arg2 = (char *) 0 ;
   int arg3 ;
@@ -7657,29 +8680,37 @@ SWIGINTERN PyObject *_wrap_VSIFWriteL(PyObject *SWIGUNUSEDPARM(self), PyObject *
     SWIG_exception_fail(SWIG_ArgError(res5), "in method '" "VSIFWriteL" "', argument " "5"" of type '" "VSILFILE *""'"); 
   }
   {
+    if (!arg5) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
     result = (int)wrapper_VSIFWriteL(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
     /* %typemap(freearg) (int *nLen, char *pBuf ) */
-    if( alloc1 == SWIG_NEWOBJ ) {
+    if (ReturnSame(alloc1) == SWIG_NEWOBJ ) {
       delete[] arg2;
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
     /* %typemap(freearg) (int *nLen, char *pBuf ) */
-    if( alloc1 == SWIG_NEWOBJ ) {
+    if (ReturnSame(alloc1) == SWIG_NEWOBJ ) {
       delete[] arg2;
     }
   }
@@ -7687,8 +8718,76 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_ParseCommandLine(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  char *arg1 = (char *) 0 ;
+  int bToFree1 = 0 ;
+  PyObject * obj0 = 0 ;
+  char **result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:ParseCommandLine",&obj0)) SWIG_fail;
+  {
+    /* %typemap(in) (const char *utf8_path) */
+    arg1 = GDALPythonObjectToCStr( obj0, &bToFree1 );
+    if (arg1 == NULL)
+    {
+      PyErr_SetString( PyExc_RuntimeError, "not a string" );
+      SWIG_fail;
+    }
+  }
+  {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (char **)CSLParseCommandLine((char const *)arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  {
+    /* %typemap(out) char **CSL -> ( string ) */
+    char **stringarray = result;
+    if ( stringarray == NULL ) {
+      resultobj = Py_None;
+      Py_INCREF( resultobj );
+    }
+    else {
+      int len = CSLCount( stringarray );
+      resultobj = PyList_New( len );
+      for ( int i = 0; i < len; ++i ) {
+        PyObject *o = GDALPythonObjectFromCStr( stringarray[i] );
+        PyList_SetItem(resultobj, i, o );
+      }
+    }
+    CSLDestroy(result);
+  }
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
+  }
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_MajorObject_GetDescription(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -7706,14 +8805,17 @@ SWIGINTERN PyObject *_wrap_MajorObject_GetDescription(PyObject *SWIGUNUSEDPARM(s
       CPLErrorReset();
     }
     result = (char *)GDALMajorObjectShadow_GetDescription(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7721,7 +8823,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_MajorObject_SetDescription(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -7753,15 +8855,18 @@ SWIGINTERN PyObject *_wrap_MajorObject_SetDescription(PyObject *SWIGUNUSEDPARM(s
       CPLErrorReset();
     }
     GDALMajorObjectShadow_SetDescription(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -7770,7 +8875,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_MajorObject_GetMetadataDomainList(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -7788,12 +8893,14 @@ SWIGINTERN PyObject *_wrap_MajorObject_GetMetadataDomainList(PyObject *SWIGUNUSE
       CPLErrorReset();
     }
     result = (char **)GDALMajorObjectShadow_GetMetadataDomainList(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) char **CSL -> ( string ) */
@@ -7812,6 +8919,7 @@ SWIGINTERN PyObject *_wrap_MajorObject_GetMetadataDomainList(PyObject *SWIGUNUSE
     }
     CSLDestroy(result);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7819,7 +8927,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_MajorObject_GetMetadata_Dict(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
   char *arg2 = (char *) "" ;
   void *argp1 = 0 ;
@@ -7849,12 +8957,14 @@ SWIGINTERN PyObject *_wrap_MajorObject_GetMetadata_Dict(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     result = (char **)GDALMajorObjectShadow_GetMetadata_Dict(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) char **dict */
@@ -7881,6 +8991,7 @@ SWIGINTERN PyObject *_wrap_MajorObject_GetMetadata_Dict(PyObject *SWIGUNUSEDPARM
     }
   }
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -7889,7 +9000,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_MajorObject_GetMetadata_List(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
   char *arg2 = (char *) "" ;
   void *argp1 = 0 ;
@@ -7919,12 +9030,14 @@ SWIGINTERN PyObject *_wrap_MajorObject_GetMetadata_List(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     result = (char **)GDALMajorObjectShadow_GetMetadata_List(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) char **options -> ( string ) */
@@ -7943,6 +9056,7 @@ SWIGINTERN PyObject *_wrap_MajorObject_GetMetadata_List(PyObject *SWIGUNUSEDPARM
     }
   }
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -7951,7 +9065,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
   char **arg2 = (char **) 0 ;
   char *arg3 = (char *) "" ;
@@ -7975,8 +9089,12 @@ SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata__SWIG_0(PyObject *SWIGUNUSEDP
     /* %typemap(in) char **dict */
     arg2 = NULL;
     if ( PySequence_Check( obj1 ) ) {
-      int size = PySequence_Size(obj1);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj1);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj1,i);
         int bFreeStr;
         char* pszStr = GDALPythonObjectToCStr(pyObj, &bFreeStr);
@@ -7992,16 +9110,16 @@ SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata__SWIG_0(PyObject *SWIGUNUSEDP
     }
     else if ( PyMapping_Check( obj1 ) ) {
       /* We need to use the dictionary form. */
-      int size = PyMapping_Length( obj1 );
-      if ( size > 0 ) {
+      Py_ssize_t size = PyMapping_Length( obj1 );
+      if ( size > 0 && size == (int)size) {
         PyObject *item_list = PyMapping_Items( obj1 );
-        for( int i=0; i<size; i++ ) {
+        for( int i=0; i<(int)size; i++ ) {
           PyObject *it = PySequence_GetItem( item_list, i );
           
           PyObject *k, *v;
           if ( ! PyArg_ParseTuple( it, "OO", &k, &v ) ) {
             Py_DECREF(it);
-            PyErr_SetString(PyExc_TypeError,"dictionnaire must contain tuples of strings");
+            PyErr_SetString(PyExc_TypeError,"Dictionary must contain tuples of strings");
             SWIG_fail;
           }
           
@@ -8013,7 +9131,7 @@ SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata__SWIG_0(PyObject *SWIGUNUSEDP
             GDALPythonFreeCStr(pszK, bFreeK);
             GDALPythonFreeCStr(pszV, bFreeV);
             Py_DECREF(it);
-            PyErr_SetString(PyExc_TypeError,"dictionnaire must contain tuples of strings");
+            PyErr_SetString(PyExc_TypeError,"Dictionary must contain tuples of strings");
             SWIG_fail;
           }
           arg2 = CSLAddNameValue( arg2, pszK, pszV );
@@ -8041,13 +9159,15 @@ SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata__SWIG_0(PyObject *SWIGUNUSEDP
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALMajorObjectShadow_SetMetadata__SWIG_0(arg1,arg2,(char const *)arg3);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALMajorObjectShadow_SetMetadata__SWIG_0(arg1,arg2,(char const *)arg3));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
@@ -8055,16 +9175,7 @@ SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata__SWIG_0(PyObject *SWIGUNUSEDP
     CSLDestroy( arg2 );
   }
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-  {
-    /* %typemap(ret) CPLErr */
-    if ( bUseExceptions == 0 ) {
-      /* We're not using exceptions.  And no error has occurred */
-      if ( resultobj == 0 ) {
-        /* No other return values set so return ErrorCode */
-        resultobj = PyInt_FromLong(result);
-      }
-    }
-  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -8077,7 +9188,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   char *arg3 = (char *) "" ;
@@ -8116,27 +9227,20 @@ SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata__SWIG_1(PyObject *SWIGUNUSEDP
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALMajorObjectShadow_SetMetadata__SWIG_1(arg1,arg2,(char const *)arg3);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALMajorObjectShadow_SetMetadata__SWIG_1(arg1,arg2,(char const *)arg3));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-  {
-    /* %typemap(ret) CPLErr */
-    if ( bUseExceptions == 0 ) {
-      /* We're not using exceptions.  And no error has occurred */
-      if ( resultobj == 0 ) {
-        /* No other return values set so return ErrorCode */
-        resultobj = PyInt_FromLong(result);
-      }
-    }
-  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -8150,9 +9254,9 @@ SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata(PyObject *self, PyObject *arg
   PyObject *argv[4];
   int ii;
   
-  if (!PyTuple_Check(args)) SWIG_fail;
+  if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
   argc = (int)PyObject_Length(args);
-  for (ii = 0; (ii < argc) && (ii < 3); ii++) {
+  for (ii = 0; (ii < 3) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
   if ((argc >= 2) && (argc <= 3)) {
@@ -8202,16 +9306,16 @@ SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata(PyObject *self, PyObject *arg
   }
   
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'MajorObject_SetMetadata'.\n"
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'MajorObject_SetMetadata'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    SetMetadata(GDALMajorObjectShadow *,char **,char const *)\n"
-    "    SetMetadata(GDALMajorObjectShadow *,char *,char const *)\n");
-  return NULL;
+    "    GDALMajorObjectShadow::SetMetadata(char **,char const *)\n"
+    "    GDALMajorObjectShadow::SetMetadata(char *,char const *)\n");
+  return 0;
 }
 
 
 SWIGINTERN PyObject *_wrap_MajorObject_GetMetadataItem(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   char *arg3 = (char *) "" ;
@@ -8256,16 +9360,19 @@ SWIGINTERN PyObject *_wrap_MajorObject_GetMetadataItem(PyObject *SWIGUNUSEDPARM(
       CPLErrorReset();
     }
     result = (char *)GDALMajorObjectShadow_GetMetadataItem(arg1,(char const *)arg2,(char const *)arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -8275,7 +9382,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_MajorObject_SetMetadataItem(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   char *arg3 = (char *) 0 ;
@@ -8329,28 +9436,21 @@ SWIGINTERN PyObject *_wrap_MajorObject_SetMetadataItem(PyObject *SWIGUNUSEDPARM(
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALMajorObjectShadow_SetMetadataItem(arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALMajorObjectShadow_SetMetadataItem(arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
   if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
-  {
-    /* %typemap(ret) CPLErr */
-    if ( bUseExceptions == 0 ) {
-      /* We're not using exceptions.  And no error has occurred */
-      if ( resultobj == 0 ) {
-        /* No other return values set so return ErrorCode */
-        resultobj = PyInt_FromLong(result);
-      }
-    }
-  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -8368,7 +9468,7 @@ SWIGINTERN PyObject *MajorObject_swigregister(PyObject *SWIGUNUSEDPARM(self), Py
 }
 
 SWIGINTERN PyObject *_wrap_Driver_ShortName_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDriverShadow *arg1 = (GDALDriverShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -8386,14 +9486,17 @@ SWIGINTERN PyObject *_wrap_Driver_ShortName_get(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (char *)GDALDriverShadow_ShortName_get(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8401,7 +9504,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Driver_LongName_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDriverShadow *arg1 = (GDALDriverShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -8419,14 +9522,17 @@ SWIGINTERN PyObject *_wrap_Driver_LongName_get(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     result = (char *)GDALDriverShadow_LongName_get(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8434,7 +9540,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Driver_HelpTopic_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDriverShadow *arg1 = (GDALDriverShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -8452,14 +9558,17 @@ SWIGINTERN PyObject *_wrap_Driver_HelpTopic_get(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (char *)GDALDriverShadow_HelpTopic_get(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8467,7 +9576,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Driver_Create(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDriverShadow *arg1 = (GDALDriverShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   int arg3 ;
@@ -8550,8 +9659,12 @@ SWIGINTERN PyObject *_wrap_Driver_Create(PyObject *SWIGUNUSEDPARM(self), PyObjec
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj6);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj6);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj6,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -8593,12 +9706,14 @@ SWIGINTERN PyObject *_wrap_Driver_Create(PyObject *SWIGUNUSEDPARM(self), PyObjec
       CPLErrorReset();
     }
     result = (GDALDatasetShadow *)GDALDriverShadow_Create(arg1,(char const *)arg2,arg3,arg4,arg5,arg6,arg7);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_POINTER_OWN |  0 );
   {
@@ -8609,6 +9724,7 @@ SWIGINTERN PyObject *_wrap_Driver_Create(PyObject *SWIGUNUSEDPARM(self), PyObjec
     /* %typemap(freearg) char **options */
     CSLDestroy( arg7 );
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -8624,7 +9740,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Driver_CreateCopy(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDriverShadow *arg1 = (GDALDriverShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   GDALDatasetShadow *arg3 = (GDALDatasetShadow *) 0 ;
@@ -8698,8 +9814,12 @@ SWIGINTERN PyObject *_wrap_Driver_CreateCopy(PyObject *SWIGUNUSEDPARM(self), PyO
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj4);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj4);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj4,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -8737,16 +9857,16 @@ SWIGINTERN PyObject *_wrap_Driver_CreateCopy(PyObject *SWIGUNUSEDPARM(self), PyO
       /* callback_func typemap */
       if (obj5 && obj5 != Py_None ) {
         void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj5, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj5,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
         
         if ( cbfunction == GDALTermProgress ) {
           arg6 = GDALTermProgress;
         } else {
           if (!PyCallable_Check(obj5)) {
-            PyErr_SetString( PyExc_RuntimeError, 
+            PyErr_SetString( PyExc_RuntimeError,
               "Object given is not a Python function" );
             SWIG_fail;
           }
@@ -8779,12 +9899,14 @@ SWIGINTERN PyObject *_wrap_Driver_CreateCopy(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (GDALDatasetShadow *)GDALDriverShadow_CreateCopy(arg1,(char const *)arg2,arg3,arg4,arg5,arg6,arg7);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_POINTER_OWN |  0 );
   {
@@ -8801,6 +9923,7 @@ SWIGINTERN PyObject *_wrap_Driver_CreateCopy(PyObject *SWIGUNUSEDPARM(self), PyO
     CPLFree(psProgressInfo);
     
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -8822,7 +9945,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Driver_Delete(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDriverShadow *arg1 = (GDALDriverShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -8856,29 +9979,22 @@ SWIGINTERN PyObject *_wrap_Driver_Delete(PyObject *SWIGUNUSEDPARM(self), PyObjec
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALDriverShadow_Delete(arg1,(char const *)arg2);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALDriverShadow_Delete(arg1,(char const *)arg2));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
     /* %typemap(freearg) (const char *utf8_path) */
     GDALPythonFreeCStr(arg2, bToFree2);
   }
-  {
-    /* %typemap(ret) CPLErr */
-    if ( bUseExceptions == 0 ) {
-      /* We're not using exceptions.  And no error has occurred */
-      if ( resultobj == 0 ) {
-        /* No other return values set so return ErrorCode */
-        resultobj = PyInt_FromLong(result);
-      }
-    }
-  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -8890,7 +10006,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Driver_Rename(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDriverShadow *arg1 = (GDALDriverShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   char *arg3 = (char *) 0 ;
@@ -8937,27 +10053,20 @@ SWIGINTERN PyObject *_wrap_Driver_Rename(PyObject *SWIGUNUSEDPARM(self), PyObjec
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALDriverShadow_Rename(arg1,(char const *)arg2,(char const *)arg3);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALDriverShadow_Rename(arg1,(char const *)arg2,(char const *)arg3));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-  {
-    /* %typemap(ret) CPLErr */
-    if ( bUseExceptions == 0 ) {
-      /* We're not using exceptions.  And no error has occurred */
-      if ( resultobj == 0 ) {
-        /* No other return values set so return ErrorCode */
-        resultobj = PyInt_FromLong(result);
-      }
-    }
-  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -8967,7 +10076,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Driver_CopyFiles(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDriverShadow *arg1 = (GDALDriverShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   char *arg3 = (char *) 0 ;
@@ -9014,27 +10123,20 @@ SWIGINTERN PyObject *_wrap_Driver_CopyFiles(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALDriverShadow_CopyFiles(arg1,(char const *)arg2,(char const *)arg3);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALDriverShadow_CopyFiles(arg1,(char const *)arg2,(char const *)arg3));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-  {
-    /* %typemap(ret) CPLErr */
-    if ( bUseExceptions == 0 ) {
-      /* We're not using exceptions.  And no error has occurred */
-      if ( resultobj == 0 ) {
-        /* No other return values set so return ErrorCode */
-        resultobj = PyInt_FromLong(result);
-      }
-    }
-  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -9044,7 +10146,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Driver_Register(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDriverShadow *arg1 = (GDALDriverShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -9062,14 +10164,17 @@ SWIGINTERN PyObject *_wrap_Driver_Register(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     result = (int)GDALDriverShadow_Register(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9077,7 +10182,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Driver_Deregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDriverShadow *arg1 = (GDALDriverShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -9094,14 +10199,17 @@ SWIGINTERN PyObject *_wrap_Driver_Deregister(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     GDALDriverShadow_Deregister(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9116,7 +10224,7 @@ SWIGINTERN PyObject *Driver_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObjec
 }
 
 SWIGINTERN PyObject *_wrap_ColorEntry_c1_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALColorEntry *arg1 = (GDALColorEntry *) 0 ;
   short arg2 ;
   GDALColorEntry ce1 ;
@@ -9133,7 +10241,7 @@ SWIGINTERN PyObject *_wrap_ColorEntry_c1_set(PyObject *SWIGUNUSEDPARM(self), PyO
       PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
-    int size = PySequence_Size(obj0);
+    Py_ssize_t size = PySequence_Size(obj0);
     if ( size > 4 ) {
       PyErr_SetString(PyExc_TypeError, "ColorEntry sequence too long");
       SWIG_fail;
@@ -9155,6 +10263,7 @@ SWIGINTERN PyObject *_wrap_ColorEntry_c1_set(PyObject *SWIGUNUSEDPARM(self), PyO
   arg2 = static_cast< short >(val2);
   if (arg1) (arg1)->c1 = arg2;
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9162,7 +10271,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_ColorEntry_c1_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALColorEntry *arg1 = (GDALColorEntry *) 0 ;
   GDALColorEntry ce1 ;
   PyObject * obj0 = 0 ;
@@ -9176,7 +10285,7 @@ SWIGINTERN PyObject *_wrap_ColorEntry_c1_get(PyObject *SWIGUNUSEDPARM(self), PyO
       PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
-    int size = PySequence_Size(obj0);
+    Py_ssize_t size = PySequence_Size(obj0);
     if ( size > 4 ) {
       PyErr_SetString(PyExc_TypeError, "ColorEntry sequence too long");
       SWIG_fail;
@@ -9193,6 +10302,7 @@ SWIGINTERN PyObject *_wrap_ColorEntry_c1_get(PyObject *SWIGUNUSEDPARM(self), PyO
   }
   result = (short) ((arg1)->c1);
   resultobj = SWIG_From_short(static_cast< short >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9200,7 +10310,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_ColorEntry_c2_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALColorEntry *arg1 = (GDALColorEntry *) 0 ;
   short arg2 ;
   GDALColorEntry ce1 ;
@@ -9217,7 +10327,7 @@ SWIGINTERN PyObject *_wrap_ColorEntry_c2_set(PyObject *SWIGUNUSEDPARM(self), PyO
       PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
-    int size = PySequence_Size(obj0);
+    Py_ssize_t size = PySequence_Size(obj0);
     if ( size > 4 ) {
       PyErr_SetString(PyExc_TypeError, "ColorEntry sequence too long");
       SWIG_fail;
@@ -9239,6 +10349,7 @@ SWIGINTERN PyObject *_wrap_ColorEntry_c2_set(PyObject *SWIGUNUSEDPARM(self), PyO
   arg2 = static_cast< short >(val2);
   if (arg1) (arg1)->c2 = arg2;
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9246,7 +10357,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_ColorEntry_c2_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALColorEntry *arg1 = (GDALColorEntry *) 0 ;
   GDALColorEntry ce1 ;
   PyObject * obj0 = 0 ;
@@ -9260,7 +10371,7 @@ SWIGINTERN PyObject *_wrap_ColorEntry_c2_get(PyObject *SWIGUNUSEDPARM(self), PyO
       PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
-    int size = PySequence_Size(obj0);
+    Py_ssize_t size = PySequence_Size(obj0);
     if ( size > 4 ) {
       PyErr_SetString(PyExc_TypeError, "ColorEntry sequence too long");
       SWIG_fail;
@@ -9277,6 +10388,7 @@ SWIGINTERN PyObject *_wrap_ColorEntry_c2_get(PyObject *SWIGUNUSEDPARM(self), PyO
   }
   result = (short) ((arg1)->c2);
   resultobj = SWIG_From_short(static_cast< short >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9284,7 +10396,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_ColorEntry_c3_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALColorEntry *arg1 = (GDALColorEntry *) 0 ;
   short arg2 ;
   GDALColorEntry ce1 ;
@@ -9301,7 +10413,7 @@ SWIGINTERN PyObject *_wrap_ColorEntry_c3_set(PyObject *SWIGUNUSEDPARM(self), PyO
       PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
-    int size = PySequence_Size(obj0);
+    Py_ssize_t size = PySequence_Size(obj0);
     if ( size > 4 ) {
       PyErr_SetString(PyExc_TypeError, "ColorEntry sequence too long");
       SWIG_fail;
@@ -9323,6 +10435,7 @@ SWIGINTERN PyObject *_wrap_ColorEntry_c3_set(PyObject *SWIGUNUSEDPARM(self), PyO
   arg2 = static_cast< short >(val2);
   if (arg1) (arg1)->c3 = arg2;
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9330,7 +10443,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_ColorEntry_c3_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALColorEntry *arg1 = (GDALColorEntry *) 0 ;
   GDALColorEntry ce1 ;
   PyObject * obj0 = 0 ;
@@ -9344,7 +10457,7 @@ SWIGINTERN PyObject *_wrap_ColorEntry_c3_get(PyObject *SWIGUNUSEDPARM(self), PyO
       PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
-    int size = PySequence_Size(obj0);
+    Py_ssize_t size = PySequence_Size(obj0);
     if ( size > 4 ) {
       PyErr_SetString(PyExc_TypeError, "ColorEntry sequence too long");
       SWIG_fail;
@@ -9361,6 +10474,7 @@ SWIGINTERN PyObject *_wrap_ColorEntry_c3_get(PyObject *SWIGUNUSEDPARM(self), PyO
   }
   result = (short) ((arg1)->c3);
   resultobj = SWIG_From_short(static_cast< short >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9368,7 +10482,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_ColorEntry_c4_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALColorEntry *arg1 = (GDALColorEntry *) 0 ;
   short arg2 ;
   GDALColorEntry ce1 ;
@@ -9385,7 +10499,7 @@ SWIGINTERN PyObject *_wrap_ColorEntry_c4_set(PyObject *SWIGUNUSEDPARM(self), PyO
       PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
-    int size = PySequence_Size(obj0);
+    Py_ssize_t size = PySequence_Size(obj0);
     if ( size > 4 ) {
       PyErr_SetString(PyExc_TypeError, "ColorEntry sequence too long");
       SWIG_fail;
@@ -9407,6 +10521,7 @@ SWIGINTERN PyObject *_wrap_ColorEntry_c4_set(PyObject *SWIGUNUSEDPARM(self), PyO
   arg2 = static_cast< short >(val2);
   if (arg1) (arg1)->c4 = arg2;
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9414,7 +10529,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_ColorEntry_c4_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALColorEntry *arg1 = (GDALColorEntry *) 0 ;
   GDALColorEntry ce1 ;
   PyObject * obj0 = 0 ;
@@ -9428,7 +10543,7 @@ SWIGINTERN PyObject *_wrap_ColorEntry_c4_get(PyObject *SWIGUNUSEDPARM(self), PyO
       PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
-    int size = PySequence_Size(obj0);
+    Py_ssize_t size = PySequence_Size(obj0);
     if ( size > 4 ) {
       PyErr_SetString(PyExc_TypeError, "ColorEntry sequence too long");
       SWIG_fail;
@@ -9445,84 +10560,7 @@ SWIGINTERN PyObject *_wrap_ColorEntry_c4_get(PyObject *SWIGUNUSEDPARM(self), PyO
   }
   result = (short) ((arg1)->c4);
   resultobj = SWIG_From_short(static_cast< short >(result));
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_new_ColorEntry(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  GDALColorEntry *result = 0 ;
-  
-  if (!PyArg_ParseTuple(args,(char *)":new_ColorEntry")) SWIG_fail;
-  {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
-    }
-    result = (GDALColorEntry *)new GDALColorEntry();
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-      }
-    }
-  }
-  {
-    /* %typemap(out) GDALColorEntry* */
-    if ( result != NULL )
-    resultobj = Py_BuildValue( "(hhhh)", (*result).c1,(*result).c2,(*result).c3,(*result).c4);
-    else
-    resultobj = NULL;
-  }
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_delete_ColorEntry(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  GDALColorEntry *arg1 = (GDALColorEntry *) 0 ;
-  GDALColorEntry ce1 ;
-  PyObject * obj0 = 0 ;
-  
-  if (!PyArg_ParseTuple(args,(char *)"O:delete_ColorEntry",&obj0)) SWIG_fail;
-  {
-    /* %typemap(in) GDALColorEntry* */
-    ce1.c4 = 255;
-    if (! PySequence_Check(obj0) ) {
-      PyErr_SetString(PyExc_TypeError, "not a sequence");
-      SWIG_fail;
-    }
-    int size = PySequence_Size(obj0);
-    if ( size > 4 ) {
-      PyErr_SetString(PyExc_TypeError, "ColorEntry sequence too long");
-      SWIG_fail;
-    }
-    if ( size < 3 ) {
-      PyErr_SetString(PyExc_TypeError, "ColorEntry sequence too short");
-      SWIG_fail;
-    }
-    if ( !PyArg_ParseTuple( obj0,"hhh|h", &ce1.c1, &ce1.c2, &ce1.c3, &ce1.c4 ) ) {
-      PyErr_SetString(PyExc_TypeError, "Invalid values in ColorEntry sequence ");
-      SWIG_fail;
-    }
-    arg1 = &ce1;
-  }
-  {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
-    }
-    delete arg1;
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-      }
-    }
-  }
-  resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9537,7 +10575,7 @@ SWIGINTERN PyObject *ColorEntry_swigregister(PyObject *SWIGUNUSEDPARM(self), PyO
 }
 
 SWIGINTERN PyObject *_wrap_GCP_GCPX_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
   double arg2 ;
   void *argp1 = 0 ;
@@ -9563,14 +10601,17 @@ SWIGINTERN PyObject *_wrap_GCP_GCPX_set(PyObject *SWIGUNUSEDPARM(self), PyObject
       CPLErrorReset();
     }
     GDAL_GCP_GCPX_set(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9578,7 +10619,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GCP_GCPX_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -9596,14 +10637,17 @@ SWIGINTERN PyObject *_wrap_GCP_GCPX_get(PyObject *SWIGUNUSEDPARM(self), PyObject
       CPLErrorReset();
     }
     result = (double)GDAL_GCP_GCPX_get(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_double(static_cast< double >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9611,7 +10655,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GCP_GCPY_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
   double arg2 ;
   void *argp1 = 0 ;
@@ -9637,14 +10681,17 @@ SWIGINTERN PyObject *_wrap_GCP_GCPY_set(PyObject *SWIGUNUSEDPARM(self), PyObject
       CPLErrorReset();
     }
     GDAL_GCP_GCPY_set(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9652,7 +10699,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GCP_GCPY_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -9670,14 +10717,17 @@ SWIGINTERN PyObject *_wrap_GCP_GCPY_get(PyObject *SWIGUNUSEDPARM(self), PyObject
       CPLErrorReset();
     }
     result = (double)GDAL_GCP_GCPY_get(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_double(static_cast< double >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9685,7 +10735,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GCP_GCPZ_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
   double arg2 ;
   void *argp1 = 0 ;
@@ -9711,14 +10761,17 @@ SWIGINTERN PyObject *_wrap_GCP_GCPZ_set(PyObject *SWIGUNUSEDPARM(self), PyObject
       CPLErrorReset();
     }
     GDAL_GCP_GCPZ_set(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9726,7 +10779,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GCP_GCPZ_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -9744,14 +10797,17 @@ SWIGINTERN PyObject *_wrap_GCP_GCPZ_get(PyObject *SWIGUNUSEDPARM(self), PyObject
       CPLErrorReset();
     }
     result = (double)GDAL_GCP_GCPZ_get(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_double(static_cast< double >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9759,7 +10815,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GCP_GCPPixel_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
   double arg2 ;
   void *argp1 = 0 ;
@@ -9785,14 +10841,17 @@ SWIGINTERN PyObject *_wrap_GCP_GCPPixel_set(PyObject *SWIGUNUSEDPARM(self), PyOb
       CPLErrorReset();
     }
     GDAL_GCP_GCPPixel_set(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9800,7 +10859,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GCP_GCPPixel_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -9818,14 +10877,17 @@ SWIGINTERN PyObject *_wrap_GCP_GCPPixel_get(PyObject *SWIGUNUSEDPARM(self), PyOb
       CPLErrorReset();
     }
     result = (double)GDAL_GCP_GCPPixel_get(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_double(static_cast< double >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9833,7 +10895,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GCP_GCPLine_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
   double arg2 ;
   void *argp1 = 0 ;
@@ -9859,14 +10921,17 @@ SWIGINTERN PyObject *_wrap_GCP_GCPLine_set(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     GDAL_GCP_GCPLine_set(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9874,7 +10939,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GCP_GCPLine_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -9892,14 +10957,17 @@ SWIGINTERN PyObject *_wrap_GCP_GCPLine_get(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     result = (double)GDAL_GCP_GCPLine_get(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_double(static_cast< double >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9907,7 +10975,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GCP_Info_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -9933,19 +11001,19 @@ SWIGINTERN PyObject *_wrap_GCP_Info_set(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    
-    /* char* Info memberin typemap */
     GDAL_GCP_Info_set(arg1,arg2);
-    
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -9954,7 +11022,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GCP_Info_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -9972,14 +11040,17 @@ SWIGINTERN PyObject *_wrap_GCP_Info_get(PyObject *SWIGUNUSEDPARM(self), PyObject
       CPLErrorReset();
     }
     result = (char *)GDAL_GCP_Info_get(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9987,7 +11058,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GCP_Id_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -10013,19 +11084,19 @@ SWIGINTERN PyObject *_wrap_GCP_Id_set(PyObject *SWIGUNUSEDPARM(self), PyObject *
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    
-    /* char* Info memberin typemap */
     GDAL_GCP_Id_set(arg1,arg2);
-    
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -10034,7 +11105,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GCP_Id_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -10052,14 +11123,17 @@ SWIGINTERN PyObject *_wrap_GCP_Id_get(PyObject *SWIGUNUSEDPARM(self), PyObject *
       CPLErrorReset();
     }
     result = (char *)GDAL_GCP_Id_get(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -10067,7 +11141,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_new_GCP(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   double arg1 = (double) 0.0 ;
   double arg2 = (double) 0.0 ;
   double arg3 = (double) 0.0 ;
@@ -10155,16 +11229,19 @@ SWIGINTERN PyObject *_wrap_new_GCP(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
       CPLErrorReset();
     }
     result = (GDAL_GCP *)new_GDAL_GCP(arg1,arg2,arg3,arg4,arg5,(char const *)arg6,(char const *)arg7);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDAL_GCP, SWIG_POINTER_NEW |  0 );
   if (alloc6 == SWIG_NEWOBJ) delete[] buf6;
   if (alloc7 == SWIG_NEWOBJ) delete[] buf7;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc6 == SWIG_NEWOBJ) delete[] buf6;
@@ -10174,7 +11251,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_delete_GCP(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -10191,14 +11268,17 @@ SWIGINTERN PyObject *_wrap_delete_GCP(PyObject *SWIGUNUSEDPARM(self), PyObject *
       CPLErrorReset();
     }
     delete_GDAL_GCP(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -10213,7 +11293,7 @@ SWIGINTERN PyObject *GCP_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *
 }
 
 SWIGINTERN PyObject *_wrap_GDAL_GCP_GCPX_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -10236,14 +11316,17 @@ SWIGINTERN PyObject *_wrap_GDAL_GCP_GCPX_get(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (double)GDAL_GCP_GCPX_get(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_double(static_cast< double >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -10251,7 +11334,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GDAL_GCP_GCPX_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
   double arg2 ;
   void *argp1 = 0 ;
@@ -10282,14 +11365,17 @@ SWIGINTERN PyObject *_wrap_GDAL_GCP_GCPX_set(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     GDAL_GCP_GCPX_set(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -10297,7 +11383,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GDAL_GCP_GCPY_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -10320,14 +11406,17 @@ SWIGINTERN PyObject *_wrap_GDAL_GCP_GCPY_get(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (double)GDAL_GCP_GCPY_get(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_double(static_cast< double >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -10335,7 +11424,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GDAL_GCP_GCPY_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
   double arg2 ;
   void *argp1 = 0 ;
@@ -10366,14 +11455,17 @@ SWIGINTERN PyObject *_wrap_GDAL_GCP_GCPY_set(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     GDAL_GCP_GCPY_set(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -10381,7 +11473,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GDAL_GCP_GCPZ_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -10404,14 +11496,17 @@ SWIGINTERN PyObject *_wrap_GDAL_GCP_GCPZ_get(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (double)GDAL_GCP_GCPZ_get(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_double(static_cast< double >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -10419,7 +11514,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GDAL_GCP_GCPZ_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
   double arg2 ;
   void *argp1 = 0 ;
@@ -10450,14 +11545,17 @@ SWIGINTERN PyObject *_wrap_GDAL_GCP_GCPZ_set(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     GDAL_GCP_GCPZ_set(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -10465,7 +11563,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GDAL_GCP_GCPPixel_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -10488,14 +11586,17 @@ SWIGINTERN PyObject *_wrap_GDAL_GCP_GCPPixel_get(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (double)GDAL_GCP_GCPPixel_get(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_double(static_cast< double >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -10503,7 +11604,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GDAL_GCP_GCPPixel_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
   double arg2 ;
   void *argp1 = 0 ;
@@ -10534,14 +11635,17 @@ SWIGINTERN PyObject *_wrap_GDAL_GCP_GCPPixel_set(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     GDAL_GCP_GCPPixel_set(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -10549,7 +11653,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GDAL_GCP_GCPLine_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -10572,14 +11676,17 @@ SWIGINTERN PyObject *_wrap_GDAL_GCP_GCPLine_get(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (double)GDAL_GCP_GCPLine_get(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_double(static_cast< double >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -10587,7 +11694,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GDAL_GCP_GCPLine_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
   double arg2 ;
   void *argp1 = 0 ;
@@ -10618,14 +11725,17 @@ SWIGINTERN PyObject *_wrap_GDAL_GCP_GCPLine_set(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     GDAL_GCP_GCPLine_set(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -10633,7 +11743,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GDAL_GCP_Info_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -10656,14 +11766,17 @@ SWIGINTERN PyObject *_wrap_GDAL_GCP_Info_get(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (char *)GDAL_GCP_Info_get(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -10671,7 +11784,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GDAL_GCP_Info_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -10703,15 +11816,18 @@ SWIGINTERN PyObject *_wrap_GDAL_GCP_Info_set(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     GDAL_GCP_Info_set(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -10720,7 +11836,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GDAL_GCP_Id_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -10743,14 +11859,17 @@ SWIGINTERN PyObject *_wrap_GDAL_GCP_Id_get(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     result = (char *)GDAL_GCP_Id_get(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -10758,7 +11877,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GDAL_GCP_Id_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDAL_GCP *arg1 = (GDAL_GCP *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -10790,15 +11909,18 @@ SWIGINTERN PyObject *_wrap_GDAL_GCP_Id_set(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     GDAL_GCP_Id_set(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -10807,7 +11929,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GCPsToGeoTransform(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   int arg1 ;
   GDAL_GCP *arg2 = (GDAL_GCP *) 0 ;
   double *arg3 ;
@@ -10822,6 +11944,7 @@ SWIGINTERN PyObject *_wrap_GCPsToGeoTransform(PyObject *SWIGUNUSEDPARM(self), Py
   
   {
     /* %typemap(in,numinputs=0) (double argout3[ANY]) */
+    memset(argout3, 0, sizeof(argout3));
     arg3 = argout3;
   }
   if (!PyArg_ParseTuple(args,(char *)"O|O:GCPsToGeoTransform",&obj0,&obj1)) SWIG_fail;
@@ -10832,13 +11955,18 @@ SWIGINTERN PyObject *_wrap_GCPsToGeoTransform(PyObject *SWIGUNUSEDPARM(self), Py
       PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
-    arg1 = PySequence_Size(obj0);
+    Py_ssize_t size = PySequence_Size(obj0);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    arg1 = (int)size;
     tmpGCPList1 = (GDAL_GCP*) malloc(arg1*sizeof(GDAL_GCP));
     arg2 = tmpGCPList1;
     for( int i = 0; i<arg1; i++ ) {
       PyObject *o = PySequence_GetItem(obj0,i);
       GDAL_GCP *item = 0;
-      SWIG_ConvertPtr( o, (void**)&item, SWIGTYPE_p_GDAL_GCP, SWIG_POINTER_EXCEPTION | 0 );
+      CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( o, (void**)&item, SWIGTYPE_p_GDAL_GCP, SWIG_POINTER_EXCEPTION | 0 ));
       if ( ! item ) {
         Py_DECREF(o);
         SWIG_fail;
@@ -10859,13 +11987,15 @@ SWIGINTERN PyObject *_wrap_GCPsToGeoTransform(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = GDALGCPsToGeoTransform(arg1,(GDAL_GCP const *)arg2,arg3,arg4);
+    result = (RETURN_NONE)GDALGCPsToGeoTransform(arg1,(GDAL_GCP const *)arg2,arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   /*%typemap(out) IF_FALSE_RETURN_NONE */
   {
@@ -10891,6 +12021,7 @@ SWIGINTERN PyObject *_wrap_GCPsToGeoTransform(PyObject *SWIGUNUSEDPARM(self), Py
       Py_INCREF(resultobj);
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -10904,7 +12035,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_delete_VirtualMem(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   CPLVirtualMemShadow *arg1 = (CPLVirtualMemShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -10921,14 +12052,17 @@ SWIGINTERN PyObject *_wrap_delete_VirtualMem(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     delete_CPLVirtualMemShadow(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -10936,7 +12070,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_VirtualMem_GetAddr(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   CPLVirtualMemShadow *arg1 = (CPLVirtualMemShadow *) 0 ;
   void **arg2 = (void **) 0 ;
   size_t *arg3 = (size_t *) 0 ;
@@ -10968,16 +12102,18 @@ SWIGINTERN PyObject *_wrap_VirtualMem_GetAddr(PyObject *SWIGUNUSEDPARM(self), Py
       CPLErrorReset();
     }
     CPLVirtualMemShadow_GetAddr(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
-#if PY_VERSION_HEX >= 0x02070000 
+#if PY_VERSION_HEX >= 0x02070000
     /* %typemap(argout) (void** pptr, size_t* pnsize, GDALDataType* pdatatype, int* preadonly)*/
     Py_buffer *buf=(Py_buffer*)malloc(sizeof(Py_buffer));
     if (PyBuffer_FillInfo(buf,  obj0,  *(arg2), *(arg3), *(arg5), PyBUF_ND)) {
@@ -10985,50 +12121,51 @@ SWIGINTERN PyObject *_wrap_VirtualMem_GetAddr(PyObject *SWIGUNUSEDPARM(self), Py
     }
     if( *(arg4) == GDT_Byte )
     {
-      buf->format = "B";
+      buf->format = (char*) "B";
       buf->itemsize = 1;
     }
     else if( *(arg4) == GDT_Int16 )
     {
-      buf->format = "h";
+      buf->format = (char*) "h";
       buf->itemsize = 2;
     }
     else if( *(arg4) == GDT_UInt16 )
     {
-      buf->format = "H";
+      buf->format = (char*) "H";
       buf->itemsize = 2;
     }
     else if( *(arg4) == GDT_Int32 )
     {
-      buf->format = "i";
+      buf->format = (char*) "i";
       buf->itemsize = 4;
     }
     else if( *(arg4) == GDT_UInt32 )
     {
-      buf->format = "I";
+      buf->format = (char*) "I";
       buf->itemsize = 4;
     }
     else if( *(arg4) == GDT_Float32 )
     {
-      buf->format = "f";
+      buf->format = (char*) "f";
       buf->itemsize = 4;
     }
     else if( *(arg4) == GDT_Float64 )
     {
-      buf->format = "F";
+      buf->format = (char*) "F";
       buf->itemsize = 8;
     }
     else
     {
-      buf->format = "B";
+      buf->format = (char*) "B";
       buf->itemsize = 1;
     }
+    Py_DECREF(resultobj);
     resultobj = PyMemoryView_FromBuffer(buf);
 #else
     PyErr_SetString( PyExc_RuntimeError, "needs Python 2.7 or later" );
-    SWIG_fail;
 #endif
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11036,7 +12173,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_VirtualMem_Pin(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   CPLVirtualMemShadow *arg1 = (CPLVirtualMemShadow *) 0 ;
   size_t arg2 = (size_t) 0 ;
   size_t arg3 = (size_t) 0 ;
@@ -11086,14 +12223,17 @@ SWIGINTERN PyObject *_wrap_VirtualMem_Pin(PyObject *SWIGUNUSEDPARM(self), PyObje
       CPLErrorReset();
     }
     CPLVirtualMemShadow_Pin(arg1,arg2,arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11108,7 +12248,7 @@ SWIGINTERN PyObject *VirtualMem_swigregister(PyObject *SWIGUNUSEDPARM(self), PyO
 }
 
 SWIGINTERN PyObject *_wrap_delete_AsyncReader(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALAsyncReaderShadow *arg1 = (GDALAsyncReaderShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -11125,14 +12265,17 @@ SWIGINTERN PyObject *_wrap_delete_AsyncReader(PyObject *SWIGUNUSEDPARM(self), Py
       CPLErrorReset();
     }
     delete_GDALAsyncReaderShadow(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11140,7 +12283,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_AsyncReader_GetNextUpdatedRegion(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALAsyncReaderShadow *arg1 = (GDALAsyncReaderShadow *) 0 ;
   double arg2 ;
   int *arg3 = (int *) 0 ;
@@ -11183,38 +12326,41 @@ SWIGINTERN PyObject *_wrap_AsyncReader_GetNextUpdatedRegion(PyObject *SWIGUNUSED
       CPLErrorReset();
     }
     result = (GDALAsyncStatusType)GDALAsyncReaderShadow_GetNextUpdatedRegion(arg1,arg2,arg3,arg4,arg5,arg6);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
-  if (SWIG_IsTmpObj(res3)) {
+  if (ReturnSame(SWIG_IsTmpObj(res3))) {
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg3)));
   } else {
     int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_int, new_flags));
   }
-  if (SWIG_IsTmpObj(res4)) {
+  if (ReturnSame(SWIG_IsTmpObj(res4))) {
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4)));
   } else {
     int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags));
   }
-  if (SWIG_IsTmpObj(res5)) {
+  if (ReturnSame(SWIG_IsTmpObj(res5))) {
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg5)));
   } else {
     int new_flags = SWIG_IsNewObj(res5) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg5), SWIGTYPE_p_int, new_flags));
   }
-  if (SWIG_IsTmpObj(res6)) {
+  if (ReturnSame(SWIG_IsTmpObj(res6))) {
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg6)));
   } else {
     int new_flags = SWIG_IsNewObj(res6) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg6), SWIGTYPE_p_int, new_flags));
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11222,7 +12368,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_AsyncReader_GetBuffer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALAsyncReaderShadow *arg1 = (GDALAsyncReaderShadow *) 0 ;
   void **arg2 = (void **) 0 ;
   void *argp1 = 0 ;
@@ -11245,12 +12391,14 @@ SWIGINTERN PyObject *_wrap_AsyncReader_GetBuffer(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     GDALAsyncReaderShadow_GetBuffer(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
@@ -11266,6 +12414,7 @@ SWIGINTERN PyObject *_wrap_AsyncReader_GetBuffer(PyObject *SWIGUNUSEDPARM(self),
       Py_INCREF(resultobj);
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11273,7 +12422,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_AsyncReader_LockBuffer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALAsyncReaderShadow *arg1 = (GDALAsyncReaderShadow *) 0 ;
   double arg2 ;
   void *argp1 = 0 ;
@@ -11300,14 +12449,17 @@ SWIGINTERN PyObject *_wrap_AsyncReader_LockBuffer(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (int)GDALAsyncReaderShadow_LockBuffer(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11315,7 +12467,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_AsyncReader_UnlockBuffer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALAsyncReaderShadow *arg1 = (GDALAsyncReaderShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -11332,14 +12484,17 @@ SWIGINTERN PyObject *_wrap_AsyncReader_UnlockBuffer(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     GDALAsyncReaderShadow_UnlockBuffer(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11354,7 +12509,7 @@ SWIGINTERN PyObject *AsyncReader_swigregister(PyObject *SWIGUNUSEDPARM(self), Py
 }
 
 SWIGINTERN PyObject *_wrap_Dataset_RasterXSize_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -11372,14 +12527,17 @@ SWIGINTERN PyObject *_wrap_Dataset_RasterXSize_get(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     result = (int)GDALDatasetShadow_RasterXSize_get(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11387,7 +12545,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_RasterYSize_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -11405,14 +12563,17 @@ SWIGINTERN PyObject *_wrap_Dataset_RasterYSize_get(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     result = (int)GDALDatasetShadow_RasterYSize_get(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11420,7 +12581,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_RasterCount_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -11438,14 +12599,17 @@ SWIGINTERN PyObject *_wrap_Dataset_RasterCount_get(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     result = (int)GDALDatasetShadow_RasterCount_get(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11453,7 +12617,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_delete_Dataset(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -11470,14 +12634,17 @@ SWIGINTERN PyObject *_wrap_delete_Dataset(PyObject *SWIGUNUSEDPARM(self), PyObje
       CPLErrorReset();
     }
     delete_GDALDatasetShadow(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11485,7 +12652,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_GetDriver(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -11503,14 +12670,17 @@ SWIGINTERN PyObject *_wrap_Dataset_GetDriver(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (GDALDriverShadow *)GDALDatasetShadow_GetDriver(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDriverShadow, 0 |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11518,7 +12688,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_GetRasterBand(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -11545,14 +12715,17 @@ SWIGINTERN PyObject *_wrap_Dataset_GetRasterBand(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (GDALRasterBandShadow *)GDALDatasetShadow_GetRasterBand(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11560,7 +12733,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_GetProjection(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -11578,14 +12751,17 @@ SWIGINTERN PyObject *_wrap_Dataset_GetProjection(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (char *)GDALDatasetShadow_GetProjection(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11593,7 +12769,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_GetProjectionRef(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -11611,14 +12787,17 @@ SWIGINTERN PyObject *_wrap_Dataset_GetProjectionRef(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     result = (char *)GDALDatasetShadow_GetProjectionRef(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11626,7 +12805,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_SetProjection(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -11658,26 +12837,19 @@ SWIGINTERN PyObject *_wrap_Dataset_SetProjection(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALDatasetShadow_SetProjection(arg1,(char const *)arg2);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALDatasetShadow_SetProjection(arg1,(char const *)arg2));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-  {
-    /* %typemap(ret) CPLErr */
-    if ( bUseExceptions == 0 ) {
-      /* We're not using exceptions.  And no error has occurred */
-      if ( resultobj == 0 ) {
-        /* No other return values set so return ErrorCode */
-        resultobj = PyInt_FromLong(result);
-      }
-    }
-  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -11686,7 +12858,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_GetGeoTransform(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   double *arg2 ;
   int *arg3 = (int *) 0 ;
@@ -11733,12 +12905,14 @@ SWIGINTERN PyObject *_wrap_Dataset_GetGeoTransform(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     GDALDatasetShadow_GetGeoTransform(arg1,arg2,arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
@@ -11753,6 +12927,7 @@ SWIGINTERN PyObject *_wrap_Dataset_GetGeoTransform(PyObject *SWIGUNUSEDPARM(self
     }
     resultobj = t_output_helper(resultobj,r);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11760,7 +12935,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_SetGeoTransform(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   double *arg2 ;
   void *argp1 = 0 ;
@@ -11783,7 +12958,7 @@ SWIGINTERN PyObject *_wrap_Dataset_SetGeoTransform(PyObject *SWIGUNUSEDPARM(self
       PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
-    int seq_size = PySequence_Size(obj1);
+    Py_ssize_t seq_size = PySequence_Size(obj1);
     if ( seq_size != 6 ) {
       PyErr_SetString(PyExc_TypeError, "sequence must have length ##size");
       SWIG_fail;
@@ -11804,25 +12979,18 @@ SWIGINTERN PyObject *_wrap_Dataset_SetGeoTransform(PyObject *SWIGUNUSEDPARM(self
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALDatasetShadow_SetGeoTransform(arg1,arg2);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALDatasetShadow_SetGeoTransform(arg1,arg2));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
-  {
-    /* %typemap(ret) CPLErr */
-    if ( bUseExceptions == 0 ) {
-      /* We're not using exceptions.  And no error has occurred */
-      if ( resultobj == 0 ) {
-        /* No other return values set so return ErrorCode */
-        resultobj = PyInt_FromLong(result);
-      }
-    }
-  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11830,7 +12998,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_BuildOverviews(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   char *arg2 = (char *) "NEAREST" ;
   int arg3 = (int) 0 ;
@@ -11880,7 +13048,12 @@ SWIGINTERN PyObject *_wrap_Dataset_BuildOverviews(PyObject *SWIGUNUSEDPARM(self)
         PyErr_SetString(PyExc_TypeError, "not a sequence");
         SWIG_fail;
       }
-      arg3 = PySequence_Size(obj2);
+      Py_ssize_t size = PySequence_Size(obj2);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      arg3 = (int)size;
       arg4 = (int*) malloc(arg3*sizeof(int));
       for( int i = 0; i<arg3; i++ ) {
         PyObject *o = PySequence_GetItem(obj2,i);
@@ -11899,16 +13072,16 @@ SWIGINTERN PyObject *_wrap_Dataset_BuildOverviews(PyObject *SWIGUNUSEDPARM(self)
       /* callback_func typemap */
       if (obj3 && obj3 != Py_None ) {
         void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj3, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
         
         if ( cbfunction == GDALTermProgress ) {
           arg5 = GDALTermProgress;
         } else {
           if (!PyCallable_Check(obj3)) {
-            PyErr_SetString( PyExc_RuntimeError, 
+            PyErr_SetString( PyExc_RuntimeError,
               "Object given is not a Python function" );
             SWIG_fail;
           }
@@ -11931,12 +13104,14 @@ SWIGINTERN PyObject *_wrap_Dataset_BuildOverviews(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (int)GDALDatasetShadow_BuildOverviews(arg1,(char const *)arg2,arg3,arg4,arg5,arg6);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -11952,6 +13127,7 @@ SWIGINTERN PyObject *_wrap_Dataset_BuildOverviews(PyObject *SWIGUNUSEDPARM(self)
     CPLFree(psProgressInfo);
     
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -11972,7 +13148,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_GetGCPCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -11990,14 +13166,17 @@ SWIGINTERN PyObject *_wrap_Dataset_GetGCPCount(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     result = (int)GDALDatasetShadow_GetGCPCount(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -12005,7 +13184,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_GetGCPProjection(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -12023,14 +13202,17 @@ SWIGINTERN PyObject *_wrap_Dataset_GetGCPProjection(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     result = (char *)GDALDatasetShadow_GetGCPProjection(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -12038,7 +13220,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_GetGCPs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   int *arg2 = (int *) 0 ;
   GDAL_GCP **arg3 = (GDAL_GCP **) 0 ;
@@ -12064,12 +13246,14 @@ SWIGINTERN PyObject *_wrap_Dataset_GetGCPs(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     GDALDatasetShadow_GetGCPs(arg1,arg2,(GDAL_GCP const **)arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
@@ -12084,12 +13268,13 @@ SWIGINTERN PyObject *_wrap_Dataset_GetGCPs(PyObject *SWIGUNUSEDPARM(self), PyObj
         (*arg3)[i].pszInfo,
         (*arg3)[i].pszId );
       
-      PyTuple_SetItem(dict, i, 
+      PyTuple_SetItem(dict, i,
         SWIG_NewPointerObj((void*)o,SWIGTYPE_p_GDAL_GCP,1) );
     }
     Py_DECREF(resultobj);
     resultobj = dict;
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -12097,7 +13282,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_SetGCPs(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   int arg2 ;
   GDAL_GCP *arg3 = (GDAL_GCP *) 0 ;
@@ -12126,13 +13311,18 @@ SWIGINTERN PyObject *_wrap_Dataset_SetGCPs(PyObject *SWIGUNUSEDPARM(self), PyObj
       PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
-    arg2 = PySequence_Size(obj1);
+    Py_ssize_t size = PySequence_Size(obj1);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    arg2 = (int)size;
     tmpGCPList2 = (GDAL_GCP*) malloc(arg2*sizeof(GDAL_GCP));
     arg3 = tmpGCPList2;
     for( int i = 0; i<arg2; i++ ) {
       PyObject *o = PySequence_GetItem(obj1,i);
       GDAL_GCP *item = 0;
-      SWIG_ConvertPtr( o, (void**)&item, SWIGTYPE_p_GDAL_GCP, SWIG_POINTER_EXCEPTION | 0 );
+      CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( o, (void**)&item, SWIGTYPE_p_GDAL_GCP, SWIG_POINTER_EXCEPTION | 0 ));
       if ( ! item ) {
         Py_DECREF(o);
         SWIG_fail;
@@ -12151,13 +13341,15 @@ SWIGINTERN PyObject *_wrap_Dataset_SetGCPs(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALDatasetShadow_SetGCPs(arg1,arg2,(GDAL_GCP const *)arg3,(char const *)arg4);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALDatasetShadow_SetGCPs(arg1,arg2,(GDAL_GCP const *)arg3,(char const *)arg4));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
@@ -12167,16 +13359,7 @@ SWIGINTERN PyObject *_wrap_Dataset_SetGCPs(PyObject *SWIGUNUSEDPARM(self), PyObj
     }
   }
   if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
-  {
-    /* %typemap(ret) CPLErr */
-    if ( bUseExceptions == 0 ) {
-      /* We're not using exceptions.  And no error has occurred */
-      if ( resultobj == 0 ) {
-        /* No other return values set so return ErrorCode */
-        resultobj = PyInt_FromLong(result);
-      }
-    }
-  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -12191,7 +13374,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_FlushCache(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -12208,14 +13391,17 @@ SWIGINTERN PyObject *_wrap_Dataset_FlushCache(PyObject *SWIGUNUSEDPARM(self), Py
       CPLErrorReset();
     }
     GDALDatasetShadow_FlushCache(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -12223,7 +13409,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_AddBand(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   GDALDataType arg2 = (GDALDataType) GDT_Byte ;
   char **arg3 = (char **) 0 ;
@@ -12265,8 +13451,12 @@ SWIGINTERN PyObject *_wrap_Dataset_AddBand(PyObject *SWIGUNUSEDPARM(self), PyObj
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj2);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj2);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj2,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -12302,29 +13492,22 @@ SWIGINTERN PyObject *_wrap_Dataset_AddBand(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALDatasetShadow_AddBand(arg1,arg2,arg3);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALDatasetShadow_AddBand(arg1,arg2,arg3));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
     /* %typemap(freearg) char **options */
     CSLDestroy( arg3 );
   }
-  {
-    /* %typemap(ret) CPLErr */
-    if ( bUseExceptions == 0 ) {
-      /* We're not using exceptions.  And no error has occurred */
-      if ( resultobj == 0 ) {
-        /* No other return values set so return ErrorCode */
-        resultobj = PyInt_FromLong(result);
-      }
-    }
-  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -12336,7 +13519,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_CreateMaskBand(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -12362,25 +13545,18 @@ SWIGINTERN PyObject *_wrap_Dataset_CreateMaskBand(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALDatasetShadow_CreateMaskBand(arg1,arg2);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALDatasetShadow_CreateMaskBand(arg1,arg2));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
-  {
-    /* %typemap(ret) CPLErr */
-    if ( bUseExceptions == 0 ) {
-      /* We're not using exceptions.  And no error has occurred */
-      if ( resultobj == 0 ) {
-        /* No other return values set so return ErrorCode */
-        resultobj = PyInt_FromLong(result);
-      }
-    }
-  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -12388,7 +13564,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_GetFileList(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -12406,12 +13582,14 @@ SWIGINTERN PyObject *_wrap_Dataset_GetFileList(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     result = (char **)GDALDatasetShadow_GetFileList(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) char **CSL -> ( string ) */
@@ -12430,6 +13608,7 @@ SWIGINTERN PyObject *_wrap_Dataset_GetFileList(PyObject *SWIGUNUSEDPARM(self), P
     }
     CSLDestroy(result);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -12437,7 +13616,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_WriteRaster(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   int arg2 ;
   int arg3 ;
@@ -12450,9 +13629,9 @@ SWIGINTERN PyObject *_wrap_Dataset_WriteRaster(PyObject *SWIGUNUSEDPARM(self), P
   GDALDataType *arg10 = (GDALDataType *) 0 ;
   int arg11 = (int) 0 ;
   int *arg12 = (int *) 0 ;
-  int *arg13 = (int *) 0 ;
-  int *arg14 = (int *) 0 ;
-  int *arg15 = (int *) 0 ;
+  GIntBig *arg13 = (GIntBig *) 0 ;
+  GIntBig *arg14 = (GIntBig *) 0 ;
+  GIntBig *arg15 = (GIntBig *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   int val2 ;
@@ -12467,9 +13646,9 @@ SWIGINTERN PyObject *_wrap_Dataset_WriteRaster(PyObject *SWIGUNUSEDPARM(self), P
   int val8 ;
   int val9 ;
   int val10 ;
-  int val13 ;
-  int val14 ;
-  int val15 ;
+  GIntBig val13 ;
+  GIntBig val14 ;
+  GIntBig val15 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   PyObject * obj2 = 0 ;
@@ -12606,7 +13785,12 @@ SWIGINTERN PyObject *_wrap_Dataset_WriteRaster(PyObject *SWIGUNUSEDPARM(self), P
         PyErr_SetString(PyExc_TypeError, "not a sequence");
         SWIG_fail;
       }
-      arg11 = PySequence_Size(obj9);
+      Py_ssize_t size = PySequence_Size(obj9);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      arg11 = (int)size;
       arg12 = (int*) malloc(arg11*sizeof(int));
       for( int i = 0; i<arg11; i++ ) {
         PyObject *o = PySequence_GetItem(obj9,i);
@@ -12621,12 +13805,12 @@ SWIGINTERN PyObject *_wrap_Dataset_WriteRaster(PyObject *SWIGUNUSEDPARM(self), P
   }
   if (obj10) {
     {
-      /* %typemap(in) (int *optional_##int) */
+      /* %typemap(in) (GIntBig *optional_##GIntBig) */
       if ( obj10 == Py_None ) {
         arg13 = 0;
       }
-      else if ( PyArg_Parse( obj10,"i" ,&val13 ) ) {
-        arg13 = (int *) &val13;
+      else if ( PyArg_Parse( obj10,"L" ,&val13 ) ) {
+        arg13 = (GIntBig *) &val13;
       }
       else {
         PyErr_SetString( PyExc_TypeError, "Invalid Parameter" );
@@ -12636,12 +13820,12 @@ SWIGINTERN PyObject *_wrap_Dataset_WriteRaster(PyObject *SWIGUNUSEDPARM(self), P
   }
   if (obj11) {
     {
-      /* %typemap(in) (int *optional_##int) */
+      /* %typemap(in) (GIntBig *optional_##GIntBig) */
       if ( obj11 == Py_None ) {
         arg14 = 0;
       }
-      else if ( PyArg_Parse( obj11,"i" ,&val14 ) ) {
-        arg14 = (int *) &val14;
+      else if ( PyArg_Parse( obj11,"L" ,&val14 ) ) {
+        arg14 = (GIntBig *) &val14;
       }
       else {
         PyErr_SetString( PyExc_TypeError, "Invalid Parameter" );
@@ -12651,12 +13835,12 @@ SWIGINTERN PyObject *_wrap_Dataset_WriteRaster(PyObject *SWIGUNUSEDPARM(self), P
   }
   if (obj12) {
     {
-      /* %typemap(in) (int *optional_##int) */
+      /* %typemap(in) (GIntBig *optional_##GIntBig) */
       if ( obj12 == Py_None ) {
         arg15 = 0;
       }
-      else if ( PyArg_Parse( obj12,"i" ,&val15 ) ) {
-        arg15 = (int *) &val15;
+      else if ( PyArg_Parse( obj12,"L" ,&val15 ) ) {
+        arg15 = (GIntBig *) &val15;
       }
       else {
         PyErr_SetString( PyExc_TypeError, "Invalid Parameter" );
@@ -12668,18 +13852,20 @@ SWIGINTERN PyObject *_wrap_Dataset_WriteRaster(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALDatasetShadow_WriteRaster(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12,arg13,arg14,arg15);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALDatasetShadow_WriteRaster(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12,arg13,arg14,arg15));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
     /* %typemap(freearg) (GIntBig *nLen, char *pBuf ) */
-    if( alloc6 == SWIG_NEWOBJ ) {
+    if (ReturnSame(alloc6) == SWIG_NEWOBJ ) {
       delete[] arg7;
     }
   }
@@ -12689,21 +13875,12 @@ SWIGINTERN PyObject *_wrap_Dataset_WriteRaster(PyObject *SWIGUNUSEDPARM(self), P
       free((void*) arg12);
     }
   }
-  {
-    /* %typemap(ret) CPLErr */
-    if ( bUseExceptions == 0 ) {
-      /* We're not using exceptions.  And no error has occurred */
-      if ( resultobj == 0 ) {
-        /* No other return values set so return ErrorCode */
-        resultobj = PyInt_FromLong(result);
-      }
-    }
-  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
     /* %typemap(freearg) (GIntBig *nLen, char *pBuf ) */
-    if( alloc6 == SWIG_NEWOBJ ) {
+    if (ReturnSame(alloc6) == SWIG_NEWOBJ ) {
       delete[] arg7;
     }
   }
@@ -12718,7 +13895,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_BeginAsyncReader(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   int arg2 ;
   int arg3 ;
@@ -12858,7 +14035,12 @@ SWIGINTERN PyObject *_wrap_Dataset_BeginAsyncReader(PyObject *SWIGUNUSEDPARM(sel
         PyErr_SetString(PyExc_TypeError, "not a sequence");
         SWIG_fail;
       }
-      arg12 = PySequence_Size(obj9);
+      Py_ssize_t size = PySequence_Size(obj9);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      arg12 = (int)size;
       arg13 = (int*) malloc(arg12*sizeof(int));
       for( int i = 0; i<arg12; i++ ) {
         PyObject *o = PySequence_GetItem(obj9,i);
@@ -12905,8 +14087,12 @@ SWIGINTERN PyObject *_wrap_Dataset_BeginAsyncReader(PyObject *SWIGUNUSEDPARM(sel
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj13);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj13);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj13,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -12943,12 +14129,14 @@ SWIGINTERN PyObject *_wrap_Dataset_BeginAsyncReader(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     result = (GDALAsyncReaderShadow *)GDALDatasetShadow_BeginAsyncReader(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12,arg13,arg14,arg15,arg16,arg17);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALAsyncReaderShadow, SWIG_POINTER_OWN |  0 );
   {
@@ -12961,6 +14149,7 @@ SWIGINTERN PyObject *_wrap_Dataset_BeginAsyncReader(PyObject *SWIGUNUSEDPARM(sel
     /* %typemap(freearg) char **options */
     CSLDestroy( arg17 );
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -12978,7 +14167,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_EndAsyncReader(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   GDALAsyncReaderShadow *arg2 = (GDALAsyncReaderShadow *) 0 ;
   void *argp1 = 0 ;
@@ -13004,14 +14193,17 @@ SWIGINTERN PyObject *_wrap_Dataset_EndAsyncReader(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     GDALDatasetShadow_EndAsyncReader(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -13019,7 +14211,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_GetVirtualMem(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   GDALRWFlag arg2 ;
   int arg3 ;
@@ -13131,7 +14323,12 @@ SWIGINTERN PyObject *_wrap_Dataset_GetVirtualMem(PyObject *SWIGUNUSEDPARM(self),
       PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
-    arg10 = PySequence_Size(obj9);
+    Py_ssize_t size = PySequence_Size(obj9);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    arg10 = (int)size;
     arg11 = (int*) malloc(arg10*sizeof(int));
     for( int i = 0; i<arg10; i++ ) {
       PyObject *o = PySequence_GetItem(obj9,i);
@@ -13171,8 +14368,12 @@ SWIGINTERN PyObject *_wrap_Dataset_GetVirtualMem(PyObject *SWIGUNUSEDPARM(self),
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj13);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj13);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj13,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -13209,12 +14410,14 @@ SWIGINTERN PyObject *_wrap_Dataset_GetVirtualMem(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (CPLVirtualMemShadow *)GDALDatasetShadow_GetVirtualMem(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12,arg13,arg14,arg15);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_CPLVirtualMemShadow, SWIG_POINTER_OWN |  0 );
   {
@@ -13227,6 +14430,7 @@ SWIGINTERN PyObject *_wrap_Dataset_GetVirtualMem(PyObject *SWIGUNUSEDPARM(self),
     /* %typemap(freearg) char **options */
     CSLDestroy( arg15 );
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -13244,7 +14448,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_GetTiledVirtualMem(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   GDALRWFlag arg2 ;
   int arg3 ;
@@ -13352,7 +14556,12 @@ SWIGINTERN PyObject *_wrap_Dataset_GetTiledVirtualMem(PyObject *SWIGUNUSEDPARM(s
       PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
-    arg10 = PySequence_Size(obj9);
+    Py_ssize_t size = PySequence_Size(obj9);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    arg10 = (int)size;
     arg11 = (int*) malloc(arg10*sizeof(int));
     for( int i = 0; i<arg10; i++ ) {
       PyObject *o = PySequence_GetItem(obj9,i);
@@ -13387,8 +14596,12 @@ SWIGINTERN PyObject *_wrap_Dataset_GetTiledVirtualMem(PyObject *SWIGUNUSEDPARM(s
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj12);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj12);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj12,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -13425,12 +14638,14 @@ SWIGINTERN PyObject *_wrap_Dataset_GetTiledVirtualMem(PyObject *SWIGUNUSEDPARM(s
       CPLErrorReset();
     }
     result = (CPLVirtualMemShadow *)GDALDatasetShadow_GetTiledVirtualMem(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12,arg13,arg14);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_CPLVirtualMemShadow, SWIG_POINTER_OWN |  0 );
   {
@@ -13443,6 +14658,7 @@ SWIGINTERN PyObject *_wrap_Dataset_GetTiledVirtualMem(PyObject *SWIGUNUSEDPARM(s
     /* %typemap(freearg) char **options */
     CSLDestroy( arg14 );
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -13460,7 +14676,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_CreateLayer(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   OSRSpatialReferenceShadow *arg3 = (OSRSpatialReferenceShadow *) NULL ;
@@ -13523,8 +14739,12 @@ SWIGINTERN PyObject *_wrap_Dataset_CreateLayer(PyObject *SWIGUNUSEDPARM(self), P
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj4);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj4);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj4,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -13566,12 +14786,14 @@ SWIGINTERN PyObject *_wrap_Dataset_CreateLayer(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     result = (OGRLayerShadow *)GDALDatasetShadow_CreateLayer(arg1,(char const *)arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -13579,6 +14801,7 @@ SWIGINTERN PyObject *_wrap_Dataset_CreateLayer(PyObject *SWIGUNUSEDPARM(self), P
     /* %typemap(freearg) char **options */
     CSLDestroy( arg5 );
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -13591,7 +14814,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_CopyLayer(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
   char *arg3 = (char *) 0 ;
@@ -13641,8 +14864,12 @@ SWIGINTERN PyObject *_wrap_Dataset_CopyLayer(PyObject *SWIGUNUSEDPARM(self), PyO
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj3);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj3);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj3,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -13684,12 +14911,14 @@ SWIGINTERN PyObject *_wrap_Dataset_CopyLayer(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (OGRLayerShadow *)GDALDatasetShadow_CopyLayer(arg1,arg2,(char const *)arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
@@ -13697,6 +14926,7 @@ SWIGINTERN PyObject *_wrap_Dataset_CopyLayer(PyObject *SWIGUNUSEDPARM(self), PyO
     /* %typemap(freearg) char **options */
     CSLDestroy( arg4 );
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
@@ -13709,7 +14939,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_DeleteLayer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -13736,12 +14966,14 @@ SWIGINTERN PyObject *_wrap_Dataset_DeleteLayer(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     result = (OGRErr)GDALDatasetShadow_DeleteLayer(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -13752,14 +14984,11 @@ SWIGINTERN PyObject *_wrap_Dataset_DeleteLayer(PyObject *SWIGUNUSEDPARM(self), P
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -13767,7 +14996,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_GetLayerCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -13785,14 +15014,17 @@ SWIGINTERN PyObject *_wrap_Dataset_GetLayerCount(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (int)GDALDatasetShadow_GetLayerCount(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -13800,7 +15032,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_GetLayerByIndex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   int arg2 = (int) 0 ;
   void *argp1 = 0 ;
@@ -13829,14 +15061,17 @@ SWIGINTERN PyObject *_wrap_Dataset_GetLayerByIndex(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     result = (OGRLayerShadow *)GDALDatasetShadow_GetLayerByIndex(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -13844,7 +15079,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_GetLayerByName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -13872,15 +15107,18 @@ SWIGINTERN PyObject *_wrap_Dataset_GetLayerByName(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (OGRLayerShadow *)GDALDatasetShadow_GetLayerByName(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -13889,7 +15127,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_TestCapability(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -13917,15 +15155,18 @@ SWIGINTERN PyObject *_wrap_Dataset_TestCapability(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (bool)GDALDatasetShadow_TestCapability(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_bool(static_cast< bool >(result));
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -13934,7 +15175,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_ExecuteSQL(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   OGRGeometryShadow *arg3 = (OGRGeometryShadow *) NULL ;
@@ -13993,16 +15234,19 @@ SWIGINTERN PyObject *_wrap_Dataset_ExecuteSQL(PyObject *SWIGUNUSEDPARM(self), Py
       CPLErrorReset();
     }
     result = (OGRLayerShadow *)GDALDatasetShadow_ExecuteSQL(arg1,(char const *)arg2,arg3,(char const *)arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -14012,7 +15256,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_ReleaseResultSet(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
   void *argp1 = 0 ;
@@ -14036,14 +15280,17 @@ SWIGINTERN PyObject *_wrap_Dataset_ReleaseResultSet(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     GDALDatasetShadow_ReleaseResultSet(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -14051,7 +15298,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_GetStyleTable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -14069,14 +15316,17 @@ SWIGINTERN PyObject *_wrap_Dataset_GetStyleTable(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (OGRStyleTableShadow *)GDALDatasetShadow_GetStyleTable(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -14084,7 +15334,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_SetStyleTable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   OGRStyleTableShadow *arg2 = (OGRStyleTableShadow *) 0 ;
   void *argp1 = 0 ;
@@ -14110,14 +15360,17 @@ SWIGINTERN PyObject *_wrap_Dataset_SetStyleTable(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     GDALDatasetShadow_SetStyleTable(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -14125,7 +15378,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_StartTransaction(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   int arg2 = (int) FALSE ;
   void *argp1 = 0 ;
@@ -14157,12 +15410,14 @@ SWIGINTERN PyObject *_wrap_Dataset_StartTransaction(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     result = (OGRErr)GDALDatasetShadow_StartTransaction(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -14173,14 +15428,11 @@ SWIGINTERN PyObject *_wrap_Dataset_StartTransaction(PyObject *SWIGUNUSEDPARM(sel
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -14188,7 +15440,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_CommitTransaction(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -14206,12 +15458,14 @@ SWIGINTERN PyObject *_wrap_Dataset_CommitTransaction(PyObject *SWIGUNUSEDPARM(se
       CPLErrorReset();
     }
     result = (OGRErr)GDALDatasetShadow_CommitTransaction(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -14222,14 +15476,11 @@ SWIGINTERN PyObject *_wrap_Dataset_CommitTransaction(PyObject *SWIGUNUSEDPARM(se
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -14237,7 +15488,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_RollbackTransaction(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -14255,12 +15506,14 @@ SWIGINTERN PyObject *_wrap_Dataset_RollbackTransaction(PyObject *SWIGUNUSEDPARM(
       CPLErrorReset();
     }
     result = (OGRErr)GDALDatasetShadow_RollbackTransaction(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -14271,14 +15524,11 @@ SWIGINTERN PyObject *_wrap_Dataset_RollbackTransaction(PyObject *SWIGUNUSEDPARM(
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -14286,7 +15536,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Dataset_ReadRaster1(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   int arg2 ;
   int arg3 ;
@@ -14433,7 +15683,12 @@ SWIGINTERN PyObject *_wrap_Dataset_ReadRaster1(PyObject *SWIGUNUSEDPARM(self), P
         PyErr_SetString(PyExc_TypeError, "not a sequence");
         SWIG_fail;
       }
-      arg10 = PySequence_Size(obj8);
+      Py_ssize_t size = PySequence_Size(obj8);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      arg10 = (int)size;
       arg11 = (int*) malloc(arg10*sizeof(int));
       for( int i = 0; i<arg10; i++ ) {
         PyObject *o = PySequence_GetItem(obj8,i);
@@ -14504,16 +15759,16 @@ SWIGINTERN PyObject *_wrap_Dataset_ReadRaster1(PyObject *SWIGUNUSEDPARM(self), P
       /* callback_func typemap */
       if (obj13 && obj13 != Py_None ) {
         void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj13, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj13,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
         
         if ( cbfunction == GDALTermProgress ) {
           arg16 = GDALTermProgress;
         } else {
           if (!PyCallable_Check(obj13)) {
-            PyErr_SetString( PyExc_RuntimeError, 
+            PyErr_SetString( PyExc_RuntimeError,
               "Object given is not a Python function" );
             SWIG_fail;
           }
@@ -14535,13 +15790,15 @@ SWIGINTERN PyObject *_wrap_Dataset_ReadRaster1(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALDatasetShadow_ReadRaster1(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12,arg13,arg14,arg15,arg16,arg17);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALDatasetShadow_ReadRaster1(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12,arg13,arg14,arg15,arg16,arg17));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
@@ -14569,16 +15826,7 @@ SWIGINTERN PyObject *_wrap_Dataset_ReadRaster1(PyObject *SWIGUNUSEDPARM(self), P
     CPLFree(psProgressInfo);
     
   }
-  {
-    /* %typemap(ret) CPLErr */
-    if ( bUseExceptions == 0 ) {
-      /* We're not using exceptions.  And no error has occurred */
-      if ( resultobj == 0 ) {
-        /* No other return values set so return ErrorCode */
-        resultobj = PyInt_FromLong(result);
-      }
-    }
-  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -14605,7 +15853,7 @@ SWIGINTERN PyObject *Dataset_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObje
 }
 
 SWIGINTERN PyObject *_wrap_Band_XSize_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -14623,14 +15871,17 @@ SWIGINTERN PyObject *_wrap_Band_XSize_get(PyObject *SWIGUNUSEDPARM(self), PyObje
       CPLErrorReset();
     }
     result = (int)GDALRasterBandShadow_XSize_get(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -14638,7 +15889,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_YSize_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -14656,14 +15907,17 @@ SWIGINTERN PyObject *_wrap_Band_YSize_get(PyObject *SWIGUNUSEDPARM(self), PyObje
       CPLErrorReset();
     }
     result = (int)GDALRasterBandShadow_YSize_get(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -14671,7 +15925,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_DataType_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -14689,14 +15943,17 @@ SWIGINTERN PyObject *_wrap_Band_DataType_get(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (GDALDataType)GDALRasterBandShadow_DataType_get(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -14704,7 +15961,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_GetDataset(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -14722,14 +15979,17 @@ SWIGINTERN PyObject *_wrap_Band_GetDataset(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     result = (GDALDatasetShadow *)GDALRasterBandShadow_GetDataset(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -14737,7 +15997,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_GetBand(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -14755,14 +16015,17 @@ SWIGINTERN PyObject *_wrap_Band_GetBand(PyObject *SWIGUNUSEDPARM(self), PyObject
       CPLErrorReset();
     }
     result = (int)GDALRasterBandShadow_GetBand(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -14770,7 +16033,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_GetBlockSize(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   int *arg2 = (int *) 0 ;
   int *arg3 = (int *) 0 ;
@@ -14795,26 +16058,29 @@ SWIGINTERN PyObject *_wrap_Band_GetBlockSize(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     GDALRasterBandShadow_GetBlockSize(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
-  if (SWIG_IsTmpObj(res2)) {
+  if (ReturnSame(SWIG_IsTmpObj(res2))) {
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg2)));
   } else {
     int new_flags = SWIG_IsNewObj(res2) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg2), SWIGTYPE_p_int, new_flags));
   }
-  if (SWIG_IsTmpObj(res3)) {
+  if (ReturnSame(SWIG_IsTmpObj(res3))) {
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg3)));
   } else {
     int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_int, new_flags));
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -14822,7 +16088,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_GetColorInterpretation(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -14840,14 +16106,17 @@ SWIGINTERN PyObject *_wrap_Band_GetColorInterpretation(PyObject *SWIGUNUSEDPARM(
       CPLErrorReset();
     }
     result = (GDALColorInterp)GDALRasterBandShadow_GetColorInterpretation(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -14855,7 +16124,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_GetRasterColorInterpretation(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -14873,14 +16142,17 @@ SWIGINTERN PyObject *_wrap_Band_GetRasterColorInterpretation(PyObject *SWIGUNUSE
       CPLErrorReset();
     }
     result = (GDALColorInterp)GDALRasterBandShadow_GetRasterColorInterpretation(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -14888,7 +16160,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_SetColorInterpretation(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   GDALColorInterp arg2 ;
   void *argp1 = 0 ;
@@ -14914,25 +16186,18 @@ SWIGINTERN PyObject *_wrap_Band_SetColorInterpretation(PyObject *SWIGUNUSEDPARM(
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALRasterBandShadow_SetColorInterpretation(arg1,arg2);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_SetColorInterpretation(arg1,arg2));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
-  {
-    /* %typemap(ret) CPLErr */
-    if ( bUseExceptions == 0 ) {
-      /* We're not using exceptions.  And no error has occurred */
-      if ( resultobj == 0 ) {
-        /* No other return values set so return ErrorCode */
-        resultobj = PyInt_FromLong(result);
-      }
-    }
-  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -14940,7 +16205,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_SetRasterColorInterpretation(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   GDALColorInterp arg2 ;
   void *argp1 = 0 ;
@@ -14966,25 +16231,18 @@ SWIGINTERN PyObject *_wrap_Band_SetRasterColorInterpretation(PyObject *SWIGUNUSE
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALRasterBandShadow_SetRasterColorInterpretation(arg1,arg2);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_SetRasterColorInterpretation(arg1,arg2));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
-  {
-    /* %typemap(ret) CPLErr */
-    if ( bUseExceptions == 0 ) {
-      /* We're not using exceptions.  And no error has occurred */
-      if ( resultobj == 0 ) {
-        /* No other return values set so return ErrorCode */
-        resultobj = PyInt_FromLong(result);
-      }
-    }
-  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -14992,7 +16250,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_GetNoDataValue(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   double *arg2 = (double *) 0 ;
   int *arg3 = (int *) 0 ;
@@ -15018,12 +16276,14 @@ SWIGINTERN PyObject *_wrap_Band_GetNoDataValue(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     GDALRasterBandShadow_GetNoDataValue(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
@@ -15039,6 +16299,7 @@ SWIGINTERN PyObject *_wrap_Band_GetNoDataValue(PyObject *SWIGUNUSEDPARM(self), P
       resultobj = t_output_helper(resultobj,r);
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -15046,7 +16307,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_SetNoDataValue(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   double arg2 ;
   void *argp1 = 0 ;
@@ -15072,25 +16333,54 @@ SWIGINTERN PyObject *_wrap_Band_SetNoDataValue(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALRasterBandShadow_SetNoDataValue(arg1,arg2);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_SetNoDataValue(arg1,arg2));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Band_DeleteNoDataValue(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  CPLErr result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:Band_DeleteNoDataValue",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_DeleteNoDataValue" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
   {
-    /* %typemap(ret) CPLErr */
-    if ( bUseExceptions == 0 ) {
-      /* We're not using exceptions.  And no error has occurred */
-      if ( resultobj == 0 ) {
-        /* No other return values set so return ErrorCode */
-        resultobj = PyInt_FromLong(result);
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_DeleteNoDataValue(arg1));
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -15098,7 +16388,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_GetUnitType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -15116,14 +16406,17 @@ SWIGINTERN PyObject *_wrap_Band_GetUnitType(PyObject *SWIGUNUSEDPARM(self), PyOb
       CPLErrorReset();
     }
     result = (char *)GDALRasterBandShadow_GetUnitType(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -15131,7 +16424,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_SetUnitType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -15158,26 +16451,19 @@ SWIGINTERN PyObject *_wrap_Band_SetUnitType(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALRasterBandShadow_SetUnitType(arg1,(char const *)arg2);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_SetUnitType(arg1,(char const *)arg2));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-  {
-    /* %typemap(ret) CPLErr */
-    if ( bUseExceptions == 0 ) {
-      /* We're not using exceptions.  And no error has occurred */
-      if ( resultobj == 0 ) {
-        /* No other return values set so return ErrorCode */
-        resultobj = PyInt_FromLong(result);
-      }
-    }
-  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -15186,7 +16472,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_GetRasterCategoryNames(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -15204,12 +16490,14 @@ SWIGINTERN PyObject *_wrap_Band_GetRasterCategoryNames(PyObject *SWIGUNUSEDPARM(
       CPLErrorReset();
     }
     result = (char **)GDALRasterBandShadow_GetRasterCategoryNames(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) char **options -> ( string ) */
@@ -15227,6 +16515,7 @@ SWIGINTERN PyObject *_wrap_Band_GetRasterCategoryNames(PyObject *SWIGUNUSEDPARM(
       }
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -15234,7 +16523,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_SetRasterCategoryNames(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   char **arg2 = (char **) 0 ;
   void *argp1 = 0 ;
@@ -15261,8 +16550,12 @@ SWIGINTERN PyObject *_wrap_Band_SetRasterCategoryNames(PyObject *SWIGUNUSEDPARM(
       SWIG_fail;
     }
     
-    int size = PySequence_Size(obj1);
-    for (int i = 0; i < size; i++) {
+    Py_ssize_t size = PySequence_Size(obj1);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    for (int i = 0; i < (int)size; i++) {
       PyObject* pyObj = PySequence_GetItem(obj1,i);
       if (PyUnicode_Check(pyObj))
       {
@@ -15297,29 +16590,22 @@ SWIGINTERN PyObject *_wrap_Band_SetRasterCategoryNames(PyObject *SWIGUNUSEDPARM(
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALRasterBandShadow_SetRasterCategoryNames(arg1,arg2);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_SetRasterCategoryNames(arg1,arg2));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
     /* %typemap(freearg) char **options */
     CSLDestroy( arg2 );
   }
-  {
-    /* %typemap(ret) CPLErr */
-    if ( bUseExceptions == 0 ) {
-      /* We're not using exceptions.  And no error has occurred */
-      if ( resultobj == 0 ) {
-        /* No other return values set so return ErrorCode */
-        resultobj = PyInt_FromLong(result);
-      }
-    }
-  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -15331,7 +16617,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_GetMinimum(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   double *arg2 = (double *) 0 ;
   int *arg3 = (int *) 0 ;
@@ -15357,12 +16643,14 @@ SWIGINTERN PyObject *_wrap_Band_GetMinimum(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     GDALRasterBandShadow_GetMinimum(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
@@ -15378,6 +16666,7 @@ SWIGINTERN PyObject *_wrap_Band_GetMinimum(PyObject *SWIGUNUSEDPARM(self), PyObj
       resultobj = t_output_helper(resultobj,r);
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -15385,7 +16674,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_GetMaximum(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   double *arg2 = (double *) 0 ;
   int *arg3 = (int *) 0 ;
@@ -15411,12 +16700,14 @@ SWIGINTERN PyObject *_wrap_Band_GetMaximum(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     GDALRasterBandShadow_GetMaximum(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
@@ -15432,6 +16723,7 @@ SWIGINTERN PyObject *_wrap_Band_GetMaximum(PyObject *SWIGUNUSEDPARM(self), PyObj
       resultobj = t_output_helper(resultobj,r);
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -15439,7 +16731,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_GetOffset(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   double *arg2 = (double *) 0 ;
   int *arg3 = (int *) 0 ;
@@ -15465,12 +16757,14 @@ SWIGINTERN PyObject *_wrap_Band_GetOffset(PyObject *SWIGUNUSEDPARM(self), PyObje
       CPLErrorReset();
     }
     GDALRasterBandShadow_GetOffset(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
@@ -15486,6 +16780,7 @@ SWIGINTERN PyObject *_wrap_Band_GetOffset(PyObject *SWIGUNUSEDPARM(self), PyObje
       resultobj = t_output_helper(resultobj,r);
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -15493,7 +16788,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_GetScale(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   double *arg2 = (double *) 0 ;
   int *arg3 = (int *) 0 ;
@@ -15519,12 +16814,14 @@ SWIGINTERN PyObject *_wrap_Band_GetScale(PyObject *SWIGUNUSEDPARM(self), PyObjec
       CPLErrorReset();
     }
     GDALRasterBandShadow_GetScale(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
@@ -15540,6 +16837,7 @@ SWIGINTERN PyObject *_wrap_Band_GetScale(PyObject *SWIGUNUSEDPARM(self), PyObjec
       resultobj = t_output_helper(resultobj,r);
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -15547,7 +16845,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_SetOffset(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   double arg2 ;
   void *argp1 = 0 ;
@@ -15573,25 +16871,18 @@ SWIGINTERN PyObject *_wrap_Band_SetOffset(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALRasterBandShadow_SetOffset(arg1,arg2);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_SetOffset(arg1,arg2));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
-  {
-    /* %typemap(ret) CPLErr */
-    if ( bUseExceptions == 0 ) {
-      /* We're not using exceptions.  And no error has occurred */
-      if ( resultobj == 0 ) {
-        /* No other return values set so return ErrorCode */
-        resultobj = PyInt_FromLong(result);
-      }
-    }
-  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -15599,7 +16890,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_SetScale(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   double arg2 ;
   void *argp1 = 0 ;
@@ -15625,25 +16916,18 @@ SWIGINTERN PyObject *_wrap_Band_SetScale(PyObject *SWIGUNUSEDPARM(self), PyObjec
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALRasterBandShadow_SetScale(arg1,arg2);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_SetScale(arg1,arg2));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
-  {
-    /* %typemap(ret) CPLErr */
-    if ( bUseExceptions == 0 ) {
-      /* We're not using exceptions.  And no error has occurred */
-      if ( resultobj == 0 ) {
-        /* No other return values set so return ErrorCode */
-        resultobj = PyInt_FromLong(result);
-      }
-    }
-  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -15651,7 +16935,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_GetStatistics(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   int arg2 ;
   int arg3 ;
@@ -15702,51 +16986,44 @@ SWIGINTERN PyObject *_wrap_Band_GetStatistics(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALRasterBandShadow_GetStatistics(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_GetStatistics(arg1,arg2,arg3,arg4,arg5,arg6,arg7));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) IF_ERROR_RETURN_NONE */
   }
-  if (SWIG_IsTmpObj(res4)) {
+  if (ReturnSame(SWIG_IsTmpObj(res4))) {
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_double((*arg4)));
   } else {
     int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_double, new_flags));
   }
-  if (SWIG_IsTmpObj(res5)) {
+  if (ReturnSame(SWIG_IsTmpObj(res5))) {
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_double((*arg5)));
   } else {
     int new_flags = SWIG_IsNewObj(res5) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg5), SWIGTYPE_p_double, new_flags));
   }
-  if (SWIG_IsTmpObj(res6)) {
+  if (ReturnSame(SWIG_IsTmpObj(res6))) {
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_double((*arg6)));
   } else {
     int new_flags = SWIG_IsNewObj(res6) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg6), SWIGTYPE_p_double, new_flags));
   }
-  if (SWIG_IsTmpObj(res7)) {
+  if (ReturnSame(SWIG_IsTmpObj(res7))) {
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_double((*arg7)));
   } else {
     int new_flags = SWIG_IsNewObj(res7) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg7), SWIGTYPE_p_double, new_flags));
   }
-  {
-    /* %typemap(ret) CPLErr */
-    if ( bUseExceptions == 0 ) {
-      /* We're not using exceptions.  And no error has occurred */
-      if ( resultobj == 0 ) {
-        /* No other return values set so return ErrorCode */
-        resultobj = PyInt_FromLong(result);
-      }
-    }
-  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -15754,7 +17031,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_ComputeStatistics(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   bool arg2 ;
   double *arg3 = (double *) NULL ;
@@ -15809,16 +17086,16 @@ SWIGINTERN PyObject *_wrap_Band_ComputeStatistics(PyObject *SWIGUNUSEDPARM(self)
       /* callback_func typemap */
       if (obj2 && obj2 != Py_None ) {
         void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj2, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj2,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
         
         if ( cbfunction == GDALTermProgress ) {
           arg7 = GDALTermProgress;
         } else {
           if (!PyCallable_Check(obj2)) {
-            PyErr_SetString( PyExc_RuntimeError, 
+            PyErr_SetString( PyExc_RuntimeError,
               "Object given is not a Python function" );
             SWIG_fail;
           }
@@ -15840,36 +17117,38 @@ SWIGINTERN PyObject *_wrap_Band_ComputeStatistics(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALRasterBandShadow_ComputeStatistics(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_ComputeStatistics(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) IF_ERROR_RETURN_NONE */
   }
-  if (SWIG_IsTmpObj(res3)) {
+  if (ReturnSame(SWIG_IsTmpObj(res3))) {
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_double((*arg3)));
   } else {
     int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_double, new_flags));
   }
-  if (SWIG_IsTmpObj(res4)) {
+  if (ReturnSame(SWIG_IsTmpObj(res4))) {
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_double((*arg4)));
   } else {
     int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_double, new_flags));
   }
-  if (SWIG_IsTmpObj(res5)) {
+  if (ReturnSame(SWIG_IsTmpObj(res5))) {
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_double((*arg5)));
   } else {
     int new_flags = SWIG_IsNewObj(res5) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg5), SWIGTYPE_p_double, new_flags));
   }
-  if (SWIG_IsTmpObj(res6)) {
+  if (ReturnSame(SWIG_IsTmpObj(res6))) {
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_double((*arg6)));
   } else {
     int new_flags = SWIG_IsNewObj(res6) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
@@ -15881,6 +17160,7 @@ SWIGINTERN PyObject *_wrap_Band_ComputeStatistics(PyObject *SWIGUNUSEDPARM(self)
     CPLFree(psProgressInfo);
     
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -15894,7 +17174,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_SetStatistics(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -15947,15 +17227,18 @@ SWIGINTERN PyObject *_wrap_Band_SetStatistics(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALRasterBandShadow_SetStatistics(arg1,arg2,arg3,arg4,arg5);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_SetStatistics(arg1,arg2,arg3,arg4,arg5));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -15963,7 +17246,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_GetOverviewCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -15981,14 +17264,17 @@ SWIGINTERN PyObject *_wrap_Band_GetOverviewCount(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (int)GDALRasterBandShadow_GetOverviewCount(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -15996,7 +17282,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_GetOverview(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -16023,14 +17309,17 @@ SWIGINTERN PyObject *_wrap_Band_GetOverview(PyObject *SWIGUNUSEDPARM(self), PyOb
       CPLErrorReset();
     }
     result = (GDALRasterBandShadow *)GDALRasterBandShadow_GetOverview(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16038,7 +17327,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_Checksum(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   int arg2 = (int) 0 ;
   int arg3 = (int) 0 ;
@@ -16117,14 +17406,17 @@ SWIGINTERN PyObject *_wrap_Band_Checksum(PyObject *SWIGUNUSEDPARM(self), PyObjec
       CPLErrorReset();
     }
     result = (int)GDALRasterBandShadow_Checksum(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16132,7 +17424,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_ComputeRasterMinMax(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   double *arg2 ;
   int arg3 = (int) 0 ;
@@ -16146,6 +17438,7 @@ SWIGINTERN PyObject *_wrap_Band_ComputeRasterMinMax(PyObject *SWIGUNUSEDPARM(sel
   
   {
     /* %typemap(in,numinputs=0) (double argout2[ANY]) */
+    memset(argout2, 0, sizeof(argout2));
     arg2 = argout2;
   }
   if (!PyArg_ParseTuple(args,(char *)"O|O:Band_ComputeRasterMinMax",&obj0,&obj1)) SWIG_fail;
@@ -16166,12 +17459,14 @@ SWIGINTERN PyObject *_wrap_Band_ComputeRasterMinMax(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     GDALRasterBandShadow_ComputeRasterMinMax(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
@@ -16179,6 +17474,7 @@ SWIGINTERN PyObject *_wrap_Band_ComputeRasterMinMax(PyObject *SWIGUNUSEDPARM(sel
     PyObject *out = CreateTupleFromDoubleArray( arg2, 2 );
     resultobj = t_output_helper(resultobj,out);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16186,7 +17482,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_ComputeBandStats(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   double *arg2 ;
   int arg3 = (int) 1 ;
@@ -16200,6 +17496,7 @@ SWIGINTERN PyObject *_wrap_Band_ComputeBandStats(PyObject *SWIGUNUSEDPARM(self),
   
   {
     /* %typemap(in,numinputs=0) (double argout2[ANY]) */
+    memset(argout2, 0, sizeof(argout2));
     arg2 = argout2;
   }
   if (!PyArg_ParseTuple(args,(char *)"O|O:Band_ComputeBandStats",&obj0,&obj1)) SWIG_fail;
@@ -16220,12 +17517,14 @@ SWIGINTERN PyObject *_wrap_Band_ComputeBandStats(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     GDALRasterBandShadow_ComputeBandStats(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
@@ -16233,6 +17532,7 @@ SWIGINTERN PyObject *_wrap_Band_ComputeBandStats(PyObject *SWIGUNUSEDPARM(self),
     PyObject *out = CreateTupleFromDoubleArray( arg2, 2 );
     resultobj = t_output_helper(resultobj,out);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16240,7 +17540,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_Fill(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   double arg2 ;
   double arg3 = (double) 0.0 ;
@@ -16277,15 +17577,18 @@ SWIGINTERN PyObject *_wrap_Band_Fill(PyObject *SWIGUNUSEDPARM(self), PyObject *a
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALRasterBandShadow_Fill(arg1,arg2,arg3);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_Fill(arg1,arg2,arg3));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16293,7 +17596,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_WriteRaster(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   int arg2 ;
   int arg3 ;
@@ -16304,8 +17607,8 @@ SWIGINTERN PyObject *_wrap_Band_WriteRaster(PyObject *SWIGUNUSEDPARM(self), PyOb
   int *arg8 = (int *) 0 ;
   int *arg9 = (int *) 0 ;
   int *arg10 = (int *) 0 ;
-  int *arg11 = (int *) 0 ;
-  int *arg12 = (int *) 0 ;
+  GIntBig *arg11 = (GIntBig *) 0 ;
+  GIntBig *arg12 = (GIntBig *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   int val2 ;
@@ -16320,8 +17623,8 @@ SWIGINTERN PyObject *_wrap_Band_WriteRaster(PyObject *SWIGUNUSEDPARM(self), PyOb
   int val8 ;
   int val9 ;
   int val10 ;
-  int val11 ;
-  int val12 ;
+  GIntBig val11 ;
+  GIntBig val12 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   PyObject * obj2 = 0 ;
@@ -16450,12 +17753,12 @@ SWIGINTERN PyObject *_wrap_Band_WriteRaster(PyObject *SWIGUNUSEDPARM(self), PyOb
   }
   if (obj9) {
     {
-      /* %typemap(in) (int *optional_##int) */
+      /* %typemap(in) (GIntBig *optional_##GIntBig) */
       if ( obj9 == Py_None ) {
         arg11 = 0;
       }
-      else if ( PyArg_Parse( obj9,"i" ,&val11 ) ) {
-        arg11 = (int *) &val11;
+      else if ( PyArg_Parse( obj9,"L" ,&val11 ) ) {
+        arg11 = (GIntBig *) &val11;
       }
       else {
         PyErr_SetString( PyExc_TypeError, "Invalid Parameter" );
@@ -16465,12 +17768,12 @@ SWIGINTERN PyObject *_wrap_Band_WriteRaster(PyObject *SWIGUNUSEDPARM(self), PyOb
   }
   if (obj10) {
     {
-      /* %typemap(in) (int *optional_##int) */
+      /* %typemap(in) (GIntBig *optional_##GIntBig) */
       if ( obj10 == Py_None ) {
         arg12 = 0;
       }
-      else if ( PyArg_Parse( obj10,"i" ,&val12 ) ) {
-        arg12 = (int *) &val12;
+      else if ( PyArg_Parse( obj10,"L" ,&val12 ) ) {
+        arg12 = (GIntBig *) &val12;
       }
       else {
         PyErr_SetString( PyExc_TypeError, "Invalid Parameter" );
@@ -16482,26 +17785,29 @@ SWIGINTERN PyObject *_wrap_Band_WriteRaster(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALRasterBandShadow_WriteRaster(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_WriteRaster(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
     /* %typemap(freearg) (GIntBig *nLen, char *pBuf ) */
-    if( alloc6 == SWIG_NEWOBJ ) {
+    if (ReturnSame(alloc6) == SWIG_NEWOBJ ) {
       delete[] arg7;
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
     /* %typemap(freearg) (GIntBig *nLen, char *pBuf ) */
-    if( alloc6 == SWIG_NEWOBJ ) {
+    if (ReturnSame(alloc6) == SWIG_NEWOBJ ) {
       delete[] arg7;
     }
   }
@@ -16510,7 +17816,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_FlushCache(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -16527,14 +17833,17 @@ SWIGINTERN PyObject *_wrap_Band_FlushCache(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     GDALRasterBandShadow_FlushCache(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16542,7 +17851,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_GetRasterColorTable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -16560,14 +17869,17 @@ SWIGINTERN PyObject *_wrap_Band_GetRasterColorTable(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     result = (GDALColorTableShadow *)GDALRasterBandShadow_GetRasterColorTable(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALColorTableShadow, 0 |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16575,7 +17887,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_GetColorTable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -16593,14 +17905,17 @@ SWIGINTERN PyObject *_wrap_Band_GetColorTable(PyObject *SWIGUNUSEDPARM(self), Py
       CPLErrorReset();
     }
     result = (GDALColorTableShadow *)GDALRasterBandShadow_GetColorTable(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALColorTableShadow, 0 |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16608,7 +17923,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_SetRasterColorTable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   GDALColorTableShadow *arg2 = (GDALColorTableShadow *) 0 ;
   void *argp1 = 0 ;
@@ -16635,14 +17950,17 @@ SWIGINTERN PyObject *_wrap_Band_SetRasterColorTable(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     result = (int)GDALRasterBandShadow_SetRasterColorTable(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16650,7 +17968,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_SetColorTable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   GDALColorTableShadow *arg2 = (GDALColorTableShadow *) 0 ;
   void *argp1 = 0 ;
@@ -16677,14 +17995,17 @@ SWIGINTERN PyObject *_wrap_Band_SetColorTable(PyObject *SWIGUNUSEDPARM(self), Py
       CPLErrorReset();
     }
     result = (int)GDALRasterBandShadow_SetColorTable(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16692,7 +18013,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_GetDefaultRAT(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -16710,14 +18031,17 @@ SWIGINTERN PyObject *_wrap_Band_GetDefaultRAT(PyObject *SWIGUNUSEDPARM(self), Py
       CPLErrorReset();
     }
     result = (GDALRasterAttributeTableShadow *)GDALRasterBandShadow_GetDefaultRAT(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALRasterAttributeTableShadow, 0 |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16725,7 +18049,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_SetDefaultRAT(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   GDALRasterAttributeTableShadow *arg2 = (GDALRasterAttributeTableShadow *) 0 ;
   void *argp1 = 0 ;
@@ -16752,14 +18076,17 @@ SWIGINTERN PyObject *_wrap_Band_SetDefaultRAT(PyObject *SWIGUNUSEDPARM(self), Py
       CPLErrorReset();
     }
     result = (int)GDALRasterBandShadow_SetDefaultRAT(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16767,7 +18094,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_GetMaskBand(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -16785,14 +18112,17 @@ SWIGINTERN PyObject *_wrap_Band_GetMaskBand(PyObject *SWIGUNUSEDPARM(self), PyOb
       CPLErrorReset();
     }
     result = (GDALRasterBandShadow *)GDALRasterBandShadow_GetMaskBand(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16800,7 +18130,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_GetMaskFlags(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -16818,14 +18148,17 @@ SWIGINTERN PyObject *_wrap_Band_GetMaskFlags(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (int)GDALRasterBandShadow_GetMaskFlags(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16833,7 +18166,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_CreateMaskBand(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -16859,15 +18192,18 @@ SWIGINTERN PyObject *_wrap_Band_CreateMaskBand(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALRasterBandShadow_CreateMaskBand(arg1,arg2);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_CreateMaskBand(arg1,arg2));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16875,7 +18211,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_GetHistogram(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   double arg2 = (double) -0.5 ;
   double arg3 = (double) 255.5 ;
@@ -16943,7 +18279,7 @@ SWIGINTERN PyObject *_wrap_Band_GetHistogram(PyObject *SWIGUNUSEDPARM(self), PyO
     {
       /* %typemap(in) int buckets, GUIntBig* panHistogram -> list */
       int requested_buckets = 0;
-      SWIG_AsVal_int(obj3, &requested_buckets);
+      CPL_IGNORE_RET_VAL(SWIG_AsVal_int(obj3, &requested_buckets));
       if( requested_buckets != arg4 )
       {
         arg4 = requested_buckets;
@@ -16981,16 +18317,16 @@ SWIGINTERN PyObject *_wrap_Band_GetHistogram(PyObject *SWIGUNUSEDPARM(self), PyO
       /* callback_func typemap */
       if (obj6 && obj6 != Py_None ) {
         void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj6, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj6,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
         
         if ( cbfunction == GDALTermProgress ) {
           arg8 = GDALTermProgress;
         } else {
           if (!PyCallable_Check(obj6)) {
-            PyErr_SetString( PyExc_RuntimeError, 
+            PyErr_SetString( PyExc_RuntimeError,
               "Object given is not a Python function" );
             SWIG_fail;
           }
@@ -17012,18 +18348,21 @@ SWIGINTERN PyObject *_wrap_Band_GetHistogram(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALRasterBandShadow_GetHistogram(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_GetHistogram(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
     /* %typemap(out) int buckets, GUIntBig* panHistogram -> list */
     GUIntBig *integerarray = arg5;
+    Py_DECREF( resultobj );
     if ( integerarray == NULL ) {
       resultobj = Py_None;
       Py_INCREF( resultobj );
@@ -17054,6 +18393,7 @@ SWIGINTERN PyObject *_wrap_Band_GetHistogram(PyObject *SWIGUNUSEDPARM(self), PyO
     CPLFree(psProgressInfo);
     
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -17073,7 +18413,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_GetDefaultHistogram(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   double *arg2 = (double *) NULL ;
   double *arg3 = (double *) NULL ;
@@ -17107,9 +18447,9 @@ SWIGINTERN PyObject *_wrap_Band_GetDefaultHistogram(PyObject *SWIGUNUSEDPARM(sel
   };
   CPLErr result;
   
-  double min_val, max_val;
-  int buckets_val;
-  GUIntBig *panHistogram;
+  double min_val = 0.0, max_val = 0.0;
+  int buckets_val = 0;
+  GUIntBig *panHistogram = NULL;
   
   arg2 = &min_val;
   arg3 = &max_val;
@@ -17169,16 +18509,16 @@ SWIGINTERN PyObject *_wrap_Band_GetDefaultHistogram(PyObject *SWIGUNUSEDPARM(sel
       /* callback_func typemap */
       if (obj6 && obj6 != Py_None ) {
         void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj6, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj6,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
         
         if ( cbfunction == GDALTermProgress ) {
           arg7 = GDALTermProgress;
         } else {
           if (!PyCallable_Check(obj6)) {
-            PyErr_SetString( PyExc_RuntimeError, 
+            PyErr_SetString( PyExc_RuntimeError,
               "Object given is not a Python function" );
             SWIG_fail;
           }
@@ -17200,13 +18540,15 @@ SWIGINTERN PyObject *_wrap_Band_GetDefaultHistogram(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALRasterBandShadow_GetDefaultHistogram(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_GetDefaultHistogram(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
@@ -17238,6 +18580,7 @@ SWIGINTERN PyObject *_wrap_Band_GetDefaultHistogram(PyObject *SWIGUNUSEDPARM(sel
     CPLFree(psProgressInfo);
     
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -17251,7 +18594,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_SetDefaultHistogram(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -17292,7 +18635,12 @@ SWIGINTERN PyObject *_wrap_Band_SetDefaultHistogram(PyObject *SWIGUNUSEDPARM(sel
       PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
-    arg4 = PySequence_Size(obj3);
+    Py_ssize_t size = PySequence_Size(obj3);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    arg4 = (int)size;
     arg5 = (GUIntBig*) malloc(arg4*sizeof(GUIntBig));
     for( int i = 0; i<arg4; i++ ) {
       PyObject *o = PySequence_GetItem(obj3,i);
@@ -17310,13 +18658,15 @@ SWIGINTERN PyObject *_wrap_Band_SetDefaultHistogram(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALRasterBandShadow_SetDefaultHistogram(arg1,arg2,arg3,arg4,arg5);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_SetDefaultHistogram(arg1,arg2,arg3,arg4,arg5));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
@@ -17325,6 +18675,7 @@ SWIGINTERN PyObject *_wrap_Band_SetDefaultHistogram(PyObject *SWIGUNUSEDPARM(sel
       free((void*) arg5);
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -17338,7 +18689,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_HasArbitraryOverviews(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -17356,14 +18707,17 @@ SWIGINTERN PyObject *_wrap_Band_HasArbitraryOverviews(PyObject *SWIGUNUSEDPARM(s
       CPLErrorReset();
     }
     result = (bool)GDALRasterBandShadow_HasArbitraryOverviews(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_bool(static_cast< bool >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -17371,7 +18725,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_GetCategoryNames(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -17389,12 +18743,14 @@ SWIGINTERN PyObject *_wrap_Band_GetCategoryNames(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (char **)GDALRasterBandShadow_GetCategoryNames(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) char **options -> ( string ) */
@@ -17412,6 +18768,7 @@ SWIGINTERN PyObject *_wrap_Band_GetCategoryNames(PyObject *SWIGUNUSEDPARM(self),
       }
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -17419,7 +18776,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_SetCategoryNames(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   char **arg2 = (char **) 0 ;
   void *argp1 = 0 ;
@@ -17446,8 +18803,12 @@ SWIGINTERN PyObject *_wrap_Band_SetCategoryNames(PyObject *SWIGUNUSEDPARM(self),
       SWIG_fail;
     }
     
-    int size = PySequence_Size(obj1);
-    for (int i = 0; i < size; i++) {
+    Py_ssize_t size = PySequence_Size(obj1);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    for (int i = 0; i < (int)size; i++) {
       PyObject* pyObj = PySequence_GetItem(obj1,i);
       if (PyUnicode_Check(pyObj))
       {
@@ -17482,19 +18843,22 @@ SWIGINTERN PyObject *_wrap_Band_SetCategoryNames(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALRasterBandShadow_SetCategoryNames(arg1,arg2);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_SetCategoryNames(arg1,arg2));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
     /* %typemap(freearg) char **options */
     CSLDestroy( arg2 );
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -17506,7 +18870,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_GetVirtualMem(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   GDALRWFlag arg2 ;
   int arg3 ;
@@ -17627,8 +18991,12 @@ SWIGINTERN PyObject *_wrap_Band_GetVirtualMem(PyObject *SWIGUNUSEDPARM(self), Py
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj11);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj11);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj11,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -17665,18 +19033,21 @@ SWIGINTERN PyObject *_wrap_Band_GetVirtualMem(PyObject *SWIGUNUSEDPARM(self), Py
       CPLErrorReset();
     }
     result = (CPLVirtualMemShadow *)GDALRasterBandShadow_GetVirtualMem(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_CPLVirtualMemShadow, SWIG_POINTER_OWN |  0 );
   {
     /* %typemap(freearg) char **options */
     CSLDestroy( arg12 );
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -17688,7 +19059,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_GetVirtualMemAuto(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   GDALRWFlag arg2 ;
   char **arg3 = (char **) NULL ;
@@ -17728,8 +19099,12 @@ SWIGINTERN PyObject *_wrap_Band_GetVirtualMemAuto(PyObject *SWIGUNUSEDPARM(self)
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj2);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj2);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj2,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -17766,18 +19141,21 @@ SWIGINTERN PyObject *_wrap_Band_GetVirtualMemAuto(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (CPLVirtualMemShadow *)GDALRasterBandShadow_GetVirtualMemAuto(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_CPLVirtualMemShadow, SWIG_POINTER_OWN |  0 );
   {
     /* %typemap(freearg) char **options */
     CSLDestroy( arg3 );
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -17789,7 +19167,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_GetTiledVirtualMem(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   GDALRWFlag arg2 ;
   int arg3 ;
@@ -17901,8 +19279,12 @@ SWIGINTERN PyObject *_wrap_Band_GetTiledVirtualMem(PyObject *SWIGUNUSEDPARM(self
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj10);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj10);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj10,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -17939,18 +19321,21 @@ SWIGINTERN PyObject *_wrap_Band_GetTiledVirtualMem(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     result = (CPLVirtualMemShadow *)GDALRasterBandShadow_GetTiledVirtualMem(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_CPLVirtualMemShadow, SWIG_POINTER_OWN |  0 );
   {
     /* %typemap(freearg) char **options */
     CSLDestroy( arg11 );
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -17962,12 +19347,12 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_ReadRaster1(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
-  int arg2 ;
-  int arg3 ;
-  int arg4 ;
-  int arg5 ;
+  double arg2 ;
+  double arg3 ;
+  double arg4 ;
+  double arg5 ;
   void **arg6 = (void **) 0 ;
   int *arg7 = (int *) 0 ;
   int *arg8 = (int *) 0 ;
@@ -17979,13 +19364,13 @@ SWIGINTERN PyObject *_wrap_Band_ReadRaster1(PyObject *SWIGUNUSEDPARM(self), PyOb
   void *arg14 = (void *) NULL ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int val2 ;
+  double val2 ;
   int ecode2 = 0 ;
-  int val3 ;
+  double val3 ;
   int ecode3 = 0 ;
-  int val4 ;
+  double val4 ;
   int ecode4 = 0 ;
-  int val5 ;
+  double val5 ;
   int ecode5 = 0 ;
   void *pyObject6 = NULL ;
   int val7 ;
@@ -18030,26 +19415,26 @@ SWIGINTERN PyObject *_wrap_Band_ReadRaster1(PyObject *SWIGUNUSEDPARM(self), PyOb
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_ReadRaster1" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
   }
   arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
-  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  ecode2 = SWIG_AsVal_double(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Band_ReadRaster1" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Band_ReadRaster1" "', argument " "2"" of type '" "double""'");
   } 
-  arg2 = static_cast< int >(val2);
-  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  arg2 = static_cast< double >(val2);
+  ecode3 = SWIG_AsVal_double(obj2, &val3);
   if (!SWIG_IsOK(ecode3)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Band_ReadRaster1" "', argument " "3"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Band_ReadRaster1" "', argument " "3"" of type '" "double""'");
   } 
-  arg3 = static_cast< int >(val3);
-  ecode4 = SWIG_AsVal_int(obj3, &val4);
+  arg3 = static_cast< double >(val3);
+  ecode4 = SWIG_AsVal_double(obj3, &val4);
   if (!SWIG_IsOK(ecode4)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Band_ReadRaster1" "', argument " "4"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Band_ReadRaster1" "', argument " "4"" of type '" "double""'");
   } 
-  arg4 = static_cast< int >(val4);
-  ecode5 = SWIG_AsVal_int(obj4, &val5);
+  arg4 = static_cast< double >(val4);
+  ecode5 = SWIG_AsVal_double(obj4, &val5);
   if (!SWIG_IsOK(ecode5)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Band_ReadRaster1" "', argument " "5"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Band_ReadRaster1" "', argument " "5"" of type '" "double""'");
   } 
-  arg5 = static_cast< int >(val5);
+  arg5 = static_cast< double >(val5);
   if (obj5) {
     {
       /* %typemap(in) (int *optional_##int) */
@@ -18138,16 +19523,16 @@ SWIGINTERN PyObject *_wrap_Band_ReadRaster1(PyObject *SWIGUNUSEDPARM(self), PyOb
       /* callback_func typemap */
       if (obj11 && obj11 != Py_None ) {
         void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj11, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj11,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
         
         if ( cbfunction == GDALTermProgress ) {
           arg13 = GDALTermProgress;
         } else {
           if (!PyCallable_Check(obj11)) {
-            PyErr_SetString( PyExc_RuntimeError, 
+            PyErr_SetString( PyExc_RuntimeError,
               "Object given is not a Python function" );
             SWIG_fail;
           }
@@ -18169,13 +19554,15 @@ SWIGINTERN PyObject *_wrap_Band_ReadRaster1(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALRasterBandShadow_ReadRaster1(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12,arg13,arg14);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_ReadRaster1(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12,arg13,arg14));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
@@ -18197,6 +19584,7 @@ SWIGINTERN PyObject *_wrap_Band_ReadRaster1(PyObject *SWIGUNUSEDPARM(self), PyOb
     CPLFree(psProgressInfo);
     
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -18210,7 +19598,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Band_ReadBlock(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   int arg2 ;
   int arg3 ;
@@ -18254,13 +19642,15 @@ SWIGINTERN PyObject *_wrap_Band_ReadBlock(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALRasterBandShadow_ReadBlock(arg1,arg2,arg3,arg4);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_ReadBlock(arg1,arg2,arg3,arg4));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
@@ -18276,6 +19666,7 @@ SWIGINTERN PyObject *_wrap_Band_ReadBlock(PyObject *SWIGUNUSEDPARM(self), PyObje
       Py_INCREF(resultobj);
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -18290,7 +19681,7 @@ SWIGINTERN PyObject *Band_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject
 }
 
 SWIGINTERN PyObject *_wrap_new_ColorTable(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALPaletteInterp arg1 = (GDALPaletteInterp) GPI_RGB ;
   int val1 ;
   int ecode1 = 0 ;
@@ -18313,14 +19704,17 @@ SWIGINTERN PyObject *_wrap_new_ColorTable(PyObject *SWIGUNUSEDPARM(self), PyObje
       CPLErrorReset();
     }
     result = (GDALColorTableShadow *)new_GDALColorTableShadow(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALColorTableShadow, SWIG_POINTER_NEW |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -18328,7 +19722,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_delete_ColorTable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALColorTableShadow *arg1 = (GDALColorTableShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -18345,14 +19739,17 @@ SWIGINTERN PyObject *_wrap_delete_ColorTable(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     delete_GDALColorTableShadow(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -18360,7 +19757,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_ColorTable_Clone(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALColorTableShadow *arg1 = (GDALColorTableShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -18378,14 +19775,17 @@ SWIGINTERN PyObject *_wrap_ColorTable_Clone(PyObject *SWIGUNUSEDPARM(self), PyOb
       CPLErrorReset();
     }
     result = (GDALColorTableShadow *)GDALColorTableShadow_Clone(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALColorTableShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -18393,7 +19793,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_ColorTable_GetPaletteInterpretation(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALColorTableShadow *arg1 = (GDALColorTableShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -18411,14 +19811,17 @@ SWIGINTERN PyObject *_wrap_ColorTable_GetPaletteInterpretation(PyObject *SWIGUNU
       CPLErrorReset();
     }
     result = (GDALPaletteInterp)GDALColorTableShadow_GetPaletteInterpretation(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -18426,7 +19829,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_ColorTable_GetCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALColorTableShadow *arg1 = (GDALColorTableShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -18444,14 +19847,17 @@ SWIGINTERN PyObject *_wrap_ColorTable_GetCount(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     result = (int)GDALColorTableShadow_GetColorEntryCount(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -18459,7 +19865,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_ColorTable_GetColorEntry(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALColorTableShadow *arg1 = (GDALColorTableShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -18486,12 +19892,14 @@ SWIGINTERN PyObject *_wrap_ColorTable_GetColorEntry(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     result = (GDALColorEntry *)GDALColorTableShadow_GetColorEntry(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) GDALColorEntry* */
@@ -18500,6 +19908,7 @@ SWIGINTERN PyObject *_wrap_ColorTable_GetColorEntry(PyObject *SWIGUNUSEDPARM(sel
     else
     resultobj = NULL;
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -18507,7 +19916,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_ColorTable_GetColorEntryAsRGB(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALColorTableShadow *arg1 = (GDALColorTableShadow *) 0 ;
   int arg2 ;
   GDALColorEntry *arg3 = (GDALColorEntry *) 0 ;
@@ -18539,7 +19948,7 @@ SWIGINTERN PyObject *_wrap_ColorTable_GetColorEntryAsRGB(PyObject *SWIGUNUSEDPAR
       PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
-    int size = PySequence_Size(obj2);
+    Py_ssize_t size = PySequence_Size(obj2);
     if ( size > 4 ) {
       PyErr_SetString(PyExc_TypeError, "ColorEntry sequence too long");
       SWIG_fail;
@@ -18559,14 +19968,17 @@ SWIGINTERN PyObject *_wrap_ColorTable_GetColorEntryAsRGB(PyObject *SWIGUNUSEDPAR
       CPLErrorReset();
     }
     result = (int)GDALColorTableShadow_GetColorEntryAsRGB(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -18574,7 +19986,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_ColorTable_SetColorEntry(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALColorTableShadow *arg1 = (GDALColorTableShadow *) 0 ;
   int arg2 ;
   GDALColorEntry *arg3 = (GDALColorEntry *) 0 ;
@@ -18605,7 +20017,7 @@ SWIGINTERN PyObject *_wrap_ColorTable_SetColorEntry(PyObject *SWIGUNUSEDPARM(sel
       PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
-    int size = PySequence_Size(obj2);
+    Py_ssize_t size = PySequence_Size(obj2);
     if ( size > 4 ) {
       PyErr_SetString(PyExc_TypeError, "ColorEntry sequence too long");
       SWIG_fail;
@@ -18625,14 +20037,17 @@ SWIGINTERN PyObject *_wrap_ColorTable_SetColorEntry(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     GDALColorTableShadow_SetColorEntry(arg1,arg2,(GDALColorEntry const *)arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -18640,7 +20055,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_ColorTable_CreateColorRamp(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALColorTableShadow *arg1 = (GDALColorTableShadow *) 0 ;
   int arg2 ;
   GDALColorEntry *arg3 = (GDALColorEntry *) 0 ;
@@ -18678,7 +20093,7 @@ SWIGINTERN PyObject *_wrap_ColorTable_CreateColorRamp(PyObject *SWIGUNUSEDPARM(s
       PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
-    int size = PySequence_Size(obj2);
+    Py_ssize_t size = PySequence_Size(obj2);
     if ( size > 4 ) {
       PyErr_SetString(PyExc_TypeError, "ColorEntry sequence too long");
       SWIG_fail;
@@ -18705,7 +20120,7 @@ SWIGINTERN PyObject *_wrap_ColorTable_CreateColorRamp(PyObject *SWIGUNUSEDPARM(s
       PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
-    int size = PySequence_Size(obj4);
+    Py_ssize_t size = PySequence_Size(obj4);
     if ( size > 4 ) {
       PyErr_SetString(PyExc_TypeError, "ColorEntry sequence too long");
       SWIG_fail;
@@ -18725,14 +20140,17 @@ SWIGINTERN PyObject *_wrap_ColorTable_CreateColorRamp(PyObject *SWIGUNUSEDPARM(s
       CPLErrorReset();
     }
     GDALColorTableShadow_CreateColorRamp(arg1,arg2,(GDALColorEntry const *)arg3,arg4,(GDALColorEntry const *)arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -18747,7 +20165,7 @@ SWIGINTERN PyObject *ColorTable_swigregister(PyObject *SWIGUNUSEDPARM(self), PyO
 }
 
 SWIGINTERN PyObject *_wrap_new_RasterAttributeTable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterAttributeTableShadow *result = 0 ;
   
   if (!PyArg_ParseTuple(args,(char *)":new_RasterAttributeTable")) SWIG_fail;
@@ -18756,14 +20174,17 @@ SWIGINTERN PyObject *_wrap_new_RasterAttributeTable(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     result = (GDALRasterAttributeTableShadow *)new_GDALRasterAttributeTableShadow();
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALRasterAttributeTableShadow, SWIG_POINTER_NEW |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -18771,7 +20192,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_delete_RasterAttributeTable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -18788,14 +20209,17 @@ SWIGINTERN PyObject *_wrap_delete_RasterAttributeTable(PyObject *SWIGUNUSEDPARM(
       CPLErrorReset();
     }
     delete_GDALRasterAttributeTableShadow(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -18803,7 +20227,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_RasterAttributeTable_Clone(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -18821,14 +20245,17 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_Clone(PyObject *SWIGUNUSEDPARM(s
       CPLErrorReset();
     }
     result = (GDALRasterAttributeTableShadow *)GDALRasterAttributeTableShadow_Clone(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALRasterAttributeTableShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -18836,7 +20263,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetColumnCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -18854,14 +20281,17 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetColumnCount(PyObject *SWIGUNU
       CPLErrorReset();
     }
     result = (int)GDALRasterAttributeTableShadow_GetColumnCount(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -18869,7 +20299,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetNameOfCol(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -18896,14 +20326,17 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetNameOfCol(PyObject *SWIGUNUSE
       CPLErrorReset();
     }
     result = (char *)GDALRasterAttributeTableShadow_GetNameOfCol(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -18911,7 +20344,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetUsageOfCol(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -18938,14 +20371,17 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetUsageOfCol(PyObject *SWIGUNUS
       CPLErrorReset();
     }
     result = (GDALRATFieldUsage)GDALRasterAttributeTableShadow_GetUsageOfCol(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -18953,7 +20389,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetTypeOfCol(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -18980,14 +20416,17 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetTypeOfCol(PyObject *SWIGUNUSE
       CPLErrorReset();
     }
     result = (GDALRATFieldType)GDALRasterAttributeTableShadow_GetTypeOfCol(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -18995,7 +20434,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetColOfUsage(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
   GDALRATFieldUsage arg2 ;
   void *argp1 = 0 ;
@@ -19022,14 +20461,17 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetColOfUsage(PyObject *SWIGUNUS
       CPLErrorReset();
     }
     result = (int)GDALRasterAttributeTableShadow_GetColOfUsage(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -19037,7 +20479,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetRowCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -19055,14 +20497,17 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetRowCount(PyObject *SWIGUNUSED
       CPLErrorReset();
     }
     result = (int)GDALRasterAttributeTableShadow_GetRowCount(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -19070,7 +20515,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetValueAsString(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
   int arg2 ;
   int arg3 ;
@@ -19106,14 +20551,17 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetValueAsString(PyObject *SWIGU
       CPLErrorReset();
     }
     result = (char *)GDALRasterAttributeTableShadow_GetValueAsString(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -19121,7 +20569,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetValueAsInt(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
   int arg2 ;
   int arg3 ;
@@ -19157,14 +20605,17 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetValueAsInt(PyObject *SWIGUNUS
       CPLErrorReset();
     }
     result = (int)GDALRasterAttributeTableShadow_GetValueAsInt(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -19172,7 +20623,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetValueAsDouble(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
   int arg2 ;
   int arg3 ;
@@ -19208,14 +20659,17 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetValueAsDouble(PyObject *SWIGU
       CPLErrorReset();
     }
     result = (double)GDALRasterAttributeTableShadow_GetValueAsDouble(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_double(static_cast< double >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -19223,7 +20677,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_RasterAttributeTable_SetValueAsString(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
   int arg2 ;
   int arg3 ;
@@ -19265,19 +20719,21 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_SetValueAsString(PyObject *SWIGU
       SWIG_fail;
     }
     
-    arg4 = GDALPythonObjectToCStr(str4, &bToFree4); 
+    arg4 = GDALPythonObjectToCStr(str4, &bToFree4);
   }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
     GDALRasterAttributeTableShadow_SetValueAsString(arg1,arg2,arg3,(char const *)arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
@@ -19288,6 +20744,7 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_SetValueAsString(PyObject *SWIGU
     }
     GDALPythonFreeCStr(arg4, bToFree4);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -19303,7 +20760,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_RasterAttributeTable_SetValueAsInt(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
   int arg2 ;
   int arg3 ;
@@ -19347,14 +20804,17 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_SetValueAsInt(PyObject *SWIGUNUS
       CPLErrorReset();
     }
     GDALRasterAttributeTableShadow_SetValueAsInt(arg1,arg2,arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -19362,7 +20822,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_RasterAttributeTable_SetValueAsDouble(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
   int arg2 ;
   int arg3 ;
@@ -19406,14 +20866,17 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_SetValueAsDouble(PyObject *SWIGU
       CPLErrorReset();
     }
     GDALRasterAttributeTableShadow_SetValueAsDouble(arg1,arg2,arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -19421,7 +20884,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_RasterAttributeTable_SetRowCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -19447,14 +20910,17 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_SetRowCount(PyObject *SWIGUNUSED
       CPLErrorReset();
     }
     GDALRasterAttributeTableShadow_SetRowCount(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -19462,7 +20928,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_RasterAttributeTable_CreateColumn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   GDALRATFieldType arg3 ;
@@ -19508,15 +20974,18 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_CreateColumn(PyObject *SWIGUNUSE
       CPLErrorReset();
     }
     result = (int)GDALRasterAttributeTableShadow_CreateColumn(arg1,(char const *)arg2,arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -19525,7 +20994,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetLinearBinning(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
   double *arg2 = (double *) 0 ;
   double *arg3 = (double *) 0 ;
@@ -19551,26 +21020,29 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetLinearBinning(PyObject *SWIGU
       CPLErrorReset();
     }
     result = (bool)GDALRasterAttributeTableShadow_GetLinearBinning(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_bool(static_cast< bool >(result));
-  if (SWIG_IsTmpObj(res2)) {
+  if (ReturnSame(SWIG_IsTmpObj(res2))) {
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_double((*arg2)));
   } else {
     int new_flags = SWIG_IsNewObj(res2) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg2), SWIGTYPE_p_double, new_flags));
   }
-  if (SWIG_IsTmpObj(res3)) {
+  if (ReturnSame(SWIG_IsTmpObj(res3))) {
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_double((*arg3)));
   } else {
     int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_double, new_flags));
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -19578,7 +21050,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_RasterAttributeTable_SetLinearBinning(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -19614,14 +21086,17 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_SetLinearBinning(PyObject *SWIGU
       CPLErrorReset();
     }
     result = (int)GDALRasterAttributeTableShadow_SetLinearBinning(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -19629,7 +21104,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetRowOfValue(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
   double arg2 ;
   void *argp1 = 0 ;
@@ -19656,14 +21131,17 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetRowOfValue(PyObject *SWIGUNUS
       CPLErrorReset();
     }
     result = (int)GDALRasterAttributeTableShadow_GetRowOfValue(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -19671,7 +21149,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_RasterAttributeTable_ChangesAreWrittenToFile(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -19689,14 +21167,17 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_ChangesAreWrittenToFile(PyObject
       CPLErrorReset();
     }
     result = (int)GDALRasterAttributeTableShadow_ChangesAreWrittenToFile(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -19704,7 +21185,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_RasterAttributeTable_DumpReadable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterAttributeTableShadow *arg1 = (GDALRasterAttributeTableShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -19721,14 +21202,17 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_DumpReadable(PyObject *SWIGUNUSE
       CPLErrorReset();
     }
     GDALRasterAttributeTableShadow_DumpReadable(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -19743,7 +21227,7 @@ SWIGINTERN PyObject *RasterAttributeTable_swigregister(PyObject *SWIGUNUSEDPARM(
 }
 
 SWIGINTERN PyObject *_wrap_TermProgress_nocb(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   double arg1 ;
   char *arg2 = (char *) NULL ;
   void *arg3 = (void *) NULL ;
@@ -19785,15 +21269,18 @@ SWIGINTERN PyObject *_wrap_TermProgress_nocb(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (int)GDALTermProgress_nocb(arg1,(char const *)arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -19802,7 +21289,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_ComputeMedianCutPCT(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   GDALRasterBandShadow *arg2 = (GDALRasterBandShadow *) 0 ;
   GDALRasterBandShadow *arg3 = (GDALRasterBandShadow *) 0 ;
@@ -19871,16 +21358,16 @@ SWIGINTERN PyObject *_wrap_ComputeMedianCutPCT(PyObject *SWIGUNUSEDPARM(self), P
       /* callback_func typemap */
       if (obj5 && obj5 != Py_None ) {
         void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj5, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj5,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
         
         if ( cbfunction == GDALTermProgress ) {
           arg6 = GDALTermProgress;
         } else {
           if (!PyCallable_Check(obj5)) {
-            PyErr_SetString( PyExc_RuntimeError, 
+            PyErr_SetString( PyExc_RuntimeError,
               "Object given is not a Python function" );
             SWIG_fail;
           }
@@ -19923,12 +21410,14 @@ SWIGINTERN PyObject *_wrap_ComputeMedianCutPCT(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     result = (int)ComputeMedianCutPCT(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
@@ -19937,6 +21426,7 @@ SWIGINTERN PyObject *_wrap_ComputeMedianCutPCT(PyObject *SWIGUNUSEDPARM(self), P
     CPLFree(psProgressInfo);
     
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -19950,7 +21440,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_DitherRGB2PCT(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   GDALRasterBandShadow *arg2 = (GDALRasterBandShadow *) 0 ;
   GDALRasterBandShadow *arg3 = (GDALRasterBandShadow *) 0 ;
@@ -20019,16 +21509,16 @@ SWIGINTERN PyObject *_wrap_DitherRGB2PCT(PyObject *SWIGUNUSEDPARM(self), PyObjec
       /* callback_func typemap */
       if (obj5 && obj5 != Py_None ) {
         void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj5, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj5,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
         
         if ( cbfunction == GDALTermProgress ) {
           arg6 = GDALTermProgress;
         } else {
           if (!PyCallable_Check(obj5)) {
-            PyErr_SetString( PyExc_RuntimeError, 
+            PyErr_SetString( PyExc_RuntimeError,
               "Object given is not a Python function" );
             SWIG_fail;
           }
@@ -20076,12 +21566,14 @@ SWIGINTERN PyObject *_wrap_DitherRGB2PCT(PyObject *SWIGUNUSEDPARM(self), PyObjec
       CPLErrorReset();
     }
     result = (int)DitherRGB2PCT(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
@@ -20090,6 +21582,7 @@ SWIGINTERN PyObject *_wrap_DitherRGB2PCT(PyObject *SWIGUNUSEDPARM(self), PyObjec
     CPLFree(psProgressInfo);
     
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -20102,8 +21595,8 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_ReprojectImage(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+SWIGINTERN PyObject *_wrap_ReprojectImage(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   GDALDatasetShadow *arg2 = (GDALDatasetShadow *) 0 ;
   char *arg3 = (char *) NULL ;
@@ -20113,6 +21606,7 @@ SWIGINTERN PyObject *_wrap_ReprojectImage(PyObject *SWIGUNUSEDPARM(self), PyObje
   double arg7 = (double) 0.0 ;
   GDALProgressFunc arg8 = (GDALProgressFunc) NULL ;
   void *arg9 = (void *) NULL ;
+  char **arg10 = (char **) NULL ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   void *argp2 = 0 ;
@@ -20138,6 +21632,10 @@ SWIGINTERN PyObject *_wrap_ReprojectImage(PyObject *SWIGUNUSEDPARM(self), PyObje
   PyObject * obj6 = 0 ;
   PyObject * obj7 = 0 ;
   PyObject * obj8 = 0 ;
+  PyObject * obj9 = 0 ;
+  char *  kwnames[] = {
+    (char *) "src_ds",(char *) "dst_ds",(char *) "src_wkt",(char *) "dst_wkt",(char *) "eResampleAlg",(char *) "WarpMemoryLimit",(char *) "maxerror",(char *) "callback",(char *) "callback_data",(char *) "options", NULL 
+  };
   CPLErr result;
   
   /* %typemap(arginit) ( const char* callback_data=NULL)  */
@@ -20147,7 +21645,7 @@ SWIGINTERN PyObject *_wrap_ReprojectImage(PyObject *SWIGUNUSEDPARM(self), PyObje
   psProgressInfo->psPyCallback = NULL;
   psProgressInfo->psPyCallbackData = NULL;
   arg9 = psProgressInfo;
-  if (!PyArg_ParseTuple(args,(char *)"OO|OOOOOOO:ReprojectImage",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6,&obj7,&obj8)) SWIG_fail;
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO|OOOOOOOO:ReprojectImage",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6,&obj7,&obj8,&obj9)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ReprojectImage" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
@@ -20199,16 +21697,16 @@ SWIGINTERN PyObject *_wrap_ReprojectImage(PyObject *SWIGUNUSEDPARM(self), PyObje
       /* callback_func typemap */
       if (obj7 && obj7 != Py_None ) {
         void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj7, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj7,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
         
         if ( cbfunction == GDALTermProgress ) {
           arg8 = GDALTermProgress;
         } else {
           if (!PyCallable_Check(obj7)) {
-            PyErr_SetString( PyExc_RuntimeError, 
+            PyErr_SetString( PyExc_RuntimeError,
               "Object given is not a Python function" );
             SWIG_fail;
           }
@@ -20226,6 +21724,56 @@ SWIGINTERN PyObject *_wrap_ReprojectImage(PyObject *SWIGUNUSEDPARM(self), PyObje
       psProgressInfo->psPyCallbackData = obj8 ;
     }
   }
+  if (obj9) {
+    {
+      /* %typemap(in) char **options */
+      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+      if ( ! PySequence_Check(obj9) || PyUnicode_Check(obj9)
+  #if PY_VERSION_HEX < 0x03000000
+        || PyString_Check(obj9)
+  #endif
+        ) {
+        PyErr_SetString(PyExc_TypeError,"not a sequence");
+        SWIG_fail;
+      }
+      
+      Py_ssize_t size = PySequence_Size(obj9);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
+        PyObject* pyObj = PySequence_GetItem(obj9,i);
+        if (PyUnicode_Check(pyObj))
+        {
+          char *pszStr;
+          Py_ssize_t nLen;
+          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+          arg10 = CSLAddString( arg10, pszStr );
+          Py_XDECREF(pyUTF8Str);
+        }
+#if PY_VERSION_HEX >= 0x03000000
+        else if (PyBytes_Check(pyObj))
+        arg10 = CSLAddString( arg10, PyBytes_AsString(pyObj) );
+#else
+        else if (PyString_Check(pyObj))
+        arg10 = CSLAddString( arg10, PyString_AsString(pyObj) );
+#endif
+        else
+        {
+          Py_DECREF(pyObj);
+          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+          SWIG_fail;
+        }
+        Py_DECREF(pyObj);
+      }
+    }
+  }
   {
     if (!arg1) {
       SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
@@ -20240,13 +21788,15 @@ SWIGINTERN PyObject *_wrap_ReprojectImage(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)ReprojectImage(arg1,arg2,(char const *)arg3,(char const *)arg4,arg5,arg6,arg7,arg8,arg9);
+    CPL_IGNORE_RET_VAL(result = (CPLErr)ReprojectImage(arg1,arg2,(char const *)arg3,(char const *)arg4,arg5,arg6,arg7,arg8,arg9,arg10));
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
@@ -20257,6 +21807,11 @@ SWIGINTERN PyObject *_wrap_ReprojectImage(PyObject *SWIGUNUSEDPARM(self), PyObje
     CPLFree(psProgressInfo);
     
   }
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg10 );
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
@@ -20267,12 +21822,16 @@ fail:
     CPLFree(psProgressInfo);
     
   }
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg10 );
+  }
   return NULL;
 }
 
 
 SWIGINTERN PyObject *_wrap_ComputeProximity(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   GDALRasterBandShadow *arg2 = (GDALRasterBandShadow *) 0 ;
   char **arg3 = (char **) NULL ;
@@ -20323,8 +21882,12 @@ SWIGINTERN PyObject *_wrap_ComputeProximity(PyObject *SWIGUNUSEDPARM(self), PyOb
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj2);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj2);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj2,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -20362,16 +21925,16 @@ SWIGINTERN PyObject *_wrap_ComputeProximity(PyObject *SWIGUNUSEDPARM(self), PyOb
       /* callback_func typemap */
       if (obj3 && obj3 != Py_None ) {
         void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj3, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
         
         if ( cbfunction == GDALTermProgress ) {
           arg4 = GDALTermProgress;
         } else {
           if (!PyCallable_Check(obj3)) {
-            PyErr_SetString( PyExc_RuntimeError, 
+            PyErr_SetString( PyExc_RuntimeError,
               "Object given is not a Python function" );
             SWIG_fail;
           }
@@ -20404,12 +21967,14 @@ SWIGINTERN PyObject *_wrap_ComputeProximity(PyObject *SWIGUNUSEDPARM(self), PyOb
       CPLErrorReset();
     }
     result = (int)ComputeProximity(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
@@ -20422,6 +21987,7 @@ SWIGINTERN PyObject *_wrap_ComputeProximity(PyObject *SWIGUNUSEDPARM(self), PyOb
     CPLFree(psProgressInfo);
     
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -20439,7 +22005,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_RasterizeLayer(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   int arg2 ;
   int *arg3 = (int *) 0 ;
@@ -20491,7 +22057,12 @@ SWIGINTERN PyObject *_wrap_RasterizeLayer(PyObject *SWIGUNUSEDPARM(self), PyObje
       PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
-    arg2 = PySequence_Size(obj1);
+    Py_ssize_t size = PySequence_Size(obj1);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    arg2 = (int)size;
     arg3 = (int*) malloc(arg2*sizeof(int));
     for( int i = 0; i<arg2; i++ ) {
       PyObject *o = PySequence_GetItem(obj1,i);
@@ -20528,7 +22099,12 @@ SWIGINTERN PyObject *_wrap_RasterizeLayer(PyObject *SWIGUNUSEDPARM(self), PyObje
         PyErr_SetString(PyExc_TypeError, "not a sequence");
         SWIG_fail;
       }
-      arg7 = PySequence_Size(obj5);
+      Py_ssize_t size = PySequence_Size(obj5);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      arg7 = (int)size;
       arg8 = (double*) malloc(arg7*sizeof(double));
       for( int i = 0; i<arg7; i++ ) {
         PyObject *o = PySequence_GetItem(obj5,i);
@@ -20554,8 +22130,12 @@ SWIGINTERN PyObject *_wrap_RasterizeLayer(PyObject *SWIGUNUSEDPARM(self), PyObje
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj6);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj6);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj6,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -20593,16 +22173,16 @@ SWIGINTERN PyObject *_wrap_RasterizeLayer(PyObject *SWIGUNUSEDPARM(self), PyObje
       /* callback_func typemap */
       if (obj7 && obj7 != Py_None ) {
         void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj7, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj7,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
         
         if ( cbfunction == GDALTermProgress ) {
           arg10 = GDALTermProgress;
         } else {
           if (!PyCallable_Check(obj7)) {
-            PyErr_SetString( PyExc_RuntimeError, 
+            PyErr_SetString( PyExc_RuntimeError,
               "Object given is not a Python function" );
             SWIG_fail;
           }
@@ -20635,12 +22215,14 @@ SWIGINTERN PyObject *_wrap_RasterizeLayer(PyObject *SWIGUNUSEDPARM(self), PyObje
       CPLErrorReset();
     }
     result = (int)RasterizeLayer(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
@@ -20665,6 +22247,7 @@ SWIGINTERN PyObject *_wrap_RasterizeLayer(PyObject *SWIGUNUSEDPARM(self), PyObje
     CPLFree(psProgressInfo);
     
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -20694,7 +22277,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Polygonize(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   GDALRasterBandShadow *arg2 = (GDALRasterBandShadow *) 0 ;
   OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
@@ -20763,8 +22346,12 @@ SWIGINTERN PyObject *_wrap_Polygonize(PyObject *SWIGUNUSEDPARM(self), PyObject *
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj4);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj4);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj4,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -20802,16 +22389,16 @@ SWIGINTERN PyObject *_wrap_Polygonize(PyObject *SWIGUNUSEDPARM(self), PyObject *
       /* callback_func typemap */
       if (obj5 && obj5 != Py_None ) {
         void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj5, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj5,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
         
         if ( cbfunction == GDALTermProgress ) {
           arg6 = GDALTermProgress;
         } else {
           if (!PyCallable_Check(obj5)) {
-            PyErr_SetString( PyExc_RuntimeError, 
+            PyErr_SetString( PyExc_RuntimeError,
               "Object given is not a Python function" );
             SWIG_fail;
           }
@@ -20844,12 +22431,14 @@ SWIGINTERN PyObject *_wrap_Polygonize(PyObject *SWIGUNUSEDPARM(self), PyObject *
       CPLErrorReset();
     }
     result = (int)Polygonize(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
@@ -20862,6 +22451,7 @@ SWIGINTERN PyObject *_wrap_Polygonize(PyObject *SWIGUNUSEDPARM(self), PyObject *
     CPLFree(psProgressInfo);
     
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -20878,11 +22468,11 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_FillNodata(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+SWIGINTERN PyObject *_wrap_FPolygonize(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   GDALRasterBandShadow *arg2 = (GDALRasterBandShadow *) 0 ;
-  double arg3 ;
+  OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
   int arg4 ;
   char **arg5 = (char **) NULL ;
   GDALProgressFunc arg6 = (GDALProgressFunc) NULL ;
@@ -20891,8 +22481,8 @@ SWIGINTERN PyObject *_wrap_FillNodata(PyObject *SWIGUNUSEDPARM(self), PyObject *
   int res1 = 0 ;
   void *argp2 = 0 ;
   int res2 = 0 ;
-  double val3 ;
-  int ecode3 = 0 ;
+  void *argp3 = 0 ;
+  int res3 = 0 ;
   int val4 ;
   int ecode4 = 0 ;
   PyObject * obj0 = 0 ;
@@ -20903,7 +22493,7 @@ SWIGINTERN PyObject *_wrap_FillNodata(PyObject *SWIGUNUSEDPARM(self), PyObject *
   PyObject * obj5 = 0 ;
   PyObject * obj6 = 0 ;
   char *  kwnames[] = {
-    (char *) "targetBand",(char *) "maskBand",(char *) "maxSearchDist",(char *) "smoothingIterations",(char *) "options",(char *) "callback",(char *) "callback_data", NULL 
+    (char *) "srcBand",(char *) "maskBand",(char *) "outLayer",(char *) "iPixValField",(char *) "options",(char *) "callback",(char *) "callback_data", NULL 
   };
   int result;
   
@@ -20914,18 +22504,210 @@ SWIGINTERN PyObject *_wrap_FillNodata(PyObject *SWIGUNUSEDPARM(self), PyObject *
   psProgressInfo->psPyCallback = NULL;
   psProgressInfo->psPyCallbackData = NULL;
   arg7 = psProgressInfo;
-  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOOO|OOO:FillNodata",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6)) SWIG_fail;
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOOO|OOO:FPolygonize",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FillNodata" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FPolygonize" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
   }
   arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
   res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "FillNodata" "', argument " "2"" of type '" "GDALRasterBandShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "FPolygonize" "', argument " "2"" of type '" "GDALRasterBandShadow *""'"); 
   }
   arg2 = reinterpret_cast< GDALRasterBandShadow * >(argp2);
-  ecode3 = SWIG_AsVal_double(obj2, &val3);
+  res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "FPolygonize" "', argument " "3"" of type '" "OGRLayerShadow *""'"); 
+  }
+  arg3 = reinterpret_cast< OGRLayerShadow * >(argp3);
+  ecode4 = SWIG_AsVal_int(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "FPolygonize" "', argument " "4"" of type '" "int""'");
+  } 
+  arg4 = static_cast< int >(val4);
+  if (obj4) {
+    {
+      /* %typemap(in) char **options */
+      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+      if ( ! PySequence_Check(obj4) || PyUnicode_Check(obj4)
+  #if PY_VERSION_HEX < 0x03000000
+        || PyString_Check(obj4)
+  #endif
+        ) {
+        PyErr_SetString(PyExc_TypeError,"not a sequence");
+        SWIG_fail;
+      }
+      
+      Py_ssize_t size = PySequence_Size(obj4);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
+        PyObject* pyObj = PySequence_GetItem(obj4,i);
+        if (PyUnicode_Check(pyObj))
+        {
+          char *pszStr;
+          Py_ssize_t nLen;
+          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+          arg5 = CSLAddString( arg5, pszStr );
+          Py_XDECREF(pyUTF8Str);
+        }
+#if PY_VERSION_HEX >= 0x03000000
+        else if (PyBytes_Check(pyObj))
+        arg5 = CSLAddString( arg5, PyBytes_AsString(pyObj) );
+#else
+        else if (PyString_Check(pyObj))
+        arg5 = CSLAddString( arg5, PyString_AsString(pyObj) );
+#endif
+        else
+        {
+          Py_DECREF(pyObj);
+          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+          SWIG_fail;
+        }
+        Py_DECREF(pyObj);
+      }
+    }
+  }
+  if (obj5) {
+    {
+      /* %typemap(in) (GDALProgressFunc callback = NULL) */
+      /* callback_func typemap */
+      if (obj5 && obj5 != Py_None ) {
+        void* cbfunction = NULL;
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj5,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
+        
+        if ( cbfunction == GDALTermProgress ) {
+          arg6 = GDALTermProgress;
+        } else {
+          if (!PyCallable_Check(obj5)) {
+            PyErr_SetString( PyExc_RuntimeError,
+              "Object given is not a Python function" );
+            SWIG_fail;
+          }
+          psProgressInfo->psPyCallback = obj5;
+          arg6 = PyProgressProxy;
+        }
+        
+      }
+      
+    }
+  }
+  if (obj6) {
+    {
+      /* %typemap(in) ( void* callback_data=NULL)  */
+      psProgressInfo->psPyCallbackData = obj6 ;
+    }
+  }
+  {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if (!arg3) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)FPolygonize(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg5 );
+  }
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg5 );
+  }
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_FillNodata(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
+  GDALRasterBandShadow *arg2 = (GDALRasterBandShadow *) 0 ;
+  double arg3 ;
+  int arg4 ;
+  char **arg5 = (char **) NULL ;
+  GDALProgressFunc arg6 = (GDALProgressFunc) NULL ;
+  void *arg7 = (void *) NULL ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  double val3 ;
+  int ecode3 = 0 ;
+  int val4 ;
+  int ecode4 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  PyObject * obj6 = 0 ;
+  char *  kwnames[] = {
+    (char *) "targetBand",(char *) "maskBand",(char *) "maxSearchDist",(char *) "smoothingIterations",(char *) "options",(char *) "callback",(char *) "callback_data", NULL 
+  };
+  int result;
+  
+  /* %typemap(arginit) ( const char* callback_data=NULL)  */
+  PyProgressData *psProgressInfo;
+  psProgressInfo = (PyProgressData *) CPLCalloc(1,sizeof(PyProgressData));
+  psProgressInfo->nLastReported = -1;
+  psProgressInfo->psPyCallback = NULL;
+  psProgressInfo->psPyCallbackData = NULL;
+  arg7 = psProgressInfo;
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOOO|OOO:FillNodata",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FillNodata" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "FillNodata" "', argument " "2"" of type '" "GDALRasterBandShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< GDALRasterBandShadow * >(argp2);
+  ecode3 = SWIG_AsVal_double(obj2, &val3);
   if (!SWIG_IsOK(ecode3)) {
     SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "FillNodata" "', argument " "3"" of type '" "double""'");
   } 
@@ -20948,8 +22730,12 @@ SWIGINTERN PyObject *_wrap_FillNodata(PyObject *SWIGUNUSEDPARM(self), PyObject *
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj4);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj4);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj4,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -20987,16 +22773,16 @@ SWIGINTERN PyObject *_wrap_FillNodata(PyObject *SWIGUNUSEDPARM(self), PyObject *
       /* callback_func typemap */
       if (obj5 && obj5 != Py_None ) {
         void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj5, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj5,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
         
         if ( cbfunction == GDALTermProgress ) {
           arg6 = GDALTermProgress;
         } else {
           if (!PyCallable_Check(obj5)) {
-            PyErr_SetString( PyExc_RuntimeError, 
+            PyErr_SetString( PyExc_RuntimeError,
               "Object given is not a Python function" );
             SWIG_fail;
           }
@@ -21024,12 +22810,14 @@ SWIGINTERN PyObject *_wrap_FillNodata(PyObject *SWIGUNUSEDPARM(self), PyObject *
       CPLErrorReset();
     }
     result = (int)FillNodata(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
@@ -21042,6 +22830,7 @@ SWIGINTERN PyObject *_wrap_FillNodata(PyObject *SWIGUNUSEDPARM(self), PyObject *
     CPLFree(psProgressInfo);
     
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -21059,7 +22848,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SieveFilter(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   GDALRasterBandShadow *arg2 = (GDALRasterBandShadow *) 0 ;
   GDALRasterBandShadow *arg3 = (GDALRasterBandShadow *) 0 ;
@@ -21139,8 +22928,12 @@ SWIGINTERN PyObject *_wrap_SieveFilter(PyObject *SWIGUNUSEDPARM(self), PyObject
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj5);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj5);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj5,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -21178,16 +22971,16 @@ SWIGINTERN PyObject *_wrap_SieveFilter(PyObject *SWIGUNUSEDPARM(self), PyObject
       /* callback_func typemap */
       if (obj6 && obj6 != Py_None ) {
         void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj6, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj6,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
         
         if ( cbfunction == GDALTermProgress ) {
           arg7 = GDALTermProgress;
         } else {
           if (!PyCallable_Check(obj6)) {
-            PyErr_SetString( PyExc_RuntimeError, 
+            PyErr_SetString( PyExc_RuntimeError,
               "Object given is not a Python function" );
             SWIG_fail;
           }
@@ -21220,12 +23013,14 @@ SWIGINTERN PyObject *_wrap_SieveFilter(PyObject *SWIGUNUSEDPARM(self), PyObject
       CPLErrorReset();
     }
     result = (int)SieveFilter(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
@@ -21238,6 +23033,7 @@ SWIGINTERN PyObject *_wrap_SieveFilter(PyObject *SWIGUNUSEDPARM(self), PyObject
     CPLFree(psProgressInfo);
     
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -21255,7 +23051,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_RegenerateOverviews(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   int arg2 ;
   GDALRasterBandShadow **arg3 = (GDALRasterBandShadow **) 0 ;
@@ -21296,12 +23092,17 @@ SWIGINTERN PyObject *_wrap_RegenerateOverviews(PyObject *SWIGUNUSEDPARM(self), P
       PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
-    arg2 = PySequence_Size(obj1);
+    Py_ssize_t size = PySequence_Size(obj1);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    arg2 = (int)size;
     arg3 = (GDALRasterBandShadow**) CPLMalloc(arg2*sizeof(GDALRasterBandShadow*));
     
     for( int i = 0; i<arg2; i++ ) {
       PyObject *o = PySequence_GetItem(obj1,i);
-#if 0x010340 <= 0x010337
+#if 0x020012 <= 0x010337
       PySwigObject *sobj = SWIG_Python_GetSwigThis(o);
 #else
       SwigPyObject *sobj = SWIG_Python_GetSwigThis(o);
@@ -21330,16 +23131,16 @@ SWIGINTERN PyObject *_wrap_RegenerateOverviews(PyObject *SWIGUNUSEDPARM(self), P
       /* callback_func typemap */
       if (obj3 && obj3 != Py_None ) {
         void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj3, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
         
         if ( cbfunction == GDALTermProgress ) {
           arg5 = GDALTermProgress;
         } else {
           if (!PyCallable_Check(obj3)) {
-            PyErr_SetString( PyExc_RuntimeError, 
+            PyErr_SetString( PyExc_RuntimeError,
               "Object given is not a Python function" );
             SWIG_fail;
           }
@@ -21367,12 +23168,14 @@ SWIGINTERN PyObject *_wrap_RegenerateOverviews(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     result = (int)RegenerateOverviews(arg1,arg2,arg3,(char const *)arg4,arg5,arg6);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
@@ -21386,6 +23189,7 @@ SWIGINTERN PyObject *_wrap_RegenerateOverviews(PyObject *SWIGUNUSEDPARM(self), P
     CPLFree(psProgressInfo);
     
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -21404,7 +23208,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_RegenerateOverview(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   GDALRasterBandShadow *arg2 = (GDALRasterBandShadow *) 0 ;
   char *arg3 = (char *) "average" ;
@@ -21458,16 +23262,16 @@ SWIGINTERN PyObject *_wrap_RegenerateOverview(PyObject *SWIGUNUSEDPARM(self), Py
       /* callback_func typemap */
       if (obj3 && obj3 != Py_None ) {
         void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj3, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
         
         if ( cbfunction == GDALTermProgress ) {
           arg4 = GDALTermProgress;
         } else {
           if (!PyCallable_Check(obj3)) {
-            PyErr_SetString( PyExc_RuntimeError, 
+            PyErr_SetString( PyExc_RuntimeError,
               "Object given is not a Python function" );
             SWIG_fail;
           }
@@ -21500,12 +23304,14 @@ SWIGINTERN PyObject *_wrap_RegenerateOverview(PyObject *SWIGUNUSEDPARM(self), Py
       CPLErrorReset();
     }
     result = (int)RegenerateOverview(arg1,arg2,(char const *)arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
@@ -21515,6 +23321,7 @@ SWIGINTERN PyObject *_wrap_RegenerateOverview(PyObject *SWIGUNUSEDPARM(self), Py
     CPLFree(psProgressInfo);
     
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
@@ -21529,7 +23336,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_ContourGenerate(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -21604,7 +23411,12 @@ SWIGINTERN PyObject *_wrap_ContourGenerate(PyObject *SWIGUNUSEDPARM(self), PyObj
       PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
-    arg4 = PySequence_Size(obj3);
+    Py_ssize_t size = PySequence_Size(obj3);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    arg4 = (int)size;
     arg5 = (double*) malloc(arg4*sizeof(double));
     for( int i = 0; i<arg4; i++ ) {
       PyObject *o = PySequence_GetItem(obj3,i);
@@ -21647,16 +23459,16 @@ SWIGINTERN PyObject *_wrap_ContourGenerate(PyObject *SWIGUNUSEDPARM(self), PyObj
       /* callback_func typemap */
       if (obj9 && obj9 != Py_None ) {
         void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj9, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj9,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
         
         if ( cbfunction == GDALTermProgress ) {
           arg11 = GDALTermProgress;
         } else {
           if (!PyCallable_Check(obj9)) {
-            PyErr_SetString( PyExc_RuntimeError, 
+            PyErr_SetString( PyExc_RuntimeError,
               "Object given is not a Python function" );
             SWIG_fail;
           }
@@ -21689,12 +23501,14 @@ SWIGINTERN PyObject *_wrap_ContourGenerate(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     result = (int)ContourGenerate(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
@@ -21709,6 +23523,7 @@ SWIGINTERN PyObject *_wrap_ContourGenerate(PyObject *SWIGUNUSEDPARM(self), PyObj
     CPLFree(psProgressInfo);
     
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -21728,7 +23543,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_AutoCreateWarpedVRT(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   char *arg3 = (char *) 0 ;
@@ -21797,16 +23612,19 @@ SWIGINTERN PyObject *_wrap_AutoCreateWarpedVRT(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     result = (GDALDatasetShadow *)AutoCreateWarpedVRT(arg1,(char const *)arg2,(char const *)arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_POINTER_OWN |  0 );
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -21815,67 +23633,167 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_new_Transformer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-  GDALDatasetShadow *arg2 = (GDALDatasetShadow *) 0 ;
-  char **arg3 = (char **) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
+SWIGINTERN PyObject *_wrap_CreatePansharpenedVRT(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  char *arg1 = (char *) 0 ;
+  GDALRasterBandShadow *arg2 = (GDALRasterBandShadow *) 0 ;
+  int arg3 ;
+  GDALRasterBandShadow **arg4 = (GDALRasterBandShadow **) 0 ;
+  int res1 ;
+  char *buf1 = 0 ;
+  int alloc1 = 0 ;
   void *argp2 = 0 ;
   int res2 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   PyObject * obj2 = 0 ;
-  GDALTransformerInfoShadow *result = 0 ;
+  GDALDatasetShadow *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOO:new_Transformer",&obj0,&obj1,&obj2)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"OOO:CreatePansharpenedVRT",&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, NULL, &alloc1);
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_Transformer" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CreatePansharpenedVRT" "', argument " "1"" of type '" "char const *""'");
   }
-  arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
+  arg1 = reinterpret_cast< char * >(buf1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "new_Transformer" "', argument " "2"" of type '" "GDALDatasetShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "CreatePansharpenedVRT" "', argument " "2"" of type '" "GDALRasterBandShadow *""'"); 
   }
-  arg2 = reinterpret_cast< GDALDatasetShadow * >(argp2);
+  arg2 = reinterpret_cast< GDALRasterBandShadow * >(argp2);
   {
-    /* %typemap(in) char **options */
-    /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
-    if ( ! PySequence_Check(obj2) || PyUnicode_Check(obj2)
-  #if PY_VERSION_HEX < 0x03000000
-      || PyString_Check(obj2)
-  #endif
-      ) {
-      PyErr_SetString(PyExc_TypeError,"not a sequence");
+    /*  OBJECT_LIST_INPUT %typemap(in) (int itemcount, GDALRasterBandShadow *optional_##GDALRasterBandShadow)*/
+    if ( !PySequence_Check(obj2) ) {
+      PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
+    Py_ssize_t size = PySequence_Size(obj2);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    arg3 = (int)size;
+    arg4 = (GDALRasterBandShadow**) CPLMalloc(arg3*sizeof(GDALRasterBandShadow*));
     
-    int size = PySequence_Size(obj2);
-    for (int i = 0; i < size; i++) {
-      PyObject* pyObj = PySequence_GetItem(obj2,i);
-      if (PyUnicode_Check(pyObj))
-      {
-        char *pszStr;
-        Py_ssize_t nLen;
-        PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
-#if PY_VERSION_HEX >= 0x03000000
-        PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+    for( int i = 0; i<arg3; i++ ) {
+      PyObject *o = PySequence_GetItem(obj2,i);
+#if 0x020012 <= 0x010337
+      PySwigObject *sobj = SWIG_Python_GetSwigThis(o);
 #else
-        PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+      SwigPyObject *sobj = SWIG_Python_GetSwigThis(o);
 #endif
-        arg3 = CSLAddString( arg3, pszStr );
-        Py_XDECREF(pyUTF8Str);
+      GDALRasterBandShadow* rawobjectpointer = NULL;
+      if (!sobj) {
+        Py_DECREF(o);
+        SWIG_fail;
       }
-#if PY_VERSION_HEX >= 0x03000000
-      else if (PyBytes_Check(pyObj))
-      arg3 = CSLAddString( arg3, PyBytes_AsString(pyObj) );
-#else
-      else if (PyString_Check(pyObj))
-      arg3 = CSLAddString( arg3, PyString_AsString(pyObj) );
-#endif
-      else
+      rawobjectpointer = (GDALRasterBandShadow*) sobj->ptr;
+      arg4[i] = rawobjectpointer;
+      Py_DECREF(o);
+      
+    }
+  }
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (GDALDatasetShadow *)CreatePansharpenedVRT((char const *)arg1,arg2,arg3,arg4);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_POINTER_OWN |  0 );
+  if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+  {
+    /* OBJECT_LIST_INPUT %typemap(freearg) (int object_list_count, GDALRasterBandShadow **poObjects)*/
+    CPLFree( arg4 );
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+  {
+    /* OBJECT_LIST_INPUT %typemap(freearg) (int object_list_count, GDALRasterBandShadow **poObjects)*/
+    CPLFree( arg4 );
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_new_Transformer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
+  GDALDatasetShadow *arg2 = (GDALDatasetShadow *) 0 ;
+  char **arg3 = (char **) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  GDALTransformerInfoShadow *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOO:new_Transformer",&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_Transformer" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "new_Transformer" "', argument " "2"" of type '" "GDALDatasetShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< GDALDatasetShadow * >(argp2);
+  {
+    /* %typemap(in) char **options */
+    /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+    if ( ! PySequence_Check(obj2) || PyUnicode_Check(obj2)
+  #if PY_VERSION_HEX < 0x03000000
+      || PyString_Check(obj2)
+  #endif
+      ) {
+      PyErr_SetString(PyExc_TypeError,"not a sequence");
+      SWIG_fail;
+    }
+    
+    Py_ssize_t size = PySequence_Size(obj2);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    for (int i = 0; i < (int)size; i++) {
+      PyObject* pyObj = PySequence_GetItem(obj2,i);
+      if (PyUnicode_Check(pyObj))
+      {
+        char *pszStr;
+        Py_ssize_t nLen;
+        PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+        PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+        PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+        arg3 = CSLAddString( arg3, pszStr );
+        Py_XDECREF(pyUTF8Str);
+      }
+#if PY_VERSION_HEX >= 0x03000000
+      else if (PyBytes_Check(pyObj))
+      arg3 = CSLAddString( arg3, PyBytes_AsString(pyObj) );
+#else
+      else if (PyString_Check(pyObj))
+      arg3 = CSLAddString( arg3, PyString_AsString(pyObj) );
+#endif
+      else
       {
         Py_DECREF(pyObj);
         PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
@@ -21889,18 +23807,21 @@ SWIGINTERN PyObject *_wrap_new_Transformer(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     result = (GDALTransformerInfoShadow *)new_GDALTransformerInfoShadow(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALTransformerInfoShadow, SWIG_POINTER_NEW |  0 );
   {
     /* %typemap(freearg) char **options */
     CSLDestroy( arg3 );
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -21912,7 +23833,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_delete_Transformer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALTransformerInfoShadow *arg1 = (GDALTransformerInfoShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -21929,14 +23850,17 @@ SWIGINTERN PyObject *_wrap_delete_Transformer(PyObject *SWIGUNUSEDPARM(self), Py
       CPLErrorReset();
     }
     delete_GDALTransformerInfoShadow(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -21944,7 +23868,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Transformer_TransformPoint__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALTransformerInfoShadow *arg1 = (GDALTransformerInfoShadow *) 0 ;
   int arg2 ;
   double *arg3 ;
@@ -21976,7 +23900,7 @@ SWIGINTERN PyObject *_wrap_Transformer_TransformPoint__SWIG_0(PyObject *SWIGUNUS
       PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
-    int seq_size = PySequence_Size(obj2);
+    Py_ssize_t seq_size = PySequence_Size(obj2);
     if ( seq_size != 3 ) {
       PyErr_SetString(PyExc_TypeError, "sequence must have length ##size");
       SWIG_fail;
@@ -21998,12 +23922,14 @@ SWIGINTERN PyObject *_wrap_Transformer_TransformPoint__SWIG_0(PyObject *SWIGUNUS
       CPLErrorReset();
     }
     result = (int)GDALTransformerInfoShadow_TransformPoint__SWIG_0(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
@@ -22011,6 +23937,7 @@ SWIGINTERN PyObject *_wrap_Transformer_TransformPoint__SWIG_0(PyObject *SWIGUNUS
     PyObject *out = CreateTupleFromDoubleArray( arg3, 3 );
     resultobj = t_output_helper(resultobj,out);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22018,7 +23945,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Transformer_TransformPoint__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALTransformerInfoShadow *arg1 = (GDALTransformerInfoShadow *) 0 ;
   double *arg2 ;
   int arg3 ;
@@ -22045,6 +23972,7 @@ SWIGINTERN PyObject *_wrap_Transformer_TransformPoint__SWIG_1(PyObject *SWIGUNUS
   
   {
     /* %typemap(in,numinputs=0) (double argout2[ANY]) */
+    memset(argout2, 0, sizeof(argout2));
     arg2 = argout2;
   }
   if (!PyArg_ParseTuple(args,(char *)"OOOO|O:Transformer_TransformPoint",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
@@ -22080,12 +24008,14 @@ SWIGINTERN PyObject *_wrap_Transformer_TransformPoint__SWIG_1(PyObject *SWIGUNUS
       CPLErrorReset();
     }
     result = (int)GDALTransformerInfoShadow_TransformPoint__SWIG_1(arg1,arg2,arg3,arg4,arg5,arg6);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
@@ -22093,6 +24023,7 @@ SWIGINTERN PyObject *_wrap_Transformer_TransformPoint__SWIG_1(PyObject *SWIGUNUS
     PyObject *out = CreateTupleFromDoubleArray( arg2, 3 );
     resultobj = t_output_helper(resultobj,out);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22104,9 +24035,9 @@ SWIGINTERN PyObject *_wrap_Transformer_TransformPoint(PyObject *self, PyObject *
   PyObject *argv[6];
   int ii;
   
-  if (!PyTuple_Check(args)) SWIG_fail;
+  if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
   argc = (int)PyObject_Length(args);
-  for (ii = 0; (ii < argc) && (ii < 5); ii++) {
+  for (ii = 0; (ii < 5) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
   if (argc == 3) {
@@ -22167,16 +24098,16 @@ SWIGINTERN PyObject *_wrap_Transformer_TransformPoint(PyObject *self, PyObject *
   }
   
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Transformer_TransformPoint'.\n"
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'Transformer_TransformPoint'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    TransformPoint(GDALTransformerInfoShadow *,int,double [3])\n"
-    "    TransformPoint(GDALTransformerInfoShadow *,double [3],int,double,double,double)\n");
-  return NULL;
+    "    GDALTransformerInfoShadow::TransformPoint(int,double [3])\n"
+    "    GDALTransformerInfoShadow::TransformPoint(double [3],int,double,double,double)\n");
+  return 0;
 }
 
 
 SWIGINTERN PyObject *_wrap_Transformer_TransformPoints(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALTransformerInfoShadow *arg1 = (GDALTransformerInfoShadow *) 0 ;
   int arg2 ;
   int arg3 ;
@@ -22211,7 +24142,12 @@ SWIGINTERN PyObject *_wrap_Transformer_TransformPoints(PyObject *SWIGUNUSEDPARM(
       SWIG_fail;
     }
     
-    arg3 = PySequence_Size(obj2);
+    Py_ssize_t size = PySequence_Size(obj2);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    arg3 = (int)size;
     arg4 = (double*) VSIMalloc(arg3*sizeof(double));
     arg5 = (double*) VSIMalloc(arg3*sizeof(double));
     arg6 = (double*) VSIMalloc(arg3*sizeof(double));
@@ -22232,12 +24168,14 @@ SWIGINTERN PyObject *_wrap_Transformer_TransformPoints(PyObject *SWIGUNUSEDPARM(
       CPLErrorReset();
     }
     result = (int)GDALTransformerInfoShadow_TransformPoints(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
@@ -22264,6 +24202,7 @@ SWIGINTERN PyObject *_wrap_Transformer_TransformPoints(PyObject *SWIGUNUSEDPARM(
     VSIFree(arg6);
     VSIFree(arg7);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -22278,7 +24217,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Transformer_TransformGeolocations(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALTransformerInfoShadow *arg1 = (GDALTransformerInfoShadow *) 0 ;
   GDALRasterBandShadow *arg2 = (GDALRasterBandShadow *) 0 ;
   GDALRasterBandShadow *arg3 = (GDALRasterBandShadow *) 0 ;
@@ -22340,16 +24279,16 @@ SWIGINTERN PyObject *_wrap_Transformer_TransformGeolocations(PyObject *SWIGUNUSE
       /* callback_func typemap */
       if (obj4 && obj4 != Py_None ) {
         void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj4, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj4,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
         
         if ( cbfunction == GDALTermProgress ) {
           arg5 = GDALTermProgress;
         } else {
           if (!PyCallable_Check(obj4)) {
-            PyErr_SetString( PyExc_RuntimeError, 
+            PyErr_SetString( PyExc_RuntimeError,
               "Object given is not a Python function" );
             SWIG_fail;
           }
@@ -22380,8 +24319,12 @@ SWIGINTERN PyObject *_wrap_Transformer_TransformGeolocations(PyObject *SWIGUNUSE
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj6);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj6);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj6,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -22433,12 +24376,14 @@ SWIGINTERN PyObject *_wrap_Transformer_TransformGeolocations(PyObject *SWIGUNUSE
       CPLErrorReset();
     }
     result = (int)GDALTransformerInfoShadow_TransformGeolocations(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
@@ -22451,6 +24396,7 @@ SWIGINTERN PyObject *_wrap_Transformer_TransformGeolocations(PyObject *SWIGUNUSE
     /* %typemap(freearg) char **options */
     CSLDestroy( arg7 );
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -22475,7 +24421,7 @@ SWIGINTERN PyObject *Transformer_swigregister(PyObject *SWIGUNUSEDPARM(self), Py
 }
 
 SWIGINTERN PyObject *_wrap_ApplyGeoTransform(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   double *arg1 ;
   double arg2 ;
   double arg3 ;
@@ -22504,7 +24450,7 @@ SWIGINTERN PyObject *_wrap_ApplyGeoTransform(PyObject *SWIGUNUSEDPARM(self), PyO
       PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
-    int seq_size = PySequence_Size(obj0);
+    Py_ssize_t seq_size = PySequence_Size(obj0);
     if ( seq_size != 6 ) {
       PyErr_SetString(PyExc_TypeError, "sequence must have length ##size");
       SWIG_fail;
@@ -22536,26 +24482,29 @@ SWIGINTERN PyObject *_wrap_ApplyGeoTransform(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     GDALApplyGeoTransform(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
-  if (SWIG_IsTmpObj(res4)) {
+  if (ReturnSame(SWIG_IsTmpObj(res4))) {
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_double((*arg4)));
   } else {
     int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_double, new_flags));
   }
-  if (SWIG_IsTmpObj(res5)) {
+  if (ReturnSame(SWIG_IsTmpObj(res5))) {
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_double((*arg5)));
   } else {
     int new_flags = SWIG_IsNewObj(res5) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg5), SWIGTYPE_p_double, new_flags));
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22563,7 +24512,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_InvGeoTransform(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   double *arg1 ;
   double *arg2 ;
   double argin1[6] ;
@@ -22573,6 +24522,7 @@ SWIGINTERN PyObject *_wrap_InvGeoTransform(PyObject *SWIGUNUSEDPARM(self), PyObj
   
   {
     /* %typemap(in,numinputs=0) (double argout2[ANY]) */
+    memset(argout2, 0, sizeof(argout2));
     arg2 = argout2;
   }
   if (!PyArg_ParseTuple(args,(char *)"O:InvGeoTransform",&obj0)) SWIG_fail;
@@ -22583,7 +24533,7 @@ SWIGINTERN PyObject *_wrap_InvGeoTransform(PyObject *SWIGUNUSEDPARM(self), PyObj
       PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
-    int seq_size = PySequence_Size(obj0);
+    Py_ssize_t seq_size = PySequence_Size(obj0);
     if ( seq_size != 6 ) {
       PyErr_SetString(PyExc_TypeError, "sequence must have length ##size");
       SWIG_fail;
@@ -22604,13 +24554,15 @@ SWIGINTERN PyObject *_wrap_InvGeoTransform(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = GDALInvGeoTransform(arg1,arg2);
+    result = (RETURN_NONE)GDALInvGeoTransform(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   /*%typemap(out) IF_FALSE_RETURN_NONE */
   {
@@ -22630,6 +24582,7 @@ SWIGINTERN PyObject *_wrap_InvGeoTransform(PyObject *SWIGUNUSEDPARM(self), PyObj
       Py_INCREF(resultobj);
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22637,7 +24590,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_VersionInfo(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) "VERSION_NUM" ;
   int res1 ;
   char *buf1 = 0 ;
@@ -22658,15 +24611,18 @@ SWIGINTERN PyObject *_wrap_VersionInfo(PyObject *SWIGUNUSEDPARM(self), PyObject
       CPLErrorReset();
     }
     result = (char *)GDALVersionInfo((char const *)arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
@@ -22675,7 +24631,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_AllRegister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   
   if (!PyArg_ParseTuple(args,(char *)":AllRegister")) SWIG_fail;
   {
@@ -22683,14 +24639,17 @@ SWIGINTERN PyObject *_wrap_AllRegister(PyObject *SWIGUNUSEDPARM(self), PyObject
       CPLErrorReset();
     }
     GDALAllRegister();
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22698,7 +24657,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GDALDestroyDriverManager(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   
   if (!PyArg_ParseTuple(args,(char *)":GDALDestroyDriverManager")) SWIG_fail;
   {
@@ -22706,14 +24665,17 @@ SWIGINTERN PyObject *_wrap_GDALDestroyDriverManager(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     GDALDestroyDriverManager();
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22721,7 +24683,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GetCacheMax(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GIntBig result;
   
   if (!PyArg_ParseTuple(args,(char *)":GetCacheMax")) SWIG_fail;
@@ -22730,12 +24692,14 @@ SWIGINTERN PyObject *_wrap_GetCacheMax(PyObject *SWIGUNUSEDPARM(self), PyObject
       CPLErrorReset();
     }
     result = wrapper_GDALGetCacheMax();
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     char szTmp[32];
@@ -22746,6 +24710,7 @@ SWIGINTERN PyObject *_wrap_GetCacheMax(PyObject *SWIGUNUSEDPARM(self), PyObject
     resultobj = PyInt_FromString(szTmp, NULL, 10);
 #endif
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22753,7 +24718,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GetCacheUsed(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GIntBig result;
   
   if (!PyArg_ParseTuple(args,(char *)":GetCacheUsed")) SWIG_fail;
@@ -22762,12 +24727,14 @@ SWIGINTERN PyObject *_wrap_GetCacheUsed(PyObject *SWIGUNUSEDPARM(self), PyObject
       CPLErrorReset();
     }
     result = wrapper_GDALGetCacheUsed();
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     char szTmp[32];
@@ -22778,6 +24745,7 @@ SWIGINTERN PyObject *_wrap_GetCacheUsed(PyObject *SWIGUNUSEDPARM(self), PyObject
     resultobj = PyInt_FromString(szTmp, NULL, 10);
 #endif
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22785,7 +24753,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SetCacheMax(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GIntBig arg1 ;
   PyObject * obj0 = 0 ;
   
@@ -22803,14 +24771,17 @@ SWIGINTERN PyObject *_wrap_SetCacheMax(PyObject *SWIGUNUSEDPARM(self), PyObject
       CPLErrorReset();
     }
     wrapper_GDALSetCacheMax(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22818,7 +24789,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GetDataTypeSize(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDataType arg1 ;
   int val1 ;
   int ecode1 = 0 ;
@@ -22836,14 +24807,17 @@ SWIGINTERN PyObject *_wrap_GetDataTypeSize(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     result = (int)GDALGetDataTypeSize(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22851,7 +24825,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_DataTypeIsComplex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDataType arg1 ;
   int val1 ;
   int ecode1 = 0 ;
@@ -22869,14 +24843,17 @@ SWIGINTERN PyObject *_wrap_DataTypeIsComplex(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (int)GDALDataTypeIsComplex(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22884,7 +24861,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GetDataTypeName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDataType arg1 ;
   int val1 ;
   int ecode1 = 0 ;
@@ -22902,14 +24879,17 @@ SWIGINTERN PyObject *_wrap_GetDataTypeName(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     result = (char *)GDALGetDataTypeName(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22917,7 +24897,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GetDataTypeByName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   int res1 ;
   char *buf1 = 0 ;
@@ -22936,15 +24916,18 @@ SWIGINTERN PyObject *_wrap_GetDataTypeByName(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (GDALDataType)GDALGetDataTypeByName((char const *)arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
@@ -22953,7 +24936,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GetColorInterpretationName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALColorInterp arg1 ;
   int val1 ;
   int ecode1 = 0 ;
@@ -22971,14 +24954,17 @@ SWIGINTERN PyObject *_wrap_GetColorInterpretationName(PyObject *SWIGUNUSEDPARM(s
       CPLErrorReset();
     }
     result = (char *)GDALGetColorInterpretationName(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22986,7 +24972,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GetPaletteInterpretationName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALPaletteInterp arg1 ;
   int val1 ;
   int ecode1 = 0 ;
@@ -23004,14 +24990,17 @@ SWIGINTERN PyObject *_wrap_GetPaletteInterpretationName(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     result = (char *)GDALGetPaletteInterpretationName(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -23019,7 +25008,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_DecToDMS(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   double arg1 ;
   char *arg2 = (char *) 0 ;
   int arg3 = (int) 2 ;
@@ -23058,15 +25047,18 @@ SWIGINTERN PyObject *_wrap_DecToDMS(PyObject *SWIGUNUSEDPARM(self), PyObject *ar
       CPLErrorReset();
     }
     result = (char *)GDALDecToDMS(arg1,(char const *)arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -23075,7 +25067,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_PackedDMSToDec(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   double arg1 ;
   double val1 ;
   int ecode1 = 0 ;
@@ -23093,14 +25085,17 @@ SWIGINTERN PyObject *_wrap_PackedDMSToDec(PyObject *SWIGUNUSEDPARM(self), PyObje
       CPLErrorReset();
     }
     result = (double)GDALPackedDMSToDec(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_double(static_cast< double >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -23108,7 +25103,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_DecToPackedDMS(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   double arg1 ;
   double val1 ;
   int ecode1 = 0 ;
@@ -23126,14 +25121,17 @@ SWIGINTERN PyObject *_wrap_DecToPackedDMS(PyObject *SWIGUNUSEDPARM(self), PyObje
       CPLErrorReset();
     }
     result = (double)GDALDecToPackedDMS(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_double(static_cast< double >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -23141,7 +25139,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_ParseXMLString(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   int res1 ;
   char *buf1 = 0 ;
@@ -23160,12 +25158,14 @@ SWIGINTERN PyObject *_wrap_ParseXMLString(PyObject *SWIGUNUSEDPARM(self), PyObje
       CPLErrorReset();
     }
     result = (CPLXMLNode *)CPLParseXMLString(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) (CPLXMLNode*) */
@@ -23196,6 +25196,7 @@ SWIGINTERN PyObject *_wrap_ParseXMLString(PyObject *SWIGUNUSEDPARM(self), PyObje
     /* %typemap(ret) (CPLXMLNode*) */
     if ( result ) CPLDestroyXMLNode( result );
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
@@ -23204,7 +25205,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SerializeXMLTree(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   CPLXMLNode *arg1 = (CPLXMLNode *) 0 ;
   PyObject * obj0 = 0 ;
   retStringAndCPLFree *result = 0 ;
@@ -23220,12 +25221,14 @@ SWIGINTERN PyObject *_wrap_SerializeXMLTree(PyObject *SWIGUNUSEDPARM(self), PyOb
       CPLErrorReset();
     }
     result = (retStringAndCPLFree *)CPLSerializeXMLTree(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) (retStringAndCPLFree*) */
@@ -23237,20 +25240,21 @@ SWIGINTERN PyObject *_wrap_SerializeXMLTree(PyObject *SWIGUNUSEDPARM(self), PyOb
   }
   {
     /* %typemap(freearg) (CPLXMLNode *xmlnode) */
-    if ( arg1 ) CPLDestroyXMLNode( arg1 );
+    CPLDestroyXMLNode( arg1 );
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
     /* %typemap(freearg) (CPLXMLNode *xmlnode) */
-    if ( arg1 ) CPLDestroyXMLNode( arg1 );
+    CPLDestroyXMLNode( arg1 );
   }
   return NULL;
 }
 
 
 SWIGINTERN PyObject *_wrap_GetJPEG2000Structure(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   char **arg2 = (char **) NULL ;
   int res1 ;
@@ -23279,8 +25283,12 @@ SWIGINTERN PyObject *_wrap_GetJPEG2000Structure(PyObject *SWIGUNUSEDPARM(self),
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj1);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj1);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj1,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -23322,12 +25330,14 @@ SWIGINTERN PyObject *_wrap_GetJPEG2000Structure(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (CPLXMLNode *)GDALGetJPEG2000Structure((char const *)arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) (CPLXMLNode*) */
@@ -23362,6 +25372,7 @@ SWIGINTERN PyObject *_wrap_GetJPEG2000Structure(PyObject *SWIGUNUSEDPARM(self),
     /* %typemap(ret) (CPLXMLNode*) */
     if ( result ) CPLDestroyXMLNode( result );
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
@@ -23374,7 +25385,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GetJPEG2000StructureAsString(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   char **arg2 = (char **) NULL ;
   int res1 ;
@@ -23403,8 +25414,12 @@ SWIGINTERN PyObject *_wrap_GetJPEG2000StructureAsString(PyObject *SWIGUNUSEDPARM
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj1);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj1);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj1,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -23446,12 +25461,14 @@ SWIGINTERN PyObject *_wrap_GetJPEG2000StructureAsString(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     result = (retStringAndCPLFree *)GetJPEG2000StructureAsString((char const *)arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) (retStringAndCPLFree*) */
@@ -23466,6 +25483,7 @@ SWIGINTERN PyObject *_wrap_GetJPEG2000StructureAsString(PyObject *SWIGUNUSEDPARM
     /* %typemap(freearg) char **options */
     CSLDestroy( arg2 );
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
@@ -23478,7 +25496,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GetDriverCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   int result;
   
   if (!PyArg_ParseTuple(args,(char *)":GetDriverCount")) SWIG_fail;
@@ -23487,14 +25505,17 @@ SWIGINTERN PyObject *_wrap_GetDriverCount(PyObject *SWIGUNUSEDPARM(self), PyObje
       CPLErrorReset();
     }
     result = (int)GetDriverCount();
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -23502,7 +25523,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GetDriverByName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   int res1 ;
   char *buf1 = 0 ;
@@ -23526,15 +25547,18 @@ SWIGINTERN PyObject *_wrap_GetDriverByName(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     result = (GDALDriverShadow *)GetDriverByName((char const *)arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDriverShadow, 0 |  0 );
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
@@ -23543,7 +25567,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GetDriver(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   int arg1 ;
   int val1 ;
   int ecode1 = 0 ;
@@ -23561,14 +25585,17 @@ SWIGINTERN PyObject *_wrap_GetDriver(PyObject *SWIGUNUSEDPARM(self), PyObject *a
       CPLErrorReset();
     }
     result = (GDALDriverShadow *)GetDriver(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDriverShadow, 0 |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -23576,7 +25603,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Open(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   GDALAccess arg2 = (GDALAccess) GA_ReadOnly ;
   int bToFree1 = 0 ;
@@ -23613,18 +25640,21 @@ SWIGINTERN PyObject *_wrap_Open(PyObject *SWIGUNUSEDPARM(self), PyObject *args)
       CPLErrorReset();
     }
     result = (GDALDatasetShadow *)Open((char const *)arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_POINTER_OWN |  0 );
   {
     /* %typemap(freearg) (const char *utf8_path) */
     GDALPythonFreeCStr(arg1, bToFree1);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -23636,7 +25666,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_OpenEx(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   unsigned int arg2 = (unsigned int) 0 ;
   char **arg3 = (char **) NULL ;
@@ -23685,8 +25715,12 @@ SWIGINTERN PyObject *_wrap_OpenEx(PyObject *SWIGUNUSEDPARM(self), PyObject *args
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj2);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj2);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj2,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -23731,8 +25765,12 @@ SWIGINTERN PyObject *_wrap_OpenEx(PyObject *SWIGUNUSEDPARM(self), PyObject *args
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj3);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj3);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj3,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -23777,8 +25815,12 @@ SWIGINTERN PyObject *_wrap_OpenEx(PyObject *SWIGUNUSEDPARM(self), PyObject *args
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj4);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj4);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj4,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -23820,12 +25862,14 @@ SWIGINTERN PyObject *_wrap_OpenEx(PyObject *SWIGUNUSEDPARM(self), PyObject *args
       CPLErrorReset();
     }
     result = (GDALDatasetShadow *)OpenEx((char const *)arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_POINTER_OWN |  0 );
   {
@@ -23844,6 +25888,7 @@ SWIGINTERN PyObject *_wrap_OpenEx(PyObject *SWIGUNUSEDPARM(self), PyObject *args
     /* %typemap(freearg) char **options */
     CSLDestroy( arg5 );
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -23867,7 +25912,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_OpenShared(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   GDALAccess arg2 = (GDALAccess) GA_ReadOnly ;
   int bToFree1 = 0 ;
@@ -23904,18 +25949,21 @@ SWIGINTERN PyObject *_wrap_OpenShared(PyObject *SWIGUNUSEDPARM(self), PyObject *
       CPLErrorReset();
     }
     result = (GDALDatasetShadow *)OpenShared((char const *)arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_POINTER_OWN |  0 );
   {
     /* %typemap(freearg) (const char *utf8_path) */
     GDALPythonFreeCStr(arg1, bToFree1);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -23927,7 +25975,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_IdentifyDriver(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   char **arg2 = (char **) NULL ;
   int bToFree1 = 0 ;
@@ -23958,8 +26006,12 @@ SWIGINTERN PyObject *_wrap_IdentifyDriver(PyObject *SWIGUNUSEDPARM(self), PyObje
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj1);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj1);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj1,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -23978,17 +26030,2906 @@ SWIGINTERN PyObject *_wrap_IdentifyDriver(PyObject *SWIGUNUSEDPARM(self), PyObje
         else if (PyBytes_Check(pyObj))
         arg2 = CSLAddString( arg2, PyBytes_AsString(pyObj) );
 #else
-        else if (PyString_Check(pyObj))
-        arg2 = CSLAddString( arg2, PyString_AsString(pyObj) );
+        else if (PyString_Check(pyObj))
+        arg2 = CSLAddString( arg2, PyString_AsString(pyObj) );
+#endif
+        else
+        {
+          Py_DECREF(pyObj);
+          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+          SWIG_fail;
+        }
+        Py_DECREF(pyObj);
+      }
+    }
+  }
+  {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (GDALDriverShadow *)IdentifyDriver((char const *)arg1,arg2);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDriverShadow, 0 |  0 );
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
+  }
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg2 );
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
+  }
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg2 );
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_GeneralCmdLineProcessor(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  char **arg1 = (char **) 0 ;
+  int arg2 = (int) 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  char **result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O|O:GeneralCmdLineProcessor",&obj0,&obj1)) SWIG_fail;
+  {
+    /* %typemap(in) char **options */
+    /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+    if ( ! PySequence_Check(obj0) || PyUnicode_Check(obj0)
+  #if PY_VERSION_HEX < 0x03000000
+      || PyString_Check(obj0)
+  #endif
+      ) {
+      PyErr_SetString(PyExc_TypeError,"not a sequence");
+      SWIG_fail;
+    }
+    
+    Py_ssize_t size = PySequence_Size(obj0);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    for (int i = 0; i < (int)size; i++) {
+      PyObject* pyObj = PySequence_GetItem(obj0,i);
+      if (PyUnicode_Check(pyObj))
+      {
+        char *pszStr;
+        Py_ssize_t nLen;
+        PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+        PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+        PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+        arg1 = CSLAddString( arg1, pszStr );
+        Py_XDECREF(pyUTF8Str);
+      }
+#if PY_VERSION_HEX >= 0x03000000
+      else if (PyBytes_Check(pyObj))
+      arg1 = CSLAddString( arg1, PyBytes_AsString(pyObj) );
+#else
+      else if (PyString_Check(pyObj))
+      arg1 = CSLAddString( arg1, PyString_AsString(pyObj) );
+#endif
+      else
+      {
+        Py_DECREF(pyObj);
+        PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+        SWIG_fail;
+      }
+      Py_DECREF(pyObj);
+    }
+  }
+  if (obj1) {
+    ecode2 = SWIG_AsVal_int(obj1, &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "GeneralCmdLineProcessor" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (char **)GeneralCmdLineProcessor(arg1,arg2);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  {
+    /* %typemap(out) char **CSL -> ( string ) */
+    char **stringarray = result;
+    if ( stringarray == NULL ) {
+      resultobj = Py_None;
+      Py_INCREF( resultobj );
+    }
+    else {
+      int len = CSLCount( stringarray );
+      resultobj = PyList_New( len );
+      for ( int i = 0; i < len; ++i ) {
+        PyObject *o = GDALPythonObjectFromCStr( stringarray[i] );
+        PyList_SetItem(resultobj, i, o );
+      }
+    }
+    CSLDestroy(result);
+  }
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg1 );
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg1 );
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_new_GDALInfoOptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  char **arg1 = (char **) 0 ;
+  PyObject * obj0 = 0 ;
+  GDALInfoOptions *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:new_GDALInfoOptions",&obj0)) SWIG_fail;
+  {
+    /* %typemap(in) char **options */
+    /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+    if ( ! PySequence_Check(obj0) || PyUnicode_Check(obj0)
+  #if PY_VERSION_HEX < 0x03000000
+      || PyString_Check(obj0)
+  #endif
+      ) {
+      PyErr_SetString(PyExc_TypeError,"not a sequence");
+      SWIG_fail;
+    }
+    
+    Py_ssize_t size = PySequence_Size(obj0);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    for (int i = 0; i < (int)size; i++) {
+      PyObject* pyObj = PySequence_GetItem(obj0,i);
+      if (PyUnicode_Check(pyObj))
+      {
+        char *pszStr;
+        Py_ssize_t nLen;
+        PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+        PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+        PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+        arg1 = CSLAddString( arg1, pszStr );
+        Py_XDECREF(pyUTF8Str);
+      }
+#if PY_VERSION_HEX >= 0x03000000
+      else if (PyBytes_Check(pyObj))
+      arg1 = CSLAddString( arg1, PyBytes_AsString(pyObj) );
+#else
+      else if (PyString_Check(pyObj))
+      arg1 = CSLAddString( arg1, PyString_AsString(pyObj) );
+#endif
+      else
+      {
+        Py_DECREF(pyObj);
+        PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+        SWIG_fail;
+      }
+      Py_DECREF(pyObj);
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (GDALInfoOptions *)new_GDALInfoOptions(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALInfoOptions, SWIG_POINTER_NEW |  0 );
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg1 );
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg1 );
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_delete_GDALInfoOptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALInfoOptions *arg1 = (GDALInfoOptions *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:delete_GDALInfoOptions",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALInfoOptions, SWIG_POINTER_DISOWN |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_GDALInfoOptions" "', argument " "1"" of type '" "GDALInfoOptions *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALInfoOptions * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    delete_GDALInfoOptions(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *GDALInfoOptions_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *obj;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
+  SWIG_TypeNewClientData(SWIGTYPE_p_GDALInfoOptions, SWIG_NewClientData(obj));
+  return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject *_wrap_InfoInternal(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
+  GDALInfoOptions *arg2 = (GDALInfoOptions *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  retStringAndCPLFree *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:InfoInternal",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "InfoInternal" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_GDALInfoOptions, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "InfoInternal" "', argument " "2"" of type '" "GDALInfoOptions *""'"); 
+  }
+  arg2 = reinterpret_cast< GDALInfoOptions * >(argp2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (retStringAndCPLFree *)GDALInfo(arg1,arg2);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  {
+    /* %typemap(out) (retStringAndCPLFree*) */
+    if(result)
+    {
+      resultobj = GDALPythonObjectFromCStr( (const char *)result);
+      CPLFree(result);
+    }
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_new_GDALTranslateOptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  char **arg1 = (char **) 0 ;
+  PyObject * obj0 = 0 ;
+  GDALTranslateOptions *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:new_GDALTranslateOptions",&obj0)) SWIG_fail;
+  {
+    /* %typemap(in) char **options */
+    /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+    if ( ! PySequence_Check(obj0) || PyUnicode_Check(obj0)
+  #if PY_VERSION_HEX < 0x03000000
+      || PyString_Check(obj0)
+  #endif
+      ) {
+      PyErr_SetString(PyExc_TypeError,"not a sequence");
+      SWIG_fail;
+    }
+    
+    Py_ssize_t size = PySequence_Size(obj0);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    for (int i = 0; i < (int)size; i++) {
+      PyObject* pyObj = PySequence_GetItem(obj0,i);
+      if (PyUnicode_Check(pyObj))
+      {
+        char *pszStr;
+        Py_ssize_t nLen;
+        PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+        PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+        PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+        arg1 = CSLAddString( arg1, pszStr );
+        Py_XDECREF(pyUTF8Str);
+      }
+#if PY_VERSION_HEX >= 0x03000000
+      else if (PyBytes_Check(pyObj))
+      arg1 = CSLAddString( arg1, PyBytes_AsString(pyObj) );
+#else
+      else if (PyString_Check(pyObj))
+      arg1 = CSLAddString( arg1, PyString_AsString(pyObj) );
+#endif
+      else
+      {
+        Py_DECREF(pyObj);
+        PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+        SWIG_fail;
+      }
+      Py_DECREF(pyObj);
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (GDALTranslateOptions *)new_GDALTranslateOptions(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALTranslateOptions, SWIG_POINTER_NEW |  0 );
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg1 );
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg1 );
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_delete_GDALTranslateOptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALTranslateOptions *arg1 = (GDALTranslateOptions *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:delete_GDALTranslateOptions",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALTranslateOptions, SWIG_POINTER_DISOWN |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_GDALTranslateOptions" "', argument " "1"" of type '" "GDALTranslateOptions *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALTranslateOptions * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    delete_GDALTranslateOptions(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *GDALTranslateOptions_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *obj;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
+  SWIG_TypeNewClientData(SWIGTYPE_p_GDALTranslateOptions, SWIG_NewClientData(obj));
+  return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject *_wrap_TranslateInternal(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  char *arg1 = (char *) 0 ;
+  GDALDatasetShadow *arg2 = (GDALDatasetShadow *) 0 ;
+  GDALTranslateOptions *arg3 = (GDALTranslateOptions *) 0 ;
+  GDALProgressFunc arg4 = (GDALProgressFunc) NULL ;
+  void *arg5 = (void *) NULL ;
+  int bToFree1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  void *argp3 = 0 ;
+  int res3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  GDALDatasetShadow *result = 0 ;
+  
+  /* %typemap(arginit) ( const char* callback_data=NULL)  */
+  PyProgressData *psProgressInfo;
+  psProgressInfo = (PyProgressData *) CPLCalloc(1,sizeof(PyProgressData));
+  psProgressInfo->nLastReported = -1;
+  psProgressInfo->psPyCallback = NULL;
+  psProgressInfo->psPyCallbackData = NULL;
+  arg5 = psProgressInfo;
+  if (!PyArg_ParseTuple(args,(char *)"OOO|OO:TranslateInternal",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  {
+    /* %typemap(in) (const char *utf8_path) */
+    arg1 = GDALPythonObjectToCStr( obj0, &bToFree1 );
+    if (arg1 == NULL)
+    {
+      PyErr_SetString( PyExc_RuntimeError, "not a string" );
+      SWIG_fail;
+    }
+  }
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "TranslateInternal" "', argument " "2"" of type '" "GDALDatasetShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< GDALDatasetShadow * >(argp2);
+  res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_GDALTranslateOptions, 0 |  0 );
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "TranslateInternal" "', argument " "3"" of type '" "GDALTranslateOptions *""'"); 
+  }
+  arg3 = reinterpret_cast< GDALTranslateOptions * >(argp3);
+  if (obj3) {
+    {
+      /* %typemap(in) (GDALProgressFunc callback = NULL) */
+      /* callback_func typemap */
+      if (obj3 && obj3 != Py_None ) {
+        void* cbfunction = NULL;
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
+        
+        if ( cbfunction == GDALTermProgress ) {
+          arg4 = GDALTermProgress;
+        } else {
+          if (!PyCallable_Check(obj3)) {
+            PyErr_SetString( PyExc_RuntimeError,
+              "Object given is not a Python function" );
+            SWIG_fail;
+          }
+          psProgressInfo->psPyCallback = obj3;
+          arg4 = PyProgressProxy;
+        }
+        
+      }
+      
+    }
+  }
+  if (obj4) {
+    {
+      /* %typemap(in) ( void* callback_data=NULL)  */
+      psProgressInfo->psPyCallbackData = obj4 ;
+    }
+  }
+  {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (GDALDatasetShadow *)wrapper_GDALTranslate((char const *)arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_POINTER_OWN |  0 );
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
+  }
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
+  }
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_new_GDALWarpAppOptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  char **arg1 = (char **) 0 ;
+  PyObject * obj0 = 0 ;
+  GDALWarpAppOptions *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:new_GDALWarpAppOptions",&obj0)) SWIG_fail;
+  {
+    /* %typemap(in) char **options */
+    /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+    if ( ! PySequence_Check(obj0) || PyUnicode_Check(obj0)
+  #if PY_VERSION_HEX < 0x03000000
+      || PyString_Check(obj0)
+  #endif
+      ) {
+      PyErr_SetString(PyExc_TypeError,"not a sequence");
+      SWIG_fail;
+    }
+    
+    Py_ssize_t size = PySequence_Size(obj0);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    for (int i = 0; i < (int)size; i++) {
+      PyObject* pyObj = PySequence_GetItem(obj0,i);
+      if (PyUnicode_Check(pyObj))
+      {
+        char *pszStr;
+        Py_ssize_t nLen;
+        PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+        PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+        PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+        arg1 = CSLAddString( arg1, pszStr );
+        Py_XDECREF(pyUTF8Str);
+      }
+#if PY_VERSION_HEX >= 0x03000000
+      else if (PyBytes_Check(pyObj))
+      arg1 = CSLAddString( arg1, PyBytes_AsString(pyObj) );
+#else
+      else if (PyString_Check(pyObj))
+      arg1 = CSLAddString( arg1, PyString_AsString(pyObj) );
+#endif
+      else
+      {
+        Py_DECREF(pyObj);
+        PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+        SWIG_fail;
+      }
+      Py_DECREF(pyObj);
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (GDALWarpAppOptions *)new_GDALWarpAppOptions(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALWarpAppOptions, SWIG_POINTER_NEW |  0 );
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg1 );
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg1 );
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_delete_GDALWarpAppOptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALWarpAppOptions *arg1 = (GDALWarpAppOptions *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:delete_GDALWarpAppOptions",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALWarpAppOptions, SWIG_POINTER_DISOWN |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_GDALWarpAppOptions" "', argument " "1"" of type '" "GDALWarpAppOptions *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALWarpAppOptions * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    delete_GDALWarpAppOptions(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *GDALWarpAppOptions_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *obj;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
+  SWIG_TypeNewClientData(SWIGTYPE_p_GDALWarpAppOptions, SWIG_NewClientData(obj));
+  return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject *_wrap_wrapper_GDALWarpDestDS(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
+  int arg2 ;
+  GDALDatasetShadow **arg3 = (GDALDatasetShadow **) 0 ;
+  GDALWarpAppOptions *arg4 = (GDALWarpAppOptions *) 0 ;
+  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
+  void *arg6 = (void *) NULL ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp4 = 0 ;
+  int res4 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  int result;
+  
+  /* %typemap(arginit) ( const char* callback_data=NULL)  */
+  PyProgressData *psProgressInfo;
+  psProgressInfo = (PyProgressData *) CPLCalloc(1,sizeof(PyProgressData));
+  psProgressInfo->nLastReported = -1;
+  psProgressInfo->psPyCallback = NULL;
+  psProgressInfo->psPyCallbackData = NULL;
+  arg6 = psProgressInfo;
+  if (!PyArg_ParseTuple(args,(char *)"OOO|OO:wrapper_GDALWarpDestDS",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "wrapper_GDALWarpDestDS" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
+  {
+    /*  OBJECT_LIST_INPUT %typemap(in) (int itemcount, GDALDatasetShadow *optional_##GDALDatasetShadow)*/
+    if ( !PySequence_Check(obj1) ) {
+      PyErr_SetString(PyExc_TypeError, "not a sequence");
+      SWIG_fail;
+    }
+    Py_ssize_t size = PySequence_Size(obj1);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    arg2 = (int)size;
+    arg3 = (GDALDatasetShadow**) CPLMalloc(arg2*sizeof(GDALDatasetShadow*));
+    
+    for( int i = 0; i<arg2; i++ ) {
+      PyObject *o = PySequence_GetItem(obj1,i);
+#if 0x020012 <= 0x010337
+      PySwigObject *sobj = SWIG_Python_GetSwigThis(o);
+#else
+      SwigPyObject *sobj = SWIG_Python_GetSwigThis(o);
+#endif
+      GDALDatasetShadow* rawobjectpointer = NULL;
+      if (!sobj) {
+        Py_DECREF(o);
+        SWIG_fail;
+      }
+      rawobjectpointer = (GDALDatasetShadow*) sobj->ptr;
+      arg3[i] = rawobjectpointer;
+      Py_DECREF(o);
+      
+    }
+  }
+  res4 = SWIG_ConvertPtr(obj2, &argp4,SWIGTYPE_p_GDALWarpAppOptions, 0 |  0 );
+  if (!SWIG_IsOK(res4)) {
+    SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "wrapper_GDALWarpDestDS" "', argument " "4"" of type '" "GDALWarpAppOptions *""'"); 
+  }
+  arg4 = reinterpret_cast< GDALWarpAppOptions * >(argp4);
+  if (obj3) {
+    {
+      /* %typemap(in) (GDALProgressFunc callback = NULL) */
+      /* callback_func typemap */
+      if (obj3 && obj3 != Py_None ) {
+        void* cbfunction = NULL;
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
+        
+        if ( cbfunction == GDALTermProgress ) {
+          arg5 = GDALTermProgress;
+        } else {
+          if (!PyCallable_Check(obj3)) {
+            PyErr_SetString( PyExc_RuntimeError,
+              "Object given is not a Python function" );
+            SWIG_fail;
+          }
+          psProgressInfo->psPyCallback = obj3;
+          arg5 = PyProgressProxy;
+        }
+        
+      }
+      
+    }
+  }
+  if (obj4) {
+    {
+      /* %typemap(in) ( void* callback_data=NULL)  */
+      psProgressInfo->psPyCallbackData = obj4 ;
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)wrapper_GDALWarpDestDS(arg1,arg2,arg3,arg4,arg5,arg6);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  {
+    /* OBJECT_LIST_INPUT %typemap(freearg) (int object_list_count, GDALDatasetShadow **poObjects)*/
+    CPLFree( arg3 );
+  }
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* OBJECT_LIST_INPUT %typemap(freearg) (int object_list_count, GDALDatasetShadow **poObjects)*/
+    CPLFree( arg3 );
+  }
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_wrapper_GDALWarpDestName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  char *arg1 = (char *) 0 ;
+  int arg2 ;
+  GDALDatasetShadow **arg3 = (GDALDatasetShadow **) 0 ;
+  GDALWarpAppOptions *arg4 = (GDALWarpAppOptions *) 0 ;
+  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
+  void *arg6 = (void *) NULL ;
+  int bToFree1 = 0 ;
+  void *argp4 = 0 ;
+  int res4 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  GDALDatasetShadow *result = 0 ;
+  
+  /* %typemap(arginit) ( const char* callback_data=NULL)  */
+  PyProgressData *psProgressInfo;
+  psProgressInfo = (PyProgressData *) CPLCalloc(1,sizeof(PyProgressData));
+  psProgressInfo->nLastReported = -1;
+  psProgressInfo->psPyCallback = NULL;
+  psProgressInfo->psPyCallbackData = NULL;
+  arg6 = psProgressInfo;
+  if (!PyArg_ParseTuple(args,(char *)"OOO|OO:wrapper_GDALWarpDestName",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  {
+    /* %typemap(in) (const char *utf8_path) */
+    arg1 = GDALPythonObjectToCStr( obj0, &bToFree1 );
+    if (arg1 == NULL)
+    {
+      PyErr_SetString( PyExc_RuntimeError, "not a string" );
+      SWIG_fail;
+    }
+  }
+  {
+    /*  OBJECT_LIST_INPUT %typemap(in) (int itemcount, GDALDatasetShadow *optional_##GDALDatasetShadow)*/
+    if ( !PySequence_Check(obj1) ) {
+      PyErr_SetString(PyExc_TypeError, "not a sequence");
+      SWIG_fail;
+    }
+    Py_ssize_t size = PySequence_Size(obj1);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    arg2 = (int)size;
+    arg3 = (GDALDatasetShadow**) CPLMalloc(arg2*sizeof(GDALDatasetShadow*));
+    
+    for( int i = 0; i<arg2; i++ ) {
+      PyObject *o = PySequence_GetItem(obj1,i);
+#if 0x020012 <= 0x010337
+      PySwigObject *sobj = SWIG_Python_GetSwigThis(o);
+#else
+      SwigPyObject *sobj = SWIG_Python_GetSwigThis(o);
+#endif
+      GDALDatasetShadow* rawobjectpointer = NULL;
+      if (!sobj) {
+        Py_DECREF(o);
+        SWIG_fail;
+      }
+      rawobjectpointer = (GDALDatasetShadow*) sobj->ptr;
+      arg3[i] = rawobjectpointer;
+      Py_DECREF(o);
+      
+    }
+  }
+  res4 = SWIG_ConvertPtr(obj2, &argp4,SWIGTYPE_p_GDALWarpAppOptions, 0 |  0 );
+  if (!SWIG_IsOK(res4)) {
+    SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "wrapper_GDALWarpDestName" "', argument " "4"" of type '" "GDALWarpAppOptions *""'"); 
+  }
+  arg4 = reinterpret_cast< GDALWarpAppOptions * >(argp4);
+  if (obj3) {
+    {
+      /* %typemap(in) (GDALProgressFunc callback = NULL) */
+      /* callback_func typemap */
+      if (obj3 && obj3 != Py_None ) {
+        void* cbfunction = NULL;
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
+        
+        if ( cbfunction == GDALTermProgress ) {
+          arg5 = GDALTermProgress;
+        } else {
+          if (!PyCallable_Check(obj3)) {
+            PyErr_SetString( PyExc_RuntimeError,
+              "Object given is not a Python function" );
+            SWIG_fail;
+          }
+          psProgressInfo->psPyCallback = obj3;
+          arg5 = PyProgressProxy;
+        }
+        
+      }
+      
+    }
+  }
+  if (obj4) {
+    {
+      /* %typemap(in) ( void* callback_data=NULL)  */
+      psProgressInfo->psPyCallbackData = obj4 ;
+    }
+  }
+  {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (GDALDatasetShadow *)wrapper_GDALWarpDestName((char const *)arg1,arg2,arg3,arg4,arg5,arg6);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_POINTER_OWN |  0 );
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
+  }
+  {
+    /* OBJECT_LIST_INPUT %typemap(freearg) (int object_list_count, GDALDatasetShadow **poObjects)*/
+    CPLFree( arg3 );
+  }
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
+  }
+  {
+    /* OBJECT_LIST_INPUT %typemap(freearg) (int object_list_count, GDALDatasetShadow **poObjects)*/
+    CPLFree( arg3 );
+  }
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_new_GDALVectorTranslateOptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  char **arg1 = (char **) 0 ;
+  PyObject * obj0 = 0 ;
+  GDALVectorTranslateOptions *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:new_GDALVectorTranslateOptions",&obj0)) SWIG_fail;
+  {
+    /* %typemap(in) char **options */
+    /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+    if ( ! PySequence_Check(obj0) || PyUnicode_Check(obj0)
+  #if PY_VERSION_HEX < 0x03000000
+      || PyString_Check(obj0)
+  #endif
+      ) {
+      PyErr_SetString(PyExc_TypeError,"not a sequence");
+      SWIG_fail;
+    }
+    
+    Py_ssize_t size = PySequence_Size(obj0);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    for (int i = 0; i < (int)size; i++) {
+      PyObject* pyObj = PySequence_GetItem(obj0,i);
+      if (PyUnicode_Check(pyObj))
+      {
+        char *pszStr;
+        Py_ssize_t nLen;
+        PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+        PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+        PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+        arg1 = CSLAddString( arg1, pszStr );
+        Py_XDECREF(pyUTF8Str);
+      }
+#if PY_VERSION_HEX >= 0x03000000
+      else if (PyBytes_Check(pyObj))
+      arg1 = CSLAddString( arg1, PyBytes_AsString(pyObj) );
+#else
+      else if (PyString_Check(pyObj))
+      arg1 = CSLAddString( arg1, PyString_AsString(pyObj) );
+#endif
+      else
+      {
+        Py_DECREF(pyObj);
+        PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+        SWIG_fail;
+      }
+      Py_DECREF(pyObj);
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (GDALVectorTranslateOptions *)new_GDALVectorTranslateOptions(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALVectorTranslateOptions, SWIG_POINTER_NEW |  0 );
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg1 );
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg1 );
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_delete_GDALVectorTranslateOptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALVectorTranslateOptions *arg1 = (GDALVectorTranslateOptions *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:delete_GDALVectorTranslateOptions",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALVectorTranslateOptions, SWIG_POINTER_DISOWN |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_GDALVectorTranslateOptions" "', argument " "1"" of type '" "GDALVectorTranslateOptions *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALVectorTranslateOptions * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    delete_GDALVectorTranslateOptions(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *GDALVectorTranslateOptions_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *obj;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
+  SWIG_TypeNewClientData(SWIGTYPE_p_GDALVectorTranslateOptions, SWIG_NewClientData(obj));
+  return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject *_wrap_wrapper_GDALVectorTranslateDestDS(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
+  GDALDatasetShadow *arg2 = (GDALDatasetShadow *) 0 ;
+  GDALVectorTranslateOptions *arg3 = (GDALVectorTranslateOptions *) 0 ;
+  GDALProgressFunc arg4 = (GDALProgressFunc) NULL ;
+  void *arg5 = (void *) NULL ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  void *argp3 = 0 ;
+  int res3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  int result;
+  
+  /* %typemap(arginit) ( const char* callback_data=NULL)  */
+  PyProgressData *psProgressInfo;
+  psProgressInfo = (PyProgressData *) CPLCalloc(1,sizeof(PyProgressData));
+  psProgressInfo->nLastReported = -1;
+  psProgressInfo->psPyCallback = NULL;
+  psProgressInfo->psPyCallbackData = NULL;
+  arg5 = psProgressInfo;
+  if (!PyArg_ParseTuple(args,(char *)"OOO|OO:wrapper_GDALVectorTranslateDestDS",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "wrapper_GDALVectorTranslateDestDS" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "wrapper_GDALVectorTranslateDestDS" "', argument " "2"" of type '" "GDALDatasetShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< GDALDatasetShadow * >(argp2);
+  res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_GDALVectorTranslateOptions, 0 |  0 );
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "wrapper_GDALVectorTranslateDestDS" "', argument " "3"" of type '" "GDALVectorTranslateOptions *""'"); 
+  }
+  arg3 = reinterpret_cast< GDALVectorTranslateOptions * >(argp3);
+  if (obj3) {
+    {
+      /* %typemap(in) (GDALProgressFunc callback = NULL) */
+      /* callback_func typemap */
+      if (obj3 && obj3 != Py_None ) {
+        void* cbfunction = NULL;
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
+        
+        if ( cbfunction == GDALTermProgress ) {
+          arg4 = GDALTermProgress;
+        } else {
+          if (!PyCallable_Check(obj3)) {
+            PyErr_SetString( PyExc_RuntimeError,
+              "Object given is not a Python function" );
+            SWIG_fail;
+          }
+          psProgressInfo->psPyCallback = obj3;
+          arg4 = PyProgressProxy;
+        }
+        
+      }
+      
+    }
+  }
+  if (obj4) {
+    {
+      /* %typemap(in) ( void* callback_data=NULL)  */
+      psProgressInfo->psPyCallbackData = obj4 ;
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)wrapper_GDALVectorTranslateDestDS(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_wrapper_GDALVectorTranslateDestName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  char *arg1 = (char *) 0 ;
+  GDALDatasetShadow *arg2 = (GDALDatasetShadow *) 0 ;
+  GDALVectorTranslateOptions *arg3 = (GDALVectorTranslateOptions *) 0 ;
+  GDALProgressFunc arg4 = (GDALProgressFunc) NULL ;
+  void *arg5 = (void *) NULL ;
+  int bToFree1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  void *argp3 = 0 ;
+  int res3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  GDALDatasetShadow *result = 0 ;
+  
+  /* %typemap(arginit) ( const char* callback_data=NULL)  */
+  PyProgressData *psProgressInfo;
+  psProgressInfo = (PyProgressData *) CPLCalloc(1,sizeof(PyProgressData));
+  psProgressInfo->nLastReported = -1;
+  psProgressInfo->psPyCallback = NULL;
+  psProgressInfo->psPyCallbackData = NULL;
+  arg5 = psProgressInfo;
+  if (!PyArg_ParseTuple(args,(char *)"OOO|OO:wrapper_GDALVectorTranslateDestName",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  {
+    /* %typemap(in) (const char *utf8_path) */
+    arg1 = GDALPythonObjectToCStr( obj0, &bToFree1 );
+    if (arg1 == NULL)
+    {
+      PyErr_SetString( PyExc_RuntimeError, "not a string" );
+      SWIG_fail;
+    }
+  }
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "wrapper_GDALVectorTranslateDestName" "', argument " "2"" of type '" "GDALDatasetShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< GDALDatasetShadow * >(argp2);
+  res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_GDALVectorTranslateOptions, 0 |  0 );
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "wrapper_GDALVectorTranslateDestName" "', argument " "3"" of type '" "GDALVectorTranslateOptions *""'"); 
+  }
+  arg3 = reinterpret_cast< GDALVectorTranslateOptions * >(argp3);
+  if (obj3) {
+    {
+      /* %typemap(in) (GDALProgressFunc callback = NULL) */
+      /* callback_func typemap */
+      if (obj3 && obj3 != Py_None ) {
+        void* cbfunction = NULL;
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
+        
+        if ( cbfunction == GDALTermProgress ) {
+          arg4 = GDALTermProgress;
+        } else {
+          if (!PyCallable_Check(obj3)) {
+            PyErr_SetString( PyExc_RuntimeError,
+              "Object given is not a Python function" );
+            SWIG_fail;
+          }
+          psProgressInfo->psPyCallback = obj3;
+          arg4 = PyProgressProxy;
+        }
+        
+      }
+      
+    }
+  }
+  if (obj4) {
+    {
+      /* %typemap(in) ( void* callback_data=NULL)  */
+      psProgressInfo->psPyCallbackData = obj4 ;
+    }
+  }
+  {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (GDALDatasetShadow *)wrapper_GDALVectorTranslateDestName((char const *)arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_POINTER_OWN |  0 );
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
+  }
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
+  }
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_new_GDALDEMProcessingOptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  char **arg1 = (char **) 0 ;
+  PyObject * obj0 = 0 ;
+  GDALDEMProcessingOptions *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:new_GDALDEMProcessingOptions",&obj0)) SWIG_fail;
+  {
+    /* %typemap(in) char **options */
+    /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+    if ( ! PySequence_Check(obj0) || PyUnicode_Check(obj0)
+  #if PY_VERSION_HEX < 0x03000000
+      || PyString_Check(obj0)
+  #endif
+      ) {
+      PyErr_SetString(PyExc_TypeError,"not a sequence");
+      SWIG_fail;
+    }
+    
+    Py_ssize_t size = PySequence_Size(obj0);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    for (int i = 0; i < (int)size; i++) {
+      PyObject* pyObj = PySequence_GetItem(obj0,i);
+      if (PyUnicode_Check(pyObj))
+      {
+        char *pszStr;
+        Py_ssize_t nLen;
+        PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+        PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+        PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+        arg1 = CSLAddString( arg1, pszStr );
+        Py_XDECREF(pyUTF8Str);
+      }
+#if PY_VERSION_HEX >= 0x03000000
+      else if (PyBytes_Check(pyObj))
+      arg1 = CSLAddString( arg1, PyBytes_AsString(pyObj) );
+#else
+      else if (PyString_Check(pyObj))
+      arg1 = CSLAddString( arg1, PyString_AsString(pyObj) );
+#endif
+      else
+      {
+        Py_DECREF(pyObj);
+        PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+        SWIG_fail;
+      }
+      Py_DECREF(pyObj);
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (GDALDEMProcessingOptions *)new_GDALDEMProcessingOptions(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDEMProcessingOptions, SWIG_POINTER_NEW |  0 );
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg1 );
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg1 );
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_delete_GDALDEMProcessingOptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALDEMProcessingOptions *arg1 = (GDALDEMProcessingOptions *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:delete_GDALDEMProcessingOptions",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALDEMProcessingOptions, SWIG_POINTER_DISOWN |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_GDALDEMProcessingOptions" "', argument " "1"" of type '" "GDALDEMProcessingOptions *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALDEMProcessingOptions * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    delete_GDALDEMProcessingOptions(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *GDALDEMProcessingOptions_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *obj;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
+  SWIG_TypeNewClientData(SWIGTYPE_p_GDALDEMProcessingOptions, SWIG_NewClientData(obj));
+  return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject *_wrap_DEMProcessingInternal(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  char *arg1 = (char *) 0 ;
+  GDALDatasetShadow *arg2 = (GDALDatasetShadow *) 0 ;
+  char *arg3 = (char *) 0 ;
+  char *arg4 = (char *) 0 ;
+  GDALDEMProcessingOptions *arg5 = (GDALDEMProcessingOptions *) 0 ;
+  GDALProgressFunc arg6 = (GDALProgressFunc) NULL ;
+  void *arg7 = (void *) NULL ;
+  int bToFree1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  int res3 ;
+  char *buf3 = 0 ;
+  int alloc3 = 0 ;
+  int res4 ;
+  char *buf4 = 0 ;
+  int alloc4 = 0 ;
+  void *argp5 = 0 ;
+  int res5 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  PyObject * obj6 = 0 ;
+  GDALDatasetShadow *result = 0 ;
+  
+  /* %typemap(arginit) ( const char* callback_data=NULL)  */
+  PyProgressData *psProgressInfo;
+  psProgressInfo = (PyProgressData *) CPLCalloc(1,sizeof(PyProgressData));
+  psProgressInfo->nLastReported = -1;
+  psProgressInfo->psPyCallback = NULL;
+  psProgressInfo->psPyCallbackData = NULL;
+  arg7 = psProgressInfo;
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO|OO:DEMProcessingInternal",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6)) SWIG_fail;
+  {
+    /* %typemap(in) (const char *utf8_path) */
+    arg1 = GDALPythonObjectToCStr( obj0, &bToFree1 );
+    if (arg1 == NULL)
+    {
+      PyErr_SetString( PyExc_RuntimeError, "not a string" );
+      SWIG_fail;
+    }
+  }
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "DEMProcessingInternal" "', argument " "2"" of type '" "GDALDatasetShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< GDALDatasetShadow * >(argp2);
+  res3 = SWIG_AsCharPtrAndSize(obj2, &buf3, NULL, &alloc3);
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "DEMProcessingInternal" "', argument " "3"" of type '" "char const *""'");
+  }
+  arg3 = reinterpret_cast< char * >(buf3);
+  res4 = SWIG_AsCharPtrAndSize(obj3, &buf4, NULL, &alloc4);
+  if (!SWIG_IsOK(res4)) {
+    SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "DEMProcessingInternal" "', argument " "4"" of type '" "char const *""'");
+  }
+  arg4 = reinterpret_cast< char * >(buf4);
+  res5 = SWIG_ConvertPtr(obj4, &argp5,SWIGTYPE_p_GDALDEMProcessingOptions, 0 |  0 );
+  if (!SWIG_IsOK(res5)) {
+    SWIG_exception_fail(SWIG_ArgError(res5), "in method '" "DEMProcessingInternal" "', argument " "5"" of type '" "GDALDEMProcessingOptions *""'"); 
+  }
+  arg5 = reinterpret_cast< GDALDEMProcessingOptions * >(argp5);
+  if (obj5) {
+    {
+      /* %typemap(in) (GDALProgressFunc callback = NULL) */
+      /* callback_func typemap */
+      if (obj5 && obj5 != Py_None ) {
+        void* cbfunction = NULL;
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj5,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
+        
+        if ( cbfunction == GDALTermProgress ) {
+          arg6 = GDALTermProgress;
+        } else {
+          if (!PyCallable_Check(obj5)) {
+            PyErr_SetString( PyExc_RuntimeError,
+              "Object given is not a Python function" );
+            SWIG_fail;
+          }
+          psProgressInfo->psPyCallback = obj5;
+          arg6 = PyProgressProxy;
+        }
+        
+      }
+      
+    }
+  }
+  if (obj6) {
+    {
+      /* %typemap(in) ( void* callback_data=NULL)  */
+      psProgressInfo->psPyCallbackData = obj6 ;
+    }
+  }
+  {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if (!arg3) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (GDALDatasetShadow *)wrapper_GDALDEMProcessing((char const *)arg1,arg2,(char const *)arg3,(char const *)arg4,arg5,arg6,arg7);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_POINTER_OWN |  0 );
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
+  }
+  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
+  }
+  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_new_GDALNearblackOptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  char **arg1 = (char **) 0 ;
+  PyObject * obj0 = 0 ;
+  GDALNearblackOptions *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:new_GDALNearblackOptions",&obj0)) SWIG_fail;
+  {
+    /* %typemap(in) char **options */
+    /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+    if ( ! PySequence_Check(obj0) || PyUnicode_Check(obj0)
+  #if PY_VERSION_HEX < 0x03000000
+      || PyString_Check(obj0)
+  #endif
+      ) {
+      PyErr_SetString(PyExc_TypeError,"not a sequence");
+      SWIG_fail;
+    }
+    
+    Py_ssize_t size = PySequence_Size(obj0);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    for (int i = 0; i < (int)size; i++) {
+      PyObject* pyObj = PySequence_GetItem(obj0,i);
+      if (PyUnicode_Check(pyObj))
+      {
+        char *pszStr;
+        Py_ssize_t nLen;
+        PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+        PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+        PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+        arg1 = CSLAddString( arg1, pszStr );
+        Py_XDECREF(pyUTF8Str);
+      }
+#if PY_VERSION_HEX >= 0x03000000
+      else if (PyBytes_Check(pyObj))
+      arg1 = CSLAddString( arg1, PyBytes_AsString(pyObj) );
+#else
+      else if (PyString_Check(pyObj))
+      arg1 = CSLAddString( arg1, PyString_AsString(pyObj) );
+#endif
+      else
+      {
+        Py_DECREF(pyObj);
+        PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+        SWIG_fail;
+      }
+      Py_DECREF(pyObj);
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (GDALNearblackOptions *)new_GDALNearblackOptions(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALNearblackOptions, SWIG_POINTER_NEW |  0 );
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg1 );
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg1 );
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_delete_GDALNearblackOptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALNearblackOptions *arg1 = (GDALNearblackOptions *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:delete_GDALNearblackOptions",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALNearblackOptions, SWIG_POINTER_DISOWN |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_GDALNearblackOptions" "', argument " "1"" of type '" "GDALNearblackOptions *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALNearblackOptions * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    delete_GDALNearblackOptions(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *GDALNearblackOptions_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *obj;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
+  SWIG_TypeNewClientData(SWIGTYPE_p_GDALNearblackOptions, SWIG_NewClientData(obj));
+  return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject *_wrap_wrapper_GDALNearblackDestDS(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
+  GDALDatasetShadow *arg2 = (GDALDatasetShadow *) 0 ;
+  GDALNearblackOptions *arg3 = (GDALNearblackOptions *) 0 ;
+  GDALProgressFunc arg4 = (GDALProgressFunc) NULL ;
+  void *arg5 = (void *) NULL ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  void *argp3 = 0 ;
+  int res3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  int result;
+  
+  /* %typemap(arginit) ( const char* callback_data=NULL)  */
+  PyProgressData *psProgressInfo;
+  psProgressInfo = (PyProgressData *) CPLCalloc(1,sizeof(PyProgressData));
+  psProgressInfo->nLastReported = -1;
+  psProgressInfo->psPyCallback = NULL;
+  psProgressInfo->psPyCallbackData = NULL;
+  arg5 = psProgressInfo;
+  if (!PyArg_ParseTuple(args,(char *)"OOO|OO:wrapper_GDALNearblackDestDS",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "wrapper_GDALNearblackDestDS" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "wrapper_GDALNearblackDestDS" "', argument " "2"" of type '" "GDALDatasetShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< GDALDatasetShadow * >(argp2);
+  res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_GDALNearblackOptions, 0 |  0 );
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "wrapper_GDALNearblackDestDS" "', argument " "3"" of type '" "GDALNearblackOptions *""'"); 
+  }
+  arg3 = reinterpret_cast< GDALNearblackOptions * >(argp3);
+  if (obj3) {
+    {
+      /* %typemap(in) (GDALProgressFunc callback = NULL) */
+      /* callback_func typemap */
+      if (obj3 && obj3 != Py_None ) {
+        void* cbfunction = NULL;
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
+        
+        if ( cbfunction == GDALTermProgress ) {
+          arg4 = GDALTermProgress;
+        } else {
+          if (!PyCallable_Check(obj3)) {
+            PyErr_SetString( PyExc_RuntimeError,
+              "Object given is not a Python function" );
+            SWIG_fail;
+          }
+          psProgressInfo->psPyCallback = obj3;
+          arg4 = PyProgressProxy;
+        }
+        
+      }
+      
+    }
+  }
+  if (obj4) {
+    {
+      /* %typemap(in) ( void* callback_data=NULL)  */
+      psProgressInfo->psPyCallbackData = obj4 ;
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)wrapper_GDALNearblackDestDS(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_wrapper_GDALNearblackDestName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  char *arg1 = (char *) 0 ;
+  GDALDatasetShadow *arg2 = (GDALDatasetShadow *) 0 ;
+  GDALNearblackOptions *arg3 = (GDALNearblackOptions *) 0 ;
+  GDALProgressFunc arg4 = (GDALProgressFunc) NULL ;
+  void *arg5 = (void *) NULL ;
+  int bToFree1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  void *argp3 = 0 ;
+  int res3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  GDALDatasetShadow *result = 0 ;
+  
+  /* %typemap(arginit) ( const char* callback_data=NULL)  */
+  PyProgressData *psProgressInfo;
+  psProgressInfo = (PyProgressData *) CPLCalloc(1,sizeof(PyProgressData));
+  psProgressInfo->nLastReported = -1;
+  psProgressInfo->psPyCallback = NULL;
+  psProgressInfo->psPyCallbackData = NULL;
+  arg5 = psProgressInfo;
+  if (!PyArg_ParseTuple(args,(char *)"OOO|OO:wrapper_GDALNearblackDestName",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  {
+    /* %typemap(in) (const char *utf8_path) */
+    arg1 = GDALPythonObjectToCStr( obj0, &bToFree1 );
+    if (arg1 == NULL)
+    {
+      PyErr_SetString( PyExc_RuntimeError, "not a string" );
+      SWIG_fail;
+    }
+  }
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "wrapper_GDALNearblackDestName" "', argument " "2"" of type '" "GDALDatasetShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< GDALDatasetShadow * >(argp2);
+  res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_GDALNearblackOptions, 0 |  0 );
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "wrapper_GDALNearblackDestName" "', argument " "3"" of type '" "GDALNearblackOptions *""'"); 
+  }
+  arg3 = reinterpret_cast< GDALNearblackOptions * >(argp3);
+  if (obj3) {
+    {
+      /* %typemap(in) (GDALProgressFunc callback = NULL) */
+      /* callback_func typemap */
+      if (obj3 && obj3 != Py_None ) {
+        void* cbfunction = NULL;
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
+        
+        if ( cbfunction == GDALTermProgress ) {
+          arg4 = GDALTermProgress;
+        } else {
+          if (!PyCallable_Check(obj3)) {
+            PyErr_SetString( PyExc_RuntimeError,
+              "Object given is not a Python function" );
+            SWIG_fail;
+          }
+          psProgressInfo->psPyCallback = obj3;
+          arg4 = PyProgressProxy;
+        }
+        
+      }
+      
+    }
+  }
+  if (obj4) {
+    {
+      /* %typemap(in) ( void* callback_data=NULL)  */
+      psProgressInfo->psPyCallbackData = obj4 ;
+    }
+  }
+  {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (GDALDatasetShadow *)wrapper_GDALNearblackDestName((char const *)arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_POINTER_OWN |  0 );
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
+  }
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
+  }
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_new_GDALGridOptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  char **arg1 = (char **) 0 ;
+  PyObject * obj0 = 0 ;
+  GDALGridOptions *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:new_GDALGridOptions",&obj0)) SWIG_fail;
+  {
+    /* %typemap(in) char **options */
+    /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+    if ( ! PySequence_Check(obj0) || PyUnicode_Check(obj0)
+  #if PY_VERSION_HEX < 0x03000000
+      || PyString_Check(obj0)
+  #endif
+      ) {
+      PyErr_SetString(PyExc_TypeError,"not a sequence");
+      SWIG_fail;
+    }
+    
+    Py_ssize_t size = PySequence_Size(obj0);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    for (int i = 0; i < (int)size; i++) {
+      PyObject* pyObj = PySequence_GetItem(obj0,i);
+      if (PyUnicode_Check(pyObj))
+      {
+        char *pszStr;
+        Py_ssize_t nLen;
+        PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+        PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+        PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+        arg1 = CSLAddString( arg1, pszStr );
+        Py_XDECREF(pyUTF8Str);
+      }
+#if PY_VERSION_HEX >= 0x03000000
+      else if (PyBytes_Check(pyObj))
+      arg1 = CSLAddString( arg1, PyBytes_AsString(pyObj) );
+#else
+      else if (PyString_Check(pyObj))
+      arg1 = CSLAddString( arg1, PyString_AsString(pyObj) );
+#endif
+      else
+      {
+        Py_DECREF(pyObj);
+        PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+        SWIG_fail;
+      }
+      Py_DECREF(pyObj);
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (GDALGridOptions *)new_GDALGridOptions(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALGridOptions, SWIG_POINTER_NEW |  0 );
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg1 );
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg1 );
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_delete_GDALGridOptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALGridOptions *arg1 = (GDALGridOptions *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:delete_GDALGridOptions",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALGridOptions, SWIG_POINTER_DISOWN |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_GDALGridOptions" "', argument " "1"" of type '" "GDALGridOptions *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALGridOptions * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    delete_GDALGridOptions(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *GDALGridOptions_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *obj;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
+  SWIG_TypeNewClientData(SWIGTYPE_p_GDALGridOptions, SWIG_NewClientData(obj));
+  return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject *_wrap_GridInternal(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  char *arg1 = (char *) 0 ;
+  GDALDatasetShadow *arg2 = (GDALDatasetShadow *) 0 ;
+  GDALGridOptions *arg3 = (GDALGridOptions *) 0 ;
+  GDALProgressFunc arg4 = (GDALProgressFunc) NULL ;
+  void *arg5 = (void *) NULL ;
+  int bToFree1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  void *argp3 = 0 ;
+  int res3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  GDALDatasetShadow *result = 0 ;
+  
+  /* %typemap(arginit) ( const char* callback_data=NULL)  */
+  PyProgressData *psProgressInfo;
+  psProgressInfo = (PyProgressData *) CPLCalloc(1,sizeof(PyProgressData));
+  psProgressInfo->nLastReported = -1;
+  psProgressInfo->psPyCallback = NULL;
+  psProgressInfo->psPyCallbackData = NULL;
+  arg5 = psProgressInfo;
+  if (!PyArg_ParseTuple(args,(char *)"OOO|OO:GridInternal",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  {
+    /* %typemap(in) (const char *utf8_path) */
+    arg1 = GDALPythonObjectToCStr( obj0, &bToFree1 );
+    if (arg1 == NULL)
+    {
+      PyErr_SetString( PyExc_RuntimeError, "not a string" );
+      SWIG_fail;
+    }
+  }
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "GridInternal" "', argument " "2"" of type '" "GDALDatasetShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< GDALDatasetShadow * >(argp2);
+  res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_GDALGridOptions, 0 |  0 );
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "GridInternal" "', argument " "3"" of type '" "GDALGridOptions *""'"); 
+  }
+  arg3 = reinterpret_cast< GDALGridOptions * >(argp3);
+  if (obj3) {
+    {
+      /* %typemap(in) (GDALProgressFunc callback = NULL) */
+      /* callback_func typemap */
+      if (obj3 && obj3 != Py_None ) {
+        void* cbfunction = NULL;
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
+        
+        if ( cbfunction == GDALTermProgress ) {
+          arg4 = GDALTermProgress;
+        } else {
+          if (!PyCallable_Check(obj3)) {
+            PyErr_SetString( PyExc_RuntimeError,
+              "Object given is not a Python function" );
+            SWIG_fail;
+          }
+          psProgressInfo->psPyCallback = obj3;
+          arg4 = PyProgressProxy;
+        }
+        
+      }
+      
+    }
+  }
+  if (obj4) {
+    {
+      /* %typemap(in) ( void* callback_data=NULL)  */
+      psProgressInfo->psPyCallbackData = obj4 ;
+    }
+  }
+  {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (GDALDatasetShadow *)wrapper_GDALGrid((char const *)arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_POINTER_OWN |  0 );
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
+  }
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
+  }
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_new_GDALRasterizeOptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  char **arg1 = (char **) 0 ;
+  PyObject * obj0 = 0 ;
+  GDALRasterizeOptions *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:new_GDALRasterizeOptions",&obj0)) SWIG_fail;
+  {
+    /* %typemap(in) char **options */
+    /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+    if ( ! PySequence_Check(obj0) || PyUnicode_Check(obj0)
+  #if PY_VERSION_HEX < 0x03000000
+      || PyString_Check(obj0)
+  #endif
+      ) {
+      PyErr_SetString(PyExc_TypeError,"not a sequence");
+      SWIG_fail;
+    }
+    
+    Py_ssize_t size = PySequence_Size(obj0);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    for (int i = 0; i < (int)size; i++) {
+      PyObject* pyObj = PySequence_GetItem(obj0,i);
+      if (PyUnicode_Check(pyObj))
+      {
+        char *pszStr;
+        Py_ssize_t nLen;
+        PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+        PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+        PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+        arg1 = CSLAddString( arg1, pszStr );
+        Py_XDECREF(pyUTF8Str);
+      }
+#if PY_VERSION_HEX >= 0x03000000
+      else if (PyBytes_Check(pyObj))
+      arg1 = CSLAddString( arg1, PyBytes_AsString(pyObj) );
+#else
+      else if (PyString_Check(pyObj))
+      arg1 = CSLAddString( arg1, PyString_AsString(pyObj) );
+#endif
+      else
+      {
+        Py_DECREF(pyObj);
+        PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+        SWIG_fail;
+      }
+      Py_DECREF(pyObj);
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (GDALRasterizeOptions *)new_GDALRasterizeOptions(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALRasterizeOptions, SWIG_POINTER_NEW |  0 );
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg1 );
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg1 );
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_delete_GDALRasterizeOptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALRasterizeOptions *arg1 = (GDALRasterizeOptions *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:delete_GDALRasterizeOptions",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALRasterizeOptions, SWIG_POINTER_DISOWN |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_GDALRasterizeOptions" "', argument " "1"" of type '" "GDALRasterizeOptions *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALRasterizeOptions * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    delete_GDALRasterizeOptions(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *GDALRasterizeOptions_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *obj;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
+  SWIG_TypeNewClientData(SWIGTYPE_p_GDALRasterizeOptions, SWIG_NewClientData(obj));
+  return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject *_wrap_wrapper_GDALRasterizeDestDS(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
+  GDALDatasetShadow *arg2 = (GDALDatasetShadow *) 0 ;
+  GDALRasterizeOptions *arg3 = (GDALRasterizeOptions *) 0 ;
+  GDALProgressFunc arg4 = (GDALProgressFunc) NULL ;
+  void *arg5 = (void *) NULL ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  void *argp3 = 0 ;
+  int res3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  int result;
+  
+  /* %typemap(arginit) ( const char* callback_data=NULL)  */
+  PyProgressData *psProgressInfo;
+  psProgressInfo = (PyProgressData *) CPLCalloc(1,sizeof(PyProgressData));
+  psProgressInfo->nLastReported = -1;
+  psProgressInfo->psPyCallback = NULL;
+  psProgressInfo->psPyCallbackData = NULL;
+  arg5 = psProgressInfo;
+  if (!PyArg_ParseTuple(args,(char *)"OOO|OO:wrapper_GDALRasterizeDestDS",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "wrapper_GDALRasterizeDestDS" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "wrapper_GDALRasterizeDestDS" "', argument " "2"" of type '" "GDALDatasetShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< GDALDatasetShadow * >(argp2);
+  res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_GDALRasterizeOptions, 0 |  0 );
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "wrapper_GDALRasterizeDestDS" "', argument " "3"" of type '" "GDALRasterizeOptions *""'"); 
+  }
+  arg3 = reinterpret_cast< GDALRasterizeOptions * >(argp3);
+  if (obj3) {
+    {
+      /* %typemap(in) (GDALProgressFunc callback = NULL) */
+      /* callback_func typemap */
+      if (obj3 && obj3 != Py_None ) {
+        void* cbfunction = NULL;
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
+        
+        if ( cbfunction == GDALTermProgress ) {
+          arg4 = GDALTermProgress;
+        } else {
+          if (!PyCallable_Check(obj3)) {
+            PyErr_SetString( PyExc_RuntimeError,
+              "Object given is not a Python function" );
+            SWIG_fail;
+          }
+          psProgressInfo->psPyCallback = obj3;
+          arg4 = PyProgressProxy;
+        }
+        
+      }
+      
+    }
+  }
+  if (obj4) {
+    {
+      /* %typemap(in) ( void* callback_data=NULL)  */
+      psProgressInfo->psPyCallbackData = obj4 ;
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)wrapper_GDALRasterizeDestDS(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_wrapper_GDALRasterizeDestName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  char *arg1 = (char *) 0 ;
+  GDALDatasetShadow *arg2 = (GDALDatasetShadow *) 0 ;
+  GDALRasterizeOptions *arg3 = (GDALRasterizeOptions *) 0 ;
+  GDALProgressFunc arg4 = (GDALProgressFunc) NULL ;
+  void *arg5 = (void *) NULL ;
+  int bToFree1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  void *argp3 = 0 ;
+  int res3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  GDALDatasetShadow *result = 0 ;
+  
+  /* %typemap(arginit) ( const char* callback_data=NULL)  */
+  PyProgressData *psProgressInfo;
+  psProgressInfo = (PyProgressData *) CPLCalloc(1,sizeof(PyProgressData));
+  psProgressInfo->nLastReported = -1;
+  psProgressInfo->psPyCallback = NULL;
+  psProgressInfo->psPyCallbackData = NULL;
+  arg5 = psProgressInfo;
+  if (!PyArg_ParseTuple(args,(char *)"OOO|OO:wrapper_GDALRasterizeDestName",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  {
+    /* %typemap(in) (const char *utf8_path) */
+    arg1 = GDALPythonObjectToCStr( obj0, &bToFree1 );
+    if (arg1 == NULL)
+    {
+      PyErr_SetString( PyExc_RuntimeError, "not a string" );
+      SWIG_fail;
+    }
+  }
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "wrapper_GDALRasterizeDestName" "', argument " "2"" of type '" "GDALDatasetShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< GDALDatasetShadow * >(argp2);
+  res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_GDALRasterizeOptions, 0 |  0 );
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "wrapper_GDALRasterizeDestName" "', argument " "3"" of type '" "GDALRasterizeOptions *""'"); 
+  }
+  arg3 = reinterpret_cast< GDALRasterizeOptions * >(argp3);
+  if (obj3) {
+    {
+      /* %typemap(in) (GDALProgressFunc callback = NULL) */
+      /* callback_func typemap */
+      if (obj3 && obj3 != Py_None ) {
+        void* cbfunction = NULL;
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
+        
+        if ( cbfunction == GDALTermProgress ) {
+          arg4 = GDALTermProgress;
+        } else {
+          if (!PyCallable_Check(obj3)) {
+            PyErr_SetString( PyExc_RuntimeError,
+              "Object given is not a Python function" );
+            SWIG_fail;
+          }
+          psProgressInfo->psPyCallback = obj3;
+          arg4 = PyProgressProxy;
+        }
+        
+      }
+      
+    }
+  }
+  if (obj4) {
+    {
+      /* %typemap(in) ( void* callback_data=NULL)  */
+      psProgressInfo->psPyCallbackData = obj4 ;
+    }
+  }
+  {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (GDALDatasetShadow *)wrapper_GDALRasterizeDestName((char const *)arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_POINTER_OWN |  0 );
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
+  }
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
+  }
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_new_GDALBuildVRTOptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  char **arg1 = (char **) 0 ;
+  PyObject * obj0 = 0 ;
+  GDALBuildVRTOptions *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:new_GDALBuildVRTOptions",&obj0)) SWIG_fail;
+  {
+    /* %typemap(in) char **options */
+    /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+    if ( ! PySequence_Check(obj0) || PyUnicode_Check(obj0)
+  #if PY_VERSION_HEX < 0x03000000
+      || PyString_Check(obj0)
+  #endif
+      ) {
+      PyErr_SetString(PyExc_TypeError,"not a sequence");
+      SWIG_fail;
+    }
+    
+    Py_ssize_t size = PySequence_Size(obj0);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    for (int i = 0; i < (int)size; i++) {
+      PyObject* pyObj = PySequence_GetItem(obj0,i);
+      if (PyUnicode_Check(pyObj))
+      {
+        char *pszStr;
+        Py_ssize_t nLen;
+        PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+        PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+        PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+        arg1 = CSLAddString( arg1, pszStr );
+        Py_XDECREF(pyUTF8Str);
+      }
+#if PY_VERSION_HEX >= 0x03000000
+      else if (PyBytes_Check(pyObj))
+      arg1 = CSLAddString( arg1, PyBytes_AsString(pyObj) );
+#else
+      else if (PyString_Check(pyObj))
+      arg1 = CSLAddString( arg1, PyString_AsString(pyObj) );
+#endif
+      else
+      {
+        Py_DECREF(pyObj);
+        PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+        SWIG_fail;
+      }
+      Py_DECREF(pyObj);
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (GDALBuildVRTOptions *)new_GDALBuildVRTOptions(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALBuildVRTOptions, SWIG_POINTER_NEW |  0 );
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg1 );
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg1 );
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_delete_GDALBuildVRTOptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALBuildVRTOptions *arg1 = (GDALBuildVRTOptions *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:delete_GDALBuildVRTOptions",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALBuildVRTOptions, SWIG_POINTER_DISOWN |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_GDALBuildVRTOptions" "', argument " "1"" of type '" "GDALBuildVRTOptions *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALBuildVRTOptions * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    delete_GDALBuildVRTOptions(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *GDALBuildVRTOptions_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *obj;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
+  SWIG_TypeNewClientData(SWIGTYPE_p_GDALBuildVRTOptions, SWIG_NewClientData(obj));
+  return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject *_wrap_BuildVRTInternalObjects(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  char *arg1 = (char *) 0 ;
+  int arg2 ;
+  GDALDatasetShadow **arg3 = (GDALDatasetShadow **) 0 ;
+  GDALBuildVRTOptions *arg4 = (GDALBuildVRTOptions *) 0 ;
+  GDALProgressFunc arg5 = (GDALProgressFunc) NULL ;
+  void *arg6 = (void *) NULL ;
+  int bToFree1 = 0 ;
+  void *argp4 = 0 ;
+  int res4 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  GDALDatasetShadow *result = 0 ;
+  
+  /* %typemap(arginit) ( const char* callback_data=NULL)  */
+  PyProgressData *psProgressInfo;
+  psProgressInfo = (PyProgressData *) CPLCalloc(1,sizeof(PyProgressData));
+  psProgressInfo->nLastReported = -1;
+  psProgressInfo->psPyCallback = NULL;
+  psProgressInfo->psPyCallbackData = NULL;
+  arg6 = psProgressInfo;
+  if (!PyArg_ParseTuple(args,(char *)"OOO|OO:BuildVRTInternalObjects",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  {
+    /* %typemap(in) (const char *utf8_path) */
+    arg1 = GDALPythonObjectToCStr( obj0, &bToFree1 );
+    if (arg1 == NULL)
+    {
+      PyErr_SetString( PyExc_RuntimeError, "not a string" );
+      SWIG_fail;
+    }
+  }
+  {
+    /*  OBJECT_LIST_INPUT %typemap(in) (int itemcount, GDALDatasetShadow *optional_##GDALDatasetShadow)*/
+    if ( !PySequence_Check(obj1) ) {
+      PyErr_SetString(PyExc_TypeError, "not a sequence");
+      SWIG_fail;
+    }
+    Py_ssize_t size = PySequence_Size(obj1);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    arg2 = (int)size;
+    arg3 = (GDALDatasetShadow**) CPLMalloc(arg2*sizeof(GDALDatasetShadow*));
+    
+    for( int i = 0; i<arg2; i++ ) {
+      PyObject *o = PySequence_GetItem(obj1,i);
+#if 0x020012 <= 0x010337
+      PySwigObject *sobj = SWIG_Python_GetSwigThis(o);
+#else
+      SwigPyObject *sobj = SWIG_Python_GetSwigThis(o);
 #endif
-        else
-        {
-          Py_DECREF(pyObj);
-          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
-          SWIG_fail;
+      GDALDatasetShadow* rawobjectpointer = NULL;
+      if (!sobj) {
+        Py_DECREF(o);
+        SWIG_fail;
+      }
+      rawobjectpointer = (GDALDatasetShadow*) sobj->ptr;
+      arg3[i] = rawobjectpointer;
+      Py_DECREF(o);
+      
+    }
+  }
+  res4 = SWIG_ConvertPtr(obj2, &argp4,SWIGTYPE_p_GDALBuildVRTOptions, 0 |  0 );
+  if (!SWIG_IsOK(res4)) {
+    SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "BuildVRTInternalObjects" "', argument " "4"" of type '" "GDALBuildVRTOptions *""'"); 
+  }
+  arg4 = reinterpret_cast< GDALBuildVRTOptions * >(argp4);
+  if (obj3) {
+    {
+      /* %typemap(in) (GDALProgressFunc callback = NULL) */
+      /* callback_func typemap */
+      if (obj3 && obj3 != Py_None ) {
+        void* cbfunction = NULL;
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
+        
+        if ( cbfunction == GDALTermProgress ) {
+          arg5 = GDALTermProgress;
+        } else {
+          if (!PyCallable_Check(obj3)) {
+            PyErr_SetString( PyExc_RuntimeError,
+              "Object given is not a Python function" );
+            SWIG_fail;
+          }
+          psProgressInfo->psPyCallback = obj3;
+          arg5 = PyProgressProxy;
         }
-        Py_DECREF(pyObj);
+        
       }
+      
+    }
+  }
+  if (obj4) {
+    {
+      /* %typemap(in) ( void* callback_data=NULL)  */
+      psProgressInfo->psPyCallbackData = obj4 ;
     }
   }
   {
@@ -24000,23 +28941,32 @@ SWIGINTERN PyObject *_wrap_IdentifyDriver(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALDriverShadow *)IdentifyDriver((char const *)arg1,arg2);
+    result = (GDALDatasetShadow *)wrapper_GDALBuildVRT_objects((char const *)arg1,arg2,arg3,arg4,arg5,arg6);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDriverShadow, 0 |  0 );
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_POINTER_OWN |  0 );
   {
     /* %typemap(freearg) (const char *utf8_path) */
     GDALPythonFreeCStr(arg1, bToFree1);
   }
   {
-    /* %typemap(freearg) char **options */
-    CSLDestroy( arg2 );
+    /* OBJECT_LIST_INPUT %typemap(freearg) (int object_list_count, GDALDatasetShadow **poObjects)*/
+    CPLFree( arg3 );
+  }
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -24024,39 +28974,72 @@ fail:
     GDALPythonFreeCStr(arg1, bToFree1);
   }
   {
-    /* %typemap(freearg) char **options */
-    CSLDestroy( arg2 );
+    /* OBJECT_LIST_INPUT %typemap(freearg) (int object_list_count, GDALDatasetShadow **poObjects)*/
+    CPLFree( arg3 );
+  }
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
   }
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_GeneralCmdLineProcessor(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  char **arg1 = (char **) 0 ;
-  int arg2 = (int) 0 ;
-  int val2 ;
-  int ecode2 = 0 ;
+SWIGINTERN PyObject *_wrap_BuildVRTInternalNames(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  char *arg1 = (char *) 0 ;
+  char **arg2 = (char **) 0 ;
+  GDALBuildVRTOptions *arg3 = (GDALBuildVRTOptions *) 0 ;
+  GDALProgressFunc arg4 = (GDALProgressFunc) NULL ;
+  void *arg5 = (void *) NULL ;
+  int bToFree1 = 0 ;
+  void *argp3 = 0 ;
+  int res3 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  char **result = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  GDALDatasetShadow *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O|O:GeneralCmdLineProcessor",&obj0,&obj1)) SWIG_fail;
+  /* %typemap(arginit) ( const char* callback_data=NULL)  */
+  PyProgressData *psProgressInfo;
+  psProgressInfo = (PyProgressData *) CPLCalloc(1,sizeof(PyProgressData));
+  psProgressInfo->nLastReported = -1;
+  psProgressInfo->psPyCallback = NULL;
+  psProgressInfo->psPyCallbackData = NULL;
+  arg5 = psProgressInfo;
+  if (!PyArg_ParseTuple(args,(char *)"OOO|OO:BuildVRTInternalNames",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  {
+    /* %typemap(in) (const char *utf8_path) */
+    arg1 = GDALPythonObjectToCStr( obj0, &bToFree1 );
+    if (arg1 == NULL)
+    {
+      PyErr_SetString( PyExc_RuntimeError, "not a string" );
+      SWIG_fail;
+    }
+  }
   {
     /* %typemap(in) char **options */
     /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
-    if ( ! PySequence_Check(obj0) || PyUnicode_Check(obj0)
+    if ( ! PySequence_Check(obj1) || PyUnicode_Check(obj1)
   #if PY_VERSION_HEX < 0x03000000
-      || PyString_Check(obj0)
+      || PyString_Check(obj1)
   #endif
       ) {
       PyErr_SetString(PyExc_TypeError,"not a sequence");
       SWIG_fail;
     }
     
-    int size = PySequence_Size(obj0);
-    for (int i = 0; i < size; i++) {
-      PyObject* pyObj = PySequence_GetItem(obj0,i);
+    Py_ssize_t size = PySequence_Size(obj1);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    for (int i = 0; i < (int)size; i++) {
+      PyObject* pyObj = PySequence_GetItem(obj1,i);
       if (PyUnicode_Check(pyObj))
       {
         char *pszStr;
@@ -24067,15 +29050,15 @@ SWIGINTERN PyObject *_wrap_GeneralCmdLineProcessor(PyObject *SWIGUNUSEDPARM(self
 #else
         PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
 #endif
-        arg1 = CSLAddString( arg1, pszStr );
+        arg2 = CSLAddString( arg2, pszStr );
         Py_XDECREF(pyUTF8Str);
       }
 #if PY_VERSION_HEX >= 0x03000000
       else if (PyBytes_Check(pyObj))
-      arg1 = CSLAddString( arg1, PyBytes_AsString(pyObj) );
+      arg2 = CSLAddString( arg2, PyBytes_AsString(pyObj) );
 #else
       else if (PyString_Check(pyObj))
-      arg1 = CSLAddString( arg1, PyString_AsString(pyObj) );
+      arg2 = CSLAddString( arg2, PyString_AsString(pyObj) );
 #endif
       else
       {
@@ -24086,51 +29069,94 @@ SWIGINTERN PyObject *_wrap_GeneralCmdLineProcessor(PyObject *SWIGUNUSEDPARM(self
       Py_DECREF(pyObj);
     }
   }
-  if (obj1) {
-    ecode2 = SWIG_AsVal_int(obj1, &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "GeneralCmdLineProcessor" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
+  res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_GDALBuildVRTOptions, 0 |  0 );
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "BuildVRTInternalNames" "', argument " "3"" of type '" "GDALBuildVRTOptions *""'"); 
+  }
+  arg3 = reinterpret_cast< GDALBuildVRTOptions * >(argp3);
+  if (obj3) {
+    {
+      /* %typemap(in) (GDALProgressFunc callback = NULL) */
+      /* callback_func typemap */
+      if (obj3 && obj3 != Py_None ) {
+        void* cbfunction = NULL;
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
+        
+        if ( cbfunction == GDALTermProgress ) {
+          arg4 = GDALTermProgress;
+        } else {
+          if (!PyCallable_Check(obj3)) {
+            PyErr_SetString( PyExc_RuntimeError,
+              "Object given is not a Python function" );
+            SWIG_fail;
+          }
+          psProgressInfo->psPyCallback = obj3;
+          arg4 = PyProgressProxy;
+        }
+        
+      }
+      
+    }
+  }
+  if (obj4) {
+    {
+      /* %typemap(in) ( void* callback_data=NULL)  */
+      psProgressInfo->psPyCallbackData = obj4 ;
+    }
+  }
+  {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
   }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char **)GeneralCmdLineProcessor(arg1,arg2);
+    result = (GDALDatasetShadow *)wrapper_GDALBuildVRT_names((char const *)arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_POINTER_OWN |  0 );
   {
-    /* %typemap(out) char **CSL -> ( string ) */
-    char **stringarray = result;
-    if ( stringarray == NULL ) {
-      resultobj = Py_None;
-      Py_INCREF( resultobj );
-    }
-    else {
-      int len = CSLCount( stringarray );
-      resultobj = PyList_New( len );
-      for ( int i = 0; i < len; ++i ) {
-        PyObject *o = GDALPythonObjectFromCStr( stringarray[i] );
-        PyList_SetItem(resultobj, i, o );
-      }
-    }
-    CSLDestroy(result);
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
   }
   {
     /* %typemap(freearg) char **options */
-    CSLDestroy( arg1 );
+    CSLDestroy( arg2 );
+  }
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
+  }
+  {
     /* %typemap(freearg) char **options */
-    CSLDestroy( arg1 );
+    CSLDestroy( arg2 );
+  }
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
   }
   return NULL;
 }
@@ -24141,36 +29167,38 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"GetUseExceptions", _wrap_GetUseExceptions, METH_VARARGS, (char *)"GetUseExceptions() -> int"},
 	 { (char *)"UseExceptions", _wrap_UseExceptions, METH_VARARGS, (char *)"UseExceptions()"},
 	 { (char *)"DontUseExceptions", _wrap_DontUseExceptions, METH_VARARGS, (char *)"DontUseExceptions()"},
-	 { (char *)"VSIFReadL", _wrap_VSIFReadL, METH_VARARGS, (char *)"VSIFReadL(int nMembSize, int nMembCount, VSILFILE fp) -> int"},
-	 { (char *)"Debug", _wrap_Debug, METH_VARARGS, (char *)"Debug(char msg_class, char message)"},
-	 { (char *)"SetErrorHandler", _wrap_SetErrorHandler, METH_VARARGS, (char *)"SetErrorHandler(char pszCallbackName = None) -> CPLErr"},
-	 { (char *)"PushErrorHandler", _wrap_PushErrorHandler, METH_VARARGS, (char *)"PushErrorHandler(CPLErrorHandler pfnErrorHandler = None) -> CPLErr"},
+	 { (char *)"VSIFReadL", _wrap_VSIFReadL, METH_VARARGS, (char *)"VSIFReadL(int nMembSize, int nMembCount, VSILFILE * fp) -> int"},
+	 { (char *)"Debug", _wrap_Debug, METH_VARARGS, (char *)"Debug(char const * msg_class, char const * message)"},
+	 { (char *)"SetErrorHandler", _wrap_SetErrorHandler, METH_VARARGS, (char *)"SetErrorHandler(char const * pszCallbackName=None) -> CPLErr"},
+	 { (char *)"PushErrorHandler", _wrap_PushErrorHandler, METH_VARARGS, (char *)"PushErrorHandler(CPLErrorHandler pfnErrorHandler=0) -> CPLErr"},
 	 { (char *)"PopErrorHandler", _wrap_PopErrorHandler, METH_VARARGS, (char *)"PopErrorHandler()"},
-	 { (char *)"Error", _wrap_Error, METH_VARARGS, (char *)"Error(CPLErr msg_class = CE_Failure, int err_code = 0, char msg = \"error\")"},
-	 { (char *)"GOA2GetAuthorizationURL", _wrap_GOA2GetAuthorizationURL, METH_VARARGS, (char *)"GOA2GetAuthorizationURL(char pszScope) -> retStringAndCPLFree"},
-	 { (char *)"GOA2GetRefreshToken", _wrap_GOA2GetRefreshToken, METH_VARARGS, (char *)"GOA2GetRefreshToken(char pszAuthToken, char pszScope) -> retStringAndCPLFree"},
-	 { (char *)"GOA2GetAccessToken", _wrap_GOA2GetAccessToken, METH_VARARGS, (char *)"GOA2GetAccessToken(char pszRefreshToken, char pszScope) -> retStringAndCPLFree"},
+	 { (char *)"Error", _wrap_Error, METH_VARARGS, (char *)"Error(CPLErr msg_class=CE_Failure, int err_code=0, char const * msg=\"error\")"},
+	 { (char *)"GOA2GetAuthorizationURL", _wrap_GOA2GetAuthorizationURL, METH_VARARGS, (char *)"GOA2GetAuthorizationURL(char const * pszScope) -> retStringAndCPLFree *"},
+	 { (char *)"GOA2GetRefreshToken", _wrap_GOA2GetRefreshToken, METH_VARARGS, (char *)"GOA2GetRefreshToken(char const * pszAuthToken, char const * pszScope) -> retStringAndCPLFree *"},
+	 { (char *)"GOA2GetAccessToken", _wrap_GOA2GetAccessToken, METH_VARARGS, (char *)"GOA2GetAccessToken(char const * pszRefreshToken, char const * pszScope) -> retStringAndCPLFree *"},
 	 { (char *)"ErrorReset", _wrap_ErrorReset, METH_VARARGS, (char *)"ErrorReset()"},
-	 { (char *)"EscapeString", (PyCFunction) _wrap_EscapeString, METH_VARARGS | METH_KEYWORDS, (char *)"EscapeString(int len, int scheme = CPLES_SQL) -> retStringAndCPLFree"},
+	 { (char *)"EscapeString", (PyCFunction) _wrap_EscapeString, METH_VARARGS | METH_KEYWORDS, (char *)"EscapeString(int len, int scheme=CPLES_SQL) -> retStringAndCPLFree *"},
 	 { (char *)"GetLastErrorNo", _wrap_GetLastErrorNo, METH_VARARGS, (char *)"GetLastErrorNo() -> int"},
 	 { (char *)"GetLastErrorType", _wrap_GetLastErrorType, METH_VARARGS, (char *)"GetLastErrorType() -> int"},
-	 { (char *)"GetLastErrorMsg", _wrap_GetLastErrorMsg, METH_VARARGS, (char *)"GetLastErrorMsg() -> char"},
-	 { (char *)"PushFinderLocation", _wrap_PushFinderLocation, METH_VARARGS, (char *)"PushFinderLocation(char utf8_path)"},
+	 { (char *)"GetLastErrorMsg", _wrap_GetLastErrorMsg, METH_VARARGS, (char *)"GetLastErrorMsg() -> char const *"},
+	 { (char *)"VSIGetLastErrorNo", _wrap_VSIGetLastErrorNo, METH_VARARGS, (char *)"VSIGetLastErrorNo() -> int"},
+	 { (char *)"VSIGetLastErrorMsg", _wrap_VSIGetLastErrorMsg, METH_VARARGS, (char *)"VSIGetLastErrorMsg() -> char const *"},
+	 { (char *)"PushFinderLocation", _wrap_PushFinderLocation, METH_VARARGS, (char *)"PushFinderLocation(char const * utf8_path)"},
 	 { (char *)"PopFinderLocation", _wrap_PopFinderLocation, METH_VARARGS, (char *)"PopFinderLocation()"},
 	 { (char *)"FinderClean", _wrap_FinderClean, METH_VARARGS, (char *)"FinderClean()"},
-	 { (char *)"FindFile", _wrap_FindFile, METH_VARARGS, (char *)"FindFile(char pszClass, char utf8_path) -> char"},
-	 { (char *)"ReadDir", _wrap_ReadDir, METH_VARARGS, (char *)"ReadDir(char utf8_path) -> char"},
-	 { (char *)"ReadDirRecursive", _wrap_ReadDirRecursive, METH_VARARGS, (char *)"ReadDirRecursive(char utf8_path) -> char"},
-	 { (char *)"SetConfigOption", _wrap_SetConfigOption, METH_VARARGS, (char *)"SetConfigOption(char pszKey, char pszValue)"},
-	 { (char *)"GetConfigOption", _wrap_GetConfigOption, METH_VARARGS, (char *)"GetConfigOption(char pszKey, char pszDefault = None) -> char"},
-	 { (char *)"CPLBinaryToHex", _wrap_CPLBinaryToHex, METH_VARARGS, (char *)"CPLBinaryToHex(int nBytes) -> retStringAndCPLFree"},
-	 { (char *)"CPLHexToBinary", _wrap_CPLHexToBinary, METH_VARARGS, (char *)"CPLHexToBinary(char pszHex, int pnBytes) -> GByte"},
-	 { (char *)"FileFromMemBuffer", _wrap_FileFromMemBuffer, METH_VARARGS, (char *)"FileFromMemBuffer(char utf8_path, int nBytes)"},
-	 { (char *)"Unlink", _wrap_Unlink, METH_VARARGS, (char *)"Unlink(char utf8_path) -> VSI_RETVAL"},
+	 { (char *)"FindFile", _wrap_FindFile, METH_VARARGS, (char *)"FindFile(char const * pszClass, char const * utf8_path) -> char const *"},
+	 { (char *)"ReadDir", _wrap_ReadDir, METH_VARARGS, (char *)"ReadDir(char const * utf8_path, int nMaxFiles=0) -> char **"},
+	 { (char *)"ReadDirRecursive", _wrap_ReadDirRecursive, METH_VARARGS, (char *)"ReadDirRecursive(char const * utf8_path) -> char **"},
+	 { (char *)"SetConfigOption", _wrap_SetConfigOption, METH_VARARGS, (char *)"SetConfigOption(char const * pszKey, char const * pszValue)"},
+	 { (char *)"GetConfigOption", _wrap_GetConfigOption, METH_VARARGS, (char *)"GetConfigOption(char const * pszKey, char const * pszDefault=None) -> char const *"},
+	 { (char *)"CPLBinaryToHex", _wrap_CPLBinaryToHex, METH_VARARGS, (char *)"CPLBinaryToHex(int nBytes) -> retStringAndCPLFree *"},
+	 { (char *)"CPLHexToBinary", _wrap_CPLHexToBinary, METH_VARARGS, (char *)"CPLHexToBinary(char const * pszHex, int * pnBytes) -> GByte *"},
+	 { (char *)"FileFromMemBuffer", _wrap_FileFromMemBuffer, METH_VARARGS, (char *)"FileFromMemBuffer(char const * utf8_path, int nBytes)"},
+	 { (char *)"Unlink", _wrap_Unlink, METH_VARARGS, (char *)"Unlink(char const * utf8_path) -> VSI_RETVAL"},
 	 { (char *)"HasThreadSupport", _wrap_HasThreadSupport, METH_VARARGS, (char *)"HasThreadSupport() -> int"},
-	 { (char *)"Mkdir", _wrap_Mkdir, METH_VARARGS, (char *)"Mkdir(char utf8_path, int mode) -> VSI_RETVAL"},
-	 { (char *)"Rmdir", _wrap_Rmdir, METH_VARARGS, (char *)"Rmdir(char utf8_path) -> VSI_RETVAL"},
-	 { (char *)"Rename", _wrap_Rename, METH_VARARGS, (char *)"Rename(char pszOld, char pszNew) -> VSI_RETVAL"},
+	 { (char *)"Mkdir", _wrap_Mkdir, METH_VARARGS, (char *)"Mkdir(char const * utf8_path, int mode) -> VSI_RETVAL"},
+	 { (char *)"Rmdir", _wrap_Rmdir, METH_VARARGS, (char *)"Rmdir(char const * utf8_path) -> VSI_RETVAL"},
+	 { (char *)"Rename", _wrap_Rename, METH_VARARGS, (char *)"Rename(char const * pszOld, char const * pszNew) -> VSI_RETVAL"},
 	 { (char *)"StatBuf_mode_get", _wrap_StatBuf_mode_get, METH_VARARGS, (char *)"StatBuf_mode_get(StatBuf self) -> int"},
 	 { (char *)"StatBuf_size_get", _wrap_StatBuf_size_get, METH_VARARGS, (char *)"StatBuf_size_get(StatBuf self) -> GIntBig"},
 	 { (char *)"StatBuf_mtime_get", _wrap_StatBuf_mtime_get, METH_VARARGS, (char *)"StatBuf_mtime_get(StatBuf self) -> GIntBig"},
@@ -24178,41 +29206,41 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"delete_StatBuf", _wrap_delete_StatBuf, METH_VARARGS, (char *)"delete_StatBuf(StatBuf self)"},
 	 { (char *)"StatBuf_IsDirectory", _wrap_StatBuf_IsDirectory, METH_VARARGS, (char *)"StatBuf_IsDirectory(StatBuf self) -> int"},
 	 { (char *)"StatBuf_swigregister", StatBuf_swigregister, METH_VARARGS, NULL},
-	 { (char *)"VSIStatL", _wrap_VSIStatL, METH_VARARGS, (char *)"VSIStatL(char utf8_path, int nFlags = 0) -> int"},
-	 { (char *)"VSIFOpenL", _wrap_VSIFOpenL, METH_VARARGS, (char *)"VSIFOpenL(char utf8_path, char pszMode) -> VSILFILE"},
-	 { (char *)"VSIFCloseL", _wrap_VSIFCloseL, METH_VARARGS, (char *)"VSIFCloseL(VSILFILE arg0) -> VSI_RETVAL"},
-	 { (char *)"VSIFSeekL", _wrap_VSIFSeekL, METH_VARARGS, (char *)"VSIFSeekL(VSILFILE arg0, GIntBig arg1, int arg2) -> int"},
-	 { (char *)"VSIFTellL", _wrap_VSIFTellL, METH_VARARGS, (char *)"VSIFTellL(VSILFILE arg0) -> GIntBig"},
-	 { (char *)"VSIFTruncateL", _wrap_VSIFTruncateL, METH_VARARGS, (char *)"VSIFTruncateL(VSILFILE arg0, GIntBig arg1) -> int"},
-	 { (char *)"VSIFWriteL", _wrap_VSIFWriteL, METH_VARARGS, (char *)"VSIFWriteL(int nLen, int size, int memb, VSILFILE f) -> int"},
-	 { (char *)"MajorObject_GetDescription", _wrap_MajorObject_GetDescription, METH_VARARGS, (char *)"MajorObject_GetDescription(MajorObject self) -> char"},
-	 { (char *)"MajorObject_SetDescription", _wrap_MajorObject_SetDescription, METH_VARARGS, (char *)"MajorObject_SetDescription(MajorObject self, char pszNewDesc)"},
-	 { (char *)"MajorObject_GetMetadataDomainList", _wrap_MajorObject_GetMetadataDomainList, METH_VARARGS, (char *)"MajorObject_GetMetadataDomainList(MajorObject self) -> char"},
-	 { (char *)"MajorObject_GetMetadata_Dict", _wrap_MajorObject_GetMetadata_Dict, METH_VARARGS, (char *)"MajorObject_GetMetadata_Dict(MajorObject self, char pszDomain = \"\") -> char"},
-	 { (char *)"MajorObject_GetMetadata_List", _wrap_MajorObject_GetMetadata_List, METH_VARARGS, (char *)"MajorObject_GetMetadata_List(MajorObject self, char pszDomain = \"\") -> char"},
+	 { (char *)"VSIStatL", _wrap_VSIStatL, METH_VARARGS, (char *)"VSIStatL(char const * utf8_path, int nFlags=0) -> int"},
+	 { (char *)"VSIFOpenL", _wrap_VSIFOpenL, METH_VARARGS, (char *)"VSIFOpenL(char const * utf8_path, char const * pszMode) -> VSILFILE *"},
+	 { (char *)"VSIFOpenExL", _wrap_VSIFOpenExL, METH_VARARGS, (char *)"VSIFOpenExL(char const * utf8_path, char const * pszMode, int bSetError) -> VSILFILE *"},
+	 { (char *)"VSIFCloseL", _wrap_VSIFCloseL, METH_VARARGS, (char *)"VSIFCloseL(VSILFILE * fp) -> VSI_RETVAL"},
+	 { (char *)"VSIFSeekL", _wrap_VSIFSeekL, METH_VARARGS, (char *)"VSIFSeekL(VSILFILE * fp, GIntBig offset, int whence) -> int"},
+	 { (char *)"VSIFTellL", _wrap_VSIFTellL, METH_VARARGS, (char *)"VSIFTellL(VSILFILE * fp) -> GIntBig"},
+	 { (char *)"VSIFTruncateL", _wrap_VSIFTruncateL, METH_VARARGS, (char *)"VSIFTruncateL(VSILFILE * fp, GIntBig length) -> int"},
+	 { (char *)"VSIFWriteL", _wrap_VSIFWriteL, METH_VARARGS, (char *)"VSIFWriteL(int nLen, int size, int memb, VSILFILE * fp) -> int"},
+	 { (char *)"ParseCommandLine", _wrap_ParseCommandLine, METH_VARARGS, (char *)"ParseCommandLine(char const * utf8_path) -> char **"},
+	 { (char *)"MajorObject_GetDescription", _wrap_MajorObject_GetDescription, METH_VARARGS, (char *)"MajorObject_GetDescription(MajorObject self) -> char const *"},
+	 { (char *)"MajorObject_SetDescription", _wrap_MajorObject_SetDescription, METH_VARARGS, (char *)"MajorObject_SetDescription(MajorObject self, char const * pszNewDesc)"},
+	 { (char *)"MajorObject_GetMetadataDomainList", _wrap_MajorObject_GetMetadataDomainList, METH_VARARGS, (char *)"MajorObject_GetMetadataDomainList(MajorObject self) -> char **"},
+	 { (char *)"MajorObject_GetMetadata_Dict", _wrap_MajorObject_GetMetadata_Dict, METH_VARARGS, (char *)"MajorObject_GetMetadata_Dict(MajorObject self, char const * pszDomain=\"\") -> char **"},
+	 { (char *)"MajorObject_GetMetadata_List", _wrap_MajorObject_GetMetadata_List, METH_VARARGS, (char *)"MajorObject_GetMetadata_List(MajorObject self, char const * pszDomain=\"\") -> char **"},
 	 { (char *)"MajorObject_SetMetadata", _wrap_MajorObject_SetMetadata, METH_VARARGS, (char *)"\n"
-		"SetMetadata(char papszMetadata, char pszDomain = \"\") -> CPLErr\n"
-		"MajorObject_SetMetadata(MajorObject self, char pszMetadataString, char pszDomain = \"\") -> CPLErr\n"
+		"SetMetadata(char ** papszMetadata, char const * pszDomain=\"\") -> CPLErr\n"
+		"MajorObject_SetMetadata(MajorObject self, char * pszMetadataString, char const * pszDomain=\"\") -> CPLErr\n"
 		""},
-	 { (char *)"MajorObject_GetMetadataItem", _wrap_MajorObject_GetMetadataItem, METH_VARARGS, (char *)"MajorObject_GetMetadataItem(MajorObject self, char pszName, char pszDomain = \"\") -> char"},
-	 { (char *)"MajorObject_SetMetadataItem", _wrap_MajorObject_SetMetadataItem, METH_VARARGS, (char *)"MajorObject_SetMetadataItem(MajorObject self, char pszName, char pszValue, char pszDomain = \"\") -> CPLErr"},
+	 { (char *)"MajorObject_GetMetadataItem", _wrap_MajorObject_GetMetadataItem, METH_VARARGS, (char *)"MajorObject_GetMetadataItem(MajorObject self, char const * pszName, char const * pszDomain=\"\") -> char const *"},
+	 { (char *)"MajorObject_SetMetadataItem", _wrap_MajorObject_SetMetadataItem, METH_VARARGS, (char *)"MajorObject_SetMetadataItem(MajorObject self, char const * pszName, char const * pszValue, char const * pszDomain=\"\") -> CPLErr"},
 	 { (char *)"MajorObject_swigregister", MajorObject_swigregister, METH_VARARGS, NULL},
-	 { (char *)"Driver_ShortName_get", _wrap_Driver_ShortName_get, METH_VARARGS, (char *)"Driver_ShortName_get(Driver self) -> char"},
-	 { (char *)"Driver_LongName_get", _wrap_Driver_LongName_get, METH_VARARGS, (char *)"Driver_LongName_get(Driver self) -> char"},
-	 { (char *)"Driver_HelpTopic_get", _wrap_Driver_HelpTopic_get, METH_VARARGS, (char *)"Driver_HelpTopic_get(Driver self) -> char"},
+	 { (char *)"Driver_ShortName_get", _wrap_Driver_ShortName_get, METH_VARARGS, (char *)"Driver_ShortName_get(Driver self) -> char const *"},
+	 { (char *)"Driver_LongName_get", _wrap_Driver_LongName_get, METH_VARARGS, (char *)"Driver_LongName_get(Driver self) -> char const *"},
+	 { (char *)"Driver_HelpTopic_get", _wrap_Driver_HelpTopic_get, METH_VARARGS, (char *)"Driver_HelpTopic_get(Driver self) -> char const *"},
 	 { (char *)"Driver_Create", (PyCFunction) _wrap_Driver_Create, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Driver_Create(Driver self, char utf8_path, int xsize, int ysize, \n"
-		"    int bands = 1, GDALDataType eType = GDT_Byte, \n"
-		"    char options = None) -> Dataset\n"
+		"Driver_Create(Driver self, char const * utf8_path, int xsize, int ysize, int bands=1, GDALDataType eType=GDT_Byte, \n"
+		"    char ** options=None) -> Dataset\n"
 		""},
 	 { (char *)"Driver_CreateCopy", (PyCFunction) _wrap_Driver_CreateCopy, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Driver_CreateCopy(Driver self, char utf8_path, Dataset src, int strict = 1, \n"
-		"    char options = None, GDALProgressFunc callback = None, \n"
-		"    void callback_data = None) -> Dataset\n"
+		"Driver_CreateCopy(Driver self, char const * utf8_path, Dataset src, int strict=1, char ** options=None, \n"
+		"    GDALProgressFunc callback=0, void * callback_data=None) -> Dataset\n"
 		""},
-	 { (char *)"Driver_Delete", _wrap_Driver_Delete, METH_VARARGS, (char *)"Driver_Delete(Driver self, char utf8_path) -> CPLErr"},
-	 { (char *)"Driver_Rename", _wrap_Driver_Rename, METH_VARARGS, (char *)"Driver_Rename(Driver self, char newName, char oldName) -> CPLErr"},
-	 { (char *)"Driver_CopyFiles", _wrap_Driver_CopyFiles, METH_VARARGS, (char *)"Driver_CopyFiles(Driver self, char newName, char oldName) -> CPLErr"},
+	 { (char *)"Driver_Delete", _wrap_Driver_Delete, METH_VARARGS, (char *)"Driver_Delete(Driver self, char const * utf8_path) -> CPLErr"},
+	 { (char *)"Driver_Rename", _wrap_Driver_Rename, METH_VARARGS, (char *)"Driver_Rename(Driver self, char const * newName, char const * oldName) -> CPLErr"},
+	 { (char *)"Driver_CopyFiles", _wrap_Driver_CopyFiles, METH_VARARGS, (char *)"Driver_CopyFiles(Driver self, char const * newName, char const * oldName) -> CPLErr"},
 	 { (char *)"Driver_Register", _wrap_Driver_Register, METH_VARARGS, (char *)"Driver_Register(Driver self) -> int"},
 	 { (char *)"Driver_Deregister", _wrap_Driver_Deregister, METH_VARARGS, (char *)"Driver_Deregister(Driver self)"},
 	 { (char *)"Driver_swigregister", Driver_swigregister, METH_VARARGS, NULL},
@@ -24224,8 +29252,6 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"ColorEntry_c3_get", _wrap_ColorEntry_c3_get, METH_VARARGS, (char *)"ColorEntry_c3_get(ColorEntry self) -> short"},
 	 { (char *)"ColorEntry_c4_set", _wrap_ColorEntry_c4_set, METH_VARARGS, (char *)"ColorEntry_c4_set(ColorEntry self, short c4)"},
 	 { (char *)"ColorEntry_c4_get", _wrap_ColorEntry_c4_get, METH_VARARGS, (char *)"ColorEntry_c4_get(ColorEntry self) -> short"},
-	 { (char *)"new_ColorEntry", _wrap_new_ColorEntry, METH_VARARGS, (char *)"new_ColorEntry() -> ColorEntry"},
-	 { (char *)"delete_ColorEntry", _wrap_delete_ColorEntry, METH_VARARGS, (char *)"delete_ColorEntry(ColorEntry self)"},
 	 { (char *)"ColorEntry_swigregister", ColorEntry_swigregister, METH_VARARGS, NULL},
 	 { (char *)"GCP_GCPX_set", _wrap_GCP_GCPX_set, METH_VARARGS, (char *)"GCP_GCPX_set(GCP self, double GCPX)"},
 	 { (char *)"GCP_GCPX_get", _wrap_GCP_GCPX_get, METH_VARARGS, (char *)"GCP_GCPX_get(GCP self) -> double"},
@@ -24237,14 +29263,13 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"GCP_GCPPixel_get", _wrap_GCP_GCPPixel_get, METH_VARARGS, (char *)"GCP_GCPPixel_get(GCP self) -> double"},
 	 { (char *)"GCP_GCPLine_set", _wrap_GCP_GCPLine_set, METH_VARARGS, (char *)"GCP_GCPLine_set(GCP self, double GCPLine)"},
 	 { (char *)"GCP_GCPLine_get", _wrap_GCP_GCPLine_get, METH_VARARGS, (char *)"GCP_GCPLine_get(GCP self) -> double"},
-	 { (char *)"GCP_Info_set", _wrap_GCP_Info_set, METH_VARARGS, (char *)"GCP_Info_set(GCP self, char Info)"},
-	 { (char *)"GCP_Info_get", _wrap_GCP_Info_get, METH_VARARGS, (char *)"GCP_Info_get(GCP self) -> char"},
-	 { (char *)"GCP_Id_set", _wrap_GCP_Id_set, METH_VARARGS, (char *)"GCP_Id_set(GCP self, char Id)"},
-	 { (char *)"GCP_Id_get", _wrap_GCP_Id_get, METH_VARARGS, (char *)"GCP_Id_get(GCP self) -> char"},
+	 { (char *)"GCP_Info_set", _wrap_GCP_Info_set, METH_VARARGS, (char *)"GCP_Info_set(GCP self, char * Info)"},
+	 { (char *)"GCP_Info_get", _wrap_GCP_Info_get, METH_VARARGS, (char *)"GCP_Info_get(GCP self) -> char *"},
+	 { (char *)"GCP_Id_set", _wrap_GCP_Id_set, METH_VARARGS, (char *)"GCP_Id_set(GCP self, char * Id)"},
+	 { (char *)"GCP_Id_get", _wrap_GCP_Id_get, METH_VARARGS, (char *)"GCP_Id_get(GCP self) -> char *"},
 	 { (char *)"new_GCP", _wrap_new_GCP, METH_VARARGS, (char *)"\n"
-		"new_GCP(double x = 0.0, double y = 0.0, double z = 0.0, double pixel = 0.0, \n"
-		"    double line = 0.0, char info = \"\", \n"
-		"    char id = \"\") -> GCP\n"
+		"new_GCP(double x=0.0, double y=0.0, double z=0.0, double pixel=0.0, double line=0.0, char const * info=\"\", \n"
+		"    char const * id=\"\") -> GCP\n"
 		""},
 	 { (char *)"delete_GCP", _wrap_delete_GCP, METH_VARARGS, (char *)"delete_GCP(GCP self)"},
 	 { (char *)"GCP_swigregister", GCP_swigregister, METH_VARARGS, NULL},
@@ -24258,17 +29283,14 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"GDAL_GCP_GCPPixel_set", _wrap_GDAL_GCP_GCPPixel_set, METH_VARARGS, (char *)"GDAL_GCP_GCPPixel_set(GCP gcp, double dfGCPPixel)"},
 	 { (char *)"GDAL_GCP_GCPLine_get", _wrap_GDAL_GCP_GCPLine_get, METH_VARARGS, (char *)"GDAL_GCP_GCPLine_get(GCP gcp) -> double"},
 	 { (char *)"GDAL_GCP_GCPLine_set", _wrap_GDAL_GCP_GCPLine_set, METH_VARARGS, (char *)"GDAL_GCP_GCPLine_set(GCP gcp, double dfGCPLine)"},
-	 { (char *)"GDAL_GCP_Info_get", _wrap_GDAL_GCP_Info_get, METH_VARARGS, (char *)"GDAL_GCP_Info_get(GCP gcp) -> char"},
-	 { (char *)"GDAL_GCP_Info_set", _wrap_GDAL_GCP_Info_set, METH_VARARGS, (char *)"GDAL_GCP_Info_set(GCP gcp, char pszInfo)"},
-	 { (char *)"GDAL_GCP_Id_get", _wrap_GDAL_GCP_Id_get, METH_VARARGS, (char *)"GDAL_GCP_Id_get(GCP gcp) -> char"},
-	 { (char *)"GDAL_GCP_Id_set", _wrap_GDAL_GCP_Id_set, METH_VARARGS, (char *)"GDAL_GCP_Id_set(GCP gcp, char pszId)"},
-	 { (char *)"GCPsToGeoTransform", _wrap_GCPsToGeoTransform, METH_VARARGS, (char *)"GCPsToGeoTransform(int nGCPs, int bApproxOK = 1) -> RETURN_NONE"},
+	 { (char *)"GDAL_GCP_Info_get", _wrap_GDAL_GCP_Info_get, METH_VARARGS, (char *)"GDAL_GCP_Info_get(GCP gcp) -> char const *"},
+	 { (char *)"GDAL_GCP_Info_set", _wrap_GDAL_GCP_Info_set, METH_VARARGS, (char *)"GDAL_GCP_Info_set(GCP gcp, char const * pszInfo)"},
+	 { (char *)"GDAL_GCP_Id_get", _wrap_GDAL_GCP_Id_get, METH_VARARGS, (char *)"GDAL_GCP_Id_get(GCP gcp) -> char const *"},
+	 { (char *)"GDAL_GCP_Id_set", _wrap_GDAL_GCP_Id_set, METH_VARARGS, (char *)"GDAL_GCP_Id_set(GCP gcp, char const * pszId)"},
+	 { (char *)"GCPsToGeoTransform", _wrap_GCPsToGeoTransform, METH_VARARGS, (char *)"GCPsToGeoTransform(int nGCPs, int bApproxOK=1) -> RETURN_NONE"},
 	 { (char *)"delete_VirtualMem", _wrap_delete_VirtualMem, METH_VARARGS, (char *)"delete_VirtualMem(VirtualMem self)"},
 	 { (char *)"VirtualMem_GetAddr", _wrap_VirtualMem_GetAddr, METH_VARARGS, (char *)"VirtualMem_GetAddr(VirtualMem self)"},
-	 { (char *)"VirtualMem_Pin", _wrap_VirtualMem_Pin, METH_VARARGS, (char *)"\n"
-		"VirtualMem_Pin(VirtualMem self, size_t start_offset = 0, size_t nsize = 0, \n"
-		"    int bWriteOp = 0)\n"
-		""},
+	 { (char *)"VirtualMem_Pin", _wrap_VirtualMem_Pin, METH_VARARGS, (char *)"VirtualMem_Pin(VirtualMem self, size_t start_offset=0, size_t nsize=0, int bWriteOp=0)"},
 	 { (char *)"VirtualMem_swigregister", VirtualMem_swigregister, METH_VARARGS, NULL},
 	 { (char *)"delete_AsyncReader", _wrap_delete_AsyncReader, METH_VARARGS, (char *)"delete_AsyncReader(AsyncReader self)"},
 	 { (char *)"AsyncReader_GetNextUpdatedRegion", _wrap_AsyncReader_GetNextUpdatedRegion, METH_VARARGS, (char *)"AsyncReader_GetNextUpdatedRegion(AsyncReader self, double timeout) -> GDALAsyncStatusType"},
@@ -24282,83 +29304,67 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"delete_Dataset", _wrap_delete_Dataset, METH_VARARGS, (char *)"delete_Dataset(Dataset self)"},
 	 { (char *)"Dataset_GetDriver", _wrap_Dataset_GetDriver, METH_VARARGS, (char *)"Dataset_GetDriver(Dataset self) -> Driver"},
 	 { (char *)"Dataset_GetRasterBand", _wrap_Dataset_GetRasterBand, METH_VARARGS, (char *)"Dataset_GetRasterBand(Dataset self, int nBand) -> Band"},
-	 { (char *)"Dataset_GetProjection", _wrap_Dataset_GetProjection, METH_VARARGS, (char *)"Dataset_GetProjection(Dataset self) -> char"},
-	 { (char *)"Dataset_GetProjectionRef", _wrap_Dataset_GetProjectionRef, METH_VARARGS, (char *)"Dataset_GetProjectionRef(Dataset self) -> char"},
-	 { (char *)"Dataset_SetProjection", _wrap_Dataset_SetProjection, METH_VARARGS, (char *)"Dataset_SetProjection(Dataset self, char prj) -> CPLErr"},
-	 { (char *)"Dataset_GetGeoTransform", (PyCFunction) _wrap_Dataset_GetGeoTransform, METH_VARARGS | METH_KEYWORDS, (char *)"Dataset_GetGeoTransform(Dataset self, int can_return_null = None)"},
-	 { (char *)"Dataset_SetGeoTransform", _wrap_Dataset_SetGeoTransform, METH_VARARGS, (char *)"Dataset_SetGeoTransform(Dataset self, double argin) -> CPLErr"},
+	 { (char *)"Dataset_GetProjection", _wrap_Dataset_GetProjection, METH_VARARGS, (char *)"Dataset_GetProjection(Dataset self) -> char const *"},
+	 { (char *)"Dataset_GetProjectionRef", _wrap_Dataset_GetProjectionRef, METH_VARARGS, (char *)"Dataset_GetProjectionRef(Dataset self) -> char const *"},
+	 { (char *)"Dataset_SetProjection", _wrap_Dataset_SetProjection, METH_VARARGS, (char *)"Dataset_SetProjection(Dataset self, char const * prj) -> CPLErr"},
+	 { (char *)"Dataset_GetGeoTransform", (PyCFunction) _wrap_Dataset_GetGeoTransform, METH_VARARGS | METH_KEYWORDS, (char *)"Dataset_GetGeoTransform(Dataset self, int * can_return_null=None)"},
+	 { (char *)"Dataset_SetGeoTransform", _wrap_Dataset_SetGeoTransform, METH_VARARGS, (char *)"Dataset_SetGeoTransform(Dataset self, double [6] argin) -> CPLErr"},
 	 { (char *)"Dataset_BuildOverviews", (PyCFunction) _wrap_Dataset_BuildOverviews, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Dataset_BuildOverviews(Dataset self, char resampling = \"NEAREST\", int overviewlist = 0, \n"
-		"    GDALProgressFunc callback = None, \n"
-		"    void callback_data = None) -> int\n"
+		"Dataset_BuildOverviews(Dataset self, char const * resampling=\"NEAREST\", int overviewlist=0, GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None) -> int\n"
 		""},
 	 { (char *)"Dataset_GetGCPCount", _wrap_Dataset_GetGCPCount, METH_VARARGS, (char *)"Dataset_GetGCPCount(Dataset self) -> int"},
-	 { (char *)"Dataset_GetGCPProjection", _wrap_Dataset_GetGCPProjection, METH_VARARGS, (char *)"Dataset_GetGCPProjection(Dataset self) -> char"},
+	 { (char *)"Dataset_GetGCPProjection", _wrap_Dataset_GetGCPProjection, METH_VARARGS, (char *)"Dataset_GetGCPProjection(Dataset self) -> char const *"},
 	 { (char *)"Dataset_GetGCPs", _wrap_Dataset_GetGCPs, METH_VARARGS, (char *)"Dataset_GetGCPs(Dataset self)"},
-	 { (char *)"Dataset_SetGCPs", _wrap_Dataset_SetGCPs, METH_VARARGS, (char *)"Dataset_SetGCPs(Dataset self, int nGCPs, char pszGCPProjection) -> CPLErr"},
+	 { (char *)"Dataset_SetGCPs", _wrap_Dataset_SetGCPs, METH_VARARGS, (char *)"Dataset_SetGCPs(Dataset self, int nGCPs, char const * pszGCPProjection) -> CPLErr"},
 	 { (char *)"Dataset_FlushCache", _wrap_Dataset_FlushCache, METH_VARARGS, (char *)"Dataset_FlushCache(Dataset self)"},
-	 { (char *)"Dataset_AddBand", (PyCFunction) _wrap_Dataset_AddBand, METH_VARARGS | METH_KEYWORDS, (char *)"Dataset_AddBand(Dataset self, GDALDataType datatype = GDT_Byte, char options = None) -> CPLErr"},
+	 { (char *)"Dataset_AddBand", (PyCFunction) _wrap_Dataset_AddBand, METH_VARARGS | METH_KEYWORDS, (char *)"Dataset_AddBand(Dataset self, GDALDataType datatype=GDT_Byte, char ** options=None) -> CPLErr"},
 	 { (char *)"Dataset_CreateMaskBand", _wrap_Dataset_CreateMaskBand, METH_VARARGS, (char *)"Dataset_CreateMaskBand(Dataset self, int nFlags) -> CPLErr"},
-	 { (char *)"Dataset_GetFileList", _wrap_Dataset_GetFileList, METH_VARARGS, (char *)"Dataset_GetFileList(Dataset self) -> char"},
+	 { (char *)"Dataset_GetFileList", _wrap_Dataset_GetFileList, METH_VARARGS, (char *)"Dataset_GetFileList(Dataset self) -> char **"},
 	 { (char *)"Dataset_WriteRaster", (PyCFunction) _wrap_Dataset_WriteRaster, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Dataset_WriteRaster(Dataset self, int xoff, int yoff, int xsize, int ysize, \n"
-		"    GIntBig buf_len, int buf_xsize = None, int buf_ysize = None, \n"
-		"    GDALDataType buf_type = None, \n"
-		"    int band_list = 0, int buf_pixel_space = None, \n"
-		"    int buf_line_space = None, int buf_band_space = None) -> CPLErr\n"
+		"Dataset_WriteRaster(Dataset self, int xoff, int yoff, int xsize, int ysize, GIntBig buf_len, int * buf_xsize=None, \n"
+		"    int * buf_ysize=None, GDALDataType * buf_type=None, int band_list=0, \n"
+		"    GIntBig * buf_pixel_space=None, GIntBig * buf_line_space=None, GIntBig * buf_band_space=None) -> CPLErr\n"
 		""},
 	 { (char *)"Dataset_BeginAsyncReader", (PyCFunction) _wrap_Dataset_BeginAsyncReader, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Dataset_BeginAsyncReader(Dataset self, int xOff, int yOff, int xSize, int ySize, \n"
-		"    int buf_len, int buf_xsize, int buf_ysize, \n"
-		"    GDALDataType bufType = (GDALDataType) 0, int band_list = 0, \n"
-		"    int nPixelSpace = 0, int nLineSpace = 0, \n"
-		"    int nBandSpace = 0, char options = None) -> AsyncReader\n"
+		"Dataset_BeginAsyncReader(Dataset self, int xOff, int yOff, int xSize, int ySize, int buf_len, int buf_xsize, \n"
+		"    int buf_ysize, GDALDataType bufType=(GDALDataType) 0, int band_list=0, int nPixelSpace=0, \n"
+		"    int nLineSpace=0, int nBandSpace=0, char ** options=None) -> AsyncReader\n"
 		""},
 	 { (char *)"Dataset_EndAsyncReader", _wrap_Dataset_EndAsyncReader, METH_VARARGS, (char *)"Dataset_EndAsyncReader(Dataset self, AsyncReader ario)"},
 	 { (char *)"Dataset_GetVirtualMem", (PyCFunction) _wrap_Dataset_GetVirtualMem, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Dataset_GetVirtualMem(Dataset self, GDALRWFlag eRWFlag, int nXOff, int nYOff, \n"
-		"    int nXSize, int nYSize, int nBufXSize, int nBufYSize, \n"
-		"    GDALDataType eBufType, int band_list, \n"
-		"    int bIsBandSequential, size_t nCacheSize, \n"
-		"    size_t nPageSizeHint, char options = None) -> VirtualMem\n"
+		"Dataset_GetVirtualMem(Dataset self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, int nBufXSize, \n"
+		"    int nBufYSize, GDALDataType eBufType, int band_list, int bIsBandSequential, \n"
+		"    size_t nCacheSize, size_t nPageSizeHint, char ** options=None) -> VirtualMem\n"
 		""},
 	 { (char *)"Dataset_GetTiledVirtualMem", (PyCFunction) _wrap_Dataset_GetTiledVirtualMem, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Dataset_GetTiledVirtualMem(Dataset self, GDALRWFlag eRWFlag, int nXOff, int nYOff, \n"
-		"    int nXSize, int nYSize, int nTileXSize, \n"
-		"    int nTileYSize, GDALDataType eBufType, int band_list, \n"
-		"    GDALTileOrganization eTileOrganization, \n"
-		"    size_t nCacheSize, char options = None) -> VirtualMem\n"
+		"Dataset_GetTiledVirtualMem(Dataset self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, int nTileXSize, \n"
+		"    int nTileYSize, GDALDataType eBufType, int band_list, GDALTileOrganization eTileOrganization, \n"
+		"    size_t nCacheSize, char ** options=None) -> VirtualMem\n"
 		""},
 	 { (char *)"Dataset_CreateLayer", (PyCFunction) _wrap_Dataset_CreateLayer, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Dataset_CreateLayer(Dataset self, char name, SpatialReference srs = None, \n"
-		"    OGRwkbGeometryType geom_type = wkbUnknown, \n"
-		"    char options = None) -> Layer\n"
+		"Dataset_CreateLayer(Dataset self, char const * name, SpatialReference srs=None, OGRwkbGeometryType geom_type=wkbUnknown, \n"
+		"    char ** options=None) -> Layer\n"
 		""},
-	 { (char *)"Dataset_CopyLayer", (PyCFunction) _wrap_Dataset_CopyLayer, METH_VARARGS | METH_KEYWORDS, (char *)"Dataset_CopyLayer(Dataset self, Layer src_layer, char new_name, char options = None) -> Layer"},
+	 { (char *)"Dataset_CopyLayer", (PyCFunction) _wrap_Dataset_CopyLayer, METH_VARARGS | METH_KEYWORDS, (char *)"Dataset_CopyLayer(Dataset self, Layer src_layer, char const * new_name, char ** options=None) -> Layer"},
 	 { (char *)"Dataset_DeleteLayer", _wrap_Dataset_DeleteLayer, METH_VARARGS, (char *)"Dataset_DeleteLayer(Dataset self, int index) -> OGRErr"},
 	 { (char *)"Dataset_GetLayerCount", _wrap_Dataset_GetLayerCount, METH_VARARGS, (char *)"Dataset_GetLayerCount(Dataset self) -> int"},
-	 { (char *)"Dataset_GetLayerByIndex", _wrap_Dataset_GetLayerByIndex, METH_VARARGS, (char *)"Dataset_GetLayerByIndex(Dataset self, int index = 0) -> Layer"},
-	 { (char *)"Dataset_GetLayerByName", _wrap_Dataset_GetLayerByName, METH_VARARGS, (char *)"Dataset_GetLayerByName(Dataset self, char layer_name) -> Layer"},
-	 { (char *)"Dataset_TestCapability", _wrap_Dataset_TestCapability, METH_VARARGS, (char *)"Dataset_TestCapability(Dataset self, char cap) -> bool"},
-	 { (char *)"Dataset_ExecuteSQL", (PyCFunction) _wrap_Dataset_ExecuteSQL, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Dataset_ExecuteSQL(Dataset self, char statement, Geometry spatialFilter = None, \n"
-		"    char dialect = \"\") -> Layer\n"
-		""},
+	 { (char *)"Dataset_GetLayerByIndex", _wrap_Dataset_GetLayerByIndex, METH_VARARGS, (char *)"Dataset_GetLayerByIndex(Dataset self, int index=0) -> Layer"},
+	 { (char *)"Dataset_GetLayerByName", _wrap_Dataset_GetLayerByName, METH_VARARGS, (char *)"Dataset_GetLayerByName(Dataset self, char const * layer_name) -> Layer"},
+	 { (char *)"Dataset_TestCapability", _wrap_Dataset_TestCapability, METH_VARARGS, (char *)"Dataset_TestCapability(Dataset self, char const * cap) -> bool"},
+	 { (char *)"Dataset_ExecuteSQL", (PyCFunction) _wrap_Dataset_ExecuteSQL, METH_VARARGS | METH_KEYWORDS, (char *)"Dataset_ExecuteSQL(Dataset self, char const * statement, Geometry spatialFilter=None, char const * dialect=\"\") -> Layer"},
 	 { (char *)"Dataset_ReleaseResultSet", _wrap_Dataset_ReleaseResultSet, METH_VARARGS, (char *)"Dataset_ReleaseResultSet(Dataset self, Layer layer)"},
 	 { (char *)"Dataset_GetStyleTable", _wrap_Dataset_GetStyleTable, METH_VARARGS, (char *)"Dataset_GetStyleTable(Dataset self) -> StyleTable"},
 	 { (char *)"Dataset_SetStyleTable", _wrap_Dataset_SetStyleTable, METH_VARARGS, (char *)"Dataset_SetStyleTable(Dataset self, StyleTable table)"},
-	 { (char *)"Dataset_StartTransaction", (PyCFunction) _wrap_Dataset_StartTransaction, METH_VARARGS | METH_KEYWORDS, (char *)"Dataset_StartTransaction(Dataset self, int force = True) -> OGRErr"},
+	 { (char *)"Dataset_StartTransaction", (PyCFunction) _wrap_Dataset_StartTransaction, METH_VARARGS | METH_KEYWORDS, (char *)"Dataset_StartTransaction(Dataset self, int force=False) -> OGRErr"},
 	 { (char *)"Dataset_CommitTransaction", _wrap_Dataset_CommitTransaction, METH_VARARGS, (char *)"Dataset_CommitTransaction(Dataset self) -> OGRErr"},
 	 { (char *)"Dataset_RollbackTransaction", _wrap_Dataset_RollbackTransaction, METH_VARARGS, (char *)"Dataset_RollbackTransaction(Dataset self) -> OGRErr"},
 	 { (char *)"Dataset_ReadRaster1", (PyCFunction) _wrap_Dataset_ReadRaster1, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Dataset_ReadRaster1(Dataset self, int xoff, int yoff, int xsize, int ysize, \n"
-		"    int buf_xsize = None, int buf_ysize = None, \n"
-		"    GDALDataType buf_type = None, int band_list = 0, \n"
-		"    GIntBig buf_pixel_space = None, GIntBig buf_line_space = None, \n"
-		"    GIntBig buf_band_space = None, \n"
-		"    GDALRIOResampleAlg resample_alg = GRIORA_NearestNeighbour, \n"
-		"    GDALProgressFunc callback = None, \n"
-		"    void callback_data = None) -> CPLErr\n"
+		"Dataset_ReadRaster1(Dataset self, int xoff, int yoff, int xsize, int ysize, int * buf_xsize=None, int * buf_ysize=None, \n"
+		"    GDALDataType * buf_type=None, int band_list=0, GIntBig * buf_pixel_space=None, \n"
+		"    GIntBig * buf_line_space=None, GIntBig * buf_band_space=None, \n"
+		"    GDALRIOResampleAlg resample_alg=GRIORA_NearestNeighbour, GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None) -> CPLErr\n"
 		""},
 	 { (char *)"Dataset_swigregister", Dataset_swigregister, METH_VARARGS, NULL},
 	 { (char *)"Band_XSize_get", _wrap_Band_XSize_get, METH_VARARGS, (char *)"Band_XSize_get(Band self) -> int"},
@@ -24373,10 +29379,11 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"Band_SetRasterColorInterpretation", _wrap_Band_SetRasterColorInterpretation, METH_VARARGS, (char *)"Band_SetRasterColorInterpretation(Band self, GDALColorInterp val) -> CPLErr"},
 	 { (char *)"Band_GetNoDataValue", _wrap_Band_GetNoDataValue, METH_VARARGS, (char *)"Band_GetNoDataValue(Band self)"},
 	 { (char *)"Band_SetNoDataValue", _wrap_Band_SetNoDataValue, METH_VARARGS, (char *)"Band_SetNoDataValue(Band self, double d) -> CPLErr"},
-	 { (char *)"Band_GetUnitType", _wrap_Band_GetUnitType, METH_VARARGS, (char *)"Band_GetUnitType(Band self) -> char"},
-	 { (char *)"Band_SetUnitType", _wrap_Band_SetUnitType, METH_VARARGS, (char *)"Band_SetUnitType(Band self, char val) -> CPLErr"},
-	 { (char *)"Band_GetRasterCategoryNames", _wrap_Band_GetRasterCategoryNames, METH_VARARGS, (char *)"Band_GetRasterCategoryNames(Band self) -> char"},
-	 { (char *)"Band_SetRasterCategoryNames", _wrap_Band_SetRasterCategoryNames, METH_VARARGS, (char *)"Band_SetRasterCategoryNames(Band self, char names) -> CPLErr"},
+	 { (char *)"Band_DeleteNoDataValue", _wrap_Band_DeleteNoDataValue, METH_VARARGS, (char *)"Band_DeleteNoDataValue(Band self) -> CPLErr"},
+	 { (char *)"Band_GetUnitType", _wrap_Band_GetUnitType, METH_VARARGS, (char *)"Band_GetUnitType(Band self) -> char const *"},
+	 { (char *)"Band_SetUnitType", _wrap_Band_SetUnitType, METH_VARARGS, (char *)"Band_SetUnitType(Band self, char const * val) -> CPLErr"},
+	 { (char *)"Band_GetRasterCategoryNames", _wrap_Band_GetRasterCategoryNames, METH_VARARGS, (char *)"Band_GetRasterCategoryNames(Band self) -> char **"},
+	 { (char *)"Band_SetRasterCategoryNames", _wrap_Band_SetRasterCategoryNames, METH_VARARGS, (char *)"Band_SetRasterCategoryNames(Band self, char ** names) -> CPLErr"},
 	 { (char *)"Band_GetMinimum", _wrap_Band_GetMinimum, METH_VARARGS, (char *)"Band_GetMinimum(Band self)"},
 	 { (char *)"Band_GetMaximum", _wrap_Band_GetMaximum, METH_VARARGS, (char *)"Band_GetMaximum(Band self)"},
 	 { (char *)"Band_GetOffset", _wrap_Band_GetOffset, METH_VARARGS, (char *)"Band_GetOffset(Band self)"},
@@ -24384,25 +29391,18 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"Band_SetOffset", _wrap_Band_SetOffset, METH_VARARGS, (char *)"Band_SetOffset(Band self, double val) -> CPLErr"},
 	 { (char *)"Band_SetScale", _wrap_Band_SetScale, METH_VARARGS, (char *)"Band_SetScale(Band self, double val) -> CPLErr"},
 	 { (char *)"Band_GetStatistics", _wrap_Band_GetStatistics, METH_VARARGS, (char *)"Band_GetStatistics(Band self, int approx_ok, int force) -> CPLErr"},
-	 { (char *)"Band_ComputeStatistics", _wrap_Band_ComputeStatistics, METH_VARARGS, (char *)"\n"
-		"Band_ComputeStatistics(Band self, bool approx_ok, GDALProgressFunc callback = None, \n"
-		"    void callback_data = None) -> CPLErr\n"
-		""},
+	 { (char *)"Band_ComputeStatistics", _wrap_Band_ComputeStatistics, METH_VARARGS, (char *)"Band_ComputeStatistics(Band self, bool approx_ok, GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr"},
 	 { (char *)"Band_SetStatistics", _wrap_Band_SetStatistics, METH_VARARGS, (char *)"Band_SetStatistics(Band self, double min, double max, double mean, double stddev) -> CPLErr"},
 	 { (char *)"Band_GetOverviewCount", _wrap_Band_GetOverviewCount, METH_VARARGS, (char *)"Band_GetOverviewCount(Band self) -> int"},
 	 { (char *)"Band_GetOverview", _wrap_Band_GetOverview, METH_VARARGS, (char *)"Band_GetOverview(Band self, int i) -> Band"},
-	 { (char *)"Band_Checksum", (PyCFunction) _wrap_Band_Checksum, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Band_Checksum(Band self, int xoff = 0, int yoff = 0, int xsize = None, \n"
-		"    int ysize = None) -> int\n"
-		""},
-	 { (char *)"Band_ComputeRasterMinMax", _wrap_Band_ComputeRasterMinMax, METH_VARARGS, (char *)"Band_ComputeRasterMinMax(Band self, int approx_ok = 0)"},
-	 { (char *)"Band_ComputeBandStats", _wrap_Band_ComputeBandStats, METH_VARARGS, (char *)"Band_ComputeBandStats(Band self, int samplestep = 1)"},
-	 { (char *)"Band_Fill", _wrap_Band_Fill, METH_VARARGS, (char *)"Band_Fill(Band self, double real_fill, double imag_fill = 0.0) -> CPLErr"},
+	 { (char *)"Band_Checksum", (PyCFunction) _wrap_Band_Checksum, METH_VARARGS | METH_KEYWORDS, (char *)"Band_Checksum(Band self, int xoff=0, int yoff=0, int * xsize=None, int * ysize=None) -> int"},
+	 { (char *)"Band_ComputeRasterMinMax", _wrap_Band_ComputeRasterMinMax, METH_VARARGS, (char *)"Band_ComputeRasterMinMax(Band self, int approx_ok=0)"},
+	 { (char *)"Band_ComputeBandStats", _wrap_Band_ComputeBandStats, METH_VARARGS, (char *)"Band_ComputeBandStats(Band self, int samplestep=1)"},
+	 { (char *)"Band_Fill", _wrap_Band_Fill, METH_VARARGS, (char *)"Band_Fill(Band self, double real_fill, double imag_fill=0.0) -> CPLErr"},
 	 { (char *)"Band_WriteRaster", (PyCFunction) _wrap_Band_WriteRaster, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Band_WriteRaster(Band self, int xoff, int yoff, int xsize, int ysize, \n"
-		"    GIntBig buf_len, int buf_xsize = None, int buf_ysize = None, \n"
-		"    int buf_type = None, int buf_pixel_space = None, \n"
-		"    int buf_line_space = None) -> CPLErr\n"
+		"Band_WriteRaster(Band self, int xoff, int yoff, int xsize, int ysize, GIntBig buf_len, int * buf_xsize=None, \n"
+		"    int * buf_ysize=None, int * buf_type=None, GIntBig * buf_pixel_space=None, \n"
+		"    GIntBig * buf_line_space=None) -> CPLErr\n"
 		""},
 	 { (char *)"Band_FlushCache", _wrap_Band_FlushCache, METH_VARARGS, (char *)"Band_FlushCache(Band self)"},
 	 { (char *)"Band_GetRasterColorTable", _wrap_Band_GetRasterColorTable, METH_VARARGS, (char *)"Band_GetRasterColorTable(Band self) -> ColorTable"},
@@ -24415,45 +29415,36 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"Band_GetMaskFlags", _wrap_Band_GetMaskFlags, METH_VARARGS, (char *)"Band_GetMaskFlags(Band self) -> int"},
 	 { (char *)"Band_CreateMaskBand", _wrap_Band_CreateMaskBand, METH_VARARGS, (char *)"Band_CreateMaskBand(Band self, int nFlags) -> CPLErr"},
 	 { (char *)"Band_GetHistogram", (PyCFunction) _wrap_Band_GetHistogram, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Band_GetHistogram(Band self, double min = -0.5, double max = 255.5, int buckets = 256, \n"
-		"    int include_out_of_range = 0, \n"
-		"    int approx_ok = 1, GDALProgressFunc callback = None, \n"
-		"    void callback_data = None) -> CPLErr\n"
+		"Band_GetHistogram(Band self, double min=-0.5, double max=255.5, int buckets=256, int include_out_of_range=0, \n"
+		"    int approx_ok=1, GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr\n"
 		""},
 	 { (char *)"Band_GetDefaultHistogram", (PyCFunction) _wrap_Band_GetDefaultHistogram, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Band_GetDefaultHistogram(Band self, double min_ret = None, double max_ret = None, \n"
-		"    int buckets_ret = None, GUIntBig ppanHistogram = None, \n"
-		"    int force = 1, GDALProgressFunc callback = None, \n"
-		"    void callback_data = None) -> CPLErr\n"
+		"Band_GetDefaultHistogram(Band self, double * min_ret=None, double * max_ret=None, int * buckets_ret=None, \n"
+		"    GUIntBig ** ppanHistogram=None, int force=1, GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr\n"
 		""},
 	 { (char *)"Band_SetDefaultHistogram", _wrap_Band_SetDefaultHistogram, METH_VARARGS, (char *)"Band_SetDefaultHistogram(Band self, double min, double max, int buckets_in) -> CPLErr"},
 	 { (char *)"Band_HasArbitraryOverviews", _wrap_Band_HasArbitraryOverviews, METH_VARARGS, (char *)"Band_HasArbitraryOverviews(Band self) -> bool"},
-	 { (char *)"Band_GetCategoryNames", _wrap_Band_GetCategoryNames, METH_VARARGS, (char *)"Band_GetCategoryNames(Band self) -> char"},
-	 { (char *)"Band_SetCategoryNames", _wrap_Band_SetCategoryNames, METH_VARARGS, (char *)"Band_SetCategoryNames(Band self, char papszCategoryNames) -> CPLErr"},
+	 { (char *)"Band_GetCategoryNames", _wrap_Band_GetCategoryNames, METH_VARARGS, (char *)"Band_GetCategoryNames(Band self) -> char **"},
+	 { (char *)"Band_SetCategoryNames", _wrap_Band_SetCategoryNames, METH_VARARGS, (char *)"Band_SetCategoryNames(Band self, char ** papszCategoryNames) -> CPLErr"},
 	 { (char *)"Band_GetVirtualMem", (PyCFunction) _wrap_Band_GetVirtualMem, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Band_GetVirtualMem(Band self, GDALRWFlag eRWFlag, int nXOff, int nYOff, \n"
-		"    int nXSize, int nYSize, int nBufXSize, int nBufYSize, \n"
-		"    GDALDataType eBufType, size_t nCacheSize, \n"
-		"    size_t nPageSizeHint, char options = None) -> VirtualMem\n"
+		"Band_GetVirtualMem(Band self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, int nBufXSize, \n"
+		"    int nBufYSize, GDALDataType eBufType, size_t nCacheSize, size_t nPageSizeHint, \n"
+		"    char ** options=None) -> VirtualMem\n"
 		""},
-	 { (char *)"Band_GetVirtualMemAuto", (PyCFunction) _wrap_Band_GetVirtualMemAuto, METH_VARARGS | METH_KEYWORDS, (char *)"Band_GetVirtualMemAuto(Band self, GDALRWFlag eRWFlag, char options = None) -> VirtualMem"},
+	 { (char *)"Band_GetVirtualMemAuto", (PyCFunction) _wrap_Band_GetVirtualMemAuto, METH_VARARGS | METH_KEYWORDS, (char *)"Band_GetVirtualMemAuto(Band self, GDALRWFlag eRWFlag, char ** options=None) -> VirtualMem"},
 	 { (char *)"Band_GetTiledVirtualMem", (PyCFunction) _wrap_Band_GetTiledVirtualMem, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Band_GetTiledVirtualMem(Band self, GDALRWFlag eRWFlag, int nXOff, int nYOff, \n"
-		"    int nXSize, int nYSize, int nTileXSize, int nTileYSize, \n"
-		"    GDALDataType eBufType, size_t nCacheSize, \n"
-		"    char options = None) -> VirtualMem\n"
+		"Band_GetTiledVirtualMem(Band self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, int nTileXSize, \n"
+		"    int nTileYSize, GDALDataType eBufType, size_t nCacheSize, char ** options=None) -> VirtualMem\n"
 		""},
 	 { (char *)"Band_ReadRaster1", (PyCFunction) _wrap_Band_ReadRaster1, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Band_ReadRaster1(Band self, int xoff, int yoff, int xsize, int ysize, \n"
-		"    int buf_xsize = None, int buf_ysize = None, \n"
-		"    int buf_type = None, GIntBig buf_pixel_space = None, \n"
-		"    GIntBig buf_line_space = None, GDALRIOResampleAlg resample_alg = GRIORA_NearestNeighbour, \n"
-		"    GDALProgressFunc callback = None, \n"
-		"    void callback_data = None) -> CPLErr\n"
+		"Band_ReadRaster1(Band self, double xoff, double yoff, double xsize, double ysize, int * buf_xsize=None, \n"
+		"    int * buf_ysize=None, int * buf_type=None, GIntBig * buf_pixel_space=None, \n"
+		"    GIntBig * buf_line_space=None, GDALRIOResampleAlg resample_alg=GRIORA_NearestNeighbour, \n"
+		"    GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr\n"
 		""},
 	 { (char *)"Band_ReadBlock", (PyCFunction) _wrap_Band_ReadBlock, METH_VARARGS | METH_KEYWORDS, (char *)"Band_ReadBlock(Band self, int xoff, int yoff) -> CPLErr"},
 	 { (char *)"Band_swigregister", Band_swigregister, METH_VARARGS, NULL},
-	 { (char *)"new_ColorTable", (PyCFunction) _wrap_new_ColorTable, METH_VARARGS | METH_KEYWORDS, (char *)"new_ColorTable(GDALPaletteInterp palette = GPI_RGB) -> ColorTable"},
+	 { (char *)"new_ColorTable", (PyCFunction) _wrap_new_ColorTable, METH_VARARGS | METH_KEYWORDS, (char *)"new_ColorTable(GDALPaletteInterp palette=GPI_RGB) -> ColorTable"},
 	 { (char *)"delete_ColorTable", _wrap_delete_ColorTable, METH_VARARGS, (char *)"delete_ColorTable(ColorTable self)"},
 	 { (char *)"ColorTable_Clone", _wrap_ColorTable_Clone, METH_VARARGS, (char *)"ColorTable_Clone(ColorTable self) -> ColorTable"},
 	 { (char *)"ColorTable_GetPaletteInterpretation", _wrap_ColorTable_GetPaletteInterpretation, METH_VARARGS, (char *)"ColorTable_GetPaletteInterpretation(ColorTable self) -> GDALPaletteInterp"},
@@ -24461,119 +29452,104 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"ColorTable_GetColorEntry", _wrap_ColorTable_GetColorEntry, METH_VARARGS, (char *)"ColorTable_GetColorEntry(ColorTable self, int entry) -> ColorEntry"},
 	 { (char *)"ColorTable_GetColorEntryAsRGB", _wrap_ColorTable_GetColorEntryAsRGB, METH_VARARGS, (char *)"ColorTable_GetColorEntryAsRGB(ColorTable self, int entry, ColorEntry centry) -> int"},
 	 { (char *)"ColorTable_SetColorEntry", _wrap_ColorTable_SetColorEntry, METH_VARARGS, (char *)"ColorTable_SetColorEntry(ColorTable self, int entry, ColorEntry centry)"},
-	 { (char *)"ColorTable_CreateColorRamp", _wrap_ColorTable_CreateColorRamp, METH_VARARGS, (char *)"\n"
-		"ColorTable_CreateColorRamp(ColorTable self, int nStartIndex, ColorEntry startcolor, \n"
-		"    int nEndIndex, ColorEntry endcolor)\n"
-		""},
+	 { (char *)"ColorTable_CreateColorRamp", _wrap_ColorTable_CreateColorRamp, METH_VARARGS, (char *)"ColorTable_CreateColorRamp(ColorTable self, int nStartIndex, ColorEntry startcolor, int nEndIndex, ColorEntry endcolor)"},
 	 { (char *)"ColorTable_swigregister", ColorTable_swigregister, METH_VARARGS, NULL},
 	 { (char *)"new_RasterAttributeTable", _wrap_new_RasterAttributeTable, METH_VARARGS, (char *)"new_RasterAttributeTable() -> RasterAttributeTable"},
 	 { (char *)"delete_RasterAttributeTable", _wrap_delete_RasterAttributeTable, METH_VARARGS, (char *)"delete_RasterAttributeTable(RasterAttributeTable self)"},
 	 { (char *)"RasterAttributeTable_Clone", _wrap_RasterAttributeTable_Clone, METH_VARARGS, (char *)"RasterAttributeTable_Clone(RasterAttributeTable self) -> RasterAttributeTable"},
 	 { (char *)"RasterAttributeTable_GetColumnCount", _wrap_RasterAttributeTable_GetColumnCount, METH_VARARGS, (char *)"RasterAttributeTable_GetColumnCount(RasterAttributeTable self) -> int"},
-	 { (char *)"RasterAttributeTable_GetNameOfCol", _wrap_RasterAttributeTable_GetNameOfCol, METH_VARARGS, (char *)"RasterAttributeTable_GetNameOfCol(RasterAttributeTable self, int iCol) -> char"},
+	 { (char *)"RasterAttributeTable_GetNameOfCol", _wrap_RasterAttributeTable_GetNameOfCol, METH_VARARGS, (char *)"RasterAttributeTable_GetNameOfCol(RasterAttributeTable self, int iCol) -> char const *"},
 	 { (char *)"RasterAttributeTable_GetUsageOfCol", _wrap_RasterAttributeTable_GetUsageOfCol, METH_VARARGS, (char *)"RasterAttributeTable_GetUsageOfCol(RasterAttributeTable self, int iCol) -> GDALRATFieldUsage"},
 	 { (char *)"RasterAttributeTable_GetTypeOfCol", _wrap_RasterAttributeTable_GetTypeOfCol, METH_VARARGS, (char *)"RasterAttributeTable_GetTypeOfCol(RasterAttributeTable self, int iCol) -> GDALRATFieldType"},
 	 { (char *)"RasterAttributeTable_GetColOfUsage", _wrap_RasterAttributeTable_GetColOfUsage, METH_VARARGS, (char *)"RasterAttributeTable_GetColOfUsage(RasterAttributeTable self, GDALRATFieldUsage eUsage) -> int"},
 	 { (char *)"RasterAttributeTable_GetRowCount", _wrap_RasterAttributeTable_GetRowCount, METH_VARARGS, (char *)"RasterAttributeTable_GetRowCount(RasterAttributeTable self) -> int"},
-	 { (char *)"RasterAttributeTable_GetValueAsString", _wrap_RasterAttributeTable_GetValueAsString, METH_VARARGS, (char *)"RasterAttributeTable_GetValueAsString(RasterAttributeTable self, int iRow, int iCol) -> char"},
+	 { (char *)"RasterAttributeTable_GetValueAsString", _wrap_RasterAttributeTable_GetValueAsString, METH_VARARGS, (char *)"RasterAttributeTable_GetValueAsString(RasterAttributeTable self, int iRow, int iCol) -> char const *"},
 	 { (char *)"RasterAttributeTable_GetValueAsInt", _wrap_RasterAttributeTable_GetValueAsInt, METH_VARARGS, (char *)"RasterAttributeTable_GetValueAsInt(RasterAttributeTable self, int iRow, int iCol) -> int"},
 	 { (char *)"RasterAttributeTable_GetValueAsDouble", _wrap_RasterAttributeTable_GetValueAsDouble, METH_VARARGS, (char *)"RasterAttributeTable_GetValueAsDouble(RasterAttributeTable self, int iRow, int iCol) -> double"},
-	 { (char *)"RasterAttributeTable_SetValueAsString", _wrap_RasterAttributeTable_SetValueAsString, METH_VARARGS, (char *)"RasterAttributeTable_SetValueAsString(RasterAttributeTable self, int iRow, int iCol, char pszValue)"},
+	 { (char *)"RasterAttributeTable_SetValueAsString", _wrap_RasterAttributeTable_SetValueAsString, METH_VARARGS, (char *)"RasterAttributeTable_SetValueAsString(RasterAttributeTable self, int iRow, int iCol, char const * pszValue)"},
 	 { (char *)"RasterAttributeTable_SetValueAsInt", _wrap_RasterAttributeTable_SetValueAsInt, METH_VARARGS, (char *)"RasterAttributeTable_SetValueAsInt(RasterAttributeTable self, int iRow, int iCol, int nValue)"},
 	 { (char *)"RasterAttributeTable_SetValueAsDouble", _wrap_RasterAttributeTable_SetValueAsDouble, METH_VARARGS, (char *)"RasterAttributeTable_SetValueAsDouble(RasterAttributeTable self, int iRow, int iCol, double dfValue)"},
 	 { (char *)"RasterAttributeTable_SetRowCount", _wrap_RasterAttributeTable_SetRowCount, METH_VARARGS, (char *)"RasterAttributeTable_SetRowCount(RasterAttributeTable self, int nCount)"},
-	 { (char *)"RasterAttributeTable_CreateColumn", _wrap_RasterAttributeTable_CreateColumn, METH_VARARGS, (char *)"\n"
-		"RasterAttributeTable_CreateColumn(RasterAttributeTable self, char pszName, GDALRATFieldType eType, \n"
-		"    GDALRATFieldUsage eUsage) -> int\n"
-		""},
+	 { (char *)"RasterAttributeTable_CreateColumn", _wrap_RasterAttributeTable_CreateColumn, METH_VARARGS, (char *)"RasterAttributeTable_CreateColumn(RasterAttributeTable self, char const * pszName, GDALRATFieldType eType, GDALRATFieldUsage eUsage) -> int"},
 	 { (char *)"RasterAttributeTable_GetLinearBinning", _wrap_RasterAttributeTable_GetLinearBinning, METH_VARARGS, (char *)"RasterAttributeTable_GetLinearBinning(RasterAttributeTable self) -> bool"},
 	 { (char *)"RasterAttributeTable_SetLinearBinning", _wrap_RasterAttributeTable_SetLinearBinning, METH_VARARGS, (char *)"RasterAttributeTable_SetLinearBinning(RasterAttributeTable self, double dfRow0Min, double dfBinSize) -> int"},
 	 { (char *)"RasterAttributeTable_GetRowOfValue", _wrap_RasterAttributeTable_GetRowOfValue, METH_VARARGS, (char *)"RasterAttributeTable_GetRowOfValue(RasterAttributeTable self, double dfValue) -> int"},
 	 { (char *)"RasterAttributeTable_ChangesAreWrittenToFile", _wrap_RasterAttributeTable_ChangesAreWrittenToFile, METH_VARARGS, (char *)"RasterAttributeTable_ChangesAreWrittenToFile(RasterAttributeTable self) -> int"},
 	 { (char *)"RasterAttributeTable_DumpReadable", _wrap_RasterAttributeTable_DumpReadable, METH_VARARGS, (char *)"RasterAttributeTable_DumpReadable(RasterAttributeTable self)"},
 	 { (char *)"RasterAttributeTable_swigregister", RasterAttributeTable_swigregister, METH_VARARGS, NULL},
-	 { (char *)"TermProgress_nocb", (PyCFunction) _wrap_TermProgress_nocb, METH_VARARGS | METH_KEYWORDS, (char *)"TermProgress_nocb(double dfProgress, char pszMessage = None, void pData = None) -> int"},
+	 { (char *)"TermProgress_nocb", (PyCFunction) _wrap_TermProgress_nocb, METH_VARARGS | METH_KEYWORDS, (char *)"TermProgress_nocb(double dfProgress, char const * pszMessage=None, void * pData=None) -> int"},
 	 { (char *)"ComputeMedianCutPCT", (PyCFunction) _wrap_ComputeMedianCutPCT, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"ComputeMedianCutPCT(Band red, Band green, Band blue, int num_colors, ColorTable colors, \n"
-		"    GDALProgressFunc callback = None, \n"
-		"    void callback_data = None) -> int\n"
+		"ComputeMedianCutPCT(Band red, Band green, Band blue, int num_colors, ColorTable colors, GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None) -> int\n"
 		""},
 	 { (char *)"DitherRGB2PCT", (PyCFunction) _wrap_DitherRGB2PCT, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"DitherRGB2PCT(Band red, Band green, Band blue, Band target, ColorTable colors, \n"
-		"    GDALProgressFunc callback = None, \n"
-		"    void callback_data = None) -> int\n"
+		"DitherRGB2PCT(Band red, Band green, Band blue, Band target, ColorTable colors, GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None) -> int\n"
 		""},
-	 { (char *)"ReprojectImage", _wrap_ReprojectImage, METH_VARARGS, (char *)"\n"
-		"ReprojectImage(Dataset src_ds, Dataset dst_ds, char src_wkt = None, \n"
-		"    char dst_wkt = None, GDALResampleAlg eResampleAlg = GRA_NearestNeighbour, \n"
-		"    double WarpMemoryLimit = 0.0, \n"
-		"    double maxerror = 0.0, GDALProgressFunc callback = None, \n"
-		"    void callback_data = None) -> CPLErr\n"
+	 { (char *)"ReprojectImage", (PyCFunction) _wrap_ReprojectImage, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
+		"ReprojectImage(Dataset src_ds, Dataset dst_ds, char const * src_wkt=None, char const * dst_wkt=None, \n"
+		"    GDALResampleAlg eResampleAlg=GRA_NearestNeighbour, double WarpMemoryLimit=0.0, \n"
+		"    double maxerror=0.0, GDALProgressFunc callback=0, void * callback_data=None, \n"
+		"    char ** options=None) -> CPLErr\n"
 		""},
 	 { (char *)"ComputeProximity", (PyCFunction) _wrap_ComputeProximity, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"ComputeProximity(Band srcBand, Band proximityBand, char options = None, \n"
-		"    GDALProgressFunc callback = None, void callback_data = None) -> int\n"
+		"ComputeProximity(Band srcBand, Band proximityBand, char ** options=None, GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None) -> int\n"
 		""},
 	 { (char *)"RasterizeLayer", (PyCFunction) _wrap_RasterizeLayer, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"RasterizeLayer(Dataset dataset, int bands, Layer layer, void pfnTransformer = None, \n"
-		"    void pTransformArg = None, \n"
-		"    int burn_values = 0, char options = None, GDALProgressFunc callback = None, \n"
-		"    void callback_data = None) -> int\n"
+		"RasterizeLayer(Dataset dataset, int bands, Layer layer, void * pfnTransformer=None, void * pTransformArg=None, \n"
+		"    int burn_values=0, char ** options=None, GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None) -> int\n"
 		""},
 	 { (char *)"Polygonize", (PyCFunction) _wrap_Polygonize, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Polygonize(Band srcBand, Band maskBand, Layer outLayer, int iPixValField, \n"
-		"    char options = None, GDALProgressFunc callback = None, \n"
-		"    void callback_data = None) -> int\n"
+		"Polygonize(Band srcBand, Band maskBand, Layer outLayer, int iPixValField, char ** options=None, \n"
+		"    GDALProgressFunc callback=0, void * callback_data=None) -> int\n"
+		""},
+	 { (char *)"FPolygonize", (PyCFunction) _wrap_FPolygonize, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
+		"FPolygonize(Band srcBand, Band maskBand, Layer outLayer, int iPixValField, char ** options=None, \n"
+		"    GDALProgressFunc callback=0, void * callback_data=None) -> int\n"
 		""},
 	 { (char *)"FillNodata", (PyCFunction) _wrap_FillNodata, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"FillNodata(Band targetBand, Band maskBand, double maxSearchDist, \n"
-		"    int smoothingIterations, char options = None, \n"
-		"    GDALProgressFunc callback = None, void callback_data = None) -> int\n"
+		"FillNodata(Band targetBand, Band maskBand, double maxSearchDist, int smoothingIterations, char ** options=None, \n"
+		"    GDALProgressFunc callback=0, void * callback_data=None) -> int\n"
 		""},
 	 { (char *)"SieveFilter", (PyCFunction) _wrap_SieveFilter, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SieveFilter(Band srcBand, Band maskBand, Band dstBand, int threshold, \n"
-		"    int connectedness = 4, char options = None, \n"
-		"    GDALProgressFunc callback = None, void callback_data = None) -> int\n"
+		"SieveFilter(Band srcBand, Band maskBand, Band dstBand, int threshold, int connectedness=4, char ** options=None, \n"
+		"    GDALProgressFunc callback=0, void * callback_data=None) -> int\n"
 		""},
 	 { (char *)"RegenerateOverviews", (PyCFunction) _wrap_RegenerateOverviews, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"RegenerateOverviews(Band srcBand, int overviewBandCount, char resampling = \"average\", \n"
-		"    GDALProgressFunc callback = None, \n"
-		"    void callback_data = None) -> int\n"
+		"RegenerateOverviews(Band srcBand, int overviewBandCount, char const * resampling=\"average\", GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None) -> int\n"
 		""},
 	 { (char *)"RegenerateOverview", (PyCFunction) _wrap_RegenerateOverview, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"RegenerateOverview(Band srcBand, Band overviewBand, char resampling = \"average\", \n"
-		"    GDALProgressFunc callback = None, \n"
-		"    void callback_data = None) -> int\n"
+		"RegenerateOverview(Band srcBand, Band overviewBand, char const * resampling=\"average\", GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None) -> int\n"
 		""},
 	 { (char *)"ContourGenerate", (PyCFunction) _wrap_ContourGenerate, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"ContourGenerate(Band srcBand, double contourInterval, double contourBase, \n"
-		"    int fixedLevelCount, int useNoData, double noDataValue, \n"
-		"    Layer dstLayer, int idField, \n"
-		"    int elevField, GDALProgressFunc callback = None, \n"
-		"    void callback_data = None) -> int\n"
+		"ContourGenerate(Band srcBand, double contourInterval, double contourBase, int fixedLevelCount, int useNoData, \n"
+		"    double noDataValue, Layer dstLayer, int idField, int elevField, \n"
+		"    GDALProgressFunc callback=0, void * callback_data=None) -> int\n"
 		""},
 	 { (char *)"AutoCreateWarpedVRT", _wrap_AutoCreateWarpedVRT, METH_VARARGS, (char *)"\n"
-		"AutoCreateWarpedVRT(Dataset src_ds, char src_wkt = None, char dst_wkt = None, \n"
-		"    GDALResampleAlg eResampleAlg = GRA_NearestNeighbour, \n"
-		"    double maxerror = 0.0) -> Dataset\n"
+		"AutoCreateWarpedVRT(Dataset src_ds, char const * src_wkt=None, char const * dst_wkt=None, GDALResampleAlg eResampleAlg=GRA_NearestNeighbour, \n"
+		"    double maxerror=0.0) -> Dataset\n"
 		""},
-	 { (char *)"new_Transformer", _wrap_new_Transformer, METH_VARARGS, (char *)"new_Transformer(Dataset src, Dataset dst, char options) -> Transformer"},
+	 { (char *)"CreatePansharpenedVRT", _wrap_CreatePansharpenedVRT, METH_VARARGS, (char *)"CreatePansharpenedVRT(char const * pszXML, Band panchroBand, int nInputSpectralBands) -> Dataset"},
+	 { (char *)"new_Transformer", _wrap_new_Transformer, METH_VARARGS, (char *)"new_Transformer(Dataset src, Dataset dst, char ** options) -> Transformer"},
 	 { (char *)"delete_Transformer", _wrap_delete_Transformer, METH_VARARGS, (char *)"delete_Transformer(Transformer self)"},
 	 { (char *)"Transformer_TransformPoint", _wrap_Transformer_TransformPoint, METH_VARARGS, (char *)"\n"
-		"TransformPoint(int bDstToSrc, double inout) -> int\n"
-		"Transformer_TransformPoint(Transformer self, int bDstToSrc, double x, double y, \n"
-		"    double z = 0.0) -> int\n"
+		"TransformPoint(int bDstToSrc, double [3] inout) -> int\n"
+		"Transformer_TransformPoint(Transformer self, int bDstToSrc, double x, double y, double z=0.0) -> int\n"
 		""},
 	 { (char *)"Transformer_TransformPoints", _wrap_Transformer_TransformPoints, METH_VARARGS, (char *)"Transformer_TransformPoints(Transformer self, int bDstToSrc, int nCount) -> int"},
 	 { (char *)"Transformer_TransformGeolocations", (PyCFunction) _wrap_Transformer_TransformGeolocations, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Transformer_TransformGeolocations(Transformer self, Band xBand, Band yBand, Band zBand, \n"
-		"    GDALProgressFunc callback = None, void callback_data = None, \n"
-		"    char options = None) -> int\n"
+		"Transformer_TransformGeolocations(Transformer self, Band xBand, Band yBand, Band zBand, GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None, char ** options=None) -> int\n"
 		""},
 	 { (char *)"Transformer_swigregister", Transformer_swigregister, METH_VARARGS, NULL},
-	 { (char *)"ApplyGeoTransform", _wrap_ApplyGeoTransform, METH_VARARGS, (char *)"ApplyGeoTransform(double padfGeoTransform, double dfPixel, double dfLine)"},
-	 { (char *)"InvGeoTransform", _wrap_InvGeoTransform, METH_VARARGS, (char *)"InvGeoTransform(double gt_in) -> RETURN_NONE"},
-	 { (char *)"VersionInfo", _wrap_VersionInfo, METH_VARARGS, (char *)"VersionInfo(char request = \"VERSION_NUM\") -> char"},
+	 { (char *)"ApplyGeoTransform", _wrap_ApplyGeoTransform, METH_VARARGS, (char *)"ApplyGeoTransform(double [6] padfGeoTransform, double dfPixel, double dfLine)"},
+	 { (char *)"InvGeoTransform", _wrap_InvGeoTransform, METH_VARARGS, (char *)"InvGeoTransform(double [6] gt_in) -> RETURN_NONE"},
+	 { (char *)"VersionInfo", _wrap_VersionInfo, METH_VARARGS, (char *)"VersionInfo(char const * request=\"VERSION_NUM\") -> char const *"},
 	 { (char *)"AllRegister", _wrap_AllRegister, METH_VARARGS, (char *)"AllRegister()"},
 	 { (char *)"GDALDestroyDriverManager", _wrap_GDALDestroyDriverManager, METH_VARARGS, (char *)"GDALDestroyDriverManager()"},
 	 { (char *)"GetCacheMax", _wrap_GetCacheMax, METH_VARARGS, (char *)"GetCacheMax() -> GIntBig"},
@@ -24581,29 +29557,109 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"SetCacheMax", _wrap_SetCacheMax, METH_VARARGS, (char *)"SetCacheMax(GIntBig nBytes)"},
 	 { (char *)"GetDataTypeSize", _wrap_GetDataTypeSize, METH_VARARGS, (char *)"GetDataTypeSize(GDALDataType eDataType) -> int"},
 	 { (char *)"DataTypeIsComplex", _wrap_DataTypeIsComplex, METH_VARARGS, (char *)"DataTypeIsComplex(GDALDataType eDataType) -> int"},
-	 { (char *)"GetDataTypeName", _wrap_GetDataTypeName, METH_VARARGS, (char *)"GetDataTypeName(GDALDataType eDataType) -> char"},
-	 { (char *)"GetDataTypeByName", _wrap_GetDataTypeByName, METH_VARARGS, (char *)"GetDataTypeByName(char pszDataTypeName) -> GDALDataType"},
-	 { (char *)"GetColorInterpretationName", _wrap_GetColorInterpretationName, METH_VARARGS, (char *)"GetColorInterpretationName(GDALColorInterp eColorInterp) -> char"},
-	 { (char *)"GetPaletteInterpretationName", _wrap_GetPaletteInterpretationName, METH_VARARGS, (char *)"GetPaletteInterpretationName(GDALPaletteInterp ePaletteInterp) -> char"},
-	 { (char *)"DecToDMS", _wrap_DecToDMS, METH_VARARGS, (char *)"DecToDMS(double arg0, char arg1, int arg2 = 2) -> char"},
+	 { (char *)"GetDataTypeName", _wrap_GetDataTypeName, METH_VARARGS, (char *)"GetDataTypeName(GDALDataType eDataType) -> char const *"},
+	 { (char *)"GetDataTypeByName", _wrap_GetDataTypeByName, METH_VARARGS, (char *)"GetDataTypeByName(char const * pszDataTypeName) -> GDALDataType"},
+	 { (char *)"GetColorInterpretationName", _wrap_GetColorInterpretationName, METH_VARARGS, (char *)"GetColorInterpretationName(GDALColorInterp eColorInterp) -> char const *"},
+	 { (char *)"GetPaletteInterpretationName", _wrap_GetPaletteInterpretationName, METH_VARARGS, (char *)"GetPaletteInterpretationName(GDALPaletteInterp ePaletteInterp) -> char const *"},
+	 { (char *)"DecToDMS", _wrap_DecToDMS, METH_VARARGS, (char *)"DecToDMS(double arg1, char const * arg2, int arg3=2) -> char const *"},
 	 { (char *)"PackedDMSToDec", _wrap_PackedDMSToDec, METH_VARARGS, (char *)"PackedDMSToDec(double dfPacked) -> double"},
 	 { (char *)"DecToPackedDMS", _wrap_DecToPackedDMS, METH_VARARGS, (char *)"DecToPackedDMS(double dfDec) -> double"},
-	 { (char *)"ParseXMLString", _wrap_ParseXMLString, METH_VARARGS, (char *)"ParseXMLString(char pszXMLString) -> CPLXMLNode"},
-	 { (char *)"SerializeXMLTree", _wrap_SerializeXMLTree, METH_VARARGS, (char *)"SerializeXMLTree(CPLXMLNode xmlnode) -> retStringAndCPLFree"},
-	 { (char *)"GetJPEG2000Structure", _wrap_GetJPEG2000Structure, METH_VARARGS, (char *)"GetJPEG2000Structure(char pszFilename, char options = None) -> CPLXMLNode"},
-	 { (char *)"GetJPEG2000StructureAsString", _wrap_GetJPEG2000StructureAsString, METH_VARARGS, (char *)"GetJPEG2000StructureAsString(char pszFilename, char options = None) -> retStringAndCPLFree"},
+	 { (char *)"ParseXMLString", _wrap_ParseXMLString, METH_VARARGS, (char *)"ParseXMLString(char * pszXMLString) -> CPLXMLNode *"},
+	 { (char *)"SerializeXMLTree", _wrap_SerializeXMLTree, METH_VARARGS, (char *)"SerializeXMLTree(CPLXMLNode * xmlnode) -> retStringAndCPLFree *"},
+	 { (char *)"GetJPEG2000Structure", _wrap_GetJPEG2000Structure, METH_VARARGS, (char *)"GetJPEG2000Structure(char const * pszFilename, char ** options=None) -> CPLXMLNode *"},
+	 { (char *)"GetJPEG2000StructureAsString", _wrap_GetJPEG2000StructureAsString, METH_VARARGS, (char *)"GetJPEG2000StructureAsString(char const * pszFilename, char ** options=None) -> retStringAndCPLFree *"},
 	 { (char *)"GetDriverCount", _wrap_GetDriverCount, METH_VARARGS, (char *)"GetDriverCount() -> int"},
-	 { (char *)"GetDriverByName", _wrap_GetDriverByName, METH_VARARGS, (char *)"GetDriverByName(char name) -> Driver"},
+	 { (char *)"GetDriverByName", _wrap_GetDriverByName, METH_VARARGS, (char *)"GetDriverByName(char const * name) -> Driver"},
 	 { (char *)"GetDriver", _wrap_GetDriver, METH_VARARGS, (char *)"GetDriver(int i) -> Driver"},
-	 { (char *)"Open", _wrap_Open, METH_VARARGS, (char *)"Open(char utf8_path, GDALAccess eAccess = GA_ReadOnly) -> Dataset"},
+	 { (char *)"Open", _wrap_Open, METH_VARARGS, (char *)"Open(char const * utf8_path, GDALAccess eAccess=GA_ReadOnly) -> Dataset"},
 	 { (char *)"OpenEx", (PyCFunction) _wrap_OpenEx, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"OpenEx(char utf8_path, unsigned int nOpenFlags = 0, char allowed_drivers = None, \n"
-		"    char open_options = None, \n"
-		"    char sibling_files = None) -> Dataset\n"
+		"OpenEx(char const * utf8_path, unsigned int nOpenFlags=0, char ** allowed_drivers=None, \n"
+		"    char ** open_options=None, char ** sibling_files=None) -> Dataset\n"
+		""},
+	 { (char *)"OpenShared", _wrap_OpenShared, METH_VARARGS, (char *)"OpenShared(char const * utf8_path, GDALAccess eAccess=GA_ReadOnly) -> Dataset"},
+	 { (char *)"IdentifyDriver", _wrap_IdentifyDriver, METH_VARARGS, (char *)"IdentifyDriver(char const * utf8_path, char ** papszSiblings=None) -> Driver"},
+	 { (char *)"GeneralCmdLineProcessor", _wrap_GeneralCmdLineProcessor, METH_VARARGS, (char *)"GeneralCmdLineProcessor(char ** papszArgv, int nOptions=0) -> char **"},
+	 { (char *)"new_GDALInfoOptions", _wrap_new_GDALInfoOptions, METH_VARARGS, (char *)"new_GDALInfoOptions(char ** options) -> GDALInfoOptions"},
+	 { (char *)"delete_GDALInfoOptions", _wrap_delete_GDALInfoOptions, METH_VARARGS, (char *)"delete_GDALInfoOptions(GDALInfoOptions self)"},
+	 { (char *)"GDALInfoOptions_swigregister", GDALInfoOptions_swigregister, METH_VARARGS, NULL},
+	 { (char *)"InfoInternal", _wrap_InfoInternal, METH_VARARGS, (char *)"InfoInternal(Dataset hDataset, GDALInfoOptions infoOptions) -> retStringAndCPLFree *"},
+	 { (char *)"new_GDALTranslateOptions", _wrap_new_GDALTranslateOptions, METH_VARARGS, (char *)"new_GDALTranslateOptions(char ** options) -> GDALTranslateOptions"},
+	 { (char *)"delete_GDALTranslateOptions", _wrap_delete_GDALTranslateOptions, METH_VARARGS, (char *)"delete_GDALTranslateOptions(GDALTranslateOptions self)"},
+	 { (char *)"GDALTranslateOptions_swigregister", GDALTranslateOptions_swigregister, METH_VARARGS, NULL},
+	 { (char *)"TranslateInternal", _wrap_TranslateInternal, METH_VARARGS, (char *)"\n"
+		"TranslateInternal(char const * dest, Dataset dataset, GDALTranslateOptions translateOptions, GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None) -> Dataset\n"
+		""},
+	 { (char *)"new_GDALWarpAppOptions", _wrap_new_GDALWarpAppOptions, METH_VARARGS, (char *)"new_GDALWarpAppOptions(char ** options) -> GDALWarpAppOptions"},
+	 { (char *)"delete_GDALWarpAppOptions", _wrap_delete_GDALWarpAppOptions, METH_VARARGS, (char *)"delete_GDALWarpAppOptions(GDALWarpAppOptions self)"},
+	 { (char *)"GDALWarpAppOptions_swigregister", GDALWarpAppOptions_swigregister, METH_VARARGS, NULL},
+	 { (char *)"wrapper_GDALWarpDestDS", _wrap_wrapper_GDALWarpDestDS, METH_VARARGS, (char *)"\n"
+		"wrapper_GDALWarpDestDS(Dataset dstDS, int object_list_count, GDALWarpAppOptions warpAppOptions, GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None) -> int\n"
+		""},
+	 { (char *)"wrapper_GDALWarpDestName", _wrap_wrapper_GDALWarpDestName, METH_VARARGS, (char *)"\n"
+		"wrapper_GDALWarpDestName(char const * dest, int object_list_count, GDALWarpAppOptions warpAppOptions, GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None) -> Dataset\n"
+		""},
+	 { (char *)"new_GDALVectorTranslateOptions", _wrap_new_GDALVectorTranslateOptions, METH_VARARGS, (char *)"new_GDALVectorTranslateOptions(char ** options) -> GDALVectorTranslateOptions"},
+	 { (char *)"delete_GDALVectorTranslateOptions", _wrap_delete_GDALVectorTranslateOptions, METH_VARARGS, (char *)"delete_GDALVectorTranslateOptions(GDALVectorTranslateOptions self)"},
+	 { (char *)"GDALVectorTranslateOptions_swigregister", GDALVectorTranslateOptions_swigregister, METH_VARARGS, NULL},
+	 { (char *)"wrapper_GDALVectorTranslateDestDS", _wrap_wrapper_GDALVectorTranslateDestDS, METH_VARARGS, (char *)"\n"
+		"wrapper_GDALVectorTranslateDestDS(Dataset dstDS, Dataset srcDS, GDALVectorTranslateOptions options, GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None) -> int\n"
+		""},
+	 { (char *)"wrapper_GDALVectorTranslateDestName", _wrap_wrapper_GDALVectorTranslateDestName, METH_VARARGS, (char *)"\n"
+		"wrapper_GDALVectorTranslateDestName(char const * dest, Dataset srcDS, GDALVectorTranslateOptions options, GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None) -> Dataset\n"
+		""},
+	 { (char *)"new_GDALDEMProcessingOptions", _wrap_new_GDALDEMProcessingOptions, METH_VARARGS, (char *)"new_GDALDEMProcessingOptions(char ** options) -> GDALDEMProcessingOptions"},
+	 { (char *)"delete_GDALDEMProcessingOptions", _wrap_delete_GDALDEMProcessingOptions, METH_VARARGS, (char *)"delete_GDALDEMProcessingOptions(GDALDEMProcessingOptions self)"},
+	 { (char *)"GDALDEMProcessingOptions_swigregister", GDALDEMProcessingOptions_swigregister, METH_VARARGS, NULL},
+	 { (char *)"DEMProcessingInternal", _wrap_DEMProcessingInternal, METH_VARARGS, (char *)"\n"
+		"DEMProcessingInternal(char const * dest, Dataset dataset, char const * pszProcessing, char const * pszColorFilename, \n"
+		"    GDALDEMProcessingOptions options, GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None) -> Dataset\n"
+		""},
+	 { (char *)"new_GDALNearblackOptions", _wrap_new_GDALNearblackOptions, METH_VARARGS, (char *)"new_GDALNearblackOptions(char ** options) -> GDALNearblackOptions"},
+	 { (char *)"delete_GDALNearblackOptions", _wrap_delete_GDALNearblackOptions, METH_VARARGS, (char *)"delete_GDALNearblackOptions(GDALNearblackOptions self)"},
+	 { (char *)"GDALNearblackOptions_swigregister", GDALNearblackOptions_swigregister, METH_VARARGS, NULL},
+	 { (char *)"wrapper_GDALNearblackDestDS", _wrap_wrapper_GDALNearblackDestDS, METH_VARARGS, (char *)"\n"
+		"wrapper_GDALNearblackDestDS(Dataset dstDS, Dataset srcDS, GDALNearblackOptions options, GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None) -> int\n"
+		""},
+	 { (char *)"wrapper_GDALNearblackDestName", _wrap_wrapper_GDALNearblackDestName, METH_VARARGS, (char *)"\n"
+		"wrapper_GDALNearblackDestName(char const * dest, Dataset srcDS, GDALNearblackOptions options, GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None) -> Dataset\n"
+		""},
+	 { (char *)"new_GDALGridOptions", _wrap_new_GDALGridOptions, METH_VARARGS, (char *)"new_GDALGridOptions(char ** options) -> GDALGridOptions"},
+	 { (char *)"delete_GDALGridOptions", _wrap_delete_GDALGridOptions, METH_VARARGS, (char *)"delete_GDALGridOptions(GDALGridOptions self)"},
+	 { (char *)"GDALGridOptions_swigregister", GDALGridOptions_swigregister, METH_VARARGS, NULL},
+	 { (char *)"GridInternal", _wrap_GridInternal, METH_VARARGS, (char *)"\n"
+		"GridInternal(char const * dest, Dataset dataset, GDALGridOptions options, GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None) -> Dataset\n"
+		""},
+	 { (char *)"new_GDALRasterizeOptions", _wrap_new_GDALRasterizeOptions, METH_VARARGS, (char *)"new_GDALRasterizeOptions(char ** options) -> GDALRasterizeOptions"},
+	 { (char *)"delete_GDALRasterizeOptions", _wrap_delete_GDALRasterizeOptions, METH_VARARGS, (char *)"delete_GDALRasterizeOptions(GDALRasterizeOptions self)"},
+	 { (char *)"GDALRasterizeOptions_swigregister", GDALRasterizeOptions_swigregister, METH_VARARGS, NULL},
+	 { (char *)"wrapper_GDALRasterizeDestDS", _wrap_wrapper_GDALRasterizeDestDS, METH_VARARGS, (char *)"\n"
+		"wrapper_GDALRasterizeDestDS(Dataset dstDS, Dataset srcDS, GDALRasterizeOptions options, GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None) -> int\n"
+		""},
+	 { (char *)"wrapper_GDALRasterizeDestName", _wrap_wrapper_GDALRasterizeDestName, METH_VARARGS, (char *)"\n"
+		"wrapper_GDALRasterizeDestName(char const * dest, Dataset srcDS, GDALRasterizeOptions options, GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None) -> Dataset\n"
+		""},
+	 { (char *)"new_GDALBuildVRTOptions", _wrap_new_GDALBuildVRTOptions, METH_VARARGS, (char *)"new_GDALBuildVRTOptions(char ** options) -> GDALBuildVRTOptions"},
+	 { (char *)"delete_GDALBuildVRTOptions", _wrap_delete_GDALBuildVRTOptions, METH_VARARGS, (char *)"delete_GDALBuildVRTOptions(GDALBuildVRTOptions self)"},
+	 { (char *)"GDALBuildVRTOptions_swigregister", GDALBuildVRTOptions_swigregister, METH_VARARGS, NULL},
+	 { (char *)"BuildVRTInternalObjects", _wrap_BuildVRTInternalObjects, METH_VARARGS, (char *)"\n"
+		"BuildVRTInternalObjects(char const * dest, int object_list_count, GDALBuildVRTOptions options, GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None) -> Dataset\n"
+		""},
+	 { (char *)"BuildVRTInternalNames", _wrap_BuildVRTInternalNames, METH_VARARGS, (char *)"\n"
+		"BuildVRTInternalNames(char const * dest, char ** source_filenames, GDALBuildVRTOptions options, GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None) -> Dataset\n"
 		""},
-	 { (char *)"OpenShared", _wrap_OpenShared, METH_VARARGS, (char *)"OpenShared(char utf8_path, GDALAccess eAccess = GA_ReadOnly) -> Dataset"},
-	 { (char *)"IdentifyDriver", _wrap_IdentifyDriver, METH_VARARGS, (char *)"IdentifyDriver(char utf8_path, char papszSiblings = None) -> Driver"},
-	 { (char *)"GeneralCmdLineProcessor", _wrap_GeneralCmdLineProcessor, METH_VARARGS, (char *)"GeneralCmdLineProcessor(char papszArgv, int nOptions = 0) -> char"},
 	 { NULL, NULL, 0, NULL }
 };
 
@@ -24627,15 +29683,24 @@ static swig_type_info _swigt__p_CPLVirtualMemShadow = {"_p_CPLVirtualMemShadow",
 static swig_type_info _swigt__p_CPLXMLNode = {"_p_CPLXMLNode", "CPLXMLNode *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_GByte = {"_p_GByte", "GByte *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_GDALAsyncReaderShadow = {"_p_GDALAsyncReaderShadow", "GDALAsyncReaderShadow *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_GDALBuildVRTOptions = {"_p_GDALBuildVRTOptions", "GDALBuildVRTOptions *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_GDALColorEntry = {"_p_GDALColorEntry", "GDALColorEntry *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_GDALColorTableShadow = {"_p_GDALColorTableShadow", "GDALColorTableShadow *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_GDALDEMProcessingOptions = {"_p_GDALDEMProcessingOptions", "GDALDEMProcessingOptions *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_GDALDatasetShadow = {"_p_GDALDatasetShadow", "GDALDatasetShadow *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_GDALDriverShadow = {"_p_GDALDriverShadow", "GDALDriverShadow *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_GDALGridOptions = {"_p_GDALGridOptions", "GDALGridOptions *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_GDALInfoOptions = {"_p_GDALInfoOptions", "GDALInfoOptions *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_GDALMajorObjectShadow = {"_p_GDALMajorObjectShadow", "GDALMajorObjectShadow *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_GDALNearblackOptions = {"_p_GDALNearblackOptions", "GDALNearblackOptions *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_GDALProgressFunc = {"_p_GDALProgressFunc", "GDALProgressFunc *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_GDALRasterAttributeTableShadow = {"_p_GDALRasterAttributeTableShadow", "GDALRasterAttributeTableShadow *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_GDALRasterBandShadow = {"_p_GDALRasterBandShadow", "GDALRasterBandShadow *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_GDALRasterizeOptions = {"_p_GDALRasterizeOptions", "GDALRasterizeOptions *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_GDALTransformerInfoShadow = {"_p_GDALTransformerInfoShadow", "GDALTransformerInfoShadow *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_GDALTranslateOptions = {"_p_GDALTranslateOptions", "GDALTranslateOptions *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_GDALVectorTranslateOptions = {"_p_GDALVectorTranslateOptions", "GDALVectorTranslateOptions *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_GDALWarpAppOptions = {"_p_GDALWarpAppOptions", "GDALWarpAppOptions *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_GDAL_GCP = {"_p_GDAL_GCP", "GDAL_GCP *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_GIntBig = {"_p_GIntBig", "GIntBig *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_GUIntBig = {"_p_GUIntBig", "GUIntBig *", 0, 0, (void*)0, 0};
@@ -24647,7 +29712,8 @@ static swig_type_info _swigt__p_StatBuf = {"_p_StatBuf", "StatBuf *", 0, 0, (voi
 static swig_type_info _swigt__p_char = {"_p_char", "char *|retStringAndCPLFree *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_double = {"_p_double", "double *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_f_double_p_q_const__char_p_void__int = {"_p_f_double_p_q_const__char_p_void__int", "int (*)(double,char const *,void *)", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_int = {"_p_int", "OGRFieldSubType *|GDALRATFieldType *|OGRFieldType *|int *|GDALAccess *|OGRwkbByteOrder *|CPLErr *|GDALRWFlag *|OGRJustification *|GDALRATFieldUsage *|GDALTileOrganization *|GDALPaletteInterp *|GDALColorInterp *|GDALResampleAlg *|GDALRIOResampleAlg *|OGRErr *|OGRwkbGeometryType *|GDALDataType *|GDALAsyncStatusType *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_int = {"_p_int", "OGRFieldSubType *|GDALRATFieldType *|OGRFieldType *|RETURN_NONE *|int *|GDALAccess *|OGRwkbByteOrder *|CPLErr *|GDALRWFlag *|OGRJustification *|GDALRATFieldUsage *|GDALTileOrganization *|GDALPaletteInterp *|GDALColorInterp *|GDALResampleAlg *|GDALRIOResampleAlg *|OGRErr *|OGRwkbGeometryType *|GDALDataType *|GDALAsyncStatusType *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_p_GDALDatasetShadow = {"_p_p_GDALDatasetShadow", "GDALDatasetShadow **", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_p_GDALRasterBandShadow = {"_p_p_GDALRasterBandShadow", "GDALRasterBandShadow **", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_p_GDAL_GCP = {"_p_p_GDAL_GCP", "GDAL_GCP **", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_p_GUIntBig = {"_p_p_GUIntBig", "GUIntBig **", 0, 0, (void*)0, 0};
@@ -24662,15 +29728,24 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_CPLXMLNode,
   &_swigt__p_GByte,
   &_swigt__p_GDALAsyncReaderShadow,
+  &_swigt__p_GDALBuildVRTOptions,
   &_swigt__p_GDALColorEntry,
   &_swigt__p_GDALColorTableShadow,
+  &_swigt__p_GDALDEMProcessingOptions,
   &_swigt__p_GDALDatasetShadow,
   &_swigt__p_GDALDriverShadow,
+  &_swigt__p_GDALGridOptions,
+  &_swigt__p_GDALInfoOptions,
   &_swigt__p_GDALMajorObjectShadow,
+  &_swigt__p_GDALNearblackOptions,
   &_swigt__p_GDALProgressFunc,
   &_swigt__p_GDALRasterAttributeTableShadow,
   &_swigt__p_GDALRasterBandShadow,
+  &_swigt__p_GDALRasterizeOptions,
   &_swigt__p_GDALTransformerInfoShadow,
+  &_swigt__p_GDALTranslateOptions,
+  &_swigt__p_GDALVectorTranslateOptions,
+  &_swigt__p_GDALWarpAppOptions,
   &_swigt__p_GDAL_GCP,
   &_swigt__p_GIntBig,
   &_swigt__p_GUIntBig,
@@ -24683,6 +29758,7 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_double,
   &_swigt__p_f_double_p_q_const__char_p_void__int,
   &_swigt__p_int,
+  &_swigt__p_p_GDALDatasetShadow,
   &_swigt__p_p_GDALRasterBandShadow,
   &_swigt__p_p_GDAL_GCP,
   &_swigt__p_p_GUIntBig,
@@ -24697,15 +29773,24 @@ static swig_cast_info _swigc__p_CPLVirtualMemShadow[] = {  {&_swigt__p_CPLVirtua
 static swig_cast_info _swigc__p_CPLXMLNode[] = {  {&_swigt__p_CPLXMLNode, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GByte[] = {  {&_swigt__p_GByte, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GDALAsyncReaderShadow[] = {  {&_swigt__p_GDALAsyncReaderShadow, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_GDALBuildVRTOptions[] = {  {&_swigt__p_GDALBuildVRTOptions, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GDALColorEntry[] = {  {&_swigt__p_GDALColorEntry, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GDALColorTableShadow[] = {  {&_swigt__p_GDALColorTableShadow, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_GDALDEMProcessingOptions[] = {  {&_swigt__p_GDALDEMProcessingOptions, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GDALDatasetShadow[] = {  {&_swigt__p_GDALDatasetShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GDALDriverShadow[] = {  {&_swigt__p_GDALDriverShadow, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_GDALGridOptions[] = {  {&_swigt__p_GDALGridOptions, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_GDALInfoOptions[] = {  {&_swigt__p_GDALInfoOptions, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GDALMajorObjectShadow[] = {  {&_swigt__p_GDALMajorObjectShadow, 0, 0, 0},  {&_swigt__p_GDALDriverShadow, _p_GDALDriverShadowTo_p_GDALMajorObjectShadow, 0, 0},  {&_swigt__p_OGRLayerShadow, _p_OGRLayerShadowTo_p_GDALMajorObjectShadow, 0, 0},  {&_swigt__p_GDALDatasetShadow, _p_GDALDatasetShadowTo_p_GDALMajorObjectShadow, 0, 0},  {&_swigt__p_GDALRasterBandShadow, _p_GDALRasterBandShadowTo_p_GDALMajorObjectShadow, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_GDALNearblackOptions[] = {  {&_swigt__p_GDALNearblackOptions, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GDALProgressFunc[] = {  {&_swigt__p_GDALProgressFunc, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GDALRasterAttributeTableShadow[] = {  {&_swigt__p_GDALRasterAttributeTableShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GDALRasterBandShadow[] = {  {&_swigt__p_GDALRasterBandShadow, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_GDALRasterizeOptions[] = {  {&_swigt__p_GDALRasterizeOptions, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GDALTransformerInfoShadow[] = {  {&_swigt__p_GDALTransformerInfoShadow, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_GDALTranslateOptions[] = {  {&_swigt__p_GDALTranslateOptions, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_GDALVectorTranslateOptions[] = {  {&_swigt__p_GDALVectorTranslateOptions, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_GDALWarpAppOptions[] = {  {&_swigt__p_GDALWarpAppOptions, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GDAL_GCP[] = {  {&_swigt__p_GDAL_GCP, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GIntBig[] = {  {&_swigt__p_GIntBig, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GUIntBig[] = {  {&_swigt__p_GUIntBig, 0, 0, 0},{0, 0, 0, 0}};
@@ -24718,6 +29803,7 @@ static swig_cast_info _swigc__p_char[] = {  {&_swigt__p_char, 0, 0, 0},{0, 0, 0,
 static swig_cast_info _swigc__p_double[] = {  {&_swigt__p_double, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_f_double_p_q_const__char_p_void__int[] = {  {&_swigt__p_f_double_p_q_const__char_p_void__int, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_int[] = {  {&_swigt__p_int, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_p_GDALDatasetShadow[] = {  {&_swigt__p_p_GDALDatasetShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_p_GDALRasterBandShadow[] = {  {&_swigt__p_p_GDALRasterBandShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_p_GDAL_GCP[] = {  {&_swigt__p_p_GDAL_GCP, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_p_GUIntBig[] = {  {&_swigt__p_p_GUIntBig, 0, 0, 0},{0, 0, 0, 0}};
@@ -24732,15 +29818,24 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_CPLXMLNode,
   _swigc__p_GByte,
   _swigc__p_GDALAsyncReaderShadow,
+  _swigc__p_GDALBuildVRTOptions,
   _swigc__p_GDALColorEntry,
   _swigc__p_GDALColorTableShadow,
+  _swigc__p_GDALDEMProcessingOptions,
   _swigc__p_GDALDatasetShadow,
   _swigc__p_GDALDriverShadow,
+  _swigc__p_GDALGridOptions,
+  _swigc__p_GDALInfoOptions,
   _swigc__p_GDALMajorObjectShadow,
+  _swigc__p_GDALNearblackOptions,
   _swigc__p_GDALProgressFunc,
   _swigc__p_GDALRasterAttributeTableShadow,
   _swigc__p_GDALRasterBandShadow,
+  _swigc__p_GDALRasterizeOptions,
   _swigc__p_GDALTransformerInfoShadow,
+  _swigc__p_GDALTranslateOptions,
+  _swigc__p_GDALVectorTranslateOptions,
+  _swigc__p_GDALWarpAppOptions,
   _swigc__p_GDAL_GCP,
   _swigc__p_GIntBig,
   _swigc__p_GUIntBig,
@@ -24753,6 +29848,7 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_double,
   _swigc__p_f_double_p_q_const__char_p_void__int,
   _swigc__p_int,
+  _swigc__p_p_GDALDatasetShadow,
   _swigc__p_p_GDALRasterBandShadow,
   _swigc__p_p_GDAL_GCP,
   _swigc__p_p_GUIntBig,
@@ -24774,18 +29870,18 @@ static swig_const_info swig_const_table[] = {
 #endif
 /* -----------------------------------------------------------------------------
  * Type initialization:
- * This problem is tough by the requirement that no dynamic 
- * memory is used. Also, since swig_type_info structures store pointers to 
+ * This problem is tough by the requirement that no dynamic
+ * memory is used. Also, since swig_type_info structures store pointers to
  * swig_cast_info structures and swig_cast_info structures store pointers back
- * to swig_type_info structures, we need some lookup code at initialization. 
- * The idea is that swig generates all the structures that are needed. 
- * The runtime then collects these partially filled structures. 
- * The SWIG_InitializeModule function takes these initial arrays out of 
+ * to swig_type_info structures, we need some lookup code at initialization.
+ * The idea is that swig generates all the structures that are needed.
+ * The runtime then collects these partially filled structures.
+ * The SWIG_InitializeModule function takes these initial arrays out of
  * swig_module, and does all the lookup, filling in the swig_module.types
  * array with the correct data and linking the correct swig_cast_info
  * structures together.
  *
- * The generated swig_type_info structures are assigned staticly to an initial 
+ * The generated swig_type_info structures are assigned staticly to an initial
  * array. We just loop through that array, and handle each type individually.
  * First we lookup if this type has been already loaded, and if so, use the
  * loaded structure instead of the generated one. Then we have to fill in the
@@ -24795,17 +29891,17 @@ static swig_const_info swig_const_table[] = {
  * a column is one of the swig_cast_info structures for that type.
  * The cast_initial array is actually an array of arrays, because each row has
  * a variable number of columns. So to actually build the cast linked list,
- * we find the array of casts associated with the type, and loop through it 
+ * we find the array of casts associated with the type, and loop through it
  * adding the casts to the list. The one last trick we need to do is making
  * sure the type pointer in the swig_cast_info struct is correct.
  *
- * First off, we lookup the cast->type name to see if it is already loaded. 
+ * First off, we lookup the cast->type name to see if it is already loaded.
  * There are three cases to handle:
  *  1) If the cast->type has already been loaded AND the type we are adding
  *     casting info to has not been loaded (it is in this module), THEN we
  *     replace the cast->type pointer with the type pointer that has already
  *     been loaded.
- *  2) If BOTH types (the one we are adding casting info to, and the 
+ *  2) If BOTH types (the one we are adding casting info to, and the
  *     cast->type) are loaded, THEN the cast info has already been loaded by
  *     the previous module so we just ignore it.
  *  3) Finally, if cast->type has not already been loaded, then we add that
@@ -24831,8 +29927,6 @@ SWIG_InitializeModule(void *clientdata) {
   swig_module_info *module_head, *iter;
   int found, init;
   
-  clientdata = clientdata;
-  
   /* check to see if the circular list has been setup, if not, set it up */
   if (swig_module.next==0) {
     /* Initialize the swig_module */
@@ -24850,7 +29944,7 @@ SWIG_InitializeModule(void *clientdata) {
     /* This is the first module loaded for this interpreter */
     /* so set the swig module into the interpreter */
     SWIG_SetModule(clientdata, &swig_module);
-    module_head = &swig_module;
+    /*module_head = &swig_module;*/
   } else {
     /* the interpreter has loaded a SWIG module, but has it loaded this one? */
     found=0;
@@ -24870,7 +29964,7 @@ SWIG_InitializeModule(void *clientdata) {
     module_head->next = &swig_module;
   }
   
-  /* When multiple interpeters are used, a module could have already been initialized in
+  /* When multiple interpreters are used, a module could have already been initialized in
        a different interpreter, but not yet have a pointer in this interpreter.
        In this case, we do not want to continue adding types... everything should be
        set up already */
@@ -25143,24 +30237,23 @@ extern "C" {
   swig_varlink_type(void) {
     static char varlink__doc__[] = "Swig var link object";
     static PyTypeObject varlink_type;
-    static int type_init = 0;  
+    static int type_init = 0;
     if (!type_init) {
-      const PyTypeObject tmp
-      = {
+      const PyTypeObject tmp = {
         /* PyObject header changed in Python 3 */
 #if PY_VERSION_HEX >= 0x03000000
-        PyVarObject_HEAD_INIT(&PyType_Type, 0)
+        PyVarObject_HEAD_INIT(NULL, 0)
 #else
         PyObject_HEAD_INIT(NULL)
-        0,                                  /* Number of items in variable part (ob_size) */
-#endif
-        (char *)"swigvarlink",              /* Type name (tp_name) */
-        sizeof(swig_varlinkobject),         /* Basic size (tp_basicsize) */
-        0,                                  /* Itemsize (tp_itemsize) */
-        (destructor) swig_varlink_dealloc,  /* Deallocator (tp_dealloc) */ 
-        (printfunc) swig_varlink_print,     /* Print (tp_print) */
-        (getattrfunc) swig_varlink_getattr, /* get attr (tp_getattr) */
-        (setattrfunc) swig_varlink_setattr, /* Set attr (tp_setattr) */
+        0,                                  /* ob_size */
+#endif
+        (char *)"swigvarlink",              /* tp_name */
+        sizeof(swig_varlinkobject),         /* tp_basicsize */
+        0,                                  /* tp_itemsize */
+        (destructor) swig_varlink_dealloc,  /* tp_dealloc */
+        (printfunc) swig_varlink_print,     /* tp_print */
+        (getattrfunc) swig_varlink_getattr, /* tp_getattr */
+        (setattrfunc) swig_varlink_setattr, /* tp_setattr */
         0,                                  /* tp_compare */
         (reprfunc) swig_varlink_repr,       /* tp_repr */
         0,                                  /* tp_as_number */
@@ -25184,16 +30277,21 @@ extern "C" {
 #if PY_VERSION_HEX >= 0x02030000
         0,                                  /* tp_del */
 #endif
+#if PY_VERSION_HEX >= 0x02060000
+        0,                                  /* tp_version */
+#endif
 #ifdef COUNT_ALLOCS
         0,0,0,0                             /* tp_alloc -> tp_next */
 #endif
       };
       varlink_type = tmp;
-      /* for Python 3 we already assigned ob_type in PyVarObject_HEAD_INIT() */
-#if PY_VERSION_HEX < 0x03000000
+      type_init = 1;
+#if PY_VERSION_HEX < 0x02020000
       varlink_type.ob_type = &PyType_Type;
+#else
+      if (PyType_Ready(&varlink_type) < 0)
+      return NULL;
 #endif
-      type_init = 1;
     }
     return &varlink_type;
   }
@@ -25244,7 +30342,7 @@ extern "C" {
     for (i = 0; constants[i].type; ++i) {
       switch(constants[i].type) {
       case SWIG_PY_POINTER:
-        obj = SWIG_NewPointerObj(constants[i].pvalue, *(constants[i]).ptype,0);
+        obj = SWIG_InternalNewPointerObj(constants[i].pvalue, *(constants[i]).ptype,0);
         break;
       case SWIG_PY_BINARY:
         obj = SWIG_NewPackedObj(constants[i].pvalue, constants[i].lvalue, *(constants[i].ptype));
@@ -25284,18 +30382,18 @@ extern "C" {
           }
         }
         if (ci) {
-          size_t shift = (ci->ptype) - types;
-          swig_type_info *ty = types_initial[shift];
-          size_t ldoc = (c - methods[i].ml_doc);
-          size_t lptr = strlen(ty->name)+2*sizeof(void*)+2;
-          char *ndoc = (char*)malloc(ldoc + lptr + 10);
-          if (ndoc) {
-            char *buff = ndoc;
-            void *ptr = (ci->type == SWIG_PY_POINTER) ? ci->pvalue : 0;
-            if (ptr) {
+          void *ptr = (ci->type == SWIG_PY_POINTER) ? ci->pvalue : 0;
+          if (ptr) {
+            size_t shift = (ci->ptype) - types;
+            swig_type_info *ty = types_initial[shift];
+            size_t ldoc = (c - methods[i].ml_doc);
+            size_t lptr = strlen(ty->name)+2*sizeof(void*)+2;
+            char *ndoc = (char*)malloc(ldoc + lptr + 10);
+            if (ndoc) {
+              char *buff = ndoc;
               strncpy(buff, methods[i].ml_doc, ldoc);
               buff += ldoc;
-              strncpy(buff, "swig_ptr: ", 10);
+              memcpy(buff, "swig_ptr: ", 10);
               buff += 10;
               SWIG_PackVoidPtr(buff, ptr, ty->name, lptr);
               methods[i].ml_doc = ndoc;
@@ -25325,10 +30423,19 @@ PyObject*
 void
 #endif
 SWIG_init(void) {
-  PyObject *m, *d;  
+  PyObject *m, *d, *md;
 #if PY_VERSION_HEX >= 0x03000000
   static struct PyModuleDef SWIG_module = {
+# if PY_VERSION_HEX >= 0x03020000
     PyModuleDef_HEAD_INIT,
+# else
+    {
+      PyObject_HEAD_INIT(NULL)
+      NULL, /* m_init */
+      0,    /* m_index */
+      NULL, /* m_copy */
+    },
+# endif
     (char *) SWIG_name,
     NULL,
     -1,
@@ -25340,6 +30447,49 @@ SWIG_init(void) {
   };
 #endif
   
+#if defined(SWIGPYTHON_BUILTIN)
+  static SwigPyClientData SwigPyObject_clientdata = {
+    0, 0, 0, 0, 0, 0, 0
+  };
+  static PyGetSetDef this_getset_def = {
+    (char *)"this", &SwigPyBuiltin_ThisClosure, NULL, NULL, NULL
+  };
+  static SwigPyGetSet thisown_getset_closure = {
+    (PyCFunction) SwigPyObject_own,
+    (PyCFunction) SwigPyObject_own
+  };
+  static PyGetSetDef thisown_getset_def = {
+    (char *)"thisown", SwigPyBuiltin_GetterClosure, SwigPyBuiltin_SetterClosure, NULL, &thisown_getset_closure
+  };
+  PyObject *metatype_args;
+  PyTypeObject *builtin_pytype;
+  int builtin_base_count;
+  swig_type_info *builtin_basetype;
+  PyObject *tuple;
+  PyGetSetDescrObject *static_getset;
+  PyTypeObject *metatype;
+  SwigPyClientData *cd;
+  PyObject *public_interface, *public_symbol;
+  PyObject *this_descr;
+  PyObject *thisown_descr;
+  int i;
+  
+  (void)builtin_pytype;
+  (void)builtin_base_count;
+  (void)builtin_basetype;
+  (void)tuple;
+  (void)static_getset;
+  
+  /* metatype is used to implement static member variables. */
+  metatype_args = Py_BuildValue("(s(O){})", "SwigPyObjectType", &PyType_Type);
+  assert(metatype_args);
+  metatype = (PyTypeObject *) PyType_Type.tp_call((PyObject *) &PyType_Type, metatype_args, NULL);
+  assert(metatype);
+  Py_DECREF(metatype_args);
+  metatype->tp_setattro = (setattrofunc) &SwigPyObjectType_setattro;
+  assert(PyType_Ready(metatype) >= 0);
+#endif
+  
   /* Fix SwigMethods to carry the callback ptrs when needed */
   SWIG_Python_FixMethods(SwigMethods, swig_const_table, swig_types, swig_type_initial);
   
@@ -25348,11 +30498,48 @@ SWIG_init(void) {
 #else
   m = Py_InitModule((char *) SWIG_name, SwigMethods);
 #endif
-  d = PyModule_GetDict(m);
+  md = d = PyModule_GetDict(m);
+  (void)md;
   
   SWIG_InitializeModule(0);
-  SWIG_InstallConstants(d,swig_const_table);
   
+#ifdef SWIGPYTHON_BUILTIN
+  SwigPyObject_stype = SWIG_MangledTypeQuery("_p_SwigPyObject");
+  assert(SwigPyObject_stype);
+  cd = (SwigPyClientData*) SwigPyObject_stype->clientdata;
+  if (!cd) {
+    SwigPyObject_stype->clientdata = &SwigPyObject_clientdata;
+    SwigPyObject_clientdata.pytype = SwigPyObject_TypeOnce();
+  } else if (SwigPyObject_TypeOnce()->tp_basicsize != cd->pytype->tp_basicsize) {
+    PyErr_SetString(PyExc_RuntimeError, "Import error: attempted to load two incompatible swig-generated modules.");
+# if PY_VERSION_HEX >= 0x03000000
+    return NULL;
+# else
+    return;
+# endif
+  }
+  
+  /* All objects have a 'this' attribute */
+  this_descr = PyDescr_NewGetSet(SwigPyObject_type(), &this_getset_def);
+  (void)this_descr;
+  
+  /* All objects have a 'thisown' attribute */
+  thisown_descr = PyDescr_NewGetSet(SwigPyObject_type(), &thisown_getset_def);
+  (void)thisown_descr;
+  
+  public_interface = PyList_New(0);
+  public_symbol = 0;
+  (void)public_symbol;
+  
+  PyDict_SetItemString(md, "__all__", public_interface);
+  Py_DECREF(public_interface);
+  for (i = 0; SwigMethods[i].ml_name != NULL; ++i)
+  SwigPyBuiltin_AddPublicSymbol(public_interface, SwigMethods[i].ml_name);
+  for (i = 0; swig_const_table[i].name != 0; ++i)
+  SwigPyBuiltin_AddPublicSymbol(public_interface, swig_const_table[i].name);
+#endif
+  
+  SWIG_InstallConstants(d,swig_const_table);
   
   
   /* gdal_python.i %init code */
diff --git a/swig/python/extensions/gdalconst_wrap.c b/swig/python/extensions/gdalconst_wrap.c
index 02bd730..ddb69a5 100644
--- a/swig/python/extensions/gdalconst_wrap.c
+++ b/swig/python/extensions/gdalconst_wrap.c
@@ -1,14 +1,15 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.40
- * 
- * This file is not intended to be easily readable and contains a number of 
+ * Version 2.0.12
+ *
+ * This file is not intended to be easily readable and contains a number of
  * coding conventions designed to improve portability and efficiency. Do not make
- * changes to this file unless you know what you are doing--modify the SWIG 
- * interface file instead. 
+ * changes to this file unless you know what you are doing--modify the SWIG
+ * interface file instead.
  * ----------------------------------------------------------------------------- */
 
 #define SWIGPYTHON
+#define SED_HACKS
 #define SWIG_PYTHON_DIRECTOR_NO_VTABLE
 
 /* -----------------------------------------------------------------------------
@@ -42,28 +43,28 @@
 #ifndef SWIGUNUSED
 # if defined(__GNUC__)
 #   if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
-#     define SWIGUNUSED __attribute__ ((__unused__)) 
+#     define SWIGUNUSED __attribute__ ((__unused__))
 #   else
 #     define SWIGUNUSED
 #   endif
 # elif defined(__ICC)
-#   define SWIGUNUSED __attribute__ ((__unused__)) 
+#   define SWIGUNUSED __attribute__ ((__unused__))
 # else
-#   define SWIGUNUSED 
+#   define SWIGUNUSED
 # endif
 #endif
 
 #ifndef SWIG_MSC_UNSUPPRESS_4505
 # if defined(_MSC_VER)
 #   pragma warning(disable : 4505) /* unreferenced local function has been removed */
-# endif 
+# endif
 #endif
 
 #ifndef SWIGUNUSEDPARM
 # ifdef __cplusplus
 #   define SWIGUNUSEDPARM(p)
 # else
-#   define SWIGUNUSEDPARM(p) p SWIGUNUSED 
+#   define SWIGUNUSEDPARM(p) p SWIGUNUSED
 # endif
 #endif
 
@@ -106,7 +107,7 @@
 #   define SWIGSTDCALL __stdcall
 # else
 #   define SWIGSTDCALL
-# endif 
+# endif
 #endif
 
 /* Deal with Microsoft's attempt at deprecating C standard runtime functions */
@@ -121,8 +122,14 @@
 
 
 
-/* Python.h has to appear first */
-#include <Python.h>
+#if defined(_DEBUG) && defined(SWIG_PYTHON_INTERPRETER_NO_DEBUG)
+/* Use debug wrappers with the Python release dll */
+# undef _DEBUG
+# include <Python.h>
+# define _DEBUG
+#else
+# include <Python.h>
+#endif
 
 /* -----------------------------------------------------------------------------
  * swigrun.swg
@@ -148,7 +155,7 @@
   You can use the SWIGRUNTIME and SWIGRUNTIMEINLINE macros for
   creating a static or dynamic library from the SWIG runtime code.
   In 99.9% of the cases, SWIG just needs to declare them as 'static'.
-  
+
   But only do this if strictly necessary, ie, if you have problems
   with your compiler or suchlike.
 */
@@ -174,16 +181,16 @@
 #define SWIG_POINTER_OWN           0x1
 
 
-/* 
+/*
    Flags/methods for returning states.
-   
-   The SWIG conversion methods, as ConvertPtr, return and integer 
+
+   The SWIG conversion methods, as ConvertPtr, return an integer
    that tells if the conversion was successful or not. And if not,
    an error code can be returned (see swigerrors.swg for the codes).
-   
+
    Use the following macros/flags to set or process the returning
    states.
-   
+
    In old versions of SWIG, code such as the following was usually written:
 
      if (SWIG_ConvertPtr(obj,vptr,ty.flags) != -1) {
@@ -216,23 +223,23 @@
     } else {
       // fail code
     }
-    
+
    I.e., now SWIG_ConvertPtr can return new objects and you can
    identify the case and take care of the deallocation. Of course that
    also requires SWIG_ConvertPtr to return new result values, such as
 
-      int SWIG_ConvertPtr(obj, ptr,...) {         
-        if (<obj is ok>) {			       
-          if (<need new object>) {		       
-            *ptr = <ptr to new allocated object>; 
-            return SWIG_NEWOBJ;		       
-          } else {				       
-            *ptr = <ptr to old object>;	       
-            return SWIG_OLDOBJ;		       
-          } 				       
-        } else {				       
-          return SWIG_BADOBJ;		       
-        }					       
+      int SWIG_ConvertPtr(obj, ptr,...) {
+        if (<obj is ok>) {
+          if (<need new object>) {
+            *ptr = <ptr to new allocated object>;
+            return SWIG_NEWOBJ;
+          } else {
+            *ptr = <ptr to old object>;
+            return SWIG_OLDOBJ;
+          }
+        } else {
+          return SWIG_BADOBJ;
+        }
       }
 
    Of course, returning the plain '0(success)/-1(fail)' still works, but you can be
@@ -246,17 +253,17 @@
        int fooi(int);
 
    and you call
- 
+
       food(1)   // cast rank '1'  (1 -> 1.0)
       fooi(1)   // cast rank '0'
 
    just use the SWIG_AddCast()/SWIG_CheckState()
 */
 
-#define SWIG_OK                    (0) 
+#define SWIG_OK                    (0)
 #define SWIG_ERROR                 (-1)
 #define SWIG_IsOK(r)               (r >= 0)
-#define SWIG_ArgError(r)           ((r != SWIG_ERROR) ? r : SWIG_TypeError)  
+#define SWIG_ArgError(r)           ((r != SWIG_ERROR) ? r : SWIG_TypeError)
 
 /* The CastRankLimit says how many bits are used for the cast rank */
 #define SWIG_CASTRANKLIMIT         (1 << 8)
@@ -287,14 +294,14 @@
 #  endif
 #  define SWIG_CASTRANKMASK          ((SWIG_CASTRANKLIMIT) -1)
 #  define SWIG_CastRank(r)           (r & SWIG_CASTRANKMASK)
-SWIGINTERNINLINE int SWIG_AddCast(int r) { 
+SWIGINTERNINLINE int SWIG_AddCast(int r) {
   return SWIG_IsOK(r) ? ((SWIG_CastRank(r) < SWIG_MAXCASTRANK) ? (r + 1) : SWIG_ERROR) : r;
 }
-SWIGINTERNINLINE int SWIG_CheckState(int r) { 
-  return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0; 
+SWIGINTERNINLINE int SWIG_CheckState(int r) {
+  return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0;
 }
 #else /* no cast-rank mode */
-#  define SWIG_AddCast
+#  define SWIG_AddCast(r) (r)
 #  define SWIG_CheckState(r) (SWIG_IsOK(r) ? 1 : 0)
 #endif
 
@@ -338,7 +345,7 @@ typedef struct swig_module_info {
   void                    *clientdata;		/* Language specific module data */
 } swig_module_info;
 
-/* 
+/*
   Compare two type names skipping the space characters, therefore
   "char*" == "char *" and "Class<int>" == "Class<int >", etc.
 
@@ -358,18 +365,18 @@ SWIG_TypeNameComp(const char *f1, const char *l1,
 
 /*
   Check type equivalence in a name list like <name1>|<name2>|...
-  Return 0 if not equal, 1 if equal
+  Return 0 if equal, -1 if nb < tb, 1 if nb > tb
 */
 SWIGRUNTIME int
-SWIG_TypeEquiv(const char *nb, const char *tb) {
-  int equiv = 0;
+SWIG_TypeCmp(const char *nb, const char *tb) {
+  int equiv = 1;
   const char* te = tb + strlen(tb);
   const char* ne = nb;
-  while (!equiv && *ne) {
+  while (equiv != 0 && *ne) {
     for (nb = ne; *ne; ++ne) {
       if (*ne == '|') break;
     }
-    equiv = (SWIG_TypeNameComp(nb, ne, tb, te) == 0) ? 1 : 0;
+    equiv = SWIG_TypeNameComp(nb, ne, tb, te);
     if (*ne) ++ne;
   }
   return equiv;
@@ -377,24 +384,13 @@ SWIG_TypeEquiv(const char *nb, const char *tb) {
 
 /*
   Check type equivalence in a name list like <name1>|<name2>|...
-  Return 0 if equal, -1 if nb < tb, 1 if nb > tb
+  Return 0 if not equal, 1 if equal
 */
 SWIGRUNTIME int
-SWIG_TypeCompare(const char *nb, const char *tb) {
-  int equiv = 0;
-  const char* te = tb + strlen(tb);
-  const char* ne = nb;
-  while (!equiv && *ne) {
-    for (nb = ne; *ne; ++ne) {
-      if (*ne == '|') break;
-    }
-    equiv = (SWIG_TypeNameComp(nb, ne, tb, te) == 0) ? 1 : 0;
-    if (*ne) ++ne;
-  }
-  return equiv;
+SWIG_TypeEquiv(const char *nb, const char *tb) {
+  return SWIG_TypeCmp(nb, tb) == 0 ? 1 : 0;
 }
 
-
 /*
   Check the typename
 */
@@ -422,7 +418,7 @@ SWIG_TypeCheck(const char *c, swig_type_info *ty) {
   return 0;
 }
 
-/* 
+/*
   Identical to SWIG_TypeCheck, except strcmp is replaced with a pointer comparison
 */
 SWIGRUNTIME swig_cast_info *
@@ -457,7 +453,7 @@ SWIG_TypeCast(swig_cast_info *ty, void *ptr, int *newmemory) {
   return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr, newmemory);
 }
 
-/* 
+/*
    Dynamic pointer casting. Down an inheritance hierarchy
 */
 SWIGRUNTIME swig_type_info *
@@ -501,7 +497,7 @@ SWIG_TypePrettyName(const swig_type_info *type) {
     return type->name;
 }
 
-/* 
+/*
    Set the clientdata field for a type
 */
 SWIGRUNTIME void
@@ -509,14 +505,14 @@ SWIG_TypeClientData(swig_type_info *ti, void *clientdata) {
   swig_cast_info *cast = ti->cast;
   /* if (ti->clientdata == clientdata) return; */
   ti->clientdata = clientdata;
-  
+
   while (cast) {
     if (!cast->converter) {
       swig_type_info *tc = cast->type;
       if (!tc->clientdata) {
 	SWIG_TypeClientData(tc, clientdata);
       }
-    }    
+    }
     cast = cast->next;
   }
 }
@@ -525,18 +521,18 @@ SWIG_TypeNewClientData(swig_type_info *ti, void *clientdata) {
   SWIG_TypeClientData(ti, clientdata);
   ti->owndata = 1;
 }
-  
+
 /*
   Search for a swig_type_info structure only by mangled name
   Search is a O(log #types)
-  
-  We start searching at module start, and finish searching when start == end.  
+
+  We start searching at module start, and finish searching when start == end.
   Note: if start == end at the beginning of the function, we go all the way around
   the circular list.
 */
 SWIGRUNTIME swig_type_info *
-SWIG_MangledTypeQueryModule(swig_module_info *start, 
-                            swig_module_info *end, 
+SWIG_MangledTypeQueryModule(swig_module_info *start,
+                            swig_module_info *end,
 		            const char *name) {
   swig_module_info *iter = start;
   do {
@@ -545,11 +541,11 @@ SWIG_MangledTypeQueryModule(swig_module_info *start,
       register size_t r = iter->size - 1;
       do {
 	/* since l+r >= 0, we can (>> 1) instead (/ 2) */
-	register size_t i = (l + r) >> 1; 
+	register size_t i = (l + r) >> 1;
 	const char *iname = iter->types[i]->name;
 	if (iname) {
 	  register int compare = strcmp(name, iname);
-	  if (compare == 0) {	    
+	  if (compare == 0) {
 	    return iter->types[i];
 	  } else if (compare < 0) {
 	    if (i) {
@@ -574,14 +570,14 @@ SWIG_MangledTypeQueryModule(swig_module_info *start,
   Search for a swig_type_info structure for either a mangled name or a human readable name.
   It first searches the mangled names of the types, which is a O(log #types)
   If a type is not found it then searches the human readable names, which is O(#types).
-  
-  We start searching at module start, and finish searching when start == end.  
+
+  We start searching at module start, and finish searching when start == end.
   Note: if start == end at the beginning of the function, we go all the way around
   the circular list.
 */
 SWIGRUNTIME swig_type_info *
-SWIG_TypeQueryModule(swig_module_info *start, 
-                     swig_module_info *end, 
+SWIG_TypeQueryModule(swig_module_info *start,
+                     swig_module_info *end,
 		     const char *name) {
   /* STEP 1: Search the name field using binary search */
   swig_type_info *ret = SWIG_MangledTypeQueryModule(start, end, name);
@@ -600,12 +596,12 @@ SWIG_TypeQueryModule(swig_module_info *start,
       iter = iter->next;
     } while (iter != end);
   }
-  
+
   /* neither found a match */
   return 0;
 }
 
-/* 
+/*
    Pack binary data into a string
 */
 SWIGRUNTIME char *
@@ -621,7 +617,7 @@ SWIG_PackData(char *c, void *ptr, size_t sz) {
   return c;
 }
 
-/* 
+/*
    Unpack binary data from a string
 */
 SWIGRUNTIME const char *
@@ -635,21 +631,21 @@ SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
       uu = ((d - '0') << 4);
     else if ((d >= 'a') && (d <= 'f'))
       uu = ((d - ('a'-10)) << 4);
-    else 
+    else
       return (char *) 0;
     d = *(c++);
     if ((d >= '0') && (d <= '9'))
       uu |= (d - '0');
     else if ((d >= 'a') && (d <= 'f'))
       uu |= (d - ('a'-10));
-    else 
+    else
       return (char *) 0;
     *u = uu;
   }
   return c;
 }
 
-/* 
+/*
    Pack 'void *' into a string buffer.
 */
 SWIGRUNTIME char *
@@ -709,18 +705,18 @@ SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) {
 #endif
 
 /*  Errors in SWIG */
-#define  SWIG_UnknownError    	   -1 
-#define  SWIG_IOError        	   -2 
-#define  SWIG_RuntimeError   	   -3 
-#define  SWIG_IndexError     	   -4 
-#define  SWIG_TypeError      	   -5 
-#define  SWIG_DivisionByZero 	   -6 
-#define  SWIG_OverflowError  	   -7 
-#define  SWIG_SyntaxError    	   -8 
-#define  SWIG_ValueError     	   -9 
+#define  SWIG_UnknownError    	   -1
+#define  SWIG_IOError        	   -2
+#define  SWIG_RuntimeError   	   -3
+#define  SWIG_IndexError     	   -4
+#define  SWIG_TypeError      	   -5
+#define  SWIG_DivisionByZero 	   -6
+#define  SWIG_OverflowError  	   -7
+#define  SWIG_SyntaxError    	   -8
+#define  SWIG_ValueError     	   -9
 #define  SWIG_SystemError    	   -10
 #define  SWIG_AttributeError 	   -11
-#define  SWIG_MemoryError    	   -12 
+#define  SWIG_MemoryError    	   -12
 #define  SWIG_NullReferenceError   -13
 
 
@@ -732,7 +728,16 @@ SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) {
 #define PyInt_Check(x) PyLong_Check(x)
 #define PyInt_AsLong(x) PyLong_AsLong(x)
 #define PyInt_FromLong(x) PyLong_FromLong(x)
+#define PyInt_FromSize_t(x) PyLong_FromSize_t(x)
+#define PyString_Check(name) PyBytes_Check(name)
+#define PyString_FromString(x) PyUnicode_FromString(x)
 #define PyString_Format(fmt, args)  PyUnicode_Format(fmt, args)
+#define PyString_AsString(str) PyBytes_AsString(str)
+#define PyString_Size(str) PyBytes_Size(str)	
+#define PyString_InternFromString(key) PyUnicode_InternFromString(key)
+#define Py_TPFLAGS_HAVE_CLASS Py_TPFLAGS_BASETYPE
+#define PyString_AS_STRING(x) PyUnicode_AS_STRING(x)
+#define _PyLong_FromSsize_t(x) PyLong_FromSsize_t(x)
 
 #endif
 
@@ -872,6 +877,67 @@ PyObject *PyBool_FromLong(long ok)
 typedef int Py_ssize_t;
 # define PY_SSIZE_T_MAX INT_MAX
 # define PY_SSIZE_T_MIN INT_MIN
+typedef inquiry lenfunc;
+typedef intargfunc ssizeargfunc;
+typedef intintargfunc ssizessizeargfunc;
+typedef intobjargproc ssizeobjargproc;
+typedef intintobjargproc ssizessizeobjargproc;
+typedef getreadbufferproc readbufferproc;
+typedef getwritebufferproc writebufferproc;
+typedef getsegcountproc segcountproc;
+typedef getcharbufferproc charbufferproc;
+static long PyNumber_AsSsize_t (PyObject *x, void *SWIGUNUSEDPARM(exc))
+{
+  long result = 0;
+  PyObject *i = PyNumber_Int(x);
+  if (i) {
+    result = PyInt_AsLong(i);
+    Py_DECREF(i);
+  }
+  return result;
+}
+#endif
+
+#if PY_VERSION_HEX < 0x02050000
+#define PyInt_FromSize_t(x) PyInt_FromLong((long)x)
+#endif
+
+#if PY_VERSION_HEX < 0x02040000
+#define Py_VISIT(op)				\
+  do { 						\
+    if (op) {					\
+      int vret = visit((op), arg);		\
+      if (vret)					\
+        return vret;				\
+    }						\
+  } while (0)
+#endif
+
+#if PY_VERSION_HEX < 0x02030000
+typedef struct {
+  PyTypeObject type;
+  PyNumberMethods as_number;
+  PyMappingMethods as_mapping;
+  PySequenceMethods as_sequence;
+  PyBufferProcs as_buffer;
+  PyObject *name, *slots;
+} PyHeapTypeObject;
+#endif
+
+#if PY_VERSION_HEX < 0x02030000
+typedef destructor freefunc;
+#endif
+
+#if ((PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 6) || \
+     (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION > 0) || \
+     (PY_MAJOR_VERSION > 3))
+# define SWIGPY_USE_CAPSULE
+# define SWIGPY_CAPSULE_NAME ((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer_capsule" SWIG_TYPE_TABLE_NAME)
+#endif
+
+#if PY_VERSION_HEX < 0x03020000
+#define PyDescr_TYPE(x) (((PyDescrObject *)(x))->d_type)
+#define PyDescr_NAME(x) (((PyDescrObject *)(x))->d_name)
 #endif
 
 /* -----------------------------------------------------------------------------
@@ -1018,9 +1084,6 @@ SWIG_Python_AddErrorMsg(const char* mesg)
 
 #ifdef __cplusplus
 extern "C" {
-#if 0
-} /* cc-mode */
-#endif
 #endif
 
 /* -----------------------------------------------------------------------------
@@ -1046,27 +1109,24 @@ typedef struct swig_const_info {
  * Wrapper of PyInstanceMethod_New() used in Python 3
  * It is exported to the generated module, used for -fastproxy
  * ----------------------------------------------------------------------------- */
-SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func)
-{
 #if PY_VERSION_HEX >= 0x03000000
+SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *func)
+{
   return PyInstanceMethod_New(func);
+}
 #else
+SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *SWIGUNUSEDPARM(func))
+{
   return NULL;
-#endif
 }
+#endif
 
 #ifdef __cplusplus
-#if 0
-{ /* cc-mode */
-#endif
 }
 #endif
 
 
 /* -----------------------------------------------------------------------------
- * See the LICENSE file for information on copyright, usage and redistribution
- * of SWIG, and the README file for authors - http://www.swig.org/release.html.
- *
  * pyrun.swg
  *
  * This file contains the runtime support for Python modules
@@ -1081,7 +1141,15 @@ SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func)
 #define SWIG_Python_ConvertPtr(obj, pptr, type, flags)  SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, 0)
 #define SWIG_ConvertPtr(obj, pptr, type, flags)         SWIG_Python_ConvertPtr(obj, pptr, type, flags)
 #define SWIG_ConvertPtrAndOwn(obj,pptr,type,flags,own)  SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, own)
-#define SWIG_NewPointerObj(ptr, type, flags)            SWIG_Python_NewPointerObj(ptr, type, flags)
+
+#ifdef SWIGPYTHON_BUILTIN
+#define SWIG_NewPointerObj(ptr, type, flags)            SWIG_Python_NewPointerObj(self, ptr, type, flags)
+#else
+#define SWIG_NewPointerObj(ptr, type, flags)            SWIG_Python_NewPointerObj(NULL, ptr, type, flags)
+#endif
+
+#define SWIG_InternalNewPointerObj(ptr, type, flags)	SWIG_Python_NewPointerObj(NULL, ptr, type, flags)
+
 #define SWIG_CheckImplicit(ty)                          SWIG_Python_CheckImplicit(ty) 
 #define SWIG_AcquirePtr(ptr, src)                       SWIG_Python_AcquirePtr(ptr, src)
 #define swig_owntype                                    int
@@ -1096,7 +1164,7 @@ SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func)
 
 /* for C or C++ function pointers */
 #define SWIG_ConvertFunctionPtr(obj, pptr, type)        SWIG_Python_ConvertFunctionPtr(obj, pptr, type)
-#define SWIG_NewFunctionPtrObj(ptr, type)               SWIG_Python_NewPointerObj(ptr, type, 0)
+#define SWIG_NewFunctionPtrObj(ptr, type)               SWIG_Python_NewPointerObj(NULL, ptr, type, 0)
 
 /* for C++ member pointers, ie, member methods */
 #define SWIG_ConvertMember(obj, ptr, sz, ty)            SWIG_Python_ConvertPacked(obj, ptr, sz, ty)
@@ -1105,11 +1173,7 @@ SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func)
 
 /* Runtime API */
 
-#if PY_VERSION_HEX >= 0x03020000
-#define SWIG_PYTHON_USE_CAPSULE
-#endif
-
-#define SWIG_GetModule(clientdata)                      SWIG_Python_GetModule()
+#define SWIG_GetModule(clientdata)                      SWIG_Python_GetModule(clientdata)
 #define SWIG_SetModule(clientdata, pointer)             SWIG_Python_SetModule(pointer)
 #define SWIG_NewClientData(obj)                         SwigPyClientData_New(obj)
 
@@ -1135,7 +1199,7 @@ SWIG_Python_SetErrorObj(PyObject *errtype, PyObject *obj) {
 SWIGINTERN void 
 SWIG_Python_SetErrorMsg(PyObject *errtype, const char *msg) {
   SWIG_PYTHON_THREAD_BEGIN_BLOCK;
-  PyErr_SetString(errtype, (char *) msg);
+  PyErr_SetString(errtype, msg);
   SWIG_PYTHON_THREAD_END_BLOCK;
 }
 
@@ -1143,12 +1207,41 @@ SWIG_Python_SetErrorMsg(PyObject *errtype, const char *msg) {
 
 /* Set a constant value */
 
+#if defined(SWIGPYTHON_BUILTIN)
+
+SWIGINTERN void
+SwigPyBuiltin_AddPublicSymbol(PyObject *seq, const char *key) {
+  PyObject *s = PyString_InternFromString(key);
+  PyList_Append(seq, s);
+  Py_DECREF(s);
+}
+
+SWIGINTERN void
+SWIG_Python_SetConstant(PyObject *d, PyObject *public_interface, const char *name, PyObject *obj) {   
+#if PY_VERSION_HEX < 0x02030000
+  PyDict_SetItemString(d, (char *)name, obj);
+#else
+  PyDict_SetItemString(d, name, obj);
+#endif
+  Py_DECREF(obj);
+  if (public_interface)
+    SwigPyBuiltin_AddPublicSymbol(public_interface, name);
+}
+
+#else
+
 SWIGINTERN void
 SWIG_Python_SetConstant(PyObject *d, const char *name, PyObject *obj) {   
-  PyDict_SetItemString(d, (char*) name, obj);
+#if PY_VERSION_HEX < 0x02030000
+  PyDict_SetItemString(d, (char *)name, obj);
+#else
+  PyDict_SetItemString(d, name, obj);
+#endif
   Py_DECREF(obj);                            
 }
 
+#endif
+
 /* Append a value to the result obj */
 
 SWIGINTERN PyObject*
@@ -1209,6 +1302,14 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi
     }
   }  
   if (!PyTuple_Check(args)) {
+    if (min <= 1 && max >= 1) {
+      register int i;
+      objs[0] = args;
+      for (i = 1; i < max; ++i) {
+	objs[i] = 0;
+      }
+      return 2;
+    }
     PyErr_SetString(PyExc_SystemError, "UnpackTuple() argument list is not a tuple");
     return 0;
   } else {
@@ -1261,11 +1362,11 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi
 
 #define SWIG_POINTER_IMPLICIT_CONV  (SWIG_POINTER_DISOWN   << 1)
 
+#define SWIG_BUILTIN_TP_INIT	    (SWIG_POINTER_OWN << 2)
+#define SWIG_BUILTIN_INIT	    (SWIG_BUILTIN_TP_INIT | SWIG_POINTER_OWN)
+
 #ifdef __cplusplus
 extern "C" {
-#if 0
-} /* cc-mode */
-#endif
 #endif
 
 /*  How to access Py_None */
@@ -1316,6 +1417,7 @@ typedef struct {
   PyObject *destroy;
   int delargs;
   int implicitconv;
+  PyTypeObject *pytype;
 } SwigPyClientData;
 
 SWIGRUNTIMEINLINE int 
@@ -1382,13 +1484,13 @@ SwigPyClientData_New(PyObject* obj)
       data->delargs = 0;
     }
     data->implicitconv = 0;
+    data->pytype = 0;
     return data;
   }
 }
 
 SWIGRUNTIME void 
-SwigPyClientData_Del(SwigPyClientData* data)
-{
+SwigPyClientData_Del(SwigPyClientData *data) {
   Py_XDECREF(data->newraw);
   Py_XDECREF(data->newargs);
   Py_XDECREF(data->destroy);
@@ -1402,6 +1504,9 @@ typedef struct {
   swig_type_info *ty;
   int own;
   PyObject *next;
+#ifdef SWIGPYTHON_BUILTIN
+  PyObject *dict;
+#endif
 } SwigPyObject;
 
 SWIGRUNTIME PyObject *
@@ -1452,54 +1557,26 @@ SwigPyObject_repr(SwigPyObject *v, PyObject *args)
 #endif
 {
   const char *name = SWIG_TypePrettyName(v->ty);
-  PyObject *repr = SWIG_Python_str_FromFormat("<Swig Object of type '%s' at %p>", name, v);
+  PyObject *repr = SWIG_Python_str_FromFormat("<Swig Object of type '%s' at %p>", (name ? name : "unknown"), (void *)v);
   if (v->next) {
-#ifdef METH_NOARGS
+# ifdef METH_NOARGS
     PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next);
-#else
+# else
     PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next, args);
-#endif
-#if PY_VERSION_HEX >= 0x03000000
+# endif
+# if PY_VERSION_HEX >= 0x03000000
     PyObject *joined = PyUnicode_Concat(repr, nrep);
     Py_DecRef(repr);
     Py_DecRef(nrep);
     repr = joined;
-#else
+# else
     PyString_ConcatAndDel(&repr,nrep);
-#endif
+# endif
   }
   return repr;  
 }
 
 SWIGRUNTIME int
-SwigPyObject_print(SwigPyObject *v, FILE *fp, int SWIGUNUSEDPARM(flags))
-{
-  char *str;
-#ifdef METH_NOARGS
-  PyObject *repr = SwigPyObject_repr(v);
-#else
-  PyObject *repr = SwigPyObject_repr(v, NULL);
-#endif
-  if (repr) {
-    str = SWIG_Python_str_AsChar(repr); 
-    fputs(str, fp);
-    SWIG_Python_str_DelForPy3(str);
-    Py_DECREF(repr);
-    return 0; 
-  } else {
-    return 1; 
-  }
-}
-
-SWIGRUNTIME PyObject *
-SwigPyObject_str(SwigPyObject *v)
-{
-  char result[SWIG_BUFFER_SIZE];
-  return SWIG_PackVoidPtr(result, v->ptr, v->ty->name, sizeof(result)) ?
-    SWIG_Python_str_FromChar(result) : 0;
-}
-
-SWIGRUNTIME int
 SwigPyObject_compare(SwigPyObject *v, SwigPyObject *w)
 {
   void *i = v->ptr;
@@ -1516,27 +1593,43 @@ SwigPyObject_richcompare(SwigPyObject *v, SwigPyObject *w, int op)
     Py_INCREF(Py_NotImplemented);
     return Py_NotImplemented;
   }
-  if( (SwigPyObject_compare(v, w)==0) == (op == Py_EQ) )
-    res = Py_True;
-  else
-    res = Py_False;
-  Py_INCREF(res);
+  res = PyBool_FromLong( (SwigPyObject_compare(v, w)==0) == (op == Py_EQ) ? 1 : 0);
   return res;  
 }
 
 
-SWIGRUNTIME PyTypeObject* _PySwigObject_type(void);
+SWIGRUNTIME PyTypeObject* SwigPyObject_TypeOnce(void);
 
+#ifdef SWIGPYTHON_BUILTIN
+static swig_type_info *SwigPyObject_stype = 0;
 SWIGRUNTIME PyTypeObject*
 SwigPyObject_type(void) {
-  static PyTypeObject *SWIG_STATIC_POINTER(type) = _PySwigObject_type();
+    SwigPyClientData *cd;
+    assert(SwigPyObject_stype);
+    cd = (SwigPyClientData*) SwigPyObject_stype->clientdata;
+    assert(cd);
+    assert(cd->pytype);
+    return cd->pytype;
+}
+#else
+SWIGRUNTIME PyTypeObject*
+SwigPyObject_type(void) {
+  static PyTypeObject *SWIG_STATIC_POINTER(type) = SwigPyObject_TypeOnce();
   return type;
 }
+#endif
 
 SWIGRUNTIMEINLINE int
 SwigPyObject_Check(PyObject *op) {
+#ifdef SWIGPYTHON_BUILTIN
+  PyTypeObject *target_tp = SwigPyObject_type();
+  if (PyType_IsSubtype(op->ob_type, target_tp))
+    return 1;
+  return (strcmp(op->ob_type->tp_name, "SwigPyObject") == 0);
+#else
   return (Py_TYPE(op) == SwigPyObject_type())
     || (strcmp(Py_TYPE(op)->tp_name,"SwigPyObject") == 0);
+#endif
 }
 
 SWIGRUNTIME PyObject *
@@ -1640,8 +1733,10 @@ SwigPyObject_own(PyObject *v, PyObject *args)
   PyObject *val = 0;
 #if (PY_VERSION_HEX < 0x02020000)
   if (!PyArg_ParseTuple(args,(char *)"|O:own",&val))
-#else
+#elif (PY_VERSION_HEX < 0x02050000)
   if (!PyArg_UnpackTuple(args, (char *)"own", 0, 1, &val)) 
+#else
+  if (!PyArg_UnpackTuple(args, "own", 0, 1, &val)) 
 #endif
     {
       return NULL;
@@ -1673,7 +1768,7 @@ SwigPyObject_own(PyObject *v, PyObject *args)
 static PyMethodDef
 swigobject_methods[] = {
   {(char *)"disown",  (PyCFunction)SwigPyObject_disown,  METH_NOARGS,  (char *)"releases ownership of the pointer"},
-  {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_NOARGS,  (char *)"aquires ownership of the pointer"},
+  {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_NOARGS,  (char *)"acquires ownership of the pointer"},
   {(char *)"own",     (PyCFunction)SwigPyObject_own,     METH_VARARGS, (char *)"returns/sets ownership of the pointer"},
   {(char *)"append",  (PyCFunction)SwigPyObject_append,  METH_O,       (char *)"appends another 'this' object"},
   {(char *)"next",    (PyCFunction)SwigPyObject_next,    METH_NOARGS,  (char *)"returns the next 'this' object"},
@@ -1702,9 +1797,9 @@ SwigPyObject_getattr(SwigPyObject *sobj,char *name)
 #endif
 
 SWIGRUNTIME PyTypeObject*
-_PySwigObject_type(void) {
+SwigPyObject_TypeOnce(void) {
   static char swigobject_doc[] = "Swig object carries a C/C++ instance pointer";
-  
+
   static PyNumberMethods SwigPyObject_as_number = {
     (binaryfunc)0, /*nb_add*/
     (binaryfunc)0, /*nb_subtract*/
@@ -1751,85 +1846,89 @@ _PySwigObject_type(void) {
 #endif
   };
 
-  static PyTypeObject swigpyobject_type;  
+  static PyTypeObject swigpyobject_type;
   static int type_init = 0;
   if (!type_init) {
-    const PyTypeObject tmp
-      = {
-	/* PyObject header changed in Python 3 */
+    const PyTypeObject tmp = {
+      /* PyObject header changed in Python 3 */
 #if PY_VERSION_HEX >= 0x03000000
-	PyVarObject_HEAD_INIT(&PyType_Type, 0)
-#else    
-	PyObject_HEAD_INIT(NULL)
-	0,				    /* ob_size */
-#endif
-	(char *)"SwigPyObject",		    /* tp_name */
-	sizeof(SwigPyObject),		    /* tp_basicsize */
-	0,			            /* tp_itemsize */
-	(destructor)SwigPyObject_dealloc,   /* tp_dealloc */
-	(printfunc)SwigPyObject_print,	    /* tp_print */
+      PyVarObject_HEAD_INIT(NULL, 0)
+#else
+      PyObject_HEAD_INIT(NULL)
+      0,                                    /* ob_size */
+#endif
+      (char *)"SwigPyObject",               /* tp_name */
+      sizeof(SwigPyObject),                 /* tp_basicsize */
+      0,                                    /* tp_itemsize */
+      (destructor)SwigPyObject_dealloc,     /* tp_dealloc */
+      0,				    /* tp_print */
 #if PY_VERSION_HEX < 0x02020000
-	(getattrfunc)SwigPyObject_getattr,  /* tp_getattr */ 
+      (getattrfunc)SwigPyObject_getattr,    /* tp_getattr */
 #else
-	(getattrfunc)0,			    /* tp_getattr */ 
+      (getattrfunc)0,                       /* tp_getattr */
 #endif
-	(setattrfunc)0,			    /* tp_setattr */ 
+      (setattrfunc)0,                       /* tp_setattr */
 #if PY_VERSION_HEX >= 0x03000000
     0, /* tp_reserved in 3.0.1, tp_compare in 3.0.0 but not used */
 #else
-	(cmpfunc)SwigPyObject_compare,	    /* tp_compare */
-#endif
-	(reprfunc)SwigPyObject_repr,	    /* tp_repr */    
-	&SwigPyObject_as_number,	    /* tp_as_number */
-	0,				    /* tp_as_sequence */
-	0,				    /* tp_as_mapping */
-	(hashfunc)0,			    /* tp_hash */
-	(ternaryfunc)0,			    /* tp_call */
-	(reprfunc)SwigPyObject_str,	    /* tp_str */
-	PyObject_GenericGetAttr,            /* tp_getattro */
-	0,				    /* tp_setattro */
-	0,		                    /* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT,	            /* tp_flags */
-	swigobject_doc, 	            /* tp_doc */        
-	0,                                  /* tp_traverse */
-	0,                                  /* tp_clear */
-	(richcmpfunc)SwigPyObject_richcompare,           /* tp_richcompare */
-	0,                                  /* tp_weaklistoffset */
+      (cmpfunc)SwigPyObject_compare,        /* tp_compare */
+#endif
+      (reprfunc)SwigPyObject_repr,          /* tp_repr */
+      &SwigPyObject_as_number,              /* tp_as_number */
+      0,                                    /* tp_as_sequence */
+      0,                                    /* tp_as_mapping */
+      (hashfunc)0,                          /* tp_hash */
+      (ternaryfunc)0,                       /* tp_call */
+      0,				    /* tp_str */
+      PyObject_GenericGetAttr,              /* tp_getattro */
+      0,                                    /* tp_setattro */
+      0,                                    /* tp_as_buffer */
+      Py_TPFLAGS_DEFAULT,                   /* tp_flags */
+      swigobject_doc,                       /* tp_doc */
+      0,                                    /* tp_traverse */
+      0,                                    /* tp_clear */
+      (richcmpfunc)SwigPyObject_richcompare,/* tp_richcompare */
+      0,                                    /* tp_weaklistoffset */
 #if PY_VERSION_HEX >= 0x02020000
-	0,                                  /* tp_iter */
-	0,                                  /* tp_iternext */
-	swigobject_methods,		    /* tp_methods */ 
-	0,			            /* tp_members */
-	0,				    /* tp_getset */	    	
-	0,			            /* tp_base */	        
-	0,				    /* tp_dict */	    	
-	0,				    /* tp_descr_get */  	
-	0,				    /* tp_descr_set */  	
-	0,				    /* tp_dictoffset */ 	
-	0,				    /* tp_init */	    	
-	0,				    /* tp_alloc */	    	
-	0,			            /* tp_new */	    	
-	0,	                            /* tp_free */	   
-	0,                                  /* tp_is_gc */  
-	0,				    /* tp_bases */   
-	0,				    /* tp_mro */
-	0,				    /* tp_cache */   
-	0,				    /* tp_subclasses */
-	0,				    /* tp_weaklist */
+      0,                                    /* tp_iter */
+      0,                                    /* tp_iternext */
+      swigobject_methods,                   /* tp_methods */
+      0,                                    /* tp_members */
+      0,                                    /* tp_getset */
+      0,                                    /* tp_base */
+      0,                                    /* tp_dict */
+      0,                                    /* tp_descr_get */
+      0,                                    /* tp_descr_set */
+      0,                                    /* tp_dictoffset */
+      0,                                    /* tp_init */
+      0,                                    /* tp_alloc */
+      0,                                    /* tp_new */
+      0,                                    /* tp_free */
+      0,                                    /* tp_is_gc */
+      0,                                    /* tp_bases */
+      0,                                    /* tp_mro */
+      0,                                    /* tp_cache */
+      0,                                    /* tp_subclasses */
+      0,                                    /* tp_weaklist */
 #endif
 #if PY_VERSION_HEX >= 0x02030000
-	0,                                  /* tp_del */
+      0,                                    /* tp_del */
+#endif
+#if PY_VERSION_HEX >= 0x02060000
+      0,                                    /* tp_version */
 #endif
 #ifdef COUNT_ALLOCS
-	0,0,0,0                             /* tp_alloc -> tp_next */
+      0,0,0,0                               /* tp_alloc -> tp_next */
 #endif
-      };
+    };
     swigpyobject_type = tmp;
-    /* for Python 3 we already assigned ob_type in PyVarObject_HEAD_INIT() */
-#if PY_VERSION_HEX < 0x03000000
+    type_init = 1;
+#if PY_VERSION_HEX < 0x02020000
     swigpyobject_type.ob_type = &PyType_Type;
+#else
+    if (PyType_Ready(&swigpyobject_type) < 0)
+      return NULL;
 #endif
-    type_init = 1;
   }
   return &swigpyobject_type;
 }
@@ -1903,17 +2002,17 @@ SwigPyPacked_compare(SwigPyPacked *v, SwigPyPacked *w)
   return s ? s : strncmp((char *)v->pack, (char *)w->pack, 2*v->size);
 }
 
-SWIGRUNTIME PyTypeObject* _PySwigPacked_type(void);
+SWIGRUNTIME PyTypeObject* SwigPyPacked_TypeOnce(void);
 
 SWIGRUNTIME PyTypeObject*
 SwigPyPacked_type(void) {
-  static PyTypeObject *SWIG_STATIC_POINTER(type) = _PySwigPacked_type();
+  static PyTypeObject *SWIG_STATIC_POINTER(type) = SwigPyPacked_TypeOnce();
   return type;
 }
 
 SWIGRUNTIMEINLINE int
 SwigPyPacked_Check(PyObject *op) {
-  return ((op)->ob_type == _PySwigPacked_type()) 
+  return ((op)->ob_type == SwigPyPacked_TypeOnce()) 
     || (strcmp((op)->ob_type->tp_name,"SwigPyPacked") == 0);
 }
 
@@ -1928,83 +2027,87 @@ SwigPyPacked_dealloc(PyObject *v)
 }
 
 SWIGRUNTIME PyTypeObject*
-_PySwigPacked_type(void) {
+SwigPyPacked_TypeOnce(void) {
   static char swigpacked_doc[] = "Swig object carries a C/C++ instance pointer";
   static PyTypeObject swigpypacked_type;
-  static int type_init = 0;  
+  static int type_init = 0;
   if (!type_init) {
-    const PyTypeObject tmp
-      = {
-    /* PyObject header changed in Python 3 */
+    const PyTypeObject tmp = {
+      /* PyObject header changed in Python 3 */
 #if PY_VERSION_HEX>=0x03000000
-    PyVarObject_HEAD_INIT(&PyType_Type, 0)
+      PyVarObject_HEAD_INIT(NULL, 0)
 #else
-	PyObject_HEAD_INIT(NULL)
-    0,				    /* ob_size */	
-#endif
-	(char *)"SwigPyPacked",		    /* tp_name */	
-	sizeof(SwigPyPacked),		    /* tp_basicsize */	
-	0,				    /* tp_itemsize */	
-	(destructor)SwigPyPacked_dealloc,   /* tp_dealloc */	
-	(printfunc)SwigPyPacked_print,	    /* tp_print */   	
-	(getattrfunc)0,			    /* tp_getattr */ 	
-	(setattrfunc)0,			    /* tp_setattr */ 	
+      PyObject_HEAD_INIT(NULL)
+      0,                                    /* ob_size */
+#endif
+      (char *)"SwigPyPacked",               /* tp_name */
+      sizeof(SwigPyPacked),                 /* tp_basicsize */
+      0,                                    /* tp_itemsize */
+      (destructor)SwigPyPacked_dealloc,     /* tp_dealloc */
+      (printfunc)SwigPyPacked_print,        /* tp_print */
+      (getattrfunc)0,                       /* tp_getattr */
+      (setattrfunc)0,                       /* tp_setattr */
 #if PY_VERSION_HEX>=0x03000000
-    0, /* tp_reserved in 3.0.1 */
+      0, /* tp_reserved in 3.0.1 */
 #else
-    (cmpfunc)SwigPyPacked_compare,	    /* tp_compare */
-#endif
-	(reprfunc)SwigPyPacked_repr,	    /* tp_repr */
-	0,	                            /* tp_as_number */
-	0,				    /* tp_as_sequence */
-	0,				    /* tp_as_mapping */
-	(hashfunc)0,			    /* tp_hash */
-	(ternaryfunc)0,			    /* tp_call */
-	(reprfunc)SwigPyPacked_str,	    /* tp_str */
-	PyObject_GenericGetAttr,            /* tp_getattro */
-	0,				    /* tp_setattro */
-	0,		                    /* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT,	            /* tp_flags */
-	swigpacked_doc, 	            /* tp_doc */
-	0,                                  /* tp_traverse */
-	0,                                  /* tp_clear */
-	0,                                  /* tp_richcompare */
-	0,                                  /* tp_weaklistoffset */
+      (cmpfunc)SwigPyPacked_compare,        /* tp_compare */
+#endif
+      (reprfunc)SwigPyPacked_repr,          /* tp_repr */
+      0,                                    /* tp_as_number */
+      0,                                    /* tp_as_sequence */
+      0,                                    /* tp_as_mapping */
+      (hashfunc)0,                          /* tp_hash */
+      (ternaryfunc)0,                       /* tp_call */
+      (reprfunc)SwigPyPacked_str,           /* tp_str */
+      PyObject_GenericGetAttr,              /* tp_getattro */
+      0,                                    /* tp_setattro */
+      0,                                    /* tp_as_buffer */
+      Py_TPFLAGS_DEFAULT,                   /* tp_flags */
+      swigpacked_doc,                       /* tp_doc */
+      0,                                    /* tp_traverse */
+      0,                                    /* tp_clear */
+      0,                                    /* tp_richcompare */
+      0,                                    /* tp_weaklistoffset */
 #if PY_VERSION_HEX >= 0x02020000
-	0,                                  /* tp_iter */
-	0,                                  /* tp_iternext */
-	0,		                    /* tp_methods */ 
-	0,			            /* tp_members */
-	0,				    /* tp_getset */	    	
-	0,			            /* tp_base */	        
-	0,				    /* tp_dict */	    	
-	0,				    /* tp_descr_get */  	
-	0,				    /* tp_descr_set */  	
-	0,				    /* tp_dictoffset */ 	
-	0,				    /* tp_init */	    	
-	0,				    /* tp_alloc */	    	
-	0,			            /* tp_new */	    	
-	0, 	                            /* tp_free */	   
-        0,                                  /* tp_is_gc */  
-	0,				    /* tp_bases */   
-	0,				    /* tp_mro */
-	0,				    /* tp_cache */   
- 	0,				    /* tp_subclasses */
-	0,				    /* tp_weaklist */
+      0,                                    /* tp_iter */
+      0,                                    /* tp_iternext */
+      0,                                    /* tp_methods */
+      0,                                    /* tp_members */
+      0,                                    /* tp_getset */
+      0,                                    /* tp_base */
+      0,                                    /* tp_dict */
+      0,                                    /* tp_descr_get */
+      0,                                    /* tp_descr_set */
+      0,                                    /* tp_dictoffset */
+      0,                                    /* tp_init */
+      0,                                    /* tp_alloc */
+      0,                                    /* tp_new */
+      0,                                    /* tp_free */
+      0,                                    /* tp_is_gc */
+      0,                                    /* tp_bases */
+      0,                                    /* tp_mro */
+      0,                                    /* tp_cache */
+      0,                                    /* tp_subclasses */
+      0,                                    /* tp_weaklist */
 #endif
 #if PY_VERSION_HEX >= 0x02030000
-	0,                                  /* tp_del */
+      0,                                    /* tp_del */
+#endif
+#if PY_VERSION_HEX >= 0x02060000
+      0,                                    /* tp_version */
 #endif
 #ifdef COUNT_ALLOCS
-	0,0,0,0                             /* tp_alloc -> tp_next */
+      0,0,0,0                               /* tp_alloc -> tp_next */
 #endif
-      };
+    };
     swigpypacked_type = tmp;
-    /* for Python 3 the ob_type already assigned in PyVarObject_HEAD_INIT() */
-#if PY_VERSION_HEX < 0x03000000
+    type_init = 1;
+#if PY_VERSION_HEX < 0x02020000
     swigpypacked_type.ob_type = &PyType_Type;
+#else
+    if (PyType_Ready(&swigpypacked_type) < 0)
+      return NULL;
 #endif
-    type_init = 1;
   }
   return &swigpypacked_type;
 }
@@ -2051,10 +2154,13 @@ _SWIG_This(void)
     return SWIG_Python_str_FromChar("this");
 }
 
+static PyObject *swig_this = NULL;
+
 SWIGRUNTIME PyObject *
 SWIG_This(void)
 {
-  static PyObject *SWIG_STATIC_POINTER(swig_this) = _SWIG_This();
+  if (swig_this == NULL)
+    swig_this = _SWIG_This();
   return swig_this;
 }
 
@@ -2068,50 +2174,65 @@ SWIG_This(void)
 SWIGRUNTIME SwigPyObject *
 SWIG_Python_GetSwigThis(PyObject *pyobj) 
 {
-  if (SwigPyObject_Check(pyobj)) {
+  PyObject *obj;
+
+  if (SwigPyObject_Check(pyobj))
     return (SwigPyObject *) pyobj;
-  } else {
-    PyObject *obj = 0;
+
+#ifdef SWIGPYTHON_BUILTIN
+  (void)obj;
+# ifdef PyWeakref_CheckProxy
+  if (PyWeakref_CheckProxy(pyobj)) {
+    pyobj = PyWeakref_GET_OBJECT(pyobj);
+    if (pyobj && SwigPyObject_Check(pyobj))
+      return (SwigPyObject*) pyobj;
+  }
+# endif
+  return NULL;
+#else
+
+  obj = 0;
+
 #if (!defined(SWIG_PYTHON_SLOW_GETSET_THIS) && (PY_VERSION_HEX >= 0x02030000))
-    if (PyInstance_Check(pyobj)) {
-      obj = _PyInstance_Lookup(pyobj, SWIG_This());      
+  if (PyInstance_Check(pyobj)) {
+    obj = _PyInstance_Lookup(pyobj, SWIG_This());      
+  } else {
+    PyObject **dictptr = _PyObject_GetDictPtr(pyobj);
+    if (dictptr != NULL) {
+      PyObject *dict = *dictptr;
+      obj = dict ? PyDict_GetItem(dict, SWIG_This()) : 0;
     } else {
-      PyObject **dictptr = _PyObject_GetDictPtr(pyobj);
-      if (dictptr != NULL) {
-	PyObject *dict = *dictptr;
-	obj = dict ? PyDict_GetItem(dict, SWIG_This()) : 0;
-      } else {
 #ifdef PyWeakref_CheckProxy
-	if (PyWeakref_CheckProxy(pyobj)) {
-	  PyObject *wobj = PyWeakref_GET_OBJECT(pyobj);
-	  return wobj ? SWIG_Python_GetSwigThis(wobj) : 0;
-	}
+      if (PyWeakref_CheckProxy(pyobj)) {
+	PyObject *wobj = PyWeakref_GET_OBJECT(pyobj);
+	return wobj ? SWIG_Python_GetSwigThis(wobj) : 0;
+      }
 #endif
-	obj = PyObject_GetAttr(pyobj,SWIG_This());
-	if (obj) {
-	  Py_DECREF(obj);
-	} else {
-	  if (PyErr_Occurred()) PyErr_Clear();
-	  return 0;
-	}
+      obj = PyObject_GetAttr(pyobj,SWIG_This());
+      if (obj) {
+	Py_DECREF(obj);
+      } else {
+	if (PyErr_Occurred()) PyErr_Clear();
+	return 0;
       }
     }
+  }
 #else
-    obj = PyObject_GetAttr(pyobj,SWIG_This());
-    if (obj) {
-      Py_DECREF(obj);
-    } else {
-      if (PyErr_Occurred()) PyErr_Clear();
-      return 0;
-    }
+  obj = PyObject_GetAttr(pyobj,SWIG_This());
+  if (obj) {
+    Py_DECREF(obj);
+  } else {
+    if (PyErr_Occurred()) PyErr_Clear();
+    return 0;
+  }
 #endif
-    if (obj && !SwigPyObject_Check(obj)) {
-      /* a PyObject is called 'this', try to get the 'real this'
-	 SwigPyObject from it */ 
-      return SWIG_Python_GetSwigThis(obj);
-    }
-    return (SwigPyObject *)obj;
+  if (obj && !SwigPyObject_Check(obj)) {
+    /* a PyObject is called 'this', try to get the 'real this'
+       SwigPyObject from it */ 
+    return SWIG_Python_GetSwigThis(obj);
   }
+  return (SwigPyObject *)obj;
+#endif
 }
 
 /* Acquire a pointer value */
@@ -2133,91 +2254,105 @@ SWIG_Python_AcquirePtr(PyObject *obj, int own) {
 
 SWIGRUNTIME int
 SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int flags, int *own) {
-  if (!obj) return SWIG_ERROR;
-  if (obj == Py_None) {
-    if (ptr) *ptr = 0;
+  int res;
+  SwigPyObject *sobj;
+  int implicit_conv = (flags & SWIG_POINTER_IMPLICIT_CONV) != 0;
+
+  if (!obj)
+    return SWIG_ERROR;
+  if (obj == Py_None && !implicit_conv) {
+    if (ptr)
+      *ptr = 0;
     return SWIG_OK;
-  } else {
-    SwigPyObject *sobj = SWIG_Python_GetSwigThis(obj);
+  }
+
+  res = SWIG_ERROR;
+
+  sobj = SWIG_Python_GetSwigThis(obj);
+  if (own)
+    *own = 0;
+  while (sobj) {
+    void *vptr = sobj->ptr;
+    if (ty) {
+      swig_type_info *to = sobj->ty;
+      if (to == ty) {
+        /* no type cast needed */
+        if (ptr) *ptr = vptr;
+        break;
+      } else {
+        swig_cast_info *tc = SWIG_TypeCheck(to->name,ty);
+        if (!tc) {
+          sobj = (SwigPyObject *)sobj->next;
+        } else {
+          if (ptr) {
+            int newmemory = 0;
+            *ptr = SWIG_TypeCast(tc,vptr,&newmemory);
+            if (newmemory == SWIG_CAST_NEW_MEMORY) {
+              assert(own); /* badly formed typemap which will lead to a memory leak - it must set and use own to delete *ptr */
+              if (own)
+                *own = *own | SWIG_CAST_NEW_MEMORY;
+            }
+          }
+          break;
+        }
+      }
+    } else {
+      if (ptr) *ptr = vptr;
+      break;
+    }
+  }
+  if (sobj) {
     if (own)
-      *own = 0;
-    while (sobj) {
-      void *vptr = sobj->ptr;
-      if (ty) {
-	swig_type_info *to = sobj->ty;
-	if (to == ty) {
-	  /* no type cast needed */
-	  if (ptr) *ptr = vptr;
-	  break;
-	} else {
-	  swig_cast_info *tc = SWIG_TypeCheck(to->name,ty);
-	  if (!tc) {
-	    sobj = (SwigPyObject *)sobj->next;
-	  } else {
-	    if (ptr) {
-              int newmemory = 0;
-              *ptr = SWIG_TypeCast(tc,vptr,&newmemory);
-              if (newmemory == SWIG_CAST_NEW_MEMORY) {
-                assert(own);
-                if (own)
-                  *own = *own | SWIG_CAST_NEW_MEMORY;
+      *own = *own | sobj->own;
+    if (flags & SWIG_POINTER_DISOWN) {
+      sobj->own = 0;
+    }
+    res = SWIG_OK;
+  } else {
+    if (implicit_conv) {
+      SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0;
+      if (data && !data->implicitconv) {
+        PyObject *klass = data->klass;
+        if (klass) {
+          PyObject *impconv;
+          data->implicitconv = 1; /* avoid recursion and call 'explicit' constructors*/
+          impconv = SWIG_Python_CallFunctor(klass, obj);
+          data->implicitconv = 0;
+          if (PyErr_Occurred()) {
+            PyErr_Clear();
+            impconv = 0;
+          }
+          if (impconv) {
+            SwigPyObject *iobj = SWIG_Python_GetSwigThis(impconv);
+            if (iobj) {
+              void *vptr;
+              res = SWIG_Python_ConvertPtrAndOwn((PyObject*)iobj, &vptr, ty, 0, 0);
+              if (SWIG_IsOK(res)) {
+                if (ptr) {
+                  *ptr = vptr;
+                  /* transfer the ownership to 'ptr' */
+                  iobj->own = 0;
+                  res = SWIG_AddCast(res);
+                  res = SWIG_AddNewMask(res);
+                } else {
+                  res = SWIG_AddCast(res);		    
+                }
               }
             }
-	    break;
-	  }
-	}
-      } else {
-	if (ptr) *ptr = vptr;
-	break;
+            Py_DECREF(impconv);
+          }
+        }
       }
     }
-    if (sobj) {
-      if (own)
-        *own = *own | sobj->own;
-      if (flags & SWIG_POINTER_DISOWN) {
-	sobj->own = 0;
-      }
-      return SWIG_OK;
-    } else {
-      int res = SWIG_ERROR;
-      if (flags & SWIG_POINTER_IMPLICIT_CONV) {
-	SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0;
-	if (data && !data->implicitconv) {
-	  PyObject *klass = data->klass;
-	  if (klass) {
-	    PyObject *impconv;
-	    data->implicitconv = 1; /* avoid recursion and call 'explicit' constructors*/
-	    impconv = SWIG_Python_CallFunctor(klass, obj);
-	    data->implicitconv = 0;
-	    if (PyErr_Occurred()) {
-	      PyErr_Clear();
-	      impconv = 0;
-	    }
-	    if (impconv) {
-	      SwigPyObject *iobj = SWIG_Python_GetSwigThis(impconv);
-	      if (iobj) {
-		void *vptr;
-		res = SWIG_Python_ConvertPtrAndOwn((PyObject*)iobj, &vptr, ty, 0, 0);
-		if (SWIG_IsOK(res)) {
-		  if (ptr) {
-		    *ptr = vptr;
-		    /* transfer the ownership to 'ptr' */
-		    iobj->own = 0;
-		    res = SWIG_AddCast(res);
-		    res = SWIG_AddNewMask(res);
-		  } else {
-		    res = SWIG_AddCast(res);		    
-		  }
-		}
-	      }
-	      Py_DECREF(impconv);
-	    }
-	  }
-	}
-      }
-      return res;
+    if (!SWIG_IsOK(res) && obj == Py_None) {
+      if (ptr)
+        *ptr = 0;
+      if (PyErr_Occurred())
+        PyErr_Clear();
+      res = SWIG_OK;
     }
   }
+  return res;
 }
 
 /* Convert a function ptr value */
@@ -2304,23 +2439,29 @@ SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this)
   } else {
 #if PY_VERSION_HEX >= 0x03000000
     inst = PyBaseObject_Type.tp_new((PyTypeObject*) data->newargs, Py_None, Py_None);
-    PyObject_SetAttr(inst, SWIG_This(), swig_this);
-    Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
+    if (inst) {
+      PyObject_SetAttr(inst, SWIG_This(), swig_this);
+      Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
+    }
 #else
     PyObject *dict = PyDict_New();
-    PyDict_SetItem(dict, SWIG_This(), swig_this);
-    inst = PyInstance_NewRaw(data->newargs, dict);
-    Py_DECREF(dict);
+    if (dict) {
+      PyDict_SetItem(dict, SWIG_This(), swig_this);
+      inst = PyInstance_NewRaw(data->newargs, dict);
+      Py_DECREF(dict);
+    }
 #endif
   }
   return inst;
 #else
 #if (PY_VERSION_HEX >= 0x02010000)
-  PyObject *inst;
+  PyObject *inst = 0;
   PyObject *dict = PyDict_New();
-  PyDict_SetItem(dict, SWIG_This(), swig_this);
-  inst = PyInstance_NewRaw(data->newargs, dict);
-  Py_DECREF(dict);
+  if (dict) {
+    PyDict_SetItem(dict, SWIG_This(), swig_this);
+    inst = PyInstance_NewRaw(data->newargs, dict);
+    Py_DECREF(dict);
+  }
   return (PyObject *) inst;
 #else
   PyInstanceObject *inst = PyObject_NEW(PyInstanceObject, &PyInstance_Type);
@@ -2371,7 +2512,7 @@ SWIG_Python_SetSwigThis(PyObject *inst, PyObject *swig_this)
 SWIGINTERN PyObject *
 SWIG_Python_InitShadowInstance(PyObject *args) {
   PyObject *obj[2];
-  if (!SWIG_Python_UnpackTuple(args,(char*)"swiginit", 2, 2, obj)) {
+  if (!SWIG_Python_UnpackTuple(args, "swiginit", 2, 2, obj)) {
     return NULL;
   } else {
     SwigPyObject *sthis = SWIG_Python_GetSwigThis(obj[0]);
@@ -2387,22 +2528,52 @@ SWIG_Python_InitShadowInstance(PyObject *args) {
 /* Create a new pointer object */
 
 SWIGRUNTIME PyObject *
-SWIG_Python_NewPointerObj(void *ptr, swig_type_info *type, int flags) {
-  if (!ptr) {
+SWIG_Python_NewPointerObj(PyObject *self, void *ptr, swig_type_info *type, int flags) {
+  SwigPyClientData *clientdata;
+  PyObject * robj;
+  int own;
+
+  if (!ptr)
     return SWIG_Py_Void();
-  } else {
-    int own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0;
-    PyObject *robj = SwigPyObject_New(ptr, type, own);
-    SwigPyClientData *clientdata = type ? (SwigPyClientData *)(type->clientdata) : 0;
-    if (clientdata && !(flags & SWIG_POINTER_NOSHADOW)) {
-      PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj);
-      if (inst) {
-	Py_DECREF(robj);
-	robj = inst;
+
+  clientdata = type ? (SwigPyClientData *)(type->clientdata) : 0;
+  own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0;
+  if (clientdata && clientdata->pytype) {
+    SwigPyObject *newobj;
+    if (flags & SWIG_BUILTIN_TP_INIT) {
+      newobj = (SwigPyObject*) self;
+      if (newobj->ptr) {
+        PyObject *next_self = clientdata->pytype->tp_alloc(clientdata->pytype, 0);
+        while (newobj->next)
+	  newobj = (SwigPyObject *) newobj->next;
+        newobj->next = next_self;
+        newobj = (SwigPyObject *)next_self;
       }
+    } else {
+      newobj = PyObject_New(SwigPyObject, clientdata->pytype);
+    }
+    if (newobj) {
+      newobj->ptr = ptr;
+      newobj->ty = type;
+      newobj->own = own;
+      newobj->next = 0;
+#ifdef SWIGPYTHON_BUILTIN
+      newobj->dict = 0;
+#endif
+      return (PyObject*) newobj;
     }
-    return robj;
+    return SWIG_Py_Void();
   }
+
+  assert(!(flags & SWIG_BUILTIN_TP_INIT));
+
+  robj = SwigPyObject_New(ptr, type, own);
+  if (robj && clientdata && !(flags & SWIG_POINTER_NOSHADOW)) {
+    PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj);
+    Py_DECREF(robj);
+    robj = inst;
+  }
+  return robj;
 }
 
 /* Create a new packed object */
@@ -2421,19 +2592,19 @@ void *SWIG_ReturnGlobalTypeList(void *);
 #endif
 
 SWIGRUNTIME swig_module_info *
-SWIG_Python_GetModule(void) {
+SWIG_Python_GetModule(void *SWIGUNUSEDPARM(clientdata)) {
   static void *type_pointer = (void *)0;
   /* first check if module already created */
   if (!type_pointer) {
 #ifdef SWIG_LINK_RUNTIME
     type_pointer = SWIG_ReturnGlobalTypeList((void *)0);
 #else
-#ifdef SWIG_PYTHON_USE_CAPSULE
-    type_pointer = PyCapsule_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer" SWIG_TYPE_TABLE_NAME, 0);
-#else
+# ifdef SWIGPY_USE_CAPSULE
+    type_pointer = PyCapsule_Import(SWIGPY_CAPSULE_NAME, 0);
+# else
     type_pointer = PyCObject_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
 				    (char*)"type_pointer" SWIG_TYPE_TABLE_NAME);
-#endif
+# endif
     if (PyErr_Occurred()) {
       PyErr_Clear();
       type_pointer = (void *)0;
@@ -2476,26 +2647,19 @@ PyModule_AddObject(PyObject *m, char *name, PyObject *o)
 #endif
 
 SWIGRUNTIME void
-#ifdef SWIG_PYTHON_USE_CAPSULE
-SWIG_Python_DestroyModule(PyObject *capsule)
-{
-  swig_module_info *swig_module;
-  swig_type_info **types;
-  size_t i;
-  swig_module = (swig_module_info *)PyCapsule_GetPointer(capsule, (char*)"swig_runtime_data" SWIG_RUNTIME_VERSION);
-  if (swig_module == NULL)
-  {
-    PyErr_Clear();
-    return;
-  }
-  types = swig_module->types;
+#ifdef SWIGPY_USE_CAPSULE
+SWIG_Python_DestroyModule(PyObject *obj)
 #else
 SWIG_Python_DestroyModule(void *vptr)
+#endif
 {
+#ifdef SWIGPY_USE_CAPSULE
+  swig_module_info *swig_module = (swig_module_info *) PyCapsule_GetPointer(obj, SWIGPY_CAPSULE_NAME);
+#else
   swig_module_info *swig_module = (swig_module_info *) vptr;
+#endif
   swig_type_info **types = swig_module->types;
   size_t i;
-#endif
   for (i =0; i < swig_module->size; ++i) {
     swig_type_info *ty = types[i];
     if (ty->owndata) {
@@ -2504,31 +2668,33 @@ SWIG_Python_DestroyModule(void *vptr)
     }
   }
   Py_DECREF(SWIG_This());
+  swig_this = NULL;
 }
 
 SWIGRUNTIME void
 SWIG_Python_SetModule(swig_module_info *swig_module) {
-  static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} };/* Sentinel */
-
 #if PY_VERSION_HEX >= 0x03000000
  /* Add a dummy module object into sys.modules */
   PyObject *module = PyImport_AddModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION);
 #else
-  PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
-				   swig_empty_runtime_method_table);
+  static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} }; /* Sentinel */
+  PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION, swig_empty_runtime_method_table);
 #endif
-#ifdef SWIG_PYTHON_USE_CAPSULE
-  PyObject *pointer = PyCapsule_New((void *) swig_module,
-                                    (char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer" SWIG_TYPE_TABLE_NAME,
-                                    SWIG_Python_DestroyModule);
+#ifdef SWIGPY_USE_CAPSULE
+  PyObject *pointer = PyCapsule_New((void *) swig_module, SWIGPY_CAPSULE_NAME, SWIG_Python_DestroyModule);
+  if (pointer && module) {
+    PyModule_AddObject(module, (char*)"type_pointer_capsule" SWIG_TYPE_TABLE_NAME, pointer);
+  } else {
+    Py_XDECREF(pointer);
+  }
 #else
   PyObject *pointer = PyCObject_FromVoidPtr((void *) swig_module, SWIG_Python_DestroyModule);
-#endif
   if (pointer && module) {
     PyModule_AddObject(module, (char*)"type_pointer" SWIG_TYPE_TABLE_NAME, pointer);
   } else {
     Py_XDECREF(pointer);
   }
+#endif
 }
 
 /* The python cached type query */
@@ -2546,17 +2712,17 @@ SWIG_Python_TypeQuery(const char *type)
   PyObject *obj = PyDict_GetItem(cache, key);
   swig_type_info *descriptor;
   if (obj) {
-#ifdef SWIG_PYTHON_USE_CAPSULE
-    descriptor = (swig_type_info *) PyCapsule_GetPointer(obj, (char*)"swig_type_info");
+#ifdef SWIGPY_USE_CAPSULE
+    descriptor = (swig_type_info *) PyCapsule_GetPointer(obj, NULL);
 #else
     descriptor = (swig_type_info *) PyCObject_AsVoidPtr(obj);
 #endif
   } else {
-    swig_module_info *swig_module = SWIG_Python_GetModule();
+    swig_module_info *swig_module = SWIG_GetModule(0);
     descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type);
     if (descriptor) {
-#ifdef SWIG_PYTHON_USE_CAPSULE
-      obj = PyCapsule_New(descriptor, (char*)"swig_type_info", NULL);
+#ifdef SWIGPY_USE_CAPSULE
+      obj = PyCapsule_New((void*) descriptor, NULL, NULL);
 #else
       obj = PyCObject_FromVoidPtr(descriptor, NULL);
 #endif
@@ -2620,7 +2786,7 @@ SwigPyObject_GetDesc(PyObject *self)
 {
   SwigPyObject *v = (SwigPyObject *)self;
   swig_type_info *ty = v ? v->ty : 0;
-  return ty ? ty->str : (char*)"";
+  return ty ? ty->str : "";
 }
 
 SWIGRUNTIME void
@@ -2663,7 +2829,7 @@ SWIG_Python_TypeError(const char *type, PyObject *obj)
 
 /* Convert a pointer value, signal an exception on a type mismatch */
 SWIGRUNTIME void *
-SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int argnum, int flags) {
+SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int SWIGUNUSEDPARM(argnum), int flags) {
   void *result;
   if (SWIG_Python_ConvertPtr(obj, &result, ty, flags) == -1) {
     PyErr_Clear();
@@ -2677,11 +2843,61 @@ SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int argnum, int flags)
   return result;
 }
 
+#ifdef SWIGPYTHON_BUILTIN
+SWIGRUNTIME int
+SWIG_Python_NonDynamicSetAttr(PyObject *obj, PyObject *name, PyObject *value) {
+  PyTypeObject *tp = obj->ob_type;
+  PyObject *descr;
+  PyObject *encoded_name;
+  descrsetfunc f;
+  int res = -1;
+
+# ifdef Py_USING_UNICODE
+  if (PyString_Check(name)) {
+    name = PyUnicode_Decode(PyString_AsString(name), PyString_Size(name), NULL, NULL);
+    if (!name)
+      return -1;
+  } else if (!PyUnicode_Check(name))
+# else
+  if (!PyString_Check(name))
+# endif
+  {
+    PyErr_Format(PyExc_TypeError, "attribute name must be string, not '%.200s'", name->ob_type->tp_name);
+    return -1;
+  } else {
+    Py_INCREF(name);
+  }
 
-#ifdef __cplusplus
-#if 0
-{ /* cc-mode */
+  if (!tp->tp_dict) {
+    if (PyType_Ready(tp) < 0)
+      goto done;
+  }
+
+  descr = _PyType_Lookup(tp, name);
+  f = NULL;
+  if (descr != NULL)
+    f = descr->ob_type->tp_descr_set;
+  if (!f) {
+    if (PyString_Check(name)) {
+      encoded_name = name;
+      Py_INCREF(name);
+    } else {
+      encoded_name = PyUnicode_AsUTF8String(name);
+    }
+    PyErr_Format(PyExc_AttributeError, "'%.100s' object has no attribute '%.200s'", tp->tp_name, PyString_AsString(encoded_name));
+    Py_DECREF(encoded_name);
+  } else {
+    res = f(descr, obj, value);
+  }
+  
+  done:
+  Py_DECREF(name);
+  return res;
+}
 #endif
+
+
+#ifdef __cplusplus
 }
 #endif
 
@@ -2721,7 +2937,7 @@ static swig_module_info swig_module = {swig_types, 1, 0, 0, 0, 0};
 #endif
 #define SWIG_name    "_gdalconst"
 
-#define SWIGVERSION 0x010340 
+#define SWIGVERSION 0x020012 
 #define SWIG_VERSION SWIGVERSION
 
 
@@ -2735,13 +2951,10 @@ static swig_module_info swig_module = {swig_types, 1, 0, 0, 0, 0};
 #include "cpl_minixml.h"
 
 
-  #define SWIG_From_long   PyInt_FromLong 
-
-
-SWIGINTERNINLINE PyObject *
-SWIG_From_int  (int value)
-{    
-  return SWIG_From_long  (value);
+SWIGINTERNINLINE PyObject*
+  SWIG_From_int  (int value)
+{
+  return PyInt_FromLong((long) value);
 }
 
 
@@ -2765,7 +2978,7 @@ SWIG_FromCharPtrAndSize(const char* carray, size_t size)
     if (size > INT_MAX) {
       swig_type_info* pchar_descriptor = SWIG_pchar_descriptor();
       return pchar_descriptor ? 
-	SWIG_NewPointerObj((char *)(carray), pchar_descriptor, 0) : SWIG_Py_Void();
+	SWIG_InternalNewPointerObj((char *)(carray), pchar_descriptor, 0) : SWIG_Py_Void();
     } else {
 #if PY_VERSION_HEX >= 0x03000000
       return PyUnicode_FromStringAndSize(carray, (int)(size));
@@ -2819,18 +3032,18 @@ static swig_const_info swig_const_table[] = {
 #endif
 /* -----------------------------------------------------------------------------
  * Type initialization:
- * This problem is tough by the requirement that no dynamic 
- * memory is used. Also, since swig_type_info structures store pointers to 
+ * This problem is tough by the requirement that no dynamic
+ * memory is used. Also, since swig_type_info structures store pointers to
  * swig_cast_info structures and swig_cast_info structures store pointers back
- * to swig_type_info structures, we need some lookup code at initialization. 
- * The idea is that swig generates all the structures that are needed. 
- * The runtime then collects these partially filled structures. 
- * The SWIG_InitializeModule function takes these initial arrays out of 
+ * to swig_type_info structures, we need some lookup code at initialization.
+ * The idea is that swig generates all the structures that are needed.
+ * The runtime then collects these partially filled structures.
+ * The SWIG_InitializeModule function takes these initial arrays out of
  * swig_module, and does all the lookup, filling in the swig_module.types
  * array with the correct data and linking the correct swig_cast_info
  * structures together.
  *
- * The generated swig_type_info structures are assigned staticly to an initial 
+ * The generated swig_type_info structures are assigned staticly to an initial
  * array. We just loop through that array, and handle each type individually.
  * First we lookup if this type has been already loaded, and if so, use the
  * loaded structure instead of the generated one. Then we have to fill in the
@@ -2840,17 +3053,17 @@ static swig_const_info swig_const_table[] = {
  * a column is one of the swig_cast_info structures for that type.
  * The cast_initial array is actually an array of arrays, because each row has
  * a variable number of columns. So to actually build the cast linked list,
- * we find the array of casts associated with the type, and loop through it 
+ * we find the array of casts associated with the type, and loop through it
  * adding the casts to the list. The one last trick we need to do is making
  * sure the type pointer in the swig_cast_info struct is correct.
  *
- * First off, we lookup the cast->type name to see if it is already loaded. 
+ * First off, we lookup the cast->type name to see if it is already loaded.
  * There are three cases to handle:
  *  1) If the cast->type has already been loaded AND the type we are adding
  *     casting info to has not been loaded (it is in this module), THEN we
  *     replace the cast->type pointer with the type pointer that has already
  *     been loaded.
- *  2) If BOTH types (the one we are adding casting info to, and the 
+ *  2) If BOTH types (the one we are adding casting info to, and the
  *     cast->type) are loaded, THEN the cast info has already been loaded by
  *     the previous module so we just ignore it.
  *  3) Finally, if cast->type has not already been loaded, then we add that
@@ -2876,8 +3089,6 @@ SWIG_InitializeModule(void *clientdata) {
   swig_module_info *module_head, *iter;
   int found, init;
   
-  clientdata = clientdata;
-  
   /* check to see if the circular list has been setup, if not, set it up */
   if (swig_module.next==0) {
     /* Initialize the swig_module */
@@ -2895,7 +3106,7 @@ SWIG_InitializeModule(void *clientdata) {
     /* This is the first module loaded for this interpreter */
     /* so set the swig module into the interpreter */
     SWIG_SetModule(clientdata, &swig_module);
-    module_head = &swig_module;
+    /*module_head = &swig_module;*/
   } else {
     /* the interpreter has loaded a SWIG module, but has it loaded this one? */
     found=0;
@@ -2915,7 +3126,7 @@ SWIG_InitializeModule(void *clientdata) {
     module_head->next = &swig_module;
   }
   
-  /* When multiple interpeters are used, a module could have already been initialized in
+  /* When multiple interpreters are used, a module could have already been initialized in
        a different interpreter, but not yet have a pointer in this interpreter.
        In this case, we do not want to continue adding types... everything should be
        set up already */
@@ -3188,24 +3399,23 @@ extern "C" {
   swig_varlink_type(void) {
     static char varlink__doc__[] = "Swig var link object";
     static PyTypeObject varlink_type;
-    static int type_init = 0;  
+    static int type_init = 0;
     if (!type_init) {
-      const PyTypeObject tmp
-      = {
+      const PyTypeObject tmp = {
         /* PyObject header changed in Python 3 */
 #if PY_VERSION_HEX >= 0x03000000
-        PyVarObject_HEAD_INIT(&PyType_Type, 0)
+        PyVarObject_HEAD_INIT(NULL, 0)
 #else
         PyObject_HEAD_INIT(NULL)
-        0,                                  /* Number of items in variable part (ob_size) */
-#endif
-        (char *)"swigvarlink",              /* Type name (tp_name) */
-        sizeof(swig_varlinkobject),         /* Basic size (tp_basicsize) */
-        0,                                  /* Itemsize (tp_itemsize) */
-        (destructor) swig_varlink_dealloc,  /* Deallocator (tp_dealloc) */ 
-        (printfunc) swig_varlink_print,     /* Print (tp_print) */
-        (getattrfunc) swig_varlink_getattr, /* get attr (tp_getattr) */
-        (setattrfunc) swig_varlink_setattr, /* Set attr (tp_setattr) */
+        0,                                  /* ob_size */
+#endif
+        (char *)"swigvarlink",              /* tp_name */
+        sizeof(swig_varlinkobject),         /* tp_basicsize */
+        0,                                  /* tp_itemsize */
+        (destructor) swig_varlink_dealloc,  /* tp_dealloc */
+        (printfunc) swig_varlink_print,     /* tp_print */
+        (getattrfunc) swig_varlink_getattr, /* tp_getattr */
+        (setattrfunc) swig_varlink_setattr, /* tp_setattr */
         0,                                  /* tp_compare */
         (reprfunc) swig_varlink_repr,       /* tp_repr */
         0,                                  /* tp_as_number */
@@ -3229,16 +3439,21 @@ extern "C" {
 #if PY_VERSION_HEX >= 0x02030000
         0,                                  /* tp_del */
 #endif
+#if PY_VERSION_HEX >= 0x02060000
+        0,                                  /* tp_version */
+#endif
 #ifdef COUNT_ALLOCS
         0,0,0,0                             /* tp_alloc -> tp_next */
 #endif
       };
       varlink_type = tmp;
-      /* for Python 3 we already assigned ob_type in PyVarObject_HEAD_INIT() */
-#if PY_VERSION_HEX < 0x03000000
+      type_init = 1;
+#if PY_VERSION_HEX < 0x02020000
       varlink_type.ob_type = &PyType_Type;
+#else
+      if (PyType_Ready(&varlink_type) < 0)
+      return NULL;
 #endif
-      type_init = 1;
     }
     return &varlink_type;
   }
@@ -3289,7 +3504,7 @@ extern "C" {
     for (i = 0; constants[i].type; ++i) {
       switch(constants[i].type) {
       case SWIG_PY_POINTER:
-        obj = SWIG_NewPointerObj(constants[i].pvalue, *(constants[i]).ptype,0);
+        obj = SWIG_InternalNewPointerObj(constants[i].pvalue, *(constants[i]).ptype,0);
         break;
       case SWIG_PY_BINARY:
         obj = SWIG_NewPackedObj(constants[i].pvalue, constants[i].lvalue, *(constants[i].ptype));
@@ -3329,18 +3544,18 @@ extern "C" {
           }
         }
         if (ci) {
-          size_t shift = (ci->ptype) - types;
-          swig_type_info *ty = types_initial[shift];
-          size_t ldoc = (c - methods[i].ml_doc);
-          size_t lptr = strlen(ty->name)+2*sizeof(void*)+2;
-          char *ndoc = (char*)malloc(ldoc + lptr + 10);
-          if (ndoc) {
-            char *buff = ndoc;
-            void *ptr = (ci->type == SWIG_PY_POINTER) ? ci->pvalue : 0;
-            if (ptr) {
+          void *ptr = (ci->type == SWIG_PY_POINTER) ? ci->pvalue : 0;
+          if (ptr) {
+            size_t shift = (ci->ptype) - types;
+            swig_type_info *ty = types_initial[shift];
+            size_t ldoc = (c - methods[i].ml_doc);
+            size_t lptr = strlen(ty->name)+2*sizeof(void*)+2;
+            char *ndoc = (char*)malloc(ldoc + lptr + 10);
+            if (ndoc) {
+              char *buff = ndoc;
               strncpy(buff, methods[i].ml_doc, ldoc);
               buff += ldoc;
-              strncpy(buff, "swig_ptr: ", 10);
+              memcpy(buff, "swig_ptr: ", 10);
               buff += 10;
               SWIG_PackVoidPtr(buff, ptr, ty->name, lptr);
               methods[i].ml_doc = ndoc;
@@ -3370,10 +3585,19 @@ PyObject*
 void
 #endif
 SWIG_init(void) {
-  PyObject *m, *d;  
+  PyObject *m, *d, *md;
 #if PY_VERSION_HEX >= 0x03000000
   static struct PyModuleDef SWIG_module = {
+# if PY_VERSION_HEX >= 0x03020000
     PyModuleDef_HEAD_INIT,
+# else
+    {
+      PyObject_HEAD_INIT(NULL)
+      NULL, /* m_init */
+      0,    /* m_index */
+      NULL, /* m_copy */
+    },
+# endif
     (char *) SWIG_name,
     NULL,
     -1,
@@ -3385,6 +3609,49 @@ SWIG_init(void) {
   };
 #endif
   
+#if defined(SWIGPYTHON_BUILTIN)
+  static SwigPyClientData SwigPyObject_clientdata = {
+    0, 0, 0, 0, 0, 0, 0
+  };
+  static PyGetSetDef this_getset_def = {
+    (char *)"this", &SwigPyBuiltin_ThisClosure, NULL, NULL, NULL
+  };
+  static SwigPyGetSet thisown_getset_closure = {
+    (PyCFunction) SwigPyObject_own,
+    (PyCFunction) SwigPyObject_own
+  };
+  static PyGetSetDef thisown_getset_def = {
+    (char *)"thisown", SwigPyBuiltin_GetterClosure, SwigPyBuiltin_SetterClosure, NULL, &thisown_getset_closure
+  };
+  PyObject *metatype_args;
+  PyTypeObject *builtin_pytype;
+  int builtin_base_count;
+  swig_type_info *builtin_basetype;
+  PyObject *tuple;
+  PyGetSetDescrObject *static_getset;
+  PyTypeObject *metatype;
+  SwigPyClientData *cd;
+  PyObject *public_interface, *public_symbol;
+  PyObject *this_descr;
+  PyObject *thisown_descr;
+  int i;
+  
+  (void)builtin_pytype;
+  (void)builtin_base_count;
+  (void)builtin_basetype;
+  (void)tuple;
+  (void)static_getset;
+  
+  /* metatype is used to implement static member variables. */
+  metatype_args = Py_BuildValue("(s(O){})", "SwigPyObjectType", &PyType_Type);
+  assert(metatype_args);
+  metatype = (PyTypeObject *) PyType_Type.tp_call((PyObject *) &PyType_Type, metatype_args, NULL);
+  assert(metatype);
+  Py_DECREF(metatype_args);
+  metatype->tp_setattro = (setattrofunc) &SwigPyObjectType_setattro;
+  assert(PyType_Ready(metatype) >= 0);
+#endif
+  
   /* Fix SwigMethods to carry the callback ptrs when needed */
   SWIG_Python_FixMethods(SwigMethods, swig_const_table, swig_types, swig_type_initial);
   
@@ -3393,11 +3660,48 @@ SWIG_init(void) {
 #else
   m = Py_InitModule((char *) SWIG_name, SwigMethods);
 #endif
-  d = PyModule_GetDict(m);
+  md = d = PyModule_GetDict(m);
+  (void)md;
   
   SWIG_InitializeModule(0);
-  SWIG_InstallConstants(d,swig_const_table);
   
+#ifdef SWIGPYTHON_BUILTIN
+  SwigPyObject_stype = SWIG_MangledTypeQuery("_p_SwigPyObject");
+  assert(SwigPyObject_stype);
+  cd = (SwigPyClientData*) SwigPyObject_stype->clientdata;
+  if (!cd) {
+    SwigPyObject_stype->clientdata = &SwigPyObject_clientdata;
+    SwigPyObject_clientdata.pytype = SwigPyObject_TypeOnce();
+  } else if (SwigPyObject_TypeOnce()->tp_basicsize != cd->pytype->tp_basicsize) {
+    PyErr_SetString(PyExc_RuntimeError, "Import error: attempted to load two incompatible swig-generated modules.");
+# if PY_VERSION_HEX >= 0x03000000
+    return NULL;
+# else
+    return;
+# endif
+  }
+  
+  /* All objects have a 'this' attribute */
+  this_descr = PyDescr_NewGetSet(SwigPyObject_type(), &this_getset_def);
+  (void)this_descr;
+  
+  /* All objects have a 'thisown' attribute */
+  thisown_descr = PyDescr_NewGetSet(SwigPyObject_type(), &thisown_getset_def);
+  (void)thisown_descr;
+  
+  public_interface = PyList_New(0);
+  public_symbol = 0;
+  (void)public_symbol;
+  
+  PyDict_SetItemString(md, "__all__", public_interface);
+  Py_DECREF(public_interface);
+  for (i = 0; SwigMethods[i].ml_name != NULL; ++i)
+  SwigPyBuiltin_AddPublicSymbol(public_interface, SwigMethods[i].ml_name);
+  for (i = 0; swig_const_table[i].name != 0; ++i)
+  SwigPyBuiltin_AddPublicSymbol(public_interface, swig_const_table[i].name);
+#endif
+  
+  SWIG_InstallConstants(d,swig_const_table);
   
   SWIG_Python_SetConstant(d, "GDT_Unknown",SWIG_From_int((int)(GDT_Unknown)));
   SWIG_Python_SetConstant(d, "GDT_Byte",SWIG_From_int((int)(GDT_Byte)));
@@ -3475,6 +3779,7 @@ SWIG_init(void) {
   SWIG_Python_SetConstant(d, "OF_ALL",SWIG_From_int((int)(GDAL_OF_ALL)));
   SWIG_Python_SetConstant(d, "OF_RASTER",SWIG_From_int((int)(GDAL_OF_RASTER)));
   SWIG_Python_SetConstant(d, "OF_VECTOR",SWIG_From_int((int)(GDAL_OF_VECTOR)));
+  SWIG_Python_SetConstant(d, "OF_GNM",SWIG_From_int((int)(GDAL_OF_GNM)));
   SWIG_Python_SetConstant(d, "OF_READONLY",SWIG_From_int((int)(GDAL_OF_READONLY)));
   SWIG_Python_SetConstant(d, "OF_UPDATE",SWIG_From_int((int)(GDAL_OF_UPDATE)));
   SWIG_Python_SetConstant(d, "OF_SHARED",SWIG_From_int((int)(GDAL_OF_SHARED)));
diff --git a/swig/python/extensions/gnm_wrap.cpp b/swig/python/extensions/gnm_wrap.cpp
new file mode 100644
index 0000000..c482d1d
--- /dev/null
+++ b/swig/python/extensions/gnm_wrap.cpp
@@ -0,0 +1,7237 @@
+/* ----------------------------------------------------------------------------
+ * This file was automatically generated by SWIG (http://www.swig.org).
+ * Version 2.0.12
+ *
+ * This file is not intended to be easily readable and contains a number of
+ * coding conventions designed to improve portability and efficiency. Do not make
+ * changes to this file unless you know what you are doing--modify the SWIG
+ * interface file instead.
+ * ----------------------------------------------------------------------------- */
+
+#define SWIGPYTHON
+#define SED_HACKS
+#define SWIG_PYTHON_DIRECTOR_NO_VTABLE
+
+
+#ifdef __cplusplus
+/* SwigValueWrapper is described in swig.swg */
+template<typename T> class SwigValueWrapper {
+  struct SwigMovePointer {
+    T *ptr;
+    SwigMovePointer(T *p) : ptr(p) { }
+    ~SwigMovePointer() { delete ptr; }
+    SwigMovePointer& operator=(SwigMovePointer& rhs) { T* oldptr = ptr; ptr = 0; delete oldptr; ptr = rhs.ptr; rhs.ptr = 0; return *this; }
+  } pointer;
+  SwigValueWrapper& operator=(const SwigValueWrapper<T>& rhs);
+  SwigValueWrapper(const SwigValueWrapper<T>& rhs);
+public:
+  SwigValueWrapper() : pointer(0) { }
+  SwigValueWrapper& operator=(const T& t) { SwigMovePointer tmp(new T(t)); pointer = tmp; return *this; }
+  operator T&() const { return *pointer.ptr; }
+  T *operator&() { return pointer.ptr; }
+};
+
+template <typename T> T SwigValueInit() {
+  return T();
+}
+#endif
+
+/* -----------------------------------------------------------------------------
+ *  This section contains generic SWIG labels for method/variable
+ *  declarations/attributes, and other compiler dependent labels.
+ * ----------------------------------------------------------------------------- */
+
+/* template workaround for compilers that cannot correctly implement the C++ standard */
+#ifndef SWIGTEMPLATEDISAMBIGUATOR
+# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560)
+#  define SWIGTEMPLATEDISAMBIGUATOR template
+# elif defined(__HP_aCC)
+/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */
+/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */
+#  define SWIGTEMPLATEDISAMBIGUATOR template
+# else
+#  define SWIGTEMPLATEDISAMBIGUATOR
+# endif
+#endif
+
+/* inline attribute */
+#ifndef SWIGINLINE
+# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__))
+#   define SWIGINLINE inline
+# else
+#   define SWIGINLINE
+# endif
+#endif
+
+/* attribute recognised by some compilers to avoid 'unused' warnings */
+#ifndef SWIGUNUSED
+# if defined(__GNUC__)
+#   if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
+#     define SWIGUNUSED __attribute__ ((__unused__))
+#   else
+#     define SWIGUNUSED
+#   endif
+# elif defined(__ICC)
+#   define SWIGUNUSED __attribute__ ((__unused__))
+# else
+#   define SWIGUNUSED
+# endif
+#endif
+
+#ifndef SWIG_MSC_UNSUPPRESS_4505
+# if defined(_MSC_VER)
+#   pragma warning(disable : 4505) /* unreferenced local function has been removed */
+# endif
+#endif
+
+#ifndef SWIGUNUSEDPARM
+# ifdef __cplusplus
+#   define SWIGUNUSEDPARM(p)
+# else
+#   define SWIGUNUSEDPARM(p) p SWIGUNUSED
+# endif
+#endif
+
+/* internal SWIG method */
+#ifndef SWIGINTERN
+# define SWIGINTERN static SWIGUNUSED
+#endif
+
+/* internal inline SWIG method */
+#ifndef SWIGINTERNINLINE
+# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE
+#endif
+
+/* exporting methods */
+#if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+#  ifndef GCC_HASCLASSVISIBILITY
+#    define GCC_HASCLASSVISIBILITY
+#  endif
+#endif
+
+#ifndef SWIGEXPORT
+# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+#   if defined(STATIC_LINKED)
+#     define SWIGEXPORT
+#   else
+#     define SWIGEXPORT __declspec(dllexport)
+#   endif
+# else
+#   if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY)
+#     define SWIGEXPORT __attribute__ ((visibility("default")))
+#   else
+#     define SWIGEXPORT
+#   endif
+# endif
+#endif
+
+/* calling conventions for Windows */
+#ifndef SWIGSTDCALL
+# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+#   define SWIGSTDCALL __stdcall
+# else
+#   define SWIGSTDCALL
+# endif
+#endif
+
+/* Deal with Microsoft's attempt at deprecating C standard runtime functions */
+#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
+# define _CRT_SECURE_NO_DEPRECATE
+#endif
+
+/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */
+#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE)
+# define _SCL_SECURE_NO_DEPRECATE
+#endif
+
+
+
+#if defined(_DEBUG) && defined(SWIG_PYTHON_INTERPRETER_NO_DEBUG)
+/* Use debug wrappers with the Python release dll */
+# undef _DEBUG
+# include <Python.h>
+# define _DEBUG
+#else
+# include <Python.h>
+#endif
+
+/* -----------------------------------------------------------------------------
+ * swigrun.swg
+ *
+ * This file contains generic C API SWIG runtime support for pointer
+ * type checking.
+ * ----------------------------------------------------------------------------- */
+
+/* This should only be incremented when either the layout of swig_type_info changes,
+   or for whatever reason, the runtime changes incompatibly */
+#define SWIG_RUNTIME_VERSION "4"
+
+/* define SWIG_TYPE_TABLE_NAME as "SWIG_TYPE_TABLE" */
+#ifdef SWIG_TYPE_TABLE
+# define SWIG_QUOTE_STRING(x) #x
+# define SWIG_EXPAND_AND_QUOTE_STRING(x) SWIG_QUOTE_STRING(x)
+# define SWIG_TYPE_TABLE_NAME SWIG_EXPAND_AND_QUOTE_STRING(SWIG_TYPE_TABLE)
+#else
+# define SWIG_TYPE_TABLE_NAME
+#endif
+
+/*
+  You can use the SWIGRUNTIME and SWIGRUNTIMEINLINE macros for
+  creating a static or dynamic library from the SWIG runtime code.
+  In 99.9% of the cases, SWIG just needs to declare them as 'static'.
+
+  But only do this if strictly necessary, ie, if you have problems
+  with your compiler or suchlike.
+*/
+
+#ifndef SWIGRUNTIME
+# define SWIGRUNTIME SWIGINTERN
+#endif
+
+#ifndef SWIGRUNTIMEINLINE
+# define SWIGRUNTIMEINLINE SWIGRUNTIME SWIGINLINE
+#endif
+
+/*  Generic buffer size */
+#ifndef SWIG_BUFFER_SIZE
+# define SWIG_BUFFER_SIZE 1024
+#endif
+
+/* Flags for pointer conversions */
+#define SWIG_POINTER_DISOWN        0x1
+#define SWIG_CAST_NEW_MEMORY       0x2
+
+/* Flags for new pointer objects */
+#define SWIG_POINTER_OWN           0x1
+
+
+/*
+   Flags/methods for returning states.
+
+   The SWIG conversion methods, as ConvertPtr, return an integer
+   that tells if the conversion was successful or not. And if not,
+   an error code can be returned (see swigerrors.swg for the codes).
+
+   Use the following macros/flags to set or process the returning
+   states.
+
+   In old versions of SWIG, code such as the following was usually written:
+
+     if (SWIG_ConvertPtr(obj,vptr,ty.flags) != -1) {
+       // success code
+     } else {
+       //fail code
+     }
+
+   Now you can be more explicit:
+
+    int res = SWIG_ConvertPtr(obj,vptr,ty.flags);
+    if (SWIG_IsOK(res)) {
+      // success code
+    } else {
+      // fail code
+    }
+
+   which is the same really, but now you can also do
+
+    Type *ptr;
+    int res = SWIG_ConvertPtr(obj,(void **)(&ptr),ty.flags);
+    if (SWIG_IsOK(res)) {
+      // success code
+      if (SWIG_IsNewObj(res) {
+        ...
+	delete *ptr;
+      } else {
+        ...
+      }
+    } else {
+      // fail code
+    }
+
+   I.e., now SWIG_ConvertPtr can return new objects and you can
+   identify the case and take care of the deallocation. Of course that
+   also requires SWIG_ConvertPtr to return new result values, such as
+
+      int SWIG_ConvertPtr(obj, ptr,...) {
+        if (<obj is ok>) {
+          if (<need new object>) {
+            *ptr = <ptr to new allocated object>;
+            return SWIG_NEWOBJ;
+          } else {
+            *ptr = <ptr to old object>;
+            return SWIG_OLDOBJ;
+          }
+        } else {
+          return SWIG_BADOBJ;
+        }
+      }
+
+   Of course, returning the plain '0(success)/-1(fail)' still works, but you can be
+   more explicit by returning SWIG_BADOBJ, SWIG_ERROR or any of the
+   SWIG errors code.
+
+   Finally, if the SWIG_CASTRANK_MODE is enabled, the result code
+   allows to return the 'cast rank', for example, if you have this
+
+       int food(double)
+       int fooi(int);
+
+   and you call
+
+      food(1)   // cast rank '1'  (1 -> 1.0)
+      fooi(1)   // cast rank '0'
+
+   just use the SWIG_AddCast()/SWIG_CheckState()
+*/
+
+#define SWIG_OK                    (0)
+#define SWIG_ERROR                 (-1)
+#define SWIG_IsOK(r)               (r >= 0)
+#define SWIG_ArgError(r)           ((r != SWIG_ERROR) ? r : SWIG_TypeError)
+
+/* The CastRankLimit says how many bits are used for the cast rank */
+#define SWIG_CASTRANKLIMIT         (1 << 8)
+/* The NewMask denotes the object was created (using new/malloc) */
+#define SWIG_NEWOBJMASK            (SWIG_CASTRANKLIMIT  << 1)
+/* The TmpMask is for in/out typemaps that use temporal objects */
+#define SWIG_TMPOBJMASK            (SWIG_NEWOBJMASK << 1)
+/* Simple returning values */
+#define SWIG_BADOBJ                (SWIG_ERROR)
+#define SWIG_OLDOBJ                (SWIG_OK)
+#define SWIG_NEWOBJ                (SWIG_OK | SWIG_NEWOBJMASK)
+#define SWIG_TMPOBJ                (SWIG_OK | SWIG_TMPOBJMASK)
+/* Check, add and del mask methods */
+#define SWIG_AddNewMask(r)         (SWIG_IsOK(r) ? (r | SWIG_NEWOBJMASK) : r)
+#define SWIG_DelNewMask(r)         (SWIG_IsOK(r) ? (r & ~SWIG_NEWOBJMASK) : r)
+#define SWIG_IsNewObj(r)           (SWIG_IsOK(r) && (r & SWIG_NEWOBJMASK))
+#define SWIG_AddTmpMask(r)         (SWIG_IsOK(r) ? (r | SWIG_TMPOBJMASK) : r)
+#define SWIG_DelTmpMask(r)         (SWIG_IsOK(r) ? (r & ~SWIG_TMPOBJMASK) : r)
+#define SWIG_IsTmpObj(r)           (SWIG_IsOK(r) && (r & SWIG_TMPOBJMASK))
+
+/* Cast-Rank Mode */
+#if defined(SWIG_CASTRANK_MODE)
+#  ifndef SWIG_TypeRank
+#    define SWIG_TypeRank             unsigned long
+#  endif
+#  ifndef SWIG_MAXCASTRANK            /* Default cast allowed */
+#    define SWIG_MAXCASTRANK          (2)
+#  endif
+#  define SWIG_CASTRANKMASK          ((SWIG_CASTRANKLIMIT) -1)
+#  define SWIG_CastRank(r)           (r & SWIG_CASTRANKMASK)
+SWIGINTERNINLINE int SWIG_AddCast(int r) {
+  return SWIG_IsOK(r) ? ((SWIG_CastRank(r) < SWIG_MAXCASTRANK) ? (r + 1) : SWIG_ERROR) : r;
+}
+SWIGINTERNINLINE int SWIG_CheckState(int r) {
+  return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0;
+}
+#else /* no cast-rank mode */
+#  define SWIG_AddCast(r) (r)
+#  define SWIG_CheckState(r) (SWIG_IsOK(r) ? 1 : 0)
+#endif
+
+
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void *(*swig_converter_func)(void *, int *);
+typedef struct swig_type_info *(*swig_dycast_func)(void **);
+
+/* Structure to store information on one type */
+typedef struct swig_type_info {
+  const char             *name;			/* mangled name of this type */
+  const char             *str;			/* human readable name of this type */
+  swig_dycast_func        dcast;		/* dynamic cast function down a hierarchy */
+  struct swig_cast_info  *cast;			/* linked list of types that can cast into this type */
+  void                   *clientdata;		/* language specific type data */
+  int                    owndata;		/* flag if the structure owns the clientdata */
+} swig_type_info;
+
+/* Structure to store a type and conversion function used for casting */
+typedef struct swig_cast_info {
+  swig_type_info         *type;			/* pointer to type that is equivalent to this type */
+  swig_converter_func     converter;		/* function to cast the void pointers */
+  struct swig_cast_info  *next;			/* pointer to next cast in linked list */
+  struct swig_cast_info  *prev;			/* pointer to the previous cast */
+} swig_cast_info;
+
+/* Structure used to store module information
+ * Each module generates one structure like this, and the runtime collects
+ * all of these structures and stores them in a circularly linked list.*/
+typedef struct swig_module_info {
+  swig_type_info         **types;		/* Array of pointers to swig_type_info structures that are in this module */
+  size_t                 size;		        /* Number of types in this module */
+  struct swig_module_info *next;		/* Pointer to next element in circularly linked list */
+  swig_type_info         **type_initial;	/* Array of initially generated type structures */
+  swig_cast_info         **cast_initial;	/* Array of initially generated casting structures */
+  void                    *clientdata;		/* Language specific module data */
+} swig_module_info;
+
+/*
+  Compare two type names skipping the space characters, therefore
+  "char*" == "char *" and "Class<int>" == "Class<int >", etc.
+
+  Return 0 when the two name types are equivalent, as in
+  strncmp, but skipping ' '.
+*/
+SWIGRUNTIME int
+SWIG_TypeNameComp(const char *f1, const char *l1,
+		  const char *f2, const char *l2) {
+  for (;(f1 != l1) && (f2 != l2); ++f1, ++f2) {
+    while ((*f1 == ' ') && (f1 != l1)) ++f1;
+    while ((*f2 == ' ') && (f2 != l2)) ++f2;
+    if (*f1 != *f2) return (*f1 > *f2) ? 1 : -1;
+  }
+  return (int)((l1 - f1) - (l2 - f2));
+}
+
+/*
+  Check type equivalence in a name list like <name1>|<name2>|...
+  Return 0 if equal, -1 if nb < tb, 1 if nb > tb
+*/
+SWIGRUNTIME int
+SWIG_TypeCmp(const char *nb, const char *tb) {
+  int equiv = 1;
+  const char* te = tb + strlen(tb);
+  const char* ne = nb;
+  while (equiv != 0 && *ne) {
+    for (nb = ne; *ne; ++ne) {
+      if (*ne == '|') break;
+    }
+    equiv = SWIG_TypeNameComp(nb, ne, tb, te);
+    if (*ne) ++ne;
+  }
+  return equiv;
+}
+
+/*
+  Check type equivalence in a name list like <name1>|<name2>|...
+  Return 0 if not equal, 1 if equal
+*/
+SWIGRUNTIME int
+SWIG_TypeEquiv(const char *nb, const char *tb) {
+  return SWIG_TypeCmp(nb, tb) == 0 ? 1 : 0;
+}
+
+/*
+  Check the typename
+*/
+SWIGRUNTIME swig_cast_info *
+SWIG_TypeCheck(const char *c, swig_type_info *ty) {
+  if (ty) {
+    swig_cast_info *iter = ty->cast;
+    while (iter) {
+      if (strcmp(iter->type->name, c) == 0) {
+        if (iter == ty->cast)
+          return iter;
+        /* Move iter to the top of the linked list */
+        iter->prev->next = iter->next;
+        if (iter->next)
+          iter->next->prev = iter->prev;
+        iter->next = ty->cast;
+        iter->prev = 0;
+        if (ty->cast) ty->cast->prev = iter;
+        ty->cast = iter;
+        return iter;
+      }
+      iter = iter->next;
+    }
+  }
+  return 0;
+}
+
+/*
+  Identical to SWIG_TypeCheck, except strcmp is replaced with a pointer comparison
+*/
+SWIGRUNTIME swig_cast_info *
+SWIG_TypeCheckStruct(swig_type_info *from, swig_type_info *ty) {
+  if (ty) {
+    swig_cast_info *iter = ty->cast;
+    while (iter) {
+      if (iter->type == from) {
+        if (iter == ty->cast)
+          return iter;
+        /* Move iter to the top of the linked list */
+        iter->prev->next = iter->next;
+        if (iter->next)
+          iter->next->prev = iter->prev;
+        iter->next = ty->cast;
+        iter->prev = 0;
+        if (ty->cast) ty->cast->prev = iter;
+        ty->cast = iter;
+        return iter;
+      }
+      iter = iter->next;
+    }
+  }
+  return 0;
+}
+
+/*
+  Cast a pointer up an inheritance hierarchy
+*/
+SWIGRUNTIMEINLINE void *
+SWIG_TypeCast(swig_cast_info *ty, void *ptr, int *newmemory) {
+  return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr, newmemory);
+}
+
+/*
+   Dynamic pointer casting. Down an inheritance hierarchy
+*/
+SWIGRUNTIME swig_type_info *
+SWIG_TypeDynamicCast(swig_type_info *ty, void **ptr) {
+  swig_type_info *lastty = ty;
+  if (!ty || !ty->dcast) return ty;
+  while (ty && (ty->dcast)) {
+    ty = (*ty->dcast)(ptr);
+    if (ty) lastty = ty;
+  }
+  return lastty;
+}
+
+/*
+  Return the name associated with this type
+*/
+SWIGRUNTIMEINLINE const char *
+SWIG_TypeName(const swig_type_info *ty) {
+  return ty->name;
+}
+
+/*
+  Return the pretty name associated with this type,
+  that is an unmangled type name in a form presentable to the user.
+*/
+SWIGRUNTIME const char *
+SWIG_TypePrettyName(const swig_type_info *type) {
+  /* The "str" field contains the equivalent pretty names of the
+     type, separated by vertical-bar characters.  We choose
+     to print the last name, as it is often (?) the most
+     specific. */
+  if (!type) return NULL;
+  if (type->str != NULL) {
+    const char *last_name = type->str;
+    const char *s;
+    for (s = type->str; *s; s++)
+      if (*s == '|') last_name = s+1;
+    return last_name;
+  }
+  else
+    return type->name;
+}
+
+/*
+   Set the clientdata field for a type
+*/
+SWIGRUNTIME void
+SWIG_TypeClientData(swig_type_info *ti, void *clientdata) {
+  swig_cast_info *cast = ti->cast;
+  /* if (ti->clientdata == clientdata) return; */
+  ti->clientdata = clientdata;
+
+  while (cast) {
+    if (!cast->converter) {
+      swig_type_info *tc = cast->type;
+      if (!tc->clientdata) {
+	SWIG_TypeClientData(tc, clientdata);
+      }
+    }
+    cast = cast->next;
+  }
+}
+SWIGRUNTIME void
+SWIG_TypeNewClientData(swig_type_info *ti, void *clientdata) {
+  SWIG_TypeClientData(ti, clientdata);
+  ti->owndata = 1;
+}
+
+/*
+  Search for a swig_type_info structure only by mangled name
+  Search is a O(log #types)
+
+  We start searching at module start, and finish searching when start == end.
+  Note: if start == end at the beginning of the function, we go all the way around
+  the circular list.
+*/
+SWIGRUNTIME swig_type_info *
+SWIG_MangledTypeQueryModule(swig_module_info *start,
+                            swig_module_info *end,
+		            const char *name) {
+  swig_module_info *iter = start;
+  do {
+    if (iter->size) {
+      register size_t l = 0;
+      register size_t r = iter->size - 1;
+      do {
+	/* since l+r >= 0, we can (>> 1) instead (/ 2) */
+	register size_t i = (l + r) >> 1;
+	const char *iname = iter->types[i]->name;
+	if (iname) {
+	  register int compare = strcmp(name, iname);
+	  if (compare == 0) {
+	    return iter->types[i];
+	  } else if (compare < 0) {
+	    if (i) {
+	      r = i - 1;
+	    } else {
+	      break;
+	    }
+	  } else if (compare > 0) {
+	    l = i + 1;
+	  }
+	} else {
+	  break; /* should never happen */
+	}
+      } while (l <= r);
+    }
+    iter = iter->next;
+  } while (iter != end);
+  return 0;
+}
+
+/*
+  Search for a swig_type_info structure for either a mangled name or a human readable name.
+  It first searches the mangled names of the types, which is a O(log #types)
+  If a type is not found it then searches the human readable names, which is O(#types).
+
+  We start searching at module start, and finish searching when start == end.
+  Note: if start == end at the beginning of the function, we go all the way around
+  the circular list.
+*/
+SWIGRUNTIME swig_type_info *
+SWIG_TypeQueryModule(swig_module_info *start,
+                     swig_module_info *end,
+		     const char *name) {
+  /* STEP 1: Search the name field using binary search */
+  swig_type_info *ret = SWIG_MangledTypeQueryModule(start, end, name);
+  if (ret) {
+    return ret;
+  } else {
+    /* STEP 2: If the type hasn't been found, do a complete search
+       of the str field (the human readable name) */
+    swig_module_info *iter = start;
+    do {
+      register size_t i = 0;
+      for (; i < iter->size; ++i) {
+	if (iter->types[i]->str && (SWIG_TypeEquiv(iter->types[i]->str, name)))
+	  return iter->types[i];
+      }
+      iter = iter->next;
+    } while (iter != end);
+  }
+
+  /* neither found a match */
+  return 0;
+}
+
+/*
+   Pack binary data into a string
+*/
+SWIGRUNTIME char *
+SWIG_PackData(char *c, void *ptr, size_t sz) {
+  static const char hex[17] = "0123456789abcdef";
+  register const unsigned char *u = (unsigned char *) ptr;
+  register const unsigned char *eu =  u + sz;
+  for (; u != eu; ++u) {
+    register unsigned char uu = *u;
+    *(c++) = hex[(uu & 0xf0) >> 4];
+    *(c++) = hex[uu & 0xf];
+  }
+  return c;
+}
+
+/*
+   Unpack binary data from a string
+*/
+SWIGRUNTIME const char *
+SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
+  register unsigned char *u = (unsigned char *) ptr;
+  register const unsigned char *eu = u + sz;
+  for (; u != eu; ++u) {
+    register char d = *(c++);
+    register unsigned char uu;
+    if ((d >= '0') && (d <= '9'))
+      uu = ((d - '0') << 4);
+    else if ((d >= 'a') && (d <= 'f'))
+      uu = ((d - ('a'-10)) << 4);
+    else
+      return (char *) 0;
+    d = *(c++);
+    if ((d >= '0') && (d <= '9'))
+      uu |= (d - '0');
+    else if ((d >= 'a') && (d <= 'f'))
+      uu |= (d - ('a'-10));
+    else
+      return (char *) 0;
+    *u = uu;
+  }
+  return c;
+}
+
+/*
+   Pack 'void *' into a string buffer.
+*/
+SWIGRUNTIME char *
+SWIG_PackVoidPtr(char *buff, void *ptr, const char *name, size_t bsz) {
+  char *r = buff;
+  if ((2*sizeof(void *) + 2) > bsz) return 0;
+  *(r++) = '_';
+  r = SWIG_PackData(r,&ptr,sizeof(void *));
+  if (strlen(name) + 1 > (bsz - (r - buff))) return 0;
+  strcpy(r,name);
+  return buff;
+}
+
+SWIGRUNTIME const char *
+SWIG_UnpackVoidPtr(const char *c, void **ptr, const char *name) {
+  if (*c != '_') {
+    if (strcmp(c,"NULL") == 0) {
+      *ptr = (void *) 0;
+      return name;
+    } else {
+      return 0;
+    }
+  }
+  return SWIG_UnpackData(++c,ptr,sizeof(void *));
+}
+
+SWIGRUNTIME char *
+SWIG_PackDataName(char *buff, void *ptr, size_t sz, const char *name, size_t bsz) {
+  char *r = buff;
+  size_t lname = (name ? strlen(name) : 0);
+  if ((2*sz + 2 + lname) > bsz) return 0;
+  *(r++) = '_';
+  r = SWIG_PackData(r,ptr,sz);
+  if (lname) {
+    strncpy(r,name,lname+1);
+  } else {
+    *r = 0;
+  }
+  return buff;
+}
+
+SWIGRUNTIME const char *
+SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) {
+  if (*c != '_') {
+    if (strcmp(c,"NULL") == 0) {
+      memset(ptr,0,sz);
+      return name;
+    } else {
+      return 0;
+    }
+  }
+  return SWIG_UnpackData(++c,ptr,sz);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+/*  Errors in SWIG */
+#define  SWIG_UnknownError    	   -1
+#define  SWIG_IOError        	   -2
+#define  SWIG_RuntimeError   	   -3
+#define  SWIG_IndexError     	   -4
+#define  SWIG_TypeError      	   -5
+#define  SWIG_DivisionByZero 	   -6
+#define  SWIG_OverflowError  	   -7
+#define  SWIG_SyntaxError    	   -8
+#define  SWIG_ValueError     	   -9
+#define  SWIG_SystemError    	   -10
+#define  SWIG_AttributeError 	   -11
+#define  SWIG_MemoryError    	   -12
+#define  SWIG_NullReferenceError   -13
+
+
+
+/* Compatibility macros for Python 3 */
+#if PY_VERSION_HEX >= 0x03000000
+
+#define PyClass_Check(obj) PyObject_IsInstance(obj, (PyObject *)&PyType_Type)
+#define PyInt_Check(x) PyLong_Check(x)
+#define PyInt_AsLong(x) PyLong_AsLong(x)
+#define PyInt_FromLong(x) PyLong_FromLong(x)
+#define PyInt_FromSize_t(x) PyLong_FromSize_t(x)
+#define PyString_Check(name) PyBytes_Check(name)
+#define PyString_FromString(x) PyUnicode_FromString(x)
+#define PyString_Format(fmt, args)  PyUnicode_Format(fmt, args)
+#define PyString_AsString(str) PyBytes_AsString(str)
+#define PyString_Size(str) PyBytes_Size(str)	
+#define PyString_InternFromString(key) PyUnicode_InternFromString(key)
+#define Py_TPFLAGS_HAVE_CLASS Py_TPFLAGS_BASETYPE
+#define PyString_AS_STRING(x) PyUnicode_AS_STRING(x)
+#define _PyLong_FromSsize_t(x) PyLong_FromSsize_t(x)
+
+#endif
+
+#ifndef Py_TYPE
+#  define Py_TYPE(op) ((op)->ob_type)
+#endif
+
+/* SWIG APIs for compatibility of both Python 2 & 3 */
+
+#if PY_VERSION_HEX >= 0x03000000
+#  define SWIG_Python_str_FromFormat PyUnicode_FromFormat
+#else
+#  define SWIG_Python_str_FromFormat PyString_FromFormat
+#endif
+
+
+/* Warning: This function will allocate a new string in Python 3,
+ * so please call SWIG_Python_str_DelForPy3(x) to free the space.
+ */
+SWIGINTERN char*
+SWIG_Python_str_AsChar(PyObject *str)
+{
+#if PY_VERSION_HEX >= 0x03000000
+  char *cstr;
+  char *newstr;
+  Py_ssize_t len;
+  str = PyUnicode_AsUTF8String(str);
+  PyBytes_AsStringAndSize(str, &cstr, &len);
+  newstr = (char *) malloc(len+1);
+  memcpy(newstr, cstr, len+1);
+  Py_XDECREF(str);
+  return newstr;
+#else
+  return PyString_AsString(str);
+#endif
+}
+
+#if PY_VERSION_HEX >= 0x03000000
+#  define SWIG_Python_str_DelForPy3(x) free( (void*) (x) )
+#else
+#  define SWIG_Python_str_DelForPy3(x) 
+#endif
+
+
+SWIGINTERN PyObject*
+SWIG_Python_str_FromChar(const char *c)
+{
+#if PY_VERSION_HEX >= 0x03000000
+  return PyUnicode_FromString(c); 
+#else
+  return PyString_FromString(c);
+#endif
+}
+
+/* Add PyOS_snprintf for old Pythons */
+#if PY_VERSION_HEX < 0x02020000
+# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(_WATCOM)
+#  define PyOS_snprintf _snprintf
+# else
+#  define PyOS_snprintf snprintf
+# endif
+#endif
+
+/* A crude PyString_FromFormat implementation for old Pythons */
+#if PY_VERSION_HEX < 0x02020000
+
+#ifndef SWIG_PYBUFFER_SIZE
+# define SWIG_PYBUFFER_SIZE 1024
+#endif
+
+static PyObject *
+PyString_FromFormat(const char *fmt, ...) {
+  va_list ap;
+  char buf[SWIG_PYBUFFER_SIZE * 2];
+  int res;
+  va_start(ap, fmt);
+  res = vsnprintf(buf, sizeof(buf), fmt, ap);
+  va_end(ap);
+  return (res < 0 || res >= (int)sizeof(buf)) ? 0 : PyString_FromString(buf);
+}
+#endif
+
+/* Add PyObject_Del for old Pythons */
+#if PY_VERSION_HEX < 0x01060000
+# define PyObject_Del(op) PyMem_DEL((op))
+#endif
+#ifndef PyObject_DEL
+# define PyObject_DEL PyObject_Del
+#endif
+
+/* A crude PyExc_StopIteration exception for old Pythons */
+#if PY_VERSION_HEX < 0x02020000
+# ifndef PyExc_StopIteration
+#  define PyExc_StopIteration PyExc_RuntimeError
+# endif
+# ifndef PyObject_GenericGetAttr
+#  define PyObject_GenericGetAttr 0
+# endif
+#endif
+
+/* Py_NotImplemented is defined in 2.1 and up. */
+#if PY_VERSION_HEX < 0x02010000
+# ifndef Py_NotImplemented
+#  define Py_NotImplemented PyExc_RuntimeError
+# endif
+#endif
+
+/* A crude PyString_AsStringAndSize implementation for old Pythons */
+#if PY_VERSION_HEX < 0x02010000
+# ifndef PyString_AsStringAndSize
+#  define PyString_AsStringAndSize(obj, s, len) {*s = PyString_AsString(obj); *len = *s ? strlen(*s) : 0;}
+# endif
+#endif
+
+/* PySequence_Size for old Pythons */
+#if PY_VERSION_HEX < 0x02000000
+# ifndef PySequence_Size
+#  define PySequence_Size PySequence_Length
+# endif
+#endif
+
+/* PyBool_FromLong for old Pythons */
+#if PY_VERSION_HEX < 0x02030000
+static
+PyObject *PyBool_FromLong(long ok)
+{
+  PyObject *result = ok ? Py_True : Py_False;
+  Py_INCREF(result);
+  return result;
+}
+#endif
+
+/* Py_ssize_t for old Pythons */
+/* This code is as recommended by: */
+/* http://www.python.org/dev/peps/pep-0353/#conversion-guidelines */
+#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
+typedef int Py_ssize_t;
+# define PY_SSIZE_T_MAX INT_MAX
+# define PY_SSIZE_T_MIN INT_MIN
+typedef inquiry lenfunc;
+typedef intargfunc ssizeargfunc;
+typedef intintargfunc ssizessizeargfunc;
+typedef intobjargproc ssizeobjargproc;
+typedef intintobjargproc ssizessizeobjargproc;
+typedef getreadbufferproc readbufferproc;
+typedef getwritebufferproc writebufferproc;
+typedef getsegcountproc segcountproc;
+typedef getcharbufferproc charbufferproc;
+static long PyNumber_AsSsize_t (PyObject *x, void *SWIGUNUSEDPARM(exc))
+{
+  long result = 0;
+  PyObject *i = PyNumber_Int(x);
+  if (i) {
+    result = PyInt_AsLong(i);
+    Py_DECREF(i);
+  }
+  return result;
+}
+#endif
+
+#if PY_VERSION_HEX < 0x02050000
+#define PyInt_FromSize_t(x) PyInt_FromLong((long)x)
+#endif
+
+#if PY_VERSION_HEX < 0x02040000
+#define Py_VISIT(op)				\
+  do { 						\
+    if (op) {					\
+      int vret = visit((op), arg);		\
+      if (vret)					\
+        return vret;				\
+    }						\
+  } while (0)
+#endif
+
+#if PY_VERSION_HEX < 0x02030000
+typedef struct {
+  PyTypeObject type;
+  PyNumberMethods as_number;
+  PyMappingMethods as_mapping;
+  PySequenceMethods as_sequence;
+  PyBufferProcs as_buffer;
+  PyObject *name, *slots;
+} PyHeapTypeObject;
+#endif
+
+#if PY_VERSION_HEX < 0x02030000
+typedef destructor freefunc;
+#endif
+
+#if ((PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 6) || \
+     (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION > 0) || \
+     (PY_MAJOR_VERSION > 3))
+# define SWIGPY_USE_CAPSULE
+# define SWIGPY_CAPSULE_NAME ((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer_capsule" SWIG_TYPE_TABLE_NAME)
+#endif
+
+#if PY_VERSION_HEX < 0x03020000
+#define PyDescr_TYPE(x) (((PyDescrObject *)(x))->d_type)
+#define PyDescr_NAME(x) (((PyDescrObject *)(x))->d_name)
+#endif
+
+/* -----------------------------------------------------------------------------
+ * error manipulation
+ * ----------------------------------------------------------------------------- */
+
+SWIGRUNTIME PyObject*
+SWIG_Python_ErrorType(int code) {
+  PyObject* type = 0;
+  switch(code) {
+  case SWIG_MemoryError:
+    type = PyExc_MemoryError;
+    break;
+  case SWIG_IOError:
+    type = PyExc_IOError;
+    break;
+  case SWIG_RuntimeError:
+    type = PyExc_RuntimeError;
+    break;
+  case SWIG_IndexError:
+    type = PyExc_IndexError;
+    break;
+  case SWIG_TypeError:
+    type = PyExc_TypeError;
+    break;
+  case SWIG_DivisionByZero:
+    type = PyExc_ZeroDivisionError;
+    break;
+  case SWIG_OverflowError:
+    type = PyExc_OverflowError;
+    break;
+  case SWIG_SyntaxError:
+    type = PyExc_SyntaxError;
+    break;
+  case SWIG_ValueError:
+    type = PyExc_ValueError;
+    break;
+  case SWIG_SystemError:
+    type = PyExc_SystemError;
+    break;
+  case SWIG_AttributeError:
+    type = PyExc_AttributeError;
+    break;
+  default:
+    type = PyExc_RuntimeError;
+  }
+  return type;
+}
+
+
+SWIGRUNTIME void
+SWIG_Python_AddErrorMsg(const char* mesg)
+{
+  PyObject *type = 0;
+  PyObject *value = 0;
+  PyObject *traceback = 0;
+
+  if (PyErr_Occurred()) PyErr_Fetch(&type, &value, &traceback);
+  if (value) {
+    char *tmp;
+    PyObject *old_str = PyObject_Str(value);
+    PyErr_Clear();
+    Py_XINCREF(type);
+
+    PyErr_Format(type, "%s %s", tmp = SWIG_Python_str_AsChar(old_str), mesg);
+    SWIG_Python_str_DelForPy3(tmp);
+    Py_DECREF(old_str);
+    Py_DECREF(value);
+  } else {
+    PyErr_SetString(PyExc_RuntimeError, mesg);
+  }
+}
+
+#if defined(SWIG_PYTHON_NO_THREADS)
+#  if defined(SWIG_PYTHON_THREADS)
+#    undef SWIG_PYTHON_THREADS
+#  endif
+#endif
+#if defined(SWIG_PYTHON_THREADS) /* Threading support is enabled */
+#  if !defined(SWIG_PYTHON_USE_GIL) && !defined(SWIG_PYTHON_NO_USE_GIL)
+#    if (PY_VERSION_HEX >= 0x02030000) /* For 2.3 or later, use the PyGILState calls */
+#      define SWIG_PYTHON_USE_GIL
+#    endif
+#  endif
+#  if defined(SWIG_PYTHON_USE_GIL) /* Use PyGILState threads calls */
+#    ifndef SWIG_PYTHON_INITIALIZE_THREADS
+#     define SWIG_PYTHON_INITIALIZE_THREADS  PyEval_InitThreads() 
+#    endif
+#    ifdef __cplusplus /* C++ code */
+       class SWIG_Python_Thread_Block {
+         bool status;
+         PyGILState_STATE state;
+       public:
+         void end() { if (status) { PyGILState_Release(state); status = false;} }
+         SWIG_Python_Thread_Block() : status(true), state(PyGILState_Ensure()) {}
+         ~SWIG_Python_Thread_Block() { end(); }
+       };
+       class SWIG_Python_Thread_Allow {
+         bool status;
+         PyThreadState *save;
+       public:
+         void end() { if (status) { PyEval_RestoreThread(save); status = false; }}
+         SWIG_Python_Thread_Allow() : status(true), save(PyEval_SaveThread()) {}
+         ~SWIG_Python_Thread_Allow() { end(); }
+       };
+#      define SWIG_PYTHON_THREAD_BEGIN_BLOCK   SWIG_Python_Thread_Block _swig_thread_block
+#      define SWIG_PYTHON_THREAD_END_BLOCK     _swig_thread_block.end()
+#      define SWIG_PYTHON_THREAD_BEGIN_ALLOW   SWIG_Python_Thread_Allow _swig_thread_allow
+#      define SWIG_PYTHON_THREAD_END_ALLOW     _swig_thread_allow.end()
+#    else /* C code */
+#      define SWIG_PYTHON_THREAD_BEGIN_BLOCK   PyGILState_STATE _swig_thread_block = PyGILState_Ensure()
+#      define SWIG_PYTHON_THREAD_END_BLOCK     PyGILState_Release(_swig_thread_block)
+#      define SWIG_PYTHON_THREAD_BEGIN_ALLOW   PyThreadState *_swig_thread_allow = PyEval_SaveThread()
+#      define SWIG_PYTHON_THREAD_END_ALLOW     PyEval_RestoreThread(_swig_thread_allow)
+#    endif
+#  else /* Old thread way, not implemented, user must provide it */
+#    if !defined(SWIG_PYTHON_INITIALIZE_THREADS)
+#      define SWIG_PYTHON_INITIALIZE_THREADS
+#    endif
+#    if !defined(SWIG_PYTHON_THREAD_BEGIN_BLOCK)
+#      define SWIG_PYTHON_THREAD_BEGIN_BLOCK
+#    endif
+#    if !defined(SWIG_PYTHON_THREAD_END_BLOCK)
+#      define SWIG_PYTHON_THREAD_END_BLOCK
+#    endif
+#    if !defined(SWIG_PYTHON_THREAD_BEGIN_ALLOW)
+#      define SWIG_PYTHON_THREAD_BEGIN_ALLOW
+#    endif
+#    if !defined(SWIG_PYTHON_THREAD_END_ALLOW)
+#      define SWIG_PYTHON_THREAD_END_ALLOW
+#    endif
+#  endif
+#else /* No thread support */
+#  define SWIG_PYTHON_INITIALIZE_THREADS
+#  define SWIG_PYTHON_THREAD_BEGIN_BLOCK
+#  define SWIG_PYTHON_THREAD_END_BLOCK
+#  define SWIG_PYTHON_THREAD_BEGIN_ALLOW
+#  define SWIG_PYTHON_THREAD_END_ALLOW
+#endif
+
+/* -----------------------------------------------------------------------------
+ * Python API portion that goes into the runtime
+ * ----------------------------------------------------------------------------- */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* -----------------------------------------------------------------------------
+ * Constant declarations
+ * ----------------------------------------------------------------------------- */
+
+/* Constant Types */
+#define SWIG_PY_POINTER 4
+#define SWIG_PY_BINARY  5
+
+/* Constant information structure */
+typedef struct swig_const_info {
+  int type;
+  char *name;
+  long lvalue;
+  double dvalue;
+  void   *pvalue;
+  swig_type_info **ptype;
+} swig_const_info;
+
+
+/* -----------------------------------------------------------------------------
+ * Wrapper of PyInstanceMethod_New() used in Python 3
+ * It is exported to the generated module, used for -fastproxy
+ * ----------------------------------------------------------------------------- */
+#if PY_VERSION_HEX >= 0x03000000
+SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *func)
+{
+  return PyInstanceMethod_New(func);
+}
+#else
+SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *SWIGUNUSEDPARM(func))
+{
+  return NULL;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/* -----------------------------------------------------------------------------
+ * pyrun.swg
+ *
+ * This file contains the runtime support for Python modules
+ * and includes code for managing global variables and pointer
+ * type checking.
+ *
+ * ----------------------------------------------------------------------------- */
+
+/* Common SWIG API */
+
+/* for raw pointers */
+#define SWIG_Python_ConvertPtr(obj, pptr, type, flags)  SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, 0)
+#define SWIG_ConvertPtr(obj, pptr, type, flags)         SWIG_Python_ConvertPtr(obj, pptr, type, flags)
+#define SWIG_ConvertPtrAndOwn(obj,pptr,type,flags,own)  SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, own)
+
+#ifdef SWIGPYTHON_BUILTIN
+#define SWIG_NewPointerObj(ptr, type, flags)            SWIG_Python_NewPointerObj(self, ptr, type, flags)
+#else
+#define SWIG_NewPointerObj(ptr, type, flags)            SWIG_Python_NewPointerObj(NULL, ptr, type, flags)
+#endif
+
+#define SWIG_InternalNewPointerObj(ptr, type, flags)	SWIG_Python_NewPointerObj(NULL, ptr, type, flags)
+
+#define SWIG_CheckImplicit(ty)                          SWIG_Python_CheckImplicit(ty) 
+#define SWIG_AcquirePtr(ptr, src)                       SWIG_Python_AcquirePtr(ptr, src)
+#define swig_owntype                                    int
+
+/* for raw packed data */
+#define SWIG_ConvertPacked(obj, ptr, sz, ty)            SWIG_Python_ConvertPacked(obj, ptr, sz, ty)
+#define SWIG_NewPackedObj(ptr, sz, type)                SWIG_Python_NewPackedObj(ptr, sz, type)
+
+/* for class or struct pointers */
+#define SWIG_ConvertInstance(obj, pptr, type, flags)    SWIG_ConvertPtr(obj, pptr, type, flags)
+#define SWIG_NewInstanceObj(ptr, type, flags)           SWIG_NewPointerObj(ptr, type, flags)
+
+/* for C or C++ function pointers */
+#define SWIG_ConvertFunctionPtr(obj, pptr, type)        SWIG_Python_ConvertFunctionPtr(obj, pptr, type)
+#define SWIG_NewFunctionPtrObj(ptr, type)               SWIG_Python_NewPointerObj(NULL, ptr, type, 0)
+
+/* for C++ member pointers, ie, member methods */
+#define SWIG_ConvertMember(obj, ptr, sz, ty)            SWIG_Python_ConvertPacked(obj, ptr, sz, ty)
+#define SWIG_NewMemberObj(ptr, sz, type)                SWIG_Python_NewPackedObj(ptr, sz, type)
+
+
+/* Runtime API */
+
+#define SWIG_GetModule(clientdata)                      SWIG_Python_GetModule(clientdata)
+#define SWIG_SetModule(clientdata, pointer)             SWIG_Python_SetModule(pointer)
+#define SWIG_NewClientData(obj)                         SwigPyClientData_New(obj)
+
+#define SWIG_SetErrorObj                                SWIG_Python_SetErrorObj                            
+#define SWIG_SetErrorMsg                        	SWIG_Python_SetErrorMsg				   
+#define SWIG_ErrorType(code)                    	SWIG_Python_ErrorType(code)                        
+#define SWIG_Error(code, msg)            		SWIG_Python_SetErrorMsg(SWIG_ErrorType(code), msg) 
+#define SWIG_fail                        		goto fail					   
+
+
+/* Runtime API implementation */
+
+/* Error manipulation */
+
+SWIGINTERN void 
+SWIG_Python_SetErrorObj(PyObject *errtype, PyObject *obj) {
+  SWIG_PYTHON_THREAD_BEGIN_BLOCK; 
+  PyErr_SetObject(errtype, obj);
+  Py_DECREF(obj);
+  SWIG_PYTHON_THREAD_END_BLOCK;
+}
+
+SWIGINTERN void 
+SWIG_Python_SetErrorMsg(PyObject *errtype, const char *msg) {
+  SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+  PyErr_SetString(errtype, msg);
+  SWIG_PYTHON_THREAD_END_BLOCK;
+}
+
+#define SWIG_Python_Raise(obj, type, desc)  SWIG_Python_SetErrorObj(SWIG_Python_ExceptionType(desc), obj)
+
+/* Set a constant value */
+
+#if defined(SWIGPYTHON_BUILTIN)
+
+SWIGINTERN void
+SwigPyBuiltin_AddPublicSymbol(PyObject *seq, const char *key) {
+  PyObject *s = PyString_InternFromString(key);
+  PyList_Append(seq, s);
+  Py_DECREF(s);
+}
+
+SWIGINTERN void
+SWIG_Python_SetConstant(PyObject *d, PyObject *public_interface, const char *name, PyObject *obj) {   
+#if PY_VERSION_HEX < 0x02030000
+  PyDict_SetItemString(d, (char *)name, obj);
+#else
+  PyDict_SetItemString(d, name, obj);
+#endif
+  Py_DECREF(obj);
+  if (public_interface)
+    SwigPyBuiltin_AddPublicSymbol(public_interface, name);
+}
+
+#else
+
+SWIGINTERN void
+SWIG_Python_SetConstant(PyObject *d, const char *name, PyObject *obj) {   
+#if PY_VERSION_HEX < 0x02030000
+  PyDict_SetItemString(d, (char *)name, obj);
+#else
+  PyDict_SetItemString(d, name, obj);
+#endif
+  Py_DECREF(obj);                            
+}
+
+#endif
+
+/* Append a value to the result obj */
+
+SWIGINTERN PyObject*
+SWIG_Python_AppendOutput(PyObject* result, PyObject* obj) {
+#if !defined(SWIG_PYTHON_OUTPUT_TUPLE)
+  if (!result) {
+    result = obj;
+  } else if (result == Py_None) {
+    Py_DECREF(result);
+    result = obj;
+  } else {
+    if (!PyList_Check(result)) {
+      PyObject *o2 = result;
+      result = PyList_New(1);
+      PyList_SetItem(result, 0, o2);
+    }
+    PyList_Append(result,obj);
+    Py_DECREF(obj);
+  }
+  return result;
+#else
+  PyObject*   o2;
+  PyObject*   o3;
+  if (!result) {
+    result = obj;
+  } else if (result == Py_None) {
+    Py_DECREF(result);
+    result = obj;
+  } else {
+    if (!PyTuple_Check(result)) {
+      o2 = result;
+      result = PyTuple_New(1);
+      PyTuple_SET_ITEM(result, 0, o2);
+    }
+    o3 = PyTuple_New(1);
+    PyTuple_SET_ITEM(o3, 0, obj);
+    o2 = result;
+    result = PySequence_Concat(o2, o3);
+    Py_DECREF(o2);
+    Py_DECREF(o3);
+  }
+  return result;
+#endif
+}
+
+/* Unpack the argument tuple */
+
+SWIGINTERN int
+SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, PyObject **objs)
+{
+  if (!args) {
+    if (!min && !max) {
+      return 1;
+    } else {
+      PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got none", 
+		   name, (min == max ? "" : "at least "), (int)min);
+      return 0;
+    }
+  }  
+  if (!PyTuple_Check(args)) {
+    if (min <= 1 && max >= 1) {
+      register int i;
+      objs[0] = args;
+      for (i = 1; i < max; ++i) {
+	objs[i] = 0;
+      }
+      return 2;
+    }
+    PyErr_SetString(PyExc_SystemError, "UnpackTuple() argument list is not a tuple");
+    return 0;
+  } else {
+    register Py_ssize_t l = PyTuple_GET_SIZE(args);
+    if (l < min) {
+      PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", 
+		   name, (min == max ? "" : "at least "), (int)min, (int)l);
+      return 0;
+    } else if (l > max) {
+      PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", 
+		   name, (min == max ? "" : "at most "), (int)max, (int)l);
+      return 0;
+    } else {
+      register int i;
+      for (i = 0; i < l; ++i) {
+	objs[i] = PyTuple_GET_ITEM(args, i);
+      }
+      for (; l < max; ++l) {
+	objs[l] = 0;
+      }
+      return i + 1;
+    }    
+  }
+}
+
+/* A functor is a function object with one single object argument */
+#if PY_VERSION_HEX >= 0x02020000
+#define SWIG_Python_CallFunctor(functor, obj)	        PyObject_CallFunctionObjArgs(functor, obj, NULL);
+#else
+#define SWIG_Python_CallFunctor(functor, obj)	        PyObject_CallFunction(functor, "O", obj);
+#endif
+
+/*
+  Helper for static pointer initialization for both C and C++ code, for example
+  static PyObject *SWIG_STATIC_POINTER(MyVar) = NewSomething(...);
+*/
+#ifdef __cplusplus
+#define SWIG_STATIC_POINTER(var)  var
+#else
+#define SWIG_STATIC_POINTER(var)  var = 0; if (!var) var
+#endif
+
+/* -----------------------------------------------------------------------------
+ * Pointer declarations
+ * ----------------------------------------------------------------------------- */
+
+/* Flags for new pointer objects */
+#define SWIG_POINTER_NOSHADOW       (SWIG_POINTER_OWN      << 1)
+#define SWIG_POINTER_NEW            (SWIG_POINTER_NOSHADOW | SWIG_POINTER_OWN)
+
+#define SWIG_POINTER_IMPLICIT_CONV  (SWIG_POINTER_DISOWN   << 1)
+
+#define SWIG_BUILTIN_TP_INIT	    (SWIG_POINTER_OWN << 2)
+#define SWIG_BUILTIN_INIT	    (SWIG_BUILTIN_TP_INIT | SWIG_POINTER_OWN)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*  How to access Py_None */
+#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+#  ifndef SWIG_PYTHON_NO_BUILD_NONE
+#    ifndef SWIG_PYTHON_BUILD_NONE
+#      define SWIG_PYTHON_BUILD_NONE
+#    endif
+#  endif
+#endif
+
+#ifdef SWIG_PYTHON_BUILD_NONE
+#  ifdef Py_None
+#   undef Py_None
+#   define Py_None SWIG_Py_None()
+#  endif
+SWIGRUNTIMEINLINE PyObject * 
+_SWIG_Py_None(void)
+{
+  PyObject *none = Py_BuildValue((char*)"");
+  Py_DECREF(none);
+  return none;
+}
+SWIGRUNTIME PyObject * 
+SWIG_Py_None(void)
+{
+  static PyObject *SWIG_STATIC_POINTER(none) = _SWIG_Py_None();
+  return none;
+}
+#endif
+
+/* The python void return value */
+
+SWIGRUNTIMEINLINE PyObject * 
+SWIG_Py_Void(void)
+{
+  PyObject *none = Py_None;
+  Py_INCREF(none);
+  return none;
+}
+
+/* SwigPyClientData */
+
+typedef struct {
+  PyObject *klass;
+  PyObject *newraw;
+  PyObject *newargs;
+  PyObject *destroy;
+  int delargs;
+  int implicitconv;
+  PyTypeObject *pytype;
+} SwigPyClientData;
+
+SWIGRUNTIMEINLINE int 
+SWIG_Python_CheckImplicit(swig_type_info *ty)
+{
+  SwigPyClientData *data = (SwigPyClientData *)ty->clientdata;
+  return data ? data->implicitconv : 0;
+}
+
+SWIGRUNTIMEINLINE PyObject *
+SWIG_Python_ExceptionType(swig_type_info *desc) {
+  SwigPyClientData *data = desc ? (SwigPyClientData *) desc->clientdata : 0;
+  PyObject *klass = data ? data->klass : 0;
+  return (klass ? klass : PyExc_RuntimeError);
+}
+
+
+SWIGRUNTIME SwigPyClientData * 
+SwigPyClientData_New(PyObject* obj)
+{
+  if (!obj) {
+    return 0;
+  } else {
+    SwigPyClientData *data = (SwigPyClientData *)malloc(sizeof(SwigPyClientData));
+    /* the klass element */
+    data->klass = obj;
+    Py_INCREF(data->klass);
+    /* the newraw method and newargs arguments used to create a new raw instance */
+    if (PyClass_Check(obj)) {
+      data->newraw = 0;
+      data->newargs = obj;
+      Py_INCREF(obj);
+    } else {
+#if (PY_VERSION_HEX < 0x02020000)
+      data->newraw = 0;
+#else
+      data->newraw = PyObject_GetAttrString(data->klass, (char *)"__new__");
+#endif
+      if (data->newraw) {
+	Py_INCREF(data->newraw);
+	data->newargs = PyTuple_New(1);
+	PyTuple_SetItem(data->newargs, 0, obj);
+      } else {
+	data->newargs = obj;
+      }
+      Py_INCREF(data->newargs);
+    }
+    /* the destroy method, aka as the C++ delete method */
+    data->destroy = PyObject_GetAttrString(data->klass, (char *)"__swig_destroy__");
+    if (PyErr_Occurred()) {
+      PyErr_Clear();
+      data->destroy = 0;
+    }
+    if (data->destroy) {
+      int flags;
+      Py_INCREF(data->destroy);
+      flags = PyCFunction_GET_FLAGS(data->destroy);
+#ifdef METH_O
+      data->delargs = !(flags & (METH_O));
+#else
+      data->delargs = 0;
+#endif
+    } else {
+      data->delargs = 0;
+    }
+    data->implicitconv = 0;
+    data->pytype = 0;
+    return data;
+  }
+}
+
+SWIGRUNTIME void 
+SwigPyClientData_Del(SwigPyClientData *data) {
+  Py_XDECREF(data->newraw);
+  Py_XDECREF(data->newargs);
+  Py_XDECREF(data->destroy);
+}
+
+/* =============== SwigPyObject =====================*/
+
+typedef struct {
+  PyObject_HEAD
+  void *ptr;
+  swig_type_info *ty;
+  int own;
+  PyObject *next;
+#ifdef SWIGPYTHON_BUILTIN
+  PyObject *dict;
+#endif
+} SwigPyObject;
+
+SWIGRUNTIME PyObject *
+SwigPyObject_long(SwigPyObject *v)
+{
+  return PyLong_FromVoidPtr(v->ptr);
+}
+
+SWIGRUNTIME PyObject *
+SwigPyObject_format(const char* fmt, SwigPyObject *v)
+{
+  PyObject *res = NULL;
+  PyObject *args = PyTuple_New(1);
+  if (args) {
+    if (PyTuple_SetItem(args, 0, SwigPyObject_long(v)) == 0) {
+      PyObject *ofmt = SWIG_Python_str_FromChar(fmt);
+      if (ofmt) {
+#if PY_VERSION_HEX >= 0x03000000
+	res = PyUnicode_Format(ofmt,args);
+#else
+	res = PyString_Format(ofmt,args);
+#endif
+	Py_DECREF(ofmt);
+      }
+      Py_DECREF(args);
+    }
+  }
+  return res;
+}
+
+SWIGRUNTIME PyObject *
+SwigPyObject_oct(SwigPyObject *v)
+{
+  return SwigPyObject_format("%o",v);
+}
+
+SWIGRUNTIME PyObject *
+SwigPyObject_hex(SwigPyObject *v)
+{
+  return SwigPyObject_format("%x",v);
+}
+
+SWIGRUNTIME PyObject *
+#ifdef METH_NOARGS
+SwigPyObject_repr(SwigPyObject *v)
+#else
+SwigPyObject_repr(SwigPyObject *v, PyObject *args)
+#endif
+{
+  const char *name = SWIG_TypePrettyName(v->ty);
+  PyObject *repr = SWIG_Python_str_FromFormat("<Swig Object of type '%s' at %p>", (name ? name : "unknown"), (void *)v);
+  if (v->next) {
+# ifdef METH_NOARGS
+    PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next);
+# else
+    PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next, args);
+# endif
+# if PY_VERSION_HEX >= 0x03000000
+    PyObject *joined = PyUnicode_Concat(repr, nrep);
+    Py_DecRef(repr);
+    Py_DecRef(nrep);
+    repr = joined;
+# else
+    PyString_ConcatAndDel(&repr,nrep);
+# endif
+  }
+  return repr;  
+}
+
+SWIGRUNTIME int
+SwigPyObject_compare(SwigPyObject *v, SwigPyObject *w)
+{
+  void *i = v->ptr;
+  void *j = w->ptr;
+  return (i < j) ? -1 : ((i > j) ? 1 : 0);
+}
+
+/* Added for Python 3.x, would it also be useful for Python 2.x? */
+SWIGRUNTIME PyObject*
+SwigPyObject_richcompare(SwigPyObject *v, SwigPyObject *w, int op)
+{
+  PyObject* res;
+  if( op != Py_EQ && op != Py_NE ) {
+    Py_INCREF(Py_NotImplemented);
+    return Py_NotImplemented;
+  }
+  res = PyBool_FromLong( (SwigPyObject_compare(v, w)==0) == (op == Py_EQ) ? 1 : 0);
+  return res;  
+}
+
+
+SWIGRUNTIME PyTypeObject* SwigPyObject_TypeOnce(void);
+
+#ifdef SWIGPYTHON_BUILTIN
+static swig_type_info *SwigPyObject_stype = 0;
+SWIGRUNTIME PyTypeObject*
+SwigPyObject_type(void) {
+    SwigPyClientData *cd;
+    assert(SwigPyObject_stype);
+    cd = (SwigPyClientData*) SwigPyObject_stype->clientdata;
+    assert(cd);
+    assert(cd->pytype);
+    return cd->pytype;
+}
+#else
+SWIGRUNTIME PyTypeObject*
+SwigPyObject_type(void) {
+  static PyTypeObject *SWIG_STATIC_POINTER(type) = SwigPyObject_TypeOnce();
+  return type;
+}
+#endif
+
+SWIGRUNTIMEINLINE int
+SwigPyObject_Check(PyObject *op) {
+#ifdef SWIGPYTHON_BUILTIN
+  PyTypeObject *target_tp = SwigPyObject_type();
+  if (PyType_IsSubtype(op->ob_type, target_tp))
+    return 1;
+  return (strcmp(op->ob_type->tp_name, "SwigPyObject") == 0);
+#else
+  return (Py_TYPE(op) == SwigPyObject_type())
+    || (strcmp(Py_TYPE(op)->tp_name,"SwigPyObject") == 0);
+#endif
+}
+
+SWIGRUNTIME PyObject *
+SwigPyObject_New(void *ptr, swig_type_info *ty, int own);
+
+SWIGRUNTIME void
+SwigPyObject_dealloc(PyObject *v)
+{
+  SwigPyObject *sobj = (SwigPyObject *) v;
+  PyObject *next = sobj->next;
+  if (sobj->own == SWIG_POINTER_OWN) {
+    swig_type_info *ty = sobj->ty;
+    SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0;
+    PyObject *destroy = data ? data->destroy : 0;
+    if (destroy) {
+      /* destroy is always a VARARGS method */
+      PyObject *res;
+      if (data->delargs) {
+	/* we need to create a temporary object to carry the destroy operation */
+	PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0);
+	res = SWIG_Python_CallFunctor(destroy, tmp);
+	Py_DECREF(tmp);
+      } else {
+	PyCFunction meth = PyCFunction_GET_FUNCTION(destroy);
+	PyObject *mself = PyCFunction_GET_SELF(destroy);
+	res = ((*meth)(mself, v));
+      }
+      Py_XDECREF(res);
+    } 
+#if !defined(SWIG_PYTHON_SILENT_MEMLEAK)
+    else {
+      const char *name = SWIG_TypePrettyName(ty);
+      printf("swig/python detected a memory leak of type '%s', no destructor found.\n", (name ? name : "unknown"));
+    }
+#endif
+  } 
+  Py_XDECREF(next);
+  PyObject_DEL(v);
+}
+
+SWIGRUNTIME PyObject* 
+SwigPyObject_append(PyObject* v, PyObject* next)
+{
+  SwigPyObject *sobj = (SwigPyObject *) v;
+#ifndef METH_O
+  PyObject *tmp = 0;
+  if (!PyArg_ParseTuple(next,(char *)"O:append", &tmp)) return NULL;
+  next = tmp;
+#endif
+  if (!SwigPyObject_Check(next)) {
+    return NULL;
+  }
+  sobj->next = next;
+  Py_INCREF(next);
+  return SWIG_Py_Void();
+}
+
+SWIGRUNTIME PyObject* 
+#ifdef METH_NOARGS
+SwigPyObject_next(PyObject* v)
+#else
+SwigPyObject_next(PyObject* v, PyObject *SWIGUNUSEDPARM(args))
+#endif
+{
+  SwigPyObject *sobj = (SwigPyObject *) v;
+  if (sobj->next) {    
+    Py_INCREF(sobj->next);
+    return sobj->next;
+  } else {
+    return SWIG_Py_Void();
+  }
+}
+
+SWIGINTERN PyObject*
+#ifdef METH_NOARGS
+SwigPyObject_disown(PyObject *v)
+#else
+SwigPyObject_disown(PyObject* v, PyObject *SWIGUNUSEDPARM(args))
+#endif
+{
+  SwigPyObject *sobj = (SwigPyObject *)v;
+  sobj->own = 0;
+  return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject*
+#ifdef METH_NOARGS
+SwigPyObject_acquire(PyObject *v)
+#else
+SwigPyObject_acquire(PyObject* v, PyObject *SWIGUNUSEDPARM(args))
+#endif
+{
+  SwigPyObject *sobj = (SwigPyObject *)v;
+  sobj->own = SWIG_POINTER_OWN;
+  return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject*
+SwigPyObject_own(PyObject *v, PyObject *args)
+{
+  PyObject *val = 0;
+#if (PY_VERSION_HEX < 0x02020000)
+  if (!PyArg_ParseTuple(args,(char *)"|O:own",&val))
+#elif (PY_VERSION_HEX < 0x02050000)
+  if (!PyArg_UnpackTuple(args, (char *)"own", 0, 1, &val)) 
+#else
+  if (!PyArg_UnpackTuple(args, "own", 0, 1, &val)) 
+#endif
+    {
+      return NULL;
+    } 
+  else
+    {
+      SwigPyObject *sobj = (SwigPyObject *)v;
+      PyObject *obj = PyBool_FromLong(sobj->own);
+      if (val) {
+#ifdef METH_NOARGS
+	if (PyObject_IsTrue(val)) {
+	  SwigPyObject_acquire(v);
+	} else {
+	  SwigPyObject_disown(v);
+	}
+#else
+	if (PyObject_IsTrue(val)) {
+	  SwigPyObject_acquire(v,args);
+	} else {
+	  SwigPyObject_disown(v,args);
+	}
+#endif
+      } 
+      return obj;
+    }
+}
+
+#ifdef METH_O
+static PyMethodDef
+swigobject_methods[] = {
+  {(char *)"disown",  (PyCFunction)SwigPyObject_disown,  METH_NOARGS,  (char *)"releases ownership of the pointer"},
+  {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_NOARGS,  (char *)"acquires ownership of the pointer"},
+  {(char *)"own",     (PyCFunction)SwigPyObject_own,     METH_VARARGS, (char *)"returns/sets ownership of the pointer"},
+  {(char *)"append",  (PyCFunction)SwigPyObject_append,  METH_O,       (char *)"appends another 'this' object"},
+  {(char *)"next",    (PyCFunction)SwigPyObject_next,    METH_NOARGS,  (char *)"returns the next 'this' object"},
+  {(char *)"__repr__",(PyCFunction)SwigPyObject_repr,    METH_NOARGS,  (char *)"returns object representation"},
+  {0, 0, 0, 0}  
+};
+#else
+static PyMethodDef
+swigobject_methods[] = {
+  {(char *)"disown",  (PyCFunction)SwigPyObject_disown,  METH_VARARGS,  (char *)"releases ownership of the pointer"},
+  {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_VARARGS,  (char *)"aquires ownership of the pointer"},
+  {(char *)"own",     (PyCFunction)SwigPyObject_own,     METH_VARARGS,  (char *)"returns/sets ownership of the pointer"},
+  {(char *)"append",  (PyCFunction)SwigPyObject_append,  METH_VARARGS,  (char *)"appends another 'this' object"},
+  {(char *)"next",    (PyCFunction)SwigPyObject_next,    METH_VARARGS,  (char *)"returns the next 'this' object"},
+  {(char *)"__repr__",(PyCFunction)SwigPyObject_repr,   METH_VARARGS,  (char *)"returns object representation"},
+  {0, 0, 0, 0}  
+};
+#endif
+
+#if PY_VERSION_HEX < 0x02020000
+SWIGINTERN PyObject *
+SwigPyObject_getattr(SwigPyObject *sobj,char *name)
+{
+  return Py_FindMethod(swigobject_methods, (PyObject *)sobj, name);
+}
+#endif
+
+SWIGRUNTIME PyTypeObject*
+SwigPyObject_TypeOnce(void) {
+  static char swigobject_doc[] = "Swig object carries a C/C++ instance pointer";
+
+  static PyNumberMethods SwigPyObject_as_number = {
+    (binaryfunc)0, /*nb_add*/
+    (binaryfunc)0, /*nb_subtract*/
+    (binaryfunc)0, /*nb_multiply*/
+    /* nb_divide removed in Python 3 */
+#if PY_VERSION_HEX < 0x03000000
+    (binaryfunc)0, /*nb_divide*/
+#endif
+    (binaryfunc)0, /*nb_remainder*/
+    (binaryfunc)0, /*nb_divmod*/
+    (ternaryfunc)0,/*nb_power*/
+    (unaryfunc)0,  /*nb_negative*/
+    (unaryfunc)0,  /*nb_positive*/
+    (unaryfunc)0,  /*nb_absolute*/
+    (inquiry)0,    /*nb_nonzero*/
+    0,		   /*nb_invert*/
+    0,		   /*nb_lshift*/
+    0,		   /*nb_rshift*/
+    0,		   /*nb_and*/
+    0,		   /*nb_xor*/
+    0,		   /*nb_or*/
+#if PY_VERSION_HEX < 0x03000000
+    0,   /*nb_coerce*/
+#endif
+    (unaryfunc)SwigPyObject_long, /*nb_int*/
+#if PY_VERSION_HEX < 0x03000000
+    (unaryfunc)SwigPyObject_long, /*nb_long*/
+#else
+    0, /*nb_reserved*/
+#endif
+    (unaryfunc)0,                 /*nb_float*/
+#if PY_VERSION_HEX < 0x03000000
+    (unaryfunc)SwigPyObject_oct,  /*nb_oct*/
+    (unaryfunc)SwigPyObject_hex,  /*nb_hex*/
+#endif
+#if PY_VERSION_HEX >= 0x03000000 /* 3.0 */
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index, nb_inplace_divide removed */
+#elif PY_VERSION_HEX >= 0x02050000 /* 2.5.0 */
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index */
+#elif PY_VERSION_HEX >= 0x02020000 /* 2.2.0 */
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_true_divide */
+#elif PY_VERSION_HEX >= 0x02000000 /* 2.0.0 */
+    0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_or */
+#endif
+  };
+
+  static PyTypeObject swigpyobject_type;
+  static int type_init = 0;
+  if (!type_init) {
+    const PyTypeObject tmp = {
+      /* PyObject header changed in Python 3 */
+#if PY_VERSION_HEX >= 0x03000000
+      PyVarObject_HEAD_INIT(NULL, 0)
+#else
+      PyObject_HEAD_INIT(NULL)
+      0,                                    /* ob_size */
+#endif
+      (char *)"SwigPyObject",               /* tp_name */
+      sizeof(SwigPyObject),                 /* tp_basicsize */
+      0,                                    /* tp_itemsize */
+      (destructor)SwigPyObject_dealloc,     /* tp_dealloc */
+      0,				    /* tp_print */
+#if PY_VERSION_HEX < 0x02020000
+      (getattrfunc)SwigPyObject_getattr,    /* tp_getattr */
+#else
+      (getattrfunc)0,                       /* tp_getattr */
+#endif
+      (setattrfunc)0,                       /* tp_setattr */
+#if PY_VERSION_HEX >= 0x03000000
+    0, /* tp_reserved in 3.0.1, tp_compare in 3.0.0 but not used */
+#else
+      (cmpfunc)SwigPyObject_compare,        /* tp_compare */
+#endif
+      (reprfunc)SwigPyObject_repr,          /* tp_repr */
+      &SwigPyObject_as_number,              /* tp_as_number */
+      0,                                    /* tp_as_sequence */
+      0,                                    /* tp_as_mapping */
+      (hashfunc)0,                          /* tp_hash */
+      (ternaryfunc)0,                       /* tp_call */
+      0,				    /* tp_str */
+      PyObject_GenericGetAttr,              /* tp_getattro */
+      0,                                    /* tp_setattro */
+      0,                                    /* tp_as_buffer */
+      Py_TPFLAGS_DEFAULT,                   /* tp_flags */
+      swigobject_doc,                       /* tp_doc */
+      0,                                    /* tp_traverse */
+      0,                                    /* tp_clear */
+      (richcmpfunc)SwigPyObject_richcompare,/* tp_richcompare */
+      0,                                    /* tp_weaklistoffset */
+#if PY_VERSION_HEX >= 0x02020000
+      0,                                    /* tp_iter */
+      0,                                    /* tp_iternext */
+      swigobject_methods,                   /* tp_methods */
+      0,                                    /* tp_members */
+      0,                                    /* tp_getset */
+      0,                                    /* tp_base */
+      0,                                    /* tp_dict */
+      0,                                    /* tp_descr_get */
+      0,                                    /* tp_descr_set */
+      0,                                    /* tp_dictoffset */
+      0,                                    /* tp_init */
+      0,                                    /* tp_alloc */
+      0,                                    /* tp_new */
+      0,                                    /* tp_free */
+      0,                                    /* tp_is_gc */
+      0,                                    /* tp_bases */
+      0,                                    /* tp_mro */
+      0,                                    /* tp_cache */
+      0,                                    /* tp_subclasses */
+      0,                                    /* tp_weaklist */
+#endif
+#if PY_VERSION_HEX >= 0x02030000
+      0,                                    /* tp_del */
+#endif
+#if PY_VERSION_HEX >= 0x02060000
+      0,                                    /* tp_version */
+#endif
+#ifdef COUNT_ALLOCS
+      0,0,0,0                               /* tp_alloc -> tp_next */
+#endif
+    };
+    swigpyobject_type = tmp;
+    type_init = 1;
+#if PY_VERSION_HEX < 0x02020000
+    swigpyobject_type.ob_type = &PyType_Type;
+#else
+    if (PyType_Ready(&swigpyobject_type) < 0)
+      return NULL;
+#endif
+  }
+  return &swigpyobject_type;
+}
+
+SWIGRUNTIME PyObject *
+SwigPyObject_New(void *ptr, swig_type_info *ty, int own)
+{
+  SwigPyObject *sobj = PyObject_NEW(SwigPyObject, SwigPyObject_type());
+  if (sobj) {
+    sobj->ptr  = ptr;
+    sobj->ty   = ty;
+    sobj->own  = own;
+    sobj->next = 0;
+  }
+  return (PyObject *)sobj;
+}
+
+/* -----------------------------------------------------------------------------
+ * Implements a simple Swig Packed type, and use it instead of string
+ * ----------------------------------------------------------------------------- */
+
+typedef struct {
+  PyObject_HEAD
+  void *pack;
+  swig_type_info *ty;
+  size_t size;
+} SwigPyPacked;
+
+SWIGRUNTIME int
+SwigPyPacked_print(SwigPyPacked *v, FILE *fp, int SWIGUNUSEDPARM(flags))
+{
+  char result[SWIG_BUFFER_SIZE];
+  fputs("<Swig Packed ", fp); 
+  if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))) {
+    fputs("at ", fp); 
+    fputs(result, fp); 
+  }
+  fputs(v->ty->name,fp); 
+  fputs(">", fp);
+  return 0; 
+}
+  
+SWIGRUNTIME PyObject *
+SwigPyPacked_repr(SwigPyPacked *v)
+{
+  char result[SWIG_BUFFER_SIZE];
+  if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))) {
+    return SWIG_Python_str_FromFormat("<Swig Packed at %s%s>", result, v->ty->name);
+  } else {
+    return SWIG_Python_str_FromFormat("<Swig Packed %s>", v->ty->name);
+  }  
+}
+
+SWIGRUNTIME PyObject *
+SwigPyPacked_str(SwigPyPacked *v)
+{
+  char result[SWIG_BUFFER_SIZE];
+  if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))){
+    return SWIG_Python_str_FromFormat("%s%s", result, v->ty->name);
+  } else {
+    return SWIG_Python_str_FromChar(v->ty->name);
+  }  
+}
+
+SWIGRUNTIME int
+SwigPyPacked_compare(SwigPyPacked *v, SwigPyPacked *w)
+{
+  size_t i = v->size;
+  size_t j = w->size;
+  int s = (i < j) ? -1 : ((i > j) ? 1 : 0);
+  return s ? s : strncmp((char *)v->pack, (char *)w->pack, 2*v->size);
+}
+
+SWIGRUNTIME PyTypeObject* SwigPyPacked_TypeOnce(void);
+
+SWIGRUNTIME PyTypeObject*
+SwigPyPacked_type(void) {
+  static PyTypeObject *SWIG_STATIC_POINTER(type) = SwigPyPacked_TypeOnce();
+  return type;
+}
+
+SWIGRUNTIMEINLINE int
+SwigPyPacked_Check(PyObject *op) {
+  return ((op)->ob_type == SwigPyPacked_TypeOnce()) 
+    || (strcmp((op)->ob_type->tp_name,"SwigPyPacked") == 0);
+}
+
+SWIGRUNTIME void
+SwigPyPacked_dealloc(PyObject *v)
+{
+  if (SwigPyPacked_Check(v)) {
+    SwigPyPacked *sobj = (SwigPyPacked *) v;
+    free(sobj->pack);
+  }
+  PyObject_DEL(v);
+}
+
+SWIGRUNTIME PyTypeObject*
+SwigPyPacked_TypeOnce(void) {
+  static char swigpacked_doc[] = "Swig object carries a C/C++ instance pointer";
+  static PyTypeObject swigpypacked_type;
+  static int type_init = 0;
+  if (!type_init) {
+    const PyTypeObject tmp = {
+      /* PyObject header changed in Python 3 */
+#if PY_VERSION_HEX>=0x03000000
+      PyVarObject_HEAD_INIT(NULL, 0)
+#else
+      PyObject_HEAD_INIT(NULL)
+      0,                                    /* ob_size */
+#endif
+      (char *)"SwigPyPacked",               /* tp_name */
+      sizeof(SwigPyPacked),                 /* tp_basicsize */
+      0,                                    /* tp_itemsize */
+      (destructor)SwigPyPacked_dealloc,     /* tp_dealloc */
+      (printfunc)SwigPyPacked_print,        /* tp_print */
+      (getattrfunc)0,                       /* tp_getattr */
+      (setattrfunc)0,                       /* tp_setattr */
+#if PY_VERSION_HEX>=0x03000000
+      0, /* tp_reserved in 3.0.1 */
+#else
+      (cmpfunc)SwigPyPacked_compare,        /* tp_compare */
+#endif
+      (reprfunc)SwigPyPacked_repr,          /* tp_repr */
+      0,                                    /* tp_as_number */
+      0,                                    /* tp_as_sequence */
+      0,                                    /* tp_as_mapping */
+      (hashfunc)0,                          /* tp_hash */
+      (ternaryfunc)0,                       /* tp_call */
+      (reprfunc)SwigPyPacked_str,           /* tp_str */
+      PyObject_GenericGetAttr,              /* tp_getattro */
+      0,                                    /* tp_setattro */
+      0,                                    /* tp_as_buffer */
+      Py_TPFLAGS_DEFAULT,                   /* tp_flags */
+      swigpacked_doc,                       /* tp_doc */
+      0,                                    /* tp_traverse */
+      0,                                    /* tp_clear */
+      0,                                    /* tp_richcompare */
+      0,                                    /* tp_weaklistoffset */
+#if PY_VERSION_HEX >= 0x02020000
+      0,                                    /* tp_iter */
+      0,                                    /* tp_iternext */
+      0,                                    /* tp_methods */
+      0,                                    /* tp_members */
+      0,                                    /* tp_getset */
+      0,                                    /* tp_base */
+      0,                                    /* tp_dict */
+      0,                                    /* tp_descr_get */
+      0,                                    /* tp_descr_set */
+      0,                                    /* tp_dictoffset */
+      0,                                    /* tp_init */
+      0,                                    /* tp_alloc */
+      0,                                    /* tp_new */
+      0,                                    /* tp_free */
+      0,                                    /* tp_is_gc */
+      0,                                    /* tp_bases */
+      0,                                    /* tp_mro */
+      0,                                    /* tp_cache */
+      0,                                    /* tp_subclasses */
+      0,                                    /* tp_weaklist */
+#endif
+#if PY_VERSION_HEX >= 0x02030000
+      0,                                    /* tp_del */
+#endif
+#if PY_VERSION_HEX >= 0x02060000
+      0,                                    /* tp_version */
+#endif
+#ifdef COUNT_ALLOCS
+      0,0,0,0                               /* tp_alloc -> tp_next */
+#endif
+    };
+    swigpypacked_type = tmp;
+    type_init = 1;
+#if PY_VERSION_HEX < 0x02020000
+    swigpypacked_type.ob_type = &PyType_Type;
+#else
+    if (PyType_Ready(&swigpypacked_type) < 0)
+      return NULL;
+#endif
+  }
+  return &swigpypacked_type;
+}
+
+SWIGRUNTIME PyObject *
+SwigPyPacked_New(void *ptr, size_t size, swig_type_info *ty)
+{
+  SwigPyPacked *sobj = PyObject_NEW(SwigPyPacked, SwigPyPacked_type());
+  if (sobj) {
+    void *pack = malloc(size);
+    if (pack) {
+      memcpy(pack, ptr, size);
+      sobj->pack = pack;
+      sobj->ty   = ty;
+      sobj->size = size;
+    } else {
+      PyObject_DEL((PyObject *) sobj);
+      sobj = 0;
+    }
+  }
+  return (PyObject *) sobj;
+}
+
+SWIGRUNTIME swig_type_info *
+SwigPyPacked_UnpackData(PyObject *obj, void *ptr, size_t size)
+{
+  if (SwigPyPacked_Check(obj)) {
+    SwigPyPacked *sobj = (SwigPyPacked *)obj;
+    if (sobj->size != size) return 0;
+    memcpy(ptr, sobj->pack, size);
+    return sobj->ty;
+  } else {
+    return 0;
+  }
+}
+
+/* -----------------------------------------------------------------------------
+ * pointers/data manipulation
+ * ----------------------------------------------------------------------------- */
+
+SWIGRUNTIMEINLINE PyObject *
+_SWIG_This(void)
+{
+    return SWIG_Python_str_FromChar("this");
+}
+
+static PyObject *swig_this = NULL;
+
+SWIGRUNTIME PyObject *
+SWIG_This(void)
+{
+  if (swig_this == NULL)
+    swig_this = _SWIG_This();
+  return swig_this;
+}
+
+/* #define SWIG_PYTHON_SLOW_GETSET_THIS */
+
+/* TODO: I don't know how to implement the fast getset in Python 3 right now */
+#if PY_VERSION_HEX>=0x03000000
+#define SWIG_PYTHON_SLOW_GETSET_THIS 
+#endif
+
+SWIGRUNTIME SwigPyObject *
+SWIG_Python_GetSwigThis(PyObject *pyobj) 
+{
+  PyObject *obj;
+
+  if (SwigPyObject_Check(pyobj))
+    return (SwigPyObject *) pyobj;
+
+#ifdef SWIGPYTHON_BUILTIN
+  (void)obj;
+# ifdef PyWeakref_CheckProxy
+  if (PyWeakref_CheckProxy(pyobj)) {
+    pyobj = PyWeakref_GET_OBJECT(pyobj);
+    if (pyobj && SwigPyObject_Check(pyobj))
+      return (SwigPyObject*) pyobj;
+  }
+# endif
+  return NULL;
+#else
+
+  obj = 0;
+
+#if (!defined(SWIG_PYTHON_SLOW_GETSET_THIS) && (PY_VERSION_HEX >= 0x02030000))
+  if (PyInstance_Check(pyobj)) {
+    obj = _PyInstance_Lookup(pyobj, SWIG_This());      
+  } else {
+    PyObject **dictptr = _PyObject_GetDictPtr(pyobj);
+    if (dictptr != NULL) {
+      PyObject *dict = *dictptr;
+      obj = dict ? PyDict_GetItem(dict, SWIG_This()) : 0;
+    } else {
+#ifdef PyWeakref_CheckProxy
+      if (PyWeakref_CheckProxy(pyobj)) {
+	PyObject *wobj = PyWeakref_GET_OBJECT(pyobj);
+	return wobj ? SWIG_Python_GetSwigThis(wobj) : 0;
+      }
+#endif
+      obj = PyObject_GetAttr(pyobj,SWIG_This());
+      if (obj) {
+	Py_DECREF(obj);
+      } else {
+	if (PyErr_Occurred()) PyErr_Clear();
+	return 0;
+      }
+    }
+  }
+#else
+  obj = PyObject_GetAttr(pyobj,SWIG_This());
+  if (obj) {
+    Py_DECREF(obj);
+  } else {
+    if (PyErr_Occurred()) PyErr_Clear();
+    return 0;
+  }
+#endif
+  if (obj && !SwigPyObject_Check(obj)) {
+    /* a PyObject is called 'this', try to get the 'real this'
+       SwigPyObject from it */ 
+    return SWIG_Python_GetSwigThis(obj);
+  }
+  return (SwigPyObject *)obj;
+#endif
+}
+
+/* Acquire a pointer value */
+
+SWIGRUNTIME int
+SWIG_Python_AcquirePtr(PyObject *obj, int own) {
+  if (own == SWIG_POINTER_OWN) {
+    SwigPyObject *sobj = SWIG_Python_GetSwigThis(obj);
+    if (sobj) {
+      int oldown = sobj->own;
+      sobj->own = own;
+      return oldown;
+    }
+  }
+  return 0;
+}
+
+/* Convert a pointer value */
+
+SWIGRUNTIME int
+SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int flags, int *own) {
+  int res;
+  SwigPyObject *sobj;
+  int implicit_conv = (flags & SWIG_POINTER_IMPLICIT_CONV) != 0;
+
+  if (!obj)
+    return SWIG_ERROR;
+  if (obj == Py_None && !implicit_conv) {
+    if (ptr)
+      *ptr = 0;
+    return SWIG_OK;
+  }
+
+  res = SWIG_ERROR;
+
+  sobj = SWIG_Python_GetSwigThis(obj);
+  if (own)
+    *own = 0;
+  while (sobj) {
+    void *vptr = sobj->ptr;
+    if (ty) {
+      swig_type_info *to = sobj->ty;
+      if (to == ty) {
+        /* no type cast needed */
+        if (ptr) *ptr = vptr;
+        break;
+      } else {
+        swig_cast_info *tc = SWIG_TypeCheck(to->name,ty);
+        if (!tc) {
+          sobj = (SwigPyObject *)sobj->next;
+        } else {
+          if (ptr) {
+            int newmemory = 0;
+            *ptr = SWIG_TypeCast(tc,vptr,&newmemory);
+            if (newmemory == SWIG_CAST_NEW_MEMORY) {
+              assert(own); /* badly formed typemap which will lead to a memory leak - it must set and use own to delete *ptr */
+              if (own)
+                *own = *own | SWIG_CAST_NEW_MEMORY;
+            }
+          }
+          break;
+        }
+      }
+    } else {
+      if (ptr) *ptr = vptr;
+      break;
+    }
+  }
+  if (sobj) {
+    if (own)
+      *own = *own | sobj->own;
+    if (flags & SWIG_POINTER_DISOWN) {
+      sobj->own = 0;
+    }
+    res = SWIG_OK;
+  } else {
+    if (implicit_conv) {
+      SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0;
+      if (data && !data->implicitconv) {
+        PyObject *klass = data->klass;
+        if (klass) {
+          PyObject *impconv;
+          data->implicitconv = 1; /* avoid recursion and call 'explicit' constructors*/
+          impconv = SWIG_Python_CallFunctor(klass, obj);
+          data->implicitconv = 0;
+          if (PyErr_Occurred()) {
+            PyErr_Clear();
+            impconv = 0;
+          }
+          if (impconv) {
+            SwigPyObject *iobj = SWIG_Python_GetSwigThis(impconv);
+            if (iobj) {
+              void *vptr;
+              res = SWIG_Python_ConvertPtrAndOwn((PyObject*)iobj, &vptr, ty, 0, 0);
+              if (SWIG_IsOK(res)) {
+                if (ptr) {
+                  *ptr = vptr;
+                  /* transfer the ownership to 'ptr' */
+                  iobj->own = 0;
+                  res = SWIG_AddCast(res);
+                  res = SWIG_AddNewMask(res);
+                } else {
+                  res = SWIG_AddCast(res);		    
+                }
+              }
+            }
+            Py_DECREF(impconv);
+          }
+        }
+      }
+    }
+    if (!SWIG_IsOK(res) && obj == Py_None) {
+      if (ptr)
+        *ptr = 0;
+      if (PyErr_Occurred())
+        PyErr_Clear();
+      res = SWIG_OK;
+    }
+  }
+  return res;
+}
+
+/* Convert a function ptr value */
+
+SWIGRUNTIME int
+SWIG_Python_ConvertFunctionPtr(PyObject *obj, void **ptr, swig_type_info *ty) {
+  if (!PyCFunction_Check(obj)) {
+    return SWIG_ConvertPtr(obj, ptr, ty, 0);
+  } else {
+    void *vptr = 0;
+    
+    /* here we get the method pointer for callbacks */
+    const char *doc = (((PyCFunctionObject *)obj) -> m_ml -> ml_doc);
+    const char *desc = doc ? strstr(doc, "swig_ptr: ") : 0;
+    if (desc)
+      desc = ty ? SWIG_UnpackVoidPtr(desc + 10, &vptr, ty->name) : 0;
+    if (!desc) 
+      return SWIG_ERROR;
+    if (ty) {
+      swig_cast_info *tc = SWIG_TypeCheck(desc,ty);
+      if (tc) {
+        int newmemory = 0;
+        *ptr = SWIG_TypeCast(tc,vptr,&newmemory);
+        assert(!newmemory); /* newmemory handling not yet implemented */
+      } else {
+        return SWIG_ERROR;
+      }
+    } else {
+      *ptr = vptr;
+    }
+    return SWIG_OK;
+  }
+}
+
+/* Convert a packed value value */
+
+SWIGRUNTIME int
+SWIG_Python_ConvertPacked(PyObject *obj, void *ptr, size_t sz, swig_type_info *ty) {
+  swig_type_info *to = SwigPyPacked_UnpackData(obj, ptr, sz);
+  if (!to) return SWIG_ERROR;
+  if (ty) {
+    if (to != ty) {
+      /* check type cast? */
+      swig_cast_info *tc = SWIG_TypeCheck(to->name,ty);
+      if (!tc) return SWIG_ERROR;
+    }
+  }
+  return SWIG_OK;
+}  
+
+/* -----------------------------------------------------------------------------
+ * Create a new pointer object
+ * ----------------------------------------------------------------------------- */
+
+/*
+  Create a new instance object, without calling __init__, and set the
+  'this' attribute.
+*/
+
+SWIGRUNTIME PyObject* 
+SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this)
+{
+#if (PY_VERSION_HEX >= 0x02020000)
+  PyObject *inst = 0;
+  PyObject *newraw = data->newraw;
+  if (newraw) {
+    inst = PyObject_Call(newraw, data->newargs, NULL);
+    if (inst) {
+#if !defined(SWIG_PYTHON_SLOW_GETSET_THIS)
+      PyObject **dictptr = _PyObject_GetDictPtr(inst);
+      if (dictptr != NULL) {
+	PyObject *dict = *dictptr;
+	if (dict == NULL) {
+	  dict = PyDict_New();
+	  *dictptr = dict;
+	  PyDict_SetItem(dict, SWIG_This(), swig_this);
+	}
+      }
+#else
+      PyObject *key = SWIG_This();
+      PyObject_SetAttr(inst, key, swig_this);
+#endif
+    }
+  } else {
+#if PY_VERSION_HEX >= 0x03000000
+    inst = PyBaseObject_Type.tp_new((PyTypeObject*) data->newargs, Py_None, Py_None);
+    if (inst) {
+      PyObject_SetAttr(inst, SWIG_This(), swig_this);
+      Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
+    }
+#else
+    PyObject *dict = PyDict_New();
+    if (dict) {
+      PyDict_SetItem(dict, SWIG_This(), swig_this);
+      inst = PyInstance_NewRaw(data->newargs, dict);
+      Py_DECREF(dict);
+    }
+#endif
+  }
+  return inst;
+#else
+#if (PY_VERSION_HEX >= 0x02010000)
+  PyObject *inst = 0;
+  PyObject *dict = PyDict_New();
+  if (dict) {
+    PyDict_SetItem(dict, SWIG_This(), swig_this);
+    inst = PyInstance_NewRaw(data->newargs, dict);
+    Py_DECREF(dict);
+  }
+  return (PyObject *) inst;
+#else
+  PyInstanceObject *inst = PyObject_NEW(PyInstanceObject, &PyInstance_Type);
+  if (inst == NULL) {
+    return NULL;
+  }
+  inst->in_class = (PyClassObject *)data->newargs;
+  Py_INCREF(inst->in_class);
+  inst->in_dict = PyDict_New();
+  if (inst->in_dict == NULL) {
+    Py_DECREF(inst);
+    return NULL;
+  }
+#ifdef Py_TPFLAGS_HAVE_WEAKREFS
+  inst->in_weakreflist = NULL;
+#endif
+#ifdef Py_TPFLAGS_GC
+  PyObject_GC_Init(inst);
+#endif
+  PyDict_SetItem(inst->in_dict, SWIG_This(), swig_this);
+  return (PyObject *) inst;
+#endif
+#endif
+}
+
+SWIGRUNTIME void
+SWIG_Python_SetSwigThis(PyObject *inst, PyObject *swig_this)
+{
+ PyObject *dict;
+#if (PY_VERSION_HEX >= 0x02020000) && !defined(SWIG_PYTHON_SLOW_GETSET_THIS)
+ PyObject **dictptr = _PyObject_GetDictPtr(inst);
+ if (dictptr != NULL) {
+   dict = *dictptr;
+   if (dict == NULL) {
+     dict = PyDict_New();
+     *dictptr = dict;
+   }
+   PyDict_SetItem(dict, SWIG_This(), swig_this);
+   return;
+ }
+#endif
+ dict = PyObject_GetAttrString(inst, (char*)"__dict__");
+ PyDict_SetItem(dict, SWIG_This(), swig_this);
+ Py_DECREF(dict);
+} 
+
+
+SWIGINTERN PyObject *
+SWIG_Python_InitShadowInstance(PyObject *args) {
+  PyObject *obj[2];
+  if (!SWIG_Python_UnpackTuple(args, "swiginit", 2, 2, obj)) {
+    return NULL;
+  } else {
+    SwigPyObject *sthis = SWIG_Python_GetSwigThis(obj[0]);
+    if (sthis) {
+      SwigPyObject_append((PyObject*) sthis, obj[1]);
+    } else {
+      SWIG_Python_SetSwigThis(obj[0], obj[1]);
+    }
+    return SWIG_Py_Void();
+  }
+}
+
+/* Create a new pointer object */
+
+SWIGRUNTIME PyObject *
+SWIG_Python_NewPointerObj(PyObject *self, void *ptr, swig_type_info *type, int flags) {
+  SwigPyClientData *clientdata;
+  PyObject * robj;
+  int own;
+
+  if (!ptr)
+    return SWIG_Py_Void();
+
+  clientdata = type ? (SwigPyClientData *)(type->clientdata) : 0;
+  own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0;
+  if (clientdata && clientdata->pytype) {
+    SwigPyObject *newobj;
+    if (flags & SWIG_BUILTIN_TP_INIT) {
+      newobj = (SwigPyObject*) self;
+      if (newobj->ptr) {
+        PyObject *next_self = clientdata->pytype->tp_alloc(clientdata->pytype, 0);
+        while (newobj->next)
+	  newobj = (SwigPyObject *) newobj->next;
+        newobj->next = next_self;
+        newobj = (SwigPyObject *)next_self;
+      }
+    } else {
+      newobj = PyObject_New(SwigPyObject, clientdata->pytype);
+    }
+    if (newobj) {
+      newobj->ptr = ptr;
+      newobj->ty = type;
+      newobj->own = own;
+      newobj->next = 0;
+#ifdef SWIGPYTHON_BUILTIN
+      newobj->dict = 0;
+#endif
+      return (PyObject*) newobj;
+    }
+    return SWIG_Py_Void();
+  }
+
+  assert(!(flags & SWIG_BUILTIN_TP_INIT));
+
+  robj = SwigPyObject_New(ptr, type, own);
+  if (robj && clientdata && !(flags & SWIG_POINTER_NOSHADOW)) {
+    PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj);
+    Py_DECREF(robj);
+    robj = inst;
+  }
+  return robj;
+}
+
+/* Create a new packed object */
+
+SWIGRUNTIMEINLINE PyObject *
+SWIG_Python_NewPackedObj(void *ptr, size_t sz, swig_type_info *type) {
+  return ptr ? SwigPyPacked_New((void *) ptr, sz, type) : SWIG_Py_Void();
+}
+
+/* -----------------------------------------------------------------------------*
+ *  Get type list 
+ * -----------------------------------------------------------------------------*/
+
+#ifdef SWIG_LINK_RUNTIME
+void *SWIG_ReturnGlobalTypeList(void *);
+#endif
+
+SWIGRUNTIME swig_module_info *
+SWIG_Python_GetModule(void *SWIGUNUSEDPARM(clientdata)) {
+  static void *type_pointer = (void *)0;
+  /* first check if module already created */
+  if (!type_pointer) {
+#ifdef SWIG_LINK_RUNTIME
+    type_pointer = SWIG_ReturnGlobalTypeList((void *)0);
+#else
+# ifdef SWIGPY_USE_CAPSULE
+    type_pointer = PyCapsule_Import(SWIGPY_CAPSULE_NAME, 0);
+# else
+    type_pointer = PyCObject_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
+				    (char*)"type_pointer" SWIG_TYPE_TABLE_NAME);
+# endif
+    if (PyErr_Occurred()) {
+      PyErr_Clear();
+      type_pointer = (void *)0;
+    }
+#endif
+  }
+  return (swig_module_info *) type_pointer;
+}
+
+#if PY_MAJOR_VERSION < 2
+/* PyModule_AddObject function was introduced in Python 2.0.  The following function
+   is copied out of Python/modsupport.c in python version 2.3.4 */
+SWIGINTERN int
+PyModule_AddObject(PyObject *m, char *name, PyObject *o)
+{
+  PyObject *dict;
+  if (!PyModule_Check(m)) {
+    PyErr_SetString(PyExc_TypeError,
+		    "PyModule_AddObject() needs module as first arg");
+    return SWIG_ERROR;
+  }
+  if (!o) {
+    PyErr_SetString(PyExc_TypeError,
+		    "PyModule_AddObject() needs non-NULL value");
+    return SWIG_ERROR;
+  }
+  
+  dict = PyModule_GetDict(m);
+  if (dict == NULL) {
+    /* Internal error -- modules must have a dict! */
+    PyErr_Format(PyExc_SystemError, "module '%s' has no __dict__",
+		 PyModule_GetName(m));
+    return SWIG_ERROR;
+  }
+  if (PyDict_SetItemString(dict, name, o))
+    return SWIG_ERROR;
+  Py_DECREF(o);
+  return SWIG_OK;
+}
+#endif
+
+SWIGRUNTIME void
+#ifdef SWIGPY_USE_CAPSULE
+SWIG_Python_DestroyModule(PyObject *obj)
+#else
+SWIG_Python_DestroyModule(void *vptr)
+#endif
+{
+#ifdef SWIGPY_USE_CAPSULE
+  swig_module_info *swig_module = (swig_module_info *) PyCapsule_GetPointer(obj, SWIGPY_CAPSULE_NAME);
+#else
+  swig_module_info *swig_module = (swig_module_info *) vptr;
+#endif
+  swig_type_info **types = swig_module->types;
+  size_t i;
+  for (i =0; i < swig_module->size; ++i) {
+    swig_type_info *ty = types[i];
+    if (ty->owndata) {
+      SwigPyClientData *data = (SwigPyClientData *) ty->clientdata;
+      if (data) SwigPyClientData_Del(data);
+    }
+  }
+  Py_DECREF(SWIG_This());
+  swig_this = NULL;
+}
+
+SWIGRUNTIME void
+SWIG_Python_SetModule(swig_module_info *swig_module) {
+#if PY_VERSION_HEX >= 0x03000000
+ /* Add a dummy module object into sys.modules */
+  PyObject *module = PyImport_AddModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION);
+#else
+  static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} }; /* Sentinel */
+  PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION, swig_empty_runtime_method_table);
+#endif
+#ifdef SWIGPY_USE_CAPSULE
+  PyObject *pointer = PyCapsule_New((void *) swig_module, SWIGPY_CAPSULE_NAME, SWIG_Python_DestroyModule);
+  if (pointer && module) {
+    PyModule_AddObject(module, (char*)"type_pointer_capsule" SWIG_TYPE_TABLE_NAME, pointer);
+  } else {
+    Py_XDECREF(pointer);
+  }
+#else
+  PyObject *pointer = PyCObject_FromVoidPtr((void *) swig_module, SWIG_Python_DestroyModule);
+  if (pointer && module) {
+    PyModule_AddObject(module, (char*)"type_pointer" SWIG_TYPE_TABLE_NAME, pointer);
+  } else {
+    Py_XDECREF(pointer);
+  }
+#endif
+}
+
+/* The python cached type query */
+SWIGRUNTIME PyObject *
+SWIG_Python_TypeCache(void) {
+  static PyObject *SWIG_STATIC_POINTER(cache) = PyDict_New();
+  return cache;
+}
+
+SWIGRUNTIME swig_type_info *
+SWIG_Python_TypeQuery(const char *type)
+{
+  PyObject *cache = SWIG_Python_TypeCache();
+  PyObject *key = SWIG_Python_str_FromChar(type); 
+  PyObject *obj = PyDict_GetItem(cache, key);
+  swig_type_info *descriptor;
+  if (obj) {
+#ifdef SWIGPY_USE_CAPSULE
+    descriptor = (swig_type_info *) PyCapsule_GetPointer(obj, NULL);
+#else
+    descriptor = (swig_type_info *) PyCObject_AsVoidPtr(obj);
+#endif
+  } else {
+    swig_module_info *swig_module = SWIG_GetModule(0);
+    descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type);
+    if (descriptor) {
+#ifdef SWIGPY_USE_CAPSULE
+      obj = PyCapsule_New((void*) descriptor, NULL, NULL);
+#else
+      obj = PyCObject_FromVoidPtr(descriptor, NULL);
+#endif
+      PyDict_SetItem(cache, key, obj);
+      Py_DECREF(obj);
+    }
+  }
+  Py_DECREF(key);
+  return descriptor;
+}
+
+/* 
+   For backward compatibility only
+*/
+#define SWIG_POINTER_EXCEPTION  0
+#define SWIG_arg_fail(arg)      SWIG_Python_ArgFail(arg)
+#define SWIG_MustGetPtr(p, type, argnum, flags)  SWIG_Python_MustGetPtr(p, type, argnum, flags)
+
+SWIGRUNTIME int
+SWIG_Python_AddErrMesg(const char* mesg, int infront)
+{  
+  if (PyErr_Occurred()) {
+    PyObject *type = 0;
+    PyObject *value = 0;
+    PyObject *traceback = 0;
+    PyErr_Fetch(&type, &value, &traceback);
+    if (value) {
+      char *tmp;
+      PyObject *old_str = PyObject_Str(value);
+      Py_XINCREF(type);
+      PyErr_Clear();
+      if (infront) {
+	PyErr_Format(type, "%s %s", mesg, tmp = SWIG_Python_str_AsChar(old_str));
+      } else {
+	PyErr_Format(type, "%s %s", tmp = SWIG_Python_str_AsChar(old_str), mesg);
+      }
+      SWIG_Python_str_DelForPy3(tmp);
+      Py_DECREF(old_str);
+    }
+    return 1;
+  } else {
+    return 0;
+  }
+}
+  
+SWIGRUNTIME int
+SWIG_Python_ArgFail(int argnum)
+{
+  if (PyErr_Occurred()) {
+    /* add information about failing argument */
+    char mesg[256];
+    PyOS_snprintf(mesg, sizeof(mesg), "argument number %d:", argnum);
+    return SWIG_Python_AddErrMesg(mesg, 1);
+  } else {
+    return 0;
+  }
+}
+
+SWIGRUNTIMEINLINE const char *
+SwigPyObject_GetDesc(PyObject *self)
+{
+  SwigPyObject *v = (SwigPyObject *)self;
+  swig_type_info *ty = v ? v->ty : 0;
+  return ty ? ty->str : "";
+}
+
+SWIGRUNTIME void
+SWIG_Python_TypeError(const char *type, PyObject *obj)
+{
+  if (type) {
+#if defined(SWIG_COBJECT_TYPES)
+    if (obj && SwigPyObject_Check(obj)) {
+      const char *otype = (const char *) SwigPyObject_GetDesc(obj);
+      if (otype) {
+	PyErr_Format(PyExc_TypeError, "a '%s' is expected, 'SwigPyObject(%s)' is received",
+		     type, otype);
+	return;
+      }
+    } else 
+#endif      
+    {
+      const char *otype = (obj ? obj->ob_type->tp_name : 0); 
+      if (otype) {
+	PyObject *str = PyObject_Str(obj);
+	const char *cstr = str ? SWIG_Python_str_AsChar(str) : 0;
+	if (cstr) {
+	  PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s(%s)' is received",
+		       type, otype, cstr);
+          SWIG_Python_str_DelForPy3(cstr);
+	} else {
+	  PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s' is received",
+		       type, otype);
+	}
+	Py_XDECREF(str);
+	return;
+      }
+    }   
+    PyErr_Format(PyExc_TypeError, "a '%s' is expected", type);
+  } else {
+    PyErr_Format(PyExc_TypeError, "unexpected type is received");
+  }
+}
+
+
+/* Convert a pointer value, signal an exception on a type mismatch */
+SWIGRUNTIME void *
+SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int SWIGUNUSEDPARM(argnum), int flags) {
+  void *result;
+  if (SWIG_Python_ConvertPtr(obj, &result, ty, flags) == -1) {
+    PyErr_Clear();
+#if SWIG_POINTER_EXCEPTION
+    if (flags) {
+      SWIG_Python_TypeError(SWIG_TypePrettyName(ty), obj);
+      SWIG_Python_ArgFail(argnum);
+    }
+#endif
+  }
+  return result;
+}
+
+#ifdef SWIGPYTHON_BUILTIN
+SWIGRUNTIME int
+SWIG_Python_NonDynamicSetAttr(PyObject *obj, PyObject *name, PyObject *value) {
+  PyTypeObject *tp = obj->ob_type;
+  PyObject *descr;
+  PyObject *encoded_name;
+  descrsetfunc f;
+  int res = -1;
+
+# ifdef Py_USING_UNICODE
+  if (PyString_Check(name)) {
+    name = PyUnicode_Decode(PyString_AsString(name), PyString_Size(name), NULL, NULL);
+    if (!name)
+      return -1;
+  } else if (!PyUnicode_Check(name))
+# else
+  if (!PyString_Check(name))
+# endif
+  {
+    PyErr_Format(PyExc_TypeError, "attribute name must be string, not '%.200s'", name->ob_type->tp_name);
+    return -1;
+  } else {
+    Py_INCREF(name);
+  }
+
+  if (!tp->tp_dict) {
+    if (PyType_Ready(tp) < 0)
+      goto done;
+  }
+
+  descr = _PyType_Lookup(tp, name);
+  f = NULL;
+  if (descr != NULL)
+    f = descr->ob_type->tp_descr_set;
+  if (!f) {
+    if (PyString_Check(name)) {
+      encoded_name = name;
+      Py_INCREF(name);
+    } else {
+      encoded_name = PyUnicode_AsUTF8String(name);
+    }
+    PyErr_Format(PyExc_AttributeError, "'%.100s' object has no attribute '%.200s'", tp->tp_name, PyString_AsString(encoded_name));
+    Py_DECREF(encoded_name);
+  } else {
+    res = f(descr, obj, value);
+  }
+  
+  done:
+  Py_DECREF(name);
+  return res;
+}
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+#define SWIG_exception_fail(code, msg) do { SWIG_Error(code, msg); SWIG_fail; } while(0) 
+
+#define SWIG_contract_assert(expr, msg) if (!(expr)) { SWIG_Error(SWIG_RuntimeError, msg); SWIG_fail; } else 
+
+
+
+  #define SWIG_exception(code, msg) do { SWIG_Error(code, msg); SWIG_fail;; } while(0) 
+
+
+/* -------- TYPES TABLE (BEGIN) -------- */
+
+#define SWIGTYPE_p_GDALMajorObjectShadow swig_types[0]
+#define SWIGTYPE_p_GIntBig swig_types[1]
+#define SWIGTYPE_p_GNMGenericNetworkShadow swig_types[2]
+#define SWIGTYPE_p_GNMGraphAlgorithmType swig_types[3]
+#define SWIGTYPE_p_GNMNetworkShadow swig_types[4]
+#define SWIGTYPE_p_OGRFeatureShadow swig_types[5]
+#define SWIGTYPE_p_OGRLayerShadow swig_types[6]
+#define SWIGTYPE_p_OGRwkbGeometryType swig_types[7]
+#define SWIGTYPE_p_OSRSpatialReferenceShadow swig_types[8]
+#define SWIGTYPE_p_char swig_types[9]
+#define SWIGTYPE_p_int swig_types[10]
+#define SWIGTYPE_p_p_char swig_types[11]
+static swig_type_info *swig_types[13];
+static swig_module_info swig_module = {swig_types, 12, 0, 0, 0, 0};
+#define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)
+#define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)
+
+/* -------- TYPES TABLE (END) -------- */
+
+#if (PY_VERSION_HEX <= 0x02000000)
+# if !defined(SWIG_PYTHON_CLASSIC)
+#  error "This python version requires swig to be run with the '-classic' option"
+# endif
+#endif
+
+/*-----------------------------------------------
+              @(target):= _gnm.so
+  ------------------------------------------------*/
+#if PY_VERSION_HEX >= 0x03000000
+#  define SWIG_init    PyInit__gnm
+
+#else
+#  define SWIG_init    init_gnm
+
+#endif
+#define SWIG_name    "_gnm"
+
+#define SWIGVERSION 0x020012 
+#define SWIG_VERSION SWIGVERSION
+
+
+#define SWIG_as_voidptr(a) const_cast< void * >(static_cast< const void * >(a)) 
+#define SWIG_as_voidptrptr(a) ((void)SWIG_as_voidptr(*a),reinterpret_cast< void** >(a)) 
+
+
+#include <stdexcept>
+
+
+namespace swig {
+  class SwigPtr_PyObject {
+  protected:
+    PyObject *_obj;
+
+  public:
+    SwigPtr_PyObject() :_obj(0)
+    {
+    }
+
+    SwigPtr_PyObject(const SwigPtr_PyObject& item) : _obj(item._obj)
+    {
+      Py_XINCREF(_obj);      
+    }
+    
+    SwigPtr_PyObject(PyObject *obj, bool initial_ref = true) :_obj(obj)
+    {
+      if (initial_ref) {
+        Py_XINCREF(_obj);
+      }
+    }
+    
+    SwigPtr_PyObject & operator=(const SwigPtr_PyObject& item) 
+    {
+      Py_XINCREF(item._obj);
+      Py_XDECREF(_obj);
+      _obj = item._obj;
+      return *this;      
+    }
+    
+    ~SwigPtr_PyObject() 
+    {
+      Py_XDECREF(_obj);
+    }
+    
+    operator PyObject *() const
+    {
+      return _obj;
+    }
+
+    PyObject *operator->() const
+    {
+      return _obj;
+    }
+  };
+}
+
+
+namespace swig {
+  struct SwigVar_PyObject : SwigPtr_PyObject {
+    SwigVar_PyObject(PyObject* obj = 0) : SwigPtr_PyObject(obj, false) { }
+    
+    SwigVar_PyObject & operator = (PyObject* obj)
+    {
+      Py_XDECREF(_obj);
+      _obj = obj;
+      return *this;      
+    }
+  };
+}
+
+
+#include "gdal.h"
+#include "gnm_api.h"
+
+typedef void GDALMajorObjectShadow;
+typedef void GNMNetworkShadow;
+typedef void GNMGenericNetworkShadow;
+
+
+#ifdef DEBUG
+typedef struct OGRLayerHS OGRLayerShadow;
+typedef struct OGRFeatureHS OGRFeatureShadow;
+typedef struct OGRSpatialReferenceHS OSRSpatialReferenceShadow;
+#else
+typedef void OGRLayerShadow;
+typedef void OGRFeatureShadow;
+typedef void OSRSpatialReferenceShadow;
+#endif
+
+
+static int bUseExceptions=0;
+static CPLErrorHandler pfnPreviousHandler = CPLDefaultErrorHandler;
+
+static void CPL_STDCALL
+PythonBindingErrorHandler(CPLErr eclass, int code, const char *msg )
+{
+  /*
+  ** Generally we want to suppress error reporting if we have exceptions
+  ** enabled as the error message will be in the exception thrown in
+  ** Python.
+  */
+
+  /* If the error class is CE_Fatal, we want to have a message issued
+     because the CPL support code does an abort() before any exception
+     can be generated */
+  if (eclass == CE_Fatal ) {
+    pfnPreviousHandler(eclass, code, msg );
+  }
+
+  /*
+  ** We do not want to interfere with warnings or debug messages since
+  ** they won't be translated into exceptions.
+  */
+  if (eclass == CE_Warning || eclass == CE_Debug ) {
+    pfnPreviousHandler(eclass, code, msg );
+  }
+}
+
+
+
+static
+int GetUseExceptions() {
+  CPLErrorReset();
+  return bUseExceptions;
+}
+
+static
+void UseExceptions() {
+  CPLErrorReset();
+  if( !bUseExceptions )
+  {
+    bUseExceptions = 1;
+    pfnPreviousHandler =
+        CPLSetErrorHandler( (CPLErrorHandler) PythonBindingErrorHandler );
+  }
+}
+
+static
+void DontUseExceptions() {
+  CPLErrorReset();
+  if( bUseExceptions )
+  {
+    bUseExceptions = 0;
+    CPLSetErrorHandler( pfnPreviousHandler );
+  }
+}
+
+
+SWIGINTERNINLINE PyObject*
+  SWIG_From_int  (int value)
+{
+  return PyInt_FromLong((long) value);
+}
+
+
+/* Completely unrelated: just to avoid Coverity warnings */
+
+static int bReturnSame = 1;
+
+void NeverCallMePlease() {
+    bReturnSame = 0;
+}
+
+/* Some SWIG code generates dead code, which Coverity warns about */
+template<class T> static T ReturnSame(T x)
+{
+    if( bReturnSame )
+        return x;
+    return 0;
+}
+
+
+
+
+/* Return a PyObject* from a NULL terminated C String */
+static PyObject* GDALPythonObjectFromCStr(const char *pszStr)
+{
+  const unsigned char* pszIter = (const unsigned char*) pszStr;
+  while(*pszIter != 0)
+  {
+    if (*pszIter > 127)
+    {
+        PyObject* pyObj = PyUnicode_DecodeUTF8(pszStr, strlen(pszStr), "ignore");
+        if (pyObj != NULL)
+            return pyObj;
+#if PY_VERSION_HEX >= 0x03000000
+        return PyBytes_FromString(pszStr);
+#else
+        return PyString_FromString(pszStr);
+#endif
+    }
+    pszIter ++;
+  }
+#if PY_VERSION_HEX >= 0x03000000
+  return PyUnicode_FromString(pszStr);
+#else
+  return PyString_FromString(pszStr);
+#endif
+}
+
+/* Return a NULL terminated c String from a PyObject */
+/* Result must be freed with GDALPythonFreeCStr */
+static char* GDALPythonObjectToCStr(PyObject* pyObject, int* pbToFree)
+{
+  *pbToFree = 0;
+  if (PyUnicode_Check(pyObject))
+  {
+      char *pszStr;
+      char *pszNewStr;
+      Py_ssize_t nLen;
+      PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObject);
+#if PY_VERSION_HEX >= 0x03000000
+      PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+      PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+      pszNewStr = (char *) malloc(nLen+1);
+      memcpy(pszNewStr, pszStr, nLen+1);
+      Py_XDECREF(pyUTF8Str);
+      *pbToFree = 1;
+      return pszNewStr;
+  }
+  else
+  {
+#if PY_VERSION_HEX >= 0x03000000
+      return PyBytes_AsString(pyObject);
+#else
+      return PyString_AsString(pyObject);
+#endif
+  }
+}
+
+static void GDALPythonFreeCStr(void* ptr, int bToFree)
+{
+   if (bToFree)
+       free(ptr);
+}
+
+
+SWIGINTERN char const *GDALMajorObjectShadow_GetDescription(GDALMajorObjectShadow *self){
+    return GDALGetDescription( self );
+  }
+
+SWIGINTERN swig_type_info*
+SWIG_pchar_descriptor(void)
+{
+  static int init = 0;
+  static swig_type_info* info = 0;
+  if (!init) {
+    info = SWIG_TypeQuery("_p_char");
+    init = 1;
+  }
+  return info;
+}
+
+
+SWIGINTERNINLINE PyObject *
+SWIG_FromCharPtrAndSize(const char* carray, size_t size)
+{
+  if (carray) {
+    if (size > INT_MAX) {
+      swig_type_info* pchar_descriptor = SWIG_pchar_descriptor();
+      return pchar_descriptor ? 
+	SWIG_InternalNewPointerObj(const_cast< char * >(carray), pchar_descriptor, 0) : SWIG_Py_Void();
+    } else {
+#if PY_VERSION_HEX >= 0x03000000
+      return PyUnicode_FromStringAndSize(carray, static_cast< int >(size));
+#else
+      return PyString_FromStringAndSize(carray, static_cast< int >(size));
+#endif
+    }
+  } else {
+    return SWIG_Py_Void();
+  }
+}
+
+
+SWIGINTERNINLINE PyObject * 
+SWIG_FromCharPtr(const char *cptr)
+{ 
+  return SWIG_FromCharPtrAndSize(cptr, (cptr ? strlen(cptr) : 0));
+}
+
+
+SWIGINTERN int
+SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc)
+{
+#if PY_VERSION_HEX>=0x03000000
+  if (PyUnicode_Check(obj))
+#else  
+  if (PyString_Check(obj))
+#endif
+  {
+    char *cstr; Py_ssize_t len;
+#if PY_VERSION_HEX>=0x03000000
+    if (!alloc && cptr) {
+        /* We can't allow converting without allocation, since the internal
+           representation of string in Python 3 is UCS-2/UCS-4 but we require
+           a UTF-8 representation.
+           TODO(bhy) More detailed explanation */
+        return SWIG_RuntimeError;
+    }
+    obj = PyUnicode_AsUTF8String(obj);
+    PyBytes_AsStringAndSize(obj, &cstr, &len);
+    if(alloc) *alloc = SWIG_NEWOBJ;
+#else
+    PyString_AsStringAndSize(obj, &cstr, &len);
+#endif
+    if (cptr) {
+      if (alloc) {
+	/* 
+	   In python the user should not be able to modify the inner
+	   string representation. To warranty that, if you define
+	   SWIG_PYTHON_SAFE_CSTRINGS, a new/copy of the python string
+	   buffer is always returned.
+
+	   The default behavior is just to return the pointer value,
+	   so, be careful.
+	*/ 
+#if defined(SWIG_PYTHON_SAFE_CSTRINGS)
+	if (*alloc != SWIG_OLDOBJ) 
+#else
+	if (*alloc == SWIG_NEWOBJ) 
+#endif
+	  {
+	    *cptr = reinterpret_cast< char* >(memcpy((new char[len + 1]), cstr, sizeof(char)*(len + 1)));
+	    *alloc = SWIG_NEWOBJ;
+	  }
+	else {
+	  *cptr = cstr;
+	  *alloc = SWIG_OLDOBJ;
+	}
+      } else {
+        #if PY_VERSION_HEX>=0x03000000
+        assert(0); /* Should never reach here in Python 3 */
+        #endif
+	*cptr = SWIG_Python_str_AsChar(obj);
+      }
+    }
+    if (psize) *psize = len + 1;
+#if PY_VERSION_HEX>=0x03000000
+    Py_XDECREF(obj);
+#endif
+    return SWIG_OK;
+  } else {
+    swig_type_info* pchar_descriptor = SWIG_pchar_descriptor();
+    if (pchar_descriptor) {
+      void* vptr = 0;
+      if (SWIG_ConvertPtr(obj, &vptr, pchar_descriptor, 0) == SWIG_OK) {
+	if (cptr) *cptr = (char *) vptr;
+	if (psize) *psize = vptr ? (strlen((char *)vptr) + 1) : 0;
+	if (alloc) *alloc = SWIG_OLDOBJ;
+	return SWIG_OK;
+      }
+    }
+  }
+  return SWIG_TypeError;
+}
+
+
+
+
+SWIGINTERN void GDALMajorObjectShadow_SetDescription(GDALMajorObjectShadow *self,char const *pszNewDesc){
+    GDALSetDescription( self, pszNewDesc );
+  }
+SWIGINTERN char **GDALMajorObjectShadow_GetMetadataDomainList(GDALMajorObjectShadow *self){
+    return GDALGetMetadataDomainList( self );
+  }
+SWIGINTERN char **GDALMajorObjectShadow_GetMetadata_Dict(GDALMajorObjectShadow *self,char const *pszDomain=""){
+    return GDALGetMetadata( self, pszDomain );
+  }
+SWIGINTERN char **GDALMajorObjectShadow_GetMetadata_List(GDALMajorObjectShadow *self,char const *pszDomain=""){
+    return GDALGetMetadata( self, pszDomain );
+  }
+SWIGINTERN CPLErr GDALMajorObjectShadow_SetMetadata__SWIG_0(GDALMajorObjectShadow *self,char **papszMetadata,char const *pszDomain=""){
+    return GDALSetMetadata( self, papszMetadata, pszDomain );
+  }
+SWIGINTERN CPLErr GDALMajorObjectShadow_SetMetadata__SWIG_1(GDALMajorObjectShadow *self,char *pszMetadataString,char const *pszDomain=""){
+    char *tmpList[2];
+    tmpList[0] = pszMetadataString;
+    tmpList[1] = 0;
+    return GDALSetMetadata( self, tmpList, pszDomain );
+  }
+SWIGINTERN char const *GDALMajorObjectShadow_GetMetadataItem(GDALMajorObjectShadow *self,char const *pszName,char const *pszDomain=""){
+    return GDALGetMetadataItem( self, pszName, pszDomain);
+  }
+SWIGINTERN CPLErr GDALMajorObjectShadow_SetMetadataItem(GDALMajorObjectShadow *self,char const *pszName,char const *pszValue,char const *pszDomain=""){
+    return GDALSetMetadataItem( self, pszName, pszValue, pszDomain);
+  }
+
+  GNMNetworkShadow* CastToNetwork(GDALMajorObjectShadow* base) {
+      return (GNMNetworkShadow*)dynamic_cast<GNMNetwork*>((GDALMajorObject*)base);
+  }
+
+
+  GNMGenericNetworkShadow* CastToGenericNetwork(GDALMajorObjectShadow* base) {
+      return (GNMGenericNetworkShadow*)dynamic_cast<GNMGenericNetwork*>((GDALMajorObject*)base);
+  }
+
+
+typedef char retStringAndCPLFree;
+
+SWIGINTERN void delete_GNMNetworkShadow(GNMNetworkShadow *self){
+            if ( GDALDereferenceDataset( self ) <= 0 ) {
+              GDALClose(self);
+            }
+        }
+SWIGINTERN void GNMNetworkShadow_ReleaseResultSet(GNMNetworkShadow *self,OGRLayerShadow *layer){
+            GDALDatasetReleaseResultSet(self, layer);
+        }
+SWIGINTERN int GNMNetworkShadow_GetVersion(GNMNetworkShadow *self){
+            return GNMGetVersion(self);
+        }
+SWIGINTERN char const *GNMNetworkShadow_GetName(GNMNetworkShadow *self){
+            return GNMGetName(self);
+        }
+SWIGINTERN OGRFeatureShadow *GNMNetworkShadow_GetFeatureByGlobalFID(GNMNetworkShadow *self,GIntBig GFID){
+            return GNMGetFeatureByGlobalFID(self, GFID);
+        }
+
+#include <limits.h>
+#if !defined(SWIG_NO_LLONG_MAX)
+# if !defined(LLONG_MAX) && defined(__GNUC__) && defined (__LONG_LONG_MAX__)
+#   define LLONG_MAX __LONG_LONG_MAX__
+#   define LLONG_MIN (-LLONG_MAX - 1LL)
+#   define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL)
+# endif
+#endif
+
+
+SWIGINTERN int
+SWIG_AsVal_double (PyObject *obj, double *val)
+{
+  int res = SWIG_TypeError;
+  if (PyFloat_Check(obj)) {
+    if (val) *val = PyFloat_AsDouble(obj);
+    return SWIG_OK;
+  } else if (PyInt_Check(obj)) {
+    if (val) *val = PyInt_AsLong(obj);
+    return SWIG_OK;
+  } else if (PyLong_Check(obj)) {
+    double v = PyLong_AsDouble(obj);
+    if (!PyErr_Occurred()) {
+      if (val) *val = v;
+      return SWIG_OK;
+    } else {
+      PyErr_Clear();
+    }
+  }
+#ifdef SWIG_PYTHON_CAST_MODE
+  {
+    int dispatch = 0;
+    double d = PyFloat_AsDouble(obj);
+    if (!PyErr_Occurred()) {
+      if (val) *val = d;
+      return SWIG_AddCast(SWIG_OK);
+    } else {
+      PyErr_Clear();
+    }
+    if (!dispatch) {
+      long v = PyLong_AsLong(obj);
+      if (!PyErr_Occurred()) {
+	if (val) *val = v;
+	return SWIG_AddCast(SWIG_AddCast(SWIG_OK));
+      } else {
+	PyErr_Clear();
+      }
+    }
+  }
+#endif
+  return res;
+}
+
+
+#include <float.h>
+
+
+#include <math.h>
+
+
+SWIGINTERNINLINE int
+SWIG_CanCastAsInteger(double *d, double min, double max) {
+  double x = *d;
+  if ((min <= x && x <= max)) {
+   double fx = floor(x);
+   double cx = ceil(x);
+   double rd =  ((x - fx) < 0.5) ? fx : cx; /* simple rint */
+   if ((errno == EDOM) || (errno == ERANGE)) {
+     errno = 0;
+   } else {
+     double summ, reps, diff;
+     if (rd < x) {
+       diff = x - rd;
+     } else if (rd > x) {
+       diff = rd - x;
+     } else {
+       return 1;
+     }
+     summ = rd + x;
+     reps = diff/summ;
+     if (reps < 8*DBL_EPSILON) {
+       *d = rd;
+       return 1;
+     }
+   }
+  }
+  return 0;
+}
+
+
+SWIGINTERN int
+SWIG_AsVal_long (PyObject *obj, long* val)
+{
+  if (PyInt_Check(obj)) {
+    if (val) *val = PyInt_AsLong(obj);
+    return SWIG_OK;
+  } else if (PyLong_Check(obj)) {
+    long v = PyLong_AsLong(obj);
+    if (!PyErr_Occurred()) {
+      if (val) *val = v;
+      return SWIG_OK;
+    } else {
+      PyErr_Clear();
+    }
+  }
+#ifdef SWIG_PYTHON_CAST_MODE
+  {
+    int dispatch = 0;
+    long v = PyInt_AsLong(obj);
+    if (!PyErr_Occurred()) {
+      if (val) *val = v;
+      return SWIG_AddCast(SWIG_OK);
+    } else {
+      PyErr_Clear();
+    }
+    if (!dispatch) {
+      double d;
+      int res = SWIG_AddCast(SWIG_AsVal_double (obj,&d));
+      if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LONG_MIN, LONG_MAX)) {
+	if (val) *val = (long)(d);
+	return res;
+      }
+    }
+  }
+#endif
+  return SWIG_TypeError;
+}
+
+
+SWIGINTERN int
+SWIG_AsVal_int (PyObject * obj, int *val)
+{
+  long v;
+  int res = SWIG_AsVal_long (obj, &v);
+  if (SWIG_IsOK(res)) {
+    if ((v < INT_MIN || v > INT_MAX)) {
+      return SWIG_OverflowError;
+    } else {
+      if (val) *val = static_cast< int >(v);
+    }
+  }  
+  return res;
+}
+
+SWIGINTERN OGRLayerShadow *GNMNetworkShadow_GetPath(GNMNetworkShadow *self,GIntBig nStartFID,GIntBig nEndFID,GNMGraphAlgorithmType eAlgorithm,char **options=0){
+            return GNMGetPath(self, nStartFID, nEndFID, eAlgorithm, options);
+        }
+SWIGINTERN CPLErr GNMNetworkShadow_DisconnectAll(GNMNetworkShadow *self){
+            return GNMDisconnectAll( self );
+        }
+SWIGINTERN char const *GNMNetworkShadow_GetProjection(GNMNetworkShadow *self){
+            return GDALGetProjectionRef( self );
+        }
+SWIGINTERN char const *GNMNetworkShadow_GetProjectionRef(GNMNetworkShadow *self){
+            return GDALGetProjectionRef( self );
+        }
+SWIGINTERN char **GNMNetworkShadow_GetFileList(GNMNetworkShadow *self){
+            return GDALGetFileList( self );
+        }
+SWIGINTERN OGRLayerShadow *GNMNetworkShadow_CreateLayer(GNMNetworkShadow *self,char const *name,OSRSpatialReferenceShadow *srs=NULL,OGRwkbGeometryType geom_type=wkbUnknown,char **options=0){
+            OGRLayerShadow* layer = (OGRLayerShadow*) GDALDatasetCreateLayer( self,
+                                      name,
+                                      srs,
+                                      geom_type,
+                                      options);
+            return layer;
+        }
+SWIGINTERN OGRLayerShadow *GNMNetworkShadow_CopyLayer(GNMNetworkShadow *self,OGRLayerShadow *src_layer,char const *new_name,char **options=0){
+            OGRLayerShadow* layer = (OGRLayerShadow*) GDALDatasetCopyLayer( self,
+                                                      src_layer,
+                                                      new_name,
+                                                      options);
+            return layer;
+        }
+SWIGINTERN OGRErr GNMNetworkShadow_DeleteLayer(GNMNetworkShadow *self,int index){
+            return GDALDatasetDeleteLayer(self, index);
+        }
+
+
+#include "ogr_core.h"
+static char const *
+OGRErrMessages( int rc ) {
+  switch( rc ) {
+  case OGRERR_NONE:
+    return "OGR Error: None";
+  case OGRERR_NOT_ENOUGH_DATA:
+    return "OGR Error: Not enough data to deserialize";
+  case OGRERR_NOT_ENOUGH_MEMORY:
+    return "OGR Error: Not enough memory";
+  case OGRERR_UNSUPPORTED_GEOMETRY_TYPE:
+    return "OGR Error: Unsupported geometry type";
+  case OGRERR_UNSUPPORTED_OPERATION:
+    return "OGR Error: Unsupported operation";
+  case OGRERR_CORRUPT_DATA:
+    return "OGR Error: Corrupt data";
+  case OGRERR_FAILURE:
+    return "OGR Error: General Error";
+  case OGRERR_UNSUPPORTED_SRS:
+    return "OGR Error: Unsupported SRS";
+  case OGRERR_INVALID_HANDLE:
+    return "OGR Error: Invalid handle";
+  case OGRERR_NON_EXISTING_FEATURE:
+    return "OGR Error: Non existing feature";
+  default:
+    return "OGR Error: Unknown";
+  }
+}
+
+SWIGINTERN int GNMNetworkShadow_GetLayerCount(GNMNetworkShadow *self){
+            return GDALDatasetGetLayerCount(self);
+        }
+SWIGINTERN OGRLayerShadow *GNMNetworkShadow_GetLayerByIndex(GNMNetworkShadow *self,int index=0){
+        
+        OGRLayerShadow* layer = (OGRLayerShadow*) GDALDatasetGetLayer(self,
+                                                                      index);
+            return layer;
+        }
+SWIGINTERN OGRLayerShadow *GNMNetworkShadow_GetLayerByName(GNMNetworkShadow *self,char const *layer_name){
+            OGRLayerShadow* layer =
+                  (OGRLayerShadow*) GDALDatasetGetLayerByName(self, layer_name);
+            return layer;
+        }
+SWIGINTERN bool GNMNetworkShadow_TestCapability(GNMNetworkShadow *self,char const *cap){
+            return (GDALDatasetTestCapability(self, cap) > 0);
+        }
+
+SWIGINTERNINLINE PyObject*
+  SWIG_From_bool  (bool value)
+{
+  return PyBool_FromLong(value ? 1 : 0);
+}
+
+SWIGINTERN OGRErr GNMNetworkShadow_StartTransaction(GNMNetworkShadow *self,int force=FALSE){
+            return GDALDatasetStartTransaction(self, force);
+        }
+SWIGINTERN OGRErr GNMNetworkShadow_CommitTransaction(GNMNetworkShadow *self){
+            return GDALDatasetCommitTransaction(self);
+        }
+SWIGINTERN OGRErr GNMNetworkShadow_RollbackTransaction(GNMNetworkShadow *self){
+            return GDALDatasetRollbackTransaction(self);
+        }
+SWIGINTERN void delete_GNMGenericNetworkShadow(GNMGenericNetworkShadow *self){
+            if ( GDALDereferenceDataset( self ) <= 0 ) {
+              GDALClose(self);
+            }
+        }
+SWIGINTERN CPLErr GNMGenericNetworkShadow_ConnectFeatures(GNMGenericNetworkShadow *self,GIntBig nSrcFID,GIntBig nTgtFID,GIntBig nConFID,double dfCost,double dfInvCost,GNMDirection eDir){
+            return GNMConnectFeatures(self, nSrcFID, nTgtFID,
+                                              nConFID, dfCost, dfInvCost, eDir);
+        }
+SWIGINTERN CPLErr GNMGenericNetworkShadow_DisconnectFeatures(GNMGenericNetworkShadow *self,GIntBig nSrcFID,GIntBig nTgtFID,GIntBig nConFID){
+            return GNMDisconnectFeatures(self, nSrcFID, nTgtFID,
+                                                           nConFID);
+        }
+SWIGINTERN CPLErr GNMGenericNetworkShadow_DisconnectFeaturesWithId(GNMGenericNetworkShadow *self,GIntBig nFID){
+            return GNMDisconnectFeaturesWithId(self, nFID);
+        }
+SWIGINTERN CPLErr GNMGenericNetworkShadow_ReconnectFeatures(GNMGenericNetworkShadow *self,GIntBig nSrcFID,GIntBig nTgtFID,GIntBig nConFID,double dfCost,double dfInvCost,GNMDirection eDir){
+            return GNMReconnectFeatures(self, nSrcFID, nTgtFID, nConFID, dfCost, dfInvCost, eDir);
+        }
+SWIGINTERN CPLErr GNMGenericNetworkShadow_CreateRule(GNMGenericNetworkShadow *self,char const *pszRuleStr){
+            return GNMCreateRule(self, pszRuleStr);
+        }
+SWIGINTERN CPLErr GNMGenericNetworkShadow_DeleteAllRules(GNMGenericNetworkShadow *self){
+            return GNMDeleteAllRules(self);
+        }
+SWIGINTERN CPLErr GNMGenericNetworkShadow_DeleteRule(GNMGenericNetworkShadow *self,char const *pszRuleStr){
+            return GNMDeleteRule(self, pszRuleStr);
+        }
+SWIGINTERN char **GNMGenericNetworkShadow_GetRules(GNMGenericNetworkShadow *self){
+            return GNMGetRules(self);
+        }
+SWIGINTERN CPLErr GNMGenericNetworkShadow_ConnectPointsByLines(GNMGenericNetworkShadow *self,char **papszLayerList,double dfTolerance,double dfCost,double dfInvCost,GNMDirection eDir){
+            return GNMConnectPointsByLines(self, papszLayerList, dfTolerance, dfCost, dfInvCost, eDir);
+        }
+
+SWIGINTERN int
+SWIG_AsVal_bool (PyObject *obj, bool *val)
+{
+  int r = PyObject_IsTrue(obj);
+  if (r == -1)
+    return SWIG_ERROR;
+  if (val) *val = r ? true : false;
+  return SWIG_OK;
+}
+
+SWIGINTERN CPLErr GNMGenericNetworkShadow_ChangeBlockState(GNMGenericNetworkShadow *self,GIntBig nFID,bool bIsBlock){
+            return GNMChangeBlockState(self, nFID, bIsBlock);
+        }
+SWIGINTERN CPLErr GNMGenericNetworkShadow_ChangeAllBlockState(GNMGenericNetworkShadow *self,bool bIsBlock=false){
+            return GNMChangeAllBlockState(self, bIsBlock);
+        }
+#ifdef __cplusplus
+extern "C" {
+#endif
+SWIGINTERN PyObject *_wrap_GetUseExceptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)":GetUseExceptions")) SWIG_fail;
+  result = (int)GetUseExceptions();
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_UseExceptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  
+  if (!PyArg_ParseTuple(args,(char *)":UseExceptions")) SWIG_fail;
+  UseExceptions();
+  resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_DontUseExceptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  
+  if (!PyArg_ParseTuple(args,(char *)":DontUseExceptions")) SWIG_fail;
+  DontUseExceptions();
+  resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_MajorObject_GetDescription(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  char *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:MajorObject_GetDescription",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_GetDescription" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (char *)GDALMajorObjectShadow_GetDescription(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_MajorObject_SetDescription(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:MajorObject_SetDescription",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_SetDescription" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "MajorObject_SetDescription" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    GDALMajorObjectShadow_SetDescription(arg1,(char const *)arg2);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_Py_Void();
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_MajorObject_GetMetadataDomainList(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  char **result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:MajorObject_GetMetadataDomainList",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_GetMetadataDomainList" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (char **)GDALMajorObjectShadow_GetMetadataDomainList(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  {
+    /* %typemap(out) char **CSL -> ( string ) */
+    char **stringarray = result;
+    if ( stringarray == NULL ) {
+      resultobj = Py_None;
+      Py_INCREF( resultobj );
+    }
+    else {
+      int len = CSLCount( stringarray );
+      resultobj = PyList_New( len );
+      for ( int i = 0; i < len; ++i ) {
+        PyObject *o = GDALPythonObjectFromCStr( stringarray[i] );
+        PyList_SetItem(resultobj, i, o );
+      }
+    }
+    CSLDestroy(result);
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_MajorObject_GetMetadata_Dict(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
+  char *arg2 = (char *) "" ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  char **result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O|O:MajorObject_GetMetadata_Dict",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_GetMetadata_Dict" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
+  if (obj1) {
+    res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "MajorObject_GetMetadata_Dict" "', argument " "2"" of type '" "char const *""'");
+    }
+    arg2 = reinterpret_cast< char * >(buf2);
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (char **)GDALMajorObjectShadow_GetMetadata_Dict(arg1,(char const *)arg2);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  {
+    /* %typemap(out) char **dict */
+    char **stringarray = result;
+    resultobj = PyDict_New();
+    if ( stringarray != NULL ) {
+      while (*stringarray != NULL ) {
+        char const *valptr;
+        char *keyptr;
+        const char* pszSep = strchr( *stringarray, '=' );
+        if ( pszSep != NULL) {
+          keyptr = CPLStrdup(*stringarray);
+          keyptr[pszSep - *stringarray] = '\0';
+          valptr = pszSep + 1;
+          PyObject *nm = GDALPythonObjectFromCStr( keyptr );
+          PyObject *val = GDALPythonObjectFromCStr( valptr );
+          PyDict_SetItem(resultobj, nm, val );
+          Py_DECREF(nm);
+          Py_DECREF(val);
+          CPLFree( keyptr );
+        }
+        stringarray++;
+      }
+    }
+  }
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_MajorObject_GetMetadata_List(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
+  char *arg2 = (char *) "" ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  char **result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O|O:MajorObject_GetMetadata_List",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_GetMetadata_List" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
+  if (obj1) {
+    res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "MajorObject_GetMetadata_List" "', argument " "2"" of type '" "char const *""'");
+    }
+    arg2 = reinterpret_cast< char * >(buf2);
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (char **)GDALMajorObjectShadow_GetMetadata_List(arg1,(char const *)arg2);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  {
+    /* %typemap(out) char **options -> ( string ) */
+    char **stringarray = result;
+    if ( stringarray == NULL ) {
+      resultobj = Py_None;
+      Py_INCREF( resultobj );
+    }
+    else {
+      int len = CSLCount( stringarray );
+      resultobj = PyList_New( len );
+      for ( int i = 0; i < len; ++i ) {
+        PyObject *o = GDALPythonObjectFromCStr( stringarray[i] );
+        PyList_SetItem(resultobj, i, o );
+      }
+    }
+  }
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
+  char **arg2 = (char **) 0 ;
+  char *arg3 = (char *) "" ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res3 ;
+  char *buf3 = 0 ;
+  int alloc3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  CPLErr result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO|O:MajorObject_SetMetadata",&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_SetMetadata" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
+  {
+    /* %typemap(in) char **dict */
+    arg2 = NULL;
+    if ( PySequence_Check( obj1 ) ) {
+      Py_ssize_t size = PySequence_Size(obj1);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
+        PyObject* pyObj = PySequence_GetItem(obj1,i);
+        int bFreeStr;
+        char* pszStr = GDALPythonObjectToCStr(pyObj, &bFreeStr);
+        if ( pszStr == NULL ) {
+          Py_DECREF(pyObj);
+          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+          SWIG_fail;
+        }
+        arg2 = CSLAddString( arg2, pszStr );
+        GDALPythonFreeCStr(pszStr, bFreeStr);
+        Py_DECREF(pyObj);
+      }
+    }
+    else if ( PyMapping_Check( obj1 ) ) {
+      /* We need to use the dictionary form. */
+      Py_ssize_t size = PyMapping_Length( obj1 );
+      if ( size > 0 && size == (int)size) {
+        PyObject *item_list = PyMapping_Items( obj1 );
+        for( int i=0; i<(int)size; i++ ) {
+          PyObject *it = PySequence_GetItem( item_list, i );
+          
+          PyObject *k, *v;
+          if ( ! PyArg_ParseTuple( it, "OO", &k, &v ) ) {
+            Py_DECREF(it);
+            PyErr_SetString(PyExc_TypeError,"Dictionary must contain tuples of strings");
+            SWIG_fail;
+          }
+          
+          int bFreeK, bFreeV;
+          char* pszK = GDALPythonObjectToCStr(k, &bFreeK);
+          char* pszV = GDALPythonObjectToCStr(v, &bFreeV);
+          if( pszK == NULL || pszV == NULL )
+          {
+            GDALPythonFreeCStr(pszK, bFreeK);
+            GDALPythonFreeCStr(pszV, bFreeV);
+            Py_DECREF(it);
+            PyErr_SetString(PyExc_TypeError,"Dictionary must contain tuples of strings");
+            SWIG_fail;
+          }
+          arg2 = CSLAddNameValue( arg2, pszK, pszV );
+          
+          GDALPythonFreeCStr(pszK, bFreeK);
+          GDALPythonFreeCStr(pszV, bFreeV);
+          Py_DECREF(it);
+        }
+        Py_DECREF(item_list);
+      }
+    }
+    else {
+      PyErr_SetString(PyExc_TypeError,"Argument must be dictionary or sequence of strings");
+      SWIG_fail;
+    }
+  }
+  if (obj2) {
+    res3 = SWIG_AsCharPtrAndSize(obj2, &buf3, NULL, &alloc3);
+    if (!SWIG_IsOK(res3)) {
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "MajorObject_SetMetadata" "', argument " "3"" of type '" "char const *""'");
+    }
+    arg3 = reinterpret_cast< char * >(buf3);
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (CPLErr)GDALMajorObjectShadow_SetMetadata__SWIG_0(arg1,arg2,(char const *)arg3);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  {
+    /* %typemap(freearg) char **dict */
+    CSLDestroy( arg2 );
+  }
+  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) char **dict */
+    CSLDestroy( arg2 );
+  }
+  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  char *arg3 = (char *) "" ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  int res3 ;
+  char *buf3 = 0 ;
+  int alloc3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  CPLErr result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO|O:MajorObject_SetMetadata",&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_SetMetadata" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "MajorObject_SetMetadata" "', argument " "2"" of type '" "char *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  if (obj2) {
+    res3 = SWIG_AsCharPtrAndSize(obj2, &buf3, NULL, &alloc3);
+    if (!SWIG_IsOK(res3)) {
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "MajorObject_SetMetadata" "', argument " "3"" of type '" "char const *""'");
+    }
+    arg3 = reinterpret_cast< char * >(buf3);
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (CPLErr)GDALMajorObjectShadow_SetMetadata__SWIG_1(arg1,arg2,(char const *)arg3);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata(PyObject *self, PyObject *args) {
+  int argc;
+  PyObject *argv[4];
+  int ii;
+  
+  if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
+  argc = (int)PyObject_Length(args);
+  for (ii = 0; (ii < 3) && (ii < argc); ii++) {
+    argv[ii] = PyTuple_GET_ITEM(args,ii);
+  }
+  if ((argc >= 2) && (argc <= 3)) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_GDALMajorObjectShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      {
+        /* %typecheck(SWIG_TYPECHECK_POINTER) (char **dict) */
+        /* Note: we exclude explicitly strings, because they can be considered as a sequence of characters, */
+        /* which is not desirable since it makes it impossible to define bindings such as SetMetadata(string) and SetMetadata(array_of_string) */
+        /* (see #4816) */
+        _v = ((PyMapping_Check(argv[1]) || PySequence_Check(argv[1]) ) && !SWIG_CheckState(SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0)) ) ? 1 : 0;
+      }
+      if (_v) {
+        if (argc <= 2) {
+          return _wrap_MajorObject_SetMetadata__SWIG_0(self, args);
+        }
+        int res = SWIG_AsCharPtrAndSize(argv[2], 0, NULL, 0);
+        _v = SWIG_CheckState(res);
+        if (_v) {
+          return _wrap_MajorObject_SetMetadata__SWIG_0(self, args);
+        }
+      }
+    }
+  }
+  if ((argc >= 2) && (argc <= 3)) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_GDALMajorObjectShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
+      _v = SWIG_CheckState(res);
+      if (_v) {
+        if (argc <= 2) {
+          return _wrap_MajorObject_SetMetadata__SWIG_1(self, args);
+        }
+        int res = SWIG_AsCharPtrAndSize(argv[2], 0, NULL, 0);
+        _v = SWIG_CheckState(res);
+        if (_v) {
+          return _wrap_MajorObject_SetMetadata__SWIG_1(self, args);
+        }
+      }
+    }
+  }
+  
+fail:
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'MajorObject_SetMetadata'.\n"
+    "  Possible C/C++ prototypes are:\n"
+    "    GDALMajorObjectShadow::SetMetadata(char **,char const *)\n"
+    "    GDALMajorObjectShadow::SetMetadata(char *,char const *)\n");
+  return 0;
+}
+
+
+SWIGINTERN PyObject *_wrap_MajorObject_GetMetadataItem(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  char *arg3 = (char *) "" ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  int res3 ;
+  char *buf3 = 0 ;
+  int alloc3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  char *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO|O:MajorObject_GetMetadataItem",&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_GetMetadataItem" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "MajorObject_GetMetadataItem" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  if (obj2) {
+    res3 = SWIG_AsCharPtrAndSize(obj2, &buf3, NULL, &alloc3);
+    if (!SWIG_IsOK(res3)) {
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "MajorObject_GetMetadataItem" "', argument " "3"" of type '" "char const *""'");
+    }
+    arg3 = reinterpret_cast< char * >(buf3);
+  }
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (char *)GDALMajorObjectShadow_GetMetadataItem(arg1,(char const *)arg2,(char const *)arg3);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_FromCharPtr((const char *)result);
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_MajorObject_SetMetadataItem(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  char *arg3 = (char *) 0 ;
+  char *arg4 = (char *) "" ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  int res3 ;
+  char *buf3 = 0 ;
+  int alloc3 = 0 ;
+  int res4 ;
+  char *buf4 = 0 ;
+  int alloc4 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  CPLErr result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOO|O:MajorObject_SetMetadataItem",&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_SetMetadataItem" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "MajorObject_SetMetadataItem" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  res3 = SWIG_AsCharPtrAndSize(obj2, &buf3, NULL, &alloc3);
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "MajorObject_SetMetadataItem" "', argument " "3"" of type '" "char const *""'");
+  }
+  arg3 = reinterpret_cast< char * >(buf3);
+  if (obj3) {
+    res4 = SWIG_AsCharPtrAndSize(obj3, &buf4, NULL, &alloc4);
+    if (!SWIG_IsOK(res4)) {
+      SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "MajorObject_SetMetadataItem" "', argument " "4"" of type '" "char const *""'");
+    }
+    arg4 = reinterpret_cast< char * >(buf4);
+  }
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (CPLErr)GDALMajorObjectShadow_SetMetadataItem(arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *MajorObject_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *obj;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
+  SWIG_TypeNewClientData(SWIGTYPE_p_GDALMajorObjectShadow, SWIG_NewClientData(obj));
+  return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject *_wrap_CastToNetwork(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  GNMNetworkShadow *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:CastToNetwork",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CastToNetwork" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (GNMNetworkShadow *)CastToNetwork(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GNMNetworkShadow, 0 |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_CastToGenericNetwork(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  GNMGenericNetworkShadow *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:CastToGenericNetwork",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CastToGenericNetwork" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (GNMGenericNetworkShadow *)CastToGenericNetwork(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GNMGenericNetworkShadow, 0 |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_delete_Network(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:delete_Network",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMNetworkShadow, SWIG_POINTER_DISOWN |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_Network" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    delete_GNMNetworkShadow(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Network_ReleaseResultSet(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Network_ReleaseResultSet",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMNetworkShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_ReleaseResultSet" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, SWIG_as_voidptrptr(&arg2), SWIGTYPE_p_OGRLayerShadow, SWIG_POINTER_DISOWN |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Network_ReleaseResultSet" "', argument " "2"" of type '" "OGRLayerShadow *""'");
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    GNMNetworkShadow_ReleaseResultSet(arg1,arg2);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Network_GetVersion(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:Network_GetVersion",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMNetworkShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_GetVersion" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)GNMNetworkShadow_GetVersion(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Network_GetName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  char *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:Network_GetName",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMNetworkShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_GetName" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (char *)GNMNetworkShadow_GetName(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Network_GetFeatureByGlobalFID(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  GIntBig arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  OGRFeatureShadow *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Network_GetFeatureByGlobalFID",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMNetworkShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_GetFeatureByGlobalFID" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
+  {
+    PY_LONG_LONG val;
+    if ( !PyArg_Parse(obj1,"L",&val) ) {
+      PyErr_SetString(PyExc_TypeError, "not an integer");
+      SWIG_fail;
+    }
+    arg2 = (GIntBig)val;
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OGRFeatureShadow *)GNMNetworkShadow_GetFeatureByGlobalFID(arg1,arg2);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Network_GetPath(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  GIntBig arg2 ;
+  GIntBig arg3 ;
+  GNMGraphAlgorithmType arg4 ;
+  char **arg5 = (char **) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val4 ;
+  int ecode4 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "nStartFID",(char *) "nEndFID",(char *) "eAlgorithm",(char *) "options", NULL 
+  };
+  OGRLayerShadow *result = 0 ;
+  
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOOO|O:Network_GetPath",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMNetworkShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_GetPath" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
+  {
+    PY_LONG_LONG val;
+    if ( !PyArg_Parse(obj1,"L",&val) ) {
+      PyErr_SetString(PyExc_TypeError, "not an integer");
+      SWIG_fail;
+    }
+    arg2 = (GIntBig)val;
+  }
+  {
+    PY_LONG_LONG val;
+    if ( !PyArg_Parse(obj2,"L",&val) ) {
+      PyErr_SetString(PyExc_TypeError, "not an integer");
+      SWIG_fail;
+    }
+    arg3 = (GIntBig)val;
+  }
+  ecode4 = SWIG_AsVal_int(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Network_GetPath" "', argument " "4"" of type '" "GNMGraphAlgorithmType""'");
+  } 
+  arg4 = static_cast< GNMGraphAlgorithmType >(val4);
+  if (obj4) {
+    {
+      /* %typemap(in) char **options */
+      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+      if ( ! PySequence_Check(obj4) || PyUnicode_Check(obj4)
+  #if PY_VERSION_HEX < 0x03000000
+        || PyString_Check(obj4)
+  #endif
+        ) {
+        PyErr_SetString(PyExc_TypeError,"not a sequence");
+        SWIG_fail;
+      }
+      
+      Py_ssize_t size = PySequence_Size(obj4);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
+        PyObject* pyObj = PySequence_GetItem(obj4,i);
+        if (PyUnicode_Check(pyObj))
+        {
+          char *pszStr;
+          Py_ssize_t nLen;
+          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+          arg5 = CSLAddString( arg5, pszStr );
+          Py_XDECREF(pyUTF8Str);
+        }
+#if PY_VERSION_HEX >= 0x03000000
+        else if (PyBytes_Check(pyObj))
+        arg5 = CSLAddString( arg5, PyBytes_AsString(pyObj) );
+#else
+        else if (PyString_Check(pyObj))
+        arg5 = CSLAddString( arg5, PyString_AsString(pyObj) );
+#endif
+        else
+        {
+          Py_DECREF(pyObj);
+          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+          SWIG_fail;
+        }
+        Py_DECREF(pyObj);
+      }
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OGRLayerShadow *)GNMNetworkShadow_GetPath(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, SWIG_POINTER_OWN |  0 );
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg5 );
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg5 );
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Network_DisconnectAll(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  CPLErr result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:Network_DisconnectAll",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMNetworkShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_DisconnectAll" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (CPLErr)GNMNetworkShadow_DisconnectAll(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Network_GetProjection(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  char *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:Network_GetProjection",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMNetworkShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_GetProjection" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (char *)GNMNetworkShadow_GetProjection(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Network_GetProjectionRef(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  char *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:Network_GetProjectionRef",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMNetworkShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_GetProjectionRef" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (char *)GNMNetworkShadow_GetProjectionRef(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Network_GetFileList(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  char **result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:Network_GetFileList",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMNetworkShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_GetFileList" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (char **)GNMNetworkShadow_GetFileList(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  {
+    /* %typemap(out) char **CSL -> ( string ) */
+    char **stringarray = result;
+    if ( stringarray == NULL ) {
+      resultobj = Py_None;
+      Py_INCREF( resultobj );
+    }
+    else {
+      int len = CSLCount( stringarray );
+      resultobj = PyList_New( len );
+      for ( int i = 0; i < len; ++i ) {
+        PyObject *o = GDALPythonObjectFromCStr( stringarray[i] );
+        PyList_SetItem(resultobj, i, o );
+      }
+    }
+    CSLDestroy(result);
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Network_CreateLayer(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  OSRSpatialReferenceShadow *arg3 = (OSRSpatialReferenceShadow *) NULL ;
+  OGRwkbGeometryType arg4 = (OGRwkbGeometryType) wkbUnknown ;
+  char **arg5 = (char **) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  void *argp3 = 0 ;
+  int res3 = 0 ;
+  void *argp4 ;
+  int res4 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "name",(char *) "srs",(char *) "geom_type",(char *) "options", NULL 
+  };
+  OGRLayerShadow *result = 0 ;
+  
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO|OOO:Network_CreateLayer",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMNetworkShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_CreateLayer" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Network_CreateLayer" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  if (obj2) {
+    res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
+    if (!SWIG_IsOK(res3)) {
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Network_CreateLayer" "', argument " "3"" of type '" "OSRSpatialReferenceShadow *""'"); 
+    }
+    arg3 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp3);
+  }
+  if (obj3) {
+    {
+      res4 = SWIG_ConvertPtr(obj3, &argp4, SWIGTYPE_p_OGRwkbGeometryType,  0  | 0);
+      if (!SWIG_IsOK(res4)) {
+        SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "Network_CreateLayer" "', argument " "4"" of type '" "OGRwkbGeometryType""'"); 
+      }  
+      if (!argp4) {
+        SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "Network_CreateLayer" "', argument " "4"" of type '" "OGRwkbGeometryType""'");
+      } else {
+        OGRwkbGeometryType * temp = reinterpret_cast< OGRwkbGeometryType * >(argp4);
+        arg4 = *temp;
+        if (SWIG_IsNewObj(res4)) delete temp;
+      }
+    }
+  }
+  if (obj4) {
+    {
+      /* %typemap(in) char **options */
+      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+      if ( ! PySequence_Check(obj4) || PyUnicode_Check(obj4)
+  #if PY_VERSION_HEX < 0x03000000
+        || PyString_Check(obj4)
+  #endif
+        ) {
+        PyErr_SetString(PyExc_TypeError,"not a sequence");
+        SWIG_fail;
+      }
+      
+      Py_ssize_t size = PySequence_Size(obj4);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
+        PyObject* pyObj = PySequence_GetItem(obj4,i);
+        if (PyUnicode_Check(pyObj))
+        {
+          char *pszStr;
+          Py_ssize_t nLen;
+          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+          arg5 = CSLAddString( arg5, pszStr );
+          Py_XDECREF(pyUTF8Str);
+        }
+#if PY_VERSION_HEX >= 0x03000000
+        else if (PyBytes_Check(pyObj))
+        arg5 = CSLAddString( arg5, PyBytes_AsString(pyObj) );
+#else
+        else if (PyString_Check(pyObj))
+        arg5 = CSLAddString( arg5, PyString_AsString(pyObj) );
+#endif
+        else
+        {
+          Py_DECREF(pyObj);
+          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+          SWIG_fail;
+        }
+        Py_DECREF(pyObj);
+      }
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OGRLayerShadow *)GNMNetworkShadow_CreateLayer(arg1,(char const *)arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg5 );
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg5 );
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Network_CopyLayer(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+  char *arg3 = (char *) 0 ;
+  char **arg4 = (char **) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  int res3 ;
+  char *buf3 = 0 ;
+  int alloc3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "src_layer",(char *) "new_name",(char *) "options", NULL 
+  };
+  OGRLayerShadow *result = 0 ;
+  
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOO|O:Network_CopyLayer",kwnames,&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMNetworkShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_CopyLayer" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Network_CopyLayer" "', argument " "2"" of type '" "OGRLayerShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< OGRLayerShadow * >(argp2);
+  res3 = SWIG_AsCharPtrAndSize(obj2, &buf3, NULL, &alloc3);
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Network_CopyLayer" "', argument " "3"" of type '" "char const *""'");
+  }
+  arg3 = reinterpret_cast< char * >(buf3);
+  if (obj3) {
+    {
+      /* %typemap(in) char **options */
+      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+      if ( ! PySequence_Check(obj3) || PyUnicode_Check(obj3)
+  #if PY_VERSION_HEX < 0x03000000
+        || PyString_Check(obj3)
+  #endif
+        ) {
+        PyErr_SetString(PyExc_TypeError,"not a sequence");
+        SWIG_fail;
+      }
+      
+      Py_ssize_t size = PySequence_Size(obj3);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
+        PyObject* pyObj = PySequence_GetItem(obj3,i);
+        if (PyUnicode_Check(pyObj))
+        {
+          char *pszStr;
+          Py_ssize_t nLen;
+          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+          arg4 = CSLAddString( arg4, pszStr );
+          Py_XDECREF(pyUTF8Str);
+        }
+#if PY_VERSION_HEX >= 0x03000000
+        else if (PyBytes_Check(pyObj))
+        arg4 = CSLAddString( arg4, PyBytes_AsString(pyObj) );
+#else
+        else if (PyString_Check(pyObj))
+        arg4 = CSLAddString( arg4, PyString_AsString(pyObj) );
+#endif
+        else
+        {
+          Py_DECREF(pyObj);
+          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+          SWIG_fail;
+        }
+        Py_DECREF(pyObj);
+      }
+    }
+  }
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OGRLayerShadow *)GNMNetworkShadow_CopyLayer(arg1,arg2,(char const *)arg3,arg4);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg4 );
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg4 );
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Network_DeleteLayer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  int arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  OGRErr result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Network_DeleteLayer",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMNetworkShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_DeleteLayer" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Network_DeleteLayer" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = GNMNetworkShadow_DeleteLayer(arg1,arg2);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  {
+    /* %typemap(out) OGRErr */
+    if ( result != 0 && bUseExceptions) {
+      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
+      SWIG_fail;
+    }
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
+      resultobj = PyInt_FromLong( result );
+    }
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Network_GetLayerCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:Network_GetLayerCount",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMNetworkShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_GetLayerCount" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)GNMNetworkShadow_GetLayerCount(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Network_GetLayerByIndex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  int arg2 = (int) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  OGRLayerShadow *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O|O:Network_GetLayerByIndex",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMNetworkShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_GetLayerByIndex" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
+  if (obj1) {
+    ecode2 = SWIG_AsVal_int(obj1, &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Network_GetLayerByIndex" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OGRLayerShadow *)GNMNetworkShadow_GetLayerByIndex(arg1,arg2);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Network_GetLayerByName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  OGRLayerShadow *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Network_GetLayerByName",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMNetworkShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_GetLayerByName" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Network_GetLayerByName" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OGRLayerShadow *)GNMNetworkShadow_GetLayerByName(arg1,(char const *)arg2);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Network_TestCapability(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  bool result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Network_TestCapability",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMNetworkShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_TestCapability" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Network_TestCapability" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (bool)GNMNetworkShadow_TestCapability(arg1,(char const *)arg2);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_bool(static_cast< bool >(result));
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Network_StartTransaction(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  int arg2 = (int) FALSE ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "force", NULL 
+  };
+  OGRErr result;
+  
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"O|O:Network_StartTransaction",kwnames,&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMNetworkShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_StartTransaction" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
+  if (obj1) {
+    ecode2 = SWIG_AsVal_int(obj1, &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Network_StartTransaction" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = GNMNetworkShadow_StartTransaction(arg1,arg2);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  {
+    /* %typemap(out) OGRErr */
+    if ( result != 0 && bUseExceptions) {
+      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
+      SWIG_fail;
+    }
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
+      resultobj = PyInt_FromLong( result );
+    }
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Network_CommitTransaction(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  OGRErr result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:Network_CommitTransaction",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMNetworkShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_CommitTransaction" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = GNMNetworkShadow_CommitTransaction(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  {
+    /* %typemap(out) OGRErr */
+    if ( result != 0 && bUseExceptions) {
+      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
+      SWIG_fail;
+    }
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
+      resultobj = PyInt_FromLong( result );
+    }
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Network_RollbackTransaction(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  OGRErr result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:Network_RollbackTransaction",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMNetworkShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_RollbackTransaction" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = GNMNetworkShadow_RollbackTransaction(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  {
+    /* %typemap(out) OGRErr */
+    if ( result != 0 && bUseExceptions) {
+      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
+      SWIG_fail;
+    }
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
+      resultobj = PyInt_FromLong( result );
+    }
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *Network_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *obj;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
+  SWIG_TypeNewClientData(SWIGTYPE_p_GNMNetworkShadow, SWIG_NewClientData(obj));
+  return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject *_wrap_delete_GenericNetwork(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMGenericNetworkShadow *arg1 = (GNMGenericNetworkShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:delete_GenericNetwork",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMGenericNetworkShadow, SWIG_POINTER_DISOWN |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_GenericNetwork" "', argument " "1"" of type '" "GNMGenericNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMGenericNetworkShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    delete_GNMGenericNetworkShadow(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_GenericNetwork_ConnectFeatures(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMGenericNetworkShadow *arg1 = (GNMGenericNetworkShadow *) 0 ;
+  GIntBig arg2 ;
+  GIntBig arg3 ;
+  GIntBig arg4 ;
+  double arg5 ;
+  double arg6 ;
+  GNMDirection arg7 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  double val5 ;
+  int ecode5 = 0 ;
+  double val6 ;
+  int ecode6 = 0 ;
+  int val7 ;
+  int ecode7 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  PyObject * obj6 = 0 ;
+  CPLErr result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOOOOO:GenericNetwork_ConnectFeatures",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMGenericNetworkShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GenericNetwork_ConnectFeatures" "', argument " "1"" of type '" "GNMGenericNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMGenericNetworkShadow * >(argp1);
+  {
+    PY_LONG_LONG val;
+    if ( !PyArg_Parse(obj1,"L",&val) ) {
+      PyErr_SetString(PyExc_TypeError, "not an integer");
+      SWIG_fail;
+    }
+    arg2 = (GIntBig)val;
+  }
+  {
+    PY_LONG_LONG val;
+    if ( !PyArg_Parse(obj2,"L",&val) ) {
+      PyErr_SetString(PyExc_TypeError, "not an integer");
+      SWIG_fail;
+    }
+    arg3 = (GIntBig)val;
+  }
+  {
+    PY_LONG_LONG val;
+    if ( !PyArg_Parse(obj3,"L",&val) ) {
+      PyErr_SetString(PyExc_TypeError, "not an integer");
+      SWIG_fail;
+    }
+    arg4 = (GIntBig)val;
+  }
+  ecode5 = SWIG_AsVal_double(obj4, &val5);
+  if (!SWIG_IsOK(ecode5)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "GenericNetwork_ConnectFeatures" "', argument " "5"" of type '" "double""'");
+  } 
+  arg5 = static_cast< double >(val5);
+  ecode6 = SWIG_AsVal_double(obj5, &val6);
+  if (!SWIG_IsOK(ecode6)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "GenericNetwork_ConnectFeatures" "', argument " "6"" of type '" "double""'");
+  } 
+  arg6 = static_cast< double >(val6);
+  ecode7 = SWIG_AsVal_int(obj6, &val7);
+  if (!SWIG_IsOK(ecode7)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "GenericNetwork_ConnectFeatures" "', argument " "7"" of type '" "GNMDirection""'");
+  } 
+  arg7 = static_cast< GNMDirection >(val7);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (CPLErr)GNMGenericNetworkShadow_ConnectFeatures(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_GenericNetwork_DisconnectFeatures(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMGenericNetworkShadow *arg1 = (GNMGenericNetworkShadow *) 0 ;
+  GIntBig arg2 ;
+  GIntBig arg3 ;
+  GIntBig arg4 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  CPLErr result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOO:GenericNetwork_DisconnectFeatures",&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMGenericNetworkShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GenericNetwork_DisconnectFeatures" "', argument " "1"" of type '" "GNMGenericNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMGenericNetworkShadow * >(argp1);
+  {
+    PY_LONG_LONG val;
+    if ( !PyArg_Parse(obj1,"L",&val) ) {
+      PyErr_SetString(PyExc_TypeError, "not an integer");
+      SWIG_fail;
+    }
+    arg2 = (GIntBig)val;
+  }
+  {
+    PY_LONG_LONG val;
+    if ( !PyArg_Parse(obj2,"L",&val) ) {
+      PyErr_SetString(PyExc_TypeError, "not an integer");
+      SWIG_fail;
+    }
+    arg3 = (GIntBig)val;
+  }
+  {
+    PY_LONG_LONG val;
+    if ( !PyArg_Parse(obj3,"L",&val) ) {
+      PyErr_SetString(PyExc_TypeError, "not an integer");
+      SWIG_fail;
+    }
+    arg4 = (GIntBig)val;
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (CPLErr)GNMGenericNetworkShadow_DisconnectFeatures(arg1,arg2,arg3,arg4);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_GenericNetwork_DisconnectFeaturesWithId(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMGenericNetworkShadow *arg1 = (GNMGenericNetworkShadow *) 0 ;
+  GIntBig arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  CPLErr result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:GenericNetwork_DisconnectFeaturesWithId",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMGenericNetworkShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GenericNetwork_DisconnectFeaturesWithId" "', argument " "1"" of type '" "GNMGenericNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMGenericNetworkShadow * >(argp1);
+  {
+    PY_LONG_LONG val;
+    if ( !PyArg_Parse(obj1,"L",&val) ) {
+      PyErr_SetString(PyExc_TypeError, "not an integer");
+      SWIG_fail;
+    }
+    arg2 = (GIntBig)val;
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (CPLErr)GNMGenericNetworkShadow_DisconnectFeaturesWithId(arg1,arg2);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_GenericNetwork_ReconnectFeatures(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMGenericNetworkShadow *arg1 = (GNMGenericNetworkShadow *) 0 ;
+  GIntBig arg2 ;
+  GIntBig arg3 ;
+  GIntBig arg4 ;
+  double arg5 ;
+  double arg6 ;
+  GNMDirection arg7 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  double val5 ;
+  int ecode5 = 0 ;
+  double val6 ;
+  int ecode6 = 0 ;
+  int val7 ;
+  int ecode7 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  PyObject * obj6 = 0 ;
+  CPLErr result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOOOOO:GenericNetwork_ReconnectFeatures",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMGenericNetworkShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GenericNetwork_ReconnectFeatures" "', argument " "1"" of type '" "GNMGenericNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMGenericNetworkShadow * >(argp1);
+  {
+    PY_LONG_LONG val;
+    if ( !PyArg_Parse(obj1,"L",&val) ) {
+      PyErr_SetString(PyExc_TypeError, "not an integer");
+      SWIG_fail;
+    }
+    arg2 = (GIntBig)val;
+  }
+  {
+    PY_LONG_LONG val;
+    if ( !PyArg_Parse(obj2,"L",&val) ) {
+      PyErr_SetString(PyExc_TypeError, "not an integer");
+      SWIG_fail;
+    }
+    arg3 = (GIntBig)val;
+  }
+  {
+    PY_LONG_LONG val;
+    if ( !PyArg_Parse(obj3,"L",&val) ) {
+      PyErr_SetString(PyExc_TypeError, "not an integer");
+      SWIG_fail;
+    }
+    arg4 = (GIntBig)val;
+  }
+  ecode5 = SWIG_AsVal_double(obj4, &val5);
+  if (!SWIG_IsOK(ecode5)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "GenericNetwork_ReconnectFeatures" "', argument " "5"" of type '" "double""'");
+  } 
+  arg5 = static_cast< double >(val5);
+  ecode6 = SWIG_AsVal_double(obj5, &val6);
+  if (!SWIG_IsOK(ecode6)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "GenericNetwork_ReconnectFeatures" "', argument " "6"" of type '" "double""'");
+  } 
+  arg6 = static_cast< double >(val6);
+  ecode7 = SWIG_AsVal_int(obj6, &val7);
+  if (!SWIG_IsOK(ecode7)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "GenericNetwork_ReconnectFeatures" "', argument " "7"" of type '" "GNMDirection""'");
+  } 
+  arg7 = static_cast< GNMDirection >(val7);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (CPLErr)GNMGenericNetworkShadow_ReconnectFeatures(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_GenericNetwork_CreateRule(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMGenericNetworkShadow *arg1 = (GNMGenericNetworkShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  CPLErr result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:GenericNetwork_CreateRule",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMGenericNetworkShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GenericNetwork_CreateRule" "', argument " "1"" of type '" "GNMGenericNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMGenericNetworkShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "GenericNetwork_CreateRule" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (CPLErr)GNMGenericNetworkShadow_CreateRule(arg1,(char const *)arg2);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_GenericNetwork_DeleteAllRules(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMGenericNetworkShadow *arg1 = (GNMGenericNetworkShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  CPLErr result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:GenericNetwork_DeleteAllRules",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMGenericNetworkShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GenericNetwork_DeleteAllRules" "', argument " "1"" of type '" "GNMGenericNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMGenericNetworkShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (CPLErr)GNMGenericNetworkShadow_DeleteAllRules(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_GenericNetwork_DeleteRule(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMGenericNetworkShadow *arg1 = (GNMGenericNetworkShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  CPLErr result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:GenericNetwork_DeleteRule",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMGenericNetworkShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GenericNetwork_DeleteRule" "', argument " "1"" of type '" "GNMGenericNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMGenericNetworkShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "GenericNetwork_DeleteRule" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (CPLErr)GNMGenericNetworkShadow_DeleteRule(arg1,(char const *)arg2);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_GenericNetwork_GetRules(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMGenericNetworkShadow *arg1 = (GNMGenericNetworkShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  char **result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:GenericNetwork_GetRules",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMGenericNetworkShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GenericNetwork_GetRules" "', argument " "1"" of type '" "GNMGenericNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMGenericNetworkShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (char **)GNMGenericNetworkShadow_GetRules(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  {
+    /* %typemap(out) char **CSL -> ( string ) */
+    char **stringarray = result;
+    if ( stringarray == NULL ) {
+      resultobj = Py_None;
+      Py_INCREF( resultobj );
+    }
+    else {
+      int len = CSLCount( stringarray );
+      resultobj = PyList_New( len );
+      for ( int i = 0; i < len; ++i ) {
+        PyObject *o = GDALPythonObjectFromCStr( stringarray[i] );
+        PyList_SetItem(resultobj, i, o );
+      }
+    }
+    CSLDestroy(result);
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_GenericNetwork_ConnectPointsByLines(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMGenericNetworkShadow *arg1 = (GNMGenericNetworkShadow *) 0 ;
+  char **arg2 = (char **) 0 ;
+  double arg3 ;
+  double arg4 ;
+  double arg5 ;
+  GNMDirection arg6 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  double val3 ;
+  int ecode3 = 0 ;
+  double val4 ;
+  int ecode4 = 0 ;
+  double val5 ;
+  int ecode5 = 0 ;
+  int val6 ;
+  int ecode6 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "papszLayerList",(char *) "dfTolerance",(char *) "dfCost",(char *) "dfInvCost",(char *) "eDir", NULL 
+  };
+  CPLErr result;
+  
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOOOOO:GenericNetwork_ConnectPointsByLines",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMGenericNetworkShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GenericNetwork_ConnectPointsByLines" "', argument " "1"" of type '" "GNMGenericNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMGenericNetworkShadow * >(argp1);
+  {
+    /* %typemap(in) char **options */
+    /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+    if ( ! PySequence_Check(obj1) || PyUnicode_Check(obj1)
+  #if PY_VERSION_HEX < 0x03000000
+      || PyString_Check(obj1)
+  #endif
+      ) {
+      PyErr_SetString(PyExc_TypeError,"not a sequence");
+      SWIG_fail;
+    }
+    
+    Py_ssize_t size = PySequence_Size(obj1);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    for (int i = 0; i < (int)size; i++) {
+      PyObject* pyObj = PySequence_GetItem(obj1,i);
+      if (PyUnicode_Check(pyObj))
+      {
+        char *pszStr;
+        Py_ssize_t nLen;
+        PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+        PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+        PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+        arg2 = CSLAddString( arg2, pszStr );
+        Py_XDECREF(pyUTF8Str);
+      }
+#if PY_VERSION_HEX >= 0x03000000
+      else if (PyBytes_Check(pyObj))
+      arg2 = CSLAddString( arg2, PyBytes_AsString(pyObj) );
+#else
+      else if (PyString_Check(pyObj))
+      arg2 = CSLAddString( arg2, PyString_AsString(pyObj) );
+#endif
+      else
+      {
+        Py_DECREF(pyObj);
+        PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+        SWIG_fail;
+      }
+      Py_DECREF(pyObj);
+    }
+  }
+  ecode3 = SWIG_AsVal_double(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "GenericNetwork_ConnectPointsByLines" "', argument " "3"" of type '" "double""'");
+  } 
+  arg3 = static_cast< double >(val3);
+  ecode4 = SWIG_AsVal_double(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "GenericNetwork_ConnectPointsByLines" "', argument " "4"" of type '" "double""'");
+  } 
+  arg4 = static_cast< double >(val4);
+  ecode5 = SWIG_AsVal_double(obj4, &val5);
+  if (!SWIG_IsOK(ecode5)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "GenericNetwork_ConnectPointsByLines" "', argument " "5"" of type '" "double""'");
+  } 
+  arg5 = static_cast< double >(val5);
+  ecode6 = SWIG_AsVal_int(obj5, &val6);
+  if (!SWIG_IsOK(ecode6)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "GenericNetwork_ConnectPointsByLines" "', argument " "6"" of type '" "GNMDirection""'");
+  } 
+  arg6 = static_cast< GNMDirection >(val6);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (CPLErr)GNMGenericNetworkShadow_ConnectPointsByLines(arg1,arg2,arg3,arg4,arg5,arg6);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg2 );
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg2 );
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_GenericNetwork_ChangeBlockState(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMGenericNetworkShadow *arg1 = (GNMGenericNetworkShadow *) 0 ;
+  GIntBig arg2 ;
+  bool arg3 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  bool val3 ;
+  int ecode3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  CPLErr result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOO:GenericNetwork_ChangeBlockState",&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMGenericNetworkShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GenericNetwork_ChangeBlockState" "', argument " "1"" of type '" "GNMGenericNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMGenericNetworkShadow * >(argp1);
+  {
+    PY_LONG_LONG val;
+    if ( !PyArg_Parse(obj1,"L",&val) ) {
+      PyErr_SetString(PyExc_TypeError, "not an integer");
+      SWIG_fail;
+    }
+    arg2 = (GIntBig)val;
+  }
+  ecode3 = SWIG_AsVal_bool(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "GenericNetwork_ChangeBlockState" "', argument " "3"" of type '" "bool""'");
+  } 
+  arg3 = static_cast< bool >(val3);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (CPLErr)GNMGenericNetworkShadow_ChangeBlockState(arg1,arg2,arg3);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_GenericNetwork_ChangeAllBlockState(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GNMGenericNetworkShadow *arg1 = (GNMGenericNetworkShadow *) 0 ;
+  bool arg2 = (bool) false ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  bool val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  CPLErr result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O|O:GenericNetwork_ChangeAllBlockState",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GNMGenericNetworkShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GenericNetwork_ChangeAllBlockState" "', argument " "1"" of type '" "GNMGenericNetworkShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GNMGenericNetworkShadow * >(argp1);
+  if (obj1) {
+    ecode2 = SWIG_AsVal_bool(obj1, &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "GenericNetwork_ChangeAllBlockState" "', argument " "2"" of type '" "bool""'");
+    } 
+    arg2 = static_cast< bool >(val2);
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (CPLErr)GNMGenericNetworkShadow_ChangeAllBlockState(arg1,arg2);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *GenericNetwork_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *obj;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
+  SWIG_TypeNewClientData(SWIGTYPE_p_GNMGenericNetworkShadow, SWIG_NewClientData(obj));
+  return SWIG_Py_Void();
+}
+
+static PyMethodDef SwigMethods[] = {
+	 { (char *)"SWIG_PyInstanceMethod_New", (PyCFunction)SWIG_PyInstanceMethod_New, METH_O, NULL},
+	 { (char *)"GetUseExceptions", _wrap_GetUseExceptions, METH_VARARGS, NULL},
+	 { (char *)"UseExceptions", _wrap_UseExceptions, METH_VARARGS, NULL},
+	 { (char *)"DontUseExceptions", _wrap_DontUseExceptions, METH_VARARGS, NULL},
+	 { (char *)"MajorObject_GetDescription", _wrap_MajorObject_GetDescription, METH_VARARGS, NULL},
+	 { (char *)"MajorObject_SetDescription", _wrap_MajorObject_SetDescription, METH_VARARGS, NULL},
+	 { (char *)"MajorObject_GetMetadataDomainList", _wrap_MajorObject_GetMetadataDomainList, METH_VARARGS, NULL},
+	 { (char *)"MajorObject_GetMetadata_Dict", _wrap_MajorObject_GetMetadata_Dict, METH_VARARGS, NULL},
+	 { (char *)"MajorObject_GetMetadata_List", _wrap_MajorObject_GetMetadata_List, METH_VARARGS, NULL},
+	 { (char *)"MajorObject_SetMetadata", _wrap_MajorObject_SetMetadata, METH_VARARGS, NULL},
+	 { (char *)"MajorObject_GetMetadataItem", _wrap_MajorObject_GetMetadataItem, METH_VARARGS, NULL},
+	 { (char *)"MajorObject_SetMetadataItem", _wrap_MajorObject_SetMetadataItem, METH_VARARGS, NULL},
+	 { (char *)"MajorObject_swigregister", MajorObject_swigregister, METH_VARARGS, NULL},
+	 { (char *)"CastToNetwork", _wrap_CastToNetwork, METH_VARARGS, (char *)"CastToNetwork(MajorObject base) -> Network"},
+	 { (char *)"CastToGenericNetwork", _wrap_CastToGenericNetwork, METH_VARARGS, (char *)"CastToGenericNetwork(MajorObject base) -> GenericNetwork"},
+	 { (char *)"delete_Network", _wrap_delete_Network, METH_VARARGS, (char *)"delete_Network(Network self)"},
+	 { (char *)"Network_ReleaseResultSet", _wrap_Network_ReleaseResultSet, METH_VARARGS, (char *)"Network_ReleaseResultSet(Network self, OGRLayerShadow * layer)"},
+	 { (char *)"Network_GetVersion", _wrap_Network_GetVersion, METH_VARARGS, (char *)"Network_GetVersion(Network self) -> int"},
+	 { (char *)"Network_GetName", _wrap_Network_GetName, METH_VARARGS, (char *)"Network_GetName(Network self) -> char const *"},
+	 { (char *)"Network_GetFeatureByGlobalFID", _wrap_Network_GetFeatureByGlobalFID, METH_VARARGS, (char *)"Network_GetFeatureByGlobalFID(Network self, GIntBig GFID) -> OGRFeatureShadow *"},
+	 { (char *)"Network_GetPath", (PyCFunction) _wrap_Network_GetPath, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
+		"Network_GetPath(Network self, GIntBig nStartFID, GIntBig nEndFID, GNMGraphAlgorithmType eAlgorithm, \n"
+		"    char ** options=None) -> OGRLayerShadow *\n"
+		""},
+	 { (char *)"Network_DisconnectAll", _wrap_Network_DisconnectAll, METH_VARARGS, (char *)"Network_DisconnectAll(Network self) -> CPLErr"},
+	 { (char *)"Network_GetProjection", _wrap_Network_GetProjection, METH_VARARGS, (char *)"Network_GetProjection(Network self) -> char const *"},
+	 { (char *)"Network_GetProjectionRef", _wrap_Network_GetProjectionRef, METH_VARARGS, (char *)"Network_GetProjectionRef(Network self) -> char const *"},
+	 { (char *)"Network_GetFileList", _wrap_Network_GetFileList, METH_VARARGS, (char *)"Network_GetFileList(Network self) -> char **"},
+	 { (char *)"Network_CreateLayer", (PyCFunction) _wrap_Network_CreateLayer, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
+		"Network_CreateLayer(Network self, char const * name, OSRSpatialReferenceShadow * srs=None, OGRwkbGeometryType geom_type=wkbUnknown, \n"
+		"    char ** options=None) -> OGRLayerShadow *\n"
+		""},
+	 { (char *)"Network_CopyLayer", (PyCFunction) _wrap_Network_CopyLayer, METH_VARARGS | METH_KEYWORDS, (char *)"Network_CopyLayer(Network self, OGRLayerShadow * src_layer, char const * new_name, char ** options=None) -> OGRLayerShadow *"},
+	 { (char *)"Network_DeleteLayer", _wrap_Network_DeleteLayer, METH_VARARGS, (char *)"Network_DeleteLayer(Network self, int index) -> OGRErr"},
+	 { (char *)"Network_GetLayerCount", _wrap_Network_GetLayerCount, METH_VARARGS, (char *)"Network_GetLayerCount(Network self) -> int"},
+	 { (char *)"Network_GetLayerByIndex", _wrap_Network_GetLayerByIndex, METH_VARARGS, (char *)"Network_GetLayerByIndex(Network self, int index=0) -> OGRLayerShadow *"},
+	 { (char *)"Network_GetLayerByName", _wrap_Network_GetLayerByName, METH_VARARGS, (char *)"Network_GetLayerByName(Network self, char const * layer_name) -> OGRLayerShadow *"},
+	 { (char *)"Network_TestCapability", _wrap_Network_TestCapability, METH_VARARGS, (char *)"Network_TestCapability(Network self, char const * cap) -> bool"},
+	 { (char *)"Network_StartTransaction", (PyCFunction) _wrap_Network_StartTransaction, METH_VARARGS | METH_KEYWORDS, (char *)"Network_StartTransaction(Network self, int force=False) -> OGRErr"},
+	 { (char *)"Network_CommitTransaction", _wrap_Network_CommitTransaction, METH_VARARGS, (char *)"Network_CommitTransaction(Network self) -> OGRErr"},
+	 { (char *)"Network_RollbackTransaction", _wrap_Network_RollbackTransaction, METH_VARARGS, (char *)"Network_RollbackTransaction(Network self) -> OGRErr"},
+	 { (char *)"Network_swigregister", Network_swigregister, METH_VARARGS, NULL},
+	 { (char *)"delete_GenericNetwork", _wrap_delete_GenericNetwork, METH_VARARGS, (char *)"delete_GenericNetwork(GenericNetwork self)"},
+	 { (char *)"GenericNetwork_ConnectFeatures", _wrap_GenericNetwork_ConnectFeatures, METH_VARARGS, (char *)"\n"
+		"GenericNetwork_ConnectFeatures(GenericNetwork self, GIntBig nSrcFID, GIntBig nTgtFID, GIntBig nConFID, double dfCost, \n"
+		"    double dfInvCost, GNMDirection eDir) -> CPLErr\n"
+		""},
+	 { (char *)"GenericNetwork_DisconnectFeatures", _wrap_GenericNetwork_DisconnectFeatures, METH_VARARGS, (char *)"GenericNetwork_DisconnectFeatures(GenericNetwork self, GIntBig nSrcFID, GIntBig nTgtFID, GIntBig nConFID) -> CPLErr"},
+	 { (char *)"GenericNetwork_DisconnectFeaturesWithId", _wrap_GenericNetwork_DisconnectFeaturesWithId, METH_VARARGS, (char *)"GenericNetwork_DisconnectFeaturesWithId(GenericNetwork self, GIntBig nFID) -> CPLErr"},
+	 { (char *)"GenericNetwork_ReconnectFeatures", _wrap_GenericNetwork_ReconnectFeatures, METH_VARARGS, (char *)"\n"
+		"GenericNetwork_ReconnectFeatures(GenericNetwork self, GIntBig nSrcFID, GIntBig nTgtFID, GIntBig nConFID, double dfCost, \n"
+		"    double dfInvCost, GNMDirection eDir) -> CPLErr\n"
+		""},
+	 { (char *)"GenericNetwork_CreateRule", _wrap_GenericNetwork_CreateRule, METH_VARARGS, (char *)"GenericNetwork_CreateRule(GenericNetwork self, char const * pszRuleStr) -> CPLErr"},
+	 { (char *)"GenericNetwork_DeleteAllRules", _wrap_GenericNetwork_DeleteAllRules, METH_VARARGS, (char *)"GenericNetwork_DeleteAllRules(GenericNetwork self) -> CPLErr"},
+	 { (char *)"GenericNetwork_DeleteRule", _wrap_GenericNetwork_DeleteRule, METH_VARARGS, (char *)"GenericNetwork_DeleteRule(GenericNetwork self, char const * pszRuleStr) -> CPLErr"},
+	 { (char *)"GenericNetwork_GetRules", _wrap_GenericNetwork_GetRules, METH_VARARGS, (char *)"GenericNetwork_GetRules(GenericNetwork self) -> char **"},
+	 { (char *)"GenericNetwork_ConnectPointsByLines", (PyCFunction) _wrap_GenericNetwork_ConnectPointsByLines, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
+		"GenericNetwork_ConnectPointsByLines(GenericNetwork self, char ** papszLayerList, double dfTolerance, double dfCost, double dfInvCost, \n"
+		"    GNMDirection eDir) -> CPLErr\n"
+		""},
+	 { (char *)"GenericNetwork_ChangeBlockState", _wrap_GenericNetwork_ChangeBlockState, METH_VARARGS, (char *)"GenericNetwork_ChangeBlockState(GenericNetwork self, GIntBig nFID, bool bIsBlock) -> CPLErr"},
+	 { (char *)"GenericNetwork_ChangeAllBlockState", _wrap_GenericNetwork_ChangeAllBlockState, METH_VARARGS, (char *)"GenericNetwork_ChangeAllBlockState(GenericNetwork self, bool bIsBlock=False) -> CPLErr"},
+	 { (char *)"GenericNetwork_swigregister", GenericNetwork_swigregister, METH_VARARGS, NULL},
+	 { NULL, NULL, 0, NULL }
+};
+
+
+/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */
+
+static void *_p_GNMNetworkShadowTo_p_GDALMajorObjectShadow(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((GDALMajorObjectShadow *)  ((GNMNetworkShadow *) x));
+}
+static void *_p_GNMGenericNetworkShadowTo_p_GDALMajorObjectShadow(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((GDALMajorObjectShadow *) (GNMNetworkShadow *) ((GNMGenericNetworkShadow *) x));
+}
+static void *_p_GNMGenericNetworkShadowTo_p_GNMNetworkShadow(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((GNMNetworkShadow *)  ((GNMGenericNetworkShadow *) x));
+}
+static swig_type_info _swigt__p_GDALMajorObjectShadow = {"_p_GDALMajorObjectShadow", "GDALMajorObjectShadow *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_GIntBig = {"_p_GIntBig", "GIntBig *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_GNMGenericNetworkShadow = {"_p_GNMGenericNetworkShadow", "GNMGenericNetworkShadow *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_GNMGraphAlgorithmType = {"_p_GNMGraphAlgorithmType", "enum GNMGraphAlgorithmType *|GNMGraphAlgorithmType *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_GNMNetworkShadow = {"_p_GNMNetworkShadow", "GNMNetworkShadow *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_OGRFeatureShadow = {"_p_OGRFeatureShadow", "OGRFeatureShadow *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_OGRLayerShadow = {"_p_OGRLayerShadow", "OGRLayerShadow *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_OGRwkbGeometryType = {"_p_OGRwkbGeometryType", "OGRwkbGeometryType *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_OSRSpatialReferenceShadow = {"_p_OSRSpatialReferenceShadow", "OSRSpatialReferenceShadow *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_char = {"_p_char", "char *|retStringAndCPLFree *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_int = {"_p_int", "CPLErr *|int *|GNMDirection *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_p_char = {"_p_p_char", "char **", 0, 0, (void*)0, 0};
+
+static swig_type_info *swig_type_initial[] = {
+  &_swigt__p_GDALMajorObjectShadow,
+  &_swigt__p_GIntBig,
+  &_swigt__p_GNMGenericNetworkShadow,
+  &_swigt__p_GNMGraphAlgorithmType,
+  &_swigt__p_GNMNetworkShadow,
+  &_swigt__p_OGRFeatureShadow,
+  &_swigt__p_OGRLayerShadow,
+  &_swigt__p_OGRwkbGeometryType,
+  &_swigt__p_OSRSpatialReferenceShadow,
+  &_swigt__p_char,
+  &_swigt__p_int,
+  &_swigt__p_p_char,
+};
+
+static swig_cast_info _swigc__p_GDALMajorObjectShadow[] = {  {&_swigt__p_GDALMajorObjectShadow, 0, 0, 0},  {&_swigt__p_GNMNetworkShadow, _p_GNMNetworkShadowTo_p_GDALMajorObjectShadow, 0, 0},  {&_swigt__p_GNMGenericNetworkShadow, _p_GNMGenericNetworkShadowTo_p_GDALMajorObjectShadow, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_GIntBig[] = {  {&_swigt__p_GIntBig, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_GNMGenericNetworkShadow[] = {  {&_swigt__p_GNMGenericNetworkShadow, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_GNMGraphAlgorithmType[] = {  {&_swigt__p_GNMGraphAlgorithmType, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_GNMNetworkShadow[] = {  {&_swigt__p_GNMNetworkShadow, 0, 0, 0},  {&_swigt__p_GNMGenericNetworkShadow, _p_GNMGenericNetworkShadowTo_p_GNMNetworkShadow, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_OGRFeatureShadow[] = {  {&_swigt__p_OGRFeatureShadow, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_OGRLayerShadow[] = {  {&_swigt__p_OGRLayerShadow, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_OGRwkbGeometryType[] = {  {&_swigt__p_OGRwkbGeometryType, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_OSRSpatialReferenceShadow[] = {  {&_swigt__p_OSRSpatialReferenceShadow, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_char[] = {  {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_int[] = {  {&_swigt__p_int, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_p_char[] = {  {&_swigt__p_p_char, 0, 0, 0},{0, 0, 0, 0}};
+
+static swig_cast_info *swig_cast_initial[] = {
+  _swigc__p_GDALMajorObjectShadow,
+  _swigc__p_GIntBig,
+  _swigc__p_GNMGenericNetworkShadow,
+  _swigc__p_GNMGraphAlgorithmType,
+  _swigc__p_GNMNetworkShadow,
+  _swigc__p_OGRFeatureShadow,
+  _swigc__p_OGRLayerShadow,
+  _swigc__p_OGRwkbGeometryType,
+  _swigc__p_OSRSpatialReferenceShadow,
+  _swigc__p_char,
+  _swigc__p_int,
+  _swigc__p_p_char,
+};
+
+
+/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */
+
+static swig_const_info swig_const_table[] = {
+{0, 0, 0, 0.0, 0, 0}};
+
+#ifdef __cplusplus
+}
+#endif
+/* -----------------------------------------------------------------------------
+ * Type initialization:
+ * This problem is tough by the requirement that no dynamic
+ * memory is used. Also, since swig_type_info structures store pointers to
+ * swig_cast_info structures and swig_cast_info structures store pointers back
+ * to swig_type_info structures, we need some lookup code at initialization.
+ * The idea is that swig generates all the structures that are needed.
+ * The runtime then collects these partially filled structures.
+ * The SWIG_InitializeModule function takes these initial arrays out of
+ * swig_module, and does all the lookup, filling in the swig_module.types
+ * array with the correct data and linking the correct swig_cast_info
+ * structures together.
+ *
+ * The generated swig_type_info structures are assigned staticly to an initial
+ * array. We just loop through that array, and handle each type individually.
+ * First we lookup if this type has been already loaded, and if so, use the
+ * loaded structure instead of the generated one. Then we have to fill in the
+ * cast linked list. The cast data is initially stored in something like a
+ * two-dimensional array. Each row corresponds to a type (there are the same
+ * number of rows as there are in the swig_type_initial array). Each entry in
+ * a column is one of the swig_cast_info structures for that type.
+ * The cast_initial array is actually an array of arrays, because each row has
+ * a variable number of columns. So to actually build the cast linked list,
+ * we find the array of casts associated with the type, and loop through it
+ * adding the casts to the list. The one last trick we need to do is making
+ * sure the type pointer in the swig_cast_info struct is correct.
+ *
+ * First off, we lookup the cast->type name to see if it is already loaded.
+ * There are three cases to handle:
+ *  1) If the cast->type has already been loaded AND the type we are adding
+ *     casting info to has not been loaded (it is in this module), THEN we
+ *     replace the cast->type pointer with the type pointer that has already
+ *     been loaded.
+ *  2) If BOTH types (the one we are adding casting info to, and the
+ *     cast->type) are loaded, THEN the cast info has already been loaded by
+ *     the previous module so we just ignore it.
+ *  3) Finally, if cast->type has not already been loaded, then we add that
+ *     swig_cast_info to the linked list (because the cast->type) pointer will
+ *     be correct.
+ * ----------------------------------------------------------------------------- */
+
+#ifdef __cplusplus
+extern "C" {
+#if 0
+} /* c-mode */
+#endif
+#endif
+
+#if 0
+#define SWIGRUNTIME_DEBUG
+#endif
+
+
+SWIGRUNTIME void
+SWIG_InitializeModule(void *clientdata) {
+  size_t i;
+  swig_module_info *module_head, *iter;
+  int found, init;
+  
+  /* check to see if the circular list has been setup, if not, set it up */
+  if (swig_module.next==0) {
+    /* Initialize the swig_module */
+    swig_module.type_initial = swig_type_initial;
+    swig_module.cast_initial = swig_cast_initial;
+    swig_module.next = &swig_module;
+    init = 1;
+  } else {
+    init = 0;
+  }
+  
+  /* Try and load any already created modules */
+  module_head = SWIG_GetModule(clientdata);
+  if (!module_head) {
+    /* This is the first module loaded for this interpreter */
+    /* so set the swig module into the interpreter */
+    SWIG_SetModule(clientdata, &swig_module);
+    /*module_head = &swig_module;*/
+  } else {
+    /* the interpreter has loaded a SWIG module, but has it loaded this one? */
+    found=0;
+    iter=module_head;
+    do {
+      if (iter==&swig_module) {
+        found=1;
+        break;
+      }
+      iter=iter->next;
+    } while (iter!= module_head);
+    
+    /* if the is found in the list, then all is done and we may leave */
+    if (found) return;
+    /* otherwise we must add out module into the list */
+    swig_module.next = module_head->next;
+    module_head->next = &swig_module;
+  }
+  
+  /* When multiple interpreters are used, a module could have already been initialized in
+       a different interpreter, but not yet have a pointer in this interpreter.
+       In this case, we do not want to continue adding types... everything should be
+       set up already */
+  if (init == 0) return;
+  
+  /* Now work on filling in swig_module.types */
+#ifdef SWIGRUNTIME_DEBUG
+  printf("SWIG_InitializeModule: size %d\n", swig_module.size);
+#endif
+  for (i = 0; i < swig_module.size; ++i) {
+    swig_type_info *type = 0;
+    swig_type_info *ret;
+    swig_cast_info *cast;
+    
+#ifdef SWIGRUNTIME_DEBUG
+    printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name);
+#endif
+    
+    /* if there is another module already loaded */
+    if (swig_module.next != &swig_module) {
+      type = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, swig_module.type_initial[i]->name);
+    }
+    if (type) {
+      /* Overwrite clientdata field */
+#ifdef SWIGRUNTIME_DEBUG
+      printf("SWIG_InitializeModule: found type %s\n", type->name);
+#endif
+      if (swig_module.type_initial[i]->clientdata) {
+        type->clientdata = swig_module.type_initial[i]->clientdata;
+#ifdef SWIGRUNTIME_DEBUG
+        printf("SWIG_InitializeModule: found and overwrite type %s \n", type->name);
+#endif
+      }
+    } else {
+      type = swig_module.type_initial[i];
+    }
+    
+    /* Insert casting types */
+    cast = swig_module.cast_initial[i];
+    while (cast->type) {
+      /* Don't need to add information already in the list */
+      ret = 0;
+#ifdef SWIGRUNTIME_DEBUG
+      printf("SWIG_InitializeModule: look cast %s\n", cast->type->name);
+#endif
+      if (swig_module.next != &swig_module) {
+        ret = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, cast->type->name);
+#ifdef SWIGRUNTIME_DEBUG
+        if (ret) printf("SWIG_InitializeModule: found cast %s\n", ret->name);
+#endif
+      }
+      if (ret) {
+        if (type == swig_module.type_initial[i]) {
+#ifdef SWIGRUNTIME_DEBUG
+          printf("SWIG_InitializeModule: skip old type %s\n", ret->name);
+#endif
+          cast->type = ret;
+          ret = 0;
+        } else {
+          /* Check for casting already in the list */
+          swig_cast_info *ocast = SWIG_TypeCheck(ret->name, type);
+#ifdef SWIGRUNTIME_DEBUG
+          if (ocast) printf("SWIG_InitializeModule: skip old cast %s\n", ret->name);
+#endif
+          if (!ocast) ret = 0;
+        }
+      }
+      
+      if (!ret) {
+#ifdef SWIGRUNTIME_DEBUG
+        printf("SWIG_InitializeModule: adding cast %s\n", cast->type->name);
+#endif
+        if (type->cast) {
+          type->cast->prev = cast;
+          cast->next = type->cast;
+        }
+        type->cast = cast;
+      }
+      cast++;
+    }
+    /* Set entry in modules->types array equal to the type */
+    swig_module.types[i] = type;
+  }
+  swig_module.types[i] = 0;
+  
+#ifdef SWIGRUNTIME_DEBUG
+  printf("**** SWIG_InitializeModule: Cast List ******\n");
+  for (i = 0; i < swig_module.size; ++i) {
+    int j = 0;
+    swig_cast_info *cast = swig_module.cast_initial[i];
+    printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name);
+    while (cast->type) {
+      printf("SWIG_InitializeModule: cast type %s\n", cast->type->name);
+      cast++;
+      ++j;
+    }
+    printf("---- Total casts: %d\n",j);
+  }
+  printf("**** SWIG_InitializeModule: Cast List ******\n");
+#endif
+}
+
+/* This function will propagate the clientdata field of type to
+* any new swig_type_info structures that have been added into the list
+* of equivalent types.  It is like calling
+* SWIG_TypeClientData(type, clientdata) a second time.
+*/
+SWIGRUNTIME void
+SWIG_PropagateClientData(void) {
+  size_t i;
+  swig_cast_info *equiv;
+  static int init_run = 0;
+  
+  if (init_run) return;
+  init_run = 1;
+  
+  for (i = 0; i < swig_module.size; i++) {
+    if (swig_module.types[i]->clientdata) {
+      equiv = swig_module.types[i]->cast;
+      while (equiv) {
+        if (!equiv->converter) {
+          if (equiv->type && !equiv->type->clientdata)
+          SWIG_TypeClientData(equiv->type, swig_module.types[i]->clientdata);
+        }
+        equiv = equiv->next;
+      }
+    }
+  }
+}
+
+#ifdef __cplusplus
+#if 0
+{
+  /* c-mode */
+#endif
+}
+#endif
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+  
+  /* Python-specific SWIG API */
+#define SWIG_newvarlink()                             SWIG_Python_newvarlink()
+#define SWIG_addvarlink(p, name, get_attr, set_attr)  SWIG_Python_addvarlink(p, name, get_attr, set_attr)
+#define SWIG_InstallConstants(d, constants)           SWIG_Python_InstallConstants(d, constants)
+  
+  /* -----------------------------------------------------------------------------
+   * global variable support code.
+   * ----------------------------------------------------------------------------- */
+  
+  typedef struct swig_globalvar {
+    char       *name;                  /* Name of global variable */
+    PyObject *(*get_attr)(void);       /* Return the current value */
+    int       (*set_attr)(PyObject *); /* Set the value */
+    struct swig_globalvar *next;
+  } swig_globalvar;
+  
+  typedef struct swig_varlinkobject {
+    PyObject_HEAD
+    swig_globalvar *vars;
+  } swig_varlinkobject;
+  
+  SWIGINTERN PyObject *
+  swig_varlink_repr(swig_varlinkobject *SWIGUNUSEDPARM(v)) {
+#if PY_VERSION_HEX >= 0x03000000
+    return PyUnicode_InternFromString("<Swig global variables>");
+#else
+    return PyString_FromString("<Swig global variables>");
+#endif
+  }
+  
+  SWIGINTERN PyObject *
+  swig_varlink_str(swig_varlinkobject *v) {
+#if PY_VERSION_HEX >= 0x03000000
+    PyObject *str = PyUnicode_InternFromString("(");
+    PyObject *tail;
+    PyObject *joined;
+    swig_globalvar *var;
+    for (var = v->vars; var; var=var->next) {
+      tail = PyUnicode_FromString(var->name);
+      joined = PyUnicode_Concat(str, tail);
+      Py_DecRef(str);
+      Py_DecRef(tail);
+      str = joined;
+      if (var->next) {
+        tail = PyUnicode_InternFromString(", ");
+        joined = PyUnicode_Concat(str, tail);
+        Py_DecRef(str);
+        Py_DecRef(tail);
+        str = joined;
+      }
+    }
+    tail = PyUnicode_InternFromString(")");
+    joined = PyUnicode_Concat(str, tail);
+    Py_DecRef(str);
+    Py_DecRef(tail);
+    str = joined;
+#else
+    PyObject *str = PyString_FromString("(");
+    swig_globalvar *var;
+    for (var = v->vars; var; var=var->next) {
+      PyString_ConcatAndDel(&str,PyString_FromString(var->name));
+      if (var->next) PyString_ConcatAndDel(&str,PyString_FromString(", "));
+    }
+    PyString_ConcatAndDel(&str,PyString_FromString(")"));
+#endif
+    return str;
+  }
+  
+  SWIGINTERN int
+  swig_varlink_print(swig_varlinkobject *v, FILE *fp, int SWIGUNUSEDPARM(flags)) {
+    char *tmp;
+    PyObject *str = swig_varlink_str(v);
+    fprintf(fp,"Swig global variables ");
+    fprintf(fp,"%s\n", tmp = SWIG_Python_str_AsChar(str));
+    SWIG_Python_str_DelForPy3(tmp);
+    Py_DECREF(str);
+    return 0;
+  }
+  
+  SWIGINTERN void
+  swig_varlink_dealloc(swig_varlinkobject *v) {
+    swig_globalvar *var = v->vars;
+    while (var) {
+      swig_globalvar *n = var->next;
+      free(var->name);
+      free(var);
+      var = n;
+    }
+  }
+  
+  SWIGINTERN PyObject *
+  swig_varlink_getattr(swig_varlinkobject *v, char *n) {
+    PyObject *res = NULL;
+    swig_globalvar *var = v->vars;
+    while (var) {
+      if (strcmp(var->name,n) == 0) {
+        res = (*var->get_attr)();
+        break;
+      }
+      var = var->next;
+    }
+    if (res == NULL && !PyErr_Occurred()) {
+      PyErr_SetString(PyExc_NameError,"Unknown C global variable");
+    }
+    return res;
+  }
+  
+  SWIGINTERN int
+  swig_varlink_setattr(swig_varlinkobject *v, char *n, PyObject *p) {
+    int res = 1;
+    swig_globalvar *var = v->vars;
+    while (var) {
+      if (strcmp(var->name,n) == 0) {
+        res = (*var->set_attr)(p);
+        break;
+      }
+      var = var->next;
+    }
+    if (res == 1 && !PyErr_Occurred()) {
+      PyErr_SetString(PyExc_NameError,"Unknown C global variable");
+    }
+    return res;
+  }
+  
+  SWIGINTERN PyTypeObject*
+  swig_varlink_type(void) {
+    static char varlink__doc__[] = "Swig var link object";
+    static PyTypeObject varlink_type;
+    static int type_init = 0;
+    if (!type_init) {
+      const PyTypeObject tmp = {
+        /* PyObject header changed in Python 3 */
+#if PY_VERSION_HEX >= 0x03000000
+        PyVarObject_HEAD_INIT(NULL, 0)
+#else
+        PyObject_HEAD_INIT(NULL)
+        0,                                  /* ob_size */
+#endif
+        (char *)"swigvarlink",              /* tp_name */
+        sizeof(swig_varlinkobject),         /* tp_basicsize */
+        0,                                  /* tp_itemsize */
+        (destructor) swig_varlink_dealloc,  /* tp_dealloc */
+        (printfunc) swig_varlink_print,     /* tp_print */
+        (getattrfunc) swig_varlink_getattr, /* tp_getattr */
+        (setattrfunc) swig_varlink_setattr, /* tp_setattr */
+        0,                                  /* tp_compare */
+        (reprfunc) swig_varlink_repr,       /* tp_repr */
+        0,                                  /* tp_as_number */
+        0,                                  /* tp_as_sequence */
+        0,                                  /* tp_as_mapping */
+        0,                                  /* tp_hash */
+        0,                                  /* tp_call */
+        (reprfunc) swig_varlink_str,        /* tp_str */
+        0,                                  /* tp_getattro */
+        0,                                  /* tp_setattro */
+        0,                                  /* tp_as_buffer */
+        0,                                  /* tp_flags */
+        varlink__doc__,                     /* tp_doc */
+        0,                                  /* tp_traverse */
+        0,                                  /* tp_clear */
+        0,                                  /* tp_richcompare */
+        0,                                  /* tp_weaklistoffset */
+#if PY_VERSION_HEX >= 0x02020000
+        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* tp_iter -> tp_weaklist */
+#endif
+#if PY_VERSION_HEX >= 0x02030000
+        0,                                  /* tp_del */
+#endif
+#if PY_VERSION_HEX >= 0x02060000
+        0,                                  /* tp_version */
+#endif
+#ifdef COUNT_ALLOCS
+        0,0,0,0                             /* tp_alloc -> tp_next */
+#endif
+      };
+      varlink_type = tmp;
+      type_init = 1;
+#if PY_VERSION_HEX < 0x02020000
+      varlink_type.ob_type = &PyType_Type;
+#else
+      if (PyType_Ready(&varlink_type) < 0)
+      return NULL;
+#endif
+    }
+    return &varlink_type;
+  }
+  
+  /* Create a variable linking object for use later */
+  SWIGINTERN PyObject *
+  SWIG_Python_newvarlink(void) {
+    swig_varlinkobject *result = PyObject_NEW(swig_varlinkobject, swig_varlink_type());
+    if (result) {
+      result->vars = 0;
+    }
+    return ((PyObject*) result);
+  }
+  
+  SWIGINTERN void 
+  SWIG_Python_addvarlink(PyObject *p, char *name, PyObject *(*get_attr)(void), int (*set_attr)(PyObject *p)) {
+    swig_varlinkobject *v = (swig_varlinkobject *) p;
+    swig_globalvar *gv = (swig_globalvar *) malloc(sizeof(swig_globalvar));
+    if (gv) {
+      size_t size = strlen(name)+1;
+      gv->name = (char *)malloc(size);
+      if (gv->name) {
+        strncpy(gv->name,name,size);
+        gv->get_attr = get_attr;
+        gv->set_attr = set_attr;
+        gv->next = v->vars;
+      }
+    }
+    v->vars = gv;
+  }
+  
+  SWIGINTERN PyObject *
+  SWIG_globals(void) {
+    static PyObject *_SWIG_globals = 0; 
+    if (!_SWIG_globals) _SWIG_globals = SWIG_newvarlink();  
+    return _SWIG_globals;
+  }
+  
+  /* -----------------------------------------------------------------------------
+   * constants/methods manipulation
+   * ----------------------------------------------------------------------------- */
+  
+  /* Install Constants */
+  SWIGINTERN void
+  SWIG_Python_InstallConstants(PyObject *d, swig_const_info constants[]) {
+    PyObject *obj = 0;
+    size_t i;
+    for (i = 0; constants[i].type; ++i) {
+      switch(constants[i].type) {
+      case SWIG_PY_POINTER:
+        obj = SWIG_InternalNewPointerObj(constants[i].pvalue, *(constants[i]).ptype,0);
+        break;
+      case SWIG_PY_BINARY:
+        obj = SWIG_NewPackedObj(constants[i].pvalue, constants[i].lvalue, *(constants[i].ptype));
+        break;
+      default:
+        obj = 0;
+        break;
+      }
+      if (obj) {
+        PyDict_SetItemString(d, constants[i].name, obj);
+        Py_DECREF(obj);
+      }
+    }
+  }
+  
+  /* -----------------------------------------------------------------------------*/
+  /* Fix SwigMethods to carry the callback ptrs when needed */
+  /* -----------------------------------------------------------------------------*/
+  
+  SWIGINTERN void
+  SWIG_Python_FixMethods(PyMethodDef *methods,
+    swig_const_info *const_table,
+    swig_type_info **types,
+    swig_type_info **types_initial) {
+    size_t i;
+    for (i = 0; methods[i].ml_name; ++i) {
+      const char *c = methods[i].ml_doc;
+      if (c && (c = strstr(c, "swig_ptr: "))) {
+        int j;
+        swig_const_info *ci = 0;
+        const char *name = c + 10;
+        for (j = 0; const_table[j].type; ++j) {
+          if (strncmp(const_table[j].name, name, 
+              strlen(const_table[j].name)) == 0) {
+            ci = &(const_table[j]);
+            break;
+          }
+        }
+        if (ci) {
+          void *ptr = (ci->type == SWIG_PY_POINTER) ? ci->pvalue : 0;
+          if (ptr) {
+            size_t shift = (ci->ptype) - types;
+            swig_type_info *ty = types_initial[shift];
+            size_t ldoc = (c - methods[i].ml_doc);
+            size_t lptr = strlen(ty->name)+2*sizeof(void*)+2;
+            char *ndoc = (char*)malloc(ldoc + lptr + 10);
+            if (ndoc) {
+              char *buff = ndoc;
+              strncpy(buff, methods[i].ml_doc, ldoc);
+              buff += ldoc;
+              memcpy(buff, "swig_ptr: ", 10);
+              buff += 10;
+              SWIG_PackVoidPtr(buff, ptr, ty->name, lptr);
+              methods[i].ml_doc = ndoc;
+            }
+          }
+        }
+      }
+    }
+  } 
+  
+#ifdef __cplusplus
+}
+#endif
+
+/* -----------------------------------------------------------------------------*
+ *  Partial Init method
+ * -----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+#endif
+
+SWIGEXPORT 
+#if PY_VERSION_HEX >= 0x03000000
+PyObject*
+#else
+void
+#endif
+SWIG_init(void) {
+  PyObject *m, *d, *md;
+#if PY_VERSION_HEX >= 0x03000000
+  static struct PyModuleDef SWIG_module = {
+# if PY_VERSION_HEX >= 0x03020000
+    PyModuleDef_HEAD_INIT,
+# else
+    {
+      PyObject_HEAD_INIT(NULL)
+      NULL, /* m_init */
+      0,    /* m_index */
+      NULL, /* m_copy */
+    },
+# endif
+    (char *) SWIG_name,
+    NULL,
+    -1,
+    SwigMethods,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+  };
+#endif
+  
+#if defined(SWIGPYTHON_BUILTIN)
+  static SwigPyClientData SwigPyObject_clientdata = {
+    0, 0, 0, 0, 0, 0, 0
+  };
+  static PyGetSetDef this_getset_def = {
+    (char *)"this", &SwigPyBuiltin_ThisClosure, NULL, NULL, NULL
+  };
+  static SwigPyGetSet thisown_getset_closure = {
+    (PyCFunction) SwigPyObject_own,
+    (PyCFunction) SwigPyObject_own
+  };
+  static PyGetSetDef thisown_getset_def = {
+    (char *)"thisown", SwigPyBuiltin_GetterClosure, SwigPyBuiltin_SetterClosure, NULL, &thisown_getset_closure
+  };
+  PyObject *metatype_args;
+  PyTypeObject *builtin_pytype;
+  int builtin_base_count;
+  swig_type_info *builtin_basetype;
+  PyObject *tuple;
+  PyGetSetDescrObject *static_getset;
+  PyTypeObject *metatype;
+  SwigPyClientData *cd;
+  PyObject *public_interface, *public_symbol;
+  PyObject *this_descr;
+  PyObject *thisown_descr;
+  int i;
+  
+  (void)builtin_pytype;
+  (void)builtin_base_count;
+  (void)builtin_basetype;
+  (void)tuple;
+  (void)static_getset;
+  
+  /* metatype is used to implement static member variables. */
+  metatype_args = Py_BuildValue("(s(O){})", "SwigPyObjectType", &PyType_Type);
+  assert(metatype_args);
+  metatype = (PyTypeObject *) PyType_Type.tp_call((PyObject *) &PyType_Type, metatype_args, NULL);
+  assert(metatype);
+  Py_DECREF(metatype_args);
+  metatype->tp_setattro = (setattrofunc) &SwigPyObjectType_setattro;
+  assert(PyType_Ready(metatype) >= 0);
+#endif
+  
+  /* Fix SwigMethods to carry the callback ptrs when needed */
+  SWIG_Python_FixMethods(SwigMethods, swig_const_table, swig_types, swig_type_initial);
+  
+#if PY_VERSION_HEX >= 0x03000000
+  m = PyModule_Create(&SWIG_module);
+#else
+  m = Py_InitModule((char *) SWIG_name, SwigMethods);
+#endif
+  md = d = PyModule_GetDict(m);
+  (void)md;
+  
+  SWIG_InitializeModule(0);
+  
+#ifdef SWIGPYTHON_BUILTIN
+  SwigPyObject_stype = SWIG_MangledTypeQuery("_p_SwigPyObject");
+  assert(SwigPyObject_stype);
+  cd = (SwigPyClientData*) SwigPyObject_stype->clientdata;
+  if (!cd) {
+    SwigPyObject_stype->clientdata = &SwigPyObject_clientdata;
+    SwigPyObject_clientdata.pytype = SwigPyObject_TypeOnce();
+  } else if (SwigPyObject_TypeOnce()->tp_basicsize != cd->pytype->tp_basicsize) {
+    PyErr_SetString(PyExc_RuntimeError, "Import error: attempted to load two incompatible swig-generated modules.");
+# if PY_VERSION_HEX >= 0x03000000
+    return NULL;
+# else
+    return;
+# endif
+  }
+  
+  /* All objects have a 'this' attribute */
+  this_descr = PyDescr_NewGetSet(SwigPyObject_type(), &this_getset_def);
+  (void)this_descr;
+  
+  /* All objects have a 'thisown' attribute */
+  thisown_descr = PyDescr_NewGetSet(SwigPyObject_type(), &thisown_getset_def);
+  (void)thisown_descr;
+  
+  public_interface = PyList_New(0);
+  public_symbol = 0;
+  (void)public_symbol;
+  
+  PyDict_SetItemString(md, "__all__", public_interface);
+  Py_DECREF(public_interface);
+  for (i = 0; SwigMethods[i].ml_name != NULL; ++i)
+  SwigPyBuiltin_AddPublicSymbol(public_interface, SwigMethods[i].ml_name);
+  for (i = 0; swig_const_table[i].name != 0; ++i)
+  SwigPyBuiltin_AddPublicSymbol(public_interface, swig_const_table[i].name);
+#endif
+  
+  SWIG_InstallConstants(d,swig_const_table);
+  
+  SWIG_Python_SetConstant(d, "GATDijkstraShortestPath",SWIG_From_int(static_cast< int >(GATDijkstraShortestPath)));
+  SWIG_Python_SetConstant(d, "GATKShortestPath",SWIG_From_int(static_cast< int >(GATKShortestPath)));
+  SWIG_Python_SetConstant(d, "GATConnectedComponents",SWIG_From_int(static_cast< int >(GATConnectedComponents)));
+  SWIG_Python_SetConstant(d, "GNM_EDGE_DIR_BOTH",SWIG_From_int(static_cast< int >(0)));
+  SWIG_Python_SetConstant(d, "GNM_EDGE_DIR_SRCTOTGT",SWIG_From_int(static_cast< int >(1)));
+  SWIG_Python_SetConstant(d, "GNM_EDGE_DIR_TGTTOSRC",SWIG_From_int(static_cast< int >(2)));
+#if PY_VERSION_HEX >= 0x03000000
+  return m;
+#else
+  return;
+#endif
+}
+
diff --git a/swig/python/extensions/ogr_wrap.cpp b/swig/python/extensions/ogr_wrap.cpp
index 7d5c5cf..884312a 100644
--- a/swig/python/extensions/ogr_wrap.cpp
+++ b/swig/python/extensions/ogr_wrap.cpp
@@ -1,14 +1,15 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.40
- * 
- * This file is not intended to be easily readable and contains a number of 
+ * Version 2.0.12
+ *
+ * This file is not intended to be easily readable and contains a number of
  * coding conventions designed to improve portability and efficiency. Do not make
- * changes to this file unless you know what you are doing--modify the SWIG 
- * interface file instead. 
+ * changes to this file unless you know what you are doing--modify the SWIG
+ * interface file instead.
  * ----------------------------------------------------------------------------- */
 
 #define SWIGPYTHON
+#define SED_HACKS
 #define SWIG_PYTHON_DIRECTOR_NO_VTABLE
 
 
@@ -66,28 +67,28 @@ template <typename T> T SwigValueInit() {
 #ifndef SWIGUNUSED
 # if defined(__GNUC__)
 #   if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
-#     define SWIGUNUSED __attribute__ ((__unused__)) 
+#     define SWIGUNUSED __attribute__ ((__unused__))
 #   else
 #     define SWIGUNUSED
 #   endif
 # elif defined(__ICC)
-#   define SWIGUNUSED __attribute__ ((__unused__)) 
+#   define SWIGUNUSED __attribute__ ((__unused__))
 # else
-#   define SWIGUNUSED 
+#   define SWIGUNUSED
 # endif
 #endif
 
 #ifndef SWIG_MSC_UNSUPPRESS_4505
 # if defined(_MSC_VER)
 #   pragma warning(disable : 4505) /* unreferenced local function has been removed */
-# endif 
+# endif
 #endif
 
 #ifndef SWIGUNUSEDPARM
 # ifdef __cplusplus
 #   define SWIGUNUSEDPARM(p)
 # else
-#   define SWIGUNUSEDPARM(p) p SWIGUNUSED 
+#   define SWIGUNUSEDPARM(p) p SWIGUNUSED
 # endif
 #endif
 
@@ -130,7 +131,7 @@ template <typename T> T SwigValueInit() {
 #   define SWIGSTDCALL __stdcall
 # else
 #   define SWIGSTDCALL
-# endif 
+# endif
 #endif
 
 /* Deal with Microsoft's attempt at deprecating C standard runtime functions */
@@ -145,8 +146,14 @@ template <typename T> T SwigValueInit() {
 
 
 
-/* Python.h has to appear first */
-#include <Python.h>
+#if defined(_DEBUG) && defined(SWIG_PYTHON_INTERPRETER_NO_DEBUG)
+/* Use debug wrappers with the Python release dll */
+# undef _DEBUG
+# include <Python.h>
+# define _DEBUG
+#else
+# include <Python.h>
+#endif
 
 /* -----------------------------------------------------------------------------
  * swigrun.swg
@@ -172,7 +179,7 @@ template <typename T> T SwigValueInit() {
   You can use the SWIGRUNTIME and SWIGRUNTIMEINLINE macros for
   creating a static or dynamic library from the SWIG runtime code.
   In 99.9% of the cases, SWIG just needs to declare them as 'static'.
-  
+
   But only do this if strictly necessary, ie, if you have problems
   with your compiler or suchlike.
 */
@@ -198,16 +205,16 @@ template <typename T> T SwigValueInit() {
 #define SWIG_POINTER_OWN           0x1
 
 
-/* 
+/*
    Flags/methods for returning states.
-   
-   The SWIG conversion methods, as ConvertPtr, return and integer 
+
+   The SWIG conversion methods, as ConvertPtr, return an integer
    that tells if the conversion was successful or not. And if not,
    an error code can be returned (see swigerrors.swg for the codes).
-   
+
    Use the following macros/flags to set or process the returning
    states.
-   
+
    In old versions of SWIG, code such as the following was usually written:
 
      if (SWIG_ConvertPtr(obj,vptr,ty.flags) != -1) {
@@ -240,23 +247,23 @@ template <typename T> T SwigValueInit() {
     } else {
       // fail code
     }
-    
+
    I.e., now SWIG_ConvertPtr can return new objects and you can
    identify the case and take care of the deallocation. Of course that
    also requires SWIG_ConvertPtr to return new result values, such as
 
-      int SWIG_ConvertPtr(obj, ptr,...) {         
-        if (<obj is ok>) {			       
-          if (<need new object>) {		       
-            *ptr = <ptr to new allocated object>; 
-            return SWIG_NEWOBJ;		       
-          } else {				       
-            *ptr = <ptr to old object>;	       
-            return SWIG_OLDOBJ;		       
-          } 				       
-        } else {				       
-          return SWIG_BADOBJ;		       
-        }					       
+      int SWIG_ConvertPtr(obj, ptr,...) {
+        if (<obj is ok>) {
+          if (<need new object>) {
+            *ptr = <ptr to new allocated object>;
+            return SWIG_NEWOBJ;
+          } else {
+            *ptr = <ptr to old object>;
+            return SWIG_OLDOBJ;
+          }
+        } else {
+          return SWIG_BADOBJ;
+        }
       }
 
    Of course, returning the plain '0(success)/-1(fail)' still works, but you can be
@@ -270,17 +277,17 @@ template <typename T> T SwigValueInit() {
        int fooi(int);
 
    and you call
- 
+
       food(1)   // cast rank '1'  (1 -> 1.0)
       fooi(1)   // cast rank '0'
 
    just use the SWIG_AddCast()/SWIG_CheckState()
 */
 
-#define SWIG_OK                    (0) 
+#define SWIG_OK                    (0)
 #define SWIG_ERROR                 (-1)
 #define SWIG_IsOK(r)               (r >= 0)
-#define SWIG_ArgError(r)           ((r != SWIG_ERROR) ? r : SWIG_TypeError)  
+#define SWIG_ArgError(r)           ((r != SWIG_ERROR) ? r : SWIG_TypeError)
 
 /* The CastRankLimit says how many bits are used for the cast rank */
 #define SWIG_CASTRANKLIMIT         (1 << 8)
@@ -311,14 +318,14 @@ template <typename T> T SwigValueInit() {
 #  endif
 #  define SWIG_CASTRANKMASK          ((SWIG_CASTRANKLIMIT) -1)
 #  define SWIG_CastRank(r)           (r & SWIG_CASTRANKMASK)
-SWIGINTERNINLINE int SWIG_AddCast(int r) { 
+SWIGINTERNINLINE int SWIG_AddCast(int r) {
   return SWIG_IsOK(r) ? ((SWIG_CastRank(r) < SWIG_MAXCASTRANK) ? (r + 1) : SWIG_ERROR) : r;
 }
-SWIGINTERNINLINE int SWIG_CheckState(int r) { 
-  return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0; 
+SWIGINTERNINLINE int SWIG_CheckState(int r) {
+  return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0;
 }
 #else /* no cast-rank mode */
-#  define SWIG_AddCast
+#  define SWIG_AddCast(r) (r)
 #  define SWIG_CheckState(r) (SWIG_IsOK(r) ? 1 : 0)
 #endif
 
@@ -362,7 +369,7 @@ typedef struct swig_module_info {
   void                    *clientdata;		/* Language specific module data */
 } swig_module_info;
 
-/* 
+/*
   Compare two type names skipping the space characters, therefore
   "char*" == "char *" and "Class<int>" == "Class<int >", etc.
 
@@ -382,18 +389,18 @@ SWIG_TypeNameComp(const char *f1, const char *l1,
 
 /*
   Check type equivalence in a name list like <name1>|<name2>|...
-  Return 0 if not equal, 1 if equal
+  Return 0 if equal, -1 if nb < tb, 1 if nb > tb
 */
 SWIGRUNTIME int
-SWIG_TypeEquiv(const char *nb, const char *tb) {
-  int equiv = 0;
+SWIG_TypeCmp(const char *nb, const char *tb) {
+  int equiv = 1;
   const char* te = tb + strlen(tb);
   const char* ne = nb;
-  while (!equiv && *ne) {
+  while (equiv != 0 && *ne) {
     for (nb = ne; *ne; ++ne) {
       if (*ne == '|') break;
     }
-    equiv = (SWIG_TypeNameComp(nb, ne, tb, te) == 0) ? 1 : 0;
+    equiv = SWIG_TypeNameComp(nb, ne, tb, te);
     if (*ne) ++ne;
   }
   return equiv;
@@ -401,24 +408,13 @@ SWIG_TypeEquiv(const char *nb, const char *tb) {
 
 /*
   Check type equivalence in a name list like <name1>|<name2>|...
-  Return 0 if equal, -1 if nb < tb, 1 if nb > tb
+  Return 0 if not equal, 1 if equal
 */
 SWIGRUNTIME int
-SWIG_TypeCompare(const char *nb, const char *tb) {
-  int equiv = 0;
-  const char* te = tb + strlen(tb);
-  const char* ne = nb;
-  while (!equiv && *ne) {
-    for (nb = ne; *ne; ++ne) {
-      if (*ne == '|') break;
-    }
-    equiv = (SWIG_TypeNameComp(nb, ne, tb, te) == 0) ? 1 : 0;
-    if (*ne) ++ne;
-  }
-  return equiv;
+SWIG_TypeEquiv(const char *nb, const char *tb) {
+  return SWIG_TypeCmp(nb, tb) == 0 ? 1 : 0;
 }
 
-
 /*
   Check the typename
 */
@@ -446,7 +442,7 @@ SWIG_TypeCheck(const char *c, swig_type_info *ty) {
   return 0;
 }
 
-/* 
+/*
   Identical to SWIG_TypeCheck, except strcmp is replaced with a pointer comparison
 */
 SWIGRUNTIME swig_cast_info *
@@ -481,7 +477,7 @@ SWIG_TypeCast(swig_cast_info *ty, void *ptr, int *newmemory) {
   return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr, newmemory);
 }
 
-/* 
+/*
    Dynamic pointer casting. Down an inheritance hierarchy
 */
 SWIGRUNTIME swig_type_info *
@@ -525,7 +521,7 @@ SWIG_TypePrettyName(const swig_type_info *type) {
     return type->name;
 }
 
-/* 
+/*
    Set the clientdata field for a type
 */
 SWIGRUNTIME void
@@ -533,14 +529,14 @@ SWIG_TypeClientData(swig_type_info *ti, void *clientdata) {
   swig_cast_info *cast = ti->cast;
   /* if (ti->clientdata == clientdata) return; */
   ti->clientdata = clientdata;
-  
+
   while (cast) {
     if (!cast->converter) {
       swig_type_info *tc = cast->type;
       if (!tc->clientdata) {
 	SWIG_TypeClientData(tc, clientdata);
       }
-    }    
+    }
     cast = cast->next;
   }
 }
@@ -549,18 +545,18 @@ SWIG_TypeNewClientData(swig_type_info *ti, void *clientdata) {
   SWIG_TypeClientData(ti, clientdata);
   ti->owndata = 1;
 }
-  
+
 /*
   Search for a swig_type_info structure only by mangled name
   Search is a O(log #types)
-  
-  We start searching at module start, and finish searching when start == end.  
+
+  We start searching at module start, and finish searching when start == end.
   Note: if start == end at the beginning of the function, we go all the way around
   the circular list.
 */
 SWIGRUNTIME swig_type_info *
-SWIG_MangledTypeQueryModule(swig_module_info *start, 
-                            swig_module_info *end, 
+SWIG_MangledTypeQueryModule(swig_module_info *start,
+                            swig_module_info *end,
 		            const char *name) {
   swig_module_info *iter = start;
   do {
@@ -569,11 +565,11 @@ SWIG_MangledTypeQueryModule(swig_module_info *start,
       register size_t r = iter->size - 1;
       do {
 	/* since l+r >= 0, we can (>> 1) instead (/ 2) */
-	register size_t i = (l + r) >> 1; 
+	register size_t i = (l + r) >> 1;
 	const char *iname = iter->types[i]->name;
 	if (iname) {
 	  register int compare = strcmp(name, iname);
-	  if (compare == 0) {	    
+	  if (compare == 0) {
 	    return iter->types[i];
 	  } else if (compare < 0) {
 	    if (i) {
@@ -598,14 +594,14 @@ SWIG_MangledTypeQueryModule(swig_module_info *start,
   Search for a swig_type_info structure for either a mangled name or a human readable name.
   It first searches the mangled names of the types, which is a O(log #types)
   If a type is not found it then searches the human readable names, which is O(#types).
-  
-  We start searching at module start, and finish searching when start == end.  
+
+  We start searching at module start, and finish searching when start == end.
   Note: if start == end at the beginning of the function, we go all the way around
   the circular list.
 */
 SWIGRUNTIME swig_type_info *
-SWIG_TypeQueryModule(swig_module_info *start, 
-                     swig_module_info *end, 
+SWIG_TypeQueryModule(swig_module_info *start,
+                     swig_module_info *end,
 		     const char *name) {
   /* STEP 1: Search the name field using binary search */
   swig_type_info *ret = SWIG_MangledTypeQueryModule(start, end, name);
@@ -624,12 +620,12 @@ SWIG_TypeQueryModule(swig_module_info *start,
       iter = iter->next;
     } while (iter != end);
   }
-  
+
   /* neither found a match */
   return 0;
 }
 
-/* 
+/*
    Pack binary data into a string
 */
 SWIGRUNTIME char *
@@ -645,7 +641,7 @@ SWIG_PackData(char *c, void *ptr, size_t sz) {
   return c;
 }
 
-/* 
+/*
    Unpack binary data from a string
 */
 SWIGRUNTIME const char *
@@ -659,21 +655,21 @@ SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
       uu = ((d - '0') << 4);
     else if ((d >= 'a') && (d <= 'f'))
       uu = ((d - ('a'-10)) << 4);
-    else 
+    else
       return (char *) 0;
     d = *(c++);
     if ((d >= '0') && (d <= '9'))
       uu |= (d - '0');
     else if ((d >= 'a') && (d <= 'f'))
       uu |= (d - ('a'-10));
-    else 
+    else
       return (char *) 0;
     *u = uu;
   }
   return c;
 }
 
-/* 
+/*
    Pack 'void *' into a string buffer.
 */
 SWIGRUNTIME char *
@@ -733,18 +729,18 @@ SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) {
 #endif
 
 /*  Errors in SWIG */
-#define  SWIG_UnknownError    	   -1 
-#define  SWIG_IOError        	   -2 
-#define  SWIG_RuntimeError   	   -3 
-#define  SWIG_IndexError     	   -4 
-#define  SWIG_TypeError      	   -5 
-#define  SWIG_DivisionByZero 	   -6 
-#define  SWIG_OverflowError  	   -7 
-#define  SWIG_SyntaxError    	   -8 
-#define  SWIG_ValueError     	   -9 
+#define  SWIG_UnknownError    	   -1
+#define  SWIG_IOError        	   -2
+#define  SWIG_RuntimeError   	   -3
+#define  SWIG_IndexError     	   -4
+#define  SWIG_TypeError      	   -5
+#define  SWIG_DivisionByZero 	   -6
+#define  SWIG_OverflowError  	   -7
+#define  SWIG_SyntaxError    	   -8
+#define  SWIG_ValueError     	   -9
 #define  SWIG_SystemError    	   -10
 #define  SWIG_AttributeError 	   -11
-#define  SWIG_MemoryError    	   -12 
+#define  SWIG_MemoryError    	   -12
 #define  SWIG_NullReferenceError   -13
 
 
@@ -756,7 +752,16 @@ SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) {
 #define PyInt_Check(x) PyLong_Check(x)
 #define PyInt_AsLong(x) PyLong_AsLong(x)
 #define PyInt_FromLong(x) PyLong_FromLong(x)
+#define PyInt_FromSize_t(x) PyLong_FromSize_t(x)
+#define PyString_Check(name) PyBytes_Check(name)
+#define PyString_FromString(x) PyUnicode_FromString(x)
 #define PyString_Format(fmt, args)  PyUnicode_Format(fmt, args)
+#define PyString_AsString(str) PyBytes_AsString(str)
+#define PyString_Size(str) PyBytes_Size(str)	
+#define PyString_InternFromString(key) PyUnicode_InternFromString(key)
+#define Py_TPFLAGS_HAVE_CLASS Py_TPFLAGS_BASETYPE
+#define PyString_AS_STRING(x) PyUnicode_AS_STRING(x)
+#define _PyLong_FromSsize_t(x) PyLong_FromSsize_t(x)
 
 #endif
 
@@ -896,6 +901,67 @@ PyObject *PyBool_FromLong(long ok)
 typedef int Py_ssize_t;
 # define PY_SSIZE_T_MAX INT_MAX
 # define PY_SSIZE_T_MIN INT_MIN
+typedef inquiry lenfunc;
+typedef intargfunc ssizeargfunc;
+typedef intintargfunc ssizessizeargfunc;
+typedef intobjargproc ssizeobjargproc;
+typedef intintobjargproc ssizessizeobjargproc;
+typedef getreadbufferproc readbufferproc;
+typedef getwritebufferproc writebufferproc;
+typedef getsegcountproc segcountproc;
+typedef getcharbufferproc charbufferproc;
+static long PyNumber_AsSsize_t (PyObject *x, void *SWIGUNUSEDPARM(exc))
+{
+  long result = 0;
+  PyObject *i = PyNumber_Int(x);
+  if (i) {
+    result = PyInt_AsLong(i);
+    Py_DECREF(i);
+  }
+  return result;
+}
+#endif
+
+#if PY_VERSION_HEX < 0x02050000
+#define PyInt_FromSize_t(x) PyInt_FromLong((long)x)
+#endif
+
+#if PY_VERSION_HEX < 0x02040000
+#define Py_VISIT(op)				\
+  do { 						\
+    if (op) {					\
+      int vret = visit((op), arg);		\
+      if (vret)					\
+        return vret;				\
+    }						\
+  } while (0)
+#endif
+
+#if PY_VERSION_HEX < 0x02030000
+typedef struct {
+  PyTypeObject type;
+  PyNumberMethods as_number;
+  PyMappingMethods as_mapping;
+  PySequenceMethods as_sequence;
+  PyBufferProcs as_buffer;
+  PyObject *name, *slots;
+} PyHeapTypeObject;
+#endif
+
+#if PY_VERSION_HEX < 0x02030000
+typedef destructor freefunc;
+#endif
+
+#if ((PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 6) || \
+     (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION > 0) || \
+     (PY_MAJOR_VERSION > 3))
+# define SWIGPY_USE_CAPSULE
+# define SWIGPY_CAPSULE_NAME ((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer_capsule" SWIG_TYPE_TABLE_NAME)
+#endif
+
+#if PY_VERSION_HEX < 0x03020000
+#define PyDescr_TYPE(x) (((PyDescrObject *)(x))->d_type)
+#define PyDescr_NAME(x) (((PyDescrObject *)(x))->d_name)
 #endif
 
 /* -----------------------------------------------------------------------------
@@ -1042,9 +1108,6 @@ SWIG_Python_AddErrorMsg(const char* mesg)
 
 #ifdef __cplusplus
 extern "C" {
-#if 0
-} /* cc-mode */
-#endif
 #endif
 
 /* -----------------------------------------------------------------------------
@@ -1070,27 +1133,24 @@ typedef struct swig_const_info {
  * Wrapper of PyInstanceMethod_New() used in Python 3
  * It is exported to the generated module, used for -fastproxy
  * ----------------------------------------------------------------------------- */
-SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func)
-{
 #if PY_VERSION_HEX >= 0x03000000
+SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *func)
+{
   return PyInstanceMethod_New(func);
+}
 #else
+SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *SWIGUNUSEDPARM(func))
+{
   return NULL;
-#endif
 }
+#endif
 
 #ifdef __cplusplus
-#if 0
-{ /* cc-mode */
-#endif
 }
 #endif
 
 
 /* -----------------------------------------------------------------------------
- * See the LICENSE file for information on copyright, usage and redistribution
- * of SWIG, and the README file for authors - http://www.swig.org/release.html.
- *
  * pyrun.swg
  *
  * This file contains the runtime support for Python modules
@@ -1105,7 +1165,15 @@ SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func)
 #define SWIG_Python_ConvertPtr(obj, pptr, type, flags)  SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, 0)
 #define SWIG_ConvertPtr(obj, pptr, type, flags)         SWIG_Python_ConvertPtr(obj, pptr, type, flags)
 #define SWIG_ConvertPtrAndOwn(obj,pptr,type,flags,own)  SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, own)
-#define SWIG_NewPointerObj(ptr, type, flags)            SWIG_Python_NewPointerObj(ptr, type, flags)
+
+#ifdef SWIGPYTHON_BUILTIN
+#define SWIG_NewPointerObj(ptr, type, flags)            SWIG_Python_NewPointerObj(self, ptr, type, flags)
+#else
+#define SWIG_NewPointerObj(ptr, type, flags)            SWIG_Python_NewPointerObj(NULL, ptr, type, flags)
+#endif
+
+#define SWIG_InternalNewPointerObj(ptr, type, flags)	SWIG_Python_NewPointerObj(NULL, ptr, type, flags)
+
 #define SWIG_CheckImplicit(ty)                          SWIG_Python_CheckImplicit(ty) 
 #define SWIG_AcquirePtr(ptr, src)                       SWIG_Python_AcquirePtr(ptr, src)
 #define swig_owntype                                    int
@@ -1120,7 +1188,7 @@ SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func)
 
 /* for C or C++ function pointers */
 #define SWIG_ConvertFunctionPtr(obj, pptr, type)        SWIG_Python_ConvertFunctionPtr(obj, pptr, type)
-#define SWIG_NewFunctionPtrObj(ptr, type)               SWIG_Python_NewPointerObj(ptr, type, 0)
+#define SWIG_NewFunctionPtrObj(ptr, type)               SWIG_Python_NewPointerObj(NULL, ptr, type, 0)
 
 /* for C++ member pointers, ie, member methods */
 #define SWIG_ConvertMember(obj, ptr, sz, ty)            SWIG_Python_ConvertPacked(obj, ptr, sz, ty)
@@ -1129,11 +1197,7 @@ SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func)
 
 /* Runtime API */
 
-#if PY_VERSION_HEX >= 0x03020000
-#define SWIG_PYTHON_USE_CAPSULE
-#endif
-
-#define SWIG_GetModule(clientdata)                      SWIG_Python_GetModule()
+#define SWIG_GetModule(clientdata)                      SWIG_Python_GetModule(clientdata)
 #define SWIG_SetModule(clientdata, pointer)             SWIG_Python_SetModule(pointer)
 #define SWIG_NewClientData(obj)                         SwigPyClientData_New(obj)
 
@@ -1159,7 +1223,7 @@ SWIG_Python_SetErrorObj(PyObject *errtype, PyObject *obj) {
 SWIGINTERN void 
 SWIG_Python_SetErrorMsg(PyObject *errtype, const char *msg) {
   SWIG_PYTHON_THREAD_BEGIN_BLOCK;
-  PyErr_SetString(errtype, (char *) msg);
+  PyErr_SetString(errtype, msg);
   SWIG_PYTHON_THREAD_END_BLOCK;
 }
 
@@ -1167,12 +1231,41 @@ SWIG_Python_SetErrorMsg(PyObject *errtype, const char *msg) {
 
 /* Set a constant value */
 
+#if defined(SWIGPYTHON_BUILTIN)
+
+SWIGINTERN void
+SwigPyBuiltin_AddPublicSymbol(PyObject *seq, const char *key) {
+  PyObject *s = PyString_InternFromString(key);
+  PyList_Append(seq, s);
+  Py_DECREF(s);
+}
+
+SWIGINTERN void
+SWIG_Python_SetConstant(PyObject *d, PyObject *public_interface, const char *name, PyObject *obj) {   
+#if PY_VERSION_HEX < 0x02030000
+  PyDict_SetItemString(d, (char *)name, obj);
+#else
+  PyDict_SetItemString(d, name, obj);
+#endif
+  Py_DECREF(obj);
+  if (public_interface)
+    SwigPyBuiltin_AddPublicSymbol(public_interface, name);
+}
+
+#else
+
 SWIGINTERN void
 SWIG_Python_SetConstant(PyObject *d, const char *name, PyObject *obj) {   
-  PyDict_SetItemString(d, (char*) name, obj);
+#if PY_VERSION_HEX < 0x02030000
+  PyDict_SetItemString(d, (char *)name, obj);
+#else
+  PyDict_SetItemString(d, name, obj);
+#endif
   Py_DECREF(obj);                            
 }
 
+#endif
+
 /* Append a value to the result obj */
 
 SWIGINTERN PyObject*
@@ -1233,6 +1326,14 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi
     }
   }  
   if (!PyTuple_Check(args)) {
+    if (min <= 1 && max >= 1) {
+      register int i;
+      objs[0] = args;
+      for (i = 1; i < max; ++i) {
+	objs[i] = 0;
+      }
+      return 2;
+    }
     PyErr_SetString(PyExc_SystemError, "UnpackTuple() argument list is not a tuple");
     return 0;
   } else {
@@ -1285,11 +1386,11 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi
 
 #define SWIG_POINTER_IMPLICIT_CONV  (SWIG_POINTER_DISOWN   << 1)
 
+#define SWIG_BUILTIN_TP_INIT	    (SWIG_POINTER_OWN << 2)
+#define SWIG_BUILTIN_INIT	    (SWIG_BUILTIN_TP_INIT | SWIG_POINTER_OWN)
+
 #ifdef __cplusplus
 extern "C" {
-#if 0
-} /* cc-mode */
-#endif
 #endif
 
 /*  How to access Py_None */
@@ -1340,6 +1441,7 @@ typedef struct {
   PyObject *destroy;
   int delargs;
   int implicitconv;
+  PyTypeObject *pytype;
 } SwigPyClientData;
 
 SWIGRUNTIMEINLINE int 
@@ -1406,13 +1508,13 @@ SwigPyClientData_New(PyObject* obj)
       data->delargs = 0;
     }
     data->implicitconv = 0;
+    data->pytype = 0;
     return data;
   }
 }
 
 SWIGRUNTIME void 
-SwigPyClientData_Del(SwigPyClientData* data)
-{
+SwigPyClientData_Del(SwigPyClientData *data) {
   Py_XDECREF(data->newraw);
   Py_XDECREF(data->newargs);
   Py_XDECREF(data->destroy);
@@ -1426,6 +1528,9 @@ typedef struct {
   swig_type_info *ty;
   int own;
   PyObject *next;
+#ifdef SWIGPYTHON_BUILTIN
+  PyObject *dict;
+#endif
 } SwigPyObject;
 
 SWIGRUNTIME PyObject *
@@ -1476,54 +1581,26 @@ SwigPyObject_repr(SwigPyObject *v, PyObject *args)
 #endif
 {
   const char *name = SWIG_TypePrettyName(v->ty);
-  PyObject *repr = SWIG_Python_str_FromFormat("<Swig Object of type '%s' at %p>", name, v);
+  PyObject *repr = SWIG_Python_str_FromFormat("<Swig Object of type '%s' at %p>", (name ? name : "unknown"), (void *)v);
   if (v->next) {
-#ifdef METH_NOARGS
+# ifdef METH_NOARGS
     PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next);
-#else
+# else
     PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next, args);
-#endif
-#if PY_VERSION_HEX >= 0x03000000
+# endif
+# if PY_VERSION_HEX >= 0x03000000
     PyObject *joined = PyUnicode_Concat(repr, nrep);
     Py_DecRef(repr);
     Py_DecRef(nrep);
     repr = joined;
-#else
+# else
     PyString_ConcatAndDel(&repr,nrep);
-#endif
+# endif
   }
   return repr;  
 }
 
 SWIGRUNTIME int
-SwigPyObject_print(SwigPyObject *v, FILE *fp, int SWIGUNUSEDPARM(flags))
-{
-  char *str;
-#ifdef METH_NOARGS
-  PyObject *repr = SwigPyObject_repr(v);
-#else
-  PyObject *repr = SwigPyObject_repr(v, NULL);
-#endif
-  if (repr) {
-    str = SWIG_Python_str_AsChar(repr); 
-    fputs(str, fp);
-    SWIG_Python_str_DelForPy3(str);
-    Py_DECREF(repr);
-    return 0; 
-  } else {
-    return 1; 
-  }
-}
-
-SWIGRUNTIME PyObject *
-SwigPyObject_str(SwigPyObject *v)
-{
-  char result[SWIG_BUFFER_SIZE];
-  return SWIG_PackVoidPtr(result, v->ptr, v->ty->name, sizeof(result)) ?
-    SWIG_Python_str_FromChar(result) : 0;
-}
-
-SWIGRUNTIME int
 SwigPyObject_compare(SwigPyObject *v, SwigPyObject *w)
 {
   void *i = v->ptr;
@@ -1540,27 +1617,43 @@ SwigPyObject_richcompare(SwigPyObject *v, SwigPyObject *w, int op)
     Py_INCREF(Py_NotImplemented);
     return Py_NotImplemented;
   }
-  if( (SwigPyObject_compare(v, w)==0) == (op == Py_EQ) )
-    res = Py_True;
-  else
-    res = Py_False;
-  Py_INCREF(res);
+  res = PyBool_FromLong( (SwigPyObject_compare(v, w)==0) == (op == Py_EQ) ? 1 : 0);
   return res;  
 }
 
 
-SWIGRUNTIME PyTypeObject* _PySwigObject_type(void);
+SWIGRUNTIME PyTypeObject* SwigPyObject_TypeOnce(void);
 
+#ifdef SWIGPYTHON_BUILTIN
+static swig_type_info *SwigPyObject_stype = 0;
+SWIGRUNTIME PyTypeObject*
+SwigPyObject_type(void) {
+    SwigPyClientData *cd;
+    assert(SwigPyObject_stype);
+    cd = (SwigPyClientData*) SwigPyObject_stype->clientdata;
+    assert(cd);
+    assert(cd->pytype);
+    return cd->pytype;
+}
+#else
 SWIGRUNTIME PyTypeObject*
 SwigPyObject_type(void) {
-  static PyTypeObject *SWIG_STATIC_POINTER(type) = _PySwigObject_type();
+  static PyTypeObject *SWIG_STATIC_POINTER(type) = SwigPyObject_TypeOnce();
   return type;
 }
+#endif
 
 SWIGRUNTIMEINLINE int
 SwigPyObject_Check(PyObject *op) {
+#ifdef SWIGPYTHON_BUILTIN
+  PyTypeObject *target_tp = SwigPyObject_type();
+  if (PyType_IsSubtype(op->ob_type, target_tp))
+    return 1;
+  return (strcmp(op->ob_type->tp_name, "SwigPyObject") == 0);
+#else
   return (Py_TYPE(op) == SwigPyObject_type())
     || (strcmp(Py_TYPE(op)->tp_name,"SwigPyObject") == 0);
+#endif
 }
 
 SWIGRUNTIME PyObject *
@@ -1664,8 +1757,10 @@ SwigPyObject_own(PyObject *v, PyObject *args)
   PyObject *val = 0;
 #if (PY_VERSION_HEX < 0x02020000)
   if (!PyArg_ParseTuple(args,(char *)"|O:own",&val))
-#else
+#elif (PY_VERSION_HEX < 0x02050000)
   if (!PyArg_UnpackTuple(args, (char *)"own", 0, 1, &val)) 
+#else
+  if (!PyArg_UnpackTuple(args, "own", 0, 1, &val)) 
 #endif
     {
       return NULL;
@@ -1697,7 +1792,7 @@ SwigPyObject_own(PyObject *v, PyObject *args)
 static PyMethodDef
 swigobject_methods[] = {
   {(char *)"disown",  (PyCFunction)SwigPyObject_disown,  METH_NOARGS,  (char *)"releases ownership of the pointer"},
-  {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_NOARGS,  (char *)"aquires ownership of the pointer"},
+  {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_NOARGS,  (char *)"acquires ownership of the pointer"},
   {(char *)"own",     (PyCFunction)SwigPyObject_own,     METH_VARARGS, (char *)"returns/sets ownership of the pointer"},
   {(char *)"append",  (PyCFunction)SwigPyObject_append,  METH_O,       (char *)"appends another 'this' object"},
   {(char *)"next",    (PyCFunction)SwigPyObject_next,    METH_NOARGS,  (char *)"returns the next 'this' object"},
@@ -1726,9 +1821,9 @@ SwigPyObject_getattr(SwigPyObject *sobj,char *name)
 #endif
 
 SWIGRUNTIME PyTypeObject*
-_PySwigObject_type(void) {
+SwigPyObject_TypeOnce(void) {
   static char swigobject_doc[] = "Swig object carries a C/C++ instance pointer";
-  
+
   static PyNumberMethods SwigPyObject_as_number = {
     (binaryfunc)0, /*nb_add*/
     (binaryfunc)0, /*nb_subtract*/
@@ -1775,85 +1870,89 @@ _PySwigObject_type(void) {
 #endif
   };
 
-  static PyTypeObject swigpyobject_type;  
+  static PyTypeObject swigpyobject_type;
   static int type_init = 0;
   if (!type_init) {
-    const PyTypeObject tmp
-      = {
-	/* PyObject header changed in Python 3 */
+    const PyTypeObject tmp = {
+      /* PyObject header changed in Python 3 */
 #if PY_VERSION_HEX >= 0x03000000
-	PyVarObject_HEAD_INIT(&PyType_Type, 0)
-#else    
-	PyObject_HEAD_INIT(NULL)
-	0,				    /* ob_size */
-#endif
-	(char *)"SwigPyObject",		    /* tp_name */
-	sizeof(SwigPyObject),		    /* tp_basicsize */
-	0,			            /* tp_itemsize */
-	(destructor)SwigPyObject_dealloc,   /* tp_dealloc */
-	(printfunc)SwigPyObject_print,	    /* tp_print */
+      PyVarObject_HEAD_INIT(NULL, 0)
+#else
+      PyObject_HEAD_INIT(NULL)
+      0,                                    /* ob_size */
+#endif
+      (char *)"SwigPyObject",               /* tp_name */
+      sizeof(SwigPyObject),                 /* tp_basicsize */
+      0,                                    /* tp_itemsize */
+      (destructor)SwigPyObject_dealloc,     /* tp_dealloc */
+      0,				    /* tp_print */
 #if PY_VERSION_HEX < 0x02020000
-	(getattrfunc)SwigPyObject_getattr,  /* tp_getattr */ 
+      (getattrfunc)SwigPyObject_getattr,    /* tp_getattr */
 #else
-	(getattrfunc)0,			    /* tp_getattr */ 
+      (getattrfunc)0,                       /* tp_getattr */
 #endif
-	(setattrfunc)0,			    /* tp_setattr */ 
+      (setattrfunc)0,                       /* tp_setattr */
 #if PY_VERSION_HEX >= 0x03000000
     0, /* tp_reserved in 3.0.1, tp_compare in 3.0.0 but not used */
 #else
-	(cmpfunc)SwigPyObject_compare,	    /* tp_compare */
-#endif
-	(reprfunc)SwigPyObject_repr,	    /* tp_repr */    
-	&SwigPyObject_as_number,	    /* tp_as_number */
-	0,				    /* tp_as_sequence */
-	0,				    /* tp_as_mapping */
-	(hashfunc)0,			    /* tp_hash */
-	(ternaryfunc)0,			    /* tp_call */
-	(reprfunc)SwigPyObject_str,	    /* tp_str */
-	PyObject_GenericGetAttr,            /* tp_getattro */
-	0,				    /* tp_setattro */
-	0,		                    /* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT,	            /* tp_flags */
-	swigobject_doc, 	            /* tp_doc */        
-	0,                                  /* tp_traverse */
-	0,                                  /* tp_clear */
-	(richcmpfunc)SwigPyObject_richcompare,           /* tp_richcompare */
-	0,                                  /* tp_weaklistoffset */
+      (cmpfunc)SwigPyObject_compare,        /* tp_compare */
+#endif
+      (reprfunc)SwigPyObject_repr,          /* tp_repr */
+      &SwigPyObject_as_number,              /* tp_as_number */
+      0,                                    /* tp_as_sequence */
+      0,                                    /* tp_as_mapping */
+      (hashfunc)0,                          /* tp_hash */
+      (ternaryfunc)0,                       /* tp_call */
+      0,				    /* tp_str */
+      PyObject_GenericGetAttr,              /* tp_getattro */
+      0,                                    /* tp_setattro */
+      0,                                    /* tp_as_buffer */
+      Py_TPFLAGS_DEFAULT,                   /* tp_flags */
+      swigobject_doc,                       /* tp_doc */
+      0,                                    /* tp_traverse */
+      0,                                    /* tp_clear */
+      (richcmpfunc)SwigPyObject_richcompare,/* tp_richcompare */
+      0,                                    /* tp_weaklistoffset */
 #if PY_VERSION_HEX >= 0x02020000
-	0,                                  /* tp_iter */
-	0,                                  /* tp_iternext */
-	swigobject_methods,		    /* tp_methods */ 
-	0,			            /* tp_members */
-	0,				    /* tp_getset */	    	
-	0,			            /* tp_base */	        
-	0,				    /* tp_dict */	    	
-	0,				    /* tp_descr_get */  	
-	0,				    /* tp_descr_set */  	
-	0,				    /* tp_dictoffset */ 	
-	0,				    /* tp_init */	    	
-	0,				    /* tp_alloc */	    	
-	0,			            /* tp_new */	    	
-	0,	                            /* tp_free */	   
-	0,                                  /* tp_is_gc */  
-	0,				    /* tp_bases */   
-	0,				    /* tp_mro */
-	0,				    /* tp_cache */   
-	0,				    /* tp_subclasses */
-	0,				    /* tp_weaklist */
+      0,                                    /* tp_iter */
+      0,                                    /* tp_iternext */
+      swigobject_methods,                   /* tp_methods */
+      0,                                    /* tp_members */
+      0,                                    /* tp_getset */
+      0,                                    /* tp_base */
+      0,                                    /* tp_dict */
+      0,                                    /* tp_descr_get */
+      0,                                    /* tp_descr_set */
+      0,                                    /* tp_dictoffset */
+      0,                                    /* tp_init */
+      0,                                    /* tp_alloc */
+      0,                                    /* tp_new */
+      0,                                    /* tp_free */
+      0,                                    /* tp_is_gc */
+      0,                                    /* tp_bases */
+      0,                                    /* tp_mro */
+      0,                                    /* tp_cache */
+      0,                                    /* tp_subclasses */
+      0,                                    /* tp_weaklist */
 #endif
 #if PY_VERSION_HEX >= 0x02030000
-	0,                                  /* tp_del */
+      0,                                    /* tp_del */
+#endif
+#if PY_VERSION_HEX >= 0x02060000
+      0,                                    /* tp_version */
 #endif
 #ifdef COUNT_ALLOCS
-	0,0,0,0                             /* tp_alloc -> tp_next */
+      0,0,0,0                               /* tp_alloc -> tp_next */
 #endif
-      };
+    };
     swigpyobject_type = tmp;
-    /* for Python 3 we already assigned ob_type in PyVarObject_HEAD_INIT() */
-#if PY_VERSION_HEX < 0x03000000
+    type_init = 1;
+#if PY_VERSION_HEX < 0x02020000
     swigpyobject_type.ob_type = &PyType_Type;
+#else
+    if (PyType_Ready(&swigpyobject_type) < 0)
+      return NULL;
 #endif
-    type_init = 1;
   }
   return &swigpyobject_type;
 }
@@ -1927,17 +2026,17 @@ SwigPyPacked_compare(SwigPyPacked *v, SwigPyPacked *w)
   return s ? s : strncmp((char *)v->pack, (char *)w->pack, 2*v->size);
 }
 
-SWIGRUNTIME PyTypeObject* _PySwigPacked_type(void);
+SWIGRUNTIME PyTypeObject* SwigPyPacked_TypeOnce(void);
 
 SWIGRUNTIME PyTypeObject*
 SwigPyPacked_type(void) {
-  static PyTypeObject *SWIG_STATIC_POINTER(type) = _PySwigPacked_type();
+  static PyTypeObject *SWIG_STATIC_POINTER(type) = SwigPyPacked_TypeOnce();
   return type;
 }
 
 SWIGRUNTIMEINLINE int
 SwigPyPacked_Check(PyObject *op) {
-  return ((op)->ob_type == _PySwigPacked_type()) 
+  return ((op)->ob_type == SwigPyPacked_TypeOnce()) 
     || (strcmp((op)->ob_type->tp_name,"SwigPyPacked") == 0);
 }
 
@@ -1952,83 +2051,87 @@ SwigPyPacked_dealloc(PyObject *v)
 }
 
 SWIGRUNTIME PyTypeObject*
-_PySwigPacked_type(void) {
+SwigPyPacked_TypeOnce(void) {
   static char swigpacked_doc[] = "Swig object carries a C/C++ instance pointer";
   static PyTypeObject swigpypacked_type;
-  static int type_init = 0;  
+  static int type_init = 0;
   if (!type_init) {
-    const PyTypeObject tmp
-      = {
-    /* PyObject header changed in Python 3 */
+    const PyTypeObject tmp = {
+      /* PyObject header changed in Python 3 */
 #if PY_VERSION_HEX>=0x03000000
-    PyVarObject_HEAD_INIT(&PyType_Type, 0)
+      PyVarObject_HEAD_INIT(NULL, 0)
 #else
-	PyObject_HEAD_INIT(NULL)
-    0,				    /* ob_size */	
-#endif
-	(char *)"SwigPyPacked",		    /* tp_name */	
-	sizeof(SwigPyPacked),		    /* tp_basicsize */	
-	0,				    /* tp_itemsize */	
-	(destructor)SwigPyPacked_dealloc,   /* tp_dealloc */	
-	(printfunc)SwigPyPacked_print,	    /* tp_print */   	
-	(getattrfunc)0,			    /* tp_getattr */ 	
-	(setattrfunc)0,			    /* tp_setattr */ 	
+      PyObject_HEAD_INIT(NULL)
+      0,                                    /* ob_size */
+#endif
+      (char *)"SwigPyPacked",               /* tp_name */
+      sizeof(SwigPyPacked),                 /* tp_basicsize */
+      0,                                    /* tp_itemsize */
+      (destructor)SwigPyPacked_dealloc,     /* tp_dealloc */
+      (printfunc)SwigPyPacked_print,        /* tp_print */
+      (getattrfunc)0,                       /* tp_getattr */
+      (setattrfunc)0,                       /* tp_setattr */
 #if PY_VERSION_HEX>=0x03000000
-    0, /* tp_reserved in 3.0.1 */
+      0, /* tp_reserved in 3.0.1 */
 #else
-    (cmpfunc)SwigPyPacked_compare,	    /* tp_compare */
-#endif
-	(reprfunc)SwigPyPacked_repr,	    /* tp_repr */
-	0,	                            /* tp_as_number */
-	0,				    /* tp_as_sequence */
-	0,				    /* tp_as_mapping */
-	(hashfunc)0,			    /* tp_hash */
-	(ternaryfunc)0,			    /* tp_call */
-	(reprfunc)SwigPyPacked_str,	    /* tp_str */
-	PyObject_GenericGetAttr,            /* tp_getattro */
-	0,				    /* tp_setattro */
-	0,		                    /* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT,	            /* tp_flags */
-	swigpacked_doc, 	            /* tp_doc */
-	0,                                  /* tp_traverse */
-	0,                                  /* tp_clear */
-	0,                                  /* tp_richcompare */
-	0,                                  /* tp_weaklistoffset */
+      (cmpfunc)SwigPyPacked_compare,        /* tp_compare */
+#endif
+      (reprfunc)SwigPyPacked_repr,          /* tp_repr */
+      0,                                    /* tp_as_number */
+      0,                                    /* tp_as_sequence */
+      0,                                    /* tp_as_mapping */
+      (hashfunc)0,                          /* tp_hash */
+      (ternaryfunc)0,                       /* tp_call */
+      (reprfunc)SwigPyPacked_str,           /* tp_str */
+      PyObject_GenericGetAttr,              /* tp_getattro */
+      0,                                    /* tp_setattro */
+      0,                                    /* tp_as_buffer */
+      Py_TPFLAGS_DEFAULT,                   /* tp_flags */
+      swigpacked_doc,                       /* tp_doc */
+      0,                                    /* tp_traverse */
+      0,                                    /* tp_clear */
+      0,                                    /* tp_richcompare */
+      0,                                    /* tp_weaklistoffset */
 #if PY_VERSION_HEX >= 0x02020000
-	0,                                  /* tp_iter */
-	0,                                  /* tp_iternext */
-	0,		                    /* tp_methods */ 
-	0,			            /* tp_members */
-	0,				    /* tp_getset */	    	
-	0,			            /* tp_base */	        
-	0,				    /* tp_dict */	    	
-	0,				    /* tp_descr_get */  	
-	0,				    /* tp_descr_set */  	
-	0,				    /* tp_dictoffset */ 	
-	0,				    /* tp_init */	    	
-	0,				    /* tp_alloc */	    	
-	0,			            /* tp_new */	    	
-	0, 	                            /* tp_free */	   
-        0,                                  /* tp_is_gc */  
-	0,				    /* tp_bases */   
-	0,				    /* tp_mro */
-	0,				    /* tp_cache */   
- 	0,				    /* tp_subclasses */
-	0,				    /* tp_weaklist */
+      0,                                    /* tp_iter */
+      0,                                    /* tp_iternext */
+      0,                                    /* tp_methods */
+      0,                                    /* tp_members */
+      0,                                    /* tp_getset */
+      0,                                    /* tp_base */
+      0,                                    /* tp_dict */
+      0,                                    /* tp_descr_get */
+      0,                                    /* tp_descr_set */
+      0,                                    /* tp_dictoffset */
+      0,                                    /* tp_init */
+      0,                                    /* tp_alloc */
+      0,                                    /* tp_new */
+      0,                                    /* tp_free */
+      0,                                    /* tp_is_gc */
+      0,                                    /* tp_bases */
+      0,                                    /* tp_mro */
+      0,                                    /* tp_cache */
+      0,                                    /* tp_subclasses */
+      0,                                    /* tp_weaklist */
 #endif
 #if PY_VERSION_HEX >= 0x02030000
-	0,                                  /* tp_del */
+      0,                                    /* tp_del */
+#endif
+#if PY_VERSION_HEX >= 0x02060000
+      0,                                    /* tp_version */
 #endif
 #ifdef COUNT_ALLOCS
-	0,0,0,0                             /* tp_alloc -> tp_next */
+      0,0,0,0                               /* tp_alloc -> tp_next */
 #endif
-      };
+    };
     swigpypacked_type = tmp;
-    /* for Python 3 the ob_type already assigned in PyVarObject_HEAD_INIT() */
-#if PY_VERSION_HEX < 0x03000000
+    type_init = 1;
+#if PY_VERSION_HEX < 0x02020000
     swigpypacked_type.ob_type = &PyType_Type;
+#else
+    if (PyType_Ready(&swigpypacked_type) < 0)
+      return NULL;
 #endif
-    type_init = 1;
   }
   return &swigpypacked_type;
 }
@@ -2075,10 +2178,13 @@ _SWIG_This(void)
     return SWIG_Python_str_FromChar("this");
 }
 
+static PyObject *swig_this = NULL;
+
 SWIGRUNTIME PyObject *
 SWIG_This(void)
 {
-  static PyObject *SWIG_STATIC_POINTER(swig_this) = _SWIG_This();
+  if (swig_this == NULL)
+    swig_this = _SWIG_This();
   return swig_this;
 }
 
@@ -2092,50 +2198,65 @@ SWIG_This(void)
 SWIGRUNTIME SwigPyObject *
 SWIG_Python_GetSwigThis(PyObject *pyobj) 
 {
-  if (SwigPyObject_Check(pyobj)) {
+  PyObject *obj;
+
+  if (SwigPyObject_Check(pyobj))
     return (SwigPyObject *) pyobj;
-  } else {
-    PyObject *obj = 0;
+
+#ifdef SWIGPYTHON_BUILTIN
+  (void)obj;
+# ifdef PyWeakref_CheckProxy
+  if (PyWeakref_CheckProxy(pyobj)) {
+    pyobj = PyWeakref_GET_OBJECT(pyobj);
+    if (pyobj && SwigPyObject_Check(pyobj))
+      return (SwigPyObject*) pyobj;
+  }
+# endif
+  return NULL;
+#else
+
+  obj = 0;
+
 #if (!defined(SWIG_PYTHON_SLOW_GETSET_THIS) && (PY_VERSION_HEX >= 0x02030000))
-    if (PyInstance_Check(pyobj)) {
-      obj = _PyInstance_Lookup(pyobj, SWIG_This());      
+  if (PyInstance_Check(pyobj)) {
+    obj = _PyInstance_Lookup(pyobj, SWIG_This());      
+  } else {
+    PyObject **dictptr = _PyObject_GetDictPtr(pyobj);
+    if (dictptr != NULL) {
+      PyObject *dict = *dictptr;
+      obj = dict ? PyDict_GetItem(dict, SWIG_This()) : 0;
     } else {
-      PyObject **dictptr = _PyObject_GetDictPtr(pyobj);
-      if (dictptr != NULL) {
-	PyObject *dict = *dictptr;
-	obj = dict ? PyDict_GetItem(dict, SWIG_This()) : 0;
-      } else {
 #ifdef PyWeakref_CheckProxy
-	if (PyWeakref_CheckProxy(pyobj)) {
-	  PyObject *wobj = PyWeakref_GET_OBJECT(pyobj);
-	  return wobj ? SWIG_Python_GetSwigThis(wobj) : 0;
-	}
+      if (PyWeakref_CheckProxy(pyobj)) {
+	PyObject *wobj = PyWeakref_GET_OBJECT(pyobj);
+	return wobj ? SWIG_Python_GetSwigThis(wobj) : 0;
+      }
 #endif
-	obj = PyObject_GetAttr(pyobj,SWIG_This());
-	if (obj) {
-	  Py_DECREF(obj);
-	} else {
-	  if (PyErr_Occurred()) PyErr_Clear();
-	  return 0;
-	}
+      obj = PyObject_GetAttr(pyobj,SWIG_This());
+      if (obj) {
+	Py_DECREF(obj);
+      } else {
+	if (PyErr_Occurred()) PyErr_Clear();
+	return 0;
       }
     }
+  }
 #else
-    obj = PyObject_GetAttr(pyobj,SWIG_This());
-    if (obj) {
-      Py_DECREF(obj);
-    } else {
-      if (PyErr_Occurred()) PyErr_Clear();
-      return 0;
-    }
+  obj = PyObject_GetAttr(pyobj,SWIG_This());
+  if (obj) {
+    Py_DECREF(obj);
+  } else {
+    if (PyErr_Occurred()) PyErr_Clear();
+    return 0;
+  }
 #endif
-    if (obj && !SwigPyObject_Check(obj)) {
-      /* a PyObject is called 'this', try to get the 'real this'
-	 SwigPyObject from it */ 
-      return SWIG_Python_GetSwigThis(obj);
-    }
-    return (SwigPyObject *)obj;
+  if (obj && !SwigPyObject_Check(obj)) {
+    /* a PyObject is called 'this', try to get the 'real this'
+       SwigPyObject from it */ 
+    return SWIG_Python_GetSwigThis(obj);
   }
+  return (SwigPyObject *)obj;
+#endif
 }
 
 /* Acquire a pointer value */
@@ -2157,91 +2278,105 @@ SWIG_Python_AcquirePtr(PyObject *obj, int own) {
 
 SWIGRUNTIME int
 SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int flags, int *own) {
-  if (!obj) return SWIG_ERROR;
-  if (obj == Py_None) {
-    if (ptr) *ptr = 0;
+  int res;
+  SwigPyObject *sobj;
+  int implicit_conv = (flags & SWIG_POINTER_IMPLICIT_CONV) != 0;
+
+  if (!obj)
+    return SWIG_ERROR;
+  if (obj == Py_None && !implicit_conv) {
+    if (ptr)
+      *ptr = 0;
     return SWIG_OK;
-  } else {
-    SwigPyObject *sobj = SWIG_Python_GetSwigThis(obj);
+  }
+
+  res = SWIG_ERROR;
+
+  sobj = SWIG_Python_GetSwigThis(obj);
+  if (own)
+    *own = 0;
+  while (sobj) {
+    void *vptr = sobj->ptr;
+    if (ty) {
+      swig_type_info *to = sobj->ty;
+      if (to == ty) {
+        /* no type cast needed */
+        if (ptr) *ptr = vptr;
+        break;
+      } else {
+        swig_cast_info *tc = SWIG_TypeCheck(to->name,ty);
+        if (!tc) {
+          sobj = (SwigPyObject *)sobj->next;
+        } else {
+          if (ptr) {
+            int newmemory = 0;
+            *ptr = SWIG_TypeCast(tc,vptr,&newmemory);
+            if (newmemory == SWIG_CAST_NEW_MEMORY) {
+              assert(own); /* badly formed typemap which will lead to a memory leak - it must set and use own to delete *ptr */
+              if (own)
+                *own = *own | SWIG_CAST_NEW_MEMORY;
+            }
+          }
+          break;
+        }
+      }
+    } else {
+      if (ptr) *ptr = vptr;
+      break;
+    }
+  }
+  if (sobj) {
     if (own)
-      *own = 0;
-    while (sobj) {
-      void *vptr = sobj->ptr;
-      if (ty) {
-	swig_type_info *to = sobj->ty;
-	if (to == ty) {
-	  /* no type cast needed */
-	  if (ptr) *ptr = vptr;
-	  break;
-	} else {
-	  swig_cast_info *tc = SWIG_TypeCheck(to->name,ty);
-	  if (!tc) {
-	    sobj = (SwigPyObject *)sobj->next;
-	  } else {
-	    if (ptr) {
-              int newmemory = 0;
-              *ptr = SWIG_TypeCast(tc,vptr,&newmemory);
-              if (newmemory == SWIG_CAST_NEW_MEMORY) {
-                assert(own);
-                if (own)
-                  *own = *own | SWIG_CAST_NEW_MEMORY;
+      *own = *own | sobj->own;
+    if (flags & SWIG_POINTER_DISOWN) {
+      sobj->own = 0;
+    }
+    res = SWIG_OK;
+  } else {
+    if (implicit_conv) {
+      SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0;
+      if (data && !data->implicitconv) {
+        PyObject *klass = data->klass;
+        if (klass) {
+          PyObject *impconv;
+          data->implicitconv = 1; /* avoid recursion and call 'explicit' constructors*/
+          impconv = SWIG_Python_CallFunctor(klass, obj);
+          data->implicitconv = 0;
+          if (PyErr_Occurred()) {
+            PyErr_Clear();
+            impconv = 0;
+          }
+          if (impconv) {
+            SwigPyObject *iobj = SWIG_Python_GetSwigThis(impconv);
+            if (iobj) {
+              void *vptr;
+              res = SWIG_Python_ConvertPtrAndOwn((PyObject*)iobj, &vptr, ty, 0, 0);
+              if (SWIG_IsOK(res)) {
+                if (ptr) {
+                  *ptr = vptr;
+                  /* transfer the ownership to 'ptr' */
+                  iobj->own = 0;
+                  res = SWIG_AddCast(res);
+                  res = SWIG_AddNewMask(res);
+                } else {
+                  res = SWIG_AddCast(res);		    
+                }
               }
             }
-	    break;
-	  }
-	}
-      } else {
-	if (ptr) *ptr = vptr;
-	break;
+            Py_DECREF(impconv);
+          }
+        }
       }
     }
-    if (sobj) {
-      if (own)
-        *own = *own | sobj->own;
-      if (flags & SWIG_POINTER_DISOWN) {
-	sobj->own = 0;
-      }
-      return SWIG_OK;
-    } else {
-      int res = SWIG_ERROR;
-      if (flags & SWIG_POINTER_IMPLICIT_CONV) {
-	SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0;
-	if (data && !data->implicitconv) {
-	  PyObject *klass = data->klass;
-	  if (klass) {
-	    PyObject *impconv;
-	    data->implicitconv = 1; /* avoid recursion and call 'explicit' constructors*/
-	    impconv = SWIG_Python_CallFunctor(klass, obj);
-	    data->implicitconv = 0;
-	    if (PyErr_Occurred()) {
-	      PyErr_Clear();
-	      impconv = 0;
-	    }
-	    if (impconv) {
-	      SwigPyObject *iobj = SWIG_Python_GetSwigThis(impconv);
-	      if (iobj) {
-		void *vptr;
-		res = SWIG_Python_ConvertPtrAndOwn((PyObject*)iobj, &vptr, ty, 0, 0);
-		if (SWIG_IsOK(res)) {
-		  if (ptr) {
-		    *ptr = vptr;
-		    /* transfer the ownership to 'ptr' */
-		    iobj->own = 0;
-		    res = SWIG_AddCast(res);
-		    res = SWIG_AddNewMask(res);
-		  } else {
-		    res = SWIG_AddCast(res);		    
-		  }
-		}
-	      }
-	      Py_DECREF(impconv);
-	    }
-	  }
-	}
-      }
-      return res;
+    if (!SWIG_IsOK(res) && obj == Py_None) {
+      if (ptr)
+        *ptr = 0;
+      if (PyErr_Occurred())
+        PyErr_Clear();
+      res = SWIG_OK;
     }
   }
+  return res;
 }
 
 /* Convert a function ptr value */
@@ -2328,23 +2463,29 @@ SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this)
   } else {
 #if PY_VERSION_HEX >= 0x03000000
     inst = PyBaseObject_Type.tp_new((PyTypeObject*) data->newargs, Py_None, Py_None);
-    PyObject_SetAttr(inst, SWIG_This(), swig_this);
-    Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
+    if (inst) {
+      PyObject_SetAttr(inst, SWIG_This(), swig_this);
+      Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
+    }
 #else
     PyObject *dict = PyDict_New();
-    PyDict_SetItem(dict, SWIG_This(), swig_this);
-    inst = PyInstance_NewRaw(data->newargs, dict);
-    Py_DECREF(dict);
+    if (dict) {
+      PyDict_SetItem(dict, SWIG_This(), swig_this);
+      inst = PyInstance_NewRaw(data->newargs, dict);
+      Py_DECREF(dict);
+    }
 #endif
   }
   return inst;
 #else
 #if (PY_VERSION_HEX >= 0x02010000)
-  PyObject *inst;
+  PyObject *inst = 0;
   PyObject *dict = PyDict_New();
-  PyDict_SetItem(dict, SWIG_This(), swig_this);
-  inst = PyInstance_NewRaw(data->newargs, dict);
-  Py_DECREF(dict);
+  if (dict) {
+    PyDict_SetItem(dict, SWIG_This(), swig_this);
+    inst = PyInstance_NewRaw(data->newargs, dict);
+    Py_DECREF(dict);
+  }
   return (PyObject *) inst;
 #else
   PyInstanceObject *inst = PyObject_NEW(PyInstanceObject, &PyInstance_Type);
@@ -2395,7 +2536,7 @@ SWIG_Python_SetSwigThis(PyObject *inst, PyObject *swig_this)
 SWIGINTERN PyObject *
 SWIG_Python_InitShadowInstance(PyObject *args) {
   PyObject *obj[2];
-  if (!SWIG_Python_UnpackTuple(args,(char*)"swiginit", 2, 2, obj)) {
+  if (!SWIG_Python_UnpackTuple(args, "swiginit", 2, 2, obj)) {
     return NULL;
   } else {
     SwigPyObject *sthis = SWIG_Python_GetSwigThis(obj[0]);
@@ -2411,22 +2552,52 @@ SWIG_Python_InitShadowInstance(PyObject *args) {
 /* Create a new pointer object */
 
 SWIGRUNTIME PyObject *
-SWIG_Python_NewPointerObj(void *ptr, swig_type_info *type, int flags) {
-  if (!ptr) {
+SWIG_Python_NewPointerObj(PyObject *self, void *ptr, swig_type_info *type, int flags) {
+  SwigPyClientData *clientdata;
+  PyObject * robj;
+  int own;
+
+  if (!ptr)
     return SWIG_Py_Void();
-  } else {
-    int own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0;
-    PyObject *robj = SwigPyObject_New(ptr, type, own);
-    SwigPyClientData *clientdata = type ? (SwigPyClientData *)(type->clientdata) : 0;
-    if (clientdata && !(flags & SWIG_POINTER_NOSHADOW)) {
-      PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj);
-      if (inst) {
-	Py_DECREF(robj);
-	robj = inst;
+
+  clientdata = type ? (SwigPyClientData *)(type->clientdata) : 0;
+  own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0;
+  if (clientdata && clientdata->pytype) {
+    SwigPyObject *newobj;
+    if (flags & SWIG_BUILTIN_TP_INIT) {
+      newobj = (SwigPyObject*) self;
+      if (newobj->ptr) {
+        PyObject *next_self = clientdata->pytype->tp_alloc(clientdata->pytype, 0);
+        while (newobj->next)
+	  newobj = (SwigPyObject *) newobj->next;
+        newobj->next = next_self;
+        newobj = (SwigPyObject *)next_self;
       }
+    } else {
+      newobj = PyObject_New(SwigPyObject, clientdata->pytype);
+    }
+    if (newobj) {
+      newobj->ptr = ptr;
+      newobj->ty = type;
+      newobj->own = own;
+      newobj->next = 0;
+#ifdef SWIGPYTHON_BUILTIN
+      newobj->dict = 0;
+#endif
+      return (PyObject*) newobj;
     }
-    return robj;
+    return SWIG_Py_Void();
+  }
+
+  assert(!(flags & SWIG_BUILTIN_TP_INIT));
+
+  robj = SwigPyObject_New(ptr, type, own);
+  if (robj && clientdata && !(flags & SWIG_POINTER_NOSHADOW)) {
+    PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj);
+    Py_DECREF(robj);
+    robj = inst;
   }
+  return robj;
 }
 
 /* Create a new packed object */
@@ -2445,19 +2616,19 @@ void *SWIG_ReturnGlobalTypeList(void *);
 #endif
 
 SWIGRUNTIME swig_module_info *
-SWIG_Python_GetModule(void) {
+SWIG_Python_GetModule(void *SWIGUNUSEDPARM(clientdata)) {
   static void *type_pointer = (void *)0;
   /* first check if module already created */
   if (!type_pointer) {
 #ifdef SWIG_LINK_RUNTIME
     type_pointer = SWIG_ReturnGlobalTypeList((void *)0);
 #else
-#ifdef SWIG_PYTHON_USE_CAPSULE
-    type_pointer = PyCapsule_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer" SWIG_TYPE_TABLE_NAME, 0);
-#else
+# ifdef SWIGPY_USE_CAPSULE
+    type_pointer = PyCapsule_Import(SWIGPY_CAPSULE_NAME, 0);
+# else
     type_pointer = PyCObject_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
 				    (char*)"type_pointer" SWIG_TYPE_TABLE_NAME);
-#endif
+# endif
     if (PyErr_Occurred()) {
       PyErr_Clear();
       type_pointer = (void *)0;
@@ -2500,26 +2671,19 @@ PyModule_AddObject(PyObject *m, char *name, PyObject *o)
 #endif
 
 SWIGRUNTIME void
-#ifdef SWIG_PYTHON_USE_CAPSULE
-SWIG_Python_DestroyModule(PyObject *capsule)
-{
-  swig_module_info *swig_module;
-  swig_type_info **types;
-  size_t i;
-  swig_module = (swig_module_info *)PyCapsule_GetPointer(capsule, (char*)"swig_runtime_data" SWIG_RUNTIME_VERSION);
-  if (swig_module == NULL)
-  {
-    PyErr_Clear();
-    return;
-  }
-  types = swig_module->types;
+#ifdef SWIGPY_USE_CAPSULE
+SWIG_Python_DestroyModule(PyObject *obj)
 #else
 SWIG_Python_DestroyModule(void *vptr)
+#endif
 {
+#ifdef SWIGPY_USE_CAPSULE
+  swig_module_info *swig_module = (swig_module_info *) PyCapsule_GetPointer(obj, SWIGPY_CAPSULE_NAME);
+#else
   swig_module_info *swig_module = (swig_module_info *) vptr;
+#endif
   swig_type_info **types = swig_module->types;
   size_t i;
-#endif
   for (i =0; i < swig_module->size; ++i) {
     swig_type_info *ty = types[i];
     if (ty->owndata) {
@@ -2528,31 +2692,33 @@ SWIG_Python_DestroyModule(void *vptr)
     }
   }
   Py_DECREF(SWIG_This());
+  swig_this = NULL;
 }
 
 SWIGRUNTIME void
 SWIG_Python_SetModule(swig_module_info *swig_module) {
-  static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} };/* Sentinel */
-
 #if PY_VERSION_HEX >= 0x03000000
  /* Add a dummy module object into sys.modules */
   PyObject *module = PyImport_AddModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION);
 #else
-  PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
-				   swig_empty_runtime_method_table);
+  static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} }; /* Sentinel */
+  PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION, swig_empty_runtime_method_table);
 #endif
-#ifdef SWIG_PYTHON_USE_CAPSULE
-  PyObject *pointer = PyCapsule_New((void *) swig_module,
-                                    (char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer" SWIG_TYPE_TABLE_NAME,
-                                    SWIG_Python_DestroyModule);
+#ifdef SWIGPY_USE_CAPSULE
+  PyObject *pointer = PyCapsule_New((void *) swig_module, SWIGPY_CAPSULE_NAME, SWIG_Python_DestroyModule);
+  if (pointer && module) {
+    PyModule_AddObject(module, (char*)"type_pointer_capsule" SWIG_TYPE_TABLE_NAME, pointer);
+  } else {
+    Py_XDECREF(pointer);
+  }
 #else
   PyObject *pointer = PyCObject_FromVoidPtr((void *) swig_module, SWIG_Python_DestroyModule);
-#endif
   if (pointer && module) {
     PyModule_AddObject(module, (char*)"type_pointer" SWIG_TYPE_TABLE_NAME, pointer);
   } else {
     Py_XDECREF(pointer);
   }
+#endif
 }
 
 /* The python cached type query */
@@ -2570,17 +2736,17 @@ SWIG_Python_TypeQuery(const char *type)
   PyObject *obj = PyDict_GetItem(cache, key);
   swig_type_info *descriptor;
   if (obj) {
-#ifdef SWIG_PYTHON_USE_CAPSULE
-    descriptor = (swig_type_info *) PyCapsule_GetPointer(obj, (char*)"swig_type_info");
+#ifdef SWIGPY_USE_CAPSULE
+    descriptor = (swig_type_info *) PyCapsule_GetPointer(obj, NULL);
 #else
     descriptor = (swig_type_info *) PyCObject_AsVoidPtr(obj);
 #endif
   } else {
-    swig_module_info *swig_module = SWIG_Python_GetModule();
+    swig_module_info *swig_module = SWIG_GetModule(0);
     descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type);
     if (descriptor) {
-#ifdef SWIG_PYTHON_USE_CAPSULE
-      obj = PyCapsule_New(descriptor, (char*)"swig_type_info", NULL);
+#ifdef SWIGPY_USE_CAPSULE
+      obj = PyCapsule_New((void*) descriptor, NULL, NULL);
 #else
       obj = PyCObject_FromVoidPtr(descriptor, NULL);
 #endif
@@ -2644,7 +2810,7 @@ SwigPyObject_GetDesc(PyObject *self)
 {
   SwigPyObject *v = (SwigPyObject *)self;
   swig_type_info *ty = v ? v->ty : 0;
-  return ty ? ty->str : (char*)"";
+  return ty ? ty->str : "";
 }
 
 SWIGRUNTIME void
@@ -2687,7 +2853,7 @@ SWIG_Python_TypeError(const char *type, PyObject *obj)
 
 /* Convert a pointer value, signal an exception on a type mismatch */
 SWIGRUNTIME void *
-SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int argnum, int flags) {
+SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int SWIGUNUSEDPARM(argnum), int flags) {
   void *result;
   if (SWIG_Python_ConvertPtr(obj, &result, ty, flags) == -1) {
     PyErr_Clear();
@@ -2701,11 +2867,61 @@ SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int argnum, int flags)
   return result;
 }
 
+#ifdef SWIGPYTHON_BUILTIN
+SWIGRUNTIME int
+SWIG_Python_NonDynamicSetAttr(PyObject *obj, PyObject *name, PyObject *value) {
+  PyTypeObject *tp = obj->ob_type;
+  PyObject *descr;
+  PyObject *encoded_name;
+  descrsetfunc f;
+  int res = -1;
+
+# ifdef Py_USING_UNICODE
+  if (PyString_Check(name)) {
+    name = PyUnicode_Decode(PyString_AsString(name), PyString_Size(name), NULL, NULL);
+    if (!name)
+      return -1;
+  } else if (!PyUnicode_Check(name))
+# else
+  if (!PyString_Check(name))
+# endif
+  {
+    PyErr_Format(PyExc_TypeError, "attribute name must be string, not '%.200s'", name->ob_type->tp_name);
+    return -1;
+  } else {
+    Py_INCREF(name);
+  }
+
+  if (!tp->tp_dict) {
+    if (PyType_Ready(tp) < 0)
+      goto done;
+  }
+
+  descr = _PyType_Lookup(tp, name);
+  f = NULL;
+  if (descr != NULL)
+    f = descr->ob_type->tp_descr_set;
+  if (!f) {
+    if (PyString_Check(name)) {
+      encoded_name = name;
+      Py_INCREF(name);
+    } else {
+      encoded_name = PyUnicode_AsUTF8String(name);
+    }
+    PyErr_Format(PyExc_AttributeError, "'%.100s' object has no attribute '%.200s'", tp->tp_name, PyString_AsString(encoded_name));
+    Py_DECREF(encoded_name);
+  } else {
+    res = f(descr, obj, value);
+  }
+  
+  done:
+  Py_DECREF(name);
+  return res;
+}
+#endif
+
 
 #ifdef __cplusplus
-#if 0
-{ /* cc-mode */
-#endif
 }
 #endif
 
@@ -2770,7 +2986,7 @@ static swig_module_info swig_module = {swig_types, 23, 0, 0, 0, 0};
 #endif
 #define SWIG_name    "_ogr"
 
-#define SWIGVERSION 0x010340 
+#define SWIGVERSION 0x020012 
 #define SWIG_VERSION SWIGVERSION
 
 
@@ -2857,12 +3073,17 @@ using namespace std;
 #include "cpl_string.h"
 #include "ogr_srs_api.h"
 
+#define FIELD_INDEX_ERROR_TMPL "Invalid field index: '%i'"
+#define FIELD_NAME_ERROR_TMPL "Invalid field name: '%s'"
+
 typedef void GDALMajorObjectShadow;
 
-#ifdef DEBUG 
+#ifdef DEBUG
 typedef struct OGRSpatialReferenceHS OSRSpatialReferenceShadow;
+#ifndef SWIGPERL
 typedef struct OGRDriverHS OGRDriverShadow;
 typedef struct OGRDataSourceHS OGRDataSourceShadow;
+#endif
 typedef struct OGRLayerHS OGRLayerShadow;
 typedef struct OGRFeatureHS OGRFeatureShadow;
 typedef struct OGRFeatureDefnHS OGRFeatureDefnShadow;
@@ -2872,8 +3093,10 @@ typedef struct OGRCoordinateTransformationHS OGRCoordinateTransformationShadow;
 typedef struct OGRFieldDefnHS OGRFieldDefnShadow;
 #else
 typedef void OSRSpatialReferenceShadow;
+#ifndef SWIGPERL
 typedef void OGRDriverShadow;
 typedef void OGRDataSourceShadow;
+#endif
 typedef void OGRLayerShadow;
 typedef void OGRFeatureShadow;
 typedef void OGRFeatureDefnShadow;
@@ -2885,13 +3108,10 @@ typedef struct OGRStyleTableHS OGRStyleTableShadow;
 typedef struct OGRGeomFieldDefnHS OGRGeomFieldDefnShadow;
 
 
-  #define SWIG_From_long   PyInt_FromLong 
-
-
-SWIGINTERNINLINE PyObject *
-SWIG_From_int  (int value)
-{    
-  return SWIG_From_long  (value);
+SWIGINTERNINLINE PyObject*
+  SWIG_From_int  (int value)
+{
+  return PyInt_FromLong((long) value);
 }
 
 
@@ -2915,7 +3135,7 @@ SWIG_FromCharPtrAndSize(const char* carray, size_t size)
     if (size > INT_MAX) {
       swig_type_info* pchar_descriptor = SWIG_pchar_descriptor();
       return pchar_descriptor ? 
-	SWIG_NewPointerObj(const_cast< char * >(carray), pchar_descriptor, 0) : SWIG_Py_Void();
+	SWIG_InternalNewPointerObj(const_cast< char * >(carray), pchar_descriptor, 0) : SWIG_Py_Void();
     } else {
 #if PY_VERSION_HEX >= 0x03000000
       return PyUnicode_FromStringAndSize(carray, static_cast< int >(size));
@@ -2936,16 +3156,16 @@ SWIG_FromCharPtr(const char *cptr)
 }
 
 
-int bUseExceptions=0;
-CPLErrorHandler pfnPreviousHandler = CPLDefaultErrorHandler;
+static int bUseExceptions=0;
+static CPLErrorHandler pfnPreviousHandler = CPLDefaultErrorHandler;
 
-void CPL_STDCALL 
-PythonBindingErrorHandler(CPLErr eclass, int code, const char *msg ) 
+static void CPL_STDCALL
+PythonBindingErrorHandler(CPLErr eclass, int code, const char *msg )
 {
-  /* 
+  /*
   ** Generally we want to suppress error reporting if we have exceptions
-  ** enabled as the error message will be in the exception thrown in 
-  ** Python.  
+  ** enabled as the error message will be in the exception thrown in
+  ** Python.
   */
 
   /* If the error class is CE_Fatal, we want to have a message issued
@@ -2966,20 +3186,26 @@ PythonBindingErrorHandler(CPLErr eclass, int code, const char *msg )
 
 
 
+static
 int GetUseExceptions() {
+  CPLErrorReset();
   return bUseExceptions;
 }
 
+static
 void UseExceptions() {
+  CPLErrorReset();
   if( !bUseExceptions )
   {
     bUseExceptions = 1;
-    pfnPreviousHandler = 
+    pfnPreviousHandler =
         CPLSetErrorHandler( (CPLErrorHandler) PythonBindingErrorHandler );
   }
 }
 
+static
 void DontUseExceptions() {
+  CPLErrorReset();
   if( bUseExceptions )
   {
     bUseExceptions = 0;
@@ -2988,6 +3214,24 @@ void DontUseExceptions() {
 }
 
 
+/* Completely unrelated: just to avoid Coverity warnings */
+
+static int bReturnSame = 1;
+
+void NeverCallMePlease() {
+    bReturnSame = 0;
+}
+
+/* Some SWIG code generates dead code, which Coverity warns about */
+template<class T> static T ReturnSame(T x)
+{
+    if( bReturnSame )
+        return x;
+    return 0;
+}
+
+
+
 
 /* Return a PyObject* from a NULL terminated C String */
 static PyObject* GDALPythonObjectFromCStr(const char *pszStr)
@@ -3009,7 +3253,7 @@ static PyObject* GDALPythonObjectFromCStr(const char *pszStr)
     pszIter ++;
   }
 #if PY_VERSION_HEX >= 0x03000000
-  return PyUnicode_FromString(pszStr); 
+  return PyUnicode_FromString(pszStr);
 #else
   return PyString_FromString(pszStr);
 #endif
@@ -3037,7 +3281,7 @@ static char* GDALPythonObjectToCStr(PyObject* pyObject, int* pbToFree)
       *pbToFree = 1;
       return pszNewStr;
   }
-  else 
+  else
   {
 #if PY_VERSION_HEX >= 0x03000000
       return PyBytes_AsString(pyObject);
@@ -3066,7 +3310,7 @@ typedef struct {
 /*                          PyProgressProxy()                           */
 /************************************************************************/
 
-int CPL_STDCALL
+static int CPL_STDCALL
 PyProgressProxy( double dfComplete, const char *pszMessage, void *pData )
 
 {
@@ -3081,19 +3325,25 @@ PyProgressProxy( double dfComplete, const char *pszMessage, void *pData )
         return TRUE;
 
     psInfo->nLastReported = (int) (100.0 * dfComplete);
-    
+
     if( pszMessage == NULL )
         pszMessage = "";
 
     if( psInfo->psPyCallbackData == NULL )
         psArgs = Py_BuildValue("(dsO)", dfComplete, pszMessage, Py_None );
     else
-        psArgs = Py_BuildValue("(dsO)", dfComplete, pszMessage, 
+        psArgs = Py_BuildValue("(dsO)", dfComplete, pszMessage,
 	                       psInfo->psPyCallbackData );
 
     psResult = PyEval_CallObject( psInfo->psPyCallback, psArgs);
     Py_XDECREF(psArgs);
 
+    if( PyErr_Occurred() != NULL )
+    {
+        PyErr_Clear();
+        return FALSE;
+    }
+
     if( psResult == NULL )
     {
         return TRUE;
@@ -3101,19 +3351,20 @@ PyProgressProxy( double dfComplete, const char *pszMessage, void *pData )
 
     if( psResult == Py_None )
     {
-	Py_XDECREF(Py_None);
         return TRUE;
     }
 
     if( !PyArg_Parse( psResult, "i", &bContinue ) )
     {
-        PyErr_SetString(PyExc_ValueError, "bad progress return value");
+        PyErr_Clear();
+        CPLError(CE_Failure, CPLE_AppDefined, "bad progress return value");
+        Py_XDECREF(psResult);
 	return FALSE;
     }
 
     Py_XDECREF(psResult);
 
-    return bContinue;    
+    return bContinue;
 }
 
 
@@ -3733,11 +3984,11 @@ SWIGINTERN OGRErr OGRFeatureShadow_SetGeomField__SWIG_1(OGRFeatureShadow *self,c
       int iField = OGR_F_GetGeomFieldIndex(self, name);
       if (iField == -1)
       {
-        CPLError(CE_Failure, 1, "No such field: '%s'", name);
-        return 6;
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+          return 6;
       }
       else
-        return OGR_F_SetGeomField(self, iField, geom);
+          return OGR_F_SetGeomField(self, iField, geom);
   }
 SWIGINTERN OGRErr OGRFeatureShadow_SetGeomFieldDirectly__SWIG_0(OGRFeatureShadow *self,int iField,OGRGeometryShadow *geom){
     return OGR_F_SetGeomFieldDirectly(self, iField, geom);
@@ -3746,24 +3997,24 @@ SWIGINTERN OGRErr OGRFeatureShadow_SetGeomFieldDirectly__SWIG_1(OGRFeatureShadow
       int iField = OGR_F_GetGeomFieldIndex(self, name);
       if (iField == -1)
       {
-        CPLError(CE_Failure, 1, "No such field: '%s'", name);
-        return 6;
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+          return 6;
       }
       else
-        return OGR_F_SetGeomFieldDirectly(self, iField, geom);
+          return OGR_F_SetGeomFieldDirectly(self, iField, geom);
   }
 SWIGINTERN OGRGeometryShadow *OGRFeatureShadow_GetGeomFieldRef__SWIG_0(OGRFeatureShadow *self,int iField){
     return (OGRGeometryShadow*) OGR_F_GetGeomFieldRef(self, iField);
   }
 SWIGINTERN OGRGeometryShadow *OGRFeatureShadow_GetGeomFieldRef__SWIG_1(OGRFeatureShadow *self,char const *name){
-    int i = OGR_F_GetGeomFieldIndex(self, name);
-    if (i == -1)
-    {
-      CPLError(CE_Failure, 1, "No such field: '%s'", name);
-      return NULL;
-    }
-    else
-      return (OGRGeometryShadow*) OGR_F_GetGeomFieldRef(self, i);
+      int i = OGR_F_GetGeomFieldIndex(self, name);
+      if (i == -1)
+      {
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+          return NULL;
+      }
+      else
+          return (OGRGeometryShadow*) OGR_F_GetGeomFieldRef(self, i);
   }
 SWIGINTERN OGRFeatureShadow *OGRFeatureShadow_Clone(OGRFeatureShadow *self){
     return (OGRFeatureShadow*) OGR_F_Clone(self);
@@ -3780,23 +4031,23 @@ SWIGINTERN OGRFieldDefnShadow *OGRFeatureShadow_GetFieldDefnRef__SWIG_0(OGRFeatu
 SWIGINTERN OGRFieldDefnShadow *OGRFeatureShadow_GetFieldDefnRef__SWIG_1(OGRFeatureShadow *self,char const *name){
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
-	  return (OGRFieldDefnShadow *) OGR_F_GetFieldDefnRef(self, i);
+          return (OGRFieldDefnShadow *) OGR_F_GetFieldDefnRef(self, i);
       return NULL;
   }
 SWIGINTERN int OGRFeatureShadow_GetGeomFieldCount(OGRFeatureShadow *self){
     return OGR_F_GetGeomFieldCount(self);
   }
 SWIGINTERN OGRGeomFieldDefnShadow *OGRFeatureShadow_GetGeomFieldDefnRef__SWIG_0(OGRFeatureShadow *self,int id){
-    return (OGRGeomFieldDefnShadow *) OGR_F_GetGeomFieldDefnRef(self, id);
+      return (OGRGeomFieldDefnShadow *) OGR_F_GetGeomFieldDefnRef(self, id);
   }
 SWIGINTERN OGRGeomFieldDefnShadow *OGRFeatureShadow_GetGeomFieldDefnRef__SWIG_1(OGRFeatureShadow *self,char const *name){
       int i = OGR_F_GetGeomFieldIndex(self, name);
       if (i == -1)
-      CPLError(CE_Failure, 1, "No such field: '%s'", name);
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
-      return (OGRGeomFieldDefnShadow *) OGR_F_GetGeomFieldDefnRef(self, i);
+          return (OGRGeomFieldDefnShadow *) OGR_F_GetGeomFieldDefnRef(self, i);
       return NULL;
   }
 SWIGINTERN char const *OGRFeatureShadow_GetFieldAsString__SWIG_0(OGRFeatureShadow *self,int id){
@@ -3805,7 +4056,7 @@ SWIGINTERN char const *OGRFeatureShadow_GetFieldAsString__SWIG_0(OGRFeatureShado
 SWIGINTERN char const *OGRFeatureShadow_GetFieldAsString__SWIG_1(OGRFeatureShadow *self,char const *name){
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
+	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
 	  return (const char *) OGR_F_GetFieldAsString(self, i);
       return NULL;
@@ -3816,7 +4067,7 @@ SWIGINTERN int OGRFeatureShadow_GetFieldAsInteger__SWIG_0(OGRFeatureShadow *self
 SWIGINTERN int OGRFeatureShadow_GetFieldAsInteger__SWIG_1(OGRFeatureShadow *self,char const *name){
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
+	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
 	  return OGR_F_GetFieldAsInteger(self, i);
       return 0;
@@ -3827,9 +4078,9 @@ SWIGINTERN GIntBig OGRFeatureShadow_GetFieldAsInteger64__SWIG_0(OGRFeatureShadow
 SWIGINTERN GIntBig OGRFeatureShadow_GetFieldAsInteger64__SWIG_1(OGRFeatureShadow *self,char const *name){
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-      CPLError(CE_Failure, 1, "No such field: '%s'", name);
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
-      return OGR_F_GetFieldAsInteger64(self, i);
+          return OGR_F_GetFieldAsInteger64(self, i);
       return 0;
   }
 SWIGINTERN double OGRFeatureShadow_GetFieldAsDouble__SWIG_0(OGRFeatureShadow *self,int id){
@@ -3841,9 +4092,9 @@ SWIGINTERN double OGRFeatureShadow_GetFieldAsDouble__SWIG_0(OGRFeatureShadow *se
 SWIGINTERN double OGRFeatureShadow_GetFieldAsDouble__SWIG_1(OGRFeatureShadow *self,char const *name){
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
-	  return OGR_F_GetFieldAsDouble(self, i);
+          return OGR_F_GetFieldAsDouble(self, i);
       return 0;
   }
 
@@ -3853,20 +4104,43 @@ SWIG_From_float  (float value)
   return SWIG_From_double  (value);
 }
 
-SWIGINTERN void OGRFeatureShadow_GetFieldAsDateTime(OGRFeatureShadow *self,int id,int *pnYear,int *pnMonth,int *pnDay,int *pnHour,int *pnMinute,float *pfSecond,int *pnTZFlag){
+SWIGINTERN void OGRFeatureShadow_GetFieldAsDateTime__SWIG_0(OGRFeatureShadow *self,int id,int *pnYear,int *pnMonth,int *pnDay,int *pnHour,int *pnMinute,float *pfSecond,int *pnTZFlag){
       OGR_F_GetFieldAsDateTimeEx(self, id, pnYear, pnMonth, pnDay,
 			       pnHour, pnMinute, pfSecond,
 			       pnTZFlag);
   }
-SWIGINTERN void OGRFeatureShadow_GetFieldAsIntegerList(OGRFeatureShadow *self,int id,int *nLen,int const **pList){
+SWIGINTERN void OGRFeatureShadow_GetFieldAsDateTime__SWIG_1(OGRFeatureShadow *self,char const *name,int *pnYear,int *pnMonth,int *pnDay,int *pnHour,int *pnMinute,float *pfSecond,int *pnTZFlag){
+      int id = OGR_F_GetFieldIndex(self, name);
+      if (id == -1)
+	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      else
+	  OGR_F_GetFieldAsDateTimeEx(self, id, pnYear, pnMonth, pnDay,
+			       pnHour, pnMinute, pfSecond,
+			       pnTZFlag);
+  }
+SWIGINTERN void OGRFeatureShadow_GetFieldAsIntegerList__SWIG_0(OGRFeatureShadow *self,int id,int *nLen,int const **pList){
       *pList = OGR_F_GetFieldAsIntegerList(self, id, nLen);
   }
+SWIGINTERN void OGRFeatureShadow_GetFieldAsIntegerList__SWIG_1(OGRFeatureShadow *self,char const *name,int *nLen,int const **pList){
+      int id = OGR_F_GetFieldIndex(self, name);
+      if (id == -1)
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      else
+          *pList = OGR_F_GetFieldAsIntegerList(self, id, nLen);
+  }
 SWIGINTERN void OGRFeatureShadow_GetFieldAsInteger64List(OGRFeatureShadow *self,int id,int *nLen,GIntBig const **pList){
       *pList = OGR_F_GetFieldAsInteger64List(self, id, nLen);
   }
-SWIGINTERN void OGRFeatureShadow_GetFieldAsDoubleList(OGRFeatureShadow *self,int id,int *nLen,double const **pList){
+SWIGINTERN void OGRFeatureShadow_GetFieldAsDoubleList__SWIG_0(OGRFeatureShadow *self,int id,int *nLen,double const **pList){
       *pList = OGR_F_GetFieldAsDoubleList(self, id, nLen);
   }
+SWIGINTERN void OGRFeatureShadow_GetFieldAsDoubleList__SWIG_1(OGRFeatureShadow *self,char const *name,int *nLen,double const **pList){
+      int id = OGR_F_GetFieldIndex(self, name);
+      if (id == -1)
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      else
+          *pList = OGR_F_GetFieldAsDoubleList(self, id, nLen);
+  }
 SWIGINTERN char **OGRFeatureShadow_GetFieldAsStringList(OGRFeatureShadow *self,int id){
       return OGR_F_GetFieldAsStringList(self, id);
   }
@@ -3880,7 +4154,7 @@ SWIGINTERN OGRErr OGRFeatureShadow_GetFieldAsBinary__SWIG_1(OGRFeatureShadow *se
       int id = OGR_F_GetFieldIndex(self, name);
       if (id == -1)
       {
-        CPLError(CE_Failure, 1, "No such field: '%s'", name);
+        CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
         return 6;
       }
       else
@@ -3897,16 +4171,22 @@ SWIGINTERN bool OGRFeatureShadow_IsFieldSet__SWIG_0(OGRFeatureShadow *self,int i
 SWIGINTERN bool OGRFeatureShadow_IsFieldSet__SWIG_1(OGRFeatureShadow *self,char const *name){
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
+	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
 	  return (OGR_F_IsFieldSet(self, i) > 0);
       return false;
   }
 SWIGINTERN int OGRFeatureShadow_GetFieldIndex(OGRFeatureShadow *self,char const *name){
-      return OGR_F_GetFieldIndex(self, name);
+      int i = OGR_F_GetFieldIndex(self, name);
+      if (i == -1)
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      return i;
   }
 SWIGINTERN int OGRFeatureShadow_GetGeomFieldIndex(OGRFeatureShadow *self,char const *name){
-      return OGR_F_GetGeomFieldIndex(self, name);
+      int i = OGR_F_GetGeomFieldIndex(self, name);
+      if (i == -1)
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      return i;
   }
 SWIGINTERN GIntBig OGRFeatureShadow_GetFID(OGRFeatureShadow *self){
     return OGR_F_GetFID(self);
@@ -3923,9 +4203,9 @@ SWIGINTERN void OGRFeatureShadow_UnsetField__SWIG_0(OGRFeatureShadow *self,int i
 SWIGINTERN void OGRFeatureShadow_UnsetField__SWIG_1(OGRFeatureShadow *self,char const *name){
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
-	  OGR_F_UnsetField(self, i);
+          OGR_F_UnsetField(self, i);
   }
 SWIGINTERN void OGRFeatureShadow_SetField__SWIG_0(OGRFeatureShadow *self,int id,char const *value){
     OGR_F_SetFieldString(self, id, value);
@@ -3933,9 +4213,9 @@ SWIGINTERN void OGRFeatureShadow_SetField__SWIG_0(OGRFeatureShadow *self,int id,
 SWIGINTERN void OGRFeatureShadow_SetField__SWIG_1(OGRFeatureShadow *self,char const *name,char const *value){
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
-	  OGR_F_SetFieldString(self, i, value);
+          OGR_F_SetFieldString(self, i, value);
   }
 SWIGINTERN void OGRFeatureShadow_SetFieldInteger64(OGRFeatureShadow *self,int id,GIntBig value){
     OGR_F_SetFieldInteger64(self, id, value);
@@ -3946,18 +4226,39 @@ SWIGINTERN void OGRFeatureShadow_SetField__SWIG_2(OGRFeatureShadow *self,int id,
 SWIGINTERN void OGRFeatureShadow_SetField__SWIG_3(OGRFeatureShadow *self,char const *name,double value){
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
+	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
 	  OGR_F_SetFieldDouble(self, i, value);
   }
 
+/* Getting isfinite working pre C99 across multiple platforms is non-trivial. Users can provide SWIG_isfinite on older platforms. */
+#ifndef SWIG_isfinite
+# if defined(isfinite)
+#  define SWIG_isfinite(X) (isfinite(X))
+# elif defined(_MSC_VER)
+#  define SWIG_isfinite(X) (_finite(X))
+# elif defined(__sun) && defined(__SVR4)
+#  include <ieeefp.h>
+#  define SWIG_isfinite(X) (finite(X))
+# endif
+#endif
+
+
+/* Accept infinite as a valid float value unless we are unable to check if a value is finite */
+#ifdef SWIG_isfinite
+# define SWIG_Float_Overflow_Check(X) ((X < -FLT_MAX || X > FLT_MAX) && SWIG_isfinite(X))
+#else
+# define SWIG_Float_Overflow_Check(X) ((X < -FLT_MAX || X > FLT_MAX))
+#endif
+
+
 SWIGINTERN int
 SWIG_AsVal_float (PyObject * obj, float *val)
 {
   double v;
   int res = SWIG_AsVal_double (obj, &v);
   if (SWIG_IsOK(res)) {
-    if ((v < -FLT_MAX || v > FLT_MAX)) {
+    if (SWIG_Float_Overflow_Check(v)) {
       return SWIG_OverflowError;
     } else {
       if (val) *val = static_cast< float >(v);
@@ -3968,16 +4269,16 @@ SWIG_AsVal_float (PyObject * obj, float *val)
 
 SWIGINTERN void OGRFeatureShadow_SetField__SWIG_4(OGRFeatureShadow *self,int id,int year,int month,int day,int hour,int minute,float second,int tzflag){
     OGR_F_SetFieldDateTimeEx(self, id, year, month, day,
-                             hour, minute, second, 
+                             hour, minute, second,
                              tzflag);
   }
 SWIGINTERN void OGRFeatureShadow_SetField__SWIG_5(OGRFeatureShadow *self,char const *name,int year,int month,int day,int hour,int minute,float second,int tzflag){
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-	  CPLError(CE_Failure, 1, "No such field: '%s'", name);
+	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
 	  OGR_F_SetFieldDateTimeEx(self, i, year, month, day,
-				 hour, minute, second, 
+				 hour, minute, second,
 				 tzflag);
   }
 SWIGINTERN void OGRFeatureShadow_SetFieldIntegerList(OGRFeatureShadow *self,int id,int nList,int *pList){
@@ -4001,13 +4302,13 @@ SWIGINTERN void OGRFeatureShadow_SetFieldBinaryFromHexString__SWIG_0(OGRFeatureS
 SWIGINTERN void OGRFeatureShadow_SetFieldBinaryFromHexString__SWIG_1(OGRFeatureShadow *self,char const *name,char const *pszValue){
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
-        CPLError(CE_Failure, 1, "No such field: '%s'", name);
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
       else
       {
-        int nBytes;
-        GByte* pabyBuf = CPLHexToBinary(pszValue, &nBytes );
-        OGR_F_SetFieldBinary(self, i, nBytes, pabyBuf);
-        CPLFree(pabyBuf);
+          int nBytes;
+          GByte* pabyBuf = CPLHexToBinary(pszValue, &nBytes );
+          OGR_F_SetFieldBinary(self, i, nBytes, pabyBuf);
+          CPLFree(pabyBuf);
       }
   }
 SWIGINTERN OGRErr OGRFeatureShadow_SetFrom(OGRFeatureShadow *self,OGRFeatureShadow *other,int forgiving=1){
@@ -4038,7 +4339,7 @@ SWIGINTERN OGRFieldType OGRFeatureShadow_GetFieldType__SWIG_0(OGRFeatureShadow *
 SWIGINTERN OGRFieldType OGRFeatureShadow_GetFieldType__SWIG_1(OGRFeatureShadow *self,char const *name){
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1) {
-          CPLError(CE_Failure, 1, "No such field: '%s'", name);
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
           return (OGRFieldType)0;
       } else
           return (OGRFieldType) OGR_Fld_GetType( OGR_F_GetFieldDefnRef( self, i ) );
@@ -4049,6 +4350,18 @@ SWIGINTERN int OGRFeatureShadow_Validate(OGRFeatureShadow *self,int flags=OGR_F_
 SWIGINTERN void OGRFeatureShadow_FillUnsetWithDefault(OGRFeatureShadow *self,int bNotNullableOnly=FALSE,char **options=NULL){
     OGR_F_FillUnsetWithDefault(self, bNotNullableOnly, options );
   }
+SWIGINTERN char const *OGRFeatureShadow_GetNativeData(OGRFeatureShadow *self){
+    return OGR_F_GetNativeData(self);
+  }
+SWIGINTERN char const *OGRFeatureShadow_GetNativeMediaType(OGRFeatureShadow *self){
+    return OGR_F_GetNativeMediaType(self);
+  }
+SWIGINTERN void OGRFeatureShadow_SetNativeData(OGRFeatureShadow *self,char const *nativeData){
+    OGR_F_SetNativeData(self, nativeData);
+  }
+SWIGINTERN void OGRFeatureShadow_SetNativeMediaType(OGRFeatureShadow *self,char const *nativeMediaType){
+    OGR_F_SetNativeMediaType(self, nativeMediaType);
+  }
 SWIGINTERN void OGRFeatureShadow_SetFieldString(OGRFeatureShadow *self,int id,char const *value){
     OGR_F_SetFieldString(self, id, value);
   }
@@ -4084,6 +4397,30 @@ SWIGINTERN void OGRFeatureShadow_SetFieldString(OGRFeatureShadow *self,int id,ch
             case wkbMultiLineString25D:
             case wkbMultiPolygon25D:
             case wkbGeometryCollection25D:
+            case wkbPointM:
+            case wkbLineStringM:
+            case wkbPolygonM:
+            case wkbMultiPointM:
+            case wkbMultiLineStringM:
+            case wkbMultiPolygonM:
+            case wkbGeometryCollectionM:
+            case wkbCircularStringM:
+            case wkbCompoundCurveM:
+            case wkbCurvePolygonM:
+            case wkbMultiCurveM:
+            case wkbMultiSurfaceM:
+            case wkbPointZM:
+            case wkbLineStringZM:
+            case wkbPolygonZM:
+            case wkbMultiPointZM:
+            case wkbMultiLineStringZM:
+            case wkbMultiPolygonZM:
+            case wkbGeometryCollectionZM:
+            case wkbCircularStringZM:
+            case wkbCompoundCurveZM:
+            case wkbCurvePolygonZM:
+            case wkbMultiCurveZM:
+            case wkbMultiSurfaceZM:
                 return TRUE;
             default:
                 CPLError(CE_Failure, CPLE_IllegalArg, "Illegal geometry type value");
@@ -4110,7 +4447,10 @@ SWIGINTERN OGRFieldDefnShadow *OGRFeatureDefnShadow_GetFieldDefn(OGRFeatureDefnS
     return (OGRFieldDefnShadow*) OGR_FD_GetFieldDefn(self, i);
   }
 SWIGINTERN int OGRFeatureDefnShadow_GetFieldIndex(OGRFeatureDefnShadow *self,char const *name){
-      return OGR_FD_GetFieldIndex(self, name);
+      int i = OGR_FD_GetFieldIndex(self, name);
+      if (i == -1)
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      return i;
   }
 SWIGINTERN void OGRFeatureDefnShadow_AddFieldDefn(OGRFeatureDefnShadow *self,OGRFieldDefnShadow *defn){
     OGR_FD_AddFieldDefn(self, defn);
@@ -4319,7 +4659,7 @@ SWIGINTERN void OGRGeomFieldDefnShadow_SetNullable(OGRGeomFieldDefnShadow *self,
     return OGR_GFld_SetNullable( self, bNullable );
   }
 
-  OGRGeometryShadow* CreateGeometryFromWkb( int len, char *bin_string, 
+  OGRGeometryShadow* CreateGeometryFromWkb( int len, char *bin_string,
                                             OSRSpatialReferenceShadow *reference=NULL ) {
     OGRGeometryH geom = NULL;
     OGRErr err = OGR_G_CreateFromWkb( (unsigned char *) bin_string,
@@ -4332,10 +4672,10 @@ SWIGINTERN void OGRGeomFieldDefnShadow_SetNullable(OGRGeomFieldDefnShadow *self,
     }
     return (OGRGeometryShadow*) geom;
   }
- 
 
 
-  OGRGeometryShadow* CreateGeometryFromWkt( char **val, 
+
+  OGRGeometryShadow* CreateGeometryFromWkt( char **val,
                                       OSRSpatialReferenceShadow *reference=NULL ) {
     OGRGeometryH geom = NULL;
     OGRErr err = OGR_G_CreateFromWkt(val,
@@ -4347,33 +4687,33 @@ SWIGINTERN void OGRGeomFieldDefnShadow_SetNullable(OGRGeomFieldDefnShadow *self,
     }
     return (OGRGeometryShadow*) geom;
   }
- 
+
 
 
   OGRGeometryShadow *CreateGeometryFromGML( const char * input_string ) {
     OGRGeometryShadow* geom = (OGRGeometryShadow*)OGR_G_CreateFromGML(input_string);
     return geom;
   }
- 
+
 
 
   OGRGeometryShadow *CreateGeometryFromJson( const char * input_string ) {
     OGRGeometryShadow* geom = (OGRGeometryShadow*)OGR_G_CreateGeometryFromJson(input_string);
     return geom;
   }
- 
 
 
-  OGRGeometryShadow* BuildPolygonFromEdges( OGRGeometryShadow*  hLineCollection,  
-                                            int bBestEffort = 0, 
-                                            int bAutoClose = 0, 
+
+  OGRGeometryShadow* BuildPolygonFromEdges( OGRGeometryShadow*  hLineCollection,
+                                            int bBestEffort = 0,
+                                            int bAutoClose = 0,
                                             double dfTolerance=0) {
-  
+
   OGRGeometryH hPolygon = NULL;
-  
+
   OGRErr eErr;
 
-  hPolygon = OGRBuildPolygonFromEdges( hLineCollection, bBestEffort, 
+  hPolygon = OGRBuildPolygonFromEdges( hLineCollection, bBestEffort,
                                        bAutoClose, dfTolerance, &eErr );
 
   if (eErr != OGRERR_NONE ) {
@@ -4385,14 +4725,14 @@ SWIGINTERN void OGRGeomFieldDefnShadow_SetNullable(OGRGeomFieldDefnShadow *self,
   }
 
 
-  OGRGeometryShadow* ApproximateArcAngles( 
+  OGRGeometryShadow* ApproximateArcAngles(
         double dfCenterX, double dfCenterY, double dfZ,
-  	double dfPrimaryRadius, double dfSecondaryAxis, double dfRotation, 
+  	double dfPrimaryRadius, double dfSecondaryAxis, double dfRotation,
         double dfStartAngle, double dfEndAngle,
         double dfMaxAngleStepSizeDegrees ) {
-  
-  return (OGRGeometryShadow* )OGR_G_ApproximateArcAngles( 
-             dfCenterX, dfCenterY, dfZ, 
+
+  return (OGRGeometryShadow* )OGR_G_ApproximateArcAngles(
+             dfCenterX, dfCenterY, dfZ,
              dfPrimaryRadius, dfSecondaryAxis, dfRotation,
              dfStartAngle, dfEndAngle, dfMaxAngleStepSizeDegrees );
   }
@@ -4472,12 +4812,12 @@ SWIGINTERN OGRErr OGRGeometryShadow_ExportToIsoWkt(OGRGeometryShadow *self,char
   }
 SWIGINTERN OGRErr OGRGeometryShadow_ExportToWkb(OGRGeometryShadow *self,int *nLen,char **pBuf,OGRwkbByteOrder byte_order=wkbXDR){
     *nLen = OGR_G_WkbSize( self );
-    *pBuf = (char *) malloc( *nLen * sizeof(unsigned char) );
+    *pBuf = (char *) malloc( *nLen );
     return OGR_G_ExportToWkb(self, byte_order, (unsigned char*) *pBuf );
   }
 SWIGINTERN OGRErr OGRGeometryShadow_ExportToIsoWkb(OGRGeometryShadow *self,int *nLen,char **pBuf,OGRwkbByteOrder byte_order=wkbXDR){
     *nLen = OGR_G_WkbSize( self );
-    *pBuf = (char *) malloc( *nLen * sizeof(unsigned char) );
+    *pBuf = (char *) malloc( *nLen );
     return OGR_G_ExportToIsoWkb(self, byte_order, (unsigned char*) *pBuf );
   }
 SWIGINTERN retStringAndCPLFree *OGRGeometryShadow_ExportToGML(OGRGeometryShadow *self,char **options=0){
@@ -4492,6 +4832,12 @@ SWIGINTERN retStringAndCPLFree *OGRGeometryShadow_ExportToJson(OGRGeometryShadow
 SWIGINTERN void OGRGeometryShadow_AddPoint(OGRGeometryShadow *self,double x,double y,double z=0){
     OGR_G_AddPoint( self, x, y, z );
   }
+SWIGINTERN void OGRGeometryShadow_AddPointM(OGRGeometryShadow *self,double x,double y,double m){
+      OGR_G_AddPointM( self, x, y, m );
+  }
+SWIGINTERN void OGRGeometryShadow_AddPointZM(OGRGeometryShadow *self,double x,double y,double z,double m){
+      OGR_G_AddPointZM( self, x, y, z, m );
+  }
 SWIGINTERN void OGRGeometryShadow_AddPoint_2D(OGRGeometryShadow *self,double x,double y){
     OGR_G_AddPoint_2D( self, x, y );
   }
@@ -4554,6 +4900,9 @@ SWIGINTERN double OGRGeometryShadow_GetY(OGRGeometryShadow *self,int point=0){
 SWIGINTERN double OGRGeometryShadow_GetZ(OGRGeometryShadow *self,int point=0){
     return OGR_G_GetZ(self, point);
   }
+SWIGINTERN double OGRGeometryShadow_GetM(OGRGeometryShadow *self,int point=0){
+    return OGR_G_GetM(self, point);
+  }
 
 static PyObject *
 CreateTupleFromDoubleArray( double *first, unsigned int size ) {
@@ -4570,6 +4919,10 @@ SWIGINTERN void OGRGeometryShadow_GetPoint(OGRGeometryShadow *self,int iPoint=0,
 
     OGR_G_GetPoint( self, iPoint, argout+0, argout+1, argout+2 );
   }
+SWIGINTERN void OGRGeometryShadow_GetPointZM(OGRGeometryShadow *self,int iPoint=0,double argout[4]=NULL){
+
+      OGR_G_GetPointZM( self, iPoint, argout+0, argout+1, argout+2, argout+3 );
+  }
 SWIGINTERN void OGRGeometryShadow_GetPoint_2D(OGRGeometryShadow *self,int iPoint=0,double argout[2]=NULL){
 
     OGR_G_GetPoint( self, iPoint, argout+0, argout+1, NULL );
@@ -4580,6 +4933,12 @@ SWIGINTERN int OGRGeometryShadow_GetGeometryCount(OGRGeometryShadow *self){
 SWIGINTERN void OGRGeometryShadow_SetPoint(OGRGeometryShadow *self,int point,double x,double y,double z=0){
     OGR_G_SetPoint(self, point, x, y, z);
   }
+SWIGINTERN void OGRGeometryShadow_SetPointM(OGRGeometryShadow *self,int point,double x,double y,double m){
+      OGR_G_SetPointM(self, point, x, y, m);
+  }
+SWIGINTERN void OGRGeometryShadow_SetPointZM(OGRGeometryShadow *self,int point,double x,double y,double z,double m){
+      OGR_G_SetPointZM(self, point, x, y, z, m);
+  }
 SWIGINTERN void OGRGeometryShadow_SetPoint_2D(OGRGeometryShadow *self,int point,double x,double y){
     OGR_G_SetPoint_2D(self, point, x, y);
   }
@@ -4592,6 +4951,9 @@ SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_Simplify(OGRGeometryShadow *self
 SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_SimplifyPreserveTopology(OGRGeometryShadow *self,double tolerance){
     return (OGRGeometryShadow*) OGR_G_SimplifyPreserveTopology(self, tolerance);
   }
+SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_DelaunayTriangulation(OGRGeometryShadow *self,double dfTolerance=0.0,int bOnlyEdges=FALSE){
+    return (OGRGeometryShadow*) OGR_G_DelaunayTriangulation(self, dfTolerance, bOnlyEdges);
+  }
 SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_Boundary(OGRGeometryShadow *self){
     return (OGRGeometryShadow*) OGR_G_Boundary(self);
   }
@@ -4714,9 +5076,24 @@ SWIGINTERN int OGRGeometryShadow_WkbSize(OGRGeometryShadow *self){
 SWIGINTERN int OGRGeometryShadow_GetCoordinateDimension(OGRGeometryShadow *self){
     return OGR_G_GetCoordinateDimension(self);
   }
+SWIGINTERN int OGRGeometryShadow_CoordinateDimension(OGRGeometryShadow *self){
+    return OGR_G_CoordinateDimension(self);
+  }
+SWIGINTERN int OGRGeometryShadow_Is3D(OGRGeometryShadow *self){
+      return OGR_G_Is3D(self);
+  }
+SWIGINTERN int OGRGeometryShadow_IsMeasured(OGRGeometryShadow *self){
+      return OGR_G_IsMeasured(self);
+  }
 SWIGINTERN void OGRGeometryShadow_SetCoordinateDimension(OGRGeometryShadow *self,int dimension){
     OGR_G_SetCoordinateDimension(self, dimension);
   }
+SWIGINTERN void OGRGeometryShadow_Set3D(OGRGeometryShadow *self,int b3D){
+      OGR_G_Set3D(self, b3D);
+  }
+SWIGINTERN void OGRGeometryShadow_SetMeasured(OGRGeometryShadow *self,int bMeasured){
+      OGR_G_SetMeasured(self, bMeasured);
+  }
 SWIGINTERN int OGRGeometryShadow_GetDimension(OGRGeometryShadow *self){
     return OGR_G_GetDimension(self);
   }
@@ -4767,13 +5144,13 @@ OGRwkbGeometryType GT_SetModifier( OGRwkbGeometryType eType, int bSetZ, int bSet
     OGRDataSourceShadow* ds = (OGRDataSourceShadow*)OGROpen(utf8_path,update,NULL);
     if( CPLGetLastErrorType() == CE_Failure && ds != NULL )
     {
-        CPLDebug( "SWIG", 
+        CPLDebug( "SWIG",
 		  "OGROpen() succeeded, but an error is posted, so we destroy"
 		  " the datasource and fail at swig level." );
         OGRReleaseDataSource(ds);
         ds = NULL;
     }
-	
+
     return ds;
   }
 
@@ -4786,15 +5163,17 @@ OGRwkbGeometryType GT_SetModifier( OGRwkbGeometryType eType, int bSetZ, int bSet
         OGRReleaseDataSource(ds);
         ds = NULL;
     }
-	
+
     return ds;
   }
 
 
+static
 OGRDriverShadow* GetDriverByName( char const *name ) {
   return (OGRDriverShadow*) OGRGetDriverByName( name );
 }
 
+static
 OGRDriverShadow* GetDriver(int driver_number) {
   return (OGRDriverShadow*) OGRGetDriver(driver_number);
 }
@@ -4803,8 +5182,11 @@ OGRDriverShadow* GetDriver(int driver_number) {
   char **GeneralCmdLineProcessor( char **papszArgv, int nOptions = 0 ) {
     int nResArgCount;
 
-    nResArgCount = 
-      OGRGeneralCmdLineProcessor( CSLCount(papszArgv), &papszArgv, nOptions ); 
+    if( papszArgv == NULL )
+        return NULL;
+
+    nResArgCount =
+      OGRGeneralCmdLineProcessor( CSLCount(papszArgv), &papszArgv, nOptions );
 
     if( nResArgCount <= 0 )
         return NULL;
@@ -4813,6 +5195,7 @@ OGRDriverShadow* GetDriver(int driver_number) {
   }
 
 
+static
 int GDALTermProgress_nocb( double dfProgress, const char * pszMessage=NULL, void *pData=NULL ) {
   return GDALTermProgress( dfProgress, pszMessage, pData);
 }
@@ -4821,12 +5204,13 @@ int GDALTermProgress_nocb( double dfProgress, const char * pszMessage=NULL, void
 extern "C" {
 #endif
 SWIGINTERN PyObject *_wrap_GetUseExceptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   int result;
   
   if (!PyArg_ParseTuple(args,(char *)":GetUseExceptions")) SWIG_fail;
   result = (int)GetUseExceptions();
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -4834,11 +5218,12 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_UseExceptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   
   if (!PyArg_ParseTuple(args,(char *)":UseExceptions")) SWIG_fail;
   UseExceptions();
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -4846,11 +5231,12 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_DontUseExceptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   
   if (!PyArg_ParseTuple(args,(char *)":DontUseExceptions")) SWIG_fail;
   DontUseExceptions();
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -4858,7 +5244,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_MajorObject_GetDescription(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -4876,14 +5262,17 @@ SWIGINTERN PyObject *_wrap_MajorObject_GetDescription(PyObject *SWIGUNUSEDPARM(s
       CPLErrorReset();
     }
     result = (char *)GDALMajorObjectShadow_GetDescription(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -4891,7 +5280,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_MajorObject_SetDescription(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -4923,15 +5312,18 @@ SWIGINTERN PyObject *_wrap_MajorObject_SetDescription(PyObject *SWIGUNUSEDPARM(s
       CPLErrorReset();
     }
     GDALMajorObjectShadow_SetDescription(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -4940,7 +5332,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_MajorObject_GetMetadataDomainList(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -4958,12 +5350,14 @@ SWIGINTERN PyObject *_wrap_MajorObject_GetMetadataDomainList(PyObject *SWIGUNUSE
       CPLErrorReset();
     }
     result = (char **)GDALMajorObjectShadow_GetMetadataDomainList(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) char **CSL -> ( string ) */
@@ -4982,6 +5376,7 @@ SWIGINTERN PyObject *_wrap_MajorObject_GetMetadataDomainList(PyObject *SWIGUNUSE
     }
     CSLDestroy(result);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -4989,7 +5384,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_MajorObject_GetMetadata_Dict(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
   char *arg2 = (char *) "" ;
   void *argp1 = 0 ;
@@ -5019,12 +5414,14 @@ SWIGINTERN PyObject *_wrap_MajorObject_GetMetadata_Dict(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     result = (char **)GDALMajorObjectShadow_GetMetadata_Dict(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) char **dict */
@@ -5051,6 +5448,7 @@ SWIGINTERN PyObject *_wrap_MajorObject_GetMetadata_Dict(PyObject *SWIGUNUSEDPARM
     }
   }
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -5059,7 +5457,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_MajorObject_GetMetadata_List(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
   char *arg2 = (char *) "" ;
   void *argp1 = 0 ;
@@ -5089,12 +5487,14 @@ SWIGINTERN PyObject *_wrap_MajorObject_GetMetadata_List(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     result = (char **)GDALMajorObjectShadow_GetMetadata_List(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) char **options -> ( string ) */
@@ -5113,6 +5513,7 @@ SWIGINTERN PyObject *_wrap_MajorObject_GetMetadata_List(PyObject *SWIGUNUSEDPARM
     }
   }
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -5121,7 +5522,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
   char **arg2 = (char **) 0 ;
   char *arg3 = (char *) "" ;
@@ -5145,8 +5546,12 @@ SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata__SWIG_0(PyObject *SWIGUNUSEDP
     /* %typemap(in) char **dict */
     arg2 = NULL;
     if ( PySequence_Check( obj1 ) ) {
-      int size = PySequence_Size(obj1);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj1);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj1,i);
         int bFreeStr;
         char* pszStr = GDALPythonObjectToCStr(pyObj, &bFreeStr);
@@ -5162,16 +5567,16 @@ SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata__SWIG_0(PyObject *SWIGUNUSEDP
     }
     else if ( PyMapping_Check( obj1 ) ) {
       /* We need to use the dictionary form. */
-      int size = PyMapping_Length( obj1 );
-      if ( size > 0 ) {
+      Py_ssize_t size = PyMapping_Length( obj1 );
+      if ( size > 0 && size == (int)size) {
         PyObject *item_list = PyMapping_Items( obj1 );
-        for( int i=0; i<size; i++ ) {
+        for( int i=0; i<(int)size; i++ ) {
           PyObject *it = PySequence_GetItem( item_list, i );
           
           PyObject *k, *v;
           if ( ! PyArg_ParseTuple( it, "OO", &k, &v ) ) {
             Py_DECREF(it);
-            PyErr_SetString(PyExc_TypeError,"dictionnaire must contain tuples of strings");
+            PyErr_SetString(PyExc_TypeError,"Dictionary must contain tuples of strings");
             SWIG_fail;
           }
           
@@ -5183,7 +5588,7 @@ SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata__SWIG_0(PyObject *SWIGUNUSEDP
             GDALPythonFreeCStr(pszK, bFreeK);
             GDALPythonFreeCStr(pszV, bFreeV);
             Py_DECREF(it);
-            PyErr_SetString(PyExc_TypeError,"dictionnaire must contain tuples of strings");
+            PyErr_SetString(PyExc_TypeError,"Dictionary must contain tuples of strings");
             SWIG_fail;
           }
           arg2 = CSLAddNameValue( arg2, pszK, pszV );
@@ -5212,12 +5617,14 @@ SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata__SWIG_0(PyObject *SWIGUNUSEDP
       CPLErrorReset();
     }
     result = (CPLErr)GDALMajorObjectShadow_SetMetadata__SWIG_0(arg1,arg2,(char const *)arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
@@ -5225,16 +5632,7 @@ SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata__SWIG_0(PyObject *SWIGUNUSEDP
     CSLDestroy( arg2 );
   }
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-  {
-    /* %typemap(ret) CPLErr */
-    if ( bUseExceptions == 0 ) {
-      /* We're not using exceptions.  And no error has occurred */
-      if ( resultobj == 0 ) {
-        /* No other return values set so return ErrorCode */
-        resultobj = PyInt_FromLong(result);
-      }
-    }
-  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -5247,7 +5645,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   char *arg3 = (char *) "" ;
@@ -5287,26 +5685,19 @@ SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata__SWIG_1(PyObject *SWIGUNUSEDP
       CPLErrorReset();
     }
     result = (CPLErr)GDALMajorObjectShadow_SetMetadata__SWIG_1(arg1,arg2,(char const *)arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-  {
-    /* %typemap(ret) CPLErr */
-    if ( bUseExceptions == 0 ) {
-      /* We're not using exceptions.  And no error has occurred */
-      if ( resultobj == 0 ) {
-        /* No other return values set so return ErrorCode */
-        resultobj = PyInt_FromLong(result);
-      }
-    }
-  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -5320,9 +5711,9 @@ SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata(PyObject *self, PyObject *arg
   PyObject *argv[4];
   int ii;
   
-  if (!PyTuple_Check(args)) SWIG_fail;
+  if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
   argc = (int)PyObject_Length(args);
-  for (ii = 0; (ii < argc) && (ii < 3); ii++) {
+  for (ii = 0; (ii < 3) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
   if ((argc >= 2) && (argc <= 3)) {
@@ -5372,16 +5763,16 @@ SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata(PyObject *self, PyObject *arg
   }
   
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'MajorObject_SetMetadata'.\n"
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'MajorObject_SetMetadata'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    SetMetadata(GDALMajorObjectShadow *,char **,char const *)\n"
-    "    SetMetadata(GDALMajorObjectShadow *,char *,char const *)\n");
-  return NULL;
+    "    GDALMajorObjectShadow::SetMetadata(char **,char const *)\n"
+    "    GDALMajorObjectShadow::SetMetadata(char *,char const *)\n");
+  return 0;
 }
 
 
 SWIGINTERN PyObject *_wrap_MajorObject_GetMetadataItem(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   char *arg3 = (char *) "" ;
@@ -5426,16 +5817,19 @@ SWIGINTERN PyObject *_wrap_MajorObject_GetMetadataItem(PyObject *SWIGUNUSEDPARM(
       CPLErrorReset();
     }
     result = (char *)GDALMajorObjectShadow_GetMetadataItem(arg1,(char const *)arg2,(char const *)arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -5445,7 +5839,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_MajorObject_SetMetadataItem(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   char *arg3 = (char *) 0 ;
@@ -5500,27 +5894,20 @@ SWIGINTERN PyObject *_wrap_MajorObject_SetMetadataItem(PyObject *SWIGUNUSEDPARM(
       CPLErrorReset();
     }
     result = (CPLErr)GDALMajorObjectShadow_SetMetadataItem(arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
   if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
-  {
-    /* %typemap(ret) CPLErr */
-    if ( bUseExceptions == 0 ) {
-      /* We're not using exceptions.  And no error has occurred */
-      if ( resultobj == 0 ) {
-        /* No other return values set so return ErrorCode */
-        resultobj = PyInt_FromLong(result);
-      }
-    }
-  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -5538,7 +5925,7 @@ SWIGINTERN PyObject *MajorObject_swigregister(PyObject *SWIGUNUSEDPARM(self), Py
 }
 
 SWIGINTERN PyObject *_wrap_new_StyleTable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRStyleTableShadow *result = 0 ;
   
   if (!PyArg_ParseTuple(args,(char *)":new_StyleTable")) SWIG_fail;
@@ -5547,14 +5934,17 @@ SWIGINTERN PyObject *_wrap_new_StyleTable(PyObject *SWIGUNUSEDPARM(self), PyObje
       CPLErrorReset();
     }
     result = (OGRStyleTableShadow *)new_OGRStyleTableShadow();
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRStyleTableShadow, SWIG_POINTER_NEW |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -5562,7 +5952,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_delete_StyleTable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -5579,14 +5969,17 @@ SWIGINTERN PyObject *_wrap_delete_StyleTable(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     delete_OGRStyleTableShadow(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -5594,7 +5987,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_StyleTable_AddStyle(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   char *arg3 = (char *) 0 ;
@@ -5632,16 +6025,19 @@ SWIGINTERN PyObject *_wrap_StyleTable_AddStyle(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     result = (int)OGRStyleTableShadow_AddStyle(arg1,(char const *)arg2,(char const *)arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -5651,7 +6047,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_StyleTable_LoadStyleTable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -5681,18 +6077,21 @@ SWIGINTERN PyObject *_wrap_StyleTable_LoadStyleTable(PyObject *SWIGUNUSEDPARM(se
       CPLErrorReset();
     }
     result = (int)OGRStyleTableShadow_LoadStyleTable(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
     /* %typemap(freearg) (const char *utf8_path) */
     GDALPythonFreeCStr(arg2, bToFree2);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -5704,7 +6103,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_StyleTable_SaveStyleTable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -5734,18 +6133,21 @@ SWIGINTERN PyObject *_wrap_StyleTable_SaveStyleTable(PyObject *SWIGUNUSEDPARM(se
       CPLErrorReset();
     }
     result = (int)OGRStyleTableShadow_SaveStyleTable(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
     /* %typemap(freearg) (const char *utf8_path) */
     GDALPythonFreeCStr(arg2, bToFree2);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -5757,7 +6159,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_StyleTable_Find(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -5785,15 +6187,18 @@ SWIGINTERN PyObject *_wrap_StyleTable_Find(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     result = (char *)OGRStyleTableShadow_Find(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -5802,7 +6207,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_StyleTable_ResetStyleStringReading(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -5819,14 +6224,17 @@ SWIGINTERN PyObject *_wrap_StyleTable_ResetStyleStringReading(PyObject *SWIGUNUS
       CPLErrorReset();
     }
     OGRStyleTableShadow_ResetStyleStringReading(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -5834,7 +6242,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_StyleTable_GetNextStyle(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -5852,14 +6260,17 @@ SWIGINTERN PyObject *_wrap_StyleTable_GetNextStyle(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     result = (char *)OGRStyleTableShadow_GetNextStyle(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -5867,7 +6278,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_StyleTable_GetLastStyleName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRStyleTableShadow *arg1 = (OGRStyleTableShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -5885,14 +6296,17 @@ SWIGINTERN PyObject *_wrap_StyleTable_GetLastStyleName(PyObject *SWIGUNUSEDPARM(
       CPLErrorReset();
     }
     result = (char *)OGRStyleTableShadow_GetLastStyleName(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -5907,7 +6321,7 @@ SWIGINTERN PyObject *StyleTable_swigregister(PyObject *SWIGUNUSEDPARM(self), PyO
 }
 
 SWIGINTERN PyObject *_wrap_Driver_name_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -5925,14 +6339,17 @@ SWIGINTERN PyObject *_wrap_Driver_name_get(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     result = (char *)OGRDriverShadow_name_get(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -5940,7 +6357,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Driver_CreateDataSource(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   char **arg3 = (char **) 0 ;
@@ -5983,8 +6400,12 @@ SWIGINTERN PyObject *_wrap_Driver_CreateDataSource(PyObject *SWIGUNUSEDPARM(self
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj2);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj2);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj2,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -6021,12 +6442,14 @@ SWIGINTERN PyObject *_wrap_Driver_CreateDataSource(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     result = (OGRDataSourceShadow *)OGRDriverShadow_CreateDataSource(arg1,(char const *)arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDataSourceShadow, SWIG_POINTER_OWN |  0 );
   {
@@ -6037,6 +6460,7 @@ SWIGINTERN PyObject *_wrap_Driver_CreateDataSource(PyObject *SWIGUNUSEDPARM(self
     /* %typemap(freearg) char **options */
     CSLDestroy( arg3 );
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -6052,7 +6476,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Driver_CopyDataSource(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
   OGRDataSourceShadow *arg2 = (OGRDataSourceShadow *) 0 ;
   char *arg3 = (char *) 0 ;
@@ -6104,8 +6528,12 @@ SWIGINTERN PyObject *_wrap_Driver_CopyDataSource(PyObject *SWIGUNUSEDPARM(self),
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj3);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj3);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj3,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -6142,12 +6570,14 @@ SWIGINTERN PyObject *_wrap_Driver_CopyDataSource(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (OGRDataSourceShadow *)OGRDriverShadow_CopyDataSource(arg1,arg2,(char const *)arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDataSourceShadow, SWIG_POINTER_OWN |  0 );
   {
@@ -6158,6 +6588,7 @@ SWIGINTERN PyObject *_wrap_Driver_CopyDataSource(PyObject *SWIGUNUSEDPARM(self),
     /* %typemap(freearg) char **options */
     CSLDestroy( arg4 );
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -6173,7 +6604,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Driver_Open(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   int arg3 = (int) 0 ;
@@ -6217,18 +6648,21 @@ SWIGINTERN PyObject *_wrap_Driver_Open(PyObject *SWIGUNUSEDPARM(self), PyObject
       CPLErrorReset();
     }
     result = (OGRDataSourceShadow *)OGRDriverShadow_Open(arg1,(char const *)arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDataSourceShadow, SWIG_POINTER_OWN |  0 );
   {
     /* %typemap(freearg) (const char *utf8_path) */
     GDALPythonFreeCStr(arg2, bToFree2);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -6240,7 +6674,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Driver_DeleteDataSource(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -6270,18 +6704,21 @@ SWIGINTERN PyObject *_wrap_Driver_DeleteDataSource(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     result = (int)OGRDriverShadow_DeleteDataSource(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
     /* %typemap(freearg) (const char *utf8_path) */
     GDALPythonFreeCStr(arg2, bToFree2);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -6293,7 +6730,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Driver_TestCapability(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -6326,15 +6763,18 @@ SWIGINTERN PyObject *_wrap_Driver_TestCapability(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (bool)OGRDriverShadow_TestCapability(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_bool(static_cast< bool >(result));
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -6343,7 +6783,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Driver_GetName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -6361,14 +6801,17 @@ SWIGINTERN PyObject *_wrap_Driver_GetName(PyObject *SWIGUNUSEDPARM(self), PyObje
       CPLErrorReset();
     }
     result = (char *)OGRDriverShadow_GetName(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6376,7 +6819,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Driver_Register(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -6393,14 +6836,17 @@ SWIGINTERN PyObject *_wrap_Driver_Register(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     OGRDriverShadow_Register(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6408,7 +6854,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Driver_Deregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -6425,14 +6871,17 @@ SWIGINTERN PyObject *_wrap_Driver_Deregister(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     OGRDriverShadow_Deregister(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6447,7 +6896,7 @@ SWIGINTERN PyObject *Driver_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObjec
 }
 
 SWIGINTERN PyObject *_wrap_DataSource_name_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -6465,14 +6914,17 @@ SWIGINTERN PyObject *_wrap_DataSource_name_get(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     result = (char *)OGRDataSourceShadow_name_get(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6480,7 +6932,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_delete_DataSource(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -6497,14 +6949,17 @@ SWIGINTERN PyObject *_wrap_delete_DataSource(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     delete_OGRDataSourceShadow(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6512,7 +6967,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_DataSource_GetRefCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -6530,14 +6985,17 @@ SWIGINTERN PyObject *_wrap_DataSource_GetRefCount(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (int)OGRDataSourceShadow_GetRefCount(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6545,7 +7003,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_DataSource_GetSummaryRefCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -6563,14 +7021,17 @@ SWIGINTERN PyObject *_wrap_DataSource_GetSummaryRefCount(PyObject *SWIGUNUSEDPAR
       CPLErrorReset();
     }
     result = (int)OGRDataSourceShadow_GetSummaryRefCount(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6578,7 +7039,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_DataSource_GetLayerCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -6596,14 +7057,17 @@ SWIGINTERN PyObject *_wrap_DataSource_GetLayerCount(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     result = (int)OGRDataSourceShadow_GetLayerCount(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6611,7 +7075,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_DataSource_GetDriver(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -6629,14 +7093,17 @@ SWIGINTERN PyObject *_wrap_DataSource_GetDriver(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (OGRDriverShadow *)OGRDataSourceShadow_GetDriver(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6644,7 +7111,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_DataSource_GetName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -6662,14 +7129,17 @@ SWIGINTERN PyObject *_wrap_DataSource_GetName(PyObject *SWIGUNUSEDPARM(self), Py
       CPLErrorReset();
     }
     result = (char *)OGRDataSourceShadow_GetName(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6677,7 +7147,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_DataSource_DeleteLayer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -6704,12 +7174,14 @@ SWIGINTERN PyObject *_wrap_DataSource_DeleteLayer(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (OGRErr)OGRDataSourceShadow_DeleteLayer(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -6720,14 +7192,11 @@ SWIGINTERN PyObject *_wrap_DataSource_DeleteLayer(PyObject *SWIGUNUSEDPARM(self)
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6735,7 +7204,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_DataSource_SyncToDisk(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -6753,12 +7222,14 @@ SWIGINTERN PyObject *_wrap_DataSource_SyncToDisk(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (OGRErr)OGRDataSourceShadow_SyncToDisk(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -6769,14 +7240,11 @@ SWIGINTERN PyObject *_wrap_DataSource_SyncToDisk(PyObject *SWIGUNUSEDPARM(self),
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6784,7 +7252,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_DataSource_FlushCache(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -6801,14 +7269,17 @@ SWIGINTERN PyObject *_wrap_DataSource_FlushCache(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     OGRDataSourceShadow_FlushCache(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6816,7 +7287,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_DataSource_CreateLayer(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   OSRSpatialReferenceShadow *arg3 = (OSRSpatialReferenceShadow *) NULL ;
@@ -6879,8 +7350,12 @@ SWIGINTERN PyObject *_wrap_DataSource_CreateLayer(PyObject *SWIGUNUSEDPARM(self)
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj4);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj4);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj4,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -6922,12 +7397,14 @@ SWIGINTERN PyObject *_wrap_DataSource_CreateLayer(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (OGRLayerShadow *)OGRDataSourceShadow_CreateLayer(arg1,(char const *)arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -6935,6 +7412,7 @@ SWIGINTERN PyObject *_wrap_DataSource_CreateLayer(PyObject *SWIGUNUSEDPARM(self)
     /* %typemap(freearg) char **options */
     CSLDestroy( arg5 );
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -6947,7 +7425,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_DataSource_CopyLayer(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
   OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
   char *arg3 = (char *) 0 ;
@@ -6997,8 +7475,12 @@ SWIGINTERN PyObject *_wrap_DataSource_CopyLayer(PyObject *SWIGUNUSEDPARM(self),
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj3);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj3);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj3,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -7040,12 +7522,14 @@ SWIGINTERN PyObject *_wrap_DataSource_CopyLayer(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (OGRLayerShadow *)OGRDataSourceShadow_CopyLayer(arg1,arg2,(char const *)arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
@@ -7053,6 +7537,7 @@ SWIGINTERN PyObject *_wrap_DataSource_CopyLayer(PyObject *SWIGUNUSEDPARM(self),
     /* %typemap(freearg) char **options */
     CSLDestroy( arg4 );
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
@@ -7065,7 +7550,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_DataSource_GetLayerByIndex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
   int arg2 = (int) 0 ;
   void *argp1 = 0 ;
@@ -7094,14 +7579,17 @@ SWIGINTERN PyObject *_wrap_DataSource_GetLayerByIndex(PyObject *SWIGUNUSEDPARM(s
       CPLErrorReset();
     }
     result = (OGRLayerShadow *)OGRDataSourceShadow_GetLayerByIndex(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7109,7 +7597,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_DataSource_GetLayerByName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -7137,15 +7625,18 @@ SWIGINTERN PyObject *_wrap_DataSource_GetLayerByName(PyObject *SWIGUNUSEDPARM(se
       CPLErrorReset();
     }
     result = (OGRLayerShadow *)OGRDataSourceShadow_GetLayerByName(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -7154,7 +7645,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_DataSource_TestCapability(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -7187,15 +7678,18 @@ SWIGINTERN PyObject *_wrap_DataSource_TestCapability(PyObject *SWIGUNUSEDPARM(se
       CPLErrorReset();
     }
     result = (bool)OGRDataSourceShadow_TestCapability(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_bool(static_cast< bool >(result));
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -7204,7 +7698,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_DataSource_ExecuteSQL(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   OGRGeometryShadow *arg3 = (OGRGeometryShadow *) NULL ;
@@ -7263,16 +7757,19 @@ SWIGINTERN PyObject *_wrap_DataSource_ExecuteSQL(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (OGRLayerShadow *)OGRDataSourceShadow_ExecuteSQL(arg1,(char const *)arg2,arg3,(char const *)arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -7282,7 +7779,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_DataSource_ReleaseResultSet(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
   OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
   void *argp1 = 0 ;
@@ -7306,14 +7803,17 @@ SWIGINTERN PyObject *_wrap_DataSource_ReleaseResultSet(PyObject *SWIGUNUSEDPARM(
       CPLErrorReset();
     }
     OGRDataSourceShadow_ReleaseResultSet(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7321,7 +7821,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_DataSource_GetStyleTable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -7339,14 +7839,17 @@ SWIGINTERN PyObject *_wrap_DataSource_GetStyleTable(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     result = (OGRStyleTableShadow *)OGRDataSourceShadow_GetStyleTable(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7354,7 +7857,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_DataSource_SetStyleTable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
   OGRStyleTableShadow *arg2 = (OGRStyleTableShadow *) 0 ;
   void *argp1 = 0 ;
@@ -7380,14 +7883,17 @@ SWIGINTERN PyObject *_wrap_DataSource_SetStyleTable(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     OGRDataSourceShadow_SetStyleTable(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7395,7 +7901,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_DataSource_StartTransaction(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
   int arg2 = (int) FALSE ;
   void *argp1 = 0 ;
@@ -7427,12 +7933,14 @@ SWIGINTERN PyObject *_wrap_DataSource_StartTransaction(PyObject *SWIGUNUSEDPARM(
       CPLErrorReset();
     }
     result = (OGRErr)OGRDataSourceShadow_StartTransaction(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -7443,14 +7951,11 @@ SWIGINTERN PyObject *_wrap_DataSource_StartTransaction(PyObject *SWIGUNUSEDPARM(
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7458,7 +7963,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_DataSource_CommitTransaction(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -7476,12 +7981,14 @@ SWIGINTERN PyObject *_wrap_DataSource_CommitTransaction(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     result = (OGRErr)OGRDataSourceShadow_CommitTransaction(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -7492,14 +7999,11 @@ SWIGINTERN PyObject *_wrap_DataSource_CommitTransaction(PyObject *SWIGUNUSEDPARM
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7507,7 +8011,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_DataSource_RollbackTransaction(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -7525,12 +8029,14 @@ SWIGINTERN PyObject *_wrap_DataSource_RollbackTransaction(PyObject *SWIGUNUSEDPA
       CPLErrorReset();
     }
     result = (OGRErr)OGRDataSourceShadow_RollbackTransaction(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -7541,14 +8047,11 @@ SWIGINTERN PyObject *_wrap_DataSource_RollbackTransaction(PyObject *SWIGUNUSEDPA
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7563,7 +8066,7 @@ SWIGINTERN PyObject *DataSource_swigregister(PyObject *SWIGUNUSEDPARM(self), PyO
 }
 
 SWIGINTERN PyObject *_wrap_Layer_GetRefCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -7581,14 +8084,17 @@ SWIGINTERN PyObject *_wrap_Layer_GetRefCount(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (int)OGRLayerShadow_GetRefCount(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7596,7 +8102,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_SetSpatialFilter__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
@@ -7622,14 +8128,17 @@ SWIGINTERN PyObject *_wrap_Layer_SetSpatialFilter__SWIG_0(PyObject *SWIGUNUSEDPA
       CPLErrorReset();
     }
     OGRLayerShadow_SetSpatialFilter__SWIG_0(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7637,7 +8146,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_SetSpatialFilterRect__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -7690,14 +8199,17 @@ SWIGINTERN PyObject *_wrap_Layer_SetSpatialFilterRect__SWIG_0(PyObject *SWIGUNUS
       CPLErrorReset();
     }
     OGRLayerShadow_SetSpatialFilterRect__SWIG_0(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7705,7 +8217,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_SetSpatialFilter__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   int arg2 ;
   OGRGeometryShadow *arg3 = (OGRGeometryShadow *) 0 ;
@@ -7740,14 +8252,17 @@ SWIGINTERN PyObject *_wrap_Layer_SetSpatialFilter__SWIG_1(PyObject *SWIGUNUSEDPA
       CPLErrorReset();
     }
     OGRLayerShadow_SetSpatialFilter__SWIG_1(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7759,9 +8274,9 @@ SWIGINTERN PyObject *_wrap_Layer_SetSpatialFilter(PyObject *self, PyObject *args
   PyObject *argv[4];
   int ii;
   
-  if (!PyTuple_Check(args)) SWIG_fail;
+  if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
   argc = (int)PyObject_Length(args);
-  for (ii = 0; (ii < argc) && (ii < 3); ii++) {
+  for (ii = 0; (ii < 3) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
   if (argc == 2) {
@@ -7800,16 +8315,16 @@ SWIGINTERN PyObject *_wrap_Layer_SetSpatialFilter(PyObject *self, PyObject *args
   }
   
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Layer_SetSpatialFilter'.\n"
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'Layer_SetSpatialFilter'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    SetSpatialFilter(OGRLayerShadow *,OGRGeometryShadow *)\n"
-    "    SetSpatialFilter(OGRLayerShadow *,int,OGRGeometryShadow *)\n");
-  return NULL;
+    "    OGRLayerShadow::SetSpatialFilter(OGRGeometryShadow *)\n"
+    "    OGRLayerShadow::SetSpatialFilter(int,OGRGeometryShadow *)\n");
+  return 0;
 }
 
 
 SWIGINTERN PyObject *_wrap_Layer_SetSpatialFilterRect__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   int arg2 ;
   double arg3 ;
@@ -7871,14 +8386,17 @@ SWIGINTERN PyObject *_wrap_Layer_SetSpatialFilterRect__SWIG_1(PyObject *SWIGUNUS
       CPLErrorReset();
     }
     OGRLayerShadow_SetSpatialFilterRect__SWIG_1(arg1,arg2,arg3,arg4,arg5,arg6);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7890,9 +8408,9 @@ SWIGINTERN PyObject *_wrap_Layer_SetSpatialFilterRect(PyObject *self, PyObject *
   PyObject *argv[7];
   int ii;
   
-  if (!PyTuple_Check(args)) SWIG_fail;
+  if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
   argc = (int)PyObject_Length(args);
-  for (ii = 0; (ii < argc) && (ii < 6); ii++) {
+  for (ii = 0; (ii < 6) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
   if (argc == 5) {
@@ -7969,16 +8487,16 @@ SWIGINTERN PyObject *_wrap_Layer_SetSpatialFilterRect(PyObject *self, PyObject *
   }
   
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Layer_SetSpatialFilterRect'.\n"
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'Layer_SetSpatialFilterRect'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    SetSpatialFilterRect(OGRLayerShadow *,double,double,double,double)\n"
-    "    SetSpatialFilterRect(OGRLayerShadow *,int,double,double,double,double)\n");
-  return NULL;
+    "    OGRLayerShadow::SetSpatialFilterRect(double,double,double,double)\n"
+    "    OGRLayerShadow::SetSpatialFilterRect(int,double,double,double,double)\n");
+  return 0;
 }
 
 
 SWIGINTERN PyObject *_wrap_Layer_GetSpatialFilter(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -7996,14 +8514,17 @@ SWIGINTERN PyObject *_wrap_Layer_GetSpatialFilter(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)OGRLayerShadow_GetSpatialFilter(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8011,7 +8532,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_SetAttributeFilter(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -8039,12 +8560,14 @@ SWIGINTERN PyObject *_wrap_Layer_SetAttributeFilter(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     result = (OGRErr)OGRLayerShadow_SetAttributeFilter(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -8056,14 +8579,11 @@ SWIGINTERN PyObject *_wrap_Layer_SetAttributeFilter(PyObject *SWIGUNUSEDPARM(sel
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -8072,7 +8592,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_ResetReading(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -8089,14 +8609,17 @@ SWIGINTERN PyObject *_wrap_Layer_ResetReading(PyObject *SWIGUNUSEDPARM(self), Py
       CPLErrorReset();
     }
     OGRLayerShadow_ResetReading(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8104,7 +8627,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_GetName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -8122,14 +8645,17 @@ SWIGINTERN PyObject *_wrap_Layer_GetName(PyObject *SWIGUNUSEDPARM(self), PyObjec
       CPLErrorReset();
     }
     result = (char *)OGRLayerShadow_GetName(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8137,7 +8663,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_GetGeomType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -8155,14 +8681,17 @@ SWIGINTERN PyObject *_wrap_Layer_GetGeomType(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (OGRwkbGeometryType)OGRLayerShadow_GetGeomType(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8170,7 +8699,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_GetGeometryColumn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -8188,14 +8717,17 @@ SWIGINTERN PyObject *_wrap_Layer_GetGeometryColumn(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     result = (char *)OGRLayerShadow_GetGeometryColumn(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8203,7 +8735,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_GetFIDColumn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -8221,14 +8753,17 @@ SWIGINTERN PyObject *_wrap_Layer_GetFIDColumn(PyObject *SWIGUNUSEDPARM(self), Py
       CPLErrorReset();
     }
     result = (char *)OGRLayerShadow_GetFIDColumn(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8236,7 +8771,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_GetFeature(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   GIntBig arg2 ;
   void *argp1 = 0 ;
@@ -8264,14 +8799,17 @@ SWIGINTERN PyObject *_wrap_Layer_GetFeature(PyObject *SWIGUNUSEDPARM(self), PyOb
       CPLErrorReset();
     }
     result = (OGRFeatureShadow *)OGRLayerShadow_GetFeature(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8279,7 +8817,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_GetNextFeature(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -8297,14 +8835,17 @@ SWIGINTERN PyObject *_wrap_Layer_GetNextFeature(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (OGRFeatureShadow *)OGRLayerShadow_GetNextFeature(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8312,7 +8853,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_SetNextByIndex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   GIntBig arg2 ;
   void *argp1 = 0 ;
@@ -8340,12 +8881,14 @@ SWIGINTERN PyObject *_wrap_Layer_SetNextByIndex(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (OGRErr)OGRLayerShadow_SetNextByIndex(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -8356,14 +8899,11 @@ SWIGINTERN PyObject *_wrap_Layer_SetNextByIndex(PyObject *SWIGUNUSEDPARM(self),
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8371,7 +8911,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_SetFeature(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
   void *argp1 = 0 ;
@@ -8403,12 +8943,14 @@ SWIGINTERN PyObject *_wrap_Layer_SetFeature(PyObject *SWIGUNUSEDPARM(self), PyOb
       CPLErrorReset();
     }
     result = (OGRErr)OGRLayerShadow_SetFeature(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -8419,14 +8961,11 @@ SWIGINTERN PyObject *_wrap_Layer_SetFeature(PyObject *SWIGUNUSEDPARM(self), PyOb
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8434,7 +8973,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_CreateFeature(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
   void *argp1 = 0 ;
@@ -8466,12 +9005,14 @@ SWIGINTERN PyObject *_wrap_Layer_CreateFeature(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     result = (OGRErr)OGRLayerShadow_CreateFeature(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -8482,14 +9023,11 @@ SWIGINTERN PyObject *_wrap_Layer_CreateFeature(PyObject *SWIGUNUSEDPARM(self), P
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8497,7 +9035,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_DeleteFeature(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   GIntBig arg2 ;
   void *argp1 = 0 ;
@@ -8525,12 +9063,14 @@ SWIGINTERN PyObject *_wrap_Layer_DeleteFeature(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     result = (OGRErr)OGRLayerShadow_DeleteFeature(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -8541,14 +9081,11 @@ SWIGINTERN PyObject *_wrap_Layer_DeleteFeature(PyObject *SWIGUNUSEDPARM(self), P
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8556,7 +9093,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_SyncToDisk(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -8574,12 +9111,14 @@ SWIGINTERN PyObject *_wrap_Layer_SyncToDisk(PyObject *SWIGUNUSEDPARM(self), PyOb
       CPLErrorReset();
     }
     result = (OGRErr)OGRLayerShadow_SyncToDisk(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -8590,14 +9129,11 @@ SWIGINTERN PyObject *_wrap_Layer_SyncToDisk(PyObject *SWIGUNUSEDPARM(self), PyOb
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8605,7 +9141,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_GetLayerDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -8623,14 +9159,17 @@ SWIGINTERN PyObject *_wrap_Layer_GetLayerDefn(PyObject *SWIGUNUSEDPARM(self), Py
       CPLErrorReset();
     }
     result = (OGRFeatureDefnShadow *)OGRLayerShadow_GetLayerDefn(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8638,7 +9177,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_GetFeatureCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   int arg2 = (int) 1 ;
   void *argp1 = 0 ;
@@ -8670,12 +9209,14 @@ SWIGINTERN PyObject *_wrap_Layer_GetFeatureCount(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = OGRLayerShadow_GetFeatureCount(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     char szTmp[32];
@@ -8686,6 +9227,7 @@ SWIGINTERN PyObject *_wrap_Layer_GetFeatureCount(PyObject *SWIGUNUSEDPARM(self),
     resultobj = PyInt_FromString(szTmp, NULL, 10);
 #endif
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8693,7 +9235,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_GetExtent(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   double *arg2 ;
   int *arg3 = (int *) NULL ;
@@ -8755,12 +9297,14 @@ SWIGINTERN PyObject *_wrap_Layer_GetExtent(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     OGRLayerShadow_GetExtent(arg1,arg2,arg3,arg4,arg5,arg6);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
@@ -8775,6 +9319,7 @@ SWIGINTERN PyObject *_wrap_Layer_GetExtent(PyObject *SWIGUNUSEDPARM(self), PyObj
     }
     resultobj = t_output_helper(resultobj,r);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8782,7 +9327,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_TestCapability(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -8815,15 +9360,18 @@ SWIGINTERN PyObject *_wrap_Layer_TestCapability(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (bool)OGRLayerShadow_TestCapability(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_bool(static_cast< bool >(result));
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -8832,7 +9380,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_CreateField(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   OGRFieldDefnShadow *arg2 = (OGRFieldDefnShadow *) 0 ;
   int arg3 = (int) 1 ;
@@ -8878,12 +9426,14 @@ SWIGINTERN PyObject *_wrap_Layer_CreateField(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (OGRErr)OGRLayerShadow_CreateField(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -8894,14 +9444,11 @@ SWIGINTERN PyObject *_wrap_Layer_CreateField(PyObject *SWIGUNUSEDPARM(self), PyO
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8909,7 +9456,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_DeleteField(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -8936,12 +9483,14 @@ SWIGINTERN PyObject *_wrap_Layer_DeleteField(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (OGRErr)OGRLayerShadow_DeleteField(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -8952,14 +9501,11 @@ SWIGINTERN PyObject *_wrap_Layer_DeleteField(PyObject *SWIGUNUSEDPARM(self), PyO
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8967,7 +9513,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_ReorderField(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   int arg2 ;
   int arg3 ;
@@ -9003,12 +9549,14 @@ SWIGINTERN PyObject *_wrap_Layer_ReorderField(PyObject *SWIGUNUSEDPARM(self), Py
       CPLErrorReset();
     }
     result = (OGRErr)OGRLayerShadow_ReorderField(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -9019,14 +9567,11 @@ SWIGINTERN PyObject *_wrap_Layer_ReorderField(PyObject *SWIGUNUSEDPARM(self), Py
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9034,7 +9579,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_ReorderFields(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   int arg2 ;
   int *arg3 = (int *) 0 ;
@@ -9057,7 +9602,12 @@ SWIGINTERN PyObject *_wrap_Layer_ReorderFields(PyObject *SWIGUNUSEDPARM(self), P
       PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
-    arg2 = PySequence_Size(obj1);
+    Py_ssize_t size = PySequence_Size(obj1);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    arg2 = (int)size;
     arg3 = (int*) malloc(arg2*sizeof(int));
     for( int i = 0; i<arg2; i++ ) {
       PyObject *o = PySequence_GetItem(obj1,i);
@@ -9074,12 +9624,14 @@ SWIGINTERN PyObject *_wrap_Layer_ReorderFields(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     result = (OGRErr)OGRLayerShadow_ReorderFields(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -9096,14 +9648,11 @@ SWIGINTERN PyObject *_wrap_Layer_ReorderFields(PyObject *SWIGUNUSEDPARM(self), P
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -9117,7 +9666,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_AlterFieldDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   int arg2 ;
   OGRFieldDefnShadow *arg3 = (OGRFieldDefnShadow *) 0 ;
@@ -9167,12 +9716,14 @@ SWIGINTERN PyObject *_wrap_Layer_AlterFieldDefn(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (OGRErr)OGRLayerShadow_AlterFieldDefn(arg1,arg2,arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -9183,14 +9734,11 @@ SWIGINTERN PyObject *_wrap_Layer_AlterFieldDefn(PyObject *SWIGUNUSEDPARM(self),
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9198,7 +9746,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_CreateGeomField(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   OGRGeomFieldDefnShadow *arg2 = (OGRGeomFieldDefnShadow *) 0 ;
   int arg3 = (int) 1 ;
@@ -9244,12 +9792,14 @@ SWIGINTERN PyObject *_wrap_Layer_CreateGeomField(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (OGRErr)OGRLayerShadow_CreateGeomField(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -9260,14 +9810,11 @@ SWIGINTERN PyObject *_wrap_Layer_CreateGeomField(PyObject *SWIGUNUSEDPARM(self),
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9275,7 +9822,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_StartTransaction(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -9293,12 +9840,14 @@ SWIGINTERN PyObject *_wrap_Layer_StartTransaction(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (OGRErr)OGRLayerShadow_StartTransaction(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -9309,14 +9858,11 @@ SWIGINTERN PyObject *_wrap_Layer_StartTransaction(PyObject *SWIGUNUSEDPARM(self)
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9324,7 +9870,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_CommitTransaction(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -9342,12 +9888,14 @@ SWIGINTERN PyObject *_wrap_Layer_CommitTransaction(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     result = (OGRErr)OGRLayerShadow_CommitTransaction(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -9358,14 +9906,11 @@ SWIGINTERN PyObject *_wrap_Layer_CommitTransaction(PyObject *SWIGUNUSEDPARM(self
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9373,7 +9918,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_RollbackTransaction(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -9391,12 +9936,14 @@ SWIGINTERN PyObject *_wrap_Layer_RollbackTransaction(PyObject *SWIGUNUSEDPARM(se
       CPLErrorReset();
     }
     result = (OGRErr)OGRLayerShadow_RollbackTransaction(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -9407,14 +9954,11 @@ SWIGINTERN PyObject *_wrap_Layer_RollbackTransaction(PyObject *SWIGUNUSEDPARM(se
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9422,7 +9966,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_FindFieldIndex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   int arg3 ;
@@ -9459,15 +10003,18 @@ SWIGINTERN PyObject *_wrap_Layer_FindFieldIndex(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (int)OGRLayerShadow_FindFieldIndex(arg1,(char const *)arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -9476,7 +10023,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_GetSpatialRef(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -9494,14 +10041,17 @@ SWIGINTERN PyObject *_wrap_Layer_GetSpatialRef(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     result = (OSRSpatialReferenceShadow *)OGRLayerShadow_GetSpatialRef(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OSRSpatialReferenceShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9509,7 +10059,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_GetFeaturesRead(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -9527,12 +10077,14 @@ SWIGINTERN PyObject *_wrap_Layer_GetFeaturesRead(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = OGRLayerShadow_GetFeaturesRead(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     char szTmp[32];
@@ -9543,6 +10095,7 @@ SWIGINTERN PyObject *_wrap_Layer_GetFeaturesRead(PyObject *SWIGUNUSEDPARM(self),
     resultobj = PyInt_FromString(szTmp, NULL, 10);
 #endif
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9550,7 +10103,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_SetIgnoredFields(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   char **arg2 = (char **) 0 ;
   void *argp1 = 0 ;
@@ -9577,8 +10130,12 @@ SWIGINTERN PyObject *_wrap_Layer_SetIgnoredFields(PyObject *SWIGUNUSEDPARM(self)
       SWIG_fail;
     }
     
-    int size = PySequence_Size(obj1);
-    for (int i = 0; i < size; i++) {
+    Py_ssize_t size = PySequence_Size(obj1);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    for (int i = 0; i < (int)size; i++) {
       PyObject* pyObj = PySequence_GetItem(obj1,i);
       if (PyUnicode_Check(pyObj))
       {
@@ -9614,12 +10171,14 @@ SWIGINTERN PyObject *_wrap_Layer_SetIgnoredFields(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (OGRErr)OGRLayerShadow_SetIgnoredFields(arg1,(char const **)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -9634,14 +10193,11 @@ SWIGINTERN PyObject *_wrap_Layer_SetIgnoredFields(PyObject *SWIGUNUSEDPARM(self)
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -9653,7 +10209,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_Intersection(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
   OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
@@ -9713,8 +10269,12 @@ SWIGINTERN PyObject *_wrap_Layer_Intersection(PyObject *SWIGUNUSEDPARM(self), Py
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj3);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj3);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj3,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -9752,16 +10312,16 @@ SWIGINTERN PyObject *_wrap_Layer_Intersection(PyObject *SWIGUNUSEDPARM(self), Py
       /* callback_func typemap */
       if (obj4 && obj4 != Py_None ) {
         void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj4, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj4,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
         
         if ( cbfunction == GDALTermProgress ) {
           arg5 = GDALTermProgress;
         } else {
           if (!PyCallable_Check(obj4)) {
-            PyErr_SetString( PyExc_RuntimeError, 
+            PyErr_SetString( PyExc_RuntimeError,
               "Object given is not a Python function" );
             SWIG_fail;
           }
@@ -9784,12 +10344,14 @@ SWIGINTERN PyObject *_wrap_Layer_Intersection(PyObject *SWIGUNUSEDPARM(self), Py
       CPLErrorReset();
     }
     result = (OGRErr)OGRLayerShadow_Intersection(arg1,arg2,arg3,arg4,arg5,arg6);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -9810,14 +10372,11 @@ SWIGINTERN PyObject *_wrap_Layer_Intersection(PyObject *SWIGUNUSEDPARM(self), Py
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -9835,7 +10394,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_Union(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
   OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
@@ -9895,8 +10454,12 @@ SWIGINTERN PyObject *_wrap_Layer_Union(PyObject *SWIGUNUSEDPARM(self), PyObject
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj3);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj3);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj3,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -9934,16 +10497,16 @@ SWIGINTERN PyObject *_wrap_Layer_Union(PyObject *SWIGUNUSEDPARM(self), PyObject
       /* callback_func typemap */
       if (obj4 && obj4 != Py_None ) {
         void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj4, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj4,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
         
         if ( cbfunction == GDALTermProgress ) {
           arg5 = GDALTermProgress;
         } else {
           if (!PyCallable_Check(obj4)) {
-            PyErr_SetString( PyExc_RuntimeError, 
+            PyErr_SetString( PyExc_RuntimeError,
               "Object given is not a Python function" );
             SWIG_fail;
           }
@@ -9966,12 +10529,14 @@ SWIGINTERN PyObject *_wrap_Layer_Union(PyObject *SWIGUNUSEDPARM(self), PyObject
       CPLErrorReset();
     }
     result = (OGRErr)OGRLayerShadow_Union(arg1,arg2,arg3,arg4,arg5,arg6);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -9992,14 +10557,11 @@ SWIGINTERN PyObject *_wrap_Layer_Union(PyObject *SWIGUNUSEDPARM(self), PyObject
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -10017,7 +10579,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_SymDifference(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
   OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
@@ -10077,8 +10639,12 @@ SWIGINTERN PyObject *_wrap_Layer_SymDifference(PyObject *SWIGUNUSEDPARM(self), P
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj3);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj3);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj3,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -10116,16 +10682,16 @@ SWIGINTERN PyObject *_wrap_Layer_SymDifference(PyObject *SWIGUNUSEDPARM(self), P
       /* callback_func typemap */
       if (obj4 && obj4 != Py_None ) {
         void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj4, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj4,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
         
         if ( cbfunction == GDALTermProgress ) {
           arg5 = GDALTermProgress;
         } else {
           if (!PyCallable_Check(obj4)) {
-            PyErr_SetString( PyExc_RuntimeError, 
+            PyErr_SetString( PyExc_RuntimeError,
               "Object given is not a Python function" );
             SWIG_fail;
           }
@@ -10148,12 +10714,14 @@ SWIGINTERN PyObject *_wrap_Layer_SymDifference(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     result = (OGRErr)OGRLayerShadow_SymDifference(arg1,arg2,arg3,arg4,arg5,arg6);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -10174,14 +10742,11 @@ SWIGINTERN PyObject *_wrap_Layer_SymDifference(PyObject *SWIGUNUSEDPARM(self), P
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -10199,7 +10764,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_Identity(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
   OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
@@ -10259,8 +10824,12 @@ SWIGINTERN PyObject *_wrap_Layer_Identity(PyObject *SWIGUNUSEDPARM(self), PyObje
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj3);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj3);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj3,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -10298,16 +10867,16 @@ SWIGINTERN PyObject *_wrap_Layer_Identity(PyObject *SWIGUNUSEDPARM(self), PyObje
       /* callback_func typemap */
       if (obj4 && obj4 != Py_None ) {
         void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj4, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj4,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
         
         if ( cbfunction == GDALTermProgress ) {
           arg5 = GDALTermProgress;
         } else {
           if (!PyCallable_Check(obj4)) {
-            PyErr_SetString( PyExc_RuntimeError, 
+            PyErr_SetString( PyExc_RuntimeError,
               "Object given is not a Python function" );
             SWIG_fail;
           }
@@ -10330,12 +10899,14 @@ SWIGINTERN PyObject *_wrap_Layer_Identity(PyObject *SWIGUNUSEDPARM(self), PyObje
       CPLErrorReset();
     }
     result = (OGRErr)OGRLayerShadow_Identity(arg1,arg2,arg3,arg4,arg5,arg6);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -10356,14 +10927,11 @@ SWIGINTERN PyObject *_wrap_Layer_Identity(PyObject *SWIGUNUSEDPARM(self), PyObje
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -10381,7 +10949,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_Update(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
   OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
@@ -10441,8 +11009,12 @@ SWIGINTERN PyObject *_wrap_Layer_Update(PyObject *SWIGUNUSEDPARM(self), PyObject
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj3);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj3);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj3,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -10480,16 +11052,16 @@ SWIGINTERN PyObject *_wrap_Layer_Update(PyObject *SWIGUNUSEDPARM(self), PyObject
       /* callback_func typemap */
       if (obj4 && obj4 != Py_None ) {
         void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj4, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj4,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
         
         if ( cbfunction == GDALTermProgress ) {
           arg5 = GDALTermProgress;
         } else {
           if (!PyCallable_Check(obj4)) {
-            PyErr_SetString( PyExc_RuntimeError, 
+            PyErr_SetString( PyExc_RuntimeError,
               "Object given is not a Python function" );
             SWIG_fail;
           }
@@ -10512,12 +11084,14 @@ SWIGINTERN PyObject *_wrap_Layer_Update(PyObject *SWIGUNUSEDPARM(self), PyObject
       CPLErrorReset();
     }
     result = (OGRErr)OGRLayerShadow_Update(arg1,arg2,arg3,arg4,arg5,arg6);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -10538,14 +11112,11 @@ SWIGINTERN PyObject *_wrap_Layer_Update(PyObject *SWIGUNUSEDPARM(self), PyObject
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -10563,7 +11134,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_Clip(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
   OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
@@ -10623,8 +11194,12 @@ SWIGINTERN PyObject *_wrap_Layer_Clip(PyObject *SWIGUNUSEDPARM(self), PyObject *
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj3);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj3);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj3,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -10662,16 +11237,16 @@ SWIGINTERN PyObject *_wrap_Layer_Clip(PyObject *SWIGUNUSEDPARM(self), PyObject *
       /* callback_func typemap */
       if (obj4 && obj4 != Py_None ) {
         void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj4, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj4,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
         
         if ( cbfunction == GDALTermProgress ) {
           arg5 = GDALTermProgress;
         } else {
           if (!PyCallable_Check(obj4)) {
-            PyErr_SetString( PyExc_RuntimeError, 
+            PyErr_SetString( PyExc_RuntimeError,
               "Object given is not a Python function" );
             SWIG_fail;
           }
@@ -10694,12 +11269,14 @@ SWIGINTERN PyObject *_wrap_Layer_Clip(PyObject *SWIGUNUSEDPARM(self), PyObject *
       CPLErrorReset();
     }
     result = (OGRErr)OGRLayerShadow_Clip(arg1,arg2,arg3,arg4,arg5,arg6);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -10720,14 +11297,11 @@ SWIGINTERN PyObject *_wrap_Layer_Clip(PyObject *SWIGUNUSEDPARM(self), PyObject *
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -10745,7 +11319,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_Erase(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
   OGRLayerShadow *arg3 = (OGRLayerShadow *) 0 ;
@@ -10805,8 +11379,12 @@ SWIGINTERN PyObject *_wrap_Layer_Erase(PyObject *SWIGUNUSEDPARM(self), PyObject
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj3);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj3);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj3,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -10844,16 +11422,16 @@ SWIGINTERN PyObject *_wrap_Layer_Erase(PyObject *SWIGUNUSEDPARM(self), PyObject
       /* callback_func typemap */
       if (obj4 && obj4 != Py_None ) {
         void* cbfunction = NULL;
-        SWIG_ConvertPtr( obj4, 
-          (void**)&cbfunction,
-          SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
-          SWIG_POINTER_EXCEPTION | 0 );
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj4,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
         
         if ( cbfunction == GDALTermProgress ) {
           arg5 = GDALTermProgress;
         } else {
           if (!PyCallable_Check(obj4)) {
-            PyErr_SetString( PyExc_RuntimeError, 
+            PyErr_SetString( PyExc_RuntimeError,
               "Object given is not a Python function" );
             SWIG_fail;
           }
@@ -10876,12 +11454,14 @@ SWIGINTERN PyObject *_wrap_Layer_Erase(PyObject *SWIGUNUSEDPARM(self), PyObject
       CPLErrorReset();
     }
     result = (OGRErr)OGRLayerShadow_Erase(arg1,arg2,arg3,arg4,arg5,arg6);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -10902,14 +11482,11 @@ SWIGINTERN PyObject *_wrap_Layer_Erase(PyObject *SWIGUNUSEDPARM(self), PyObject
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -10927,7 +11504,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_GetStyleTable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -10945,14 +11522,17 @@ SWIGINTERN PyObject *_wrap_Layer_GetStyleTable(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     result = (OGRStyleTableShadow *)OGRLayerShadow_GetStyleTable(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRStyleTableShadow, 0 |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -10960,7 +11540,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_SetStyleTable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   OGRStyleTableShadow *arg2 = (OGRStyleTableShadow *) 0 ;
   void *argp1 = 0 ;
@@ -10986,14 +11566,17 @@ SWIGINTERN PyObject *_wrap_Layer_SetStyleTable(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     OGRLayerShadow_SetStyleTable(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11008,7 +11591,7 @@ SWIGINTERN PyObject *Layer_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject
 }
 
 SWIGINTERN PyObject *_wrap_delete_Feature(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -11025,14 +11608,17 @@ SWIGINTERN PyObject *_wrap_delete_Feature(PyObject *SWIGUNUSEDPARM(self), PyObje
       CPLErrorReset();
     }
     delete_OGRFeatureShadow(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11040,7 +11626,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_new_Feature(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -11066,14 +11652,17 @@ SWIGINTERN PyObject *_wrap_new_Feature(PyObject *SWIGUNUSEDPARM(self), PyObject
       CPLErrorReset();
     }
     result = (OGRFeatureShadow *)new_OGRFeatureShadow(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureShadow, SWIG_POINTER_NEW |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11081,7 +11670,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetDefnRef(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -11099,14 +11688,17 @@ SWIGINTERN PyObject *_wrap_Feature_GetDefnRef(PyObject *SWIGUNUSEDPARM(self), Py
       CPLErrorReset();
     }
     result = (OGRFeatureDefnShadow *)OGRFeatureShadow_GetDefnRef(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11114,7 +11706,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_SetGeometry(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
@@ -11141,12 +11733,14 @@ SWIGINTERN PyObject *_wrap_Feature_SetGeometry(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     result = (OGRErr)OGRFeatureShadow_SetGeometry(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -11157,14 +11751,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetGeometry(PyObject *SWIGUNUSEDPARM(self), P
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11172,7 +11763,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_SetGeometryDirectly(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
@@ -11197,12 +11788,14 @@ SWIGINTERN PyObject *_wrap_Feature_SetGeometryDirectly(PyObject *SWIGUNUSEDPARM(
       CPLErrorReset();
     }
     result = (OGRErr)OGRFeatureShadow_SetGeometryDirectly(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -11213,14 +11806,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetGeometryDirectly(PyObject *SWIGUNUSEDPARM(
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11228,7 +11818,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetGeometryRef(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -11246,14 +11836,17 @@ SWIGINTERN PyObject *_wrap_Feature_GetGeometryRef(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)OGRFeatureShadow_GetGeometryRef(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11261,7 +11854,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_SetGeomField__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
   OGRGeometryShadow *arg3 = (OGRGeometryShadow *) 0 ;
@@ -11297,12 +11890,14 @@ SWIGINTERN PyObject *_wrap_Feature_SetGeomField__SWIG_0(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     result = (OGRErr)OGRFeatureShadow_SetGeomField__SWIG_0(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -11313,14 +11908,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetGeomField__SWIG_0(PyObject *SWIGUNUSEDPARM
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11328,7 +11920,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_SetGeomField__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   OGRGeometryShadow *arg3 = (OGRGeometryShadow *) 0 ;
@@ -11370,12 +11962,14 @@ SWIGINTERN PyObject *_wrap_Feature_SetGeomField__SWIG_1(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     result = (OGRErr)OGRFeatureShadow_SetGeomField__SWIG_1(arg1,(char const *)arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -11387,14 +11981,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetGeomField__SWIG_1(PyObject *SWIGUNUSEDPARM
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -11407,9 +11998,9 @@ SWIGINTERN PyObject *_wrap_Feature_SetGeomField(PyObject *self, PyObject *args)
   PyObject *argv[4];
   int ii;
   
-  if (!PyTuple_Check(args)) SWIG_fail;
+  if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
   argc = (int)PyObject_Length(args);
-  for (ii = 0; (ii < argc) && (ii < 3); ii++) {
+  for (ii = 0; (ii < 3) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
   if (argc == 3) {
@@ -11452,16 +12043,16 @@ SWIGINTERN PyObject *_wrap_Feature_SetGeomField(PyObject *self, PyObject *args)
   }
   
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_SetGeomField'.\n"
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'Feature_SetGeomField'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    SetGeomField(OGRFeatureShadow *,int,OGRGeometryShadow *)\n"
-    "    SetGeomField(OGRFeatureShadow *,char const *,OGRGeometryShadow *)\n");
-  return NULL;
+    "    OGRFeatureShadow::SetGeomField(int,OGRGeometryShadow *)\n"
+    "    OGRFeatureShadow::SetGeomField(char const *,OGRGeometryShadow *)\n");
+  return 0;
 }
 
 
 SWIGINTERN PyObject *_wrap_Feature_SetGeomFieldDirectly__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
   OGRGeometryShadow *arg3 = (OGRGeometryShadow *) 0 ;
@@ -11495,12 +12086,14 @@ SWIGINTERN PyObject *_wrap_Feature_SetGeomFieldDirectly__SWIG_0(PyObject *SWIGUN
       CPLErrorReset();
     }
     result = (OGRErr)OGRFeatureShadow_SetGeomFieldDirectly__SWIG_0(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -11511,14 +12104,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetGeomFieldDirectly__SWIG_0(PyObject *SWIGUN
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11526,7 +12116,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_SetGeomFieldDirectly__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   OGRGeometryShadow *arg3 = (OGRGeometryShadow *) 0 ;
@@ -11566,12 +12156,14 @@ SWIGINTERN PyObject *_wrap_Feature_SetGeomFieldDirectly__SWIG_1(PyObject *SWIGUN
       CPLErrorReset();
     }
     result = (OGRErr)OGRFeatureShadow_SetGeomFieldDirectly__SWIG_1(arg1,(char const *)arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -11583,14 +12175,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetGeomFieldDirectly__SWIG_1(PyObject *SWIGUN
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -11603,9 +12192,9 @@ SWIGINTERN PyObject *_wrap_Feature_SetGeomFieldDirectly(PyObject *self, PyObject
   PyObject *argv[4];
   int ii;
   
-  if (!PyTuple_Check(args)) SWIG_fail;
+  if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
   argc = (int)PyObject_Length(args);
-  for (ii = 0; (ii < argc) && (ii < 3); ii++) {
+  for (ii = 0; (ii < 3) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
   if (argc == 3) {
@@ -11648,16 +12237,16 @@ SWIGINTERN PyObject *_wrap_Feature_SetGeomFieldDirectly(PyObject *self, PyObject
   }
   
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_SetGeomFieldDirectly'.\n"
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'Feature_SetGeomFieldDirectly'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    SetGeomFieldDirectly(OGRFeatureShadow *,int,OGRGeometryShadow *)\n"
-    "    SetGeomFieldDirectly(OGRFeatureShadow *,char const *,OGRGeometryShadow *)\n");
-  return NULL;
+    "    OGRFeatureShadow::SetGeomFieldDirectly(int,OGRGeometryShadow *)\n"
+    "    OGRFeatureShadow::SetGeomFieldDirectly(char const *,OGRGeometryShadow *)\n");
+  return 0;
 }
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldRef__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -11684,14 +12273,17 @@ SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldRef__SWIG_0(PyObject *SWIGUNUSEDP
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)OGRFeatureShadow_GetGeomFieldRef__SWIG_0(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11699,7 +12291,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldRef__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -11732,15 +12324,18 @@ SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldRef__SWIG_1(PyObject *SWIGUNUSEDP
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)OGRFeatureShadow_GetGeomFieldRef__SWIG_1(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -11753,9 +12348,9 @@ SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldRef(PyObject *self, PyObject *arg
   PyObject *argv[3];
   int ii;
   
-  if (!PyTuple_Check(args)) SWIG_fail;
+  if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
   argc = (int)PyObject_Length(args);
-  for (ii = 0; (ii < argc) && (ii < 2); ii++) {
+  for (ii = 0; (ii < 2) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
   if (argc == 2) {
@@ -11788,16 +12383,16 @@ SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldRef(PyObject *self, PyObject *arg
   }
   
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_GetGeomFieldRef'.\n"
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'Feature_GetGeomFieldRef'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    GetGeomFieldRef(OGRFeatureShadow *,int)\n"
-    "    GetGeomFieldRef(OGRFeatureShadow *,char const *)\n");
-  return NULL;
+    "    OGRFeatureShadow::GetGeomFieldRef(int)\n"
+    "    OGRFeatureShadow::GetGeomFieldRef(char const *)\n");
+  return 0;
 }
 
 
 SWIGINTERN PyObject *_wrap_Feature_Clone(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -11815,14 +12410,17 @@ SWIGINTERN PyObject *_wrap_Feature_Clone(PyObject *SWIGUNUSEDPARM(self), PyObjec
       CPLErrorReset();
     }
     result = (OGRFeatureShadow *)OGRFeatureShadow_Clone(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11830,7 +12428,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_Equal(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
   void *argp1 = 0 ;
@@ -11862,14 +12460,17 @@ SWIGINTERN PyObject *_wrap_Feature_Equal(PyObject *SWIGUNUSEDPARM(self), PyObjec
       CPLErrorReset();
     }
     result = (bool)OGRFeatureShadow_Equal(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_bool(static_cast< bool >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11877,7 +12478,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetFieldCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -11895,14 +12496,17 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldCount(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (int)OGRFeatureShadow_GetFieldCount(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11910,7 +12514,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetFieldDefnRef__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -11937,14 +12541,17 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldDefnRef__SWIG_0(PyObject *SWIGUNUSEDP
       CPLErrorReset();
     }
     result = (OGRFieldDefnShadow *)OGRFeatureShadow_GetFieldDefnRef__SWIG_0(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11952,7 +12559,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetFieldDefnRef__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -11985,15 +12592,18 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldDefnRef__SWIG_1(PyObject *SWIGUNUSEDP
       CPLErrorReset();
     }
     result = (OGRFieldDefnShadow *)OGRFeatureShadow_GetFieldDefnRef__SWIG_1(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -12006,9 +12616,9 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldDefnRef(PyObject *self, PyObject *arg
   PyObject *argv[3];
   int ii;
   
-  if (!PyTuple_Check(args)) SWIG_fail;
+  if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
   argc = (int)PyObject_Length(args);
-  for (ii = 0; (ii < argc) && (ii < 2); ii++) {
+  for (ii = 0; (ii < 2) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
   if (argc == 2) {
@@ -12041,16 +12651,16 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldDefnRef(PyObject *self, PyObject *arg
   }
   
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_GetFieldDefnRef'.\n"
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'Feature_GetFieldDefnRef'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    GetFieldDefnRef(OGRFeatureShadow *,int)\n"
-    "    GetFieldDefnRef(OGRFeatureShadow *,char const *)\n");
-  return NULL;
+    "    OGRFeatureShadow::GetFieldDefnRef(int)\n"
+    "    OGRFeatureShadow::GetFieldDefnRef(char const *)\n");
+  return 0;
 }
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -12068,14 +12678,17 @@ SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldCount(PyObject *SWIGUNUSEDPARM(se
       CPLErrorReset();
     }
     result = (int)OGRFeatureShadow_GetGeomFieldCount(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -12083,7 +12696,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldDefnRef__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -12110,14 +12723,17 @@ SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldDefnRef__SWIG_0(PyObject *SWIGUNU
       CPLErrorReset();
     }
     result = (OGRGeomFieldDefnShadow *)OGRFeatureShadow_GetGeomFieldDefnRef__SWIG_0(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -12125,7 +12741,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldDefnRef__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -12158,15 +12774,18 @@ SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldDefnRef__SWIG_1(PyObject *SWIGUNU
       CPLErrorReset();
     }
     result = (OGRGeomFieldDefnShadow *)OGRFeatureShadow_GetGeomFieldDefnRef__SWIG_1(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -12179,9 +12798,9 @@ SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldDefnRef(PyObject *self, PyObject
   PyObject *argv[3];
   int ii;
   
-  if (!PyTuple_Check(args)) SWIG_fail;
+  if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
   argc = (int)PyObject_Length(args);
-  for (ii = 0; (ii < argc) && (ii < 2); ii++) {
+  for (ii = 0; (ii < 2) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
   if (argc == 2) {
@@ -12214,16 +12833,16 @@ SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldDefnRef(PyObject *self, PyObject
   }
   
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_GetGeomFieldDefnRef'.\n"
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'Feature_GetGeomFieldDefnRef'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    GetGeomFieldDefnRef(OGRFeatureShadow *,int)\n"
-    "    GetGeomFieldDefnRef(OGRFeatureShadow *,char const *)\n");
-  return NULL;
+    "    OGRFeatureShadow::GetGeomFieldDefnRef(int)\n"
+    "    OGRFeatureShadow::GetGeomFieldDefnRef(char const *)\n");
+  return 0;
 }
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetFieldAsString__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -12250,14 +12869,17 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsString__SWIG_0(PyObject *SWIGUNUSED
       CPLErrorReset();
     }
     result = (char *)OGRFeatureShadow_GetFieldAsString__SWIG_0(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -12265,7 +12887,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetFieldAsString__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -12298,15 +12920,18 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsString__SWIG_1(PyObject *SWIGUNUSED
       CPLErrorReset();
     }
     result = (char *)OGRFeatureShadow_GetFieldAsString__SWIG_1(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -12319,9 +12944,9 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsString(PyObject *self, PyObject *ar
   PyObject *argv[3];
   int ii;
   
-  if (!PyTuple_Check(args)) SWIG_fail;
+  if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
   argc = (int)PyObject_Length(args);
-  for (ii = 0; (ii < argc) && (ii < 2); ii++) {
+  for (ii = 0; (ii < 2) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
   if (argc == 2) {
@@ -12354,16 +12979,16 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsString(PyObject *self, PyObject *ar
   }
   
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_GetFieldAsString'.\n"
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'Feature_GetFieldAsString'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    GetFieldAsString(OGRFeatureShadow *,int)\n"
-    "    GetFieldAsString(OGRFeatureShadow *,char const *)\n");
-  return NULL;
+    "    OGRFeatureShadow::GetFieldAsString(int)\n"
+    "    OGRFeatureShadow::GetFieldAsString(char const *)\n");
+  return 0;
 }
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -12390,14 +13015,17 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger__SWIG_0(PyObject *SWIGUNUSE
       CPLErrorReset();
     }
     result = (int)OGRFeatureShadow_GetFieldAsInteger__SWIG_0(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -12405,7 +13033,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -12438,15 +13066,18 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger__SWIG_1(PyObject *SWIGUNUSE
       CPLErrorReset();
     }
     result = (int)OGRFeatureShadow_GetFieldAsInteger__SWIG_1(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -12459,9 +13090,9 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger(PyObject *self, PyObject *a
   PyObject *argv[3];
   int ii;
   
-  if (!PyTuple_Check(args)) SWIG_fail;
+  if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
   argc = (int)PyObject_Length(args);
-  for (ii = 0; (ii < argc) && (ii < 2); ii++) {
+  for (ii = 0; (ii < 2) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
   if (argc == 2) {
@@ -12494,16 +13125,16 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger(PyObject *self, PyObject *a
   }
   
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_GetFieldAsInteger'.\n"
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'Feature_GetFieldAsInteger'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    GetFieldAsInteger(OGRFeatureShadow *,int)\n"
-    "    GetFieldAsInteger(OGRFeatureShadow *,char const *)\n");
-  return NULL;
+    "    OGRFeatureShadow::GetFieldAsInteger(int)\n"
+    "    OGRFeatureShadow::GetFieldAsInteger(char const *)\n");
+  return 0;
 }
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger64__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -12530,12 +13161,14 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger64__SWIG_0(PyObject *SWIGUNU
       CPLErrorReset();
     }
     result = OGRFeatureShadow_GetFieldAsInteger64__SWIG_0(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     char szTmp[32];
@@ -12546,6 +13179,7 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger64__SWIG_0(PyObject *SWIGUNU
     resultobj = PyInt_FromString(szTmp, NULL, 10);
 #endif
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -12553,7 +13187,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger64__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -12586,12 +13220,14 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger64__SWIG_1(PyObject *SWIGUNU
       CPLErrorReset();
     }
     result = OGRFeatureShadow_GetFieldAsInteger64__SWIG_1(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     char szTmp[32];
@@ -12603,6 +13239,7 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger64__SWIG_1(PyObject *SWIGUNU
 #endif
   }
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -12615,9 +13252,9 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger64(PyObject *self, PyObject
   PyObject *argv[3];
   int ii;
   
-  if (!PyTuple_Check(args)) SWIG_fail;
+  if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
   argc = (int)PyObject_Length(args);
-  for (ii = 0; (ii < argc) && (ii < 2); ii++) {
+  for (ii = 0; (ii < 2) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
   if (argc == 2) {
@@ -12650,16 +13287,16 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger64(PyObject *self, PyObject
   }
   
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_GetFieldAsInteger64'.\n"
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'Feature_GetFieldAsInteger64'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    GetFieldAsInteger64(OGRFeatureShadow *,int)\n"
-    "    GetFieldAsInteger64(OGRFeatureShadow *,char const *)\n");
-  return NULL;
+    "    OGRFeatureShadow::GetFieldAsInteger64(int)\n"
+    "    OGRFeatureShadow::GetFieldAsInteger64(char const *)\n");
+  return 0;
 }
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDouble__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -12686,14 +13323,17 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDouble__SWIG_0(PyObject *SWIGUNUSED
       CPLErrorReset();
     }
     result = (double)OGRFeatureShadow_GetFieldAsDouble__SWIG_0(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_double(static_cast< double >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -12701,7 +13341,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDouble__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -12734,15 +13374,18 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDouble__SWIG_1(PyObject *SWIGUNUSED
       CPLErrorReset();
     }
     result = (double)OGRFeatureShadow_GetFieldAsDouble__SWIG_1(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_double(static_cast< double >(result));
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -12755,9 +13398,9 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDouble(PyObject *self, PyObject *ar
   PyObject *argv[3];
   int ii;
   
-  if (!PyTuple_Check(args)) SWIG_fail;
+  if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
   argc = (int)PyObject_Length(args);
-  for (ii = 0; (ii < argc) && (ii < 2); ii++) {
+  for (ii = 0; (ii < 2) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
   if (argc == 2) {
@@ -12790,16 +13433,16 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDouble(PyObject *self, PyObject *ar
   }
   
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_GetFieldAsDouble'.\n"
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'Feature_GetFieldAsDouble'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    GetFieldAsDouble(OGRFeatureShadow *,int)\n"
-    "    GetFieldAsDouble(OGRFeatureShadow *,char const *)\n");
-  return NULL;
+    "    OGRFeatureShadow::GetFieldAsDouble(int)\n"
+    "    OGRFeatureShadow::GetFieldAsDouble(char const *)\n");
+  return 0;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDateTime(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDateTime__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
   int *arg3 = (int *) 0 ;
@@ -12852,397 +13495,819 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDateTime(PyObject *SWIGUNUSEDPARM(s
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_GetFieldAsDateTime(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+    OGRFeatureShadow_GetFieldAsDateTime__SWIG_0(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
-  if (SWIG_IsTmpObj(res3)) {
+  if (ReturnSame(SWIG_IsTmpObj(res3))) {
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg3)));
   } else {
     int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_int, new_flags));
   }
-  if (SWIG_IsTmpObj(res4)) {
+  if (ReturnSame(SWIG_IsTmpObj(res4))) {
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4)));
   } else {
     int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags));
   }
-  if (SWIG_IsTmpObj(res5)) {
+  if (ReturnSame(SWIG_IsTmpObj(res5))) {
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg5)));
   } else {
     int new_flags = SWIG_IsNewObj(res5) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg5), SWIGTYPE_p_int, new_flags));
   }
-  if (SWIG_IsTmpObj(res6)) {
+  if (ReturnSame(SWIG_IsTmpObj(res6))) {
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg6)));
   } else {
     int new_flags = SWIG_IsNewObj(res6) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg6), SWIGTYPE_p_int, new_flags));
   }
-  if (SWIG_IsTmpObj(res7)) {
+  if (ReturnSame(SWIG_IsTmpObj(res7))) {
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg7)));
   } else {
     int new_flags = SWIG_IsNewObj(res7) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg7), SWIGTYPE_p_int, new_flags));
   }
-  if (SWIG_IsTmpObj(res8)) {
+  if (ReturnSame(SWIG_IsTmpObj(res8))) {
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_float((*arg8)));
   } else {
     int new_flags = SWIG_IsNewObj(res8) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg8), SWIGTYPE_p_float, new_flags));
   }
-  if (SWIG_IsTmpObj(res9)) {
+  if (ReturnSame(SWIG_IsTmpObj(res9))) {
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg9)));
   } else {
     int new_flags = SWIG_IsNewObj(res9) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg9), SWIGTYPE_p_int, new_flags));
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_GetFieldAsIntegerList(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDateTime__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  int arg2 ;
+  char *arg2 = (char *) 0 ;
   int *arg3 = (int *) 0 ;
-  int **arg4 = (int **) 0 ;
+  int *arg4 = (int *) 0 ;
+  int *arg5 = (int *) 0 ;
+  int *arg6 = (int *) 0 ;
+  int *arg7 = (int *) 0 ;
+  float *arg8 = (float *) 0 ;
+  int *arg9 = (int *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int val2 ;
-  int ecode2 = 0 ;
-  int nLen3 ;
-  int *pList3 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  int temp3 ;
+  int res3 = SWIG_TMPOBJ ;
+  int temp4 ;
+  int res4 = SWIG_TMPOBJ ;
+  int temp5 ;
+  int res5 = SWIG_TMPOBJ ;
+  int temp6 ;
+  int res6 = SWIG_TMPOBJ ;
+  int temp7 ;
+  int res7 = SWIG_TMPOBJ ;
+  float temp8 ;
+  int res8 = SWIG_TMPOBJ ;
+  int temp9 ;
+  int res9 = SWIG_TMPOBJ ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   
-  {
-    /* %typemap(in,numinputs=0) (int *nLen3, const int **pList3) (int nLen3, int *pList3) */
-    arg3 = &nLen3;
-    arg4 = &pList3;
-  }
-  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsIntegerList",&obj0,&obj1)) SWIG_fail;
+  arg3 = &temp3;
+  arg4 = &temp4;
+  arg5 = &temp5;
+  arg6 = &temp6;
+  arg7 = &temp7;
+  arg8 = &temp8;
+  arg9 = &temp9;
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsDateTime",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsIntegerList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsDateTime" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-  ecode2 = SWIG_AsVal_int(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsIntegerList" "', argument " "2"" of type '" "int""'");
-  } 
-  arg2 = static_cast< int >(val2);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_GetFieldAsDateTime" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_GetFieldAsIntegerList(arg1,arg2,arg3,(int const **)arg4);
+    OGRFeatureShadow_GetFieldAsDateTime__SWIG_1(arg1,(char const *)arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
-  {
-    /* %typemap(argout) (int *nLen, const int **pList ) */
-    Py_DECREF(resultobj);
-    PyObject *out = PyList_New( *arg3 );
-    for( int i=0; i<*arg3; i++ ) {
-      PyObject *val = PyInt_FromLong( (*arg4)[i] );
-      PyList_SetItem( out, i, val );
-    }
-    resultobj = out;
+  if (ReturnSame(SWIG_IsTmpObj(res3))) {
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg3)));
+  } else {
+    int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_int, new_flags));
+  }
+  if (ReturnSame(SWIG_IsTmpObj(res4))) {
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4)));
+  } else {
+    int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags));
+  }
+  if (ReturnSame(SWIG_IsTmpObj(res5))) {
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg5)));
+  } else {
+    int new_flags = SWIG_IsNewObj(res5) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg5), SWIGTYPE_p_int, new_flags));
+  }
+  if (ReturnSame(SWIG_IsTmpObj(res6))) {
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg6)));
+  } else {
+    int new_flags = SWIG_IsNewObj(res6) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg6), SWIGTYPE_p_int, new_flags));
+  }
+  if (ReturnSame(SWIG_IsTmpObj(res7))) {
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg7)));
+  } else {
+    int new_flags = SWIG_IsNewObj(res7) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg7), SWIGTYPE_p_int, new_flags));
+  }
+  if (ReturnSame(SWIG_IsTmpObj(res8))) {
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_float((*arg8)));
+  } else {
+    int new_flags = SWIG_IsNewObj(res8) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg8), SWIGTYPE_p_float, new_flags));
+  }
+  if (ReturnSame(SWIG_IsTmpObj(res9))) {
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg9)));
+  } else {
+    int new_flags = SWIG_IsNewObj(res9) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg9), SWIGTYPE_p_int, new_flags));
   }
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger64List(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  int arg2 ;
-  int *arg3 = (int *) 0 ;
-  GIntBig **arg4 = (GIntBig **) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  int val2 ;
-  int ecode2 = 0 ;
-  int nLen3 ;
-  GIntBig *pList3 ;
-  PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
+SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDateTime(PyObject *self, PyObject *args) {
+  int argc;
+  PyObject *argv[3];
+  int ii;
   
-  {
-    /* %typemap(in,numinputs=0) (int *nLen3, const GIntBig **pList3) (int nLen3, GIntBig *pList3) */
-    arg3 = &nLen3;
-    arg4 = &pList3;
-  }
-  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsInteger64List",&obj0,&obj1)) SWIG_fail;
+  if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
+  argc = (int)PyObject_Length(args);
+  for (ii = 0; (ii < 2) && (ii < argc); ii++) {
+    argv[ii] = PyTuple_GET_ITEM(args,ii);
+  }
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        return _wrap_Feature_GetFieldAsDateTime__SWIG_0(self, args);
+      }
+    }
+  }
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
+      _v = SWIG_CheckState(res);
+      if (_v) {
+        return _wrap_Feature_GetFieldAsDateTime__SWIG_1(self, args);
+      }
+    }
+  }
+  
+fail:
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'Feature_GetFieldAsDateTime'.\n"
+    "  Possible C/C++ prototypes are:\n"
+    "    OGRFeatureShadow::GetFieldAsDateTime(int,int *,int *,int *,int *,int *,float *,int *)\n"
+    "    OGRFeatureShadow::GetFieldAsDateTime(char const *,int *,int *,int *,int *,int *,float *,int *)\n");
+  return 0;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_GetFieldAsIntegerList__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  int *arg3 = (int *) 0 ;
+  int **arg4 = (int **) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  int nLen3 ;
+  int *pList3 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  {
+    /* %typemap(in,numinputs=0) (int *nLen3, const int **pList3) (int nLen3, int *pList3) */
+    arg3 = &nLen3;
+    arg4 = &pList3;
+  }
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsIntegerList",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsInteger64List" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsIntegerList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsInteger64List" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsIntegerList" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_GetFieldAsInteger64List(arg1,arg2,arg3,(GIntBig const **)arg4);
+    OGRFeatureShadow_GetFieldAsIntegerList__SWIG_0(arg1,arg2,arg3,(int const **)arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
-    /* %typemap(argout) (int *nLen, const GIntBig **pList ) */
+    /* %typemap(argout) (int *nLen, const int **pList ) */
     Py_DECREF(resultobj);
     PyObject *out = PyList_New( *arg3 );
     for( int i=0; i<*arg3; i++ ) {
-      char szTmp[32];
-      sprintf(szTmp, CPL_FRMT_GIB, (*arg4)[i]);
-      PyObject* val;
-#if PY_VERSION_HEX>=0x03000000
-      val = PyLong_FromString(szTmp, NULL, 10);
-#else
-      val = PyInt_FromString(szTmp, NULL, 10);
-#endif
+      PyObject *val = PyInt_FromLong( (*arg4)[i] );
       PyList_SetItem( out, i, val );
     }
     resultobj = out;
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDoubleList(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+SWIGINTERN PyObject *_wrap_Feature_GetFieldAsIntegerList__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-  int arg2 ;
+  char *arg2 = (char *) 0 ;
   int *arg3 = (int *) 0 ;
-  double **arg4 = (double **) 0 ;
+  int **arg4 = (int **) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int val2 ;
-  int ecode2 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
   int nLen3 ;
-  double *pList3 ;
+  int *pList3 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   
   {
-    /* %typemap(in,numinputs=0) (int *nLen3, const double **pList3) (int nLen3, double *pList3) */
+    /* %typemap(in,numinputs=0) (int *nLen3, const int **pList3) (int nLen3, int *pList3) */
     arg3 = &nLen3;
     arg4 = &pList3;
   }
-  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsDoubleList",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsIntegerList",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsDoubleList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsIntegerList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-  ecode2 = SWIG_AsVal_int(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsDoubleList" "', argument " "2"" of type '" "int""'");
-  } 
-  arg2 = static_cast< int >(val2);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_GetFieldAsIntegerList" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_GetFieldAsDoubleList(arg1,arg2,arg3,(double const **)arg4);
+    OGRFeatureShadow_GetFieldAsIntegerList__SWIG_1(arg1,(char const *)arg2,arg3,(int const **)arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
-    /* %typemap(argout) (int *nLen, const double **pList ) */
+    /* %typemap(argout) (int *nLen, const int **pList ) */
     Py_DECREF(resultobj);
     PyObject *out = PyList_New( *arg3 );
     for( int i=0; i<*arg3; i++ ) {
-      PyObject *val = PyFloat_FromDouble( (*arg4)[i] );
+      PyObject *val = PyInt_FromLong( (*arg4)[i] );
       PyList_SetItem( out, i, val );
     }
     resultobj = out;
   }
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_GetFieldAsStringList(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+SWIGINTERN PyObject *_wrap_Feature_GetFieldAsIntegerList(PyObject *self, PyObject *args) {
+  int argc;
+  PyObject *argv[3];
+  int ii;
+  
+  if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
+  argc = (int)PyObject_Length(args);
+  for (ii = 0; (ii < 2) && (ii < argc); ii++) {
+    argv[ii] = PyTuple_GET_ITEM(args,ii);
+  }
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        return _wrap_Feature_GetFieldAsIntegerList__SWIG_0(self, args);
+      }
+    }
+  }
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
+      _v = SWIG_CheckState(res);
+      if (_v) {
+        return _wrap_Feature_GetFieldAsIntegerList__SWIG_1(self, args);
+      }
+    }
+  }
+  
+fail:
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'Feature_GetFieldAsIntegerList'.\n"
+    "  Possible C/C++ prototypes are:\n"
+    "    OGRFeatureShadow::GetFieldAsIntegerList(int,int *,int const **)\n"
+    "    OGRFeatureShadow::GetFieldAsIntegerList(char const *,int *,int const **)\n");
+  return 0;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger64List(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
+  int *arg3 = (int *) 0 ;
+  GIntBig **arg4 = (GIntBig **) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   int val2 ;
   int ecode2 = 0 ;
+  int nLen3 ;
+  GIntBig *pList3 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  char **result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsStringList",&obj0,&obj1)) SWIG_fail;
+  {
+    /* %typemap(in,numinputs=0) (int *nLen3, const GIntBig **pList3) (int nLen3, GIntBig *pList3) */
+    arg3 = &nLen3;
+    arg4 = &pList3;
+  }
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsInteger64List",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsStringList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsInteger64List" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsStringList" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsInteger64List" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char **)OGRFeatureShadow_GetFieldAsStringList(arg1,arg2);
+    OGRFeatureShadow_GetFieldAsInteger64List(arg1,arg2,arg3,(GIntBig const **)arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
+  resultobj = SWIG_Py_Void();
   {
-    /* %typemap(out) char **options -> ( string ) */
-    char **stringarray = result;
-    if ( stringarray == NULL ) {
-      resultobj = Py_None;
-      Py_INCREF( resultobj );
-    }
-    else {
-      int len = CSLCount( stringarray );
-      resultobj = PyList_New( len );
-      for ( int i = 0; i < len; ++i ) {
-        PyObject *o = GDALPythonObjectFromCStr( stringarray[i] );
-        PyList_SetItem(resultobj, i, o );
-      }
+    /* %typemap(argout) (int *nLen, const GIntBig **pList ) */
+    Py_DECREF(resultobj);
+    PyObject *out = PyList_New( *arg3 );
+    for( int i=0; i<*arg3; i++ ) {
+      char szTmp[32];
+      sprintf(szTmp, CPL_FRMT_GIB, (*arg4)[i]);
+      PyObject* val;
+#if PY_VERSION_HEX>=0x03000000
+      val = PyLong_FromString(szTmp, NULL, 10);
+#else
+      val = PyInt_FromString(szTmp, NULL, 10);
+#endif
+      PyList_SetItem( out, i, val );
     }
+    resultobj = out;
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Feature_GetFieldAsBinary__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDoubleList__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
   int *arg3 = (int *) 0 ;
-  char **arg4 = (char **) 0 ;
+  double **arg4 = (double **) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   int val2 ;
   int ecode2 = 0 ;
-  int nLen3 = 0 ;
-  char *pBuf3 = 0 ;
+  int nLen3 ;
+  double *pList3 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  OGRErr result;
   
   {
-    /* %typemap(in,numinputs=0) (int *nLen3, char **pBuf3 ) */
+    /* %typemap(in,numinputs=0) (int *nLen3, const double **pList3) (int nLen3, double *pList3) */
     arg3 = &nLen3;
-    arg4 = &pBuf3;
+    arg4 = &pList3;
   }
-  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsBinary",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsDoubleList",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsBinary" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsDoubleList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsBinary" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsDoubleList" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRFeatureShadow_GetFieldAsBinary__SWIG_0(arg1,arg2,arg3,arg4);
+    OGRFeatureShadow_GetFieldAsDoubleList__SWIG_0(arg1,arg2,arg3,(double const **)arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
-  }
-  {
-    /* %typemap(out) OGRErr */
-    if ( result != 0 && bUseExceptions) {
-      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
-      SWIG_fail;
-    }
-  }
-  {
-    /* %typemap(argout) (int *nLen, char **pBuf ) */
-    Py_XDECREF(resultobj);
-#if PY_VERSION_HEX >= 0x03000000
-    resultobj = PyBytes_FromStringAndSize( *arg4, *arg3 );
-#else
-    resultobj = PyString_FromStringAndSize( *arg4, *arg3 );
 #endif
   }
+  resultobj = SWIG_Py_Void();
   {
-    /* %typemap(freearg) (int *nLen, char **pBuf ) */
-    if( *arg3 ) {
-      free( *arg4 );
-    }
-  }
-  {
-    /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
-      resultobj = PyInt_FromLong( result );
+    /* %typemap(argout) (int *nLen, const double **pList ) */
+    Py_DECREF(resultobj);
+    PyObject *out = PyList_New( *arg3 );
+    for( int i=0; i<*arg3; i++ ) {
+      PyObject *val = PyFloat_FromDouble( (*arg4)[i] );
+      PyList_SetItem( out, i, val );
     }
+    resultobj = out;
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
-  {
-    /* %typemap(freearg) (int *nLen, char **pBuf ) */
-    if( *arg3 ) {
-      free( *arg4 );
-    }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDoubleList__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  int *arg3 = (int *) 0 ;
+  double **arg4 = (double **) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  int nLen3 ;
+  double *pList3 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  {
+    /* %typemap(in,numinputs=0) (int *nLen3, const double **pList3) (int nLen3, double *pList3) */
+    arg3 = &nLen3;
+    arg4 = &pList3;
+  }
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsDoubleList",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsDoubleList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_GetFieldAsDoubleList" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRFeatureShadow_GetFieldAsDoubleList__SWIG_1(arg1,(char const *)arg2,arg3,(double const **)arg4);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_Py_Void();
+  {
+    /* %typemap(argout) (int *nLen, const double **pList ) */
+    Py_DECREF(resultobj);
+    PyObject *out = PyList_New( *arg3 );
+    for( int i=0; i<*arg3; i++ ) {
+      PyObject *val = PyFloat_FromDouble( (*arg4)[i] );
+      PyList_SetItem( out, i, val );
+    }
+    resultobj = out;
+  }
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDoubleList(PyObject *self, PyObject *args) {
+  int argc;
+  PyObject *argv[3];
+  int ii;
+  
+  if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
+  argc = (int)PyObject_Length(args);
+  for (ii = 0; (ii < 2) && (ii < argc); ii++) {
+    argv[ii] = PyTuple_GET_ITEM(args,ii);
+  }
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        return _wrap_Feature_GetFieldAsDoubleList__SWIG_0(self, args);
+      }
+    }
+  }
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
+      _v = SWIG_CheckState(res);
+      if (_v) {
+        return _wrap_Feature_GetFieldAsDoubleList__SWIG_1(self, args);
+      }
+    }
+  }
+  
+fail:
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'Feature_GetFieldAsDoubleList'.\n"
+    "  Possible C/C++ prototypes are:\n"
+    "    OGRFeatureShadow::GetFieldAsDoubleList(int,int *,double const **)\n"
+    "    OGRFeatureShadow::GetFieldAsDoubleList(char const *,int *,double const **)\n");
+  return 0;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_GetFieldAsStringList(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  char **result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsStringList",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsStringList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsStringList" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (char **)OGRFeatureShadow_GetFieldAsStringList(arg1,arg2);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  {
+    /* %typemap(out) char **options -> ( string ) */
+    char **stringarray = result;
+    if ( stringarray == NULL ) {
+      resultobj = Py_None;
+      Py_INCREF( resultobj );
+    }
+    else {
+      int len = CSLCount( stringarray );
+      resultobj = PyList_New( len );
+      for ( int i = 0; i < len; ++i ) {
+        PyObject *o = GDALPythonObjectFromCStr( stringarray[i] );
+        PyList_SetItem(resultobj, i, o );
+      }
+    }
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_GetFieldAsBinary__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  int *arg3 = (int *) 0 ;
+  char **arg4 = (char **) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  int nLen3 = 0 ;
+  char *pBuf3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  OGRErr result;
+  
+  {
+    /* %typemap(in,numinputs=0) (int *nLen3, char **pBuf3 ) */
+    arg3 = &nLen3;
+    arg4 = &pBuf3;
+  }
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_GetFieldAsBinary",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsBinary" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsBinary" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OGRErr)OGRFeatureShadow_GetFieldAsBinary__SWIG_0(arg1,arg2,arg3,arg4);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  {
+    /* %typemap(out) OGRErr */
+    if ( result != 0 && bUseExceptions) {
+      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
+      SWIG_fail;
+    }
+  }
+  {
+    /* %typemap(argout) (int *nLen, char **pBuf ) */
+    Py_XDECREF(resultobj);
+#if PY_VERSION_HEX >= 0x03000000
+    resultobj = PyBytes_FromStringAndSize( *arg4, *arg3 );
+#else
+    resultobj = PyString_FromStringAndSize( *arg4, *arg3 );
+#endif
+  }
+  {
+    /* %typemap(freearg) (int *nLen, char **pBuf ) */
+    if( *arg3 ) {
+      free( *arg4 );
+    }
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
+      resultobj = PyInt_FromLong( result );
+    }
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) (int *nLen, char **pBuf ) */
+    if( *arg3 ) {
+      free( *arg4 );
+    }
   }
   return NULL;
 }
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetFieldAsBinary__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   int *arg3 = (int *) 0 ;
@@ -13284,12 +14349,14 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsBinary__SWIG_1(PyObject *SWIGUNUSED
       CPLErrorReset();
     }
     result = (OGRErr)OGRFeatureShadow_GetFieldAsBinary__SWIG_1(arg1,(char const *)arg2,arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -13316,14 +14383,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsBinary__SWIG_1(PyObject *SWIGUNUSED
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -13342,9 +14406,9 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsBinary(PyObject *self, PyObject *ar
   PyObject *argv[3];
   int ii;
   
-  if (!PyTuple_Check(args)) SWIG_fail;
+  if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
   argc = (int)PyObject_Length(args);
-  for (ii = 0; (ii < argc) && (ii < 2); ii++) {
+  for (ii = 0; (ii < 2) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
   if (argc == 2) {
@@ -13377,16 +14441,16 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsBinary(PyObject *self, PyObject *ar
   }
   
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_GetFieldAsBinary'.\n"
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'Feature_GetFieldAsBinary'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    GetFieldAsBinary(OGRFeatureShadow *,int,int *,char **)\n"
-    "    GetFieldAsBinary(OGRFeatureShadow *,char const *,int *,char **)\n");
-  return NULL;
+    "    OGRFeatureShadow::GetFieldAsBinary(int,int *,char **)\n"
+    "    OGRFeatureShadow::GetFieldAsBinary(char const *,int *,char **)\n");
+  return 0;
 }
 
 
 SWIGINTERN PyObject *_wrap_Feature_IsFieldSet__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -13413,14 +14477,17 @@ SWIGINTERN PyObject *_wrap_Feature_IsFieldSet__SWIG_0(PyObject *SWIGUNUSEDPARM(s
       CPLErrorReset();
     }
     result = (bool)OGRFeatureShadow_IsFieldSet__SWIG_0(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_bool(static_cast< bool >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -13428,7 +14495,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_IsFieldSet__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -13461,15 +14528,18 @@ SWIGINTERN PyObject *_wrap_Feature_IsFieldSet__SWIG_1(PyObject *SWIGUNUSEDPARM(s
       CPLErrorReset();
     }
     result = (bool)OGRFeatureShadow_IsFieldSet__SWIG_1(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_bool(static_cast< bool >(result));
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -13482,9 +14552,9 @@ SWIGINTERN PyObject *_wrap_Feature_IsFieldSet(PyObject *self, PyObject *args) {
   PyObject *argv[3];
   int ii;
   
-  if (!PyTuple_Check(args)) SWIG_fail;
+  if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
   argc = (int)PyObject_Length(args);
-  for (ii = 0; (ii < argc) && (ii < 2); ii++) {
+  for (ii = 0; (ii < 2) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
   if (argc == 2) {
@@ -13517,16 +14587,16 @@ SWIGINTERN PyObject *_wrap_Feature_IsFieldSet(PyObject *self, PyObject *args) {
   }
   
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_IsFieldSet'.\n"
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'Feature_IsFieldSet'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    IsFieldSet(OGRFeatureShadow *,int)\n"
-    "    IsFieldSet(OGRFeatureShadow *,char const *)\n");
-  return NULL;
+    "    OGRFeatureShadow::IsFieldSet(int)\n"
+    "    OGRFeatureShadow::IsFieldSet(char const *)\n");
+  return 0;
 }
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetFieldIndex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -13559,15 +14629,18 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldIndex(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (int)OGRFeatureShadow_GetFieldIndex(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -13576,7 +14649,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldIndex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -13609,15 +14682,18 @@ SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldIndex(PyObject *SWIGUNUSEDPARM(se
       CPLErrorReset();
     }
     result = (int)OGRFeatureShadow_GetGeomFieldIndex(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -13626,7 +14702,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetFID(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -13644,12 +14720,14 @@ SWIGINTERN PyObject *_wrap_Feature_GetFID(PyObject *SWIGUNUSEDPARM(self), PyObje
       CPLErrorReset();
     }
     result = OGRFeatureShadow_GetFID(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     char szTmp[32];
@@ -13660,6 +14738,7 @@ SWIGINTERN PyObject *_wrap_Feature_GetFID(PyObject *SWIGUNUSEDPARM(self), PyObje
     resultobj = PyInt_FromString(szTmp, NULL, 10);
 #endif
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -13667,7 +14746,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_SetFID(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   GIntBig arg2 ;
   void *argp1 = 0 ;
@@ -13695,12 +14774,14 @@ SWIGINTERN PyObject *_wrap_Feature_SetFID(PyObject *SWIGUNUSEDPARM(self), PyObje
       CPLErrorReset();
     }
     result = (OGRErr)OGRFeatureShadow_SetFID(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -13711,14 +14792,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetFID(PyObject *SWIGUNUSEDPARM(self), PyObje
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -13726,7 +14804,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_DumpReadable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -13743,14 +14821,17 @@ SWIGINTERN PyObject *_wrap_Feature_DumpReadable(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     OGRFeatureShadow_DumpReadable(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -13758,7 +14839,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_UnsetField__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -13784,14 +14865,17 @@ SWIGINTERN PyObject *_wrap_Feature_UnsetField__SWIG_0(PyObject *SWIGUNUSEDPARM(s
       CPLErrorReset();
     }
     OGRFeatureShadow_UnsetField__SWIG_0(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -13799,7 +14883,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_UnsetField__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -13831,15 +14915,18 @@ SWIGINTERN PyObject *_wrap_Feature_UnsetField__SWIG_1(PyObject *SWIGUNUSEDPARM(s
       CPLErrorReset();
     }
     OGRFeatureShadow_UnsetField__SWIG_1(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -13852,9 +14939,9 @@ SWIGINTERN PyObject *_wrap_Feature_UnsetField(PyObject *self, PyObject *args) {
   PyObject *argv[3];
   int ii;
   
-  if (!PyTuple_Check(args)) SWIG_fail;
+  if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
   argc = (int)PyObject_Length(args);
-  for (ii = 0; (ii < argc) && (ii < 2); ii++) {
+  for (ii = 0; (ii < 2) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
   if (argc == 2) {
@@ -13887,16 +14974,16 @@ SWIGINTERN PyObject *_wrap_Feature_UnsetField(PyObject *self, PyObject *args) {
   }
   
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_UnsetField'.\n"
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'Feature_UnsetField'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    UnsetField(OGRFeatureShadow *,int)\n"
-    "    UnsetField(OGRFeatureShadow *,char const *)\n");
-  return NULL;
+    "    OGRFeatureShadow::UnsetField(int)\n"
+    "    OGRFeatureShadow::UnsetField(char const *)\n");
+  return 0;
 }
 
 
 SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
   char *arg3 = (char *) 0 ;
@@ -13929,19 +15016,21 @@ SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_0(PyObject *SWIGUNUSEDPARM(sel
       SWIG_fail;
     }
     
-    arg3 = GDALPythonObjectToCStr(str3, &bToFree3); 
+    arg3 = GDALPythonObjectToCStr(str3, &bToFree3);
   }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
     OGRFeatureShadow_SetField__SWIG_0(arg1,arg2,(char const *)arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
@@ -13952,6 +15041,7 @@ SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_0(PyObject *SWIGUNUSEDPARM(sel
     }
     GDALPythonFreeCStr(arg3, bToFree3);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -13967,7 +15057,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   char *arg3 = (char *) 0 ;
@@ -14001,7 +15091,7 @@ SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_1(PyObject *SWIGUNUSEDPARM(sel
       SWIG_fail;
     }
     
-    arg3 = GDALPythonObjectToCStr(str3, &bToFree3); 
+    arg3 = GDALPythonObjectToCStr(str3, &bToFree3);
   }
   {
     if (!arg2) {
@@ -14013,12 +15103,14 @@ SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_1(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     OGRFeatureShadow_SetField__SWIG_1(arg1,(char const *)arg2,(char const *)arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -14030,6 +15122,7 @@ SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_1(PyObject *SWIGUNUSEDPARM(sel
     }
     GDALPythonFreeCStr(arg3, bToFree3);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -14046,7 +15139,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_SetFieldInteger64(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
   GIntBig arg3 ;
@@ -14082,14 +15175,17 @@ SWIGINTERN PyObject *_wrap_Feature_SetFieldInteger64(PyObject *SWIGUNUSEDPARM(se
       CPLErrorReset();
     }
     OGRFeatureShadow_SetFieldInteger64(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -14097,7 +15193,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_2(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
   double arg3 ;
@@ -14132,14 +15228,17 @@ SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_2(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     OGRFeatureShadow_SetField__SWIG_2(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -14147,7 +15246,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_3(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   double arg3 ;
@@ -14188,15 +15287,18 @@ SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_3(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     OGRFeatureShadow_SetField__SWIG_3(arg1,(char const *)arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -14205,7 +15307,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_4(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
   int arg3 ;
@@ -14294,14 +15396,17 @@ SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_4(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     OGRFeatureShadow_SetField__SWIG_4(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -14309,7 +15414,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_5(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   int arg3 ;
@@ -14404,15 +15509,18 @@ SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_5(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     OGRFeatureShadow_SetField__SWIG_5(arg1,(char const *)arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -14425,9 +15533,9 @@ SWIGINTERN PyObject *_wrap_Feature_SetField(PyObject *self, PyObject *args) {
   PyObject *argv[10];
   int ii;
   
-  if (!PyTuple_Check(args)) SWIG_fail;
+  if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
   argc = (int)PyObject_Length(args);
-  for (ii = 0; (ii < argc) && (ii < 9); ii++) {
+  for (ii = 0; (ii < 9) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
   if (argc == 3) {
@@ -14620,20 +15728,20 @@ SWIGINTERN PyObject *_wrap_Feature_SetField(PyObject *self, PyObject *args) {
   }
   
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_SetField'.\n"
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'Feature_SetField'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    SetField(OGRFeatureShadow *,int,char const *)\n"
-    "    SetField(OGRFeatureShadow *,char const *,char const *)\n"
-    "    SetField(OGRFeatureShadow *,int,double)\n"
-    "    SetField(OGRFeatureShadow *,char const *,double)\n"
-    "    SetField(OGRFeatureShadow *,int,int,int,int,int,int,float,int)\n"
-    "    SetField(OGRFeatureShadow *,char const *,int,int,int,int,int,float,int)\n");
-  return NULL;
+    "    OGRFeatureShadow::SetField(int,char const *)\n"
+    "    OGRFeatureShadow::SetField(char const *,char const *)\n"
+    "    OGRFeatureShadow::SetField(int,double)\n"
+    "    OGRFeatureShadow::SetField(char const *,double)\n"
+    "    OGRFeatureShadow::SetField(int,int,int,int,int,int,float,int)\n"
+    "    OGRFeatureShadow::SetField(char const *,int,int,int,int,int,float,int)\n");
+  return 0;
 }
 
 
 SWIGINTERN PyObject *_wrap_Feature_SetFieldIntegerList(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
   int arg3 ;
@@ -14664,7 +15772,12 @@ SWIGINTERN PyObject *_wrap_Feature_SetFieldIntegerList(PyObject *SWIGUNUSEDPARM(
       PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
-    arg3 = PySequence_Size(obj2);
+    Py_ssize_t size = PySequence_Size(obj2);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    arg3 = (int)size;
     arg4 = (int*) malloc(arg3*sizeof(int));
     for( int i = 0; i<arg3; i++ ) {
       PyObject *o = PySequence_GetItem(obj2,i);
@@ -14681,12 +15794,14 @@ SWIGINTERN PyObject *_wrap_Feature_SetFieldIntegerList(PyObject *SWIGUNUSEDPARM(
       CPLErrorReset();
     }
     OGRFeatureShadow_SetFieldIntegerList(arg1,arg2,arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
@@ -14695,6 +15810,7 @@ SWIGINTERN PyObject *_wrap_Feature_SetFieldIntegerList(PyObject *SWIGUNUSEDPARM(
       free((void*) arg4);
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -14708,7 +15824,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_SetFieldInteger64List(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
   int arg3 ;
@@ -14739,7 +15855,12 @@ SWIGINTERN PyObject *_wrap_Feature_SetFieldInteger64List(PyObject *SWIGUNUSEDPAR
       PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
-    arg3 = PySequence_Size(obj2);
+    Py_ssize_t size = PySequence_Size(obj2);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    arg3 = (int)size;
     arg4 = (GIntBig*) malloc(arg3*sizeof(GIntBig));
     for( int i = 0; i<arg3; i++ ) {
       PyObject *o = PySequence_GetItem(obj2,i);
@@ -14758,12 +15879,14 @@ SWIGINTERN PyObject *_wrap_Feature_SetFieldInteger64List(PyObject *SWIGUNUSEDPAR
       CPLErrorReset();
     }
     OGRFeatureShadow_SetFieldInteger64List(arg1,arg2,arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
@@ -14772,6 +15895,7 @@ SWIGINTERN PyObject *_wrap_Feature_SetFieldInteger64List(PyObject *SWIGUNUSEDPAR
       free((void*) arg4);
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -14785,7 +15909,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_SetFieldDoubleList(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
   int arg3 ;
@@ -14816,7 +15940,12 @@ SWIGINTERN PyObject *_wrap_Feature_SetFieldDoubleList(PyObject *SWIGUNUSEDPARM(s
       PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
-    arg3 = PySequence_Size(obj2);
+    Py_ssize_t size = PySequence_Size(obj2);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    arg3 = (int)size;
     arg4 = (double*) malloc(arg3*sizeof(double));
     for( int i = 0; i<arg3; i++ ) {
       PyObject *o = PySequence_GetItem(obj2,i);
@@ -14833,12 +15962,14 @@ SWIGINTERN PyObject *_wrap_Feature_SetFieldDoubleList(PyObject *SWIGUNUSEDPARM(s
       CPLErrorReset();
     }
     OGRFeatureShadow_SetFieldDoubleList(arg1,arg2,arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
@@ -14847,6 +15978,7 @@ SWIGINTERN PyObject *_wrap_Feature_SetFieldDoubleList(PyObject *SWIGUNUSEDPARM(s
       free((void*) arg4);
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -14860,7 +15992,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_SetFieldStringList(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
   char **arg3 = (char **) 0 ;
@@ -14895,8 +16027,12 @@ SWIGINTERN PyObject *_wrap_Feature_SetFieldStringList(PyObject *SWIGUNUSEDPARM(s
       SWIG_fail;
     }
     
-    int size = PySequence_Size(obj2);
-    for (int i = 0; i < size; i++) {
+    Py_ssize_t size = PySequence_Size(obj2);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    for (int i = 0; i < (int)size; i++) {
       PyObject* pyObj = PySequence_GetItem(obj2,i);
       if (PyUnicode_Check(pyObj))
       {
@@ -14932,18 +16068,21 @@ SWIGINTERN PyObject *_wrap_Feature_SetFieldStringList(PyObject *SWIGUNUSEDPARM(s
       CPLErrorReset();
     }
     OGRFeatureShadow_SetFieldStringList(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
     /* %typemap(freearg) char **options */
     CSLDestroy( arg3 );
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -14955,7 +16094,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_SetFieldBinaryFromHexString__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
   char *arg3 = (char *) 0 ;
@@ -14991,15 +16130,18 @@ SWIGINTERN PyObject *_wrap_Feature_SetFieldBinaryFromHexString__SWIG_0(PyObject
       CPLErrorReset();
     }
     OGRFeatureShadow_SetFieldBinaryFromHexString__SWIG_0(arg1,arg2,(char const *)arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
@@ -15008,7 +16150,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_SetFieldBinaryFromHexString__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   char *arg3 = (char *) 0 ;
@@ -15050,16 +16192,19 @@ SWIGINTERN PyObject *_wrap_Feature_SetFieldBinaryFromHexString__SWIG_1(PyObject
       CPLErrorReset();
     }
     OGRFeatureShadow_SetFieldBinaryFromHexString__SWIG_1(arg1,(char const *)arg2,(char const *)arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -15073,9 +16218,9 @@ SWIGINTERN PyObject *_wrap_Feature_SetFieldBinaryFromHexString(PyObject *self, P
   PyObject *argv[4];
   int ii;
   
-  if (!PyTuple_Check(args)) SWIG_fail;
+  if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
   argc = (int)PyObject_Length(args);
-  for (ii = 0; (ii < argc) && (ii < 3); ii++) {
+  for (ii = 0; (ii < 3) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
   if (argc == 3) {
@@ -15116,16 +16261,16 @@ SWIGINTERN PyObject *_wrap_Feature_SetFieldBinaryFromHexString(PyObject *self, P
   }
   
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_SetFieldBinaryFromHexString'.\n"
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'Feature_SetFieldBinaryFromHexString'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    SetFieldBinaryFromHexString(OGRFeatureShadow *,int,char const *)\n"
-    "    SetFieldBinaryFromHexString(OGRFeatureShadow *,char const *,char const *)\n");
-  return NULL;
+    "    OGRFeatureShadow::SetFieldBinaryFromHexString(int,char const *)\n"
+    "    OGRFeatureShadow::SetFieldBinaryFromHexString(char const *,char const *)\n");
+  return 0;
 }
 
 
 SWIGINTERN PyObject *_wrap_Feature_SetFrom(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
   int arg3 = (int) 1 ;
@@ -15171,12 +16316,14 @@ SWIGINTERN PyObject *_wrap_Feature_SetFrom(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     result = (OGRErr)OGRFeatureShadow_SetFrom(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -15187,14 +16334,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetFrom(PyObject *SWIGUNUSEDPARM(self), PyObj
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -15202,7 +16346,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_SetFromWithMap(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
   int arg3 ;
@@ -15243,7 +16387,12 @@ SWIGINTERN PyObject *_wrap_Feature_SetFromWithMap(PyObject *SWIGUNUSEDPARM(self)
       PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
-    arg4 = PySequence_Size(obj3);
+    Py_ssize_t size = PySequence_Size(obj3);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    arg4 = (int)size;
     arg5 = (int*) malloc(arg4*sizeof(int));
     for( int i = 0; i<arg4; i++ ) {
       PyObject *o = PySequence_GetItem(obj3,i);
@@ -15265,12 +16414,14 @@ SWIGINTERN PyObject *_wrap_Feature_SetFromWithMap(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (OGRErr)OGRFeatureShadow_SetFromWithMap(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -15287,14 +16438,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetFromWithMap(PyObject *SWIGUNUSEDPARM(self)
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -15308,7 +16456,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetStyleString(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -15326,14 +16474,17 @@ SWIGINTERN PyObject *_wrap_Feature_GetStyleString(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (char *)OGRFeatureShadow_GetStyleString(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -15341,7 +16492,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_SetStyleString(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -15368,15 +16519,18 @@ SWIGINTERN PyObject *_wrap_Feature_SetStyleString(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     OGRFeatureShadow_SetStyleString(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -15385,7 +16539,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetFieldType__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -15412,14 +16566,17 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldType__SWIG_0(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     result = (OGRFieldType)OGRFeatureShadow_GetFieldType__SWIG_0(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -15427,7 +16584,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetFieldType__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -15460,15 +16617,18 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldType__SWIG_1(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     result = (OGRFieldType)OGRFeatureShadow_GetFieldType__SWIG_1(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -15481,9 +16641,9 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldType(PyObject *self, PyObject *args)
   PyObject *argv[3];
   int ii;
   
-  if (!PyTuple_Check(args)) SWIG_fail;
+  if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
   argc = (int)PyObject_Length(args);
-  for (ii = 0; (ii < argc) && (ii < 2); ii++) {
+  for (ii = 0; (ii < 2) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
   if (argc == 2) {
@@ -15516,16 +16676,16 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldType(PyObject *self, PyObject *args)
   }
   
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'Feature_GetFieldType'.\n"
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'Feature_GetFieldType'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    GetFieldType(OGRFeatureShadow *,int)\n"
-    "    GetFieldType(OGRFeatureShadow *,char const *)\n");
-  return NULL;
+    "    OGRFeatureShadow::GetFieldType(int)\n"
+    "    OGRFeatureShadow::GetFieldType(char const *)\n");
+  return 0;
 }
 
 
 SWIGINTERN PyObject *_wrap_Feature_Validate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 = (int) OGR_F_VAL_ALL ;
   int arg3 = (int) TRUE ;
@@ -15565,14 +16725,17 @@ SWIGINTERN PyObject *_wrap_Feature_Validate(PyObject *SWIGUNUSEDPARM(self), PyOb
       CPLErrorReset();
     }
     result = (int)OGRFeatureShadow_Validate(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -15580,7 +16743,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_FillUnsetWithDefault(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 = (int) FALSE ;
   char **arg3 = (char **) NULL ;
@@ -15618,8 +16781,12 @@ SWIGINTERN PyObject *_wrap_Feature_FillUnsetWithDefault(PyObject *SWIGUNUSEDPARM
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj2);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj2);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj2,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -15656,18 +16823,21 @@ SWIGINTERN PyObject *_wrap_Feature_FillUnsetWithDefault(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     OGRFeatureShadow_FillUnsetWithDefault(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
     /* %typemap(freearg) char **options */
     CSLDestroy( arg3 );
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -15678,8 +16848,174 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_Feature_GetNativeData(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  char *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:Feature_GetNativeData",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetNativeData" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (char *)OGRFeatureShadow_GetNativeData(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_GetNativeMediaType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  char *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:Feature_GetNativeMediaType",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetNativeMediaType" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (char *)OGRFeatureShadow_GetNativeMediaType(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_SetNativeData(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_SetNativeData",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetNativeData" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetNativeData" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRFeatureShadow_SetNativeData(arg1,(char const *)arg2);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_Py_Void();
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_SetNativeMediaType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_SetNativeMediaType",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetNativeMediaType" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetNativeMediaType" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRFeatureShadow_SetNativeMediaType(arg1,(char const *)arg2);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_Py_Void();
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_Feature_SetFieldString(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
   char *arg3 = (char *) 0 ;
@@ -15717,18 +17053,21 @@ SWIGINTERN PyObject *_wrap_Feature_SetFieldString(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     OGRFeatureShadow_SetFieldString(arg1,arg2,(char const *)arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
     /* %typemap(freearg) (const char *utf8_path) */
     GDALPythonFreeCStr(arg3, bToFree3);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -15747,7 +17086,7 @@ SWIGINTERN PyObject *Feature_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObje
 }
 
 SWIGINTERN PyObject *_wrap_delete_FeatureDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -15764,14 +17103,17 @@ SWIGINTERN PyObject *_wrap_delete_FeatureDefn(PyObject *SWIGUNUSEDPARM(self), Py
       CPLErrorReset();
     }
     delete_OGRFeatureDefnShadow(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -15779,7 +17121,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_new_FeatureDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) NULL ;
   int res1 ;
   char *buf1 = 0 ;
@@ -15803,15 +17145,18 @@ SWIGINTERN PyObject *_wrap_new_FeatureDefn(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     result = (OGRFeatureDefnShadow *)new_OGRFeatureDefnShadow((char const *)arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureDefnShadow, SWIG_POINTER_NEW |  0 );
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
@@ -15820,7 +17165,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FeatureDefn_GetName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -15838,14 +17183,17 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_GetName(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     result = (char *)OGRFeatureDefnShadow_GetName(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -15853,7 +17201,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FeatureDefn_GetFieldCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -15871,14 +17219,17 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_GetFieldCount(PyObject *SWIGUNUSEDPARM(se
       CPLErrorReset();
     }
     result = (int)OGRFeatureDefnShadow_GetFieldCount(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -15886,7 +17237,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FeatureDefn_GetFieldDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -15913,14 +17264,17 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_GetFieldDefn(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     result = (OGRFieldDefnShadow *)OGRFeatureDefnShadow_GetFieldDefn(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFieldDefnShadow, 0 |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -15928,7 +17282,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FeatureDefn_GetFieldIndex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -15961,15 +17315,18 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_GetFieldIndex(PyObject *SWIGUNUSEDPARM(se
       CPLErrorReset();
     }
     result = (int)OGRFeatureDefnShadow_GetFieldIndex(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -15978,7 +17335,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FeatureDefn_AddFieldDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   OGRFieldDefnShadow *arg2 = (OGRFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
@@ -16009,14 +17366,17 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_AddFieldDefn(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     OGRFeatureDefnShadow_AddFieldDefn(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16024,7 +17384,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FeatureDefn_GetGeomFieldCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -16042,14 +17402,17 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_GetGeomFieldCount(PyObject *SWIGUNUSEDPAR
       CPLErrorReset();
     }
     result = (int)OGRFeatureDefnShadow_GetGeomFieldCount(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16057,7 +17420,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FeatureDefn_GetGeomFieldDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -16084,14 +17447,17 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_GetGeomFieldDefn(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     result = (OGRGeomFieldDefnShadow *)OGRFeatureDefnShadow_GetGeomFieldDefn(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16099,7 +17465,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FeatureDefn_GetGeomFieldIndex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -16132,15 +17498,18 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_GetGeomFieldIndex(PyObject *SWIGUNUSEDPAR
       CPLErrorReset();
     }
     result = (int)OGRFeatureDefnShadow_GetGeomFieldIndex(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -16149,7 +17518,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FeatureDefn_AddGeomFieldDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   OGRGeomFieldDefnShadow *arg2 = (OGRGeomFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
@@ -16180,14 +17549,17 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_AddGeomFieldDefn(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     OGRFeatureDefnShadow_AddGeomFieldDefn(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16195,7 +17567,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FeatureDefn_DeleteGeomFieldDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -16222,12 +17594,14 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_DeleteGeomFieldDefn(PyObject *SWIGUNUSEDP
       CPLErrorReset();
     }
     result = (OGRErr)OGRFeatureDefnShadow_DeleteGeomFieldDefn(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -16238,14 +17612,11 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_DeleteGeomFieldDefn(PyObject *SWIGUNUSEDP
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16253,7 +17624,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FeatureDefn_GetGeomType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -16271,14 +17642,17 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_GetGeomType(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     result = (OGRwkbGeometryType)OGRFeatureDefnShadow_GetGeomType(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16286,7 +17660,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FeatureDefn_SetGeomType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   OGRwkbGeometryType arg2 ;
   void *argp1 = 0 ;
@@ -16312,14 +17686,17 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_SetGeomType(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     OGRFeatureDefnShadow_SetGeomType(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16327,7 +17704,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FeatureDefn_GetReferenceCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -16345,14 +17722,17 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_GetReferenceCount(PyObject *SWIGUNUSEDPAR
       CPLErrorReset();
     }
     result = (int)OGRFeatureDefnShadow_GetReferenceCount(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16360,7 +17740,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FeatureDefn_IsGeometryIgnored(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -16378,14 +17758,17 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_IsGeometryIgnored(PyObject *SWIGUNUSEDPAR
       CPLErrorReset();
     }
     result = (int)OGRFeatureDefnShadow_IsGeometryIgnored(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16393,7 +17776,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FeatureDefn_SetGeometryIgnored(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -16419,14 +17802,17 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_SetGeometryIgnored(PyObject *SWIGUNUSEDPA
       CPLErrorReset();
     }
     OGRFeatureDefnShadow_SetGeometryIgnored(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16434,7 +17820,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FeatureDefn_IsStyleIgnored(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -16452,14 +17838,17 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_IsStyleIgnored(PyObject *SWIGUNUSEDPARM(s
       CPLErrorReset();
     }
     result = (int)OGRFeatureDefnShadow_IsStyleIgnored(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16467,7 +17856,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FeatureDefn_SetStyleIgnored(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -16493,14 +17882,17 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_SetStyleIgnored(PyObject *SWIGUNUSEDPARM(
       CPLErrorReset();
     }
     OGRFeatureDefnShadow_SetStyleIgnored(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16508,7 +17900,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FeatureDefn_IsSame(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
   OGRFeatureDefnShadow *arg2 = (OGRFeatureDefnShadow *) 0 ;
   void *argp1 = 0 ;
@@ -16540,14 +17932,17 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_IsSame(PyObject *SWIGUNUSEDPARM(self), Py
       CPLErrorReset();
     }
     result = (int)OGRFeatureDefnShadow_IsSame(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16562,7 +17957,7 @@ SWIGINTERN PyObject *FeatureDefn_swigregister(PyObject *SWIGUNUSEDPARM(self), Py
 }
 
 SWIGINTERN PyObject *_wrap_delete_FieldDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -16579,14 +17974,17 @@ SWIGINTERN PyObject *_wrap_delete_FieldDefn(PyObject *SWIGUNUSEDPARM(self), PyOb
       CPLErrorReset();
     }
     delete_OGRFieldDefnShadow(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16594,7 +17992,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_new_FieldDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) "unnamed" ;
   OGRFieldType arg2 = (OGRFieldType) OFTString ;
   int res1 ;
@@ -16629,15 +18027,18 @@ SWIGINTERN PyObject *_wrap_new_FieldDefn(PyObject *SWIGUNUSEDPARM(self), PyObjec
       CPLErrorReset();
     }
     result = (OGRFieldDefnShadow *)new_OGRFieldDefnShadow((char const *)arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFieldDefnShadow, SWIG_POINTER_NEW |  0 );
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
@@ -16646,7 +18047,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FieldDefn_GetName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -16664,14 +18065,17 @@ SWIGINTERN PyObject *_wrap_FieldDefn_GetName(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (char *)OGRFieldDefnShadow_GetName(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16679,7 +18083,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FieldDefn_GetNameRef(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -16697,14 +18101,17 @@ SWIGINTERN PyObject *_wrap_FieldDefn_GetNameRef(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (char *)OGRFieldDefnShadow_GetNameRef(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16712,7 +18119,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FieldDefn_SetName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -16744,15 +18151,18 @@ SWIGINTERN PyObject *_wrap_FieldDefn_SetName(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     OGRFieldDefnShadow_SetName(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -16761,7 +18171,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FieldDefn_GetType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -16779,14 +18189,17 @@ SWIGINTERN PyObject *_wrap_FieldDefn_GetType(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (OGRFieldType)OGRFieldDefnShadow_GetType(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16794,7 +18207,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FieldDefn_SetType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   OGRFieldType arg2 ;
   void *argp1 = 0 ;
@@ -16820,14 +18233,17 @@ SWIGINTERN PyObject *_wrap_FieldDefn_SetType(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     OGRFieldDefnShadow_SetType(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16835,7 +18251,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FieldDefn_GetSubType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -16853,14 +18269,17 @@ SWIGINTERN PyObject *_wrap_FieldDefn_GetSubType(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (OGRFieldSubType)OGRFieldDefnShadow_GetSubType(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16868,7 +18287,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FieldDefn_SetSubType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   OGRFieldSubType arg2 ;
   void *argp1 = 0 ;
@@ -16894,14 +18313,17 @@ SWIGINTERN PyObject *_wrap_FieldDefn_SetSubType(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     OGRFieldDefnShadow_SetSubType(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16909,7 +18331,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FieldDefn_GetJustify(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -16927,14 +18349,17 @@ SWIGINTERN PyObject *_wrap_FieldDefn_GetJustify(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (OGRJustification)OGRFieldDefnShadow_GetJustify(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16942,7 +18367,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FieldDefn_SetJustify(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   OGRJustification arg2 ;
   void *argp1 = 0 ;
@@ -16968,14 +18393,17 @@ SWIGINTERN PyObject *_wrap_FieldDefn_SetJustify(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     OGRFieldDefnShadow_SetJustify(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -16983,7 +18411,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FieldDefn_GetWidth(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -17001,14 +18429,17 @@ SWIGINTERN PyObject *_wrap_FieldDefn_GetWidth(PyObject *SWIGUNUSEDPARM(self), Py
       CPLErrorReset();
     }
     result = (int)OGRFieldDefnShadow_GetWidth(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -17016,7 +18447,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FieldDefn_SetWidth(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -17042,14 +18473,17 @@ SWIGINTERN PyObject *_wrap_FieldDefn_SetWidth(PyObject *SWIGUNUSEDPARM(self), Py
       CPLErrorReset();
     }
     OGRFieldDefnShadow_SetWidth(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -17057,7 +18491,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FieldDefn_GetPrecision(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -17075,14 +18509,17 @@ SWIGINTERN PyObject *_wrap_FieldDefn_GetPrecision(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (int)OGRFieldDefnShadow_GetPrecision(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -17090,7 +18527,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FieldDefn_SetPrecision(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -17116,14 +18553,17 @@ SWIGINTERN PyObject *_wrap_FieldDefn_SetPrecision(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     OGRFieldDefnShadow_SetPrecision(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -17131,7 +18571,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FieldDefn_GetTypeName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -17149,14 +18589,17 @@ SWIGINTERN PyObject *_wrap_FieldDefn_GetTypeName(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (char *)OGRFieldDefnShadow_GetTypeName(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -17164,7 +18607,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FieldDefn_GetFieldTypeName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   OGRFieldType arg2 ;
   void *argp1 = 0 ;
@@ -17191,14 +18634,17 @@ SWIGINTERN PyObject *_wrap_FieldDefn_GetFieldTypeName(PyObject *SWIGUNUSEDPARM(s
       CPLErrorReset();
     }
     result = (char *)OGRFieldDefnShadow_GetFieldTypeName(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -17206,7 +18652,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FieldDefn_IsIgnored(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -17224,14 +18670,17 @@ SWIGINTERN PyObject *_wrap_FieldDefn_IsIgnored(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     result = (int)OGRFieldDefnShadow_IsIgnored(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -17239,7 +18688,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FieldDefn_SetIgnored(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -17265,14 +18714,17 @@ SWIGINTERN PyObject *_wrap_FieldDefn_SetIgnored(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     OGRFieldDefnShadow_SetIgnored(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -17280,7 +18732,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FieldDefn_IsNullable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -17298,14 +18750,17 @@ SWIGINTERN PyObject *_wrap_FieldDefn_IsNullable(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (int)OGRFieldDefnShadow_IsNullable(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -17313,7 +18768,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FieldDefn_SetNullable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -17339,14 +18794,17 @@ SWIGINTERN PyObject *_wrap_FieldDefn_SetNullable(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     OGRFieldDefnShadow_SetNullable(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -17354,7 +18812,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FieldDefn_GetDefault(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -17372,14 +18830,17 @@ SWIGINTERN PyObject *_wrap_FieldDefn_GetDefault(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (char *)OGRFieldDefnShadow_GetDefault(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -17387,7 +18848,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FieldDefn_SetDefault(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -17414,15 +18875,18 @@ SWIGINTERN PyObject *_wrap_FieldDefn_SetDefault(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     OGRFieldDefnShadow_SetDefault(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -17431,7 +18895,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_FieldDefn_IsDefaultDriverSpecific(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -17449,14 +18913,17 @@ SWIGINTERN PyObject *_wrap_FieldDefn_IsDefaultDriverSpecific(PyObject *SWIGUNUSE
       CPLErrorReset();
     }
     result = (int)OGRFieldDefnShadow_IsDefaultDriverSpecific(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -17471,7 +18938,7 @@ SWIGINTERN PyObject *FieldDefn_swigregister(PyObject *SWIGUNUSEDPARM(self), PyOb
 }
 
 SWIGINTERN PyObject *_wrap_delete_GeomFieldDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -17488,14 +18955,17 @@ SWIGINTERN PyObject *_wrap_delete_GeomFieldDefn(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     delete_OGRGeomFieldDefnShadow(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -17503,7 +18973,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_new_GeomFieldDefn(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) "" ;
   OGRwkbGeometryType arg2 = (OGRwkbGeometryType) wkbUnknown ;
   int res1 ;
@@ -17538,15 +19008,18 @@ SWIGINTERN PyObject *_wrap_new_GeomFieldDefn(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (OGRGeomFieldDefnShadow *)new_OGRGeomFieldDefnShadow((char const *)arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeomFieldDefnShadow, SWIG_POINTER_NEW |  0 );
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
@@ -17555,7 +19028,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GeomFieldDefn_GetName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -17573,14 +19046,17 @@ SWIGINTERN PyObject *_wrap_GeomFieldDefn_GetName(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (char *)OGRGeomFieldDefnShadow_GetName(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -17588,7 +19064,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GeomFieldDefn_GetNameRef(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -17606,14 +19082,17 @@ SWIGINTERN PyObject *_wrap_GeomFieldDefn_GetNameRef(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     result = (char *)OGRGeomFieldDefnShadow_GetNameRef(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -17621,7 +19100,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GeomFieldDefn_SetName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -17653,15 +19132,18 @@ SWIGINTERN PyObject *_wrap_GeomFieldDefn_SetName(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     OGRGeomFieldDefnShadow_SetName(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -17670,7 +19152,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GeomFieldDefn_GetType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -17688,14 +19170,17 @@ SWIGINTERN PyObject *_wrap_GeomFieldDefn_GetType(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (OGRwkbGeometryType)OGRGeomFieldDefnShadow_GetType(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -17703,7 +19188,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GeomFieldDefn_SetType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
   OGRwkbGeometryType arg2 ;
   void *argp1 = 0 ;
@@ -17729,14 +19214,17 @@ SWIGINTERN PyObject *_wrap_GeomFieldDefn_SetType(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     OGRGeomFieldDefnShadow_SetType(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -17744,7 +19232,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GeomFieldDefn_GetSpatialRef(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -17762,14 +19250,17 @@ SWIGINTERN PyObject *_wrap_GeomFieldDefn_GetSpatialRef(PyObject *SWIGUNUSEDPARM(
       CPLErrorReset();
     }
     result = (OSRSpatialReferenceShadow *)OGRGeomFieldDefnShadow_GetSpatialRef(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OSRSpatialReferenceShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -17777,7 +19268,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GeomFieldDefn_SetSpatialRef(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
   OSRSpatialReferenceShadow *arg2 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
@@ -17803,14 +19294,17 @@ SWIGINTERN PyObject *_wrap_GeomFieldDefn_SetSpatialRef(PyObject *SWIGUNUSEDPARM(
       CPLErrorReset();
     }
     OGRGeomFieldDefnShadow_SetSpatialRef(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -17818,7 +19312,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GeomFieldDefn_IsIgnored(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -17836,14 +19330,17 @@ SWIGINTERN PyObject *_wrap_GeomFieldDefn_IsIgnored(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     result = (int)OGRGeomFieldDefnShadow_IsIgnored(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -17851,7 +19348,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GeomFieldDefn_SetIgnored(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -17877,14 +19374,17 @@ SWIGINTERN PyObject *_wrap_GeomFieldDefn_SetIgnored(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     OGRGeomFieldDefnShadow_SetIgnored(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -17892,7 +19392,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GeomFieldDefn_IsNullable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -17910,14 +19410,17 @@ SWIGINTERN PyObject *_wrap_GeomFieldDefn_IsNullable(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     result = (int)OGRGeomFieldDefnShadow_IsNullable(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -17925,7 +19428,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GeomFieldDefn_SetNullable(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeomFieldDefnShadow *arg1 = (OGRGeomFieldDefnShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -17951,14 +19454,17 @@ SWIGINTERN PyObject *_wrap_GeomFieldDefn_SetNullable(PyObject *SWIGUNUSEDPARM(se
       CPLErrorReset();
     }
     OGRGeomFieldDefnShadow_SetNullable(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -17973,7 +19479,7 @@ SWIGINTERN PyObject *GeomFieldDefn_swigregister(PyObject *SWIGUNUSEDPARM(self),
 }
 
 SWIGINTERN PyObject *_wrap_CreateGeometryFromWkb(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   int arg1 ;
   char *arg2 = (char *) 0 ;
   OSRSpatialReferenceShadow *arg3 = (OSRSpatialReferenceShadow *) NULL ;
@@ -18039,25 +19545,28 @@ SWIGINTERN PyObject *_wrap_CreateGeometryFromWkb(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)CreateGeometryFromWkb(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
   {
     /* %typemap(freearg) (int *nLen, char *pBuf ) */
-    if( alloc1 == SWIG_NEWOBJ ) {
+    if (ReturnSame(alloc1) == SWIG_NEWOBJ ) {
       delete[] arg2;
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
     /* %typemap(freearg) (int *nLen, char *pBuf ) */
-    if( alloc1 == SWIG_NEWOBJ ) {
+    if (ReturnSame(alloc1) == SWIG_NEWOBJ ) {
       delete[] arg2;
     }
   }
@@ -18066,7 +19575,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_CreateGeometryFromWkt(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char **arg1 = (char **) 0 ;
   OSRSpatialReferenceShadow *arg2 = (OSRSpatialReferenceShadow *) NULL ;
   char *val1 ;
@@ -18100,14 +19609,17 @@ SWIGINTERN PyObject *_wrap_CreateGeometryFromWkt(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)CreateGeometryFromWkt(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -18115,7 +19627,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_CreateGeometryFromGML(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   int res1 ;
   char *buf1 = 0 ;
@@ -18134,15 +19646,18 @@ SWIGINTERN PyObject *_wrap_CreateGeometryFromGML(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)CreateGeometryFromGML((char const *)arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
@@ -18151,7 +19666,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_CreateGeometryFromJson(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   int res1 ;
   char *buf1 = 0 ;
@@ -18170,15 +19685,18 @@ SWIGINTERN PyObject *_wrap_CreateGeometryFromJson(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)CreateGeometryFromJson((char const *)arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
@@ -18187,7 +19705,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_BuildPolygonFromEdges(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   int arg2 = (int) 0 ;
   int arg3 = (int) 0 ;
@@ -18241,14 +19759,17 @@ SWIGINTERN PyObject *_wrap_BuildPolygonFromEdges(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)BuildPolygonFromEdges(arg1,arg2,arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -18256,7 +19777,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_ApproximateArcAngles(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   double arg1 ;
   double arg2 ;
   double arg3 ;
@@ -18349,14 +19870,17 @@ SWIGINTERN PyObject *_wrap_ApproximateArcAngles(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)ApproximateArcAngles(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -18364,7 +19888,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_ForceToPolygon(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -18382,14 +19906,17 @@ SWIGINTERN PyObject *_wrap_ForceToPolygon(PyObject *SWIGUNUSEDPARM(self), PyObje
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)ForceToPolygon(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -18397,7 +19924,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_ForceToLineString(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -18415,14 +19942,17 @@ SWIGINTERN PyObject *_wrap_ForceToLineString(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)ForceToLineString(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -18430,7 +19960,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_ForceToMultiPolygon(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -18448,14 +19978,17 @@ SWIGINTERN PyObject *_wrap_ForceToMultiPolygon(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)ForceToMultiPolygon(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -18463,7 +19996,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_ForceToMultiPoint(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -18481,14 +20014,17 @@ SWIGINTERN PyObject *_wrap_ForceToMultiPoint(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)ForceToMultiPoint(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -18496,7 +20032,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_ForceToMultiLineString(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -18514,14 +20050,17 @@ SWIGINTERN PyObject *_wrap_ForceToMultiLineString(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)ForceToMultiLineString(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -18529,7 +20068,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_ForceTo(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   OGRwkbGeometryType arg2 ;
   char **arg3 = (char **) NULL ;
@@ -18566,8 +20105,12 @@ SWIGINTERN PyObject *_wrap_ForceTo(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj2);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj2);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj2,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -18604,18 +20147,21 @@ SWIGINTERN PyObject *_wrap_ForceTo(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)ForceTo(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
   {
     /* %typemap(freearg) char **options */
     CSLDestroy( arg3 );
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -18627,7 +20173,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_delete_Geometry(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -18644,14 +20190,17 @@ SWIGINTERN PyObject *_wrap_delete_Geometry(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     delete_OGRGeometryShadow(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -18659,7 +20208,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_new_Geometry(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRwkbGeometryType arg1 = (OGRwkbGeometryType) wkbUnknown ;
   char *arg2 = (char *) 0 ;
   int arg3 = (int) 0 ;
@@ -18751,28 +20300,31 @@ SWIGINTERN PyObject *_wrap_new_Geometry(PyObject *SWIGUNUSEDPARM(self), PyObject
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)new_OGRGeometryShadow(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_NEW |  0 );
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   {
     /* %typemap(freearg) (int *nLen, char *pBuf ) */
-    if( alloc3 == SWIG_NEWOBJ ) {
+    if (ReturnSame(alloc3) == SWIG_NEWOBJ ) {
       delete[] arg4;
     }
   }
   if (alloc5 == SWIG_NEWOBJ) delete[] buf5;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   {
     /* %typemap(freearg) (int *nLen, char *pBuf ) */
-    if( alloc3 == SWIG_NEWOBJ ) {
+    if (ReturnSame(alloc3) == SWIG_NEWOBJ ) {
       delete[] arg4;
     }
   }
@@ -18782,7 +20334,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_ExportToWkt(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   char **arg2 = (char **) 0 ;
   void *argp1 = 0 ;
@@ -18806,12 +20358,14 @@ SWIGINTERN PyObject *_wrap_Geometry_ExportToWkt(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (OGRErr)OGRGeometryShadow_ExportToWkt(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -18823,7 +20377,7 @@ SWIGINTERN PyObject *_wrap_Geometry_ExportToWkt(PyObject *SWIGUNUSEDPARM(self),
   {
     /* %typemap(argout) (char **argout) */
     PyObject *o;
-    if ( arg2 != NULL && *arg2 != NULL) {
+    if ( ReturnSame(arg2) != NULL && *arg2 != NULL ) {
       o = GDALPythonObjectFromCStr( *arg2 );
     }
     else {
@@ -18839,14 +20393,11 @@ SWIGINTERN PyObject *_wrap_Geometry_ExportToWkt(PyObject *SWIGUNUSEDPARM(self),
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -18859,7 +20410,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_ExportToIsoWkt(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   char **arg2 = (char **) 0 ;
   void *argp1 = 0 ;
@@ -18883,12 +20434,14 @@ SWIGINTERN PyObject *_wrap_Geometry_ExportToIsoWkt(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     result = (OGRErr)OGRGeometryShadow_ExportToIsoWkt(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -18900,7 +20453,7 @@ SWIGINTERN PyObject *_wrap_Geometry_ExportToIsoWkt(PyObject *SWIGUNUSEDPARM(self
   {
     /* %typemap(argout) (char **argout) */
     PyObject *o;
-    if ( arg2 != NULL && *arg2 != NULL) {
+    if ( ReturnSame(arg2) != NULL && *arg2 != NULL ) {
       o = GDALPythonObjectFromCStr( *arg2 );
     }
     else {
@@ -18916,14 +20469,11 @@ SWIGINTERN PyObject *_wrap_Geometry_ExportToIsoWkt(PyObject *SWIGUNUSEDPARM(self
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -18936,7 +20486,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_ExportToWkb(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   int *arg2 = (int *) 0 ;
   char **arg3 = (char **) 0 ;
@@ -18977,12 +20527,14 @@ SWIGINTERN PyObject *_wrap_Geometry_ExportToWkb(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (OGRErr)OGRGeometryShadow_ExportToWkb(arg1,arg2,arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -19008,14 +20560,11 @@ SWIGINTERN PyObject *_wrap_Geometry_ExportToWkb(PyObject *SWIGUNUSEDPARM(self),
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -19029,7 +20578,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_ExportToIsoWkb(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   int *arg2 = (int *) 0 ;
   char **arg3 = (char **) 0 ;
@@ -19070,12 +20619,14 @@ SWIGINTERN PyObject *_wrap_Geometry_ExportToIsoWkb(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     result = (OGRErr)OGRGeometryShadow_ExportToIsoWkb(arg1,arg2,arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -19101,14 +20652,11 @@ SWIGINTERN PyObject *_wrap_Geometry_ExportToIsoWkb(PyObject *SWIGUNUSEDPARM(self
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -19122,7 +20670,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_ExportToGML(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   char **arg2 = (char **) 0 ;
   void *argp1 = 0 ;
@@ -19153,8 +20701,12 @@ SWIGINTERN PyObject *_wrap_Geometry_ExportToGML(PyObject *SWIGUNUSEDPARM(self),
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj1);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj1);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj1,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -19191,12 +20743,14 @@ SWIGINTERN PyObject *_wrap_Geometry_ExportToGML(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (retStringAndCPLFree *)OGRGeometryShadow_ExportToGML(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) (retStringAndCPLFree*) */
@@ -19210,6 +20764,7 @@ SWIGINTERN PyObject *_wrap_Geometry_ExportToGML(PyObject *SWIGUNUSEDPARM(self),
     /* %typemap(freearg) char **options */
     CSLDestroy( arg2 );
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -19221,7 +20776,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_ExportToKML(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   char *arg2 = (char *) NULL ;
   void *argp1 = 0 ;
@@ -19251,12 +20806,14 @@ SWIGINTERN PyObject *_wrap_Geometry_ExportToKML(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (retStringAndCPLFree *)OGRGeometryShadow_ExportToKML(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) (retStringAndCPLFree*) */
@@ -19267,6 +20824,7 @@ SWIGINTERN PyObject *_wrap_Geometry_ExportToKML(PyObject *SWIGUNUSEDPARM(self),
     }
   }
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -19275,7 +20833,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_ExportToJson(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   char **arg2 = (char **) 0 ;
   void *argp1 = 0 ;
@@ -19306,8 +20864,12 @@ SWIGINTERN PyObject *_wrap_Geometry_ExportToJson(PyObject *SWIGUNUSEDPARM(self),
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj1);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj1);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj1,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -19344,12 +20906,14 @@ SWIGINTERN PyObject *_wrap_Geometry_ExportToJson(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (retStringAndCPLFree *)OGRGeometryShadow_ExportToJson(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) (retStringAndCPLFree*) */
@@ -19363,6 +20927,7 @@ SWIGINTERN PyObject *_wrap_Geometry_ExportToJson(PyObject *SWIGUNUSEDPARM(self),
     /* %typemap(freearg) char **options */
     CSLDestroy( arg2 );
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -19374,7 +20939,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_AddPoint(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -19423,14 +20988,156 @@ SWIGINTERN PyObject *_wrap_Geometry_AddPoint(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     OGRGeometryShadow_AddPoint(arg1,arg2,arg3,arg4);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Geometry_AddPointM(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  double arg2 ;
+  double arg3 ;
+  double arg4 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  double val2 ;
+  int ecode2 = 0 ;
+  double val3 ;
+  int ecode3 = 0 ;
+  double val4 ;
+  int ecode4 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "x",(char *) "y",(char *) "m", NULL 
+  };
+  
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOOO:Geometry_AddPointM",kwnames,&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_AddPointM" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
+  ecode2 = SWIG_AsVal_double(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_AddPointM" "', argument " "2"" of type '" "double""'");
+  } 
+  arg2 = static_cast< double >(val2);
+  ecode3 = SWIG_AsVal_double(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Geometry_AddPointM" "', argument " "3"" of type '" "double""'");
+  } 
+  arg3 = static_cast< double >(val3);
+  ecode4 = SWIG_AsVal_double(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Geometry_AddPointM" "', argument " "4"" of type '" "double""'");
+  } 
+  arg4 = static_cast< double >(val4);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRGeometryShadow_AddPointM(arg1,arg2,arg3,arg4);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Geometry_AddPointZM(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  double arg2 ;
+  double arg3 ;
+  double arg4 ;
+  double arg5 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  double val2 ;
+  int ecode2 = 0 ;
+  double val3 ;
+  int ecode3 = 0 ;
+  double val4 ;
+  int ecode4 = 0 ;
+  double val5 ;
+  int ecode5 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "x",(char *) "y",(char *) "z",(char *) "m", NULL 
+  };
+  
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOOOO:Geometry_AddPointZM",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_AddPointZM" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
+  ecode2 = SWIG_AsVal_double(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_AddPointZM" "', argument " "2"" of type '" "double""'");
+  } 
+  arg2 = static_cast< double >(val2);
+  ecode3 = SWIG_AsVal_double(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Geometry_AddPointZM" "', argument " "3"" of type '" "double""'");
+  } 
+  arg3 = static_cast< double >(val3);
+  ecode4 = SWIG_AsVal_double(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Geometry_AddPointZM" "', argument " "4"" of type '" "double""'");
+  } 
+  arg4 = static_cast< double >(val4);
+  ecode5 = SWIG_AsVal_double(obj4, &val5);
+  if (!SWIG_IsOK(ecode5)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Geometry_AddPointZM" "', argument " "5"" of type '" "double""'");
+  } 
+  arg5 = static_cast< double >(val5);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRGeometryShadow_AddPointZM(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -19438,7 +21145,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_AddPoint_2D(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -19473,14 +21180,17 @@ SWIGINTERN PyObject *_wrap_Geometry_AddPoint_2D(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     OGRGeometryShadow_AddPoint_2D(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -19488,7 +21198,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_AddGeometryDirectly(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
@@ -19518,12 +21228,14 @@ SWIGINTERN PyObject *_wrap_Geometry_AddGeometryDirectly(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     result = (OGRErr)OGRGeometryShadow_AddGeometryDirectly(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -19534,14 +21246,11 @@ SWIGINTERN PyObject *_wrap_Geometry_AddGeometryDirectly(PyObject *SWIGUNUSEDPARM
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -19549,7 +21258,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_AddGeometry(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
@@ -19581,12 +21290,14 @@ SWIGINTERN PyObject *_wrap_Geometry_AddGeometry(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (OGRErr)OGRGeometryShadow_AddGeometry(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -19597,14 +21308,11 @@ SWIGINTERN PyObject *_wrap_Geometry_AddGeometry(PyObject *SWIGUNUSEDPARM(self),
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -19612,7 +21320,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_Clone(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -19630,14 +21338,17 @@ SWIGINTERN PyObject *_wrap_Geometry_Clone(PyObject *SWIGUNUSEDPARM(self), PyObje
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)OGRGeometryShadow_Clone(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -19645,7 +21356,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_GetGeometryType(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -19663,14 +21374,17 @@ SWIGINTERN PyObject *_wrap_Geometry_GetGeometryType(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     result = (OGRwkbGeometryType)OGRGeometryShadow_GetGeometryType(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -19678,7 +21392,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_GetGeometryName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -19696,14 +21410,17 @@ SWIGINTERN PyObject *_wrap_Geometry_GetGeometryName(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     result = (char *)OGRGeometryShadow_GetGeometryName(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -19711,7 +21428,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_Length(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -19729,14 +21446,17 @@ SWIGINTERN PyObject *_wrap_Geometry_Length(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     result = (double)OGRGeometryShadow_Length(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_double(static_cast< double >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -19744,7 +21464,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_Area(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -19762,14 +21482,17 @@ SWIGINTERN PyObject *_wrap_Geometry_Area(PyObject *SWIGUNUSEDPARM(self), PyObjec
       CPLErrorReset();
     }
     result = (double)OGRGeometryShadow_Area(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_double(static_cast< double >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -19777,7 +21500,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_GetArea(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -19795,14 +21518,17 @@ SWIGINTERN PyObject *_wrap_Geometry_GetArea(PyObject *SWIGUNUSEDPARM(self), PyOb
       CPLErrorReset();
     }
     result = (double)OGRGeometryShadow_GetArea(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_double(static_cast< double >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -19810,7 +21536,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_GetPointCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -19828,14 +21554,17 @@ SWIGINTERN PyObject *_wrap_Geometry_GetPointCount(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (int)OGRGeometryShadow_GetPointCount(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -19843,7 +21572,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_GetPoints(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   int *arg2 = (int *) 0 ;
   double **arg3 = (double **) 0 ;
@@ -19886,12 +21615,14 @@ SWIGINTERN PyObject *_wrap_Geometry_GetPoints(PyObject *SWIGUNUSEDPARM(self), Py
       CPLErrorReset();
     }
     OGRGeometryShadow_GetPoints(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
@@ -19922,6 +21653,7 @@ SWIGINTERN PyObject *_wrap_Geometry_GetPoints(PyObject *SWIGUNUSEDPARM(self), Py
     VSIFree(*arg3);
     VSIFree(*arg4);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -19934,7 +21666,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_GetX(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   int arg2 = (int) 0 ;
   void *argp1 = 0 ;
@@ -19966,14 +21698,17 @@ SWIGINTERN PyObject *_wrap_Geometry_GetX(PyObject *SWIGUNUSEDPARM(self), PyObjec
       CPLErrorReset();
     }
     result = (double)OGRGeometryShadow_GetX(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_double(static_cast< double >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -19981,7 +21716,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_GetY(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   int arg2 = (int) 0 ;
   void *argp1 = 0 ;
@@ -20013,14 +21748,17 @@ SWIGINTERN PyObject *_wrap_Geometry_GetY(PyObject *SWIGUNUSEDPARM(self), PyObjec
       CPLErrorReset();
     }
     result = (double)OGRGeometryShadow_GetY(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_double(static_cast< double >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -20028,7 +21766,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_GetZ(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   int arg2 = (int) 0 ;
   void *argp1 = 0 ;
@@ -20060,14 +21798,67 @@ SWIGINTERN PyObject *_wrap_Geometry_GetZ(PyObject *SWIGUNUSEDPARM(self), PyObjec
       CPLErrorReset();
     }
     result = (double)OGRGeometryShadow_GetZ(arg1,arg2);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_double(static_cast< double >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Geometry_GetM(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  int arg2 = (int) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "point", NULL 
+  };
+  double result;
+  
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"O|O:Geometry_GetM",kwnames,&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_GetM" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
+  if (obj1) {
+    ecode2 = SWIG_AsVal_int(obj1, &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_GetM" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (double)OGRGeometryShadow_GetM(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_double(static_cast< double >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -20075,7 +21866,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_GetPoint(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   int arg2 = (int) 0 ;
   double *arg3 = (double *) (double *)NULL ;
@@ -20089,6 +21880,7 @@ SWIGINTERN PyObject *_wrap_Geometry_GetPoint(PyObject *SWIGUNUSEDPARM(self), PyO
   
   {
     /* %typemap(in,numinputs=0) (double argout3[ANY]) */
+    memset(argout3, 0, sizeof(argout3));
     arg3 = argout3;
   }
   if (!PyArg_ParseTuple(args,(char *)"O|O:Geometry_GetPoint",&obj0,&obj1)) SWIG_fail;
@@ -20109,12 +21901,14 @@ SWIGINTERN PyObject *_wrap_Geometry_GetPoint(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     OGRGeometryShadow_GetPoint(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
@@ -20122,6 +21916,65 @@ SWIGINTERN PyObject *_wrap_Geometry_GetPoint(PyObject *SWIGUNUSEDPARM(self), PyO
     PyObject *out = CreateTupleFromDoubleArray( arg3, 3 );
     resultobj = t_output_helper(resultobj,out);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Geometry_GetPointZM(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  int arg2 = (int) 0 ;
+  double *arg3 = (double *) (double *)NULL ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  double argout3[4] ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  {
+    /* %typemap(in,numinputs=0) (double argout3[ANY]) */
+    memset(argout3, 0, sizeof(argout3));
+    arg3 = argout3;
+  }
+  if (!PyArg_ParseTuple(args,(char *)"O|O:Geometry_GetPointZM",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_GetPointZM" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
+  if (obj1) {
+    ecode2 = SWIG_AsVal_int(obj1, &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_GetPointZM" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRGeometryShadow_GetPointZM(arg1,arg2,arg3);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_Py_Void();
+  {
+    /* %typemap(argout) (double argout[ANY]) */
+    PyObject *out = CreateTupleFromDoubleArray( arg3, 4 );
+    resultobj = t_output_helper(resultobj,out);
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -20129,7 +21982,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_GetPoint_2D(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   int arg2 = (int) 0 ;
   double *arg3 = (double *) (double *)NULL ;
@@ -20143,6 +21996,7 @@ SWIGINTERN PyObject *_wrap_Geometry_GetPoint_2D(PyObject *SWIGUNUSEDPARM(self),
   
   {
     /* %typemap(in,numinputs=0) (double argout3[ANY]) */
+    memset(argout3, 0, sizeof(argout3));
     arg3 = argout3;
   }
   if (!PyArg_ParseTuple(args,(char *)"O|O:Geometry_GetPoint_2D",&obj0,&obj1)) SWIG_fail;
@@ -20163,12 +22017,14 @@ SWIGINTERN PyObject *_wrap_Geometry_GetPoint_2D(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     OGRGeometryShadow_GetPoint_2D(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
@@ -20176,6 +22032,7 @@ SWIGINTERN PyObject *_wrap_Geometry_GetPoint_2D(PyObject *SWIGUNUSEDPARM(self),
     PyObject *out = CreateTupleFromDoubleArray( arg3, 2 );
     resultobj = t_output_helper(resultobj,out);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -20183,7 +22040,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_GetGeometryCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -20201,14 +22058,17 @@ SWIGINTERN PyObject *_wrap_Geometry_GetGeometryCount(PyObject *SWIGUNUSEDPARM(se
       CPLErrorReset();
     }
     result = (int)OGRGeometryShadow_GetGeometryCount(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -20216,7 +22076,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_SetPoint(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   int arg2 ;
   double arg3 ;
@@ -20274,26 +22134,30 @@ SWIGINTERN PyObject *_wrap_Geometry_SetPoint(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     OGRGeometryShadow_SetPoint(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Geometry_SetPoint_2D(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+SWIGINTERN PyObject *_wrap_Geometry_SetPointM(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   int arg2 ;
   double arg3 ;
   double arg4 ;
+  double arg5 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   int val2 ;
@@ -20302,48 +22166,207 @@ SWIGINTERN PyObject *_wrap_Geometry_SetPoint_2D(PyObject *SWIGUNUSEDPARM(self),
   int ecode3 = 0 ;
   double val4 ;
   int ecode4 = 0 ;
+  double val5 ;
+  int ecode5 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   PyObject * obj2 = 0 ;
   PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
   char *  kwnames[] = {
-    (char *) "self",(char *) "point",(char *) "x",(char *) "y", NULL 
+    (char *) "self",(char *) "point",(char *) "x",(char *) "y",(char *) "m", NULL 
   };
   
-  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOOO:Geometry_SetPoint_2D",kwnames,&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOOOO:Geometry_SetPointM",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_SetPoint_2D" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_SetPointM" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_SetPoint_2D" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_SetPointM" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
   ecode3 = SWIG_AsVal_double(obj2, &val3);
   if (!SWIG_IsOK(ecode3)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Geometry_SetPoint_2D" "', argument " "3"" of type '" "double""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Geometry_SetPointM" "', argument " "3"" of type '" "double""'");
   } 
   arg3 = static_cast< double >(val3);
   ecode4 = SWIG_AsVal_double(obj3, &val4);
   if (!SWIG_IsOK(ecode4)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Geometry_SetPoint_2D" "', argument " "4"" of type '" "double""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Geometry_SetPointM" "', argument " "4"" of type '" "double""'");
   } 
   arg4 = static_cast< double >(val4);
-  {
-    if ( bUseExceptions ) {
+  ecode5 = SWIG_AsVal_double(obj4, &val5);
+  if (!SWIG_IsOK(ecode5)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Geometry_SetPointM" "', argument " "5"" of type '" "double""'");
+  } 
+  arg5 = static_cast< double >(val5);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRGeometryShadow_SetPointM(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Geometry_SetPointZM(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  int arg2 ;
+  double arg3 ;
+  double arg4 ;
+  double arg5 ;
+  double arg6 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  double val3 ;
+  int ecode3 = 0 ;
+  double val4 ;
+  int ecode4 = 0 ;
+  double val5 ;
+  int ecode5 = 0 ;
+  double val6 ;
+  int ecode6 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "point",(char *) "x",(char *) "y",(char *) "z",(char *) "m", NULL 
+  };
+  
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOOOOO:Geometry_SetPointZM",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_SetPointZM" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_SetPointZM" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  ecode3 = SWIG_AsVal_double(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Geometry_SetPointZM" "', argument " "3"" of type '" "double""'");
+  } 
+  arg3 = static_cast< double >(val3);
+  ecode4 = SWIG_AsVal_double(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Geometry_SetPointZM" "', argument " "4"" of type '" "double""'");
+  } 
+  arg4 = static_cast< double >(val4);
+  ecode5 = SWIG_AsVal_double(obj4, &val5);
+  if (!SWIG_IsOK(ecode5)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Geometry_SetPointZM" "', argument " "5"" of type '" "double""'");
+  } 
+  arg5 = static_cast< double >(val5);
+  ecode6 = SWIG_AsVal_double(obj5, &val6);
+  if (!SWIG_IsOK(ecode6)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "Geometry_SetPointZM" "', argument " "6"" of type '" "double""'");
+  } 
+  arg6 = static_cast< double >(val6);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRGeometryShadow_SetPointZM(arg1,arg2,arg3,arg4,arg5,arg6);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Geometry_SetPoint_2D(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  int arg2 ;
+  double arg3 ;
+  double arg4 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  double val3 ;
+  int ecode3 = 0 ;
+  double val4 ;
+  int ecode4 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "point",(char *) "x",(char *) "y", NULL 
+  };
+  
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOOO:Geometry_SetPoint_2D",kwnames,&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_SetPoint_2D" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_SetPoint_2D" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  ecode3 = SWIG_AsVal_double(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Geometry_SetPoint_2D" "', argument " "3"" of type '" "double""'");
+  } 
+  arg3 = static_cast< double >(val3);
+  ecode4 = SWIG_AsVal_double(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Geometry_SetPoint_2D" "', argument " "4"" of type '" "double""'");
+  } 
+  arg4 = static_cast< double >(val4);
+  {
+    if ( bUseExceptions ) {
       CPLErrorReset();
     }
     OGRGeometryShadow_SetPoint_2D(arg1,arg2,arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -20351,7 +22374,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_GetGeometryRef(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -20378,14 +22401,17 @@ SWIGINTERN PyObject *_wrap_Geometry_GetGeometryRef(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)OGRGeometryShadow_GetGeometryRef(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -20393,7 +22419,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_Simplify(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   double arg2 ;
   void *argp1 = 0 ;
@@ -20420,14 +22446,17 @@ SWIGINTERN PyObject *_wrap_Geometry_Simplify(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)OGRGeometryShadow_Simplify(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -20435,7 +22464,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_SimplifyPreserveTopology(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   double arg2 ;
   void *argp1 = 0 ;
@@ -20462,14 +22491,78 @@ SWIGINTERN PyObject *_wrap_Geometry_SimplifyPreserveTopology(PyObject *SWIGUNUSE
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)OGRGeometryShadow_SimplifyPreserveTopology(arg1,arg2);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Geometry_DelaunayTriangulation(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  double arg2 = (double) 0.0 ;
+  int arg3 = (int) FALSE ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  double val2 ;
+  int ecode2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "dfTolerance",(char *) "bOnlyEdges", NULL 
+  };
+  OGRGeometryShadow *result = 0 ;
+  
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"O|OO:Geometry_DelaunayTriangulation",kwnames,&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_DelaunayTriangulation" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
+  if (obj1) {
+    ecode2 = SWIG_AsVal_double(obj1, &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_DelaunayTriangulation" "', argument " "2"" of type '" "double""'");
+    } 
+    arg2 = static_cast< double >(val2);
+  }
+  if (obj2) {
+    ecode3 = SWIG_AsVal_int(obj2, &val3);
+    if (!SWIG_IsOK(ecode3)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Geometry_DelaunayTriangulation" "', argument " "3"" of type '" "int""'");
+    } 
+    arg3 = static_cast< int >(val3);
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OGRGeometryShadow *)OGRGeometryShadow_DelaunayTriangulation(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -20477,7 +22570,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_Boundary(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -20495,14 +22588,17 @@ SWIGINTERN PyObject *_wrap_Geometry_Boundary(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)OGRGeometryShadow_Boundary(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -20510,7 +22606,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_GetBoundary(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -20528,14 +22624,17 @@ SWIGINTERN PyObject *_wrap_Geometry_GetBoundary(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)OGRGeometryShadow_GetBoundary(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -20543,7 +22642,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_ConvexHull(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -20561,14 +22660,17 @@ SWIGINTERN PyObject *_wrap_Geometry_ConvexHull(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)OGRGeometryShadow_ConvexHull(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -20576,7 +22678,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_Buffer(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   double arg2 ;
   int arg3 = (int) 30 ;
@@ -20617,14 +22719,17 @@ SWIGINTERN PyObject *_wrap_Geometry_Buffer(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)OGRGeometryShadow_Buffer(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -20632,7 +22737,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_Intersection(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
@@ -20664,14 +22769,17 @@ SWIGINTERN PyObject *_wrap_Geometry_Intersection(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)OGRGeometryShadow_Intersection(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -20679,7 +22787,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_Union(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
@@ -20711,14 +22819,17 @@ SWIGINTERN PyObject *_wrap_Geometry_Union(PyObject *SWIGUNUSEDPARM(self), PyObje
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)OGRGeometryShadow_Union(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -20726,7 +22837,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_UnionCascaded(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -20744,14 +22855,17 @@ SWIGINTERN PyObject *_wrap_Geometry_UnionCascaded(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)OGRGeometryShadow_UnionCascaded(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -20759,7 +22873,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_Difference(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
@@ -20791,14 +22905,17 @@ SWIGINTERN PyObject *_wrap_Geometry_Difference(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)OGRGeometryShadow_Difference(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -20806,7 +22923,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_SymDifference(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
@@ -20838,14 +22955,17 @@ SWIGINTERN PyObject *_wrap_Geometry_SymDifference(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)OGRGeometryShadow_SymDifference(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -20853,7 +22973,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_SymmetricDifference(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
@@ -20885,14 +23005,17 @@ SWIGINTERN PyObject *_wrap_Geometry_SymmetricDifference(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)OGRGeometryShadow_SymmetricDifference(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -20900,7 +23023,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_Distance(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
@@ -20932,14 +23055,17 @@ SWIGINTERN PyObject *_wrap_Geometry_Distance(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (double)OGRGeometryShadow_Distance(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_double(static_cast< double >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -20947,7 +23073,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_Empty(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -20964,14 +23090,17 @@ SWIGINTERN PyObject *_wrap_Geometry_Empty(PyObject *SWIGUNUSEDPARM(self), PyObje
       CPLErrorReset();
     }
     OGRGeometryShadow_Empty(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -20979,7 +23108,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_IsEmpty(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -20997,14 +23126,17 @@ SWIGINTERN PyObject *_wrap_Geometry_IsEmpty(PyObject *SWIGUNUSEDPARM(self), PyOb
       CPLErrorReset();
     }
     result = (bool)OGRGeometryShadow_IsEmpty(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_bool(static_cast< bool >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -21012,7 +23144,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_IsValid(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -21030,14 +23162,17 @@ SWIGINTERN PyObject *_wrap_Geometry_IsValid(PyObject *SWIGUNUSEDPARM(self), PyOb
       CPLErrorReset();
     }
     result = (bool)OGRGeometryShadow_IsValid(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_bool(static_cast< bool >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -21045,7 +23180,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_IsSimple(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -21063,14 +23198,17 @@ SWIGINTERN PyObject *_wrap_Geometry_IsSimple(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (bool)OGRGeometryShadow_IsSimple(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_bool(static_cast< bool >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -21078,7 +23216,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_IsRing(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -21096,14 +23234,17 @@ SWIGINTERN PyObject *_wrap_Geometry_IsRing(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     result = (bool)OGRGeometryShadow_IsRing(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_bool(static_cast< bool >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -21111,7 +23252,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_Intersects(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
@@ -21143,14 +23284,17 @@ SWIGINTERN PyObject *_wrap_Geometry_Intersects(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     result = (bool)OGRGeometryShadow_Intersects(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_bool(static_cast< bool >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -21158,7 +23302,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_Intersect(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
@@ -21190,14 +23334,17 @@ SWIGINTERN PyObject *_wrap_Geometry_Intersect(PyObject *SWIGUNUSEDPARM(self), Py
       CPLErrorReset();
     }
     result = (bool)OGRGeometryShadow_Intersect(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_bool(static_cast< bool >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -21205,7 +23352,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_Equals(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
@@ -21237,14 +23384,17 @@ SWIGINTERN PyObject *_wrap_Geometry_Equals(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     result = (bool)OGRGeometryShadow_Equals(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_bool(static_cast< bool >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -21252,7 +23402,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_Equal(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
@@ -21284,14 +23434,17 @@ SWIGINTERN PyObject *_wrap_Geometry_Equal(PyObject *SWIGUNUSEDPARM(self), PyObje
       CPLErrorReset();
     }
     result = (bool)OGRGeometryShadow_Equal(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_bool(static_cast< bool >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -21299,7 +23452,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_Disjoint(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
@@ -21331,14 +23484,17 @@ SWIGINTERN PyObject *_wrap_Geometry_Disjoint(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (bool)OGRGeometryShadow_Disjoint(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_bool(static_cast< bool >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -21346,7 +23502,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_Touches(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
@@ -21378,14 +23534,17 @@ SWIGINTERN PyObject *_wrap_Geometry_Touches(PyObject *SWIGUNUSEDPARM(self), PyOb
       CPLErrorReset();
     }
     result = (bool)OGRGeometryShadow_Touches(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_bool(static_cast< bool >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -21393,7 +23552,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_Crosses(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
@@ -21425,14 +23584,17 @@ SWIGINTERN PyObject *_wrap_Geometry_Crosses(PyObject *SWIGUNUSEDPARM(self), PyOb
       CPLErrorReset();
     }
     result = (bool)OGRGeometryShadow_Crosses(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_bool(static_cast< bool >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -21440,7 +23602,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_Within(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
@@ -21472,14 +23634,17 @@ SWIGINTERN PyObject *_wrap_Geometry_Within(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     result = (bool)OGRGeometryShadow_Within(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_bool(static_cast< bool >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -21487,7 +23652,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_Contains(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
@@ -21519,14 +23684,17 @@ SWIGINTERN PyObject *_wrap_Geometry_Contains(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (bool)OGRGeometryShadow_Contains(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_bool(static_cast< bool >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -21534,7 +23702,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_Overlaps(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
@@ -21566,14 +23734,17 @@ SWIGINTERN PyObject *_wrap_Geometry_Overlaps(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (bool)OGRGeometryShadow_Overlaps(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_bool(static_cast< bool >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -21581,7 +23752,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_TransformTo(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   OSRSpatialReferenceShadow *arg2 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
@@ -21613,12 +23784,14 @@ SWIGINTERN PyObject *_wrap_Geometry_TransformTo(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (OGRErr)OGRGeometryShadow_TransformTo(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -21629,14 +23802,11 @@ SWIGINTERN PyObject *_wrap_Geometry_TransformTo(PyObject *SWIGUNUSEDPARM(self),
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -21644,7 +23814,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_Transform(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   OSRCoordinateTransformationShadow *arg2 = (OSRCoordinateTransformationShadow *) 0 ;
   void *argp1 = 0 ;
@@ -21676,12 +23846,14 @@ SWIGINTERN PyObject *_wrap_Geometry_Transform(PyObject *SWIGUNUSEDPARM(self), Py
       CPLErrorReset();
     }
     result = (OGRErr)OGRGeometryShadow_Transform(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -21692,14 +23864,11 @@ SWIGINTERN PyObject *_wrap_Geometry_Transform(PyObject *SWIGUNUSEDPARM(self), Py
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -21707,7 +23876,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_GetSpatialReference(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -21725,14 +23894,17 @@ SWIGINTERN PyObject *_wrap_Geometry_GetSpatialReference(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     result = (OSRSpatialReferenceShadow *)OGRGeometryShadow_GetSpatialReference(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OSRSpatialReferenceShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -21740,7 +23912,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_AssignSpatialReference(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   OSRSpatialReferenceShadow *arg2 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
@@ -21766,14 +23938,17 @@ SWIGINTERN PyObject *_wrap_Geometry_AssignSpatialReference(PyObject *SWIGUNUSEDP
       CPLErrorReset();
     }
     OGRGeometryShadow_AssignSpatialReference(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -21781,7 +23956,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_CloseRings(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -21798,14 +23973,17 @@ SWIGINTERN PyObject *_wrap_Geometry_CloseRings(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     OGRGeometryShadow_CloseRings(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -21813,7 +23991,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_FlattenTo2D(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -21830,14 +24008,17 @@ SWIGINTERN PyObject *_wrap_Geometry_FlattenTo2D(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     OGRGeometryShadow_FlattenTo2D(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -21845,7 +24026,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_Segmentize(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   double arg2 ;
   void *argp1 = 0 ;
@@ -21871,14 +24052,17 @@ SWIGINTERN PyObject *_wrap_Geometry_Segmentize(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     OGRGeometryShadow_Segmentize(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -21886,7 +24070,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_GetEnvelope(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   double *arg2 ;
   void *argp1 = 0 ;
@@ -21896,6 +24080,7 @@ SWIGINTERN PyObject *_wrap_Geometry_GetEnvelope(PyObject *SWIGUNUSEDPARM(self),
   
   {
     /* %typemap(in,numinputs=0) (double argout2[ANY]) */
+    memset(argout2, 0, sizeof(argout2));
     arg2 = argout2;
   }
   if (!PyArg_ParseTuple(args,(char *)"O:Geometry_GetEnvelope",&obj0)) SWIG_fail;
@@ -21909,12 +24094,14 @@ SWIGINTERN PyObject *_wrap_Geometry_GetEnvelope(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     OGRGeometryShadow_GetEnvelope(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
@@ -21922,6 +24109,7 @@ SWIGINTERN PyObject *_wrap_Geometry_GetEnvelope(PyObject *SWIGUNUSEDPARM(self),
     PyObject *out = CreateTupleFromDoubleArray( arg2, 4 );
     resultobj = t_output_helper(resultobj,out);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -21929,7 +24117,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_GetEnvelope3D(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   double *arg2 ;
   void *argp1 = 0 ;
@@ -21939,6 +24127,7 @@ SWIGINTERN PyObject *_wrap_Geometry_GetEnvelope3D(PyObject *SWIGUNUSEDPARM(self)
   
   {
     /* %typemap(in,numinputs=0) (double argout2[ANY]) */
+    memset(argout2, 0, sizeof(argout2));
     arg2 = argout2;
   }
   if (!PyArg_ParseTuple(args,(char *)"O:Geometry_GetEnvelope3D",&obj0)) SWIG_fail;
@@ -21952,12 +24141,14 @@ SWIGINTERN PyObject *_wrap_Geometry_GetEnvelope3D(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     OGRGeometryShadow_GetEnvelope3D(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
@@ -21965,6 +24156,7 @@ SWIGINTERN PyObject *_wrap_Geometry_GetEnvelope3D(PyObject *SWIGUNUSEDPARM(self)
     PyObject *out = CreateTupleFromDoubleArray( arg2, 6 );
     resultobj = t_output_helper(resultobj,out);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -21972,7 +24164,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_Centroid(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -21990,14 +24182,17 @@ SWIGINTERN PyObject *_wrap_Geometry_Centroid(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)OGRGeometryShadow_Centroid(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22005,7 +24200,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_PointOnSurface(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -22023,14 +24218,17 @@ SWIGINTERN PyObject *_wrap_Geometry_PointOnSurface(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)OGRGeometryShadow_PointOnSurface(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22038,7 +24236,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_WkbSize(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -22056,14 +24254,17 @@ SWIGINTERN PyObject *_wrap_Geometry_WkbSize(PyObject *SWIGUNUSEDPARM(self), PyOb
       CPLErrorReset();
     }
     result = (int)OGRGeometryShadow_WkbSize(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22071,7 +24272,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_GetCoordinateDimension(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -22089,96 +24290,301 @@ SWIGINTERN PyObject *_wrap_Geometry_GetCoordinateDimension(PyObject *SWIGUNUSEDP
       CPLErrorReset();
     }
     result = (int)OGRGeometryShadow_GetCoordinateDimension(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Geometry_SetCoordinateDimension(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+SWIGINTERN PyObject *_wrap_Geometry_CoordinateDimension(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
-  int arg2 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int val2 ;
-  int ecode2 = 0 ;
   PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
+  int result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Geometry_SetCoordinateDimension",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:Geometry_CoordinateDimension",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_SetCoordinateDimension" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_CoordinateDimension" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
-  ecode2 = SWIG_AsVal_int(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_SetCoordinateDimension" "', argument " "2"" of type '" "int""'");
-  } 
-  arg2 = static_cast< int >(val2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRGeometryShadow_SetCoordinateDimension(arg1,arg2);
+    result = (int)OGRGeometryShadow_CoordinateDimension(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
-  resultobj = SWIG_Py_Void();
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Geometry_GetDimension(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+SWIGINTERN PyObject *_wrap_Geometry_Is3D(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
   int result;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:Geometry_GetDimension",&obj0)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:Geometry_Is3D",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_GetDimension" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_Is3D" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRGeometryShadow_GetDimension(arg1);
+    result = (int)OGRGeometryShadow_Is3D(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Geometry_HasCurveGeometry(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+SWIGINTERN PyObject *_wrap_Geometry_IsMeasured(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:Geometry_IsMeasured",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_IsMeasured" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)OGRGeometryShadow_IsMeasured(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Geometry_SetCoordinateDimension(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  int arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Geometry_SetCoordinateDimension",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_SetCoordinateDimension" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_SetCoordinateDimension" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRGeometryShadow_SetCoordinateDimension(arg1,arg2);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Geometry_Set3D(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  int arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Geometry_Set3D",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_Set3D" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_Set3D" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRGeometryShadow_Set3D(arg1,arg2);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Geometry_SetMeasured(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  int arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Geometry_SetMeasured",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_SetMeasured" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_SetMeasured" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRGeometryShadow_SetMeasured(arg1,arg2);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Geometry_GetDimension(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:Geometry_GetDimension",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_GetDimension" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)OGRGeometryShadow_GetDimension(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Geometry_HasCurveGeometry(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   int arg2 = (int) FALSE ;
   void *argp1 = 0 ;
@@ -22207,14 +24613,17 @@ SWIGINTERN PyObject *_wrap_Geometry_HasCurveGeometry(PyObject *SWIGUNUSEDPARM(se
       CPLErrorReset();
     }
     result = (int)OGRGeometryShadow_HasCurveGeometry(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22222,7 +24631,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_GetLinearGeometry(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   double arg2 = (double) 0.0 ;
   char **arg3 = (char **) NULL ;
@@ -22264,8 +24673,12 @@ SWIGINTERN PyObject *_wrap_Geometry_GetLinearGeometry(PyObject *SWIGUNUSEDPARM(s
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj2);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj2);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj2,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -22302,18 +24715,21 @@ SWIGINTERN PyObject *_wrap_Geometry_GetLinearGeometry(PyObject *SWIGUNUSEDPARM(s
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)OGRGeometryShadow_GetLinearGeometry(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
   {
     /* %typemap(freearg) char **options */
     CSLDestroy( arg3 );
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -22325,7 +24741,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_GetCurveGeometry(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   char **arg2 = (char **) NULL ;
   void *argp1 = 0 ;
@@ -22356,8 +24772,12 @@ SWIGINTERN PyObject *_wrap_Geometry_GetCurveGeometry(PyObject *SWIGUNUSEDPARM(se
         SWIG_fail;
       }
       
-      int size = PySequence_Size(obj1);
-      for (int i = 0; i < size; i++) {
+      Py_ssize_t size = PySequence_Size(obj1);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
         PyObject* pyObj = PySequence_GetItem(obj1,i);
         if (PyUnicode_Check(pyObj))
         {
@@ -22394,18 +24814,21 @@ SWIGINTERN PyObject *_wrap_Geometry_GetCurveGeometry(PyObject *SWIGUNUSEDPARM(se
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)OGRGeometryShadow_GetCurveGeometry(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
   {
     /* %typemap(freearg) char **options */
     CSLDestroy( arg2 );
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -22417,7 +24840,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Geometry_Value(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   double arg2 ;
   void *argp1 = 0 ;
@@ -22444,14 +24867,17 @@ SWIGINTERN PyObject *_wrap_Geometry_Value(PyObject *SWIGUNUSEDPARM(self), PyObje
       CPLErrorReset();
     }
     result = (OGRGeometryShadow *)OGRGeometryShadow_Value(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22466,7 +24892,7 @@ SWIGINTERN PyObject *Geometry_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObj
 }
 
 SWIGINTERN PyObject *_wrap_GetDriverCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   int result;
   
   if (!PyArg_ParseTuple(args,(char *)":GetDriverCount")) SWIG_fail;
@@ -22475,14 +24901,17 @@ SWIGINTERN PyObject *_wrap_GetDriverCount(PyObject *SWIGUNUSEDPARM(self), PyObje
       CPLErrorReset();
     }
     result = (int)OGRGetDriverCount();
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22490,7 +24919,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GetOpenDSCount(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   int result;
   
   if (!PyArg_ParseTuple(args,(char *)":GetOpenDSCount")) SWIG_fail;
@@ -22499,14 +24928,17 @@ SWIGINTERN PyObject *_wrap_GetOpenDSCount(PyObject *SWIGUNUSEDPARM(self), PyObje
       CPLErrorReset();
     }
     result = (int)OGRGetOpenDSCount();
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22514,7 +24946,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SetGenerate_DB2_V72_BYTE_ORDER(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   int arg1 ;
   int val1 ;
   int ecode1 = 0 ;
@@ -22532,12 +24964,14 @@ SWIGINTERN PyObject *_wrap_SetGenerate_DB2_V72_BYTE_ORDER(PyObject *SWIGUNUSEDPA
       CPLErrorReset();
     }
     result = (OGRErr)OGRSetGenerate_DB2_V72_BYTE_ORDER(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -22548,14 +24982,11 @@ SWIGINTERN PyObject *_wrap_SetGenerate_DB2_V72_BYTE_ORDER(PyObject *SWIGUNUSEDPA
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22563,7 +24994,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_RegisterAll(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   
   if (!PyArg_ParseTuple(args,(char *)":RegisterAll")) SWIG_fail;
   {
@@ -22571,14 +25002,17 @@ SWIGINTERN PyObject *_wrap_RegisterAll(PyObject *SWIGUNUSEDPARM(self), PyObject
       CPLErrorReset();
     }
     OGRRegisterAll();
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22586,7 +25020,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GeometryTypeToName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRwkbGeometryType arg1 ;
   int val1 ;
   int ecode1 = 0 ;
@@ -22604,14 +25038,17 @@ SWIGINTERN PyObject *_wrap_GeometryTypeToName(PyObject *SWIGUNUSEDPARM(self), Py
       CPLErrorReset();
     }
     result = (char *)OGRGeometryTypeToName(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22619,7 +25056,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GetFieldTypeName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFieldType arg1 ;
   int val1 ;
   int ecode1 = 0 ;
@@ -22637,14 +25074,17 @@ SWIGINTERN PyObject *_wrap_GetFieldTypeName(PyObject *SWIGUNUSEDPARM(self), PyOb
       CPLErrorReset();
     }
     result = (char *)OGR_GetFieldTypeName(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22652,7 +25092,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GetFieldSubTypeName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFieldSubType arg1 ;
   int val1 ;
   int ecode1 = 0 ;
@@ -22670,14 +25110,17 @@ SWIGINTERN PyObject *_wrap_GetFieldSubTypeName(PyObject *SWIGUNUSEDPARM(self), P
       CPLErrorReset();
     }
     result = (char *)OGR_GetFieldSubTypeName(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22685,7 +25128,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GT_Flatten(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRwkbGeometryType arg1 ;
   int val1 ;
   int ecode1 = 0 ;
@@ -22703,14 +25146,17 @@ SWIGINTERN PyObject *_wrap_GT_Flatten(PyObject *SWIGUNUSEDPARM(self), PyObject *
       CPLErrorReset();
     }
     result = (OGRwkbGeometryType)OGR_GT_Flatten(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22718,7 +25164,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GT_SetZ(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRwkbGeometryType arg1 ;
   int val1 ;
   int ecode1 = 0 ;
@@ -22736,14 +25182,53 @@ SWIGINTERN PyObject *_wrap_GT_SetZ(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
       CPLErrorReset();
     }
     result = (OGRwkbGeometryType)OGR_GT_SetZ(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_GT_SetM(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  OGRwkbGeometryType arg1 ;
+  int val1 ;
+  int ecode1 = 0 ;
+  PyObject * obj0 = 0 ;
+  OGRwkbGeometryType result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:GT_SetM",&obj0)) SWIG_fail;
+  ecode1 = SWIG_AsVal_int(obj0, &val1);
+  if (!SWIG_IsOK(ecode1)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "GT_SetM" "', argument " "1"" of type '" "OGRwkbGeometryType""'");
+  } 
+  arg1 = static_cast< OGRwkbGeometryType >(val1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OGRwkbGeometryType)OGR_GT_SetM(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22751,7 +25236,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GT_SetModifier(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRwkbGeometryType arg1 ;
   int arg2 ;
   int arg3 = (int) FALSE ;
@@ -22789,14 +25274,17 @@ SWIGINTERN PyObject *_wrap_GT_SetModifier(PyObject *SWIGUNUSEDPARM(self), PyObje
       CPLErrorReset();
     }
     result = (OGRwkbGeometryType)GT_SetModifier(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22804,7 +25292,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GT_HasZ(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRwkbGeometryType arg1 ;
   int val1 ;
   int ecode1 = 0 ;
@@ -22822,14 +25310,53 @@ SWIGINTERN PyObject *_wrap_GT_HasZ(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
       CPLErrorReset();
     }
     result = (int)OGR_GT_HasZ(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_GT_HasM(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  OGRwkbGeometryType arg1 ;
+  int val1 ;
+  int ecode1 = 0 ;
+  PyObject * obj0 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:GT_HasM",&obj0)) SWIG_fail;
+  ecode1 = SWIG_AsVal_int(obj0, &val1);
+  if (!SWIG_IsOK(ecode1)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "GT_HasM" "', argument " "1"" of type '" "OGRwkbGeometryType""'");
+  } 
+  arg1 = static_cast< OGRwkbGeometryType >(val1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)OGR_GT_HasM(arg1);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22837,7 +25364,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GT_IsSubClassOf(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRwkbGeometryType arg1 ;
   OGRwkbGeometryType arg2 ;
   int val1 ;
@@ -22864,14 +25391,17 @@ SWIGINTERN PyObject *_wrap_GT_IsSubClassOf(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     result = (int)OGR_GT_IsSubClassOf(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22879,7 +25409,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GT_IsCurve(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRwkbGeometryType arg1 ;
   int val1 ;
   int ecode1 = 0 ;
@@ -22897,14 +25427,17 @@ SWIGINTERN PyObject *_wrap_GT_IsCurve(PyObject *SWIGUNUSEDPARM(self), PyObject *
       CPLErrorReset();
     }
     result = (int)OGR_GT_IsCurve(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22912,7 +25445,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GT_IsSurface(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRwkbGeometryType arg1 ;
   int val1 ;
   int ecode1 = 0 ;
@@ -22930,14 +25463,17 @@ SWIGINTERN PyObject *_wrap_GT_IsSurface(PyObject *SWIGUNUSEDPARM(self), PyObject
       CPLErrorReset();
     }
     result = (int)OGR_GT_IsSurface(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22945,7 +25481,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GT_IsNonLinear(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRwkbGeometryType arg1 ;
   int val1 ;
   int ecode1 = 0 ;
@@ -22963,14 +25499,17 @@ SWIGINTERN PyObject *_wrap_GT_IsNonLinear(PyObject *SWIGUNUSEDPARM(self), PyObje
       CPLErrorReset();
     }
     result = (int)OGR_GT_IsNonLinear(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -22978,7 +25517,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GT_GetCollection(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRwkbGeometryType arg1 ;
   int val1 ;
   int ecode1 = 0 ;
@@ -22996,14 +25535,17 @@ SWIGINTERN PyObject *_wrap_GT_GetCollection(PyObject *SWIGUNUSEDPARM(self), PyOb
       CPLErrorReset();
     }
     result = (OGRwkbGeometryType)OGR_GT_GetCollection(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -23011,7 +25553,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GT_GetCurve(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRwkbGeometryType arg1 ;
   int val1 ;
   int ecode1 = 0 ;
@@ -23029,14 +25571,17 @@ SWIGINTERN PyObject *_wrap_GT_GetCurve(PyObject *SWIGUNUSEDPARM(self), PyObject
       CPLErrorReset();
     }
     result = (OGRwkbGeometryType)OGR_GT_GetCurve(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -23044,7 +25589,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GT_GetLinear(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRwkbGeometryType arg1 ;
   int val1 ;
   int ecode1 = 0 ;
@@ -23062,14 +25607,17 @@ SWIGINTERN PyObject *_wrap_GT_GetLinear(PyObject *SWIGUNUSEDPARM(self), PyObject
       CPLErrorReset();
     }
     result = (OGRwkbGeometryType)OGR_GT_GetLinear(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -23077,7 +25625,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SetNonLinearGeometriesEnabledFlag(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   int arg1 ;
   int val1 ;
   int ecode1 = 0 ;
@@ -23094,14 +25642,17 @@ SWIGINTERN PyObject *_wrap_SetNonLinearGeometriesEnabledFlag(PyObject *SWIGUNUSE
       CPLErrorReset();
     }
     OGRSetNonLinearGeometriesEnabledFlag(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -23109,7 +25660,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GetNonLinearGeometriesEnabledFlag(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   int result;
   
   if (!PyArg_ParseTuple(args,(char *)":GetNonLinearGeometriesEnabledFlag")) SWIG_fail;
@@ -23118,14 +25669,17 @@ SWIGINTERN PyObject *_wrap_GetNonLinearGeometriesEnabledFlag(PyObject *SWIGUNUSE
       CPLErrorReset();
     }
     result = (int)OGRGetNonLinearGeometriesEnabledFlag();
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -23133,7 +25687,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GetOpenDS(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   int arg1 ;
   int val1 ;
   int ecode1 = 0 ;
@@ -23151,14 +25705,17 @@ SWIGINTERN PyObject *_wrap_GetOpenDS(PyObject *SWIGUNUSEDPARM(self), PyObject *a
       CPLErrorReset();
     }
     result = (OGRDataSourceShadow *)GetOpenDS(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDataSourceShadow, 0 |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -23166,7 +25723,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Open(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   int arg2 = (int) 0 ;
   int bToFree1 = 0 ;
@@ -23201,18 +25758,21 @@ SWIGINTERN PyObject *_wrap_Open(PyObject *SWIGUNUSEDPARM(self), PyObject *args,
       CPLErrorReset();
     }
     result = (OGRDataSourceShadow *)Open((char const *)arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDataSourceShadow, SWIG_POINTER_OWN |  0 );
   {
     /* %typemap(freearg) (const char *utf8_path) */
     GDALPythonFreeCStr(arg1, bToFree1);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -23224,7 +25784,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_OpenShared(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   int arg2 = (int) 0 ;
   int bToFree1 = 0 ;
@@ -23259,18 +25819,21 @@ SWIGINTERN PyObject *_wrap_OpenShared(PyObject *SWIGUNUSEDPARM(self), PyObject *
       CPLErrorReset();
     }
     result = (OGRDataSourceShadow *)OpenShared((char const *)arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDataSourceShadow, SWIG_POINTER_OWN |  0 );
   {
     /* %typemap(freearg) (const char *utf8_path) */
     GDALPythonFreeCStr(arg1, bToFree1);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -23282,7 +25845,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GetDriverByName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   int res1 ;
   char *buf1 = 0 ;
@@ -23306,15 +25869,18 @@ SWIGINTERN PyObject *_wrap_GetDriverByName(PyObject *SWIGUNUSEDPARM(self), PyObj
       CPLErrorReset();
     }
     result = (OGRDriverShadow *)GetDriverByName((char const *)arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
@@ -23323,7 +25889,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GetDriver(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   int arg1 ;
   int val1 ;
   int ecode1 = 0 ;
@@ -23341,14 +25907,17 @@ SWIGINTERN PyObject *_wrap_GetDriver(PyObject *SWIGUNUSEDPARM(self), PyObject *a
       CPLErrorReset();
     }
     result = (OGRDriverShadow *)GetDriver(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDriverShadow, 0 |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -23356,7 +25925,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GeneralCmdLineProcessor(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char **arg1 = (char **) 0 ;
   int arg2 = (int) 0 ;
   int val2 ;
@@ -23378,8 +25947,12 @@ SWIGINTERN PyObject *_wrap_GeneralCmdLineProcessor(PyObject *SWIGUNUSEDPARM(self
       SWIG_fail;
     }
     
-    int size = PySequence_Size(obj0);
-    for (int i = 0; i < size; i++) {
+    Py_ssize_t size = PySequence_Size(obj0);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    for (int i = 0; i < (int)size; i++) {
       PyObject* pyObj = PySequence_GetItem(obj0,i);
       if (PyUnicode_Check(pyObj))
       {
@@ -23422,12 +25995,14 @@ SWIGINTERN PyObject *_wrap_GeneralCmdLineProcessor(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     result = (char **)GeneralCmdLineProcessor(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) char **CSL -> ( string ) */
@@ -23450,6 +26025,7 @@ SWIGINTERN PyObject *_wrap_GeneralCmdLineProcessor(PyObject *SWIGUNUSEDPARM(self
     /* %typemap(freearg) char **options */
     CSLDestroy( arg1 );
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -23461,7 +26037,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_TermProgress_nocb(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   double arg1 ;
   char *arg2 = (char *) NULL ;
   void *arg3 = (void *) NULL ;
@@ -23503,15 +26079,18 @@ SWIGINTERN PyObject *_wrap_TermProgress_nocb(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (int)GDALTermProgress_nocb(arg1,(char const *)arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -23524,31 +26103,31 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"GetUseExceptions", _wrap_GetUseExceptions, METH_VARARGS, (char *)"GetUseExceptions() -> int"},
 	 { (char *)"UseExceptions", _wrap_UseExceptions, METH_VARARGS, (char *)"UseExceptions()"},
 	 { (char *)"DontUseExceptions", _wrap_DontUseExceptions, METH_VARARGS, (char *)"DontUseExceptions()"},
-	 { (char *)"MajorObject_GetDescription", _wrap_MajorObject_GetDescription, METH_VARARGS, (char *)"MajorObject_GetDescription(MajorObject self) -> char"},
-	 { (char *)"MajorObject_SetDescription", _wrap_MajorObject_SetDescription, METH_VARARGS, (char *)"MajorObject_SetDescription(MajorObject self, char pszNewDesc)"},
-	 { (char *)"MajorObject_GetMetadataDomainList", _wrap_MajorObject_GetMetadataDomainList, METH_VARARGS, (char *)"MajorObject_GetMetadataDomainList(MajorObject self) -> char"},
-	 { (char *)"MajorObject_GetMetadata_Dict", _wrap_MajorObject_GetMetadata_Dict, METH_VARARGS, (char *)"MajorObject_GetMetadata_Dict(MajorObject self, char pszDomain = \"\") -> char"},
-	 { (char *)"MajorObject_GetMetadata_List", _wrap_MajorObject_GetMetadata_List, METH_VARARGS, (char *)"MajorObject_GetMetadata_List(MajorObject self, char pszDomain = \"\") -> char"},
+	 { (char *)"MajorObject_GetDescription", _wrap_MajorObject_GetDescription, METH_VARARGS, (char *)"MajorObject_GetDescription(MajorObject self) -> char const *"},
+	 { (char *)"MajorObject_SetDescription", _wrap_MajorObject_SetDescription, METH_VARARGS, (char *)"MajorObject_SetDescription(MajorObject self, char const * pszNewDesc)"},
+	 { (char *)"MajorObject_GetMetadataDomainList", _wrap_MajorObject_GetMetadataDomainList, METH_VARARGS, (char *)"MajorObject_GetMetadataDomainList(MajorObject self) -> char **"},
+	 { (char *)"MajorObject_GetMetadata_Dict", _wrap_MajorObject_GetMetadata_Dict, METH_VARARGS, (char *)"MajorObject_GetMetadata_Dict(MajorObject self, char const * pszDomain=\"\") -> char **"},
+	 { (char *)"MajorObject_GetMetadata_List", _wrap_MajorObject_GetMetadata_List, METH_VARARGS, (char *)"MajorObject_GetMetadata_List(MajorObject self, char const * pszDomain=\"\") -> char **"},
 	 { (char *)"MajorObject_SetMetadata", _wrap_MajorObject_SetMetadata, METH_VARARGS, (char *)"\n"
-		"SetMetadata(char papszMetadata, char pszDomain = \"\") -> CPLErr\n"
-		"MajorObject_SetMetadata(MajorObject self, char pszMetadataString, char pszDomain = \"\") -> CPLErr\n"
+		"SetMetadata(char ** papszMetadata, char const * pszDomain=\"\") -> CPLErr\n"
+		"MajorObject_SetMetadata(MajorObject self, char * pszMetadataString, char const * pszDomain=\"\") -> CPLErr\n"
 		""},
-	 { (char *)"MajorObject_GetMetadataItem", _wrap_MajorObject_GetMetadataItem, METH_VARARGS, (char *)"MajorObject_GetMetadataItem(MajorObject self, char pszName, char pszDomain = \"\") -> char"},
-	 { (char *)"MajorObject_SetMetadataItem", _wrap_MajorObject_SetMetadataItem, METH_VARARGS, (char *)"MajorObject_SetMetadataItem(MajorObject self, char pszName, char pszValue, char pszDomain = \"\") -> CPLErr"},
+	 { (char *)"MajorObject_GetMetadataItem", _wrap_MajorObject_GetMetadataItem, METH_VARARGS, (char *)"MajorObject_GetMetadataItem(MajorObject self, char const * pszName, char const * pszDomain=\"\") -> char const *"},
+	 { (char *)"MajorObject_SetMetadataItem", _wrap_MajorObject_SetMetadataItem, METH_VARARGS, (char *)"MajorObject_SetMetadataItem(MajorObject self, char const * pszName, char const * pszValue, char const * pszDomain=\"\") -> CPLErr"},
 	 { (char *)"MajorObject_swigregister", MajorObject_swigregister, METH_VARARGS, NULL},
 	 { (char *)"new_StyleTable", _wrap_new_StyleTable, METH_VARARGS, (char *)"new_StyleTable() -> StyleTable"},
 	 { (char *)"delete_StyleTable", _wrap_delete_StyleTable, METH_VARARGS, (char *)"delete_StyleTable(StyleTable self)"},
-	 { (char *)"StyleTable_AddStyle", _wrap_StyleTable_AddStyle, METH_VARARGS, (char *)"StyleTable_AddStyle(StyleTable self, char pszName, char pszStyleString) -> int"},
-	 { (char *)"StyleTable_LoadStyleTable", _wrap_StyleTable_LoadStyleTable, METH_VARARGS, (char *)"StyleTable_LoadStyleTable(StyleTable self, char utf8_path) -> int"},
-	 { (char *)"StyleTable_SaveStyleTable", _wrap_StyleTable_SaveStyleTable, METH_VARARGS, (char *)"StyleTable_SaveStyleTable(StyleTable self, char utf8_path) -> int"},
-	 { (char *)"StyleTable_Find", _wrap_StyleTable_Find, METH_VARARGS, (char *)"StyleTable_Find(StyleTable self, char pszName) -> char"},
+	 { (char *)"StyleTable_AddStyle", _wrap_StyleTable_AddStyle, METH_VARARGS, (char *)"StyleTable_AddStyle(StyleTable self, char const * pszName, char const * pszStyleString) -> int"},
+	 { (char *)"StyleTable_LoadStyleTable", _wrap_StyleTable_LoadStyleTable, METH_VARARGS, (char *)"StyleTable_LoadStyleTable(StyleTable self, char const * utf8_path) -> int"},
+	 { (char *)"StyleTable_SaveStyleTable", _wrap_StyleTable_SaveStyleTable, METH_VARARGS, (char *)"StyleTable_SaveStyleTable(StyleTable self, char const * utf8_path) -> int"},
+	 { (char *)"StyleTable_Find", _wrap_StyleTable_Find, METH_VARARGS, (char *)"StyleTable_Find(StyleTable self, char const * pszName) -> char const *"},
 	 { (char *)"StyleTable_ResetStyleStringReading", _wrap_StyleTable_ResetStyleStringReading, METH_VARARGS, (char *)"StyleTable_ResetStyleStringReading(StyleTable self)"},
-	 { (char *)"StyleTable_GetNextStyle", _wrap_StyleTable_GetNextStyle, METH_VARARGS, (char *)"StyleTable_GetNextStyle(StyleTable self) -> char"},
-	 { (char *)"StyleTable_GetLastStyleName", _wrap_StyleTable_GetLastStyleName, METH_VARARGS, (char *)"StyleTable_GetLastStyleName(StyleTable self) -> char"},
+	 { (char *)"StyleTable_GetNextStyle", _wrap_StyleTable_GetNextStyle, METH_VARARGS, (char *)"StyleTable_GetNextStyle(StyleTable self) -> char const *"},
+	 { (char *)"StyleTable_GetLastStyleName", _wrap_StyleTable_GetLastStyleName, METH_VARARGS, (char *)"StyleTable_GetLastStyleName(StyleTable self) -> char const *"},
 	 { (char *)"StyleTable_swigregister", StyleTable_swigregister, METH_VARARGS, NULL},
-	 { (char *)"Driver_name_get", _wrap_Driver_name_get, METH_VARARGS, (char *)"Driver_name_get(Driver self) -> char"},
+	 { (char *)"Driver_name_get", _wrap_Driver_name_get, METH_VARARGS, (char *)"Driver_name_get(Driver self) -> char const *"},
 	 { (char *)"Driver_CreateDataSource", (PyCFunction) _wrap_Driver_CreateDataSource, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Driver_CreateDataSource(Driver self, char utf8_path, char options = None) -> DataSource\n"
+		"Driver_CreateDataSource(Driver self, char const * utf8_path, char ** options=None) -> DataSource\n"
 		"\n"
 		"OGRDataSourceH\n"
 		"OGR_Dr_CreateDataSource(OGRSFDriverH hDriver, const char *pszName,\n"
@@ -23564,8 +26143,7 @@ static PyMethodDef SwigMethods[] = {
 		"It is important to call OGR_DS_Destroy() when the datasource is no\n"
 		"longer used to ensure that all data has been properly flushed to disk.\n"
 		"\n"
-		"This function is the same as the C++ method\n"
-		"OGRSFDriver::CreateDataSource().\n"
+		"Deprecated Use GDALCreate() in GDAL 2.0\n"
 		"\n"
 		"Parameters:\n"
 		"-----------\n"
@@ -23576,13 +26154,13 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"papszOptions:  a StringList of name=value options. Options are driver\n"
 		"specific, and driver information can be found at the following\n"
-		"url:http://www.gdal.org/ogr/ogr_formats.html\n"
+		"url:http://www.gdal.org/ogr_formats.html\n"
 		"\n"
 		"NULL is returned on failure, or a new OGRDataSource handle on success.\n"
 		"\n"
 		""},
 	 { (char *)"Driver_CopyDataSource", (PyCFunction) _wrap_Driver_CopyDataSource, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Driver_CopyDataSource(Driver self, DataSource copy_ds, char utf8_path, char options = None) -> DataSource\n"
+		"Driver_CopyDataSource(Driver self, DataSource copy_ds, char const * utf8_path, char ** options=None) -> DataSource\n"
 		"\n"
 		"OGRDataSourceH\n"
 		"OGR_Dr_CopyDataSource(OGRSFDriverH hDriver, OGRDataSourceH hSrcDS,\n"
@@ -23594,8 +26172,7 @@ static PyMethodDef SwigMethods[] = {
 		"It is important to call OGR_DS_Destroy() when the datasource is no\n"
 		"longer used to ensure that all data has been properly flushed to disk.\n"
 		"\n"
-		"This function is the same as the C++ method\n"
-		"OGRSFDriver::CopyDataSource().\n"
+		"Deprecated Use GDALCreateCopy() in GDAL 2.0\n"
 		"\n"
 		"Parameters:\n"
 		"-----------\n"
@@ -23608,20 +26185,25 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"papszOptions:  a StringList of name=value options. Options are driver\n"
 		"specific, and driver information can be found at the following\n"
-		"url:http://www.gdal.org/ogr/ogr_formats.html\n"
+		"url:http://www.gdal.org/ogr_formats.html\n"
 		"\n"
 		"NULL is returned on failure, or a new OGRDataSource handle on success.\n"
 		"\n"
 		""},
 	 { (char *)"Driver_Open", (PyCFunction) _wrap_Driver_Open, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Driver_Open(Driver self, char utf8_path, int update = 0) -> DataSource\n"
+		"Driver_Open(Driver self, char const * utf8_path, int update=0) -> DataSource\n"
 		"\n"
 		"OGRDataSourceH OGR_Dr_Open(OGRSFDriverH\n"
 		"hDriver, const char *pszName, int bUpdate)\n"
 		"\n"
 		"Attempt to open file with this driver.\n"
 		"\n"
-		"This function is the same as the C++ method OGRSFDriver::Open().\n"
+		"NOTE: Starting with GDAL 2.0, it is *NOT* safe to cast the returned\n"
+		"handle to OGRDataSource*. If a C++ object is needed, the handle should\n"
+		"be cast to GDALDataset*. Similarly, the returned OGRSFDriverH handle\n"
+		"should be cast to GDALDriver*, and NOT* OGRSFDriver*.\n"
+		"\n"
+		"Deprecated Use GDALOpenEx() in GDAL 2.0\n"
 		"\n"
 		"Parameters:\n"
 		"-----------\n"
@@ -23634,11 +26216,11 @@ static PyMethodDef SwigMethods[] = {
 		"default).\n"
 		"\n"
 		"NULL on error or if the pass name is not supported by this driver,\n"
-		"otherwise an handle to an OGRDataSource. This OGRDataSource should be\n"
+		"otherwise an handle to a GDALDataset. This GDALDataset should be\n"
 		"closed by deleting the object when it is no longer needed. \n"
 		""},
 	 { (char *)"Driver_DeleteDataSource", _wrap_Driver_DeleteDataSource, METH_VARARGS, (char *)"\n"
-		"Driver_DeleteDataSource(Driver self, char utf8_path) -> int\n"
+		"Driver_DeleteDataSource(Driver self, char const * utf8_path) -> int\n"
 		"\n"
 		"OGRErr\n"
 		"OGR_Dr_DeleteDataSource(OGRSFDriverH hDriver, const char\n"
@@ -23653,8 +26235,7 @@ static PyMethodDef SwigMethods[] = {
 		"Whether this is a supported operation on this driver case be tested\n"
 		"using TestCapability() on ODrCDeleteDataSource.\n"
 		"\n"
-		"This method is the same as the C++ method\n"
-		"OGRSFDriver::DeleteDataSource().\n"
+		"Deprecated Use GDALDeleteDataset() in GDAL 2\n"
 		"\n"
 		"Parameters:\n"
 		"-----------\n"
@@ -23667,7 +26248,7 @@ static PyMethodDef SwigMethods[] = {
 		"not supported by this driver. \n"
 		""},
 	 { (char *)"Driver_TestCapability", _wrap_Driver_TestCapability, METH_VARARGS, (char *)"\n"
-		"Driver_TestCapability(Driver self, char cap) -> bool\n"
+		"Driver_TestCapability(Driver self, char const * cap) -> bool\n"
 		"\n"
 		"int\n"
 		"OGR_Dr_TestCapability(OGRSFDriverH hDriver, const char *pszCap)\n"
@@ -23685,10 +26266,10 @@ static PyMethodDef SwigMethods[] = {
 		"sources.\n"
 		"\n"
 		"The #define macro forms of the capability names should be used in\n"
-		"preference to the strings themselves to avoid mispelling.\n"
+		"preference to the strings themselves to avoid misspelling.\n"
 		"\n"
-		"This function is the same as the C++ method\n"
-		"OGRSFDriver::TestCapability().\n"
+		"Deprecated Use GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATE) in GDAL\n"
+		"2.0\n"
 		"\n"
 		"Parameters:\n"
 		"-----------\n"
@@ -23700,21 +26281,22 @@ static PyMethodDef SwigMethods[] = {
 		"TRUE if capability available otherwise FALSE. \n"
 		""},
 	 { (char *)"Driver_GetName", _wrap_Driver_GetName, METH_VARARGS, (char *)"\n"
-		"Driver_GetName(Driver self) -> char\n"
+		"Driver_GetName(Driver self) -> char const *\n"
 		"\n"
 		"const char*\n"
 		"OGR_Dr_GetName(OGRSFDriverH hDriver)\n"
 		"\n"
-		"Fetch name of driver (file format). This name should be relatively\n"
-		"short (10-40 characters), and should reflect the underlying file\n"
-		"format. For instance \"ESRI Shapefile\".\n"
+		"Fetch name of driver (file format).\n"
+		"\n"
+		"This name should be relatively short (10-40 characters), and should\n"
+		"reflect the underlying file format. For instance \"ESRI Shapefile\".\n"
 		"\n"
 		"This function is the same as the C++ method OGRSFDriver::GetName().\n"
 		"\n"
 		"Parameters:\n"
 		"-----------\n"
 		"\n"
-		"hDriver:  handle to the the driver to get the name from.\n"
+		"hDriver:  handle to the driver to get the name from.\n"
 		"\n"
 		"driver name. This is an internal string and should not be modified or\n"
 		"freed. \n"
@@ -23722,7 +26304,7 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"Driver_Register", _wrap_Driver_Register, METH_VARARGS, (char *)"Driver_Register(Driver self)"},
 	 { (char *)"Driver_Deregister", _wrap_Driver_Deregister, METH_VARARGS, (char *)"Driver_Deregister(Driver self)"},
 	 { (char *)"Driver_swigregister", Driver_swigregister, METH_VARARGS, NULL},
-	 { (char *)"DataSource_name_get", _wrap_DataSource_name_get, METH_VARARGS, (char *)"DataSource_name_get(DataSource self) -> char"},
+	 { (char *)"DataSource_name_get", _wrap_DataSource_name_get, METH_VARARGS, (char *)"DataSource_name_get(DataSource self) -> char const *"},
 	 { (char *)"delete_DataSource", _wrap_delete_DataSource, METH_VARARGS, (char *)"delete_DataSource(DataSource self)"},
 	 { (char *)"DataSource_GetRefCount", _wrap_DataSource_GetRefCount, METH_VARARGS, (char *)"\n"
 		"DataSource_GetRefCount(DataSource self) -> int\n"
@@ -23744,8 +26326,7 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"Get the number of layers in this data source.\n"
 		"\n"
-		"This function is the same as the C++ method\n"
-		"OGRDataSource::GetLayerCount().\n"
+		"Deprecated Use GDALDatasetGetLayerCount() in GDAL 2.0\n"
 		"\n"
 		"Parameters:\n"
 		"-----------\n"
@@ -23763,7 +26344,11 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"Returns the driver that the dataset was opened with.\n"
 		"\n"
-		"This method is the same as the C++ method OGRDataSource::GetDriver()\n"
+		"NOTE: Starting with GDAL 2.0, it is *NOT* safe to cast the returned\n"
+		"handle to OGRSFDriver*. If a C++ object is needed, the handle should\n"
+		"be cast to GDALDriver*.\n"
+		"\n"
+		"Deprecated Use GDALGetDatasetDriver() in GDAL 2.0\n"
 		"\n"
 		"Parameters:\n"
 		"-----------\n"
@@ -23774,7 +26359,7 @@ static PyMethodDef SwigMethods[] = {
 		"the OGRSFDriverManager. \n"
 		""},
 	 { (char *)"DataSource_GetName", _wrap_DataSource_GetName, METH_VARARGS, (char *)"\n"
-		"DataSource_GetName(DataSource self) -> char\n"
+		"DataSource_GetName(DataSource self) -> char const *\n"
 		"\n"
 		"const char*\n"
 		"OGR_DS_GetName(OGRDataSourceH hDS)\n"
@@ -23786,7 +26371,7 @@ static PyMethodDef SwigMethods[] = {
 		"need not be exactly the same string that was used to open the data\n"
 		"source. Normally this is a filename.\n"
 		"\n"
-		"This function is the same as the C++ method OGRDataSource::GetName().\n"
+		"Deprecated Use GDALGetDescription() in GDAL 2.0\n"
 		"\n"
 		"Parameters:\n"
 		"-----------\n"
@@ -23807,8 +26392,7 @@ static PyMethodDef SwigMethods[] = {
 		"If this method is supported the ODsCDeleteLayer capability will test\n"
 		"TRUE on the OGRDataSource.\n"
 		"\n"
-		"This method is the same as the C++ method\n"
-		"OGRDataSource::DeleteLayer().\n"
+		"Deprecated Use GDALDatasetDeleteLayer() in GDAL 2.0\n"
 		"\n"
 		"Parameters:\n"
 		"-----------\n"
@@ -23824,41 +26408,12 @@ static PyMethodDef SwigMethods[] = {
 		"DataSource_SyncToDisk(DataSource self) -> OGRErr\n"
 		"\n"
 		"OGRErr\n"
-		"OGR_DS_SyncToDisk(OGRDataSourceH hDS)\n"
-		"\n"
-		"Flush pending changes to disk.\n"
-		"\n"
-		"This call is intended to force the datasource to flush any pending\n"
-		"writes to disk, and leave the disk file in a consistent state. It\n"
-		"would not normally have any effect on read-only datasources.\n"
-		"\n"
-		"Some data sources do not implement this method, and will still return\n"
-		"OGRERR_NONE. An error is only returned if an error occurs while\n"
-		"attempting to flush to disk.\n"
-		"\n"
-		"The default implementation of this method just calls the SyncToDisk()\n"
-		"method on each of the layers. Conceptionally, calling SyncToDisk() on\n"
-		"a datasource should include any work that might be accomplished by\n"
-		"calling SyncToDisk() on layers in that data source.\n"
-		"\n"
-		"In any event, you should always close any opened datasource with\n"
-		"OGR_DS_Destroy() that will ensure all data is correctly flushed.\n"
-		"\n"
-		"This method is the same as the C++ method OGRDataSource::SyncToDisk()\n"
-		"\n"
-		"Parameters:\n"
-		"-----------\n"
-		"\n"
-		"hDS:  handle to the data source\n"
-		"\n"
-		"OGRERR_NONE if no error occurs (even if nothing is done) or an error\n"
-		"code. \n"
+		"OGR_DS_SyncToDisk(OGRDataSourceH hDS) \n"
 		""},
 	 { (char *)"DataSource_FlushCache", _wrap_DataSource_FlushCache, METH_VARARGS, (char *)"DataSource_FlushCache(DataSource self)"},
 	 { (char *)"DataSource_CreateLayer", (PyCFunction) _wrap_DataSource_CreateLayer, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"DataSource_CreateLayer(DataSource self, char name, SpatialReference srs = None, \n"
-		"    OGRwkbGeometryType geom_type = wkbUnknown, \n"
-		"    char options = None) -> Layer\n"
+		"DataSource_CreateLayer(DataSource self, char const * name, SpatialReference srs=None, OGRwkbGeometryType geom_type=wkbUnknown, \n"
+		"    char ** options=None) -> Layer\n"
 		"\n"
 		"OGRLayerH\n"
 		"OGR_DS_CreateLayer(OGRDataSourceH hDS, const char *pszName,\n"
@@ -23872,8 +26427,7 @@ static PyMethodDef SwigMethods[] = {
 		"creation options. These options are normally documented in the format\n"
 		"specific documentation.\n"
 		"\n"
-		"This function is the same as the C++ method\n"
-		"OGRDataSource::CreateLayer().\n"
+		"Deprecated Use GDALDatasetCreateLayer() in GDAL 2.0\n"
 		"\n"
 		"Parameters:\n"
 		"-----------\n"
@@ -23891,13 +26445,13 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"papszOptions:  a StringList of name=value options. Options are driver\n"
 		"specific, and driver information can be found at the following\n"
-		"url:http://www.gdal.org/ogr/ogr_formats.html\n"
+		"url:http://www.gdal.org/ogr_formats.html\n"
 		"\n"
 		"NULL is returned on failure, or a new OGRLayer handle on success.\n"
 		"Example: \n"
 		""},
 	 { (char *)"DataSource_CopyLayer", (PyCFunction) _wrap_DataSource_CopyLayer, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"DataSource_CopyLayer(DataSource self, Layer src_layer, char new_name, char options = None) -> Layer\n"
+		"DataSource_CopyLayer(DataSource self, Layer src_layer, char const * new_name, char ** options=None) -> Layer\n"
 		"\n"
 		"OGRLayerH\n"
 		"OGR_DS_CopyLayer(OGRDataSourceH hDS, OGRLayerH hSrcLayer, const char\n"
@@ -23912,7 +26466,7 @@ static PyMethodDef SwigMethods[] = {
 		"specific documentation. The source layer may come from another\n"
 		"dataset.\n"
 		"\n"
-		"This function is the same as the C++ method OGRDataSource::CopyLayer\n"
+		"Deprecated Use GDALDatasetCopyLayer() in GDAL 2.0\n"
 		"\n"
 		"Parameters:\n"
 		"-----------\n"
@@ -23928,9 +26482,9 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"an handle to the layer, or NULL if an error occurs. \n"
 		""},
-	 { (char *)"DataSource_GetLayerByIndex", _wrap_DataSource_GetLayerByIndex, METH_VARARGS, (char *)"DataSource_GetLayerByIndex(DataSource self, int index = 0) -> Layer"},
+	 { (char *)"DataSource_GetLayerByIndex", _wrap_DataSource_GetLayerByIndex, METH_VARARGS, (char *)"DataSource_GetLayerByIndex(DataSource self, int index=0) -> Layer"},
 	 { (char *)"DataSource_GetLayerByName", _wrap_DataSource_GetLayerByName, METH_VARARGS, (char *)"\n"
-		"DataSource_GetLayerByName(DataSource self, char layer_name) -> Layer\n"
+		"DataSource_GetLayerByName(DataSource self, char const * layer_name) -> Layer\n"
 		"\n"
 		"OGRLayerH\n"
 		"OGR_DS_GetLayerByName(OGRDataSourceH hDS, const char *pszName)\n"
@@ -23940,8 +26494,7 @@ static PyMethodDef SwigMethods[] = {
 		"The returned layer remains owned by the OGRDataSource and should not\n"
 		"be deleted by the application.\n"
 		"\n"
-		"This function is the same as the C++ method\n"
-		"OGRDataSource::GetLayerByName().\n"
+		"Deprecated Use GDALDatasetGetLayerByName() in GDAL 2.0\n"
 		"\n"
 		"Parameters:\n"
 		"-----------\n"
@@ -23954,7 +26507,7 @@ static PyMethodDef SwigMethods[] = {
 		"occurs. \n"
 		""},
 	 { (char *)"DataSource_TestCapability", _wrap_DataSource_TestCapability, METH_VARARGS, (char *)"\n"
-		"DataSource_TestCapability(DataSource self, char cap) -> bool\n"
+		"DataSource_TestCapability(DataSource self, char const * cap) -> bool\n"
 		"\n"
 		"int\n"
 		"OGR_DS_TestCapability(OGRDataSourceH hDS, const char *pszCap)\n"
@@ -23967,11 +26520,19 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"ODsCCreateLayer: True if this datasource can create new layers.\n"
 		"\n"
+		"ODsCDeleteLayer: True if this datasource can delete existing layers.\n"
+		"\n"
+		"ODsCCreateGeomFieldAfterCreateLayer: True if the layers of this\n"
+		"datasource support CreateGeomField() just after layer creation.\n"
+		"\n"
+		"ODsCCurveGeometries: True if this datasource supports writing curve\n"
+		"geometries. (GDAL 2.0). In that case, OLCCurveGeometries must also be\n"
+		"declared in layers of that dataset.\n"
+		"\n"
 		"The #define macro forms of the capability names should be used in\n"
-		"preference to the strings themselves to avoid mispelling.\n"
+		"preference to the strings themselves to avoid misspelling.\n"
 		"\n"
-		"This function is the same as the C++ method\n"
-		"OGRDataSource::TestCapability().\n"
+		"Deprecated Use GDALDatasetTestCapability() in GDAL 2.0\n"
 		"\n"
 		"Parameters:\n"
 		"-----------\n"
@@ -23983,8 +26544,7 @@ static PyMethodDef SwigMethods[] = {
 		"TRUE if capability available otherwise FALSE. \n"
 		""},
 	 { (char *)"DataSource_ExecuteSQL", (PyCFunction) _wrap_DataSource_ExecuteSQL, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"DataSource_ExecuteSQL(DataSource self, char statement, Geometry spatialFilter = None, \n"
-		"    char dialect = \"\") -> Layer\n"
+		"DataSource_ExecuteSQL(DataSource self, char const * statement, Geometry spatialFilter=None, char const * dialect=\"\") -> Layer\n"
 		"\n"
 		"OGRLayerH\n"
 		"OGR_DS_ExecuteSQL(OGRDataSourceH hDS, const char *pszStatement,\n"
@@ -24000,11 +26560,12 @@ static PyMethodDef SwigMethods[] = {
 		"(destroyed).\n"
 		"\n"
 		"For more information on the SQL dialect supported internally by OGR\n"
-		"review theOGR SQL document. Some drivers (ie. Oracle and PostGIS) pass\n"
-		"the SQL directly through to the underlying RDBMS.\n"
+		"review theOGR SQL document. Some drivers (i.e. Oracle and PostGIS)\n"
+		"pass the SQL directly through to the underlying RDBMS.\n"
 		"\n"
-		"This function is the same as the C++ method\n"
-		"OGRDataSource::ExecuteSQL();\n"
+		"Starting with OGR 1.10, theSQLITE dialect can also be used.\n"
+		"\n"
+		"Deprecated Use GDALDatasetExecuteSQL() in GDAL 2.0\n"
 		"\n"
 		"Parameters:\n"
 		"-----------\n"
@@ -24019,7 +26580,8 @@ static PyMethodDef SwigMethods[] = {
 		"pszDialect:  allows control of the statement dialect. If set to NULL,\n"
 		"the OGR SQL engine will be used, except for RDBMS drivers that will\n"
 		"use their dedicated SQL engine, unless OGRSQL is explicitly passed as\n"
-		"the dialect.\n"
+		"the dialect. Starting with OGR 1.10, the SQLITE dialect can also be\n"
+		"used.\n"
 		"\n"
 		"an handle to a OGRLayer containing the results of the query.\n"
 		"Deallocate with OGR_DS_ReleaseResultSet(). \n"
@@ -24037,8 +26599,7 @@ static PyMethodDef SwigMethods[] = {
 		"deallocate a results set before destroying the OGRDataSource may cause\n"
 		"errors.\n"
 		"\n"
-		"This function is the same as the C++ method\n"
-		"OGRDataSource::ReleaseResultSet().\n"
+		"Deprecated Use GDALDatasetReleaseResultSet() in GDAL 2.0\n"
 		"\n"
 		"Parameters:\n"
 		"-----------\n"
@@ -24061,7 +26622,7 @@ static PyMethodDef SwigMethods[] = {
 		"OGR_DS_SetStyleTable(OGRDataSourceH hDS, OGRStyleTableH hStyleTable)\n"
 		"\n"
 		""},
-	 { (char *)"DataSource_StartTransaction", (PyCFunction) _wrap_DataSource_StartTransaction, METH_VARARGS | METH_KEYWORDS, (char *)"DataSource_StartTransaction(DataSource self, int force = True) -> OGRErr"},
+	 { (char *)"DataSource_StartTransaction", (PyCFunction) _wrap_DataSource_StartTransaction, METH_VARARGS | METH_KEYWORDS, (char *)"DataSource_StartTransaction(DataSource self, int force=False) -> OGRErr"},
 	 { (char *)"DataSource_CommitTransaction", _wrap_DataSource_CommitTransaction, METH_VARARGS, (char *)"DataSource_CommitTransaction(DataSource self) -> OGRErr"},
 	 { (char *)"DataSource_RollbackTransaction", _wrap_DataSource_RollbackTransaction, METH_VARARGS, (char *)"DataSource_RollbackTransaction(DataSource self) -> OGRErr"},
 	 { (char *)"DataSource_swigregister", DataSource_swigregister, METH_VARARGS, NULL},
@@ -24113,8 +26674,7 @@ static PyMethodDef SwigMethods[] = {
 		""},
 	 { (char *)"Layer_SetSpatialFilterRect", _wrap_Layer_SetSpatialFilterRect, METH_VARARGS, (char *)"\n"
 		"SetSpatialFilterRect(double minx, double miny, double maxx, double maxy)\n"
-		"Layer_SetSpatialFilterRect(Layer self, int iGeomField, double minx, double miny, \n"
-		"    double maxx, double maxy)\n"
+		"Layer_SetSpatialFilterRect(Layer self, int iGeomField, double minx, double miny, double maxx, double maxy)\n"
 		"\n"
 		"void\n"
 		"OGR_L_SetSpatialFilterRect(OGRLayerH hLayer, double dfMinX, double\n"
@@ -24173,7 +26733,7 @@ static PyMethodDef SwigMethods[] = {
 		"an handle to the spatial filter geometry. \n"
 		""},
 	 { (char *)"Layer_SetAttributeFilter", _wrap_Layer_SetAttributeFilter, METH_VARARGS, (char *)"\n"
-		"Layer_SetAttributeFilter(Layer self, char filter_string) -> OGRErr\n"
+		"Layer_SetAttributeFilter(Layer self, char * filter_string) -> OGRErr\n"
 		"\n"
 		"OGRErr\n"
 		"OGR_L_SetAttributeFilter(OGRLayerH hLayer, const char *pszQuery)\n"
@@ -24228,7 +26788,7 @@ static PyMethodDef SwigMethods[] = {
 		"hLayer:  handle to the layer on which features are read. \n"
 		""},
 	 { (char *)"Layer_GetName", _wrap_Layer_GetName, METH_VARARGS, (char *)"\n"
-		"Layer_GetName(Layer self) -> char\n"
+		"Layer_GetName(Layer self) -> char const *\n"
 		"\n"
 		"const char* OGR_L_GetName(OGRLayerH\n"
 		"hLayer)\n"
@@ -24264,6 +26824,12 @@ static PyMethodDef SwigMethods[] = {
 		"calling OGR_L_GetGeomType() directly can avoid lengthy layer\n"
 		"definition initialization.\n"
 		"\n"
+		"For layers with multiple geometry fields, this method only returns the\n"
+		"geometry type of the first geometry column. For other columns, use\n"
+		"OGR_GFld_GetType(OGR_FD_GetGeomFieldDefn(OGR_L_GetLayerDefn(hLayer),\n"
+		"i)). For layers without any geometry field, this method returns\n"
+		"wkbNone.\n"
+		"\n"
 		"This function is the same as the C++ method OGRLayer::GetGeomType().\n"
 		"\n"
 		"Parameters:\n"
@@ -24276,7 +26842,7 @@ static PyMethodDef SwigMethods[] = {
 		"OGR 1.8.0 \n"
 		""},
 	 { (char *)"Layer_GetGeometryColumn", _wrap_Layer_GetGeometryColumn, METH_VARARGS, (char *)"\n"
-		"Layer_GetGeometryColumn(Layer self) -> char\n"
+		"Layer_GetGeometryColumn(Layer self) -> char const *\n"
 		"\n"
 		"const char*\n"
 		"OGR_L_GetGeometryColumn(OGRLayerH hLayer)\n"
@@ -24284,6 +26850,11 @@ static PyMethodDef SwigMethods[] = {
 		"This method returns the name of the underlying database column being\n"
 		"used as the geometry column, or \"\" if not supported.\n"
 		"\n"
+		"For layers with multiple geometry fields, this method only returns the\n"
+		"geometry type of the first geometry column. For other columns, use OGR\n"
+		"_GFld_GetNameRef(OGR_FD_GetGeomFieldDefn(OGR_L_GetLayerDefn(hLayer),\n"
+		"i)).\n"
+		"\n"
 		"This method is the same as the C++ method\n"
 		"OGRLayer::GetGeometryColumn()\n"
 		"\n"
@@ -24295,7 +26866,7 @@ static PyMethodDef SwigMethods[] = {
 		"geometry column name. \n"
 		""},
 	 { (char *)"Layer_GetFIDColumn", _wrap_Layer_GetFIDColumn, METH_VARARGS, (char *)"\n"
-		"Layer_GetFIDColumn(Layer self) -> char\n"
+		"Layer_GetFIDColumn(Layer self) -> char const *\n"
 		"\n"
 		"const char*\n"
 		"OGR_L_GetFIDColumn(OGRLayerH hLayer)\n"
@@ -24316,13 +26887,15 @@ static PyMethodDef SwigMethods[] = {
 		"Layer_GetFeature(Layer self, GIntBig fid) -> Feature\n"
 		"\n"
 		"OGRFeatureH\n"
-		"OGR_L_GetFeature(OGRLayerH hLayer, long nFeatureId)\n"
+		"OGR_L_GetFeature(OGRLayerH hLayer, GIntBig nFeatureId)\n"
 		"\n"
 		"Fetch a feature by its identifier.\n"
 		"\n"
 		"This function will attempt to read the identified feature. The nFID\n"
 		"value cannot be OGRNullFID. Success or failure of this operation is\n"
-		"unaffected by the spatial or attribute filters.\n"
+		"unaffected by the spatial or attribute filters (and specialized\n"
+		"implementations in drivers should make sure that they do not take into\n"
+		"account spatial or attribute filters).\n"
 		"\n"
 		"If this function returns a non-NULL feature, it is guaranteed that its\n"
 		"feature id ( OGR_F_GetFID()) will be the same as nFID.\n"
@@ -24333,8 +26906,8 @@ static PyMethodDef SwigMethods[] = {
 		"fallback implementation just scans all the features in the layer\n"
 		"looking for the desired feature.\n"
 		"\n"
-		"Sequential reads are generally considered interrupted by a\n"
-		"OGR_L_GetFeature() call.\n"
+		"Sequential reads (with OGR_L_GetNextFeature()) are generally\n"
+		"considered interrupted by a OGR_L_GetFeature() call.\n"
 		"\n"
 		"The returned feature should be free with OGR_F_Destroy().\n"
 		"\n"
@@ -24357,10 +26930,10 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"Fetch the next available feature from this layer.\n"
 		"\n"
-		"The returned feature becomes the responsiblity of the caller to delete\n"
-		"with OGR_F_Destroy(). It is critical that all features associated with\n"
-		"an OGRLayer (more specifically an OGRFeatureDefn) be deleted before\n"
-		"that layer/datasource is deleted.\n"
+		"The returned feature becomes the responsibility of the caller to\n"
+		"delete with OGR_F_Destroy(). It is critical that all features\n"
+		"associated with an OGRLayer (more specifically an OGRFeatureDefn) be\n"
+		"deleted before that layer/datasource is deleted.\n"
 		"\n"
 		"Only features matching the current spatial filter (set with\n"
 		"SetSpatialFilter()) will be returned.\n"
@@ -24369,6 +26942,16 @@ static PyMethodDef SwigMethods[] = {
 		"The OGR_L_ResetReading() function can be used to start at the\n"
 		"beginning again.\n"
 		"\n"
+		"Features returned by OGR_GetNextFeature() may or may not be affected\n"
+		"by concurrent modifications depending on drivers. A guaranteed way of\n"
+		"seeing modifications in effect is to call OGR_L_ResetReading() on\n"
+		"layers where OGR_GetNextFeature() has been called, before reading\n"
+		"again. Structural changes in layers (field addition, deletion, ...)\n"
+		"when a read is in progress may or may not be possible depending on\n"
+		"drivers. If a transaction is committed/aborted, the current sequential\n"
+		"reading may or may not be valid after that operation and a call to\n"
+		"OGR_L_ResetReading() might be needed.\n"
+		"\n"
 		"This function is the same as the C++ method\n"
 		"OGRLayer::GetNextFeature().\n"
 		"\n"
@@ -24383,7 +26966,7 @@ static PyMethodDef SwigMethods[] = {
 		"Layer_SetNextByIndex(Layer self, GIntBig new_index) -> OGRErr\n"
 		"\n"
 		"OGRErr\n"
-		"OGR_L_SetNextByIndex(OGRLayerH hLayer, long nIndex)\n"
+		"OGR_L_SetNextByIndex(OGRLayerH hLayer, GIntBig nIndex)\n"
 		"\n"
 		"Move read cursor to the nIndex'th feature in the current resultset.\n"
 		"\n"
@@ -24437,7 +27020,8 @@ static PyMethodDef SwigMethods[] = {
 		"hFeat:  the feature to write.\n"
 		"\n"
 		"OGRERR_NONE if the operation works, otherwise an appropriate error\n"
-		"code. \n"
+		"code (e.g OGRERR_NON_EXISTING_FEATURE if the feature does not exist).\n"
+		"\n"
 		""},
 	 { (char *)"Layer_CreateFeature", _wrap_Layer_CreateFeature, METH_VARARGS, (char *)"\n"
 		"Layer_CreateFeature(Layer self, Feature feature) -> OGRErr\n"
@@ -24469,7 +27053,7 @@ static PyMethodDef SwigMethods[] = {
 		"Layer_DeleteFeature(Layer self, GIntBig fid) -> OGRErr\n"
 		"\n"
 		"OGRErr\n"
-		"OGR_L_DeleteFeature(OGRLayerH hDS, long nFID)\n"
+		"OGR_L_DeleteFeature(OGRLayerH hLayer, GIntBig nFID)\n"
 		"\n"
 		"Delete feature from layer.\n"
 		"\n"
@@ -24488,13 +27072,15 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"nFID:  the feature id to be deleted from the layer\n"
 		"\n"
-		"OGRERR_NONE on success. \n"
+		"OGRERR_NONE if the operation works, otherwise an appropriate error\n"
+		"code (e.g OGRERR_NON_EXISTING_FEATURE if the feature does not exist).\n"
+		"\n"
 		""},
 	 { (char *)"Layer_SyncToDisk", _wrap_Layer_SyncToDisk, METH_VARARGS, (char *)"\n"
 		"Layer_SyncToDisk(Layer self) -> OGRErr\n"
 		"\n"
 		"OGRErr OGR_L_SyncToDisk(OGRLayerH\n"
-		"hDS)\n"
+		"hLayer)\n"
 		"\n"
 		"Flush pending changes to disk.\n"
 		"\n"
@@ -24542,9 +27128,9 @@ static PyMethodDef SwigMethods[] = {
 		"an handle to the feature definition. \n"
 		""},
 	 { (char *)"Layer_GetFeatureCount", (PyCFunction) _wrap_Layer_GetFeatureCount, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Layer_GetFeatureCount(Layer self, int force = 1) -> GIntBig\n"
+		"Layer_GetFeatureCount(Layer self, int force=1) -> GIntBig\n"
 		"\n"
-		"int\n"
+		"GIntBig\n"
 		"OGR_L_GetFeatureCount(OGRLayerH hLayer, int bForce)\n"
 		"\n"
 		"Fetch the feature count in this layer.\n"
@@ -24563,6 +27149,8 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"This function is the same as the CPP OGRLayer::GetFeatureCount().\n"
 		"\n"
+		"Note: since GDAL 2.0, this method returns a GIntBig (previously a int)\n"
+		"\n"
 		"Parameters:\n"
 		"-----------\n"
 		"\n"
@@ -24574,8 +27162,7 @@ static PyMethodDef SwigMethods[] = {
 		"feature count, -1 if count not known. \n"
 		""},
 	 { (char *)"Layer_GetExtent", (PyCFunction) _wrap_Layer_GetExtent, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Layer_GetExtent(Layer self, int force = 1, int can_return_null = 0, \n"
-		"    int geom_field = 0)\n"
+		"Layer_GetExtent(Layer self, int force=1, int can_return_null=0, int geom_field=0)\n"
 		"\n"
 		"OGRErr OGR_L_GetExtent(OGRLayerH\n"
 		"hLayer, OGREnvelope *psExtent, int bForce)\n"
@@ -24613,7 +27200,7 @@ static PyMethodDef SwigMethods[] = {
 		"OGRERR_NONE on success, OGRERR_FAILURE if extent not known. \n"
 		""},
 	 { (char *)"Layer_TestCapability", _wrap_Layer_TestCapability, METH_VARARGS, (char *)"\n"
-		"Layer_TestCapability(Layer self, char cap) -> bool\n"
+		"Layer_TestCapability(Layer self, char const * cap) -> bool\n"
 		"\n"
 		"int\n"
 		"OGR_L_TestCapability(OGRLayerH hLayer, const char *pszCap)\n"
@@ -24648,12 +27235,12 @@ static PyMethodDef SwigMethods[] = {
 		"features in this layer.\n"
 		"\n"
 		"OLCFastFeatureCount / \"FastFeatureCount\": TRUE if this layer can\n"
-		"return a feature count (via OGR_L_GetFeatureCount()) efficiently ...\n"
-		"ie. without counting the features. In some cases this will return TRUE\n"
+		"return a feature count (via OGR_L_GetFeatureCount()) efficiently, i.e.\n"
+		"without counting the features. In some cases this will return TRUE\n"
 		"until a spatial filter is installed after which it will return FALSE.\n"
 		"\n"
 		"OLCFastGetExtent / \"FastGetExtent\": TRUE if this layer can return\n"
-		"its data extent (via OGR_L_GetExtent()) efficiently ... ie. without\n"
+		"its data extent (via OGR_L_GetExtent()) efficiently, i.e. without\n"
 		"scanning all the features. In some cases this will return TRUE until a\n"
 		"spatial filter is installed after which it will return FALSE.\n"
 		"\n"
@@ -24663,6 +27250,10 @@ static PyMethodDef SwigMethods[] = {
 		"OLCCreateField / \"CreateField\": TRUE if this layer can create new\n"
 		"fields on the current layer using CreateField(), otherwise FALSE.\n"
 		"\n"
+		"OLCCreateGeomField / \"CreateGeomField\": (GDAL >= 1.11) TRUE if this\n"
+		"layer can create new geometry fields on the current layer using\n"
+		"CreateGeomField(), otherwise FALSE.\n"
+		"\n"
 		"OLCDeleteField / \"DeleteField\": TRUE if this layer can delete\n"
 		"existing fields on the current layer using DeleteField(), otherwise\n"
 		"FALSE.\n"
@@ -24686,6 +27277,9 @@ static PyMethodDef SwigMethods[] = {
 		"CommitTransaction() and RollbackTransaction() methods work in a\n"
 		"meaningful way, otherwise FALSE.\n"
 		"\n"
+		"OLCCurveGeometries / \"CurveGeometries\": TRUE if this layer supports\n"
+		"writing curve geometries or may return such geometries. (GDAL 2.0).\n"
+		"\n"
 		"This function is the same as the C++ method\n"
 		"OGRLayer::TestCapability().\n"
 		"\n"
@@ -24697,10 +27291,10 @@ static PyMethodDef SwigMethods[] = {
 		"pszCap:  the name of the capability to test.\n"
 		"\n"
 		"TRUE if the layer has the requested capability, or FALSE otherwise.\n"
-		"OGRLayers will return FALSE for any unrecognised capabilities. \n"
+		"OGRLayers will return FALSE for any unrecognized capabilities. \n"
 		""},
 	 { (char *)"Layer_CreateField", (PyCFunction) _wrap_Layer_CreateField, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Layer_CreateField(Layer self, FieldDefn field_def, int approx_ok = 1) -> OGRErr\n"
+		"Layer_CreateField(Layer self, FieldDefn field_def, int approx_ok=1) -> OGRErr\n"
 		"\n"
 		"OGRErr\n"
 		"OGR_L_CreateField(OGRLayerH hLayer, OGRFieldDefnH hField, int\n"
@@ -24714,15 +27308,19 @@ static PyMethodDef SwigMethods[] = {
 		"directly.\n"
 		"\n"
 		"This function should not be called while there are feature objects in\n"
-		"existance that were obtained or created with the previous layer\n"
+		"existence that were obtained or created with the previous layer\n"
 		"definition.\n"
 		"\n"
 		"Not all drivers support this function. You can query a layer to check\n"
 		"if it supports it with the OLCCreateField capability. Some drivers may\n"
 		"only support this method while there are still no features in the\n"
-		"layer. When it is supported, the existings features of the backing\n"
+		"layer. When it is supported, the existing features of the backing\n"
 		"file/database should be updated accordingly.\n"
 		"\n"
+		"Drivers may or may not support not-null constraints. If they support\n"
+		"creating fields with not-null constraints, this is generally before\n"
+		"creating any feature to the layer.\n"
+		"\n"
 		"This function is the same as the C++ method OGRLayer::CreateField().\n"
 		"\n"
 		"Parameters:\n"
@@ -24751,13 +27349,13 @@ static PyMethodDef SwigMethods[] = {
 		"used by a layer directly.\n"
 		"\n"
 		"This function should not be called while there are feature objects in\n"
-		"existance that were obtained or created with the previous layer\n"
+		"existence that were obtained or created with the previous layer\n"
 		"definition.\n"
 		"\n"
 		"Not all drivers support this function. You can query a layer to check\n"
 		"if it supports it with the OLCDeleteField capability. Some drivers may\n"
 		"only support this method while there are still no features in the\n"
-		"layer. When it is supported, the existings features of the backing\n"
+		"layer. When it is supported, the existing features of the backing\n"
 		"file/database should be updated accordingly.\n"
 		"\n"
 		"This function is the same as the C++ method OGRLayer::DeleteField().\n"
@@ -24782,7 +27380,7 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"Reorder an existing field on a layer.\n"
 		"\n"
-		"This function is a conveniency wrapper of OGR_L_ReorderFields()\n"
+		"This function is a convenience wrapper of OGR_L_ReorderFields()\n"
 		"dedicated to move a single field.\n"
 		"\n"
 		"You must use this to reorder existing fields on a real layer.\n"
@@ -24791,7 +27389,7 @@ static PyMethodDef SwigMethods[] = {
 		"OGRFeatureDefn used by a layer directly.\n"
 		"\n"
 		"This function should not be called while there are feature objects in\n"
-		"existance that were obtained or created with the previous layer\n"
+		"existence that were obtained or created with the previous layer\n"
 		"definition.\n"
 		"\n"
 		"The field definition that was at initial position iOldFieldPos will be\n"
@@ -24805,7 +27403,7 @@ static PyMethodDef SwigMethods[] = {
 		"Not all drivers support this function. You can query a layer to check\n"
 		"if it supports it with the OLCReorderFields capability. Some drivers\n"
 		"may only support this method while there are still no features in the\n"
-		"layer. When it is supported, the existings features of the backing\n"
+		"layer. When it is supported, the existing features of the backing\n"
 		"file/database should be updated accordingly.\n"
 		"\n"
 		"This function is the same as the C++ method OGRLayer::ReorderField().\n"
@@ -24839,7 +27437,7 @@ static PyMethodDef SwigMethods[] = {
 		"OGRFeatureDefn used by a layer directly.\n"
 		"\n"
 		"This function should not be called while there are feature objects in\n"
-		"existance that were obtained or created with the previous layer\n"
+		"existence that were obtained or created with the previous layer\n"
 		"definition.\n"
 		"\n"
 		"panMap is such that,for each field definition at position i after\n"
@@ -24852,7 +27450,7 @@ static PyMethodDef SwigMethods[] = {
 		"Not all drivers support this function. You can query a layer to check\n"
 		"if it supports it with the OLCReorderFields capability. Some drivers\n"
 		"may only support this method while there are still no features in the\n"
-		"layer. When it is supported, the existings features of the backing\n"
+		"layer. When it is supported, the existing features of the backing\n"
 		"file/database should be updated accordingly.\n"
 		"\n"
 		"This function is the same as the C++ method OGRLayer::ReorderFields().\n"
@@ -24860,222 +27458,736 @@ static PyMethodDef SwigMethods[] = {
 		"Parameters:\n"
 		"-----------\n"
 		"\n"
-		"hLayer:  handle to the layer.\n"
-		"\n"
-		"panMap:  an array of GetLayerDefn()->GetFieldCount() elements which is\n"
-		"a permutation of [0, GetLayerDefn()->GetFieldCount()-1].\n"
-		"\n"
-		"OGRERR_NONE on success.\n"
+		"hLayer:  handle to the layer.\n"
+		"\n"
+		"panMap:  an array of GetLayerDefn()-> OGRFeatureDefn::GetFieldCount()\n"
+		"elements which is a permutation of [0, GetLayerDefn()->\n"
+		"OGRFeatureDefn::GetFieldCount()-1].\n"
+		"\n"
+		"OGRERR_NONE on success.\n"
+		"\n"
+		"OGR 1.9.0 \n"
+		""},
+	 { (char *)"Layer_AlterFieldDefn", _wrap_Layer_AlterFieldDefn, METH_VARARGS, (char *)"\n"
+		"Layer_AlterFieldDefn(Layer self, int iField, FieldDefn field_def, int nFlags) -> OGRErr\n"
+		"\n"
+		"OGRErr\n"
+		"OGR_L_AlterFieldDefn(OGRLayerH hLayer, int iField, OGRFieldDefnH\n"
+		"hNewFieldDefn, int nFlags)\n"
+		"\n"
+		"Alter the definition of an existing field on a layer.\n"
+		"\n"
+		"You must use this to alter the definition of an existing field of a\n"
+		"real layer. Internally the OGRFeatureDefn for the layer will be\n"
+		"updated to reflect the altered field. Applications should never modify\n"
+		"the OGRFeatureDefn used by a layer directly.\n"
+		"\n"
+		"This function should not be called while there are feature objects in\n"
+		"existence that were obtained or created with the previous layer\n"
+		"definition.\n"
+		"\n"
+		"Not all drivers support this function. You can query a layer to check\n"
+		"if it supports it with the OLCAlterFieldDefn capability. Some drivers\n"
+		"may only support this method while there are still no features in the\n"
+		"layer. When it is supported, the existing features of the backing\n"
+		"file/database should be updated accordingly. Some drivers might also\n"
+		"not support all update flags.\n"
+		"\n"
+		"This function is the same as the C++ method\n"
+		"OGRLayer::AlterFieldDefn().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hLayer:  handle to the layer.\n"
+		"\n"
+		"iField:  index of the field whose definition must be altered.\n"
+		"\n"
+		"hNewFieldDefn:  new field definition\n"
+		"\n"
+		"nFlags:  combination of ALTER_NAME_FLAG, ALTER_TYPE_FLAG,\n"
+		"ALTER_WIDTH_PRECISION_FLAG, ALTER_NULLABLE_FLAG and ALTER_DEFAULT_FLAG\n"
+		"to indicate which of the name and/or type and/or width and precision\n"
+		"fields and/or nullability from the new field definition must be taken\n"
+		"into account.\n"
+		"\n"
+		"OGRERR_NONE on success.\n"
+		"\n"
+		"OGR 1.9.0 \n"
+		""},
+	 { (char *)"Layer_CreateGeomField", (PyCFunction) _wrap_Layer_CreateGeomField, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
+		"Layer_CreateGeomField(Layer self, GeomFieldDefn field_def, int approx_ok=1) -> OGRErr\n"
+		"\n"
+		"OGRErr\n"
+		"OGR_L_CreateGeomField(OGRLayerH hLayer, OGRGeomFieldDefnH hField, int\n"
+		"bApproxOK)\n"
+		"\n"
+		"Create a new geometry field on a layer.\n"
+		"\n"
+		"You must use this to create new geometry fields on a real layer.\n"
+		"Internally the OGRFeatureDefn for the layer will be updated to reflect\n"
+		"the new field. Applications should never modify the OGRFeatureDefn\n"
+		"used by a layer directly.\n"
+		"\n"
+		"This function should not be called while there are feature objects in\n"
+		"existence that were obtained or created with the previous layer\n"
+		"definition.\n"
+		"\n"
+		"Not all drivers support this function. You can query a layer to check\n"
+		"if it supports it with the OLCCreateField capability. Some drivers may\n"
+		"only support this method while there are still no features in the\n"
+		"layer. When it is supported, the existing features of the backing\n"
+		"file/database should be updated accordingly.\n"
+		"\n"
+		"Drivers may or may not support not-null constraints. If they support\n"
+		"creating fields with not-null constraints, this is generally before\n"
+		"creating any feature to the layer.\n"
+		"\n"
+		"This function is the same as the C++ method OGRLayer::CreateField().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hLayer:  handle to the layer to write the field definition.\n"
+		"\n"
+		"hField:  handle of the geometry field definition to write to disk.\n"
+		"\n"
+		"bApproxOK:  If TRUE, the field may be created in a slightly different\n"
+		"form depending on the limitations of the format driver.\n"
+		"\n"
+		"OGRERR_NONE on success.\n"
+		"\n"
+		"OGR 1.11 \n"
+		""},
+	 { (char *)"Layer_StartTransaction", _wrap_Layer_StartTransaction, METH_VARARGS, (char *)"\n"
+		"Layer_StartTransaction(Layer self) -> OGRErr\n"
+		"\n"
+		"OGRErr\n"
+		"OGR_L_StartTransaction(OGRLayerH hLayer)\n"
+		"\n"
+		"For datasources which support transactions, StartTransaction creates a\n"
+		"transaction.\n"
+		"\n"
+		"If starting the transaction fails, will return OGRERR_FAILURE.\n"
+		"Datasources which do not support transactions will always return\n"
+		"OGRERR_NONE.\n"
+		"\n"
+		"Note: as of GDAL 2.0, use of this API is discouraged when the dataset\n"
+		"offers dataset level transaction with GDALDataset::StartTransaction().\n"
+		"The reason is that most drivers can only offer transactions at dataset\n"
+		"level, and not layer level. Very few drivers really support\n"
+		"transactions at layer scope.\n"
+		"\n"
+		"This function is the same as the C++ method\n"
+		"OGRLayer::StartTransaction().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hLayer:  handle to the layer\n"
+		"\n"
+		"OGRERR_NONE on success. \n"
+		""},
+	 { (char *)"Layer_CommitTransaction", _wrap_Layer_CommitTransaction, METH_VARARGS, (char *)"\n"
+		"Layer_CommitTransaction(Layer self) -> OGRErr\n"
+		"\n"
+		"OGRErr\n"
+		"OGR_L_CommitTransaction(OGRLayerH hLayer)\n"
+		"\n"
+		"For datasources which support transactions, CommitTransaction commits\n"
+		"a transaction.\n"
+		"\n"
+		"If no transaction is active, or the commit fails, will return\n"
+		"OGRERR_FAILURE. Datasources which do not support transactions will\n"
+		"always return OGRERR_NONE.\n"
+		"\n"
+		"This function is the same as the C++ method\n"
+		"OGRLayer::CommitTransaction().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hLayer:  handle to the layer\n"
+		"\n"
+		"OGRERR_NONE on success. \n"
+		""},
+	 { (char *)"Layer_RollbackTransaction", _wrap_Layer_RollbackTransaction, METH_VARARGS, (char *)"\n"
+		"Layer_RollbackTransaction(Layer self) -> OGRErr\n"
+		"\n"
+		"OGRErr\n"
+		"OGR_L_RollbackTransaction(OGRLayerH hLayer)\n"
+		"\n"
+		"For datasources which support transactions, RollbackTransaction will\n"
+		"roll back a datasource to its state before the start of the current\n"
+		"transaction.\n"
+		"\n"
+		"If no transaction is active, or the rollback fails, will return\n"
+		"OGRERR_FAILURE. Datasources which do not support transactions will\n"
+		"always return OGRERR_NONE.\n"
+		"\n"
+		"This function is the same as the C++ method\n"
+		"OGRLayer::RollbackTransaction().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hLayer:  handle to the layer\n"
+		"\n"
+		"OGRERR_NONE on success. \n"
+		""},
+	 { (char *)"Layer_FindFieldIndex", _wrap_Layer_FindFieldIndex, METH_VARARGS, (char *)"\n"
+		"Layer_FindFieldIndex(Layer self, char const * pszFieldName, int bExactMatch) -> int\n"
+		"\n"
+		"int\n"
+		"OGR_L_FindFieldIndex(OGRLayerH hLayer, const char *pszFieldName, int\n"
+		"bExactMatch)\n"
+		"\n"
+		"Find the index of field in a layer.\n"
+		"\n"
+		"The returned number is the index of the field in the layers, or -1 if\n"
+		"the field doesn't exist.\n"
+		"\n"
+		"If bExactMatch is set to FALSE and the field doesn't exists in the\n"
+		"given form the driver might apply some changes to make it match, like\n"
+		"those it might do if the layer was created (eg. like LAUNDER in the\n"
+		"OCI driver).\n"
+		"\n"
+		"This method is the same as the C++ method OGRLayer::FindFieldIndex().\n"
+		"\n"
+		"field index, or -1 if the field doesn't exist \n"
+		""},
+	 { (char *)"Layer_GetSpatialRef", _wrap_Layer_GetSpatialRef, METH_VARARGS, (char *)"\n"
+		"Layer_GetSpatialRef(Layer self) -> SpatialReference\n"
+		"\n"
+		"OGRSpatialReferenceH\n"
+		"OGR_L_GetSpatialRef(OGRLayerH hLayer)\n"
+		"\n"
+		"Fetch the spatial reference system for this layer.\n"
+		"\n"
+		"The returned object is owned by the OGRLayer and should not be\n"
+		"modified or freed by the application.\n"
+		"\n"
+		"This function is the same as the C++ method OGRLayer::GetSpatialRef().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hLayer:  handle to the layer to get the spatial reference from.\n"
+		"\n"
+		"spatial reference, or NULL if there isn't one. \n"
+		""},
+	 { (char *)"Layer_GetFeaturesRead", _wrap_Layer_GetFeaturesRead, METH_VARARGS, (char *)"\n"
+		"Layer_GetFeaturesRead(Layer self) -> GIntBig\n"
+		"\n"
+		"GIntBig\n"
+		"OGR_L_GetFeaturesRead(OGRLayerH hLayer) \n"
+		""},
+	 { (char *)"Layer_SetIgnoredFields", _wrap_Layer_SetIgnoredFields, METH_VARARGS, (char *)"\n"
+		"Layer_SetIgnoredFields(Layer self, char const ** options) -> OGRErr\n"
+		"\n"
+		"OGRErr\n"
+		"OGR_L_SetIgnoredFields(OGRLayerH hLayer, const char **papszFields)\n"
+		"\n"
+		"Set which fields can be omitted when retrieving features from the\n"
+		"layer.\n"
+		"\n"
+		"If the driver supports this functionality (testable using\n"
+		"OLCIgnoreFields capability), it will not fetch the specified fields in\n"
+		"subsequent calls to GetFeature() / GetNextFeature() and thus save some\n"
+		"processing time and/or bandwidth.\n"
+		"\n"
+		"Besides field names of the layers, the following special fields can be\n"
+		"passed: \"OGR_GEOMETRY\" to ignore geometry and \"OGR_STYLE\" to\n"
+		"ignore layer style.\n"
+		"\n"
+		"By default, no fields are ignored.\n"
+		"\n"
+		"This method is the same as the C++ method OGRLayer::SetIgnoredFields()\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"papszFields:  an array of field names terminated by NULL item. If NULL\n"
+		"is passed, the ignored list is cleared.\n"
+		"\n"
+		"OGRERR_NONE if all field names have been resolved (even if the driver\n"
+		"does not support this method) \n"
+		""},
+	 { (char *)"Layer_Intersection", (PyCFunction) _wrap_Layer_Intersection, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
+		"Layer_Intersection(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None) -> OGRErr\n"
+		"\n"
+		"OGRErr\n"
+		"OGR_L_Intersection(OGRLayerH pLayerInput, OGRLayerH pLayerMethod,\n"
+		"OGRLayerH pLayerResult, char **papszOptions, GDALProgressFunc\n"
+		"pfnProgress, void *pProgressArg)\n"
+		"\n"
+		"Intersection of two layers.\n"
+		"\n"
+		"The result layer contains features whose geometries represent areas\n"
+		"that are common between features in the input layer and in the method\n"
+		"layer. The features in the result layer have attributes from both\n"
+		"input and method layers. The schema of the result layer can be set by\n"
+		"the user or, if it is empty, is initialized to contain all fields in\n"
+		"the input and method layers.\n"
+		"\n"
+		"If the schema of the result is set by user and contains fields that\n"
+		"have the same name as a field in input and in method layer, then the\n"
+		"attribute in the result feature will get the value from the feature of\n"
+		"the method layer.\n"
+		"\n"
+		"For best performance use the minimum amount of features in the method\n"
+		"layer and copy it into a memory layer.\n"
+		"\n"
+		"This method relies on GEOS support. Do not use unless the GEOS support\n"
+		"is compiled in.  The recognized list of options is :\n"
+		"SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a feature\n"
+		"could not be inserted.\n"
+		"\n"
+		"PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons into\n"
+		"MultiPolygons, or LineStrings to MultiLineStrings.\n"
+		"\n"
+		"INPUT_PREFIX=string. Set a prefix for the field names that will be\n"
+		"created from the fields of the input layer.\n"
+		"\n"
+		"METHOD_PREFIX=string. Set a prefix for the field names that will be\n"
+		"created from the fields of the method layer.\n"
+		"\n"
+		"USE_PREPARED_GEOMETRIES=YES/NO. Set to NO to not use prepared\n"
+		"geometries to pretest intersection of features of method layer with\n"
+		"features of this layer.\n"
+		"\n"
+		"PRETEST_CONTAINMENT=YES/NO. Set to YES to pretest the containment of\n"
+		"features of method layer within the features of this layer. This will\n"
+		"speed up the method significantly in some cases. Requires that the\n"
+		"prepared geometries are in effect.\n"
+		"\n"
+		"This function is the same as the C++ method OGRLayer::Intersection().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"pLayerInput:  the input layer. Should not be NULL.\n"
+		"\n"
+		"pLayerMethod:  the method layer. Should not be NULL.\n"
+		"\n"
+		"pLayerResult:  the layer where the features resulting from the\n"
+		"operation are inserted. Should not be NULL. See above the note about\n"
+		"the schema.\n"
+		"\n"
+		"papszOptions:  NULL terminated list of options (may be NULL).\n"
+		"\n"
+		"pfnProgress:  a GDALProgressFunc() compatible callback function for\n"
+		"reporting progress or NULL.\n"
+		"\n"
+		"pProgressArg:  argument to be passed to pfnProgress. May be NULL.\n"
+		"\n"
+		"an error code if there was an error or the execution was interrupted,\n"
+		"OGRERR_NONE otherwise.\n"
+		"\n"
+		"The first geometry field is always used.\n"
+		"\n"
+		"OGR 1.10 \n"
+		""},
+	 { (char *)"Layer_Union", (PyCFunction) _wrap_Layer_Union, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
+		"Layer_Union(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None) -> OGRErr\n"
+		"\n"
+		"OGRErr OGR_L_Union(OGRLayerH\n"
+		"pLayerInput, OGRLayerH pLayerMethod, OGRLayerH pLayerResult, char\n"
+		"**papszOptions, GDALProgressFunc pfnProgress, void *pProgressArg)\n"
+		"\n"
+		"Union of two layers.\n"
+		"\n"
+		"The result layer contains features whose geometries represent areas\n"
+		"that are in either in the input layer or in the method layer. The\n"
+		"features in the result layer have attributes from both input and\n"
+		"method layers. For features which represent areas that are only in the\n"
+		"input or in the method layer the respective attributes have undefined\n"
+		"values. The schema of the result layer can be set by the user or, if\n"
+		"it is empty, is initialized to contain all fields in the input and\n"
+		"method layers.\n"
+		"\n"
+		"If the schema of the result is set by user and contains fields that\n"
+		"have the same name as a field in input and in method layer, then the\n"
+		"attribute in the result feature will get the value from the feature of\n"
+		"the method layer (even if it is undefined).\n"
+		"\n"
+		"For best performance use the minimum amount of features in the method\n"
+		"layer and copy it into a memory layer.\n"
+		"\n"
+		"This method relies on GEOS support. Do not use unless the GEOS support\n"
+		"is compiled in.  The recognized list of options is :\n"
+		"SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a feature\n"
+		"could not be inserted.\n"
+		"\n"
+		"PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons into\n"
+		"MultiPolygons, or LineStrings to MultiLineStrings.\n"
+		"\n"
+		"INPUT_PREFIX=string. Set a prefix for the field names that will be\n"
+		"created from the fields of the input layer.\n"
+		"\n"
+		"METHOD_PREFIX=string. Set a prefix for the field names that will be\n"
+		"created from the fields of the method layer.\n"
+		"\n"
+		"USE_PREPARED_GEOMETRIES=YES/NO. Set to NO to not use prepared\n"
+		"geometries to pretest intersection of features of method layer with\n"
+		"features of this layer.\n"
+		"\n"
+		"This function is the same as the C++ method OGRLayer::Union().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"pLayerInput:  the input layer. Should not be NULL.\n"
+		"\n"
+		"pLayerMethod:  the method layer. Should not be NULL.\n"
+		"\n"
+		"pLayerResult:  the layer where the features resulting from the\n"
+		"operation are inserted. Should not be NULL. See above the note about\n"
+		"the schema.\n"
+		"\n"
+		"papszOptions:  NULL terminated list of options (may be NULL).\n"
+		"\n"
+		"pfnProgress:  a GDALProgressFunc() compatible callback function for\n"
+		"reporting progress or NULL.\n"
+		"\n"
+		"pProgressArg:  argument to be passed to pfnProgress. May be NULL.\n"
+		"\n"
+		"an error code if there was an error or the execution was interrupted,\n"
+		"OGRERR_NONE otherwise.\n"
+		"\n"
+		"The first geometry field is always used.\n"
+		"\n"
+		"OGR 1.10 \n"
+		""},
+	 { (char *)"Layer_SymDifference", (PyCFunction) _wrap_Layer_SymDifference, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
+		"Layer_SymDifference(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None) -> OGRErr\n"
+		"\n"
+		"OGRErr\n"
+		"OGR_L_SymDifference(OGRLayerH pLayerInput, OGRLayerH pLayerMethod,\n"
+		"OGRLayerH pLayerResult, char **papszOptions, GDALProgressFunc\n"
+		"pfnProgress, void *pProgressArg)\n"
+		"\n"
+		"Symmetrical difference of two layers.\n"
+		"\n"
+		"The result layer contains features whose geometries represent areas\n"
+		"that are in either in the input layer or in the method layer but not\n"
+		"in both. The features in the result layer have attributes from both\n"
+		"input and method layers. For features which represent areas that are\n"
+		"only in the input or in the method layer the respective attributes\n"
+		"have undefined values. The schema of the result layer can be set by\n"
+		"the user or, if it is empty, is initialized to contain all fields in\n"
+		"the input and method layers.\n"
+		"\n"
+		"If the schema of the result is set by user and contains fields that\n"
+		"have the same name as a field in input and in method layer, then the\n"
+		"attribute in the result feature will get the value from the feature of\n"
+		"the method layer (even if it is undefined).\n"
+		"\n"
+		"For best performance use the minimum amount of features in the method\n"
+		"layer and copy it into a memory layer.\n"
+		"\n"
+		"This method relies on GEOS support. Do not use unless the GEOS support\n"
+		"is compiled in.  The recognized list of options is :\n"
+		"SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a feature\n"
+		"could not be inserted.\n"
+		"\n"
+		"PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons into\n"
+		"MultiPolygons, or LineStrings to MultiLineStrings.\n"
+		"\n"
+		"INPUT_PREFIX=string. Set a prefix for the field names that will be\n"
+		"created from the fields of the input layer.\n"
+		"\n"
+		"METHOD_PREFIX=string. Set a prefix for the field names that will be\n"
+		"created from the fields of the method layer.\n"
+		"\n"
+		"This function is the same as the C++ method OGRLayer::SymDifference().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"pLayerInput:  the input layer. Should not be NULL.\n"
+		"\n"
+		"pLayerMethod:  the method layer. Should not be NULL.\n"
+		"\n"
+		"pLayerResult:  the layer where the features resulting from the\n"
+		"operation are inserted. Should not be NULL. See above the note about\n"
+		"the schema.\n"
+		"\n"
+		"papszOptions:  NULL terminated list of options (may be NULL).\n"
+		"\n"
+		"pfnProgress:  a GDALProgressFunc() compatible callback function for\n"
+		"reporting progress or NULL.\n"
+		"\n"
+		"pProgressArg:  argument to be passed to pfnProgress. May be NULL.\n"
+		"\n"
+		"an error code if there was an error or the execution was interrupted,\n"
+		"OGRERR_NONE otherwise.\n"
+		"\n"
+		"The first geometry field is always used.\n"
+		"\n"
+		"OGR 1.10 \n"
+		""},
+	 { (char *)"Layer_Identity", (PyCFunction) _wrap_Layer_Identity, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
+		"Layer_Identity(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None) -> OGRErr\n"
+		"\n"
+		"OGRErr OGR_L_Identity(OGRLayerH\n"
+		"pLayerInput, OGRLayerH pLayerMethod, OGRLayerH pLayerResult, char\n"
+		"**papszOptions, GDALProgressFunc pfnProgress, void *pProgressArg)\n"
+		"\n"
+		"Identify the features of this layer with the ones from the identity\n"
+		"layer.\n"
+		"\n"
+		"The result layer contains features whose geometries represent areas\n"
+		"that are in the input layer. The features in the result layer have\n"
+		"attributes from both input and method layers. The schema of the result\n"
+		"layer can be set by the user or, if it is empty, is initialized to\n"
+		"contain all fields in input and method layers.\n"
+		"\n"
+		"If the schema of the result is set by user and contains fields that\n"
+		"have the same name as a field in input and in method layer, then the\n"
+		"attribute in the result feature will get the value from the feature of\n"
+		"the method layer (even if it is undefined).\n"
+		"\n"
+		"For best performance use the minimum amount of features in the method\n"
+		"layer and copy it into a memory layer.\n"
+		"\n"
+		"This method relies on GEOS support. Do not use unless the GEOS support\n"
+		"is compiled in.  The recognized list of options is :\n"
+		"SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a feature\n"
+		"could not be inserted.\n"
+		"\n"
+		"PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons into\n"
+		"MultiPolygons, or LineStrings to MultiLineStrings.\n"
+		"\n"
+		"INPUT_PREFIX=string. Set a prefix for the field names that will be\n"
+		"created from the fields of the input layer.\n"
+		"\n"
+		"METHOD_PREFIX=string. Set a prefix for the field names that will be\n"
+		"created from the fields of the method layer.\n"
+		"\n"
+		"USE_PREPARED_GEOMETRIES=YES/NO. Set to NO to not use prepared\n"
+		"geometries to pretest intersection of features of method layer with\n"
+		"features of this layer.\n"
+		"\n"
+		"This function is the same as the C++ method OGRLayer::Identity().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"pLayerInput:  the input layer. Should not be NULL.\n"
 		"\n"
-		"OGR 1.9.0 \n"
-		""},
-	 { (char *)"Layer_AlterFieldDefn", _wrap_Layer_AlterFieldDefn, METH_VARARGS, (char *)"\n"
-		"Layer_AlterFieldDefn(Layer self, int iField, FieldDefn field_def, int nFlags) -> OGRErr\n"
+		"pLayerMethod:  the method layer. Should not be NULL.\n"
 		"\n"
-		"OGRErr\n"
-		"OGR_L_AlterFieldDefn(OGRLayerH hLayer, int iField, OGRFieldDefnH\n"
-		"hNewFieldDefn, int nFlags)\n"
+		"pLayerResult:  the layer where the features resulting from the\n"
+		"operation are inserted. Should not be NULL. See above the note about\n"
+		"the schema.\n"
 		"\n"
-		"Alter the definition of an existing field on a layer.\n"
+		"papszOptions:  NULL terminated list of options (may be NULL).\n"
 		"\n"
-		"You must use this to alter the definition of an existing field of a\n"
-		"real layer. Internally the OGRFeatureDefn for the layer will be\n"
-		"updated to reflect the altered field. Applications should never modify\n"
-		"the OGRFeatureDefn used by a layer directly.\n"
+		"pfnProgress:  a GDALProgressFunc() compatible callback function for\n"
+		"reporting progress or NULL.\n"
 		"\n"
-		"This function should not be called while there are feature objects in\n"
-		"existance that were obtained or created with the previous layer\n"
-		"definition.\n"
+		"pProgressArg:  argument to be passed to pfnProgress. May be NULL.\n"
 		"\n"
-		"Not all drivers support this function. You can query a layer to check\n"
-		"if it supports it with the OLCAlterFieldDefn capability. Some drivers\n"
-		"may only support this method while there are still no features in the\n"
-		"layer. When it is supported, the existings features of the backing\n"
-		"file/database should be updated accordingly. Some drivers might also\n"
-		"not support all update flags.\n"
+		"an error code if there was an error or the execution was interrupted,\n"
+		"OGRERR_NONE otherwise.\n"
 		"\n"
-		"This function is the same as the C++ method\n"
-		"OGRLayer::AlterFieldDefn().\n"
+		"The first geometry field is always used.\n"
 		"\n"
-		"Parameters:\n"
-		"-----------\n"
+		"OGR 1.10 \n"
+		""},
+	 { (char *)"Layer_Update", (PyCFunction) _wrap_Layer_Update, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
+		"Layer_Update(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None) -> OGRErr\n"
 		"\n"
-		"hLayer:  handle to the layer.\n"
+		"OGRErr OGR_L_Update(OGRLayerH\n"
+		"pLayerInput, OGRLayerH pLayerMethod, OGRLayerH pLayerResult, char\n"
+		"**papszOptions, GDALProgressFunc pfnProgress, void *pProgressArg)\n"
 		"\n"
-		"iField:  index of the field whose definition must be altered.\n"
+		"Update this layer with features from the update layer.\n"
 		"\n"
-		"hNewFieldDefn:  new field definition\n"
+		"The result layer contains features whose geometries represent areas\n"
+		"that are either in the input layer or in the method layer. The\n"
+		"features in the result layer have areas of the features of the method\n"
+		"layer or those ares of the features of the input layer that are not\n"
+		"covered by the method layer. The features of the result layer get\n"
+		"their attributes from the input layer. The schema of the result layer\n"
+		"can be set by the user or, if it is empty, is initialized to contain\n"
+		"all fields in the input layer.\n"
 		"\n"
-		"nFlags:  combination of ALTER_NAME_FLAG, ALTER_TYPE_FLAG and\n"
-		"ALTER_WIDTH_PRECISION_FLAG to indicate which of the name and/or type\n"
-		"and/or width and precision fields from the new field definition must\n"
-		"be taken into account.\n"
+		"If the schema of the result is set by user and contains fields that\n"
+		"have the same name as a field in the method layer, then the attribute\n"
+		"in the result feature the originates from the method layer will get\n"
+		"the value from the feature of the method layer.\n"
 		"\n"
-		"OGRERR_NONE on success.\n"
+		"For best performance use the minimum amount of features in the method\n"
+		"layer and copy it into a memory layer.\n"
 		"\n"
-		"OGR 1.9.0 \n"
-		""},
-	 { (char *)"Layer_CreateGeomField", (PyCFunction) _wrap_Layer_CreateGeomField, METH_VARARGS | METH_KEYWORDS, (char *)"Layer_CreateGeomField(Layer self, GeomFieldDefn field_def, int approx_ok = 1) -> OGRErr"},
-	 { (char *)"Layer_StartTransaction", _wrap_Layer_StartTransaction, METH_VARARGS, (char *)"\n"
-		"Layer_StartTransaction(Layer self) -> OGRErr\n"
+		"This method relies on GEOS support. Do not use unless the GEOS support\n"
+		"is compiled in.  The recognized list of options is :\n"
+		"SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a feature\n"
+		"could not be inserted.\n"
 		"\n"
-		"OGRErr\n"
-		"OGR_L_StartTransaction(OGRLayerH hLayer)\n"
+		"PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons into\n"
+		"MultiPolygons, or LineStrings to MultiLineStrings.\n"
 		"\n"
-		"For datasources which support transactions, StartTransaction creates a\n"
-		"transaction.\n"
+		"INPUT_PREFIX=string. Set a prefix for the field names that will be\n"
+		"created from the fields of the input layer.\n"
 		"\n"
-		"If starting the transaction fails, will return OGRERR_FAILURE.\n"
-		"Datasources which do not support transactions will always return\n"
-		"OGRERR_NONE.\n"
+		"METHOD_PREFIX=string. Set a prefix for the field names that will be\n"
+		"created from the fields of the method layer.\n"
 		"\n"
-		"This function is the same as the C++ method\n"
-		"OGRLayer::StartTransaction().\n"
+		"This function is the same as the C++ method OGRLayer::Update().\n"
 		"\n"
 		"Parameters:\n"
 		"-----------\n"
 		"\n"
-		"hLayer:  handle to the layer\n"
+		"pLayerInput:  the input layer. Should not be NULL.\n"
 		"\n"
-		"OGRERR_NONE on success. \n"
-		""},
-	 { (char *)"Layer_CommitTransaction", _wrap_Layer_CommitTransaction, METH_VARARGS, (char *)"\n"
-		"Layer_CommitTransaction(Layer self) -> OGRErr\n"
+		"pLayerMethod:  the method layer. Should not be NULL.\n"
 		"\n"
-		"OGRErr\n"
-		"OGR_L_CommitTransaction(OGRLayerH hLayer)\n"
+		"pLayerResult:  the layer where the features resulting from the\n"
+		"operation are inserted. Should not be NULL. See above the note about\n"
+		"the schema.\n"
 		"\n"
-		"For datasources which support transactions, CommitTransaction commits\n"
-		"a transaction.\n"
+		"papszOptions:  NULL terminated list of options (may be NULL).\n"
 		"\n"
-		"If no transaction is active, or the commit fails, will return\n"
-		"OGRERR_FAILURE. Datasources which do not support transactions will\n"
-		"always return OGRERR_NONE.\n"
+		"pfnProgress:  a GDALProgressFunc() compatible callback function for\n"
+		"reporting progress or NULL.\n"
 		"\n"
-		"This function is the same as the C++ method\n"
-		"OGRLayer::CommitTransaction().\n"
+		"pProgressArg:  argument to be passed to pfnProgress. May be NULL.\n"
 		"\n"
-		"Parameters:\n"
-		"-----------\n"
+		"an error code if there was an error or the execution was interrupted,\n"
+		"OGRERR_NONE otherwise.\n"
 		"\n"
-		"hLayer:  handle to the layer\n"
+		"The first geometry field is always used.\n"
 		"\n"
-		"OGRERR_NONE on success. \n"
+		"OGR 1.10 \n"
 		""},
-	 { (char *)"Layer_RollbackTransaction", _wrap_Layer_RollbackTransaction, METH_VARARGS, (char *)"\n"
-		"Layer_RollbackTransaction(Layer self) -> OGRErr\n"
+	 { (char *)"Layer_Clip", (PyCFunction) _wrap_Layer_Clip, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
+		"Layer_Clip(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None) -> OGRErr\n"
 		"\n"
-		"OGRErr\n"
-		"OGR_L_RollbackTransaction(OGRLayerH hLayer)\n"
+		"OGRErr OGR_L_Clip(OGRLayerH pLayerInput,\n"
+		"OGRLayerH pLayerMethod, OGRLayerH pLayerResult, char **papszOptions,\n"
+		"GDALProgressFunc pfnProgress, void *pProgressArg)\n"
 		"\n"
-		"For datasources which support transactions, RollbackTransaction will\n"
-		"roll back a datasource to its state before the start of the current\n"
-		"transaction. If no transaction is active, or the rollback fails, will\n"
-		"return OGRERR_FAILURE. Datasources which do not support transactions\n"
-		"will always return OGRERR_NONE.\n"
+		"Clip off areas that are not covered by the method layer.\n"
 		"\n"
-		"This function is the same as the C++ method\n"
-		"OGRLayer::RollbackTransaction().\n"
+		"The result layer contains features whose geometries represent areas\n"
+		"that are in the input layer and in the method layer. The features in\n"
+		"the result layer have the (possibly clipped) areas of features in the\n"
+		"input layer and the attributes from the same features. The schema of\n"
+		"the result layer can be set by the user or, if it is empty, is\n"
+		"initialized to contain all fields in the input layer.\n"
+		"\n"
+		"For best performance use the minimum amount of features in the method\n"
+		"layer and copy it into a memory layer.\n"
+		"\n"
+		"This method relies on GEOS support. Do not use unless the GEOS support\n"
+		"is compiled in.  The recognized list of options is :\n"
+		"SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a feature\n"
+		"could not be inserted.\n"
+		"\n"
+		"PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons into\n"
+		"MultiPolygons, or LineStrings to MultiLineStrings.\n"
+		"\n"
+		"INPUT_PREFIX=string. Set a prefix for the field names that will be\n"
+		"created from the fields of the input layer.\n"
+		"\n"
+		"METHOD_PREFIX=string. Set a prefix for the field names that will be\n"
+		"created from the fields of the method layer.\n"
+		"\n"
+		"This function is the same as the C++ method OGRLayer::Clip().\n"
 		"\n"
 		"Parameters:\n"
 		"-----------\n"
 		"\n"
-		"hLayer:  handle to the layer\n"
+		"pLayerInput:  the input layer. Should not be NULL.\n"
 		"\n"
-		"OGRERR_NONE on success. \n"
-		""},
-	 { (char *)"Layer_FindFieldIndex", _wrap_Layer_FindFieldIndex, METH_VARARGS, (char *)"Layer_FindFieldIndex(Layer self, char pszFieldName, int bExactMatch) -> int"},
-	 { (char *)"Layer_GetSpatialRef", _wrap_Layer_GetSpatialRef, METH_VARARGS, (char *)"\n"
-		"Layer_GetSpatialRef(Layer self) -> SpatialReference\n"
+		"pLayerMethod:  the method layer. Should not be NULL.\n"
 		"\n"
-		"OGRSpatialReferenceH\n"
-		"OGR_L_GetSpatialRef(OGRLayerH hLayer)\n"
+		"pLayerResult:  the layer where the features resulting from the\n"
+		"operation are inserted. Should not be NULL. See above the note about\n"
+		"the schema.\n"
 		"\n"
-		"Fetch the spatial reference system for this layer.\n"
+		"papszOptions:  NULL terminated list of options (may be NULL).\n"
 		"\n"
-		"The returned object is owned by the OGRLayer and should not be\n"
-		"modified or freed by the application.\n"
+		"pfnProgress:  a GDALProgressFunc() compatible callback function for\n"
+		"reporting progress or NULL.\n"
 		"\n"
-		"This function is the same as the C++ method OGRLayer::GetSpatialRef().\n"
+		"pProgressArg:  argument to be passed to pfnProgress. May be NULL.\n"
 		"\n"
-		"Parameters:\n"
-		"-----------\n"
+		"an error code if there was an error or the execution was interrupted,\n"
+		"OGRERR_NONE otherwise.\n"
 		"\n"
-		"hLayer:  handle to the layer to get the spatial reference from.\n"
+		"The first geometry field is always used.\n"
 		"\n"
-		"spatial reference, or NULL if there isn't one. \n"
+		"OGR 1.10 \n"
 		""},
-	 { (char *)"Layer_GetFeaturesRead", _wrap_Layer_GetFeaturesRead, METH_VARARGS, (char *)"\n"
-		"Layer_GetFeaturesRead(Layer self) -> GIntBig\n"
+	 { (char *)"Layer_Erase", (PyCFunction) _wrap_Layer_Erase, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
+		"Layer_Erase(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, \n"
+		"    void * callback_data=None) -> OGRErr\n"
 		"\n"
-		"GIntBig\n"
-		"OGR_L_GetFeaturesRead(OGRLayerH hLayer) \n"
-		""},
-	 { (char *)"Layer_SetIgnoredFields", _wrap_Layer_SetIgnoredFields, METH_VARARGS, (char *)"\n"
-		"Layer_SetIgnoredFields(Layer self, char options) -> OGRErr\n"
+		"OGRErr OGR_L_Erase(OGRLayerH\n"
+		"pLayerInput, OGRLayerH pLayerMethod, OGRLayerH pLayerResult, char\n"
+		"**papszOptions, GDALProgressFunc pfnProgress, void *pProgressArg)\n"
 		"\n"
-		"OGRErr\n"
-		"OGR_L_SetIgnoredFields(OGRLayerH hLayer, const char **papszFields)\n"
+		"Remove areas that are covered by the method layer.\n"
 		"\n"
-		"Set which fields can be omitted when retrieving features from the\n"
-		"layer.\n"
+		"The result layer contains features whose geometries represent areas\n"
+		"that are in the input layer but not in the method layer. The features\n"
+		"in the result layer have attributes from the input layer. The schema\n"
+		"of the result layer can be set by the user or, if it is empty, is\n"
+		"initialized to contain all fields in the input layer.\n"
 		"\n"
-		"If the driver supports this functionality (testable using\n"
-		"OLCIgnoreFields capability), it will not fetch the specified fields in\n"
-		"subsequent calls to GetFeature() / GetNextFeature() and thus save some\n"
-		"processing time and/or bandwidth.\n"
+		"For best performance use the minimum amount of features in the method\n"
+		"layer and copy it into a memory layer.\n"
 		"\n"
-		"Besides field names of the layers, the following special fields can be\n"
-		"passed: \"OGR_GEOMETRY\" to ignore geometry and \"OGR_STYLE\" to\n"
-		"ignore layer style.\n"
+		"This method relies on GEOS support. Do not use unless the GEOS support\n"
+		"is compiled in.  The recognized list of options is :\n"
+		"SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a feature\n"
+		"could not be inserted.\n"
 		"\n"
-		"By default, no fields are ignored.\n"
+		"PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons into\n"
+		"MultiPolygons, or LineStrings to MultiLineStrings.\n"
 		"\n"
-		"This method is the same as the C++ method OGRLayer::SetIgnoredFields()\n"
+		"INPUT_PREFIX=string. Set a prefix for the field names that will be\n"
+		"created from the fields of the input layer.\n"
+		"\n"
+		"METHOD_PREFIX=string. Set a prefix for the field names that will be\n"
+		"created from the fields of the method layer.\n"
+		"\n"
+		"This function is the same as the C++ method OGRLayer::Erase().\n"
 		"\n"
 		"Parameters:\n"
 		"-----------\n"
 		"\n"
-		"papszFields:  an array of field names terminated by NULL item. If NULL\n"
-		"is passed, the ignored list is cleared.\n"
+		"pLayerInput:  the input layer. Should not be NULL.\n"
 		"\n"
-		"OGRERR_NONE if all field names have been resolved (even if the driver\n"
-		"does not support this method) \n"
-		""},
-	 { (char *)"Layer_Intersection", (PyCFunction) _wrap_Layer_Intersection, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Layer_Intersection(Layer self, Layer method_layer, Layer result_layer, \n"
-		"    char options = None, GDALProgressFunc callback = None, \n"
-		"    void callback_data = None) -> OGRErr\n"
-		""},
-	 { (char *)"Layer_Union", (PyCFunction) _wrap_Layer_Union, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Layer_Union(Layer self, Layer method_layer, Layer result_layer, \n"
-		"    char options = None, GDALProgressFunc callback = None, \n"
-		"    void callback_data = None) -> OGRErr\n"
-		""},
-	 { (char *)"Layer_SymDifference", (PyCFunction) _wrap_Layer_SymDifference, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Layer_SymDifference(Layer self, Layer method_layer, Layer result_layer, \n"
-		"    char options = None, GDALProgressFunc callback = None, \n"
-		"    void callback_data = None) -> OGRErr\n"
-		""},
-	 { (char *)"Layer_Identity", (PyCFunction) _wrap_Layer_Identity, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Layer_Identity(Layer self, Layer method_layer, Layer result_layer, \n"
-		"    char options = None, GDALProgressFunc callback = None, \n"
-		"    void callback_data = None) -> OGRErr\n"
-		""},
-	 { (char *)"Layer_Update", (PyCFunction) _wrap_Layer_Update, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Layer_Update(Layer self, Layer method_layer, Layer result_layer, \n"
-		"    char options = None, GDALProgressFunc callback = None, \n"
-		"    void callback_data = None) -> OGRErr\n"
-		""},
-	 { (char *)"Layer_Clip", (PyCFunction) _wrap_Layer_Clip, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Layer_Clip(Layer self, Layer method_layer, Layer result_layer, \n"
-		"    char options = None, GDALProgressFunc callback = None, \n"
-		"    void callback_data = None) -> OGRErr\n"
-		""},
-	 { (char *)"Layer_Erase", (PyCFunction) _wrap_Layer_Erase, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Layer_Erase(Layer self, Layer method_layer, Layer result_layer, \n"
-		"    char options = None, GDALProgressFunc callback = None, \n"
-		"    void callback_data = None) -> OGRErr\n"
+		"pLayerMethod:  the method layer. Should not be NULL.\n"
+		"\n"
+		"pLayerResult:  the layer where the features resulting from the\n"
+		"operation are inserted. Should not be NULL. See above the note about\n"
+		"the schema.\n"
+		"\n"
+		"papszOptions:  NULL terminated list of options (may be NULL).\n"
+		"\n"
+		"pfnProgress:  a GDALProgressFunc() compatible callback function for\n"
+		"reporting progress or NULL.\n"
+		"\n"
+		"pProgressArg:  argument to be passed to pfnProgress. May be NULL.\n"
+		"\n"
+		"an error code if there was an error or the execution was interrupted,\n"
+		"OGRERR_NONE otherwise.\n"
+		"\n"
+		"The first geometry field is always used.\n"
+		"\n"
+		"OGR 1.10 \n"
 		""},
 	 { (char *)"Layer_GetStyleTable", _wrap_Layer_GetStyleTable, METH_VARARGS, (char *)"\n"
 		"Layer_GetStyleTable(Layer self) -> StyleTable\n"
@@ -25145,7 +28257,7 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"This function updates the features geometry, and operate exactly as\n"
 		"SetGeometry(), except that this function assumes ownership of the\n"
-		"passed geometry.\n"
+		"passed geometry (even in case of failure of that function).\n"
 		"\n"
 		"This function is the same as the C++ method\n"
 		"OGRFeature::SetGeometryDirectly.\n"
@@ -25182,15 +28294,87 @@ static PyMethodDef SwigMethods[] = {
 		""},
 	 { (char *)"Feature_SetGeomField", _wrap_Feature_SetGeomField, METH_VARARGS, (char *)"\n"
 		"SetGeomField(int iField, Geometry geom) -> OGRErr\n"
-		"Feature_SetGeomField(Feature self, char name, Geometry geom) -> OGRErr\n"
+		"Feature_SetGeomField(Feature self, char const * name, Geometry geom) -> OGRErr\n"
+		"\n"
+		"OGRErr\n"
+		"OGR_F_SetGeomField(OGRFeatureH hFeat, int iField, OGRGeometryH hGeom)\n"
+		"\n"
+		"Set feature geometry of a specified geometry field.\n"
+		"\n"
+		"This function updates the features geometry, and operate exactly as\n"
+		"SetGeometryDirectly(), except that this function does not assume\n"
+		"ownership of the passed geometry, but instead makes a copy of it.\n"
+		"\n"
+		"This function is the same as the C++ OGRFeature::SetGeomField().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hFeat:  handle to the feature on which new geometry is applied to.\n"
+		"\n"
+		"iField:  geometry field to set.\n"
+		"\n"
+		"hGeom:  handle to the new geometry to apply to feature.\n"
+		"\n"
+		"OGRERR_NONE if successful, or OGR_UNSUPPORTED_GEOMETRY_TYPE if the\n"
+		"geometry type is illegal for the OGRFeatureDefn (checking not yet\n"
+		"implemented). \n"
 		""},
 	 { (char *)"Feature_SetGeomFieldDirectly", _wrap_Feature_SetGeomFieldDirectly, METH_VARARGS, (char *)"\n"
 		"SetGeomFieldDirectly(int iField, Geometry geom) -> OGRErr\n"
-		"Feature_SetGeomFieldDirectly(Feature self, char name, Geometry geom) -> OGRErr\n"
+		"Feature_SetGeomFieldDirectly(Feature self, char const * name, Geometry geom) -> OGRErr\n"
+		"\n"
+		"OGRErr\n"
+		"OGR_F_SetGeomFieldDirectly(OGRFeatureH hFeat, int iField, OGRGeometryH\n"
+		"hGeom)\n"
+		"\n"
+		"Set feature geometry of a specified geometry field.\n"
+		"\n"
+		"This function updates the features geometry, and operate exactly as\n"
+		"SetGeomField(), except that this function assumes ownership of the\n"
+		"passed geometry (even in case of failure of that function).\n"
+		"\n"
+		"This function is the same as the C++ method\n"
+		"OGRFeature::SetGeomFieldDirectly.\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hFeat:  handle to the feature on which to apply the geometry.\n"
+		"\n"
+		"iField:  geometry field to set.\n"
+		"\n"
+		"hGeom:  handle to the new geometry to apply to feature.\n"
+		"\n"
+		"OGRERR_NONE if successful, or OGRERR_FAILURE if the index is invalid,\n"
+		"or OGR_UNSUPPORTED_GEOMETRY_TYPE if the geometry type is illegal for\n"
+		"the OGRFeatureDefn (checking not yet implemented).\n"
+		"\n"
+		"GDAL 1.11 \n"
 		""},
 	 { (char *)"Feature_GetGeomFieldRef", _wrap_Feature_GetGeomFieldRef, METH_VARARGS, (char *)"\n"
 		"GetGeomFieldRef(int iField) -> Geometry\n"
-		"Feature_GetGeomFieldRef(Feature self, char name) -> Geometry\n"
+		"Feature_GetGeomFieldRef(Feature self, char const * name) -> Geometry\n"
+		"\n"
+		"OGRGeometryH\n"
+		"OGR_F_GetGeomFieldRef(OGRFeatureH hFeat, int iField)\n"
+		"\n"
+		"Fetch an handle to feature geometry.\n"
+		"\n"
+		"This function is the same as the C++ method\n"
+		"OGRFeature::GetGeomFieldRef().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hFeat:  handle to the feature to get geometry from.\n"
+		"\n"
+		"iField:  geometry field to get.\n"
+		"\n"
+		"an handle to internal feature geometry. This object should not be\n"
+		"modified.\n"
+		"\n"
+		"GDAL 1.11 \n"
 		""},
 	 { (char *)"Feature_Clone", _wrap_Feature_Clone, METH_VARARGS, (char *)"\n"
 		"Feature_Clone(Feature self) -> Feature\n"
@@ -25256,7 +28440,7 @@ static PyMethodDef SwigMethods[] = {
 		""},
 	 { (char *)"Feature_GetFieldDefnRef", _wrap_Feature_GetFieldDefnRef, METH_VARARGS, (char *)"\n"
 		"GetFieldDefnRef(int id) -> FieldDefn\n"
-		"Feature_GetFieldDefnRef(Feature self, char name) -> FieldDefn\n"
+		"Feature_GetFieldDefnRef(Feature self, char const * name) -> FieldDefn\n"
 		"\n"
 		"OGRFieldDefnH\n"
 		"OGR_F_GetFieldDefnRef(OGRFeatureH hFeat, int i)\n"
@@ -25276,14 +28460,54 @@ static PyMethodDef SwigMethods[] = {
 		"an handle to the field definition (from the OGRFeatureDefn). This is\n"
 		"an internal reference, and should not be deleted or modified. \n"
 		""},
-	 { (char *)"Feature_GetGeomFieldCount", _wrap_Feature_GetGeomFieldCount, METH_VARARGS, (char *)"Feature_GetGeomFieldCount(Feature self) -> int"},
+	 { (char *)"Feature_GetGeomFieldCount", _wrap_Feature_GetGeomFieldCount, METH_VARARGS, (char *)"\n"
+		"Feature_GetGeomFieldCount(Feature self) -> int\n"
+		"\n"
+		"int\n"
+		"OGR_F_GetGeomFieldCount(OGRFeatureH hFeat)\n"
+		"\n"
+		"Fetch number of geometry fields on this feature This will always be\n"
+		"the same as the geometry field count for the OGRFeatureDefn.\n"
+		"\n"
+		"This function is the same as the C++ method\n"
+		"OGRFeature::GetGeomFieldCount().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hFeat:  handle to the feature to get the geometry fields count from.\n"
+		"\n"
+		"count of geometry fields.\n"
+		"\n"
+		"GDAL 1.11 \n"
+		""},
 	 { (char *)"Feature_GetGeomFieldDefnRef", _wrap_Feature_GetGeomFieldDefnRef, METH_VARARGS, (char *)"\n"
 		"GetGeomFieldDefnRef(int id) -> GeomFieldDefn\n"
-		"Feature_GetGeomFieldDefnRef(Feature self, char name) -> GeomFieldDefn\n"
+		"Feature_GetGeomFieldDefnRef(Feature self, char const * name) -> GeomFieldDefn\n"
+		"\n"
+		"OGRGeomFieldDefnH\n"
+		"OGR_F_GetGeomFieldDefnRef(OGRFeatureH hFeat, int i)\n"
+		"\n"
+		"Fetch definition for this geometry field.\n"
+		"\n"
+		"This function is the same as the C++ method\n"
+		"OGRFeature::GetGeomFieldDefnRef().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hFeat:  handle to the feature on which the field is found.\n"
+		"\n"
+		"i:  the field to fetch, from 0 to GetGeomFieldCount()-1.\n"
+		"\n"
+		"an handle to the field definition (from the OGRFeatureDefn). This is\n"
+		"an internal reference, and should not be deleted or modified.\n"
+		"\n"
+		"GDAL 1.11 \n"
 		""},
 	 { (char *)"Feature_GetFieldAsString", _wrap_Feature_GetFieldAsString, METH_VARARGS, (char *)"\n"
-		"GetFieldAsString(int id) -> char\n"
-		"Feature_GetFieldAsString(Feature self, char name) -> char\n"
+		"GetFieldAsString(int id) -> char const\n"
+		"Feature_GetFieldAsString(Feature self, char const * name) -> char const *\n"
 		"\n"
 		"const char*\n"
 		"OGR_F_GetFieldAsString(OGRFeatureH hFeat, int iField)\n"
@@ -25309,7 +28533,7 @@ static PyMethodDef SwigMethods[] = {
 		""},
 	 { (char *)"Feature_GetFieldAsInteger", _wrap_Feature_GetFieldAsInteger, METH_VARARGS, (char *)"\n"
 		"GetFieldAsInteger(int id) -> int\n"
-		"Feature_GetFieldAsInteger(Feature self, char name) -> int\n"
+		"Feature_GetFieldAsInteger(Feature self, char const * name) -> int\n"
 		"\n"
 		"int\n"
 		"OGR_F_GetFieldAsInteger(OGRFeatureH hFeat, int iField)\n"
@@ -25334,20 +28558,44 @@ static PyMethodDef SwigMethods[] = {
 		""},
 	 { (char *)"Feature_GetFieldAsInteger64", _wrap_Feature_GetFieldAsInteger64, METH_VARARGS, (char *)"\n"
 		"GetFieldAsInteger64(int id) -> GIntBig\n"
-		"Feature_GetFieldAsInteger64(Feature self, char name) -> GIntBig\n"
+		"Feature_GetFieldAsInteger64(Feature self, char const * name) -> GIntBig\n"
+		"\n"
+		"GIntBig\n"
+		"OGR_F_GetFieldAsInteger64(OGRFeatureH hFeat, int iField)\n"
+		"\n"
+		"Fetch field value as integer 64 bit.\n"
+		"\n"
+		"OFTInteger are promoted to 64 bit. OFTString features will be\n"
+		"translated using CPLAtoGIntBig(). OFTReal fields will be cast to\n"
+		"integer. Other field types, or errors will result in a return value of\n"
+		"zero.\n"
+		"\n"
+		"This function is the same as the C++ method\n"
+		"OGRFeature::GetFieldAsInteger64().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hFeat:  handle to the feature that owned the field.\n"
+		"\n"
+		"iField:  the field to fetch, from 0 to GetFieldCount()-1.\n"
+		"\n"
+		"the field value.\n"
+		"\n"
+		"GDAL 2.0 \n"
 		""},
 	 { (char *)"Feature_GetFieldAsDouble", _wrap_Feature_GetFieldAsDouble, METH_VARARGS, (char *)"\n"
 		"GetFieldAsDouble(int id) -> double\n"
-		"Feature_GetFieldAsDouble(Feature self, char name) -> double\n"
+		"Feature_GetFieldAsDouble(Feature self, char const * name) -> double\n"
 		"\n"
 		"double\n"
 		"OGR_F_GetFieldAsDouble(OGRFeatureH hFeat, int iField)\n"
 		"\n"
 		"Fetch field value as a double.\n"
 		"\n"
-		"OFTString features will be translated using atof(). OFTInteger fields\n"
-		"will be cast to double. Other field types, or errors will result in a\n"
-		"return value of zero.\n"
+		"OFTString features will be translated using CPLAtof(). OFTInteger\n"
+		"fields will be cast to double. Other field types, or errors will\n"
+		"result in a return value of zero.\n"
 		"\n"
 		"This function is the same as the C++ method\n"
 		"OGRFeature::GetFieldAsDouble().\n"
@@ -25362,7 +28610,8 @@ static PyMethodDef SwigMethods[] = {
 		"the field value. \n"
 		""},
 	 { (char *)"Feature_GetFieldAsDateTime", _wrap_Feature_GetFieldAsDateTime, METH_VARARGS, (char *)"\n"
-		"Feature_GetFieldAsDateTime(Feature self, int id)\n"
+		"GetFieldAsDateTime(int id)\n"
+		"Feature_GetFieldAsDateTime(Feature self, char const * name)\n"
 		"\n"
 		"int\n"
 		"OGR_F_GetFieldAsDateTime(OGRFeatureH hFeat, int iField, int *pnYear,\n"
@@ -25399,10 +28648,14 @@ static PyMethodDef SwigMethods[] = {
 		"pnTZFlag:  (0=unknown, 1=localtime, 100=GMT, see data model for\n"
 		"details)\n"
 		"\n"
-		"TRUE on success or FALSE on failure. \n"
+		"TRUE on success or FALSE on failure.\n"
+		"\n"
+		"See:  Use OGR_F_GetFieldAsDateTimeEx() for second with millisecond\n"
+		"accuracy. \n"
 		""},
 	 { (char *)"Feature_GetFieldAsIntegerList", _wrap_Feature_GetFieldAsIntegerList, METH_VARARGS, (char *)"\n"
-		"Feature_GetFieldAsIntegerList(Feature self, int id)\n"
+		"GetFieldAsIntegerList(int id)\n"
+		"Feature_GetFieldAsIntegerList(Feature self, char const * name)\n"
 		"\n"
 		"const int*\n"
 		"OGR_F_GetFieldAsIntegerList(OGRFeatureH hFeat, int iField, int\n"
@@ -25428,9 +28681,38 @@ static PyMethodDef SwigMethods[] = {
 		"freed. Its lifetime may be very brief. If *pnCount is zero on return\n"
 		"the returned pointer may be NULL or non-NULL. \n"
 		""},
-	 { (char *)"Feature_GetFieldAsInteger64List", _wrap_Feature_GetFieldAsInteger64List, METH_VARARGS, (char *)"Feature_GetFieldAsInteger64List(Feature self, int id)"},
+	 { (char *)"Feature_GetFieldAsInteger64List", _wrap_Feature_GetFieldAsInteger64List, METH_VARARGS, (char *)"\n"
+		"Feature_GetFieldAsInteger64List(Feature self, int id)\n"
+		"\n"
+		"const GIntBig*\n"
+		"OGR_F_GetFieldAsInteger64List(OGRFeatureH hFeat, int iField, int\n"
+		"*pnCount)\n"
+		"\n"
+		"Fetch field value as a list of 64 bit integers.\n"
+		"\n"
+		"Currently this function only works for OFTInteger64List fields.\n"
+		"\n"
+		"This function is the same as the C++ method\n"
+		"OGRFeature::GetFieldAsInteger64List().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hFeat:  handle to the feature that owned the field.\n"
+		"\n"
+		"iField:  the field to fetch, from 0 to GetFieldCount()-1.\n"
+		"\n"
+		"pnCount:  an integer to put the list count (number of integers) into.\n"
+		"\n"
+		"the field value. This list is internal, and should not be modified, or\n"
+		"freed. Its lifetime may be very brief. If *pnCount is zero on return\n"
+		"the returned pointer may be NULL or non-NULL.\n"
+		"\n"
+		"GDAL 2.0 \n"
+		""},
 	 { (char *)"Feature_GetFieldAsDoubleList", _wrap_Feature_GetFieldAsDoubleList, METH_VARARGS, (char *)"\n"
-		"Feature_GetFieldAsDoubleList(Feature self, int id)\n"
+		"GetFieldAsDoubleList(int id)\n"
+		"Feature_GetFieldAsDoubleList(Feature self, char const * name)\n"
 		"\n"
 		"const double*\n"
 		"OGR_F_GetFieldAsDoubleList(OGRFeatureH hFeat, int iField, int\n"
@@ -25457,7 +28739,7 @@ static PyMethodDef SwigMethods[] = {
 		"the returned pointer may be NULL or non-NULL. \n"
 		""},
 	 { (char *)"Feature_GetFieldAsStringList", _wrap_Feature_GetFieldAsStringList, METH_VARARGS, (char *)"\n"
-		"Feature_GetFieldAsStringList(Feature self, int id) -> char\n"
+		"Feature_GetFieldAsStringList(Feature self, int id) -> char **\n"
 		"\n"
 		"char**\n"
 		"OGR_F_GetFieldAsStringList(OGRFeatureH hFeat, int iField)\n"
@@ -25484,14 +28766,14 @@ static PyMethodDef SwigMethods[] = {
 		""},
 	 { (char *)"Feature_GetFieldAsBinary", _wrap_Feature_GetFieldAsBinary, METH_VARARGS, (char *)"\n"
 		"GetFieldAsBinary(int id) -> OGRErr\n"
-		"Feature_GetFieldAsBinary(Feature self, char name) -> OGRErr\n"
+		"Feature_GetFieldAsBinary(Feature self, char const * name) -> OGRErr\n"
 		"\n"
 		"GByte*\n"
 		"OGR_F_GetFieldAsBinary(OGRFeatureH hFeat, int iField, int *pnBytes)\n"
 		"\n"
 		"Fetch field value as binary.\n"
 		"\n"
-		"Currently this method only works for OFTBinary fields.\n"
+		"This method only works for OFTBinary and OFTString fields.\n"
 		"\n"
 		"This function is the same as the C++ method\n"
 		"OGRFeature::GetFieldAsBinary().\n"
@@ -25510,7 +28792,7 @@ static PyMethodDef SwigMethods[] = {
 		""},
 	 { (char *)"Feature_IsFieldSet", _wrap_Feature_IsFieldSet, METH_VARARGS, (char *)"\n"
 		"IsFieldSet(int id) -> bool\n"
-		"Feature_IsFieldSet(Feature self, char name) -> bool\n"
+		"Feature_IsFieldSet(Feature self, char const * name) -> bool\n"
 		"\n"
 		"int OGR_F_IsFieldSet(OGRFeatureH\n"
 		"hFeat, int iField)\n"
@@ -25529,7 +28811,7 @@ static PyMethodDef SwigMethods[] = {
 		"TRUE if the field has been set, otherwise false. \n"
 		""},
 	 { (char *)"Feature_GetFieldIndex", _wrap_Feature_GetFieldIndex, METH_VARARGS, (char *)"\n"
-		"Feature_GetFieldIndex(Feature self, char name) -> int\n"
+		"Feature_GetFieldIndex(Feature self, char const * name) -> int\n"
 		"\n"
 		"int\n"
 		"OGR_F_GetFieldIndex(OGRFeatureH hFeat, const char *pszName)\n"
@@ -25550,15 +28832,42 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"the field index, or -1 if no matching field is found. \n"
 		""},
-	 { (char *)"Feature_GetGeomFieldIndex", _wrap_Feature_GetGeomFieldIndex, METH_VARARGS, (char *)"Feature_GetGeomFieldIndex(Feature self, char name) -> int"},
+	 { (char *)"Feature_GetGeomFieldIndex", _wrap_Feature_GetGeomFieldIndex, METH_VARARGS, (char *)"\n"
+		"Feature_GetGeomFieldIndex(Feature self, char const * name) -> int\n"
+		"\n"
+		"int\n"
+		"OGR_F_GetGeomFieldIndex(OGRFeatureH hFeat, const char *pszName)\n"
+		"\n"
+		"Fetch the geometry field index given geometry field name.\n"
+		"\n"
+		"This is a cover for the OGRFeatureDefn::GetGeomFieldIndex() method.\n"
+		"\n"
+		"This function is the same as the C++ method\n"
+		"OGRFeature::GetGeomFieldIndex().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hFeat:  handle to the feature on which the geometry field is found.\n"
+		"\n"
+		"pszName:  the name of the geometry field to search for.\n"
+		"\n"
+		"the geometry field index, or -1 if no matching geometry field is\n"
+		"found.\n"
+		"\n"
+		"GDAL 1.11 \n"
+		""},
 	 { (char *)"Feature_GetFID", _wrap_Feature_GetFID, METH_VARARGS, (char *)"\n"
 		"Feature_GetFID(Feature self) -> GIntBig\n"
 		"\n"
-		"long OGR_F_GetFID(OGRFeatureH hFeat)\n"
+		"GIntBig OGR_F_GetFID(OGRFeatureH\n"
+		"hFeat)\n"
 		"\n"
 		"Get feature identifier.\n"
 		"\n"
 		"This function is the same as the C++ method OGRFeature::GetFID().\n"
+		"Note: since GDAL 2.0, this method returns a GIntBig (previously a\n"
+		"long)\n"
 		"\n"
 		"Parameters:\n"
 		"-----------\n"
@@ -25572,7 +28881,7 @@ static PyMethodDef SwigMethods[] = {
 		"Feature_SetFID(Feature self, GIntBig fid) -> OGRErr\n"
 		"\n"
 		"OGRErr OGR_F_SetFID(OGRFeatureH hFeat,\n"
-		"long nFID)\n"
+		"GIntBig nFID)\n"
 		"\n"
 		"Set the feature identifier.\n"
 		"\n"
@@ -25616,7 +28925,7 @@ static PyMethodDef SwigMethods[] = {
 		""},
 	 { (char *)"Feature_UnsetField", _wrap_Feature_UnsetField, METH_VARARGS, (char *)"\n"
 		"UnsetField(int id)\n"
-		"Feature_UnsetField(Feature self, char name)\n"
+		"Feature_UnsetField(Feature self, char const * name)\n"
 		"\n"
 		"void OGR_F_UnsetField(OGRFeatureH\n"
 		"hFeat, int iField)\n"
@@ -25632,16 +28941,40 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"iField:  the field to unset. \n"
 		""},
-	 { (char *)"Feature_SetFieldInteger64", _wrap_Feature_SetFieldInteger64, METH_VARARGS, (char *)"Feature_SetFieldInteger64(Feature self, int id, GIntBig value)"},
+	 { (char *)"Feature_SetFieldInteger64", _wrap_Feature_SetFieldInteger64, METH_VARARGS, (char *)"\n"
+		"Feature_SetFieldInteger64(Feature self, int id, GIntBig value)\n"
+		"\n"
+		"void\n"
+		"OGR_F_SetFieldInteger64(OGRFeatureH hFeat, int iField, GIntBig nValue)\n"
+		"\n"
+		"Set field to 64 bit integer value.\n"
+		"\n"
+		"OFTInteger, OFTInteger64 and OFTReal fields will be set directly.\n"
+		"OFTString fields will be assigned a string representation of the\n"
+		"value, but not necessarily taking into account formatting constraints\n"
+		"on this field. Other field types may be unaffected.\n"
+		"\n"
+		"This function is the same as the C++ method OGRFeature::SetField().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hFeat:  handle to the feature that owned the field.\n"
+		"\n"
+		"iField:  the field to fetch, from 0 to GetFieldCount()-1.\n"
+		"\n"
+		"nValue:  the value to assign.\n"
+		"\n"
+		"GDAL 2.0 \n"
+		""},
 	 { (char *)"Feature_SetField", _wrap_Feature_SetField, METH_VARARGS, (char *)"\n"
-		"SetField(int id, char value)\n"
-		"SetField(char name, char value)\n"
+		"SetField(int id, char const * value)\n"
+		"SetField(char const * name, char const * value)\n"
 		"SetField(int id, double value)\n"
-		"SetField(char name, double value)\n"
-		"SetField(int id, int year, int month, int day, int hour, int minute, \n"
+		"SetField(char const * name, double value)\n"
+		"SetField(int id, int year, int month, int day, int hour, int minute, float second, int tzflag)\n"
+		"Feature_SetField(Feature self, char const * name, int year, int month, int day, int hour, int minute, \n"
 		"    float second, int tzflag)\n"
-		"Feature_SetField(Feature self, char name, int year, int month, int day, \n"
-		"    int hour, int minute, float second, int tzflag)\n"
 		""},
 	 { (char *)"Feature_SetFieldIntegerList", _wrap_Feature_SetFieldIntegerList, METH_VARARGS, (char *)"\n"
 		"Feature_SetFieldIntegerList(Feature self, int id, int nList)\n"
@@ -25652,7 +28985,8 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"Set field to list of integers value.\n"
 		"\n"
-		"This function currently on has an effect of OFTIntegerList fields.\n"
+		"This function currently on has an effect of OFTIntegerList,\n"
+		"OFTInteger64List and OFTRealList fields.\n"
 		"\n"
 		"This function is the same as the C++ method OGRFeature::SetField().\n"
 		"\n"
@@ -25667,7 +29001,33 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"panValues:  the values to assign. \n"
 		""},
-	 { (char *)"Feature_SetFieldInteger64List", _wrap_Feature_SetFieldInteger64List, METH_VARARGS, (char *)"Feature_SetFieldInteger64List(Feature self, int id, int nList)"},
+	 { (char *)"Feature_SetFieldInteger64List", _wrap_Feature_SetFieldInteger64List, METH_VARARGS, (char *)"\n"
+		"Feature_SetFieldInteger64List(Feature self, int id, int nList)\n"
+		"\n"
+		"void\n"
+		"OGR_F_SetFieldInteger64List(OGRFeatureH hFeat, int iField, int nCount,\n"
+		"const GIntBig *panValues)\n"
+		"\n"
+		"Set field to list of 64 bit integers value.\n"
+		"\n"
+		"This function currently on has an effect of OFTIntegerList,\n"
+		"OFTInteger64List and OFTRealList fields.\n"
+		"\n"
+		"This function is the same as the C++ method OGRFeature::SetField().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hFeat:  handle to the feature that owned the field.\n"
+		"\n"
+		"iField:  the field to set, from 0 to GetFieldCount()-1.\n"
+		"\n"
+		"nCount:  the number of values in the list being assigned.\n"
+		"\n"
+		"panValues:  the values to assign.\n"
+		"\n"
+		"GDAL 2.0 \n"
+		""},
 	 { (char *)"Feature_SetFieldDoubleList", _wrap_Feature_SetFieldDoubleList, METH_VARARGS, (char *)"\n"
 		"Feature_SetFieldDoubleList(Feature self, int id, int nList)\n"
 		"\n"
@@ -25677,7 +29037,8 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"Set field to list of doubles value.\n"
 		"\n"
-		"This function currently on has an effect of OFTRealList fields.\n"
+		"This function currently on has an effect of OFTIntegerList,\n"
+		"OFTInteger64List, OFTRealList fields.\n"
 		"\n"
 		"This function is the same as the C++ method OGRFeature::SetField().\n"
 		"\n"
@@ -25693,7 +29054,7 @@ static PyMethodDef SwigMethods[] = {
 		"padfValues:  the values to assign. \n"
 		""},
 	 { (char *)"Feature_SetFieldStringList", _wrap_Feature_SetFieldStringList, METH_VARARGS, (char *)"\n"
-		"Feature_SetFieldStringList(Feature self, int id, char pList)\n"
+		"Feature_SetFieldStringList(Feature self, int id, char ** pList)\n"
 		"\n"
 		"void\n"
 		"OGR_F_SetFieldStringList(OGRFeatureH hFeat, int iField, char\n"
@@ -25715,11 +29076,11 @@ static PyMethodDef SwigMethods[] = {
 		"papszValues:  the values to assign. \n"
 		""},
 	 { (char *)"Feature_SetFieldBinaryFromHexString", _wrap_Feature_SetFieldBinaryFromHexString, METH_VARARGS, (char *)"\n"
-		"SetFieldBinaryFromHexString(int id, char pszValue)\n"
-		"Feature_SetFieldBinaryFromHexString(Feature self, char name, char pszValue)\n"
+		"SetFieldBinaryFromHexString(int id, char const * pszValue)\n"
+		"Feature_SetFieldBinaryFromHexString(Feature self, char const * name, char const * pszValue)\n"
 		""},
 	 { (char *)"Feature_SetFrom", (PyCFunction) _wrap_Feature_SetFrom, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Feature_SetFrom(Feature self, Feature other, int forgiving = 1) -> OGRErr\n"
+		"Feature_SetFrom(Feature self, Feature other, int forgiving=1) -> OGRErr\n"
 		"\n"
 		"OGRErr OGR_F_SetFrom(OGRFeatureH\n"
 		"hFeat, OGRFeatureH hOtherFeat, int bForgiving)\n"
@@ -25789,7 +29150,7 @@ static PyMethodDef SwigMethods[] = {
 		"transferred, otherwise an error code. \n"
 		""},
 	 { (char *)"Feature_GetStyleString", _wrap_Feature_GetStyleString, METH_VARARGS, (char *)"\n"
-		"Feature_GetStyleString(Feature self) -> char\n"
+		"Feature_GetStyleString(Feature self) -> char const *\n"
 		"\n"
 		"const char*\n"
 		"OGR_F_GetStyleString(OGRFeatureH hFeat)\n"
@@ -25812,14 +29173,16 @@ static PyMethodDef SwigMethods[] = {
 		"isn't one. \n"
 		""},
 	 { (char *)"Feature_SetStyleString", _wrap_Feature_SetStyleString, METH_VARARGS, (char *)"\n"
-		"Feature_SetStyleString(Feature self, char the_string)\n"
+		"Feature_SetStyleString(Feature self, char const * the_string)\n"
 		"\n"
 		"void\n"
 		"OGR_F_SetStyleString(OGRFeatureH hFeat, const char *pszStyle)\n"
 		"\n"
-		"Set feature style string. This method operate exactly as\n"
-		"OGR_F_SetStyleStringDirectly() except that it does not assume\n"
-		"ownership of the passed string, but instead makes a copy of it.\n"
+		"Set feature style string.\n"
+		"\n"
+		"This method operate exactly as OGR_F_SetStyleStringDirectly() except\n"
+		"that it does not assume ownership of the passed string, but instead\n"
+		"makes a copy of it.\n"
 		"\n"
 		"This function is the same as the C++ method\n"
 		"OGRFeature::SetStyleString().\n"
@@ -25834,12 +29197,196 @@ static PyMethodDef SwigMethods[] = {
 		""},
 	 { (char *)"Feature_GetFieldType", _wrap_Feature_GetFieldType, METH_VARARGS, (char *)"\n"
 		"GetFieldType(int id) -> OGRFieldType\n"
-		"Feature_GetFieldType(Feature self, char name) -> OGRFieldType\n"
+		"Feature_GetFieldType(Feature self, char const * name) -> OGRFieldType\n"
+		""},
+	 { (char *)"Feature_Validate", _wrap_Feature_Validate, METH_VARARGS, (char *)"\n"
+		"Feature_Validate(Feature self, int flags=OGR_F_VAL_ALL, int bEmitError=True) -> int\n"
+		"\n"
+		"int OGR_F_Validate(OGRFeatureH\n"
+		"hFeat, int nValidateFlags, int bEmitError)\n"
+		"\n"
+		"Validate that a feature meets constraints of its schema.\n"
+		"\n"
+		"The scope of test is specified with the nValidateFlags parameter.\n"
+		"\n"
+		"Regarding OGR_F_VAL_WIDTH, the test is done assuming the string width\n"
+		"must be interpreted as the number of UTF-8 characters. Some drivers\n"
+		"might interpret the width as the number of bytes instead. So this test\n"
+		"is rather conservative (if it fails, then it will fail for all\n"
+		"interpretations).\n"
+		"\n"
+		"This function is the same as the C++ method OGRFeature::Validate().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hFeat:  handle to the feature to validate.\n"
+		"\n"
+		"nValidateFlags:  OGR_F_VAL_ALL or combination of OGR_F_VAL_NULL,\n"
+		"OGR_F_VAL_GEOM_TYPE, OGR_F_VAL_WIDTH and\n"
+		"OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT with '|' operator\n"
+		"\n"
+		"bEmitError:  TRUE if a CPLError() must be emitted when a check fails\n"
+		"\n"
+		"TRUE if all enabled validation tests pass.\n"
+		"\n"
+		"GDAL 2.0 \n"
+		""},
+	 { (char *)"Feature_FillUnsetWithDefault", _wrap_Feature_FillUnsetWithDefault, METH_VARARGS, (char *)"\n"
+		"Feature_FillUnsetWithDefault(Feature self, int bNotNullableOnly=False, char ** options=None)\n"
+		"\n"
+		"void\n"
+		"OGR_F_FillUnsetWithDefault(OGRFeatureH hFeat, int bNotNullableOnly,\n"
+		"char **papszOptions)\n"
+		"\n"
+		"Fill unset fields with default values that might be defined.\n"
+		"\n"
+		"This function is the same as the C++ method\n"
+		"OGRFeature::FillUnsetWithDefault().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hFeat:  handle to the feature.\n"
+		"\n"
+		"bNotNullableOnly:  if we should fill only unset fields with a not-null\n"
+		"constraint.\n"
+		"\n"
+		"papszOptions:  unused currently. Must be set to NULL.\n"
+		"\n"
+		"GDAL 2.0 \n"
+		""},
+	 { (char *)"Feature_GetNativeData", _wrap_Feature_GetNativeData, METH_VARARGS, (char *)"\n"
+		"Feature_GetNativeData(Feature self) -> char const *\n"
+		"\n"
+		"const char*\n"
+		"OGR_F_GetNativeData(OGRFeatureH hFeat)\n"
+		"\n"
+		"Returns the native data for the feature.\n"
+		"\n"
+		"The native data is the representation in a \"natural\" form that comes\n"
+		"from the driver that created this feature, or that is aimed at an\n"
+		"output driver. The native data may be in different format, which is\n"
+		"indicated by OGR_F_GetNativeMediaType().\n"
+		"\n"
+		"Note that most drivers do not support storing the native data in the\n"
+		"feature object, and if they do, generally the NATIVE_DATA open option\n"
+		"must be passed at dataset opening.\n"
+		"\n"
+		"The \"native data\" does not imply it is something more performant or\n"
+		"powerful than what can be obtained with the rest of the API, but it\n"
+		"may be useful in round-tripping scenarios where some characteristics\n"
+		"of the underlying format are not captured otherwise by the OGR\n"
+		"abstraction.\n"
+		"\n"
+		"This function is the same as the C++ method\n"
+		"OGRFeature::GetNativeData().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hFeat:  handle to the feature.\n"
+		"\n"
+		"a string with the native data, or NULL if there is none.\n"
+		"\n"
+		"GDAL 2.1\n"
+		"\n"
+		"See:\n"
+		"https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr\n"
+		"\n"
+		""},
+	 { (char *)"Feature_GetNativeMediaType", _wrap_Feature_GetNativeMediaType, METH_VARARGS, (char *)"\n"
+		"Feature_GetNativeMediaType(Feature self) -> char const *\n"
+		"\n"
+		"const char*\n"
+		"OGR_F_GetNativeMediaType(OGRFeatureH hFeat)\n"
+		"\n"
+		"Returns the native media type for the feature.\n"
+		"\n"
+		"The native media type is the identifier for the format of the native\n"
+		"data. It follows the IANA RFC 2045\n"
+		"(seehttps://en.wikipedia.org/wiki/Media_type), e.g.\n"
+		"\"application/vnd.geo+json\" for JSon.\n"
+		"\n"
+		"This function is the same as the C function\n"
+		"OGR_F_GetNativeMediaType().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hFeat:  handle to the feature.\n"
+		"\n"
+		"a string with the native media type, or NULL if there is none.\n"
+		"\n"
+		"GDAL 2.1\n"
+		"\n"
+		"See:\n"
+		"https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr\n"
+		"\n"
+		""},
+	 { (char *)"Feature_SetNativeData", _wrap_Feature_SetNativeData, METH_VARARGS, (char *)"\n"
+		"Feature_SetNativeData(Feature self, char const * nativeData)\n"
+		"\n"
+		"void\n"
+		"OGR_F_SetNativeData(OGRFeatureH hFeat, const char *pszNativeData)\n"
+		"\n"
+		"Sets the native data for the feature.\n"
+		"\n"
+		"The native data is the representation in a \"natural\" form that comes\n"
+		"from the driver that created this feature, or that is aimed at an\n"
+		"output driver. The native data may be in different format, which is\n"
+		"indicated by OGR_F_GetNativeMediaType().\n"
+		"\n"
+		"This function is the same as the C++ method\n"
+		"OGRFeature::SetNativeData().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hFeat:  handle to the feature.\n"
+		"\n"
+		"pszNativeData:  a string with the native data, or NULL if there is\n"
+		"none.\n"
+		"\n"
+		"GDAL 2.1\n"
+		"\n"
+		"See:\n"
+		"https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr\n"
+		"\n"
+		""},
+	 { (char *)"Feature_SetNativeMediaType", _wrap_Feature_SetNativeMediaType, METH_VARARGS, (char *)"\n"
+		"Feature_SetNativeMediaType(Feature self, char const * nativeMediaType)\n"
+		"\n"
+		"void\n"
+		"OGR_F_SetNativeMediaType(OGRFeatureH hFeat, const char\n"
+		"*pszNativeMediaType)\n"
+		"\n"
+		"Sets the native media type for the feature.\n"
+		"\n"
+		"The native media type is the identifier for the format of the native\n"
+		"data. It follows the IANA RFC 2045\n"
+		"(seehttps://en.wikipedia.org/wiki/Media_type), e.g.\n"
+		"\"application/vnd.geo+json\" for JSon.\n"
+		"\n"
+		"This function is the same as the C++ method\n"
+		"OGRFeature::SetNativeMediaType().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hFeat:  handle to the feature.\n"
+		"\n"
+		"pszNativeMediaType:  a string with the native media type, or NULL if\n"
+		"there is none.\n"
+		"\n"
+		"GDAL 2.1\n"
+		"\n"
+		"See:\n"
+		"https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr\n"
+		"\n"
 		""},
-	 { (char *)"Feature_Validate", _wrap_Feature_Validate, METH_VARARGS, (char *)"Feature_Validate(Feature self, int flags = OGR_F_VAL_ALL, int bEmitError = TRUE) -> int"},
-	 { (char *)"Feature_FillUnsetWithDefault", _wrap_Feature_FillUnsetWithDefault, METH_VARARGS, (char *)"Feature_FillUnsetWithDefault(Feature self, int bNotNullableOnly = True, char options = None)"},
 	 { (char *)"Feature_SetFieldString", _wrap_Feature_SetFieldString, METH_VARARGS, (char *)"\n"
-		"Feature_SetFieldString(Feature self, int id, char value)\n"
+		"Feature_SetFieldString(Feature self, int id, char const * value)\n"
 		"\n"
 		"void\n"
 		"OGR_F_SetFieldString(OGRFeatureH hFeat, int iField, const char\n"
@@ -25848,8 +29395,10 @@ static PyMethodDef SwigMethods[] = {
 		"Set field to string value.\n"
 		"\n"
 		"OFTInteger fields will be set based on an atoi() conversion of the\n"
-		"string. OFTReal fields will be set based on an atof() conversion of\n"
-		"the string. Other field types may be unaffected.\n"
+		"string. OFTInteger64 fields will be set based on an CPLAtoGIntBig()\n"
+		"conversion of the string. OFTReal fields will be set based on an\n"
+		"CPLAtof() conversion of the string. Other field types may be\n"
+		"unaffected.\n"
 		"\n"
 		"This function is the same as the C++ method OGRFeature::SetField().\n"
 		"\n"
@@ -25864,9 +29413,9 @@ static PyMethodDef SwigMethods[] = {
 		""},
 	 { (char *)"Feature_swigregister", Feature_swigregister, METH_VARARGS, NULL},
 	 { (char *)"delete_FeatureDefn", _wrap_delete_FeatureDefn, METH_VARARGS, (char *)"delete_FeatureDefn(FeatureDefn self)"},
-	 { (char *)"new_FeatureDefn", (PyCFunction) _wrap_new_FeatureDefn, METH_VARARGS | METH_KEYWORDS, (char *)"new_FeatureDefn(char name_null_ok = None) -> FeatureDefn"},
+	 { (char *)"new_FeatureDefn", (PyCFunction) _wrap_new_FeatureDefn, METH_VARARGS | METH_KEYWORDS, (char *)"new_FeatureDefn(char const * name_null_ok=None) -> FeatureDefn"},
 	 { (char *)"FeatureDefn_GetName", _wrap_FeatureDefn_GetName, METH_VARARGS, (char *)"\n"
-		"FeatureDefn_GetName(FeatureDefn self) -> char\n"
+		"FeatureDefn_GetName(FeatureDefn self) -> char const *\n"
 		"\n"
 		"const char*\n"
 		"OGR_FD_GetName(OGRFeatureDefnH hDefn)\n"
@@ -25927,7 +29476,7 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		""},
 	 { (char *)"FeatureDefn_GetFieldIndex", _wrap_FeatureDefn_GetFieldIndex, METH_VARARGS, (char *)"\n"
-		"FeatureDefn_GetFieldIndex(FeatureDefn self, char name) -> int\n"
+		"FeatureDefn_GetFieldIndex(FeatureDefn self, char const * name) -> int\n"
 		"\n"
 		"int\n"
 		"OGR_FD_GetFieldIndex(OGRFeatureDefnH hDefn, const char *pszFieldName)\n"
@@ -25961,7 +29510,7 @@ static PyMethodDef SwigMethods[] = {
 		"function directly, but use OGR_L_CreateField() instead.\n"
 		"\n"
 		"This function should only be called while there are no OGRFeature\n"
-		"objects in existance based on this OGRFeatureDefn. The OGRFieldDefn\n"
+		"objects in existence based on this OGRFeatureDefn. The OGRFieldDefn\n"
 		"passed in is copied, and remains the responsibility of the caller.\n"
 		"\n"
 		"This function is the same as the C++ method\n"
@@ -25975,11 +29524,134 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"hNewField:  handle to the new field definition. \n"
 		""},
-	 { (char *)"FeatureDefn_GetGeomFieldCount", _wrap_FeatureDefn_GetGeomFieldCount, METH_VARARGS, (char *)"FeatureDefn_GetGeomFieldCount(FeatureDefn self) -> int"},
-	 { (char *)"FeatureDefn_GetGeomFieldDefn", _wrap_FeatureDefn_GetGeomFieldDefn, METH_VARARGS, (char *)"FeatureDefn_GetGeomFieldDefn(FeatureDefn self, int i) -> GeomFieldDefn"},
-	 { (char *)"FeatureDefn_GetGeomFieldIndex", _wrap_FeatureDefn_GetGeomFieldIndex, METH_VARARGS, (char *)"FeatureDefn_GetGeomFieldIndex(FeatureDefn self, char name) -> int"},
-	 { (char *)"FeatureDefn_AddGeomFieldDefn", _wrap_FeatureDefn_AddGeomFieldDefn, METH_VARARGS, (char *)"FeatureDefn_AddGeomFieldDefn(FeatureDefn self, GeomFieldDefn defn)"},
-	 { (char *)"FeatureDefn_DeleteGeomFieldDefn", _wrap_FeatureDefn_DeleteGeomFieldDefn, METH_VARARGS, (char *)"FeatureDefn_DeleteGeomFieldDefn(FeatureDefn self, int idx) -> OGRErr"},
+	 { (char *)"FeatureDefn_GetGeomFieldCount", _wrap_FeatureDefn_GetGeomFieldCount, METH_VARARGS, (char *)"\n"
+		"FeatureDefn_GetGeomFieldCount(FeatureDefn self) -> int\n"
+		"\n"
+		"int\n"
+		"OGR_FD_GetGeomFieldCount(OGRFeatureDefnH hDefn)\n"
+		"\n"
+		"Fetch number of geometry fields on the passed feature definition.\n"
+		"\n"
+		"This function is the same as the C++\n"
+		"OGRFeatureDefn::GetGeomFieldCount().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hDefn:  handle to the feature definition to get the fields count from.\n"
+		"\n"
+		"count of geometry fields.\n"
+		"\n"
+		"GDAL 1.11 \n"
+		""},
+	 { (char *)"FeatureDefn_GetGeomFieldDefn", _wrap_FeatureDefn_GetGeomFieldDefn, METH_VARARGS, (char *)"\n"
+		"FeatureDefn_GetGeomFieldDefn(FeatureDefn self, int i) -> GeomFieldDefn\n"
+		"\n"
+		"OGRGeomFieldDefnH\n"
+		"OGR_FD_GetGeomFieldDefn(OGRFeatureDefnH hDefn, int iGeomField)\n"
+		"\n"
+		"Fetch geometry field definition of the passed feature definition.\n"
+		"\n"
+		"This function is the same as the C++ method\n"
+		"OGRFeatureDefn::GetGeomFieldDefn().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hDefn:  handle to the feature definition to get the field definition\n"
+		"from.\n"
+		"\n"
+		"iGeomField:  the geometry field to fetch, between 0 and\n"
+		"GetGeomFieldCount()-1.\n"
+		"\n"
+		"an handle to an internal field definition object or NULL if invalid\n"
+		"index. This object should not be modified or freed by the application.\n"
+		"\n"
+		"GDAL 1.11 \n"
+		""},
+	 { (char *)"FeatureDefn_GetGeomFieldIndex", _wrap_FeatureDefn_GetGeomFieldIndex, METH_VARARGS, (char *)"\n"
+		"FeatureDefn_GetGeomFieldIndex(FeatureDefn self, char const * name) -> int\n"
+		"\n"
+		"int\n"
+		"OGR_FD_GetGeomFieldIndex(OGRFeatureDefnH hDefn, const char\n"
+		"*pszGeomFieldName)\n"
+		"\n"
+		"Find geometry field by name.\n"
+		"\n"
+		"The geometry field index of the first geometry field matching the\n"
+		"passed field name (case insensitively) is returned.\n"
+		"\n"
+		"This function is the same as the C++ method\n"
+		"OGRFeatureDefn::GetGeomFieldIndex.\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hDefn:  handle to the feature definition to get field index from.\n"
+		"\n"
+		"pszGeomFieldName:  the geometry field name to search for.\n"
+		"\n"
+		"the geometry field index, or -1 if no match found. \n"
+		""},
+	 { (char *)"FeatureDefn_AddGeomFieldDefn", _wrap_FeatureDefn_AddGeomFieldDefn, METH_VARARGS, (char *)"\n"
+		"FeatureDefn_AddGeomFieldDefn(FeatureDefn self, GeomFieldDefn defn)\n"
+		"\n"
+		"void\n"
+		"OGR_FD_AddGeomFieldDefn(OGRFeatureDefnH hDefn, OGRGeomFieldDefnH\n"
+		"hNewGeomField)\n"
+		"\n"
+		"Add a new field definition to the passed feature definition.\n"
+		"\n"
+		"To add a new field definition to a layer definition, do not use this\n"
+		"function directly, but use OGR_L_CreateGeomField() instead.\n"
+		"\n"
+		"This function should only be called while there are no OGRFeature\n"
+		"objects in existence based on this OGRFeatureDefn. The\n"
+		"OGRGeomFieldDefn passed in is copied, and remains the responsibility\n"
+		"of the caller.\n"
+		"\n"
+		"This function is the same as the C++ method\n"
+		"OGRFeatureDefn::AddGeomFieldDefn().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hDefn:  handle to the feature definition to add the geometry field\n"
+		"definition to.\n"
+		"\n"
+		"hNewGeomField:  handle to the new field definition.\n"
+		"\n"
+		"GDAL 1.11 \n"
+		""},
+	 { (char *)"FeatureDefn_DeleteGeomFieldDefn", _wrap_FeatureDefn_DeleteGeomFieldDefn, METH_VARARGS, (char *)"\n"
+		"FeatureDefn_DeleteGeomFieldDefn(FeatureDefn self, int idx) -> OGRErr\n"
+		"\n"
+		"OGRErr\n"
+		"OGR_FD_DeleteGeomFieldDefn(OGRFeatureDefnH hDefn, int iGeomField)\n"
+		"\n"
+		"Delete an existing geometry field definition.\n"
+		"\n"
+		"To delete an existing geometry field definition from a layer\n"
+		"definition, do not use this function directly, but use\n"
+		"OGR_L_DeleteGeomField() instead (*not implemented yet*).\n"
+		"\n"
+		"This method should only be called while there are no OGRFeature\n"
+		"objects in existence based on this OGRFeatureDefn.\n"
+		"\n"
+		"This method is the same as the C++ method\n"
+		"OGRFeatureDefn::DeleteGeomFieldDefn().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hDefn:  handle to the feature definition.\n"
+		"\n"
+		"iGeomField:  the index of the geometry field definition.\n"
+		"\n"
+		"OGRERR_NONE in case of success.\n"
+		"\n"
+		"GDAL 1.11 \n"
+		""},
 	 { (char *)"FeatureDefn_GetGeomType", _wrap_FeatureDefn_GetGeomType, METH_VARARGS, (char *)"\n"
 		"FeatureDefn_GetGeomType(FeatureDefn self) -> OGRwkbGeometryType\n"
 		"\n"
@@ -25991,6 +29663,9 @@ static PyMethodDef SwigMethods[] = {
 		"This function is the same as the C++ method\n"
 		"OGRFeatureDefn::GetGeomType().\n"
 		"\n"
+		"Starting with GDAL 1.11, this method returns\n"
+		"GetGeomFieldDefn(0)->GetType().\n"
+		"\n"
 		"Parameters:\n"
 		"-----------\n"
 		"\n"
@@ -26016,6 +29691,9 @@ static PyMethodDef SwigMethods[] = {
 		"This function is the same as the C++ method\n"
 		"OGRFeatureDefn::SetGeomType().\n"
 		"\n"
+		"Starting with GDAL 1.11, this method calls\n"
+		"GetGeomFieldDefn(0)->SetType().\n"
+		"\n"
 		"Parameters:\n"
 		"-----------\n"
 		"\n"
@@ -26038,7 +29716,7 @@ static PyMethodDef SwigMethods[] = {
 		"Parameters:\n"
 		"-----------\n"
 		"\n"
-		"hDefn:  hanlde to the feature definition on witch OGRFeature are based\n"
+		"hDefn:  handle to the feature definition on witch OGRFeature are based\n"
 		"on.\n"
 		"\n"
 		"the current reference count. \n"
@@ -26054,10 +29732,13 @@ static PyMethodDef SwigMethods[] = {
 		"This function is the same as the C++ method\n"
 		"OGRFeatureDefn::IsGeometryIgnored().\n"
 		"\n"
+		"Starting with GDAL 1.11, this method returns\n"
+		"GetGeomFieldDefn(0)->IsIgnored().\n"
+		"\n"
 		"Parameters:\n"
 		"-----------\n"
 		"\n"
-		"hDefn:  hanlde to the feature definition on witch OGRFeature are based\n"
+		"hDefn:  handle to the feature definition on witch OGRFeature are based\n"
 		"on.\n"
 		"\n"
 		"ignore state \n"
@@ -26073,10 +29754,13 @@ static PyMethodDef SwigMethods[] = {
 		"This function is the same as the C++ method\n"
 		"OGRFeatureDefn::SetGeometryIgnored().\n"
 		"\n"
+		"Starting with GDAL 1.11, this method calls\n"
+		"GetGeomFieldDefn(0)->SetIgnored().\n"
+		"\n"
 		"Parameters:\n"
 		"-----------\n"
 		"\n"
-		"hDefn:  hanlde to the feature definition on witch OGRFeature are based\n"
+		"hDefn:  handle to the feature definition on witch OGRFeature are based\n"
 		"on.\n"
 		"\n"
 		"bIgnore:  ignore state \n"
@@ -26114,18 +29798,37 @@ static PyMethodDef SwigMethods[] = {
 		"Parameters:\n"
 		"-----------\n"
 		"\n"
-		"hDefn:  hanlde to the feature definition on witch OGRFeature are based\n"
+		"hDefn:  handle to the feature definition on witch OGRFeature are based\n"
 		"on.\n"
 		"\n"
 		"bIgnore:  ignore state \n"
 		""},
-	 { (char *)"FeatureDefn_IsSame", _wrap_FeatureDefn_IsSame, METH_VARARGS, (char *)"FeatureDefn_IsSame(FeatureDefn self, FeatureDefn other_defn) -> int"},
+	 { (char *)"FeatureDefn_IsSame", _wrap_FeatureDefn_IsSame, METH_VARARGS, (char *)"\n"
+		"FeatureDefn_IsSame(FeatureDefn self, FeatureDefn other_defn) -> int\n"
+		"\n"
+		"int OGR_FD_IsSame(OGRFeatureDefnH\n"
+		"hFDefn, OGRFeatureDefnH hOtherFDefn)\n"
+		"\n"
+		"Test if the feature definition is identical to the other one.\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hFDefn:  handle to the feature definition on witch OGRFeature are\n"
+		"based on.\n"
+		"\n"
+		"hOtherFDefn:  handle to the other feature definition to compare to.\n"
+		"\n"
+		"TRUE if the feature definition is identical to the other one.\n"
+		"\n"
+		"OGR 1.11 \n"
+		""},
 	 { (char *)"FeatureDefn_swigregister", FeatureDefn_swigregister, METH_VARARGS, NULL},
 	 { (char *)"delete_FieldDefn", _wrap_delete_FieldDefn, METH_VARARGS, (char *)"delete_FieldDefn(FieldDefn self)"},
-	 { (char *)"new_FieldDefn", (PyCFunction) _wrap_new_FieldDefn, METH_VARARGS | METH_KEYWORDS, (char *)"new_FieldDefn(char name_null_ok = \"unnamed\", OGRFieldType field_type = OFTString) -> FieldDefn"},
-	 { (char *)"FieldDefn_GetName", _wrap_FieldDefn_GetName, METH_VARARGS, (char *)"FieldDefn_GetName(FieldDefn self) -> char"},
+	 { (char *)"new_FieldDefn", (PyCFunction) _wrap_new_FieldDefn, METH_VARARGS | METH_KEYWORDS, (char *)"new_FieldDefn(char const * name_null_ok=\"unnamed\", OGRFieldType field_type=OFTString) -> FieldDefn"},
+	 { (char *)"FieldDefn_GetName", _wrap_FieldDefn_GetName, METH_VARARGS, (char *)"FieldDefn_GetName(FieldDefn self) -> char const *"},
 	 { (char *)"FieldDefn_GetNameRef", _wrap_FieldDefn_GetNameRef, METH_VARARGS, (char *)"\n"
-		"FieldDefn_GetNameRef(FieldDefn self) -> char\n"
+		"FieldDefn_GetNameRef(FieldDefn self) -> char const *\n"
 		"\n"
 		"const char*\n"
 		"OGR_Fld_GetNameRef(OGRFieldDefnH hDefn)\n"
@@ -26143,7 +29846,7 @@ static PyMethodDef SwigMethods[] = {
 		"the name of the field definition. \n"
 		""},
 	 { (char *)"FieldDefn_SetName", _wrap_FieldDefn_SetName, METH_VARARGS, (char *)"\n"
-		"FieldDefn_SetName(FieldDefn self, char name)\n"
+		"FieldDefn_SetName(FieldDefn self, char const * name)\n"
 		"\n"
 		"void OGR_Fld_SetName(OGRFieldDefnH\n"
 		"hDefn, const char *pszName)\n"
@@ -26172,30 +29875,73 @@ static PyMethodDef SwigMethods[] = {
 		"Parameters:\n"
 		"-----------\n"
 		"\n"
-		"hDefn:  handle to the field definition to get type from.\n"
+		"hDefn:  handle to the field definition to get type from.\n"
+		"\n"
+		"field type. \n"
+		""},
+	 { (char *)"FieldDefn_SetType", _wrap_FieldDefn_SetType, METH_VARARGS, (char *)"\n"
+		"FieldDefn_SetType(FieldDefn self, OGRFieldType type)\n"
+		"\n"
+		"void OGR_Fld_SetType(OGRFieldDefnH\n"
+		"hDefn, OGRFieldType eType)\n"
+		"\n"
+		"Set the type of this field.\n"
+		"\n"
+		"This should never be done to an OGRFieldDefn that is already part of\n"
+		"an OGRFeatureDefn.\n"
+		"\n"
+		"This function is the same as the CPP method OGRFieldDefn::SetType().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hDefn:  handle to the field definition to set type to.\n"
+		"\n"
+		"eType:  the new field type. \n"
+		""},
+	 { (char *)"FieldDefn_GetSubType", _wrap_FieldDefn_GetSubType, METH_VARARGS, (char *)"\n"
+		"FieldDefn_GetSubType(FieldDefn self) -> OGRFieldSubType\n"
+		"\n"
+		"OGRFieldSubType\n"
+		"OGR_Fld_GetSubType(OGRFieldDefnH hDefn)\n"
+		"\n"
+		"Fetch subtype of this field.\n"
+		"\n"
+		"This function is the same as the CPP method\n"
+		"OGRFieldDefn::GetSubType().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hDefn:  handle to the field definition to get subtype from.\n"
 		"\n"
-		"field type. \n"
+		"field subtype.\n"
+		"\n"
+		"GDAL 2.0 \n"
 		""},
-	 { (char *)"FieldDefn_SetType", _wrap_FieldDefn_SetType, METH_VARARGS, (char *)"\n"
-		"FieldDefn_SetType(FieldDefn self, OGRFieldType type)\n"
+	 { (char *)"FieldDefn_SetSubType", _wrap_FieldDefn_SetSubType, METH_VARARGS, (char *)"\n"
+		"FieldDefn_SetSubType(FieldDefn self, OGRFieldSubType type)\n"
 		"\n"
-		"void OGR_Fld_SetType(OGRFieldDefnH\n"
-		"hDefn, OGRFieldType eType)\n"
+		"void\n"
+		"OGR_Fld_SetSubType(OGRFieldDefnH hDefn, OGRFieldSubType eSubType)\n"
 		"\n"
-		"Set the type of this field. This should never be done to an\n"
-		"OGRFieldDefn that is already part of an OGRFeatureDefn.\n"
+		"Set the subtype of this field.\n"
 		"\n"
-		"This function is the same as the CPP method OGRFieldDefn::SetType().\n"
+		"This should never be done to an OGRFieldDefn that is already part of\n"
+		"an OGRFeatureDefn.\n"
+		"\n"
+		"This function is the same as the CPP method\n"
+		"OGRFieldDefn::SetSubType().\n"
 		"\n"
 		"Parameters:\n"
 		"-----------\n"
 		"\n"
 		"hDefn:  handle to the field definition to set type to.\n"
 		"\n"
-		"eType:  the new field type. \n"
+		"eSubType:  the new field subtype.\n"
+		"\n"
+		"GDAL 2.0 \n"
 		""},
-	 { (char *)"FieldDefn_GetSubType", _wrap_FieldDefn_GetSubType, METH_VARARGS, (char *)"FieldDefn_GetSubType(FieldDefn self) -> OGRFieldSubType"},
-	 { (char *)"FieldDefn_SetSubType", _wrap_FieldDefn_SetSubType, METH_VARARGS, (char *)"FieldDefn_SetSubType(FieldDefn self, OGRFieldSubType type)"},
 	 { (char *)"FieldDefn_GetJustify", _wrap_FieldDefn_GetJustify, METH_VARARGS, (char *)"\n"
 		"FieldDefn_GetJustify(FieldDefn self) -> OGRJustification\n"
 		"\n"
@@ -26207,6 +29953,8 @@ static PyMethodDef SwigMethods[] = {
 		"This function is the same as the CPP method\n"
 		"OGRFieldDefn::GetJustify().\n"
 		"\n"
+		"Note: no driver is know to use the concept of field justification.\n"
+		"\n"
 		"Parameters:\n"
 		"-----------\n"
 		"\n"
@@ -26222,6 +29970,8 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"Set the justification for this field.\n"
 		"\n"
+		"Note: no driver is know to use the concept of field justification.\n"
+		"\n"
 		"This function is the same as the CPP method\n"
 		"OGRFieldDefn::SetJustify().\n"
 		"\n"
@@ -26272,8 +30022,9 @@ static PyMethodDef SwigMethods[] = {
 		"int\n"
 		"OGR_Fld_GetPrecision(OGRFieldDefnH hDefn)\n"
 		"\n"
-		"Get the formatting precision for this field. This should normally be\n"
-		"zero for fields of types other than OFTReal.\n"
+		"Get the formatting precision for this field.\n"
+		"\n"
+		"This should normally be zero for fields of types other than OFTReal.\n"
 		"\n"
 		"This function is the same as the CPP method\n"
 		"OGRFieldDefn::GetPrecision().\n"
@@ -26305,8 +30056,8 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"nPrecision:  the new precision. \n"
 		""},
-	 { (char *)"FieldDefn_GetTypeName", _wrap_FieldDefn_GetTypeName, METH_VARARGS, (char *)"FieldDefn_GetTypeName(FieldDefn self) -> char"},
-	 { (char *)"FieldDefn_GetFieldTypeName", _wrap_FieldDefn_GetFieldTypeName, METH_VARARGS, (char *)"FieldDefn_GetFieldTypeName(FieldDefn self, OGRFieldType type) -> char"},
+	 { (char *)"FieldDefn_GetTypeName", _wrap_FieldDefn_GetTypeName, METH_VARARGS, (char *)"FieldDefn_GetTypeName(FieldDefn self) -> char const *"},
+	 { (char *)"FieldDefn_GetFieldTypeName", _wrap_FieldDefn_GetFieldTypeName, METH_VARARGS, (char *)"FieldDefn_GetFieldTypeName(FieldDefn self, OGRFieldType type) -> char const *"},
 	 { (char *)"FieldDefn_IsIgnored", _wrap_FieldDefn_IsIgnored, METH_VARARGS, (char *)"\n"
 		"FieldDefn_IsIgnored(FieldDefn self) -> int\n"
 		"\n"
@@ -26332,7 +30083,7 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"Set whether this field should be omitted when fetching features.\n"
 		"\n"
-		"This method is the same as the C function OGRFieldDefn::SetIgnored().\n"
+		"This method is the same as the C++ method OGRFieldDefn::SetIgnored().\n"
 		"\n"
 		"Parameters:\n"
 		"-----------\n"
@@ -26341,17 +30092,146 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"ignore:  ignore state \n"
 		""},
-	 { (char *)"FieldDefn_IsNullable", _wrap_FieldDefn_IsNullable, METH_VARARGS, (char *)"FieldDefn_IsNullable(FieldDefn self) -> int"},
-	 { (char *)"FieldDefn_SetNullable", _wrap_FieldDefn_SetNullable, METH_VARARGS, (char *)"FieldDefn_SetNullable(FieldDefn self, int bNullable)"},
-	 { (char *)"FieldDefn_GetDefault", _wrap_FieldDefn_GetDefault, METH_VARARGS, (char *)"FieldDefn_GetDefault(FieldDefn self) -> char"},
-	 { (char *)"FieldDefn_SetDefault", _wrap_FieldDefn_SetDefault, METH_VARARGS, (char *)"FieldDefn_SetDefault(FieldDefn self, char pszValue)"},
-	 { (char *)"FieldDefn_IsDefaultDriverSpecific", _wrap_FieldDefn_IsDefaultDriverSpecific, METH_VARARGS, (char *)"FieldDefn_IsDefaultDriverSpecific(FieldDefn self) -> int"},
+	 { (char *)"FieldDefn_IsNullable", _wrap_FieldDefn_IsNullable, METH_VARARGS, (char *)"\n"
+		"FieldDefn_IsNullable(FieldDefn self) -> int\n"
+		"\n"
+		"int\n"
+		"OGR_Fld_IsNullable(OGRFieldDefnH hDefn)\n"
+		"\n"
+		"Return whether this field can receive null values.\n"
+		"\n"
+		"By default, fields are nullable.\n"
+		"\n"
+		"Even if this method returns FALSE (i.e not-nullable field), it doesn't\n"
+		"mean that OGRFeature::IsFieldSet() will necessary return TRUE, as\n"
+		"fields can be temporary unset and null/not-null validation is usually\n"
+		"done when OGRLayer::CreateFeature()/SetFeature() is called.\n"
+		"\n"
+		"This method is the same as the C++ method OGRFieldDefn::IsNullable().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hDefn:  handle to the field definition\n"
+		"\n"
+		"TRUE if the field is authorized to be null.\n"
+		"\n"
+		"GDAL 2.0 \n"
+		""},
+	 { (char *)"FieldDefn_SetNullable", _wrap_FieldDefn_SetNullable, METH_VARARGS, (char *)"\n"
+		"FieldDefn_SetNullable(FieldDefn self, int bNullable)\n"
+		"\n"
+		"void\n"
+		"OGR_Fld_SetNullable(OGRFieldDefnH hDefn, int bNullableIn)\n"
+		"\n"
+		"Set whether this field can receive null values.\n"
+		"\n"
+		"By default, fields are nullable, so this method is generally called\n"
+		"with FALSE to set a not-null constraint.\n"
+		"\n"
+		"Drivers that support writing not-null constraint will advertize the\n"
+		"GDAL_DCAP_NOTNULL_FIELDS driver metadata item.\n"
+		"\n"
+		"This method is the same as the C++ method OGRFieldDefn::SetNullable().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hDefn:  handle to the field definition\n"
+		"\n"
+		"bNullableIn:  FALSE if the field must have a not-null constraint.\n"
+		"\n"
+		"GDAL 2.0 \n"
+		""},
+	 { (char *)"FieldDefn_GetDefault", _wrap_FieldDefn_GetDefault, METH_VARARGS, (char *)"\n"
+		"FieldDefn_GetDefault(FieldDefn self) -> char const *\n"
+		"\n"
+		"const char*\n"
+		"OGR_Fld_GetDefault(OGRFieldDefnH hDefn)\n"
+		"\n"
+		"Get default field value.\n"
+		"\n"
+		"This function is the same as the C++ method\n"
+		"OGRFieldDefn::GetDefault().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hDefn:  handle to the field definition.\n"
+		"\n"
+		"default field value or NULL.\n"
+		"\n"
+		"GDAL 2.0 \n"
+		""},
+	 { (char *)"FieldDefn_SetDefault", _wrap_FieldDefn_SetDefault, METH_VARARGS, (char *)"\n"
+		"FieldDefn_SetDefault(FieldDefn self, char const * pszValue)\n"
+		"\n"
+		"void\n"
+		"OGR_Fld_SetDefault(OGRFieldDefnH hDefn, const char *pszDefault)\n"
+		"\n"
+		"Set default field value.\n"
+		"\n"
+		"The default field value is taken into account by drivers (generally\n"
+		"those with a SQL interface) that support it at field creation time.\n"
+		"OGR will generally not automatically set the default field value to\n"
+		"null fields by itself when calling OGRFeature::CreateFeature() /\n"
+		"OGRFeature::SetFeature(), but will let the low-level layers to do the\n"
+		"job. So retrieving the feature from the layer is recommended.\n"
+		"\n"
+		"The accepted values are NULL, a numeric value, a literal value\n"
+		"enclosed between single quote characters (and inner single quote\n"
+		"characters escaped by repetition of the single quote character),\n"
+		"CURRENT_TIMESTAMP, CURRENT_TIME, CURRENT_DATE or a driver specific\n"
+		"expression (that might be ignored by other drivers). For a datetime\n"
+		"literal value, format should be 'YYYY/MM/DD HH:MM:SS[.sss]'\n"
+		"(considered as UTC time).\n"
+		"\n"
+		"Drivers that support writing DEFAULT clauses will advertize the\n"
+		"GDAL_DCAP_DEFAULT_FIELDS driver metadata item.\n"
+		"\n"
+		"This function is the same as the C++ method\n"
+		"OGRFieldDefn::SetDefault().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hDefn:  handle to the field definition.\n"
+		"\n"
+		"pszDefault:  new default field value or NULL pointer.\n"
+		"\n"
+		"GDAL 2.0 \n"
+		""},
+	 { (char *)"FieldDefn_IsDefaultDriverSpecific", _wrap_FieldDefn_IsDefaultDriverSpecific, METH_VARARGS, (char *)"\n"
+		"FieldDefn_IsDefaultDriverSpecific(FieldDefn self) -> int\n"
+		"\n"
+		"int\n"
+		"OGR_Fld_IsDefaultDriverSpecific(OGRFieldDefnH hDefn)\n"
+		"\n"
+		"Returns whether the default value is driver specific.\n"
+		"\n"
+		"Driver specific default values are those that are *not* NULL, a\n"
+		"numeric value, a literal value enclosed between single quote\n"
+		"characters, CURRENT_TIMESTAMP, CURRENT_TIME, CURRENT_DATE or datetime\n"
+		"literal value.\n"
+		"\n"
+		"This function is the same as the C++ method\n"
+		"OGRFieldDefn::IsDefaultDriverSpecific().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hDefn:  handle to the field definition\n"
+		"\n"
+		"TRUE if the default value is driver specific.\n"
+		"\n"
+		"GDAL 2.0 \n"
+		""},
 	 { (char *)"FieldDefn_swigregister", FieldDefn_swigregister, METH_VARARGS, NULL},
 	 { (char *)"delete_GeomFieldDefn", _wrap_delete_GeomFieldDefn, METH_VARARGS, (char *)"delete_GeomFieldDefn(GeomFieldDefn self)"},
-	 { (char *)"new_GeomFieldDefn", (PyCFunction) _wrap_new_GeomFieldDefn, METH_VARARGS | METH_KEYWORDS, (char *)"new_GeomFieldDefn(char name_null_ok = \"\", OGRwkbGeometryType field_type = wkbUnknown) -> GeomFieldDefn"},
-	 { (char *)"GeomFieldDefn_GetName", _wrap_GeomFieldDefn_GetName, METH_VARARGS, (char *)"GeomFieldDefn_GetName(GeomFieldDefn self) -> char"},
-	 { (char *)"GeomFieldDefn_GetNameRef", _wrap_GeomFieldDefn_GetNameRef, METH_VARARGS, (char *)"GeomFieldDefn_GetNameRef(GeomFieldDefn self) -> char"},
-	 { (char *)"GeomFieldDefn_SetName", _wrap_GeomFieldDefn_SetName, METH_VARARGS, (char *)"GeomFieldDefn_SetName(GeomFieldDefn self, char name)"},
+	 { (char *)"new_GeomFieldDefn", (PyCFunction) _wrap_new_GeomFieldDefn, METH_VARARGS | METH_KEYWORDS, (char *)"new_GeomFieldDefn(char const * name_null_ok=\"\", OGRwkbGeometryType field_type=wkbUnknown) -> GeomFieldDefn"},
+	 { (char *)"GeomFieldDefn_GetName", _wrap_GeomFieldDefn_GetName, METH_VARARGS, (char *)"GeomFieldDefn_GetName(GeomFieldDefn self) -> char const *"},
+	 { (char *)"GeomFieldDefn_GetNameRef", _wrap_GeomFieldDefn_GetNameRef, METH_VARARGS, (char *)"GeomFieldDefn_GetNameRef(GeomFieldDefn self) -> char const *"},
+	 { (char *)"GeomFieldDefn_SetName", _wrap_GeomFieldDefn_SetName, METH_VARARGS, (char *)"GeomFieldDefn_SetName(GeomFieldDefn self, char const * name)"},
 	 { (char *)"GeomFieldDefn_GetType", _wrap_GeomFieldDefn_GetType, METH_VARARGS, (char *)"GeomFieldDefn_GetType(GeomFieldDefn self) -> OGRwkbGeometryType"},
 	 { (char *)"GeomFieldDefn_SetType", _wrap_GeomFieldDefn_SetType, METH_VARARGS, (char *)"GeomFieldDefn_SetType(GeomFieldDefn self, OGRwkbGeometryType type)"},
 	 { (char *)"GeomFieldDefn_GetSpatialRef", _wrap_GeomFieldDefn_GetSpatialRef, METH_VARARGS, (char *)"GeomFieldDefn_GetSpatialRef(GeomFieldDefn self) -> SpatialReference"},
@@ -26361,31 +30241,23 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"GeomFieldDefn_IsNullable", _wrap_GeomFieldDefn_IsNullable, METH_VARARGS, (char *)"GeomFieldDefn_IsNullable(GeomFieldDefn self) -> int"},
 	 { (char *)"GeomFieldDefn_SetNullable", _wrap_GeomFieldDefn_SetNullable, METH_VARARGS, (char *)"GeomFieldDefn_SetNullable(GeomFieldDefn self, int bNullable)"},
 	 { (char *)"GeomFieldDefn_swigregister", GeomFieldDefn_swigregister, METH_VARARGS, NULL},
-	 { (char *)"CreateGeometryFromWkb", (PyCFunction) _wrap_CreateGeometryFromWkb, METH_VARARGS | METH_KEYWORDS, (char *)"CreateGeometryFromWkb(int len, SpatialReference reference = None) -> Geometry"},
-	 { (char *)"CreateGeometryFromWkt", (PyCFunction) _wrap_CreateGeometryFromWkt, METH_VARARGS | METH_KEYWORDS, (char *)"CreateGeometryFromWkt(char val, SpatialReference reference = None) -> Geometry"},
-	 { (char *)"CreateGeometryFromGML", _wrap_CreateGeometryFromGML, METH_VARARGS, (char *)"CreateGeometryFromGML(char input_string) -> Geometry"},
-	 { (char *)"CreateGeometryFromJson", _wrap_CreateGeometryFromJson, METH_VARARGS, (char *)"CreateGeometryFromJson(char input_string) -> Geometry"},
-	 { (char *)"BuildPolygonFromEdges", (PyCFunction) _wrap_BuildPolygonFromEdges, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"BuildPolygonFromEdges(Geometry hLineCollection, int bBestEffort = 0, int bAutoClose = 0, \n"
-		"    double dfTolerance = 0) -> Geometry\n"
-		""},
+	 { (char *)"CreateGeometryFromWkb", (PyCFunction) _wrap_CreateGeometryFromWkb, METH_VARARGS | METH_KEYWORDS, (char *)"CreateGeometryFromWkb(int len, SpatialReference reference=None) -> Geometry"},
+	 { (char *)"CreateGeometryFromWkt", (PyCFunction) _wrap_CreateGeometryFromWkt, METH_VARARGS | METH_KEYWORDS, (char *)"CreateGeometryFromWkt(char ** val, SpatialReference reference=None) -> Geometry"},
+	 { (char *)"CreateGeometryFromGML", _wrap_CreateGeometryFromGML, METH_VARARGS, (char *)"CreateGeometryFromGML(char const * input_string) -> Geometry"},
+	 { (char *)"CreateGeometryFromJson", _wrap_CreateGeometryFromJson, METH_VARARGS, (char *)"CreateGeometryFromJson(char const * input_string) -> Geometry"},
+	 { (char *)"BuildPolygonFromEdges", (PyCFunction) _wrap_BuildPolygonFromEdges, METH_VARARGS | METH_KEYWORDS, (char *)"BuildPolygonFromEdges(Geometry hLineCollection, int bBestEffort=0, int bAutoClose=0, double dfTolerance=0) -> Geometry"},
 	 { (char *)"ApproximateArcAngles", (PyCFunction) _wrap_ApproximateArcAngles, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"ApproximateArcAngles(double dfCenterX, double dfCenterY, double dfZ, double dfPrimaryRadius, \n"
-		"    double dfSecondaryAxis, \n"
-		"    double dfRotation, double dfStartAngle, double dfEndAngle, \n"
-		"    double dfMaxAngleStepSizeDegrees) -> Geometry\n"
+		"ApproximateArcAngles(double dfCenterX, double dfCenterY, double dfZ, double dfPrimaryRadius, double dfSecondaryAxis, \n"
+		"    double dfRotation, double dfStartAngle, double dfEndAngle, double dfMaxAngleStepSizeDegrees) -> Geometry\n"
 		""},
 	 { (char *)"ForceToPolygon", _wrap_ForceToPolygon, METH_VARARGS, (char *)"ForceToPolygon(Geometry geom_in) -> Geometry"},
 	 { (char *)"ForceToLineString", _wrap_ForceToLineString, METH_VARARGS, (char *)"ForceToLineString(Geometry geom_in) -> Geometry"},
 	 { (char *)"ForceToMultiPolygon", _wrap_ForceToMultiPolygon, METH_VARARGS, (char *)"ForceToMultiPolygon(Geometry geom_in) -> Geometry"},
 	 { (char *)"ForceToMultiPoint", _wrap_ForceToMultiPoint, METH_VARARGS, (char *)"ForceToMultiPoint(Geometry geom_in) -> Geometry"},
 	 { (char *)"ForceToMultiLineString", _wrap_ForceToMultiLineString, METH_VARARGS, (char *)"ForceToMultiLineString(Geometry geom_in) -> Geometry"},
-	 { (char *)"ForceTo", _wrap_ForceTo, METH_VARARGS, (char *)"ForceTo(Geometry geom_in, OGRwkbGeometryType eTargetType, char options = None) -> Geometry"},
+	 { (char *)"ForceTo", _wrap_ForceTo, METH_VARARGS, (char *)"ForceTo(Geometry geom_in, OGRwkbGeometryType eTargetType, char ** options=None) -> Geometry"},
 	 { (char *)"delete_Geometry", _wrap_delete_Geometry, METH_VARARGS, (char *)"delete_Geometry(Geometry self)"},
-	 { (char *)"new_Geometry", (PyCFunction) _wrap_new_Geometry, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"new_Geometry(OGRwkbGeometryType type = wkbUnknown, char wkt = None, \n"
-		"    int wkb = 0, char gml = None) -> Geometry\n"
-		""},
+	 { (char *)"new_Geometry", (PyCFunction) _wrap_new_Geometry, METH_VARARGS | METH_KEYWORDS, (char *)"new_Geometry(OGRwkbGeometryType type=wkbUnknown, char * wkt=None, int wkb=0, char * gml=None) -> Geometry"},
 	 { (char *)"Geometry_ExportToWkt", _wrap_Geometry_ExportToWkt, METH_VARARGS, (char *)"\n"
 		"Geometry_ExportToWkt(Geometry self) -> OGRErr\n"
 		"\n"
@@ -26396,6 +30268,11 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"This function relates to the SFCOM IWks::ExportToWKT() method.\n"
 		"\n"
+		"For backward compatibility purposes, it exports the Old-style 99-402\n"
+		"extended dimension (Z) WKB types for types Point, LineString, Polygon,\n"
+		"MultiPoint, MultiLineString, MultiPolygon and GeometryCollection. For\n"
+		"other geometry types, it is equivalent to OGR_G_ExportToIsoWkt().\n"
+		"\n"
 		"This function is the same as the CPP method\n"
 		"OGRGeometry::exportToWkt().\n"
 		"\n"
@@ -26405,24 +30282,59 @@ static PyMethodDef SwigMethods[] = {
 		"hGeom:  handle on the geometry to convert to a text format from.\n"
 		"\n"
 		"ppszSrcText:  a text buffer is allocated by the program, and assigned\n"
-		"to the passed pointer.\n"
+		"to the passed pointer. After use, *ppszDstText should be freed with\n"
+		"OGRFree().\n"
 		"\n"
 		"Currently OGRERR_NONE is always returned. \n"
 		""},
-	 { (char *)"Geometry_ExportToIsoWkt", _wrap_Geometry_ExportToIsoWkt, METH_VARARGS, (char *)"Geometry_ExportToIsoWkt(Geometry self) -> OGRErr"},
+	 { (char *)"Geometry_ExportToIsoWkt", _wrap_Geometry_ExportToIsoWkt, METH_VARARGS, (char *)"\n"
+		"Geometry_ExportToIsoWkt(Geometry self) -> OGRErr\n"
+		"\n"
+		"OGRErr\n"
+		"OGR_G_ExportToIsoWkt(OGRGeometryH hGeom, char **ppszSrcText)\n"
+		"\n"
+		"Convert a geometry into SFSQL 1.2 / ISO SQL/MM Part 3 well known text\n"
+		"format.\n"
+		"\n"
+		"This function relates to the SFCOM IWks::ExportToWKT() method. It\n"
+		"exports the SFSQL 1.2 and ISO SQL/MM Part 3 extended dimension (Z&M)\n"
+		"WKB types\n"
+		"\n"
+		"This function is the same as the CPP method\n"
+		"OGRGeometry::exportToWkt(,wkbVariantIso).\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hGeom:  handle on the geometry to convert to a text format from.\n"
+		"\n"
+		"ppszSrcText:  a text buffer is allocated by the program, and assigned\n"
+		"to the passed pointer. After use, *ppszDstText should be freed with\n"
+		"OGRFree().\n"
+		"\n"
+		"Currently OGRERR_NONE is always returned.\n"
+		"\n"
+		"GDAL 2.0 \n"
+		""},
 	 { (char *)"Geometry_ExportToWkb", (PyCFunction) _wrap_Geometry_ExportToWkb, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Geometry_ExportToWkb(Geometry self, OGRwkbByteOrder byte_order = wkbXDR) -> OGRErr\n"
+		"Geometry_ExportToWkb(Geometry self, OGRwkbByteOrder byte_order=wkbXDR) -> OGRErr\n"
 		"\n"
 		"OGRErr\n"
 		"OGR_G_ExportToWkb(OGRGeometryH hGeom, OGRwkbByteOrder eOrder, unsigned\n"
 		"char *pabyDstBuffer)\n"
 		"\n"
-		"Convert a geometry into well known binary format.\n"
+		"Convert a geometry well known binary format.\n"
 		"\n"
 		"This function relates to the SFCOM IWks::ExportToWKB() method.\n"
 		"\n"
+		"For backward compatibility purposes, it exports the Old-style 99-402\n"
+		"extended dimension (Z) WKB types for types Point, LineString, Polygon,\n"
+		"MultiPoint, MultiLineString, MultiPolygon and GeometryCollection. For\n"
+		"other geometry types, it is equivalent to OGR_G_ExportToIsoWkb().\n"
+		"\n"
 		"This function is the same as the CPP method\n"
-		"OGRGeometry::exportToWkb().\n"
+		"OGRGeometry::exportToWkb(OGRwkbByteOrder, unsigned char *,\n"
+		"OGRwkbVariant) with eWkbVariant = wkbVariantOldOgc.\n"
 		"\n"
 		"Parameters:\n"
 		"-----------\n"
@@ -26438,11 +30350,46 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"Currently OGRERR_NONE is always returned. \n"
 		""},
-	 { (char *)"Geometry_ExportToIsoWkb", (PyCFunction) _wrap_Geometry_ExportToIsoWkb, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_ExportToIsoWkb(Geometry self, OGRwkbByteOrder byte_order = wkbXDR) -> OGRErr"},
-	 { (char *)"Geometry_ExportToGML", (PyCFunction) _wrap_Geometry_ExportToGML, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_ExportToGML(Geometry self, char options = None) -> retStringAndCPLFree"},
-	 { (char *)"Geometry_ExportToKML", _wrap_Geometry_ExportToKML, METH_VARARGS, (char *)"Geometry_ExportToKML(Geometry self, char altitude_mode = None) -> retStringAndCPLFree"},
-	 { (char *)"Geometry_ExportToJson", (PyCFunction) _wrap_Geometry_ExportToJson, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_ExportToJson(Geometry self, char options = None) -> retStringAndCPLFree"},
-	 { (char *)"Geometry_AddPoint", (PyCFunction) _wrap_Geometry_AddPoint, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_AddPoint(Geometry self, double x, double y, double z = 0)"},
+	 { (char *)"Geometry_ExportToIsoWkb", (PyCFunction) _wrap_Geometry_ExportToIsoWkb, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
+		"Geometry_ExportToIsoWkb(Geometry self, OGRwkbByteOrder byte_order=wkbXDR) -> OGRErr\n"
+		"\n"
+		"OGRErr\n"
+		"OGR_G_ExportToIsoWkb(OGRGeometryH hGeom, OGRwkbByteOrder eOrder,\n"
+		"unsigned char *pabyDstBuffer)\n"
+		"\n"
+		"Convert a geometry into SFSQL 1.2 / ISO SQL/MM Part 3 well known\n"
+		"binary format.\n"
+		"\n"
+		"This function relates to the SFCOM IWks::ExportToWKB() method. It\n"
+		"exports the SFSQL 1.2 and ISO SQL/MM Part 3 extended dimension (Z&M)\n"
+		"WKB types\n"
+		"\n"
+		"This function is the same as the CPP method\n"
+		"OGRGeometry::exportToWkb(OGRwkbByteOrder, unsigned char *,\n"
+		"OGRwkbVariant) with eWkbVariant = wkbVariantIso.\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hGeom:  handle on the geometry to convert to a well know binary data\n"
+		"from.\n"
+		"\n"
+		"eOrder:  One of wkbXDR or wkbNDR indicating MSB or LSB byte order\n"
+		"respectively.\n"
+		"\n"
+		"pabyDstBuffer:  a buffer into which the binary representation is\n"
+		"written. This buffer must be at least OGR_G_WkbSize() byte in size.\n"
+		"\n"
+		"Currently OGRERR_NONE is always returned.\n"
+		"\n"
+		"GDAL 2.0 \n"
+		""},
+	 { (char *)"Geometry_ExportToGML", (PyCFunction) _wrap_Geometry_ExportToGML, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_ExportToGML(Geometry self, char ** options=None) -> retStringAndCPLFree *"},
+	 { (char *)"Geometry_ExportToKML", _wrap_Geometry_ExportToKML, METH_VARARGS, (char *)"Geometry_ExportToKML(Geometry self, char const * altitude_mode=None) -> retStringAndCPLFree *"},
+	 { (char *)"Geometry_ExportToJson", (PyCFunction) _wrap_Geometry_ExportToJson, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_ExportToJson(Geometry self, char ** options=None) -> retStringAndCPLFree *"},
+	 { (char *)"Geometry_AddPoint", (PyCFunction) _wrap_Geometry_AddPoint, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_AddPoint(Geometry self, double x, double y, double z=0)"},
+	 { (char *)"Geometry_AddPointM", (PyCFunction) _wrap_Geometry_AddPointM, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_AddPointM(Geometry self, double x, double y, double m)"},
+	 { (char *)"Geometry_AddPointZM", (PyCFunction) _wrap_Geometry_AddPointZM, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_AddPointZM(Geometry self, double x, double y, double z, double m)"},
 	 { (char *)"Geometry_AddPoint_2D", _wrap_Geometry_AddPoint_2D, METH_VARARGS, (char *)"Geometry_AddPoint_2D(Geometry self, double x, double y)"},
 	 { (char *)"Geometry_AddGeometryDirectly", _wrap_Geometry_AddGeometryDirectly, METH_VARARGS, (char *)"Geometry_AddGeometryDirectly(Geometry self, Geometry other_disown) -> OGRErr"},
 	 { (char *)"Geometry_AddGeometry", _wrap_Geometry_AddGeometry, METH_VARARGS, (char *)"Geometry_AddGeometry(Geometry self, Geometry other) -> OGRErr"},
@@ -26489,7 +30436,7 @@ static PyMethodDef SwigMethods[] = {
 		"the geometry type code. \n"
 		""},
 	 { (char *)"Geometry_GetGeometryName", _wrap_Geometry_GetGeometryName, METH_VARARGS, (char *)"\n"
-		"Geometry_GetGeometryName(Geometry self) -> char\n"
+		"Geometry_GetGeometryName(Geometry self) -> char const *\n"
 		"\n"
 		"const char*\n"
 		"OGR_G_GetGeometryName(OGRGeometryH hGeom)\n"
@@ -26512,14 +30459,18 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"Geometry_Area", _wrap_Geometry_Area, METH_VARARGS, (char *)"Geometry_Area(Geometry self) -> double"},
 	 { (char *)"Geometry_GetArea", _wrap_Geometry_GetArea, METH_VARARGS, (char *)"Geometry_GetArea(Geometry self) -> double"},
 	 { (char *)"Geometry_GetPointCount", _wrap_Geometry_GetPointCount, METH_VARARGS, (char *)"Geometry_GetPointCount(Geometry self) -> int"},
-	 { (char *)"Geometry_GetPoints", (PyCFunction) _wrap_Geometry_GetPoints, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_GetPoints(Geometry self, int nCoordDimension = 0)"},
-	 { (char *)"Geometry_GetX", (PyCFunction) _wrap_Geometry_GetX, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_GetX(Geometry self, int point = 0) -> double"},
-	 { (char *)"Geometry_GetY", (PyCFunction) _wrap_Geometry_GetY, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_GetY(Geometry self, int point = 0) -> double"},
-	 { (char *)"Geometry_GetZ", (PyCFunction) _wrap_Geometry_GetZ, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_GetZ(Geometry self, int point = 0) -> double"},
-	 { (char *)"Geometry_GetPoint", _wrap_Geometry_GetPoint, METH_VARARGS, (char *)"Geometry_GetPoint(Geometry self, int iPoint = 0)"},
-	 { (char *)"Geometry_GetPoint_2D", _wrap_Geometry_GetPoint_2D, METH_VARARGS, (char *)"Geometry_GetPoint_2D(Geometry self, int iPoint = 0)"},
+	 { (char *)"Geometry_GetPoints", (PyCFunction) _wrap_Geometry_GetPoints, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_GetPoints(Geometry self, int nCoordDimension=0)"},
+	 { (char *)"Geometry_GetX", (PyCFunction) _wrap_Geometry_GetX, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_GetX(Geometry self, int point=0) -> double"},
+	 { (char *)"Geometry_GetY", (PyCFunction) _wrap_Geometry_GetY, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_GetY(Geometry self, int point=0) -> double"},
+	 { (char *)"Geometry_GetZ", (PyCFunction) _wrap_Geometry_GetZ, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_GetZ(Geometry self, int point=0) -> double"},
+	 { (char *)"Geometry_GetM", (PyCFunction) _wrap_Geometry_GetM, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_GetM(Geometry self, int point=0) -> double"},
+	 { (char *)"Geometry_GetPoint", _wrap_Geometry_GetPoint, METH_VARARGS, (char *)"Geometry_GetPoint(Geometry self, int iPoint=0)"},
+	 { (char *)"Geometry_GetPointZM", _wrap_Geometry_GetPointZM, METH_VARARGS, (char *)"Geometry_GetPointZM(Geometry self, int iPoint=0)"},
+	 { (char *)"Geometry_GetPoint_2D", _wrap_Geometry_GetPoint_2D, METH_VARARGS, (char *)"Geometry_GetPoint_2D(Geometry self, int iPoint=0)"},
 	 { (char *)"Geometry_GetGeometryCount", _wrap_Geometry_GetGeometryCount, METH_VARARGS, (char *)"Geometry_GetGeometryCount(Geometry self) -> int"},
-	 { (char *)"Geometry_SetPoint", (PyCFunction) _wrap_Geometry_SetPoint, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_SetPoint(Geometry self, int point, double x, double y, double z = 0)"},
+	 { (char *)"Geometry_SetPoint", (PyCFunction) _wrap_Geometry_SetPoint, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_SetPoint(Geometry self, int point, double x, double y, double z=0)"},
+	 { (char *)"Geometry_SetPointM", (PyCFunction) _wrap_Geometry_SetPointM, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_SetPointM(Geometry self, int point, double x, double y, double m)"},
+	 { (char *)"Geometry_SetPointZM", (PyCFunction) _wrap_Geometry_SetPointZM, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_SetPointZM(Geometry self, int point, double x, double y, double z, double m)"},
 	 { (char *)"Geometry_SetPoint_2D", (PyCFunction) _wrap_Geometry_SetPoint_2D, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_SetPoint_2D(Geometry self, int point, double x, double y)"},
 	 { (char *)"Geometry_GetGeometryRef", _wrap_Geometry_GetGeometryRef, METH_VARARGS, (char *)"Geometry_GetGeometryRef(Geometry self, int geom) -> Geometry"},
 	 { (char *)"Geometry_Simplify", _wrap_Geometry_Simplify, METH_VARARGS, (char *)"\n"
@@ -26554,7 +30505,7 @@ static PyMethodDef SwigMethods[] = {
 		"OGRGeometryH\n"
 		"OGR_G_SimplifyPreserveTopology(OGRGeometryH hThis, double dTolerance)\n"
 		"\n"
-		"Compute a simplified geometry.\n"
+		"Simplify the geometry while preserving topology.\n"
 		"\n"
 		"This function is the same as the C++ method\n"
 		"OGRGeometry::SimplifyPreserveTopology().\n"
@@ -26575,6 +30526,38 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"OGR 1.9.0 \n"
 		""},
+	 { (char *)"Geometry_DelaunayTriangulation", (PyCFunction) _wrap_Geometry_DelaunayTriangulation, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
+		"Geometry_DelaunayTriangulation(Geometry self, double dfTolerance=0.0, int bOnlyEdges=False) -> Geometry\n"
+		"\n"
+		"OGRGeometryH\n"
+		"OGR_G_DelaunayTriangulation(OGRGeometryH hThis, double dfTolerance,\n"
+		"int bOnlyEdges)\n"
+		"\n"
+		"Return a Delaunay triangulation of the vertices of the geometry.\n"
+		"\n"
+		"This function is the same as the C++ method\n"
+		"OGRGeometry::DelaunayTriangulation().\n"
+		"\n"
+		"This function is built on the GEOS library, v3.4 or above. If OGR is\n"
+		"built without the GEOS library, this function will always fail,\n"
+		"issuing a CPLE_NotSupported error.\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hThis:  the geometry.\n"
+		"\n"
+		"dfTolerance:  optional snapping tolerance to use for improved\n"
+		"robustness\n"
+		"\n"
+		"bOnlyEdges:  if TRUE, will return a MULTILINESTRING, otherwise it will\n"
+		"return a GEOMETRYCOLLECTION containing triangular POLYGONs.\n"
+		"\n"
+		"the geometry resulting from the Delaunay triangulation or NULL if an\n"
+		"error occurs.\n"
+		"\n"
+		"OGR 2.1 \n"
+		""},
 	 { (char *)"Geometry_Boundary", _wrap_Geometry_Boundary, METH_VARARGS, (char *)"\n"
 		"Geometry_Boundary(Geometry self) -> Geometry\n"
 		"\n"
@@ -26640,7 +30623,7 @@ static PyMethodDef SwigMethods[] = {
 		"NULL on failure. \n"
 		""},
 	 { (char *)"Geometry_Buffer", (PyCFunction) _wrap_Geometry_Buffer, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Geometry_Buffer(Geometry self, double distance, int quadsecs = 30) -> Geometry\n"
+		"Geometry_Buffer(Geometry self, double distance, int quadsecs=30) -> Geometry\n"
 		"\n"
 		"OGRGeometryH OGR_G_Buffer(OGRGeometryH\n"
 		"hTarget, double dfDist, int nQuadSegs)\n"
@@ -26653,7 +30636,7 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"Some buffer sections are properly described as curves, but are\n"
 		"converted to approximate polygons. The nQuadSegs parameter can be used\n"
-		"to control how many segements should be used to define a 90 degree\n"
+		"to control how many segments should be used to define a 90 degree\n"
 		"curve - a quadrant of a circle. A value of 30 is a reasonable default.\n"
 		"Large values result in large numbers of vertices in the resulting\n"
 		"buffer geometry while small numbers reduce the accuracy of the result.\n"
@@ -26670,7 +30653,8 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"hTarget:  the geometry.\n"
 		"\n"
-		"dfDist:  the buffer distance to be applied.\n"
+		"dfDist:  the buffer distance to be applied. Should be expressed into\n"
+		"the same unit as the coordinates of the geometry.\n"
 		"\n"
 		"nQuadSegs:  the number of segments used to approximate a 90 degree\n"
 		"(quadrant) of curvature.\n"
@@ -26834,7 +30818,8 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"Compute distance between two geometries.\n"
 		"\n"
-		"Returns the shortest distance between the two geometries.\n"
+		"Returns the shortest distance between the two geometries. The distance\n"
+		"is expressed into the same unit as the coordinates of the geometries.\n"
 		"\n"
 		"This function is the same as the C++ method OGRGeometry::Distance().\n"
 		"\n"
@@ -26857,8 +30842,10 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"void OGR_G_Empty(OGRGeometryH hGeom)\n"
 		"\n"
-		"Clear geometry information. This restores the geometry to it's initial\n"
-		"state after construction, and before assignment of actual geometry.\n"
+		"Clear geometry information.\n"
+		"\n"
+		"This restores the geometry to it's initial state after construction,\n"
+		"and before assignment of actual geometry.\n"
 		"\n"
 		"This function relates to the SFCOM IGeometry::Empty() method.\n"
 		"\n"
@@ -26959,9 +30946,9 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"Do these features intersect?\n"
 		"\n"
-		"Currently this is not implemented in a rigerous fashion, and generally\n"
-		"just tests whether the envelopes of the two features intersect.\n"
-		"Eventually this will be made rigerous.\n"
+		"Determines whether two geometries intersect. If GEOS is enabled, then\n"
+		"this is done in rigorous fashion otherwise TRUE is returned if the\n"
+		"envelopes (bounding boxes) of the two geometries overlap.\n"
 		"\n"
 		"This function is the same as the CPP method OGRGeometry::Intersects.\n"
 		"\n"
@@ -27302,8 +31289,9 @@ static PyMethodDef SwigMethods[] = {
 		"void\n"
 		"OGR_G_FlattenTo2D(OGRGeometryH hGeom)\n"
 		"\n"
-		"Convert geometry to strictly 2D. In a sense this converts all Z\n"
-		"coordinates to 0.0.\n"
+		"Convert geometry to strictly 2D.\n"
+		"\n"
+		"In a sense this converts all Z coordinates to 0.0.\n"
 		"\n"
 		"This function is the same as the CPP method\n"
 		"OGRGeometry::flattenTo2D().\n"
@@ -27402,7 +31390,32 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"OGRERR_NONE on success or OGRERR_FAILURE on error. \n"
 		""},
-	 { (char *)"Geometry_PointOnSurface", _wrap_Geometry_PointOnSurface, METH_VARARGS, (char *)"Geometry_PointOnSurface(Geometry self) -> Geometry"},
+	 { (char *)"Geometry_PointOnSurface", _wrap_Geometry_PointOnSurface, METH_VARARGS, (char *)"\n"
+		"Geometry_PointOnSurface(Geometry self) -> Geometry\n"
+		"\n"
+		"OGRGeometryH\n"
+		"OGR_G_PointOnSurface(OGRGeometryH hGeom)\n"
+		"\n"
+		"Returns a point guaranteed to lie on the surface.\n"
+		"\n"
+		"This method relates to the SFCOM ISurface::get_PointOnSurface() method\n"
+		"however the current implementation based on GEOS can operate on other\n"
+		"geometry types than the types that are supported by SQL/MM-Part 3 :\n"
+		"surfaces (polygons) and multisurfaces (multipolygons).\n"
+		"\n"
+		"This method is built on the GEOS library, check it for the definition\n"
+		"of the geometry operation. If OGR is built without the GEOS library,\n"
+		"this method will always fail, issuing a CPLE_NotSupported error.\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hGeom:  the geometry to operate on.\n"
+		"\n"
+		"a point guaranteed to lie on the surface or NULL if an error occurred.\n"
+		"\n"
+		"OGR 1.10 \n"
+		""},
 	 { (char *)"Geometry_WkbSize", _wrap_Geometry_WkbSize, METH_VARARGS, (char *)"\n"
 		"Geometry_WkbSize(Geometry self) -> int\n"
 		"\n"
@@ -27433,9 +31446,6 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"Get the dimension of the coordinates in this geometry.\n"
 		"\n"
-		"This function corresponds to the SFCOM IGeometry::GetDimension()\n"
-		"method.\n"
-		"\n"
 		"This function is the same as the CPP method\n"
 		"OGRGeometry::getCoordinateDimension().\n"
 		"\n"
@@ -27445,8 +31455,66 @@ static PyMethodDef SwigMethods[] = {
 		"hGeom:  handle on the geometry to get the dimension of the coordinates\n"
 		"from.\n"
 		"\n"
-		"in practice this will return 2 or 3. It can also return 0 in the case\n"
-		"of an empty point. \n"
+		"Deprecated use OGR_G_CoordinateDimension(), OGR_G_Is3D(), or\n"
+		"OGR_G_IsMeasured().\n"
+		"\n"
+		"this will return 2 or 3. \n"
+		""},
+	 { (char *)"Geometry_CoordinateDimension", _wrap_Geometry_CoordinateDimension, METH_VARARGS, (char *)"\n"
+		"Geometry_CoordinateDimension(Geometry self) -> int\n"
+		"\n"
+		"int\n"
+		"OGR_G_CoordinateDimension(OGRGeometryH hGeom)\n"
+		"\n"
+		"Get the dimension of the coordinates in this geometry.\n"
+		"\n"
+		"This function is the same as the CPP method\n"
+		"OGRGeometry::CoordinateDimension().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hGeom:  handle on the geometry to get the dimension of the coordinates\n"
+		"from.\n"
+		"\n"
+		"this will return 2 for XY, 3 for XYZ and XYM, and 4 for XYZM data. \n"
+		""},
+	 { (char *)"Geometry_Is3D", _wrap_Geometry_Is3D, METH_VARARGS, (char *)"\n"
+		"Geometry_Is3D(Geometry self) -> int\n"
+		"\n"
+		"int OGR_G_Is3D(OGRGeometryH hGeom)\n"
+		"\n"
+		"See whether this geometry has Z coordinates.\n"
+		"\n"
+		"This function is the same as the CPP method OGRGeometry::Is3D().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hGeom:  handle on the geometry to check whether it has Z coordinates.\n"
+		"\n"
+		"TRUE if the geometry has Z coordinates.\n"
+		"\n"
+		"GDAL 2.1 \n"
+		""},
+	 { (char *)"Geometry_IsMeasured", _wrap_Geometry_IsMeasured, METH_VARARGS, (char *)"\n"
+		"Geometry_IsMeasured(Geometry self) -> int\n"
+		"\n"
+		"int OGR_G_IsMeasured(OGRGeometryH\n"
+		"hGeom)\n"
+		"\n"
+		"See whether this geometry is measured.\n"
+		"\n"
+		"This function is the same as the CPP method OGRGeometry::IsMeasured().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hGeom:  handle on the geometry to check whether it is measured.\n"
+		"\n"
+		"TRUE if the geometry has M coordinates.\n"
+		"\n"
+		"GDAL 2.1 \n"
 		""},
 	 { (char *)"Geometry_SetCoordinateDimension", _wrap_Geometry_SetCoordinateDimension, METH_VARARGS, (char *)"\n"
 		"Geometry_SetCoordinateDimension(Geometry self, int dimension)\n"
@@ -27458,8 +31526,11 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"This method sets the explicit coordinate dimension. Setting the\n"
 		"coordinate dimension of a geometry to 2 should zero out any existing Z\n"
-		"values. Setting the dimension of a geometry collection will not\n"
-		"necessarily affect the children geometries.\n"
+		"values. Setting the dimension of a geometry collection, a compound\n"
+		"curve, a polygon, etc. will affect the children geometries. This will\n"
+		"also remove the M dimension if present before this call.\n"
+		"\n"
+		"Deprecated use OGR_G_Set3D() or OGR_G_SetMeasured().\n"
 		"\n"
 		"Parameters:\n"
 		"-----------\n"
@@ -27469,6 +31540,52 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"nNewDimension:  New coordinate dimension value, either 2 or 3. \n"
 		""},
+	 { (char *)"Geometry_Set3D", _wrap_Geometry_Set3D, METH_VARARGS, (char *)"\n"
+		"Geometry_Set3D(Geometry self, int b3D)\n"
+		"\n"
+		"void OGR_G_Set3D(OGRGeometryH hGeom,\n"
+		"int bIs3D)\n"
+		"\n"
+		"Add or remove the Z coordinate dimension.\n"
+		"\n"
+		"This method adds or removes the explicit Z coordinate dimension.\n"
+		"Removing the Z coordinate dimension of a geometry will remove any\n"
+		"existing Z values. Adding the Z dimension to a geometry collection, a\n"
+		"compound curve, a polygon, etc. will affect the children geometries.\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hGeom:  handle on the geometry to set or unset the Z dimension.\n"
+		"\n"
+		"bIs3D:  Should the geometry have a Z dimension, either TRUE or FALSE.\n"
+		"\n"
+		"GDAL 2.1 \n"
+		""},
+	 { (char *)"Geometry_SetMeasured", _wrap_Geometry_SetMeasured, METH_VARARGS, (char *)"\n"
+		"Geometry_SetMeasured(Geometry self, int bMeasured)\n"
+		"\n"
+		"void\n"
+		"OGR_G_SetMeasured(OGRGeometryH hGeom, int bIsMeasured)\n"
+		"\n"
+		"Set the coordinate dimension.\n"
+		"\n"
+		"Add or remove the M coordinate dimension. This method adds or removes\n"
+		"the explicit M coordinate dimension. Removing the M coordinate\n"
+		"dimension of a geometry will remove any existing M values. Adding the\n"
+		"M dimension to a geometry collection, a compound curve, a polygon,\n"
+		"etc. will affect the children geometries.\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hGeom:  handle on the geometry to set or unset the M dimension.\n"
+		"\n"
+		"bIsMeasured:  Should the geometry have a M dimension, either TRUE or\n"
+		"FALSE.\n"
+		"\n"
+		"GDAL 2.1 \n"
+		""},
 	 { (char *)"Geometry_GetDimension", _wrap_Geometry_GetDimension, METH_VARARGS, (char *)"\n"
 		"Geometry_GetDimension(Geometry self) -> int\n"
 		"\n"
@@ -27492,41 +31609,40 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"0 for points, 1 for lines and 2 for surfaces. \n"
 		""},
-	 { (char *)"Geometry_HasCurveGeometry", _wrap_Geometry_HasCurveGeometry, METH_VARARGS, (char *)"Geometry_HasCurveGeometry(Geometry self, int bLookForCircular = True) -> int"},
-	 { (char *)"Geometry_GetLinearGeometry", (PyCFunction) _wrap_Geometry_GetLinearGeometry, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Geometry_GetLinearGeometry(Geometry self, double dfMaxAngleStepSizeDegrees = 0.0, \n"
-		"    char options = None) -> Geometry\n"
-		""},
-	 { (char *)"Geometry_GetCurveGeometry", (PyCFunction) _wrap_Geometry_GetCurveGeometry, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_GetCurveGeometry(Geometry self, char options = None) -> Geometry"},
+	 { (char *)"Geometry_HasCurveGeometry", _wrap_Geometry_HasCurveGeometry, METH_VARARGS, (char *)"Geometry_HasCurveGeometry(Geometry self, int bLookForCircular=False) -> int"},
+	 { (char *)"Geometry_GetLinearGeometry", (PyCFunction) _wrap_Geometry_GetLinearGeometry, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_GetLinearGeometry(Geometry self, double dfMaxAngleStepSizeDegrees=0.0, char ** options=None) -> Geometry"},
+	 { (char *)"Geometry_GetCurveGeometry", (PyCFunction) _wrap_Geometry_GetCurveGeometry, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_GetCurveGeometry(Geometry self, char ** options=None) -> Geometry"},
 	 { (char *)"Geometry_Value", _wrap_Geometry_Value, METH_VARARGS, (char *)"Geometry_Value(Geometry self, double dfDistance) -> Geometry"},
 	 { (char *)"Geometry_swigregister", Geometry_swigregister, METH_VARARGS, NULL},
 	 { (char *)"GetDriverCount", _wrap_GetDriverCount, METH_VARARGS, (char *)"GetDriverCount() -> int"},
 	 { (char *)"GetOpenDSCount", _wrap_GetOpenDSCount, METH_VARARGS, (char *)"GetOpenDSCount() -> int"},
 	 { (char *)"SetGenerate_DB2_V72_BYTE_ORDER", _wrap_SetGenerate_DB2_V72_BYTE_ORDER, METH_VARARGS, (char *)"SetGenerate_DB2_V72_BYTE_ORDER(int bGenerate_DB2_V72_BYTE_ORDER) -> OGRErr"},
 	 { (char *)"RegisterAll", _wrap_RegisterAll, METH_VARARGS, (char *)"RegisterAll()"},
-	 { (char *)"GeometryTypeToName", _wrap_GeometryTypeToName, METH_VARARGS, (char *)"GeometryTypeToName(OGRwkbGeometryType eType) -> char"},
-	 { (char *)"GetFieldTypeName", _wrap_GetFieldTypeName, METH_VARARGS, (char *)"GetFieldTypeName(OGRFieldType type) -> char"},
-	 { (char *)"GetFieldSubTypeName", _wrap_GetFieldSubTypeName, METH_VARARGS, (char *)"GetFieldSubTypeName(OGRFieldSubType type) -> char"},
+	 { (char *)"GeometryTypeToName", _wrap_GeometryTypeToName, METH_VARARGS, (char *)"GeometryTypeToName(OGRwkbGeometryType eType) -> char const *"},
+	 { (char *)"GetFieldTypeName", _wrap_GetFieldTypeName, METH_VARARGS, (char *)"GetFieldTypeName(OGRFieldType type) -> char const *"},
+	 { (char *)"GetFieldSubTypeName", _wrap_GetFieldSubTypeName, METH_VARARGS, (char *)"GetFieldSubTypeName(OGRFieldSubType type) -> char const *"},
 	 { (char *)"GT_Flatten", _wrap_GT_Flatten, METH_VARARGS, (char *)"GT_Flatten(OGRwkbGeometryType eType) -> OGRwkbGeometryType"},
 	 { (char *)"GT_SetZ", _wrap_GT_SetZ, METH_VARARGS, (char *)"GT_SetZ(OGRwkbGeometryType eType) -> OGRwkbGeometryType"},
-	 { (char *)"GT_SetModifier", _wrap_GT_SetModifier, METH_VARARGS, (char *)"GT_SetModifier(OGRwkbGeometryType eType, int bSetZ, int bSetM = True) -> OGRwkbGeometryType"},
+	 { (char *)"GT_SetM", _wrap_GT_SetM, METH_VARARGS, (char *)"GT_SetM(OGRwkbGeometryType eType) -> OGRwkbGeometryType"},
+	 { (char *)"GT_SetModifier", _wrap_GT_SetModifier, METH_VARARGS, (char *)"GT_SetModifier(OGRwkbGeometryType eType, int bSetZ, int bSetM=False) -> OGRwkbGeometryType"},
 	 { (char *)"GT_HasZ", _wrap_GT_HasZ, METH_VARARGS, (char *)"GT_HasZ(OGRwkbGeometryType eType) -> int"},
+	 { (char *)"GT_HasM", _wrap_GT_HasM, METH_VARARGS, (char *)"GT_HasM(OGRwkbGeometryType eType) -> int"},
 	 { (char *)"GT_IsSubClassOf", _wrap_GT_IsSubClassOf, METH_VARARGS, (char *)"GT_IsSubClassOf(OGRwkbGeometryType eType, OGRwkbGeometryType eSuperType) -> int"},
-	 { (char *)"GT_IsCurve", _wrap_GT_IsCurve, METH_VARARGS, (char *)"GT_IsCurve(OGRwkbGeometryType arg0) -> int"},
-	 { (char *)"GT_IsSurface", _wrap_GT_IsSurface, METH_VARARGS, (char *)"GT_IsSurface(OGRwkbGeometryType arg0) -> int"},
-	 { (char *)"GT_IsNonLinear", _wrap_GT_IsNonLinear, METH_VARARGS, (char *)"GT_IsNonLinear(OGRwkbGeometryType arg0) -> int"},
+	 { (char *)"GT_IsCurve", _wrap_GT_IsCurve, METH_VARARGS, (char *)"GT_IsCurve(OGRwkbGeometryType arg1) -> int"},
+	 { (char *)"GT_IsSurface", _wrap_GT_IsSurface, METH_VARARGS, (char *)"GT_IsSurface(OGRwkbGeometryType arg1) -> int"},
+	 { (char *)"GT_IsNonLinear", _wrap_GT_IsNonLinear, METH_VARARGS, (char *)"GT_IsNonLinear(OGRwkbGeometryType arg1) -> int"},
 	 { (char *)"GT_GetCollection", _wrap_GT_GetCollection, METH_VARARGS, (char *)"GT_GetCollection(OGRwkbGeometryType eType) -> OGRwkbGeometryType"},
 	 { (char *)"GT_GetCurve", _wrap_GT_GetCurve, METH_VARARGS, (char *)"GT_GetCurve(OGRwkbGeometryType eType) -> OGRwkbGeometryType"},
 	 { (char *)"GT_GetLinear", _wrap_GT_GetLinear, METH_VARARGS, (char *)"GT_GetLinear(OGRwkbGeometryType eType) -> OGRwkbGeometryType"},
 	 { (char *)"SetNonLinearGeometriesEnabledFlag", _wrap_SetNonLinearGeometriesEnabledFlag, METH_VARARGS, (char *)"SetNonLinearGeometriesEnabledFlag(int bFlag)"},
 	 { (char *)"GetNonLinearGeometriesEnabledFlag", _wrap_GetNonLinearGeometriesEnabledFlag, METH_VARARGS, (char *)"GetNonLinearGeometriesEnabledFlag() -> int"},
 	 { (char *)"GetOpenDS", _wrap_GetOpenDS, METH_VARARGS, (char *)"GetOpenDS(int ds_number) -> DataSource"},
-	 { (char *)"Open", (PyCFunction) _wrap_Open, METH_VARARGS | METH_KEYWORDS, (char *)"Open(char utf8_path, int update = 0) -> DataSource"},
-	 { (char *)"OpenShared", (PyCFunction) _wrap_OpenShared, METH_VARARGS | METH_KEYWORDS, (char *)"OpenShared(char utf8_path, int update = 0) -> DataSource"},
-	 { (char *)"GetDriverByName", _wrap_GetDriverByName, METH_VARARGS, (char *)"GetDriverByName(char name) -> Driver"},
+	 { (char *)"Open", (PyCFunction) _wrap_Open, METH_VARARGS | METH_KEYWORDS, (char *)"Open(char const * utf8_path, int update=0) -> DataSource"},
+	 { (char *)"OpenShared", (PyCFunction) _wrap_OpenShared, METH_VARARGS | METH_KEYWORDS, (char *)"OpenShared(char const * utf8_path, int update=0) -> DataSource"},
+	 { (char *)"GetDriverByName", _wrap_GetDriverByName, METH_VARARGS, (char *)"GetDriverByName(char const * name) -> Driver"},
 	 { (char *)"GetDriver", _wrap_GetDriver, METH_VARARGS, (char *)"GetDriver(int driver_number) -> Driver"},
-	 { (char *)"GeneralCmdLineProcessor", _wrap_GeneralCmdLineProcessor, METH_VARARGS, (char *)"GeneralCmdLineProcessor(char papszArgv, int nOptions = 0) -> char"},
-	 { (char *)"TermProgress_nocb", (PyCFunction) _wrap_TermProgress_nocb, METH_VARARGS | METH_KEYWORDS, (char *)"TermProgress_nocb(double dfProgress, char pszMessage = None, void pData = None) -> int"},
+	 { (char *)"GeneralCmdLineProcessor", _wrap_GeneralCmdLineProcessor, METH_VARARGS, (char *)"GeneralCmdLineProcessor(char ** papszArgv, int nOptions=0) -> char **"},
+	 { (char *)"TermProgress_nocb", (PyCFunction) _wrap_TermProgress_nocb, METH_VARARGS | METH_KEYWORDS, (char *)"TermProgress_nocb(double dfProgress, char const * pszMessage=None, void * pData=None) -> int"},
 	 { NULL, NULL, 0, NULL }
 };
 
@@ -27654,18 +31770,18 @@ static swig_const_info swig_const_table[] = {
 #endif
 /* -----------------------------------------------------------------------------
  * Type initialization:
- * This problem is tough by the requirement that no dynamic 
- * memory is used. Also, since swig_type_info structures store pointers to 
+ * This problem is tough by the requirement that no dynamic
+ * memory is used. Also, since swig_type_info structures store pointers to
  * swig_cast_info structures and swig_cast_info structures store pointers back
- * to swig_type_info structures, we need some lookup code at initialization. 
- * The idea is that swig generates all the structures that are needed. 
- * The runtime then collects these partially filled structures. 
- * The SWIG_InitializeModule function takes these initial arrays out of 
+ * to swig_type_info structures, we need some lookup code at initialization.
+ * The idea is that swig generates all the structures that are needed.
+ * The runtime then collects these partially filled structures.
+ * The SWIG_InitializeModule function takes these initial arrays out of
  * swig_module, and does all the lookup, filling in the swig_module.types
  * array with the correct data and linking the correct swig_cast_info
  * structures together.
  *
- * The generated swig_type_info structures are assigned staticly to an initial 
+ * The generated swig_type_info structures are assigned staticly to an initial
  * array. We just loop through that array, and handle each type individually.
  * First we lookup if this type has been already loaded, and if so, use the
  * loaded structure instead of the generated one. Then we have to fill in the
@@ -27675,17 +31791,17 @@ static swig_const_info swig_const_table[] = {
  * a column is one of the swig_cast_info structures for that type.
  * The cast_initial array is actually an array of arrays, because each row has
  * a variable number of columns. So to actually build the cast linked list,
- * we find the array of casts associated with the type, and loop through it 
+ * we find the array of casts associated with the type, and loop through it
  * adding the casts to the list. The one last trick we need to do is making
  * sure the type pointer in the swig_cast_info struct is correct.
  *
- * First off, we lookup the cast->type name to see if it is already loaded. 
+ * First off, we lookup the cast->type name to see if it is already loaded.
  * There are three cases to handle:
  *  1) If the cast->type has already been loaded AND the type we are adding
  *     casting info to has not been loaded (it is in this module), THEN we
  *     replace the cast->type pointer with the type pointer that has already
  *     been loaded.
- *  2) If BOTH types (the one we are adding casting info to, and the 
+ *  2) If BOTH types (the one we are adding casting info to, and the
  *     cast->type) are loaded, THEN the cast info has already been loaded by
  *     the previous module so we just ignore it.
  *  3) Finally, if cast->type has not already been loaded, then we add that
@@ -27711,8 +31827,6 @@ SWIG_InitializeModule(void *clientdata) {
   swig_module_info *module_head, *iter;
   int found, init;
   
-  clientdata = clientdata;
-  
   /* check to see if the circular list has been setup, if not, set it up */
   if (swig_module.next==0) {
     /* Initialize the swig_module */
@@ -27730,7 +31844,7 @@ SWIG_InitializeModule(void *clientdata) {
     /* This is the first module loaded for this interpreter */
     /* so set the swig module into the interpreter */
     SWIG_SetModule(clientdata, &swig_module);
-    module_head = &swig_module;
+    /*module_head = &swig_module;*/
   } else {
     /* the interpreter has loaded a SWIG module, but has it loaded this one? */
     found=0;
@@ -27750,7 +31864,7 @@ SWIG_InitializeModule(void *clientdata) {
     module_head->next = &swig_module;
   }
   
-  /* When multiple interpeters are used, a module could have already been initialized in
+  /* When multiple interpreters are used, a module could have already been initialized in
        a different interpreter, but not yet have a pointer in this interpreter.
        In this case, we do not want to continue adding types... everything should be
        set up already */
@@ -28023,24 +32137,23 @@ extern "C" {
   swig_varlink_type(void) {
     static char varlink__doc__[] = "Swig var link object";
     static PyTypeObject varlink_type;
-    static int type_init = 0;  
+    static int type_init = 0;
     if (!type_init) {
-      const PyTypeObject tmp
-      = {
+      const PyTypeObject tmp = {
         /* PyObject header changed in Python 3 */
 #if PY_VERSION_HEX >= 0x03000000
-        PyVarObject_HEAD_INIT(&PyType_Type, 0)
+        PyVarObject_HEAD_INIT(NULL, 0)
 #else
         PyObject_HEAD_INIT(NULL)
-        0,                                  /* Number of items in variable part (ob_size) */
-#endif
-        (char *)"swigvarlink",              /* Type name (tp_name) */
-        sizeof(swig_varlinkobject),         /* Basic size (tp_basicsize) */
-        0,                                  /* Itemsize (tp_itemsize) */
-        (destructor) swig_varlink_dealloc,  /* Deallocator (tp_dealloc) */ 
-        (printfunc) swig_varlink_print,     /* Print (tp_print) */
-        (getattrfunc) swig_varlink_getattr, /* get attr (tp_getattr) */
-        (setattrfunc) swig_varlink_setattr, /* Set attr (tp_setattr) */
+        0,                                  /* ob_size */
+#endif
+        (char *)"swigvarlink",              /* tp_name */
+        sizeof(swig_varlinkobject),         /* tp_basicsize */
+        0,                                  /* tp_itemsize */
+        (destructor) swig_varlink_dealloc,  /* tp_dealloc */
+        (printfunc) swig_varlink_print,     /* tp_print */
+        (getattrfunc) swig_varlink_getattr, /* tp_getattr */
+        (setattrfunc) swig_varlink_setattr, /* tp_setattr */
         0,                                  /* tp_compare */
         (reprfunc) swig_varlink_repr,       /* tp_repr */
         0,                                  /* tp_as_number */
@@ -28064,16 +32177,21 @@ extern "C" {
 #if PY_VERSION_HEX >= 0x02030000
         0,                                  /* tp_del */
 #endif
+#if PY_VERSION_HEX >= 0x02060000
+        0,                                  /* tp_version */
+#endif
 #ifdef COUNT_ALLOCS
         0,0,0,0                             /* tp_alloc -> tp_next */
 #endif
       };
       varlink_type = tmp;
-      /* for Python 3 we already assigned ob_type in PyVarObject_HEAD_INIT() */
-#if PY_VERSION_HEX < 0x03000000
+      type_init = 1;
+#if PY_VERSION_HEX < 0x02020000
       varlink_type.ob_type = &PyType_Type;
+#else
+      if (PyType_Ready(&varlink_type) < 0)
+      return NULL;
 #endif
-      type_init = 1;
     }
     return &varlink_type;
   }
@@ -28124,7 +32242,7 @@ extern "C" {
     for (i = 0; constants[i].type; ++i) {
       switch(constants[i].type) {
       case SWIG_PY_POINTER:
-        obj = SWIG_NewPointerObj(constants[i].pvalue, *(constants[i]).ptype,0);
+        obj = SWIG_InternalNewPointerObj(constants[i].pvalue, *(constants[i]).ptype,0);
         break;
       case SWIG_PY_BINARY:
         obj = SWIG_NewPackedObj(constants[i].pvalue, constants[i].lvalue, *(constants[i].ptype));
@@ -28164,18 +32282,18 @@ extern "C" {
           }
         }
         if (ci) {
-          size_t shift = (ci->ptype) - types;
-          swig_type_info *ty = types_initial[shift];
-          size_t ldoc = (c - methods[i].ml_doc);
-          size_t lptr = strlen(ty->name)+2*sizeof(void*)+2;
-          char *ndoc = (char*)malloc(ldoc + lptr + 10);
-          if (ndoc) {
-            char *buff = ndoc;
-            void *ptr = (ci->type == SWIG_PY_POINTER) ? ci->pvalue : 0;
-            if (ptr) {
+          void *ptr = (ci->type == SWIG_PY_POINTER) ? ci->pvalue : 0;
+          if (ptr) {
+            size_t shift = (ci->ptype) - types;
+            swig_type_info *ty = types_initial[shift];
+            size_t ldoc = (c - methods[i].ml_doc);
+            size_t lptr = strlen(ty->name)+2*sizeof(void*)+2;
+            char *ndoc = (char*)malloc(ldoc + lptr + 10);
+            if (ndoc) {
+              char *buff = ndoc;
               strncpy(buff, methods[i].ml_doc, ldoc);
               buff += ldoc;
-              strncpy(buff, "swig_ptr: ", 10);
+              memcpy(buff, "swig_ptr: ", 10);
               buff += 10;
               SWIG_PackVoidPtr(buff, ptr, ty->name, lptr);
               methods[i].ml_doc = ndoc;
@@ -28205,10 +32323,19 @@ PyObject*
 void
 #endif
 SWIG_init(void) {
-  PyObject *m, *d;  
+  PyObject *m, *d, *md;
 #if PY_VERSION_HEX >= 0x03000000
   static struct PyModuleDef SWIG_module = {
+# if PY_VERSION_HEX >= 0x03020000
     PyModuleDef_HEAD_INIT,
+# else
+    {
+      PyObject_HEAD_INIT(NULL)
+      NULL, /* m_init */
+      0,    /* m_index */
+      NULL, /* m_copy */
+    },
+# endif
     (char *) SWIG_name,
     NULL,
     -1,
@@ -28220,6 +32347,49 @@ SWIG_init(void) {
   };
 #endif
   
+#if defined(SWIGPYTHON_BUILTIN)
+  static SwigPyClientData SwigPyObject_clientdata = {
+    0, 0, 0, 0, 0, 0, 0
+  };
+  static PyGetSetDef this_getset_def = {
+    (char *)"this", &SwigPyBuiltin_ThisClosure, NULL, NULL, NULL
+  };
+  static SwigPyGetSet thisown_getset_closure = {
+    (PyCFunction) SwigPyObject_own,
+    (PyCFunction) SwigPyObject_own
+  };
+  static PyGetSetDef thisown_getset_def = {
+    (char *)"thisown", SwigPyBuiltin_GetterClosure, SwigPyBuiltin_SetterClosure, NULL, &thisown_getset_closure
+  };
+  PyObject *metatype_args;
+  PyTypeObject *builtin_pytype;
+  int builtin_base_count;
+  swig_type_info *builtin_basetype;
+  PyObject *tuple;
+  PyGetSetDescrObject *static_getset;
+  PyTypeObject *metatype;
+  SwigPyClientData *cd;
+  PyObject *public_interface, *public_symbol;
+  PyObject *this_descr;
+  PyObject *thisown_descr;
+  int i;
+  
+  (void)builtin_pytype;
+  (void)builtin_base_count;
+  (void)builtin_basetype;
+  (void)tuple;
+  (void)static_getset;
+  
+  /* metatype is used to implement static member variables. */
+  metatype_args = Py_BuildValue("(s(O){})", "SwigPyObjectType", &PyType_Type);
+  assert(metatype_args);
+  metatype = (PyTypeObject *) PyType_Type.tp_call((PyObject *) &PyType_Type, metatype_args, NULL);
+  assert(metatype);
+  Py_DECREF(metatype_args);
+  metatype->tp_setattro = (setattrofunc) &SwigPyObjectType_setattro;
+  assert(PyType_Ready(metatype) >= 0);
+#endif
+  
   /* Fix SwigMethods to carry the callback ptrs when needed */
   SWIG_Python_FixMethods(SwigMethods, swig_const_table, swig_types, swig_type_initial);
   
@@ -28228,11 +32398,48 @@ SWIG_init(void) {
 #else
   m = Py_InitModule((char *) SWIG_name, SwigMethods);
 #endif
-  d = PyModule_GetDict(m);
+  md = d = PyModule_GetDict(m);
+  (void)md;
   
   SWIG_InitializeModule(0);
-  SWIG_InstallConstants(d,swig_const_table);
   
+#ifdef SWIGPYTHON_BUILTIN
+  SwigPyObject_stype = SWIG_MangledTypeQuery("_p_SwigPyObject");
+  assert(SwigPyObject_stype);
+  cd = (SwigPyClientData*) SwigPyObject_stype->clientdata;
+  if (!cd) {
+    SwigPyObject_stype->clientdata = &SwigPyObject_clientdata;
+    SwigPyObject_clientdata.pytype = SwigPyObject_TypeOnce();
+  } else if (SwigPyObject_TypeOnce()->tp_basicsize != cd->pytype->tp_basicsize) {
+    PyErr_SetString(PyExc_RuntimeError, "Import error: attempted to load two incompatible swig-generated modules.");
+# if PY_VERSION_HEX >= 0x03000000
+    return NULL;
+# else
+    return;
+# endif
+  }
+  
+  /* All objects have a 'this' attribute */
+  this_descr = PyDescr_NewGetSet(SwigPyObject_type(), &this_getset_def);
+  (void)this_descr;
+  
+  /* All objects have a 'thisown' attribute */
+  thisown_descr = PyDescr_NewGetSet(SwigPyObject_type(), &thisown_getset_def);
+  (void)thisown_descr;
+  
+  public_interface = PyList_New(0);
+  public_symbol = 0;
+  (void)public_symbol;
+  
+  PyDict_SetItemString(md, "__all__", public_interface);
+  Py_DECREF(public_interface);
+  for (i = 0; SwigMethods[i].ml_name != NULL; ++i)
+  SwigPyBuiltin_AddPublicSymbol(public_interface, SwigMethods[i].ml_name);
+  for (i = 0; swig_const_table[i].name != 0; ++i)
+  SwigPyBuiltin_AddPublicSymbol(public_interface, swig_const_table[i].name);
+#endif
+  
+  SWIG_InstallConstants(d,swig_const_table);
   
   SWIG_Python_SetConstant(d, "wkb25DBit",SWIG_From_int(static_cast< int >(0x80000000)));
   SWIG_Python_SetConstant(d, "wkb25Bit",SWIG_From_int(static_cast< int >(0x80000000)));
@@ -28249,6 +32456,10 @@ SWIG_init(void) {
   SWIG_Python_SetConstant(d, "wkbCurvePolygon",SWIG_From_int(static_cast< int >(10)));
   SWIG_Python_SetConstant(d, "wkbMultiCurve",SWIG_From_int(static_cast< int >(11)));
   SWIG_Python_SetConstant(d, "wkbMultiSurface",SWIG_From_int(static_cast< int >(12)));
+  SWIG_Python_SetConstant(d, "wkbCurve",SWIG_From_int(static_cast< int >(13)));
+  SWIG_Python_SetConstant(d, "wkbSurface",SWIG_From_int(static_cast< int >(14)));
+  SWIG_Python_SetConstant(d, "wkbPolyhedralSurface",SWIG_From_int(static_cast< int >(15)));
+  SWIG_Python_SetConstant(d, "wkbTIN",SWIG_From_int(static_cast< int >(16)));
   SWIG_Python_SetConstant(d, "wkbNone",SWIG_From_int(static_cast< int >(100)));
   SWIG_Python_SetConstant(d, "wkbLinearRing",SWIG_From_int(static_cast< int >(101)));
   SWIG_Python_SetConstant(d, "wkbCircularStringZ",SWIG_From_int(static_cast< int >(1008)));
@@ -28256,6 +32467,42 @@ SWIG_init(void) {
   SWIG_Python_SetConstant(d, "wkbCurvePolygonZ",SWIG_From_int(static_cast< int >(1010)));
   SWIG_Python_SetConstant(d, "wkbMultiCurveZ",SWIG_From_int(static_cast< int >(1011)));
   SWIG_Python_SetConstant(d, "wkbMultiSurfaceZ",SWIG_From_int(static_cast< int >(1012)));
+  SWIG_Python_SetConstant(d, "wkbCurveZ",SWIG_From_int(static_cast< int >(1013)));
+  SWIG_Python_SetConstant(d, "wkbSurfaceZ",SWIG_From_int(static_cast< int >(1014)));
+  SWIG_Python_SetConstant(d, "wkbPolyhedralSurfaceZ",SWIG_From_int(static_cast< int >(1015)));
+  SWIG_Python_SetConstant(d, "wkbTINZ",SWIG_From_int(static_cast< int >(1016)));
+  SWIG_Python_SetConstant(d, "wkbPointM",SWIG_From_int(static_cast< int >(2001)));
+  SWIG_Python_SetConstant(d, "wkbLineStringM",SWIG_From_int(static_cast< int >(2002)));
+  SWIG_Python_SetConstant(d, "wkbPolygonM",SWIG_From_int(static_cast< int >(2003)));
+  SWIG_Python_SetConstant(d, "wkbMultiPointM",SWIG_From_int(static_cast< int >(2004)));
+  SWIG_Python_SetConstant(d, "wkbMultiLineStringM",SWIG_From_int(static_cast< int >(2005)));
+  SWIG_Python_SetConstant(d, "wkbMultiPolygonM",SWIG_From_int(static_cast< int >(2006)));
+  SWIG_Python_SetConstant(d, "wkbGeometryCollectionM",SWIG_From_int(static_cast< int >(2007)));
+  SWIG_Python_SetConstant(d, "wkbCircularStringM",SWIG_From_int(static_cast< int >(2008)));
+  SWIG_Python_SetConstant(d, "wkbCompoundCurveM",SWIG_From_int(static_cast< int >(2009)));
+  SWIG_Python_SetConstant(d, "wkbCurvePolygonM",SWIG_From_int(static_cast< int >(2010)));
+  SWIG_Python_SetConstant(d, "wkbMultiCurveM",SWIG_From_int(static_cast< int >(2011)));
+  SWIG_Python_SetConstant(d, "wkbMultiSurfaceM",SWIG_From_int(static_cast< int >(2012)));
+  SWIG_Python_SetConstant(d, "wkbCurveM",SWIG_From_int(static_cast< int >(2013)));
+  SWIG_Python_SetConstant(d, "wkbSurfaceM",SWIG_From_int(static_cast< int >(2014)));
+  SWIG_Python_SetConstant(d, "wkbPolyhedralSurfaceM",SWIG_From_int(static_cast< int >(2015)));
+  SWIG_Python_SetConstant(d, "wkbTINM",SWIG_From_int(static_cast< int >(2016)));
+  SWIG_Python_SetConstant(d, "wkbPointZM",SWIG_From_int(static_cast< int >(3001)));
+  SWIG_Python_SetConstant(d, "wkbLineStringZM",SWIG_From_int(static_cast< int >(3002)));
+  SWIG_Python_SetConstant(d, "wkbPolygonZM",SWIG_From_int(static_cast< int >(3003)));
+  SWIG_Python_SetConstant(d, "wkbMultiPointZM",SWIG_From_int(static_cast< int >(3004)));
+  SWIG_Python_SetConstant(d, "wkbMultiLineStringZM",SWIG_From_int(static_cast< int >(3005)));
+  SWIG_Python_SetConstant(d, "wkbMultiPolygonZM",SWIG_From_int(static_cast< int >(3006)));
+  SWIG_Python_SetConstant(d, "wkbGeometryCollectionZM",SWIG_From_int(static_cast< int >(3007)));
+  SWIG_Python_SetConstant(d, "wkbCircularStringZM",SWIG_From_int(static_cast< int >(3008)));
+  SWIG_Python_SetConstant(d, "wkbCompoundCurveZM",SWIG_From_int(static_cast< int >(3009)));
+  SWIG_Python_SetConstant(d, "wkbCurvePolygonZM",SWIG_From_int(static_cast< int >(3010)));
+  SWIG_Python_SetConstant(d, "wkbMultiCurveZM",SWIG_From_int(static_cast< int >(3011)));
+  SWIG_Python_SetConstant(d, "wkbMultiSurfaceZM",SWIG_From_int(static_cast< int >(3012)));
+  SWIG_Python_SetConstant(d, "wkbCurveZM",SWIG_From_int(static_cast< int >(3013)));
+  SWIG_Python_SetConstant(d, "wkbSurfaceZM",SWIG_From_int(static_cast< int >(3014)));
+  SWIG_Python_SetConstant(d, "wkbPolyhedralSurfaceZM",SWIG_From_int(static_cast< int >(3015)));
+  SWIG_Python_SetConstant(d, "wkbTINZM",SWIG_From_int(static_cast< int >(3016)));
   SWIG_Python_SetConstant(d, "wkbPoint25D",SWIG_From_int(static_cast< int >(0x80000001)));
   SWIG_Python_SetConstant(d, "wkbLineString25D",SWIG_From_int(static_cast< int >(0x80000002)));
   SWIG_Python_SetConstant(d, "wkbPolygon25D",SWIG_From_int(static_cast< int >(0x80000003)));
@@ -28315,12 +32562,14 @@ SWIG_init(void) {
   SWIG_Python_SetConstant(d, "OLCIgnoreFields",SWIG_FromCharPtr("IgnoreFields"));
   SWIG_Python_SetConstant(d, "OLCCreateGeomField",SWIG_FromCharPtr("CreateGeomField"));
   SWIG_Python_SetConstant(d, "OLCCurveGeometries",SWIG_FromCharPtr("CurveGeometries"));
+  SWIG_Python_SetConstant(d, "OLCMeasuredGeometries",SWIG_FromCharPtr("MeasuredGeometries"));
   SWIG_Python_SetConstant(d, "ODsCCreateLayer",SWIG_FromCharPtr("CreateLayer"));
   SWIG_Python_SetConstant(d, "ODsCDeleteLayer",SWIG_FromCharPtr("DeleteLayer"));
   SWIG_Python_SetConstant(d, "ODsCCreateGeomFieldAfterCreateLayer",SWIG_FromCharPtr("CreateGeomFieldAfterCreateLayer"));
   SWIG_Python_SetConstant(d, "ODsCCurveGeometries",SWIG_FromCharPtr("CurveGeometries"));
   SWIG_Python_SetConstant(d, "ODsCTransactions",SWIG_FromCharPtr("Transactions"));
   SWIG_Python_SetConstant(d, "ODsCEmulatedTransactions",SWIG_FromCharPtr("EmulatedTransactions"));
+  SWIG_Python_SetConstant(d, "ODsCMeasuredGeometries",SWIG_FromCharPtr("MeasuredGeometries"));
   SWIG_Python_SetConstant(d, "ODrCCreateDataSource",SWIG_FromCharPtr("CreateDataSource"));
   SWIG_Python_SetConstant(d, "ODrCDeleteDataSource",SWIG_FromCharPtr("DeleteDataSource"));
   SWIG_Python_SetConstant(d, "OLMD_FID64",SWIG_FromCharPtr("OLMD_FID64"));
diff --git a/swig/python/extensions/osr_wrap.cpp b/swig/python/extensions/osr_wrap.cpp
index a19501e..a801ba0 100644
--- a/swig/python/extensions/osr_wrap.cpp
+++ b/swig/python/extensions/osr_wrap.cpp
@@ -1,14 +1,15 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.40
- * 
- * This file is not intended to be easily readable and contains a number of 
+ * Version 2.0.12
+ *
+ * This file is not intended to be easily readable and contains a number of
  * coding conventions designed to improve portability and efficiency. Do not make
- * changes to this file unless you know what you are doing--modify the SWIG 
- * interface file instead. 
+ * changes to this file unless you know what you are doing--modify the SWIG
+ * interface file instead.
  * ----------------------------------------------------------------------------- */
 
 #define SWIGPYTHON
+#define SED_HACKS
 #define SWIG_PYTHON_DIRECTOR_NO_VTABLE
 
 
@@ -66,28 +67,28 @@ template <typename T> T SwigValueInit() {
 #ifndef SWIGUNUSED
 # if defined(__GNUC__)
 #   if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
-#     define SWIGUNUSED __attribute__ ((__unused__)) 
+#     define SWIGUNUSED __attribute__ ((__unused__))
 #   else
 #     define SWIGUNUSED
 #   endif
 # elif defined(__ICC)
-#   define SWIGUNUSED __attribute__ ((__unused__)) 
+#   define SWIGUNUSED __attribute__ ((__unused__))
 # else
-#   define SWIGUNUSED 
+#   define SWIGUNUSED
 # endif
 #endif
 
 #ifndef SWIG_MSC_UNSUPPRESS_4505
 # if defined(_MSC_VER)
 #   pragma warning(disable : 4505) /* unreferenced local function has been removed */
-# endif 
+# endif
 #endif
 
 #ifndef SWIGUNUSEDPARM
 # ifdef __cplusplus
 #   define SWIGUNUSEDPARM(p)
 # else
-#   define SWIGUNUSEDPARM(p) p SWIGUNUSED 
+#   define SWIGUNUSEDPARM(p) p SWIGUNUSED
 # endif
 #endif
 
@@ -130,7 +131,7 @@ template <typename T> T SwigValueInit() {
 #   define SWIGSTDCALL __stdcall
 # else
 #   define SWIGSTDCALL
-# endif 
+# endif
 #endif
 
 /* Deal with Microsoft's attempt at deprecating C standard runtime functions */
@@ -145,8 +146,14 @@ template <typename T> T SwigValueInit() {
 
 
 
-/* Python.h has to appear first */
-#include <Python.h>
+#if defined(_DEBUG) && defined(SWIG_PYTHON_INTERPRETER_NO_DEBUG)
+/* Use debug wrappers with the Python release dll */
+# undef _DEBUG
+# include <Python.h>
+# define _DEBUG
+#else
+# include <Python.h>
+#endif
 
 /* -----------------------------------------------------------------------------
  * swigrun.swg
@@ -172,7 +179,7 @@ template <typename T> T SwigValueInit() {
   You can use the SWIGRUNTIME and SWIGRUNTIMEINLINE macros for
   creating a static or dynamic library from the SWIG runtime code.
   In 99.9% of the cases, SWIG just needs to declare them as 'static'.
-  
+
   But only do this if strictly necessary, ie, if you have problems
   with your compiler or suchlike.
 */
@@ -198,16 +205,16 @@ template <typename T> T SwigValueInit() {
 #define SWIG_POINTER_OWN           0x1
 
 
-/* 
+/*
    Flags/methods for returning states.
-   
-   The SWIG conversion methods, as ConvertPtr, return and integer 
+
+   The SWIG conversion methods, as ConvertPtr, return an integer
    that tells if the conversion was successful or not. And if not,
    an error code can be returned (see swigerrors.swg for the codes).
-   
+
    Use the following macros/flags to set or process the returning
    states.
-   
+
    In old versions of SWIG, code such as the following was usually written:
 
      if (SWIG_ConvertPtr(obj,vptr,ty.flags) != -1) {
@@ -240,23 +247,23 @@ template <typename T> T SwigValueInit() {
     } else {
       // fail code
     }
-    
+
    I.e., now SWIG_ConvertPtr can return new objects and you can
    identify the case and take care of the deallocation. Of course that
    also requires SWIG_ConvertPtr to return new result values, such as
 
-      int SWIG_ConvertPtr(obj, ptr,...) {         
-        if (<obj is ok>) {			       
-          if (<need new object>) {		       
-            *ptr = <ptr to new allocated object>; 
-            return SWIG_NEWOBJ;		       
-          } else {				       
-            *ptr = <ptr to old object>;	       
-            return SWIG_OLDOBJ;		       
-          } 				       
-        } else {				       
-          return SWIG_BADOBJ;		       
-        }					       
+      int SWIG_ConvertPtr(obj, ptr,...) {
+        if (<obj is ok>) {
+          if (<need new object>) {
+            *ptr = <ptr to new allocated object>;
+            return SWIG_NEWOBJ;
+          } else {
+            *ptr = <ptr to old object>;
+            return SWIG_OLDOBJ;
+          }
+        } else {
+          return SWIG_BADOBJ;
+        }
       }
 
    Of course, returning the plain '0(success)/-1(fail)' still works, but you can be
@@ -270,17 +277,17 @@ template <typename T> T SwigValueInit() {
        int fooi(int);
 
    and you call
- 
+
       food(1)   // cast rank '1'  (1 -> 1.0)
       fooi(1)   // cast rank '0'
 
    just use the SWIG_AddCast()/SWIG_CheckState()
 */
 
-#define SWIG_OK                    (0) 
+#define SWIG_OK                    (0)
 #define SWIG_ERROR                 (-1)
 #define SWIG_IsOK(r)               (r >= 0)
-#define SWIG_ArgError(r)           ((r != SWIG_ERROR) ? r : SWIG_TypeError)  
+#define SWIG_ArgError(r)           ((r != SWIG_ERROR) ? r : SWIG_TypeError)
 
 /* The CastRankLimit says how many bits are used for the cast rank */
 #define SWIG_CASTRANKLIMIT         (1 << 8)
@@ -311,14 +318,14 @@ template <typename T> T SwigValueInit() {
 #  endif
 #  define SWIG_CASTRANKMASK          ((SWIG_CASTRANKLIMIT) -1)
 #  define SWIG_CastRank(r)           (r & SWIG_CASTRANKMASK)
-SWIGINTERNINLINE int SWIG_AddCast(int r) { 
+SWIGINTERNINLINE int SWIG_AddCast(int r) {
   return SWIG_IsOK(r) ? ((SWIG_CastRank(r) < SWIG_MAXCASTRANK) ? (r + 1) : SWIG_ERROR) : r;
 }
-SWIGINTERNINLINE int SWIG_CheckState(int r) { 
-  return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0; 
+SWIGINTERNINLINE int SWIG_CheckState(int r) {
+  return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0;
 }
 #else /* no cast-rank mode */
-#  define SWIG_AddCast
+#  define SWIG_AddCast(r) (r)
 #  define SWIG_CheckState(r) (SWIG_IsOK(r) ? 1 : 0)
 #endif
 
@@ -362,7 +369,7 @@ typedef struct swig_module_info {
   void                    *clientdata;		/* Language specific module data */
 } swig_module_info;
 
-/* 
+/*
   Compare two type names skipping the space characters, therefore
   "char*" == "char *" and "Class<int>" == "Class<int >", etc.
 
@@ -382,18 +389,18 @@ SWIG_TypeNameComp(const char *f1, const char *l1,
 
 /*
   Check type equivalence in a name list like <name1>|<name2>|...
-  Return 0 if not equal, 1 if equal
+  Return 0 if equal, -1 if nb < tb, 1 if nb > tb
 */
 SWIGRUNTIME int
-SWIG_TypeEquiv(const char *nb, const char *tb) {
-  int equiv = 0;
+SWIG_TypeCmp(const char *nb, const char *tb) {
+  int equiv = 1;
   const char* te = tb + strlen(tb);
   const char* ne = nb;
-  while (!equiv && *ne) {
+  while (equiv != 0 && *ne) {
     for (nb = ne; *ne; ++ne) {
       if (*ne == '|') break;
     }
-    equiv = (SWIG_TypeNameComp(nb, ne, tb, te) == 0) ? 1 : 0;
+    equiv = SWIG_TypeNameComp(nb, ne, tb, te);
     if (*ne) ++ne;
   }
   return equiv;
@@ -401,24 +408,13 @@ SWIG_TypeEquiv(const char *nb, const char *tb) {
 
 /*
   Check type equivalence in a name list like <name1>|<name2>|...
-  Return 0 if equal, -1 if nb < tb, 1 if nb > tb
+  Return 0 if not equal, 1 if equal
 */
 SWIGRUNTIME int
-SWIG_TypeCompare(const char *nb, const char *tb) {
-  int equiv = 0;
-  const char* te = tb + strlen(tb);
-  const char* ne = nb;
-  while (!equiv && *ne) {
-    for (nb = ne; *ne; ++ne) {
-      if (*ne == '|') break;
-    }
-    equiv = (SWIG_TypeNameComp(nb, ne, tb, te) == 0) ? 1 : 0;
-    if (*ne) ++ne;
-  }
-  return equiv;
+SWIG_TypeEquiv(const char *nb, const char *tb) {
+  return SWIG_TypeCmp(nb, tb) == 0 ? 1 : 0;
 }
 
-
 /*
   Check the typename
 */
@@ -446,7 +442,7 @@ SWIG_TypeCheck(const char *c, swig_type_info *ty) {
   return 0;
 }
 
-/* 
+/*
   Identical to SWIG_TypeCheck, except strcmp is replaced with a pointer comparison
 */
 SWIGRUNTIME swig_cast_info *
@@ -481,7 +477,7 @@ SWIG_TypeCast(swig_cast_info *ty, void *ptr, int *newmemory) {
   return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr, newmemory);
 }
 
-/* 
+/*
    Dynamic pointer casting. Down an inheritance hierarchy
 */
 SWIGRUNTIME swig_type_info *
@@ -525,7 +521,7 @@ SWIG_TypePrettyName(const swig_type_info *type) {
     return type->name;
 }
 
-/* 
+/*
    Set the clientdata field for a type
 */
 SWIGRUNTIME void
@@ -533,14 +529,14 @@ SWIG_TypeClientData(swig_type_info *ti, void *clientdata) {
   swig_cast_info *cast = ti->cast;
   /* if (ti->clientdata == clientdata) return; */
   ti->clientdata = clientdata;
-  
+
   while (cast) {
     if (!cast->converter) {
       swig_type_info *tc = cast->type;
       if (!tc->clientdata) {
 	SWIG_TypeClientData(tc, clientdata);
       }
-    }    
+    }
     cast = cast->next;
   }
 }
@@ -549,18 +545,18 @@ SWIG_TypeNewClientData(swig_type_info *ti, void *clientdata) {
   SWIG_TypeClientData(ti, clientdata);
   ti->owndata = 1;
 }
-  
+
 /*
   Search for a swig_type_info structure only by mangled name
   Search is a O(log #types)
-  
-  We start searching at module start, and finish searching when start == end.  
+
+  We start searching at module start, and finish searching when start == end.
   Note: if start == end at the beginning of the function, we go all the way around
   the circular list.
 */
 SWIGRUNTIME swig_type_info *
-SWIG_MangledTypeQueryModule(swig_module_info *start, 
-                            swig_module_info *end, 
+SWIG_MangledTypeQueryModule(swig_module_info *start,
+                            swig_module_info *end,
 		            const char *name) {
   swig_module_info *iter = start;
   do {
@@ -569,11 +565,11 @@ SWIG_MangledTypeQueryModule(swig_module_info *start,
       register size_t r = iter->size - 1;
       do {
 	/* since l+r >= 0, we can (>> 1) instead (/ 2) */
-	register size_t i = (l + r) >> 1; 
+	register size_t i = (l + r) >> 1;
 	const char *iname = iter->types[i]->name;
 	if (iname) {
 	  register int compare = strcmp(name, iname);
-	  if (compare == 0) {	    
+	  if (compare == 0) {
 	    return iter->types[i];
 	  } else if (compare < 0) {
 	    if (i) {
@@ -598,14 +594,14 @@ SWIG_MangledTypeQueryModule(swig_module_info *start,
   Search for a swig_type_info structure for either a mangled name or a human readable name.
   It first searches the mangled names of the types, which is a O(log #types)
   If a type is not found it then searches the human readable names, which is O(#types).
-  
-  We start searching at module start, and finish searching when start == end.  
+
+  We start searching at module start, and finish searching when start == end.
   Note: if start == end at the beginning of the function, we go all the way around
   the circular list.
 */
 SWIGRUNTIME swig_type_info *
-SWIG_TypeQueryModule(swig_module_info *start, 
-                     swig_module_info *end, 
+SWIG_TypeQueryModule(swig_module_info *start,
+                     swig_module_info *end,
 		     const char *name) {
   /* STEP 1: Search the name field using binary search */
   swig_type_info *ret = SWIG_MangledTypeQueryModule(start, end, name);
@@ -624,12 +620,12 @@ SWIG_TypeQueryModule(swig_module_info *start,
       iter = iter->next;
     } while (iter != end);
   }
-  
+
   /* neither found a match */
   return 0;
 }
 
-/* 
+/*
    Pack binary data into a string
 */
 SWIGRUNTIME char *
@@ -645,7 +641,7 @@ SWIG_PackData(char *c, void *ptr, size_t sz) {
   return c;
 }
 
-/* 
+/*
    Unpack binary data from a string
 */
 SWIGRUNTIME const char *
@@ -659,21 +655,21 @@ SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
       uu = ((d - '0') << 4);
     else if ((d >= 'a') && (d <= 'f'))
       uu = ((d - ('a'-10)) << 4);
-    else 
+    else
       return (char *) 0;
     d = *(c++);
     if ((d >= '0') && (d <= '9'))
       uu |= (d - '0');
     else if ((d >= 'a') && (d <= 'f'))
       uu |= (d - ('a'-10));
-    else 
+    else
       return (char *) 0;
     *u = uu;
   }
   return c;
 }
 
-/* 
+/*
    Pack 'void *' into a string buffer.
 */
 SWIGRUNTIME char *
@@ -733,18 +729,18 @@ SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) {
 #endif
 
 /*  Errors in SWIG */
-#define  SWIG_UnknownError    	   -1 
-#define  SWIG_IOError        	   -2 
-#define  SWIG_RuntimeError   	   -3 
-#define  SWIG_IndexError     	   -4 
-#define  SWIG_TypeError      	   -5 
-#define  SWIG_DivisionByZero 	   -6 
-#define  SWIG_OverflowError  	   -7 
-#define  SWIG_SyntaxError    	   -8 
-#define  SWIG_ValueError     	   -9 
+#define  SWIG_UnknownError    	   -1
+#define  SWIG_IOError        	   -2
+#define  SWIG_RuntimeError   	   -3
+#define  SWIG_IndexError     	   -4
+#define  SWIG_TypeError      	   -5
+#define  SWIG_DivisionByZero 	   -6
+#define  SWIG_OverflowError  	   -7
+#define  SWIG_SyntaxError    	   -8
+#define  SWIG_ValueError     	   -9
 #define  SWIG_SystemError    	   -10
 #define  SWIG_AttributeError 	   -11
-#define  SWIG_MemoryError    	   -12 
+#define  SWIG_MemoryError    	   -12
 #define  SWIG_NullReferenceError   -13
 
 
@@ -756,7 +752,16 @@ SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) {
 #define PyInt_Check(x) PyLong_Check(x)
 #define PyInt_AsLong(x) PyLong_AsLong(x)
 #define PyInt_FromLong(x) PyLong_FromLong(x)
+#define PyInt_FromSize_t(x) PyLong_FromSize_t(x)
+#define PyString_Check(name) PyBytes_Check(name)
+#define PyString_FromString(x) PyUnicode_FromString(x)
 #define PyString_Format(fmt, args)  PyUnicode_Format(fmt, args)
+#define PyString_AsString(str) PyBytes_AsString(str)
+#define PyString_Size(str) PyBytes_Size(str)	
+#define PyString_InternFromString(key) PyUnicode_InternFromString(key)
+#define Py_TPFLAGS_HAVE_CLASS Py_TPFLAGS_BASETYPE
+#define PyString_AS_STRING(x) PyUnicode_AS_STRING(x)
+#define _PyLong_FromSsize_t(x) PyLong_FromSsize_t(x)
 
 #endif
 
@@ -896,6 +901,67 @@ PyObject *PyBool_FromLong(long ok)
 typedef int Py_ssize_t;
 # define PY_SSIZE_T_MAX INT_MAX
 # define PY_SSIZE_T_MIN INT_MIN
+typedef inquiry lenfunc;
+typedef intargfunc ssizeargfunc;
+typedef intintargfunc ssizessizeargfunc;
+typedef intobjargproc ssizeobjargproc;
+typedef intintobjargproc ssizessizeobjargproc;
+typedef getreadbufferproc readbufferproc;
+typedef getwritebufferproc writebufferproc;
+typedef getsegcountproc segcountproc;
+typedef getcharbufferproc charbufferproc;
+static long PyNumber_AsSsize_t (PyObject *x, void *SWIGUNUSEDPARM(exc))
+{
+  long result = 0;
+  PyObject *i = PyNumber_Int(x);
+  if (i) {
+    result = PyInt_AsLong(i);
+    Py_DECREF(i);
+  }
+  return result;
+}
+#endif
+
+#if PY_VERSION_HEX < 0x02050000
+#define PyInt_FromSize_t(x) PyInt_FromLong((long)x)
+#endif
+
+#if PY_VERSION_HEX < 0x02040000
+#define Py_VISIT(op)				\
+  do { 						\
+    if (op) {					\
+      int vret = visit((op), arg);		\
+      if (vret)					\
+        return vret;				\
+    }						\
+  } while (0)
+#endif
+
+#if PY_VERSION_HEX < 0x02030000
+typedef struct {
+  PyTypeObject type;
+  PyNumberMethods as_number;
+  PyMappingMethods as_mapping;
+  PySequenceMethods as_sequence;
+  PyBufferProcs as_buffer;
+  PyObject *name, *slots;
+} PyHeapTypeObject;
+#endif
+
+#if PY_VERSION_HEX < 0x02030000
+typedef destructor freefunc;
+#endif
+
+#if ((PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 6) || \
+     (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION > 0) || \
+     (PY_MAJOR_VERSION > 3))
+# define SWIGPY_USE_CAPSULE
+# define SWIGPY_CAPSULE_NAME ((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer_capsule" SWIG_TYPE_TABLE_NAME)
+#endif
+
+#if PY_VERSION_HEX < 0x03020000
+#define PyDescr_TYPE(x) (((PyDescrObject *)(x))->d_type)
+#define PyDescr_NAME(x) (((PyDescrObject *)(x))->d_name)
 #endif
 
 /* -----------------------------------------------------------------------------
@@ -1042,9 +1108,6 @@ SWIG_Python_AddErrorMsg(const char* mesg)
 
 #ifdef __cplusplus
 extern "C" {
-#if 0
-} /* cc-mode */
-#endif
 #endif
 
 /* -----------------------------------------------------------------------------
@@ -1070,27 +1133,24 @@ typedef struct swig_const_info {
  * Wrapper of PyInstanceMethod_New() used in Python 3
  * It is exported to the generated module, used for -fastproxy
  * ----------------------------------------------------------------------------- */
-SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func)
-{
 #if PY_VERSION_HEX >= 0x03000000
+SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *func)
+{
   return PyInstanceMethod_New(func);
+}
 #else
+SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *SWIGUNUSEDPARM(func))
+{
   return NULL;
-#endif
 }
+#endif
 
 #ifdef __cplusplus
-#if 0
-{ /* cc-mode */
-#endif
 }
 #endif
 
 
 /* -----------------------------------------------------------------------------
- * See the LICENSE file for information on copyright, usage and redistribution
- * of SWIG, and the README file for authors - http://www.swig.org/release.html.
- *
  * pyrun.swg
  *
  * This file contains the runtime support for Python modules
@@ -1105,7 +1165,15 @@ SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func)
 #define SWIG_Python_ConvertPtr(obj, pptr, type, flags)  SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, 0)
 #define SWIG_ConvertPtr(obj, pptr, type, flags)         SWIG_Python_ConvertPtr(obj, pptr, type, flags)
 #define SWIG_ConvertPtrAndOwn(obj,pptr,type,flags,own)  SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, own)
-#define SWIG_NewPointerObj(ptr, type, flags)            SWIG_Python_NewPointerObj(ptr, type, flags)
+
+#ifdef SWIGPYTHON_BUILTIN
+#define SWIG_NewPointerObj(ptr, type, flags)            SWIG_Python_NewPointerObj(self, ptr, type, flags)
+#else
+#define SWIG_NewPointerObj(ptr, type, flags)            SWIG_Python_NewPointerObj(NULL, ptr, type, flags)
+#endif
+
+#define SWIG_InternalNewPointerObj(ptr, type, flags)	SWIG_Python_NewPointerObj(NULL, ptr, type, flags)
+
 #define SWIG_CheckImplicit(ty)                          SWIG_Python_CheckImplicit(ty) 
 #define SWIG_AcquirePtr(ptr, src)                       SWIG_Python_AcquirePtr(ptr, src)
 #define swig_owntype                                    int
@@ -1120,7 +1188,7 @@ SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func)
 
 /* for C or C++ function pointers */
 #define SWIG_ConvertFunctionPtr(obj, pptr, type)        SWIG_Python_ConvertFunctionPtr(obj, pptr, type)
-#define SWIG_NewFunctionPtrObj(ptr, type)               SWIG_Python_NewPointerObj(ptr, type, 0)
+#define SWIG_NewFunctionPtrObj(ptr, type)               SWIG_Python_NewPointerObj(NULL, ptr, type, 0)
 
 /* for C++ member pointers, ie, member methods */
 #define SWIG_ConvertMember(obj, ptr, sz, ty)            SWIG_Python_ConvertPacked(obj, ptr, sz, ty)
@@ -1129,11 +1197,7 @@ SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func)
 
 /* Runtime API */
 
-#if PY_VERSION_HEX >= 0x03020000
-#define SWIG_PYTHON_USE_CAPSULE
-#endif
-
-#define SWIG_GetModule(clientdata)                      SWIG_Python_GetModule()
+#define SWIG_GetModule(clientdata)                      SWIG_Python_GetModule(clientdata)
 #define SWIG_SetModule(clientdata, pointer)             SWIG_Python_SetModule(pointer)
 #define SWIG_NewClientData(obj)                         SwigPyClientData_New(obj)
 
@@ -1159,7 +1223,7 @@ SWIG_Python_SetErrorObj(PyObject *errtype, PyObject *obj) {
 SWIGINTERN void 
 SWIG_Python_SetErrorMsg(PyObject *errtype, const char *msg) {
   SWIG_PYTHON_THREAD_BEGIN_BLOCK;
-  PyErr_SetString(errtype, (char *) msg);
+  PyErr_SetString(errtype, msg);
   SWIG_PYTHON_THREAD_END_BLOCK;
 }
 
@@ -1167,12 +1231,41 @@ SWIG_Python_SetErrorMsg(PyObject *errtype, const char *msg) {
 
 /* Set a constant value */
 
+#if defined(SWIGPYTHON_BUILTIN)
+
+SWIGINTERN void
+SwigPyBuiltin_AddPublicSymbol(PyObject *seq, const char *key) {
+  PyObject *s = PyString_InternFromString(key);
+  PyList_Append(seq, s);
+  Py_DECREF(s);
+}
+
+SWIGINTERN void
+SWIG_Python_SetConstant(PyObject *d, PyObject *public_interface, const char *name, PyObject *obj) {   
+#if PY_VERSION_HEX < 0x02030000
+  PyDict_SetItemString(d, (char *)name, obj);
+#else
+  PyDict_SetItemString(d, name, obj);
+#endif
+  Py_DECREF(obj);
+  if (public_interface)
+    SwigPyBuiltin_AddPublicSymbol(public_interface, name);
+}
+
+#else
+
 SWIGINTERN void
 SWIG_Python_SetConstant(PyObject *d, const char *name, PyObject *obj) {   
-  PyDict_SetItemString(d, (char*) name, obj);
+#if PY_VERSION_HEX < 0x02030000
+  PyDict_SetItemString(d, (char *)name, obj);
+#else
+  PyDict_SetItemString(d, name, obj);
+#endif
   Py_DECREF(obj);                            
 }
 
+#endif
+
 /* Append a value to the result obj */
 
 SWIGINTERN PyObject*
@@ -1233,6 +1326,14 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi
     }
   }  
   if (!PyTuple_Check(args)) {
+    if (min <= 1 && max >= 1) {
+      register int i;
+      objs[0] = args;
+      for (i = 1; i < max; ++i) {
+	objs[i] = 0;
+      }
+      return 2;
+    }
     PyErr_SetString(PyExc_SystemError, "UnpackTuple() argument list is not a tuple");
     return 0;
   } else {
@@ -1285,11 +1386,11 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi
 
 #define SWIG_POINTER_IMPLICIT_CONV  (SWIG_POINTER_DISOWN   << 1)
 
+#define SWIG_BUILTIN_TP_INIT	    (SWIG_POINTER_OWN << 2)
+#define SWIG_BUILTIN_INIT	    (SWIG_BUILTIN_TP_INIT | SWIG_POINTER_OWN)
+
 #ifdef __cplusplus
 extern "C" {
-#if 0
-} /* cc-mode */
-#endif
 #endif
 
 /*  How to access Py_None */
@@ -1340,6 +1441,7 @@ typedef struct {
   PyObject *destroy;
   int delargs;
   int implicitconv;
+  PyTypeObject *pytype;
 } SwigPyClientData;
 
 SWIGRUNTIMEINLINE int 
@@ -1406,13 +1508,13 @@ SwigPyClientData_New(PyObject* obj)
       data->delargs = 0;
     }
     data->implicitconv = 0;
+    data->pytype = 0;
     return data;
   }
 }
 
 SWIGRUNTIME void 
-SwigPyClientData_Del(SwigPyClientData* data)
-{
+SwigPyClientData_Del(SwigPyClientData *data) {
   Py_XDECREF(data->newraw);
   Py_XDECREF(data->newargs);
   Py_XDECREF(data->destroy);
@@ -1426,6 +1528,9 @@ typedef struct {
   swig_type_info *ty;
   int own;
   PyObject *next;
+#ifdef SWIGPYTHON_BUILTIN
+  PyObject *dict;
+#endif
 } SwigPyObject;
 
 SWIGRUNTIME PyObject *
@@ -1476,54 +1581,26 @@ SwigPyObject_repr(SwigPyObject *v, PyObject *args)
 #endif
 {
   const char *name = SWIG_TypePrettyName(v->ty);
-  PyObject *repr = SWIG_Python_str_FromFormat("<Swig Object of type '%s' at %p>", name, v);
+  PyObject *repr = SWIG_Python_str_FromFormat("<Swig Object of type '%s' at %p>", (name ? name : "unknown"), (void *)v);
   if (v->next) {
-#ifdef METH_NOARGS
+# ifdef METH_NOARGS
     PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next);
-#else
+# else
     PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next, args);
-#endif
-#if PY_VERSION_HEX >= 0x03000000
+# endif
+# if PY_VERSION_HEX >= 0x03000000
     PyObject *joined = PyUnicode_Concat(repr, nrep);
     Py_DecRef(repr);
     Py_DecRef(nrep);
     repr = joined;
-#else
+# else
     PyString_ConcatAndDel(&repr,nrep);
-#endif
+# endif
   }
   return repr;  
 }
 
 SWIGRUNTIME int
-SwigPyObject_print(SwigPyObject *v, FILE *fp, int SWIGUNUSEDPARM(flags))
-{
-  char *str;
-#ifdef METH_NOARGS
-  PyObject *repr = SwigPyObject_repr(v);
-#else
-  PyObject *repr = SwigPyObject_repr(v, NULL);
-#endif
-  if (repr) {
-    str = SWIG_Python_str_AsChar(repr); 
-    fputs(str, fp);
-    SWIG_Python_str_DelForPy3(str);
-    Py_DECREF(repr);
-    return 0; 
-  } else {
-    return 1; 
-  }
-}
-
-SWIGRUNTIME PyObject *
-SwigPyObject_str(SwigPyObject *v)
-{
-  char result[SWIG_BUFFER_SIZE];
-  return SWIG_PackVoidPtr(result, v->ptr, v->ty->name, sizeof(result)) ?
-    SWIG_Python_str_FromChar(result) : 0;
-}
-
-SWIGRUNTIME int
 SwigPyObject_compare(SwigPyObject *v, SwigPyObject *w)
 {
   void *i = v->ptr;
@@ -1540,27 +1617,43 @@ SwigPyObject_richcompare(SwigPyObject *v, SwigPyObject *w, int op)
     Py_INCREF(Py_NotImplemented);
     return Py_NotImplemented;
   }
-  if( (SwigPyObject_compare(v, w)==0) == (op == Py_EQ) )
-    res = Py_True;
-  else
-    res = Py_False;
-  Py_INCREF(res);
+  res = PyBool_FromLong( (SwigPyObject_compare(v, w)==0) == (op == Py_EQ) ? 1 : 0);
   return res;  
 }
 
 
-SWIGRUNTIME PyTypeObject* _PySwigObject_type(void);
+SWIGRUNTIME PyTypeObject* SwigPyObject_TypeOnce(void);
 
+#ifdef SWIGPYTHON_BUILTIN
+static swig_type_info *SwigPyObject_stype = 0;
+SWIGRUNTIME PyTypeObject*
+SwigPyObject_type(void) {
+    SwigPyClientData *cd;
+    assert(SwigPyObject_stype);
+    cd = (SwigPyClientData*) SwigPyObject_stype->clientdata;
+    assert(cd);
+    assert(cd->pytype);
+    return cd->pytype;
+}
+#else
 SWIGRUNTIME PyTypeObject*
 SwigPyObject_type(void) {
-  static PyTypeObject *SWIG_STATIC_POINTER(type) = _PySwigObject_type();
+  static PyTypeObject *SWIG_STATIC_POINTER(type) = SwigPyObject_TypeOnce();
   return type;
 }
+#endif
 
 SWIGRUNTIMEINLINE int
 SwigPyObject_Check(PyObject *op) {
+#ifdef SWIGPYTHON_BUILTIN
+  PyTypeObject *target_tp = SwigPyObject_type();
+  if (PyType_IsSubtype(op->ob_type, target_tp))
+    return 1;
+  return (strcmp(op->ob_type->tp_name, "SwigPyObject") == 0);
+#else
   return (Py_TYPE(op) == SwigPyObject_type())
     || (strcmp(Py_TYPE(op)->tp_name,"SwigPyObject") == 0);
+#endif
 }
 
 SWIGRUNTIME PyObject *
@@ -1664,8 +1757,10 @@ SwigPyObject_own(PyObject *v, PyObject *args)
   PyObject *val = 0;
 #if (PY_VERSION_HEX < 0x02020000)
   if (!PyArg_ParseTuple(args,(char *)"|O:own",&val))
-#else
+#elif (PY_VERSION_HEX < 0x02050000)
   if (!PyArg_UnpackTuple(args, (char *)"own", 0, 1, &val)) 
+#else
+  if (!PyArg_UnpackTuple(args, "own", 0, 1, &val)) 
 #endif
     {
       return NULL;
@@ -1697,7 +1792,7 @@ SwigPyObject_own(PyObject *v, PyObject *args)
 static PyMethodDef
 swigobject_methods[] = {
   {(char *)"disown",  (PyCFunction)SwigPyObject_disown,  METH_NOARGS,  (char *)"releases ownership of the pointer"},
-  {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_NOARGS,  (char *)"aquires ownership of the pointer"},
+  {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_NOARGS,  (char *)"acquires ownership of the pointer"},
   {(char *)"own",     (PyCFunction)SwigPyObject_own,     METH_VARARGS, (char *)"returns/sets ownership of the pointer"},
   {(char *)"append",  (PyCFunction)SwigPyObject_append,  METH_O,       (char *)"appends another 'this' object"},
   {(char *)"next",    (PyCFunction)SwigPyObject_next,    METH_NOARGS,  (char *)"returns the next 'this' object"},
@@ -1726,9 +1821,9 @@ SwigPyObject_getattr(SwigPyObject *sobj,char *name)
 #endif
 
 SWIGRUNTIME PyTypeObject*
-_PySwigObject_type(void) {
+SwigPyObject_TypeOnce(void) {
   static char swigobject_doc[] = "Swig object carries a C/C++ instance pointer";
-  
+
   static PyNumberMethods SwigPyObject_as_number = {
     (binaryfunc)0, /*nb_add*/
     (binaryfunc)0, /*nb_subtract*/
@@ -1775,85 +1870,89 @@ _PySwigObject_type(void) {
 #endif
   };
 
-  static PyTypeObject swigpyobject_type;  
+  static PyTypeObject swigpyobject_type;
   static int type_init = 0;
   if (!type_init) {
-    const PyTypeObject tmp
-      = {
-	/* PyObject header changed in Python 3 */
+    const PyTypeObject tmp = {
+      /* PyObject header changed in Python 3 */
 #if PY_VERSION_HEX >= 0x03000000
-	PyVarObject_HEAD_INIT(&PyType_Type, 0)
-#else    
-	PyObject_HEAD_INIT(NULL)
-	0,				    /* ob_size */
-#endif
-	(char *)"SwigPyObject",		    /* tp_name */
-	sizeof(SwigPyObject),		    /* tp_basicsize */
-	0,			            /* tp_itemsize */
-	(destructor)SwigPyObject_dealloc,   /* tp_dealloc */
-	(printfunc)SwigPyObject_print,	    /* tp_print */
+      PyVarObject_HEAD_INIT(NULL, 0)
+#else
+      PyObject_HEAD_INIT(NULL)
+      0,                                    /* ob_size */
+#endif
+      (char *)"SwigPyObject",               /* tp_name */
+      sizeof(SwigPyObject),                 /* tp_basicsize */
+      0,                                    /* tp_itemsize */
+      (destructor)SwigPyObject_dealloc,     /* tp_dealloc */
+      0,				    /* tp_print */
 #if PY_VERSION_HEX < 0x02020000
-	(getattrfunc)SwigPyObject_getattr,  /* tp_getattr */ 
+      (getattrfunc)SwigPyObject_getattr,    /* tp_getattr */
 #else
-	(getattrfunc)0,			    /* tp_getattr */ 
+      (getattrfunc)0,                       /* tp_getattr */
 #endif
-	(setattrfunc)0,			    /* tp_setattr */ 
+      (setattrfunc)0,                       /* tp_setattr */
 #if PY_VERSION_HEX >= 0x03000000
     0, /* tp_reserved in 3.0.1, tp_compare in 3.0.0 but not used */
 #else
-	(cmpfunc)SwigPyObject_compare,	    /* tp_compare */
-#endif
-	(reprfunc)SwigPyObject_repr,	    /* tp_repr */    
-	&SwigPyObject_as_number,	    /* tp_as_number */
-	0,				    /* tp_as_sequence */
-	0,				    /* tp_as_mapping */
-	(hashfunc)0,			    /* tp_hash */
-	(ternaryfunc)0,			    /* tp_call */
-	(reprfunc)SwigPyObject_str,	    /* tp_str */
-	PyObject_GenericGetAttr,            /* tp_getattro */
-	0,				    /* tp_setattro */
-	0,		                    /* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT,	            /* tp_flags */
-	swigobject_doc, 	            /* tp_doc */        
-	0,                                  /* tp_traverse */
-	0,                                  /* tp_clear */
-	(richcmpfunc)SwigPyObject_richcompare,           /* tp_richcompare */
-	0,                                  /* tp_weaklistoffset */
+      (cmpfunc)SwigPyObject_compare,        /* tp_compare */
+#endif
+      (reprfunc)SwigPyObject_repr,          /* tp_repr */
+      &SwigPyObject_as_number,              /* tp_as_number */
+      0,                                    /* tp_as_sequence */
+      0,                                    /* tp_as_mapping */
+      (hashfunc)0,                          /* tp_hash */
+      (ternaryfunc)0,                       /* tp_call */
+      0,				    /* tp_str */
+      PyObject_GenericGetAttr,              /* tp_getattro */
+      0,                                    /* tp_setattro */
+      0,                                    /* tp_as_buffer */
+      Py_TPFLAGS_DEFAULT,                   /* tp_flags */
+      swigobject_doc,                       /* tp_doc */
+      0,                                    /* tp_traverse */
+      0,                                    /* tp_clear */
+      (richcmpfunc)SwigPyObject_richcompare,/* tp_richcompare */
+      0,                                    /* tp_weaklistoffset */
 #if PY_VERSION_HEX >= 0x02020000
-	0,                                  /* tp_iter */
-	0,                                  /* tp_iternext */
-	swigobject_methods,		    /* tp_methods */ 
-	0,			            /* tp_members */
-	0,				    /* tp_getset */	    	
-	0,			            /* tp_base */	        
-	0,				    /* tp_dict */	    	
-	0,				    /* tp_descr_get */  	
-	0,				    /* tp_descr_set */  	
-	0,				    /* tp_dictoffset */ 	
-	0,				    /* tp_init */	    	
-	0,				    /* tp_alloc */	    	
-	0,			            /* tp_new */	    	
-	0,	                            /* tp_free */	   
-	0,                                  /* tp_is_gc */  
-	0,				    /* tp_bases */   
-	0,				    /* tp_mro */
-	0,				    /* tp_cache */   
-	0,				    /* tp_subclasses */
-	0,				    /* tp_weaklist */
+      0,                                    /* tp_iter */
+      0,                                    /* tp_iternext */
+      swigobject_methods,                   /* tp_methods */
+      0,                                    /* tp_members */
+      0,                                    /* tp_getset */
+      0,                                    /* tp_base */
+      0,                                    /* tp_dict */
+      0,                                    /* tp_descr_get */
+      0,                                    /* tp_descr_set */
+      0,                                    /* tp_dictoffset */
+      0,                                    /* tp_init */
+      0,                                    /* tp_alloc */
+      0,                                    /* tp_new */
+      0,                                    /* tp_free */
+      0,                                    /* tp_is_gc */
+      0,                                    /* tp_bases */
+      0,                                    /* tp_mro */
+      0,                                    /* tp_cache */
+      0,                                    /* tp_subclasses */
+      0,                                    /* tp_weaklist */
 #endif
 #if PY_VERSION_HEX >= 0x02030000
-	0,                                  /* tp_del */
+      0,                                    /* tp_del */
+#endif
+#if PY_VERSION_HEX >= 0x02060000
+      0,                                    /* tp_version */
 #endif
 #ifdef COUNT_ALLOCS
-	0,0,0,0                             /* tp_alloc -> tp_next */
+      0,0,0,0                               /* tp_alloc -> tp_next */
 #endif
-      };
+    };
     swigpyobject_type = tmp;
-    /* for Python 3 we already assigned ob_type in PyVarObject_HEAD_INIT() */
-#if PY_VERSION_HEX < 0x03000000
+    type_init = 1;
+#if PY_VERSION_HEX < 0x02020000
     swigpyobject_type.ob_type = &PyType_Type;
+#else
+    if (PyType_Ready(&swigpyobject_type) < 0)
+      return NULL;
 #endif
-    type_init = 1;
   }
   return &swigpyobject_type;
 }
@@ -1927,17 +2026,17 @@ SwigPyPacked_compare(SwigPyPacked *v, SwigPyPacked *w)
   return s ? s : strncmp((char *)v->pack, (char *)w->pack, 2*v->size);
 }
 
-SWIGRUNTIME PyTypeObject* _PySwigPacked_type(void);
+SWIGRUNTIME PyTypeObject* SwigPyPacked_TypeOnce(void);
 
 SWIGRUNTIME PyTypeObject*
 SwigPyPacked_type(void) {
-  static PyTypeObject *SWIG_STATIC_POINTER(type) = _PySwigPacked_type();
+  static PyTypeObject *SWIG_STATIC_POINTER(type) = SwigPyPacked_TypeOnce();
   return type;
 }
 
 SWIGRUNTIMEINLINE int
 SwigPyPacked_Check(PyObject *op) {
-  return ((op)->ob_type == _PySwigPacked_type()) 
+  return ((op)->ob_type == SwigPyPacked_TypeOnce()) 
     || (strcmp((op)->ob_type->tp_name,"SwigPyPacked") == 0);
 }
 
@@ -1952,83 +2051,87 @@ SwigPyPacked_dealloc(PyObject *v)
 }
 
 SWIGRUNTIME PyTypeObject*
-_PySwigPacked_type(void) {
+SwigPyPacked_TypeOnce(void) {
   static char swigpacked_doc[] = "Swig object carries a C/C++ instance pointer";
   static PyTypeObject swigpypacked_type;
-  static int type_init = 0;  
+  static int type_init = 0;
   if (!type_init) {
-    const PyTypeObject tmp
-      = {
-    /* PyObject header changed in Python 3 */
+    const PyTypeObject tmp = {
+      /* PyObject header changed in Python 3 */
 #if PY_VERSION_HEX>=0x03000000
-    PyVarObject_HEAD_INIT(&PyType_Type, 0)
+      PyVarObject_HEAD_INIT(NULL, 0)
 #else
-	PyObject_HEAD_INIT(NULL)
-    0,				    /* ob_size */	
-#endif
-	(char *)"SwigPyPacked",		    /* tp_name */	
-	sizeof(SwigPyPacked),		    /* tp_basicsize */	
-	0,				    /* tp_itemsize */	
-	(destructor)SwigPyPacked_dealloc,   /* tp_dealloc */	
-	(printfunc)SwigPyPacked_print,	    /* tp_print */   	
-	(getattrfunc)0,			    /* tp_getattr */ 	
-	(setattrfunc)0,			    /* tp_setattr */ 	
+      PyObject_HEAD_INIT(NULL)
+      0,                                    /* ob_size */
+#endif
+      (char *)"SwigPyPacked",               /* tp_name */
+      sizeof(SwigPyPacked),                 /* tp_basicsize */
+      0,                                    /* tp_itemsize */
+      (destructor)SwigPyPacked_dealloc,     /* tp_dealloc */
+      (printfunc)SwigPyPacked_print,        /* tp_print */
+      (getattrfunc)0,                       /* tp_getattr */
+      (setattrfunc)0,                       /* tp_setattr */
 #if PY_VERSION_HEX>=0x03000000
-    0, /* tp_reserved in 3.0.1 */
+      0, /* tp_reserved in 3.0.1 */
 #else
-    (cmpfunc)SwigPyPacked_compare,	    /* tp_compare */
-#endif
-	(reprfunc)SwigPyPacked_repr,	    /* tp_repr */
-	0,	                            /* tp_as_number */
-	0,				    /* tp_as_sequence */
-	0,				    /* tp_as_mapping */
-	(hashfunc)0,			    /* tp_hash */
-	(ternaryfunc)0,			    /* tp_call */
-	(reprfunc)SwigPyPacked_str,	    /* tp_str */
-	PyObject_GenericGetAttr,            /* tp_getattro */
-	0,				    /* tp_setattro */
-	0,		                    /* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT,	            /* tp_flags */
-	swigpacked_doc, 	            /* tp_doc */
-	0,                                  /* tp_traverse */
-	0,                                  /* tp_clear */
-	0,                                  /* tp_richcompare */
-	0,                                  /* tp_weaklistoffset */
+      (cmpfunc)SwigPyPacked_compare,        /* tp_compare */
+#endif
+      (reprfunc)SwigPyPacked_repr,          /* tp_repr */
+      0,                                    /* tp_as_number */
+      0,                                    /* tp_as_sequence */
+      0,                                    /* tp_as_mapping */
+      (hashfunc)0,                          /* tp_hash */
+      (ternaryfunc)0,                       /* tp_call */
+      (reprfunc)SwigPyPacked_str,           /* tp_str */
+      PyObject_GenericGetAttr,              /* tp_getattro */
+      0,                                    /* tp_setattro */
+      0,                                    /* tp_as_buffer */
+      Py_TPFLAGS_DEFAULT,                   /* tp_flags */
+      swigpacked_doc,                       /* tp_doc */
+      0,                                    /* tp_traverse */
+      0,                                    /* tp_clear */
+      0,                                    /* tp_richcompare */
+      0,                                    /* tp_weaklistoffset */
 #if PY_VERSION_HEX >= 0x02020000
-	0,                                  /* tp_iter */
-	0,                                  /* tp_iternext */
-	0,		                    /* tp_methods */ 
-	0,			            /* tp_members */
-	0,				    /* tp_getset */	    	
-	0,			            /* tp_base */	        
-	0,				    /* tp_dict */	    	
-	0,				    /* tp_descr_get */  	
-	0,				    /* tp_descr_set */  	
-	0,				    /* tp_dictoffset */ 	
-	0,				    /* tp_init */	    	
-	0,				    /* tp_alloc */	    	
-	0,			            /* tp_new */	    	
-	0, 	                            /* tp_free */	   
-        0,                                  /* tp_is_gc */  
-	0,				    /* tp_bases */   
-	0,				    /* tp_mro */
-	0,				    /* tp_cache */   
- 	0,				    /* tp_subclasses */
-	0,				    /* tp_weaklist */
+      0,                                    /* tp_iter */
+      0,                                    /* tp_iternext */
+      0,                                    /* tp_methods */
+      0,                                    /* tp_members */
+      0,                                    /* tp_getset */
+      0,                                    /* tp_base */
+      0,                                    /* tp_dict */
+      0,                                    /* tp_descr_get */
+      0,                                    /* tp_descr_set */
+      0,                                    /* tp_dictoffset */
+      0,                                    /* tp_init */
+      0,                                    /* tp_alloc */
+      0,                                    /* tp_new */
+      0,                                    /* tp_free */
+      0,                                    /* tp_is_gc */
+      0,                                    /* tp_bases */
+      0,                                    /* tp_mro */
+      0,                                    /* tp_cache */
+      0,                                    /* tp_subclasses */
+      0,                                    /* tp_weaklist */
 #endif
 #if PY_VERSION_HEX >= 0x02030000
-	0,                                  /* tp_del */
+      0,                                    /* tp_del */
+#endif
+#if PY_VERSION_HEX >= 0x02060000
+      0,                                    /* tp_version */
 #endif
 #ifdef COUNT_ALLOCS
-	0,0,0,0                             /* tp_alloc -> tp_next */
+      0,0,0,0                               /* tp_alloc -> tp_next */
 #endif
-      };
+    };
     swigpypacked_type = tmp;
-    /* for Python 3 the ob_type already assigned in PyVarObject_HEAD_INIT() */
-#if PY_VERSION_HEX < 0x03000000
+    type_init = 1;
+#if PY_VERSION_HEX < 0x02020000
     swigpypacked_type.ob_type = &PyType_Type;
+#else
+    if (PyType_Ready(&swigpypacked_type) < 0)
+      return NULL;
 #endif
-    type_init = 1;
   }
   return &swigpypacked_type;
 }
@@ -2075,10 +2178,13 @@ _SWIG_This(void)
     return SWIG_Python_str_FromChar("this");
 }
 
+static PyObject *swig_this = NULL;
+
 SWIGRUNTIME PyObject *
 SWIG_This(void)
 {
-  static PyObject *SWIG_STATIC_POINTER(swig_this) = _SWIG_This();
+  if (swig_this == NULL)
+    swig_this = _SWIG_This();
   return swig_this;
 }
 
@@ -2092,50 +2198,65 @@ SWIG_This(void)
 SWIGRUNTIME SwigPyObject *
 SWIG_Python_GetSwigThis(PyObject *pyobj) 
 {
-  if (SwigPyObject_Check(pyobj)) {
+  PyObject *obj;
+
+  if (SwigPyObject_Check(pyobj))
     return (SwigPyObject *) pyobj;
-  } else {
-    PyObject *obj = 0;
+
+#ifdef SWIGPYTHON_BUILTIN
+  (void)obj;
+# ifdef PyWeakref_CheckProxy
+  if (PyWeakref_CheckProxy(pyobj)) {
+    pyobj = PyWeakref_GET_OBJECT(pyobj);
+    if (pyobj && SwigPyObject_Check(pyobj))
+      return (SwigPyObject*) pyobj;
+  }
+# endif
+  return NULL;
+#else
+
+  obj = 0;
+
 #if (!defined(SWIG_PYTHON_SLOW_GETSET_THIS) && (PY_VERSION_HEX >= 0x02030000))
-    if (PyInstance_Check(pyobj)) {
-      obj = _PyInstance_Lookup(pyobj, SWIG_This());      
+  if (PyInstance_Check(pyobj)) {
+    obj = _PyInstance_Lookup(pyobj, SWIG_This());      
+  } else {
+    PyObject **dictptr = _PyObject_GetDictPtr(pyobj);
+    if (dictptr != NULL) {
+      PyObject *dict = *dictptr;
+      obj = dict ? PyDict_GetItem(dict, SWIG_This()) : 0;
     } else {
-      PyObject **dictptr = _PyObject_GetDictPtr(pyobj);
-      if (dictptr != NULL) {
-	PyObject *dict = *dictptr;
-	obj = dict ? PyDict_GetItem(dict, SWIG_This()) : 0;
-      } else {
 #ifdef PyWeakref_CheckProxy
-	if (PyWeakref_CheckProxy(pyobj)) {
-	  PyObject *wobj = PyWeakref_GET_OBJECT(pyobj);
-	  return wobj ? SWIG_Python_GetSwigThis(wobj) : 0;
-	}
+      if (PyWeakref_CheckProxy(pyobj)) {
+	PyObject *wobj = PyWeakref_GET_OBJECT(pyobj);
+	return wobj ? SWIG_Python_GetSwigThis(wobj) : 0;
+      }
 #endif
-	obj = PyObject_GetAttr(pyobj,SWIG_This());
-	if (obj) {
-	  Py_DECREF(obj);
-	} else {
-	  if (PyErr_Occurred()) PyErr_Clear();
-	  return 0;
-	}
+      obj = PyObject_GetAttr(pyobj,SWIG_This());
+      if (obj) {
+	Py_DECREF(obj);
+      } else {
+	if (PyErr_Occurred()) PyErr_Clear();
+	return 0;
       }
     }
+  }
 #else
-    obj = PyObject_GetAttr(pyobj,SWIG_This());
-    if (obj) {
-      Py_DECREF(obj);
-    } else {
-      if (PyErr_Occurred()) PyErr_Clear();
-      return 0;
-    }
+  obj = PyObject_GetAttr(pyobj,SWIG_This());
+  if (obj) {
+    Py_DECREF(obj);
+  } else {
+    if (PyErr_Occurred()) PyErr_Clear();
+    return 0;
+  }
 #endif
-    if (obj && !SwigPyObject_Check(obj)) {
-      /* a PyObject is called 'this', try to get the 'real this'
-	 SwigPyObject from it */ 
-      return SWIG_Python_GetSwigThis(obj);
-    }
-    return (SwigPyObject *)obj;
+  if (obj && !SwigPyObject_Check(obj)) {
+    /* a PyObject is called 'this', try to get the 'real this'
+       SwigPyObject from it */ 
+    return SWIG_Python_GetSwigThis(obj);
   }
+  return (SwigPyObject *)obj;
+#endif
 }
 
 /* Acquire a pointer value */
@@ -2157,91 +2278,105 @@ SWIG_Python_AcquirePtr(PyObject *obj, int own) {
 
 SWIGRUNTIME int
 SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int flags, int *own) {
-  if (!obj) return SWIG_ERROR;
-  if (obj == Py_None) {
-    if (ptr) *ptr = 0;
+  int res;
+  SwigPyObject *sobj;
+  int implicit_conv = (flags & SWIG_POINTER_IMPLICIT_CONV) != 0;
+
+  if (!obj)
+    return SWIG_ERROR;
+  if (obj == Py_None && !implicit_conv) {
+    if (ptr)
+      *ptr = 0;
     return SWIG_OK;
-  } else {
-    SwigPyObject *sobj = SWIG_Python_GetSwigThis(obj);
+  }
+
+  res = SWIG_ERROR;
+
+  sobj = SWIG_Python_GetSwigThis(obj);
+  if (own)
+    *own = 0;
+  while (sobj) {
+    void *vptr = sobj->ptr;
+    if (ty) {
+      swig_type_info *to = sobj->ty;
+      if (to == ty) {
+        /* no type cast needed */
+        if (ptr) *ptr = vptr;
+        break;
+      } else {
+        swig_cast_info *tc = SWIG_TypeCheck(to->name,ty);
+        if (!tc) {
+          sobj = (SwigPyObject *)sobj->next;
+        } else {
+          if (ptr) {
+            int newmemory = 0;
+            *ptr = SWIG_TypeCast(tc,vptr,&newmemory);
+            if (newmemory == SWIG_CAST_NEW_MEMORY) {
+              assert(own); /* badly formed typemap which will lead to a memory leak - it must set and use own to delete *ptr */
+              if (own)
+                *own = *own | SWIG_CAST_NEW_MEMORY;
+            }
+          }
+          break;
+        }
+      }
+    } else {
+      if (ptr) *ptr = vptr;
+      break;
+    }
+  }
+  if (sobj) {
     if (own)
-      *own = 0;
-    while (sobj) {
-      void *vptr = sobj->ptr;
-      if (ty) {
-	swig_type_info *to = sobj->ty;
-	if (to == ty) {
-	  /* no type cast needed */
-	  if (ptr) *ptr = vptr;
-	  break;
-	} else {
-	  swig_cast_info *tc = SWIG_TypeCheck(to->name,ty);
-	  if (!tc) {
-	    sobj = (SwigPyObject *)sobj->next;
-	  } else {
-	    if (ptr) {
-              int newmemory = 0;
-              *ptr = SWIG_TypeCast(tc,vptr,&newmemory);
-              if (newmemory == SWIG_CAST_NEW_MEMORY) {
-                assert(own);
-                if (own)
-                  *own = *own | SWIG_CAST_NEW_MEMORY;
+      *own = *own | sobj->own;
+    if (flags & SWIG_POINTER_DISOWN) {
+      sobj->own = 0;
+    }
+    res = SWIG_OK;
+  } else {
+    if (implicit_conv) {
+      SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0;
+      if (data && !data->implicitconv) {
+        PyObject *klass = data->klass;
+        if (klass) {
+          PyObject *impconv;
+          data->implicitconv = 1; /* avoid recursion and call 'explicit' constructors*/
+          impconv = SWIG_Python_CallFunctor(klass, obj);
+          data->implicitconv = 0;
+          if (PyErr_Occurred()) {
+            PyErr_Clear();
+            impconv = 0;
+          }
+          if (impconv) {
+            SwigPyObject *iobj = SWIG_Python_GetSwigThis(impconv);
+            if (iobj) {
+              void *vptr;
+              res = SWIG_Python_ConvertPtrAndOwn((PyObject*)iobj, &vptr, ty, 0, 0);
+              if (SWIG_IsOK(res)) {
+                if (ptr) {
+                  *ptr = vptr;
+                  /* transfer the ownership to 'ptr' */
+                  iobj->own = 0;
+                  res = SWIG_AddCast(res);
+                  res = SWIG_AddNewMask(res);
+                } else {
+                  res = SWIG_AddCast(res);		    
+                }
               }
             }
-	    break;
-	  }
-	}
-      } else {
-	if (ptr) *ptr = vptr;
-	break;
+            Py_DECREF(impconv);
+          }
+        }
       }
     }
-    if (sobj) {
-      if (own)
-        *own = *own | sobj->own;
-      if (flags & SWIG_POINTER_DISOWN) {
-	sobj->own = 0;
-      }
-      return SWIG_OK;
-    } else {
-      int res = SWIG_ERROR;
-      if (flags & SWIG_POINTER_IMPLICIT_CONV) {
-	SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0;
-	if (data && !data->implicitconv) {
-	  PyObject *klass = data->klass;
-	  if (klass) {
-	    PyObject *impconv;
-	    data->implicitconv = 1; /* avoid recursion and call 'explicit' constructors*/
-	    impconv = SWIG_Python_CallFunctor(klass, obj);
-	    data->implicitconv = 0;
-	    if (PyErr_Occurred()) {
-	      PyErr_Clear();
-	      impconv = 0;
-	    }
-	    if (impconv) {
-	      SwigPyObject *iobj = SWIG_Python_GetSwigThis(impconv);
-	      if (iobj) {
-		void *vptr;
-		res = SWIG_Python_ConvertPtrAndOwn((PyObject*)iobj, &vptr, ty, 0, 0);
-		if (SWIG_IsOK(res)) {
-		  if (ptr) {
-		    *ptr = vptr;
-		    /* transfer the ownership to 'ptr' */
-		    iobj->own = 0;
-		    res = SWIG_AddCast(res);
-		    res = SWIG_AddNewMask(res);
-		  } else {
-		    res = SWIG_AddCast(res);		    
-		  }
-		}
-	      }
-	      Py_DECREF(impconv);
-	    }
-	  }
-	}
-      }
-      return res;
+    if (!SWIG_IsOK(res) && obj == Py_None) {
+      if (ptr)
+        *ptr = 0;
+      if (PyErr_Occurred())
+        PyErr_Clear();
+      res = SWIG_OK;
     }
   }
+  return res;
 }
 
 /* Convert a function ptr value */
@@ -2328,23 +2463,29 @@ SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this)
   } else {
 #if PY_VERSION_HEX >= 0x03000000
     inst = PyBaseObject_Type.tp_new((PyTypeObject*) data->newargs, Py_None, Py_None);
-    PyObject_SetAttr(inst, SWIG_This(), swig_this);
-    Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
+    if (inst) {
+      PyObject_SetAttr(inst, SWIG_This(), swig_this);
+      Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
+    }
 #else
     PyObject *dict = PyDict_New();
-    PyDict_SetItem(dict, SWIG_This(), swig_this);
-    inst = PyInstance_NewRaw(data->newargs, dict);
-    Py_DECREF(dict);
+    if (dict) {
+      PyDict_SetItem(dict, SWIG_This(), swig_this);
+      inst = PyInstance_NewRaw(data->newargs, dict);
+      Py_DECREF(dict);
+    }
 #endif
   }
   return inst;
 #else
 #if (PY_VERSION_HEX >= 0x02010000)
-  PyObject *inst;
+  PyObject *inst = 0;
   PyObject *dict = PyDict_New();
-  PyDict_SetItem(dict, SWIG_This(), swig_this);
-  inst = PyInstance_NewRaw(data->newargs, dict);
-  Py_DECREF(dict);
+  if (dict) {
+    PyDict_SetItem(dict, SWIG_This(), swig_this);
+    inst = PyInstance_NewRaw(data->newargs, dict);
+    Py_DECREF(dict);
+  }
   return (PyObject *) inst;
 #else
   PyInstanceObject *inst = PyObject_NEW(PyInstanceObject, &PyInstance_Type);
@@ -2395,7 +2536,7 @@ SWIG_Python_SetSwigThis(PyObject *inst, PyObject *swig_this)
 SWIGINTERN PyObject *
 SWIG_Python_InitShadowInstance(PyObject *args) {
   PyObject *obj[2];
-  if (!SWIG_Python_UnpackTuple(args,(char*)"swiginit", 2, 2, obj)) {
+  if (!SWIG_Python_UnpackTuple(args, "swiginit", 2, 2, obj)) {
     return NULL;
   } else {
     SwigPyObject *sthis = SWIG_Python_GetSwigThis(obj[0]);
@@ -2411,22 +2552,52 @@ SWIG_Python_InitShadowInstance(PyObject *args) {
 /* Create a new pointer object */
 
 SWIGRUNTIME PyObject *
-SWIG_Python_NewPointerObj(void *ptr, swig_type_info *type, int flags) {
-  if (!ptr) {
+SWIG_Python_NewPointerObj(PyObject *self, void *ptr, swig_type_info *type, int flags) {
+  SwigPyClientData *clientdata;
+  PyObject * robj;
+  int own;
+
+  if (!ptr)
     return SWIG_Py_Void();
-  } else {
-    int own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0;
-    PyObject *robj = SwigPyObject_New(ptr, type, own);
-    SwigPyClientData *clientdata = type ? (SwigPyClientData *)(type->clientdata) : 0;
-    if (clientdata && !(flags & SWIG_POINTER_NOSHADOW)) {
-      PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj);
-      if (inst) {
-	Py_DECREF(robj);
-	robj = inst;
+
+  clientdata = type ? (SwigPyClientData *)(type->clientdata) : 0;
+  own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0;
+  if (clientdata && clientdata->pytype) {
+    SwigPyObject *newobj;
+    if (flags & SWIG_BUILTIN_TP_INIT) {
+      newobj = (SwigPyObject*) self;
+      if (newobj->ptr) {
+        PyObject *next_self = clientdata->pytype->tp_alloc(clientdata->pytype, 0);
+        while (newobj->next)
+	  newobj = (SwigPyObject *) newobj->next;
+        newobj->next = next_self;
+        newobj = (SwigPyObject *)next_self;
       }
+    } else {
+      newobj = PyObject_New(SwigPyObject, clientdata->pytype);
+    }
+    if (newobj) {
+      newobj->ptr = ptr;
+      newobj->ty = type;
+      newobj->own = own;
+      newobj->next = 0;
+#ifdef SWIGPYTHON_BUILTIN
+      newobj->dict = 0;
+#endif
+      return (PyObject*) newobj;
     }
-    return robj;
+    return SWIG_Py_Void();
+  }
+
+  assert(!(flags & SWIG_BUILTIN_TP_INIT));
+
+  robj = SwigPyObject_New(ptr, type, own);
+  if (robj && clientdata && !(flags & SWIG_POINTER_NOSHADOW)) {
+    PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj);
+    Py_DECREF(robj);
+    robj = inst;
   }
+  return robj;
 }
 
 /* Create a new packed object */
@@ -2445,19 +2616,19 @@ void *SWIG_ReturnGlobalTypeList(void *);
 #endif
 
 SWIGRUNTIME swig_module_info *
-SWIG_Python_GetModule(void) {
+SWIG_Python_GetModule(void *SWIGUNUSEDPARM(clientdata)) {
   static void *type_pointer = (void *)0;
   /* first check if module already created */
   if (!type_pointer) {
 #ifdef SWIG_LINK_RUNTIME
     type_pointer = SWIG_ReturnGlobalTypeList((void *)0);
 #else
-#ifdef SWIG_PYTHON_USE_CAPSULE
-    type_pointer = PyCapsule_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer" SWIG_TYPE_TABLE_NAME, 0);
-#else
+# ifdef SWIGPY_USE_CAPSULE
+    type_pointer = PyCapsule_Import(SWIGPY_CAPSULE_NAME, 0);
+# else
     type_pointer = PyCObject_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
 				    (char*)"type_pointer" SWIG_TYPE_TABLE_NAME);
-#endif
+# endif
     if (PyErr_Occurred()) {
       PyErr_Clear();
       type_pointer = (void *)0;
@@ -2500,26 +2671,19 @@ PyModule_AddObject(PyObject *m, char *name, PyObject *o)
 #endif
 
 SWIGRUNTIME void
-#ifdef SWIG_PYTHON_USE_CAPSULE
-SWIG_Python_DestroyModule(PyObject *capsule)
-{
-  swig_module_info *swig_module;
-  swig_type_info **types;
-  size_t i;
-  swig_module = (swig_module_info *)PyCapsule_GetPointer(capsule, (char*)"swig_runtime_data" SWIG_RUNTIME_VERSION);
-  if (swig_module == NULL)
-  {
-    PyErr_Clear();
-    return;
-  }
-  types = swig_module->types;
+#ifdef SWIGPY_USE_CAPSULE
+SWIG_Python_DestroyModule(PyObject *obj)
 #else
 SWIG_Python_DestroyModule(void *vptr)
+#endif
 {
+#ifdef SWIGPY_USE_CAPSULE
+  swig_module_info *swig_module = (swig_module_info *) PyCapsule_GetPointer(obj, SWIGPY_CAPSULE_NAME);
+#else
   swig_module_info *swig_module = (swig_module_info *) vptr;
+#endif
   swig_type_info **types = swig_module->types;
   size_t i;
-#endif
   for (i =0; i < swig_module->size; ++i) {
     swig_type_info *ty = types[i];
     if (ty->owndata) {
@@ -2528,31 +2692,33 @@ SWIG_Python_DestroyModule(void *vptr)
     }
   }
   Py_DECREF(SWIG_This());
+  swig_this = NULL;
 }
 
 SWIGRUNTIME void
 SWIG_Python_SetModule(swig_module_info *swig_module) {
-  static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} };/* Sentinel */
-
 #if PY_VERSION_HEX >= 0x03000000
  /* Add a dummy module object into sys.modules */
   PyObject *module = PyImport_AddModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION);
 #else
-  PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
-				   swig_empty_runtime_method_table);
+  static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} }; /* Sentinel */
+  PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION, swig_empty_runtime_method_table);
 #endif
-#ifdef SWIG_PYTHON_USE_CAPSULE
-  PyObject *pointer = PyCapsule_New((void *) swig_module,
-                                    (char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer" SWIG_TYPE_TABLE_NAME,
-                                    SWIG_Python_DestroyModule);
+#ifdef SWIGPY_USE_CAPSULE
+  PyObject *pointer = PyCapsule_New((void *) swig_module, SWIGPY_CAPSULE_NAME, SWIG_Python_DestroyModule);
+  if (pointer && module) {
+    PyModule_AddObject(module, (char*)"type_pointer_capsule" SWIG_TYPE_TABLE_NAME, pointer);
+  } else {
+    Py_XDECREF(pointer);
+  }
 #else
   PyObject *pointer = PyCObject_FromVoidPtr((void *) swig_module, SWIG_Python_DestroyModule);
-#endif
   if (pointer && module) {
     PyModule_AddObject(module, (char*)"type_pointer" SWIG_TYPE_TABLE_NAME, pointer);
   } else {
     Py_XDECREF(pointer);
   }
+#endif
 }
 
 /* The python cached type query */
@@ -2570,17 +2736,17 @@ SWIG_Python_TypeQuery(const char *type)
   PyObject *obj = PyDict_GetItem(cache, key);
   swig_type_info *descriptor;
   if (obj) {
-#ifdef SWIG_PYTHON_USE_CAPSULE
-    descriptor = (swig_type_info *) PyCapsule_GetPointer(obj, (char*)"swig_type_info");
+#ifdef SWIGPY_USE_CAPSULE
+    descriptor = (swig_type_info *) PyCapsule_GetPointer(obj, NULL);
 #else
     descriptor = (swig_type_info *) PyCObject_AsVoidPtr(obj);
 #endif
   } else {
-    swig_module_info *swig_module = SWIG_Python_GetModule();
+    swig_module_info *swig_module = SWIG_GetModule(0);
     descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type);
     if (descriptor) {
-#ifdef SWIG_PYTHON_USE_CAPSULE
-      obj = PyCapsule_New(descriptor, (char*)"swig_type_info", NULL);
+#ifdef SWIGPY_USE_CAPSULE
+      obj = PyCapsule_New((void*) descriptor, NULL, NULL);
 #else
       obj = PyCObject_FromVoidPtr(descriptor, NULL);
 #endif
@@ -2644,7 +2810,7 @@ SwigPyObject_GetDesc(PyObject *self)
 {
   SwigPyObject *v = (SwigPyObject *)self;
   swig_type_info *ty = v ? v->ty : 0;
-  return ty ? ty->str : (char*)"";
+  return ty ? ty->str : "";
 }
 
 SWIGRUNTIME void
@@ -2687,7 +2853,7 @@ SWIG_Python_TypeError(const char *type, PyObject *obj)
 
 /* Convert a pointer value, signal an exception on a type mismatch */
 SWIGRUNTIME void *
-SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int argnum, int flags) {
+SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int SWIGUNUSEDPARM(argnum), int flags) {
   void *result;
   if (SWIG_Python_ConvertPtr(obj, &result, ty, flags) == -1) {
     PyErr_Clear();
@@ -2701,11 +2867,61 @@ SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int argnum, int flags)
   return result;
 }
 
+#ifdef SWIGPYTHON_BUILTIN
+SWIGRUNTIME int
+SWIG_Python_NonDynamicSetAttr(PyObject *obj, PyObject *name, PyObject *value) {
+  PyTypeObject *tp = obj->ob_type;
+  PyObject *descr;
+  PyObject *encoded_name;
+  descrsetfunc f;
+  int res = -1;
+
+# ifdef Py_USING_UNICODE
+  if (PyString_Check(name)) {
+    name = PyUnicode_Decode(PyString_AsString(name), PyString_Size(name), NULL, NULL);
+    if (!name)
+      return -1;
+  } else if (!PyUnicode_Check(name))
+# else
+  if (!PyString_Check(name))
+# endif
+  {
+    PyErr_Format(PyExc_TypeError, "attribute name must be string, not '%.200s'", name->ob_type->tp_name);
+    return -1;
+  } else {
+    Py_INCREF(name);
+  }
 
-#ifdef __cplusplus
-#if 0
-{ /* cc-mode */
+  if (!tp->tp_dict) {
+    if (PyType_Ready(tp) < 0)
+      goto done;
+  }
+
+  descr = _PyType_Lookup(tp, name);
+  f = NULL;
+  if (descr != NULL)
+    f = descr->ob_type->tp_descr_set;
+  if (!f) {
+    if (PyString_Check(name)) {
+      encoded_name = name;
+      Py_INCREF(name);
+    } else {
+      encoded_name = PyUnicode_AsUTF8String(name);
+    }
+    PyErr_Format(PyExc_AttributeError, "'%.100s' object has no attribute '%.200s'", tp->tp_name, PyString_AsString(encoded_name));
+    Py_DECREF(encoded_name);
+  } else {
+    res = f(descr, obj, value);
+  }
+  
+  done:
+  Py_DECREF(name);
+  return res;
+}
 #endif
+
+
+#ifdef __cplusplus
 }
 #endif
 
@@ -2755,7 +2971,7 @@ static swig_module_info swig_module = {swig_types, 8, 0, 0, 0, 0};
 #endif
 #define SWIG_name    "_osr"
 
-#define SWIGVERSION 0x010340 
+#define SWIGVERSION 0x020012 
 #define SWIG_VERSION SWIGVERSION
 
 
@@ -2848,7 +3064,7 @@ SWIG_FromCharPtrAndSize(const char* carray, size_t size)
     if (size > INT_MAX) {
       swig_type_info* pchar_descriptor = SWIG_pchar_descriptor();
       return pchar_descriptor ? 
-	SWIG_NewPointerObj(const_cast< char * >(carray), pchar_descriptor, 0) : SWIG_Py_Void();
+	SWIG_InternalNewPointerObj(const_cast< char * >(carray), pchar_descriptor, 0) : SWIG_Py_Void();
     } else {
 #if PY_VERSION_HEX >= 0x03000000
       return PyUnicode_FromStringAndSize(carray, static_cast< int >(size));
@@ -2893,16 +3109,16 @@ typedef void OSRCoordinateTransformationShadow;
 #endif
 
 
-int bUseExceptions=0;
-CPLErrorHandler pfnPreviousHandler = CPLDefaultErrorHandler;
+static int bUseExceptions=0;
+static CPLErrorHandler pfnPreviousHandler = CPLDefaultErrorHandler;
 
-void CPL_STDCALL 
-PythonBindingErrorHandler(CPLErr eclass, int code, const char *msg ) 
+static void CPL_STDCALL
+PythonBindingErrorHandler(CPLErr eclass, int code, const char *msg )
 {
-  /* 
+  /*
   ** Generally we want to suppress error reporting if we have exceptions
-  ** enabled as the error message will be in the exception thrown in 
-  ** Python.  
+  ** enabled as the error message will be in the exception thrown in
+  ** Python.
   */
 
   /* If the error class is CE_Fatal, we want to have a message issued
@@ -2923,20 +3139,26 @@ PythonBindingErrorHandler(CPLErr eclass, int code, const char *msg )
 
 
 
+static
 int GetUseExceptions() {
+  CPLErrorReset();
   return bUseExceptions;
 }
 
+static
 void UseExceptions() {
+  CPLErrorReset();
   if( !bUseExceptions )
   {
     bUseExceptions = 1;
-    pfnPreviousHandler = 
+    pfnPreviousHandler =
         CPLSetErrorHandler( (CPLErrorHandler) PythonBindingErrorHandler );
   }
 }
 
+static
 void DontUseExceptions() {
+  CPLErrorReset();
   if( bUseExceptions )
   {
     bUseExceptions = 0;
@@ -2945,17 +3167,32 @@ void DontUseExceptions() {
 }
 
 
-  #define SWIG_From_long   PyInt_FromLong 
+SWIGINTERNINLINE PyObject*
+  SWIG_From_int  (int value)
+{
+  return PyInt_FromLong((long) value);
+}
 
 
-SWIGINTERNINLINE PyObject *
-SWIG_From_int  (int value)
-{    
-  return SWIG_From_long  (value);
+/* Completely unrelated: just to avoid Coverity warnings */
+
+static int bReturnSame = 1;
+
+void NeverCallMePlease() {
+    bReturnSame = 0;
+}
+
+/* Some SWIG code generates dead code, which Coverity warns about */
+template<class T> static T ReturnSame(T x)
+{
+    if( bReturnSame )
+        return x;
+    return 0;
 }
 
 
 
+
 /* Return a PyObject* from a NULL terminated C String */
 static PyObject* GDALPythonObjectFromCStr(const char *pszStr)
 {
@@ -2976,7 +3213,7 @@ static PyObject* GDALPythonObjectFromCStr(const char *pszStr)
     pszIter ++;
   }
 #if PY_VERSION_HEX >= 0x03000000
-  return PyUnicode_FromString(pszStr); 
+  return PyUnicode_FromString(pszStr);
 #else
   return PyString_FromString(pszStr);
 #endif
@@ -3004,7 +3241,7 @@ static char* GDALPythonObjectToCStr(PyObject* pyObject, int* pbToFree)
       *pbToFree = 1;
       return pszNewStr;
   }
-  else 
+  else
   {
 #if PY_VERSION_HEX >= 0x03000000
       return PyBytes_AsString(pyObject);
@@ -3028,7 +3265,7 @@ py_OPTGetProjectionMethods(PyObject *self, PyObject *args) {
     PyObject *py_MList;
     char     **papszMethods;
     int      iMethod;
-    
+
     self = self;
     args = args;
 
@@ -3042,10 +3279,13 @@ py_OPTGetProjectionMethods(PyObject *self, PyObject *args) {
 	PyObject *py_PList;
 	int       iParam;
 
-	papszParameters = OPTGetParameterList( papszMethods[iMethod], 
+	papszParameters = OPTGetParameterList( papszMethods[iMethod],
 					       &pszUserMethodName );
         if( papszParameters == NULL )
+        {
+            CSLDestroy( papszMethods );
             return NULL;
+        }
 
 	py_PList = PyList_New(CSLCount(papszParameters));
 	for( iParam = 0; papszParameters[iParam] != NULL; iParam++ )
@@ -3054,25 +3294,25 @@ py_OPTGetProjectionMethods(PyObject *self, PyObject *args) {
 	    char    *pszUserParamName;
             double  dfDefault;
 
-	    OPTGetParameterInfo( papszMethods[iMethod], 
-				 papszParameters[iParam], 
-				 &pszUserParamName, 
+	    OPTGetParameterInfo( papszMethods[iMethod],
+				 papszParameters[iParam],
+				 &pszUserParamName,
 				 &pszType, &dfDefault );
-	    PyList_SetItem(py_PList, iParam, 
-			   Py_BuildValue("(sssd)", 
-					 papszParameters[iParam], 
-					 pszUserParamName, 
+	    PyList_SetItem(py_PList, iParam,
+			   Py_BuildValue("(sssd)",
+					 papszParameters[iParam],
+					 pszUserParamName,
                                          pszType, dfDefault ));
 	}
-	
+
 	CSLDestroy( papszParameters );
 
-	PyList_SetItem(py_MList, iMethod, 
-		       Py_BuildValue("(ssO)", 
-		                     papszMethods[iMethod], 
-				     pszUserMethodName, 
+	PyList_SetItem(py_MList, iMethod,
+		       Py_BuildValue("(ssO)",
+		                     papszMethods[iMethod],
+				     pszUserMethodName,
 		                     py_PList));
-        
+
         Py_XDECREF( py_PList );
     }
 
@@ -3086,7 +3326,7 @@ OGRErr GetWellKnownGeogCSAsWKT( const char *name, char **argout ) {
   OGRSpatialReferenceH srs = OSRNewSpatialReference("");
   OGRErr rcode = OSRSetWellKnownGeogCS( srs, name );
   if( rcode == OGRERR_NONE )
-      rcode = OSRExportToWkt ( srs, argout );  
+      rcode = OSRExportToWkt ( srs, argout );
   OSRDestroySpatialReference( srs );
   return rcode;
 }
@@ -3209,7 +3449,7 @@ OGRErr GetUserInputAsWKT( const char *name, char **argout ) {
   OGRSpatialReferenceH srs = OSRNewSpatialReference("");
   OGRErr rcode = OSRSetFromUserInput( srs, name );
   if( rcode == OGRERR_NONE )
-      rcode = OSRExportToWkt ( srs, argout );  
+      rcode = OSRExportToWkt ( srs, argout );
   OSRDestroySpatialReference( srs );
   return rcode;
 }
@@ -3412,7 +3652,7 @@ SWIGINTERN char const *OSRSpatialReferenceShadow_GetAttrValue(OSRSpatialReferenc
     return OSRGetAttrValue( self, name, child );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetAttrValue(OSRSpatialReferenceShadow *self,char const *name,char const *value){
-    return OSRSetAttrValue( self, name, value ); 
+    return OSRSetAttrValue( self, name, value );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetAngularUnits(OSRSpatialReferenceShadow *self,char const *name,double to_radians){
     return OSRSetAngularUnits( self, name, to_radians );
@@ -3443,7 +3683,7 @@ SWIGINTERN char const *OSRSpatialReferenceShadow_GetLinearUnitsName(OSRSpatialRe
       name = OSRGetAttrValue( self, "LOCAL_CS|UNIT", 0 );
     }
 
-    if (name != 0) 
+    if (name != 0)
       return name;
 
     return "Meter";
@@ -3458,8 +3698,8 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetUTM(OSRSpatialReferenceShadow *se
     return OSRSetUTM( self, zone, north );
   }
 SWIGINTERN int OSRSpatialReferenceShadow_GetUTMZone(OSRSpatialReferenceShadow *self){
-    // Note: we will return south zones as negative since it is 
-    // hard to return two values as the C API does. 
+    // Note: we will return south zones as negative since it is
+    // hard to return two values as the C API does.
     int bNorth = FALSE;
     int nZone = OSRGetUTMZone( self, &bNorth );
     if( !bNorth )
@@ -3476,7 +3716,7 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetProjection(OSRSpatialReferenceSha
     return OSRSetProjection( self, arg );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetProjParm(OSRSpatialReferenceShadow *self,char const *name,double val){
-    return OSRSetProjParm( self, name, val ); 
+    return OSRSetProjParm( self, name, val );
   }
 SWIGINTERN double OSRSpatialReferenceShadow_GetProjParm(OSRSpatialReferenceShadow *self,char const *name,double default_val=0.0){
     // Return code ignored.
@@ -3502,26 +3742,26 @@ SWIGINTERN double OSRSpatialReferenceShadow_GetInvFlattening(OSRSpatialReference
     return OSRGetInvFlattening( self, 0 );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetACEA(OSRSpatialReferenceShadow *self,double stdp1,double stdp2,double clat,double clong,double fe,double fn){
-    return OSRSetACEA( self, stdp1, stdp2, clat, clong, 
+    return OSRSetACEA( self, stdp1, stdp2, clat, clong,
                        fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetAE(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetAE( self, clat, clong, 
+    return OSRSetAE( self, clat, clong,
                      fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetBonne(OSRSpatialReferenceShadow *self,double stdp,double cm,double fe,double fn){
     return OSRSetBonne( self, stdp, cm, fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetCEA(OSRSpatialReferenceShadow *self,double stdp1,double cm,double fe,double fn){
-    return OSRSetCEA( self, stdp1, cm, 
+    return OSRSetCEA( self, stdp1, cm,
                       fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetCS(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetCS( self, clat, clong, 
+    return OSRSetCS( self, clat, clong,
                      fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetEC(OSRSpatialReferenceShadow *self,double stdp1,double stdp2,double clat,double clong,double fe,double fn){
-    return OSRSetEC( self, stdp1, stdp2, clat, clong, 
+    return OSRSetEC( self, stdp1, stdp2, clat, clong,
                      fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetEckertIV(OSRSpatialReferenceShadow *self,double cm,double fe,double fn){
@@ -3531,7 +3771,7 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetEckertVI(OSRSpatialReferenceShado
     return OSRSetEckertVI( self, cm, fe, fn);
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetEquirectangular(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetEquirectangular( self, clat, clong, 
+    return OSRSetEquirectangular( self, clat, clong,
                                   fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetEquirectangular2(OSRSpatialReferenceShadow *self,double clat,double clong,double pseudostdparallellat,double fe,double fn){
@@ -3556,7 +3796,7 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGEOS(OSRSpatialReferenceShadow *s
                        fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGnomonic(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetGnomonic( self, clat, clong, 
+    return OSRSetGnomonic( self, clat, clong,
                            fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetHOM(OSRSpatialReferenceShadow *self,double clat,double clong,double azimuth,double recttoskew,double scale,double fe,double fn){
@@ -3564,56 +3804,56 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetHOM(OSRSpatialReferenceShadow *se
                       scale, fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetHOM2PNO(OSRSpatialReferenceShadow *self,double clat,double dfLat1,double dfLong1,double dfLat2,double dfLong2,double scale,double fe,double fn){
-    return OSRSetHOM2PNO( self, clat, dfLat1, dfLong1, dfLat2, dfLong2, 
+    return OSRSetHOM2PNO( self, clat, dfLat1, dfLong1, dfLat2, dfLong2,
                           scale, fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetKrovak(OSRSpatialReferenceShadow *self,double clat,double clong,double azimuth,double pseudostdparallellat,double scale,double fe,double fn){
-    return OSRSetKrovak( self, clat, clong, 
-                         azimuth, pseudostdparallellat, 
+    return OSRSetKrovak( self, clat, clong,
+                         azimuth, pseudostdparallellat,
                          scale, fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLAEA(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetLAEA( self, clat, clong, 
+    return OSRSetLAEA( self, clat, clong,
                        fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLCC(OSRSpatialReferenceShadow *self,double stdp1,double stdp2,double clat,double clong,double fe,double fn){
-    return OSRSetLCC( self, stdp1, stdp2, clat, clong, 
+    return OSRSetLCC( self, stdp1, stdp2, clat, clong,
                       fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLCC1SP(OSRSpatialReferenceShadow *self,double clat,double clong,double scale,double fe,double fn){
-    return OSRSetLCC1SP( self, clat, clong, scale, 
+    return OSRSetLCC1SP( self, clat, clong, scale,
                          fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLCCB(OSRSpatialReferenceShadow *self,double stdp1,double stdp2,double clat,double clong,double fe,double fn){
-    return OSRSetLCCB( self, stdp1, stdp2, clat, clong, 
+    return OSRSetLCCB( self, stdp1, stdp2, clat, clong,
                        fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetMC(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetMC( self, clat, clong,    
+    return OSRSetMC( self, clat, clong,
                      fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetMercator(OSRSpatialReferenceShadow *self,double clat,double clong,double scale,double fe,double fn){
-    return OSRSetMercator( self, clat, clong, 
+    return OSRSetMercator( self, clat, clong,
                            scale, fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetMollweide(OSRSpatialReferenceShadow *self,double cm,double fe,double fn){
-    return OSRSetMollweide( self, cm, 
+    return OSRSetMollweide( self, cm,
                             fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetNZMG(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetNZMG( self, clat, clong, 
+    return OSRSetNZMG( self, clat, clong,
                        fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetOS(OSRSpatialReferenceShadow *self,double dfOriginLat,double dfCMeridian,double scale,double fe,double fn){
-    return OSRSetOS( self, dfOriginLat, dfCMeridian, scale, 
+    return OSRSetOS( self, dfOriginLat, dfCMeridian, scale,
                      fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetOrthographic(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetOrthographic( self, clat, clong, 
+    return OSRSetOrthographic( self, clat, clong,
                                fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetPolyconic(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetPolyconic( self, clat, clong, 
+    return OSRSetPolyconic( self, clat, clong,
                             fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetPS(OSRSpatialReferenceShadow *self,double clat,double clong,double scale,double fe,double fn){
@@ -3627,7 +3867,7 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetSinusoidal(OSRSpatialReferenceSha
     return OSRSetSinusoidal( self, clong, fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetStereographic(OSRSpatialReferenceShadow *self,double clat,double clong,double scale,double fe,double fn){
-    return OSRSetStereographic( self, clat, clong, scale, 
+    return OSRSetStereographic( self, clat, clong, scale,
                                 fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetSOC(OSRSpatialReferenceShadow *self,double latitudeoforigin,double cm,double fe,double fn){
@@ -3635,19 +3875,19 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetSOC(OSRSpatialReferenceShadow *se
 	              fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetTM(OSRSpatialReferenceShadow *self,double clat,double clong,double scale,double fe,double fn){
-    return OSRSetTM( self, clat, clong, scale, 
+    return OSRSetTM( self, clat, clong, scale,
                      fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetTMVariant(OSRSpatialReferenceShadow *self,char const *pszVariantName,double clat,double clong,double scale,double fe,double fn){
-    return OSRSetTMVariant( self, pszVariantName, clat, clong,  
+    return OSRSetTMVariant( self, pszVariantName, clat, clong,
                             scale, fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetTMG(OSRSpatialReferenceShadow *self,double clat,double clong,double fe,double fn){
-    return OSRSetTMG( self, clat, clong, 
+    return OSRSetTMG( self, clat, clong,
                       fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetTMSO(OSRSpatialReferenceShadow *self,double clat,double clong,double scale,double fe,double fn){
-    return OSRSetTMSO( self, clat, clong, scale, 
+    return OSRSetTMSO( self, clat, clong, scale,
                        fe, fn );
   }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetVDG(OSRSpatialReferenceShadow *self,double clong,double fe,double fn){
@@ -3749,6 +3989,9 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_ExportToProj4(OSRSpatialReferenceSha
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_ExportToPCI(OSRSpatialReferenceShadow *self,char **proj,char **units,double *parms[17]){
     return OSRExportToPCI( self, proj, units, parms );
   }
+
+  #define SWIG_From_long   PyLong_FromLong 
+
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_ExportToUSGS(OSRSpatialReferenceShadow *self,long *code,long *zone,double *parms[15],long *datum){
     return OSRExportToUSGS( self, code, zone, parms, datum );
   }
@@ -3892,12 +4135,13 @@ SWIGINTERN void OSRCoordinateTransformationShadow_TransformPoints(OSRCoordinateT
 extern "C" {
 #endif
 SWIGINTERN PyObject *_wrap_GetUseExceptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   int result;
   
   if (!PyArg_ParseTuple(args,(char *)":GetUseExceptions")) SWIG_fail;
   result = (int)GetUseExceptions();
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -3905,11 +4149,12 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_UseExceptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   
   if (!PyArg_ParseTuple(args,(char *)":UseExceptions")) SWIG_fail;
   UseExceptions();
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -3917,11 +4162,12 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_DontUseExceptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   
   if (!PyArg_ParseTuple(args,(char *)":DontUseExceptions")) SWIG_fail;
   DontUseExceptions();
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -3929,7 +4175,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GetWellKnownGeogCSAsWKT(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   char **arg2 = (char **) 0 ;
   int res1 ;
@@ -3959,12 +4205,14 @@ SWIGINTERN PyObject *_wrap_GetWellKnownGeogCSAsWKT(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     result = (OGRErr)GetWellKnownGeogCSAsWKT((char const *)arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -3976,7 +4224,7 @@ SWIGINTERN PyObject *_wrap_GetWellKnownGeogCSAsWKT(PyObject *SWIGUNUSEDPARM(self
   {
     /* %typemap(argout) (char **argout) */
     PyObject *o;
-    if ( arg2 != NULL && *arg2 != NULL) {
+    if ( ReturnSame(arg2) != NULL && *arg2 != NULL ) {
       o = GDALPythonObjectFromCStr( *arg2 );
     }
     else {
@@ -3993,14 +4241,11 @@ SWIGINTERN PyObject *_wrap_GetWellKnownGeogCSAsWKT(PyObject *SWIGUNUSEDPARM(self
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
@@ -4014,7 +4259,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_GetUserInputAsWKT(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
   char **arg2 = (char **) 0 ;
   int res1 ;
@@ -4044,12 +4289,14 @@ SWIGINTERN PyObject *_wrap_GetUserInputAsWKT(PyObject *SWIGUNUSEDPARM(self), PyO
       CPLErrorReset();
     }
     result = (OGRErr)GetUserInputAsWKT((char const *)arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -4061,7 +4308,7 @@ SWIGINTERN PyObject *_wrap_GetUserInputAsWKT(PyObject *SWIGUNUSEDPARM(self), PyO
   {
     /* %typemap(argout) (char **argout) */
     PyObject *o;
-    if ( arg2 != NULL && *arg2 != NULL) {
+    if ( ReturnSame(arg2) != NULL && *arg2 != NULL ) {
       o = GDALPythonObjectFromCStr( *arg2 );
     }
     else {
@@ -4078,14 +4325,11 @@ SWIGINTERN PyObject *_wrap_GetUserInputAsWKT(PyObject *SWIGUNUSEDPARM(self), PyO
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
@@ -4099,7 +4343,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_new_SpatialReference(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) "" ;
   int res1 ;
   char *buf1 = 0 ;
@@ -4123,15 +4367,18 @@ SWIGINTERN PyObject *_wrap_new_SpatialReference(PyObject *SWIGUNUSEDPARM(self),
       CPLErrorReset();
     }
     result = (OSRSpatialReferenceShadow *)new_OSRSpatialReferenceShadow((char const *)arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OSRSpatialReferenceShadow, SWIG_POINTER_NEW |  0 );
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
@@ -4140,7 +4387,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_delete_SpatialReference(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -4157,14 +4404,17 @@ SWIGINTERN PyObject *_wrap_delete_SpatialReference(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     delete_OSRSpatialReferenceShadow(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -4172,7 +4422,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference___str__(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -4190,12 +4440,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference___str__(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     result = (retStringAndCPLFree *)OSRSpatialReferenceShadow___str__(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) (retStringAndCPLFree*) */
@@ -4205,6 +4457,7 @@ SWIGINTERN PyObject *_wrap_SpatialReference___str__(PyObject *SWIGUNUSEDPARM(sel
       CPLFree(result);
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -4212,7 +4465,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_IsSame(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   OSRSpatialReferenceShadow *arg2 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
@@ -4244,14 +4497,17 @@ SWIGINTERN PyObject *_wrap_SpatialReference_IsSame(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     result = (int)OSRSpatialReferenceShadow_IsSame(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -4259,7 +4515,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_IsSameGeogCS(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   OSRSpatialReferenceShadow *arg2 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
@@ -4291,14 +4547,17 @@ SWIGINTERN PyObject *_wrap_SpatialReference_IsSameGeogCS(PyObject *SWIGUNUSEDPAR
       CPLErrorReset();
     }
     result = (int)OSRSpatialReferenceShadow_IsSameGeogCS(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -4306,7 +4565,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_IsSameVertCS(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   OSRSpatialReferenceShadow *arg2 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
@@ -4338,14 +4597,17 @@ SWIGINTERN PyObject *_wrap_SpatialReference_IsSameVertCS(PyObject *SWIGUNUSEDPAR
       CPLErrorReset();
     }
     result = (int)OSRSpatialReferenceShadow_IsSameVertCS(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -4353,7 +4615,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_IsGeographic(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -4371,14 +4633,17 @@ SWIGINTERN PyObject *_wrap_SpatialReference_IsGeographic(PyObject *SWIGUNUSEDPAR
       CPLErrorReset();
     }
     result = (int)OSRSpatialReferenceShadow_IsGeographic(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -4386,7 +4651,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_IsProjected(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -4404,14 +4669,17 @@ SWIGINTERN PyObject *_wrap_SpatialReference_IsProjected(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     result = (int)OSRSpatialReferenceShadow_IsProjected(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -4419,7 +4687,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_IsCompound(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -4437,14 +4705,17 @@ SWIGINTERN PyObject *_wrap_SpatialReference_IsCompound(PyObject *SWIGUNUSEDPARM(
       CPLErrorReset();
     }
     result = (int)OSRSpatialReferenceShadow_IsCompound(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -4452,7 +4723,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_IsGeocentric(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -4470,14 +4741,17 @@ SWIGINTERN PyObject *_wrap_SpatialReference_IsGeocentric(PyObject *SWIGUNUSEDPAR
       CPLErrorReset();
     }
     result = (int)OSRSpatialReferenceShadow_IsGeocentric(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -4485,7 +4759,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_IsLocal(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -4503,14 +4777,17 @@ SWIGINTERN PyObject *_wrap_SpatialReference_IsLocal(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     result = (int)OSRSpatialReferenceShadow_IsLocal(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -4518,7 +4795,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_IsVertical(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -4536,14 +4813,17 @@ SWIGINTERN PyObject *_wrap_SpatialReference_IsVertical(PyObject *SWIGUNUSEDPARM(
       CPLErrorReset();
     }
     result = (int)OSRSpatialReferenceShadow_IsVertical(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -4551,7 +4831,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_EPSGTreatsAsLatLong(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -4569,14 +4849,17 @@ SWIGINTERN PyObject *_wrap_SpatialReference_EPSGTreatsAsLatLong(PyObject *SWIGUN
       CPLErrorReset();
     }
     result = (int)OSRSpatialReferenceShadow_EPSGTreatsAsLatLong(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -4584,7 +4867,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_EPSGTreatsAsNorthingEasting(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -4602,14 +4885,17 @@ SWIGINTERN PyObject *_wrap_SpatialReference_EPSGTreatsAsNorthingEasting(PyObject
       CPLErrorReset();
     }
     result = (int)OSRSpatialReferenceShadow_EPSGTreatsAsNorthingEasting(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -4617,7 +4903,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetAuthority(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   char *arg3 = (char *) 0 ;
@@ -4664,12 +4950,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetAuthority(PyObject *SWIGUNUSEDPAR
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetAuthority(arg1,(char const *)arg2,(char const *)arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -4682,14 +4970,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetAuthority(PyObject *SWIGUNUSEDPAR
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -4699,7 +4984,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_GetAttrValue(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   int arg3 = (int) 0 ;
@@ -4743,15 +5028,18 @@ SWIGINTERN PyObject *_wrap_SpatialReference_GetAttrValue(PyObject *SWIGUNUSEDPAR
       CPLErrorReset();
     }
     result = (char *)OSRSpatialReferenceShadow_GetAttrValue(arg1,(char const *)arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -4760,7 +5048,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetAttrValue(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   char *arg3 = (char *) 0 ;
@@ -4803,12 +5091,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetAttrValue(PyObject *SWIGUNUSEDPAR
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetAttrValue(arg1,(char const *)arg2,(char const *)arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -4821,14 +5111,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetAttrValue(PyObject *SWIGUNUSEDPAR
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -4838,7 +5125,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetAngularUnits(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   double arg3 ;
@@ -4880,12 +5167,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetAngularUnits(PyObject *SWIGUNUSED
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetAngularUnits(arg1,(char const *)arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -4897,14 +5186,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetAngularUnits(PyObject *SWIGUNUSED
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -4913,7 +5199,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_GetAngularUnits(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -4931,14 +5217,17 @@ SWIGINTERN PyObject *_wrap_SpatialReference_GetAngularUnits(PyObject *SWIGUNUSED
       CPLErrorReset();
     }
     result = (double)OSRSpatialReferenceShadow_GetAngularUnits(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_double(static_cast< double >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -4946,7 +5235,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetTargetLinearUnits(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   char *arg3 = (char *) 0 ;
@@ -4998,12 +5287,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetTargetLinearUnits(PyObject *SWIGU
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetTargetLinearUnits(arg1,(char const *)arg2,(char const *)arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -5016,14 +5307,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetTargetLinearUnits(PyObject *SWIGU
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -5033,7 +5321,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetLinearUnits(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   double arg3 ;
@@ -5075,12 +5363,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetLinearUnits(PyObject *SWIGUNUSEDP
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetLinearUnits(arg1,(char const *)arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -5092,14 +5382,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetLinearUnits(PyObject *SWIGUNUSEDP
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -5108,7 +5395,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetLinearUnitsAndUpdateParameters(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   double arg3 ;
@@ -5150,12 +5437,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetLinearUnitsAndUpdateParameters(Py
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetLinearUnitsAndUpdateParameters(arg1,(char const *)arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -5167,14 +5456,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetLinearUnitsAndUpdateParameters(Py
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -5183,7 +5469,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_GetLinearUnits(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -5201,14 +5487,17 @@ SWIGINTERN PyObject *_wrap_SpatialReference_GetLinearUnits(PyObject *SWIGUNUSEDP
       CPLErrorReset();
     }
     result = (double)OSRSpatialReferenceShadow_GetLinearUnits(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_double(static_cast< double >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -5216,7 +5505,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_GetLinearUnitsName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -5234,14 +5523,17 @@ SWIGINTERN PyObject *_wrap_SpatialReference_GetLinearUnitsName(PyObject *SWIGUNU
       CPLErrorReset();
     }
     result = (char *)OSRSpatialReferenceShadow_GetLinearUnitsName(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -5249,7 +5541,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_GetAuthorityCode(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -5277,15 +5569,18 @@ SWIGINTERN PyObject *_wrap_SpatialReference_GetAuthorityCode(PyObject *SWIGUNUSE
       CPLErrorReset();
     }
     result = (char *)OSRSpatialReferenceShadow_GetAuthorityCode(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -5294,7 +5589,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_GetAuthorityName(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -5322,15 +5617,18 @@ SWIGINTERN PyObject *_wrap_SpatialReference_GetAuthorityName(PyObject *SWIGUNUSE
       CPLErrorReset();
     }
     result = (char *)OSRSpatialReferenceShadow_GetAuthorityName(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_FromCharPtr((const char *)result);
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -5339,7 +5637,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetUTM(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   int arg2 ;
   int arg3 = (int) 1 ;
@@ -5377,12 +5675,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetUTM(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetUTM(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -5393,14 +5693,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetUTM(PyObject *SWIGUNUSEDPARM(self
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -5408,7 +5705,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_GetUTMZone(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -5426,14 +5723,17 @@ SWIGINTERN PyObject *_wrap_SpatialReference_GetUTMZone(PyObject *SWIGUNUSEDPARM(
       CPLErrorReset();
     }
     result = (int)OSRSpatialReferenceShadow_GetUTMZone(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -5441,7 +5741,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetStatePlane(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   int arg2 ;
   int arg3 = (int) 1 ;
@@ -5502,12 +5802,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetStatePlane(PyObject *SWIGUNUSEDPA
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetStatePlane(arg1,arg2,arg3,(char const *)arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -5519,14 +5821,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetStatePlane(PyObject *SWIGUNUSEDPA
   if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
@@ -5535,7 +5834,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_AutoIdentifyEPSG(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -5553,12 +5852,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_AutoIdentifyEPSG(PyObject *SWIGUNUSE
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_AutoIdentifyEPSG(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -5569,14 +5870,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_AutoIdentifyEPSG(PyObject *SWIGUNUSE
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -5584,7 +5882,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetProjection(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -5612,12 +5910,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetProjection(PyObject *SWIGUNUSEDPA
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetProjection(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -5629,14 +5929,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetProjection(PyObject *SWIGUNUSEDPA
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -5645,7 +5942,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetProjParm(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   double arg3 ;
@@ -5687,12 +5984,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetProjParm(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetProjParm(arg1,(char const *)arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -5704,14 +6003,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetProjParm(PyObject *SWIGUNUSEDPARM
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -5720,7 +6016,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_GetProjParm(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   double arg3 = (double) 0.0 ;
@@ -5764,15 +6060,18 @@ SWIGINTERN PyObject *_wrap_SpatialReference_GetProjParm(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     result = (double)OSRSpatialReferenceShadow_GetProjParm(arg1,(char const *)arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_double(static_cast< double >(result));
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -5781,7 +6080,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetNormProjParm(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   double arg3 ;
@@ -5823,12 +6122,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetNormProjParm(PyObject *SWIGUNUSED
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetNormProjParm(arg1,(char const *)arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -5840,14 +6141,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetNormProjParm(PyObject *SWIGUNUSED
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -5856,7 +6154,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_GetNormProjParm(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   double arg3 = (double) 0.0 ;
@@ -5900,15 +6198,18 @@ SWIGINTERN PyObject *_wrap_SpatialReference_GetNormProjParm(PyObject *SWIGUNUSED
       CPLErrorReset();
     }
     result = (double)OSRSpatialReferenceShadow_GetNormProjParm(arg1,(char const *)arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_double(static_cast< double >(result));
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -5917,7 +6218,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_GetSemiMajor(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -5935,14 +6236,17 @@ SWIGINTERN PyObject *_wrap_SpatialReference_GetSemiMajor(PyObject *SWIGUNUSEDPAR
       CPLErrorReset();
     }
     result = (double)OSRSpatialReferenceShadow_GetSemiMajor(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_double(static_cast< double >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -5950,7 +6254,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_GetSemiMinor(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -5968,14 +6272,17 @@ SWIGINTERN PyObject *_wrap_SpatialReference_GetSemiMinor(PyObject *SWIGUNUSEDPAR
       CPLErrorReset();
     }
     result = (double)OSRSpatialReferenceShadow_GetSemiMinor(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_double(static_cast< double >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -5983,7 +6290,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_GetInvFlattening(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -6001,14 +6308,17 @@ SWIGINTERN PyObject *_wrap_SpatialReference_GetInvFlattening(PyObject *SWIGUNUSE
       CPLErrorReset();
     }
     result = (double)OSRSpatialReferenceShadow_GetInvFlattening(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_From_double(static_cast< double >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6016,7 +6326,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetACEA(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -6091,12 +6401,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetACEA(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetACEA(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -6107,14 +6419,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetACEA(PyObject *SWIGUNUSEDPARM(sel
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6122,7 +6431,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetAE(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -6179,12 +6488,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetAE(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetAE(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -6195,14 +6506,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetAE(PyObject *SWIGUNUSEDPARM(self)
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6210,7 +6518,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetBonne(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -6267,12 +6575,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetBonne(PyObject *SWIGUNUSEDPARM(se
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetBonne(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -6283,14 +6593,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetBonne(PyObject *SWIGUNUSEDPARM(se
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6298,7 +6605,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetCEA(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -6355,12 +6662,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetCEA(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetCEA(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -6371,14 +6680,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetCEA(PyObject *SWIGUNUSEDPARM(self
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6386,7 +6692,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetCS(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -6443,12 +6749,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetCS(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetCS(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -6459,14 +6767,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetCS(PyObject *SWIGUNUSEDPARM(self)
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6474,7 +6779,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetEC(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -6549,12 +6854,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetEC(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetEC(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -6565,14 +6872,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetEC(PyObject *SWIGUNUSEDPARM(self)
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6580,7 +6884,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetEckertIV(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -6628,12 +6932,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetEckertIV(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetEckertIV(arg1,arg2,arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -6644,14 +6950,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetEckertIV(PyObject *SWIGUNUSEDPARM
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6659,7 +6962,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetEckertVI(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -6707,12 +7010,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetEckertVI(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetEckertVI(arg1,arg2,arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -6723,14 +7028,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetEckertVI(PyObject *SWIGUNUSEDPARM
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6738,7 +7040,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetEquirectangular(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -6795,12 +7097,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetEquirectangular(PyObject *SWIGUNU
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetEquirectangular(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -6811,14 +7115,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetEquirectangular(PyObject *SWIGUNU
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6826,7 +7127,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetEquirectangular2(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -6892,12 +7193,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetEquirectangular2(PyObject *SWIGUN
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetEquirectangular2(arg1,arg2,arg3,arg4,arg5,arg6);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -6908,14 +7211,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetEquirectangular2(PyObject *SWIGUN
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -6923,7 +7223,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetGaussSchreiberTMercator(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -6989,12 +7289,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetGaussSchreiberTMercator(PyObject
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetGaussSchreiberTMercator(arg1,arg2,arg3,arg4,arg5,arg6);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -7005,14 +7307,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetGaussSchreiberTMercator(PyObject
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7020,7 +7319,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetGS(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -7068,12 +7367,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetGS(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetGS(arg1,arg2,arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -7084,14 +7385,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetGS(PyObject *SWIGUNUSEDPARM(self)
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7099,7 +7397,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetGH(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -7147,12 +7445,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetGH(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetGH(arg1,arg2,arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -7163,14 +7463,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetGH(PyObject *SWIGUNUSEDPARM(self)
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7178,7 +7475,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetIGH(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -7196,12 +7493,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetIGH(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetIGH(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -7212,14 +7511,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetIGH(PyObject *SWIGUNUSEDPARM(self
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7227,7 +7523,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetGEOS(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -7284,12 +7580,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetGEOS(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetGEOS(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -7300,14 +7598,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetGEOS(PyObject *SWIGUNUSEDPARM(sel
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7315,7 +7610,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetGnomonic(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -7372,12 +7667,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetGnomonic(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetGnomonic(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -7388,14 +7685,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetGnomonic(PyObject *SWIGUNUSEDPARM
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7403,7 +7697,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetHOM(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -7487,12 +7781,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetHOM(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetHOM(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -7503,14 +7799,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetHOM(PyObject *SWIGUNUSEDPARM(self
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7518,7 +7811,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetHOM2PNO(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -7611,12 +7904,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetHOM2PNO(PyObject *SWIGUNUSEDPARM(
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetHOM2PNO(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -7627,14 +7922,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetHOM2PNO(PyObject *SWIGUNUSEDPARM(
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7642,7 +7934,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetKrovak(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -7726,12 +8018,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetKrovak(PyObject *SWIGUNUSEDPARM(s
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetKrovak(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -7742,14 +8036,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetKrovak(PyObject *SWIGUNUSEDPARM(s
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7757,7 +8048,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetLAEA(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -7814,12 +8105,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetLAEA(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetLAEA(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -7830,14 +8123,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetLAEA(PyObject *SWIGUNUSEDPARM(sel
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7845,7 +8135,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetLCC(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -7920,12 +8210,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetLCC(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetLCC(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -7936,14 +8228,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetLCC(PyObject *SWIGUNUSEDPARM(self
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -7951,7 +8240,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetLCC1SP(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -8017,12 +8306,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetLCC1SP(PyObject *SWIGUNUSEDPARM(s
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetLCC1SP(arg1,arg2,arg3,arg4,arg5,arg6);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -8033,14 +8324,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetLCC1SP(PyObject *SWIGUNUSEDPARM(s
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8048,7 +8336,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetLCCB(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -8123,12 +8411,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetLCCB(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetLCCB(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -8139,14 +8429,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetLCCB(PyObject *SWIGUNUSEDPARM(sel
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8154,7 +8441,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetMC(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -8211,12 +8498,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetMC(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetMC(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -8227,14 +8516,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetMC(PyObject *SWIGUNUSEDPARM(self)
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8242,7 +8528,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetMercator(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -8308,12 +8594,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetMercator(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetMercator(arg1,arg2,arg3,arg4,arg5,arg6);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -8324,14 +8612,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetMercator(PyObject *SWIGUNUSEDPARM
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8339,7 +8624,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetMollweide(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -8387,12 +8672,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetMollweide(PyObject *SWIGUNUSEDPAR
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetMollweide(arg1,arg2,arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -8403,14 +8690,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetMollweide(PyObject *SWIGUNUSEDPAR
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8418,7 +8702,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetNZMG(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -8475,12 +8759,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetNZMG(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetNZMG(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -8491,14 +8777,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetNZMG(PyObject *SWIGUNUSEDPARM(sel
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8506,7 +8789,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetOS(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -8572,12 +8855,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetOS(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetOS(arg1,arg2,arg3,arg4,arg5,arg6);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -8588,14 +8873,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetOS(PyObject *SWIGUNUSEDPARM(self)
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8603,7 +8885,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetOrthographic(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -8660,12 +8942,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetOrthographic(PyObject *SWIGUNUSED
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetOrthographic(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -8676,14 +8960,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetOrthographic(PyObject *SWIGUNUSED
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8691,7 +8972,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetPolyconic(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -8748,12 +9029,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetPolyconic(PyObject *SWIGUNUSEDPAR
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetPolyconic(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -8764,14 +9047,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetPolyconic(PyObject *SWIGUNUSEDPAR
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8779,7 +9059,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetPS(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -8845,12 +9125,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetPS(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetPS(arg1,arg2,arg3,arg4,arg5,arg6);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -8861,14 +9143,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetPS(PyObject *SWIGUNUSEDPARM(self)
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8876,7 +9155,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetRobinson(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -8924,12 +9203,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetRobinson(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetRobinson(arg1,arg2,arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -8940,14 +9221,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetRobinson(PyObject *SWIGUNUSEDPARM
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -8955,7 +9233,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetSinusoidal(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -9003,12 +9281,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetSinusoidal(PyObject *SWIGUNUSEDPA
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetSinusoidal(arg1,arg2,arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -9019,14 +9299,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetSinusoidal(PyObject *SWIGUNUSEDPA
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9034,7 +9311,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetStereographic(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -9100,12 +9377,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetStereographic(PyObject *SWIGUNUSE
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetStereographic(arg1,arg2,arg3,arg4,arg5,arg6);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -9116,14 +9395,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetStereographic(PyObject *SWIGUNUSE
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9131,7 +9407,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetSOC(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -9188,12 +9464,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetSOC(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetSOC(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -9204,14 +9482,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetSOC(PyObject *SWIGUNUSEDPARM(self
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9219,7 +9494,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetTM(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -9285,12 +9560,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetTM(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetTM(arg1,arg2,arg3,arg4,arg5,arg6);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -9301,14 +9578,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetTM(PyObject *SWIGUNUSEDPARM(self)
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9316,7 +9590,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetTMVariant(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   double arg3 ;
@@ -9392,12 +9666,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetTMVariant(PyObject *SWIGUNUSEDPAR
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetTMVariant(arg1,(char const *)arg2,arg3,arg4,arg5,arg6,arg7);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -9409,14 +9685,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetTMVariant(PyObject *SWIGUNUSEDPAR
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -9425,7 +9698,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetTMG(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -9482,12 +9755,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetTMG(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetTMG(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -9498,14 +9773,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetTMG(PyObject *SWIGUNUSEDPARM(self
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9513,7 +9785,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetTMSO(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -9579,12 +9851,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetTMSO(PyObject *SWIGUNUSEDPARM(sel
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetTMSO(arg1,arg2,arg3,arg4,arg5,arg6);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -9595,14 +9869,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetTMSO(PyObject *SWIGUNUSEDPARM(sel
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9610,7 +9881,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetVDG(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -9658,12 +9929,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetVDG(PyObject *SWIGUNUSEDPARM(self
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetVDG(arg1,arg2,arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -9674,14 +9947,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetVDG(PyObject *SWIGUNUSEDPARM(self
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9689,7 +9959,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetWellKnownGeogCS(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -9722,12 +9992,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetWellKnownGeogCS(PyObject *SWIGUNU
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetWellKnownGeogCS(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -9739,14 +10011,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetWellKnownGeogCS(PyObject *SWIGUNU
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -9755,7 +10024,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetFromUserInput(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -9788,12 +10057,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetFromUserInput(PyObject *SWIGUNUSE
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetFromUserInput(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -9805,14 +10076,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetFromUserInput(PyObject *SWIGUNUSE
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -9821,7 +10089,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_CopyGeogCSFrom(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   OSRSpatialReferenceShadow *arg2 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
@@ -9853,12 +10121,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_CopyGeogCSFrom(PyObject *SWIGUNUSEDP
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_CopyGeogCSFrom(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -9869,14 +10139,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_CopyGeogCSFrom(PyObject *SWIGUNUSEDP
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -9884,7 +10151,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetTOWGS84(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double arg2 ;
   double arg3 ;
@@ -9973,12 +10240,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetTOWGS84(PyObject *SWIGUNUSEDPARM(
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetTOWGS84(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -9989,14 +10258,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetTOWGS84(PyObject *SWIGUNUSEDPARM(
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -10004,7 +10270,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_GetTOWGS84(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   double *arg2 ;
   void *argp1 = 0 ;
@@ -10015,6 +10281,7 @@ SWIGINTERN PyObject *_wrap_SpatialReference_GetTOWGS84(PyObject *SWIGUNUSEDPARM(
   
   {
     /* %typemap(in,numinputs=0) (double argout2[ANY]) */
+    memset(argout2, 0, sizeof(argout2));
     arg2 = argout2;
   }
   if (!PyArg_ParseTuple(args,(char *)"O:SpatialReference_GetTOWGS84",&obj0)) SWIG_fail;
@@ -10028,12 +10295,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_GetTOWGS84(PyObject *SWIGUNUSEDPARM(
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_GetTOWGS84(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -10049,14 +10318,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_GetTOWGS84(PyObject *SWIGUNUSEDPARM(
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -10064,7 +10330,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetLocalCS(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -10092,12 +10358,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetLocalCS(PyObject *SWIGUNUSEDPARM(
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetLocalCS(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -10109,14 +10377,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetLocalCS(PyObject *SWIGUNUSEDPARM(
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -10125,7 +10390,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetGeogCS(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   char *arg3 = (char *) 0 ;
@@ -10237,12 +10502,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetGeogCS(PyObject *SWIGUNUSEDPARM(s
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetGeogCS(arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4,arg5,arg6,(char const *)arg7,arg8,(char const *)arg9,arg10);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -10258,14 +10525,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetGeogCS(PyObject *SWIGUNUSEDPARM(s
   if (alloc9 == SWIG_NEWOBJ) delete[] buf9;
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -10278,7 +10542,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetProjCS(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char *arg2 = (char *) "unnamed" ;
   void *argp1 = 0 ;
@@ -10313,12 +10577,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetProjCS(PyObject *SWIGUNUSEDPARM(s
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetProjCS(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -10330,14 +10596,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetProjCS(PyObject *SWIGUNUSEDPARM(s
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -10346,7 +10609,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetGeocCS(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char *arg2 = (char *) "unnamed" ;
   void *argp1 = 0 ;
@@ -10381,12 +10644,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetGeocCS(PyObject *SWIGUNUSEDPARM(s
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetGeocCS(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -10398,14 +10663,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetGeocCS(PyObject *SWIGUNUSEDPARM(s
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -10414,7 +10676,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetVertCS(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char *arg2 = (char *) "unnamed" ;
   char *arg3 = (char *) "unnamed" ;
@@ -10467,12 +10729,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetVertCS(PyObject *SWIGUNUSEDPARM(s
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetVertCS(arg1,(char const *)arg2,(char const *)arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -10485,14 +10749,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetVertCS(PyObject *SWIGUNUSEDPARM(s
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -10502,7 +10763,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_SetCompoundCS(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   OSRSpatialReferenceShadow *arg3 = (OSRSpatialReferenceShadow *) 0 ;
@@ -10563,12 +10824,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetCompoundCS(PyObject *SWIGUNUSEDPA
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_SetCompoundCS(arg1,(char const *)arg2,arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -10580,14 +10843,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetCompoundCS(PyObject *SWIGUNUSEDPA
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -10596,7 +10856,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromWkt(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char **arg2 = (char **) 0 ;
   void *argp1 = 0 ;
@@ -10625,12 +10885,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromWkt(PyObject *SWIGUNUSEDPA
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_ImportFromWkt(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -10641,14 +10903,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromWkt(PyObject *SWIGUNUSEDPA
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -10656,7 +10915,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromProj4(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -10684,12 +10943,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromProj4(PyObject *SWIGUNUSED
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_ImportFromProj4(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -10701,14 +10962,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromProj4(PyObject *SWIGUNUSED
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -10717,7 +10975,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromUrl(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -10750,12 +11008,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromUrl(PyObject *SWIGUNUSEDPA
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_ImportFromUrl(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -10767,14 +11027,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromUrl(PyObject *SWIGUNUSEDPA
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -10783,7 +11040,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromESRI(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char **arg2 = (char **) 0 ;
   void *argp1 = 0 ;
@@ -10810,8 +11067,12 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromESRI(PyObject *SWIGUNUSEDP
       SWIG_fail;
     }
     
-    int size = PySequence_Size(obj1);
-    for (int i = 0; i < size; i++) {
+    Py_ssize_t size = PySequence_Size(obj1);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    for (int i = 0; i < (int)size; i++) {
       PyObject* pyObj = PySequence_GetItem(obj1,i);
       if (PyUnicode_Check(pyObj))
       {
@@ -10847,12 +11108,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromESRI(PyObject *SWIGUNUSEDP
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_ImportFromESRI(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -10867,14 +11130,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromESRI(PyObject *SWIGUNUSEDP
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -10886,7 +11146,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromEPSG(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -10913,12 +11173,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromEPSG(PyObject *SWIGUNUSEDP
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_ImportFromEPSG(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -10929,14 +11191,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromEPSG(PyObject *SWIGUNUSEDP
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -10944,7 +11203,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromEPSGA(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   int arg2 ;
   void *argp1 = 0 ;
@@ -10971,12 +11230,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromEPSGA(PyObject *SWIGUNUSED
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_ImportFromEPSGA(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -10987,14 +11248,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromEPSGA(PyObject *SWIGUNUSED
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11002,7 +11260,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromPCI(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   char *arg3 = (char *) "METRE" ;
@@ -11048,7 +11306,7 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromPCI(PyObject *SWIGUNUSEDPA
         PyErr_SetString(PyExc_TypeError, "not a sequence");
         SWIG_fail;
       }
-      int seq_size = PySequence_Size(obj3);
+      Py_ssize_t seq_size = PySequence_Size(obj3);
       if ( seq_size != 17 ) {
         PyErr_SetString(PyExc_TypeError, "sequence must have length ##size");
         SWIG_fail;
@@ -11071,12 +11329,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromPCI(PyObject *SWIGUNUSEDPA
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_ImportFromPCI(arg1,(char const *)arg2,(char const *)arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -11089,14 +11349,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromPCI(PyObject *SWIGUNUSEDPA
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -11106,7 +11363,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromUSGS(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   long arg2 ;
   long arg3 = (long) 0 ;
@@ -11154,7 +11411,7 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromUSGS(PyObject *SWIGUNUSEDP
         PyErr_SetString(PyExc_TypeError, "not a sequence");
         SWIG_fail;
       }
-      int seq_size = PySequence_Size(obj3);
+      Py_ssize_t seq_size = PySequence_Size(obj3);
       if ( seq_size != 15 ) {
         PyErr_SetString(PyExc_TypeError, "sequence must have length ##size");
         SWIG_fail;
@@ -11184,12 +11441,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromUSGS(PyObject *SWIGUNUSEDP
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_ImportFromUSGS(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -11200,14 +11459,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromUSGS(PyObject *SWIGUNUSEDP
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -11215,7 +11471,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromXML(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -11243,12 +11499,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromXML(PyObject *SWIGUNUSEDPA
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_ImportFromXML(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -11260,14 +11518,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromXML(PyObject *SWIGUNUSEDPA
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -11276,7 +11531,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromERM(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   char *arg3 = (char *) 0 ;
@@ -11334,12 +11589,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromERM(PyObject *SWIGUNUSEDPA
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_ImportFromERM(arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -11353,14 +11610,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromERM(PyObject *SWIGUNUSEDPA
   if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -11371,7 +11625,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromMICoordSys(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
@@ -11399,12 +11653,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromMICoordSys(PyObject *SWIGU
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_ImportFromMICoordSys(arg1,(char const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -11416,14 +11672,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromMICoordSys(PyObject *SWIGU
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -11432,7 +11685,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromOzi(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char **arg2 = (char **) 0 ;
   void *argp1 = 0 ;
@@ -11459,8 +11712,12 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromOzi(PyObject *SWIGUNUSEDPA
       SWIG_fail;
     }
     
-    int size = PySequence_Size(obj1);
-    for (int i = 0; i < size; i++) {
+    Py_ssize_t size = PySequence_Size(obj1);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    for (int i = 0; i < (int)size; i++) {
       PyObject* pyObj = PySequence_GetItem(obj1,i);
       if (PyUnicode_Check(pyObj))
       {
@@ -11501,12 +11758,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromOzi(PyObject *SWIGUNUSEDPA
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_ImportFromOzi(arg1,(char const *const *)arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -11521,14 +11780,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromOzi(PyObject *SWIGUNUSEDPA
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -11540,7 +11796,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_ExportToWkt(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char **arg2 = (char **) 0 ;
   void *argp1 = 0 ;
@@ -11564,12 +11820,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToWkt(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_ExportToWkt(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -11581,7 +11839,7 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToWkt(PyObject *SWIGUNUSEDPARM
   {
     /* %typemap(argout) (char **argout) */
     PyObject *o;
-    if ( arg2 != NULL && *arg2 != NULL) {
+    if ( ReturnSame(arg2) != NULL && *arg2 != NULL ) {
       o = GDALPythonObjectFromCStr( *arg2 );
     }
     else {
@@ -11597,14 +11855,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToWkt(PyObject *SWIGUNUSEDPARM
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -11617,7 +11872,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_ExportToPrettyWkt(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char **arg2 = (char **) 0 ;
   int arg3 = (int) 0 ;
@@ -11652,12 +11907,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToPrettyWkt(PyObject *SWIGUNUS
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_ExportToPrettyWkt(arg1,arg2,arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -11669,7 +11926,7 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToPrettyWkt(PyObject *SWIGUNUS
   {
     /* %typemap(argout) (char **argout) */
     PyObject *o;
-    if ( arg2 != NULL && *arg2 != NULL) {
+    if ( ReturnSame(arg2) != NULL && *arg2 != NULL ) {
       o = GDALPythonObjectFromCStr( *arg2 );
     }
     else {
@@ -11685,14 +11942,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToPrettyWkt(PyObject *SWIGUNUS
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -11705,7 +11959,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_ExportToProj4(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char **arg2 = (char **) 0 ;
   void *argp1 = 0 ;
@@ -11729,12 +11983,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToProj4(PyObject *SWIGUNUSEDPA
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_ExportToProj4(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -11746,7 +12002,7 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToProj4(PyObject *SWIGUNUSEDPA
   {
     /* %typemap(argout) (char **argout) */
     PyObject *o;
-    if ( arg2 != NULL && *arg2 != NULL) {
+    if ( ReturnSame(arg2) != NULL && *arg2 != NULL ) {
       o = GDALPythonObjectFromCStr( *arg2 );
     }
     else {
@@ -11762,14 +12018,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToProj4(PyObject *SWIGUNUSEDPA
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -11782,7 +12035,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_ExportToPCI(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char **arg2 = (char **) 0 ;
   char **arg3 = (char **) 0 ;
@@ -11805,6 +12058,7 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToPCI(PyObject *SWIGUNUSEDPARM
   }
   {
     /* %typemap(in,numinputs=0) (double *argout4[ANY]) */
+    argout4 = NULL;
     arg4 = &argout4;
   }
   if (!PyArg_ParseTuple(args,(char *)"O:SpatialReference_ExportToPCI",&obj0)) SWIG_fail;
@@ -11818,12 +12072,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToPCI(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_ExportToPCI(arg1,arg2,arg3,arg4);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -11835,7 +12091,7 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToPCI(PyObject *SWIGUNUSEDPARM
   {
     /* %typemap(argout) (char **argout) */
     PyObject *o;
-    if ( arg2 != NULL && *arg2 != NULL) {
+    if ( ReturnSame(arg2) != NULL && *arg2 != NULL ) {
       o = GDALPythonObjectFromCStr( *arg2 );
     }
     else {
@@ -11847,7 +12103,7 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToPCI(PyObject *SWIGUNUSEDPARM
   {
     /* %typemap(argout) (char **argout) */
     PyObject *o;
-    if ( arg3 != NULL && *arg3 != NULL) {
+    if ( ReturnSame(arg3) != NULL && *arg3 != NULL ) {
       o = GDALPythonObjectFromCStr( *arg3 );
     }
     else {
@@ -11877,14 +12133,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToPCI(PyObject *SWIGUNUSEDPARM
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -11906,7 +12159,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_ExportToUSGS(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   long *arg2 = (long *) 0 ;
   long *arg3 = (long *) 0 ;
@@ -11928,6 +12181,7 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToUSGS(PyObject *SWIGUNUSEDPAR
   arg3 = &temp3;
   {
     /* %typemap(in,numinputs=0) (double *argout4[ANY]) */
+    argout4 = NULL;
     arg4 = &argout4;
   }
   arg5 = &temp5;
@@ -11942,12 +12196,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToUSGS(PyObject *SWIGUNUSEDPAR
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_ExportToUSGS(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -11956,13 +12212,13 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToUSGS(PyObject *SWIGUNUSEDPAR
       SWIG_fail;
     }
   }
-  if (SWIG_IsTmpObj(res2)) {
+  if (ReturnSame(SWIG_IsTmpObj(res2))) {
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_long((*arg2)));
   } else {
     int new_flags = SWIG_IsNewObj(res2) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg2), SWIGTYPE_p_long, new_flags));
   }
-  if (SWIG_IsTmpObj(res3)) {
+  if (ReturnSame(SWIG_IsTmpObj(res3))) {
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_long((*arg3)));
   } else {
     int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
@@ -11973,7 +12229,7 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToUSGS(PyObject *SWIGUNUSEDPAR
     PyObject *out = CreateTupleFromDoubleArray( *arg4, 15 );
     resultobj = t_output_helper(resultobj,out);
   }
-  if (SWIG_IsTmpObj(res5)) {
+  if (ReturnSame(SWIG_IsTmpObj(res5))) {
     resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_long((*arg5)));
   } else {
     int new_flags = SWIG_IsNewObj(res5) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
@@ -11985,14 +12241,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToUSGS(PyObject *SWIGUNUSEDPAR
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -12004,7 +12257,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_ExportToXML(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char **arg2 = (char **) 0 ;
   char *arg3 = (char *) "" ;
@@ -12040,12 +12293,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToXML(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_ExportToXML(arg1,arg2,(char const *)arg3);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -12057,7 +12312,7 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToXML(PyObject *SWIGUNUSEDPARM
   {
     /* %typemap(argout) (char **argout) */
     PyObject *o;
-    if ( arg2 != NULL && *arg2 != NULL) {
+    if ( ReturnSame(arg2) != NULL && *arg2 != NULL ) {
       o = GDALPythonObjectFromCStr( *arg2 );
     }
     else {
@@ -12074,14 +12329,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToXML(PyObject *SWIGUNUSEDPARM
   if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -12095,7 +12347,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_ExportToMICoordSys(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   char **arg2 = (char **) 0 ;
   void *argp1 = 0 ;
@@ -12119,12 +12371,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToMICoordSys(PyObject *SWIGUNU
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_ExportToMICoordSys(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -12136,7 +12390,7 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToMICoordSys(PyObject *SWIGUNU
   {
     /* %typemap(argout) (char **argout) */
     PyObject *o;
-    if ( arg2 != NULL && *arg2 != NULL) {
+    if ( ReturnSame(arg2) != NULL && *arg2 != NULL ) {
       o = GDALPythonObjectFromCStr( *arg2 );
     }
     else {
@@ -12152,14 +12406,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToMICoordSys(PyObject *SWIGUNU
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -12172,7 +12423,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_CloneGeogCS(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -12190,14 +12441,17 @@ SWIGINTERN PyObject *_wrap_SpatialReference_CloneGeogCS(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     result = (OSRSpatialReferenceShadow *)OSRSpatialReferenceShadow_CloneGeogCS(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OSRSpatialReferenceShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -12205,7 +12459,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_Clone(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -12223,14 +12477,17 @@ SWIGINTERN PyObject *_wrap_SpatialReference_Clone(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (OSRSpatialReferenceShadow *)OSRSpatialReferenceShadow_Clone(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OSRSpatialReferenceShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -12238,7 +12495,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_Validate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -12256,12 +12513,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_Validate(PyObject *SWIGUNUSEDPARM(se
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_Validate(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -12272,14 +12531,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_Validate(PyObject *SWIGUNUSEDPARM(se
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -12287,7 +12543,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_StripCTParms(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -12305,12 +12561,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_StripCTParms(PyObject *SWIGUNUSEDPAR
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_StripCTParms(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -12321,14 +12579,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_StripCTParms(PyObject *SWIGUNUSEDPAR
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -12336,7 +12591,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_FixupOrdering(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -12354,12 +12609,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_FixupOrdering(PyObject *SWIGUNUSEDPA
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_FixupOrdering(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -12370,14 +12627,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_FixupOrdering(PyObject *SWIGUNUSEDPA
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -12385,7 +12639,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_Fixup(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -12403,12 +12657,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_Fixup(PyObject *SWIGUNUSEDPARM(self)
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_Fixup(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -12419,14 +12675,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_Fixup(PyObject *SWIGUNUSEDPARM(self)
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -12434,7 +12687,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_MorphToESRI(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -12452,12 +12705,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_MorphToESRI(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_MorphToESRI(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -12468,14 +12723,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_MorphToESRI(PyObject *SWIGUNUSEDPARM
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -12483,7 +12735,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_SpatialReference_MorphFromESRI(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -12501,12 +12753,14 @@ SWIGINTERN PyObject *_wrap_SpatialReference_MorphFromESRI(PyObject *SWIGUNUSEDPA
       CPLErrorReset();
     }
     result = (OGRErr)OSRSpatialReferenceShadow_MorphFromESRI(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   {
     /* %typemap(out) OGRErr */
@@ -12517,14 +12771,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_MorphFromESRI(PyObject *SWIGUNUSEDPA
   }
   {
     /* %typemap(ret) OGRErr */
-    if (resultobj == Py_None ) {
-      Py_DECREF(resultobj);
-      resultobj = 0;
-    }
-    if (resultobj == 0) {
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
       resultobj = PyInt_FromLong( result );
     }
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -12539,7 +12790,7 @@ SWIGINTERN PyObject *SpatialReference_swigregister(PyObject *SWIGUNUSEDPARM(self
 }
 
 SWIGINTERN PyObject *_wrap_new_CoordinateTransformation(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   OSRSpatialReferenceShadow *arg2 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
@@ -12566,14 +12817,17 @@ SWIGINTERN PyObject *_wrap_new_CoordinateTransformation(PyObject *SWIGUNUSEDPARM
       CPLErrorReset();
     }
     result = (OSRCoordinateTransformationShadow *)new_OSRCoordinateTransformationShadow(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OSRCoordinateTransformationShadow, SWIG_POINTER_NEW |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -12581,7 +12835,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_delete_CoordinateTransformation(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRCoordinateTransformationShadow *arg1 = (OSRCoordinateTransformationShadow *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -12598,14 +12852,17 @@ SWIGINTERN PyObject *_wrap_delete_CoordinateTransformation(PyObject *SWIGUNUSEDP
       CPLErrorReset();
     }
     delete_OSRCoordinateTransformationShadow(arg1);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -12613,7 +12870,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_CoordinateTransformation_TransformPoint__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRCoordinateTransformationShadow *arg1 = (OSRCoordinateTransformationShadow *) 0 ;
   double *arg2 ;
   void *argp1 = 0 ;
@@ -12635,7 +12892,7 @@ SWIGINTERN PyObject *_wrap_CoordinateTransformation_TransformPoint__SWIG_0(PyObj
       PyErr_SetString(PyExc_TypeError, "not a sequence");
       SWIG_fail;
     }
-    int seq_size = PySequence_Size(obj1);
+    Py_ssize_t seq_size = PySequence_Size(obj1);
     if ( seq_size != 3 ) {
       PyErr_SetString(PyExc_TypeError, "sequence must have length ##size");
       SWIG_fail;
@@ -12657,12 +12914,14 @@ SWIGINTERN PyObject *_wrap_CoordinateTransformation_TransformPoint__SWIG_0(PyObj
       CPLErrorReset();
     }
     OSRCoordinateTransformationShadow_TransformPoint__SWIG_0(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
@@ -12670,6 +12929,7 @@ SWIGINTERN PyObject *_wrap_CoordinateTransformation_TransformPoint__SWIG_0(PyObj
     PyObject *out = CreateTupleFromDoubleArray( arg2, 3 );
     resultobj = t_output_helper(resultobj,out);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -12677,7 +12937,7 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_CoordinateTransformation_TransformPoint__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRCoordinateTransformationShadow *arg1 = (OSRCoordinateTransformationShadow *) 0 ;
   double *arg2 ;
   double arg3 ;
@@ -12699,6 +12959,7 @@ SWIGINTERN PyObject *_wrap_CoordinateTransformation_TransformPoint__SWIG_1(PyObj
   
   {
     /* %typemap(in,numinputs=0) (double argout2[ANY]) */
+    memset(argout2, 0, sizeof(argout2));
     arg2 = argout2;
   }
   if (!PyArg_ParseTuple(args,(char *)"OOO|O:CoordinateTransformation_TransformPoint",&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
@@ -12729,12 +12990,14 @@ SWIGINTERN PyObject *_wrap_CoordinateTransformation_TransformPoint__SWIG_1(PyObj
       CPLErrorReset();
     }
     OSRCoordinateTransformationShadow_TransformPoint__SWIG_1(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
@@ -12742,6 +13005,7 @@ SWIGINTERN PyObject *_wrap_CoordinateTransformation_TransformPoint__SWIG_1(PyObj
     PyObject *out = CreateTupleFromDoubleArray( arg2, 3 );
     resultobj = t_output_helper(resultobj,out);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -12753,9 +13017,9 @@ SWIGINTERN PyObject *_wrap_CoordinateTransformation_TransformPoint(PyObject *sel
   PyObject *argv[5];
   int ii;
   
-  if (!PyTuple_Check(args)) SWIG_fail;
+  if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
   argc = (int)PyObject_Length(args);
-  for (ii = 0; (ii < argc) && (ii < 4); ii++) {
+  for (ii = 0; (ii < 4) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
   if (argc == 2) {
@@ -12804,16 +13068,16 @@ SWIGINTERN PyObject *_wrap_CoordinateTransformation_TransformPoint(PyObject *sel
   }
   
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'CoordinateTransformation_TransformPoint'.\n"
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'CoordinateTransformation_TransformPoint'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    TransformPoint(OSRCoordinateTransformationShadow *,double [3])\n"
-    "    TransformPoint(OSRCoordinateTransformationShadow *,double [3],double,double,double)\n");
-  return NULL;
+    "    OSRCoordinateTransformationShadow::TransformPoint(double [3])\n"
+    "    OSRCoordinateTransformationShadow::TransformPoint(double [3],double,double,double)\n");
+  return 0;
 }
 
 
 SWIGINTERN PyObject *_wrap_CoordinateTransformation_TransformPoints(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRCoordinateTransformationShadow *arg1 = (OSRCoordinateTransformationShadow *) 0 ;
   int arg2 ;
   double *arg3 = (double *) 0 ;
@@ -12836,7 +13100,12 @@ SWIGINTERN PyObject *_wrap_CoordinateTransformation_TransformPoints(PyObject *SW
       SWIG_fail;
     }
     
-    arg2 = PySequence_Size(obj1);
+    Py_ssize_t size = PySequence_Size(obj1);
+    if( size != (int)size ) {
+      PyErr_SetString(PyExc_TypeError, "too big sequence");
+      SWIG_fail;
+    }
+    arg2 = (int)size;
     arg3 = (double*) VSIMalloc(arg2*sizeof(double));
     arg4 = (double*) VSIMalloc(arg2*sizeof(double));
     arg5 = (double*) VSIMalloc(arg2*sizeof(double));
@@ -12856,12 +13125,14 @@ SWIGINTERN PyObject *_wrap_CoordinateTransformation_TransformPoints(PyObject *SW
       CPLErrorReset();
     }
     OSRCoordinateTransformationShadow_TransformPoints(arg1,arg2,arg3,arg4,arg5);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_Py_Void();
   {
@@ -12883,6 +13154,7 @@ SWIGINTERN PyObject *_wrap_CoordinateTransformation_TransformPoints(PyObject *SW
     VSIFree(arg4);
     VSIFree(arg5);
   }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
@@ -12903,7 +13175,7 @@ SWIGINTERN PyObject *CoordinateTransformation_swigregister(PyObject *SWIGUNUSEDP
 }
 
 SWIGINTERN PyObject *_wrap_CreateCoordinateTransformation(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
   OSRSpatialReferenceShadow *arg2 = (OSRSpatialReferenceShadow *) 0 ;
   void *argp1 = 0 ;
@@ -12930,14 +13202,17 @@ SWIGINTERN PyObject *_wrap_CreateCoordinateTransformation(PyObject *SWIGUNUSEDPA
       CPLErrorReset();
     }
     result = (OSRCoordinateTransformationShadow *)CreateCoordinateTransformation(arg1,arg2);
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
       }
     }
+#endif
   }
   resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OSRCoordinateTransformationShadow, SWIG_POINTER_OWN |  0 );
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   return NULL;
@@ -12950,11 +13225,11 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"UseExceptions", _wrap_UseExceptions, METH_VARARGS, (char *)"UseExceptions()"},
 	 { (char *)"DontUseExceptions", _wrap_DontUseExceptions, METH_VARARGS, (char *)"DontUseExceptions()"},
 	 { (char *)"GetProjectionMethods", py_OPTGetProjectionMethods, METH_VARARGS, NULL},
-	 { (char *)"GetWellKnownGeogCSAsWKT", _wrap_GetWellKnownGeogCSAsWKT, METH_VARARGS, (char *)"GetWellKnownGeogCSAsWKT(char name) -> OGRErr"},
-	 { (char *)"GetUserInputAsWKT", _wrap_GetUserInputAsWKT, METH_VARARGS, (char *)"GetUserInputAsWKT(char name) -> OGRErr"},
-	 { (char *)"new_SpatialReference", (PyCFunction) _wrap_new_SpatialReference, METH_VARARGS | METH_KEYWORDS, (char *)"new_SpatialReference(char wkt = \"\") -> SpatialReference"},
+	 { (char *)"GetWellKnownGeogCSAsWKT", _wrap_GetWellKnownGeogCSAsWKT, METH_VARARGS, (char *)"GetWellKnownGeogCSAsWKT(char const * name) -> OGRErr"},
+	 { (char *)"GetUserInputAsWKT", _wrap_GetUserInputAsWKT, METH_VARARGS, (char *)"GetUserInputAsWKT(char const * name) -> OGRErr"},
+	 { (char *)"new_SpatialReference", (PyCFunction) _wrap_new_SpatialReference, METH_VARARGS | METH_KEYWORDS, (char *)"new_SpatialReference(char const * wkt=\"\") -> SpatialReference"},
 	 { (char *)"delete_SpatialReference", _wrap_delete_SpatialReference, METH_VARARGS, (char *)"delete_SpatialReference(SpatialReference self)"},
-	 { (char *)"SpatialReference___str__", _wrap_SpatialReference___str__, METH_VARARGS, (char *)"SpatialReference___str__(SpatialReference self) -> retStringAndCPLFree"},
+	 { (char *)"SpatialReference___str__", _wrap_SpatialReference___str__, METH_VARARGS, (char *)"SpatialReference___str__(SpatialReference self) -> retStringAndCPLFree *"},
 	 { (char *)"SpatialReference_IsSame", _wrap_SpatialReference_IsSame, METH_VARARGS, (char *)"SpatialReference_IsSame(SpatialReference self, SpatialReference rhs) -> int"},
 	 { (char *)"SpatialReference_IsSameGeogCS", _wrap_SpatialReference_IsSameGeogCS, METH_VARARGS, (char *)"SpatialReference_IsSameGeogCS(SpatialReference self, SpatialReference rhs) -> int"},
 	 { (char *)"SpatialReference_IsSameVertCS", _wrap_SpatialReference_IsSameVertCS, METH_VARARGS, (char *)"SpatialReference_IsSameVertCS(SpatialReference self, SpatialReference rhs) -> int"},
@@ -12966,224 +13241,140 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"SpatialReference_IsVertical", _wrap_SpatialReference_IsVertical, METH_VARARGS, (char *)"SpatialReference_IsVertical(SpatialReference self) -> int"},
 	 { (char *)"SpatialReference_EPSGTreatsAsLatLong", _wrap_SpatialReference_EPSGTreatsAsLatLong, METH_VARARGS, (char *)"SpatialReference_EPSGTreatsAsLatLong(SpatialReference self) -> int"},
 	 { (char *)"SpatialReference_EPSGTreatsAsNorthingEasting", _wrap_SpatialReference_EPSGTreatsAsNorthingEasting, METH_VARARGS, (char *)"SpatialReference_EPSGTreatsAsNorthingEasting(SpatialReference self) -> int"},
-	 { (char *)"SpatialReference_SetAuthority", _wrap_SpatialReference_SetAuthority, METH_VARARGS, (char *)"\n"
-		"SpatialReference_SetAuthority(SpatialReference self, char pszTargetKey, char pszAuthority, \n"
-		"    int nCode) -> OGRErr\n"
-		""},
-	 { (char *)"SpatialReference_GetAttrValue", _wrap_SpatialReference_GetAttrValue, METH_VARARGS, (char *)"SpatialReference_GetAttrValue(SpatialReference self, char name, int child = 0) -> char"},
-	 { (char *)"SpatialReference_SetAttrValue", _wrap_SpatialReference_SetAttrValue, METH_VARARGS, (char *)"SpatialReference_SetAttrValue(SpatialReference self, char name, char value) -> OGRErr"},
-	 { (char *)"SpatialReference_SetAngularUnits", _wrap_SpatialReference_SetAngularUnits, METH_VARARGS, (char *)"SpatialReference_SetAngularUnits(SpatialReference self, char name, double to_radians) -> OGRErr"},
+	 { (char *)"SpatialReference_SetAuthority", _wrap_SpatialReference_SetAuthority, METH_VARARGS, (char *)"SpatialReference_SetAuthority(SpatialReference self, char const * pszTargetKey, char const * pszAuthority, int nCode) -> OGRErr"},
+	 { (char *)"SpatialReference_GetAttrValue", _wrap_SpatialReference_GetAttrValue, METH_VARARGS, (char *)"SpatialReference_GetAttrValue(SpatialReference self, char const * name, int child=0) -> char const *"},
+	 { (char *)"SpatialReference_SetAttrValue", _wrap_SpatialReference_SetAttrValue, METH_VARARGS, (char *)"SpatialReference_SetAttrValue(SpatialReference self, char const * name, char const * value) -> OGRErr"},
+	 { (char *)"SpatialReference_SetAngularUnits", _wrap_SpatialReference_SetAngularUnits, METH_VARARGS, (char *)"SpatialReference_SetAngularUnits(SpatialReference self, char const * name, double to_radians) -> OGRErr"},
 	 { (char *)"SpatialReference_GetAngularUnits", _wrap_SpatialReference_GetAngularUnits, METH_VARARGS, (char *)"SpatialReference_GetAngularUnits(SpatialReference self) -> double"},
-	 { (char *)"SpatialReference_SetTargetLinearUnits", _wrap_SpatialReference_SetTargetLinearUnits, METH_VARARGS, (char *)"SpatialReference_SetTargetLinearUnits(SpatialReference self, char target, char name, double to_meters) -> OGRErr"},
-	 { (char *)"SpatialReference_SetLinearUnits", _wrap_SpatialReference_SetLinearUnits, METH_VARARGS, (char *)"SpatialReference_SetLinearUnits(SpatialReference self, char name, double to_meters) -> OGRErr"},
-	 { (char *)"SpatialReference_SetLinearUnitsAndUpdateParameters", _wrap_SpatialReference_SetLinearUnitsAndUpdateParameters, METH_VARARGS, (char *)"SpatialReference_SetLinearUnitsAndUpdateParameters(SpatialReference self, char name, double to_meters) -> OGRErr"},
+	 { (char *)"SpatialReference_SetTargetLinearUnits", _wrap_SpatialReference_SetTargetLinearUnits, METH_VARARGS, (char *)"SpatialReference_SetTargetLinearUnits(SpatialReference self, char const * target, char const * name, double to_meters) -> OGRErr"},
+	 { (char *)"SpatialReference_SetLinearUnits", _wrap_SpatialReference_SetLinearUnits, METH_VARARGS, (char *)"SpatialReference_SetLinearUnits(SpatialReference self, char const * name, double to_meters) -> OGRErr"},
+	 { (char *)"SpatialReference_SetLinearUnitsAndUpdateParameters", _wrap_SpatialReference_SetLinearUnitsAndUpdateParameters, METH_VARARGS, (char *)"SpatialReference_SetLinearUnitsAndUpdateParameters(SpatialReference self, char const * name, double to_meters) -> OGRErr"},
 	 { (char *)"SpatialReference_GetLinearUnits", _wrap_SpatialReference_GetLinearUnits, METH_VARARGS, (char *)"SpatialReference_GetLinearUnits(SpatialReference self) -> double"},
-	 { (char *)"SpatialReference_GetLinearUnitsName", _wrap_SpatialReference_GetLinearUnitsName, METH_VARARGS, (char *)"SpatialReference_GetLinearUnitsName(SpatialReference self) -> char"},
-	 { (char *)"SpatialReference_GetAuthorityCode", _wrap_SpatialReference_GetAuthorityCode, METH_VARARGS, (char *)"SpatialReference_GetAuthorityCode(SpatialReference self, char target_key) -> char"},
-	 { (char *)"SpatialReference_GetAuthorityName", _wrap_SpatialReference_GetAuthorityName, METH_VARARGS, (char *)"SpatialReference_GetAuthorityName(SpatialReference self, char target_key) -> char"},
-	 { (char *)"SpatialReference_SetUTM", _wrap_SpatialReference_SetUTM, METH_VARARGS, (char *)"SpatialReference_SetUTM(SpatialReference self, int zone, int north = 1) -> OGRErr"},
+	 { (char *)"SpatialReference_GetLinearUnitsName", _wrap_SpatialReference_GetLinearUnitsName, METH_VARARGS, (char *)"SpatialReference_GetLinearUnitsName(SpatialReference self) -> char const *"},
+	 { (char *)"SpatialReference_GetAuthorityCode", _wrap_SpatialReference_GetAuthorityCode, METH_VARARGS, (char *)"SpatialReference_GetAuthorityCode(SpatialReference self, char const * target_key) -> char const *"},
+	 { (char *)"SpatialReference_GetAuthorityName", _wrap_SpatialReference_GetAuthorityName, METH_VARARGS, (char *)"SpatialReference_GetAuthorityName(SpatialReference self, char const * target_key) -> char const *"},
+	 { (char *)"SpatialReference_SetUTM", _wrap_SpatialReference_SetUTM, METH_VARARGS, (char *)"SpatialReference_SetUTM(SpatialReference self, int zone, int north=1) -> OGRErr"},
 	 { (char *)"SpatialReference_GetUTMZone", _wrap_SpatialReference_GetUTMZone, METH_VARARGS, (char *)"SpatialReference_GetUTMZone(SpatialReference self) -> int"},
-	 { (char *)"SpatialReference_SetStatePlane", _wrap_SpatialReference_SetStatePlane, METH_VARARGS, (char *)"\n"
-		"SpatialReference_SetStatePlane(SpatialReference self, int zone, int is_nad83 = 1, \n"
-		"    char unitsname = \"\", double units = 0.0) -> OGRErr\n"
-		""},
+	 { (char *)"SpatialReference_SetStatePlane", _wrap_SpatialReference_SetStatePlane, METH_VARARGS, (char *)"SpatialReference_SetStatePlane(SpatialReference self, int zone, int is_nad83=1, char const * unitsname=\"\", double units=0.0) -> OGRErr"},
 	 { (char *)"SpatialReference_AutoIdentifyEPSG", _wrap_SpatialReference_AutoIdentifyEPSG, METH_VARARGS, (char *)"SpatialReference_AutoIdentifyEPSG(SpatialReference self) -> OGRErr"},
-	 { (char *)"SpatialReference_SetProjection", _wrap_SpatialReference_SetProjection, METH_VARARGS, (char *)"SpatialReference_SetProjection(SpatialReference self, char arg) -> OGRErr"},
-	 { (char *)"SpatialReference_SetProjParm", _wrap_SpatialReference_SetProjParm, METH_VARARGS, (char *)"SpatialReference_SetProjParm(SpatialReference self, char name, double val) -> OGRErr"},
-	 { (char *)"SpatialReference_GetProjParm", _wrap_SpatialReference_GetProjParm, METH_VARARGS, (char *)"SpatialReference_GetProjParm(SpatialReference self, char name, double default_val = 0.0) -> double"},
-	 { (char *)"SpatialReference_SetNormProjParm", _wrap_SpatialReference_SetNormProjParm, METH_VARARGS, (char *)"SpatialReference_SetNormProjParm(SpatialReference self, char name, double val) -> OGRErr"},
-	 { (char *)"SpatialReference_GetNormProjParm", _wrap_SpatialReference_GetNormProjParm, METH_VARARGS, (char *)"SpatialReference_GetNormProjParm(SpatialReference self, char name, double default_val = 0.0) -> double"},
+	 { (char *)"SpatialReference_SetProjection", _wrap_SpatialReference_SetProjection, METH_VARARGS, (char *)"SpatialReference_SetProjection(SpatialReference self, char const * arg) -> OGRErr"},
+	 { (char *)"SpatialReference_SetProjParm", _wrap_SpatialReference_SetProjParm, METH_VARARGS, (char *)"SpatialReference_SetProjParm(SpatialReference self, char const * name, double val) -> OGRErr"},
+	 { (char *)"SpatialReference_GetProjParm", _wrap_SpatialReference_GetProjParm, METH_VARARGS, (char *)"SpatialReference_GetProjParm(SpatialReference self, char const * name, double default_val=0.0) -> double"},
+	 { (char *)"SpatialReference_SetNormProjParm", _wrap_SpatialReference_SetNormProjParm, METH_VARARGS, (char *)"SpatialReference_SetNormProjParm(SpatialReference self, char const * name, double val) -> OGRErr"},
+	 { (char *)"SpatialReference_GetNormProjParm", _wrap_SpatialReference_GetNormProjParm, METH_VARARGS, (char *)"SpatialReference_GetNormProjParm(SpatialReference self, char const * name, double default_val=0.0) -> double"},
 	 { (char *)"SpatialReference_GetSemiMajor", _wrap_SpatialReference_GetSemiMajor, METH_VARARGS, (char *)"SpatialReference_GetSemiMajor(SpatialReference self) -> double"},
 	 { (char *)"SpatialReference_GetSemiMinor", _wrap_SpatialReference_GetSemiMinor, METH_VARARGS, (char *)"SpatialReference_GetSemiMinor(SpatialReference self) -> double"},
 	 { (char *)"SpatialReference_GetInvFlattening", _wrap_SpatialReference_GetInvFlattening, METH_VARARGS, (char *)"SpatialReference_GetInvFlattening(SpatialReference self) -> double"},
 	 { (char *)"SpatialReference_SetACEA", (PyCFunction) _wrap_SpatialReference_SetACEA, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetACEA(SpatialReference self, double stdp1, double stdp2, \n"
-		"    double clat, double clong, double fe, double fn) -> OGRErr\n"
-		""},
-	 { (char *)"SpatialReference_SetAE", (PyCFunction) _wrap_SpatialReference_SetAE, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetAE(SpatialReference self, double clat, double clong, double fe, \n"
-		"    double fn) -> OGRErr\n"
-		""},
-	 { (char *)"SpatialReference_SetBonne", (PyCFunction) _wrap_SpatialReference_SetBonne, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetBonne(SpatialReference self, double stdp, double cm, double fe, \n"
-		"    double fn) -> OGRErr\n"
-		""},
-	 { (char *)"SpatialReference_SetCEA", (PyCFunction) _wrap_SpatialReference_SetCEA, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetCEA(SpatialReference self, double stdp1, double cm, double fe, \n"
-		"    double fn) -> OGRErr\n"
-		""},
-	 { (char *)"SpatialReference_SetCS", (PyCFunction) _wrap_SpatialReference_SetCS, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetCS(SpatialReference self, double clat, double clong, double fe, \n"
+		"SpatialReference_SetACEA(SpatialReference self, double stdp1, double stdp2, double clat, double clong, double fe, \n"
 		"    double fn) -> OGRErr\n"
 		""},
+	 { (char *)"SpatialReference_SetAE", (PyCFunction) _wrap_SpatialReference_SetAE, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetAE(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"},
+	 { (char *)"SpatialReference_SetBonne", (PyCFunction) _wrap_SpatialReference_SetBonne, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetBonne(SpatialReference self, double stdp, double cm, double fe, double fn) -> OGRErr"},
+	 { (char *)"SpatialReference_SetCEA", (PyCFunction) _wrap_SpatialReference_SetCEA, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetCEA(SpatialReference self, double stdp1, double cm, double fe, double fn) -> OGRErr"},
+	 { (char *)"SpatialReference_SetCS", (PyCFunction) _wrap_SpatialReference_SetCS, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetCS(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetEC", (PyCFunction) _wrap_SpatialReference_SetEC, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetEC(SpatialReference self, double stdp1, double stdp2, \n"
-		"    double clat, double clong, double fe, double fn) -> OGRErr\n"
+		"SpatialReference_SetEC(SpatialReference self, double stdp1, double stdp2, double clat, double clong, double fe, \n"
+		"    double fn) -> OGRErr\n"
 		""},
 	 { (char *)"SpatialReference_SetEckertIV", (PyCFunction) _wrap_SpatialReference_SetEckertIV, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetEckertIV(SpatialReference self, double cm, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetEckertVI", (PyCFunction) _wrap_SpatialReference_SetEckertVI, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetEckertVI(SpatialReference self, double cm, double fe, double fn) -> OGRErr"},
-	 { (char *)"SpatialReference_SetEquirectangular", (PyCFunction) _wrap_SpatialReference_SetEquirectangular, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetEquirectangular(SpatialReference self, double clat, double clong, double fe, \n"
-		"    double fn) -> OGRErr\n"
-		""},
+	 { (char *)"SpatialReference_SetEquirectangular", (PyCFunction) _wrap_SpatialReference_SetEquirectangular, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetEquirectangular(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetEquirectangular2", (PyCFunction) _wrap_SpatialReference_SetEquirectangular2, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetEquirectangular2(SpatialReference self, double clat, double clong, double pseudostdparallellat, \n"
-		"    double fe, double fn) -> OGRErr\n"
-		""},
-	 { (char *)"SpatialReference_SetGaussSchreiberTMercator", (PyCFunction) _wrap_SpatialReference_SetGaussSchreiberTMercator, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetGaussSchreiberTMercator(SpatialReference self, double clat, double clong, double sc, \n"
-		"    double fe, double fn) -> OGRErr\n"
+		"SpatialReference_SetEquirectangular2(SpatialReference self, double clat, double clong, double pseudostdparallellat, double fe, \n"
+		"    double fn) -> OGRErr\n"
 		""},
+	 { (char *)"SpatialReference_SetGaussSchreiberTMercator", (PyCFunction) _wrap_SpatialReference_SetGaussSchreiberTMercator, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetGaussSchreiberTMercator(SpatialReference self, double clat, double clong, double sc, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetGS", (PyCFunction) _wrap_SpatialReference_SetGS, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetGS(SpatialReference self, double cm, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetGH", (PyCFunction) _wrap_SpatialReference_SetGH, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetGH(SpatialReference self, double cm, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetIGH", _wrap_SpatialReference_SetIGH, METH_VARARGS, (char *)"SpatialReference_SetIGH(SpatialReference self) -> OGRErr"},
-	 { (char *)"SpatialReference_SetGEOS", (PyCFunction) _wrap_SpatialReference_SetGEOS, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetGEOS(SpatialReference self, double cm, double satelliteheight, \n"
-		"    double fe, double fn) -> OGRErr\n"
-		""},
-	 { (char *)"SpatialReference_SetGnomonic", (PyCFunction) _wrap_SpatialReference_SetGnomonic, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetGnomonic(SpatialReference self, double clat, double clong, double fe, \n"
-		"    double fn) -> OGRErr\n"
-		""},
+	 { (char *)"SpatialReference_SetGEOS", (PyCFunction) _wrap_SpatialReference_SetGEOS, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetGEOS(SpatialReference self, double cm, double satelliteheight, double fe, double fn) -> OGRErr"},
+	 { (char *)"SpatialReference_SetGnomonic", (PyCFunction) _wrap_SpatialReference_SetGnomonic, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetGnomonic(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetHOM", (PyCFunction) _wrap_SpatialReference_SetHOM, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetHOM(SpatialReference self, double clat, double clong, double azimuth, \n"
-		"    double recttoskew, double scale, \n"
-		"    double fe, double fn) -> OGRErr\n"
+		"SpatialReference_SetHOM(SpatialReference self, double clat, double clong, double azimuth, double recttoskew, \n"
+		"    double scale, double fe, double fn) -> OGRErr\n"
 		""},
 	 { (char *)"SpatialReference_SetHOM2PNO", (PyCFunction) _wrap_SpatialReference_SetHOM2PNO, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetHOM2PNO(SpatialReference self, double clat, double dfLat1, \n"
-		"    double dfLong1, double dfLat2, double dfLong2, \n"
-		"    double scale, double fe, double fn) -> OGRErr\n"
+		"SpatialReference_SetHOM2PNO(SpatialReference self, double clat, double dfLat1, double dfLong1, double dfLat2, \n"
+		"    double dfLong2, double scale, double fe, double fn) -> OGRErr\n"
 		""},
 	 { (char *)"SpatialReference_SetKrovak", (PyCFunction) _wrap_SpatialReference_SetKrovak, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetKrovak(SpatialReference self, double clat, double clong, double azimuth, \n"
-		"    double pseudostdparallellat, double scale, \n"
-		"    double fe, double fn) -> OGRErr\n"
-		""},
-	 { (char *)"SpatialReference_SetLAEA", (PyCFunction) _wrap_SpatialReference_SetLAEA, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetLAEA(SpatialReference self, double clat, double clong, double fe, \n"
-		"    double fn) -> OGRErr\n"
+		"SpatialReference_SetKrovak(SpatialReference self, double clat, double clong, double azimuth, double pseudostdparallellat, \n"
+		"    double scale, double fe, double fn) -> OGRErr\n"
 		""},
+	 { (char *)"SpatialReference_SetLAEA", (PyCFunction) _wrap_SpatialReference_SetLAEA, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetLAEA(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetLCC", (PyCFunction) _wrap_SpatialReference_SetLCC, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetLCC(SpatialReference self, double stdp1, double stdp2, \n"
-		"    double clat, double clong, double fe, double fn) -> OGRErr\n"
-		""},
-	 { (char *)"SpatialReference_SetLCC1SP", (PyCFunction) _wrap_SpatialReference_SetLCC1SP, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetLCC1SP(SpatialReference self, double clat, double clong, double scale, \n"
-		"    double fe, double fn) -> OGRErr\n"
+		"SpatialReference_SetLCC(SpatialReference self, double stdp1, double stdp2, double clat, double clong, double fe, \n"
+		"    double fn) -> OGRErr\n"
 		""},
+	 { (char *)"SpatialReference_SetLCC1SP", (PyCFunction) _wrap_SpatialReference_SetLCC1SP, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetLCC1SP(SpatialReference self, double clat, double clong, double scale, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetLCCB", (PyCFunction) _wrap_SpatialReference_SetLCCB, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetLCCB(SpatialReference self, double stdp1, double stdp2, \n"
-		"    double clat, double clong, double fe, double fn) -> OGRErr\n"
-		""},
-	 { (char *)"SpatialReference_SetMC", (PyCFunction) _wrap_SpatialReference_SetMC, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetMC(SpatialReference self, double clat, double clong, double fe, \n"
+		"SpatialReference_SetLCCB(SpatialReference self, double stdp1, double stdp2, double clat, double clong, double fe, \n"
 		"    double fn) -> OGRErr\n"
 		""},
-	 { (char *)"SpatialReference_SetMercator", (PyCFunction) _wrap_SpatialReference_SetMercator, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetMercator(SpatialReference self, double clat, double clong, double scale, \n"
-		"    double fe, double fn) -> OGRErr\n"
-		""},
+	 { (char *)"SpatialReference_SetMC", (PyCFunction) _wrap_SpatialReference_SetMC, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetMC(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"},
+	 { (char *)"SpatialReference_SetMercator", (PyCFunction) _wrap_SpatialReference_SetMercator, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetMercator(SpatialReference self, double clat, double clong, double scale, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetMollweide", (PyCFunction) _wrap_SpatialReference_SetMollweide, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetMollweide(SpatialReference self, double cm, double fe, double fn) -> OGRErr"},
-	 { (char *)"SpatialReference_SetNZMG", (PyCFunction) _wrap_SpatialReference_SetNZMG, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetNZMG(SpatialReference self, double clat, double clong, double fe, \n"
-		"    double fn) -> OGRErr\n"
-		""},
+	 { (char *)"SpatialReference_SetNZMG", (PyCFunction) _wrap_SpatialReference_SetNZMG, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetNZMG(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetOS", (PyCFunction) _wrap_SpatialReference_SetOS, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetOS(SpatialReference self, double dfOriginLat, double dfCMeridian, \n"
-		"    double scale, double fe, double fn) -> OGRErr\n"
-		""},
-	 { (char *)"SpatialReference_SetOrthographic", (PyCFunction) _wrap_SpatialReference_SetOrthographic, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetOrthographic(SpatialReference self, double clat, double clong, double fe, \n"
-		"    double fn) -> OGRErr\n"
-		""},
-	 { (char *)"SpatialReference_SetPolyconic", (PyCFunction) _wrap_SpatialReference_SetPolyconic, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetPolyconic(SpatialReference self, double clat, double clong, double fe, \n"
+		"SpatialReference_SetOS(SpatialReference self, double dfOriginLat, double dfCMeridian, double scale, double fe, \n"
 		"    double fn) -> OGRErr\n"
 		""},
-	 { (char *)"SpatialReference_SetPS", (PyCFunction) _wrap_SpatialReference_SetPS, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetPS(SpatialReference self, double clat, double clong, double scale, \n"
-		"    double fe, double fn) -> OGRErr\n"
-		""},
+	 { (char *)"SpatialReference_SetOrthographic", (PyCFunction) _wrap_SpatialReference_SetOrthographic, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetOrthographic(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"},
+	 { (char *)"SpatialReference_SetPolyconic", (PyCFunction) _wrap_SpatialReference_SetPolyconic, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetPolyconic(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"},
+	 { (char *)"SpatialReference_SetPS", (PyCFunction) _wrap_SpatialReference_SetPS, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetPS(SpatialReference self, double clat, double clong, double scale, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetRobinson", (PyCFunction) _wrap_SpatialReference_SetRobinson, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetRobinson(SpatialReference self, double clong, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetSinusoidal", (PyCFunction) _wrap_SpatialReference_SetSinusoidal, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetSinusoidal(SpatialReference self, double clong, double fe, double fn) -> OGRErr"},
-	 { (char *)"SpatialReference_SetStereographic", (PyCFunction) _wrap_SpatialReference_SetStereographic, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetStereographic(SpatialReference self, double clat, double clong, double scale, \n"
-		"    double fe, double fn) -> OGRErr\n"
-		""},
-	 { (char *)"SpatialReference_SetSOC", (PyCFunction) _wrap_SpatialReference_SetSOC, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetSOC(SpatialReference self, double latitudeoforigin, double cm, \n"
-		"    double fe, double fn) -> OGRErr\n"
-		""},
-	 { (char *)"SpatialReference_SetTM", (PyCFunction) _wrap_SpatialReference_SetTM, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetTM(SpatialReference self, double clat, double clong, double scale, \n"
-		"    double fe, double fn) -> OGRErr\n"
-		""},
+	 { (char *)"SpatialReference_SetStereographic", (PyCFunction) _wrap_SpatialReference_SetStereographic, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetStereographic(SpatialReference self, double clat, double clong, double scale, double fe, double fn) -> OGRErr"},
+	 { (char *)"SpatialReference_SetSOC", (PyCFunction) _wrap_SpatialReference_SetSOC, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetSOC(SpatialReference self, double latitudeoforigin, double cm, double fe, double fn) -> OGRErr"},
+	 { (char *)"SpatialReference_SetTM", (PyCFunction) _wrap_SpatialReference_SetTM, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetTM(SpatialReference self, double clat, double clong, double scale, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetTMVariant", (PyCFunction) _wrap_SpatialReference_SetTMVariant, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetTMVariant(SpatialReference self, char pszVariantName, double clat, \n"
-		"    double clong, double scale, double fe, \n"
-		"    double fn) -> OGRErr\n"
-		""},
-	 { (char *)"SpatialReference_SetTMG", (PyCFunction) _wrap_SpatialReference_SetTMG, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetTMG(SpatialReference self, double clat, double clong, double fe, \n"
-		"    double fn) -> OGRErr\n"
-		""},
-	 { (char *)"SpatialReference_SetTMSO", (PyCFunction) _wrap_SpatialReference_SetTMSO, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetTMSO(SpatialReference self, double clat, double clong, double scale, \n"
+		"SpatialReference_SetTMVariant(SpatialReference self, char const * pszVariantName, double clat, double clong, double scale, \n"
 		"    double fe, double fn) -> OGRErr\n"
 		""},
+	 { (char *)"SpatialReference_SetTMG", (PyCFunction) _wrap_SpatialReference_SetTMG, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetTMG(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"},
+	 { (char *)"SpatialReference_SetTMSO", (PyCFunction) _wrap_SpatialReference_SetTMSO, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetTMSO(SpatialReference self, double clat, double clong, double scale, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetVDG", (PyCFunction) _wrap_SpatialReference_SetVDG, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetVDG(SpatialReference self, double clong, double fe, double fn) -> OGRErr"},
-	 { (char *)"SpatialReference_SetWellKnownGeogCS", _wrap_SpatialReference_SetWellKnownGeogCS, METH_VARARGS, (char *)"SpatialReference_SetWellKnownGeogCS(SpatialReference self, char name) -> OGRErr"},
-	 { (char *)"SpatialReference_SetFromUserInput", _wrap_SpatialReference_SetFromUserInput, METH_VARARGS, (char *)"SpatialReference_SetFromUserInput(SpatialReference self, char name) -> OGRErr"},
+	 { (char *)"SpatialReference_SetWellKnownGeogCS", _wrap_SpatialReference_SetWellKnownGeogCS, METH_VARARGS, (char *)"SpatialReference_SetWellKnownGeogCS(SpatialReference self, char const * name) -> OGRErr"},
+	 { (char *)"SpatialReference_SetFromUserInput", _wrap_SpatialReference_SetFromUserInput, METH_VARARGS, (char *)"SpatialReference_SetFromUserInput(SpatialReference self, char const * name) -> OGRErr"},
 	 { (char *)"SpatialReference_CopyGeogCSFrom", _wrap_SpatialReference_CopyGeogCSFrom, METH_VARARGS, (char *)"SpatialReference_CopyGeogCSFrom(SpatialReference self, SpatialReference rhs) -> OGRErr"},
 	 { (char *)"SpatialReference_SetTOWGS84", _wrap_SpatialReference_SetTOWGS84, METH_VARARGS, (char *)"\n"
-		"SpatialReference_SetTOWGS84(SpatialReference self, double p1, double p2, double p3, \n"
-		"    double p4 = 0.0, double p5 = 0.0, double p6 = 0.0, \n"
-		"    double p7 = 0.0) -> OGRErr\n"
+		"SpatialReference_SetTOWGS84(SpatialReference self, double p1, double p2, double p3, double p4=0.0, double p5=0.0, \n"
+		"    double p6=0.0, double p7=0.0) -> OGRErr\n"
 		""},
 	 { (char *)"SpatialReference_GetTOWGS84", _wrap_SpatialReference_GetTOWGS84, METH_VARARGS, (char *)"SpatialReference_GetTOWGS84(SpatialReference self) -> OGRErr"},
-	 { (char *)"SpatialReference_SetLocalCS", _wrap_SpatialReference_SetLocalCS, METH_VARARGS, (char *)"SpatialReference_SetLocalCS(SpatialReference self, char pszName) -> OGRErr"},
+	 { (char *)"SpatialReference_SetLocalCS", _wrap_SpatialReference_SetLocalCS, METH_VARARGS, (char *)"SpatialReference_SetLocalCS(SpatialReference self, char const * pszName) -> OGRErr"},
 	 { (char *)"SpatialReference_SetGeogCS", _wrap_SpatialReference_SetGeogCS, METH_VARARGS, (char *)"\n"
-		"SpatialReference_SetGeogCS(SpatialReference self, char pszGeogName, char pszDatumName, \n"
-		"    char pszEllipsoidName, double dfSemiMajor, \n"
-		"    double dfInvFlattening, char pszPMName = \"Greenwich\", \n"
-		"    double dfPMOffset = 0.0, char pszUnits = \"degree\", \n"
-		"    double dfConvertToRadians = 0.0174532925199433) -> OGRErr\n"
+		"SpatialReference_SetGeogCS(SpatialReference self, char const * pszGeogName, char const * pszDatumName, char const * pszEllipsoidName, \n"
+		"    double dfSemiMajor, double dfInvFlattening, char const * pszPMName=\"Greenwich\", \n"
+		"    double dfPMOffset=0.0, char const * pszUnits=\"degree\", \n"
+		"    double dfConvertToRadians=0.0174532925199433) -> OGRErr\n"
 		""},
-	 { (char *)"SpatialReference_SetProjCS", _wrap_SpatialReference_SetProjCS, METH_VARARGS, (char *)"SpatialReference_SetProjCS(SpatialReference self, char name = \"unnamed\") -> OGRErr"},
-	 { (char *)"SpatialReference_SetGeocCS", _wrap_SpatialReference_SetGeocCS, METH_VARARGS, (char *)"SpatialReference_SetGeocCS(SpatialReference self, char name = \"unnamed\") -> OGRErr"},
+	 { (char *)"SpatialReference_SetProjCS", _wrap_SpatialReference_SetProjCS, METH_VARARGS, (char *)"SpatialReference_SetProjCS(SpatialReference self, char const * name=\"unnamed\") -> OGRErr"},
+	 { (char *)"SpatialReference_SetGeocCS", _wrap_SpatialReference_SetGeocCS, METH_VARARGS, (char *)"SpatialReference_SetGeocCS(SpatialReference self, char const * name=\"unnamed\") -> OGRErr"},
 	 { (char *)"SpatialReference_SetVertCS", _wrap_SpatialReference_SetVertCS, METH_VARARGS, (char *)"\n"
-		"SpatialReference_SetVertCS(SpatialReference self, char VertCSName = \"unnamed\", \n"
-		"    char VertDatumName = \"unnamed\", int VertDatumType = 0) -> OGRErr\n"
-		""},
-	 { (char *)"SpatialReference_SetCompoundCS", _wrap_SpatialReference_SetCompoundCS, METH_VARARGS, (char *)"\n"
-		"SpatialReference_SetCompoundCS(SpatialReference self, char name, SpatialReference horizcs, \n"
-		"    SpatialReference vertcs) -> OGRErr\n"
+		"SpatialReference_SetVertCS(SpatialReference self, char const * VertCSName=\"unnamed\", char const * VertDatumName=\"unnamed\", \n"
+		"    int VertDatumType=0) -> OGRErr\n"
 		""},
-	 { (char *)"SpatialReference_ImportFromWkt", _wrap_SpatialReference_ImportFromWkt, METH_VARARGS, (char *)"SpatialReference_ImportFromWkt(SpatialReference self, char ppszInput) -> OGRErr"},
-	 { (char *)"SpatialReference_ImportFromProj4", _wrap_SpatialReference_ImportFromProj4, METH_VARARGS, (char *)"SpatialReference_ImportFromProj4(SpatialReference self, char ppszInput) -> OGRErr"},
-	 { (char *)"SpatialReference_ImportFromUrl", _wrap_SpatialReference_ImportFromUrl, METH_VARARGS, (char *)"SpatialReference_ImportFromUrl(SpatialReference self, char url) -> OGRErr"},
-	 { (char *)"SpatialReference_ImportFromESRI", _wrap_SpatialReference_ImportFromESRI, METH_VARARGS, (char *)"SpatialReference_ImportFromESRI(SpatialReference self, char ppszInput) -> OGRErr"},
+	 { (char *)"SpatialReference_SetCompoundCS", _wrap_SpatialReference_SetCompoundCS, METH_VARARGS, (char *)"SpatialReference_SetCompoundCS(SpatialReference self, char const * name, SpatialReference horizcs, SpatialReference vertcs) -> OGRErr"},
+	 { (char *)"SpatialReference_ImportFromWkt", _wrap_SpatialReference_ImportFromWkt, METH_VARARGS, (char *)"SpatialReference_ImportFromWkt(SpatialReference self, char ** ppszInput) -> OGRErr"},
+	 { (char *)"SpatialReference_ImportFromProj4", _wrap_SpatialReference_ImportFromProj4, METH_VARARGS, (char *)"SpatialReference_ImportFromProj4(SpatialReference self, char * ppszInput) -> OGRErr"},
+	 { (char *)"SpatialReference_ImportFromUrl", _wrap_SpatialReference_ImportFromUrl, METH_VARARGS, (char *)"SpatialReference_ImportFromUrl(SpatialReference self, char * url) -> OGRErr"},
+	 { (char *)"SpatialReference_ImportFromESRI", _wrap_SpatialReference_ImportFromESRI, METH_VARARGS, (char *)"SpatialReference_ImportFromESRI(SpatialReference self, char ** ppszInput) -> OGRErr"},
 	 { (char *)"SpatialReference_ImportFromEPSG", _wrap_SpatialReference_ImportFromEPSG, METH_VARARGS, (char *)"SpatialReference_ImportFromEPSG(SpatialReference self, int arg) -> OGRErr"},
 	 { (char *)"SpatialReference_ImportFromEPSGA", _wrap_SpatialReference_ImportFromEPSGA, METH_VARARGS, (char *)"SpatialReference_ImportFromEPSGA(SpatialReference self, int arg) -> OGRErr"},
-	 { (char *)"SpatialReference_ImportFromPCI", _wrap_SpatialReference_ImportFromPCI, METH_VARARGS, (char *)"\n"
-		"SpatialReference_ImportFromPCI(SpatialReference self, char proj, char units = \"METRE\", \n"
-		"    double argin = 0) -> OGRErr\n"
-		""},
-	 { (char *)"SpatialReference_ImportFromUSGS", _wrap_SpatialReference_ImportFromUSGS, METH_VARARGS, (char *)"\n"
-		"SpatialReference_ImportFromUSGS(SpatialReference self, long proj_code, long zone = 0, \n"
-		"    double argin = 0, long datum_code = 0) -> OGRErr\n"
-		""},
-	 { (char *)"SpatialReference_ImportFromXML", _wrap_SpatialReference_ImportFromXML, METH_VARARGS, (char *)"SpatialReference_ImportFromXML(SpatialReference self, char xmlString) -> OGRErr"},
-	 { (char *)"SpatialReference_ImportFromERM", _wrap_SpatialReference_ImportFromERM, METH_VARARGS, (char *)"SpatialReference_ImportFromERM(SpatialReference self, char proj, char datum, char units) -> OGRErr"},
-	 { (char *)"SpatialReference_ImportFromMICoordSys", _wrap_SpatialReference_ImportFromMICoordSys, METH_VARARGS, (char *)"SpatialReference_ImportFromMICoordSys(SpatialReference self, char pszCoordSys) -> OGRErr"},
-	 { (char *)"SpatialReference_ImportFromOzi", _wrap_SpatialReference_ImportFromOzi, METH_VARARGS, (char *)"SpatialReference_ImportFromOzi(SpatialReference self, char papszLines) -> OGRErr"},
+	 { (char *)"SpatialReference_ImportFromPCI", _wrap_SpatialReference_ImportFromPCI, METH_VARARGS, (char *)"SpatialReference_ImportFromPCI(SpatialReference self, char const * proj, char const * units=\"METRE\", double [17] argin=0) -> OGRErr"},
+	 { (char *)"SpatialReference_ImportFromUSGS", _wrap_SpatialReference_ImportFromUSGS, METH_VARARGS, (char *)"SpatialReference_ImportFromUSGS(SpatialReference self, long proj_code, long zone=0, double [15] argin=0, long datum_code=0) -> OGRErr"},
+	 { (char *)"SpatialReference_ImportFromXML", _wrap_SpatialReference_ImportFromXML, METH_VARARGS, (char *)"SpatialReference_ImportFromXML(SpatialReference self, char const * xmlString) -> OGRErr"},
+	 { (char *)"SpatialReference_ImportFromERM", _wrap_SpatialReference_ImportFromERM, METH_VARARGS, (char *)"SpatialReference_ImportFromERM(SpatialReference self, char const * proj, char const * datum, char const * units) -> OGRErr"},
+	 { (char *)"SpatialReference_ImportFromMICoordSys", _wrap_SpatialReference_ImportFromMICoordSys, METH_VARARGS, (char *)"SpatialReference_ImportFromMICoordSys(SpatialReference self, char const * pszCoordSys) -> OGRErr"},
+	 { (char *)"SpatialReference_ImportFromOzi", _wrap_SpatialReference_ImportFromOzi, METH_VARARGS, (char *)"SpatialReference_ImportFromOzi(SpatialReference self, char const *const * papszLines) -> OGRErr"},
 	 { (char *)"SpatialReference_ExportToWkt", _wrap_SpatialReference_ExportToWkt, METH_VARARGS, (char *)"SpatialReference_ExportToWkt(SpatialReference self) -> OGRErr"},
-	 { (char *)"SpatialReference_ExportToPrettyWkt", _wrap_SpatialReference_ExportToPrettyWkt, METH_VARARGS, (char *)"SpatialReference_ExportToPrettyWkt(SpatialReference self, int simplify = 0) -> OGRErr"},
+	 { (char *)"SpatialReference_ExportToPrettyWkt", _wrap_SpatialReference_ExportToPrettyWkt, METH_VARARGS, (char *)"SpatialReference_ExportToPrettyWkt(SpatialReference self, int simplify=0) -> OGRErr"},
 	 { (char *)"SpatialReference_ExportToProj4", _wrap_SpatialReference_ExportToProj4, METH_VARARGS, (char *)"SpatialReference_ExportToProj4(SpatialReference self) -> OGRErr"},
 	 { (char *)"SpatialReference_ExportToPCI", _wrap_SpatialReference_ExportToPCI, METH_VARARGS, (char *)"SpatialReference_ExportToPCI(SpatialReference self) -> OGRErr"},
 	 { (char *)"SpatialReference_ExportToUSGS", _wrap_SpatialReference_ExportToUSGS, METH_VARARGS, (char *)"SpatialReference_ExportToUSGS(SpatialReference self) -> OGRErr"},
-	 { (char *)"SpatialReference_ExportToXML", _wrap_SpatialReference_ExportToXML, METH_VARARGS, (char *)"SpatialReference_ExportToXML(SpatialReference self, char dialect = \"\") -> OGRErr"},
+	 { (char *)"SpatialReference_ExportToXML", _wrap_SpatialReference_ExportToXML, METH_VARARGS, (char *)"SpatialReference_ExportToXML(SpatialReference self, char const * dialect=\"\") -> OGRErr"},
 	 { (char *)"SpatialReference_ExportToMICoordSys", _wrap_SpatialReference_ExportToMICoordSys, METH_VARARGS, (char *)"SpatialReference_ExportToMICoordSys(SpatialReference self) -> OGRErr"},
 	 { (char *)"SpatialReference_CloneGeogCS", _wrap_SpatialReference_CloneGeogCS, METH_VARARGS, (char *)"SpatialReference_CloneGeogCS(SpatialReference self) -> SpatialReference"},
 	 { (char *)"SpatialReference_Clone", _wrap_SpatialReference_Clone, METH_VARARGS, (char *)"SpatialReference_Clone(SpatialReference self) -> SpatialReference"},
@@ -13197,9 +13388,8 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"new_CoordinateTransformation", _wrap_new_CoordinateTransformation, METH_VARARGS, (char *)"new_CoordinateTransformation(SpatialReference src, SpatialReference dst) -> CoordinateTransformation"},
 	 { (char *)"delete_CoordinateTransformation", _wrap_delete_CoordinateTransformation, METH_VARARGS, (char *)"delete_CoordinateTransformation(CoordinateTransformation self)"},
 	 { (char *)"CoordinateTransformation_TransformPoint", _wrap_CoordinateTransformation_TransformPoint, METH_VARARGS, (char *)"\n"
-		"TransformPoint(double inout)\n"
-		"CoordinateTransformation_TransformPoint(CoordinateTransformation self, double x, double y, \n"
-		"    double z = 0.0)\n"
+		"TransformPoint(double [3] inout)\n"
+		"CoordinateTransformation_TransformPoint(CoordinateTransformation self, double x, double y, double z=0.0)\n"
 		""},
 	 { (char *)"CoordinateTransformation_TransformPoints", _wrap_CoordinateTransformation_TransformPoints, METH_VARARGS, (char *)"CoordinateTransformation_TransformPoints(CoordinateTransformation self, int nCount)"},
 	 { (char *)"CoordinateTransformation_swigregister", CoordinateTransformation_swigregister, METH_VARARGS, NULL},
@@ -13261,18 +13451,18 @@ static swig_const_info swig_const_table[] = {
 #endif
 /* -----------------------------------------------------------------------------
  * Type initialization:
- * This problem is tough by the requirement that no dynamic 
- * memory is used. Also, since swig_type_info structures store pointers to 
+ * This problem is tough by the requirement that no dynamic
+ * memory is used. Also, since swig_type_info structures store pointers to
  * swig_cast_info structures and swig_cast_info structures store pointers back
- * to swig_type_info structures, we need some lookup code at initialization. 
- * The idea is that swig generates all the structures that are needed. 
- * The runtime then collects these partially filled structures. 
- * The SWIG_InitializeModule function takes these initial arrays out of 
+ * to swig_type_info structures, we need some lookup code at initialization.
+ * The idea is that swig generates all the structures that are needed.
+ * The runtime then collects these partially filled structures.
+ * The SWIG_InitializeModule function takes these initial arrays out of
  * swig_module, and does all the lookup, filling in the swig_module.types
  * array with the correct data and linking the correct swig_cast_info
  * structures together.
  *
- * The generated swig_type_info structures are assigned staticly to an initial 
+ * The generated swig_type_info structures are assigned staticly to an initial
  * array. We just loop through that array, and handle each type individually.
  * First we lookup if this type has been already loaded, and if so, use the
  * loaded structure instead of the generated one. Then we have to fill in the
@@ -13282,17 +13472,17 @@ static swig_const_info swig_const_table[] = {
  * a column is one of the swig_cast_info structures for that type.
  * The cast_initial array is actually an array of arrays, because each row has
  * a variable number of columns. So to actually build the cast linked list,
- * we find the array of casts associated with the type, and loop through it 
+ * we find the array of casts associated with the type, and loop through it
  * adding the casts to the list. The one last trick we need to do is making
  * sure the type pointer in the swig_cast_info struct is correct.
  *
- * First off, we lookup the cast->type name to see if it is already loaded. 
+ * First off, we lookup the cast->type name to see if it is already loaded.
  * There are three cases to handle:
  *  1) If the cast->type has already been loaded AND the type we are adding
  *     casting info to has not been loaded (it is in this module), THEN we
  *     replace the cast->type pointer with the type pointer that has already
  *     been loaded.
- *  2) If BOTH types (the one we are adding casting info to, and the 
+ *  2) If BOTH types (the one we are adding casting info to, and the
  *     cast->type) are loaded, THEN the cast info has already been loaded by
  *     the previous module so we just ignore it.
  *  3) Finally, if cast->type has not already been loaded, then we add that
@@ -13318,8 +13508,6 @@ SWIG_InitializeModule(void *clientdata) {
   swig_module_info *module_head, *iter;
   int found, init;
   
-  clientdata = clientdata;
-  
   /* check to see if the circular list has been setup, if not, set it up */
   if (swig_module.next==0) {
     /* Initialize the swig_module */
@@ -13337,7 +13525,7 @@ SWIG_InitializeModule(void *clientdata) {
     /* This is the first module loaded for this interpreter */
     /* so set the swig module into the interpreter */
     SWIG_SetModule(clientdata, &swig_module);
-    module_head = &swig_module;
+    /*module_head = &swig_module;*/
   } else {
     /* the interpreter has loaded a SWIG module, but has it loaded this one? */
     found=0;
@@ -13357,7 +13545,7 @@ SWIG_InitializeModule(void *clientdata) {
     module_head->next = &swig_module;
   }
   
-  /* When multiple interpeters are used, a module could have already been initialized in
+  /* When multiple interpreters are used, a module could have already been initialized in
        a different interpreter, but not yet have a pointer in this interpreter.
        In this case, we do not want to continue adding types... everything should be
        set up already */
@@ -13630,24 +13818,23 @@ extern "C" {
   swig_varlink_type(void) {
     static char varlink__doc__[] = "Swig var link object";
     static PyTypeObject varlink_type;
-    static int type_init = 0;  
+    static int type_init = 0;
     if (!type_init) {
-      const PyTypeObject tmp
-      = {
+      const PyTypeObject tmp = {
         /* PyObject header changed in Python 3 */
 #if PY_VERSION_HEX >= 0x03000000
-        PyVarObject_HEAD_INIT(&PyType_Type, 0)
+        PyVarObject_HEAD_INIT(NULL, 0)
 #else
         PyObject_HEAD_INIT(NULL)
-        0,                                  /* Number of items in variable part (ob_size) */
-#endif
-        (char *)"swigvarlink",              /* Type name (tp_name) */
-        sizeof(swig_varlinkobject),         /* Basic size (tp_basicsize) */
-        0,                                  /* Itemsize (tp_itemsize) */
-        (destructor) swig_varlink_dealloc,  /* Deallocator (tp_dealloc) */ 
-        (printfunc) swig_varlink_print,     /* Print (tp_print) */
-        (getattrfunc) swig_varlink_getattr, /* get attr (tp_getattr) */
-        (setattrfunc) swig_varlink_setattr, /* Set attr (tp_setattr) */
+        0,                                  /* ob_size */
+#endif
+        (char *)"swigvarlink",              /* tp_name */
+        sizeof(swig_varlinkobject),         /* tp_basicsize */
+        0,                                  /* tp_itemsize */
+        (destructor) swig_varlink_dealloc,  /* tp_dealloc */
+        (printfunc) swig_varlink_print,     /* tp_print */
+        (getattrfunc) swig_varlink_getattr, /* tp_getattr */
+        (setattrfunc) swig_varlink_setattr, /* tp_setattr */
         0,                                  /* tp_compare */
         (reprfunc) swig_varlink_repr,       /* tp_repr */
         0,                                  /* tp_as_number */
@@ -13671,16 +13858,21 @@ extern "C" {
 #if PY_VERSION_HEX >= 0x02030000
         0,                                  /* tp_del */
 #endif
+#if PY_VERSION_HEX >= 0x02060000
+        0,                                  /* tp_version */
+#endif
 #ifdef COUNT_ALLOCS
         0,0,0,0                             /* tp_alloc -> tp_next */
 #endif
       };
       varlink_type = tmp;
-      /* for Python 3 we already assigned ob_type in PyVarObject_HEAD_INIT() */
-#if PY_VERSION_HEX < 0x03000000
+      type_init = 1;
+#if PY_VERSION_HEX < 0x02020000
       varlink_type.ob_type = &PyType_Type;
+#else
+      if (PyType_Ready(&varlink_type) < 0)
+      return NULL;
 #endif
-      type_init = 1;
     }
     return &varlink_type;
   }
@@ -13731,7 +13923,7 @@ extern "C" {
     for (i = 0; constants[i].type; ++i) {
       switch(constants[i].type) {
       case SWIG_PY_POINTER:
-        obj = SWIG_NewPointerObj(constants[i].pvalue, *(constants[i]).ptype,0);
+        obj = SWIG_InternalNewPointerObj(constants[i].pvalue, *(constants[i]).ptype,0);
         break;
       case SWIG_PY_BINARY:
         obj = SWIG_NewPackedObj(constants[i].pvalue, constants[i].lvalue, *(constants[i].ptype));
@@ -13771,18 +13963,18 @@ extern "C" {
           }
         }
         if (ci) {
-          size_t shift = (ci->ptype) - types;
-          swig_type_info *ty = types_initial[shift];
-          size_t ldoc = (c - methods[i].ml_doc);
-          size_t lptr = strlen(ty->name)+2*sizeof(void*)+2;
-          char *ndoc = (char*)malloc(ldoc + lptr + 10);
-          if (ndoc) {
-            char *buff = ndoc;
-            void *ptr = (ci->type == SWIG_PY_POINTER) ? ci->pvalue : 0;
-            if (ptr) {
+          void *ptr = (ci->type == SWIG_PY_POINTER) ? ci->pvalue : 0;
+          if (ptr) {
+            size_t shift = (ci->ptype) - types;
+            swig_type_info *ty = types_initial[shift];
+            size_t ldoc = (c - methods[i].ml_doc);
+            size_t lptr = strlen(ty->name)+2*sizeof(void*)+2;
+            char *ndoc = (char*)malloc(ldoc + lptr + 10);
+            if (ndoc) {
+              char *buff = ndoc;
               strncpy(buff, methods[i].ml_doc, ldoc);
               buff += ldoc;
-              strncpy(buff, "swig_ptr: ", 10);
+              memcpy(buff, "swig_ptr: ", 10);
               buff += 10;
               SWIG_PackVoidPtr(buff, ptr, ty->name, lptr);
               methods[i].ml_doc = ndoc;
@@ -13812,10 +14004,19 @@ PyObject*
 void
 #endif
 SWIG_init(void) {
-  PyObject *m, *d;  
+  PyObject *m, *d, *md;
 #if PY_VERSION_HEX >= 0x03000000
   static struct PyModuleDef SWIG_module = {
+# if PY_VERSION_HEX >= 0x03020000
     PyModuleDef_HEAD_INIT,
+# else
+    {
+      PyObject_HEAD_INIT(NULL)
+      NULL, /* m_init */
+      0,    /* m_index */
+      NULL, /* m_copy */
+    },
+# endif
     (char *) SWIG_name,
     NULL,
     -1,
@@ -13827,6 +14028,49 @@ SWIG_init(void) {
   };
 #endif
   
+#if defined(SWIGPYTHON_BUILTIN)
+  static SwigPyClientData SwigPyObject_clientdata = {
+    0, 0, 0, 0, 0, 0, 0
+  };
+  static PyGetSetDef this_getset_def = {
+    (char *)"this", &SwigPyBuiltin_ThisClosure, NULL, NULL, NULL
+  };
+  static SwigPyGetSet thisown_getset_closure = {
+    (PyCFunction) SwigPyObject_own,
+    (PyCFunction) SwigPyObject_own
+  };
+  static PyGetSetDef thisown_getset_def = {
+    (char *)"thisown", SwigPyBuiltin_GetterClosure, SwigPyBuiltin_SetterClosure, NULL, &thisown_getset_closure
+  };
+  PyObject *metatype_args;
+  PyTypeObject *builtin_pytype;
+  int builtin_base_count;
+  swig_type_info *builtin_basetype;
+  PyObject *tuple;
+  PyGetSetDescrObject *static_getset;
+  PyTypeObject *metatype;
+  SwigPyClientData *cd;
+  PyObject *public_interface, *public_symbol;
+  PyObject *this_descr;
+  PyObject *thisown_descr;
+  int i;
+  
+  (void)builtin_pytype;
+  (void)builtin_base_count;
+  (void)builtin_basetype;
+  (void)tuple;
+  (void)static_getset;
+  
+  /* metatype is used to implement static member variables. */
+  metatype_args = Py_BuildValue("(s(O){})", "SwigPyObjectType", &PyType_Type);
+  assert(metatype_args);
+  metatype = (PyTypeObject *) PyType_Type.tp_call((PyObject *) &PyType_Type, metatype_args, NULL);
+  assert(metatype);
+  Py_DECREF(metatype_args);
+  metatype->tp_setattro = (setattrofunc) &SwigPyObjectType_setattro;
+  assert(PyType_Ready(metatype) >= 0);
+#endif
+  
   /* Fix SwigMethods to carry the callback ptrs when needed */
   SWIG_Python_FixMethods(SwigMethods, swig_const_table, swig_types, swig_type_initial);
   
@@ -13835,13 +14079,50 @@ SWIG_init(void) {
 #else
   m = Py_InitModule((char *) SWIG_name, SwigMethods);
 #endif
-  d = PyModule_GetDict(m);
+  md = d = PyModule_GetDict(m);
+  (void)md;
   
   SWIG_InitializeModule(0);
-  SWIG_InstallConstants(d,swig_const_table);
   
+#ifdef SWIGPYTHON_BUILTIN
+  SwigPyObject_stype = SWIG_MangledTypeQuery("_p_SwigPyObject");
+  assert(SwigPyObject_stype);
+  cd = (SwigPyClientData*) SwigPyObject_stype->clientdata;
+  if (!cd) {
+    SwigPyObject_stype->clientdata = &SwigPyObject_clientdata;
+    SwigPyObject_clientdata.pytype = SwigPyObject_TypeOnce();
+  } else if (SwigPyObject_TypeOnce()->tp_basicsize != cd->pytype->tp_basicsize) {
+    PyErr_SetString(PyExc_RuntimeError, "Import error: attempted to load two incompatible swig-generated modules.");
+# if PY_VERSION_HEX >= 0x03000000
+    return NULL;
+# else
+    return;
+# endif
+  }
+  
+  /* All objects have a 'this' attribute */
+  this_descr = PyDescr_NewGetSet(SwigPyObject_type(), &this_getset_def);
+  (void)this_descr;
+  
+  /* All objects have a 'thisown' attribute */
+  thisown_descr = PyDescr_NewGetSet(SwigPyObject_type(), &thisown_getset_def);
+  (void)thisown_descr;
+  
+  public_interface = PyList_New(0);
+  public_symbol = 0;
+  (void)public_symbol;
+  
+  PyDict_SetItemString(md, "__all__", public_interface);
+  Py_DECREF(public_interface);
+  for (i = 0; SwigMethods[i].ml_name != NULL; ++i)
+  SwigPyBuiltin_AddPublicSymbol(public_interface, SwigMethods[i].ml_name);
+  for (i = 0; swig_const_table[i].name != 0; ++i)
+  SwigPyBuiltin_AddPublicSymbol(public_interface, swig_const_table[i].name);
+#endif
+  
+  SWIG_InstallConstants(d,swig_const_table);
   
-  SWIG_Python_SetConstant(d, "SRS_WKT_WGS84",SWIG_FromCharPtr("GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9108\"]],AUTHORITY[\"EPSG\",\"4326\"]]"));
+  SWIG_Python_SetConstant(d, "SRS_WKT_WGS84",SWIG_FromCharPtr("GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]]"));
   SWIG_Python_SetConstant(d, "SRS_PT_ALBERS_CONIC_EQUAL_AREA",SWIG_FromCharPtr("Albers_Conic_Equal_Area"));
   SWIG_Python_SetConstant(d, "SRS_PT_AZIMUTHAL_EQUIDISTANT",SWIG_FromCharPtr("Azimuthal_Equidistant"));
   SWIG_Python_SetConstant(d, "SRS_PT_CASSINI_SOLDNER",SWIG_FromCharPtr("Cassini_Soldner"));
@@ -13910,6 +14191,7 @@ SWIG_init(void) {
   SWIG_Python_SetConstant(d, "SRS_PT_CRASTER_PARABOLIC",SWIG_FromCharPtr("Craster_Parabolic"));
   SWIG_Python_SetConstant(d, "SRS_PT_LOXIMUTHAL",SWIG_FromCharPtr("Loximuthal"));
   SWIG_Python_SetConstant(d, "SRS_PT_QUARTIC_AUTHALIC",SWIG_FromCharPtr("Quartic_Authalic"));
+  SWIG_Python_SetConstant(d, "SRS_PT_SCH",SWIG_FromCharPtr("Spherical_Cross_Track_Height"));
   SWIG_Python_SetConstant(d, "SRS_PP_CENTRAL_MERIDIAN",SWIG_FromCharPtr("central_meridian"));
   SWIG_Python_SetConstant(d, "SRS_PP_SCALE_FACTOR",SWIG_FromCharPtr("scale_factor"));
   SWIG_Python_SetConstant(d, "SRS_PP_STANDARD_PARALLEL_1",SWIG_FromCharPtr("standard_parallel_1"));
@@ -13939,6 +14221,10 @@ SWIG_init(void) {
   SWIG_Python_SetConstant(d, "SRS_PP_LONGITUDE_OF_1ST_POINT",SWIG_FromCharPtr("Longitude_Of_1st_Point"));
   SWIG_Python_SetConstant(d, "SRS_PP_LATITUDE_OF_2ND_POINT",SWIG_FromCharPtr("Latitude_Of_2nd_Point"));
   SWIG_Python_SetConstant(d, "SRS_PP_LONGITUDE_OF_2ND_POINT",SWIG_FromCharPtr("Longitude_Of_2nd_Point"));
+  SWIG_Python_SetConstant(d, "SRS_PP_PEG_POINT_LATITUDE",SWIG_FromCharPtr("peg_point_latitude"));
+  SWIG_Python_SetConstant(d, "SRS_PP_PEG_POINT_LONGITUDE",SWIG_FromCharPtr("peg_point_longitude"));
+  SWIG_Python_SetConstant(d, "SRS_PP_PEG_POINT_HEADING",SWIG_FromCharPtr("peg_point_heading"));
+  SWIG_Python_SetConstant(d, "SRS_PP_PEG_POINT_HEIGHT",SWIG_FromCharPtr("peg_point_height"));
   SWIG_Python_SetConstant(d, "SRS_UL_METER",SWIG_FromCharPtr("Meter"));
   SWIG_Python_SetConstant(d, "SRS_UL_FOOT",SWIG_FromCharPtr("Foot (International)"));
   SWIG_Python_SetConstant(d, "SRS_UL_FOOT_CONV",SWIG_FromCharPtr("0.3048"));
diff --git a/swig/python/fallback_build.bat b/swig/python/fallback_build.bat
index 66fc240..2ae452f 100755
--- a/swig/python/fallback_build.bat
+++ b/swig/python/fallback_build.bat
@@ -8,7 +8,7 @@ rem
 set PYTHONHOME=C:\OSGeo4W\apps\Python25
 set OUTDIR=build\lib.win32-2.5\osgeo
 
-set CLARGS=/c /nologo /Ox /MD /EHsc /DNDEBUG -I../../port -I../../gcore -I../../alg -I../../ogr/ -I%PYTHONHOME%\include -I%PYTHONHOME%\PC -I%PYTHONHOME%\lib\site-packages\numpy\core\include
+set CLARGS=/c /nologo /Ox /MD /EHsc /DNDEBUG -I../../port -I../../gcore -I../../alg -I../../ogr/ -I../../apps/ -I%PYTHONHOME%\include -I%PYTHONHOME%\PC -I%PYTHONHOME%\lib\site-packages\numpy\core\include
 
 cl.exe %CLARGS% extensions\gdal_wrap.cpp
 cl.exe %CLARGS% extensions\osr_wrap.cpp
diff --git a/swig/python/fallback_build_mingw32_under_unix.sh b/swig/python/fallback_build_mingw32_under_unix.sh
index 443b72e..5dcdf7f 100755
--- a/swig/python/fallback_build_mingw32_under_unix.sh
+++ b/swig/python/fallback_build_mingw32_under_unix.sh
@@ -20,7 +20,7 @@ else
     HAS_NUMPY=no
 fi
 
-INCFLAGS="-I${PYTHONHOME}/include -I../../port -I../../gcore -I../../alg -I../../ogr/"
+INCFLAGS="-I${PYTHONHOME}/include -I../../port -I../../gcore -I../../alg -I../../ogr/ -I../../apps/"
 LINKFLAGS="-L../../.libs -lgdal -L${PYTHONHOME}/libs -l${PYTHONLIB}"
 CFLAGS="-O2 -D__MSVCRT_VERSION__=0x0601"
 
diff --git a/swig/python/gnm.py b/swig/python/gnm.py
new file mode 100644
index 0000000..065db15
--- /dev/null
+++ b/swig/python/gnm.py
@@ -0,0 +1,277 @@
+# This file was automatically generated by SWIG (http://www.swig.org).
+# Version 2.0.12
+#
+# Do not make changes to this file unless you know what you are doing--modify
+# the SWIG interface file instead.
+
+
+
+
+
+from sys import version_info
+if version_info >= (2,6,0):
+    def swig_import_helper():
+        from os.path import dirname
+        import imp
+        fp = None
+        try:
+            fp, pathname, description = imp.find_module('_gnm', [dirname(__file__)])
+        except ImportError:
+            import _gnm
+            return _gnm
+        if fp is not None:
+            try:
+                _mod = imp.load_module('_gnm', fp, pathname, description)
+            finally:
+                fp.close()
+            return _mod
+    _gnm = swig_import_helper()
+    del swig_import_helper
+else:
+    import _gnm
+del version_info
+try:
+    _swig_property = property
+except NameError:
+    pass # Python < 2.2 doesn't have 'property'.
+def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
+    if (name == "thisown"): return self.this.own(value)
+    if (name == "this"):
+        if type(value).__name__ == 'SwigPyObject':
+            self.__dict__[name] = value
+            return
+    method = class_type.__swig_setmethods__.get(name,None)
+    if method: return method(self,value)
+    if (not static):
+        self.__dict__[name] = value
+    else:
+        raise AttributeError("You cannot add attributes to %s" % self)
+
+def _swig_setattr(self,class_type,name,value):
+    return _swig_setattr_nondynamic(self,class_type,name,value,0)
+
+def _swig_getattr(self,class_type,name):
+    if (name == "thisown"): return self.this.own()
+    method = class_type.__swig_getmethods__.get(name,None)
+    if method: return method(self)
+    raise AttributeError(name)
+
+def _swig_repr(self):
+    try: strthis = "proxy of " + self.this.__repr__()
+    except: strthis = ""
+    return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+try:
+    _object = object
+    _newclass = 1
+except AttributeError:
+    class _object : pass
+    _newclass = 0
+
+
+
+def GetUseExceptions(*args):
+  return _gnm.GetUseExceptions(*args)
+GetUseExceptions = _gnm.GetUseExceptions
+
+def UseExceptions(*args):
+  return _gnm.UseExceptions(*args)
+UseExceptions = _gnm.UseExceptions
+
+def DontUseExceptions(*args):
+  return _gnm.DontUseExceptions(*args)
+DontUseExceptions = _gnm.DontUseExceptions
+class MajorObject(_object):
+    __swig_setmethods__ = {}
+    __setattr__ = lambda self, name, value: _swig_setattr(self, MajorObject, name, value)
+    __swig_getmethods__ = {}
+    __getattr__ = lambda self, name: _swig_getattr(self, MajorObject, name)
+    def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+    def GetDescription(self, *args): return _gnm.MajorObject_GetDescription(self, *args)
+    def SetDescription(self, *args): return _gnm.MajorObject_SetDescription(self, *args)
+    def GetMetadataDomainList(self, *args): return _gnm.MajorObject_GetMetadataDomainList(self, *args)
+    def GetMetadata_Dict(self, *args): return _gnm.MajorObject_GetMetadata_Dict(self, *args)
+    def GetMetadata_List(self, *args): return _gnm.MajorObject_GetMetadata_List(self, *args)
+    def SetMetadata(self, *args): return _gnm.MajorObject_SetMetadata(self, *args)
+    def GetMetadataItem(self, *args): return _gnm.MajorObject_GetMetadataItem(self, *args)
+    def SetMetadataItem(self, *args): return _gnm.MajorObject_SetMetadataItem(self, *args)
+MajorObject_swigregister = _gnm.MajorObject_swigregister
+MajorObject_swigregister(MajorObject)
+
+GATDijkstraShortestPath = _gnm.GATDijkstraShortestPath
+GATKShortestPath = _gnm.GATKShortestPath
+GATConnectedComponents = _gnm.GATConnectedComponents
+GNM_EDGE_DIR_BOTH = _gnm.GNM_EDGE_DIR_BOTH
+GNM_EDGE_DIR_SRCTOTGT = _gnm.GNM_EDGE_DIR_SRCTOTGT
+GNM_EDGE_DIR_TGTTOSRC = _gnm.GNM_EDGE_DIR_TGTTOSRC
+
+def CastToNetwork(*args):
+  """CastToNetwork(MajorObject base) -> Network"""
+  return _gnm.CastToNetwork(*args)
+
+def CastToGenericNetwork(*args):
+  """CastToGenericNetwork(MajorObject base) -> GenericNetwork"""
+  return _gnm.CastToGenericNetwork(*args)
+class Network(MajorObject):
+    """Proxy of C++ GNMNetworkShadow class"""
+    __swig_setmethods__ = {}
+    for _s in [MajorObject]: __swig_setmethods__.update(getattr(_s,'__swig_setmethods__',{}))
+    __setattr__ = lambda self, name, value: _swig_setattr(self, Network, name, value)
+    __swig_getmethods__ = {}
+    for _s in [MajorObject]: __swig_getmethods__.update(getattr(_s,'__swig_getmethods__',{}))
+    __getattr__ = lambda self, name: _swig_getattr(self, Network, name)
+    def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+    __swig_destroy__ = _gnm.delete_Network
+    __del__ = lambda self : None;
+    def ReleaseResultSet(self, *args):
+        """ReleaseResultSet(Network self, OGRLayerShadow * layer)"""
+        return _gnm.Network_ReleaseResultSet(self, *args)
+
+    def GetVersion(self, *args):
+        """GetVersion(Network self) -> int"""
+        return _gnm.Network_GetVersion(self, *args)
+
+    def GetName(self, *args):
+        """GetName(Network self) -> char const *"""
+        return _gnm.Network_GetName(self, *args)
+
+    def GetFeatureByGlobalFID(self, *args):
+        """GetFeatureByGlobalFID(Network self, GIntBig GFID) -> OGRFeatureShadow *"""
+        return _gnm.Network_GetFeatureByGlobalFID(self, *args)
+
+    def GetPath(self, *args, **kwargs):
+        """GetPath(Network self, GIntBig nStartFID, GIntBig nEndFID, GNMGraphAlgorithmType eAlgorithm, char ** options=None) -> OGRLayerShadow *"""
+        return _gnm.Network_GetPath(self, *args, **kwargs)
+
+    def DisconnectAll(self, *args):
+        """DisconnectAll(Network self) -> CPLErr"""
+        return _gnm.Network_DisconnectAll(self, *args)
+
+    def GetProjection(self, *args):
+        """GetProjection(Network self) -> char const *"""
+        return _gnm.Network_GetProjection(self, *args)
+
+    def GetProjectionRef(self, *args):
+        """GetProjectionRef(Network self) -> char const *"""
+        return _gnm.Network_GetProjectionRef(self, *args)
+
+    def GetFileList(self, *args):
+        """GetFileList(Network self) -> char **"""
+        return _gnm.Network_GetFileList(self, *args)
+
+    def CreateLayer(self, *args, **kwargs):
+        """
+        CreateLayer(Network self, char const * name, OSRSpatialReferenceShadow * srs=None, OGRwkbGeometryType geom_type=wkbUnknown,
+            char ** options=None) -> OGRLayerShadow *
+        """
+        return _gnm.Network_CreateLayer(self, *args, **kwargs)
+
+    def CopyLayer(self, *args, **kwargs):
+        """CopyLayer(Network self, OGRLayerShadow * src_layer, char const * new_name, char ** options=None) -> OGRLayerShadow *"""
+        return _gnm.Network_CopyLayer(self, *args, **kwargs)
+
+    def DeleteLayer(self, *args):
+        """DeleteLayer(Network self, int index) -> OGRErr"""
+        return _gnm.Network_DeleteLayer(self, *args)
+
+    def GetLayerCount(self, *args):
+        """GetLayerCount(Network self) -> int"""
+        return _gnm.Network_GetLayerCount(self, *args)
+
+    def GetLayerByIndex(self, *args):
+        """GetLayerByIndex(Network self, int index=0) -> OGRLayerShadow *"""
+        return _gnm.Network_GetLayerByIndex(self, *args)
+
+    def GetLayerByName(self, *args):
+        """GetLayerByName(Network self, char const * layer_name) -> OGRLayerShadow *"""
+        return _gnm.Network_GetLayerByName(self, *args)
+
+    def TestCapability(self, *args):
+        """TestCapability(Network self, char const * cap) -> bool"""
+        return _gnm.Network_TestCapability(self, *args)
+
+    def StartTransaction(self, *args, **kwargs):
+        """StartTransaction(Network self, int force=False) -> OGRErr"""
+        return _gnm.Network_StartTransaction(self, *args, **kwargs)
+
+    def CommitTransaction(self, *args):
+        """CommitTransaction(Network self) -> OGRErr"""
+        return _gnm.Network_CommitTransaction(self, *args)
+
+    def RollbackTransaction(self, *args):
+        """RollbackTransaction(Network self) -> OGRErr"""
+        return _gnm.Network_RollbackTransaction(self, *args)
+
+Network_swigregister = _gnm.Network_swigregister
+Network_swigregister(Network)
+
+class GenericNetwork(Network):
+    """Proxy of C++ GNMGenericNetworkShadow class"""
+    __swig_setmethods__ = {}
+    for _s in [Network]: __swig_setmethods__.update(getattr(_s,'__swig_setmethods__',{}))
+    __setattr__ = lambda self, name, value: _swig_setattr(self, GenericNetwork, name, value)
+    __swig_getmethods__ = {}
+    for _s in [Network]: __swig_getmethods__.update(getattr(_s,'__swig_getmethods__',{}))
+    __getattr__ = lambda self, name: _swig_getattr(self, GenericNetwork, name)
+    def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+    __swig_destroy__ = _gnm.delete_GenericNetwork
+    __del__ = lambda self : None;
+    def ConnectFeatures(self, *args):
+        """
+        ConnectFeatures(GenericNetwork self, GIntBig nSrcFID, GIntBig nTgtFID, GIntBig nConFID, double dfCost, double dfInvCost,
+            GNMDirection eDir) -> CPLErr
+        """
+        return _gnm.GenericNetwork_ConnectFeatures(self, *args)
+
+    def DisconnectFeatures(self, *args):
+        """DisconnectFeatures(GenericNetwork self, GIntBig nSrcFID, GIntBig nTgtFID, GIntBig nConFID) -> CPLErr"""
+        return _gnm.GenericNetwork_DisconnectFeatures(self, *args)
+
+    def DisconnectFeaturesWithId(self, *args):
+        """DisconnectFeaturesWithId(GenericNetwork self, GIntBig nFID) -> CPLErr"""
+        return _gnm.GenericNetwork_DisconnectFeaturesWithId(self, *args)
+
+    def ReconnectFeatures(self, *args):
+        """
+        ReconnectFeatures(GenericNetwork self, GIntBig nSrcFID, GIntBig nTgtFID, GIntBig nConFID, double dfCost, double dfInvCost,
+            GNMDirection eDir) -> CPLErr
+        """
+        return _gnm.GenericNetwork_ReconnectFeatures(self, *args)
+
+    def CreateRule(self, *args):
+        """CreateRule(GenericNetwork self, char const * pszRuleStr) -> CPLErr"""
+        return _gnm.GenericNetwork_CreateRule(self, *args)
+
+    def DeleteAllRules(self, *args):
+        """DeleteAllRules(GenericNetwork self) -> CPLErr"""
+        return _gnm.GenericNetwork_DeleteAllRules(self, *args)
+
+    def DeleteRule(self, *args):
+        """DeleteRule(GenericNetwork self, char const * pszRuleStr) -> CPLErr"""
+        return _gnm.GenericNetwork_DeleteRule(self, *args)
+
+    def GetRules(self, *args):
+        """GetRules(GenericNetwork self) -> char **"""
+        return _gnm.GenericNetwork_GetRules(self, *args)
+
+    def ConnectPointsByLines(self, *args, **kwargs):
+        """ConnectPointsByLines(GenericNetwork self, char ** papszLayerList, double dfTolerance, double dfCost, double dfInvCost, GNMDirection eDir) -> CPLErr"""
+        return _gnm.GenericNetwork_ConnectPointsByLines(self, *args, **kwargs)
+
+    def ChangeBlockState(self, *args):
+        """ChangeBlockState(GenericNetwork self, GIntBig nFID, bool bIsBlock) -> CPLErr"""
+        return _gnm.GenericNetwork_ChangeBlockState(self, *args)
+
+    def ChangeAllBlockState(self, *args):
+        """ChangeAllBlockState(GenericNetwork self, bool bIsBlock=False) -> CPLErr"""
+        return _gnm.GenericNetwork_ChangeAllBlockState(self, *args)
+
+GenericNetwork_swigregister = _gnm.GenericNetwork_swigregister
+GenericNetwork_swigregister(GenericNetwork)
+
+# This file is compatible with both classic and new-style classes.
+
+
diff --git a/swig/python/osgeo/__init__.py b/swig/python/osgeo/__init__.py
index 92b584b..9242f85 100644
--- a/swig/python/osgeo/__init__.py
+++ b/swig/python/osgeo/__init__.py
@@ -23,5 +23,5 @@ if version_info >= (2,6,0):
 else:
     import _gdal
 
-__version__ = _gdal.__version__ = _gdal.VersionInfo("RELEASE_NAME") 
+__version__ = _gdal.__version__ = _gdal.VersionInfo("RELEASE_NAME")
 
diff --git a/swig/python/osgeo/gdal.py b/swig/python/osgeo/gdal.py
index 0f27ae5..07c20dc 100644
--- a/swig/python/osgeo/gdal.py
+++ b/swig/python/osgeo/gdal.py
@@ -1,9 +1,12 @@
 # This file was automatically generated by SWIG (http://www.swig.org).
-# Version 1.3.40
+# Version 2.0.12
 #
 # Do not make changes to this file unless you know what you are doing--modify
 # the SWIG interface file instead.
-# This file is compatible with both classic and new-style classes.
+
+
+
+
 
 from sys import version_info
 if version_info >= (2,6,0):
@@ -39,7 +42,7 @@ def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
             return
     method = class_type.__swig_setmethods__.get(name,None)
     if method: return method(self,value)
-    if (not static) or hasattr(self,name):
+    if (not static):
         self.__dict__[name] = value
     else:
         raise AttributeError("You cannot add attributes to %s" % self)
@@ -78,8 +81,8 @@ def deprecation_warn( module ):
   from warnings import warn
   warn('%s.py was placed in a namespace, it is now available as osgeo.%s' % (module,module),
        DeprecationWarning)
-       
-       
+
+
 from gdalconst import *
 import gdalconst
 
@@ -143,19 +146,1042 @@ def DontUseExceptions(*args):
   return _gdal.DontUseExceptions(*args)
 
 def VSIFReadL(*args):
-  """VSIFReadL(int nMembSize, int nMembCount, VSILFILE fp) -> int"""
+  """VSIFReadL(int nMembSize, int nMembCount, VSILFILE * fp) -> int"""
   return _gdal.VSIFReadL(*args)
+def _is_str_or_unicode(o):
+    return isinstance(o, str) or str(type(o)) == "<type 'unicode'>"
+
+def InfoOptions(options = [], format = 'text', deserialize = True,
+         computeMinMax = False, reportHistograms = False, reportProj4 = False,
+         stats = False, approxStats = False, computeChecksum = False,
+         showGCPs = True, showMetadata = True, showRAT = True, showColorTable = True,
+         listMDD = False, showFileList = True, allMetadata = False,
+         extraMDDomains = None):
+    """ Create a InfoOptions() object that can be passed to gdal.Info()
+        options can be be an array of strings, a string or let empty and filled from other keywords."""
+    import copy
+
+    if _is_str_or_unicode(options):
+        new_options = ParseCommandLine(options)
+        format = 'text'
+        if '-json' in new_options:
+            format = 'json'
+    else:
+        new_options = copy.copy(options)
+        if format == 'json':
+            new_options += ['-json']
+        if computeMinMax:
+            new_options += ['-mm']
+        if reportHistograms:
+            new_options += ['-hist']
+        if reportProj4:
+            new_options += ['-proj4']
+        if stats:
+            new_options += ['-stats']
+        if approxStats:
+            new_options += ['-approx_stats']
+        if computeChecksum:
+            new_options += ['-checksum']
+        if not showGCPs:
+            new_options += ['-nogcp']
+        if not showMetadata:
+            new_options += ['-nomd']
+        if not showRAT:
+            new_options += ['-norat']
+        if not showColorTable:
+            new_options += ['-noct']
+        if listMDD:
+            new_options += ['-listmdd']
+        if not showFileList:
+            new_options += ['-nofl']
+        if allMetadata:
+            new_options += ['-mdd', 'all']
+        if extraMDDomains is not None:
+            for mdd in extraMDDomains:
+                new_options += ['-mdd', mdd]
+
+    return (GDALInfoOptions(new_options), format, deserialize)
+
+def Info(ds, **kwargs):
+    """ Return information on a dataset.
+        Arguments are :
+          ds --- a Dataset object or a filename
+        Keyword arguments are :
+          options --- return of gdal.InfoOptions(), string or array of strings
+          other keywords arguments of gdal.InfoOptions()
+        If options is provided as a gdal.InfoOptions() object, other keywords are ignored. """
+    if not 'options' in kwargs or type(kwargs['options']) == type([]) or _is_str_or_unicode(kwargs['options']):
+        (opts, format, deserialize) = InfoOptions(**kwargs)
+    else:
+        (opts, format, deserialize) = kwargs['options']
+    if _is_str_or_unicode(ds):
+        ds = Open(ds)
+    ret = InfoInternal(ds, opts)
+    if format == 'json' and deserialize:
+        import json
+        ret = json.loads(ret)
+    return ret
+
+
+def TranslateOptions(options = [], format = 'GTiff',
+              outputType = GDT_Unknown, bandList = None, maskBand = None,
+              width = 0, height = 0, widthPct = 0.0, heightPct = 0.0,
+              xRes = 0.0, yRes = 0.0,
+              creationOptions = None, srcWin = None, projWin = None, projWinSRS = None, strict = False,
+              unscale = False, scaleParams = None, exponents = None,
+              outputBounds = None, metadataOptions = None,
+              outputSRS = None, GCPs = None,
+              noData = None, rgbExpand = None,
+              stats = False, rat = True, resampleAlg = None,
+              callback = None, callback_data = None):
+    """ Create a TranslateOptions() object that can be passed to gdal.Translate()
+        Keyword arguments are :
+          options --- can be be an array of strings, a string or let empty and filled from other keywords.
+          format --- output format ("GTiff", etc...)
+          outputType --- output type (gdal.GDT_Byte, etc...)
+          bandList --- array of band numbers (index start at 1)
+          maskBand --- mask band to generate or not ("none", "auto", "mask", 1, ...)
+          width --- width of the output raster in pixel
+          height --- height of the output raster in pixel
+          widthPct --- width of the output raster in percentage (100 = original width)
+          heightPct --- height of the output raster in percentage (100 = original height)
+          xRes --- output horizontal resolution
+          yRes --- output vertical resolution
+          creationOptions --- list of creation options
+          srcWin --- subwindow in pixels to extract: [left_x, top_y, width, height]
+          projWin --- subwindow in projected coordinates to extract: [ulx, uly, lrx, lry]
+          projWinSRS --- SRS in which projWin is expressed
+          strict --- strict mode
+          unscale --- unscale values with scale and offset metadata
+          scaleParams --- list of scale parameters, each of the form [src_min,src_max] or [src_min,src_max,dst_min,dst_max]
+          exponents --- list of exponentiation parameters
+          outputBounds --- assigned output bounds: [ulx, uly, lrx, lry]
+          metadataOptions --- list of metadata options
+          outputSRS --- assigned output SRS
+          GCPs --- list of GCPs
+          noData --- nodata value (or "none" to unset it)
+          rgbExpand --- Color palette expansion mode: "gray", "rgb", "rgba"
+          stats --- whether to calculate statistics
+          rat --- whether to write source RAT
+          resampleAlg --- resampling mode
+          callback --- callback method
+          callback_data --- user data for callback
+    """
+    import copy
+
+    if _is_str_or_unicode(options):
+        new_options = ParseCommandLine(options)
+    else:
+        new_options = copy.copy(options)
+        new_options += ['-of', format]
+        if outputType != GDT_Unknown:
+            new_options += ['-ot', GetDataTypeName(outputType) ]
+        if maskBand != None:
+            new_options += ['-mask', str(maskBand) ]
+        if bandList != None:
+            for b in bandList:
+                new_options += ['-b', str(b) ]
+        if width != 0 or height != 0:
+            new_options += ['-outsize', str(width), str(height)]
+        elif widthPct != 0 and heightPct != 0:
+            new_options += ['-outsize', str(widthPct) + '%%', str(heightPct) + '%%']
+        if creationOptions is not None:
+            for opt in creationOptions:
+                new_options += ['-co', opt ]
+        if srcWin is not None:
+            new_options += ['-srcwin', str(srcWin[0]), str(srcWin[1]), str(srcWin[2]), str(srcWin[3])]
+        if strict:
+            new_options += ['-strict']
+        if unscale:
+            new_options += ['-unscale']
+        if scaleParams:
+            for scaleParam in scaleParams:
+                new_options += ['-scale']
+                for v in scaleParam:
+                    new_options += [ str(v) ]
+        if exponents:
+            for exponent in exponents:
+                new_options += ['-exponent', str(exponent)]
+        if outputBounds is not None:
+            new_options += ['-a_ullr', str(outputBounds[0]), str(outputBounds[1]), str(outputBounds[2]), str(outputBounds[3])]
+        if metadataOptions is not None:
+            for opt in metadataOptions:
+                new_options += ['-mo', opt ]
+        if outputSRS is not None:
+            new_options += ['-a_srs', str(outputSRS) ]
+        if GCPs is not None:
+            for gcp in GCPs:
+                new_options += ['-gcp', str(gcp.GCPPixel), str(gcp.GCPLine), str(gcp.GCPX), str(gcp.GCPY), str(gcp.GCPZ) ]
+        if projWin is not None:
+            new_options += ['-projwin', str(projWin[0]), str(projWin[1]), str(projWin[2]), str(projWin[3])]
+        if projWinSRS is not None:
+            new_options += ['-projwin_srs', str(projWinSRS) ]
+        if noData is not None:
+            new_options += ['-a_nodata', str(noData) ]
+        if rgbExpand is not None:
+            new_options += ['-expand', str(rgbExpand) ]
+        if stats:
+            new_options += ['-stats']
+        if not rat:
+            new_options += ['-norat']
+        if resampleAlg is not None:
+            if resampleAlg == GRA_NearestNeighbour:
+                new_options += ['-r', 'near']
+            elif resampleAlg == GRA_Bilinear:
+                new_options += ['-r', 'bilinear']
+            elif resampleAlg == GRA_Cubic:
+                new_options += ['-r', 'cubic']
+            elif resampleAlg == GRA_CubicSpline:
+                new_options += ['-r', 'cubicspline']
+            elif resampleAlg == GRA_Lanczos:
+                new_options += ['-r', 'lanczos']
+            elif resampleAlg == GRA_Average:
+                new_options += ['-r', 'average']
+            elif resampleAlg == GRA_Mode:
+                new_options += ['-r', 'mode']
+            else:
+                new_options += ['-r', str(resampleAlg) ]
+        if xRes != 0 and yRes != 0:
+            new_options += ['-tr', str(xRes), str(yRes) ]
+
+    return (GDALTranslateOptions(new_options), callback, callback_data)
+
+def Translate(destName, srcDS, **kwargs):
+    """ Convert a dataset.
+        Arguments are :
+          destName --- Output dataset name
+          srcDS --- a Dataset object or a filename
+        Keyword arguments are :
+          options --- return of gdal.InfoOptions(), string or array of strings
+          other keywords arguments of gdal.TranslateOptions()
+        If options is provided as a gdal.TranslateOptions() object, other keywords are ignored. """
+
+    if not 'options' in kwargs or type(kwargs['options']) == type([]) or _is_str_or_unicode(kwargs['options']):
+        (opts, callback, callback_data) = TranslateOptions(**kwargs)
+    else:
+        (opts, callback, callback_data) = kwargs['options']
+    if _is_str_or_unicode(srcDS):
+        srcDS = Open(srcDS)
+
+    return TranslateInternal(destName, srcDS, opts, callback, callback_data)
+
+def WarpOptions(options = [], format = 'GTiff',
+         outputBounds = None,
+         outputBoundsSRS = None,
+         xRes = None, yRes = None, targetAlignedPixels = False,
+         width = 0, height = 0,
+         srcSRS = None, dstSRS = None,
+         srcAlpha = False, dstAlpha = False,
+         warpOptions = None, errorThreshold = None,
+         warpMemoryLimit = None, creationOptions = None, outputType = GDT_Unknown,
+         workingType = GDT_Unknown, resampleAlg = None,
+         srcNodata = None, dstNodata = None, multithread = False,
+         tps = False, rpc = False, geoloc = False, polynomialOrder = None,
+         transformerOptions = None, cutlineDSName = None,
+         cutlineLayer = None, cutlineWhere = None, cutlineSQL = None, cutlineBlend = None, cropToCutline = False,
+         copyMetadata = True, metadataConflictValue = None,
+         setColorInterpretation = False,
+         callback = None, callback_data = None):
+    """ Create a WarpOptions() object that can be passed to gdal.Warp()
+        Keyword arguments are :
+          options --- can be be an array of strings, a string or let empty and filled from other keywords.
+          format --- output format ("GTiff", etc...)
+          outputBounds --- output bounds as (minX, minY, maxX, maxY) in target SRS
+          outputBoundsSRS --- SRS in which output bounds are expressed, in the case they are not expressed in dstSRS
+          xRes, yRes --- output resolution in target SRS
+          targetAlignedPixels --- whether to force output bounds to be multiple of output resolution
+          width --- width of the output raster in pixel
+          height --- height of the output raster in pixel
+          srcSRS --- source SRS
+          dstSRS --- output SRS
+          srcAlpha --- whether to force the last band of the input dataset to be considered as an alpha band
+          dstAlpha --- whether to force the creation of an output alpha band
+          outputType --- output type (gdal.GDT_Byte, etc...)
+          workingType --- working type (gdal.GDT_Byte, etc...)
+          warpOptions --- list of warping options
+          errorThreshold --- error threshold for approximation transformer (in pixels)
+          warpMemoryLimit --- size of working buffer in bytes
+          resampleAlg --- resampling mode
+          creationOptions --- list of creation options
+          srcNodata --- source nodata value(s)
+          dstNodata --- output nodata value(s)
+          multithread --- whether to multithread computation and I/O operations
+          tps --- whether to use Thin Plate Spline GCP transformer
+          rpc --- whether to use RPC transformer
+          geoloc --- whether to use GeoLocation array transformer
+          polynomialOrder --- order of polynomial GCP interpolation
+          transformerOptions --- list of transformer options
+          cutlineDSName --- cutline dataset name
+          cutlineLayer --- cutline layer name
+          cutlineWhere --- cutline WHERE clause
+          cutlineSQL --- cutline SQL statement
+          cutlineBlend --- cutline blend distance in pixels
+          cropToCutline --- whether to use cutline extent for output bounds
+          copyMetadata --- whether to copy source metadata
+          metadataConflictValue --- metadata data conflict value
+          setColorInterpretation --- whether to force color interpretation of input bands to output bands
+          callback --- callback method
+          callback_data --- user data for callback
+    """
+    import copy
+
+    if _is_str_or_unicode(options):
+        new_options = ParseCommandLine(options)
+    else:
+        new_options = copy.copy(options)
+        new_options += ['-of', format]
+        if outputType != GDT_Unknown:
+            new_options += ['-ot', GetDataTypeName(outputType) ]
+        if workingType != GDT_Unknown:
+            new_options += ['-wt', GetDataTypeName(workingType) ]
+        if outputBounds is not None:
+            new_options += ['-te', str(outputBounds[0]), str(outputBounds[1]), str(outputBounds[2]), str(outputBounds[3]) ]
+        if outputBoundsSRS is not None:
+            new_options += ['-te_srs', str(outputBoundsSRS) ]
+        if xRes is not None and yRes is not None:
+            new_options += ['-tr', str(xRes), str(yRes) ]
+        if width != 0 or height != 0:
+            new_options += ['-ts', str(width), str(height)]
+        if srcSRS is not None:
+            new_options += ['-s_srs', str(srcSRS) ]
+        if dstSRS is not None:
+            new_options += ['-t_srs', str(dstSRS) ]
+        if targetAlignedPixels:
+            new_options += ['-tap']
+        if srcAlpha:
+            new_options += ['-srcalpha']
+        if dstAlpha:
+            new_options += ['-dstalpha']
+        if warpOptions is not None:
+            for opt in warpOptions:
+                new_options += ['-wo', str(opt)]
+        if errorThreshold is not None:
+            new_options += ['-et', str(errorThreshold)]
+        if resampleAlg is not None:
+            if resampleAlg == GRIORA_NearestNeighbour:
+                new_options += ['-r', 'near']
+            elif resampleAlg == GRIORA_Bilinear:
+                new_options += ['-rb']
+            elif resampleAlg == GRIORA_Cubic:
+                new_options += ['-rc']
+            elif resampleAlg == GRIORA_CubicSpline:
+                new_options += ['-rcs']
+            elif resampleAlg == GRIORA_Lanczos:
+                new_options += ['-r', 'lanczos']
+            elif resampleAlg == GRIORA_Average:
+                new_options += ['-r', 'average']
+            elif resampleAlg == GRIORA_Mode:
+                new_options += ['-r', 'mode']
+            elif resampleAlg == GRIORA_Gauss:
+                new_options += ['-r', 'gauss']
+            else:
+                new_options += ['-r', str(resampleAlg) ]
+        if warpMemoryLimit is not None:
+            new_options += ['-wm', str(warpMemoryLimit) ]
+        if creationOptions is not None:
+            for opt in creationOptions:
+                new_options += ['-co', opt ]
+        if srcNodata is not None:
+            new_options += ['-srcnodata', str(srcNodata) ]
+        if dstNodata is not None:
+            new_options += ['-dstnodata', str(dstNodata) ]
+        if multithread:
+            new_options += ['-multi']
+        if tps:
+            new_options += ['-tps']
+        if rpc:
+            new_options += ['-rpc']
+        if geoloc:
+            new_options += ['-geoloc']
+        if polynomialOrder is not None:
+            new_options += ['-order', str(polynomialOrder)]
+        if transformerOptions is not None:
+            for opt in transformerOptions:
+                new_options += ['-to', opt ]
+        if cutlineDSName is not None:
+            new_options += ['-cutline', str(cutlineDSName) ]
+        if cutlineLayer is not None:
+            new_options += ['-cl', str(cutlineLayer) ]
+        if cutlineWhere is not None:
+            new_options += ['-cwhere', str(cutlineWhere) ]
+        if cutlineSQL is not None:
+            new_options += ['-csql', str(cutlineSQL) ]
+        if cutlineBlend is not None:
+            new_options += ['-cblend', str(cutlineBlend) ]
+        if cropToCutline:
+            new_options += ['-crop_to_cutline']
+        if not copyMetadata:
+            new_options += ['-nomd']
+        if metadataConflictValue:
+            new_options += ['-cvmd', str(metadataConflictValue) ]
+        if setColorInterpretation:
+            new_options += ['-setci']
+
+    return (GDALWarpAppOptions(new_options), callback, callback_data)
+
+def Warp(destNameOrDestDS, srcDSOrSrcDSTab, **kwargs):
+    """ Warp one or several datasets.
+        Arguments are :
+          destNameOrDestDS --- Output dataset name or object
+          srcDSOrSrcDSTab --- an array of Dataset objects or filenames, or a Dataset object or a filename
+        Keyword arguments are :
+          options --- return of gdal.InfoOptions(), string or array of strings
+          other keywords arguments of gdal.WarpOptions()
+        If options is provided as a gdal.WarpOptions() object, other keywords are ignored. """
+
+    if not 'options' in kwargs or type(kwargs['options']) == type([]) or _is_str_or_unicode(kwargs['options']):
+        (opts, callback, callback_data) = WarpOptions(**kwargs)
+    else:
+        (opts, callback, callback_data) = kwargs['options']
+    if _is_str_or_unicode(srcDSOrSrcDSTab):
+        srcDSTab = [Open(srcDSOrSrcDSTab)]
+    elif type(srcDSOrSrcDSTab) == type([]):
+        srcDSTab = []
+        for elt in srcDSOrSrcDSTab:
+            if _is_str_or_unicode(elt):
+                srcDSTab.append(Open(elt))
+            else:
+                srcDSTab.append(elt)
+    else:
+        srcDSTab = [ srcDSOrSrcDSTab ]
+
+    if _is_str_or_unicode(destNameOrDestDS):
+        return wrapper_GDALWarpDestName(destNameOrDestDS, srcDSTab, opts, callback, callback_data)
+    else:
+        return wrapper_GDALWarpDestDS(destNameOrDestDS, srcDSTab, opts, callback, callback_data)
+
+
+def VectorTranslateOptions(options = [], format = 'ESRI Shapefile',
+         accessMode = None,
+         srcSRS = None, dstSRS = None, reproject = True,
+         SQLStatement = None, SQLDialect = None, where = None, selectFields = None, spatFilter = None,
+         datasetCreationOptions = None,
+         layerCreationOptions = None,
+         layers = None,
+         layerName = None,
+         geometryType = None,
+         dim = None,
+         segmentizeMaxDist= None,
+         zField = None,
+         skipFailures = False,
+         callback = None, callback_data = None):
+    """ Create a VectorTranslateOptions() object that can be passed to gdal.VectorTranslate()
+        Keyword arguments are :
+          options --- can be be an array of strings, a string or let empty and filled from other keywords.
+          format --- output format ("ESRI Shapefile", etc...)
+          accessMode --- None for creation, 'update', 'append', 'overwrite'
+          srcSRS --- source SRS
+          dstSRS --- output SRS (with reprojection if reproject = True)
+          reproject --- whether to do reprojection
+          SQLStatement --- SQL statement to apply to the source dataset
+          SQLDialect --- SQL dialect ('OGRSQL', 'SQLITE', ...)
+          where --- WHERE clause to apply to source layer(s)
+          selectFields --- list of fields to select
+          spatFilter --- spatial filter as (minX, minY, maxX, maxY) bounding box
+          datasetCreationOptions --- list of dataset creation options
+          layerCreationOptions --- list of layer creation options
+          layers --- list of layers to convert
+          layerName --- output layer name
+          geometryType --- output layer geometry type ('POINT', ....)
+          dim --- output dimension ('XY', 'XYZ', 'XYM', 'XYZM', 'layer_dim')
+          segmentizeMaxDist --- maximum distance between consecutive nodes of a line geometry
+          zField --- name of field to use to set the Z component of geometries
+          skipFailures --- whether to skip failures
+          callback --- callback method
+          callback_data --- user data for callback
+    """
+    import copy
+
+    if _is_str_or_unicode(options):
+        new_options = ParseCommandLine(options)
+    else:
+        new_options = copy.copy(options)
+        new_options += ['-f', format]
+        if srcSRS is not None:
+            new_options += ['-s_srs', str(srcSRS) ]
+        if dstSRS is not None:
+            if reproject:
+                new_options += ['-t_srs', str(dstSRS) ]
+            else:
+                new_options += ['-a_srs', str(dstSRS) ]
+        if SQLStatement is not None:
+            new_options += ['-sql', str(SQLStatement) ]
+        if SQLDialect is not None:
+            new_options += ['-dialect', str(SQLDialect) ]
+        if where is not None:
+            new_options += ['-where', str(where) ]
+        if accessMode is not None:
+            if accessMode == 'update':
+                new_options += ['-update']
+            elif accessMode == 'append':
+                new_options += ['-append']
+            elif accessMode == 'overwrite':
+                new_options += ['-overwrite']
+            else:
+                raise Exception('unhandled accessMode')
+        if selectFields is not None:
+            val = ''
+            for item in selectFields:
+                if len(val)>0:
+                    val += ','
+                val += item
+            new_options += ['-select', val]
+        if datasetCreationOptions is not None:
+            for opt in datasetCreationOptions:
+                new_options += ['-dsco', opt ]
+        if layerCreationOptions is not None:
+            for opt in layerCreationOptions:
+                new_options += ['-lco', opt ]
+        if layers is not None:
+            for lyr in layers:
+                new_options += [ lyr ]
+        if segmentizeMaxDist is not None:
+            new_options += ['-segmentize', str(segmentizeMaxDist) ]
+        if spatFilter is not None:
+            new_options += ['-spat', str(spatFilter[0]), str(spatFilter[1]), str(spatFilter[2]), str(spatFilter[3]) ]
+        if layerName is not None:
+            new_options += ['-nln', layerName]
+        if geometryType is not None:
+            new_options += ['-nlt', geometryType]
+        if dim is not None:
+            new_options += ['-dim', dim]
+        if zField is not None:
+            new_options += ['-zfield', zField]
+        if skipFailures:
+            new_options += ['-skip']
+
+    if callback is not None:
+        new_options += [ '-progress' ]
+
+    return (GDALVectorTranslateOptions(new_options), callback, callback_data)
+
+def VectorTranslate(destNameOrDestDS, srcDS, **kwargs):
+    """ Convert one vector dataset
+        Arguments are :
+          destNameOrDestDS --- Output dataset name or object
+          srcDS --- a Dataset object or a filename
+        Keyword arguments are :
+          options --- return of gdal.InfoOptions(), string or array of strings
+          other keywords arguments of gdal.VectorTranslateOptions()
+        If options is provided as a gdal.VectorTranslateOptions() object, other keywords are ignored. """
+
+    if not 'options' in kwargs or type(kwargs['options']) == type([]) or _is_str_or_unicode(kwargs['options']):
+        (opts, callback, callback_data) = VectorTranslateOptions(**kwargs)
+    else:
+        (opts, callback, callback_data) = kwargs['options']
+    if _is_str_or_unicode(srcDS):
+        srcDS = OpenEx(srcDS)
+
+    if _is_str_or_unicode(destNameOrDestDS):
+        return wrapper_GDALVectorTranslateDestName(destNameOrDestDS, srcDS, opts, callback, callback_data)
+    else:
+        return wrapper_GDALVectorTranslateDestDS(destNameOrDestDS, srcDS, opts, callback, callback_data)
+
+def DEMProcessingOptions(options = [], colorFilename = None, format = 'GTiff',
+              creationOptions = None, computeEdges = False, alg = 'Horn', band = 1,
+              zFactor = None, scale = None, azimuth = None, altitude = None, combined = False,
+              slopeFormat = None, trigonometric = False, zeroForFlat = False,
+              callback = None, callback_data = None):
+    """ Create a DEMProcessingOptions() object that can be passed to gdal.DEMProcessing()
+        Keyword arguments are :
+          options --- can be be an array of strings, a string or let empty and filled from other keywords.
+          colorFilename --- (mandatory for "color-relief") name of file that contains palette definition for the "color-relief" processing.
+          format --- output format ("GTiff", etc...)
+          creationOptions --- list of creation options
+          computeEdges --- whether to compute values at raster edges.
+          alg --- 'ZevenbergenThorne' or 'Horn'
+          band --- source band number to use
+          zFactor --- (hillshade only) vertical exaggeration used to pre-multiply the elevations.
+          scale --- ratio of vertical units to horizontal.
+          azimuth --- (hillshade only) azimuth of the light, in degrees. 0 if it comes from the top of the raster, 90 from the east, ... The default value, 315, should rarely be changed as it is the value generally used to generate shaded maps.
+          altitude ---(hillshade only) altitude of the light, in degrees. 90 if the light comes from above the DEM, 0 if it is raking light.
+          combined --- (hillshade only) whether to compute combined shading, a combination of slope and oblique shading.
+          slopeformat --- (slope only) "degree" or "percent".
+          trigonometric --- (aspect only) whether to return trigonometric angle instead of azimuth. Thus 0deg means East, 90deg North, 180deg West, 270deg South.
+          zeroForFlat --- (aspect only) whether to return 0 for flat areas with slope=0, instead of -9999.
+          callback --- callback method
+          callback_data --- user data for callback
+    """
+    import copy
+
+    if _is_str_or_unicode(options):
+        new_options = ParseCommandLine(options)
+    else:
+        new_options = copy.copy(options)
+        new_options += ['-of', format]
+        if creationOptions is not None:
+            for opt in creationOptions:
+                new_options += ['-co', opt ]
+        if computeEdges:
+            new_options += ['-compute_edges' ]
+        if alg ==  'ZevenbergenThorne':
+            new_options += ['-alg', 'ZevenbergenThorne']
+        new_options += ['-b', str(band) ]
+        if zFactor is not None:
+            new_options += ['-z', str(zFactor) ]
+        if scale is not None:
+            new_options += ['-s', str(scale) ]
+        if azimuth is not None:
+            new_options += ['-az', str(azimuth) ]
+        if altitude is not None:
+            new_options += ['-alt', str(altitude) ]
+        if combined:
+            new_options += ['-combined' ]
+        if slopeFormat == 'percent':
+            new_options += ['-p' ]
+        if trigonometric:
+            new_options += ['-trigonometric' ]
+        if zeroForFlat:
+            new_options += ['zero_for_flat' ]
+
+    return (GDALDEMProcessingOptions(new_options), colorFilename, callback, callback_data)
+
+def DEMProcessing(destName, srcDS, processing, **kwargs):
+    """ Apply a DEM processing.
+        Arguments are :
+          destName --- Output dataset name
+          srcDS --- a Dataset object or a filename
+          processing --- one of "hillshade", "slope", "aspect", "color-relief", "TRI", "TPI", "Roughness"
+        Keyword arguments are :
+          options --- return of gdal.InfoOptions(), string or array of strings
+          other keywords arguments of gdal.DEMProcessingOptions()
+        If options is provided as a gdal.DEMProcessingOptions() object, other keywords are ignored. """
+
+    if not 'options' in kwargs or type(kwargs['options']) == type([]) or _is_str_or_unicode(kwargs['options']):
+        (opts, colorFilename, callback, callback_data) = DEMProcessingOptions(**kwargs)
+    else:
+        (opts, colorFilename, callback, callback_data) = kwargs['options']
+    if _is_str_or_unicode(srcDS):
+        srcDS = Open(srcDS)
+
+    return DEMProcessingInternal(destName, srcDS, processing, colorFilename, opts, callback, callback_data)
+
+
+def NearblackOptions(options = [], format = 'GTiff',
+         creationOptions = None, white = False, colors = None,
+         maxNonBlack = None, nearDist = None, setAlpha = False, setMask = False,
+         callback = None, callback_data = None):
+    """ Create a NearblackOptions() object that can be passed to gdal.Nearblack()
+        Keyword arguments are :
+          options --- can be be an array of strings, a string or let empty and filled from other keywords.
+          format --- output format ("GTiff", etc...)
+          creationOptions --- list of creation options
+          white --- whether to search for nearly white (255) pixels instead of nearly black pixels.
+          colors --- list of colors  to search for, e.g. ((0,0,0),(255,255,255)). The pixels that are considered as the collar are set to 0
+          maxNonBlack --- number of non-black (or other searched colors specified with white / colors) pixels that can be encountered before the giving up search inwards. Defaults to 2.
+          nearDist --- select how far from black, white or custom colors the pixel values can be and still considered near black, white or custom color.  Defaults to 15.
+          setAlpha --- adds an alpha band if the output file.
+          setMask --- adds a mask band to the output file.
+          callback --- callback method
+          callback_data --- user data for callback
+    """
+    import copy
+
+    if _is_str_or_unicode(options):
+        new_options = ParseCommandLine(options)
+    else:
+        new_options = copy.copy(options)
+        new_options += ['-of', format]
+        if creationOptions is not None:
+            for opt in creationOptions:
+                new_options += ['-co', opt ]
+        if white:
+            new_options += ['-white']
+        if colors is not None:
+            for color in colors:
+                color_str = ''
+                for cpt in color:
+                    if color_str != '':
+                        color_str += ','
+                    color_str += str(cpt)
+                new_options += ['-color',color_str]
+        if maxNonBlack is not None:
+            new_options += ['-nb', str(maxNonBlack) ]
+        if nearDist is not None:
+            new_options += ['-near', str(nearDist) ]
+        if setAlpha:
+            new_options += ['-setalpha']
+        if setMask:
+            new_options += ['-setmask']
+
+    return (GDALNearblackOptions(new_options), callback, callback_data)
+
+def Nearblack(destNameOrDestDS, srcDS, **kwargs):
+    """ Convert nearly black/white borders to exact value.
+        Arguments are :
+          destNameOrDestDS --- Output dataset name or object
+          srcDS --- a Dataset object or a filename
+        Keyword arguments are :
+          options --- return of gdal.InfoOptions(), string or array of strings
+          other keywords arguments of gdal.NearblackOptions()
+        If options is provided as a gdal.NearblackOptions() object, other keywords are ignored. """
+
+    if not 'options' in kwargs or type(kwargs['options']) == type([]) or _is_str_or_unicode(kwargs['options']):
+        (opts, callback, callback_data) = NearblackOptions(**kwargs)
+    else:
+        (opts, callback, callback_data) = kwargs['options']
+    if _is_str_or_unicode(srcDS):
+        srcDS = OpenEx(srcDS)
+
+    if _is_str_or_unicode(destNameOrDestDS):
+        return wrapper_GDALNearblackDestName(destNameOrDestDS, srcDS, opts, callback, callback_data)
+    else:
+        return wrapper_GDALNearblackDestDS(destNameOrDestDS, srcDS, opts, callback, callback_data)
+
+
+def GridOptions(options = [], format = 'GTiff',
+              outputType = GDT_Unknown,
+              width = 0, height = 0,
+              creationOptions = None,
+              outputBounds = None,
+              outputSRS = None,
+              noData = None,
+              algorithm = None,
+              layers = None,
+              SQLStatement = None,
+              where = None,
+              spatFilter = None,
+              zfield = None,
+              z_increase = None,
+              z_multiply = None,
+              callback = None, callback_data = None):
+    """ Create a GridOptions() object that can be passed to gdal.Grid()
+        Keyword arguments are :
+          options --- can be be an array of strings, a string or let empty and filled from other keywords.
+          format --- output format ("GTiff", etc...)
+          outputType --- output type (gdal.GDT_Byte, etc...)
+          width --- width of the output raster in pixel
+          height --- height of the output raster in pixel
+          creationOptions --- list of creation options
+          outputBounds --- assigned output bounds: [ulx, uly, lrx, lry]
+          outputSRS --- assigned output SRS
+          noData --- nodata value
+          algorithm --- e.g "invdist:power=2.0:smoothing=0.0:radius1=0.0:radius2=0.0:angle=0.0:max_points=0:min_points=0:nodata=0.0"
+          layers --- list of layers to convert
+          SQLStatement --- SQL statement to apply to the source dataset
+          where --- WHERE clause to apply to source layer(s)
+          spatFilter --- spatial filter as (minX, minY, maxX, maxY) bounding box
+          zfield --- Identifies an attribute field on the features to be used to get a Z value from. This value overrides Z value read from feature geometry record.
+          z_increase --- Addition to the attribute field on the features to be used to get a Z value from. The addition should be the same unit as Z value. The result value will be Z value + Z increase value. The default value is 0.
+          z_multiply - Multiplication ratio for Z field. This can be used for shift from e.g. foot to meters or from  elevation to deep. The result value will be (Z value + Z increase value) * Z multiply value.  The default value is 1.
+          callback --- callback method
+          callback_data --- user data for callback
+    """
+    import copy
+
+    if _is_str_or_unicode(options):
+        new_options = ParseCommandLine(options)
+    else:
+        new_options = copy.copy(options)
+        new_options += ['-of', format]
+        if outputType != GDT_Unknown:
+            new_options += ['-ot', GetDataTypeName(outputType) ]
+        if width != 0 or height != 0:
+            new_options += ['-outsize', str(width), str(height)]
+        if creationOptions is not None:
+            for opt in creationOptions:
+                new_options += ['-co', opt ]
+        if outputBounds is not None:
+            new_options += ['-txe', str(outputBounds[0]), str(outputBounds[2]), '-tye', str(outputBounds[1]), str(outputBounds[3])]
+        if outputSRS is not None:
+            new_options += ['-a_srs', str(outputSRS) ]
+        if algorithm is not None:
+            new_options += ['-a', algorithm ]
+        if layers is not None:
+            if type(layers) == type(()) or type(layers) == type([]):
+                for layer in layers:
+                    new_options += ['-l', layer]
+            else:
+                new_options += ['-l', layers]
+        if SQLStatement is not None:
+            new_options += ['-sql', str(SQLStatement) ]
+        if where is not None:
+            new_options += ['-where', str(where) ]
+        if zfield is not None:
+            new_options += ['-zfield', zfield ]
+        if z_increase is not None:
+            new_options += ['-z_increase', str(z_increase) ]
+        if z_multiply is not None:
+            new_options += ['-z_multiply', str(z_multiply) ]
+        if spatFilter is not None:
+            new_options += ['-spat', str(spatFilter[0]), str(spatFilter[1]), str(spatFilter[2]), str(spatFilter[3]) ]
+
+    return (GDALGridOptions(new_options), callback, callback_data)
+
+def Grid(destName, srcDS, **kwargs):
+    """ Create raster from the scattered data.
+        Arguments are :
+          destName --- Output dataset name
+          srcDS --- a Dataset object or a filename
+        Keyword arguments are :
+          options --- return of gdal.InfoOptions(), string or array of strings
+          other keywords arguments of gdal.GridOptions()
+        If options is provided as a gdal.GridOptions() object, other keywords are ignored. """
+
+    if not 'options' in kwargs or type(kwargs['options']) == type([]) or _is_str_or_unicode(kwargs['options']):
+        (opts, callback, callback_data) = GridOptions(**kwargs)
+    else:
+        (opts, callback, callback_data) = kwargs['options']
+    if _is_str_or_unicode(srcDS):
+        srcDS = OpenEx(srcDS, OF_VECTOR)
+
+    return GridInternal(destName, srcDS, opts, callback, callback_data)
+
+def RasterizeOptions(options = [], format = None,
+         creationOptions = None, noData = None, initValues = None,
+         outputBounds = None, outputSRS = None,
+         width = None, height = None,
+         xRes = None, yRes = None, targetAlignedPixels = False,
+         bands = None, inverse = False, allTouched = False,
+         burnValues = None, attribute = None, useZ = False, layers = None,
+         SQLStatement = None, SQLDialect = None, where = None,
+         callback = None, callback_data = None):
+    """ Create a RasterizeOptions() object that can be passed to gdal.Rasterize()
+        Keyword arguments are :
+          options --- can be be an array of strings, a string or let empty and filled from other keywords.
+          format --- output format ("GTiff", etc...)
+          creationOptions --- list of creation options
+          outputBounds --- assigned output bounds: [minx, miny, maxx, maxy]
+          outputSRS --- assigned output SRS
+          width --- width of the output raster in pixel
+          height --- height of the output raster in pixel
+          xRes, yRes --- output resolution in target SRS
+          targetAlignedPixels --- whether to force output bounds to be multiple of output resolution
+          noData --- nodata value
+          initValues --- Value or list of values to pre-initialize the output image bands with.  However, it is not marked as the nodata value in the output file.  If only one value is given, the same value is used in all the bands.
+          bands --- list of output bands to burn values into
+          inverse --- whether to invert rasterization, i.e. burn the fixed burn value, or the burn value associated  with the first feature into all parts of the image not inside the provided a polygon.
+          allTouched -- whether to enable the ALL_TOUCHED rasterization option so that all pixels touched by lines or polygons will be updated, not just those on the line render path, or whose center point is within the polygon.
+          burnValues -- list of fixed values to burn into each band for all objects. Excusive with attribute.
+          attribute --- identifies an attribute field on the features to be used for a burn-in value. The value will be burned into all output bands. Excusive with burnValues.
+          useZ --- whether to indicate that a burn value should be extracted from the "Z" values of the feature. These values are added to the burn value given by burnValues or attribute if provided. As of now, only points and lines are drawn in 3D.
+          layers --- list of layers from the datasource that will be used for input features.
+          SQLStatement --- SQL statement to apply to the source dataset
+          SQLDialect --- SQL dialect ('OGRSQL', 'SQLITE', ...)
+          where --- WHERE clause to apply to source layer(s)
+          callback --- callback method
+          callback_data --- user data for callback
+    """
+    import copy
+
+    if _is_str_or_unicode(options):
+        new_options = ParseCommandLine(options)
+    else:
+        new_options = copy.copy(options)
+        if format is not None:
+            new_options += ['-of', format]
+        if creationOptions is not None:
+            for opt in creationOptions:
+                new_options += ['-co', opt ]
+        if bands is not None:
+            for b in bands:
+                new_options += ['-b', str(b) ]
+        if noData is not None:
+            new_options += ['-a_nodata', str(noData) ]
+        if initValues is not None:
+            if type(initValues) == type(()) or type(initValues) == type([]):
+                for val in initValues:
+                    new_options += ['-init', str(val) ]
+            else:
+                new_options += ['-init', str(initValues) ]
+        if outputBounds is not None:
+            new_options += ['-te', str(outputBounds[0]), str(outputBounds[1]), str(outputBounds[2]), str(outputBounds[3])]
+        if outputSRS is not None:
+            new_options += ['-a_srs', str(outputSRS) ]
+        if width is not None and height is not None:
+            new_options += ['-ts', str(width), str(height)]
+        if xRes is not None and yRes is not None:
+            new_options += ['-tr', str(xRes), str(yRes)]
+        if targetAlignedPixels:
+            new_options += ['-tap']
+        if inverse:
+            new_options += ['-i']
+        if allTouched:
+            new_options += ['-at']
+        if burnValues is not None:
+            if attribute is not None:
+                raise Exception('burnValues and attribute option are exclusive.')
+            if type(burnValues) == type(()) or type(burnValues) == type([]):
+                for val in burnValues:
+                    new_options += ['-burn', str(val) ]
+            else:
+                new_options += ['-burn', str(burnValues) ]
+        if attribute is not None:
+            new_options += ['-a', attribute]
+        if useZ:
+            new_options += ['-3d']
+        if layers is not None:
+            if type(layers) == type(()) or type(layers) == type([]):
+                for layer in layers:
+                    new_options += ['-l', layer]
+            else:
+                new_options += ['-l', layers]
+        if SQLStatement is not None:
+            new_options += ['-sql', str(SQLStatement) ]
+        if SQLDialect is not None:
+            new_options += ['-dialect', str(SQLDialect) ]
+        if where is not None:
+            new_options += ['-where', str(where) ]
+
+    return (GDALRasterizeOptions(new_options), callback, callback_data)
+
+def Rasterize(destNameOrDestDS, srcDS, **kwargs):
+    """ Burns vector geometries into a raster
+        Arguments are :
+          destNameOrDestDS --- Output dataset name or object
+          srcDS --- a Dataset object or a filename
+        Keyword arguments are :
+          options --- return of gdal.InfoOptions(), string or array of strings
+          other keywords arguments of gdal.RasterizeOptions()
+        If options is provided as a gdal.RasterizeOptions() object, other keywords are ignored. """
+
+    if not 'options' in kwargs or type(kwargs['options']) == type([]) or _is_str_or_unicode(kwargs['options']):
+        (opts, callback, callback_data) = RasterizeOptions(**kwargs)
+    else:
+        (opts, callback, callback_data) = kwargs['options']
+    if _is_str_or_unicode(srcDS):
+        srcDS = OpenEx(srcDS)
+
+    if _is_str_or_unicode(destNameOrDestDS):
+        return wrapper_GDALRasterizeDestName(destNameOrDestDS, srcDS, opts, callback, callback_data)
+    else:
+        return wrapper_GDALRasterizeDestDS(destNameOrDestDS, srcDS, opts, callback, callback_data)
+
+
+def BuildVRTOptions(options = [],
+                    resolution = None,
+                    outputBounds = None,
+                    xRes = None, yRes = None,
+                    targetAlignedPixels = None,
+                    separate = None,
+                    bandList = None,
+                    addAlpha = None,
+                    resampleAlg = None,
+                    outputSRS = None,
+                    allowProjectionDifference = None,
+                    srcNodata = None,
+                    VRTNodata = None,
+                    hideNodata = None,
+                    callback = None, callback_data = None):
+    """ Create a BuildVRTOptions() object that can be passed to gdal.BuildVRT()
+        Keyword arguments are :
+          options --- can be be an array of strings, a string or let empty and filled from other keywords..
+          resolution --- 'highest', 'lowest', 'average', 'user'.
+          outputBounds --- output bounds as (minX, minY, maxX, maxY) in target SRS.
+          xRes, yRes --- output resolution in target SRS.
+          targetAlignedPixels --- whether to force output bounds to be multiple of output resolution.
+          separate --- whether each source file goes into a separate stacked band in the VRT band.
+          bandList --- array of band numbers (index start at 1).
+          addAlpha --- whether to add an alpha mask band to the VRT when the source raster have none.
+          resampleAlg --- resampling mode.
+          outputSRS --- assigned output SRS.
+          allowProjectionDifference --- whether to accept input datasets have not the same projection. Note: they will *not* be reprojected.
+          srcNodata --- source nodata value(s).
+          VRTNodata --- nodata values at the VRT band level.
+          hideNodata --- whether to make the VRT band not report the NoData value.
+          callback --- callback method.
+          callback_data --- user data for callback.
+    """
+    import copy
+
+    if _is_str_or_unicode(options):
+        new_options = ParseCommandLine(options)
+    else:
+        new_options = copy.copy(options)
+        if resolution is not None:
+            new_options += ['-resolution', str(resolution) ]
+        if outputBounds is not None:
+            new_options += ['-te', str(outputBounds[0]), str(outputBounds[1]), str(outputBounds[2]), str(outputBounds[3])]
+        if xRes is not None and yRes is not None:
+            new_options += ['-tr', str(xRes), str(yRes)]
+        if targetAlignedPixels:
+            new_options += ['-tap']
+        if separate:
+            new_options += ['-separate']
+        if bandList != None:
+            for b in bandList:
+                new_options += ['-b', str(b) ]
+        if addAlpha:
+            new_options += ['-addalpha']
+        if resampleAlg is not None:
+            if resampleAlg == GRIORA_NearestNeighbour:
+                new_options += ['-r', 'near']
+            elif resampleAlg == GRIORA_Bilinear:
+                new_options += ['-rb']
+            elif resampleAlg == GRIORA_Cubic:
+                new_options += ['-rc']
+            elif resampleAlg == GRIORA_CubicSpline:
+                new_options += ['-rcs']
+            elif resampleAlg == GRIORA_Lanczos:
+                new_options += ['-r', 'lanczos']
+            elif resampleAlg == GRIORA_Average:
+                new_options += ['-r', 'average']
+            elif resampleAlg == GRIORA_Mode:
+                new_options += ['-r', 'mode']
+            elif resampleAlg == GRIORA_Gauss:
+                new_options += ['-r', 'gauss']
+            else:
+                new_options += ['-r', str(resampleAlg) ]
+        if outputSRS is not None:
+            new_options += ['-a_srs', str(outputSRS) ]
+        if allowProjectionDifference:
+            new_options += ['-allow_projection_difference']
+        if srcNodata is not None:
+            new_options += ['-srcnodata', str(srcNodata) ]
+        if VRTNodata is not None:
+            new_options += ['-vrtnodata', str(VRTNodata) ]
+        if hideNodata:
+            new_options += ['-hidenodata']
+
+    return (GDALBuildVRTOptions(new_options), callback, callback_data)
+
+def BuildVRT(destName, srcDSOrSrcDSTab, **kwargs):
+    """ Build a VRT from a list of datasets.
+        Arguments are :
+          destName --- Output dataset name
+          srcDSOrSrcDSTab --- an array of Dataset objects or filenames, or a Dataset object or a filename
+        Keyword arguments are :
+          options --- return of gdal.InfoOptions(), string or array of strings
+          other keywords arguments of gdal.BuildVRTOptions()
+        If options is provided as a gdal.BuildVRTOptions() object, other keywords are ignored. """
+
+    if not 'options' in kwargs or type(kwargs['options']) == type([]) or _is_str_or_unicode(kwargs['options']):
+        (opts, callback, callback_data) = BuildVRTOptions(**kwargs)
+    else:
+        (opts, callback, callback_data) = kwargs['options']
+
+    srcDSTab = []
+    srcDSNamesTab = []
+    if _is_str_or_unicode(srcDSOrSrcDSTab):
+        srcDSNamesTab = [ srcDSOrSrcDSTab ]
+    elif type(srcDSOrSrcDSTab) == type([]):
+        for elt in srcDSOrSrcDSTab:
+            if _is_str_or_unicode(elt):
+                srcDSNamesTab.append(elt)
+            else:
+                srcDSTab.append(elt)
+        if len(srcDSTab) != 0 and len(srcDSNamesTab) != 0:
+            raise Exception('Mix of names and dataset objects not supported')
+    else:
+        srcDSTab = [ srcDSOrSrcDSTab ]
+
+    if len(srcDSTab) > 0:
+        return BuildVRTInternalObjects(destName, srcDSTab, opts, callback, callback_data)
+    else:
+        return BuildVRTInternalNames(destName, srcDSNamesTab, opts, callback, callback_data)
+
+
 
 def Debug(*args):
-  """Debug(char msg_class, char message)"""
+  """Debug(char const * msg_class, char const * message)"""
   return _gdal.Debug(*args)
 
 def SetErrorHandler(*args):
-  """SetErrorHandler(char pszCallbackName = None) -> CPLErr"""
+  """SetErrorHandler(char const * pszCallbackName=None) -> CPLErr"""
   return _gdal.SetErrorHandler(*args)
 
 def PushErrorHandler(*args):
-  """PushErrorHandler(CPLErrorHandler pfnErrorHandler = None) -> CPLErr"""
+  """PushErrorHandler(CPLErrorHandler pfnErrorHandler=0) -> CPLErr"""
   return _gdal.PushErrorHandler(*args)
 
 def PopErrorHandler(*args):
@@ -163,19 +1189,19 @@ def PopErrorHandler(*args):
   return _gdal.PopErrorHandler(*args)
 
 def Error(*args):
-  """Error(CPLErr msg_class = CE_Failure, int err_code = 0, char msg = "error")"""
+  """Error(CPLErr msg_class=CE_Failure, int err_code=0, char const * msg="error")"""
   return _gdal.Error(*args)
 
 def GOA2GetAuthorizationURL(*args):
-  """GOA2GetAuthorizationURL(char pszScope) -> retStringAndCPLFree"""
+  """GOA2GetAuthorizationURL(char const * pszScope) -> retStringAndCPLFree *"""
   return _gdal.GOA2GetAuthorizationURL(*args)
 
 def GOA2GetRefreshToken(*args):
-  """GOA2GetRefreshToken(char pszAuthToken, char pszScope) -> retStringAndCPLFree"""
+  """GOA2GetRefreshToken(char const * pszAuthToken, char const * pszScope) -> retStringAndCPLFree *"""
   return _gdal.GOA2GetRefreshToken(*args)
 
 def GOA2GetAccessToken(*args):
-  """GOA2GetAccessToken(char pszRefreshToken, char pszScope) -> retStringAndCPLFree"""
+  """GOA2GetAccessToken(char const * pszRefreshToken, char const * pszScope) -> retStringAndCPLFree *"""
   return _gdal.GOA2GetAccessToken(*args)
 
 def ErrorReset(*args):
@@ -183,7 +1209,7 @@ def ErrorReset(*args):
   return _gdal.ErrorReset(*args)
 
 def EscapeString(*args, **kwargs):
-  """EscapeString(int len, int scheme = CPLES_SQL) -> retStringAndCPLFree"""
+  """EscapeString(int len, int scheme=CPLES_SQL) -> retStringAndCPLFree *"""
   return _gdal.EscapeString(*args, **kwargs)
 
 def GetLastErrorNo(*args):
@@ -195,11 +1221,19 @@ def GetLastErrorType(*args):
   return _gdal.GetLastErrorType(*args)
 
 def GetLastErrorMsg(*args):
-  """GetLastErrorMsg() -> char"""
+  """GetLastErrorMsg() -> char const *"""
   return _gdal.GetLastErrorMsg(*args)
 
+def VSIGetLastErrorNo(*args):
+  """VSIGetLastErrorNo() -> int"""
+  return _gdal.VSIGetLastErrorNo(*args)
+
+def VSIGetLastErrorMsg(*args):
+  """VSIGetLastErrorMsg() -> char const *"""
+  return _gdal.VSIGetLastErrorMsg(*args)
+
 def PushFinderLocation(*args):
-  """PushFinderLocation(char utf8_path)"""
+  """PushFinderLocation(char const * utf8_path)"""
   return _gdal.PushFinderLocation(*args)
 
 def PopFinderLocation(*args):
@@ -211,39 +1245,39 @@ def FinderClean(*args):
   return _gdal.FinderClean(*args)
 
 def FindFile(*args):
-  """FindFile(char pszClass, char utf8_path) -> char"""
+  """FindFile(char const * pszClass, char const * utf8_path) -> char const *"""
   return _gdal.FindFile(*args)
 
 def ReadDir(*args):
-  """ReadDir(char utf8_path) -> char"""
+  """ReadDir(char const * utf8_path, int nMaxFiles=0) -> char **"""
   return _gdal.ReadDir(*args)
 
 def ReadDirRecursive(*args):
-  """ReadDirRecursive(char utf8_path) -> char"""
+  """ReadDirRecursive(char const * utf8_path) -> char **"""
   return _gdal.ReadDirRecursive(*args)
 
 def SetConfigOption(*args):
-  """SetConfigOption(char pszKey, char pszValue)"""
+  """SetConfigOption(char const * pszKey, char const * pszValue)"""
   return _gdal.SetConfigOption(*args)
 
 def GetConfigOption(*args):
-  """GetConfigOption(char pszKey, char pszDefault = None) -> char"""
+  """GetConfigOption(char const * pszKey, char const * pszDefault=None) -> char const *"""
   return _gdal.GetConfigOption(*args)
 
 def CPLBinaryToHex(*args):
-  """CPLBinaryToHex(int nBytes) -> retStringAndCPLFree"""
+  """CPLBinaryToHex(int nBytes) -> retStringAndCPLFree *"""
   return _gdal.CPLBinaryToHex(*args)
 
 def CPLHexToBinary(*args):
-  """CPLHexToBinary(char pszHex, int pnBytes) -> GByte"""
+  """CPLHexToBinary(char const * pszHex, int * pnBytes) -> GByte *"""
   return _gdal.CPLHexToBinary(*args)
 
 def FileFromMemBuffer(*args):
-  """FileFromMemBuffer(char utf8_path, int nBytes)"""
+  """FileFromMemBuffer(char const * utf8_path, int nBytes)"""
   return _gdal.FileFromMemBuffer(*args)
 
 def Unlink(*args):
-  """Unlink(char utf8_path) -> VSI_RETVAL"""
+  """Unlink(char const * utf8_path) -> VSI_RETVAL"""
   return _gdal.Unlink(*args)
 
 def HasThreadSupport(*args):
@@ -251,15 +1285,15 @@ def HasThreadSupport(*args):
   return _gdal.HasThreadSupport(*args)
 
 def Mkdir(*args):
-  """Mkdir(char utf8_path, int mode) -> VSI_RETVAL"""
+  """Mkdir(char const * utf8_path, int mode) -> VSI_RETVAL"""
   return _gdal.Mkdir(*args)
 
 def Rmdir(*args):
-  """Rmdir(char utf8_path) -> VSI_RETVAL"""
+  """Rmdir(char const * utf8_path) -> VSI_RETVAL"""
   return _gdal.Rmdir(*args)
 
 def Rename(*args):
-  """Rename(char pszOld, char pszNew) -> VSI_RETVAL"""
+  """Rename(char const * pszOld, char const * pszNew) -> VSI_RETVAL"""
   return _gdal.Rename(*args)
 VSI_STAT_EXISTS_FLAG = _gdal.VSI_STAT_EXISTS_FLAG
 VSI_STAT_NATURE_FLAG = _gdal.VSI_STAT_NATURE_FLAG
@@ -277,15 +1311,15 @@ class StatBuf(_object):
     if _newclass:size = _swig_property(_gdal.StatBuf_size_get)
     __swig_getmethods__["mtime"] = _gdal.StatBuf_mtime_get
     if _newclass:mtime = _swig_property(_gdal.StatBuf_mtime_get)
-    def __init__(self, *args): 
-        """__init__(self, StatBuf psStatBuf) -> StatBuf"""
+    def __init__(self, *args):
+        """__init__(StatBuf self, StatBuf psStatBuf) -> StatBuf"""
         this = _gdal.new_StatBuf(*args)
         try: self.this.append(this)
         except: self.this = this
     __swig_destroy__ = _gdal.delete_StatBuf
     __del__ = lambda self : None;
     def IsDirectory(self, *args):
-        """IsDirectory(self) -> int"""
+        """IsDirectory(StatBuf self) -> int"""
         return _gdal.StatBuf_IsDirectory(self, *args)
 
 StatBuf_swigregister = _gdal.StatBuf_swigregister
@@ -293,32 +1327,40 @@ StatBuf_swigregister(StatBuf)
 
 
 def VSIStatL(*args):
-  """VSIStatL(char utf8_path, int nFlags = 0) -> int"""
+  """VSIStatL(char const * utf8_path, int nFlags=0) -> int"""
   return _gdal.VSIStatL(*args)
 
 def VSIFOpenL(*args):
-  """VSIFOpenL(char utf8_path, char pszMode) -> VSILFILE"""
+  """VSIFOpenL(char const * utf8_path, char const * pszMode) -> VSILFILE *"""
   return _gdal.VSIFOpenL(*args)
 
+def VSIFOpenExL(*args):
+  """VSIFOpenExL(char const * utf8_path, char const * pszMode, int bSetError) -> VSILFILE *"""
+  return _gdal.VSIFOpenExL(*args)
+
 def VSIFCloseL(*args):
-  """VSIFCloseL(VSILFILE arg0) -> VSI_RETVAL"""
+  """VSIFCloseL(VSILFILE * fp) -> VSI_RETVAL"""
   return _gdal.VSIFCloseL(*args)
 
 def VSIFSeekL(*args):
-  """VSIFSeekL(VSILFILE arg0, GIntBig arg1, int arg2) -> int"""
+  """VSIFSeekL(VSILFILE * fp, GIntBig offset, int whence) -> int"""
   return _gdal.VSIFSeekL(*args)
 
 def VSIFTellL(*args):
-  """VSIFTellL(VSILFILE arg0) -> GIntBig"""
+  """VSIFTellL(VSILFILE * fp) -> GIntBig"""
   return _gdal.VSIFTellL(*args)
 
 def VSIFTruncateL(*args):
-  """VSIFTruncateL(VSILFILE arg0, GIntBig arg1) -> int"""
+  """VSIFTruncateL(VSILFILE * fp, GIntBig length) -> int"""
   return _gdal.VSIFTruncateL(*args)
 
 def VSIFWriteL(*args):
-  """VSIFWriteL(int nLen, int size, int memb, VSILFILE f) -> int"""
+  """VSIFWriteL(int nLen, int size, int memb, VSILFILE * fp) -> int"""
   return _gdal.VSIFWriteL(*args)
+
+def ParseCommandLine(*args):
+  """ParseCommandLine(char const * utf8_path) -> char **"""
+  return _gdal.ParseCommandLine(*args)
 class MajorObject(_object):
     """Proxy of C++ GDALMajorObjectShadow class"""
     __swig_setmethods__ = {}
@@ -328,38 +1370,38 @@ class MajorObject(_object):
     def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined")
     __repr__ = _swig_repr
     def GetDescription(self, *args):
-        """GetDescription(self) -> char"""
+        """GetDescription(MajorObject self) -> char const *"""
         return _gdal.MajorObject_GetDescription(self, *args)
 
     def SetDescription(self, *args):
-        """SetDescription(self, char pszNewDesc)"""
+        """SetDescription(MajorObject self, char const * pszNewDesc)"""
         return _gdal.MajorObject_SetDescription(self, *args)
 
     def GetMetadataDomainList(self, *args):
-        """GetMetadataDomainList(self) -> char"""
+        """GetMetadataDomainList(MajorObject self) -> char **"""
         return _gdal.MajorObject_GetMetadataDomainList(self, *args)
 
     def GetMetadata_Dict(self, *args):
-        """GetMetadata_Dict(self, char pszDomain = "") -> char"""
+        """GetMetadata_Dict(MajorObject self, char const * pszDomain="") -> char **"""
         return _gdal.MajorObject_GetMetadata_Dict(self, *args)
 
     def GetMetadata_List(self, *args):
-        """GetMetadata_List(self, char pszDomain = "") -> char"""
+        """GetMetadata_List(MajorObject self, char const * pszDomain="") -> char **"""
         return _gdal.MajorObject_GetMetadata_List(self, *args)
 
     def SetMetadata(self, *args):
         """
-        SetMetadata(self, char papszMetadata, char pszDomain = "") -> CPLErr
-        SetMetadata(self, char pszMetadataString, char pszDomain = "") -> CPLErr
+        SetMetadata(MajorObject self, char ** papszMetadata, char const * pszDomain="") -> CPLErr
+        SetMetadata(MajorObject self, char * pszMetadataString, char const * pszDomain="") -> CPLErr
         """
         return _gdal.MajorObject_SetMetadata(self, *args)
 
     def GetMetadataItem(self, *args):
-        """GetMetadataItem(self, char pszName, char pszDomain = "") -> char"""
+        """GetMetadataItem(MajorObject self, char const * pszName, char const * pszDomain="") -> char const *"""
         return _gdal.MajorObject_GetMetadataItem(self, *args)
 
     def SetMetadataItem(self, *args):
-        """SetMetadataItem(self, char pszName, char pszValue, char pszDomain = "") -> CPLErr"""
+        """SetMetadataItem(MajorObject self, char const * pszName, char const * pszValue, char const * pszDomain="") -> CPLErr"""
         return _gdal.MajorObject_SetMetadataItem(self, *args)
 
     def GetMetadata( self, domain = '' ):
@@ -388,37 +1430,36 @@ class Driver(MajorObject):
     if _newclass:HelpTopic = _swig_property(_gdal.Driver_HelpTopic_get)
     def Create(self, *args, **kwargs):
         """
-        Create(self, char utf8_path, int xsize, int ysize, int bands = 1, 
-            GDALDataType eType = GDT_Byte, char options = None) -> Dataset
+        Create(Driver self, char const * utf8_path, int xsize, int ysize, int bands=1, GDALDataType eType=GDT_Byte,
+            char ** options=None) -> Dataset
         """
         return _gdal.Driver_Create(self, *args, **kwargs)
 
     def CreateCopy(self, *args, **kwargs):
         """
-        CreateCopy(self, char utf8_path, Dataset src, int strict = 1, char options = None, 
-            GDALProgressFunc callback = None, 
-            void callback_data = None) -> Dataset
+        CreateCopy(Driver self, char const * utf8_path, Dataset src, int strict=1, char ** options=None, GDALProgressFunc callback=0,
+            void * callback_data=None) -> Dataset
         """
         return _gdal.Driver_CreateCopy(self, *args, **kwargs)
 
     def Delete(self, *args):
-        """Delete(self, char utf8_path) -> CPLErr"""
+        """Delete(Driver self, char const * utf8_path) -> CPLErr"""
         return _gdal.Driver_Delete(self, *args)
 
     def Rename(self, *args):
-        """Rename(self, char newName, char oldName) -> CPLErr"""
+        """Rename(Driver self, char const * newName, char const * oldName) -> CPLErr"""
         return _gdal.Driver_Rename(self, *args)
 
     def CopyFiles(self, *args):
-        """CopyFiles(self, char newName, char oldName) -> CPLErr"""
+        """CopyFiles(Driver self, char const * newName, char const * oldName) -> CPLErr"""
         return _gdal.Driver_CopyFiles(self, *args)
 
     def Register(self, *args):
-        """Register(self) -> int"""
+        """Register(Driver self) -> int"""
         return _gdal.Driver_Register(self, *args)
 
     def Deregister(self, *args):
-        """Deregister(self)"""
+        """Deregister(Driver self)"""
         return _gdal.Driver_Deregister(self, *args)
 
 Driver_swigregister = _gdal.Driver_swigregister
@@ -432,6 +1473,7 @@ class ColorEntry(_object):
     __setattr__ = lambda self, name, value: _swig_setattr(self, ColorEntry, name, value)
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, ColorEntry, name)
+    def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined")
     __repr__ = _swig_repr
     __swig_setmethods__["c1"] = _gdal.ColorEntry_c1_set
     __swig_getmethods__["c1"] = _gdal.ColorEntry_c1_get
@@ -445,13 +1487,6 @@ class ColorEntry(_object):
     __swig_setmethods__["c4"] = _gdal.ColorEntry_c4_set
     __swig_getmethods__["c4"] = _gdal.ColorEntry_c4_get
     if _newclass:c4 = _swig_property(_gdal.ColorEntry_c4_get, _gdal.ColorEntry_c4_set)
-    def __init__(self, *args): 
-        """__init__(self) -> ColorEntry"""
-        this = _gdal.new_ColorEntry(*args)
-        try: self.this.append(this)
-        except: self.this = this
-    __swig_destroy__ = _gdal.delete_ColorEntry
-    __del__ = lambda self : None;
 ColorEntry_swigregister = _gdal.ColorEntry_swigregister
 ColorEntry_swigregister(ColorEntry)
 
@@ -483,11 +1518,10 @@ class GCP(_object):
     __swig_setmethods__["Id"] = _gdal.GCP_Id_set
     __swig_getmethods__["Id"] = _gdal.GCP_Id_get
     if _newclass:Id = _swig_property(_gdal.GCP_Id_get, _gdal.GCP_Id_set)
-    def __init__(self, *args): 
+    def __init__(self, *args):
         """
-        __init__(self, double x = 0.0, double y = 0.0, double z = 0.0, double pixel = 0.0, 
-            double line = 0.0, char info = "", 
-            char id = "") -> GCP
+        __init__(GDAL_GCP self, double x=0.0, double y=0.0, double z=0.0, double pixel=0.0, double line=0.0, char const * info="",
+            char const * id="") -> GCP
         """
         this = _gdal.new_GCP(*args)
         try: self.this.append(this)
@@ -503,7 +1537,7 @@ class GCP(_object):
     def serialize(self,with_Z=0):
       base = [CXT_Element,'GCP']
       base.append([CXT_Attribute,'Id',[CXT_Text,self.Id]])
-      pixval = '%0.15E' % self.GCPPixel       
+      pixval = '%0.15E' % self.GCPPixel
       lineval = '%0.15E' % self.GCPLine
       xval = '%0.15E' % self.GCPX
       yval = '%0.15E' % self.GCPY
@@ -513,7 +1547,7 @@ class GCP(_object):
       base.append([CXT_Attribute,'X',[CXT_Text,xval]])
       base.append([CXT_Attribute,'Y',[CXT_Text,yval]])
       if with_Z:
-          base.append([CXT_Attribute,'Z',[CXT_Text,zval]])        
+          base.append([CXT_Attribute,'Z',[CXT_Text,zval]])
       return base
 
 GCP_swigregister = _gdal.GCP_swigregister
@@ -561,23 +1595,23 @@ def GDAL_GCP_GCPLine_set(*args):
   return _gdal.GDAL_GCP_GCPLine_set(*args)
 
 def GDAL_GCP_Info_get(*args):
-  """GDAL_GCP_Info_get(GCP gcp) -> char"""
+  """GDAL_GCP_Info_get(GCP gcp) -> char const *"""
   return _gdal.GDAL_GCP_Info_get(*args)
 
 def GDAL_GCP_Info_set(*args):
-  """GDAL_GCP_Info_set(GCP gcp, char pszInfo)"""
+  """GDAL_GCP_Info_set(GCP gcp, char const * pszInfo)"""
   return _gdal.GDAL_GCP_Info_set(*args)
 
 def GDAL_GCP_Id_get(*args):
-  """GDAL_GCP_Id_get(GCP gcp) -> char"""
+  """GDAL_GCP_Id_get(GCP gcp) -> char const *"""
   return _gdal.GDAL_GCP_Id_get(*args)
 
 def GDAL_GCP_Id_set(*args):
-  """GDAL_GCP_Id_set(GCP gcp, char pszId)"""
+  """GDAL_GCP_Id_set(GCP gcp, char const * pszId)"""
   return _gdal.GDAL_GCP_Id_set(*args)
 
 def GCPsToGeoTransform(*args):
-  """GCPsToGeoTransform(int nGCPs, int bApproxOK = 1) -> RETURN_NONE"""
+  """GCPsToGeoTransform(int nGCPs, int bApproxOK=1) -> RETURN_NONE"""
   return _gdal.GCPsToGeoTransform(*args)
 class VirtualMem(_object):
     """Proxy of C++ CPLVirtualMemShadow class"""
@@ -590,11 +1624,11 @@ class VirtualMem(_object):
     __swig_destroy__ = _gdal.delete_VirtualMem
     __del__ = lambda self : None;
     def GetAddr(self, *args):
-        """GetAddr(self)"""
+        """GetAddr(VirtualMem self)"""
         return _gdal.VirtualMem_GetAddr(self, *args)
 
     def Pin(self, *args):
-        """Pin(self, size_t start_offset = 0, size_t nsize = 0, int bWriteOp = 0)"""
+        """Pin(VirtualMem self, size_t start_offset=0, size_t nsize=0, int bWriteOp=0)"""
         return _gdal.VirtualMem_Pin(self, *args)
 
 VirtualMem_swigregister = _gdal.VirtualMem_swigregister
@@ -611,19 +1645,19 @@ class AsyncReader(_object):
     __swig_destroy__ = _gdal.delete_AsyncReader
     __del__ = lambda self : None;
     def GetNextUpdatedRegion(self, *args):
-        """GetNextUpdatedRegion(self, double timeout) -> GDALAsyncStatusType"""
+        """GetNextUpdatedRegion(AsyncReader self, double timeout) -> GDALAsyncStatusType"""
         return _gdal.AsyncReader_GetNextUpdatedRegion(self, *args)
 
     def GetBuffer(self, *args):
-        """GetBuffer(self)"""
+        """GetBuffer(AsyncReader self)"""
         return _gdal.AsyncReader_GetBuffer(self, *args)
 
     def LockBuffer(self, *args):
-        """LockBuffer(self, double timeout) -> int"""
+        """LockBuffer(AsyncReader self, double timeout) -> int"""
         return _gdal.AsyncReader_LockBuffer(self, *args)
 
     def UnlockBuffer(self, *args):
-        """UnlockBuffer(self)"""
+        """UnlockBuffer(AsyncReader self)"""
         return _gdal.AsyncReader_UnlockBuffer(self, *args)
 
 AsyncReader_swigregister = _gdal.AsyncReader_swigregister
@@ -648,184 +1682,174 @@ class Dataset(MajorObject):
     __swig_destroy__ = _gdal.delete_Dataset
     __del__ = lambda self : None;
     def GetDriver(self, *args):
-        """GetDriver(self) -> Driver"""
+        """GetDriver(Dataset self) -> Driver"""
         return _gdal.Dataset_GetDriver(self, *args)
 
     def GetRasterBand(self, *args):
-        """GetRasterBand(self, int nBand) -> Band"""
+        """GetRasterBand(Dataset self, int nBand) -> Band"""
         return _gdal.Dataset_GetRasterBand(self, *args)
 
     def GetProjection(self, *args):
-        """GetProjection(self) -> char"""
+        """GetProjection(Dataset self) -> char const *"""
         return _gdal.Dataset_GetProjection(self, *args)
 
     def GetProjectionRef(self, *args):
-        """GetProjectionRef(self) -> char"""
+        """GetProjectionRef(Dataset self) -> char const *"""
         return _gdal.Dataset_GetProjectionRef(self, *args)
 
     def SetProjection(self, *args):
-        """SetProjection(self, char prj) -> CPLErr"""
+        """SetProjection(Dataset self, char const * prj) -> CPLErr"""
         return _gdal.Dataset_SetProjection(self, *args)
 
     def GetGeoTransform(self, *args, **kwargs):
-        """GetGeoTransform(self, int can_return_null = None)"""
+        """GetGeoTransform(Dataset self, int * can_return_null=None)"""
         return _gdal.Dataset_GetGeoTransform(self, *args, **kwargs)
 
     def SetGeoTransform(self, *args):
-        """SetGeoTransform(self, double argin) -> CPLErr"""
+        """SetGeoTransform(Dataset self, double [6] argin) -> CPLErr"""
         return _gdal.Dataset_SetGeoTransform(self, *args)
 
     def BuildOverviews(self, *args, **kwargs):
         """
-        BuildOverviews(self, char resampling = "NEAREST", int overviewlist = 0, 
-            GDALProgressFunc callback = None, void callback_data = None) -> int
+        BuildOverviews(Dataset self, char const * resampling="NEAREST", int overviewlist=0, GDALProgressFunc callback=0,
+            void * callback_data=None) -> int
         """
         return _gdal.Dataset_BuildOverviews(self, *args, **kwargs)
 
     def GetGCPCount(self, *args):
-        """GetGCPCount(self) -> int"""
+        """GetGCPCount(Dataset self) -> int"""
         return _gdal.Dataset_GetGCPCount(self, *args)
 
     def GetGCPProjection(self, *args):
-        """GetGCPProjection(self) -> char"""
+        """GetGCPProjection(Dataset self) -> char const *"""
         return _gdal.Dataset_GetGCPProjection(self, *args)
 
     def GetGCPs(self, *args):
-        """GetGCPs(self)"""
+        """GetGCPs(Dataset self)"""
         return _gdal.Dataset_GetGCPs(self, *args)
 
     def SetGCPs(self, *args):
-        """SetGCPs(self, int nGCPs, char pszGCPProjection) -> CPLErr"""
+        """SetGCPs(Dataset self, int nGCPs, char const * pszGCPProjection) -> CPLErr"""
         return _gdal.Dataset_SetGCPs(self, *args)
 
     def FlushCache(self, *args):
-        """FlushCache(self)"""
+        """FlushCache(Dataset self)"""
         return _gdal.Dataset_FlushCache(self, *args)
 
     def AddBand(self, *args, **kwargs):
-        """AddBand(self, GDALDataType datatype = GDT_Byte, char options = None) -> CPLErr"""
+        """AddBand(Dataset self, GDALDataType datatype=GDT_Byte, char ** options=None) -> CPLErr"""
         return _gdal.Dataset_AddBand(self, *args, **kwargs)
 
     def CreateMaskBand(self, *args):
-        """CreateMaskBand(self, int nFlags) -> CPLErr"""
+        """CreateMaskBand(Dataset self, int nFlags) -> CPLErr"""
         return _gdal.Dataset_CreateMaskBand(self, *args)
 
     def GetFileList(self, *args):
-        """GetFileList(self) -> char"""
+        """GetFileList(Dataset self) -> char **"""
         return _gdal.Dataset_GetFileList(self, *args)
 
     def WriteRaster(self, *args, **kwargs):
         """
-        WriteRaster(self, int xoff, int yoff, int xsize, int ysize, GIntBig buf_len, 
-            int buf_xsize = None, int buf_ysize = None, 
-            GDALDataType buf_type = None, int band_list = 0, 
-            int buf_pixel_space = None, int buf_line_space = None, 
-            int buf_band_space = None) -> CPLErr
+        WriteRaster(Dataset self, int xoff, int yoff, int xsize, int ysize, GIntBig buf_len, int * buf_xsize=None,
+            int * buf_ysize=None, GDALDataType * buf_type=None, int band_list=0, GIntBig * buf_pixel_space=None,
+            GIntBig * buf_line_space=None, GIntBig * buf_band_space=None) -> CPLErr
         """
         return _gdal.Dataset_WriteRaster(self, *args, **kwargs)
 
     def BeginAsyncReader(self, *args, **kwargs):
         """
-        BeginAsyncReader(self, int xOff, int yOff, int xSize, int ySize, int buf_len, 
-            int buf_xsize, int buf_ysize, GDALDataType bufType = (GDALDataType) 0, 
-            int band_list = 0, 
-            int nPixelSpace = 0, int nLineSpace = 0, 
-            int nBandSpace = 0, char options = None) -> AsyncReader
+        BeginAsyncReader(Dataset self, int xOff, int yOff, int xSize, int ySize, int buf_len, int buf_xsize, int buf_ysize,
+            GDALDataType bufType=(GDALDataType) 0, int band_list=0, int nPixelSpace=0,
+            int nLineSpace=0, int nBandSpace=0, char ** options=None) -> AsyncReader
         """
         return _gdal.Dataset_BeginAsyncReader(self, *args, **kwargs)
 
     def EndAsyncReader(self, *args):
-        """EndAsyncReader(self, AsyncReader ario)"""
+        """EndAsyncReader(Dataset self, AsyncReader ario)"""
         return _gdal.Dataset_EndAsyncReader(self, *args)
 
     def GetVirtualMem(self, *args, **kwargs):
         """
-        GetVirtualMem(self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, 
-            int nYSize, int nBufXSize, int nBufYSize, 
-            GDALDataType eBufType, int band_list, int bIsBandSequential, 
-            size_t nCacheSize, size_t nPageSizeHint, 
-            char options = None) -> VirtualMem
+        GetVirtualMem(Dataset self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, int nBufXSize,
+            int nBufYSize, GDALDataType eBufType, int band_list, int bIsBandSequential,
+            size_t nCacheSize, size_t nPageSizeHint, char ** options=None) -> VirtualMem
         """
         return _gdal.Dataset_GetVirtualMem(self, *args, **kwargs)
 
     def GetTiledVirtualMem(self, *args, **kwargs):
         """
-        GetTiledVirtualMem(self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, 
-            int nYSize, int nTileXSize, int nTileYSize, 
-            GDALDataType eBufType, int band_list, GDALTileOrganization eTileOrganization, 
-            size_t nCacheSize, 
-            char options = None) -> VirtualMem
+        GetTiledVirtualMem(Dataset self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, int nTileXSize,
+            int nTileYSize, GDALDataType eBufType, int band_list, GDALTileOrganization eTileOrganization,
+            size_t nCacheSize, char ** options=None) -> VirtualMem
         """
         return _gdal.Dataset_GetTiledVirtualMem(self, *args, **kwargs)
 
     def CreateLayer(self, *args, **kwargs):
         """
-        CreateLayer(self, char name, SpatialReference srs = None, OGRwkbGeometryType geom_type = wkbUnknown, 
-            char options = None) -> Layer
+        CreateLayer(Dataset self, char const * name, SpatialReference srs=None, OGRwkbGeometryType geom_type=wkbUnknown,
+            char ** options=None) -> Layer
         """
         return _gdal.Dataset_CreateLayer(self, *args, **kwargs)
 
     def CopyLayer(self, *args, **kwargs):
-        """CopyLayer(self, Layer src_layer, char new_name, char options = None) -> Layer"""
+        """CopyLayer(Dataset self, Layer src_layer, char const * new_name, char ** options=None) -> Layer"""
         return _gdal.Dataset_CopyLayer(self, *args, **kwargs)
 
     def DeleteLayer(self, *args):
-        """DeleteLayer(self, int index) -> OGRErr"""
+        """DeleteLayer(Dataset self, int index) -> OGRErr"""
         return _gdal.Dataset_DeleteLayer(self, *args)
 
     def GetLayerCount(self, *args):
-        """GetLayerCount(self) -> int"""
+        """GetLayerCount(Dataset self) -> int"""
         return _gdal.Dataset_GetLayerCount(self, *args)
 
     def GetLayerByIndex(self, *args):
-        """GetLayerByIndex(self, int index = 0) -> Layer"""
+        """GetLayerByIndex(Dataset self, int index=0) -> Layer"""
         return _gdal.Dataset_GetLayerByIndex(self, *args)
 
     def GetLayerByName(self, *args):
-        """GetLayerByName(self, char layer_name) -> Layer"""
+        """GetLayerByName(Dataset self, char const * layer_name) -> Layer"""
         return _gdal.Dataset_GetLayerByName(self, *args)
 
     def TestCapability(self, *args):
-        """TestCapability(self, char cap) -> bool"""
+        """TestCapability(Dataset self, char const * cap) -> bool"""
         return _gdal.Dataset_TestCapability(self, *args)
 
     def ExecuteSQL(self, *args, **kwargs):
-        """ExecuteSQL(self, char statement, Geometry spatialFilter = None, char dialect = "") -> Layer"""
+        """ExecuteSQL(Dataset self, char const * statement, Geometry spatialFilter=None, char const * dialect="") -> Layer"""
         return _gdal.Dataset_ExecuteSQL(self, *args, **kwargs)
 
     def ReleaseResultSet(self, *args):
-        """ReleaseResultSet(self, Layer layer)"""
+        """ReleaseResultSet(Dataset self, Layer layer)"""
         return _gdal.Dataset_ReleaseResultSet(self, *args)
 
     def GetStyleTable(self, *args):
-        """GetStyleTable(self) -> StyleTable"""
+        """GetStyleTable(Dataset self) -> StyleTable"""
         return _gdal.Dataset_GetStyleTable(self, *args)
 
     def SetStyleTable(self, *args):
-        """SetStyleTable(self, StyleTable table)"""
+        """SetStyleTable(Dataset self, StyleTable table)"""
         return _gdal.Dataset_SetStyleTable(self, *args)
 
     def StartTransaction(self, *args, **kwargs):
-        """StartTransaction(self, int force = True) -> OGRErr"""
+        """StartTransaction(Dataset self, int force=False) -> OGRErr"""
         return _gdal.Dataset_StartTransaction(self, *args, **kwargs)
 
     def CommitTransaction(self, *args):
-        """CommitTransaction(self) -> OGRErr"""
+        """CommitTransaction(Dataset self) -> OGRErr"""
         return _gdal.Dataset_CommitTransaction(self, *args)
 
     def RollbackTransaction(self, *args):
-        """RollbackTransaction(self) -> OGRErr"""
+        """RollbackTransaction(Dataset self) -> OGRErr"""
         return _gdal.Dataset_RollbackTransaction(self, *args)
 
     def ReadRaster1(self, *args, **kwargs):
         """
-        ReadRaster1(self, int xoff, int yoff, int xsize, int ysize, int buf_xsize = None, 
-            int buf_ysize = None, GDALDataType buf_type = None, 
-            int band_list = 0, GIntBig buf_pixel_space = None, 
-            GIntBig buf_line_space = None, 
-            GIntBig buf_band_space = None, GDALRIOResampleAlg resample_alg = GRIORA_NearestNeighbour, 
-            GDALProgressFunc callback = None, 
-            void callback_data = None) -> CPLErr
+        ReadRaster1(Dataset self, int xoff, int yoff, int xsize, int ysize, int * buf_xsize=None, int * buf_ysize=None,
+            GDALDataType * buf_type=None, int band_list=0, GIntBig * buf_pixel_space=None,
+            GIntBig * buf_line_space=None, GIntBig * buf_band_space=None, GDALRIOResampleAlg resample_alg=GRIORA_NearestNeighbour,
+            GDALProgressFunc callback=0,
+            void * callback_data=None) -> CPLErr
         """
         return _gdal.Dataset_ReadRaster1(self, *args, **kwargs)
 
@@ -957,7 +1981,7 @@ class Dataset(MajorObject):
 
     def GetSubDatasets(self):
         sd_list = []
-        
+
         sd = self.GetMetadata('SUBDATASETS')
         if sd is None:
             return sd_list
@@ -1037,234 +2061,229 @@ class Band(MajorObject):
     __swig_getmethods__["DataType"] = _gdal.Band_DataType_get
     if _newclass:DataType = _swig_property(_gdal.Band_DataType_get)
     def GetDataset(self, *args):
-        """GetDataset(self) -> Dataset"""
+        """GetDataset(Band self) -> Dataset"""
         return _gdal.Band_GetDataset(self, *args)
 
     def GetBand(self, *args):
-        """GetBand(self) -> int"""
+        """GetBand(Band self) -> int"""
         return _gdal.Band_GetBand(self, *args)
 
     def GetBlockSize(self, *args):
-        """GetBlockSize(self)"""
+        """GetBlockSize(Band self)"""
         return _gdal.Band_GetBlockSize(self, *args)
 
     def GetColorInterpretation(self, *args):
-        """GetColorInterpretation(self) -> GDALColorInterp"""
+        """GetColorInterpretation(Band self) -> GDALColorInterp"""
         return _gdal.Band_GetColorInterpretation(self, *args)
 
     def GetRasterColorInterpretation(self, *args):
-        """GetRasterColorInterpretation(self) -> GDALColorInterp"""
+        """GetRasterColorInterpretation(Band self) -> GDALColorInterp"""
         return _gdal.Band_GetRasterColorInterpretation(self, *args)
 
     def SetColorInterpretation(self, *args):
-        """SetColorInterpretation(self, GDALColorInterp val) -> CPLErr"""
+        """SetColorInterpretation(Band self, GDALColorInterp val) -> CPLErr"""
         return _gdal.Band_SetColorInterpretation(self, *args)
 
     def SetRasterColorInterpretation(self, *args):
-        """SetRasterColorInterpretation(self, GDALColorInterp val) -> CPLErr"""
+        """SetRasterColorInterpretation(Band self, GDALColorInterp val) -> CPLErr"""
         return _gdal.Band_SetRasterColorInterpretation(self, *args)
 
     def GetNoDataValue(self, *args):
-        """GetNoDataValue(self)"""
+        """GetNoDataValue(Band self)"""
         return _gdal.Band_GetNoDataValue(self, *args)
 
     def SetNoDataValue(self, *args):
-        """SetNoDataValue(self, double d) -> CPLErr"""
+        """SetNoDataValue(Band self, double d) -> CPLErr"""
         return _gdal.Band_SetNoDataValue(self, *args)
 
+    def DeleteNoDataValue(self, *args):
+        """DeleteNoDataValue(Band self) -> CPLErr"""
+        return _gdal.Band_DeleteNoDataValue(self, *args)
+
     def GetUnitType(self, *args):
-        """GetUnitType(self) -> char"""
+        """GetUnitType(Band self) -> char const *"""
         return _gdal.Band_GetUnitType(self, *args)
 
     def SetUnitType(self, *args):
-        """SetUnitType(self, char val) -> CPLErr"""
+        """SetUnitType(Band self, char const * val) -> CPLErr"""
         return _gdal.Band_SetUnitType(self, *args)
 
     def GetRasterCategoryNames(self, *args):
-        """GetRasterCategoryNames(self) -> char"""
+        """GetRasterCategoryNames(Band self) -> char **"""
         return _gdal.Band_GetRasterCategoryNames(self, *args)
 
     def SetRasterCategoryNames(self, *args):
-        """SetRasterCategoryNames(self, char names) -> CPLErr"""
+        """SetRasterCategoryNames(Band self, char ** names) -> CPLErr"""
         return _gdal.Band_SetRasterCategoryNames(self, *args)
 
     def GetMinimum(self, *args):
-        """GetMinimum(self)"""
+        """GetMinimum(Band self)"""
         return _gdal.Band_GetMinimum(self, *args)
 
     def GetMaximum(self, *args):
-        """GetMaximum(self)"""
+        """GetMaximum(Band self)"""
         return _gdal.Band_GetMaximum(self, *args)
 
     def GetOffset(self, *args):
-        """GetOffset(self)"""
+        """GetOffset(Band self)"""
         return _gdal.Band_GetOffset(self, *args)
 
     def GetScale(self, *args):
-        """GetScale(self)"""
+        """GetScale(Band self)"""
         return _gdal.Band_GetScale(self, *args)
 
     def SetOffset(self, *args):
-        """SetOffset(self, double val) -> CPLErr"""
+        """SetOffset(Band self, double val) -> CPLErr"""
         return _gdal.Band_SetOffset(self, *args)
 
     def SetScale(self, *args):
-        """SetScale(self, double val) -> CPLErr"""
+        """SetScale(Band self, double val) -> CPLErr"""
         return _gdal.Band_SetScale(self, *args)
 
     def GetStatistics(self, *args):
-        """GetStatistics(self, int approx_ok, int force) -> CPLErr"""
+        """GetStatistics(Band self, int approx_ok, int force) -> CPLErr"""
         return _gdal.Band_GetStatistics(self, *args)
 
     def ComputeStatistics(self, *args):
-        """ComputeStatistics(self, bool approx_ok, GDALProgressFunc callback = None, void callback_data = None) -> CPLErr"""
+        """ComputeStatistics(Band self, bool approx_ok, GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr"""
         return _gdal.Band_ComputeStatistics(self, *args)
 
     def SetStatistics(self, *args):
-        """SetStatistics(self, double min, double max, double mean, double stddev) -> CPLErr"""
+        """SetStatistics(Band self, double min, double max, double mean, double stddev) -> CPLErr"""
         return _gdal.Band_SetStatistics(self, *args)
 
     def GetOverviewCount(self, *args):
-        """GetOverviewCount(self) -> int"""
+        """GetOverviewCount(Band self) -> int"""
         return _gdal.Band_GetOverviewCount(self, *args)
 
     def GetOverview(self, *args):
-        """GetOverview(self, int i) -> Band"""
+        """GetOverview(Band self, int i) -> Band"""
         return _gdal.Band_GetOverview(self, *args)
 
     def Checksum(self, *args, **kwargs):
-        """Checksum(self, int xoff = 0, int yoff = 0, int xsize = None, int ysize = None) -> int"""
+        """Checksum(Band self, int xoff=0, int yoff=0, int * xsize=None, int * ysize=None) -> int"""
         return _gdal.Band_Checksum(self, *args, **kwargs)
 
     def ComputeRasterMinMax(self, *args):
-        """ComputeRasterMinMax(self, int approx_ok = 0)"""
+        """ComputeRasterMinMax(Band self, int approx_ok=0)"""
         return _gdal.Band_ComputeRasterMinMax(self, *args)
 
     def ComputeBandStats(self, *args):
-        """ComputeBandStats(self, int samplestep = 1)"""
+        """ComputeBandStats(Band self, int samplestep=1)"""
         return _gdal.Band_ComputeBandStats(self, *args)
 
     def Fill(self, *args):
-        """Fill(self, double real_fill, double imag_fill = 0.0) -> CPLErr"""
+        """Fill(Band self, double real_fill, double imag_fill=0.0) -> CPLErr"""
         return _gdal.Band_Fill(self, *args)
 
     def WriteRaster(self, *args, **kwargs):
         """
-        WriteRaster(self, int xoff, int yoff, int xsize, int ysize, GIntBig buf_len, 
-            int buf_xsize = None, int buf_ysize = None, 
-            int buf_type = None, int buf_pixel_space = None, 
-            int buf_line_space = None) -> CPLErr
+        WriteRaster(Band self, int xoff, int yoff, int xsize, int ysize, GIntBig buf_len, int * buf_xsize=None,
+            int * buf_ysize=None, int * buf_type=None, GIntBig * buf_pixel_space=None,
+            GIntBig * buf_line_space=None) -> CPLErr
         """
         return _gdal.Band_WriteRaster(self, *args, **kwargs)
 
     def FlushCache(self, *args):
-        """FlushCache(self)"""
+        """FlushCache(Band self)"""
         return _gdal.Band_FlushCache(self, *args)
 
     def GetRasterColorTable(self, *args):
-        """GetRasterColorTable(self) -> ColorTable"""
+        """GetRasterColorTable(Band self) -> ColorTable"""
         return _gdal.Band_GetRasterColorTable(self, *args)
 
     def GetColorTable(self, *args):
-        """GetColorTable(self) -> ColorTable"""
+        """GetColorTable(Band self) -> ColorTable"""
         return _gdal.Band_GetColorTable(self, *args)
 
     def SetRasterColorTable(self, *args):
-        """SetRasterColorTable(self, ColorTable arg) -> int"""
+        """SetRasterColorTable(Band self, ColorTable arg) -> int"""
         return _gdal.Band_SetRasterColorTable(self, *args)
 
     def SetColorTable(self, *args):
-        """SetColorTable(self, ColorTable arg) -> int"""
+        """SetColorTable(Band self, ColorTable arg) -> int"""
         return _gdal.Band_SetColorTable(self, *args)
 
     def GetDefaultRAT(self, *args):
-        """GetDefaultRAT(self) -> RasterAttributeTable"""
+        """GetDefaultRAT(Band self) -> RasterAttributeTable"""
         return _gdal.Band_GetDefaultRAT(self, *args)
 
     def SetDefaultRAT(self, *args):
-        """SetDefaultRAT(self, RasterAttributeTable table) -> int"""
+        """SetDefaultRAT(Band self, RasterAttributeTable table) -> int"""
         return _gdal.Band_SetDefaultRAT(self, *args)
 
     def GetMaskBand(self, *args):
-        """GetMaskBand(self) -> Band"""
+        """GetMaskBand(Band self) -> Band"""
         return _gdal.Band_GetMaskBand(self, *args)
 
     def GetMaskFlags(self, *args):
-        """GetMaskFlags(self) -> int"""
+        """GetMaskFlags(Band self) -> int"""
         return _gdal.Band_GetMaskFlags(self, *args)
 
     def CreateMaskBand(self, *args):
-        """CreateMaskBand(self, int nFlags) -> CPLErr"""
+        """CreateMaskBand(Band self, int nFlags) -> CPLErr"""
         return _gdal.Band_CreateMaskBand(self, *args)
 
     def GetHistogram(self, *args, **kwargs):
         """
-        GetHistogram(self, double min = -0.5, double max = 255.5, int buckets = 256, 
-            int include_out_of_range = 0, int approx_ok = 1, 
-            GDALProgressFunc callback = None, 
-            void callback_data = None) -> CPLErr
+        GetHistogram(Band self, double min=-0.5, double max=255.5, int buckets=256, int include_out_of_range=0, int approx_ok=1,
+            GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr
         """
         return _gdal.Band_GetHistogram(self, *args, **kwargs)
 
     def GetDefaultHistogram(self, *args, **kwargs):
         """
-        GetDefaultHistogram(self, double min_ret = None, double max_ret = None, int buckets_ret = None, 
-            GUIntBig ppanHistogram = None, 
-            int force = 1, GDALProgressFunc callback = None, 
-            void callback_data = None) -> CPLErr
+        GetDefaultHistogram(Band self, double * min_ret=None, double * max_ret=None, int * buckets_ret=None, GUIntBig ** ppanHistogram=None,
+            int force=1, GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr
         """
         return _gdal.Band_GetDefaultHistogram(self, *args, **kwargs)
 
     def SetDefaultHistogram(self, *args):
-        """SetDefaultHistogram(self, double min, double max, int buckets_in) -> CPLErr"""
+        """SetDefaultHistogram(Band self, double min, double max, int buckets_in) -> CPLErr"""
         return _gdal.Band_SetDefaultHistogram(self, *args)
 
     def HasArbitraryOverviews(self, *args):
-        """HasArbitraryOverviews(self) -> bool"""
+        """HasArbitraryOverviews(Band self) -> bool"""
         return _gdal.Band_HasArbitraryOverviews(self, *args)
 
     def GetCategoryNames(self, *args):
-        """GetCategoryNames(self) -> char"""
+        """GetCategoryNames(Band self) -> char **"""
         return _gdal.Band_GetCategoryNames(self, *args)
 
     def SetCategoryNames(self, *args):
-        """SetCategoryNames(self, char papszCategoryNames) -> CPLErr"""
+        """SetCategoryNames(Band self, char ** papszCategoryNames) -> CPLErr"""
         return _gdal.Band_SetCategoryNames(self, *args)
 
     def GetVirtualMem(self, *args, **kwargs):
         """
-        GetVirtualMem(self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, 
-            int nYSize, int nBufXSize, int nBufYSize, 
-            GDALDataType eBufType, size_t nCacheSize, size_t nPageSizeHint, 
-            char options = None) -> VirtualMem
+        GetVirtualMem(Band self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, int nBufXSize,
+            int nBufYSize, GDALDataType eBufType, size_t nCacheSize, size_t nPageSizeHint,
+            char ** options=None) -> VirtualMem
         """
         return _gdal.Band_GetVirtualMem(self, *args, **kwargs)
 
     def GetVirtualMemAuto(self, *args, **kwargs):
-        """GetVirtualMemAuto(self, GDALRWFlag eRWFlag, char options = None) -> VirtualMem"""
+        """GetVirtualMemAuto(Band self, GDALRWFlag eRWFlag, char ** options=None) -> VirtualMem"""
         return _gdal.Band_GetVirtualMemAuto(self, *args, **kwargs)
 
     def GetTiledVirtualMem(self, *args, **kwargs):
         """
-        GetTiledVirtualMem(self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, 
-            int nYSize, int nTileXSize, int nTileYSize, 
-            GDALDataType eBufType, size_t nCacheSize, char options = None) -> VirtualMem
+        GetTiledVirtualMem(Band self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, int nTileXSize,
+            int nTileYSize, GDALDataType eBufType, size_t nCacheSize, char ** options=None) -> VirtualMem
         """
         return _gdal.Band_GetTiledVirtualMem(self, *args, **kwargs)
 
     def ReadRaster1(self, *args, **kwargs):
         """
-        ReadRaster1(self, int xoff, int yoff, int xsize, int ysize, int buf_xsize = None, 
-            int buf_ysize = None, int buf_type = None, 
-            GIntBig buf_pixel_space = None, GIntBig buf_line_space = None, 
-            GDALRIOResampleAlg resample_alg = GRIORA_NearestNeighbour, 
-            GDALProgressFunc callback = None, 
-            void callback_data = None) -> CPLErr
+        ReadRaster1(Band self, double xoff, double yoff, double xsize, double ysize, int * buf_xsize=None, int * buf_ysize=None,
+            int * buf_type=None, GIntBig * buf_pixel_space=None, GIntBig * buf_line_space=None,
+            GDALRIOResampleAlg resample_alg=GRIORA_NearestNeighbour,
+            GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr
         """
         return _gdal.Band_ReadRaster1(self, *args, **kwargs)
 
     def ReadBlock(self, *args, **kwargs):
-        """ReadBlock(self, int xoff, int yoff) -> CPLErr"""
+        """ReadBlock(Band self, int xoff, int yoff) -> CPLErr"""
         return _gdal.Band_ReadBlock(self, *args, **kwargs)
 
     def ReadRaster(self, xoff = 0, yoff = 0, xsize = None, ysize = None,
@@ -1300,7 +2319,7 @@ class Band(MajorObject):
                                             resample_alg = resample_alg,
                                             callback = callback,
                                             callback_data = callback_data)
-      
+
     def WriteArray(self, array, xoff=0, yoff=0,
                    resample_alg = GRIORA_NearestNeighbour,
                    callback = None,
@@ -1377,7 +2396,7 @@ class Band(MajorObject):
 
     def __get_array_interface__(self):
         shape = [1, self.XSize, self.YSize]
-        
+
 
 Band_swigregister = _gdal.Band_swigregister
 Band_swigregister(Band)
@@ -1389,42 +2408,39 @@ class ColorTable(_object):
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, ColorTable, name)
     __repr__ = _swig_repr
-    def __init__(self, *args, **kwargs): 
-        """__init__(self, GDALPaletteInterp palette = GPI_RGB) -> ColorTable"""
+    def __init__(self, *args, **kwargs):
+        """__init__(GDALColorTableShadow self, GDALPaletteInterp palette=GPI_RGB) -> ColorTable"""
         this = _gdal.new_ColorTable(*args, **kwargs)
         try: self.this.append(this)
         except: self.this = this
     __swig_destroy__ = _gdal.delete_ColorTable
     __del__ = lambda self : None;
     def Clone(self, *args):
-        """Clone(self) -> ColorTable"""
+        """Clone(ColorTable self) -> ColorTable"""
         return _gdal.ColorTable_Clone(self, *args)
 
     def GetPaletteInterpretation(self, *args):
-        """GetPaletteInterpretation(self) -> GDALPaletteInterp"""
+        """GetPaletteInterpretation(ColorTable self) -> GDALPaletteInterp"""
         return _gdal.ColorTable_GetPaletteInterpretation(self, *args)
 
     def GetCount(self, *args):
-        """GetCount(self) -> int"""
+        """GetCount(ColorTable self) -> int"""
         return _gdal.ColorTable_GetCount(self, *args)
 
     def GetColorEntry(self, *args):
-        """GetColorEntry(self, int entry) -> ColorEntry"""
+        """GetColorEntry(ColorTable self, int entry) -> ColorEntry"""
         return _gdal.ColorTable_GetColorEntry(self, *args)
 
     def GetColorEntryAsRGB(self, *args):
-        """GetColorEntryAsRGB(self, int entry, ColorEntry centry) -> int"""
+        """GetColorEntryAsRGB(ColorTable self, int entry, ColorEntry centry) -> int"""
         return _gdal.ColorTable_GetColorEntryAsRGB(self, *args)
 
     def SetColorEntry(self, *args):
-        """SetColorEntry(self, int entry, ColorEntry centry)"""
+        """SetColorEntry(ColorTable self, int entry, ColorEntry centry)"""
         return _gdal.ColorTable_SetColorEntry(self, *args)
 
     def CreateColorRamp(self, *args):
-        """
-        CreateColorRamp(self, int nStartIndex, ColorEntry startcolor, int nEndIndex, 
-            ColorEntry endcolor)
-        """
+        """CreateColorRamp(ColorTable self, int nStartIndex, ColorEntry startcolor, int nEndIndex, ColorEntry endcolor)"""
         return _gdal.ColorTable_CreateColorRamp(self, *args)
 
 ColorTable_swigregister = _gdal.ColorTable_swigregister
@@ -1437,91 +2453,91 @@ class RasterAttributeTable(_object):
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, RasterAttributeTable, name)
     __repr__ = _swig_repr
-    def __init__(self, *args): 
-        """__init__(self) -> RasterAttributeTable"""
+    def __init__(self, *args):
+        """__init__(GDALRasterAttributeTableShadow self) -> RasterAttributeTable"""
         this = _gdal.new_RasterAttributeTable(*args)
         try: self.this.append(this)
         except: self.this = this
     __swig_destroy__ = _gdal.delete_RasterAttributeTable
     __del__ = lambda self : None;
     def Clone(self, *args):
-        """Clone(self) -> RasterAttributeTable"""
+        """Clone(RasterAttributeTable self) -> RasterAttributeTable"""
         return _gdal.RasterAttributeTable_Clone(self, *args)
 
     def GetColumnCount(self, *args):
-        """GetColumnCount(self) -> int"""
+        """GetColumnCount(RasterAttributeTable self) -> int"""
         return _gdal.RasterAttributeTable_GetColumnCount(self, *args)
 
     def GetNameOfCol(self, *args):
-        """GetNameOfCol(self, int iCol) -> char"""
+        """GetNameOfCol(RasterAttributeTable self, int iCol) -> char const *"""
         return _gdal.RasterAttributeTable_GetNameOfCol(self, *args)
 
     def GetUsageOfCol(self, *args):
-        """GetUsageOfCol(self, int iCol) -> GDALRATFieldUsage"""
+        """GetUsageOfCol(RasterAttributeTable self, int iCol) -> GDALRATFieldUsage"""
         return _gdal.RasterAttributeTable_GetUsageOfCol(self, *args)
 
     def GetTypeOfCol(self, *args):
-        """GetTypeOfCol(self, int iCol) -> GDALRATFieldType"""
+        """GetTypeOfCol(RasterAttributeTable self, int iCol) -> GDALRATFieldType"""
         return _gdal.RasterAttributeTable_GetTypeOfCol(self, *args)
 
     def GetColOfUsage(self, *args):
-        """GetColOfUsage(self, GDALRATFieldUsage eUsage) -> int"""
+        """GetColOfUsage(RasterAttributeTable self, GDALRATFieldUsage eUsage) -> int"""
         return _gdal.RasterAttributeTable_GetColOfUsage(self, *args)
 
     def GetRowCount(self, *args):
-        """GetRowCount(self) -> int"""
+        """GetRowCount(RasterAttributeTable self) -> int"""
         return _gdal.RasterAttributeTable_GetRowCount(self, *args)
 
     def GetValueAsString(self, *args):
-        """GetValueAsString(self, int iRow, int iCol) -> char"""
+        """GetValueAsString(RasterAttributeTable self, int iRow, int iCol) -> char const *"""
         return _gdal.RasterAttributeTable_GetValueAsString(self, *args)
 
     def GetValueAsInt(self, *args):
-        """GetValueAsInt(self, int iRow, int iCol) -> int"""
+        """GetValueAsInt(RasterAttributeTable self, int iRow, int iCol) -> int"""
         return _gdal.RasterAttributeTable_GetValueAsInt(self, *args)
 
     def GetValueAsDouble(self, *args):
-        """GetValueAsDouble(self, int iRow, int iCol) -> double"""
+        """GetValueAsDouble(RasterAttributeTable self, int iRow, int iCol) -> double"""
         return _gdal.RasterAttributeTable_GetValueAsDouble(self, *args)
 
     def SetValueAsString(self, *args):
-        """SetValueAsString(self, int iRow, int iCol, char pszValue)"""
+        """SetValueAsString(RasterAttributeTable self, int iRow, int iCol, char const * pszValue)"""
         return _gdal.RasterAttributeTable_SetValueAsString(self, *args)
 
     def SetValueAsInt(self, *args):
-        """SetValueAsInt(self, int iRow, int iCol, int nValue)"""
+        """SetValueAsInt(RasterAttributeTable self, int iRow, int iCol, int nValue)"""
         return _gdal.RasterAttributeTable_SetValueAsInt(self, *args)
 
     def SetValueAsDouble(self, *args):
-        """SetValueAsDouble(self, int iRow, int iCol, double dfValue)"""
+        """SetValueAsDouble(RasterAttributeTable self, int iRow, int iCol, double dfValue)"""
         return _gdal.RasterAttributeTable_SetValueAsDouble(self, *args)
 
     def SetRowCount(self, *args):
-        """SetRowCount(self, int nCount)"""
+        """SetRowCount(RasterAttributeTable self, int nCount)"""
         return _gdal.RasterAttributeTable_SetRowCount(self, *args)
 
     def CreateColumn(self, *args):
-        """CreateColumn(self, char pszName, GDALRATFieldType eType, GDALRATFieldUsage eUsage) -> int"""
+        """CreateColumn(RasterAttributeTable self, char const * pszName, GDALRATFieldType eType, GDALRATFieldUsage eUsage) -> int"""
         return _gdal.RasterAttributeTable_CreateColumn(self, *args)
 
     def GetLinearBinning(self, *args):
-        """GetLinearBinning(self) -> bool"""
+        """GetLinearBinning(RasterAttributeTable self) -> bool"""
         return _gdal.RasterAttributeTable_GetLinearBinning(self, *args)
 
     def SetLinearBinning(self, *args):
-        """SetLinearBinning(self, double dfRow0Min, double dfBinSize) -> int"""
+        """SetLinearBinning(RasterAttributeTable self, double dfRow0Min, double dfBinSize) -> int"""
         return _gdal.RasterAttributeTable_SetLinearBinning(self, *args)
 
     def GetRowOfValue(self, *args):
-        """GetRowOfValue(self, double dfValue) -> int"""
+        """GetRowOfValue(RasterAttributeTable self, double dfValue) -> int"""
         return _gdal.RasterAttributeTable_GetRowOfValue(self, *args)
 
     def ChangesAreWrittenToFile(self, *args):
-        """ChangesAreWrittenToFile(self) -> int"""
+        """ChangesAreWrittenToFile(RasterAttributeTable self) -> int"""
         return _gdal.RasterAttributeTable_ChangesAreWrittenToFile(self, *args)
 
     def DumpReadable(self, *args):
-        """DumpReadable(self)"""
+        """DumpReadable(RasterAttributeTable self)"""
         return _gdal.RasterAttributeTable_DumpReadable(self, *args)
 
     def WriteArray(self, array, field, start=0):
@@ -1539,121 +2555,122 @@ RasterAttributeTable_swigregister(RasterAttributeTable)
 
 
 def TermProgress_nocb(*args, **kwargs):
-  """TermProgress_nocb(double dfProgress, char pszMessage = None, void pData = None) -> int"""
+  """TermProgress_nocb(double dfProgress, char const * pszMessage=None, void * pData=None) -> int"""
   return _gdal.TermProgress_nocb(*args, **kwargs)
 TermProgress = _gdal.TermProgress
 
 def ComputeMedianCutPCT(*args, **kwargs):
   """
-    ComputeMedianCutPCT(Band red, Band green, Band blue, int num_colors, ColorTable colors, 
-        GDALProgressFunc callback = None, 
-        void callback_data = None) -> int
+    ComputeMedianCutPCT(Band red, Band green, Band blue, int num_colors, ColorTable colors, GDALProgressFunc callback=0,
+        void * callback_data=None) -> int
     """
   return _gdal.ComputeMedianCutPCT(*args, **kwargs)
 ComputeMedianCutPCT = _gdal.ComputeMedianCutPCT
 
 def DitherRGB2PCT(*args, **kwargs):
   """
-    DitherRGB2PCT(Band red, Band green, Band blue, Band target, ColorTable colors, 
-        GDALProgressFunc callback = None, 
-        void callback_data = None) -> int
+    DitherRGB2PCT(Band red, Band green, Band blue, Band target, ColorTable colors, GDALProgressFunc callback=0,
+        void * callback_data=None) -> int
     """
   return _gdal.DitherRGB2PCT(*args, **kwargs)
 DitherRGB2PCT = _gdal.DitherRGB2PCT
 
-def ReprojectImage(*args):
+def ReprojectImage(*args, **kwargs):
   """
-    ReprojectImage(Dataset src_ds, Dataset dst_ds, char src_wkt = None, 
-        char dst_wkt = None, GDALResampleAlg eResampleAlg = GRA_NearestNeighbour, 
-        double WarpMemoryLimit = 0.0, 
-        double maxerror = 0.0, GDALProgressFunc callback = None, 
-        void callback_data = None) -> CPLErr
+    ReprojectImage(Dataset src_ds, Dataset dst_ds, char const * src_wkt=None, char const * dst_wkt=None,
+        GDALResampleAlg eResampleAlg=GRA_NearestNeighbour, double WarpMemoryLimit=0.0,
+        double maxerror=0.0, GDALProgressFunc callback=0, void * callback_data=None,
+        char ** options=None) -> CPLErr
     """
-  return _gdal.ReprojectImage(*args)
+  return _gdal.ReprojectImage(*args, **kwargs)
 ReprojectImage = _gdal.ReprojectImage
 
 def ComputeProximity(*args, **kwargs):
   """
-    ComputeProximity(Band srcBand, Band proximityBand, char options = None, 
-        GDALProgressFunc callback = None, void callback_data = None) -> int
+    ComputeProximity(Band srcBand, Band proximityBand, char ** options=None, GDALProgressFunc callback=0,
+        void * callback_data=None) -> int
     """
   return _gdal.ComputeProximity(*args, **kwargs)
 ComputeProximity = _gdal.ComputeProximity
 
 def RasterizeLayer(*args, **kwargs):
   """
-    RasterizeLayer(Dataset dataset, int bands, Layer layer, void pfnTransformer = None, 
-        void pTransformArg = None, 
-        int burn_values = 0, char options = None, GDALProgressFunc callback = None, 
-        void callback_data = None) -> int
+    RasterizeLayer(Dataset dataset, int bands, Layer layer, void * pfnTransformer=None, void * pTransformArg=None,
+        int burn_values=0, char ** options=None, GDALProgressFunc callback=0,
+        void * callback_data=None) -> int
     """
   return _gdal.RasterizeLayer(*args, **kwargs)
 RasterizeLayer = _gdal.RasterizeLayer
 
 def Polygonize(*args, **kwargs):
   """
-    Polygonize(Band srcBand, Band maskBand, Layer outLayer, int iPixValField, 
-        char options = None, GDALProgressFunc callback = None, 
-        void callback_data = None) -> int
+    Polygonize(Band srcBand, Band maskBand, Layer outLayer, int iPixValField, char ** options=None,
+        GDALProgressFunc callback=0, void * callback_data=None) -> int
     """
   return _gdal.Polygonize(*args, **kwargs)
 Polygonize = _gdal.Polygonize
 
+def FPolygonize(*args, **kwargs):
+  """
+    FPolygonize(Band srcBand, Band maskBand, Layer outLayer, int iPixValField, char ** options=None,
+        GDALProgressFunc callback=0, void * callback_data=None) -> int
+    """
+  return _gdal.FPolygonize(*args, **kwargs)
+FPolygonize = _gdal.FPolygonize
+
 def FillNodata(*args, **kwargs):
   """
-    FillNodata(Band targetBand, Band maskBand, double maxSearchDist, 
-        int smoothingIterations, char options = None, 
-        GDALProgressFunc callback = None, void callback_data = None) -> int
+    FillNodata(Band targetBand, Band maskBand, double maxSearchDist, int smoothingIterations, char ** options=None,
+        GDALProgressFunc callback=0, void * callback_data=None) -> int
     """
   return _gdal.FillNodata(*args, **kwargs)
 FillNodata = _gdal.FillNodata
 
 def SieveFilter(*args, **kwargs):
   """
-    SieveFilter(Band srcBand, Band maskBand, Band dstBand, int threshold, 
-        int connectedness = 4, char options = None, 
-        GDALProgressFunc callback = None, void callback_data = None) -> int
+    SieveFilter(Band srcBand, Band maskBand, Band dstBand, int threshold, int connectedness=4, char ** options=None,
+        GDALProgressFunc callback=0, void * callback_data=None) -> int
     """
   return _gdal.SieveFilter(*args, **kwargs)
 SieveFilter = _gdal.SieveFilter
 
 def RegenerateOverviews(*args, **kwargs):
   """
-    RegenerateOverviews(Band srcBand, int overviewBandCount, char resampling = "average", 
-        GDALProgressFunc callback = None, 
-        void callback_data = None) -> int
+    RegenerateOverviews(Band srcBand, int overviewBandCount, char const * resampling="average", GDALProgressFunc callback=0,
+        void * callback_data=None) -> int
     """
   return _gdal.RegenerateOverviews(*args, **kwargs)
 RegenerateOverviews = _gdal.RegenerateOverviews
 
 def RegenerateOverview(*args, **kwargs):
   """
-    RegenerateOverview(Band srcBand, Band overviewBand, char resampling = "average", 
-        GDALProgressFunc callback = None, 
-        void callback_data = None) -> int
+    RegenerateOverview(Band srcBand, Band overviewBand, char const * resampling="average", GDALProgressFunc callback=0,
+        void * callback_data=None) -> int
     """
   return _gdal.RegenerateOverview(*args, **kwargs)
 RegenerateOverview = _gdal.RegenerateOverview
 
 def ContourGenerate(*args, **kwargs):
   """
-    ContourGenerate(Band srcBand, double contourInterval, double contourBase, 
-        int fixedLevelCount, int useNoData, double noDataValue, 
-        Layer dstLayer, int idField, 
-        int elevField, GDALProgressFunc callback = None, 
-        void callback_data = None) -> int
+    ContourGenerate(Band srcBand, double contourInterval, double contourBase, int fixedLevelCount, int useNoData,
+        double noDataValue, Layer dstLayer, int idField, int elevField,
+        GDALProgressFunc callback=0, void * callback_data=None) -> int
     """
   return _gdal.ContourGenerate(*args, **kwargs)
 ContourGenerate = _gdal.ContourGenerate
 
 def AutoCreateWarpedVRT(*args):
   """
-    AutoCreateWarpedVRT(Dataset src_ds, char src_wkt = None, char dst_wkt = None, 
-        GDALResampleAlg eResampleAlg = GRA_NearestNeighbour, 
-        double maxerror = 0.0) -> Dataset
+    AutoCreateWarpedVRT(Dataset src_ds, char const * src_wkt=None, char const * dst_wkt=None, GDALResampleAlg eResampleAlg=GRA_NearestNeighbour,
+        double maxerror=0.0) -> Dataset
     """
   return _gdal.AutoCreateWarpedVRT(*args)
 AutoCreateWarpedVRT = _gdal.AutoCreateWarpedVRT
+
+def CreatePansharpenedVRT(*args):
+  """CreatePansharpenedVRT(char const * pszXML, Band panchroBand, int nInputSpectralBands) -> Dataset"""
+  return _gdal.CreatePansharpenedVRT(*args)
+CreatePansharpenedVRT = _gdal.CreatePansharpenedVRT
 class Transformer(_object):
     """Proxy of C++ GDALTransformerInfoShadow class"""
     __swig_setmethods__ = {}
@@ -1661,8 +2678,8 @@ class Transformer(_object):
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, Transformer, name)
     __repr__ = _swig_repr
-    def __init__(self, *args): 
-        """__init__(self, Dataset src, Dataset dst, char options) -> Transformer"""
+    def __init__(self, *args):
+        """__init__(GDALTransformerInfoShadow self, Dataset src, Dataset dst, char ** options) -> Transformer"""
         this = _gdal.new_Transformer(*args)
         try: self.this.append(this)
         except: self.this = this
@@ -1670,20 +2687,19 @@ class Transformer(_object):
     __del__ = lambda self : None;
     def TransformPoint(self, *args):
         """
-        TransformPoint(self, int bDstToSrc, double inout) -> int
-        TransformPoint(self, int bDstToSrc, double x, double y, double z = 0.0) -> int
+        TransformPoint(Transformer self, int bDstToSrc, double [3] inout) -> int
+        TransformPoint(Transformer self, int bDstToSrc, double x, double y, double z=0.0) -> int
         """
         return _gdal.Transformer_TransformPoint(self, *args)
 
     def TransformPoints(self, *args):
-        """TransformPoints(self, int bDstToSrc, int nCount) -> int"""
+        """TransformPoints(Transformer self, int bDstToSrc, int nCount) -> int"""
         return _gdal.Transformer_TransformPoints(self, *args)
 
     def TransformGeolocations(self, *args, **kwargs):
         """
-        TransformGeolocations(self, Band xBand, Band yBand, Band zBand, GDALProgressFunc callback = None, 
-            void callback_data = None, 
-            char options = None) -> int
+        TransformGeolocations(Transformer self, Band xBand, Band yBand, Band zBand, GDALProgressFunc callback=0, void * callback_data=None,
+            char ** options=None) -> int
         """
         return _gdal.Transformer_TransformGeolocations(self, *args, **kwargs)
 
@@ -1692,17 +2708,17 @@ Transformer_swigregister(Transformer)
 
 
 def ApplyGeoTransform(*args):
-  """ApplyGeoTransform(double padfGeoTransform, double dfPixel, double dfLine)"""
+  """ApplyGeoTransform(double [6] padfGeoTransform, double dfPixel, double dfLine)"""
   return _gdal.ApplyGeoTransform(*args)
 ApplyGeoTransform = _gdal.ApplyGeoTransform
 
 def InvGeoTransform(*args):
-  """InvGeoTransform(double gt_in) -> RETURN_NONE"""
+  """InvGeoTransform(double [6] gt_in) -> RETURN_NONE"""
   return _gdal.InvGeoTransform(*args)
 InvGeoTransform = _gdal.InvGeoTransform
 
 def VersionInfo(*args):
-  """VersionInfo(char request = "VERSION_NUM") -> char"""
+  """VersionInfo(char const * request="VERSION_NUM") -> char const *"""
   return _gdal.VersionInfo(*args)
 VersionInfo = _gdal.VersionInfo
 
@@ -1742,27 +2758,27 @@ def DataTypeIsComplex(*args):
 DataTypeIsComplex = _gdal.DataTypeIsComplex
 
 def GetDataTypeName(*args):
-  """GetDataTypeName(GDALDataType eDataType) -> char"""
+  """GetDataTypeName(GDALDataType eDataType) -> char const *"""
   return _gdal.GetDataTypeName(*args)
 GetDataTypeName = _gdal.GetDataTypeName
 
 def GetDataTypeByName(*args):
-  """GetDataTypeByName(char pszDataTypeName) -> GDALDataType"""
+  """GetDataTypeByName(char const * pszDataTypeName) -> GDALDataType"""
   return _gdal.GetDataTypeByName(*args)
 GetDataTypeByName = _gdal.GetDataTypeByName
 
 def GetColorInterpretationName(*args):
-  """GetColorInterpretationName(GDALColorInterp eColorInterp) -> char"""
+  """GetColorInterpretationName(GDALColorInterp eColorInterp) -> char const *"""
   return _gdal.GetColorInterpretationName(*args)
 GetColorInterpretationName = _gdal.GetColorInterpretationName
 
 def GetPaletteInterpretationName(*args):
-  """GetPaletteInterpretationName(GDALPaletteInterp ePaletteInterp) -> char"""
+  """GetPaletteInterpretationName(GDALPaletteInterp ePaletteInterp) -> char const *"""
   return _gdal.GetPaletteInterpretationName(*args)
 GetPaletteInterpretationName = _gdal.GetPaletteInterpretationName
 
 def DecToDMS(*args):
-  """DecToDMS(double arg0, char arg1, int arg2 = 2) -> char"""
+  """DecToDMS(double arg1, char const * arg2, int arg3=2) -> char const *"""
   return _gdal.DecToDMS(*args)
 DecToDMS = _gdal.DecToDMS
 
@@ -1777,22 +2793,22 @@ def DecToPackedDMS(*args):
 DecToPackedDMS = _gdal.DecToPackedDMS
 
 def ParseXMLString(*args):
-  """ParseXMLString(char pszXMLString) -> CPLXMLNode"""
+  """ParseXMLString(char * pszXMLString) -> CPLXMLNode *"""
   return _gdal.ParseXMLString(*args)
 ParseXMLString = _gdal.ParseXMLString
 
 def SerializeXMLTree(*args):
-  """SerializeXMLTree(CPLXMLNode xmlnode) -> retStringAndCPLFree"""
+  """SerializeXMLTree(CPLXMLNode * xmlnode) -> retStringAndCPLFree *"""
   return _gdal.SerializeXMLTree(*args)
 SerializeXMLTree = _gdal.SerializeXMLTree
 
 def GetJPEG2000Structure(*args):
-  """GetJPEG2000Structure(char pszFilename, char options = None) -> CPLXMLNode"""
+  """GetJPEG2000Structure(char const * pszFilename, char ** options=None) -> CPLXMLNode *"""
   return _gdal.GetJPEG2000Structure(*args)
 GetJPEG2000Structure = _gdal.GetJPEG2000Structure
 
 def GetJPEG2000StructureAsString(*args):
-  """GetJPEG2000StructureAsString(char pszFilename, char options = None) -> retStringAndCPLFree"""
+  """GetJPEG2000StructureAsString(char const * pszFilename, char ** options=None) -> retStringAndCPLFree *"""
   return _gdal.GetJPEG2000StructureAsString(*args)
 GetJPEG2000StructureAsString = _gdal.GetJPEG2000StructureAsString
 
@@ -1802,7 +2818,7 @@ def GetDriverCount(*args):
 GetDriverCount = _gdal.GetDriverCount
 
 def GetDriverByName(*args):
-  """GetDriverByName(char name) -> Driver"""
+  """GetDriverByName(char const * name) -> Driver"""
   return _gdal.GetDriverByName(*args)
 GetDriverByName = _gdal.GetDriverByName
 
@@ -1812,34 +2828,297 @@ def GetDriver(*args):
 GetDriver = _gdal.GetDriver
 
 def Open(*args):
-  """Open(char utf8_path, GDALAccess eAccess = GA_ReadOnly) -> Dataset"""
+  """Open(char const * utf8_path, GDALAccess eAccess=GA_ReadOnly) -> Dataset"""
   return _gdal.Open(*args)
 Open = _gdal.Open
 
 def OpenEx(*args, **kwargs):
   """
-    OpenEx(char utf8_path, unsigned int nOpenFlags = 0, char allowed_drivers = None, 
-        char open_options = None, 
-        char sibling_files = None) -> Dataset
+    OpenEx(char const * utf8_path, unsigned int nOpenFlags=0, char ** allowed_drivers=None,
+        char ** open_options=None, char ** sibling_files=None) -> Dataset
     """
   return _gdal.OpenEx(*args, **kwargs)
 OpenEx = _gdal.OpenEx
 
 def OpenShared(*args):
-  """OpenShared(char utf8_path, GDALAccess eAccess = GA_ReadOnly) -> Dataset"""
+  """OpenShared(char const * utf8_path, GDALAccess eAccess=GA_ReadOnly) -> Dataset"""
   return _gdal.OpenShared(*args)
 OpenShared = _gdal.OpenShared
 
 def IdentifyDriver(*args):
-  """IdentifyDriver(char utf8_path, char papszSiblings = None) -> Driver"""
+  """IdentifyDriver(char const * utf8_path, char ** papszSiblings=None) -> Driver"""
   return _gdal.IdentifyDriver(*args)
 IdentifyDriver = _gdal.IdentifyDriver
 
 def GeneralCmdLineProcessor(*args):
-  """GeneralCmdLineProcessor(char papszArgv, int nOptions = 0) -> char"""
+  """GeneralCmdLineProcessor(char ** papszArgv, int nOptions=0) -> char **"""
   return _gdal.GeneralCmdLineProcessor(*args)
 GeneralCmdLineProcessor = _gdal.GeneralCmdLineProcessor
-__version__ = _gdal.VersionInfo("RELEASE_NAME") 
+__version__ = _gdal.VersionInfo("RELEASE_NAME")
+
+class GDALInfoOptions(_object):
+    """Proxy of C++ GDALInfoOptions class"""
+    __swig_setmethods__ = {}
+    __setattr__ = lambda self, name, value: _swig_setattr(self, GDALInfoOptions, name, value)
+    __swig_getmethods__ = {}
+    __getattr__ = lambda self, name: _swig_getattr(self, GDALInfoOptions, name)
+    __repr__ = _swig_repr
+    def __init__(self, *args):
+        """__init__(GDALInfoOptions self, char ** options) -> GDALInfoOptions"""
+        this = _gdal.new_GDALInfoOptions(*args)
+        try: self.this.append(this)
+        except: self.this = this
+    __swig_destroy__ = _gdal.delete_GDALInfoOptions
+    __del__ = lambda self : None;
+GDALInfoOptions_swigregister = _gdal.GDALInfoOptions_swigregister
+GDALInfoOptions_swigregister(GDALInfoOptions)
+
+
+def InfoInternal(*args):
+  """InfoInternal(Dataset hDataset, GDALInfoOptions infoOptions) -> retStringAndCPLFree *"""
+  return _gdal.InfoInternal(*args)
+InfoInternal = _gdal.InfoInternal
+class GDALTranslateOptions(_object):
+    """Proxy of C++ GDALTranslateOptions class"""
+    __swig_setmethods__ = {}
+    __setattr__ = lambda self, name, value: _swig_setattr(self, GDALTranslateOptions, name, value)
+    __swig_getmethods__ = {}
+    __getattr__ = lambda self, name: _swig_getattr(self, GDALTranslateOptions, name)
+    __repr__ = _swig_repr
+    def __init__(self, *args):
+        """__init__(GDALTranslateOptions self, char ** options) -> GDALTranslateOptions"""
+        this = _gdal.new_GDALTranslateOptions(*args)
+        try: self.this.append(this)
+        except: self.this = this
+    __swig_destroy__ = _gdal.delete_GDALTranslateOptions
+    __del__ = lambda self : None;
+GDALTranslateOptions_swigregister = _gdal.GDALTranslateOptions_swigregister
+GDALTranslateOptions_swigregister(GDALTranslateOptions)
+
+
+def TranslateInternal(*args):
+  """
+    TranslateInternal(char const * dest, Dataset dataset, GDALTranslateOptions translateOptions, GDALProgressFunc callback=0,
+        void * callback_data=None) -> Dataset
+    """
+  return _gdal.TranslateInternal(*args)
+TranslateInternal = _gdal.TranslateInternal
+class GDALWarpAppOptions(_object):
+    """Proxy of C++ GDALWarpAppOptions class"""
+    __swig_setmethods__ = {}
+    __setattr__ = lambda self, name, value: _swig_setattr(self, GDALWarpAppOptions, name, value)
+    __swig_getmethods__ = {}
+    __getattr__ = lambda self, name: _swig_getattr(self, GDALWarpAppOptions, name)
+    __repr__ = _swig_repr
+    def __init__(self, *args):
+        """__init__(GDALWarpAppOptions self, char ** options) -> GDALWarpAppOptions"""
+        this = _gdal.new_GDALWarpAppOptions(*args)
+        try: self.this.append(this)
+        except: self.this = this
+    __swig_destroy__ = _gdal.delete_GDALWarpAppOptions
+    __del__ = lambda self : None;
+GDALWarpAppOptions_swigregister = _gdal.GDALWarpAppOptions_swigregister
+GDALWarpAppOptions_swigregister(GDALWarpAppOptions)
+
+
+def wrapper_GDALWarpDestDS(*args):
+  """
+    wrapper_GDALWarpDestDS(Dataset dstDS, int object_list_count, GDALWarpAppOptions warpAppOptions, GDALProgressFunc callback=0,
+        void * callback_data=None) -> int
+    """
+  return _gdal.wrapper_GDALWarpDestDS(*args)
+wrapper_GDALWarpDestDS = _gdal.wrapper_GDALWarpDestDS
+
+def wrapper_GDALWarpDestName(*args):
+  """
+    wrapper_GDALWarpDestName(char const * dest, int object_list_count, GDALWarpAppOptions warpAppOptions, GDALProgressFunc callback=0,
+        void * callback_data=None) -> Dataset
+    """
+  return _gdal.wrapper_GDALWarpDestName(*args)
+wrapper_GDALWarpDestName = _gdal.wrapper_GDALWarpDestName
+class GDALVectorTranslateOptions(_object):
+    """Proxy of C++ GDALVectorTranslateOptions class"""
+    __swig_setmethods__ = {}
+    __setattr__ = lambda self, name, value: _swig_setattr(self, GDALVectorTranslateOptions, name, value)
+    __swig_getmethods__ = {}
+    __getattr__ = lambda self, name: _swig_getattr(self, GDALVectorTranslateOptions, name)
+    __repr__ = _swig_repr
+    def __init__(self, *args):
+        """__init__(GDALVectorTranslateOptions self, char ** options) -> GDALVectorTranslateOptions"""
+        this = _gdal.new_GDALVectorTranslateOptions(*args)
+        try: self.this.append(this)
+        except: self.this = this
+    __swig_destroy__ = _gdal.delete_GDALVectorTranslateOptions
+    __del__ = lambda self : None;
+GDALVectorTranslateOptions_swigregister = _gdal.GDALVectorTranslateOptions_swigregister
+GDALVectorTranslateOptions_swigregister(GDALVectorTranslateOptions)
+
+
+def wrapper_GDALVectorTranslateDestDS(*args):
+  """
+    wrapper_GDALVectorTranslateDestDS(Dataset dstDS, Dataset srcDS, GDALVectorTranslateOptions options, GDALProgressFunc callback=0,
+        void * callback_data=None) -> int
+    """
+  return _gdal.wrapper_GDALVectorTranslateDestDS(*args)
+wrapper_GDALVectorTranslateDestDS = _gdal.wrapper_GDALVectorTranslateDestDS
+
+def wrapper_GDALVectorTranslateDestName(*args):
+  """
+    wrapper_GDALVectorTranslateDestName(char const * dest, Dataset srcDS, GDALVectorTranslateOptions options, GDALProgressFunc callback=0,
+        void * callback_data=None) -> Dataset
+    """
+  return _gdal.wrapper_GDALVectorTranslateDestName(*args)
+wrapper_GDALVectorTranslateDestName = _gdal.wrapper_GDALVectorTranslateDestName
+class GDALDEMProcessingOptions(_object):
+    """Proxy of C++ GDALDEMProcessingOptions class"""
+    __swig_setmethods__ = {}
+    __setattr__ = lambda self, name, value: _swig_setattr(self, GDALDEMProcessingOptions, name, value)
+    __swig_getmethods__ = {}
+    __getattr__ = lambda self, name: _swig_getattr(self, GDALDEMProcessingOptions, name)
+    __repr__ = _swig_repr
+    def __init__(self, *args):
+        """__init__(GDALDEMProcessingOptions self, char ** options) -> GDALDEMProcessingOptions"""
+        this = _gdal.new_GDALDEMProcessingOptions(*args)
+        try: self.this.append(this)
+        except: self.this = this
+    __swig_destroy__ = _gdal.delete_GDALDEMProcessingOptions
+    __del__ = lambda self : None;
+GDALDEMProcessingOptions_swigregister = _gdal.GDALDEMProcessingOptions_swigregister
+GDALDEMProcessingOptions_swigregister(GDALDEMProcessingOptions)
+
+
+def DEMProcessingInternal(*args):
+  """
+    DEMProcessingInternal(char const * dest, Dataset dataset, char const * pszProcessing, char const * pszColorFilename,
+        GDALDEMProcessingOptions options, GDALProgressFunc callback=0,
+        void * callback_data=None) -> Dataset
+    """
+  return _gdal.DEMProcessingInternal(*args)
+DEMProcessingInternal = _gdal.DEMProcessingInternal
+class GDALNearblackOptions(_object):
+    """Proxy of C++ GDALNearblackOptions class"""
+    __swig_setmethods__ = {}
+    __setattr__ = lambda self, name, value: _swig_setattr(self, GDALNearblackOptions, name, value)
+    __swig_getmethods__ = {}
+    __getattr__ = lambda self, name: _swig_getattr(self, GDALNearblackOptions, name)
+    __repr__ = _swig_repr
+    def __init__(self, *args):
+        """__init__(GDALNearblackOptions self, char ** options) -> GDALNearblackOptions"""
+        this = _gdal.new_GDALNearblackOptions(*args)
+        try: self.this.append(this)
+        except: self.this = this
+    __swig_destroy__ = _gdal.delete_GDALNearblackOptions
+    __del__ = lambda self : None;
+GDALNearblackOptions_swigregister = _gdal.GDALNearblackOptions_swigregister
+GDALNearblackOptions_swigregister(GDALNearblackOptions)
+
+
+def wrapper_GDALNearblackDestDS(*args):
+  """
+    wrapper_GDALNearblackDestDS(Dataset dstDS, Dataset srcDS, GDALNearblackOptions options, GDALProgressFunc callback=0,
+        void * callback_data=None) -> int
+    """
+  return _gdal.wrapper_GDALNearblackDestDS(*args)
+wrapper_GDALNearblackDestDS = _gdal.wrapper_GDALNearblackDestDS
+
+def wrapper_GDALNearblackDestName(*args):
+  """
+    wrapper_GDALNearblackDestName(char const * dest, Dataset srcDS, GDALNearblackOptions options, GDALProgressFunc callback=0,
+        void * callback_data=None) -> Dataset
+    """
+  return _gdal.wrapper_GDALNearblackDestName(*args)
+wrapper_GDALNearblackDestName = _gdal.wrapper_GDALNearblackDestName
+class GDALGridOptions(_object):
+    """Proxy of C++ GDALGridOptions class"""
+    __swig_setmethods__ = {}
+    __setattr__ = lambda self, name, value: _swig_setattr(self, GDALGridOptions, name, value)
+    __swig_getmethods__ = {}
+    __getattr__ = lambda self, name: _swig_getattr(self, GDALGridOptions, name)
+    __repr__ = _swig_repr
+    def __init__(self, *args):
+        """__init__(GDALGridOptions self, char ** options) -> GDALGridOptions"""
+        this = _gdal.new_GDALGridOptions(*args)
+        try: self.this.append(this)
+        except: self.this = this
+    __swig_destroy__ = _gdal.delete_GDALGridOptions
+    __del__ = lambda self : None;
+GDALGridOptions_swigregister = _gdal.GDALGridOptions_swigregister
+GDALGridOptions_swigregister(GDALGridOptions)
+
 
+def GridInternal(*args):
+  """
+    GridInternal(char const * dest, Dataset dataset, GDALGridOptions options, GDALProgressFunc callback=0,
+        void * callback_data=None) -> Dataset
+    """
+  return _gdal.GridInternal(*args)
+GridInternal = _gdal.GridInternal
+class GDALRasterizeOptions(_object):
+    """Proxy of C++ GDALRasterizeOptions class"""
+    __swig_setmethods__ = {}
+    __setattr__ = lambda self, name, value: _swig_setattr(self, GDALRasterizeOptions, name, value)
+    __swig_getmethods__ = {}
+    __getattr__ = lambda self, name: _swig_getattr(self, GDALRasterizeOptions, name)
+    __repr__ = _swig_repr
+    def __init__(self, *args):
+        """__init__(GDALRasterizeOptions self, char ** options) -> GDALRasterizeOptions"""
+        this = _gdal.new_GDALRasterizeOptions(*args)
+        try: self.this.append(this)
+        except: self.this = this
+    __swig_destroy__ = _gdal.delete_GDALRasterizeOptions
+    __del__ = lambda self : None;
+GDALRasterizeOptions_swigregister = _gdal.GDALRasterizeOptions_swigregister
+GDALRasterizeOptions_swigregister(GDALRasterizeOptions)
+
+
+def wrapper_GDALRasterizeDestDS(*args):
+  """
+    wrapper_GDALRasterizeDestDS(Dataset dstDS, Dataset srcDS, GDALRasterizeOptions options, GDALProgressFunc callback=0,
+        void * callback_data=None) -> int
+    """
+  return _gdal.wrapper_GDALRasterizeDestDS(*args)
+wrapper_GDALRasterizeDestDS = _gdal.wrapper_GDALRasterizeDestDS
+
+def wrapper_GDALRasterizeDestName(*args):
+  """
+    wrapper_GDALRasterizeDestName(char const * dest, Dataset srcDS, GDALRasterizeOptions options, GDALProgressFunc callback=0,
+        void * callback_data=None) -> Dataset
+    """
+  return _gdal.wrapper_GDALRasterizeDestName(*args)
+wrapper_GDALRasterizeDestName = _gdal.wrapper_GDALRasterizeDestName
+class GDALBuildVRTOptions(_object):
+    """Proxy of C++ GDALBuildVRTOptions class"""
+    __swig_setmethods__ = {}
+    __setattr__ = lambda self, name, value: _swig_setattr(self, GDALBuildVRTOptions, name, value)
+    __swig_getmethods__ = {}
+    __getattr__ = lambda self, name: _swig_getattr(self, GDALBuildVRTOptions, name)
+    __repr__ = _swig_repr
+    def __init__(self, *args):
+        """__init__(GDALBuildVRTOptions self, char ** options) -> GDALBuildVRTOptions"""
+        this = _gdal.new_GDALBuildVRTOptions(*args)
+        try: self.this.append(this)
+        except: self.this = this
+    __swig_destroy__ = _gdal.delete_GDALBuildVRTOptions
+    __del__ = lambda self : None;
+GDALBuildVRTOptions_swigregister = _gdal.GDALBuildVRTOptions_swigregister
+GDALBuildVRTOptions_swigregister(GDALBuildVRTOptions)
+
+
+def BuildVRTInternalObjects(*args):
+  """
+    BuildVRTInternalObjects(char const * dest, int object_list_count, GDALBuildVRTOptions options, GDALProgressFunc callback=0,
+        void * callback_data=None) -> Dataset
+    """
+  return _gdal.BuildVRTInternalObjects(*args)
+BuildVRTInternalObjects = _gdal.BuildVRTInternalObjects
+
+def BuildVRTInternalNames(*args):
+  """
+    BuildVRTInternalNames(char const * dest, char ** source_filenames, GDALBuildVRTOptions options, GDALProgressFunc callback=0,
+        void * callback_data=None) -> Dataset
+    """
+  return _gdal.BuildVRTInternalNames(*args)
+BuildVRTInternalNames = _gdal.BuildVRTInternalNames
+# This file is compatible with both classic and new-style classes.
 
 
diff --git a/swig/python/osgeo/gdal_array.py b/swig/python/osgeo/gdal_array.py
index f09960c..8d604b9 100644
--- a/swig/python/osgeo/gdal_array.py
+++ b/swig/python/osgeo/gdal_array.py
@@ -1,9 +1,12 @@
 # This file was automatically generated by SWIG (http://www.swig.org).
-# Version 1.3.40
+# Version 2.0.12
 #
 # Do not make changes to this file unless you know what you are doing--modify
 # the SWIG interface file instead.
-# This file is compatible with both classic and new-style classes.
+
+
+
+
 
 from sys import version_info
 if version_info >= (2,6,0):
@@ -39,7 +42,7 @@ def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
             return
     method = class_type.__swig_setmethods__.get(name,None)
     if method: return method(self,value)
-    if (not static) or hasattr(self,name):
+    if (not static):
         self.__dict__[name] = value
     else:
         raise AttributeError("You cannot add attributes to %s" % self)
@@ -78,15 +81,15 @@ class VirtualMem(_object):
     __swig_destroy__ = _gdal_array.delete_VirtualMem
     __del__ = lambda self : None;
     def GetAddr(self):
-        """GetAddr(self)"""
+        """GetAddr(VirtualMem self)"""
         return _gdal_array.VirtualMem_GetAddr(self)
 
-    def Pin(self, start_offset = 0, nsize = 0, bWriteOp = 0):
+    def Pin(self, start_offset=0, nsize=0, bWriteOp=0):
         """
-        Pin(self, size_t start_offset = 0, size_t nsize = 0, int bWriteOp = 0)
-        Pin(self, size_t start_offset = 0, size_t nsize = 0)
-        Pin(self, size_t start_offset = 0)
-        Pin(self)
+        Pin(VirtualMem self, size_t start_offset=0, size_t nsize=0, int bWriteOp=0)
+        Pin(VirtualMem self, size_t start_offset=0, size_t nsize=0)
+        Pin(VirtualMem self, size_t start_offset=0)
+        Pin(VirtualMem self)
         """
         return _gdal_array.VirtualMem_Pin(self, start_offset, nsize, bWriteOp)
 
@@ -95,31 +98,34 @@ VirtualMem_swigregister(VirtualMem)
 
 
 def TermProgress_nocb(*args, **kwargs):
-  """TermProgress_nocb(double dfProgress, char pszMessage = None, void pData = None) -> int"""
+  """TermProgress_nocb(double dfProgress, char const * pszMessage=None, void * pData=None) -> int"""
   return _gdal_array.TermProgress_nocb(*args, **kwargs)
 TermProgress = _gdal_array.TermProgress
 
+def OpenNumPyArray(*args):
+  """OpenNumPyArray(PyArrayObject * psArray) -> Dataset"""
+  return _gdal_array.OpenNumPyArray(*args)
+OpenNumPyArray = _gdal_array.OpenNumPyArray
+
 def GetArrayFilename(*args):
-  """GetArrayFilename(PyArrayObject psArray) -> retStringAndCPLFree"""
+  """GetArrayFilename(PyArrayObject * psArray) -> retStringAndCPLFree *"""
   return _gdal_array.GetArrayFilename(*args)
 GetArrayFilename = _gdal_array.GetArrayFilename
 
 def BandRasterIONumPy(*args, **kwargs):
   """
-    BandRasterIONumPy(Band band, int bWrite, int xoff, int yoff, int xsize, 
-        int ysize, PyArrayObject psArray, int buf_type, 
-        GDALRIOResampleAlg resample_alg, GDALProgressFunc callback = None, 
-        void callback_data = None) -> CPLErr
+    BandRasterIONumPy(Band band, int bWrite, double xoff, double yoff, double xsize, double ysize, PyArrayObject * psArray,
+        int buf_type, GDALRIOResampleAlg resample_alg, GDALProgressFunc callback=0,
+        void * callback_data=None) -> CPLErr
     """
   return _gdal_array.BandRasterIONumPy(*args, **kwargs)
 BandRasterIONumPy = _gdal_array.BandRasterIONumPy
 
 def DatasetIONumPy(*args, **kwargs):
   """
-    DatasetIONumPy(Dataset ds, int bWrite, int xoff, int yoff, int xsize, 
-        int ysize, PyArrayObject psArray, int buf_type, 
-        GDALRIOResampleAlg resample_alg, GDALProgressFunc callback = None, 
-        void callback_data = None) -> CPLErr
+    DatasetIONumPy(Dataset ds, int bWrite, int xoff, int yoff, int xsize, int ysize, PyArrayObject * psArray,
+        int buf_type, GDALRIOResampleAlg resample_alg, GDALProgressFunc callback=0,
+        void * callback_data=None) -> CPLErr
     """
   return _gdal_array.DatasetIONumPy(*args, **kwargs)
 DatasetIONumPy = _gdal_array.DatasetIONumPy
@@ -130,18 +136,12 @@ def VirtualMemGetArray(*args):
 VirtualMemGetArray = _gdal_array.VirtualMemGetArray
 
 def RATValuesIONumPyWrite(*args, **kwargs):
-  """
-    RATValuesIONumPyWrite(RasterAttributeTable poRAT, int nField, int nStart, 
-        PyArrayObject psArray) -> CPLErr
-    """
+  """RATValuesIONumPyWrite(RasterAttributeTable poRAT, int nField, int nStart, PyArrayObject * psArray) -> CPLErr"""
   return _gdal_array.RATValuesIONumPyWrite(*args, **kwargs)
 RATValuesIONumPyWrite = _gdal_array.RATValuesIONumPyWrite
 
 def RATValuesIONumPyRead(*args, **kwargs):
-  """
-    RATValuesIONumPyRead(RasterAttributeTable poRAT, int nField, int nStart, 
-        int nLength) -> PyObject
-    """
+  """RATValuesIONumPyRead(RasterAttributeTable poRAT, int nField, int nStart, int nLength) -> PyObject *"""
   return _gdal_array.RATValuesIONumPyRead(*args, **kwargs)
 RATValuesIONumPyRead = _gdal_array.RATValuesIONumPyRead
 import numpy
@@ -166,17 +166,17 @@ codes = {   gdalconst.GDT_Byte      :   numpy.uint8,
 
 def OpenArray( array, prototype_ds = None ):
 
-    ds = gdal.Open( GetArrayFilename(array) )
+    ds = OpenNumPyArray( array )
 
     if ds is not None and prototype_ds is not None:
         if type(prototype_ds).__name__ == 'str':
             prototype_ds = gdal.Open( prototype_ds )
         if prototype_ds is not None:
             CopyDatasetInfo( prototype_ds, ds )
-            
+
     return ds
-    
-    
+
+
 def flip_code(code):
     if isinstance(code, (numpy.dtype,type)):
         # since several things map to complex64 we must carefully select
@@ -185,7 +185,7 @@ def flip_code(code):
             return gdalconst.GDT_Byte
         if code == numpy.complex64:
             return gdalconst.GDT_CFloat32
-        
+
         for key, value in codes.items():
             if value == code:
                 return key
@@ -203,7 +203,7 @@ def NumericTypeCodeToGDALTypeCode(numeric_type):
 
 def GDALTypeCodeToNumericTypeCode(gdal_code):
     return flip_code(gdal_code)
-    
+
 def LoadFile( filename, xoff=0, yoff=0, xsize=None, ysize=None,
               buf_xsize=None, buf_ysize=None, buf_type=None,
               resample_alg = gdal.GRIORA_NearestNeighbour,
@@ -372,7 +372,7 @@ def BandWriteArray( band, array, xoff=0, yoff=0,
         gdal.Debug( 'gdal_array', 'force array to float64' )
         array = array.astype( numpy.float64 )
         datatype = NumericTypeCodeToGDALTypeCode( array.dtype.type )
-        
+
     if not datatype:
         raise ValueError("array does not have corresponding GDAL data type")
 
@@ -423,28 +423,28 @@ def RATReadArray(rat, field, start=0, length=None):
         length = rat.GetRowCount() - start
 
     return RATValuesIONumPyRead(rat, field, start, length)
-    
+
 def CopyDatasetInfo( src, dst, xoff=0, yoff=0 ):
     """
     Copy georeferencing information and metadata from one dataset to another.
     src: input dataset
-    dst: output dataset - It can be a ROI - 
-    xoff, yoff:  dst's offset with respect to src in pixel/line.  
-    
+    dst: output dataset - It can be a ROI -
+    xoff, yoff:  dst's offset with respect to src in pixel/line.
+
     Notes: Destination dataset must have update access.  Certain formats
            do not support creation of geotransforms and/or gcps.
 
     """
 
     dst.SetMetadata( src.GetMetadata() )
-                    
+
 
 
     #Check for geo transform
     gt = src.GetGeoTransform()
     if gt != (0,1,0,0,0,1):
         dst.SetProjection( src.GetProjectionRef() )
-        
+
         if (xoff == 0) and (yoff == 0):
             dst.SetGeoTransform( gt  )
         else:
@@ -452,10 +452,10 @@ def CopyDatasetInfo( src, dst, xoff=0, yoff=0 ):
             ngt[0] = gt[0] + xoff*gt[1] + yoff*gt[2];
             ngt[3] = gt[3] + xoff*gt[4] + yoff*gt[5];
             dst.SetGeoTransform( ( ngt[0], ngt[1], ngt[2], ngt[3], ngt[4], ngt[5] ) )
-            
+
     #Check for GCPs
     elif src.GetGCPCount() > 0:
-        
+
         if (xoff == 0) and (yoff == 0):
             dst.SetGCPs( src.GetGCPs(), src.GetGCPProjection() )
         else:
@@ -464,7 +464,7 @@ def CopyDatasetInfo( src, dst, xoff=0, yoff=0 ):
             new_gcps = []
             for gcp in gcps:
                 ngcp = gdal.GCP()
-                ngcp.GCPX = gcp.GCPX 
+                ngcp.GCPX = gcp.GCPX
                 ngcp.GCPY = gcp.GCPY
                 ngcp.GCPZ = gcp.GCPZ
                 ngcp.GCPPixel = gcp.GCPPixel - xoff
@@ -481,5 +481,6 @@ def CopyDatasetInfo( src, dst, xoff=0, yoff=0 ):
 
     return
 
+# This file is compatible with both classic and new-style classes.
 
 
diff --git a/swig/python/osgeo/gdalconst.py b/swig/python/osgeo/gdalconst.py
index 425cdf3..7477963 100644
--- a/swig/python/osgeo/gdalconst.py
+++ b/swig/python/osgeo/gdalconst.py
@@ -1,9 +1,12 @@
 # This file was automatically generated by SWIG (http://www.swig.org).
-# Version 1.3.40
+# Version 2.0.12
 #
 # Do not make changes to this file unless you know what you are doing--modify
 # the SWIG interface file instead.
-# This file is compatible with both classic and new-style classes.
+
+
+
+
 
 from sys import version_info
 if version_info >= (2,6,0):
@@ -39,7 +42,7 @@ def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
             return
     method = class_type.__swig_setmethods__.get(name,None)
     if method: return method(self,value)
-    if (not static) or hasattr(self,name):
+    if (not static):
         self.__dict__[name] = value
     else:
         raise AttributeError("You cannot add attributes to %s" % self)
@@ -142,6 +145,7 @@ CPLE_UserInterrupt = _gdalconst.CPLE_UserInterrupt
 OF_ALL = _gdalconst.OF_ALL
 OF_RASTER = _gdalconst.OF_RASTER
 OF_VECTOR = _gdalconst.OF_VECTOR
+OF_GNM = _gdalconst.OF_GNM
 OF_READONLY = _gdalconst.OF_READONLY
 OF_UPDATE = _gdalconst.OF_UPDATE
 OF_SHARED = _gdalconst.OF_SHARED
@@ -203,5 +207,6 @@ GARIO_COMPLETE = _gdalconst.GARIO_COMPLETE
 GTO_TIP = _gdalconst.GTO_TIP
 GTO_BIT = _gdalconst.GTO_BIT
 GTO_BSQ = _gdalconst.GTO_BSQ
+# This file is compatible with both classic and new-style classes.
 
 
diff --git a/swig/python/osgeo/gnm.py b/swig/python/osgeo/gnm.py
new file mode 100644
index 0000000..065db15
--- /dev/null
+++ b/swig/python/osgeo/gnm.py
@@ -0,0 +1,277 @@
+# This file was automatically generated by SWIG (http://www.swig.org).
+# Version 2.0.12
+#
+# Do not make changes to this file unless you know what you are doing--modify
+# the SWIG interface file instead.
+
+
+
+
+
+from sys import version_info
+if version_info >= (2,6,0):
+    def swig_import_helper():
+        from os.path import dirname
+        import imp
+        fp = None
+        try:
+            fp, pathname, description = imp.find_module('_gnm', [dirname(__file__)])
+        except ImportError:
+            import _gnm
+            return _gnm
+        if fp is not None:
+            try:
+                _mod = imp.load_module('_gnm', fp, pathname, description)
+            finally:
+                fp.close()
+            return _mod
+    _gnm = swig_import_helper()
+    del swig_import_helper
+else:
+    import _gnm
+del version_info
+try:
+    _swig_property = property
+except NameError:
+    pass # Python < 2.2 doesn't have 'property'.
+def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
+    if (name == "thisown"): return self.this.own(value)
+    if (name == "this"):
+        if type(value).__name__ == 'SwigPyObject':
+            self.__dict__[name] = value
+            return
+    method = class_type.__swig_setmethods__.get(name,None)
+    if method: return method(self,value)
+    if (not static):
+        self.__dict__[name] = value
+    else:
+        raise AttributeError("You cannot add attributes to %s" % self)
+
+def _swig_setattr(self,class_type,name,value):
+    return _swig_setattr_nondynamic(self,class_type,name,value,0)
+
+def _swig_getattr(self,class_type,name):
+    if (name == "thisown"): return self.this.own()
+    method = class_type.__swig_getmethods__.get(name,None)
+    if method: return method(self)
+    raise AttributeError(name)
+
+def _swig_repr(self):
+    try: strthis = "proxy of " + self.this.__repr__()
+    except: strthis = ""
+    return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+try:
+    _object = object
+    _newclass = 1
+except AttributeError:
+    class _object : pass
+    _newclass = 0
+
+
+
+def GetUseExceptions(*args):
+  return _gnm.GetUseExceptions(*args)
+GetUseExceptions = _gnm.GetUseExceptions
+
+def UseExceptions(*args):
+  return _gnm.UseExceptions(*args)
+UseExceptions = _gnm.UseExceptions
+
+def DontUseExceptions(*args):
+  return _gnm.DontUseExceptions(*args)
+DontUseExceptions = _gnm.DontUseExceptions
+class MajorObject(_object):
+    __swig_setmethods__ = {}
+    __setattr__ = lambda self, name, value: _swig_setattr(self, MajorObject, name, value)
+    __swig_getmethods__ = {}
+    __getattr__ = lambda self, name: _swig_getattr(self, MajorObject, name)
+    def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+    def GetDescription(self, *args): return _gnm.MajorObject_GetDescription(self, *args)
+    def SetDescription(self, *args): return _gnm.MajorObject_SetDescription(self, *args)
+    def GetMetadataDomainList(self, *args): return _gnm.MajorObject_GetMetadataDomainList(self, *args)
+    def GetMetadata_Dict(self, *args): return _gnm.MajorObject_GetMetadata_Dict(self, *args)
+    def GetMetadata_List(self, *args): return _gnm.MajorObject_GetMetadata_List(self, *args)
+    def SetMetadata(self, *args): return _gnm.MajorObject_SetMetadata(self, *args)
+    def GetMetadataItem(self, *args): return _gnm.MajorObject_GetMetadataItem(self, *args)
+    def SetMetadataItem(self, *args): return _gnm.MajorObject_SetMetadataItem(self, *args)
+MajorObject_swigregister = _gnm.MajorObject_swigregister
+MajorObject_swigregister(MajorObject)
+
+GATDijkstraShortestPath = _gnm.GATDijkstraShortestPath
+GATKShortestPath = _gnm.GATKShortestPath
+GATConnectedComponents = _gnm.GATConnectedComponents
+GNM_EDGE_DIR_BOTH = _gnm.GNM_EDGE_DIR_BOTH
+GNM_EDGE_DIR_SRCTOTGT = _gnm.GNM_EDGE_DIR_SRCTOTGT
+GNM_EDGE_DIR_TGTTOSRC = _gnm.GNM_EDGE_DIR_TGTTOSRC
+
+def CastToNetwork(*args):
+  """CastToNetwork(MajorObject base) -> Network"""
+  return _gnm.CastToNetwork(*args)
+
+def CastToGenericNetwork(*args):
+  """CastToGenericNetwork(MajorObject base) -> GenericNetwork"""
+  return _gnm.CastToGenericNetwork(*args)
+class Network(MajorObject):
+    """Proxy of C++ GNMNetworkShadow class"""
+    __swig_setmethods__ = {}
+    for _s in [MajorObject]: __swig_setmethods__.update(getattr(_s,'__swig_setmethods__',{}))
+    __setattr__ = lambda self, name, value: _swig_setattr(self, Network, name, value)
+    __swig_getmethods__ = {}
+    for _s in [MajorObject]: __swig_getmethods__.update(getattr(_s,'__swig_getmethods__',{}))
+    __getattr__ = lambda self, name: _swig_getattr(self, Network, name)
+    def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+    __swig_destroy__ = _gnm.delete_Network
+    __del__ = lambda self : None;
+    def ReleaseResultSet(self, *args):
+        """ReleaseResultSet(Network self, OGRLayerShadow * layer)"""
+        return _gnm.Network_ReleaseResultSet(self, *args)
+
+    def GetVersion(self, *args):
+        """GetVersion(Network self) -> int"""
+        return _gnm.Network_GetVersion(self, *args)
+
+    def GetName(self, *args):
+        """GetName(Network self) -> char const *"""
+        return _gnm.Network_GetName(self, *args)
+
+    def GetFeatureByGlobalFID(self, *args):
+        """GetFeatureByGlobalFID(Network self, GIntBig GFID) -> OGRFeatureShadow *"""
+        return _gnm.Network_GetFeatureByGlobalFID(self, *args)
+
+    def GetPath(self, *args, **kwargs):
+        """GetPath(Network self, GIntBig nStartFID, GIntBig nEndFID, GNMGraphAlgorithmType eAlgorithm, char ** options=None) -> OGRLayerShadow *"""
+        return _gnm.Network_GetPath(self, *args, **kwargs)
+
+    def DisconnectAll(self, *args):
+        """DisconnectAll(Network self) -> CPLErr"""
+        return _gnm.Network_DisconnectAll(self, *args)
+
+    def GetProjection(self, *args):
+        """GetProjection(Network self) -> char const *"""
+        return _gnm.Network_GetProjection(self, *args)
+
+    def GetProjectionRef(self, *args):
+        """GetProjectionRef(Network self) -> char const *"""
+        return _gnm.Network_GetProjectionRef(self, *args)
+
+    def GetFileList(self, *args):
+        """GetFileList(Network self) -> char **"""
+        return _gnm.Network_GetFileList(self, *args)
+
+    def CreateLayer(self, *args, **kwargs):
+        """
+        CreateLayer(Network self, char const * name, OSRSpatialReferenceShadow * srs=None, OGRwkbGeometryType geom_type=wkbUnknown,
+            char ** options=None) -> OGRLayerShadow *
+        """
+        return _gnm.Network_CreateLayer(self, *args, **kwargs)
+
+    def CopyLayer(self, *args, **kwargs):
+        """CopyLayer(Network self, OGRLayerShadow * src_layer, char const * new_name, char ** options=None) -> OGRLayerShadow *"""
+        return _gnm.Network_CopyLayer(self, *args, **kwargs)
+
+    def DeleteLayer(self, *args):
+        """DeleteLayer(Network self, int index) -> OGRErr"""
+        return _gnm.Network_DeleteLayer(self, *args)
+
+    def GetLayerCount(self, *args):
+        """GetLayerCount(Network self) -> int"""
+        return _gnm.Network_GetLayerCount(self, *args)
+
+    def GetLayerByIndex(self, *args):
+        """GetLayerByIndex(Network self, int index=0) -> OGRLayerShadow *"""
+        return _gnm.Network_GetLayerByIndex(self, *args)
+
+    def GetLayerByName(self, *args):
+        """GetLayerByName(Network self, char const * layer_name) -> OGRLayerShadow *"""
+        return _gnm.Network_GetLayerByName(self, *args)
+
+    def TestCapability(self, *args):
+        """TestCapability(Network self, char const * cap) -> bool"""
+        return _gnm.Network_TestCapability(self, *args)
+
+    def StartTransaction(self, *args, **kwargs):
+        """StartTransaction(Network self, int force=False) -> OGRErr"""
+        return _gnm.Network_StartTransaction(self, *args, **kwargs)
+
+    def CommitTransaction(self, *args):
+        """CommitTransaction(Network self) -> OGRErr"""
+        return _gnm.Network_CommitTransaction(self, *args)
+
+    def RollbackTransaction(self, *args):
+        """RollbackTransaction(Network self) -> OGRErr"""
+        return _gnm.Network_RollbackTransaction(self, *args)
+
+Network_swigregister = _gnm.Network_swigregister
+Network_swigregister(Network)
+
+class GenericNetwork(Network):
+    """Proxy of C++ GNMGenericNetworkShadow class"""
+    __swig_setmethods__ = {}
+    for _s in [Network]: __swig_setmethods__.update(getattr(_s,'__swig_setmethods__',{}))
+    __setattr__ = lambda self, name, value: _swig_setattr(self, GenericNetwork, name, value)
+    __swig_getmethods__ = {}
+    for _s in [Network]: __swig_getmethods__.update(getattr(_s,'__swig_getmethods__',{}))
+    __getattr__ = lambda self, name: _swig_getattr(self, GenericNetwork, name)
+    def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+    __swig_destroy__ = _gnm.delete_GenericNetwork
+    __del__ = lambda self : None;
+    def ConnectFeatures(self, *args):
+        """
+        ConnectFeatures(GenericNetwork self, GIntBig nSrcFID, GIntBig nTgtFID, GIntBig nConFID, double dfCost, double dfInvCost,
+            GNMDirection eDir) -> CPLErr
+        """
+        return _gnm.GenericNetwork_ConnectFeatures(self, *args)
+
+    def DisconnectFeatures(self, *args):
+        """DisconnectFeatures(GenericNetwork self, GIntBig nSrcFID, GIntBig nTgtFID, GIntBig nConFID) -> CPLErr"""
+        return _gnm.GenericNetwork_DisconnectFeatures(self, *args)
+
+    def DisconnectFeaturesWithId(self, *args):
+        """DisconnectFeaturesWithId(GenericNetwork self, GIntBig nFID) -> CPLErr"""
+        return _gnm.GenericNetwork_DisconnectFeaturesWithId(self, *args)
+
+    def ReconnectFeatures(self, *args):
+        """
+        ReconnectFeatures(GenericNetwork self, GIntBig nSrcFID, GIntBig nTgtFID, GIntBig nConFID, double dfCost, double dfInvCost,
+            GNMDirection eDir) -> CPLErr
+        """
+        return _gnm.GenericNetwork_ReconnectFeatures(self, *args)
+
+    def CreateRule(self, *args):
+        """CreateRule(GenericNetwork self, char const * pszRuleStr) -> CPLErr"""
+        return _gnm.GenericNetwork_CreateRule(self, *args)
+
+    def DeleteAllRules(self, *args):
+        """DeleteAllRules(GenericNetwork self) -> CPLErr"""
+        return _gnm.GenericNetwork_DeleteAllRules(self, *args)
+
+    def DeleteRule(self, *args):
+        """DeleteRule(GenericNetwork self, char const * pszRuleStr) -> CPLErr"""
+        return _gnm.GenericNetwork_DeleteRule(self, *args)
+
+    def GetRules(self, *args):
+        """GetRules(GenericNetwork self) -> char **"""
+        return _gnm.GenericNetwork_GetRules(self, *args)
+
+    def ConnectPointsByLines(self, *args, **kwargs):
+        """ConnectPointsByLines(GenericNetwork self, char ** papszLayerList, double dfTolerance, double dfCost, double dfInvCost, GNMDirection eDir) -> CPLErr"""
+        return _gnm.GenericNetwork_ConnectPointsByLines(self, *args, **kwargs)
+
+    def ChangeBlockState(self, *args):
+        """ChangeBlockState(GenericNetwork self, GIntBig nFID, bool bIsBlock) -> CPLErr"""
+        return _gnm.GenericNetwork_ChangeBlockState(self, *args)
+
+    def ChangeAllBlockState(self, *args):
+        """ChangeAllBlockState(GenericNetwork self, bool bIsBlock=False) -> CPLErr"""
+        return _gnm.GenericNetwork_ChangeAllBlockState(self, *args)
+
+GenericNetwork_swigregister = _gnm.GenericNetwork_swigregister
+GenericNetwork_swigregister(GenericNetwork)
+
+# This file is compatible with both classic and new-style classes.
+
+
diff --git a/swig/python/osgeo/ogr.py b/swig/python/osgeo/ogr.py
index f2cfe59..0a2e8c5 100644
--- a/swig/python/osgeo/ogr.py
+++ b/swig/python/osgeo/ogr.py
@@ -1,9 +1,12 @@
 # This file was automatically generated by SWIG (http://www.swig.org).
-# Version 1.3.40
+# Version 2.0.12
 #
 # Do not make changes to this file unless you know what you are doing--modify
 # the SWIG interface file instead.
-# This file is compatible with both classic and new-style classes.
+
+
+
+
 
 from sys import version_info
 if version_info >= (2,6,0):
@@ -39,7 +42,7 @@ def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
             return
     method = class_type.__swig_setmethods__.get(name,None)
     if method: return method(self,value)
-    if (not static) or hasattr(self,name):
+    if (not static):
         self.__dict__[name] = value
     else:
         raise AttributeError("You cannot add attributes to %s" % self)
@@ -81,6 +84,10 @@ wkbCompoundCurve = _ogr.wkbCompoundCurve
 wkbCurvePolygon = _ogr.wkbCurvePolygon
 wkbMultiCurve = _ogr.wkbMultiCurve
 wkbMultiSurface = _ogr.wkbMultiSurface
+wkbCurve = _ogr.wkbCurve
+wkbSurface = _ogr.wkbSurface
+wkbPolyhedralSurface = _ogr.wkbPolyhedralSurface
+wkbTIN = _ogr.wkbTIN
 wkbNone = _ogr.wkbNone
 wkbLinearRing = _ogr.wkbLinearRing
 wkbCircularStringZ = _ogr.wkbCircularStringZ
@@ -88,6 +95,42 @@ wkbCompoundCurveZ = _ogr.wkbCompoundCurveZ
 wkbCurvePolygonZ = _ogr.wkbCurvePolygonZ
 wkbMultiCurveZ = _ogr.wkbMultiCurveZ
 wkbMultiSurfaceZ = _ogr.wkbMultiSurfaceZ
+wkbCurveZ = _ogr.wkbCurveZ
+wkbSurfaceZ = _ogr.wkbSurfaceZ
+wkbPolyhedralSurfaceZ = _ogr.wkbPolyhedralSurfaceZ
+wkbTINZ = _ogr.wkbTINZ
+wkbPointM = _ogr.wkbPointM
+wkbLineStringM = _ogr.wkbLineStringM
+wkbPolygonM = _ogr.wkbPolygonM
+wkbMultiPointM = _ogr.wkbMultiPointM
+wkbMultiLineStringM = _ogr.wkbMultiLineStringM
+wkbMultiPolygonM = _ogr.wkbMultiPolygonM
+wkbGeometryCollectionM = _ogr.wkbGeometryCollectionM
+wkbCircularStringM = _ogr.wkbCircularStringM
+wkbCompoundCurveM = _ogr.wkbCompoundCurveM
+wkbCurvePolygonM = _ogr.wkbCurvePolygonM
+wkbMultiCurveM = _ogr.wkbMultiCurveM
+wkbMultiSurfaceM = _ogr.wkbMultiSurfaceM
+wkbCurveM = _ogr.wkbCurveM
+wkbSurfaceM = _ogr.wkbSurfaceM
+wkbPolyhedralSurfaceM = _ogr.wkbPolyhedralSurfaceM
+wkbTINM = _ogr.wkbTINM
+wkbPointZM = _ogr.wkbPointZM
+wkbLineStringZM = _ogr.wkbLineStringZM
+wkbPolygonZM = _ogr.wkbPolygonZM
+wkbMultiPointZM = _ogr.wkbMultiPointZM
+wkbMultiLineStringZM = _ogr.wkbMultiLineStringZM
+wkbMultiPolygonZM = _ogr.wkbMultiPolygonZM
+wkbGeometryCollectionZM = _ogr.wkbGeometryCollectionZM
+wkbCircularStringZM = _ogr.wkbCircularStringZM
+wkbCompoundCurveZM = _ogr.wkbCompoundCurveZM
+wkbCurvePolygonZM = _ogr.wkbCurvePolygonZM
+wkbMultiCurveZM = _ogr.wkbMultiCurveZM
+wkbMultiSurfaceZM = _ogr.wkbMultiSurfaceZM
+wkbCurveZM = _ogr.wkbCurveZM
+wkbSurfaceZM = _ogr.wkbSurfaceZM
+wkbPolyhedralSurfaceZM = _ogr.wkbPolyhedralSurfaceZM
+wkbTINZM = _ogr.wkbTINZM
 wkbPoint25D = _ogr.wkbPoint25D
 wkbLineString25D = _ogr.wkbLineString25D
 wkbPolygon25D = _ogr.wkbPolygon25D
@@ -147,12 +190,14 @@ OLCStringsAsUTF8 = _ogr.OLCStringsAsUTF8
 OLCIgnoreFields = _ogr.OLCIgnoreFields
 OLCCreateGeomField = _ogr.OLCCreateGeomField
 OLCCurveGeometries = _ogr.OLCCurveGeometries
+OLCMeasuredGeometries = _ogr.OLCMeasuredGeometries
 ODsCCreateLayer = _ogr.ODsCCreateLayer
 ODsCDeleteLayer = _ogr.ODsCDeleteLayer
 ODsCCreateGeomFieldAfterCreateLayer = _ogr.ODsCCreateGeomFieldAfterCreateLayer
 ODsCCurveGeometries = _ogr.ODsCCurveGeometries
 ODsCTransactions = _ogr.ODsCTransactions
 ODsCEmulatedTransactions = _ogr.ODsCEmulatedTransactions
+ODsCMeasuredGeometries = _ogr.ODsCMeasuredGeometries
 ODrCCreateDataSource = _ogr.ODrCCreateDataSource
 ODrCDeleteDataSource = _ogr.ODrCDeleteDataSource
 OLMD_FID64 = _ogr.OLMD_FID64
@@ -178,81 +223,6 @@ def UseExceptions(*args):
 def DontUseExceptions(*args):
   """DontUseExceptions()"""
   return _ogr.DontUseExceptions(*args)
-# Backup original dictionnary before doing anything else
-_initial_dict = globals().copy()
-
- at property
-def wkb25Bit(module):
-    import warnings
-    warnings.warn("ogr.wkb25DBit deprecated: use ogr.GT_Flatten(), ogr.GT_HasZ() or ogr.GT_SetZ() instead", DeprecationWarning)
-    return module._initial_dict['wkb25DBit']
-
- at property
-def wkb25DBit(module):
-    import warnings
-    warnings.warn("ogr.wkb25DBit deprecated: use ogr.GT_Flatten(), ogr.GT_HasZ() or ogr.GT_SetZ() instead", DeprecationWarning)
-    return module._initial_dict['wkb25DBit']
-
-# Inspired from http://www.dr-josiah.com/2013/12/properties-on-python-modules.html
-class _Module(object):
-    def __init__(self):
-        self.__dict__ = globals()
-        self._initial_dict = _initial_dict
-
-        # Transfer properties from the object to the Class
-        for k, v in list(self.__dict__.items()):
-            if isinstance(v, property):
-                setattr(self.__class__, k, v)
-                #del self.__dict__[k]
-
-        # Replace original module by our object
-        import sys
-        self._original_module = sys.modules[self.__name__]
-        sys.modules[self.__name__] = self
-
-# Custom help() replacement to display the help of the original module
-# instead of the one of our instance object
-class _MyHelper(object):
-
-    def __init__(self, module):
-        self.module = module
-        self.original_help = help
-
-        # Replace builtin help by ours
-        try:
-            import __builtin__ as builtins # Python 2
-        except ImportError:
-            import builtins # Python 3
-        builtins.help = self
-
-    def __repr__(self):
-        return self.original_help.__repr__()
-
-    def __call__(self, *args, **kwds):
-
-        if args == (self.module,):
-            import sys
-
-            # Restore original module before calling help() otherwise
-            # we don't get methods or classes mentionned
-            sys.modules[self.module.__name__] = self.module._original_module
-
-            ret = self.original_help(self.module._original_module, **kwds)
-
-            # Reinstall our module
-            sys.modules[self.module.__name__] = self.module
-
-            return ret
-        elif args == (self,):
-            return self.original_help(self.original_help, **kwds)
-        else:
-            return self.original_help(*args, **kwds)
-
-_MyHelper(_Module())
-del _MyHelper
-del _Module
-
-
 import osr
 class MajorObject(_object):
     """Proxy of C++ GDALMajorObjectShadow class"""
@@ -263,38 +233,38 @@ class MajorObject(_object):
     def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined")
     __repr__ = _swig_repr
     def GetDescription(self, *args):
-        """GetDescription(self) -> char"""
+        """GetDescription(MajorObject self) -> char const *"""
         return _ogr.MajorObject_GetDescription(self, *args)
 
     def SetDescription(self, *args):
-        """SetDescription(self, char pszNewDesc)"""
+        """SetDescription(MajorObject self, char const * pszNewDesc)"""
         return _ogr.MajorObject_SetDescription(self, *args)
 
     def GetMetadataDomainList(self, *args):
-        """GetMetadataDomainList(self) -> char"""
+        """GetMetadataDomainList(MajorObject self) -> char **"""
         return _ogr.MajorObject_GetMetadataDomainList(self, *args)
 
     def GetMetadata_Dict(self, *args):
-        """GetMetadata_Dict(self, char pszDomain = "") -> char"""
+        """GetMetadata_Dict(MajorObject self, char const * pszDomain="") -> char **"""
         return _ogr.MajorObject_GetMetadata_Dict(self, *args)
 
     def GetMetadata_List(self, *args):
-        """GetMetadata_List(self, char pszDomain = "") -> char"""
+        """GetMetadata_List(MajorObject self, char const * pszDomain="") -> char **"""
         return _ogr.MajorObject_GetMetadata_List(self, *args)
 
     def SetMetadata(self, *args):
         """
-        SetMetadata(self, char papszMetadata, char pszDomain = "") -> CPLErr
-        SetMetadata(self, char pszMetadataString, char pszDomain = "") -> CPLErr
+        SetMetadata(MajorObject self, char ** papszMetadata, char const * pszDomain="") -> CPLErr
+        SetMetadata(MajorObject self, char * pszMetadataString, char const * pszDomain="") -> CPLErr
         """
         return _ogr.MajorObject_SetMetadata(self, *args)
 
     def GetMetadataItem(self, *args):
-        """GetMetadataItem(self, char pszName, char pszDomain = "") -> char"""
+        """GetMetadataItem(MajorObject self, char const * pszName, char const * pszDomain="") -> char const *"""
         return _ogr.MajorObject_GetMetadataItem(self, *args)
 
     def SetMetadataItem(self, *args):
-        """SetMetadataItem(self, char pszName, char pszValue, char pszDomain = "") -> CPLErr"""
+        """SetMetadataItem(MajorObject self, char const * pszName, char const * pszValue, char const * pszDomain="") -> CPLErr"""
         return _ogr.MajorObject_SetMetadataItem(self, *args)
 
     def GetMetadata( self, domain = '' ):
@@ -312,39 +282,39 @@ class StyleTable(_object):
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, StyleTable, name)
     __repr__ = _swig_repr
-    def __init__(self, *args): 
-        """__init__(self) -> StyleTable"""
+    def __init__(self, *args):
+        """__init__(OGRStyleTableShadow self) -> StyleTable"""
         this = _ogr.new_StyleTable(*args)
         try: self.this.append(this)
         except: self.this = this
     __swig_destroy__ = _ogr.delete_StyleTable
     __del__ = lambda self : None;
     def AddStyle(self, *args):
-        """AddStyle(self, char pszName, char pszStyleString) -> int"""
+        """AddStyle(StyleTable self, char const * pszName, char const * pszStyleString) -> int"""
         return _ogr.StyleTable_AddStyle(self, *args)
 
     def LoadStyleTable(self, *args):
-        """LoadStyleTable(self, char utf8_path) -> int"""
+        """LoadStyleTable(StyleTable self, char const * utf8_path) -> int"""
         return _ogr.StyleTable_LoadStyleTable(self, *args)
 
     def SaveStyleTable(self, *args):
-        """SaveStyleTable(self, char utf8_path) -> int"""
+        """SaveStyleTable(StyleTable self, char const * utf8_path) -> int"""
         return _ogr.StyleTable_SaveStyleTable(self, *args)
 
     def Find(self, *args):
-        """Find(self, char pszName) -> char"""
+        """Find(StyleTable self, char const * pszName) -> char const *"""
         return _ogr.StyleTable_Find(self, *args)
 
     def ResetStyleStringReading(self, *args):
-        """ResetStyleStringReading(self)"""
+        """ResetStyleStringReading(StyleTable self)"""
         return _ogr.StyleTable_ResetStyleStringReading(self, *args)
 
     def GetNextStyle(self, *args):
-        """GetNextStyle(self) -> char"""
+        """GetNextStyle(StyleTable self) -> char const *"""
         return _ogr.StyleTable_GetNextStyle(self, *args)
 
     def GetLastStyleName(self, *args):
-        """GetLastStyleName(self) -> char"""
+        """GetLastStyleName(StyleTable self) -> char const *"""
         return _ogr.StyleTable_GetLastStyleName(self, *args)
 
 StyleTable_swigregister = _ogr.StyleTable_swigregister
@@ -364,7 +334,7 @@ class Driver(MajorObject):
     if _newclass:name = _swig_property(_ogr.Driver_name_get)
     def CreateDataSource(self, *args, **kwargs):
         """
-        CreateDataSource(self, char utf8_path, char options = None) -> DataSource
+        CreateDataSource(Driver self, char const * utf8_path, char ** options=None) -> DataSource
 
         OGRDataSourceH
         OGR_Dr_CreateDataSource(OGRSFDriverH hDriver, const char *pszName,
@@ -380,8 +350,7 @@ class Driver(MajorObject):
         It is important to call OGR_DS_Destroy() when the datasource is no
         longer used to ensure that all data has been properly flushed to disk.
 
-        This function is the same as the C++ method
-        OGRSFDriver::CreateDataSource().
+        Deprecated Use GDALCreate() in GDAL 2.0
 
         Parameters:
         -----------
@@ -392,7 +361,7 @@ class Driver(MajorObject):
 
         papszOptions:  a StringList of name=value options. Options are driver
         specific, and driver information can be found at the following
-        url:http://www.gdal.org/ogr/ogr_formats.html
+        url:http://www.gdal.org/ogr_formats.html
 
         NULL is returned on failure, or a new OGRDataSource handle on success.
 
@@ -401,7 +370,7 @@ class Driver(MajorObject):
 
     def CopyDataSource(self, *args, **kwargs):
         """
-        CopyDataSource(self, DataSource copy_ds, char utf8_path, char options = None) -> DataSource
+        CopyDataSource(Driver self, DataSource copy_ds, char const * utf8_path, char ** options=None) -> DataSource
 
         OGRDataSourceH
         OGR_Dr_CopyDataSource(OGRSFDriverH hDriver, OGRDataSourceH hSrcDS,
@@ -413,8 +382,7 @@ class Driver(MajorObject):
         It is important to call OGR_DS_Destroy() when the datasource is no
         longer used to ensure that all data has been properly flushed to disk.
 
-        This function is the same as the C++ method
-        OGRSFDriver::CopyDataSource().
+        Deprecated Use GDALCreateCopy() in GDAL 2.0
 
         Parameters:
         -----------
@@ -427,7 +395,7 @@ class Driver(MajorObject):
 
         papszOptions:  a StringList of name=value options. Options are driver
         specific, and driver information can be found at the following
-        url:http://www.gdal.org/ogr/ogr_formats.html
+        url:http://www.gdal.org/ogr_formats.html
 
         NULL is returned on failure, or a new OGRDataSource handle on success.
 
@@ -436,14 +404,19 @@ class Driver(MajorObject):
 
     def Open(self, *args, **kwargs):
         """
-        Open(self, char utf8_path, int update = 0) -> DataSource
+        Open(Driver self, char const * utf8_path, int update=0) -> DataSource
 
         OGRDataSourceH OGR_Dr_Open(OGRSFDriverH
         hDriver, const char *pszName, int bUpdate)
 
         Attempt to open file with this driver.
 
-        This function is the same as the C++ method OGRSFDriver::Open().
+        NOTE: Starting with GDAL 2.0, it is *NOT* safe to cast the returned
+        handle to OGRDataSource*. If a C++ object is needed, the handle should
+        be cast to GDALDataset*. Similarly, the returned OGRSFDriverH handle
+        should be cast to GDALDriver*, and NOT* OGRSFDriver*.
+
+        Deprecated Use GDALOpenEx() in GDAL 2.0
 
         Parameters:
         -----------
@@ -456,14 +429,14 @@ class Driver(MajorObject):
         default).
 
         NULL on error or if the pass name is not supported by this driver,
-        otherwise an handle to an OGRDataSource. This OGRDataSource should be
-        closed by deleting the object when it is no longer needed. 
+        otherwise an handle to a GDALDataset. This GDALDataset should be
+        closed by deleting the object when it is no longer needed.
         """
         return _ogr.Driver_Open(self, *args, **kwargs)
 
     def DeleteDataSource(self, *args):
         """
-        DeleteDataSource(self, char utf8_path) -> int
+        DeleteDataSource(Driver self, char const * utf8_path) -> int
 
         OGRErr
         OGR_Dr_DeleteDataSource(OGRSFDriverH hDriver, const char
@@ -478,8 +451,7 @@ class Driver(MajorObject):
         Whether this is a supported operation on this driver case be tested
         using TestCapability() on ODrCDeleteDataSource.
 
-        This method is the same as the C++ method
-        OGRSFDriver::DeleteDataSource().
+        Deprecated Use GDALDeleteDataset() in GDAL 2
 
         Parameters:
         -----------
@@ -489,13 +461,13 @@ class Driver(MajorObject):
         pszDataSource:  the name of the datasource to delete.
 
         OGRERR_NONE on success, and OGRERR_UNSUPPORTED_OPERATION if this is
-        not supported by this driver. 
+        not supported by this driver.
         """
         return _ogr.Driver_DeleteDataSource(self, *args)
 
     def TestCapability(self, *args):
         """
-        TestCapability(self, char cap) -> bool
+        TestCapability(Driver self, char const * cap) -> bool
 
         int
         OGR_Dr_TestCapability(OGRSFDriverH hDriver, const char *pszCap)
@@ -513,10 +485,10 @@ class Driver(MajorObject):
         sources.
 
         The #define macro forms of the capability names should be used in
-        preference to the strings themselves to avoid mispelling.
+        preference to the strings themselves to avoid misspelling.
 
-        This function is the same as the C++ method
-        OGRSFDriver::TestCapability().
+        Deprecated Use GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATE) in GDAL
+        2.0
 
         Parameters:
         -----------
@@ -525,39 +497,40 @@ class Driver(MajorObject):
 
         pszCap:  the capability to test.
 
-        TRUE if capability available otherwise FALSE. 
+        TRUE if capability available otherwise FALSE.
         """
         return _ogr.Driver_TestCapability(self, *args)
 
     def GetName(self, *args):
         """
-        GetName(self) -> char
+        GetName(Driver self) -> char const *
 
         const char*
         OGR_Dr_GetName(OGRSFDriverH hDriver)
 
-        Fetch name of driver (file format). This name should be relatively
-        short (10-40 characters), and should reflect the underlying file
-        format. For instance "ESRI Shapefile".
+        Fetch name of driver (file format).
+
+        This name should be relatively short (10-40 characters), and should
+        reflect the underlying file format. For instance "ESRI Shapefile".
 
         This function is the same as the C++ method OGRSFDriver::GetName().
 
         Parameters:
         -----------
 
-        hDriver:  handle to the the driver to get the name from.
+        hDriver:  handle to the driver to get the name from.
 
         driver name. This is an internal string and should not be modified or
-        freed. 
+        freed.
         """
         return _ogr.Driver_GetName(self, *args)
 
     def Register(self, *args):
-        """Register(self)"""
+        """Register(Driver self)"""
         return _ogr.Driver_Register(self, *args)
 
     def Deregister(self, *args):
-        """Deregister(self)"""
+        """Deregister(Driver self)"""
         return _ogr.Driver_Deregister(self, *args)
 
 Driver_swigregister = _ogr.Driver_swigregister
@@ -579,33 +552,32 @@ class DataSource(MajorObject):
     __del__ = lambda self : None;
     def GetRefCount(self, *args):
         """
-        GetRefCount(self) -> int
+        GetRefCount(DataSource self) -> int
 
         int
-        OGR_DS_GetRefCount(OGRDataSourceH hDataSource) 
+        OGR_DS_GetRefCount(OGRDataSourceH hDataSource)
         """
         return _ogr.DataSource_GetRefCount(self, *args)
 
     def GetSummaryRefCount(self, *args):
         """
-        GetSummaryRefCount(self) -> int
+        GetSummaryRefCount(DataSource self) -> int
 
         int
-        OGR_DS_GetSummaryRefCount(OGRDataSourceH hDataSource) 
+        OGR_DS_GetSummaryRefCount(OGRDataSourceH hDataSource)
         """
         return _ogr.DataSource_GetSummaryRefCount(self, *args)
 
     def GetLayerCount(self, *args):
         """
-        GetLayerCount(self) -> int
+        GetLayerCount(DataSource self) -> int
 
         int
         OGR_DS_GetLayerCount(OGRDataSourceH hDS)
 
         Get the number of layers in this data source.
 
-        This function is the same as the C++ method
-        OGRDataSource::GetLayerCount().
+        Deprecated Use GDALDatasetGetLayerCount() in GDAL 2.0
 
         Parameters:
         -----------
@@ -613,20 +585,24 @@ class DataSource(MajorObject):
         hDS:  handle to the data source from which to get the number of
         layers.
 
-        layer count. 
+        layer count.
         """
         return _ogr.DataSource_GetLayerCount(self, *args)
 
     def GetDriver(self, *args):
         """
-        GetDriver(self) -> Driver
+        GetDriver(DataSource self) -> Driver
 
         OGRSFDriverH
         OGR_DS_GetDriver(OGRDataSourceH hDS)
 
         Returns the driver that the dataset was opened with.
 
-        This method is the same as the C++ method OGRDataSource::GetDriver()
+        NOTE: Starting with GDAL 2.0, it is *NOT* safe to cast the returned
+        handle to OGRSFDriver*. If a C++ object is needed, the handle should
+        be cast to GDALDriver*.
+
+        Deprecated Use GDALGetDatasetDriver() in GDAL 2.0
 
         Parameters:
         -----------
@@ -634,13 +610,13 @@ class DataSource(MajorObject):
         hDS:  handle to the datasource
 
         NULL if driver info is not available, or pointer to a driver owned by
-        the OGRSFDriverManager. 
+        the OGRSFDriverManager.
         """
         return _ogr.DataSource_GetDriver(self, *args)
 
     def GetName(self, *args):
         """
-        GetName(self) -> char
+        GetName(DataSource self) -> char const *
 
         const char*
         OGR_DS_GetName(OGRDataSourceH hDS)
@@ -652,7 +628,7 @@ class DataSource(MajorObject):
         need not be exactly the same string that was used to open the data
         source. Normally this is a filename.
 
-        This function is the same as the C++ method OGRDataSource::GetName().
+        Deprecated Use GDALGetDescription() in GDAL 2.0
 
         Parameters:
         -----------
@@ -660,13 +636,13 @@ class DataSource(MajorObject):
         hDS:  handle to the data source to get the name from.
 
         pointer to an internal name string which should not be modified or
-        freed by the caller. 
+        freed by the caller.
         """
         return _ogr.DataSource_GetName(self, *args)
 
     def DeleteLayer(self, *args):
         """
-        DeleteLayer(self, int index) -> OGRErr
+        DeleteLayer(DataSource self, int index) -> OGRErr
 
         OGRErr
         OGR_DS_DeleteLayer(OGRDataSourceH hDS, int iLayer)
@@ -676,8 +652,7 @@ class DataSource(MajorObject):
         If this method is supported the ODsCDeleteLayer capability will test
         TRUE on the OGRDataSource.
 
-        This method is the same as the C++ method
-        OGRDataSource::DeleteLayer().
+        Deprecated Use GDALDatasetDeleteLayer() in GDAL 2.0
 
         Parameters:
         -----------
@@ -687,55 +662,27 @@ class DataSource(MajorObject):
         iLayer:  the index of the layer to delete.
 
         OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
-        layers is not supported for this datasource. 
+        layers is not supported for this datasource.
         """
         return _ogr.DataSource_DeleteLayer(self, *args)
 
     def SyncToDisk(self, *args):
         """
-        SyncToDisk(self) -> OGRErr
+        SyncToDisk(DataSource self) -> OGRErr
 
         OGRErr
         OGR_DS_SyncToDisk(OGRDataSourceH hDS)
-
-        Flush pending changes to disk.
-
-        This call is intended to force the datasource to flush any pending
-        writes to disk, and leave the disk file in a consistent state. It
-        would not normally have any effect on read-only datasources.
-
-        Some data sources do not implement this method, and will still return
-        OGRERR_NONE. An error is only returned if an error occurs while
-        attempting to flush to disk.
-
-        The default implementation of this method just calls the SyncToDisk()
-        method on each of the layers. Conceptionally, calling SyncToDisk() on
-        a datasource should include any work that might be accomplished by
-        calling SyncToDisk() on layers in that data source.
-
-        In any event, you should always close any opened datasource with
-        OGR_DS_Destroy() that will ensure all data is correctly flushed.
-
-        This method is the same as the C++ method OGRDataSource::SyncToDisk()
-
-        Parameters:
-        -----------
-
-        hDS:  handle to the data source
-
-        OGRERR_NONE if no error occurs (even if nothing is done) or an error
-        code. 
         """
         return _ogr.DataSource_SyncToDisk(self, *args)
 
     def FlushCache(self, *args):
-        """FlushCache(self)"""
+        """FlushCache(DataSource self)"""
         return _ogr.DataSource_FlushCache(self, *args)
 
     def CreateLayer(self, *args, **kwargs):
         """
-        CreateLayer(self, char name, SpatialReference srs = None, OGRwkbGeometryType geom_type = wkbUnknown, 
-            char options = None) -> Layer
+        CreateLayer(DataSource self, char const * name, SpatialReference srs=None, OGRwkbGeometryType geom_type=wkbUnknown,
+            char ** options=None) -> Layer
 
         OGRLayerH
         OGR_DS_CreateLayer(OGRDataSourceH hDS, const char *pszName,
@@ -749,8 +696,7 @@ class DataSource(MajorObject):
         creation options. These options are normally documented in the format
         specific documentation.
 
-        This function is the same as the C++ method
-        OGRDataSource::CreateLayer().
+        Deprecated Use GDALDatasetCreateLayer() in GDAL 2.0
 
         Parameters:
         -----------
@@ -768,16 +714,16 @@ class DataSource(MajorObject):
 
         papszOptions:  a StringList of name=value options. Options are driver
         specific, and driver information can be found at the following
-        url:http://www.gdal.org/ogr/ogr_formats.html
+        url:http://www.gdal.org/ogr_formats.html
 
         NULL is returned on failure, or a new OGRLayer handle on success.
-        Example: 
+        Example:
         """
         return _ogr.DataSource_CreateLayer(self, *args, **kwargs)
 
     def CopyLayer(self, *args, **kwargs):
         """
-        CopyLayer(self, Layer src_layer, char new_name, char options = None) -> Layer
+        CopyLayer(DataSource self, Layer src_layer, char const * new_name, char ** options=None) -> Layer
 
         OGRLayerH
         OGR_DS_CopyLayer(OGRDataSourceH hDS, OGRLayerH hSrcLayer, const char
@@ -792,7 +738,7 @@ class DataSource(MajorObject):
         specific documentation. The source layer may come from another
         dataset.
 
-        This function is the same as the C++ method OGRDataSource::CopyLayer
+        Deprecated Use GDALDatasetCopyLayer() in GDAL 2.0
 
         Parameters:
         -----------
@@ -806,17 +752,17 @@ class DataSource(MajorObject):
         papszOptions:  a StringList of name=value options. Options are driver
         specific.
 
-        an handle to the layer, or NULL if an error occurs. 
+        an handle to the layer, or NULL if an error occurs.
         """
         return _ogr.DataSource_CopyLayer(self, *args, **kwargs)
 
     def GetLayerByIndex(self, *args):
-        """GetLayerByIndex(self, int index = 0) -> Layer"""
+        """GetLayerByIndex(DataSource self, int index=0) -> Layer"""
         return _ogr.DataSource_GetLayerByIndex(self, *args)
 
     def GetLayerByName(self, *args):
         """
-        GetLayerByName(self, char layer_name) -> Layer
+        GetLayerByName(DataSource self, char const * layer_name) -> Layer
 
         OGRLayerH
         OGR_DS_GetLayerByName(OGRDataSourceH hDS, const char *pszName)
@@ -826,8 +772,7 @@ class DataSource(MajorObject):
         The returned layer remains owned by the OGRDataSource and should not
         be deleted by the application.
 
-        This function is the same as the C++ method
-        OGRDataSource::GetLayerByName().
+        Deprecated Use GDALDatasetGetLayerByName() in GDAL 2.0
 
         Parameters:
         -----------
@@ -837,13 +782,13 @@ class DataSource(MajorObject):
         pszLayerName:  Layer the layer name of the layer to fetch.
 
         an handle to the layer, or NULL if the layer is not found or an error
-        occurs. 
+        occurs.
         """
         return _ogr.DataSource_GetLayerByName(self, *args)
 
     def TestCapability(self, *args):
         """
-        TestCapability(self, char cap) -> bool
+        TestCapability(DataSource self, char const * cap) -> bool
 
         int
         OGR_DS_TestCapability(OGRDataSourceH hDS, const char *pszCap)
@@ -856,11 +801,19 @@ class DataSource(MajorObject):
 
         ODsCCreateLayer: True if this datasource can create new layers.
 
+        ODsCDeleteLayer: True if this datasource can delete existing layers.
+
+        ODsCCreateGeomFieldAfterCreateLayer: True if the layers of this
+        datasource support CreateGeomField() just after layer creation.
+
+        ODsCCurveGeometries: True if this datasource supports writing curve
+        geometries. (GDAL 2.0). In that case, OLCCurveGeometries must also be
+        declared in layers of that dataset.
+
         The #define macro forms of the capability names should be used in
-        preference to the strings themselves to avoid mispelling.
+        preference to the strings themselves to avoid misspelling.
 
-        This function is the same as the C++ method
-        OGRDataSource::TestCapability().
+        Deprecated Use GDALDatasetTestCapability() in GDAL 2.0
 
         Parameters:
         -----------
@@ -869,13 +822,13 @@ class DataSource(MajorObject):
 
         pszCapability:  the capability to test.
 
-        TRUE if capability available otherwise FALSE. 
+        TRUE if capability available otherwise FALSE.
         """
         return _ogr.DataSource_TestCapability(self, *args)
 
     def ExecuteSQL(self, *args, **kwargs):
         """
-        ExecuteSQL(self, char statement, Geometry spatialFilter = None, char dialect = "") -> Layer
+        ExecuteSQL(DataSource self, char const * statement, Geometry spatialFilter=None, char const * dialect="") -> Layer
 
         OGRLayerH
         OGR_DS_ExecuteSQL(OGRDataSourceH hDS, const char *pszStatement,
@@ -891,11 +844,12 @@ class DataSource(MajorObject):
         (destroyed).
 
         For more information on the SQL dialect supported internally by OGR
-        review theOGR SQL document. Some drivers (ie. Oracle and PostGIS) pass
-        the SQL directly through to the underlying RDBMS.
+        review theOGR SQL document. Some drivers (i.e. Oracle and PostGIS)
+        pass the SQL directly through to the underlying RDBMS.
 
-        This function is the same as the C++ method
-        OGRDataSource::ExecuteSQL();
+        Starting with OGR 1.10, theSQLITE dialect can also be used.
+
+        Deprecated Use GDALDatasetExecuteSQL() in GDAL 2.0
 
         Parameters:
         -----------
@@ -910,16 +864,17 @@ class DataSource(MajorObject):
         pszDialect:  allows control of the statement dialect. If set to NULL,
         the OGR SQL engine will be used, except for RDBMS drivers that will
         use their dedicated SQL engine, unless OGRSQL is explicitly passed as
-        the dialect.
+        the dialect. Starting with OGR 1.10, the SQLITE dialect can also be
+        used.
 
         an handle to a OGRLayer containing the results of the query.
-        Deallocate with OGR_DS_ReleaseResultSet(). 
+        Deallocate with OGR_DS_ReleaseResultSet().
         """
         return _ogr.DataSource_ExecuteSQL(self, *args, **kwargs)
 
     def ReleaseResultSet(self, *args):
         """
-        ReleaseResultSet(self, Layer layer)
+        ReleaseResultSet(DataSource self, Layer layer)
 
         void
         OGR_DS_ReleaseResultSet(OGRDataSourceH hDS, OGRLayerH hLayer)
@@ -931,8 +886,7 @@ class DataSource(MajorObject):
         deallocate a results set before destroying the OGRDataSource may cause
         errors.
 
-        This function is the same as the C++ method
-        OGRDataSource::ReleaseResultSet().
+        Deprecated Use GDALDatasetReleaseResultSet() in GDAL 2.0
 
         Parameters:
         -----------
@@ -946,16 +900,16 @@ class DataSource(MajorObject):
 
     def GetStyleTable(self, *args):
         """
-        GetStyleTable(self) -> StyleTable
+        GetStyleTable(DataSource self) -> StyleTable
 
         OGRStyleTableH
-        OGR_DS_GetStyleTable(OGRDataSourceH hDS) 
+        OGR_DS_GetStyleTable(OGRDataSourceH hDS)
         """
         return _ogr.DataSource_GetStyleTable(self, *args)
 
     def SetStyleTable(self, *args):
         """
-        SetStyleTable(self, StyleTable table)
+        SetStyleTable(DataSource self, StyleTable table)
 
         void
         OGR_DS_SetStyleTable(OGRDataSourceH hDS, OGRStyleTableH hStyleTable)
@@ -964,24 +918,24 @@ class DataSource(MajorObject):
         return _ogr.DataSource_SetStyleTable(self, *args)
 
     def StartTransaction(self, *args, **kwargs):
-        """StartTransaction(self, int force = True) -> OGRErr"""
+        """StartTransaction(DataSource self, int force=False) -> OGRErr"""
         return _ogr.DataSource_StartTransaction(self, *args, **kwargs)
 
     def CommitTransaction(self, *args):
-        """CommitTransaction(self) -> OGRErr"""
+        """CommitTransaction(DataSource self) -> OGRErr"""
         return _ogr.DataSource_CommitTransaction(self, *args)
 
     def RollbackTransaction(self, *args):
-        """RollbackTransaction(self) -> OGRErr"""
+        """RollbackTransaction(DataSource self) -> OGRErr"""
         return _ogr.DataSource_RollbackTransaction(self, *args)
 
     def Destroy(self):
-      "Once called, self has effectively been destroyed.  Do not access. For backwards compatiblity only"
+      "Once called, self has effectively been destroyed.  Do not access. For backwards compatibility only"
       _ogr.delete_DataSource( self )
       self.thisown = 0
 
     def Release(self):
-      "Once called, self has effectively been destroyed.  Do not access. For backwards compatiblity only"
+      "Once called, self has effectively been destroyed.  Do not access. For backwards compatibility only"
       _ogr.delete_DataSource( self )
       self.thisown = 0
 
@@ -1056,17 +1010,17 @@ class Layer(MajorObject):
     __repr__ = _swig_repr
     def GetRefCount(self, *args):
         """
-        GetRefCount(self) -> int
+        GetRefCount(Layer self) -> int
 
         int OGR_L_GetRefCount(OGRLayerH
-        hLayer) 
+        hLayer)
         """
         return _ogr.Layer_GetRefCount(self, *args)
 
     def SetSpatialFilter(self, *args):
         """
-        SetSpatialFilter(self, Geometry filter)
-        SetSpatialFilter(self, int iGeomField, Geometry filter)
+        SetSpatialFilter(Layer self, Geometry filter)
+        SetSpatialFilter(Layer self, int iGeomField, Geometry filter)
 
         void
         OGR_L_SetSpatialFilter(OGRLayerH hLayer, OGRGeometryH hGeom)
@@ -1102,15 +1056,14 @@ class Layer(MajorObject):
 
         hGeom:  handle to the geometry to use as a filtering region. NULL may
         be passed indicating that the current spatial filter should be
-        cleared, but no new one instituted. 
+        cleared, but no new one instituted.
         """
         return _ogr.Layer_SetSpatialFilter(self, *args)
 
     def SetSpatialFilterRect(self, *args):
         """
-        SetSpatialFilterRect(self, double minx, double miny, double maxx, double maxy)
-        SetSpatialFilterRect(self, int iGeomField, double minx, double miny, double maxx, 
-            double maxy)
+        SetSpatialFilterRect(Layer self, double minx, double miny, double maxx, double maxy)
+        SetSpatialFilterRect(Layer self, int iGeomField, double minx, double miny, double maxx, double maxy)
 
         void
         OGR_L_SetSpatialFilterRect(OGRLayerH hLayer, double dfMinX, double
@@ -1145,13 +1098,13 @@ class Layer(MajorObject):
 
         dfMaxX:  the maximum X coordinate for the rectangular region.
 
-        dfMaxY:  the maximum Y coordinate for the rectangular region. 
+        dfMaxY:  the maximum Y coordinate for the rectangular region.
         """
         return _ogr.Layer_SetSpatialFilterRect(self, *args)
 
     def GetSpatialFilter(self, *args):
         """
-        GetSpatialFilter(self) -> Geometry
+        GetSpatialFilter(Layer self) -> Geometry
 
         OGRGeometryH
         OGR_L_GetSpatialFilter(OGRLayerH hLayer)
@@ -1169,13 +1122,13 @@ class Layer(MajorObject):
 
         hLayer:  handle to the layer to get the spatial filter from.
 
-        an handle to the spatial filter geometry. 
+        an handle to the spatial filter geometry.
         """
         return _ogr.Layer_GetSpatialFilter(self, *args)
 
     def SetAttributeFilter(self, *args):
         """
-        SetAttributeFilter(self, char filter_string) -> OGRErr
+        SetAttributeFilter(Layer self, char * filter_string) -> OGRErr
 
         OGRErr
         OGR_L_SetAttributeFilter(OGRLayerH hLayer, const char *pszQuery)
@@ -1210,13 +1163,13 @@ class Layer(MajorObject):
         current query.
 
         OGRERR_NONE if successfully installed, or an error code if the query
-        expression is in error, or some other failure occurs. 
+        expression is in error, or some other failure occurs.
         """
         return _ogr.Layer_SetAttributeFilter(self, *args)
 
     def ResetReading(self, *args):
         """
-        ResetReading(self)
+        ResetReading(Layer self)
 
         void
         OGR_L_ResetReading(OGRLayerH hLayer)
@@ -1230,13 +1183,13 @@ class Layer(MajorObject):
         Parameters:
         -----------
 
-        hLayer:  handle to the layer on which features are read. 
+        hLayer:  handle to the layer on which features are read.
         """
         return _ogr.Layer_ResetReading(self, *args)
 
     def GetName(self, *args):
         """
-        GetName(self) -> char
+        GetName(Layer self) -> char const *
 
         const char* OGR_L_GetName(OGRLayerH
         hLayer)
@@ -1257,13 +1210,13 @@ class Layer(MajorObject):
 
         the layer name (must not been freed)
 
-        OGR 1.8.0 
+        OGR 1.8.0
         """
         return _ogr.Layer_GetName(self, *args)
 
     def GetGeomType(self, *args):
         """
-        GetGeomType(self) -> OGRwkbGeometryType
+        GetGeomType(Layer self) -> OGRwkbGeometryType
 
         OGRwkbGeometryType
         OGR_L_GetGeomType(OGRLayerH hLayer)
@@ -1275,6 +1228,12 @@ class Layer(MajorObject):
         calling OGR_L_GetGeomType() directly can avoid lengthy layer
         definition initialization.
 
+        For layers with multiple geometry fields, this method only returns the
+        geometry type of the first geometry column. For other columns, use
+        OGR_GFld_GetType(OGR_FD_GetGeomFieldDefn(OGR_L_GetLayerDefn(hLayer),
+        i)). For layers without any geometry field, this method returns
+        wkbNone.
+
         This function is the same as the C++ method OGRLayer::GetGeomType().
 
         Parameters:
@@ -1284,13 +1243,13 @@ class Layer(MajorObject):
 
         the geometry type
 
-        OGR 1.8.0 
+        OGR 1.8.0
         """
         return _ogr.Layer_GetGeomType(self, *args)
 
     def GetGeometryColumn(self, *args):
         """
-        GetGeometryColumn(self) -> char
+        GetGeometryColumn(Layer self) -> char const *
 
         const char*
         OGR_L_GetGeometryColumn(OGRLayerH hLayer)
@@ -1298,6 +1257,11 @@ class Layer(MajorObject):
         This method returns the name of the underlying database column being
         used as the geometry column, or "" if not supported.
 
+        For layers with multiple geometry fields, this method only returns the
+        geometry type of the first geometry column. For other columns, use OGR
+        _GFld_GetNameRef(OGR_FD_GetGeomFieldDefn(OGR_L_GetLayerDefn(hLayer),
+        i)).
+
         This method is the same as the C++ method
         OGRLayer::GetGeometryColumn()
 
@@ -1306,13 +1270,13 @@ class Layer(MajorObject):
 
         hLayer:  handle to the layer
 
-        geometry column name. 
+        geometry column name.
         """
         return _ogr.Layer_GetGeometryColumn(self, *args)
 
     def GetFIDColumn(self, *args):
         """
-        GetFIDColumn(self) -> char
+        GetFIDColumn(Layer self) -> char const *
 
         const char*
         OGR_L_GetFIDColumn(OGRLayerH hLayer)
@@ -1327,22 +1291,24 @@ class Layer(MajorObject):
 
         hLayer:  handle to the layer
 
-        fid column name. 
+        fid column name.
         """
         return _ogr.Layer_GetFIDColumn(self, *args)
 
     def GetFeature(self, *args):
         """
-        GetFeature(self, GIntBig fid) -> Feature
+        GetFeature(Layer self, GIntBig fid) -> Feature
 
         OGRFeatureH
-        OGR_L_GetFeature(OGRLayerH hLayer, long nFeatureId)
+        OGR_L_GetFeature(OGRLayerH hLayer, GIntBig nFeatureId)
 
         Fetch a feature by its identifier.
 
         This function will attempt to read the identified feature. The nFID
         value cannot be OGRNullFID. Success or failure of this operation is
-        unaffected by the spatial or attribute filters.
+        unaffected by the spatial or attribute filters (and specialized
+        implementations in drivers should make sure that they do not take into
+        account spatial or attribute filters).
 
         If this function returns a non-NULL feature, it is guaranteed that its
         feature id ( OGR_F_GetFID()) will be the same as nFID.
@@ -1353,8 +1319,8 @@ class Layer(MajorObject):
         fallback implementation just scans all the features in the layer
         looking for the desired feature.
 
-        Sequential reads are generally considered interrupted by a
-        OGR_L_GetFeature() call.
+        Sequential reads (with OGR_L_GetNextFeature()) are generally
+        considered interrupted by a OGR_L_GetFeature() call.
 
         The returned feature should be free with OGR_F_Destroy().
 
@@ -1367,23 +1333,23 @@ class Layer(MajorObject):
 
         nFeatureId:  the feature id of the feature to read.
 
-        an handle to a feature now owned by the caller, or NULL on failure. 
+        an handle to a feature now owned by the caller, or NULL on failure.
         """
         return _ogr.Layer_GetFeature(self, *args)
 
     def GetNextFeature(self, *args):
         """
-        GetNextFeature(self) -> Feature
+        GetNextFeature(Layer self) -> Feature
 
         OGRFeatureH
         OGR_L_GetNextFeature(OGRLayerH hLayer)
 
         Fetch the next available feature from this layer.
 
-        The returned feature becomes the responsiblity of the caller to delete
-        with OGR_F_Destroy(). It is critical that all features associated with
-        an OGRLayer (more specifically an OGRFeatureDefn) be deleted before
-        that layer/datasource is deleted.
+        The returned feature becomes the responsibility of the caller to
+        delete with OGR_F_Destroy(). It is critical that all features
+        associated with an OGRLayer (more specifically an OGRFeatureDefn) be
+        deleted before that layer/datasource is deleted.
 
         Only features matching the current spatial filter (set with
         SetSpatialFilter()) will be returned.
@@ -1392,6 +1358,16 @@ class Layer(MajorObject):
         The OGR_L_ResetReading() function can be used to start at the
         beginning again.
 
+        Features returned by OGR_GetNextFeature() may or may not be affected
+        by concurrent modifications depending on drivers. A guaranteed way of
+        seeing modifications in effect is to call OGR_L_ResetReading() on
+        layers where OGR_GetNextFeature() has been called, before reading
+        again. Structural changes in layers (field addition, deletion, ...)
+        when a read is in progress may or may not be possible depending on
+        drivers. If a transaction is committed/aborted, the current sequential
+        reading may or may not be valid after that operation and a call to
+        OGR_L_ResetReading() might be needed.
+
         This function is the same as the C++ method
         OGRLayer::GetNextFeature().
 
@@ -1400,16 +1376,16 @@ class Layer(MajorObject):
 
         hLayer:  handle to the layer from which feature are read.
 
-        an handle to a feature, or NULL if no more features are available. 
+        an handle to a feature, or NULL if no more features are available.
         """
         return _ogr.Layer_GetNextFeature(self, *args)
 
     def SetNextByIndex(self, *args):
         """
-        SetNextByIndex(self, GIntBig new_index) -> OGRErr
+        SetNextByIndex(Layer self, GIntBig new_index) -> OGRErr
 
         OGRErr
-        OGR_L_SetNextByIndex(OGRLayerH hLayer, long nIndex)
+        OGR_L_SetNextByIndex(OGRLayerH hLayer, GIntBig nIndex)
 
         Move read cursor to the nIndex'th feature in the current resultset.
 
@@ -1437,13 +1413,13 @@ class Layer(MajorObject):
         nIndex:  the index indicating how many steps into the result set to
         seek.
 
-        OGRERR_NONE on success or an error code. 
+        OGRERR_NONE on success or an error code.
         """
         return _ogr.Layer_SetNextByIndex(self, *args)
 
     def SetFeature(self, *args):
         """
-        SetFeature(self, Feature feature) -> OGRErr
+        SetFeature(Layer self, Feature feature) -> OGRErr
 
         OGRErr OGR_L_SetFeature(OGRLayerH
         hLayer, OGRFeatureH hFeat)
@@ -1466,13 +1442,14 @@ class Layer(MajorObject):
         hFeat:  the feature to write.
 
         OGRERR_NONE if the operation works, otherwise an appropriate error
-        code. 
+        code (e.g OGRERR_NON_EXISTING_FEATURE if the feature does not exist).
+
         """
         return _ogr.Layer_SetFeature(self, *args)
 
     def CreateFeature(self, *args):
         """
-        CreateFeature(self, Feature feature) -> OGRErr
+        CreateFeature(Layer self, Feature feature) -> OGRErr
 
         OGRErr
         OGR_L_CreateFeature(OGRLayerH hLayer, OGRFeatureH hFeat)
@@ -1495,16 +1472,16 @@ class Layer(MajorObject):
 
         hFeat:  the handle of the feature to write to disk.
 
-        OGRERR_NONE on success. 
+        OGRERR_NONE on success.
         """
         return _ogr.Layer_CreateFeature(self, *args)
 
     def DeleteFeature(self, *args):
         """
-        DeleteFeature(self, GIntBig fid) -> OGRErr
+        DeleteFeature(Layer self, GIntBig fid) -> OGRErr
 
         OGRErr
-        OGR_L_DeleteFeature(OGRLayerH hDS, long nFID)
+        OGR_L_DeleteFeature(OGRLayerH hLayer, GIntBig nFID)
 
         Delete feature from layer.
 
@@ -1523,16 +1500,18 @@ class Layer(MajorObject):
 
         nFID:  the feature id to be deleted from the layer
 
-        OGRERR_NONE on success. 
+        OGRERR_NONE if the operation works, otherwise an appropriate error
+        code (e.g OGRERR_NON_EXISTING_FEATURE if the feature does not exist).
+
         """
         return _ogr.Layer_DeleteFeature(self, *args)
 
     def SyncToDisk(self, *args):
         """
-        SyncToDisk(self) -> OGRErr
+        SyncToDisk(Layer self) -> OGRErr
 
         OGRErr OGR_L_SyncToDisk(OGRLayerH
-        hDS)
+        hLayer)
 
         Flush pending changes to disk.
 
@@ -1556,13 +1535,13 @@ class Layer(MajorObject):
         hLayer:  handle to the layer
 
         OGRERR_NONE if no error occurs (even if nothing is done) or an error
-        code. 
+        code.
         """
         return _ogr.Layer_SyncToDisk(self, *args)
 
     def GetLayerDefn(self, *args):
         """
-        GetLayerDefn(self) -> FeatureDefn
+        GetLayerDefn(Layer self) -> FeatureDefn
 
         OGRFeatureDefnH
         OGR_L_GetLayerDefn(OGRLayerH hLayer)
@@ -1580,15 +1559,15 @@ class Layer(MajorObject):
 
         hLayer:  handle to the layer to get the schema information.
 
-        an handle to the feature definition. 
+        an handle to the feature definition.
         """
         return _ogr.Layer_GetLayerDefn(self, *args)
 
     def GetFeatureCount(self, *args, **kwargs):
         """
-        GetFeatureCount(self, int force = 1) -> GIntBig
+        GetFeatureCount(Layer self, int force=1) -> GIntBig
 
-        int
+        GIntBig
         OGR_L_GetFeatureCount(OGRLayerH hLayer, int bForce)
 
         Fetch the feature count in this layer.
@@ -1607,6 +1586,8 @@ class Layer(MajorObject):
 
         This function is the same as the CPP OGRLayer::GetFeatureCount().
 
+        Note: since GDAL 2.0, this method returns a GIntBig (previously a int)
+
         Parameters:
         -----------
 
@@ -1615,13 +1596,13 @@ class Layer(MajorObject):
         bForce:  Flag indicating whether the count should be computed even if
         it is expensive.
 
-        feature count, -1 if count not known. 
+        feature count, -1 if count not known.
         """
         return _ogr.Layer_GetFeatureCount(self, *args, **kwargs)
 
     def GetExtent(self, *args, **kwargs):
         """
-        GetExtent(self, int force = 1, int can_return_null = 0, int geom_field = 0)
+        GetExtent(Layer self, int force=1, int can_return_null=0, int geom_field=0)
 
         OGRErr OGR_L_GetExtent(OGRLayerH
         hLayer, OGREnvelope *psExtent, int bForce)
@@ -1656,13 +1637,13 @@ class Layer(MajorObject):
         bForce:  Flag indicating whether the extent should be computed even if
         it is expensive.
 
-        OGRERR_NONE on success, OGRERR_FAILURE if extent not known. 
+        OGRERR_NONE on success, OGRERR_FAILURE if extent not known.
         """
         return _ogr.Layer_GetExtent(self, *args, **kwargs)
 
     def TestCapability(self, *args):
         """
-        TestCapability(self, char cap) -> bool
+        TestCapability(Layer self, char const * cap) -> bool
 
         int
         OGR_L_TestCapability(OGRLayerH hLayer, const char *pszCap)
@@ -1697,12 +1678,12 @@ class Layer(MajorObject):
         features in this layer.
 
         OLCFastFeatureCount / "FastFeatureCount": TRUE if this layer can
-        return a feature count (via OGR_L_GetFeatureCount()) efficiently ...
-        ie. without counting the features. In some cases this will return TRUE
+        return a feature count (via OGR_L_GetFeatureCount()) efficiently, i.e.
+        without counting the features. In some cases this will return TRUE
         until a spatial filter is installed after which it will return FALSE.
 
         OLCFastGetExtent / "FastGetExtent": TRUE if this layer can return
-        its data extent (via OGR_L_GetExtent()) efficiently ... ie. without
+        its data extent (via OGR_L_GetExtent()) efficiently, i.e. without
         scanning all the features. In some cases this will return TRUE until a
         spatial filter is installed after which it will return FALSE.
 
@@ -1712,6 +1693,10 @@ class Layer(MajorObject):
         OLCCreateField / "CreateField": TRUE if this layer can create new
         fields on the current layer using CreateField(), otherwise FALSE.
 
+        OLCCreateGeomField / "CreateGeomField": (GDAL >= 1.11) TRUE if this
+        layer can create new geometry fields on the current layer using
+        CreateGeomField(), otherwise FALSE.
+
         OLCDeleteField / "DeleteField": TRUE if this layer can delete
         existing fields on the current layer using DeleteField(), otherwise
         FALSE.
@@ -1735,6 +1720,9 @@ class Layer(MajorObject):
         CommitTransaction() and RollbackTransaction() methods work in a
         meaningful way, otherwise FALSE.
 
+        OLCCurveGeometries / "CurveGeometries": TRUE if this layer supports
+        writing curve geometries or may return such geometries. (GDAL 2.0).
+
         This function is the same as the C++ method
         OGRLayer::TestCapability().
 
@@ -1746,13 +1734,13 @@ class Layer(MajorObject):
         pszCap:  the name of the capability to test.
 
         TRUE if the layer has the requested capability, or FALSE otherwise.
-        OGRLayers will return FALSE for any unrecognised capabilities. 
+        OGRLayers will return FALSE for any unrecognized capabilities.
         """
         return _ogr.Layer_TestCapability(self, *args)
 
     def CreateField(self, *args, **kwargs):
         """
-        CreateField(self, FieldDefn field_def, int approx_ok = 1) -> OGRErr
+        CreateField(Layer self, FieldDefn field_def, int approx_ok=1) -> OGRErr
 
         OGRErr
         OGR_L_CreateField(OGRLayerH hLayer, OGRFieldDefnH hField, int
@@ -1766,15 +1754,19 @@ class Layer(MajorObject):
         directly.
 
         This function should not be called while there are feature objects in
-        existance that were obtained or created with the previous layer
+        existence that were obtained or created with the previous layer
         definition.
 
         Not all drivers support this function. You can query a layer to check
         if it supports it with the OLCCreateField capability. Some drivers may
         only support this method while there are still no features in the
-        layer. When it is supported, the existings features of the backing
+        layer. When it is supported, the existing features of the backing
         file/database should be updated accordingly.
 
+        Drivers may or may not support not-null constraints. If they support
+        creating fields with not-null constraints, this is generally before
+        creating any feature to the layer.
+
         This function is the same as the C++ method OGRLayer::CreateField().
 
         Parameters:
@@ -1787,13 +1779,13 @@ class Layer(MajorObject):
         bApproxOK:  If TRUE, the field may be created in a slightly different
         form depending on the limitations of the format driver.
 
-        OGRERR_NONE on success. 
+        OGRERR_NONE on success.
         """
         return _ogr.Layer_CreateField(self, *args, **kwargs)
 
     def DeleteField(self, *args):
         """
-        DeleteField(self, int iField) -> OGRErr
+        DeleteField(Layer self, int iField) -> OGRErr
 
         OGRErr
         OGR_L_DeleteField(OGRLayerH hLayer, int iField)
@@ -1806,13 +1798,13 @@ class Layer(MajorObject):
         used by a layer directly.
 
         This function should not be called while there are feature objects in
-        existance that were obtained or created with the previous layer
+        existence that were obtained or created with the previous layer
         definition.
 
         Not all drivers support this function. You can query a layer to check
         if it supports it with the OLCDeleteField capability. Some drivers may
         only support this method while there are still no features in the
-        layer. When it is supported, the existings features of the backing
+        layer. When it is supported, the existing features of the backing
         file/database should be updated accordingly.
 
         This function is the same as the C++ method OGRLayer::DeleteField().
@@ -1826,13 +1818,13 @@ class Layer(MajorObject):
 
         OGRERR_NONE on success.
 
-        OGR 1.9.0 
+        OGR 1.9.0
         """
         return _ogr.Layer_DeleteField(self, *args)
 
     def ReorderField(self, *args):
         """
-        ReorderField(self, int iOldFieldPos, int iNewFieldPos) -> OGRErr
+        ReorderField(Layer self, int iOldFieldPos, int iNewFieldPos) -> OGRErr
 
         OGRErr
         OGR_L_ReorderField(OGRLayerH hLayer, int iOldFieldPos, int
@@ -1840,7 +1832,7 @@ class Layer(MajorObject):
 
         Reorder an existing field on a layer.
 
-        This function is a conveniency wrapper of OGR_L_ReorderFields()
+        This function is a convenience wrapper of OGR_L_ReorderFields()
         dedicated to move a single field.
 
         You must use this to reorder existing fields on a real layer.
@@ -1849,7 +1841,7 @@ class Layer(MajorObject):
         OGRFeatureDefn used by a layer directly.
 
         This function should not be called while there are feature objects in
-        existance that were obtained or created with the previous layer
+        existence that were obtained or created with the previous layer
         definition.
 
         The field definition that was at initial position iOldFieldPos will be
@@ -1863,7 +1855,7 @@ class Layer(MajorObject):
         Not all drivers support this function. You can query a layer to check
         if it supports it with the OLCReorderFields capability. Some drivers
         may only support this method while there are still no features in the
-        layer. When it is supported, the existings features of the backing
+        layer. When it is supported, the existing features of the backing
         file/database should be updated accordingly.
 
         This function is the same as the C++ method OGRLayer::ReorderField().
@@ -1881,13 +1873,13 @@ class Layer(MajorObject):
 
         OGRERR_NONE on success.
 
-        OGR 1.9.0 
+        OGR 1.9.0
         """
         return _ogr.Layer_ReorderField(self, *args)
 
     def ReorderFields(self, *args):
         """
-        ReorderFields(self, int nList) -> OGRErr
+        ReorderFields(Layer self, int nList) -> OGRErr
 
         OGRErr
         OGR_L_ReorderFields(OGRLayerH hLayer, int *panMap)
@@ -1900,7 +1892,7 @@ class Layer(MajorObject):
         OGRFeatureDefn used by a layer directly.
 
         This function should not be called while there are feature objects in
-        existance that were obtained or created with the previous layer
+        existence that were obtained or created with the previous layer
         definition.
 
         panMap is such that,for each field definition at position i after
@@ -1913,7 +1905,7 @@ class Layer(MajorObject):
         Not all drivers support this function. You can query a layer to check
         if it supports it with the OLCReorderFields capability. Some drivers
         may only support this method while there are still no features in the
-        layer. When it is supported, the existings features of the backing
+        layer. When it is supported, the existing features of the backing
         file/database should be updated accordingly.
 
         This function is the same as the C++ method OGRLayer::ReorderFields().
@@ -1923,18 +1915,19 @@ class Layer(MajorObject):
 
         hLayer:  handle to the layer.
 
-        panMap:  an array of GetLayerDefn()->GetFieldCount() elements which is
-        a permutation of [0, GetLayerDefn()->GetFieldCount()-1].
+        panMap:  an array of GetLayerDefn()-> OGRFeatureDefn::GetFieldCount()
+        elements which is a permutation of [0, GetLayerDefn()->
+        OGRFeatureDefn::GetFieldCount()-1].
 
         OGRERR_NONE on success.
 
-        OGR 1.9.0 
+        OGR 1.9.0
         """
         return _ogr.Layer_ReorderFields(self, *args)
 
     def AlterFieldDefn(self, *args):
         """
-        AlterFieldDefn(self, int iField, FieldDefn field_def, int nFlags) -> OGRErr
+        AlterFieldDefn(Layer self, int iField, FieldDefn field_def, int nFlags) -> OGRErr
 
         OGRErr
         OGR_L_AlterFieldDefn(OGRLayerH hLayer, int iField, OGRFieldDefnH
@@ -1948,13 +1941,13 @@ class Layer(MajorObject):
         the OGRFeatureDefn used by a layer directly.
 
         This function should not be called while there are feature objects in
-        existance that were obtained or created with the previous layer
+        existence that were obtained or created with the previous layer
         definition.
 
         Not all drivers support this function. You can query a layer to check
         if it supports it with the OLCAlterFieldDefn capability. Some drivers
         may only support this method while there are still no features in the
-        layer. When it is supported, the existings features of the backing
+        layer. When it is supported, the existing features of the backing
         file/database should be updated accordingly. Some drivers might also
         not support all update flags.
 
@@ -1970,24 +1963,68 @@ class Layer(MajorObject):
 
         hNewFieldDefn:  new field definition
 
-        nFlags:  combination of ALTER_NAME_FLAG, ALTER_TYPE_FLAG and
-        ALTER_WIDTH_PRECISION_FLAG to indicate which of the name and/or type
-        and/or width and precision fields from the new field definition must
-        be taken into account.
+        nFlags:  combination of ALTER_NAME_FLAG, ALTER_TYPE_FLAG,
+        ALTER_WIDTH_PRECISION_FLAG, ALTER_NULLABLE_FLAG and ALTER_DEFAULT_FLAG
+        to indicate which of the name and/or type and/or width and precision
+        fields and/or nullability from the new field definition must be taken
+        into account.
 
         OGRERR_NONE on success.
 
-        OGR 1.9.0 
+        OGR 1.9.0
         """
         return _ogr.Layer_AlterFieldDefn(self, *args)
 
     def CreateGeomField(self, *args, **kwargs):
-        """CreateGeomField(self, GeomFieldDefn field_def, int approx_ok = 1) -> OGRErr"""
+        """
+        CreateGeomField(Layer self, GeomFieldDefn field_def, int approx_ok=1) -> OGRErr
+
+        OGRErr
+        OGR_L_CreateGeomField(OGRLayerH hLayer, OGRGeomFieldDefnH hField, int
+        bApproxOK)
+
+        Create a new geometry field on a layer.
+
+        You must use this to create new geometry fields on a real layer.
+        Internally the OGRFeatureDefn for the layer will be updated to reflect
+        the new field. Applications should never modify the OGRFeatureDefn
+        used by a layer directly.
+
+        This function should not be called while there are feature objects in
+        existence that were obtained or created with the previous layer
+        definition.
+
+        Not all drivers support this function. You can query a layer to check
+        if it supports it with the OLCCreateField capability. Some drivers may
+        only support this method while there are still no features in the
+        layer. When it is supported, the existing features of the backing
+        file/database should be updated accordingly.
+
+        Drivers may or may not support not-null constraints. If they support
+        creating fields with not-null constraints, this is generally before
+        creating any feature to the layer.
+
+        This function is the same as the C++ method OGRLayer::CreateField().
+
+        Parameters:
+        -----------
+
+        hLayer:  handle to the layer to write the field definition.
+
+        hField:  handle of the geometry field definition to write to disk.
+
+        bApproxOK:  If TRUE, the field may be created in a slightly different
+        form depending on the limitations of the format driver.
+
+        OGRERR_NONE on success.
+
+        OGR 1.11
+        """
         return _ogr.Layer_CreateGeomField(self, *args, **kwargs)
 
     def StartTransaction(self, *args):
         """
-        StartTransaction(self) -> OGRErr
+        StartTransaction(Layer self) -> OGRErr
 
         OGRErr
         OGR_L_StartTransaction(OGRLayerH hLayer)
@@ -1999,6 +2036,12 @@ class Layer(MajorObject):
         Datasources which do not support transactions will always return
         OGRERR_NONE.
 
+        Note: as of GDAL 2.0, use of this API is discouraged when the dataset
+        offers dataset level transaction with GDALDataset::StartTransaction().
+        The reason is that most drivers can only offer transactions at dataset
+        level, and not layer level. Very few drivers really support
+        transactions at layer scope.
+
         This function is the same as the C++ method
         OGRLayer::StartTransaction().
 
@@ -2007,13 +2050,13 @@ class Layer(MajorObject):
 
         hLayer:  handle to the layer
 
-        OGRERR_NONE on success. 
+        OGRERR_NONE on success.
         """
         return _ogr.Layer_StartTransaction(self, *args)
 
     def CommitTransaction(self, *args):
         """
-        CommitTransaction(self) -> OGRErr
+        CommitTransaction(Layer self) -> OGRErr
 
         OGRErr
         OGR_L_CommitTransaction(OGRLayerH hLayer)
@@ -2033,22 +2076,24 @@ class Layer(MajorObject):
 
         hLayer:  handle to the layer
 
-        OGRERR_NONE on success. 
+        OGRERR_NONE on success.
         """
         return _ogr.Layer_CommitTransaction(self, *args)
 
     def RollbackTransaction(self, *args):
         """
-        RollbackTransaction(self) -> OGRErr
+        RollbackTransaction(Layer self) -> OGRErr
 
         OGRErr
         OGR_L_RollbackTransaction(OGRLayerH hLayer)
 
         For datasources which support transactions, RollbackTransaction will
         roll back a datasource to its state before the start of the current
-        transaction. If no transaction is active, or the rollback fails, will
-        return OGRERR_FAILURE. Datasources which do not support transactions
-        will always return OGRERR_NONE.
+        transaction.
+
+        If no transaction is active, or the rollback fails, will return
+        OGRERR_FAILURE. Datasources which do not support transactions will
+        always return OGRERR_NONE.
 
         This function is the same as the C++ method
         OGRLayer::RollbackTransaction().
@@ -2058,17 +2103,37 @@ class Layer(MajorObject):
 
         hLayer:  handle to the layer
 
-        OGRERR_NONE on success. 
+        OGRERR_NONE on success.
         """
         return _ogr.Layer_RollbackTransaction(self, *args)
 
     def FindFieldIndex(self, *args):
-        """FindFieldIndex(self, char pszFieldName, int bExactMatch) -> int"""
+        """
+        FindFieldIndex(Layer self, char const * pszFieldName, int bExactMatch) -> int
+
+        int
+        OGR_L_FindFieldIndex(OGRLayerH hLayer, const char *pszFieldName, int
+        bExactMatch)
+
+        Find the index of field in a layer.
+
+        The returned number is the index of the field in the layers, or -1 if
+        the field doesn't exist.
+
+        If bExactMatch is set to FALSE and the field doesn't exists in the
+        given form the driver might apply some changes to make it match, like
+        those it might do if the layer was created (eg. like LAUNDER in the
+        OCI driver).
+
+        This method is the same as the C++ method OGRLayer::FindFieldIndex().
+
+        field index, or -1 if the field doesn't exist
+        """
         return _ogr.Layer_FindFieldIndex(self, *args)
 
     def GetSpatialRef(self, *args):
         """
-        GetSpatialRef(self) -> SpatialReference
+        GetSpatialRef(Layer self) -> SpatialReference
 
         OGRSpatialReferenceH
         OGR_L_GetSpatialRef(OGRLayerH hLayer)
@@ -2085,22 +2150,22 @@ class Layer(MajorObject):
 
         hLayer:  handle to the layer to get the spatial reference from.
 
-        spatial reference, or NULL if there isn't one. 
+        spatial reference, or NULL if there isn't one.
         """
         return _ogr.Layer_GetSpatialRef(self, *args)
 
     def GetFeaturesRead(self, *args):
         """
-        GetFeaturesRead(self) -> GIntBig
+        GetFeaturesRead(Layer self) -> GIntBig
 
         GIntBig
-        OGR_L_GetFeaturesRead(OGRLayerH hLayer) 
+        OGR_L_GetFeaturesRead(OGRLayerH hLayer)
         """
         return _ogr.Layer_GetFeaturesRead(self, *args)
 
     def SetIgnoredFields(self, *args):
         """
-        SetIgnoredFields(self, char options) -> OGRErr
+        SetIgnoredFields(Layer self, char const ** options) -> OGRErr
 
         OGRErr
         OGR_L_SetIgnoredFields(OGRLayerH hLayer, const char **papszFields)
@@ -2128,218 +2193,666 @@ class Layer(MajorObject):
         is passed, the ignored list is cleared.
 
         OGRERR_NONE if all field names have been resolved (even if the driver
-        does not support this method) 
+        does not support this method)
         """
         return _ogr.Layer_SetIgnoredFields(self, *args)
 
     def Intersection(self, *args, **kwargs):
         """
-        Intersection(self, Layer method_layer, Layer result_layer, char options = None, 
-            GDALProgressFunc callback = None, void callback_data = None) -> OGRErr
-        """
-        return _ogr.Layer_Intersection(self, *args, **kwargs)
-
-    def Union(self, *args, **kwargs):
-        """
-        Union(self, Layer method_layer, Layer result_layer, char options = None, 
-            GDALProgressFunc callback = None, void callback_data = None) -> OGRErr
-        """
-        return _ogr.Layer_Union(self, *args, **kwargs)
+        Intersection(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0,
+            void * callback_data=None) -> OGRErr
 
-    def SymDifference(self, *args, **kwargs):
-        """
-        SymDifference(self, Layer method_layer, Layer result_layer, char options = None, 
-            GDALProgressFunc callback = None, void callback_data = None) -> OGRErr
-        """
-        return _ogr.Layer_SymDifference(self, *args, **kwargs)
+        OGRErr
+        OGR_L_Intersection(OGRLayerH pLayerInput, OGRLayerH pLayerMethod,
+        OGRLayerH pLayerResult, char **papszOptions, GDALProgressFunc
+        pfnProgress, void *pProgressArg)
 
-    def Identity(self, *args, **kwargs):
-        """
-        Identity(self, Layer method_layer, Layer result_layer, char options = None, 
-            GDALProgressFunc callback = None, void callback_data = None) -> OGRErr
-        """
-        return _ogr.Layer_Identity(self, *args, **kwargs)
+        Intersection of two layers.
 
-    def Update(self, *args, **kwargs):
-        """
-        Update(self, Layer method_layer, Layer result_layer, char options = None, 
-            GDALProgressFunc callback = None, void callback_data = None) -> OGRErr
-        """
-        return _ogr.Layer_Update(self, *args, **kwargs)
+        The result layer contains features whose geometries represent areas
+        that are common between features in the input layer and in the method
+        layer. The features in the result layer have attributes from both
+        input and method layers. The schema of the result layer can be set by
+        the user or, if it is empty, is initialized to contain all fields in
+        the input and method layers.
 
-    def Clip(self, *args, **kwargs):
-        """
-        Clip(self, Layer method_layer, Layer result_layer, char options = None, 
-            GDALProgressFunc callback = None, void callback_data = None) -> OGRErr
-        """
-        return _ogr.Layer_Clip(self, *args, **kwargs)
+        If the schema of the result is set by user and contains fields that
+        have the same name as a field in input and in method layer, then the
+        attribute in the result feature will get the value from the feature of
+        the method layer.
 
-    def Erase(self, *args, **kwargs):
-        """
-        Erase(self, Layer method_layer, Layer result_layer, char options = None, 
-            GDALProgressFunc callback = None, void callback_data = None) -> OGRErr
-        """
-        return _ogr.Layer_Erase(self, *args, **kwargs)
+        For best performance use the minimum amount of features in the method
+        layer and copy it into a memory layer.
 
-    def GetStyleTable(self, *args):
-        """
-        GetStyleTable(self) -> StyleTable
+        This method relies on GEOS support. Do not use unless the GEOS support
+        is compiled in.  The recognized list of options is :
+        SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a feature
+        could not be inserted.
 
-        OGRStyleTableH
-        OGR_L_GetStyleTable(OGRLayerH hLayer) 
-        """
-        return _ogr.Layer_GetStyleTable(self, *args)
+        PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons into
+        MultiPolygons, or LineStrings to MultiLineStrings.
 
-    def SetStyleTable(self, *args):
-        """
-        SetStyleTable(self, StyleTable table)
+        INPUT_PREFIX=string. Set a prefix for the field names that will be
+        created from the fields of the input layer.
 
-        void
-        OGR_L_SetStyleTable(OGRLayerH hLayer, OGRStyleTableH hStyleTable) 
-        """
-        return _ogr.Layer_SetStyleTable(self, *args)
+        METHOD_PREFIX=string. Set a prefix for the field names that will be
+        created from the fields of the method layer.
 
-    def Reference(self):
-      "For backwards compatibility only."
-      pass
+        USE_PREPARED_GEOMETRIES=YES/NO. Set to NO to not use prepared
+        geometries to pretest intersection of features of method layer with
+        features of this layer.
 
-    def Dereference(self):
-      "For backwards compatibility only."
-      pass
+        PRETEST_CONTAINMENT=YES/NO. Set to YES to pretest the containment of
+        features of method layer within the features of this layer. This will
+        speed up the method significantly in some cases. Requires that the
+        prepared geometries are in effect.
 
-    def __len__(self):
-        """Returns the number of features in the layer"""
-        return self.GetFeatureCount()
+        This function is the same as the C++ method OGRLayer::Intersection().
 
-    # To avoid __len__ being called when testing boolean value
-    # which can have side effects (#4758)
-    def __nonzero__(self):
-        return True
+        Parameters:
+        -----------
 
-    # For Python 3 compat
-    __bool__ = __nonzero__
+        pLayerInput:  the input layer. Should not be NULL.
 
-    def __getitem__(self, value):
-        """Support list and slice -like access to the layer.
-        layer[0] would return the first feature on the layer.
-        layer[0:4] would return a list of the first four features."""
-        if isinstance(value, slice):
-            import sys
-            output = []
-            if value.stop == sys.maxint:
-                #for an unending slice, sys.maxint is used
-                #We need to stop before that or GDAL will write an
-                ##error to stdout
-                stop = len(self) - 1
-            else:
-                stop = value.stop
-            for i in xrange(value.start,stop,value.step):
-                feature = self.GetFeature(i)
-                if feature:
-                    output.append(feature)
-                else:
-                    return output
-            return output
-        if isinstance(value, int):
-            if value > len(self)-1:
-                raise IndexError
-            return self.GetFeature(value)
-        else:
-            raise TypeError("Input %s is not of IntType or SliceType" % type(value))
+        pLayerMethod:  the method layer. Should not be NULL.
 
-    def CreateFields(self, fields):
-        """Create a list of fields on the Layer"""
-        for i in fields:
-            self.CreateField(i)
+        pLayerResult:  the layer where the features resulting from the
+        operation are inserted. Should not be NULL. See above the note about
+        the schema.
 
-    def __iter__(self):
-        return self
+        papszOptions:  NULL terminated list of options (may be NULL).
 
-    def next(self):
-        feature = self.GetNextFeature()
-        if not feature:
-            raise StopIteration
-        else:
-            return feature
+        pfnProgress:  a GDALProgressFunc() compatible callback function for
+        reporting progress or NULL.
 
-    def schema(self):
-        output = []
-        defn = self.GetLayerDefn()
-        for n in range(defn.GetFieldCount()):
-            output.append(defn.GetFieldDefn(n))
-        return output
-    schema = property(schema)
+        pProgressArg:  argument to be passed to pfnProgress. May be NULL.
 
+        an error code if there was an error or the execution was interrupted,
+        OGRERR_NONE otherwise.
 
-Layer_swigregister = _ogr.Layer_swigregister
-Layer_swigregister(Layer)
+        The first geometry field is always used.
 
-class Feature(_object):
-    """Proxy of C++ OGRFeatureShadow class"""
-    __swig_setmethods__ = {}
-    __setattr__ = lambda self, name, value: _swig_setattr(self, Feature, name, value)
-    __swig_getmethods__ = {}
-    __getattr__ = lambda self, name: _swig_getattr(self, Feature, name)
-    __repr__ = _swig_repr
-    __swig_destroy__ = _ogr.delete_Feature
-    __del__ = lambda self : None;
-    def __init__(self, *args, **kwargs): 
-        """__init__(self, FeatureDefn feature_def) -> Feature"""
-        this = _ogr.new_Feature(*args, **kwargs)
-        try: self.this.append(this)
-        except: self.this = this
-    def GetDefnRef(self, *args):
+        OGR 1.10
         """
-        GetDefnRef(self) -> FeatureDefn
+        return _ogr.Layer_Intersection(self, *args, **kwargs)
 
-        OGRFeatureDefnH
-        OGR_F_GetDefnRef(OGRFeatureH hFeat)
+    def Union(self, *args, **kwargs):
+        """
+        Union(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0,
+            void * callback_data=None) -> OGRErr
 
-        Fetch feature definition.
+        OGRErr OGR_L_Union(OGRLayerH
+        pLayerInput, OGRLayerH pLayerMethod, OGRLayerH pLayerResult, char
+        **papszOptions, GDALProgressFunc pfnProgress, void *pProgressArg)
 
-        This function is the same as the C++ method OGRFeature::GetDefnRef().
+        Union of two layers.
 
-        Parameters:
-        -----------
+        The result layer contains features whose geometries represent areas
+        that are in either in the input layer or in the method layer. The
+        features in the result layer have attributes from both input and
+        method layers. For features which represent areas that are only in the
+        input or in the method layer the respective attributes have undefined
+        values. The schema of the result layer can be set by the user or, if
+        it is empty, is initialized to contain all fields in the input and
+        method layers.
 
-        hFeat:  handle to the feature to get the feature definition from.
+        If the schema of the result is set by user and contains fields that
+        have the same name as a field in input and in method layer, then the
+        attribute in the result feature will get the value from the feature of
+        the method layer (even if it is undefined).
 
-        an handle to the feature definition object on which feature depends.
+        For best performance use the minimum amount of features in the method
+        layer and copy it into a memory layer.
 
-        """
-        return _ogr.Feature_GetDefnRef(self, *args)
+        This method relies on GEOS support. Do not use unless the GEOS support
+        is compiled in.  The recognized list of options is :
+        SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a feature
+        could not be inserted.
 
-    def SetGeometry(self, *args):
-        """
-        SetGeometry(self, Geometry geom) -> OGRErr
+        PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons into
+        MultiPolygons, or LineStrings to MultiLineStrings.
 
-        OGRErr
-        OGR_F_SetGeometry(OGRFeatureH hFeat, OGRGeometryH hGeom)
+        INPUT_PREFIX=string. Set a prefix for the field names that will be
+        created from the fields of the input layer.
 
-        Set feature geometry.
+        METHOD_PREFIX=string. Set a prefix for the field names that will be
+        created from the fields of the method layer.
 
-        This function updates the features geometry, and operate exactly as
-        SetGeometryDirectly(), except that this function does not assume
-        ownership of the passed geometry, but instead makes a copy of it.
+        USE_PREPARED_GEOMETRIES=YES/NO. Set to NO to not use prepared
+        geometries to pretest intersection of features of method layer with
+        features of this layer.
 
-        This function is the same as the C++ OGRFeature::SetGeometry().
+        This function is the same as the C++ method OGRLayer::Union().
 
         Parameters:
         -----------
 
-        hFeat:  handle to the feature on which new geometry is applied to.
+        pLayerInput:  the input layer. Should not be NULL.
+
+        pLayerMethod:  the method layer. Should not be NULL.
+
+        pLayerResult:  the layer where the features resulting from the
+        operation are inserted. Should not be NULL. See above the note about
+        the schema.
+
+        papszOptions:  NULL terminated list of options (may be NULL).
+
+        pfnProgress:  a GDALProgressFunc() compatible callback function for
+        reporting progress or NULL.
+
+        pProgressArg:  argument to be passed to pfnProgress. May be NULL.
+
+        an error code if there was an error or the execution was interrupted,
+        OGRERR_NONE otherwise.
+
+        The first geometry field is always used.
+
+        OGR 1.10
+        """
+        return _ogr.Layer_Union(self, *args, **kwargs)
+
+    def SymDifference(self, *args, **kwargs):
+        """
+        SymDifference(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0,
+            void * callback_data=None) -> OGRErr
+
+        OGRErr
+        OGR_L_SymDifference(OGRLayerH pLayerInput, OGRLayerH pLayerMethod,
+        OGRLayerH pLayerResult, char **papszOptions, GDALProgressFunc
+        pfnProgress, void *pProgressArg)
+
+        Symmetrical difference of two layers.
+
+        The result layer contains features whose geometries represent areas
+        that are in either in the input layer or in the method layer but not
+        in both. The features in the result layer have attributes from both
+        input and method layers. For features which represent areas that are
+        only in the input or in the method layer the respective attributes
+        have undefined values. The schema of the result layer can be set by
+        the user or, if it is empty, is initialized to contain all fields in
+        the input and method layers.
+
+        If the schema of the result is set by user and contains fields that
+        have the same name as a field in input and in method layer, then the
+        attribute in the result feature will get the value from the feature of
+        the method layer (even if it is undefined).
+
+        For best performance use the minimum amount of features in the method
+        layer and copy it into a memory layer.
+
+        This method relies on GEOS support. Do not use unless the GEOS support
+        is compiled in.  The recognized list of options is :
+        SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a feature
+        could not be inserted.
+
+        PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons into
+        MultiPolygons, or LineStrings to MultiLineStrings.
+
+        INPUT_PREFIX=string. Set a prefix for the field names that will be
+        created from the fields of the input layer.
+
+        METHOD_PREFIX=string. Set a prefix for the field names that will be
+        created from the fields of the method layer.
+
+        This function is the same as the C++ method OGRLayer::SymDifference().
+
+        Parameters:
+        -----------
+
+        pLayerInput:  the input layer. Should not be NULL.
+
+        pLayerMethod:  the method layer. Should not be NULL.
+
+        pLayerResult:  the layer where the features resulting from the
+        operation are inserted. Should not be NULL. See above the note about
+        the schema.
+
+        papszOptions:  NULL terminated list of options (may be NULL).
+
+        pfnProgress:  a GDALProgressFunc() compatible callback function for
+        reporting progress or NULL.
+
+        pProgressArg:  argument to be passed to pfnProgress. May be NULL.
+
+        an error code if there was an error or the execution was interrupted,
+        OGRERR_NONE otherwise.
+
+        The first geometry field is always used.
+
+        OGR 1.10
+        """
+        return _ogr.Layer_SymDifference(self, *args, **kwargs)
+
+    def Identity(self, *args, **kwargs):
+        """
+        Identity(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0,
+            void * callback_data=None) -> OGRErr
+
+        OGRErr OGR_L_Identity(OGRLayerH
+        pLayerInput, OGRLayerH pLayerMethod, OGRLayerH pLayerResult, char
+        **papszOptions, GDALProgressFunc pfnProgress, void *pProgressArg)
+
+        Identify the features of this layer with the ones from the identity
+        layer.
+
+        The result layer contains features whose geometries represent areas
+        that are in the input layer. The features in the result layer have
+        attributes from both input and method layers. The schema of the result
+        layer can be set by the user or, if it is empty, is initialized to
+        contain all fields in input and method layers.
+
+        If the schema of the result is set by user and contains fields that
+        have the same name as a field in input and in method layer, then the
+        attribute in the result feature will get the value from the feature of
+        the method layer (even if it is undefined).
+
+        For best performance use the minimum amount of features in the method
+        layer and copy it into a memory layer.
+
+        This method relies on GEOS support. Do not use unless the GEOS support
+        is compiled in.  The recognized list of options is :
+        SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a feature
+        could not be inserted.
+
+        PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons into
+        MultiPolygons, or LineStrings to MultiLineStrings.
+
+        INPUT_PREFIX=string. Set a prefix for the field names that will be
+        created from the fields of the input layer.
+
+        METHOD_PREFIX=string. Set a prefix for the field names that will be
+        created from the fields of the method layer.
+
+        USE_PREPARED_GEOMETRIES=YES/NO. Set to NO to not use prepared
+        geometries to pretest intersection of features of method layer with
+        features of this layer.
+
+        This function is the same as the C++ method OGRLayer::Identity().
+
+        Parameters:
+        -----------
+
+        pLayerInput:  the input layer. Should not be NULL.
+
+        pLayerMethod:  the method layer. Should not be NULL.
+
+        pLayerResult:  the layer where the features resulting from the
+        operation are inserted. Should not be NULL. See above the note about
+        the schema.
+
+        papszOptions:  NULL terminated list of options (may be NULL).
+
+        pfnProgress:  a GDALProgressFunc() compatible callback function for
+        reporting progress or NULL.
+
+        pProgressArg:  argument to be passed to pfnProgress. May be NULL.
+
+        an error code if there was an error or the execution was interrupted,
+        OGRERR_NONE otherwise.
+
+        The first geometry field is always used.
+
+        OGR 1.10
+        """
+        return _ogr.Layer_Identity(self, *args, **kwargs)
+
+    def Update(self, *args, **kwargs):
+        """
+        Update(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0,
+            void * callback_data=None) -> OGRErr
+
+        OGRErr OGR_L_Update(OGRLayerH
+        pLayerInput, OGRLayerH pLayerMethod, OGRLayerH pLayerResult, char
+        **papszOptions, GDALProgressFunc pfnProgress, void *pProgressArg)
+
+        Update this layer with features from the update layer.
+
+        The result layer contains features whose geometries represent areas
+        that are either in the input layer or in the method layer. The
+        features in the result layer have areas of the features of the method
+        layer or those ares of the features of the input layer that are not
+        covered by the method layer. The features of the result layer get
+        their attributes from the input layer. The schema of the result layer
+        can be set by the user or, if it is empty, is initialized to contain
+        all fields in the input layer.
+
+        If the schema of the result is set by user and contains fields that
+        have the same name as a field in the method layer, then the attribute
+        in the result feature the originates from the method layer will get
+        the value from the feature of the method layer.
+
+        For best performance use the minimum amount of features in the method
+        layer and copy it into a memory layer.
+
+        This method relies on GEOS support. Do not use unless the GEOS support
+        is compiled in.  The recognized list of options is :
+        SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a feature
+        could not be inserted.
+
+        PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons into
+        MultiPolygons, or LineStrings to MultiLineStrings.
+
+        INPUT_PREFIX=string. Set a prefix for the field names that will be
+        created from the fields of the input layer.
+
+        METHOD_PREFIX=string. Set a prefix for the field names that will be
+        created from the fields of the method layer.
+
+        This function is the same as the C++ method OGRLayer::Update().
+
+        Parameters:
+        -----------
+
+        pLayerInput:  the input layer. Should not be NULL.
+
+        pLayerMethod:  the method layer. Should not be NULL.
+
+        pLayerResult:  the layer where the features resulting from the
+        operation are inserted. Should not be NULL. See above the note about
+        the schema.
+
+        papszOptions:  NULL terminated list of options (may be NULL).
+
+        pfnProgress:  a GDALProgressFunc() compatible callback function for
+        reporting progress or NULL.
+
+        pProgressArg:  argument to be passed to pfnProgress. May be NULL.
+
+        an error code if there was an error or the execution was interrupted,
+        OGRERR_NONE otherwise.
+
+        The first geometry field is always used.
+
+        OGR 1.10
+        """
+        return _ogr.Layer_Update(self, *args, **kwargs)
+
+    def Clip(self, *args, **kwargs):
+        """
+        Clip(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0,
+            void * callback_data=None) -> OGRErr
+
+        OGRErr OGR_L_Clip(OGRLayerH pLayerInput,
+        OGRLayerH pLayerMethod, OGRLayerH pLayerResult, char **papszOptions,
+        GDALProgressFunc pfnProgress, void *pProgressArg)
+
+        Clip off areas that are not covered by the method layer.
+
+        The result layer contains features whose geometries represent areas
+        that are in the input layer and in the method layer. The features in
+        the result layer have the (possibly clipped) areas of features in the
+        input layer and the attributes from the same features. The schema of
+        the result layer can be set by the user or, if it is empty, is
+        initialized to contain all fields in the input layer.
+
+        For best performance use the minimum amount of features in the method
+        layer and copy it into a memory layer.
+
+        This method relies on GEOS support. Do not use unless the GEOS support
+        is compiled in.  The recognized list of options is :
+        SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a feature
+        could not be inserted.
+
+        PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons into
+        MultiPolygons, or LineStrings to MultiLineStrings.
+
+        INPUT_PREFIX=string. Set a prefix for the field names that will be
+        created from the fields of the input layer.
+
+        METHOD_PREFIX=string. Set a prefix for the field names that will be
+        created from the fields of the method layer.
+
+        This function is the same as the C++ method OGRLayer::Clip().
+
+        Parameters:
+        -----------
+
+        pLayerInput:  the input layer. Should not be NULL.
+
+        pLayerMethod:  the method layer. Should not be NULL.
+
+        pLayerResult:  the layer where the features resulting from the
+        operation are inserted. Should not be NULL. See above the note about
+        the schema.
+
+        papszOptions:  NULL terminated list of options (may be NULL).
+
+        pfnProgress:  a GDALProgressFunc() compatible callback function for
+        reporting progress or NULL.
+
+        pProgressArg:  argument to be passed to pfnProgress. May be NULL.
+
+        an error code if there was an error or the execution was interrupted,
+        OGRERR_NONE otherwise.
+
+        The first geometry field is always used.
+
+        OGR 1.10
+        """
+        return _ogr.Layer_Clip(self, *args, **kwargs)
+
+    def Erase(self, *args, **kwargs):
+        """
+        Erase(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0,
+            void * callback_data=None) -> OGRErr
+
+        OGRErr OGR_L_Erase(OGRLayerH
+        pLayerInput, OGRLayerH pLayerMethod, OGRLayerH pLayerResult, char
+        **papszOptions, GDALProgressFunc pfnProgress, void *pProgressArg)
+
+        Remove areas that are covered by the method layer.
+
+        The result layer contains features whose geometries represent areas
+        that are in the input layer but not in the method layer. The features
+        in the result layer have attributes from the input layer. The schema
+        of the result layer can be set by the user or, if it is empty, is
+        initialized to contain all fields in the input layer.
+
+        For best performance use the minimum amount of features in the method
+        layer and copy it into a memory layer.
+
+        This method relies on GEOS support. Do not use unless the GEOS support
+        is compiled in.  The recognized list of options is :
+        SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a feature
+        could not be inserted.
+
+        PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons into
+        MultiPolygons, or LineStrings to MultiLineStrings.
+
+        INPUT_PREFIX=string. Set a prefix for the field names that will be
+        created from the fields of the input layer.
+
+        METHOD_PREFIX=string. Set a prefix for the field names that will be
+        created from the fields of the method layer.
+
+        This function is the same as the C++ method OGRLayer::Erase().
+
+        Parameters:
+        -----------
+
+        pLayerInput:  the input layer. Should not be NULL.
+
+        pLayerMethod:  the method layer. Should not be NULL.
+
+        pLayerResult:  the layer where the features resulting from the
+        operation are inserted. Should not be NULL. See above the note about
+        the schema.
+
+        papszOptions:  NULL terminated list of options (may be NULL).
+
+        pfnProgress:  a GDALProgressFunc() compatible callback function for
+        reporting progress or NULL.
+
+        pProgressArg:  argument to be passed to pfnProgress. May be NULL.
+
+        an error code if there was an error or the execution was interrupted,
+        OGRERR_NONE otherwise.
+
+        The first geometry field is always used.
+
+        OGR 1.10
+        """
+        return _ogr.Layer_Erase(self, *args, **kwargs)
+
+    def GetStyleTable(self, *args):
+        """
+        GetStyleTable(Layer self) -> StyleTable
+
+        OGRStyleTableH
+        OGR_L_GetStyleTable(OGRLayerH hLayer)
+        """
+        return _ogr.Layer_GetStyleTable(self, *args)
+
+    def SetStyleTable(self, *args):
+        """
+        SetStyleTable(Layer self, StyleTable table)
+
+        void
+        OGR_L_SetStyleTable(OGRLayerH hLayer, OGRStyleTableH hStyleTable)
+        """
+        return _ogr.Layer_SetStyleTable(self, *args)
+
+    def Reference(self):
+      "For backwards compatibility only."
+      pass
+
+    def Dereference(self):
+      "For backwards compatibility only."
+      pass
+
+    def __len__(self):
+        """Returns the number of features in the layer"""
+        return self.GetFeatureCount()
+
+    # To avoid __len__ being called when testing boolean value
+    # which can have side effects (#4758)
+    def __nonzero__(self):
+        return True
+
+    # For Python 3 compat
+    __bool__ = __nonzero__
+
+    def __getitem__(self, value):
+        """Support list and slice -like access to the layer.
+        layer[0] would return the first feature on the layer.
+        layer[0:4] would return a list of the first four features."""
+        if isinstance(value, slice):
+            import sys
+            output = []
+            if value.stop == sys.maxint:
+                #for an unending slice, sys.maxint is used
+                #We need to stop before that or GDAL will write an
+                ##error to stdout
+                stop = len(self) - 1
+            else:
+                stop = value.stop
+            for i in xrange(value.start,stop,value.step):
+                feature = self.GetFeature(i)
+                if feature:
+                    output.append(feature)
+                else:
+                    return output
+            return output
+        if isinstance(value, int):
+            if value > len(self)-1:
+                raise IndexError
+            return self.GetFeature(value)
+        else:
+            raise TypeError("Input %s is not of IntType or SliceType" % type(value))
+
+    def CreateFields(self, fields):
+        """Create a list of fields on the Layer"""
+        for i in fields:
+            self.CreateField(i)
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        feature = self.GetNextFeature()
+        if not feature:
+            raise StopIteration
+        else:
+            return feature
+
+    def schema(self):
+        output = []
+        defn = self.GetLayerDefn()
+        for n in range(defn.GetFieldCount()):
+            output.append(defn.GetFieldDefn(n))
+        return output
+    schema = property(schema)
+
+
+Layer_swigregister = _ogr.Layer_swigregister
+Layer_swigregister(Layer)
+
+class Feature(_object):
+    """Proxy of C++ OGRFeatureShadow class"""
+    __swig_setmethods__ = {}
+    __setattr__ = lambda self, name, value: _swig_setattr(self, Feature, name, value)
+    __swig_getmethods__ = {}
+    __getattr__ = lambda self, name: _swig_getattr(self, Feature, name)
+    __repr__ = _swig_repr
+    __swig_destroy__ = _ogr.delete_Feature
+    __del__ = lambda self : None;
+    def __init__(self, *args, **kwargs):
+        """__init__(OGRFeatureShadow self, FeatureDefn feature_def) -> Feature"""
+        this = _ogr.new_Feature(*args, **kwargs)
+        try: self.this.append(this)
+        except: self.this = this
+    def GetDefnRef(self, *args):
+        """
+        GetDefnRef(Feature self) -> FeatureDefn
+
+        OGRFeatureDefnH
+        OGR_F_GetDefnRef(OGRFeatureH hFeat)
+
+        Fetch feature definition.
+
+        This function is the same as the C++ method OGRFeature::GetDefnRef().
+
+        Parameters:
+        -----------
+
+        hFeat:  handle to the feature to get the feature definition from.
+
+        an handle to the feature definition object on which feature depends.
+
+        """
+        return _ogr.Feature_GetDefnRef(self, *args)
+
+    def SetGeometry(self, *args):
+        """
+        SetGeometry(Feature self, Geometry geom) -> OGRErr
+
+        OGRErr
+        OGR_F_SetGeometry(OGRFeatureH hFeat, OGRGeometryH hGeom)
+
+        Set feature geometry.
+
+        This function updates the features geometry, and operate exactly as
+        SetGeometryDirectly(), except that this function does not assume
+        ownership of the passed geometry, but instead makes a copy of it.
+
+        This function is the same as the C++ OGRFeature::SetGeometry().
+
+        Parameters:
+        -----------
+
+        hFeat:  handle to the feature on which new geometry is applied to.
 
         hGeom:  handle to the new geometry to apply to feature.
 
         OGRERR_NONE if successful, or OGR_UNSUPPORTED_GEOMETRY_TYPE if the
         geometry type is illegal for the OGRFeatureDefn (checking not yet
-        implemented). 
+        implemented).
         """
         return _ogr.Feature_SetGeometry(self, *args)
 
     def SetGeometryDirectly(self, *args):
         """
-        SetGeometryDirectly(self, Geometry geom) -> OGRErr
+        SetGeometryDirectly(Feature self, Geometry geom) -> OGRErr
 
         OGRErr
         OGR_F_SetGeometryDirectly(OGRFeatureH hFeat, OGRGeometryH hGeom)
@@ -2348,7 +2861,7 @@ class Feature(_object):
 
         This function updates the features geometry, and operate exactly as
         SetGeometry(), except that this function assumes ownership of the
-        passed geometry.
+        passed geometry (even in case of failure of that function).
 
         This function is the same as the C++ method
         OGRFeature::SetGeometryDirectly.
@@ -2362,13 +2875,13 @@ class Feature(_object):
 
         OGRERR_NONE if successful, or OGR_UNSUPPORTED_GEOMETRY_TYPE if the
         geometry type is illegal for the OGRFeatureDefn (checking not yet
-        implemented). 
+        implemented).
         """
         return _ogr.Feature_SetGeometryDirectly(self, *args)
 
     def GetGeometryRef(self, *args):
         """
-        GetGeometryRef(self) -> Geometry
+        GetGeometryRef(Feature self) -> Geometry
 
         OGRGeometryH
         OGR_F_GetGeometryRef(OGRFeatureH hFeat)
@@ -2384,34 +2897,106 @@ class Feature(_object):
         hFeat:  handle to the feature to get geometry from.
 
         an handle to internal feature geometry. This object should not be
-        modified. 
+        modified.
         """
         return _ogr.Feature_GetGeometryRef(self, *args)
 
     def SetGeomField(self, *args):
         """
-        SetGeomField(self, int iField, Geometry geom) -> OGRErr
-        SetGeomField(self, char name, Geometry geom) -> OGRErr
+        SetGeomField(Feature self, int iField, Geometry geom) -> OGRErr
+        SetGeomField(Feature self, char const * name, Geometry geom) -> OGRErr
+
+        OGRErr
+        OGR_F_SetGeomField(OGRFeatureH hFeat, int iField, OGRGeometryH hGeom)
+
+        Set feature geometry of a specified geometry field.
+
+        This function updates the features geometry, and operate exactly as
+        SetGeometryDirectly(), except that this function does not assume
+        ownership of the passed geometry, but instead makes a copy of it.
+
+        This function is the same as the C++ OGRFeature::SetGeomField().
+
+        Parameters:
+        -----------
+
+        hFeat:  handle to the feature on which new geometry is applied to.
+
+        iField:  geometry field to set.
+
+        hGeom:  handle to the new geometry to apply to feature.
+
+        OGRERR_NONE if successful, or OGR_UNSUPPORTED_GEOMETRY_TYPE if the
+        geometry type is illegal for the OGRFeatureDefn (checking not yet
+        implemented).
         """
         return _ogr.Feature_SetGeomField(self, *args)
 
     def SetGeomFieldDirectly(self, *args):
         """
-        SetGeomFieldDirectly(self, int iField, Geometry geom) -> OGRErr
-        SetGeomFieldDirectly(self, char name, Geometry geom) -> OGRErr
+        SetGeomFieldDirectly(Feature self, int iField, Geometry geom) -> OGRErr
+        SetGeomFieldDirectly(Feature self, char const * name, Geometry geom) -> OGRErr
+
+        OGRErr
+        OGR_F_SetGeomFieldDirectly(OGRFeatureH hFeat, int iField, OGRGeometryH
+        hGeom)
+
+        Set feature geometry of a specified geometry field.
+
+        This function updates the features geometry, and operate exactly as
+        SetGeomField(), except that this function assumes ownership of the
+        passed geometry (even in case of failure of that function).
+
+        This function is the same as the C++ method
+        OGRFeature::SetGeomFieldDirectly.
+
+        Parameters:
+        -----------
+
+        hFeat:  handle to the feature on which to apply the geometry.
+
+        iField:  geometry field to set.
+
+        hGeom:  handle to the new geometry to apply to feature.
+
+        OGRERR_NONE if successful, or OGRERR_FAILURE if the index is invalid,
+        or OGR_UNSUPPORTED_GEOMETRY_TYPE if the geometry type is illegal for
+        the OGRFeatureDefn (checking not yet implemented).
+
+        GDAL 1.11
         """
         return _ogr.Feature_SetGeomFieldDirectly(self, *args)
 
     def GetGeomFieldRef(self, *args):
         """
-        GetGeomFieldRef(self, int iField) -> Geometry
-        GetGeomFieldRef(self, char name) -> Geometry
+        GetGeomFieldRef(Feature self, int iField) -> Geometry
+        GetGeomFieldRef(Feature self, char const * name) -> Geometry
+
+        OGRGeometryH
+        OGR_F_GetGeomFieldRef(OGRFeatureH hFeat, int iField)
+
+        Fetch an handle to feature geometry.
+
+        This function is the same as the C++ method
+        OGRFeature::GetGeomFieldRef().
+
+        Parameters:
+        -----------
+
+        hFeat:  handle to the feature to get geometry from.
+
+        iField:  geometry field to get.
+
+        an handle to internal feature geometry. This object should not be
+        modified.
+
+        GDAL 1.11
         """
         return _ogr.Feature_GetGeomFieldRef(self, *args)
 
     def Clone(self, *args):
         """
-        Clone(self) -> Feature
+        Clone(Feature self) -> Feature
 
         OGRFeatureH OGR_F_Clone(OGRFeatureH
         hFeat)
@@ -2428,13 +3013,13 @@ class Feature(_object):
 
         hFeat:  handle to the feature to clone.
 
-        an handle to the new feature, exactly matching this feature. 
+        an handle to the new feature, exactly matching this feature.
         """
         return _ogr.Feature_Clone(self, *args)
 
     def Equal(self, *args):
         """
-        Equal(self, Feature feature) -> bool
+        Equal(Feature self, Feature feature) -> bool
 
         int OGR_F_Equal(OGRFeatureH hFeat,
         OGRFeatureH hOtherFeat)
@@ -2454,13 +3039,13 @@ class Feature(_object):
 
         hOtherFeat:  handle to the other feature to test this one against.
 
-        TRUE if they are equal, otherwise FALSE. 
+        TRUE if they are equal, otherwise FALSE.
         """
         return _ogr.Feature_Equal(self, *args)
 
     def GetFieldCount(self, *args):
         """
-        GetFieldCount(self) -> int
+        GetFieldCount(Feature self) -> int
 
         int
         OGR_F_GetFieldCount(OGRFeatureH hFeat)
@@ -2476,14 +3061,14 @@ class Feature(_object):
 
         hFeat:  handle to the feature to get the fields count from.
 
-        count of fields. 
+        count of fields.
         """
         return _ogr.Feature_GetFieldCount(self, *args)
 
     def GetFieldDefnRef(self, *args):
         """
-        GetFieldDefnRef(self, int id) -> FieldDefn
-        GetFieldDefnRef(self, char name) -> FieldDefn
+        GetFieldDefnRef(Feature self, int id) -> FieldDefn
+        GetFieldDefnRef(Feature self, char const * name) -> FieldDefn
 
         OGRFieldDefnH
         OGR_F_GetFieldDefnRef(OGRFeatureH hFeat, int i)
@@ -2501,25 +3086,65 @@ class Feature(_object):
         i:  the field to fetch, from 0 to GetFieldCount()-1.
 
         an handle to the field definition (from the OGRFeatureDefn). This is
-        an internal reference, and should not be deleted or modified. 
+        an internal reference, and should not be deleted or modified.
         """
         return _ogr.Feature_GetFieldDefnRef(self, *args)
 
     def GetGeomFieldCount(self, *args):
-        """GetGeomFieldCount(self) -> int"""
+        """
+        GetGeomFieldCount(Feature self) -> int
+
+        int
+        OGR_F_GetGeomFieldCount(OGRFeatureH hFeat)
+
+        Fetch number of geometry fields on this feature This will always be
+        the same as the geometry field count for the OGRFeatureDefn.
+
+        This function is the same as the C++ method
+        OGRFeature::GetGeomFieldCount().
+
+        Parameters:
+        -----------
+
+        hFeat:  handle to the feature to get the geometry fields count from.
+
+        count of geometry fields.
+
+        GDAL 1.11
+        """
         return _ogr.Feature_GetGeomFieldCount(self, *args)
 
     def GetGeomFieldDefnRef(self, *args):
         """
-        GetGeomFieldDefnRef(self, int id) -> GeomFieldDefn
-        GetGeomFieldDefnRef(self, char name) -> GeomFieldDefn
+        GetGeomFieldDefnRef(Feature self, int id) -> GeomFieldDefn
+        GetGeomFieldDefnRef(Feature self, char const * name) -> GeomFieldDefn
+
+        OGRGeomFieldDefnH
+        OGR_F_GetGeomFieldDefnRef(OGRFeatureH hFeat, int i)
+
+        Fetch definition for this geometry field.
+
+        This function is the same as the C++ method
+        OGRFeature::GetGeomFieldDefnRef().
+
+        Parameters:
+        -----------
+
+        hFeat:  handle to the feature on which the field is found.
+
+        i:  the field to fetch, from 0 to GetGeomFieldCount()-1.
+
+        an handle to the field definition (from the OGRFeatureDefn). This is
+        an internal reference, and should not be deleted or modified.
+
+        GDAL 1.11
         """
         return _ogr.Feature_GetGeomFieldDefnRef(self, *args)
 
     def GetFieldAsString(self, *args):
         """
-        GetFieldAsString(self, int id) -> char
-        GetFieldAsString(self, char name) -> char
+        GetFieldAsString(Feature self, int id) -> char const
+        GetFieldAsString(Feature self, char const * name) -> char const *
 
         const char*
         OGR_F_GetFieldAsString(OGRFeatureH hFeat, int iField)
@@ -2541,14 +3166,14 @@ class Feature(_object):
         iField:  the field to fetch, from 0 to GetFieldCount()-1.
 
         the field value. This string is internal, and should not be modified,
-        or freed. Its lifetime may be very brief. 
+        or freed. Its lifetime may be very brief.
         """
         return _ogr.Feature_GetFieldAsString(self, *args)
 
     def GetFieldAsInteger(self, *args):
         """
-        GetFieldAsInteger(self, int id) -> int
-        GetFieldAsInteger(self, char name) -> int
+        GetFieldAsInteger(Feature self, int id) -> int
+        GetFieldAsInteger(Feature self, char const * name) -> int
 
         int
         OGR_F_GetFieldAsInteger(OGRFeatureH hFeat, int iField)
@@ -2569,30 +3194,54 @@ class Feature(_object):
 
         iField:  the field to fetch, from 0 to GetFieldCount()-1.
 
-        the field value. 
+        the field value.
         """
         return _ogr.Feature_GetFieldAsInteger(self, *args)
 
     def GetFieldAsInteger64(self, *args):
         """
-        GetFieldAsInteger64(self, int id) -> GIntBig
-        GetFieldAsInteger64(self, char name) -> GIntBig
+        GetFieldAsInteger64(Feature self, int id) -> GIntBig
+        GetFieldAsInteger64(Feature self, char const * name) -> GIntBig
+
+        GIntBig
+        OGR_F_GetFieldAsInteger64(OGRFeatureH hFeat, int iField)
+
+        Fetch field value as integer 64 bit.
+
+        OFTInteger are promoted to 64 bit. OFTString features will be
+        translated using CPLAtoGIntBig(). OFTReal fields will be cast to
+        integer. Other field types, or errors will result in a return value of
+        zero.
+
+        This function is the same as the C++ method
+        OGRFeature::GetFieldAsInteger64().
+
+        Parameters:
+        -----------
+
+        hFeat:  handle to the feature that owned the field.
+
+        iField:  the field to fetch, from 0 to GetFieldCount()-1.
+
+        the field value.
+
+        GDAL 2.0
         """
         return _ogr.Feature_GetFieldAsInteger64(self, *args)
 
     def GetFieldAsDouble(self, *args):
         """
-        GetFieldAsDouble(self, int id) -> double
-        GetFieldAsDouble(self, char name) -> double
+        GetFieldAsDouble(Feature self, int id) -> double
+        GetFieldAsDouble(Feature self, char const * name) -> double
 
         double
         OGR_F_GetFieldAsDouble(OGRFeatureH hFeat, int iField)
 
         Fetch field value as a double.
 
-        OFTString features will be translated using atof(). OFTInteger fields
-        will be cast to double. Other field types, or errors will result in a
-        return value of zero.
+        OFTString features will be translated using CPLAtof(). OFTInteger
+        fields will be cast to double. Other field types, or errors will
+        result in a return value of zero.
 
         This function is the same as the C++ method
         OGRFeature::GetFieldAsDouble().
@@ -2604,13 +3253,14 @@ class Feature(_object):
 
         iField:  the field to fetch, from 0 to GetFieldCount()-1.
 
-        the field value. 
+        the field value.
         """
         return _ogr.Feature_GetFieldAsDouble(self, *args)
 
     def GetFieldAsDateTime(self, *args):
         """
-        GetFieldAsDateTime(self, int id)
+        GetFieldAsDateTime(Feature self, int id)
+        GetFieldAsDateTime(Feature self, char const * name)
 
         int
         OGR_F_GetFieldAsDateTime(OGRFeatureH hFeat, int iField, int *pnYear,
@@ -2647,13 +3297,17 @@ class Feature(_object):
         pnTZFlag:  (0=unknown, 1=localtime, 100=GMT, see data model for
         details)
 
-        TRUE on success or FALSE on failure. 
+        TRUE on success or FALSE on failure.
+
+        See:  Use OGR_F_GetFieldAsDateTimeEx() for second with millisecond
+        accuracy.
         """
         return _ogr.Feature_GetFieldAsDateTime(self, *args)
 
     def GetFieldAsIntegerList(self, *args):
         """
-        GetFieldAsIntegerList(self, int id)
+        GetFieldAsIntegerList(Feature self, int id)
+        GetFieldAsIntegerList(Feature self, char const * name)
 
         const int*
         OGR_F_GetFieldAsIntegerList(OGRFeatureH hFeat, int iField, int
@@ -2677,17 +3331,46 @@ class Feature(_object):
 
         the field value. This list is internal, and should not be modified, or
         freed. Its lifetime may be very brief. If *pnCount is zero on return
-        the returned pointer may be NULL or non-NULL. 
+        the returned pointer may be NULL or non-NULL.
         """
         return _ogr.Feature_GetFieldAsIntegerList(self, *args)
 
     def GetFieldAsInteger64List(self, *args):
-        """GetFieldAsInteger64List(self, int id)"""
+        """
+        GetFieldAsInteger64List(Feature self, int id)
+
+        const GIntBig*
+        OGR_F_GetFieldAsInteger64List(OGRFeatureH hFeat, int iField, int
+        *pnCount)
+
+        Fetch field value as a list of 64 bit integers.
+
+        Currently this function only works for OFTInteger64List fields.
+
+        This function is the same as the C++ method
+        OGRFeature::GetFieldAsInteger64List().
+
+        Parameters:
+        -----------
+
+        hFeat:  handle to the feature that owned the field.
+
+        iField:  the field to fetch, from 0 to GetFieldCount()-1.
+
+        pnCount:  an integer to put the list count (number of integers) into.
+
+        the field value. This list is internal, and should not be modified, or
+        freed. Its lifetime may be very brief. If *pnCount is zero on return
+        the returned pointer may be NULL or non-NULL.
+
+        GDAL 2.0
+        """
         return _ogr.Feature_GetFieldAsInteger64List(self, *args)
 
     def GetFieldAsDoubleList(self, *args):
         """
-        GetFieldAsDoubleList(self, int id)
+        GetFieldAsDoubleList(Feature self, int id)
+        GetFieldAsDoubleList(Feature self, char const * name)
 
         const double*
         OGR_F_GetFieldAsDoubleList(OGRFeatureH hFeat, int iField, int
@@ -2711,13 +3394,13 @@ class Feature(_object):
 
         the field value. This list is internal, and should not be modified, or
         freed. Its lifetime may be very brief. If *pnCount is zero on return
-        the returned pointer may be NULL or non-NULL. 
+        the returned pointer may be NULL or non-NULL.
         """
         return _ogr.Feature_GetFieldAsDoubleList(self, *args)
 
     def GetFieldAsStringList(self, *args):
         """
-        GetFieldAsStringList(self, int id) -> char
+        GetFieldAsStringList(Feature self, int id) -> char **
 
         char**
         OGR_F_GetFieldAsStringList(OGRFeatureH hFeat, int iField)
@@ -2740,21 +3423,21 @@ class Feature(_object):
         iField:  the field to fetch, from 0 to GetFieldCount()-1.
 
         the field value. This list is internal, and should not be modified, or
-        freed. Its lifetime may be very brief. 
+        freed. Its lifetime may be very brief.
         """
         return _ogr.Feature_GetFieldAsStringList(self, *args)
 
     def GetFieldAsBinary(self, *args):
         """
-        GetFieldAsBinary(self, int id) -> OGRErr
-        GetFieldAsBinary(self, char name) -> OGRErr
+        GetFieldAsBinary(Feature self, int id) -> OGRErr
+        GetFieldAsBinary(Feature self, char const * name) -> OGRErr
 
         GByte*
         OGR_F_GetFieldAsBinary(OGRFeatureH hFeat, int iField, int *pnBytes)
 
         Fetch field value as binary.
 
-        Currently this method only works for OFTBinary fields.
+        This method only works for OFTBinary and OFTString fields.
 
         This function is the same as the C++ method
         OGRFeature::GetFieldAsBinary().
@@ -2769,14 +3452,14 @@ class Feature(_object):
         pnBytes:  location to place count of bytes returned.
 
         the field value. This list is internal, and should not be modified, or
-        freed. Its lifetime may be very brief. 
+        freed. Its lifetime may be very brief.
         """
         return _ogr.Feature_GetFieldAsBinary(self, *args)
 
     def IsFieldSet(self, *args):
         """
-        IsFieldSet(self, int id) -> bool
-        IsFieldSet(self, char name) -> bool
+        IsFieldSet(Feature self, int id) -> bool
+        IsFieldSet(Feature self, char const * name) -> bool
 
         int OGR_F_IsFieldSet(OGRFeatureH
         hFeat, int iField)
@@ -2792,13 +3475,13 @@ class Feature(_object):
 
         iField:  the field to test.
 
-        TRUE if the field has been set, otherwise false. 
+        TRUE if the field has been set, otherwise false.
         """
         return _ogr.Feature_IsFieldSet(self, *args)
 
     def GetFieldIndex(self, *args):
         """
-        GetFieldIndex(self, char name) -> int
+        GetFieldIndex(Feature self, char const * name) -> int
 
         int
         OGR_F_GetFieldIndex(OGRFeatureH hFeat, const char *pszName)
@@ -2817,23 +3500,50 @@ class Feature(_object):
 
         pszName:  the name of the field to search for.
 
-        the field index, or -1 if no matching field is found. 
+        the field index, or -1 if no matching field is found.
         """
         return _ogr.Feature_GetFieldIndex(self, *args)
 
     def GetGeomFieldIndex(self, *args):
-        """GetGeomFieldIndex(self, char name) -> int"""
+        """
+        GetGeomFieldIndex(Feature self, char const * name) -> int
+
+        int
+        OGR_F_GetGeomFieldIndex(OGRFeatureH hFeat, const char *pszName)
+
+        Fetch the geometry field index given geometry field name.
+
+        This is a cover for the OGRFeatureDefn::GetGeomFieldIndex() method.
+
+        This function is the same as the C++ method
+        OGRFeature::GetGeomFieldIndex().
+
+        Parameters:
+        -----------
+
+        hFeat:  handle to the feature on which the geometry field is found.
+
+        pszName:  the name of the geometry field to search for.
+
+        the geometry field index, or -1 if no matching geometry field is
+        found.
+
+        GDAL 1.11
+        """
         return _ogr.Feature_GetGeomFieldIndex(self, *args)
 
     def GetFID(self, *args):
         """
-        GetFID(self) -> GIntBig
+        GetFID(Feature self) -> GIntBig
 
-        long OGR_F_GetFID(OGRFeatureH hFeat)
+        GIntBig OGR_F_GetFID(OGRFeatureH
+        hFeat)
 
         Get feature identifier.
 
         This function is the same as the C++ method OGRFeature::GetFID().
+        Note: since GDAL 2.0, this method returns a GIntBig (previously a
+        long)
 
         Parameters:
         -----------
@@ -2841,16 +3551,16 @@ class Feature(_object):
         hFeat:  handle to the feature from which to get the feature
         identifier.
 
-        feature id or OGRNullFID if none has been assigned. 
+        feature id or OGRNullFID if none has been assigned.
         """
         return _ogr.Feature_GetFID(self, *args)
 
     def SetFID(self, *args):
         """
-        SetFID(self, GIntBig fid) -> OGRErr
+        SetFID(Feature self, GIntBig fid) -> OGRErr
 
         OGRErr OGR_F_SetFID(OGRFeatureH hFeat,
-        long nFID)
+        GIntBig nFID)
 
         Set the feature identifier.
 
@@ -2868,13 +3578,13 @@ class Feature(_object):
 
         nFID:  the new feature identifier value to assign.
 
-        On success OGRERR_NONE, or on failure some other value. 
+        On success OGRERR_NONE, or on failure some other value.
         """
         return _ogr.Feature_SetFID(self, *args)
 
     def DumpReadable(self, *args):
         """
-        DumpReadable(self)
+        DumpReadable(Feature self)
 
         void
         OGR_F_DumpReadable(OGRFeatureH hFeat, FILE *fpOut)
@@ -2893,14 +3603,14 @@ class Feature(_object):
 
         hFeat:  handle to the feature to dump.
 
-        fpOut:  the stream to write to, such as strout. 
+        fpOut:  the stream to write to, such as strout.
         """
         return _ogr.Feature_DumpReadable(self, *args)
 
     def UnsetField(self, *args):
         """
-        UnsetField(self, int id)
-        UnsetField(self, char name)
+        UnsetField(Feature self, int id)
+        UnsetField(Feature self, char const * name)
 
         void OGR_F_UnsetField(OGRFeatureH
         hFeat, int iField)
@@ -2914,30 +3624,54 @@ class Feature(_object):
 
         hFeat:  handle to the feature on which the field is.
 
-        iField:  the field to unset. 
+        iField:  the field to unset.
         """
         return _ogr.Feature_UnsetField(self, *args)
 
     def SetFieldInteger64(self, *args):
-        """SetFieldInteger64(self, int id, GIntBig value)"""
+        """
+        SetFieldInteger64(Feature self, int id, GIntBig value)
+
+        void
+        OGR_F_SetFieldInteger64(OGRFeatureH hFeat, int iField, GIntBig nValue)
+
+        Set field to 64 bit integer value.
+
+        OFTInteger, OFTInteger64 and OFTReal fields will be set directly.
+        OFTString fields will be assigned a string representation of the
+        value, but not necessarily taking into account formatting constraints
+        on this field. Other field types may be unaffected.
+
+        This function is the same as the C++ method OGRFeature::SetField().
+
+        Parameters:
+        -----------
+
+        hFeat:  handle to the feature that owned the field.
+
+        iField:  the field to fetch, from 0 to GetFieldCount()-1.
+
+        nValue:  the value to assign.
+
+        GDAL 2.0
+        """
         return _ogr.Feature_SetFieldInteger64(self, *args)
 
     def SetField(self, *args):
         """
-        SetField(self, int id, char value)
-        SetField(self, char name, char value)
-        SetField(self, int id, double value)
-        SetField(self, char name, double value)
-        SetField(self, int id, int year, int month, int day, int hour, int minute, 
-            float second, int tzflag)
-        SetField(self, char name, int year, int month, int day, int hour, 
-            int minute, float second, int tzflag)
+        SetField(Feature self, int id, char const * value)
+        SetField(Feature self, char const * name, char const * value)
+        SetField(Feature self, int id, double value)
+        SetField(Feature self, char const * name, double value)
+        SetField(Feature self, int id, int year, int month, int day, int hour, int minute, float second, int tzflag)
+        SetField(Feature self, char const * name, int year, int month, int day, int hour, int minute, float second,
+            int tzflag)
         """
         return _ogr.Feature_SetField(self, *args)
 
     def SetFieldIntegerList(self, *args):
         """
-        SetFieldIntegerList(self, int id, int nList)
+        SetFieldIntegerList(Feature self, int id, int nList)
 
         void
         OGR_F_SetFieldIntegerList(OGRFeatureH hFeat, int iField, int nCount,
@@ -2945,7 +3679,8 @@ class Feature(_object):
 
         Set field to list of integers value.
 
-        This function currently on has an effect of OFTIntegerList fields.
+        This function currently on has an effect of OFTIntegerList,
+        OFTInteger64List and OFTRealList fields.
 
         This function is the same as the C++ method OGRFeature::SetField().
 
@@ -2958,17 +3693,43 @@ class Feature(_object):
 
         nCount:  the number of values in the list being assigned.
 
-        panValues:  the values to assign. 
+        panValues:  the values to assign.
         """
         return _ogr.Feature_SetFieldIntegerList(self, *args)
 
     def SetFieldInteger64List(self, *args):
-        """SetFieldInteger64List(self, int id, int nList)"""
+        """
+        SetFieldInteger64List(Feature self, int id, int nList)
+
+        void
+        OGR_F_SetFieldInteger64List(OGRFeatureH hFeat, int iField, int nCount,
+        const GIntBig *panValues)
+
+        Set field to list of 64 bit integers value.
+
+        This function currently on has an effect of OFTIntegerList,
+        OFTInteger64List and OFTRealList fields.
+
+        This function is the same as the C++ method OGRFeature::SetField().
+
+        Parameters:
+        -----------
+
+        hFeat:  handle to the feature that owned the field.
+
+        iField:  the field to set, from 0 to GetFieldCount()-1.
+
+        nCount:  the number of values in the list being assigned.
+
+        panValues:  the values to assign.
+
+        GDAL 2.0
+        """
         return _ogr.Feature_SetFieldInteger64List(self, *args)
 
     def SetFieldDoubleList(self, *args):
         """
-        SetFieldDoubleList(self, int id, int nList)
+        SetFieldDoubleList(Feature self, int id, int nList)
 
         void
         OGR_F_SetFieldDoubleList(OGRFeatureH hFeat, int iField, int nCount,
@@ -2976,7 +3737,8 @@ class Feature(_object):
 
         Set field to list of doubles value.
 
-        This function currently on has an effect of OFTRealList fields.
+        This function currently on has an effect of OFTIntegerList,
+        OFTInteger64List, OFTRealList fields.
 
         This function is the same as the C++ method OGRFeature::SetField().
 
@@ -2989,13 +3751,13 @@ class Feature(_object):
 
         nCount:  the number of values in the list being assigned.
 
-        padfValues:  the values to assign. 
+        padfValues:  the values to assign.
         """
         return _ogr.Feature_SetFieldDoubleList(self, *args)
 
     def SetFieldStringList(self, *args):
         """
-        SetFieldStringList(self, int id, char pList)
+        SetFieldStringList(Feature self, int id, char ** pList)
 
         void
         OGR_F_SetFieldStringList(OGRFeatureH hFeat, int iField, char
@@ -3014,20 +3776,20 @@ class Feature(_object):
 
         iField:  the field to set, from 0 to GetFieldCount()-1.
 
-        papszValues:  the values to assign. 
+        papszValues:  the values to assign.
         """
         return _ogr.Feature_SetFieldStringList(self, *args)
 
     def SetFieldBinaryFromHexString(self, *args):
         """
-        SetFieldBinaryFromHexString(self, int id, char pszValue)
-        SetFieldBinaryFromHexString(self, char name, char pszValue)
+        SetFieldBinaryFromHexString(Feature self, int id, char const * pszValue)
+        SetFieldBinaryFromHexString(Feature self, char const * name, char const * pszValue)
         """
         return _ogr.Feature_SetFieldBinaryFromHexString(self, *args)
 
     def SetFrom(self, *args, **kwargs):
         """
-        SetFrom(self, Feature other, int forgiving = 1) -> OGRErr
+        SetFrom(Feature self, Feature other, int forgiving=1) -> OGRErr
 
         OGRErr OGR_F_SetFrom(OGRFeatureH
         hFeat, OGRFeatureH hOtherFeat, int bForgiving)
@@ -3054,13 +3816,13 @@ class Feature(_object):
         output fields matching some of the source fields.
 
         OGRERR_NONE if the operation succeeds, even if some values are not
-        transferred, otherwise an error code. 
+        transferred, otherwise an error code.
         """
         return _ogr.Feature_SetFrom(self, *args, **kwargs)
 
     def SetFromWithMap(self, *args):
         """
-        SetFromWithMap(self, Feature other, int forgiving, int nList) -> OGRErr
+        SetFromWithMap(Feature self, Feature other, int forgiving, int nList) -> OGRErr
 
         OGRErr
         OGR_F_SetFromWithMap(OGRFeatureH hFeat, OGRFeatureH hOtherFeat, int
@@ -3097,13 +3859,13 @@ class Feature(_object):
         output fields matching some of the source fields.
 
         OGRERR_NONE if the operation succeeds, even if some values are not
-        transferred, otherwise an error code. 
+        transferred, otherwise an error code.
         """
         return _ogr.Feature_SetFromWithMap(self, *args)
 
     def GetStyleString(self, *args):
         """
-        GetStyleString(self) -> char
+        GetStyleString(Feature self) -> char const *
 
         const char*
         OGR_F_GetStyleString(OGRFeatureH hFeat)
@@ -3123,20 +3885,22 @@ class Feature(_object):
         hFeat:  handle to the feature to get the style from.
 
         a reference to a representation in string format, or NULL if there
-        isn't one. 
+        isn't one.
         """
         return _ogr.Feature_GetStyleString(self, *args)
 
     def SetStyleString(self, *args):
         """
-        SetStyleString(self, char the_string)
+        SetStyleString(Feature self, char const * the_string)
 
         void
         OGR_F_SetStyleString(OGRFeatureH hFeat, const char *pszStyle)
 
-        Set feature style string. This method operate exactly as
-        OGR_F_SetStyleStringDirectly() except that it does not assume
-        ownership of the passed string, but instead makes a copy of it.
+        Set feature style string.
+
+        This method operate exactly as OGR_F_SetStyleStringDirectly() except
+        that it does not assume ownership of the passed string, but instead
+        makes a copy of it.
 
         This function is the same as the C++ method
         OGRFeature::SetStyleString().
@@ -3153,22 +3917,218 @@ class Feature(_object):
 
     def GetFieldType(self, *args):
         """
-        GetFieldType(self, int id) -> OGRFieldType
-        GetFieldType(self, char name) -> OGRFieldType
+        GetFieldType(Feature self, int id) -> OGRFieldType
+        GetFieldType(Feature self, char const * name) -> OGRFieldType
         """
         return _ogr.Feature_GetFieldType(self, *args)
 
     def Validate(self, *args):
-        """Validate(self, int flags = OGR_F_VAL_ALL, int bEmitError = TRUE) -> int"""
+        """
+        Validate(Feature self, int flags=OGR_F_VAL_ALL, int bEmitError=True) -> int
+
+        int OGR_F_Validate(OGRFeatureH
+        hFeat, int nValidateFlags, int bEmitError)
+
+        Validate that a feature meets constraints of its schema.
+
+        The scope of test is specified with the nValidateFlags parameter.
+
+        Regarding OGR_F_VAL_WIDTH, the test is done assuming the string width
+        must be interpreted as the number of UTF-8 characters. Some drivers
+        might interpret the width as the number of bytes instead. So this test
+        is rather conservative (if it fails, then it will fail for all
+        interpretations).
+
+        This function is the same as the C++ method OGRFeature::Validate().
+
+        Parameters:
+        -----------
+
+        hFeat:  handle to the feature to validate.
+
+        nValidateFlags:  OGR_F_VAL_ALL or combination of OGR_F_VAL_NULL,
+        OGR_F_VAL_GEOM_TYPE, OGR_F_VAL_WIDTH and
+        OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT with '|' operator
+
+        bEmitError:  TRUE if a CPLError() must be emitted when a check fails
+
+        TRUE if all enabled validation tests pass.
+
+        GDAL 2.0
+        """
         return _ogr.Feature_Validate(self, *args)
 
     def FillUnsetWithDefault(self, *args):
-        """FillUnsetWithDefault(self, int bNotNullableOnly = True, char options = None)"""
+        """
+        FillUnsetWithDefault(Feature self, int bNotNullableOnly=False, char ** options=None)
+
+        void
+        OGR_F_FillUnsetWithDefault(OGRFeatureH hFeat, int bNotNullableOnly,
+        char **papszOptions)
+
+        Fill unset fields with default values that might be defined.
+
+        This function is the same as the C++ method
+        OGRFeature::FillUnsetWithDefault().
+
+        Parameters:
+        -----------
+
+        hFeat:  handle to the feature.
+
+        bNotNullableOnly:  if we should fill only unset fields with a not-null
+        constraint.
+
+        papszOptions:  unused currently. Must be set to NULL.
+
+        GDAL 2.0
+        """
         return _ogr.Feature_FillUnsetWithDefault(self, *args)
 
+    def GetNativeData(self, *args):
+        """
+        GetNativeData(Feature self) -> char const *
+
+        const char*
+        OGR_F_GetNativeData(OGRFeatureH hFeat)
+
+        Returns the native data for the feature.
+
+        The native data is the representation in a "natural" form that comes
+        from the driver that created this feature, or that is aimed at an
+        output driver. The native data may be in different format, which is
+        indicated by OGR_F_GetNativeMediaType().
+
+        Note that most drivers do not support storing the native data in the
+        feature object, and if they do, generally the NATIVE_DATA open option
+        must be passed at dataset opening.
+
+        The "native data" does not imply it is something more performant or
+        powerful than what can be obtained with the rest of the API, but it
+        may be useful in round-tripping scenarios where some characteristics
+        of the underlying format are not captured otherwise by the OGR
+        abstraction.
+
+        This function is the same as the C++ method
+        OGRFeature::GetNativeData().
+
+        Parameters:
+        -----------
+
+        hFeat:  handle to the feature.
+
+        a string with the native data, or NULL if there is none.
+
+        GDAL 2.1
+
+        See:
+        https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
+
+        """
+        return _ogr.Feature_GetNativeData(self, *args)
+
+    def GetNativeMediaType(self, *args):
+        """
+        GetNativeMediaType(Feature self) -> char const *
+
+        const char*
+        OGR_F_GetNativeMediaType(OGRFeatureH hFeat)
+
+        Returns the native media type for the feature.
+
+        The native media type is the identifier for the format of the native
+        data. It follows the IANA RFC 2045
+        (seehttps://en.wikipedia.org/wiki/Media_type), e.g.
+        "application/vnd.geo+json" for JSon.
+
+        This function is the same as the C function
+        OGR_F_GetNativeMediaType().
+
+        Parameters:
+        -----------
+
+        hFeat:  handle to the feature.
+
+        a string with the native media type, or NULL if there is none.
+
+        GDAL 2.1
+
+        See:
+        https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
+
+        """
+        return _ogr.Feature_GetNativeMediaType(self, *args)
+
+    def SetNativeData(self, *args):
+        """
+        SetNativeData(Feature self, char const * nativeData)
+
+        void
+        OGR_F_SetNativeData(OGRFeatureH hFeat, const char *pszNativeData)
+
+        Sets the native data for the feature.
+
+        The native data is the representation in a "natural" form that comes
+        from the driver that created this feature, or that is aimed at an
+        output driver. The native data may be in different format, which is
+        indicated by OGR_F_GetNativeMediaType().
+
+        This function is the same as the C++ method
+        OGRFeature::SetNativeData().
+
+        Parameters:
+        -----------
+
+        hFeat:  handle to the feature.
+
+        pszNativeData:  a string with the native data, or NULL if there is
+        none.
+
+        GDAL 2.1
+
+        See:
+        https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
+
+        """
+        return _ogr.Feature_SetNativeData(self, *args)
+
+    def SetNativeMediaType(self, *args):
+        """
+        SetNativeMediaType(Feature self, char const * nativeMediaType)
+
+        void
+        OGR_F_SetNativeMediaType(OGRFeatureH hFeat, const char
+        *pszNativeMediaType)
+
+        Sets the native media type for the feature.
+
+        The native media type is the identifier for the format of the native
+        data. It follows the IANA RFC 2045
+        (seehttps://en.wikipedia.org/wiki/Media_type), e.g.
+        "application/vnd.geo+json" for JSon.
+
+        This function is the same as the C++ method
+        OGRFeature::SetNativeMediaType().
+
+        Parameters:
+        -----------
+
+        hFeat:  handle to the feature.
+
+        pszNativeMediaType:  a string with the native media type, or NULL if
+        there is none.
+
+        GDAL 2.1
+
+        See:
+        https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
+
+        """
+        return _ogr.Feature_SetNativeMediaType(self, *args)
+
     def SetFieldString(self, *args):
         """
-        SetFieldString(self, int id, char value)
+        SetFieldString(Feature self, int id, char const * value)
 
         void
         OGR_F_SetFieldString(OGRFeatureH hFeat, int iField, const char
@@ -3177,8 +4137,10 @@ class Feature(_object):
         Set field to string value.
 
         OFTInteger fields will be set based on an atoi() conversion of the
-        string. OFTReal fields will be set based on an atof() conversion of
-        the string. Other field types may be unaffected.
+        string. OFTInteger64 fields will be set based on an CPLAtoGIntBig()
+        conversion of the string. OFTReal fields will be set based on an
+        CPLAtof() conversion of the string. Other field types may be
+        unaffected.
 
         This function is the same as the C++ method OGRFeature::SetField().
 
@@ -3189,7 +4151,7 @@ class Feature(_object):
 
         iField:  the field to fetch, from 0 to GetFieldCount()-1.
 
-        pszValue:  the value to assign. 
+        pszValue:  the value to assign.
         """
         return _ogr.Feature_SetFieldString(self, *args)
 
@@ -3200,7 +4162,7 @@ class Feature(_object):
       pass
 
     def Destroy(self):
-      "Once called, self has effectively been destroyed.  Do not access. For backwards compatiblity only"
+      "Once called, self has effectively been destroyed.  Do not access. For backwards compatibility only"
       _ogr.delete_Feature( self )
       self.thisown = 0
 
@@ -3211,7 +4173,7 @@ class Feature(_object):
     def __copy__(self):
         return self.Clone()
 
-    # This makes it possible to fetch fields in the form "feature.area". 
+    # This makes it possible to fetch fields in the form "feature.area".
     # This has some risk of name collisions.
     def __getattr__(self, key):
         """Returns the values of fields by the given name"""
@@ -3228,7 +4190,7 @@ class Feature(_object):
         else:
             return self.GetField(idx)
 
-    # This makes it possible to set fields in the form "feature.area". 
+    # This makes it possible to set fields in the form "feature.area".
     # This has some risk of name collisions.
     def __setattr__(self, key, value):
         """Set the values of fields by the given name"""
@@ -3245,7 +4207,7 @@ class Feature(_object):
                 else:
                     self.__dict__[key] = value
 
-    # This makes it possible to fetch fields in the form "feature['area']". 
+    # This makes it possible to fetch fields in the form "feature['area']".
     def __getitem__(self, key):
         """Returns the values of fields by the given name / field_index"""
         if isinstance(key, str):
@@ -3260,7 +4222,7 @@ class Feature(_object):
         else:
             return self.GetField(fld_index)
 
-    # This makes it possible to set fields in the form "feature['area'] = 123". 
+    # This makes it possible to set fields in the form "feature['area'] = 123".
     def __setitem__(self, key, value):
         """Returns the value of a field by field name / index"""
         if isinstance(key, str):
@@ -3316,9 +4278,9 @@ class Feature(_object):
         SetField(self, char name, int value)
         SetField(self, int id, double value)
         SetField(self, char name, double value)
-        SetField(self, int id, int year, int month, int day, int hour, int minute, 
+        SetField(self, int id, int year, int month, int day, int hour, int minute,
             int second, int tzflag)
-        SetField(self, char name, int year, int month, int day, int hour, 
+        SetField(self, char name, int year, int month, int day, int hour,
             int minute, int second, int tzflag)
         """
 
@@ -3387,7 +4349,7 @@ class Feature(_object):
 
     def ExportToJson(self, as_object = False, options = None):
         """Exports a GeoJSON object which represents the Feature. The
-           as_object parameter determines whether the returned value 
+           as_object parameter determines whether the returned value
            should be a Python object instead of a string. Defaults to False.
            The options parameter is passed to Geometry.ExportToJson()"""
 
@@ -3411,15 +4373,22 @@ class Feature(_object):
         output = {'type':'Feature',
                    'geometry': geom_json_object,
                    'properties': {}
-                  } 
-        
+                  }
+
         fid = self.GetFID()
         if fid != NullFID:
             output['id'] = fid
-            
+
         for key in self.keys():
-            output['properties'][key] = self.GetField(key)
-        
+            fld_defn = self.GetFieldDefnRef(self.GetFieldIndex(key))
+            if fld_defn.GetType() == _ogr.OFTInteger and fld_defn.GetSubType() == _ogr.OFSTBoolean:
+                if self.GetField(key):
+                    output['properties'][key] = True
+                else:
+                    output['properties'][key] = False
+            else:
+                output['properties'][key] = self.GetField(key)
+
         if not as_object:
             output = simplejson.dumps(output)
 
@@ -3439,14 +4408,14 @@ class FeatureDefn(_object):
     __repr__ = _swig_repr
     __swig_destroy__ = _ogr.delete_FeatureDefn
     __del__ = lambda self : None;
-    def __init__(self, *args, **kwargs): 
-        """__init__(self, char name_null_ok = None) -> FeatureDefn"""
+    def __init__(self, *args, **kwargs):
+        """__init__(OGRFeatureDefnShadow self, char const * name_null_ok=None) -> FeatureDefn"""
         this = _ogr.new_FeatureDefn(*args, **kwargs)
         try: self.this.append(this)
         except: self.this = this
     def GetName(self, *args):
         """
-        GetName(self) -> char
+        GetName(FeatureDefn self) -> char const *
 
         const char*
         OGR_FD_GetName(OGRFeatureDefnH hDefn)
@@ -3467,7 +4436,7 @@ class FeatureDefn(_object):
 
     def GetFieldCount(self, *args):
         """
-        GetFieldCount(self) -> int
+        GetFieldCount(FeatureDefn self) -> int
 
         int
         OGR_FD_GetFieldCount(OGRFeatureDefnH hDefn)
@@ -3481,13 +4450,13 @@ class FeatureDefn(_object):
 
         hDefn:  handle to the feature definition to get the fields count from.
 
-        count of fields. 
+        count of fields.
         """
         return _ogr.FeatureDefn_GetFieldCount(self, *args)
 
     def GetFieldDefn(self, *args):
         """
-        GetFieldDefn(self, int i) -> FieldDefn
+        GetFieldDefn(FeatureDefn self, int i) -> FieldDefn
 
         OGRFieldDefnH
         OGR_FD_GetFieldDefn(OGRFeatureDefnH hDefn, int iField)
@@ -3516,7 +4485,7 @@ class FeatureDefn(_object):
 
     def GetFieldIndex(self, *args):
         """
-        GetFieldIndex(self, char name) -> int
+        GetFieldIndex(FeatureDefn self, char const * name) -> int
 
         int
         OGR_FD_GetFieldIndex(OGRFeatureDefnH hDefn, const char *pszFieldName)
@@ -3536,13 +4505,13 @@ class FeatureDefn(_object):
 
         pszFieldName:  the field name to search for.
 
-        the field index, or -1 if no match found. 
+        the field index, or -1 if no match found.
         """
         return _ogr.FeatureDefn_GetFieldIndex(self, *args)
 
     def AddFieldDefn(self, *args):
         """
-        AddFieldDefn(self, FieldDefn defn)
+        AddFieldDefn(FeatureDefn self, FieldDefn defn)
 
         void
         OGR_FD_AddFieldDefn(OGRFeatureDefnH hDefn, OGRFieldDefnH hNewField)
@@ -3553,7 +4522,7 @@ class FeatureDefn(_object):
         function directly, but use OGR_L_CreateField() instead.
 
         This function should only be called while there are no OGRFeature
-        objects in existance based on this OGRFeatureDefn. The OGRFieldDefn
+        objects in existence based on this OGRFeatureDefn. The OGRFieldDefn
         passed in is copied, and remains the responsibility of the caller.
 
         This function is the same as the C++ method
@@ -3565,33 +4534,156 @@ class FeatureDefn(_object):
         hDefn:  handle to the feature definition to add the field definition
         to.
 
-        hNewField:  handle to the new field definition. 
+        hNewField:  handle to the new field definition.
         """
         return _ogr.FeatureDefn_AddFieldDefn(self, *args)
 
     def GetGeomFieldCount(self, *args):
-        """GetGeomFieldCount(self) -> int"""
+        """
+        GetGeomFieldCount(FeatureDefn self) -> int
+
+        int
+        OGR_FD_GetGeomFieldCount(OGRFeatureDefnH hDefn)
+
+        Fetch number of geometry fields on the passed feature definition.
+
+        This function is the same as the C++
+        OGRFeatureDefn::GetGeomFieldCount().
+
+        Parameters:
+        -----------
+
+        hDefn:  handle to the feature definition to get the fields count from.
+
+        count of geometry fields.
+
+        GDAL 1.11
+        """
         return _ogr.FeatureDefn_GetGeomFieldCount(self, *args)
 
     def GetGeomFieldDefn(self, *args):
-        """GetGeomFieldDefn(self, int i) -> GeomFieldDefn"""
+        """
+        GetGeomFieldDefn(FeatureDefn self, int i) -> GeomFieldDefn
+
+        OGRGeomFieldDefnH
+        OGR_FD_GetGeomFieldDefn(OGRFeatureDefnH hDefn, int iGeomField)
+
+        Fetch geometry field definition of the passed feature definition.
+
+        This function is the same as the C++ method
+        OGRFeatureDefn::GetGeomFieldDefn().
+
+        Parameters:
+        -----------
+
+        hDefn:  handle to the feature definition to get the field definition
+        from.
+
+        iGeomField:  the geometry field to fetch, between 0 and
+        GetGeomFieldCount()-1.
+
+        an handle to an internal field definition object or NULL if invalid
+        index. This object should not be modified or freed by the application.
+
+        GDAL 1.11
+        """
         return _ogr.FeatureDefn_GetGeomFieldDefn(self, *args)
 
     def GetGeomFieldIndex(self, *args):
-        """GetGeomFieldIndex(self, char name) -> int"""
+        """
+        GetGeomFieldIndex(FeatureDefn self, char const * name) -> int
+
+        int
+        OGR_FD_GetGeomFieldIndex(OGRFeatureDefnH hDefn, const char
+        *pszGeomFieldName)
+
+        Find geometry field by name.
+
+        The geometry field index of the first geometry field matching the
+        passed field name (case insensitively) is returned.
+
+        This function is the same as the C++ method
+        OGRFeatureDefn::GetGeomFieldIndex.
+
+        Parameters:
+        -----------
+
+        hDefn:  handle to the feature definition to get field index from.
+
+        pszGeomFieldName:  the geometry field name to search for.
+
+        the geometry field index, or -1 if no match found.
+        """
         return _ogr.FeatureDefn_GetGeomFieldIndex(self, *args)
 
     def AddGeomFieldDefn(self, *args):
-        """AddGeomFieldDefn(self, GeomFieldDefn defn)"""
+        """
+        AddGeomFieldDefn(FeatureDefn self, GeomFieldDefn defn)
+
+        void
+        OGR_FD_AddGeomFieldDefn(OGRFeatureDefnH hDefn, OGRGeomFieldDefnH
+        hNewGeomField)
+
+        Add a new field definition to the passed feature definition.
+
+        To add a new field definition to a layer definition, do not use this
+        function directly, but use OGR_L_CreateGeomField() instead.
+
+        This function should only be called while there are no OGRFeature
+        objects in existence based on this OGRFeatureDefn. The
+        OGRGeomFieldDefn passed in is copied, and remains the responsibility
+        of the caller.
+
+        This function is the same as the C++ method
+        OGRFeatureDefn::AddGeomFieldDefn().
+
+        Parameters:
+        -----------
+
+        hDefn:  handle to the feature definition to add the geometry field
+        definition to.
+
+        hNewGeomField:  handle to the new field definition.
+
+        GDAL 1.11
+        """
         return _ogr.FeatureDefn_AddGeomFieldDefn(self, *args)
 
     def DeleteGeomFieldDefn(self, *args):
-        """DeleteGeomFieldDefn(self, int idx) -> OGRErr"""
+        """
+        DeleteGeomFieldDefn(FeatureDefn self, int idx) -> OGRErr
+
+        OGRErr
+        OGR_FD_DeleteGeomFieldDefn(OGRFeatureDefnH hDefn, int iGeomField)
+
+        Delete an existing geometry field definition.
+
+        To delete an existing geometry field definition from a layer
+        definition, do not use this function directly, but use
+        OGR_L_DeleteGeomField() instead (*not implemented yet*).
+
+        This method should only be called while there are no OGRFeature
+        objects in existence based on this OGRFeatureDefn.
+
+        This method is the same as the C++ method
+        OGRFeatureDefn::DeleteGeomFieldDefn().
+
+        Parameters:
+        -----------
+
+        hDefn:  handle to the feature definition.
+
+        iGeomField:  the index of the geometry field definition.
+
+        OGRERR_NONE in case of success.
+
+        GDAL 1.11
+        """
         return _ogr.FeatureDefn_DeleteGeomFieldDefn(self, *args)
 
     def GetGeomType(self, *args):
         """
-        GetGeomType(self) -> OGRwkbGeometryType
+        GetGeomType(FeatureDefn self) -> OGRwkbGeometryType
 
         OGRwkbGeometryType
         OGR_FD_GetGeomType(OGRFeatureDefnH hDefn)
@@ -3601,19 +4693,22 @@ class FeatureDefn(_object):
         This function is the same as the C++ method
         OGRFeatureDefn::GetGeomType().
 
+        Starting with GDAL 1.11, this method returns
+        GetGeomFieldDefn(0)->GetType().
+
         Parameters:
         -----------
 
         hDefn:  handle to the feature definition to get the geometry type
         from.
 
-        the base type for all geometry related to this definition. 
+        the base type for all geometry related to this definition.
         """
         return _ogr.FeatureDefn_GetGeomType(self, *args)
 
     def SetGeomType(self, *args):
         """
-        SetGeomType(self, OGRwkbGeometryType geom_type)
+        SetGeomType(FeatureDefn self, OGRwkbGeometryType geom_type)
 
         void
         OGR_FD_SetGeomType(OGRFeatureDefnH hDefn, OGRwkbGeometryType eType)
@@ -3629,19 +4724,22 @@ class FeatureDefn(_object):
         This function is the same as the C++ method
         OGRFeatureDefn::SetGeomType().
 
+        Starting with GDAL 1.11, this method calls
+        GetGeomFieldDefn(0)->SetType().
+
         Parameters:
         -----------
 
         hDefn:  handle to the layer or feature definition to set the geometry
         type to.
 
-        eType:  the new type to assign. 
+        eType:  the new type to assign.
         """
         return _ogr.FeatureDefn_SetGeomType(self, *args)
 
     def GetReferenceCount(self, *args):
         """
-        GetReferenceCount(self) -> int
+        GetReferenceCount(FeatureDefn self) -> int
 
         int
         OGR_FD_GetReferenceCount(OGRFeatureDefnH hDefn)
@@ -3654,16 +4752,16 @@ class FeatureDefn(_object):
         Parameters:
         -----------
 
-        hDefn:  hanlde to the feature definition on witch OGRFeature are based
+        hDefn:  handle to the feature definition on witch OGRFeature are based
         on.
 
-        the current reference count. 
+        the current reference count.
         """
         return _ogr.FeatureDefn_GetReferenceCount(self, *args)
 
     def IsGeometryIgnored(self, *args):
         """
-        IsGeometryIgnored(self) -> int
+        IsGeometryIgnored(FeatureDefn self) -> int
 
         int
         OGR_FD_IsGeometryIgnored(OGRFeatureDefnH hDefn)
@@ -3673,19 +4771,22 @@ class FeatureDefn(_object):
         This function is the same as the C++ method
         OGRFeatureDefn::IsGeometryIgnored().
 
+        Starting with GDAL 1.11, this method returns
+        GetGeomFieldDefn(0)->IsIgnored().
+
         Parameters:
         -----------
 
-        hDefn:  hanlde to the feature definition on witch OGRFeature are based
+        hDefn:  handle to the feature definition on witch OGRFeature are based
         on.
 
-        ignore state 
+        ignore state
         """
         return _ogr.FeatureDefn_IsGeometryIgnored(self, *args)
 
     def SetGeometryIgnored(self, *args):
         """
-        SetGeometryIgnored(self, int bIgnored)
+        SetGeometryIgnored(FeatureDefn self, int bIgnored)
 
         void
         OGR_FD_SetGeometryIgnored(OGRFeatureDefnH hDefn, int bIgnore)
@@ -3695,19 +4796,22 @@ class FeatureDefn(_object):
         This function is the same as the C++ method
         OGRFeatureDefn::SetGeometryIgnored().
 
+        Starting with GDAL 1.11, this method calls
+        GetGeomFieldDefn(0)->SetIgnored().
+
         Parameters:
         -----------
 
-        hDefn:  hanlde to the feature definition on witch OGRFeature are based
+        hDefn:  handle to the feature definition on witch OGRFeature are based
         on.
 
-        bIgnore:  ignore state 
+        bIgnore:  ignore state
         """
         return _ogr.FeatureDefn_SetGeometryIgnored(self, *args)
 
     def IsStyleIgnored(self, *args):
         """
-        IsStyleIgnored(self) -> int
+        IsStyleIgnored(FeatureDefn self) -> int
 
         int
         OGR_FD_IsStyleIgnored(OGRFeatureDefnH hDefn)
@@ -3723,13 +4827,13 @@ class FeatureDefn(_object):
         hDefn:  handle to the feature definition on which OGRFeature are based
         on.
 
-        ignore state 
+        ignore state
         """
         return _ogr.FeatureDefn_IsStyleIgnored(self, *args)
 
     def SetStyleIgnored(self, *args):
         """
-        SetStyleIgnored(self, int bIgnored)
+        SetStyleIgnored(FeatureDefn self, int bIgnored)
 
         void
         OGR_FD_SetStyleIgnored(OGRFeatureDefnH hDefn, int bIgnore)
@@ -3742,19 +4846,38 @@ class FeatureDefn(_object):
         Parameters:
         -----------
 
-        hDefn:  hanlde to the feature definition on witch OGRFeature are based
+        hDefn:  handle to the feature definition on witch OGRFeature are based
         on.
 
-        bIgnore:  ignore state 
+        bIgnore:  ignore state
         """
         return _ogr.FeatureDefn_SetStyleIgnored(self, *args)
 
     def IsSame(self, *args):
-        """IsSame(self, FeatureDefn other_defn) -> int"""
+        """
+        IsSame(FeatureDefn self, FeatureDefn other_defn) -> int
+
+        int OGR_FD_IsSame(OGRFeatureDefnH
+        hFDefn, OGRFeatureDefnH hOtherFDefn)
+
+        Test if the feature definition is identical to the other one.
+
+        Parameters:
+        -----------
+
+        hFDefn:  handle to the feature definition on witch OGRFeature are
+        based on.
+
+        hOtherFDefn:  handle to the other feature definition to compare to.
+
+        TRUE if the feature definition is identical to the other one.
+
+        OGR 1.11
+        """
         return _ogr.FeatureDefn_IsSame(self, *args)
 
     def Destroy(self):
-      "Once called, self has effectively been destroyed.  Do not access. For backwards compatiblity only"
+      "Once called, self has effectively been destroyed.  Do not access. For backwards compatibility only"
       _ogr.delete_FeatureDefn( self )
       self.thisown = 0
 
@@ -3771,18 +4894,18 @@ class FieldDefn(_object):
     __repr__ = _swig_repr
     __swig_destroy__ = _ogr.delete_FieldDefn
     __del__ = lambda self : None;
-    def __init__(self, *args, **kwargs): 
-        """__init__(self, char name_null_ok = "unnamed", OGRFieldType field_type = OFTString) -> FieldDefn"""
+    def __init__(self, *args, **kwargs):
+        """__init__(OGRFieldDefnShadow self, char const * name_null_ok="unnamed", OGRFieldType field_type=OFTString) -> FieldDefn"""
         this = _ogr.new_FieldDefn(*args, **kwargs)
         try: self.this.append(this)
         except: self.this = this
     def GetName(self, *args):
-        """GetName(self) -> char"""
+        """GetName(FieldDefn self) -> char const *"""
         return _ogr.FieldDefn_GetName(self, *args)
 
     def GetNameRef(self, *args):
         """
-        GetNameRef(self) -> char
+        GetNameRef(FieldDefn self) -> char const *
 
         const char*
         OGR_Fld_GetNameRef(OGRFieldDefnH hDefn)
@@ -3797,13 +4920,13 @@ class FieldDefn(_object):
 
         hDefn:  handle to the field definition.
 
-        the name of the field definition. 
+        the name of the field definition.
         """
         return _ogr.FieldDefn_GetNameRef(self, *args)
 
     def SetName(self, *args):
         """
-        SetName(self, char name)
+        SetName(FieldDefn self, char const * name)
 
         void OGR_Fld_SetName(OGRFieldDefnH
         hDefn, const char *pszName)
@@ -3817,13 +4940,13 @@ class FieldDefn(_object):
 
         hDefn:  handle to the field definition to apply the new name to.
 
-        pszName:  the new name to apply. 
+        pszName:  the new name to apply.
         """
         return _ogr.FieldDefn_SetName(self, *args)
 
     def GetType(self, *args):
         """
-        GetType(self) -> OGRFieldType
+        GetType(FieldDefn self) -> OGRFieldType
 
         OGRFieldType
         OGR_Fld_GetType(OGRFieldDefnH hDefn)
@@ -3837,19 +4960,21 @@ class FieldDefn(_object):
 
         hDefn:  handle to the field definition to get type from.
 
-        field type. 
+        field type.
         """
         return _ogr.FieldDefn_GetType(self, *args)
 
     def SetType(self, *args):
         """
-        SetType(self, OGRFieldType type)
+        SetType(FieldDefn self, OGRFieldType type)
 
         void OGR_Fld_SetType(OGRFieldDefnH
         hDefn, OGRFieldType eType)
 
-        Set the type of this field. This should never be done to an
-        OGRFieldDefn that is already part of an OGRFeatureDefn.
+        Set the type of this field.
+
+        This should never be done to an OGRFieldDefn that is already part of
+        an OGRFeatureDefn.
 
         This function is the same as the CPP method OGRFieldDefn::SetType().
 
@@ -3858,21 +4983,62 @@ class FieldDefn(_object):
 
         hDefn:  handle to the field definition to set type to.
 
-        eType:  the new field type. 
-        """
-        return _ogr.FieldDefn_SetType(self, *args)
-
-    def GetSubType(self, *args):
-        """GetSubType(self) -> OGRFieldSubType"""
-        return _ogr.FieldDefn_GetSubType(self, *args)
+        eType:  the new field type.
+        """
+        return _ogr.FieldDefn_SetType(self, *args)
+
+    def GetSubType(self, *args):
+        """
+        GetSubType(FieldDefn self) -> OGRFieldSubType
+
+        OGRFieldSubType
+        OGR_Fld_GetSubType(OGRFieldDefnH hDefn)
+
+        Fetch subtype of this field.
+
+        This function is the same as the CPP method
+        OGRFieldDefn::GetSubType().
+
+        Parameters:
+        -----------
+
+        hDefn:  handle to the field definition to get subtype from.
+
+        field subtype.
+
+        GDAL 2.0
+        """
+        return _ogr.FieldDefn_GetSubType(self, *args)
+
+    def SetSubType(self, *args):
+        """
+        SetSubType(FieldDefn self, OGRFieldSubType type)
+
+        void
+        OGR_Fld_SetSubType(OGRFieldDefnH hDefn, OGRFieldSubType eSubType)
+
+        Set the subtype of this field.
+
+        This should never be done to an OGRFieldDefn that is already part of
+        an OGRFeatureDefn.
+
+        This function is the same as the CPP method
+        OGRFieldDefn::SetSubType().
+
+        Parameters:
+        -----------
+
+        hDefn:  handle to the field definition to set type to.
+
+        eSubType:  the new field subtype.
 
-    def SetSubType(self, *args):
-        """SetSubType(self, OGRFieldSubType type)"""
+        GDAL 2.0
+        """
         return _ogr.FieldDefn_SetSubType(self, *args)
 
     def GetJustify(self, *args):
         """
-        GetJustify(self) -> OGRJustification
+        GetJustify(FieldDefn self) -> OGRJustification
 
         OGRJustification
         OGR_Fld_GetJustify(OGRFieldDefnH hDefn)
@@ -3882,24 +5048,28 @@ class FieldDefn(_object):
         This function is the same as the CPP method
         OGRFieldDefn::GetJustify().
 
+        Note: no driver is know to use the concept of field justification.
+
         Parameters:
         -----------
 
         hDefn:  handle to the field definition to get justification from.
 
-        the justification. 
+        the justification.
         """
         return _ogr.FieldDefn_GetJustify(self, *args)
 
     def SetJustify(self, *args):
         """
-        SetJustify(self, OGRJustification justify)
+        SetJustify(FieldDefn self, OGRJustification justify)
 
         void
         OGR_Fld_SetJustify(OGRFieldDefnH hDefn, OGRJustification eJustify)
 
         Set the justification for this field.
 
+        Note: no driver is know to use the concept of field justification.
+
         This function is the same as the CPP method
         OGRFieldDefn::SetJustify().
 
@@ -3908,13 +5078,13 @@ class FieldDefn(_object):
 
         hDefn:  handle to the field definition to set justification to.
 
-        eJustify:  the new justification. 
+        eJustify:  the new justification.
         """
         return _ogr.FieldDefn_SetJustify(self, *args)
 
     def GetWidth(self, *args):
         """
-        GetWidth(self) -> int
+        GetWidth(FieldDefn self) -> int
 
         int OGR_Fld_GetWidth(OGRFieldDefnH
         hDefn)
@@ -3928,13 +5098,13 @@ class FieldDefn(_object):
 
         hDefn:  handle to the field definition to get width from.
 
-        the width, zero means no specified width. 
+        the width, zero means no specified width.
         """
         return _ogr.FieldDefn_GetWidth(self, *args)
 
     def SetWidth(self, *args):
         """
-        SetWidth(self, int width)
+        SetWidth(FieldDefn self, int width)
 
         void OGR_Fld_SetWidth(OGRFieldDefnH
         hDefn, int nNewWidth)
@@ -3948,19 +5118,20 @@ class FieldDefn(_object):
 
         hDefn:  handle to the field definition to set width to.
 
-        nNewWidth:  the new width. 
+        nNewWidth:  the new width.
         """
         return _ogr.FieldDefn_SetWidth(self, *args)
 
     def GetPrecision(self, *args):
         """
-        GetPrecision(self) -> int
+        GetPrecision(FieldDefn self) -> int
 
         int
         OGR_Fld_GetPrecision(OGRFieldDefnH hDefn)
 
-        Get the formatting precision for this field. This should normally be
-        zero for fields of types other than OFTReal.
+        Get the formatting precision for this field.
+
+        This should normally be zero for fields of types other than OFTReal.
 
         This function is the same as the CPP method
         OGRFieldDefn::GetPrecision().
@@ -3970,13 +5141,13 @@ class FieldDefn(_object):
 
         hDefn:  handle to the field definition to get precision from.
 
-        the precision. 
+        the precision.
         """
         return _ogr.FieldDefn_GetPrecision(self, *args)
 
     def SetPrecision(self, *args):
         """
-        SetPrecision(self, int precision)
+        SetPrecision(FieldDefn self, int precision)
 
         void
         OGR_Fld_SetPrecision(OGRFieldDefnH hDefn, int nPrecision)
@@ -3993,21 +5164,21 @@ class FieldDefn(_object):
 
         hDefn:  handle to the field definition to set precision to.
 
-        nPrecision:  the new precision. 
+        nPrecision:  the new precision.
         """
         return _ogr.FieldDefn_SetPrecision(self, *args)
 
     def GetTypeName(self, *args):
-        """GetTypeName(self) -> char"""
+        """GetTypeName(FieldDefn self) -> char const *"""
         return _ogr.FieldDefn_GetTypeName(self, *args)
 
     def GetFieldTypeName(self, *args):
-        """GetFieldTypeName(self, OGRFieldType type) -> char"""
+        """GetFieldTypeName(FieldDefn self, OGRFieldType type) -> char const *"""
         return _ogr.FieldDefn_GetFieldTypeName(self, *args)
 
     def IsIgnored(self, *args):
         """
-        IsIgnored(self) -> int
+        IsIgnored(FieldDefn self) -> int
 
         int OGR_Fld_IsIgnored(OGRFieldDefnH
         hDefn)
@@ -4021,48 +5192,177 @@ class FieldDefn(_object):
 
         hDefn:  handle to the field definition
 
-        ignore state 
+        ignore state
         """
         return _ogr.FieldDefn_IsIgnored(self, *args)
 
     def SetIgnored(self, *args):
         """
-        SetIgnored(self, int bIgnored)
+        SetIgnored(FieldDefn self, int bIgnored)
 
         void
         OGR_Fld_SetIgnored(OGRFieldDefnH hDefn, int ignore)
 
         Set whether this field should be omitted when fetching features.
 
-        This method is the same as the C function OGRFieldDefn::SetIgnored().
+        This method is the same as the C++ method OGRFieldDefn::SetIgnored().
 
         Parameters:
         -----------
 
         hDefn:  handle to the field definition
 
-        ignore:  ignore state 
+        ignore:  ignore state
         """
         return _ogr.FieldDefn_SetIgnored(self, *args)
 
     def IsNullable(self, *args):
-        """IsNullable(self) -> int"""
+        """
+        IsNullable(FieldDefn self) -> int
+
+        int
+        OGR_Fld_IsNullable(OGRFieldDefnH hDefn)
+
+        Return whether this field can receive null values.
+
+        By default, fields are nullable.
+
+        Even if this method returns FALSE (i.e not-nullable field), it doesn't
+        mean that OGRFeature::IsFieldSet() will necessary return TRUE, as
+        fields can be temporary unset and null/not-null validation is usually
+        done when OGRLayer::CreateFeature()/SetFeature() is called.
+
+        This method is the same as the C++ method OGRFieldDefn::IsNullable().
+
+        Parameters:
+        -----------
+
+        hDefn:  handle to the field definition
+
+        TRUE if the field is authorized to be null.
+
+        GDAL 2.0
+        """
         return _ogr.FieldDefn_IsNullable(self, *args)
 
     def SetNullable(self, *args):
-        """SetNullable(self, int bNullable)"""
+        """
+        SetNullable(FieldDefn self, int bNullable)
+
+        void
+        OGR_Fld_SetNullable(OGRFieldDefnH hDefn, int bNullableIn)
+
+        Set whether this field can receive null values.
+
+        By default, fields are nullable, so this method is generally called
+        with FALSE to set a not-null constraint.
+
+        Drivers that support writing not-null constraint will advertize the
+        GDAL_DCAP_NOTNULL_FIELDS driver metadata item.
+
+        This method is the same as the C++ method OGRFieldDefn::SetNullable().
+
+        Parameters:
+        -----------
+
+        hDefn:  handle to the field definition
+
+        bNullableIn:  FALSE if the field must have a not-null constraint.
+
+        GDAL 2.0
+        """
         return _ogr.FieldDefn_SetNullable(self, *args)
 
     def GetDefault(self, *args):
-        """GetDefault(self) -> char"""
+        """
+        GetDefault(FieldDefn self) -> char const *
+
+        const char*
+        OGR_Fld_GetDefault(OGRFieldDefnH hDefn)
+
+        Get default field value.
+
+        This function is the same as the C++ method
+        OGRFieldDefn::GetDefault().
+
+        Parameters:
+        -----------
+
+        hDefn:  handle to the field definition.
+
+        default field value or NULL.
+
+        GDAL 2.0
+        """
         return _ogr.FieldDefn_GetDefault(self, *args)
 
     def SetDefault(self, *args):
-        """SetDefault(self, char pszValue)"""
+        """
+        SetDefault(FieldDefn self, char const * pszValue)
+
+        void
+        OGR_Fld_SetDefault(OGRFieldDefnH hDefn, const char *pszDefault)
+
+        Set default field value.
+
+        The default field value is taken into account by drivers (generally
+        those with a SQL interface) that support it at field creation time.
+        OGR will generally not automatically set the default field value to
+        null fields by itself when calling OGRFeature::CreateFeature() /
+        OGRFeature::SetFeature(), but will let the low-level layers to do the
+        job. So retrieving the feature from the layer is recommended.
+
+        The accepted values are NULL, a numeric value, a literal value
+        enclosed between single quote characters (and inner single quote
+        characters escaped by repetition of the single quote character),
+        CURRENT_TIMESTAMP, CURRENT_TIME, CURRENT_DATE or a driver specific
+        expression (that might be ignored by other drivers). For a datetime
+        literal value, format should be 'YYYY/MM/DD HH:MM:SS[.sss]'
+        (considered as UTC time).
+
+        Drivers that support writing DEFAULT clauses will advertize the
+        GDAL_DCAP_DEFAULT_FIELDS driver metadata item.
+
+        This function is the same as the C++ method
+        OGRFieldDefn::SetDefault().
+
+        Parameters:
+        -----------
+
+        hDefn:  handle to the field definition.
+
+        pszDefault:  new default field value or NULL pointer.
+
+        GDAL 2.0
+        """
         return _ogr.FieldDefn_SetDefault(self, *args)
 
     def IsDefaultDriverSpecific(self, *args):
-        """IsDefaultDriverSpecific(self) -> int"""
+        """
+        IsDefaultDriverSpecific(FieldDefn self) -> int
+
+        int
+        OGR_Fld_IsDefaultDriverSpecific(OGRFieldDefnH hDefn)
+
+        Returns whether the default value is driver specific.
+
+        Driver specific default values are those that are *not* NULL, a
+        numeric value, a literal value enclosed between single quote
+        characters, CURRENT_TIMESTAMP, CURRENT_TIME, CURRENT_DATE or datetime
+        literal value.
+
+        This function is the same as the C++ method
+        OGRFieldDefn::IsDefaultDriverSpecific().
+
+        Parameters:
+        -----------
+
+        hDefn:  handle to the field definition
+
+        TRUE if the default value is driver specific.
+
+        GDAL 2.0
+        """
         return _ogr.FieldDefn_IsDefaultDriverSpecific(self, *args)
 
     width = property(GetWidth, SetWidth)
@@ -4072,7 +5372,7 @@ class FieldDefn(_object):
     justify = property(GetJustify, SetJustify)
 
     def Destroy(self):
-      "Once called, self has effectively been destroyed.  Do not access. For backwards compatiblity only"
+      "Once called, self has effectively been destroyed.  Do not access. For backwards compatibility only"
       _ogr.delete_FieldDefn( self )
       self.thisown = 0
 
@@ -4088,53 +5388,53 @@ class GeomFieldDefn(_object):
     __repr__ = _swig_repr
     __swig_destroy__ = _ogr.delete_GeomFieldDefn
     __del__ = lambda self : None;
-    def __init__(self, *args, **kwargs): 
-        """__init__(self, char name_null_ok = "", OGRwkbGeometryType field_type = wkbUnknown) -> GeomFieldDefn"""
+    def __init__(self, *args, **kwargs):
+        """__init__(OGRGeomFieldDefnShadow self, char const * name_null_ok="", OGRwkbGeometryType field_type=wkbUnknown) -> GeomFieldDefn"""
         this = _ogr.new_GeomFieldDefn(*args, **kwargs)
         try: self.this.append(this)
         except: self.this = this
     def GetName(self, *args):
-        """GetName(self) -> char"""
+        """GetName(GeomFieldDefn self) -> char const *"""
         return _ogr.GeomFieldDefn_GetName(self, *args)
 
     def GetNameRef(self, *args):
-        """GetNameRef(self) -> char"""
+        """GetNameRef(GeomFieldDefn self) -> char const *"""
         return _ogr.GeomFieldDefn_GetNameRef(self, *args)
 
     def SetName(self, *args):
-        """SetName(self, char name)"""
+        """SetName(GeomFieldDefn self, char const * name)"""
         return _ogr.GeomFieldDefn_SetName(self, *args)
 
     def GetType(self, *args):
-        """GetType(self) -> OGRwkbGeometryType"""
+        """GetType(GeomFieldDefn self) -> OGRwkbGeometryType"""
         return _ogr.GeomFieldDefn_GetType(self, *args)
 
     def SetType(self, *args):
-        """SetType(self, OGRwkbGeometryType type)"""
+        """SetType(GeomFieldDefn self, OGRwkbGeometryType type)"""
         return _ogr.GeomFieldDefn_SetType(self, *args)
 
     def GetSpatialRef(self, *args):
-        """GetSpatialRef(self) -> SpatialReference"""
+        """GetSpatialRef(GeomFieldDefn self) -> SpatialReference"""
         return _ogr.GeomFieldDefn_GetSpatialRef(self, *args)
 
     def SetSpatialRef(self, *args):
-        """SetSpatialRef(self, SpatialReference srs)"""
+        """SetSpatialRef(GeomFieldDefn self, SpatialReference srs)"""
         return _ogr.GeomFieldDefn_SetSpatialRef(self, *args)
 
     def IsIgnored(self, *args):
-        """IsIgnored(self) -> int"""
+        """IsIgnored(GeomFieldDefn self) -> int"""
         return _ogr.GeomFieldDefn_IsIgnored(self, *args)
 
     def SetIgnored(self, *args):
-        """SetIgnored(self, int bIgnored)"""
+        """SetIgnored(GeomFieldDefn self, int bIgnored)"""
         return _ogr.GeomFieldDefn_SetIgnored(self, *args)
 
     def IsNullable(self, *args):
-        """IsNullable(self) -> int"""
+        """IsNullable(GeomFieldDefn self) -> int"""
         return _ogr.GeomFieldDefn_IsNullable(self, *args)
 
     def SetNullable(self, *args):
-        """SetNullable(self, int bNullable)"""
+        """SetNullable(GeomFieldDefn self, int bNullable)"""
         return _ogr.GeomFieldDefn_SetNullable(self, *args)
 
     type = property(GetType, SetType)
@@ -4146,34 +5446,29 @@ GeomFieldDefn_swigregister(GeomFieldDefn)
 
 
 def CreateGeometryFromWkb(*args, **kwargs):
-  """CreateGeometryFromWkb(int len, SpatialReference reference = None) -> Geometry"""
+  """CreateGeometryFromWkb(int len, SpatialReference reference=None) -> Geometry"""
   return _ogr.CreateGeometryFromWkb(*args, **kwargs)
 
 def CreateGeometryFromWkt(*args, **kwargs):
-  """CreateGeometryFromWkt(char val, SpatialReference reference = None) -> Geometry"""
+  """CreateGeometryFromWkt(char ** val, SpatialReference reference=None) -> Geometry"""
   return _ogr.CreateGeometryFromWkt(*args, **kwargs)
 
 def CreateGeometryFromGML(*args):
-  """CreateGeometryFromGML(char input_string) -> Geometry"""
+  """CreateGeometryFromGML(char const * input_string) -> Geometry"""
   return _ogr.CreateGeometryFromGML(*args)
 
 def CreateGeometryFromJson(*args):
-  """CreateGeometryFromJson(char input_string) -> Geometry"""
+  """CreateGeometryFromJson(char const * input_string) -> Geometry"""
   return _ogr.CreateGeometryFromJson(*args)
 
 def BuildPolygonFromEdges(*args, **kwargs):
-  """
-    BuildPolygonFromEdges(Geometry hLineCollection, int bBestEffort = 0, int bAutoClose = 0, 
-        double dfTolerance = 0) -> Geometry
-    """
+  """BuildPolygonFromEdges(Geometry hLineCollection, int bBestEffort=0, int bAutoClose=0, double dfTolerance=0) -> Geometry"""
   return _ogr.BuildPolygonFromEdges(*args, **kwargs)
 
 def ApproximateArcAngles(*args, **kwargs):
   """
-    ApproximateArcAngles(double dfCenterX, double dfCenterY, double dfZ, double dfPrimaryRadius, 
-        double dfSecondaryAxis, 
-        double dfRotation, double dfStartAngle, double dfEndAngle, 
-        double dfMaxAngleStepSizeDegrees) -> Geometry
+    ApproximateArcAngles(double dfCenterX, double dfCenterY, double dfZ, double dfPrimaryRadius, double dfSecondaryAxis,
+        double dfRotation, double dfStartAngle, double dfEndAngle, double dfMaxAngleStepSizeDegrees) -> Geometry
     """
   return _ogr.ApproximateArcAngles(*args, **kwargs)
 
@@ -4198,7 +5493,7 @@ def ForceToMultiLineString(*args):
   return _ogr.ForceToMultiLineString(*args)
 
 def ForceTo(*args):
-  """ForceTo(Geometry geom_in, OGRwkbGeometryType eTargetType, char options = None) -> Geometry"""
+  """ForceTo(Geometry geom_in, OGRwkbGeometryType eTargetType, char ** options=None) -> Geometry"""
   return _ogr.ForceTo(*args)
 class Geometry(_object):
     """Proxy of C++ OGRGeometryShadow class"""
@@ -4209,17 +5504,14 @@ class Geometry(_object):
     __repr__ = _swig_repr
     __swig_destroy__ = _ogr.delete_Geometry
     __del__ = lambda self : None;
-    def __init__(self, *args, **kwargs): 
-        """
-        __init__(self, OGRwkbGeometryType type = wkbUnknown, char wkt = None, 
-            int wkb = 0, char gml = None) -> Geometry
-        """
+    def __init__(self, *args, **kwargs):
+        """__init__(OGRGeometryShadow self, OGRwkbGeometryType type=wkbUnknown, char * wkt=None, int wkb=0, char * gml=None) -> Geometry"""
         this = _ogr.new_Geometry(*args, **kwargs)
         try: self.this.append(this)
         except: self.this = this
     def ExportToWkt(self, *args):
         """
-        ExportToWkt(self) -> OGRErr
+        ExportToWkt(Geometry self) -> OGRErr
 
         OGRErr
         OGR_G_ExportToWkt(OGRGeometryH hGeom, char **ppszSrcText)
@@ -4228,6 +5520,11 @@ class Geometry(_object):
 
         This function relates to the SFCOM IWks::ExportToWKT() method.
 
+        For backward compatibility purposes, it exports the Old-style 99-402
+        extended dimension (Z) WKB types for types Point, LineString, Polygon,
+        MultiPoint, MultiLineString, MultiPolygon and GeometryCollection. For
+        other geometry types, it is equivalent to OGR_G_ExportToIsoWkt().
+
         This function is the same as the CPP method
         OGRGeometry::exportToWkt().
 
@@ -4237,30 +5534,65 @@ class Geometry(_object):
         hGeom:  handle on the geometry to convert to a text format from.
 
         ppszSrcText:  a text buffer is allocated by the program, and assigned
-        to the passed pointer.
+        to the passed pointer. After use, *ppszDstText should be freed with
+        OGRFree().
 
-        Currently OGRERR_NONE is always returned. 
+        Currently OGRERR_NONE is always returned.
         """
         return _ogr.Geometry_ExportToWkt(self, *args)
 
     def ExportToIsoWkt(self, *args):
-        """ExportToIsoWkt(self) -> OGRErr"""
+        """
+        ExportToIsoWkt(Geometry self) -> OGRErr
+
+        OGRErr
+        OGR_G_ExportToIsoWkt(OGRGeometryH hGeom, char **ppszSrcText)
+
+        Convert a geometry into SFSQL 1.2 / ISO SQL/MM Part 3 well known text
+        format.
+
+        This function relates to the SFCOM IWks::ExportToWKT() method. It
+        exports the SFSQL 1.2 and ISO SQL/MM Part 3 extended dimension (Z&M)
+        WKB types
+
+        This function is the same as the CPP method
+        OGRGeometry::exportToWkt(,wkbVariantIso).
+
+        Parameters:
+        -----------
+
+        hGeom:  handle on the geometry to convert to a text format from.
+
+        ppszSrcText:  a text buffer is allocated by the program, and assigned
+        to the passed pointer. After use, *ppszDstText should be freed with
+        OGRFree().
+
+        Currently OGRERR_NONE is always returned.
+
+        GDAL 2.0
+        """
         return _ogr.Geometry_ExportToIsoWkt(self, *args)
 
     def ExportToWkb(self, *args, **kwargs):
         """
-        ExportToWkb(self, OGRwkbByteOrder byte_order = wkbXDR) -> OGRErr
+        ExportToWkb(Geometry self, OGRwkbByteOrder byte_order=wkbXDR) -> OGRErr
 
         OGRErr
         OGR_G_ExportToWkb(OGRGeometryH hGeom, OGRwkbByteOrder eOrder, unsigned
         char *pabyDstBuffer)
 
-        Convert a geometry into well known binary format.
+        Convert a geometry well known binary format.
 
         This function relates to the SFCOM IWks::ExportToWKB() method.
 
+        For backward compatibility purposes, it exports the Old-style 99-402
+        extended dimension (Z) WKB types for types Point, LineString, Polygon,
+        MultiPoint, MultiLineString, MultiPolygon and GeometryCollection. For
+        other geometry types, it is equivalent to OGR_G_ExportToIsoWkb().
+
         This function is the same as the CPP method
-        OGRGeometry::exportToWkb().
+        OGRGeometry::exportToWkb(OGRwkbByteOrder, unsigned char *,
+        OGRwkbVariant) with eWkbVariant = wkbVariantOldOgc.
 
         Parameters:
         -----------
@@ -4274,45 +5606,86 @@ class Geometry(_object):
         pabyDstBuffer:  a buffer into which the binary representation is
         written. This buffer must be at least OGR_G_WkbSize() byte in size.
 
-        Currently OGRERR_NONE is always returned. 
+        Currently OGRERR_NONE is always returned.
         """
         return _ogr.Geometry_ExportToWkb(self, *args, **kwargs)
 
     def ExportToIsoWkb(self, *args, **kwargs):
-        """ExportToIsoWkb(self, OGRwkbByteOrder byte_order = wkbXDR) -> OGRErr"""
+        """
+        ExportToIsoWkb(Geometry self, OGRwkbByteOrder byte_order=wkbXDR) -> OGRErr
+
+        OGRErr
+        OGR_G_ExportToIsoWkb(OGRGeometryH hGeom, OGRwkbByteOrder eOrder,
+        unsigned char *pabyDstBuffer)
+
+        Convert a geometry into SFSQL 1.2 / ISO SQL/MM Part 3 well known
+        binary format.
+
+        This function relates to the SFCOM IWks::ExportToWKB() method. It
+        exports the SFSQL 1.2 and ISO SQL/MM Part 3 extended dimension (Z&M)
+        WKB types
+
+        This function is the same as the CPP method
+        OGRGeometry::exportToWkb(OGRwkbByteOrder, unsigned char *,
+        OGRwkbVariant) with eWkbVariant = wkbVariantIso.
+
+        Parameters:
+        -----------
+
+        hGeom:  handle on the geometry to convert to a well know binary data
+        from.
+
+        eOrder:  One of wkbXDR or wkbNDR indicating MSB or LSB byte order
+        respectively.
+
+        pabyDstBuffer:  a buffer into which the binary representation is
+        written. This buffer must be at least OGR_G_WkbSize() byte in size.
+
+        Currently OGRERR_NONE is always returned.
+
+        GDAL 2.0
+        """
         return _ogr.Geometry_ExportToIsoWkb(self, *args, **kwargs)
 
     def ExportToGML(self, *args, **kwargs):
-        """ExportToGML(self, char options = None) -> retStringAndCPLFree"""
+        """ExportToGML(Geometry self, char ** options=None) -> retStringAndCPLFree *"""
         return _ogr.Geometry_ExportToGML(self, *args, **kwargs)
 
     def ExportToKML(self, *args):
-        """ExportToKML(self, char altitude_mode = None) -> retStringAndCPLFree"""
+        """ExportToKML(Geometry self, char const * altitude_mode=None) -> retStringAndCPLFree *"""
         return _ogr.Geometry_ExportToKML(self, *args)
 
     def ExportToJson(self, *args, **kwargs):
-        """ExportToJson(self, char options = None) -> retStringAndCPLFree"""
+        """ExportToJson(Geometry self, char ** options=None) -> retStringAndCPLFree *"""
         return _ogr.Geometry_ExportToJson(self, *args, **kwargs)
 
     def AddPoint(self, *args, **kwargs):
-        """AddPoint(self, double x, double y, double z = 0)"""
+        """AddPoint(Geometry self, double x, double y, double z=0)"""
         return _ogr.Geometry_AddPoint(self, *args, **kwargs)
 
+    def AddPointM(self, *args, **kwargs):
+        """AddPointM(Geometry self, double x, double y, double m)"""
+        return _ogr.Geometry_AddPointM(self, *args, **kwargs)
+
+    def AddPointZM(self, *args, **kwargs):
+        """AddPointZM(Geometry self, double x, double y, double z, double m)"""
+        return _ogr.Geometry_AddPointZM(self, *args, **kwargs)
+
     def AddPoint_2D(self, *args):
-        """AddPoint_2D(self, double x, double y)"""
+        """AddPoint_2D(Geometry self, double x, double y)"""
         return _ogr.Geometry_AddPoint_2D(self, *args)
 
     def AddGeometryDirectly(self, *args):
-        """AddGeometryDirectly(self, Geometry other_disown) -> OGRErr"""
+        """AddGeometryDirectly(Geometry self, Geometry other_disown) -> OGRErr"""
         return _ogr.Geometry_AddGeometryDirectly(self, *args)
 
     def AddGeometry(self, *args):
-        """AddGeometry(self, Geometry other) -> OGRErr"""
+        """AddGeometry(Geometry self, Geometry other) -> OGRErr"""
         return _ogr.Geometry_AddGeometry(self, *args)
 
     def Clone(self, *args):
         """
-        Clone(self) -> Geometry
+        Clone(Geometry self) -> Geometry
 
         OGRGeometryH OGR_G_Clone(OGRGeometryH
         hGeom)
@@ -4329,13 +5702,13 @@ class Geometry(_object):
         hGeom:  handle on the geometry to clone from.
 
         an handle on the copy of the geometry with the spatial reference
-        system as the original. 
+        system as the original.
         """
         return _ogr.Geometry_Clone(self, *args)
 
     def GetGeometryType(self, *args):
         """
-        GetGeometryType(self) -> OGRwkbGeometryType
+        GetGeometryType(Geometry self) -> OGRwkbGeometryType
 
         OGRwkbGeometryType
         OGR_G_GetGeometryType(OGRGeometryH hGeom)
@@ -4354,13 +5727,13 @@ class Geometry(_object):
 
         hGeom:  handle on the geometry to get type from.
 
-        the geometry type code. 
+        the geometry type code.
         """
         return _ogr.Geometry_GetGeometryType(self, *args)
 
     def GetGeometryName(self, *args):
         """
-        GetGeometryName(self) -> char
+        GetGeometryName(Geometry self) -> char const *
 
         const char*
         OGR_G_GetGeometryName(OGRGeometryH hGeom)
@@ -4377,69 +5750,85 @@ class Geometry(_object):
 
         hGeom:  handle on the geometry to get name from.
 
-        name used for this geometry type in well known text format. 
+        name used for this geometry type in well known text format.
         """
         return _ogr.Geometry_GetGeometryName(self, *args)
 
     def Length(self, *args):
-        """Length(self) -> double"""
+        """Length(Geometry self) -> double"""
         return _ogr.Geometry_Length(self, *args)
 
     def Area(self, *args):
-        """Area(self) -> double"""
+        """Area(Geometry self) -> double"""
         return _ogr.Geometry_Area(self, *args)
 
     def GetArea(self, *args):
-        """GetArea(self) -> double"""
+        """GetArea(Geometry self) -> double"""
         return _ogr.Geometry_GetArea(self, *args)
 
     def GetPointCount(self, *args):
-        """GetPointCount(self) -> int"""
+        """GetPointCount(Geometry self) -> int"""
         return _ogr.Geometry_GetPointCount(self, *args)
 
     def GetPoints(self, *args, **kwargs):
-        """GetPoints(self, int nCoordDimension = 0)"""
+        """GetPoints(Geometry self, int nCoordDimension=0)"""
         return _ogr.Geometry_GetPoints(self, *args, **kwargs)
 
     def GetX(self, *args, **kwargs):
-        """GetX(self, int point = 0) -> double"""
+        """GetX(Geometry self, int point=0) -> double"""
         return _ogr.Geometry_GetX(self, *args, **kwargs)
 
     def GetY(self, *args, **kwargs):
-        """GetY(self, int point = 0) -> double"""
+        """GetY(Geometry self, int point=0) -> double"""
         return _ogr.Geometry_GetY(self, *args, **kwargs)
 
     def GetZ(self, *args, **kwargs):
-        """GetZ(self, int point = 0) -> double"""
+        """GetZ(Geometry self, int point=0) -> double"""
         return _ogr.Geometry_GetZ(self, *args, **kwargs)
 
+    def GetM(self, *args, **kwargs):
+        """GetM(Geometry self, int point=0) -> double"""
+        return _ogr.Geometry_GetM(self, *args, **kwargs)
+
     def GetPoint(self, *args):
-        """GetPoint(self, int iPoint = 0)"""
+        """GetPoint(Geometry self, int iPoint=0)"""
         return _ogr.Geometry_GetPoint(self, *args)
 
+    def GetPointZM(self, *args):
+        """GetPointZM(Geometry self, int iPoint=0)"""
+        return _ogr.Geometry_GetPointZM(self, *args)
+
     def GetPoint_2D(self, *args):
-        """GetPoint_2D(self, int iPoint = 0)"""
+        """GetPoint_2D(Geometry self, int iPoint=0)"""
         return _ogr.Geometry_GetPoint_2D(self, *args)
 
     def GetGeometryCount(self, *args):
-        """GetGeometryCount(self) -> int"""
+        """GetGeometryCount(Geometry self) -> int"""
         return _ogr.Geometry_GetGeometryCount(self, *args)
 
     def SetPoint(self, *args, **kwargs):
-        """SetPoint(self, int point, double x, double y, double z = 0)"""
+        """SetPoint(Geometry self, int point, double x, double y, double z=0)"""
         return _ogr.Geometry_SetPoint(self, *args, **kwargs)
 
+    def SetPointM(self, *args, **kwargs):
+        """SetPointM(Geometry self, int point, double x, double y, double m)"""
+        return _ogr.Geometry_SetPointM(self, *args, **kwargs)
+
+    def SetPointZM(self, *args, **kwargs):
+        """SetPointZM(Geometry self, int point, double x, double y, double z, double m)"""
+        return _ogr.Geometry_SetPointZM(self, *args, **kwargs)
+
     def SetPoint_2D(self, *args, **kwargs):
-        """SetPoint_2D(self, int point, double x, double y)"""
+        """SetPoint_2D(Geometry self, int point, double x, double y)"""
         return _ogr.Geometry_SetPoint_2D(self, *args, **kwargs)
 
     def GetGeometryRef(self, *args):
-        """GetGeometryRef(self, int geom) -> Geometry"""
+        """GetGeometryRef(Geometry self, int geom) -> Geometry"""
         return _ogr.Geometry_GetGeometryRef(self, *args)
 
     def Simplify(self, *args):
         """
-        Simplify(self, double tolerance) -> Geometry
+        Simplify(Geometry self, double tolerance) -> Geometry
 
         OGRGeometryH
         OGR_G_Simplify(OGRGeometryH hThis, double dTolerance)
@@ -4462,18 +5851,18 @@ class Geometry(_object):
 
         the simplified geometry or NULL if an error occurs.
 
-        OGR 1.8.0 
+        OGR 1.8.0
         """
         return _ogr.Geometry_Simplify(self, *args)
 
     def SimplifyPreserveTopology(self, *args):
         """
-        SimplifyPreserveTopology(self, double tolerance) -> Geometry
+        SimplifyPreserveTopology(Geometry self, double tolerance) -> Geometry
 
         OGRGeometryH
         OGR_G_SimplifyPreserveTopology(OGRGeometryH hThis, double dTolerance)
 
-        Compute a simplified geometry.
+        Simplify the geometry while preserving topology.
 
         This function is the same as the C++ method
         OGRGeometry::SimplifyPreserveTopology().
@@ -4492,13 +5881,48 @@ class Geometry(_object):
 
         the simplified geometry or NULL if an error occurs.
 
-        OGR 1.9.0 
+        OGR 1.9.0
         """
         return _ogr.Geometry_SimplifyPreserveTopology(self, *args)
 
+    def DelaunayTriangulation(self, *args, **kwargs):
+        """
+        DelaunayTriangulation(Geometry self, double dfTolerance=0.0, int bOnlyEdges=False) -> Geometry
+
+        OGRGeometryH
+        OGR_G_DelaunayTriangulation(OGRGeometryH hThis, double dfTolerance,
+        int bOnlyEdges)
+
+        Return a Delaunay triangulation of the vertices of the geometry.
+
+        This function is the same as the C++ method
+        OGRGeometry::DelaunayTriangulation().
+
+        This function is built on the GEOS library, v3.4 or above. If OGR is
+        built without the GEOS library, this function will always fail,
+        issuing a CPLE_NotSupported error.
+
+        Parameters:
+        -----------
+
+        hThis:  the geometry.
+
+        dfTolerance:  optional snapping tolerance to use for improved
+        robustness
+
+        bOnlyEdges:  if TRUE, will return a MULTILINESTRING, otherwise it will
+        return a GEOMETRYCOLLECTION containing triangular POLYGONs.
+
+        the geometry resulting from the Delaunay triangulation or NULL if an
+        error occurs.
+
+        OGR 2.1
+        """
+        return _ogr.Geometry_DelaunayTriangulation(self, *args, **kwargs)
+
     def Boundary(self, *args):
         """
-        Boundary(self) -> Geometry
+        Boundary(Geometry self) -> Geometry
 
         OGRGeometryH
         OGR_G_Boundary(OGRGeometryH hTarget)
@@ -4523,26 +5947,26 @@ class Geometry(_object):
         a handle to a newly allocated geometry now owned by the caller, or
         NULL on failure.
 
-        OGR 1.8.0 
+        OGR 1.8.0
         """
         return _ogr.Geometry_Boundary(self, *args)
 
     def GetBoundary(self, *args):
         """
-        GetBoundary(self) -> Geometry
+        GetBoundary(Geometry self) -> Geometry
 
         OGRGeometryH
         OGR_G_GetBoundary(OGRGeometryH hTarget)
 
         Compute boundary (deprecated).
 
-        Deprecated See:   OGR_G_Boundary() 
+        Deprecated See:   OGR_G_Boundary()
         """
         return _ogr.Geometry_GetBoundary(self, *args)
 
     def ConvexHull(self, *args):
         """
-        ConvexHull(self) -> Geometry
+        ConvexHull(Geometry self) -> Geometry
 
         OGRGeometryH
         OGR_G_ConvexHull(OGRGeometryH hTarget)
@@ -4565,13 +5989,13 @@ class Geometry(_object):
         hTarget:  The Geometry to calculate the convex hull of.
 
         a handle to a newly allocated geometry now owned by the caller, or
-        NULL on failure. 
+        NULL on failure.
         """
         return _ogr.Geometry_ConvexHull(self, *args)
 
     def Buffer(self, *args, **kwargs):
         """
-        Buffer(self, double distance, int quadsecs = 30) -> Geometry
+        Buffer(Geometry self, double distance, int quadsecs=30) -> Geometry
 
         OGRGeometryH OGR_G_Buffer(OGRGeometryH
         hTarget, double dfDist, int nQuadSegs)
@@ -4584,7 +6008,7 @@ class Geometry(_object):
 
         Some buffer sections are properly described as curves, but are
         converted to approximate polygons. The nQuadSegs parameter can be used
-        to control how many segements should be used to define a 90 degree
+        to control how many segments should be used to define a 90 degree
         curve - a quadrant of a circle. A value of 30 is a reasonable default.
         Large values result in large numbers of vertices in the resulting
         buffer geometry while small numbers reduce the accuracy of the result.
@@ -4601,18 +6025,19 @@ class Geometry(_object):
 
         hTarget:  the geometry.
 
-        dfDist:  the buffer distance to be applied.
+        dfDist:  the buffer distance to be applied. Should be expressed into
+        the same unit as the coordinates of the geometry.
 
         nQuadSegs:  the number of segments used to approximate a 90 degree
         (quadrant) of curvature.
 
-        the newly created geometry, or NULL if an error occurs. 
+        the newly created geometry, or NULL if an error occurs.
         """
         return _ogr.Geometry_Buffer(self, *args, **kwargs)
 
     def Intersection(self, *args):
         """
-        Intersection(self, Geometry other) -> Geometry
+        Intersection(Geometry self, Geometry other) -> Geometry
 
         OGRGeometryH
         OGR_G_Intersection(OGRGeometryH hThis, OGRGeometryH hOther)
@@ -4639,13 +6064,13 @@ class Geometry(_object):
         hOther:  the other geometry.
 
         a new geometry representing the intersection or NULL if there is no
-        intersection or an error occurs. 
+        intersection or an error occurs.
         """
         return _ogr.Geometry_Intersection(self, *args)
 
     def Union(self, *args):
         """
-        Union(self, Geometry other) -> Geometry
+        Union(Geometry self, Geometry other) -> Geometry
 
         OGRGeometryH OGR_G_Union(OGRGeometryH
         hThis, OGRGeometryH hOther)
@@ -4669,13 +6094,13 @@ class Geometry(_object):
 
         hOther:  the other geometry.
 
-        a new geometry representing the union or NULL if an error occurs. 
+        a new geometry representing the union or NULL if an error occurs.
         """
         return _ogr.Geometry_Union(self, *args)
 
     def UnionCascaded(self, *args):
         """
-        UnionCascaded(self) -> Geometry
+        UnionCascaded(Geometry self) -> Geometry
 
         OGRGeometryH
         OGR_G_UnionCascaded(OGRGeometryH hThis)
@@ -4695,13 +6120,13 @@ class Geometry(_object):
 
         hThis:  the geometry.
 
-        a new geometry representing the union or NULL if an error occurs. 
+        a new geometry representing the union or NULL if an error occurs.
         """
         return _ogr.Geometry_UnionCascaded(self, *args)
 
     def Difference(self, *args):
         """
-        Difference(self, Geometry other) -> Geometry
+        Difference(Geometry self, Geometry other) -> Geometry
 
         OGRGeometryH
         OGR_G_Difference(OGRGeometryH hThis, OGRGeometryH hOther)
@@ -4726,13 +6151,13 @@ class Geometry(_object):
         hOther:  the other geometry.
 
         a new geometry representing the difference or NULL if the difference
-        is empty or an error occurs. 
+        is empty or an error occurs.
         """
         return _ogr.Geometry_Difference(self, *args)
 
     def SymDifference(self, *args):
         """
-        SymDifference(self, Geometry other) -> Geometry
+        SymDifference(Geometry self, Geometry other) -> Geometry
 
         OGRGeometryH
         OGR_G_SymDifference(OGRGeometryH hThis, OGRGeometryH hOther)
@@ -4760,33 +6185,34 @@ class Geometry(_object):
         a new geometry representing the symmetric difference or NULL if the
         difference is empty or an error occurs.
 
-        OGR 1.8.0 
+        OGR 1.8.0
         """
         return _ogr.Geometry_SymDifference(self, *args)
 
     def SymmetricDifference(self, *args):
         """
-        SymmetricDifference(self, Geometry other) -> Geometry
+        SymmetricDifference(Geometry self, Geometry other) -> Geometry
 
         OGRGeometryH
         OGR_G_SymmetricDifference(OGRGeometryH hThis, OGRGeometryH hOther)
 
         Compute symmetric difference (deprecated).
 
-        Deprecated See:   OGR_G_SymmetricDifference() 
+        Deprecated See:   OGR_G_SymmetricDifference()
         """
         return _ogr.Geometry_SymmetricDifference(self, *args)
 
     def Distance(self, *args):
         """
-        Distance(self, Geometry other) -> double
+        Distance(Geometry self, Geometry other) -> double
 
         double OGR_G_Distance(OGRGeometryH
         hFirst, OGRGeometryH hOther)
 
         Compute distance between two geometries.
 
-        Returns the shortest distance between the two geometries.
+        Returns the shortest distance between the two geometries. The distance
+        is expressed into the same unit as the coordinates of the geometries.
 
         This function is the same as the C++ method OGRGeometry::Distance().
 
@@ -4802,18 +6228,20 @@ class Geometry(_object):
 
         hOther:  the other geometry to compare against.
 
-        the distance between the geometries or -1 if an error occurs. 
+        the distance between the geometries or -1 if an error occurs.
         """
         return _ogr.Geometry_Distance(self, *args)
 
     def Empty(self, *args):
         """
-        Empty(self)
+        Empty(Geometry self)
 
         void OGR_G_Empty(OGRGeometryH hGeom)
 
-        Clear geometry information. This restores the geometry to it's initial
-        state after construction, and before assignment of actual geometry.
+        Clear geometry information.
+
+        This restores the geometry to it's initial state after construction,
+        and before assignment of actual geometry.
 
         This function relates to the SFCOM IGeometry::Empty() method.
 
@@ -4822,13 +6250,13 @@ class Geometry(_object):
         Parameters:
         -----------
 
-        hGeom:  handle on the geometry to empty. 
+        hGeom:  handle on the geometry to empty.
         """
         return _ogr.Geometry_Empty(self, *args)
 
     def IsEmpty(self, *args):
         """
-        IsEmpty(self) -> bool
+        IsEmpty(Geometry self) -> bool
 
         int OGR_G_IsEmpty(OGRGeometryH hGeom)
 
@@ -4841,13 +6269,13 @@ class Geometry(_object):
 
         hGeom:  The Geometry to test.
 
-        TRUE if the geometry has no points, otherwise FALSE. 
+        TRUE if the geometry has no points, otherwise FALSE.
         """
         return _ogr.Geometry_IsEmpty(self, *args)
 
     def IsValid(self, *args):
         """
-        IsValid(self) -> bool
+        IsValid(Geometry self) -> bool
 
         int OGR_G_IsValid(OGRGeometryH hGeom)
 
@@ -4864,13 +6292,13 @@ class Geometry(_object):
 
         hGeom:  The Geometry to test.
 
-        TRUE if the geometry has no points, otherwise FALSE. 
+        TRUE if the geometry has no points, otherwise FALSE.
         """
         return _ogr.Geometry_IsValid(self, *args)
 
     def IsSimple(self, *args):
         """
-        IsSimple(self) -> bool
+        IsSimple(Geometry self) -> bool
 
         int OGR_G_IsSimple(OGRGeometryH
         hGeom)
@@ -4893,13 +6321,13 @@ class Geometry(_object):
 
         hGeom:  The Geometry to test.
 
-        TRUE if object is simple, otherwise FALSE. 
+        TRUE if object is simple, otherwise FALSE.
         """
         return _ogr.Geometry_IsSimple(self, *args)
 
     def IsRing(self, *args):
         """
-        IsRing(self) -> bool
+        IsRing(Geometry self) -> bool
 
         int OGR_G_IsRing(OGRGeometryH hGeom)
 
@@ -4916,22 +6344,22 @@ class Geometry(_object):
 
         hGeom:  The Geometry to test.
 
-        TRUE if the geometry has no points, otherwise FALSE. 
+        TRUE if the geometry has no points, otherwise FALSE.
         """
         return _ogr.Geometry_IsRing(self, *args)
 
     def Intersects(self, *args):
         """
-        Intersects(self, Geometry other) -> bool
+        Intersects(Geometry self, Geometry other) -> bool
 
         int OGR_G_Intersects(OGRGeometryH
         hGeom, OGRGeometryH hOtherGeom)
 
         Do these features intersect?
 
-        Currently this is not implemented in a rigerous fashion, and generally
-        just tests whether the envelopes of the two features intersect.
-        Eventually this will be made rigerous.
+        Determines whether two geometries intersect. If GEOS is enabled, then
+        this is done in rigorous fashion otherwise TRUE is returned if the
+        envelopes (bounding boxes) of the two geometries overlap.
 
         This function is the same as the CPP method OGRGeometry::Intersects.
 
@@ -4942,22 +6370,22 @@ class Geometry(_object):
 
         hOtherGeom:  handle on the other geometry to test against.
 
-        TRUE if the geometries intersect, otherwise FALSE. 
+        TRUE if the geometries intersect, otherwise FALSE.
         """
         return _ogr.Geometry_Intersects(self, *args)
 
     def Intersect(self, *args):
         """
-        Intersect(self, Geometry other) -> bool
+        Intersect(Geometry self, Geometry other) -> bool
 
         int OGR_G_Intersect(OGRGeometryH
-        hGeom, OGRGeometryH hOtherGeom) 
+        hGeom, OGRGeometryH hOtherGeom)
         """
         return _ogr.Geometry_Intersect(self, *args)
 
     def Equals(self, *args):
         """
-        Equals(self, Geometry other) -> bool
+        Equals(Geometry self, Geometry other) -> bool
 
         int OGR_G_Equals(OGRGeometryH hGeom,
         OGRGeometryH hOther)
@@ -4974,22 +6402,22 @@ class Geometry(_object):
 
         hOther:  handle on the other geometry to test against.
 
-        TRUE if equivalent or FALSE otherwise. 
+        TRUE if equivalent or FALSE otherwise.
         """
         return _ogr.Geometry_Equals(self, *args)
 
     def Equal(self, *args):
         """
-        Equal(self, Geometry other) -> bool
+        Equal(Geometry self, Geometry other) -> bool
 
         int OGR_G_Equal(OGRGeometryH hGeom,
-        OGRGeometryH hOther) 
+        OGRGeometryH hOther)
         """
         return _ogr.Geometry_Equal(self, *args)
 
     def Disjoint(self, *args):
         """
-        Disjoint(self, Geometry other) -> bool
+        Disjoint(Geometry self, Geometry other) -> bool
 
         int OGR_G_Disjoint(OGRGeometryH
         hThis, OGRGeometryH hOther)
@@ -5012,13 +6440,13 @@ class Geometry(_object):
 
         hOther:  the other geometry to compare.
 
-        TRUE if they are disjoint, otherwise FALSE. 
+        TRUE if they are disjoint, otherwise FALSE.
         """
         return _ogr.Geometry_Disjoint(self, *args)
 
     def Touches(self, *args):
         """
-        Touches(self, Geometry other) -> bool
+        Touches(Geometry self, Geometry other) -> bool
 
         int OGR_G_Touches(OGRGeometryH hThis,
         OGRGeometryH hOther)
@@ -5041,13 +6469,13 @@ class Geometry(_object):
 
         hOther:  the other geometry to compare.
 
-        TRUE if they are touching, otherwise FALSE. 
+        TRUE if they are touching, otherwise FALSE.
         """
         return _ogr.Geometry_Touches(self, *args)
 
     def Crosses(self, *args):
         """
-        Crosses(self, Geometry other) -> bool
+        Crosses(Geometry self, Geometry other) -> bool
 
         int OGR_G_Crosses(OGRGeometryH hThis,
         OGRGeometryH hOther)
@@ -5070,13 +6498,13 @@ class Geometry(_object):
 
         hOther:  the other geometry to compare.
 
-        TRUE if they are crossing, otherwise FALSE. 
+        TRUE if they are crossing, otherwise FALSE.
         """
         return _ogr.Geometry_Crosses(self, *args)
 
     def Within(self, *args):
         """
-        Within(self, Geometry other) -> bool
+        Within(Geometry self, Geometry other) -> bool
 
         int OGR_G_Within(OGRGeometryH hThis,
         OGRGeometryH hOther)
@@ -5099,13 +6527,13 @@ class Geometry(_object):
 
         hOther:  the other geometry to compare.
 
-        TRUE if hThis is within hOther, otherwise FALSE. 
+        TRUE if hThis is within hOther, otherwise FALSE.
         """
         return _ogr.Geometry_Within(self, *args)
 
     def Contains(self, *args):
         """
-        Contains(self, Geometry other) -> bool
+        Contains(Geometry self, Geometry other) -> bool
 
         int OGR_G_Contains(OGRGeometryH
         hThis, OGRGeometryH hOther)
@@ -5128,13 +6556,13 @@ class Geometry(_object):
 
         hOther:  the other geometry to compare.
 
-        TRUE if hThis contains hOther geometry, otherwise FALSE. 
+        TRUE if hThis contains hOther geometry, otherwise FALSE.
         """
         return _ogr.Geometry_Contains(self, *args)
 
     def Overlaps(self, *args):
         """
-        Overlaps(self, Geometry other) -> bool
+        Overlaps(Geometry self, Geometry other) -> bool
 
         int OGR_G_Overlaps(OGRGeometryH
         hThis, OGRGeometryH hOther)
@@ -5158,13 +6586,13 @@ class Geometry(_object):
 
         hOther:  the other geometry to compare.
 
-        TRUE if they are overlapping, otherwise FALSE. 
+        TRUE if they are overlapping, otherwise FALSE.
         """
         return _ogr.Geometry_Overlaps(self, *args)
 
     def TransformTo(self, *args):
         """
-        TransformTo(self, SpatialReference reference) -> OGRErr
+        TransformTo(Geometry self, SpatialReference reference) -> OGRErr
 
         OGRErr
         OGR_G_TransformTo(OGRGeometryH hGeom, OGRSpatialReferenceH hSRS)
@@ -5196,13 +6624,13 @@ class Geometry(_object):
 
         hSRS:  handle on the spatial reference system to apply.
 
-        OGRERR_NONE on success, or an error code. 
+        OGRERR_NONE on success, or an error code.
         """
         return _ogr.Geometry_TransformTo(self, *args)
 
     def Transform(self, *args):
         """
-        Transform(self, CoordinateTransformation trans) -> OGRErr
+        Transform(Geometry self, CoordinateTransformation trans) -> OGRErr
 
         OGRErr OGR_G_Transform(OGRGeometryH
         hGeom, OGRCoordinateTransformationH hTransform)
@@ -5231,13 +6659,13 @@ class Geometry(_object):
 
         hTransform:  handle on the transformation to apply.
 
-        OGRERR_NONE on success or an error code. 
+        OGRERR_NONE on success or an error code.
         """
         return _ogr.Geometry_Transform(self, *args)
 
     def GetSpatialReference(self, *args):
         """
-        GetSpatialReference(self) -> SpatialReference
+        GetSpatialReference(Geometry self) -> SpatialReference
 
         OGRSpatialReferenceH
         OGR_G_GetSpatialReference(OGRGeometryH hGeom)
@@ -5255,13 +6683,13 @@ class Geometry(_object):
 
         hGeom:  handle on the geometry to get spatial reference from.
 
-        a reference to the spatial reference geometry. 
+        a reference to the spatial reference geometry.
         """
         return _ogr.Geometry_GetSpatialReference(self, *args)
 
     def AssignSpatialReference(self, *args):
         """
-        AssignSpatialReference(self, SpatialReference reference)
+        AssignSpatialReference(Geometry self, SpatialReference reference)
 
         void
         OGR_G_AssignSpatialReference(OGRGeometryH hGeom, OGRSpatialReferenceH
@@ -5286,13 +6714,13 @@ class Geometry(_object):
         hGeom:  handle on the geometry to apply the new spatial reference
         system.
 
-        hSRS:  handle on the new spatial reference system to apply. 
+        hSRS:  handle on the new spatial reference system to apply.
         """
         return _ogr.Geometry_AssignSpatialReference(self, *args)
 
     def CloseRings(self, *args):
         """
-        CloseRings(self)
+        CloseRings(Geometry self)
 
         void OGR_G_CloseRings(OGRGeometryH
         hGeom)
@@ -5306,19 +6734,20 @@ class Geometry(_object):
         Parameters:
         -----------
 
-        hGeom:  handle to the geometry. 
+        hGeom:  handle to the geometry.
         """
         return _ogr.Geometry_CloseRings(self, *args)
 
     def FlattenTo2D(self, *args):
         """
-        FlattenTo2D(self)
+        FlattenTo2D(Geometry self)
 
         void
         OGR_G_FlattenTo2D(OGRGeometryH hGeom)
 
-        Convert geometry to strictly 2D. In a sense this converts all Z
-        coordinates to 0.0.
+        Convert geometry to strictly 2D.
+
+        In a sense this converts all Z coordinates to 0.0.
 
         This function is the same as the CPP method
         OGRGeometry::flattenTo2D().
@@ -5326,13 +6755,13 @@ class Geometry(_object):
         Parameters:
         -----------
 
-        hGeom:  handle on the geometry to convert. 
+        hGeom:  handle on the geometry to convert.
         """
         return _ogr.Geometry_FlattenTo2D(self, *args)
 
     def Segmentize(self, *args):
         """
-        Segmentize(self, double dfMaxLength)
+        Segmentize(Geometry self, double dfMaxLength)
 
         void OGR_G_Segmentize(OGRGeometryH
         hGeom, double dfMaxLength)
@@ -5351,13 +6780,13 @@ class Geometry(_object):
         hGeom:  handle on the geometry to segmentize
 
         dfMaxLength:  the maximum distance between 2 points after
-        segmentization 
+        segmentization
         """
         return _ogr.Geometry_Segmentize(self, *args)
 
     def GetEnvelope(self, *args):
         """
-        GetEnvelope(self)
+        GetEnvelope(Geometry self)
 
         void
         OGR_G_GetEnvelope(OGRGeometryH hGeom, OGREnvelope *psEnvelope)
@@ -5373,13 +6802,13 @@ class Geometry(_object):
 
         hGeom:  handle of the geometry to get envelope from.
 
-        psEnvelope:  the structure in which to place the results. 
+        psEnvelope:  the structure in which to place the results.
         """
         return _ogr.Geometry_GetEnvelope(self, *args)
 
     def GetEnvelope3D(self, *args):
         """
-        GetEnvelope3D(self)
+        GetEnvelope3D(Geometry self)
 
         void
         OGR_G_GetEnvelope3D(OGRGeometryH hGeom, OGREnvelope3D *psEnvelope)
@@ -5397,13 +6826,13 @@ class Geometry(_object):
 
         psEnvelope:  the structure in which to place the results.
 
-        OGR 1.9.0 
+        OGR 1.9.0
         """
         return _ogr.Geometry_GetEnvelope3D(self, *args)
 
     def Centroid(self, *args):
         """
-        Centroid(self) -> Geometry
+        Centroid(Geometry self) -> Geometry
 
         int OGR_G_Centroid(OGRGeometryH
         hGeom, OGRGeometryH hCentroidPoint)
@@ -5427,17 +6856,42 @@ class Geometry(_object):
         library, this function will always fail, issuing a CPLE_NotSupported
         error.
 
-        OGRERR_NONE on success or OGRERR_FAILURE on error. 
+        OGRERR_NONE on success or OGRERR_FAILURE on error.
         """
         return _ogr.Geometry_Centroid(self, *args)
 
     def PointOnSurface(self, *args):
-        """PointOnSurface(self) -> Geometry"""
+        """
+        PointOnSurface(Geometry self) -> Geometry
+
+        OGRGeometryH
+        OGR_G_PointOnSurface(OGRGeometryH hGeom)
+
+        Returns a point guaranteed to lie on the surface.
+
+        This method relates to the SFCOM ISurface::get_PointOnSurface() method
+        however the current implementation based on GEOS can operate on other
+        geometry types than the types that are supported by SQL/MM-Part 3 :
+        surfaces (polygons) and multisurfaces (multipolygons).
+
+        This method is built on the GEOS library, check it for the definition
+        of the geometry operation. If OGR is built without the GEOS library,
+        this method will always fail, issuing a CPLE_NotSupported error.
+
+        Parameters:
+        -----------
+
+        hGeom:  the geometry to operate on.
+
+        a point guaranteed to lie on the surface or NULL if an error occurred.
+
+        OGR 1.10
+        """
         return _ogr.Geometry_PointOnSurface(self, *args)
 
     def WkbSize(self, *args):
         """
-        WkbSize(self) -> int
+        WkbSize(Geometry self) -> int
 
         int OGR_G_WkbSize(OGRGeometryH hGeom)
 
@@ -5456,22 +6910,19 @@ class Geometry(_object):
 
         hGeom:  handle on the geometry to get the binary size from.
 
-        size of binary representation in bytes. 
+        size of binary representation in bytes.
         """
         return _ogr.Geometry_WkbSize(self, *args)
 
     def GetCoordinateDimension(self, *args):
         """
-        GetCoordinateDimension(self) -> int
+        GetCoordinateDimension(Geometry self) -> int
 
         int
         OGR_G_GetCoordinateDimension(OGRGeometryH hGeom)
 
         Get the dimension of the coordinates in this geometry.
 
-        This function corresponds to the SFCOM IGeometry::GetDimension()
-        method.
-
         This function is the same as the CPP method
         OGRGeometry::getCoordinateDimension().
 
@@ -5481,14 +6932,81 @@ class Geometry(_object):
         hGeom:  handle on the geometry to get the dimension of the coordinates
         from.
 
-        in practice this will return 2 or 3. It can also return 0 in the case
-        of an empty point. 
+        Deprecated use OGR_G_CoordinateDimension(), OGR_G_Is3D(), or
+        OGR_G_IsMeasured().
+
+        this will return 2 or 3.
         """
         return _ogr.Geometry_GetCoordinateDimension(self, *args)
 
+    def CoordinateDimension(self, *args):
+        """
+        CoordinateDimension(Geometry self) -> int
+
+        int
+        OGR_G_CoordinateDimension(OGRGeometryH hGeom)
+
+        Get the dimension of the coordinates in this geometry.
+
+        This function is the same as the CPP method
+        OGRGeometry::CoordinateDimension().
+
+        Parameters:
+        -----------
+
+        hGeom:  handle on the geometry to get the dimension of the coordinates
+        from.
+
+        this will return 2 for XY, 3 for XYZ and XYM, and 4 for XYZM data.
+        """
+        return _ogr.Geometry_CoordinateDimension(self, *args)
+
+    def Is3D(self, *args):
+        """
+        Is3D(Geometry self) -> int
+
+        int OGR_G_Is3D(OGRGeometryH hGeom)
+
+        See whether this geometry has Z coordinates.
+
+        This function is the same as the CPP method OGRGeometry::Is3D().
+
+        Parameters:
+        -----------
+
+        hGeom:  handle on the geometry to check whether it has Z coordinates.
+
+        TRUE if the geometry has Z coordinates.
+
+        GDAL 2.1
+        """
+        return _ogr.Geometry_Is3D(self, *args)
+
+    def IsMeasured(self, *args):
+        """
+        IsMeasured(Geometry self) -> int
+
+        int OGR_G_IsMeasured(OGRGeometryH
+        hGeom)
+
+        See whether this geometry is measured.
+
+        This function is the same as the CPP method OGRGeometry::IsMeasured().
+
+        Parameters:
+        -----------
+
+        hGeom:  handle on the geometry to check whether it is measured.
+
+        TRUE if the geometry has M coordinates.
+
+        GDAL 2.1
+        """
+        return _ogr.Geometry_IsMeasured(self, *args)
+
     def SetCoordinateDimension(self, *args):
         """
-        SetCoordinateDimension(self, int dimension)
+        SetCoordinateDimension(Geometry self, int dimension)
 
         void
         OGR_G_SetCoordinateDimension(OGRGeometryH hGeom, int nNewDimension)
@@ -5497,8 +7015,11 @@ class Geometry(_object):
 
         This method sets the explicit coordinate dimension. Setting the
         coordinate dimension of a geometry to 2 should zero out any existing Z
-        values. Setting the dimension of a geometry collection will not
-        necessarily affect the children geometries.
+        values. Setting the dimension of a geometry collection, a compound
+        curve, a polygon, etc. will affect the children geometries. This will
+        also remove the M dimension if present before this call.
+
+        Deprecated use OGR_G_Set3D() or OGR_G_SetMeasured().
 
         Parameters:
         -----------
@@ -5506,13 +7027,65 @@ class Geometry(_object):
         hGeom:  handle on the geometry to set the dimension of the
         coordinates.
 
-        nNewDimension:  New coordinate dimension value, either 2 or 3. 
+        nNewDimension:  New coordinate dimension value, either 2 or 3.
         """
         return _ogr.Geometry_SetCoordinateDimension(self, *args)
 
+    def Set3D(self, *args):
+        """
+        Set3D(Geometry self, int b3D)
+
+        void OGR_G_Set3D(OGRGeometryH hGeom,
+        int bIs3D)
+
+        Add or remove the Z coordinate dimension.
+
+        This method adds or removes the explicit Z coordinate dimension.
+        Removing the Z coordinate dimension of a geometry will remove any
+        existing Z values. Adding the Z dimension to a geometry collection, a
+        compound curve, a polygon, etc. will affect the children geometries.
+
+        Parameters:
+        -----------
+
+        hGeom:  handle on the geometry to set or unset the Z dimension.
+
+        bIs3D:  Should the geometry have a Z dimension, either TRUE or FALSE.
+
+        GDAL 2.1
+        """
+        return _ogr.Geometry_Set3D(self, *args)
+
+    def SetMeasured(self, *args):
+        """
+        SetMeasured(Geometry self, int bMeasured)
+
+        void
+        OGR_G_SetMeasured(OGRGeometryH hGeom, int bIsMeasured)
+
+        Set the coordinate dimension.
+
+        Add or remove the M coordinate dimension. This method adds or removes
+        the explicit M coordinate dimension. Removing the M coordinate
+        dimension of a geometry will remove any existing M values. Adding the
+        M dimension to a geometry collection, a compound curve, a polygon,
+        etc. will affect the children geometries.
+
+        Parameters:
+        -----------
+
+        hGeom:  handle on the geometry to set or unset the M dimension.
+
+        bIsMeasured:  Should the geometry have a M dimension, either TRUE or
+        FALSE.
+
+        GDAL 2.1
+        """
+        return _ogr.Geometry_SetMeasured(self, *args)
+
     def GetDimension(self, *args):
         """
-        GetDimension(self) -> int
+        GetDimension(Geometry self) -> int
 
         int
         OGR_G_GetDimension(OGRGeometryH hGeom)
@@ -5532,34 +7105,34 @@ class Geometry(_object):
 
         hGeom:  handle on the geometry to get the dimension from.
 
-        0 for points, 1 for lines and 2 for surfaces. 
+        0 for points, 1 for lines and 2 for surfaces.
         """
         return _ogr.Geometry_GetDimension(self, *args)
 
     def HasCurveGeometry(self, *args):
-        """HasCurveGeometry(self, int bLookForCircular = True) -> int"""
+        """HasCurveGeometry(Geometry self, int bLookForCircular=False) -> int"""
         return _ogr.Geometry_HasCurveGeometry(self, *args)
 
     def GetLinearGeometry(self, *args, **kwargs):
-        """GetLinearGeometry(self, double dfMaxAngleStepSizeDegrees = 0.0, char options = None) -> Geometry"""
+        """GetLinearGeometry(Geometry self, double dfMaxAngleStepSizeDegrees=0.0, char ** options=None) -> Geometry"""
         return _ogr.Geometry_GetLinearGeometry(self, *args, **kwargs)
 
     def GetCurveGeometry(self, *args, **kwargs):
-        """GetCurveGeometry(self, char options = None) -> Geometry"""
+        """GetCurveGeometry(Geometry self, char ** options=None) -> Geometry"""
         return _ogr.Geometry_GetCurveGeometry(self, *args, **kwargs)
 
     def Value(self, *args):
-        """Value(self, double dfDistance) -> Geometry"""
+        """Value(Geometry self, double dfDistance) -> Geometry"""
         return _ogr.Geometry_Value(self, *args)
 
     def Destroy(self):
-      self.__swig_destroy__(self) 
+      self.__swig_destroy__(self)
       self.__del__()
       self.thisown = 0
 
     def __str__(self):
       return self.ExportToWkt()
-      
+
 
     def __reduce__(self):
       return (self.__class__, (), self.ExportToWkb())
@@ -5567,11 +7140,11 @@ class Geometry(_object):
     def __setstate__(self, state):
         result = CreateGeometryFromWkb(state)
         self.this = result.this
-          
+
     def __iter__(self):
         self.iter_subgeom = 0
         return self
-        
+
     def next(self):
         if self.iter_subgeom < self.GetGeometryCount():
             subgeom = self.GetGeometryRef(self.iter_subgeom)
@@ -5601,15 +7174,15 @@ def RegisterAll(*args):
   return _ogr.RegisterAll(*args)
 
 def GeometryTypeToName(*args):
-  """GeometryTypeToName(OGRwkbGeometryType eType) -> char"""
+  """GeometryTypeToName(OGRwkbGeometryType eType) -> char const *"""
   return _ogr.GeometryTypeToName(*args)
 
 def GetFieldTypeName(*args):
-  """GetFieldTypeName(OGRFieldType type) -> char"""
+  """GetFieldTypeName(OGRFieldType type) -> char const *"""
   return _ogr.GetFieldTypeName(*args)
 
 def GetFieldSubTypeName(*args):
-  """GetFieldSubTypeName(OGRFieldSubType type) -> char"""
+  """GetFieldSubTypeName(OGRFieldSubType type) -> char const *"""
   return _ogr.GetFieldSubTypeName(*args)
 
 def GT_Flatten(*args):
@@ -5620,28 +7193,36 @@ def GT_SetZ(*args):
   """GT_SetZ(OGRwkbGeometryType eType) -> OGRwkbGeometryType"""
   return _ogr.GT_SetZ(*args)
 
+def GT_SetM(*args):
+  """GT_SetM(OGRwkbGeometryType eType) -> OGRwkbGeometryType"""
+  return _ogr.GT_SetM(*args)
+
 def GT_SetModifier(*args):
-  """GT_SetModifier(OGRwkbGeometryType eType, int bSetZ, int bSetM = True) -> OGRwkbGeometryType"""
+  """GT_SetModifier(OGRwkbGeometryType eType, int bSetZ, int bSetM=False) -> OGRwkbGeometryType"""
   return _ogr.GT_SetModifier(*args)
 
 def GT_HasZ(*args):
   """GT_HasZ(OGRwkbGeometryType eType) -> int"""
   return _ogr.GT_HasZ(*args)
 
+def GT_HasM(*args):
+  """GT_HasM(OGRwkbGeometryType eType) -> int"""
+  return _ogr.GT_HasM(*args)
+
 def GT_IsSubClassOf(*args):
   """GT_IsSubClassOf(OGRwkbGeometryType eType, OGRwkbGeometryType eSuperType) -> int"""
   return _ogr.GT_IsSubClassOf(*args)
 
 def GT_IsCurve(*args):
-  """GT_IsCurve(OGRwkbGeometryType arg0) -> int"""
+  """GT_IsCurve(OGRwkbGeometryType arg1) -> int"""
   return _ogr.GT_IsCurve(*args)
 
 def GT_IsSurface(*args):
-  """GT_IsSurface(OGRwkbGeometryType arg0) -> int"""
+  """GT_IsSurface(OGRwkbGeometryType arg1) -> int"""
   return _ogr.GT_IsSurface(*args)
 
 def GT_IsNonLinear(*args):
-  """GT_IsNonLinear(OGRwkbGeometryType arg0) -> int"""
+  """GT_IsNonLinear(OGRwkbGeometryType arg1) -> int"""
   return _ogr.GT_IsNonLinear(*args)
 
 def GT_GetCollection(*args):
@@ -5669,15 +7250,15 @@ def GetOpenDS(*args):
   return _ogr.GetOpenDS(*args)
 
 def Open(*args, **kwargs):
-  """Open(char utf8_path, int update = 0) -> DataSource"""
+  """Open(char const * utf8_path, int update=0) -> DataSource"""
   return _ogr.Open(*args, **kwargs)
 
 def OpenShared(*args, **kwargs):
-  """OpenShared(char utf8_path, int update = 0) -> DataSource"""
+  """OpenShared(char const * utf8_path, int update=0) -> DataSource"""
   return _ogr.OpenShared(*args, **kwargs)
 
 def GetDriverByName(*args):
-  """GetDriverByName(char name) -> Driver"""
+  """GetDriverByName(char const * name) -> Driver"""
   return _ogr.GetDriverByName(*args)
 
 def GetDriver(*args):
@@ -5685,12 +7266,13 @@ def GetDriver(*args):
   return _ogr.GetDriver(*args)
 
 def GeneralCmdLineProcessor(*args):
-  """GeneralCmdLineProcessor(char papszArgv, int nOptions = 0) -> char"""
+  """GeneralCmdLineProcessor(char ** papszArgv, int nOptions=0) -> char **"""
   return _ogr.GeneralCmdLineProcessor(*args)
 
 def TermProgress_nocb(*args, **kwargs):
-  """TermProgress_nocb(double dfProgress, char pszMessage = None, void pData = None) -> int"""
+  """TermProgress_nocb(double dfProgress, char const * pszMessage=None, void * pData=None) -> int"""
   return _ogr.TermProgress_nocb(*args, **kwargs)
 TermProgress = _ogr.TermProgress
+# This file is compatible with both classic and new-style classes.
 
 
diff --git a/swig/python/osgeo/osr.py b/swig/python/osgeo/osr.py
index d495c79..ea69494 100644
--- a/swig/python/osgeo/osr.py
+++ b/swig/python/osgeo/osr.py
@@ -1,9 +1,12 @@
 # This file was automatically generated by SWIG (http://www.swig.org).
-# Version 1.3.40
+# Version 2.0.12
 #
 # Do not make changes to this file unless you know what you are doing--modify
 # the SWIG interface file instead.
-# This file is compatible with both classic and new-style classes.
+
+
+
+
 
 from sys import version_info
 if version_info >= (2,6,0):
@@ -39,7 +42,7 @@ def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
             return
     method = class_type.__swig_setmethods__.get(name,None)
     if method: return method(self,value)
-    if (not static) or hasattr(self,name):
+    if (not static):
         self.__dict__[name] = value
     else:
         raise AttributeError("You cannot add attributes to %s" % self)
@@ -135,6 +138,7 @@ SRS_PT_WINKEL_TRIPEL = _osr.SRS_PT_WINKEL_TRIPEL
 SRS_PT_CRASTER_PARABOLIC = _osr.SRS_PT_CRASTER_PARABOLIC
 SRS_PT_LOXIMUTHAL = _osr.SRS_PT_LOXIMUTHAL
 SRS_PT_QUARTIC_AUTHALIC = _osr.SRS_PT_QUARTIC_AUTHALIC
+SRS_PT_SCH = _osr.SRS_PT_SCH
 SRS_PP_CENTRAL_MERIDIAN = _osr.SRS_PP_CENTRAL_MERIDIAN
 SRS_PP_SCALE_FACTOR = _osr.SRS_PP_SCALE_FACTOR
 SRS_PP_STANDARD_PARALLEL_1 = _osr.SRS_PP_STANDARD_PARALLEL_1
@@ -164,6 +168,10 @@ SRS_PP_LATITUDE_OF_1ST_POINT = _osr.SRS_PP_LATITUDE_OF_1ST_POINT
 SRS_PP_LONGITUDE_OF_1ST_POINT = _osr.SRS_PP_LONGITUDE_OF_1ST_POINT
 SRS_PP_LATITUDE_OF_2ND_POINT = _osr.SRS_PP_LATITUDE_OF_2ND_POINT
 SRS_PP_LONGITUDE_OF_2ND_POINT = _osr.SRS_PP_LONGITUDE_OF_2ND_POINT
+SRS_PP_PEG_POINT_LATITUDE = _osr.SRS_PP_PEG_POINT_LATITUDE
+SRS_PP_PEG_POINT_LONGITUDE = _osr.SRS_PP_PEG_POINT_LONGITUDE
+SRS_PP_PEG_POINT_HEADING = _osr.SRS_PP_PEG_POINT_HEADING
+SRS_PP_PEG_POINT_HEIGHT = _osr.SRS_PP_PEG_POINT_HEIGHT
 SRS_UL_METER = _osr.SRS_UL_METER
 SRS_UL_FOOT = _osr.SRS_UL_FOOT
 SRS_UL_FOOT_CONV = _osr.SRS_UL_FOOT_CONV
@@ -241,11 +249,11 @@ def DontUseExceptions(*args):
   return _osr.DontUseExceptions(*args)
 
 def GetWellKnownGeogCSAsWKT(*args):
-  """GetWellKnownGeogCSAsWKT(char name) -> OGRErr"""
+  """GetWellKnownGeogCSAsWKT(char const * name) -> OGRErr"""
   return _osr.GetWellKnownGeogCSAsWKT(*args)
 
 def GetUserInputAsWKT(*args):
-  """GetUserInputAsWKT(char name) -> OGRErr"""
+  """GetUserInputAsWKT(char const * name) -> OGRErr"""
   return _osr.GetUserInputAsWKT(*args)
 class SpatialReference(_object):
     """Proxy of C++ OSRSpatialReferenceShadow class"""
@@ -254,528 +262,483 @@ class SpatialReference(_object):
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, SpatialReference, name)
     __repr__ = _swig_repr
-    def __init__(self, *args, **kwargs): 
-        """__init__(self, char wkt = "") -> SpatialReference"""
+    def __init__(self, *args, **kwargs):
+        """__init__(OSRSpatialReferenceShadow self, char const * wkt="") -> SpatialReference"""
         this = _osr.new_SpatialReference(*args, **kwargs)
         try: self.this.append(this)
         except: self.this = this
     __swig_destroy__ = _osr.delete_SpatialReference
     __del__ = lambda self : None;
     def __str__(self, *args):
-        """__str__(self) -> retStringAndCPLFree"""
+        """__str__(SpatialReference self) -> retStringAndCPLFree *"""
         return _osr.SpatialReference___str__(self, *args)
 
     def IsSame(self, *args):
-        """IsSame(self, SpatialReference rhs) -> int"""
+        """IsSame(SpatialReference self, SpatialReference rhs) -> int"""
         return _osr.SpatialReference_IsSame(self, *args)
 
     def IsSameGeogCS(self, *args):
-        """IsSameGeogCS(self, SpatialReference rhs) -> int"""
+        """IsSameGeogCS(SpatialReference self, SpatialReference rhs) -> int"""
         return _osr.SpatialReference_IsSameGeogCS(self, *args)
 
     def IsSameVertCS(self, *args):
-        """IsSameVertCS(self, SpatialReference rhs) -> int"""
+        """IsSameVertCS(SpatialReference self, SpatialReference rhs) -> int"""
         return _osr.SpatialReference_IsSameVertCS(self, *args)
 
     def IsGeographic(self, *args):
-        """IsGeographic(self) -> int"""
+        """IsGeographic(SpatialReference self) -> int"""
         return _osr.SpatialReference_IsGeographic(self, *args)
 
     def IsProjected(self, *args):
-        """IsProjected(self) -> int"""
+        """IsProjected(SpatialReference self) -> int"""
         return _osr.SpatialReference_IsProjected(self, *args)
 
     def IsCompound(self, *args):
-        """IsCompound(self) -> int"""
+        """IsCompound(SpatialReference self) -> int"""
         return _osr.SpatialReference_IsCompound(self, *args)
 
     def IsGeocentric(self, *args):
-        """IsGeocentric(self) -> int"""
+        """IsGeocentric(SpatialReference self) -> int"""
         return _osr.SpatialReference_IsGeocentric(self, *args)
 
     def IsLocal(self, *args):
-        """IsLocal(self) -> int"""
+        """IsLocal(SpatialReference self) -> int"""
         return _osr.SpatialReference_IsLocal(self, *args)
 
     def IsVertical(self, *args):
-        """IsVertical(self) -> int"""
+        """IsVertical(SpatialReference self) -> int"""
         return _osr.SpatialReference_IsVertical(self, *args)
 
     def EPSGTreatsAsLatLong(self, *args):
-        """EPSGTreatsAsLatLong(self) -> int"""
+        """EPSGTreatsAsLatLong(SpatialReference self) -> int"""
         return _osr.SpatialReference_EPSGTreatsAsLatLong(self, *args)
 
     def EPSGTreatsAsNorthingEasting(self, *args):
-        """EPSGTreatsAsNorthingEasting(self) -> int"""
+        """EPSGTreatsAsNorthingEasting(SpatialReference self) -> int"""
         return _osr.SpatialReference_EPSGTreatsAsNorthingEasting(self, *args)
 
     def SetAuthority(self, *args):
-        """SetAuthority(self, char pszTargetKey, char pszAuthority, int nCode) -> OGRErr"""
+        """SetAuthority(SpatialReference self, char const * pszTargetKey, char const * pszAuthority, int nCode) -> OGRErr"""
         return _osr.SpatialReference_SetAuthority(self, *args)
 
     def GetAttrValue(self, *args):
-        """GetAttrValue(self, char name, int child = 0) -> char"""
+        """GetAttrValue(SpatialReference self, char const * name, int child=0) -> char const *"""
         return _osr.SpatialReference_GetAttrValue(self, *args)
 
     def SetAttrValue(self, *args):
-        """SetAttrValue(self, char name, char value) -> OGRErr"""
+        """SetAttrValue(SpatialReference self, char const * name, char const * value) -> OGRErr"""
         return _osr.SpatialReference_SetAttrValue(self, *args)
 
     def SetAngularUnits(self, *args):
-        """SetAngularUnits(self, char name, double to_radians) -> OGRErr"""
+        """SetAngularUnits(SpatialReference self, char const * name, double to_radians) -> OGRErr"""
         return _osr.SpatialReference_SetAngularUnits(self, *args)
 
     def GetAngularUnits(self, *args):
-        """GetAngularUnits(self) -> double"""
+        """GetAngularUnits(SpatialReference self) -> double"""
         return _osr.SpatialReference_GetAngularUnits(self, *args)
 
     def SetTargetLinearUnits(self, *args):
-        """SetTargetLinearUnits(self, char target, char name, double to_meters) -> OGRErr"""
+        """SetTargetLinearUnits(SpatialReference self, char const * target, char const * name, double to_meters) -> OGRErr"""
         return _osr.SpatialReference_SetTargetLinearUnits(self, *args)
 
     def SetLinearUnits(self, *args):
-        """SetLinearUnits(self, char name, double to_meters) -> OGRErr"""
+        """SetLinearUnits(SpatialReference self, char const * name, double to_meters) -> OGRErr"""
         return _osr.SpatialReference_SetLinearUnits(self, *args)
 
     def SetLinearUnitsAndUpdateParameters(self, *args):
-        """SetLinearUnitsAndUpdateParameters(self, char name, double to_meters) -> OGRErr"""
+        """SetLinearUnitsAndUpdateParameters(SpatialReference self, char const * name, double to_meters) -> OGRErr"""
         return _osr.SpatialReference_SetLinearUnitsAndUpdateParameters(self, *args)
 
     def GetLinearUnits(self, *args):
-        """GetLinearUnits(self) -> double"""
+        """GetLinearUnits(SpatialReference self) -> double"""
         return _osr.SpatialReference_GetLinearUnits(self, *args)
 
     def GetLinearUnitsName(self, *args):
-        """GetLinearUnitsName(self) -> char"""
+        """GetLinearUnitsName(SpatialReference self) -> char const *"""
         return _osr.SpatialReference_GetLinearUnitsName(self, *args)
 
     def GetAuthorityCode(self, *args):
-        """GetAuthorityCode(self, char target_key) -> char"""
+        """GetAuthorityCode(SpatialReference self, char const * target_key) -> char const *"""
         return _osr.SpatialReference_GetAuthorityCode(self, *args)
 
     def GetAuthorityName(self, *args):
-        """GetAuthorityName(self, char target_key) -> char"""
+        """GetAuthorityName(SpatialReference self, char const * target_key) -> char const *"""
         return _osr.SpatialReference_GetAuthorityName(self, *args)
 
     def SetUTM(self, *args):
-        """SetUTM(self, int zone, int north = 1) -> OGRErr"""
+        """SetUTM(SpatialReference self, int zone, int north=1) -> OGRErr"""
         return _osr.SpatialReference_SetUTM(self, *args)
 
     def GetUTMZone(self, *args):
-        """GetUTMZone(self) -> int"""
+        """GetUTMZone(SpatialReference self) -> int"""
         return _osr.SpatialReference_GetUTMZone(self, *args)
 
     def SetStatePlane(self, *args):
-        """SetStatePlane(self, int zone, int is_nad83 = 1, char unitsname = "", double units = 0.0) -> OGRErr"""
+        """SetStatePlane(SpatialReference self, int zone, int is_nad83=1, char const * unitsname="", double units=0.0) -> OGRErr"""
         return _osr.SpatialReference_SetStatePlane(self, *args)
 
     def AutoIdentifyEPSG(self, *args):
-        """AutoIdentifyEPSG(self) -> OGRErr"""
+        """AutoIdentifyEPSG(SpatialReference self) -> OGRErr"""
         return _osr.SpatialReference_AutoIdentifyEPSG(self, *args)
 
     def SetProjection(self, *args):
-        """SetProjection(self, char arg) -> OGRErr"""
+        """SetProjection(SpatialReference self, char const * arg) -> OGRErr"""
         return _osr.SpatialReference_SetProjection(self, *args)
 
     def SetProjParm(self, *args):
-        """SetProjParm(self, char name, double val) -> OGRErr"""
+        """SetProjParm(SpatialReference self, char const * name, double val) -> OGRErr"""
         return _osr.SpatialReference_SetProjParm(self, *args)
 
     def GetProjParm(self, *args):
-        """GetProjParm(self, char name, double default_val = 0.0) -> double"""
+        """GetProjParm(SpatialReference self, char const * name, double default_val=0.0) -> double"""
         return _osr.SpatialReference_GetProjParm(self, *args)
 
     def SetNormProjParm(self, *args):
-        """SetNormProjParm(self, char name, double val) -> OGRErr"""
+        """SetNormProjParm(SpatialReference self, char const * name, double val) -> OGRErr"""
         return _osr.SpatialReference_SetNormProjParm(self, *args)
 
     def GetNormProjParm(self, *args):
-        """GetNormProjParm(self, char name, double default_val = 0.0) -> double"""
+        """GetNormProjParm(SpatialReference self, char const * name, double default_val=0.0) -> double"""
         return _osr.SpatialReference_GetNormProjParm(self, *args)
 
     def GetSemiMajor(self, *args):
-        """GetSemiMajor(self) -> double"""
+        """GetSemiMajor(SpatialReference self) -> double"""
         return _osr.SpatialReference_GetSemiMajor(self, *args)
 
     def GetSemiMinor(self, *args):
-        """GetSemiMinor(self) -> double"""
+        """GetSemiMinor(SpatialReference self) -> double"""
         return _osr.SpatialReference_GetSemiMinor(self, *args)
 
     def GetInvFlattening(self, *args):
-        """GetInvFlattening(self) -> double"""
+        """GetInvFlattening(SpatialReference self) -> double"""
         return _osr.SpatialReference_GetInvFlattening(self, *args)
 
     def SetACEA(self, *args, **kwargs):
-        """
-        SetACEA(self, double stdp1, double stdp2, double clat, double clong, 
-            double fe, double fn) -> OGRErr
-        """
+        """SetACEA(SpatialReference self, double stdp1, double stdp2, double clat, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetACEA(self, *args, **kwargs)
 
     def SetAE(self, *args, **kwargs):
-        """SetAE(self, double clat, double clong, double fe, double fn) -> OGRErr"""
+        """SetAE(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetAE(self, *args, **kwargs)
 
     def SetBonne(self, *args, **kwargs):
-        """SetBonne(self, double stdp, double cm, double fe, double fn) -> OGRErr"""
+        """SetBonne(SpatialReference self, double stdp, double cm, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetBonne(self, *args, **kwargs)
 
     def SetCEA(self, *args, **kwargs):
-        """SetCEA(self, double stdp1, double cm, double fe, double fn) -> OGRErr"""
+        """SetCEA(SpatialReference self, double stdp1, double cm, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetCEA(self, *args, **kwargs)
 
     def SetCS(self, *args, **kwargs):
-        """SetCS(self, double clat, double clong, double fe, double fn) -> OGRErr"""
+        """SetCS(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetCS(self, *args, **kwargs)
 
     def SetEC(self, *args, **kwargs):
-        """
-        SetEC(self, double stdp1, double stdp2, double clat, double clong, 
-            double fe, double fn) -> OGRErr
-        """
+        """SetEC(SpatialReference self, double stdp1, double stdp2, double clat, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetEC(self, *args, **kwargs)
 
     def SetEckertIV(self, *args, **kwargs):
-        """SetEckertIV(self, double cm, double fe, double fn) -> OGRErr"""
+        """SetEckertIV(SpatialReference self, double cm, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetEckertIV(self, *args, **kwargs)
 
     def SetEckertVI(self, *args, **kwargs):
-        """SetEckertVI(self, double cm, double fe, double fn) -> OGRErr"""
+        """SetEckertVI(SpatialReference self, double cm, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetEckertVI(self, *args, **kwargs)
 
     def SetEquirectangular(self, *args, **kwargs):
-        """SetEquirectangular(self, double clat, double clong, double fe, double fn) -> OGRErr"""
+        """SetEquirectangular(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetEquirectangular(self, *args, **kwargs)
 
     def SetEquirectangular2(self, *args, **kwargs):
-        """
-        SetEquirectangular2(self, double clat, double clong, double pseudostdparallellat, 
-            double fe, double fn) -> OGRErr
-        """
+        """SetEquirectangular2(SpatialReference self, double clat, double clong, double pseudostdparallellat, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetEquirectangular2(self, *args, **kwargs)
 
     def SetGaussSchreiberTMercator(self, *args, **kwargs):
-        """SetGaussSchreiberTMercator(self, double clat, double clong, double sc, double fe, double fn) -> OGRErr"""
+        """SetGaussSchreiberTMercator(SpatialReference self, double clat, double clong, double sc, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetGaussSchreiberTMercator(self, *args, **kwargs)
 
     def SetGS(self, *args, **kwargs):
-        """SetGS(self, double cm, double fe, double fn) -> OGRErr"""
+        """SetGS(SpatialReference self, double cm, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetGS(self, *args, **kwargs)
 
     def SetGH(self, *args, **kwargs):
-        """SetGH(self, double cm, double fe, double fn) -> OGRErr"""
+        """SetGH(SpatialReference self, double cm, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetGH(self, *args, **kwargs)
 
     def SetIGH(self, *args):
-        """SetIGH(self) -> OGRErr"""
+        """SetIGH(SpatialReference self) -> OGRErr"""
         return _osr.SpatialReference_SetIGH(self, *args)
 
     def SetGEOS(self, *args, **kwargs):
-        """SetGEOS(self, double cm, double satelliteheight, double fe, double fn) -> OGRErr"""
+        """SetGEOS(SpatialReference self, double cm, double satelliteheight, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetGEOS(self, *args, **kwargs)
 
     def SetGnomonic(self, *args, **kwargs):
-        """SetGnomonic(self, double clat, double clong, double fe, double fn) -> OGRErr"""
+        """SetGnomonic(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetGnomonic(self, *args, **kwargs)
 
     def SetHOM(self, *args, **kwargs):
         """
-        SetHOM(self, double clat, double clong, double azimuth, double recttoskew, 
-            double scale, double fe, double fn) -> OGRErr
+        SetHOM(SpatialReference self, double clat, double clong, double azimuth, double recttoskew, double scale, double fe,
+            double fn) -> OGRErr
         """
         return _osr.SpatialReference_SetHOM(self, *args, **kwargs)
 
     def SetHOM2PNO(self, *args, **kwargs):
         """
-        SetHOM2PNO(self, double clat, double dfLat1, double dfLong1, double dfLat2, 
-            double dfLong2, double scale, double fe, 
-            double fn) -> OGRErr
+        SetHOM2PNO(SpatialReference self, double clat, double dfLat1, double dfLong1, double dfLat2, double dfLong2, double scale,
+            double fe, double fn) -> OGRErr
         """
         return _osr.SpatialReference_SetHOM2PNO(self, *args, **kwargs)
 
     def SetKrovak(self, *args, **kwargs):
         """
-        SetKrovak(self, double clat, double clong, double azimuth, double pseudostdparallellat, 
-            double scale, double fe, 
-            double fn) -> OGRErr
+        SetKrovak(SpatialReference self, double clat, double clong, double azimuth, double pseudostdparallellat, double scale,
+            double fe, double fn) -> OGRErr
         """
         return _osr.SpatialReference_SetKrovak(self, *args, **kwargs)
 
     def SetLAEA(self, *args, **kwargs):
-        """SetLAEA(self, double clat, double clong, double fe, double fn) -> OGRErr"""
+        """SetLAEA(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetLAEA(self, *args, **kwargs)
 
     def SetLCC(self, *args, **kwargs):
-        """
-        SetLCC(self, double stdp1, double stdp2, double clat, double clong, 
-            double fe, double fn) -> OGRErr
-        """
+        """SetLCC(SpatialReference self, double stdp1, double stdp2, double clat, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetLCC(self, *args, **kwargs)
 
     def SetLCC1SP(self, *args, **kwargs):
-        """
-        SetLCC1SP(self, double clat, double clong, double scale, double fe, 
-            double fn) -> OGRErr
-        """
+        """SetLCC1SP(SpatialReference self, double clat, double clong, double scale, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetLCC1SP(self, *args, **kwargs)
 
     def SetLCCB(self, *args, **kwargs):
-        """
-        SetLCCB(self, double stdp1, double stdp2, double clat, double clong, 
-            double fe, double fn) -> OGRErr
-        """
+        """SetLCCB(SpatialReference self, double stdp1, double stdp2, double clat, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetLCCB(self, *args, **kwargs)
 
     def SetMC(self, *args, **kwargs):
-        """SetMC(self, double clat, double clong, double fe, double fn) -> OGRErr"""
+        """SetMC(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetMC(self, *args, **kwargs)
 
     def SetMercator(self, *args, **kwargs):
-        """
-        SetMercator(self, double clat, double clong, double scale, double fe, 
-            double fn) -> OGRErr
-        """
+        """SetMercator(SpatialReference self, double clat, double clong, double scale, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetMercator(self, *args, **kwargs)
 
     def SetMollweide(self, *args, **kwargs):
-        """SetMollweide(self, double cm, double fe, double fn) -> OGRErr"""
+        """SetMollweide(SpatialReference self, double cm, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetMollweide(self, *args, **kwargs)
 
     def SetNZMG(self, *args, **kwargs):
-        """SetNZMG(self, double clat, double clong, double fe, double fn) -> OGRErr"""
+        """SetNZMG(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetNZMG(self, *args, **kwargs)
 
     def SetOS(self, *args, **kwargs):
-        """
-        SetOS(self, double dfOriginLat, double dfCMeridian, double scale, 
-            double fe, double fn) -> OGRErr
-        """
+        """SetOS(SpatialReference self, double dfOriginLat, double dfCMeridian, double scale, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetOS(self, *args, **kwargs)
 
     def SetOrthographic(self, *args, **kwargs):
-        """SetOrthographic(self, double clat, double clong, double fe, double fn) -> OGRErr"""
+        """SetOrthographic(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetOrthographic(self, *args, **kwargs)
 
     def SetPolyconic(self, *args, **kwargs):
-        """SetPolyconic(self, double clat, double clong, double fe, double fn) -> OGRErr"""
+        """SetPolyconic(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetPolyconic(self, *args, **kwargs)
 
     def SetPS(self, *args, **kwargs):
-        """
-        SetPS(self, double clat, double clong, double scale, double fe, 
-            double fn) -> OGRErr
-        """
+        """SetPS(SpatialReference self, double clat, double clong, double scale, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetPS(self, *args, **kwargs)
 
     def SetRobinson(self, *args, **kwargs):
-        """SetRobinson(self, double clong, double fe, double fn) -> OGRErr"""
+        """SetRobinson(SpatialReference self, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetRobinson(self, *args, **kwargs)
 
     def SetSinusoidal(self, *args, **kwargs):
-        """SetSinusoidal(self, double clong, double fe, double fn) -> OGRErr"""
+        """SetSinusoidal(SpatialReference self, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetSinusoidal(self, *args, **kwargs)
 
     def SetStereographic(self, *args, **kwargs):
-        """
-        SetStereographic(self, double clat, double clong, double scale, double fe, 
-            double fn) -> OGRErr
-        """
+        """SetStereographic(SpatialReference self, double clat, double clong, double scale, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetStereographic(self, *args, **kwargs)
 
     def SetSOC(self, *args, **kwargs):
-        """SetSOC(self, double latitudeoforigin, double cm, double fe, double fn) -> OGRErr"""
+        """SetSOC(SpatialReference self, double latitudeoforigin, double cm, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetSOC(self, *args, **kwargs)
 
     def SetTM(self, *args, **kwargs):
-        """
-        SetTM(self, double clat, double clong, double scale, double fe, 
-            double fn) -> OGRErr
-        """
+        """SetTM(SpatialReference self, double clat, double clong, double scale, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetTM(self, *args, **kwargs)
 
     def SetTMVariant(self, *args, **kwargs):
         """
-        SetTMVariant(self, char pszVariantName, double clat, double clong, double scale, 
-            double fe, double fn) -> OGRErr
+        SetTMVariant(SpatialReference self, char const * pszVariantName, double clat, double clong, double scale, double fe,
+            double fn) -> OGRErr
         """
         return _osr.SpatialReference_SetTMVariant(self, *args, **kwargs)
 
     def SetTMG(self, *args, **kwargs):
-        """SetTMG(self, double clat, double clong, double fe, double fn) -> OGRErr"""
+        """SetTMG(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetTMG(self, *args, **kwargs)
 
     def SetTMSO(self, *args, **kwargs):
-        """
-        SetTMSO(self, double clat, double clong, double scale, double fe, 
-            double fn) -> OGRErr
-        """
+        """SetTMSO(SpatialReference self, double clat, double clong, double scale, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetTMSO(self, *args, **kwargs)
 
     def SetVDG(self, *args, **kwargs):
-        """SetVDG(self, double clong, double fe, double fn) -> OGRErr"""
+        """SetVDG(SpatialReference self, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetVDG(self, *args, **kwargs)
 
     def SetWellKnownGeogCS(self, *args):
-        """SetWellKnownGeogCS(self, char name) -> OGRErr"""
+        """SetWellKnownGeogCS(SpatialReference self, char const * name) -> OGRErr"""
         return _osr.SpatialReference_SetWellKnownGeogCS(self, *args)
 
     def SetFromUserInput(self, *args):
-        """SetFromUserInput(self, char name) -> OGRErr"""
+        """SetFromUserInput(SpatialReference self, char const * name) -> OGRErr"""
         return _osr.SpatialReference_SetFromUserInput(self, *args)
 
     def CopyGeogCSFrom(self, *args):
-        """CopyGeogCSFrom(self, SpatialReference rhs) -> OGRErr"""
+        """CopyGeogCSFrom(SpatialReference self, SpatialReference rhs) -> OGRErr"""
         return _osr.SpatialReference_CopyGeogCSFrom(self, *args)
 
     def SetTOWGS84(self, *args):
-        """
-        SetTOWGS84(self, double p1, double p2, double p3, double p4 = 0.0, double p5 = 0.0, 
-            double p6 = 0.0, double p7 = 0.0) -> OGRErr
-        """
+        """SetTOWGS84(SpatialReference self, double p1, double p2, double p3, double p4=0.0, double p5=0.0, double p6=0.0, double p7=0.0) -> OGRErr"""
         return _osr.SpatialReference_SetTOWGS84(self, *args)
 
     def GetTOWGS84(self, *args):
-        """GetTOWGS84(self) -> OGRErr"""
+        """GetTOWGS84(SpatialReference self) -> OGRErr"""
         return _osr.SpatialReference_GetTOWGS84(self, *args)
 
     def SetLocalCS(self, *args):
-        """SetLocalCS(self, char pszName) -> OGRErr"""
+        """SetLocalCS(SpatialReference self, char const * pszName) -> OGRErr"""
         return _osr.SpatialReference_SetLocalCS(self, *args)
 
     def SetGeogCS(self, *args):
         """
-        SetGeogCS(self, char pszGeogName, char pszDatumName, char pszEllipsoidName, 
-            double dfSemiMajor, double dfInvFlattening, 
-            char pszPMName = "Greenwich", double dfPMOffset = 0.0, 
-            char pszUnits = "degree", double dfConvertToRadians = 0.0174532925199433) -> OGRErr
+        SetGeogCS(SpatialReference self, char const * pszGeogName, char const * pszDatumName, char const * pszEllipsoidName,
+            double dfSemiMajor, double dfInvFlattening, char const * pszPMName="Greenwich",
+            double dfPMOffset=0.0, char const * pszUnits="degree", double dfConvertToRadians=0.0174532925199433) -> OGRErr
         """
         return _osr.SpatialReference_SetGeogCS(self, *args)
 
     def SetProjCS(self, *args):
-        """SetProjCS(self, char name = "unnamed") -> OGRErr"""
+        """SetProjCS(SpatialReference self, char const * name="unnamed") -> OGRErr"""
         return _osr.SpatialReference_SetProjCS(self, *args)
 
     def SetGeocCS(self, *args):
-        """SetGeocCS(self, char name = "unnamed") -> OGRErr"""
+        """SetGeocCS(SpatialReference self, char const * name="unnamed") -> OGRErr"""
         return _osr.SpatialReference_SetGeocCS(self, *args)
 
     def SetVertCS(self, *args):
-        """
-        SetVertCS(self, char VertCSName = "unnamed", char VertDatumName = "unnamed", 
-            int VertDatumType = 0) -> OGRErr
-        """
+        """SetVertCS(SpatialReference self, char const * VertCSName="unnamed", char const * VertDatumName="unnamed", int VertDatumType=0) -> OGRErr"""
         return _osr.SpatialReference_SetVertCS(self, *args)
 
     def SetCompoundCS(self, *args):
-        """SetCompoundCS(self, char name, SpatialReference horizcs, SpatialReference vertcs) -> OGRErr"""
+        """SetCompoundCS(SpatialReference self, char const * name, SpatialReference horizcs, SpatialReference vertcs) -> OGRErr"""
         return _osr.SpatialReference_SetCompoundCS(self, *args)
 
     def ImportFromWkt(self, *args):
-        """ImportFromWkt(self, char ppszInput) -> OGRErr"""
+        """ImportFromWkt(SpatialReference self, char ** ppszInput) -> OGRErr"""
         return _osr.SpatialReference_ImportFromWkt(self, *args)
 
     def ImportFromProj4(self, *args):
-        """ImportFromProj4(self, char ppszInput) -> OGRErr"""
+        """ImportFromProj4(SpatialReference self, char * ppszInput) -> OGRErr"""
         return _osr.SpatialReference_ImportFromProj4(self, *args)
 
     def ImportFromUrl(self, *args):
-        """ImportFromUrl(self, char url) -> OGRErr"""
+        """ImportFromUrl(SpatialReference self, char * url) -> OGRErr"""
         return _osr.SpatialReference_ImportFromUrl(self, *args)
 
     def ImportFromESRI(self, *args):
-        """ImportFromESRI(self, char ppszInput) -> OGRErr"""
+        """ImportFromESRI(SpatialReference self, char ** ppszInput) -> OGRErr"""
         return _osr.SpatialReference_ImportFromESRI(self, *args)
 
     def ImportFromEPSG(self, *args):
-        """ImportFromEPSG(self, int arg) -> OGRErr"""
+        """ImportFromEPSG(SpatialReference self, int arg) -> OGRErr"""
         return _osr.SpatialReference_ImportFromEPSG(self, *args)
 
     def ImportFromEPSGA(self, *args):
-        """ImportFromEPSGA(self, int arg) -> OGRErr"""
+        """ImportFromEPSGA(SpatialReference self, int arg) -> OGRErr"""
         return _osr.SpatialReference_ImportFromEPSGA(self, *args)
 
     def ImportFromPCI(self, *args):
-        """ImportFromPCI(self, char proj, char units = "METRE", double argin = 0) -> OGRErr"""
+        """ImportFromPCI(SpatialReference self, char const * proj, char const * units="METRE", double [17] argin=0) -> OGRErr"""
         return _osr.SpatialReference_ImportFromPCI(self, *args)
 
     def ImportFromUSGS(self, *args):
-        """ImportFromUSGS(self, long proj_code, long zone = 0, double argin = 0, long datum_code = 0) -> OGRErr"""
+        """ImportFromUSGS(SpatialReference self, long proj_code, long zone=0, double [15] argin=0, long datum_code=0) -> OGRErr"""
         return _osr.SpatialReference_ImportFromUSGS(self, *args)
 
     def ImportFromXML(self, *args):
-        """ImportFromXML(self, char xmlString) -> OGRErr"""
+        """ImportFromXML(SpatialReference self, char const * xmlString) -> OGRErr"""
         return _osr.SpatialReference_ImportFromXML(self, *args)
 
     def ImportFromERM(self, *args):
-        """ImportFromERM(self, char proj, char datum, char units) -> OGRErr"""
+        """ImportFromERM(SpatialReference self, char const * proj, char const * datum, char const * units) -> OGRErr"""
         return _osr.SpatialReference_ImportFromERM(self, *args)
 
     def ImportFromMICoordSys(self, *args):
-        """ImportFromMICoordSys(self, char pszCoordSys) -> OGRErr"""
+        """ImportFromMICoordSys(SpatialReference self, char const * pszCoordSys) -> OGRErr"""
         return _osr.SpatialReference_ImportFromMICoordSys(self, *args)
 
     def ImportFromOzi(self, *args):
-        """ImportFromOzi(self, char papszLines) -> OGRErr"""
+        """ImportFromOzi(SpatialReference self, char const *const * papszLines) -> OGRErr"""
         return _osr.SpatialReference_ImportFromOzi(self, *args)
 
     def ExportToWkt(self, *args):
-        """ExportToWkt(self) -> OGRErr"""
+        """ExportToWkt(SpatialReference self) -> OGRErr"""
         return _osr.SpatialReference_ExportToWkt(self, *args)
 
     def ExportToPrettyWkt(self, *args):
-        """ExportToPrettyWkt(self, int simplify = 0) -> OGRErr"""
+        """ExportToPrettyWkt(SpatialReference self, int simplify=0) -> OGRErr"""
         return _osr.SpatialReference_ExportToPrettyWkt(self, *args)
 
     def ExportToProj4(self, *args):
-        """ExportToProj4(self) -> OGRErr"""
+        """ExportToProj4(SpatialReference self) -> OGRErr"""
         return _osr.SpatialReference_ExportToProj4(self, *args)
 
     def ExportToPCI(self, *args):
-        """ExportToPCI(self) -> OGRErr"""
+        """ExportToPCI(SpatialReference self) -> OGRErr"""
         return _osr.SpatialReference_ExportToPCI(self, *args)
 
     def ExportToUSGS(self, *args):
-        """ExportToUSGS(self) -> OGRErr"""
+        """ExportToUSGS(SpatialReference self) -> OGRErr"""
         return _osr.SpatialReference_ExportToUSGS(self, *args)
 
     def ExportToXML(self, *args):
-        """ExportToXML(self, char dialect = "") -> OGRErr"""
+        """ExportToXML(SpatialReference self, char const * dialect="") -> OGRErr"""
         return _osr.SpatialReference_ExportToXML(self, *args)
 
     def ExportToMICoordSys(self, *args):
-        """ExportToMICoordSys(self) -> OGRErr"""
+        """ExportToMICoordSys(SpatialReference self) -> OGRErr"""
         return _osr.SpatialReference_ExportToMICoordSys(self, *args)
 
     def CloneGeogCS(self, *args):
-        """CloneGeogCS(self) -> SpatialReference"""
+        """CloneGeogCS(SpatialReference self) -> SpatialReference"""
         return _osr.SpatialReference_CloneGeogCS(self, *args)
 
     def Clone(self, *args):
-        """Clone(self) -> SpatialReference"""
+        """Clone(SpatialReference self) -> SpatialReference"""
         return _osr.SpatialReference_Clone(self, *args)
 
     def Validate(self, *args):
-        """Validate(self) -> OGRErr"""
+        """Validate(SpatialReference self) -> OGRErr"""
         return _osr.SpatialReference_Validate(self, *args)
 
     def StripCTParms(self, *args):
-        """StripCTParms(self) -> OGRErr"""
+        """StripCTParms(SpatialReference self) -> OGRErr"""
         return _osr.SpatialReference_StripCTParms(self, *args)
 
     def FixupOrdering(self, *args):
-        """FixupOrdering(self) -> OGRErr"""
+        """FixupOrdering(SpatialReference self) -> OGRErr"""
         return _osr.SpatialReference_FixupOrdering(self, *args)
 
     def Fixup(self, *args):
-        """Fixup(self) -> OGRErr"""
+        """Fixup(SpatialReference self) -> OGRErr"""
         return _osr.SpatialReference_Fixup(self, *args)
 
     def MorphToESRI(self, *args):
-        """MorphToESRI(self) -> OGRErr"""
+        """MorphToESRI(SpatialReference self) -> OGRErr"""
         return _osr.SpatialReference_MorphToESRI(self, *args)
 
     def MorphFromESRI(self, *args):
-        """MorphFromESRI(self) -> OGRErr"""
+        """MorphFromESRI(SpatialReference self) -> OGRErr"""
         return _osr.SpatialReference_MorphFromESRI(self, *args)
 
 SpatialReference_swigregister = _osr.SpatialReference_swigregister
@@ -789,8 +752,8 @@ class CoordinateTransformation(_object):
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, CoordinateTransformation, name)
     __repr__ = _swig_repr
-    def __init__(self, *args): 
-        """__init__(self, SpatialReference src, SpatialReference dst) -> CoordinateTransformation"""
+    def __init__(self, *args):
+        """__init__(OSRCoordinateTransformationShadow self, SpatialReference src, SpatialReference dst) -> CoordinateTransformation"""
         this = _osr.new_CoordinateTransformation(*args)
         try: self.this.append(this)
         except: self.this = this
@@ -798,13 +761,13 @@ class CoordinateTransformation(_object):
     __del__ = lambda self : None;
     def TransformPoint(self, *args):
         """
-        TransformPoint(self, double inout)
-        TransformPoint(self, double x, double y, double z = 0.0)
+        TransformPoint(CoordinateTransformation self, double [3] inout)
+        TransformPoint(CoordinateTransformation self, double x, double y, double z=0.0)
         """
         return _osr.CoordinateTransformation_TransformPoint(self, *args)
 
     def TransformPoints(self, *args):
-        """TransformPoints(self, int nCount)"""
+        """TransformPoints(CoordinateTransformation self, int nCount)"""
         return _osr.CoordinateTransformation_TransformPoints(self, *args)
 
 CoordinateTransformation_swigregister = _osr.CoordinateTransformation_swigregister
@@ -814,5 +777,6 @@ CoordinateTransformation_swigregister(CoordinateTransformation)
 def CreateCoordinateTransformation(*args):
   """CreateCoordinateTransformation(SpatialReference src, SpatialReference dst) -> CoordinateTransformation"""
   return _osr.CreateCoordinateTransformation(*args)
+# This file is compatible with both classic and new-style classes.
 
 
diff --git a/swig/python/samples/README b/swig/python/samples/README
index ea5d3e4..164efe1 100644
--- a/swig/python/samples/README
+++ b/swig/python/samples/README
@@ -8,7 +8,7 @@ assemblepoly.py		Script demonstrates how to assemble polygons from
 			arcs.  Demonstrates various aspects of OGR Python API.
 
 attachpct.py		Simple command line program for copying the color table of a
-                    raster into another raster.
+                        raster into another raster.
 
 fft.py			Script to perform forward and inverse two-dimensional
 			fast Fourier transform.
@@ -41,7 +41,7 @@ load2odbc.py		Load ODBC table to an ODBC datastore.  Uses direct SQL
 			since the ODBC driver is read-only for OGR.
 
 rel.py			Script to produce a shaded relief image from the
-			elevation data. (similar functionnality in gdaldem now)
+			elevation data. (similar functionality in gdaldem now)
 
 tigerpoly.py		Script demonstrating how to assemble polygons from
 			arcs in TIGER/Line datasource, writing results to
@@ -61,7 +61,7 @@ vec_tr.py		Example of applying some algorithm to all the
 			geometries in the file, such as a fixed offset.
 
 vec_tr_spat.py		Example of using Intersect() to filter based on 
-			only those features that truely intersect a given
+			only those features that truly intersect a given
 			rectangle.  Easily extended to general polygon!
 
 classify.py             Demonstrates using numpy for simple range based
@@ -74,7 +74,7 @@ gdal_lut.py             Read a LUT from a text file, and apply it to an image.
 magphase.py             Example script computing magnitude and phase images
                         from a complex image.
 
-hsv_merge.py            Merge greyscale image into rgb image as intensity
+hsv_merge.py            Merge greyscale image into RGB image as intensity
                         in HSV space.
 
 val_at_coord.py         Outputs the value of the raster bands at a given
diff --git a/swig/python/samples/assemblepoly.py b/swig/python/samples/assemblepoly.py
index f6b89c7..d4f210c 100755
--- a/swig/python/samples/assemblepoly.py
+++ b/swig/python/samples/assemblepoly.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: assemblepoly.py 28391 2015-01-30 19:57:31Z rouault $
+# $Id: assemblepoly.py 33791 2016-03-26 12:51:23Z goatbar $
 #
 # Project:  OGR Python samples
 # Purpose:  Assemble polygon geometries from arcs fulled from an arc layer.
@@ -10,7 +10,7 @@
 #
 ###############################################################################
 # Copyright (c) 2003, Frank Warmerdam <warmerdam at pobox.com>
-# 
+#
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
 # to deal in the Software without restriction, including without limitation
@@ -30,10 +30,7 @@
 # DEALINGS IN THE SOFTWARE.
 ###############################################################################
 
-try:
-    from osgeo import ogr
-except ImportError:
-    import ogr
+from osgeo import ogr
 
 #############################################################################-
 # Open the datasource to operate on.
@@ -77,7 +74,7 @@ print('Got %d lines.' % len(lines_hash))
 
 
 #############################################################################
-# Read all polygon features. 
+# Read all polygon features.
 
 feat = poly_layer.GetNextFeature()
 link_field = feat.GetFieldIndex( 'GEOM_ID_OF_LINK' )
@@ -108,7 +105,7 @@ while feat is not None:
         print(poly.ExportToWkt())
         feat.SetGeometryDirectly( poly )
     except:
-        print('BuildPolygonFromEdges failed.') 
+        print('BuildPolygonFromEdges failed.')
 
 # For now we don't actually write back the assembled polygons.
 #    poly_layer.SetFeature( feat )
diff --git a/swig/python/samples/attachpct.py b/swig/python/samples/attachpct.py
index 3d5026d..f28f76f 100755
--- a/swig/python/samples/attachpct.py
+++ b/swig/python/samples/attachpct.py
@@ -1,26 +1,26 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #******************************************************************************
-#  $Id: attachpct.py 28391 2015-01-30 19:57:31Z rouault $
-# 
+#  $Id: attachpct.py 33791 2016-03-26 12:51:23Z goatbar $
+#
 #  Project:  GDAL
 #  Purpose:  Simple command line program for copying the color table of a
 #            raster into another raster.
 #  Author:   Frank Warmerdam, warmerda at home.com
-# 
+#
 #******************************************************************************
 #  Copyright (c) 2000, Frank Warmerdam
-# 
+#
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
 #  to deal in the Software without restriction, including without limitation
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -30,13 +30,10 @@
 #  DEALINGS IN THE SOFTWARE.
 #******************************************************************************
 
-try:
-    from osgeo import gdal
-except ImportError:
-    import gdal
-
 import sys
 
+from osgeo import gdal
+
 if len(sys.argv) < 3:
     print('Usage: attachpct.py <pctfile> <infile> <outfile>')
     sys.exit(1)
@@ -56,7 +53,7 @@ ct = ct.Clone()
 ds = None
 
 # =============================================================================
-# Create a MEM clone of the source file. 
+# Create a MEM clone of the source file.
 # =============================================================================
 
 src_ds = gdal.Open( sys.argv[2] )
@@ -71,7 +68,7 @@ mem_ds.GetRasterBand(1).SetRasterColorTable( ct )
 mem_ds.GetRasterBand(1).SetRasterColorInterpretation( gdal.GCI_PaletteIndex )
 
 # =============================================================================
-# Write the dataset to the output file. 
+# Write the dataset to the output file.
 # =============================================================================
 
 drv = gdal.GetDriverByName( 'GTiff' )
diff --git a/swig/python/samples/build_jp2_from_xml.py b/swig/python/samples/build_jp2_from_xml.py
index d0a0be7..0589585 100644
--- a/swig/python/samples/build_jp2_from_xml.py
+++ b/swig/python/samples/build_jp2_from_xml.py
@@ -1,26 +1,26 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #******************************************************************************
-#  $Id: build_jp2_from_xml.py 29270 2015-06-01 13:35:43Z rouault $
-# 
+#  $Id: build_jp2_from_xml.py 32002 2015-12-05 06:03:16Z goatbar $
+#
 #  Project:  GDAL
 #  Purpose:  Build a JPEG2000 file from the XML structure dumped by dump_jp2.py
 #            Mostly useful to build non-conformant files
 #  Author:   Even Rouault, <even dot rouault at spatialys dot com>
-# 
+#
 #******************************************************************************
 #  Copyright (c) 2015, European Union (European Environment Agency)
-# 
+#
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
 #  to deal in the Software without restriction, including without limitation
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -31,8 +31,9 @@
 #******************************************************************************
 
 import os
-import sys
 import struct
+import sys
+
 from osgeo import gdal
 
 XML_TYPE_IDX = 0
@@ -315,7 +316,7 @@ def parse_jp2_box(xml_tree, out_f, src_jp2file):
 
         vrt_ds = gdal.Open(serialized_xml_content)
         if vrt_ds is None:
-            print('Cannot decode VRTDataset. Outputing empty content')
+            print('Cannot decode VRTDataset. Outputting empty content')
             binary_content = ''
         else:
             gdal.GetDriverByName('GTiff').CreateCopy('/vsimem/out.tif', vrt_ds)
diff --git a/swig/python/samples/classify.py b/swig/python/samples/classify.py
index b0a3d3d..c55d695 100755
--- a/swig/python/samples/classify.py
+++ b/swig/python/samples/classify.py
@@ -1,23 +1,23 @@
 #!/usr/bin/env python
 #******************************************************************************
-# 
+#
 #  Project:  GDAL
 #  Purpose:  Example doing range based classification
 #  Author:   Frank Warmerdam, warmerdam at pobox.com
-# 
+#
 #******************************************************************************
 #  Copyright (c) 2008, Frank Warmerdam <warmerdam at pobox.com>
-# 
+#
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
 #  to deal in the Software without restriction, including without limitation
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -53,7 +53,7 @@ for class_info in class_defs:
     class_end = class_info[2]
 
     class_value = numpy.ones((ysize,xsize)) * class_id
-    
+
     mask = numpy.bitwise_and(
         numpy.greater_equal(src_image,class_start),
         numpy.less_equal(src_image,class_end))
diff --git a/swig/python/samples/crs2crs2grid.py b/swig/python/samples/crs2crs2grid.py
index 98e0078..2bb5bea 100755
--- a/swig/python/samples/crs2crs2grid.py
+++ b/swig/python/samples/crs2crs2grid.py
@@ -34,7 +34,8 @@ import os
 import numpy
 import sys
 
-from osgeo import gdal, gdal_array
+from osgeo import gdal
+from osgeo import gdal_array
 
 # Input looks like this:
 """
@@ -140,7 +141,6 @@ def write_grid(grid,out_filename):
             fd_out.write('%f %f 0 "PNT_%d_%d"\n' % (grid[1,j,i],grid[0,j,i],i,j))
     fd_out.close()
 
-    
 ##############################################################################
 # Write the resulting grid out in GeoTIFF format.
 def write_gdal_grid(filename, grid, griddef ):
@@ -161,7 +161,7 @@ def write_control( control_fn, out_grid_fn, in_grid_fn,
                    dst_crs_id, dst_crs_date ):
 
     # start_date, end_date should be something like "2011.0"
-    
+
     control_template = """
 4
 %s
@@ -178,7 +178,7 @@ def write_control( control_fn, out_grid_fn, in_grid_fn,
 """
 
     control_filled = control_template % ( out_grid_fn,
-                                          src_crs_id, 
+                                          src_crs_id,
                                           dst_crs_id,
                                           src_crs_date,
                                           dst_crs_date,
@@ -208,57 +208,57 @@ eg.
         print("""
 The output file will be in CTable2 format suitable for use with PROJ.4
 +nadgrids= directive.
- 
+
 Format dates like 2002.0 (for the start of 2002)
 
 CRS Ids
 -------
-  1...NAD_83(2011) (North America tectonic plate fixed) 
-  29...NAD_83(CORS96)  (NAD_83(2011) will be used) 
-  30...NAD_83(2007)    (NAD_83(2011) will be used) 
-  2...NAD_83(PA11) (Pacific tectonic plate fixed) 
-  31...NAD_83(PACP00)  (NAD 83(PA11) will be used) 
-  3...NAD_83(MA11) (Mariana tectonic plate fixed) 
-  32...NAD_83(MARP00)  (NAD_83(MA11) will be used) 
-                                                   
-  4...WGS_72                             16...ITRF92 
-  5...WGS_84(transit) = NAD_83(2011)     17...ITRF93 
-  6...WGS_84(G730) = ITRF92              18...ITRF94 = ITRF96 
-  7...WGS_84(G873) = ITRF96              19...ITRF96 
-  8...WGS_84(G1150) = ITRF2000           20...ITRF97 
-  9...PNEOS_90 = ITRF90                  21...IGS97 = ITRF97 
- 10...NEOS_90 = ITRF90                   22...ITRF2000 
- 11...SIO/MIT_92 = ITRF91                23...IGS00 = ITRF2000 
- 12...ITRF88                             24...IGb00 = ITRF2000 
- 13...ITRF89                             25...ITRF2005 
- 14...ITRF90                             26...IGS05 = ITRF2005 
- 15...ITRF91                             27...ITRF2008 
-                                         28...IGS08 = ITRF2008 
+  1...NAD_83(2011) (North America tectonic plate fixed)
+  29...NAD_83(CORS96)  (NAD_83(2011) will be used)
+  30...NAD_83(2007)    (NAD_83(2011) will be used)
+  2...NAD_83(PA11) (Pacific tectonic plate fixed)
+  31...NAD_83(PACP00)  (NAD 83(PA11) will be used)
+  3...NAD_83(MA11) (Mariana tectonic plate fixed)
+  32...NAD_83(MARP00)  (NAD_83(MA11) will be used)
+
+  4...WGS_72                             16...ITRF92
+  5...WGS_84(transit) = NAD_83(2011)     17...ITRF93
+  6...WGS_84(G730) = ITRF92              18...ITRF94 = ITRF96
+  7...WGS_84(G873) = ITRF96              19...ITRF96
+  8...WGS_84(G1150) = ITRF2000           20...ITRF97
+  9...PNEOS_90 = ITRF90                  21...IGS97 = ITRF97
+ 10...NEOS_90 = ITRF90                   22...ITRF2000
+ 11...SIO/MIT_92 = ITRF91                23...IGS00 = ITRF2000
+ 12...ITRF88                             24...IGb00 = ITRF2000
+ 13...ITRF89                             25...ITRF2005
+ 14...ITRF90                             26...IGS05 = ITRF2005
+ 15...ITRF91                             27...ITRF2008
+                                         28...IGS08 = ITRF2008
 """)
 
     sys.exit(1)
-    
+
 #############################################################################
 # Main
 
 if __name__ == '__main__':
 
     # Default GDAL argument parsing.
-    
+
     argv = gdal.GeneralCmdLineProcessor( sys.argv )
     if argv is None:
         sys.exit( 0 )
 
     if len(argv) == 1:
         Usage(brief=0)
-        
+
     # Script argument defaults
     src_crs_id = None
     src_crs_date = None
     dst_crs_id = None
     dst_crs_date = None
 
-    # Decent representation of continental US 
+    # Decent representation of continental US
     griddef = (-127.0, 50.0, -66.0, 25.0, 611, 251 )
 
     htdp_path = 'htdp'
@@ -321,19 +321,19 @@ if __name__ == '__main__':
         i = i + 1
         # next argument
 
-
     if output_grid_name is None:
         print('Missing output grid name (-o)')
         Usage()
 
     if dst_crs_date is None:
-        print('Source and Destination CRS Ids and Dates are manditory, not all provided.')
+        print('Source and Destination CRS Ids and Dates are mandatory, '
+              'not all provided.')
         Usage()
 
     # Do a bit of validation of parameters.
     if src_crs_id < 1 or src_crs_id > 32 \
        or dst_crs_id < 1 or dst_crs_id > 32:
-        print('Invalid source or destination CRS Id %d and %d.' \
+        print('Invalid source or destination CRS Id %d and %d.'
               % (src_crs_id, dst_crs_id))
         Usage(brief=0)
 
diff --git a/swig/python/samples/densify.py b/swig/python/samples/densify.py
index e41a2f2..f995ae1 100755
--- a/swig/python/samples/densify.py
+++ b/swig/python/samples/densify.py
@@ -1,18 +1,12 @@
 #!/usr/bin/env python
 
-try:
-    from osgeo import osr
-    from osgeo import ogr
-    ogr.UseExceptions()
-except ImportError:
-    import osr
-    import ogr
-
-import sys
-import os
 import math
+import os
+import sys
 
-
+from osgeo import osr
+from osgeo import ogr
+ogr.UseExceptions()
 
 
 class Translator(object):
@@ -27,7 +21,7 @@ class Translator(object):
         g.add_option("-o", "--output", dest='output',
                           help="OGR output data source", metavar="OUTPUT")
         g.add_option("-n", "--nooverwrite",
-                          action="store_false", dest="overwrite", 
+                          action="store_false", dest="overwrite",
                           help="Do not overwrite the existing output file")
 
         g.add_option("-f", "--driver", dest='driver',
@@ -39,10 +33,10 @@ class Translator(object):
                           help="""Spatial query extents -- minx miny maxx maxy""",
                           type=float, nargs=4)
         g.add_option('-l', "--layer", dest="layer",
-                          help="""The name of the input layer to translate, if not given, the first layer on the data source is used""",)                          
+                          help="""The name of the input layer to translate, if not given, the first layer on the data source is used""",)
 
         g.add_option('-k', "--select", dest="fields",
-                          help="""Comma separated list of fields to include -- field1,field2,field3,...,fieldn""",)                          
+                          help="""Comma separated list of fields to include -- field1,field2,field3,...,fieldn""",)
         g.add_option('-t', '--target-srs', dest="t_srs",
                           help="""Target SRS -- the spatial reference system to project the data to""")
         g.add_option('-a', '--assign-srs', dest="a_srs",
@@ -61,11 +55,11 @@ class Translator(object):
         parser.set_defaults(verbose=True, driver="ESRI Shapefile", overwrite=True)
 
         self.parser = parser
-        
+
     def __init__(self, arguments, options=None):
         self.input = None
         self.output = None
-        
+
         self.opts = options
         self.construct_parser()
         self.options, self.args = self.parser.parse_args(args=arguments)
@@ -74,7 +68,7 @@ class Translator(object):
         self.open()
         self.make_fields()
         self.translate()
-        
+
     def open(self):
         if self.options.input:
             self.in_ds = ogr.Open(self.options.input)
@@ -95,12 +89,12 @@ class Translator(object):
 
         if self.options.spat:
             self.input.SetSpatialFilterRect(*self.options.spat)
-            
+
         self.out_drv = ogr.GetDriverByName(self.options.driver)
-        
+
         if self.options.where:
             self.input.SetAttributeFilter(self.options.where)
-            
+
         if not self.out_drv:
             raise Exception("The '%s' driver was not found, did you misspell it or is it not available in this GDAL build?", self.options.driver)
         if not self.out_drv.TestCapability( 'CreateDataSource' ):
@@ -126,14 +120,14 @@ class Translator(object):
             dsco = (),
 
         self.out_ds = self.out_drv.CreateDataSource( self.options.output, dsco)
-        
+
         if self.options.t_srs:
             self.out_srs = osr.SpatialReference()
             self.out_srs.SetFromUserInput(self.options.t_srs)
         else:
             self.out_srs = None
         self.output = self.out_ds.CreateLayer(  self.options.output,
-                                                geom_type = self.input.GetLayerDefn().GetGeomType(), 
+                                                geom_type = self.input.GetLayerDefn().GetGeomType(),
                                                 srs= self.out_srs)
 
 
@@ -159,21 +153,19 @@ class Translator(object):
             trans = osr.CoordinateTransformation(self.in_srs, self.out_srs)
         while f:
             geom = f.GetGeometryRef().Clone()
-            
+
             if trans:
                 geom.Transform(trans)
 
             if geometry_callback:
                 geom = geometry_callback(geom)
 
-                
             f.SetGeometry(geom)
             d = ogr.Feature(feature_def=self.output.GetLayerDefn())
             d.SetFrom(f)
             self.output.CreateFeature(d)
             f = self.input.GetNextFeature()
 
-            
     def __del__(self):
         if self.output:
             self.output.SyncToDisk()
@@ -182,24 +174,24 @@ def radians(degrees):
     return math.pi/180.0*degrees
 def degrees(radians):
     return radians*180.0/math.pi
-    
+
 class Densify(Translator):
 
     def calcpoint(self,x0, x1, y0, y1, d):
         a = x1 - x0
         b = y1 - y0
-        
+
         if a == 0:
             xn = x1
-            
+
             if b > 0:
                 yn = y0 + d
             else:
                 yn = y0 - d
             return (xn, yn)
-                      
+
         theta = degrees(math.atan(abs(b)/abs(a)))
-        
+
         if a > 0 and b > 0:
             omega = theta
         if a < 0 and b > 0:
@@ -218,21 +210,21 @@ class Densify(Translator):
         else:
             xn = x0 + d*math.cos(radians(omega))
             yn = y0 + d*math.sin(radians(omega))
-        
+
         return (xn, yn)
-                    
+
     def distance(self, x0, x1, y0, y1):
         deltax = x0 - x1
         deltay = y0 - y1
         d2 = (deltax)**2 + (deltay)**2
         d = math.sqrt(d2)
         return d
-    
+
     def densify(self, geometry):
         gtype = geometry.GetGeometryType()
         if  not (gtype == ogr.wkbLineString or gtype == ogr.wkbMultiLineString):
             raise Exception("The densify function only works on linestring or multilinestring geometries")
-            
+
         g = ogr.Geometry(ogr.wkbLineString)
 
         # add the first point
@@ -267,7 +259,7 @@ class Densify(Translator):
                         x = x + dx
                         y = y + dy
                         g.AddPoint(x, y)
-                        
+
                 elif self.options.remainder.upper() == "END":
                     segcount = int(math.floor(d/threshold))
                     xa = None
@@ -284,10 +276,10 @@ class Densify(Translator):
                         xa = xn
                         ya = yn
                         g.AddPoint(xa,ya)
-                        
+
                 elif self.options.remainder.upper() == "BEGIN":
-                    
-                    # I think this might put an extra point in at the end of the 
+
+                    # I think this might put an extra point in at the end of the
                     # first segment
                     segcount = int(math.floor(d/threshold))
                     xa = None
@@ -298,7 +290,7 @@ class Densify(Translator):
                     for p in range(segcount):
                         if not xa:
                             xn, yn = self.calcpoint(x0,x1,y0,y1,remainder)
- 
+
                             d = self.distance(x0, xn, y0, yn)
                             xa = xn
                             ya = yn
@@ -313,7 +305,6 @@ class Densify(Translator):
             x0 = x1
             y0 = y1
 
-                
         return g
 
     def process(self):
@@ -324,7 +315,7 @@ class Densify(Translator):
 def GetLength(geometry):
 
     def get_distance(x1, y1, x2, y2):
-        """Return the euclidian distance between this point and another"""
+        """Return the euclidean distance between this point and another."""
         import math
         deltax = x1 - x2
         deltay = y1 - y2
@@ -347,7 +338,7 @@ def GetLength(geometry):
 
     cumulative = 0.0
     geom_count = geometry.GetGeometryCount()
-    
+
     if geom_count:
         for gi in range(geom_count):
             g = geometry.GetGeometryRef(gi)
@@ -355,27 +346,29 @@ def GetLength(geometry):
     else:
         cumulative = cumulate(geometry)
     return cumulative
-    
+
+
 def main():
     import optparse
 
     options = []
     o = optparse.make_option("-r", "--remainder", dest="remainder",
-                         type="choice",default='end', 
-                          help="""what to do with the remainder -- place it at the beginning, 
+                         type="choice",default='end',
+                          help="""what to do with the remainder -- place it at the beginning,
 place it at the end, or evenly distribute it across the segment""",
                           choices=['end','begin','uniform'])
     options.append(o)
     o = optparse.make_option("-d", "--distance", dest='distance', type="float",
-                          help="""Threshold distance for point placement.  If the 
-'uniform' remainder is used, points will be evenly placed 
-along the segment in a fashion that makes sure they are 
-no further apart than the threshold.  If 'beg' or 'end' 
-is chosen, the threshold distance will be used as an absolute value.""", 
+                          help="""Threshold distance for point placement.  If the
+'uniform' remainder is used, points will be evenly placed
+along the segment in a fashion that makes sure they are
+no further apart than the threshold.  If 'beg' or 'end'
+is chosen, the threshold distance will be used as an absolute value.""",
                           metavar="DISTANCE")
     options.append(o)
     d = Densify(sys.argv[1:], options=options)
     d.process()
 
+
 if __name__=='__main__':
     main()
diff --git a/swig/python/samples/dump_jp2.py b/swig/python/samples/dump_jp2.py
index eb0fed5..869f571 100644
--- a/swig/python/samples/dump_jp2.py
+++ b/swig/python/samples/dump_jp2.py
@@ -1,26 +1,26 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #******************************************************************************
-#  $Id: dump_jp2.py 29068 2015-04-30 09:49:21Z rouault $
-# 
+#  $Id: dump_jp2.py 31957 2015-12-02 12:44:54Z goatbar $
+#
 #  Project:  GDAL
 #  Purpose:  Dump JPEG2000 file structure
 #  Author:   Even Rouault, <even dot rouault at spatialys dot com>
-# 
+#
 #******************************************************************************
 #  Copyright (c) 2015, European Union (European Environment Agency)
 #  Copyright (c) 2015, European Union Satellite Centre
-# 
+#
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
 #  to deal in the Software without restriction, including without limitation
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
diff --git a/swig/python/samples/fft.py b/swig/python/samples/fft.py
index 7d5b1b2..037fbef 100755
--- a/swig/python/samples/fft.py
+++ b/swig/python/samples/fft.py
@@ -1,16 +1,16 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: fft.py 28391 2015-01-30 19:57:31Z rouault $
+# $Id: fft.py 31957 2015-12-02 12:44:54Z goatbar $
 #
 # Project:  GDAL Python samples
 # Purpose:  Script to perform forward and inverse two-dimensional fast
-#	    Fourier transform.
+#           Fourier transform.
 # Author:   Andrey Kiselev, dron at remotesensing.org
 #
 ###############################################################################
 # Copyright (c) 2003, Andrey Kiselev <dron at remotesensing.org>
 # Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
-# 
+#
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
 # to deal in the Software without restriction, including without limitation
@@ -30,14 +30,11 @@
 # DEALINGS IN THE SOFTWARE.
 ###############################################################################
 
-try:
-    from osgeo import gdal
-except ImportError:
-    import gdal
-    
-import FFT
 import sys
 
+import FFT
+from osgeo import gdal
+
 # =============================================================================
 def Usage():
     print('Usage: fft.py [-inv] [-of out_format] [-ot out_type] infile outfile')
@@ -89,7 +86,7 @@ while i < len(sys.argv):
         transformation = 'inverse'
         if type == None:
             type = gdal.GDT_Float32
-        
+
     elif arg == '-of':
         i = i + 1
         format = sys.argv[i]
diff --git a/swig/python/samples/gcps2ogr.py b/swig/python/samples/gcps2ogr.py
index c6a0acd..7f81f60 100644
--- a/swig/python/samples/gcps2ogr.py
+++ b/swig/python/samples/gcps2ogr.py
@@ -1,25 +1,25 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #******************************************************************************
-#  $Id: gcps2ogr.py 29219 2015-05-21 10:01:42Z rouault $
-# 
+#  $Id: gcps2ogr.py 31957 2015-12-02 12:44:54Z goatbar $
+#
 #  Project:  GDAL
 #  Purpose:  Outputs GDAL GCPs as OGR points
 #  Author:   Even Rouault, <even dot rouault at spatialys dot com>
-# 
+#
 #******************************************************************************
 #  Copyright (c) 2015, Even Rouault, <even dot rouault at spatialys dot com>
-# 
+#
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
 #  to deal in the Software without restriction, including without limitation
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -29,10 +29,11 @@
 #  DEALINGS IN THE SOFTWARE.
 #******************************************************************************
 
+import sys
+
 from osgeo import gdal
 from osgeo import ogr
 from osgeo import osr
-import sys
 
 
 def Usage():
diff --git a/swig/python/samples/gdal2grd.py b/swig/python/samples/gdal2grd.py
index 7f4f552..5a79ad4 100755
--- a/swig/python/samples/gdal2grd.py
+++ b/swig/python/samples/gdal2grd.py
@@ -1,17 +1,17 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: gdal2grd.py 28391 2015-01-30 19:57:31Z rouault $
+# $Id: gdal2grd.py 31957 2015-12-02 12:44:54Z goatbar $
 #
 # Project:  GDAL Python samples
 # Purpose:  Script to write out ASCII GRD rasters (used in Golden Software
-#	    Surfer)
+#           Surfer)
 #           from any source supported by GDAL.
 # Author:   Andrey Kiselev, dron at remotesensing.org
 #
 ###############################################################################
 # Copyright (c) 2003, Andrey Kiselev <dron at remotesensing.org>
 # Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
-# 
+#
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
 # to deal in the Software without restriction, including without limitation
@@ -31,14 +31,11 @@
 # DEALINGS IN THE SOFTWARE.
 ###############################################################################
 
-try:
-    from osgeo import gdal
-    gdal.TermProgress = gdal.TermProgress_nocb
-except ImportError:
-    import gdal
-
 import sys
 
+from osgeo import gdal
+gdal.TermProgress = gdal.TermProgress_nocb
+
 # =============================================================================
 def Usage():
     print('Usage: gdal2grd.py [-b band] [-quiet] infile outfile')
diff --git a/swig/python/samples/gdal_cp.py b/swig/python/samples/gdal_cp.py
index 51fb2ac..d4ad512 100755
--- a/swig/python/samples/gdal_cp.py
+++ b/swig/python/samples/gdal_cp.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: gdal_cp.py 27044 2014-03-16 23:41:27Z rouault $
+# $Id: gdal_cp.py 31957 2015-12-02 12:44:54Z goatbar $
 #
 #  Project:  GDAL samples
 #  Purpose:  Copy a virtual file
@@ -28,10 +28,12 @@
 #  DEALINGS IN THE SOFTWARE.
 ###############################################################################
 
-from osgeo import gdal
-import sys
-import os
 import fnmatch
+import os
+import sys
+
+from osgeo import gdal
+
 
 def needsVSICurl(filename):
     return filename.startswith('http://') or filename.startswith('https://') or filename.startswith('ftp://')
diff --git a/swig/python/samples/gdal_ls.py b/swig/python/samples/gdal_ls.py
index 8745fd2..93ec622 100755
--- a/swig/python/samples/gdal_ls.py
+++ b/swig/python/samples/gdal_ls.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 ###############################################################################
-# $Id: gdal_ls.py 27044 2014-03-16 23:41:27Z rouault $
+# $Id: gdal_ls.py 31957 2015-12-02 12:44:54Z goatbar $
 #
 #  Project:  GDAL samples
 #  Purpose:  Display the list of files in a virtual directory, like /vsicurl or /vsizip
@@ -29,9 +29,10 @@
 #  DEALINGS IN THE SOFTWARE.
 ###############################################################################
 
-from osgeo import gdal
-import sys
 import os
+import sys
+
+from osgeo import gdal
 
 def needsVSICurl(filename):
     return filename.startswith('http://') or filename.startswith('https://') or filename.startswith('ftp://')
diff --git a/swig/python/samples/gdal_lut.py b/swig/python/samples/gdal_lut.py
index 693dda7..e7a3771 100755
--- a/swig/python/samples/gdal_lut.py
+++ b/swig/python/samples/gdal_lut.py
@@ -1,25 +1,25 @@
 #!/usr/bin/env python
 #******************************************************************************
 #  $Id: pct2rgb.py 13087 2007-11-26 20:56:29Z hobu $
-# 
+#
 #  Name:     gdal_lut
 #  Project:  GDAL Python Interface
 #  Purpose:  Utility to apply a lookup table provided in a text file.
 #  Author:   Frank Warmerdam, warmerdam at pobox.com
-# 
+#
 #******************************************************************************
 #  Copyright (c) 2008, Frank Warmerdam
-# 
+#
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
 #  to deal in the Software without restriction, including without limitation
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -29,11 +29,10 @@
 #  DEALINGS IN THE SOFTWARE.
 #******************************************************************************
 
-try:
-    from osgeo import gdal
-    gdal.TermProgress = gdal.TermProgress_nocb
-except ImportError:
-    import gdal
+import sys
+
+from osgeo import gdal
+gdal.TermProgress = gdal.TermProgress_nocb
 
 try:
     import numpy
@@ -41,9 +40,6 @@ except:
     import Numeric as numpy
     numpy.arange = numpy.arrayrange
 
-
-import sys
-
 # =============================================================================
 #		read_lut()
 #
@@ -59,7 +55,7 @@ def read_lut( filename ):
         lut.append(int(line))
 
     return lut
-    
+
 # =============================================================================
 #		Usage()
 # =============================================================================
@@ -84,7 +80,7 @@ would map input pixel values 0,1,2,3,4,5 to 0,5,11,12,12,13 respectively.
 Values not mapped by the lut file (for instance values 6-255 in the above
 case) will be left unaltered.  Sixteen bit (UInt16) output values are
 supported as well as luts of more than 256 input values.
-""")                   
+""")
     sys.exit(1)
 
 # =============================================================================
@@ -142,7 +138,7 @@ while i < len(argv):
 
 if src_filename is None or lut_filename is None:
     Usage()
-    
+
 # ----------------------------------------------------------------------------
 # Load the LUT file.
 
@@ -183,7 +179,7 @@ if dst_filename is None:
 else:
     src_ds = gdal.Open( src_filename )
     dst_ds = None
-    
+
 if src_ds is None:
     print('Unable to open ', src_filename)
     sys.exit(1)
@@ -211,12 +207,12 @@ if dst_ds is None:
                                    1, gc, options = create_options )
         dst_ds.SetProjection( src_ds.GetProjection() )
         dst_ds.SetGeoTransform( src_ds.GetGeoTransform() )
-        
+
 
 dst_band = dst_ds.GetRasterBand(dst_band_n)
 
 # ----------------------------------------------------------------------------
-# Do the processing one scanline at a time. 
+# Do the processing one scanline at a time.
 
 gdal.TermProgress( 0.0 )
 for iY in range(src_ds.RasterYSize):
diff --git a/swig/python/samples/gdal_vrtmerge.py b/swig/python/samples/gdal_vrtmerge.py
index 7b18ede..a0465a7 100755
--- a/swig/python/samples/gdal_vrtmerge.py
+++ b/swig/python/samples/gdal_vrtmerge.py
@@ -1,19 +1,19 @@
 #!/usr/bin/env python
-# -*- coding: utf-8 -*- 
+# -*- coding: utf-8 -*-
 # Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
 # Copyright (C) 2005  Gabriel Ebner <ge at gabrielebner.at>
 # Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
-# 
+#
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Library General Public
 # License as published by the Free Software Foundation; either
 # version 2 of the License, or (at your option) any later version.
-# 
+#
 # This library is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 # Library General Public License for more details.
-# 
+#
 # You should have received a copy of the GNU Library General Public
 # License along with this library; if not, write to the
 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
@@ -23,13 +23,10 @@
 # precision as the gdal 'C' utilities
 # Norman Vine  nhv at cape.com  03-Oct-2005 6:23:45 am
 
-try:
-    from osgeo import gdal
-except ImportError:
-    import gdal
-
 import sys
 
+from osgeo import gdal
+
 # =============================================================================
 def names_to_fileinfos( names ):
     """
@@ -40,7 +37,7 @@ def names_to_fileinfos( names ):
     Returns a list of file_info objects.  There may be less file_info objects
     than names if some of the names could not be opened as GDAL files.
     """
-    
+
     file_infos = []
     for name in names:
         fi = file_info()
@@ -79,14 +76,14 @@ class file_info:
         self.lry = self.uly + self.geotransform[5] * self.ysize
 
         self.band_types = [None]
-        self.block_sizes = [None] 
+        self.block_sizes = [None]
         self.nodata = [None]
         self.cts = [None]
         self.color_interps = [None]
         for i in range(1, fh.RasterCount+1):
             band = fh.GetRasterBand(i)
             self.band_types.append(band.DataType)
-            self.block_sizes.append(band.GetBlockSize()) 
+            self.block_sizes.append(band.GetBlockSize())
             if band.GetNoDataValue() != None:
                 self.nodata.append(band.GetNoDataValue())
             self.color_interps.append(band.GetRasterColorInterpretation())
@@ -113,7 +110,7 @@ class file_info:
         else:
             tgw_uly = max(t_uly,self.uly)
             tgw_lry = min(t_lry,self.lry)
-        
+
         # do they even intersect?
         if tgw_ulx >= tgw_lrx:
             return 1
@@ -121,7 +118,7 @@ class file_info:
             return 1
         if t_geotransform[5] > 0 and tgw_uly >= tgw_lry:
             return 1
-            
+
         # compute target window in pixel coordinates.
         tw_xoff = int((tgw_ulx - t_geotransform[0]) / t_geotransform[1] + 0.1)
         tw_yoff = int((tgw_uly - t_geotransform[3]) / t_geotransform[5] + 0.1)
@@ -145,11 +142,11 @@ class file_info:
             return 1
 
         t_fh.write('\t\t<SimpleSource>\n')
-        t_fh.write(('\t\t\t<SourceFilename relativeToVRT="1">%s' + 
+        t_fh.write(('\t\t\t<SourceFilename relativeToVRT="1">%s' +
             '</SourceFilename>\n') % self.filename)
         t_fh.write('\t\t\t<SourceBand>%i</SourceBand>\n' % s_band)
-        data_type_name = gdal.GetDataTypeName(self.band_types[s_band]) 
-        block_size_x, block_size_y = self.block_sizes[s_band] 
+        data_type_name = gdal.GetDataTypeName(self.band_types[s_band])
+        block_size_x, block_size_y = self.block_sizes[s_band]
         t_fh.write('\t\t\t<SourceProperties RasterXSize="%i" RasterYSize="%i"' \
                     ' DataType="%s" BlockXSize="%i" BlockYSize="%i"/>\n' \
                     % (self.xsize, self.ysize, data_type_name, block_size_x, block_size_y))
@@ -192,11 +189,11 @@ if __name__ == '__main__':
         if arg == '-o':
             i = i + 1
             out_file = argv[i]
-            
-        elif arg == '-i': 
-            i = i + 1 
-            in_file_list = open(argv[i]) 
-            names.extend(in_file_list.read().split()) 
+
+        elif arg == '-i':
+            i = i + 1
+            in_file_list = open(argv[i])
+            names.extend(in_file_list.read().split())
 
         elif arg == '-separate':
             separate = True
@@ -209,13 +206,13 @@ if __name__ == '__main__':
             i = i + 4
 
         elif arg[:1] == '-':
-            print ('Unrecognised command option: ', arg)
+            print ('Unrecognized command option: ', arg)
             Usage()
             sys.exit( 1 )
 
         else:
             names.append( arg )
-            
+
         i = i + 1
 
     if len(names) == 0:
@@ -234,7 +231,7 @@ if __name__ == '__main__':
         uly = file_infos[0].uly
         lrx = file_infos[0].lrx
         lry = file_infos[0].lry
-        
+
         for fi in file_infos:
             ulx = min(ulx, fi.ulx)
             uly = max(uly, fi.uly)
@@ -244,9 +241,9 @@ if __name__ == '__main__':
     if psize_x is None:
         psize_x = file_infos[0].geotransform[1]
         psize_y = file_infos[0].geotransform[5]
-    
+
     projection = file_infos[0].projection
-    
+
     for fi in file_infos:
         if fi.geotransform[1] != psize_x or fi.geotransform[5] != psize_y:
             print ("All files must have the same scale; %s does not" \
@@ -286,7 +283,8 @@ if __name__ == '__main__':
         for fi in file_infos:
             band_n = band_n + 1
             if len(fi.band_types) != 2:
-                print ('File %s has %d bands. Only first band will be taken into accout' % (fi.filename, len(fi.band_types)-1))
+                print ( 'File %s has %d bands. Only first band will be taken '
+                        'into account' % (fi.filename, len(fi.band_types)-1))
             dataType = gdal.GetDataTypeName(fi.band_types[1])
 
             t_fh.write('\t<VRTRasterBand dataType="%s" band="%i">\n'
diff --git a/swig/python/samples/gdalcopyproj.py b/swig/python/samples/gdalcopyproj.py
index 7ee99d5..17e9bbe 100755
--- a/swig/python/samples/gdalcopyproj.py
+++ b/swig/python/samples/gdalcopyproj.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 #******************************************************************************
-#  $Id: gdalcopyproj.py 28391 2015-01-30 19:57:31Z rouault $
-# 
+#  $Id: gdalcopyproj.py 31957 2015-12-02 12:44:54Z goatbar $
+#
 #  Name:     gdalcopyproj.py
 #  Project:  GDAL Python Interface
 #  Purpose:  Duplicate the geotransform and projection metadata from
@@ -9,21 +9,21 @@
 #	     performing image manipulations with other software that
 #	     ignores or discards georeferencing metadata.
 #  Author:   Schuyler Erle, schuyler at nocat.net
-# 
+#
 #******************************************************************************
 #  Copyright (c) 2005, Frank Warmerdam
 #  Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
-# 
+#
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
 #  to deal in the Software without restriction, including without limitation
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -33,13 +33,10 @@
 #  DEALINGS IN THE SOFTWARE.
 #******************************************************************************
 
-try:
-    from osgeo import gdal
-except ImportError:
-    import gdal
-
 import sys
 
+from osgeo import gdal
+
 if len(sys.argv) < 3:
     print("Usage: gdalcopyproj.py source_file dest_file")
     sys.exit(1)
diff --git a/swig/python/samples/gdalfilter.py b/swig/python/samples/gdalfilter.py
index c853aea..780b0cf 100755
--- a/swig/python/samples/gdalfilter.py
+++ b/swig/python/samples/gdalfilter.py
@@ -1,14 +1,14 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: gdalfilter.py 18195 2009-12-06 20:24:39Z rouault $
+# $Id: gdalfilter.py 33791 2016-03-26 12:51:23Z goatbar $
 #
 # Project:  OGR Python samples
-# Purpose:  Filter an input file, producing an output file. 
+# Purpose:  Filter an input file, producing an output file.
 # Author:   Frank Warmerdam, warmerdam at pobox.com
 #
 ###############################################################################
 # Copyright (c) 2003, Frank Warmerdam <warmerdam at pobox.com>
-# 
+#
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
 # to deal in the Software without restriction, including without limitation
@@ -28,11 +28,8 @@
 # DEALINGS IN THE SOFTWARE.
 ###############################################################################
 
-try:
-    from osgeo import gdal
-    gdal.TermProgress = gdal.TermProgress_nocb
-except ImportError:
-    import gdal
+from osgeo import gdal
+gdal.TermProgress = gdal.TermProgress_nocb
 
 import sys
 import string
@@ -157,13 +154,13 @@ filt_template = \
 
 for iBand in range(vrt_ds.RasterCount):
     band = vrt_ds.GetRasterBand(iBand+1)
-    
+
     src_xml = filt_template % (iBand+1)
 
     band.SetMetadata( { 'source_0' : src_xml }, 'vrt_sources' )
 
 # =============================================================================
-#	copy the results to a new file. 
+#	copy the results to a new file.
 # =============================================================================
 
 if out_format == 'VRT':
diff --git a/swig/python/samples/gdalinfo.py b/swig/python/samples/gdalinfo.py
index f165e6c..73195c1 100755
--- a/swig/python/samples/gdalinfo.py
+++ b/swig/python/samples/gdalinfo.py
@@ -1,47 +1,44 @@
 #!/usr/bin/env python
-#/******************************************************************************
-# * $Id: gdalinfo.py 28391 2015-01-30 19:57:31Z rouault $
-# *
-# * Project:  GDAL Utilities
-# * Purpose:  Python port of Commandline application to list info about a file.
-# * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
-# *
-# * Port from gdalinfo.c whose author is Frank Warmerdam
-# *
-# ******************************************************************************
-# * Copyright (c) 2010-2011, Even Rouault <even dot rouault at mines-paris dot org>
-# * Copyright (c) 1998, Frank Warmerdam
-# *
-# * Permission is hereby granted, free of charge, to any person obtaining a
-# * copy of this software and associated documentation files (the "Software"),
-# * to deal in the Software without restriction, including without limitation
-# * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-# * and/or sell copies of the Software, and to permit persons to whom the
-# * Software is furnished to do so, subject to the following conditions:
-# *
-# * The above copyright notice and this permission notice shall be included
-# * in all copies or substantial portions of the Software.
-# *
-# * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-# * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# * DEALINGS IN THE SOFTWARE.
-# ****************************************************************************/
+#*****************************************************************************
+# $Id: gdalinfo.py 31957 2015-12-02 12:44:54Z goatbar $
+#
+# Project:  GDAL Utilities
+# Purpose:  Python port of Commandline application to list info about a file.
+# Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+#
+# Port from gdalinfo.c whose author is Frank Warmerdam
+#
+#*****************************************************************************
+# Copyright (c) 2010-2011, Even Rouault <even dot rouault at mines-paris dot org>
+# Copyright (c) 1998, Frank Warmerdam
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+#***************************************************************************/
 
 import sys
-try:
-    from osgeo import gdal
-    from osgeo import osr
-except:
-    import gdal
-    import osr
 
-#/************************************************************************/
-#/*                               Usage()                                */
-#/************************************************************************/
+from osgeo import gdal
+from osgeo import osr
+
+#**********************************************************************
+#                               Usage()
+#**********************************************************************
 
 def Usage():
     print( "Usage: gdalinfo [--help-general] [-mm] [-stats] [-hist] [-nogcp] [-nomd]\n" + \
@@ -52,9 +49,9 @@ def Usage():
 def EQUAL(a, b):
     return a.lower() == b.lower()
 
-#/************************************************************************/
-#/*                                main()                                */
-#/************************************************************************/
+#**********************************************************************
+#                                main()
+#**********************************************************************
 
 def main( argv = None ):
 
@@ -73,9 +70,9 @@ def main( argv = None ):
     hTransform = None
     bShowFileList = True
 
-    #/* Must process GDAL_SKIP before GDALAllRegister(), but we can't call */
-    #/* GDALGeneralCmdLineProcessor before it needs the drivers to be registered */
-    #/* for the --format or --formats options */
+    # Must process GDAL_SKIP before GDALAllRegister(), but we can't call
+    # GDALGeneralCmdLineProcessor before it needs the drivers to be registered
+    # for the --format or --formats options
     #for( i = 1; i < argc; i++ )
     #{
     #    if EQUAL(argv[i],"--config") and i + 2 < argc and EQUAL(argv[i + 1], "GDAL_SKIP"):
@@ -97,9 +94,9 @@ def main( argv = None ):
         return 1
 
     nArgc = len(argv)
-#/* -------------------------------------------------------------------- */
-#/*      Parse arguments.                                                */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Parse arguments.
+# --------------------------------------------------------------------
     i = 1
     while i < nArgc:
 
@@ -144,9 +141,9 @@ def main( argv = None ):
     if pszFilename is None:
         return Usage()
 
-#/* -------------------------------------------------------------------- */
-#/*      Open dataset.                                                   */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Open dataset.
+# --------------------------------------------------------------------
     hDataset = gdal.Open( pszFilename, gdal.GA_ReadOnly )
 
     if hDataset is None:
@@ -154,10 +151,10 @@ def main( argv = None ):
         print("gdalinfo failed - unable to open '%s'." % pszFilename )
 
         return 1
-    
-#/* -------------------------------------------------------------------- */
-#/*      Report general info.                                            */
-#/* -------------------------------------------------------------------- */
+
+# --------------------------------------------------------------------
+#      Report general info.
+# --------------------------------------------------------------------
     hDriver = hDataset.GetDriver();
     print( "Driver: %s/%s" % ( \
             hDriver.ShortName, \
@@ -174,9 +171,9 @@ def main( argv = None ):
 
     print( "Size is %d, %d" % (hDataset.RasterXSize, hDataset.RasterYSize))
 
-#/* -------------------------------------------------------------------- */
-#/*      Report projection.                                              */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Report projection.
+# --------------------------------------------------------------------
     pszProjection = hDataset.GetProjectionRef()
     if pszProjection is not None:
 
@@ -188,9 +185,9 @@ def main( argv = None ):
         else:
             print( "Coordinate System is `%s'" % pszProjection )
 
-#/* -------------------------------------------------------------------- */
-#/*      Report Geotransform.                                            */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Report Geotransform.
+# --------------------------------------------------------------------
     adfGeoTransform = hDataset.GetGeoTransform(can_return_null = True)
     if adfGeoTransform is not None:
 
@@ -212,9 +209,9 @@ def main( argv = None ):
                     adfGeoTransform[4], \
                     adfGeoTransform[5] ))
 
-#/* -------------------------------------------------------------------- */
-#/*      Report GCPs.                                                    */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Report GCPs.
+# --------------------------------------------------------------------
     if bShowGCPs and hDataset.GetGCPCount() > 0:
 
         pszProjection = hDataset.GetGCPProjection()
@@ -240,9 +237,9 @@ def main( argv = None ):
                     gcp.GCPX, gcp.GCPY, gcp.GCPZ ))
             i = i + 1
 
-#/* -------------------------------------------------------------------- */
-#/*      Report metadata.                                                */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Report metadata.
+# --------------------------------------------------------------------
     if bShowMetadata:
         papszMetadata = hDataset.GetMetadata_List()
     else:
@@ -260,9 +257,9 @@ def main( argv = None ):
                 for metadata in papszMetadata:
                   print( "  %s" % metadata )
 
-#/* -------------------------------------------------------------------- */
-#/*      Report "IMAGE_STRUCTURE" metadata.                              */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Report "IMAGE_STRUCTURE" metadata.
+# --------------------------------------------------------------------
     if bShowMetadata:
         papszMetadata = hDataset.GetMetadata_List("IMAGE_STRUCTURE")
     else:
@@ -272,18 +269,18 @@ def main( argv = None ):
         for metadata in papszMetadata:
             print( "  %s" % metadata )
 
-#/* -------------------------------------------------------------------- */
-#/*      Report subdatasets.                                             */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Report subdatasets.
+# --------------------------------------------------------------------
     papszMetadata = hDataset.GetMetadata_List("SUBDATASETS")
     if papszMetadata is not None and len(papszMetadata) > 0 :
         print( "Subdatasets:" )
         for metadata in papszMetadata:
             print( "  %s" % metadata )
 
-#/* -------------------------------------------------------------------- */
-#/*      Report geolocation.                                             */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Report geolocation.
+# --------------------------------------------------------------------
     if bShowMetadata:
         papszMetadata = hDataset.GetMetadata_List("GEOLOCATION")
     else:
@@ -293,9 +290,9 @@ def main( argv = None ):
         for metadata in papszMetadata:
             print( "  %s" % metadata )
 
-#/* -------------------------------------------------------------------- */
-#/*      Report RPCs                                                     */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Report RPCs
+# --------------------------------------------------------------------
     if bShowMetadata:
         papszMetadata = hDataset.GetMetadata_List("RPC")
     else:
@@ -305,9 +302,9 @@ def main( argv = None ):
         for metadata in papszMetadata:
             print( "  %s" % metadata )
 
-#/* -------------------------------------------------------------------- */
-#/*      Setup projected to lat/long transform if appropriate.           */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Setup projected to lat/long transform if appropriate.
+# --------------------------------------------------------------------
     if pszProjection is not None and len(pszProjection) > 0:
         hProj = osr.SpatialReference( pszProjection )
         if hProj is not None:
@@ -320,9 +317,9 @@ def main( argv = None ):
             if gdal.GetLastErrorMsg().find( 'Unable to load PROJ.4 library' ) != -1:
                 hTransform = None
 
-#/* -------------------------------------------------------------------- */
-#/*      Report corners.                                                 */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Report corners.
+# --------------------------------------------------------------------
     print( "Corner Coordinates:" )
     GDALInfoReportCorner( hDataset, hTransform, "Upper Left", \
                           0.0, 0.0 );
@@ -337,9 +334,9 @@ def main( argv = None ):
                           hDataset.RasterXSize/2.0, \
                           hDataset.RasterYSize/2.0 );
 
-#/* ==================================================================== */
-#/*      Loop over bands.                                                */
-#/* ==================================================================== */
+# ====================================================================
+#      Loop over bands.
+# ====================================================================
     for iBand in range(hDataset.RasterCount):
 
         hBand = hDataset.GetRasterBand(iBand+1 )
@@ -556,18 +553,18 @@ def main( argv = None ):
 
     return 0
 
-#/************************************************************************/
-#/*                        GDALInfoReportCorner()                        */
-#/************************************************************************/
+#**********************************************************************
+#                        GDALInfoReportCorner()
+#**********************************************************************
 
 def GDALInfoReportCorner( hDataset, hTransform, corner_name, x, y ):
 
 
     line = "%-11s " % corner_name
 
-#/* -------------------------------------------------------------------- */
-#/*      Transform the point into georeferenced coordinates.             */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Transform the point into georeferenced coordinates.
+# --------------------------------------------------------------------
     adfGeoTransform = hDataset.GetGeoTransform(can_return_null = True)
     if adfGeoTransform is not None:
         dfGeoX = adfGeoTransform[0] + adfGeoTransform[1] * x \
@@ -580,18 +577,18 @@ def GDALInfoReportCorner( hDataset, hTransform, corner_name, x, y ):
         print(line)
         return False
 
-#/* -------------------------------------------------------------------- */
-#/*      Report the georeferenced coordinates.                           */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Report the georeferenced coordinates.
+# --------------------------------------------------------------------
     if abs(dfGeoX) < 181 and abs(dfGeoY) < 91:
         line = line + ( "(%12.7f,%12.7f) " % (dfGeoX, dfGeoY ))
 
     else:
         line = line + ( "(%12.3f,%12.3f) " % (dfGeoX, dfGeoY ))
 
-#/* -------------------------------------------------------------------- */
-#/*      Transform to latlong and report.                                */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Transform to latlong and report.
+# --------------------------------------------------------------------
     if hTransform is not None:
         pnt = hTransform.TransformPoint(dfGeoX, dfGeoY, 0)
         if pnt is not None:
diff --git a/swig/python/samples/gdalpythonserver.py b/swig/python/samples/gdalpythonserver.py
index 5fd8e76..e621762 100755
--- a/swig/python/samples/gdalpythonserver.py
+++ b/swig/python/samples/gdalpythonserver.py
@@ -1,39 +1,39 @@
 #!/usr/bin/python
 # -*- coding: utf-8 -*-
-#/******************************************************************************
-# * $Id$
-# *
-# * Project:  GDAL
-# * Purpose:  GDAL API_PROXY server written in Python
-# * Author:   Even Rouault, <even dot rouault at mines-paris dot org>
-# *
-# ******************************************************************************
-# * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
-# *
-# * Permission is hereby granted, free of charge, to any person obtaining a
-# * copy of this software and associated documentation files (the "Software"),
-# * to deal in the Software without restriction, including without limitation
-# * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-# * and/or sell copies of the Software, and to permit persons to whom the
-# * Software is furnished to do so, subject to the following conditions:
-# *
-# * The above copyright notice and this permission notice shall be included
-# * in all copies or substantial portions of the Software.
-# *
-# * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-# * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# * DEALINGS IN THE SOFTWARE.
-# ****************************************************************************/
+#*****************************************************************************
+# $Id$
+#
+# Project:  GDAL
+# Purpose:  GDAL API_PROXY server written in Python
+# Author:   Even Rouault, <even dot rouault at mines-paris dot org>
+#
+#*****************************************************************************
+# Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+#***************************************************************************/
 
 # WARNING: only Python 2 compatible for now
 
-import sys
 import os
 import struct
+import sys
 
 from osgeo import gdal
 
@@ -124,8 +124,13 @@ class GDALPythonServerRasterBand:
 
 class GDALPythonServerDataset:
 
-    def __init__(self, filename, access = gdal.GA_ReadOnly):
-        self.gdal_ds = gdal.Open(filename, access)
+    def __init__(self, filename, access = gdal.GA_ReadOnly, open_options = None):
+        nFlags = 0
+        if access == gdal.GA_Update:
+            nFlags |= gdal.OF_UPDATE
+        if open_options is None:
+            open_options = []
+        self.gdal_ds = gdal.OpenEx(filename, nFlags, open_options = open_options)
         if self.gdal_ds is None:
             raise Exception(gdal.GetLastErrorMsg())
         self.RasterXSize = self.gdal_ds.RasterXSize
@@ -254,8 +259,9 @@ INSTR_Band_GetUnitType = 72
 INSTR_Band_GetDefaultRAT = 75
 #INSTR_Band_SetDefaultRAT = 76
 #INSTR_Band_AdviseRead = 77
-INSTR_Band_End = 78
-#INSTR_END = 79
+#INSTR_Band_DeleteNoDataValue=78
+INSTR_Band_End = 79
+#INSTR_END = 80
 
 caps_list = [
     INSTR_GetGDALVersion,
@@ -336,7 +342,7 @@ caps_list = [
     #INSTR_Band_SetDefaultRAT,
     #INSTR_Band_AdviseRead ,
     #INSTR_Band_End,
-    #INSTR_END = 79
+    #INSTR_END = 80
 ]
 
 CE_None = 0
@@ -484,10 +490,10 @@ def main_loop():
                 sys.stderr.write('protovminor=%d\n' % protovminor)
                 sys.stderr.write('extra_bytes=%d\n' % extra_bytes)
 
-            write_str('2.0')
+            write_str('2.1dev')
             write_int(2) # vmajor
-            write_int(0) # vminor
-            write_int(2) # protovmajor
+            write_int(1) # vminor
+            write_int(3) # protovmajor
             write_int(0) # protovminor
             write_int(0) # extra bytes
             continue
@@ -522,15 +528,17 @@ def main_loop():
             access = read_int()
             filename = read_str()
             cwd = read_str()
+            open_options = read_strlist()
             if cwd is not None:
                 os.chdir(cwd)
             if VERBOSE:
                 sys.stderr.write('access=%d\n' % access)
                 sys.stderr.write('filename=%s\n' % filename)
                 sys.stderr.write('cwd=%s\n' % cwd)
+                sys.stderr.write('open_options=%s\n' % str(open_options))
             #sys.stderr.write('Open(%s)\n' % filename)
             try:
-                server_ds = GDALPythonServerDataset(filename, access)
+                server_ds = GDALPythonServerDataset(filename, access, open_options)
             except:
                 server_ds = None
 
@@ -573,20 +581,20 @@ def main_loop():
         elif instr == INSTR_Create:
             filename = read_str()
             cwd = read_str()
-            read_int() # xsize = 
-            read_int() # ysize = 
-            read_int() # bands = 
-            read_int() # datatype = 
-            read_strlist() #options = 
+            read_int() # xsize =
+            read_int() # ysize =
+            read_int() # bands =
+            read_int() # datatype =
+            read_strlist() #options =
             write_marker()
             # FIXME
             write_int(0)
         elif instr == INSTR_CreateCopy:
             filename = read_str()
-            read_str() # src_description = 
+            read_str() # src_description =
             cwd = read_str()
-            read_int() # strict = 
-            read_strlist() # options = 
+            read_int() # strict =
+            read_strlist() # options =
             # FIXME
             write_int(0)
         elif instr == INSTR_QuietDelete:
@@ -604,13 +612,6 @@ def main_loop():
                     write_double(gt[i])
             else:
                 write_int(CE_Failure)
-                write_int(6 * 8)
-                write_double(0)
-                write_double(1)
-                write_double(0)
-                write_double(0)
-                write_double(0)
-                write_double(1)
         elif instr == INSTR_GetProjectionRef:
             write_marker()
             write_str(server_ds.GetProjectionRef())
@@ -646,7 +647,7 @@ def main_loop():
             nBufType = read_int()
             nBandCount = read_int()
             panBandMap = []
-            read_int() # size = 
+            read_int() # size =
             for i in range(nBandCount):
                 panBandMap.append(read_int())
             nPixelSpace = read_bigint()
diff --git a/swig/python/samples/get_soundg.py b/swig/python/samples/get_soundg.py
index 077fa3b..1b39d02 100755
--- a/swig/python/samples/get_soundg.py
+++ b/swig/python/samples/get_soundg.py
@@ -1,16 +1,16 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: get_soundg.py 28391 2015-01-30 19:57:31Z rouault $
+# $Id: get_soundg.py 33791 2016-03-26 12:51:23Z goatbar $
 #
 # Project:  OGR Python samples
 # Purpose:  Extract SOUNDGings from an S-57 dataset, and write them to
 #           Shapefile format, creating one feature for each sounding, and
-#           adding the elevation as an attribute for easier use. 
+#           adding the elevation as an attribute for easier use.
 # Author:   Frank Warmerdam, warmerdam at pobox.com
 #
 ###############################################################################
 # Copyright (c) 2003, Frank Warmerdam <warmerdam at pobox.com>
-# 
+#
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
 # to deal in the Software without restriction, including without limitation
@@ -30,13 +30,10 @@
 # DEALINGS IN THE SOFTWARE.
 ###############################################################################
 
-try:
-    from osgeo import ogr
-except ImportError:
-    import ogr
-
 import sys
 
+from osgeo import ogr
+
 #############################################################################
 def Usage():
     print('Usage: get_soundg.py <s57file> <shapefile>')
@@ -59,7 +56,7 @@ ds = ogr.Open( s57filename )
 src_soundg = ds.GetLayerByName( 'SOUNDG' )
 
 #############################################################################-
-# Create the output shapefile. 
+# Create the output shapefile.
 
 shp_driver = ogr.GetDriverByName( 'ESRI Shapefile' )
 shp_driver.DeleteDataSource( shpfilename )
@@ -77,7 +74,7 @@ field_count = src_defn.GetFieldCount()
 out_mapping = []
 for fld_index in range(field_count):
     src_fd = src_defn.GetFieldDefn( fld_index )
-    
+
     fd = ogr.FieldDefn( src_fd.GetName(), src_fd.GetType() )
     fd.SetWidth( src_fd.GetWidth() )
     fd.SetPrecision( src_fd.GetPrecision() )
@@ -90,7 +87,7 @@ fd = ogr.FieldDefn( 'ELEV', ogr.OFTReal )
 fd.SetWidth( 12 )
 fd.SetPrecision( 4 )
 shp_layer.CreateField( fd )
-    
+
 #############################################################################
 # Process all SOUNDG features.
 
diff --git a/swig/python/samples/histrep.py b/swig/python/samples/histrep.py
index dd7ad96..eede784 100755
--- a/swig/python/samples/histrep.py
+++ b/swig/python/samples/histrep.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: histrep.py 27044 2014-03-16 23:41:27Z rouault $
+# $Id: histrep.py 33791 2016-03-26 12:51:23Z goatbar $
 #
 # Project:  GDAL Python Samples
 # Purpose:  Report histogram from file.
@@ -9,7 +9,7 @@
 ###############################################################################
 # Copyright (c) 2005, Frank Warmerdam, warmerdam at pobox.com
 # Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
-# 
+#
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
 # to deal in the Software without restriction, including without limitation
@@ -29,13 +29,10 @@
 # DEALINGS IN THE SOFTWARE.
 ###############################################################################
 
-try:
-    from osgeo import gdal
-except ImportError:
-    import gdal
-
 import sys
 
+from osgeo import gdal
+
 # =============================================================================
 def Usage():
     print('Usage: histrep.py [-force] input_file')
@@ -80,7 +77,7 @@ if __name__ == '__main__':
 
         else:
             Usage()
-            
+
         i = i + 1
 
     if file is None:
@@ -95,12 +92,12 @@ if __name__ == '__main__':
         if hist is None:
             print('No default histogram.')
         else:
-            print('Default Histogram:') 
+            print('Default Histogram:')
             print('Min: ', hist[0])
             print('Max: ', hist[1])
             print('Buckets: ', hist[2])
             print('Histogram: ', hist[3])
-        
+
     else:
         hist = ds.GetRasterBand(1).GetHistogram( req[0], req[1], req[2],
                                                 ioor, approxok )
diff --git a/swig/python/samples/hsv_merge.py b/swig/python/samples/hsv_merge.py
index aa0b87a..14eb966 100755
--- a/swig/python/samples/hsv_merge.py
+++ b/swig/python/samples/hsv_merge.py
@@ -1,27 +1,27 @@
 #!/usr/bin/env python
 #******************************************************************************
-#  $Id: hsv_merge.py 28391 2015-01-30 19:57:31Z rouault $
-# 
+#  $Id: hsv_merge.py 31957 2015-12-02 12:44:54Z goatbar $
+#
 #  Project:  GDAL Python Interface
 #  Purpose:  Script to merge greyscale as intensity into an RGB(A) image, for
 #            instance to apply hillshading to a dem colour relief.
 #  Author:   Frank Warmerdam, warmerdam at pobox.com
 #            Trent Hare (USGS)
-# 
+#
 #******************************************************************************
 #  Copyright (c) 2009, Frank Warmerdam
 #  Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
-# 
+#
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
 #  to deal in the Software without restriction, including without limitation
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -31,10 +31,11 @@
 #  DEALINGS IN THE SOFTWARE.
 #******************************************************************************
 
-from osgeo import gdal
-import numpy
 import sys
 
+import numpy
+from osgeo import gdal
+
 # =============================================================================
 # rgb_to_hsv()
 #
@@ -72,7 +73,7 @@ def rgb_to_hsv( r,g,b ):
     h = numpy.mod(h/6.0,1.0)
 
     hsv = numpy.asarray([h,s,v])
-    
+
     return hsv
 
 # =============================================================================
@@ -99,7 +100,7 @@ def hsv_to_rgb( hsv ):
     b = i.choose( p, p, t, v, v, q )
 
     rgb = numpy.asarray([r,g,b]).astype(numpy.uint8)
-    
+
     return rgb
 
 # =============================================================================
@@ -114,7 +115,7 @@ where src_color is a RGB or RGBA dataset,
       intensity for the color dataset.
 """)
     sys.exit(1)
-    
+
 # =============================================================================
 # 	Mainline
 # =============================================================================
@@ -188,7 +189,7 @@ hillbandnodatavalue = hillband.GetNoDataValue()
 
 #check for same file size
 if ((rBand.YSize != hillband.YSize) or (rBand.XSize != hillband.XSize)):
-    print('Color and hilshade must be the same size in pixels.')
+    print('Color and hillshade must be the same size in pixels.')
     sys.exit(1)
 
 #loop over lines to apply hillshade
@@ -201,7 +202,7 @@ for i in range(hillband.YSize):
 
     #convert to HSV
     hsv = rgb_to_hsv( rScanline, gScanline, bScanline )
-    
+
     # if there's nodata on the hillband, use the v value from the color
     # dataset instead of the hillshade value.
     if hillbandnodatavalue is not None:
@@ -212,7 +213,7 @@ for i in range(hillband.YSize):
 
     #replace v with hillshade
     hsv_adjusted = numpy.asarray( [hsv[0], hsv[1], v] )
-    
+
     #convert back to RGB
     dst_color = hsv_to_rgb( hsv_adjusted )
 
@@ -227,7 +228,7 @@ for i in range(hillband.YSize):
         aScanline = aBand.ReadAsArray(0, i, hillband.XSize, 1, hillband.XSize, 1)
         outband = outdataset.GetRasterBand(4)
         outband.WriteArray(aScanline, 0, i)
-    
+
     #update progress line
     if not quiet:
         gdal.TermProgress_nocb( (float(i+1) / hillband.YSize) )
diff --git a/swig/python/samples/jpeg_in_tiff_extract.py b/swig/python/samples/jpeg_in_tiff_extract.py
index 9c9cc0a..eee9cfd 100755
--- a/swig/python/samples/jpeg_in_tiff_extract.py
+++ b/swig/python/samples/jpeg_in_tiff_extract.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 ###############################################################################
-# $Id: jpeg_in_tiff_extract.py 28391 2015-01-30 19:57:31Z rouault $
+# $Id: jpeg_in_tiff_extract.py 31957 2015-12-02 12:44:54Z goatbar $
 #
 # Project:  GDAL/OGR samples
 # Purpose:  Extract a JPEG file from a JPEG-in-TIFF tile/strip
@@ -29,9 +29,10 @@
 # DEALINGS IN THE SOFTWARE.
 ###############################################################################
 
-from osgeo import gdal
 import sys
 
+from osgeo import gdal
+
 ###############################################################
 # Usage()
 
diff --git a/swig/python/samples/load2odbc.py b/swig/python/samples/load2odbc.py
index 6baf244..e800cf2 100755
--- a/swig/python/samples/load2odbc.py
+++ b/swig/python/samples/load2odbc.py
@@ -1,16 +1,16 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: load2odbc.py 28391 2015-01-30 19:57:31Z rouault $
+# $Id: load2odbc.py 33791 2016-03-26 12:51:23Z goatbar $
 #
 # Project:  OGR Python samples
-# Purpose:  Load ODBC table to an ODBC datastore.  Uses direct SQL 
+# Purpose:  Load ODBC table to an ODBC datastore.  Uses direct SQL
 #           since the ODBC driver is read-only for OGR.
 # Author:   Frank Warmerdam, warmerdam at pobox.com
 #
 ###############################################################################
 # Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
 # Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
-# 
+#
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
 # to deal in the Software without restriction, including without limitation
@@ -30,13 +30,10 @@
 # DEALINGS IN THE SOFTWARE.
 ###############################################################################
 
-try:
-    from osgeo import ogr
-except ImportError:
-    import ogr
-
 import sys
 
+from osgeo import ogr
+
 #############################################################################
 def Usage():
     print('Usage: load2odbc.py [-where attr_filter] infile odbc_dsn layer')
@@ -97,7 +94,7 @@ else:
     out_ds = ogr.Open( odbc_dsn )
 
     if out_ds is None:
-        print('Unable to connect to ' + odbc_dsn) 
+        print('Unable to connect to ' + odbc_dsn)
         sys.exit(1)
 
 #############################################################################
@@ -114,7 +111,7 @@ except:
 
 defn = in_layer.GetLayerDefn()
 
-cmd = 'CREATE TABLE ' + layername + '( OGC_FID INTEGER, WKT_GEOMETRY MEMO' 
+cmd = 'CREATE TABLE ' + layername + '( OGC_FID INTEGER, WKT_GEOMETRY MEMO'
 
 if extents_flag:
     cmd = cmd + ', XMIN NUMBER, YMIN NUMBER, XMAX NUMBER, YMAX NUMBER'
@@ -123,13 +120,13 @@ for iField in range(defn.GetFieldCount()):
     fielddef = defn.GetFieldDefn(iField)
     cmd = cmd + ', ' + fielddef.GetName()
     if fielddef.GetType() == ogr.OFTInteger:
-        cmd = cmd + ' INTEGER' 
+        cmd = cmd + ' INTEGER'
     elif fielddef.GetType() == ogr.OFTString:
-        cmd = cmd + ' TEXT' 
+        cmd = cmd + ' TEXT'
     elif fielddef.GetType() == ogr.OFTReal:
         cmd = cmd + ' NUMBER'
     else:
-        cmd = cmd + ' TEXT' 
+        cmd = cmd + ' TEXT'
 
 cmd = cmd + ')'
 
diff --git a/swig/python/samples/loslas2ntv2.py b/swig/python/samples/loslas2ntv2.py
index 02bc335..24542ec 100755
--- a/swig/python/samples/loslas2ntv2.py
+++ b/swig/python/samples/loslas2ntv2.py
@@ -1,26 +1,26 @@
 #!/usr/bin/env python
 #******************************************************************************
 #  $Id: epsg_tr.py 19102 2010-03-15 23:41:44Z warmerdam $
-# 
+#
 #  Project:  LOS/LAS to NTv2 Translator
 #  Purpose:  Translate one or many LOS/LAS sets into an NTv2 datum shift grid
 #            file.
 #  Author:   Frank Warmerdam, warmerdam at pobox.com
 #  Financial Support: i-cubed (http://www.i-cubed.com)
-# 
+#
 #******************************************************************************
 #  Copyright (c) 2010, Frank Warmerdam
-# 
+#
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
 #  to deal in the Software without restriction, including without limitation
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -64,7 +64,7 @@ def TranslateLOSLAS( los, ntv2_filename, options ):
     # Open the LOS and LAS files.
     los_filename = los[:-4] + '.los'
     las_filename = los[:-4] + '.las'
-    
+
     los_db = gdal.Open( los_filename )
     las_db = gdal.Open( las_filename )
 
@@ -105,7 +105,7 @@ def auto_noaa( options, loslas_list ):
     options.verbose_flag = 0
 
     original_metadata = options.metadata
-    
+
     have_nad27 = 0
     #have_hpgn = 0
 
@@ -124,7 +124,7 @@ def auto_noaa( options, loslas_list ):
             options.metadata.append( 'MINOR_T=6356752.31414' )
             options.metadata.append( 'SYSTEM_F=HARN' )
             options.metadata.append( 'SYSTEM_T=NAD83' )
-            
+
         else:
             ntv2_filename = 'nad27_usa.gsb'
             options.metadata.append( 'SUB_NAME=' + los[:-4] )
@@ -141,11 +141,11 @@ def auto_noaa( options, loslas_list ):
             have_nad27 = 1
 
         print('Integrate %s into %s.' % (los, ntv2_filename))
-        
+
         TranslateLOSLAS( los, ntv2_filename, options )
-        
+
     sys.exit(0)
-    
+
 # =============================================================================
 
 if __name__ == '__main__':
@@ -160,13 +160,13 @@ if __name__ == '__main__':
     options.create_options = []
     options.metadata = []
     options.negate = 0
-    
+
     argv = gdal.GeneralCmdLineProcessor( sys.argv )
     if argv is None:
         sys.exit( 0 )
-        
+
     # Parse command line arguments.
-    
+
     i = 1
     while i < len(argv):
         arg = argv[i]
@@ -224,10 +224,10 @@ if __name__ == '__main__':
 
         elif arg == '-negate':
             options.negate = 1
-            
+
         elif arg == '-auto':
             auto_flag = 1
-            
+
         elif arg == '-a':
             options.append = 1
 
@@ -236,12 +236,12 @@ if __name__ == '__main__':
 
         elif arg[-4:] == '.los' or arg[-4:] == '.las':
             loslas_list.append( arg )
-            
+
         elif arg[-4:] == '.gsb' and ntv2_filename is None:
             ntv2_filename = arg
-            
+
         else:
-            print('Unrecognised argument: ', arg)
+            print('Unrecognized argument: ', arg)
             Usage()
 
         i = i + 1
@@ -252,7 +252,7 @@ if __name__ == '__main__':
 
     if auto_flag == 1:
         auto_noaa( options, loslas_list )
-        
+
     if ntv2_filename is None:
         print('No NTv2 file specified.')
         Usage()
@@ -264,4 +264,3 @@ if __name__ == '__main__':
         TranslateLOSLAS( los, ntv2_filename, options )
         options.append = 1
 
-    
diff --git a/swig/python/samples/magphase.py b/swig/python/samples/magphase.py
index e9a204b..3777389 100755
--- a/swig/python/samples/magphase.py
+++ b/swig/python/samples/magphase.py
@@ -1,23 +1,23 @@
 #!/usr/bin/env python
 #******************************************************************************
-# 
+#
 #  Project:  GDAL
 #  Purpose:  Example computing the magnitude and phase from a complex image.
 #  Author:   Frank Warmerdam, warmerdam at pobox.com
-# 
+#
 #******************************************************************************
 #  Copyright (c) 2008, Frank Warmerdam <warmerdam at pobox.com>
-# 
+#
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
 #  to deal in the Software without restriction, including without limitation
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
diff --git a/swig/python/samples/make_fuzzer_friendly_archive.py b/swig/python/samples/make_fuzzer_friendly_archive.py
new file mode 100644
index 0000000..8dc7899
--- /dev/null
+++ b/swig/python/samples/make_fuzzer_friendly_archive.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#******************************************************************************
+#  $Id: make_fuzzer_friendly_archive.py 32639 2016-01-01 16:41:52Z rouault $
+#
+#  Project:  GDAL
+#  Purpose:  Make fuzzer friendly archive (only works in DEBUG mode)
+#  Author:   Even Rouault, <even dot rouault at spatialys dot com>
+#
+#******************************************************************************
+#  Copyright (c) 2016 Even Rouault, <even dot rouault at spatialys dot com>
+#
+#  Permission is hereby granted, free of charge, to any person obtaining a
+#  copy of this software and associated documentation files (the "Software"),
+#  to deal in the Software without restriction, including without limitation
+#  the rights to use, copy, modify, merge, publish, distribute, sublicense,
+#  and/or sell copies of the Software, and to permit persons to whom the
+#  Software is furnished to do so, subject to the following conditions:
+#
+#  The above copyright notice and this permission notice shall be included
+#  in all copies or substantial portions of the Software.
+#
+#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+#  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+#  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+#  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+#  DEALINGS IN THE SOFTWARE.
+#******************************************************************************
+
+import os
+import sys
+
+fout = open(sys.argv[1], "wb")
+fout.write('FUZZER_FRIENDLY_ARCHIVE\n'.encode('ascii'))
+for filename in sys.argv[2:]:
+    fout.write(('***NEWFILE***:%s\n' % os.path.basename(filename)).encode('ascii'))
+    fout.write(open(filename, 'rb').read())
+fout.close()
diff --git a/swig/python/samples/ogr2ogr.py b/swig/python/samples/ogr2ogr.py
index 6bbae6d..70fa6a2 100755
--- a/swig/python/samples/ogr2ogr.py
+++ b/swig/python/samples/ogr2ogr.py
@@ -1,36 +1,36 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
-#/******************************************************************************
-# * $Id: ogr2ogr.py 28392 2015-01-30 21:01:09Z rouault $
-# *
-# * Project:  OpenGIS Simple Features Reference Implementation
-# * Purpose:  Python port of a simple client for translating between formats.
-# * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
-# *
-# * Port from ogr2ogr.cpp whose author is Frank Warmerdam
-# *
-# ******************************************************************************
-# * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
-# * Copyright (c) 1999, Frank Warmerdam
-# *
-# * Permission is hereby granted, free of charge, to any person obtaining a
-# * copy of this software and associated documentation files (the "Software"),
-# * to deal in the Software without restriction, including without limitation
-# * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-# * and/or sell copies of the Software, and to permit persons to whom the
-# * Software is furnished to do so, subject to the following conditions:
-# *
-# * The above copyright notice and this permission notice shall be included
-# * in all copies or substantial portions of the Software.
-# *
-# * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-# * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# * DEALINGS IN THE SOFTWARE.
-# ****************************************************************************/
+#*****************************************************************************
+# $Id: ogr2ogr.py 31956 2015-12-02 06:34:05Z goatbar $
+#
+# Project:  OpenGIS Simple Features Reference Implementation
+# Purpose:  Python port of a simple client for translating between formats.
+# Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+#
+# Port from ogr2ogr.cpp whose author is Frank Warmerdam
+#
+#*****************************************************************************
+# Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
+# Copyright (c) 1999, Frank Warmerdam
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+#**************************************************************************
 
 # Note : this is the most direct port of ogr2ogr.cpp possible
 # It could be made much more Python'ish !
@@ -39,14 +39,9 @@ import sys
 import os
 import stat
 
-try:
-    from osgeo import gdal
-    from osgeo import ogr
-    from osgeo import osr
-except:
-    import gdal
-    import ogr
-    import osr
+from osgeo import gdal
+from osgeo import ogr
+from osgeo import osr
 
 ###############################################################################
 
@@ -85,7 +80,7 @@ def TermProgress( dfComplete, pszMessage, pProgressArg ):
     if nThisTick > 40:
         nThisTick = 40
 
-    # Have we started a new progress run?  
+    # Have we started a new progress run?
     if nThisTick < nLastTick and nLastTick >= 39:
         nLastTick = -1
 
@@ -119,9 +114,9 @@ class AssociatedLayers:
         self.poSrcLayer = None
         self.psInfo = None
 
-#/************************************************************************/
-#/*                                main()                                */
-#/************************************************************************/
+#**********************************************************************
+#                                main()
+#**********************************************************************
 
 bSkipFailures = False
 nGroupTransactions = 200
@@ -137,12 +132,12 @@ class Enum(set):
 GeomOperation = Enum(["NONE", "SEGMENTIZE", "SIMPLIFY_PRESERVE_TOPOLOGY"])
 
 def main(args = None, progress_func = TermProgress, progress_data = None):
-    
+
     global bSkipFailures
     global nGroupTransactions
     global bPreserveFID
     global nFIDToFetch
-    
+
     pszFormat = "ESRI Shapefile"
     pszDataSource = None
     pszDestDataSource = None
@@ -196,9 +191,9 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
 
     args = ogr.GeneralCmdLineProcessor( args )
 
-#/* -------------------------------------------------------------------- */
-#/*      Processing command line arguments.                              */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Processing command line arguments.
+# --------------------------------------------------------------------
     if args is None:
         return False
 
@@ -223,7 +218,7 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
 
         elif len(args[iArg]) >= 5 and EQUAL(args[iArg][0:5], "-skip"):
             bSkipFailures = True
-            nGroupTransactions = 1 # /* #2409 */
+            nGroupTransactions = 1 # #2409
 
         elif EQUAL(args[iArg],"-append"):
             bAppend = True
@@ -392,11 +387,11 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
         elif EQUAL(args[iArg],"-progress"):
             bDisplayProgress = True
 
-        #/*elif EQUAL(args[iArg],"-wrapdateline") )
+        #elif EQUAL(args[iArg],"-wrapdateline") )
         #{
         #    bWrapDateline = True;
         #}
-        #*/
+        #
         elif EQUAL(args[iArg],"-clipsrc") and iArg < nArgc-1:
 
             bClipSrc = True
@@ -530,14 +525,14 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
             print("FAILURE: cannot load dest clip geometry\n" )
             return Usage()
 
-#/* -------------------------------------------------------------------- */
-#/*      Open data source.                                               */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Open data source.
+# --------------------------------------------------------------------
     poDS = ogr.Open( pszDataSource, False )
 
-#/* -------------------------------------------------------------------- */
-#/*      Report failure                                                  */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Report failure
+# --------------------------------------------------------------------
     if poDS is None:
         print("FAILURE:\n" + \
                 "Unable to open datasource `%s' with the following drivers." % pszDataSource)
@@ -547,9 +542,9 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
 
         return False
 
-#/* -------------------------------------------------------------------- */
-#/*      Try opening the output datasource as an existing, writable      */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Try opening the output datasource as an existing, writable
+# --------------------------------------------------------------------
     poODS = None
     poDriver = None
 
@@ -560,7 +555,7 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
             if bOverwrite or bAppend:
                 poODS = ogr.Open( pszDestDataSource, False )
                 if poODS is None:
-                    # /* ok the datasource doesn't exist at all */
+                    # the datasource doesn't exist at all
                     bUpdate = False
                 else:
                     poODS.delete()
@@ -578,9 +573,9 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
         if poODS is not None:
             poDriver = poODS.GetDriver()
 
-#/* -------------------------------------------------------------------- */
-#/*      Find the output driver.                                         */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Find the output driver.
+# --------------------------------------------------------------------
     if not bUpdate:
         poDriver = ogr.GetDriverByName(pszFormat)
         if poDriver is None:
@@ -596,14 +591,14 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
             print( "%s driver does not support data source creation." % pszFormat)
             return False
 
-#/* -------------------------------------------------------------------- */
-#/*      Special case to improve user experience when translating        */
-#/*      a datasource with multiple layers into a shapefile. If the      */
-#/*      user gives a target datasource with .shp and it does not exist, */
-#/*      the shapefile driver will try to create a file, but this is not */
-#/*      appropriate because here we have several layers, so create      */
-#/*      a directory instead.                                            */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Special case to improve user experience when translating
+#      a datasource with multiple layers into a shapefile. If the
+#      user gives a target datasource with .shp and it does not exist,
+#      the shapefile driver will try to create a file, but this is not
+#      appropriate because here we have several layers, so create
+#      a directory instead.
+# --------------------------------------------------------------------
         if EQUAL(poDriver.GetName(), "ESRI Shapefile") and \
            pszSQLStatement is None and \
            (len(papszLayers) > 1 or \
@@ -623,35 +618,35 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
                           "for shapefile datastore.\n" % pszDestDataSource )
                     return False
 
-#/* -------------------------------------------------------------------- */
-#/*      Create the output data source.                                  */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Create the output data source.
+# --------------------------------------------------------------------
         poODS = poDriver.CreateDataSource( pszDestDataSource, options = papszDSCO )
         if poODS is None:
             print( "%s driver failed to create %s" % (pszFormat, pszDestDataSource ))
             return False
 
-#/* -------------------------------------------------------------------- */
-#/*      Parse the output SRS definition if possible.                    */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Parse the output SRS definition if possible.
+# --------------------------------------------------------------------
     if pszOutputSRSDef is not None:
         poOutputSRS = osr.SpatialReference()
         if poOutputSRS.SetFromUserInput( pszOutputSRSDef ) != 0:
             print( "Failed to process SRS definition: %s" % pszOutputSRSDef )
             return False
 
-#/* -------------------------------------------------------------------- */
-#/*      Parse the source SRS definition if possible.                    */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Parse the source SRS definition if possible.
+# --------------------------------------------------------------------
     if pszSourceSRSDef is not None:
         poSourceSRS = osr.SpatialReference()
         if poSourceSRS.SetFromUserInput( pszSourceSRSDef ) != 0:
             print( "Failed to process SRS definition: %s" % pszSourceSRSDef )
             return False
 
-#/* -------------------------------------------------------------------- */
-#/*      For OSM file.                                                   */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      For OSM file.
+# --------------------------------------------------------------------
     bSrcIsOSM = poDS.GetDriver() is not None and \
                              poDS.GetDriver().GetName() == "OSM"
     nSrcFileSize = 0
@@ -660,9 +655,9 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
         if sStat is not None:
             nSrcFileSize = sStat.size
 
-#/* -------------------------------------------------------------------- */
-#/*      Special case for -sql clause.  No source layers required.       */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Special case for -sql clause.  No source layers required.
+# --------------------------------------------------------------------
     if pszSQLStatement is not None:
         if pszWHERE is not None:
             print( "-where clause ignored in combination with -sql." )
@@ -688,11 +683,11 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
                     pfnProgress = progress_func
                     pProgressArg = progress_data
 
-#/* -------------------------------------------------------------------- */
-#/*      Special case to improve user experience when translating into   */
-#/*      single file shapefile and source has only one layer, and that   */
-#/*      the layer name isn't specified                                  */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Special case to improve user experience when translating into
+#      single file shapefile and source has only one layer, and that
+#      the layer name isn't specified
+# --------------------------------------------------------------------
             if EQUAL(poDriver.GetName(), "ESRI Shapefile") and \
                 pszNewLayerName is None:
                 try:
@@ -740,9 +735,9 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
             poDS.ReleaseResultSet( poResultSet )
 
 
-#/* -------------------------------------------------------------------- */
-#/*      Special case for layer interleaving mode.                       */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Special case for layer interleaving mode.
+# --------------------------------------------------------------------
     elif bSrcIsOSM and gdal.GetConfigOption("OGR_INTERLEAVED_READING", None) is None:
 
         gdal.SetConfigOption("OGR_INTERLEAVED_READING", "YES")
@@ -756,11 +751,11 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
         nSrcLayerCount = poDS.GetLayerCount()
         pasAssocLayers = [ AssociatedLayers() for i in range(nSrcLayerCount) ]
 
-#/* -------------------------------------------------------------------- */
-#/*      Special case to improve user experience when translating into   */
-#/*      single file shapefile and source has only one layer, and that   */
-#/*      the layer name isn't specified                                  */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Special case to improve user experience when translating into
+#      single file shapefile and source has only one layer, and that
+#      the layer name isn't specified
+# --------------------------------------------------------------------
 
         if EQUAL(poDriver.GetName(), "ESRI Shapefile") and \
            (len(papszLayers) == 1 or nSrcLayerCount == 1) and pszNewLayerName is None:
@@ -775,9 +770,9 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
             pfnProgress = progress_func
             pProgressArg = progress_data
 
-#/* -------------------------------------------------------------------- */
-#/*      If no target layer specified, use all source layers.            */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      If no target layer specified, use all source layers.
+# --------------------------------------------------------------------
         if len(papszLayers) == 0:
             papszLayers = [ None for i in range(nSrcLayerCount) ]
             for iLayer in range(nSrcLayerCount):
@@ -797,9 +792,9 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
 
                 poDS.ExecuteSQL(osInterestLayers, None, None)
 
-#/* -------------------------------------------------------------------- */
-#/*      First pass to set filters and create target layers.             */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      First pass to set filters and create target layers.
+# --------------------------------------------------------------------
         for iLayer in range(nSrcLayerCount):
             poLayer = poDS.GetLayer(iLayer)
             if poLayer is None:
@@ -842,9 +837,9 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
             else:
                 pasAssocLayers[iLayer].psInfo = None
 
-#/* -------------------------------------------------------------------- */
-#/*      Second pass to process features in a interleaved layer mode.    */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Second pass to process features in a interleaved layer mode.
+# --------------------------------------------------------------------
         bHasLayersNonEmpty = True
         while bHasLayersNonEmpty:
             bHasLayersNonEmpty = False
@@ -872,7 +867,7 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
 
                         return False
                 else:
-                    #/* No matching target layer : just consumes the features */
+                    # No matching target layer : just consumes the features
 
                     poFeature = poLayer.GetNextFeature()
                     while poFeature is not None:
@@ -887,9 +882,9 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
         nLayerCount = 0
         papoLayers = []
 
-#/* -------------------------------------------------------------------- */
-#/*      Process each data source layer.                                 */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Process each data source layer.
+# --------------------------------------------------------------------
         if len(papszLayers) == 0:
             nLayerCount = poDS.GetLayerCount()
             papoLayers = [None for i in range(nLayerCount)]
@@ -905,9 +900,9 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
                 papoLayers[iLayer] = poLayer
                 iLayer = iLayer + 1
 
-#/* -------------------------------------------------------------------- */
-#/*      Process specified data source layers.                           */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Process specified data source layers.
+# --------------------------------------------------------------------
         else:
             nLayerCount = len(papszLayers)
             papoLayers = [None for i in range(nLayerCount)]
@@ -927,7 +922,7 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
         nCountLayersFeatures = 0
         nAccCountFeatures = 0
 
-        #/* First pass to apply filters and count all features if necessary */
+        # First pass to apply filters and count all features if necessary
         for iLayer in range(nLayerCount):
             poLayer = papoLayers[iLayer]
 
@@ -948,7 +943,7 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
                     panLayerCountFeatures[iLayer] = poLayer.GetFeatureCount()
                     nCountLayersFeatures += panLayerCountFeatures[iLayer]
 
-        #/* Second pass to do the real job */
+        # Second pass to do the real job
         for iLayer in range(nLayerCount):
             poLayer = papoLayers[iLayer]
 
@@ -965,11 +960,11 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
 
             nAccCountFeatures += panLayerCountFeatures[iLayer]
 
-#/* -------------------------------------------------------------------- */
-#/*      Special case to improve user experience when translating into   */
-#/*      single file shapefile and source has only one layer, and that   */
-#/*      the layer name isn't specified                                  */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Special case to improve user experience when translating into
+#      single file shapefile and source has only one layer, and that
+#      the layer name isn't specified
+# --------------------------------------------------------------------
             if EQUAL(poDriver.GetName(), "ESRI Shapefile") and \
                 nLayerCount == 1 and pszNewLayerName is None:
                 try:
@@ -1016,19 +1011,19 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
 
                 return False
 
-#/* -------------------------------------------------------------------- */
-#/*      Close down.                                                     */
-#/* -------------------------------------------------------------------- */
-    #/* We must explicetely destroy the output dataset in order the file */
-    #/* to be properly closed ! */
+# --------------------------------------------------------------------
+#      Close down.
+# --------------------------------------------------------------------
+    # We must explicitly destroy the output dataset in order the file
+    # to be properly closed !
     poODS.Destroy()
     poDS.Destroy()
 
     return True
 
-#/************************************************************************/
-#/*                               Usage()                                */
-#/************************************************************************/
+#**********************************************************************
+#                               Usage()
+#**********************************************************************
 
 def Usage():
 
@@ -1079,12 +1074,12 @@ def Usage():
             "      Integer, Real, String, Date, Time, DateTime, Binary, IntegerList, RealList,\n" + \
             "      StringList. Special value All can be used to convert all fields to strings.")
 
-    print(" -a_srs srs_def: Assign an output SRS\n" + \
-        " -t_srs srs_def: Reproject/transform to this SRS on output\n" + \
-        " -s_srs srs_def: Override source SRS\n" + \
-        "\n" + \
-        " Srs_def can be a full WKT definition (hard to escape properly),\n" + \
-        " or a well known definition (ie. EPSG:4326) or a file with a WKT\n" + \
+    print(" -a_srs srs_def: Assign an output SRS\n"
+        " -t_srs srs_def: Reproject/transform to this SRS on output\n"
+        " -s_srs srs_def: Override source SRS\n"
+        "\n"
+        " Srs_def can be a full WKT definition (hard to escape properly),\n"
+        " or a well known definition (i.e. EPSG:4326) or a file with a WKT\n"
         " definition." )
 
     return False
@@ -1160,9 +1155,9 @@ def LoadGeometry( pszDS, pszSQL, pszLyr, pszWhere):
 def wkbFlatten(x):
     return x & (~ogr.wkb25DBit)
 
-#/************************************************************************/
-#/*                               SetZ()                                 */
-#/************************************************************************/
+#**********************************************************************
+#                               SetZ()
+#**********************************************************************
 
 def SetZ (poGeom, dfZ ):
 
@@ -1186,9 +1181,9 @@ def SetZ (poGeom, dfZ ):
         for i in range(poGeom.GetGeometryCount()):
             SetZ(poGeom.GetGeometryRef(i), dfZ)
 
-#/************************************************************************/
-#/*                         SetupTargetLayer()                           */
-#/************************************************************************/
+#**********************************************************************
+#                         SetupTargetLayer()
+#**********************************************************************
 
 def SetupTargetLayer( poSrcDS, poSrcLayer, poDstDS, papszLCO, pszNewLayerName, \
                     bTransform,  poOutputSRS, bNullifyOutputSRS, poSourceSRS, papszSelFields, \
@@ -1199,9 +1194,9 @@ def SetupTargetLayer( poSrcDS, poSrcLayer, poDstDS, papszLCO, pszNewLayerName, \
     if pszNewLayerName is None:
         pszNewLayerName = poSrcLayer.GetLayerDefn().GetName()
 
-#/* -------------------------------------------------------------------- */
-#/*      Setup coordinate transformation if we need it.                  */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Setup coordinate transformation if we need it.
+# --------------------------------------------------------------------
     poCT = None
 
     if bTransform:
@@ -1232,22 +1227,22 @@ def SetupTargetLayer( poSrcDS, poSrcLayer, poDstDS, papszLCO, pszNewLayerName, \
             print( "Target:\n" + pszWKT )
             return None
 
-#/* -------------------------------------------------------------------- */
-#/*      Get other info.                                                 */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Get other info.
+# --------------------------------------------------------------------
     poSrcFDefn = poSrcLayer.GetLayerDefn()
 
     if poOutputSRS is None and not bNullifyOutputSRS:
         poOutputSRS = poSrcLayer.GetSpatialRef()
 
-#/* -------------------------------------------------------------------- */
-#/*      Find the layer.                                                 */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Find the layer.
+# --------------------------------------------------------------------
 
-    #/* GetLayerByName() can instanciate layers that would have been */
-    #*/ 'hidden' otherwise, for example, non-spatial tables in a */
-    #*/ Postgis-enabled database, so this apparently useless command is */
-    #/* not useless... (#4012) */
+    # GetLayerByName() can instantiate layers that would have been
+    # 'hidden' otherwise, for example, non-spatial tables in a
+    # PostGIS-enabled database, so this apparently useless command is
+    # not useless. (#4012)
     gdal.PushErrorHandler('CPLQuietErrorHandler')
     poDstLayer = poDstDS.GetLayerByName(pszNewLayerName)
     gdal.PopErrorHandler()
@@ -1265,14 +1260,14 @@ def SetupTargetLayer( poSrcDS, poSrcLayer, poDstDS, papszLCO, pszNewLayerName, \
                 break
 
         if (iLayer == nLayerCount):
-            # /* shouldn't happen with an ideal driver */
+            # Shouldn't happen with an ideal driver
             poDstLayer = None
 
-#/* -------------------------------------------------------------------- */
-#/*      If the user requested overwrite, and we have the layer in       */
-#/*      question we need to delete it now so it will get recreated      */
-#/*      (overwritten).                                                  */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      If the user requested overwrite, and we have the layer in
+#      question we need to delete it now so it will get recreated
+#      (overwritten).
+# --------------------------------------------------------------------
     if poDstLayer is not None and bOverwrite:
         if poDstDS.DeleteLayer( iLayer ) != 0:
             print("DeleteLayer() failed when overwrite requested." )
@@ -1280,9 +1275,9 @@ def SetupTargetLayer( poSrcDS, poSrcLayer, poDstDS, papszLCO, pszNewLayerName, \
 
         poDstLayer = None
 
-#/* -------------------------------------------------------------------- */
-#/*      If the layer does not exist, then create it.                    */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      If the layer does not exist, then create it.
+# --------------------------------------------------------------------
     if poDstLayer is None:
         if eGType == -2:
             eGType = poSrcFDefn.GetGeomType()
@@ -1326,9 +1321,9 @@ def SetupTargetLayer( poSrcDS, poSrcLayer, poDstDS, papszLCO, pszNewLayerName, \
 
         bAppend = False
 
-#/* -------------------------------------------------------------------- */
-#/*      Otherwise we will append to it, if append was requested.        */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Otherwise we will append to it, if append was requested.
+# --------------------------------------------------------------------
     elif not bAppend:
         print("FAILED: Layer " + pszNewLayerName + "already exists, and -append not specified.\n" + \
                             "        Consider using -append, or -overwrite.")
@@ -1338,12 +1333,12 @@ def SetupTargetLayer( poSrcDS, poSrcLayer, poDstDS, papszLCO, pszNewLayerName, \
             print("WARNING: Layer creation options ignored since an existing layer is\n" + \
                     "         being appended to." )
 
-#/* -------------------------------------------------------------------- */
-#/*      Add fields.  Default to copy all field.                         */
-#/*      If only a subset of all fields requested, then output only      */
-#/*      the selected fields, and in the order that they were            */
-#/*      selected.                                                       */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Add fields.  Default to copy all field.
+#      If only a subset of all fields requested, then output only
+#      the selected fields, and in the order that they were
+#      selected.
+# --------------------------------------------------------------------
 
     # Initialize the index-to-index map to -1's
     nSrcFieldCount = poSrcFDefn.GetFieldCount()
@@ -1385,7 +1380,7 @@ def SetupTargetLayer( poSrcDS, poSrcLayer, poDstDS, papszLCO, pszNewLayerName, \
                     if poDstFDefn is None:
                         poDstFDefn = poDstLayer.GetLayerDefn()
 
-                    #/* Sanity check : if it fails, the driver is buggy */
+                    # Sanity check : if it fails, the driver is buggy
                     if poDstFDefn is not None and \
                         poDstFDefn.GetFieldCount() != nDstFieldCount + 1:
                         print("The output driver has claimed to have added the %s field, but it did not!" %  oFieldDefn.GetNameRef() )
@@ -1398,9 +1393,9 @@ def SetupTargetLayer( poSrcDS, poSrcLayer, poDstDS, papszLCO, pszNewLayerName, \
                 if not bSkipFailures:
                     return None
 
-        #/* -------------------------------------------------------------------- */
-        #/* Use SetIgnoredFields() on source layer if available                  */
-        #/* -------------------------------------------------------------------- */
+        # --------------------------------------------------------------------
+        # Use SetIgnoredFields() on source layer if available
+        # --------------------------------------------------------------------
 
         # Here we differ from the ogr2ogr.cpp implementation since the OGRFeatureQuery
         # isn't mapped to swig. So in that case just don't use SetIgnoredFields()
@@ -1418,7 +1413,7 @@ def SetupTargetLayer( poSrcDS, poSrcLayer, poDstDS, papszLCO, pszNewLayerName, \
                 if pszZField is not None and EQUAL(pszFieldName, pszZField):
                     bFieldRequested = True
 
-                #/* If source field not requested, add it to ignored files list */
+                # If source field not requested, add it to ignored files list
                 if not bFieldRequested:
                     papszIgnoredFields.append(pszFieldName)
 
@@ -1456,7 +1451,7 @@ def SetupTargetLayer( poSrcDS, poSrcLayer, poDstDS, papszLCO, pszNewLayerName, \
                 if poDstFDefn is None:
                     poDstFDefn = poDstLayer.GetLayerDefn()
 
-                #/* Sanity check : if it fails, the driver is buggy */
+                # Sanity check : if it fails, the driver is buggy
                 if poDstFDefn is not None and \
                     poDstFDefn.GetFieldCount() != nDstFieldCount + 1:
                     print("The output driver has claimed to have added the %s field, but it did not!" %  oFieldDefn.GetNameRef() )
@@ -1465,8 +1460,8 @@ def SetupTargetLayer( poSrcDS, poSrcLayer, poDstDS, papszLCO, pszNewLayerName, \
                     nDstFieldCount = nDstFieldCount + 1
 
     else:
-        #/* For an existing layer, build the map by fetching the index in the destination */
-        #/* layer for each source field */
+        # For an existing layer, build the map by fetching the index in the destination
+        # layer for each source field
         if poDstFDefn is None:
             print( "poDstFDefn == NULL.\n" )
             return None
@@ -1490,9 +1485,9 @@ def SetupTargetLayer( poSrcDS, poSrcLayer, poDstDS, papszLCO, pszNewLayerName, \
 
     return psInfo
 
-#/************************************************************************/
-#/*                           TranslateLayer()                           */
-#/************************************************************************/
+#**********************************************************************
+#                           TranslateLayer()
+#**********************************************************************
 
 def TranslateLayer( psInfo, poSrcDS, poSrcLayer, poDstDS,  \
                     poOutputSRS, bNullifyOutputSRS, \
@@ -1504,7 +1499,7 @@ def TranslateLayer( psInfo, poSrcDS, poSrcLayer, poDstDS,  \
     bForceToPolygon = False
     bForceToMultiPolygon = False
     bForceToMultiLineString = False
-    
+
     poDstLayer = psInfo.poDstLayer
     #papszTransformOptions = psInfo.papszTransformOptions
     poCT = psInfo.poCT
@@ -1521,9 +1516,9 @@ def TranslateLayer( psInfo, poSrcDS, poSrcLayer, poDstDS,  \
     elif wkbFlatten(eGType) == ogr.wkbMultiLineString:
         bForceToMultiLineString = True
 
-#/* -------------------------------------------------------------------- */
-#/*      Transfer features.                                              */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Transfer features.
+# --------------------------------------------------------------------
     nFeaturesInTransaction = 0
     nCount = 0
 
@@ -1588,14 +1583,14 @@ def TranslateLayer( psInfo, poSrcDS, poSrcLayer, poDstDS,  \
             if poDstGeometry is not None:
 
                 if nParts > 0:
-                    # /* For -explodecollections, extract the iPart(th) of the geometry */
+                    # For -explodecollections, extract the iPart(th) of the geometry
                     poPart = poDstGeometry.GetGeometryRef(iPart).Clone()
                     poDstFeature.SetGeometryDirectly(poPart)
                     poDstGeometry = poPart
 
                 if iSrcZField != -1:
                     SetZ(poDstGeometry, poFeature.GetFieldAsDouble(iSrcZField))
-                    # /* This will correct the coordinate dimension to 3 */
+                    # This will correct the coordinate dimension to 3
                     poDupGeometry = poDstGeometry.Clone()
                     poDstFeature.SetGeometryDirectly(poDupGeometry)
                     poDstGeometry = poDupGeometry
@@ -1606,8 +1601,8 @@ def TranslateLayer( psInfo, poSrcDS, poSrcLayer, poDstDS,  \
 
                 if eGeomOp == GeomOperation.SEGMENTIZE:
                     pass
-                    #/*if (poDstFeature.GetGeometryRef() is not None and dfGeomOpParam > 0)
-                    #    poDstFeature.GetGeometryRef().segmentize(dfGeomOpParam);*/
+                    #if (poDstFeature.GetGeometryRef() is not None and dfGeomOpParam > 0)
+                    #    poDstFeature.GetGeometryRef().segmentize(dfGeomOpParam);
                 elif eGeomOp == GeomOperation.SIMPLIFY_PRESERVE_TOPOLOGY and dfGeomOpParam > 0:
                     poNewGeom = poDstGeometry.SimplifyPreserveTopology(dfGeomOpParam)
                     if poNewGeom is not None:
@@ -1617,7 +1612,7 @@ def TranslateLayer( psInfo, poSrcDS, poSrcLayer, poDstDS,  \
                 if poClipSrc is not None:
                     poClipped = poDstGeometry.Intersection(poClipSrc)
                     if poClipped is None or poClipped.IsEmpty():
-                        #/* Report progress */
+                        # Report progress
                         nCount = nCount +1
                         if pfnProgress is not None:
                             pfnProgress(nCount * 1.0 / nCountLayerFeatures, "", pProgressArg)
@@ -1665,7 +1660,7 @@ def TranslateLayer( psInfo, poSrcDS, poSrcLayer, poDstDS,  \
 
                 return False
 
-        #/* Report progress */
+        # Report progress
         nCount = nCount  + 1
         if pfnProgress is not None:
             if nSrcFileSize != 0:
@@ -1699,4 +1694,3 @@ if __name__ == '__main__':
         sys.exit(1)
     else:
         sys.exit(0)
-
diff --git a/swig/python/samples/ogr2vrt.py b/swig/python/samples/ogr2vrt.py
index c152859..a23356c 100755
--- a/swig/python/samples/ogr2vrt.py
+++ b/swig/python/samples/ogr2vrt.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 ###############################################################################
-# $Id: ogr2vrt.py 29016 2015-04-25 19:04:46Z rouault $
+# $Id: ogr2vrt.py 33791 2016-03-26 12:51:23Z goatbar $
 #
 # Project:  OGR Python samples
 # Purpose:  Create OGR VRT from source datasource
@@ -10,7 +10,7 @@
 ###############################################################################
 # Copyright (c) 2009, Frank Warmerdam <warmerdam at pobox.com>
 # Copyright (c) 2009-2014, Even Rouault <even dot rouault at mines-paris dot org>
-# 
+#
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
 # to deal in the Software without restriction, including without limitation
@@ -30,13 +30,10 @@
 # DEALINGS IN THE SOFTWARE.
 ###############################################################################
 
-try:
-    from osgeo import ogr, gdal
-except ImportError:
-    import  ogr, gdal
-
 import sys
 
+from osgeo import ogr, gdal
+
 #############################################################################
 
 def GeomType2Name( type ):
@@ -55,10 +52,18 @@ def GeomType2Name( type ):
             ogr.wkbCompoundCurve : ('wkbCompoundCurve', 'Z'),
             ogr.wkbCurvePolygon : ('wkbCurvePolygon', 'Z'),
             ogr.wkbMultiCurve : ('wkbMultiCurve', 'Z'),
-            ogr.wkbMultiSurface : ('wkbMultiSurface', 'Z') }
+            ogr.wkbMultiSurface : ('wkbMultiSurface', 'Z'),
+            ogr.wkbCurve : ('wkbCurve', 'Z'),
+            ogr.wkbSurface : ('wkbSurface', 'Z') }
     ret = dic[flat_type][0]
     if flat_type != type:
-        ret += dic[flat_type][1]
+        if ogr.GT_HasM(type):
+          if ogr.GT_HasZ(type):
+            ret += "ZM"
+          else:
+            ret += "M"
+        else:
+          ret += dic[flat_type][1]
     return ret
 
 #############################################################################
@@ -87,7 +92,7 @@ openoptions = []
 argv = gdal.GeneralCmdLineProcessor( sys.argv )
 if argv is None:
     sys.exit( 0 )
-        
+
 i = 1
 while i < len(argv):
     arg = argv[i]
@@ -132,7 +137,7 @@ if schema and feature_count:
 if schema and extent:
     sys.stderr.write('Ignoring -extent when used with -schema.\n')
     extent = 0
-    
+
 #############################################################################
 # Open the datasource to read.
 
@@ -203,14 +208,14 @@ for name in layer_list:
            % (relative,not schema,Esc(infile))
 
     if len(openoptions) > 0:
-        vrt += '    <OpenOptions>\n' 
+        vrt += '    <OpenOptions>\n'
         for option in openoptions:
             (key, value) = option.split('=')
             vrt += '        <OOI key="%s">%s</OOI>\n'  % (Esc(key), Esc(value))
-        vrt += '    </OpenOptions>\n' 
+        vrt += '    </OpenOptions>\n'
 
     if schema:
-        vrt += '    <SrcLayer>@dummy@</SrcLayer>\n' 
+        vrt += '    <SrcLayer>@dummy@</SrcLayer>\n'
     else:
         vrt += '    <SrcLayer>%s</SrcLayer>\n' % Esc(name)
 
@@ -303,7 +308,7 @@ for name in layer_list:
 
     vrt += '  </OGRVRTLayer>\n'
 
-vrt += '</OGRVRTDataSource>\n' 
+vrt += '</OGRVRTDataSource>\n'
 
 #############################################################################
 # Write vrt
diff --git a/swig/python/samples/ogr_build_junction_table.py b/swig/python/samples/ogr_build_junction_table.py
index 25f3963..fd8800e 100644
--- a/swig/python/samples/ogr_build_junction_table.py
+++ b/swig/python/samples/ogr_build_junction_table.py
@@ -2,9 +2,9 @@
 #!/usr/bin/env python
 #******************************************************************************
 #  $Id$
-# 
+#
 #  Name:     $Id$
-#  Project:  
+#  Project:
 #  Purpose:  Build a junction table from _href fields
 #  Author:   Even Rouault, <even dot rouault at mines-paris dot org>
 #
@@ -17,10 +17,10 @@
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -30,10 +30,10 @@
 #  DEALINGS IN THE SOFTWARE.
 #******************************************************************************
 
+import sys
 
 from osgeo import gdal
 from osgeo import ogr
-import sys
 
 
 def Usage():
diff --git a/swig/python/samples/ogr_dispatch.py b/swig/python/samples/ogr_dispatch.py
index 9b09576..388119a 100644
--- a/swig/python/samples/ogr_dispatch.py
+++ b/swig/python/samples/ogr_dispatch.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 ###############################################################################
-# $Id: ogr_dispatch.py 28392 2015-01-30 21:01:09Z rouault $
+# $Id: ogr_dispatch.py 31658 2015-11-20 14:27:51Z goatbar $
 #
 # Project:  GDAL/OGR samples
 # Purpose:  Dispatch features into layers according to the value of some fields
@@ -53,7 +53,7 @@ def Usage():
     print(' -src name: name of the source dataset.')
     print(' -dst name: name of the destination dataset (existing or to be created).')
     print(' -field field: name of a field to use to dispatch features. May also')
-    print('                        be \'OGR_GEOMETRY\'. At least, one occurence needed.')
+    print('                        be \'OGR_GEOMETRY\'. At least, one occurrence needed.')
     print(' -25D_as_2D: for dispatching, consider 2.5D geometries as 2D.')
     print(' -multi_as_single: for dispatching, consider MULTIPOLYGON as POLYGON and')
     print('                   MULTILINESTRING as LINESTRING.')
diff --git a/swig/python/samples/ogr_layer_algebra.py b/swig/python/samples/ogr_layer_algebra.py
index 8ae63c2..80e5e0d 100644
--- a/swig/python/samples/ogr_layer_algebra.py
+++ b/swig/python/samples/ogr_layer_algebra.py
@@ -1,25 +1,25 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #******************************************************************************
-#  $Id: ogr_layer_algebra.py 29254 2015-05-27 12:45:56Z rouault $
-# 
+#  $Id: ogr_layer_algebra.py 32002 2015-12-05 06:03:16Z goatbar $
+#
 #  Project:  GDAL Python Interface
 #  Purpose:  Application for executing OGR layer algebra operations
 #  Author:   Even Rouault, even dot rouault at mines-paris dot org
-# 
+#
 #******************************************************************************
 #  Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
-# 
+#
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
 #  to deal in the Software without restriction, including without limitation
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -29,10 +29,13 @@
 #  DEALINGS IN THE SOFTWARE.
 #******************************************************************************
 
-from osgeo import gdal, ogr, osr
 import os
 import sys
 
+from osgeo import gdal
+from osgeo import ogr
+from osgeo import osr
+
 ###############################################################################
 
 def Usage():
@@ -430,7 +433,7 @@ def main(argv = None):
     output_ds = None
 
     if ret != 0:
-        print('An error occured during %s operation' % op_str)
+        print('An error occurred during %s operation' % op_str)
         return 1
 
     return 0
diff --git a/swig/python/samples/ogrinfo.py b/swig/python/samples/ogrinfo.py
index 5f2bc2d..1cb65c4 100755
--- a/swig/python/samples/ogrinfo.py
+++ b/swig/python/samples/ogrinfo.py
@@ -1,47 +1,43 @@
 #!/usr/bin/env python
-#/******************************************************************************
-# * $Id: ogrinfo.py 28395 2015-01-31 10:21:04Z rouault $
-# *
-# * Project:  OpenGIS Simple Features Reference Implementation
-# * Purpose:  Python port of a simple client for viewing OGR driver data.
-# * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
-# *
-# * Port from ogrinfo.cpp whose author is Frank Warmerdam
-# *
-# ******************************************************************************
-# * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
-# * Copyright (c) 1999, Frank Warmerdam
-# *
-# * Permission is hereby granted, free of charge, to any person obtaining a
-# * copy of this software and associated documentation files (the "Software"),
-# * to deal in the Software without restriction, including without limitation
-# * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-# * and/or sell copies of the Software, and to permit persons to whom the
-# * Software is furnished to do so, subject to the following conditions:
-# *
-# * The above copyright notice and this permission notice shall be included
-# * in all copies or substantial portions of the Software.
-# *
-# * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-# * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# * DEALINGS IN THE SOFTWARE.
-# ****************************************************************************/
+#*****************************************************************************
+# $Id: ogrinfo.py 33791 2016-03-26 12:51:23Z goatbar $
+#
+# Project:  OpenGIS Simple Features Reference Implementation
+# Purpose:  Python port of a simple client for viewing OGR driver data.
+# Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+#
+# Port from ogrinfo.cpp whose author is Frank Warmerdam
+#
+#*****************************************************************************
+# Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
+# Copyright (c) 1999, Frank Warmerdam
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+#***************************************************************************/
 
 # Note : this is the most direct port of ogrinfo.cpp possible
 # It could be made much more Python'ish !
 
 import sys
 
-try:
-    from osgeo import gdal
-    from osgeo import ogr
-except:
-    import gdal
-    import ogr
+from osgeo import gdal
+from osgeo import ogr
 
 bReadOnly = False
 bVerbose = True
@@ -52,18 +48,18 @@ papszOptions = None
 def EQUAL(a, b):
     return a.lower() == b.lower()
 
-#/************************************************************************/
-#/*                                main()                                */
-#/************************************************************************/
+#**********************************************************************
+#                                main()
+#**********************************************************************
 
 def main(argv = None):
-    
+
     global bReadOnly
     global bVerbose
     global bSummaryOnly
     global nFetchFID
     global papszOptions
-    
+
     pszWHERE = None
     pszDataSource = None
     papszLayers = None
@@ -80,9 +76,9 @@ def main(argv = None):
 
     argv = ogr.GeneralCmdLineProcessor( argv )
 
-#/* -------------------------------------------------------------------- */
-#/*      Processing command line arguments.                              */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Processing command line arguments.
+# --------------------------------------------------------------------
     if argv is None:
         return 1
 
@@ -164,9 +160,9 @@ def main(argv = None):
     if pszDataSource is None:
         return Usage()
 
-#/* -------------------------------------------------------------------- */
-#/*      Open data source.                                               */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Open data source.
+# --------------------------------------------------------------------
     poDS = None
     poDriver = None
 
@@ -177,9 +173,9 @@ def main(argv = None):
             print( "Had to open data source read-only." )
             bReadOnly = True
 
-#/* -------------------------------------------------------------------- */
-#/*      Report failure                                                  */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Report failure.
+# --------------------------------------------------------------------
     if poDS is None:
         print( "FAILURE:\n"
                 "Unable to open datasource `%s' with the following drivers." % pszDataSource )
@@ -191,9 +187,9 @@ def main(argv = None):
 
     poDriver = poDS.GetDriver()
 
-#/* -------------------------------------------------------------------- */
-#/*      Some information messages.                                      */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Some information messages.
+# --------------------------------------------------------------------
     if bVerbose:
         print( "INFO: Open of `%s'\n"
                 "      using driver `%s' successful." % (pszDataSource, poDriver.GetName()) )
@@ -205,9 +201,9 @@ def main(argv = None):
         print( "INFO: Internal data source name `%s'\n"
                 "      different from user name `%s'." % (poDS_Name, pszDataSource ))
 
-#/* -------------------------------------------------------------------- */
-#/*      Special case for -sql clause.  No source layers required.       */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Special case for -sql clause.  No source layers required.
+# --------------------------------------------------------------------
     if pszSQLStatement is not None:
         poResultSet = None
 
@@ -217,7 +213,7 @@ def main(argv = None):
             print( "layer names ignored in combination with -sql." )
 
         if pszGeomField is None:
-            poResultSet = poDS.ExecuteSQL( pszSQLStatement, poSpatialFilter, 
+            poResultSet = poDS.ExecuteSQL( pszSQLStatement, poSpatialFilter,
                                             pszDialect )
         else:
             poResultSet = poDS.ExecuteSQL( pszSQLStatement, None, pszDialect )
@@ -238,9 +234,9 @@ def main(argv = None):
 
     for iRepeat in range(nRepeatCount):
         if papszLayers is None:
-#/* -------------------------------------------------------------------- */ 
-#/*      Process each data source layer.                                 */ 
-#/* -------------------------------------------------------------------- */ 
+# --------------------------------------------------------------------
+#      Process each data source layer.
+# --------------------------------------------------------------------
             for iLayer in range(poDS.GetLayerCount()):
                 poLayer = poDS.GetLayer(iLayer)
 
@@ -272,9 +268,9 @@ def main(argv = None):
                     ReportOnLayer( poLayer, pszWHERE, pszGeomField, poSpatialFilter, options )
 
         else:
-#/* -------------------------------------------------------------------- */ 
-#/*      Process specified data source layers.                           */ 
-#/* -------------------------------------------------------------------- */ 
+# --------------------------------------------------------------------
+#      Process specified data source layers.
+# --------------------------------------------------------------------
             for papszIter in papszLayers:
                 poLayer = poDS.GetLayerByName(papszIter)
 
@@ -287,16 +283,16 @@ def main(argv = None):
 
                 ReportOnLayer( poLayer, pszWHERE, pszGeomField, poSpatialFilter, options )
 
-#/* -------------------------------------------------------------------- */
-#/*      Close down.                                                     */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Close down.
+# --------------------------------------------------------------------
     poDS.Destroy()
 
     return 0
 
-#/************************************************************************/
-#/*                               Usage()                                */
-#/************************************************************************/
+#**********************************************************************
+#                               Usage()
+#**********************************************************************
 
 def Usage():
 
@@ -307,17 +303,17 @@ def Usage():
             "               datasource_name [layer [layer ...]]")
     return 1
 
-#/************************************************************************/
-#/*                           ReportOnLayer()                            */
-#/************************************************************************/
+#**********************************************************************
+#                           ReportOnLayer()
+#**********************************************************************
 
 def ReportOnLayer( poLayer, pszWHERE, pszGeomField, poSpatialFilter, options ):
 
     poDefn = poLayer.GetLayerDefn()
 
-#/* -------------------------------------------------------------------- */
-#/*      Set filters if provided.                                        */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Set filters if provided.
+# --------------------------------------------------------------------
     if pszWHERE is not None:
         if poLayer.SetAttributeFilter( pszWHERE ) != 0:
             print("FAILURE: SetAttributeFilter(%s) failed." % pszWHERE)
@@ -333,11 +329,11 @@ def ReportOnLayer( poLayer, pszWHERE, pszGeomField, poSpatialFilter, options ):
         else:
             poLayer.SetSpatialFilter( poSpatialFilter )
 
-#/* -------------------------------------------------------------------- */
-#/*      Report various overall information.                             */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Report various overall information.
+# --------------------------------------------------------------------
     print( "" )
-    
+
     print( "Layer name: %s" % poDefn.GetName() )
 
     if bVerbose:
@@ -348,9 +344,9 @@ def ReportOnLayer( poLayer, pszWHERE, pszGeomField, poSpatialFilter, options ):
                 print( "Geometry (%s): %s" % (poGFldDefn.GetNameRef(), ogr.GeometryTypeToName( poGFldDefn.GetType() ) ))
         else:
             print( "Geometry: %s" % ogr.GeometryTypeToName( poDefn.GetGeomType() ) )
-        
+
         print( "Feature Count: %d" % poLayer.GetFeatureCount() )
-        
+
         if nGeomFieldCount > 1:
             for iGeom in range(nGeomFieldCount):
                 poGFldDefn = poLayer.GetLayerDefn().GetGeomFieldDefn(iGeom)
@@ -376,10 +372,10 @@ def ReportOnLayer( poLayer, pszWHERE, pszGeomField, poSpatialFilter, options ):
             else:
                 pszWKT = poLayer.GetSpatialRef().ExportToPrettyWkt()
             print( "Layer SRS WKT:\n%s" % pszWKT )
-    
+
         if len(poLayer.GetFIDColumn()) > 0:
             print( "FID Column = %s" % poLayer.GetFIDColumn() )
-    
+
         if nGeomFieldCount > 1:
             for iGeom in range(nGeomFieldCount):
                 poGFldDefn = poLayer.GetLayerDefn().GetGeomFieldDefn(iGeom)
@@ -390,16 +386,16 @@ def ReportOnLayer( poLayer, pszWHERE, pszGeomField, poSpatialFilter, options ):
 
         for iAttr in range(poDefn.GetFieldCount()):
             poField = poDefn.GetFieldDefn( iAttr )
-            
+
             print( "%s: %s (%d.%d)" % ( \
                     poField.GetNameRef(), \
                     poField.GetFieldTypeName( poField.GetType() ), \
                     poField.GetWidth(), \
                     poField.GetPrecision() ))
 
-#/* -------------------------------------------------------------------- */
-#/*      Read, and dump features.                                        */
-#/* -------------------------------------------------------------------- */
+# --------------------------------------------------------------------
+#      Read, and dump features.
+# --------------------------------------------------------------------
     poFeature = None
 
     if nFetchFID == ogr.NullFID and not bSummaryOnly:
diff --git a/swig/python/samples/ogrupdate.py b/swig/python/samples/ogrupdate.py
index 010500e..d702a9b 100644
--- a/swig/python/samples/ogrupdate.py
+++ b/swig/python/samples/ogrupdate.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 ###############################################################################
-# $Id: ogrupdate.py 28391 2015-01-30 19:57:31Z rouault $
+# $Id: ogrupdate.py 33791 2016-03-26 12:51:23Z goatbar $
 #
 # Project:  GDAL/OGR samples
 # Purpose:  Update an existing datasource with features from another one
@@ -29,9 +29,11 @@
 # DEALINGS IN THE SOFTWARE.
 ###############################################################################
 
-from osgeo import ogr, gdal
 import sys
 
+from osgeo import gdal
+from osgeo import ogr
+
 DEFAULT = 0
 UPDATE_ONLY = 1
 APPEND_ONLY = 2
@@ -81,7 +83,7 @@ def ogrupdate_analyse_args(argv, progress = None, progress_arg = None):
     # in case there's no existing matching feature in the target datasource
     # should we preserve the FID of the source feature that will be inserted ?
     preserve_fid = False
-    
+
     # whether we should compare all fields from the features that are found to
     # be matching before actually updating
     compare_before_update = False
@@ -91,7 +93,7 @@ def ogrupdate_analyse_args(argv, progress = None, progress_arg = None):
     quiet = False
 
     skip_failures = False
-    
+
     papszSelFields = None
 
     dry_run = False
@@ -285,7 +287,7 @@ def ogrupdate_process(src_layer, dst_layer, matchfieldname = None, update_mode =
         dst_idx = dst_layer_defn.GetFieldIndex(matchfieldname)
         if dst_idx < 0:
             print('Cannot find field to match in destination layer')
-            return 1 
+            return 1
         dst_type = dst_layer_defn.GetFieldDefn(dst_idx).GetType()
 
     if papszSelFields is not None:
@@ -433,7 +435,8 @@ def ogrupdate_process(src_layer, dst_layer, matchfieldname = None, update_mode =
         if ret != 0:
             if not skip_failures:
                 if gdal.GetLastErrorMsg() == '':
-                    print('An error occured during feature insertion/update. Interrupting processing.')
+                    print('An error occurred during feature insertion/update. '
+                          'Interrupting processing.')
                 ret = 1
                 break
             else:
diff --git a/swig/python/samples/rel.py b/swig/python/samples/rel.py
index f737e24..aaa54e4 100755
--- a/swig/python/samples/rel.py
+++ b/swig/python/samples/rel.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: rel.py 28391 2015-01-30 19:57:31Z rouault $
+# $Id: rel.py 33320 2016-02-02 09:31:22Z rouault $
 #
 # Project:  GDAL Python samples
 # Purpose:  Script to produce a shaded relief image from elevation data
@@ -9,7 +9,7 @@
 ###############################################################################
 # Copyright (c) 2003, Andrey Kiselev <dron at remotesensing.org>
 # Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
-# 
+#
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
 # to deal in the Software without restriction, including without limitation
@@ -29,11 +29,11 @@
 # DEALINGS IN THE SOFTWARE.
 ###############################################################################
 
-try:
-    from osgeo import gdal
-    gdal.TermProgress = gdal.TermProgress_nocb
-except ImportError:
-    import gdal
+import math
+import sys
+
+from osgeo import gdal
+gdal.TermProgress = gdal.TermProgress_nocb
 
 try:
     import numpy as Numeric
@@ -46,9 +46,6 @@ try:
 except ImportError:
     import gdalnumeric
 
-import sys
-import math
-
 # =============================================================================
 def Usage():
     print('Usage: rel.py -lsrcaz azimuth -lsrcel elevation [-elstep step]')
@@ -59,7 +56,7 @@ def Usage():
     print('  -lsrcel elevation Elevation angle of the diffuse light source (0..180 degrees)')
     print('  -elstep step      Elevation change corresponding to a change of one grey level')
     print('                    (default 1)')
-    print('  -dx xsize         X and Y dimensions (in metres) of one pixel on the ground')
+    print('  -dx xsize         X and Y dimensions (in meters) of one pixel on the ground')
     print('  -dy ysize         (taken from the geotransform matrix by default)')
     print('  -r range	       Dynamic range for output image (default 255)')
     print('  -b band	       Select a band number to convert (default 1)')
diff --git a/swig/python/samples/tigerpoly.py b/swig/python/samples/tigerpoly.py
index 66d6e51..a36231f 100755
--- a/swig/python/samples/tigerpoly.py
+++ b/swig/python/samples/tigerpoly.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: tigerpoly.py 28391 2015-01-30 19:57:31Z rouault $
+# $Id: tigerpoly.py 33791 2016-03-26 12:51:23Z goatbar $
 #
 # Project:  OGR Python samples
 # Purpose:  Assemble TIGER Polygons.
@@ -9,7 +9,7 @@
 ###############################################################################
 # Copyright (c) 2003, Frank Warmerdam <warmerdam at pobox.com>
 # Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
-# 
+#
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
 # to deal in the Software without restriction, including without limitation
@@ -29,15 +29,12 @@
 # DEALINGS IN THE SOFTWARE.
 ###############################################################################
 
-try:
-    from osgeo import osr
-    from osgeo import ogr
-except ImportError:
-    import osr
-    import ogr
-
 import sys
 
+from osgeo import ogr
+from osgeo import osr
+
+
 #############################################################################
 class Module:
 
@@ -104,7 +101,7 @@ poly_field_count = src_defn.GetFieldCount()
 
 for fld_index in range(poly_field_count):
     src_fd = src_defn.GetFieldDefn( fld_index )
-    
+
     fd = ogr.FieldDefn( src_fd.GetName(), src_fd.GetType() )
     fd.SetWidth( src_fd.GetWidth() )
     fd.SetPrecision( src_fd.GetPrecision() )
@@ -143,7 +140,7 @@ print('Got %d lines in %d modules.' % (line_count,len(modules_hash)))
 
 #############################################################################
 # Read all polygon/chain links and build a hash keyed by POLY_ID listing
-# the chains (by TLID) attached to it. 
+# the chains (by TLID) attached to it.
 
 link_layer = ds.GetLayerByName( 'PolyChainLink' )
 
@@ -163,12 +160,11 @@ while feat is not None:
     lpoly_id = feat.GetField( lpoly_field )
     rpoly_id = feat.GetField( rpoly_field )
 
- 
     if lpoly_id == rpoly_id:
         feat.Destroy()
         feat = link_layer.GetNextFeature()
-        continue    
-    
+        continue
+
     try:
         module.poly_line_links[lpoly_id].append( tlid )
     except:
@@ -217,7 +213,7 @@ while feat is not None:
             feat.Destroy()
             feat = poly_layer.GetNextFeature()
             continue
-        
+
         #print poly.ExportToWkt()
         #feat.SetGeometryDirectly( poly )
 
@@ -239,7 +235,7 @@ while feat is not None:
 
     feat = poly_layer.GetNextFeature()
 
-if degenerate_count: 
+if degenerate_count:
     print('Discarded %d degenerate polygons.' % degenerate_count)
 
 print('Built %d polygons.' % poly_count)
diff --git a/swig/python/samples/tolatlong.py b/swig/python/samples/tolatlong.py
index e7d1c80..32a5ed6 100755
--- a/swig/python/samples/tolatlong.py
+++ b/swig/python/samples/tolatlong.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: tolatlong.py 28450 2015-02-11 13:09:05Z rouault $
+# $Id: tolatlong.py 31957 2015-12-02 12:44:54Z goatbar $
 #
 # Project:  GDAL Python samples
 # Purpose:  Script to read coordinate system and geotransformation matrix
@@ -11,7 +11,7 @@
 ###############################################################################
 # Copyright (c) 2003, Andrey Kiselev <dron at remotesensing.org>
 # Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
-# 
+#
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
 # to deal in the Software without restriction, including without limitation
@@ -31,11 +31,8 @@
 # DEALINGS IN THE SOFTWARE.
 ###############################################################################
 
-try:
-    from osgeo import gdal, osr
-except ImportError:
-    import gdal
-    import osr
+from osgeo import gdal
+from osgeo import osr
 
 import sys
 
diff --git a/swig/python/samples/val_at_coord.py b/swig/python/samples/val_at_coord.py
index a0a3bb3..387459e 100755
--- a/swig/python/samples/val_at_coord.py
+++ b/swig/python/samples/val_at_coord.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: val_at_coord.py 28391 2015-01-30 19:57:31Z rouault $
+# $Id: val_at_coord.py 31957 2015-12-02 12:44:54Z goatbar $
 #
 # Project:  GDAL Python samples
 # Purpose:  Outputs the value of the raster bands at a given
@@ -9,7 +9,7 @@
 #
 ###############################################################################
 # Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
-# 
+#
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
 # to deal in the Software without restriction, including without limitation
@@ -29,11 +29,8 @@
 # DEALINGS IN THE SOFTWARE.
 ###############################################################################
 
-try:
-    from osgeo import gdal
-    from osgeo import osr
-except ImportError:
-    import gdal
+from osgeo import gdal
+from osgeo import osr
 
 import sys
 
@@ -43,7 +40,7 @@ def Usage():
     print('')
     print('By default, the 2 first arguments are supposed to be the location')
     print('in longitude, latitude order. If -coordtype=georef is specified before')
-    print('the next 2 values will be interpretated as the X and Y coordinates')
+    print('the next 2 values will be interpreted as the X and Y coordinates')
     print('in the dataset spatial reference system.')
     sys.exit( 1 )
 
diff --git a/swig/python/samples/val_repl.py b/swig/python/samples/val_repl.py
index b5c0702..b27cf64 100755
--- a/swig/python/samples/val_repl.py
+++ b/swig/python/samples/val_repl.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: val_repl.py 28391 2015-01-30 19:57:31Z rouault $
+# $Id: val_repl.py 31957 2015-12-02 12:44:54Z goatbar $
 #
 # Project:  GDAL Python samples
 # Purpose:  Script to replace specified values from the input raster file
@@ -12,7 +12,7 @@
 ###############################################################################
 # Copyright (c) 2003, Andrey Kiselev <dron at remotesensing.org>
 # Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
-# 
+#
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
 # to deal in the Software without restriction, including without limitation
@@ -33,11 +33,8 @@
 ###############################################################################
 
 
-try:
-    from osgeo import gdal
-    gdal.TermProgress = gdal.TermProgress_nocb
-except ImportError:
-    import gdal
+from osgeo import gdal
+gdal.TermProgress = gdal.TermProgress_nocb
 
 try:
     import numpy
diff --git a/swig/python/samples/validate_jp2.py b/swig/python/samples/validate_jp2.py
index 267a569..7198bb6 100644
--- a/swig/python/samples/validate_jp2.py
+++ b/swig/python/samples/validate_jp2.py
@@ -1,25 +1,25 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #******************************************************************************
-#  $Id: validate_jp2.py 29330 2015-06-14 12:11:11Z rouault $
-# 
+#  $Id: validate_jp2.py 31957 2015-12-02 12:44:54Z goatbar $
+#
 #  Project:  GDAL
 #  Purpose:  Validate JPEG2000 file structure
 #  Author:   Even Rouault, <even dot rouault at spatialys dot com>
-# 
+#
 #******************************************************************************
 #  Copyright (c) 2015, European Union (European Environment Agency)
-# 
+#
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
 #  to deal in the Software without restriction, including without limitation
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -1080,7 +1080,8 @@ def validate(filename, oidoc, inspire_tg, expected_gmljp2, ogc_schemas_location,
                             if count_fields != Csiz:
                                 error_report.EmitError('INSPIRE_TG', 'count(OrthoImageryCoverage.rangeType.field)(=%d) != Csiz(=%d) ' % (count_fields, Csiz), conformance_class = 'A.8.6')
                             else:
-                                # Check consistency of each channel bit-deph with the corresponding rangeType.field
+                                # Check consistency of each channel bit-depth
+                                # with the corresponding rangeType.field.
                                 for i in range(Csiz):
                                     if tab_Ssiz[i] >= 128:
                                         tab_Ssiz[i] -= 128
@@ -1133,7 +1134,10 @@ def validate(filename, oidoc, inspire_tg, expected_gmljp2, ogc_schemas_location,
             for i in range(SPcod_NumDecompositions+1):
                 SPcod_Precincts = get_field_val(cod, 'SPcod_Precincts%d' % i)
                 if SPcod_Precincts is not None and (Scod & 1) == 0:
-                    error_report.EmitWarning('GENERAL', 'User-defined precincts %d found but SPcod_transformation dit not advertize it' % i)
+                    error_report.EmitWarning(
+                        'GENERAL',
+                        'User-defined precincts %d found but '
+                        'SPcod_transformation did not advertize it' % i)
                 elif SPcod_Precincts is None and (Scod & 1) != 0:
                     error_report.EmitWarning('GENERAL', 'No user-defined precincts %d defined but SPcod_transformation advertized it' % i)
                 elif SPcod_Precincts is None and inspire_tg:
diff --git a/swig/python/samples/vec_tr.py b/swig/python/samples/vec_tr.py
index ec62269..bd6b5dd 100755
--- a/swig/python/samples/vec_tr.py
+++ b/swig/python/samples/vec_tr.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: vec_tr.py 28391 2015-01-30 19:57:31Z rouault $
+# $Id: vec_tr.py 31957 2015-12-02 12:44:54Z goatbar $
 #
 # Project:  OGR Python samples
 # Purpose:  Apply a transformation to all OGR geometries.
@@ -8,7 +8,7 @@
 #
 ###############################################################################
 # Copyright (c) 2006, Frank Warmerdam <warmerdam at pobox.com>
-# 
+#
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
 # to deal in the Software without restriction, including without limitation
@@ -28,13 +28,10 @@
 # DEALINGS IN THE SOFTWARE.
 ###############################################################################
 
-try:
-    from osgeo import ogr
-except ImportError:
-    import ogr
-
 import sys
 
+from osgeo import ogr
+
 #############################################################################
 def TransformPoint( xyz ):
 
@@ -61,7 +58,7 @@ def WalkAndTransform( geom ):
         xyz = (geom.GetX(i), geom.GetY(i), geom.GetZ(i))
 
         xyz = TransformPoint( xyz )
-        
+
         geom.SetPoint( i, xyz[0], xyz[1], xyz[2] )
 
     return geom
@@ -128,7 +125,7 @@ in_field_count = in_defn.GetFieldCount()
 
 for fld_index in range(in_field_count):
     src_fd = in_defn.GetFieldDefn( fld_index )
-    
+
     fd = ogr.FieldDefn( src_fd.GetName(), src_fd.GetType() )
     fd.SetWidth( src_fd.GetWidth() )
     fd.SetPrecision( src_fd.GetPrecision() )
@@ -143,7 +140,7 @@ while in_feat is not None:
     geom = in_feat.GetGeometryRef().Clone()
 
     geom = WalkAndTransform( geom )
-    
+
     out_feat = ogr.Feature( feature_def = shp_layer.GetLayerDefn() )
     out_feat.SetFrom( in_feat )
     out_feat.SetGeometryDirectly( geom )
diff --git a/swig/python/samples/vec_tr_spat.py b/swig/python/samples/vec_tr_spat.py
index 54b1f4d..d51c16d 100755
--- a/swig/python/samples/vec_tr_spat.py
+++ b/swig/python/samples/vec_tr_spat.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: vec_tr_spat.py 28391 2015-01-30 19:57:31Z rouault $
+# $Id: vec_tr_spat.py 31957 2015-12-02 12:44:54Z goatbar $
 #
 # Project:  OGR Python samples
 # Purpose:  Apply a transformation to all OGR geometries.
@@ -8,7 +8,7 @@
 #
 ###############################################################################
 # Copyright (c) 2006, Frank Warmerdam <warmerdam at pobox.com>
-# 
+#
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
 # to deal in the Software without restriction, including without limitation
@@ -28,13 +28,10 @@
 # DEALINGS IN THE SOFTWARE.
 ###############################################################################
 
-try:
-    from osgeo import ogr
-except ImportError:
-    import ogr
-
 import sys
 
+from osgeo import ogr
+
 #############################################################################
 def Usage():
     print('Usage: vec_tr_spat.py [-spat xmin ymin xmax ymax] infile outfile [layer]')
@@ -58,7 +55,7 @@ while i < len(sys.argv):
         s_maxx = int(sys.argv[i+3])
         s_maxy = int(sys.argv[i+4])
         i = i + 4
-        
+
     elif infile is None:
         infile = arg
 
@@ -104,7 +101,7 @@ in_field_count = in_defn.GetFieldCount()
 
 for fld_index in range(in_field_count):
     src_fd = in_defn.GetFieldDefn( fld_index )
-    
+
     fd = ogr.FieldDefn( src_fd.GetName(), src_fd.GetType() )
     fd.SetWidth( src_fd.GetWidth() )
     fd.SetPrecision( src_fd.GetPrecision() )
diff --git a/swig/python/samples/wcs_virtds_params.py b/swig/python/samples/wcs_virtds_params.py
index 51f25e6..704ac9f 100644
--- a/swig/python/samples/wcs_virtds_params.py
+++ b/swig/python/samples/wcs_virtds_params.py
@@ -2,7 +2,7 @@
 #!/usr/bin/env python
 #******************************************************************************
 #  $Id$
-# 
+#
 #  Name:     wcs_virtds_params.py
 #  Project:  GDAL Python Interface
 #  Purpose:  Generates MapServer WCS layer definition from a tileindex with mixed SRS
@@ -17,10 +17,10 @@
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -30,12 +30,12 @@
 #  DEALINGS IN THE SOFTWARE.
 #******************************************************************************
 
+import os
+import sys
 
 from osgeo import gdal
 from osgeo import ogr
 from osgeo import osr
-import os
-import sys
 
 
 def Usage():
@@ -173,7 +173,7 @@ if ogr_ds.GetDriver().GetName() != 'ESRI Shapefile':
   CONNECTIONTYPE OGR
   CONNECTION "%s,%s"
   PROJECTION
-    "+init=epsg:%s" 
+    "+init=epsg:%s"
   END
 END""" % (layername, ogr_ds_name, lyr.GetName(), authority_code))
     print("")
@@ -190,9 +190,9 @@ print("""LAYER
   TILEITEM "%s"
   TILESRS "%s"
   PROJECTION
-    "+init=epsg:%s" 
+    "+init=epsg:%s"
   END
-  METADATA   
+  METADATA
    "wcs_label"       "%s"
    "wcs_rangeset_name"   "Range 1"  ### required to support DescribeCoverage request
    "wcs_rangeset_label"  "My Label" ### required to support DescribeCoverage request
diff --git a/swig/python/scripts/epsg_tr.py b/swig/python/scripts/epsg_tr.py
index 1d0044e..d857034 100755
--- a/swig/python/scripts/epsg_tr.py
+++ b/swig/python/scripts/epsg_tr.py
@@ -1,27 +1,27 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #******************************************************************************
-#  $Id: epsg_tr.py 28389 2015-01-30 19:26:09Z rouault $
-# 
+#  $Id: epsg_tr.py 32555 2015-12-30 19:26:44Z goatbar $
+#
 #  Project:  CFS OGC MapServer
 #  Purpose:  Script to create WKT and PROJ.4 dictionaries for EPSG GCS/PCS
 #            codes.
 #  Author:   Frank Warmerdam, warmerdam at pobox.com
-# 
+#
 #******************************************************************************
 #  Copyright (c) 2001, Frank Warmerdam
 #  Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
-# 
+#
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
 #  to deal in the Software without restriction, including without limitation
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -31,15 +31,11 @@
 #  DEALINGS IN THE SOFTWARE.
 #******************************************************************************
 
-try:
-    from osgeo import osr
-    from osgeo import gdal
-except ImportError:
-    import osr
-    import gdal
-
-import sys
 import string
+import sys
+
+from osgeo import osr
+from osgeo import gdal
 
 # =============================================================================
 def Usage():
@@ -58,7 +54,7 @@ def trHandleCode(code, gen_dict_line, report_error, output_format):
 
     if err != 0 and report_error:
         print('Unable to lookup %d, either not a valid EPSG' % code)
-        print('code, or it the EPSG csv files are not accessable.')
+        print('code, or it the EPSG CSV files are not accessible.')
         sys.exit(2)
     else:
         if output_format == '-pretty_wkt':
@@ -69,13 +65,13 @@ def trHandleCode(code, gen_dict_line, report_error, output_format):
 
         if output_format == '-xml':
             print(prj_srs.ExportToXML())
-            
+
         if output_format == '-wkt':
             if gen_dict_line:
                 print('EPSG:%d' % code)
-                    
+
             print(prj_srs.ExportToWkt())
-                
+
         if output_format == '-proj4':
             out_string = prj_srs.ExportToProj4()
 
@@ -89,12 +85,13 @@ def trHandleCode(code, gen_dict_line, report_error, output_format):
 
             if name is None:
                 name = 'Unknown'
-            
+
             print('# %s' % name)
             if err == 0 and out_string.find('+proj=') > -1:
                 print('<%s> %s <>' % (str(code), out_string))
             else:
-                print('# Unable to translate coordinate system EPSG:%d into PROJ.4 format.' % code)
+                print('# Unable to translate coordinate system '
+                      'EPSG:%d into PROJ.4 format.' % code)
                 print('#')
 
         if output_format == '-postgis':
@@ -112,7 +109,7 @@ def trHandleCode(code, gen_dict_line, report_error, output_format):
             except:
                 err = 1
             wkt = prj_srs.ExportToWkt()
-            
+
             print('---')
             print('--- EPSG %d : %s' % (code, name))
             print('---')
@@ -127,7 +124,7 @@ def trHandleCode(code, gen_dict_line, report_error, output_format):
 
         # INGRES COPY command input.
         if output_format == '-copy':
-            
+
             try:
                 wkt = prj_srs.ExportToWkt()
                 proj4text = prj_srs.ExportToProj4()
@@ -147,13 +144,13 @@ if __name__ == '__main__':
     list_file = None
     output_format = '-pretty_wkt'
     report_error = 1
-    
+
     argv = gdal.GeneralCmdLineProcessor( sys.argv )
     if argv is None:
         sys.exit( 0 )
-        
+
     # Parse command line arguments.
-    
+
     i = 1
     while i < len(argv):
         arg = argv[i]
@@ -164,16 +161,16 @@ if __name__ == '__main__':
 
         elif arg[:5] == '-skip':
             report_error = 0
-            
+
         elif arg == '-list' and i < len(argv)-1:
             i = i + 1
             list_file = argv[i]
-            
+
         elif arg[0] == '-':
             Usage()
 
         elif int(arg) > 0:
-            
+
             if start_code == -1:
                 start_code = int(arg)
                 end_code = int(arg)
@@ -196,7 +193,7 @@ if __name__ == '__main__':
     gen_dict_line = start_code != end_code
 
     # loop over all codes to generate output
-    
+
     prj_srs = osr.SpatialReference()
 
     if start_code != -1:
@@ -214,22 +211,20 @@ if __name__ == '__main__':
                 c_offset = line.find(',')
                 if c_offset > 0:
                     line = line[:c_offset]
-                    
+
                 code = string.atoi(line)
             except:
                 code = -1
 
             if code != -1:
                 trHandleCode(code, gen_dict_line, report_error, output_format)
-                
+
             line = list_fd.readline()
 
     else:
         Usage()
-        
+
     # Output COMMIT transaction for PostGIS
     if output_format == '-postgis':
         print('COMMIT;')
         print('VACUUM ANALYZE spatial_ref_sys;')
-
-
diff --git a/swig/python/scripts/esri2wkt.py b/swig/python/scripts/esri2wkt.py
index d7ba931..d0b4d00 100755
--- a/swig/python/scripts/esri2wkt.py
+++ b/swig/python/scripts/esri2wkt.py
@@ -1,25 +1,25 @@
 #!/usr/bin/env python
 #******************************************************************************
-#  $Id: esri2wkt.py 18952 2010-02-28 11:59:53Z rouault $
-# 
+#  $Id: esri2wkt.py 32555 2015-12-30 19:26:44Z goatbar $
+#
 #  Project:  GDAL
 #  Purpose:  Simple command line program for translating ESRI .prj files
-#            into WKT. 
+#            into WKT.
 #  Author:   Frank Warmerdam, warmerda at home.com
-# 
+#
 #******************************************************************************
 #  Copyright (c) 2000, Frank Warmerdam
-# 
+#
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
 #  to deal in the Software without restriction, including without limitation
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -29,18 +29,16 @@
 #  DEALINGS IN THE SOFTWARE.
 #******************************************************************************
 
-try:
-    from osgeo import osr
-except ImportError:
-    import osr
-
-import sys
 import string
+import sys
+
+from osgeo import osr
+
 
 if len(sys.argv) < 2:
     print('Usage: esri2wkt.py <esri .prj file>')
     sys.exit(1)
-    
+
 prj_fd = open( sys.argv[1] )
 prj_lines = prj_fd.readlines()
 prj_fd.close()
@@ -54,4 +52,3 @@ if err != 0:
     print('Error = %d' % err)
 else:
     print(prj_srs.ExportToPrettyWkt())
-
diff --git a/swig/python/scripts/gcps2vec.py b/swig/python/scripts/gcps2vec.py
index cdb8230..8b45b5a 100755
--- a/swig/python/scripts/gcps2vec.py
+++ b/swig/python/scripts/gcps2vec.py
@@ -1,24 +1,24 @@
 #!/usr/bin/env python
 #******************************************************************************
-#  $Id: gcps2vec.py 28389 2015-01-30 19:26:09Z rouault $
-# 
+#  $Id: gcps2vec.py 33790 2016-03-26 12:42:12Z goatbar $
+#
 #  Project:  GDAL
 #  Purpose:  Convert GCPs to a point layer.
 #  Author:   Frank Warmerdam, warmerdam at pobox.com
-# 
+#
 #******************************************************************************
 #  Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
-# 
+#
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
 #  to deal in the Software without restriction, including without limitation
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -28,17 +28,13 @@
 #  DEALINGS IN THE SOFTWARE.
 #******************************************************************************
 
-try:
-    from osgeo import gdal
-    from osgeo import ogr
-    from osgeo import osr
-except ImportError:
-    import gdal
-    import ogr
-    import osr
-
 import sys
 
+from osgeo import gdal
+from osgeo import ogr
+from osgeo import osr
+
+
 def Usage():
     print('Usage: gcps2vec.py [-of <ogr_drivername>] [-p] <raster_file> <vector_file>')
     sys.exit(1)
@@ -84,7 +80,7 @@ if out_file is None:
     Usage()
 
 # ----------------------------------------------------------------------------
-# Open input file, and fetch GCPs. 
+# Open input file, and fetch GCPs.
 # ----------------------------------------------------------------------------
 ds = gdal.Open( in_file )
 if ds is None:
@@ -147,7 +143,7 @@ fd = ogr.FieldDefn( 'Info', ogr.OFTString )
 layer.CreateField( fd )
 
 # ----------------------------------------------------------------------------
-# Write GCPs. 
+# Write GCPs.
 # ----------------------------------------------------------------------------
 
 for gcp in gcps:
@@ -165,7 +161,7 @@ for gcp in gcps:
         feat.SetField( 'Y',  gcp.GCPY )
         feat.SetField( 'Z',  gcp.GCPZ )
         geom.SetPoint( 0, gcp.GCPPixel, gcp.GCPLine )
-        
+
     feat.SetField( 'Id',    gcp.Id )
     feat.SetField( 'Info',  gcp.Info )
 
@@ -174,5 +170,3 @@ for gcp in gcps:
 
 feat = None
 ds.Destroy()
-
-
diff --git a/swig/python/scripts/gcps2wld.py b/swig/python/scripts/gcps2wld.py
index d5c0d15..f4ac5a6 100755
--- a/swig/python/scripts/gcps2wld.py
+++ b/swig/python/scripts/gcps2wld.py
@@ -1,27 +1,27 @@
 #!/usr/bin/env python
 #******************************************************************************
-#  $Id: gcps2wld.py 28389 2015-01-30 19:26:09Z rouault $
-# 
+#  $Id: gcps2wld.py 32555 2015-12-30 19:26:44Z goatbar $
+#
 #  Name:     gcps2wld
 #  Project:  GDAL Python Interface
 #  Purpose:  Translate the set of GCPs on a file into first order approximation
 #            in world file format.
 #  Author:   Frank Warmerdam, warmerdam at pobox.com
-# 
+#
 #******************************************************************************
 #  Copyright (c) 2002, Frank Warmerdam
 #  Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
-# 
+#
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
 #  to deal in the Software without restriction, including without limitation
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -31,19 +31,14 @@
 #  DEALINGS IN THE SOFTWARE.
 #******************************************************************************
 
-try:
-    from osgeo import gdal
-except ImportError:
-    import gdal
-
 import sys
 
+from osgeo import gdal
+
 if len(sys.argv) < 2:
     print("Usage: gcps2wld.py source_file")
     sys.exit(1)
 
-    
-
 filename = sys.argv[1]
 dataset = gdal.Open( filename )
 if dataset is None:
@@ -60,7 +55,7 @@ geotransform = gdal.GCPsToGeoTransform( gcps )
 
 if geotransform is None:
     print('Unable to extract a geotransform.')
-    sys.exit( 1 ) 
+    sys.exit( 1 )
 
 print(geotransform[1])
 print(geotransform[4])
@@ -68,5 +63,3 @@ print(geotransform[2])
 print(geotransform[5])
 print(geotransform[0] + 0.5 * geotransform[1] + 0.5 * geotransform[2])
 print(geotransform[3] + 0.5 * geotransform[4] + 0.5 * geotransform[5])
-
-
diff --git a/swig/python/scripts/gdal2tiles.py b/swig/python/scripts/gdal2tiles.py
index deb2d46..2e0cfe9 100755
--- a/swig/python/scripts/gdal2tiles.py
+++ b/swig/python/scripts/gdal2tiles.py
@@ -1,8 +1,8 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #******************************************************************************
-#  $Id: gdal2tiles.py 28392 2015-01-30 21:01:09Z rouault $
-# 
+#  $Id: gdal2tiles.py 33790 2016-03-26 12:42:12Z goatbar $
+#
 # Project:  Google Summer of Code 2007, 2008 (http://code.google.com/soc/)
 # Support:  BRGM (http://www.brgm.fr)
 # Purpose:  Convert a raster into TMS (Tile Map Service) tiles in a directory.
@@ -17,17 +17,17 @@
 ###############################################################################
 # Copyright (c) 2008, Klokan Petr Pridal
 # Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
-# 
+#
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
 #  to deal in the Software without restriction, including without limitation
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -37,18 +37,12 @@
 #  DEALINGS IN THE SOFTWARE.
 #******************************************************************************
 
+import math
+import os
 import sys
 
-try:
-    from osgeo import gdal
-    from osgeo import osr
-except:
-    import gdal
-    print('You are using "old gen" bindings. gdal2tiles needs "new gen" bindings.')
-    sys.exit(1)
-
-import os
-import math
+from osgeo import gdal
+from osgeo import osr
 
 try:
     from PIL import Image
@@ -58,11 +52,11 @@ except:
     # 'antialias' resampling is not available
     pass
 
-__version__ = "$Id: gdal2tiles.py 28392 2015-01-30 21:01:09Z rouault $"
+__version__ = "$Id: gdal2tiles.py 33790 2016-03-26 12:42:12Z goatbar $"
 
 resampling_list = ('average','near','bilinear','cubic','cubicspline','lanczos','antialias')
 profile_list = ('mercator','geodetic','raster') #,'zoomify')
-webviewer_list = ('all','google','openlayers','none')
+webviewer_list = ('all','google','openlayers','leaflet','none')
 
 # =============================================================================
 # =============================================================================
@@ -77,7 +71,7 @@ Global Map Tiles as defined in Tile Map Service (TMS) Profiles
 Functions necessary for generation of global tiles used on the web.
 It contains classes implementing coordinate conversions for:
 
-  - GlobalMercator (based on EPSG:900913 = EPSG:3785)
+  - GlobalMercator (based on EPSG:3857)
        for Google Maps, Yahoo Maps, Bing Maps compatible tiles
   - GlobalGeodetic (based on EPSG:4326)
        for OpenLayers Base Map and Google Earth compatible tiles
@@ -108,7 +102,7 @@ class GlobalMercator(object):
     ---------------------------
 
   Functions necessary for generation of tiles in Spherical Mercator projection,
-  EPSG:900913 (EPSG:gOOglE, Google Maps Global Mercator), EPSG:3785, OSGEO:41001.
+  EPSG:3857.
 
   Such tiles are compatible with Google Maps, Bing Maps, Yahoo Maps,
   UK Ordnance Survey OpenSpace API, ...
@@ -118,27 +112,27 @@ class GlobalMercator(object):
 
     What coordinate conversions do we need for TMS Global Mercator tiles::
 
-         LatLon      <->       Meters      <->     Pixels    <->       Tile     
+         LatLon      <->       Meters      <->     Pixels    <->       Tile
 
      WGS84 coordinates   Spherical Mercator  Pixels in pyramid  Tiles in pyramid
-         lat/lon            XY in metres     XY pixels Z zoom      XYZ from TMS 
-        EPSG:4326           EPSG:900913                                         
-         .----.              ---------               --                TMS      
-        /      \     <->     |       |     <->     /----/    <->      Google    
-        \      /             |       |           /--------/          QuadTree   
-         -----               ---------         /------------/                   
+         lat/lon            XY in meters     XY pixels Z zoom      XYZ from TMS
+        EPSG:4326           EPSG:387
+         .----.              ---------               --                TMS
+        /      \     <->     |       |     <->     /----/    <->      Google
+        \      /             |       |           /--------/          QuadTree
+         -----               ---------         /------------/
        KML, public         WebMapService         Web Clients      TileMapService
 
-    What is the coordinate extent of Earth in EPSG:900913?
+    What is the coordinate extent of Earth in EPSG:3857?
 
       [-20037508.342789244, -20037508.342789244, 20037508.342789244, 20037508.342789244]
       Constant 20037508.342789244 comes from the circumference of the Earth in meters,
       which is 40 thousand kilometers, the coordinate origin is in the middle of extent.
       In fact you can calculate the constant as: 2 * math.pi * 6378137 / 2.0
-      $ echo 180 85 | gdaltransform -s_srs EPSG:4326 -t_srs EPSG:900913
+      $ echo 180 85 | gdaltransform -s_srs EPSG:4326 -t_srs EPSG:3857
       Polar areas with abs(latitude) bigger then 85.05112878 are clipped off.
 
-    What are zoom level constants (pixels/meter) for pyramid with EPSG:900913?
+    What are zoom level constants (pixels/meter) for pyramid with EPSG:3857?
 
       whole region is on top of pyramid (zoom=0) covered by 256x256 pixels tile,
       every lower zoom level resolution is always divided by two
@@ -153,35 +147,36 @@ class GlobalMercator(object):
       Microsoft is referencing tiles by a QuadTree name, defined on the website:
       http://msdn2.microsoft.com/en-us/library/bb259689.aspx
 
-    The lat/lon coordinates are using WGS84 datum, yeh?
+    The lat/lon coordinates are using WGS84 datum, yes?
 
       Yes, all lat/lon we are mentioning should use WGS84 Geodetic Datum.
       Well, the web clients like Google Maps are projecting those coordinates by
       Spherical Mercator, so in fact lat/lon coordinates on sphere are treated as if
       the were on the WGS84 ellipsoid.
-     
+
       From MSDN documentation:
       To simplify the calculations, we use the spherical form of projection, not
       the ellipsoidal form. Since the projection is used only for map display,
       and not for displaying numeric coordinates, we don't need the extra precision
       of an ellipsoidal projection. The spherical projection causes approximately
-      0.33 percent scale distortion in the Y direction, which is not visually noticable.
+      0.33 percent scale distortion in the Y direction, which is not visually
+      noticeable.
 
-    How do I create a raster in EPSG:900913 and convert coordinates with PROJ.4?
+    How do I create a raster in EPSG:3857 and convert coordinates with PROJ.4?
 
       You can use standard GIS tools like gdalwarp, cs2cs or gdaltransform.
-      All of the tools supports -t_srs 'epsg:900913'.
+      All of the tools supports -t_srs 'epsg:3857'.
 
       For other GIS programs check the exact definition of the projection:
       More info at http://spatialreference.org/ref/user/google-projection/
-      The same projection is degined as EPSG:3785. WKT definition is in the official
-      EPSG database.
+      The same projection is designated as EPSG:3857. WKT definition is in the
+      official EPSG database.
 
       Proj4 Text:
         +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0
         +k=1.0 +units=m +nadgrids=@null +no_defs
 
-      Human readable WKT format of EPGS:900913:
+      Human readable WKT format of EPSG:3857:
          PROJCS["Google Maps Global Mercator",
              GEOGCS["WGS 84",
                  DATUM["WGS_1984",
@@ -209,7 +204,7 @@ class GlobalMercator(object):
         # 20037508.342789244
 
     def LatLonToMeters(self, lat, lon ):
-        "Converts given lat/lon in WGS84 Datum to XY in Spherical Mercator EPSG:900913"
+        "Converts given lat/lon in WGS84 Datum to XY in Spherical Mercator EPSG:3857"
 
         mx = lon * self.originShift / 180.0
         my = math.log( math.tan((90 + lat) * math.pi / 360.0 )) / (math.pi / 180.0)
@@ -218,7 +213,7 @@ class GlobalMercator(object):
         return mx, my
 
     def MetersToLatLon(self, mx, my ):
-        "Converts XY point from Spherical Mercator EPSG:900913 to lat/lon in WGS84 Datum"
+        "Converts XY point from Spherical Mercator EPSG:3857 to lat/lon in WGS84 Datum"
 
         lon = (mx / self.originShift) * 180.0
         lat = (my / self.originShift) * 180.0
@@ -227,7 +222,7 @@ class GlobalMercator(object):
         return lat, lon
 
     def PixelsToMeters(self, px, py, zoom):
-        "Converts pixel coordinates in given zoom level of pyramid to EPSG:900913"
+        "Converts pixel coordinates in given zoom level of pyramid to EPSG:3857"
 
         res = self.Resolution( zoom )
         mx = px * res - self.originShift
@@ -235,7 +230,7 @@ class GlobalMercator(object):
         return mx, my
 
     def MetersToPixels(self, mx, my, zoom):
-        "Converts EPSG:900913 to pyramid pixel coordinates in given zoom level"
+        "Converts EPSG:3857 to pyramid pixel coordinates in given zoom level"
 
         res = self.Resolution( zoom )
         px = (mx + self.originShift) / res
@@ -262,14 +257,14 @@ class GlobalMercator(object):
         return self.PixelsToTile( px, py)
 
     def TileBounds(self, tx, ty, zoom):
-        "Returns bounds of the given tile in EPSG:900913 coordinates"
+        "Returns bounds of the given tile in EPSG:3857 coordinates"
 
         minx, miny = self.PixelsToMeters( tx*self.tileSize, ty*self.tileSize, zoom )
         maxx, maxy = self.PixelsToMeters( (tx+1)*self.tileSize, (ty+1)*self.tileSize, zoom )
         return ( minx, miny, maxx, maxy )
 
     def TileLatLonBounds(self, tx, ty, zoom ):
-        "Returns bounds of the given tile in latutude/longitude using WGS84 datum"
+        "Returns bounds of the given tile in latitude/longitude using WGS84 datum"
 
         bounds = self.TileBounds( tx, ty, zoom)
         minLat, minLon = self.MetersToLatLon(bounds[0], bounds[1])
@@ -340,15 +335,15 @@ class GlobalGeodetic(object):
       TMS has coordinate origin (for pixels and tiles) in bottom-left corner.
       Rasters are in EPSG:4326 and therefore are compatible with Google Earth.
 
-         LatLon      <->      Pixels      <->     Tiles     
+         LatLon      <->      Pixels      <->     Tiles
 
      WGS84 coordinates   Pixels in pyramid  Tiles in pyramid
-         lat/lon         XY pixels Z zoom      XYZ from TMS 
-        EPSG:4326                                           
-         .----.                ----                         
-        /      \     <->    /--------/    <->      TMS      
-        \      /         /--------------/                   
-         -----        /--------------------/                
+         lat/lon         XY pixels Z zoom      XYZ from TMS
+        EPSG:4326
+         .----.                ----
+        /      \     <->    /--------/    <->      TMS
+        \      /         /--------------/
+         -----        /--------------------/
        WMS, KML    Web Clients, Google Earth  TileMapService
     """
 
@@ -416,7 +411,7 @@ class GlobalGeodetic(object):
         return (b[1],b[0],b[3],b[2])
 
 #---------------------
-# TODO: Finish Zoomify implemtentation!!!
+# TODO: Finish Zoomify implementation.
 class Zoomify(object):
     """
     Tiles compatible with the Zoomify viewer
@@ -504,6 +499,24 @@ class GDAL2Tiles(object):
         gdal.TermProgress_nocb(complete)
 
     # -------------------------------------------------------------------------
+    def gettempfilename(self, suffix):
+        """Returns a temporary filename"""
+        if '_' in os.environ:
+            # tempfile.mktemp() crashes on some Wine versions (the one of Ubuntu 12.04 particularly)
+            if os.environ['_'].find('wine') >= 0:
+                tmpdir = '.'
+                if 'TMP' in os.environ:
+                    tmpdir = os.environ['TMP']
+                import time
+                import random
+                random.seed(time.time())
+                random_part = 'file%d' % random.randint(0,1000000000)
+                return os.path.join(tmpdir, random_part + suffix)
+
+        import tempfile
+        return tempfile.mktemp(suffix)
+
+    # -------------------------------------------------------------------------
     def stop(self):
         """Stop the rendering immediately"""
         self.stopped = True
@@ -522,7 +535,7 @@ class GDAL2Tiles(object):
         self.tileext = 'png'
 
         # Should we read bigger window of the input raster and scale it down?
-        # Note: Modified leter by open_input()
+        # Note: Modified later by open_input()
         # Not for 'near' resampling
         # Not for Wavelet based drivers (JPEG2000, ECW, MrSID)
         # Not for 'raster' profile
@@ -630,7 +643,7 @@ gdal_vrtmerge.py -o merged.vrt %s""" % " ".join(self.args))
             if max:
                 self.tmaxz = int(max)
             else:
-                self.tmaxz = int(min) 
+                self.tmaxz = int(min)
 
         # KML generation
         self.kml = self.options.kml
@@ -668,8 +681,11 @@ gdal_vrtmerge.py -o merged.vrt %s""" % " ".join(self.args))
         p.add_option("-v", "--verbose",
                           action="store_true", dest="verbose",
                           help="Print status messages to stdout")
+        p.add_option("-q", "--quiet",
+                          action="store_true", dest="quiet",
+                          help="Disable messages and status to stdout")
 
-        # KML options 
+        # KML options
         g = OptionGroup(p, "KML (Google Earth) options", "Options for generated Google Earth SuperOverlay metadata")
         g.add_option("-k", "--force-kml", dest='kml', action="store_true",
                           help="Generate KML for Google Earth - default for 'geodetic' profile and 'raster' in EPSG:4326. For a dataset with different projection use with caution!")
@@ -793,7 +809,7 @@ gdal2tiles temp.vrt""" % self.input )
         self.out_srs = osr.SpatialReference()
 
         if self.options.profile == 'mercator':
-            self.out_srs.ImportFromEPSG(900913)
+            self.out_srs.ImportFromEPSG(3857)
         elif self.options.profile == 'geodetic':
             self.out_srs.ImportFromEPSG(4326)
         else:
@@ -802,9 +818,9 @@ gdal2tiles temp.vrt""" % self.input )
         # Are the reference systems the same? Reproject if necessary.
 
         self.out_ds = None
-        
+
         if self.options.profile in ('mercator', 'geodetic'):
-                        
+
             if (self.in_ds.GetGeoTransform() == (0.0, 1.0, 0.0, 0.0, 0.0, 1.0)) and (self.in_ds.GetGCPCount() == 0):
                 self.error("There is no georeference - neither affine transformation (worldfile) nor GCPs. You can generate only 'raster' profile tiles.",
                 "Either gdal2tiles with parameter -p 'raster' or use another GIS software for georeference e.g. gdal_transform -gcp / -a_ullr / -a_srs")
@@ -826,8 +842,7 @@ gdal2tiles temp.vrt""" % self.input )
 
                     # Correction of AutoCreateWarpedVRT for NODATA values
                     if self.in_nodata != []:
-                        import tempfile
-                        tempfilename = tempfile.mktemp('-gdal2tiles.vrt')
+                        tempfilename = self.gettempfilename('-gdal2tiles.vrt')
                         self.out_ds.GetDriver().CreateCopy(tempfilename, self.out_ds)
                         # open as a text file
                         s = open(tempfilename).read()
@@ -851,7 +866,7 @@ gdal2tiles temp.vrt""" % self.input )
                         os.unlink(tempfilename)
 
                         # set NODATA_VALUE metadata
-                        self.out_ds.SetMetadataItem('NODATA_VALUES','%i %i %i' % (self.in_nodata[0],self.in_nodata[1],self.in_nodata[2]))
+                        self.out_ds.SetMetadataItem('NODATA_VALUES',' '.join([str(i) for i in self.in_nodata]))
 
                         if self.options.verbose:
                             print("Modified warping result saved into 'tiles1.vrt'")
@@ -861,8 +876,7 @@ gdal2tiles temp.vrt""" % self.input )
                     # Correction of AutoCreateWarpedVRT for Mono (1 band) and RGB (3 bands) files without NODATA:
                     # equivalent of gdalwarp -dstalpha
                     if self.in_nodata == [] and self.out_ds.RasterCount in [1,3]:
-                        import tempfile
-                        tempfilename = tempfile.mktemp('-gdal2tiles.vrt')
+                        tempfilename = self.gettempfilename('-gdal2tiles.vrt')
                         self.out_ds.GetDriver().CreateCopy(tempfilename, self.out_ds)
                         # open as a text file
                         s = open(tempfilename).read()
@@ -893,7 +907,7 @@ gdal2tiles temp.vrt""" % self.input )
 
             if self.out_ds and self.options.verbose:
                 print("Projected file:", "tiles.vrt", "( %sP x %sL - %s bands)" % (self.out_ds.RasterXSize, self.out_ds.RasterYSize, self.out_ds.RasterCount))
-        
+
         if not self.out_ds:
             self.out_ds = self.in_ds
 
@@ -919,7 +933,7 @@ gdal2tiles temp.vrt""" % self.input )
             if self.options.verbose:
                 print("KML autotest OK!")
 
-        # Read the georeference 
+        # Read the georeference
 
         self.out_gt = self.out_ds.GetGeoTransform()
 
@@ -930,13 +944,13 @@ gdal2tiles temp.vrt""" % self.input )
 
         # MAPTILER - COMMENTED
         #if self.out_gt[1] != (-1 * self.out_gt[5]) and self.options.profile != 'raster':
-            # TODO: Process corectly coordinates with are have swichted Y axis (display in OpenLayers too)
+            # TODO: Process correctly coordinates with are have switched Y axis (display in OpenLayers too)
             #self.error("Size of the pixel in the output differ for X and Y axes.")
 
         # Report error in case rotation/skew is in geotransform (possible only in 'raster' profile)
         if (self.out_gt[2], self.out_gt[4]) != (0,0):
             self.error("Georeference of the raster contains rotation or skew. Such raster is not supported. Please use gdalwarp first.")
-            # TODO: Do the warping in this case automaticaly
+            # TODO: Do the warping in this case automatically
 
         #
         # Here we expect: pixel is square, no rotation on the raster
@@ -975,7 +989,7 @@ gdal2tiles temp.vrt""" % self.input )
 
             # TODO: Maps crossing 180E (Alaska?)
 
-            # Get the minimal zoom level (map covers area equivalent to one tile) 
+            # Get the minimal zoom level (map covers area equivalent to one tile)
             if self.tminz == None:
                 self.tminz = self.mercator.ZoomForPixelSize( self.out_gt[1] * max( self.out_ds.RasterXSize, self.out_ds.RasterYSize) / float(self.tilesize) )
 
@@ -1098,6 +1112,13 @@ gdal2tiles temp.vrt""" % self.input )
                     f.write( self.generate_openlayers() )
                     f.close()
 
+            # Generate leaflet.html
+            if self.options.webviewer in ('all','leaflet'):
+                if not self.options.resume or not os.path.exists(os.path.join(self.output, 'leaflet.html')):
+                    f = open(os.path.join(self.output, 'leaflet.html'), 'w')
+                    f.write( self.generate_leaflet() )
+                    f.close()
+
         elif self.options.profile == 'geodetic':
 
             west, south = self.ominx, self.ominy
@@ -1141,7 +1162,7 @@ gdal2tiles temp.vrt""" % self.input )
             xmin, ymin, xmax, ymax = self.tminmax[self.tminz]
             for x in range(xmin, xmax+1):
                 for y in range(ymin, ymax+1):
-                    children.append( [ x, y, self.tminz ] ) 
+                    children.append( [ x, y, self.tminz ] )
             # Generate Root KML
             if self.kml:
                 if not self.options.resume or not os.path.exists(os.path.join(self.output, 'doc.kml')):
@@ -1153,7 +1174,8 @@ gdal2tiles temp.vrt""" % self.input )
     def generate_base_tiles(self):
         """Generation of the base tiles (the lowest in the pyramid) directly from the input raster"""
 
-        print("Generating Base Tiles:")
+        if not self.options.quiet:
+            print("Generating Base Tiles:")
 
         if self.options.verbose:
             #mx, my = self.out_gt[0], self.out_gt[3] # OriginX, OriginY
@@ -1200,7 +1222,7 @@ gdal2tiles temp.vrt""" % self.input )
 
                 if self.options.resume and os.path.exists(tilefilename):
                     if self.options.verbose:
-                        print("Tile generation skiped because of --resume")
+                        print("Tile generation skipped because of --resume")
                     else:
                         self.progressbar( ti / float(tcount) )
                     continue
@@ -1210,7 +1232,7 @@ gdal2tiles temp.vrt""" % self.input )
                     os.makedirs(os.path.dirname(tilefilename))
 
                 if self.options.profile == 'mercator':
-                    # Tile bounds in EPSG:900913
+                    # Tile bounds in EPSG:3857
                     b = self.mercator.TileBounds(tx, ty, tz)
                 elif self.options.profile == 'geodetic':
                     b = self.geodetic.TileBounds(tx, ty, tz)
@@ -1306,14 +1328,15 @@ gdal2tiles temp.vrt""" % self.input )
                         f.write( self.generate_kml( tx, ty, tz ))
                         f.close()
 
-                if not self.options.verbose:
+                if not self.options.verbose and not self.options.quiet:
                     self.progressbar( ti / float(tcount) )
 
     # -------------------------------------------------------------------------
     def generate_overview_tiles(self):
         """Generation of the overview tiles (higher in the pyramid) based on existing tiles"""
 
-        print("Generating Overview Tiles:")
+        if not self.options.quiet:
+            print("Generating Overview Tiles:")
 
         tilebands = self.dataBandsCount + 1
 
@@ -1344,7 +1367,7 @@ gdal2tiles temp.vrt""" % self.input )
 
                     if self.options.resume and os.path.exists(tilefilename):
                         if self.options.verbose:
-                            print("Tile generation skiped because of --resume")
+                            print("Tile generation skipped because of --resume")
                         else:
                             self.progressbar( ti / float(tcount) )
                         continue
@@ -1400,7 +1423,7 @@ gdal2tiles temp.vrt""" % self.input )
                         f.write( self.generate_kml( tx, ty, tz, children ) )
                         f.close()
 
-                    if not self.options.verbose:
+                    if not self.options.verbose and not self.options.quiet:
                         self.progressbar( ti / float(tcount) )
 
 
@@ -1477,7 +1500,7 @@ gdal2tiles temp.vrt""" % self.input )
             im1 = im.resize((tilesize,tilesize), Image.ANTIALIAS)
             if os.path.exists(tilefilename):
                 im0 = Image.open(tilefilename)
-                im1 = Image.composite(im1, im0, im1) 
+                im1 = Image.composite(im1, im0, im1)
             im1.save(tilefilename,self.tiledriver)
 
         else:
@@ -1507,7 +1530,7 @@ gdal2tiles temp.vrt""" % self.input )
         args['profile'] = self.options.profile
 
         if self.options.profile == 'mercator':
-            args['srs'] = "EPSG:900913"
+            args['srs'] = "EPSG:3857"
         elif self.options.profile == 'geodetic':
             args['srs'] = "EPSG:4326"
         elif self.options.s_srs:
@@ -1564,9 +1587,9 @@ gdal2tiles temp.vrt""" % self.input )
             args['title'] = "%d/%d/%d.kml" % (tz, tx, ty)
             args['south'], args['west'], args['north'], args['east'] = self.tileswne(tx, ty, tz)
 
-        if tx == 0: 
-            args['drawOrder'] = 2 * tz + 1 
-        elif tx != None: 
+        if tx == 0:
+            args['drawOrder'] = 2 * tz + 1
+        elif tx != None:
             args['drawOrder'] = 2 * tz
         else:
             args['drawOrder'] = 0
@@ -1665,7 +1688,7 @@ gdal2tiles temp.vrt""" % self.input )
         args['copyright'] = self.options.copyright
 
         s = """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-            <html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml"> 
+            <html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml">
               <head>
                 <title>%(title)s</title>
                 <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
@@ -1700,7 +1723,7 @@ gdal2tiles temp.vrt""" % self.input )
                  * http://www.maptiler.org/google-maps-overlay-opacity-control/
                  */
 
-                var CTransparencyLENGTH = 58; 
+                var CTransparencyLENGTH = 58;
                 // maximum width that the knob can move (slide width minus knob width)
 
                 function CTransparencyControl( overlay ) {
@@ -1754,11 +1777,11 @@ gdal2tiles temp.vrt""" % self.input )
                     // Handle transparent PNG files in MSIE
                     if (this.ie) {
                       var loader = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://www.maptiler.org/img/opacity-slider.png', sizingMethod='crop');";
-                      this.knob = document.createElement("div"); 
+                      this.knob = document.createElement("div");
                       this.knob.style.height="21px";
                       this.knob.style.width="13px";
                   this.knob.style.overflow="hidden";
-                      this.knob_img = document.createElement("div"); 
+                      this.knob_img = document.createElement("div");
                       this.knob_img.style.height="21px";
                       this.knob_img.style.width="83px";
                       this.knob_img.style.filter=loader;
@@ -1766,7 +1789,7 @@ gdal2tiles temp.vrt""" % self.input )
                   this.knob_img.style.left="-70px";
                       this.knob.appendChild(this.knob_img);
                     } else {
-                      this.knob = document.createElement("div"); 
+                      this.knob = document.createElement("div");
                       this.knob.style.height="21px";
                       this.knob.style.width="13px";
                       this.knob.style.backgroundImage="url(http://www.maptiler.org/img/opacity-slider.png)";
@@ -1817,9 +1840,9 @@ gdal2tiles temp.vrt""" % self.input )
                 }
 
                 function resize() {
-                    var map = document.getElementById("map");  
-                    var header = document.getElementById("header");  
-                    var subheader = document.getElementById("subheader");  
+                    var map = document.getElementById("map");
+                    var header = document.getElementById("header");
+                    var subheader = document.getElementById("subheader");
                     map.style.height = (getWindowHeight()-80) + "px";
                     map.style.width = (getWindowWidth()-20) + "px";
                     header.style.width = (getWindowWidth()-20) + "px";
@@ -1916,7 +1939,7 @@ gdal2tiles temp.vrt""" % self.input )
                        else { link.setHref(url) };
                        var networkLink = ge.createNetworkLink("");
                        networkLink.setName("TMS Map Overlay");
-                       networkLink.setFlyToView(true);  
+                       networkLink.setFlyToView(true);
                        networkLink.setLink(link);
                        ge.getFeatures().appendChild(networkLink);
                    } else {
@@ -1933,7 +1956,7 @@ gdal2tiles temp.vrt""" % self.input )
               </head>
               <body onload="load()">
                   <div id="header"><h1>%(title)s</h1></div>
-                  <div id="subheader">Generated by <a href="http://www.maptiler.org/">MapTiler</a>/<a href="http://www.klokan.cz/projects/gdal2tiles/">GDAL2Tiles</a>, Copyright © 2008 <a href="http://www.klokan.cz/">Klokan Petr Pridal</a>,  <a href="http://www.gdal.org/">GDAL</a> & <a href="http://www.osgeo.org/">OSGeo</a> <a href="http://code.google.com/soc/">GSoC</a>
+                  <div id="subheader">Generated by <a href="http://www.klokan.cz/projects/gdal2tiles/">GDAL2Tiles</a>, Copyright © 2008 <a href="http://www.klokan.cz/">Klokan Petr Pridal</a>,  <a href="http://www.gdal.org/">GDAL</a> & <a href="http://www.osgeo.org/">OSGeo</a> <a href="http://code.google.com/soc/">GSoC</a>
             <!-- PLEASE, LET THIS NOTE ABOUT AUTHOR AND PROJECT SOMEWHERE ON YOUR WEBSITE, OR AT LEAST IN THE COMMENT IN HTML. THANK YOU -->
                   </div>
                    <div id="map"></div>
@@ -1945,6 +1968,139 @@ gdal2tiles temp.vrt""" % self.input )
 
 
     # -------------------------------------------------------------------------
+    def generate_leaflet(self):
+        """
+        Template for leaflet.html implementing overlay of tiles for 'mercator' profile.
+        It returns filled string. Expected variables:
+        title, north, south, east, west, minzoom, maxzoom, tilesize, tileformat, publishurl
+        """
+
+        args = {}
+        args['title'] = self.options.title.replace('"', '\\"')
+        args['htmltitle'] = self.options.title
+        args['south'], args['west'], args['north'], args['east'] = self.swne
+        args['centerlon'] = (args['north'] + args['south']) / 2.
+        args['centerlat'] = (args['west'] + args['east']) / 2.
+        args['minzoom'] = self.tminz
+        args['maxzoom'] = self.tmaxz
+        args['beginzoom'] = self.tmaxz
+        args['tilesize'] = self.tilesize  # not used
+        args['tileformat'] = self.tileext
+        args['publishurl'] = self.options.url  # not used
+        args['copyright'] = self.options.copyright.replace('"', '\\"')
+
+        s = """<!DOCTYPE html>
+        <html lang="en">
+          <head>
+            <meta charset="utf-8">
+            <meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no' />
+            <title>%(htmltitle)s</title>
+
+            <!-- Leaflet -->
+            <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.5/leaflet.css" />
+            <script src="http://cdn.leafletjs.com/leaflet-0.7.5/leaflet.js"></script>
+
+            <style>
+                body { margin:0; padding:0; }
+                body, table, tr, td, th, div, h1, h2, input { font-family: "Calibri", "Trebuchet MS", "Ubuntu", Serif; font-size: 11pt; }
+                #map { position:absolute; top:0; bottom:0; width:100%%; } /* full size */
+                .ctl {
+                    padding: 2px 10px 2px 10px;
+                    background: white;
+                    background: rgba(255,255,255,0.9);
+                    box-shadow: 0 0 15px rgba(0,0,0,0.2);
+                    border-radius: 5px;
+                    text-align: right;
+                }
+                .title {
+                    font-size: 18pt;
+                    font-weight: bold;
+                }
+                .src {
+                    font-size: 10pt;
+                }
+
+            </style>
+
+        </head>
+        <body>
+
+        <div id="map"></div>
+
+        <script>
+        /* **** Leaflet **** */
+
+        // Base layers
+        //  .. OpenStreetMap
+        var osm = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'});
+
+        //  .. CartoDB Positron
+        var cartodb = L.tileLayer('http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', {attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, © <a href="http://cartodb.com/attributions">CartoDB</a>'});
+
+        //  .. OSM Toner
+        var toner = L.tileLayer('http://{s}.tile.stamen.com/toner/{z}/{x}/{y}.png', {attribution: 'Map tiles by <a href="http://stamen.com">Stamen Design</a>, under <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>. Data by <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://www.openstreetmap.org/copyright">ODbL</a>.'});
+
+        //  .. White background
+        var white = L.tileLayer("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEAAQMAAABmvDolAAAAA1BMVEX///+nxBvIAAAAH0lEQVQYGe3BAQ0AAADCIPunfg43YAAAAAAAAAAA5wIhAAAB9aK9BAAAAABJRU5ErkJggg==");
+
+        // Overlay layers (TMS)
+        var lyr = L.tileLayer('./{z}/{x}/{y}.%(tileformat)s', {tms: true, opacity: 0.7, attribution: "%(copyright)s"});
+
+        // Map
+        var map = L.map('map', {
+            center: [%(centerlon)s, %(centerlat)s],
+            zoom: %(beginzoom)s,
+            minZoom: %(minzoom)s,
+            maxZoom: %(maxzoom)s,
+            layers: [osm]
+        });
+
+        var basemaps = {"OpenStreetMap": osm, "CartoDB Positron": cartodb, "Stamen Toner": toner, "Without background": white}
+        var overlaymaps = {"Layer": lyr}
+
+        // Title
+        var title = L.control();
+        title.onAdd = function(map) {
+	        this._div = L.DomUtil.create('div', 'ctl title');
+	        this.update();
+	        return this._div;
+        };
+        title.update = function(props) {
+	        this._div.innerHTML = "%(title)s";
+        };
+        title.addTo(map);
+
+        // Note
+        var src = 'Generated by <a href="http://www.klokan.cz/projects/gdal2tiles/">GDAL2Tiles</a>, Copyright © 2008 <a href="http://www.klokan.cz/">Klokan Petr Pridal</a>,  <a href="http://www.gdal.org/">GDAL</a> & <a href="http://www.osgeo.org/">OSGeo</a> <a href="http://code.google.com/soc/">GSoC</a>';
+        var title = L.control({position: 'bottomleft'});
+        title.onAdd = function(map) {
+	        this._div = L.DomUtil.create('div', 'ctl src');
+	        this.update();
+	        return this._div;
+        };
+        title.update = function(props) {
+	        this._div.innerHTML = src;
+        };
+        title.addTo(map);
+
+
+        // Add base layers
+        L.control.layers(basemaps, overlaymaps, {collapsed: false}).addTo(map);
+
+        // Fit to overlay bounds (SW and NE points with (lat, lon))
+        map.fitBounds([[%(south)s, %(east)s], [%(north)s, %(west)s]]);
+
+        </script>
+
+        </body>
+        </html>
+
+        """ % args
+
+        return s
+
+
+    # -------------------------------------------------------------------------
     def generate_openlayers( self ):
         """
         Template for openlayers.html implementing overlay of available Spherical Mercator layers.
@@ -1984,7 +2140,7 @@ gdal2tiles temp.vrt""" % self.input )
             #subheader { height: 12px; text-align: right; font-size: 10px; color: #555;}
             #map { height: 95%%; border: 1px solid #888; }
             .olImageLoadError { display: none; }
-            .olControlLayerSwitcher .layersDiv { border-radius: 10px 0 0 10px; } 
+            .olControlLayerSwitcher .layersDiv { border-radius: 10px 0 0 10px; }
         </style>""" % args
 
         if self.options.profile == 'mercator':
@@ -2008,7 +2164,7 @@ gdal2tiles temp.vrt""" % self.input )
                   var options = {
                       div: "map",
                       controls: [],
-                      projection: "EPSG:900913",
+                      projection: "EPSG:3857",
                       displayProjection: new OpenLayers.Projection("EPSG:4326"),
                       numZoomLevels: 20
                   };
@@ -2132,7 +2288,7 @@ gdal2tiles temp.vrt""" % self.input )
                       numZoomLevels: %(rasterzoomlevels)d
                   };
                   map = new OpenLayers.Map(options);
-      
+
                   var layer = new OpenLayers.Layer.TMS("TMS Layer", "",
                   {
                       serviceVersion: '.',
@@ -2167,7 +2323,7 @@ gdal2tiles temp.vrt""" % self.input )
                   if (this.map.baseLayer.CLASS_NAME === 'OpenLayers.Layer.Bing') {
                       z+=1;
                   }
-                  var path = this.serviceVersion + "/" + this.layername + "/" + z + "/" + x + "/" + y + "." + this.type; 
+                  var path = this.serviceVersion + "/" + this.layername + "/" + z + "/" + x + "/" + y + "." + this.type;
                   var url = this.url;
                   if (OpenLayers.Util.isArray(url)) {
                       url = this.selectUrl(path, url);
@@ -2177,7 +2333,7 @@ gdal2tiles temp.vrt""" % self.input )
                   } else {
                       return emptyTileURL;
                   }
-              } 
+              }
           """ % args
 
         elif self.options.profile == 'geodetic':
@@ -2188,7 +2344,7 @@ gdal2tiles temp.vrt""" % self.input )
                   var x = Math.round((bounds.left - this.tileOrigin.lon) / (res * this.tileSize.w));
                   var y = Math.round((bounds.bottom - this.tileOrigin.lat) / (res * this.tileSize.h));
                   var z = this.getServerZoom()%(tmsoffset)s;
-                  var path = this.serviceVersion + "/" + this.layername + "/" + z + "/" + x + "/" + y + "." + this.type; 
+                  var path = this.serviceVersion + "/" + this.layername + "/" + z + "/" + x + "/" + y + "." + this.type;
                   var url = this.url;
                   if (OpenLayers.Util.isArray(url)) {
                       url = this.selectUrl(path, url);
@@ -2209,7 +2365,7 @@ gdal2tiles temp.vrt""" % self.input )
                   var x = Math.round((bounds.left - this.tileOrigin.lon) / (res * this.tileSize.w));
                   var y = Math.round((bounds.bottom - this.tileOrigin.lat) / (res * this.tileSize.h));
                   var z = this.getServerZoom();
-                  var path = this.serviceVersion + "/" + this.layername + "/" + z + "/" + x + "/" + y + "." + this.type; 
+                  var path = this.serviceVersion + "/" + this.layername + "/" + z + "/" + x + "/" + y + "." + this.type;
                   var url = this.url;
                   if (OpenLayers.Util.isArray(url)) {
                       url = this.selectUrl(path, url);
@@ -2239,10 +2395,10 @@ gdal2tiles temp.vrt""" % self.input )
                         return 0;
                 }
 
-                function resize() {  
-                    var map = document.getElementById("map");  
-                    var header = document.getElementById("header");  
-                    var subheader = document.getElementById("subheader");  
+                function resize() {
+                    var map = document.getElementById("map");
+                    var header = document.getElementById("header");
+                    var subheader = document.getElementById("subheader");
                     map.style.height = (getWindowHeight()-80) + "px";
                     map.style.width = (getWindowWidth()-20) + "px";
                     header.style.width = (getWindowWidth()-20) + "px";
@@ -2256,7 +2412,7 @@ gdal2tiles temp.vrt""" % self.input )
               </head>
               <body onload="init()">
                 <div id="header"><h1>%(title)s</h1></div>
-                <div id="subheader">Generated by <a href="http://www.maptiler.org/">MapTiler</a>/<a href="http://www.klokan.cz/projects/gdal2tiles/">GDAL2Tiles</a>, Copyright © 2008 <a href="http://www.klokan.cz/">Klokan Petr Pridal</a>,  <a href="http://www.gdal.org/">GDAL</a> & <a href="http://www.osgeo.org/">OSGeo</a> <a href="http://code.google.com/soc/">GSoC</a>
+                <div id="subheader">Generated by <a href="http://www.klokan.cz/projects/gdal2tiles/">GDAL2Tiles</a>, Copyright © 2008 <a href="http://www.klokan.cz/">Klokan Petr Pridal</a>,  <a href="http://www.gdal.org/">GDAL</a> & <a href="http://www.osgeo.org/">OSGeo</a> <a href="http://code.google.com/soc/">GSoC</a>
                 <!-- PLEASE, LET THIS NOTE ABOUT AUTHOR AND PROJECT SOMEWHERE ON YOUR WEBSITE, OR AT LEAST IN THE COMMENT IN HTML. THANK YOU -->
                 </div>
                 <div id="map"></div>
@@ -2270,8 +2426,11 @@ gdal2tiles temp.vrt""" % self.input )
 # =============================================================================
 # =============================================================================
 
-if __name__=='__main__':
+def main():
     argv = gdal.GeneralCmdLineProcessor( sys.argv )
     if argv:
         gdal2tiles = GDAL2Tiles( argv[1:] )
         gdal2tiles.process()
+
+if __name__=='__main__':
+    main()
diff --git a/swig/python/scripts/gdal2xyz.py b/swig/python/scripts/gdal2xyz.py
index 176cfd9..576fb01 100755
--- a/swig/python/scripts/gdal2xyz.py
+++ b/swig/python/scripts/gdal2xyz.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: gdal2xyz.py 24523 2012-05-31 20:57:05Z rouault $
+# $Id: gdal2xyz.py 33790 2016-03-26 12:42:12Z goatbar $
 #
 # Project:  GDAL
 # Purpose:  Script to translate GDAL supported raster into XYZ ASCII
@@ -9,17 +9,17 @@
 #
 ###############################################################################
 # Copyright (c) 2002, Frank Warmerdam <warmerdam at pobox.com>
-# 
+#
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
 # to deal in the Software without restriction, including without limitation
 # the rights to use, copy, modify, merge, publish, distribute, sublicense,
 # and/or sell copies of the Software, and to permit persons to whom the
 # Software is furnished to do so, subject to the following conditions:
-# 
+#
 # The above copyright notice and this permission notice shall be included
 # in all copies or substantial portions of the Software.
-# 
+#
 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -29,13 +29,10 @@
 # DEALINGS IN THE SOFTWARE.
 ###############################################################################
 
-try:
-    from osgeo import gdal
-except ImportError:
-    import gdal
-
 import sys
 
+from osgeo import gdal
+
 try:
     import numpy as Numeric
 except ImportError:
@@ -56,7 +53,7 @@ def Usage():
 if __name__ == '__main__':
 
     srcwin = None
-    skip = 1    
+    skip = 1
     srcfile = None
     dstfile = None
     band_nums = []
@@ -106,14 +103,14 @@ if __name__ == '__main__':
         Usage()
 
     if band_nums == []: band_nums = [1]
-    # Open source file. 
+    # Open source file.
     srcds = gdal.Open( srcfile )
     if srcds is None:
         print('Could not open %s.' % srcfile)
         sys.exit( 1 )
 
     bands = []
-    for band_num in band_nums: 
+    for band_num in band_nums:
         band = srcds.GetRasterBand(band_num)
         if band is None:
             print('Could not get band %d' % band_num)
@@ -121,7 +118,7 @@ if __name__ == '__main__':
         bands.append(band)
 
     gt = srcds.GetGeoTransform()
-  
+
     # Collect information on all the source files.
     if srcwin is None:
         srcwin = (0,0,srcds.RasterXSize,srcds.RasterYSize)
@@ -149,7 +146,7 @@ if __name__ == '__main__':
         data = []
         for band in bands:
 
-            band_data = band.ReadAsArray( srcwin[0], y, srcwin[2], 1 )    
+            band_data = band.ReadAsArray( srcwin[0], y, srcwin[2], 1 )
             band_data = Numeric.reshape( band_data, (srcwin[2],) )
             data.append(band_data)
 
@@ -163,11 +160,9 @@ if __name__ == '__main__':
             x_i_data = []
             for i in range(len(bands)):
                 x_i_data.append(data[i][x_i])
-            
+
             band_str = band_format % tuple(x_i_data)
 
             line = format % (float(geo_x),float(geo_y), band_str)
 
             dst_fh.write( line )
-
-
diff --git a/swig/python/scripts/gdal_auth.py b/swig/python/scripts/gdal_auth.py
index 7cbba43..56e0ad0 100755
--- a/swig/python/scripts/gdal_auth.py
+++ b/swig/python/scripts/gdal_auth.py
@@ -2,24 +2,24 @@
 # -*- coding: utf-8 -*-
 #******************************************************************************
 #  $Id$
-# 
+#
 #  Project:  GDAL
 #  Purpose:  Application for Google web service authentication.
 #  Author:   Frank Warmerdam, warmerdam at pobox.com
-# 
+#
 #******************************************************************************
 #  Copyright (c) 2013, Frank Warmerdam <warmerdam at pobox.com>
-# 
+#
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
 #  to deal in the Software without restriction, including without limitation
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -28,18 +28,16 @@
 #  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 #  DEALINGS IN THE SOFTWARE.
 #******************************************************************************
-#
 
-from osgeo import gdal
 
 import sys
 import time
 import webbrowser
 
+from osgeo import gdal
+
 SCOPES = {
     'ft' : 'https://www.googleapis.com/auth/fusiontables',
-    'gme' : 'https://www.googleapis.com/auth/mapsengine',
-    'gme.ro' : 'https://www.googleapis.com/auth/mapsengine.readonly',
     }
 
 # =============================================================================
@@ -55,7 +53,7 @@ def Usage():
     print('Usage: gdal_auth.py auth2refresh [-s scope] auth_token')
     print('Usage: gdal_auth.py refresh2access [-s scope] refresh_token')
     print('')
-    print('scopes: ft/gme/gme.ro/full_url')
+    print('scopes: ft/full_url')
     print('')
     sys.exit(1)
 
@@ -126,14 +124,10 @@ else:
     print('')
     print('Enter authorization token:')
     auth_token = sys.stdin.readline()
-    
+
     refresh_token = gdal.GOA2GetRefreshToken(auth_token, scope)
-    
+
     print('Refresh Token:'+refresh_token)
     print('')
     print('Consider setting a configuration option like:')
     print('GFT_REFRESH_TOKEN='+refresh_token)
-
-
-
-
diff --git a/swig/python/scripts/gdal_calc.py b/swig/python/scripts/gdal_calc.py
index e928b7e..de35ac6 100755
--- a/swig/python/scripts/gdal_calc.py
+++ b/swig/python/scripts/gdal_calc.py
@@ -1,25 +1,25 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #******************************************************************************
-# 
+#
 #  Project:  GDAL
 #  Purpose:  Command line raster calculator with numpy syntax
 #  Author:   Chris Yesson, chris.yesson at ioz.ac.uk
-# 
+#
 #******************************************************************************
 #  Copyright (c) 2010, Chris Yesson <chris.yesson at ioz.ac.uk>
 #  Copyright (c) 2010-2011, Even Rouault <even dot rouault at mines-paris dot org>
-# 
+#
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
 #  to deal in the Software without restriction, including without limitation
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -42,13 +42,15 @@
 # gdal_calc.py -A input.tif --outfile=result.tif --calc="A*(A>0)" --NoDataValue=0
 ################################################################
 
+from optparse import OptionParser
+import os
+import sys
+
+import numpy
+
 from osgeo import gdal
 from osgeo import gdalnumeric
-import numpy
 
-from optparse import OptionParser
-import sys
-import os
 
 # create alphabetic list for storing input layers
 AlphaList=["A","B","C","D","E","F","G","H","I","J","K","L","M",
@@ -177,7 +179,7 @@ def doit(opts, args):
         print("output file: %s, dimensions: %s, %s, type: %s" %(opts.outF,myOut.RasterXSize,myOut.RasterYSize,myOutType))
 
     ################################################################
-    # find block size to chop grids into bite-sized chunks 
+    # find block size to chop grids into bite-sized chunks
     ################################################################
 
     # use the block size of the first layer to read efficiently
@@ -197,7 +199,7 @@ def doit(opts, args):
     ProgressCt=-1
     ProgressMk=-1
     ProgressEnd=nXBlocks*nYBlocks*allBandsCount
-    
+
     ################################################################
     # start looping through each band in allBandsCount
     ################################################################
@@ -274,8 +276,8 @@ def doit(opts, args):
                     print("evaluation of calculation %s failed" %(opts.calc))
                     raise
 
-                # propogate nodata values 
-                # (set nodata cells to zero then add nodata value to these cells)
+                # Propagate nodata values (set nodata cells to zero
+                # then add nodata value to these cells).
                 myResult = ((1*(myNDVs==0))*myResult) + (myOutNDV*myNDVs)
 
                 # write data block to the output file
diff --git a/swig/python/scripts/gdal_edit.dox b/swig/python/scripts/gdal_edit.dox
index 4e7b19f..4a0c886 100644
--- a/swig/python/scripts/gdal_edit.dox
+++ b/swig/python/scripts/gdal_edit.dox
@@ -7,7 +7,7 @@ Edit in place various information of an existing GDAL dataset
 
 \verbatim
 gdal_edit [--help-general] [-ro] [-a_srs srs_def] [-a_ullr ulx uly lrx lry]
-          [-tr xres yres] [-unsetgt] [-a_nodata value]
+          [-tr xres yres] [-unsetgt] [-a_nodata value] [-unsetnodata]
           [-unsetstats] [-stats] [-approx_stats]
           [-gcp pixel line easting northing [elevation]]*
           [-unsetmd] [-oo NAME=VALUE]* [-mo "META-TAG=VALUE"]*  datasetname
@@ -59,6 +59,9 @@ Calculate and store approximate band statistics.</dd>
 <dt> <b>-a_nodata</b> <i>value</i>:</dt><dd>
 Assign a specified nodata value to output bands.</dd>
 
+<dt> <b>-unsetnodata</b></dt>:<dd> (GDAL >= 2.1)
+Remove existing nodata values.</dd>
+
 <dt> <b>-gcp</b> <i>pixel line easting northing [elevation]</i>:</dt><dd>
 Add the indicated ground control point to the dataset.  This option 
 may be provided multiple times to provide a set of GCPs. 
diff --git a/swig/python/scripts/gdal_edit.py b/swig/python/scripts/gdal_edit.py
index c2834f1..8dbfa0a 100755
--- a/swig/python/scripts/gdal_edit.py
+++ b/swig/python/scripts/gdal_edit.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 ###############################################################################
-# $Id: gdal_edit.py 29248 2015-05-25 09:57:17Z rouault $
+# $Id: gdal_edit.py 32555 2015-12-30 19:26:44Z goatbar $
 #
 #  Project:  GDAL samples
 #  Purpose:  Edit in place various information of an existing GDAL dataset
@@ -30,12 +30,13 @@
 ###############################################################################
 
 import sys
+
 from osgeo import gdal
 from osgeo import osr
 
 def Usage():
     print('Usage: gdal_edit [--help-general] [-ro] [-a_srs srs_def] [-a_ullr ulx uly lrx lry]')
-    print('                 [-tr xres yres] [-unsetgt] [-a_nodata value]')
+    print('                 [-tr xres yres] [-unsetgt] [-a_nodata value] [-unsetnodata]')
     print('                 [-unsetstats] [-stats] [-approx_stats]')
     print('                 [-gcp pixel line easting northing [elevation]]*')
     print('                 [-unsetmd] [-oo NAME=VALUE]* [-mo "META-TAG=VALUE"]*  datasetname')
@@ -67,6 +68,7 @@ def gdal_edit(argv):
     lrx = None
     lry = None
     nodata = None
+    unsetnodata = False
     xres = None
     yres = None
     unsetgt = False
@@ -134,6 +136,8 @@ def gdal_edit(argv):
             stats = True
         elif argv[i] == '-unsetmd':
             unsetmd = True
+        elif argv[i] == '-unsetnodata':
+            unsetnodata = True
         elif argv[i] == '-oo' and i < len(argv)-1:
             open_options.append(argv[i+1])
             i = i + 1
@@ -153,7 +157,7 @@ def gdal_edit(argv):
 
     if (srs is None and lry is None and yres is None and not unsetgt
             and not unsetstats and not stats and nodata is None
-            and len(molist) == 0 and not unsetmd and len(gcp_list) == 0):
+            and len(molist) == 0 and not unsetmd and len(gcp_list) == 0 and not unsetnodata):
         print('No option specified')
         print('')
         return Usage()
@@ -175,6 +179,11 @@ def gdal_edit(argv):
         print('')
         return Usage()
 
+    if unsetnodata and nodata:
+        print('-unsetnodata and -nodata options are exclusive.')
+        print('')
+        return Usage()
+
     if open_options is not None:
         if ro:
             ds = gdal.OpenEx(datasetname, gdal.OF_RASTER, open_options = open_options)
@@ -226,6 +235,9 @@ def gdal_edit(argv):
     if nodata is not None:
         for i in range(ds.RasterCount):
             ds.GetRasterBand(i+1).SetNoDataValue(nodata)
+    elif unsetnodata:
+        for i in range(ds.RasterCount):
+            ds.GetRasterBand(i+1).DeleteNoDataValue()
 
     if unsetstats:
         for i in range(ds.RasterCount):
diff --git a/swig/python/scripts/gdal_fillnodata.py b/swig/python/scripts/gdal_fillnodata.py
index 4f53ab3..d3f97a0 100755
--- a/swig/python/scripts/gdal_fillnodata.py
+++ b/swig/python/scripts/gdal_fillnodata.py
@@ -1,25 +1,25 @@
 #!/usr/bin/env python
 #******************************************************************************
-#  $Id: gdal_fillnodata.py 28389 2015-01-30 19:26:09Z rouault $
-# 
+#  $Id: gdal_fillnodata.py 33790 2016-03-26 12:42:12Z goatbar $
+#
 #  Project:  GDAL Python Interface
 #  Purpose:  Application for filling nodata areas in a raster by interpolation
 #  Author:   Frank Warmerdam, warmerdam at pobox.com
-# 
+#
 #******************************************************************************
 #  Copyright (c) 2008, Frank Warmerdam
 #  Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
-# 
+#
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
 #  to deal in the Software without restriction, including without limitation
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -29,19 +29,16 @@
 #  DEALINGS IN THE SOFTWARE.
 #******************************************************************************
 
-try:
-    from osgeo import gdal
-except ImportError:
-    import gdal
-
 import sys
 
+from osgeo import gdal
+
 def CopyBand( srcband, dstband ):
     for line in range(srcband.YSize):
         line_data = srcband.ReadRaster( 0, line, srcband.XSize, 1 )
         dstband.WriteRaster( 0, line, srcband.XSize, 1, line_data,
                              buf_type = srcband.DataType )
-        
+
 def Usage():
     print("""
 gdal_fillnodata [-q] [-md max_distance] [-si smooth_iterations]
@@ -49,7 +46,7 @@ gdal_fillnodata [-q] [-md max_distance] [-si smooth_iterations]
                 srcfile [-nomask] [-mask filename] [-of format] [-co name=value]* [dstfile]
 """)
     sys.exit(1)
-    
+
 # =============================================================================
 # 	Mainline
 # =============================================================================
@@ -87,33 +84,33 @@ while i < len(argv):
 
     elif arg == '-q' or arg == '-quiet':
         quiet_flag = 1
-        
+
     elif arg == '-si':
         i = i + 1
         smoothing_iterations = int(argv[i])
-        
+
     elif arg == '-b':
         i = i + 1
         src_band = int(argv[i])
-        
+
     elif arg == '-md':
         i = i + 1
         max_distance = float(argv[i])
-        
+
     elif arg == '-nomask':
         mask = 'none'
-        
+
     elif arg == '-mask':
         i = i + 1
         mask = argv[i]
-        
+
     elif arg == '-mask':
         i = i + 1
         mask = argv[i]
-        
+
     elif arg[:2] == '-h':
         Usage()
-        
+
     elif src_filename is None:
         src_filename = argv[i]
 
@@ -127,7 +124,7 @@ while i < len(argv):
 
 if src_filename is None:
     Usage()
-    
+
 # =============================================================================
 # 	Verify we have next gen bindings with the sievefilter method.
 # =============================================================================
@@ -148,7 +145,7 @@ if dst_filename is None:
     src_ds = gdal.Open( src_filename, gdal.GA_Update )
 else:
     src_ds = gdal.Open( src_filename, gdal.GA_ReadOnly )
-    
+
 if src_ds is None:
     print('Unable to open %s' % src_filename)
     sys.exit(1)
@@ -176,7 +173,7 @@ if dst_filename is not None:
     if wkt != '':
         dst_ds.SetProjection( wkt )
     dst_ds.SetGeoTransform( src_ds.GetGeoTransform() )
-    
+
     dstband = dst_ds.GetRasterBand(1)
     CopyBand( srcband, dstband )
     ndv = srcband.GetNoDataValue()
@@ -194,7 +191,7 @@ if quiet_flag:
     prog_func = None
 else:
     prog_func = gdal.TermProgress
-    
+
 result = gdal.FillNodata( dstband, maskband,
                           max_distance, smoothing_iterations, options,
                           callback = prog_func )
@@ -203,4 +200,3 @@ result = gdal.FillNodata( dstband, maskband,
 src_ds = None
 dst_ds = None
 mask_ds = None
-
diff --git a/swig/python/scripts/gdal_merge.py b/swig/python/scripts/gdal_merge.py
index ca03be2..74d8150 100755
--- a/swig/python/scripts/gdal_merge.py
+++ b/swig/python/scripts/gdal_merge.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: gdal_merge.py 29629 2015-08-08 13:47:42Z rouault $
+# $Id: gdal_merge.py 33790 2016-03-26 12:42:12Z goatbar $
 #
 # Project:  InSAR Peppers
 # Purpose:  Module to extract data from many rasters into one output.
@@ -9,43 +9,38 @@
 ###############################################################################
 # Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
 # Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
-# 
+#
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Library General Public
 # License as published by the Free Software Foundation; either
 # version 2 of the License, or (at your option) any later version.
-# 
+#
 # This library is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 # Library General Public License for more details.
-# 
+#
 # You should have received a copy of the GNU Library General Public
 # License along with this library; if not, write to the
 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 # Boston, MA 02111-1307, USA.
 ###############################################################################
 # changes 29Apr2011
-# if the input image is a multi-band one, use all 
-# the channels in building the stack
+# If the input image is a multi-band one, use all the channels in
+# building the stack.
 # anssi.pekkarinen at fao.org
 
+import math
+import sys
+import time
 
-try:
-    from osgeo import gdal
-except ImportError:
-    import gdal
+from osgeo import gdal
 
 try:
     progress = gdal.TermProgress_nocb
 except:
     progress = gdal.TermProgress
 
-
-import sys
-import math
-import time
-
 __version__ = '$id$'[5:-1]
 verbose = 0
 quiet = 0
@@ -57,7 +52,7 @@ def raster_copy( s_fh, s_xoff, s_yoff, s_xsize, s_ysize, s_band_n,
                  nodata=None ):
 
     if verbose != 0:
-        print('Copy %d,%d,%d,%d to %d,%d,%d,%d.' \
+        print('Copy %d,%d,%d,%d to %d,%d,%d,%d.'
               % (s_xoff, s_yoff, s_xsize, s_ysize,
              t_xoff, t_yoff, t_xsize, t_ysize ))
 
@@ -70,7 +65,7 @@ def raster_copy( s_fh, s_xoff, s_yoff, s_xsize, s_ysize, s_band_n,
     s_band = s_fh.GetRasterBand( s_band_n )
     m_band = None
     # Works only in binary mode and doesn't take into account
-    # intermediate transparency values for compositing
+    # intermediate transparency values for compositing.
     if s_band.GetMaskFlags() != gdal.GMF_ALL_VALID:
         m_band = s_band.GetMaskBand()
     elif s_band.GetColorInterpretation() == gdal.GCI_AlphaBand:
@@ -88,7 +83,6 @@ def raster_copy( s_fh, s_xoff, s_yoff, s_xsize, s_ysize, s_band_n,
                              t_xsize, t_ysize, t_band.DataType )
     t_band.WriteRaster( t_xoff, t_yoff, t_xsize, t_ysize,
                         data, t_xsize, t_ysize, t_band.DataType )
-        
 
     return 0
 
@@ -114,7 +108,7 @@ def raster_copy_with_nodata( s_fh, s_xoff, s_yoff, s_xsize, s_ysize, s_band_n,
     t_band.WriteArray( to_write, t_xoff, t_yoff )
 
     return 0
-    
+
 # =============================================================================
 def raster_copy_with_mask( s_fh, s_xoff, s_yoff, s_xsize, s_ysize, s_band_n,
                            t_fh, t_xoff, t_yoff, t_xsize, t_ysize, t_band_n,
@@ -139,7 +133,7 @@ def raster_copy_with_mask( s_fh, s_xoff, s_yoff, s_xsize, s_ysize, s_band_n,
     t_band.WriteArray( to_write, t_xoff, t_yoff )
 
     return 0
-    
+
 # =============================================================================
 def names_to_fileinfos( names ):
     """
@@ -150,7 +144,7 @@ def names_to_fileinfos( names ):
     Returns a list of file_info objects.  There may be less file_info objects
     than names if some of the names could not be opened as GDAL files.
     """
-    
+
     file_infos = []
     for name in names:
         fi = file_info()
@@ -197,11 +191,11 @@ class file_info:
 
     def report( self ):
         print('Filename: '+ self.filename)
-        print('File Size: %dx%dx%d' \
+        print('File Size: %dx%dx%d'
               % (self.xsize, self.ysize, self.bands))
-        print('Pixel Size: %f x %f' \
+        print('Pixel Size: %f x %f'
               % (self.geotransform[1],self.geotransform[5]))
-        print('UL:(%f,%f)   LR:(%f,%f)' \
+        print('UL:(%f,%f)   LR:(%f,%f)'
               % (self.ulx,self.uly,self.lrx,self.lry))
 
     def copy_into( self, t_fh, s_band = 1, t_band = 1, nodata_arg=None ):
@@ -237,7 +231,7 @@ class file_info:
         else:
             tgw_uly = max(t_uly,self.uly)
             tgw_lry = min(t_lry,self.lry)
-        
+
         # do they even intersect?
         if tgw_ulx >= tgw_lrx:
             return 1
@@ -245,7 +239,7 @@ class file_info:
             return 1
         if t_geotransform[5] > 0 and tgw_uly >= tgw_lry:
             return 1
-            
+
         # compute target window in pixel coordinates.
         tw_xoff = int((tgw_ulx - t_geotransform[0]) / t_geotransform[1] + 0.1)
         tw_yoff = int((tgw_uly - t_geotransform[3]) / t_geotransform[5] + 0.1)
@@ -271,10 +265,9 @@ class file_info:
         # Open the source file, and copy the selected region.
         s_fh = gdal.Open( self.filename )
 
-        return \
-            raster_copy( s_fh, sw_xoff, sw_yoff, sw_xsize, sw_ysize, s_band,
-                         t_fh, tw_xoff, tw_yoff, tw_xsize, tw_ysize, t_band,
-                         nodata_arg )
+        return raster_copy( s_fh, sw_xoff, sw_yoff, sw_xsize, sw_ysize, s_band,
+                            t_fh, tw_xoff, tw_yoff, tw_xsize, tw_ysize, t_band,
+                            nodata_arg )
 
 
 # =============================================================================
@@ -313,7 +306,7 @@ def main( argv=None ):
     createonly = 0
     bTargetAlignedPixels = False
     start_time = time.time()
-    
+
     gdal.AllRegister()
     if argv is None:
         argv = sys.argv
@@ -398,7 +391,7 @@ def main( argv=None ):
             i = i + 4
 
         elif arg[:1] == '-':
-            print('Unrecognised command option: %s' % arg)
+            print('Unrecognized command option: %s' % arg)
             Usage()
             sys.exit( 1 )
 
@@ -430,7 +423,7 @@ def main( argv=None ):
         uly = file_infos[0].uly
         lrx = file_infos[0].lrx
         lry = file_infos[0].lry
-        
+
         for fi in file_infos:
             ulx = min(ulx, fi.ulx)
             uly = max(uly, fi.uly)
@@ -448,16 +441,16 @@ def main( argv=None ):
     gdal.PushErrorHandler( 'CPLQuietErrorHandler' )
     t_fh = gdal.Open( out_file, gdal.GA_Update )
     gdal.PopErrorHandler()
-    
+
     # Create output file if it does not already exist.
     if t_fh is None:
-    
+
         if bTargetAlignedPixels:
             ulx = math.floor(ulx / psize_x) * psize_x
             lrx = math.ceil(lrx / psize_x) * psize_x
             lry = math.floor(lry / -psize_y) * -psize_y
             uly = math.ceil(uly / -psize_y) * -psize_y
-    
+
         geotransform = [ulx, psize_x, 0, uly, 0, psize_y]
 
         xsize = int((lrx - ulx) / geotransform[1] + 0.5)
@@ -478,7 +471,7 @@ def main( argv=None ):
         if t_fh is None:
             print('Creation failed, terminating gdal_merge.')
             sys.exit( 1 )
-            
+
         t_fh.SetGeoTransform( geotransform )
         t_fh.SetProjection( file_infos[0].projection )
 
@@ -488,7 +481,7 @@ def main( argv=None ):
         if separate != 0:
             bands=0
             for fi in file_infos:
-                bands=bands + fi.bands            
+                bands=bands + fi.bands
             if t_fh.RasterCount < bands :
                 print('Existing output file has less bands than the input files. You should delete it before. Terminating gdal_merge.')
                 sys.exit( 1 )
@@ -515,14 +508,14 @@ def main( argv=None ):
     if quiet == 0 and verbose == 0:
         progress( 0.0 )
     fi_processed = 0
-    
+
     for fi in file_infos:
         if createonly != 0:
             continue
-        
+
         if verbose != 0:
             print("")
-            print("Processing file %5d of %5d, %6.3f%% completed in %d minutes." \
+            print("Processing file %5d of %5d, %6.3f%% completed in %d minutes."
                   % (fi_processed+1,len(file_infos),
                      fi_processed * 100.0 / len(file_infos),
                      int(round((time.time() - start_time)/60.0)) ))
@@ -535,11 +528,11 @@ def main( argv=None ):
             for band in range(1, fi.bands+1):
                 fi.copy_into( t_fh, band, t_band, nodata )
                 t_band = t_band+1
-            
+
         fi_processed = fi_processed+1
         if quiet == 0 and verbose == 0:
             progress( fi_processed / float(len(file_infos))  )
-    
+
     # Force file to be closed.
     t_fh = None
 
diff --git a/swig/python/scripts/gdal_pansharpen.py b/swig/python/scripts/gdal_pansharpen.py
new file mode 100644
index 0000000..accea2b
--- /dev/null
+++ b/swig/python/scripts/gdal_pansharpen.py
@@ -0,0 +1,249 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+###############################################################################
+# $Id: gdal_pansharpen.py 29568 2015-07-23 14:33:44Z rouault $
+#
+#  Project:  GDAL scripts
+#  Purpose:  Perform a pansharpening operation
+#  Author:   Even Rouault <even.rouault at spatialys.com>
+#
+###############################################################################
+#  Copyright (c) 2015, Even Rouault <even.rouault at spatialys.com>
+#
+#  Permission is hereby granted, free of charge, to any person obtaining a
+#  copy of this software and associated documentation files (the "Software"),
+#  to deal in the Software without restriction, including without limitation
+#  the rights to use, copy, modify, merge, publish, distribute, sublicense,
+#  and/or sell copies of the Software, and to permit persons to whom the
+#  Software is furnished to do so, subject to the following conditions:
+#
+#  The above copyright notice and this permission notice shall be included
+#  in all copies or substantial portions of the Software.
+#
+#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+#  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+#  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+#  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+#  DEALINGS IN THE SOFTWARE.
+###############################################################################
+
+import os
+import sys
+from osgeo import gdal
+
+def Usage():
+    print('Usage: gdal_pansharpen [--help-general] pan_dataset {spectral_dataset[,band=num]}+ out_dataset')
+    print('                       [-of format] [-b band]* [-w weight]*')
+    print('                       [-r {nearest,bilinear,cubic,cubicspline,lanczos,average}]')
+    print('                       [-threads {ALL_CPUS|number}] [-bitdepth val] [-nodata val]')
+    print('                       [-spat_adjust {union,intersection,none,nonewithoutwarning}]')
+    print('                       [-verbose_vrt] [-co NAME=VALUE]* [-q]')
+    print('')
+    print('Create a dataset resulting from a pansharpening operation.')
+    return -1
+
+def gdal_pansharpen(argv):
+
+    argv = gdal.GeneralCmdLineProcessor( argv )
+    if argv is None:
+        return -1
+
+    pan_name = None
+    last_name = None
+    spectral_ds = []
+    spectral_bands = []
+    out_name = None
+    bands = []
+    weights = []
+    format = 'GTiff'
+    creation_options = []
+    callback = gdal.TermProgress
+    resampling = None
+    spat_adjust = None
+    verbose_vrt = False
+    num_threads = None
+    bitdepth = None
+    nodata = None
+
+    i = 1
+    argc = len(argv)
+    while i < argc:
+        if argv[i] == '-of' and i < len(argv)-1:
+            format = argv[i+1]
+            i = i + 1
+        elif argv[i] == '-r' and i < len(argv)-1:
+            resampling = argv[i+1]
+            i = i + 1
+        elif argv[i] == '-spat_adjust' and i < len(argv)-1:
+            spat_adjust = argv[i+1]
+            i = i + 1
+        elif argv[i] == '-b' and i < len(argv)-1:
+            bands.append(int(argv[i+1]))
+            i = i + 1
+        elif argv[i] == '-w' and i < len(argv)-1:
+            weights.append(float(argv[i+1]))
+            i = i + 1
+        elif argv[i] == '-co' and i < len(argv)-1:
+            creation_options.append(argv[i+1])
+            i = i + 1
+        elif argv[i] == '-threads' and i < len(argv)-1:
+            num_threads = argv[i+1]
+            i = i + 1
+        elif argv[i] == '-bitdepth' and i < len(argv)-1:
+            bitdepth = argv[i+1]
+            i = i + 1
+        elif argv[i] == '-nodata' and i < len(argv)-1:
+            nodata = argv[i+1]
+            i = i + 1
+        elif argv[i] == '-q':
+            callback = None
+        elif argv[i] == '-verbose_vrt':
+            verbose_vrt = True
+        elif argv[i][0] == '-':
+            sys.stderr.write('Unrecognized option : %s\n' % argv[i])
+            return Usage()
+        elif pan_name is None:
+            pan_name = argv[i]
+            pan_ds = gdal.Open(pan_name)
+            if pan_ds is None:
+                return 1
+        else:
+            if last_name is not None:
+                pos = last_name.find(',band=')
+                if pos > 0:
+                    spectral_name = last_name[0:pos]
+                    ds = gdal.Open(spectral_name)
+                    if ds is None:
+                        return 1
+                    band_num = int(last_name[pos+len(',band='):])
+                    band = ds.GetRasterBand(band_num)
+                    spectral_ds.append(ds)
+                    spectral_bands.append(band)
+                else:
+                    spectral_name = last_name
+                    ds = gdal.Open(spectral_name)
+                    if ds is None:
+                        return 1
+                    for j in range(ds.RasterCount):
+                        spectral_ds.append(ds)
+                        spectral_bands.append(ds.GetRasterBand(j+1))
+
+            last_name = argv[i]
+
+        i = i + 1
+
+    if pan_name is None or len(spectral_bands) == 0:
+        return Usage()
+    out_name = last_name
+
+    if len(bands) == 0:
+        bands = [ j+1 for j in range(len(spectral_bands)) ]
+    else:
+        for i in range(len(bands)):
+            if bands[i] < 0 or bands[i] > len(spectral_bands):
+                print('Invalid band number in -b: %d' % bands[i])
+                return 1
+
+    if len(weights) != 0 and len(weights) != len(spectral_bands):
+        print('There must be as many -w values specified as input spectral bands')
+        return 1
+
+    vrt_xml = """<VRTDataset subClass="VRTPansharpenedDataset">\n"""
+    if bands != [ j+1 for j in range(len(spectral_bands)) ]:
+        for i in range(len(bands)):
+            band = spectral_bands[bands[i]-1]
+            datatype = gdal.GetDataTypeName(band.DataType)
+            colorname = gdal.GetColorInterpretationName(band.GetColorInterpretation())
+            vrt_xml += """  <VRTRasterBand dataType="%s" band="%d" subClass="VRTPansharpenedRasterBand">
+      <ColorInterp>%s</ColorInterp>
+  </VRTRasterBand>\n""" % (datatype, i+1, colorname)
+
+    vrt_xml += """  <PansharpeningOptions>\n"""
+
+    if len(weights) != 0:
+        vrt_xml += """      <AlgorithmOptions>\n"""
+        vrt_xml += """        <Weights>"""
+        for i in range(len(weights)):
+            if i > 0: vrt_xml += ","
+            vrt_xml += "%.16g" % weights[i]
+        vrt_xml += "</Weights>\n"
+        vrt_xml += """      </AlgorithmOptions>\n"""
+
+    if resampling is not None:
+        vrt_xml += '      <Resampling>%s</Resampling>\n' % resampling
+
+    if num_threads is not None:
+        vrt_xml += '      <NumThreads>%s</NumThreads>\n' % num_threads
+
+    if bitdepth is not None:
+        vrt_xml += '      <BitDepth>%s</BitDepth>\n' % bitdepth
+
+    if nodata is not None:
+        vrt_xml += '      <NoData>%s</NoData>\n' % nodata
+
+    if spat_adjust is not None:
+        vrt_xml += '      <SpatialExtentAdjustment>%s</SpatialExtentAdjustment>\n' % spat_adjust
+
+    pan_relative='0'
+    if format.upper() == 'VRT':
+        if not os.path.isabs(pan_name):
+            pan_relative='1'
+            pan_name = os.path.relpath(pan_name, os.path.dirname(out_name))
+
+    vrt_xml += """    <PanchroBand>
+      <SourceFilename relativeToVRT="%s">%s</SourceFilename>
+      <SourceBand>1</SourceBand>
+    </PanchroBand>\n""" % (pan_relative, pan_name)
+
+    for i in range(len(spectral_bands)):
+        dstband = ''
+        for j in range(len(bands)):
+            if i + 1 == bands[j]:
+                dstband = ' dstBand="%d"' % (j+1)
+                break
+
+        ms_relative='0'
+        ms_name = spectral_ds[i].GetDescription()
+        if format.upper() == 'VRT':
+            if not os.path.isabs(ms_name):
+                ms_relative='1'
+                ms_name = os.path.relpath(ms_name, os.path.dirname(out_name))
+
+        vrt_xml += """    <SpectralBand%s>
+      <SourceFilename relativeToVRT="%s">%s</SourceFilename>
+      <SourceBand>%d</SourceBand>
+    </SpectralBand>\n""" % (dstband, ms_relative, ms_name, spectral_bands[i].GetBand())
+
+    vrt_xml += """  </PansharpeningOptions>\n"""
+    vrt_xml += """</VRTDataset>\n"""
+
+    if format.upper() == 'VRT':
+        f = gdal.VSIFOpenL(out_name, 'wb')
+        if f is None:
+            print('Cannot create %s' % out_name)
+            return 1
+        gdal.VSIFWriteL(vrt_xml, 1, len(vrt_xml), f)
+        gdal.VSIFCloseL(f)
+        if verbose_vrt:
+            vrt_ds = gdal.Open(out_name, gdal.GA_Update)
+            vrt_ds.SetMetadata(vrt_ds.GetMetadata())
+        else:
+            vrt_ds = gdal.Open(out_name)
+        if vrt_ds is None:
+            return 1
+
+        return 0
+
+    vrt_ds = gdal.Open(vrt_xml)
+    out_ds = gdal.GetDriverByName(format).CreateCopy(out_name, vrt_ds, 0, creation_options, callback = callback)
+    if out_ds is None:
+        return 1
+    return 0
+
+def main():
+    return gdal_pansharpen(sys.argv)
+
+if __name__ == '__main__':
+    sys.exit(gdal_pansharpen(sys.argv))
diff --git a/swig/python/scripts/gdal_polygonize.py b/swig/python/scripts/gdal_polygonize.py
index efe24c6..15a041c 100755
--- a/swig/python/scripts/gdal_polygonize.py
+++ b/swig/python/scripts/gdal_polygonize.py
@@ -1,26 +1,26 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #******************************************************************************
-#  $Id: gdal_polygonize.py 28389 2015-01-30 19:26:09Z rouault $
-# 
+#  $Id: gdal_polygonize.py 33790 2016-03-26 12:42:12Z goatbar $
+#
 #  Project:  GDAL Python Interface
 #  Purpose:  Application for converting raster data to a vector polygon layer.
 #  Author:   Frank Warmerdam, warmerdam at pobox.com
-# 
+#
 #******************************************************************************
 #  Copyright (c) 2008, Frank Warmerdam
 #  Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
-# 
+#
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
 #  to deal in the Software without restriction, including without limitation
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -30,13 +30,13 @@
 #  DEALINGS IN THE SOFTWARE.
 #******************************************************************************
 
-try:
-    from osgeo import gdal, ogr, osr
-except ImportError:
-    import gdal, ogr, osr
-
 import sys
 
+from osgeo import gdal
+from osgeo import ogr
+from osgeo import osr
+
+
 def Usage():
     print("""
 gdal_polygonize [-8] [-nomask] [-mask filename] raster_file [-b band]
@@ -80,14 +80,14 @@ while i < len(argv):
 
     elif arg == '-8':
         options.append('8CONNECTED=8')
-        
+
     elif arg == '-nomask':
         mask = 'none'
-        
+
     elif arg == '-mask':
         i = i + 1
         mask = argv[i]
-        
+
     elif arg == '-b':
         i = i + 1
         src_band_n = int(argv[i])
@@ -114,7 +114,7 @@ if src_filename is None or dst_filename is None:
 
 if dst_layername is None:
     dst_layername = 'out'
-    
+
 # =============================================================================
 # 	Verify we have next gen bindings with the polygonize method.
 # =============================================================================
@@ -132,7 +132,7 @@ except:
 # =============================================================================
 
 src_ds = gdal.Open( src_filename )
-    
+
 if src_ds is None:
     print('Unable to open %s' % src_filename)
     sys.exit(1)
@@ -181,12 +181,12 @@ if dst_layer is None:
     if src_ds.GetProjectionRef() != '':
         srs = osr.SpatialReference()
         srs.ImportFromWkt( src_ds.GetProjectionRef() )
-        
+
     dst_layer = dst_ds.CreateLayer(dst_layername, srs = srs )
 
     if dst_fieldname is None:
         dst_fieldname = 'DN'
-        
+
     fd = ogr.FieldDefn( dst_fieldname, ogr.OFTInteger )
     dst_layer.CreateField( fd )
     dst_field = 0
@@ -204,18 +204,11 @@ if quiet_flag:
     prog_func = None
 else:
     prog_func = gdal.TermProgress
-    
+
 result = gdal.Polygonize( srcband, maskband, dst_layer, dst_field, options,
                           callback = prog_func )
-    
+
 srcband = None
 src_ds = None
 dst_ds = None
 mask_ds = None
-
-
-
-
-
-
-
diff --git a/swig/python/scripts/gdal_proximity.dox b/swig/python/scripts/gdal_proximity.dox
index 090b0a9..ff46362 100644
--- a/swig/python/scripts/gdal_proximity.dox
+++ b/swig/python/scripts/gdal_proximity.dox
@@ -38,7 +38,7 @@ format specific documentation for legal creation options for each format.
 </dd>
 
 <dt> <b>-ot</b> <i>datatype</i>:</dt><dd> 
-Force the output image bands to have a specific type. Use type names (ie. Byte, Int16,...)
+Force the output image bands to have a specific type. Use type names (i.e. Byte, Int16,...)
 </dd>
 
 <dt> <b>-values</b> <i>n,n,n</i>:</dt><dd> 
diff --git a/swig/python/scripts/gdal_proximity.py b/swig/python/scripts/gdal_proximity.py
index b93399f..2e3b05e 100755
--- a/swig/python/scripts/gdal_proximity.py
+++ b/swig/python/scripts/gdal_proximity.py
@@ -1,26 +1,26 @@
 #!/usr/bin/env python
 #******************************************************************************
-#  $Id: gdal_proximity.py 28882 2015-04-09 15:59:38Z rouault $
-# 
+#  $Id: gdal_proximity.py 33790 2016-03-26 12:42:12Z goatbar $
+#
 #  Name:     gdalproximity
 #  Project:  GDAL Python Interface
 #  Purpose:  Application for computing raster proximity maps.
 #  Author:   Frank Warmerdam, warmerdam at pobox.com
-# 
+#
 #******************************************************************************
 #  Copyright (c) 2008, Frank Warmerdam
 #  Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
-# 
+#
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
 #  to deal in the Software without restriction, including without limitation
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -30,16 +30,13 @@
 #  DEALINGS IN THE SOFTWARE.
 #******************************************************************************
 
-try:
-    from osgeo import gdal
-except ImportError:
-    import gdal
-
 import sys
 
+from osgeo import gdal
+
 def Usage():
     print("""
-gdal_proximity.py srcfile dstfile [-srcband n] [-dstband n] 
+gdal_proximity.py srcfile dstfile [-srcband n] [-dstband n]
                   [-of format] [-co name=value]*
                   [-ot Byte/Int16/Int32/Float32/etc]
                   [-values n,n,n] [-distunits PIXEL/GEO]
@@ -131,13 +128,13 @@ while i < len(argv):
 
 if src_filename is None or dst_filename is None:
     Usage()
-    
+
 # =============================================================================
 #    Open source file
 # =============================================================================
 
 src_ds = gdal.Open( src_filename )
-    
+
 if src_ds is None:
     print('Unable to open %s' % src_filename)
     sys.exit(1)
@@ -169,7 +166,7 @@ if dst_ds is None:
 
     dst_ds.SetGeoTransform( src_ds.GetGeoTransform() )
     dst_ds.SetProjection( src_ds.GetProjectionRef() )
-    
+
     dstband = dst_ds.GetRasterBand(1)
 
 # =============================================================================
@@ -180,16 +177,11 @@ if quiet_flag:
     prog_func = None
 else:
     prog_func = gdal.TermProgress
-    
+
 gdal.ComputeProximity( srcband, dstband, options,
                        callback = prog_func )
-    
+
 srcband = None
 dstband = None
 src_ds = None
 dst_ds = None
-
-
-
-
-
diff --git a/swig/python/scripts/gdal_retile.py b/swig/python/scripts/gdal_retile.py
index 876e922..a414c5c 100755
--- a/swig/python/scripts/gdal_retile.py
+++ b/swig/python/scripts/gdal_retile.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ###############################################################################
-#  $Id: gdal_retile.py 28389 2015-01-30 19:26:09Z rouault $
+#  $Id: gdal_retile.py 33790 2016-03-26 12:42:12Z goatbar $
 #
 # Purpose:  Module for retiling (merging) tiles and building tiled pyramids
 # Author:   Christian Meuller, christian.mueller at nvoe.at
@@ -29,19 +29,13 @@
 # DEALINGS IN THE SOFTWARE.
 ###############################################################################
 
-
-try:
-    from osgeo import gdal
-    from osgeo import ogr
-    from osgeo import osr
-except:
-    import gdal
-    import ogr
-    import osr
-
-import sys
-import os
 import math
+import os
+import sys
+
+from osgeo import gdal
+from osgeo import ogr
+from osgeo import osr
 
 try:
     progress = gdal.TermProgress_nocb
@@ -264,16 +258,16 @@ class mosaic_info:
             assert tw_yoff >= 0
             assert sw_xoff >= 0
             assert sw_yoff >= 0
-            
+
             for bandNr in range(1, self.bands + 1):
                 s_band = sourceDS.GetRasterBand( bandNr )
                 t_band = resultDS.GetRasterBand( bandNr )
                 if self.ct is not None:
                     t_band.SetRasterColorTable(self.ct)
                 t_band.SetRasterColorInterpretation(self.ci[bandNr-1])
-                
+
                 data = s_band.ReadRaster( sw_xoff, sw_yoff, sw_xsize, sw_ysize, tw_xsize, tw_ysize, self.band_type )
-                if data is None:                    
+                if data is None:
                     print(gdal.GetLastErrorMsg())
 
                 t_band.WriteRaster(tw_xoff, tw_yoff, tw_xsize, tw_ysize, data )
@@ -867,7 +861,7 @@ def main(args = None):
         elif arg == '-useDirForEachRow':
             UseDirForEachRow=True
         elif arg[:1] == '-':
-            print('Unrecognised command option: %s' % arg)
+            print('Unrecognized command option: %s' % arg)
             Usage()
             return 1
 
diff --git a/swig/python/scripts/gdal_sieve.py b/swig/python/scripts/gdal_sieve.py
index 7f0cbfb..ee63dd3 100755
--- a/swig/python/scripts/gdal_sieve.py
+++ b/swig/python/scripts/gdal_sieve.py
@@ -1,25 +1,25 @@
 #!/usr/bin/env python
 #******************************************************************************
-#  $Id: gdal_sieve.py 28389 2015-01-30 19:26:09Z rouault $
-# 
+#  $Id: gdal_sieve.py 33790 2016-03-26 12:42:12Z goatbar $
+#
 #  Project:  GDAL Python Interface
 #  Purpose:  Application for applying sieve filter to raster data.
 #  Author:   Frank Warmerdam, warmerdam at pobox.com
-# 
+#
 #******************************************************************************
 #  Copyright (c) 2008, Frank Warmerdam
 #  Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
-# 
+#
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
 #  to deal in the Software without restriction, including without limitation
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -29,20 +29,18 @@
 #  DEALINGS IN THE SOFTWARE.
 #******************************************************************************
 
-try:
-    from osgeo import gdal
-except ImportError:
-    import gdal
-
 import sys
 
+from osgeo import gdal
+
+
 def Usage():
     print("""
 gdal_sieve [-q] [-st threshold] [-4] [-8] [-o name=value]
            srcfile [-nomask] [-mask filename] [-of format] [dstfile]
 """)
     sys.exit(1)
-    
+
 # =============================================================================
 # 	Mainline
 # =============================================================================
@@ -74,31 +72,31 @@ while i < len(argv):
 
     elif arg == '-4':
         connectedness = 4
-        
+
     elif arg == '-8':
         connectedness = 8
-        
+
     elif arg == '-q' or arg == '-quiet':
         quiet_flag = 1
-        
+
     elif arg == '-st':
         i = i + 1
         threshold = int(argv[i])
-        
+
     elif arg == '-nomask':
         mask = 'none'
-        
+
     elif arg == '-mask':
         i = i + 1
         mask = argv[i]
-        
+
     elif arg == '-mask':
         i = i + 1
         mask = argv[i]
-        
+
     elif arg[:2] == '-h':
         Usage()
-        
+
     elif src_filename is None:
         src_filename = argv[i]
 
@@ -112,7 +110,7 @@ while i < len(argv):
 
 if src_filename is None:
     Usage()
-    
+
 # =============================================================================
 # 	Verify we have next gen bindings with the sievefilter method.
 # =============================================================================
@@ -133,7 +131,7 @@ if dst_filename is None:
     src_ds = gdal.Open( src_filename, gdal.GA_Update )
 else:
     src_ds = gdal.Open( src_filename, gdal.GA_ReadOnly )
-    
+
 if src_ds is None:
     print('Unable to open %s ' % src_filename)
     sys.exit(1)
@@ -161,7 +159,7 @@ if dst_filename is not None:
     if wkt != '':
         dst_ds.SetProjection( wkt )
     dst_ds.SetGeoTransform( src_ds.GetGeoTransform() )
-    
+
     dstband = dst_ds.GetRasterBand(1)
 else:
     dstband = srcband
@@ -174,17 +172,11 @@ if quiet_flag:
     prog_func = None
 else:
     prog_func = gdal.TermProgress
-    
+
 result = gdal.SieveFilter( srcband, maskband, dstband,
-                           threshold, connectedness, 
+                           threshold, connectedness,
                            callback = prog_func )
-    
+
 src_ds = None
 dst_ds = None
 mask_ds = None
-
-
-
-
-
-
diff --git a/swig/python/scripts/gdalchksum.py b/swig/python/scripts/gdalchksum.py
index c5e26d2..2cdda66 100755
--- a/swig/python/scripts/gdalchksum.py
+++ b/swig/python/scripts/gdalchksum.py
@@ -1,24 +1,24 @@
 #!/usr/bin/env python
 #******************************************************************************
-#  $Id: gdalchksum.py 18952 2010-02-28 11:59:53Z rouault $
-# 
+#  $Id: gdalchksum.py 33790 2016-03-26 12:42:12Z goatbar $
+#
 #  Project:  GDAL
 #  Purpose:  Application to checksum a GDAL image file.
 #  Author:   Frank Warmerdam, warmerdam at pobox.com
-# 
+#
 #******************************************************************************
 #  Copyright (c) 2003, Frank Warmerdam <warmerdam at pobox.com>
-# 
+#
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
 #  to deal in the Software without restriction, including without limitation
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -28,13 +28,10 @@
 #  DEALINGS IN THE SOFTWARE.
 #******************************************************************************
 
-try:
-    from osgeo import gdal
-except ImportError:
-    import gdal
-
 import sys
 
+from osgeo import gdal
+
 def Usage():
     print('Usage: gdalchksum.py [-b band] [-srcwin xoff yoff xsize ysize] file')
     sys.exit(1)
@@ -77,7 +74,7 @@ while i < len(argv):
 
 if filename is None:
     Usage()
-    
+
 # Open source file
 
 ds = gdal.Open( filename )
@@ -102,11 +99,3 @@ for band_num in bands:
     print(result)
 
 ds = None
-
-
-
-
-
-
-
-
diff --git a/swig/python/scripts/gdalcompare.py b/swig/python/scripts/gdalcompare.py
index 1edb73c..82255bc 100755
--- a/swig/python/scripts/gdalcompare.py
+++ b/swig/python/scripts/gdalcompare.py
@@ -32,7 +32,8 @@ import os
 import sys
 import filecmp
 
-from osgeo import gdal, osr
+from osgeo import gdal
+from osgeo import osr
 
 #######################################################
 def compare_metadata(golden_md, new_md, id, options=[]):
@@ -115,7 +116,7 @@ def compare_band(golden_band, new_band, id, options=[]):
     for i in range(golden_band.GetOverviewCount()):
       found_diff += compare_band(golden_band.GetOverview(i),
                    new_band.GetOverview(i),
-                   id + ' overview ' + str(i), 
+                   id + ' overview ' + str(i),
                    options)
 
   # Metadata
@@ -139,7 +140,7 @@ def compare_srs(golden_wkt, new_wkt):
   new_srs = osr.SpatialReference(new_wkt)
 
   if golden_srs.IsSame(new_srs):
-    print('  * IsSame() reports them as equivelent.')
+    print('  * IsSame() reports them as equivalent.')
   else:
     print('  * IsSame() reports them as different.')
 
@@ -180,14 +181,14 @@ def compare_db(golden_db, new_db, options=[]):
     print('Band count mismatch (golden=%d, new=%d)' \
         % (golden_db.RasterCount, new_db.RasterCount))
     found_diff += 1
-  
+
   # Dimensions
   for i in range(golden_db.RasterCount):
       gSzX = golden_db.GetRasterBand(i+1).XSize
       nSzX = new_db.GetRasterBand(i+1).XSize
       gSzY = golden_db.GetRasterBand(i+1).YSize
       nSzY = new_db.GetRasterBand(i+1).YSize
-      
+
       if gSzX != nSzX or gSzY != nSzY:
           print('Band size mismatch (band=%d golden=[%d,%d], new=[%d,%d])' %
                 (i, gSzX, gSzY, nSzX, nSzY))
@@ -206,7 +207,7 @@ def compare_db(golden_db, new_db, options=[]):
 #######################################################
 def compare_sds(golden_db, new_db, options=[]):
   found_diff = 0
-  
+
   golden_sds = golden_db.GetMetadata('SUBDATASETS')
   new_sds = new_db.GetMetadata('SUBDATASETS')
 
@@ -224,7 +225,7 @@ def compare_sds(golden_db, new_db, options=[]):
             % (sds_diff, golden_sds[key],new_sds[key]))
 
   return found_diff
-  
+
 #######################################################
 def Usage():
   print('Usage: gdalcompare.py [-sds] <golden_file> <new_file>')
@@ -276,7 +277,7 @@ if __name__ == '__main__':
   # compare raw binary files.
   try:
     os.stat(golden_file)
-    
+
     if not filecmp.cmp(golden_file,new_file):
       print('Files differ at the binary level.')
       found_diff += 1
@@ -290,7 +291,7 @@ if __name__ == '__main__':
 
   if check_sds:
     found_diff += compare_sds(golden_db, new_db)
-    
+
   print('Differences Found: ' + str(found_diff))
 
   sys.exit(found_diff)
diff --git a/swig/python/scripts/gdalident.py b/swig/python/scripts/gdalident.py
index ddc2b3d..6cea22c 100755
--- a/swig/python/scripts/gdalident.py
+++ b/swig/python/scripts/gdalident.py
@@ -1,24 +1,24 @@
 #!/usr/bin/env python
 #******************************************************************************
-#  $Id: gdalident.py 24064 2012-03-04 00:34:19Z warmerdam $
-# 
+#  $Id: gdalident.py 32555 2015-12-30 19:26:44Z goatbar $
+#
 #  Project:  GDAL
 #  Purpose:  Application to identify files by format.
 #  Author:   Frank Warmerdam, warmerdam at pobox.com
-# 
+#
 #******************************************************************************
 #  Copyright (c) 2007, Frank Warmerdam <warmerdam at pobox.com>
-# 
+#
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
 #  to deal in the Software without restriction, including without limitation
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -28,14 +28,13 @@
 #  DEALINGS IN THE SOFTWARE.
 #******************************************************************************
 #
-try:
-    from osgeo import gdal
-except ImportError:
-    import gdal
 
-import sys
-import stat
 import os
+import stat
+import sys
+
+from osgeo import gdal
+
 
 # =============================================================================
 # 	Usage()
@@ -58,7 +57,7 @@ def ProcessTarget( target, recursive, report_failure, filelist = None ):
     if driver is not None:
         print('%s: %s' % (target, driver.ShortName))
     elif report_failure:
-        print('%s: unrecognised' % target)
+        print('%s: unrecognized' % target)
 
     if recursive and driver is None:
         try:
@@ -71,7 +70,7 @@ def ProcessTarget( target, recursive, report_failure, filelist = None ):
             for item in subfilelist:
                 subtarget = os.path.join(target,item)
                 ProcessTarget( subtarget, 1, report_failure, subfilelist )
-            
+
 # =============================================================================
 # 	Mainline
 # =============================================================================
diff --git a/swig/python/scripts/gdalimport.py b/swig/python/scripts/gdalimport.py
index fe37d5d..734ce06 100755
--- a/swig/python/scripts/gdalimport.py
+++ b/swig/python/scripts/gdalimport.py
@@ -1,25 +1,25 @@
 #!/usr/bin/env python
 #******************************************************************************
-#  $Id: gdalimport.py 18952 2010-02-28 11:59:53Z rouault $
-# 
+#  $Id: gdalimport.py 33790 2016-03-26 12:42:12Z goatbar $
+#
 #  Name:     gdalimport
 #  Project:  GDAL Python Interface
 #  Purpose:  Import a GDAL supported file to Tiled GeoTIFF, and build overviews
 #  Author:   Frank Warmerdam, warmerdam at pobox.com
-# 
+#
 #******************************************************************************
 #  Copyright (c) 2000, Frank Warmerdam
-# 
+#
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
 #  to deal in the Software without restriction, including without limitation
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -29,13 +29,10 @@
 #  DEALINGS IN THE SOFTWARE.
 #******************************************************************************
 
-try:
-    from osgeo import gdal
-except ImportError:
-    import gdal
-
-import sys
 import os.path
+import sys
+
+from osgeo import gdal
 
 gdal.AllRegister()
 argv = gdal.GeneralCmdLineProcessor( sys.argv )
@@ -48,7 +45,7 @@ if len(argv) < 2:
 
 def progress_cb( complete, message, cb_data ):
     print('%s %d' % (cb_data, complete))
-    
+
 
 filename = argv[1]
 dataset = gdal.Open( filename )
@@ -61,7 +58,7 @@ if geotiff is None:
     print('GeoTIFF driver not registered.')
     sys.exit(1)
 
-if len(argv) < 3: 
+if len(argv) < 3:
     newbase, ext = os.path.splitext(os.path.basename(filename))
     newfile = newbase + ".tif"
     i = 0
@@ -84,6 +81,3 @@ new_dataset.BuildOverviews( "average", callback=progress_cb,
 new_dataset = None
 
 print('Done')
-
-
-
diff --git a/swig/python/scripts/gdalmove.py b/swig/python/scripts/gdalmove.py
index c60c6a2..e4f8c56 100755
--- a/swig/python/scripts/gdalmove.py
+++ b/swig/python/scripts/gdalmove.py
@@ -1,24 +1,24 @@
 #!/usr/bin/env python
 #******************************************************************************
-# 
+#
 #  Project:  GDAL Python Interface
 #  Purpose:  Application for "warping" an image by just updating it's SRS
 #            and geotransform.
 #  Author:   Frank Warmerdam, warmerdam at pobox.com
-# 
+#
 #******************************************************************************
 #  Copyright (c) 2012, Frank Warmerdam
-# 
+#
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
 #  to deal in the Software without restriction, including without limitation
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -28,9 +28,10 @@
 #  DEALINGS IN THE SOFTWARE.
 #******************************************************************************
 
-from osgeo import gdal, osr
-import sys
 import math
+import sys
+
+from osgeo import gdal, osr
 
 ###############################################################################
 def fmt_loc( srs_obj, loc):
@@ -38,18 +39,18 @@ def fmt_loc( srs_obj, loc):
         return '%12.3f %12.3f' % (loc[0], loc[1])
     else:
         return '%12.8f %12.8f' % (loc[0], loc[1])
-    
+
 ###############################################################################
 def move( filename, t_srs, s_srs=None, pixel_threshold = None ):
 
     # -------------------------------------------------------------------------
-    # Open the file. 
+    # Open the file.
     # -------------------------------------------------------------------------
     ds = gdal.Open( filename )
 
     # -------------------------------------------------------------------------
     # Compute the current (s_srs) locations of the four corners and center
-    # of the image. 
+    # of the image.
     # -------------------------------------------------------------------------
     corners_names = [
         'Upper Left',
@@ -57,7 +58,7 @@ def move( filename, t_srs, s_srs=None, pixel_threshold = None ):
         'Upper Right',
         'Lower Right',
         'Center' ]
-    
+
     corners_pixel_line = [
         (0, 0, 0),
         (0, ds.RasterYSize,0),
@@ -74,16 +75,16 @@ def move( filename, t_srs, s_srs=None, pixel_threshold = None ):
             (orig_gt[0] + item[0] * orig_gt[1] + item[1] * orig_gt[2],
              orig_gt[3] + item[0] * orig_gt[4] + item[1] * orig_gt[5],
              item[2]) )
-        
+
     # -------------------------------------------------------------------------
-    # Prepare a transformation from source to destination srs. 
+    # Prepare a transformation from source to destination srs.
     # -------------------------------------------------------------------------
     if s_srs is None:
         s_srs = ds.GetProjectionRef()
 
     s_srs_obj = osr.SpatialReference()
     s_srs_obj.SetFromUserInput( s_srs )
-    
+
     t_srs_obj = osr.SpatialReference()
     t_srs_obj.SetFromUserInput( t_srs )
 
@@ -92,9 +93,9 @@ def move( filename, t_srs, s_srs=None, pixel_threshold = None ):
     # -------------------------------------------------------------------------
     # Transform the corners
     # -------------------------------------------------------------------------
-    
+
     corners_t_geo = tr.TransformPoints( corners_s_geo )
-    
+
     # -------------------------------------------------------------------------
     #  Compute a new geotransform for the image in the target SRS.  For now
     #  we just use the top left, top right, and bottom left to produce the
@@ -102,12 +103,12 @@ def move( filename, t_srs, s_srs=None, pixel_threshold = None ):
     #  definition, but if the underlying transformation is not affine it will
     #  be wrong at the center and bottom right.  It would be better if we
     #  used all five points for a least squares fit but that is a bit beyond
-    #  me for now. 
+    #  me for now.
     # -------------------------------------------------------------------------
     ul = corners_t_geo[0]
     ur = corners_t_geo[2]
     ll = corners_t_geo[1]
-    
+
     new_gt = (ul[0],
               (ur[0] - ul[0]) / ds.RasterXSize,
               (ll[0] - ul[0]) / ds.RasterYSize,
@@ -116,7 +117,7 @@ def move( filename, t_srs, s_srs=None, pixel_threshold = None ):
               (ll[1] - ul[1]) / ds.RasterYSize)
 
     inv_new_gt = gdal.InvGeoTransform( new_gt )
-    
+
     # -------------------------------------------------------------------------
     #  Report results for the five locations.
     # -------------------------------------------------------------------------
@@ -125,13 +126,13 @@ def move( filename, t_srs, s_srs=None, pixel_threshold = None ):
     error_geo = []
     error_pixel_line = []
     corners_pixel_line_new = []
-    
+
     print('___Corner___ ________Original________  _______Adjusted_________   ______ Err (geo) ______ _Err (pix)_')
 
     for i in range(len(corners_s_geo)):
 
         item = corners_pixel_line[i]
-        corners_t_new_geo.append( 
+        corners_t_new_geo.append(
             (new_gt[0] + item[0] * new_gt[1] + item[1] * new_gt[2],
              new_gt[3] + item[0] * new_gt[4] + item[1] * new_gt[5],
              item[2]) )
@@ -194,7 +195,7 @@ def move( filename, t_srs, s_srs=None, pixel_threshold = None ):
     else:
         print("""Maximum check point error is %.5f pixels which exceeds the
 error threshold so the file has not been updated.""" % max_error)
-    
+
     ds = None
 
 ###############################################################################
@@ -204,20 +205,20 @@ gdalmove.py [-s_srs <srs_defn>] -t_srs <srs_defn>
             [-et <max_pixel_err>] target_file
 """)
     sys.exit(1)
-    
+
 #############################################################################
 # Main
 
 def main():
     # Default GDAL argument parsing.
-    
+
     argv = gdal.GeneralCmdLineProcessor( sys.argv )
     if argv is None:
         sys.exit( 0 )
 
     if len(argv) == 1:
         Usage()
-        
+
     # Script argument defaults
     s_srs = None
     t_srs = None
diff --git a/swig/python/scripts/mkgraticule.py b/swig/python/scripts/mkgraticule.py
index 7d67231..33466a5 100755
--- a/swig/python/scripts/mkgraticule.py
+++ b/swig/python/scripts/mkgraticule.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: mkgraticule.py 28389 2015-01-30 19:26:09Z rouault $
+# $Id: mkgraticule.py 33790 2016-03-26 12:42:12Z goatbar $
 #
 # Project:  OGR Python samples
 # Purpose:  Produce a graticule (grid) dataset.
@@ -8,7 +8,7 @@
 #
 ###############################################################################
 # Copyright (c) 2003, Frank Warmerdam <warmerdam at pobox.com>
-# 
+#
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
 # to deal in the Software without restriction, including without limitation
@@ -28,15 +28,12 @@
 # DEALINGS IN THE SOFTWARE.
 ###############################################################################
 
-try:
-    from osgeo import osr
-    from osgeo import ogr
-except ImportError:
-    import osr
-    import ogr
-
 import sys
 
+from osgeo import ogr
+from osgeo import osr
+
+
 #############################################################################
 def float_range(*args):
     start = 0.0
@@ -108,14 +105,14 @@ while i < len(sys.argv):
         Usage()
 
     i = i + 1
-    
+
 if outfile is None:
     outfile = "graticule.shp"
 
 
 if substepsize > stepsize:
     substepsize = stepsize
-    
+
 #############################################################################-
 # Do we have an alternate SRS?
 
@@ -132,7 +129,7 @@ if t_srs is not None:
 else:
     t_srs_o = osr.SpatialReference()
     t_srs_o.SetFromUserInput( 'WGS84' )
-    
+
 #############################################################################-
 # Create graticule file.
 
@@ -149,7 +146,7 @@ layer = ds.CreateLayer( 'out', geom_type = ogr.wkbLineString,
 
 #########################################################################
 # Not connected case.  Produce individual segments are these are going to
-# be more resilent in the face of reprojection errors.
+# be more resilient in the face of reprojection errors.
 
 if not connected:
     #########################################################################
@@ -167,7 +164,7 @@ if not connected:
             err = 0
             if ct is not None:
                 err = geom.Transform( ct )
-              
+
             if err is 0:
                 feat.SetGeometry( geom )
                 layer.CreateFeature( feat )
@@ -188,7 +185,7 @@ if not connected:
                 feat.SetGeometry( geom )
                 layer.CreateFeature( feat )
 
-                
+
 #########################################################################
 # Connected case - produce one polyline for each complete line of latitude
 # or longitude.
@@ -202,14 +199,14 @@ if connected:
     for lat in float_range(ymin,ymax+stepsize/2,stepsize):
 
         geom = ogr.Geometry( type = ogr.wkbLineString )
-        
+
         for long_ in float_range(xmin,xmax+substepsize/2,substepsize):
             geom.AddPoint( long_, lat )
 
         err = 0
         if ct is not None:
             err = geom.Transform( ct )
-              
+
         if err is 0:
             feat.SetGeometry( geom )
             layer.CreateFeature( feat )
@@ -218,9 +215,9 @@ if connected:
     # Generate lines of longitude
 
     for long_ in float_range(xmin,xmax+stepsize/2,stepsize):
-        
+
         geom = ogr.Geometry( type = ogr.wkbLineString )
-        
+
         for lat in float_range(ymin,ymax+substepsize/2,substepsize):
             geom.AddPoint( long_, lat )
 
@@ -231,7 +228,7 @@ if connected:
         if err is 0:
             feat.SetGeometry( geom )
             layer.CreateFeature( feat )
-                
+
 #############################################################################
 # Cleanup
 
@@ -240,4 +237,3 @@ geom = None
 
 ds.Destroy()
 ds = None
-
diff --git a/swig/python/scripts/pct2rgb.py b/swig/python/scripts/pct2rgb.py
index 8b758ba..0b83e5b 100755
--- a/swig/python/scripts/pct2rgb.py
+++ b/swig/python/scripts/pct2rgb.py
@@ -1,26 +1,26 @@
 #!/usr/bin/env python
 #******************************************************************************
-#  $Id: pct2rgb.py 28389 2015-01-30 19:26:09Z rouault $
-# 
+#  $Id: pct2rgb.py 33127 2016-01-23 19:47:48Z rouault $
+#
 #  Name:     pct2rgb
 #  Project:  GDAL Python Interface
-#  Purpose:  Utility to convert palletted images into RGB (or RGBA) images.
+#  Purpose:  Utility to convert paletted images into RGB (or RGBA) images.
 #  Author:   Frank Warmerdam, warmerdam at pobox.com
-# 
+#
 #******************************************************************************
 #  Copyright (c) 2001, Frank Warmerdam
 #  Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
-# 
+#
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
 #  to deal in the Software without restriction, including without limitation
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -30,10 +30,9 @@
 #  DEALINGS IN THE SOFTWARE.
 #******************************************************************************
 
-try:
-    from osgeo import gdal
-except ImportError:
-    import gdal
+import sys
+
+from osgeo import gdal
 
 try:
     progress = gdal.TermProgress_nocb
@@ -47,8 +46,6 @@ except ImportError:
     import Numeric
 
 
-import sys
-
 def Usage():
     print('Usage: pct2rgb.py [-of format] [-b <band>] [-rgba] source_file dest_file')
     sys.exit(1)
@@ -182,10 +179,3 @@ if tif_filename != dst_filename:
     tif_ds = None
 
     gtiff_driver.Delete( tif_filename )
-
-
-
-
-
-
-
diff --git a/swig/python/scripts/rgb2pct.py b/swig/python/scripts/rgb2pct.py
index 7f6a7eb..e67ed79 100755
--- a/swig/python/scripts/rgb2pct.py
+++ b/swig/python/scripts/rgb2pct.py
@@ -1,25 +1,25 @@
 #!/usr/bin/env python
 #******************************************************************************
-#  $Id: rgb2pct.py 26001 2013-05-14 03:24:22Z warmerdam $
-# 
+#  $Id: rgb2pct.py 33790 2016-03-26 12:42:12Z goatbar $
+#
 #  Name:     rgb2pct
 #  Project:  GDAL Python Interface
 #  Purpose:  Application for converting an RGB image to a pseudocolored image.
 #  Author:   Frank Warmerdam, warmerdam at pobox.com
-# 
+#
 #******************************************************************************
 #  Copyright (c) 2001, Frank Warmerdam
-# 
+#
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
 #  to deal in the Software without restriction, including without limitation
 #  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 #  and/or sell copies of the Software, and to permit persons to whom the
 #  Software is furnished to do so, subject to the following conditions:
-# 
+#
 #  The above copyright notice and this permission notice shall be included
 #  in all copies or substantial portions of the Software.
-# 
+#
 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 #  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -29,13 +29,10 @@
 #  DEALINGS IN THE SOFTWARE.
 #******************************************************************************
 
-try:
-    from osgeo import gdal
-except ImportError:
-    import gdal
-
-import sys
 import os.path
+import sys
+
+from osgeo import gdal
 
 def Usage():
     print('Usage: rgb2pct.py [-n colors | -pct palette_file] [-of format] source_file dest_file')
@@ -86,7 +83,7 @@ while i < len(argv):
 
 if dst_filename is None:
     Usage()
-    
+
 # Open source file
 
 src_ds = gdal.Open( src_filename )
@@ -164,4 +161,3 @@ if tif_filename != dst_filename:
 
     os.close(tif_filedesc)
     gtiff_driver.Delete( tif_filename )
-
diff --git a/swig/python/setup.py b/swig/python/setup.py
index 249874e..d73af84 100644
--- a/swig/python/setup.py
+++ b/swig/python/setup.py
@@ -1,17 +1,16 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
- 
+
 # Setup script for GDAL Python bindings.
 # Inspired by psycopg2 setup.py file
 # http://www.initd.org/tracker/psycopg/browser/psycopg2/trunk/setup.py
 # Howard Butler hobu.inc at gmail.com
 
 
-gdal_version = '2.0.2'
+gdal_version = '2.1.0'
 
 import sys
 import os
-import string
 
 from glob import glob
 
@@ -22,13 +21,14 @@ from glob import glob
 HAVE_NUMPY=False
 HAVE_SETUPTOOLS = False
 BUILD_FOR_CHEESESHOP = False
+GNM_ENABLED = False
 
 # ---------------------------------------------------------------------------
 # Default build options
-# (may be overriden with setup.cfg or command line switches).
+# (may be overridden with setup.cfg or command line switches).
 # ---------------------------------------------------------------------------
 
-include_dirs = ['../../port', '../../gcore', '../../alg', '../../ogr/']
+include_dirs = ['../../port', '../../gcore', '../../alg', '../../ogr/', '../../ogr/ogrsf_frmts', '../../gnm', '../../apps']
 library_dirs = ['../../.libs', '../../']
 libraries = ['gdal']
 
@@ -104,7 +104,6 @@ class gdal_config_error(Exception): pass
 
 from distutils.command.build_ext import build_ext
 from distutils.ccompiler import get_default_compiler
-from distutils.sysconfig import get_python_inc
 
 def fetch_config(option, gdal_config='gdal-config'):
 
@@ -132,16 +131,16 @@ except OSError, e:
         p.wait()
 
     except ImportError:
-        
+
         import popen2
-        
+
         p = popen2.popen3(command)
         r = p[0].readline().strip()
         if not r:
             raise Warning(p[2].readline())
-    
+
     return r
-    
+
 class gdal_ext(build_ext):
 
     GDAL_CONFIG = 'gdal-config'
@@ -161,20 +160,20 @@ class gdal_ext(build_ext):
 
     def get_compiler(self):
         return self.compiler or get_default_compiler()
-    
+
     def get_gdal_config(self, option):
         try:
             return fetch_config(option, gdal_config = self.gdal_config)
         except gdal_config_error:
-            # If an error is thrown, it is possibly because 
-            # the gdal-config location given in setup.cfg is 
+            # If an error is thrown, it is possibly because
+            # the gdal-config location given in setup.cfg is
             # incorrect, or possibly the default -- ../../apps/gdal-config
-            # We'll try one time to use the gdal-config that might be 
+            # We'll try one time to use the gdal-config that might be
             # on the path. If that fails, we're done, however.
             if not self.already_raised_no_config_error:
                 self.already_raised_no_config_error = True
                 return fetch_config(option)
-            
+
     def finalize_options(self):
         if self.include_dirs is None:
             self.include_dirs = include_dirs
@@ -187,9 +186,9 @@ class gdal_ext(build_ext):
             self.libraries = libraries
 
         build_ext.finalize_options(self)
-        
+
         self.include_dirs.append(self.numpy_include_dir)
-        
+
         if self.get_compiler() == 'msvc':
             return True
 
@@ -232,6 +231,11 @@ array_module = Extension('osgeo._gdal_array',
                     extra_compile_args = extra_compile_args,
                     extra_link_args = extra_link_args)
 
+gnm_module = Extension('osgeo._gnm',
+                    sources=['extensions/gnm_wrap.cpp'],
+                    extra_compile_args = extra_compile_args,
+                    extra_link_args = extra_link_args)
+
 ext_modules = [gdal_module,
               gdalconst_module,
               osr_module,
@@ -241,7 +245,18 @@ py_modules = ['gdal',
               'ogr',
               'osr',
               'gdalconst']
-      
+
+if os.path.exists('setup_vars.ini'):
+    with open('setup_vars.ini') as f:
+        lines = f.readlines()
+        if 'GNM_ENABLED=yes' or 'GNM_ENABLED=yes\n' in lines:
+            GNM_ENABLED = True
+
+if GNM_ENABLED:
+    ext_modules.append(gnm_module)
+    py_modules.append('gnm')
+
+
 if HAVE_NUMPY:
     ext_modules.append(array_module)
     py_modules.append('gdalnumeric')
@@ -272,16 +287,15 @@ classifiers = [
         'Programming Language :: C++',
         'Topic :: Scientific/Engineering :: GIS',
         'Topic :: Scientific/Engineering :: Information Analysis',
-        
-]
 
+]
 
 
 if BUILD_FOR_CHEESESHOP:
     data_files = [("osgeo/data/gdal", glob(os.path.join("../../data", "*")))]
 else:
     data_files = None
-    
+
 exclude_package_data = {'':['GNUmakefile']}
 
 if HAVE_SETUPTOOLS:
diff --git a/update_copyright.py b/update_copyright.py
index 195e211..c6f3d5d 100644
--- a/update_copyright.py
+++ b/update_copyright.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 ###############################################################################
-# $Id: update_copyright.py 27043 2014-03-16 23:32:18Z rouault $
+# $Id: update_copyright.py 32002 2015-12-05 06:03:16Z goatbar $
 #
 # Project:  GDAL/OGR
 # Purpose:  Update copyright info in headers
@@ -10,7 +10,7 @@
 ###############################################################################
 # Copyright (c) 2014, Even Rouault <even dot rouault at mines-paris dot org>
 #
-# Permission is hereby granted, free of charge, to any person oxyzaining a
+# Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
 # to deal in the Software without restriction, including without limitation
 # the rights to use, copy, modify, merge, publish, distribute, sublicense,
@@ -34,7 +34,7 @@ import os
 # WARNING: Only works from a git repository !
 
 # Please edit for a different author
-author_in_file = 'ouault'
+author_in_file = 'rouault'
 git_author = 'Even Rouault'
 full_author = 'Even Rouault <even dot rouault at mines-paris dot org>'
 
@@ -133,7 +133,7 @@ for dirname, dirnames, filenames in os.walk('.'):
                         maxyear = year
             i = i + 1
 
-        # only clame copyright if we have authored more than 10 lines
+        # Only claim copyright if we have authored more than 10 lines.
         if count_matching_lines < 10:
             continue
 
diff --git a/vb6/README.TXT b/vb6/README.TXT
index ae37a33..6d135b3 100644
--- a/vb6/README.TXT
+++ b/vb6/README.TXT
@@ -23,7 +23,7 @@ Quick Test Run
 1) VB6 needs to be launched in such a way that it can find the gdal12vb.dll.
    This could be accomplished by having VB6 run in the same directory as the
    DLL, or by copying the DLL into windows\system32 or by editing GDALCore.bas
-   and changing all occurances of "gdal12vb.dll" to a full path to the DLL. 
+   and changing all occurrences of "gdal12vb.dll" to a full path to the DLL. 
 
    But for the test app to run, you need to have the sample files in the
    current directory, so you might as well just make a shortcut copy of your
@@ -49,7 +49,7 @@ Quick Test Run
    creation and copies metadata, georeferencing and actual image data to 
    it "manually".  This shows most of the setting API is working OK. 
 
-10) Tools->CreateCopy: Simplier option to create out.tif, demonstrates 
+10) Tools->CreateCopy: Simpler option to create out.tif, demonstrates 
     simple file copying. 
 
 
diff --git a/vb6/vb6_support.cpp b/vb6/vb6_support.cpp
index fabebac..36ae844 100644
--- a/vb6/vb6_support.cpp
+++ b/vb6/vb6_support.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vb6_support.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: vb6_support.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  GDAL VB6 Bindings
  * Purpose:  Support functions for GDAL VB6 bindings.
@@ -34,7 +34,7 @@
 // This is just for the USES_CONVERSION & OLESTR stuff.
 #include <atlbase.h>
 
-CPL_CVSID("$Id: vb6_support.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: vb6_support.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 // External entry points (from VB)
 extern "C" {
@@ -45,11 +45,11 @@ vbCStringToVB6( VARIANT *vResult, char *pszInput );
 void __declspec(dllexport) __stdcall
 vbCSLToVariant( char **papszList, VARIANT *out_list );
 
-char __declspec(dllexport) ** __stdcall 
+char __declspec(dllexport) ** __stdcall
 vbVariantToCSL( VARIANT *vList );
 
-int __declspec(dllexport) __stdcall 
-vbSafeArrayToPtr( VARIANT *vArray, GDALDataType *peDataType, 
+int __declspec(dllexport) __stdcall
+vbSafeArrayToPtr( VARIANT *vArray, GDALDataType *peDataType,
                   int *pnXSize, int *pnYSize );
 
 }
@@ -67,7 +67,7 @@ vbCStringToVB6( VARIANT *vResult, char *pszInput )
     USES_CONVERSION;
 
     VariantClear( vResult );
-    
+
     if( pszInput != NULL )
     {
         vResult->vt = VT_BSTR;
@@ -100,11 +100,11 @@ vbCSLToVariant( char **papszList, VARIANT *out_list )
     sBounds.lLbound = 1;
     sBounds.cElements = nLength;
 
-    result = SafeArrayCreate( VT_BSTR, 1, &sBounds );     
+    result = SafeArrayCreate( VT_BSTR, 1, &sBounds );
 
     for( i = 1; i <= nLength; i++ )
     {
-        SafeArrayPutElement( result, &i, 
+        SafeArrayPutElement( result, &i,
                              SysAllocString( A2BSTR(papszList[i-1]) ) );
 //        MessageBox( NULL, papszList[i-1], "Metadata Item", MB_OK );
     }
@@ -124,7 +124,7 @@ vbCSLToVariant( char **papszList, VARIANT *out_list )
 /*      Extract a list of strings from a variant as a stringlist.       */
 /************************************************************************/
 
-char __declspec(dllexport) ** __stdcall 
+char __declspec(dllexport) ** __stdcall
 vbVariantToCSL( VARIANT *vList )
 
 {
@@ -138,7 +138,7 @@ vbVariantToCSL( VARIANT *vList )
 /* -------------------------------------------------------------------- */
     if( vList == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "VARIANT is NULL in VariantToCSL()." );
         return NULL;
     }
@@ -149,16 +149,16 @@ vbVariantToCSL( VARIANT *vList )
         psSA = vList->parray;
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "VARIANT is wrong type (%x).", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "VARIANT is wrong type (%x).",
                   vList->vt );
         return NULL;
     }
 
     if( SafeArrayGetDim(psSA) != 1 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Wrong dimension in array (%d)", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Wrong dimension in array (%d)",
                   SafeArrayGetDim(psSA) );
         return NULL;
     }
@@ -166,14 +166,14 @@ vbVariantToCSL( VARIANT *vList )
     if( FAILED(SafeArrayGetLBound( psSA, 1, &nLBound ))
         || FAILED(SafeArrayGetUBound( psSA, 1, &nUBound)) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "SafeARrayGet{L,U}Bound() failed." );
         return NULL;
     }
 
     if( nUBound < nLBound )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Crazy L/U Bound (L=%d, U=%d)",
                   nLBound, nUBound );
         return NULL;
@@ -182,8 +182,8 @@ vbVariantToCSL( VARIANT *vList )
     SafeArrayGetVartype(psSA, &eVartype );
     if( eVartype != VT_BSTR )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "SafeArray contains type %d instead of VT_BSTR.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "SafeArray contains type %d instead of VT_BSTR.",
                   eVartype );
         return NULL;
     }
@@ -200,8 +200,8 @@ vbVariantToCSL( VARIANT *vList )
 
         if( FAILED(SafeArrayGetElement(psSA, &iElement, &bstrValue)) )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "SafeArrayGetElement(%d) failed.", 
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "SafeArrayGetElement(%d) failed.",
                       iElement );
             CSLDestroy( papszResult );
             return NULL;
@@ -221,8 +221,8 @@ vbVariantToCSL( VARIANT *vList )
 /*      SafeArray.                                                      */
 /************************************************************************/
 
-int __declspec(dllexport) __stdcall 
-vbSafeArrayToPtr( VARIANT *vArray, GDALDataType *peDataType, 
+int __declspec(dllexport) __stdcall
+vbSafeArrayToPtr( VARIANT *vArray, GDALDataType *peDataType,
                   int *pnXSize, int *pnYSize )
 
 {
@@ -236,7 +236,7 @@ vbSafeArrayToPtr( VARIANT *vArray, GDALDataType *peDataType,
 /* -------------------------------------------------------------------- */
     if( vArray == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "VARIANT is NULL in SafeArrayToPtr()." );
         return NULL;
     }
@@ -247,16 +247,16 @@ vbSafeArrayToPtr( VARIANT *vArray, GDALDataType *peDataType,
         psSA = vArray->parray;
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "VARIANT is wrong type (%x).", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "VARIANT is wrong type (%x).",
                   vArray->vt );
         return NULL;
     }
 
     if( SafeArrayGetDim(psSA) < 1 || SafeArrayGetDim(psSA) > 2 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Wrong dimension in array (%d)", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Wrong dimension in array (%d)",
                   SafeArrayGetDim(psSA) );
         return NULL;
     }
@@ -267,14 +267,14 @@ vbSafeArrayToPtr( VARIANT *vArray, GDALDataType *peDataType,
     if( FAILED(SafeArrayGetLBound( psSA, 1, &nLBound ))
         || FAILED(SafeArrayGetUBound( psSA, 1, &nUBound)) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "SafeARrayGet{L,U}Bound() failed." );
         return NULL;
     }
 
     if( nUBound <= nLBound )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Crazy L/U Bound (L=%d, U=%d)",
                   nLBound, nUBound );
         return NULL;
@@ -292,22 +292,22 @@ vbSafeArrayToPtr( VARIANT *vArray, GDALDataType *peDataType,
         if( FAILED(SafeArrayGetLBound( psSA, 1, &nLBound ))
             || FAILED(SafeArrayGetUBound( psSA, 1, &nUBound)) )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "SafeARrayGet{L,U}Bound() failed." );
             return NULL;
         }
-        
+
         if( nUBound <= nLBound )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Crazy L/U Bound (L=%d, U=%d)",
                       nLBound, nUBound );
             return NULL;
         }
-        
+
         *pnYSize = nUBound - nLBound + 1;
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Translate the type.                                             */
 /* -------------------------------------------------------------------- */
@@ -328,8 +328,8 @@ vbSafeArrayToPtr( VARIANT *vArray, GDALDataType *peDataType,
         *peDataType = GDT_Float64;
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "SafeArray contains type %d which is not supported.", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "SafeArray contains type %d which is not supported.",
                   eVartype );
         return NULL;
     }
diff --git a/wince/README b/wince/README
deleted file mode 100644
index 18986f3..0000000
--- a/wince/README
+++ /dev/null
@@ -1,253 +0,0 @@
-$Id: README 18465 2010-01-07 20:39:16Z mloskot $
-=============================================================================
- GDAL port for Window CE
- Originally ported by Mateusz Loskot, mateusz at loskot.net
-=============================================================================
-
-GDAL 1.4.0 includes following features for Windows CE platform:
-
-1. CPL library
-2. GDAL and OGR core API
-3. GDAL drivers:
-   -  AAIGrid
-   -  DTED
-   -  GeoTIFF
-4. OGR drivers
-   - CSV
-   - Generic
-   - MITAB
-   - ESRI Shapefile
-5. Unit Test suite (gdalautotest/cpp) 
-6. Optional PROJ.4 support
-7. Optional GEOS support
-
-
-GDAL for Windows CE has been tested on following versions of Windows CE:
-
-1. Windows CE 3.x
-   - Pocket PC 2002
-2. Windows CE 4.x
-   - Windows Mobile 2003
-3. Windows CE 5.x
-   - Windows Mobile 5
-   - customized versions of Windows CE 5.0
-
-Supported compilers for Windows CE operating system:
-
-1. Microsoft Visual C++ 2005 Standard or Professional
-2. Microsoft eMbedded Visual C++ 4.0 (NOTE: Currently, no project files provided)
-
-
-=============================================================================
- Content of gdal\wince directory:
-=============================================================================
-
-Active content:
-
-- msvc80 - project for Visual C++ 2005 to build GDAL DLL for Windows CE
-- README - the file you're currently reading
-- TODO   - planned and requested features 
-
-=============================================================================
- Building GDAL for Windows CE using Microsoft Visual C++ 2005
-=============================================================================
-
-1. Requirements
-
-You need to have installed Visual C++ 2005 Standard, Professional or
-Team Suite Edition.
-
-You also need to have installed at least one SDK for Windows CE platform:
-
-- Windows Mobile 2003 Pocket PC SDK
-- Windows Mobile 2003 SmartphoneSDK
-- Windows Mobile 5.0 Pocket PC SDK
-- Windows Mobile 5.0 Smartphone SDK
-
-If you are going to build against Windows Mobile 2003 SDK, there is one more 
-requirement. You have to install the Run-time Type Information library
-for the Pocket PC 2003 SDK
-
-http://support.microsoft.com/default.aspx?scid=kb;[LN];830482
-
-2. External dependencies
-
-There is only one external dependency required to build GDAL for Windows CE.
-This dependency is WCELIBCEX library available to download from the SourceForge.net:
-
-http://sourceforge.net/projects/wcelibcex
-
-You can download latest release - wcelibcex-1.0 - or checkout sources directly form SVN.
-In both cases, you will be provided with project file for Visual C++ 2005.
-WCELIBCEX is built to Static Library. For details, check README.txt file form the package.
-
-3. Download GDAL 1.4.0
-
-Go to http://www.gdal.org/download.html and download ZIP package with GDAL 1.4.0.
-You can also checkout sources directly from SVN.
-
-For this guidelines, I assume following directories structure:
-
-C:\dev\gdal-1.4.0
-C:\dev\wcelibcex-1.0
-
-4. Projects configuration
-
-a) Open gdalce_dll.sln project in Visual C++ 2005 IDE.
-   According to the paths presented in step 3, you should load following file:
-
-   C:\dev\gdal-1.4.0\wince\msvc80\gdalce_dll\gdalce_dll.sln
-
-b) Add WCELIBCEX project to gdalce_dll.sln solution:
-
-   Go to File -> Add -> Existing Project, navigage and open following file:
-
-   C:\dev\wcelibcex-1.0\msvc80\wcelibcex_lib.vcproj 
-
-c) Configure path to WCELIBCEX source:
-
-   - Go to View -> Property Manager to open property manager window.
-   - Expand tree below gdalce_dll -> Debug -> gdalce_common.
-   - Right-click on gdalce_common and select Properties.
-   - In Property Pages dialog, under Common Properties, go to User Macros
-   - In macros list, double-click on macro named as WCELIBCEX_DIR
-   - Change the macro value to C:\dev\wcelibcex-1.0\src, according paths assumed in step 3
-   - Click OK to apply changes and close the dialog
-
-d) Configure wcelibcex_lib.vcproj as a dependency for gdalce_dll.vcproj
-
-   - Select gdalce_dll project in Solution Explorer
-   - Go to Project -> Project Dependencies
-   - In the 'Depends on:' pane, select checkbox next to wcelibcex_lib 
-   - Click OK to apply and close
-
-5. Now, you are ready to build GDAL for Windows CE
-
-   Go to Build and select Build Solution
-
-   After a few minutes, you should see GDAL DLL ready to use.
-   For example, when Pocket PC 2003 SDK is used and Debug configuration requested,
-   all output files are located under this path:
-   
-   C:\dev\gdal-1.4.0\wince\msvc80\gdalce_dll\Pocket PC 2003 (ARMV4)\Debug
-
-   where you can find following binaries:
-
-   gdalce.dll - dymamic-link library
-   gdalce_i.lib - import library
-
-
-============================================
- Optional configuration
-============================================
-
-Currently, configuring PROJ.4 and GEOS support is not easy, but feasible.
-In near future, I'll prepare some best practice and try to make it as easy as possible.
-On the CVS of PROJ.4, there are project files for Visual C++ 2005 for Windows CE available.
-Unfortunately, no project files for Windows CE are provided for GEOS, but I'll try to change it very soon.
-
-1. Enable PROJ.4 support
-
-It is recommended to read README.txt file in C:\dev\proj\wince\msvc80.
-There, you will find instructions how to build PROJ.4 without attaching its project to gdalce_dll.sln.
-Then you can just add proj.dll and proj_i.lib to linker settings of gdalce_dll.vcproj project.
-
-Below, you can find instructions how to add projce_dll.vcproj project
-directly to gdalce_dll.sln and build everything together.
-
-a) Go to http://proj.maptools.org and learn how to checkout PROJ.4 source from the CVS
-
-b) Checkout sources to prefered location, for example C:\dev\proj
-
-c) Add projce_dll.vcproj project to gdalce_dll.sln solution
-
-   Go to File -> Add -> Existing Project, navigage and open following file:
-
-   C:\dev\proj\wince\msvc80\projce_dll\projce_dll.vcproj 
-
-d) Open Property Manager as described in point 4.c) above, open Property Page for gdalce_common,
-   and edit macro named as PROJ_DIR.
-   
-   Set the PROJ_DIR value to C:\dev\proj
-
-   Don't close the Property Manager yet.
-
-e) Configure path to WCELIBCEX source:
-
-   - Go to View -> Property Manager to open property manager window.
-   - Expand tree below projce_dll -> Debug -> projce_common.
-   - Right-click on projce_common and select Properties.
-   - In Property Pages dialog, under Common Properties, go to User Macros
-   - In macros list, double-click on macro named as WCELIBCEX_DIR
-   - Change the macro value to C:\dev\wcelibcex-1.0\src
-   - Click OK to apply changes and close the dialog
-
-f) Follow instructions explained in step 4.d) and add projce_dll.vcproj as a dependency for gdalce_dll.vcproj.
-
-g) Update proj_config.h file:
-
-   Go to C:\dev\proj\src and rename proj_config.h.wince to proj_config.h
-
-h) Now, you are ready to rebuild GDAL for Windows CE
-
-   Go to Build and select Build Solution
-
-   Similarly to explanation above in step 5 for GDAL, binaries for PROJ.4 for Windows CE
-   can be found here:
-
-   C:\dev\proj\wince\msvc80\projce_dll\Pocket PC 2003 (ARMV4)\Debug
-
-   where you can find following binaries:
-
-   proj.dll - dymamic-link library
-   proj_i.lib - import library
-
-   NOTE: PROJ.4 binaries for Windows CE do not include 'ce' in names.
-         This is due the fact GDAL uses fixed proj.dll name to find and
-         link dynamically with PROJ.4 DLL.
-
-i) After all, put gdalce.dll and proj.dll to the same directory where your
-   application which uses GDAL is installed on device.
-
-
-2. Enable GEOS support
-
-TODO - I'm going to publish VC++ project files soon, then this points will be updated.
-
-
-=============================================================================
- How can I contribute?
-=============================================================================
-
-- you can build GDAL for Windows CE and report problems if any
-- you can try to port new drivers
-- you can test GDAL on different Windows CE devices
-- you can write sample applications using GDAL
-- if you have found a bug, please report it
-
-=============================================================================
- How can I report a bug?
-=============================================================================
-
-Visit Bugzilla on http://bugzilla.remotesensing.org
-
-Bug Writing Guidelines:
-http://bugzilla.remotesensing.org/page.cgi?id=bug-writing.htm
-
-=============================================================================
- Thanks to:
-=============================================================================
-
-- Frank Warmerdam for GDAL/OGR and priceless support he provide me
-- Taxus SI Ltd. from Poland for their great support
-- Users from IRC #gdal channel
-- All users, testers and contributor
-
-=============================================================================
-Questions?
-=============================================================================
-
-Mailing list: gdal-dev at lists.maptools.org
-You can catch me on mateusz at loskot.net or ping mloskot on the #gdal IRC channel.
-
-
diff --git a/wince/TODO b/wince/TODO
deleted file mode 100644
index f4e433b..0000000
--- a/wince/TODO
+++ /dev/null
@@ -1,6 +0,0 @@
-TODO list for Windows CE port:
------------------------------
-- Add project files for eVC++ 4.0
-- Port OGR driver for GML
-- Port OGR driver for SQLite
-- Port OGR driver for new GDAL rasters support
diff --git a/wince/msvc80/gdalce_common.vsprops b/wince/msvc80/gdalce_common.vsprops
deleted file mode 100644
index d285e20..0000000
--- a/wince/msvc80/gdalce_common.vsprops
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="windows-1250"?>
-<VisualStudioPropertySheet
-	ProjectType="Visual C++"
-	Version="8.00"
-	Name="gdalce_common"
-	>
-	<Tool
-		Name="VCCLCompilerTool"
-		AdditionalIncludeDirectories="$(WCELIBCEX_DIR)"
-		PreprocessorDefinitions="OGR_ENABLED;SHAPE_ENABLED;FRMT_aaigrid;FRMT_dted;FRMT_gtiff"
-	/>
-	<Tool
-		Name="VCPreBuildEventTool"
-		Description=""
-		CommandLine=""
-	/>
-	<UserMacro
-		Name="WCELIBCEX_DIR"
-		Value="D:\dev\wcelibcex\_svn\wcelibcex\trunk\src"
-	/>
-	<UserMacro
-		Name="PROJ_DIR"
-		Value=""
-	/>
-	<UserMacro
-		Name="GEOS_DIR"
-		Value=""
-	/>
-	<UserMacro
-		Name="GDAL_DIR"
-		Value="..\..\.."
-	/>
-	<UserMacro
-		Name="CPL_CONFIG_H"
-		Value="cpl_config.h"
-	/>
-	<UserMacro
-		Name="TIF_CONFIG_H"
-		Value="tif_config.h"
-	/>
-</VisualStudioPropertySheet>
diff --git a/wince/msvc80/gdalce_dll/gdalce_dll.sln b/wince/msvc80/gdalce_dll/gdalce_dll.sln
deleted file mode 100644
index f7a7b73..0000000
--- a/wince/msvc80/gdalce_dll/gdalce_dll.sln
+++ /dev/null
@@ -1,44 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 9.00
-# Visual Studio 2005
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gdalce_dll", "gdalce_dll.vcproj", "{E9FBF1D2-B6F1-49AE-912F-BD2BBC56A6E3}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{88953934-D658-4765-9710-A22237DEEBB1}"
-	ProjectSection(SolutionItems) = preProject
-		..\..\README = ..\..\README
-		..\..\TODO = ..\..\TODO
-	EndProjectSection
-EndProject
-Global
-	GlobalSection(SolutionConfigurationPlatforms) = preSolution
-		Debug|Pocket PC 2003 (ARMV4) = Debug|Pocket PC 2003 (ARMV4)
-		Debug|Smartphone 2003 (ARMV4) = Debug|Smartphone 2003 (ARMV4)
-		Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
-		Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I) = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
-		Release|Pocket PC 2003 (ARMV4) = Release|Pocket PC 2003 (ARMV4)
-		Release|Smartphone 2003 (ARMV4) = Release|Smartphone 2003 (ARMV4)
-		Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
-		Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I) = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
-	EndGlobalSection
-	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{E9FBF1D2-B6F1-49AE-912F-BD2BBC56A6E3}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
-		{E9FBF1D2-B6F1-49AE-912F-BD2BBC56A6E3}.Debug|Pocket PC 2003 (ARMV4).Build.0 = Debug|Pocket PC 2003 (ARMV4)
-		{E9FBF1D2-B6F1-49AE-912F-BD2BBC56A6E3}.Debug|Pocket PC 2003 (ARMV4).Deploy.0 = Debug|Pocket PC 2003 (ARMV4)
-		{E9FBF1D2-B6F1-49AE-912F-BD2BBC56A6E3}.Debug|Smartphone 2003 (ARMV4).ActiveCfg = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
-		{E9FBF1D2-B6F1-49AE-912F-BD2BBC56A6E3}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
-		{E9FBF1D2-B6F1-49AE-912F-BD2BBC56A6E3}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
-		{E9FBF1D2-B6F1-49AE-912F-BD2BBC56A6E3}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
-		{E9FBF1D2-B6F1-49AE-912F-BD2BBC56A6E3}.Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
-		{E9FBF1D2-B6F1-49AE-912F-BD2BBC56A6E3}.Release|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Pocket PC 2003 (ARMV4)
-		{E9FBF1D2-B6F1-49AE-912F-BD2BBC56A6E3}.Release|Pocket PC 2003 (ARMV4).Build.0 = Release|Pocket PC 2003 (ARMV4)
-		{E9FBF1D2-B6F1-49AE-912F-BD2BBC56A6E3}.Release|Pocket PC 2003 (ARMV4).Deploy.0 = Release|Pocket PC 2003 (ARMV4)
-		{E9FBF1D2-B6F1-49AE-912F-BD2BBC56A6E3}.Release|Smartphone 2003 (ARMV4).ActiveCfg = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
-		{E9FBF1D2-B6F1-49AE-912F-BD2BBC56A6E3}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
-		{E9FBF1D2-B6F1-49AE-912F-BD2BBC56A6E3}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
-		{E9FBF1D2-B6F1-49AE-912F-BD2BBC56A6E3}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
-		{E9FBF1D2-B6F1-49AE-912F-BD2BBC56A6E3}.Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
-	EndGlobalSection
-	GlobalSection(SolutionProperties) = preSolution
-		HideSolutionNode = FALSE
-	EndGlobalSection
-EndGlobal
diff --git a/wince/msvc80/gdalce_dll/gdalce_dll.vcproj b/wince/msvc80/gdalce_dll/gdalce_dll.vcproj
deleted file mode 100644
index f40bc45..0000000
--- a/wince/msvc80/gdalce_dll/gdalce_dll.vcproj
+++ /dev/null
@@ -1,1515 +0,0 @@
-<?xml version="1.0" encoding="windows-1250"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="8.00"
-	Name="gdalce_dll"
-	ProjectGUID="{E9FBF1D2-B6F1-49AE-912F-BD2BBC56A6E3}"
-	Keyword="Win32Proj"
-	>
-	<Platforms>
-		<Platform
-			Name="Pocket PC 2003 (ARMV4)"
-		/>
-		<Platform
-			Name="Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
-		/>
-	</Platforms>
-	<ToolFiles>
-	</ToolFiles>
-	<Configurations>
-		<Configuration
-			Name="Debug|Pocket PC 2003 (ARMV4)"
-			OutputDirectory="$(PlatformName)\$(ConfigurationName)"
-			IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
-			ConfigurationType="2"
-			InheritedPropertySheets="..\gdalce_common.vsprops"
-			CharacterSet="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-				Description="*** Making GDAL config files for Windows CE ***"
-				CommandLine="echo **** Copying $(GDAL_DIR)\port\$(CPL_CONFIG_H).wince to $(GDAL_DIR)\port\$(CPL_CONFIG_H)&#x0D;&#x0A;copy /Y $(GDAL_DIR)\port\$(CPL_CONFIG_H).wince $(GDAL_DIR)\port\$(CPL_CONFIG_H)&#x0D;&#x0A;echo **** Copying $(GDAL_DIR)\frmts\gtiff\libtiff\$(TIF_CONFIG_H).wince to $(GDAL_DIR)\frmts\gtiff\libtiff\$(TIF_CONFIG_H)&#x0D;&#x0A;copy /Y $(GDAL_DIR)\frmts\gtiff\libtiff\$(TIF_CONFIG_H).wince $(GDAL_DIR)\frmts\gtiff\libtiff\$(TIF_CONFIG_H)&#x0D;&#x0A;"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				ExecutionBucket="7"
-				Optimization="0"
-				AdditionalIncludeDirectories=""$(GDAL_DIR)\port";"$(GDAL_DIR)\gcore";"$(GDAL_DIR)\frmts\gtiff";"$(GDAL_DIR)\frmts\gtiff\libtiff";"$(GDAL_DIR)\frmts\gtiff\libgeotiff";"$(GDAL_DIR)\ogr";"$(GDAL_DIR)\ogr\ogrsf_frmts";"$(GEOS_DIR)\capi""
-				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;DEBUG;_WINDOWS;_USRDLL;GDALCE_DLL_EXPORTS;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
-				MinimalRebuild="true"
-				RuntimeLibrary="1"
-				BufferSecurityCheck="false"
-				UsePrecompiledHeader="0"
-				WarningLevel="3"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES)"
-				Culture="1033"
-				AdditionalIncludeDirectories="$(IntDir)"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalOptions=" /subsystem:windowsce,4.20 /machine:ARM /ARMPADCODE"
-				AdditionalDependencies="ccrtrtti.lib"
-				OutputFile="$(OutDir)/gdalce.dll"
-				LinkIncremental="2"
-				DelayLoadDLLs="$(NOINHERIT)"
-				GenerateDebugInformation="true"
-				ProgramDatabaseFile="$(OutDir)/gdalce_dll.pdb"
-				SubSystem="0"
-				ImportLibrary="$(OutDir)/gdalce_i.lib"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCCodeSignTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-			<DeploymentTool
-				ForceDirty="-1"
-				RemoteDirectory="%CSIDL_PROGRAM_FILES%\gdalce"
-				RegisterOutput="0"
-				AdditionalFiles=""
-			/>
-			<DebuggerTool
-			/>
-		</Configuration>
-		<Configuration
-			Name="Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
-			OutputDirectory="$(PlatformName)\$(ConfigurationName)"
-			IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
-			ConfigurationType="2"
-			InheritedPropertySheets="..\gdalce_common.vsprops"
-			CharacterSet="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-				Description="*** Making GDAL config files for Windows CE ***"
-				CommandLine="echo **** Copying $(GDAL_DIR)\port\$(CPL_CONFIG_H).wince to $(GDAL_DIR)\port\$(CPL_CONFIG_H)&#x0D;&#x0A;copy /Y $(GDAL_DIR)\port\$(CPL_CONFIG_H).wince $(GDAL_DIR)\port\$(CPL_CONFIG_H)&#x0D;&#x0A;echo **** Copying $(GDAL_DIR)\frmts\gtiff\libtiff\$(TIF_CONFIG_H).wince to $(GDAL_DIR)\frmts\gtiff\libtiff\$(TIF_CONFIG_H)&#x0D;&#x0A;copy /Y $(GDAL_DIR)\frmts\gtiff\libtiff\$(TIF_CONFIG_H).wince $(GDAL_DIR)\frmts\gtiff\libtiff\$(TIF_CONFIG_H)&#x0D;&#x0A;"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				ExecutionBucket="7"
-				Optimization="0"
-				AdditionalIncludeDirectories=""$(GEOS_DIR)\capi";"$(GDAL_DIR)\port";"$(GDAL_DIR)\gcore";"$(GDAL_DIR)\frmts\gtiff";"$(GDAL_DIR)\frmts\gtiff\libtiff";"$(GDAL_DIR)\frmts\gtiff\libgeotiff";"$(GDAL_DIR)\ogr";"$(GDAL_DIR)\ogr\ogrsf_frmts""
-				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;DEBUG;_WINDOWS;_USRDLL;GDALCE_DLL_EXPORTS;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
-				MinimalRebuild="true"
-				RuntimeLibrary="1"
-				UsePrecompiledHeader="0"
-				WarningLevel="3"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES)"
-				Culture="1033"
-				AdditionalIncludeDirectories="$(IntDir)"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalOptions=" /subsystem:windowsce,5.01"
-				OutputFile="$(OutDir)/gdalce.dll"
-				LinkIncremental="2"
-				DelayLoadDLLs="$(NOINHERIT)"
-				GenerateDebugInformation="true"
-				ProgramDatabaseFile="$(OutDir)/gdalce_dll.pdb"
-				SubSystem="0"
-				ImportLibrary="$(OutDir)/gdalce_i.lib"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCCodeSignTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-			<DeploymentTool
-				ForceDirty="-1"
-				RemoteDirectory="%CSIDL_PROGRAM_FILES%\gdalce"
-				RegisterOutput="0"
-				AdditionalFiles=""
-			/>
-			<DebuggerTool
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|Pocket PC 2003 (ARMV4)"
-			OutputDirectory="$(PlatformName)\$(ConfigurationName)"
-			IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
-			ConfigurationType="2"
-			InheritedPropertySheets="..\gdalce_common.vsprops"
-			CharacterSet="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-				Description="*** Making GDAL config files for Windows CE ***"
-				CommandLine="echo **** Copying $(GDAL_DIR)\port\$(CPL_CONFIG_H).wince to $(GDAL_DIR)\port\$(CPL_CONFIG_H)&#x0D;&#x0A;copy /Y $(GDAL_DIR)\port\$(CPL_CONFIG_H).wince $(GDAL_DIR)\port\$(CPL_CONFIG_H)&#x0D;&#x0A;echo **** Copying $(GDAL_DIR)\frmts\gtiff\libtiff\$(TIF_CONFIG_H).wince to $(GDAL_DIR)\frmts\gtiff\libtiff\$(TIF_CONFIG_H)&#x0D;&#x0A;copy /Y $(GDAL_DIR)\frmts\gtiff\libtiff\$(TIF_CONFIG_H).wince $(GDAL_DIR)\frmts\gtiff\libtiff\$(TIF_CONFIG_H)&#x0D;&#x0A;"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				ExecutionBucket="7"
-				Optimization="2"
-				AdditionalIncludeDirectories=""$(GEOS_DIR)\capi";"$(GDAL_DIR)\port";"$(GDAL_DIR)\gcore";"$(GDAL_DIR)\frmts\gtiff";"$(GDAL_DIR)\frmts\gtiff\libtiff";"$(GDAL_DIR)\frmts\gtiff\libgeotiff";"$(GDAL_DIR)\ogr";"$(GDAL_DIR)\ogr\ogrsf_frmts""
-				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;_WINDOWS;_USRDLL;GDALCE_DLL_EXPORTS;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
-				RuntimeLibrary="0"
-				UsePrecompiledHeader="0"
-				WarningLevel="3"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES)"
-				Culture="1033"
-				AdditionalIncludeDirectories="$(IntDir)"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalOptions=" /subsystem:windowsce,4.20 /machine:ARM /ARMPADCODE"
-				OutputFile="$(OutDir)/gdalce.dll"
-				LinkIncremental="1"
-				DelayLoadDLLs="$(NOINHERIT)"
-				GenerateDebugInformation="true"
-				ProgramDatabaseFile="$(OutDir)/gdalce_dll.pdb"
-				SubSystem="0"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				ImportLibrary="$(OutDir)/gdalce_i.lib"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCCodeSignTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-			<DeploymentTool
-				ForceDirty="-1"
-				RemoteDirectory="%CSIDL_PROGRAM_FILES%\gdalce"
-				RegisterOutput="0"
-				AdditionalFiles=""
-			/>
-			<DebuggerTool
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
-			OutputDirectory="$(PlatformName)\$(ConfigurationName)"
-			IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
-			ConfigurationType="2"
-			InheritedPropertySheets="..\gdalce_common.vsprops"
-			CharacterSet="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-				Description="*** Making GDAL config files for Windows CE ***"
-				CommandLine="echo **** Copying $(GDAL_DIR)\port\$(CPL_CONFIG_H).wince to $(GDAL_DIR)\port\$(CPL_CONFIG_H)&#x0D;&#x0A;copy /Y $(GDAL_DIR)\port\$(CPL_CONFIG_H).wince $(GDAL_DIR)\port\$(CPL_CONFIG_H)&#x0D;&#x0A;echo **** Copying $(GDAL_DIR)\frmts\gtiff\libtiff\$(TIF_CONFIG_H).wince to $(GDAL_DIR)\frmts\gtiff\libtiff\$(TIF_CONFIG_H)&#x0D;&#x0A;copy /Y $(GDAL_DIR)\frmts\gtiff\libtiff\$(TIF_CONFIG_H).wince $(GDAL_DIR)\frmts\gtiff\libtiff\$(TIF_CONFIG_H)&#x0D;&#x0A;"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				ExecutionBucket="7"
-				Optimization="2"
-				AdditionalIncludeDirectories=""$(GEOS_DIR)\capi";"$(GDAL_DIR)\port";"$(GDAL_DIR)\gcore";"$(GDAL_DIR)\frmts\gtiff";"$(GDAL_DIR)\frmts\gtiff\libtiff";"$(GDAL_DIR)\frmts\gtiff\libgeotiff";"$(GDAL_DIR)\ogr";"$(GDAL_DIR)\ogr\ogrsf_frmts""
-				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;_WINDOWS;_USRDLL;GDALCE_DLL_EXPORTS;$(ARCHFAM);$(_ARCHFAM_);_UNICODE;UNICODE"
-				RuntimeLibrary="0"
-				UsePrecompiledHeader="0"
-				WarningLevel="3"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="NDEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES)"
-				Culture="1033"
-				AdditionalIncludeDirectories="$(IntDir)"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalOptions=" /subsystem:windowsce,5.01"
-				OutputFile="$(OutDir)/gdalce.dll"
-				LinkIncremental="1"
-				DelayLoadDLLs="$(NOINHERIT)"
-				GenerateDebugInformation="true"
-				ProgramDatabaseFile="$(OutDir)/gdalce_dll.pdb"
-				SubSystem="0"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				ImportLibrary="$(OutDir)/gdalce_i.lib"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCCodeSignTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-			<DeploymentTool
-				ForceDirty="-1"
-				RemoteDirectory="%CSIDL_PROGRAM_FILES%\gdalce"
-				RegisterOutput="0"
-				AdditionalFiles=""
-			/>
-			<DebuggerTool
-			/>
-		</Configuration>
-	</Configurations>
-	<References>
-	</References>
-	<Files>
-		<Filter
-			Name="port"
-			>
-			<File
-				RelativePath="..\..\..\port\cpl_config.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_config.h.wince"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_conv.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_conv.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_csv.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_csv.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_error.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_error.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_findfile.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_getexecpath.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_http.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_http.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_list.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_list.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_minixml.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_minixml.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_multiproc.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_multiproc.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_odbc.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_odbc.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_path.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_port.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_string.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_string.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_strtod.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_vsi.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_vsi_mem.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_vsi_private.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_vsil.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_vsil_win32.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_vsisimple.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_win32ce_api.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_win32ce_api.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cpl_wince.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cplgetsymbol.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\port\cplstring.cpp"
-				>
-			</File>
-		</Filter>
-		<Filter
-			Name="ogr"
-			>
-			<File
-				RelativePath="..\..\..\ogr\gml2ogrgeometry.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogr2gmlgeometry.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogr_api.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogr_api.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogr_core.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogr_feature.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogr_featurestyle.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogr_fromepsg.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogr_geometry.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogr_geos.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogr_geos_convert.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogr_opt.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogr_p.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogr_spatialref.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogr_srs_api.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogr_srs_dict.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogr_srs_esri.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogr_srs_pci.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogr_srs_proj4.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogr_srs_usgs.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogr_srs_validate.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogr_srs_xml.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogr_srsnode.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ograssemblepolygon.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogrct.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogrcurve.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogrfeature.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogrfeaturedefn.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogrfeaturequery.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogrfeaturestyle.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogrfielddefn.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogrgeometry.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogrgeometrycollection.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogrgeometryfactory.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogrlinearring.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogrlinestring.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogrmultilinestring.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogrmultipoint.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogrmultipolygon.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogrpoint.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogrpolygon.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogrspatialreference.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogrsurface.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\ogrutils.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\swq.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\ogr\swq.h"
-				>
-			</File>
-			<Filter
-				Name="ogrsf_frmts"
-				>
-				<File
-					RelativePath="..\..\..\ogr\ogrsf_frmts\ogr_attrind.h"
-					>
-				</File>
-				<File
-					RelativePath="..\..\..\ogr\ogrsf_frmts\ogrsf_frmts.h"
-					>
-				</File>
-				<Filter
-					Name="generic"
-					>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\generic\ogr_attrind.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\generic\ogr_gensql.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\generic\ogr_gensql.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\generic\ogr_miattrind.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\generic\ogrdatasource.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\generic\ogrlayer.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\generic\ogrregisterall.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\generic\ogrsfdriver.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\generic\ogrsfdriverregistrar.cpp"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="mitab"
-					>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab_bounds.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab_coordsys.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab_datfile.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab_feature.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab_feature_mif.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab_geometry.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab_geometry.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab_idfile.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab_imapinfofile.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab_indfile.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab_mapcoordblock.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab_mapfile.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab_mapheaderblock.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab_mapindexblock.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab_mapobjectblock.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab_maptoolblock.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab_middatafile.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab_miffile.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab_ogr_datasource.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab_ogr_driver.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab_ogr_driver.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab_priv.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab_rawbinblock.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab_spatialref.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab_tabfile.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab_tabseamless.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab_tabview.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab_tooldef.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab_utils.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\mitab\mitab_utils.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="shape"
-					>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\shape\dbfopen.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\shape\ogrshape.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\shape\ogrshapedatasource.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\shape\ogrshapedriver.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\shape\ogrshapelayer.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\shape\shape2ogr.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\shape\shapefil.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\shape\shp_vsi.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\shape\shpopen.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\shape\shptree.c"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="csv"
-					>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\csv\ogr_csv.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\csv\ogrcsvdatasource.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\csv\ogrcsvdriver.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\ogr\ogrsf_frmts\csv\ogrcsvlayer.cpp"
-						>
-					</File>
-				</Filter>
-			</Filter>
-		</Filter>
-		<Filter
-			Name="gcore"
-			>
-			<File
-				RelativePath="..\..\..\gcore\gdal.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\gcore\gdal_frmts.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\gcore\gdal_misc.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\gcore\gdal_pam.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\gcore\gdal_priv.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\gcore\gdal_rat.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\gcore\gdal_rat.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\gcore\gdal_version.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\gcore\gdalallvalidmaskband.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\gcore\gdalcolortable.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\gcore\gdaldataset.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\gcore\gdaldefaultoverviews.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\gcore\gdaldriver.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\gcore\gdaldrivermanager.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\gcore\gdalgmlcoverage.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\gcore\gdaljp2box.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\gcore\gdaljp2metadata.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\gcore\gdaljp2metadata.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\gcore\gdalmajorobject.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\gcore\gdalmultidomainmetadata.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\gcore\gdalnodatamaskband.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\gcore\gdalopeninfo.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\gcore\gdalpamdataset.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\gcore\gdalpamproxydb.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\gcore\gdalpamrasterband.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\gcore\gdalrasterband.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\gcore\gdalrasterblock.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\gcore\overview.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\gcore\rasterio.cpp"
-				>
-			</File>
-		</Filter>
-		<Filter
-			Name="frmts"
-			>
-			<File
-				RelativePath="..\..\..\frmts\gdalallregister.cpp"
-				>
-			</File>
-			<Filter
-				Name="gtiff"
-				>
-				<File
-					RelativePath="..\..\..\frmts\gtiff\geotiff.cpp"
-					>
-				</File>
-				<File
-					RelativePath="..\..\..\frmts\gtiff\gt_overview.cpp"
-					>
-				</File>
-				<File
-					RelativePath="..\..\..\frmts\gtiff\gt_wkt_srs.cpp"
-					>
-				</File>
-				<File
-					RelativePath="..\..\..\frmts\gtiff\tif_float.c"
-					>
-				</File>
-				<File
-					RelativePath="..\..\..\frmts\gtiff\tif_overview.c"
-					>
-				</File>
-				<File
-					RelativePath="..\..\..\frmts\gtiff\tif_ovrcache.c"
-					>
-				</File>
-				<File
-					RelativePath="..\..\..\frmts\gtiff\tif_ovrcache.h"
-					>
-				</File>
-				<File
-					RelativePath="..\..\..\frmts\gtiff\tifvsi.cpp"
-					>
-				</File>
-				<Filter
-					Name="libtiff"
-					>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\t4.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_aux.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_close.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_codec.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_color.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_compress.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_config.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_config.h.wince"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_dir.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_dir.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_dirinfo.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_dirread.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_dirwrite.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_dumpmode.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_error.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_extension.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_fax3.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_fax3.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_fax3sm.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_flush.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_getimage.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_jpeg.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_luv.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_lzw.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_next.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_open.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_packbits.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_pixarlog.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_predict.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_predict.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_print.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_read.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_strip.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_swab.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_thunder.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_tile.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_version.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_vsi.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_warning.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_write.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tif_zip.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tiff.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tiffconf.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tiffio.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tiffiop.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\tiffvers.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libtiff\uvcode.h"
-						>
-					</File>
-				</Filter>
-				<Filter
-					Name="libgeotiff"
-					>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libgeotiff\cpl_serv.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libgeotiff\geo_config.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libgeotiff\geo_extra.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libgeotiff\geo_free.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libgeotiff\geo_get.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libgeotiff\geo_keyp.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libgeotiff\geo_names.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libgeotiff\geo_new.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libgeotiff\geo_normalize.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libgeotiff\geo_normalize.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libgeotiff\geo_print.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libgeotiff\geo_set.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libgeotiff\geo_tiffp.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libgeotiff\geo_tiffp.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libgeotiff\geo_trans.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libgeotiff\geo_write.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libgeotiff\geokeys.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libgeotiff\geonames.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libgeotiff\geotiff.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libgeotiff\geotiff_proj4.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libgeotiff\geotiffio.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libgeotiff\geovalues.h"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libgeotiff\xtiff.c"
-						>
-					</File>
-					<File
-						RelativePath="..\..\..\frmts\gtiff\libgeotiff\xtiffio.h"
-						>
-					</File>
-				</Filter>
-			</Filter>
-			<Filter
-				Name="dted"
-				>
-				<File
-					RelativePath="..\..\..\frmts\dted\dted_api.c"
-					>
-				</File>
-				<File
-					RelativePath="..\..\..\frmts\dted\dted_api.h"
-					>
-				</File>
-				<File
-					RelativePath="..\..\..\frmts\dted\dted_create.c"
-					>
-				</File>
-				<File
-					RelativePath="..\..\..\frmts\dted\dted_ptstream.c"
-					>
-				</File>
-				<File
-					RelativePath="..\..\..\frmts\dted\dteddataset.cpp"
-					>
-				</File>
-			</Filter>
-			<Filter
-				Name="aaigrid"
-				>
-				<File
-					RelativePath="..\..\..\frmts\aaigrid\aaigriddataset.cpp"
-					>
-				</File>
-			</Filter>
-		</Filter>
-		<Filter
-			Name="alg"
-			>
-			<File
-				RelativePath="..\..\..\alg\contour.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\alg\gdal_alg.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\alg\gdal_crs.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\alg\gdal_rpc.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\alg\gdal_tps.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\alg\gdalchecksum.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\alg\gdaldither.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\alg\gdalgeoloc.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\alg\gdalmediancut.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\alg\gdalrasterize.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\alg\gdalsimplewarp.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\alg\gdaltransformer.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\alg\gdalwarper.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\alg\gdalwarper.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\alg\gdalwarpkernel.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\alg\gdalwarpoperation.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\alg\llrasterize.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\alg\thinplatespline.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\alg\thinplatespline.h"
-				>
-			</File>
-		</Filter>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/gdal.git



More information about the Pkg-grass-devel mailing list